From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- ANDROID_3.4.5/sound/Kconfig | 137 - ANDROID_3.4.5/sound/Makefile | 19 - ANDROID_3.4.5/sound/ac97_bus.c | 77 - ANDROID_3.4.5/sound/aoa/Kconfig | 17 - ANDROID_3.4.5/sound/aoa/Makefile | 4 - ANDROID_3.4.5/sound/aoa/aoa-gpio.h | 83 - ANDROID_3.4.5/sound/aoa/aoa.h | 129 - ANDROID_3.4.5/sound/aoa/codecs/Kconfig | 24 - ANDROID_3.4.5/sound/aoa/codecs/Makefile | 7 - ANDROID_3.4.5/sound/aoa/codecs/onyx.c | 1135 ---- ANDROID_3.4.5/sound/aoa/codecs/onyx.h | 75 - ANDROID_3.4.5/sound/aoa/codecs/tas-basstreble.h | 134 - ANDROID_3.4.5/sound/aoa/codecs/tas-gain-table.h | 209 - ANDROID_3.4.5/sound/aoa/codecs/tas.c | 1029 --- ANDROID_3.4.5/sound/aoa/codecs/tas.h | 55 - ANDROID_3.4.5/sound/aoa/codecs/toonie.c | 151 - ANDROID_3.4.5/sound/aoa/core/Makefile | 5 - ANDROID_3.4.5/sound/aoa/core/alsa.c | 100 - ANDROID_3.4.5/sound/aoa/core/alsa.h | 16 - ANDROID_3.4.5/sound/aoa/core/core.c | 162 - ANDROID_3.4.5/sound/aoa/core/gpio-feature.c | 422 -- ANDROID_3.4.5/sound/aoa/core/gpio-pmf.c | 253 - ANDROID_3.4.5/sound/aoa/fabrics/Kconfig | 11 - ANDROID_3.4.5/sound/aoa/fabrics/Makefile | 3 - ANDROID_3.4.5/sound/aoa/fabrics/layout.c | 1168 ---- ANDROID_3.4.5/sound/aoa/soundbus/Kconfig | 14 - ANDROID_3.4.5/sound/aoa/soundbus/Makefile | 3 - ANDROID_3.4.5/sound/aoa/soundbus/core.c | 219 - ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/Makefile | 2 - ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/control.c | 194 - ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/core.c | 464 -- ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/i2sbus.h | 126 - .../sound/aoa/soundbus/i2sbus/interface.h | 187 - ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/pcm.c | 1064 --- ANDROID_3.4.5/sound/aoa/soundbus/soundbus.h | 204 - ANDROID_3.4.5/sound/aoa/soundbus/sysfs.c | 42 - ANDROID_3.4.5/sound/arm/Kconfig | 43 - ANDROID_3.4.5/sound/arm/Makefile | 16 - ANDROID_3.4.5/sound/arm/aaci.c | 1116 ---- ANDROID_3.4.5/sound/arm/aaci.h | 250 - ANDROID_3.4.5/sound/arm/pxa2xx-ac97-lib.c | 402 -- ANDROID_3.4.5/sound/arm/pxa2xx-ac97.c | 260 - ANDROID_3.4.5/sound/arm/pxa2xx-pcm-lib.c | 285 - ANDROID_3.4.5/sound/arm/pxa2xx-pcm.c | 132 - ANDROID_3.4.5/sound/arm/pxa2xx-pcm.h | 30 - ANDROID_3.4.5/sound/atmel/Kconfig | 19 - ANDROID_3.4.5/sound/atmel/Makefile | 5 - ANDROID_3.4.5/sound/atmel/abdac.c | 612 -- ANDROID_3.4.5/sound/atmel/ac97c.c | 1231 ---- ANDROID_3.4.5/sound/atmel/ac97c.h | 73 - ANDROID_3.4.5/sound/core/Kconfig | 220 - ANDROID_3.4.5/sound/core/Makefile | 38 - ANDROID_3.4.5/sound/core/compress_offload.c | 773 --- ANDROID_3.4.5/sound/core/control.c | 1726 ----- ANDROID_3.4.5/sound/core/control_compat.c | 448 -- ANDROID_3.4.5/sound/core/ctljack.c | 56 - ANDROID_3.4.5/sound/core/device.c | 245 - ANDROID_3.4.5/sound/core/hrtimer.c | 167 - ANDROID_3.4.5/sound/core/hwdep.c | 547 -- ANDROID_3.4.5/sound/core/hwdep_compat.c | 78 - ANDROID_3.4.5/sound/core/info.c | 1016 --- ANDROID_3.4.5/sound/core/info_oss.c | 139 - ANDROID_3.4.5/sound/core/init.c | 991 --- ANDROID_3.4.5/sound/core/isadma.c | 117 - ANDROID_3.4.5/sound/core/jack.c | 242 - ANDROID_3.4.5/sound/core/memalloc.c | 547 -- ANDROID_3.4.5/sound/core/memory.c | 92 - ANDROID_3.4.5/sound/core/misc.c | 148 - ANDROID_3.4.5/sound/core/oss/Makefile | 13 - ANDROID_3.4.5/sound/core/oss/copy.c | 92 - ANDROID_3.4.5/sound/core/oss/io.c | 141 - ANDROID_3.4.5/sound/core/oss/linear.c | 178 - ANDROID_3.4.5/sound/core/oss/mixer_oss.c | 1422 ---- ANDROID_3.4.5/sound/core/oss/mulaw.c | 344 - ANDROID_3.4.5/sound/core/oss/pcm_oss.c | 3117 --------- ANDROID_3.4.5/sound/core/oss/pcm_plugin.c | 756 --- ANDROID_3.4.5/sound/core/oss/pcm_plugin.h | 185 - ANDROID_3.4.5/sound/core/oss/rate.c | 348 - ANDROID_3.4.5/sound/core/oss/route.c | 109 - ANDROID_3.4.5/sound/core/pcm.c | 1220 ---- ANDROID_3.4.5/sound/core/pcm_compat.c | 532 -- ANDROID_3.4.5/sound/core/pcm_lib.c | 2289 ------- ANDROID_3.4.5/sound/core/pcm_memory.c | 493 -- ANDROID_3.4.5/sound/core/pcm_misc.c | 490 -- ANDROID_3.4.5/sound/core/pcm_native.c | 3492 ---------- ANDROID_3.4.5/sound/core/pcm_timer.c | 141 - ANDROID_3.4.5/sound/core/rawmidi.c | 1726 ----- ANDROID_3.4.5/sound/core/rawmidi_compat.c | 120 - ANDROID_3.4.5/sound/core/rtctimer.c | 188 - ANDROID_3.4.5/sound/core/seq/Kconfig | 16 - ANDROID_3.4.5/sound/core/seq/Makefile | 29 - ANDROID_3.4.5/sound/core/seq/oss/Makefile | 10 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c | 312 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h | 189 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c | 447 -- ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h | 112 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c | 546 -- ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c | 209 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c | 714 -- ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h | 48 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c | 237 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h | 56 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c | 216 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c | 664 -- ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h | 51 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c | 284 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h | 70 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c | 173 - ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h | 50 - ANDROID_3.4.5/sound/core/seq/seq.c | 137 - ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c | 2591 ------- ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h | 103 - ANDROID_3.4.5/sound/core/seq/seq_compat.c | 138 - ANDROID_3.4.5/sound/core/seq/seq_device.c | 573 -- ANDROID_3.4.5/sound/core/seq/seq_dummy.c | 261 - ANDROID_3.4.5/sound/core/seq/seq_fifo.c | 272 - ANDROID_3.4.5/sound/core/seq/seq_fifo.h | 72 - ANDROID_3.4.5/sound/core/seq/seq_info.c | 72 - ANDROID_3.4.5/sound/core/seq/seq_info.h | 40 - ANDROID_3.4.5/sound/core/seq/seq_lock.c | 49 - ANDROID_3.4.5/sound/core/seq/seq_lock.h | 33 - ANDROID_3.4.5/sound/core/seq/seq_memory.c | 521 -- ANDROID_3.4.5/sound/core/seq/seq_memory.h | 107 - ANDROID_3.4.5/sound/core/seq/seq_midi.c | 481 -- ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c | 740 -- ANDROID_3.4.5/sound/core/seq/seq_midi_event.c | 550 -- ANDROID_3.4.5/sound/core/seq/seq_ports.c | 685 -- ANDROID_3.4.5/sound/core/seq/seq_ports.h | 142 - ANDROID_3.4.5/sound/core/seq/seq_prioq.c | 453 -- ANDROID_3.4.5/sound/core/seq/seq_prioq.h | 62 - ANDROID_3.4.5/sound/core/seq/seq_queue.c | 793 --- ANDROID_3.4.5/sound/core/seq/seq_queue.h | 139 - ANDROID_3.4.5/sound/core/seq/seq_system.c | 175 - ANDROID_3.4.5/sound/core/seq/seq_system.h | 46 - ANDROID_3.4.5/sound/core/seq/seq_timer.c | 455 -- ANDROID_3.4.5/sound/core/seq/seq_timer.h | 148 - ANDROID_3.4.5/sound/core/seq/seq_virmidi.c | 543 -- ANDROID_3.4.5/sound/core/sgbuf.c | 138 - ANDROID_3.4.5/sound/core/sound.c | 491 -- ANDROID_3.4.5/sound/core/sound_oss.c | 285 - ANDROID_3.4.5/sound/core/timer.c | 1999 ------ ANDROID_3.4.5/sound/core/timer_compat.c | 127 - ANDROID_3.4.5/sound/core/vmaster.c | 455 -- ANDROID_3.4.5/sound/drivers/Kconfig | 223 - ANDROID_3.4.5/sound/drivers/Makefile | 25 - ANDROID_3.4.5/sound/drivers/aloop.c | 1258 ---- ANDROID_3.4.5/sound/drivers/dummy.c | 1157 ---- ANDROID_3.4.5/sound/drivers/ml403-ac97cr.c | 1344 ---- ANDROID_3.4.5/sound/drivers/mpu401/Makefile | 12 - ANDROID_3.4.5/sound/drivers/mpu401/mpu401.c | 288 - ANDROID_3.4.5/sound/drivers/mpu401/mpu401_uart.c | 632 -- ANDROID_3.4.5/sound/drivers/mtpav.c | 792 --- ANDROID_3.4.5/sound/drivers/mts64.c | 1090 --- ANDROID_3.4.5/sound/drivers/opl3/Makefile | 12 - ANDROID_3.4.5/sound/drivers/opl3/opl3_drums.c | 226 - ANDROID_3.4.5/sound/drivers/opl3/opl3_lib.c | 561 -- ANDROID_3.4.5/sound/drivers/opl3/opl3_midi.c | 881 --- ANDROID_3.4.5/sound/drivers/opl3/opl3_oss.c | 285 - ANDROID_3.4.5/sound/drivers/opl3/opl3_seq.c | 298 - ANDROID_3.4.5/sound/drivers/opl3/opl3_synth.c | 616 -- ANDROID_3.4.5/sound/drivers/opl3/opl3_voice.h | 52 - ANDROID_3.4.5/sound/drivers/opl4/Makefile | 10 - ANDROID_3.4.5/sound/drivers/opl4/opl4_lib.c | 281 - ANDROID_3.4.5/sound/drivers/opl4/opl4_local.h | 232 - ANDROID_3.4.5/sound/drivers/opl4/opl4_mixer.c | 95 - ANDROID_3.4.5/sound/drivers/opl4/opl4_proc.c | 133 - ANDROID_3.4.5/sound/drivers/opl4/opl4_seq.c | 215 - ANDROID_3.4.5/sound/drivers/opl4/opl4_synth.c | 634 -- ANDROID_3.4.5/sound/drivers/opl4/yrw801.c | 961 --- ANDROID_3.4.5/sound/drivers/pcm-indirect2.c | 573 -- ANDROID_3.4.5/sound/drivers/pcm-indirect2.h | 140 - ANDROID_3.4.5/sound/drivers/pcsp/Makefile | 2 - ANDROID_3.4.5/sound/drivers/pcsp/pcsp.c | 244 - ANDROID_3.4.5/sound/drivers/pcsp/pcsp.h | 82 - ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.c | 116 - ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.h | 14 - ANDROID_3.4.5/sound/drivers/pcsp/pcsp_lib.c | 359 - ANDROID_3.4.5/sound/drivers/pcsp/pcsp_mixer.c | 163 - ANDROID_3.4.5/sound/drivers/portman2x4.c | 879 --- ANDROID_3.4.5/sound/drivers/serial-u16550.c | 1050 --- ANDROID_3.4.5/sound/drivers/virmidi.c | 197 - ANDROID_3.4.5/sound/drivers/vx/Makefile | 8 - ANDROID_3.4.5/sound/drivers/vx/vx_cmd.c | 109 - ANDROID_3.4.5/sound/drivers/vx/vx_cmd.h | 246 - ANDROID_3.4.5/sound/drivers/vx/vx_core.c | 828 --- ANDROID_3.4.5/sound/drivers/vx/vx_hwdep.c | 260 - ANDROID_3.4.5/sound/drivers/vx/vx_mixer.c | 1028 --- ANDROID_3.4.5/sound/drivers/vx/vx_pcm.c | 1283 ---- ANDROID_3.4.5/sound/drivers/vx/vx_uer.c | 312 - ANDROID_3.4.5/sound/firewire/Kconfig | 36 - ANDROID_3.4.5/sound/firewire/Makefile | 8 - ANDROID_3.4.5/sound/firewire/amdtp.c | 563 -- ANDROID_3.4.5/sound/firewire/amdtp.h | 169 - ANDROID_3.4.5/sound/firewire/cmp.c | 307 - ANDROID_3.4.5/sound/firewire/cmp.h | 41 - ANDROID_3.4.5/sound/firewire/fcp.c | 224 - ANDROID_3.4.5/sound/firewire/fcp.h | 12 - ANDROID_3.4.5/sound/firewire/isight.c | 753 --- ANDROID_3.4.5/sound/firewire/iso-resources.c | 232 - ANDROID_3.4.5/sound/firewire/iso-resources.h | 38 - ANDROID_3.4.5/sound/firewire/lib.c | 85 - ANDROID_3.4.5/sound/firewire/lib.h | 19 - ANDROID_3.4.5/sound/firewire/packets-buffer.c | 77 - ANDROID_3.4.5/sound/firewire/packets-buffer.h | 26 - ANDROID_3.4.5/sound/firewire/speakers.c | 854 --- ANDROID_3.4.5/sound/i2c/Makefile | 15 - ANDROID_3.4.5/sound/i2c/cs8427.c | 616 -- ANDROID_3.4.5/sound/i2c/i2c.c | 353 - ANDROID_3.4.5/sound/i2c/other/Makefile | 17 - ANDROID_3.4.5/sound/i2c/other/ak4113.c | 639 -- ANDROID_3.4.5/sound/i2c/other/ak4114.c | 626 -- ANDROID_3.4.5/sound/i2c/other/ak4117.c | 552 -- ANDROID_3.4.5/sound/i2c/other/ak4xxx-adda.c | 945 --- ANDROID_3.4.5/sound/i2c/other/pt2258.c | 227 - ANDROID_3.4.5/sound/i2c/other/tea575x-tuner.c | 427 -- ANDROID_3.4.5/sound/i2c/tea6330t.c | 386 -- ANDROID_3.4.5/sound/isa/Kconfig | 446 -- ANDROID_3.4.5/sound/isa/Makefile | 26 - ANDROID_3.4.5/sound/isa/ad1816a/Makefile | 9 - ANDROID_3.4.5/sound/isa/ad1816a/ad1816a.c | 294 - ANDROID_3.4.5/sound/isa/ad1816a/ad1816a_lib.c | 972 --- ANDROID_3.4.5/sound/isa/ad1848/Makefile | 10 - ANDROID_3.4.5/sound/isa/ad1848/ad1848.c | 188 - ANDROID_3.4.5/sound/isa/adlib.c | 129 - ANDROID_3.4.5/sound/isa/als100.c | 378 -- ANDROID_3.4.5/sound/isa/azt2320.c | 354 - ANDROID_3.4.5/sound/isa/cmi8330.c | 782 --- ANDROID_3.4.5/sound/isa/cs423x/Makefile | 13 - ANDROID_3.4.5/sound/isa/cs423x/cs4231.c | 204 - ANDROID_3.4.5/sound/isa/cs423x/cs4236.c | 728 -- ANDROID_3.4.5/sound/isa/cs423x/cs4236_lib.c | 1089 --- ANDROID_3.4.5/sound/isa/es1688/Makefile | 11 - ANDROID_3.4.5/sound/isa/es1688/es1688.c | 372 -- ANDROID_3.4.5/sound/isa/es1688/es1688_lib.c | 1046 --- ANDROID_3.4.5/sound/isa/es18xx.c | 2434 ------- ANDROID_3.4.5/sound/isa/galaxy/Makefile | 10 - ANDROID_3.4.5/sound/isa/galaxy/azt1605.c | 91 - ANDROID_3.4.5/sound/isa/galaxy/azt2316.c | 111 - ANDROID_3.4.5/sound/isa/galaxy/galaxy.c | 651 -- ANDROID_3.4.5/sound/isa/gus/Makefile | 24 - ANDROID_3.4.5/sound/isa/gus/gus_dma.c | 250 - ANDROID_3.4.5/sound/isa/gus/gus_dram.c | 102 - ANDROID_3.4.5/sound/isa/gus/gus_instr.c | 172 - ANDROID_3.4.5/sound/isa/gus/gus_io.c | 540 -- ANDROID_3.4.5/sound/isa/gus/gus_irq.c | 149 - ANDROID_3.4.5/sound/isa/gus/gus_main.c | 483 -- ANDROID_3.4.5/sound/isa/gus/gus_mem.c | 351 - ANDROID_3.4.5/sound/isa/gus/gus_mem_proc.c | 102 - ANDROID_3.4.5/sound/isa/gus/gus_mixer.c | 193 - ANDROID_3.4.5/sound/isa/gus/gus_pcm.c | 910 --- ANDROID_3.4.5/sound/isa/gus/gus_reset.c | 413 -- ANDROID_3.4.5/sound/isa/gus/gus_tables.h | 90 - ANDROID_3.4.5/sound/isa/gus/gus_timer.c | 203 - ANDROID_3.4.5/sound/isa/gus/gus_uart.c | 262 - ANDROID_3.4.5/sound/isa/gus/gus_volume.c | 218 - ANDROID_3.4.5/sound/isa/gus/gusclassic.c | 245 - ANDROID_3.4.5/sound/isa/gus/gusextreme.c | 373 -- ANDROID_3.4.5/sound/isa/gus/gusmax.c | 387 -- ANDROID_3.4.5/sound/isa/gus/interwave-stb.c | 2 - ANDROID_3.4.5/sound/isa/gus/interwave.c | 947 --- ANDROID_3.4.5/sound/isa/msnd/Makefile | 9 - ANDROID_3.4.5/sound/isa/msnd/msnd.c | 708 -- ANDROID_3.4.5/sound/isa/msnd/msnd.h | 308 - ANDROID_3.4.5/sound/isa/msnd/msnd_classic.c | 3 - ANDROID_3.4.5/sound/isa/msnd/msnd_classic.h | 129 - ANDROID_3.4.5/sound/isa/msnd/msnd_midi.c | 182 - ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.c | 1245 ---- ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.h | 181 - ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle_mixer.c | 344 - ANDROID_3.4.5/sound/isa/opl3sa2.c | 971 --- ANDROID_3.4.5/sound/isa/opti9xx/Makefile | 15 - ANDROID_3.4.5/sound/isa/opti9xx/miro.c | 1680 ----- ANDROID_3.4.5/sound/isa/opti9xx/opti92x-ad1848.c | 1165 ---- ANDROID_3.4.5/sound/isa/opti9xx/opti92x-cs4231.c | 2 - ANDROID_3.4.5/sound/isa/opti9xx/opti93x.c | 3 - ANDROID_3.4.5/sound/isa/sb/Makefile | 28 - ANDROID_3.4.5/sound/isa/sb/emu8000.c | 1163 ---- ANDROID_3.4.5/sound/isa/sb/emu8000_callback.c | 547 -- ANDROID_3.4.5/sound/isa/sb/emu8000_local.h | 45 - ANDROID_3.4.5/sound/isa/sb/emu8000_patch.c | 305 - ANDROID_3.4.5/sound/isa/sb/emu8000_pcm.c | 705 -- ANDROID_3.4.5/sound/isa/sb/emu8000_synth.c | 136 - ANDROID_3.4.5/sound/isa/sb/jazz16.c | 404 -- ANDROID_3.4.5/sound/isa/sb/sb16.c | 699 -- ANDROID_3.4.5/sound/isa/sb/sb16_csp.c | 1202 ---- ANDROID_3.4.5/sound/isa/sb/sb16_main.c | 925 --- ANDROID_3.4.5/sound/isa/sb/sb8.c | 268 - ANDROID_3.4.5/sound/isa/sb/sb8_main.c | 646 -- ANDROID_3.4.5/sound/isa/sb/sb8_midi.c | 286 - ANDROID_3.4.5/sound/isa/sb/sb_common.c | 324 - ANDROID_3.4.5/sound/isa/sb/sb_mixer.c | 978 --- ANDROID_3.4.5/sound/isa/sb/sbawe.c | 2 - ANDROID_3.4.5/sound/isa/sc6000.c | 728 -- ANDROID_3.4.5/sound/isa/sscape.c | 1359 ---- ANDROID_3.4.5/sound/isa/wavefront/Makefile | 9 - ANDROID_3.4.5/sound/isa/wavefront/wavefront.c | 687 -- ANDROID_3.4.5/sound/isa/wavefront/wavefront_fx.c | 285 - ANDROID_3.4.5/sound/isa/wavefront/wavefront_midi.c | 577 -- .../sound/isa/wavefront/wavefront_synth.c | 2199 ------ ANDROID_3.4.5/sound/isa/wss/Makefile | 10 - ANDROID_3.4.5/sound/isa/wss/wss_lib.c | 2304 ------- ANDROID_3.4.5/sound/last.c | 41 - ANDROID_3.4.5/sound/mips/Kconfig | 37 - ANDROID_3.4.5/sound/mips/Makefile | 12 - ANDROID_3.4.5/sound/mips/ad1843.c | 561 -- ANDROID_3.4.5/sound/mips/au1x00.c | 696 -- ANDROID_3.4.5/sound/mips/hal2.c | 938 --- ANDROID_3.4.5/sound/mips/hal2.h | 245 - ANDROID_3.4.5/sound/mips/sgio2audio.c | 979 --- ANDROID_3.4.5/sound/oss/CHANGELOG | 369 - ANDROID_3.4.5/sound/oss/Kconfig | 541 -- ANDROID_3.4.5/sound/oss/Makefile | 108 - ANDROID_3.4.5/sound/oss/README.FIRST | 6 - ANDROID_3.4.5/sound/oss/ad1848.c | 3069 --------- ANDROID_3.4.5/sound/oss/ad1848.h | 24 - ANDROID_3.4.5/sound/oss/ad1848_mixer.h | 253 - ANDROID_3.4.5/sound/oss/aedsp16.c | 1373 ---- ANDROID_3.4.5/sound/oss/audio.c | 985 --- ANDROID_3.4.5/sound/oss/bin2hex.c | 39 - ANDROID_3.4.5/sound/oss/coproc.h | 12 - ANDROID_3.4.5/sound/oss/dev_table.c | 256 - ANDROID_3.4.5/sound/oss/dev_table.h | 390 -- ANDROID_3.4.5/sound/oss/dmabuf.c | 1268 ---- ANDROID_3.4.5/sound/oss/dmasound/Kconfig | 45 - ANDROID_3.4.5/sound/oss/dmasound/Makefile | 7 - ANDROID_3.4.5/sound/oss/dmasound/dmasound.h | 262 - ANDROID_3.4.5/sound/oss/dmasound/dmasound_atari.c | 1620 ----- ANDROID_3.4.5/sound/oss/dmasound/dmasound_core.c | 1589 ----- ANDROID_3.4.5/sound/oss/dmasound/dmasound_paula.c | 751 --- ANDROID_3.4.5/sound/oss/dmasound/dmasound_q40.c | 638 -- ANDROID_3.4.5/sound/oss/hex2hex.c | 101 - ANDROID_3.4.5/sound/oss/kahlua.c | 231 - ANDROID_3.4.5/sound/oss/midi_ctrl.h | 22 - ANDROID_3.4.5/sound/oss/midi_synth.c | 712 -- ANDROID_3.4.5/sound/oss/midi_synth.h | 47 - ANDROID_3.4.5/sound/oss/midibuf.c | 425 -- ANDROID_3.4.5/sound/oss/mpu401.c | 1806 ----- ANDROID_3.4.5/sound/oss/mpu401.h | 11 - ANDROID_3.4.5/sound/oss/msnd.c | 413 -- ANDROID_3.4.5/sound/oss/msnd.h | 278 - ANDROID_3.4.5/sound/oss/msnd_classic.c | 3 - ANDROID_3.4.5/sound/oss/msnd_classic.h | 185 - ANDROID_3.4.5/sound/oss/msnd_pinnacle.c | 1935 ------ ANDROID_3.4.5/sound/oss/msnd_pinnacle.h | 246 - ANDROID_3.4.5/sound/oss/opl3.c | 1258 ---- ANDROID_3.4.5/sound/oss/opl3_hw.h | 246 - ANDROID_3.4.5/sound/oss/os.h | 45 - ANDROID_3.4.5/sound/oss/pas2.h | 17 - ANDROID_3.4.5/sound/oss/pas2_card.c | 455 -- ANDROID_3.4.5/sound/oss/pas2_midi.c | 262 - ANDROID_3.4.5/sound/oss/pas2_mixer.c | 336 - ANDROID_3.4.5/sound/oss/pas2_pcm.c | 437 -- ANDROID_3.4.5/sound/oss/pss.c | 1268 ---- ANDROID_3.4.5/sound/oss/sb.h | 185 - ANDROID_3.4.5/sound/oss/sb_audio.c | 1098 --- ANDROID_3.4.5/sound/oss/sb_card.c | 354 - ANDROID_3.4.5/sound/oss/sb_card.h | 149 - ANDROID_3.4.5/sound/oss/sb_common.c | 1292 ---- ANDROID_3.4.5/sound/oss/sb_ess.c | 1831 ----- ANDROID_3.4.5/sound/oss/sb_ess.h | 34 - ANDROID_3.4.5/sound/oss/sb_midi.c | 206 - ANDROID_3.4.5/sound/oss/sb_mixer.c | 770 --- ANDROID_3.4.5/sound/oss/sb_mixer.h | 105 - ANDROID_3.4.5/sound/oss/sequencer.c | 1671 ----- ANDROID_3.4.5/sound/oss/sound_calls.h | 87 - ANDROID_3.4.5/sound/oss/sound_config.h | 147 - ANDROID_3.4.5/sound/oss/sound_firmware.h | 2 - ANDROID_3.4.5/sound/oss/sound_timer.c | 327 - ANDROID_3.4.5/sound/oss/soundcard.c | 739 -- ANDROID_3.4.5/sound/oss/soundvers.h | 2 - ANDROID_3.4.5/sound/oss/swarm_cs4297a.c | 2768 -------- ANDROID_3.4.5/sound/oss/sys_timer.c | 285 - ANDROID_3.4.5/sound/oss/trix.c | 525 -- ANDROID_3.4.5/sound/oss/tuning.h | 23 - ANDROID_3.4.5/sound/oss/uart401.c | 482 -- ANDROID_3.4.5/sound/oss/uart6850.c | 361 - ANDROID_3.4.5/sound/oss/ulaw.h | 69 - ANDROID_3.4.5/sound/oss/v_midi.c | 290 - ANDROID_3.4.5/sound/oss/v_midi.h | 14 - ANDROID_3.4.5/sound/oss/vidc.c | 557 -- ANDROID_3.4.5/sound/oss/vidc.h | 63 - ANDROID_3.4.5/sound/oss/vidc_fill.S | 218 - ANDROID_3.4.5/sound/oss/vwsnd.c | 3498 ---------- ANDROID_3.4.5/sound/oss/waveartist.c | 2024 ------ ANDROID_3.4.5/sound/oss/waveartist.h | 92 - ANDROID_3.4.5/sound/parisc/Kconfig | 20 - ANDROID_3.4.5/sound/parisc/Makefile | 8 - ANDROID_3.4.5/sound/parisc/harmony.c | 1047 --- ANDROID_3.4.5/sound/parisc/harmony.h | 154 - ANDROID_3.4.5/sound/pci/Kconfig | 872 --- ANDROID_3.4.5/sound/pci/Makefile | 82 - ANDROID_3.4.5/sound/pci/ac97/Makefile | 10 - ANDROID_3.4.5/sound/pci/ac97/ac97_codec.c | 2937 -------- ANDROID_3.4.5/sound/pci/ac97/ac97_id.h | 66 - ANDROID_3.4.5/sound/pci/ac97/ac97_local.h | 41 - ANDROID_3.4.5/sound/pci/ac97/ac97_patch.c | 3965 ----------- ANDROID_3.4.5/sound/pci/ac97/ac97_patch.h | 95 - ANDROID_3.4.5/sound/pci/ac97/ac97_pcm.c | 737 -- ANDROID_3.4.5/sound/pci/ac97/ac97_proc.c | 490 -- ANDROID_3.4.5/sound/pci/ad1889.c | 1078 --- ANDROID_3.4.5/sound/pci/ad1889.h | 189 - ANDROID_3.4.5/sound/pci/ak4531_codec.c | 494 -- ANDROID_3.4.5/sound/pci/ali5451/Makefile | 9 - ANDROID_3.4.5/sound/pci/ali5451/ali5451.c | 2319 ------- ANDROID_3.4.5/sound/pci/als300.c | 877 --- ANDROID_3.4.5/sound/pci/als4000.c | 1061 --- ANDROID_3.4.5/sound/pci/asihpi/Makefile | 5 - ANDROID_3.4.5/sound/pci/asihpi/asihpi.c | 2992 --------- ANDROID_3.4.5/sound/pci/asihpi/hpi.h | 1727 ----- ANDROID_3.4.5/sound/pci/asihpi/hpi6000.c | 1809 ----- ANDROID_3.4.5/sound/pci/asihpi/hpi6000.h | 70 - ANDROID_3.4.5/sound/pci/asihpi/hpi6205.c | 2208 ------ ANDROID_3.4.5/sound/pci/asihpi/hpi6205.h | 103 - ANDROID_3.4.5/sound/pci/asihpi/hpi_internal.h | 1431 ---- ANDROID_3.4.5/sound/pci/asihpi/hpi_version.h | 32 - ANDROID_3.4.5/sound/pci/asihpi/hpicmn.c | 703 -- ANDROID_3.4.5/sound/pci/asihpi/hpicmn.h | 67 - ANDROID_3.4.5/sound/pci/asihpi/hpidebug.c | 78 - ANDROID_3.4.5/sound/pci/asihpi/hpidebug.h | 102 - ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.c | 148 - ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.h | 106 - ANDROID_3.4.5/sound/pci/asihpi/hpifunc.c | 2871 -------- ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.c | 116 - ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.h | 46 - ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.c | 800 --- ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.h | 36 - ANDROID_3.4.5/sound/pci/asihpi/hpioctl.c | 482 -- ANDROID_3.4.5/sound/pci/asihpi/hpioctl.h | 38 - ANDROID_3.4.5/sound/pci/asihpi/hpios.c | 83 - ANDROID_3.4.5/sound/pci/asihpi/hpios.h | 165 - ANDROID_3.4.5/sound/pci/asihpi/hpipcida.h | 37 - ANDROID_3.4.5/sound/pci/atiixp.c | 1726 ----- ANDROID_3.4.5/sound/pci/atiixp_modem.c | 1357 ---- ANDROID_3.4.5/sound/pci/au88x0/Makefile | 7 - ANDROID_3.4.5/sound/pci/au88x0/au8810.c | 16 - ANDROID_3.4.5/sound/pci/au88x0/au8810.h | 224 - ANDROID_3.4.5/sound/pci/au88x0/au8820.c | 14 - ANDROID_3.4.5/sound/pci/au88x0/au8820.h | 204 - ANDROID_3.4.5/sound/pci/au88x0/au8830.c | 17 - ANDROID_3.4.5/sound/pci/au88x0/au8830.h | 251 - ANDROID_3.4.5/sound/pci/au88x0/au88x0.c | 398 -- ANDROID_3.4.5/sound/pci/au88x0/au88x0.h | 295 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.c | 914 --- ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.h | 123 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3ddata.c | 91 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_core.c | 2856 -------- ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.c | 929 --- ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.h | 43 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_eqdata.c | 116 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_game.c | 133 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_mixer.c | 32 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_mpu401.c | 112 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_pcm.c | 678 -- ANDROID_3.4.5/sound/pci/au88x0/au88x0_synth.c | 418 -- ANDROID_3.4.5/sound/pci/au88x0/au88x0_wt.h | 65 - ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.c | 795 --- ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.h | 61 - ANDROID_3.4.5/sound/pci/aw2/Makefile | 3 - ANDROID_3.4.5/sound/pci/aw2/aw2-alsa.c | 792 --- ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.c | 463 -- ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.h | 105 - ANDROID_3.4.5/sound/pci/aw2/aw2-tsl.c | 110 - ANDROID_3.4.5/sound/pci/aw2/saa7146.h | 168 - ANDROID_3.4.5/sound/pci/azt3328.c | 2895 -------- ANDROID_3.4.5/sound/pci/azt3328.h | 342 - ANDROID_3.4.5/sound/pci/bt87x.c | 987 --- ANDROID_3.4.5/sound/pci/ca0106/Makefile | 3 - ANDROID_3.4.5/sound/pci/ca0106/ca0106.h | 742 --- ANDROID_3.4.5/sound/pci/ca0106/ca0106_main.c | 1959 ------ ANDROID_3.4.5/sound/pci/ca0106/ca0106_mixer.c | 956 --- ANDROID_3.4.5/sound/pci/ca0106/ca0106_proc.c | 457 -- ANDROID_3.4.5/sound/pci/ca0106/ca_midi.c | 316 - ANDROID_3.4.5/sound/pci/ca0106/ca_midi.h | 66 - ANDROID_3.4.5/sound/pci/cmipci.c | 3423 ---------- ANDROID_3.4.5/sound/pci/cs4281.c | 2109 ------ ANDROID_3.4.5/sound/pci/cs46xx/Makefile | 10 - ANDROID_3.4.5/sound/pci/cs46xx/cs46xx.c | 186 - ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_image.h | 3468 ---------- ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.c | 3882 ----------- ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.h | 210 - ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.c | 2017 ------ ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.h | 231 - ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos_scb_lib.c | 1784 ----- ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwc4630.h | 320 - ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcasync.h | 176 - ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcbinhack.h | 48 - ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.asp | 170 - ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.h | 68 - ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcsnoop.h | 46 - ANDROID_3.4.5/sound/pci/cs5530.c | 313 - ANDROID_3.4.5/sound/pci/cs5535audio/Makefile | 10 - ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.c | 424 -- ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.h | 142 - .../sound/pci/cs5535audio/cs5535audio_olpc.c | 191 - .../sound/pci/cs5535audio/cs5535audio_pcm.c | 454 -- .../sound/pci/cs5535audio/cs5535audio_pm.c | 131 - ANDROID_3.4.5/sound/pci/ctxfi/Makefile | 5 - ANDROID_3.4.5/sound/pci/ctxfi/ct20k1reg.h | 636 -- ANDROID_3.4.5/sound/pci/ctxfi/ct20k2reg.h | 89 - ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.c | 486 -- ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.h | 96 - ANDROID_3.4.5/sound/pci/ctxfi/ctatc.c | 1744 ----- ANDROID_3.4.5/sound/pci/ctxfi/ctatc.h | 160 - ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.c | 762 --- ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.h | 123 - ANDROID_3.4.5/sound/pci/ctxfi/cthardware.c | 91 - ANDROID_3.4.5/sound/pci/ctxfi/cthardware.h | 215 - ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.c | 2304 ------- ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.h | 26 - ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.c | 2370 ------- ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.h | 26 - ANDROID_3.4.5/sound/pci/ctxfi/ctimap.c | 112 - ANDROID_3.4.5/sound/pci/ctxfi/ctimap.h | 40 - ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.c | 1227 ---- ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.h | 70 - ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.c | 435 -- ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.h | 27 - ANDROID_3.4.5/sound/pci/ctxfi/ctresource.c | 301 - ANDROID_3.4.5/sound/pci/ctxfi/ctresource.h | 72 - ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.c | 885 --- ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.h | 149 - ANDROID_3.4.5/sound/pci/ctxfi/cttimer.c | 443 -- ANDROID_3.4.5/sound/pci/ctxfi/cttimer.h | 29 - ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.c | 247 - ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.h | 63 - ANDROID_3.4.5/sound/pci/ctxfi/xfi.c | 168 - ANDROID_3.4.5/sound/pci/echoaudio/Makefile | 34 - ANDROID_3.4.5/sound/pci/echoaudio/darla20.c | 101 - ANDROID_3.4.5/sound/pci/echoaudio/darla20_dsp.c | 130 - ANDROID_3.4.5/sound/pci/echoaudio/darla24.c | 108 - ANDROID_3.4.5/sound/pci/echoaudio/darla24_dsp.c | 162 - ANDROID_3.4.5/sound/pci/echoaudio/echo3g.c | 122 - ANDROID_3.4.5/sound/pci/echoaudio/echo3g_dsp.c | 132 - ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.c | 2360 ------- ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.h | 598 -- ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_3g.c | 432 -- ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.c | 1151 ---- ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.h | 698 -- ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_gml.c | 200 - ANDROID_3.4.5/sound/pci/echoaudio/gina20.c | 105 - ANDROID_3.4.5/sound/pci/echoaudio/gina20_dsp.c | 220 - ANDROID_3.4.5/sound/pci/echoaudio/gina24.c | 129 - ANDROID_3.4.5/sound/pci/echoaudio/gina24_dsp.c | 349 - ANDROID_3.4.5/sound/pci/echoaudio/indigo.c | 107 - ANDROID_3.4.5/sound/pci/echoaudio/indigo_dsp.c | 164 - .../sound/pci/echoaudio/indigo_express_dsp.c | 120 - ANDROID_3.4.5/sound/pci/echoaudio/indigodj.c | 107 - ANDROID_3.4.5/sound/pci/echoaudio/indigodj_dsp.c | 164 - ANDROID_3.4.5/sound/pci/echoaudio/indigodjx.c | 108 - ANDROID_3.4.5/sound/pci/echoaudio/indigodjx_dsp.c | 71 - ANDROID_3.4.5/sound/pci/echoaudio/indigoio.c | 108 - ANDROID_3.4.5/sound/pci/echoaudio/indigoio_dsp.c | 135 - ANDROID_3.4.5/sound/pci/echoaudio/indigoiox.c | 110 - ANDROID_3.4.5/sound/pci/echoaudio/indigoiox_dsp.c | 71 - ANDROID_3.4.5/sound/pci/echoaudio/layla20.c | 115 - ANDROID_3.4.5/sound/pci/echoaudio/layla20_dsp.c | 295 - ANDROID_3.4.5/sound/pci/echoaudio/layla24.c | 127 - ANDROID_3.4.5/sound/pci/echoaudio/layla24_dsp.c | 398 -- ANDROID_3.4.5/sound/pci/echoaudio/mia.c | 121 - ANDROID_3.4.5/sound/pci/echoaudio/mia_dsp.c | 224 - ANDROID_3.4.5/sound/pci/echoaudio/midi.c | 331 - ANDROID_3.4.5/sound/pci/echoaudio/mona.c | 138 - ANDROID_3.4.5/sound/pci/echoaudio/mona_dsp.c | 427 -- ANDROID_3.4.5/sound/pci/emu10k1/Makefile | 15 - ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c | 288 - ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c | 552 -- ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c | 2101 ------ ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c | 229 - ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c | 124 - .../sound/pci/emu10k1/emu10k1_synth_local.h | 42 - ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c | 1635 ----- ANDROID_3.4.5/sound/pci/emu10k1/emufx.c | 2758 -------- ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c | 2143 ------ ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c | 396 -- ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c | 1870 ------ ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c | 671 -- ANDROID_3.4.5/sound/pci/emu10k1/io.c | 583 -- ANDROID_3.4.5/sound/pci/emu10k1/irq.c | 208 - ANDROID_3.4.5/sound/pci/emu10k1/memory.c | 573 -- ANDROID_3.4.5/sound/pci/emu10k1/p16v.c | 934 --- ANDROID_3.4.5/sound/pci/emu10k1/p16v.h | 299 - ANDROID_3.4.5/sound/pci/emu10k1/p17v.h | 158 - ANDROID_3.4.5/sound/pci/emu10k1/timer.c | 96 - ANDROID_3.4.5/sound/pci/emu10k1/tina2.h | 32 - ANDROID_3.4.5/sound/pci/emu10k1/voice.c | 168 - ANDROID_3.4.5/sound/pci/ens1370.c | 2513 ------- ANDROID_3.4.5/sound/pci/ens1371.c | 2 - ANDROID_3.4.5/sound/pci/es1938.c | 1907 ------ ANDROID_3.4.5/sound/pci/es1968.c | 2923 -------- ANDROID_3.4.5/sound/pci/fm801.c | 1441 ---- ANDROID_3.4.5/sound/pci/hda/Kconfig | 261 - ANDROID_3.4.5/sound/pci/hda/Makefile | 65 - ANDROID_3.4.5/sound/pci/hda/hda_beep.c | 268 - ANDROID_3.4.5/sound/pci/hda/hda_beep.h | 61 - ANDROID_3.4.5/sound/pci/hda/hda_codec.c | 5548 --------------- ANDROID_3.4.5/sound/pci/hda/hda_codec.h | 1084 --- ANDROID_3.4.5/sound/pci/hda/hda_eld.c | 671 -- ANDROID_3.4.5/sound/pci/hda/hda_generic.c | 1085 --- ANDROID_3.4.5/sound/pci/hda/hda_hwdep.c | 817 --- ANDROID_3.4.5/sound/pci/hda/hda_intel.c | 3173 --------- ANDROID_3.4.5/sound/pci/hda/hda_jack.c | 375 -- ANDROID_3.4.5/sound/pci/hda/hda_jack.h | 75 - ANDROID_3.4.5/sound/pci/hda/hda_local.h | 708 -- ANDROID_3.4.5/sound/pci/hda/hda_proc.c | 742 --- ANDROID_3.4.5/sound/pci/hda/hda_trace.h | 117 - ANDROID_3.4.5/sound/pci/hda/patch_analog.c | 5067 -------------- ANDROID_3.4.5/sound/pci/hda/patch_ca0110.c | 576 -- ANDROID_3.4.5/sound/pci/hda/patch_ca0132.c | 1103 --- ANDROID_3.4.5/sound/pci/hda/patch_cirrus.c | 2053 ------ ANDROID_3.4.5/sound/pci/hda/patch_cmedia.c | 776 --- ANDROID_3.4.5/sound/pci/hda/patch_conexant.c | 4599 ------------- ANDROID_3.4.5/sound/pci/hda/patch_hdmi.c | 1986 ------ ANDROID_3.4.5/sound/pci/hda/patch_realtek.c | 7034 -------------------- ANDROID_3.4.5/sound/pci/hda/patch_si3054.c | 337 - ANDROID_3.4.5/sound/pci/hda/patch_sigmatel.c | 6515 ------------------ ANDROID_3.4.5/sound/pci/hda/patch_via.c | 3935 ----------- ANDROID_3.4.5/sound/pci/ice1712/Makefile | 12 - ANDROID_3.4.5/sound/pci/ice1712/ak4xxx.c | 196 - ANDROID_3.4.5/sound/pci/ice1712/amp.c | 98 - ANDROID_3.4.5/sound/pci/ice1712/amp.h | 48 - ANDROID_3.4.5/sound/pci/ice1712/aureon.c | 2308 ------- ANDROID_3.4.5/sound/pci/ice1712/aureon.h | 65 - ANDROID_3.4.5/sound/pci/ice1712/delta.c | 881 --- ANDROID_3.4.5/sound/pci/ice1712/delta.h | 166 - ANDROID_3.4.5/sound/pci/ice1712/envy24ht.h | 220 - ANDROID_3.4.5/sound/pci/ice1712/ews.c | 1087 --- ANDROID_3.4.5/sound/pci/ice1712/ews.h | 86 - ANDROID_3.4.5/sound/pci/ice1712/hoontech.c | 360 - ANDROID_3.4.5/sound/pci/ice1712/hoontech.h | 77 - ANDROID_3.4.5/sound/pci/ice1712/ice1712.c | 2824 -------- ANDROID_3.4.5/sound/pci/ice1712/ice1712.h | 531 -- ANDROID_3.4.5/sound/pci/ice1712/ice1724.c | 2898 -------- ANDROID_3.4.5/sound/pci/ice1712/juli.c | 700 -- ANDROID_3.4.5/sound/pci/ice1712/juli.h | 10 - ANDROID_3.4.5/sound/pci/ice1712/maya44.c | 779 --- ANDROID_3.4.5/sound/pci/ice1712/maya44.h | 10 - ANDROID_3.4.5/sound/pci/ice1712/phase.c | 975 --- ANDROID_3.4.5/sound/pci/ice1712/phase.h | 53 - ANDROID_3.4.5/sound/pci/ice1712/pontis.c | 836 --- ANDROID_3.4.5/sound/pci/ice1712/pontis.h | 33 - ANDROID_3.4.5/sound/pci/ice1712/prodigy192.c | 822 --- ANDROID_3.4.5/sound/pci/ice1712/prodigy192.h | 19 - ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.c | 1236 ---- ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.h | 38 - ANDROID_3.4.5/sound/pci/ice1712/quartet.c | 1130 ---- ANDROID_3.4.5/sound/pci/ice1712/quartet.h | 10 - ANDROID_3.4.5/sound/pci/ice1712/revo.c | 633 -- ANDROID_3.4.5/sound/pci/ice1712/revo.h | 55 - ANDROID_3.4.5/sound/pci/ice1712/se.c | 774 --- ANDROID_3.4.5/sound/pci/ice1712/se.h | 15 - ANDROID_3.4.5/sound/pci/ice1712/stac946x.h | 25 - ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.c | 139 - ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.h | 41 - ANDROID_3.4.5/sound/pci/ice1712/wtm.c | 517 -- ANDROID_3.4.5/sound/pci/ice1712/wtm.h | 20 - ANDROID_3.4.5/sound/pci/intel8x0.c | 3364 ---------- ANDROID_3.4.5/sound/pci/intel8x0m.c | 1350 ---- ANDROID_3.4.5/sound/pci/korg1212/Makefile | 9 - ANDROID_3.4.5/sound/pci/korg1212/korg1212.c | 2497 ------- ANDROID_3.4.5/sound/pci/lola/Makefile | 4 - ANDROID_3.4.5/sound/pci/lola/lola.c | 791 --- ANDROID_3.4.5/sound/pci/lola/lola.h | 527 -- ANDROID_3.4.5/sound/pci/lola/lola_clock.c | 323 - ANDROID_3.4.5/sound/pci/lola/lola_mixer.c | 895 --- ANDROID_3.4.5/sound/pci/lola/lola_pcm.c | 706 -- ANDROID_3.4.5/sound/pci/lola/lola_proc.c | 222 - ANDROID_3.4.5/sound/pci/lx6464es/Makefile | 2 - ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.c | 1164 ---- ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.h | 114 - ANDROID_3.4.5/sound/pci/lx6464es/lx_core.c | 1357 ---- ANDROID_3.4.5/sound/pci/lx6464es/lx_core.h | 239 - ANDROID_3.4.5/sound/pci/lx6464es/lx_defs.h | 376 -- ANDROID_3.4.5/sound/pci/maestro3.c | 2862 -------- ANDROID_3.4.5/sound/pci/mixart/Makefile | 8 - ANDROID_3.4.5/sound/pci/mixart/mixart.c | 1401 ---- ANDROID_3.4.5/sound/pci/mixart/mixart.h | 228 - ANDROID_3.4.5/sound/pci/mixart/mixart_core.c | 598 -- ANDROID_3.4.5/sound/pci/mixart/mixart_core.h | 571 -- ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c | 653 -- ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h | 155 - ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c | 1186 ---- ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h | 31 - ANDROID_3.4.5/sound/pci/nm256/Makefile | 9 - ANDROID_3.4.5/sound/pci/nm256/nm256.c | 1768 ----- ANDROID_3.4.5/sound/pci/nm256/nm256_coef.c | 4607 ------------- ANDROID_3.4.5/sound/pci/oxygen/Makefile | 8 - ANDROID_3.4.5/sound/pci/oxygen/ak4396.h | 44 - ANDROID_3.4.5/sound/pci/oxygen/cm9780.h | 63 - ANDROID_3.4.5/sound/pci/oxygen/cs2000.h | 83 - ANDROID_3.4.5/sound/pci/oxygen/cs4245.h | 107 - ANDROID_3.4.5/sound/pci/oxygen/cs4362a.h | 69 - ANDROID_3.4.5/sound/pci/oxygen/cs4398.h | 69 - ANDROID_3.4.5/sound/pci/oxygen/oxygen.c | 884 --- ANDROID_3.4.5/sound/pci/oxygen/oxygen.h | 260 - ANDROID_3.4.5/sound/pci/oxygen/oxygen_io.c | 279 - ANDROID_3.4.5/sound/pci/oxygen/oxygen_lib.c | 834 --- ANDROID_3.4.5/sound/pci/oxygen/oxygen_mixer.c | 1102 --- ANDROID_3.4.5/sound/pci/oxygen/oxygen_pcm.c | 766 --- ANDROID_3.4.5/sound/pci/oxygen/oxygen_regs.h | 457 -- ANDROID_3.4.5/sound/pci/oxygen/pcm1796.h | 58 - ANDROID_3.4.5/sound/pci/oxygen/virtuoso.c | 114 - ANDROID_3.4.5/sound/pci/oxygen/wm8766.h | 73 - ANDROID_3.4.5/sound/pci/oxygen/wm8776.h | 177 - ANDROID_3.4.5/sound/pci/oxygen/wm8785.h | 45 - ANDROID_3.4.5/sound/pci/oxygen/xonar.h | 54 - ANDROID_3.4.5/sound/pci/oxygen/xonar_cs43xx.c | 452 -- ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.c | 609 -- ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.h | 8 - ANDROID_3.4.5/sound/pci/oxygen/xonar_hdmi.c | 128 - ANDROID_3.4.5/sound/pci/oxygen/xonar_lib.c | 134 - ANDROID_3.4.5/sound/pci/oxygen/xonar_pcm179x.c | 1145 ---- ANDROID_3.4.5/sound/pci/oxygen/xonar_wm87x6.c | 1338 ---- ANDROID_3.4.5/sound/pci/pcxhr/Makefile | 2 - ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.c | 1628 ----- ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.h | 216 - ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.c | 1305 ---- ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.h | 203 - ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.c | 503 -- ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.h | 40 - ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.c | 852 --- ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.h | 59 - ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.c | 1270 ---- ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.h | 29 - ANDROID_3.4.5/sound/pci/riptide/Makefile | 3 - ANDROID_3.4.5/sound/pci/riptide/riptide.c | 2223 ------- ANDROID_3.4.5/sound/pci/rme32.c | 2005 ------ ANDROID_3.4.5/sound/pci/rme96.c | 2416 ------- ANDROID_3.4.5/sound/pci/rme9652/Makefile | 13 - ANDROID_3.4.5/sound/pci/rme9652/hdsp.c | 5657 ---------------- ANDROID_3.4.5/sound/pci/rme9652/hdspm.c | 6940 ------------------- ANDROID_3.4.5/sound/pci/rme9652/rme9652.c | 2652 -------- ANDROID_3.4.5/sound/pci/sis7019.c | 1502 ----- ANDROID_3.4.5/sound/pci/sis7019.h | 342 - ANDROID_3.4.5/sound/pci/sonicvibes.c | 1551 ----- ANDROID_3.4.5/sound/pci/trident/Makefile | 9 - ANDROID_3.4.5/sound/pci/trident/trident.c | 197 - ANDROID_3.4.5/sound/pci/trident/trident_main.c | 3982 ----------- ANDROID_3.4.5/sound/pci/trident/trident_memory.c | 315 - ANDROID_3.4.5/sound/pci/via82xx.c | 2644 -------- ANDROID_3.4.5/sound/pci/via82xx_modem.c | 1248 ---- ANDROID_3.4.5/sound/pci/vx222/Makefile | 8 - ANDROID_3.4.5/sound/pci/vx222/vx222.c | 314 - ANDROID_3.4.5/sound/pci/vx222/vx222.h | 114 - ANDROID_3.4.5/sound/pci/vx222/vx222_ops.c | 1031 --- ANDROID_3.4.5/sound/pci/ymfpci/Makefile | 9 - ANDROID_3.4.5/sound/pci/ymfpci/ymfpci.c | 375 -- ANDROID_3.4.5/sound/pci/ymfpci/ymfpci_main.c | 2470 ------- ANDROID_3.4.5/sound/pcmcia/Kconfig | 33 - ANDROID_3.4.5/sound/pcmcia/Makefile | 6 - ANDROID_3.4.5/sound/pcmcia/pdaudiocf/Makefile | 8 - ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.c | 312 - ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.h | 142 - .../sound/pcmcia/pdaudiocf/pdaudiocf_core.c | 298 - .../sound/pcmcia/pdaudiocf/pdaudiocf_irq.c | 325 - .../sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 307 - ANDROID_3.4.5/sound/pcmcia/vx/Makefile | 8 - ANDROID_3.4.5/sound/pcmcia/vx/vxp_mixer.c | 151 - ANDROID_3.4.5/sound/pcmcia/vx/vxp_ops.c | 614 -- ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.c | 382 -- ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.h | 90 - ANDROID_3.4.5/sound/ppc/Kconfig | 52 - ANDROID_3.4.5/sound/ppc/Makefile | 10 - ANDROID_3.4.5/sound/ppc/awacs.c | 1146 ---- ANDROID_3.4.5/sound/ppc/awacs.h | 205 - ANDROID_3.4.5/sound/ppc/beep.c | 285 - ANDROID_3.4.5/sound/ppc/burgundy.c | 732 -- ANDROID_3.4.5/sound/ppc/burgundy.h | 114 - ANDROID_3.4.5/sound/ppc/daca.c | 282 - ANDROID_3.4.5/sound/ppc/keywest.c | 147 - ANDROID_3.4.5/sound/ppc/pmac.c | 1410 ---- ANDROID_3.4.5/sound/ppc/pmac.h | 210 - ANDROID_3.4.5/sound/ppc/powermac.c | 195 - ANDROID_3.4.5/sound/ppc/snd_ps3.c | 1160 ---- ANDROID_3.4.5/sound/ppc/snd_ps3.h | 136 - ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h | 891 --- ANDROID_3.4.5/sound/ppc/tumbler.c | 1495 ----- ANDROID_3.4.5/sound/ppc/tumbler_volume.h | 250 - ANDROID_3.4.5/sound/sh/Kconfig | 31 - ANDROID_3.4.5/sound/sh/Makefile | 10 - ANDROID_3.4.5/sound/sh/aica.c | 689 -- ANDROID_3.4.5/sound/sh/aica.h | 81 - ANDROID_3.4.5/sound/sh/sh_dac_audio.c | 444 -- ANDROID_3.4.5/sound/soc/Kconfig | 57 - ANDROID_3.4.5/sound/soc/Makefile | 28 - ANDROID_3.4.5/sound/soc/atmel/Kconfig | 33 - ANDROID_3.4.5/sound/soc/atmel/Makefile | 12 - ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.c | 501 -- ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.h | 83 - ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.c | 867 --- ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.h | 122 - ANDROID_3.4.5/sound/soc/atmel/sam9g20_wm8731.c | 280 - ANDROID_3.4.5/sound/soc/atmel/snd-soc-afeb9260.c | 163 - ANDROID_3.4.5/sound/soc/au1x/Kconfig | 64 - ANDROID_3.4.5/sound/soc/au1x/Makefile | 23 - ANDROID_3.4.5/sound/soc/au1x/ac97c.c | 352 - ANDROID_3.4.5/sound/soc/au1x/db1000.c | 65 - ANDROID_3.4.5/sound/soc/au1x/db1200.c | 211 - ANDROID_3.4.5/sound/soc/au1x/dbdma2.c | 385 -- ANDROID_3.4.5/sound/soc/au1x/dma.c | 358 - ANDROID_3.4.5/sound/soc/au1x/i2sc.c | 319 - ANDROID_3.4.5/sound/soc/au1x/psc-ac97.c | 518 -- ANDROID_3.4.5/sound/soc/au1x/psc-i2s.c | 428 -- ANDROID_3.4.5/sound/soc/au1x/psc.h | 42 - ANDROID_3.4.5/sound/soc/blackfin/Kconfig | 181 - ANDROID_3.4.5/sound/soc/blackfin/Makefile | 35 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.c | 481 -- ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.h | 26 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.c | 382 -- ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.h | 59 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1836.c | 123 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad193x.c | 151 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1980.c | 112 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad73311.c | 213 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.c | 320 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.h | 26 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s.c | 297 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.c | 1094 --- ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.h | 174 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ssm2602.c | 156 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.c | 345 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.h | 18 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.c | 323 - ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.h | 23 - .../sound/soc/blackfin/bfin-eval-adau1373.c | 184 - .../sound/soc/blackfin/bfin-eval-adau1701.c | 124 - .../sound/soc/blackfin/bfin-eval-adav80x.c | 156 - ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.c | 1488 ----- ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.h | 97 - ANDROID_3.4.5/sound/soc/codecs/Kconfig | 455 -- ANDROID_3.4.5/sound/soc/codecs/Makefile | 219 - ANDROID_3.4.5/sound/soc/codecs/ac97.c | 156 - ANDROID_3.4.5/sound/soc/codecs/ad1836.c | 398 -- ANDROID_3.4.5/sound/soc/codecs/ad1836.h | 51 - ANDROID_3.4.5/sound/soc/codecs/ad193x.c | 538 -- ANDROID_3.4.5/sound/soc/codecs/ad193x.h | 85 - ANDROID_3.4.5/sound/soc/codecs/ad1980.c | 284 - ANDROID_3.4.5/sound/soc/codecs/ad1980.h | 26 - ANDROID_3.4.5/sound/soc/codecs/ad73311.c | 70 - ANDROID_3.4.5/sound/soc/codecs/ad73311.h | 88 - ANDROID_3.4.5/sound/soc/codecs/adau1373.c | 1409 ---- ANDROID_3.4.5/sound/soc/codecs/adau1373.h | 29 - ANDROID_3.4.5/sound/soc/codecs/adau1701.c | 546 -- ANDROID_3.4.5/sound/soc/codecs/adau1701.h | 17 - ANDROID_3.4.5/sound/soc/codecs/adav80x.c | 952 --- ANDROID_3.4.5/sound/soc/codecs/adav80x.h | 35 - ANDROID_3.4.5/sound/soc/codecs/ads117x.c | 65 - ANDROID_3.4.5/sound/soc/codecs/ak4104.c | 258 - ANDROID_3.4.5/sound/soc/codecs/ak4535.c | 497 -- ANDROID_3.4.5/sound/soc/codecs/ak4535.h | 37 - ANDROID_3.4.5/sound/soc/codecs/ak4641.c | 664 -- ANDROID_3.4.5/sound/soc/codecs/ak4641.h | 47 - ANDROID_3.4.5/sound/soc/codecs/ak4642.c | 590 -- ANDROID_3.4.5/sound/soc/codecs/ak4671.c | 713 -- ANDROID_3.4.5/sound/soc/codecs/ak4671.h | 153 - ANDROID_3.4.5/sound/soc/codecs/alc5623.c | 1109 --- ANDROID_3.4.5/sound/soc/codecs/alc5623.h | 161 - ANDROID_3.4.5/sound/soc/codecs/alc5632.c | 1234 ---- ANDROID_3.4.5/sound/soc/codecs/alc5632.h | 252 - ANDROID_3.4.5/sound/soc/codecs/cq93vc.c | 211 - ANDROID_3.4.5/sound/soc/codecs/cs4270.c | 740 -- ANDROID_3.4.5/sound/soc/codecs/cs4271.c | 664 -- ANDROID_3.4.5/sound/soc/codecs/cs42l51.c | 639 -- ANDROID_3.4.5/sound/soc/codecs/cs42l51.h | 161 - ANDROID_3.4.5/sound/soc/codecs/cs42l73.c | 1455 ---- ANDROID_3.4.5/sound/soc/codecs/cs42l73.h | 227 - ANDROID_3.4.5/sound/soc/codecs/cx20442.c | 443 -- ANDROID_3.4.5/sound/soc/codecs/cx20442.h | 18 - ANDROID_3.4.5/sound/soc/codecs/da7210.c | 1151 ---- ANDROID_3.4.5/sound/soc/codecs/dfbmcs320.c | 62 - ANDROID_3.4.5/sound/soc/codecs/dmic.c | 96 - ANDROID_3.4.5/sound/soc/codecs/jz4740.c | 431 -- ANDROID_3.4.5/sound/soc/codecs/l3.c | 91 - ANDROID_3.4.5/sound/soc/codecs/lm4857.c | 267 - ANDROID_3.4.5/sound/soc/codecs/max9768.c | 247 - ANDROID_3.4.5/sound/soc/codecs/max98088.c | 2130 ------ ANDROID_3.4.5/sound/soc/codecs/max98088.h | 206 - ANDROID_3.4.5/sound/soc/codecs/max98095.c | 2399 ------- ANDROID_3.4.5/sound/soc/codecs/max98095.h | 299 - ANDROID_3.4.5/sound/soc/codecs/max9850.c | 386 -- ANDROID_3.4.5/sound/soc/codecs/max9850.h | 38 - ANDROID_3.4.5/sound/soc/codecs/max9877.c | 308 - ANDROID_3.4.5/sound/soc/codecs/max9877.h | 37 - ANDROID_3.4.5/sound/soc/codecs/pcm3008.c | 179 - ANDROID_3.4.5/sound/soc/codecs/pcm3008.h | 22 - ANDROID_3.4.5/sound/soc/codecs/rt5631.c | 1769 ----- ANDROID_3.4.5/sound/soc/codecs/rt5631.h | 701 -- ANDROID_3.4.5/sound/soc/codecs/sgtl5000.c | 1468 ---- ANDROID_3.4.5/sound/soc/codecs/sgtl5000.h | 400 -- ANDROID_3.4.5/sound/soc/codecs/sigmadsp.c | 246 - ANDROID_3.4.5/sound/soc/codecs/sigmadsp.h | 21 - ANDROID_3.4.5/sound/soc/codecs/sn95031.c | 928 --- ANDROID_3.4.5/sound/soc/codecs/sn95031.h | 132 - ANDROID_3.4.5/sound/soc/codecs/spdif_transciever.c | 69 - ANDROID_3.4.5/sound/soc/codecs/ssm2602.c | 773 --- ANDROID_3.4.5/sound/soc/codecs/ssm2602.h | 125 - ANDROID_3.4.5/sound/soc/codecs/sta32x.c | 1024 --- ANDROID_3.4.5/sound/soc/codecs/sta32x.h | 211 - ANDROID_3.4.5/sound/soc/codecs/stac9766.c | 414 -- ANDROID_3.4.5/sound/soc/codecs/stac9766.h | 17 - ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.c | 696 -- ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.h | 119 - ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.c | 458 -- ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.h | 93 - ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.c | 770 --- ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.h | 143 - ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.c | 1505 ----- ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.h | 253 - ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.c | 1650 ----- ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.h | 264 - ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.c | 505 -- ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.h | 62 - ANDROID_3.4.5/sound/soc/codecs/twl4030.c | 2303 ------- ANDROID_3.4.5/sound/soc/codecs/twl6040.c | 1662 ----- ANDROID_3.4.5/sound/soc/codecs/twl6040.h | 44 - ANDROID_3.4.5/sound/soc/codecs/uda134x.c | 631 -- ANDROID_3.4.5/sound/soc/codecs/uda134x.h | 34 - ANDROID_3.4.5/sound/soc/codecs/uda1380.c | 864 --- ANDROID_3.4.5/sound/soc/codecs/uda1380.h | 79 - ANDROID_3.4.5/sound/soc/codecs/vt1603.c | 1249 ---- ANDROID_3.4.5/sound/soc/codecs/vt1603.h | 119 - ANDROID_3.4.5/sound/soc/codecs/wl1273.c | 517 -- ANDROID_3.4.5/sound/soc/codecs/wl1273.h | 30 - ANDROID_3.4.5/sound/soc/codecs/wm1250-ev1.c | 238 - ANDROID_3.4.5/sound/soc/codecs/wm2000.c | 862 --- ANDROID_3.4.5/sound/soc/codecs/wm2000.h | 69 - ANDROID_3.4.5/sound/soc/codecs/wm2200.c | 2287 ------- ANDROID_3.4.5/sound/soc/codecs/wm2200.h | 3674 ---------- ANDROID_3.4.5/sound/soc/codecs/wm5100-tables.c | 1364 ---- ANDROID_3.4.5/sound/soc/codecs/wm5100.c | 2766 -------- ANDROID_3.4.5/sound/soc/codecs/wm5100.h | 5156 -------------- ANDROID_3.4.5/sound/soc/codecs/wm8350.c | 1697 ----- ANDROID_3.4.5/sound/soc/codecs/wm8350.h | 29 - ANDROID_3.4.5/sound/soc/codecs/wm8400.c | 1469 ---- ANDROID_3.4.5/sound/soc/codecs/wm8400.h | 59 - ANDROID_3.4.5/sound/soc/codecs/wm8510.c | 706 -- ANDROID_3.4.5/sound/soc/codecs/wm8510.h | 102 - ANDROID_3.4.5/sound/soc/codecs/wm8523.c | 584 -- ANDROID_3.4.5/sound/soc/codecs/wm8523.h | 157 - ANDROID_3.4.5/sound/soc/codecs/wm8580.c | 966 --- ANDROID_3.4.5/sound/soc/codecs/wm8580.h | 35 - ANDROID_3.4.5/sound/soc/codecs/wm8711.c | 529 -- ANDROID_3.4.5/sound/soc/codecs/wm8711.h | 39 - ANDROID_3.4.5/sound/soc/codecs/wm8727.c | 74 - ANDROID_3.4.5/sound/soc/codecs/wm8728.c | 396 -- ANDROID_3.4.5/sound/soc/codecs/wm8728.h | 21 - ANDROID_3.4.5/sound/soc/codecs/wm8731.c | 787 --- ANDROID_3.4.5/sound/soc/codecs/wm8731.h | 39 - ANDROID_3.4.5/sound/soc/codecs/wm8737.c | 763 --- ANDROID_3.4.5/sound/soc/codecs/wm8737.h | 322 - ANDROID_3.4.5/sound/soc/codecs/wm8741.c | 606 -- ANDROID_3.4.5/sound/soc/codecs/wm8741.h | 211 - ANDROID_3.4.5/sound/soc/codecs/wm8750.c | 857 --- ANDROID_3.4.5/sound/soc/codecs/wm8750.h | 60 - ANDROID_3.4.5/sound/soc/codecs/wm8753.c | 1709 ----- ANDROID_3.4.5/sound/soc/codecs/wm8753.h | 118 - ANDROID_3.4.5/sound/soc/codecs/wm8770.c | 748 --- ANDROID_3.4.5/sound/soc/codecs/wm8770.h | 51 - ANDROID_3.4.5/sound/soc/codecs/wm8776.c | 572 -- ANDROID_3.4.5/sound/soc/codecs/wm8776.h | 48 - ANDROID_3.4.5/sound/soc/codecs/wm8782.c | 70 - ANDROID_3.4.5/sound/soc/codecs/wm8804.c | 841 --- ANDROID_3.4.5/sound/soc/codecs/wm8804.h | 61 - ANDROID_3.4.5/sound/soc/codecs/wm8900.c | 1340 ---- ANDROID_3.4.5/sound/soc/codecs/wm8900.h | 55 - ANDROID_3.4.5/sound/soc/codecs/wm8903.c | 2257 ------- ANDROID_3.4.5/sound/soc/codecs/wm8903.h | 1225 ---- ANDROID_3.4.5/sound/soc/codecs/wm8904.c | 2339 ------- ANDROID_3.4.5/sound/soc/codecs/wm8904.h | 1592 ----- ANDROID_3.4.5/sound/soc/codecs/wm8940.c | 809 --- ANDROID_3.4.5/sound/soc/codecs/wm8940.h | 102 - ANDROID_3.4.5/sound/soc/codecs/wm8955.c | 1094 --- ANDROID_3.4.5/sound/soc/codecs/wm8955.h | 486 -- ANDROID_3.4.5/sound/soc/codecs/wm8958-dsp2.c | 1054 --- ANDROID_3.4.5/sound/soc/codecs/wm8960.c | 1032 --- ANDROID_3.4.5/sound/soc/codecs/wm8960.h | 113 - ANDROID_3.4.5/sound/soc/codecs/wm8961.c | 1135 ---- ANDROID_3.4.5/sound/soc/codecs/wm8961.h | 863 --- ANDROID_3.4.5/sound/soc/codecs/wm8962.c | 3778 ----------- ANDROID_3.4.5/sound/soc/codecs/wm8962.h | 3780 ----------- ANDROID_3.4.5/sound/soc/codecs/wm8971.c | 745 --- ANDROID_3.4.5/sound/soc/codecs/wm8971.h | 56 - ANDROID_3.4.5/sound/soc/codecs/wm8974.c | 682 -- ANDROID_3.4.5/sound/soc/codecs/wm8974.h | 86 - ANDROID_3.4.5/sound/soc/codecs/wm8978.c | 1129 ---- ANDROID_3.4.5/sound/soc/codecs/wm8978.h | 85 - ANDROID_3.4.5/sound/soc/codecs/wm8983.c | 1199 ---- ANDROID_3.4.5/sound/soc/codecs/wm8983.h | 1029 --- ANDROID_3.4.5/sound/soc/codecs/wm8985.c | 1260 ---- ANDROID_3.4.5/sound/soc/codecs/wm8985.h | 1045 --- ANDROID_3.4.5/sound/soc/codecs/wm8988.c | 1010 --- ANDROID_3.4.5/sound/soc/codecs/wm8988.h | 57 - ANDROID_3.4.5/sound/soc/codecs/wm8990.c | 1453 ---- ANDROID_3.4.5/sound/soc/codecs/wm8990.h | 835 --- ANDROID_3.4.5/sound/soc/codecs/wm8991.c | 1423 ---- ANDROID_3.4.5/sound/soc/codecs/wm8991.h | 833 --- ANDROID_3.4.5/sound/soc/codecs/wm8993.c | 1866 ------ ANDROID_3.4.5/sound/soc/codecs/wm8993.h | 2138 ------ ANDROID_3.4.5/sound/soc/codecs/wm8994.c | 4391 ------------ ANDROID_3.4.5/sound/soc/codecs/wm8994.h | 155 - ANDROID_3.4.5/sound/soc/codecs/wm8995.c | 2415 ------- ANDROID_3.4.5/sound/soc/codecs/wm8995.h | 4269 ------------ ANDROID_3.4.5/sound/soc/codecs/wm8996.c | 3265 --------- ANDROID_3.4.5/sound/soc/codecs/wm8996.h | 3721 ----------- ANDROID_3.4.5/sound/soc/codecs/wm9081.c | 1425 ---- ANDROID_3.4.5/sound/soc/codecs/wm9081.h | 784 --- ANDROID_3.4.5/sound/soc/codecs/wm9090.c | 712 -- ANDROID_3.4.5/sound/soc/codecs/wm9090.h | 713 -- ANDROID_3.4.5/sound/soc/codecs/wm9705.c | 413 -- ANDROID_3.4.5/sound/soc/codecs/wm9705.h | 11 - ANDROID_3.4.5/sound/soc/codecs/wm9712.c | 700 -- ANDROID_3.4.5/sound/soc/codecs/wm9712.h | 11 - ANDROID_3.4.5/sound/soc/codecs/wm9713.c | 1283 ---- ANDROID_3.4.5/sound/soc/codecs/wm9713.h | 50 - ANDROID_3.4.5/sound/soc/codecs/wm_hubs.c | 1086 --- ANDROID_3.4.5/sound/soc/codecs/wm_hubs.h | 62 - ANDROID_3.4.5/sound/soc/codecs/wmt_fm34.c | 830 --- ANDROID_3.4.5/sound/soc/codecs/wmt_hwdac.c | 195 - ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.c | 981 --- ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.h | 67 - ANDROID_3.4.5/sound/soc/davinci/Kconfig | 85 - ANDROID_3.4.5/sound/soc/davinci/Makefile | 20 - ANDROID_3.4.5/sound/soc/davinci/davinci-evm.c | 339 - ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.c | 768 --- ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.h | 20 - ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c | 983 --- ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.h | 59 - ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.c | 892 --- ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.h | 31 - ANDROID_3.4.5/sound/soc/davinci/davinci-sffsdr.c | 181 - ANDROID_3.4.5/sound/soc/davinci/davinci-vcif.c | 266 - ANDROID_3.4.5/sound/soc/ep93xx/Kconfig | 42 - ANDROID_3.4.5/sound/soc/ep93xx/Makefile | 17 - ANDROID_3.4.5/sound/soc/ep93xx/edb93xx.c | 128 - ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-ac97.c | 457 -- ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-i2s.c | 472 -- ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.c | 242 - ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.h | 20 - ANDROID_3.4.5/sound/soc/ep93xx/simone.c | 90 - ANDROID_3.4.5/sound/soc/ep93xx/snappercl15.c | 146 - ANDROID_3.4.5/sound/soc/fsl/Kconfig | 67 - ANDROID_3.4.5/sound/soc/fsl/Makefile | 22 - ANDROID_3.4.5/sound/soc/fsl/efika-audio-fabric.c | 91 - ANDROID_3.4.5/sound/soc/fsl/fsl_dma.c | 999 --- ANDROID_3.4.5/sound/soc/fsl/fsl_dma.h | 129 - ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.c | 800 --- ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.h | 200 - ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.c | 534 -- ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.h | 84 - ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.c | 333 - ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.h | 13 - ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_i2s.c | 230 - ANDROID_3.4.5/sound/soc/fsl/mpc8610_hpcd.c | 595 -- ANDROID_3.4.5/sound/soc/fsl/p1022_ds.c | 601 -- ANDROID_3.4.5/sound/soc/fsl/pcm030-audio-fabric.c | 91 - ANDROID_3.4.5/sound/soc/imx/Kconfig | 79 - ANDROID_3.4.5/sound/soc/imx/Makefile | 22 - ANDROID_3.4.5/sound/soc/imx/eukrea-tlv320.c | 164 - ANDROID_3.4.5/sound/soc/imx/imx-audmux.c | 311 - ANDROID_3.4.5/sound/soc/imx/imx-audmux.h | 60 - ANDROID_3.4.5/sound/soc/imx/imx-pcm-dma-mx2.c | 175 - ANDROID_3.4.5/sound/soc/imx/imx-pcm-fiq.c | 336 - ANDROID_3.4.5/sound/soc/imx/imx-pcm.c | 105 - ANDROID_3.4.5/sound/soc/imx/imx-pcm.h | 32 - ANDROID_3.4.5/sound/soc/imx/imx-ssi.c | 690 -- ANDROID_3.4.5/sound/soc/imx/imx-ssi.h | 216 - ANDROID_3.4.5/sound/soc/imx/mx27vis-aic32x4.c | 245 - ANDROID_3.4.5/sound/soc/imx/phycore-ac97.c | 125 - ANDROID_3.4.5/sound/soc/imx/wm1133-ev1.c | 304 - ANDROID_3.4.5/sound/soc/jz4740/Kconfig | 23 - ANDROID_3.4.5/sound/soc/jz4740/Makefile | 13 - ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.c | 527 -- ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.h | 16 - ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.c | 362 - ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.h | 20 - ANDROID_3.4.5/sound/soc/jz4740/qi_lb60.c | 142 - ANDROID_3.4.5/sound/soc/kirkwood/Kconfig | 30 - ANDROID_3.4.5/sound/soc/kirkwood/Makefile | 11 - ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-dma.c | 398 -- ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-i2s.c | 491 -- ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-openrd.c | 111 - ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-t5325.c | 131 - ANDROID_3.4.5/sound/soc/kirkwood/kirkwood.h | 128 - ANDROID_3.4.5/sound/soc/mid-x86/Kconfig | 13 - ANDROID_3.4.5/sound/soc/mid-x86/Makefile | 5 - ANDROID_3.4.5/sound/soc/mid-x86/mfld_machine.c | 438 -- ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.c | 517 -- ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.h | 131 - ANDROID_3.4.5/sound/soc/mxs/Kconfig | 20 - ANDROID_3.4.5/sound/soc/mxs/Makefile | 10 - ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.c | 247 - ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.h | 27 - ANDROID_3.4.5/sound/soc/mxs/mxs-saif.c | 762 --- ANDROID_3.4.5/sound/soc/mxs/mxs-saif.h | 134 - ANDROID_3.4.5/sound/soc/mxs/mxs-sgtl5000.c | 165 - ANDROID_3.4.5/sound/soc/nuc900/Kconfig | 27 - ANDROID_3.4.5/sound/soc/nuc900/Makefile | 11 - ANDROID_3.4.5/sound/soc/nuc900/nuc900-ac97.c | 414 -- ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.c | 75 - ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.h | 115 - ANDROID_3.4.5/sound/soc/nuc900/nuc900-pcm.c | 365 - ANDROID_3.4.5/sound/soc/omap/Kconfig | 152 - ANDROID_3.4.5/sound/soc/omap/Makefile | 44 - ANDROID_3.4.5/sound/soc/omap/am3517evm.c | 161 - ANDROID_3.4.5/sound/soc/omap/ams-delta.c | 630 -- ANDROID_3.4.5/sound/soc/omap/igep0020.c | 120 - ANDROID_3.4.5/sound/soc/omap/mcbsp.c | 1040 --- ANDROID_3.4.5/sound/soc/omap/mcbsp.h | 346 - ANDROID_3.4.5/sound/soc/omap/n810.c | 384 -- ANDROID_3.4.5/sound/soc/omap/omap-abe-twl6040.c | 349 - ANDROID_3.4.5/sound/soc/omap/omap-dmic.c | 545 -- ANDROID_3.4.5/sound/soc/omap/omap-dmic.h | 69 - ANDROID_3.4.5/sound/soc/omap/omap-hdmi.c | 148 - ANDROID_3.4.5/sound/soc/omap/omap-hdmi.h | 36 - ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.c | 817 --- ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.h | 64 - ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.c | 524 -- ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.h | 107 - ANDROID_3.4.5/sound/soc/omap/omap-pcm.c | 443 -- ANDROID_3.4.5/sound/soc/omap/omap-pcm.h | 40 - ANDROID_3.4.5/sound/soc/omap/omap3beagle.c | 150 - ANDROID_3.4.5/sound/soc/omap/omap3evm.c | 118 - ANDROID_3.4.5/sound/soc/omap/omap3pandora.c | 325 - ANDROID_3.4.5/sound/soc/omap/omap4-hdmi-card.c | 121 - ANDROID_3.4.5/sound/soc/omap/osk5912.c | 189 - ANDROID_3.4.5/sound/soc/omap/overo.c | 122 - ANDROID_3.4.5/sound/soc/omap/rx51.c | 451 -- ANDROID_3.4.5/sound/soc/omap/sdp3430.c | 279 - ANDROID_3.4.5/sound/soc/omap/zoom2.c | 219 - ANDROID_3.4.5/sound/soc/pxa/Kconfig | 196 - ANDROID_3.4.5/sound/soc/pxa/Makefile | 49 - ANDROID_3.4.5/sound/soc/pxa/corgi.c | 343 - ANDROID_3.4.5/sound/soc/pxa/e740_wm9705.c | 192 - ANDROID_3.4.5/sound/soc/pxa/e750_wm9705.c | 174 - ANDROID_3.4.5/sound/soc/pxa/e800_wm9712.c | 164 - ANDROID_3.4.5/sound/soc/pxa/em-x270.c | 96 - ANDROID_3.4.5/sound/soc/pxa/hx4700.c | 234 - ANDROID_3.4.5/sound/soc/pxa/imote2.c | 104 - ANDROID_3.4.5/sound/soc/pxa/magician.c | 563 -- ANDROID_3.4.5/sound/soc/pxa/mioa701_wm9713.c | 236 - ANDROID_3.4.5/sound/soc/pxa/palm27x.c | 210 - ANDROID_3.4.5/sound/soc/pxa/poodle.c | 317 - ANDROID_3.4.5/sound/soc/pxa/pxa-ssp.c | 845 --- ANDROID_3.4.5/sound/soc/pxa/pxa-ssp.h | 45 - ANDROID_3.4.5/sound/soc/pxa/pxa2xx-ac97.c | 271 - ANDROID_3.4.5/sound/soc/pxa/pxa2xx-ac97.h | 20 - ANDROID_3.4.5/sound/soc/pxa/pxa2xx-i2s.c | 402 -- ANDROID_3.4.5/sound/soc/pxa/pxa2xx-i2s.h | 18 - ANDROID_3.4.5/sound/soc/pxa/pxa2xx-pcm.c | 148 - ANDROID_3.4.5/sound/soc/pxa/raumfeld.c | 339 - ANDROID_3.4.5/sound/soc/pxa/saarb.c | 190 - ANDROID_3.4.5/sound/soc/pxa/spitz.c | 363 - ANDROID_3.4.5/sound/soc/pxa/tavorevb3.c | 189 - ANDROID_3.4.5/sound/soc/pxa/tosa.c | 289 - ANDROID_3.4.5/sound/soc/pxa/z2.c | 231 - ANDROID_3.4.5/sound/soc/pxa/zylonite.c | 291 - ANDROID_3.4.5/sound/soc/s6000/Kconfig | 19 - ANDROID_3.4.5/sound/soc/s6000/Makefile | 11 - ANDROID_3.4.5/sound/soc/s6000/s6000-i2s.c | 611 -- ANDROID_3.4.5/sound/soc/s6000/s6000-i2s.h | 23 - ANDROID_3.4.5/sound/soc/s6000/s6000-pcm.c | 528 -- ANDROID_3.4.5/sound/soc/s6000/s6000-pcm.h | 33 - ANDROID_3.4.5/sound/soc/s6000/s6105-ipcam.c | 244 - ANDROID_3.4.5/sound/soc/samsung/Kconfig | 214 - ANDROID_3.4.5/sound/soc/samsung/Makefile | 67 - ANDROID_3.4.5/sound/soc/samsung/ac97.c | 517 -- ANDROID_3.4.5/sound/soc/samsung/dma.c | 465 -- ANDROID_3.4.5/sound/soc/samsung/dma.h | 24 - ANDROID_3.4.5/sound/soc/samsung/goni_wm8994.c | 302 - ANDROID_3.4.5/sound/soc/samsung/h1940_uda1380.c | 281 - ANDROID_3.4.5/sound/soc/samsung/i2s-regs.h | 143 - ANDROID_3.4.5/sound/soc/samsung/i2s.c | 1158 ---- ANDROID_3.4.5/sound/soc/samsung/i2s.h | 29 - ANDROID_3.4.5/sound/soc/samsung/idma.c | 444 -- ANDROID_3.4.5/sound/soc/samsung/idma.h | 26 - ANDROID_3.4.5/sound/soc/samsung/jive_wm8750.c | 174 - ANDROID_3.4.5/sound/soc/samsung/littlemill.c | 256 - ANDROID_3.4.5/sound/soc/samsung/ln2440sbc_alc650.c | 72 - ANDROID_3.4.5/sound/soc/samsung/lowland.c | 237 - ANDROID_3.4.5/sound/soc/samsung/neo1973_wm8753.c | 472 -- ANDROID_3.4.5/sound/soc/samsung/pcm.c | 645 -- ANDROID_3.4.5/sound/soc/samsung/pcm.h | 17 - ANDROID_3.4.5/sound/soc/samsung/regs-i2s-v2.h | 115 - ANDROID_3.4.5/sound/soc/samsung/rx1950_uda1380.c | 301 - ANDROID_3.4.5/sound/soc/samsung/s3c-i2s-v2.c | 757 --- ANDROID_3.4.5/sound/soc/samsung/s3c-i2s-v2.h | 106 - ANDROID_3.4.5/sound/soc/samsung/s3c2412-i2s.c | 193 - ANDROID_3.4.5/sound/soc/samsung/s3c2412-i2s.h | 27 - ANDROID_3.4.5/sound/soc/samsung/s3c24xx-i2s.c | 498 -- ANDROID_3.4.5/sound/soc/samsung/s3c24xx-i2s.h | 35 - ANDROID_3.4.5/sound/soc/samsung/s3c24xx_simtec.c | 388 -- ANDROID_3.4.5/sound/soc/samsung/s3c24xx_simtec.h | 22 - .../sound/soc/samsung/s3c24xx_simtec_hermes.c | 123 - .../sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c | 111 - ANDROID_3.4.5/sound/soc/samsung/s3c24xx_uda134x.c | 351 - ANDROID_3.4.5/sound/soc/samsung/smartq_wm8987.c | 275 - ANDROID_3.4.5/sound/soc/samsung/smdk2443_wm9710.c | 68 - ANDROID_3.4.5/sound/soc/samsung/smdk_spdif.c | 223 - ANDROID_3.4.5/sound/soc/samsung/smdk_wm8580.c | 258 - ANDROID_3.4.5/sound/soc/samsung/smdk_wm8580pcm.c | 196 - ANDROID_3.4.5/sound/soc/samsung/smdk_wm8994.c | 179 - ANDROID_3.4.5/sound/soc/samsung/smdk_wm8994pcm.c | 166 - ANDROID_3.4.5/sound/soc/samsung/smdk_wm9713.c | 108 - ANDROID_3.4.5/sound/soc/samsung/spdif.c | 491 -- ANDROID_3.4.5/sound/soc/samsung/spdif.h | 19 - ANDROID_3.4.5/sound/soc/samsung/speyside.c | 357 - ANDROID_3.4.5/sound/soc/samsung/tobermory.c | 258 - ANDROID_3.4.5/sound/soc/sh/Kconfig | 80 - ANDROID_3.4.5/sound/soc/sh/Makefile | 26 - ANDROID_3.4.5/sound/soc/sh/dma-sh7760.c | 376 -- ANDROID_3.4.5/sound/soc/sh/fsi-ak4642.c | 108 - ANDROID_3.4.5/sound/soc/sh/fsi-da7210.c | 81 - ANDROID_3.4.5/sound/soc/sh/fsi-hdmi.c | 118 - ANDROID_3.4.5/sound/soc/sh/fsi.c | 1771 ----- ANDROID_3.4.5/sound/soc/sh/hac.c | 339 - ANDROID_3.4.5/sound/soc/sh/migor.c | 225 - ANDROID_3.4.5/sound/soc/sh/sh7760-ac97.c | 73 - ANDROID_3.4.5/sound/soc/sh/siu.h | 194 - ANDROID_3.4.5/sound/soc/sh/siu_dai.c | 853 --- ANDROID_3.4.5/sound/soc/sh/siu_pcm.c | 617 -- ANDROID_3.4.5/sound/soc/sh/ssi.c | 408 -- ANDROID_3.4.5/sound/soc/soc-cache.c | 340 - ANDROID_3.4.5/sound/soc/soc-core.c | 3955 ----------- ANDROID_3.4.5/sound/soc/soc-dapm.c | 3288 --------- ANDROID_3.4.5/sound/soc/soc-dmaengine-pcm.c | 288 - ANDROID_3.4.5/sound/soc/soc-io.c | 170 - ANDROID_3.4.5/sound/soc/soc-jack.c | 385 -- ANDROID_3.4.5/sound/soc/soc-pcm.c | 707 -- ANDROID_3.4.5/sound/soc/soc-utils.c | 158 - ANDROID_3.4.5/sound/soc/tegra/Kconfig | 58 - ANDROID_3.4.5/sound/soc/tegra/Makefile | 21 - ANDROID_3.4.5/sound/soc/tegra/tegra_alc5632.c | 289 - ANDROID_3.4.5/sound/soc/tegra/tegra_asoc_utils.c | 157 - ANDROID_3.4.5/sound/soc/tegra/tegra_asoc_utils.h | 45 - ANDROID_3.4.5/sound/soc/tegra/tegra_das.c | 261 - ANDROID_3.4.5/sound/soc/tegra/tegra_das.h | 135 - ANDROID_3.4.5/sound/soc/tegra/tegra_i2s.c | 459 -- ANDROID_3.4.5/sound/soc/tegra/tegra_i2s.h | 166 - ANDROID_3.4.5/sound/soc/tegra/tegra_pcm.c | 399 -- ANDROID_3.4.5/sound/soc/tegra/tegra_pcm.h | 55 - ANDROID_3.4.5/sound/soc/tegra/tegra_spdif.c | 364 - ANDROID_3.4.5/sound/soc/tegra/tegra_spdif.h | 473 -- ANDROID_3.4.5/sound/soc/tegra/tegra_wm8903.c | 527 -- ANDROID_3.4.5/sound/soc/tegra/trimslice.c | 203 - ANDROID_3.4.5/sound/soc/txx9/Kconfig | 29 - ANDROID_3.4.5/sound/soc/txx9/Makefile | 11 - ANDROID_3.4.5/sound/soc/txx9/txx9aclc-ac97.c | 231 - ANDROID_3.4.5/sound/soc/txx9/txx9aclc-generic.c | 90 - ANDROID_3.4.5/sound/soc/txx9/txx9aclc.c | 445 -- ANDROID_3.4.5/sound/soc/txx9/txx9aclc.h | 74 - ANDROID_3.4.5/sound/soc/wmt/Kconfig | 65 - ANDROID_3.4.5/sound/soc/wmt/Makefile | 12 - ANDROID_3.4.5/sound/soc/wmt/wmt-i2s.c | 1105 --- ANDROID_3.4.5/sound/soc/wmt/wmt-pcm-controller.c | 419 -- ANDROID_3.4.5/sound/soc/wmt/wmt-pcm-controller.h | 122 - ANDROID_3.4.5/sound/soc/wmt/wmt-pcm-dma.c | 597 -- ANDROID_3.4.5/sound/soc/wmt/wmt-pcm-dma.h | 35 - ANDROID_3.4.5/sound/soc/wmt/wmt-pcm.c | 767 --- ANDROID_3.4.5/sound/soc/wmt/wmt-pcm.h | 46 - ANDROID_3.4.5/sound/soc/wmt/wmt-soc.c | 321 - ANDROID_3.4.5/sound/soc/wmt/wmt-soc.h | 53 - ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.c | 259 - ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.h | 55 - ANDROID_3.4.5/sound/soc/wmt/wmt_swmixer.c | 101 - ANDROID_3.4.5/sound/soc/wmt/wmt_swmixer.h | 33 - ANDROID_3.4.5/sound/soc/wmt/wmt_wm8994.c | 304 - ANDROID_3.4.5/sound/sound_core.c | 670 -- ANDROID_3.4.5/sound/sound_firmware.c | 78 - ANDROID_3.4.5/sound/sparc/Kconfig | 41 - ANDROID_3.4.5/sound/sparc/Makefile | 12 - ANDROID_3.4.5/sound/sparc/amd7930.c | 1099 --- ANDROID_3.4.5/sound/sparc/cs4231.c | 2121 ------ ANDROID_3.4.5/sound/sparc/dbri.c | 2700 -------- ANDROID_3.4.5/sound/spi/Kconfig | 38 - ANDROID_3.4.5/sound/spi/Makefile | 5 - ANDROID_3.4.5/sound/spi/at73c213.c | 1119 ---- ANDROID_3.4.5/sound/spi/at73c213.h | 119 - ANDROID_3.4.5/sound/synth/Makefile | 12 - ANDROID_3.4.5/sound/synth/emux/Makefile | 12 - ANDROID_3.4.5/sound/synth/emux/emux.c | 192 - ANDROID_3.4.5/sound/synth/emux/emux_effect.c | 310 - ANDROID_3.4.5/sound/synth/emux/emux_hwdep.c | 153 - ANDROID_3.4.5/sound/synth/emux/emux_nrpn.c | 396 -- ANDROID_3.4.5/sound/synth/emux/emux_oss.c | 517 -- ANDROID_3.4.5/sound/synth/emux/emux_proc.c | 132 - ANDROID_3.4.5/sound/synth/emux/emux_seq.c | 403 -- ANDROID_3.4.5/sound/synth/emux/emux_synth.c | 984 --- ANDROID_3.4.5/sound/synth/emux/emux_voice.h | 96 - ANDROID_3.4.5/sound/synth/emux/soundfont.c | 1496 ----- ANDROID_3.4.5/sound/synth/util_mem.c | 211 - ANDROID_3.4.5/sound/usb/6fire/Makefile | 3 - ANDROID_3.4.5/sound/usb/6fire/chip.c | 220 - ANDROID_3.4.5/sound/usb/6fire/chip.h | 31 - ANDROID_3.4.5/sound/usb/6fire/comm.c | 175 - ANDROID_3.4.5/sound/usb/6fire/comm.h | 43 - ANDROID_3.4.5/sound/usb/6fire/common.h | 29 - ANDROID_3.4.5/sound/usb/6fire/control.c | 631 -- ANDROID_3.4.5/sound/usb/6fire/control.h | 57 - ANDROID_3.4.5/sound/usb/6fire/firmware.c | 418 -- ANDROID_3.4.5/sound/usb/6fire/firmware.h | 27 - ANDROID_3.4.5/sound/usb/6fire/midi.c | 202 - ANDROID_3.4.5/sound/usb/6fire/midi.h | 45 - ANDROID_3.4.5/sound/usb/6fire/pcm.c | 666 -- ANDROID_3.4.5/sound/usb/6fire/pcm.h | 75 - ANDROID_3.4.5/sound/usb/Kconfig | 119 - ANDROID_3.4.5/sound/usb/Makefile | 26 - ANDROID_3.4.5/sound/usb/caiaq/Makefile | 4 - ANDROID_3.4.5/sound/usb/caiaq/audio.c | 889 --- ANDROID_3.4.5/sound/usb/caiaq/audio.h | 7 - ANDROID_3.4.5/sound/usb/caiaq/control.c | 559 -- ANDROID_3.4.5/sound/usb/caiaq/control.h | 6 - ANDROID_3.4.5/sound/usb/caiaq/device.c | 542 -- ANDROID_3.4.5/sound/usb/caiaq/device.h | 140 - ANDROID_3.4.5/sound/usb/caiaq/input.c | 842 --- ANDROID_3.4.5/sound/usb/caiaq/input.h | 8 - ANDROID_3.4.5/sound/usb/caiaq/midi.c | 174 - ANDROID_3.4.5/sound/usb/caiaq/midi.h | 8 - ANDROID_3.4.5/sound/usb/card.c | 729 -- ANDROID_3.4.5/sound/usb/card.h | 111 - ANDROID_3.4.5/sound/usb/clock.c | 318 - ANDROID_3.4.5/sound/usb/clock.h | 10 - ANDROID_3.4.5/sound/usb/debug.h | 15 - ANDROID_3.4.5/sound/usb/endpoint.c | 966 --- ANDROID_3.4.5/sound/usb/endpoint.h | 21 - ANDROID_3.4.5/sound/usb/format.c | 515 -- ANDROID_3.4.5/sound/usb/format.h | 9 - ANDROID_3.4.5/sound/usb/helper.c | 118 - ANDROID_3.4.5/sound/usb/helper.h | 36 - ANDROID_3.4.5/sound/usb/midi.c | 2237 ------- ANDROID_3.4.5/sound/usb/midi.h | 50 - ANDROID_3.4.5/sound/usb/misc/Makefile | 2 - ANDROID_3.4.5/sound/usb/misc/ua101.c | 1390 ---- ANDROID_3.4.5/sound/usb/mixer.c | 2283 ------- ANDROID_3.4.5/sound/usb/mixer.h | 71 - ANDROID_3.4.5/sound/usb/mixer_maps.c | 376 -- ANDROID_3.4.5/sound/usb/mixer_quirks.c | 654 -- ANDROID_3.4.5/sound/usb/mixer_quirks.h | 13 - ANDROID_3.4.5/sound/usb/pcm.c | 911 --- ANDROID_3.4.5/sound/usb/pcm.h | 14 - ANDROID_3.4.5/sound/usb/power.h | 17 - ANDROID_3.4.5/sound/usb/proc.c | 173 - ANDROID_3.4.5/sound/usb/proc.h | 8 - ANDROID_3.4.5/sound/usb/quirks-table.h | 2769 -------- ANDROID_3.4.5/sound/usb/quirks.c | 763 --- ANDROID_3.4.5/sound/usb/quirks.h | 23 - ANDROID_3.4.5/sound/usb/stream.c | 452 -- ANDROID_3.4.5/sound/usb/stream.h | 12 - ANDROID_3.4.5/sound/usb/usbaudio.h | 105 - ANDROID_3.4.5/sound/usb/usx2y/Makefile | 5 - ANDROID_3.4.5/sound/usb/usx2y/us122l.c | 775 --- ANDROID_3.4.5/sound/usb/usx2y/us122l.h | 31 - ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.c | 265 - ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.h | 6 - ANDROID_3.4.5/sound/usb/usx2y/usb_stream.c | 754 --- ANDROID_3.4.5/sound/usb/usx2y/usb_stream.h | 112 - ANDROID_3.4.5/sound/usb/usx2y/usbus428ctldefs.h | 104 - ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.c | 462 -- ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.h | 88 - ANDROID_3.4.5/sound/usb/usx2y/usbusx2yaudio.c | 1028 --- ANDROID_3.4.5/sound/usb/usx2y/usx2y.h | 51 - ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.c | 794 --- ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.h | 22 - 1361 files changed, 724495 deletions(-) delete mode 100644 ANDROID_3.4.5/sound/Kconfig delete mode 100644 ANDROID_3.4.5/sound/Makefile delete mode 100644 ANDROID_3.4.5/sound/ac97_bus.c delete mode 100644 ANDROID_3.4.5/sound/aoa/Kconfig delete mode 100644 ANDROID_3.4.5/sound/aoa/Makefile delete mode 100644 ANDROID_3.4.5/sound/aoa/aoa-gpio.h delete mode 100644 ANDROID_3.4.5/sound/aoa/aoa.h delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/Kconfig delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/Makefile delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/onyx.c delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/onyx.h delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/tas-basstreble.h delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/tas-gain-table.h delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/tas.c delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/tas.h delete mode 100644 ANDROID_3.4.5/sound/aoa/codecs/toonie.c delete mode 100644 ANDROID_3.4.5/sound/aoa/core/Makefile delete mode 100644 ANDROID_3.4.5/sound/aoa/core/alsa.c delete mode 100644 ANDROID_3.4.5/sound/aoa/core/alsa.h delete mode 100644 ANDROID_3.4.5/sound/aoa/core/core.c delete mode 100644 ANDROID_3.4.5/sound/aoa/core/gpio-feature.c delete mode 100644 ANDROID_3.4.5/sound/aoa/core/gpio-pmf.c delete mode 100644 ANDROID_3.4.5/sound/aoa/fabrics/Kconfig delete mode 100644 ANDROID_3.4.5/sound/aoa/fabrics/Makefile delete mode 100644 ANDROID_3.4.5/sound/aoa/fabrics/layout.c delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/Kconfig delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/Makefile delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/core.c delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/Makefile delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/control.c delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/core.c delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/i2sbus.h delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/interface.h delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/pcm.c delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/soundbus.h delete mode 100644 ANDROID_3.4.5/sound/aoa/soundbus/sysfs.c delete mode 100644 ANDROID_3.4.5/sound/arm/Kconfig delete mode 100644 ANDROID_3.4.5/sound/arm/Makefile delete mode 100644 ANDROID_3.4.5/sound/arm/aaci.c delete mode 100644 ANDROID_3.4.5/sound/arm/aaci.h delete mode 100644 ANDROID_3.4.5/sound/arm/pxa2xx-ac97-lib.c delete mode 100644 ANDROID_3.4.5/sound/arm/pxa2xx-ac97.c delete mode 100644 ANDROID_3.4.5/sound/arm/pxa2xx-pcm-lib.c delete mode 100644 ANDROID_3.4.5/sound/arm/pxa2xx-pcm.c delete mode 100644 ANDROID_3.4.5/sound/arm/pxa2xx-pcm.h delete mode 100644 ANDROID_3.4.5/sound/atmel/Kconfig delete mode 100644 ANDROID_3.4.5/sound/atmel/Makefile delete mode 100644 ANDROID_3.4.5/sound/atmel/abdac.c delete mode 100644 ANDROID_3.4.5/sound/atmel/ac97c.c delete mode 100644 ANDROID_3.4.5/sound/atmel/ac97c.h delete mode 100644 ANDROID_3.4.5/sound/core/Kconfig delete mode 100644 ANDROID_3.4.5/sound/core/Makefile delete mode 100644 ANDROID_3.4.5/sound/core/compress_offload.c delete mode 100644 ANDROID_3.4.5/sound/core/control.c delete mode 100644 ANDROID_3.4.5/sound/core/control_compat.c delete mode 100644 ANDROID_3.4.5/sound/core/ctljack.c delete mode 100644 ANDROID_3.4.5/sound/core/device.c delete mode 100644 ANDROID_3.4.5/sound/core/hrtimer.c delete mode 100644 ANDROID_3.4.5/sound/core/hwdep.c delete mode 100644 ANDROID_3.4.5/sound/core/hwdep_compat.c delete mode 100644 ANDROID_3.4.5/sound/core/info.c delete mode 100644 ANDROID_3.4.5/sound/core/info_oss.c delete mode 100644 ANDROID_3.4.5/sound/core/init.c delete mode 100644 ANDROID_3.4.5/sound/core/isadma.c delete mode 100644 ANDROID_3.4.5/sound/core/jack.c delete mode 100644 ANDROID_3.4.5/sound/core/memalloc.c delete mode 100644 ANDROID_3.4.5/sound/core/memory.c delete mode 100644 ANDROID_3.4.5/sound/core/misc.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/Makefile delete mode 100644 ANDROID_3.4.5/sound/core/oss/copy.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/io.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/linear.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/mixer_oss.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/mulaw.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/pcm_oss.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/pcm_plugin.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/pcm_plugin.h delete mode 100644 ANDROID_3.4.5/sound/core/oss/rate.c delete mode 100644 ANDROID_3.4.5/sound/core/oss/route.c delete mode 100644 ANDROID_3.4.5/sound/core/pcm.c delete mode 100644 ANDROID_3.4.5/sound/core/pcm_compat.c delete mode 100644 ANDROID_3.4.5/sound/core/pcm_lib.c delete mode 100644 ANDROID_3.4.5/sound/core/pcm_memory.c delete mode 100644 ANDROID_3.4.5/sound/core/pcm_misc.c delete mode 100644 ANDROID_3.4.5/sound/core/pcm_native.c delete mode 100644 ANDROID_3.4.5/sound/core/pcm_timer.c delete mode 100644 ANDROID_3.4.5/sound/core/rawmidi.c delete mode 100644 ANDROID_3.4.5/sound/core/rawmidi_compat.c delete mode 100644 ANDROID_3.4.5/sound/core/rtctimer.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/Kconfig delete mode 100644 ANDROID_3.4.5/sound/core/seq/Makefile delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/Makefile delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_compat.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_device.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_dummy.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_fifo.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_fifo.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_info.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_info.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_lock.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_lock.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_memory.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_memory.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_midi.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_midi_event.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_ports.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_ports.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_prioq.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_prioq.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_queue.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_queue.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_system.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_system.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_timer.c delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_timer.h delete mode 100644 ANDROID_3.4.5/sound/core/seq/seq_virmidi.c delete mode 100644 ANDROID_3.4.5/sound/core/sgbuf.c delete mode 100644 ANDROID_3.4.5/sound/core/sound.c delete mode 100644 ANDROID_3.4.5/sound/core/sound_oss.c delete mode 100644 ANDROID_3.4.5/sound/core/timer.c delete mode 100644 ANDROID_3.4.5/sound/core/timer_compat.c delete mode 100644 ANDROID_3.4.5/sound/core/vmaster.c delete mode 100644 ANDROID_3.4.5/sound/drivers/Kconfig delete mode 100644 ANDROID_3.4.5/sound/drivers/Makefile delete mode 100644 ANDROID_3.4.5/sound/drivers/aloop.c delete mode 100644 ANDROID_3.4.5/sound/drivers/dummy.c delete mode 100644 ANDROID_3.4.5/sound/drivers/ml403-ac97cr.c delete mode 100644 ANDROID_3.4.5/sound/drivers/mpu401/Makefile delete mode 100644 ANDROID_3.4.5/sound/drivers/mpu401/mpu401.c delete mode 100644 ANDROID_3.4.5/sound/drivers/mpu401/mpu401_uart.c delete mode 100644 ANDROID_3.4.5/sound/drivers/mtpav.c delete mode 100644 ANDROID_3.4.5/sound/drivers/mts64.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl3/Makefile delete mode 100644 ANDROID_3.4.5/sound/drivers/opl3/opl3_drums.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl3/opl3_lib.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl3/opl3_midi.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl3/opl3_oss.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl3/opl3_seq.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl3/opl3_synth.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl3/opl3_voice.h delete mode 100644 ANDROID_3.4.5/sound/drivers/opl4/Makefile delete mode 100644 ANDROID_3.4.5/sound/drivers/opl4/opl4_lib.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl4/opl4_local.h delete mode 100644 ANDROID_3.4.5/sound/drivers/opl4/opl4_mixer.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl4/opl4_proc.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl4/opl4_seq.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl4/opl4_synth.c delete mode 100644 ANDROID_3.4.5/sound/drivers/opl4/yrw801.c delete mode 100644 ANDROID_3.4.5/sound/drivers/pcm-indirect2.c delete mode 100644 ANDROID_3.4.5/sound/drivers/pcm-indirect2.h delete mode 100644 ANDROID_3.4.5/sound/drivers/pcsp/Makefile delete mode 100644 ANDROID_3.4.5/sound/drivers/pcsp/pcsp.c delete mode 100644 ANDROID_3.4.5/sound/drivers/pcsp/pcsp.h delete mode 100644 ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.c delete mode 100644 ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.h delete mode 100644 ANDROID_3.4.5/sound/drivers/pcsp/pcsp_lib.c delete mode 100644 ANDROID_3.4.5/sound/drivers/pcsp/pcsp_mixer.c delete mode 100644 ANDROID_3.4.5/sound/drivers/portman2x4.c delete mode 100644 ANDROID_3.4.5/sound/drivers/serial-u16550.c delete mode 100644 ANDROID_3.4.5/sound/drivers/virmidi.c delete mode 100644 ANDROID_3.4.5/sound/drivers/vx/Makefile delete mode 100644 ANDROID_3.4.5/sound/drivers/vx/vx_cmd.c delete mode 100644 ANDROID_3.4.5/sound/drivers/vx/vx_cmd.h delete mode 100644 ANDROID_3.4.5/sound/drivers/vx/vx_core.c delete mode 100644 ANDROID_3.4.5/sound/drivers/vx/vx_hwdep.c delete mode 100644 ANDROID_3.4.5/sound/drivers/vx/vx_mixer.c delete mode 100644 ANDROID_3.4.5/sound/drivers/vx/vx_pcm.c delete mode 100644 ANDROID_3.4.5/sound/drivers/vx/vx_uer.c delete mode 100644 ANDROID_3.4.5/sound/firewire/Kconfig delete mode 100644 ANDROID_3.4.5/sound/firewire/Makefile delete mode 100644 ANDROID_3.4.5/sound/firewire/amdtp.c delete mode 100644 ANDROID_3.4.5/sound/firewire/amdtp.h delete mode 100644 ANDROID_3.4.5/sound/firewire/cmp.c delete mode 100644 ANDROID_3.4.5/sound/firewire/cmp.h delete mode 100644 ANDROID_3.4.5/sound/firewire/fcp.c delete mode 100644 ANDROID_3.4.5/sound/firewire/fcp.h delete mode 100644 ANDROID_3.4.5/sound/firewire/isight.c delete mode 100644 ANDROID_3.4.5/sound/firewire/iso-resources.c delete mode 100644 ANDROID_3.4.5/sound/firewire/iso-resources.h delete mode 100644 ANDROID_3.4.5/sound/firewire/lib.c delete mode 100644 ANDROID_3.4.5/sound/firewire/lib.h delete mode 100644 ANDROID_3.4.5/sound/firewire/packets-buffer.c delete mode 100644 ANDROID_3.4.5/sound/firewire/packets-buffer.h delete mode 100644 ANDROID_3.4.5/sound/firewire/speakers.c delete mode 100644 ANDROID_3.4.5/sound/i2c/Makefile delete mode 100644 ANDROID_3.4.5/sound/i2c/cs8427.c delete mode 100644 ANDROID_3.4.5/sound/i2c/i2c.c delete mode 100644 ANDROID_3.4.5/sound/i2c/other/Makefile delete mode 100644 ANDROID_3.4.5/sound/i2c/other/ak4113.c delete mode 100644 ANDROID_3.4.5/sound/i2c/other/ak4114.c delete mode 100644 ANDROID_3.4.5/sound/i2c/other/ak4117.c delete mode 100644 ANDROID_3.4.5/sound/i2c/other/ak4xxx-adda.c delete mode 100644 ANDROID_3.4.5/sound/i2c/other/pt2258.c delete mode 100644 ANDROID_3.4.5/sound/i2c/other/tea575x-tuner.c delete mode 100644 ANDROID_3.4.5/sound/i2c/tea6330t.c delete mode 100644 ANDROID_3.4.5/sound/isa/Kconfig delete mode 100644 ANDROID_3.4.5/sound/isa/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/ad1816a/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/ad1816a/ad1816a.c delete mode 100644 ANDROID_3.4.5/sound/isa/ad1816a/ad1816a_lib.c delete mode 100644 ANDROID_3.4.5/sound/isa/ad1848/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/ad1848/ad1848.c delete mode 100644 ANDROID_3.4.5/sound/isa/adlib.c delete mode 100644 ANDROID_3.4.5/sound/isa/als100.c delete mode 100644 ANDROID_3.4.5/sound/isa/azt2320.c delete mode 100644 ANDROID_3.4.5/sound/isa/cmi8330.c delete mode 100644 ANDROID_3.4.5/sound/isa/cs423x/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/cs423x/cs4231.c delete mode 100644 ANDROID_3.4.5/sound/isa/cs423x/cs4236.c delete mode 100644 ANDROID_3.4.5/sound/isa/cs423x/cs4236_lib.c delete mode 100644 ANDROID_3.4.5/sound/isa/es1688/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/es1688/es1688.c delete mode 100644 ANDROID_3.4.5/sound/isa/es1688/es1688_lib.c delete mode 100644 ANDROID_3.4.5/sound/isa/es18xx.c delete mode 100644 ANDROID_3.4.5/sound/isa/galaxy/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/galaxy/azt1605.c delete mode 100644 ANDROID_3.4.5/sound/isa/galaxy/azt2316.c delete mode 100644 ANDROID_3.4.5/sound/isa/galaxy/galaxy.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_dma.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_dram.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_instr.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_io.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_irq.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_main.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_mem.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_mem_proc.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_mixer.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_pcm.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_reset.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_tables.h delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_timer.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_uart.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gus_volume.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gusclassic.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gusextreme.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/gusmax.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/interwave-stb.c delete mode 100644 ANDROID_3.4.5/sound/isa/gus/interwave.c delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/msnd.c delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/msnd.h delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/msnd_classic.c delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/msnd_classic.h delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/msnd_midi.c delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.c delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.h delete mode 100644 ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle_mixer.c delete mode 100644 ANDROID_3.4.5/sound/isa/opl3sa2.c delete mode 100644 ANDROID_3.4.5/sound/isa/opti9xx/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/opti9xx/miro.c delete mode 100644 ANDROID_3.4.5/sound/isa/opti9xx/opti92x-ad1848.c delete mode 100644 ANDROID_3.4.5/sound/isa/opti9xx/opti92x-cs4231.c delete mode 100644 ANDROID_3.4.5/sound/isa/opti9xx/opti93x.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/sb/emu8000.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/emu8000_callback.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/emu8000_local.h delete mode 100644 ANDROID_3.4.5/sound/isa/sb/emu8000_patch.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/emu8000_pcm.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/emu8000_synth.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/jazz16.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sb16.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sb16_csp.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sb16_main.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sb8.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sb8_main.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sb8_midi.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sb_common.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sb_mixer.c delete mode 100644 ANDROID_3.4.5/sound/isa/sb/sbawe.c delete mode 100644 ANDROID_3.4.5/sound/isa/sc6000.c delete mode 100644 ANDROID_3.4.5/sound/isa/sscape.c delete mode 100644 ANDROID_3.4.5/sound/isa/wavefront/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/wavefront/wavefront.c delete mode 100644 ANDROID_3.4.5/sound/isa/wavefront/wavefront_fx.c delete mode 100644 ANDROID_3.4.5/sound/isa/wavefront/wavefront_midi.c delete mode 100644 ANDROID_3.4.5/sound/isa/wavefront/wavefront_synth.c delete mode 100644 ANDROID_3.4.5/sound/isa/wss/Makefile delete mode 100644 ANDROID_3.4.5/sound/isa/wss/wss_lib.c delete mode 100644 ANDROID_3.4.5/sound/last.c delete mode 100644 ANDROID_3.4.5/sound/mips/Kconfig delete mode 100644 ANDROID_3.4.5/sound/mips/Makefile delete mode 100644 ANDROID_3.4.5/sound/mips/ad1843.c delete mode 100644 ANDROID_3.4.5/sound/mips/au1x00.c delete mode 100644 ANDROID_3.4.5/sound/mips/hal2.c delete mode 100644 ANDROID_3.4.5/sound/mips/hal2.h delete mode 100644 ANDROID_3.4.5/sound/mips/sgio2audio.c delete mode 100644 ANDROID_3.4.5/sound/oss/CHANGELOG delete mode 100644 ANDROID_3.4.5/sound/oss/Kconfig delete mode 100644 ANDROID_3.4.5/sound/oss/Makefile delete mode 100644 ANDROID_3.4.5/sound/oss/README.FIRST delete mode 100644 ANDROID_3.4.5/sound/oss/ad1848.c delete mode 100644 ANDROID_3.4.5/sound/oss/ad1848.h delete mode 100644 ANDROID_3.4.5/sound/oss/ad1848_mixer.h delete mode 100644 ANDROID_3.4.5/sound/oss/aedsp16.c delete mode 100644 ANDROID_3.4.5/sound/oss/audio.c delete mode 100644 ANDROID_3.4.5/sound/oss/bin2hex.c delete mode 100644 ANDROID_3.4.5/sound/oss/coproc.h delete mode 100644 ANDROID_3.4.5/sound/oss/dev_table.c delete mode 100644 ANDROID_3.4.5/sound/oss/dev_table.h delete mode 100644 ANDROID_3.4.5/sound/oss/dmabuf.c delete mode 100644 ANDROID_3.4.5/sound/oss/dmasound/Kconfig delete mode 100644 ANDROID_3.4.5/sound/oss/dmasound/Makefile delete mode 100644 ANDROID_3.4.5/sound/oss/dmasound/dmasound.h delete mode 100644 ANDROID_3.4.5/sound/oss/dmasound/dmasound_atari.c delete mode 100644 ANDROID_3.4.5/sound/oss/dmasound/dmasound_core.c delete mode 100644 ANDROID_3.4.5/sound/oss/dmasound/dmasound_paula.c delete mode 100644 ANDROID_3.4.5/sound/oss/dmasound/dmasound_q40.c delete mode 100644 ANDROID_3.4.5/sound/oss/hex2hex.c delete mode 100644 ANDROID_3.4.5/sound/oss/kahlua.c delete mode 100644 ANDROID_3.4.5/sound/oss/midi_ctrl.h delete mode 100644 ANDROID_3.4.5/sound/oss/midi_synth.c delete mode 100644 ANDROID_3.4.5/sound/oss/midi_synth.h delete mode 100644 ANDROID_3.4.5/sound/oss/midibuf.c delete mode 100644 ANDROID_3.4.5/sound/oss/mpu401.c delete mode 100644 ANDROID_3.4.5/sound/oss/mpu401.h delete mode 100644 ANDROID_3.4.5/sound/oss/msnd.c delete mode 100644 ANDROID_3.4.5/sound/oss/msnd.h delete mode 100644 ANDROID_3.4.5/sound/oss/msnd_classic.c delete mode 100644 ANDROID_3.4.5/sound/oss/msnd_classic.h delete mode 100644 ANDROID_3.4.5/sound/oss/msnd_pinnacle.c delete mode 100644 ANDROID_3.4.5/sound/oss/msnd_pinnacle.h delete mode 100644 ANDROID_3.4.5/sound/oss/opl3.c delete mode 100644 ANDROID_3.4.5/sound/oss/opl3_hw.h delete mode 100644 ANDROID_3.4.5/sound/oss/os.h delete mode 100644 ANDROID_3.4.5/sound/oss/pas2.h delete mode 100644 ANDROID_3.4.5/sound/oss/pas2_card.c delete mode 100644 ANDROID_3.4.5/sound/oss/pas2_midi.c delete mode 100644 ANDROID_3.4.5/sound/oss/pas2_mixer.c delete mode 100644 ANDROID_3.4.5/sound/oss/pas2_pcm.c delete mode 100644 ANDROID_3.4.5/sound/oss/pss.c delete mode 100644 ANDROID_3.4.5/sound/oss/sb.h delete mode 100644 ANDROID_3.4.5/sound/oss/sb_audio.c delete mode 100644 ANDROID_3.4.5/sound/oss/sb_card.c delete mode 100644 ANDROID_3.4.5/sound/oss/sb_card.h delete mode 100644 ANDROID_3.4.5/sound/oss/sb_common.c delete mode 100644 ANDROID_3.4.5/sound/oss/sb_ess.c delete mode 100644 ANDROID_3.4.5/sound/oss/sb_ess.h delete mode 100644 ANDROID_3.4.5/sound/oss/sb_midi.c delete mode 100644 ANDROID_3.4.5/sound/oss/sb_mixer.c delete mode 100644 ANDROID_3.4.5/sound/oss/sb_mixer.h delete mode 100644 ANDROID_3.4.5/sound/oss/sequencer.c delete mode 100644 ANDROID_3.4.5/sound/oss/sound_calls.h delete mode 100644 ANDROID_3.4.5/sound/oss/sound_config.h delete mode 100644 ANDROID_3.4.5/sound/oss/sound_firmware.h delete mode 100644 ANDROID_3.4.5/sound/oss/sound_timer.c delete mode 100644 ANDROID_3.4.5/sound/oss/soundcard.c delete mode 100644 ANDROID_3.4.5/sound/oss/soundvers.h delete mode 100644 ANDROID_3.4.5/sound/oss/swarm_cs4297a.c delete mode 100644 ANDROID_3.4.5/sound/oss/sys_timer.c delete mode 100644 ANDROID_3.4.5/sound/oss/trix.c delete mode 100644 ANDROID_3.4.5/sound/oss/tuning.h delete mode 100644 ANDROID_3.4.5/sound/oss/uart401.c delete mode 100644 ANDROID_3.4.5/sound/oss/uart6850.c delete mode 100644 ANDROID_3.4.5/sound/oss/ulaw.h delete mode 100644 ANDROID_3.4.5/sound/oss/v_midi.c delete mode 100644 ANDROID_3.4.5/sound/oss/v_midi.h delete mode 100644 ANDROID_3.4.5/sound/oss/vidc.c delete mode 100644 ANDROID_3.4.5/sound/oss/vidc.h delete mode 100644 ANDROID_3.4.5/sound/oss/vidc_fill.S delete mode 100644 ANDROID_3.4.5/sound/oss/vwsnd.c delete mode 100644 ANDROID_3.4.5/sound/oss/waveartist.c delete mode 100644 ANDROID_3.4.5/sound/oss/waveartist.h delete mode 100644 ANDROID_3.4.5/sound/parisc/Kconfig delete mode 100644 ANDROID_3.4.5/sound/parisc/Makefile delete mode 100644 ANDROID_3.4.5/sound/parisc/harmony.c delete mode 100644 ANDROID_3.4.5/sound/parisc/harmony.h delete mode 100644 ANDROID_3.4.5/sound/pci/Kconfig delete mode 100644 ANDROID_3.4.5/sound/pci/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/ac97/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/ac97/ac97_codec.c delete mode 100644 ANDROID_3.4.5/sound/pci/ac97/ac97_id.h delete mode 100644 ANDROID_3.4.5/sound/pci/ac97/ac97_local.h delete mode 100644 ANDROID_3.4.5/sound/pci/ac97/ac97_patch.c delete mode 100644 ANDROID_3.4.5/sound/pci/ac97/ac97_patch.h delete mode 100644 ANDROID_3.4.5/sound/pci/ac97/ac97_pcm.c delete mode 100644 ANDROID_3.4.5/sound/pci/ac97/ac97_proc.c delete mode 100644 ANDROID_3.4.5/sound/pci/ad1889.c delete mode 100644 ANDROID_3.4.5/sound/pci/ad1889.h delete mode 100644 ANDROID_3.4.5/sound/pci/ak4531_codec.c delete mode 100644 ANDROID_3.4.5/sound/pci/ali5451/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/ali5451/ali5451.c delete mode 100644 ANDROID_3.4.5/sound/pci/als300.c delete mode 100644 ANDROID_3.4.5/sound/pci/als4000.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/asihpi.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpi.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpi6000.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpi6000.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpi6205.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpi6205.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpi_internal.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpi_version.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpicmn.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpicmn.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpidebug.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpidebug.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpifunc.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpioctl.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpioctl.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpios.c delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpios.h delete mode 100644 ANDROID_3.4.5/sound/pci/asihpi/hpipcida.h delete mode 100644 ANDROID_3.4.5/sound/pci/atiixp.c delete mode 100644 ANDROID_3.4.5/sound/pci/atiixp_modem.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au8810.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au8810.h delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au8820.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au8820.h delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au8830.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au8830.h delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0.h delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.h delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3ddata.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_core.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.h delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_eqdata.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_game.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_mixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_mpu401.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_pcm.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_synth.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_wt.h delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.c delete mode 100644 ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.h delete mode 100644 ANDROID_3.4.5/sound/pci/aw2/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/aw2/aw2-alsa.c delete mode 100644 ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.c delete mode 100644 ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.h delete mode 100644 ANDROID_3.4.5/sound/pci/aw2/aw2-tsl.c delete mode 100644 ANDROID_3.4.5/sound/pci/aw2/saa7146.h delete mode 100644 ANDROID_3.4.5/sound/pci/azt3328.c delete mode 100644 ANDROID_3.4.5/sound/pci/azt3328.h delete mode 100644 ANDROID_3.4.5/sound/pci/bt87x.c delete mode 100644 ANDROID_3.4.5/sound/pci/ca0106/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/ca0106/ca0106.h delete mode 100644 ANDROID_3.4.5/sound/pci/ca0106/ca0106_main.c delete mode 100644 ANDROID_3.4.5/sound/pci/ca0106/ca0106_mixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/ca0106/ca0106_proc.c delete mode 100644 ANDROID_3.4.5/sound/pci/ca0106/ca_midi.c delete mode 100644 ANDROID_3.4.5/sound/pci/ca0106/ca_midi.h delete mode 100644 ANDROID_3.4.5/sound/pci/cmipci.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs4281.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/cs46xx.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_image.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos_scb_lib.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwc4630.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcasync.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcbinhack.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.asp delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcsnoop.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs5530.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs5535audio/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.h delete mode 100644 ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_olpc.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_pcm.c delete mode 100644 ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_pm.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ct20k1reg.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ct20k2reg.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctatc.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctatc.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/cthardware.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/cthardware.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctimap.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctimap.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctresource.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctresource.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/cttimer.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/cttimer.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.c delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.h delete mode 100644 ANDROID_3.4.5/sound/pci/ctxfi/xfi.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/darla20.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/darla20_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/darla24.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/darla24_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/echo3g.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/echo3g_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.h delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_3g.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.h delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_gml.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/gina20.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/gina20_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/gina24.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/gina24_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigo.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigo_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigo_express_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigodj.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigodj_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigodjx.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigodjx_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigoio.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigoio_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigoiox.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/indigoiox_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/layla20.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/layla20_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/layla24.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/layla24_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/mia.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/mia_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/midi.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/mona.c delete mode 100644 ANDROID_3.4.5/sound/pci/echoaudio/mona_dsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth_local.h delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emufx.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/io.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/irq.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/memory.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/p16v.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/p16v.h delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/p17v.h delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/timer.c delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/tina2.h delete mode 100644 ANDROID_3.4.5/sound/pci/emu10k1/voice.c delete mode 100644 ANDROID_3.4.5/sound/pci/ens1370.c delete mode 100644 ANDROID_3.4.5/sound/pci/ens1371.c delete mode 100644 ANDROID_3.4.5/sound/pci/es1938.c delete mode 100644 ANDROID_3.4.5/sound/pci/es1968.c delete mode 100644 ANDROID_3.4.5/sound/pci/fm801.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/Kconfig delete mode 100644 ANDROID_3.4.5/sound/pci/hda/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_beep.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_beep.h delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_codec.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_codec.h delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_eld.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_generic.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_hwdep.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_intel.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_jack.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_jack.h delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_local.h delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_proc.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/hda_trace.h delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_analog.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_ca0110.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_ca0132.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_cirrus.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_cmedia.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_conexant.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_hdmi.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_realtek.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_si3054.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_sigmatel.c delete mode 100644 ANDROID_3.4.5/sound/pci/hda/patch_via.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/ak4xxx.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/amp.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/amp.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/aureon.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/aureon.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/delta.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/delta.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/envy24ht.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/ews.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/ews.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/hoontech.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/hoontech.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/ice1712.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/ice1712.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/ice1724.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/juli.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/juli.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/maya44.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/maya44.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/phase.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/phase.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/pontis.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/pontis.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/prodigy192.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/prodigy192.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/quartet.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/quartet.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/revo.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/revo.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/se.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/se.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/stac946x.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.h delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/wtm.c delete mode 100644 ANDROID_3.4.5/sound/pci/ice1712/wtm.h delete mode 100644 ANDROID_3.4.5/sound/pci/intel8x0.c delete mode 100644 ANDROID_3.4.5/sound/pci/intel8x0m.c delete mode 100644 ANDROID_3.4.5/sound/pci/korg1212/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/korg1212/korg1212.c delete mode 100644 ANDROID_3.4.5/sound/pci/lola/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/lola/lola.c delete mode 100644 ANDROID_3.4.5/sound/pci/lola/lola.h delete mode 100644 ANDROID_3.4.5/sound/pci/lola/lola_clock.c delete mode 100644 ANDROID_3.4.5/sound/pci/lola/lola_mixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/lola/lola_pcm.c delete mode 100644 ANDROID_3.4.5/sound/pci/lola/lola_proc.c delete mode 100644 ANDROID_3.4.5/sound/pci/lx6464es/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.c delete mode 100644 ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.h delete mode 100644 ANDROID_3.4.5/sound/pci/lx6464es/lx_core.c delete mode 100644 ANDROID_3.4.5/sound/pci/lx6464es/lx_core.h delete mode 100644 ANDROID_3.4.5/sound/pci/lx6464es/lx_defs.h delete mode 100644 ANDROID_3.4.5/sound/pci/maestro3.c delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/mixart.c delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/mixart.h delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/mixart_core.c delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/mixart_core.h delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h delete mode 100644 ANDROID_3.4.5/sound/pci/nm256/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/nm256/nm256.c delete mode 100644 ANDROID_3.4.5/sound/pci/nm256/nm256_coef.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/ak4396.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/cm9780.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/cs2000.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/cs4245.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/cs4362a.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/cs4398.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/oxygen.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/oxygen.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/oxygen_io.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/oxygen_lib.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/oxygen_mixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/oxygen_pcm.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/oxygen_regs.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/pcm1796.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/virtuoso.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/wm8766.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/wm8776.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/wm8785.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/xonar.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/xonar_cs43xx.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.h delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/xonar_hdmi.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/xonar_lib.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/xonar_pcm179x.c delete mode 100644 ANDROID_3.4.5/sound/pci/oxygen/xonar_wm87x6.c delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.c delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.h delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.c delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.h delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.c delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.h delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.c delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.h delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.c delete mode 100644 ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.h delete mode 100644 ANDROID_3.4.5/sound/pci/riptide/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/riptide/riptide.c delete mode 100644 ANDROID_3.4.5/sound/pci/rme32.c delete mode 100644 ANDROID_3.4.5/sound/pci/rme96.c delete mode 100644 ANDROID_3.4.5/sound/pci/rme9652/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/rme9652/hdsp.c delete mode 100644 ANDROID_3.4.5/sound/pci/rme9652/hdspm.c delete mode 100644 ANDROID_3.4.5/sound/pci/rme9652/rme9652.c delete mode 100644 ANDROID_3.4.5/sound/pci/sis7019.c delete mode 100644 ANDROID_3.4.5/sound/pci/sis7019.h delete mode 100644 ANDROID_3.4.5/sound/pci/sonicvibes.c delete mode 100644 ANDROID_3.4.5/sound/pci/trident/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/trident/trident.c delete mode 100644 ANDROID_3.4.5/sound/pci/trident/trident_main.c delete mode 100644 ANDROID_3.4.5/sound/pci/trident/trident_memory.c delete mode 100644 ANDROID_3.4.5/sound/pci/via82xx.c delete mode 100644 ANDROID_3.4.5/sound/pci/via82xx_modem.c delete mode 100644 ANDROID_3.4.5/sound/pci/vx222/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/vx222/vx222.c delete mode 100644 ANDROID_3.4.5/sound/pci/vx222/vx222.h delete mode 100644 ANDROID_3.4.5/sound/pci/vx222/vx222_ops.c delete mode 100644 ANDROID_3.4.5/sound/pci/ymfpci/Makefile delete mode 100644 ANDROID_3.4.5/sound/pci/ymfpci/ymfpci.c delete mode 100644 ANDROID_3.4.5/sound/pci/ymfpci/ymfpci_main.c delete mode 100644 ANDROID_3.4.5/sound/pcmcia/Kconfig delete mode 100644 ANDROID_3.4.5/sound/pcmcia/Makefile delete mode 100644 ANDROID_3.4.5/sound/pcmcia/pdaudiocf/Makefile delete mode 100644 ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.c delete mode 100644 ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.h delete mode 100644 ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_core.c delete mode 100644 ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c delete mode 100644 ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c delete mode 100644 ANDROID_3.4.5/sound/pcmcia/vx/Makefile delete mode 100644 ANDROID_3.4.5/sound/pcmcia/vx/vxp_mixer.c delete mode 100644 ANDROID_3.4.5/sound/pcmcia/vx/vxp_ops.c delete mode 100644 ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.c delete mode 100644 ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.h delete mode 100644 ANDROID_3.4.5/sound/ppc/Kconfig delete mode 100644 ANDROID_3.4.5/sound/ppc/Makefile delete mode 100644 ANDROID_3.4.5/sound/ppc/awacs.c delete mode 100644 ANDROID_3.4.5/sound/ppc/awacs.h delete mode 100644 ANDROID_3.4.5/sound/ppc/beep.c delete mode 100644 ANDROID_3.4.5/sound/ppc/burgundy.c delete mode 100644 ANDROID_3.4.5/sound/ppc/burgundy.h delete mode 100644 ANDROID_3.4.5/sound/ppc/daca.c delete mode 100644 ANDROID_3.4.5/sound/ppc/keywest.c delete mode 100644 ANDROID_3.4.5/sound/ppc/pmac.c delete mode 100644 ANDROID_3.4.5/sound/ppc/pmac.h delete mode 100644 ANDROID_3.4.5/sound/ppc/powermac.c delete mode 100644 ANDROID_3.4.5/sound/ppc/snd_ps3.c delete mode 100644 ANDROID_3.4.5/sound/ppc/snd_ps3.h delete mode 100644 ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h delete mode 100644 ANDROID_3.4.5/sound/ppc/tumbler.c delete mode 100644 ANDROID_3.4.5/sound/ppc/tumbler_volume.h delete mode 100644 ANDROID_3.4.5/sound/sh/Kconfig delete mode 100644 ANDROID_3.4.5/sound/sh/Makefile delete mode 100644 ANDROID_3.4.5/sound/sh/aica.c delete mode 100644 ANDROID_3.4.5/sound/sh/aica.h delete mode 100644 ANDROID_3.4.5/sound/sh/sh_dac_audio.c delete mode 100644 ANDROID_3.4.5/sound/soc/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/atmel/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/atmel/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.c delete mode 100644 ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.h delete mode 100644 ANDROID_3.4.5/sound/soc/atmel/sam9g20_wm8731.c delete mode 100644 ANDROID_3.4.5/sound/soc/atmel/snd-soc-afeb9260.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/ac97c.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/db1000.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/db1200.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/dbdma2.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/dma.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/i2sc.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/psc-ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/psc-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/au1x/psc.h delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.h delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1836.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad193x.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1980.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad73311.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.h delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ssm2602.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.h delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adau1373.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adau1701.c delete mode 100644 ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adav80x.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ad1836.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ad1836.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ad193x.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ad193x.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ad1980.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ad1980.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ad73311.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ad73311.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/adau1373.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/adau1373.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/adau1701.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/adau1701.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/adav80x.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/adav80x.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ads117x.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ak4104.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ak4535.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ak4535.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ak4641.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ak4641.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ak4642.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ak4671.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ak4671.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/alc5623.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/alc5623.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/alc5632.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/alc5632.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cq93vc.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cs4270.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cs4271.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cs42l51.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cs42l51.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cs42l73.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cs42l73.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cx20442.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/cx20442.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/da7210.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/dfbmcs320.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/dmic.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/jz4740.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/l3.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/lm4857.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max9768.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max98088.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max98088.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max98095.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max98095.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max9850.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max9850.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max9877.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/max9877.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/pcm3008.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/pcm3008.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/rt5631.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/rt5631.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/sgtl5000.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/sgtl5000.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/sigmadsp.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/sigmadsp.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/sn95031.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/sn95031.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/spdif_transciever.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ssm2602.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/ssm2602.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/sta32x.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/sta32x.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/stac9766.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/stac9766.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/twl4030.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/twl6040.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/twl6040.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/uda134x.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/uda134x.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/uda1380.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/uda1380.h delete mode 100755 ANDROID_3.4.5/sound/soc/codecs/vt1603.c delete mode 100755 ANDROID_3.4.5/sound/soc/codecs/vt1603.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wl1273.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wl1273.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm1250-ev1.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm2000.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm2000.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm2200.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm2200.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm5100-tables.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm5100.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm5100.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8350.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8350.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8400.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8400.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8510.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8510.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8523.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8523.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8580.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8580.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8711.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8711.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8727.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8728.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8728.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8731.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8731.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8737.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8737.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8741.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8741.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8750.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8750.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8753.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8753.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8770.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8770.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8776.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8776.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8782.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8804.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8804.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8900.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8900.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8903.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8903.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8904.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8904.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8940.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8940.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8955.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8955.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8958-dsp2.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8960.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8960.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8961.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8961.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8962.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8962.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8971.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8971.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8974.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8974.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8978.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8978.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8983.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8983.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8985.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8985.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8988.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8988.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8990.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8990.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8991.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8991.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8993.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8993.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8994.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8994.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8995.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8995.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8996.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm8996.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9081.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9081.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9090.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9090.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9705.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9705.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9712.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9712.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9713.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm9713.h delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm_hubs.c delete mode 100644 ANDROID_3.4.5/sound/soc/codecs/wm_hubs.h delete mode 100755 ANDROID_3.4.5/sound/soc/codecs/wmt_fm34.c delete mode 100755 ANDROID_3.4.5/sound/soc/codecs/wmt_hwdac.c delete mode 100755 ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.c delete mode 100755 ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.h delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-evm.c delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.h delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.h delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-sffsdr.c delete mode 100644 ANDROID_3.4.5/sound/soc/davinci/davinci-vcif.c delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/edb93xx.c delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/simone.c delete mode 100644 ANDROID_3.4.5/sound/soc/ep93xx/snappercl15.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/efika-audio-fabric.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/fsl_dma.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/fsl_dma.h delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.h delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.h delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.h delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/mpc8610_hpcd.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/p1022_ds.c delete mode 100644 ANDROID_3.4.5/sound/soc/fsl/pcm030-audio-fabric.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/imx/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/imx/eukrea-tlv320.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/imx-audmux.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/imx-audmux.h delete mode 100644 ANDROID_3.4.5/sound/soc/imx/imx-pcm-dma-mx2.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/imx-pcm-fiq.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/imx-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/imx-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/imx/imx-ssi.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/imx-ssi.h delete mode 100644 ANDROID_3.4.5/sound/soc/imx/mx27vis-aic32x4.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/phycore-ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/imx/wm1133-ev1.c delete mode 100644 ANDROID_3.4.5/sound/soc/jz4740/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/jz4740/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.h delete mode 100644 ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/jz4740/qi_lb60.c delete mode 100644 ANDROID_3.4.5/sound/soc/kirkwood/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/kirkwood/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-dma.c delete mode 100644 ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-openrd.c delete mode 100644 ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-t5325.c delete mode 100644 ANDROID_3.4.5/sound/soc/kirkwood/kirkwood.h delete mode 100644 ANDROID_3.4.5/sound/soc/mid-x86/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/mid-x86/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/mid-x86/mfld_machine.c delete mode 100644 ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.c delete mode 100644 ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.h delete mode 100644 ANDROID_3.4.5/sound/soc/mxs/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/mxs/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/mxs/mxs-saif.c delete mode 100644 ANDROID_3.4.5/sound/soc/mxs/mxs-saif.h delete mode 100644 ANDROID_3.4.5/sound/soc/mxs/mxs-sgtl5000.c delete mode 100644 ANDROID_3.4.5/sound/soc/nuc900/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/nuc900/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/nuc900/nuc900-ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.c delete mode 100644 ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.h delete mode 100644 ANDROID_3.4.5/sound/soc/nuc900/nuc900-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/omap/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/omap/am3517evm.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/ams-delta.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/igep0020.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/mcbsp.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/mcbsp.h delete mode 100644 ANDROID_3.4.5/sound/soc/omap/n810.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-abe-twl6040.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-dmic.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-dmic.h delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-hdmi.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-hdmi.h delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.h delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.h delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap3beagle.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap3evm.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap3pandora.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/omap4-hdmi-card.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/osk5912.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/overo.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/rx51.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/sdp3430.c delete mode 100644 ANDROID_3.4.5/sound/soc/omap/zoom2.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/corgi.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/e740_wm9705.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/e750_wm9705.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/e800_wm9712.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/em-x270.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/hx4700.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/imote2.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/magician.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/mioa701_wm9713.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/palm27x.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/poodle.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/pxa-ssp.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/pxa-ssp.h delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/pxa2xx-ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/pxa2xx-ac97.h delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/pxa2xx-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/pxa2xx-i2s.h delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/pxa2xx-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/raumfeld.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/saarb.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/spitz.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/tavorevb3.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/tosa.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/z2.c delete mode 100644 ANDROID_3.4.5/sound/soc/pxa/zylonite.c delete mode 100644 ANDROID_3.4.5/sound/soc/s6000/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/s6000/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/s6000/s6000-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/s6000/s6000-i2s.h delete mode 100644 ANDROID_3.4.5/sound/soc/s6000/s6000-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/s6000/s6000-pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/s6000/s6105-ipcam.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/dma.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/dma.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/goni_wm8994.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/h1940_uda1380.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/i2s-regs.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/i2s.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/idma.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/idma.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/jive_wm8750.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/littlemill.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/ln2440sbc_alc650.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/lowland.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/neo1973_wm8753.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/regs-i2s-v2.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/rx1950_uda1380.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c-i2s-v2.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c-i2s-v2.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c2412-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c2412-i2s.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c24xx-i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c24xx-i2s.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c24xx_simtec.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c24xx_simtec.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c24xx_simtec_hermes.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/s3c24xx_uda134x.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/smartq_wm8987.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/smdk2443_wm9710.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/smdk_spdif.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/smdk_wm8580.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/smdk_wm8580pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/smdk_wm8994.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/smdk_wm8994pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/smdk_wm9713.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/spdif.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/spdif.h delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/speyside.c delete mode 100644 ANDROID_3.4.5/sound/soc/samsung/tobermory.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/sh/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/sh/dma-sh7760.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/fsi-ak4642.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/fsi-da7210.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/fsi-hdmi.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/fsi.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/hac.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/migor.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/sh7760-ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/siu.h delete mode 100644 ANDROID_3.4.5/sound/soc/sh/siu_dai.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/siu_pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/sh/ssi.c delete mode 100644 ANDROID_3.4.5/sound/soc/soc-cache.c delete mode 100644 ANDROID_3.4.5/sound/soc/soc-core.c delete mode 100644 ANDROID_3.4.5/sound/soc/soc-dapm.c delete mode 100644 ANDROID_3.4.5/sound/soc/soc-dmaengine-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/soc-io.c delete mode 100644 ANDROID_3.4.5/sound/soc/soc-jack.c delete mode 100644 ANDROID_3.4.5/sound/soc/soc-pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/soc-utils.c delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_alc5632.c delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_asoc_utils.c delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_asoc_utils.h delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_das.c delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_das.h delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_i2s.c delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_i2s.h delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_pcm.c delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_pcm.h delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_spdif.c delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_spdif.h delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/tegra_wm8903.c delete mode 100644 ANDROID_3.4.5/sound/soc/tegra/trimslice.c delete mode 100644 ANDROID_3.4.5/sound/soc/txx9/Kconfig delete mode 100644 ANDROID_3.4.5/sound/soc/txx9/Makefile delete mode 100644 ANDROID_3.4.5/sound/soc/txx9/txx9aclc-ac97.c delete mode 100644 ANDROID_3.4.5/sound/soc/txx9/txx9aclc-generic.c delete mode 100644 ANDROID_3.4.5/sound/soc/txx9/txx9aclc.c delete mode 100644 ANDROID_3.4.5/sound/soc/txx9/txx9aclc.h delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/Kconfig delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/Makefile delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-i2s.c delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-pcm-controller.c delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-pcm-controller.h delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-pcm-dma.c delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-pcm-dma.h delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-pcm.c delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-pcm.h delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-soc.c delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt-soc.h delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.c delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt_hwdep.h delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt_swmixer.c delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt_swmixer.h delete mode 100755 ANDROID_3.4.5/sound/soc/wmt/wmt_wm8994.c delete mode 100644 ANDROID_3.4.5/sound/sound_core.c delete mode 100644 ANDROID_3.4.5/sound/sound_firmware.c delete mode 100644 ANDROID_3.4.5/sound/sparc/Kconfig delete mode 100644 ANDROID_3.4.5/sound/sparc/Makefile delete mode 100644 ANDROID_3.4.5/sound/sparc/amd7930.c delete mode 100644 ANDROID_3.4.5/sound/sparc/cs4231.c delete mode 100644 ANDROID_3.4.5/sound/sparc/dbri.c delete mode 100644 ANDROID_3.4.5/sound/spi/Kconfig delete mode 100644 ANDROID_3.4.5/sound/spi/Makefile delete mode 100644 ANDROID_3.4.5/sound/spi/at73c213.c delete mode 100644 ANDROID_3.4.5/sound/spi/at73c213.h delete mode 100644 ANDROID_3.4.5/sound/synth/Makefile delete mode 100644 ANDROID_3.4.5/sound/synth/emux/Makefile delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux.c delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux_effect.c delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux_hwdep.c delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux_nrpn.c delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux_oss.c delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux_proc.c delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux_seq.c delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux_synth.c delete mode 100644 ANDROID_3.4.5/sound/synth/emux/emux_voice.h delete mode 100644 ANDROID_3.4.5/sound/synth/emux/soundfont.c delete mode 100644 ANDROID_3.4.5/sound/synth/util_mem.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/chip.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/chip.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/comm.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/comm.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/common.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/control.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/control.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/firmware.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/firmware.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/midi.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/midi.h delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/pcm.c delete mode 100644 ANDROID_3.4.5/sound/usb/6fire/pcm.h delete mode 100644 ANDROID_3.4.5/sound/usb/Kconfig delete mode 100644 ANDROID_3.4.5/sound/usb/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/audio.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/audio.h delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/control.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/control.h delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/device.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/device.h delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/input.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/input.h delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/midi.c delete mode 100644 ANDROID_3.4.5/sound/usb/caiaq/midi.h delete mode 100644 ANDROID_3.4.5/sound/usb/card.c delete mode 100644 ANDROID_3.4.5/sound/usb/card.h delete mode 100644 ANDROID_3.4.5/sound/usb/clock.c delete mode 100644 ANDROID_3.4.5/sound/usb/clock.h delete mode 100644 ANDROID_3.4.5/sound/usb/debug.h delete mode 100644 ANDROID_3.4.5/sound/usb/endpoint.c delete mode 100644 ANDROID_3.4.5/sound/usb/endpoint.h delete mode 100644 ANDROID_3.4.5/sound/usb/format.c delete mode 100644 ANDROID_3.4.5/sound/usb/format.h delete mode 100644 ANDROID_3.4.5/sound/usb/helper.c delete mode 100644 ANDROID_3.4.5/sound/usb/helper.h delete mode 100644 ANDROID_3.4.5/sound/usb/midi.c delete mode 100644 ANDROID_3.4.5/sound/usb/midi.h delete mode 100644 ANDROID_3.4.5/sound/usb/misc/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/misc/ua101.c delete mode 100644 ANDROID_3.4.5/sound/usb/mixer.c delete mode 100644 ANDROID_3.4.5/sound/usb/mixer.h delete mode 100644 ANDROID_3.4.5/sound/usb/mixer_maps.c delete mode 100644 ANDROID_3.4.5/sound/usb/mixer_quirks.c delete mode 100644 ANDROID_3.4.5/sound/usb/mixer_quirks.h delete mode 100644 ANDROID_3.4.5/sound/usb/pcm.c delete mode 100644 ANDROID_3.4.5/sound/usb/pcm.h delete mode 100644 ANDROID_3.4.5/sound/usb/power.h delete mode 100644 ANDROID_3.4.5/sound/usb/proc.c delete mode 100644 ANDROID_3.4.5/sound/usb/proc.h delete mode 100644 ANDROID_3.4.5/sound/usb/quirks-table.h delete mode 100644 ANDROID_3.4.5/sound/usb/quirks.c delete mode 100644 ANDROID_3.4.5/sound/usb/quirks.h delete mode 100644 ANDROID_3.4.5/sound/usb/stream.c delete mode 100644 ANDROID_3.4.5/sound/usb/stream.h delete mode 100644 ANDROID_3.4.5/sound/usb/usbaudio.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/Makefile delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/us122l.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/us122l.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usX2Yhwdep.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usb_stream.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usb_stream.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usbus428ctldefs.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usbusx2y.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usbusx2yaudio.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usx2y.h delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.c delete mode 100644 ANDROID_3.4.5/sound/usb/usx2y/usx2yhwdeppcm.h (limited to 'ANDROID_3.4.5/sound') diff --git a/ANDROID_3.4.5/sound/Kconfig b/ANDROID_3.4.5/sound/Kconfig deleted file mode 100644 index 261a03c8..00000000 --- a/ANDROID_3.4.5/sound/Kconfig +++ /dev/null @@ -1,137 +0,0 @@ -menuconfig SOUND - tristate "Sound card support" - depends on HAS_IOMEM - help - If you have a sound card in your computer, i.e. if it can say more - than an occasional beep, say Y. Be sure to have all the information - about your sound card and its configuration down (I/O port, - interrupt and DMA channel), because you will be asked for it. - - You want to read the Sound-HOWTO, available from - . General information about - the modular sound system is contained in the files - . The file - contains some slightly - outdated but still useful information as well. Newer sound - driver documentation is found in . - - If you have a PnP sound card and you want to configure it at boot - time using the ISA PnP tools (read - ), then you need to - compile the sound card support as a module and load that module - after the PnP configuration is finished. To do this, choose M here - and read ; the module - will be called soundcore. - -if SOUND - -config SOUND_OSS_CORE - bool - default n - -config SOUND_OSS_CORE_PRECLAIM - bool "Preclaim OSS device numbers" - depends on SOUND_OSS_CORE - default y - help - With this option enabled, the kernel will claim all OSS device - numbers if any OSS support (native or emulation) is enabled - whether the respective module is loaded or not and try to load the - appropriate module using sound-slot/service-* and char-major-* - module aliases when one of the device numbers is opened. With - this option disabled, kernel will only claim actually in-use - device numbers and opening a missing device will generate only the - standard char-major-* aliases. - - The only visible difference is use of additional module aliases - and whether OSS sound devices appear multiple times in - /proc/devices. sound-slot/service-* module aliases are scheduled - to be removed (ie. PRECLAIM won't be available) and this option is - to make the transition easier. This option can be overridden - during boot using the kernel parameter soundcore.preclaim_oss. - - Disabling this allows alternative OSS implementations. - - Please read Documentation/feature-removal-schedule.txt for - details. - - If unsure, say Y. - -source "sound/oss/dmasound/Kconfig" - -if !M68K && !UML - -menuconfig SND - tristate "Advanced Linux Sound Architecture" - help - Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture), - the new base sound system. - - For more information, see - -if SND - -source "sound/core/Kconfig" - -source "sound/drivers/Kconfig" - -source "sound/isa/Kconfig" - -source "sound/pci/Kconfig" - -source "sound/ppc/Kconfig" - -source "sound/aoa/Kconfig" - -source "sound/arm/Kconfig" - -source "sound/atmel/Kconfig" - -source "sound/spi/Kconfig" - -source "sound/mips/Kconfig" - -source "sound/sh/Kconfig" - -# the following will depend on the order of config. -# here assuming USB is defined before ALSA -source "sound/usb/Kconfig" - -source "sound/firewire/Kconfig" - -# the following will depend on the order of config. -# here assuming PCMCIA is defined before ALSA -source "sound/pcmcia/Kconfig" - -source "sound/sparc/Kconfig" - -source "sound/parisc/Kconfig" - -source "sound/soc/Kconfig" - -endif # SND - -menuconfig SOUND_PRIME - tristate "Open Sound System (DEPRECATED)" - select SOUND_OSS_CORE - help - Say 'Y' or 'M' to enable Open Sound System drivers. - -if SOUND_PRIME - -source "sound/oss/Kconfig" - -endif # SOUND_PRIME - -endif # !M68K - -endif # SOUND - -# AC97_BUS is used from both sound and ucb1400 -config AC97_BUS - tristate - help - This is used to avoid config and link hard dependencies between the - sound subsystem and other function drivers completely unrelated to - sound although they're sharing the AC97 bus. Concerned drivers - should "select" this. diff --git a/ANDROID_3.4.5/sound/Makefile b/ANDROID_3.4.5/sound/Makefile deleted file mode 100644 index 987b7d2b..00000000 --- a/ANDROID_3.4.5/sound/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# Makefile for the Linux sound card driver -# - -obj-$(CONFIG_SOUND) += soundcore.o -obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o -obj-$(CONFIG_SOUND_PRIME) += oss/ -obj-$(CONFIG_DMASOUND) += oss/ -obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ \ - firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ usb/ -obj-$(CONFIG_SND_AOA) += aoa/ - -# This one must be compilable even if sound is configured out -obj-$(CONFIG_AC97_BUS) += ac97_bus.o - -ifeq ($(CONFIG_SND),y) - obj-y += last.o -endif - -soundcore-objs := sound_core.o diff --git a/ANDROID_3.4.5/sound/ac97_bus.c b/ANDROID_3.4.5/sound/ac97_bus.c deleted file mode 100644 index 2b50cbe6..00000000 --- a/ANDROID_3.4.5/sound/ac97_bus.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Linux driver model AC97 bus interface - * - * Author: Nicolas Pitre - * Created: Jan 14, 2005 - * Copyright: (C) MontaVista Software Inc. - * - * 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. - */ - -#include -#include -#include -#include -#include - -/* - * Let drivers decide whether they want to support given codec from their - * probe method. Drivers have direct access to the struct snd_ac97 - * structure and may decide based on the id field amongst other things. - */ -static int ac97_bus_match(struct device *dev, struct device_driver *drv) -{ - return 1; -} - -#ifdef CONFIG_PM -static int ac97_bus_suspend(struct device *dev, pm_message_t state) -{ - int ret = 0; - - if (dev->driver && dev->driver->suspend) - ret = dev->driver->suspend(dev, state); - - return ret; -} - -static int ac97_bus_resume(struct device *dev) -{ - int ret = 0; - - if (dev->driver && dev->driver->resume) - ret = dev->driver->resume(dev); - - return ret; -} -#endif /* CONFIG_PM */ - -struct bus_type ac97_bus_type = { - .name = "ac97", - .match = ac97_bus_match, -#ifdef CONFIG_PM - .suspend = ac97_bus_suspend, - .resume = ac97_bus_resume, -#endif /* CONFIG_PM */ -}; - -static int __init ac97_bus_init(void) -{ - return bus_register(&ac97_bus_type); -} - -subsys_initcall(ac97_bus_init); - -static void __exit ac97_bus_exit(void) -{ - bus_unregister(&ac97_bus_type); -} - -module_exit(ac97_bus_exit); - -EXPORT_SYMBOL(ac97_bus_type); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/aoa/Kconfig b/ANDROID_3.4.5/sound/aoa/Kconfig deleted file mode 100644 index c081e18b..00000000 --- a/ANDROID_3.4.5/sound/aoa/Kconfig +++ /dev/null @@ -1,17 +0,0 @@ -menuconfig SND_AOA - tristate "Apple Onboard Audio driver" - depends on PPC_PMAC - select SND_PCM - ---help--- - This option enables the new driver for the various - Apple Onboard Audio components. - -if SND_AOA - -source "sound/aoa/fabrics/Kconfig" - -source "sound/aoa/codecs/Kconfig" - -source "sound/aoa/soundbus/Kconfig" - -endif # SND_AOA diff --git a/ANDROID_3.4.5/sound/aoa/Makefile b/ANDROID_3.4.5/sound/aoa/Makefile deleted file mode 100644 index a8c037f9..00000000 --- a/ANDROID_3.4.5/sound/aoa/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_SND_AOA) += core/ -obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/ -obj-$(CONFIG_SND_AOA) += fabrics/ -obj-$(CONFIG_SND_AOA) += codecs/ diff --git a/ANDROID_3.4.5/sound/aoa/aoa-gpio.h b/ANDROID_3.4.5/sound/aoa/aoa-gpio.h deleted file mode 100644 index 6065b034..00000000 --- a/ANDROID_3.4.5/sound/aoa/aoa-gpio.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Apple Onboard Audio GPIO definitions - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ - -#ifndef __AOA_GPIO_H -#define __AOA_GPIO_H -#include -#include -#include - -typedef void (*notify_func_t)(void *data); - -enum notify_type { - AOA_NOTIFY_HEADPHONE, - AOA_NOTIFY_LINE_IN, - AOA_NOTIFY_LINE_OUT, -}; - -struct gpio_runtime; -struct gpio_methods { - /* for initialisation/de-initialisation of the GPIO layer */ - void (*init)(struct gpio_runtime *rt); - void (*exit)(struct gpio_runtime *rt); - - /* turn off headphone, speakers, lineout */ - void (*all_amps_off)(struct gpio_runtime *rt); - /* turn headphone, speakers, lineout back to previous setting */ - void (*all_amps_restore)(struct gpio_runtime *rt); - - void (*set_headphone)(struct gpio_runtime *rt, int on); - void (*set_speakers)(struct gpio_runtime *rt, int on); - void (*set_lineout)(struct gpio_runtime *rt, int on); - void (*set_master)(struct gpio_runtime *rt, int on); - - int (*get_headphone)(struct gpio_runtime *rt); - int (*get_speakers)(struct gpio_runtime *rt); - int (*get_lineout)(struct gpio_runtime *rt); - int (*get_master)(struct gpio_runtime *rt); - - void (*set_hw_reset)(struct gpio_runtime *rt, int on); - - /* use this to be notified of any events. The notification - * function is passed the data, and is called in process - * context by the use of schedule_work. - * The interface for it is that setting a function to NULL - * removes it, and they return 0 if the operation succeeded, - * and -EBUSY if the notification is already assigned by - * someone else. */ - int (*set_notify)(struct gpio_runtime *rt, - enum notify_type type, - notify_func_t notify, - void *data); - /* returns 0 if not plugged in, 1 if plugged in - * or a negative error code */ - int (*get_detect)(struct gpio_runtime *rt, - enum notify_type type); -}; - -struct gpio_notification { - struct delayed_work work; - notify_func_t notify; - void *data; - void *gpio_private; - struct mutex mutex; -}; - -struct gpio_runtime { - /* to be assigned by fabric */ - struct device_node *node; - /* since everyone needs this pointer anyway... */ - struct gpio_methods *methods; - /* to be used by the gpio implementation */ - int implementation_private; - struct gpio_notification headphone_notify; - struct gpio_notification line_in_notify; - struct gpio_notification line_out_notify; -}; - -#endif /* __AOA_GPIO_H */ diff --git a/ANDROID_3.4.5/sound/aoa/aoa.h b/ANDROID_3.4.5/sound/aoa/aoa.h deleted file mode 100644 index e0878948..00000000 --- a/ANDROID_3.4.5/sound/aoa/aoa.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Apple Onboard Audio definitions - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ - -#ifndef __AOA_H -#define __AOA_H -#include -#include -#include -#include -#include -#include "aoa-gpio.h" -#include "soundbus/soundbus.h" - -#define MAX_CODEC_NAME_LEN 32 - -struct aoa_codec { - char name[MAX_CODEC_NAME_LEN]; - - struct module *owner; - - /* called when the fabric wants to init this codec. - * Do alsa card manipulations from here. */ - int (*init)(struct aoa_codec *codec); - - /* called when the fabric is done with the codec. - * The alsa card will be cleaned up so don't bother. */ - void (*exit)(struct aoa_codec *codec); - - /* May be NULL, but can be used by the fabric. - * Refcounting is the codec driver's responsibility */ - struct device_node *node; - - /* assigned by fabric before init() is called, points - * to the soundbus device. Cannot be NULL. */ - struct soundbus_dev *soundbus_dev; - - /* assigned by the fabric before init() is called, points - * to the fabric's gpio runtime record for the relevant - * device. */ - struct gpio_runtime *gpio; - - /* assigned by the fabric before init() is called, contains - * a codec specific bitmask of what outputs and inputs are - * actually connected */ - u32 connected; - - /* data the fabric can associate with this structure */ - void *fabric_data; - - /* private! */ - struct list_head list; - struct aoa_fabric *fabric; -}; - -/* return 0 on success */ -extern int -aoa_codec_register(struct aoa_codec *codec); -extern void -aoa_codec_unregister(struct aoa_codec *codec); - -#define MAX_LAYOUT_NAME_LEN 32 - -struct aoa_fabric { - char name[MAX_LAYOUT_NAME_LEN]; - - struct module *owner; - - /* once codecs register, they are passed here after. - * They are of course not initialised, since the - * fabric is responsible for initialising some fields - * in the codec structure! */ - int (*found_codec)(struct aoa_codec *codec); - /* called for each codec when it is removed, - * also in the case that aoa_fabric_unregister - * is called and all codecs are removed - * from this fabric. - * Also called if found_codec returned 0 but - * the codec couldn't initialise. */ - void (*remove_codec)(struct aoa_codec *codec); - /* If found_codec returned 0, and the codec - * could be initialised, this is called. */ - void (*attached_codec)(struct aoa_codec *codec); -}; - -/* return 0 on success, -EEXIST if another fabric is - * registered, -EALREADY if the same fabric is registered. - * Passing NULL can be used to test for the presence - * of another fabric, if -EALREADY is returned there is - * no other fabric present. - * In the case that the function returns -EALREADY - * and the fabric passed is not NULL, all codecs - * that are not assigned yet are passed to the fabric - * again for reconsideration. */ -extern int -aoa_fabric_register(struct aoa_fabric *fabric, struct device *dev); - -/* it is vital to call this when the fabric exits! - * When calling, the remove_codec will be called - * for all codecs, unless it is NULL. */ -extern void -aoa_fabric_unregister(struct aoa_fabric *fabric); - -/* if for some reason you want to get rid of a codec - * before the fabric is removed, use this. - * Note that remove_codec is called for it! */ -extern void -aoa_fabric_unlink_codec(struct aoa_codec *codec); - -/* alsa help methods */ -struct aoa_card { - struct snd_card *alsa_card; -}; - -extern int aoa_snd_device_new(snd_device_type_t type, - void * device_data, struct snd_device_ops * ops); -extern struct snd_card *aoa_get_card(void); -extern int aoa_snd_ctl_add(struct snd_kcontrol* control); - -/* GPIO stuff */ -extern struct gpio_methods *pmf_gpio_methods; -extern struct gpio_methods *ftr_gpio_methods; -/* extern struct gpio_methods *map_gpio_methods; */ - -#endif /* __AOA_H */ diff --git a/ANDROID_3.4.5/sound/aoa/codecs/Kconfig b/ANDROID_3.4.5/sound/aoa/codecs/Kconfig deleted file mode 100644 index 0c68e328..00000000 --- a/ANDROID_3.4.5/sound/aoa/codecs/Kconfig +++ /dev/null @@ -1,24 +0,0 @@ -config SND_AOA_ONYX - tristate "support Onyx chip" - select I2C - select I2C_POWERMAC - ---help--- - This option enables support for the Onyx (pcm3052) - codec chip found in the latest Apple machines - (most of those with digital audio output). - -config SND_AOA_TAS - tristate "support TAS chips" - select I2C - select I2C_POWERMAC - ---help--- - This option enables support for the tas chips - found in a lot of Apple Machines, especially - iBooks and PowerBooks without digital. - -config SND_AOA_TOONIE - tristate "support Toonie chip" - ---help--- - This option enables support for the toonie codec - found in the Mac Mini. If you have a Mac Mini and - want to hear sound, select this option. diff --git a/ANDROID_3.4.5/sound/aoa/codecs/Makefile b/ANDROID_3.4.5/sound/aoa/codecs/Makefile deleted file mode 100644 index c3ee77fc..00000000 --- a/ANDROID_3.4.5/sound/aoa/codecs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -snd-aoa-codec-onyx-objs := onyx.o -snd-aoa-codec-tas-objs := tas.o -snd-aoa-codec-toonie-objs := toonie.o - -obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o -obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o -obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o diff --git a/ANDROID_3.4.5/sound/aoa/codecs/onyx.c b/ANDROID_3.4.5/sound/aoa/codecs/onyx.c deleted file mode 100644 index 270790d3..00000000 --- a/ANDROID_3.4.5/sound/aoa/codecs/onyx.c +++ /dev/null @@ -1,1135 +0,0 @@ -/* - * Apple Onboard Audio driver for Onyx codec - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - * - * - * This is a driver for the pcm3052 codec chip (codenamed Onyx) - * that is present in newer Apple hardware (with digital output). - * - * The Onyx codec has the following connections (listed by the bit - * to be used in aoa_codec.connected): - * 0: analog output - * 1: digital output - * 2: line input - * 3: microphone input - * Note that even though I know of no machine that has for example - * the digital output connected but not the analog, I have handled - * all the different cases in the code so that this driver may serve - * as a good example of what to do. - * - * NOTE: This driver assumes that there's at most one chip to be - * used with one alsa card, in form of creating all kinds - * of mixer elements without regard for their existence. - * But snd-aoa assumes that there's at most one card, so - * this means you can only have one onyx on a system. This - * should probably be fixed by changing the assumption of - * having just a single card on a system, and making the - * 'card' pointer accessible to anyone who needs it instead - * of hiding it in the aoa_snd_* functions... - * - */ -#include -#include -#include -MODULE_AUTHOR("Johannes Berg "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa"); - -#include "onyx.h" -#include "../aoa.h" -#include "../soundbus/soundbus.h" - - -#define PFX "snd-aoa-codec-onyx: " - -struct onyx { - /* cache registers 65 to 80, they are write-only! */ - u8 cache[16]; - struct i2c_client *i2c; - struct aoa_codec codec; - u32 initialised:1, - spdif_locked:1, - analog_locked:1, - original_mute:2; - int open_count; - struct codec_info *codec_info; - - /* mutex serializes concurrent access to the device - * and this structure. - */ - struct mutex mutex; -}; -#define codec_to_onyx(c) container_of(c, struct onyx, codec) - -/* both return 0 if all ok, else on error */ -static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value) -{ - s32 v; - - if (reg != ONYX_REG_CONTROL) { - *value = onyx->cache[reg-FIRSTREGISTER]; - return 0; - } - v = i2c_smbus_read_byte_data(onyx->i2c, reg); - if (v < 0) - return -1; - *value = (u8)v; - onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; - return 0; -} - -static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value) -{ - int result; - - result = i2c_smbus_write_byte_data(onyx->i2c, reg, value); - if (!result) - onyx->cache[reg-FIRSTREGISTER] = value; - return result; -} - -/* alsa stuff */ - -static int onyx_dev_register(struct snd_device *dev) -{ - return 0; -} - -static struct snd_device_ops ops = { - .dev_register = onyx_dev_register, -}; - -/* this is necessary because most alsa mixer programs - * can't properly handle the negative range */ -#define VOLUME_RANGE_SHIFT 128 - -static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT; - uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT; - return 0; -} - -static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - s8 l, r; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); - onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); - mutex_unlock(&onyx->mutex); - - ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT; - ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT; - - return 0; -} - -static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - s8 l, r; - - if (ucontrol->value.integer.value[0] < -128 + VOLUME_RANGE_SHIFT || - ucontrol->value.integer.value[0] > -1 + VOLUME_RANGE_SHIFT) - return -EINVAL; - if (ucontrol->value.integer.value[1] < -128 + VOLUME_RANGE_SHIFT || - ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT) - return -EINVAL; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); - onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); - - if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] && - r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) { - mutex_unlock(&onyx->mutex); - return 0; - } - - onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, - ucontrol->value.integer.value[0] - - VOLUME_RANGE_SHIFT); - onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, - ucontrol->value.integer.value[1] - - VOLUME_RANGE_SHIFT); - mutex_unlock(&onyx->mutex); - - return 1; -} - -static struct snd_kcontrol_new volume_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = onyx_snd_vol_info, - .get = onyx_snd_vol_get, - .put = onyx_snd_vol_put, -}; - -/* like above, this is necessary because a lot - * of alsa mixer programs don't handle ranges - * that don't start at 0 properly. - * even alsamixer is one of them... */ -#define INPUTGAIN_RANGE_SHIFT (-3) - -static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT; - uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT; - return 0; -} - -static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - u8 ig; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig); - mutex_unlock(&onyx->mutex); - - ucontrol->value.integer.value[0] = - (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT; - - return 0; -} - -static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - u8 v, n; - - if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT || - ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT) - return -EINVAL; - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); - n = v; - n &= ~ONYX_ADC_PGA_GAIN_MASK; - n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT) - & ONYX_ADC_PGA_GAIN_MASK; - onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n); - mutex_unlock(&onyx->mutex); - - return n != v; -} - -static struct snd_kcontrol_new inputgain_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Capture Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = onyx_snd_inputgain_info, - .get = onyx_snd_inputgain_get, - .put = onyx_snd_inputgain_put, -}; - -static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "Line-In", "Microphone" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - s8 v; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); - mutex_unlock(&onyx->mutex); - - ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC); - - return 0; -} - -static void onyx_set_capture_source(struct onyx *onyx, int mic) -{ - s8 v; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); - v &= ~ONYX_ADC_INPUT_MIC; - if (mic) - v |= ONYX_ADC_INPUT_MIC; - onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v); - mutex_unlock(&onyx->mutex); -} - -static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - if (ucontrol->value.enumerated.item[0] > 1) - return -EINVAL; - onyx_set_capture_source(snd_kcontrol_chip(kcontrol), - ucontrol->value.enumerated.item[0]); - return 1; -} - -static struct snd_kcontrol_new capture_source_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* If we name this 'Input Source', it properly shows up in - * alsamixer as a selection, * but it's shown under the - * 'Playback' category. - * If I name it 'Capture Source', it shows up in strange - * ways (two bools of which one can be selected at a - * time) but at least it's shown in the 'Capture' - * category. - * I was told that this was due to backward compatibility, - * but I don't understand then why the mangling is *not* - * done when I name it "Input Source"..... - */ - .name = "Capture Source", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = onyx_snd_capture_source_info, - .get = onyx_snd_capture_source_get, - .put = onyx_snd_capture_source_put, -}; - -#define onyx_snd_mute_info snd_ctl_boolean_stereo_info - -static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - u8 c; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c); - mutex_unlock(&onyx->mutex); - - ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT); - ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT); - - return 0; -} - -static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - u8 v = 0, c = 0; - int err = -EBUSY; - - mutex_lock(&onyx->mutex); - if (onyx->analog_locked) - goto out_unlock; - - onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); - c = v; - c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT); - if (!ucontrol->value.integer.value[0]) - c |= ONYX_MUTE_LEFT; - if (!ucontrol->value.integer.value[1]) - c |= ONYX_MUTE_RIGHT; - err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c); - - out_unlock: - mutex_unlock(&onyx->mutex); - - return !err ? (v != c) : err; -} - -static struct snd_kcontrol_new mute_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = onyx_snd_mute_info, - .get = onyx_snd_mute_get, - .put = onyx_snd_mute_put, -}; - - -#define onyx_snd_single_bit_info snd_ctl_boolean_mono_info - -#define FLAG_POLARITY_INVERT 1 -#define FLAG_SPDIFLOCK 2 - -static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - u8 c; - long int pv = kcontrol->private_value; - u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT; - u8 address = (pv >> 8) & 0xff; - u8 mask = pv & 0xff; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, address, &c); - mutex_unlock(&onyx->mutex); - - ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity; - - return 0; -} - -static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - u8 v = 0, c = 0; - int err; - long int pv = kcontrol->private_value; - u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT; - u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK; - u8 address = (pv >> 8) & 0xff; - u8 mask = pv & 0xff; - - mutex_lock(&onyx->mutex); - if (spdiflock && onyx->spdif_locked) { - /* even if alsamixer doesn't care.. */ - err = -EBUSY; - goto out_unlock; - } - onyx_read_register(onyx, address, &v); - c = v; - c &= ~(mask); - if (!!ucontrol->value.integer.value[0] ^ polarity) - c |= mask; - err = onyx_write_register(onyx, address, c); - - out_unlock: - mutex_unlock(&onyx->mutex); - - return !err ? (v != c) : err; -} - -#define SINGLE_BIT(n, type, description, address, mask, flags) \ -static struct snd_kcontrol_new n##_control = { \ - .iface = SNDRV_CTL_ELEM_IFACE_##type, \ - .name = description, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = onyx_snd_single_bit_info, \ - .get = onyx_snd_single_bit_get, \ - .put = onyx_snd_single_bit_put, \ - .private_value = (flags << 16) | (address << 8) | mask \ -} - -SINGLE_BIT(spdif, - MIXER, - SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), - ONYX_REG_DIG_INFO4, - ONYX_SPDIF_ENABLE, - FLAG_SPDIFLOCK); -SINGLE_BIT(ovr1, - MIXER, - "Oversampling Rate", - ONYX_REG_DAC_CONTROL, - ONYX_OVR1, - 0); -SINGLE_BIT(flt0, - MIXER, - "Fast Digital Filter Rolloff", - ONYX_REG_DAC_FILTER, - ONYX_ROLLOFF_FAST, - FLAG_POLARITY_INVERT); -SINGLE_BIT(hpf, - MIXER, - "Highpass Filter", - ONYX_REG_ADC_HPF_BYPASS, - ONYX_HPF_DISABLE, - FLAG_POLARITY_INVERT); -SINGLE_BIT(dm12, - MIXER, - "Digital De-Emphasis", - ONYX_REG_DAC_DEEMPH, - ONYX_DIGDEEMPH_CTRL, - 0); - -static int onyx_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - /* datasheet page 30, all others are 0 */ - ucontrol->value.iec958.status[0] = 0x3e; - ucontrol->value.iec958.status[1] = 0xff; - - ucontrol->value.iec958.status[3] = 0x3f; - ucontrol->value.iec958.status[4] = 0x0f; - - return 0; -} - -static struct snd_kcontrol_new onyx_spdif_mask = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), - .info = onyx_spdif_info, - .get = onyx_spdif_mask_get, -}; - -static int onyx_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - u8 v; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); - ucontrol->value.iec958.status[0] = v & 0x3e; - - onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v); - ucontrol->value.iec958.status[1] = v; - - onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); - ucontrol->value.iec958.status[3] = v & 0x3f; - - onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); - ucontrol->value.iec958.status[4] = v & 0x0f; - mutex_unlock(&onyx->mutex); - - return 0; -} - -static int onyx_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct onyx *onyx = snd_kcontrol_chip(kcontrol); - u8 v; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); - v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e); - onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v); - - v = ucontrol->value.iec958.status[1]; - onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v); - - onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); - v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f); - onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v); - - onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); - v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f); - onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); - mutex_unlock(&onyx->mutex); - - return 1; -} - -static struct snd_kcontrol_new onyx_spdif_ctrl = { - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = onyx_spdif_info, - .get = onyx_spdif_get, - .put = onyx_spdif_put, -}; - -/* our registers */ - -static u8 register_map[] = { - ONYX_REG_DAC_ATTEN_LEFT, - ONYX_REG_DAC_ATTEN_RIGHT, - ONYX_REG_CONTROL, - ONYX_REG_DAC_CONTROL, - ONYX_REG_DAC_DEEMPH, - ONYX_REG_DAC_FILTER, - ONYX_REG_DAC_OUTPHASE, - ONYX_REG_ADC_CONTROL, - ONYX_REG_ADC_HPF_BYPASS, - ONYX_REG_DIG_INFO1, - ONYX_REG_DIG_INFO2, - ONYX_REG_DIG_INFO3, - ONYX_REG_DIG_INFO4 -}; - -static u8 initial_values[ARRAY_SIZE(register_map)] = { - 0x80, 0x80, /* muted */ - ONYX_MRST | ONYX_SRST, /* but handled specially! */ - ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT, - 0, /* no deemphasis */ - ONYX_DAC_FILTER_ALWAYS, - ONYX_OUTPHASE_INVERTED, - (-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/ - ONYX_ADC_HPF_ALWAYS, - (1<<2), /* pcm audio */ - 2, /* category: pcm coder */ - 0, /* sampling frequency 44.1 kHz, clock accuracy level II */ - 1 /* 24 bit depth */ -}; - -/* reset registers of chip, either to initial or to previous values */ -static int onyx_register_init(struct onyx *onyx) -{ - int i; - u8 val; - u8 regs[sizeof(initial_values)]; - - if (!onyx->initialised) { - memcpy(regs, initial_values, sizeof(initial_values)); - if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val)) - return -1; - val &= ~ONYX_SILICONVERSION; - val |= initial_values[3]; - regs[3] = val; - } else { - for (i=0; icache[register_map[i]-FIRSTREGISTER]; - } - - for (i=0; iinitialised = 1; - return 0; -} - -static struct transfer_info onyx_transfers[] = { - /* this is first so we can skip it if no input is present... - * No hardware exists with that, but it's here as an example - * of what to do :) */ - { - /* analog input */ - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_BE, - .rates = SNDRV_PCM_RATE_8000_96000, - .transfer_in = 1, - .must_be_clock_source = 0, - .tag = 0, - }, - { - /* if analog and digital are currently off, anything should go, - * so this entry describes everything we can do... */ - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_BE -#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE - | SNDRV_PCM_FMTBIT_COMPRESSED_16BE -#endif - , - .rates = SNDRV_PCM_RATE_8000_96000, - .tag = 0, - }, - { - /* analog output */ - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_BE, - .rates = SNDRV_PCM_RATE_8000_96000, - .transfer_in = 0, - .must_be_clock_source = 0, - .tag = 1, - }, - { - /* digital pcm output, also possible for analog out */ - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000, - .transfer_in = 0, - .must_be_clock_source = 0, - .tag = 2, - }, -#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE - /* Once alsa gets supports for this kind of thing we can add it... */ - { - /* digital compressed output */ - .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000, - .tag = 2, - }, -#endif - {} -}; - -static int onyx_usable(struct codec_info_item *cii, - struct transfer_info *ti, - struct transfer_info *out) -{ - u8 v; - struct onyx *onyx = cii->codec_data; - int spdif_enabled, analog_enabled; - - mutex_lock(&onyx->mutex); - onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); - spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); - onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); - analog_enabled = - (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) - != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); - mutex_unlock(&onyx->mutex); - - switch (ti->tag) { - case 0: return 1; - case 1: return analog_enabled; - case 2: return spdif_enabled; - } - return 1; -} - -static int onyx_prepare(struct codec_info_item *cii, - struct bus_info *bi, - struct snd_pcm_substream *substream) -{ - u8 v; - struct onyx *onyx = cii->codec_data; - int err = -EBUSY; - - mutex_lock(&onyx->mutex); - -#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE - if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { - /* mute and lock analog output */ - onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); - if (onyx_write_register(onyx, - ONYX_REG_DAC_CONTROL, - v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) - goto out_unlock; - onyx->analog_locked = 1; - err = 0; - goto out_unlock; - } -#endif - switch (substream->runtime->rate) { - case 32000: - case 44100: - case 48000: - /* these rates are ok for all outputs */ - /* FIXME: program spdif channel control bits here so that - * userspace doesn't have to if it only plays pcm! */ - err = 0; - goto out_unlock; - default: - /* got some rate that the digital output can't do, - * so disable and lock it */ - onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v); - if (onyx_write_register(onyx, - ONYX_REG_DIG_INFO4, - v & ~ONYX_SPDIF_ENABLE)) - goto out_unlock; - onyx->spdif_locked = 1; - err = 0; - goto out_unlock; - } - - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; -} - -static int onyx_open(struct codec_info_item *cii, - struct snd_pcm_substream *substream) -{ - struct onyx *onyx = cii->codec_data; - - mutex_lock(&onyx->mutex); - onyx->open_count++; - mutex_unlock(&onyx->mutex); - - return 0; -} - -static int onyx_close(struct codec_info_item *cii, - struct snd_pcm_substream *substream) -{ - struct onyx *onyx = cii->codec_data; - - mutex_lock(&onyx->mutex); - onyx->open_count--; - if (!onyx->open_count) - onyx->spdif_locked = onyx->analog_locked = 0; - mutex_unlock(&onyx->mutex); - - return 0; -} - -static int onyx_switch_clock(struct codec_info_item *cii, - enum clock_switch what) -{ - struct onyx *onyx = cii->codec_data; - - mutex_lock(&onyx->mutex); - /* this *MUST* be more elaborate later... */ - switch (what) { - case CLOCK_SWITCH_PREPARE_SLAVE: - onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio); - break; - case CLOCK_SWITCH_SLAVE: - onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio); - break; - default: /* silence warning */ - break; - } - mutex_unlock(&onyx->mutex); - - return 0; -} - -#ifdef CONFIG_PM - -static int onyx_suspend(struct codec_info_item *cii, pm_message_t state) -{ - struct onyx *onyx = cii->codec_data; - u8 v; - int err = -ENXIO; - - mutex_lock(&onyx->mutex); - if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) - goto out_unlock; - onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV); - /* Apple does a sleep here but the datasheet says to do it on resume */ - err = 0; - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; -} - -static int onyx_resume(struct codec_info_item *cii) -{ - struct onyx *onyx = cii->codec_data; - u8 v; - int err = -ENXIO; - - mutex_lock(&onyx->mutex); - - /* reset codec */ - onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); - msleep(1); - onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1); - msleep(1); - onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); - msleep(1); - - /* take codec out of suspend (if it still is after reset) */ - if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) - goto out_unlock; - onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); - /* FIXME: should divide by sample rate, but 8k is the lowest we go */ - msleep(2205000/8000); - /* reset all values */ - onyx_register_init(onyx); - err = 0; - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; -} - -#endif /* CONFIG_PM */ - -static struct codec_info onyx_codec_info = { - .transfers = onyx_transfers, - .sysclock_factor = 256, - .bus_factor = 64, - .owner = THIS_MODULE, - .usable = onyx_usable, - .prepare = onyx_prepare, - .open = onyx_open, - .close = onyx_close, - .switch_clock = onyx_switch_clock, -#ifdef CONFIG_PM - .suspend = onyx_suspend, - .resume = onyx_resume, -#endif -}; - -static int onyx_init_codec(struct aoa_codec *codec) -{ - struct onyx *onyx = codec_to_onyx(codec); - struct snd_kcontrol *ctl; - struct codec_info *ci = &onyx_codec_info; - u8 v; - int err; - - if (!onyx->codec.gpio || !onyx->codec.gpio->methods) { - printk(KERN_ERR PFX "gpios not assigned!!\n"); - return -EINVAL; - } - - onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); - msleep(1); - onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1); - msleep(1); - onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); - msleep(1); - - if (onyx_register_init(onyx)) { - printk(KERN_ERR PFX "failed to initialise onyx registers\n"); - return -ENODEV; - } - - if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) { - printk(KERN_ERR PFX "failed to create onyx snd device!\n"); - return -ENODEV; - } - - /* nothing connected? what a joke! */ - if ((onyx->codec.connected & 0xF) == 0) - return -ENOTCONN; - - /* if no inputs are present... */ - if ((onyx->codec.connected & 0xC) == 0) { - if (!onyx->codec_info) - onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); - if (!onyx->codec_info) - return -ENOMEM; - ci = onyx->codec_info; - *ci = onyx_codec_info; - ci->transfers++; - } - - /* if no outputs are present... */ - if ((onyx->codec.connected & 3) == 0) { - if (!onyx->codec_info) - onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); - if (!onyx->codec_info) - return -ENOMEM; - ci = onyx->codec_info; - /* this is fine as there have to be inputs - * if we end up in this part of the code */ - *ci = onyx_codec_info; - ci->transfers[1].formats = 0; - } - - if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev, - aoa_get_card(), - ci, onyx)) { - printk(KERN_ERR PFX "error creating onyx pcm\n"); - return -ENODEV; - } -#define ADDCTL(n) \ - do { \ - ctl = snd_ctl_new1(&n, onyx); \ - if (ctl) { \ - ctl->id.device = \ - onyx->codec.soundbus_dev->pcm->device; \ - err = aoa_snd_ctl_add(ctl); \ - if (err) \ - goto error; \ - } \ - } while (0) - - if (onyx->codec.soundbus_dev->pcm) { - /* give the user appropriate controls - * depending on what inputs are connected */ - if ((onyx->codec.connected & 0xC) == 0xC) - ADDCTL(capture_source_control); - else if (onyx->codec.connected & 4) - onyx_set_capture_source(onyx, 0); - else - onyx_set_capture_source(onyx, 1); - if (onyx->codec.connected & 0xC) - ADDCTL(inputgain_control); - - /* depending on what output is connected, - * give the user appropriate controls */ - if (onyx->codec.connected & 1) { - ADDCTL(volume_control); - ADDCTL(mute_control); - ADDCTL(ovr1_control); - ADDCTL(flt0_control); - ADDCTL(hpf_control); - ADDCTL(dm12_control); - /* spdif control defaults to off */ - } - if (onyx->codec.connected & 2) { - ADDCTL(onyx_spdif_mask); - ADDCTL(onyx_spdif_ctrl); - } - if ((onyx->codec.connected & 3) == 3) - ADDCTL(spdif_control); - /* if only S/PDIF is connected, enable it unconditionally */ - if ((onyx->codec.connected & 3) == 2) { - onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); - v |= ONYX_SPDIF_ENABLE; - onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); - } - } -#undef ADDCTL - printk(KERN_INFO PFX "attached to onyx codec via i2c\n"); - - return 0; - error: - onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); - snd_device_free(aoa_get_card(), onyx); - return err; -} - -static void onyx_exit_codec(struct aoa_codec *codec) -{ - struct onyx *onyx = codec_to_onyx(codec); - - if (!onyx->codec.soundbus_dev) { - printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n"); - return; - } - onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); -} - -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; - - onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL); - - if (!onyx) - return -ENOMEM; - - mutex_init(&onyx->mutex); - 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) { - printk(KERN_ERR PFX "failed to read control register\n"); - goto fail; - } - - strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN); - onyx->codec.owner = THIS_MODULE; - onyx->codec.init = onyx_init_codec; - onyx->codec.exit = onyx_exit_codec; - onyx->codec.node = of_node_get(node); - - if (aoa_codec_register(&onyx->codec)) { - goto fail; - } - printk(KERN_DEBUG PFX "created and attached onyx instance\n"); - return 0; - fail: - kfree(onyx); - return -ENODEV; -} - -static int onyx_i2c_attach(struct i2c_adapter *adapter) -{ - struct device_node *busnode, *dev = NULL; - struct pmac_i2c_bus *bus; - - bus = pmac_i2c_adapter_to_bus(adapter); - if (bus == NULL) - return -ENODEV; - busnode = pmac_i2c_get_bus_node(bus); - - while ((dev = of_get_next_child(busnode, dev)) != NULL) { - if (of_device_is_compatible(dev, "pcm3052")) { - const u32 *addr; - printk(KERN_DEBUG PFX "found pcm3052\n"); - addr = of_get_property(dev, "reg", NULL); - if (!addr) - return -ENODEV; - return onyx_create(adapter, dev, (*addr)>>1); - } - } - - /* if that didn't work, try desperate mode for older - * machines that have stuff missing from the device tree */ - - if (!of_device_is_compatible(busnode, "k2-i2c")) - return -ENODEV; - - printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n"); - /* probe both possible addresses for the onyx chip */ - if (onyx_create(adapter, NULL, 0x46) == 0) - return 0; - return onyx_create(adapter, NULL, 0x47); -} - -static int onyx_i2c_remove(struct i2c_client *client) -{ - struct onyx *onyx = i2c_get_clientdata(client); - - aoa_codec_unregister(&onyx->codec); - of_node_put(onyx->codec.node); - kfree(onyx->codec_info); - 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, - .probe = onyx_i2c_probe, - .remove = onyx_i2c_remove, - .id_table = onyx_i2c_id, -}; - -module_i2c_driver(onyx_driver); diff --git a/ANDROID_3.4.5/sound/aoa/codecs/onyx.h b/ANDROID_3.4.5/sound/aoa/codecs/onyx.h deleted file mode 100644 index ffd20254..00000000 --- a/ANDROID_3.4.5/sound/aoa/codecs/onyx.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Apple Onboard Audio driver for Onyx codec (header) - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ -#ifndef __SND_AOA_CODEC_ONYX_H -#define __SND_AOA_CODEC_ONYX_H -#include -#include -#include -#include - -/* PCM3052 register definitions */ - -/* the attenuation registers take values from - * -1 (0dB) to -127 (-63.0 dB) or others (muted) */ -#define ONYX_REG_DAC_ATTEN_LEFT 65 -#define FIRSTREGISTER ONYX_REG_DAC_ATTEN_LEFT -#define ONYX_REG_DAC_ATTEN_RIGHT 66 - -#define ONYX_REG_CONTROL 67 -# define ONYX_MRST (1<<7) -# define ONYX_SRST (1<<6) -# define ONYX_ADPSV (1<<5) -# define ONYX_DAPSV (1<<4) -# define ONYX_SILICONVERSION (1<<0) -/* all others reserved */ - -#define ONYX_REG_DAC_CONTROL 68 -# define ONYX_OVR1 (1<<6) -# define ONYX_MUTE_RIGHT (1<<1) -# define ONYX_MUTE_LEFT (1<<0) - -#define ONYX_REG_DAC_DEEMPH 69 -# define ONYX_DIGDEEMPH_SHIFT 5 -# define ONYX_DIGDEEMPH_MASK (3<= 50) - result += tas3004_bass_diff_to_treble[idx-50]; - return result; -} diff --git a/ANDROID_3.4.5/sound/aoa/codecs/tas-gain-table.h b/ANDROID_3.4.5/sound/aoa/codecs/tas-gain-table.h deleted file mode 100644 index 4cfa6757..00000000 --- a/ANDROID_3.4.5/sound/aoa/codecs/tas-gain-table.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - This is the program used to generate below table. - -#include -#include -int main() { - int dB2; - printf("/" "* This file is only included exactly once!\n"); - printf(" *\n"); - printf(" * If they'd only tell us that generating this table was\n"); - printf(" * as easy as calculating\n"); - printf(" * hwvalue = 1048576.0*exp(0.057564628*dB*2)\n"); - printf(" * :) *" "/\n"); - printf("static int tas_gaintable[] = {\n"); - printf(" 0x000000, /" "* -infinity dB *" "/\n"); - for (dB2=-140;dB2<=36;dB2++) - printf(" 0x%.6x, /" "* %-02.1f dB *" "/\n", (int)(1048576.0*exp(0.057564628*dB2)), dB2/2.0); - printf("};\n\n"); -} - -*/ - -/* This file is only included exactly once! - * - * If they'd only tell us that generating this table was - * as easy as calculating - * hwvalue = 1048576.0*exp(0.057564628*dB*2) - * :) */ -static int tas_gaintable[] = { - 0x000000, /* -infinity dB */ - 0x00014b, /* -70.0 dB */ - 0x00015f, /* -69.5 dB */ - 0x000174, /* -69.0 dB */ - 0x00018a, /* -68.5 dB */ - 0x0001a1, /* -68.0 dB */ - 0x0001ba, /* -67.5 dB */ - 0x0001d4, /* -67.0 dB */ - 0x0001f0, /* -66.5 dB */ - 0x00020d, /* -66.0 dB */ - 0x00022c, /* -65.5 dB */ - 0x00024d, /* -65.0 dB */ - 0x000270, /* -64.5 dB */ - 0x000295, /* -64.0 dB */ - 0x0002bc, /* -63.5 dB */ - 0x0002e6, /* -63.0 dB */ - 0x000312, /* -62.5 dB */ - 0x000340, /* -62.0 dB */ - 0x000372, /* -61.5 dB */ - 0x0003a6, /* -61.0 dB */ - 0x0003dd, /* -60.5 dB */ - 0x000418, /* -60.0 dB */ - 0x000456, /* -59.5 dB */ - 0x000498, /* -59.0 dB */ - 0x0004de, /* -58.5 dB */ - 0x000528, /* -58.0 dB */ - 0x000576, /* -57.5 dB */ - 0x0005c9, /* -57.0 dB */ - 0x000620, /* -56.5 dB */ - 0x00067d, /* -56.0 dB */ - 0x0006e0, /* -55.5 dB */ - 0x000748, /* -55.0 dB */ - 0x0007b7, /* -54.5 dB */ - 0x00082c, /* -54.0 dB */ - 0x0008a8, /* -53.5 dB */ - 0x00092b, /* -53.0 dB */ - 0x0009b6, /* -52.5 dB */ - 0x000a49, /* -52.0 dB */ - 0x000ae5, /* -51.5 dB */ - 0x000b8b, /* -51.0 dB */ - 0x000c3a, /* -50.5 dB */ - 0x000cf3, /* -50.0 dB */ - 0x000db8, /* -49.5 dB */ - 0x000e88, /* -49.0 dB */ - 0x000f64, /* -48.5 dB */ - 0x00104e, /* -48.0 dB */ - 0x001145, /* -47.5 dB */ - 0x00124b, /* -47.0 dB */ - 0x001361, /* -46.5 dB */ - 0x001487, /* -46.0 dB */ - 0x0015be, /* -45.5 dB */ - 0x001708, /* -45.0 dB */ - 0x001865, /* -44.5 dB */ - 0x0019d8, /* -44.0 dB */ - 0x001b60, /* -43.5 dB */ - 0x001cff, /* -43.0 dB */ - 0x001eb7, /* -42.5 dB */ - 0x002089, /* -42.0 dB */ - 0x002276, /* -41.5 dB */ - 0x002481, /* -41.0 dB */ - 0x0026ab, /* -40.5 dB */ - 0x0028f5, /* -40.0 dB */ - 0x002b63, /* -39.5 dB */ - 0x002df5, /* -39.0 dB */ - 0x0030ae, /* -38.5 dB */ - 0x003390, /* -38.0 dB */ - 0x00369e, /* -37.5 dB */ - 0x0039db, /* -37.0 dB */ - 0x003d49, /* -36.5 dB */ - 0x0040ea, /* -36.0 dB */ - 0x0044c3, /* -35.5 dB */ - 0x0048d6, /* -35.0 dB */ - 0x004d27, /* -34.5 dB */ - 0x0051b9, /* -34.0 dB */ - 0x005691, /* -33.5 dB */ - 0x005bb2, /* -33.0 dB */ - 0x006121, /* -32.5 dB */ - 0x0066e3, /* -32.0 dB */ - 0x006cfb, /* -31.5 dB */ - 0x007370, /* -31.0 dB */ - 0x007a48, /* -30.5 dB */ - 0x008186, /* -30.0 dB */ - 0x008933, /* -29.5 dB */ - 0x009154, /* -29.0 dB */ - 0x0099f1, /* -28.5 dB */ - 0x00a310, /* -28.0 dB */ - 0x00acba, /* -27.5 dB */ - 0x00b6f6, /* -27.0 dB */ - 0x00c1cd, /* -26.5 dB */ - 0x00cd49, /* -26.0 dB */ - 0x00d973, /* -25.5 dB */ - 0x00e655, /* -25.0 dB */ - 0x00f3fb, /* -24.5 dB */ - 0x010270, /* -24.0 dB */ - 0x0111c0, /* -23.5 dB */ - 0x0121f9, /* -23.0 dB */ - 0x013328, /* -22.5 dB */ - 0x01455b, /* -22.0 dB */ - 0x0158a2, /* -21.5 dB */ - 0x016d0e, /* -21.0 dB */ - 0x0182af, /* -20.5 dB */ - 0x019999, /* -20.0 dB */ - 0x01b1de, /* -19.5 dB */ - 0x01cb94, /* -19.0 dB */ - 0x01e6cf, /* -18.5 dB */ - 0x0203a7, /* -18.0 dB */ - 0x022235, /* -17.5 dB */ - 0x024293, /* -17.0 dB */ - 0x0264db, /* -16.5 dB */ - 0x02892c, /* -16.0 dB */ - 0x02afa3, /* -15.5 dB */ - 0x02d862, /* -15.0 dB */ - 0x03038a, /* -14.5 dB */ - 0x033142, /* -14.0 dB */ - 0x0361af, /* -13.5 dB */ - 0x0394fa, /* -13.0 dB */ - 0x03cb50, /* -12.5 dB */ - 0x0404de, /* -12.0 dB */ - 0x0441d5, /* -11.5 dB */ - 0x048268, /* -11.0 dB */ - 0x04c6d0, /* -10.5 dB */ - 0x050f44, /* -10.0 dB */ - 0x055c04, /* -9.5 dB */ - 0x05ad50, /* -9.0 dB */ - 0x06036e, /* -8.5 dB */ - 0x065ea5, /* -8.0 dB */ - 0x06bf44, /* -7.5 dB */ - 0x07259d, /* -7.0 dB */ - 0x079207, /* -6.5 dB */ - 0x0804dc, /* -6.0 dB */ - 0x087e80, /* -5.5 dB */ - 0x08ff59, /* -5.0 dB */ - 0x0987d5, /* -4.5 dB */ - 0x0a1866, /* -4.0 dB */ - 0x0ab189, /* -3.5 dB */ - 0x0b53be, /* -3.0 dB */ - 0x0bff91, /* -2.5 dB */ - 0x0cb591, /* -2.0 dB */ - 0x0d765a, /* -1.5 dB */ - 0x0e4290, /* -1.0 dB */ - 0x0f1adf, /* -0.5 dB */ - 0x100000, /* 0.0 dB */ - 0x10f2b4, /* 0.5 dB */ - 0x11f3c9, /* 1.0 dB */ - 0x13041a, /* 1.5 dB */ - 0x14248e, /* 2.0 dB */ - 0x15561a, /* 2.5 dB */ - 0x1699c0, /* 3.0 dB */ - 0x17f094, /* 3.5 dB */ - 0x195bb8, /* 4.0 dB */ - 0x1adc61, /* 4.5 dB */ - 0x1c73d5, /* 5.0 dB */ - 0x1e236d, /* 5.5 dB */ - 0x1fec98, /* 6.0 dB */ - 0x21d0d9, /* 6.5 dB */ - 0x23d1cd, /* 7.0 dB */ - 0x25f125, /* 7.5 dB */ - 0x2830af, /* 8.0 dB */ - 0x2a9254, /* 8.5 dB */ - 0x2d1818, /* 9.0 dB */ - 0x2fc420, /* 9.5 dB */ - 0x3298b0, /* 10.0 dB */ - 0x35982f, /* 10.5 dB */ - 0x38c528, /* 11.0 dB */ - 0x3c224c, /* 11.5 dB */ - 0x3fb278, /* 12.0 dB */ - 0x4378b0, /* 12.5 dB */ - 0x477829, /* 13.0 dB */ - 0x4bb446, /* 13.5 dB */ - 0x5030a1, /* 14.0 dB */ - 0x54f106, /* 14.5 dB */ - 0x59f980, /* 15.0 dB */ - 0x5f4e52, /* 15.5 dB */ - 0x64f403, /* 16.0 dB */ - 0x6aef5e, /* 16.5 dB */ - 0x714575, /* 17.0 dB */ - 0x77fbaa, /* 17.5 dB */ - 0x7f17af, /* 18.0 dB */ -}; - diff --git a/ANDROID_3.4.5/sound/aoa/codecs/tas.c b/ANDROID_3.4.5/sound/aoa/codecs/tas.c deleted file mode 100644 index 8e63d1f3..00000000 --- a/ANDROID_3.4.5/sound/aoa/codecs/tas.c +++ /dev/null @@ -1,1029 +0,0 @@ -/* - * Apple Onboard Audio driver for tas codec - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - * - * Open questions: - * - How to distinguish between 3004 and versions? - * - * FIXMEs: - * - This codec driver doesn't honour the 'connected' - * property of the aoa_codec struct, hence if - * it is used in machines where not everything is - * connected it will display wrong mixer elements. - * - Driver assumes that the microphone is always - * monaureal and connected to the right channel of - * the input. This should also be a codec-dependent - * flag, maybe the codec should have 3 different - * bits for the three different possibilities how - * it can be hooked up... - * But as long as I don't see any hardware hooked - * up that way... - * - As Apple notes in their code, the tas3004 seems - * to delay the right channel by one sample. You can - * see this when for example recording stereo in - * audacity, or recording the tas output via cable - * on another machine (use a sinus generator or so). - * I tried programming the BiQuads but couldn't - * make the delay work, maybe someone can read the - * datasheet and fix it. The relevant Apple comment - * is in AppleTAS3004Audio.cpp lines 1637 ff. Note - * that their comment describing how they program - * the filters sucks... - * - * Other things: - * - this should actually register *two* aoa_codec - * structs since it has two inputs. Then it must - * use the prepare callback to forbid running the - * secondary output on a different clock. - * Also, whatever bus knows how to do this must - * provide two soundbus_dev devices and the fabric - * must be able to link them correctly. - * - * I don't even know if Apple ever uses the second - * port on the tas3004 though, I don't think their - * i2s controllers can even do it. OTOH, they all - * derive the clocks from common clocks, so it - * might just be possible. The framework allows the - * codec to refine the transfer_info items in the - * usable callback, so we can simply remove the - * rates the second instance is not using when it - * actually is in use. - * Maybe we'll need to make the sound busses have - * a 'clock group id' value so the codec can - * determine if the two outputs can be driven at - * the same time. But that is likely overkill, up - * to the fabric to not link them up incorrectly, - * and up to the hardware designer to not wire - * them up in some weird unusable way. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Johannes Berg "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("tas codec driver for snd-aoa"); - -#include "tas.h" -#include "tas-gain-table.h" -#include "tas-basstreble.h" -#include "../aoa.h" -#include "../soundbus/soundbus.h" - -#define PFX "snd-aoa-codec-tas: " - - -struct tas { - struct aoa_codec codec; - struct i2c_client *i2c; - u32 mute_l:1, mute_r:1 , - controls_created:1 , - drc_enabled:1, - hw_enabled:1; - u8 cached_volume_l, cached_volume_r; - u8 mixer_l[3], mixer_r[3]; - u8 bass, treble; - u8 acr; - int drc_range; - /* protects hardware access against concurrency from - * userspace when hitting controls and during - * codec init/suspend/resume */ - struct mutex mtx; -}; - -static int tas_reset_init(struct tas *tas); - -static struct tas *codec_to_tas(struct aoa_codec *codec) -{ - return container_of(codec, struct tas, 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); - else - return i2c_smbus_write_i2c_block_data(tas->i2c, reg, len, data); -} - -static void tas3004_set_drc(struct tas *tas) -{ - unsigned char val[6]; - - if (tas->drc_enabled) - val[0] = 0x50; /* 3:1 above threshold */ - else - val[0] = 0x51; /* disabled */ - val[1] = 0x02; /* 1:1 below threshold */ - if (tas->drc_range > 0xef) - val[2] = 0xef; - else if (tas->drc_range < 0) - val[2] = 0x00; - else - val[2] = tas->drc_range; - val[3] = 0xb0; - val[4] = 0x60; - val[5] = 0xa0; - - tas_write_reg(tas, TAS_REG_DRC, 6, val); -} - -static void tas_set_treble(struct tas *tas) -{ - u8 tmp; - - tmp = tas3004_treble(tas->treble); - tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp); -} - -static void tas_set_bass(struct tas *tas) -{ - u8 tmp; - - tmp = tas3004_bass(tas->bass); - tas_write_reg(tas, TAS_REG_BASS, 1, &tmp); -} - -static void tas_set_volume(struct tas *tas) -{ - u8 block[6]; - int tmp; - u8 left, right; - - left = tas->cached_volume_l; - right = tas->cached_volume_r; - - if (left > 177) left = 177; - if (right > 177) right = 177; - - if (tas->mute_l) left = 0; - if (tas->mute_r) right = 0; - - /* analysing the volume and mixer tables shows - * that they are similar enough when we shift - * the mixer table down by 4 bits. The error - * is miniscule, in just one item the error - * is 1, at a value of 0x07f17b (mixer table - * value is 0x07f17a) */ - tmp = tas_gaintable[left]; - block[0] = tmp>>20; - block[1] = tmp>>12; - block[2] = tmp>>4; - tmp = tas_gaintable[right]; - block[3] = tmp>>20; - block[4] = tmp>>12; - block[5] = tmp>>4; - tas_write_reg(tas, TAS_REG_VOL, 6, block); -} - -static void tas_set_mixer(struct tas *tas) -{ - u8 block[9]; - int tmp, i; - u8 val; - - for (i=0;i<3;i++) { - val = tas->mixer_l[i]; - if (val > 177) val = 177; - tmp = tas_gaintable[val]; - block[3*i+0] = tmp>>16; - block[3*i+1] = tmp>>8; - block[3*i+2] = tmp; - } - tas_write_reg(tas, TAS_REG_LMIX, 9, block); - - for (i=0;i<3;i++) { - val = tas->mixer_r[i]; - if (val > 177) val = 177; - tmp = tas_gaintable[val]; - block[3*i+0] = tmp>>16; - block[3*i+1] = tmp>>8; - block[3*i+2] = tmp; - } - tas_write_reg(tas, TAS_REG_RMIX, 9, block); -} - -/* alsa stuff */ - -static int tas_dev_register(struct snd_device *dev) -{ - return 0; -} - -static struct snd_device_ops ops = { - .dev_register = tas_dev_register, -}; - -static int tas_snd_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 177; - return 0; -} - -static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - ucontrol->value.integer.value[0] = tas->cached_volume_l; - ucontrol->value.integer.value[1] = tas->cached_volume_r; - mutex_unlock(&tas->mtx); - return 0; -} - -static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.integer.value[0] < 0 || - ucontrol->value.integer.value[0] > 177) - return -EINVAL; - if (ucontrol->value.integer.value[1] < 0 || - ucontrol->value.integer.value[1] > 177) - return -EINVAL; - - mutex_lock(&tas->mtx); - if (tas->cached_volume_l == ucontrol->value.integer.value[0] - && tas->cached_volume_r == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); - return 0; - } - - tas->cached_volume_l = ucontrol->value.integer.value[0]; - tas->cached_volume_r = ucontrol->value.integer.value[1]; - if (tas->hw_enabled) - tas_set_volume(tas); - mutex_unlock(&tas->mtx); - return 1; -} - -static struct snd_kcontrol_new volume_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = tas_snd_vol_info, - .get = tas_snd_vol_get, - .put = tas_snd_vol_put, -}; - -#define tas_snd_mute_info snd_ctl_boolean_stereo_info - -static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - ucontrol->value.integer.value[0] = !tas->mute_l; - ucontrol->value.integer.value[1] = !tas->mute_r; - mutex_unlock(&tas->mtx); - return 0; -} - -static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - if (tas->mute_l == !ucontrol->value.integer.value[0] - && tas->mute_r == !ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); - return 0; - } - - tas->mute_l = !ucontrol->value.integer.value[0]; - tas->mute_r = !ucontrol->value.integer.value[1]; - if (tas->hw_enabled) - tas_set_volume(tas); - mutex_unlock(&tas->mtx); - return 1; -} - -static struct snd_kcontrol_new mute_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = tas_snd_mute_info, - .get = tas_snd_mute_get, - .put = tas_snd_mute_put, -}; - -static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 177; - return 0; -} - -static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - int idx = kcontrol->private_value; - - mutex_lock(&tas->mtx); - ucontrol->value.integer.value[0] = tas->mixer_l[idx]; - ucontrol->value.integer.value[1] = tas->mixer_r[idx]; - mutex_unlock(&tas->mtx); - - return 0; -} - -static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - int idx = kcontrol->private_value; - - mutex_lock(&tas->mtx); - if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] - && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); - return 0; - } - - tas->mixer_l[idx] = ucontrol->value.integer.value[0]; - tas->mixer_r[idx] = ucontrol->value.integer.value[1]; - - if (tas->hw_enabled) - tas_set_mixer(tas); - mutex_unlock(&tas->mtx); - return 1; -} - -#define MIXER_CONTROL(n,descr,idx) \ -static struct snd_kcontrol_new n##_control = { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = descr " Playback Volume", \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = tas_snd_mixer_info, \ - .get = tas_snd_mixer_get, \ - .put = tas_snd_mixer_put, \ - .private_value = idx, \ -} - -MIXER_CONTROL(pcm1, "PCM", 0); -MIXER_CONTROL(monitor, "Monitor", 2); - -static int tas_snd_drc_range_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = TAS3004_DRC_MAX; - return 0; -} - -static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - ucontrol->value.integer.value[0] = tas->drc_range; - mutex_unlock(&tas->mtx); - return 0; -} - -static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.integer.value[0] < 0 || - ucontrol->value.integer.value[0] > TAS3004_DRC_MAX) - return -EINVAL; - - mutex_lock(&tas->mtx); - if (tas->drc_range == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); - return 0; - } - - tas->drc_range = ucontrol->value.integer.value[0]; - if (tas->hw_enabled) - tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); - return 1; -} - -static struct snd_kcontrol_new drc_range_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Range", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = tas_snd_drc_range_info, - .get = tas_snd_drc_range_get, - .put = tas_snd_drc_range_put, -}; - -#define tas_snd_drc_switch_info snd_ctl_boolean_mono_info - -static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - ucontrol->value.integer.value[0] = tas->drc_enabled; - mutex_unlock(&tas->mtx); - return 0; -} - -static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - if (tas->drc_enabled == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); - return 0; - } - - tas->drc_enabled = !!ucontrol->value.integer.value[0]; - if (tas->hw_enabled) - tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); - return 1; -} - -static struct snd_kcontrol_new drc_switch_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Range Switch", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = tas_snd_drc_switch_info, - .get = tas_snd_drc_switch_get, - .put = tas_snd_drc_switch_put, -}; - -static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "Line-In", "Microphone" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); - mutex_unlock(&tas->mtx); - return 0; -} - -static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - int oldacr; - - if (ucontrol->value.enumerated.item[0] > 1) - return -EINVAL; - mutex_lock(&tas->mtx); - oldacr = tas->acr; - - /* - * Despite what the data sheet says in one place, the - * TAS_ACR_B_MONAUREAL bit forces mono output even when - * input A (line in) is selected. - */ - tas->acr &= ~(TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL); - if (ucontrol->value.enumerated.item[0]) - tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL | - TAS_ACR_B_MON_SEL_RIGHT; - if (oldacr == tas->acr) { - mutex_unlock(&tas->mtx); - return 0; - } - if (tas->hw_enabled) - tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); - return 1; -} - -static struct snd_kcontrol_new capture_source_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* If we name this 'Input Source', it properly shows up in - * alsamixer as a selection, * but it's shown under the - * 'Playback' category. - * If I name it 'Capture Source', it shows up in strange - * ways (two bools of which one can be selected at a - * time) but at least it's shown in the 'Capture' - * category. - * I was told that this was due to backward compatibility, - * but I don't understand then why the mangling is *not* - * done when I name it "Input Source"..... - */ - .name = "Capture Source", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = tas_snd_capture_source_info, - .get = tas_snd_capture_source_get, - .put = tas_snd_capture_source_put, -}; - -static int tas_snd_treble_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = TAS3004_TREBLE_MIN; - uinfo->value.integer.max = TAS3004_TREBLE_MAX; - return 0; -} - -static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - ucontrol->value.integer.value[0] = tas->treble; - mutex_unlock(&tas->mtx); - return 0; -} - -static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN || - ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX) - return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->treble == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); - return 0; - } - - tas->treble = ucontrol->value.integer.value[0]; - if (tas->hw_enabled) - tas_set_treble(tas); - mutex_unlock(&tas->mtx); - return 1; -} - -static struct snd_kcontrol_new treble_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Treble", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = tas_snd_treble_info, - .get = tas_snd_treble_get, - .put = tas_snd_treble_put, -}; - -static int tas_snd_bass_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = TAS3004_BASS_MIN; - uinfo->value.integer.max = TAS3004_BASS_MAX; - return 0; -} - -static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas->mtx); - ucontrol->value.integer.value[0] = tas->bass; - mutex_unlock(&tas->mtx); - return 0; -} - -static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tas *tas = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN || - ucontrol->value.integer.value[0] > TAS3004_BASS_MAX) - return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->bass == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); - return 0; - } - - tas->bass = ucontrol->value.integer.value[0]; - if (tas->hw_enabled) - tas_set_bass(tas); - mutex_unlock(&tas->mtx); - return 1; -} - -static struct snd_kcontrol_new bass_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Bass", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = tas_snd_bass_info, - .get = tas_snd_bass_get, - .put = tas_snd_bass_put, -}; - -static struct transfer_info tas_transfers[] = { - { - /* input */ - .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .transfer_in = 1, - }, - { - /* output */ - .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE, - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .transfer_in = 0, - }, - {} -}; - -static int tas_usable(struct codec_info_item *cii, - struct transfer_info *ti, - struct transfer_info *out) -{ - return 1; -} - -static int tas_reset_init(struct tas *tas) -{ - u8 tmp; - - tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); - msleep(5); - tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); - msleep(5); - tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); - msleep(20); - tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); - msleep(10); - tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); - - tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; - if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) - goto outerr; - - tas->acr |= TAS_ACR_ANALOG_PDOWN; - if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) - goto outerr; - - tmp = 0; - if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) - goto outerr; - - tas3004_set_drc(tas); - - /* Set treble & bass to 0dB */ - tas->treble = TAS3004_TREBLE_ZERO; - tas->bass = TAS3004_BASS_ZERO; - tas_set_treble(tas); - tas_set_bass(tas); - - tas->acr &= ~TAS_ACR_ANALOG_PDOWN; - if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) - goto outerr; - - return 0; - outerr: - return -ENODEV; -} - -static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock) -{ - struct tas *tas = cii->codec_data; - - switch(clock) { - case CLOCK_SWITCH_PREPARE_SLAVE: - /* Clocks are going away, mute mute mute */ - tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); - tas->hw_enabled = 0; - break; - case CLOCK_SWITCH_SLAVE: - /* Clocks are back, re-init the codec */ - mutex_lock(&tas->mtx); - tas_reset_init(tas); - tas_set_volume(tas); - tas_set_mixer(tas); - tas->hw_enabled = 1; - tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); - mutex_unlock(&tas->mtx); - break; - default: - /* doesn't happen as of now */ - return -EINVAL; - } - return 0; -} - -#ifdef CONFIG_PM -/* we are controlled via i2c and assume that is always up - * If that wasn't the case, we'd have to suspend once - * our i2c device is suspended, and then take note of that! */ -static int tas_suspend(struct tas *tas) -{ - mutex_lock(&tas->mtx); - tas->hw_enabled = 0; - tas->acr |= TAS_ACR_ANALOG_PDOWN; - tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); - return 0; -} - -static int tas_resume(struct tas *tas) -{ - /* reset codec */ - mutex_lock(&tas->mtx); - tas_reset_init(tas); - tas_set_volume(tas); - tas_set_mixer(tas); - tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); - return 0; -} - -static int _tas_suspend(struct codec_info_item *cii, pm_message_t state) -{ - return tas_suspend(cii->codec_data); -} - -static int _tas_resume(struct codec_info_item *cii) -{ - return tas_resume(cii->codec_data); -} -#else /* CONFIG_PM */ -#define _tas_suspend NULL -#define _tas_resume NULL -#endif /* CONFIG_PM */ - -static struct codec_info tas_codec_info = { - .transfers = tas_transfers, - /* in theory, we can drive it at 512 too... - * but so far the framework doesn't allow - * for that and I don't see much point in it. */ - .sysclock_factor = 256, - /* same here, could be 32 for just one 16 bit format */ - .bus_factor = 64, - .owner = THIS_MODULE, - .usable = tas_usable, - .switch_clock = tas_switch_clock, - .suspend = _tas_suspend, - .resume = _tas_resume, -}; - -static int tas_init_codec(struct aoa_codec *codec) -{ - struct tas *tas = codec_to_tas(codec); - int err; - - if (!tas->codec.gpio || !tas->codec.gpio->methods) { - printk(KERN_ERR PFX "gpios not assigned!!\n"); - return -EINVAL; - } - - mutex_lock(&tas->mtx); - if (tas_reset_init(tas)) { - printk(KERN_ERR PFX "tas failed to initialise\n"); - mutex_unlock(&tas->mtx); - return -ENXIO; - } - tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); - - if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, - aoa_get_card(), - &tas_codec_info, tas)) { - printk(KERN_ERR PFX "error attaching tas to soundbus\n"); - return -ENODEV; - } - - if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) { - printk(KERN_ERR PFX "failed to create tas snd device!\n"); - return -ENODEV; - } - err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas)); - if (err) - goto error; - - err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas)); - if (err) - goto error; - - err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas)); - if (err) - goto error; - - err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas)); - if (err) - goto error; - - err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas)); - if (err) - goto error; - - err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas)); - if (err) - goto error; - - err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas)); - if (err) - goto error; - - err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas)); - if (err) - goto error; - - err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas)); - if (err) - goto error; - - return 0; - error: - tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); - snd_device_free(aoa_get_card(), tas); - return err; -} - -static void tas_exit_codec(struct aoa_codec *codec) -{ - struct tas *tas = codec_to_tas(codec); - - if (!tas->codec.soundbus_dev) - return; - tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); -} - - -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; - /* - * We know the driver is already loaded, so the device should be - * already bound. If not it means binding failed, and then there - * is no point in keeping the device instantiated. - */ - 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 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); - - if (!tas) - return -ENOMEM; - - mutex_init(&tas->mtx); - tas->i2c = client; - i2c_set_clientdata(client, tas); - - /* seems that half is a saner default */ - tas->drc_range = TAS3004_DRC_MAX / 2; - - strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN); - tas->codec.owner = THIS_MODULE; - tas->codec.init = tas_init_codec; - tas->codec.exit = tas_exit_codec; - tas->codec.node = of_node_get(node); - - if (aoa_codec_register(&tas->codec)) { - goto fail; - } - printk(KERN_DEBUG - "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n", - (unsigned int)client->addr, node->full_name); - return 0; - fail: - mutex_destroy(&tas->mtx); - kfree(tas); - return -EINVAL; -} - -static int tas_i2c_attach(struct i2c_adapter *adapter) -{ - struct device_node *busnode, *dev = NULL; - struct pmac_i2c_bus *bus; - - bus = pmac_i2c_adapter_to_bus(adapter); - if (bus == NULL) - return -ENODEV; - busnode = pmac_i2c_get_bus_node(bus); - - while ((dev = of_get_next_child(busnode, dev)) != NULL) { - if (of_device_is_compatible(dev, "tas3004")) { - const u32 *addr; - printk(KERN_DEBUG PFX "found tas3004\n"); - addr = of_get_property(dev, "reg", NULL); - if (!addr) - continue; - return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f); - } - /* older machines have no 'codec' node with a 'compatible' - * property that says 'tas3004', they just have a 'deq' - * node without any such property... */ - if (strcmp(dev->name, "deq") == 0) { - const u32 *_addr; - u32 addr; - printk(KERN_DEBUG PFX "found 'deq' node\n"); - _addr = of_get_property(dev, "i2c-address", NULL); - if (!_addr) - continue; - addr = ((*_addr) >> 1) & 0x7f; - /* now, if the address doesn't match any of the two - * that a tas3004 can have, we cannot handle this. - * I doubt it ever happens but hey. */ - if (addr != 0x34 && addr != 0x35) - continue; - return tas_create(adapter, dev, addr); - } - } - return -ENODEV; -} - -static int tas_i2c_remove(struct i2c_client *client) -{ - struct tas *tas = i2c_get_clientdata(client); - u8 tmp = TAS_ACR_ANALOG_PDOWN; - - aoa_codec_unregister(&tas->codec); - of_node_put(tas->codec.node); - - /* power down codec chip */ - tas_write_reg(tas, TAS_REG_ACR, 1, &tmp); - - mutex_destroy(&tas->mtx); - kfree(tas); - 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, - .probe = tas_i2c_probe, - .remove = tas_i2c_remove, - .id_table = tas_i2c_id, -}; - -module_i2c_driver(tas_driver); diff --git a/ANDROID_3.4.5/sound/aoa/codecs/tas.h b/ANDROID_3.4.5/sound/aoa/codecs/tas.h deleted file mode 100644 index ae177e34..00000000 --- a/ANDROID_3.4.5/sound/aoa/codecs/tas.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Apple Onboard Audio driver for tas codec (header) - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ -#ifndef __SND_AOA_CODECTASH -#define __SND_AOA_CODECTASH - -#define TAS_REG_MCS 0x01 /* main control */ -# define TAS_MCS_FASTLOAD (1<<7) -# define TAS_MCS_SCLK64 (1<<6) -# define TAS_MCS_SPORT_MODE_MASK (3<<4) -# define TAS_MCS_SPORT_MODE_I2S (2<<4) -# define TAS_MCS_SPORT_MODE_RJ (1<<4) -# define TAS_MCS_SPORT_MODE_LJ (0<<4) -# define TAS_MCS_SPORT_WL_MASK (3<<0) -# define TAS_MCS_SPORT_WL_16BIT (0<<0) -# define TAS_MCS_SPORT_WL_18BIT (1<<0) -# define TAS_MCS_SPORT_WL_20BIT (2<<0) -# define TAS_MCS_SPORT_WL_24BIT (3<<0) - -#define TAS_REG_DRC 0x02 -#define TAS_REG_VOL 0x04 -#define TAS_REG_TREBLE 0x05 -#define TAS_REG_BASS 0x06 -#define TAS_REG_LMIX 0x07 -#define TAS_REG_RMIX 0x08 - -#define TAS_REG_ACR 0x40 /* analog control */ -# define TAS_ACR_B_MONAUREAL (1<<7) -# define TAS_ACR_B_MON_SEL_RIGHT (1<<6) -# define TAS_ACR_DEEMPH_MASK (3<<2) -# define TAS_ACR_DEEMPH_OFF (0<<2) -# define TAS_ACR_DEEMPH_48KHz (1<<2) -# define TAS_ACR_DEEMPH_44KHz (2<<2) -# define TAS_ACR_INPUT_B (1<<1) -# define TAS_ACR_ANALOG_PDOWN (1<<0) - -#define TAS_REG_MCS2 0x43 /* main control 2 */ -# define TAS_MCS2_ALLPASS (1<<1) - -#define TAS_REG_LEFT_BIQUAD6 0x10 -#define TAS_REG_RIGHT_BIQUAD6 0x19 - -#define TAS_REG_LEFT_LOUDNESS 0x21 -#define TAS_REG_RIGHT_LOUDNESS 0x22 -#define TAS_REG_LEFT_LOUDNESS_GAIN 0x23 -#define TAS_REG_RIGHT_LOUDNESS_GAIN 0x24 - -#define TAS3001_DRC_MAX 0x5f -#define TAS3004_DRC_MAX 0xef - -#endif /* __SND_AOA_CODECTASH */ diff --git a/ANDROID_3.4.5/sound/aoa/codecs/toonie.c b/ANDROID_3.4.5/sound/aoa/codecs/toonie.c deleted file mode 100644 index 69d2cb60..00000000 --- a/ANDROID_3.4.5/sound/aoa/codecs/toonie.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Apple Onboard Audio driver for Toonie codec - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - * - * - * This is a driver for the toonie codec chip. This chip is present - * on the Mac Mini and is nothing but a DAC. - */ -#include -#include -#include -MODULE_AUTHOR("Johannes Berg "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("toonie codec driver for snd-aoa"); - -#include "../aoa.h" -#include "../soundbus/soundbus.h" - - -#define PFX "snd-aoa-codec-toonie: " - -struct toonie { - struct aoa_codec codec; -}; -#define codec_to_toonie(c) container_of(c, struct toonie, codec) - -static int toonie_dev_register(struct snd_device *dev) -{ - return 0; -} - -static struct snd_device_ops ops = { - .dev_register = toonie_dev_register, -}; - -static struct transfer_info toonie_transfers[] = { - /* This thing *only* has analog output, - * the rates are taken from Info.plist - * from Darwin. */ - { - .formats = SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - }, - {} -}; - -static int toonie_usable(struct codec_info_item *cii, - struct transfer_info *ti, - struct transfer_info *out) -{ - return 1; -} - -#ifdef CONFIG_PM -static int toonie_suspend(struct codec_info_item *cii, pm_message_t state) -{ - /* can we turn it off somehow? */ - return 0; -} - -static int toonie_resume(struct codec_info_item *cii) -{ - return 0; -} -#endif /* CONFIG_PM */ - -static struct codec_info toonie_codec_info = { - .transfers = toonie_transfers, - .sysclock_factor = 256, - .bus_factor = 64, - .owner = THIS_MODULE, - .usable = toonie_usable, -#ifdef CONFIG_PM - .suspend = toonie_suspend, - .resume = toonie_resume, -#endif -}; - -static int toonie_init_codec(struct aoa_codec *codec) -{ - struct toonie *toonie = codec_to_toonie(codec); - - /* nothing connected? what a joke! */ - if (toonie->codec.connected != 1) - return -ENOTCONN; - - if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) { - printk(KERN_ERR PFX "failed to create toonie snd device!\n"); - return -ENODEV; - } - - if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev, - aoa_get_card(), - &toonie_codec_info, toonie)) { - printk(KERN_ERR PFX "error creating toonie pcm\n"); - snd_device_free(aoa_get_card(), toonie); - return -ENODEV; - } - - return 0; -} - -static void toonie_exit_codec(struct aoa_codec *codec) -{ - struct toonie *toonie = codec_to_toonie(codec); - - if (!toonie->codec.soundbus_dev) { - printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n"); - return; - } - toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie); -} - -static struct toonie *toonie; - -static int __init toonie_init(void) -{ - toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL); - - if (!toonie) - return -ENOMEM; - - strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); - toonie->codec.owner = THIS_MODULE; - toonie->codec.init = toonie_init_codec; - toonie->codec.exit = toonie_exit_codec; - - if (aoa_codec_register(&toonie->codec)) { - kfree(toonie); - return -EINVAL; - } - - return 0; -} - -static void __exit toonie_exit(void) -{ - aoa_codec_unregister(&toonie->codec); - kfree(toonie); -} - -module_init(toonie_init); -module_exit(toonie_exit); diff --git a/ANDROID_3.4.5/sound/aoa/core/Makefile b/ANDROID_3.4.5/sound/aoa/core/Makefile deleted file mode 100644 index a1596e88..00000000 --- a/ANDROID_3.4.5/sound/aoa/core/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_SND_AOA) += snd-aoa.o -snd-aoa-objs := core.o \ - alsa.o \ - gpio-pmf.o \ - gpio-feature.o diff --git a/ANDROID_3.4.5/sound/aoa/core/alsa.c b/ANDROID_3.4.5/sound/aoa/core/alsa.c deleted file mode 100644 index 0fa3855b..00000000 --- a/ANDROID_3.4.5/sound/aoa/core/alsa.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Apple Onboard Audio Alsa helpers - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ -#include -#include "alsa.h" - -static int index = -1; -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "index for AOA sound card."); - -static struct aoa_card *aoa_card; - -int aoa_alsa_init(char *name, struct module *mod, struct device *dev) -{ - struct snd_card *alsa_card; - int err; - - if (aoa_card) - /* cannot be EEXIST due to usage in aoa_fabric_register */ - return -EBUSY; - - err = snd_card_create(index, name, mod, sizeof(struct aoa_card), - &alsa_card); - if (err < 0) - return err; - aoa_card = alsa_card->private_data; - aoa_card->alsa_card = alsa_card; - alsa_card->dev = dev; - strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); - strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); - strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)); - strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)); - err = snd_card_register(aoa_card->alsa_card); - if (err < 0) { - printk(KERN_ERR "snd-aoa: couldn't register alsa card\n"); - snd_card_free(aoa_card->alsa_card); - aoa_card = NULL; - return err; - } - return 0; -} - -struct snd_card *aoa_get_card(void) -{ - if (aoa_card) - return aoa_card->alsa_card; - return NULL; -} -EXPORT_SYMBOL_GPL(aoa_get_card); - -void aoa_alsa_cleanup(void) -{ - if (aoa_card) { - snd_card_free(aoa_card->alsa_card); - aoa_card = NULL; - } -} - -int aoa_snd_device_new(snd_device_type_t type, - void * device_data, struct snd_device_ops * ops) -{ - struct snd_card *card = aoa_get_card(); - int err; - - if (!card) return -ENOMEM; - - err = snd_device_new(card, type, device_data, ops); - if (err) { - printk(KERN_ERR "snd-aoa: failed to create snd device (%d)\n", err); - return err; - } - err = snd_device_register(card, device_data); - if (err) { - printk(KERN_ERR "snd-aoa: failed to register " - "snd device (%d)\n", err); - printk(KERN_ERR "snd-aoa: have you forgotten the " - "dev_register callback?\n"); - snd_device_free(card, device_data); - } - return err; -} -EXPORT_SYMBOL_GPL(aoa_snd_device_new); - -int aoa_snd_ctl_add(struct snd_kcontrol* control) -{ - int err; - - if (!aoa_card) return -ENODEV; - - err = snd_ctl_add(aoa_card->alsa_card, control); - if (err) - printk(KERN_ERR "snd-aoa: failed to add alsa control (%d)\n", - err); - return err; -} -EXPORT_SYMBOL_GPL(aoa_snd_ctl_add); diff --git a/ANDROID_3.4.5/sound/aoa/core/alsa.h b/ANDROID_3.4.5/sound/aoa/core/alsa.h deleted file mode 100644 index 9669e448..00000000 --- a/ANDROID_3.4.5/sound/aoa/core/alsa.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Apple Onboard Audio Alsa private helpers - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ - -#ifndef __SND_AOA_ALSA_H -#define __SND_AOA_ALSA_H -#include "../aoa.h" - -extern int aoa_alsa_init(char *name, struct module *mod, struct device *dev); -extern void aoa_alsa_cleanup(void); - -#endif /* __SND_AOA_ALSA_H */ diff --git a/ANDROID_3.4.5/sound/aoa/core/core.c b/ANDROID_3.4.5/sound/aoa/core/core.c deleted file mode 100644 index 10bec6c6..00000000 --- a/ANDROID_3.4.5/sound/aoa/core/core.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Apple Onboard Audio driver core - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ - -#include -#include -#include -#include "../aoa.h" -#include "alsa.h" - -MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver"); -MODULE_AUTHOR("Johannes Berg "); -MODULE_LICENSE("GPL"); - -/* We allow only one fabric. This simplifies things, - * and more don't really make that much sense */ -static struct aoa_fabric *fabric; -static LIST_HEAD(codec_list); - -static int attach_codec_to_fabric(struct aoa_codec *c) -{ - int err; - - if (!try_module_get(c->owner)) - return -EBUSY; - /* found_codec has to be assigned */ - err = -ENOENT; - if (fabric->found_codec) - err = fabric->found_codec(c); - if (err) { - module_put(c->owner); - printk(KERN_ERR "snd-aoa: fabric didn't like codec %s\n", - c->name); - return err; - } - c->fabric = fabric; - - err = 0; - if (c->init) - err = c->init(c); - if (err) { - printk(KERN_ERR "snd-aoa: codec %s didn't init\n", c->name); - c->fabric = NULL; - if (fabric->remove_codec) - fabric->remove_codec(c); - module_put(c->owner); - return err; - } - if (fabric->attached_codec) - fabric->attached_codec(c); - return 0; -} - -int aoa_codec_register(struct aoa_codec *codec) -{ - int err = 0; - - /* if there's a fabric already, we can tell if we - * will want to have this codec, so propagate error - * through. Otherwise, this will happen later... */ - if (fabric) - err = attach_codec_to_fabric(codec); - if (!err) - list_add(&codec->list, &codec_list); - return err; -} -EXPORT_SYMBOL_GPL(aoa_codec_register); - -void aoa_codec_unregister(struct aoa_codec *codec) -{ - list_del(&codec->list); - if (codec->fabric && codec->exit) - codec->exit(codec); - if (fabric && fabric->remove_codec) - fabric->remove_codec(codec); - codec->fabric = NULL; - module_put(codec->owner); -} -EXPORT_SYMBOL_GPL(aoa_codec_unregister); - -int aoa_fabric_register(struct aoa_fabric *new_fabric, struct device *dev) -{ - struct aoa_codec *c; - int err; - - /* allow querying for presence of fabric - * (i.e. do this test first!) */ - if (new_fabric == fabric) { - err = -EALREADY; - goto attach; - } - if (fabric) - return -EEXIST; - if (!new_fabric) - return -EINVAL; - - err = aoa_alsa_init(new_fabric->name, new_fabric->owner, dev); - if (err) - return err; - - fabric = new_fabric; - - attach: - list_for_each_entry(c, &codec_list, list) { - if (c->fabric != fabric) - attach_codec_to_fabric(c); - } - return err; -} -EXPORT_SYMBOL_GPL(aoa_fabric_register); - -void aoa_fabric_unregister(struct aoa_fabric *old_fabric) -{ - struct aoa_codec *c; - - if (fabric != old_fabric) - return; - - list_for_each_entry(c, &codec_list, list) { - if (c->fabric) - aoa_fabric_unlink_codec(c); - } - - aoa_alsa_cleanup(); - - fabric = NULL; -} -EXPORT_SYMBOL_GPL(aoa_fabric_unregister); - -void aoa_fabric_unlink_codec(struct aoa_codec *codec) -{ - if (!codec->fabric) { - printk(KERN_ERR "snd-aoa: fabric unassigned " - "in aoa_fabric_unlink_codec\n"); - dump_stack(); - return; - } - if (codec->exit) - codec->exit(codec); - if (codec->fabric->remove_codec) - codec->fabric->remove_codec(codec); - codec->fabric = NULL; - module_put(codec->owner); -} -EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec); - -static int __init aoa_init(void) -{ - return 0; -} - -static void __exit aoa_exit(void) -{ - aoa_alsa_cleanup(); -} - -module_init(aoa_init); -module_exit(aoa_exit); diff --git a/ANDROID_3.4.5/sound/aoa/core/gpio-feature.c b/ANDROID_3.4.5/sound/aoa/core/gpio-feature.c deleted file mode 100644 index faa31749..00000000 --- a/ANDROID_3.4.5/sound/aoa/core/gpio-feature.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Apple Onboard Audio feature call GPIO control - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - * - * This file contains the GPIO control routines for - * direct (through feature calls) access to the GPIO - * registers. - */ - -#include -#include -#include "../aoa.h" - -/* TODO: these are lots of global variables - * that aren't used on most machines... - * Move them into a dynamically allocated - * structure and use that. - */ - -/* these are the GPIO numbers (register addresses as offsets into - * the GPIO space) */ -static int headphone_mute_gpio; -static int master_mute_gpio; -static int amp_mute_gpio; -static int lineout_mute_gpio; -static int hw_reset_gpio; -static int lineout_detect_gpio; -static int headphone_detect_gpio; -static int linein_detect_gpio; - -/* see the SWITCH_GPIO macro */ -static int headphone_mute_gpio_activestate; -static int master_mute_gpio_activestate; -static int amp_mute_gpio_activestate; -static int lineout_mute_gpio_activestate; -static int hw_reset_gpio_activestate; -static int lineout_detect_gpio_activestate; -static int headphone_detect_gpio_activestate; -static int linein_detect_gpio_activestate; - -/* node pointers that we save when getting the GPIO number - * to get the interrupt later */ -static struct device_node *lineout_detect_node; -static struct device_node *linein_detect_node; -static struct device_node *headphone_detect_node; - -static int lineout_detect_irq; -static int linein_detect_irq; -static int headphone_detect_irq; - -static struct device_node *get_gpio(char *name, - char *altname, - int *gpioptr, - int *gpioactiveptr) -{ - struct device_node *np, *gpio; - const u32 *reg; - const char *audio_gpio; - - *gpioptr = -1; - - /* check if we can get it the easy way ... */ - np = of_find_node_by_name(NULL, name); - if (!np) { - /* some machines have only gpioX/extint-gpioX nodes, - * and an audio-gpio property saying what it is ... - * So what we have to do is enumerate all children - * of the gpio node and check them all. */ - gpio = of_find_node_by_name(NULL, "gpio"); - if (!gpio) - return NULL; - while ((np = of_get_next_child(gpio, np))) { - audio_gpio = of_get_property(np, "audio-gpio", NULL); - if (!audio_gpio) - continue; - if (strcmp(audio_gpio, name) == 0) - break; - if (altname && (strcmp(audio_gpio, altname) == 0)) - break; - } - /* still not found, assume not there */ - if (!np) - return NULL; - } - - reg = of_get_property(np, "reg", NULL); - if (!reg) - return NULL; - - *gpioptr = *reg; - - /* this is a hack, usually the GPIOs 'reg' property - * should have the offset based from the GPIO space - * which is at 0x50, but apparently not always... */ - if (*gpioptr < 0x50) - *gpioptr += 0x50; - - reg = of_get_property(np, "audio-gpio-active-state", NULL); - if (!reg) - /* Apple seems to default to 1, but - * that doesn't seem right at least on most - * machines. So until proven that the opposite - * is necessary, we default to 0 - * (which, incidentally, snd-powermac also does...) */ - *gpioactiveptr = 0; - else - *gpioactiveptr = *reg; - - return np; -} - -static void get_irq(struct device_node * np, int *irqptr) -{ - if (np) - *irqptr = irq_of_parse_and_map(np, 0); - else - *irqptr = NO_IRQ; -} - -/* 0x4 is outenable, 0x1 is out, thus 4 or 5 */ -#define SWITCH_GPIO(name, v, on) \ - (((v)&~1) | ((on)? \ - (name##_gpio_activestate==0?4:5): \ - (name##_gpio_activestate==0?5:4))) - -#define FTR_GPIO(name, bit) \ -static void ftr_gpio_set_##name(struct gpio_runtime *rt, int on)\ -{ \ - int v; \ - \ - if (unlikely(!rt)) return; \ - \ - if (name##_mute_gpio < 0) \ - return; \ - \ - v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, \ - name##_mute_gpio, \ - 0); \ - \ - /* muted = !on... */ \ - v = SWITCH_GPIO(name##_mute, v, !on); \ - \ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, \ - name##_mute_gpio, v); \ - \ - rt->implementation_private &= ~(1<implementation_private |= (!!on << bit); \ -} \ -static int ftr_gpio_get_##name(struct gpio_runtime *rt) \ -{ \ - if (unlikely(!rt)) return 0; \ - return (rt->implementation_private>>bit)&1; \ -} - -FTR_GPIO(headphone, 0); -FTR_GPIO(amp, 1); -FTR_GPIO(lineout, 2); -FTR_GPIO(master, 3); - -static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) -{ - int v; - - if (unlikely(!rt)) return; - if (hw_reset_gpio < 0) - return; - - v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, - hw_reset_gpio, 0); - v = SWITCH_GPIO(hw_reset, v, on); - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, - hw_reset_gpio, v); -} - -static struct gpio_methods methods; - -static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) -{ - int saved; - - if (unlikely(!rt)) return; - saved = rt->implementation_private; - ftr_gpio_set_headphone(rt, 0); - ftr_gpio_set_amp(rt, 0); - ftr_gpio_set_lineout(rt, 0); - if (methods.set_master) - ftr_gpio_set_master(rt, 0); - rt->implementation_private = saved; -} - -static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) -{ - int s; - - if (unlikely(!rt)) return; - s = rt->implementation_private; - ftr_gpio_set_headphone(rt, (s>>0)&1); - ftr_gpio_set_amp(rt, (s>>1)&1); - ftr_gpio_set_lineout(rt, (s>>2)&1); - if (methods.set_master) - ftr_gpio_set_master(rt, (s>>3)&1); -} - -static void ftr_handle_notify(struct work_struct *work) -{ - struct gpio_notification *notif = - container_of(work, struct gpio_notification, work.work); - - mutex_lock(¬if->mutex); - if (notif->notify) - notif->notify(notif->data); - mutex_unlock(¬if->mutex); -} - -static void gpio_enable_dual_edge(int gpio) -{ - int v; - - if (gpio == -1) - return; - v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0); - v |= 0x80; /* enable dual edge */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio, v); -} - -static void ftr_gpio_init(struct gpio_runtime *rt) -{ - get_gpio("headphone-mute", NULL, - &headphone_mute_gpio, - &headphone_mute_gpio_activestate); - get_gpio("amp-mute", NULL, - &_mute_gpio, - &_mute_gpio_activestate); - get_gpio("lineout-mute", NULL, - &lineout_mute_gpio, - &lineout_mute_gpio_activestate); - get_gpio("hw-reset", "audio-hw-reset", - &hw_reset_gpio, - &hw_reset_gpio_activestate); - if (get_gpio("master-mute", NULL, - &master_mute_gpio, - &master_mute_gpio_activestate)) { - methods.set_master = ftr_gpio_set_master; - methods.get_master = ftr_gpio_get_master; - } - - headphone_detect_node = get_gpio("headphone-detect", NULL, - &headphone_detect_gpio, - &headphone_detect_gpio_activestate); - /* go Apple, and thanks for giving these different names - * across the board... */ - lineout_detect_node = get_gpio("lineout-detect", "line-output-detect", - &lineout_detect_gpio, - &lineout_detect_gpio_activestate); - linein_detect_node = get_gpio("linein-detect", "line-input-detect", - &linein_detect_gpio, - &linein_detect_gpio_activestate); - - gpio_enable_dual_edge(headphone_detect_gpio); - gpio_enable_dual_edge(lineout_detect_gpio); - gpio_enable_dual_edge(linein_detect_gpio); - - get_irq(headphone_detect_node, &headphone_detect_irq); - get_irq(lineout_detect_node, &lineout_detect_irq); - get_irq(linein_detect_node, &linein_detect_irq); - - ftr_gpio_all_amps_off(rt); - rt->implementation_private = 0; - INIT_DELAYED_WORK(&rt->headphone_notify.work, ftr_handle_notify); - INIT_DELAYED_WORK(&rt->line_in_notify.work, ftr_handle_notify); - INIT_DELAYED_WORK(&rt->line_out_notify.work, ftr_handle_notify); - mutex_init(&rt->headphone_notify.mutex); - mutex_init(&rt->line_in_notify.mutex); - mutex_init(&rt->line_out_notify.mutex); -} - -static void ftr_gpio_exit(struct gpio_runtime *rt) -{ - ftr_gpio_all_amps_off(rt); - rt->implementation_private = 0; - if (rt->headphone_notify.notify) - free_irq(headphone_detect_irq, &rt->headphone_notify); - if (rt->line_in_notify.gpio_private) - free_irq(linein_detect_irq, &rt->line_in_notify); - if (rt->line_out_notify.gpio_private) - free_irq(lineout_detect_irq, &rt->line_out_notify); - cancel_delayed_work_sync(&rt->headphone_notify.work); - cancel_delayed_work_sync(&rt->line_in_notify.work); - cancel_delayed_work_sync(&rt->line_out_notify.work); - mutex_destroy(&rt->headphone_notify.mutex); - mutex_destroy(&rt->line_in_notify.mutex); - mutex_destroy(&rt->line_out_notify.mutex); -} - -static irqreturn_t ftr_handle_notify_irq(int xx, void *data) -{ - struct gpio_notification *notif = data; - - schedule_delayed_work(¬if->work, 0); - - return IRQ_HANDLED; -} - -static int ftr_set_notify(struct gpio_runtime *rt, - enum notify_type type, - notify_func_t notify, - void *data) -{ - struct gpio_notification *notif; - notify_func_t old; - int irq; - char *name; - int err = -EBUSY; - - switch (type) { - case AOA_NOTIFY_HEADPHONE: - notif = &rt->headphone_notify; - name = "headphone-detect"; - irq = headphone_detect_irq; - break; - case AOA_NOTIFY_LINE_IN: - notif = &rt->line_in_notify; - name = "linein-detect"; - irq = linein_detect_irq; - break; - case AOA_NOTIFY_LINE_OUT: - notif = &rt->line_out_notify; - name = "lineout-detect"; - irq = lineout_detect_irq; - break; - default: - return -EINVAL; - } - - if (irq == NO_IRQ) - return -ENODEV; - - mutex_lock(¬if->mutex); - - old = notif->notify; - - if (!old && !notify) { - err = 0; - goto out_unlock; - } - - if (old && notify) { - if (old == notify && notif->data == data) - err = 0; - goto out_unlock; - } - - if (old && !notify) - free_irq(irq, notif); - - if (!old && notify) { - err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif); - if (err) - goto out_unlock; - } - - notif->notify = notify; - notif->data = data; - - err = 0; - out_unlock: - mutex_unlock(¬if->mutex); - return err; -} - -static int ftr_get_detect(struct gpio_runtime *rt, - enum notify_type type) -{ - int gpio, ret, active; - - switch (type) { - case AOA_NOTIFY_HEADPHONE: - gpio = headphone_detect_gpio; - active = headphone_detect_gpio_activestate; - break; - case AOA_NOTIFY_LINE_IN: - gpio = linein_detect_gpio; - active = linein_detect_gpio_activestate; - break; - case AOA_NOTIFY_LINE_OUT: - gpio = lineout_detect_gpio; - active = lineout_detect_gpio_activestate; - break; - default: - return -EINVAL; - } - - if (gpio == -1) - return -ENODEV; - - ret = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0); - if (ret < 0) - return ret; - return ((ret >> 1) & 1) == active; -} - -static struct gpio_methods methods = { - .init = ftr_gpio_init, - .exit = ftr_gpio_exit, - .all_amps_off = ftr_gpio_all_amps_off, - .all_amps_restore = ftr_gpio_all_amps_restore, - .set_headphone = ftr_gpio_set_headphone, - .set_speakers = ftr_gpio_set_amp, - .set_lineout = ftr_gpio_set_lineout, - .set_hw_reset = ftr_gpio_set_hw_reset, - .get_headphone = ftr_gpio_get_headphone, - .get_speakers = ftr_gpio_get_amp, - .get_lineout = ftr_gpio_get_lineout, - .set_notify = ftr_set_notify, - .get_detect = ftr_get_detect, -}; - -struct gpio_methods *ftr_gpio_methods = &methods; -EXPORT_SYMBOL_GPL(ftr_gpio_methods); diff --git a/ANDROID_3.4.5/sound/aoa/core/gpio-pmf.c b/ANDROID_3.4.5/sound/aoa/core/gpio-pmf.c deleted file mode 100644 index c8d8a1a6..00000000 --- a/ANDROID_3.4.5/sound/aoa/core/gpio-pmf.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Apple Onboard Audio pmf GPIOs - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ - -#include -#include -#include -#include "../aoa.h" - -#define PMF_GPIO(name, bit) \ -static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\ -{ \ - struct pmf_args args = { .count = 1, .u[0].v = !on }; \ - int rc; \ - \ - if (unlikely(!rt)) return; \ - rc = pmf_call_function(rt->node, #name "-mute", &args); \ - if (rc && rc != -ENODEV) \ - printk(KERN_WARNING "pmf_gpio_set_" #name \ - " failed, rc: %d\n", rc); \ - rt->implementation_private &= ~(1<implementation_private |= (!!on << bit); \ -} \ -static int pmf_gpio_get_##name(struct gpio_runtime *rt) \ -{ \ - if (unlikely(!rt)) return 0; \ - return (rt->implementation_private>>bit)&1; \ -} - -PMF_GPIO(headphone, 0); -PMF_GPIO(amp, 1); -PMF_GPIO(lineout, 2); - -static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on) -{ - struct pmf_args args = { .count = 1, .u[0].v = !!on }; - int rc; - - if (unlikely(!rt)) return; - rc = pmf_call_function(rt->node, "hw-reset", &args); - if (rc) - printk(KERN_WARNING "pmf_gpio_set_hw_reset" - " failed, rc: %d\n", rc); -} - -static void pmf_gpio_all_amps_off(struct gpio_runtime *rt) -{ - int saved; - - if (unlikely(!rt)) return; - saved = rt->implementation_private; - pmf_gpio_set_headphone(rt, 0); - pmf_gpio_set_amp(rt, 0); - pmf_gpio_set_lineout(rt, 0); - rt->implementation_private = saved; -} - -static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt) -{ - int s; - - if (unlikely(!rt)) return; - s = rt->implementation_private; - pmf_gpio_set_headphone(rt, (s>>0)&1); - pmf_gpio_set_amp(rt, (s>>1)&1); - pmf_gpio_set_lineout(rt, (s>>2)&1); -} - -static void pmf_handle_notify(struct work_struct *work) -{ - struct gpio_notification *notif = - container_of(work, struct gpio_notification, work.work); - - mutex_lock(¬if->mutex); - if (notif->notify) - notif->notify(notif->data); - mutex_unlock(¬if->mutex); -} - -static void pmf_gpio_init(struct gpio_runtime *rt) -{ - pmf_gpio_all_amps_off(rt); - rt->implementation_private = 0; - INIT_DELAYED_WORK(&rt->headphone_notify.work, pmf_handle_notify); - INIT_DELAYED_WORK(&rt->line_in_notify.work, pmf_handle_notify); - INIT_DELAYED_WORK(&rt->line_out_notify.work, pmf_handle_notify); - mutex_init(&rt->headphone_notify.mutex); - mutex_init(&rt->line_in_notify.mutex); - mutex_init(&rt->line_out_notify.mutex); -} - -static void pmf_gpio_exit(struct gpio_runtime *rt) -{ - pmf_gpio_all_amps_off(rt); - rt->implementation_private = 0; - - if (rt->headphone_notify.gpio_private) - pmf_unregister_irq_client(rt->headphone_notify.gpio_private); - if (rt->line_in_notify.gpio_private) - pmf_unregister_irq_client(rt->line_in_notify.gpio_private); - if (rt->line_out_notify.gpio_private) - pmf_unregister_irq_client(rt->line_out_notify.gpio_private); - - /* make sure no work is pending before freeing - * all things */ - cancel_delayed_work_sync(&rt->headphone_notify.work); - cancel_delayed_work_sync(&rt->line_in_notify.work); - cancel_delayed_work_sync(&rt->line_out_notify.work); - - mutex_destroy(&rt->headphone_notify.mutex); - mutex_destroy(&rt->line_in_notify.mutex); - mutex_destroy(&rt->line_out_notify.mutex); - - kfree(rt->headphone_notify.gpio_private); - kfree(rt->line_in_notify.gpio_private); - kfree(rt->line_out_notify.gpio_private); -} - -static void pmf_handle_notify_irq(void *data) -{ - struct gpio_notification *notif = data; - - schedule_delayed_work(¬if->work, 0); -} - -static int pmf_set_notify(struct gpio_runtime *rt, - enum notify_type type, - notify_func_t notify, - void *data) -{ - struct gpio_notification *notif; - notify_func_t old; - struct pmf_irq_client *irq_client; - char *name; - int err = -EBUSY; - - switch (type) { - case AOA_NOTIFY_HEADPHONE: - notif = &rt->headphone_notify; - name = "headphone-detect"; - break; - case AOA_NOTIFY_LINE_IN: - notif = &rt->line_in_notify; - name = "linein-detect"; - break; - case AOA_NOTIFY_LINE_OUT: - notif = &rt->line_out_notify; - name = "lineout-detect"; - break; - default: - return -EINVAL; - } - - mutex_lock(¬if->mutex); - - old = notif->notify; - - if (!old && !notify) { - err = 0; - goto out_unlock; - } - - if (old && notify) { - if (old == notify && notif->data == data) - err = 0; - goto out_unlock; - } - - if (old && !notify) { - irq_client = notif->gpio_private; - pmf_unregister_irq_client(irq_client); - kfree(irq_client); - notif->gpio_private = NULL; - } - if (!old && notify) { - irq_client = kzalloc(sizeof(struct pmf_irq_client), - GFP_KERNEL); - if (!irq_client) { - err = -ENOMEM; - goto out_unlock; - } - irq_client->data = notif; - irq_client->handler = pmf_handle_notify_irq; - irq_client->owner = THIS_MODULE; - err = pmf_register_irq_client(rt->node, - name, - irq_client); - if (err) { - printk(KERN_ERR "snd-aoa: gpio layer failed to" - " register %s irq (%d)\n", name, err); - kfree(irq_client); - goto out_unlock; - } - notif->gpio_private = irq_client; - } - notif->notify = notify; - notif->data = data; - - err = 0; - out_unlock: - mutex_unlock(¬if->mutex); - return err; -} - -static int pmf_get_detect(struct gpio_runtime *rt, - enum notify_type type) -{ - char *name; - int err = -EBUSY, ret; - struct pmf_args args = { .count = 1, .u[0].p = &ret }; - - switch (type) { - case AOA_NOTIFY_HEADPHONE: - name = "headphone-detect"; - break; - case AOA_NOTIFY_LINE_IN: - name = "linein-detect"; - break; - case AOA_NOTIFY_LINE_OUT: - name = "lineout-detect"; - break; - default: - return -EINVAL; - } - - err = pmf_call_function(rt->node, name, &args); - if (err) - return err; - return ret; -} - -static struct gpio_methods methods = { - .init = pmf_gpio_init, - .exit = pmf_gpio_exit, - .all_amps_off = pmf_gpio_all_amps_off, - .all_amps_restore = pmf_gpio_all_amps_restore, - .set_headphone = pmf_gpio_set_headphone, - .set_speakers = pmf_gpio_set_amp, - .set_lineout = pmf_gpio_set_lineout, - .set_hw_reset = pmf_gpio_set_hw_reset, - .get_headphone = pmf_gpio_get_headphone, - .get_speakers = pmf_gpio_get_amp, - .get_lineout = pmf_gpio_get_lineout, - .set_notify = pmf_set_notify, - .get_detect = pmf_get_detect, -}; - -struct gpio_methods *pmf_gpio_methods = &methods; -EXPORT_SYMBOL_GPL(pmf_gpio_methods); diff --git a/ANDROID_3.4.5/sound/aoa/fabrics/Kconfig b/ANDROID_3.4.5/sound/aoa/fabrics/Kconfig deleted file mode 100644 index 3ca475a8..00000000 --- a/ANDROID_3.4.5/sound/aoa/fabrics/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -config SND_AOA_FABRIC_LAYOUT - tristate "layout-id fabric" - select SND_AOA_SOUNDBUS - select SND_AOA_SOUNDBUS_I2S - ---help--- - This enables the layout-id fabric for the Apple Onboard - Audio driver, the module holding it all together - based on the device-tree's layout-id property. - - If you are unsure and have a later Apple machine, - compile it as a module. diff --git a/ANDROID_3.4.5/sound/aoa/fabrics/Makefile b/ANDROID_3.4.5/sound/aoa/fabrics/Makefile deleted file mode 100644 index da37c10e..00000000 --- a/ANDROID_3.4.5/sound/aoa/fabrics/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -snd-aoa-fabric-layout-objs += layout.o - -obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o diff --git a/ANDROID_3.4.5/sound/aoa/fabrics/layout.c b/ANDROID_3.4.5/sound/aoa/fabrics/layout.c deleted file mode 100644 index 552b97af..00000000 --- a/ANDROID_3.4.5/sound/aoa/fabrics/layout.c +++ /dev/null @@ -1,1168 +0,0 @@ -/* - * Apple Onboard Audio driver -- layout/machine id fabric - * - * Copyright 2006-2008 Johannes Berg - * - * GPL v2, can be found in COPYING. - * - * - * This fabric module looks for sound codecs based on the - * layout-id or device-id property in the device tree. - */ -#include -#include -#include -#include -#include "../aoa.h" -#include "../soundbus/soundbus.h" - -MODULE_AUTHOR("Johannes Berg "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa"); - -#define MAX_CODECS_PER_BUS 2 - -/* These are the connections the layout fabric - * knows about. It doesn't really care about the - * input ones, but I thought I'd separate them - * to give them proper names. The thing is that - * Apple usually will distinguish the active output - * by GPIOs, while the active input is set directly - * on the codec. Hence we here tell the codec what - * we think is connected. This information is hard- - * coded below ... */ -#define CC_SPEAKERS (1<<0) -#define CC_HEADPHONE (1<<1) -#define CC_LINEOUT (1<<2) -#define CC_DIGITALOUT (1<<3) -#define CC_LINEIN (1<<4) -#define CC_MICROPHONE (1<<5) -#define CC_DIGITALIN (1<<6) -/* pretty bogus but users complain... - * This is a flag saying that the LINEOUT - * should be renamed to HEADPHONE. - * be careful with input detection! */ -#define CC_LINEOUT_LABELLED_HEADPHONE (1<<7) - -struct codec_connection { - /* CC_ flags from above */ - int connected; - /* codec dependent bit to be set in the aoa_codec.connected field. - * This intentionally doesn't have any generic flags because the - * fabric has to know the codec anyway and all codecs might have - * different connectors */ - int codec_bit; -}; - -struct codec_connect_info { - char *name; - struct codec_connection *connections; -}; - -#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) - -struct layout { - unsigned int layout_id, device_id; - struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; - int flags; - - /* if busname is not assigned, we use 'Master' below, - * so that our layout table doesn't need to be filled - * too much. - * We only assign these two if we expect to find more - * than one soundbus, i.e. on those machines with - * multiple layout-ids */ - char *busname; - int pcmid; -}; - -MODULE_ALIAS("sound-layout-36"); -MODULE_ALIAS("sound-layout-41"); -MODULE_ALIAS("sound-layout-45"); -MODULE_ALIAS("sound-layout-47"); -MODULE_ALIAS("sound-layout-48"); -MODULE_ALIAS("sound-layout-49"); -MODULE_ALIAS("sound-layout-50"); -MODULE_ALIAS("sound-layout-51"); -MODULE_ALIAS("sound-layout-56"); -MODULE_ALIAS("sound-layout-57"); -MODULE_ALIAS("sound-layout-58"); -MODULE_ALIAS("sound-layout-60"); -MODULE_ALIAS("sound-layout-61"); -MODULE_ALIAS("sound-layout-62"); -MODULE_ALIAS("sound-layout-64"); -MODULE_ALIAS("sound-layout-65"); -MODULE_ALIAS("sound-layout-66"); -MODULE_ALIAS("sound-layout-67"); -MODULE_ALIAS("sound-layout-68"); -MODULE_ALIAS("sound-layout-69"); -MODULE_ALIAS("sound-layout-70"); -MODULE_ALIAS("sound-layout-72"); -MODULE_ALIAS("sound-layout-76"); -MODULE_ALIAS("sound-layout-80"); -MODULE_ALIAS("sound-layout-82"); -MODULE_ALIAS("sound-layout-84"); -MODULE_ALIAS("sound-layout-86"); -MODULE_ALIAS("sound-layout-90"); -MODULE_ALIAS("sound-layout-92"); -MODULE_ALIAS("sound-layout-94"); -MODULE_ALIAS("sound-layout-96"); -MODULE_ALIAS("sound-layout-98"); -MODULE_ALIAS("sound-layout-100"); - -MODULE_ALIAS("aoa-device-id-14"); -MODULE_ALIAS("aoa-device-id-22"); -MODULE_ALIAS("aoa-device-id-35"); - -/* onyx with all but microphone connected */ -static struct codec_connection onyx_connections_nomic[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, - .codec_bit = 0, - }, - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* onyx on machines without headphone */ -static struct codec_connection onyx_connections_noheadphones[] = { - { - .connected = CC_SPEAKERS | CC_LINEOUT | - CC_LINEOUT_LABELLED_HEADPHONE, - .codec_bit = 0, - }, - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - /* FIXME: are these correct? probably not for all the machines - * below ... If not this will need separating. */ - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - { - .connected = CC_MICROPHONE, - .codec_bit = 3, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* onyx on machines with real line-out */ -static struct codec_connection onyx_connections_reallineout[] = { - { - .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE, - .codec_bit = 0, - }, - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* tas on machines without line out */ -static struct codec_connection tas_connections_nolineout[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE, - .codec_bit = 0, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - { - .connected = CC_MICROPHONE, - .codec_bit = 3, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* tas on machines with neither line out nor line in */ -static struct codec_connection tas_connections_noline[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE, - .codec_bit = 0, - }, - { - .connected = CC_MICROPHONE, - .codec_bit = 3, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* tas on machines without microphone */ -static struct codec_connection tas_connections_nomic[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, - .codec_bit = 0, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* tas on machines with everything connected */ -static struct codec_connection tas_connections_all[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, - .codec_bit = 0, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - { - .connected = CC_MICROPHONE, - .codec_bit = 3, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct codec_connection toonie_connections[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE, - .codec_bit = 0, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct codec_connection topaz_input[] = { - { - .connected = CC_DIGITALIN, - .codec_bit = 0, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct codec_connection topaz_output[] = { - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct codec_connection topaz_inout[] = { - { - .connected = CC_DIGITALIN, - .codec_bit = 0, - }, - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct layout layouts[] = { - /* last PowerBooks (15" Oct 2005) */ - { .layout_id = 82, - .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerMac9,1 */ - { .layout_id = 60, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_reallineout, - }, - }, - /* PowerMac9,1 */ - { .layout_id = 61, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerBook5,7 */ - { .layout_id = 64, - .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - /* PowerBook5,7 */ - { .layout_id = 65, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerBook5,9 [17" Oct 2005] */ - { .layout_id = 84, - .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerMac8,1 */ - { .layout_id = 45, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* Quad PowerMac (analog in, analog/digital out) */ - { .layout_id = 68, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_nomic, - }, - }, - /* Quad PowerMac (digital in) */ - { .layout_id = 69, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - .busname = "digital in", .pcmid = 1 }, - /* Early 2005 PowerBook (PowerBook 5,6) */ - { .layout_id = 70, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nolineout, - }, - }, - /* PowerBook 5,4 */ - { .layout_id = 51, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nolineout, - }, - }, - /* PowerBook6,7 */ - { .layout_id = 80, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_noline, - }, - }, - /* PowerBook6,8 */ - { .layout_id = 72, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nolineout, - }, - }, - /* PowerMac8,2 */ - { .layout_id = 86, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_nomic, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerBook6,7 */ - { .layout_id = 92, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nolineout, - }, - }, - /* PowerMac10,1 (Mac Mini) */ - { .layout_id = 58, - .codecs[0] = { - .name = "toonie", - .connections = toonie_connections, - }, - }, - { - .layout_id = 96, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - /* unknown, untested, but this comes from Apple */ - { .layout_id = 41, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_all, - }, - }, - { .layout_id = 36, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nomic, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_inout, - }, - }, - { .layout_id = 47, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - { .layout_id = 48, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - { .layout_id = 49, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_nomic, - }, - }, - { .layout_id = 50, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - { .layout_id = 56, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - { .layout_id = 57, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - { .layout_id = 62, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_output, - }, - }, - { .layout_id = 66, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - { .layout_id = 67, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - { .layout_id = 76, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nomic, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_inout, - }, - }, - { .layout_id = 90, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_noline, - }, - }, - { .layout_id = 94, - .codecs[0] = { - .name = "onyx", - /* but it has an external mic?? how to select? */ - .connections = onyx_connections_noheadphones, - }, - }, - { .layout_id = 98, - .codecs[0] = { - .name = "toonie", - .connections = toonie_connections, - }, - }, - { .layout_id = 100, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - .codecs[1] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - /* PowerMac3,4 */ - { .device_id = 14, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_noline, - }, - }, - /* PowerMac3,6 */ - { .device_id = 22, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_all, - }, - }, - /* PowerBook5,2 */ - { .device_id = 35, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_all, - }, - }, - {} -}; - -static struct layout *find_layout_by_id(unsigned int id) -{ - struct layout *l; - - l = layouts; - while (l->codecs[0].name) { - if (l->layout_id == id) - return l; - l++; - } - return NULL; -} - -static struct layout *find_layout_by_device(unsigned int id) -{ - struct layout *l; - - l = layouts; - while (l->codecs[0].name) { - if (l->device_id == id) - return l; - l++; - } - return NULL; -} - -static void use_layout(struct layout *l) -{ - int i; - - for (i=0; icodecs[i].name) { - request_module("snd-aoa-codec-%s", l->codecs[i].name); - } - } - /* now we wait for the codecs to call us back */ -} - -struct layout_dev; - -struct layout_dev_ptr { - struct layout_dev *ptr; -}; - -struct layout_dev { - struct list_head list; - struct soundbus_dev *sdev; - struct device_node *sound; - struct aoa_codec *codecs[MAX_CODECS_PER_BUS]; - struct layout *layout; - struct gpio_runtime gpio; - - /* we need these for headphone/lineout detection */ - struct snd_kcontrol *headphone_ctrl; - struct snd_kcontrol *lineout_ctrl; - struct snd_kcontrol *speaker_ctrl; - struct snd_kcontrol *master_ctrl; - struct snd_kcontrol *headphone_detected_ctrl; - struct snd_kcontrol *lineout_detected_ctrl; - - struct layout_dev_ptr selfptr_headphone; - struct layout_dev_ptr selfptr_lineout; - - u32 have_lineout_detect:1, - have_headphone_detect:1, - switch_on_headphone:1, - switch_on_lineout:1; -}; - -static LIST_HEAD(layouts_list); -static int layouts_list_items; -/* this can go away but only if we allow multiple cards, - * make the fabric handle all the card stuff, etc... */ -static struct layout_dev *layout_device; - -#define control_info snd_ctl_boolean_mono_info - -#define AMP_CONTROL(n, description) \ -static int n##_control_get(struct snd_kcontrol *kcontrol, \ - struct snd_ctl_elem_value *ucontrol) \ -{ \ - struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ - if (gpio->methods && gpio->methods->get_##n) \ - ucontrol->value.integer.value[0] = \ - gpio->methods->get_##n(gpio); \ - return 0; \ -} \ -static int n##_control_put(struct snd_kcontrol *kcontrol, \ - struct snd_ctl_elem_value *ucontrol) \ -{ \ - struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ - if (gpio->methods && gpio->methods->get_##n) \ - gpio->methods->set_##n(gpio, \ - !!ucontrol->value.integer.value[0]); \ - return 1; \ -} \ -static struct snd_kcontrol_new n##_ctl = { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = description, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = control_info, \ - .get = n##_control_get, \ - .put = n##_control_put, \ -} - -AMP_CONTROL(headphone, "Headphone Switch"); -AMP_CONTROL(speakers, "Speakers Switch"); -AMP_CONTROL(lineout, "Line-Out Switch"); -AMP_CONTROL(master, "Master Switch"); - -static int detect_choice_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); - - switch (kcontrol->private_value) { - case 0: - ucontrol->value.integer.value[0] = ldev->switch_on_headphone; - break; - case 1: - ucontrol->value.integer.value[0] = ldev->switch_on_lineout; - break; - default: - return -ENODEV; - } - return 0; -} - -static int detect_choice_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); - - switch (kcontrol->private_value) { - case 0: - ldev->switch_on_headphone = !!ucontrol->value.integer.value[0]; - break; - case 1: - ldev->switch_on_lineout = !!ucontrol->value.integer.value[0]; - break; - default: - return -ENODEV; - } - return 1; -} - -static struct snd_kcontrol_new headphone_detect_choice = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Detect Autoswitch", - .info = control_info, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .get = detect_choice_get, - .put = detect_choice_put, - .private_value = 0, -}; - -static struct snd_kcontrol_new lineout_detect_choice = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line-Out Detect Autoswitch", - .info = control_info, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .get = detect_choice_get, - .put = detect_choice_put, - .private_value = 1, -}; - -static int detected_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); - int v; - - switch (kcontrol->private_value) { - case 0: - v = ldev->gpio.methods->get_detect(&ldev->gpio, - AOA_NOTIFY_HEADPHONE); - break; - case 1: - v = ldev->gpio.methods->get_detect(&ldev->gpio, - AOA_NOTIFY_LINE_OUT); - break; - default: - return -ENODEV; - } - ucontrol->value.integer.value[0] = v; - return 0; -} - -static struct snd_kcontrol_new headphone_detected = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Detected", - .info = control_info, - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .get = detected_get, - .private_value = 0, -}; - -static struct snd_kcontrol_new lineout_detected = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line-Out Detected", - .info = control_info, - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .get = detected_get, - .private_value = 1, -}; - -static int check_codec(struct aoa_codec *codec, - struct layout_dev *ldev, - struct codec_connect_info *cci) -{ - const u32 *ref; - char propname[32]; - struct codec_connection *cc; - - /* if the codec has a 'codec' node, we require a reference */ - if (codec->node && (strcmp(codec->node->name, "codec") == 0)) { - snprintf(propname, sizeof(propname), - "platform-%s-codec-ref", codec->name); - ref = of_get_property(ldev->sound, propname, NULL); - if (!ref) { - printk(KERN_INFO "snd-aoa-fabric-layout: " - "required property %s not present\n", propname); - return -ENODEV; - } - if (*ref != codec->node->phandle) { - printk(KERN_INFO "snd-aoa-fabric-layout: " - "%s doesn't match!\n", propname); - return -ENODEV; - } - } else { - if (layouts_list_items != 1) { - printk(KERN_INFO "snd-aoa-fabric-layout: " - "more than one soundbus, but no references.\n"); - return -ENODEV; - } - } - codec->soundbus_dev = ldev->sdev; - codec->gpio = &ldev->gpio; - - cc = cci->connections; - if (!cc) - return -EINVAL; - - printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n"); - - codec->connected = 0; - codec->fabric_data = cc; - - while (cc->connected) { - codec->connected |= 1<codec_bit; - cc++; - } - - return 0; -} - -static int layout_found_codec(struct aoa_codec *codec) -{ - struct layout_dev *ldev; - int i; - - list_for_each_entry(ldev, &layouts_list, list) { - for (i=0; ilayout->codecs[i].name) - continue; - if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) { - if (check_codec(codec, - ldev, - &ldev->layout->codecs[i]) == 0) - return 0; - } - } - } - return -ENODEV; -} - -static void layout_remove_codec(struct aoa_codec *codec) -{ - int i; - /* here remove the codec from the layout dev's - * codec reference */ - - codec->soundbus_dev = NULL; - codec->gpio = NULL; - for (i=0; iptr; - if (data == &ldev->selfptr_headphone) { - v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE); - detected = ldev->headphone_detected_ctrl; - update = ldev->switch_on_headphone; - if (update) { - ldev->gpio.methods->set_speakers(&ldev->gpio, !v); - ldev->gpio.methods->set_headphone(&ldev->gpio, v); - ldev->gpio.methods->set_lineout(&ldev->gpio, 0); - } - } else if (data == &ldev->selfptr_lineout) { - v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT); - detected = ldev->lineout_detected_ctrl; - update = ldev->switch_on_lineout; - if (update) { - ldev->gpio.methods->set_speakers(&ldev->gpio, !v); - ldev->gpio.methods->set_headphone(&ldev->gpio, 0); - ldev->gpio.methods->set_lineout(&ldev->gpio, v); - } - } else - return; - - if (detected) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id); - if (update) { - c = ldev->headphone_ctrl; - if (c) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); - c = ldev->speaker_ctrl; - if (c) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); - c = ldev->lineout_ctrl; - if (c) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); - } -} - -static void layout_attached_codec(struct aoa_codec *codec) -{ - struct codec_connection *cc; - struct snd_kcontrol *ctl; - int headphones, lineout; - struct layout_dev *ldev = layout_device; - - /* need to add this codec to our codec array! */ - - cc = codec->fabric_data; - - headphones = codec->gpio->methods->get_detect(codec->gpio, - AOA_NOTIFY_HEADPHONE); - lineout = codec->gpio->methods->get_detect(codec->gpio, - AOA_NOTIFY_LINE_OUT); - - if (codec->gpio->methods->set_master) { - ctl = snd_ctl_new1(&master_ctl, codec->gpio); - ldev->master_ctrl = ctl; - aoa_snd_ctl_add(ctl); - } - while (cc->connected) { - if (cc->connected & CC_SPEAKERS) { - if (headphones <= 0 && lineout <= 0) - ldev->gpio.methods->set_speakers(codec->gpio, 1); - ctl = snd_ctl_new1(&speakers_ctl, codec->gpio); - ldev->speaker_ctrl = ctl; - aoa_snd_ctl_add(ctl); - } - if (cc->connected & CC_HEADPHONE) { - if (headphones == 1) - ldev->gpio.methods->set_headphone(codec->gpio, 1); - ctl = snd_ctl_new1(&headphone_ctl, codec->gpio); - ldev->headphone_ctrl = ctl; - aoa_snd_ctl_add(ctl); - ldev->have_headphone_detect = - !ldev->gpio.methods - ->set_notify(&ldev->gpio, - AOA_NOTIFY_HEADPHONE, - layout_notify, - &ldev->selfptr_headphone); - if (ldev->have_headphone_detect) { - ctl = snd_ctl_new1(&headphone_detect_choice, - ldev); - aoa_snd_ctl_add(ctl); - ctl = snd_ctl_new1(&headphone_detected, - ldev); - ldev->headphone_detected_ctrl = ctl; - aoa_snd_ctl_add(ctl); - } - } - if (cc->connected & CC_LINEOUT) { - if (lineout == 1) - ldev->gpio.methods->set_lineout(codec->gpio, 1); - ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); - if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, - "Headphone Switch", sizeof(ctl->id.name)); - ldev->lineout_ctrl = ctl; - aoa_snd_ctl_add(ctl); - ldev->have_lineout_detect = - !ldev->gpio.methods - ->set_notify(&ldev->gpio, - AOA_NOTIFY_LINE_OUT, - layout_notify, - &ldev->selfptr_lineout); - if (ldev->have_lineout_detect) { - ctl = snd_ctl_new1(&lineout_detect_choice, - ldev); - if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, - "Headphone Detect Autoswitch", - sizeof(ctl->id.name)); - aoa_snd_ctl_add(ctl); - ctl = snd_ctl_new1(&lineout_detected, - ldev); - if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, - "Headphone Detected", - sizeof(ctl->id.name)); - ldev->lineout_detected_ctrl = ctl; - aoa_snd_ctl_add(ctl); - } - } - cc++; - } - /* now update initial state */ - if (ldev->have_headphone_detect) - layout_notify(&ldev->selfptr_headphone); - if (ldev->have_lineout_detect) - layout_notify(&ldev->selfptr_lineout); -} - -static struct aoa_fabric layout_fabric = { - .name = "SoundByLayout", - .owner = THIS_MODULE, - .found_codec = layout_found_codec, - .remove_codec = layout_remove_codec, - .attached_codec = layout_attached_codec, -}; - -static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) -{ - struct device_node *sound = NULL; - const unsigned int *id; - struct layout *layout = NULL; - struct layout_dev *ldev = NULL; - int err; - - /* hm, currently we can only have one ... */ - if (layout_device) - return -ENODEV; - - /* by breaking out we keep a reference */ - while ((sound = of_get_next_child(sdev->ofdev.dev.of_node, sound))) { - if (sound->type && strcasecmp(sound->type, "soundchip") == 0) - break; - } - if (!sound) - return -ENODEV; - - id = of_get_property(sound, "layout-id", NULL); - if (id) { - layout = find_layout_by_id(*id); - } else { - id = of_get_property(sound, "device-id", NULL); - if (id) - layout = find_layout_by_device(*id); - } - - if (!layout) { - printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); - goto outnodev; - } - - ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL); - if (!ldev) - goto outnodev; - - layout_device = ldev; - ldev->sdev = sdev; - ldev->sound = sound; - ldev->layout = layout; - ldev->gpio.node = sound->parent; - switch (layout->layout_id) { - case 0: /* anything with device_id, not layout_id */ - case 41: /* that unknown machine no one seems to have */ - case 51: /* PowerBook5,4 */ - case 58: /* Mac Mini */ - ldev->gpio.methods = ftr_gpio_methods; - printk(KERN_DEBUG - "snd-aoa-fabric-layout: Using direct GPIOs\n"); - break; - default: - ldev->gpio.methods = pmf_gpio_methods; - printk(KERN_DEBUG - "snd-aoa-fabric-layout: Using PMF GPIOs\n"); - } - ldev->selfptr_headphone.ptr = ldev; - ldev->selfptr_lineout.ptr = ldev; - dev_set_drvdata(&sdev->ofdev.dev, ldev); - list_add(&ldev->list, &layouts_list); - layouts_list_items++; - - /* assign these before registering ourselves, so - * callbacks that are done during registration - * already have the values */ - sdev->pcmid = ldev->layout->pcmid; - if (ldev->layout->busname) { - sdev->pcmname = ldev->layout->busname; - } else { - sdev->pcmname = "Master"; - } - - ldev->gpio.methods->init(&ldev->gpio); - - err = aoa_fabric_register(&layout_fabric, &sdev->ofdev.dev); - if (err && err != -EALREADY) { - printk(KERN_INFO "snd-aoa-fabric-layout: can't use," - " another fabric is active!\n"); - goto outlistdel; - } - - use_layout(layout); - ldev->switch_on_headphone = 1; - ldev->switch_on_lineout = 1; - return 0; - outlistdel: - /* we won't be using these then... */ - ldev->gpio.methods->exit(&ldev->gpio); - /* reset if we didn't use it */ - sdev->pcmname = NULL; - sdev->pcmid = -1; - list_del(&ldev->list); - layouts_list_items--; - kfree(ldev); - outnodev: - of_node_put(sound); - layout_device = NULL; - return -ENODEV; -} - -static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) -{ - struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); - int i; - - for (i=0; icodecs[i]) { - aoa_fabric_unlink_codec(ldev->codecs[i]); - } - ldev->codecs[i] = NULL; - } - list_del(&ldev->list); - layouts_list_items--; - of_node_put(ldev->sound); - - ldev->gpio.methods->set_notify(&ldev->gpio, - AOA_NOTIFY_HEADPHONE, - NULL, - NULL); - ldev->gpio.methods->set_notify(&ldev->gpio, - AOA_NOTIFY_LINE_OUT, - NULL, - NULL); - - ldev->gpio.methods->exit(&ldev->gpio); - layout_device = NULL; - kfree(ldev); - sdev->pcmid = -1; - sdev->pcmname = NULL; - return 0; -} - -#ifdef CONFIG_PM -static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state) -{ - struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); - - if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) - ldev->gpio.methods->all_amps_off(&ldev->gpio); - - return 0; -} - -static int aoa_fabric_layout_resume(struct soundbus_dev *sdev) -{ - struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); - - if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) - ldev->gpio.methods->all_amps_restore(&ldev->gpio); - - return 0; -} -#endif - -static struct soundbus_driver aoa_soundbus_driver = { - .name = "snd_aoa_soundbus_drv", - .owner = THIS_MODULE, - .probe = aoa_fabric_layout_probe, - .remove = aoa_fabric_layout_remove, -#ifdef CONFIG_PM - .suspend = aoa_fabric_layout_suspend, - .resume = aoa_fabric_layout_resume, -#endif - .driver = { - .owner = THIS_MODULE, - } -}; - -static int __init aoa_fabric_layout_init(void) -{ - int err; - - err = soundbus_register_driver(&aoa_soundbus_driver); - if (err) - return err; - return 0; -} - -static void __exit aoa_fabric_layout_exit(void) -{ - soundbus_unregister_driver(&aoa_soundbus_driver); - aoa_fabric_unregister(&layout_fabric); -} - -module_init(aoa_fabric_layout_init); -module_exit(aoa_fabric_layout_exit); diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/Kconfig b/ANDROID_3.4.5/sound/aoa/soundbus/Kconfig deleted file mode 100644 index 839d1137..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -config SND_AOA_SOUNDBUS - tristate "Apple Soundbus support" - select SND_PCM - ---help--- - This option enables the generic driver for the soundbus - support on Apple machines. - - It is required for the sound bus implementations. - -config SND_AOA_SOUNDBUS_I2S - tristate "I2S bus support" - depends on SND_AOA_SOUNDBUS && PCI - ---help--- - This option enables support for Apple I2S busses. diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/Makefile b/ANDROID_3.4.5/sound/aoa/soundbus/Makefile deleted file mode 100644 index 0e61f5aa..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_SND_AOA_SOUNDBUS) += snd-aoa-soundbus.o -snd-aoa-soundbus-objs := core.o sysfs.o -obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += i2sbus/ diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/core.c b/ANDROID_3.4.5/sound/aoa/soundbus/core.c deleted file mode 100644 index 7487eb76..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/core.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * soundbus - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ - -#include -#include "soundbus.h" - -MODULE_AUTHOR("Johannes Berg "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Apple Soundbus"); - -struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev) -{ - struct device *tmp; - - if (!dev) - return NULL; - tmp = get_device(&dev->ofdev.dev); - if (tmp) - return to_soundbus_device(tmp); - else - return NULL; -} -EXPORT_SYMBOL_GPL(soundbus_dev_get); - -void soundbus_dev_put(struct soundbus_dev *dev) -{ - if (dev) - put_device(&dev->ofdev.dev); -} -EXPORT_SYMBOL_GPL(soundbus_dev_put); - -static int soundbus_probe(struct device *dev) -{ - int error = -ENODEV; - struct soundbus_driver *drv; - struct soundbus_dev *soundbus_dev; - - drv = to_soundbus_driver(dev->driver); - soundbus_dev = to_soundbus_device(dev); - - if (!drv->probe) - return error; - - soundbus_dev_get(soundbus_dev); - - error = drv->probe(soundbus_dev); - if (error) - soundbus_dev_put(soundbus_dev); - - return error; -} - - -static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct soundbus_dev * soundbus_dev; - struct platform_device * of; - const char *compat; - int retval = 0; - int cplen, seen = 0; - - if (!dev) - return -ENODEV; - - soundbus_dev = to_soundbus_device(dev); - if (!soundbus_dev) - return -ENODEV; - - of = &soundbus_dev->ofdev; - - /* stuff we want to pass to /sbin/hotplug */ - retval = add_uevent_var(env, "OF_NAME=%s", of->dev.of_node->name); - if (retval) - return retval; - - retval = add_uevent_var(env, "OF_TYPE=%s", of->dev.of_node->type); - if (retval) - return retval; - - /* Since the compatible field can contain pretty much anything - * it's not really legal to split it out with commas. We split it - * up using a number of environment variables instead. */ - - compat = of_get_property(of->dev.of_node, "compatible", &cplen); - while (compat && cplen > 0) { - int tmp = env->buflen; - retval = add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat); - if (retval) - return retval; - compat += env->buflen - tmp; - cplen -= env->buflen - tmp; - seen += 1; - } - - retval = add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); - if (retval) - return retval; - retval = add_uevent_var(env, "MODALIAS=%s", soundbus_dev->modalias); - - return retval; -} - -static int soundbus_device_remove(struct device *dev) -{ - struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); - struct soundbus_driver * drv = to_soundbus_driver(dev->driver); - - if (dev->driver && drv->remove) - drv->remove(soundbus_dev); - soundbus_dev_put(soundbus_dev); - - return 0; -} - -static void soundbus_device_shutdown(struct device *dev) -{ - struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); - struct soundbus_driver * drv = to_soundbus_driver(dev->driver); - - if (dev->driver && drv->shutdown) - drv->shutdown(soundbus_dev); -} - -#ifdef CONFIG_PM - -static int soundbus_device_suspend(struct device *dev, pm_message_t state) -{ - struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); - struct soundbus_driver * drv = to_soundbus_driver(dev->driver); - - if (dev->driver && drv->suspend) - return drv->suspend(soundbus_dev, state); - return 0; -} - -static int soundbus_device_resume(struct device * dev) -{ - struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); - struct soundbus_driver * drv = to_soundbus_driver(dev->driver); - - if (dev->driver && drv->resume) - return drv->resume(soundbus_dev); - return 0; -} - -#endif /* CONFIG_PM */ - -static struct bus_type soundbus_bus_type = { - .name = "aoa-soundbus", - .probe = soundbus_probe, - .uevent = soundbus_uevent, - .remove = soundbus_device_remove, - .shutdown = soundbus_device_shutdown, -#ifdef CONFIG_PM - .suspend = soundbus_device_suspend, - .resume = soundbus_device_resume, -#endif - .dev_attrs = soundbus_dev_attrs, -}; - -int soundbus_add_one(struct soundbus_dev *dev) -{ - static int devcount; - - /* sanity checks */ - if (!dev->attach_codec || - !dev->ofdev.dev.of_node || - dev->pcmname || - dev->pcmid != -1) { - printk(KERN_ERR "soundbus: adding device failed sanity check!\n"); - return -EINVAL; - } - - dev_set_name(&dev->ofdev.dev, "soundbus:%x", ++devcount); - dev->ofdev.dev.bus = &soundbus_bus_type; - return of_device_register(&dev->ofdev); -} -EXPORT_SYMBOL_GPL(soundbus_add_one); - -void soundbus_remove_one(struct soundbus_dev *dev) -{ - of_device_unregister(&dev->ofdev); -} -EXPORT_SYMBOL_GPL(soundbus_remove_one); - -int soundbus_register_driver(struct soundbus_driver *drv) -{ - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &soundbus_bus_type; - - /* register with core */ - return driver_register(&drv->driver); -} -EXPORT_SYMBOL_GPL(soundbus_register_driver); - -void soundbus_unregister_driver(struct soundbus_driver *drv) -{ - driver_unregister(&drv->driver); -} -EXPORT_SYMBOL_GPL(soundbus_unregister_driver); - -static int __init soundbus_init(void) -{ - return bus_register(&soundbus_bus_type); -} - -static void __exit soundbus_exit(void) -{ - bus_unregister(&soundbus_bus_type); -} - -subsys_initcall(soundbus_init); -module_exit(soundbus_exit); diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/Makefile b/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/Makefile deleted file mode 100644 index 1b949b2a..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o -snd-aoa-i2sbus-objs := core.o pcm.o control.o diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/control.c b/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/control.c deleted file mode 100644 index 4dc9b49c..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/control.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * i2sbus driver -- bus control routines - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "i2sbus.h" - -int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c) -{ - *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL); - if (!*c) - return -ENOMEM; - - INIT_LIST_HEAD(&(*c)->list); - - (*c)->macio = dev->bus->chip; - return 0; -} - -void i2sbus_control_destroy(struct i2sbus_control *c) -{ - kfree(c); -} - -/* this is serialised externally */ -int i2sbus_control_add_dev(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev) -{ - struct device_node *np; - - np = i2sdev->sound.ofdev.dev.of_node; - i2sdev->enable = pmf_find_function(np, "enable"); - i2sdev->cell_enable = pmf_find_function(np, "cell-enable"); - i2sdev->clock_enable = pmf_find_function(np, "clock-enable"); - i2sdev->cell_disable = pmf_find_function(np, "cell-disable"); - i2sdev->clock_disable = pmf_find_function(np, "clock-disable"); - - /* if the bus number is not 0 or 1 we absolutely need to use - * the platform functions -- there's nothing in Darwin that - * would allow seeing a system behind what the FCRs are then, - * and I don't want to go parsing a bunch of platform functions - * by hand to try finding a system... */ - if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 && - (!i2sdev->enable || - !i2sdev->cell_enable || !i2sdev->clock_enable || - !i2sdev->cell_disable || !i2sdev->clock_disable)) { - pmf_put_function(i2sdev->enable); - pmf_put_function(i2sdev->cell_enable); - pmf_put_function(i2sdev->clock_enable); - pmf_put_function(i2sdev->cell_disable); - pmf_put_function(i2sdev->clock_disable); - return -ENODEV; - } - - list_add(&i2sdev->item, &c->list); - - return 0; -} - -void i2sbus_control_remove_dev(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev) -{ - /* this is serialised externally */ - list_del(&i2sdev->item); - if (list_empty(&c->list)) - i2sbus_control_destroy(c); -} - -int i2sbus_control_enable(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev) -{ - struct pmf_args args = { .count = 0 }; - struct macio_chip *macio = c->macio; - - if (i2sdev->enable) - return pmf_call_one(i2sdev->enable, &args); - - if (macio == NULL || macio->base == NULL) - return -ENODEV; - - switch (i2sdev->bus_number) { - case 0: - /* these need to be locked or done through - * newly created feature calls! */ - MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE); - break; - case 1: - MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE); - break; - default: - return -ENODEV; - } - return 0; -} - -int i2sbus_control_cell(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev, - int enable) -{ - struct pmf_args args = { .count = 0 }; - struct macio_chip *macio = c->macio; - - switch (enable) { - case 0: - if (i2sdev->cell_disable) - return pmf_call_one(i2sdev->cell_disable, &args); - break; - case 1: - if (i2sdev->cell_enable) - return pmf_call_one(i2sdev->cell_enable, &args); - break; - default: - printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n"); - return -ENODEV; - } - - if (macio == NULL || macio->base == NULL) - return -ENODEV; - - switch (i2sdev->bus_number) { - case 0: - if (enable) - MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE); - else - MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE); - break; - case 1: - if (enable) - MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE); - else - MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE); - break; - default: - return -ENODEV; - } - return 0; -} - -int i2sbus_control_clock(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev, - int enable) -{ - struct pmf_args args = { .count = 0 }; - struct macio_chip *macio = c->macio; - - switch (enable) { - case 0: - if (i2sdev->clock_disable) - return pmf_call_one(i2sdev->clock_disable, &args); - break; - case 1: - if (i2sdev->clock_enable) - return pmf_call_one(i2sdev->clock_enable, &args); - break; - default: - printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n"); - return -ENODEV; - } - - if (macio == NULL || macio->base == NULL) - return -ENODEV; - - switch (i2sdev->bus_number) { - case 0: - if (enable) - MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT); - else - MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT); - break; - case 1: - if (enable) - MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT); - else - MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT); - break; - default: - return -ENODEV; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/core.c b/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/core.c deleted file mode 100644 index 01065833..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/core.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * i2sbus driver - * - * Copyright 2006-2008 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "../soundbus.h" -#include "i2sbus.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Johannes Berg "); -MODULE_DESCRIPTION("Apple Soundbus: I2S support"); - -static int force; -module_param(force, int, 0444); -MODULE_PARM_DESC(force, "Force loading i2sbus even when" - " no layout-id property is present"); - -static struct of_device_id i2sbus_match[] = { - { .name = "i2s" }, - { } -}; - -MODULE_DEVICE_TABLE(of, i2sbus_match); - -static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, - struct dbdma_command_mem *r, - int numcmds) -{ - /* one more for rounding, one for branch back, one for stop command */ - r->size = (numcmds + 3) * sizeof(struct dbdma_cmd); - /* We use the PCI APIs for now until the generic one gets fixed - * enough or until we get some macio-specific versions - */ - r->space = dma_alloc_coherent( - &macio_get_pci_dev(i2sdev->macio)->dev, - r->size, - &r->bus_addr, - GFP_KERNEL); - - if (!r->space) return -ENOMEM; - - memset(r->space, 0, r->size); - r->cmds = (void*)DBDMA_ALIGN(r->space); - r->bus_cmd_start = r->bus_addr + - (dma_addr_t)((char*)r->cmds - (char*)r->space); - - return 0; -} - -static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, - struct dbdma_command_mem *r) -{ - if (!r->space) return; - - dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev, - r->size, r->space, r->bus_addr); -} - -static void i2sbus_release_dev(struct device *dev) -{ - struct i2sbus_dev *i2sdev; - int i; - - i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev); - - if (i2sdev->intfregs) iounmap(i2sdev->intfregs); - if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma); - if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma); - for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) - if (i2sdev->allocated_resource[i]) - release_and_free_resource(i2sdev->allocated_resource[i]); - free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring); - free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring); - for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) - free_irq(i2sdev->interrupts[i], i2sdev); - i2sbus_control_remove_dev(i2sdev->control, i2sdev); - mutex_destroy(&i2sdev->lock); - kfree(i2sdev); -} - -static irqreturn_t i2sbus_bus_intr(int irq, void *devid) -{ - struct i2sbus_dev *dev = devid; - u32 intreg; - - spin_lock(&dev->low_lock); - intreg = in_le32(&dev->intfregs->intr_ctl); - - /* acknowledge interrupt reasons */ - out_le32(&dev->intfregs->intr_ctl, intreg); - - spin_unlock(&dev->low_lock); - - return IRQ_HANDLED; -} - - -/* - * XXX FIXME: We test the layout_id's here to get the proper way of - * mapping in various registers, thanks to bugs in Apple device-trees. - * We could instead key off the machine model and the name of the i2s - * node (i2s-a). This we'll do when we move it all to macio_asic.c - * and have that export items for each sub-node too. - */ -static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index, - int layout, struct resource *res) -{ - struct device_node *parent; - int pindex, rc = -ENXIO; - const u32 *reg; - - /* Machines with layout 76 and 36 (K2 based) have a weird device - * tree what we need to special case. - * Normal machines just fetch the resource from the i2s-X node. - * Darwin further divides normal machines into old and new layouts - * with a subtely different code path but that doesn't seem necessary - * in practice, they just bloated it. In addition, even on our K2 - * case the i2s-modem node, if we ever want to handle it, uses the - * normal layout - */ - if (layout != 76 && layout != 36) - return of_address_to_resource(np, index, res); - - parent = of_get_parent(np); - pindex = (index == aoa_resource_i2smmio) ? 0 : 1; - rc = of_address_to_resource(parent, pindex, res); - if (rc) - goto bail; - reg = of_get_property(np, "reg", NULL); - if (reg == NULL) { - rc = -ENXIO; - goto bail; - } - res->start += reg[index * 2]; - res->end = res->start + reg[index * 2 + 1] - 1; - bail: - of_node_put(parent); - return rc; -} - -/* FIXME: look at device node refcounting */ -static int i2sbus_add_dev(struct macio_dev *macio, - struct i2sbus_control *control, - struct device_node *np) -{ - struct i2sbus_dev *dev; - struct device_node *child = NULL, *sound = NULL; - struct resource *r; - int i, layout = 0, rlen, ok = force; - static const char *rnames[] = { "i2sbus: %s (control)", - "i2sbus: %s (tx)", - "i2sbus: %s (rx)" }; - static irq_handler_t ints[] = { - i2sbus_bus_intr, - i2sbus_tx_intr, - i2sbus_rx_intr - }; - - if (strlen(np->name) != 5) - return 0; - if (strncmp(np->name, "i2s-", 4)) - return 0; - - dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); - if (!dev) - return 0; - - i = 0; - while ((child = of_get_next_child(np, child))) { - if (strcmp(child->name, "sound") == 0) { - i++; - sound = child; - } - } - if (i == 1) { - const u32 *id = of_get_property(sound, "layout-id", NULL); - - if (id) { - layout = *id; - snprintf(dev->sound.modalias, 32, - "sound-layout-%d", layout); - ok = 1; - } else { - id = of_get_property(sound, "device-id", NULL); - /* - * We probably cannot handle all device-id machines, - * so restrict to those we do handle for now. - */ - if (id && (*id == 22 || *id == 14 || *id == 35)) { - snprintf(dev->sound.modalias, 32, - "aoa-device-id-%d", *id); - ok = 1; - layout = -1; - } - } - } - /* for the time being, until we can handle non-layout-id - * things in some fabric, refuse to attach if there is no - * layout-id property or we haven't been forced to attach. - * When there are two i2s busses and only one has a layout-id, - * then this depends on the order, but that isn't important - * either as the second one in that case is just a modem. */ - if (!ok) { - kfree(dev); - return -ENODEV; - } - - mutex_init(&dev->lock); - spin_lock_init(&dev->low_lock); - dev->sound.ofdev.archdata.dma_mask = macio->ofdev.archdata.dma_mask; - dev->sound.ofdev.dev.of_node = np; - dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.archdata.dma_mask; - dev->sound.ofdev.dev.parent = &macio->ofdev.dev; - dev->sound.ofdev.dev.release = i2sbus_release_dev; - dev->sound.attach_codec = i2sbus_attach_codec; - dev->sound.detach_codec = i2sbus_detach_codec; - dev->sound.pcmid = -1; - dev->macio = macio; - dev->control = control; - dev->bus_number = np->name[4] - 'a'; - INIT_LIST_HEAD(&dev->sound.codec_list); - - for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { - dev->interrupts[i] = -1; - snprintf(dev->rnames[i], sizeof(dev->rnames[i]), - rnames[i], np->name); - } - for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { - int irq = irq_of_parse_and_map(np, i); - if (request_irq(irq, ints[i], 0, dev->rnames[i], dev)) - goto err; - dev->interrupts[i] = irq; - } - - - /* Resource handling is problematic as some device-trees contain - * useless crap (ugh ugh ugh). We work around that here by calling - * specific functions for calculating the appropriate resources. - * - * This will all be moved to macio_asic.c at one point - */ - for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { - if (i2sbus_get_and_fixup_rsrc(np,i,layout,&dev->resources[i])) - goto err; - /* If only we could use our resource dev->resources[i]... - * but request_resource doesn't know about parents and - * contained resources... - */ - dev->allocated_resource[i] = - request_mem_region(dev->resources[i].start, - resource_size(&dev->resources[i]), - dev->rnames[i]); - if (!dev->allocated_resource[i]) { - printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i); - goto err; - } - } - - r = &dev->resources[aoa_resource_i2smmio]; - rlen = resource_size(r); - if (rlen < sizeof(struct i2s_interface_regs)) - goto err; - dev->intfregs = ioremap(r->start, rlen); - - r = &dev->resources[aoa_resource_txdbdma]; - rlen = resource_size(r); - if (rlen < sizeof(struct dbdma_regs)) - goto err; - dev->out.dbdma = ioremap(r->start, rlen); - - r = &dev->resources[aoa_resource_rxdbdma]; - rlen = resource_size(r); - if (rlen < sizeof(struct dbdma_regs)) - goto err; - dev->in.dbdma = ioremap(r->start, rlen); - - if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma) - goto err; - - if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring, - MAX_DBDMA_COMMANDS)) - goto err; - if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring, - MAX_DBDMA_COMMANDS)) - goto err; - - if (i2sbus_control_add_dev(dev->control, dev)) { - printk(KERN_ERR "i2sbus: control layer didn't like bus\n"); - goto err; - } - - if (soundbus_add_one(&dev->sound)) { - printk(KERN_DEBUG "i2sbus: device registration error!\n"); - goto err; - } - - /* enable this cell */ - i2sbus_control_cell(dev->control, dev, 1); - i2sbus_control_enable(dev->control, dev); - i2sbus_control_clock(dev->control, dev, 1); - - return 1; - err: - for (i=0;i<3;i++) - if (dev->interrupts[i] != -1) - free_irq(dev->interrupts[i], dev); - free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring); - free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring); - if (dev->intfregs) iounmap(dev->intfregs); - if (dev->out.dbdma) iounmap(dev->out.dbdma); - if (dev->in.dbdma) iounmap(dev->in.dbdma); - for (i=0;i<3;i++) - if (dev->allocated_resource[i]) - release_and_free_resource(dev->allocated_resource[i]); - mutex_destroy(&dev->lock); - kfree(dev); - return 0; -} - -static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match) -{ - struct device_node *np = NULL; - int got = 0, err; - struct i2sbus_control *control = NULL; - - err = i2sbus_control_init(dev, &control); - if (err) - return err; - if (!control) { - printk(KERN_ERR "i2sbus_control_init API breakage\n"); - return -ENODEV; - } - - while ((np = of_get_next_child(dev->ofdev.dev.of_node, np))) { - if (of_device_is_compatible(np, "i2sbus") || - of_device_is_compatible(np, "i2s-modem")) { - got += i2sbus_add_dev(dev, control, np); - } - } - - if (!got) { - /* found none, clean up */ - i2sbus_control_destroy(control); - return -ENODEV; - } - - dev_set_drvdata(&dev->ofdev.dev, control); - - return 0; -} - -static int i2sbus_remove(struct macio_dev* dev) -{ - struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev); - struct i2sbus_dev *i2sdev, *tmp; - - list_for_each_entry_safe(i2sdev, tmp, &control->list, item) - soundbus_remove_one(&i2sdev->sound); - - return 0; -} - -#ifdef CONFIG_PM -static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state) -{ - struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev); - struct codec_info_item *cii; - struct i2sbus_dev* i2sdev; - int err, ret = 0; - - list_for_each_entry(i2sdev, &control->list, item) { - /* Notify Alsa */ - if (i2sdev->sound.pcm) { - /* Suspend PCM streams */ - snd_pcm_suspend_all(i2sdev->sound.pcm); - } - - /* Notify codecs */ - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { - err = 0; - if (cii->codec->suspend) - err = cii->codec->suspend(cii, state); - if (err) - ret = err; - } - - /* wait until streams are stopped */ - i2sbus_wait_for_stop_both(i2sdev); - } - - return ret; -} - -static int i2sbus_resume(struct macio_dev* dev) -{ - struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev); - struct codec_info_item *cii; - struct i2sbus_dev* i2sdev; - int err, ret = 0; - - list_for_each_entry(i2sdev, &control->list, item) { - /* reset i2s bus format etc. */ - i2sbus_pcm_prepare_both(i2sdev); - - /* Notify codecs so they can re-initialize */ - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { - err = 0; - if (cii->codec->resume) - err = cii->codec->resume(cii); - if (err) - ret = err; - } - } - - return ret; -} -#endif /* CONFIG_PM */ - -static int i2sbus_shutdown(struct macio_dev* dev) -{ - return 0; -} - -static struct macio_driver i2sbus_drv = { - .driver = { - .name = "soundbus-i2s", - .owner = THIS_MODULE, - .of_match_table = i2sbus_match, - }, - .probe = i2sbus_probe, - .remove = i2sbus_remove, -#ifdef CONFIG_PM - .suspend = i2sbus_suspend, - .resume = i2sbus_resume, -#endif - .shutdown = i2sbus_shutdown, -}; - -static int __init soundbus_i2sbus_init(void) -{ - return macio_register_driver(&i2sbus_drv); -} - -static void __exit soundbus_i2sbus_exit(void) -{ - macio_unregister_driver(&i2sbus_drv); -} - -module_init(soundbus_i2sbus_init); -module_exit(soundbus_i2sbus_exit); diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/i2sbus.h b/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/i2sbus.h deleted file mode 100644 index befefd99..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/i2sbus.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * i2sbus driver -- private definitions - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ -#ifndef __I2SBUS_H -#define __I2SBUS_H -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "interface.h" -#include "../soundbus.h" - -struct i2sbus_control { - struct list_head list; - struct macio_chip *macio; -}; - -#define MAX_DBDMA_COMMANDS 32 - -struct dbdma_command_mem { - dma_addr_t bus_addr; - dma_addr_t bus_cmd_start; - struct dbdma_cmd *cmds; - void *space; - int size; - u32 running:1; - u32 stopping:1; -}; - -struct pcm_info { - u32 created:1, /* has this direction been created with alsa? */ - active:1; /* is this stream active? */ - /* runtime information */ - struct snd_pcm_substream *substream; - int current_period; - u32 frame_count; - struct dbdma_command_mem dbdma_ring; - volatile struct dbdma_regs __iomem *dbdma; - struct completion *stop_completion; -}; - -enum { - aoa_resource_i2smmio = 0, - aoa_resource_txdbdma, - aoa_resource_rxdbdma, -}; - -struct i2sbus_dev { - struct soundbus_dev sound; - struct macio_dev *macio; - struct i2sbus_control *control; - volatile struct i2s_interface_regs __iomem *intfregs; - - struct resource resources[3]; - struct resource *allocated_resource[3]; - int interrupts[3]; - char rnames[3][32]; - - /* info about currently active substreams */ - struct pcm_info out, in; - snd_pcm_format_t format; - unsigned int rate; - - /* list for a single controller */ - struct list_head item; - /* number of bus on controller */ - int bus_number; - /* for use by control layer */ - struct pmf_function *enable, - *cell_enable, - *cell_disable, - *clock_enable, - *clock_disable; - - /* locks */ - /* spinlock for low-level interrupt locking */ - spinlock_t low_lock; - /* mutex for high-level consistency */ - struct mutex lock; -}; - -#define soundbus_dev_to_i2sbus_dev(sdev) \ - container_of(sdev, struct i2sbus_dev, sound) - -/* pcm specific functions */ -extern int -i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, - struct codec_info *ci, void *data); -extern void -i2sbus_detach_codec(struct soundbus_dev *dev, void *data); -extern irqreturn_t -i2sbus_tx_intr(int irq, void *devid); -extern irqreturn_t -i2sbus_rx_intr(int irq, void *devid); - -extern void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev); -extern void i2sbus_pcm_prepare_both(struct i2sbus_dev *i2sdev); - -/* control specific functions */ -extern int i2sbus_control_init(struct macio_dev* dev, - struct i2sbus_control **c); -extern void i2sbus_control_destroy(struct i2sbus_control *c); -extern int i2sbus_control_add_dev(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev); -extern void i2sbus_control_remove_dev(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev); -extern int i2sbus_control_enable(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev); -extern int i2sbus_control_cell(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev, - int enable); -extern int i2sbus_control_clock(struct i2sbus_control *c, - struct i2sbus_dev *i2sdev, - int enable); -#endif /* __I2SBUS_H */ diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/interface.h b/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/interface.h deleted file mode 100644 index c6b5f545..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/i2sbus/interface.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * i2sbus driver -- interface register definitions - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ -#ifndef __I2SBUS_INTERFACE_H -#define __I2SBUS_INTERFACE_H - -/* i2s bus control registers, at least what we know about them */ - -#define __PAD(m,n) u8 __pad##m[n] -#define _PAD(line, n) __PAD(line, n) -#define PAD(n) _PAD(__LINE__, (n)) -struct i2s_interface_regs { - __le32 intr_ctl; /* 0x00 */ - PAD(12); - __le32 serial_format; /* 0x10 */ - PAD(12); - __le32 codec_msg_out; /* 0x20 */ - PAD(12); - __le32 codec_msg_in; /* 0x30 */ - PAD(12); - __le32 frame_count; /* 0x40 */ - PAD(12); - __le32 frame_match; /* 0x50 */ - PAD(12); - __le32 data_word_sizes; /* 0x60 */ - PAD(12); - __le32 peak_level_sel; /* 0x70 */ - PAD(12); - __le32 peak_level_in0; /* 0x80 */ - PAD(12); - __le32 peak_level_in1; /* 0x90 */ - PAD(12); - /* total size: 0x100 bytes */ -} __attribute__((__packed__)); - -/* interrupt register is just a bitfield with - * interrupt enable and pending bits */ -#define I2S_REG_INTR_CTL 0x00 -# define I2S_INT_FRAME_COUNT (1<<31) -# define I2S_PENDING_FRAME_COUNT (1<<30) -# define I2S_INT_MESSAGE_FLAG (1<<29) -# define I2S_PENDING_MESSAGE_FLAG (1<<28) -# define I2S_INT_NEW_PEAK (1<<27) -# define I2S_PENDING_NEW_PEAK (1<<26) -# define I2S_INT_CLOCKS_STOPPED (1<<25) -# define I2S_PENDING_CLOCKS_STOPPED (1<<24) -# define I2S_INT_EXTERNAL_SYNC_ERROR (1<<23) -# define I2S_PENDING_EXTERNAL_SYNC_ERROR (1<<22) -# define I2S_INT_EXTERNAL_SYNC_OK (1<<21) -# define I2S_PENDING_EXTERNAL_SYNC_OK (1<<20) -# define I2S_INT_NEW_SAMPLE_RATE (1<<19) -# define I2S_PENDING_NEW_SAMPLE_RATE (1<<18) -# define I2S_INT_STATUS_FLAG (1<<17) -# define I2S_PENDING_STATUS_FLAG (1<<16) - -/* serial format register is more interesting :) - * It contains: - * - clock source - * - MClk divisor - * - SClk divisor - * - SClk master flag - * - serial format (sony, i2s 64x, i2s 32x, dav, silabs) - * - external sample frequency interrupt (don't understand) - * - external sample frequency - */ -#define I2S_REG_SERIAL_FORMAT 0x10 -/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */ -# define I2S_SF_CLOCK_SOURCE_SHIFT 30 -# define I2S_SF_CLOCK_SOURCE_MASK (3< - * - * GPL v2, can be found in COPYING. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "../soundbus.h" -#include "i2sbus.h" - -static inline void get_pcm_info(struct i2sbus_dev *i2sdev, int in, - struct pcm_info **pi, struct pcm_info **other) -{ - if (in) { - if (pi) - *pi = &i2sdev->in; - if (other) - *other = &i2sdev->out; - } else { - if (pi) - *pi = &i2sdev->out; - if (other) - *other = &i2sdev->in; - } -} - -static int clock_and_divisors(int mclk, int sclk, int rate, int *out) -{ - /* sclk must be derived from mclk! */ - if (mclk % sclk) - return -1; - /* derive sclk register value */ - if (i2s_sf_sclkdiv(mclk / sclk, out)) - return -1; - - if (I2S_CLOCK_SPEED_18MHz % (rate * mclk) == 0) { - if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) { - *out |= I2S_SF_CLOCK_SOURCE_18MHz; - return 0; - } - } - if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) { - if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) { - *out |= I2S_SF_CLOCK_SOURCE_45MHz; - return 0; - } - } - if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) { - if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) { - *out |= I2S_SF_CLOCK_SOURCE_49MHz; - return 0; - } - } - return -1; -} - -#define CHECK_RATE(rate) \ - do { if (rates & SNDRV_PCM_RATE_ ##rate) { \ - int dummy; \ - if (clock_and_divisors(sysclock_factor, \ - bus_factor, rate, &dummy)) \ - rates &= ~SNDRV_PCM_RATE_ ##rate; \ - } } while (0) - -static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) -{ - struct pcm_info *pi, *other; - struct soundbus_dev *sdev; - int masks_inited = 0, err; - struct codec_info_item *cii, *rev; - struct snd_pcm_hardware *hw; - u64 formats = 0; - unsigned int rates = 0; - struct transfer_info v; - int result = 0; - int bus_factor = 0, sysclock_factor = 0; - int found_this; - - mutex_lock(&i2sdev->lock); - - get_pcm_info(i2sdev, in, &pi, &other); - - hw = &pi->substream->runtime->hw; - sdev = &i2sdev->sound; - - if (pi->active) { - /* alsa messed up */ - result = -EBUSY; - goto out_unlock; - } - - /* we now need to assign the hw */ - list_for_each_entry(cii, &sdev->codec_list, list) { - struct transfer_info *ti = cii->codec->transfers; - bus_factor = cii->codec->bus_factor; - sysclock_factor = cii->codec->sysclock_factor; - while (ti->formats && ti->rates) { - v = *ti; - if (ti->transfer_in == in - && cii->codec->usable(cii, ti, &v)) { - if (masks_inited) { - formats &= v.formats; - rates &= v.rates; - } else { - formats = v.formats; - rates = v.rates; - masks_inited = 1; - } - } - ti++; - } - } - if (!masks_inited || !bus_factor || !sysclock_factor) { - result = -ENODEV; - goto out_unlock; - } - /* bus dependent stuff */ - hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_JOINT_DUPLEX; - - CHECK_RATE(5512); - CHECK_RATE(8000); - CHECK_RATE(11025); - CHECK_RATE(16000); - CHECK_RATE(22050); - CHECK_RATE(32000); - CHECK_RATE(44100); - CHECK_RATE(48000); - CHECK_RATE(64000); - CHECK_RATE(88200); - CHECK_RATE(96000); - CHECK_RATE(176400); - CHECK_RATE(192000); - hw->rates = rates; - - /* well. the codec might want 24 bits only, and we'll - * ever only transfer 24 bits, but they are top-aligned! - * So for alsa, we claim that we're doing full 32 bit - * while in reality we'll ignore the lower 8 bits of - * that when doing playback (they're transferred as 0 - * as far as I know, no codecs we have are 32-bit capable - * so I can't really test) and when doing recording we'll - * always have those lower 8 bits recorded as 0 */ - if (formats & SNDRV_PCM_FMTBIT_S24_BE) - formats |= SNDRV_PCM_FMTBIT_S32_BE; - if (formats & SNDRV_PCM_FMTBIT_U24_BE) - formats |= SNDRV_PCM_FMTBIT_U32_BE; - /* now mask off what we can support. I suppose we could - * also support S24_3LE and some similar formats, but I - * doubt there's a codec that would be able to use that, - * so we don't support it here. */ - hw->formats = formats & (SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_U16_BE | - SNDRV_PCM_FMTBIT_S32_BE | - SNDRV_PCM_FMTBIT_U32_BE); - - /* we need to set the highest and lowest rate possible. - * These are the highest and lowest rates alsa can - * support properly in its bitfield. - * Below, we'll use that to restrict to the rate - * currently in use (if any). */ - hw->rate_min = 5512; - hw->rate_max = 192000; - /* if the other stream is active, then we can only - * support what it is currently using. - * FIXME: I lied. This comment is wrong. We can support - * anything that works with the same serial format, ie. - * when recording 24 bit sound we can well play 16 bit - * sound at the same time iff using the same transfer mode. - */ - if (other->active) { - /* FIXME: is this guaranteed by the alsa api? */ - hw->formats &= (1ULL << i2sdev->format); - /* see above, restrict rates to the one we already have */ - hw->rate_min = i2sdev->rate; - hw->rate_max = i2sdev->rate; - } - - hw->channels_min = 2; - hw->channels_max = 2; - /* these are somewhat arbitrary */ - hw->buffer_bytes_max = 131072; - hw->period_bytes_min = 256; - hw->period_bytes_max = 16384; - hw->periods_min = 3; - hw->periods_max = MAX_DBDMA_COMMANDS; - err = snd_pcm_hw_constraint_integer(pi->substream->runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - result = err; - goto out_unlock; - } - list_for_each_entry(cii, &sdev->codec_list, list) { - if (cii->codec->open) { - err = cii->codec->open(cii, pi->substream); - if (err) { - result = err; - /* unwind */ - found_this = 0; - list_for_each_entry_reverse(rev, - &sdev->codec_list, list) { - if (found_this && rev->codec->close) { - rev->codec->close(rev, - pi->substream); - } - if (rev == cii) - found_this = 1; - } - goto out_unlock; - } - } - } - - out_unlock: - mutex_unlock(&i2sdev->lock); - return result; -} - -#undef CHECK_RATE - -static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) -{ - struct codec_info_item *cii; - struct pcm_info *pi; - int err = 0, tmp; - - mutex_lock(&i2sdev->lock); - - get_pcm_info(i2sdev, in, &pi, NULL); - - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { - if (cii->codec->close) { - tmp = cii->codec->close(cii, pi->substream); - if (tmp) - err = tmp; - } - } - - pi->substream = NULL; - pi->active = 0; - mutex_unlock(&i2sdev->lock); - return err; -} - -static void i2sbus_wait_for_stop(struct i2sbus_dev *i2sdev, - struct pcm_info *pi) -{ - unsigned long flags; - struct completion done; - long timeout; - - spin_lock_irqsave(&i2sdev->low_lock, flags); - if (pi->dbdma_ring.stopping) { - init_completion(&done); - pi->stop_completion = &done; - spin_unlock_irqrestore(&i2sdev->low_lock, flags); - timeout = wait_for_completion_timeout(&done, HZ); - spin_lock_irqsave(&i2sdev->low_lock, flags); - pi->stop_completion = NULL; - if (timeout == 0) { - /* timeout expired, stop dbdma forcefully */ - printk(KERN_ERR "i2sbus_wait_for_stop: timed out\n"); - /* make sure RUN, PAUSE and S0 bits are cleared */ - out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16); - pi->dbdma_ring.stopping = 0; - timeout = 10; - while (in_le32(&pi->dbdma->status) & ACTIVE) { - if (--timeout <= 0) - break; - udelay(1); - } - } - } - spin_unlock_irqrestore(&i2sdev->low_lock, flags); -} - -#ifdef CONFIG_PM -void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev) -{ - struct pcm_info *pi; - - get_pcm_info(i2sdev, 0, &pi, NULL); - i2sbus_wait_for_stop(i2sdev, pi); - get_pcm_info(i2sdev, 1, &pi, NULL); - i2sbus_wait_for_stop(i2sdev, pi); -} -#endif - -static int i2sbus_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); -} - -static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - struct pcm_info *pi; - - get_pcm_info(i2sdev, in, &pi, NULL); - if (pi->dbdma_ring.stopping) - i2sbus_wait_for_stop(i2sdev, pi); - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int i2sbus_playback_hw_free(struct snd_pcm_substream *substream) -{ - return i2sbus_hw_free(substream, 0); -} - -static int i2sbus_record_hw_free(struct snd_pcm_substream *substream) -{ - return i2sbus_hw_free(substream, 1); -} - -static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) -{ - /* whee. Hard work now. The user has selected a bitrate - * and bit format, so now we have to program our - * I2S controller appropriately. */ - struct snd_pcm_runtime *runtime; - struct dbdma_cmd *command; - int i, periodsize, nperiods; - dma_addr_t offset; - struct bus_info bi; - struct codec_info_item *cii; - int sfr = 0; /* serial format register */ - int dws = 0; /* data word sizes reg */ - int input_16bit; - struct pcm_info *pi, *other; - int cnt; - int result = 0; - unsigned int cmd, stopaddr; - - mutex_lock(&i2sdev->lock); - - get_pcm_info(i2sdev, in, &pi, &other); - - if (pi->dbdma_ring.running) { - result = -EBUSY; - goto out_unlock; - } - if (pi->dbdma_ring.stopping) - i2sbus_wait_for_stop(i2sdev, pi); - - if (!pi->substream || !pi->substream->runtime) { - result = -EINVAL; - goto out_unlock; - } - - runtime = pi->substream->runtime; - pi->active = 1; - if (other->active && - ((i2sdev->format != runtime->format) - || (i2sdev->rate != runtime->rate))) { - result = -EINVAL; - goto out_unlock; - } - - i2sdev->format = runtime->format; - i2sdev->rate = runtime->rate; - - periodsize = snd_pcm_lib_period_bytes(pi->substream); - nperiods = pi->substream->runtime->periods; - pi->current_period = 0; - - /* generate dbdma command ring first */ - command = pi->dbdma_ring.cmds; - memset(command, 0, (nperiods + 2) * sizeof(struct dbdma_cmd)); - - /* commands to DMA to/from the ring */ - /* - * For input, we need to do a graceful stop; if we abort - * the DMA, we end up with leftover bytes that corrupt - * the next recording. To do this we set the S0 status - * bit and wait for the DMA controller to stop. Each - * command has a branch condition to - * make it branch to a stop command if S0 is set. - * On input we also need to wait for the S7 bit to be - * set before turning off the DMA controller. - * In fact we do the graceful stop for output as well. - */ - offset = runtime->dma_addr; - cmd = (in? INPUT_MORE: OUTPUT_MORE) | BR_IFSET | INTR_ALWAYS; - stopaddr = pi->dbdma_ring.bus_cmd_start + - (nperiods + 1) * sizeof(struct dbdma_cmd); - for (i = 0; i < nperiods; i++, command++, offset += periodsize) { - command->command = cpu_to_le16(cmd); - command->cmd_dep = cpu_to_le32(stopaddr); - command->phy_addr = cpu_to_le32(offset); - command->req_count = cpu_to_le16(periodsize); - } - - /* branch back to beginning of ring */ - command->command = cpu_to_le16(DBDMA_NOP | BR_ALWAYS); - command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start); - command++; - - /* set stop command */ - command->command = cpu_to_le16(DBDMA_STOP); - - /* ok, let's set the serial format and stuff */ - switch (runtime->format) { - /* 16 bit formats */ - case SNDRV_PCM_FORMAT_S16_BE: - case SNDRV_PCM_FORMAT_U16_BE: - /* FIXME: if we add different bus factors we need to - * do more here!! */ - bi.bus_factor = 0; - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { - bi.bus_factor = cii->codec->bus_factor; - break; - } - if (!bi.bus_factor) { - result = -ENODEV; - goto out_unlock; - } - input_16bit = 1; - break; - case SNDRV_PCM_FORMAT_S32_BE: - case SNDRV_PCM_FORMAT_U32_BE: - /* force 64x bus speed, otherwise the data cannot be - * transferred quickly enough! */ - bi.bus_factor = 64; - input_16bit = 0; - break; - default: - result = -EINVAL; - goto out_unlock; - } - /* we assume all sysclocks are the same! */ - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { - bi.sysclock_factor = cii->codec->sysclock_factor; - break; - } - - if (clock_and_divisors(bi.sysclock_factor, - bi.bus_factor, - runtime->rate, - &sfr) < 0) { - result = -EINVAL; - goto out_unlock; - } - switch (bi.bus_factor) { - case 32: - sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X; - break; - case 64: - sfr |= I2S_SF_SERIAL_FORMAT_I2S_64X; - break; - } - /* FIXME: THIS ASSUMES MASTER ALL THE TIME */ - sfr |= I2S_SF_SCLK_MASTER; - - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { - int err = 0; - if (cii->codec->prepare) - err = cii->codec->prepare(cii, &bi, pi->substream); - if (err) { - result = err; - goto out_unlock; - } - } - /* codecs are fine with it, so set our clocks */ - if (input_16bit) - dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | - (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | - I2S_DWS_DATA_IN_16BIT | I2S_DWS_DATA_OUT_16BIT; - else - dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | - (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | - I2S_DWS_DATA_IN_24BIT | I2S_DWS_DATA_OUT_24BIT; - - /* early exit if already programmed correctly */ - /* not locking these is fine since we touch them only in this function */ - if (in_le32(&i2sdev->intfregs->serial_format) == sfr - && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) - goto out_unlock; - - /* let's notify the codecs about clocks going away. - * For now we only do mastering on the i2s cell... */ - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) - if (cii->codec->switch_clock) - cii->codec->switch_clock(cii, CLOCK_SWITCH_PREPARE_SLAVE); - - i2sbus_control_enable(i2sdev->control, i2sdev); - i2sbus_control_cell(i2sdev->control, i2sdev, 1); - - out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); - - i2sbus_control_clock(i2sdev->control, i2sdev, 0); - - msleep(1); - - /* wait for clock stopped. This can apparently take a while... */ - cnt = 100; - while (cnt-- && - !(in_le32(&i2sdev->intfregs->intr_ctl) & I2S_PENDING_CLOCKS_STOPPED)) { - msleep(5); - } - out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); - - /* not locking these is fine since we touch them only in this function */ - out_le32(&i2sdev->intfregs->serial_format, sfr); - out_le32(&i2sdev->intfregs->data_word_sizes, dws); - - i2sbus_control_enable(i2sdev->control, i2sdev); - i2sbus_control_cell(i2sdev->control, i2sdev, 1); - i2sbus_control_clock(i2sdev->control, i2sdev, 1); - msleep(1); - - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) - if (cii->codec->switch_clock) - cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); - - out_unlock: - mutex_unlock(&i2sdev->lock); - return result; -} - -#ifdef CONFIG_PM -void i2sbus_pcm_prepare_both(struct i2sbus_dev *i2sdev) -{ - i2sbus_pcm_prepare(i2sdev, 0); - i2sbus_pcm_prepare(i2sdev, 1); -} -#endif - -static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) -{ - struct codec_info_item *cii; - struct pcm_info *pi; - int result = 0; - unsigned long flags; - - spin_lock_irqsave(&i2sdev->low_lock, flags); - - get_pcm_info(i2sdev, in, &pi, NULL); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (pi->dbdma_ring.running) { - result = -EALREADY; - goto out_unlock; - } - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) - if (cii->codec->start) - cii->codec->start(cii, pi->substream); - pi->dbdma_ring.running = 1; - - if (pi->dbdma_ring.stopping) { - /* Clear the S0 bit, then see if we stopped yet */ - out_le32(&pi->dbdma->control, 1 << 16); - if (in_le32(&pi->dbdma->status) & ACTIVE) { - /* possible race here? */ - udelay(10); - if (in_le32(&pi->dbdma->status) & ACTIVE) { - pi->dbdma_ring.stopping = 0; - goto out_unlock; /* keep running */ - } - } - } - - /* make sure RUN, PAUSE and S0 bits are cleared */ - out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16); - - /* set branch condition select register */ - out_le32(&pi->dbdma->br_sel, (1 << 16) | 1); - - /* write dma command buffer address to the dbdma chip */ - out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); - - /* initialize the frame count and current period */ - pi->current_period = 0; - pi->frame_count = in_le32(&i2sdev->intfregs->frame_count); - - /* set the DMA controller running */ - out_le32(&pi->dbdma->control, (RUN << 16) | RUN); - - /* off you go! */ - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (!pi->dbdma_ring.running) { - result = -EALREADY; - goto out_unlock; - } - pi->dbdma_ring.running = 0; - - /* Set the S0 bit to make the DMA branch to the stop cmd */ - out_le32(&pi->dbdma->control, (1 << 16) | 1); - pi->dbdma_ring.stopping = 1; - - list_for_each_entry(cii, &i2sdev->sound.codec_list, list) - if (cii->codec->stop) - cii->codec->stop(cii, pi->substream); - break; - default: - result = -EINVAL; - goto out_unlock; - } - - out_unlock: - spin_unlock_irqrestore(&i2sdev->low_lock, flags); - return result; -} - -static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in) -{ - struct pcm_info *pi; - u32 fc; - - get_pcm_info(i2sdev, in, &pi, NULL); - - fc = in_le32(&i2sdev->intfregs->frame_count); - fc = fc - pi->frame_count; - - if (fc >= pi->substream->runtime->buffer_size) - fc %= pi->substream->runtime->buffer_size; - return fc; -} - -static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in) -{ - struct pcm_info *pi; - u32 fc, nframes; - u32 status; - int timeout, i; - int dma_stopped = 0; - struct snd_pcm_runtime *runtime; - - spin_lock(&i2sdev->low_lock); - get_pcm_info(i2sdev, in, &pi, NULL); - if (!pi->dbdma_ring.running && !pi->dbdma_ring.stopping) - goto out_unlock; - - i = pi->current_period; - runtime = pi->substream->runtime; - while (pi->dbdma_ring.cmds[i].xfer_status) { - if (le16_to_cpu(pi->dbdma_ring.cmds[i].xfer_status) & BT) - /* - * BT is the branch taken bit. If it took a branch - * it is because we set the S0 bit to make it - * branch to the stop command. - */ - dma_stopped = 1; - pi->dbdma_ring.cmds[i].xfer_status = 0; - - if (++i >= runtime->periods) { - i = 0; - pi->frame_count += runtime->buffer_size; - } - pi->current_period = i; - - /* - * Check the frame count. The DMA tends to get a bit - * ahead of the frame counter, which confuses the core. - */ - fc = in_le32(&i2sdev->intfregs->frame_count); - nframes = i * runtime->period_size; - if (fc < pi->frame_count + nframes) - pi->frame_count = fc - nframes; - } - - if (dma_stopped) { - timeout = 1000; - for (;;) { - status = in_le32(&pi->dbdma->status); - if (!(status & ACTIVE) && (!in || (status & 0x80))) - break; - if (--timeout <= 0) { - printk(KERN_ERR "i2sbus: timed out " - "waiting for DMA to stop!\n"); - break; - } - udelay(1); - } - - /* Turn off DMA controller, clear S0 bit */ - out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16); - - pi->dbdma_ring.stopping = 0; - if (pi->stop_completion) - complete(pi->stop_completion); - } - - if (!pi->dbdma_ring.running) - goto out_unlock; - spin_unlock(&i2sdev->low_lock); - /* may call _trigger again, hence needs to be unlocked */ - snd_pcm_period_elapsed(pi->substream); - return; - - out_unlock: - spin_unlock(&i2sdev->low_lock); -} - -irqreturn_t i2sbus_tx_intr(int irq, void *devid) -{ - handle_interrupt((struct i2sbus_dev *)devid, 0); - return IRQ_HANDLED; -} - -irqreturn_t i2sbus_rx_intr(int irq, void *devid) -{ - handle_interrupt((struct i2sbus_dev *)devid, 1); - return IRQ_HANDLED; -} - -static int i2sbus_playback_open(struct snd_pcm_substream *substream) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - - if (!i2sdev) - return -EINVAL; - i2sdev->out.substream = substream; - return i2sbus_pcm_open(i2sdev, 0); -} - -static int i2sbus_playback_close(struct snd_pcm_substream *substream) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - int err; - - if (!i2sdev) - return -EINVAL; - if (i2sdev->out.substream != substream) - return -EINVAL; - err = i2sbus_pcm_close(i2sdev, 0); - if (!err) - i2sdev->out.substream = NULL; - return err; -} - -static int i2sbus_playback_prepare(struct snd_pcm_substream *substream) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - - if (!i2sdev) - return -EINVAL; - if (i2sdev->out.substream != substream) - return -EINVAL; - return i2sbus_pcm_prepare(i2sdev, 0); -} - -static int i2sbus_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - - if (!i2sdev) - return -EINVAL; - if (i2sdev->out.substream != substream) - return -EINVAL; - return i2sbus_pcm_trigger(i2sdev, 0, cmd); -} - -static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream - *substream) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - - if (!i2sdev) - return -EINVAL; - if (i2sdev->out.substream != substream) - return 0; - return i2sbus_pcm_pointer(i2sdev, 0); -} - -static struct snd_pcm_ops i2sbus_playback_ops = { - .open = i2sbus_playback_open, - .close = i2sbus_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = i2sbus_hw_params, - .hw_free = i2sbus_playback_hw_free, - .prepare = i2sbus_playback_prepare, - .trigger = i2sbus_playback_trigger, - .pointer = i2sbus_playback_pointer, -}; - -static int i2sbus_record_open(struct snd_pcm_substream *substream) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - - if (!i2sdev) - return -EINVAL; - i2sdev->in.substream = substream; - return i2sbus_pcm_open(i2sdev, 1); -} - -static int i2sbus_record_close(struct snd_pcm_substream *substream) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - int err; - - if (!i2sdev) - return -EINVAL; - if (i2sdev->in.substream != substream) - return -EINVAL; - err = i2sbus_pcm_close(i2sdev, 1); - if (!err) - i2sdev->in.substream = NULL; - return err; -} - -static int i2sbus_record_prepare(struct snd_pcm_substream *substream) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - - if (!i2sdev) - return -EINVAL; - if (i2sdev->in.substream != substream) - return -EINVAL; - return i2sbus_pcm_prepare(i2sdev, 1); -} - -static int i2sbus_record_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - - if (!i2sdev) - return -EINVAL; - if (i2sdev->in.substream != substream) - return -EINVAL; - return i2sbus_pcm_trigger(i2sdev, 1, cmd); -} - -static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream - *substream) -{ - struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); - - if (!i2sdev) - return -EINVAL; - if (i2sdev->in.substream != substream) - return 0; - return i2sbus_pcm_pointer(i2sdev, 1); -} - -static struct snd_pcm_ops i2sbus_record_ops = { - .open = i2sbus_record_open, - .close = i2sbus_record_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = i2sbus_hw_params, - .hw_free = i2sbus_record_hw_free, - .prepare = i2sbus_record_prepare, - .trigger = i2sbus_record_trigger, - .pointer = i2sbus_record_pointer, -}; - -static void i2sbus_private_free(struct snd_pcm *pcm) -{ - struct i2sbus_dev *i2sdev = snd_pcm_chip(pcm); - struct codec_info_item *p, *tmp; - - i2sdev->sound.pcm = NULL; - i2sdev->out.created = 0; - i2sdev->in.created = 0; - list_for_each_entry_safe(p, tmp, &i2sdev->sound.codec_list, list) { - printk(KERN_ERR "i2sbus: a codec didn't unregister!\n"); - list_del(&p->list); - module_put(p->codec->owner); - kfree(p); - } - soundbus_dev_put(&i2sdev->sound); - module_put(THIS_MODULE); -} - -int -i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, - struct codec_info *ci, void *data) -{ - int err, in = 0, out = 0; - struct transfer_info *tmp; - struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev); - struct codec_info_item *cii; - - if (!dev->pcmname || dev->pcmid == -1) { - printk(KERN_ERR "i2sbus: pcm name and id must be set!\n"); - return -EINVAL; - } - - list_for_each_entry(cii, &dev->codec_list, list) { - if (cii->codec_data == data) - return -EALREADY; - } - - if (!ci->transfers || !ci->transfers->formats - || !ci->transfers->rates || !ci->usable) - return -EINVAL; - - /* we currently code the i2s transfer on the clock, and support only - * 32 and 64 */ - if (ci->bus_factor != 32 && ci->bus_factor != 64) - return -EINVAL; - - /* If you want to fix this, you need to keep track of what transport infos - * are to be used, which codecs they belong to, and then fix all the - * sysclock/busclock stuff above to depend on which is usable */ - list_for_each_entry(cii, &dev->codec_list, list) { - if (cii->codec->sysclock_factor != ci->sysclock_factor) { - printk(KERN_DEBUG - "cannot yet handle multiple different sysclocks!\n"); - return -EINVAL; - } - if (cii->codec->bus_factor != ci->bus_factor) { - printk(KERN_DEBUG - "cannot yet handle multiple different bus clocks!\n"); - return -EINVAL; - } - } - - tmp = ci->transfers; - while (tmp->formats && tmp->rates) { - if (tmp->transfer_in) - in = 1; - else - out = 1; - tmp++; - } - - cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL); - if (!cii) { - printk(KERN_DEBUG "i2sbus: failed to allocate cii\n"); - return -ENOMEM; - } - - /* use the private data to point to the codec info */ - cii->sdev = soundbus_dev_get(dev); - cii->codec = ci; - cii->codec_data = data; - - if (!cii->sdev) { - printk(KERN_DEBUG - "i2sbus: failed to get soundbus dev reference\n"); - err = -ENODEV; - goto out_free_cii; - } - - if (!try_module_get(THIS_MODULE)) { - printk(KERN_DEBUG "i2sbus: failed to get module reference!\n"); - err = -EBUSY; - goto out_put_sdev; - } - - if (!try_module_get(ci->owner)) { - printk(KERN_DEBUG - "i2sbus: failed to get module reference to codec owner!\n"); - err = -EBUSY; - goto out_put_this_module; - } - - if (!dev->pcm) { - err = snd_pcm_new(card, dev->pcmname, dev->pcmid, 0, 0, - &dev->pcm); - if (err) { - printk(KERN_DEBUG "i2sbus: failed to create pcm\n"); - goto out_put_ci_module; - } - dev->pcm->dev = &dev->ofdev.dev; - } - - /* ALSA yet again sucks. - * If it is ever fixed, remove this line. See below. */ - out = in = 1; - - if (!i2sdev->out.created && out) { - if (dev->pcm->card != card) { - /* eh? */ - printk(KERN_ERR - "Can't attach same bus to different cards!\n"); - err = -EINVAL; - goto out_put_ci_module; - } - err = snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1); - if (err) - goto out_put_ci_module; - snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, - &i2sbus_playback_ops); - i2sdev->out.created = 1; - } - - if (!i2sdev->in.created && in) { - if (dev->pcm->card != card) { - printk(KERN_ERR - "Can't attach same bus to different cards!\n"); - err = -EINVAL; - goto out_put_ci_module; - } - err = snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1); - if (err) - goto out_put_ci_module; - snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, - &i2sbus_record_ops); - i2sdev->in.created = 1; - } - - /* so we have to register the pcm after adding any substream - * to it because alsa doesn't create the devices for the - * substreams when we add them later. - * Therefore, force in and out on both busses (above) and - * register the pcm now instead of just after creating it. - */ - err = snd_device_register(card, dev->pcm); - if (err) { - printk(KERN_ERR "i2sbus: error registering new pcm\n"); - goto out_put_ci_module; - } - /* no errors any more, so let's add this to our list */ - list_add(&cii->list, &dev->codec_list); - - dev->pcm->private_data = i2sdev; - dev->pcm->private_free = i2sbus_private_free; - - /* well, we really should support scatter/gather DMA */ - snd_pcm_lib_preallocate_pages_for_all( - dev->pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)), - 64 * 1024, 64 * 1024); - - return 0; - out_put_ci_module: - module_put(ci->owner); - out_put_this_module: - module_put(THIS_MODULE); - out_put_sdev: - soundbus_dev_put(dev); - out_free_cii: - kfree(cii); - return err; -} - -void i2sbus_detach_codec(struct soundbus_dev *dev, void *data) -{ - struct codec_info_item *cii = NULL, *i; - - list_for_each_entry(i, &dev->codec_list, list) { - if (i->codec_data == data) { - cii = i; - break; - } - } - if (cii) { - list_del(&cii->list); - module_put(cii->codec->owner); - kfree(cii); - } - /* no more codecs, but still a pcm? */ - if (list_empty(&dev->codec_list) && dev->pcm) { - /* the actual cleanup is done by the callback above! */ - snd_device_free(dev->pcm->card, dev->pcm); - } -} diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/soundbus.h b/ANDROID_3.4.5/sound/aoa/soundbus/soundbus.h deleted file mode 100644 index adecbf36..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/soundbus.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * soundbus generic definitions - * - * Copyright 2006 Johannes Berg - * - * GPL v2, can be found in COPYING. - */ -#ifndef __SOUNDBUS_H -#define __SOUNDBUS_H - -#include -#include -#include - - -/* When switching from master to slave or the other way around, - * you don't want to have the codec chip acting as clock source - * while the bus still is. - * More importantly, while switch from slave to master, you need - * to turn off the chip's master function first, but then there's - * no clock for a while and other chips might reset, so we notify - * their drivers after having switched. - * The constants here are codec-point of view, so when we switch - * the soundbus to master we tell the codec we're going to switch - * and give it CLOCK_SWITCH_PREPARE_SLAVE! - */ -enum clock_switch { - CLOCK_SWITCH_PREPARE_SLAVE, - CLOCK_SWITCH_PREPARE_MASTER, - CLOCK_SWITCH_SLAVE, - CLOCK_SWITCH_MASTER, - CLOCK_SWITCH_NOTIFY, -}; - -/* information on a transfer the codec can take */ -struct transfer_info { - u64 formats; /* SNDRV_PCM_FMTBIT_* */ - unsigned int rates; /* SNDRV_PCM_RATE_* */ - /* flags */ - u32 transfer_in:1, /* input = 1, output = 0 */ - must_be_clock_source:1; - /* for codecs to distinguish among their TIs */ - int tag; -}; - -struct codec_info_item { - struct codec_info *codec; - void *codec_data; - struct soundbus_dev *sdev; - /* internal, to be used by the soundbus provider */ - struct list_head list; -}; - -/* for prepare, where the codecs need to know - * what we're going to drive the bus with */ -struct bus_info { - /* see below */ - int sysclock_factor; - int bus_factor; -}; - -/* information on the codec itself, plus function pointers */ -struct codec_info { - /* the module this lives in */ - struct module *owner; - - /* supported transfer possibilities, array terminated by - * formats or rates being 0. */ - struct transfer_info *transfers; - - /* Master clock speed factor - * to be used (master clock speed = sysclock_factor * sampling freq) - * Unused if the soundbus provider has no such notion. - */ - int sysclock_factor; - - /* Bus factor, bus clock speed = bus_factor * sampling freq) - * Unused if the soundbus provider has no such notion. - */ - int bus_factor; - - /* operations */ - /* clock switching, see above */ - int (*switch_clock)(struct codec_info_item *cii, - enum clock_switch clock); - - /* called for each transfer_info when the user - * opens the pcm device to determine what the - * hardware can support at this point in time. - * That can depend on other user-switchable controls. - * Return 1 if usable, 0 if not. - * out points to another instance of a transfer_info - * which is initialised to the values in *ti, and - * it's format and rate values can be modified by - * the callback if it is necessary to further restrict - * the formats that can be used at the moment, for - * example when one codec has multiple logical codec - * info structs for multiple inputs. - */ - int (*usable)(struct codec_info_item *cii, - struct transfer_info *ti, - struct transfer_info *out); - - /* called when pcm stream is opened, probably not implemented - * most of the time since it isn't too useful */ - int (*open)(struct codec_info_item *cii, - struct snd_pcm_substream *substream); - - /* called when the pcm stream is closed, at this point - * the user choices can all be unlocked (see below) */ - int (*close)(struct codec_info_item *cii, - struct snd_pcm_substream *substream); - - /* if the codec must forbid some user choices because - * they are not valid with the substream/transfer info, - * it must do so here. Example: no digital output for - * incompatible framerate, say 8KHz, on Onyx. - * If the selected stuff in the substream is NOT - * compatible, you have to reject this call! */ - int (*prepare)(struct codec_info_item *cii, - struct bus_info *bi, - struct snd_pcm_substream *substream); - - /* start() is called before data is pushed to the codec. - * Note that start() must be atomic! */ - int (*start)(struct codec_info_item *cii, - struct snd_pcm_substream *substream); - - /* stop() is called after data is no longer pushed to the codec. - * Note that stop() must be atomic! */ - int (*stop)(struct codec_info_item *cii, - struct snd_pcm_substream *substream); - - int (*suspend)(struct codec_info_item *cii, pm_message_t state); - int (*resume)(struct codec_info_item *cii); -}; - -/* information on a soundbus device */ -struct soundbus_dev { - /* the bus it belongs to */ - struct list_head onbuslist; - - /* the of device it represents */ - struct platform_device ofdev; - - /* what modules go by */ - char modalias[32]; - - /* These fields must be before attach_codec can be called. - * They should be set by the owner of the alsa card object - * that is needed, and whoever sets them must make sure - * that they are unique within that alsa card object. */ - char *pcmname; - int pcmid; - - /* this is assigned by the soundbus provider in attach_codec */ - struct snd_pcm *pcm; - - /* operations */ - /* attach a codec to this soundbus, give the alsa - * card object the PCMs for this soundbus should be in. - * The 'data' pointer must be unique, it is used as the - * key for detach_codec(). */ - int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card, - struct codec_info *ci, void *data); - void (*detach_codec)(struct soundbus_dev *dev, void *data); - /* TODO: suspend/resume */ - - /* private for the soundbus provider */ - struct list_head codec_list; - u32 have_out:1, have_in:1; -}; -#define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev) -#define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev) - -extern int soundbus_add_one(struct soundbus_dev *dev); -extern void soundbus_remove_one(struct soundbus_dev *dev); - -extern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev); -extern void soundbus_dev_put(struct soundbus_dev *dev); - -struct soundbus_driver { - char *name; - struct module *owner; - - /* we don't implement any matching at all */ - - int (*probe)(struct soundbus_dev* dev); - int (*remove)(struct soundbus_dev* dev); - - int (*suspend)(struct soundbus_dev* dev, pm_message_t state); - int (*resume)(struct soundbus_dev* dev); - int (*shutdown)(struct soundbus_dev* dev); - - struct device_driver driver; -}; -#define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver) - -extern int soundbus_register_driver(struct soundbus_driver *drv); -extern void soundbus_unregister_driver(struct soundbus_driver *drv); - -extern struct device_attribute soundbus_dev_attrs[]; - -#endif /* __SOUNDBUS_H */ diff --git a/ANDROID_3.4.5/sound/aoa/soundbus/sysfs.c b/ANDROID_3.4.5/sound/aoa/soundbus/sysfs.c deleted file mode 100644 index e0980b5c..00000000 --- a/ANDROID_3.4.5/sound/aoa/soundbus/sysfs.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -/* FIX UP */ -#include "soundbus.h" - -#define soundbus_config_of_attr(field, format_string) \ -static ssize_t \ -field##_show (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct soundbus_dev *mdev = to_soundbus_device (dev); \ - return sprintf (buf, format_string, mdev->ofdev.dev.of_node->field); \ -} - -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct soundbus_dev *sdev = to_soundbus_device(dev); - struct platform_device *of = &sdev->ofdev; - int length; - - if (*sdev->modalias) { - strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1); - strcat(buf, "\n"); - length = strlen(buf); - } else { - length = sprintf(buf, "of:N%sT%s\n", - of->dev.of_node->name, of->dev.of_node->type); - } - - return length; -} - -soundbus_config_of_attr (name, "%s\n"); -soundbus_config_of_attr (type, "%s\n"); - -struct device_attribute soundbus_dev_attrs[] = { - __ATTR_RO(name), - __ATTR_RO(type), - __ATTR_RO(modalias), - __ATTR_NULL -}; diff --git a/ANDROID_3.4.5/sound/arm/Kconfig b/ANDROID_3.4.5/sound/arm/Kconfig deleted file mode 100644 index 885683a3..00000000 --- a/ANDROID_3.4.5/sound/arm/Kconfig +++ /dev/null @@ -1,43 +0,0 @@ -# ALSA ARM drivers - -menuconfig SND_ARM - bool "ARM sound devices" - depends on ARM - default y - help - Support for sound devices specific to ARM architectures. - Drivers that are implemented on ASoC can be found in - "ALSA for SoC audio support" section. - -if SND_ARM - -config SND_ARMAACI - tristate "ARM PrimeCell PL041 AC Link support" - depends on ARM_AMBA - select SND_PCM - select SND_AC97_CODEC - -config SND_PXA2XX_PCM - tristate - select SND_PCM - -config SND_PXA2XX_LIB - tristate - select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97 - -config SND_PXA2XX_LIB_AC97 - bool - -config SND_PXA2XX_AC97 - tristate "AC97 driver for the Intel PXA2xx chip" - depends on ARCH_PXA - select SND_PXA2XX_PCM - select SND_AC97_CODEC - select SND_PXA2XX_LIB - select SND_PXA2XX_LIB_AC97 - help - Say Y or M if you want to support any AC97 codec attached to - the PXA2xx AC97 interface. - -endif # SND_ARM - diff --git a/ANDROID_3.4.5/sound/arm/Makefile b/ANDROID_3.4.5/sound/arm/Makefile deleted file mode 100644 index 8c0c851d..00000000 --- a/ANDROID_3.4.5/sound/arm/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Makefile for ALSA -# - -obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o -snd-aaci-objs := aaci.o - -obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o -snd-pxa2xx-pcm-objs := pxa2xx-pcm.o - -obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o -snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o -snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o - -obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o -snd-pxa2xx-ac97-objs := pxa2xx-ac97.o diff --git a/ANDROID_3.4.5/sound/arm/aaci.c b/ANDROID_3.4.5/sound/arm/aaci.c deleted file mode 100644 index 5119fdab..00000000 --- a/ANDROID_3.4.5/sound/arm/aaci.c +++ /dev/null @@ -1,1116 +0,0 @@ -/* - * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver - * - * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Documentation: ARM DDI 0173B - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "aaci.h" - -#define DRIVER_NAME "aaci-pl041" - -#define FRAME_PERIOD_US 21 - -/* - * PM support is not complete. Turn it off. - */ -#undef CONFIG_PM - -static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97) -{ - u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num); - - /* - * Ensure that the slot 1/2 RX registers are empty. - */ - v = readl(aaci->base + AACI_SLFR); - if (v & SLFR_2RXV) - readl(aaci->base + AACI_SL2RX); - if (v & SLFR_1RXV) - readl(aaci->base + AACI_SL1RX); - - if (maincr != readl(aaci->base + AACI_MAINCR)) { - writel(maincr, aaci->base + AACI_MAINCR); - readl(aaci->base + AACI_MAINCR); - udelay(1); - } -} - -/* - * P29: - * The recommended use of programming the external codec through slot 1 - * and slot 2 data is to use the channels during setup routines and the - * slot register at any other time. The data written into slot 1, slot 2 - * and slot 12 registers is transmitted only when their corresponding - * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR - * register. - */ -static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct aaci *aaci = ac97->private_data; - int timeout; - u32 v; - - if (ac97->num >= 4) - return; - - mutex_lock(&aaci->ac97_sem); - - aaci_ac97_select_codec(aaci, ac97); - - /* - * P54: You must ensure that AACI_SL2TX is always written - * to, if required, before data is written to AACI_SL1TX. - */ - writel(val << 4, aaci->base + AACI_SL2TX); - writel(reg << 12, aaci->base + AACI_SL1TX); - - /* Initially, wait one frame period */ - udelay(FRAME_PERIOD_US); - - /* And then wait an additional eight frame periods for it to be sent */ - timeout = FRAME_PERIOD_US * 8; - do { - udelay(1); - v = readl(aaci->base + AACI_SLFR); - } while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout); - - if (v & (SLFR_1TXB|SLFR_2TXB)) - dev_err(&aaci->dev->dev, - "timeout waiting for write to complete\n"); - - mutex_unlock(&aaci->ac97_sem); -} - -/* - * Read an AC'97 register. - */ -static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct aaci *aaci = ac97->private_data; - int timeout, retries = 10; - u32 v; - - if (ac97->num >= 4) - return ~0; - - mutex_lock(&aaci->ac97_sem); - - aaci_ac97_select_codec(aaci, ac97); - - /* - * Write the register address to slot 1. - */ - writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); - - /* Initially, wait one frame period */ - udelay(FRAME_PERIOD_US); - - /* And then wait an additional eight frame periods for it to be sent */ - timeout = FRAME_PERIOD_US * 8; - do { - udelay(1); - v = readl(aaci->base + AACI_SLFR); - } while ((v & SLFR_1TXB) && --timeout); - - if (v & SLFR_1TXB) { - dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n"); - v = ~0; - goto out; - } - - /* Now wait for the response frame */ - udelay(FRAME_PERIOD_US); - - /* And then wait an additional eight frame periods for data */ - timeout = FRAME_PERIOD_US * 8; - do { - udelay(1); - cond_resched(); - v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); - } while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout); - - if (v != (SLFR_1RXV|SLFR_2RXV)) { - dev_err(&aaci->dev->dev, "timeout on RX valid\n"); - v = ~0; - goto out; - } - - do { - v = readl(aaci->base + AACI_SL1RX) >> 12; - if (v == reg) { - v = readl(aaci->base + AACI_SL2RX) >> 4; - break; - } else if (--retries) { - dev_warn(&aaci->dev->dev, - "ac97 read back fail. retry\n"); - continue; - } else { - dev_warn(&aaci->dev->dev, - "wrong ac97 register read back (%x != %x)\n", - v, reg); - v = ~0; - } - } while (retries); - out: - mutex_unlock(&aaci->ac97_sem); - return v; -} - -static inline void -aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask) -{ - u32 val; - int timeout = 5000; - - do { - udelay(1); - val = readl(aacirun->base + AACI_SR); - } while (val & mask && timeout--); -} - - - -/* - * Interrupt support. - */ -static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) -{ - if (mask & ISR_ORINTR) { - dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel); - writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR); - } - - if (mask & ISR_RXTOINTR) { - dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel); - writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR); - } - - if (mask & ISR_RXINTR) { - struct aaci_runtime *aacirun = &aaci->capture; - bool period_elapsed = false; - void *ptr; - - if (!aacirun->substream || !aacirun->start) { - dev_warn(&aaci->dev->dev, "RX interrupt???\n"); - writel(0, aacirun->base + AACI_IE); - return; - } - - spin_lock(&aacirun->lock); - - ptr = aacirun->ptr; - do { - unsigned int len = aacirun->fifo_bytes; - u32 val; - - if (aacirun->bytes <= 0) { - aacirun->bytes += aacirun->period; - period_elapsed = true; - } - if (!(aacirun->cr & CR_EN)) - break; - - val = readl(aacirun->base + AACI_SR); - if (!(val & SR_RXHF)) - break; - if (!(val & SR_RXFF)) - len >>= 1; - - aacirun->bytes -= len; - - /* reading 16 bytes at a time */ - for( ; len > 0; len -= 16) { - asm( - "ldmia %1, {r0, r1, r2, r3}\n\t" - "stmia %0!, {r0, r1, r2, r3}" - : "+r" (ptr) - : "r" (aacirun->fifo) - : "r0", "r1", "r2", "r3", "cc"); - - if (ptr >= aacirun->end) - ptr = aacirun->start; - } - } while(1); - - aacirun->ptr = ptr; - - spin_unlock(&aacirun->lock); - - if (period_elapsed) - snd_pcm_period_elapsed(aacirun->substream); - } - - if (mask & ISR_URINTR) { - dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel); - writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR); - } - - if (mask & ISR_TXINTR) { - struct aaci_runtime *aacirun = &aaci->playback; - bool period_elapsed = false; - void *ptr; - - if (!aacirun->substream || !aacirun->start) { - dev_warn(&aaci->dev->dev, "TX interrupt???\n"); - writel(0, aacirun->base + AACI_IE); - return; - } - - spin_lock(&aacirun->lock); - - ptr = aacirun->ptr; - do { - unsigned int len = aacirun->fifo_bytes; - u32 val; - - if (aacirun->bytes <= 0) { - aacirun->bytes += aacirun->period; - period_elapsed = true; - } - if (!(aacirun->cr & CR_EN)) - break; - - val = readl(aacirun->base + AACI_SR); - if (!(val & SR_TXHE)) - break; - if (!(val & SR_TXFE)) - len >>= 1; - - aacirun->bytes -= len; - - /* writing 16 bytes at a time */ - for ( ; len > 0; len -= 16) { - asm( - "ldmia %0!, {r0, r1, r2, r3}\n\t" - "stmia %1, {r0, r1, r2, r3}" - : "+r" (ptr) - : "r" (aacirun->fifo) - : "r0", "r1", "r2", "r3", "cc"); - - if (ptr >= aacirun->end) - ptr = aacirun->start; - } - } while (1); - - aacirun->ptr = ptr; - - spin_unlock(&aacirun->lock); - - if (period_elapsed) - snd_pcm_period_elapsed(aacirun->substream); - } -} - -static irqreturn_t aaci_irq(int irq, void *devid) -{ - struct aaci *aaci = devid; - u32 mask; - int i; - - mask = readl(aaci->base + AACI_ALLINTS); - if (mask) { - u32 m = mask; - for (i = 0; i < 4; i++, m >>= 7) { - if (m & 0x7f) { - aaci_fifo_irq(aaci, i, m); - } - } - } - - return mask ? IRQ_HANDLED : IRQ_NONE; -} - - - -/* - * ALSA support. - */ -static struct snd_pcm_hardware aaci_hw_info = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME, - - /* - * ALSA doesn't support 18-bit or 20-bit packed into 32-bit - * words. It also doesn't support 12-bit at all. - */ - .formats = SNDRV_PCM_FMTBIT_S16_LE, - - /* rates are setup from the AC'97 codec */ - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 64 * 1024, - .period_bytes_min = 256, - .period_bytes_max = PAGE_SIZE, - .periods_min = 4, - .periods_max = PAGE_SIZE / 16, -}; - -/* - * We can support two and four channel audio. Unfortunately - * six channel audio requires a non-standard channel ordering: - * 2 -> FL(3), FR(4) - * 4 -> FL(3), FR(4), SL(7), SR(8) - * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required) - * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual) - * This requires an ALSA configuration file to correct. - */ -static int aaci_rule_channels(struct snd_pcm_hw_params *p, - struct snd_pcm_hw_rule *rule) -{ - static unsigned int channel_list[] = { 2, 4, 6 }; - struct aaci *aaci = rule->private; - unsigned int mask = 1 << 0, slots; - - /* pcms[0] is the our 5.1 PCM instance. */ - slots = aaci->ac97_bus->pcms[0].r[0].slots; - if (slots & (1 << AC97_SLOT_PCM_SLEFT)) { - mask |= 1 << 1; - if (slots & (1 << AC97_SLOT_LFE)) - mask |= 1 << 2; - } - - return snd_interval_list(hw_param_interval(p, rule->var), - ARRAY_SIZE(channel_list), channel_list, mask); -} - -static int aaci_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct aaci *aaci = substream->private_data; - struct aaci_runtime *aacirun; - int ret = 0; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - aacirun = &aaci->playback; - } else { - aacirun = &aaci->capture; - } - - aacirun->substream = substream; - runtime->private_data = aacirun; - runtime->hw = aaci_hw_info; - runtime->hw.rates = aacirun->pcm->rates; - snd_pcm_limit_hw_rates(runtime); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - runtime->hw.channels_max = 6; - - /* Add rule describing channel dependency. */ - ret = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - aaci_rule_channels, aaci, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - if (ret) - return ret; - - if (aacirun->pcm->r[1].slots) - snd_ac97_pcm_double_rate_rules(runtime); - } - - /* - * ALSA wants the byte-size of the FIFOs. As we only support - * 16-bit samples, this is twice the FIFO depth irrespective - * of whether it's in compact mode or not. - */ - runtime->hw.fifo_size = aaci->fifo_depth * 2; - - mutex_lock(&aaci->irq_lock); - if (!aaci->users++) { - ret = request_irq(aaci->dev->irq[0], aaci_irq, - IRQF_SHARED, DRIVER_NAME, aaci); - if (ret != 0) - aaci->users--; - } - mutex_unlock(&aaci->irq_lock); - - return ret; -} - - -/* - * Common ALSA stuff - */ -static int aaci_pcm_close(struct snd_pcm_substream *substream) -{ - struct aaci *aaci = substream->private_data; - struct aaci_runtime *aacirun = substream->runtime->private_data; - - WARN_ON(aacirun->cr & CR_EN); - - aacirun->substream = NULL; - - mutex_lock(&aaci->irq_lock); - if (!--aaci->users) - free_irq(aaci->dev->irq[0], aaci); - mutex_unlock(&aaci->irq_lock); - - return 0; -} - -static int aaci_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct aaci_runtime *aacirun = substream->runtime->private_data; - - /* - * This must not be called with the device enabled. - */ - WARN_ON(aacirun->cr & CR_EN); - - if (aacirun->pcm_open) - snd_ac97_pcm_close(aacirun->pcm); - aacirun->pcm_open = 0; - - /* - * Clear out the DMA and any allocated buffers. - */ - snd_pcm_lib_free_pages(substream); - - return 0; -} - -/* Channel to slot mask */ -static const u32 channels_to_slotmask[] = { - [2] = CR_SL3 | CR_SL4, - [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8, - [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9, -}; - -static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct aaci_runtime *aacirun = substream->runtime->private_data; - unsigned int channels = params_channels(params); - unsigned int rate = params_rate(params); - int dbl = rate > 48000; - int err; - - aaci_pcm_hw_free(substream); - if (aacirun->pcm_open) { - snd_ac97_pcm_close(aacirun->pcm); - aacirun->pcm_open = 0; - } - - /* channels is already limited to 2, 4, or 6 by aaci_rule_channels */ - if (dbl && channels != 2) - return -EINVAL; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(params)); - if (err >= 0) { - struct aaci *aaci = substream->private_data; - - err = snd_ac97_pcm_open(aacirun->pcm, rate, channels, - aacirun->pcm->r[dbl].slots); - - aacirun->pcm_open = err == 0; - aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; - aacirun->cr |= channels_to_slotmask[channels + dbl * 2]; - - /* - * fifo_bytes is the number of bytes we transfer to/from - * the FIFO, including padding. So that's x4. As we're - * in compact mode, the FIFO is half the size. - */ - aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2; - } - - return err; -} - -static int aaci_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct aaci_runtime *aacirun = runtime->private_data; - - aacirun->period = snd_pcm_lib_period_bytes(substream); - aacirun->start = runtime->dma_area; - aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream); - aacirun->ptr = aacirun->start; - aacirun->bytes = aacirun->period; - - return 0; -} - -static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct aaci_runtime *aacirun = runtime->private_data; - ssize_t bytes = aacirun->ptr - aacirun->start; - - return bytes_to_frames(runtime, bytes); -} - - -/* - * Playback specific ALSA stuff - */ -static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) -{ - u32 ie; - - ie = readl(aacirun->base + AACI_IE); - ie &= ~(IE_URIE|IE_TXIE); - writel(ie, aacirun->base + AACI_IE); - aacirun->cr &= ~CR_EN; - aaci_chan_wait_ready(aacirun, SR_TXB); - writel(aacirun->cr, aacirun->base + AACI_TXCR); -} - -static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) -{ - u32 ie; - - aaci_chan_wait_ready(aacirun, SR_TXB); - aacirun->cr |= CR_EN; - - ie = readl(aacirun->base + AACI_IE); - ie |= IE_URIE | IE_TXIE; - writel(ie, aacirun->base + AACI_IE); - writel(aacirun->cr, aacirun->base + AACI_TXCR); -} - -static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct aaci_runtime *aacirun = substream->runtime->private_data; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&aacirun->lock, flags); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - aaci_pcm_playback_start(aacirun); - break; - - case SNDRV_PCM_TRIGGER_RESUME: - aaci_pcm_playback_start(aacirun); - break; - - case SNDRV_PCM_TRIGGER_STOP: - aaci_pcm_playback_stop(aacirun); - break; - - case SNDRV_PCM_TRIGGER_SUSPEND: - aaci_pcm_playback_stop(aacirun); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - break; - - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - break; - - default: - ret = -EINVAL; - } - - spin_unlock_irqrestore(&aacirun->lock, flags); - - return ret; -} - -static struct snd_pcm_ops aaci_playback_ops = { - .open = aaci_pcm_open, - .close = aaci_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = aaci_pcm_hw_params, - .hw_free = aaci_pcm_hw_free, - .prepare = aaci_pcm_prepare, - .trigger = aaci_pcm_playback_trigger, - .pointer = aaci_pcm_pointer, -}; - -static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) -{ - u32 ie; - - aaci_chan_wait_ready(aacirun, SR_RXB); - - ie = readl(aacirun->base + AACI_IE); - ie &= ~(IE_ORIE | IE_RXIE); - writel(ie, aacirun->base+AACI_IE); - - aacirun->cr &= ~CR_EN; - - writel(aacirun->cr, aacirun->base + AACI_RXCR); -} - -static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) -{ - u32 ie; - - aaci_chan_wait_ready(aacirun, SR_RXB); - -#ifdef DEBUG - /* RX Timeout value: bits 28:17 in RXCR */ - aacirun->cr |= 0xf << 17; -#endif - - aacirun->cr |= CR_EN; - writel(aacirun->cr, aacirun->base + AACI_RXCR); - - ie = readl(aacirun->base + AACI_IE); - ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full - writel(ie, aacirun->base + AACI_IE); -} - -static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct aaci_runtime *aacirun = substream->runtime->private_data; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&aacirun->lock, flags); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - aaci_pcm_capture_start(aacirun); - break; - - case SNDRV_PCM_TRIGGER_RESUME: - aaci_pcm_capture_start(aacirun); - break; - - case SNDRV_PCM_TRIGGER_STOP: - aaci_pcm_capture_stop(aacirun); - break; - - case SNDRV_PCM_TRIGGER_SUSPEND: - aaci_pcm_capture_stop(aacirun); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - break; - - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - break; - - default: - ret = -EINVAL; - } - - spin_unlock_irqrestore(&aacirun->lock, flags); - - return ret; -} - -static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct aaci *aaci = substream->private_data; - - aaci_pcm_prepare(substream); - - /* allow changing of sample rate */ - aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */ - aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); - aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate); - - /* Record select: Mic: 0, Aux: 3, Line: 4 */ - aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404); - - return 0; -} - -static struct snd_pcm_ops aaci_capture_ops = { - .open = aaci_pcm_open, - .close = aaci_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = aaci_pcm_hw_params, - .hw_free = aaci_pcm_hw_free, - .prepare = aaci_pcm_capture_prepare, - .trigger = aaci_pcm_capture_trigger, - .pointer = aaci_pcm_pointer, -}; - -/* - * Power Management. - */ -#ifdef CONFIG_PM -static int aaci_do_suspend(struct snd_card *card, unsigned int state) -{ - struct aaci *aaci = card->private_data; - snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); - snd_pcm_suspend_all(aaci->pcm); - return 0; -} - -static int aaci_do_resume(struct snd_card *card, unsigned int state) -{ - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} - -static int aaci_suspend(struct amba_device *dev, pm_message_t state) -{ - struct snd_card *card = amba_get_drvdata(dev); - return card ? aaci_do_suspend(card) : 0; -} - -static int aaci_resume(struct amba_device *dev) -{ - struct snd_card *card = amba_get_drvdata(dev); - return card ? aaci_do_resume(card) : 0; -} -#else -#define aaci_do_suspend NULL -#define aaci_do_resume NULL -#define aaci_suspend NULL -#define aaci_resume NULL -#endif - - -static struct ac97_pcm ac97_defs[] __devinitdata = { - [0] = { /* Front PCM */ - .exclusive = 1, - .r = { - [0] = { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) | - (1 << AC97_SLOT_PCM_CENTER) | - (1 << AC97_SLOT_PCM_SLEFT) | - (1 << AC97_SLOT_PCM_SRIGHT) | - (1 << AC97_SLOT_LFE), - }, - [1] = { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) | - (1 << AC97_SLOT_PCM_LEFT_0) | - (1 << AC97_SLOT_PCM_RIGHT_0), - }, - }, - }, - [1] = { /* PCM in */ - .stream = 1, - .exclusive = 1, - .r = { - [0] = { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT), - }, - }, - }, - [2] = { /* Mic in */ - .stream = 1, - .exclusive = 1, - .r = { - [0] = { - .slots = (1 << AC97_SLOT_MIC), - }, - }, - } -}; - -static struct snd_ac97_bus_ops aaci_bus_ops = { - .write = aaci_ac97_write, - .read = aaci_ac97_read, -}; - -static int __devinit aaci_probe_ac97(struct aaci *aaci) -{ - struct snd_ac97_template ac97_template; - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97; - int ret; - - /* - * Assert AACIRESET for 2us - */ - writel(0, aaci->base + AACI_RESET); - udelay(2); - writel(RESET_NRST, aaci->base + AACI_RESET); - - /* - * Give the AC'97 codec more than enough time - * to wake up. (42us = ~2 frames at 48kHz.) - */ - udelay(FRAME_PERIOD_US * 2); - - ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); - if (ret) - goto out; - - ac97_bus->clock = 48000; - aaci->ac97_bus = ac97_bus; - - memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); - ac97_template.private_data = aaci; - ac97_template.num = 0; - ac97_template.scaps = AC97_SCAP_SKIP_MODEM; - - ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); - if (ret) - goto out; - aaci->ac97 = ac97; - - /* - * Disable AC97 PC Beep input on audio codecs. - */ - if (ac97_is_audio(ac97)) - snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e); - - ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs); - if (ret) - goto out; - - aaci->playback.pcm = &ac97_bus->pcms[0]; - aaci->capture.pcm = &ac97_bus->pcms[1]; - - out: - return ret; -} - -static void aaci_free_card(struct snd_card *card) -{ - struct aaci *aaci = card->private_data; - if (aaci->base) - iounmap(aaci->base); -} - -static struct aaci * __devinit aaci_init_card(struct amba_device *dev) -{ - struct aaci *aaci; - struct snd_card *card; - int err; - - err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct aaci), &card); - if (err < 0) - return NULL; - - card->private_free = aaci_free_card; - - strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); - strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); - snprintf(card->longname, sizeof(card->longname), - "%s PL%03x rev%u at 0x%08llx, irq %d", - card->shortname, amba_part(dev), amba_rev(dev), - (unsigned long long)dev->res.start, dev->irq[0]); - - aaci = card->private_data; - mutex_init(&aaci->ac97_sem); - mutex_init(&aaci->irq_lock); - aaci->card = card; - aaci->dev = dev; - - /* Set MAINCR to allow slot 1 and 2 data IO */ - aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN | - MAINCR_SL2RXEN | MAINCR_SL2TXEN; - - return aaci; -} - -static int __devinit aaci_init_pcm(struct aaci *aaci) -{ - struct snd_pcm *pcm; - int ret; - - ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm); - if (ret == 0) { - aaci->pcm = pcm; - pcm->private_data = aaci; - pcm->info_flags = 0; - - strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - NULL, 0, 64 * 1024); - } - - return ret; -} - -static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) -{ - struct aaci_runtime *aacirun = &aaci->playback; - int i; - - /* - * Enable the channel, but don't assign it to any slots, so - * it won't empty onto the AC'97 link. - */ - writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR); - - for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++) - writel(0, aacirun->fifo); - - writel(0, aacirun->base + AACI_TXCR); - - /* - * Re-initialise the AACI after the FIFO depth test, to - * ensure that the FIFOs are empty. Unfortunately, merely - * disabling the channel doesn't clear the FIFO. - */ - writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); - readl(aaci->base + AACI_MAINCR); - udelay(1); - writel(aaci->maincr, aaci->base + AACI_MAINCR); - - /* - * If we hit 4096 entries, we failed. Go back to the specified - * fifo depth. - */ - if (i == 4096) - i = 8; - - return i; -} - -static int __devinit aaci_probe(struct amba_device *dev, - const struct amba_id *id) -{ - struct aaci *aaci; - int ret, i; - - ret = amba_request_regions(dev, NULL); - if (ret) - return ret; - - aaci = aaci_init_card(dev); - if (!aaci) { - ret = -ENOMEM; - goto out; - } - - aaci->base = ioremap(dev->res.start, resource_size(&dev->res)); - if (!aaci->base) { - ret = -ENOMEM; - goto out; - } - - /* - * Playback uses AACI channel 0 - */ - spin_lock_init(&aaci->playback.lock); - aaci->playback.base = aaci->base + AACI_CSCH1; - aaci->playback.fifo = aaci->base + AACI_DR1; - - /* - * Capture uses AACI channel 0 - */ - spin_lock_init(&aaci->capture.lock); - aaci->capture.base = aaci->base + AACI_CSCH1; - aaci->capture.fifo = aaci->base + AACI_DR1; - - for (i = 0; i < 4; i++) { - void __iomem *base = aaci->base + i * 0x14; - - writel(0, base + AACI_IE); - writel(0, base + AACI_TXCR); - writel(0, base + AACI_RXCR); - } - - writel(0x1fff, aaci->base + AACI_INTCLR); - writel(aaci->maincr, aaci->base + AACI_MAINCR); - /* - * Fix: ac97 read back fail errors by reading - * from any arbitrary aaci register. - */ - readl(aaci->base + AACI_CSCH1); - ret = aaci_probe_ac97(aaci); - if (ret) - goto out; - - /* - * Size the FIFOs (must be multiple of 16). - * This is the number of entries in the FIFO. - */ - aaci->fifo_depth = aaci_size_fifo(aaci); - if (aaci->fifo_depth & 15) { - printk(KERN_WARNING "AACI: FIFO depth %d not supported\n", - aaci->fifo_depth); - ret = -ENODEV; - goto out; - } - - ret = aaci_init_pcm(aaci); - if (ret) - goto out; - - snd_card_set_dev(aaci->card, &dev->dev); - - ret = snd_card_register(aaci->card); - if (ret == 0) { - dev_info(&dev->dev, "%s\n", aaci->card->longname); - dev_info(&dev->dev, "FIFO %u entries\n", aaci->fifo_depth); - amba_set_drvdata(dev, aaci->card); - return ret; - } - - out: - if (aaci) - snd_card_free(aaci->card); - amba_release_regions(dev); - return ret; -} - -static int __devexit aaci_remove(struct amba_device *dev) -{ - struct snd_card *card = amba_get_drvdata(dev); - - amba_set_drvdata(dev, NULL); - - if (card) { - struct aaci *aaci = card->private_data; - writel(0, aaci->base + AACI_MAINCR); - - snd_card_free(card); - amba_release_regions(dev); - } - - return 0; -} - -static struct amba_id aaci_ids[] = { - { - .id = 0x00041041, - .mask = 0x000fffff, - }, - { 0, 0 }, -}; - -MODULE_DEVICE_TABLE(amba, aaci_ids); - -static struct amba_driver aaci_driver = { - .drv = { - .name = DRIVER_NAME, - }, - .probe = aaci_probe, - .remove = __devexit_p(aaci_remove), - .suspend = aaci_suspend, - .resume = aaci_resume, - .id_table = aaci_ids, -}; - -module_amba_driver(aaci_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver"); diff --git a/ANDROID_3.4.5/sound/arm/aaci.h b/ANDROID_3.4.5/sound/arm/aaci.h deleted file mode 100644 index 5791bd5b..00000000 --- a/ANDROID_3.4.5/sound/arm/aaci.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver - * - * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef AACI_H -#define AACI_H - -/* - * Control and status register offsets - * P39. - */ -#define AACI_CSCH1 0x000 -#define AACI_CSCH2 0x014 -#define AACI_CSCH3 0x028 -#define AACI_CSCH4 0x03c - -#define AACI_RXCR 0x000 /* 29 bits Control Rx FIFO */ -#define AACI_TXCR 0x004 /* 17 bits Control Tx FIFO */ -#define AACI_SR 0x008 /* 12 bits Status */ -#define AACI_ISR 0x00c /* 7 bits Int Status */ -#define AACI_IE 0x010 /* 7 bits Int Enable */ - -/* - * Other registers - */ -#define AACI_SL1RX 0x050 -#define AACI_SL1TX 0x054 -#define AACI_SL2RX 0x058 -#define AACI_SL2TX 0x05c -#define AACI_SL12RX 0x060 -#define AACI_SL12TX 0x064 -#define AACI_SLFR 0x068 /* slot flags */ -#define AACI_SLISTAT 0x06c /* slot interrupt status */ -#define AACI_SLIEN 0x070 /* slot interrupt enable */ -#define AACI_INTCLR 0x074 /* interrupt clear */ -#define AACI_MAINCR 0x078 /* main control */ -#define AACI_RESET 0x07c /* reset control */ -#define AACI_SYNC 0x080 /* sync control */ -#define AACI_ALLINTS 0x084 /* all fifo interrupt status */ -#define AACI_MAINFR 0x088 /* main flag register */ -#define AACI_DR1 0x090 /* data read/written fifo 1 */ -#define AACI_DR2 0x0b0 /* data read/written fifo 2 */ -#define AACI_DR3 0x0d0 /* data read/written fifo 3 */ -#define AACI_DR4 0x0f0 /* data read/written fifo 4 */ - -/* - * TX/RX fifo control register (CR). P48 - */ -#define CR_FEN (1 << 16) /* fifo enable */ -#define CR_COMPACT (1 << 15) /* compact mode */ -#define CR_SZ16 (0 << 13) /* 16 bits */ -#define CR_SZ18 (1 << 13) /* 18 bits */ -#define CR_SZ20 (2 << 13) /* 20 bits */ -#define CR_SZ12 (3 << 13) /* 12 bits */ -#define CR_SL12 (1 << 12) -#define CR_SL11 (1 << 11) -#define CR_SL10 (1 << 10) -#define CR_SL9 (1 << 9) -#define CR_SL8 (1 << 8) -#define CR_SL7 (1 << 7) -#define CR_SL6 (1 << 6) -#define CR_SL5 (1 << 5) -#define CR_SL4 (1 << 4) -#define CR_SL3 (1 << 3) -#define CR_SL2 (1 << 2) -#define CR_SL1 (1 << 1) -#define CR_EN (1 << 0) /* transmit enable */ - -/* - * status register bits. P49 - */ -#define SR_RXTOFE (1 << 11) /* rx timeout fifo empty */ -#define SR_TXTO (1 << 10) /* rx timeout fifo nonempty */ -#define SR_TXU (1 << 9) /* tx underrun */ -#define SR_RXO (1 << 8) /* rx overrun */ -#define SR_TXB (1 << 7) /* tx busy */ -#define SR_RXB (1 << 6) /* rx busy */ -#define SR_TXFF (1 << 5) /* tx fifo full */ -#define SR_RXFF (1 << 4) /* rx fifo full */ -#define SR_TXHE (1 << 3) /* tx fifo half empty */ -#define SR_RXHF (1 << 2) /* rx fifo half full */ -#define SR_TXFE (1 << 1) /* tx fifo empty */ -#define SR_RXFE (1 << 0) /* rx fifo empty */ - -/* - * interrupt status register bits. - */ -#define ISR_RXTOFEINTR (1 << 6) /* rx fifo empty */ -#define ISR_URINTR (1 << 5) /* tx underflow */ -#define ISR_ORINTR (1 << 4) /* rx overflow */ -#define ISR_RXINTR (1 << 3) /* rx fifo */ -#define ISR_TXINTR (1 << 2) /* tx fifo intr */ -#define ISR_RXTOINTR (1 << 1) /* tx timeout */ -#define ISR_TXCINTR (1 << 0) /* tx complete */ - -/* - * interrupt enable register bits. - */ -#define IE_RXTOIE (1 << 6) -#define IE_URIE (1 << 5) -#define IE_ORIE (1 << 4) -#define IE_RXIE (1 << 3) -#define IE_TXIE (1 << 2) -#define IE_RXTIE (1 << 1) -#define IE_TXCIE (1 << 0) - -/* - * interrupt status. P51 - */ -#define ISR_RXTOFE (1 << 6) /* rx timeout fifo empty */ -#define ISR_UR (1 << 5) /* tx fifo underrun */ -#define ISR_OR (1 << 4) /* rx fifo overrun */ -#define ISR_RX (1 << 3) /* rx interrupt status */ -#define ISR_TX (1 << 2) /* tx interrupt status */ -#define ISR_RXTO (1 << 1) /* rx timeout */ -#define ISR_TXC (1 << 0) /* tx complete */ - -/* - * interrupt enable. P52 - */ -#define IE_RXTOFE (1 << 6) /* rx timeout fifo empty */ -#define IE_UR (1 << 5) /* tx fifo underrun */ -#define IE_OR (1 << 4) /* rx fifo overrun */ -#define IE_RX (1 << 3) /* rx interrupt status */ -#define IE_TX (1 << 2) /* tx interrupt status */ -#define IE_RXTO (1 << 1) /* rx timeout */ -#define IE_TXC (1 << 0) /* tx complete */ - -/* - * slot flag register bits. P56 - */ -#define SLFR_RWIS (1 << 13) /* raw wake-up interrupt status */ -#define SLFR_RGPIOINTR (1 << 12) /* raw gpio interrupt */ -#define SLFR_12TXE (1 << 11) /* slot 12 tx empty */ -#define SLFR_12RXV (1 << 10) /* slot 12 rx valid */ -#define SLFR_2TXE (1 << 9) /* slot 2 tx empty */ -#define SLFR_2RXV (1 << 8) /* slot 2 rx valid */ -#define SLFR_1TXE (1 << 7) /* slot 1 tx empty */ -#define SLFR_1RXV (1 << 6) /* slot 1 rx valid */ -#define SLFR_12TXB (1 << 5) /* slot 12 tx busy */ -#define SLFR_12RXB (1 << 4) /* slot 12 rx busy */ -#define SLFR_2TXB (1 << 3) /* slot 2 tx busy */ -#define SLFR_2RXB (1 << 2) /* slot 2 rx busy */ -#define SLFR_1TXB (1 << 1) /* slot 1 tx busy */ -#define SLFR_1RXB (1 << 0) /* slot 1 rx busy */ - -/* - * Interrupt clear register. - */ -#define ICLR_RXTOFEC4 (1 << 12) -#define ICLR_RXTOFEC3 (1 << 11) -#define ICLR_RXTOFEC2 (1 << 10) -#define ICLR_RXTOFEC1 (1 << 9) -#define ICLR_TXUEC4 (1 << 8) -#define ICLR_TXUEC3 (1 << 7) -#define ICLR_TXUEC2 (1 << 6) -#define ICLR_TXUEC1 (1 << 5) -#define ICLR_RXOEC4 (1 << 4) -#define ICLR_RXOEC3 (1 << 3) -#define ICLR_RXOEC2 (1 << 2) -#define ICLR_RXOEC1 (1 << 1) -#define ICLR_WISC (1 << 0) - -/* - * Main control register bits. P62 - */ -#define MAINCR_SCRA(x) ((x) << 10) /* secondary codec reg access */ -#define MAINCR_DMAEN (1 << 9) /* dma enable */ -#define MAINCR_SL12TXEN (1 << 8) /* slot 12 transmit enable */ -#define MAINCR_SL12RXEN (1 << 7) /* slot 12 receive enable */ -#define MAINCR_SL2TXEN (1 << 6) /* slot 2 transmit enable */ -#define MAINCR_SL2RXEN (1 << 5) /* slot 2 receive enable */ -#define MAINCR_SL1TXEN (1 << 4) /* slot 1 transmit enable */ -#define MAINCR_SL1RXEN (1 << 3) /* slot 1 receive enable */ -#define MAINCR_LPM (1 << 2) /* low power mode */ -#define MAINCR_LOOPBK (1 << 1) /* loopback */ -#define MAINCR_IE (1 << 0) /* aaci interface enable */ - -/* - * Reset register bits. P65 - */ -#define RESET_NRST (1 << 0) - -/* - * Sync register bits. P65 - */ -#define SYNC_FORCE (1 << 0) - -/* - * Main flag register bits. P66 - */ -#define MAINFR_TXB (1 << 1) /* transmit busy */ -#define MAINFR_RXB (1 << 0) /* receive busy */ - - - -struct aaci_runtime { - void __iomem *base; - void __iomem *fifo; - spinlock_t lock; - - struct ac97_pcm *pcm; - int pcm_open; - - u32 cr; - struct snd_pcm_substream *substream; - - unsigned int period; /* byte size of a "period" */ - - /* - * PIO support - */ - void *start; - void *end; - void *ptr; - int bytes; - unsigned int fifo_bytes; -}; - -struct aaci { - struct amba_device *dev; - struct snd_card *card; - void __iomem *base; - unsigned int fifo_depth; - unsigned int users; - struct mutex irq_lock; - - /* AC'97 */ - struct mutex ac97_sem; - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97; - - u32 maincr; - - struct aaci_runtime playback; - struct aaci_runtime capture; - - struct snd_pcm *pcm; -}; - -#define ACSTREAM_FRONT 0 -#define ACSTREAM_SURROUND 1 -#define ACSTREAM_LFE 2 - -#endif diff --git a/ANDROID_3.4.5/sound/arm/pxa2xx-ac97-lib.c b/ANDROID_3.4.5/sound/arm/pxa2xx-ac97-lib.c deleted file mode 100644 index 48d7c0aa..00000000 --- a/ANDROID_3.4.5/sound/arm/pxa2xx-ac97-lib.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Based on sound/arm/pxa2xx-ac97.c and sound/soc/pxa/pxa2xx-ac97.c - * which contain: - * - * Author: Nicolas Pitre - * Created: Dec 02, 2004 - * Copyright: MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -static DEFINE_MUTEX(car_mutex); -static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); -static volatile long gsr_bits; -static struct clk *ac97_clk; -static struct clk *ac97conf_clk; -static int reset_gpio; - -extern void pxa27x_assert_ac97reset(int reset_gpio, int on); - -/* - * Beware PXA27x bugs: - * - * o Slot 12 read from modem space will hang controller. - * o CDONE, SDONE interrupt fails after any slot 12 IO. - * - * We therefore have an hybrid approach for waiting on SDONE (interrupt or - * 1 jiffy timeout if interrupt never comes). - */ - -unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - unsigned short val = -1; - volatile u32 *reg_addr; - - mutex_lock(&car_mutex); - - /* set up primary or secondary codec space */ - if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS) - reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; - else - reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; - reg_addr += (reg >> 1); - - /* start read access across the ac97 link */ - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - val = *reg_addr; - if (reg == AC97_GPIO_STATUS) - goto out; - if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 && - !((GSR | gsr_bits) & GSR_SDONE)) { - printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", - __func__, reg, GSR | gsr_bits); - val = -1; - goto out; - } - - /* valid data now */ - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - val = *reg_addr; - /* but we've just started another cycle... */ - wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1); - -out: mutex_unlock(&car_mutex); - return val; -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_read); - -void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - volatile u32 *reg_addr; - - mutex_lock(&car_mutex); - - /* set up primary or secondary codec space */ - if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS) - reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; - else - reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; - reg_addr += (reg >> 1); - - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - *reg_addr = val; - if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 && - !((GSR | gsr_bits) & GSR_CDONE)) - printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", - __func__, reg, GSR | gsr_bits); - - mutex_unlock(&car_mutex); -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_write); - -#ifdef CONFIG_PXA25x -static inline void pxa_ac97_warm_pxa25x(void) -{ - gsr_bits = 0; - - GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN; - wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); -} - -static inline void pxa_ac97_cold_pxa25x(void) -{ - GCR &= GCR_COLD_RST; /* clear everything but nCRST */ - GCR &= ~GCR_COLD_RST; /* then assert nCRST */ - - gsr_bits = 0; - - GCR = GCR_COLD_RST; - GCR |= GCR_CDONE_IE|GCR_SDONE_IE; - wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); -} -#endif - -#ifdef CONFIG_PXA27x -static inline void pxa_ac97_warm_pxa27x(void) -{ - gsr_bits = 0; - - /* warm reset broken on Bulverde, so manually keep AC97 reset high */ - pxa27x_assert_ac97reset(reset_gpio, 1); - udelay(10); - GCR |= GCR_WARM_RST; - pxa27x_assert_ac97reset(reset_gpio, 0); - udelay(500); -} - -static inline void pxa_ac97_cold_pxa27x(void) -{ - GCR &= GCR_COLD_RST; /* clear everything but nCRST */ - GCR &= ~GCR_COLD_RST; /* then assert nCRST */ - - gsr_bits = 0; - - /* PXA27x Developers Manual section 13.5.2.2.1 */ - clk_enable(ac97conf_clk); - udelay(5); - clk_disable(ac97conf_clk); - GCR = GCR_COLD_RST; - udelay(50); -} -#endif - -#ifdef CONFIG_PXA3xx -static inline void pxa_ac97_warm_pxa3xx(void) -{ - int timeout = 100; - - gsr_bits = 0; - - /* Can't use interrupts */ - GCR |= GCR_WARM_RST; - while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) - mdelay(1); -} - -static inline void pxa_ac97_cold_pxa3xx(void) -{ - int timeout = 1000; - - /* Hold CLKBPB for 100us */ - GCR = 0; - GCR = GCR_CLKBPB; - udelay(100); - GCR = 0; - - GCR &= GCR_COLD_RST; /* clear everything but nCRST */ - GCR &= ~GCR_COLD_RST; /* then assert nCRST */ - - gsr_bits = 0; - - /* Can't use interrupts on PXA3xx */ - GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); - - GCR = GCR_WARM_RST | GCR_COLD_RST; - while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--) - mdelay(10); -} -#endif - -bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97) -{ - unsigned long gsr; - -#ifdef CONFIG_PXA25x - if (cpu_is_pxa25x()) - pxa_ac97_warm_pxa25x(); - else -#endif -#ifdef CONFIG_PXA27x - if (cpu_is_pxa27x()) - pxa_ac97_warm_pxa27x(); - else -#endif -#ifdef CONFIG_PXA3xx - if (cpu_is_pxa3xx()) - pxa_ac97_warm_pxa3xx(); - else -#endif - BUG(); - gsr = GSR | gsr_bits; - if (!(gsr & (GSR_PCR | GSR_SCR))) { - printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", - __func__, gsr); - - return false; - } - - return true; -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset); - -bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97) -{ - unsigned long gsr; - -#ifdef CONFIG_PXA25x - if (cpu_is_pxa25x()) - pxa_ac97_cold_pxa25x(); - else -#endif -#ifdef CONFIG_PXA27x - if (cpu_is_pxa27x()) - pxa_ac97_cold_pxa27x(); - else -#endif -#ifdef CONFIG_PXA3xx - if (cpu_is_pxa3xx()) - pxa_ac97_cold_pxa3xx(); - else -#endif - BUG(); - - gsr = GSR | gsr_bits; - if (!(gsr & (GSR_PCR | GSR_SCR))) { - printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", - __func__, gsr); - - return false; - } - - return true; -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset); - - -void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97) -{ - GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); - GCR |= GCR_SDONE_IE|GCR_CDONE_IE; -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset); - -static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) -{ - long status; - - status = GSR; - if (status) { - GSR = status; - gsr_bits |= status; - wake_up(&gsr_wq); - - /* Although we don't use those we still need to clear them - since they tend to spuriously trigger when MMC is used - (hardware bug? go figure)... */ - if (cpu_is_pxa27x()) { - MISR = MISR_EOC; - PISR = PISR_EOC; - MCSR = MCSR_EOC; - } - - return IRQ_HANDLED; - } - - return IRQ_NONE; -} - -#ifdef CONFIG_PM -int pxa2xx_ac97_hw_suspend(void) -{ - GCR |= GCR_ACLINK_OFF; - clk_disable(ac97_clk); - return 0; -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend); - -int pxa2xx_ac97_hw_resume(void) -{ - clk_enable(ac97_clk); - return 0; -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); -#endif - -int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) -{ - int ret; - pxa2xx_audio_ops_t *pdata = dev->dev.platform_data; - - if (pdata) { - switch (pdata->reset_gpio) { - case 95: - case 113: - reset_gpio = pdata->reset_gpio; - break; - case 0: - reset_gpio = 113; - break; - case -1: - break; - default: - dev_err(&dev->dev, "Invalid reset GPIO %d\n", - pdata->reset_gpio); - } - } else { - if (cpu_is_pxa27x()) - reset_gpio = 113; - } - - if (cpu_is_pxa27x()) { - /* Use GPIO 113 as AC97 Reset on Bulverde */ - pxa27x_assert_ac97reset(reset_gpio, 0); - ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); - if (IS_ERR(ac97conf_clk)) { - ret = PTR_ERR(ac97conf_clk); - ac97conf_clk = NULL; - goto err_conf; - } - } - - ac97_clk = clk_get(&dev->dev, "AC97CLK"); - if (IS_ERR(ac97_clk)) { - ret = PTR_ERR(ac97_clk); - ac97_clk = NULL; - goto err_clk; - } - - ret = clk_enable(ac97_clk); - if (ret) - goto err_clk2; - - ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); - if (ret < 0) - goto err_irq; - - return 0; - -err_irq: - GCR |= GCR_ACLINK_OFF; -err_clk2: - clk_put(ac97_clk); - ac97_clk = NULL; -err_clk: - if (ac97conf_clk) { - clk_put(ac97conf_clk); - ac97conf_clk = NULL; - } -err_conf: - return ret; -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); - -void pxa2xx_ac97_hw_remove(struct platform_device *dev) -{ - GCR |= GCR_ACLINK_OFF; - free_irq(IRQ_AC97, NULL); - if (ac97conf_clk) { - clk_put(ac97conf_clk); - ac97conf_clk = NULL; - } - clk_disable(ac97_clk); - clk_put(ac97_clk); - ac97_clk = NULL; -} -EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove); - -MODULE_AUTHOR("Nicolas Pitre"); -MODULE_DESCRIPTION("Intel/Marvell PXA sound library"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/arm/pxa2xx-ac97.c b/ANDROID_3.4.5/sound/arm/pxa2xx-ac97.c deleted file mode 100644 index afef72c4..00000000 --- a/ANDROID_3.4.5/sound/arm/pxa2xx-ac97.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip. - * - * Author: Nicolas Pitre - * Created: Dec 02, 2004 - * Copyright: MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "pxa2xx-pcm.h" - -static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) -{ - if (!pxa2xx_ac97_try_cold_reset(ac97)) { - pxa2xx_ac97_try_warm_reset(ac97); - } - - pxa2xx_ac97_finish_reset(ac97); -} - -static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { - .read = pxa2xx_ac97_read, - .write = pxa2xx_ac97_write, - .reset = pxa2xx_ac97_reset, -}; - -static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = { - .name = "AC97 PCM out", - .dev_addr = __PREG(PCDR), - .drcmr = &DRCMR(12), - .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | - DCMD_BURST32 | DCMD_WIDTH4, -}; - -static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = { - .name = "AC97 PCM in", - .dev_addr = __PREG(PCDR), - .drcmr = &DRCMR(11), - .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | - DCMD_BURST32 | DCMD_WIDTH4, -}; - -static struct snd_pcm *pxa2xx_ac97_pcm; -static struct snd_ac97 *pxa2xx_ac97_ac97; - -static int pxa2xx_ac97_pcm_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - pxa2xx_audio_ops_t *platform_ops; - int r; - - runtime->hw.channels_min = 2; - runtime->hw.channels_max = 2; - - r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - AC97_RATES_FRONT_DAC : AC97_RATES_ADC; - runtime->hw.rates = pxa2xx_ac97_ac97->rates[r]; - snd_pcm_limit_hw_rates(runtime); - - platform_ops = substream->pcm->card->dev->platform_data; - if (platform_ops && platform_ops->startup) - return platform_ops->startup(substream, platform_ops->priv); - else - return 0; -} - -static void pxa2xx_ac97_pcm_shutdown(struct snd_pcm_substream *substream) -{ - pxa2xx_audio_ops_t *platform_ops; - - platform_ops = substream->pcm->card->dev->platform_data; - if (platform_ops && platform_ops->shutdown) - platform_ops->shutdown(substream, platform_ops->priv); -} - -static int pxa2xx_ac97_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; - return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate); -} - -static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = { - .playback_params = &pxa2xx_ac97_pcm_out, - .capture_params = &pxa2xx_ac97_pcm_in, - .startup = pxa2xx_ac97_pcm_startup, - .shutdown = pxa2xx_ac97_pcm_shutdown, - .prepare = pxa2xx_ac97_pcm_prepare, -}; - -#ifdef CONFIG_PM - -static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state) -{ - pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); - snd_pcm_suspend_all(pxa2xx_ac97_pcm); - snd_ac97_suspend(pxa2xx_ac97_ac97); - if (platform_ops && platform_ops->suspend) - platform_ops->suspend(platform_ops->priv); - - return pxa2xx_ac97_hw_suspend(); -} - -static int pxa2xx_ac97_do_resume(struct snd_card *card) -{ - pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; - int rc; - - rc = pxa2xx_ac97_hw_resume(); - if (rc) - return rc; - - if (platform_ops && platform_ops->resume) - platform_ops->resume(platform_ops->priv); - snd_ac97_resume(pxa2xx_ac97_ac97); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - - return 0; -} - -static int pxa2xx_ac97_suspend(struct device *dev) -{ - struct snd_card *card = dev_get_drvdata(dev); - int ret = 0; - - if (card) - ret = pxa2xx_ac97_do_suspend(card, PMSG_SUSPEND); - - return ret; -} - -static int pxa2xx_ac97_resume(struct device *dev) -{ - struct snd_card *card = dev_get_drvdata(dev); - int ret = 0; - - if (card) - ret = pxa2xx_ac97_do_resume(card); - - return ret; -} - -static const struct dev_pm_ops pxa2xx_ac97_pm_ops = { - .suspend = pxa2xx_ac97_suspend, - .resume = pxa2xx_ac97_resume, -}; -#endif - -static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) -{ - struct snd_card *card; - struct snd_ac97_bus *ac97_bus; - struct snd_ac97_template ac97_template; - int ret; - pxa2xx_audio_ops_t *pdata = dev->dev.platform_data; - - if (dev->id >= 0) { - dev_err(&dev->dev, "PXA2xx has only one AC97 port.\n"); - ret = -ENXIO; - goto err_dev; - } - - ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, 0, &card); - if (ret < 0) - goto err; - - card->dev = &dev->dev; - strncpy(card->driver, dev->dev.driver->name, sizeof(card->driver)); - - ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm); - if (ret) - goto err; - - ret = pxa2xx_ac97_hw_probe(dev); - if (ret) - goto err; - - ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); - if (ret) - goto err_remove; - memset(&ac97_template, 0, sizeof(ac97_template)); - ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97); - if (ret) - goto err_remove; - - snprintf(card->shortname, sizeof(card->shortname), - "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97)); - snprintf(card->longname, sizeof(card->longname), - "%s (%s)", dev->dev.driver->name, card->mixername); - - if (pdata && pdata->codec_pdata[0]) - snd_ac97_dev_add_pdata(ac97_bus->codec[0], pdata->codec_pdata[0]); - snd_card_set_dev(card, &dev->dev); - ret = snd_card_register(card); - if (ret == 0) { - platform_set_drvdata(dev, card); - return 0; - } - -err_remove: - pxa2xx_ac97_hw_remove(dev); -err: - if (card) - snd_card_free(card); -err_dev: - return ret; -} - -static int __devexit pxa2xx_ac97_remove(struct platform_device *dev) -{ - struct snd_card *card = platform_get_drvdata(dev); - - if (card) { - snd_card_free(card); - platform_set_drvdata(dev, NULL); - pxa2xx_ac97_hw_remove(dev); - } - - return 0; -} - -static struct platform_driver pxa2xx_ac97_driver = { - .probe = pxa2xx_ac97_probe, - .remove = __devexit_p(pxa2xx_ac97_remove), - .driver = { - .name = "pxa2xx-ac97", - .owner = THIS_MODULE, -#ifdef CONFIG_PM - .pm = &pxa2xx_ac97_pm_ops, -#endif - }, -}; - -module_platform_driver(pxa2xx_ac97_driver); - -MODULE_AUTHOR("Nicolas Pitre"); -MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pxa2xx-ac97"); diff --git a/ANDROID_3.4.5/sound/arm/pxa2xx-pcm-lib.c b/ANDROID_3.4.5/sound/arm/pxa2xx-pcm-lib.c deleted file mode 100644 index 76e0d569..00000000 --- a/ANDROID_3.4.5/sound/arm/pxa2xx-pcm-lib.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "pxa2xx-pcm.h" - -static const struct snd_pcm_hardware pxa2xx_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .period_bytes_min = 32, - .period_bytes_max = 8192 - 32, - .periods_min = 1, - .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc), - .buffer_bytes_max = 128 * 1024, - .fifo_size = 32, -}; - -int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *rtd = runtime->private_data; - size_t totsize = params_buffer_bytes(params); - size_t period = params_period_bytes(params); - pxa_dma_desc *dma_desc; - dma_addr_t dma_buff_phys, next_desc_phys; - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = totsize; - - dma_desc = rtd->dma_desc_array; - next_desc_phys = rtd->dma_desc_array_phys; - dma_buff_phys = runtime->dma_addr; - do { - next_desc_phys += sizeof(pxa_dma_desc); - dma_desc->ddadr = next_desc_phys; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dma_desc->dsadr = dma_buff_phys; - dma_desc->dtadr = rtd->params->dev_addr; - } else { - dma_desc->dsadr = rtd->params->dev_addr; - dma_desc->dtadr = dma_buff_phys; - } - if (period > totsize) - period = totsize; - dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN; - dma_desc++; - dma_buff_phys += period; - } while (totsize -= period); - dma_desc[-1].ddadr = rtd->dma_desc_array_phys; - - return 0; -} -EXPORT_SYMBOL(__pxa2xx_pcm_hw_params); - -int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; - - if (rtd && rtd->params && rtd->params->drcmr) - *rtd->params->drcmr = 0; - - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} -EXPORT_SYMBOL(__pxa2xx_pcm_hw_free); - -int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; - DCSR(prtd->dma_ch) = DCSR_RUN; - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - DCSR(prtd->dma_ch) &= ~DCSR_RUN; - break; - - case SNDRV_PCM_TRIGGER_RESUME: - DCSR(prtd->dma_ch) |= DCSR_RUN; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; - DCSR(prtd->dma_ch) |= DCSR_RUN; - break; - - default: - ret = -EINVAL; - } - - return ret; -} -EXPORT_SYMBOL(pxa2xx_pcm_trigger); - -snd_pcm_uframes_t -pxa2xx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *prtd = runtime->private_data; - - dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch); - snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); - - if (x == runtime->buffer_size) - x = 0; - return x; -} -EXPORT_SYMBOL(pxa2xx_pcm_pointer); - -int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; - - if (!prtd || !prtd->params) - return 0; - - if (prtd->dma_ch == -1) - return -EINVAL; - - DCSR(prtd->dma_ch) &= ~DCSR_RUN; - DCSR(prtd->dma_ch) = 0; - DCMD(prtd->dma_ch) = 0; - *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD; - - return 0; -} -EXPORT_SYMBOL(__pxa2xx_pcm_prepare); - -void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) -{ - struct snd_pcm_substream *substream = dev_id; - struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; - int dcsr; - - dcsr = DCSR(dma_ch); - DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; - - if (dcsr & DCSR_ENDINTR) { - snd_pcm_period_elapsed(substream); - } else { - printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", - rtd->params->name, dma_ch, dcsr); - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - } -} -EXPORT_SYMBOL(pxa2xx_pcm_dma_irq); - -int __pxa2xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *rtd; - int ret; - - runtime->hw = pxa2xx_pcm_hardware; - - /* - * For mysterious reasons (and despite what the manual says) - * playback samples are lost if the DMA count is not a multiple - * of the DMA burst size. Let's add a rule to enforce that. - */ - ret = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); - if (ret) - goto out; - - ret = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); - if (ret) - goto out; - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - ret = -ENOMEM; - rtd = kzalloc(sizeof(*rtd), GFP_KERNEL); - if (!rtd) - goto out; - rtd->dma_desc_array = - dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, - &rtd->dma_desc_array_phys, GFP_KERNEL); - if (!rtd->dma_desc_array) - goto err1; - - rtd->dma_ch = -1; - runtime->private_data = rtd; - return 0; - - err1: - kfree(rtd); - out: - return ret; -} -EXPORT_SYMBOL(__pxa2xx_pcm_open); - -int __pxa2xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *rtd = runtime->private_data; - - dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, - rtd->dma_desc_array, rtd->dma_desc_array_phys); - kfree(rtd); - return 0; -} -EXPORT_SYMBOL(__pxa2xx_pcm_close); - -int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} -EXPORT_SYMBOL(pxa2xx_pcm_mmap); - -int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - return 0; -} -EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer); - -void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} -EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers); - -MODULE_AUTHOR("Nicolas Pitre"); -MODULE_DESCRIPTION("Intel PXA2xx sound library"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/arm/pxa2xx-pcm.c b/ANDROID_3.4.5/sound/arm/pxa2xx-pcm.c deleted file mode 100644 index 26422a35..00000000 --- a/ANDROID_3.4.5/sound/arm/pxa2xx-pcm.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip - * - * Author: Nicolas Pitre - * Created: Nov 30, 2004 - * Copyright: (C) 2004 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "pxa2xx-pcm.h" - -static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct pxa2xx_pcm_client *client = substream->private_data; - - __pxa2xx_pcm_prepare(substream); - - return client->prepare(substream); -} - -static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct pxa2xx_pcm_client *client = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *rtd; - int ret; - - ret = __pxa2xx_pcm_open(substream); - if (ret) - goto out; - - rtd = runtime->private_data; - - rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - client->playback_params : client->capture_params; - ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW, - pxa2xx_pcm_dma_irq, substream); - if (ret < 0) - goto err2; - rtd->dma_ch = ret; - - ret = client->startup(substream); - if (!ret) - goto out; - - pxa_free_dma(rtd->dma_ch); - err2: - __pxa2xx_pcm_close(substream); - out: - return ret; -} - -static int pxa2xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct pxa2xx_pcm_client *client = substream->private_data; - struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; - - pxa_free_dma(rtd->dma_ch); - client->shutdown(substream); - - return __pxa2xx_pcm_close(substream); -} - -static struct snd_pcm_ops pxa2xx_pcm_ops = { - .open = pxa2xx_pcm_open, - .close = pxa2xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = __pxa2xx_pcm_hw_params, - .hw_free = __pxa2xx_pcm_hw_free, - .prepare = pxa2xx_pcm_prepare, - .trigger = pxa2xx_pcm_trigger, - .pointer = pxa2xx_pcm_pointer, - .mmap = pxa2xx_pcm_mmap, -}; - -static u64 pxa2xx_pcm_dmamask = 0xffffffff; - -int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client, - struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int play = client->playback_params ? 1 : 0; - int capt = client->capture_params ? 1 : 0; - int ret; - - ret = snd_pcm_new(card, "PXA2xx-PCM", 0, play, capt, &pcm); - if (ret) - goto out; - - pcm->private_data = client; - pcm->private_free = pxa2xx_pcm_free_dma_buffers; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &pxa2xx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = 0xffffffff; - - if (play) { - int stream = SNDRV_PCM_STREAM_PLAYBACK; - snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops); - ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream); - if (ret) - goto out; - } - if (capt) { - int stream = SNDRV_PCM_STREAM_CAPTURE; - snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops); - ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream); - if (ret) - goto out; - } - - if (rpcm) - *rpcm = pcm; - ret = 0; - - out: - return ret; -} - -EXPORT_SYMBOL(pxa2xx_pcm_new); - -MODULE_AUTHOR("Nicolas Pitre"); -MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/arm/pxa2xx-pcm.h b/ANDROID_3.4.5/sound/arm/pxa2xx-pcm.h deleted file mode 100644 index 65f86b56..00000000 --- a/ANDROID_3.4.5/sound/arm/pxa2xx-pcm.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip - * - * Author: Nicolas Pitre - * Created: Nov 30, 2004 - * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include - -struct pxa2xx_runtime_data { - int dma_ch; - struct pxa2xx_pcm_dma_params *params; - pxa_dma_desc *dma_desc_array; - dma_addr_t dma_desc_array_phys; -}; - -struct pxa2xx_pcm_client { - struct pxa2xx_pcm_dma_params *playback_params; - struct pxa2xx_pcm_dma_params *capture_params; - int (*startup)(struct snd_pcm_substream *); - void (*shutdown)(struct snd_pcm_substream *); - int (*prepare)(struct snd_pcm_substream *); -}; - -extern int pxa2xx_pcm_new(struct snd_card *, struct pxa2xx_pcm_client *, struct snd_pcm **); - diff --git a/ANDROID_3.4.5/sound/atmel/Kconfig b/ANDROID_3.4.5/sound/atmel/Kconfig deleted file mode 100644 index 94de43a0..00000000 --- a/ANDROID_3.4.5/sound/atmel/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -menu "Atmel devices (AVR32 and AT91)" - depends on AVR32 || ARCH_AT91 - -config SND_ATMEL_ABDAC - tristate "Atmel Audio Bitstream DAC (ABDAC) driver" - select SND_PCM - depends on DW_DMAC && AVR32 - help - ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC). - -config SND_ATMEL_AC97C - tristate "Atmel AC97 Controller (AC97C) driver" - select SND_PCM - select SND_AC97_CODEC - depends on (DW_DMAC && AVR32) || ARCH_AT91 - help - ALSA sound driver for the Atmel AC97 controller. - -endmenu diff --git a/ANDROID_3.4.5/sound/atmel/Makefile b/ANDROID_3.4.5/sound/atmel/Makefile deleted file mode 100644 index 219dcfac..00000000 --- a/ANDROID_3.4.5/sound/atmel/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -snd-atmel-abdac-objs := abdac.o -snd-atmel-ac97c-objs := ac97c.o - -obj-$(CONFIG_SND_ATMEL_ABDAC) += snd-atmel-abdac.o -obj-$(CONFIG_SND_ATMEL_AC97C) += snd-atmel-ac97c.o diff --git a/ANDROID_3.4.5/sound/atmel/abdac.c b/ANDROID_3.4.5/sound/atmel/abdac.c deleted file mode 100644 index f7c2bb08..00000000 --- a/ANDROID_3.4.5/sound/atmel/abdac.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Driver for the Atmel on-chip Audio Bitstream DAC (ABDAC) - * - * Copyright (C) 2006-2009 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* DAC register offsets */ -#define DAC_DATA 0x0000 -#define DAC_CTRL 0x0008 -#define DAC_INT_MASK 0x000c -#define DAC_INT_EN 0x0010 -#define DAC_INT_DIS 0x0014 -#define DAC_INT_CLR 0x0018 -#define DAC_INT_STATUS 0x001c - -/* Bitfields in CTRL */ -#define DAC_SWAP_OFFSET 30 -#define DAC_SWAP_SIZE 1 -#define DAC_EN_OFFSET 31 -#define DAC_EN_SIZE 1 - -/* Bitfields in INT_MASK/INT_EN/INT_DIS/INT_STATUS/INT_CLR */ -#define DAC_UNDERRUN_OFFSET 28 -#define DAC_UNDERRUN_SIZE 1 -#define DAC_TX_READY_OFFSET 29 -#define DAC_TX_READY_SIZE 1 - -/* Bit manipulation macros */ -#define DAC_BIT(name) \ - (1 << DAC_##name##_OFFSET) -#define DAC_BF(name, value) \ - (((value) & ((1 << DAC_##name##_SIZE) - 1)) \ - << DAC_##name##_OFFSET) -#define DAC_BFEXT(name, value) \ - (((value) >> DAC_##name##_OFFSET) \ - & ((1 << DAC_##name##_SIZE) - 1)) -#define DAC_BFINS(name, value, old) \ - (((old) & ~(((1 << DAC_##name##_SIZE) - 1) \ - << DAC_##name##_OFFSET)) \ - | DAC_BF(name, value)) - -/* Register access macros */ -#define dac_readl(port, reg) \ - __raw_readl((port)->regs + DAC_##reg) -#define dac_writel(port, reg, value) \ - __raw_writel((value), (port)->regs + DAC_##reg) - -/* - * ABDAC supports a maximum of 6 different rates from a generic clock. The - * generic clock has a power of two divider, which gives 6 steps from 192 kHz - * to 5112 Hz. - */ -#define MAX_NUM_RATES 6 -/* ALSA seems to use rates between 192000 Hz and 5112 Hz. */ -#define RATE_MAX 192000 -#define RATE_MIN 5112 - -enum { - DMA_READY = 0, -}; - -struct atmel_abdac_dma { - struct dma_chan *chan; - struct dw_cyclic_desc *cdesc; -}; - -struct atmel_abdac { - struct clk *pclk; - struct clk *sample_clk; - struct platform_device *pdev; - struct atmel_abdac_dma dma; - - struct snd_pcm_hw_constraint_list constraints_rates; - struct snd_pcm_substream *substream; - struct snd_card *card; - struct snd_pcm *pcm; - - void __iomem *regs; - unsigned long flags; - unsigned int rates[MAX_NUM_RATES]; - unsigned int rates_num; - int irq; -}; - -#define get_dac(card) ((struct atmel_abdac *)(card)->private_data) - -/* This function is called by the DMA driver. */ -static void atmel_abdac_dma_period_done(void *arg) -{ - struct atmel_abdac *dac = arg; - snd_pcm_period_elapsed(dac->substream); -} - -static int atmel_abdac_prepare_dma(struct atmel_abdac *dac, - struct snd_pcm_substream *substream, - enum dma_data_direction direction) -{ - struct dma_chan *chan = dac->dma.chan; - struct dw_cyclic_desc *cdesc; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long buffer_len, period_len; - - /* - * We don't do DMA on "complex" transfers, i.e. with - * non-halfword-aligned buffers or lengths. - */ - if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { - dev_dbg(&dac->pdev->dev, "too complex transfer\n"); - return -EINVAL; - } - - buffer_len = frames_to_bytes(runtime, runtime->buffer_size); - period_len = frames_to_bytes(runtime, runtime->period_size); - - cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, - period_len, DMA_MEM_TO_DEV); - if (IS_ERR(cdesc)) { - dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n"); - return PTR_ERR(cdesc); - } - - cdesc->period_callback = atmel_abdac_dma_period_done; - cdesc->period_callback_param = dac; - - dac->dma.cdesc = cdesc; - - set_bit(DMA_READY, &dac->flags); - - return 0; -} - -static struct snd_pcm_hardware atmel_abdac_hw = { - .info = (SNDRV_PCM_INFO_MMAP - | SNDRV_PCM_INFO_MMAP_VALID - | SNDRV_PCM_INFO_INTERLEAVED - | SNDRV_PCM_INFO_BLOCK_TRANSFER - | SNDRV_PCM_INFO_RESUME - | SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_BE), - .rates = (SNDRV_PCM_RATE_KNOT), - .rate_min = RATE_MIN, - .rate_max = RATE_MAX, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 64 * 4096, - .period_bytes_min = 4096, - .period_bytes_max = 4096, - .periods_min = 6, - .periods_max = 64, -}; - -static int atmel_abdac_open(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - - dac->substream = substream; - atmel_abdac_hw.rate_max = dac->rates[dac->rates_num - 1]; - atmel_abdac_hw.rate_min = dac->rates[0]; - substream->runtime->hw = atmel_abdac_hw; - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &dac->constraints_rates); -} - -static int atmel_abdac_close(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - dac->substream = NULL; - return 0; -} - -static int atmel_abdac_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - int retval; - - retval = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (retval < 0) - return retval; - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (retval == 1) - if (test_and_clear_bit(DMA_READY, &dac->flags)) - dw_dma_cyclic_free(dac->dma.chan); - - return retval; -} - -static int atmel_abdac_hw_free(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - if (test_and_clear_bit(DMA_READY, &dac->flags)) - dw_dma_cyclic_free(dac->dma.chan); - return snd_pcm_lib_free_pages(substream); -} - -static int atmel_abdac_prepare(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - int retval; - - retval = clk_set_rate(dac->sample_clk, 256 * substream->runtime->rate); - if (retval) - return retval; - - if (!test_bit(DMA_READY, &dac->flags)) - retval = atmel_abdac_prepare_dma(dac, substream, DMA_TO_DEVICE); - - return retval; -} - -static int atmel_abdac_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - int retval = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ - case SNDRV_PCM_TRIGGER_START: - clk_enable(dac->sample_clk); - retval = dw_dma_cyclic_start(dac->dma.chan); - if (retval) - goto out; - dac_writel(dac, CTRL, DAC_BIT(EN)); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ - case SNDRV_PCM_TRIGGER_STOP: - dw_dma_cyclic_stop(dac->dma.chan); - dac_writel(dac, DATA, 0); - dac_writel(dac, CTRL, 0); - clk_disable(dac->sample_clk); - break; - default: - retval = -EINVAL; - break; - } -out: - return retval; -} - -static snd_pcm_uframes_t -atmel_abdac_pointer(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t frames; - unsigned long bytes; - - bytes = dw_dma_get_src_addr(dac->dma.chan); - bytes -= runtime->dma_addr; - - frames = bytes_to_frames(runtime, bytes); - if (frames >= runtime->buffer_size) - frames -= runtime->buffer_size; - - return frames; -} - -static irqreturn_t abdac_interrupt(int irq, void *dev_id) -{ - struct atmel_abdac *dac = dev_id; - u32 status; - - status = dac_readl(dac, INT_STATUS); - if (status & DAC_BIT(UNDERRUN)) { - dev_err(&dac->pdev->dev, "underrun detected\n"); - dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN)); - } else { - dev_err(&dac->pdev->dev, "spurious interrupt (status=0x%x)\n", - status); - dac_writel(dac, INT_CLR, status); - } - - return IRQ_HANDLED; -} - -static struct snd_pcm_ops atmel_abdac_ops = { - .open = atmel_abdac_open, - .close = atmel_abdac_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = atmel_abdac_hw_params, - .hw_free = atmel_abdac_hw_free, - .prepare = atmel_abdac_prepare, - .trigger = atmel_abdac_trigger, - .pointer = atmel_abdac_pointer, -}; - -static int __devinit atmel_abdac_pcm_new(struct atmel_abdac *dac) -{ - struct snd_pcm_hardware hw = atmel_abdac_hw; - struct snd_pcm *pcm; - int retval; - - retval = snd_pcm_new(dac->card, dac->card->shortname, - dac->pdev->id, 1, 0, &pcm); - if (retval) - return retval; - - strcpy(pcm->name, dac->card->shortname); - pcm->private_data = dac; - pcm->info_flags = 0; - dac->pcm = pcm; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_abdac_ops); - - retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - &dac->pdev->dev, hw.periods_min * hw.period_bytes_min, - hw.buffer_bytes_max); - - return retval; -} - -static bool filter(struct dma_chan *chan, void *slave) -{ - struct dw_dma_slave *dws = slave; - - if (dws->dma_dev == chan->device->dev) { - chan->private = dws; - return true; - } else - return false; -} - -static int set_sample_rates(struct atmel_abdac *dac) -{ - long new_rate = RATE_MAX; - int retval = -EINVAL; - int index = 0; - - /* we start at 192 kHz and work our way down to 5112 Hz */ - while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) { - new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate); - if (new_rate < 0) - break; - /* make sure we are below the ABDAC clock */ - if (new_rate <= clk_get_rate(dac->pclk)) { - dac->rates[index] = new_rate / 256; - index++; - } - /* divide by 256 and then by two to get next rate */ - new_rate /= 256 * 2; - } - - if (index) { - int i; - - /* reverse array, smallest go first */ - for (i = 0; i < (index / 2); i++) { - unsigned int tmp = dac->rates[index - 1 - i]; - dac->rates[index - 1 - i] = dac->rates[i]; - dac->rates[i] = tmp; - } - - dac->constraints_rates.count = index; - dac->constraints_rates.list = dac->rates; - dac->constraints_rates.mask = 0; - dac->rates_num = index; - - retval = 0; - } - - return retval; -} - -static int __devinit atmel_abdac_probe(struct platform_device *pdev) -{ - struct snd_card *card; - struct atmel_abdac *dac; - struct resource *regs; - struct atmel_abdac_pdata *pdata; - struct clk *pclk; - struct clk *sample_clk; - int retval; - int irq; - - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { - dev_dbg(&pdev->dev, "no memory resource\n"); - return -ENXIO; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_dbg(&pdev->dev, "could not get IRQ number\n"); - return irq; - } - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_dbg(&pdev->dev, "no platform data\n"); - return -ENXIO; - } - - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) { - dev_dbg(&pdev->dev, "no peripheral clock\n"); - return PTR_ERR(pclk); - } - sample_clk = clk_get(&pdev->dev, "sample_clk"); - if (IS_ERR(sample_clk)) { - dev_dbg(&pdev->dev, "no sample clock\n"); - retval = PTR_ERR(sample_clk); - goto out_put_pclk; - } - clk_enable(pclk); - - retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct atmel_abdac), &card); - if (retval) { - dev_dbg(&pdev->dev, "could not create sound card device\n"); - goto out_put_sample_clk; - } - - dac = get_dac(card); - - dac->irq = irq; - dac->card = card; - dac->pclk = pclk; - dac->sample_clk = sample_clk; - dac->pdev = pdev; - - retval = set_sample_rates(dac); - if (retval < 0) { - dev_dbg(&pdev->dev, "could not set supported rates\n"); - goto out_free_card; - } - - dac->regs = ioremap(regs->start, resource_size(regs)); - if (!dac->regs) { - dev_dbg(&pdev->dev, "could not remap register memory\n"); - goto out_free_card; - } - - /* make sure the DAC is silent and disabled */ - dac_writel(dac, DATA, 0); - dac_writel(dac, CTRL, 0); - - retval = request_irq(irq, abdac_interrupt, 0, "abdac", dac); - if (retval) { - dev_dbg(&pdev->dev, "could not request irq\n"); - goto out_unmap_regs; - } - - snd_card_set_dev(card, &pdev->dev); - - if (pdata->dws.dma_dev) { - dma_cap_mask_t mask; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - dac->dma.chan = dma_request_channel(mask, filter, &pdata->dws); - if (dac->dma.chan) { - struct dma_slave_config dma_conf = { - .dst_addr = regs->start + DAC_DATA, - .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, - .src_maxburst = 1, - .dst_maxburst = 1, - .direction = DMA_MEM_TO_DEV, - .device_fc = false, - }; - - dmaengine_slave_config(dac->dma.chan, &dma_conf); - } - } - if (!pdata->dws.dma_dev || !dac->dma.chan) { - dev_dbg(&pdev->dev, "DMA not available\n"); - retval = -ENODEV; - goto out_unset_card_dev; - } - - strcpy(card->driver, "Atmel ABDAC"); - strcpy(card->shortname, "Atmel ABDAC"); - sprintf(card->longname, "Atmel Audio Bitstream DAC"); - - retval = atmel_abdac_pcm_new(dac); - if (retval) { - dev_dbg(&pdev->dev, "could not register ABDAC pcm device\n"); - goto out_release_dma; - } - - retval = snd_card_register(card); - if (retval) { - dev_dbg(&pdev->dev, "could not register sound card\n"); - goto out_release_dma; - } - - platform_set_drvdata(pdev, card); - - dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", - dac->regs, dev_name(&dac->dma.chan->dev->device)); - - return retval; - -out_release_dma: - dma_release_channel(dac->dma.chan); - dac->dma.chan = NULL; -out_unset_card_dev: - snd_card_set_dev(card, NULL); - free_irq(irq, dac); -out_unmap_regs: - iounmap(dac->regs); -out_free_card: - snd_card_free(card); -out_put_sample_clk: - clk_put(sample_clk); - clk_disable(pclk); -out_put_pclk: - clk_put(pclk); - return retval; -} - -#ifdef CONFIG_PM -static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct atmel_abdac *dac = card->private_data; - - dw_dma_cyclic_stop(dac->dma.chan); - clk_disable(dac->sample_clk); - clk_disable(dac->pclk); - - return 0; -} - -static int atmel_abdac_resume(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct atmel_abdac *dac = card->private_data; - - clk_enable(dac->pclk); - clk_enable(dac->sample_clk); - if (test_bit(DMA_READY, &dac->flags)) - dw_dma_cyclic_start(dac->dma.chan); - - return 0; -} -#else -#define atmel_abdac_suspend NULL -#define atmel_abdac_resume NULL -#endif - -static int __devexit atmel_abdac_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct atmel_abdac *dac = get_dac(card); - - clk_put(dac->sample_clk); - clk_disable(dac->pclk); - clk_put(dac->pclk); - - dma_release_channel(dac->dma.chan); - dac->dma.chan = NULL; - snd_card_set_dev(card, NULL); - iounmap(dac->regs); - free_irq(dac->irq, dac); - snd_card_free(card); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver atmel_abdac_driver = { - .remove = __devexit_p(atmel_abdac_remove), - .driver = { - .name = "atmel_abdac", - }, - .suspend = atmel_abdac_suspend, - .resume = atmel_abdac_resume, -}; - -static int __init atmel_abdac_init(void) -{ - return platform_driver_probe(&atmel_abdac_driver, - atmel_abdac_probe); -} -module_init(atmel_abdac_init); - -static void __exit atmel_abdac_exit(void) -{ - platform_driver_unregister(&atmel_abdac_driver); -} -module_exit(atmel_abdac_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)"); -MODULE_AUTHOR("Hans-Christian Egtvedt "); diff --git a/ANDROID_3.4.5/sound/atmel/ac97c.c b/ANDROID_3.4.5/sound/atmel/ac97c.c deleted file mode 100644 index 115313ef..00000000 --- a/ANDROID_3.4.5/sound/atmel/ac97c.c +++ /dev/null @@ -1,1231 +0,0 @@ -/* - * Driver for Atmel AC97C - * - * Copyright (C) 2005-2009 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#ifdef CONFIG_ARCH_AT91 -#include -#endif - -#include "ac97c.h" - -enum { - DMA_TX_READY = 0, - DMA_RX_READY, - DMA_TX_CHAN_PRESENT, - DMA_RX_CHAN_PRESENT, -}; - -/* Serialize access to opened variable */ -static DEFINE_MUTEX(opened_mutex); - -struct atmel_ac97c_dma { - struct dma_chan *rx_chan; - struct dma_chan *tx_chan; -}; - -struct atmel_ac97c { - struct clk *pclk; - struct platform_device *pdev; - struct atmel_ac97c_dma dma; - - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_ac97 *ac97; - struct snd_ac97_bus *ac97_bus; - - u64 cur_format; - unsigned int cur_rate; - unsigned long flags; - int playback_period, capture_period; - /* Serialize access to opened variable */ - spinlock_t lock; - void __iomem *regs; - int irq; - int opened; - int reset_pin; -}; - -#define get_chip(card) ((struct atmel_ac97c *)(card)->private_data) - -#define ac97c_writel(chip, reg, val) \ - __raw_writel((val), (chip)->regs + AC97C_##reg) -#define ac97c_readl(chip, reg) \ - __raw_readl((chip)->regs + AC97C_##reg) - -/* This function is called by the DMA driver. */ -static void atmel_ac97c_dma_playback_period_done(void *arg) -{ - struct atmel_ac97c *chip = arg; - snd_pcm_period_elapsed(chip->playback_substream); -} - -static void atmel_ac97c_dma_capture_period_done(void *arg) -{ - struct atmel_ac97c *chip = arg; - snd_pcm_period_elapsed(chip->capture_substream); -} - -static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, - struct snd_pcm_substream *substream, - enum dma_transfer_direction direction) -{ - struct dma_chan *chan; - struct dw_cyclic_desc *cdesc; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long buffer_len, period_len; - - /* - * We don't do DMA on "complex" transfers, i.e. with - * non-halfword-aligned buffers or lengths. - */ - if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { - dev_dbg(&chip->pdev->dev, "too complex transfer\n"); - return -EINVAL; - } - - if (direction == DMA_MEM_TO_DEV) - chan = chip->dma.tx_chan; - else - chan = chip->dma.rx_chan; - - buffer_len = frames_to_bytes(runtime, runtime->buffer_size); - period_len = frames_to_bytes(runtime, runtime->period_size); - - cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, - period_len, direction); - if (IS_ERR(cdesc)) { - dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n"); - return PTR_ERR(cdesc); - } - - if (direction == DMA_MEM_TO_DEV) { - cdesc->period_callback = atmel_ac97c_dma_playback_period_done; - set_bit(DMA_TX_READY, &chip->flags); - } else { - cdesc->period_callback = atmel_ac97c_dma_capture_period_done; - set_bit(DMA_RX_READY, &chip->flags); - } - - cdesc->period_callback_param = chip; - - return 0; -} - -static struct snd_pcm_hardware atmel_ac97c_hw = { - .info = (SNDRV_PCM_INFO_MMAP - | SNDRV_PCM_INFO_MMAP_VALID - | SNDRV_PCM_INFO_INTERLEAVED - | SNDRV_PCM_INFO_BLOCK_TRANSFER - | SNDRV_PCM_INFO_JOINT_DUPLEX - | SNDRV_PCM_INFO_RESUME - | SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_BE - | SNDRV_PCM_FMTBIT_S16_LE), - .rates = (SNDRV_PCM_RATE_CONTINUOUS), - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 2 * 2 * 64 * 2048, - .period_bytes_min = 4096, - .period_bytes_max = 4096, - .periods_min = 6, - .periods_max = 64, -}; - -static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - mutex_lock(&opened_mutex); - chip->opened++; - runtime->hw = atmel_ac97c_hw; - if (chip->cur_rate) { - runtime->hw.rate_min = chip->cur_rate; - runtime->hw.rate_max = chip->cur_rate; - } - if (chip->cur_format) - runtime->hw.formats = (1ULL << chip->cur_format); - mutex_unlock(&opened_mutex); - chip->playback_substream = substream; - return 0; -} - -static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - mutex_lock(&opened_mutex); - chip->opened++; - runtime->hw = atmel_ac97c_hw; - if (chip->cur_rate) { - runtime->hw.rate_min = chip->cur_rate; - runtime->hw.rate_max = chip->cur_rate; - } - if (chip->cur_format) - runtime->hw.formats = (1ULL << chip->cur_format); - mutex_unlock(&opened_mutex); - chip->capture_substream = substream; - return 0; -} - -static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - - mutex_lock(&opened_mutex); - chip->opened--; - if (!chip->opened) { - chip->cur_rate = 0; - chip->cur_format = 0; - } - mutex_unlock(&opened_mutex); - - chip->playback_substream = NULL; - - return 0; -} - -static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - - mutex_lock(&opened_mutex); - chip->opened--; - if (!chip->opened) { - chip->cur_rate = 0; - chip->cur_format = 0; - } - mutex_unlock(&opened_mutex); - - chip->capture_substream = NULL; - - return 0; -} - -static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - int retval; - - retval = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (retval < 0) - return retval; - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (cpu_is_at32ap7000()) { - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (retval == 1) - if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.tx_chan); - } - /* Set restrictions to params. */ - mutex_lock(&opened_mutex); - chip->cur_rate = params_rate(hw_params); - chip->cur_format = params_format(hw_params); - mutex_unlock(&opened_mutex); - - return retval; -} - -static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - int retval; - - retval = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (retval < 0) - return retval; - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (cpu_is_at32ap7000()) { - if (retval < 0) - return retval; - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (retval == 1) - if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.rx_chan); - } - - /* Set restrictions to params. */ - mutex_lock(&opened_mutex); - chip->cur_rate = params_rate(hw_params); - chip->cur_format = params_format(hw_params); - mutex_unlock(&opened_mutex); - - return retval; -} - -static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - if (cpu_is_at32ap7000()) { - if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.tx_chan); - } - return snd_pcm_lib_free_pages(substream); -} - -static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - if (cpu_is_at32ap7000()) { - if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.rx_chan); - } - return snd_pcm_lib_free_pages(substream); -} - -static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int block_size = frames_to_bytes(runtime, runtime->period_size); - unsigned long word = ac97c_readl(chip, OCA); - int retval; - - chip->playback_period = 0; - word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); - - /* assign channels to AC97C channel A */ - switch (runtime->channels) { - case 1: - word |= AC97C_CH_ASSIGN(PCM_LEFT, A); - break; - case 2: - word |= AC97C_CH_ASSIGN(PCM_LEFT, A) - | AC97C_CH_ASSIGN(PCM_RIGHT, A); - break; - default: - /* TODO: support more than two channels */ - return -EINVAL; - } - ac97c_writel(chip, OCA, word); - - /* configure sample format and size */ - word = ac97c_readl(chip, CAMR); - if (chip->opened <= 1) - word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; - else - word |= AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; - - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - if (cpu_is_at32ap7000()) - word |= AC97C_CMR_CEM_LITTLE; - break; - case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ - word &= ~(AC97C_CMR_CEM_LITTLE); - break; - default: - word = ac97c_readl(chip, OCA); - word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); - ac97c_writel(chip, OCA, word); - return -EINVAL; - } - - /* Enable underrun interrupt on channel A */ - word |= AC97C_CSR_UNRUN; - - ac97c_writel(chip, CAMR, word); - - /* Enable channel A event interrupt */ - word = ac97c_readl(chip, IMR); - word |= AC97C_SR_CAEVT; - ac97c_writel(chip, IER, word); - - /* set variable rate if needed */ - if (runtime->rate != 48000) { - word = ac97c_readl(chip, MR); - word |= AC97C_MR_VRA; - ac97c_writel(chip, MR, word); - } else { - word = ac97c_readl(chip, MR); - word &= ~(AC97C_MR_VRA); - ac97c_writel(chip, MR, word); - } - - retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, - runtime->rate); - if (retval) - dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", - runtime->rate); - - if (cpu_is_at32ap7000()) { - if (!test_bit(DMA_TX_READY, &chip->flags)) - retval = atmel_ac97c_prepare_dma(chip, substream, - DMA_MEM_TO_DEV); - } else { - /* Initialize and start the PDC */ - writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR); - writel(block_size / 2, chip->regs + ATMEL_PDC_TCR); - writel(runtime->dma_addr + block_size, - chip->regs + ATMEL_PDC_TNPR); - writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR); - } - - return retval; -} - -static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int block_size = frames_to_bytes(runtime, runtime->period_size); - unsigned long word = ac97c_readl(chip, ICA); - int retval; - - chip->capture_period = 0; - word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); - - /* assign channels to AC97C channel A */ - switch (runtime->channels) { - case 1: - word |= AC97C_CH_ASSIGN(PCM_LEFT, A); - break; - case 2: - word |= AC97C_CH_ASSIGN(PCM_LEFT, A) - | AC97C_CH_ASSIGN(PCM_RIGHT, A); - break; - default: - /* TODO: support more than two channels */ - return -EINVAL; - } - ac97c_writel(chip, ICA, word); - - /* configure sample format and size */ - word = ac97c_readl(chip, CAMR); - if (chip->opened <= 1) - word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; - else - word |= AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16; - - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - if (cpu_is_at32ap7000()) - word |= AC97C_CMR_CEM_LITTLE; - break; - case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ - word &= ~(AC97C_CMR_CEM_LITTLE); - break; - default: - word = ac97c_readl(chip, ICA); - word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT)); - ac97c_writel(chip, ICA, word); - return -EINVAL; - } - - /* Enable overrun interrupt on channel A */ - word |= AC97C_CSR_OVRUN; - - ac97c_writel(chip, CAMR, word); - - /* Enable channel A event interrupt */ - word = ac97c_readl(chip, IMR); - word |= AC97C_SR_CAEVT; - ac97c_writel(chip, IER, word); - - /* set variable rate if needed */ - if (runtime->rate != 48000) { - word = ac97c_readl(chip, MR); - word |= AC97C_MR_VRA; - ac97c_writel(chip, MR, word); - } else { - word = ac97c_readl(chip, MR); - word &= ~(AC97C_MR_VRA); - ac97c_writel(chip, MR, word); - } - - retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, - runtime->rate); - if (retval) - dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", - runtime->rate); - - if (cpu_is_at32ap7000()) { - if (!test_bit(DMA_RX_READY, &chip->flags)) - retval = atmel_ac97c_prepare_dma(chip, substream, - DMA_DEV_TO_MEM); - } else { - /* Initialize and start the PDC */ - writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR); - writel(block_size / 2, chip->regs + ATMEL_PDC_RCR); - writel(runtime->dma_addr + block_size, - chip->regs + ATMEL_PDC_RNPR); - writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR); - } - - return retval; -} - -static int -atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - unsigned long camr, ptcr = 0; - int retval = 0; - - camr = ac97c_readl(chip, CAMR); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ - case SNDRV_PCM_TRIGGER_START: - if (cpu_is_at32ap7000()) { - retval = dw_dma_cyclic_start(chip->dma.tx_chan); - if (retval) - goto out; - } else { - ptcr = ATMEL_PDC_TXTEN; - } - camr |= AC97C_CMR_CENA | AC97C_CSR_ENDTX; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ - case SNDRV_PCM_TRIGGER_STOP: - if (cpu_is_at32ap7000()) - dw_dma_cyclic_stop(chip->dma.tx_chan); - else - ptcr |= ATMEL_PDC_TXTDIS; - if (chip->opened <= 1) - camr &= ~AC97C_CMR_CENA; - break; - default: - retval = -EINVAL; - goto out; - } - - ac97c_writel(chip, CAMR, camr); - if (!cpu_is_at32ap7000()) - writel(ptcr, chip->regs + ATMEL_PDC_PTCR); -out: - return retval; -} - -static int -atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - unsigned long camr, ptcr = 0; - int retval = 0; - - camr = ac97c_readl(chip, CAMR); - ptcr = readl(chip->regs + ATMEL_PDC_PTSR); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ - case SNDRV_PCM_TRIGGER_START: - if (cpu_is_at32ap7000()) { - retval = dw_dma_cyclic_start(chip->dma.rx_chan); - if (retval) - goto out; - } else { - ptcr = ATMEL_PDC_RXTEN; - } - camr |= AC97C_CMR_CENA | AC97C_CSR_ENDRX; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ - case SNDRV_PCM_TRIGGER_STOP: - if (cpu_is_at32ap7000()) - dw_dma_cyclic_stop(chip->dma.rx_chan); - else - ptcr |= (ATMEL_PDC_RXTDIS); - if (chip->opened <= 1) - camr &= ~AC97C_CMR_CENA; - break; - default: - retval = -EINVAL; - break; - } - - ac97c_writel(chip, CAMR, camr); - if (!cpu_is_at32ap7000()) - writel(ptcr, chip->regs + ATMEL_PDC_PTCR); -out: - return retval; -} - -static snd_pcm_uframes_t -atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t frames; - unsigned long bytes; - - if (cpu_is_at32ap7000()) - bytes = dw_dma_get_src_addr(chip->dma.tx_chan); - else - bytes = readl(chip->regs + ATMEL_PDC_TPR); - bytes -= runtime->dma_addr; - - frames = bytes_to_frames(runtime, bytes); - if (frames >= runtime->buffer_size) - frames -= runtime->buffer_size; - return frames; -} - -static snd_pcm_uframes_t -atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t frames; - unsigned long bytes; - - if (cpu_is_at32ap7000()) - bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); - else - bytes = readl(chip->regs + ATMEL_PDC_RPR); - bytes -= runtime->dma_addr; - - frames = bytes_to_frames(runtime, bytes); - if (frames >= runtime->buffer_size) - frames -= runtime->buffer_size; - return frames; -} - -static struct snd_pcm_ops atmel_ac97_playback_ops = { - .open = atmel_ac97c_playback_open, - .close = atmel_ac97c_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = atmel_ac97c_playback_hw_params, - .hw_free = atmel_ac97c_playback_hw_free, - .prepare = atmel_ac97c_playback_prepare, - .trigger = atmel_ac97c_playback_trigger, - .pointer = atmel_ac97c_playback_pointer, -}; - -static struct snd_pcm_ops atmel_ac97_capture_ops = { - .open = atmel_ac97c_capture_open, - .close = atmel_ac97c_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = atmel_ac97c_capture_hw_params, - .hw_free = atmel_ac97c_capture_hw_free, - .prepare = atmel_ac97c_capture_prepare, - .trigger = atmel_ac97c_capture_trigger, - .pointer = atmel_ac97c_capture_pointer, -}; - -static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) -{ - struct atmel_ac97c *chip = (struct atmel_ac97c *)dev; - irqreturn_t retval = IRQ_NONE; - u32 sr = ac97c_readl(chip, SR); - u32 casr = ac97c_readl(chip, CASR); - u32 cosr = ac97c_readl(chip, COSR); - u32 camr = ac97c_readl(chip, CAMR); - - if (sr & AC97C_SR_CAEVT) { - struct snd_pcm_runtime *runtime; - int offset, next_period, block_size; - dev_dbg(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n", - casr & AC97C_CSR_OVRUN ? " OVRUN" : "", - casr & AC97C_CSR_RXRDY ? " RXRDY" : "", - casr & AC97C_CSR_UNRUN ? " UNRUN" : "", - casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", - casr & AC97C_CSR_TXRDY ? " TXRDY" : "", - !casr ? " NONE" : ""); - if (!cpu_is_at32ap7000()) { - if ((casr & camr) & AC97C_CSR_ENDTX) { - runtime = chip->playback_substream->runtime; - block_size = frames_to_bytes(runtime, - runtime->period_size); - chip->playback_period++; - - if (chip->playback_period == runtime->periods) - chip->playback_period = 0; - next_period = chip->playback_period + 1; - if (next_period == runtime->periods) - next_period = 0; - - offset = block_size * next_period; - - writel(runtime->dma_addr + offset, - chip->regs + ATMEL_PDC_TNPR); - writel(block_size / 2, - chip->regs + ATMEL_PDC_TNCR); - - snd_pcm_period_elapsed( - chip->playback_substream); - } - if ((casr & camr) & AC97C_CSR_ENDRX) { - runtime = chip->capture_substream->runtime; - block_size = frames_to_bytes(runtime, - runtime->period_size); - chip->capture_period++; - - if (chip->capture_period == runtime->periods) - chip->capture_period = 0; - next_period = chip->capture_period + 1; - if (next_period == runtime->periods) - next_period = 0; - - offset = block_size * next_period; - - writel(runtime->dma_addr + offset, - chip->regs + ATMEL_PDC_RNPR); - writel(block_size / 2, - chip->regs + ATMEL_PDC_RNCR); - snd_pcm_period_elapsed(chip->capture_substream); - } - } - retval = IRQ_HANDLED; - } - - if (sr & AC97C_SR_COEVT) { - dev_info(&chip->pdev->dev, "codec channel event%s%s%s%s%s\n", - cosr & AC97C_CSR_OVRUN ? " OVRUN" : "", - cosr & AC97C_CSR_RXRDY ? " RXRDY" : "", - cosr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", - cosr & AC97C_CSR_TXRDY ? " TXRDY" : "", - !cosr ? " NONE" : ""); - retval = IRQ_HANDLED; - } - - if (retval == IRQ_NONE) { - dev_err(&chip->pdev->dev, "spurious interrupt sr 0x%08x " - "casr 0x%08x cosr 0x%08x\n", sr, casr, cosr); - } - - return retval; -} - -static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = { - /* Playback */ - { - .exclusive = 1, - .r = { { - .slots = ((1 << AC97_SLOT_PCM_LEFT) - | (1 << AC97_SLOT_PCM_RIGHT)), - } }, - }, - /* PCM in */ - { - .stream = 1, - .exclusive = 1, - .r = { { - .slots = ((1 << AC97_SLOT_PCM_LEFT) - | (1 << AC97_SLOT_PCM_RIGHT)), - } } - }, - /* Mic in */ - { - .stream = 1, - .exclusive = 1, - .r = { { - .slots = (1<flags); - playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - - if (!cpu_is_at32ap7000()) { - err = snd_ac97_pcm_assign(chip->ac97_bus, - ARRAY_SIZE(at91_ac97_pcm_defs), - at91_ac97_pcm_defs); - if (err) - return err; - } - retval = snd_pcm_new(chip->card, chip->card->shortname, - chip->pdev->id, playback, capture, &pcm); - if (retval) - return retval; - - if (capture) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &atmel_ac97_capture_ops); - if (playback) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &atmel_ac97_playback_ops); - - retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - &chip->pdev->dev, hw.periods_min * hw.period_bytes_min, - hw.buffer_bytes_max); - if (retval) - return retval; - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->shortname); - chip->pcm = pcm; - - return 0; -} - -static int atmel_ac97c_mixer_new(struct atmel_ac97c *chip) -{ - struct snd_ac97_template template; - memset(&template, 0, sizeof(template)); - template.private_data = chip; - return snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97); -} - -static void atmel_ac97c_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct atmel_ac97c *chip = get_chip(ac97); - unsigned long word; - int timeout = 40; - - word = (reg & 0x7f) << 16 | val; - - do { - if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) { - ac97c_writel(chip, COTHR, word); - return; - } - udelay(1); - } while (--timeout); - - dev_dbg(&chip->pdev->dev, "codec write timeout\n"); -} - -static unsigned short atmel_ac97c_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct atmel_ac97c *chip = get_chip(ac97); - unsigned long word; - int timeout = 40; - int write = 10; - - word = (0x80 | (reg & 0x7f)) << 16; - - if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) - ac97c_readl(chip, CORHR); - -retry_write: - timeout = 40; - - do { - if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) { - ac97c_writel(chip, COTHR, word); - goto read_reg; - } - udelay(10); - } while (--timeout); - - if (!--write) - goto timed_out; - goto retry_write; - -read_reg: - do { - if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) { - unsigned short val = ac97c_readl(chip, CORHR); - return val; - } - udelay(10); - } while (--timeout); - - if (!--write) - goto timed_out; - goto retry_write; - -timed_out: - dev_dbg(&chip->pdev->dev, "codec read timeout\n"); - return 0xffff; -} - -static bool filter(struct dma_chan *chan, void *slave) -{ - struct dw_dma_slave *dws = slave; - - if (dws->dma_dev == chan->device->dev) { - chan->private = dws; - return true; - } else - return false; -} - -static void atmel_ac97c_reset(struct atmel_ac97c *chip) -{ - ac97c_writel(chip, MR, 0); - ac97c_writel(chip, MR, AC97C_MR_ENA); - ac97c_writel(chip, CAMR, 0); - ac97c_writel(chip, COMR, 0); - - if (gpio_is_valid(chip->reset_pin)) { - gpio_set_value(chip->reset_pin, 0); - /* AC97 v2.2 specifications says minimum 1 us. */ - udelay(2); - gpio_set_value(chip->reset_pin, 1); - } else { - ac97c_writel(chip, MR, AC97C_MR_WRST | AC97C_MR_ENA); - udelay(2); - ac97c_writel(chip, MR, AC97C_MR_ENA); - } -} - -static int __devinit atmel_ac97c_probe(struct platform_device *pdev) -{ - struct snd_card *card; - struct atmel_ac97c *chip; - struct resource *regs; - struct ac97c_platform_data *pdata; - struct clk *pclk; - static struct snd_ac97_bus_ops ops = { - .write = atmel_ac97c_write, - .read = atmel_ac97c_read, - }; - int retval; - int irq; - - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { - dev_dbg(&pdev->dev, "no memory resource\n"); - return -ENXIO; - } - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_dbg(&pdev->dev, "no platform data\n"); - return -ENXIO; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_dbg(&pdev->dev, "could not get irq\n"); - return -ENXIO; - } - - if (cpu_is_at32ap7000()) { - pclk = clk_get(&pdev->dev, "pclk"); - } else { - pclk = clk_get(&pdev->dev, "ac97_clk"); - } - - if (IS_ERR(pclk)) { - dev_dbg(&pdev->dev, "no peripheral clock\n"); - return PTR_ERR(pclk); - } - clk_enable(pclk); - - retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, - THIS_MODULE, sizeof(struct atmel_ac97c), &card); - if (retval) { - dev_dbg(&pdev->dev, "could not create sound card device\n"); - goto err_snd_card_new; - } - - chip = get_chip(card); - - retval = request_irq(irq, atmel_ac97c_interrupt, 0, "AC97C", chip); - if (retval) { - dev_dbg(&pdev->dev, "unable to request irq %d\n", irq); - goto err_request_irq; - } - chip->irq = irq; - - spin_lock_init(&chip->lock); - - strcpy(card->driver, "Atmel AC97C"); - strcpy(card->shortname, "Atmel AC97C"); - sprintf(card->longname, "Atmel AC97 controller"); - - chip->card = card; - chip->pclk = pclk; - chip->pdev = pdev; - chip->regs = ioremap(regs->start, resource_size(regs)); - - if (!chip->regs) { - dev_dbg(&pdev->dev, "could not remap register memory\n"); - goto err_ioremap; - } - - if (gpio_is_valid(pdata->reset_pin)) { - if (gpio_request(pdata->reset_pin, "reset_pin")) { - dev_dbg(&pdev->dev, "reset pin not available\n"); - chip->reset_pin = -ENODEV; - } else { - gpio_direction_output(pdata->reset_pin, 1); - chip->reset_pin = pdata->reset_pin; - } - } - - snd_card_set_dev(card, &pdev->dev); - - atmel_ac97c_reset(chip); - - /* Enable overrun interrupt from codec channel */ - ac97c_writel(chip, COMR, AC97C_CSR_OVRUN); - ac97c_writel(chip, IER, ac97c_readl(chip, IMR) | AC97C_SR_COEVT); - - retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); - if (retval) { - dev_dbg(&pdev->dev, "could not register on ac97 bus\n"); - goto err_ac97_bus; - } - - retval = atmel_ac97c_mixer_new(chip); - if (retval) { - dev_dbg(&pdev->dev, "could not register ac97 mixer\n"); - goto err_ac97_bus; - } - - if (cpu_is_at32ap7000()) { - if (pdata->rx_dws.dma_dev) { - dma_cap_mask_t mask; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - chip->dma.rx_chan = dma_request_channel(mask, filter, - &pdata->rx_dws); - if (chip->dma.rx_chan) { - struct dma_slave_config dma_conf = { - .src_addr = regs->start + AC97C_CARHR + - 2, - .src_addr_width = - DMA_SLAVE_BUSWIDTH_2_BYTES, - .src_maxburst = 1, - .dst_maxburst = 1, - .direction = DMA_DEV_TO_MEM, - .device_fc = false, - }; - - dmaengine_slave_config(chip->dma.rx_chan, - &dma_conf); - } - - dev_info(&chip->pdev->dev, "using %s for DMA RX\n", - dev_name(&chip->dma.rx_chan->dev->device)); - set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - } - - if (pdata->tx_dws.dma_dev) { - dma_cap_mask_t mask; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - chip->dma.tx_chan = dma_request_channel(mask, filter, - &pdata->tx_dws); - if (chip->dma.tx_chan) { - struct dma_slave_config dma_conf = { - .dst_addr = regs->start + AC97C_CATHR + - 2, - .dst_addr_width = - DMA_SLAVE_BUSWIDTH_2_BYTES, - .src_maxburst = 1, - .dst_maxburst = 1, - .direction = DMA_MEM_TO_DEV, - .device_fc = false, - }; - - dmaengine_slave_config(chip->dma.tx_chan, - &dma_conf); - } - - dev_info(&chip->pdev->dev, "using %s for DMA TX\n", - dev_name(&chip->dma.tx_chan->dev->device)); - set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - } - - if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) && - !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) { - dev_dbg(&pdev->dev, "DMA not available\n"); - retval = -ENODEV; - goto err_dma; - } - } else { - /* Just pretend that we have DMA channel(for at91 i is actually - * the PDC) */ - set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - } - - retval = atmel_ac97c_pcm_new(chip); - if (retval) { - dev_dbg(&pdev->dev, "could not register ac97 pcm device\n"); - goto err_dma; - } - - retval = snd_card_register(card); - if (retval) { - dev_dbg(&pdev->dev, "could not register sound card\n"); - goto err_dma; - } - - platform_set_drvdata(pdev, card); - - dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p, irq = %d\n", - chip->regs, irq); - - return 0; - -err_dma: - if (cpu_is_at32ap7000()) { - if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) - dma_release_channel(chip->dma.rx_chan); - if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) - dma_release_channel(chip->dma.tx_chan); - clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - chip->dma.rx_chan = NULL; - chip->dma.tx_chan = NULL; - } -err_ac97_bus: - snd_card_set_dev(card, NULL); - - if (gpio_is_valid(chip->reset_pin)) - gpio_free(chip->reset_pin); - - iounmap(chip->regs); -err_ioremap: - free_irq(irq, chip); -err_request_irq: - snd_card_free(card); -err_snd_card_new: - clk_disable(pclk); - clk_put(pclk); - return retval; -} - -#ifdef CONFIG_PM -static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct atmel_ac97c *chip = card->private_data; - - if (cpu_is_at32ap7000()) { - if (test_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_stop(chip->dma.rx_chan); - if (test_bit(DMA_TX_READY, &chip->flags)) - dw_dma_cyclic_stop(chip->dma.tx_chan); - } - clk_disable(chip->pclk); - - return 0; -} - -static int atmel_ac97c_resume(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct atmel_ac97c *chip = card->private_data; - - clk_enable(chip->pclk); - if (cpu_is_at32ap7000()) { - if (test_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_start(chip->dma.rx_chan); - if (test_bit(DMA_TX_READY, &chip->flags)) - dw_dma_cyclic_start(chip->dma.tx_chan); - } - return 0; -} -#else -#define atmel_ac97c_suspend NULL -#define atmel_ac97c_resume NULL -#endif - -static int __devexit atmel_ac97c_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct atmel_ac97c *chip = get_chip(card); - - if (gpio_is_valid(chip->reset_pin)) - gpio_free(chip->reset_pin); - - ac97c_writel(chip, CAMR, 0); - ac97c_writel(chip, COMR, 0); - ac97c_writel(chip, MR, 0); - - clk_disable(chip->pclk); - clk_put(chip->pclk); - iounmap(chip->regs); - free_irq(chip->irq, chip); - - if (cpu_is_at32ap7000()) { - if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) - dma_release_channel(chip->dma.rx_chan); - if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) - dma_release_channel(chip->dma.tx_chan); - clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - chip->dma.rx_chan = NULL; - chip->dma.tx_chan = NULL; - } - - snd_card_set_dev(card, NULL); - snd_card_free(card); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver atmel_ac97c_driver = { - .remove = __devexit_p(atmel_ac97c_remove), - .driver = { - .name = "atmel_ac97c", - }, - .suspend = atmel_ac97c_suspend, - .resume = atmel_ac97c_resume, -}; - -static int __init atmel_ac97c_init(void) -{ - return platform_driver_probe(&atmel_ac97c_driver, - atmel_ac97c_probe); -} -module_init(atmel_ac97c_init); - -static void __exit atmel_ac97c_exit(void) -{ - platform_driver_unregister(&atmel_ac97c_driver); -} -module_exit(atmel_ac97c_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Driver for Atmel AC97 controller"); -MODULE_AUTHOR("Hans-Christian Egtvedt "); diff --git a/ANDROID_3.4.5/sound/atmel/ac97c.h b/ANDROID_3.4.5/sound/atmel/ac97c.h deleted file mode 100644 index ecbba502..00000000 --- a/ANDROID_3.4.5/sound/atmel/ac97c.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Register definitions for Atmel AC97C - * - * Copyright (C) 2005-2009 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ -#ifndef __SOUND_ATMEL_AC97C_H -#define __SOUND_ATMEL_AC97C_H - -#define AC97C_MR 0x08 -#define AC97C_ICA 0x10 -#define AC97C_OCA 0x14 -#define AC97C_CARHR 0x20 -#define AC97C_CATHR 0x24 -#define AC97C_CASR 0x28 -#define AC97C_CAMR 0x2c -#define AC97C_CORHR 0x40 -#define AC97C_COTHR 0x44 -#define AC97C_COSR 0x48 -#define AC97C_COMR 0x4c -#define AC97C_SR 0x50 -#define AC97C_IER 0x54 -#define AC97C_IDR 0x58 -#define AC97C_IMR 0x5c -#define AC97C_VERSION 0xfc - -#define AC97C_CATPR PDC_TPR -#define AC97C_CATCR PDC_TCR -#define AC97C_CATNPR PDC_TNPR -#define AC97C_CATNCR PDC_TNCR -#define AC97C_CARPR PDC_RPR -#define AC97C_CARCR PDC_RCR -#define AC97C_CARNPR PDC_RNPR -#define AC97C_CARNCR PDC_RNCR -#define AC97C_PTCR PDC_PTCR - -#define AC97C_MR_ENA (1 << 0) -#define AC97C_MR_WRST (1 << 1) -#define AC97C_MR_VRA (1 << 2) - -#define AC97C_CSR_TXRDY (1 << 0) -#define AC97C_CSR_TXEMPTY (1 << 1) -#define AC97C_CSR_UNRUN (1 << 2) -#define AC97C_CSR_RXRDY (1 << 4) -#define AC97C_CSR_OVRUN (1 << 5) -#define AC97C_CSR_ENDTX (1 << 10) -#define AC97C_CSR_ENDRX (1 << 14) - -#define AC97C_CMR_SIZE_20 (0 << 16) -#define AC97C_CMR_SIZE_18 (1 << 16) -#define AC97C_CMR_SIZE_16 (2 << 16) -#define AC97C_CMR_SIZE_10 (3 << 16) -#define AC97C_CMR_CEM_LITTLE (1 << 18) -#define AC97C_CMR_CEM_BIG (0 << 18) -#define AC97C_CMR_CENA (1 << 21) -#define AC97C_CMR_DMAEN (1 << 22) - -#define AC97C_SR_CAEVT (1 << 3) -#define AC97C_SR_COEVT (1 << 2) -#define AC97C_SR_WKUP (1 << 1) -#define AC97C_SR_SOF (1 << 0) - -#define AC97C_CH_MASK(slot) \ - (0x7 << (3 * (AC97_SLOT_##slot - 3))) -#define AC97C_CH_ASSIGN(slot, channel) \ - (AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3))) -#define AC97C_CHANNEL_NONE 0x0 -#define AC97C_CHANNEL_A 0x1 - -#endif /* __SOUND_ATMEL_AC97C_H */ diff --git a/ANDROID_3.4.5/sound/core/Kconfig b/ANDROID_3.4.5/sound/core/Kconfig deleted file mode 100644 index 72261551..00000000 --- a/ANDROID_3.4.5/sound/core/Kconfig +++ /dev/null @@ -1,220 +0,0 @@ -# ALSA soundcard-configuration -config SND_TIMER - tristate - -config SND_PCM - tristate - select SND_TIMER - -config SND_HWDEP - tristate - -config SND_RAWMIDI - tristate - -config SND_COMPRESS_OFFLOAD - tristate - -# To be effective this also requires INPUT - users should say: -# select SND_JACK if INPUT=y || INPUT=SND -# to avoid having to force INPUT on. -config SND_JACK - bool - -config SND_SEQUENCER - tristate "Sequencer support" - select SND_TIMER - help - Say Y or M to enable MIDI sequencer and router support. This - feature allows routing and enqueueing of MIDI events. Events - can be processed at a given time. - - Many programs require this feature, so you should enable it - unless you know what you're doing. - -config SND_SEQ_DUMMY - tristate "Sequencer dummy client" - depends on SND_SEQUENCER - help - Say Y here to enable the dummy sequencer client. This client - is a simple MIDI-through client: all normal input events are - redirected to the output port immediately. - - You don't need this unless you want to connect many MIDI - devices or applications together. - - To compile this driver as a module, choose M here: the module - will be called snd-seq-dummy. - -config SND_OSSEMUL - select SOUND_OSS_CORE - bool - -config SND_MIXER_OSS - tristate "OSS Mixer API" - select SND_OSSEMUL - help - To enable OSS mixer API emulation (/dev/mixer*), say Y here - and read . - - Many programs still use the OSS API, so say Y. - - To compile this driver as a module, choose M here: the module - will be called snd-mixer-oss. - -config SND_PCM_OSS - tristate "OSS PCM (digital audio) API" - select SND_OSSEMUL - select SND_PCM - help - To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y - here and read . - - Many programs still use the OSS API, so say Y. - - To compile this driver as a module, choose M here: the module - will be called snd-pcm-oss. - -config SND_PCM_OSS_PLUGINS - bool "OSS PCM (digital audio) API - Include plugin system" - depends on SND_PCM_OSS - default y - help - If you disable this option, the ALSA's OSS PCM API will not - support conversion of channels, formats and rates. It will - behave like most of new OSS/Free drivers in 2.4/2.6 kernels. - -config SND_SEQUENCER_OSS - bool "OSS Sequencer API" - depends on SND_SEQUENCER - select SND_OSSEMUL - help - Say Y here to enable OSS sequencer emulation (both - /dev/sequencer and /dev/music interfaces). - - Many programs still use the OSS API, so say Y. - - If you choose M in "Sequencer support" (SND_SEQUENCER), - this will be compiled as a module. The module will be called - snd-seq-oss. - -config SND_HRTIMER - tristate "HR-timer backend support" - depends on HIGH_RES_TIMERS - select SND_TIMER - help - Say Y here to enable HR-timer backend for ALSA timer. ALSA uses - the hrtimer as a precise timing source. The ALSA sequencer code - also can use this timing source. - - To compile this driver as a module, choose M here: the module - will be called snd-hrtimer. - -config SND_SEQ_HRTIMER_DEFAULT - bool "Use HR-timer as default sequencer timer" - depends on SND_HRTIMER && SND_SEQUENCER - default y - help - Say Y here to use the HR-timer backend as the default sequencer - timer. - -config SND_RTCTIMER - tristate "RTC Timer support" - depends on RTC - select SND_TIMER - help - Say Y here to enable RTC timer support for ALSA. ALSA uses - the RTC timer as a precise timing source and maps the RTC - timer to ALSA's timer interface. The ALSA sequencer code also - can use this timing source. - - To compile this driver as a module, choose M here: the module - will be called snd-rtctimer. - - Note that this option is exclusive with the new RTC drivers - (CONFIG_RTC_CLASS) since this requires the old API. - -config SND_SEQ_RTCTIMER_DEFAULT - bool "Use RTC as default sequencer timer" - depends on SND_RTCTIMER && SND_SEQUENCER - depends on !SND_SEQ_HRTIMER_DEFAULT - default y - help - Say Y here to use the RTC timer as the default sequencer - timer. This is strongly recommended because it ensures - precise MIDI timing even when the system timer runs at less - than 1000 Hz. - - If in doubt, say Y. - -config SND_DYNAMIC_MINORS - bool "Dynamic device file minor numbers" - help - If you say Y here, the minor numbers of ALSA device files in - /dev/snd/ are allocated dynamically. This allows you to have - more than 8 sound cards, but requires a dynamic device file - system like udev. - - If you are unsure about this, say N here. - -config SND_SUPPORT_OLD_API - bool "Support old ALSA API" - select SND_HWDEP - default y - help - Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3 - or older). - -config SND_VERBOSE_PROCFS - bool "Verbose procfs contents" - depends on PROC_FS - default y - help - Say Y here to include code for verbose procfs contents (provides - useful information to developers when a problem occurs). On the - other side, it makes the ALSA subsystem larger. - -config SND_VERBOSE_PRINTK - bool "Verbose printk" - help - Say Y here to enable verbose log messages. These messages - will help to identify source file and position containing - printed messages. - - You don't need this unless you're debugging ALSA. - -config SND_DEBUG - bool "Debug" - help - Say Y here to enable ALSA debug code. - -config SND_DEBUG_VERBOSE - bool "More verbose debug" - depends on SND_DEBUG - help - Say Y here to enable extra-verbose debugging messages. - - Let me repeat: it enables EXTRA-VERBOSE DEBUGGING messages. - So, say Y only if you are ready to be annoyed. - -config SND_PCM_XRUN_DEBUG - bool "Enable PCM ring buffer overrun/underrun debugging" - default n - depends on SND_DEBUG && SND_VERBOSE_PROCFS - help - Say Y to enable the PCM ring buffer overrun/underrun debugging. - It is usually not required, but if you have trouble with - sound clicking when system is loaded, it may help to determine - the process or driver which causes the scheduling gaps. - -config SND_VMASTER - bool - -config SND_KCTL_JACK - bool - -config SND_DMA_SGBUF - def_bool y - depends on X86 - -source "sound/core/seq/Kconfig" diff --git a/ANDROID_3.4.5/sound/core/Makefile b/ANDROID_3.4.5/sound/core/Makefile deleted file mode 100644 index 43d41174..00000000 --- a/ANDROID_3.4.5/sound/core/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 1999,2001 by Jaroslav Kysela -# - -snd-y := sound.o init.o memory.o info.o control.o misc.o device.o -snd-$(CONFIG_ISA_DMA_API) += isadma.o -snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o -snd-$(CONFIG_SND_VMASTER) += vmaster.o -snd-$(CONFIG_SND_KCTL_JACK) += ctljack.o -snd-$(CONFIG_SND_JACK) += jack.o - -snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ - pcm_memory.o - -snd-page-alloc-y := memalloc.o -snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o - -snd-rawmidi-objs := rawmidi.o -snd-timer-objs := timer.o -snd-hrtimer-objs := hrtimer.o -snd-rtctimer-objs := rtctimer.o -snd-hwdep-objs := hwdep.o - -snd-compress-objs := compress_offload.o - -obj-$(CONFIG_SND) += snd.o -obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o -obj-$(CONFIG_SND_TIMER) += snd-timer.o -obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o -obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o -obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o -obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o - -obj-$(CONFIG_SND_OSSEMUL) += oss/ -obj-$(CONFIG_SND_SEQUENCER) += seq/ - -obj-$(CONFIG_SND_COMPRESS_OFFLOAD) += snd-compress.o diff --git a/ANDROID_3.4.5/sound/core/compress_offload.c b/ANDROID_3.4.5/sound/core/compress_offload.c deleted file mode 100644 index a58cf359..00000000 --- a/ANDROID_3.4.5/sound/core/compress_offload.c +++ /dev/null @@ -1,773 +0,0 @@ -/* - * compress_core.c - compress offload core - * - * Copyright (C) 2011 Intel Corporation - * Authors: Vinod Koul - * Pierre-Louis Bossart - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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; version 2 of the License. - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - */ -#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__ -#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* TODO: - * - add substream support for multiple devices in case of - * SND_DYNAMIC_MINORS is not used - * - Multiple node representation - * driver should be able to register multiple nodes - */ - -static DEFINE_MUTEX(device_mutex); - -struct snd_compr_file { - unsigned long caps; - struct snd_compr_stream stream; -}; - -/* - * a note on stream states used: - * we use follwing states in the compressed core - * SNDRV_PCM_STATE_OPEN: When stream has been opened. - * SNDRV_PCM_STATE_SETUP: When stream has been initialized. This is done by - * calling SNDRV_COMPRESS_SET_PARAMS. running streams will come to this - * state at stop by calling SNDRV_COMPRESS_STOP, or at end of drain. - * SNDRV_PCM_STATE_RUNNING: When stream has been started and is - * decoding/encoding and rendering/capturing data. - * SNDRV_PCM_STATE_DRAINING: When stream is draining current data. This is done - * by calling SNDRV_COMPRESS_DRAIN. - * SNDRV_PCM_STATE_PAUSED: When stream is paused. This is done by calling - * SNDRV_COMPRESS_PAUSE. It can be stopped or resumed by calling - * SNDRV_COMPRESS_STOP or SNDRV_COMPRESS_RESUME respectively. - */ -static int snd_compr_open(struct inode *inode, struct file *f) -{ - struct snd_compr *compr; - struct snd_compr_file *data; - struct snd_compr_runtime *runtime; - enum snd_compr_direction dirn; - int maj = imajor(inode); - int ret; - - if (f->f_flags & O_WRONLY) - dirn = SND_COMPRESS_PLAYBACK; - else if (f->f_flags & O_RDONLY) - dirn = SND_COMPRESS_CAPTURE; - else { - pr_err("invalid direction\n"); - return -EINVAL; - } - - if (maj == snd_major) - compr = snd_lookup_minor_data(iminor(inode), - SNDRV_DEVICE_TYPE_COMPRESS); - else - return -EBADFD; - - if (compr == NULL) { - pr_err("no device data!!!\n"); - return -ENODEV; - } - - if (dirn != compr->direction) { - pr_err("this device doesn't support this direction\n"); - snd_card_unref(compr->card); - return -EINVAL; - } - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - snd_card_unref(compr->card); - return -ENOMEM; - } - data->stream.ops = compr->ops; - data->stream.direction = dirn; - data->stream.private_data = compr->private_data; - data->stream.device = compr; - runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); - if (!runtime) { - kfree(data); - snd_card_unref(compr->card); - return -ENOMEM; - } - runtime->state = SNDRV_PCM_STATE_OPEN; - init_waitqueue_head(&runtime->sleep); - data->stream.runtime = runtime; - f->private_data = (void *)data; - mutex_lock(&compr->lock); - ret = compr->ops->open(&data->stream); - mutex_unlock(&compr->lock); - if (ret) { - kfree(runtime); - kfree(data); - } - snd_card_unref(compr->card); - return 0; -} - -static int snd_compr_free(struct inode *inode, struct file *f) -{ - struct snd_compr_file *data = f->private_data; - data->stream.ops->free(&data->stream); - kfree(data->stream.runtime->buffer); - kfree(data->stream.runtime); - kfree(data); - return 0; -} - -static void snd_compr_update_tstamp(struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) -{ - if (!stream->ops->pointer) - return; - stream->ops->pointer(stream, tstamp); - pr_debug("dsp consumed till %d total %d bytes\n", - tstamp->byte_offset, tstamp->copied_total); - stream->runtime->hw_pointer = tstamp->byte_offset; - stream->runtime->total_bytes_transferred = tstamp->copied_total; -} - -static size_t snd_compr_calc_avail(struct snd_compr_stream *stream, - struct snd_compr_avail *avail) -{ - long avail_calc; /*this needs to be signed variable */ - - snd_compr_update_tstamp(stream, &avail->tstamp); - - /* FIXME: This needs to be different for capture stream, - available is # of compressed data, for playback it's - remainder of buffer */ - - if (stream->runtime->total_bytes_available == 0 && - stream->runtime->state == SNDRV_PCM_STATE_SETUP) { - pr_debug("detected init and someone forgot to do a write\n"); - return stream->runtime->buffer_size; - } - pr_debug("app wrote %lld, DSP consumed %lld\n", - stream->runtime->total_bytes_available, - stream->runtime->total_bytes_transferred); - if (stream->runtime->total_bytes_available == - stream->runtime->total_bytes_transferred) { - pr_debug("both pointers are same, returning full avail\n"); - return stream->runtime->buffer_size; - } - - /* FIXME: this routine isn't consistent, in one test we use - * cumulative values and in the other byte offsets. Do we - * really need the byte offsets if the cumulative values have - * been updated? In the PCM interface app_ptr and hw_ptr are - * already cumulative */ - - avail_calc = stream->runtime->buffer_size - - (stream->runtime->app_pointer - stream->runtime->hw_pointer); - pr_debug("calc avail as %ld, app_ptr %lld, hw+ptr %lld\n", avail_calc, - stream->runtime->app_pointer, - stream->runtime->hw_pointer); - if (avail_calc >= stream->runtime->buffer_size) - avail_calc -= stream->runtime->buffer_size; - pr_debug("ret avail as %ld\n", avail_calc); - avail->avail = avail_calc; - return avail_calc; -} - -static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream) -{ - struct snd_compr_avail avail; - - return snd_compr_calc_avail(stream, &avail); -} - -static int -snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg) -{ - struct snd_compr_avail ioctl_avail; - size_t avail; - - avail = snd_compr_calc_avail(stream, &ioctl_avail); - ioctl_avail.avail = avail; - - if (copy_to_user((__u64 __user *)arg, - &ioctl_avail, sizeof(ioctl_avail))) - return -EFAULT; - return 0; -} - -static int snd_compr_write_data(struct snd_compr_stream *stream, - const char __user *buf, size_t count) -{ - void *dstn; - size_t copy; - struct snd_compr_runtime *runtime = stream->runtime; - - dstn = runtime->buffer + runtime->app_pointer; - pr_debug("copying %ld at %lld\n", - (unsigned long)count, runtime->app_pointer); - if (count < runtime->buffer_size - runtime->app_pointer) { - if (copy_from_user(dstn, buf, count)) - return -EFAULT; - runtime->app_pointer += count; - } else { - copy = runtime->buffer_size - runtime->app_pointer; - if (copy_from_user(dstn, buf, copy)) - return -EFAULT; - if (copy_from_user(runtime->buffer, buf + copy, count - copy)) - return -EFAULT; - runtime->app_pointer = count - copy; - } - /* if DSP cares, let it know data has been written */ - if (stream->ops->ack) - stream->ops->ack(stream, count); - return count; -} - -static ssize_t snd_compr_write(struct file *f, const char __user *buf, - size_t count, loff_t *offset) -{ - struct snd_compr_file *data = f->private_data; - struct snd_compr_stream *stream; - size_t avail; - int retval; - - if (snd_BUG_ON(!data)) - return -EFAULT; - - stream = &data->stream; - mutex_lock(&stream->device->lock); - /* write is allowed when stream is running or has been steup */ - if (stream->runtime->state != SNDRV_PCM_STATE_SETUP && - stream->runtime->state != SNDRV_PCM_STATE_RUNNING) { - mutex_unlock(&stream->device->lock); - return -EBADFD; - } - - avail = snd_compr_get_avail(stream); - pr_debug("avail returned %ld\n", (unsigned long)avail); - /* calculate how much we can write to buffer */ - if (avail > count) - avail = count; - - if (stream->ops->copy) - retval = stream->ops->copy(stream, buf, avail); - else - retval = snd_compr_write_data(stream, buf, avail); - if (retval > 0) - stream->runtime->total_bytes_available += retval; - - /* while initiating the stream, write should be called before START - * call, so in setup move state */ - if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) { - stream->runtime->state = SNDRV_PCM_STATE_PREPARED; - pr_debug("stream prepared, Houston we are good to go\n"); - } - - mutex_unlock(&stream->device->lock); - return retval; -} - - -static ssize_t snd_compr_read(struct file *f, char __user *buf, - size_t count, loff_t *offset) -{ - return -ENXIO; -} - -static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma) -{ - return -ENXIO; -} - -static inline int snd_compr_get_poll(struct snd_compr_stream *stream) -{ - if (stream->direction == SND_COMPRESS_PLAYBACK) - return POLLOUT | POLLWRNORM; - else - return POLLIN | POLLRDNORM; -} - -static unsigned int snd_compr_poll(struct file *f, poll_table *wait) -{ - struct snd_compr_file *data = f->private_data; - struct snd_compr_stream *stream; - size_t avail; - int retval = 0; - - if (snd_BUG_ON(!data)) - return -EFAULT; - stream = &data->stream; - if (snd_BUG_ON(!stream)) - return -EFAULT; - - mutex_lock(&stream->device->lock); - if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED || - stream->runtime->state == SNDRV_PCM_STATE_OPEN) { - retval = -EBADFD; - goto out; - } - poll_wait(f, &stream->runtime->sleep, wait); - - avail = snd_compr_get_avail(stream); - pr_debug("avail is %ld\n", (unsigned long)avail); - /* check if we have at least one fragment to fill */ - switch (stream->runtime->state) { - case SNDRV_PCM_STATE_DRAINING: - /* stream has been woken up after drain is complete - * draining done so set stream state to stopped - */ - retval = snd_compr_get_poll(stream); - stream->runtime->state = SNDRV_PCM_STATE_SETUP; - break; - case SNDRV_PCM_STATE_RUNNING: - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_PAUSED: - if (avail >= stream->runtime->fragment_size) - retval = snd_compr_get_poll(stream); - break; - default: - if (stream->direction == SND_COMPRESS_PLAYBACK) - retval = POLLOUT | POLLWRNORM | POLLERR; - else - retval = POLLIN | POLLRDNORM | POLLERR; - break; - } -out: - mutex_unlock(&stream->device->lock); - return retval; -} - -static int -snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg) -{ - int retval; - struct snd_compr_caps caps; - - if (!stream->ops->get_caps) - return -ENXIO; - - retval = stream->ops->get_caps(stream, &caps); - if (retval) - goto out; - if (copy_to_user((void __user *)arg, &caps, sizeof(caps))) - retval = -EFAULT; -out: - return retval; -} - -static int -snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg) -{ - int retval; - struct snd_compr_codec_caps *caps; - - if (!stream->ops->get_codec_caps) - return -ENXIO; - - caps = kmalloc(sizeof(*caps), GFP_KERNEL); - if (!caps) - return -ENOMEM; - - retval = stream->ops->get_codec_caps(stream, caps); - if (retval) - goto out; - if (copy_to_user((void __user *)arg, caps, sizeof(*caps))) - retval = -EFAULT; - -out: - kfree(caps); - return retval; -} - -/* revisit this with snd_pcm_preallocate_xxx */ -static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, - struct snd_compr_params *params) -{ - unsigned int buffer_size; - void *buffer; - - buffer_size = params->buffer.fragment_size * params->buffer.fragments; - if (stream->ops->copy) { - buffer = NULL; - /* if copy is defined the driver will be required to copy - * the data from core - */ - } else { - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - } - stream->runtime->fragment_size = params->buffer.fragment_size; - stream->runtime->fragments = params->buffer.fragments; - stream->runtime->buffer = buffer; - stream->runtime->buffer_size = buffer_size; - return 0; -} - -static int -snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) -{ - struct snd_compr_params *params; - int retval; - - if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) { - /* - * we should allow parameter change only when stream has been - * opened not in other cases - */ - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - if (copy_from_user(params, (void __user *)arg, sizeof(*params))) { - retval = -EFAULT; - goto out; - } - retval = snd_compr_allocate_buffer(stream, params); - if (retval) { - retval = -ENOMEM; - goto out; - } - retval = stream->ops->set_params(stream, params); - if (retval) - goto out; - stream->runtime->state = SNDRV_PCM_STATE_SETUP; - } else { - return -EPERM; - } -out: - kfree(params); - return retval; -} - -static int -snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg) -{ - struct snd_codec *params; - int retval; - - if (!stream->ops->get_params) - return -EBADFD; - - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - retval = stream->ops->get_params(stream, params); - if (retval) - goto out; - if (copy_to_user((char __user *)arg, params, sizeof(*params))) - retval = -EFAULT; - -out: - kfree(params); - return retval; -} - -static inline int -snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg) -{ - struct snd_compr_tstamp tstamp; - - snd_compr_update_tstamp(stream, &tstamp); - return copy_to_user((struct snd_compr_tstamp __user *)arg, - &tstamp, sizeof(tstamp)) ? -EFAULT : 0; -} - -static int snd_compr_pause(struct snd_compr_stream *stream) -{ - int retval; - - if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) - return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); - if (!retval) { - stream->runtime->state = SNDRV_PCM_STATE_PAUSED; - wake_up(&stream->runtime->sleep); - } - return retval; -} - -static int snd_compr_resume(struct snd_compr_stream *stream) -{ - int retval; - - if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED) - return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); - if (!retval) - stream->runtime->state = SNDRV_PCM_STATE_RUNNING; - return retval; -} - -static int snd_compr_start(struct snd_compr_stream *stream) -{ - int retval; - - if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED) - return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START); - if (!retval) - stream->runtime->state = SNDRV_PCM_STATE_RUNNING; - return retval; -} - -static int snd_compr_stop(struct snd_compr_stream *stream) -{ - int retval; - - if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || - stream->runtime->state == SNDRV_PCM_STATE_SETUP) - return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); - if (!retval) { - stream->runtime->state = SNDRV_PCM_STATE_SETUP; - wake_up(&stream->runtime->sleep); - } - return retval; -} - -static int snd_compr_drain(struct snd_compr_stream *stream) -{ - int retval; - - if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED || - stream->runtime->state == SNDRV_PCM_STATE_SETUP) - return -EPERM; - retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN); - if (!retval) { - stream->runtime->state = SNDRV_PCM_STATE_DRAINING; - wake_up(&stream->runtime->sleep); - } - return retval; -} - -static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) -{ - struct snd_compr_file *data = f->private_data; - struct snd_compr_stream *stream; - int retval = -ENOTTY; - - if (snd_BUG_ON(!data)) - return -EFAULT; - stream = &data->stream; - if (snd_BUG_ON(!stream)) - return -EFAULT; - mutex_lock(&stream->device->lock); - switch (_IOC_NR(cmd)) { - case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION): - put_user(SNDRV_COMPRESS_VERSION, - (int __user *)arg) ? -EFAULT : 0; - break; - case _IOC_NR(SNDRV_COMPRESS_GET_CAPS): - retval = snd_compr_get_caps(stream, arg); - break; - case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS): - retval = snd_compr_get_codec_caps(stream, arg); - break; - case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS): - retval = snd_compr_set_params(stream, arg); - break; - case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS): - retval = snd_compr_get_params(stream, arg); - break; - case _IOC_NR(SNDRV_COMPRESS_TSTAMP): - retval = snd_compr_tstamp(stream, arg); - break; - case _IOC_NR(SNDRV_COMPRESS_AVAIL): - retval = snd_compr_ioctl_avail(stream, arg); - break; - case _IOC_NR(SNDRV_COMPRESS_PAUSE): - retval = snd_compr_pause(stream); - break; - case _IOC_NR(SNDRV_COMPRESS_RESUME): - retval = snd_compr_resume(stream); - break; - case _IOC_NR(SNDRV_COMPRESS_START): - retval = snd_compr_start(stream); - break; - case _IOC_NR(SNDRV_COMPRESS_STOP): - retval = snd_compr_stop(stream); - break; - case _IOC_NR(SNDRV_COMPRESS_DRAIN): - retval = snd_compr_drain(stream); - break; - } - mutex_unlock(&stream->device->lock); - return retval; -} - -static const struct file_operations snd_compr_file_ops = { - .owner = THIS_MODULE, - .open = snd_compr_open, - .release = snd_compr_free, - .write = snd_compr_write, - .read = snd_compr_read, - .unlocked_ioctl = snd_compr_ioctl, - .mmap = snd_compr_mmap, - .poll = snd_compr_poll, -}; - -static int snd_compress_dev_register(struct snd_device *device) -{ - int ret = -EINVAL; - char str[16]; - struct snd_compr *compr; - - if (snd_BUG_ON(!device || !device->device_data)) - return -EBADFD; - compr = device->device_data; - - sprintf(str, "comprC%iD%i", compr->card->number, compr->device); - pr_debug("reg %s for device %s, direction %d\n", str, compr->name, - compr->direction); - /* register compressed device */ - ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card, - compr->device, &snd_compr_file_ops, compr, str); - if (ret < 0) { - pr_err("snd_register_device failed\n %d", ret); - return ret; - } - return ret; - -} - -static int snd_compress_dev_disconnect(struct snd_device *device) -{ - struct snd_compr *compr; - - compr = device->device_data; - snd_unregister_device(compr->direction, compr->card, compr->device); - return 0; -} - -/* - * snd_compress_new: create new compress device - * @card: sound card pointer - * @device: device number - * @dirn: device direction, should be of type enum snd_compr_direction - * @compr: compress device pointer - */ -int snd_compress_new(struct snd_card *card, int device, - int dirn, struct snd_compr *compr) -{ - static struct snd_device_ops ops = { - .dev_free = NULL, - .dev_register = snd_compress_dev_register, - .dev_disconnect = snd_compress_dev_disconnect, - }; - - compr->card = card; - compr->device = device; - compr->direction = dirn; - return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops); -} -EXPORT_SYMBOL_GPL(snd_compress_new); - -static int snd_compress_add_device(struct snd_compr *device) -{ - int ret; - - if (!device->card) - return -EINVAL; - - /* register the card */ - ret = snd_card_register(device->card); - if (ret) - goto out; - return 0; - -out: - pr_err("failed with %d\n", ret); - return ret; - -} - -static int snd_compress_remove_device(struct snd_compr *device) -{ - return snd_card_free(device->card); -} - -/** - * snd_compress_register - register compressed device - * - * @device: compressed device to register - */ -int snd_compress_register(struct snd_compr *device) -{ - int retval; - - if (device->name == NULL || device->dev == NULL || device->ops == NULL) - return -EINVAL; - - pr_debug("Registering compressed device %s\n", device->name); - if (snd_BUG_ON(!device->ops->open)) - return -EINVAL; - if (snd_BUG_ON(!device->ops->free)) - return -EINVAL; - if (snd_BUG_ON(!device->ops->set_params)) - return -EINVAL; - if (snd_BUG_ON(!device->ops->trigger)) - return -EINVAL; - - mutex_init(&device->lock); - - /* register a compressed card */ - mutex_lock(&device_mutex); - retval = snd_compress_add_device(device); - mutex_unlock(&device_mutex); - return retval; -} -EXPORT_SYMBOL_GPL(snd_compress_register); - -int snd_compress_deregister(struct snd_compr *device) -{ - pr_debug("Removing compressed device %s\n", device->name); - mutex_lock(&device_mutex); - snd_compress_remove_device(device); - mutex_unlock(&device_mutex); - return 0; -} -EXPORT_SYMBOL_GPL(snd_compress_deregister); - -static int __init snd_compress_init(void) -{ - return 0; -} - -static void __exit snd_compress_exit(void) -{ -} - -module_init(snd_compress_init); -module_exit(snd_compress_exit); - -MODULE_DESCRIPTION("ALSA Compressed offload framework"); -MODULE_AUTHOR("Vinod Koul "); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/core/control.c b/ANDROID_3.4.5/sound/core/control.c deleted file mode 100644 index daa4fc88..00000000 --- a/ANDROID_3.4.5/sound/core/control.c +++ /dev/null @@ -1,1726 +0,0 @@ -/* - * Routines for driver control interface - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include - -/* max number of user-defined controls */ -#define MAX_USER_CONTROLS 32 -#define MAX_CONTROL_COUNT 1028 - -struct snd_kctl_ioctl { - struct list_head list; /* list of all ioctls */ - snd_kctl_ioctl_func_t fioctl; -}; - -static DECLARE_RWSEM(snd_ioctl_rwsem); -static LIST_HEAD(snd_control_ioctls); -#ifdef CONFIG_COMPAT -static LIST_HEAD(snd_control_compat_ioctls); -#endif - -static int snd_ctl_open(struct inode *inode, struct file *file) -{ - unsigned long flags; - struct snd_card *card; - struct snd_ctl_file *ctl; - int err; - - err = nonseekable_open(inode, file); - if (err < 0) - return err; - - card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL); - if (!card) { - err = -ENODEV; - goto __error1; - } - err = snd_card_file_add(card, file); - if (err < 0) { - err = -ENODEV; - goto __error1; - } - if (!try_module_get(card->module)) { - err = -EFAULT; - goto __error2; - } - ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); - if (ctl == NULL) { - err = -ENOMEM; - goto __error; - } - INIT_LIST_HEAD(&ctl->events); - init_waitqueue_head(&ctl->change_sleep); - spin_lock_init(&ctl->read_lock); - ctl->card = card; - ctl->prefer_pcm_subdevice = -1; - ctl->prefer_rawmidi_subdevice = -1; - ctl->pid = get_pid(task_pid(current)); - file->private_data = ctl; - write_lock_irqsave(&card->ctl_files_rwlock, flags); - list_add_tail(&ctl->list, &card->ctl_files); - write_unlock_irqrestore(&card->ctl_files_rwlock, flags); - snd_card_unref(card); - return 0; - - __error: - module_put(card->module); - __error2: - snd_card_file_remove(card, file); - __error1: - if (card) - snd_card_unref(card); - return err; -} - -static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl) -{ - unsigned long flags; - struct snd_kctl_event *cread; - - spin_lock_irqsave(&ctl->read_lock, flags); - while (!list_empty(&ctl->events)) { - cread = snd_kctl_event(ctl->events.next); - list_del(&cread->list); - kfree(cread); - } - spin_unlock_irqrestore(&ctl->read_lock, flags); -} - -static int snd_ctl_release(struct inode *inode, struct file *file) -{ - unsigned long flags; - struct snd_card *card; - struct snd_ctl_file *ctl; - struct snd_kcontrol *control; - unsigned int idx; - - ctl = file->private_data; - file->private_data = NULL; - card = ctl->card; - write_lock_irqsave(&card->ctl_files_rwlock, flags); - list_del(&ctl->list); - write_unlock_irqrestore(&card->ctl_files_rwlock, flags); - down_write(&card->controls_rwsem); - list_for_each_entry(control, &card->controls, list) - for (idx = 0; idx < control->count; idx++) - if (control->vd[idx].owner == ctl) - control->vd[idx].owner = NULL; - up_write(&card->controls_rwsem); - snd_ctl_empty_read_queue(ctl); - put_pid(ctl->pid); - kfree(ctl); - module_put(card->module); - snd_card_file_remove(card, file); - return 0; -} - -void snd_ctl_notify(struct snd_card *card, unsigned int mask, - struct snd_ctl_elem_id *id) -{ - unsigned long flags; - struct snd_ctl_file *ctl; - struct snd_kctl_event *ev; - - if (snd_BUG_ON(!card || !id)) - return; - read_lock(&card->ctl_files_rwlock); -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) - card->mixer_oss_change_count++; -#endif - list_for_each_entry(ctl, &card->ctl_files, list) { - if (!ctl->subscribed) - continue; - spin_lock_irqsave(&ctl->read_lock, flags); - list_for_each_entry(ev, &ctl->events, list) { - if (ev->id.numid == id->numid) { - ev->mask |= mask; - goto _found; - } - } - ev = kzalloc(sizeof(*ev), GFP_ATOMIC); - if (ev) { - ev->id = *id; - ev->mask = mask; - list_add_tail(&ev->list, &ctl->events); - } else { - snd_printk(KERN_ERR "No memory available to allocate event\n"); - } - _found: - wake_up(&ctl->change_sleep); - spin_unlock_irqrestore(&ctl->read_lock, flags); - kill_fasync(&ctl->fasync, SIGIO, POLL_IN); - } - read_unlock(&card->ctl_files_rwlock); -} - -EXPORT_SYMBOL(snd_ctl_notify); - -/** - * snd_ctl_new - create a control instance from the template - * @control: the control template - * @access: the default control access - * - * Allocates a new struct snd_kcontrol instance and copies the given template - * to the new instance. It does not copy volatile data (access). - * - * Returns the pointer of the new instance, or NULL on failure. - */ -static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, - unsigned int access) -{ - struct snd_kcontrol *kctl; - unsigned int idx; - - if (snd_BUG_ON(!control || !control->count)) - return NULL; - - if (control->count > MAX_CONTROL_COUNT) - return NULL; - - kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL); - if (kctl == NULL) { - snd_printk(KERN_ERR "Cannot allocate control instance\n"); - return NULL; - } - *kctl = *control; - for (idx = 0; idx < kctl->count; idx++) - kctl->vd[idx].access = access; - return kctl; -} - -/** - * snd_ctl_new1 - create a control instance from the template - * @ncontrol: the initialization record - * @private_data: the private data to set - * - * Allocates a new struct snd_kcontrol instance and initialize from the given - * template. When the access field of ncontrol is 0, it's assumed as - * READWRITE access. When the count field is 0, it's assumes as one. - * - * Returns the pointer of the newly generated instance, or NULL on failure. - */ -struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, - void *private_data) -{ - struct snd_kcontrol kctl; - unsigned int access; - - if (snd_BUG_ON(!ncontrol || !ncontrol->info)) - return NULL; - memset(&kctl, 0, sizeof(kctl)); - kctl.id.iface = ncontrol->iface; - kctl.id.device = ncontrol->device; - kctl.id.subdevice = ncontrol->subdevice; - if (ncontrol->name) { - strlcpy(kctl.id.name, ncontrol->name, sizeof(kctl.id.name)); - if (strcmp(ncontrol->name, kctl.id.name) != 0) - snd_printk(KERN_WARNING - "Control name '%s' truncated to '%s'\n", - ncontrol->name, kctl.id.name); - } - kctl.id.index = ncontrol->index; - kctl.count = ncontrol->count ? ncontrol->count : 1; - access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : - (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| - SNDRV_CTL_ELEM_ACCESS_INACTIVE| - SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| - SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND| - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)); - kctl.info = ncontrol->info; - kctl.get = ncontrol->get; - kctl.put = ncontrol->put; - kctl.tlv.p = ncontrol->tlv.p; - kctl.private_value = ncontrol->private_value; - kctl.private_data = private_data; - return snd_ctl_new(&kctl, access); -} - -EXPORT_SYMBOL(snd_ctl_new1); - -/** - * snd_ctl_free_one - release the control instance - * @kcontrol: the control instance - * - * Releases the control instance created via snd_ctl_new() - * or snd_ctl_new1(). - * Don't call this after the control was added to the card. - */ -void snd_ctl_free_one(struct snd_kcontrol *kcontrol) -{ - if (kcontrol) { - if (kcontrol->private_free) - kcontrol->private_free(kcontrol); - kfree(kcontrol); - } -} - -EXPORT_SYMBOL(snd_ctl_free_one); - -static bool snd_ctl_remove_numid_conflict(struct snd_card *card, - unsigned int count) -{ - struct snd_kcontrol *kctl; - - list_for_each_entry(kctl, &card->controls, list) { - if (kctl->id.numid < card->last_numid + 1 + count && - kctl->id.numid + kctl->count > card->last_numid + 1) { - card->last_numid = kctl->id.numid + kctl->count - 1; - return true; - } - } - return false; -} - -static int snd_ctl_find_hole(struct snd_card *card, unsigned int count) -{ - unsigned int iter = 100000; - - while (snd_ctl_remove_numid_conflict(card, count)) { - if (--iter == 0) { - /* this situation is very unlikely */ - snd_printk(KERN_ERR "unable to allocate new control numid\n"); - return -ENOMEM; - } - } - return 0; -} - -/** - * snd_ctl_add - add the control instance to the card - * @card: the card instance - * @kcontrol: the control instance to add - * - * Adds the control instance created via snd_ctl_new() or - * snd_ctl_new1() to the given card. Assigns also an unique - * numid used for fast search. - * - * Returns zero if successful, or a negative error code on failure. - * - * It frees automatically the control which cannot be added. - */ -int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) -{ - struct snd_ctl_elem_id id; - unsigned int idx; - int err = -EINVAL; - - if (! kcontrol) - return err; - if (snd_BUG_ON(!card || !kcontrol->info)) - goto error; - id = kcontrol->id; - down_write(&card->controls_rwsem); - if (snd_ctl_find_id(card, &id)) { - up_write(&card->controls_rwsem); - snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n", - id.iface, - id.device, - id.subdevice, - id.name, - id.index); - err = -EBUSY; - goto error; - } - if (snd_ctl_find_hole(card, kcontrol->count) < 0) { - up_write(&card->controls_rwsem); - err = -ENOMEM; - goto error; - } - list_add_tail(&kcontrol->list, &card->controls); - card->controls_count += kcontrol->count; - kcontrol->id.numid = card->last_numid + 1; - card->last_numid += kcontrol->count; - up_write(&card->controls_rwsem); - for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); - return 0; - - error: - snd_ctl_free_one(kcontrol); - return err; -} - -EXPORT_SYMBOL(snd_ctl_add); - -/** - * snd_ctl_replace - replace the control instance of the card - * @card: the card instance - * @kcontrol: the control instance to replace - * @add_on_replace: add the control if not already added - * - * Replaces the given control. If the given control does not exist - * and the add_on_replace flag is set, the control is added. If the - * control exists, it is destroyed first. - * - * Returns zero if successful, or a negative error code on failure. - * - * It frees automatically the control which cannot be added or replaced. - */ -int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, - bool add_on_replace) -{ - struct snd_ctl_elem_id id; - unsigned int idx; - struct snd_kcontrol *old; - int ret; - - if (!kcontrol) - return -EINVAL; - if (snd_BUG_ON(!card || !kcontrol->info)) { - ret = -EINVAL; - goto error; - } - id = kcontrol->id; - down_write(&card->controls_rwsem); - old = snd_ctl_find_id(card, &id); - if (!old) { - if (add_on_replace) - goto add; - up_write(&card->controls_rwsem); - ret = -EINVAL; - goto error; - } - ret = snd_ctl_remove(card, old); - if (ret < 0) { - up_write(&card->controls_rwsem); - goto error; - } -add: - if (snd_ctl_find_hole(card, kcontrol->count) < 0) { - up_write(&card->controls_rwsem); - ret = -ENOMEM; - goto error; - } - list_add_tail(&kcontrol->list, &card->controls); - card->controls_count += kcontrol->count; - kcontrol->id.numid = card->last_numid + 1; - card->last_numid += kcontrol->count; - up_write(&card->controls_rwsem); - for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); - return 0; - -error: - snd_ctl_free_one(kcontrol); - return ret; -} -EXPORT_SYMBOL(snd_ctl_replace); - -/** - * snd_ctl_remove - remove the control from the card and release it - * @card: the card instance - * @kcontrol: the control instance to remove - * - * Removes the control from the card and then releases the instance. - * You don't need to call snd_ctl_free_one(). You must be in - * the write lock - down_write(&card->controls_rwsem). - * - * Returns 0 if successful, or a negative error code on failure. - */ -int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol) -{ - struct snd_ctl_elem_id id; - unsigned int idx; - - if (snd_BUG_ON(!card || !kcontrol)) - return -EINVAL; - list_del(&kcontrol->list); - card->controls_count -= kcontrol->count; - id = kcontrol->id; - for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_REMOVE, &id); - snd_ctl_free_one(kcontrol); - return 0; -} - -EXPORT_SYMBOL(snd_ctl_remove); - -/** - * snd_ctl_remove_id - remove the control of the given id and release it - * @card: the card instance - * @id: the control id to remove - * - * Finds the control instance with the given id, removes it from the - * card list and releases it. - * - * Returns 0 if successful, or a negative error code on failure. - */ -int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) -{ - struct snd_kcontrol *kctl; - int ret; - - down_write(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, id); - if (kctl == NULL) { - up_write(&card->controls_rwsem); - return -ENOENT; - } - ret = snd_ctl_remove(card, kctl); - up_write(&card->controls_rwsem); - return ret; -} - -EXPORT_SYMBOL(snd_ctl_remove_id); - -/** - * snd_ctl_remove_user_ctl - remove and release the unlocked user control - * @file: active control handle - * @id: the control id to remove - * - * Finds the control instance with the given id, removes it from the - * card list and releases it. - * - * Returns 0 if successful, or a negative error code on failure. - */ -static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, - struct snd_ctl_elem_id *id) -{ - struct snd_card *card = file->card; - struct snd_kcontrol *kctl; - int idx, ret; - - down_write(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, id); - if (kctl == NULL) { - ret = -ENOENT; - goto error; - } - if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) { - ret = -EINVAL; - goto error; - } - for (idx = 0; idx < kctl->count; idx++) - if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { - ret = -EBUSY; - goto error; - } - ret = snd_ctl_remove(card, kctl); - if (ret < 0) - goto error; - card->user_ctl_count--; -error: - up_write(&card->controls_rwsem); - return ret; -} - -/** - * snd_ctl_activate_id - activate/inactivate the control of the given id - * @card: the card instance - * @id: the control id to activate/inactivate - * @active: non-zero to activate - * - * Finds the control instance with the given id, and activate or - * inactivate the control together with notification, if changed. - * - * Returns 0 if unchanged, 1 if changed, or a negative error code on failure. - */ -int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, - int active) -{ - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - unsigned int index_offset; - int ret; - - down_write(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, id); - if (kctl == NULL) { - ret = -ENOENT; - goto unlock; - } - index_offset = snd_ctl_get_ioff(kctl, &kctl->id); - vd = &kctl->vd[index_offset]; - ret = 0; - if (active) { - if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)) - goto unlock; - vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - } else { - if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) - goto unlock; - vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - } - ret = 1; - unlock: - up_write(&card->controls_rwsem); - if (ret > 0) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id); - return ret; -} -EXPORT_SYMBOL_GPL(snd_ctl_activate_id); - -/** - * snd_ctl_rename_id - replace the id of a control on the card - * @card: the card instance - * @src_id: the old id - * @dst_id: the new id - * - * Finds the control with the old id from the card, and replaces the - * id with the new one. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id, - struct snd_ctl_elem_id *dst_id) -{ - struct snd_kcontrol *kctl; - - down_write(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, src_id); - if (kctl == NULL) { - up_write(&card->controls_rwsem); - return -ENOENT; - } - kctl->id = *dst_id; - kctl->id.numid = card->last_numid + 1; - card->last_numid += kctl->count; - up_write(&card->controls_rwsem); - return 0; -} - -EXPORT_SYMBOL(snd_ctl_rename_id); - -/** - * snd_ctl_find_numid - find the control instance with the given number-id - * @card: the card instance - * @numid: the number-id to search - * - * Finds the control instance with the given number-id from the card. - * - * Returns the pointer of the instance if found, or NULL if not. - * - * The caller must down card->controls_rwsem before calling this function - * (if the race condition can happen). - */ -struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid) -{ - struct snd_kcontrol *kctl; - - if (snd_BUG_ON(!card || !numid)) - return NULL; - list_for_each_entry(kctl, &card->controls, list) { - if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid) - return kctl; - } - return NULL; -} - -EXPORT_SYMBOL(snd_ctl_find_numid); - -/** - * snd_ctl_find_id - find the control instance with the given id - * @card: the card instance - * @id: the id to search - * - * Finds the control instance with the given id from the card. - * - * Returns the pointer of the instance if found, or NULL if not. - * - * The caller must down card->controls_rwsem before calling this function - * (if the race condition can happen). - */ -struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, - struct snd_ctl_elem_id *id) -{ - struct snd_kcontrol *kctl; - - if (snd_BUG_ON(!card || !id)) - return NULL; - if (id->numid != 0) - return snd_ctl_find_numid(card, id->numid); - list_for_each_entry(kctl, &card->controls, list) { - if (kctl->id.iface != id->iface) - continue; - if (kctl->id.device != id->device) - continue; - if (kctl->id.subdevice != id->subdevice) - continue; - if (strncmp(kctl->id.name, id->name, sizeof(kctl->id.name))) - continue; - if (kctl->id.index > id->index) - continue; - if (kctl->id.index + kctl->count <= id->index) - continue; - return kctl; - } - return NULL; -} - -EXPORT_SYMBOL(snd_ctl_find_id); - -static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, - unsigned int cmd, void __user *arg) -{ - struct snd_ctl_card_info *info; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (! info) - return -ENOMEM; - down_read(&snd_ioctl_rwsem); - info->card = card->number; - strlcpy(info->id, card->id, sizeof(info->id)); - strlcpy(info->driver, card->driver, sizeof(info->driver)); - strlcpy(info->name, card->shortname, sizeof(info->name)); - strlcpy(info->longname, card->longname, sizeof(info->longname)); - strlcpy(info->mixername, card->mixername, sizeof(info->mixername)); - strlcpy(info->components, card->components, sizeof(info->components)); - up_read(&snd_ioctl_rwsem); - if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) { - kfree(info); - return -EFAULT; - } - kfree(info); - return 0; -} - -static int snd_ctl_elem_list(struct snd_card *card, - struct snd_ctl_elem_list __user *_list) -{ - struct list_head *plist; - struct snd_ctl_elem_list list; - struct snd_kcontrol *kctl; - struct snd_ctl_elem_id *dst, *id; - unsigned int offset, space, jidx; - - if (copy_from_user(&list, _list, sizeof(list))) - return -EFAULT; - offset = list.offset; - space = list.space; - /* try limit maximum space */ - if (space > 16384) - return -ENOMEM; - if (space > 0) { - /* allocate temporary buffer for atomic operation */ - dst = vmalloc(space * sizeof(struct snd_ctl_elem_id)); - if (dst == NULL) - return -ENOMEM; - down_read(&card->controls_rwsem); - list.count = card->controls_count; - plist = card->controls.next; - while (plist != &card->controls) { - if (offset == 0) - break; - kctl = snd_kcontrol(plist); - if (offset < kctl->count) - break; - offset -= kctl->count; - plist = plist->next; - } - list.used = 0; - id = dst; - while (space > 0 && plist != &card->controls) { - kctl = snd_kcontrol(plist); - for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) { - snd_ctl_build_ioff(id, kctl, jidx); - id++; - space--; - list.used++; - } - plist = plist->next; - offset = 0; - } - up_read(&card->controls_rwsem); - if (list.used > 0 && - copy_to_user(list.pids, dst, - list.used * sizeof(struct snd_ctl_elem_id))) { - vfree(dst); - return -EFAULT; - } - vfree(dst); - } else { - down_read(&card->controls_rwsem); - list.count = card->controls_count; - up_read(&card->controls_rwsem); - } - if (copy_to_user(_list, &list, sizeof(list))) - return -EFAULT; - return 0; -} - -static int snd_ctl_elem_info(struct snd_ctl_file *ctl, - struct snd_ctl_elem_info *info) -{ - struct snd_card *card = ctl->card; - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - unsigned int index_offset; - int result; - - down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, &info->id); - if (kctl == NULL) { - up_read(&card->controls_rwsem); - return -ENOENT; - } -#ifdef CONFIG_SND_DEBUG - info->access = 0; -#endif - result = kctl->info(kctl, info); - if (result >= 0) { - snd_BUG_ON(info->access); - index_offset = snd_ctl_get_ioff(kctl, &info->id); - vd = &kctl->vd[index_offset]; - snd_ctl_build_ioff(&info->id, kctl, index_offset); - info->access = vd->access; - if (vd->owner) { - info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK; - if (vd->owner == ctl) - info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER; - info->owner = pid_vnr(vd->owner->pid); - } else { - info->owner = -1; - } - } - up_read(&card->controls_rwsem); - return result; -} - -static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl, - struct snd_ctl_elem_info __user *_info) -{ - struct snd_ctl_elem_info info; - int result; - - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - snd_power_lock(ctl->card); - result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); - if (result >= 0) - result = snd_ctl_elem_info(ctl, &info); - snd_power_unlock(ctl->card); - if (result >= 0) - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return result; -} - -static int snd_ctl_elem_read(struct snd_card *card, - struct snd_ctl_elem_value *control) -{ - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - unsigned int index_offset; - int result; - - down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, &control->id); - if (kctl == NULL) { - result = -ENOENT; - } else { - index_offset = snd_ctl_get_ioff(kctl, &control->id); - vd = &kctl->vd[index_offset]; - if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && - kctl->get != NULL) { - snd_ctl_build_ioff(&control->id, kctl, index_offset); - result = kctl->get(kctl, control); - } else - result = -EPERM; - } - up_read(&card->controls_rwsem); - return result; -} - -static int snd_ctl_elem_read_user(struct snd_card *card, - struct snd_ctl_elem_value __user *_control) -{ - struct snd_ctl_elem_value *control; - int result; - - 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) - result = snd_ctl_elem_read(card, control); - snd_power_unlock(card); - if (result >= 0) - if (copy_to_user(_control, control, sizeof(*control))) - result = -EFAULT; - kfree(control); - return result; -} - -static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, - struct snd_ctl_elem_value *control) -{ - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - unsigned int index_offset; - int result; - - down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, &control->id); - if (kctl == NULL) { - result = -ENOENT; - } else { - index_offset = snd_ctl_get_ioff(kctl, &control->id); - vd = &kctl->vd[index_offset]; - if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || - kctl->put == NULL || - (file && vd->owner && vd->owner != file)) { - result = -EPERM; - } else { - snd_ctl_build_ioff(&control->id, kctl, index_offset); - result = kctl->put(kctl, control); - } - if (result > 0) { - up_read(&card->controls_rwsem); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &control->id); - return 0; - } - } - up_read(&card->controls_rwsem); - return result; -} - -static int snd_ctl_elem_write_user(struct snd_ctl_file *file, - struct snd_ctl_elem_value __user *_control) -{ - struct snd_ctl_elem_value *control; - struct snd_card *card; - int result; - - 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); - if (result >= 0) - result = snd_ctl_elem_write(card, file, control); - snd_power_unlock(card); - if (result >= 0) - if (copy_to_user(_control, control, sizeof(*control))) - result = -EFAULT; - kfree(control); - return result; -} - -static int snd_ctl_elem_lock(struct snd_ctl_file *file, - struct snd_ctl_elem_id __user *_id) -{ - struct snd_card *card = file->card; - struct snd_ctl_elem_id id; - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - int result; - - if (copy_from_user(&id, _id, sizeof(id))) - return -EFAULT; - down_write(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, &id); - if (kctl == NULL) { - result = -ENOENT; - } else { - vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)]; - if (vd->owner != NULL) - result = -EBUSY; - else { - vd->owner = file; - result = 0; - } - } - up_write(&card->controls_rwsem); - return result; -} - -static int snd_ctl_elem_unlock(struct snd_ctl_file *file, - struct snd_ctl_elem_id __user *_id) -{ - struct snd_card *card = file->card; - struct snd_ctl_elem_id id; - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - int result; - - if (copy_from_user(&id, _id, sizeof(id))) - return -EFAULT; - down_write(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, &id); - if (kctl == NULL) { - result = -ENOENT; - } else { - vd = &kctl->vd[snd_ctl_get_ioff(kctl, &id)]; - if (vd->owner == NULL) - result = -EINVAL; - else if (vd->owner != file) - result = -EPERM; - else { - vd->owner = NULL; - result = 0; - } - } - up_write(&card->controls_rwsem); - return result; -} - -struct user_element { - struct snd_ctl_elem_info info; - void *elem_data; /* element data */ - unsigned long elem_data_size; /* size of element data in bytes */ - void *tlv_data; /* TLV data */ - unsigned long tlv_data_size; /* TLV data size */ - void *priv_data; /* private data (like strings for enumerated type) */ -}; - -static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct user_element *ue = kcontrol->private_data; - - *uinfo = ue->info; - return 0; -} - -static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct user_element *ue = kcontrol->private_data; - const char *names; - unsigned int item; - - item = uinfo->value.enumerated.item; - - *uinfo = ue->info; - - item = min(item, uinfo->value.enumerated.items - 1); - uinfo->value.enumerated.item = item; - - names = ue->priv_data; - for (; item > 0; --item) - names += strlen(names) + 1; - strcpy(uinfo->value.enumerated.name, names); - - return 0; -} - -static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct user_element *ue = kcontrol->private_data; - - memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size); - return 0; -} - -static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int change; - struct user_element *ue = kcontrol->private_data; - - change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 0; - if (change) - memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size); - return change; -} - -static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, - int op_flag, - unsigned int size, - unsigned int __user *tlv) -{ - struct user_element *ue = kcontrol->private_data; - int change = 0; - void *new_data; - - if (op_flag > 0) { - if (size > 1024 * 128) /* sane value */ - return -EINVAL; - - 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); - kfree(ue->tlv_data); - ue->tlv_data = new_data; - ue->tlv_data_size = size; - } else { - if (! ue->tlv_data_size || ! ue->tlv_data) - return -ENXIO; - if (size < ue->tlv_data_size) - return -ENOSPC; - if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size)) - return -EFAULT; - } - return change; -} - -static int snd_ctl_elem_init_enum_names(struct user_element *ue) -{ - char *names, *p; - size_t buf_len, name_len; - unsigned int i; - const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr; - - if (ue->info.value.enumerated.names_length > 64 * 1024) - return -EINVAL; - - names = memdup_user((const void __user *)user_ptrval, - ue->info.value.enumerated.names_length); - if (IS_ERR(names)) - return PTR_ERR(names); - - /* check that there are enough valid names */ - buf_len = ue->info.value.enumerated.names_length; - p = names; - for (i = 0; i < ue->info.value.enumerated.items; ++i) { - name_len = strnlen(p, buf_len); - if (name_len == 0 || name_len >= 64 || name_len == buf_len) { - kfree(names); - return -EINVAL; - } - p += name_len + 1; - buf_len -= name_len + 1; - } - - ue->priv_data = names; - ue->info.value.enumerated.names_ptr = 0; - - return 0; -} - -static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol) -{ - struct user_element *ue = kcontrol->private_data; - - kfree(ue->tlv_data); - kfree(ue->priv_data); - kfree(ue); -} - -static int snd_ctl_elem_add(struct snd_ctl_file *file, - struct snd_ctl_elem_info *info, int replace) -{ - struct snd_card *card = file->card; - struct snd_kcontrol kctl, *_kctl; - unsigned int access; - long private_size; - struct user_element *ue; - int idx, err; - - if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS) - return -ENOMEM; - if (info->count < 1) - return -EINVAL; - access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : - (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| - SNDRV_CTL_ELEM_ACCESS_INACTIVE| - SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)); - info->id.numid = 0; - memset(&kctl, 0, sizeof(kctl)); - down_write(&card->controls_rwsem); - _kctl = snd_ctl_find_id(card, &info->id); - err = 0; - if (_kctl) { - if (replace) - err = snd_ctl_remove(card, _kctl); - else - err = -EBUSY; - } else { - if (replace) - err = -ENOENT; - } - up_write(&card->controls_rwsem); - if (err < 0) - return err; - memcpy(&kctl.id, &info->id, sizeof(info->id)); - kctl.count = info->owner ? info->owner : 1; - access |= SNDRV_CTL_ELEM_ACCESS_USER; - if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) - kctl.info = snd_ctl_elem_user_enum_info; - else - kctl.info = snd_ctl_elem_user_info; - if (access & SNDRV_CTL_ELEM_ACCESS_READ) - kctl.get = snd_ctl_elem_user_get; - if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) - kctl.put = snd_ctl_elem_user_put; - if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) { - kctl.tlv.c = snd_ctl_elem_user_tlv; - access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; - } - switch (info->type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - private_size = sizeof(long); - if (info->count > 128) - return -EINVAL; - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - private_size = sizeof(long long); - if (info->count > 64) - return -EINVAL; - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - private_size = sizeof(unsigned int); - if (info->count > 128 || info->value.enumerated.items == 0) - return -EINVAL; - break; - case SNDRV_CTL_ELEM_TYPE_BYTES: - private_size = sizeof(unsigned char); - if (info->count > 512) - return -EINVAL; - break; - case SNDRV_CTL_ELEM_TYPE_IEC958: - private_size = sizeof(struct snd_aes_iec958); - if (info->count != 1) - return -EINVAL; - break; - default: - return -EINVAL; - } - private_size *= info->count; - ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL); - if (ue == NULL) - return -ENOMEM; - ue->info = *info; - ue->info.access = 0; - ue->elem_data = (char *)ue + sizeof(*ue); - ue->elem_data_size = private_size; - if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { - err = snd_ctl_elem_init_enum_names(ue); - if (err < 0) { - kfree(ue); - return err; - } - } - kctl.private_free = snd_ctl_elem_user_free; - _kctl = snd_ctl_new(&kctl, access); - if (_kctl == NULL) { - kfree(ue->priv_data); - kfree(ue); - return -ENOMEM; - } - _kctl->private_data = ue; - for (idx = 0; idx < _kctl->count; idx++) - _kctl->vd[idx].owner = file; - err = snd_ctl_add(card, _kctl); - if (err < 0) - return err; - - down_write(&card->controls_rwsem); - card->user_ctl_count++; - up_write(&card->controls_rwsem); - - return 0; -} - -static int snd_ctl_elem_add_user(struct snd_ctl_file *file, - struct snd_ctl_elem_info __user *_info, int replace) -{ - struct snd_ctl_elem_info info; - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - return snd_ctl_elem_add(file, &info, replace); -} - -static int snd_ctl_elem_remove(struct snd_ctl_file *file, - struct snd_ctl_elem_id __user *_id) -{ - struct snd_ctl_elem_id id; - - if (copy_from_user(&id, _id, sizeof(id))) - return -EFAULT; - return snd_ctl_remove_user_ctl(file, &id); -} - -static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) -{ - int subscribe; - if (get_user(subscribe, ptr)) - return -EFAULT; - if (subscribe < 0) { - subscribe = file->subscribed; - if (put_user(subscribe, ptr)) - return -EFAULT; - return 0; - } - if (subscribe) { - file->subscribed = 1; - return 0; - } else if (file->subscribed) { - snd_ctl_empty_read_queue(file); - file->subscribed = 0; - } - return 0; -} - -static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, - struct snd_ctl_tlv __user *_tlv, - int op_flag) -{ - struct snd_card *card = file->card; - struct snd_ctl_tlv tlv; - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - unsigned int len; - int err = 0; - - if (copy_from_user(&tlv, _tlv, sizeof(tlv))) - return -EFAULT; - if (tlv.length < sizeof(unsigned int) * 2) - return -EINVAL; - down_read(&card->controls_rwsem); - kctl = snd_ctl_find_numid(card, tlv.numid); - if (kctl == NULL) { - err = -ENOENT; - goto __kctl_end; - } - if (kctl->tlv.p == NULL) { - err = -ENXIO; - goto __kctl_end; - } - vd = &kctl->vd[tlv.numid - kctl->id.numid]; - if ((op_flag == 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) == 0) || - (op_flag > 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) == 0) || - (op_flag < 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) == 0)) { - err = -ENXIO; - goto __kctl_end; - } - if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - if (vd->owner != NULL && vd->owner != file) { - err = -EPERM; - goto __kctl_end; - } - err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv); - if (err > 0) { - up_read(&card->controls_rwsem); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id); - return 0; - } - } else { - if (op_flag) { - err = -ENXIO; - goto __kctl_end; - } - len = kctl->tlv.p[1] + 2 * sizeof(unsigned int); - if (tlv.length < len) { - err = -ENOMEM; - goto __kctl_end; - } - if (copy_to_user(_tlv->tlv, kctl->tlv.p, len)) - err = -EFAULT; - } - __kctl_end: - up_read(&card->controls_rwsem); - return err; -} - -static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_ctl_file *ctl; - struct snd_card *card; - struct snd_kctl_ioctl *p; - void __user *argp = (void __user *)arg; - int __user *ip = argp; - int err; - - ctl = file->private_data; - card = ctl->card; - if (snd_BUG_ON(!card)) - return -ENXIO; - switch (cmd) { - case SNDRV_CTL_IOCTL_PVERSION: - return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0; - case SNDRV_CTL_IOCTL_CARD_INFO: - return snd_ctl_card_info(card, ctl, cmd, argp); - case SNDRV_CTL_IOCTL_ELEM_LIST: - return snd_ctl_elem_list(card, argp); - case SNDRV_CTL_IOCTL_ELEM_INFO: - return snd_ctl_elem_info_user(ctl, argp); - case SNDRV_CTL_IOCTL_ELEM_READ: - return snd_ctl_elem_read_user(card, argp); - case SNDRV_CTL_IOCTL_ELEM_WRITE: - return snd_ctl_elem_write_user(ctl, argp); - case SNDRV_CTL_IOCTL_ELEM_LOCK: - return snd_ctl_elem_lock(ctl, argp); - case SNDRV_CTL_IOCTL_ELEM_UNLOCK: - return snd_ctl_elem_unlock(ctl, argp); - case SNDRV_CTL_IOCTL_ELEM_ADD: - return snd_ctl_elem_add_user(ctl, argp, 0); - case SNDRV_CTL_IOCTL_ELEM_REPLACE: - return snd_ctl_elem_add_user(ctl, argp, 1); - case SNDRV_CTL_IOCTL_ELEM_REMOVE: - return snd_ctl_elem_remove(ctl, argp); - case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: - return snd_ctl_subscribe_events(ctl, ip); - case SNDRV_CTL_IOCTL_TLV_READ: - return snd_ctl_tlv_ioctl(ctl, argp, 0); - case SNDRV_CTL_IOCTL_TLV_WRITE: - return snd_ctl_tlv_ioctl(ctl, argp, 1); - case SNDRV_CTL_IOCTL_TLV_COMMAND: - return snd_ctl_tlv_ioctl(ctl, argp, -1); - case SNDRV_CTL_IOCTL_POWER: - return -ENOPROTOOPT; - case SNDRV_CTL_IOCTL_POWER_STATE: -#ifdef CONFIG_PM - return put_user(card->power_state, ip) ? -EFAULT : 0; -#else - return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0; -#endif - } - down_read(&snd_ioctl_rwsem); - list_for_each_entry(p, &snd_control_ioctls, list) { - err = p->fioctl(card, ctl, cmd, arg); - if (err != -ENOIOCTLCMD) { - up_read(&snd_ioctl_rwsem); - return err; - } - } - up_read(&snd_ioctl_rwsem); - snd_printdd("unknown ioctl = 0x%x\n", cmd); - return -ENOTTY; -} - -static ssize_t snd_ctl_read(struct file *file, char __user *buffer, - size_t count, loff_t * offset) -{ - struct snd_ctl_file *ctl; - int err = 0; - ssize_t result = 0; - - ctl = file->private_data; - if (snd_BUG_ON(!ctl || !ctl->card)) - return -ENXIO; - if (!ctl->subscribed) - return -EBADFD; - if (count < sizeof(struct snd_ctl_event)) - return -EINVAL; - spin_lock_irq(&ctl->read_lock); - while (count >= sizeof(struct snd_ctl_event)) { - struct snd_ctl_event ev; - struct snd_kctl_event *kev; - while (list_empty(&ctl->events)) { - wait_queue_t wait; - if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { - err = -EAGAIN; - goto __end_lock; - } - init_waitqueue_entry(&wait, current); - add_wait_queue(&ctl->change_sleep, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(&ctl->read_lock); - schedule(); - remove_wait_queue(&ctl->change_sleep, &wait); - if (ctl->card->shutdown) - return -ENODEV; - if (signal_pending(current)) - return -ERESTARTSYS; - spin_lock_irq(&ctl->read_lock); - } - kev = snd_kctl_event(ctl->events.next); - ev.type = SNDRV_CTL_EVENT_ELEM; - ev.data.elem.mask = kev->mask; - ev.data.elem.id = kev->id; - list_del(&kev->list); - spin_unlock_irq(&ctl->read_lock); - kfree(kev); - if (copy_to_user(buffer, &ev, sizeof(struct snd_ctl_event))) { - err = -EFAULT; - goto __end; - } - spin_lock_irq(&ctl->read_lock); - buffer += sizeof(struct snd_ctl_event); - count -= sizeof(struct snd_ctl_event); - result += sizeof(struct snd_ctl_event); - } - __end_lock: - spin_unlock_irq(&ctl->read_lock); - __end: - return result > 0 ? result : err; -} - -static unsigned int snd_ctl_poll(struct file *file, poll_table * wait) -{ - unsigned int mask; - struct snd_ctl_file *ctl; - - ctl = file->private_data; - if (!ctl->subscribed) - return 0; - poll_wait(file, &ctl->change_sleep, wait); - - mask = 0; - if (!list_empty(&ctl->events)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} - -/* - * register the device-specific control-ioctls. - * called from each device manager like pcm.c, hwdep.c, etc. - */ -static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) -{ - struct snd_kctl_ioctl *pn; - - pn = kzalloc(sizeof(struct snd_kctl_ioctl), GFP_KERNEL); - if (pn == NULL) - return -ENOMEM; - pn->fioctl = fcn; - down_write(&snd_ioctl_rwsem); - list_add_tail(&pn->list, lists); - up_write(&snd_ioctl_rwsem); - return 0; -} - -int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) -{ - return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); -} - -EXPORT_SYMBOL(snd_ctl_register_ioctl); - -#ifdef CONFIG_COMPAT -int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) -{ - return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); -} - -EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); -#endif - -/* - * de-register the device-specific control-ioctls. - */ -static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, - struct list_head *lists) -{ - struct snd_kctl_ioctl *p; - - if (snd_BUG_ON(!fcn)) - return -EINVAL; - down_write(&snd_ioctl_rwsem); - list_for_each_entry(p, lists, list) { - if (p->fioctl == fcn) { - list_del(&p->list); - up_write(&snd_ioctl_rwsem); - kfree(p); - return 0; - } - } - up_write(&snd_ioctl_rwsem); - snd_BUG(); - return -EINVAL; -} - -int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) -{ - return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); -} - -EXPORT_SYMBOL(snd_ctl_unregister_ioctl); - -#ifdef CONFIG_COMPAT -int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) -{ - return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); -} - -EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); -#endif - -static int snd_ctl_fasync(int fd, struct file * file, int on) -{ - struct snd_ctl_file *ctl; - - ctl = file->private_data; - return fasync_helper(fd, file, on, &ctl->fasync); -} - -/* - * ioctl32 compat - */ -#ifdef CONFIG_COMPAT -#include "control_compat.c" -#else -#define snd_ctl_ioctl_compat NULL -#endif - -/* - * INIT PART - */ - -static const struct file_operations snd_ctl_f_ops = -{ - .owner = THIS_MODULE, - .read = snd_ctl_read, - .open = snd_ctl_open, - .release = snd_ctl_release, - .llseek = no_llseek, - .poll = snd_ctl_poll, - .unlocked_ioctl = snd_ctl_ioctl, - .compat_ioctl = snd_ctl_ioctl_compat, - .fasync = snd_ctl_fasync, -}; - -/* - * registration of the control device - */ -static int snd_ctl_dev_register(struct snd_device *device) -{ - struct snd_card *card = device->device_data; - int err, cardnum; - char name[16]; - - if (snd_BUG_ON(!card)) - return -ENXIO; - cardnum = card->number; - if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS)) - return -ENXIO; - sprintf(name, "controlC%i", cardnum); - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1, - &snd_ctl_f_ops, card, name)) < 0) - return err; - return 0; -} - -/* - * disconnection of the control device - */ -static int snd_ctl_dev_disconnect(struct snd_device *device) -{ - struct snd_card *card = device->device_data; - struct snd_ctl_file *ctl; - int err, cardnum; - - if (snd_BUG_ON(!card)) - return -ENXIO; - cardnum = card->number; - if (snd_BUG_ON(cardnum < 0 || cardnum >= SNDRV_CARDS)) - return -ENXIO; - - read_lock(&card->ctl_files_rwlock); - list_for_each_entry(ctl, &card->ctl_files, list) { - wake_up(&ctl->change_sleep); - kill_fasync(&ctl->fasync, SIGIO, POLL_ERR); - } - read_unlock(&card->ctl_files_rwlock); - - if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, - card, -1)) < 0) - return err; - return 0; -} - -/* - * free all controls - */ -static int snd_ctl_dev_free(struct snd_device *device) -{ - struct snd_card *card = device->device_data; - struct snd_kcontrol *control; - - down_write(&card->controls_rwsem); - while (!list_empty(&card->controls)) { - control = snd_kcontrol(card->controls.next); - snd_ctl_remove(card, control); - } - up_write(&card->controls_rwsem); - return 0; -} - -/* - * create control core: - * called from init.c - */ -int snd_ctl_create(struct snd_card *card) -{ - static struct snd_device_ops ops = { - .dev_free = snd_ctl_dev_free, - .dev_register = snd_ctl_dev_register, - .dev_disconnect = snd_ctl_dev_disconnect, - }; - - if (snd_BUG_ON(!card)) - return -ENXIO; - return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); -} - -/* - * Frequently used control callbacks/helpers - */ -int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -EXPORT_SYMBOL(snd_ctl_boolean_mono_info); - -int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -EXPORT_SYMBOL(snd_ctl_boolean_stereo_info); - -/** - * snd_ctl_enum_info - fills the info structure for an enumerated control - * @info: the structure to be filled - * @channels: the number of the control's channels; often one - * @items: the number of control values; also the size of @names - * @names: an array containing the names of all control values - * - * Sets all required fields in @info to their appropriate values. - * If the control's accessibility is not the default (readable and writable), - * the caller has to fill @info->access. - */ -int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels, - unsigned int items, const char *const names[]) -{ - info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - info->count = channels; - info->value.enumerated.items = items; - if (info->value.enumerated.item >= items) - info->value.enumerated.item = items - 1; - strlcpy(info->value.enumerated.name, - names[info->value.enumerated.item], - sizeof(info->value.enumerated.name)); - return 0; -} -EXPORT_SYMBOL(snd_ctl_enum_info); diff --git a/ANDROID_3.4.5/sound/core/control_compat.c b/ANDROID_3.4.5/sound/core/control_compat.c deleted file mode 100644 index 2bb95a7a..00000000 --- a/ANDROID_3.4.5/sound/core/control_compat.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * compat ioctls for control API - * - * Copyright (c) by Takashi Iwai - * - * 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 - */ - -/* this file included from control.c */ - -#include -#include - -struct snd_ctl_elem_list32 { - u32 offset; - u32 space; - u32 used; - u32 count; - u32 pids; - unsigned char reserved[50]; -} /* don't set packed attribute here */; - -static int snd_ctl_elem_list_compat(struct snd_card *card, - struct snd_ctl_elem_list32 __user *data32) -{ - struct snd_ctl_elem_list __user *data; - compat_caddr_t ptr; - int err; - - data = compat_alloc_user_space(sizeof(*data)); - - /* offset, space, used, count */ - if (copy_in_user(data, data32, 4 * sizeof(u32))) - return -EFAULT; - /* pids */ - if (get_user(ptr, &data32->pids) || - put_user(compat_ptr(ptr), &data->pids)) - return -EFAULT; - err = snd_ctl_elem_list(card, data); - if (err < 0) - return err; - /* copy the result */ - if (copy_in_user(data32, data, 4 * sizeof(u32))) - return -EFAULT; - return 0; -} - -/* - * control element info - * it uses union, so the things are not easy.. - */ - -struct snd_ctl_elem_info32 { - struct snd_ctl_elem_id id; // the size of struct is same - s32 type; - u32 access; - u32 count; - s32 owner; - union { - struct { - s32 min; - s32 max; - s32 step; - } integer; - struct { - u64 min; - u64 max; - u64 step; - } integer64; - struct { - u32 items; - u32 item; - char name[64]; - u64 names_ptr; - u32 names_length; - } enumerated; - unsigned char reserved[128]; - } value; - unsigned char reserved[64]; -} __attribute__((packed)); - -static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, - struct snd_ctl_elem_info32 __user *data32) -{ - struct snd_ctl_elem_info *data; - int err; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (! data) - return -ENOMEM; - - err = -EFAULT; - /* copy id */ - if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) - goto error; - /* we need to copy the item index. - * hope this doesn't break anything.. - */ - if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) - goto error; - - snd_power_lock(ctl->card); - err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); - if (err >= 0) - err = snd_ctl_elem_info(ctl, data); - snd_power_unlock(ctl->card); - - if (err < 0) - goto error; - /* restore info to 32bit */ - err = -EFAULT; - /* id, type, access, count */ - if (copy_to_user(&data32->id, &data->id, sizeof(data->id)) || - copy_to_user(&data32->type, &data->type, 3 * sizeof(u32))) - goto error; - if (put_user(data->owner, &data32->owner)) - goto error; - switch (data->type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - if (put_user(data->value.integer.min, &data32->value.integer.min) || - put_user(data->value.integer.max, &data32->value.integer.max) || - put_user(data->value.integer.step, &data32->value.integer.step)) - goto error; - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - if (copy_to_user(&data32->value.integer64, - &data->value.integer64, - sizeof(data->value.integer64))) - goto error; - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - if (copy_to_user(&data32->value.enumerated, - &data->value.enumerated, - sizeof(data->value.enumerated))) - goto error; - break; - default: - break; - } - err = 0; - error: - kfree(data); - return err; -} - -/* read / write */ -struct snd_ctl_elem_value32 { - struct snd_ctl_elem_id id; - unsigned int indirect; /* bit-field causes misalignment */ - union { - s32 integer[128]; - unsigned char data[512]; -#ifndef CONFIG_X86_64 - s64 integer64[64]; -#endif - } value; - unsigned char reserved[128]; -}; - - -/* get the value type and count of the control */ -static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, - int *countp) -{ - struct snd_kcontrol *kctl; - struct snd_ctl_elem_info *info; - int err; - - down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, id); - if (! kctl) { - up_read(&card->controls_rwsem); - return -ENXIO; - } - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (info == NULL) { - up_read(&card->controls_rwsem); - return -ENOMEM; - } - info->id = *id; - err = kctl->info(kctl, info); - up_read(&card->controls_rwsem); - if (err >= 0) { - err = info->type; - *countp = info->count; - } - kfree(info); - return err; -} - -static int get_elem_size(int type, int count) -{ - switch (type) { - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - return sizeof(s64) * count; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - return sizeof(int) * count; - case SNDRV_CTL_ELEM_TYPE_BYTES: - return 512; - case SNDRV_CTL_ELEM_TYPE_IEC958: - return sizeof(struct snd_aes_iec958); - default: - return -1; - } -} - -static int copy_ctl_value_from_user(struct snd_card *card, - struct snd_ctl_elem_value *data, - struct snd_ctl_elem_value32 __user *data32, - int *typep, int *countp) -{ - int i, type, size; - int uninitialized_var(count); - unsigned int indirect; - - if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) - return -EFAULT; - if (get_user(indirect, &data32->indirect)) - return -EFAULT; - if (indirect) - return -EINVAL; - type = get_ctl_type(card, &data->id, &count); - if (type < 0) - return type; - - if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || - type == SNDRV_CTL_ELEM_TYPE_INTEGER) { - for (i = 0; i < count; i++) { - int val; - if (get_user(val, &data32->value.integer[i])) - return -EFAULT; - data->value.integer.value[i] = val; - } - } else { - size = get_elem_size(type, count); - if (size < 0) { - printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); - return -EINVAL; - } - if (copy_from_user(data->value.bytes.data, - data32->value.data, size)) - return -EFAULT; - } - - *typep = type; - *countp = count; - return 0; -} - -/* restore the value to 32bit */ -static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32, - struct snd_ctl_elem_value *data, - int type, int count) -{ - int i, size; - - if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || - type == SNDRV_CTL_ELEM_TYPE_INTEGER) { - for (i = 0; i < count; i++) { - int val; - val = data->value.integer.value[i]; - if (put_user(val, &data32->value.integer[i])) - return -EFAULT; - } - } else { - size = get_elem_size(type, count); - if (copy_to_user(data32->value.data, - data->value.bytes.data, size)) - return -EFAULT; - } - return 0; -} - -static int snd_ctl_elem_read_user_compat(struct snd_card *card, - struct snd_ctl_elem_value32 __user *data32) -{ - struct snd_ctl_elem_value *data; - int err, type, count; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) - goto error; - - snd_power_lock(card); - err = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (err >= 0) - err = snd_ctl_elem_read(card, data); - snd_power_unlock(card); - if (err >= 0) - err = copy_ctl_value_to_user(data32, data, type, count); - error: - kfree(data); - return err; -} - -static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file, - struct snd_ctl_elem_value32 __user *data32) -{ - struct snd_ctl_elem_value *data; - struct snd_card *card = file->card; - int err, type, count; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) - goto error; - - snd_power_lock(card); - err = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (err >= 0) - err = snd_ctl_elem_write(card, file, data); - snd_power_unlock(card); - if (err >= 0) - err = copy_ctl_value_to_user(data32, data, type, count); - error: - kfree(data); - return err; -} - -/* add or replace a user control */ -static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, - struct snd_ctl_elem_info32 __user *data32, - int replace) -{ - struct snd_ctl_elem_info *data; - int err; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (! data) - return -ENOMEM; - - err = -EFAULT; - /* id, type, access, count */ \ - if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || - copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) - goto error; - if (get_user(data->owner, &data32->owner) || - get_user(data->type, &data32->type)) - goto error; - switch (data->type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - case SNDRV_CTL_ELEM_TYPE_INTEGER: - if (get_user(data->value.integer.min, &data32->value.integer.min) || - get_user(data->value.integer.max, &data32->value.integer.max) || - get_user(data->value.integer.step, &data32->value.integer.step)) - goto error; - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER64: - if (copy_from_user(&data->value.integer64, - &data32->value.integer64, - sizeof(data->value.integer64))) - goto error; - break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - if (copy_from_user(&data->value.enumerated, - &data32->value.enumerated, - sizeof(data->value.enumerated))) - goto error; - data->value.enumerated.names_ptr = - (uintptr_t)compat_ptr(data->value.enumerated.names_ptr); - break; - default: - break; - } - err = snd_ctl_elem_add(file, data, replace); - error: - kfree(data); - return err; -} - -enum { - SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct snd_ctl_elem_list32), - SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct snd_ctl_elem_info32), - SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct snd_ctl_elem_value32), - SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32), - SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32), - SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32), -}; - -static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_ctl_file *ctl; - struct snd_kctl_ioctl *p; - void __user *argp = compat_ptr(arg); - int err; - - ctl = file->private_data; - if (snd_BUG_ON(!ctl || !ctl->card)) - return -ENXIO; - - switch (cmd) { - case SNDRV_CTL_IOCTL_PVERSION: - case SNDRV_CTL_IOCTL_CARD_INFO: - case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: - case SNDRV_CTL_IOCTL_POWER: - case SNDRV_CTL_IOCTL_POWER_STATE: - case SNDRV_CTL_IOCTL_ELEM_LOCK: - case SNDRV_CTL_IOCTL_ELEM_UNLOCK: - case SNDRV_CTL_IOCTL_ELEM_REMOVE: - case SNDRV_CTL_IOCTL_TLV_READ: - case SNDRV_CTL_IOCTL_TLV_WRITE: - case SNDRV_CTL_IOCTL_TLV_COMMAND: - return snd_ctl_ioctl(file, cmd, (unsigned long)argp); - case SNDRV_CTL_IOCTL_ELEM_LIST32: - return snd_ctl_elem_list_compat(ctl->card, argp); - case SNDRV_CTL_IOCTL_ELEM_INFO32: - return snd_ctl_elem_info_compat(ctl, argp); - case SNDRV_CTL_IOCTL_ELEM_READ32: - return snd_ctl_elem_read_user_compat(ctl->card, argp); - case SNDRV_CTL_IOCTL_ELEM_WRITE32: - return snd_ctl_elem_write_user_compat(ctl, argp); - case SNDRV_CTL_IOCTL_ELEM_ADD32: - return snd_ctl_elem_add_compat(ctl, argp, 0); - case SNDRV_CTL_IOCTL_ELEM_REPLACE32: - return snd_ctl_elem_add_compat(ctl, argp, 1); - } - - down_read(&snd_ioctl_rwsem); - list_for_each_entry(p, &snd_control_compat_ioctls, list) { - if (p->fioctl) { - err = p->fioctl(ctl->card, ctl, cmd, arg); - if (err != -ENOIOCTLCMD) { - up_read(&snd_ioctl_rwsem); - return err; - } - } - } - up_read(&snd_ioctl_rwsem); - return -ENOIOCTLCMD; -} diff --git a/ANDROID_3.4.5/sound/core/ctljack.c b/ANDROID_3.4.5/sound/core/ctljack.c deleted file mode 100644 index e4b38fbe..00000000 --- a/ANDROID_3.4.5/sound/core/ctljack.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Helper functions for jack-detection kcontrols - * - * Copyright (c) 2011 Takashi Iwai - * - * 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. - */ - -#include -#include -#include -#include - -#define jack_detect_kctl_info snd_ctl_boolean_mono_info - -static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = kcontrol->private_value; - return 0; -} - -static struct snd_kcontrol_new jack_detect_kctl = { - /* name is filled later */ - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = jack_detect_kctl_info, - .get = jack_detect_kctl_get, -}; - -struct snd_kcontrol * -snd_kctl_jack_new(const char *name, int idx, void *private_data) -{ - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(&jack_detect_kctl, private_data); - if (!kctl) - return NULL; - snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name); - kctl->id.index = idx; - kctl->private_value = 0; - return kctl; -} -EXPORT_SYMBOL_GPL(snd_kctl_jack_new); - -void snd_kctl_jack_report(struct snd_card *card, - struct snd_kcontrol *kctl, bool status) -{ - if (kctl->private_value == status) - return; - kctl->private_value = status; - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); -} -EXPORT_SYMBOL_GPL(snd_kctl_jack_report); diff --git a/ANDROID_3.4.5/sound/core/device.c b/ANDROID_3.4.5/sound/core/device.c deleted file mode 100644 index f03cb544..00000000 --- a/ANDROID_3.4.5/sound/core/device.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Device management routines - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -/** - * snd_device_new - create an ALSA device component - * @card: the card instance - * @type: the device type, SNDRV_DEV_XXX - * @device_data: the data pointer of this device - * @ops: the operator table - * - * Creates a new device component for the given data pointer. - * The device will be assigned to the card and managed together - * by the card. - * - * The data pointer plays a role as the identifier, too, so the - * pointer address must be unique and unchanged. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_device_new(struct snd_card *card, snd_device_type_t type, - void *device_data, struct snd_device_ops *ops) -{ - struct snd_device *dev; - - if (snd_BUG_ON(!card || !device_data || !ops)) - return -ENXIO; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - snd_printk(KERN_ERR "Cannot allocate device\n"); - return -ENOMEM; - } - dev->card = card; - dev->type = type; - dev->state = SNDRV_DEV_BUILD; - dev->device_data = device_data; - dev->ops = ops; - list_add(&dev->list, &card->devices); /* add to the head of list */ - return 0; -} - -EXPORT_SYMBOL(snd_device_new); - -/** - * snd_device_free - release the device from the card - * @card: the card instance - * @device_data: the data pointer to release - * - * Removes the device from the list on the card and invokes the - * callbacks, dev_disconnect and dev_free, corresponding to the state. - * Then release the device. - * - * Returns zero if successful, or a negative error code on failure or if the - * device not found. - */ -int snd_device_free(struct snd_card *card, void *device_data) -{ - struct snd_device *dev; - - if (snd_BUG_ON(!card || !device_data)) - return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (dev->device_data != device_data) - continue; - /* unlink */ - list_del(&dev->list); - if (dev->state == SNDRV_DEV_REGISTERED && - dev->ops->dev_disconnect) - if (dev->ops->dev_disconnect(dev)) - snd_printk(KERN_ERR - "device disconnect failure\n"); - if (dev->ops->dev_free) { - if (dev->ops->dev_free(dev)) - snd_printk(KERN_ERR "device free failure\n"); - } - kfree(dev); - return 0; - } - snd_printd("device free %p (from %pF), not found\n", device_data, - __builtin_return_address(0)); - return -ENXIO; -} - -EXPORT_SYMBOL(snd_device_free); - -/** - * snd_device_disconnect - disconnect the device - * @card: the card instance - * @device_data: the data pointer to disconnect - * - * Turns the device into the disconnection state, invoking - * dev_disconnect callback, if the device was already registered. - * - * Usually called from snd_card_disconnect(). - * - * Returns zero if successful, or a negative error code on failure or if the - * device not found. - */ -int snd_device_disconnect(struct snd_card *card, void *device_data) -{ - struct snd_device *dev; - - if (snd_BUG_ON(!card || !device_data)) - return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (dev->device_data != device_data) - continue; - if (dev->state == SNDRV_DEV_REGISTERED && - dev->ops->dev_disconnect) { - if (dev->ops->dev_disconnect(dev)) - snd_printk(KERN_ERR "device disconnect failure\n"); - dev->state = SNDRV_DEV_DISCONNECTED; - } - return 0; - } - snd_printd("device disconnect %p (from %pF), not found\n", device_data, - __builtin_return_address(0)); - return -ENXIO; -} - -/** - * snd_device_register - register the device - * @card: the card instance - * @device_data: the data pointer to register - * - * Registers the device which was already created via - * snd_device_new(). Usually this is called from snd_card_register(), - * but it can be called later if any new devices are created after - * invocation of snd_card_register(). - * - * Returns zero if successful, or a negative error code on failure or if the - * device not found. - */ -int snd_device_register(struct snd_card *card, void *device_data) -{ - struct snd_device *dev; - int err; - - if (snd_BUG_ON(!card || !device_data)) - return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (dev->device_data != device_data) - continue; - if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { - if ((err = dev->ops->dev_register(dev)) < 0) - return err; - dev->state = SNDRV_DEV_REGISTERED; - return 0; - } - snd_printd("snd_device_register busy\n"); - return -EBUSY; - } - snd_BUG(); - return -ENXIO; -} - -EXPORT_SYMBOL(snd_device_register); - -/* - * register all the devices on the card. - * called from init.c - */ -int snd_device_register_all(struct snd_card *card) -{ - struct snd_device *dev; - int err; - - if (snd_BUG_ON(!card)) - return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { - if ((err = dev->ops->dev_register(dev)) < 0) - return err; - dev->state = SNDRV_DEV_REGISTERED; - } - } - return 0; -} - -/* - * disconnect all the devices on the card. - * called from init.c - */ -int snd_device_disconnect_all(struct snd_card *card) -{ - struct snd_device *dev; - int err = 0; - - if (snd_BUG_ON(!card)) - return -ENXIO; - list_for_each_entry(dev, &card->devices, list) { - if (snd_device_disconnect(card, dev->device_data) < 0) - err = -ENXIO; - } - return err; -} - -/* - * release all the devices on the card. - * called from init.c - */ -int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd) -{ - struct snd_device *dev; - int err; - unsigned int range_low, range_high, type; - - if (snd_BUG_ON(!card)) - return -ENXIO; - range_low = (__force unsigned int)cmd * SNDRV_DEV_TYPE_RANGE_SIZE; - range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1; - __again: - list_for_each_entry(dev, &card->devices, list) { - type = (__force unsigned int)dev->type; - if (type >= range_low && type <= range_high) { - if ((err = snd_device_free(card, dev->device_data)) < 0) - return err; - goto __again; - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/hrtimer.c b/ANDROID_3.4.5/sound/core/hrtimer.c deleted file mode 100644 index b8b31c43..00000000 --- a/ANDROID_3.4.5/sound/core/hrtimer.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * ALSA timer back-end using hrtimer - * Copyright (C) 2008 Takashi Iwai - * - * 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 - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("ALSA hrtimer backend"); -MODULE_LICENSE("GPL"); - -MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_HRTIMER)); - -#define NANO_SEC 1000000000UL /* 10^9 in sec */ -static unsigned int resolution; - -struct snd_hrtimer { - struct snd_timer *timer; - struct hrtimer hrt; - atomic_t running; -}; - -static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) -{ - struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt); - struct snd_timer *t = stime->timer; - unsigned long oruns; - - if (!atomic_read(&stime->running)) - return HRTIMER_NORESTART; - - oruns = hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); - snd_timer_interrupt(stime->timer, t->sticks * oruns); - - if (!atomic_read(&stime->running)) - return HRTIMER_NORESTART; - return HRTIMER_RESTART; -} - -static int snd_hrtimer_open(struct snd_timer *t) -{ - struct snd_hrtimer *stime; - - stime = kmalloc(sizeof(*stime), GFP_KERNEL); - if (!stime) - return -ENOMEM; - hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - stime->timer = t; - stime->hrt.function = snd_hrtimer_callback; - atomic_set(&stime->running, 0); - t->private_data = stime; - return 0; -} - -static int snd_hrtimer_close(struct snd_timer *t) -{ - struct snd_hrtimer *stime = t->private_data; - - if (stime) { - hrtimer_cancel(&stime->hrt); - kfree(stime); - t->private_data = NULL; - } - return 0; -} - -static int snd_hrtimer_start(struct snd_timer *t) -{ - struct snd_hrtimer *stime = t->private_data; - - atomic_set(&stime->running, 0); - hrtimer_cancel(&stime->hrt); - hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), - HRTIMER_MODE_REL); - atomic_set(&stime->running, 1); - return 0; -} - -static int snd_hrtimer_stop(struct snd_timer *t) -{ - struct snd_hrtimer *stime = t->private_data; - atomic_set(&stime->running, 0); - return 0; -} - -static struct snd_timer_hardware hrtimer_hw = { - .flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_TASKLET, - .open = snd_hrtimer_open, - .close = snd_hrtimer_close, - .start = snd_hrtimer_start, - .stop = snd_hrtimer_stop, -}; - -/* - * entry functions - */ - -static struct snd_timer *mytimer; - -static int __init snd_hrtimer_init(void) -{ - struct snd_timer *timer; - struct timespec tp; - int err; - - hrtimer_get_res(CLOCK_MONOTONIC, &tp); - if (tp.tv_sec > 0 || !tp.tv_nsec) { - snd_printk(KERN_ERR - "snd-hrtimer: Invalid resolution %u.%09u", - (unsigned)tp.tv_sec, (unsigned)tp.tv_nsec); - return -EINVAL; - } - resolution = tp.tv_nsec; - - /* Create a new timer and set up the fields */ - err = snd_timer_global_new("hrtimer", SNDRV_TIMER_GLOBAL_HRTIMER, - &timer); - if (err < 0) - return err; - - timer->module = THIS_MODULE; - strcpy(timer->name, "HR timer"); - timer->hw = hrtimer_hw; - timer->hw.resolution = resolution; - timer->hw.ticks = NANO_SEC / resolution; - - err = snd_timer_global_register(timer); - if (err < 0) { - snd_timer_global_free(timer); - return err; - } - mytimer = timer; /* remember this */ - - return 0; -} - -static void __exit snd_hrtimer_exit(void) -{ - if (mytimer) { - snd_timer_global_free(mytimer); - mytimer = NULL; - } -} - -module_init(snd_hrtimer_init); -module_exit(snd_hrtimer_exit); diff --git a/ANDROID_3.4.5/sound/core/hwdep.c b/ANDROID_3.4.5/sound/core/hwdep.c deleted file mode 100644 index 3f7f6628..00000000 --- a/ANDROID_3.4.5/sound/core/hwdep.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Hardware dependent layer - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Hardware dependent layer"); -MODULE_LICENSE("GPL"); - -static LIST_HEAD(snd_hwdep_devices); -static DEFINE_MUTEX(register_mutex); - -static int snd_hwdep_free(struct snd_hwdep *hwdep); -static int snd_hwdep_dev_free(struct snd_device *device); -static int snd_hwdep_dev_register(struct snd_device *device); -static int snd_hwdep_dev_disconnect(struct snd_device *device); - - -static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device) -{ - struct snd_hwdep *hwdep; - - list_for_each_entry(hwdep, &snd_hwdep_devices, list) - if (hwdep->card == card && hwdep->device == device) - return hwdep; - return NULL; -} - -static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig) -{ - struct snd_hwdep *hw = file->private_data; - if (hw->ops.llseek) - return hw->ops.llseek(hw, file, offset, orig); - return -ENXIO; -} - -static ssize_t snd_hwdep_read(struct file * file, char __user *buf, - size_t count, loff_t *offset) -{ - struct snd_hwdep *hw = file->private_data; - if (hw->ops.read) - return hw->ops.read(hw, buf, count, offset); - return -ENXIO; -} - -static ssize_t snd_hwdep_write(struct file * file, const char __user *buf, - size_t count, loff_t *offset) -{ - struct snd_hwdep *hw = file->private_data; - if (hw->ops.write) - return hw->ops.write(hw, buf, count, offset); - return -ENXIO; -} - -static int snd_hwdep_open(struct inode *inode, struct file * file) -{ - int major = imajor(inode); - struct snd_hwdep *hw; - int err; - wait_queue_t wait; - - if (major == snd_major) { - hw = snd_lookup_minor_data(iminor(inode), - SNDRV_DEVICE_TYPE_HWDEP); -#ifdef CONFIG_SND_OSSEMUL - } else if (major == SOUND_MAJOR) { - hw = snd_lookup_oss_minor_data(iminor(inode), - SNDRV_OSS_DEVICE_TYPE_DMFM); -#endif - } else - return -ENXIO; - if (hw == NULL) - return -ENODEV; - - if (!try_module_get(hw->card->module)) { - snd_card_unref(hw->card); - return -EFAULT; - } - - init_waitqueue_entry(&wait, current); - add_wait_queue(&hw->open_wait, &wait); - mutex_lock(&hw->open_mutex); - while (1) { - if (hw->exclusive && hw->used > 0) { - err = -EBUSY; - break; - } - if (!hw->ops.open) { - err = 0; - break; - } - err = hw->ops.open(hw, file); - if (err >= 0) - break; - if (err == -EAGAIN) { - if (file->f_flags & O_NONBLOCK) { - err = -EBUSY; - break; - } - } else - break; - set_current_state(TASK_INTERRUPTIBLE); - mutex_unlock(&hw->open_mutex); - schedule(); - mutex_lock(&hw->open_mutex); - if (hw->card->shutdown) { - err = -ENODEV; - break; - } - if (signal_pending(current)) { - err = -ERESTARTSYS; - break; - } - } - remove_wait_queue(&hw->open_wait, &wait); - if (err >= 0) { - err = snd_card_file_add(hw->card, file); - if (err >= 0) { - file->private_data = hw; - hw->used++; - } else { - if (hw->ops.release) - hw->ops.release(hw, file); - } - } - mutex_unlock(&hw->open_mutex); - if (err < 0) - module_put(hw->card->module); - snd_card_unref(hw->card); - return err; -} - -static int snd_hwdep_release(struct inode *inode, struct file * file) -{ - int err = 0; - struct snd_hwdep *hw = file->private_data; - struct module *mod = hw->card->module; - - mutex_lock(&hw->open_mutex); - if (hw->ops.release) - err = hw->ops.release(hw, file); - if (hw->used > 0) - hw->used--; - mutex_unlock(&hw->open_mutex); - wake_up(&hw->open_wait); - - snd_card_file_remove(hw->card, file); - module_put(mod); - return err; -} - -static unsigned int snd_hwdep_poll(struct file * file, poll_table * wait) -{ - struct snd_hwdep *hw = file->private_data; - if (hw->ops.poll) - return hw->ops.poll(hw, file, wait); - return 0; -} - -static int snd_hwdep_info(struct snd_hwdep *hw, - struct snd_hwdep_info __user *_info) -{ - struct snd_hwdep_info info; - - memset(&info, 0, sizeof(info)); - info.card = hw->card->number; - strlcpy(info.id, hw->id, sizeof(info.id)); - strlcpy(info.name, hw->name, sizeof(info.name)); - info.iface = hw->iface; - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int snd_hwdep_dsp_status(struct snd_hwdep *hw, - struct snd_hwdep_dsp_status __user *_info) -{ - struct snd_hwdep_dsp_status info; - int err; - - if (! hw->ops.dsp_status) - return -ENXIO; - memset(&info, 0, sizeof(info)); - info.dsp_loaded = hw->dsp_loaded; - if ((err = hw->ops.dsp_status(hw, &info)) < 0) - return err; - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int snd_hwdep_dsp_load(struct snd_hwdep *hw, - struct snd_hwdep_dsp_image __user *_info) -{ - struct snd_hwdep_dsp_image info; - int err; - - if (! hw->ops.dsp_load) - return -ENXIO; - memset(&info, 0, sizeof(info)); - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - /* check whether the dsp was already loaded */ - if (hw->dsp_loaded & (1 << info.index)) - return -EBUSY; - if (!access_ok(VERIFY_READ, info.image, info.length)) - return -EFAULT; - err = hw->ops.dsp_load(hw, &info); - if (err < 0) - return err; - hw->dsp_loaded |= (1 << info.index); - return 0; -} - -static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, - unsigned long arg) -{ - struct snd_hwdep *hw = file->private_data; - void __user *argp = (void __user *)arg; - switch (cmd) { - case SNDRV_HWDEP_IOCTL_PVERSION: - return put_user(SNDRV_HWDEP_VERSION, (int __user *)argp); - case SNDRV_HWDEP_IOCTL_INFO: - return snd_hwdep_info(hw, argp); - case SNDRV_HWDEP_IOCTL_DSP_STATUS: - return snd_hwdep_dsp_status(hw, argp); - case SNDRV_HWDEP_IOCTL_DSP_LOAD: - return snd_hwdep_dsp_load(hw, argp); - } - if (hw->ops.ioctl) - return hw->ops.ioctl(hw, file, cmd, arg); - return -ENOTTY; -} - -static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma) -{ - struct snd_hwdep *hw = file->private_data; - if (hw->ops.mmap) - return hw->ops.mmap(hw, file, vma); - return -ENXIO; -} - -static int snd_hwdep_control_ioctl(struct snd_card *card, - struct snd_ctl_file * control, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE: - { - int device; - - if (get_user(device, (int __user *)arg)) - return -EFAULT; - mutex_lock(®ister_mutex); - - if (device < 0) - device = 0; - else if (device < SNDRV_MINOR_HWDEPS) - device++; - else - device = SNDRV_MINOR_HWDEPS; - - while (device < SNDRV_MINOR_HWDEPS) { - if (snd_hwdep_search(card, device)) - break; - device++; - } - if (device >= SNDRV_MINOR_HWDEPS) - device = -1; - mutex_unlock(®ister_mutex); - if (put_user(device, (int __user *)arg)) - return -EFAULT; - return 0; - } - case SNDRV_CTL_IOCTL_HWDEP_INFO: - { - struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg; - int device, err; - struct snd_hwdep *hwdep; - - if (get_user(device, &info->device)) - return -EFAULT; - mutex_lock(®ister_mutex); - hwdep = snd_hwdep_search(card, device); - if (hwdep) - err = snd_hwdep_info(hwdep, info); - else - err = -ENXIO; - mutex_unlock(®ister_mutex); - return err; - } - } - return -ENOIOCTLCMD; -} - -#ifdef CONFIG_COMPAT -#include "hwdep_compat.c" -#else -#define snd_hwdep_ioctl_compat NULL -#endif - -/* - - */ - -static const struct file_operations snd_hwdep_f_ops = -{ - .owner = THIS_MODULE, - .llseek = snd_hwdep_llseek, - .read = snd_hwdep_read, - .write = snd_hwdep_write, - .open = snd_hwdep_open, - .release = snd_hwdep_release, - .poll = snd_hwdep_poll, - .unlocked_ioctl = snd_hwdep_ioctl, - .compat_ioctl = snd_hwdep_ioctl_compat, - .mmap = snd_hwdep_mmap, -}; - -/** - * snd_hwdep_new - create a new hwdep instance - * @card: the card instance - * @id: the id string - * @device: the device index (zero-based) - * @rhwdep: the pointer to store the new hwdep instance - * - * Creates a new hwdep instance with the given index on the card. - * The callbacks (hwdep->ops) must be set on the returned instance - * after this call manually by the caller. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_hwdep_new(struct snd_card *card, char *id, int device, - struct snd_hwdep **rhwdep) -{ - struct snd_hwdep *hwdep; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_hwdep_dev_free, - .dev_register = snd_hwdep_dev_register, - .dev_disconnect = snd_hwdep_dev_disconnect, - }; - - if (snd_BUG_ON(!card)) - return -ENXIO; - if (rhwdep) - *rhwdep = NULL; - hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL); - if (hwdep == NULL) { - snd_printk(KERN_ERR "hwdep: cannot allocate\n"); - return -ENOMEM; - } - hwdep->card = card; - hwdep->device = device; - if (id) - strlcpy(hwdep->id, id, sizeof(hwdep->id)); -#ifdef CONFIG_SND_OSSEMUL - hwdep->oss_type = -1; -#endif - if ((err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops)) < 0) { - snd_hwdep_free(hwdep); - return err; - } - init_waitqueue_head(&hwdep->open_wait); - mutex_init(&hwdep->open_mutex); - if (rhwdep) - *rhwdep = hwdep; - return 0; -} - -static int snd_hwdep_free(struct snd_hwdep *hwdep) -{ - if (!hwdep) - return 0; - if (hwdep->private_free) - hwdep->private_free(hwdep); - kfree(hwdep); - return 0; -} - -static int snd_hwdep_dev_free(struct snd_device *device) -{ - struct snd_hwdep *hwdep = device->device_data; - return snd_hwdep_free(hwdep); -} - -static int snd_hwdep_dev_register(struct snd_device *device) -{ - struct snd_hwdep *hwdep = device->device_data; - int err; - char name[32]; - - mutex_lock(®ister_mutex); - if (snd_hwdep_search(hwdep->card, hwdep->device)) { - mutex_unlock(®ister_mutex); - return -EBUSY; - } - list_add_tail(&hwdep->list, &snd_hwdep_devices); - sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, - hwdep->card, hwdep->device, - &snd_hwdep_f_ops, hwdep, name)) < 0) { - snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", - hwdep->card->number, hwdep->device); - list_del(&hwdep->list); - mutex_unlock(®ister_mutex); - return err; - } -#ifdef CONFIG_SND_OSSEMUL - hwdep->ossreg = 0; - if (hwdep->oss_type >= 0) { - if ((hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM) && (hwdep->device != 0)) { - snd_printk (KERN_WARNING "only hwdep device 0 can be registered as OSS direct FM device!\n"); - } else { - if (snd_register_oss_device(hwdep->oss_type, - hwdep->card, hwdep->device, - &snd_hwdep_f_ops, hwdep, - hwdep->oss_dev) < 0) { - snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n", - hwdep->card->number, hwdep->device); - } else - hwdep->ossreg = 1; - } - } -#endif - mutex_unlock(®ister_mutex); - return 0; -} - -static int snd_hwdep_dev_disconnect(struct snd_device *device) -{ - struct snd_hwdep *hwdep = device->device_data; - - if (snd_BUG_ON(!hwdep)) - return -ENXIO; - mutex_lock(®ister_mutex); - if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) { - mutex_unlock(®ister_mutex); - return -EINVAL; - } - mutex_lock(&hwdep->open_mutex); - wake_up(&hwdep->open_wait); -#ifdef CONFIG_SND_OSSEMUL - if (hwdep->ossreg) - snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); -#endif - snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); - list_del_init(&hwdep->list); - mutex_unlock(&hwdep->open_mutex); - mutex_unlock(®ister_mutex); - return 0; -} - -#ifdef CONFIG_PROC_FS -/* - * Info interface - */ - -static void snd_hwdep_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_hwdep *hwdep; - - mutex_lock(®ister_mutex); - list_for_each_entry(hwdep, &snd_hwdep_devices, list) - snd_iprintf(buffer, "%02i-%02i: %s\n", - hwdep->card->number, hwdep->device, hwdep->name); - mutex_unlock(®ister_mutex); -} - -static struct snd_info_entry *snd_hwdep_proc_entry; - -static void __init snd_hwdep_proc_init(void) -{ - struct snd_info_entry *entry; - - if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { - entry->c.text.read = snd_hwdep_proc_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_hwdep_proc_entry = entry; -} - -static void __exit snd_hwdep_proc_done(void) -{ - snd_info_free_entry(snd_hwdep_proc_entry); -} -#else /* !CONFIG_PROC_FS */ -#define snd_hwdep_proc_init() -#define snd_hwdep_proc_done() -#endif /* CONFIG_PROC_FS */ - - -/* - * ENTRY functions - */ - -static int __init alsa_hwdep_init(void) -{ - snd_hwdep_proc_init(); - snd_ctl_register_ioctl(snd_hwdep_control_ioctl); - snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl); - return 0; -} - -static void __exit alsa_hwdep_exit(void) -{ - snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl); - snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl); - snd_hwdep_proc_done(); -} - -module_init(alsa_hwdep_init) -module_exit(alsa_hwdep_exit) - -EXPORT_SYMBOL(snd_hwdep_new); diff --git a/ANDROID_3.4.5/sound/core/hwdep_compat.c b/ANDROID_3.4.5/sound/core/hwdep_compat.c deleted file mode 100644 index 3827c0ce..00000000 --- a/ANDROID_3.4.5/sound/core/hwdep_compat.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for hwdep API - * Copyright (c) by Takashi Iwai - * - * 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 - * - */ - -/* This file is included from hwdep.c */ - -#include - -struct snd_hwdep_dsp_image32 { - u32 index; - unsigned char name[64]; - u32 image; /* pointer */ - u32 length; - u32 driver_data; -} /* don't set packed attribute here */; - -static int snd_hwdep_dsp_load_compat(struct snd_hwdep *hw, - struct snd_hwdep_dsp_image32 __user *src) -{ - struct snd_hwdep_dsp_image __user *dst; - compat_caddr_t ptr; - u32 val; - - dst = compat_alloc_user_space(sizeof(*dst)); - - /* index and name */ - if (copy_in_user(dst, src, 4 + 64)) - return -EFAULT; - if (get_user(ptr, &src->image) || - put_user(compat_ptr(ptr), &dst->image)) - return -EFAULT; - if (get_user(val, &src->length) || - put_user(val, &dst->length)) - return -EFAULT; - if (get_user(val, &src->driver_data) || - put_user(val, &dst->driver_data)) - return -EFAULT; - - return snd_hwdep_dsp_load(hw, dst); -} - -enum { - SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct snd_hwdep_dsp_image32) -}; - -static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, - unsigned long arg) -{ - struct snd_hwdep *hw = file->private_data; - void __user *argp = compat_ptr(arg); - switch (cmd) { - case SNDRV_HWDEP_IOCTL_PVERSION: - case SNDRV_HWDEP_IOCTL_INFO: - case SNDRV_HWDEP_IOCTL_DSP_STATUS: - return snd_hwdep_ioctl(file, cmd, (unsigned long)argp); - case SNDRV_HWDEP_IOCTL_DSP_LOAD32: - return snd_hwdep_dsp_load_compat(hw, argp); - } - if (hw->ops.ioctl_compat) - return hw->ops.ioctl_compat(hw, file, cmd, arg); - return -ENOIOCTLCMD; -} diff --git a/ANDROID_3.4.5/sound/core/info.c b/ANDROID_3.4.5/sound/core/info.c deleted file mode 100644 index c1e611c6..00000000 --- a/ANDROID_3.4.5/sound/core/info.c +++ /dev/null @@ -1,1016 +0,0 @@ -/* - * Information interface for ALSA driver - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#include - -/* - * - */ - -#ifdef CONFIG_PROC_FS - -int snd_info_check_reserved_words(const char *str) -{ - static char *reserved[] = - { - "version", - "meminfo", - "memdebug", - "detect", - "devices", - "oss", - "cards", - "timers", - "synth", - "pcm", - "seq", - NULL - }; - char **xstr = reserved; - - while (*xstr) { - if (!strcmp(*xstr, str)) - return 0; - xstr++; - } - if (!strncmp(str, "card", 4)) - return 0; - return 1; -} - -static DEFINE_MUTEX(info_mutex); - -struct snd_info_private_data { - struct snd_info_buffer *rbuffer; - struct snd_info_buffer *wbuffer; - struct snd_info_entry *entry; - void *file_private_data; -}; - -static int snd_info_version_init(void); -static int snd_info_version_done(void); -static void snd_info_disconnect(struct snd_info_entry *entry); - - -/* resize the proc r/w buffer */ -static int resize_info_buffer(struct snd_info_buffer *buffer, - unsigned int nsize) -{ - char *nbuf; - - nsize = PAGE_ALIGN(nsize); - nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL); - if (! nbuf) - return -ENOMEM; - - buffer->buffer = nbuf; - buffer->len = nsize; - return 0; -} - -/** - * snd_iprintf - printf on the procfs buffer - * @buffer: the procfs buffer - * @fmt: the printf format - * - * Outputs the string on the procfs buffer just like printf(). - * - * Returns the size of output string. - */ -int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...) -{ - va_list args; - int len, res; - int err = 0; - - might_sleep(); - if (buffer->stop || buffer->error) - return 0; - len = buffer->len - buffer->size; - va_start(args, fmt); - for (;;) { - va_list ap; - va_copy(ap, args); - res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, ap); - va_end(ap); - if (res < len) - break; - err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); - if (err < 0) - break; - len = buffer->len - buffer->size; - } - va_end(args); - - if (err < 0) - return err; - buffer->curr += res; - buffer->size += res; - return res; -} - -EXPORT_SYMBOL(snd_iprintf); - -/* - - */ - -static struct proc_dir_entry *snd_proc_root; -struct snd_info_entry *snd_seq_root; -EXPORT_SYMBOL(snd_seq_root); - -#ifdef CONFIG_SND_OSSEMUL -struct snd_info_entry *snd_oss_root; -#endif - -static void snd_remove_proc_entry(struct proc_dir_entry *parent, - struct proc_dir_entry *de) -{ - if (de) - remove_proc_entry(de->name, parent); -} - -static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) -{ - struct snd_info_private_data *data; - struct snd_info_entry *entry; - loff_t ret = -EINVAL, size; - - data = file->private_data; - entry = data->entry; - mutex_lock(&entry->access); - if (entry->content == SNDRV_INFO_CONTENT_DATA && - entry->c.ops->llseek) { - offset = entry->c.ops->llseek(entry, - data->file_private_data, - file, offset, orig); - goto out; - } - if (entry->content == SNDRV_INFO_CONTENT_DATA) - size = entry->size; - else - size = 0; - switch (orig) { - case SEEK_SET: - break; - case SEEK_CUR: - offset += file->f_pos; - break; - case SEEK_END: - if (!size) - goto out; - offset += size; - break; - default: - goto out; - } - if (offset < 0) - goto out; - if (size && offset > size) - offset = size; - file->f_pos = offset; - ret = offset; - out: - mutex_unlock(&entry->access); - return ret; -} - -static ssize_t snd_info_entry_read(struct file *file, char __user *buffer, - size_t count, loff_t * offset) -{ - struct snd_info_private_data *data; - struct snd_info_entry *entry; - struct snd_info_buffer *buf; - size_t size = 0; - loff_t pos; - - data = file->private_data; - if (snd_BUG_ON(!data)) - return -ENXIO; - pos = *offset; - if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) - return -EIO; - if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) - return -EIO; - entry = data->entry; - switch (entry->content) { - case SNDRV_INFO_CONTENT_TEXT: - buf = data->rbuffer; - if (buf == NULL) - return -EIO; - if (pos >= buf->size) - return 0; - size = buf->size - pos; - size = min(count, size); - if (copy_to_user(buffer, buf->buffer + pos, size)) - return -EFAULT; - break; - case SNDRV_INFO_CONTENT_DATA: - if (pos >= entry->size) - return 0; - if (entry->c.ops->read) { - size = entry->size - pos; - size = min(count, size); - size = entry->c.ops->read(entry, - data->file_private_data, - file, buffer, size, pos); - } - break; - } - if ((ssize_t) size > 0) - *offset = pos + size; - return size; -} - -static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer, - size_t count, loff_t * offset) -{ - struct snd_info_private_data *data; - struct snd_info_entry *entry; - struct snd_info_buffer *buf; - ssize_t size = 0; - loff_t pos; - - data = file->private_data; - if (snd_BUG_ON(!data)) - return -ENXIO; - entry = data->entry; - pos = *offset; - if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) - return -EIO; - if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) - return -EIO; - switch (entry->content) { - case SNDRV_INFO_CONTENT_TEXT: - buf = data->wbuffer; - if (buf == NULL) - return -EIO; - mutex_lock(&entry->access); - if (pos + count >= buf->len) { - if (resize_info_buffer(buf, pos + count)) { - mutex_unlock(&entry->access); - return -ENOMEM; - } - } - if (copy_from_user(buf->buffer + pos, buffer, count)) { - mutex_unlock(&entry->access); - return -EFAULT; - } - buf->size = pos + count; - mutex_unlock(&entry->access); - size = count; - break; - case SNDRV_INFO_CONTENT_DATA: - if (entry->c.ops->write && count > 0) { - size_t maxsize = entry->size - pos; - count = min(count, maxsize); - size = entry->c.ops->write(entry, - data->file_private_data, - file, buffer, count, pos); - } - break; - } - if ((ssize_t) size > 0) - *offset = pos + size; - return size; -} - -static int snd_info_entry_open(struct inode *inode, struct file *file) -{ - struct snd_info_entry *entry; - struct snd_info_private_data *data; - struct snd_info_buffer *buffer; - struct proc_dir_entry *p; - int mode, err; - - mutex_lock(&info_mutex); - p = PDE(inode); - entry = p == NULL ? NULL : (struct snd_info_entry *)p->data; - if (entry == NULL || ! entry->p) { - mutex_unlock(&info_mutex); - return -ENODEV; - } - if (!try_module_get(entry->module)) { - err = -EFAULT; - goto __error1; - } - mode = file->f_flags & O_ACCMODE; - if (mode == O_RDONLY || mode == O_RDWR) { - if ((entry->content == SNDRV_INFO_CONTENT_DATA && - entry->c.ops->read == NULL)) { - err = -ENODEV; - goto __error; - } - } - if (mode == O_WRONLY || mode == O_RDWR) { - if ((entry->content == SNDRV_INFO_CONTENT_DATA && - entry->c.ops->write == NULL)) { - err = -ENODEV; - goto __error; - } - } - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) { - err = -ENOMEM; - goto __error; - } - data->entry = entry; - switch (entry->content) { - case SNDRV_INFO_CONTENT_TEXT: - if (mode == O_RDONLY || mode == O_RDWR) { - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (buffer == NULL) - goto __nomem; - data->rbuffer = buffer; - buffer->len = PAGE_SIZE; - buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); - if (buffer->buffer == NULL) - goto __nomem; - } - if (mode == O_WRONLY || mode == O_RDWR) { - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - if (buffer == NULL) - goto __nomem; - data->wbuffer = buffer; - buffer->len = PAGE_SIZE; - buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); - if (buffer->buffer == NULL) - goto __nomem; - } - break; - case SNDRV_INFO_CONTENT_DATA: /* data */ - if (entry->c.ops->open) { - if ((err = entry->c.ops->open(entry, mode, - &data->file_private_data)) < 0) { - kfree(data); - goto __error; - } - } - break; - } - file->private_data = data; - mutex_unlock(&info_mutex); - if (entry->content == SNDRV_INFO_CONTENT_TEXT && - (mode == O_RDONLY || mode == O_RDWR)) { - if (entry->c.text.read) { - mutex_lock(&entry->access); - entry->c.text.read(entry, data->rbuffer); - mutex_unlock(&entry->access); - } - } - return 0; - - __nomem: - if (data->rbuffer) { - kfree(data->rbuffer->buffer); - kfree(data->rbuffer); - } - if (data->wbuffer) { - kfree(data->wbuffer->buffer); - kfree(data->wbuffer); - } - kfree(data); - err = -ENOMEM; - __error: - module_put(entry->module); - __error1: - mutex_unlock(&info_mutex); - return err; -} - -static int snd_info_entry_release(struct inode *inode, struct file *file) -{ - struct snd_info_entry *entry; - struct snd_info_private_data *data; - int mode; - - mode = file->f_flags & O_ACCMODE; - data = file->private_data; - entry = data->entry; - switch (entry->content) { - case SNDRV_INFO_CONTENT_TEXT: - if (data->rbuffer) { - kfree(data->rbuffer->buffer); - kfree(data->rbuffer); - } - if (data->wbuffer) { - if (entry->c.text.write) { - entry->c.text.write(entry, data->wbuffer); - if (data->wbuffer->error) { - snd_printk(KERN_WARNING "data write error to %s (%i)\n", - entry->name, - data->wbuffer->error); - } - } - kfree(data->wbuffer->buffer); - kfree(data->wbuffer); - } - break; - case SNDRV_INFO_CONTENT_DATA: - if (entry->c.ops->release) - entry->c.ops->release(entry, mode, - data->file_private_data); - break; - } - module_put(entry->module); - kfree(data); - return 0; -} - -static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait) -{ - struct snd_info_private_data *data; - struct snd_info_entry *entry; - unsigned int mask; - - data = file->private_data; - if (data == NULL) - return 0; - entry = data->entry; - mask = 0; - switch (entry->content) { - case SNDRV_INFO_CONTENT_DATA: - if (entry->c.ops->poll) - return entry->c.ops->poll(entry, - data->file_private_data, - file, wait); - if (entry->c.ops->read) - mask |= POLLIN | POLLRDNORM; - if (entry->c.ops->write) - mask |= POLLOUT | POLLWRNORM; - break; - } - return mask; -} - -static long snd_info_entry_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct snd_info_private_data *data; - struct snd_info_entry *entry; - - data = file->private_data; - if (data == NULL) - return 0; - entry = data->entry; - switch (entry->content) { - case SNDRV_INFO_CONTENT_DATA: - if (entry->c.ops->ioctl) - return entry->c.ops->ioctl(entry, - data->file_private_data, - file, cmd, arg); - break; - } - return -ENOTTY; -} - -static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct inode *inode = file->f_path.dentry->d_inode; - struct snd_info_private_data *data; - struct snd_info_entry *entry; - - data = file->private_data; - if (data == NULL) - return 0; - entry = data->entry; - switch (entry->content) { - case SNDRV_INFO_CONTENT_DATA: - if (entry->c.ops->mmap) - return entry->c.ops->mmap(entry, - data->file_private_data, - inode, file, vma); - break; - } - return -ENXIO; -} - -static const struct file_operations snd_info_entry_operations = -{ - .owner = THIS_MODULE, - .llseek = snd_info_entry_llseek, - .read = snd_info_entry_read, - .write = snd_info_entry_write, - .poll = snd_info_entry_poll, - .unlocked_ioctl = snd_info_entry_ioctl, - .mmap = snd_info_entry_mmap, - .open = snd_info_entry_open, - .release = snd_info_entry_release, -}; - -int __init snd_info_init(void) -{ - struct proc_dir_entry *p; - - p = proc_mkdir("asound", NULL); - if (p == NULL) - return -ENOMEM; - snd_proc_root = p; -#ifdef CONFIG_SND_OSSEMUL - { - struct snd_info_entry *entry; - if ((entry = snd_info_create_module_entry(THIS_MODULE, "oss", NULL)) == NULL) - return -ENOMEM; - entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } - snd_oss_root = entry; - } -#endif -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) - { - struct snd_info_entry *entry; - if ((entry = snd_info_create_module_entry(THIS_MODULE, "seq", NULL)) == NULL) - return -ENOMEM; - entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } - snd_seq_root = entry; - } -#endif - snd_info_version_init(); - snd_minor_info_init(); - snd_minor_info_oss_init(); - snd_card_info_init(); - return 0; -} - -int __exit snd_info_done(void) -{ - snd_card_info_done(); - snd_minor_info_oss_done(); - snd_minor_info_done(); - snd_info_version_done(); - if (snd_proc_root) { -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) - snd_info_free_entry(snd_seq_root); -#endif -#ifdef CONFIG_SND_OSSEMUL - snd_info_free_entry(snd_oss_root); -#endif - snd_remove_proc_entry(NULL, snd_proc_root); - } - return 0; -} - -/* - - */ - - -/* - * create a card proc file - * called from init.c - */ -int snd_info_card_create(struct snd_card *card) -{ - char str[8]; - struct snd_info_entry *entry; - - if (snd_BUG_ON(!card)) - return -ENXIO; - - sprintf(str, "card%i", card->number); - if ((entry = snd_info_create_module_entry(card->module, str, NULL)) == NULL) - return -ENOMEM; - entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } - card->proc_root = entry; - return 0; -} - -/* - * register the card proc file - * called from init.c - */ -int snd_info_card_register(struct snd_card *card) -{ - struct proc_dir_entry *p; - - if (snd_BUG_ON(!card)) - return -ENXIO; - - if (!strcmp(card->id, card->proc_root->name)) - return 0; - - p = proc_symlink(card->id, snd_proc_root, card->proc_root->name); - if (p == NULL) - return -ENOMEM; - card->proc_root_link = p; - return 0; -} - -/* - * called on card->id change - */ -void snd_info_card_id_change(struct snd_card *card) -{ - mutex_lock(&info_mutex); - if (card->proc_root_link) { - snd_remove_proc_entry(snd_proc_root, card->proc_root_link); - card->proc_root_link = NULL; - } - if (strcmp(card->id, card->proc_root->name)) - card->proc_root_link = proc_symlink(card->id, - snd_proc_root, - card->proc_root->name); - mutex_unlock(&info_mutex); -} - -/* - * de-register the card proc file - * called from init.c - */ -void snd_info_card_disconnect(struct snd_card *card) -{ - if (!card) - return; - mutex_lock(&info_mutex); - if (card->proc_root_link) { - snd_remove_proc_entry(snd_proc_root, card->proc_root_link); - card->proc_root_link = NULL; - } - if (card->proc_root) - snd_info_disconnect(card->proc_root); - mutex_unlock(&info_mutex); -} - -/* - * release the card proc file resources - * called from init.c - */ -int snd_info_card_free(struct snd_card *card) -{ - if (!card) - return 0; - snd_info_free_entry(card->proc_root); - card->proc_root = NULL; - return 0; -} - - -/** - * snd_info_get_line - read one line from the procfs buffer - * @buffer: the procfs buffer - * @line: the buffer to store - * @len: the max. buffer size - 1 - * - * Reads one line from the buffer and stores the string. - * - * Returns zero if successful, or 1 if error or EOF. - */ -int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) -{ - int c = -1; - - if (len <= 0 || buffer->stop || buffer->error) - return 1; - while (--len > 0) { - c = buffer->buffer[buffer->curr++]; - if (c == '\n') { - if (buffer->curr >= buffer->size) - buffer->stop = 1; - break; - } - *line++ = c; - if (buffer->curr >= buffer->size) { - buffer->stop = 1; - break; - } - } - while (c != '\n' && !buffer->stop) { - c = buffer->buffer[buffer->curr++]; - if (buffer->curr >= buffer->size) - buffer->stop = 1; - } - *line = '\0'; - return 0; -} - -EXPORT_SYMBOL(snd_info_get_line); - -/** - * snd_info_get_str - parse a string token - * @dest: the buffer to store the string token - * @src: the original string - * @len: the max. length of token - 1 - * - * Parses the original string and copy a token to the given - * string buffer. - * - * Returns the updated pointer of the original string so that - * it can be used for the next call. - */ -const char *snd_info_get_str(char *dest, const char *src, int len) -{ - int c; - - while (*src == ' ' || *src == '\t') - src++; - if (*src == '"' || *src == '\'') { - c = *src++; - while (--len > 0 && *src && *src != c) { - *dest++ = *src++; - } - if (*src == c) - src++; - } else { - while (--len > 0 && *src && *src != ' ' && *src != '\t') { - *dest++ = *src++; - } - } - *dest = 0; - while (*src == ' ' || *src == '\t') - src++; - return src; -} - -EXPORT_SYMBOL(snd_info_get_str); - -/** - * snd_info_create_entry - create an info entry - * @name: the proc file name - * - * Creates an info entry with the given file name and initializes as - * the default state. - * - * Usually called from other functions such as - * snd_info_create_card_entry(). - * - * Returns the pointer of the new instance, or NULL on failure. - */ -static struct snd_info_entry *snd_info_create_entry(const char *name) -{ - struct snd_info_entry *entry; - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (entry == NULL) - return NULL; - entry->name = kstrdup(name, GFP_KERNEL); - if (entry->name == NULL) { - kfree(entry); - return NULL; - } - entry->mode = S_IFREG | S_IRUGO; - entry->content = SNDRV_INFO_CONTENT_TEXT; - mutex_init(&entry->access); - INIT_LIST_HEAD(&entry->children); - INIT_LIST_HEAD(&entry->list); - return entry; -} - -/** - * snd_info_create_module_entry - create an info entry for the given module - * @module: the module pointer - * @name: the file name - * @parent: the parent directory - * - * Creates a new info entry and assigns it to the given module. - * - * Returns the pointer of the new instance, or NULL on failure. - */ -struct snd_info_entry *snd_info_create_module_entry(struct module * module, - const char *name, - struct snd_info_entry *parent) -{ - struct snd_info_entry *entry = snd_info_create_entry(name); - if (entry) { - entry->module = module; - entry->parent = parent; - } - return entry; -} - -EXPORT_SYMBOL(snd_info_create_module_entry); - -/** - * snd_info_create_card_entry - create an info entry for the given card - * @card: the card instance - * @name: the file name - * @parent: the parent directory - * - * Creates a new info entry and assigns it to the given card. - * - * Returns the pointer of the new instance, or NULL on failure. - */ -struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, - const char *name, - struct snd_info_entry * parent) -{ - struct snd_info_entry *entry = snd_info_create_entry(name); - if (entry) { - entry->module = card->module; - entry->card = card; - entry->parent = parent; - } - return entry; -} - -EXPORT_SYMBOL(snd_info_create_card_entry); - -static void snd_info_disconnect(struct snd_info_entry *entry) -{ - struct list_head *p, *n; - struct proc_dir_entry *root; - - list_for_each_safe(p, n, &entry->children) { - snd_info_disconnect(list_entry(p, struct snd_info_entry, list)); - } - - if (! entry->p) - return; - list_del_init(&entry->list); - root = entry->parent == NULL ? snd_proc_root : entry->parent->p; - snd_BUG_ON(!root); - snd_remove_proc_entry(root, entry->p); - entry->p = NULL; -} - -static int snd_info_dev_free_entry(struct snd_device *device) -{ - struct snd_info_entry *entry = device->device_data; - snd_info_free_entry(entry); - return 0; -} - -static int snd_info_dev_register_entry(struct snd_device *device) -{ - struct snd_info_entry *entry = device->device_data; - return snd_info_register(entry); -} - -/** - * snd_card_proc_new - create an info entry for the given card - * @card: the card instance - * @name: the file name - * @entryp: the pointer to store the new info entry - * - * Creates a new info entry and assigns it to the given card. - * Unlike snd_info_create_card_entry(), this function registers the - * info entry as an ALSA device component, so that it can be - * unregistered/released without explicit call. - * Also, you don't have to register this entry via snd_info_register(), - * since this will be registered by snd_card_register() automatically. - * - * The parent is assumed as card->proc_root. - * - * For releasing this entry, use snd_device_free() instead of - * snd_info_free_entry(). - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_card_proc_new(struct snd_card *card, const char *name, - struct snd_info_entry **entryp) -{ - static struct snd_device_ops ops = { - .dev_free = snd_info_dev_free_entry, - .dev_register = snd_info_dev_register_entry, - /* disconnect is done via snd_info_card_disconnect() */ - }; - struct snd_info_entry *entry; - int err; - - entry = snd_info_create_card_entry(card, name, card->proc_root); - if (! entry) - return -ENOMEM; - if ((err = snd_device_new(card, SNDRV_DEV_INFO, entry, &ops)) < 0) { - snd_info_free_entry(entry); - return err; - } - if (entryp) - *entryp = entry; - return 0; -} - -EXPORT_SYMBOL(snd_card_proc_new); - -/** - * snd_info_free_entry - release the info entry - * @entry: the info entry - * - * Releases the info entry. Don't call this after registered. - */ -void snd_info_free_entry(struct snd_info_entry * entry) -{ - if (entry == NULL) - return; - if (entry->p) { - mutex_lock(&info_mutex); - snd_info_disconnect(entry); - mutex_unlock(&info_mutex); - } - kfree(entry->name); - if (entry->private_free) - entry->private_free(entry); - kfree(entry); -} - -EXPORT_SYMBOL(snd_info_free_entry); - -/** - * snd_info_register - register the info entry - * @entry: the info entry - * - * Registers the proc info entry. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_info_register(struct snd_info_entry * entry) -{ - struct proc_dir_entry *root, *p = NULL; - - if (snd_BUG_ON(!entry)) - return -ENXIO; - root = entry->parent == NULL ? snd_proc_root : entry->parent->p; - mutex_lock(&info_mutex); - p = create_proc_entry(entry->name, entry->mode, root); - if (!p) { - mutex_unlock(&info_mutex); - return -ENOMEM; - } - if (!S_ISDIR(entry->mode)) - p->proc_fops = &snd_info_entry_operations; - p->size = entry->size; - p->data = entry; - entry->p = p; - if (entry->parent) - list_add_tail(&entry->list, &entry->parent->children); - mutex_unlock(&info_mutex); - return 0; -} - -EXPORT_SYMBOL(snd_info_register); - -/* - - */ - -static struct snd_info_entry *snd_info_version_entry; - -static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - snd_iprintf(buffer, - "Advanced Linux Sound Architecture Driver Version " - CONFIG_SND_VERSION CONFIG_SND_DATE ".\n" - ); -} - -static int __init snd_info_version_init(void) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL); - if (entry == NULL) - return -ENOMEM; - entry->c.text.read = snd_info_version_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } - snd_info_version_entry = entry; - return 0; -} - -static int __exit snd_info_version_done(void) -{ - snd_info_free_entry(snd_info_version_entry); - return 0; -} - -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/core/info_oss.c b/ANDROID_3.4.5/sound/core/info_oss.c deleted file mode 100644 index cf42ab50..00000000 --- a/ANDROID_3.4.5/sound/core/info_oss.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Information interface for ALSA driver - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include - -#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) - -/* - * OSS compatible part - */ - -static DEFINE_MUTEX(strings); -static char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT]; -static struct snd_info_entry *snd_sndstat_proc_entry; - -int snd_oss_info_register(int dev, int num, char *string) -{ - char *x; - - if (snd_BUG_ON(dev < 0 || dev >= SNDRV_OSS_INFO_DEV_COUNT)) - return -ENXIO; - if (snd_BUG_ON(num < 0 || num >= SNDRV_CARDS)) - return -ENXIO; - mutex_lock(&strings); - if (string == NULL) { - if ((x = snd_sndstat_strings[num][dev]) != NULL) { - kfree(x); - x = NULL; - } - } else { - x = kstrdup(string, GFP_KERNEL); - if (x == NULL) { - mutex_unlock(&strings); - return -ENOMEM; - } - } - snd_sndstat_strings[num][dev] = x; - mutex_unlock(&strings); - return 0; -} - -EXPORT_SYMBOL(snd_oss_info_register); - -static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) -{ - int idx, ok = -1; - char *str; - - snd_iprintf(buf, "\n%s:", id); - mutex_lock(&strings); - for (idx = 0; idx < SNDRV_CARDS; idx++) { - str = snd_sndstat_strings[idx][dev]; - if (str) { - if (ok < 0) { - snd_iprintf(buf, "\n"); - ok++; - } - snd_iprintf(buf, "%i: %s\n", idx, str); - } - } - mutex_unlock(&strings); - if (ok < 0) - snd_iprintf(buf, " NOT ENABLED IN CONFIG\n"); - return ok; -} - -static void snd_sndstat_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA v" CONFIG_SND_VERSION " emulation code)\n"); - snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n", - init_utsname()->sysname, - init_utsname()->nodename, - init_utsname()->release, - init_utsname()->version, - init_utsname()->machine); - snd_iprintf(buffer, "Config options: 0\n"); - snd_iprintf(buffer, "\nInstalled drivers: \n"); - snd_iprintf(buffer, "Type 10: ALSA emulation\n"); - snd_iprintf(buffer, "\nCard config: \n"); - snd_card_info_read_oss(buffer); - snd_sndstat_show_strings(buffer, "Audio devices", SNDRV_OSS_INFO_DEV_AUDIO); - snd_sndstat_show_strings(buffer, "Synth devices", SNDRV_OSS_INFO_DEV_SYNTH); - snd_sndstat_show_strings(buffer, "Midi devices", SNDRV_OSS_INFO_DEV_MIDI); - snd_sndstat_show_strings(buffer, "Timers", SNDRV_OSS_INFO_DEV_TIMERS); - snd_sndstat_show_strings(buffer, "Mixers", SNDRV_OSS_INFO_DEV_MIXERS); -} - -int snd_info_minor_register(void) -{ - struct snd_info_entry *entry; - - memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); - if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) { - entry->c.text.read = snd_sndstat_proc_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_sndstat_proc_entry = entry; - return 0; -} - -int snd_info_minor_unregister(void) -{ - snd_info_free_entry(snd_sndstat_proc_entry); - snd_sndstat_proc_entry = NULL; - return 0; -} - -#endif /* CONFIG_SND_OSSEMUL */ diff --git a/ANDROID_3.4.5/sound/core/init.c b/ANDROID_3.4.5/sound/core/init.c deleted file mode 100644 index 7b012d15..00000000 --- a/ANDROID_3.4.5/sound/core/init.c +++ /dev/null @@ -1,991 +0,0 @@ -/* - * Initialization routines - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -#include -#include -#include - -/* monitor files for graceful shutdown (hotplug) */ -struct snd_monitor_file { - struct file *file; - const struct file_operations *disconnected_f_op; - struct list_head shutdown_list; /* still need to shutdown */ - struct list_head list; /* link of monitor files */ -}; - -static DEFINE_SPINLOCK(shutdown_lock); -static LIST_HEAD(shutdown_files); - -static const struct file_operations snd_shutdown_f_ops; - -static unsigned int snd_cards_lock; /* locked for registering/using */ -struct snd_card *snd_cards[SNDRV_CARDS]; -EXPORT_SYMBOL(snd_cards); - -static DEFINE_MUTEX(snd_card_mutex); - -static char *slots[SNDRV_CARDS]; -module_param_array(slots, charp, NULL, 0444); -MODULE_PARM_DESC(slots, "Module names assigned to the slots."); - -/* return non-zero if the given index is reserved for the given - * module via slots option - */ -static int module_slot_match(struct module *module, int idx) -{ - int match = 1; -#ifdef MODULE - const char *s1, *s2; - - if (!module || !module->name || !slots[idx]) - return 0; - - s1 = module->name; - s2 = slots[idx]; - if (*s2 == '!') { - match = 0; /* negative match */ - s2++; - } - /* compare module name strings - * hyphens are handled as equivalent with underscore - */ - for (;;) { - char c1 = *s1++; - char c2 = *s2++; - if (c1 == '-') - c1 = '_'; - if (c2 == '-') - c2 = '_'; - if (c1 != c2) - return !match; - if (!c1) - break; - } -#endif /* MODULE */ - return match; -} - -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) -int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); -EXPORT_SYMBOL(snd_mixer_oss_notify_callback); -#endif - -#ifdef CONFIG_PROC_FS -static void snd_card_id_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_iprintf(buffer, "%s\n", entry->card->id); -} - -static inline int init_info_for_card(struct snd_card *card) -{ - int err; - struct snd_info_entry *entry; - - if ((err = snd_info_card_register(card)) < 0) { - snd_printd("unable to create card info\n"); - return err; - } - if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) { - snd_printd("unable to create card entry\n"); - return err; - } - entry->c.text.read = snd_card_id_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - card->proc_id = entry; - return 0; -} -#else /* !CONFIG_PROC_FS */ -#define init_info_for_card(card) -#endif - -/** - * snd_card_create - create and initialize a soundcard structure - * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] - * @xid: card identification (ASCII string) - * @module: top level module for locking - * @extra_size: allocate this extra size after the main soundcard structure - * @card_ret: the pointer to store the created card instance - * - * Creates and initializes a soundcard structure. - * - * The function allocates snd_card instance via kzalloc with the given - * space for the driver to use freely. The allocated struct is stored - * in the given card_ret pointer. - * - * Returns zero if successful or a negative error code. - */ -int snd_card_create(int idx, const char *xid, - struct module *module, int extra_size, - struct snd_card **card_ret) -{ - struct snd_card *card; - int err, idx2; - - if (snd_BUG_ON(!card_ret)) - return -EINVAL; - *card_ret = NULL; - - if (extra_size < 0) - extra_size = 0; - card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); - if (!card) - return -ENOMEM; - if (xid) - strlcpy(card->id, xid, sizeof(card->id)); - err = 0; - mutex_lock(&snd_card_mutex); - if (idx < 0) { - for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) - /* idx == -1 == 0xffff means: take any free slot */ - if (~snd_cards_lock & idx & 1<= SNDRV_CARDS) - err = -ENODEV; - if (err < 0) { - mutex_unlock(&snd_card_mutex); - snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n", - idx, snd_ecards_limit - 1, err); - goto __error; - } - snd_cards_lock |= 1 << idx; /* lock it */ - if (idx >= snd_ecards_limit) - snd_ecards_limit = idx + 1; /* increase the limit */ - mutex_unlock(&snd_card_mutex); - card->number = idx; - card->module = module; - INIT_LIST_HEAD(&card->devices); - init_rwsem(&card->controls_rwsem); - rwlock_init(&card->ctl_files_rwlock); - INIT_LIST_HEAD(&card->controls); - INIT_LIST_HEAD(&card->ctl_files); - spin_lock_init(&card->files_lock); - INIT_LIST_HEAD(&card->files_list); - init_waitqueue_head(&card->shutdown_sleep); - atomic_set(&card->refcount, 0); -#ifdef CONFIG_PM - mutex_init(&card->power_lock); - init_waitqueue_head(&card->power_sleep); -#endif - /* the control interface cannot be accessed from the user space until */ - /* snd_cards_bitmask and snd_cards are set with snd_card_register */ - err = snd_ctl_create(card); - if (err < 0) { - snd_printk(KERN_ERR "unable to register control minors\n"); - goto __error; - } - err = snd_info_card_create(card); - if (err < 0) { - snd_printk(KERN_ERR "unable to create card info\n"); - goto __error_ctl; - } - if (extra_size > 0) - card->private_data = (char *)card + sizeof(struct snd_card); - *card_ret = card; - return 0; - - __error_ctl: - snd_device_free_all(card, SNDRV_DEV_CMD_PRE); - __error: - kfree(card); - return err; -} -EXPORT_SYMBOL(snd_card_create); - -/* return non-zero if a card is already locked */ -int snd_card_locked(int card) -{ - int locked; - - mutex_lock(&snd_card_mutex); - locked = snd_cards_lock & (1 << card); - mutex_unlock(&snd_card_mutex); - return locked; -} - -static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig) -{ - return -ENODEV; -} - -static ssize_t snd_disconnect_read(struct file *file, char __user *buf, - size_t count, loff_t *offset) -{ - return -ENODEV; -} - -static ssize_t snd_disconnect_write(struct file *file, const char __user *buf, - size_t count, loff_t *offset) -{ - return -ENODEV; -} - -static int snd_disconnect_release(struct inode *inode, struct file *file) -{ - struct snd_monitor_file *df = NULL, *_df; - - spin_lock(&shutdown_lock); - list_for_each_entry(_df, &shutdown_files, shutdown_list) { - if (_df->file == file) { - df = _df; - list_del_init(&df->shutdown_list); - break; - } - } - spin_unlock(&shutdown_lock); - - if (likely(df)) { - if ((file->f_flags & FASYNC) && df->disconnected_f_op->fasync) - df->disconnected_f_op->fasync(-1, file, 0); - return df->disconnected_f_op->release(inode, file); - } - - panic("%s(%p, %p) failed!", __func__, inode, file); -} - -static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait) -{ - return POLLERR | POLLNVAL; -} - -static long snd_disconnect_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return -ENODEV; -} - -static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma) -{ - return -ENODEV; -} - -static int snd_disconnect_fasync(int fd, struct file *file, int on) -{ - return -ENODEV; -} - -static const struct file_operations snd_shutdown_f_ops = -{ - .owner = THIS_MODULE, - .llseek = snd_disconnect_llseek, - .read = snd_disconnect_read, - .write = snd_disconnect_write, - .release = snd_disconnect_release, - .poll = snd_disconnect_poll, - .unlocked_ioctl = snd_disconnect_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = snd_disconnect_ioctl, -#endif - .mmap = snd_disconnect_mmap, - .fasync = snd_disconnect_fasync -}; - -/** - * snd_card_disconnect - disconnect all APIs from the file-operations (user space) - * @card: soundcard structure - * - * Disconnects all APIs from the file-operations (user space). - * - * Returns zero, otherwise a negative error code. - * - * Note: The current implementation replaces all active file->f_op with special - * dummy file operations (they do nothing except release). - */ -int snd_card_disconnect(struct snd_card *card) -{ - struct snd_monitor_file *mfile; - int err; - - if (!card) - return -EINVAL; - - spin_lock(&card->files_lock); - if (card->shutdown) { - spin_unlock(&card->files_lock); - return 0; - } - card->shutdown = 1; - spin_unlock(&card->files_lock); - - /* phase 1: disable fops (user space) operations for ALSA API */ - mutex_lock(&snd_card_mutex); - snd_cards[card->number] = NULL; - snd_cards_lock &= ~(1 << card->number); - mutex_unlock(&snd_card_mutex); - - /* phase 2: replace file->f_op with special dummy operations */ - - spin_lock(&card->files_lock); - list_for_each_entry(mfile, &card->files_list, list) { - /* it's critical part, use endless loop */ - /* we have no room to fail */ - mfile->disconnected_f_op = mfile->file->f_op; - - spin_lock(&shutdown_lock); - list_add(&mfile->shutdown_list, &shutdown_files); - spin_unlock(&shutdown_lock); - - mfile->file->f_op = &snd_shutdown_f_ops; - fops_get(mfile->file->f_op); - } - spin_unlock(&card->files_lock); - - /* phase 3: notify all connected devices about disconnection */ - /* at this point, they cannot respond to any calls except release() */ - -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) - if (snd_mixer_oss_notify_callback) - snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT); -#endif - - /* notify all devices that we are disconnected */ - err = snd_device_disconnect_all(card); - if (err < 0) - snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number); - - snd_info_card_disconnect(card); - if (card->card_dev) { - device_unregister(card->card_dev); - card->card_dev = NULL; - } -#ifdef CONFIG_PM - wake_up(&card->power_sleep); -#endif - return 0; -} - -EXPORT_SYMBOL(snd_card_disconnect); - -/** - * snd_card_free - frees given soundcard structure - * @card: soundcard structure - * - * This function releases the soundcard structure and the all assigned - * devices automatically. That is, you don't have to release the devices - * by yourself. - * - * Returns zero. Frees all associated devices and frees the control - * interface associated to given soundcard. - */ -static int snd_card_do_free(struct snd_card *card) -{ -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) - if (snd_mixer_oss_notify_callback) - snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); -#endif - if (snd_device_free_all(card, SNDRV_DEV_CMD_PRE) < 0) { - snd_printk(KERN_ERR "unable to free all devices (pre)\n"); - /* Fatal, but this situation should never occur */ - } - if (snd_device_free_all(card, SNDRV_DEV_CMD_NORMAL) < 0) { - snd_printk(KERN_ERR "unable to free all devices (normal)\n"); - /* Fatal, but this situation should never occur */ - } - if (snd_device_free_all(card, SNDRV_DEV_CMD_POST) < 0) { - snd_printk(KERN_ERR "unable to free all devices (post)\n"); - /* Fatal, but this situation should never occur */ - } - if (card->private_free) - card->private_free(card); - snd_info_free_entry(card->proc_id); - if (snd_info_card_free(card) < 0) { - snd_printk(KERN_WARNING "unable to free card info\n"); - /* Not fatal error */ - } - kfree(card); - return 0; -} - -/** - * snd_card_unref - release the reference counter - * @card: the card instance - * - * Decrements the reference counter. When it reaches to zero, wake up - * the sleeper and call the destructor if needed. - */ -void snd_card_unref(struct snd_card *card) -{ - if (atomic_dec_and_test(&card->refcount)) { - wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - snd_card_do_free(card); - } -} -EXPORT_SYMBOL(snd_card_unref); - -int snd_card_free_when_closed(struct snd_card *card) -{ - int ret; - - atomic_inc(&card->refcount); - ret = snd_card_disconnect(card); - if (ret) { - atomic_dec(&card->refcount); - return ret; - } - - card->free_on_last_close = 1; - if (atomic_dec_and_test(&card->refcount)) - snd_card_do_free(card); - return 0; -} - -EXPORT_SYMBOL(snd_card_free_when_closed); - -int snd_card_free(struct snd_card *card) -{ - int ret = snd_card_disconnect(card); - if (ret) - return ret; - - /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); - snd_card_do_free(card); - return 0; -} - -EXPORT_SYMBOL(snd_card_free); - -/* retrieve the last word of shortname or longname */ -static const char *retrieve_id_from_card_name(const char *name) -{ - const char *spos = name; - - while (*name) { - if (isspace(*name) && isalnum(name[1])) - spos = name + 1; - name++; - } - return spos; -} - -/* return true if the given id string doesn't conflict any other card ids */ -static bool card_id_ok(struct snd_card *card, const char *id) -{ - int i; - if (!snd_info_check_reserved_words(id)) - return false; - for (i = 0; i < snd_ecards_limit; i++) { - if (snd_cards[i] && snd_cards[i] != card && - !strcmp(snd_cards[i]->id, id)) - return false; - } - return true; -} - -/* copy to card->id only with valid letters from nid */ -static void copy_valid_id_string(struct snd_card *card, const char *src, - const char *nid) -{ - char *id = card->id; - - while (*nid && !isalnum(*nid)) - nid++; - if (isdigit(*nid)) - *id++ = isalpha(*src) ? *src : 'D'; - while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) { - if (isalnum(*nid)) - *id++ = *nid; - nid++; - } - *id = 0; -} - -/* Set card->id from the given string - * If the string conflicts with other ids, add a suffix to make it unique. - */ -static void snd_card_set_id_no_lock(struct snd_card *card, const char *src, - const char *nid) -{ - int len, loops; - bool with_suffix; - bool is_default = false; - char *id; - - copy_valid_id_string(card, src, nid); - id = card->id; - - again: - /* use "Default" for obviously invalid strings - * ("card" conflicts with proc directories) - */ - if (!*id || !strncmp(id, "card", 4)) { - strcpy(id, "Default"); - is_default = true; - } - - with_suffix = false; - for (loops = 0; loops < SNDRV_CARDS; loops++) { - if (card_id_ok(card, id)) - return; /* OK */ - - len = strlen(id); - if (!with_suffix) { - /* add the "_X" suffix */ - char *spos = id + len; - if (len > sizeof(card->id) - 3) - spos = id + sizeof(card->id) - 3; - strcpy(spos, "_1"); - with_suffix = true; - } else { - /* modify the existing suffix */ - if (id[len - 1] != '9') - id[len - 1]++; - else - id[len - 1] = 'A'; - } - } - /* fallback to the default id */ - if (!is_default) { - *id = 0; - goto again; - } - /* last resort... */ - snd_printk(KERN_ERR "unable to set card id (%s)\n", id); - if (card->proc_root->name) - strcpy(card->id, card->proc_root->name); -} - -/** - * snd_card_set_id - set card identification name - * @card: soundcard structure - * @nid: new identification string - * - * This function sets the card identification and checks for name - * collisions. - */ -void snd_card_set_id(struct snd_card *card, const char *nid) -{ - /* check if user specified own card->id */ - if (card->id[0] != '\0') - return; - mutex_lock(&snd_card_mutex); - snd_card_set_id_no_lock(card, nid, nid); - mutex_unlock(&snd_card_mutex); -} -EXPORT_SYMBOL(snd_card_set_id); - -static ssize_t -card_id_show_attr(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct snd_card *card = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%s\n", card ? card->id : "(null)"); -} - -static ssize_t -card_id_store_attr(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct snd_card *card = dev_get_drvdata(dev); - char buf1[sizeof(card->id)]; - size_t copy = count > sizeof(card->id) - 1 ? - sizeof(card->id) - 1 : count; - size_t idx; - int c; - - for (idx = 0; idx < copy; idx++) { - c = buf[idx]; - if (!isalnum(c) && c != '_' && c != '-') - return -EINVAL; - } - memcpy(buf1, buf, copy); - buf1[copy] = '\0'; - mutex_lock(&snd_card_mutex); - if (!card_id_ok(NULL, buf1)) { - mutex_unlock(&snd_card_mutex); - return -EEXIST; - } - strcpy(card->id, buf1); - snd_info_card_id_change(card); - mutex_unlock(&snd_card_mutex); - - return count; -} - -static struct device_attribute card_id_attrs = - __ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr); - -static ssize_t -card_number_show_attr(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct snd_card *card = dev_get_drvdata(dev); - return snprintf(buf, PAGE_SIZE, "%i\n", card ? card->number : -1); -} - -static struct device_attribute card_number_attrs = - __ATTR(number, S_IRUGO, card_number_show_attr, NULL); - -/** - * snd_card_register - register the soundcard - * @card: soundcard structure - * - * This function registers all the devices assigned to the soundcard. - * Until calling this, the ALSA control interface is blocked from the - * external accesses. Thus, you should call this function at the end - * of the initialization of the card. - * - * Returns zero otherwise a negative error code if the registration failed. - */ -int snd_card_register(struct snd_card *card) -{ - int err; - - if (snd_BUG_ON(!card)) - return -EINVAL; - - if (!card->card_dev) { - card->card_dev = device_create(sound_class, card->dev, - MKDEV(0, 0), card, - "card%i", card->number); - if (IS_ERR(card->card_dev)) - card->card_dev = NULL; - } - - if ((err = snd_device_register_all(card)) < 0) - return err; - mutex_lock(&snd_card_mutex); - if (snd_cards[card->number]) { - /* already registered */ - mutex_unlock(&snd_card_mutex); - return 0; - } - if (*card->id) { - /* make a unique id name from the given string */ - char tmpid[sizeof(card->id)]; - memcpy(tmpid, card->id, sizeof(card->id)); - snd_card_set_id_no_lock(card, tmpid, tmpid); - } else { - /* create an id from either shortname or longname */ - const char *src; - src = *card->shortname ? card->shortname : card->longname; - snd_card_set_id_no_lock(card, src, - retrieve_id_from_card_name(src)); - } - snd_cards[card->number] = card; - mutex_unlock(&snd_card_mutex); - init_info_for_card(card); -#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) - if (snd_mixer_oss_notify_callback) - snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER); -#endif - if (card->card_dev) { - err = device_create_file(card->card_dev, &card_id_attrs); - if (err < 0) - return err; - err = device_create_file(card->card_dev, &card_number_attrs); - if (err < 0) - return err; - } - - return 0; -} - -EXPORT_SYMBOL(snd_card_register); - -#ifdef CONFIG_PROC_FS -static struct snd_info_entry *snd_card_info_entry; - -static void snd_card_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - int idx, count; - struct snd_card *card; - - for (idx = count = 0; idx < SNDRV_CARDS; idx++) { - mutex_lock(&snd_card_mutex); - if ((card = snd_cards[idx]) != NULL) { - count++; - snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n", - idx, - card->id, - card->driver, - card->shortname); - snd_iprintf(buffer, " %s\n", - card->longname); - } - mutex_unlock(&snd_card_mutex); - } - if (!count) - snd_iprintf(buffer, "--- no soundcards ---\n"); -} - -#ifdef CONFIG_SND_OSSEMUL - -void snd_card_info_read_oss(struct snd_info_buffer *buffer) -{ - int idx, count; - struct snd_card *card; - - for (idx = count = 0; idx < SNDRV_CARDS; idx++) { - mutex_lock(&snd_card_mutex); - if ((card = snd_cards[idx]) != NULL) { - count++; - snd_iprintf(buffer, "%s\n", card->longname); - } - mutex_unlock(&snd_card_mutex); - } - if (!count) { - snd_iprintf(buffer, "--- no soundcards ---\n"); - } -} - -#endif - -#ifdef MODULE -static struct snd_info_entry *snd_card_module_info_entry; -static void snd_card_module_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - int idx; - struct snd_card *card; - - for (idx = 0; idx < SNDRV_CARDS; idx++) { - mutex_lock(&snd_card_mutex); - if ((card = snd_cards[idx]) != NULL) - snd_iprintf(buffer, "%2i %s\n", - idx, card->module->name); - mutex_unlock(&snd_card_mutex); - } -} -#endif - -int __init snd_card_info_init(void) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL); - if (! entry) - return -ENOMEM; - entry->c.text.read = snd_card_info_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } - snd_card_info_entry = entry; - -#ifdef MODULE - entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL); - if (entry) { - entry->c.text.read = snd_card_module_info_read; - if (snd_info_register(entry) < 0) - snd_info_free_entry(entry); - else - snd_card_module_info_entry = entry; - } -#endif - - return 0; -} - -int __exit snd_card_info_done(void) -{ - snd_info_free_entry(snd_card_info_entry); -#ifdef MODULE - snd_info_free_entry(snd_card_module_info_entry); -#endif - return 0; -} - -#endif /* CONFIG_PROC_FS */ - -/** - * snd_component_add - add a component string - * @card: soundcard structure - * @component: the component id string - * - * This function adds the component id string to the supported list. - * The component can be referred from the alsa-lib. - * - * Returns zero otherwise a negative error code. - */ - -int snd_component_add(struct snd_card *card, const char *component) -{ - char *ptr; - int len = strlen(component); - - ptr = strstr(card->components, component); - if (ptr != NULL) { - if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */ - return 1; - } - if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) { - snd_BUG(); - return -ENOMEM; - } - if (card->components[0] != '\0') - strcat(card->components, " "); - strcat(card->components, component); - return 0; -} - -EXPORT_SYMBOL(snd_component_add); - -/** - * snd_card_file_add - add the file to the file list of the card - * @card: soundcard structure - * @file: file pointer - * - * This function adds the file to the file linked-list of the card. - * This linked-list is used to keep tracking the connection state, - * and to avoid the release of busy resources by hotplug. - * - * Returns zero or a negative error code. - */ -int snd_card_file_add(struct snd_card *card, struct file *file) -{ - struct snd_monitor_file *mfile; - - mfile = kmalloc(sizeof(*mfile), GFP_KERNEL); - if (mfile == NULL) - return -ENOMEM; - mfile->file = file; - mfile->disconnected_f_op = NULL; - INIT_LIST_HEAD(&mfile->shutdown_list); - spin_lock(&card->files_lock); - if (card->shutdown) { - spin_unlock(&card->files_lock); - kfree(mfile); - return -ENODEV; - } - list_add(&mfile->list, &card->files_list); - atomic_inc(&card->refcount); - spin_unlock(&card->files_lock); - return 0; -} - -EXPORT_SYMBOL(snd_card_file_add); - -/** - * snd_card_file_remove - remove the file from the file list - * @card: soundcard structure - * @file: file pointer - * - * This function removes the file formerly added to the card via - * snd_card_file_add() function. - * If all files are removed and snd_card_free_when_closed() was - * called beforehand, it processes the pending release of - * resources. - * - * Returns zero or a negative error code. - */ -int snd_card_file_remove(struct snd_card *card, struct file *file) -{ - struct snd_monitor_file *mfile, *found = NULL; - - spin_lock(&card->files_lock); - list_for_each_entry(mfile, &card->files_list, list) { - if (mfile->file == file) { - list_del(&mfile->list); - spin_lock(&shutdown_lock); - list_del(&mfile->shutdown_list); - spin_unlock(&shutdown_lock); - if (mfile->disconnected_f_op) - fops_put(mfile->disconnected_f_op); - found = mfile; - break; - } - } - spin_unlock(&card->files_lock); - if (!found) { - snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); - return -ENOENT; - } - kfree(found); - snd_card_unref(card); - return 0; -} - -EXPORT_SYMBOL(snd_card_file_remove); - -#ifdef CONFIG_PM -/** - * snd_power_wait - wait until the power-state is changed. - * @card: soundcard structure - * @power_state: expected power state - * - * Waits until the power-state is changed. - * - * Note: the power lock must be active before call. - */ -int snd_power_wait(struct snd_card *card, unsigned int power_state) -{ - wait_queue_t wait; - int result = 0; - - /* fastpath */ - if (snd_power_get_state(card) == power_state) - return 0; - init_waitqueue_entry(&wait, current); - add_wait_queue(&card->power_sleep, &wait); - while (1) { - if (card->shutdown) { - result = -ENODEV; - break; - } - if (snd_power_get_state(card) == power_state) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - snd_power_unlock(card); - schedule_timeout(30 * HZ); - snd_power_lock(card); - } - remove_wait_queue(&card->power_sleep, &wait); - return result; -} - -EXPORT_SYMBOL(snd_power_wait); -#endif /* CONFIG_PM */ diff --git a/ANDROID_3.4.5/sound/core/isadma.c b/ANDROID_3.4.5/sound/core/isadma.c deleted file mode 100644 index c0f1208b..00000000 --- a/ANDROID_3.4.5/sound/core/isadma.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ISA DMA support functions - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -/* - * Defining following add some delay. Maybe this helps for some broken - * ISA DMA controllers. - */ - -#undef HAVE_REALLY_SLOW_DMA_CONTROLLER - -#include -#include -#include - -/** - * snd_dma_program - program an ISA DMA transfer - * @dma: the dma number - * @addr: the physical address of the buffer - * @size: the DMA transfer size - * @mode: the DMA transfer mode, DMA_MODE_XXX - * - * Programs an ISA DMA transfer for the given buffer. - */ -void snd_dma_program(unsigned long dma, - unsigned long addr, unsigned int size, - unsigned short mode) -{ - unsigned long flags; - - flags = claim_dma_lock(); - disable_dma(dma); - clear_dma_ff(dma); - set_dma_mode(dma, mode); - set_dma_addr(dma, addr); - set_dma_count(dma, size); - if (!(mode & DMA_MODE_NO_ENABLE)) - enable_dma(dma); - release_dma_lock(flags); -} - -EXPORT_SYMBOL(snd_dma_program); - -/** - * snd_dma_disable - stop the ISA DMA transfer - * @dma: the dma number - * - * Stops the ISA DMA transfer. - */ -void snd_dma_disable(unsigned long dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma); - disable_dma(dma); - release_dma_lock(flags); -} - -EXPORT_SYMBOL(snd_dma_disable); - -/** - * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes - * @dma: the dma number - * @size: the dma transfer size - * - * Returns the current pointer in DMA tranfer buffer in bytes - */ -unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) -{ - unsigned long flags; - unsigned int result, result1; - - flags = claim_dma_lock(); - clear_dma_ff(dma); - if (!isa_dma_bridge_buggy) - disable_dma(dma); - result = get_dma_residue(dma); - /* - * HACK - read the counter again and choose higher value in order to - * avoid reading during counter lower byte roll over if the - * isa_dma_bridge_buggy is set. - */ - result1 = get_dma_residue(dma); - if (!isa_dma_bridge_buggy) - enable_dma(dma); - release_dma_lock(flags); - if (unlikely(result < result1)) - result = result1; -#ifdef CONFIG_SND_DEBUG - if (result > size) - snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size); -#endif - if (result >= size || result == 0) - return 0; - else - return size - result; -} - -EXPORT_SYMBOL(snd_dma_pointer); diff --git a/ANDROID_3.4.5/sound/core/jack.c b/ANDROID_3.4.5/sound/core/jack.c deleted file mode 100644 index 471e1e3b..00000000 --- a/ANDROID_3.4.5/sound/core/jack.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Jack abstraction layer - * - * Copyright 2008 Wolfson Microelectronics - * - * 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 - -static int jack_switch_types[SND_JACK_SWITCH_TYPES] = { - SW_HEADPHONE_INSERT, - SW_MICROPHONE_INSERT, - SW_LINEOUT_INSERT, - SW_JACK_PHYSICAL_INSERT, - SW_VIDEOOUT_INSERT, - SW_LINEIN_INSERT, -}; - -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) - input_unregister_device(jack->input_dev); - else - input_free_device(jack->input_dev); - - kfree(jack->id); - kfree(jack); - - return 0; -} - -static int snd_jack_dev_register(struct snd_device *device) -{ - struct snd_jack *jack = device->device_data; - struct snd_card *card = device->card; - int err, i; - - snprintf(jack->name, sizeof(jack->name), "%s %s", - card->shortname, jack->id); - jack->input_dev->name = jack->name; - - /* Default to the sound card device. */ - if (!jack->input_dev->dev.parent) - jack->input_dev->dev.parent = snd_card_get_device_link(card); - - /* Add capabilities for any keys that are enabled */ - for (i = 0; i < ARRAY_SIZE(jack->key); i++) { - int testbit = SND_JACK_BTN_0 >> i; - - if (!(jack->type & testbit)) - continue; - - if (!jack->key[i]) - jack->key[i] = BTN_0 + i; - - input_set_capability(jack->input_dev, EV_KEY, jack->key[i]); - } - - err = input_register_device(jack->input_dev); - if (err == 0) - jack->registered = 1; - - return err; -} - -/** - * snd_jack_new - Create a new jack - * @card: the card instance - * @id: an identifying string for this jack - * @type: a bitmask of enum snd_jack_type values that can be detected by - * this jack - * @jjack: Used to provide the allocated jack object to the caller. - * - * Creates a new jack object. - * - * Returns zero if successful, or a negative error code on failure. - * On success jjack will be initialised. - */ -int snd_jack_new(struct snd_card *card, const char *id, int type, - struct snd_jack **jjack) -{ - struct snd_jack *jack; - int err; - int i; - static struct snd_device_ops ops = { - .dev_free = snd_jack_dev_free, - .dev_register = snd_jack_dev_register, - }; - - jack = kzalloc(sizeof(struct snd_jack), GFP_KERNEL); - if (jack == NULL) - return -ENOMEM; - - jack->id = kstrdup(id, GFP_KERNEL); - - jack->input_dev = input_allocate_device(); - if (jack->input_dev == NULL) { - err = -ENOMEM; - goto fail_input; - } - - jack->input_dev->phys = "ALSA"; - - jack->type = type; - - for (i = 0; i < SND_JACK_SWITCH_TYPES; i++) - if (type & (1 << i)) - input_set_capability(jack->input_dev, EV_SW, - jack_switch_types[i]); - - err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); - if (err < 0) - goto fail_input; - - *jjack = jack; - - return 0; - -fail_input: - input_free_device(jack->input_dev); - kfree(jack->id); - kfree(jack); - return err; -} -EXPORT_SYMBOL(snd_jack_new); - -/** - * snd_jack_set_parent - Set the parent device for a jack - * - * @jack: The jack to configure - * @parent: The device to set as parent for the jack. - * - * Set the parent for the jack input device in the device tree. This - * function is only valid prior to registration of the jack. If no - * parent is configured then the parent device will be the sound card. - */ -void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) -{ - WARN_ON(jack->registered); - - jack->input_dev->dev.parent = parent; -} -EXPORT_SYMBOL(snd_jack_set_parent); - -/** - * snd_jack_set_key - Set a key mapping on a jack - * - * @jack: The jack to configure - * @type: Jack report type for this key - * @keytype: Input layer key type to be reported - * - * Map a SND_JACK_BTN_ button type to an input layer key, allowing - * reporting of keys on accessories via the jack abstraction. If no - * mapping is provided but keys are enabled in the jack type then - * BTN_n numeric buttons will be reported. - * - * Note that this is intended to be use by simple devices with small - * numbers of keys that can be reported. It is also possible to - * access the input device directly - devices with complex input - * capabilities on accessories should consider doing this rather than - * using this abstraction. - * - * This function may only be called prior to registration of the jack. - */ -int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type, - int keytype) -{ - int key = fls(SND_JACK_BTN_0) - fls(type); - - WARN_ON(jack->registered); - - if (!keytype || key >= ARRAY_SIZE(jack->key)) - return -EINVAL; - - jack->type |= type; - jack->key[key] = keytype; - - return 0; -} -EXPORT_SYMBOL(snd_jack_set_key); - -/** - * snd_jack_report - Report the current status of a jack - * - * @jack: The jack to report status for - * @status: The current status of the jack - */ -void snd_jack_report(struct snd_jack *jack, int status) -{ - int i; - - if (!jack) - return; - - for (i = 0; i < ARRAY_SIZE(jack->key); i++) { - int testbit = SND_JACK_BTN_0 >> i; - - if (jack->type & testbit) - input_report_key(jack->input_dev, jack->key[i], - status & testbit); - } - - for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) { - int testbit = 1 << i; - if (jack->type & testbit) - input_report_switch(jack->input_dev, - jack_switch_types[i], - status & testbit); - } - - input_sync(jack->input_dev); -} -EXPORT_SYMBOL(snd_jack_report); - -MODULE_AUTHOR("Mark Brown "); -MODULE_DESCRIPTION("Jack detection support for ALSA"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/core/memalloc.c b/ANDROID_3.4.5/sound/core/memalloc.c deleted file mode 100644 index 69156923..00000000 --- a/ANDROID_3.4.5/sound/core/memalloc.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Takashi Iwai - * - * Generic memory allocators - * - * - * 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 -#include -#include -#include - - -MODULE_AUTHOR("Takashi Iwai , Jaroslav Kysela "); -MODULE_DESCRIPTION("Memory allocator for ALSA system."); -MODULE_LICENSE("GPL"); - - -/* - */ - -static DEFINE_MUTEX(list_mutex); -static LIST_HEAD(mem_list_head); - -/* buffer preservation list */ -struct snd_mem_list { - struct snd_dma_buffer buffer; - unsigned int id; - struct list_head list; -}; - -/* id for pre-allocated buffers */ -#define SNDRV_DMA_DEVICE_UNUSED (unsigned int)-1 - -/* - * - * Generic memory allocators - * - */ - -static long snd_allocated_pages; /* holding the number of allocated pages */ - -static inline void inc_snd_pages(int order) -{ - snd_allocated_pages += 1 << order; -} - -static inline void dec_snd_pages(int order) -{ - snd_allocated_pages -= 1 << order; -} - -/** - * snd_malloc_pages - allocate pages with the given size - * @size: the size to allocate in bytes - * @gfp_flags: the allocation conditions, GFP_XXX - * - * Allocates the physically contiguous pages with the given size. - * - * Returns the pointer of the buffer, or NULL if no enoguh memory. - */ -void *snd_malloc_pages(size_t size, gfp_t gfp_flags) -{ - int pg; - void *res; - - if (WARN_ON(!size)) - return NULL; - if (WARN_ON(!gfp_flags)) - return NULL; - gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */ - pg = get_order(size); - if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) - inc_snd_pages(pg); - return res; -} - -/** - * snd_free_pages - release the pages - * @ptr: the buffer pointer to release - * @size: the allocated buffer size - * - * Releases the buffer allocated via snd_malloc_pages(). - */ -void snd_free_pages(void *ptr, size_t size) -{ - int pg; - - if (ptr == NULL) - return; - pg = get_order(size); - dec_snd_pages(pg); - free_pages((unsigned long) ptr, pg); -} - -/* - * - * Bus-specific memory allocators - * - */ - -#ifdef CONFIG_HAS_DMA -/* allocate the coherent DMA pages */ -static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma) -{ - int pg; - void *res; - gfp_t gfp_flags; - - if (WARN_ON(!dma)) - return NULL; - pg = get_order(size); - gfp_flags = GFP_KERNEL - | __GFP_COMP /* compound page lets parts be mapped */ - | __GFP_NORETRY /* don't trigger OOM-killer */ - | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ - res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags); - if (res != NULL) - inc_snd_pages(pg); - - return res; -} - -/* free the coherent DMA pages */ -static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, - dma_addr_t dma) -{ - int pg; - - if (ptr == NULL) - return; - pg = get_order(size); - dec_snd_pages(pg); - dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma); -} -#endif /* CONFIG_HAS_DMA */ - -/* - * - * ALSA generic memory management - * - */ - - -/** - * snd_dma_alloc_pages - allocate the buffer area according to the given type - * @type: the DMA buffer type - * @device: the device pointer - * @size: the buffer size to allocate - * @dmab: buffer allocation record to store the allocated data - * - * Calls the memory-allocator function for the corresponding - * buffer type. - * - * Returns zero if the buffer with the given size is allocated successfully, - * other a negative value at error. - */ -int snd_dma_alloc_pages(int type, struct device *device, size_t size, - struct snd_dma_buffer *dmab) -{ - if (WARN_ON(!size)) - return -ENXIO; - if (WARN_ON(!dmab)) - return -ENXIO; - - dmab->dev.type = type; - dmab->dev.dev = device; - dmab->bytes = 0; - switch (type) { - case SNDRV_DMA_TYPE_CONTINUOUS: - dmab->area = snd_malloc_pages(size, - (__force gfp_t)(unsigned long)device); - dmab->addr = 0; - break; -#ifdef CONFIG_HAS_DMA - case SNDRV_DMA_TYPE_DEV: - dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); - break; -#endif -#ifdef CONFIG_SND_DMA_SGBUF - case SNDRV_DMA_TYPE_DEV_SG: - snd_malloc_sgbuf_pages(device, size, dmab, NULL); - break; -#endif - default: - printk(KERN_ERR "snd-malloc: invalid device type %d\n", type); - dmab->area = NULL; - dmab->addr = 0; - return -ENXIO; - } - if (! dmab->area) - return -ENOMEM; - dmab->bytes = size; - return 0; -} - -/** - * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback - * @type: the DMA buffer type - * @device: the device pointer - * @size: the buffer size to allocate - * @dmab: buffer allocation record to store the allocated data - * - * Calls the memory-allocator function for the corresponding - * buffer type. When no space is left, this function reduces the size and - * tries to allocate again. The size actually allocated is stored in - * res_size argument. - * - * Returns zero if the buffer with the given size is allocated successfully, - * other a negative value at error. - */ -int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, - struct snd_dma_buffer *dmab) -{ - int err; - - while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) { - size_t aligned_size; - if (err != -ENOMEM) - return err; - if (size <= PAGE_SIZE) - return -ENOMEM; - aligned_size = PAGE_SIZE << get_order(size); - if (size != aligned_size) - size = aligned_size; - else - size >>= 1; - } - if (! dmab->area) - return -ENOMEM; - return 0; -} - - -/** - * snd_dma_free_pages - release the allocated buffer - * @dmab: the buffer allocation record to release - * - * Releases the allocated buffer via snd_dma_alloc_pages(). - */ -void snd_dma_free_pages(struct snd_dma_buffer *dmab) -{ - switch (dmab->dev.type) { - case SNDRV_DMA_TYPE_CONTINUOUS: - snd_free_pages(dmab->area, dmab->bytes); - break; -#ifdef CONFIG_HAS_DMA - case SNDRV_DMA_TYPE_DEV: - snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); - break; -#endif -#ifdef CONFIG_SND_DMA_SGBUF - case SNDRV_DMA_TYPE_DEV_SG: - snd_free_sgbuf_pages(dmab); - break; -#endif - default: - printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type); - } -} - - -/** - * snd_dma_get_reserved - get the reserved buffer for the given device - * @dmab: the buffer allocation record to store - * @id: the buffer id - * - * Looks for the reserved-buffer list and re-uses if the same buffer - * is found in the list. When the buffer is found, it's removed from the free list. - * - * Returns the size of buffer if the buffer is found, or zero if not found. - */ -size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id) -{ - struct snd_mem_list *mem; - - if (WARN_ON(!dmab)) - return 0; - - mutex_lock(&list_mutex); - list_for_each_entry(mem, &mem_list_head, list) { - if (mem->id == id && - (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL || - ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) { - struct device *dev = dmab->dev.dev; - list_del(&mem->list); - *dmab = mem->buffer; - if (dmab->dev.dev == NULL) - dmab->dev.dev = dev; - kfree(mem); - mutex_unlock(&list_mutex); - return dmab->bytes; - } - } - mutex_unlock(&list_mutex); - return 0; -} - -/** - * snd_dma_reserve_buf - reserve the buffer - * @dmab: the buffer to reserve - * @id: the buffer id - * - * Reserves the given buffer as a reserved buffer. - * - * Returns zero if successful, or a negative code at error. - */ -int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id) -{ - struct snd_mem_list *mem; - - if (WARN_ON(!dmab)) - return -EINVAL; - mem = kmalloc(sizeof(*mem), GFP_KERNEL); - if (! mem) - return -ENOMEM; - mutex_lock(&list_mutex); - mem->buffer = *dmab; - mem->id = id; - list_add_tail(&mem->list, &mem_list_head); - mutex_unlock(&list_mutex); - return 0; -} - -/* - * purge all reserved buffers - */ -static void free_all_reserved_pages(void) -{ - struct list_head *p; - struct snd_mem_list *mem; - - mutex_lock(&list_mutex); - while (! list_empty(&mem_list_head)) { - p = mem_list_head.next; - mem = list_entry(p, struct snd_mem_list, list); - list_del(p); - snd_dma_free_pages(&mem->buffer); - kfree(mem); - } - mutex_unlock(&list_mutex); -} - - -#ifdef CONFIG_PROC_FS -/* - * proc file interface - */ -#define SND_MEM_PROC_FILE "driver/snd-page-alloc" -static struct proc_dir_entry *snd_mem_proc; - -static int snd_mem_proc_read(struct seq_file *seq, void *offset) -{ - long pages = snd_allocated_pages >> (PAGE_SHIFT-12); - struct snd_mem_list *mem; - int devno; - static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" }; - - mutex_lock(&list_mutex); - seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n", - pages * PAGE_SIZE, pages, PAGE_SIZE / 1024); - devno = 0; - list_for_each_entry(mem, &mem_list_head, list) { - devno++; - seq_printf(seq, "buffer %d : ID %08x : type %s\n", - devno, mem->id, types[mem->buffer.dev.type]); - seq_printf(seq, " addr = 0x%lx, size = %d bytes\n", - (unsigned long)mem->buffer.addr, - (int)mem->buffer.bytes); - } - mutex_unlock(&list_mutex); - return 0; -} - -static int snd_mem_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, snd_mem_proc_read, NULL); -} - -/* FIXME: for pci only - other bus? */ -#ifdef CONFIG_PCI -#define gettoken(bufp) strsep(bufp, " \t\n") - -static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) -{ - char buf[128]; - char *token, *p; - - if (count > sizeof(buf) - 1) - return -EINVAL; - if (copy_from_user(buf, buffer, count)) - return -EFAULT; - buf[count] = '\0'; - - p = buf; - token = gettoken(&p); - if (! token || *token == '#') - return count; - if (strcmp(token, "add") == 0) { - char *endp; - int vendor, device, size, buffers; - long mask; - int i, alloced; - struct pci_dev *pci; - - if ((token = gettoken(&p)) == NULL || - (vendor = simple_strtol(token, NULL, 0)) <= 0 || - (token = gettoken(&p)) == NULL || - (device = simple_strtol(token, NULL, 0)) <= 0 || - (token = gettoken(&p)) == NULL || - (mask = simple_strtol(token, NULL, 0)) < 0 || - (token = gettoken(&p)) == NULL || - (size = memparse(token, &endp)) < 64*1024 || - size > 16*1024*1024 /* too big */ || - (token = gettoken(&p)) == NULL || - (buffers = simple_strtol(token, NULL, 0)) <= 0 || - buffers > 4) { - printk(KERN_ERR "snd-page-alloc: invalid proc write format\n"); - return count; - } - vendor &= 0xffff; - device &= 0xffff; - - alloced = 0; - pci = NULL; - while ((pci = pci_get_device(vendor, device, pci)) != NULL) { - if (mask > 0 && mask < 0xffffffff) { - if (pci_set_dma_mask(pci, mask) < 0 || - pci_set_consistent_dma_mask(pci, mask) < 0) { - printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device); - pci_dev_put(pci); - return count; - } - } - for (i = 0; i < buffers; i++) { - struct snd_dma_buffer dmab; - memset(&dmab, 0, sizeof(dmab)); - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, &dmab) < 0) { - printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); - pci_dev_put(pci); - return count; - } - snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci)); - } - alloced++; - } - if (! alloced) { - for (i = 0; i < buffers; i++) { - struct snd_dma_buffer dmab; - memset(&dmab, 0, sizeof(dmab)); - /* FIXME: We can allocate only in ZONE_DMA - * without a device pointer! - */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL, - size, &dmab) < 0) { - printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); - break; - } - snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device)); - } - } - } else if (strcmp(token, "erase") == 0) - /* FIXME: need for releasing each buffer chunk? */ - free_all_reserved_pages(); - else - printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n"); - return count; -} -#endif /* CONFIG_PCI */ - -static const struct file_operations snd_mem_proc_fops = { - .owner = THIS_MODULE, - .open = snd_mem_proc_open, - .read = seq_read, -#ifdef CONFIG_PCI - .write = snd_mem_proc_write, -#endif - .llseek = seq_lseek, - .release = single_release, -}; - -#endif /* CONFIG_PROC_FS */ - -/* - * module entry - */ - -static int __init snd_mem_init(void) -{ -#ifdef CONFIG_PROC_FS - snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL, - &snd_mem_proc_fops); -#endif - return 0; -} - -static void __exit snd_mem_exit(void) -{ - remove_proc_entry(SND_MEM_PROC_FILE, NULL); - free_all_reserved_pages(); - if (snd_allocated_pages > 0) - printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages); -} - - -module_init(snd_mem_init) -module_exit(snd_mem_exit) - - -/* - * exports - */ -EXPORT_SYMBOL(snd_dma_alloc_pages); -EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); -EXPORT_SYMBOL(snd_dma_free_pages); - -EXPORT_SYMBOL(snd_dma_get_reserved_buf); -EXPORT_SYMBOL(snd_dma_reserve_buf); - -EXPORT_SYMBOL(snd_malloc_pages); -EXPORT_SYMBOL(snd_free_pages); diff --git a/ANDROID_3.4.5/sound/core/memory.c b/ANDROID_3.4.5/sound/core/memory.c deleted file mode 100644 index 66a278d0..00000000 --- a/ANDROID_3.4.5/sound/core/memory.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * - * Misc memory accessors - * - * - * 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 - -/** - * copy_to_user_fromio - copy data from mmio-space to user-space - * @dst: the destination pointer on user-space - * @src: the source pointer on mmio - * @count: the data size to copy in bytes - * - * Copies the data from mmio-space to user-space. - * - * Returns zero if successful, or non-zero on failure. - */ -int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count) -{ -#if defined(__i386__) || defined(CONFIG_SPARC32) - return copy_to_user(dst, (const void __force*)src, count) ? -EFAULT : 0; -#else - char buf[256]; - while (count) { - size_t c = count; - if (c > sizeof(buf)) - c = sizeof(buf); - memcpy_fromio(buf, (void __iomem *)src, c); - if (copy_to_user(dst, buf, c)) - return -EFAULT; - count -= c; - dst += c; - src += c; - } - return 0; -#endif -} - -EXPORT_SYMBOL(copy_to_user_fromio); - -/** - * copy_from_user_toio - copy data from user-space to mmio-space - * @dst: the destination pointer on mmio-space - * @src: the source pointer on user-space - * @count: the data size to copy in bytes - * - * Copies the data from user-space to mmio-space. - * - * Returns zero if successful, or non-zero on failure. - */ -int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count) -{ -#if defined(__i386__) || defined(CONFIG_SPARC32) - return copy_from_user((void __force *)dst, src, count) ? -EFAULT : 0; -#else - char buf[256]; - while (count) { - size_t c = count; - if (c > sizeof(buf)) - c = sizeof(buf); - if (copy_from_user(buf, src, c)) - return -EFAULT; - memcpy_toio(dst, buf, c); - count -= c; - dst += c; - src += c; - } - return 0; -#endif -} - -EXPORT_SYMBOL(copy_from_user_toio); diff --git a/ANDROID_3.4.5/sound/core/misc.c b/ANDROID_3.4.5/sound/core/misc.c deleted file mode 100644 index 76816792..00000000 --- a/ANDROID_3.4.5/sound/core/misc.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Misc and compatibility things - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -#ifdef CONFIG_SND_DEBUG - -#ifdef CONFIG_SND_DEBUG_VERBOSE -#define DEFAULT_DEBUG_LEVEL 2 -#else -#define DEFAULT_DEBUG_LEVEL 1 -#endif - -static int debug = DEFAULT_DEBUG_LEVEL; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0 = disable)"); - -#endif /* CONFIG_SND_DEBUG */ - -void release_and_free_resource(struct resource *res) -{ - if (res) { - release_resource(res); - kfree(res); - } -} - -EXPORT_SYMBOL(release_and_free_resource); - -#ifdef CONFIG_SND_VERBOSE_PRINTK -/* strip the leading path if the given path is absolute */ -static const char *sanity_file_name(const char *path) -{ - if (*path == '/') - return strrchr(path, '/') + 1; - else - return path; -} -#endif - -#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) -void __snd_printk(unsigned int level, const char *path, int line, - const char *format, ...) -{ - va_list args; -#ifdef CONFIG_SND_VERBOSE_PRINTK - struct va_format vaf; - char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV"; -#endif - -#ifdef CONFIG_SND_DEBUG - if (debug < level) - return; -#endif - - va_start(args, format); -#ifdef CONFIG_SND_VERBOSE_PRINTK - vaf.fmt = format; - vaf.va = &args; - if (format[0] == '<' && format[2] == '>') { - memcpy(verbose_fmt, format, 3); - vaf.fmt = format + 3; - } else if (level) - memcpy(verbose_fmt, KERN_DEBUG, 3); - printk(verbose_fmt, sanity_file_name(path), line, &vaf); -#else - vprintk(format, args); -#endif - va_end(args); -} -EXPORT_SYMBOL_GPL(__snd_printk); -#endif - -#ifdef CONFIG_PCI -#include -/** - * snd_pci_quirk_lookup_id - look up a PCI SSID quirk list - * @vendor: PCI SSV id - * @device: PCI SSD id - * @list: quirk list, terminated by a null entry - * - * Look through the given quirk list and finds a matching entry - * with the same PCI SSID. When subdevice is 0, all subdevice - * values may match. - * - * Returns the matched entry pointer, or NULL if nothing matched. - */ -const struct snd_pci_quirk * -snd_pci_quirk_lookup_id(u16 vendor, u16 device, - const struct snd_pci_quirk *list) -{ - const struct snd_pci_quirk *q; - - for (q = list; q->subvendor; q++) { - if (q->subvendor != vendor) - continue; - if (!q->subdevice || - (device & q->subdevice_mask) == q->subdevice) - return q; - } - return NULL; -} -EXPORT_SYMBOL(snd_pci_quirk_lookup_id); - -/** - * snd_pci_quirk_lookup - look up a PCI SSID quirk list - * @pci: pci_dev handle - * @list: quirk list, terminated by a null entry - * - * Look through the given quirk list and finds a matching entry - * with the same PCI SSID. When subdevice is 0, all subdevice - * values may match. - * - * Returns the matched entry pointer, or NULL if nothing matched. - */ -const struct snd_pci_quirk * -snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list) -{ - return snd_pci_quirk_lookup_id(pci->subsystem_vendor, - pci->subsystem_device, - list); -} -EXPORT_SYMBOL(snd_pci_quirk_lookup); -#endif diff --git a/ANDROID_3.4.5/sound/core/oss/Makefile b/ANDROID_3.4.5/sound/core/oss/Makefile deleted file mode 100644 index 10a79453..00000000 --- a/ANDROID_3.4.5/sound/core/oss/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 1999 by Jaroslav Kysela -# - -snd-mixer-oss-objs := mixer_oss.o - -snd-pcm-oss-y := pcm_oss.o -snd-pcm-oss-$(CONFIG_SND_PCM_OSS_PLUGINS) += pcm_plugin.o \ - io.o copy.o linear.o mulaw.o route.o rate.o - -obj-$(CONFIG_SND_MIXER_OSS) += snd-mixer-oss.o -obj-$(CONFIG_SND_PCM_OSS) += snd-pcm-oss.o diff --git a/ANDROID_3.4.5/sound/core/oss/copy.c b/ANDROID_3.4.5/sound/core/oss/copy.c deleted file mode 100644 index 05b58d4f..00000000 --- a/ANDROID_3.4.5/sound/core/oss/copy.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Linear conversion Plug-In - * Copyright (c) 2000 by Abramo Bagnara - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include "pcm_plugin.h" - -static snd_pcm_sframes_t copy_transfer(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - unsigned int channel; - unsigned int nchannels; - - if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) - return -ENXIO; - if (frames == 0) - return 0; - nchannels = plugin->src_format.channels; - for (channel = 0; channel < nchannels; channel++) { - if (snd_BUG_ON(src_channels->area.first % 8 || - src_channels->area.step % 8)) - return -ENXIO; - if (snd_BUG_ON(dst_channels->area.first % 8 || - dst_channels->area.step % 8)) - return -ENXIO; - if (!src_channels->enabled) { - if (dst_channels->wanted) - snd_pcm_area_silence(&dst_channels->area, 0, frames, plugin->dst_format.format); - dst_channels->enabled = 0; - continue; - } - dst_channels->enabled = 1; - snd_pcm_area_copy(&src_channels->area, 0, &dst_channels->area, 0, frames, plugin->src_format.format); - src_channels++; - dst_channels++; - } - return frames; -} - -int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin) -{ - int err; - struct snd_pcm_plugin *plugin; - int width; - - if (snd_BUG_ON(!r_plugin)) - return -ENXIO; - *r_plugin = NULL; - - if (snd_BUG_ON(src_format->format != dst_format->format)) - return -ENXIO; - if (snd_BUG_ON(src_format->rate != dst_format->rate)) - return -ENXIO; - if (snd_BUG_ON(src_format->channels != dst_format->channels)) - return -ENXIO; - - width = snd_pcm_format_physical_width(src_format->format); - if (snd_BUG_ON(width <= 0)) - return -ENXIO; - - err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format, - 0, &plugin); - if (err < 0) - return err; - plugin->transfer = copy_transfer; - *r_plugin = plugin; - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/oss/io.c b/ANDROID_3.4.5/sound/core/oss/io.c deleted file mode 100644 index 6faa1d71..00000000 --- a/ANDROID_3.4.5/sound/core/oss/io.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * PCM I/O Plug-In Interface - * Copyright (c) 1999 by Jaroslav Kysela - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include "pcm_plugin.h" - -#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1) -#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1) -#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1) -#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1) - -/* - * Basic io plugin - */ - -static snd_pcm_sframes_t io_playback_transfer(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - if (snd_BUG_ON(!plugin)) - return -ENXIO; - if (snd_BUG_ON(!src_channels)) - return -ENXIO; - if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { - return pcm_write(plugin->plug, src_channels->area.addr, frames); - } else { - int channel, channels = plugin->dst_format.channels; - void **bufs = (void**)plugin->extra_data; - if (snd_BUG_ON(!bufs)) - return -ENXIO; - for (channel = 0; channel < channels; channel++) { - if (src_channels[channel].enabled) - bufs[channel] = src_channels[channel].area.addr; - else - bufs[channel] = NULL; - } - return pcm_writev(plugin->plug, bufs, frames); - } -} - -static snd_pcm_sframes_t io_capture_transfer(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - if (snd_BUG_ON(!plugin)) - return -ENXIO; - if (snd_BUG_ON(!dst_channels)) - return -ENXIO; - if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { - return pcm_read(plugin->plug, dst_channels->area.addr, frames); - } else { - int channel, channels = plugin->dst_format.channels; - void **bufs = (void**)plugin->extra_data; - if (snd_BUG_ON(!bufs)) - return -ENXIO; - for (channel = 0; channel < channels; channel++) { - if (dst_channels[channel].enabled) - bufs[channel] = dst_channels[channel].area.addr; - else - bufs[channel] = NULL; - } - return pcm_readv(plugin->plug, bufs, frames); - } - return 0; -} - -static snd_pcm_sframes_t io_src_channels(struct snd_pcm_plugin *plugin, - snd_pcm_uframes_t frames, - struct snd_pcm_plugin_channel **channels) -{ - int err; - unsigned int channel; - struct snd_pcm_plugin_channel *v; - err = snd_pcm_plugin_client_channels(plugin, frames, &v); - if (err < 0) - return err; - *channels = v; - if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { - for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v) - v->wanted = 1; - } - return frames; -} - -int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug, - struct snd_pcm_hw_params *params, - struct snd_pcm_plugin **r_plugin) -{ - int err; - struct snd_pcm_plugin_format format; - struct snd_pcm_plugin *plugin; - - if (snd_BUG_ON(!r_plugin)) - return -ENXIO; - *r_plugin = NULL; - if (snd_BUG_ON(!plug || !params)) - return -ENXIO; - format.format = params_format(params); - format.rate = params_rate(params); - format.channels = params_channels(params); - err = snd_pcm_plugin_build(plug, "I/O io", - &format, &format, - sizeof(void *) * format.channels, - &plugin); - if (err < 0) - return err; - plugin->access = params_access(params); - if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) { - plugin->transfer = io_playback_transfer; - if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) - plugin->client_channels = io_src_channels; - } else { - plugin->transfer = io_capture_transfer; - } - - *r_plugin = plugin; - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/oss/linear.c b/ANDROID_3.4.5/sound/core/oss/linear.c deleted file mode 100644 index 2045697f..00000000 --- a/ANDROID_3.4.5/sound/core/oss/linear.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Linear conversion Plug-In - * Copyright (c) 1999 by Jaroslav Kysela , - * Abramo Bagnara - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include "pcm_plugin.h" - -/* - * Basic linear conversion plugin - */ - -struct linear_priv { - int cvt_endian; /* need endian conversion? */ - unsigned int src_ofs; /* byte offset in source format */ - unsigned int dst_ofs; /* byte soffset in destination format */ - unsigned int copy_ofs; /* byte offset in temporary u32 data */ - unsigned int dst_bytes; /* byte size of destination format */ - unsigned int copy_bytes; /* bytes to copy per conversion */ - unsigned int flip; /* MSB flip for signeness, done after endian conv */ -}; - -static inline void do_convert(struct linear_priv *data, - unsigned char *dst, unsigned char *src) -{ - unsigned int tmp = 0; - unsigned char *p = (unsigned char *)&tmp; - - memcpy(p + data->copy_ofs, src + data->src_ofs, data->copy_bytes); - if (data->cvt_endian) - tmp = swab32(tmp); - tmp ^= data->flip; - memcpy(dst, p + data->dst_ofs, data->dst_bytes); -} - -static void convert(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - struct linear_priv *data = (struct linear_priv *)plugin->extra_data; - int channel; - int nchannels = plugin->src_format.channels; - for (channel = 0; channel < nchannels; ++channel) { - char *src; - char *dst; - int src_step, dst_step; - snd_pcm_uframes_t frames1; - if (!src_channels[channel].enabled) { - if (dst_channels[channel].wanted) - snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format); - dst_channels[channel].enabled = 0; - continue; - } - dst_channels[channel].enabled = 1; - src = src_channels[channel].area.addr + src_channels[channel].area.first / 8; - dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8; - src_step = src_channels[channel].area.step / 8; - dst_step = dst_channels[channel].area.step / 8; - frames1 = frames; - while (frames1-- > 0) { - do_convert(data, dst, src); - src += src_step; - dst += dst_step; - } - } -} - -static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) - return -ENXIO; - if (frames == 0) - return 0; -#ifdef CONFIG_SND_DEBUG - { - unsigned int channel; - for (channel = 0; channel < plugin->src_format.channels; channel++) { - if (snd_BUG_ON(src_channels[channel].area.first % 8 || - src_channels[channel].area.step % 8)) - return -ENXIO; - if (snd_BUG_ON(dst_channels[channel].area.first % 8 || - dst_channels[channel].area.step % 8)) - return -ENXIO; - } - } -#endif - convert(plugin, src_channels, dst_channels, frames); - return frames; -} - -static void init_data(struct linear_priv *data, - snd_pcm_format_t src_format, snd_pcm_format_t dst_format) -{ - int src_le, dst_le, src_bytes, dst_bytes; - - src_bytes = snd_pcm_format_width(src_format) / 8; - dst_bytes = snd_pcm_format_width(dst_format) / 8; - src_le = snd_pcm_format_little_endian(src_format) > 0; - dst_le = snd_pcm_format_little_endian(dst_format) > 0; - - data->dst_bytes = dst_bytes; - data->cvt_endian = src_le != dst_le; - data->copy_bytes = src_bytes < dst_bytes ? src_bytes : dst_bytes; - if (src_le) { - data->copy_ofs = 4 - data->copy_bytes; - data->src_ofs = src_bytes - data->copy_bytes; - } else - data->src_ofs = snd_pcm_format_physical_width(src_format) / 8 - - src_bytes; - if (dst_le) - data->dst_ofs = 4 - data->dst_bytes; - else - data->dst_ofs = snd_pcm_format_physical_width(dst_format) / 8 - - dst_bytes; - if (snd_pcm_format_signed(src_format) != - snd_pcm_format_signed(dst_format)) { - if (dst_le) - data->flip = (__force u32)cpu_to_le32(0x80000000); - else - data->flip = (__force u32)cpu_to_be32(0x80000000); - } -} - -int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin) -{ - int err; - struct linear_priv *data; - struct snd_pcm_plugin *plugin; - - if (snd_BUG_ON(!r_plugin)) - return -ENXIO; - *r_plugin = NULL; - - if (snd_BUG_ON(src_format->rate != dst_format->rate)) - return -ENXIO; - if (snd_BUG_ON(src_format->channels != dst_format->channels)) - return -ENXIO; - if (snd_BUG_ON(!snd_pcm_format_linear(src_format->format) || - !snd_pcm_format_linear(dst_format->format))) - return -ENXIO; - - err = snd_pcm_plugin_build(plug, "linear format conversion", - src_format, dst_format, - sizeof(struct linear_priv), &plugin); - if (err < 0) - return err; - data = (struct linear_priv *)plugin->extra_data; - init_data(data, src_format->format, dst_format->format); - plugin->transfer = linear_transfer; - *r_plugin = plugin; - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/oss/mixer_oss.c b/ANDROID_3.4.5/sound/core/oss/mixer_oss.c deleted file mode 100644 index c3537688..00000000 --- a/ANDROID_3.4.5/sound/core/oss/mixer_oss.c +++ /dev/null @@ -1,1422 +0,0 @@ -/* - * OSS emulation layer for the mixer interface - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include - -#define OSS_ALSAEMULVER _SIOR ('M', 249, int) - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Mixer OSS emulation for ALSA."); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER); - -static int snd_mixer_oss_open(struct inode *inode, struct file *file) -{ - struct snd_card *card; - struct snd_mixer_oss_file *fmixer; - int err; - - err = nonseekable_open(inode, file); - if (err < 0) - return err; - - card = snd_lookup_oss_minor_data(iminor(inode), - SNDRV_OSS_DEVICE_TYPE_MIXER); - if (card == NULL) - return -ENODEV; - if (card->mixer_oss == NULL) { - snd_card_unref(card); - return -ENODEV; - } - err = snd_card_file_add(card, file); - if (err < 0) { - snd_card_unref(card); - return err; - } - fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); - if (fmixer == NULL) { - snd_card_file_remove(card, file); - snd_card_unref(card); - return -ENOMEM; - } - fmixer->card = card; - fmixer->mixer = card->mixer_oss; - file->private_data = fmixer; - if (!try_module_get(card->module)) { - kfree(fmixer); - snd_card_file_remove(card, file); - snd_card_unref(card); - return -EFAULT; - } - snd_card_unref(card); - return 0; -} - -static int snd_mixer_oss_release(struct inode *inode, struct file *file) -{ - struct snd_mixer_oss_file *fmixer; - - if (file->private_data) { - fmixer = file->private_data; - module_put(fmixer->card->module); - snd_card_file_remove(fmixer->card, file); - kfree(fmixer); - } - return 0; -} - -static int snd_mixer_oss_info(struct snd_mixer_oss_file *fmixer, - mixer_info __user *_info) -{ - struct snd_card *card = fmixer->card; - struct snd_mixer_oss *mixer = fmixer->mixer; - struct mixer_info info; - - memset(&info, 0, sizeof(info)); - strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); - strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); - info.modify_counter = card->mixer_oss_change_count; - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int snd_mixer_oss_info_obsolete(struct snd_mixer_oss_file *fmixer, - _old_mixer_info __user *_info) -{ - struct snd_card *card = fmixer->card; - struct snd_mixer_oss *mixer = fmixer->mixer; - _old_mixer_info info; - - memset(&info, 0, sizeof(info)); - strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id)); - strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name)); - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int snd_mixer_oss_caps(struct snd_mixer_oss_file *fmixer) -{ - struct snd_mixer_oss *mixer = fmixer->mixer; - int result = 0; - - if (mixer == NULL) - return -EIO; - if (mixer->get_recsrc && mixer->put_recsrc) - result |= SOUND_CAP_EXCL_INPUT; - return result; -} - -static int snd_mixer_oss_devmask(struct snd_mixer_oss_file *fmixer) -{ - struct snd_mixer_oss *mixer = fmixer->mixer; - struct snd_mixer_oss_slot *pslot; - int result = 0, chn; - - if (mixer == NULL) - return -EIO; - for (chn = 0; chn < 31; chn++) { - pslot = &mixer->slots[chn]; - if (pslot->put_volume || pslot->put_recsrc) - result |= 1 << chn; - } - return result; -} - -static int snd_mixer_oss_stereodevs(struct snd_mixer_oss_file *fmixer) -{ - struct snd_mixer_oss *mixer = fmixer->mixer; - struct snd_mixer_oss_slot *pslot; - int result = 0, chn; - - if (mixer == NULL) - return -EIO; - for (chn = 0; chn < 31; chn++) { - pslot = &mixer->slots[chn]; - if (pslot->put_volume && pslot->stereo) - result |= 1 << chn; - } - return result; -} - -static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer) -{ - struct snd_mixer_oss *mixer = fmixer->mixer; - int result = 0; - - if (mixer == NULL) - return -EIO; - if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ - result = mixer->mask_recsrc; - } else { - struct snd_mixer_oss_slot *pslot; - int chn; - for (chn = 0; chn < 31; chn++) { - pslot = &mixer->slots[chn]; - if (pslot->put_recsrc) - result |= 1 << chn; - } - } - return result; -} - -static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) -{ - struct snd_mixer_oss *mixer = fmixer->mixer; - int result = 0; - - if (mixer == NULL) - return -EIO; - if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ - int err; - unsigned int index; - if ((err = mixer->get_recsrc(fmixer, &index)) < 0) - return err; - result = 1 << index; - } else { - struct snd_mixer_oss_slot *pslot; - int chn; - for (chn = 0; chn < 31; chn++) { - pslot = &mixer->slots[chn]; - if (pslot->get_recsrc) { - int active = 0; - pslot->get_recsrc(fmixer, pslot, &active); - if (active) - result |= 1 << chn; - } - } - } - return mixer->oss_recsrc = result; -} - -static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc) -{ - struct snd_mixer_oss *mixer = fmixer->mixer; - struct snd_mixer_oss_slot *pslot; - int chn, active; - unsigned int index; - int result = 0; - - if (mixer == NULL) - return -EIO; - if (mixer->get_recsrc && mixer->put_recsrc) { /* exclusive input */ - if (recsrc & ~mixer->oss_recsrc) - recsrc &= ~mixer->oss_recsrc; - mixer->put_recsrc(fmixer, ffz(~recsrc)); - mixer->get_recsrc(fmixer, &index); - result = 1 << index; - } - for (chn = 0; chn < 31; chn++) { - pslot = &mixer->slots[chn]; - if (pslot->put_recsrc) { - active = (recsrc & (1 << chn)) ? 1 : 0; - pslot->put_recsrc(fmixer, pslot, active); - } - } - if (! result) { - for (chn = 0; chn < 31; chn++) { - pslot = &mixer->slots[chn]; - if (pslot->get_recsrc) { - active = 0; - pslot->get_recsrc(fmixer, pslot, &active); - if (active) - result |= 1 << chn; - } - } - } - return result; -} - -static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot) -{ - struct snd_mixer_oss *mixer = fmixer->mixer; - struct snd_mixer_oss_slot *pslot; - int result = 0, left, right; - - if (mixer == NULL || slot > 30) - return -EIO; - pslot = &mixer->slots[slot]; - left = pslot->volume[0]; - right = pslot->volume[1]; - if (pslot->get_volume) - result = pslot->get_volume(fmixer, pslot, &left, &right); - if (!pslot->stereo) - right = left; - if (snd_BUG_ON(left < 0 || left > 100)) - return -EIO; - if (snd_BUG_ON(right < 0 || right > 100)) - return -EIO; - if (result >= 0) { - pslot->volume[0] = left; - pslot->volume[1] = right; - result = (left & 0xff) | ((right & 0xff) << 8); - } - return result; -} - -static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer, - int slot, int volume) -{ - struct snd_mixer_oss *mixer = fmixer->mixer; - struct snd_mixer_oss_slot *pslot; - int result = 0, left = volume & 0xff, right = (volume >> 8) & 0xff; - - if (mixer == NULL || slot > 30) - return -EIO; - pslot = &mixer->slots[slot]; - if (left > 100) - left = 100; - if (right > 100) - right = 100; - if (!pslot->stereo) - right = left; - if (pslot->put_volume) - result = pslot->put_volume(fmixer, pslot, left, right); - if (result < 0) - return result; - pslot->volume[0] = left; - pslot->volume[1] = right; - return (left & 0xff) | ((right & 0xff) << 8); -} - -static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - int tmp; - - if (snd_BUG_ON(!fmixer)) - return -ENXIO; - if (((cmd >> 8) & 0xff) == 'M') { - switch (cmd) { - case SOUND_MIXER_INFO: - return snd_mixer_oss_info(fmixer, argp); - case SOUND_OLD_MIXER_INFO: - return snd_mixer_oss_info_obsolete(fmixer, argp); - case SOUND_MIXER_WRITE_RECSRC: - if (get_user(tmp, p)) - return -EFAULT; - tmp = snd_mixer_oss_set_recsrc(fmixer, tmp); - if (tmp < 0) - return tmp; - return put_user(tmp, p); - case OSS_GETVERSION: - return put_user(SNDRV_OSS_VERSION, p); - case OSS_ALSAEMULVER: - return put_user(1, p); - case SOUND_MIXER_READ_DEVMASK: - tmp = snd_mixer_oss_devmask(fmixer); - if (tmp < 0) - return tmp; - return put_user(tmp, p); - case SOUND_MIXER_READ_STEREODEVS: - tmp = snd_mixer_oss_stereodevs(fmixer); - if (tmp < 0) - return tmp; - return put_user(tmp, p); - case SOUND_MIXER_READ_RECMASK: - tmp = snd_mixer_oss_recmask(fmixer); - if (tmp < 0) - return tmp; - return put_user(tmp, p); - case SOUND_MIXER_READ_CAPS: - tmp = snd_mixer_oss_caps(fmixer); - if (tmp < 0) - return tmp; - return put_user(tmp, p); - case SOUND_MIXER_READ_RECSRC: - tmp = snd_mixer_oss_get_recsrc(fmixer); - if (tmp < 0) - return tmp; - return put_user(tmp, p); - } - } - if (cmd & SIOC_IN) { - if (get_user(tmp, p)) - return -EFAULT; - tmp = snd_mixer_oss_set_volume(fmixer, cmd & 0xff, tmp); - if (tmp < 0) - return tmp; - return put_user(tmp, p); - } else if (cmd & SIOC_OUT) { - tmp = snd_mixer_oss_get_volume(fmixer, cmd & 0xff); - if (tmp < 0) - return tmp; - return put_user(tmp, p); - } - return -ENXIO; -} - -static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return snd_mixer_oss_ioctl1(file->private_data, cmd, arg); -} - -int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg) -{ - struct snd_mixer_oss_file fmixer; - - if (snd_BUG_ON(!card)) - return -ENXIO; - if (card->mixer_oss == NULL) - return -ENXIO; - memset(&fmixer, 0, sizeof(fmixer)); - fmixer.card = card; - fmixer.mixer = card->mixer_oss; - return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); -} - -#ifdef CONFIG_COMPAT -/* all compatible */ -#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl -#else -#define snd_mixer_oss_ioctl_compat NULL -#endif - -/* - * REGISTRATION PART - */ - -static const struct file_operations snd_mixer_oss_f_ops = -{ - .owner = THIS_MODULE, - .open = snd_mixer_oss_open, - .release = snd_mixer_oss_release, - .llseek = no_llseek, - .unlocked_ioctl = snd_mixer_oss_ioctl, - .compat_ioctl = snd_mixer_oss_ioctl_compat, -}; - -/* - * utilities - */ - -static long snd_mixer_oss_conv(long val, long omin, long omax, long nmin, long nmax) -{ - long orange = omax - omin, nrange = nmax - nmin; - - if (orange == 0) - return 0; - return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin; -} - -/* convert from alsa native to oss values (0-100) */ -static long snd_mixer_oss_conv1(long val, long min, long max, int *old) -{ - if (val == snd_mixer_oss_conv(*old, 0, 100, min, max)) - return *old; - return snd_mixer_oss_conv(val, min, max, 0, 100); -} - -/* convert from oss to alsa native values */ -static long snd_mixer_oss_conv2(long val, long min, long max) -{ - return snd_mixer_oss_conv(val, 0, 100, min, max); -} - -#if 0 -static void snd_mixer_oss_recsrce_set(struct snd_card *card, int slot) -{ - struct snd_mixer_oss *mixer = card->mixer_oss; - if (mixer) - mixer->mask_recsrc |= 1 << slot; -} - -static int snd_mixer_oss_recsrce_get(struct snd_card *card, int slot) -{ - struct snd_mixer_oss *mixer = card->mixer_oss; - if (mixer && (mixer->mask_recsrc & (1 << slot))) - return 1; - return 0; -} -#endif - -#define SNDRV_MIXER_OSS_SIGNATURE 0x65999250 - -#define SNDRV_MIXER_OSS_ITEM_GLOBAL 0 -#define SNDRV_MIXER_OSS_ITEM_GSWITCH 1 -#define SNDRV_MIXER_OSS_ITEM_GROUTE 2 -#define SNDRV_MIXER_OSS_ITEM_GVOLUME 3 -#define SNDRV_MIXER_OSS_ITEM_PSWITCH 4 -#define SNDRV_MIXER_OSS_ITEM_PROUTE 5 -#define SNDRV_MIXER_OSS_ITEM_PVOLUME 6 -#define SNDRV_MIXER_OSS_ITEM_CSWITCH 7 -#define SNDRV_MIXER_OSS_ITEM_CROUTE 8 -#define SNDRV_MIXER_OSS_ITEM_CVOLUME 9 -#define SNDRV_MIXER_OSS_ITEM_CAPTURE 10 - -#define SNDRV_MIXER_OSS_ITEM_COUNT 11 - -#define SNDRV_MIXER_OSS_PRESENT_GLOBAL (1<<0) -#define SNDRV_MIXER_OSS_PRESENT_GSWITCH (1<<1) -#define SNDRV_MIXER_OSS_PRESENT_GROUTE (1<<2) -#define SNDRV_MIXER_OSS_PRESENT_GVOLUME (1<<3) -#define SNDRV_MIXER_OSS_PRESENT_PSWITCH (1<<4) -#define SNDRV_MIXER_OSS_PRESENT_PROUTE (1<<5) -#define SNDRV_MIXER_OSS_PRESENT_PVOLUME (1<<6) -#define SNDRV_MIXER_OSS_PRESENT_CSWITCH (1<<7) -#define SNDRV_MIXER_OSS_PRESENT_CROUTE (1<<8) -#define SNDRV_MIXER_OSS_PRESENT_CVOLUME (1<<9) -#define SNDRV_MIXER_OSS_PRESENT_CAPTURE (1<<10) - -struct slot { - unsigned int signature; - unsigned int present; - unsigned int channels; - unsigned int numid[SNDRV_MIXER_OSS_ITEM_COUNT]; - unsigned int capture_item; - struct snd_mixer_oss_assign_table *assigned; - unsigned int allocated: 1; -}; - -#define ID_UNKNOWN ((unsigned int)-1) - -static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, const char *name, int index) -{ - struct snd_card *card = mixer->card; - struct snd_ctl_elem_id id; - - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strlcpy(id.name, name, sizeof(id.name)); - id.index = index; - return snd_ctl_find_id(card, &id); -} - -static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - unsigned int numid, - int *left, int *right) -{ - struct snd_ctl_elem_info *uinfo; - struct snd_ctl_elem_value *uctl; - struct snd_kcontrol *kctl; - struct snd_card *card = fmixer->card; - - if (numid == ID_UNKNOWN) - return; - down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { - up_read(&card->controls_rwsem); - return; - } - uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); - uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); - if (uinfo == NULL || uctl == NULL) - goto __unalloc; - if (kctl->info(kctl, uinfo)) - goto __unalloc; - if (kctl->get(kctl, uctl)) - goto __unalloc; - if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && - uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1) - goto __unalloc; - *left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]); - if (uinfo->count > 1) - *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]); - __unalloc: - up_read(&card->controls_rwsem); - kfree(uctl); - kfree(uinfo); -} - -static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - unsigned int numid, - int *left, int *right, - int route) -{ - struct snd_ctl_elem_info *uinfo; - struct snd_ctl_elem_value *uctl; - struct snd_kcontrol *kctl; - struct snd_card *card = fmixer->card; - - if (numid == ID_UNKNOWN) - return; - down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { - up_read(&card->controls_rwsem); - return; - } - uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); - uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); - if (uinfo == NULL || uctl == NULL) - goto __unalloc; - if (kctl->info(kctl, uinfo)) - goto __unalloc; - if (kctl->get(kctl, uctl)) - goto __unalloc; - if (!uctl->value.integer.value[0]) { - *left = 0; - if (uinfo->count == 1) - *right = 0; - } - if (uinfo->count > 1 && !uctl->value.integer.value[route ? 3 : 1]) - *right = 0; - __unalloc: - up_read(&card->controls_rwsem); - kfree(uctl); - kfree(uinfo); -} - -static int snd_mixer_oss_get_volume1(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - int *left, int *right) -{ - struct slot *slot = pslot->private_data; - - *left = *right = 100; - if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) { - snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) { - snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) { - snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right); - } - if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) { - snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) { - snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) { - snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) { - snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); - } - return 0; -} - -static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - unsigned int numid, - int left, int right) -{ - struct snd_ctl_elem_info *uinfo; - struct snd_ctl_elem_value *uctl; - struct snd_kcontrol *kctl; - struct snd_card *card = fmixer->card; - int res; - - if (numid == ID_UNKNOWN) - return; - down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { - up_read(&card->controls_rwsem); - return; - } - uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); - uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); - if (uinfo == NULL || uctl == NULL) - goto __unalloc; - if (kctl->info(kctl, uinfo)) - goto __unalloc; - if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && - uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1) - goto __unalloc; - uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max); - if (uinfo->count > 1) - uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max); - if ((res = kctl->put(kctl, uctl)) < 0) - goto __unalloc; - if (res > 0) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); - __unalloc: - up_read(&card->controls_rwsem); - kfree(uctl); - kfree(uinfo); -} - -static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - unsigned int numid, - int left, int right, - int route) -{ - struct snd_ctl_elem_info *uinfo; - struct snd_ctl_elem_value *uctl; - struct snd_kcontrol *kctl; - struct snd_card *card = fmixer->card; - int res; - - if (numid == ID_UNKNOWN) - return; - down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { - up_read(&card->controls_rwsem); - return; - } - uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); - uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); - if (uinfo == NULL || uctl == NULL) - goto __unalloc; - if (kctl->info(kctl, uinfo)) - goto __unalloc; - if (uinfo->count > 1) { - uctl->value.integer.value[0] = left > 0 ? 1 : 0; - uctl->value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0; - if (route) { - uctl->value.integer.value[1] = - uctl->value.integer.value[2] = 0; - } - } else { - uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0; - } - if ((res = kctl->put(kctl, uctl)) < 0) - goto __unalloc; - if (res > 0) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); - __unalloc: - up_read(&card->controls_rwsem); - kfree(uctl); - kfree(uinfo); -} - -static int snd_mixer_oss_put_volume1(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - int left, int right) -{ - struct slot *slot = pslot->private_data; - - if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) { - snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right); - if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME) - snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME) { - snd_mixer_oss_put_volume1_vol(fmixer, pslot, - slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) { - snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) { - snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right); - } - if (left || right) { - if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); - if (slot->present & SNDRV_MIXER_OSS_PRESENT_CSWITCH) - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], left, right, 0); - if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); - if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); - if (slot->present & SNDRV_MIXER_OSS_PRESENT_CROUTE) - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], left, right, 1); - if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); - } else { - if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) { - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CSWITCH) { - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], left, right, 0); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) { - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) { - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_CROUTE) { - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], left, right, 1); - } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) { - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); - } - } - return 0; -} - -static int snd_mixer_oss_get_recsrc1_sw(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - int *active) -{ - struct slot *slot = pslot->private_data; - int left, right; - - left = right = 1; - snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], &left, &right, 0); - *active = (left || right) ? 1 : 0; - return 0; -} - -static int snd_mixer_oss_get_recsrc1_route(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - int *active) -{ - struct slot *slot = pslot->private_data; - int left, right; - - left = right = 1; - snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], &left, &right, 1); - *active = (left || right) ? 1 : 0; - return 0; -} - -static int snd_mixer_oss_put_recsrc1_sw(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - int active) -{ - struct slot *slot = pslot->private_data; - - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0); - return 0; -} - -static int snd_mixer_oss_put_recsrc1_route(struct snd_mixer_oss_file *fmixer, - struct snd_mixer_oss_slot *pslot, - int active) -{ - struct slot *slot = pslot->private_data; - - snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1); - return 0; -} - -static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned int *active_index) -{ - struct snd_card *card = fmixer->card; - struct snd_mixer_oss *mixer = fmixer->mixer; - struct snd_kcontrol *kctl; - struct snd_mixer_oss_slot *pslot; - struct slot *slot; - struct snd_ctl_elem_info *uinfo; - struct snd_ctl_elem_value *uctl; - int err, idx; - - uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); - uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); - if (uinfo == NULL || uctl == NULL) { - err = -ENOMEM; - goto __free_only; - } - down_read(&card->controls_rwsem); - kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); - if (! kctl) { - err = -ENOENT; - goto __unlock; - } - if ((err = kctl->info(kctl, uinfo)) < 0) - goto __unlock; - if ((err = kctl->get(kctl, uctl)) < 0) - goto __unlock; - for (idx = 0; idx < 32; idx++) { - if (!(mixer->mask_recsrc & (1 << idx))) - continue; - pslot = &mixer->slots[idx]; - slot = pslot->private_data; - if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE) - continue; - if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE)) - continue; - if (slot->capture_item == uctl->value.enumerated.item[0]) { - *active_index = idx; - break; - } - } - err = 0; - __unlock: - up_read(&card->controls_rwsem); - __free_only: - kfree(uctl); - kfree(uinfo); - return err; -} - -static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned int active_index) -{ - struct snd_card *card = fmixer->card; - struct snd_mixer_oss *mixer = fmixer->mixer; - struct snd_kcontrol *kctl; - struct snd_mixer_oss_slot *pslot; - struct slot *slot = NULL; - struct snd_ctl_elem_info *uinfo; - struct snd_ctl_elem_value *uctl; - int err; - unsigned int idx; - - uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); - uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); - if (uinfo == NULL || uctl == NULL) { - err = -ENOMEM; - goto __free_only; - } - down_read(&card->controls_rwsem); - kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); - if (! kctl) { - err = -ENOENT; - goto __unlock; - } - if ((err = kctl->info(kctl, uinfo)) < 0) - goto __unlock; - for (idx = 0; idx < 32; idx++) { - if (!(mixer->mask_recsrc & (1 << idx))) - continue; - pslot = &mixer->slots[idx]; - slot = pslot->private_data; - if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE) - continue; - if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE)) - continue; - if (idx == active_index) - break; - slot = NULL; - } - if (! slot) - goto __unlock; - for (idx = 0; idx < uinfo->count; idx++) - uctl->value.enumerated.item[idx] = slot->capture_item; - err = kctl->put(kctl, uctl); - if (err > 0) - snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); - err = 0; - __unlock: - up_read(&card->controls_rwsem); - __free_only: - kfree(uctl); - kfree(uinfo); - return err; -} - -struct snd_mixer_oss_assign_table { - int oss_id; - const char *name; - int index; -}; - -static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *slot, const char *name, int index, int item) -{ - struct snd_ctl_elem_info *info; - struct snd_kcontrol *kcontrol; - struct snd_card *card = mixer->card; - int err; - - down_read(&card->controls_rwsem); - kcontrol = snd_mixer_oss_test_id(mixer, name, index); - if (kcontrol == NULL) { - up_read(&card->controls_rwsem); - return 0; - } - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) { - up_read(&card->controls_rwsem); - return -ENOMEM; - } - if ((err = kcontrol->info(kcontrol, info)) < 0) { - up_read(&card->controls_rwsem); - kfree(info); - return err; - } - slot->numid[item] = kcontrol->id.numid; - up_read(&card->controls_rwsem); - if (info->count > slot->channels) - slot->channels = info->count; - slot->present |= 1 << item; - kfree(info); - return 0; -} - -static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn) -{ - struct slot *p = chn->private_data; - if (p) { - if (p->allocated && p->assigned) { - kfree(p->assigned->name); - kfree(p->assigned); - } - kfree(p); - } -} - -static void mixer_slot_clear(struct snd_mixer_oss_slot *rslot) -{ - int idx = rslot->number; /* remember this */ - if (rslot->private_free) - rslot->private_free(rslot); - memset(rslot, 0, sizeof(*rslot)); - rslot->number = idx; -} - -/* In a separate function to keep gcc 3.2 happy - do NOT merge this in - snd_mixer_oss_build_input! */ -static int snd_mixer_oss_build_test_all(struct snd_mixer_oss *mixer, - struct snd_mixer_oss_assign_table *ptr, - struct slot *slot) -{ - char str[64]; - int err; - - err = snd_mixer_oss_build_test(mixer, slot, ptr->name, ptr->index, - SNDRV_MIXER_OSS_ITEM_GLOBAL); - if (err) - return err; - sprintf(str, "%s Switch", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_GSWITCH); - if (err) - return err; - sprintf(str, "%s Route", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_GROUTE); - if (err) - return err; - sprintf(str, "%s Volume", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_GVOLUME); - if (err) - return err; - sprintf(str, "%s Playback Switch", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_PSWITCH); - if (err) - return err; - sprintf(str, "%s Playback Route", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_PROUTE); - if (err) - return err; - sprintf(str, "%s Playback Volume", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_PVOLUME); - if (err) - return err; - sprintf(str, "%s Capture Switch", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_CSWITCH); - if (err) - return err; - sprintf(str, "%s Capture Route", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_CROUTE); - if (err) - return err; - sprintf(str, "%s Capture Volume", ptr->name); - err = snd_mixer_oss_build_test(mixer, slot, str, ptr->index, - SNDRV_MIXER_OSS_ITEM_CVOLUME); - if (err) - return err; - - return 0; -} - -/* - * build an OSS mixer element. - * ptr_allocated means the entry is dynamically allocated (change via proc file). - * when replace_old = 1, the old entry is replaced with the new one. - */ -static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mixer_oss_assign_table *ptr, int ptr_allocated, int replace_old) -{ - struct slot slot; - struct slot *pslot; - struct snd_kcontrol *kctl; - struct snd_mixer_oss_slot *rslot; - char str[64]; - - /* check if already assigned */ - if (mixer->slots[ptr->oss_id].get_volume && ! replace_old) - return 0; - - memset(&slot, 0, sizeof(slot)); - memset(slot.numid, 0xff, sizeof(slot.numid)); /* ID_UNKNOWN */ - if (snd_mixer_oss_build_test_all(mixer, ptr, &slot)) - return 0; - down_read(&mixer->card->controls_rwsem); - if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) { - struct snd_ctl_elem_info *uinfo; - - uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); - if (! uinfo) { - up_read(&mixer->card->controls_rwsem); - return -ENOMEM; - } - - if (kctl->info(kctl, uinfo)) { - up_read(&mixer->card->controls_rwsem); - return 0; - } - strcpy(str, ptr->name); - if (!strcmp(str, "Master")) - strcpy(str, "Mix"); - if (!strcmp(str, "Master Mono")) - strcpy(str, "Mix Mono"); - slot.capture_item = 0; - if (!strcmp(uinfo->value.enumerated.name, str)) { - slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE; - } else { - for (slot.capture_item = 1; slot.capture_item < uinfo->value.enumerated.items; slot.capture_item++) { - uinfo->value.enumerated.item = slot.capture_item; - if (kctl->info(kctl, uinfo)) { - up_read(&mixer->card->controls_rwsem); - return 0; - } - if (!strcmp(uinfo->value.enumerated.name, str)) { - slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE; - break; - } - } - } - kfree(uinfo); - } - up_read(&mixer->card->controls_rwsem); - if (slot.present != 0) { - pslot = kmalloc(sizeof(slot), GFP_KERNEL); - if (! pslot) - return -ENOMEM; - *pslot = slot; - pslot->signature = SNDRV_MIXER_OSS_SIGNATURE; - pslot->assigned = ptr; - pslot->allocated = ptr_allocated; - rslot = &mixer->slots[ptr->oss_id]; - mixer_slot_clear(rslot); - rslot->stereo = slot.channels > 1 ? 1 : 0; - rslot->get_volume = snd_mixer_oss_get_volume1; - rslot->put_volume = snd_mixer_oss_put_volume1; - /* note: ES18xx have both Capture Source and XX Capture Volume !!! */ - if (slot.present & SNDRV_MIXER_OSS_PRESENT_CSWITCH) { - rslot->get_recsrc = snd_mixer_oss_get_recsrc1_sw; - rslot->put_recsrc = snd_mixer_oss_put_recsrc1_sw; - } else if (slot.present & SNDRV_MIXER_OSS_PRESENT_CROUTE) { - rslot->get_recsrc = snd_mixer_oss_get_recsrc1_route; - rslot->put_recsrc = snd_mixer_oss_put_recsrc1_route; - } else if (slot.present & SNDRV_MIXER_OSS_PRESENT_CAPTURE) { - mixer->mask_recsrc |= 1 << ptr->oss_id; - } - rslot->private_data = pslot; - rslot->private_free = snd_mixer_oss_slot_free; - return 1; - } - return 0; -} - -#ifdef CONFIG_PROC_FS -/* - */ -#define MIXER_VOL(name) [SOUND_MIXER_##name] = #name -static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = { - MIXER_VOL(VOLUME), - MIXER_VOL(BASS), - MIXER_VOL(TREBLE), - MIXER_VOL(SYNTH), - MIXER_VOL(PCM), - MIXER_VOL(SPEAKER), - MIXER_VOL(LINE), - MIXER_VOL(MIC), - MIXER_VOL(CD), - MIXER_VOL(IMIX), - MIXER_VOL(ALTPCM), - MIXER_VOL(RECLEV), - MIXER_VOL(IGAIN), - MIXER_VOL(OGAIN), - MIXER_VOL(LINE1), - MIXER_VOL(LINE2), - MIXER_VOL(LINE3), - MIXER_VOL(DIGITAL1), - MIXER_VOL(DIGITAL2), - MIXER_VOL(DIGITAL3), - MIXER_VOL(PHONEIN), - MIXER_VOL(PHONEOUT), - MIXER_VOL(VIDEO), - MIXER_VOL(RADIO), - MIXER_VOL(MONITOR), -}; - -/* - * /proc interface - */ - -static void snd_mixer_oss_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_mixer_oss *mixer = entry->private_data; - int i; - - mutex_lock(&mixer->reg_mutex); - for (i = 0; i < SNDRV_OSS_MAX_MIXERS; i++) { - struct slot *p; - - if (! oss_mixer_names[i]) - continue; - p = (struct slot *)mixer->slots[i].private_data; - snd_iprintf(buffer, "%s ", oss_mixer_names[i]); - if (p && p->assigned) - snd_iprintf(buffer, "\"%s\" %d\n", - p->assigned->name, - p->assigned->index); - else - snd_iprintf(buffer, "\"\" 0\n"); - } - mutex_unlock(&mixer->reg_mutex); -} - -static void snd_mixer_oss_proc_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_mixer_oss *mixer = entry->private_data; - char line[128], str[32], idxstr[16]; - const char *cptr; - int ch, idx; - struct snd_mixer_oss_assign_table *tbl; - struct slot *slot; - - while (!snd_info_get_line(buffer, line, sizeof(line))) { - cptr = snd_info_get_str(str, line, sizeof(str)); - for (ch = 0; ch < SNDRV_OSS_MAX_MIXERS; ch++) - if (oss_mixer_names[ch] && strcmp(oss_mixer_names[ch], str) == 0) - break; - if (ch >= SNDRV_OSS_MAX_MIXERS) { - snd_printk(KERN_ERR "mixer_oss: invalid OSS volume '%s'\n", str); - continue; - } - cptr = snd_info_get_str(str, cptr, sizeof(str)); - if (! *str) { - /* remove the entry */ - mutex_lock(&mixer->reg_mutex); - mixer_slot_clear(&mixer->slots[ch]); - mutex_unlock(&mixer->reg_mutex); - continue; - } - snd_info_get_str(idxstr, cptr, sizeof(idxstr)); - idx = simple_strtoul(idxstr, NULL, 10); - if (idx >= 0x4000) { /* too big */ - snd_printk(KERN_ERR "mixer_oss: invalid index %d\n", idx); - continue; - } - mutex_lock(&mixer->reg_mutex); - slot = (struct slot *)mixer->slots[ch].private_data; - if (slot && slot->assigned && - slot->assigned->index == idx && ! strcmp(slot->assigned->name, str)) - /* not changed */ - goto __unlock; - tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); - if (! tbl) { - snd_printk(KERN_ERR "mixer_oss: no memory\n"); - goto __unlock; - } - tbl->oss_id = ch; - tbl->name = kstrdup(str, GFP_KERNEL); - if (! tbl->name) { - kfree(tbl); - goto __unlock; - } - tbl->index = idx; - if (snd_mixer_oss_build_input(mixer, tbl, 1, 1) <= 0) { - kfree(tbl->name); - kfree(tbl); - } - __unlock: - mutex_unlock(&mixer->reg_mutex); - } -} - -static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_card_entry(mixer->card, "oss_mixer", - mixer->card->proc_root); - if (! entry) - return; - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read = snd_mixer_oss_proc_read; - entry->c.text.write = snd_mixer_oss_proc_write; - entry->private_data = mixer; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - mixer->proc_entry = entry; -} - -static void snd_mixer_oss_proc_done(struct snd_mixer_oss *mixer) -{ - snd_info_free_entry(mixer->proc_entry); - mixer->proc_entry = NULL; -} -#else /* !CONFIG_PROC_FS */ -#define snd_mixer_oss_proc_init(mix) -#define snd_mixer_oss_proc_done(mix) -#endif /* CONFIG_PROC_FS */ - -static void snd_mixer_oss_build(struct snd_mixer_oss *mixer) -{ - static struct snd_mixer_oss_assign_table table[] = { - { SOUND_MIXER_VOLUME, "Master", 0 }, - { SOUND_MIXER_VOLUME, "Front", 0 }, /* fallback */ - { SOUND_MIXER_BASS, "Tone Control - Bass", 0 }, - { SOUND_MIXER_TREBLE, "Tone Control - Treble", 0 }, - { SOUND_MIXER_SYNTH, "Synth", 0 }, - { SOUND_MIXER_SYNTH, "FM", 0 }, /* fallback */ - { SOUND_MIXER_SYNTH, "Music", 0 }, /* fallback */ - { SOUND_MIXER_PCM, "PCM", 0 }, - { SOUND_MIXER_SPEAKER, "Beep", 0 }, - { SOUND_MIXER_SPEAKER, "PC Speaker", 0 }, /* fallback */ - { SOUND_MIXER_SPEAKER, "Speaker", 0 }, /* fallback */ - { SOUND_MIXER_LINE, "Line", 0 }, - { SOUND_MIXER_MIC, "Mic", 0 }, - { SOUND_MIXER_CD, "CD", 0 }, - { SOUND_MIXER_IMIX, "Monitor Mix", 0 }, - { SOUND_MIXER_ALTPCM, "PCM", 1 }, - { SOUND_MIXER_ALTPCM, "Headphone", 0 }, /* fallback */ - { SOUND_MIXER_ALTPCM, "Wave", 0 }, /* fallback */ - { SOUND_MIXER_RECLEV, "-- nothing --", 0 }, - { SOUND_MIXER_IGAIN, "Capture", 0 }, - { SOUND_MIXER_OGAIN, "Playback", 0 }, - { SOUND_MIXER_LINE1, "Aux", 0 }, - { SOUND_MIXER_LINE2, "Aux", 1 }, - { SOUND_MIXER_LINE3, "Aux", 2 }, - { SOUND_MIXER_DIGITAL1, "Digital", 0 }, - { SOUND_MIXER_DIGITAL1, "IEC958", 0 }, /* fallback */ - { SOUND_MIXER_DIGITAL1, "IEC958 Optical", 0 }, /* fallback */ - { SOUND_MIXER_DIGITAL1, "IEC958 Coaxial", 0 }, /* fallback */ - { SOUND_MIXER_DIGITAL2, "Digital", 1 }, - { SOUND_MIXER_DIGITAL3, "Digital", 2 }, - { SOUND_MIXER_PHONEIN, "Phone", 0 }, - { SOUND_MIXER_PHONEOUT, "Master Mono", 0 }, - { SOUND_MIXER_PHONEOUT, "Speaker", 0 }, /*fallback*/ - { SOUND_MIXER_PHONEOUT, "Mono", 0 }, /*fallback*/ - { SOUND_MIXER_PHONEOUT, "Phone", 0 }, /* fallback */ - { SOUND_MIXER_VIDEO, "Video", 0 }, - { SOUND_MIXER_RADIO, "Radio", 0 }, - { SOUND_MIXER_MONITOR, "Monitor", 0 } - }; - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(table); idx++) - snd_mixer_oss_build_input(mixer, &table[idx], 0, 0); - if (mixer->mask_recsrc) { - mixer->get_recsrc = snd_mixer_oss_get_recsrc2; - mixer->put_recsrc = snd_mixer_oss_put_recsrc2; - } -} - -/* - * - */ - -static int snd_mixer_oss_free1(void *private) -{ - struct snd_mixer_oss *mixer = private; - struct snd_card *card; - int idx; - - if (!mixer) - return 0; - card = mixer->card; - if (snd_BUG_ON(mixer != card->mixer_oss)) - return -ENXIO; - card->mixer_oss = NULL; - for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++) { - struct snd_mixer_oss_slot *chn = &mixer->slots[idx]; - if (chn->private_free) - chn->private_free(chn); - } - kfree(mixer); - return 0; -} - -static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) -{ - struct snd_mixer_oss *mixer; - - if (cmd == SND_MIXER_OSS_NOTIFY_REGISTER) { - char name[128]; - int idx, err; - - mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL); - if (mixer == NULL) - return -ENOMEM; - mutex_init(&mixer->reg_mutex); - sprintf(name, "mixer%i%i", card->number, 0); - if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, - card, 0, - &snd_mixer_oss_f_ops, card, - name)) < 0) { - snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n", - card->number, 0); - kfree(mixer); - return err; - } - mixer->oss_dev_alloc = 1; - mixer->card = card; - if (*card->mixername) - strlcpy(mixer->name, card->mixername, sizeof(mixer->name)); - else - strlcpy(mixer->name, name, sizeof(mixer->name)); -#ifdef SNDRV_OSS_INFO_DEV_MIXERS - snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS, - card->number, - mixer->name); -#endif - for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++) - mixer->slots[idx].number = idx; - card->mixer_oss = mixer; - snd_mixer_oss_build(mixer); - snd_mixer_oss_proc_init(mixer); - } else { - mixer = card->mixer_oss; - if (mixer == NULL) - return 0; - if (mixer->oss_dev_alloc) { -#ifdef SNDRV_OSS_INFO_DEV_MIXERS - snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number); -#endif - snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0); - mixer->oss_dev_alloc = 0; - } - if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT) - return 0; - snd_mixer_oss_proc_done(mixer); - return snd_mixer_oss_free1(mixer); - } - return 0; -} - -static int __init alsa_mixer_oss_init(void) -{ - int idx; - - snd_mixer_oss_notify_callback = snd_mixer_oss_notify_handler; - for (idx = 0; idx < SNDRV_CARDS; idx++) { - if (snd_cards[idx]) - snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_REGISTER); - } - return 0; -} - -static void __exit alsa_mixer_oss_exit(void) -{ - int idx; - - snd_mixer_oss_notify_callback = NULL; - for (idx = 0; idx < SNDRV_CARDS; idx++) { - if (snd_cards[idx]) - snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_FREE); - } -} - -module_init(alsa_mixer_oss_init) -module_exit(alsa_mixer_oss_exit) - -EXPORT_SYMBOL(snd_mixer_oss_ioctl_card); diff --git a/ANDROID_3.4.5/sound/core/oss/mulaw.c b/ANDROID_3.4.5/sound/core/oss/mulaw.c deleted file mode 100644 index 7915564b..00000000 --- a/ANDROID_3.4.5/sound/core/oss/mulaw.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Mu-Law conversion Plug-In Interface - * Copyright (c) 1999 by Jaroslav Kysela - * Uros Bizjak - * - * Based on reference implementation by Sun Microsystems, Inc. - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include "pcm_plugin.h" - -#define SIGN_BIT (0x80) /* Sign bit for a u-law byte. */ -#define QUANT_MASK (0xf) /* Quantization field mask. */ -#define NSEGS (8) /* Number of u-law segments. */ -#define SEG_SHIFT (4) /* Left shift for segment number. */ -#define SEG_MASK (0x70) /* Segment field mask. */ - -static inline int val_seg(int val) -{ - int r = 0; - val >>= 7; - if (val & 0xf0) { - val >>= 4; - r += 4; - } - if (val & 0x0c) { - val >>= 2; - r += 2; - } - if (val & 0x02) - r += 1; - return r; -} - -#define BIAS (0x84) /* Bias for linear code. */ - -/* - * linear2ulaw() - Convert a linear PCM value to u-law - * - * In order to simplify the encoding process, the original linear magnitude - * is biased by adding 33 which shifts the encoding range from (0 - 8158) to - * (33 - 8191). The result can be seen in the following encoding table: - * - * Biased Linear Input Code Compressed Code - * ------------------------ --------------- - * 00000001wxyza 000wxyz - * 0000001wxyzab 001wxyz - * 000001wxyzabc 010wxyz - * 00001wxyzabcd 011wxyz - * 0001wxyzabcde 100wxyz - * 001wxyzabcdef 101wxyz - * 01wxyzabcdefg 110wxyz - * 1wxyzabcdefgh 111wxyz - * - * Each biased linear code has a leading 1 which identifies the segment - * number. The value of the segment number is equal to 7 minus the number - * of leading 0's. The quantization interval is directly available as the - * four bits wxyz. * The trailing bits (a - h) are ignored. - * - * Ordinarily the complement of the resulting code word is used for - * transmission, and so the code word is complemented before it is returned. - * - * For further information see John C. Bellamy's Digital Telephony, 1982, - * John Wiley & Sons, pps 98-111 and 472-476. - */ -static unsigned char linear2ulaw(int pcm_val) /* 2's complement (16-bit range) */ -{ - int mask; - int seg; - unsigned char uval; - - /* Get the sign and the magnitude of the value. */ - if (pcm_val < 0) { - pcm_val = BIAS - pcm_val; - mask = 0x7F; - } else { - pcm_val += BIAS; - mask = 0xFF; - } - if (pcm_val > 0x7FFF) - pcm_val = 0x7FFF; - - /* Convert the scaled magnitude to segment number. */ - seg = val_seg(pcm_val); - - /* - * Combine the sign, segment, quantization bits; - * and complement the code word. - */ - uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); - return uval ^ mask; -} - -/* - * ulaw2linear() - Convert a u-law value to 16-bit linear PCM - * - * First, a biased linear code is derived from the code word. An unbiased - * output can then be obtained by subtracting 33 from the biased code. - * - * Note that this function expects to be passed the complement of the - * original code word. This is in keeping with ISDN conventions. - */ -static int ulaw2linear(unsigned char u_val) -{ - int t; - - /* Complement to obtain normal u-law value. */ - u_val = ~u_val; - - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = ((u_val & QUANT_MASK) << 3) + BIAS; - t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; - - return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); -} - -/* - * Basic Mu-Law plugin - */ - -typedef void (*mulaw_f)(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames); - -struct mulaw_priv { - mulaw_f func; - int cvt_endian; /* need endian conversion? */ - unsigned int native_ofs; /* byte offset in native format */ - unsigned int copy_ofs; /* byte offset in s16 format */ - unsigned int native_bytes; /* byte size of the native format */ - unsigned int copy_bytes; /* bytes to copy per conversion */ - u16 flip; /* MSB flip for signedness, done after endian conversion */ -}; - -static inline void cvt_s16_to_native(struct mulaw_priv *data, - unsigned char *dst, u16 sample) -{ - sample ^= data->flip; - if (data->cvt_endian) - sample = swab16(sample); - if (data->native_bytes > data->copy_bytes) - memset(dst, 0, data->native_bytes); - memcpy(dst + data->native_ofs, (char *)&sample + data->copy_ofs, - data->copy_bytes); -} - -static void mulaw_decode(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data; - int channel; - int nchannels = plugin->src_format.channels; - for (channel = 0; channel < nchannels; ++channel) { - char *src; - char *dst; - int src_step, dst_step; - snd_pcm_uframes_t frames1; - if (!src_channels[channel].enabled) { - if (dst_channels[channel].wanted) - snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format); - dst_channels[channel].enabled = 0; - continue; - } - dst_channels[channel].enabled = 1; - src = src_channels[channel].area.addr + src_channels[channel].area.first / 8; - dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8; - src_step = src_channels[channel].area.step / 8; - dst_step = dst_channels[channel].area.step / 8; - frames1 = frames; - while (frames1-- > 0) { - signed short sample = ulaw2linear(*src); - cvt_s16_to_native(data, dst, sample); - src += src_step; - dst += dst_step; - } - } -} - -static inline signed short cvt_native_to_s16(struct mulaw_priv *data, - unsigned char *src) -{ - u16 sample = 0; - memcpy((char *)&sample + data->copy_ofs, src + data->native_ofs, - data->copy_bytes); - if (data->cvt_endian) - sample = swab16(sample); - sample ^= data->flip; - return (signed short)sample; -} - -static void mulaw_encode(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data; - int channel; - int nchannels = plugin->src_format.channels; - for (channel = 0; channel < nchannels; ++channel) { - char *src; - char *dst; - int src_step, dst_step; - snd_pcm_uframes_t frames1; - if (!src_channels[channel].enabled) { - if (dst_channels[channel].wanted) - snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format); - dst_channels[channel].enabled = 0; - continue; - } - dst_channels[channel].enabled = 1; - src = src_channels[channel].area.addr + src_channels[channel].area.first / 8; - dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8; - src_step = src_channels[channel].area.step / 8; - dst_step = dst_channels[channel].area.step / 8; - frames1 = frames; - while (frames1-- > 0) { - signed short sample = cvt_native_to_s16(data, src); - *dst = linear2ulaw(sample); - src += src_step; - dst += dst_step; - } - } -} - -static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - struct mulaw_priv *data; - - if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) - return -ENXIO; - if (frames == 0) - return 0; -#ifdef CONFIG_SND_DEBUG - { - unsigned int channel; - for (channel = 0; channel < plugin->src_format.channels; channel++) { - if (snd_BUG_ON(src_channels[channel].area.first % 8 || - src_channels[channel].area.step % 8)) - return -ENXIO; - if (snd_BUG_ON(dst_channels[channel].area.first % 8 || - dst_channels[channel].area.step % 8)) - return -ENXIO; - } - } -#endif - data = (struct mulaw_priv *)plugin->extra_data; - data->func(plugin, src_channels, dst_channels, frames); - return frames; -} - -static void init_data(struct mulaw_priv *data, snd_pcm_format_t format) -{ -#ifdef SNDRV_LITTLE_ENDIAN - data->cvt_endian = snd_pcm_format_big_endian(format) > 0; -#else - data->cvt_endian = snd_pcm_format_little_endian(format) > 0; -#endif - if (!snd_pcm_format_signed(format)) - data->flip = 0x8000; - data->native_bytes = snd_pcm_format_physical_width(format) / 8; - data->copy_bytes = data->native_bytes < 2 ? 1 : 2; - if (snd_pcm_format_little_endian(format)) { - data->native_ofs = data->native_bytes - data->copy_bytes; - data->copy_ofs = 2 - data->copy_bytes; - } else { - /* S24 in 4bytes need an 1 byte offset */ - data->native_ofs = data->native_bytes - - snd_pcm_format_width(format) / 8; - } -} - -int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin) -{ - int err; - struct mulaw_priv *data; - struct snd_pcm_plugin *plugin; - struct snd_pcm_plugin_format *format; - mulaw_f func; - - if (snd_BUG_ON(!r_plugin)) - return -ENXIO; - *r_plugin = NULL; - - if (snd_BUG_ON(src_format->rate != dst_format->rate)) - return -ENXIO; - if (snd_BUG_ON(src_format->channels != dst_format->channels)) - return -ENXIO; - - if (dst_format->format == SNDRV_PCM_FORMAT_MU_LAW) { - format = src_format; - func = mulaw_encode; - } - else if (src_format->format == SNDRV_PCM_FORMAT_MU_LAW) { - format = dst_format; - func = mulaw_decode; - } - else { - snd_BUG(); - return -EINVAL; - } - if (snd_BUG_ON(!snd_pcm_format_linear(format->format))) - return -ENXIO; - - err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion", - src_format, dst_format, - sizeof(struct mulaw_priv), &plugin); - if (err < 0) - return err; - data = (struct mulaw_priv *)plugin->extra_data; - data->func = func; - init_data(data, format->format); - plugin->transfer = mulaw_transfer; - *r_plugin = plugin; - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/oss/pcm_oss.c b/ANDROID_3.4.5/sound/core/oss/pcm_oss.c deleted file mode 100644 index 4c1cc517..00000000 --- a/ANDROID_3.4.5/sound/core/oss/pcm_oss.c +++ /dev/null @@ -1,3117 +0,0 @@ -/* - * Digital Audio (PCM) abstract layer / OSS compatible - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -#if 0 -#define PLUGIN_DEBUG -#endif -#if 0 -#define OSS_DEBUG -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pcm_plugin.h" -#include -#include -#include -#include - -#define OSS_ALSAEMULVER _SIOR ('M', 249, int) - -static int dsp_map[SNDRV_CARDS]; -static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; -static bool nonblock_open = 1; - -MODULE_AUTHOR("Jaroslav Kysela , Abramo Bagnara "); -MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); -MODULE_LICENSE("GPL"); -module_param_array(dsp_map, int, NULL, 0444); -MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device."); -module_param_array(adsp_map, int, NULL, 0444); -MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device."); -module_param(nonblock_open, bool, 0644); -MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices."); -MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM); -MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1); - -static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file); -static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); -static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* - * helper functions to process hw_params - */ -static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin) -{ - int changed = 0; - if (i->min < min) { - i->min = min; - i->openmin = openmin; - changed = 1; - } else if (i->min == min && !i->openmin && openmin) { - i->openmin = 1; - changed = 1; - } - if (i->integer) { - if (i->openmin) { - i->min++; - i->openmin = 0; - } - } - if (snd_interval_checkempty(i)) { - snd_interval_none(i); - return -EINVAL; - } - return changed; -} - -static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax) -{ - int changed = 0; - if (i->max > max) { - i->max = max; - i->openmax = openmax; - changed = 1; - } else if (i->max == max && !i->openmax && openmax) { - i->openmax = 1; - changed = 1; - } - if (i->integer) { - if (i->openmax) { - i->max--; - i->openmax = 0; - } - } - if (snd_interval_checkempty(i)) { - snd_interval_none(i); - return -EINVAL; - } - return changed; -} - -static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) -{ - struct snd_interval t; - t.empty = 0; - t.min = t.max = val; - t.openmin = t.openmax = 0; - t.integer = 1; - return snd_interval_refine(i, &t); -} - -/** - * snd_pcm_hw_param_value_min - * @params: the hw_params instance - * @var: parameter to retrieve - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Return the minimum value for field PAR. - */ -static unsigned int -snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) -{ - if (hw_is_mask(var)) { - if (dir) - *dir = 0; - return snd_mask_min(hw_param_mask_c(params, var)); - } - if (hw_is_interval(var)) { - const struct snd_interval *i = hw_param_interval_c(params, var); - if (dir) - *dir = i->openmin; - return snd_interval_min(i); - } - return -EINVAL; -} - -/** - * snd_pcm_hw_param_value_max - * @params: the hw_params instance - * @var: parameter to retrieve - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Return the maximum value for field PAR. - */ -static unsigned int -snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) -{ - if (hw_is_mask(var)) { - if (dir) - *dir = 0; - return snd_mask_max(hw_param_mask_c(params, var)); - } - if (hw_is_interval(var)) { - const struct snd_interval *i = hw_param_interval_c(params, var); - if (dir) - *dir = - (int) i->openmax; - return snd_interval_max(i); - } - return -EINVAL; -} - -static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, - const struct snd_mask *val) -{ - int changed; - changed = snd_mask_refine(hw_param_mask(params, var), val); - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, - const struct snd_mask *val) -{ - int changed = _snd_pcm_hw_param_mask(params, var, val); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return 0; -} - -static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int dir) -{ - int changed; - int open = 0; - if (dir) { - if (dir > 0) { - open = 1; - } else if (dir < 0) { - if (val > 0) { - open = 1; - val--; - } - } - } - if (hw_is_mask(var)) - changed = snd_mask_refine_min(hw_param_mask(params, var), - val + !!open); - else if (hw_is_interval(var)) - changed = snd_interval_refine_min(hw_param_interval(params, var), - val, open); - else - return -EINVAL; - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -/** - * snd_pcm_hw_param_min - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @val: minimal value - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Inside configuration space defined by PARAMS remove from PAR all - * values < VAL. Reduce configuration space accordingly. - * Return new minimum or -EINVAL if the configuration space is empty - */ -static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int *dir) -{ - int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return snd_pcm_hw_param_value_min(params, var, dir); -} - -static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int dir) -{ - int changed; - int open = 0; - if (dir) { - if (dir < 0) { - open = 1; - } else if (dir > 0) { - open = 1; - val++; - } - } - if (hw_is_mask(var)) { - if (val == 0 && open) { - snd_mask_none(hw_param_mask(params, var)); - changed = -EINVAL; - } else - changed = snd_mask_refine_max(hw_param_mask(params, var), - val - !!open); - } else if (hw_is_interval(var)) - changed = snd_interval_refine_max(hw_param_interval(params, var), - val, open); - else - return -EINVAL; - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -/** - * snd_pcm_hw_param_max - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @val: maximal value - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Inside configuration space defined by PARAMS remove from PAR all - * values >= VAL + 1. Reduce configuration space accordingly. - * Return new maximum or -EINVAL if the configuration space is empty - */ -static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int *dir) -{ - int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return snd_pcm_hw_param_value_max(params, var, dir); -} - -static int boundary_sub(int a, int adir, - int b, int bdir, - int *c, int *cdir) -{ - adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0); - bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0); - *c = a - b; - *cdir = adir - bdir; - if (*cdir == -2) { - (*c)--; - } else if (*cdir == 2) { - (*c)++; - } - return 0; -} - -static int boundary_lt(unsigned int a, int adir, - unsigned int b, int bdir) -{ - if (adir < 0) { - a--; - adir = 1; - } else if (adir > 0) - adir = 1; - if (bdir < 0) { - b--; - bdir = 1; - } else if (bdir > 0) - bdir = 1; - return a < b || (a == b && adir < bdir); -} - -/* Return 1 if min is nearer to best than max */ -static int boundary_nearer(int min, int mindir, - int best, int bestdir, - int max, int maxdir) -{ - int dmin, dmindir; - int dmax, dmaxdir; - boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir); - boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir); - return boundary_lt(dmin, dmindir, dmax, dmaxdir); -} - -/** - * snd_pcm_hw_param_near - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @best: value to set - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Inside configuration space defined by PARAMS set PAR to the available value - * nearest to VAL. Reduce configuration space accordingly. - * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS, - * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT. - * Return the value found. - */ -static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int best, - int *dir) -{ - struct snd_pcm_hw_params *save = NULL; - int v; - unsigned int saved_min; - int last = 0; - int min, max; - int mindir, maxdir; - int valdir = dir ? *dir : 0; - /* FIXME */ - if (best > INT_MAX) - best = INT_MAX; - min = max = best; - mindir = maxdir = valdir; - if (maxdir > 0) - maxdir = 0; - else if (maxdir == 0) - maxdir = -1; - else { - maxdir = 1; - max--; - } - save = kmalloc(sizeof(*save), GFP_KERNEL); - if (save == NULL) - return -ENOMEM; - *save = *params; - saved_min = min; - min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir); - if (min >= 0) { - struct snd_pcm_hw_params *params1; - if (max < 0) - goto _end; - if ((unsigned int)min == saved_min && mindir == valdir) - goto _end; - params1 = kmalloc(sizeof(*params1), GFP_KERNEL); - if (params1 == NULL) { - kfree(save); - return -ENOMEM; - } - *params1 = *save; - max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir); - if (max < 0) { - kfree(params1); - goto _end; - } - if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) { - *params = *params1; - last = 1; - } - kfree(params1); - } else { - *params = *save; - max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); - if (max < 0) { - kfree(save); - return max; - } - last = 1; - } - _end: - kfree(save); - if (last) - v = snd_pcm_hw_param_last(pcm, params, var, dir); - else - v = snd_pcm_hw_param_first(pcm, params, var, dir); - snd_BUG_ON(v < 0); - return v; -} - -static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int dir) -{ - int changed; - if (hw_is_mask(var)) { - struct snd_mask *m = hw_param_mask(params, var); - if (val == 0 && dir < 0) { - changed = -EINVAL; - snd_mask_none(m); - } else { - if (dir > 0) - val++; - else if (dir < 0) - val--; - changed = snd_mask_refine_set(hw_param_mask(params, var), val); - } - } else if (hw_is_interval(var)) { - struct snd_interval *i = hw_param_interval(params, var); - if (val == 0 && dir < 0) { - changed = -EINVAL; - snd_interval_none(i); - } else if (dir == 0) - changed = snd_interval_refine_set(i, val); - else { - struct snd_interval t; - t.openmin = 1; - t.openmax = 1; - t.empty = 0; - t.integer = 0; - if (dir < 0) { - t.min = val - 1; - t.max = val; - } else { - t.min = val; - t.max = val+1; - } - changed = snd_interval_refine(i, &t); - } - } else - return -EINVAL; - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -/** - * snd_pcm_hw_param_set - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @val: value to set - * @dir: pointer to the direction (-1,0,1) or NULL - * - * Inside configuration space defined by PARAMS remove from PAR all - * values != VAL. Reduce configuration space accordingly. - * Return VAL or -EINVAL if the configuration space is empty - */ -static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, unsigned int val, - int dir) -{ - int changed = _snd_pcm_hw_param_set(params, var, val, dir); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (err < 0) - return err; - } - return snd_pcm_hw_param_value(params, var, NULL); -} - -static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var) -{ - int changed; - changed = snd_interval_setinteger(hw_param_interval(params, var)); - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - -/* - * plugin - */ - -#ifdef CONFIG_SND_PCM_OSS_PLUGINS -static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_plugin *plugin, *next; - - plugin = runtime->oss.plugin_first; - while (plugin) { - next = plugin->next; - snd_pcm_plugin_free(plugin); - plugin = next; - } - runtime->oss.plugin_first = runtime->oss.plugin_last = NULL; - return 0; -} - -static int snd_pcm_plugin_insert(struct snd_pcm_plugin *plugin) -{ - struct snd_pcm_runtime *runtime = plugin->plug->runtime; - plugin->next = runtime->oss.plugin_first; - plugin->prev = NULL; - if (runtime->oss.plugin_first) { - runtime->oss.plugin_first->prev = plugin; - runtime->oss.plugin_first = plugin; - } else { - runtime->oss.plugin_last = - runtime->oss.plugin_first = plugin; - } - return 0; -} - -int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin) -{ - struct snd_pcm_runtime *runtime = plugin->plug->runtime; - plugin->next = NULL; - plugin->prev = runtime->oss.plugin_last; - if (runtime->oss.plugin_last) { - runtime->oss.plugin_last->next = plugin; - runtime->oss.plugin_last = plugin; - } else { - runtime->oss.plugin_last = - runtime->oss.plugin_first = plugin; - } - return 0; -} -#endif /* CONFIG_SND_PCM_OSS_PLUGINS */ - -static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - long buffer_size = snd_pcm_lib_buffer_bytes(substream); - long bytes = frames_to_bytes(runtime, frames); - if (buffer_size == runtime->oss.buffer_bytes) - return bytes; -#if BITS_PER_LONG >= 64 - return runtime->oss.buffer_bytes * bytes / buffer_size; -#else - { - u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; - return div_u64(bsize, buffer_size); - } -#endif -} - -static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - long buffer_size = snd_pcm_lib_buffer_bytes(substream); - if (buffer_size == runtime->oss.buffer_bytes) - return bytes_to_frames(runtime, bytes); - return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); -} - -static inline -snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime) -{ - return runtime->hw_ptr_interrupt; -} - -/* define extended formats in the recent OSS versions (if any) */ -/* linear formats */ -#define AFMT_S32_LE 0x00001000 -#define AFMT_S32_BE 0x00002000 -#define AFMT_S24_LE 0x00008000 -#define AFMT_S24_BE 0x00010000 -#define AFMT_S24_PACKED 0x00040000 - -/* other supported formats */ -#define AFMT_FLOAT 0x00004000 -#define AFMT_SPDIF_RAW 0x00020000 - -/* unsupported formats */ -#define AFMT_AC3 0x00000400 -#define AFMT_VORBIS 0x00000800 - -static snd_pcm_format_t snd_pcm_oss_format_from(int format) -{ - switch (format) { - case AFMT_MU_LAW: return SNDRV_PCM_FORMAT_MU_LAW; - case AFMT_A_LAW: return SNDRV_PCM_FORMAT_A_LAW; - case AFMT_IMA_ADPCM: return SNDRV_PCM_FORMAT_IMA_ADPCM; - case AFMT_U8: return SNDRV_PCM_FORMAT_U8; - case AFMT_S16_LE: return SNDRV_PCM_FORMAT_S16_LE; - case AFMT_S16_BE: return SNDRV_PCM_FORMAT_S16_BE; - case AFMT_S8: return SNDRV_PCM_FORMAT_S8; - case AFMT_U16_LE: return SNDRV_PCM_FORMAT_U16_LE; - case AFMT_U16_BE: return SNDRV_PCM_FORMAT_U16_BE; - case AFMT_MPEG: return SNDRV_PCM_FORMAT_MPEG; - case AFMT_S32_LE: return SNDRV_PCM_FORMAT_S32_LE; - case AFMT_S32_BE: return SNDRV_PCM_FORMAT_S32_BE; - case AFMT_S24_LE: return SNDRV_PCM_FORMAT_S24_LE; - case AFMT_S24_BE: return SNDRV_PCM_FORMAT_S24_BE; - case AFMT_S24_PACKED: return SNDRV_PCM_FORMAT_S24_3LE; - case AFMT_FLOAT: return SNDRV_PCM_FORMAT_FLOAT; - case AFMT_SPDIF_RAW: return SNDRV_PCM_FORMAT_IEC958_SUBFRAME; - default: return SNDRV_PCM_FORMAT_U8; - } -} - -static int snd_pcm_oss_format_to(snd_pcm_format_t format) -{ - switch (format) { - case SNDRV_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW; - case SNDRV_PCM_FORMAT_A_LAW: return AFMT_A_LAW; - case SNDRV_PCM_FORMAT_IMA_ADPCM: return AFMT_IMA_ADPCM; - case SNDRV_PCM_FORMAT_U8: return AFMT_U8; - case SNDRV_PCM_FORMAT_S16_LE: return AFMT_S16_LE; - case SNDRV_PCM_FORMAT_S16_BE: return AFMT_S16_BE; - case SNDRV_PCM_FORMAT_S8: return AFMT_S8; - case SNDRV_PCM_FORMAT_U16_LE: return AFMT_U16_LE; - case SNDRV_PCM_FORMAT_U16_BE: return AFMT_U16_BE; - case SNDRV_PCM_FORMAT_MPEG: return AFMT_MPEG; - case SNDRV_PCM_FORMAT_S32_LE: return AFMT_S32_LE; - case SNDRV_PCM_FORMAT_S32_BE: return AFMT_S32_BE; - case SNDRV_PCM_FORMAT_S24_LE: return AFMT_S24_LE; - case SNDRV_PCM_FORMAT_S24_BE: return AFMT_S24_BE; - case SNDRV_PCM_FORMAT_S24_3LE: return AFMT_S24_PACKED; - case SNDRV_PCM_FORMAT_FLOAT: return AFMT_FLOAT; - case SNDRV_PCM_FORMAT_IEC958_SUBFRAME: return AFMT_SPDIF_RAW; - default: return -EINVAL; - } -} - -static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *oss_params, - struct snd_pcm_hw_params *slave_params) -{ - size_t s; - size_t oss_buffer_size, oss_period_size, oss_periods; - size_t min_period_size, max_period_size; - struct snd_pcm_runtime *runtime = substream->runtime; - size_t oss_frame_size; - - oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * - params_channels(oss_params) / 8; - - oss_buffer_size = snd_pcm_plug_client_size(substream, - snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; - oss_buffer_size = 1 << ld2(oss_buffer_size); - if (atomic_read(&substream->mmap_count)) { - if (oss_buffer_size > runtime->oss.mmap_bytes) - oss_buffer_size = runtime->oss.mmap_bytes; - } - - if (substream->oss.setup.period_size > 16) - oss_period_size = substream->oss.setup.period_size; - else if (runtime->oss.fragshift) { - oss_period_size = 1 << runtime->oss.fragshift; - if (oss_period_size > oss_buffer_size / 2) - oss_period_size = oss_buffer_size / 2; - } else { - int sd; - size_t bytes_per_sec = params_rate(oss_params) * snd_pcm_format_physical_width(params_format(oss_params)) * params_channels(oss_params) / 8; - - oss_period_size = oss_buffer_size; - do { - oss_period_size /= 2; - } while (oss_period_size > bytes_per_sec); - if (runtime->oss.subdivision == 0) { - sd = 4; - if (oss_period_size / sd > 4096) - sd *= 2; - if (oss_period_size / sd < 4096) - sd = 1; - } else - sd = runtime->oss.subdivision; - oss_period_size /= sd; - if (oss_period_size < 16) - oss_period_size = 16; - } - - min_period_size = snd_pcm_plug_client_size(substream, - snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); - min_period_size *= oss_frame_size; - min_period_size = 1 << (ld2(min_period_size - 1) + 1); - if (oss_period_size < min_period_size) - oss_period_size = min_period_size; - - max_period_size = snd_pcm_plug_client_size(substream, - snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); - max_period_size *= oss_frame_size; - max_period_size = 1 << ld2(max_period_size); - if (oss_period_size > max_period_size) - oss_period_size = max_period_size; - - oss_periods = oss_buffer_size / oss_period_size; - - if (substream->oss.setup.periods > 1) - oss_periods = substream->oss.setup.periods; - - s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); - if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) - s = runtime->oss.maxfrags; - if (oss_periods > s) - oss_periods = s; - - s = snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); - if (s < 2) - s = 2; - if (oss_periods < s) - oss_periods = s; - - while (oss_period_size * oss_periods > oss_buffer_size) - oss_period_size /= 2; - - if (oss_period_size < 16) - return -EINVAL; - runtime->oss.period_bytes = oss_period_size; - runtime->oss.period_frames = 1; - runtime->oss.periods = oss_periods; - return 0; -} - -static int choose_rate(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, unsigned int best_rate) -{ - struct snd_interval *it; - struct snd_pcm_hw_params *save; - unsigned int rate, prev; - - save = kmalloc(sizeof(*save), GFP_KERNEL); - if (save == NULL) - return -ENOMEM; - *save = *params; - it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE); - - /* try multiples of the best rate */ - rate = best_rate; - for (;;) { - if (it->max < rate || (it->max == rate && it->openmax)) - break; - if (it->min < rate || (it->min == rate && !it->openmin)) { - int ret; - ret = snd_pcm_hw_param_set(substream, params, - SNDRV_PCM_HW_PARAM_RATE, - rate, 0); - if (ret == (int)rate) { - kfree(save); - return rate; - } - *params = *save; - } - prev = rate; - rate += best_rate; - if (rate <= prev) - break; - } - - /* not found, use the nearest rate */ - kfree(save); - return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); -} - -static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_hw_params *params, *sparams; - struct snd_pcm_sw_params *sw_params; - ssize_t oss_buffer_size, oss_period_size; - size_t oss_frame_size; - int err; - int direct; - snd_pcm_format_t format, sformat; - int n; - struct snd_mask sformat_mask; - struct snd_mask mask; - - if (mutex_lock_interruptible(&runtime->oss.params_lock)) - return -EINTR; - sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL); - params = kmalloc(sizeof(*params), GFP_KERNEL); - sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); - if (!sw_params || !params || !sparams) { - snd_printd("No memory\n"); - err = -ENOMEM; - goto failure; - } - - if (atomic_read(&substream->mmap_count)) - direct = 1; - else - direct = substream->oss.setup.direct; - - _snd_pcm_hw_params_any(sparams); - _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); - _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); - snd_mask_none(&mask); - if (atomic_read(&substream->mmap_count)) - snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); - else { - snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED); - if (!direct) - snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); - } - err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask); - if (err < 0) { - snd_printd("No usable accesses\n"); - err = -EINVAL; - goto failure; - } - choose_rate(substream, sparams, runtime->oss.rate); - snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL); - - format = snd_pcm_oss_format_from(runtime->oss.format); - - sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT); - if (direct) - sformat = format; - else - sformat = snd_pcm_plug_slave_format(format, &sformat_mask); - - if ((__force int)sformat < 0 || - !snd_mask_test(&sformat_mask, (__force int)sformat)) { - for (sformat = (__force snd_pcm_format_t)0; - (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST; - sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) { - if (snd_mask_test(&sformat_mask, (__force int)sformat) && - snd_pcm_oss_format_to(sformat) >= 0) - break; - } - if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) { - snd_printd("Cannot find a format!!!\n"); - err = -EINVAL; - goto failure; - } - } - err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0); - if (err < 0) - goto failure; - - if (direct) { - memcpy(params, sparams, sizeof(*params)); - } else { - _snd_pcm_hw_params_any(params); - _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, - (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0); - _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, - (__force int)snd_pcm_oss_format_from(runtime->oss.format), 0); - _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, - runtime->oss.channels, 0); - _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, - runtime->oss.rate, 0); - pdprintf("client: access = %i, format = %i, channels = %i, rate = %i\n", - params_access(params), params_format(params), - params_channels(params), params_rate(params)); - } - pdprintf("slave: access = %i, format = %i, channels = %i, rate = %i\n", - params_access(sparams), params_format(sparams), - params_channels(sparams), params_rate(sparams)); - - oss_frame_size = snd_pcm_format_physical_width(params_format(params)) * - params_channels(params) / 8; - -#ifdef CONFIG_SND_PCM_OSS_PLUGINS - snd_pcm_oss_plugin_clear(substream); - if (!direct) { - /* add necessary plugins */ - snd_pcm_oss_plugin_clear(substream); - if ((err = snd_pcm_plug_format_plugins(substream, - params, - sparams)) < 0) { - snd_printd("snd_pcm_plug_format_plugins failed: %i\n", err); - snd_pcm_oss_plugin_clear(substream); - goto failure; - } - if (runtime->oss.plugin_first) { - struct snd_pcm_plugin *plugin; - if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) { - snd_printd("snd_pcm_plugin_build_io failed: %i\n", err); - snd_pcm_oss_plugin_clear(substream); - goto failure; - } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - err = snd_pcm_plugin_append(plugin); - } else { - err = snd_pcm_plugin_insert(plugin); - } - if (err < 0) { - snd_pcm_oss_plugin_clear(substream); - goto failure; - } - } - } -#endif - - err = snd_pcm_oss_period_size(substream, params, sparams); - if (err < 0) - goto failure; - - n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size); - err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL); - if (err < 0) - goto failure; - - err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS, - runtime->oss.periods, NULL); - if (err < 0) - goto failure; - - snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - - if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) { - snd_printd("HW_PARAMS failed: %i\n", err); - goto failure; - } - - memset(sw_params, 0, sizeof(*sw_params)); - if (runtime->oss.trigger) { - sw_params->start_threshold = 1; - } else { - sw_params->start_threshold = runtime->boundary; - } - if (atomic_read(&substream->mmap_count) || - substream->stream == SNDRV_PCM_STREAM_CAPTURE) - sw_params->stop_threshold = runtime->boundary; - else - sw_params->stop_threshold = runtime->buffer_size; - sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; - sw_params->period_step = 1; - sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - 1 : runtime->period_size; - if (atomic_read(&substream->mmap_count) || - substream->oss.setup.nosilence) { - sw_params->silence_threshold = 0; - sw_params->silence_size = 0; - } else { - snd_pcm_uframes_t frames; - frames = runtime->period_size + 16; - if (frames > runtime->buffer_size) - frames = runtime->buffer_size; - sw_params->silence_threshold = frames; - sw_params->silence_size = frames; - } - - if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { - snd_printd("SW_PARAMS failed: %i\n", err); - goto failure; - } - - runtime->oss.periods = params_periods(sparams); - oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams)); - if (oss_period_size < 0) { - err = -EINVAL; - goto failure; - } -#ifdef CONFIG_SND_PCM_OSS_PLUGINS - if (runtime->oss.plugin_first) { - err = snd_pcm_plug_alloc(substream, oss_period_size); - if (err < 0) - goto failure; - } -#endif - oss_period_size *= oss_frame_size; - - oss_buffer_size = oss_period_size * runtime->oss.periods; - if (oss_buffer_size < 0) { - err = -EINVAL; - goto failure; - } - - runtime->oss.period_bytes = oss_period_size; - runtime->oss.buffer_bytes = oss_buffer_size; - - pdprintf("oss: period bytes = %i, buffer bytes = %i\n", - runtime->oss.period_bytes, - runtime->oss.buffer_bytes); - pdprintf("slave: period_size = %i, buffer_size = %i\n", - params_period_size(sparams), - params_buffer_size(sparams)); - - runtime->oss.format = snd_pcm_oss_format_to(params_format(params)); - runtime->oss.channels = params_channels(params); - runtime->oss.rate = params_rate(params); - - vfree(runtime->oss.buffer); - runtime->oss.buffer = vmalloc(runtime->oss.period_bytes); - if (!runtime->oss.buffer) { - err = -ENOMEM; - goto failure; - } - - runtime->oss.params = 0; - runtime->oss.prepare = 1; - runtime->oss.buffer_used = 0; - if (runtime->dma_area) - snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes)); - - runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size); - - err = 0; -failure: - kfree(sw_params); - kfree(params); - kfree(sparams); - mutex_unlock(&runtime->oss.params_lock); - return err; -} - -static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_file, struct snd_pcm_substream **r_substream) -{ - int idx, err; - struct snd_pcm_substream *asubstream = NULL, *substream; - - for (idx = 0; idx < 2; idx++) { - substream = pcm_oss_file->streams[idx]; - if (substream == NULL) - continue; - if (asubstream == NULL) - asubstream = substream; - if (substream->runtime->oss.params) { - err = snd_pcm_oss_change_params(substream); - if (err < 0) - return err; - } - } - if (!asubstream) - return -EIO; - if (r_substream) - *r_substream = asubstream; - return 0; -} - -static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) -{ - int err; - struct snd_pcm_runtime *runtime = substream->runtime; - - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); - if (err < 0) { - snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n"); - return err; - } - runtime->oss.prepare = 0; - runtime->oss.prev_hw_ptr_period = 0; - runtime->oss.period_ptr = 0; - runtime->oss.buffer_used = 0; - - return 0; -} - -static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - int err; - - if (substream == NULL) - return 0; - runtime = substream->runtime; - if (runtime->oss.params) { - err = snd_pcm_oss_change_params(substream); - if (err < 0) - return err; - } - if (runtime->oss.prepare) { - err = snd_pcm_oss_prepare(substream); - if (err < 0) - return err; - } - return 0; -} - -static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substream, snd_pcm_sframes_t *delay) -{ - struct snd_pcm_runtime *runtime; - snd_pcm_uframes_t frames; - int err = 0; - - while (1) { - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay); - if (err < 0) - break; - runtime = substream->runtime; - if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size) - break; - /* in case of overrun, skip whole periods like OSS/Linux driver does */ - /* until avail(delay) <= buffer_size */ - frames = (*delay - runtime->buffer_size) + runtime->period_size - 1; - frames /= runtime->period_size; - frames *= runtime->period_size; - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames); - if (err < 0) - break; - } - return err; -} - -snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { -#ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk(KERN_DEBUG "pcm_oss: write: " - "recovering from XRUN\n"); - else - printk(KERN_DEBUG "pcm_oss: write: " - "recovering from SUSPEND\n"); -#endif - ret = snd_pcm_oss_prepare(substream); - if (ret < 0) - break; - } - if (in_kernel) { - mm_segment_t fs; - fs = snd_enter_user(); - ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); - snd_leave_user(fs); - } else { - ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); - } - if (ret != -EPIPE && ret != -ESTRPIPE) - break; - /* test, if we can't store new data, because the stream */ - /* has not been started */ - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) - return -EAGAIN; - } - return ret; -} - -snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t delay; - int ret; - while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { -#ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk(KERN_DEBUG "pcm_oss: read: " - "recovering from XRUN\n"); - else - printk(KERN_DEBUG "pcm_oss: read: " - "recovering from SUSPEND\n"); -#endif - ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); - if (ret < 0) - break; - } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { - ret = snd_pcm_oss_prepare(substream); - if (ret < 0) - break; - } - ret = snd_pcm_oss_capture_position_fixup(substream, &delay); - if (ret < 0) - break; - if (in_kernel) { - mm_segment_t fs; - fs = snd_enter_user(); - ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); - snd_leave_user(fs); - } else { - ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); - } - if (ret == -EPIPE) { - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { - ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - if (ret < 0) - break; - } - continue; - } - if (ret != -ESTRPIPE) - break; - } - return ret; -} - -snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { -#ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk(KERN_DEBUG "pcm_oss: writev: " - "recovering from XRUN\n"); - else - printk(KERN_DEBUG "pcm_oss: writev: " - "recovering from SUSPEND\n"); -#endif - ret = snd_pcm_oss_prepare(substream); - if (ret < 0) - break; - } - if (in_kernel) { - mm_segment_t fs; - fs = snd_enter_user(); - ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); - snd_leave_user(fs); - } else { - ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); - } - if (ret != -EPIPE && ret != -ESTRPIPE) - break; - - /* test, if we can't store new data, because the stream */ - /* has not been started */ - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) - return -EAGAIN; - } - return ret; -} - -snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { -#ifdef OSS_DEBUG - if (runtime->status->state == SNDRV_PCM_STATE_XRUN) - printk(KERN_DEBUG "pcm_oss: readv: " - "recovering from XRUN\n"); - else - printk(KERN_DEBUG "pcm_oss: readv: " - "recovering from SUSPEND\n"); -#endif - ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); - if (ret < 0) - break; - } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { - ret = snd_pcm_oss_prepare(substream); - if (ret < 0) - break; - } - if (in_kernel) { - mm_segment_t fs; - fs = snd_enter_user(); - ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); - snd_leave_user(fs); - } else { - ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); - } - if (ret != -EPIPE && ret != -ESTRPIPE) - break; - } - return ret; -} - -static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t frames, frames1; -#ifdef CONFIG_SND_PCM_OSS_PLUGINS - if (runtime->oss.plugin_first) { - struct snd_pcm_plugin_channel *channels; - size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; - if (!in_kernel) { - if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes)) - return -EFAULT; - buf = runtime->oss.buffer; - } - frames = bytes / oss_frame_bytes; - frames1 = snd_pcm_plug_client_channels_buf(substream, (char *)buf, frames, &channels); - if (frames1 < 0) - return frames1; - frames1 = snd_pcm_plug_write_transfer(substream, channels, frames1); - if (frames1 <= 0) - return frames1; - bytes = frames1 * oss_frame_bytes; - } else -#endif - { - frames = bytes_to_frames(runtime, bytes); - frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel); - if (frames1 <= 0) - return frames1; - bytes = frames_to_bytes(runtime, frames1); - } - return bytes; -} - -static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes) -{ - size_t xfer = 0; - ssize_t tmp; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (atomic_read(&substream->mmap_count)) - return -ENXIO; - - if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) - return tmp; - mutex_lock(&runtime->oss.params_lock); - while (bytes > 0) { - if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { - tmp = bytes; - if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes) - tmp = runtime->oss.period_bytes - runtime->oss.buffer_used; - if (tmp > 0) { - if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) { - tmp = -EFAULT; - goto err; - } - } - runtime->oss.buffer_used += tmp; - buf += tmp; - bytes -= tmp; - xfer += tmp; - if (substream->oss.setup.partialfrag || - runtime->oss.buffer_used == runtime->oss.period_bytes) { - tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, - runtime->oss.buffer_used - runtime->oss.period_ptr, 1); - if (tmp <= 0) - goto err; - runtime->oss.bytes += tmp; - runtime->oss.period_ptr += tmp; - runtime->oss.period_ptr %= runtime->oss.period_bytes; - if (runtime->oss.period_ptr == 0 || - runtime->oss.period_ptr == runtime->oss.buffer_used) - runtime->oss.buffer_used = 0; - else if ((substream->f_flags & O_NONBLOCK) != 0) { - tmp = -EAGAIN; - goto err; - } - } - } else { - tmp = snd_pcm_oss_write2(substream, - (const char __force *)buf, - runtime->oss.period_bytes, 0); - if (tmp <= 0) - goto err; - runtime->oss.bytes += tmp; - buf += tmp; - bytes -= tmp; - xfer += tmp; - if ((substream->f_flags & O_NONBLOCK) != 0 && - tmp != runtime->oss.period_bytes) - break; - } - } - mutex_unlock(&runtime->oss.params_lock); - return xfer; - - err: - mutex_unlock(&runtime->oss.params_lock); - return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; -} - -static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t frames, frames1; -#ifdef CONFIG_SND_PCM_OSS_PLUGINS - char __user *final_dst = (char __force __user *)buf; - if (runtime->oss.plugin_first) { - struct snd_pcm_plugin_channel *channels; - size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; - if (!in_kernel) - buf = runtime->oss.buffer; - frames = bytes / oss_frame_bytes; - frames1 = snd_pcm_plug_client_channels_buf(substream, buf, frames, &channels); - if (frames1 < 0) - return frames1; - frames1 = snd_pcm_plug_read_transfer(substream, channels, frames1); - if (frames1 <= 0) - return frames1; - bytes = frames1 * oss_frame_bytes; - if (!in_kernel && copy_to_user(final_dst, buf, bytes)) - return -EFAULT; - } else -#endif - { - frames = bytes_to_frames(runtime, bytes); - frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel); - if (frames1 <= 0) - return frames1; - bytes = frames_to_bytes(runtime, frames1); - } - return bytes; -} - -static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes) -{ - size_t xfer = 0; - ssize_t tmp; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (atomic_read(&substream->mmap_count)) - return -ENXIO; - - if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) - return tmp; - mutex_lock(&runtime->oss.params_lock); - while (bytes > 0) { - if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { - if (runtime->oss.buffer_used == 0) { - tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); - if (tmp <= 0) - goto err; - runtime->oss.bytes += tmp; - runtime->oss.period_ptr = tmp; - runtime->oss.buffer_used = tmp; - } - tmp = bytes; - if ((size_t) tmp > runtime->oss.buffer_used) - tmp = runtime->oss.buffer_used; - if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) { - tmp = -EFAULT; - goto err; - } - buf += tmp; - bytes -= tmp; - xfer += tmp; - runtime->oss.buffer_used -= tmp; - } else { - tmp = snd_pcm_oss_read2(substream, (char __force *)buf, - runtime->oss.period_bytes, 0); - if (tmp <= 0) - goto err; - runtime->oss.bytes += tmp; - buf += tmp; - bytes -= tmp; - xfer += tmp; - } - } - mutex_unlock(&runtime->oss.params_lock); - return xfer; - - err: - mutex_unlock(&runtime->oss.params_lock); - return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; -} - -static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - int i; - - for (i = 0; i < 2; i++) { - substream = pcm_oss_file->streams[i]; - if (!substream) - continue; - runtime = substream->runtime; - snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - runtime->oss.prepare = 1; - runtime->oss.buffer_used = 0; - runtime->oss.prev_hw_ptr_period = 0; - runtime->oss.period_ptr = 0; - } - return 0; -} - -static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *substream; - int err; - - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream != NULL) { - if ((err = snd_pcm_oss_make_ready(substream)) < 0) - return err; - snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL); - } - /* note: all errors from the start action are ignored */ - /* OSS apps do not know, how to handle them */ - return 0; -} - -static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) -{ - struct snd_pcm_runtime *runtime; - ssize_t result = 0; - snd_pcm_state_t state; - long res; - wait_queue_t wait; - - runtime = substream->runtime; - init_waitqueue_entry(&wait, current); - add_wait_queue(&runtime->sleep, &wait); -#ifdef OSS_DEBUG - printk(KERN_DEBUG "sync1: size = %li\n", size); -#endif - while (1) { - result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); - if (result > 0) { - runtime->oss.buffer_used = 0; - result = 0; - break; - } - if (result != 0 && result != -EAGAIN) - break; - result = 0; - set_current_state(TASK_INTERRUPTIBLE); - snd_pcm_stream_lock_irq(substream); - state = runtime->status->state; - snd_pcm_stream_unlock_irq(substream); - if (state != SNDRV_PCM_STATE_RUNNING) { - set_current_state(TASK_RUNNING); - break; - } - res = schedule_timeout(10 * HZ); - if (signal_pending(current)) { - result = -ERESTARTSYS; - break; - } - if (res == 0) { - snd_printk(KERN_ERR "OSS sync error - DMA timeout\n"); - result = -EIO; - break; - } - } - remove_wait_queue(&runtime->sleep, &wait); - return result; -} - -static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) -{ - int err = 0; - unsigned int saved_f_flags; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - snd_pcm_format_t format; - unsigned long width; - size_t size; - - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream != NULL) { - runtime = substream->runtime; - if (atomic_read(&substream->mmap_count)) - goto __direct; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) - return err; - format = snd_pcm_oss_format_from(runtime->oss.format); - width = snd_pcm_format_physical_width(format); - mutex_lock(&runtime->oss.params_lock); - if (runtime->oss.buffer_used > 0) { -#ifdef OSS_DEBUG - printk(KERN_DEBUG "sync: buffer_used\n"); -#endif - size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; - snd_pcm_format_set_silence(format, - runtime->oss.buffer + runtime->oss.buffer_used, - size); - err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes); - if (err < 0) { - mutex_unlock(&runtime->oss.params_lock); - return err; - } - } else if (runtime->oss.period_ptr > 0) { -#ifdef OSS_DEBUG - printk(KERN_DEBUG "sync: period_ptr\n"); -#endif - size = runtime->oss.period_bytes - runtime->oss.period_ptr; - snd_pcm_format_set_silence(format, - runtime->oss.buffer, - size * 8 / width); - err = snd_pcm_oss_sync1(substream, size); - if (err < 0) { - mutex_unlock(&runtime->oss.params_lock); - return err; - } - } - /* - * The ALSA's period might be a bit large than OSS one. - * Fill the remain portion of ALSA period with zeros. - */ - size = runtime->control->appl_ptr % runtime->period_size; - if (size > 0) { - size = runtime->period_size - size; - if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { - size = (runtime->frame_bits * size) / 8; - while (size > 0) { - mm_segment_t fs; - size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes; - size -= size1; - size1 *= 8; - size1 /= runtime->sample_bits; - snd_pcm_format_set_silence(runtime->format, - runtime->oss.buffer, - size1); - size1 /= runtime->channels; /* frames */ - fs = snd_enter_user(); - snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1); - snd_leave_user(fs); - } - } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { - void __user *buffers[runtime->channels]; - memset(buffers, 0, runtime->channels * sizeof(void *)); - snd_pcm_lib_writev(substream, buffers, size); - } - } - mutex_unlock(&runtime->oss.params_lock); - /* - * finish sync: drain the buffer - */ - __direct: - saved_f_flags = substream->f_flags; - substream->f_flags &= ~O_NONBLOCK; - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); - substream->f_flags = saved_f_flags; - if (err < 0) - return err; - runtime->oss.prepare = 1; - } - - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - if (substream != NULL) { - if ((err = snd_pcm_oss_make_ready(substream)) < 0) - return err; - runtime = substream->runtime; - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - if (err < 0) - return err; - runtime->oss.buffer_used = 0; - runtime->oss.prepare = 1; - } - return 0; -} - -static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate) -{ - int idx; - - for (idx = 1; idx >= 0; --idx) { - struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; - struct snd_pcm_runtime *runtime; - if (substream == NULL) - continue; - runtime = substream->runtime; - if (rate < 1000) - rate = 1000; - else if (rate > 192000) - rate = 192000; - if (runtime->oss.rate != rate) { - runtime->oss.params = 1; - runtime->oss.rate = rate; - } - } - return snd_pcm_oss_get_rate(pcm_oss_file); -} - -static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *substream; - int err; - - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) - return err; - return substream->runtime->oss.rate; -} - -static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsigned int channels) -{ - int idx; - if (channels < 1) - channels = 1; - if (channels > 128) - return -EINVAL; - for (idx = 1; idx >= 0; --idx) { - struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; - struct snd_pcm_runtime *runtime; - if (substream == NULL) - continue; - runtime = substream->runtime; - if (runtime->oss.channels != channels) { - runtime->oss.params = 1; - runtime->oss.channels = channels; - } - } - return snd_pcm_oss_get_channels(pcm_oss_file); -} - -static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *substream; - int err; - - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) - return err; - return substream->runtime->oss.channels; -} - -static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *substream; - int err; - - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) - return err; - return substream->runtime->oss.period_bytes; -} - -static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *substream; - int err; - int direct; - struct snd_pcm_hw_params *params; - unsigned int formats = 0; - struct snd_mask format_mask; - int fmt; - - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) - return err; - if (atomic_read(&substream->mmap_count)) - direct = 1; - else - direct = substream->oss.setup.direct; - if (!direct) - return AFMT_MU_LAW | AFMT_U8 | - AFMT_S16_LE | AFMT_S16_BE | - AFMT_S8 | AFMT_U16_LE | - AFMT_U16_BE | - AFMT_S32_LE | AFMT_S32_BE | - AFMT_S24_LE | AFMT_S24_BE | - AFMT_S24_PACKED; - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - _snd_pcm_hw_params_any(params); - err = snd_pcm_hw_refine(substream, params); - format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - kfree(params); - if (err < 0) - return err; - for (fmt = 0; fmt < 32; ++fmt) { - if (snd_mask_test(&format_mask, fmt)) { - int f = snd_pcm_oss_format_to(fmt); - if (f >= 0) - formats |= f; - } - } - return formats; -} - -static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) -{ - int formats, idx; - - if (format != AFMT_QUERY) { - formats = snd_pcm_oss_get_formats(pcm_oss_file); - if (formats < 0) - return formats; - if (!(formats & format)) - format = AFMT_U8; - for (idx = 1; idx >= 0; --idx) { - struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; - struct snd_pcm_runtime *runtime; - if (substream == NULL) - continue; - runtime = substream->runtime; - if (runtime->oss.format != format) { - runtime->oss.params = 1; - runtime->oss.format = format; - } - } - } - return snd_pcm_oss_get_format(pcm_oss_file); -} - -static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *substream; - int err; - - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) - return err; - return substream->runtime->oss.format; -} - -static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide) -{ - struct snd_pcm_runtime *runtime; - - if (substream == NULL) - return 0; - runtime = substream->runtime; - if (subdivide == 0) { - subdivide = runtime->oss.subdivision; - if (subdivide == 0) - subdivide = 1; - return subdivide; - } - if (runtime->oss.subdivision || runtime->oss.fragshift) - return -EINVAL; - if (subdivide != 1 && subdivide != 2 && subdivide != 4 && - subdivide != 8 && subdivide != 16) - return -EINVAL; - runtime->oss.subdivision = subdivide; - runtime->oss.params = 1; - return subdivide; -} - -static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide) -{ - int err = -EINVAL, idx; - - for (idx = 1; idx >= 0; --idx) { - struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; - if (substream == NULL) - continue; - if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0) - return err; - } - return err; -} - -static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val) -{ - struct snd_pcm_runtime *runtime; - - if (substream == NULL) - return 0; - runtime = substream->runtime; - if (runtime->oss.subdivision || runtime->oss.fragshift) - return -EINVAL; - runtime->oss.fragshift = val & 0xffff; - runtime->oss.maxfrags = (val >> 16) & 0xffff; - if (runtime->oss.fragshift < 4) /* < 16 */ - runtime->oss.fragshift = 4; - if (runtime->oss.maxfrags < 2) - runtime->oss.maxfrags = 2; - runtime->oss.params = 1; - return 0; -} - -static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val) -{ - int err = -EINVAL, idx; - - for (idx = 1; idx >= 0; --idx) { - struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; - if (substream == NULL) - continue; - if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0) - return err; - } - return err; -} - -static int snd_pcm_oss_nonblock(struct file * file) -{ - spin_lock(&file->f_lock); - file->f_flags |= O_NONBLOCK; - spin_unlock(&file->f_lock); - return 0; -} - -static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res) -{ - - if (substream == NULL) { - res &= ~DSP_CAP_DUPLEX; - return res; - } -#ifdef DSP_CAP_MULTI - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - if (substream->pstr->substream_count > 1) - res |= DSP_CAP_MULTI; -#endif - /* DSP_CAP_REALTIME is set all times: */ - /* all ALSA drivers can return actual pointer in ring buffer */ -#if defined(DSP_CAP_REALTIME) && 0 - { - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH)) - res &= ~DSP_CAP_REALTIME; - } -#endif - return res; -} - -static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file) -{ - int result, idx; - - result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME; - for (idx = 0; idx < 2; idx++) { - struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; - result = snd_pcm_oss_get_caps1(substream, result); - } - result |= 0x0001; /* revision - same as SB AWE 64 */ - return result; -} - -static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, - snd_pcm_uframes_t hw_ptr) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t appl_ptr; - appl_ptr = hw_ptr + runtime->buffer_size; - appl_ptr %= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; -} - -static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger) -{ - struct snd_pcm_runtime *runtime; - struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; - int err, cmd; - -#ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger); -#endif - - psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - - if (psubstream) { - if ((err = snd_pcm_oss_make_ready(psubstream)) < 0) - return err; - } - if (csubstream) { - if ((err = snd_pcm_oss_make_ready(csubstream)) < 0) - return err; - } - if (psubstream) { - runtime = psubstream->runtime; - if (trigger & PCM_ENABLE_OUTPUT) { - if (runtime->oss.trigger) - goto _skip1; - if (atomic_read(&psubstream->mmap_count)) - snd_pcm_oss_simulate_fill(psubstream, - get_hw_ptr_period(runtime)); - runtime->oss.trigger = 1; - runtime->start_threshold = 1; - cmd = SNDRV_PCM_IOCTL_START; - } else { - if (!runtime->oss.trigger) - goto _skip1; - runtime->oss.trigger = 0; - runtime->start_threshold = runtime->boundary; - cmd = SNDRV_PCM_IOCTL_DROP; - runtime->oss.prepare = 1; - } - err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); - if (err < 0) - return err; - } - _skip1: - if (csubstream) { - runtime = csubstream->runtime; - if (trigger & PCM_ENABLE_INPUT) { - if (runtime->oss.trigger) - goto _skip2; - runtime->oss.trigger = 1; - runtime->start_threshold = 1; - cmd = SNDRV_PCM_IOCTL_START; - } else { - if (!runtime->oss.trigger) - goto _skip2; - runtime->oss.trigger = 0; - runtime->start_threshold = runtime->boundary; - cmd = SNDRV_PCM_IOCTL_DROP; - runtime->oss.prepare = 1; - } - err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); - if (err < 0) - return err; - } - _skip2: - return 0; -} - -static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; - int result = 0; - - psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger) - result |= PCM_ENABLE_OUTPUT; - if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger) - result |= PCM_ENABLE_INPUT; - return result; -} - -static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - snd_pcm_sframes_t delay; - int err; - - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream == NULL) - return -EINVAL; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) - return err; - runtime = substream->runtime; - if (runtime->oss.params || runtime->oss.prepare) - return 0; - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); - if (err == -EPIPE) - delay = 0; /* hack for broken OSS applications */ - else if (err < 0) - return err; - return snd_pcm_oss_bytes(substream, delay); -} - -static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - snd_pcm_sframes_t delay; - int fixup; - struct count_info info; - int err; - - if (_info == NULL) - return -EFAULT; - substream = pcm_oss_file->streams[stream]; - if (substream == NULL) - return -EINVAL; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) - return err; - runtime = substream->runtime; - if (runtime->oss.params || runtime->oss.prepare) { - memset(&info, 0, sizeof(info)); - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); - if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) { - err = 0; - delay = 0; - fixup = 0; - } else { - fixup = runtime->oss.buffer_used; - } - } else { - err = snd_pcm_oss_capture_position_fixup(substream, &delay); - fixup = -runtime->oss.buffer_used; - } - if (err < 0) - return err; - info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); - if (atomic_read(&substream->mmap_count)) { - snd_pcm_sframes_t n; - delay = get_hw_ptr_period(runtime); - n = delay - runtime->oss.prev_hw_ptr_period; - if (n < 0) - n += runtime->boundary; - info.blocks = n / runtime->period_size; - runtime->oss.prev_hw_ptr_period = delay; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - snd_pcm_oss_simulate_fill(substream, delay); - info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; - } else { - delay = snd_pcm_oss_bytes(substream, delay); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (substream->oss.setup.buggyptr) - info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; - else - info.blocks = (delay + fixup) / runtime->oss.period_bytes; - info.bytes = (runtime->oss.bytes - delay) & INT_MAX; - } else { - delay += fixup; - info.blocks = delay / runtime->oss.period_bytes; - info.bytes = (runtime->oss.bytes + delay) & INT_MAX; - } - } - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - snd_pcm_sframes_t avail; - int fixup; - struct audio_buf_info info; - int err; - - if (_info == NULL) - return -EFAULT; - substream = pcm_oss_file->streams[stream]; - if (substream == NULL) - return -EINVAL; - runtime = substream->runtime; - - if (runtime->oss.params && - (err = snd_pcm_oss_change_params(substream)) < 0) - return err; - - info.fragsize = runtime->oss.period_bytes; - info.fragstotal = runtime->periods; - if (runtime->oss.prepare) { - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - info.bytes = runtime->oss.period_bytes * runtime->oss.periods; - info.fragments = runtime->oss.periods; - } else { - info.bytes = 0; - info.fragments = 0; - } - } else { - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail); - if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) { - avail = runtime->buffer_size; - err = 0; - fixup = 0; - } else { - avail = runtime->buffer_size - avail; - fixup = -runtime->oss.buffer_used; - } - } else { - err = snd_pcm_oss_capture_position_fixup(substream, &avail); - fixup = runtime->oss.buffer_used; - } - if (err < 0) - return err; - info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup; - info.fragments = info.bytes / runtime->oss.period_bytes; - } - -#ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, " - "fragstotal = %i, fragsize = %i\n", - info.bytes, info.fragments, info.fragstotal, info.fragsize); -#endif - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info) -{ - // it won't be probably implemented - // snd_printd("TODO: snd_pcm_oss_get_mapbuf\n"); - return -EINVAL; -} - -static const char *strip_task_path(const char *path) -{ - const char *ptr, *ptrl = NULL; - for (ptr = path; *ptr; ptr++) { - if (*ptr == '/') - ptrl = ptr + 1; - } - return ptrl; -} - -static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, - const char *task_name, - struct snd_pcm_oss_setup *rsetup) -{ - struct snd_pcm_oss_setup *setup; - - mutex_lock(&pcm->streams[stream].oss.setup_mutex); - do { - for (setup = pcm->streams[stream].oss.setup_list; setup; - setup = setup->next) { - if (!strcmp(setup->task_name, task_name)) - goto out; - } - } while ((task_name = strip_task_path(task_name)) != NULL); - out: - if (setup) - *rsetup = *setup; - mutex_unlock(&pcm->streams[stream].oss.setup_mutex); -} - -static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - runtime = substream->runtime; - vfree(runtime->oss.buffer); - runtime->oss.buffer = NULL; -#ifdef CONFIG_SND_PCM_OSS_PLUGINS - snd_pcm_oss_plugin_clear(substream); -#endif - substream->oss.oss = 0; -} - -static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, - struct snd_pcm_oss_setup *setup, - int minor) -{ - struct snd_pcm_runtime *runtime; - - substream->oss.oss = 1; - substream->oss.setup = *setup; - if (setup->nonblock) - substream->f_flags |= O_NONBLOCK; - else if (setup->block) - substream->f_flags &= ~O_NONBLOCK; - runtime = substream->runtime; - runtime->oss.params = 1; - runtime->oss.trigger = 1; - runtime->oss.rate = 8000; - mutex_init(&runtime->oss.params_lock); - switch (SNDRV_MINOR_OSS_DEVICE(minor)) { - case SNDRV_MINOR_OSS_PCM_8: - runtime->oss.format = AFMT_U8; - break; - case SNDRV_MINOR_OSS_PCM_16: - runtime->oss.format = AFMT_S16_LE; - break; - default: - runtime->oss.format = AFMT_MU_LAW; - } - runtime->oss.channels = 1; - runtime->oss.fragshift = 0; - runtime->oss.maxfrags = 0; - runtime->oss.subdivision = 0; - substream->pcm_release = snd_pcm_oss_release_substream; -} - -static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) -{ - int cidx; - if (!pcm_oss_file) - return 0; - for (cidx = 0; cidx < 2; ++cidx) { - struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; - if (substream) - snd_pcm_release_substream(substream); - } - kfree(pcm_oss_file); - return 0; -} - -static int snd_pcm_oss_open_file(struct file *file, - struct snd_pcm *pcm, - struct snd_pcm_oss_file **rpcm_oss_file, - int minor, - struct snd_pcm_oss_setup *setup) -{ - int idx, err; - struct snd_pcm_oss_file *pcm_oss_file; - struct snd_pcm_substream *substream; - fmode_t f_mode = file->f_mode; - - if (rpcm_oss_file) - *rpcm_oss_file = NULL; - - pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL); - if (pcm_oss_file == NULL) - return -ENOMEM; - - if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) && - (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) - f_mode = FMODE_WRITE; - - file->f_flags &= ~O_APPEND; - for (idx = 0; idx < 2; idx++) { - if (setup[idx].disable) - continue; - if (! pcm->streams[idx].substream_count) - continue; /* no matching substream */ - if (idx == SNDRV_PCM_STREAM_PLAYBACK) { - if (! (f_mode & FMODE_WRITE)) - continue; - } else { - if (! (f_mode & FMODE_READ)) - continue; - } - err = snd_pcm_open_substream(pcm, idx, file, &substream); - if (err < 0) { - snd_pcm_oss_release_file(pcm_oss_file); - return err; - } - - pcm_oss_file->streams[idx] = substream; - substream->file = pcm_oss_file; - snd_pcm_oss_init_substream(substream, &setup[idx], minor); - } - - if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) { - snd_pcm_oss_release_file(pcm_oss_file); - return -EINVAL; - } - - file->private_data = pcm_oss_file; - if (rpcm_oss_file) - *rpcm_oss_file = pcm_oss_file; - return 0; -} - - -static int snd_task_name(struct task_struct *task, char *name, size_t size) -{ - unsigned int idx; - - if (snd_BUG_ON(!task || !name || size < 2)) - return -EINVAL; - for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) - name[idx] = task->comm[idx]; - name[idx] = '\0'; - return 0; -} - -static int snd_pcm_oss_open(struct inode *inode, struct file *file) -{ - int err; - char task_name[32]; - struct snd_pcm *pcm; - struct snd_pcm_oss_file *pcm_oss_file; - struct snd_pcm_oss_setup setup[2]; - int nonblock; - wait_queue_t wait; - - err = nonseekable_open(inode, file); - if (err < 0) - return err; - - pcm = snd_lookup_oss_minor_data(iminor(inode), - SNDRV_OSS_DEVICE_TYPE_PCM); - if (pcm == NULL) { - err = -ENODEV; - goto __error1; - } - err = snd_card_file_add(pcm->card, file); - if (err < 0) - goto __error1; - if (!try_module_get(pcm->card->module)) { - err = -EFAULT; - goto __error2; - } - if (snd_task_name(current, task_name, sizeof(task_name)) < 0) { - err = -EFAULT; - goto __error; - } - memset(setup, 0, sizeof(setup)); - if (file->f_mode & FMODE_WRITE) - snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, - task_name, &setup[0]); - if (file->f_mode & FMODE_READ) - snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, - task_name, &setup[1]); - - nonblock = !!(file->f_flags & O_NONBLOCK); - if (!nonblock) - nonblock = nonblock_open; - - init_waitqueue_entry(&wait, current); - add_wait_queue(&pcm->open_wait, &wait); - mutex_lock(&pcm->open_mutex); - while (1) { - err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, - iminor(inode), setup); - if (err >= 0) - break; - if (err == -EAGAIN) { - if (nonblock) { - err = -EBUSY; - break; - } - } else - break; - set_current_state(TASK_INTERRUPTIBLE); - mutex_unlock(&pcm->open_mutex); - schedule(); - mutex_lock(&pcm->open_mutex); - if (pcm->card->shutdown) { - err = -ENODEV; - break; - } - if (signal_pending(current)) { - err = -ERESTARTSYS; - break; - } - } - remove_wait_queue(&pcm->open_wait, &wait); - mutex_unlock(&pcm->open_mutex); - if (err < 0) - goto __error; - snd_card_unref(pcm->card); - return err; - - __error: - module_put(pcm->card->module); - __error2: - snd_card_file_remove(pcm->card, file); - __error1: - if (pcm) - snd_card_unref(pcm->card); - return err; -} - -static int snd_pcm_oss_release(struct inode *inode, struct file *file) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - struct snd_pcm_oss_file *pcm_oss_file; - - pcm_oss_file = file->private_data; - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream == NULL) - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - if (snd_BUG_ON(!substream)) - return -ENXIO; - pcm = substream->pcm; - if (!pcm->card->shutdown) - snd_pcm_oss_sync(pcm_oss_file); - mutex_lock(&pcm->open_mutex); - snd_pcm_oss_release_file(pcm_oss_file); - mutex_unlock(&pcm->open_mutex); - wake_up(&pcm->open_wait); - module_put(pcm->card->module); - snd_card_file_remove(pcm->card, file); - return 0; -} - -static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_pcm_oss_file *pcm_oss_file; - int __user *p = (int __user *)arg; - int res; - - pcm_oss_file = file->private_data; - if (cmd == OSS_GETVERSION) - return put_user(SNDRV_OSS_VERSION, p); - if (cmd == OSS_ALSAEMULVER) - return put_user(1, p); -#if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE)) - if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */ - struct snd_pcm_substream *substream; - int idx; - for (idx = 0; idx < 2; ++idx) { - substream = pcm_oss_file->streams[idx]; - if (substream != NULL) - break; - } - if (snd_BUG_ON(idx >= 2)) - return -ENXIO; - return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg); - } -#endif - if (((cmd >> 8) & 0xff) != 'P') - return -EINVAL; -#ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd); -#endif - switch (cmd) { - case SNDCTL_DSP_RESET: - return snd_pcm_oss_reset(pcm_oss_file); - case SNDCTL_DSP_SYNC: - return snd_pcm_oss_sync(pcm_oss_file); - case SNDCTL_DSP_SPEED: - if (get_user(res, p)) - return -EFAULT; - if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0) - return res; - return put_user(res, p); - case SOUND_PCM_READ_RATE: - res = snd_pcm_oss_get_rate(pcm_oss_file); - if (res < 0) - return res; - return put_user(res, p); - case SNDCTL_DSP_STEREO: - if (get_user(res, p)) - return -EFAULT; - res = res > 0 ? 2 : 1; - if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0) - return res; - return put_user(--res, p); - case SNDCTL_DSP_GETBLKSIZE: - res = snd_pcm_oss_get_block_size(pcm_oss_file); - if (res < 0) - return res; - return put_user(res, p); - case SNDCTL_DSP_SETFMT: - if (get_user(res, p)) - return -EFAULT; - res = snd_pcm_oss_set_format(pcm_oss_file, res); - if (res < 0) - return res; - return put_user(res, p); - case SOUND_PCM_READ_BITS: - res = snd_pcm_oss_get_format(pcm_oss_file); - if (res < 0) - return res; - return put_user(res, p); - case SNDCTL_DSP_CHANNELS: - if (get_user(res, p)) - return -EFAULT; - res = snd_pcm_oss_set_channels(pcm_oss_file, res); - if (res < 0) - return res; - return put_user(res, p); - case SOUND_PCM_READ_CHANNELS: - res = snd_pcm_oss_get_channels(pcm_oss_file); - if (res < 0) - return res; - return put_user(res, p); - case SOUND_PCM_WRITE_FILTER: - case SOUND_PCM_READ_FILTER: - return -EIO; - case SNDCTL_DSP_POST: - return snd_pcm_oss_post(pcm_oss_file); - case SNDCTL_DSP_SUBDIVIDE: - if (get_user(res, p)) - return -EFAULT; - res = snd_pcm_oss_set_subdivide(pcm_oss_file, res); - if (res < 0) - return res; - return put_user(res, p); - case SNDCTL_DSP_SETFRAGMENT: - if (get_user(res, p)) - return -EFAULT; - return snd_pcm_oss_set_fragment(pcm_oss_file, res); - case SNDCTL_DSP_GETFMTS: - res = snd_pcm_oss_get_formats(pcm_oss_file); - if (res < 0) - return res; - return put_user(res, p); - case SNDCTL_DSP_GETOSPACE: - case SNDCTL_DSP_GETISPACE: - return snd_pcm_oss_get_space(pcm_oss_file, - cmd == SNDCTL_DSP_GETISPACE ? - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, - (struct audio_buf_info __user *) arg); - case SNDCTL_DSP_NONBLOCK: - return snd_pcm_oss_nonblock(file); - case SNDCTL_DSP_GETCAPS: - res = snd_pcm_oss_get_caps(pcm_oss_file); - if (res < 0) - return res; - return put_user(res, p); - case SNDCTL_DSP_GETTRIGGER: - res = snd_pcm_oss_get_trigger(pcm_oss_file); - if (res < 0) - return res; - return put_user(res, p); - case SNDCTL_DSP_SETTRIGGER: - if (get_user(res, p)) - return -EFAULT; - return snd_pcm_oss_set_trigger(pcm_oss_file, res); - case SNDCTL_DSP_GETIPTR: - case SNDCTL_DSP_GETOPTR: - return snd_pcm_oss_get_ptr(pcm_oss_file, - cmd == SNDCTL_DSP_GETIPTR ? - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, - (struct count_info __user *) arg); - case SNDCTL_DSP_MAPINBUF: - case SNDCTL_DSP_MAPOUTBUF: - return snd_pcm_oss_get_mapbuf(pcm_oss_file, - cmd == SNDCTL_DSP_MAPINBUF ? - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, - (struct buffmem_desc __user *) arg); - case SNDCTL_DSP_SETSYNCRO: - /* stop DMA now.. */ - return 0; - case SNDCTL_DSP_SETDUPLEX: - if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX) - return 0; - return -EIO; - case SNDCTL_DSP_GETODELAY: - res = snd_pcm_oss_get_odelay(pcm_oss_file); - if (res < 0) { - /* it's for sure, some broken apps don't check for error codes */ - put_user(0, p); - return res; - } - return put_user(res, p); - case SNDCTL_DSP_PROFILE: - return 0; /* silently ignore */ - default: - snd_printd("pcm_oss: unknown command = 0x%x\n", cmd); - } - return -EINVAL; -} - -#ifdef CONFIG_COMPAT -/* all compatible */ -#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl -#else -#define snd_pcm_oss_ioctl_compat NULL -#endif - -static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) -{ - struct snd_pcm_oss_file *pcm_oss_file; - struct snd_pcm_substream *substream; - - pcm_oss_file = file->private_data; - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - if (substream == NULL) - return -ENXIO; - substream->f_flags = file->f_flags & O_NONBLOCK; -#ifndef OSS_DEBUG - return snd_pcm_oss_read1(substream, buf, count); -#else - { - ssize_t res = snd_pcm_oss_read1(substream, buf, count); - printk(KERN_DEBUG "pcm_oss: read %li bytes " - "(returned %li bytes)\n", (long)count, (long)res); - return res; - } -#endif -} - -static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) -{ - struct snd_pcm_oss_file *pcm_oss_file; - struct snd_pcm_substream *substream; - long result; - - pcm_oss_file = file->private_data; - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream == NULL) - return -ENXIO; - substream->f_flags = file->f_flags & O_NONBLOCK; - result = snd_pcm_oss_write1(substream, buf, count); -#ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n", - (long)count, (long)result); -#endif - return result; -} - -static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (atomic_read(&substream->mmap_count)) - return runtime->oss.prev_hw_ptr_period != - get_hw_ptr_period(runtime); - else - return snd_pcm_playback_avail(runtime) >= - runtime->oss.period_frames; -} - -static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (atomic_read(&substream->mmap_count)) - return runtime->oss.prev_hw_ptr_period != - get_hw_ptr_period(runtime); - else - return snd_pcm_capture_avail(runtime) >= - runtime->oss.period_frames; -} - -static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) -{ - struct snd_pcm_oss_file *pcm_oss_file; - unsigned int mask; - struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; - - pcm_oss_file = file->private_data; - - psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - - mask = 0; - if (psubstream != NULL) { - struct snd_pcm_runtime *runtime = psubstream->runtime; - poll_wait(file, &runtime->sleep, wait); - snd_pcm_stream_lock_irq(psubstream); - if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && - (runtime->status->state != SNDRV_PCM_STATE_RUNNING || - snd_pcm_oss_playback_ready(psubstream))) - mask |= POLLOUT | POLLWRNORM; - snd_pcm_stream_unlock_irq(psubstream); - } - if (csubstream != NULL) { - struct snd_pcm_runtime *runtime = csubstream->runtime; - snd_pcm_state_t ostate; - poll_wait(file, &runtime->sleep, wait); - snd_pcm_stream_lock_irq(csubstream); - if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING || - snd_pcm_oss_capture_ready(csubstream)) - mask |= POLLIN | POLLRDNORM; - snd_pcm_stream_unlock_irq(csubstream); - if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) { - struct snd_pcm_oss_file ofile; - memset(&ofile, 0, sizeof(ofile)); - ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - runtime->oss.trigger = 0; - snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT); - } - } - - return mask; -} - -static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) -{ - struct snd_pcm_oss_file *pcm_oss_file; - struct snd_pcm_substream *substream = NULL; - struct snd_pcm_runtime *runtime; - int err; - -#ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: mmap begin\n"); -#endif - pcm_oss_file = file->private_data; - switch ((area->vm_flags & (VM_READ | VM_WRITE))) { - case VM_READ | VM_WRITE: - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream) - break; - /* Fall through */ - case VM_READ: - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - break; - case VM_WRITE: - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - break; - default: - return -EINVAL; - } - /* set VM_READ access as well to fix memset() routines that do - reads before writes (to improve performance) */ - area->vm_flags |= VM_READ; - if (substream == NULL) - return -ENXIO; - runtime = substream->runtime; - if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID)) - return -EIO; - if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED) - runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; - else - return -EIO; - - if (runtime->oss.params) { - if ((err = snd_pcm_oss_change_params(substream)) < 0) - return err; - } -#ifdef CONFIG_SND_PCM_OSS_PLUGINS - if (runtime->oss.plugin_first != NULL) - return -EIO; -#endif - - if (area->vm_pgoff != 0) - return -EINVAL; - - err = snd_pcm_mmap_data(substream, file, area); - if (err < 0) - return err; - runtime->oss.mmap_bytes = area->vm_end - area->vm_start; - runtime->silence_threshold = 0; - runtime->silence_size = 0; -#ifdef OSS_DEBUG - printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n", - runtime->oss.mmap_bytes); -#endif - /* In mmap mode we never stop */ - runtime->stop_threshold = runtime->boundary; - - return 0; -} - -#ifdef CONFIG_SND_VERBOSE_PROCFS -/* - * /proc interface - */ - -static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_str *pstr = entry->private_data; - struct snd_pcm_oss_setup *setup = pstr->oss.setup_list; - mutex_lock(&pstr->oss.setup_mutex); - while (setup) { - snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n", - setup->task_name, - setup->periods, - setup->period_size, - setup->disable ? " disable" : "", - setup->direct ? " direct" : "", - setup->block ? " block" : "", - setup->nonblock ? " non-block" : "", - setup->partialfrag ? " partial-frag" : "", - setup->nosilence ? " no-silence" : ""); - setup = setup->next; - } - mutex_unlock(&pstr->oss.setup_mutex); -} - -static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) -{ - struct snd_pcm_oss_setup *setup, *setupn; - - for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL; - setup; setup = setupn) { - setupn = setup->next; - kfree(setup->task_name); - kfree(setup); - } - pstr->oss.setup_list = NULL; -} - -static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_str *pstr = entry->private_data; - char line[128], str[32], task_name[32]; - const char *ptr; - int idx1; - struct snd_pcm_oss_setup *setup, *setup1, template; - - while (!snd_info_get_line(buffer, line, sizeof(line))) { - mutex_lock(&pstr->oss.setup_mutex); - memset(&template, 0, sizeof(template)); - ptr = snd_info_get_str(task_name, line, sizeof(task_name)); - if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) { - snd_pcm_oss_proc_free_setup_list(pstr); - mutex_unlock(&pstr->oss.setup_mutex); - continue; - } - for (setup = pstr->oss.setup_list; setup; setup = setup->next) { - if (!strcmp(setup->task_name, task_name)) { - template = *setup; - break; - } - } - ptr = snd_info_get_str(str, ptr, sizeof(str)); - template.periods = simple_strtoul(str, NULL, 10); - ptr = snd_info_get_str(str, ptr, sizeof(str)); - template.period_size = simple_strtoul(str, NULL, 10); - for (idx1 = 31; idx1 >= 0; idx1--) - if (template.period_size & (1 << idx1)) - break; - for (idx1--; idx1 >= 0; idx1--) - template.period_size &= ~(1 << idx1); - do { - ptr = snd_info_get_str(str, ptr, sizeof(str)); - if (!strcmp(str, "disable")) { - template.disable = 1; - } else if (!strcmp(str, "direct")) { - template.direct = 1; - } else if (!strcmp(str, "block")) { - template.block = 1; - } else if (!strcmp(str, "non-block")) { - template.nonblock = 1; - } else if (!strcmp(str, "partial-frag")) { - template.partialfrag = 1; - } else if (!strcmp(str, "no-silence")) { - template.nosilence = 1; - } else if (!strcmp(str, "buggy-ptr")) { - template.buggyptr = 1; - } - } while (*str); - if (setup == NULL) { - setup = kmalloc(sizeof(*setup), GFP_KERNEL); - if (! setup) { - buffer->error = -ENOMEM; - mutex_unlock(&pstr->oss.setup_mutex); - return; - } - if (pstr->oss.setup_list == NULL) - pstr->oss.setup_list = setup; - else { - for (setup1 = pstr->oss.setup_list; - setup1->next; setup1 = setup1->next); - setup1->next = setup; - } - template.task_name = kstrdup(task_name, GFP_KERNEL); - if (! template.task_name) { - kfree(setup); - buffer->error = -ENOMEM; - mutex_unlock(&pstr->oss.setup_mutex); - return; - } - } - *setup = template; - mutex_unlock(&pstr->oss.setup_mutex); - } -} - -static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) -{ - int stream; - for (stream = 0; stream < 2; ++stream) { - struct snd_info_entry *entry; - struct snd_pcm_str *pstr = &pcm->streams[stream]; - if (pstr->substream_count == 0) - continue; - if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read = snd_pcm_oss_proc_read; - entry->c.text.write = snd_pcm_oss_proc_write; - entry->private_data = pstr; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - pstr->oss.proc_entry = entry; - } -} - -static void snd_pcm_oss_proc_done(struct snd_pcm *pcm) -{ - int stream; - for (stream = 0; stream < 2; ++stream) { - struct snd_pcm_str *pstr = &pcm->streams[stream]; - snd_info_free_entry(pstr->oss.proc_entry); - pstr->oss.proc_entry = NULL; - snd_pcm_oss_proc_free_setup_list(pstr); - } -} -#else /* !CONFIG_SND_VERBOSE_PROCFS */ -#define snd_pcm_oss_proc_init(pcm) -#define snd_pcm_oss_proc_done(pcm) -#endif /* CONFIG_SND_VERBOSE_PROCFS */ - -/* - * ENTRY functions - */ - -static const struct file_operations snd_pcm_oss_f_reg = -{ - .owner = THIS_MODULE, - .read = snd_pcm_oss_read, - .write = snd_pcm_oss_write, - .open = snd_pcm_oss_open, - .release = snd_pcm_oss_release, - .llseek = no_llseek, - .poll = snd_pcm_oss_poll, - .unlocked_ioctl = snd_pcm_oss_ioctl, - .compat_ioctl = snd_pcm_oss_ioctl_compat, - .mmap = snd_pcm_oss_mmap, -}; - -static void register_oss_dsp(struct snd_pcm *pcm, int index) -{ - char name[128]; - sprintf(name, "dsp%i%i", pcm->card->number, pcm->device); - if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, - pcm->card, index, &snd_pcm_oss_f_reg, - pcm, name) < 0) { - snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", - pcm->card->number, pcm->device); - } -} - -static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) -{ - pcm->oss.reg = 0; - if (dsp_map[pcm->card->number] == (int)pcm->device) { - char name[128]; - int duplex; - register_oss_dsp(pcm, 0); - duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && - pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && - !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)); - sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : ""); -#ifdef SNDRV_OSS_INFO_DEV_AUDIO - snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO, - pcm->card->number, - name); -#endif - pcm->oss.reg++; - pcm->oss.reg_mask |= 1; - } - if (adsp_map[pcm->card->number] == (int)pcm->device) { - register_oss_dsp(pcm, 1); - pcm->oss.reg++; - pcm->oss.reg_mask |= 2; - } - - if (pcm->oss.reg) - snd_pcm_oss_proc_init(pcm); - - return 0; -} - -static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) -{ - if (pcm->oss.reg) { - if (pcm->oss.reg_mask & 1) { - pcm->oss.reg_mask &= ~1; - snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, - pcm->card, 0); - } - if (pcm->oss.reg_mask & 2) { - pcm->oss.reg_mask &= ~2; - snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, - pcm->card, 1); - } - if (dsp_map[pcm->card->number] == (int)pcm->device) { -#ifdef SNDRV_OSS_INFO_DEV_AUDIO - snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); -#endif - } - pcm->oss.reg = 0; - } - return 0; -} - -static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm) -{ - snd_pcm_oss_disconnect_minor(pcm); - snd_pcm_oss_proc_done(pcm); - return 0; -} - -static struct snd_pcm_notify snd_pcm_oss_notify = -{ - .n_register = snd_pcm_oss_register_minor, - .n_disconnect = snd_pcm_oss_disconnect_minor, - .n_unregister = snd_pcm_oss_unregister_minor, -}; - -static int __init alsa_pcm_oss_init(void) -{ - int i; - int err; - - /* check device map table */ - for (i = 0; i < SNDRV_CARDS; i++) { - if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { - snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n", - i, dsp_map[i]); - dsp_map[i] = 0; - } - if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { - snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n", - i, adsp_map[i]); - adsp_map[i] = 1; - } - } - if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0) - return err; - return 0; -} - -static void __exit alsa_pcm_oss_exit(void) -{ - snd_pcm_notify(&snd_pcm_oss_notify, 1); -} - -module_init(alsa_pcm_oss_init) -module_exit(alsa_pcm_oss_exit) diff --git a/ANDROID_3.4.5/sound/core/oss/pcm_plugin.c b/ANDROID_3.4.5/sound/core/oss/pcm_plugin.c deleted file mode 100644 index 71cc3ddf..00000000 --- a/ANDROID_3.4.5/sound/core/oss/pcm_plugin.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - * PCM Plug-In shared (kernel/library) code - * Copyright (c) 1999 by Jaroslav Kysela - * Copyright (c) 2000 by Abramo Bagnara - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#if 0 -#define PLUGIN_DEBUG -#endif - -#include -#include -#include -#include -#include -#include -#include "pcm_plugin.h" - -#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first) -#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last) - -/* - * because some cards might have rates "very close", we ignore - * all "resampling" requests within +-5% - */ -static int rate_match(unsigned int src_rate, unsigned int dst_rate) -{ - unsigned int low = (src_rate * 95) / 100; - unsigned int high = (src_rate * 105) / 100; - return dst_rate >= low && dst_rate <= high; -} - -static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames) -{ - struct snd_pcm_plugin_format *format; - ssize_t width; - size_t size; - unsigned int channel; - struct snd_pcm_plugin_channel *c; - - if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK) { - format = &plugin->src_format; - } else { - format = &plugin->dst_format; - } - if ((width = snd_pcm_format_physical_width(format->format)) < 0) - return width; - size = frames * format->channels * width; - if (snd_BUG_ON(size % 8)) - return -ENXIO; - size /= 8; - if (plugin->buf_frames < frames) { - vfree(plugin->buf); - plugin->buf = vmalloc(size); - plugin->buf_frames = frames; - } - if (!plugin->buf) { - plugin->buf_frames = 0; - return -ENOMEM; - } - c = plugin->buf_channels; - if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { - for (channel = 0; channel < format->channels; channel++, c++) { - c->frames = frames; - c->enabled = 1; - c->wanted = 0; - c->area.addr = plugin->buf; - c->area.first = channel * width; - c->area.step = format->channels * width; - } - } else if (plugin->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { - if (snd_BUG_ON(size % format->channels)) - return -EINVAL; - size /= format->channels; - for (channel = 0; channel < format->channels; channel++, c++) { - c->frames = frames; - c->enabled = 1; - c->wanted = 0; - c->area.addr = plugin->buf + (channel * size); - c->area.first = 0; - c->area.step = width; - } - } else - return -EINVAL; - return 0; -} - -int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) -{ - int err; - if (snd_BUG_ON(!snd_pcm_plug_first(plug))) - return -ENXIO; - if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) { - struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug); - while (plugin->next) { - if (plugin->dst_frames) - frames = plugin->dst_frames(plugin, frames); - if (snd_BUG_ON(frames <= 0)) - return -ENXIO; - plugin = plugin->next; - err = snd_pcm_plugin_alloc(plugin, frames); - if (err < 0) - return err; - } - } else { - struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug); - while (plugin->prev) { - if (plugin->src_frames) - frames = plugin->src_frames(plugin, frames); - if (snd_BUG_ON(frames <= 0)) - return -ENXIO; - plugin = plugin->prev; - err = snd_pcm_plugin_alloc(plugin, frames); - if (err < 0) - return err; - } - } - return 0; -} - - -snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin, - snd_pcm_uframes_t frames, - struct snd_pcm_plugin_channel **channels) -{ - *channels = plugin->buf_channels; - return frames; -} - -int snd_pcm_plugin_build(struct snd_pcm_substream *plug, - const char *name, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - size_t extra, - struct snd_pcm_plugin **ret) -{ - struct snd_pcm_plugin *plugin; - unsigned int channels; - - if (snd_BUG_ON(!plug)) - return -ENXIO; - if (snd_BUG_ON(!src_format || !dst_format)) - return -ENXIO; - plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL); - if (plugin == NULL) - return -ENOMEM; - plugin->name = name; - plugin->plug = plug; - plugin->stream = snd_pcm_plug_stream(plug); - plugin->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED; - plugin->src_format = *src_format; - plugin->src_width = snd_pcm_format_physical_width(src_format->format); - snd_BUG_ON(plugin->src_width <= 0); - plugin->dst_format = *dst_format; - plugin->dst_width = snd_pcm_format_physical_width(dst_format->format); - snd_BUG_ON(plugin->dst_width <= 0); - if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK) - channels = src_format->channels; - else - channels = dst_format->channels; - plugin->buf_channels = kcalloc(channels, sizeof(*plugin->buf_channels), GFP_KERNEL); - if (plugin->buf_channels == NULL) { - snd_pcm_plugin_free(plugin); - return -ENOMEM; - } - plugin->client_channels = snd_pcm_plugin_client_channels; - *ret = plugin; - return 0; -} - -int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin) -{ - if (! plugin) - return 0; - if (plugin->private_free) - plugin->private_free(plugin); - kfree(plugin->buf_channels); - vfree(plugin->buf); - kfree(plugin); - return 0; -} - -snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames) -{ - struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; - int stream = snd_pcm_plug_stream(plug); - - if (snd_BUG_ON(!plug)) - return -ENXIO; - if (drv_frames == 0) - return 0; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_last(plug); - while (plugin && drv_frames > 0) { - plugin_prev = plugin->prev; - if (plugin->src_frames) - drv_frames = plugin->src_frames(plugin, drv_frames); - plugin = plugin_prev; - } - } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_first(plug); - while (plugin && drv_frames > 0) { - plugin_next = plugin->next; - if (plugin->dst_frames) - drv_frames = plugin->dst_frames(plugin, drv_frames); - plugin = plugin_next; - } - } else - snd_BUG(); - return drv_frames; -} - -snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t clt_frames) -{ - struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next; - snd_pcm_sframes_t frames; - int stream = snd_pcm_plug_stream(plug); - - if (snd_BUG_ON(!plug)) - return -ENXIO; - if (clt_frames == 0) - return 0; - frames = clt_frames; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_first(plug); - while (plugin && frames > 0) { - plugin_next = plugin->next; - if (plugin->dst_frames) { - frames = plugin->dst_frames(plugin, frames); - if (frames < 0) - return frames; - } - plugin = plugin_next; - } - } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_last(plug); - while (plugin) { - plugin_prev = plugin->prev; - if (plugin->src_frames) { - frames = plugin->src_frames(plugin, frames); - if (frames < 0) - return frames; - } - plugin = plugin_prev; - } - } else - snd_BUG(); - return frames; -} - -static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format) -{ - struct snd_mask formats = *mask; - u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE | - SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE | - SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); - snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW); - - if (formats.bits[0] & (u32)linfmts) - formats.bits[0] |= (u32)linfmts; - if (formats.bits[1] & (u32)(linfmts >> 32)) - formats.bits[1] |= (u32)(linfmts >> 32); - return snd_mask_test(&formats, (__force int)format); -} - -static snd_pcm_format_t preferred_formats[] = { - SNDRV_PCM_FORMAT_S16_LE, - SNDRV_PCM_FORMAT_S16_BE, - SNDRV_PCM_FORMAT_U16_LE, - SNDRV_PCM_FORMAT_U16_BE, - SNDRV_PCM_FORMAT_S24_3LE, - SNDRV_PCM_FORMAT_S24_3BE, - SNDRV_PCM_FORMAT_U24_3LE, - SNDRV_PCM_FORMAT_U24_3BE, - SNDRV_PCM_FORMAT_S24_LE, - SNDRV_PCM_FORMAT_S24_BE, - SNDRV_PCM_FORMAT_U24_LE, - SNDRV_PCM_FORMAT_U24_BE, - SNDRV_PCM_FORMAT_S32_LE, - SNDRV_PCM_FORMAT_S32_BE, - SNDRV_PCM_FORMAT_U32_LE, - SNDRV_PCM_FORMAT_U32_BE, - SNDRV_PCM_FORMAT_S8, - SNDRV_PCM_FORMAT_U8 -}; - -snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, - struct snd_mask *format_mask) -{ - int i; - - if (snd_mask_test(format_mask, (__force int)format)) - return format; - if (!snd_pcm_plug_formats(format_mask, format)) - return (__force snd_pcm_format_t)-EINVAL; - if (snd_pcm_format_linear(format)) { - unsigned int width = snd_pcm_format_width(format); - int unsignd = snd_pcm_format_unsigned(format) > 0; - int big = snd_pcm_format_big_endian(format) > 0; - unsigned int badness, best = -1; - snd_pcm_format_t best_format = (__force snd_pcm_format_t)-1; - for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) { - snd_pcm_format_t f = preferred_formats[i]; - unsigned int w; - if (!snd_mask_test(format_mask, (__force int)f)) - continue; - w = snd_pcm_format_width(f); - if (w >= width) - badness = w - width; - else - badness = width - w + 32; - badness += snd_pcm_format_unsigned(f) != unsignd; - badness += snd_pcm_format_big_endian(f) != big; - if (badness < best) { - best_format = f; - best = badness; - } - } - if ((__force int)best_format >= 0) - return best_format; - else - return (__force snd_pcm_format_t)-EINVAL; - } else { - switch (format) { - case SNDRV_PCM_FORMAT_MU_LAW: - for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) { - snd_pcm_format_t format1 = preferred_formats[i]; - if (snd_mask_test(format_mask, (__force int)format1)) - return format1; - } - default: - return (__force snd_pcm_format_t)-EINVAL; - } - } -} - -int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug, - struct snd_pcm_hw_params *params, - struct snd_pcm_hw_params *slave_params) -{ - struct snd_pcm_plugin_format tmpformat; - struct snd_pcm_plugin_format dstformat; - struct snd_pcm_plugin_format srcformat; - snd_pcm_access_t src_access, dst_access; - struct snd_pcm_plugin *plugin = NULL; - int err; - int stream = snd_pcm_plug_stream(plug); - int slave_interleaved = (params_channels(slave_params) == 1 || - params_access(slave_params) == SNDRV_PCM_ACCESS_RW_INTERLEAVED); - - switch (stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - dstformat.format = params_format(slave_params); - dstformat.rate = params_rate(slave_params); - dstformat.channels = params_channels(slave_params); - srcformat.format = params_format(params); - srcformat.rate = params_rate(params); - srcformat.channels = params_channels(params); - src_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED; - dst_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED : - SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); - break; - case SNDRV_PCM_STREAM_CAPTURE: - dstformat.format = params_format(params); - dstformat.rate = params_rate(params); - dstformat.channels = params_channels(params); - srcformat.format = params_format(slave_params); - srcformat.rate = params_rate(slave_params); - srcformat.channels = params_channels(slave_params); - src_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED : - SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); - dst_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED; - break; - default: - snd_BUG(); - return -EINVAL; - } - tmpformat = srcformat; - - pdprintf("srcformat: format=%i, rate=%i, channels=%i\n", - srcformat.format, - srcformat.rate, - srcformat.channels); - pdprintf("dstformat: format=%i, rate=%i, channels=%i\n", - dstformat.format, - dstformat.rate, - dstformat.channels); - - /* Format change (linearization) */ - if (! rate_match(srcformat.rate, dstformat.rate) && - ! snd_pcm_format_linear(srcformat.format)) { - if (srcformat.format != SNDRV_PCM_FORMAT_MU_LAW) - return -EINVAL; - tmpformat.format = SNDRV_PCM_FORMAT_S16; - err = snd_pcm_plugin_build_mulaw(plug, - &srcformat, &tmpformat, - &plugin); - if (err < 0) - return err; - err = snd_pcm_plugin_append(plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcformat = tmpformat; - src_access = dst_access; - } - - /* channels reduction */ - if (srcformat.channels > dstformat.channels) { - tmpformat.channels = dstformat.channels; - err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin); - pdprintf("channels reduction: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err); - if (err < 0) - return err; - err = snd_pcm_plugin_append(plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcformat = tmpformat; - src_access = dst_access; - } - - /* rate resampling */ - if (!rate_match(srcformat.rate, dstformat.rate)) { - if (srcformat.format != SNDRV_PCM_FORMAT_S16) { - /* convert to S16 for resampling */ - tmpformat.format = SNDRV_PCM_FORMAT_S16; - err = snd_pcm_plugin_build_linear(plug, - &srcformat, &tmpformat, - &plugin); - if (err < 0) - return err; - err = snd_pcm_plugin_append(plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcformat = tmpformat; - src_access = dst_access; - } - tmpformat.rate = dstformat.rate; - err = snd_pcm_plugin_build_rate(plug, - &srcformat, &tmpformat, - &plugin); - pdprintf("rate down resampling: src=%i, dst=%i returns %i\n", srcformat.rate, tmpformat.rate, err); - if (err < 0) - return err; - err = snd_pcm_plugin_append(plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcformat = tmpformat; - src_access = dst_access; - } - - /* format change */ - if (srcformat.format != dstformat.format) { - tmpformat.format = dstformat.format; - if (srcformat.format == SNDRV_PCM_FORMAT_MU_LAW || - tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) { - err = snd_pcm_plugin_build_mulaw(plug, - &srcformat, &tmpformat, - &plugin); - } - else if (snd_pcm_format_linear(srcformat.format) && - snd_pcm_format_linear(tmpformat.format)) { - err = snd_pcm_plugin_build_linear(plug, - &srcformat, &tmpformat, - &plugin); - } - else - return -EINVAL; - pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err); - if (err < 0) - return err; - err = snd_pcm_plugin_append(plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcformat = tmpformat; - src_access = dst_access; - } - - /* channels extension */ - if (srcformat.channels < dstformat.channels) { - tmpformat.channels = dstformat.channels; - err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin); - pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, err); - if (err < 0) - return err; - err = snd_pcm_plugin_append(plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - srcformat = tmpformat; - src_access = dst_access; - } - - /* de-interleave */ - if (src_access != dst_access) { - err = snd_pcm_plugin_build_copy(plug, - &srcformat, - &tmpformat, - &plugin); - pdprintf("interleave change (copy: returns %i)\n", err); - if (err < 0) - return err; - err = snd_pcm_plugin_append(plugin); - if (err < 0) { - snd_pcm_plugin_free(plugin); - return err; - } - } - - return 0; -} - -snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plug, - char *buf, - snd_pcm_uframes_t count, - struct snd_pcm_plugin_channel **channels) -{ - struct snd_pcm_plugin *plugin; - struct snd_pcm_plugin_channel *v; - struct snd_pcm_plugin_format *format; - int width, nchannels, channel; - int stream = snd_pcm_plug_stream(plug); - - if (snd_BUG_ON(!buf)) - return -ENXIO; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_first(plug); - format = &plugin->src_format; - } else { - plugin = snd_pcm_plug_last(plug); - format = &plugin->dst_format; - } - v = plugin->buf_channels; - *channels = v; - if ((width = snd_pcm_format_physical_width(format->format)) < 0) - return width; - nchannels = format->channels; - if (snd_BUG_ON(plugin->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && - format->channels > 1)) - return -ENXIO; - for (channel = 0; channel < nchannels; channel++, v++) { - v->frames = count; - v->enabled = 1; - v->wanted = (stream == SNDRV_PCM_STREAM_CAPTURE); - v->area.addr = buf; - v->area.first = channel * width; - v->area.step = nchannels * width; - } - return count; -} - -snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *src_channels, snd_pcm_uframes_t size) -{ - struct snd_pcm_plugin *plugin, *next; - struct snd_pcm_plugin_channel *dst_channels; - int err; - snd_pcm_sframes_t frames = size; - - plugin = snd_pcm_plug_first(plug); - while (plugin && frames > 0) { - if ((next = plugin->next) != NULL) { - snd_pcm_sframes_t frames1 = frames; - if (plugin->dst_frames) - frames1 = plugin->dst_frames(plugin, frames); - if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) { - return err; - } - if (err != frames1) { - frames = err; - if (plugin->src_frames) - frames = plugin->src_frames(plugin, frames1); - } - } else - dst_channels = NULL; - pdprintf("write plugin: %s, %li\n", plugin->name, frames); - if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) - return frames; - src_channels = dst_channels; - plugin = next; - } - return snd_pcm_plug_client_size(plug, frames); -} - -snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *dst_channels_final, snd_pcm_uframes_t size) -{ - struct snd_pcm_plugin *plugin, *next; - struct snd_pcm_plugin_channel *src_channels, *dst_channels; - snd_pcm_sframes_t frames = size; - int err; - - frames = snd_pcm_plug_slave_size(plug, frames); - if (frames < 0) - return frames; - - src_channels = NULL; - plugin = snd_pcm_plug_first(plug); - while (plugin && frames > 0) { - if ((next = plugin->next) != NULL) { - if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) { - return err; - } - frames = err; - } else { - dst_channels = dst_channels_final; - } - pdprintf("read plugin: %s, %li\n", plugin->name, frames); - if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) - return frames; - plugin = next; - src_channels = dst_channels; - } - return frames; -} - -int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset, - size_t samples, snd_pcm_format_t format) -{ - /* FIXME: sub byte resolution and odd dst_offset */ - unsigned char *dst; - unsigned int dst_step; - int width; - const unsigned char *silence; - if (!dst_area->addr) - return 0; - dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8; - width = snd_pcm_format_physical_width(format); - if (width <= 0) - return -EINVAL; - if (dst_area->step == (unsigned int) width && width >= 8) - return snd_pcm_format_set_silence(format, dst, samples); - silence = snd_pcm_format_silence_64(format); - if (! silence) - return -EINVAL; - dst_step = dst_area->step / 8; - if (width == 4) { - /* Ima ADPCM */ - int dstbit = dst_area->first % 8; - int dstbit_step = dst_area->step % 8; - while (samples-- > 0) { - if (dstbit) - *dst &= 0xf0; - else - *dst &= 0x0f; - dst += dst_step; - dstbit += dstbit_step; - if (dstbit == 8) { - dst++; - dstbit = 0; - } - } - } else { - width /= 8; - while (samples-- > 0) { - memcpy(dst, silence, width); - dst += dst_step; - } - } - return 0; -} - -int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset, - const struct snd_pcm_channel_area *dst_area, size_t dst_offset, - size_t samples, snd_pcm_format_t format) -{ - /* FIXME: sub byte resolution and odd dst_offset */ - char *src, *dst; - int width; - int src_step, dst_step; - src = src_area->addr + (src_area->first + src_area->step * src_offset) / 8; - if (!src_area->addr) - return snd_pcm_area_silence(dst_area, dst_offset, samples, format); - dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8; - if (!dst_area->addr) - return 0; - width = snd_pcm_format_physical_width(format); - if (width <= 0) - return -EINVAL; - if (src_area->step == (unsigned int) width && - dst_area->step == (unsigned int) width && width >= 8) { - size_t bytes = samples * width / 8; - memcpy(dst, src, bytes); - return 0; - } - src_step = src_area->step / 8; - dst_step = dst_area->step / 8; - if (width == 4) { - /* Ima ADPCM */ - int srcbit = src_area->first % 8; - int srcbit_step = src_area->step % 8; - int dstbit = dst_area->first % 8; - int dstbit_step = dst_area->step % 8; - while (samples-- > 0) { - unsigned char srcval; - if (srcbit) - srcval = *src & 0x0f; - else - srcval = (*src & 0xf0) >> 4; - if (dstbit) - *dst = (*dst & 0xf0) | srcval; - else - *dst = (*dst & 0x0f) | (srcval << 4); - src += src_step; - srcbit += srcbit_step; - if (srcbit == 8) { - src++; - srcbit = 0; - } - dst += dst_step; - dstbit += dstbit_step; - if (dstbit == 8) { - dst++; - dstbit = 0; - } - } - } else { - width /= 8; - while (samples-- > 0) { - memcpy(dst, src, width); - src += src_step; - dst += dst_step; - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/oss/pcm_plugin.h b/ANDROID_3.4.5/sound/core/oss/pcm_plugin.h deleted file mode 100644 index a5035c23..00000000 --- a/ANDROID_3.4.5/sound/core/oss/pcm_plugin.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef __PCM_PLUGIN_H -#define __PCM_PLUGIN_H - -/* - * Digital Audio (Plugin interface) abstract layer - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -#ifdef CONFIG_SND_PCM_OSS_PLUGINS - -#define snd_pcm_plug_stream(plug) ((plug)->stream) - -enum snd_pcm_plugin_action { - INIT = 0, - PREPARE = 1, -}; - -struct snd_pcm_channel_area { - void *addr; /* base address of channel samples */ - unsigned int first; /* offset to first sample in bits */ - unsigned int step; /* samples distance in bits */ -}; - -struct snd_pcm_plugin_channel { - void *aptr; /* pointer to the allocated area */ - struct snd_pcm_channel_area area; - snd_pcm_uframes_t frames; /* allocated frames */ - unsigned int enabled:1; /* channel need to be processed */ - unsigned int wanted:1; /* channel is wanted */ -}; - -struct snd_pcm_plugin_format { - snd_pcm_format_t format; - unsigned int rate; - unsigned int channels; -}; - -struct snd_pcm_plugin { - const char *name; /* plug-in name */ - int stream; - struct snd_pcm_plugin_format src_format; /* source format */ - struct snd_pcm_plugin_format dst_format; /* destination format */ - int src_width; /* sample width in bits */ - int dst_width; /* sample width in bits */ - snd_pcm_access_t access; - snd_pcm_sframes_t (*src_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames); - snd_pcm_sframes_t (*dst_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t src_frames); - snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin, - snd_pcm_uframes_t frames, - struct snd_pcm_plugin_channel **channels); - snd_pcm_sframes_t (*transfer)(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames); - int (*action)(struct snd_pcm_plugin *plugin, - enum snd_pcm_plugin_action action, - unsigned long data); - struct snd_pcm_plugin *prev; - struct snd_pcm_plugin *next; - struct snd_pcm_substream *plug; - void *private_data; - void (*private_free)(struct snd_pcm_plugin *plugin); - char *buf; - snd_pcm_uframes_t buf_frames; - struct snd_pcm_plugin_channel *buf_channels; - char extra_data[0]; -}; - -int snd_pcm_plugin_build(struct snd_pcm_substream *handle, - const char *name, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - size_t extra, - struct snd_pcm_plugin **ret); -int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin); -int snd_pcm_plugin_clear(struct snd_pcm_plugin **first); -int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames); -snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size); -snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size); - -#define FULL ROUTE_PLUGIN_RESOLUTION -#define HALF ROUTE_PLUGIN_RESOLUTION / 2 - -int snd_pcm_plugin_build_io(struct snd_pcm_substream *handle, - struct snd_pcm_hw_params *params, - struct snd_pcm_plugin **r_plugin); -int snd_pcm_plugin_build_linear(struct snd_pcm_substream *handle, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin); -int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *handle, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin); -int snd_pcm_plugin_build_rate(struct snd_pcm_substream *handle, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin); -int snd_pcm_plugin_build_route(struct snd_pcm_substream *handle, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin); -int snd_pcm_plugin_build_copy(struct snd_pcm_substream *handle, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin); - -int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_pcm_hw_params *slave_params); - -snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, - struct snd_mask *format_mask); - -int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin); - -snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *handle, - struct snd_pcm_plugin_channel *src_channels, - snd_pcm_uframes_t size); -snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *handle, - struct snd_pcm_plugin_channel *dst_channels_final, - snd_pcm_uframes_t size); - -snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *handle, - char *buf, snd_pcm_uframes_t count, - struct snd_pcm_plugin_channel **channels); - -snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin, - snd_pcm_uframes_t frames, - struct snd_pcm_plugin_channel **channels); - -int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_channel, - size_t dst_offset, - size_t samples, snd_pcm_format_t format); -int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel, - size_t src_offset, - const struct snd_pcm_channel_area *dst_channel, - size_t dst_offset, - size_t samples, snd_pcm_format_t format); - -void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size); -void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr); -snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, - const char *ptr, snd_pcm_uframes_t size, - int in_kernel); -snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, - char *ptr, snd_pcm_uframes_t size, int in_kernel); -snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, - void **bufs, snd_pcm_uframes_t frames, - int in_kernel); -snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, - void **bufs, snd_pcm_uframes_t frames, - int in_kernel); - -#else - -static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } -static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; } -static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; } - -#endif - -#ifdef PLUGIN_DEBUG -#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args) -#else -#define pdprintf(fmt, args...) -#endif - -#endif /* __PCM_PLUGIN_H */ diff --git a/ANDROID_3.4.5/sound/core/oss/rate.c b/ANDROID_3.4.5/sound/core/oss/rate.c deleted file mode 100644 index 2fa9299a..00000000 --- a/ANDROID_3.4.5/sound/core/oss/rate.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Rate conversion Plug-In - * Copyright (c) 1999 by Jaroslav Kysela - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include "pcm_plugin.h" - -#define SHIFT 11 -#define BITS (1<extra_data; - data->pos = 0; - for (channel = 0; channel < plugin->src_format.channels; channel++) { - data->channels[channel].last_S1 = 0; - data->channels[channel].last_S2 = 0; - } -} - -static void resample_expand(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - int src_frames, int dst_frames) -{ - unsigned int pos = 0; - signed int val; - signed short S1, S2; - signed short *src, *dst; - unsigned int channel; - int src_step, dst_step; - int src_frames1, dst_frames1; - struct rate_priv *data = (struct rate_priv *)plugin->extra_data; - struct rate_channel *rchannels = data->channels; - - for (channel = 0; channel < plugin->src_format.channels; channel++) { - pos = data->pos; - S1 = rchannels->last_S1; - S2 = rchannels->last_S2; - if (!src_channels[channel].enabled) { - if (dst_channels[channel].wanted) - snd_pcm_area_silence(&dst_channels[channel].area, 0, dst_frames, plugin->dst_format.format); - dst_channels[channel].enabled = 0; - continue; - } - dst_channels[channel].enabled = 1; - src = (signed short *)src_channels[channel].area.addr + - src_channels[channel].area.first / 8 / 2; - dst = (signed short *)dst_channels[channel].area.addr + - dst_channels[channel].area.first / 8 / 2; - src_step = src_channels[channel].area.step / 8 / 2; - dst_step = dst_channels[channel].area.step / 8 / 2; - src_frames1 = src_frames; - dst_frames1 = dst_frames; - while (dst_frames1-- > 0) { - if (pos & ~R_MASK) { - pos &= R_MASK; - S1 = S2; - if (src_frames1-- > 0) { - S2 = *src; - src += src_step; - } - } - val = S1 + ((S2 - S1) * (signed int)pos) / BITS; - if (val < -32768) - val = -32768; - else if (val > 32767) - val = 32767; - *dst = val; - dst += dst_step; - pos += data->pitch; - } - rchannels->last_S1 = S1; - rchannels->last_S2 = S2; - rchannels++; - } - data->pos = pos; -} - -static void resample_shrink(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - int src_frames, int dst_frames) -{ - unsigned int pos = 0; - signed int val; - signed short S1, S2; - signed short *src, *dst; - unsigned int channel; - int src_step, dst_step; - int src_frames1, dst_frames1; - struct rate_priv *data = (struct rate_priv *)plugin->extra_data; - struct rate_channel *rchannels = data->channels; - - for (channel = 0; channel < plugin->src_format.channels; ++channel) { - pos = data->pos; - S1 = rchannels->last_S1; - S2 = rchannels->last_S2; - if (!src_channels[channel].enabled) { - if (dst_channels[channel].wanted) - snd_pcm_area_silence(&dst_channels[channel].area, 0, dst_frames, plugin->dst_format.format); - dst_channels[channel].enabled = 0; - continue; - } - dst_channels[channel].enabled = 1; - src = (signed short *)src_channels[channel].area.addr + - src_channels[channel].area.first / 8 / 2; - dst = (signed short *)dst_channels[channel].area.addr + - dst_channels[channel].area.first / 8 / 2; - src_step = src_channels[channel].area.step / 8 / 2; - dst_step = dst_channels[channel].area.step / 8 / 2; - src_frames1 = src_frames; - dst_frames1 = dst_frames; - while (dst_frames1 > 0) { - S1 = S2; - if (src_frames1-- > 0) { - S2 = *src; - src += src_step; - } - if (pos & ~R_MASK) { - pos &= R_MASK; - val = S1 + ((S2 - S1) * (signed int)pos) / BITS; - if (val < -32768) - val = -32768; - else if (val > 32767) - val = 32767; - *dst = val; - dst += dst_step; - dst_frames1--; - } - pos += data->pitch; - } - rchannels->last_S1 = S1; - rchannels->last_S2 = S2; - rchannels++; - } - data->pos = pos; -} - -static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames) -{ - struct rate_priv *data; - snd_pcm_sframes_t res; - - if (snd_BUG_ON(!plugin)) - return -ENXIO; - if (frames == 0) - return 0; - data = (struct rate_priv *)plugin->extra_data; - if (plugin->src_format.rate < plugin->dst_format.rate) { - res = (((frames * data->pitch) + (BITS/2)) >> SHIFT); - } else { - res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch); - } - if (data->old_src_frames > 0) { - snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames; - while (data->old_src_frames < frames1) { - frames1 >>= 1; - res1 <<= 1; - } - while (data->old_src_frames > frames1) { - frames1 <<= 1; - res1 >>= 1; - } - if (data->old_src_frames == frames1) - return res1; - } - data->old_src_frames = frames; - data->old_dst_frames = res; - return res; -} - -static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames) -{ - struct rate_priv *data; - snd_pcm_sframes_t res; - - if (snd_BUG_ON(!plugin)) - return -ENXIO; - if (frames == 0) - return 0; - data = (struct rate_priv *)plugin->extra_data; - if (plugin->src_format.rate < plugin->dst_format.rate) { - res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch); - } else { - res = (((frames * data->pitch) + (BITS/2)) >> SHIFT); - } - if (data->old_dst_frames > 0) { - snd_pcm_sframes_t frames1 = frames, res1 = data->old_src_frames; - while (data->old_dst_frames < frames1) { - frames1 >>= 1; - res1 <<= 1; - } - while (data->old_dst_frames > frames1) { - frames1 <<= 1; - res1 >>= 1; - } - if (data->old_dst_frames == frames1) - return res1; - } - data->old_dst_frames = frames; - data->old_src_frames = res; - return res; -} - -static snd_pcm_sframes_t rate_transfer(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - snd_pcm_uframes_t dst_frames; - struct rate_priv *data; - - if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) - return -ENXIO; - if (frames == 0) - return 0; -#ifdef CONFIG_SND_DEBUG - { - unsigned int channel; - for (channel = 0; channel < plugin->src_format.channels; channel++) { - if (snd_BUG_ON(src_channels[channel].area.first % 8 || - src_channels[channel].area.step % 8)) - return -ENXIO; - if (snd_BUG_ON(dst_channels[channel].area.first % 8 || - dst_channels[channel].area.step % 8)) - return -ENXIO; - } - } -#endif - - dst_frames = rate_dst_frames(plugin, frames); - if (dst_frames > dst_channels[0].frames) - dst_frames = dst_channels[0].frames; - data = (struct rate_priv *)plugin->extra_data; - data->func(plugin, src_channels, dst_channels, frames, dst_frames); - return dst_frames; -} - -static int rate_action(struct snd_pcm_plugin *plugin, - enum snd_pcm_plugin_action action, - unsigned long udata) -{ - if (snd_BUG_ON(!plugin)) - return -ENXIO; - switch (action) { - case INIT: - case PREPARE: - rate_init(plugin); - break; - default: - break; - } - return 0; /* silenty ignore other actions */ -} - -int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin) -{ - int err; - struct rate_priv *data; - struct snd_pcm_plugin *plugin; - - if (snd_BUG_ON(!r_plugin)) - return -ENXIO; - *r_plugin = NULL; - - if (snd_BUG_ON(src_format->channels != dst_format->channels)) - return -ENXIO; - if (snd_BUG_ON(src_format->channels <= 0)) - return -ENXIO; - if (snd_BUG_ON(src_format->format != SNDRV_PCM_FORMAT_S16)) - return -ENXIO; - if (snd_BUG_ON(dst_format->format != SNDRV_PCM_FORMAT_S16)) - return -ENXIO; - if (snd_BUG_ON(src_format->rate == dst_format->rate)) - return -ENXIO; - - err = snd_pcm_plugin_build(plug, "rate conversion", - src_format, dst_format, - sizeof(struct rate_priv) + - src_format->channels * sizeof(struct rate_channel), - &plugin); - if (err < 0) - return err; - data = (struct rate_priv *)plugin->extra_data; - if (src_format->rate < dst_format->rate) { - data->pitch = ((src_format->rate << SHIFT) + (dst_format->rate >> 1)) / dst_format->rate; - data->func = resample_expand; - } else { - data->pitch = ((dst_format->rate << SHIFT) + (src_format->rate >> 1)) / src_format->rate; - data->func = resample_shrink; - } - data->pos = 0; - rate_init(plugin); - data->old_src_frames = data->old_dst_frames = 0; - plugin->transfer = rate_transfer; - plugin->src_frames = rate_src_frames; - plugin->dst_frames = rate_dst_frames; - plugin->action = rate_action; - *r_plugin = plugin; - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/oss/route.c b/ANDROID_3.4.5/sound/core/oss/route.c deleted file mode 100644 index c8171f57..00000000 --- a/ANDROID_3.4.5/sound/core/oss/route.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Route Plug-In - * Copyright (c) 2000 by Abramo Bagnara - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include "pcm_plugin.h" - -static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts, - snd_pcm_uframes_t frames, snd_pcm_format_t format) -{ - int dst = 0; - for (; dst < ndsts; ++dst) { - if (dvp->wanted) - snd_pcm_area_silence(&dvp->area, 0, frames, format); - dvp->enabled = 0; - dvp++; - } -} - -static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel, - struct snd_pcm_plugin_channel *dst_channel, - snd_pcm_uframes_t frames, snd_pcm_format_t format) -{ - dst_channel->enabled = 1; - snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format); -} - -static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin, - const struct snd_pcm_plugin_channel *src_channels, - struct snd_pcm_plugin_channel *dst_channels, - snd_pcm_uframes_t frames) -{ - int nsrcs, ndsts, dst; - struct snd_pcm_plugin_channel *dvp; - snd_pcm_format_t format; - - if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) - return -ENXIO; - if (frames == 0) - return 0; - - nsrcs = plugin->src_format.channels; - ndsts = plugin->dst_format.channels; - - format = plugin->dst_format.format; - dvp = dst_channels; - if (nsrcs <= 1) { - /* expand to all channels */ - for (dst = 0; dst < ndsts; ++dst) { - copy_area(src_channels, dvp, frames, format); - dvp++; - } - return frames; - } - - for (dst = 0; dst < ndsts && dst < nsrcs; ++dst) { - copy_area(src_channels, dvp, frames, format); - dvp++; - src_channels++; - } - if (dst < ndsts) - zero_areas(dvp, ndsts - dst, frames, format); - return frames; -} - -int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug, - struct snd_pcm_plugin_format *src_format, - struct snd_pcm_plugin_format *dst_format, - struct snd_pcm_plugin **r_plugin) -{ - struct snd_pcm_plugin *plugin; - int err; - - if (snd_BUG_ON(!r_plugin)) - return -ENXIO; - *r_plugin = NULL; - if (snd_BUG_ON(src_format->rate != dst_format->rate)) - return -ENXIO; - if (snd_BUG_ON(src_format->format != dst_format->format)) - return -ENXIO; - - err = snd_pcm_plugin_build(plug, "route conversion", - src_format, dst_format, 0, &plugin); - if (err < 0) - return err; - - plugin->transfer = route_transfer; - *r_plugin = plugin; - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/pcm.c b/ANDROID_3.4.5/sound/core/pcm.c deleted file mode 100644 index e30e1be3..00000000 --- a/ANDROID_3.4.5/sound/core/pcm.c +++ /dev/null @@ -1,1220 +0,0 @@ -/* - * Digital Audio (PCM) abstract layer - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela , Abramo Bagnara "); -MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); -MODULE_LICENSE("GPL"); - -static LIST_HEAD(snd_pcm_devices); -static LIST_HEAD(snd_pcm_notify_list); -static DEFINE_MUTEX(register_mutex); - -static int snd_pcm_free(struct snd_pcm *pcm); -static int snd_pcm_dev_free(struct snd_device *device); -static int snd_pcm_dev_register(struct snd_device *device); -static int snd_pcm_dev_disconnect(struct snd_device *device); - -static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) -{ - struct snd_pcm *pcm; - - list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->card == card && pcm->device == device) - return pcm; - } - return NULL; -} - -static int snd_pcm_next(struct snd_card *card, int device) -{ - struct snd_pcm *pcm; - - list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->card == card && pcm->device > device) - return pcm->device; - else if (pcm->card->number > card->number) - return -1; - } - return -1; -} - -static int snd_pcm_add(struct snd_pcm *newpcm) -{ - struct snd_pcm *pcm; - - list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->card == newpcm->card && pcm->device == newpcm->device) - return -EBUSY; - if (pcm->card->number > newpcm->card->number || - (pcm->card == newpcm->card && - pcm->device > newpcm->device)) { - list_add(&newpcm->list, pcm->list.prev); - return 0; - } - } - list_add_tail(&newpcm->list, &snd_pcm_devices); - return 0; -} - -static int snd_pcm_control_ioctl(struct snd_card *card, - struct snd_ctl_file *control, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE: - { - int device; - - if (get_user(device, (int __user *)arg)) - return -EFAULT; - mutex_lock(®ister_mutex); - device = snd_pcm_next(card, device); - mutex_unlock(®ister_mutex); - if (put_user(device, (int __user *)arg)) - return -EFAULT; - return 0; - } - case SNDRV_CTL_IOCTL_PCM_INFO: - { - struct snd_pcm_info __user *info; - unsigned int device, subdevice; - int stream; - struct snd_pcm *pcm; - struct snd_pcm_str *pstr; - struct snd_pcm_substream *substream; - int err; - - info = (struct snd_pcm_info __user *)arg; - if (get_user(device, &info->device)) - return -EFAULT; - if (get_user(stream, &info->stream)) - return -EFAULT; - if (stream < 0 || stream > 1) - return -EINVAL; - if (get_user(subdevice, &info->subdevice)) - return -EFAULT; - mutex_lock(®ister_mutex); - pcm = snd_pcm_get(card, device); - if (pcm == NULL) { - err = -ENXIO; - goto _error; - } - pstr = &pcm->streams[stream]; - if (pstr->substream_count == 0) { - err = -ENOENT; - goto _error; - } - if (subdevice >= pstr->substream_count) { - err = -ENXIO; - goto _error; - } - for (substream = pstr->substream; substream; - substream = substream->next) - if (substream->number == (int)subdevice) - break; - if (substream == NULL) { - err = -ENXIO; - goto _error; - } - err = snd_pcm_info_user(substream, info); - _error: - mutex_unlock(®ister_mutex); - return err; - } - case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE: - { - int val; - - if (get_user(val, (int __user *)arg)) - return -EFAULT; - control->prefer_pcm_subdevice = val; - return 0; - } - } - return -ENOIOCTLCMD; -} - -#define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v - -static char *snd_pcm_format_names[] = { - FORMAT(S8), - FORMAT(U8), - FORMAT(S16_LE), - FORMAT(S16_BE), - FORMAT(U16_LE), - FORMAT(U16_BE), - FORMAT(S24_LE), - FORMAT(S24_BE), - FORMAT(U24_LE), - FORMAT(U24_BE), - FORMAT(S32_LE), - FORMAT(S32_BE), - FORMAT(U32_LE), - FORMAT(U32_BE), - FORMAT(FLOAT_LE), - FORMAT(FLOAT_BE), - FORMAT(FLOAT64_LE), - FORMAT(FLOAT64_BE), - FORMAT(IEC958_SUBFRAME_LE), - FORMAT(IEC958_SUBFRAME_BE), - FORMAT(MU_LAW), - FORMAT(A_LAW), - FORMAT(IMA_ADPCM), - FORMAT(MPEG), - FORMAT(GSM), - FORMAT(SPECIAL), - FORMAT(S24_3LE), - FORMAT(S24_3BE), - FORMAT(U24_3LE), - FORMAT(U24_3BE), - FORMAT(S20_3LE), - FORMAT(S20_3BE), - FORMAT(U20_3LE), - FORMAT(U20_3BE), - FORMAT(S18_3LE), - FORMAT(S18_3BE), - FORMAT(U18_3LE), - FORMAT(U18_3BE), - FORMAT(G723_24), - FORMAT(G723_24_1B), - FORMAT(G723_40), - FORMAT(G723_40_1B), -}; - -const char *snd_pcm_format_name(snd_pcm_format_t format) -{ - if ((__force unsigned int)format >= ARRAY_SIZE(snd_pcm_format_names)) - return "Unknown"; - return snd_pcm_format_names[(__force unsigned int)format]; -} -EXPORT_SYMBOL_GPL(snd_pcm_format_name); - -#ifdef CONFIG_SND_VERBOSE_PROCFS - -#define STATE(v) [SNDRV_PCM_STATE_##v] = #v -#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v -#define READY(v) [SNDRV_PCM_READY_##v] = #v -#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v -#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v -#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v -#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v -#define START(v) [SNDRV_PCM_START_##v] = #v -#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v - -static char *snd_pcm_stream_names[] = { - STREAM(PLAYBACK), - STREAM(CAPTURE), -}; - -static char *snd_pcm_state_names[] = { - STATE(OPEN), - STATE(SETUP), - STATE(PREPARED), - STATE(RUNNING), - STATE(XRUN), - STATE(DRAINING), - STATE(PAUSED), - STATE(SUSPENDED), -}; - -static char *snd_pcm_access_names[] = { - ACCESS(MMAP_INTERLEAVED), - ACCESS(MMAP_NONINTERLEAVED), - ACCESS(MMAP_COMPLEX), - ACCESS(RW_INTERLEAVED), - ACCESS(RW_NONINTERLEAVED), -}; - -static char *snd_pcm_subformat_names[] = { - SUBFORMAT(STD), -}; - -static char *snd_pcm_tstamp_mode_names[] = { - TSTAMP(NONE), - TSTAMP(ENABLE), -}; - -static const char *snd_pcm_stream_name(int stream) -{ - return snd_pcm_stream_names[stream]; -} - -static const char *snd_pcm_access_name(snd_pcm_access_t access) -{ - return snd_pcm_access_names[(__force int)access]; -} - -static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat) -{ - return snd_pcm_subformat_names[(__force int)subformat]; -} - -static const char *snd_pcm_tstamp_mode_name(int mode) -{ - return snd_pcm_tstamp_mode_names[mode]; -} - -static const char *snd_pcm_state_name(snd_pcm_state_t state) -{ - return snd_pcm_state_names[(__force int)state]; -} - -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) -#include - -static const char *snd_pcm_oss_format_name(int format) -{ - switch (format) { - case AFMT_MU_LAW: - return "MU_LAW"; - case AFMT_A_LAW: - return "A_LAW"; - case AFMT_IMA_ADPCM: - return "IMA_ADPCM"; - case AFMT_U8: - return "U8"; - case AFMT_S16_LE: - return "S16_LE"; - case AFMT_S16_BE: - return "S16_BE"; - case AFMT_S8: - return "S8"; - case AFMT_U16_LE: - return "U16_LE"; - case AFMT_U16_BE: - return "U16_BE"; - case AFMT_MPEG: - return "MPEG"; - default: - return "unknown"; - } -} -#endif - -static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_info *info; - int err; - - if (! substream) - return; - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) { - printk(KERN_DEBUG "snd_pcm_proc_info_read: cannot malloc\n"); - return; - } - - err = snd_pcm_info(substream, info); - if (err < 0) { - snd_iprintf(buffer, "error %d\n", err); - kfree(info); - return; - } - snd_iprintf(buffer, "card: %d\n", info->card); - snd_iprintf(buffer, "device: %d\n", info->device); - snd_iprintf(buffer, "subdevice: %d\n", info->subdevice); - snd_iprintf(buffer, "stream: %s\n", snd_pcm_stream_name(info->stream)); - snd_iprintf(buffer, "id: %s\n", info->id); - snd_iprintf(buffer, "name: %s\n", info->name); - snd_iprintf(buffer, "subname: %s\n", info->subname); - snd_iprintf(buffer, "class: %d\n", info->dev_class); - snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass); - snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count); - snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail); - kfree(info); -} - -static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_pcm_proc_info_read(((struct snd_pcm_str *)entry->private_data)->substream, - buffer); -} - -static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_pcm_proc_info_read(entry->private_data, buffer); -} - -static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_substream *substream = entry->private_data; - struct snd_pcm_runtime *runtime; - - mutex_lock(&substream->pcm->open_mutex); - runtime = substream->runtime; - if (!runtime) { - snd_iprintf(buffer, "closed\n"); - goto unlock; - } - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { - snd_iprintf(buffer, "no setup\n"); - goto unlock; - } - snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); - snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format)); - snd_iprintf(buffer, "subformat: %s\n", snd_pcm_subformat_name(runtime->subformat)); - snd_iprintf(buffer, "channels: %u\n", runtime->channels); - snd_iprintf(buffer, "rate: %u (%u/%u)\n", runtime->rate, runtime->rate_num, runtime->rate_den); - snd_iprintf(buffer, "period_size: %lu\n", runtime->period_size); - snd_iprintf(buffer, "buffer_size: %lu\n", runtime->buffer_size); -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) - if (substream->oss.oss) { - snd_iprintf(buffer, "OSS format: %s\n", snd_pcm_oss_format_name(runtime->oss.format)); - snd_iprintf(buffer, "OSS channels: %u\n", runtime->oss.channels); - snd_iprintf(buffer, "OSS rate: %u\n", runtime->oss.rate); - snd_iprintf(buffer, "OSS period bytes: %lu\n", (unsigned long)runtime->oss.period_bytes); - snd_iprintf(buffer, "OSS periods: %u\n", runtime->oss.periods); - snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames); - } -#endif - unlock: - mutex_unlock(&substream->pcm->open_mutex); -} - -static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_substream *substream = entry->private_data; - struct snd_pcm_runtime *runtime; - - mutex_lock(&substream->pcm->open_mutex); - runtime = substream->runtime; - if (!runtime) { - snd_iprintf(buffer, "closed\n"); - goto unlock; - } - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { - snd_iprintf(buffer, "no setup\n"); - goto unlock; - } - snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); - snd_iprintf(buffer, "period_step: %u\n", runtime->period_step); - snd_iprintf(buffer, "avail_min: %lu\n", runtime->control->avail_min); - snd_iprintf(buffer, "start_threshold: %lu\n", runtime->start_threshold); - snd_iprintf(buffer, "stop_threshold: %lu\n", runtime->stop_threshold); - snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); - snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); - snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary); - unlock: - mutex_unlock(&substream->pcm->open_mutex); -} - -static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_substream *substream = entry->private_data; - struct snd_pcm_runtime *runtime; - struct snd_pcm_status status; - int err; - - mutex_lock(&substream->pcm->open_mutex); - runtime = substream->runtime; - if (!runtime) { - snd_iprintf(buffer, "closed\n"); - goto unlock; - } - memset(&status, 0, sizeof(status)); - err = snd_pcm_status(substream, &status); - if (err < 0) { - snd_iprintf(buffer, "error %d\n", err); - goto unlock; - } - snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state)); - snd_iprintf(buffer, "owner_pid : %d\n", pid_vnr(substream->pid)); - snd_iprintf(buffer, "trigger_time: %ld.%09ld\n", - status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec); - snd_iprintf(buffer, "tstamp : %ld.%09ld\n", - status.tstamp.tv_sec, status.tstamp.tv_nsec); - snd_iprintf(buffer, "delay : %ld\n", status.delay); - snd_iprintf(buffer, "avail : %ld\n", status.avail); - snd_iprintf(buffer, "avail_max : %ld\n", status.avail_max); - snd_iprintf(buffer, "-----\n"); - snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr); - snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr); - unlock: - mutex_unlock(&substream->pcm->open_mutex); -} - -#ifdef CONFIG_SND_PCM_XRUN_DEBUG -static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_str *pstr = entry->private_data; - snd_iprintf(buffer, "%d\n", pstr->xrun_debug); -} - -static void snd_pcm_xrun_debug_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_str *pstr = entry->private_data; - char line[64]; - if (!snd_info_get_line(buffer, line, sizeof(line))) - pstr->xrun_debug = simple_strtoul(line, NULL, 10); -} -#endif - -static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) -{ - struct snd_pcm *pcm = pstr->pcm; - struct snd_info_entry *entry; - char name[16]; - - sprintf(name, "pcm%i%c", pcm->device, - pstr->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c'); - if ((entry = snd_info_create_card_entry(pcm->card, name, pcm->card->proc_root)) == NULL) - return -ENOMEM; - entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } - pstr->proc_root = entry; - - if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) { - snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read); - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - pstr->proc_info_entry = entry; - -#ifdef CONFIG_SND_PCM_XRUN_DEBUG - if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", - pstr->proc_root)) != NULL) { - entry->c.text.read = snd_pcm_xrun_debug_read; - entry->c.text.write = snd_pcm_xrun_debug_write; - entry->mode |= S_IWUSR; - entry->private_data = pstr; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - pstr->proc_xrun_debug_entry = entry; -#endif - return 0; -} - -static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) -{ -#ifdef CONFIG_SND_PCM_XRUN_DEBUG - snd_info_free_entry(pstr->proc_xrun_debug_entry); - pstr->proc_xrun_debug_entry = NULL; -#endif - snd_info_free_entry(pstr->proc_info_entry); - pstr->proc_info_entry = NULL; - snd_info_free_entry(pstr->proc_root); - pstr->proc_root = NULL; - return 0; -} - -static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) -{ - struct snd_info_entry *entry; - struct snd_card *card; - char name[16]; - - card = substream->pcm->card; - - sprintf(name, "sub%i", substream->number); - if ((entry = snd_info_create_card_entry(card, name, substream->pstr->proc_root)) == NULL) - return -ENOMEM; - entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } - substream->proc_root = entry; - - if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) { - snd_info_set_text_ops(entry, substream, - snd_pcm_substream_proc_info_read); - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - substream->proc_info_entry = entry; - - if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) { - snd_info_set_text_ops(entry, substream, - snd_pcm_substream_proc_hw_params_read); - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - substream->proc_hw_params_entry = entry; - - if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) { - snd_info_set_text_ops(entry, substream, - snd_pcm_substream_proc_sw_params_read); - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - substream->proc_sw_params_entry = entry; - - if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) { - snd_info_set_text_ops(entry, substream, - snd_pcm_substream_proc_status_read); - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - substream->proc_status_entry = entry; - - return 0; -} - -static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) -{ - snd_info_free_entry(substream->proc_info_entry); - substream->proc_info_entry = NULL; - snd_info_free_entry(substream->proc_hw_params_entry); - substream->proc_hw_params_entry = NULL; - snd_info_free_entry(substream->proc_sw_params_entry); - substream->proc_sw_params_entry = NULL; - snd_info_free_entry(substream->proc_status_entry); - substream->proc_status_entry = NULL; - snd_info_free_entry(substream->proc_root); - substream->proc_root = NULL; - return 0; -} -#else /* !CONFIG_SND_VERBOSE_PROCFS */ -static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; } -static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; } -static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; } -static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; } -#endif /* CONFIG_SND_VERBOSE_PROCFS */ - -/** - * snd_pcm_new_stream - create a new PCM stream - * @pcm: the pcm instance - * @stream: the stream direction, SNDRV_PCM_STREAM_XXX - * @substream_count: the number of substreams - * - * Creates a new stream for the pcm. - * The corresponding stream on the pcm must have been empty before - * calling this, i.e. zero must be given to the argument of - * snd_pcm_new(). - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) -{ - int idx, err; - struct snd_pcm_str *pstr = &pcm->streams[stream]; - struct snd_pcm_substream *substream, *prev; - -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) - mutex_init(&pstr->oss.setup_mutex); -#endif - pstr->stream = stream; - pstr->pcm = pcm; - pstr->substream_count = substream_count; - if (substream_count > 0 && !pcm->internal) { - err = snd_pcm_stream_proc_init(pstr); - if (err < 0) { - snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n"); - return err; - } - } - prev = NULL; - for (idx = 0, prev = NULL; idx < substream_count; idx++) { - substream = kzalloc(sizeof(*substream), GFP_KERNEL); - if (substream == NULL) { - snd_printk(KERN_ERR "Cannot allocate PCM substream\n"); - return -ENOMEM; - } - substream->pcm = pcm; - substream->pstr = pstr; - substream->number = idx; - substream->stream = stream; - sprintf(substream->name, "subdevice #%i", idx); - substream->buffer_bytes_max = UINT_MAX; - if (prev == NULL) - pstr->substream = substream; - else - prev->next = substream; - - if (!pcm->internal) { - err = snd_pcm_substream_proc_init(substream); - if (err < 0) { - snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n"); - if (prev == NULL) - pstr->substream = NULL; - else - prev->next = NULL; - kfree(substream); - return err; - } - } - substream->group = &substream->self_group; - spin_lock_init(&substream->self_group.lock); - INIT_LIST_HEAD(&substream->self_group.substreams); - list_add_tail(&substream->link_list, &substream->self_group.substreams); - atomic_set(&substream->mmap_count, 0); - prev = substream; - } - return 0; -} - -EXPORT_SYMBOL(snd_pcm_new_stream); - -static int _snd_pcm_new(struct snd_card *card, const char *id, int device, - int playback_count, int capture_count, bool internal, - struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_pcm_dev_free, - .dev_register = snd_pcm_dev_register, - .dev_disconnect = snd_pcm_dev_disconnect, - }; - - if (snd_BUG_ON(!card)) - return -ENXIO; - if (rpcm) - *rpcm = NULL; - pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); - if (pcm == NULL) { - snd_printk(KERN_ERR "Cannot allocate PCM\n"); - return -ENOMEM; - } - pcm->card = card; - pcm->device = device; - pcm->internal = internal; - if (id) - strlcpy(pcm->id, id, sizeof(pcm->id)); - if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) { - snd_pcm_free(pcm); - return err; - } - if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count)) < 0) { - snd_pcm_free(pcm); - return err; - } - mutex_init(&pcm->open_mutex); - init_waitqueue_head(&pcm->open_wait); - if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) { - snd_pcm_free(pcm); - return err; - } - if (rpcm) - *rpcm = pcm; - return 0; -} - -/** - * snd_pcm_new - create a new PCM instance - * @card: the card instance - * @id: the id string - * @device: the device index (zero based) - * @playback_count: the number of substreams for playback - * @capture_count: the number of substreams for capture - * @rpcm: the pointer to store the new pcm instance - * - * Creates a new PCM instance. - * - * The pcm operators have to be set afterwards to the new instance - * via snd_pcm_set_ops(). - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_new(struct snd_card *card, const char *id, int device, - int playback_count, int capture_count, struct snd_pcm **rpcm) -{ - return _snd_pcm_new(card, id, device, playback_count, capture_count, - false, rpcm); -} -EXPORT_SYMBOL(snd_pcm_new); - -/** - * snd_pcm_new_internal - create a new internal PCM instance - * @card: the card instance - * @id: the id string - * @device: the device index (zero based - shared with normal PCMs) - * @playback_count: the number of substreams for playback - * @capture_count: the number of substreams for capture - * @rpcm: the pointer to store the new pcm instance - * - * Creates a new internal PCM instance with no userspace device or procfs - * entries. This is used by ASoC Back End PCMs in order to create a PCM that - * will only be used internally by kernel drivers. i.e. it cannot be opened - * by userspace. It provides existing ASoC components drivers with a substream - * and access to any private data. - * - * The pcm operators have to be set afterwards to the new instance - * via snd_pcm_set_ops(). - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_new_internal(struct snd_card *card, const char *id, int device, - int playback_count, int capture_count, - struct snd_pcm **rpcm) -{ - return _snd_pcm_new(card, id, device, playback_count, capture_count, - true, rpcm); -} -EXPORT_SYMBOL(snd_pcm_new_internal); - -static void snd_pcm_free_stream(struct snd_pcm_str * pstr) -{ - struct snd_pcm_substream *substream, *substream_next; -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) - struct snd_pcm_oss_setup *setup, *setupn; -#endif - substream = pstr->substream; - while (substream) { - substream_next = substream->next; - snd_pcm_timer_done(substream); - snd_pcm_substream_proc_done(substream); - kfree(substream); - substream = substream_next; - } - snd_pcm_stream_proc_done(pstr); -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) - for (setup = pstr->oss.setup_list; setup; setup = setupn) { - setupn = setup->next; - kfree(setup->task_name); - kfree(setup); - } -#endif -} - -static int snd_pcm_free(struct snd_pcm *pcm) -{ - struct snd_pcm_notify *notify; - - if (!pcm) - return 0; - list_for_each_entry(notify, &snd_pcm_notify_list, list) { - notify->n_unregister(pcm); - } - if (pcm->private_free) - pcm->private_free(pcm); - snd_pcm_lib_preallocate_free_for_all(pcm); - snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]); - snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_CAPTURE]); - kfree(pcm); - return 0; -} - -static int snd_pcm_dev_free(struct snd_device *device) -{ - struct snd_pcm *pcm = device->device_data; - return snd_pcm_free(pcm); -} - -int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, - struct file *file, - struct snd_pcm_substream **rsubstream) -{ - struct snd_pcm_str * pstr; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - struct snd_ctl_file *kctl; - struct snd_card *card; - int prefer_subdevice = -1; - size_t size; - - if (snd_BUG_ON(!pcm || !rsubstream)) - return -ENXIO; - *rsubstream = NULL; - pstr = &pcm->streams[stream]; - if (pstr->substream == NULL || pstr->substream_count == 0) - return -ENODEV; - - card = pcm->card; - read_lock(&card->ctl_files_rwlock); - list_for_each_entry(kctl, &card->ctl_files, list) { - if (kctl->pid == task_pid(current)) { - prefer_subdevice = kctl->prefer_pcm_subdevice; - if (prefer_subdevice != -1) - break; - } - } - read_unlock(&card->ctl_files_rwlock); - - switch (stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { - for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) { - if (SUBSTREAM_BUSY(substream)) - return -EAGAIN; - } - } - break; - case SNDRV_PCM_STREAM_CAPTURE: - if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) { - if (SUBSTREAM_BUSY(substream)) - return -EAGAIN; - } - } - break; - default: - return -EINVAL; - } - - if (file->f_flags & O_APPEND) { - if (prefer_subdevice < 0) { - if (pstr->substream_count > 1) - return -EINVAL; /* must be unique */ - substream = pstr->substream; - } else { - for (substream = pstr->substream; substream; - substream = substream->next) - if (substream->number == prefer_subdevice) - break; - } - if (! substream) - return -ENODEV; - if (! SUBSTREAM_BUSY(substream)) - return -EBADFD; - substream->ref_count++; - *rsubstream = substream; - return 0; - } - - if (prefer_subdevice >= 0) { - for (substream = pstr->substream; substream; substream = substream->next) - if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) - goto __ok; - } - for (substream = pstr->substream; substream; substream = substream->next) - if (!SUBSTREAM_BUSY(substream)) - break; - __ok: - if (substream == NULL) - return -EAGAIN; - - runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); - if (runtime == NULL) - return -ENOMEM; - - size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)); - runtime->status = snd_malloc_pages(size, GFP_KERNEL); - if (runtime->status == NULL) { - kfree(runtime); - return -ENOMEM; - } - memset((void*)runtime->status, 0, size); - - size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)); - runtime->control = snd_malloc_pages(size, GFP_KERNEL); - if (runtime->control == NULL) { - snd_free_pages((void*)runtime->status, - PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))); - kfree(runtime); - return -ENOMEM; - } - memset((void*)runtime->control, 0, size); - - init_waitqueue_head(&runtime->sleep); - init_waitqueue_head(&runtime->tsleep); - - runtime->status->state = SNDRV_PCM_STATE_OPEN; - - substream->runtime = runtime; - substream->private_data = pcm->private_data; - substream->ref_count = 1; - substream->f_flags = file->f_flags; - substream->pid = get_pid(task_pid(current)); - pstr->substream_opened++; - *rsubstream = substream; - return 0; -} - -void snd_pcm_detach_substream(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - - if (PCM_RUNTIME_CHECK(substream)) - return; - runtime = substream->runtime; - if (runtime->private_free != NULL) - runtime->private_free(runtime); - snd_free_pages((void*)runtime->status, - PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))); - snd_free_pages((void*)runtime->control, - PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))); - kfree(runtime->hw_constraints.rules); -#ifdef CONFIG_SND_PCM_XRUN_DEBUG - if (runtime->hwptr_log) - kfree(runtime->hwptr_log); -#endif - kfree(runtime); - substream->runtime = NULL; - put_pid(substream->pid); - substream->pid = NULL; - substream->pstr->substream_opened--; -} - -static ssize_t show_pcm_class(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct snd_pcm *pcm; - const char *str; - static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = { - [SNDRV_PCM_CLASS_GENERIC] = "generic", - [SNDRV_PCM_CLASS_MULTI] = "multi", - [SNDRV_PCM_CLASS_MODEM] = "modem", - [SNDRV_PCM_CLASS_DIGITIZER] = "digitizer", - }; - - if (! (pcm = dev_get_drvdata(dev)) || - pcm->dev_class > SNDRV_PCM_CLASS_LAST) - str = "none"; - else - str = strs[pcm->dev_class]; - return snprintf(buf, PAGE_SIZE, "%s\n", str); -} - -static struct device_attribute pcm_attrs = - __ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL); - -static int snd_pcm_dev_register(struct snd_device *device) -{ - int cidx, err; - struct snd_pcm_substream *substream; - struct snd_pcm_notify *notify; - char str[16]; - struct snd_pcm *pcm; - struct device *dev; - - if (snd_BUG_ON(!device || !device->device_data)) - return -ENXIO; - pcm = device->device_data; - mutex_lock(®ister_mutex); - err = snd_pcm_add(pcm); - if (err) { - mutex_unlock(®ister_mutex); - return err; - } - for (cidx = 0; cidx < 2; cidx++) { - int devtype = -1; - if (pcm->streams[cidx].substream == NULL || pcm->internal) - continue; - switch (cidx) { - case SNDRV_PCM_STREAM_PLAYBACK: - sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device); - devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; - break; - case SNDRV_PCM_STREAM_CAPTURE: - sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device); - devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; - break; - } - /* device pointer to use, pcm->dev takes precedence if - * it is assigned, otherwise fall back to card's device - * if possible */ - dev = pcm->dev; - if (!dev) - dev = snd_card_get_device_link(pcm->card); - /* register pcm */ - err = snd_register_device_for_dev(devtype, pcm->card, - pcm->device, - &snd_pcm_f_ops[cidx], - pcm, str, dev); - if (err < 0) { - list_del(&pcm->list); - mutex_unlock(®ister_mutex); - return err; - } - snd_add_device_sysfs_file(devtype, pcm->card, pcm->device, - &pcm_attrs); - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) - snd_pcm_timer_init(substream); - } - - list_for_each_entry(notify, &snd_pcm_notify_list, list) - notify->n_register(pcm); - - mutex_unlock(®ister_mutex); - return 0; -} - -static int snd_pcm_dev_disconnect(struct snd_device *device) -{ - struct snd_pcm *pcm = device->device_data; - struct snd_pcm_notify *notify; - struct snd_pcm_substream *substream; - int cidx, devtype; - - mutex_lock(®ister_mutex); - if (list_empty(&pcm->list)) - goto unlock; - - mutex_lock(&pcm->open_mutex); - wake_up(&pcm->open_wait); - list_del_init(&pcm->list); - for (cidx = 0; cidx < 2; cidx++) - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { - snd_pcm_stream_lock_irq(substream); - if (substream->runtime) { - substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; - wake_up(&substream->runtime->sleep); - wake_up(&substream->runtime->tsleep); - } - snd_pcm_stream_unlock_irq(substream); - } - list_for_each_entry(notify, &snd_pcm_notify_list, list) { - notify->n_disconnect(pcm); - } - for (cidx = 0; cidx < 2; cidx++) { - devtype = -1; - switch (cidx) { - case SNDRV_PCM_STREAM_PLAYBACK: - devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; - break; - case SNDRV_PCM_STREAM_CAPTURE: - devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; - break; - } - snd_unregister_device(devtype, pcm->card, pcm->device); - } - mutex_unlock(&pcm->open_mutex); - unlock: - mutex_unlock(®ister_mutex); - return 0; -} - -int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) -{ - struct snd_pcm *pcm; - - if (snd_BUG_ON(!notify || - !notify->n_register || - !notify->n_unregister || - !notify->n_disconnect)) - return -EINVAL; - mutex_lock(®ister_mutex); - if (nfree) { - list_del(¬ify->list); - list_for_each_entry(pcm, &snd_pcm_devices, list) - notify->n_unregister(pcm); - } else { - list_add_tail(¬ify->list, &snd_pcm_notify_list); - list_for_each_entry(pcm, &snd_pcm_devices, list) - notify->n_register(pcm); - } - mutex_unlock(®ister_mutex); - return 0; -} - -EXPORT_SYMBOL(snd_pcm_notify); - -#ifdef CONFIG_PROC_FS -/* - * Info interface - */ - -static void snd_pcm_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm *pcm; - - mutex_lock(®ister_mutex); - list_for_each_entry(pcm, &snd_pcm_devices, list) { - snd_iprintf(buffer, "%02i-%02i: %s : %s", - pcm->card->number, pcm->device, pcm->id, pcm->name); - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) - snd_iprintf(buffer, " : playback %i", - pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count); - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) - snd_iprintf(buffer, " : capture %i", - pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count); - snd_iprintf(buffer, "\n"); - } - mutex_unlock(®ister_mutex); -} - -static struct snd_info_entry *snd_pcm_proc_entry; - -static void snd_pcm_proc_init(void) -{ - struct snd_info_entry *entry; - - if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) { - snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read); - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_pcm_proc_entry = entry; -} - -static void snd_pcm_proc_done(void) -{ - snd_info_free_entry(snd_pcm_proc_entry); -} - -#else /* !CONFIG_PROC_FS */ -#define snd_pcm_proc_init() -#define snd_pcm_proc_done() -#endif /* CONFIG_PROC_FS */ - - -/* - * ENTRY functions - */ - -static int __init alsa_pcm_init(void) -{ - snd_ctl_register_ioctl(snd_pcm_control_ioctl); - snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl); - snd_pcm_proc_init(); - return 0; -} - -static void __exit alsa_pcm_exit(void) -{ - snd_ctl_unregister_ioctl(snd_pcm_control_ioctl); - snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl); - snd_pcm_proc_done(); -} - -module_init(alsa_pcm_init) -module_exit(alsa_pcm_exit) diff --git a/ANDROID_3.4.5/sound/core/pcm_compat.c b/ANDROID_3.4.5/sound/core/pcm_compat.c deleted file mode 100644 index 91cdf943..00000000 --- a/ANDROID_3.4.5/sound/core/pcm_compat.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for PCM API - * Copyright (c) by Takashi Iwai - * - * 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 - * - */ - -/* This file included from pcm_native.c */ - -#include -#include - -static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream, - s32 __user *src) -{ - snd_pcm_sframes_t delay; - mm_segment_t fs; - int err; - - fs = snd_enter_user(); - err = snd_pcm_delay(substream, &delay); - snd_leave_user(fs); - if (err < 0) - return err; - if (put_user(delay, src)) - return -EFAULT; - return err; -} - -static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream, - u32 __user *src) -{ - snd_pcm_uframes_t frames; - int err; - - if (get_user(frames, src)) - return -EFAULT; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - err = snd_pcm_playback_rewind(substream, frames); - else - err = snd_pcm_capture_rewind(substream, frames); - if (put_user(err, src)) - return -EFAULT; - return err < 0 ? err : 0; -} - -static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream, - u32 __user *src) -{ - snd_pcm_uframes_t frames; - int err; - - if (get_user(frames, src)) - return -EFAULT; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - err = snd_pcm_playback_forward(substream, frames); - else - err = snd_pcm_capture_forward(substream, frames); - if (put_user(err, src)) - return -EFAULT; - return err < 0 ? err : 0; -} - -struct snd_pcm_hw_params32 { - u32 flags; - struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */ - struct snd_mask mres[5]; /* reserved masks */ - struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; - struct snd_interval ires[9]; /* reserved intervals */ - u32 rmask; - u32 cmask; - u32 info; - u32 msbits; - u32 rate_num; - u32 rate_den; - u32 fifo_size; - unsigned char reserved[64]; -}; - -struct snd_pcm_sw_params32 { - s32 tstamp_mode; - u32 period_step; - u32 sleep_min; - u32 avail_min; - u32 xfer_align; - u32 start_threshold; - u32 stop_threshold; - u32 silence_threshold; - u32 silence_size; - u32 boundary; - unsigned char reserved[64]; -}; - -/* recalcuate the boundary within 32bit */ -static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime) -{ - snd_pcm_uframes_t boundary; - - if (! runtime->buffer_size) - return 0; - boundary = runtime->buffer_size; - while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size) - boundary *= 2; - return boundary; -} - -static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream, - struct snd_pcm_sw_params32 __user *src) -{ - struct snd_pcm_sw_params params; - snd_pcm_uframes_t boundary; - int err; - - memset(¶ms, 0, sizeof(params)); - if (get_user(params.tstamp_mode, &src->tstamp_mode) || - get_user(params.period_step, &src->period_step) || - get_user(params.sleep_min, &src->sleep_min) || - get_user(params.avail_min, &src->avail_min) || - get_user(params.xfer_align, &src->xfer_align) || - get_user(params.start_threshold, &src->start_threshold) || - get_user(params.stop_threshold, &src->stop_threshold) || - get_user(params.silence_threshold, &src->silence_threshold) || - get_user(params.silence_size, &src->silence_size)) - return -EFAULT; - /* - * Check silent_size parameter. Since we have 64bit boundary, - * silence_size must be compared with the 32bit boundary. - */ - boundary = recalculate_boundary(substream->runtime); - if (boundary && params.silence_size >= boundary) - params.silence_size = substream->runtime->boundary; - err = snd_pcm_sw_params(substream, ¶ms); - if (err < 0) - return err; - if (boundary && put_user(boundary, &src->boundary)) - return -EFAULT; - return err; -} - -struct snd_pcm_channel_info32 { - u32 channel; - u32 offset; - u32 first; - u32 step; -}; - -static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream, - struct snd_pcm_channel_info32 __user *src) -{ - struct snd_pcm_channel_info info; - int err; - - if (get_user(info.channel, &src->channel) || - get_user(info.offset, &src->offset) || - get_user(info.first, &src->first) || - get_user(info.step, &src->step)) - return -EFAULT; - err = snd_pcm_channel_info(substream, &info); - if (err < 0) - return err; - if (put_user(info.channel, &src->channel) || - put_user(info.offset, &src->offset) || - put_user(info.first, &src->first) || - put_user(info.step, &src->step)) - return -EFAULT; - return err; -} - -struct snd_pcm_status32 { - s32 state; - struct compat_timespec trigger_tstamp; - struct compat_timespec tstamp; - u32 appl_ptr; - u32 hw_ptr; - s32 delay; - u32 avail; - u32 avail_max; - u32 overrange; - s32 suspended_state; - unsigned char reserved[60]; -} __attribute__((packed)); - - -static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, - struct snd_pcm_status32 __user *src) -{ - struct snd_pcm_status status; - int err; - - err = snd_pcm_status(substream, &status); - if (err < 0) - return err; - - if (put_user(status.state, &src->state) || - put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) || - put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) || - put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || - put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || - put_user(status.appl_ptr, &src->appl_ptr) || - put_user(status.hw_ptr, &src->hw_ptr) || - put_user(status.delay, &src->delay) || - put_user(status.avail, &src->avail) || - put_user(status.avail_max, &src->avail_max) || - put_user(status.overrange, &src->overrange) || - put_user(status.suspended_state, &src->suspended_state)) - return -EFAULT; - - return err; -} - -/* both for HW_PARAMS and HW_REFINE */ -static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, - int refine, - struct snd_pcm_hw_params32 __user *data32) -{ - struct snd_pcm_hw_params *data; - struct snd_pcm_runtime *runtime; - int err; - - if (! (runtime = substream->runtime)) - return -ENOTTY; - - /* only fifo_size is different, so just copy all */ - data = memdup_user(data32, sizeof(*data32)); - if (IS_ERR(data)) - return PTR_ERR(data); - - if (refine) - err = snd_pcm_hw_refine(substream, data); - else - err = snd_pcm_hw_params(substream, data); - if (err < 0) - goto error; - if (copy_to_user(data32, data, sizeof(*data32)) || - put_user(data->fifo_size, &data32->fifo_size)) { - err = -EFAULT; - goto error; - } - - if (! refine) { - unsigned int new_boundary = recalculate_boundary(runtime); - if (new_boundary) - runtime->boundary = new_boundary; - } - error: - kfree(data); - return err; -} - - -/* - */ -struct snd_xferi32 { - s32 result; - u32 buf; - u32 frames; -}; - -static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream, - int dir, struct snd_xferi32 __user *data32) -{ - compat_caddr_t buf; - u32 frames; - int err; - - if (! substream->runtime) - return -ENOTTY; - if (substream->stream != dir) - return -EINVAL; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - - if (get_user(buf, &data32->buf) || - get_user(frames, &data32->frames)) - return -EFAULT; - - if (dir == SNDRV_PCM_STREAM_PLAYBACK) - err = snd_pcm_lib_write(substream, compat_ptr(buf), frames); - else - err = snd_pcm_lib_read(substream, compat_ptr(buf), frames); - if (err < 0) - return err; - /* copy the result */ - if (put_user(err, &data32->result)) - return -EFAULT; - return 0; -} - - -/* snd_xfern needs remapping of bufs */ -struct snd_xfern32 { - s32 result; - u32 bufs; /* this is void **; */ - u32 frames; -}; - -/* - * xfern ioctl nees to copy (up to) 128 pointers on stack. - * although we may pass the copied pointers through f_op->ioctl, but the ioctl - * handler there expands again the same 128 pointers on stack, so it is better - * to handle the function (calling pcm_readv/writev) directly in this handler. - */ -static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, - int dir, struct snd_xfern32 __user *data32) -{ - compat_caddr_t buf; - compat_caddr_t __user *bufptr; - u32 frames; - void __user **bufs; - int err, ch, i; - - if (! substream->runtime) - return -ENOTTY; - if (substream->stream != dir) - return -EINVAL; - - if ((ch = substream->runtime->channels) > 128) - return -EINVAL; - if (get_user(buf, &data32->bufs) || - get_user(frames, &data32->frames)) - return -EFAULT; - bufptr = compat_ptr(buf); - bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL); - if (bufs == NULL) - return -ENOMEM; - for (i = 0; i < ch; i++) { - u32 ptr; - if (get_user(ptr, bufptr)) { - kfree(bufs); - return -EFAULT; - } - bufs[i] = compat_ptr(ptr); - bufptr++; - } - if (dir == SNDRV_PCM_STREAM_PLAYBACK) - err = snd_pcm_lib_writev(substream, bufs, frames); - else - err = snd_pcm_lib_readv(substream, bufs, frames); - if (err >= 0) { - if (put_user(err, &data32->result)) - err = -EFAULT; - } - kfree(bufs); - return err; -} - - -struct snd_pcm_mmap_status32 { - s32 state; - s32 pad1; - u32 hw_ptr; - struct compat_timespec tstamp; - s32 suspended_state; -} __attribute__((packed)); - -struct snd_pcm_mmap_control32 { - u32 appl_ptr; - u32 avail_min; -}; - -struct snd_pcm_sync_ptr32 { - u32 flags; - union { - struct snd_pcm_mmap_status32 status; - unsigned char reserved[64]; - } s; - union { - struct snd_pcm_mmap_control32 control; - unsigned char reserved[64]; - } c; -} __attribute__((packed)); - -static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, - struct snd_pcm_sync_ptr32 __user *src) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - volatile struct snd_pcm_mmap_status *status; - volatile struct snd_pcm_mmap_control *control; - u32 sflags; - struct snd_pcm_mmap_control scontrol; - struct snd_pcm_mmap_status sstatus; - snd_pcm_uframes_t boundary; - int err; - - if (snd_BUG_ON(!runtime)) - return -EINVAL; - - if (get_user(sflags, &src->flags) || - get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || - get_user(scontrol.avail_min, &src->c.control.avail_min)) - return -EFAULT; - if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { - err = snd_pcm_hwsync(substream); - if (err < 0) - return err; - } - status = runtime->status; - control = runtime->control; - boundary = recalculate_boundary(runtime); - if (! boundary) - boundary = 0x7fffffff; - snd_pcm_stream_lock_irq(substream); - /* FIXME: we should consider the boundary for the sync from app */ - if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) - control->appl_ptr = scontrol.appl_ptr; - else - scontrol.appl_ptr = control->appl_ptr % boundary; - if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) - control->avail_min = scontrol.avail_min; - else - scontrol.avail_min = control->avail_min; - sstatus.state = status->state; - sstatus.hw_ptr = status->hw_ptr % boundary; - sstatus.tstamp = status->tstamp; - sstatus.suspended_state = status->suspended_state; - snd_pcm_stream_unlock_irq(substream); - if (put_user(sstatus.state, &src->s.status.state) || - put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || - put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) || - put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) || - put_user(sstatus.suspended_state, &src->s.status.suspended_state) || - put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || - put_user(scontrol.avail_min, &src->c.control.avail_min)) - return -EFAULT; - - return 0; -} - - -/* - */ -enum { - SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32), - SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32), - SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32), - SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32), - SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), - SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32), - SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), - SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32), - SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct snd_xferi32), - SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32), - SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32), - SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32), - SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32), - -}; - -static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream; - void __user *argp = compat_ptr(arg); - - pcm_file = file->private_data; - if (! pcm_file) - return -ENOTTY; - substream = pcm_file->substream; - if (! substream) - return -ENOTTY; - - /* - * When PCM is used on 32bit mode, we need to disable - * mmap of PCM status/control records because of the size - * incompatibility. - */ - pcm_file->no_compat_mmap = 1; - - switch (cmd) { - case SNDRV_PCM_IOCTL_PVERSION: - case SNDRV_PCM_IOCTL_INFO: - case SNDRV_PCM_IOCTL_TSTAMP: - case SNDRV_PCM_IOCTL_TTSTAMP: - case SNDRV_PCM_IOCTL_HWSYNC: - case SNDRV_PCM_IOCTL_PREPARE: - case SNDRV_PCM_IOCTL_RESET: - case SNDRV_PCM_IOCTL_START: - case SNDRV_PCM_IOCTL_DROP: - case SNDRV_PCM_IOCTL_DRAIN: - case SNDRV_PCM_IOCTL_PAUSE: - case SNDRV_PCM_IOCTL_HW_FREE: - case SNDRV_PCM_IOCTL_RESUME: - case SNDRV_PCM_IOCTL_XRUN: - case SNDRV_PCM_IOCTL_LINK: - case SNDRV_PCM_IOCTL_UNLINK: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - return snd_pcm_playback_ioctl1(file, substream, cmd, argp); - else - return snd_pcm_capture_ioctl1(file, substream, cmd, argp); - case SNDRV_PCM_IOCTL_HW_REFINE32: - return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); - case SNDRV_PCM_IOCTL_HW_PARAMS32: - return snd_pcm_ioctl_hw_params_compat(substream, 0, argp); - case SNDRV_PCM_IOCTL_SW_PARAMS32: - return snd_pcm_ioctl_sw_params_compat(substream, argp); - case SNDRV_PCM_IOCTL_STATUS32: - return snd_pcm_status_user_compat(substream, argp); - case SNDRV_PCM_IOCTL_SYNC_PTR32: - return snd_pcm_ioctl_sync_ptr_compat(substream, argp); - case SNDRV_PCM_IOCTL_CHANNEL_INFO32: - return snd_pcm_ioctl_channel_info_compat(substream, argp); - case SNDRV_PCM_IOCTL_WRITEI_FRAMES32: - return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); - case SNDRV_PCM_IOCTL_READI_FRAMES32: - return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); - case SNDRV_PCM_IOCTL_WRITEN_FRAMES32: - return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); - case SNDRV_PCM_IOCTL_READN_FRAMES32: - return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); - case SNDRV_PCM_IOCTL_DELAY32: - return snd_pcm_ioctl_delay_compat(substream, argp); - case SNDRV_PCM_IOCTL_REWIND32: - return snd_pcm_ioctl_rewind_compat(substream, argp); - case SNDRV_PCM_IOCTL_FORWARD32: - return snd_pcm_ioctl_forward_compat(substream, argp); - } - - return -ENOIOCTLCMD; -} diff --git a/ANDROID_3.4.5/sound/core/pcm_lib.c b/ANDROID_3.4.5/sound/core/pcm_lib.c deleted file mode 100644 index 4d189411..00000000 --- a/ANDROID_3.4.5/sound/core/pcm_lib.c +++ /dev/null @@ -1,2289 +0,0 @@ -/* - * Digital Audio (PCM) abstract layer - * Copyright (c) by Jaroslav Kysela - * Abramo Bagnara - * - * - * 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 -#include - -/* - * fill ring buffer with silence - * runtime->silence_start: starting pointer to silence area - * runtime->silence_filled: size filled with silence - * runtime->silence_threshold: threshold from application - * runtime->silence_size: maximal size from application - * - * when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately - */ -void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t frames, ofs, transfer; - - if (runtime->silence_size < runtime->boundary) { - snd_pcm_sframes_t noise_dist, n; - if (runtime->silence_start != runtime->control->appl_ptr) { - n = runtime->control->appl_ptr - runtime->silence_start; - if (n < 0) - n += runtime->boundary; - if ((snd_pcm_uframes_t)n < runtime->silence_filled) - runtime->silence_filled -= n; - else - runtime->silence_filled = 0; - runtime->silence_start = runtime->control->appl_ptr; - } - if (runtime->silence_filled >= runtime->buffer_size) - return; - noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled; - if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold) - return; - frames = runtime->silence_threshold - noise_dist; - if (frames > runtime->silence_size) - frames = runtime->silence_size; - } else { - if (new_hw_ptr == ULONG_MAX) { /* initialization */ - snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime); - if (avail > runtime->buffer_size) - avail = runtime->buffer_size; - runtime->silence_filled = avail > 0 ? avail : 0; - runtime->silence_start = (runtime->status->hw_ptr + - runtime->silence_filled) % - runtime->boundary; - } else { - ofs = runtime->status->hw_ptr; - frames = new_hw_ptr - ofs; - if ((snd_pcm_sframes_t)frames < 0) - frames += runtime->boundary; - runtime->silence_filled -= frames; - if ((snd_pcm_sframes_t)runtime->silence_filled < 0) { - runtime->silence_filled = 0; - runtime->silence_start = new_hw_ptr; - } else { - runtime->silence_start = ofs; - } - } - frames = runtime->buffer_size - runtime->silence_filled; - } - if (snd_BUG_ON(frames > runtime->buffer_size)) - return; - if (frames == 0) - return; - ofs = runtime->silence_start % runtime->buffer_size; - while (frames > 0) { - transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; - if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || - runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { - if (substream->ops->silence) { - int err; - err = substream->ops->silence(substream, -1, ofs, transfer); - snd_BUG_ON(err < 0); - } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); - } - } else { - unsigned int c; - unsigned int channels = runtime->channels; - if (substream->ops->silence) { - for (c = 0; c < channels; ++c) { - int err; - err = substream->ops->silence(substream, c, ofs, transfer); - snd_BUG_ON(err < 0); - } - } else { - size_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c) { - char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer); - } - } - } - runtime->silence_filled += transfer; - frames -= transfer; - ofs = 0; - } -} - -#ifdef CONFIG_SND_DEBUG -void snd_pcm_debug_name(struct snd_pcm_substream *substream, - char *name, size_t len) -{ - snprintf(name, len, "pcmC%dD%d%c:%d", - substream->pcm->card->number, - substream->pcm->device, - substream->stream ? 'c' : 'p', - substream->number); -} -EXPORT_SYMBOL(snd_pcm_debug_name); -#endif - -#define XRUN_DEBUG_BASIC (1<<0) -#define XRUN_DEBUG_STACK (1<<1) /* dump also stack */ -#define XRUN_DEBUG_JIFFIESCHECK (1<<2) /* do jiffies check */ -#define XRUN_DEBUG_PERIODUPDATE (1<<3) /* full period update info */ -#define XRUN_DEBUG_HWPTRUPDATE (1<<4) /* full hwptr update info */ -#define XRUN_DEBUG_LOG (1<<5) /* show last 10 positions on err */ -#define XRUN_DEBUG_LOGONCE (1<<6) /* do above only once */ - -#ifdef CONFIG_SND_PCM_XRUN_DEBUG - -#define xrun_debug(substream, mask) \ - ((substream)->pstr->xrun_debug & (mask)) -#else -#define xrun_debug(substream, mask) 0 -#endif - -#define dump_stack_on_xrun(substream) do { \ - if (xrun_debug(substream, XRUN_DEBUG_STACK)) \ - dump_stack(); \ - } while (0) - -static void xrun(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) - snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { - char name[16]; - snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printd(KERN_DEBUG "XRUN: %s\n", name); - dump_stack_on_xrun(substream); - } -} - -#ifdef CONFIG_SND_PCM_XRUN_DEBUG -#define hw_ptr_error(substream, fmt, args...) \ - do { \ - if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \ - xrun_log_show(substream); \ - if (printk_ratelimit()) { \ - snd_printd("PCM: " fmt, ##args); \ - } \ - dump_stack_on_xrun(substream); \ - } \ - } while (0) - -#define XRUN_LOG_CNT 10 - -struct hwptr_log_entry { - unsigned int in_interrupt; - unsigned long jiffies; - snd_pcm_uframes_t pos; - snd_pcm_uframes_t period_size; - snd_pcm_uframes_t buffer_size; - snd_pcm_uframes_t old_hw_ptr; - snd_pcm_uframes_t hw_ptr_base; -}; - -struct snd_pcm_hwptr_log { - unsigned int idx; - unsigned int hit: 1; - struct hwptr_log_entry entries[XRUN_LOG_CNT]; -}; - -static void xrun_log(struct snd_pcm_substream *substream, - snd_pcm_uframes_t pos, int in_interrupt) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_hwptr_log *log = runtime->hwptr_log; - struct hwptr_log_entry *entry; - - if (log == NULL) { - log = kzalloc(sizeof(*log), GFP_ATOMIC); - if (log == NULL) - return; - runtime->hwptr_log = log; - } else { - if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit) - return; - } - entry = &log->entries[log->idx]; - entry->in_interrupt = in_interrupt; - entry->jiffies = jiffies; - entry->pos = pos; - entry->period_size = runtime->period_size; - entry->buffer_size = runtime->buffer_size; - entry->old_hw_ptr = runtime->status->hw_ptr; - entry->hw_ptr_base = runtime->hw_ptr_base; - log->idx = (log->idx + 1) % XRUN_LOG_CNT; -} - -static void xrun_log_show(struct snd_pcm_substream *substream) -{ - struct snd_pcm_hwptr_log *log = substream->runtime->hwptr_log; - struct hwptr_log_entry *entry; - char name[16]; - unsigned int idx; - int cnt; - - if (log == NULL) - return; - if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit) - return; - snd_pcm_debug_name(substream, name, sizeof(name)); - for (cnt = 0, idx = log->idx; cnt < XRUN_LOG_CNT; cnt++) { - entry = &log->entries[idx]; - if (entry->period_size == 0) - break; - snd_printd("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, " - "hwptr=%ld/%ld\n", - name, entry->in_interrupt ? "[Q] " : "", - entry->jiffies, - (unsigned long)entry->pos, - (unsigned long)entry->period_size, - (unsigned long)entry->buffer_size, - (unsigned long)entry->old_hw_ptr, - (unsigned long)entry->hw_ptr_base); - idx++; - idx %= XRUN_LOG_CNT; - } - log->hit = 1; -} - -#else /* ! CONFIG_SND_PCM_XRUN_DEBUG */ - -#define hw_ptr_error(substream, fmt, args...) do { } while (0) -#define xrun_log(substream, pos, in_interrupt) do { } while (0) -#define xrun_log_show(substream) do { } while (0) - -#endif - -int snd_pcm_update_state(struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) -{ - snd_pcm_uframes_t avail; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - avail = snd_pcm_playback_avail(runtime); - else - avail = snd_pcm_capture_avail(runtime); - if (avail > runtime->avail_max) - runtime->avail_max = avail; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { - if (avail >= runtime->buffer_size) { - snd_pcm_drain_done(substream); - return -EPIPE; - } - } else { - if (avail >= runtime->stop_threshold) { - xrun(substream); - return -EPIPE; - } - } - if (runtime->twake) { - if (avail >= runtime->twake) - wake_up(&runtime->tsleep); - } else if (avail >= runtime->control->avail_min) - wake_up(&runtime->sleep); - return 0; -} - -static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, - unsigned int in_interrupt) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t pos; - snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; - snd_pcm_sframes_t hdelta, delta; - unsigned long jdelta; - - old_hw_ptr = runtime->status->hw_ptr; - pos = substream->ops->pointer(substream); - if (pos == SNDRV_PCM_POS_XRUN) { - xrun(substream); - return -EPIPE; - } - if (pos >= runtime->buffer_size) { - if (printk_ratelimit()) { - char name[16]; - snd_pcm_debug_name(substream, name, sizeof(name)); - xrun_log_show(substream); - snd_printd(KERN_ERR "BUG: %s, pos = %ld, " - "buffer size = %ld, period size = %ld\n", - name, pos, runtime->buffer_size, - runtime->period_size); - } - pos = 0; - } - pos -= pos % runtime->min_align; - if (xrun_debug(substream, XRUN_DEBUG_LOG)) - xrun_log(substream, pos, in_interrupt); - hw_base = runtime->hw_ptr_base; - new_hw_ptr = hw_base + pos; - if (in_interrupt) { - /* we know that one period was processed */ - /* delta = "expected next hw_ptr" for in_interrupt != 0 */ - delta = runtime->hw_ptr_interrupt + runtime->period_size; - if (delta > new_hw_ptr) { - /* check for double acknowledged interrupts */ - hdelta = jiffies - runtime->hw_ptr_jiffies; - if (hdelta > runtime->hw_ptr_buffer_jiffies/2) { - hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) - hw_base = 0; - new_hw_ptr = hw_base + pos; - goto __delta; - } - } - } - /* new_hw_ptr might be lower than old_hw_ptr in case when */ - /* pointer crosses the end of the ring buffer */ - if (new_hw_ptr < old_hw_ptr) { - hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) - hw_base = 0; - new_hw_ptr = hw_base + pos; - } - __delta: - delta = new_hw_ptr - old_hw_ptr; - if (delta < 0) - delta += runtime->boundary; - if (xrun_debug(substream, in_interrupt ? - XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) { - char name[16]; - snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printd("%s_update: %s: pos=%u/%u/%u, " - "hwptr=%ld/%ld/%ld/%ld\n", - in_interrupt ? "period" : "hwptr", - name, - (unsigned int)pos, - (unsigned int)runtime->period_size, - (unsigned int)runtime->buffer_size, - (unsigned long)delta, - (unsigned long)old_hw_ptr, - (unsigned long)new_hw_ptr, - (unsigned long)runtime->hw_ptr_base); - } - - if (runtime->no_period_wakeup) { - snd_pcm_sframes_t xrun_threshold; - /* - * Without regular period interrupts, we have to check - * the elapsed time to detect xruns. - */ - jdelta = jiffies - runtime->hw_ptr_jiffies; - if (jdelta < runtime->hw_ptr_buffer_jiffies / 2) - goto no_delta_check; - hdelta = jdelta - delta * HZ / runtime->rate; - xrun_threshold = runtime->hw_ptr_buffer_jiffies / 2 + 1; - while (hdelta > xrun_threshold) { - delta += runtime->buffer_size; - hw_base += runtime->buffer_size; - if (hw_base >= runtime->boundary) - hw_base = 0; - new_hw_ptr = hw_base + pos; - hdelta -= runtime->hw_ptr_buffer_jiffies; - } - goto no_delta_check; - } - - /* something must be really wrong */ - if (delta >= runtime->buffer_size + runtime->period_size) { - hw_ptr_error(substream, - "Unexpected hw_pointer value %s" - "(stream=%i, pos=%ld, new_hw_ptr=%ld, " - "old_hw_ptr=%ld)\n", - in_interrupt ? "[Q] " : "[P]", - substream->stream, (long)pos, - (long)new_hw_ptr, (long)old_hw_ptr); - return 0; - } - - /* Do jiffies check only in xrun_debug mode */ - if (!xrun_debug(substream, XRUN_DEBUG_JIFFIESCHECK)) - goto no_jiffies_check; - - /* 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 = delta; - if (hdelta < runtime->delay) - goto no_jiffies_check; - hdelta -= runtime->delay; - jdelta = jiffies - runtime->hw_ptr_jiffies; - if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { - delta = jdelta / - (((runtime->period_size * HZ) / runtime->rate) - + HZ/100); - /* move new_hw_ptr according jiffies not pos variable */ - new_hw_ptr = old_hw_ptr; - hw_base = delta; - /* use loop to avoid checks for delta overflows */ - /* the delta value is small or zero in most cases */ - while (delta > 0) { - new_hw_ptr += runtime->period_size; - if (new_hw_ptr >= runtime->boundary) - new_hw_ptr -= runtime->boundary; - delta--; - } - /* align hw_base to buffer_size */ - hw_ptr_error(substream, - "hw_ptr skipping! %s" - "(pos=%ld, delta=%ld, period=%ld, " - "jdelta=%lu/%lu/%lu, hw_ptr=%ld/%ld)\n", - in_interrupt ? "[Q] " : "", - (long)pos, (long)hdelta, - (long)runtime->period_size, jdelta, - ((hdelta * HZ) / runtime->rate), hw_base, - (unsigned long)old_hw_ptr, - (unsigned long)new_hw_ptr); - /* reset values to proper state */ - delta = 0; - hw_base = new_hw_ptr - (new_hw_ptr % runtime->buffer_size); - } - no_jiffies_check: - if (delta > runtime->period_size + runtime->period_size / 2) { - hw_ptr_error(substream, - "Lost interrupts? %s" - "(stream=%i, delta=%ld, new_hw_ptr=%ld, " - "old_hw_ptr=%ld)\n", - in_interrupt ? "[Q] " : "", - substream->stream, (long)delta, - (long)new_hw_ptr, - (long)old_hw_ptr); - } - - no_delta_check: - if (runtime->status->hw_ptr == new_hw_ptr) - return 0; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) - snd_pcm_playback_silence(substream, new_hw_ptr); - - if (in_interrupt) { - delta = new_hw_ptr - runtime->hw_ptr_interrupt; - if (delta < 0) - delta += runtime->boundary; - delta -= (snd_pcm_uframes_t)delta % runtime->period_size; - runtime->hw_ptr_interrupt += delta; - if (runtime->hw_ptr_interrupt >= runtime->boundary) - runtime->hw_ptr_interrupt -= runtime->boundary; - } - runtime->hw_ptr_base = hw_base; - runtime->status->hw_ptr = new_hw_ptr; - runtime->hw_ptr_jiffies = jiffies; - if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) - snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); - - return snd_pcm_update_state(substream, runtime); -} - -/* CAUTION: call it with irq disabled */ -int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) -{ - return snd_pcm_update_hw_ptr0(substream, 0); -} - -/** - * snd_pcm_set_ops - set the PCM operators - * @pcm: the pcm instance - * @direction: stream direction, SNDRV_PCM_STREAM_XXX - * @ops: the operator table - * - * Sets the given PCM operators to the pcm instance. - */ -void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, struct snd_pcm_ops *ops) -{ - struct snd_pcm_str *stream = &pcm->streams[direction]; - struct snd_pcm_substream *substream; - - for (substream = stream->substream; substream != NULL; substream = substream->next) - substream->ops = ops; -} - -EXPORT_SYMBOL(snd_pcm_set_ops); - -/** - * snd_pcm_sync - set the PCM sync id - * @substream: the pcm substream - * - * Sets the PCM sync identifier for the card. - */ -void snd_pcm_set_sync(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->sync.id32[0] = substream->pcm->card->number; - runtime->sync.id32[1] = -1; - runtime->sync.id32[2] = -1; - runtime->sync.id32[3] = -1; -} - -EXPORT_SYMBOL(snd_pcm_set_sync); - -/* - * Standard ioctl routine - */ - -static inline unsigned int div32(unsigned int a, unsigned int b, - unsigned int *r) -{ - if (b == 0) { - *r = 0; - return UINT_MAX; - } - *r = a % b; - return a / b; -} - -static inline unsigned int div_down(unsigned int a, unsigned int b) -{ - if (b == 0) - return UINT_MAX; - return a / b; -} - -static inline unsigned int div_up(unsigned int a, unsigned int b) -{ - unsigned int r; - unsigned int q; - if (b == 0) - return UINT_MAX; - q = div32(a, b, &r); - if (r) - ++q; - return q; -} - -static inline unsigned int mul(unsigned int a, unsigned int b) -{ - if (a == 0) - return 0; - if (div_down(UINT_MAX, a) < b) - return UINT_MAX; - return a * b; -} - -static inline unsigned int muldiv32(unsigned int a, unsigned int b, - unsigned int c, unsigned int *r) -{ - u_int64_t n = (u_int64_t) a * b; - if (c == 0) { - snd_BUG_ON(!n); - *r = 0; - return UINT_MAX; - } - n = div_u64_rem(n, c, r); - if (n >= UINT_MAX) { - *r = 0; - return UINT_MAX; - } - return n; -} - -/** - * snd_interval_refine - refine the interval value of configurator - * @i: the interval value to refine - * @v: the interval value to refer to - * - * Refines the interval value with the reference value. - * The interval is changed to the range satisfying both intervals. - * The interval status (min, max, integer, etc.) are evaluated. - * - * Returns non-zero if the value is changed, zero if not changed. - */ -int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) -{ - int changed = 0; - if (snd_BUG_ON(snd_interval_empty(i))) - return -EINVAL; - if (i->min < v->min) { - i->min = v->min; - i->openmin = v->openmin; - changed = 1; - } else if (i->min == v->min && !i->openmin && v->openmin) { - i->openmin = 1; - changed = 1; - } - if (i->max > v->max) { - i->max = v->max; - i->openmax = v->openmax; - changed = 1; - } else if (i->max == v->max && !i->openmax && v->openmax) { - i->openmax = 1; - changed = 1; - } - if (!i->integer && v->integer) { - i->integer = 1; - changed = 1; - } - if (i->integer) { - if (i->openmin) { - i->min++; - i->openmin = 0; - } - if (i->openmax) { - i->max--; - i->openmax = 0; - } - } else if (!i->openmin && !i->openmax && i->min == i->max) - i->integer = 1; - if (snd_interval_checkempty(i)) { - snd_interval_none(i); - return -EINVAL; - } - return changed; -} - -EXPORT_SYMBOL(snd_interval_refine); - -static int snd_interval_refine_first(struct snd_interval *i) -{ - if (snd_BUG_ON(snd_interval_empty(i))) - return -EINVAL; - if (snd_interval_single(i)) - return 0; - i->max = i->min; - i->openmax = i->openmin; - if (i->openmax) - i->max++; - return 1; -} - -static int snd_interval_refine_last(struct snd_interval *i) -{ - if (snd_BUG_ON(snd_interval_empty(i))) - return -EINVAL; - if (snd_interval_single(i)) - return 0; - i->min = i->max; - i->openmin = i->openmax; - if (i->openmin) - i->min--; - return 1; -} - -void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c) -{ - if (a->empty || b->empty) { - snd_interval_none(c); - return; - } - c->empty = 0; - c->min = mul(a->min, b->min); - c->openmin = (a->openmin || b->openmin); - c->max = mul(a->max, b->max); - c->openmax = (a->openmax || b->openmax); - c->integer = (a->integer && b->integer); -} - -/** - * snd_interval_div - refine the interval value with division - * @a: dividend - * @b: divisor - * @c: quotient - * - * c = a / b - * - * Returns non-zero if the value is changed, zero if not changed. - */ -void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c) -{ - unsigned int r; - if (a->empty || b->empty) { - snd_interval_none(c); - return; - } - c->empty = 0; - c->min = div32(a->min, b->max, &r); - c->openmin = (r || a->openmin || b->openmax); - if (b->min > 0) { - c->max = div32(a->max, b->min, &r); - if (r) { - c->max++; - c->openmax = 1; - } else - c->openmax = (a->openmax || b->openmin); - } else { - c->max = UINT_MAX; - c->openmax = 0; - } - c->integer = 0; -} - -/** - * snd_interval_muldivk - refine the interval value - * @a: dividend 1 - * @b: dividend 2 - * @k: divisor (as integer) - * @c: result - * - * c = a * b / k - * - * Returns non-zero if the value is changed, zero if not changed. - */ -void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b, - unsigned int k, struct snd_interval *c) -{ - unsigned int r; - if (a->empty || b->empty) { - snd_interval_none(c); - return; - } - c->empty = 0; - c->min = muldiv32(a->min, b->min, k, &r); - c->openmin = (r || a->openmin || b->openmin); - c->max = muldiv32(a->max, b->max, k, &r); - if (r) { - c->max++; - c->openmax = 1; - } else - c->openmax = (a->openmax || b->openmax); - c->integer = 0; -} - -/** - * snd_interval_mulkdiv - refine the interval value - * @a: dividend 1 - * @k: dividend 2 (as integer) - * @b: divisor - * @c: result - * - * c = a * k / b - * - * Returns non-zero if the value is changed, zero if not changed. - */ -void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, - const struct snd_interval *b, struct snd_interval *c) -{ - unsigned int r; - if (a->empty || b->empty) { - snd_interval_none(c); - return; - } - c->empty = 0; - c->min = muldiv32(a->min, k, b->max, &r); - c->openmin = (r || a->openmin || b->openmax); - if (b->min > 0) { - c->max = muldiv32(a->max, k, b->min, &r); - if (r) { - c->max++; - c->openmax = 1; - } else - c->openmax = (a->openmax || b->openmin); - } else { - c->max = UINT_MAX; - c->openmax = 0; - } - c->integer = 0; -} - -/* ---- */ - - -/** - * snd_interval_ratnum - refine the interval value - * @i: interval to refine - * @rats_count: number of ratnum_t - * @rats: ratnum_t array - * @nump: pointer to store the resultant numerator - * @denp: pointer to store the resultant denominator - * - * Returns non-zero if the value is changed, zero if not changed. - */ -int snd_interval_ratnum(struct snd_interval *i, - unsigned int rats_count, struct snd_ratnum *rats, - unsigned int *nump, unsigned int *denp) -{ - unsigned int best_num, best_den; - int best_diff; - unsigned int k; - struct snd_interval t; - int err; - unsigned int result_num, result_den; - int result_diff; - - best_num = best_den = best_diff = 0; - for (k = 0; k < rats_count; ++k) { - unsigned int num = rats[k].num; - unsigned int den; - unsigned int q = i->min; - int diff; - if (q == 0) - q = 1; - den = div_up(num, q); - if (den < rats[k].den_min) - continue; - if (den > rats[k].den_max) - den = rats[k].den_max; - else { - unsigned int r; - r = (den - rats[k].den_min) % rats[k].den_step; - if (r != 0) - den -= r; - } - diff = num - q * den; - if (diff < 0) - diff = -diff; - if (best_num == 0 || - diff * best_den < best_diff * den) { - best_diff = diff; - best_den = den; - best_num = num; - } - } - if (best_den == 0) { - i->empty = 1; - return -EINVAL; - } - t.min = div_down(best_num, best_den); - t.openmin = !!(best_num % best_den); - - result_num = best_num; - result_diff = best_diff; - result_den = best_den; - best_num = best_den = best_diff = 0; - for (k = 0; k < rats_count; ++k) { - unsigned int num = rats[k].num; - unsigned int den; - unsigned int q = i->max; - int diff; - if (q == 0) { - i->empty = 1; - return -EINVAL; - } - den = div_down(num, q); - if (den > rats[k].den_max) - continue; - if (den < rats[k].den_min) - den = rats[k].den_min; - else { - unsigned int r; - r = (den - rats[k].den_min) % rats[k].den_step; - if (r != 0) - den += rats[k].den_step - r; - } - diff = q * den - num; - if (diff < 0) - diff = -diff; - if (best_num == 0 || - diff * best_den < best_diff * den) { - best_diff = diff; - best_den = den; - best_num = num; - } - } - if (best_den == 0) { - i->empty = 1; - return -EINVAL; - } - t.max = div_up(best_num, best_den); - t.openmax = !!(best_num % best_den); - t.integer = 0; - err = snd_interval_refine(i, &t); - if (err < 0) - return err; - - if (snd_interval_single(i)) { - if (best_diff * result_den < result_diff * best_den) { - result_num = best_num; - result_den = best_den; - } - if (nump) - *nump = result_num; - if (denp) - *denp = result_den; - } - return err; -} - -EXPORT_SYMBOL(snd_interval_ratnum); - -/** - * snd_interval_ratden - refine the interval value - * @i: interval to refine - * @rats_count: number of struct ratden - * @rats: struct ratden array - * @nump: pointer to store the resultant numerator - * @denp: pointer to store the resultant denominator - * - * Returns non-zero if the value is changed, zero if not changed. - */ -static int snd_interval_ratden(struct snd_interval *i, - unsigned int rats_count, struct snd_ratden *rats, - unsigned int *nump, unsigned int *denp) -{ - unsigned int best_num, best_diff, best_den; - unsigned int k; - struct snd_interval t; - int err; - - best_num = best_den = best_diff = 0; - for (k = 0; k < rats_count; ++k) { - unsigned int num; - unsigned int den = rats[k].den; - unsigned int q = i->min; - int diff; - num = mul(q, den); - if (num > rats[k].num_max) - continue; - if (num < rats[k].num_min) - num = rats[k].num_max; - else { - unsigned int r; - r = (num - rats[k].num_min) % rats[k].num_step; - if (r != 0) - num += rats[k].num_step - r; - } - diff = num - q * den; - if (best_num == 0 || - diff * best_den < best_diff * den) { - best_diff = diff; - best_den = den; - best_num = num; - } - } - if (best_den == 0) { - i->empty = 1; - return -EINVAL; - } - t.min = div_down(best_num, best_den); - t.openmin = !!(best_num % best_den); - - best_num = best_den = best_diff = 0; - for (k = 0; k < rats_count; ++k) { - unsigned int num; - unsigned int den = rats[k].den; - unsigned int q = i->max; - int diff; - num = mul(q, den); - if (num < rats[k].num_min) - continue; - if (num > rats[k].num_max) - num = rats[k].num_max; - else { - unsigned int r; - r = (num - rats[k].num_min) % rats[k].num_step; - if (r != 0) - num -= r; - } - diff = q * den - num; - if (best_num == 0 || - diff * best_den < best_diff * den) { - best_diff = diff; - best_den = den; - best_num = num; - } - } - if (best_den == 0) { - i->empty = 1; - return -EINVAL; - } - t.max = div_up(best_num, best_den); - t.openmax = !!(best_num % best_den); - t.integer = 0; - err = snd_interval_refine(i, &t); - if (err < 0) - return err; - - if (snd_interval_single(i)) { - if (nump) - *nump = best_num; - if (denp) - *denp = best_den; - } - return err; -} - -/** - * snd_interval_list - refine the interval value from the list - * @i: the interval value to refine - * @count: the number of elements in the list - * @list: the value list - * @mask: the bit-mask to evaluate - * - * Refines the interval value from the list. - * When mask is non-zero, only the elements corresponding to bit 1 are - * evaluated. - * - * Returns non-zero if the value is changed, zero if not changed. - */ -int snd_interval_list(struct snd_interval *i, unsigned int count, - const unsigned int *list, unsigned int mask) -{ - unsigned int k; - struct snd_interval list_range; - - if (!count) { - i->empty = 1; - return -EINVAL; - } - snd_interval_any(&list_range); - list_range.min = UINT_MAX; - list_range.max = 0; - for (k = 0; k < count; k++) { - if (mask && !(mask & (1 << k))) - continue; - if (!snd_interval_test(i, list[k])) - continue; - list_range.min = min(list_range.min, list[k]); - list_range.max = max(list_range.max, list[k]); - } - return snd_interval_refine(i, &list_range); -} - -EXPORT_SYMBOL(snd_interval_list); - -static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step) -{ - unsigned int n; - int changed = 0; - n = (i->min - min) % step; - if (n != 0 || i->openmin) { - i->min += step - n; - changed = 1; - } - n = (i->max - min) % step; - if (n != 0 || i->openmax) { - i->max -= n; - changed = 1; - } - if (snd_interval_checkempty(i)) { - i->empty = 1; - return -EINVAL; - } - return changed; -} - -/* Info constraints helpers */ - -/** - * snd_pcm_hw_rule_add - add the hw-constraint rule - * @runtime: the pcm runtime instance - * @cond: condition bits - * @var: the variable to evaluate - * @func: the evaluation function - * @private: the private data pointer passed to function - * @dep: the dependent variables - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, - int var, - snd_pcm_hw_rule_func_t func, void *private, - int dep, ...) -{ - struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; - struct snd_pcm_hw_rule *c; - unsigned int k; - va_list args; - va_start(args, dep); - if (constrs->rules_num >= constrs->rules_all) { - struct snd_pcm_hw_rule *new; - unsigned int new_rules = constrs->rules_all + 16; - new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL); - if (!new) { - va_end(args); - return -ENOMEM; - } - if (constrs->rules) { - memcpy(new, constrs->rules, - constrs->rules_num * sizeof(*c)); - kfree(constrs->rules); - } - constrs->rules = new; - constrs->rules_all = new_rules; - } - c = &constrs->rules[constrs->rules_num]; - c->cond = cond; - c->func = func; - c->var = var; - c->private = private; - k = 0; - while (1) { - if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps))) { - va_end(args); - return -EINVAL; - } - c->deps[k++] = dep; - if (dep < 0) - break; - dep = va_arg(args, int); - } - constrs->rules_num++; - va_end(args); - return 0; -} - -EXPORT_SYMBOL(snd_pcm_hw_rule_add); - -/** - * snd_pcm_hw_constraint_mask - apply the given bitmap mask constraint - * @runtime: PCM runtime instance - * @var: hw_params variable to apply the mask - * @mask: the bitmap mask - * - * Apply the constraint of the given bitmap mask to a 32-bit mask parameter. - */ -int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, - u_int32_t mask) -{ - struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; - struct snd_mask *maskp = constrs_mask(constrs, var); - *maskp->bits &= mask; - memset(maskp->bits + 1, 0, (SNDRV_MASK_MAX-32) / 8); /* clear rest */ - if (*maskp->bits == 0) - return -EINVAL; - return 0; -} - -/** - * snd_pcm_hw_constraint_mask64 - apply the given bitmap mask constraint - * @runtime: PCM runtime instance - * @var: hw_params variable to apply the mask - * @mask: the 64bit bitmap mask - * - * Apply the constraint of the given bitmap mask to a 64-bit mask parameter. - */ -int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, - u_int64_t mask) -{ - struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; - struct snd_mask *maskp = constrs_mask(constrs, var); - maskp->bits[0] &= (u_int32_t)mask; - maskp->bits[1] &= (u_int32_t)(mask >> 32); - memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */ - if (! maskp->bits[0] && ! maskp->bits[1]) - return -EINVAL; - return 0; -} - -/** - * snd_pcm_hw_constraint_integer - apply an integer constraint to an interval - * @runtime: PCM runtime instance - * @var: hw_params variable to apply the integer constraint - * - * Apply the constraint of integer to an interval parameter. - */ -int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var) -{ - struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; - return snd_interval_setinteger(constrs_interval(constrs, var)); -} - -EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); - -/** - * snd_pcm_hw_constraint_minmax - apply a min/max range constraint to an interval - * @runtime: PCM runtime instance - * @var: hw_params variable to apply the range - * @min: the minimal value - * @max: the maximal value - * - * Apply the min/max range constraint to an interval parameter. - */ -int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var, - unsigned int min, unsigned int max) -{ - struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; - struct snd_interval t; - t.min = min; - t.max = max; - t.openmin = t.openmax = 0; - t.integer = 0; - return snd_interval_refine(constrs_interval(constrs, var), &t); -} - -EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); - -static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pcm_hw_constraint_list *list = rule->private; - return snd_interval_list(hw_param_interval(params, rule->var), list->count, list->list, list->mask); -} - - -/** - * snd_pcm_hw_constraint_list - apply a list of constraints to a parameter - * @runtime: PCM runtime instance - * @cond: condition bits - * @var: hw_params variable to apply the list constraint - * @l: list - * - * Apply the list of constraints to an interval parameter. - */ -int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, - unsigned int cond, - snd_pcm_hw_param_t var, - struct snd_pcm_hw_constraint_list *l) -{ - return snd_pcm_hw_rule_add(runtime, cond, var, - snd_pcm_hw_rule_list, l, - var, -1); -} - -EXPORT_SYMBOL(snd_pcm_hw_constraint_list); - -static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pcm_hw_constraint_ratnums *r = rule->private; - unsigned int num = 0, den = 0; - int err; - err = snd_interval_ratnum(hw_param_interval(params, rule->var), - r->nrats, r->rats, &num, &den); - if (err >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) { - params->rate_num = num; - params->rate_den = den; - } - return err; -} - -/** - * snd_pcm_hw_constraint_ratnums - apply ratnums constraint to a parameter - * @runtime: PCM runtime instance - * @cond: condition bits - * @var: hw_params variable to apply the ratnums constraint - * @r: struct snd_ratnums constriants - */ -int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, - unsigned int cond, - snd_pcm_hw_param_t var, - struct snd_pcm_hw_constraint_ratnums *r) -{ - return snd_pcm_hw_rule_add(runtime, cond, var, - snd_pcm_hw_rule_ratnums, r, - var, -1); -} - -EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); - -static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pcm_hw_constraint_ratdens *r = rule->private; - unsigned int num = 0, den = 0; - int err = snd_interval_ratden(hw_param_interval(params, rule->var), - r->nrats, r->rats, &num, &den); - if (err >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) { - params->rate_num = num; - params->rate_den = den; - } - return err; -} - -/** - * snd_pcm_hw_constraint_ratdens - apply ratdens constraint to a parameter - * @runtime: PCM runtime instance - * @cond: condition bits - * @var: hw_params variable to apply the ratdens constraint - * @r: struct snd_ratdens constriants - */ -int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, - unsigned int cond, - snd_pcm_hw_param_t var, - struct snd_pcm_hw_constraint_ratdens *r) -{ - return snd_pcm_hw_rule_add(runtime, cond, var, - snd_pcm_hw_rule_ratdens, r, - var, -1); -} - -EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); - -static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - unsigned int l = (unsigned long) rule->private; - int width = l & 0xffff; - unsigned int msbits = l >> 16; - struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); - if (snd_interval_single(i) && snd_interval_value(i) == width) - params->msbits = msbits; - return 0; -} - -/** - * snd_pcm_hw_constraint_msbits - add a hw constraint msbits rule - * @runtime: PCM runtime instance - * @cond: condition bits - * @width: sample bits width - * @msbits: msbits width - */ -int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, - unsigned int cond, - unsigned int width, - unsigned int msbits) -{ - unsigned long l = (msbits << 16) | width; - return snd_pcm_hw_rule_add(runtime, cond, -1, - snd_pcm_hw_rule_msbits, - (void*) l, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); -} - -EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); - -static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - unsigned long step = (unsigned long) rule->private; - return snd_interval_step(hw_param_interval(params, rule->var), 0, step); -} - -/** - * snd_pcm_hw_constraint_step - add a hw constraint step rule - * @runtime: PCM runtime instance - * @cond: condition bits - * @var: hw_params variable to apply the step constraint - * @step: step size - */ -int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, - unsigned int cond, - snd_pcm_hw_param_t var, - unsigned long step) -{ - return snd_pcm_hw_rule_add(runtime, cond, var, - snd_pcm_hw_rule_step, (void *) step, - var, -1); -} - -EXPORT_SYMBOL(snd_pcm_hw_constraint_step); - -static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) -{ - static unsigned int pow2_sizes[] = { - 1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7, - 1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, - 1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23, - 1<<24, 1<<25, 1<<26, 1<<27, 1<<28, 1<<29, 1<<30 - }; - return snd_interval_list(hw_param_interval(params, rule->var), - ARRAY_SIZE(pow2_sizes), pow2_sizes, 0); -} - -/** - * snd_pcm_hw_constraint_pow2 - add a hw constraint power-of-2 rule - * @runtime: PCM runtime instance - * @cond: condition bits - * @var: hw_params variable to apply the power-of-2 constraint - */ -int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, - unsigned int cond, - snd_pcm_hw_param_t var) -{ - return snd_pcm_hw_rule_add(runtime, cond, var, - snd_pcm_hw_rule_pow2, NULL, - var, -1); -} - -EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); - -static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - unsigned int base_rate = (unsigned int)(uintptr_t)rule->private; - struct snd_interval *rate; - - rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - return snd_interval_list(rate, 1, &base_rate, 0); -} - -/** - * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling - * @runtime: PCM runtime instance - * @base_rate: the rate at which the hardware does not resample - */ -int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime, - unsigned int base_rate) -{ - return snd_pcm_hw_rule_add(runtime, SNDRV_PCM_HW_PARAMS_NORESAMPLE, - SNDRV_PCM_HW_PARAM_RATE, - snd_pcm_hw_rule_noresample_func, - (void *)(uintptr_t)base_rate, - SNDRV_PCM_HW_PARAM_RATE, -1); -} -EXPORT_SYMBOL(snd_pcm_hw_rule_noresample); - -static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var) -{ - if (hw_is_mask(var)) { - snd_mask_any(hw_param_mask(params, var)); - params->cmask |= 1 << var; - params->rmask |= 1 << var; - return; - } - if (hw_is_interval(var)) { - snd_interval_any(hw_param_interval(params, var)); - params->cmask |= 1 << var; - params->rmask |= 1 << var; - return; - } - snd_BUG(); -} - -void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) -{ - unsigned int k; - memset(params, 0, sizeof(*params)); - for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) - _snd_pcm_hw_param_any(params, k); - for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) - _snd_pcm_hw_param_any(params, k); - params->info = ~0U; -} - -EXPORT_SYMBOL(_snd_pcm_hw_params_any); - -/** - * snd_pcm_hw_param_value - return @params field @var value - * @params: the hw_params instance - * @var: parameter to retrieve - * @dir: pointer to the direction (-1,0,1) or %NULL - * - * Return the value for field @var if it's fixed in configuration space - * defined by @params. Return -%EINVAL otherwise. - */ -int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) -{ - if (hw_is_mask(var)) { - const struct snd_mask *mask = hw_param_mask_c(params, var); - if (!snd_mask_single(mask)) - return -EINVAL; - if (dir) - *dir = 0; - return snd_mask_value(mask); - } - if (hw_is_interval(var)) { - const struct snd_interval *i = hw_param_interval_c(params, var); - if (!snd_interval_single(i)) - return -EINVAL; - if (dir) - *dir = i->openmin; - return snd_interval_value(i); - } - return -EINVAL; -} - -EXPORT_SYMBOL(snd_pcm_hw_param_value); - -void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var) -{ - if (hw_is_mask(var)) { - snd_mask_none(hw_param_mask(params, var)); - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } else if (hw_is_interval(var)) { - snd_interval_none(hw_param_interval(params, var)); - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } else { - snd_BUG(); - } -} - -EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); - -static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var) -{ - int changed; - if (hw_is_mask(var)) - changed = snd_mask_refine_first(hw_param_mask(params, var)); - else if (hw_is_interval(var)) - changed = snd_interval_refine_first(hw_param_interval(params, var)); - else - return -EINVAL; - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - - -/** - * snd_pcm_hw_param_first - refine config space and return minimum value - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @dir: pointer to the direction (-1,0,1) or %NULL - * - * Inside configuration space defined by @params remove from @var all - * values > minimum. Reduce configuration space accordingly. - * Return the minimum. - */ -int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) -{ - int changed = _snd_pcm_hw_param_first(params, var); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (snd_BUG_ON(err < 0)) - return err; - } - return snd_pcm_hw_param_value(params, var, dir); -} - -EXPORT_SYMBOL(snd_pcm_hw_param_first); - -static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var) -{ - int changed; - if (hw_is_mask(var)) - changed = snd_mask_refine_last(hw_param_mask(params, var)); - else if (hw_is_interval(var)) - changed = snd_interval_refine_last(hw_param_interval(params, var)); - else - return -EINVAL; - if (changed) { - params->cmask |= 1 << var; - params->rmask |= 1 << var; - } - return changed; -} - - -/** - * snd_pcm_hw_param_last - refine config space and return maximum value - * @pcm: PCM instance - * @params: the hw_params instance - * @var: parameter to retrieve - * @dir: pointer to the direction (-1,0,1) or %NULL - * - * Inside configuration space defined by @params remove from @var all - * values < maximum. Reduce configuration space accordingly. - * Return the maximum. - */ -int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params, - snd_pcm_hw_param_t var, int *dir) -{ - int changed = _snd_pcm_hw_param_last(params, var); - if (changed < 0) - return changed; - if (params->rmask) { - int err = snd_pcm_hw_refine(pcm, params); - if (snd_BUG_ON(err < 0)) - return err; - } - return snd_pcm_hw_param_value(params, var, dir); -} - -EXPORT_SYMBOL(snd_pcm_hw_param_last); - -/** - * snd_pcm_hw_param_choose - choose a configuration defined by @params - * @pcm: PCM instance - * @params: the hw_params instance - * - * Choose one configuration from configuration space defined by @params. - * The configuration chosen is that obtained fixing in this order: - * first access, first format, first subformat, min channels, - * min rate, min period time, max buffer size, min tick time - */ -int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params) -{ - static int vars[] = { - SNDRV_PCM_HW_PARAM_ACCESS, - SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_HW_PARAM_SUBFORMAT, - SNDRV_PCM_HW_PARAM_CHANNELS, - SNDRV_PCM_HW_PARAM_RATE, - SNDRV_PCM_HW_PARAM_PERIOD_TIME, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - SNDRV_PCM_HW_PARAM_TICK_TIME, - -1 - }; - int err, *v; - - for (v = vars; *v != -1; v++) { - if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE) - err = snd_pcm_hw_param_first(pcm, params, *v, NULL); - else - err = snd_pcm_hw_param_last(pcm, params, *v, NULL); - if (snd_BUG_ON(err < 0)) - return err; - } - return 0; -} - -static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, - void *arg) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - snd_pcm_stream_lock_irqsave(substream, flags); - if (snd_pcm_running(substream) && - snd_pcm_update_hw_ptr(substream) >= 0) - runtime->status->hw_ptr %= runtime->buffer_size; - else - runtime->status->hw_ptr = 0; - snd_pcm_stream_unlock_irqrestore(substream, flags); - return 0; -} - -static int snd_pcm_lib_ioctl_channel_info(struct snd_pcm_substream *substream, - void *arg) -{ - struct snd_pcm_channel_info *info = arg; - struct snd_pcm_runtime *runtime = substream->runtime; - int width; - if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) { - info->offset = -1; - return 0; - } - width = snd_pcm_format_physical_width(runtime->format); - if (width < 0) - return width; - info->offset = 0; - switch (runtime->access) { - case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED: - case SNDRV_PCM_ACCESS_RW_INTERLEAVED: - info->first = info->channel * width; - info->step = runtime->channels * width; - break; - case SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED: - case SNDRV_PCM_ACCESS_RW_NONINTERLEAVED: - { - size_t size = runtime->dma_bytes / runtime->channels; - info->first = info->channel * size * 8; - info->step = width; - break; - } - default: - snd_BUG(); - break; - } - return 0; -} - -static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream, - void *arg) -{ - struct snd_pcm_hw_params *params = arg; - snd_pcm_format_t format; - int channels, width; - - params->fifo_size = substream->runtime->hw.fifo_size; - if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) { - format = params_format(params); - channels = params_channels(params); - width = snd_pcm_format_physical_width(format); - params->fifo_size /= width * channels; - } - return 0; -} - -/** - * snd_pcm_lib_ioctl - a generic PCM ioctl callback - * @substream: the pcm substream instance - * @cmd: ioctl command - * @arg: ioctl argument - * - * Processes the generic ioctl commands for PCM. - * Can be passed as the ioctl callback for PCM ops. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - switch (cmd) { - case SNDRV_PCM_IOCTL1_INFO: - return 0; - case SNDRV_PCM_IOCTL1_RESET: - return snd_pcm_lib_ioctl_reset(substream, arg); - case SNDRV_PCM_IOCTL1_CHANNEL_INFO: - return snd_pcm_lib_ioctl_channel_info(substream, arg); - case SNDRV_PCM_IOCTL1_FIFO_SIZE: - return snd_pcm_lib_ioctl_fifo_size(substream, arg); - } - return -ENXIO; -} - -EXPORT_SYMBOL(snd_pcm_lib_ioctl); - -/** - * snd_pcm_period_elapsed - update the pcm status for the next period - * @substream: the pcm substream instance - * - * This function is called from the interrupt handler when the - * PCM has processed the period size. It will update the current - * pointer, wake up sleepers, etc. - * - * Even if more than one periods have elapsed since the last call, you - * have to call this only once. - */ -void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - unsigned long flags; - - if (PCM_RUNTIME_CHECK(substream)) - return; - runtime = substream->runtime; - - if (runtime->transfer_ack_begin) - runtime->transfer_ack_begin(substream); - - snd_pcm_stream_lock_irqsave(substream, flags); - if (!snd_pcm_running(substream) || - snd_pcm_update_hw_ptr0(substream, 1) < 0) - goto _end; - - if (substream->timer_running) - snd_timer_interrupt(substream->timer, 1); - _end: - snd_pcm_stream_unlock_irqrestore(substream, flags); - if (runtime->transfer_ack_end) - runtime->transfer_ack_end(substream); - kill_fasync(&runtime->fasync, SIGIO, POLL_IN); -} - -EXPORT_SYMBOL(snd_pcm_period_elapsed); - -/* - * Wait until avail_min data becomes available - * Returns a negative error code if any error occurs during operation. - * The available space is stored on availp. When err = 0 and avail = 0 - * on the capture stream, it indicates the stream is in DRAINING state. - */ -static int wait_for_avail(struct snd_pcm_substream *substream, - snd_pcm_uframes_t *availp) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - wait_queue_t wait; - int err = 0; - snd_pcm_uframes_t avail = 0; - long wait_time, tout; - - init_waitqueue_entry(&wait, current); - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&runtime->tsleep, &wait); - - if (runtime->no_period_wakeup) - wait_time = MAX_SCHEDULE_TIMEOUT; - else { - wait_time = 10; - if (runtime->rate) { - long t = runtime->period_size * 2 / runtime->rate; - wait_time = max(t, wait_time); - } - wait_time = msecs_to_jiffies(wait_time * 1000); - } - - for (;;) { - if (signal_pending(current)) { - err = -ERESTARTSYS; - break; - } - - /* - * We need to check if space became available already - * (and thus the wakeup happened already) first to close - * the race of space already having become available. - * This check must happen after been added to the waitqueue - * and having current state be INTERRUPTIBLE. - */ - if (is_playback) - avail = snd_pcm_playback_avail(runtime); - else - avail = snd_pcm_capture_avail(runtime); - if (avail >= runtime->twake) - break; - snd_pcm_stream_unlock_irq(substream); - - tout = schedule_timeout(wait_time); - - snd_pcm_stream_lock_irq(substream); - set_current_state(TASK_INTERRUPTIBLE); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - goto _endloop; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _endloop; - case SNDRV_PCM_STATE_DRAINING: - if (is_playback) - err = -EPIPE; - else - avail = 0; /* indicate draining */ - goto _endloop; - case SNDRV_PCM_STATE_OPEN: - case SNDRV_PCM_STATE_SETUP: - case SNDRV_PCM_STATE_DISCONNECTED: - err = -EBADFD; - goto _endloop; - } - if (!tout) { - snd_printd("%s write error (DMA or IRQ trouble?)\n", - is_playback ? "playback" : "capture"); - err = -EIO; - break; - } - } - _endloop: - set_current_state(TASK_RUNNING); - remove_wait_queue(&runtime->tsleep, &wait); - *availp = avail; - return err; -} - -static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, - unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); - if (substream->ops->copy) { - if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) - return err; - } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); - if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames))) - return -EFAULT; - } - return 0; -} - -typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t size); - -static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, - unsigned long data, - snd_pcm_uframes_t size, - int nonblock, - transfer_f transfer) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t xfer = 0; - snd_pcm_uframes_t offset = 0; - int err = 0; - - if (size == 0) - return 0; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_RUNNING: - case SNDRV_PCM_STATE_PAUSED: - break; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _end_unlock; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - goto _end_unlock; - default: - err = -EBADFD; - goto _end_unlock; - } - - runtime->twake = runtime->control->avail_min ? : 1; - while (size > 0) { - snd_pcm_uframes_t frames, appl_ptr, appl_ofs; - snd_pcm_uframes_t avail; - snd_pcm_uframes_t cont; - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) - snd_pcm_update_hw_ptr(substream); - avail = snd_pcm_playback_avail(runtime); - if (!avail) { - if (nonblock) { - err = -EAGAIN; - goto _end_unlock; - } - runtime->twake = min_t(snd_pcm_uframes_t, size, - runtime->control->avail_min ? : 1); - err = wait_for_avail(substream, &avail); - if (err < 0) - goto _end_unlock; - } - frames = size > avail ? avail : size; - cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; - if (frames > cont) - frames = cont; - if (snd_BUG_ON(!frames)) { - runtime->twake = 0; - snd_pcm_stream_unlock_irq(substream); - return -EINVAL; - } - appl_ptr = runtime->control->appl_ptr; - appl_ofs = appl_ptr % runtime->buffer_size; - snd_pcm_stream_unlock_irq(substream); - err = transfer(substream, appl_ofs, data, offset, frames); - snd_pcm_stream_lock_irq(substream); - if (err < 0) - goto _end_unlock; - switch (runtime->status->state) { - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _end_unlock; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - goto _end_unlock; - default: - break; - } - appl_ptr += frames; - if (appl_ptr >= runtime->boundary) - appl_ptr -= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - if (substream->ops->ack) - substream->ops->ack(substream); - - offset += frames; - size -= frames; - xfer += frames; - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED && - snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { - err = snd_pcm_start(substream); - if (err < 0) - goto _end_unlock; - } - } - _end_unlock: - runtime->twake = 0; - if (xfer > 0 && err >= 0) - snd_pcm_update_state(substream, runtime); - snd_pcm_stream_unlock_irq(substream); - return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; -} - -/* sanity-check for read/write methods */ -static int pcm_sanity_check(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area)) - return -EINVAL; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - return 0; -} - -snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size) -{ - struct snd_pcm_runtime *runtime; - int nonblock; - int err; - - err = pcm_sanity_check(substream); - if (err < 0) - return err; - runtime = substream->runtime; - nonblock = !!(substream->f_flags & O_NONBLOCK); - - if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && - runtime->channels > 1) - return -EINVAL; - return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock, - snd_pcm_lib_write_transfer); -} - -EXPORT_SYMBOL(snd_pcm_lib_write); - -static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, - unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - void __user **bufs = (void __user **)data; - int channels = runtime->channels; - int c; - if (substream->ops->copy) { - if (snd_BUG_ON(!substream->ops->silence)) - return -EINVAL; - for (c = 0; c < channels; ++c, ++bufs) { - if (*bufs == NULL) { - if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0) - return err; - } else { - char __user *buf = *bufs + samples_to_bytes(runtime, off); - if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) - return err; - } - } - } else { - /* default transfer behaviour */ - size_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c, ++bufs) { - char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff); - if (*bufs == NULL) { - snd_pcm_format_set_silence(runtime->format, hwbuf, frames); - } else { - char __user *buf = *bufs + samples_to_bytes(runtime, off); - if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames))) - return -EFAULT; - } - } - } - return 0; -} - -snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, - void __user **bufs, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime; - int nonblock; - int err; - - err = pcm_sanity_check(substream); - if (err < 0) - return err; - runtime = substream->runtime; - nonblock = !!(substream->f_flags & O_NONBLOCK); - - if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) - return -EINVAL; - return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames, - nonblock, snd_pcm_lib_writev_transfer); -} - -EXPORT_SYMBOL(snd_pcm_lib_writev); - -static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, - unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); - if (substream->ops->copy) { - if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) - return err; - } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); - if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) - return -EFAULT; - } - return 0; -} - -static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, - unsigned long data, - snd_pcm_uframes_t size, - int nonblock, - transfer_f transfer) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t xfer = 0; - snd_pcm_uframes_t offset = 0; - int err = 0; - - if (size == 0) - return 0; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - if (size >= runtime->start_threshold) { - err = snd_pcm_start(substream); - if (err < 0) - goto _end_unlock; - } - break; - case SNDRV_PCM_STATE_DRAINING: - case SNDRV_PCM_STATE_RUNNING: - case SNDRV_PCM_STATE_PAUSED: - break; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _end_unlock; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - goto _end_unlock; - default: - err = -EBADFD; - goto _end_unlock; - } - - runtime->twake = runtime->control->avail_min ? : 1; - while (size > 0) { - snd_pcm_uframes_t frames, appl_ptr, appl_ofs; - snd_pcm_uframes_t avail; - snd_pcm_uframes_t cont; - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) - snd_pcm_update_hw_ptr(substream); - avail = snd_pcm_capture_avail(runtime); - if (!avail) { - if (runtime->status->state == - SNDRV_PCM_STATE_DRAINING) { - snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); - goto _end_unlock; - } - if (nonblock) { - err = -EAGAIN; - goto _end_unlock; - } - runtime->twake = min_t(snd_pcm_uframes_t, size, - runtime->control->avail_min ? : 1); - err = wait_for_avail(substream, &avail); - if (err < 0) - goto _end_unlock; - if (!avail) - continue; /* draining */ - } - frames = size > avail ? avail : size; - cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; - if (frames > cont) - frames = cont; - if (snd_BUG_ON(!frames)) { - runtime->twake = 0; - snd_pcm_stream_unlock_irq(substream); - return -EINVAL; - } - appl_ptr = runtime->control->appl_ptr; - appl_ofs = appl_ptr % runtime->buffer_size; - snd_pcm_stream_unlock_irq(substream); - err = transfer(substream, appl_ofs, data, offset, frames); - snd_pcm_stream_lock_irq(substream); - if (err < 0) - goto _end_unlock; - switch (runtime->status->state) { - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _end_unlock; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - goto _end_unlock; - default: - break; - } - appl_ptr += frames; - if (appl_ptr >= runtime->boundary) - appl_ptr -= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - if (substream->ops->ack) - substream->ops->ack(substream); - - offset += frames; - size -= frames; - xfer += frames; - } - _end_unlock: - runtime->twake = 0; - if (xfer > 0 && err >= 0) - snd_pcm_update_state(substream, runtime); - snd_pcm_stream_unlock_irq(substream); - return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; -} - -snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size) -{ - struct snd_pcm_runtime *runtime; - int nonblock; - int err; - - err = pcm_sanity_check(substream); - if (err < 0) - return err; - runtime = substream->runtime; - nonblock = !!(substream->f_flags & O_NONBLOCK); - if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) - return -EINVAL; - return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); -} - -EXPORT_SYMBOL(snd_pcm_lib_read); - -static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, - unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - void __user **bufs = (void __user **)data; - int channels = runtime->channels; - int c; - if (substream->ops->copy) { - for (c = 0; c < channels; ++c, ++bufs) { - char __user *buf; - if (*bufs == NULL) - continue; - buf = *bufs + samples_to_bytes(runtime, off); - if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) - return err; - } - } else { - snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c, ++bufs) { - char *hwbuf; - char __user *buf; - if (*bufs == NULL) - continue; - - hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff); - buf = *bufs + samples_to_bytes(runtime, off); - if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames))) - return -EFAULT; - } - } - return 0; -} - -snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, - void __user **bufs, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime; - int nonblock; - int err; - - err = pcm_sanity_check(substream); - if (err < 0) - return err; - runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - - nonblock = !!(substream->f_flags & O_NONBLOCK); - if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) - return -EINVAL; - return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); -} - -EXPORT_SYMBOL(snd_pcm_lib_readv); diff --git a/ANDROID_3.4.5/sound/core/pcm_memory.c b/ANDROID_3.4.5/sound/core/pcm_memory.c deleted file mode 100644 index 95713136..00000000 --- a/ANDROID_3.4.5/sound/core/pcm_memory.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Digital Audio (PCM) abstract layer - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include - -static int preallocate_dma = 1; -module_param(preallocate_dma, int, 0444); -MODULE_PARM_DESC(preallocate_dma, "Preallocate DMA memory when the PCM devices are initialized."); - -static int maximum_substreams = 4; -module_param(maximum_substreams, int, 0444); -MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory."); - -static const size_t snd_minimum_buffer = 16384; - - -/* - * try to allocate as the large pages as possible. - * stores the resultant memory size in *res_size. - * - * the minimum size is snd_minimum_buffer. it should be power of 2. - */ -static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size) -{ - struct snd_dma_buffer *dmab = &substream->dma_buffer; - int err; - - /* already reserved? */ - if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) { - if (dmab->bytes >= size) - return 0; /* yes */ - /* no, free the reserved block */ - snd_dma_free_pages(dmab); - dmab->bytes = 0; - } - - do { - if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev, - size, dmab)) < 0) { - if (err != -ENOMEM) - return err; /* fatal error */ - } else - return 0; - size >>= 1; - } while (size >= snd_minimum_buffer); - dmab->bytes = 0; /* tell error */ - return 0; -} - -/* - * release the preallocated buffer if not yet done. - */ -static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream) -{ - if (substream->dma_buffer.area == NULL) - return; - if (substream->dma_buf_id) - snd_dma_reserve_buf(&substream->dma_buffer, substream->dma_buf_id); - else - snd_dma_free_pages(&substream->dma_buffer); - substream->dma_buffer.area = NULL; -} - -/** - * snd_pcm_lib_preallocate_free - release the preallocated buffer of the specified substream. - * @substream: the pcm substream instance - * - * Releases the pre-allocated buffer of the given substream. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_preallocate_dma_free(substream); -#ifdef CONFIG_SND_VERBOSE_PROCFS - snd_info_free_entry(substream->proc_prealloc_max_entry); - substream->proc_prealloc_max_entry = NULL; - snd_info_free_entry(substream->proc_prealloc_entry); - substream->proc_prealloc_entry = NULL; -#endif - return 0; -} - -/** - * snd_pcm_lib_preallocate_free_for_all - release all pre-allocated buffers on the pcm - * @pcm: the pcm instance - * - * Releases all the pre-allocated buffers on the given pcm. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - int stream; - - for (stream = 0; stream < 2; stream++) - for (substream = pcm->streams[stream].substream; substream; substream = substream->next) - snd_pcm_lib_preallocate_free(substream); - return 0; -} - -EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); - -#ifdef CONFIG_SND_VERBOSE_PROCFS -/* - * read callback for prealloc proc file - * - * prints the current allocated size in kB. - */ -static void snd_pcm_lib_preallocate_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_substream *substream = entry->private_data; - snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024); -} - -/* - * read callback for prealloc_max proc file - * - * prints the maximum allowed size in kB. - */ -static void snd_pcm_lib_preallocate_max_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_substream *substream = entry->private_data; - snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_max / 1024); -} - -/* - * write callback for prealloc proc file - * - * accepts the preallocation size in kB. - */ -static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcm_substream *substream = entry->private_data; - char line[64], str[64]; - size_t size; - struct snd_dma_buffer new_dmab; - - if (substream->runtime) { - buffer->error = -EBUSY; - return; - } - if (!snd_info_get_line(buffer, line, sizeof(line))) { - snd_info_get_str(str, line, sizeof(str)); - size = simple_strtoul(str, NULL, 10) * 1024; - if ((size != 0 && size < 8192) || size > substream->dma_max) { - buffer->error = -EINVAL; - return; - } - if (substream->dma_buffer.bytes == size) - return; - memset(&new_dmab, 0, sizeof(new_dmab)); - new_dmab.dev = substream->dma_buffer.dev; - if (size > 0) { - if (snd_dma_alloc_pages(substream->dma_buffer.dev.type, - substream->dma_buffer.dev.dev, - size, &new_dmab) < 0) { - buffer->error = -ENOMEM; - return; - } - substream->buffer_bytes_max = size; - } else { - substream->buffer_bytes_max = UINT_MAX; - } - if (substream->dma_buffer.area) - snd_dma_free_pages(&substream->dma_buffer); - substream->dma_buffer = new_dmab; - } else { - buffer->error = -EINVAL; - } -} - -static inline void preallocate_info_init(struct snd_pcm_substream *substream) -{ - struct snd_info_entry *entry; - - if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) { - entry->c.text.read = snd_pcm_lib_preallocate_proc_read; - entry->c.text.write = snd_pcm_lib_preallocate_proc_write; - entry->mode |= S_IWUSR; - entry->private_data = substream; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - substream->proc_prealloc_entry = entry; - if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max", substream->proc_root)) != NULL) { - entry->c.text.read = snd_pcm_lib_preallocate_max_proc_read; - entry->private_data = substream; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - substream->proc_prealloc_max_entry = entry; -} - -#else /* !CONFIG_SND_VERBOSE_PROCFS */ -#define preallocate_info_init(s) -#endif /* CONFIG_SND_VERBOSE_PROCFS */ - -/* - * pre-allocate the buffer and create a proc file for the substream - */ -static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream, - size_t size, size_t max) -{ - - if (size > 0 && preallocate_dma && substream->number < maximum_substreams) - preallocate_pcm_pages(substream, size); - - if (substream->dma_buffer.bytes > 0) - substream->buffer_bytes_max = substream->dma_buffer.bytes; - substream->dma_max = max; - preallocate_info_init(substream); - return 0; -} - - -/** - * snd_pcm_lib_preallocate_pages - pre-allocation for the given DMA type - * @substream: the pcm substream instance - * @type: DMA type (SNDRV_DMA_TYPE_*) - * @data: DMA type dependent data - * @size: the requested pre-allocation size in bytes - * @max: the max. allowed pre-allocation size - * - * Do pre-allocation for the given DMA buffer type. - * - * When substream->dma_buf_id is set, the function tries to look for - * the reserved buffer, and the buffer is not freed but reserved at - * destruction time. The dma_buf_id must be unique for all systems - * (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id(). - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, - int type, struct device *data, - size_t size, size_t max) -{ - substream->dma_buffer.dev.type = type; - substream->dma_buffer.dev.dev = data; - return snd_pcm_lib_preallocate_pages1(substream, size, max); -} - -EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); - -/** - * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continuous memory type (all substreams) - * @pcm: the pcm instance - * @type: DMA type (SNDRV_DMA_TYPE_*) - * @data: DMA type dependent data - * @size: the requested pre-allocation size in bytes - * @max: the max. allowed pre-allocation size - * - * Do pre-allocation to all substreams of the given pcm for the - * specified DMA type. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, - int type, void *data, - size_t size, size_t max) -{ - struct snd_pcm_substream *substream; - int stream, err; - - for (stream = 0; stream < 2; stream++) - for (substream = pcm->streams[stream].substream; substream; substream = substream->next) - if ((err = snd_pcm_lib_preallocate_pages(substream, type, data, size, max)) < 0) - return err; - return 0; -} - -EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); - -#ifdef CONFIG_SND_DMA_SGBUF -/** - * snd_pcm_sgbuf_ops_page - get the page struct at the given offset - * @substream: the pcm substream instance - * @offset: the buffer offset - * - * Returns the page struct at the given buffer offset. - * Used as the page callback of PCM ops. - */ -struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset) -{ - struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream); - - unsigned int idx = offset >> PAGE_SHIFT; - if (idx >= (unsigned int)sgbuf->pages) - return NULL; - return sgbuf->page_table[idx]; -} - -EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); - -/* - * compute the max chunk size with continuous pages on sg-buffer - */ -unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, - unsigned int ofs, unsigned int size) -{ - struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream); - unsigned int start, end, pg; - - start = ofs >> PAGE_SHIFT; - end = (ofs + size - 1) >> PAGE_SHIFT; - /* check page continuity */ - pg = sg->table[start].addr >> PAGE_SHIFT; - for (;;) { - start++; - if (start > end) - break; - pg++; - if ((sg->table[start].addr >> PAGE_SHIFT) != pg) - return (start << PAGE_SHIFT) - ofs; - } - /* ok, all on continuous pages */ - return size; -} -EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size); -#endif /* CONFIG_SND_DMA_SGBUF */ - -/** - * snd_pcm_lib_malloc_pages - allocate the DMA buffer - * @substream: the substream to allocate the DMA buffer to - * @size: the requested buffer size in bytes - * - * Allocates the DMA buffer on the BUS type given earlier to - * snd_pcm_lib_preallocate_xxx_pages(). - * - * Returns 1 if the buffer is changed, 0 if not changed, or a negative - * code on failure. - */ -int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size) -{ - struct snd_pcm_runtime *runtime; - struct snd_dma_buffer *dmab = NULL; - - if (PCM_RUNTIME_CHECK(substream)) - return -EINVAL; - if (snd_BUG_ON(substream->dma_buffer.dev.type == - SNDRV_DMA_TYPE_UNKNOWN)) - return -EINVAL; - runtime = substream->runtime; - - if (runtime->dma_buffer_p) { - /* perphaps, we might free the large DMA memory region - to save some space here, but the actual solution - costs us less time */ - if (runtime->dma_buffer_p->bytes >= size) { - runtime->dma_bytes = size; - return 0; /* ok, do not change */ - } - snd_pcm_lib_free_pages(substream); - } - if (substream->dma_buffer.area != NULL && - substream->dma_buffer.bytes >= size) { - dmab = &substream->dma_buffer; /* use the pre-allocated buffer */ - } else { - dmab = kzalloc(sizeof(*dmab), GFP_KERNEL); - if (! dmab) - return -ENOMEM; - dmab->dev = substream->dma_buffer.dev; - if (snd_dma_alloc_pages(substream->dma_buffer.dev.type, - substream->dma_buffer.dev.dev, - size, dmab) < 0) { - kfree(dmab); - return -ENOMEM; - } - } - snd_pcm_set_runtime_buffer(substream, dmab); - runtime->dma_bytes = size; - return 1; /* area was changed */ -} - -EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); - -/** - * snd_pcm_lib_free_pages - release the allocated DMA buffer. - * @substream: the substream to release the DMA buffer - * - * Releases the DMA buffer allocated via snd_pcm_lib_malloc_pages(). - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - - if (PCM_RUNTIME_CHECK(substream)) - return -EINVAL; - runtime = substream->runtime; - if (runtime->dma_area == NULL) - return 0; - if (runtime->dma_buffer_p != &substream->dma_buffer) { - /* it's a newly allocated buffer. release it now. */ - snd_dma_free_pages(runtime->dma_buffer_p); - kfree(runtime->dma_buffer_p); - } - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - -EXPORT_SYMBOL(snd_pcm_lib_free_pages); - -int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, - size_t size, gfp_t gfp_flags) -{ - struct snd_pcm_runtime *runtime; - - if (PCM_RUNTIME_CHECK(substream)) - return -EINVAL; - runtime = substream->runtime; - if (runtime->dma_area) { - if (runtime->dma_bytes >= size) - return 0; /* already large enough */ - vfree(runtime->dma_area); - } - runtime->dma_area = __vmalloc(size, gfp_flags, PAGE_KERNEL); - if (!runtime->dma_area) - return -ENOMEM; - runtime->dma_bytes = size; - return 1; -} -EXPORT_SYMBOL(_snd_pcm_lib_alloc_vmalloc_buffer); - -/** - * snd_pcm_lib_free_vmalloc_buffer - free vmalloc buffer - * @substream: the substream with a buffer allocated by - * snd_pcm_lib_alloc_vmalloc_buffer() - */ -int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - - if (PCM_RUNTIME_CHECK(substream)) - return -EINVAL; - runtime = substream->runtime; - vfree(runtime->dma_area); - runtime->dma_area = NULL; - return 0; -} -EXPORT_SYMBOL(snd_pcm_lib_free_vmalloc_buffer); - -/** - * snd_pcm_lib_get_vmalloc_page - map vmalloc buffer offset to page struct - * @substream: the substream with a buffer allocated by - * snd_pcm_lib_alloc_vmalloc_buffer() - * @offset: offset in the buffer - * - * This function is to be used as the page callback in the PCM ops. - */ -struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream, - unsigned long offset) -{ - return vmalloc_to_page(substream->runtime->dma_area + offset); -} -EXPORT_SYMBOL(snd_pcm_lib_get_vmalloc_page); diff --git a/ANDROID_3.4.5/sound/core/pcm_misc.c b/ANDROID_3.4.5/sound/core/pcm_misc.c deleted file mode 100644 index 9c9eff9a..00000000 --- a/ANDROID_3.4.5/sound/core/pcm_misc.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * PCM Interface - misc routines - * Copyright (c) 1998 by Jaroslav Kysela - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library 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 Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#define SND_PCM_FORMAT_UNKNOWN (-1) - -/* NOTE: "signed" prefix must be given below since the default char is - * unsigned on some architectures! - */ -struct pcm_format_data { - unsigned char width; /* bit width */ - unsigned char phys; /* physical bit width */ - signed char le; /* 0 = big-endian, 1 = little-endian, -1 = others */ - signed char signd; /* 0 = unsigned, 1 = signed, -1 = others */ - unsigned char silence[8]; /* silence data to fill */ -}; - -/* we do lots of calculations on snd_pcm_format_t; shut up sparse */ -#define INT __force int - -static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = { - [SNDRV_PCM_FORMAT_S8] = { - .width = 8, .phys = 8, .le = -1, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_U8] = { - .width = 8, .phys = 8, .le = -1, .signd = 0, - .silence = { 0x80 }, - }, - [SNDRV_PCM_FORMAT_S16_LE] = { - .width = 16, .phys = 16, .le = 1, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_S16_BE] = { - .width = 16, .phys = 16, .le = 0, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_U16_LE] = { - .width = 16, .phys = 16, .le = 1, .signd = 0, - .silence = { 0x00, 0x80 }, - }, - [SNDRV_PCM_FORMAT_U16_BE] = { - .width = 16, .phys = 16, .le = 0, .signd = 0, - .silence = { 0x80, 0x00 }, - }, - [SNDRV_PCM_FORMAT_S24_LE] = { - .width = 24, .phys = 32, .le = 1, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_S24_BE] = { - .width = 24, .phys = 32, .le = 0, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_U24_LE] = { - .width = 24, .phys = 32, .le = 1, .signd = 0, - .silence = { 0x00, 0x00, 0x80 }, - }, - [SNDRV_PCM_FORMAT_U24_BE] = { - .width = 24, .phys = 32, .le = 0, .signd = 0, - .silence = { 0x00, 0x80, 0x00, 0x00 }, - }, - [SNDRV_PCM_FORMAT_S32_LE] = { - .width = 32, .phys = 32, .le = 1, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_S32_BE] = { - .width = 32, .phys = 32, .le = 0, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_U32_LE] = { - .width = 32, .phys = 32, .le = 1, .signd = 0, - .silence = { 0x00, 0x00, 0x00, 0x80 }, - }, - [SNDRV_PCM_FORMAT_U32_BE] = { - .width = 32, .phys = 32, .le = 0, .signd = 0, - .silence = { 0x80, 0x00, 0x00, 0x00 }, - }, - [SNDRV_PCM_FORMAT_FLOAT_LE] = { - .width = 32, .phys = 32, .le = 1, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_FLOAT_BE] = { - .width = 32, .phys = 32, .le = 0, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_FLOAT64_LE] = { - .width = 64, .phys = 64, .le = 1, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_FLOAT64_BE] = { - .width = 64, .phys = 64, .le = 0, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE] = { - .width = 32, .phys = 32, .le = 1, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE] = { - .width = 32, .phys = 32, .le = 0, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_MU_LAW] = { - .width = 8, .phys = 8, .le = -1, .signd = -1, - .silence = { 0x7f }, - }, - [SNDRV_PCM_FORMAT_A_LAW] = { - .width = 8, .phys = 8, .le = -1, .signd = -1, - .silence = { 0x55 }, - }, - [SNDRV_PCM_FORMAT_IMA_ADPCM] = { - .width = 4, .phys = 4, .le = -1, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_G723_24] = { - .width = 3, .phys = 3, .le = -1, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_G723_40] = { - .width = 5, .phys = 5, .le = -1, .signd = -1, - .silence = {}, - }, - /* FIXME: the following three formats are not defined properly yet */ - [SNDRV_PCM_FORMAT_MPEG] = { - .le = -1, .signd = -1, - }, - [SNDRV_PCM_FORMAT_GSM] = { - .le = -1, .signd = -1, - }, - [SNDRV_PCM_FORMAT_SPECIAL] = { - .le = -1, .signd = -1, - }, - [SNDRV_PCM_FORMAT_S24_3LE] = { - .width = 24, .phys = 24, .le = 1, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_S24_3BE] = { - .width = 24, .phys = 24, .le = 0, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_U24_3LE] = { - .width = 24, .phys = 24, .le = 1, .signd = 0, - .silence = { 0x00, 0x00, 0x80 }, - }, - [SNDRV_PCM_FORMAT_U24_3BE] = { - .width = 24, .phys = 24, .le = 0, .signd = 0, - .silence = { 0x80, 0x00, 0x00 }, - }, - [SNDRV_PCM_FORMAT_S20_3LE] = { - .width = 20, .phys = 24, .le = 1, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_S20_3BE] = { - .width = 20, .phys = 24, .le = 0, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_U20_3LE] = { - .width = 20, .phys = 24, .le = 1, .signd = 0, - .silence = { 0x00, 0x00, 0x08 }, - }, - [SNDRV_PCM_FORMAT_U20_3BE] = { - .width = 20, .phys = 24, .le = 0, .signd = 0, - .silence = { 0x08, 0x00, 0x00 }, - }, - [SNDRV_PCM_FORMAT_S18_3LE] = { - .width = 18, .phys = 24, .le = 1, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_S18_3BE] = { - .width = 18, .phys = 24, .le = 0, .signd = 1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_U18_3LE] = { - .width = 18, .phys = 24, .le = 1, .signd = 0, - .silence = { 0x00, 0x00, 0x02 }, - }, - [SNDRV_PCM_FORMAT_U18_3BE] = { - .width = 18, .phys = 24, .le = 0, .signd = 0, - .silence = { 0x02, 0x00, 0x00 }, - }, - [SNDRV_PCM_FORMAT_G723_24_1B] = { - .width = 3, .phys = 8, .le = -1, .signd = -1, - .silence = {}, - }, - [SNDRV_PCM_FORMAT_G723_40_1B] = { - .width = 5, .phys = 8, .le = -1, .signd = -1, - .silence = {}, - }, -}; - - -/** - * snd_pcm_format_signed - Check the PCM format is signed linear - * @format: the format to check - * - * Returns 1 if the given PCM format is signed linear, 0 if unsigned - * linear, and a negative error code for non-linear formats. - */ -int snd_pcm_format_signed(snd_pcm_format_t format) -{ - int val; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) - return -EINVAL; - if ((val = pcm_formats[(INT)format].signd) < 0) - return -EINVAL; - return val; -} - -EXPORT_SYMBOL(snd_pcm_format_signed); - -/** - * snd_pcm_format_unsigned - Check the PCM format is unsigned linear - * @format: the format to check - * - * Returns 1 if the given PCM format is unsigned linear, 0 if signed - * linear, and a negative error code for non-linear formats. - */ -int snd_pcm_format_unsigned(snd_pcm_format_t format) -{ - int val; - - val = snd_pcm_format_signed(format); - if (val < 0) - return val; - return !val; -} - -EXPORT_SYMBOL(snd_pcm_format_unsigned); - -/** - * snd_pcm_format_linear - Check the PCM format is linear - * @format: the format to check - * - * Returns 1 if the given PCM format is linear, 0 if not. - */ -int snd_pcm_format_linear(snd_pcm_format_t format) -{ - return snd_pcm_format_signed(format) >= 0; -} - -EXPORT_SYMBOL(snd_pcm_format_linear); - -/** - * snd_pcm_format_little_endian - Check the PCM format is little-endian - * @format: the format to check - * - * Returns 1 if the given PCM format is little-endian, 0 if - * big-endian, or a negative error code if endian not specified. - */ -int snd_pcm_format_little_endian(snd_pcm_format_t format) -{ - int val; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) - return -EINVAL; - if ((val = pcm_formats[(INT)format].le) < 0) - return -EINVAL; - return val; -} - -EXPORT_SYMBOL(snd_pcm_format_little_endian); - -/** - * snd_pcm_format_big_endian - Check the PCM format is big-endian - * @format: the format to check - * - * Returns 1 if the given PCM format is big-endian, 0 if - * little-endian, or a negative error code if endian not specified. - */ -int snd_pcm_format_big_endian(snd_pcm_format_t format) -{ - int val; - - val = snd_pcm_format_little_endian(format); - if (val < 0) - return val; - return !val; -} - -EXPORT_SYMBOL(snd_pcm_format_big_endian); - -/** - * snd_pcm_format_width - return the bit-width of the format - * @format: the format to check - * - * Returns the bit-width of the format, or a negative error code - * if unknown format. - */ -int snd_pcm_format_width(snd_pcm_format_t format) -{ - int val; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) - return -EINVAL; - if ((val = pcm_formats[(INT)format].width) == 0) - return -EINVAL; - return val; -} - -EXPORT_SYMBOL(snd_pcm_format_width); - -/** - * snd_pcm_format_physical_width - return the physical bit-width of the format - * @format: the format to check - * - * Returns the physical bit-width of the format, or a negative error code - * if unknown format. - */ -int snd_pcm_format_physical_width(snd_pcm_format_t format) -{ - int val; - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) - return -EINVAL; - if ((val = pcm_formats[(INT)format].phys) == 0) - return -EINVAL; - return val; -} - -EXPORT_SYMBOL(snd_pcm_format_physical_width); - -/** - * snd_pcm_format_size - return the byte size of samples on the given format - * @format: the format to check - * @samples: sampling rate - * - * Returns the byte size of the given samples for the format, or a - * negative error code if unknown format. - */ -ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) -{ - int phys_width = snd_pcm_format_physical_width(format); - if (phys_width < 0) - return -EINVAL; - return samples * phys_width / 8; -} - -EXPORT_SYMBOL(snd_pcm_format_size); - -/** - * snd_pcm_format_silence_64 - return the silent data in 8 bytes array - * @format: the format to check - * - * Returns the format pattern to fill or NULL if error. - */ -const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) -{ - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) - return NULL; - if (! pcm_formats[(INT)format].phys) - return NULL; - return pcm_formats[(INT)format].silence; -} - -EXPORT_SYMBOL(snd_pcm_format_silence_64); - -/** - * snd_pcm_format_set_silence - set the silence data on the buffer - * @format: the PCM format - * @data: the buffer pointer - * @samples: the number of samples to set silence - * - * Sets the silence data on the buffer for the given samples. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples) -{ - int width; - unsigned char *dst, *pat; - - if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) - return -EINVAL; - if (samples == 0) - return 0; - width = pcm_formats[(INT)format].phys; /* physical width */ - pat = pcm_formats[(INT)format].silence; - if (! width) - return -EINVAL; - /* signed or 1 byte data */ - if (pcm_formats[(INT)format].signd == 1 || width <= 8) { - unsigned int bytes = samples * width / 8; - memset(data, *pat, bytes); - return 0; - } - /* non-zero samples, fill using a loop */ - width /= 8; - dst = data; -#if 0 - while (samples--) { - memcpy(dst, pat, width); - dst += width; - } -#else - /* a bit optimization for constant width */ - switch (width) { - case 2: - while (samples--) { - memcpy(dst, pat, 2); - dst += 2; - } - break; - case 3: - while (samples--) { - memcpy(dst, pat, 3); - dst += 3; - } - break; - case 4: - while (samples--) { - memcpy(dst, pat, 4); - dst += 4; - } - break; - case 8: - while (samples--) { - memcpy(dst, pat, 8); - dst += 8; - } - break; - } -#endif - return 0; -} - -EXPORT_SYMBOL(snd_pcm_format_set_silence); - -/** - * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields - * @runtime: the runtime instance - * - * Determines the rate_min and rate_max fields from the rates bits of - * the given runtime->hw. - * - * Returns zero if successful. - */ -int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) -{ - int i; - for (i = 0; i < (int)snd_pcm_known_rates.count; i++) { - if (runtime->hw.rates & (1 << i)) { - runtime->hw.rate_min = snd_pcm_known_rates.list[i]; - break; - } - } - for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) { - if (runtime->hw.rates & (1 << i)) { - runtime->hw.rate_max = snd_pcm_known_rates.list[i]; - break; - } - } - return 0; -} - -EXPORT_SYMBOL(snd_pcm_limit_hw_rates); - -/** - * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit - * @rate: the sample rate to convert - * - * Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or - * SNDRV_PCM_RATE_KNOT for an unknown rate. - */ -unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate) -{ - unsigned int i; - - for (i = 0; i < snd_pcm_known_rates.count; i++) - if (snd_pcm_known_rates.list[i] == rate) - return 1u << i; - return SNDRV_PCM_RATE_KNOT; -} -EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit); diff --git a/ANDROID_3.4.5/sound/core/pcm_native.c b/ANDROID_3.4.5/sound/core/pcm_native.c deleted file mode 100644 index d535b341..00000000 --- a/ANDROID_3.4.5/sound/core/pcm_native.c +++ /dev/null @@ -1,3492 +0,0 @@ -/* - * Digital Audio (PCM) abstract layer - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT) -#include -#endif - -/* - * Compatibility - */ - -struct snd_pcm_hw_params_old { - unsigned int flags; - unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT - - SNDRV_PCM_HW_PARAM_ACCESS + 1]; - struct snd_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME - - SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1]; - unsigned int rmask; - unsigned int cmask; - unsigned int info; - unsigned int msbits; - unsigned int rate_num; - unsigned int rate_den; - snd_pcm_uframes_t fifo_size; - unsigned char reserved[64]; -}; - -#ifdef CONFIG_SND_SUPPORT_OLD_API -#define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct snd_pcm_hw_params_old) -#define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct snd_pcm_hw_params_old) - -static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params_old __user * _oparams); -static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params_old __user * _oparams); -#endif -static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream); - -/* - * - */ - -DEFINE_RWLOCK(snd_pcm_link_rwlock); -EXPORT_SYMBOL(snd_pcm_link_rwlock); - -static DECLARE_RWSEM(snd_pcm_link_rwsem); - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - - - -int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) -{ - struct snd_pcm_runtime *runtime; - struct snd_pcm *pcm = substream->pcm; - struct snd_pcm_str *pstr = substream->pstr; - - memset(info, 0, sizeof(*info)); - info->card = pcm->card->number; - info->device = pcm->device; - info->stream = substream->stream; - info->subdevice = substream->number; - strlcpy(info->id, pcm->id, sizeof(info->id)); - strlcpy(info->name, pcm->name, sizeof(info->name)); - info->dev_class = pcm->dev_class; - info->dev_subclass = pcm->dev_subclass; - info->subdevices_count = pstr->substream_count; - info->subdevices_avail = pstr->substream_count - pstr->substream_opened; - strlcpy(info->subname, substream->name, sizeof(info->subname)); - runtime = substream->runtime; - /* AB: FIXME!!! This is definitely nonsense */ - if (runtime) { - info->sync = runtime->sync; - substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info); - } - return 0; -} - -int snd_pcm_info_user(struct snd_pcm_substream *substream, - struct snd_pcm_info __user * _info) -{ - struct snd_pcm_info *info; - int err; - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) - return -ENOMEM; - err = snd_pcm_info(substream, info); - if (err >= 0) { - if (copy_to_user(_info, info, sizeof(*info))) - err = -EFAULT; - } - kfree(info); - return err; -} - -#undef RULES_DEBUG - -#ifdef RULES_DEBUG -#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v -static const char * const snd_pcm_hw_param_names[] = { - HW_PARAM(ACCESS), - HW_PARAM(FORMAT), - HW_PARAM(SUBFORMAT), - HW_PARAM(SAMPLE_BITS), - HW_PARAM(FRAME_BITS), - HW_PARAM(CHANNELS), - HW_PARAM(RATE), - HW_PARAM(PERIOD_TIME), - HW_PARAM(PERIOD_SIZE), - HW_PARAM(PERIOD_BYTES), - HW_PARAM(PERIODS), - HW_PARAM(BUFFER_TIME), - HW_PARAM(BUFFER_SIZE), - HW_PARAM(BUFFER_BYTES), - HW_PARAM(TICK_TIME), -}; -#endif - -int snd_pcm_hw_refine(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - unsigned int k; - struct snd_pcm_hardware *hw; - struct snd_interval *i = NULL; - struct snd_mask *m = NULL; - struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints; - unsigned int rstamps[constrs->rules_num]; - unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; - unsigned int stamp = 2; - int changed, again; - - params->info = 0; - params->fifo_size = 0; - if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) - params->msbits = 0; - if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) { - params->rate_num = 0; - params->rate_den = 0; - } - - for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { - m = hw_param_mask(params, k); - if (snd_mask_empty(m)) - return -EINVAL; - if (!(params->rmask & (1 << k))) - continue; -#ifdef RULES_DEBUG - printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]); - printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); -#endif - changed = snd_mask_refine(m, constrs_mask(constrs, k)); -#ifdef RULES_DEBUG - printk("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); -#endif - if (changed) - params->cmask |= 1 << k; - if (changed < 0) - return changed; - } - - for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { - i = hw_param_interval(params, k); - if (snd_interval_empty(i)) - return -EINVAL; - if (!(params->rmask & (1 << k))) - continue; -#ifdef RULES_DEBUG - printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]); - if (i->empty) - printk("empty"); - else - printk("%c%u %u%c", - i->openmin ? '(' : '[', i->min, - i->max, i->openmax ? ')' : ']'); - printk(" -> "); -#endif - changed = snd_interval_refine(i, constrs_interval(constrs, k)); -#ifdef RULES_DEBUG - if (i->empty) - printk("empty\n"); - else - printk("%c%u %u%c\n", - i->openmin ? '(' : '[', i->min, - i->max, i->openmax ? ')' : ']'); -#endif - if (changed) - params->cmask |= 1 << k; - if (changed < 0) - return changed; - } - - for (k = 0; k < constrs->rules_num; k++) - rstamps[k] = 0; - for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) - vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; - do { - again = 0; - for (k = 0; k < constrs->rules_num; k++) { - struct snd_pcm_hw_rule *r = &constrs->rules[k]; - unsigned int d; - int doit = 0; - if (r->cond && !(r->cond & params->flags)) - continue; - for (d = 0; r->deps[d] >= 0; d++) { - if (vstamps[r->deps[d]] > rstamps[k]) { - doit = 1; - break; - } - } - if (!doit) - continue; -#ifdef RULES_DEBUG - printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func); - if (r->var >= 0) { - printk("%s = ", snd_pcm_hw_param_names[r->var]); - if (hw_is_mask(r->var)) { - m = hw_param_mask(params, r->var); - printk("%x", *m->bits); - } else { - i = hw_param_interval(params, r->var); - if (i->empty) - printk("empty"); - else - printk("%c%u %u%c", - i->openmin ? '(' : '[', i->min, - i->max, i->openmax ? ')' : ']'); - } - } -#endif - changed = r->func(params, r); -#ifdef RULES_DEBUG - if (r->var >= 0) { - printk(" -> "); - if (hw_is_mask(r->var)) - printk("%x", *m->bits); - else { - if (i->empty) - printk("empty"); - else - printk("%c%u %u%c", - i->openmin ? '(' : '[', i->min, - i->max, i->openmax ? ')' : ']'); - } - } - printk("\n"); -#endif - rstamps[k] = stamp; - if (changed && r->var >= 0) { - params->cmask |= (1 << r->var); - vstamps[r->var] = stamp; - again = 1; - } - if (changed < 0) - return changed; - stamp++; - } - } while (again); - if (!params->msbits) { - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); - if (snd_interval_single(i)) - params->msbits = snd_interval_value(i); - } - - if (!params->rate_den) { - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (snd_interval_single(i)) { - params->rate_num = snd_interval_value(i); - params->rate_den = 1; - } - } - - hw = &substream->runtime->hw; - if (!params->info) - params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES; - if (!params->fifo_size) { - m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - if (snd_mask_min(m) == snd_mask_max(m) && - snd_interval_min(i) == snd_interval_max(i)) { - changed = substream->ops->ioctl(substream, - SNDRV_PCM_IOCTL1_FIFO_SIZE, params); - if (changed < 0) - return changed; - } - } - params->rmask = 0; - return 0; -} - -EXPORT_SYMBOL(snd_pcm_hw_refine); - -static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params __user * _params) -{ - struct snd_pcm_hw_params *params; - int err; - - 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; - } - - kfree(params); - return err; -} - -static int period_to_usecs(struct snd_pcm_runtime *runtime) -{ - int usecs; - - if (! runtime->rate) - return -1; /* invalid */ - - /* take 75% of period time as the deadline */ - usecs = (750000 / runtime->rate) * runtime->period_size; - usecs += ((750000 % runtime->rate) * runtime->period_size) / - runtime->rate; - - return usecs; -} - -static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) -{ - snd_pcm_stream_lock_irq(substream); - if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) - substream->runtime->status->state = state; - snd_pcm_stream_unlock_irq(substream); -} - -static int snd_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime; - int err, usecs; - unsigned int bits; - snd_pcm_uframes_t frames; - - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_OPEN: - case SNDRV_PCM_STATE_SETUP: - case SNDRV_PCM_STATE_PREPARED: - break; - default: - snd_pcm_stream_unlock_irq(substream); - return -EBADFD; - } - snd_pcm_stream_unlock_irq(substream); -#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) - if (!substream->oss.oss) -#endif - if (atomic_read(&substream->mmap_count)) - return -EBADFD; - - params->rmask = ~0U; - err = snd_pcm_hw_refine(substream, params); - if (err < 0) - goto _error; - - err = snd_pcm_hw_params_choose(substream, params); - if (err < 0) - goto _error; - - if (substream->ops->hw_params != NULL) { - err = substream->ops->hw_params(substream, params); - if (err < 0) - goto _error; - } - - runtime->access = params_access(params); - runtime->format = params_format(params); - runtime->subformat = params_subformat(params); - runtime->channels = params_channels(params); - runtime->rate = params_rate(params); - runtime->period_size = params_period_size(params); - runtime->periods = params_periods(params); - runtime->buffer_size = params_buffer_size(params); - runtime->info = params->info; - runtime->rate_num = params->rate_num; - runtime->rate_den = params->rate_den; - runtime->no_period_wakeup = - (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) && - (params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP); - - bits = snd_pcm_format_physical_width(runtime->format); - runtime->sample_bits = bits; - bits *= runtime->channels; - runtime->frame_bits = bits; - frames = 1; - while (bits % 8 != 0) { - bits *= 2; - frames *= 2; - } - runtime->byte_align = bits / 8; - runtime->min_align = frames; - - /* Default sw params */ - runtime->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; - runtime->period_step = 1; - runtime->control->avail_min = runtime->period_size; - runtime->start_threshold = 1; - runtime->stop_threshold = runtime->buffer_size; - runtime->silence_threshold = 0; - runtime->silence_size = 0; - runtime->boundary = runtime->buffer_size; - while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size) - runtime->boundary *= 2; - - snd_pcm_timer_resolution_change(substream); - snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); - - if (pm_qos_request_active(&substream->latency_pm_qos_req)) - pm_qos_remove_request(&substream->latency_pm_qos_req); - if ((usecs = period_to_usecs(runtime)) >= 0) - pm_qos_add_request(&substream->latency_pm_qos_req, - PM_QOS_CPU_DMA_LATENCY, usecs); - return 0; - _error: - /* hardware might be unusable from this time, - so we force application to retry to set - the correct hardware parameter settings */ - snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); - if (substream->ops->hw_free != NULL) - substream->ops->hw_free(substream); - return err; -} - -static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params __user * _params) -{ - struct snd_pcm_hw_params *params; - int err; - - 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; - } - - kfree(params); - return err; -} - -static int snd_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - int result = 0; - - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_SETUP: - case SNDRV_PCM_STATE_PREPARED: - break; - default: - snd_pcm_stream_unlock_irq(substream); - return -EBADFD; - } - snd_pcm_stream_unlock_irq(substream); - if (atomic_read(&substream->mmap_count)) - return -EBADFD; - if (substream->ops->hw_free) - result = substream->ops->hw_free(substream); - snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); - pm_qos_remove_request(&substream->latency_pm_qos_req); - return result; -} - -static int snd_pcm_sw_params(struct snd_pcm_substream *substream, - struct snd_pcm_sw_params *params) -{ - struct snd_pcm_runtime *runtime; - int err; - - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - snd_pcm_stream_lock_irq(substream); - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { - snd_pcm_stream_unlock_irq(substream); - return -EBADFD; - } - snd_pcm_stream_unlock_irq(substream); - - if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST) - return -EINVAL; - if (params->avail_min == 0) - return -EINVAL; - if (params->silence_size >= runtime->boundary) { - if (params->silence_threshold != 0) - return -EINVAL; - } else { - if (params->silence_size > params->silence_threshold) - return -EINVAL; - if (params->silence_threshold > runtime->buffer_size) - return -EINVAL; - } - err = 0; - snd_pcm_stream_lock_irq(substream); - runtime->tstamp_mode = params->tstamp_mode; - runtime->period_step = params->period_step; - runtime->control->avail_min = params->avail_min; - runtime->start_threshold = params->start_threshold; - runtime->stop_threshold = params->stop_threshold; - runtime->silence_threshold = params->silence_threshold; - runtime->silence_size = params->silence_size; - params->boundary = runtime->boundary; - if (snd_pcm_running(substream)) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) - snd_pcm_playback_silence(substream, ULONG_MAX); - err = snd_pcm_update_state(substream, runtime); - } - snd_pcm_stream_unlock_irq(substream); - return err; -} - -static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream, - struct snd_pcm_sw_params __user * _params) -{ - struct snd_pcm_sw_params params; - int err; - if (copy_from_user(¶ms, _params, sizeof(params))) - return -EFAULT; - err = snd_pcm_sw_params(substream, ¶ms); - if (copy_to_user(_params, ¶ms, sizeof(params))) - return -EFAULT; - return err; -} - -int snd_pcm_status(struct snd_pcm_substream *substream, - struct snd_pcm_status *status) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_pcm_stream_lock_irq(substream); - status->state = runtime->status->state; - status->suspended_state = runtime->status->suspended_state; - if (status->state == SNDRV_PCM_STATE_OPEN) - goto _end; - status->trigger_tstamp = runtime->trigger_tstamp; - if (snd_pcm_running(substream)) { - snd_pcm_update_hw_ptr(substream); - if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) { - status->tstamp = runtime->status->tstamp; - goto _tstamp_end; - } - } - snd_pcm_gettime(runtime, &status->tstamp); - _tstamp_end: - status->appl_ptr = runtime->control->appl_ptr; - status->hw_ptr = runtime->status->hw_ptr; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - status->avail = snd_pcm_playback_avail(runtime); - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING || - runtime->status->state == SNDRV_PCM_STATE_DRAINING) { - status->delay = runtime->buffer_size - status->avail; - status->delay += runtime->delay; - } else - status->delay = 0; - } else { - status->avail = snd_pcm_capture_avail(runtime); - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) - status->delay = status->avail + runtime->delay; - else - status->delay = 0; - } - status->avail_max = runtime->avail_max; - status->overrange = runtime->overrange; - runtime->avail_max = 0; - runtime->overrange = 0; - _end: - snd_pcm_stream_unlock_irq(substream); - return 0; -} - -static int snd_pcm_status_user(struct snd_pcm_substream *substream, - struct snd_pcm_status __user * _status) -{ - struct snd_pcm_status status; - int res; - - memset(&status, 0, sizeof(status)); - res = snd_pcm_status(substream, &status); - if (res < 0) - return res; - if (copy_to_user(_status, &status, sizeof(status))) - return -EFAULT; - return 0; -} - -static int snd_pcm_channel_info(struct snd_pcm_substream *substream, - struct snd_pcm_channel_info * info) -{ - struct snd_pcm_runtime *runtime; - unsigned int channel; - - channel = info->channel; - runtime = substream->runtime; - snd_pcm_stream_lock_irq(substream); - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { - snd_pcm_stream_unlock_irq(substream); - return -EBADFD; - } - snd_pcm_stream_unlock_irq(substream); - if (channel >= runtime->channels) - return -EINVAL; - memset(info, 0, sizeof(*info)); - info->channel = channel; - return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info); -} - -static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream, - struct snd_pcm_channel_info __user * _info) -{ - struct snd_pcm_channel_info info; - int res; - - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - res = snd_pcm_channel_info(substream, &info); - if (res < 0) - return res; - if (copy_to_user(_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->trigger_master == NULL) - return; - if (runtime->trigger_master == substream) { - snd_pcm_gettime(runtime, &runtime->trigger_tstamp); - } else { - snd_pcm_trigger_tstamp(runtime->trigger_master); - runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp; - } - runtime->trigger_master = NULL; -} - -struct action_ops { - int (*pre_action)(struct snd_pcm_substream *substream, int state); - int (*do_action)(struct snd_pcm_substream *substream, int state); - void (*undo_action)(struct snd_pcm_substream *substream, int state); - void (*post_action)(struct snd_pcm_substream *substream, int state); -}; - -/* - * this functions is core for handling of linked stream - * Note: the stream state might be changed also on failure - * Note2: call with calling stream lock + link lock - */ -static int snd_pcm_action_group(struct action_ops *ops, - struct snd_pcm_substream *substream, - int state, int do_lock) -{ - struct snd_pcm_substream *s = NULL; - struct snd_pcm_substream *s1; - int res = 0; - - snd_pcm_group_for_each_entry(s, substream) { - if (do_lock && s != substream) - spin_lock_nested(&s->self_group.lock, - SINGLE_DEPTH_NESTING); - res = ops->pre_action(s, state); - if (res < 0) - goto _unlock; - } - snd_pcm_group_for_each_entry(s, substream) { - res = ops->do_action(s, state); - if (res < 0) { - if (ops->undo_action) { - snd_pcm_group_for_each_entry(s1, substream) { - if (s1 == s) /* failed stream */ - break; - ops->undo_action(s1, state); - } - } - s = NULL; /* unlock all */ - goto _unlock; - } - } - snd_pcm_group_for_each_entry(s, substream) { - ops->post_action(s, state); - } - _unlock: - if (do_lock) { - /* unlock streams */ - snd_pcm_group_for_each_entry(s1, substream) { - if (s1 != substream) - spin_unlock(&s1->self_group.lock); - if (s1 == s) /* end */ - break; - } - } - return res; -} - -/* - * Note: call with stream lock - */ -static int snd_pcm_action_single(struct action_ops *ops, - struct snd_pcm_substream *substream, - int state) -{ - int res; - - res = ops->pre_action(substream, state); - if (res < 0) - return res; - res = ops->do_action(substream, state); - if (res == 0) - ops->post_action(substream, state); - else if (ops->undo_action) - ops->undo_action(substream, state); - return res; -} - -/* - * Note: call with stream lock - */ -static int snd_pcm_action(struct action_ops *ops, - struct snd_pcm_substream *substream, - int state) -{ - int res; - - if (snd_pcm_stream_linked(substream)) { - if (!spin_trylock(&substream->group->lock)) { - spin_unlock(&substream->self_group.lock); - spin_lock(&substream->group->lock); - spin_lock(&substream->self_group.lock); - } - res = snd_pcm_action_group(ops, substream, state, 1); - spin_unlock(&substream->group->lock); - } else { - res = snd_pcm_action_single(ops, substream, state); - } - return res; -} - -/* - * Note: don't use any locks before - */ -static int snd_pcm_action_lock_irq(struct action_ops *ops, - struct snd_pcm_substream *substream, - int state) -{ - int res; - - read_lock_irq(&snd_pcm_link_rwlock); - if (snd_pcm_stream_linked(substream)) { - spin_lock(&substream->group->lock); - spin_lock(&substream->self_group.lock); - res = snd_pcm_action_group(ops, substream, state, 1); - spin_unlock(&substream->self_group.lock); - spin_unlock(&substream->group->lock); - } else { - spin_lock(&substream->self_group.lock); - res = snd_pcm_action_single(ops, substream, state); - spin_unlock(&substream->self_group.lock); - } - read_unlock_irq(&snd_pcm_link_rwlock); - return res; -} - -/* - */ -static int snd_pcm_action_nonatomic(struct action_ops *ops, - struct snd_pcm_substream *substream, - int state) -{ - int res; - - down_read(&snd_pcm_link_rwsem); - if (snd_pcm_stream_linked(substream)) - res = snd_pcm_action_group(ops, substream, state, 0); - else - res = snd_pcm_action_single(ops, substream, state); - up_read(&snd_pcm_link_rwsem); - return res; -} - -/* - * start callbacks - */ -static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state != SNDRV_PCM_STATE_PREPARED) - return -EBADFD; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - !snd_pcm_playback_data(substream)) - return -EPIPE; - runtime->trigger_master = substream; - return 0; -} - -static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state) -{ - if (substream->runtime->trigger_master != substream) - return 0; - return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START); -} - -static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state) -{ - if (substream->runtime->trigger_master == substream) - substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); -} - -static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_trigger_tstamp(substream); - runtime->hw_ptr_jiffies = jiffies; - runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / - runtime->rate; - runtime->status->state = state; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) - snd_pcm_playback_silence(substream, ULONG_MAX); - if (substream->timer) - snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART, - &runtime->trigger_tstamp); -} - -static struct action_ops snd_pcm_action_start = { - .pre_action = snd_pcm_pre_start, - .do_action = snd_pcm_do_start, - .undo_action = snd_pcm_undo_start, - .post_action = snd_pcm_post_start -}; - -/** - * snd_pcm_start - start all linked streams - * @substream: the PCM substream instance - */ -int snd_pcm_start(struct snd_pcm_substream *substream) -{ - return snd_pcm_action(&snd_pcm_action_start, substream, - SNDRV_PCM_STATE_RUNNING); -} - -/* - * stop callbacks - */ -static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - runtime->trigger_master = substream; - return 0; -} - -static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state) -{ - if (substream->runtime->trigger_master == substream && - snd_pcm_running(substream)) - substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); - return 0; /* unconditonally stop all substreams */ -} - -static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state != state) { - snd_pcm_trigger_tstamp(substream); - if (substream->timer) - snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP, - &runtime->trigger_tstamp); - runtime->status->state = state; - } - wake_up(&runtime->sleep); - wake_up(&runtime->tsleep); -} - -static struct action_ops snd_pcm_action_stop = { - .pre_action = snd_pcm_pre_stop, - .do_action = snd_pcm_do_stop, - .post_action = snd_pcm_post_stop -}; - -/** - * snd_pcm_stop - try to stop all running streams in the substream group - * @substream: the PCM substream instance - * @state: PCM state after stopping the stream - * - * The state of each stream is then changed to the given state unconditionally. - */ -int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) -{ - return snd_pcm_action(&snd_pcm_action_stop, substream, state); -} - -EXPORT_SYMBOL(snd_pcm_stop); - -/** - * snd_pcm_drain_done - stop the DMA only when the given stream is playback - * @substream: the PCM substream - * - * After stopping, the state is changed to SETUP. - * Unlike snd_pcm_stop(), this affects only the given stream. - */ -int snd_pcm_drain_done(struct snd_pcm_substream *substream) -{ - return snd_pcm_action_single(&snd_pcm_action_stop, substream, - SNDRV_PCM_STATE_SETUP); -} - -/* - * pause callbacks - */ -static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (!(runtime->info & SNDRV_PCM_INFO_PAUSE)) - return -ENOSYS; - if (push) { - if (runtime->status->state != SNDRV_PCM_STATE_RUNNING) - return -EBADFD; - } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED) - return -EBADFD; - runtime->trigger_master = substream; - return 0; -} - -static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push) -{ - if (substream->runtime->trigger_master != substream) - return 0; - /* some drivers might use hw_ptr to recover from the pause - - update the hw_ptr now */ - if (push) - snd_pcm_update_hw_ptr(substream); - /* The jiffies check in snd_pcm_update_hw_ptr*() is done by - * a delta between the current jiffies, this gives a large enough - * delta, effectively to skip the check once. - */ - substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000; - return substream->ops->trigger(substream, - push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH : - SNDRV_PCM_TRIGGER_PAUSE_RELEASE); -} - -static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push) -{ - if (substream->runtime->trigger_master == substream) - substream->ops->trigger(substream, - push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE : - SNDRV_PCM_TRIGGER_PAUSE_PUSH); -} - -static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_trigger_tstamp(substream); - if (push) { - runtime->status->state = SNDRV_PCM_STATE_PAUSED; - if (substream->timer) - snd_timer_notify(substream->timer, - SNDRV_TIMER_EVENT_MPAUSE, - &runtime->trigger_tstamp); - wake_up(&runtime->sleep); - wake_up(&runtime->tsleep); - } else { - runtime->status->state = SNDRV_PCM_STATE_RUNNING; - if (substream->timer) - snd_timer_notify(substream->timer, - SNDRV_TIMER_EVENT_MCONTINUE, - &runtime->trigger_tstamp); - } -} - -static struct action_ops snd_pcm_action_pause = { - .pre_action = snd_pcm_pre_pause, - .do_action = snd_pcm_do_pause, - .undo_action = snd_pcm_undo_pause, - .post_action = snd_pcm_post_pause -}; - -/* - * Push/release the pause for all linked streams. - */ -static int snd_pcm_pause(struct snd_pcm_substream *substream, int push) -{ - return snd_pcm_action(&snd_pcm_action_pause, substream, push); -} - -#ifdef CONFIG_PM -/* suspend */ - -static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) - return -EBUSY; - runtime->trigger_master = substream; - return 0; -} - -static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->trigger_master != substream) - return 0; - if (! snd_pcm_running(substream)) - return 0; - substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND); - return 0; /* suspend unconditionally */ -} - -static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_trigger_tstamp(substream); - if (substream->timer) - snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSUSPEND, - &runtime->trigger_tstamp); - runtime->status->suspended_state = runtime->status->state; - runtime->status->state = SNDRV_PCM_STATE_SUSPENDED; - wake_up(&runtime->sleep); - wake_up(&runtime->tsleep); -} - -static struct action_ops snd_pcm_action_suspend = { - .pre_action = snd_pcm_pre_suspend, - .do_action = snd_pcm_do_suspend, - .post_action = snd_pcm_post_suspend -}; - -/** - * snd_pcm_suspend - trigger SUSPEND to all linked streams - * @substream: the PCM substream - * - * After this call, all streams are changed to SUSPENDED state. - */ -int snd_pcm_suspend(struct snd_pcm_substream *substream) -{ - int err; - unsigned long flags; - - if (! substream) - return 0; - - snd_pcm_stream_lock_irqsave(substream, flags); - err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0); - snd_pcm_stream_unlock_irqrestore(substream, flags); - return err; -} - -EXPORT_SYMBOL(snd_pcm_suspend); - -/** - * snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm - * @pcm: the PCM instance - * - * After this call, all streams are changed to SUSPENDED state. - */ -int snd_pcm_suspend_all(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - int stream, err = 0; - - if (! pcm) - return 0; - - for (stream = 0; stream < 2; stream++) { - for (substream = pcm->streams[stream].substream; - substream; substream = substream->next) { - /* FIXME: the open/close code should lock this as well */ - if (substream->runtime == NULL) - continue; - err = snd_pcm_suspend(substream); - if (err < 0 && err != -EBUSY) - return err; - } - } - return 0; -} - -EXPORT_SYMBOL(snd_pcm_suspend_all); - -/* resume */ - -static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (!(runtime->info & SNDRV_PCM_INFO_RESUME)) - return -ENOSYS; - runtime->trigger_master = substream; - return 0; -} - -static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->trigger_master != substream) - return 0; - /* DMA not running previously? */ - if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING && - (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING || - substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) - return 0; - return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME); -} - -static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state) -{ - if (substream->runtime->trigger_master == substream && - snd_pcm_running(substream)) - substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND); -} - -static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_trigger_tstamp(substream); - if (substream->timer) - snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME, - &runtime->trigger_tstamp); - runtime->status->state = runtime->status->suspended_state; -} - -static struct action_ops snd_pcm_action_resume = { - .pre_action = snd_pcm_pre_resume, - .do_action = snd_pcm_do_resume, - .undo_action = snd_pcm_undo_resume, - .post_action = snd_pcm_post_resume -}; - -static int snd_pcm_resume(struct snd_pcm_substream *substream) -{ - struct snd_card *card = substream->pcm->card; - int res; - - snd_power_lock(card); - if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) - res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); - snd_power_unlock(card); - return res; -} - -#else - -static int snd_pcm_resume(struct snd_pcm_substream *substream) -{ - return -ENOSYS; -} - -#endif /* CONFIG_PM */ - -/* - * xrun ioctl - * - * Change the RUNNING stream(s) to XRUN state. - */ -static int snd_pcm_xrun(struct snd_pcm_substream *substream) -{ - struct snd_card *card = substream->pcm->card; - struct snd_pcm_runtime *runtime = substream->runtime; - int result; - - snd_power_lock(card); - if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) - goto _unlock; - } - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_XRUN: - result = 0; /* already there */ - break; - case SNDRV_PCM_STATE_RUNNING: - result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - break; - default: - result = -EBADFD; - } - snd_pcm_stream_unlock_irq(substream); - _unlock: - snd_power_unlock(card); - return result; -} - -/* - * reset ioctl - */ -static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - switch (runtime->status->state) { - case SNDRV_PCM_STATE_RUNNING: - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_PAUSED: - case SNDRV_PCM_STATE_SUSPENDED: - return 0; - default: - return -EBADFD; - } -} - -static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL); - if (err < 0) - return err; - runtime->hw_ptr_base = 0; - runtime->hw_ptr_interrupt = runtime->status->hw_ptr - - runtime->status->hw_ptr % runtime->period_size; - runtime->silence_start = runtime->status->hw_ptr; - runtime->silence_filled = 0; - return 0; -} - -static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - runtime->control->appl_ptr = runtime->status->hw_ptr; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - runtime->silence_size > 0) - snd_pcm_playback_silence(substream, ULONG_MAX); -} - -static struct action_ops snd_pcm_action_reset = { - .pre_action = snd_pcm_pre_reset, - .do_action = snd_pcm_do_reset, - .post_action = snd_pcm_post_reset -}; - -static int snd_pcm_reset(struct snd_pcm_substream *substream) -{ - return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0); -} - -/* - * prepare ioctl - */ -/* we use the second argument for updating f_flags */ -static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, - int f_flags) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) - return -EBADFD; - if (snd_pcm_running(substream)) - return -EBUSY; - substream->f_flags = f_flags; - return 0; -} - -static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state) -{ - int err; - err = substream->ops->prepare(substream); - if (err < 0) - return err; - return snd_pcm_do_reset(substream, 0); -} - -static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - runtime->control->appl_ptr = runtime->status->hw_ptr; - snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); -} - -static struct action_ops snd_pcm_action_prepare = { - .pre_action = snd_pcm_pre_prepare, - .do_action = snd_pcm_do_prepare, - .post_action = snd_pcm_post_prepare -}; - -/** - * snd_pcm_prepare - prepare the PCM substream to be triggerable - * @substream: the PCM substream instance - * @file: file to refer f_flags - */ -static int snd_pcm_prepare(struct snd_pcm_substream *substream, - struct file *file) -{ - int res; - struct snd_card *card = substream->pcm->card; - int f_flags; - - if (file) - f_flags = file->f_flags; - else - f_flags = substream->f_flags; - - snd_power_lock(card); - if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) - res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, - substream, f_flags); - snd_power_unlock(card); - return res; -} - -/* - * drain ioctl - */ - -static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) -{ - substream->runtime->trigger_master = substream; - return 0; -} - -static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - /* start playback stream if possible */ - if (! snd_pcm_playback_empty(substream)) { - snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); - snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); - } - break; - case SNDRV_PCM_STATE_RUNNING: - runtime->status->state = SNDRV_PCM_STATE_DRAINING; - break; - default: - break; - } - } else { - /* stop running stream */ - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) { - int new_state = snd_pcm_capture_avail(runtime) > 0 ? - SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP; - snd_pcm_do_stop(substream, new_state); - snd_pcm_post_stop(substream, new_state); - } - } - return 0; -} - -static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state) -{ -} - -static struct action_ops snd_pcm_action_drain_init = { - .pre_action = snd_pcm_pre_drain_init, - .do_action = snd_pcm_do_drain_init, - .post_action = snd_pcm_post_drain_init -}; - -static int snd_pcm_drop(struct snd_pcm_substream *substream); - -/* - * Drain the stream(s). - * When the substream is linked, sync until the draining of all playback streams - * is finished. - * After this call, all streams are supposed to be either SETUP or DRAINING - * (capture only) state. - */ -static int snd_pcm_drain(struct snd_pcm_substream *substream, - struct file *file) -{ - struct snd_card *card; - struct snd_pcm_runtime *runtime; - struct snd_pcm_substream *s; - wait_queue_t wait; - int result = 0; - int nonblock = 0; - - card = substream->pcm->card; - runtime = substream->runtime; - - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - - snd_power_lock(card); - if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) { - snd_power_unlock(card); - return result; - } - } - - if (file) { - if (file->f_flags & O_NONBLOCK) - nonblock = 1; - } else if (substream->f_flags & O_NONBLOCK) - nonblock = 1; - - down_read(&snd_pcm_link_rwsem); - snd_pcm_stream_lock_irq(substream); - /* resume pause */ - if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) - snd_pcm_pause(substream, 0); - - /* pre-start/stop - all running streams are changed to DRAINING state */ - result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); - if (result < 0) - goto unlock; - /* in non-blocking, we don't wait in ioctl but let caller poll */ - if (nonblock) { - result = -EAGAIN; - goto unlock; - } - - for (;;) { - long tout; - struct snd_pcm_runtime *to_check; - if (signal_pending(current)) { - result = -ERESTARTSYS; - break; - } - /* find a substream to drain */ - to_check = NULL; - snd_pcm_group_for_each_entry(s, substream) { - if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) - continue; - runtime = s->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { - to_check = runtime; - break; - } - } - if (!to_check) - break; /* all drained */ - init_waitqueue_entry(&wait, current); - add_wait_queue(&to_check->sleep, &wait); - snd_pcm_stream_unlock_irq(substream); - up_read(&snd_pcm_link_rwsem); - snd_power_unlock(card); - if (runtime->no_period_wakeup) - tout = MAX_SCHEDULE_TIMEOUT; - else { - tout = 10; - if (runtime->rate) { - long t = runtime->period_size * 2 / runtime->rate; - tout = max(t, tout); - } - tout = msecs_to_jiffies(tout * 1000); - } - tout = schedule_timeout_interruptible(tout); - snd_power_lock(card); - down_read(&snd_pcm_link_rwsem); - snd_pcm_stream_lock_irq(substream); - remove_wait_queue(&to_check->sleep, &wait); - if (card->shutdown) { - result = -ENODEV; - break; - } - if (tout == 0) { - if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) - result = -ESTRPIPE; - else { - snd_printd("playback drain error (DMA or IRQ trouble?)\n"); - snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); - result = -EIO; - } - break; - } - } - - unlock: - snd_pcm_stream_unlock_irq(substream); - up_read(&snd_pcm_link_rwsem); - snd_power_unlock(card); - - return result; -} - -/* - * drop ioctl - * - * Immediately put all linked substreams into SETUP state. - */ -static int snd_pcm_drop(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime; - int result = 0; - - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) - return -EBADFD; - - snd_pcm_stream_lock_irq(substream); - /* resume pause */ - if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) - snd_pcm_pause(substream, 0); - - snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); - /* runtime->control->appl_ptr = runtime->status->hw_ptr; */ - snd_pcm_stream_unlock_irq(substream); - - return result; -} - - -/* WARNING: Don't forget to fput back the file */ -static struct file *snd_pcm_file_fd(int fd) -{ - struct file *file; - struct inode *inode; - unsigned int minor; - - file = fget(fd); - if (!file) - return NULL; - inode = file->f_path.dentry->d_inode; - if (!S_ISCHR(inode->i_mode) || - imajor(inode) != snd_major) { - fput(file); - return NULL; - } - minor = iminor(inode); - if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) && - !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) { - fput(file); - return NULL; - } - return file; -} - -/* - * PCM link handling - */ -static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) -{ - int res = 0; - struct file *file; - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream1; - struct snd_pcm_group *group; - - file = snd_pcm_file_fd(fd); - if (!file) - return -EBADFD; - pcm_file = file->private_data; - substream1 = pcm_file->substream; - group = kmalloc(sizeof(*group), GFP_KERNEL); - if (!group) { - res = -ENOMEM; - goto _nolock; - } - down_write(&snd_pcm_link_rwsem); - write_lock_irq(&snd_pcm_link_rwlock); - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || - substream->runtime->status->state != substream1->runtime->status->state) { - res = -EBADFD; - goto _end; - } - if (snd_pcm_stream_linked(substream1)) { - res = -EALREADY; - goto _end; - } - if (!snd_pcm_stream_linked(substream)) { - substream->group = group; - spin_lock_init(&substream->group->lock); - INIT_LIST_HEAD(&substream->group->substreams); - list_add_tail(&substream->link_list, &substream->group->substreams); - substream->group->count = 1; - } - list_add_tail(&substream1->link_list, &substream->group->substreams); - substream->group->count++; - substream1->group = substream->group; - _end: - write_unlock_irq(&snd_pcm_link_rwlock); - up_write(&snd_pcm_link_rwsem); - _nolock: - snd_card_unref(substream1->pcm->card); - fput(file); - if (res < 0) - kfree(group); - return res; -} - -static void relink_to_local(struct snd_pcm_substream *substream) -{ - substream->group = &substream->self_group; - INIT_LIST_HEAD(&substream->self_group.substreams); - list_add_tail(&substream->link_list, &substream->self_group.substreams); -} - -static int snd_pcm_unlink(struct snd_pcm_substream *substream) -{ - struct snd_pcm_substream *s; - int res = 0; - - down_write(&snd_pcm_link_rwsem); - write_lock_irq(&snd_pcm_link_rwlock); - if (!snd_pcm_stream_linked(substream)) { - res = -EALREADY; - goto _end; - } - list_del(&substream->link_list); - substream->group->count--; - if (substream->group->count == 1) { /* detach the last stream, too */ - snd_pcm_group_for_each_entry(s, substream) { - relink_to_local(s); - break; - } - kfree(substream->group); - } - relink_to_local(substream); - _end: - write_unlock_irq(&snd_pcm_link_rwlock); - up_write(&snd_pcm_link_rwsem); - return res; -} - -/* - * hw configurator - */ -static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval t; - snd_interval_mul(hw_param_interval_c(params, rule->deps[0]), - hw_param_interval_c(params, rule->deps[1]), &t); - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval t; - snd_interval_div(hw_param_interval_c(params, rule->deps[0]), - hw_param_interval_c(params, rule->deps[1]), &t); - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval t; - snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]), - hw_param_interval_c(params, rule->deps[1]), - (unsigned long) rule->private, &t); - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval t; - snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]), - (unsigned long) rule->private, - hw_param_interval_c(params, rule->deps[1]), &t); - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - unsigned int k; - struct snd_interval *i = hw_param_interval(params, rule->deps[0]); - struct snd_mask m; - struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - snd_mask_any(&m); - for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) { - int bits; - if (! snd_mask_test(mask, k)) - continue; - bits = snd_pcm_format_physical_width(k); - if (bits <= 0) - continue; /* ignore invalid formats */ - if ((unsigned)bits < i->min || (unsigned)bits > i->max) - snd_mask_reset(&m, k); - } - return snd_mask_refine(mask, &m); -} - -static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval t; - unsigned int k; - t.min = UINT_MAX; - t.max = 0; - t.openmin = 0; - t.openmax = 0; - for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) { - int bits; - if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k)) - continue; - bits = snd_pcm_format_physical_width(k); - if (bits <= 0) - continue; /* ignore invalid formats */ - if (t.min > (unsigned)bits) - t.min = bits; - if (t.max < (unsigned)bits) - t.max = bits; - } - t.integer = 1; - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -#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 }; - -const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, -}; - -static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pcm_hardware *hw = rule->private; - return snd_interval_list(hw_param_interval(params, rule->var), - snd_pcm_known_rates.count, - snd_pcm_known_rates.list, hw->rates); -} - -static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval t; - struct snd_pcm_substream *substream = rule->private; - t.min = 0; - t.max = substream->buffer_bytes_max; - t.openmin = 0; - t.openmax = 0; - t.integer = 1; - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; - int k, err; - - for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { - snd_mask_any(constrs_mask(constrs, k)); - } - - for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { - snd_interval_any(constrs_interval(constrs, k)); - } - - snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_CHANNELS)); - snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_SIZE)); - snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_BYTES)); - snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)); - snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_FRAME_BITS)); - - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, - snd_pcm_hw_rule_format, NULL, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - snd_pcm_hw_rule_sample_bits, NULL, - SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - snd_pcm_hw_rule_div, NULL, - SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, - snd_pcm_hw_rule_mul, NULL, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, - snd_pcm_hw_rule_mulkdiv, (void*) 8, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, - snd_pcm_hw_rule_mulkdiv, (void*) 8, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_pcm_hw_rule_div, NULL, - SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_pcm_hw_rule_mulkdiv, (void*) 1000000, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_TIME, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_pcm_hw_rule_mulkdiv, (void*) 1000000, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_BUFFER_TIME, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS, - snd_pcm_hw_rule_div, NULL, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - snd_pcm_hw_rule_div, NULL, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - snd_pcm_hw_rule_mulkdiv, (void*) 8, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - snd_pcm_hw_rule_muldivk, (void*) 1000000, - SNDRV_PCM_HW_PARAM_PERIOD_TIME, SNDRV_PCM_HW_PARAM_RATE, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - snd_pcm_hw_rule_mul, NULL, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - snd_pcm_hw_rule_mulkdiv, (void*) 8, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - snd_pcm_hw_rule_muldivk, (void*) 1000000, - SNDRV_PCM_HW_PARAM_BUFFER_TIME, SNDRV_PCM_HW_PARAM_RATE, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - snd_pcm_hw_rule_muldivk, (void*) 8, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - snd_pcm_hw_rule_muldivk, (void*) 8, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_TIME, - snd_pcm_hw_rule_mulkdiv, (void*) 1000000, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_TIME, - snd_pcm_hw_rule_mulkdiv, (void*) 1000000, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1); - if (err < 0) - return err; - return 0; -} - -int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_hardware *hw = &runtime->hw; - int err; - unsigned int mask = 0; - - if (hw->info & SNDRV_PCM_INFO_INTERLEAVED) - mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED; - if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED) - mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED; - if (hw->info & SNDRV_PCM_INFO_MMAP) { - if (hw->info & SNDRV_PCM_INFO_INTERLEAVED) - mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; - if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED) - mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED; - if (hw->info & SNDRV_PCM_INFO_COMPLEX) - mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX; - } - err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, - hw->channels_min, hw->channels_max); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, - hw->rate_min, hw->rate_max); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - hw->period_bytes_min, hw->period_bytes_max); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS, - hw->periods_min, hw->periods_max); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - hw->period_bytes_min, hw->buffer_bytes_max); - if (err < 0) - return err; - - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - snd_pcm_hw_rule_buffer_bytes_max, substream, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1); - if (err < 0) - return err; - - /* FIXME: remove */ - if (runtime->dma_bytes) { - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes); - if (err < 0) - return -EINVAL; - } - - if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) { - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_pcm_hw_rule_rate, hw, - SNDRV_PCM_HW_PARAM_RATE, -1); - if (err < 0) - return err; - } - - /* FIXME: this belong to lowlevel */ - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - - return 0; -} - -static void pcm_release_private(struct snd_pcm_substream *substream) -{ - snd_pcm_unlink(substream); -} - -void snd_pcm_release_substream(struct snd_pcm_substream *substream) -{ - substream->ref_count--; - if (substream->ref_count > 0) - return; - - snd_pcm_drop(substream); - if (substream->hw_opened) { - if (substream->ops->hw_free != NULL) - substream->ops->hw_free(substream); - substream->ops->close(substream); - substream->hw_opened = 0; - } - if (pm_qos_request_active(&substream->latency_pm_qos_req)) - pm_qos_remove_request(&substream->latency_pm_qos_req); - if (substream->pcm_release) { - substream->pcm_release(substream); - substream->pcm_release = NULL; - } - snd_pcm_detach_substream(substream); -} - -EXPORT_SYMBOL(snd_pcm_release_substream); - -int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, - struct file *file, - struct snd_pcm_substream **rsubstream) -{ - struct snd_pcm_substream *substream; - int err; - - err = snd_pcm_attach_substream(pcm, stream, file, &substream); - if (err < 0) - return err; - if (substream->ref_count > 1) { - *rsubstream = substream; - return 0; - } - - err = snd_pcm_hw_constraints_init(substream); - if (err < 0) { - snd_printd("snd_pcm_hw_constraints_init failed\n"); - goto error; - } - - if ((err = substream->ops->open(substream)) < 0) - goto error; - - substream->hw_opened = 1; - - err = snd_pcm_hw_constraints_complete(substream); - if (err < 0) { - snd_printd("snd_pcm_hw_constraints_complete failed\n"); - goto error; - } - - *rsubstream = substream; - return 0; - - error: - snd_pcm_release_substream(substream); - return err; -} - -EXPORT_SYMBOL(snd_pcm_open_substream); - -static int snd_pcm_open_file(struct file *file, - struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream; - int err; - - err = snd_pcm_open_substream(pcm, stream, file, &substream); - if (err < 0) - return err; - - pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); - if (pcm_file == NULL) { - snd_pcm_release_substream(substream); - return -ENOMEM; - } - pcm_file->substream = substream; - if (substream->ref_count == 1) { - substream->file = pcm_file; - substream->pcm_release = pcm_release_private; - } - file->private_data = pcm_file; - - return 0; -} - -static int snd_pcm_playback_open(struct inode *inode, struct file *file) -{ - struct snd_pcm *pcm; - int err = nonseekable_open(inode, file); - if (err < 0) - return err; - pcm = snd_lookup_minor_data(iminor(inode), - SNDRV_DEVICE_TYPE_PCM_PLAYBACK); - err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); - if (pcm) - snd_card_unref(pcm->card); - return err; -} - -static int snd_pcm_capture_open(struct inode *inode, struct file *file) -{ - struct snd_pcm *pcm; - int err = nonseekable_open(inode, file); - if (err < 0) - return err; - pcm = snd_lookup_minor_data(iminor(inode), - SNDRV_DEVICE_TYPE_PCM_CAPTURE); - err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); - if (pcm) - snd_card_unref(pcm->card); - return err; -} - -static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) -{ - int err; - wait_queue_t wait; - - if (pcm == NULL) { - err = -ENODEV; - goto __error1; - } - err = snd_card_file_add(pcm->card, file); - if (err < 0) - goto __error1; - if (!try_module_get(pcm->card->module)) { - err = -EFAULT; - goto __error2; - } - init_waitqueue_entry(&wait, current); - add_wait_queue(&pcm->open_wait, &wait); - mutex_lock(&pcm->open_mutex); - while (1) { - err = snd_pcm_open_file(file, pcm, stream); - if (err >= 0) - break; - if (err == -EAGAIN) { - if (file->f_flags & O_NONBLOCK) { - err = -EBUSY; - break; - } - } else - break; - set_current_state(TASK_INTERRUPTIBLE); - mutex_unlock(&pcm->open_mutex); - schedule(); - mutex_lock(&pcm->open_mutex); - if (pcm->card->shutdown) { - err = -ENODEV; - break; - } - if (signal_pending(current)) { - err = -ERESTARTSYS; - break; - } - } - remove_wait_queue(&pcm->open_wait, &wait); - mutex_unlock(&pcm->open_mutex); - if (err < 0) - goto __error; - return err; - - __error: - module_put(pcm->card->module); - __error2: - snd_card_file_remove(pcm->card, file); - __error1: - return err; -} - -static int snd_pcm_release(struct inode *inode, struct file *file) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - struct snd_pcm_file *pcm_file; - - pcm_file = file->private_data; - substream = pcm_file->substream; - if (snd_BUG_ON(!substream)) - return -ENXIO; - pcm = substream->pcm; - mutex_lock(&pcm->open_mutex); - snd_pcm_release_substream(substream); - kfree(pcm_file); - mutex_unlock(&pcm->open_mutex); - wake_up(&pcm->open_wait); - module_put(pcm->card->module); - snd_card_file_remove(pcm->card, file); - return 0; -} - -static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t appl_ptr; - snd_pcm_sframes_t ret; - snd_pcm_sframes_t hw_avail; - - if (frames == 0) - return 0; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - break; - case SNDRV_PCM_STATE_DRAINING: - case SNDRV_PCM_STATE_RUNNING: - if (snd_pcm_update_hw_ptr(substream) >= 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_XRUN: - ret = -EPIPE; - goto __end; - case SNDRV_PCM_STATE_SUSPENDED: - ret = -ESTRPIPE; - goto __end; - default: - ret = -EBADFD; - goto __end; - } - - hw_avail = snd_pcm_playback_hw_avail(runtime); - if (hw_avail <= 0) { - ret = 0; - goto __end; - } - if (frames > (snd_pcm_uframes_t)hw_avail) - frames = hw_avail; - appl_ptr = runtime->control->appl_ptr - frames; - if (appl_ptr < 0) - appl_ptr += runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - ret = frames; - __end: - snd_pcm_stream_unlock_irq(substream); - return ret; -} - -static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t appl_ptr; - snd_pcm_sframes_t ret; - snd_pcm_sframes_t hw_avail; - - if (frames == 0) - return 0; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_DRAINING: - break; - case SNDRV_PCM_STATE_RUNNING: - if (snd_pcm_update_hw_ptr(substream) >= 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_XRUN: - ret = -EPIPE; - goto __end; - case SNDRV_PCM_STATE_SUSPENDED: - ret = -ESTRPIPE; - goto __end; - default: - ret = -EBADFD; - goto __end; - } - - hw_avail = snd_pcm_capture_hw_avail(runtime); - if (hw_avail <= 0) { - ret = 0; - goto __end; - } - if (frames > (snd_pcm_uframes_t)hw_avail) - frames = hw_avail; - appl_ptr = runtime->control->appl_ptr - frames; - if (appl_ptr < 0) - appl_ptr += runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - ret = frames; - __end: - snd_pcm_stream_unlock_irq(substream); - return ret; -} - -static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t appl_ptr; - snd_pcm_sframes_t ret; - snd_pcm_sframes_t avail; - - if (frames == 0) - return 0; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_PAUSED: - break; - case SNDRV_PCM_STATE_DRAINING: - case SNDRV_PCM_STATE_RUNNING: - if (snd_pcm_update_hw_ptr(substream) >= 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_XRUN: - ret = -EPIPE; - goto __end; - case SNDRV_PCM_STATE_SUSPENDED: - ret = -ESTRPIPE; - goto __end; - default: - ret = -EBADFD; - goto __end; - } - - avail = snd_pcm_playback_avail(runtime); - if (avail <= 0) { - ret = 0; - goto __end; - } - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - appl_ptr = runtime->control->appl_ptr + frames; - if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) - appl_ptr -= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - ret = frames; - __end: - snd_pcm_stream_unlock_irq(substream); - return ret; -} - -static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t appl_ptr; - snd_pcm_sframes_t ret; - snd_pcm_sframes_t avail; - - if (frames == 0) - return 0; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_DRAINING: - case SNDRV_PCM_STATE_PAUSED: - break; - case SNDRV_PCM_STATE_RUNNING: - if (snd_pcm_update_hw_ptr(substream) >= 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_XRUN: - ret = -EPIPE; - goto __end; - case SNDRV_PCM_STATE_SUSPENDED: - ret = -ESTRPIPE; - goto __end; - default: - ret = -EBADFD; - goto __end; - } - - avail = snd_pcm_capture_avail(runtime); - if (avail <= 0) { - ret = 0; - goto __end; - } - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - appl_ptr = runtime->control->appl_ptr + frames; - if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) - appl_ptr -= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - ret = frames; - __end: - snd_pcm_stream_unlock_irq(substream); - return ret; -} - -static int snd_pcm_hwsync(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_DRAINING: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - goto __badfd; - case SNDRV_PCM_STATE_RUNNING: - if ((err = snd_pcm_update_hw_ptr(substream)) < 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_SUSPENDED: - err = 0; - break; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - break; - default: - __badfd: - err = -EBADFD; - break; - } - snd_pcm_stream_unlock_irq(substream); - return err; -} - -static int snd_pcm_delay(struct snd_pcm_substream *substream, - snd_pcm_sframes_t __user *res) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - snd_pcm_sframes_t n = 0; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_DRAINING: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - goto __badfd; - case SNDRV_PCM_STATE_RUNNING: - if ((err = snd_pcm_update_hw_ptr(substream)) < 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_SUSPENDED: - err = 0; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - n = snd_pcm_playback_hw_avail(runtime); - else - n = snd_pcm_capture_avail(runtime); - n += runtime->delay; - break; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - break; - default: - __badfd: - err = -EBADFD; - break; - } - snd_pcm_stream_unlock_irq(substream); - if (!err) - if (put_user(n, res)) - err = -EFAULT; - return err; -} - -static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, - struct snd_pcm_sync_ptr __user *_sync_ptr) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_sync_ptr sync_ptr; - volatile struct snd_pcm_mmap_status *status; - volatile struct snd_pcm_mmap_control *control; - int err; - - memset(&sync_ptr, 0, sizeof(sync_ptr)); - if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags))) - return -EFAULT; - if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control))) - return -EFAULT; - status = runtime->status; - control = runtime->control; - if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) { - err = snd_pcm_hwsync(substream); - if (err < 0) - return err; - } - snd_pcm_stream_lock_irq(substream); - if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) - control->appl_ptr = sync_ptr.c.control.appl_ptr; - else - sync_ptr.c.control.appl_ptr = control->appl_ptr; - if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) - control->avail_min = sync_ptr.c.control.avail_min; - else - sync_ptr.c.control.avail_min = control->avail_min; - sync_ptr.s.status.state = status->state; - sync_ptr.s.status.hw_ptr = status->hw_ptr; - sync_ptr.s.status.tstamp = status->tstamp; - sync_ptr.s.status.suspended_state = status->suspended_state; - snd_pcm_stream_unlock_irq(substream); - if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr))) - return -EFAULT; - return 0; -} - -static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int arg; - - if (get_user(arg, _arg)) - return -EFAULT; - if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST) - return -EINVAL; - runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY; - if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC) - runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC; - return 0; -} - -static int snd_pcm_common_ioctl1(struct file *file, - struct snd_pcm_substream *substream, - unsigned int cmd, void __user *arg) -{ - switch (cmd) { - case SNDRV_PCM_IOCTL_PVERSION: - return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; - case SNDRV_PCM_IOCTL_INFO: - return snd_pcm_info_user(substream, arg); - case SNDRV_PCM_IOCTL_TSTAMP: /* just for compatibility */ - return 0; - case SNDRV_PCM_IOCTL_TTSTAMP: - return snd_pcm_tstamp(substream, arg); - case SNDRV_PCM_IOCTL_HW_REFINE: - return snd_pcm_hw_refine_user(substream, arg); - case SNDRV_PCM_IOCTL_HW_PARAMS: - return snd_pcm_hw_params_user(substream, arg); - case SNDRV_PCM_IOCTL_HW_FREE: - return snd_pcm_hw_free(substream); - case SNDRV_PCM_IOCTL_SW_PARAMS: - return snd_pcm_sw_params_user(substream, arg); - case SNDRV_PCM_IOCTL_STATUS: - return snd_pcm_status_user(substream, arg); - case SNDRV_PCM_IOCTL_CHANNEL_INFO: - return snd_pcm_channel_info_user(substream, arg); - case SNDRV_PCM_IOCTL_PREPARE: - return snd_pcm_prepare(substream, file); - case SNDRV_PCM_IOCTL_RESET: - return snd_pcm_reset(substream); - case SNDRV_PCM_IOCTL_START: - return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING); - case SNDRV_PCM_IOCTL_LINK: - return snd_pcm_link(substream, (int)(unsigned long) arg); - case SNDRV_PCM_IOCTL_UNLINK: - return snd_pcm_unlink(substream); - case SNDRV_PCM_IOCTL_RESUME: - return snd_pcm_resume(substream); - case SNDRV_PCM_IOCTL_XRUN: - return snd_pcm_xrun(substream); - case SNDRV_PCM_IOCTL_HWSYNC: - return snd_pcm_hwsync(substream); - case SNDRV_PCM_IOCTL_DELAY: - return snd_pcm_delay(substream, arg); - case SNDRV_PCM_IOCTL_SYNC_PTR: - return snd_pcm_sync_ptr(substream, arg); -#ifdef CONFIG_SND_SUPPORT_OLD_API - case SNDRV_PCM_IOCTL_HW_REFINE_OLD: - return snd_pcm_hw_refine_old_user(substream, arg); - case SNDRV_PCM_IOCTL_HW_PARAMS_OLD: - return snd_pcm_hw_params_old_user(substream, arg); -#endif - case SNDRV_PCM_IOCTL_DRAIN: - return snd_pcm_drain(substream, file); - case SNDRV_PCM_IOCTL_DROP: - return snd_pcm_drop(substream); - case SNDRV_PCM_IOCTL_PAUSE: - { - int res; - snd_pcm_stream_lock_irq(substream); - res = snd_pcm_pause(substream, (int)(unsigned long)arg); - snd_pcm_stream_unlock_irq(substream); - return res; - } - } - snd_printd("unknown ioctl = 0x%x\n", cmd); - return -ENOTTY; -} - -static int snd_pcm_playback_ioctl1(struct file *file, - struct snd_pcm_substream *substream, - unsigned int cmd, void __user *arg) -{ - if (snd_BUG_ON(!substream)) - return -ENXIO; - if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) - return -EINVAL; - switch (cmd) { - case SNDRV_PCM_IOCTL_WRITEI_FRAMES: - { - struct snd_xferi xferi; - struct snd_xferi __user *_xferi = arg; - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t result; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (put_user(0, &_xferi->result)) - return -EFAULT; - if (copy_from_user(&xferi, _xferi, sizeof(xferi))) - return -EFAULT; - result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames); - __put_user(result, &_xferi->result); - return result < 0 ? result : 0; - } - case SNDRV_PCM_IOCTL_WRITEN_FRAMES: - { - struct snd_xfern xfern; - struct snd_xfern __user *_xfern = arg; - struct snd_pcm_runtime *runtime = substream->runtime; - void __user **bufs; - snd_pcm_sframes_t result; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (runtime->channels > 128) - return -EINVAL; - if (put_user(0, &_xfern->result)) - return -EFAULT; - if (copy_from_user(&xfern, _xfern, sizeof(xfern))) - 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); - return result < 0 ? result : 0; - } - case SNDRV_PCM_IOCTL_REWIND: - { - snd_pcm_uframes_t frames; - snd_pcm_uframes_t __user *_frames = arg; - snd_pcm_sframes_t result; - if (get_user(frames, _frames)) - return -EFAULT; - if (put_user(0, _frames)) - return -EFAULT; - result = snd_pcm_playback_rewind(substream, frames); - __put_user(result, _frames); - return result < 0 ? result : 0; - } - case SNDRV_PCM_IOCTL_FORWARD: - { - snd_pcm_uframes_t frames; - snd_pcm_uframes_t __user *_frames = arg; - snd_pcm_sframes_t result; - if (get_user(frames, _frames)) - return -EFAULT; - if (put_user(0, _frames)) - return -EFAULT; - result = snd_pcm_playback_forward(substream, frames); - __put_user(result, _frames); - return result < 0 ? result : 0; - } - } - return snd_pcm_common_ioctl1(file, substream, cmd, arg); -} - -static int snd_pcm_capture_ioctl1(struct file *file, - struct snd_pcm_substream *substream, - unsigned int cmd, void __user *arg) -{ - if (snd_BUG_ON(!substream)) - return -ENXIO; - if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE)) - return -EINVAL; - switch (cmd) { - case SNDRV_PCM_IOCTL_READI_FRAMES: - { - struct snd_xferi xferi; - struct snd_xferi __user *_xferi = arg; - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t result; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (put_user(0, &_xferi->result)) - return -EFAULT; - if (copy_from_user(&xferi, _xferi, sizeof(xferi))) - return -EFAULT; - result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames); - __put_user(result, &_xferi->result); - return result < 0 ? result : 0; - } - case SNDRV_PCM_IOCTL_READN_FRAMES: - { - struct snd_xfern xfern; - struct snd_xfern __user *_xfern = arg; - struct snd_pcm_runtime *runtime = substream->runtime; - void *bufs; - snd_pcm_sframes_t result; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (runtime->channels > 128) - return -EINVAL; - if (put_user(0, &_xfern->result)) - return -EFAULT; - if (copy_from_user(&xfern, _xfern, sizeof(xfern))) - 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); - return result < 0 ? result : 0; - } - case SNDRV_PCM_IOCTL_REWIND: - { - snd_pcm_uframes_t frames; - snd_pcm_uframes_t __user *_frames = arg; - snd_pcm_sframes_t result; - if (get_user(frames, _frames)) - return -EFAULT; - if (put_user(0, _frames)) - return -EFAULT; - result = snd_pcm_capture_rewind(substream, frames); - __put_user(result, _frames); - return result < 0 ? result : 0; - } - case SNDRV_PCM_IOCTL_FORWARD: - { - snd_pcm_uframes_t frames; - snd_pcm_uframes_t __user *_frames = arg; - snd_pcm_sframes_t result; - if (get_user(frames, _frames)) - return -EFAULT; - if (put_user(0, _frames)) - return -EFAULT; - result = snd_pcm_capture_forward(substream, frames); - __put_user(result, _frames); - return result < 0 ? result : 0; - } - } - return snd_pcm_common_ioctl1(file, substream, cmd, arg); -} - -static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct snd_pcm_file *pcm_file; - - pcm_file = file->private_data; - - if (((cmd >> 8) & 0xff) != 'A') - return -ENOTTY; - - return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd, - (void __user *)arg); -} - -static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct snd_pcm_file *pcm_file; - - pcm_file = file->private_data; - - if (((cmd >> 8) & 0xff) != 'A') - return -ENOTTY; - - return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd, - (void __user *)arg); -} - -int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - mm_segment_t fs; - int result; - - fs = snd_enter_user(); - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - result = snd_pcm_playback_ioctl1(NULL, substream, cmd, - (void __user *)arg); - break; - case SNDRV_PCM_STREAM_CAPTURE: - result = snd_pcm_capture_ioctl1(NULL, substream, cmd, - (void __user *)arg); - break; - default: - result = -EINVAL; - break; - } - snd_leave_user(fs); - return result; -} - -EXPORT_SYMBOL(snd_pcm_kernel_ioctl); - -static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, - loff_t * offset) -{ - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - snd_pcm_sframes_t result; - - pcm_file = file->private_data; - substream = pcm_file->substream; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (!frame_aligned(runtime, count)) - return -EINVAL; - count = bytes_to_frames(runtime, count); - result = snd_pcm_lib_read(substream, buf, count); - if (result > 0) - result = frames_to_bytes(runtime, result); - return result; -} - -static ssize_t snd_pcm_write(struct file *file, const char __user *buf, - size_t count, loff_t * offset) -{ - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - snd_pcm_sframes_t result; - - pcm_file = file->private_data; - substream = pcm_file->substream; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (!frame_aligned(runtime, count)) - return -EINVAL; - count = bytes_to_frames(runtime, count); - result = snd_pcm_lib_write(substream, buf, count); - if (result > 0) - result = frames_to_bytes(runtime, result); - return result; -} - -static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) - -{ - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - snd_pcm_sframes_t result; - unsigned long i; - void __user **bufs; - snd_pcm_uframes_t frames; - - pcm_file = iocb->ki_filp->private_data; - substream = pcm_file->substream; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (nr_segs > 1024 || nr_segs != runtime->channels) - return -EINVAL; - if (!frame_aligned(runtime, iov->iov_len)) - return -EINVAL; - frames = bytes_to_samples(runtime, iov->iov_len); - bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL); - if (bufs == NULL) - return -ENOMEM; - for (i = 0; i < nr_segs; ++i) - bufs[i] = iov[i].iov_base; - result = snd_pcm_lib_readv(substream, bufs, frames); - if (result > 0) - result = frames_to_bytes(runtime, result); - kfree(bufs); - return result; -} - -static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - snd_pcm_sframes_t result; - unsigned long i; - void __user **bufs; - snd_pcm_uframes_t frames; - - pcm_file = iocb->ki_filp->private_data; - substream = pcm_file->substream; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (nr_segs > 128 || nr_segs != runtime->channels || - !frame_aligned(runtime, iov->iov_len)) - return -EINVAL; - frames = bytes_to_samples(runtime, iov->iov_len); - bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL); - if (bufs == NULL) - return -ENOMEM; - for (i = 0; i < nr_segs; ++i) - bufs[i] = iov[i].iov_base; - result = snd_pcm_lib_writev(substream, bufs, frames); - if (result > 0) - result = frames_to_bytes(runtime, result); - kfree(bufs); - return result; -} - -static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait) -{ - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - unsigned int mask; - snd_pcm_uframes_t avail; - - pcm_file = file->private_data; - - substream = pcm_file->substream; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - - poll_wait(file, &runtime->sleep, wait); - - snd_pcm_stream_lock_irq(substream); - avail = snd_pcm_playback_avail(runtime); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_RUNNING: - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_PAUSED: - if (avail >= runtime->control->avail_min) { - mask = POLLOUT | POLLWRNORM; - break; - } - /* Fall through */ - case SNDRV_PCM_STATE_DRAINING: - mask = 0; - break; - default: - mask = POLLOUT | POLLWRNORM | POLLERR; - break; - } - snd_pcm_stream_unlock_irq(substream); - return mask; -} - -static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait) -{ - struct snd_pcm_file *pcm_file; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - unsigned int mask; - snd_pcm_uframes_t avail; - - pcm_file = file->private_data; - - substream = pcm_file->substream; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - - poll_wait(file, &runtime->sleep, wait); - - snd_pcm_stream_lock_irq(substream); - avail = snd_pcm_capture_avail(runtime); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_RUNNING: - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_PAUSED: - if (avail >= runtime->control->avail_min) { - mask = POLLIN | POLLRDNORM; - break; - } - mask = 0; - break; - case SNDRV_PCM_STATE_DRAINING: - if (avail > 0) { - mask = POLLIN | POLLRDNORM; - break; - } - /* Fall through */ - default: - mask = POLLIN | POLLRDNORM | POLLERR; - break; - } - snd_pcm_stream_unlock_irq(substream); - return mask; -} - -/* - * mmap support - */ - -/* - * Only on coherent architectures, we can mmap the status and the control records - * for effcient data transfer. On others, we have to use HWSYNC ioctl... - */ -#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA) -/* - * mmap status record - */ -static int snd_pcm_mmap_status_fault(struct vm_area_struct *area, - struct vm_fault *vmf) -{ - struct snd_pcm_substream *substream = area->vm_private_data; - struct snd_pcm_runtime *runtime; - - if (substream == NULL) - return VM_FAULT_SIGBUS; - runtime = substream->runtime; - vmf->page = virt_to_page(runtime->status); - get_page(vmf->page); - return 0; -} - -static const struct vm_operations_struct snd_pcm_vm_ops_status = -{ - .fault = snd_pcm_mmap_status_fault, -}; - -static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, - struct vm_area_struct *area) -{ - long size; - if (!(area->vm_flags & VM_READ)) - return -EINVAL; - size = area->vm_end - area->vm_start; - if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status))) - return -EINVAL; - area->vm_ops = &snd_pcm_vm_ops_status; - area->vm_private_data = substream; - area->vm_flags |= VM_RESERVED; - return 0; -} - -/* - * mmap control record - */ -static int snd_pcm_mmap_control_fault(struct vm_area_struct *area, - struct vm_fault *vmf) -{ - struct snd_pcm_substream *substream = area->vm_private_data; - struct snd_pcm_runtime *runtime; - - if (substream == NULL) - return VM_FAULT_SIGBUS; - runtime = substream->runtime; - vmf->page = virt_to_page(runtime->control); - get_page(vmf->page); - return 0; -} - -static const struct vm_operations_struct snd_pcm_vm_ops_control = -{ - .fault = snd_pcm_mmap_control_fault, -}; - -static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, - struct vm_area_struct *area) -{ - long size; - if (!(area->vm_flags & VM_READ)) - return -EINVAL; - size = area->vm_end - area->vm_start; - if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control))) - return -EINVAL; - area->vm_ops = &snd_pcm_vm_ops_control; - area->vm_private_data = substream; - area->vm_flags |= VM_RESERVED; - return 0; -} -#else /* ! coherent mmap */ -/* - * don't support mmap for status and control records. - */ -static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, - struct vm_area_struct *area) -{ - return -ENXIO; -} -static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, - struct vm_area_struct *area) -{ - return -ENXIO; -} -#endif /* coherent mmap */ - -static inline struct page * -snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) -{ - void *vaddr = substream->runtime->dma_area + ofs; -#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT) - if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) - return virt_to_page(CAC_ADDR(vaddr)); -#endif -#if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE) - if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) { - dma_addr_t addr = substream->runtime->dma_addr + ofs; - addr -= get_dma_offset(substream->dma_buffer.dev.dev); - /* assume dma_handle set via pfn_to_phys() in - * mm/dma-noncoherent.c - */ - return pfn_to_page(addr >> PAGE_SHIFT); - } -#endif - return virt_to_page(vaddr); -} - -/* - * fault callback for mmapping a RAM page - */ -static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, - struct vm_fault *vmf) -{ - struct snd_pcm_substream *substream = area->vm_private_data; - struct snd_pcm_runtime *runtime; - unsigned long offset; - struct page * page; - size_t dma_bytes; - - if (substream == NULL) - return VM_FAULT_SIGBUS; - runtime = substream->runtime; - offset = vmf->pgoff << PAGE_SHIFT; - dma_bytes = PAGE_ALIGN(runtime->dma_bytes); - if (offset > dma_bytes - PAGE_SIZE) - return VM_FAULT_SIGBUS; - if (substream->ops->page) - page = substream->ops->page(substream, offset); - else - page = snd_pcm_default_page_ops(substream, offset); - if (!page) - return VM_FAULT_SIGBUS; - get_page(page); - vmf->page = page; - return 0; -} - -static const struct vm_operations_struct snd_pcm_vm_ops_data = { - .open = snd_pcm_mmap_data_open, - .close = snd_pcm_mmap_data_close, -}; - -static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = { - .open = snd_pcm_mmap_data_open, - .close = snd_pcm_mmap_data_close, - .fault = snd_pcm_mmap_data_fault, -}; - -#ifndef ARCH_HAS_DMA_MMAP_COHERENT -/* This should be defined / handled globally! */ -#ifdef CONFIG_ARM -#define ARCH_HAS_DMA_MMAP_COHERENT -#endif -#endif - -/* - * mmap the DMA buffer on RAM - */ -int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *area) -{ - area->vm_flags |= VM_RESERVED; -#ifdef ARCH_HAS_DMA_MMAP_COHERENT - if (!substream->ops->page && - substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) - return dma_mmap_coherent(substream->dma_buffer.dev.dev, - area, - substream->runtime->dma_area, - substream->runtime->dma_addr, - area->vm_end - area->vm_start); -#elif defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT) - if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV && - !plat_device_is_coherent(substream->dma_buffer.dev.dev)) - area->vm_page_prot = pgprot_noncached(area->vm_page_prot); -#endif /* ARCH_HAS_DMA_MMAP_COHERENT */ - /* mmap with fault handler */ - area->vm_ops = &snd_pcm_vm_ops_data_fault; - return 0; -} -EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap); - -/* - * mmap the DMA buffer on I/O memory area - */ -#if SNDRV_PCM_INFO_MMAP_IOMEM -int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, - struct vm_area_struct *area) -{ - long size; - unsigned long offset; - - area->vm_page_prot = pgprot_noncached(area->vm_page_prot); - area->vm_flags |= VM_IO; - size = area->vm_end - area->vm_start; - offset = area->vm_pgoff << PAGE_SHIFT; - if (io_remap_pfn_range(area, area->vm_start, - (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, - size, area->vm_page_prot)) - return -EAGAIN; - return 0; -} - -EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); -#endif /* SNDRV_PCM_INFO_MMAP */ - -/* - * mmap DMA buffer - */ -int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, - struct vm_area_struct *area) -{ - struct snd_pcm_runtime *runtime; - long size; - unsigned long offset; - size_t dma_bytes; - int err; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (!(area->vm_flags & (VM_WRITE|VM_READ))) - return -EINVAL; - } else { - if (!(area->vm_flags & VM_READ)) - return -EINVAL; - } - runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) - return -ENXIO; - if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || - runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) - return -EINVAL; - size = area->vm_end - area->vm_start; - offset = area->vm_pgoff << PAGE_SHIFT; - dma_bytes = PAGE_ALIGN(runtime->dma_bytes); - if ((size_t)size > dma_bytes) - return -EINVAL; - if (offset > dma_bytes - size) - return -EINVAL; - - area->vm_ops = &snd_pcm_vm_ops_data; - area->vm_private_data = substream; - if (substream->ops->mmap) - err = substream->ops->mmap(substream, area); - else - err = snd_pcm_lib_default_mmap(substream, area); - if (!err) - atomic_inc(&substream->mmap_count); - return err; -} - -EXPORT_SYMBOL(snd_pcm_mmap_data); - -static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) -{ - struct snd_pcm_file * pcm_file; - struct snd_pcm_substream *substream; - unsigned long offset; - - pcm_file = file->private_data; - substream = pcm_file->substream; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - - offset = area->vm_pgoff << PAGE_SHIFT; - switch (offset) { - case SNDRV_PCM_MMAP_OFFSET_STATUS: - if (pcm_file->no_compat_mmap) - return -ENXIO; - return snd_pcm_mmap_status(substream, file, area); - case SNDRV_PCM_MMAP_OFFSET_CONTROL: - if (pcm_file->no_compat_mmap) - return -ENXIO; - return snd_pcm_mmap_control(substream, file, area); - default: - return snd_pcm_mmap_data(substream, file, area); - } - return 0; -} - -static int snd_pcm_fasync(int fd, struct file * file, int on) -{ - struct snd_pcm_file * pcm_file; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - - pcm_file = file->private_data; - substream = pcm_file->substream; - if (PCM_RUNTIME_CHECK(substream)) - return -ENXIO; - runtime = substream->runtime; - return fasync_helper(fd, file, on, &runtime->fasync); -} - -/* - * ioctl32 compat - */ -#ifdef CONFIG_COMPAT -#include "pcm_compat.c" -#else -#define snd_pcm_ioctl_compat NULL -#endif - -/* - * To be removed helpers to keep binary compatibility - */ - -#ifdef CONFIG_SND_SUPPORT_OLD_API -#define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5)) -#define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5)) - -static void snd_pcm_hw_convert_from_old_params(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_params_old *oparams) -{ - unsigned int i; - - memset(params, 0, sizeof(*params)); - params->flags = oparams->flags; - for (i = 0; i < ARRAY_SIZE(oparams->masks); i++) - params->masks[i].bits[0] = oparams->masks[i]; - memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals)); - params->rmask = __OLD_TO_NEW_MASK(oparams->rmask); - params->cmask = __OLD_TO_NEW_MASK(oparams->cmask); - params->info = oparams->info; - params->msbits = oparams->msbits; - params->rate_num = oparams->rate_num; - params->rate_den = oparams->rate_den; - params->fifo_size = oparams->fifo_size; -} - -static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *oparams, - struct snd_pcm_hw_params *params) -{ - unsigned int i; - - memset(oparams, 0, sizeof(*oparams)); - oparams->flags = params->flags; - for (i = 0; i < ARRAY_SIZE(oparams->masks); i++) - oparams->masks[i] = params->masks[i].bits[0]; - memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals)); - oparams->rmask = __NEW_TO_OLD_MASK(params->rmask); - oparams->cmask = __NEW_TO_OLD_MASK(params->cmask); - oparams->info = params->info; - oparams->msbits = params->msbits; - oparams->rate_num = params->rate_num; - oparams->rate_den = params->rate_den; - oparams->fifo_size = params->fifo_size; -} - -static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params_old __user * _oparams) -{ - struct snd_pcm_hw_params *params; - struct snd_pcm_hw_params_old *oparams = NULL; - int err; - - params = kmalloc(sizeof(*params), GFP_KERNEL); - 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); - err = snd_pcm_hw_refine(substream, params); - snd_pcm_hw_convert_to_old_params(oparams, params); - if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { - if (!err) - err = -EFAULT; - } - - kfree(oparams); -out: - kfree(params); - return err; -} - -static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params_old __user * _oparams) -{ - struct snd_pcm_hw_params *params; - struct snd_pcm_hw_params_old *oparams = NULL; - int err; - - params = kmalloc(sizeof(*params), GFP_KERNEL); - 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); - err = snd_pcm_hw_params(substream, params); - snd_pcm_hw_convert_to_old_params(oparams, params); - if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { - if (!err) - err = -EFAULT; - } - - kfree(oparams); -out: - kfree(params); - return err; -} -#endif /* CONFIG_SND_SUPPORT_OLD_API */ - -#ifndef CONFIG_MMU -static unsigned long snd_pcm_get_unmapped_area(struct file *file, - unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags) -{ - struct snd_pcm_file *pcm_file = file->private_data; - struct snd_pcm_substream *substream = pcm_file->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long offset = pgoff << PAGE_SHIFT; - - switch (offset) { - case SNDRV_PCM_MMAP_OFFSET_STATUS: - return (unsigned long)runtime->status; - case SNDRV_PCM_MMAP_OFFSET_CONTROL: - return (unsigned long)runtime->control; - default: - return (unsigned long)runtime->dma_area + offset; - } -} -#else -# define snd_pcm_get_unmapped_area NULL -#endif - -/* - * Register section - */ - -const struct file_operations snd_pcm_f_ops[2] = { - { - .owner = THIS_MODULE, - .write = snd_pcm_write, - .aio_write = snd_pcm_aio_write, - .open = snd_pcm_playback_open, - .release = snd_pcm_release, - .llseek = no_llseek, - .poll = snd_pcm_playback_poll, - .unlocked_ioctl = snd_pcm_playback_ioctl, - .compat_ioctl = snd_pcm_ioctl_compat, - .mmap = snd_pcm_mmap, - .fasync = snd_pcm_fasync, - .get_unmapped_area = snd_pcm_get_unmapped_area, - }, - { - .owner = THIS_MODULE, - .read = snd_pcm_read, - .aio_read = snd_pcm_aio_read, - .open = snd_pcm_capture_open, - .release = snd_pcm_release, - .llseek = no_llseek, - .poll = snd_pcm_capture_poll, - .unlocked_ioctl = snd_pcm_capture_ioctl, - .compat_ioctl = snd_pcm_ioctl_compat, - .mmap = snd_pcm_mmap, - .fasync = snd_pcm_fasync, - .get_unmapped_area = snd_pcm_get_unmapped_area, - } -}; diff --git a/ANDROID_3.4.5/sound/core/pcm_timer.c b/ANDROID_3.4.5/sound/core/pcm_timer.c deleted file mode 100644 index b01d9481..00000000 --- a/ANDROID_3.4.5/sound/core/pcm_timer.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Digital Audio (PCM) abstract layer - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -/* - * Timer functions - */ - -void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) -{ - unsigned long rate, mult, fsize, l, post; - struct snd_pcm_runtime *runtime = substream->runtime; - - mult = 1000000000; - rate = runtime->rate; - if (snd_BUG_ON(!rate)) - return; - l = gcd(mult, rate); - mult /= l; - rate /= l; - fsize = runtime->period_size; - if (snd_BUG_ON(!fsize)) - return; - l = gcd(rate, fsize); - rate /= l; - fsize /= l; - post = 1; - while ((mult * fsize) / fsize != mult) { - mult /= 2; - post *= 2; - } - if (rate == 0) { - snd_printk(KERN_ERR "pcm timer resolution out of range (rate = %u, period_size = %lu)\n", runtime->rate, runtime->period_size); - runtime->timer_resolution = -1; - return; - } - runtime->timer_resolution = (mult * fsize / rate) * post; -} - -static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) -{ - struct snd_pcm_substream *substream; - - substream = timer->private_data; - return substream->runtime ? substream->runtime->timer_resolution : 0; -} - -static int snd_pcm_timer_start(struct snd_timer * timer) -{ - struct snd_pcm_substream *substream; - - substream = snd_timer_chip(timer); - substream->timer_running = 1; - return 0; -} - -static int snd_pcm_timer_stop(struct snd_timer * timer) -{ - struct snd_pcm_substream *substream; - - substream = snd_timer_chip(timer); - substream->timer_running = 0; - return 0; -} - -static struct snd_timer_hardware snd_pcm_timer = -{ - .flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_SLAVE, - .resolution = 0, - .ticks = 1, - .c_resolution = snd_pcm_timer_resolution, - .start = snd_pcm_timer_start, - .stop = snd_pcm_timer_stop, -}; - -/* - * Init functions - */ - -static void snd_pcm_timer_free(struct snd_timer *timer) -{ - struct snd_pcm_substream *substream = timer->private_data; - substream->timer = NULL; -} - -void snd_pcm_timer_init(struct snd_pcm_substream *substream) -{ - struct snd_timer_id tid; - struct snd_timer *timer; - - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.dev_class = SNDRV_TIMER_CLASS_PCM; - tid.card = substream->pcm->card->number; - tid.device = substream->pcm->device; - tid.subdevice = (substream->number << 1) | (substream->stream & 1); - if (snd_timer_new(substream->pcm->card, "PCM", &tid, &timer) < 0) - return; - sprintf(timer->name, "PCM %s %i-%i-%i", - substream->stream == SNDRV_PCM_STREAM_CAPTURE ? - "capture" : "playback", - tid.card, tid.device, tid.subdevice); - timer->hw = snd_pcm_timer; - if (snd_device_register(timer->card, timer) < 0) { - snd_device_free(timer->card, timer); - return; - } - timer->private_data = substream; - timer->private_free = snd_pcm_timer_free; - substream->timer = timer; -} - -void snd_pcm_timer_done(struct snd_pcm_substream *substream) -{ - if (substream->timer) { - snd_device_free(substream->pcm->card, substream->timer); - substream->timer = NULL; - } -} diff --git a/ANDROID_3.4.5/sound/core/rawmidi.c b/ANDROID_3.4.5/sound/core/rawmidi.c deleted file mode 100644 index 1bb95aee..00000000 --- a/ANDROID_3.4.5/sound/core/rawmidi.c +++ /dev/null @@ -1,1726 +0,0 @@ -/* - * Abstract layer for MIDI v1.0 stream - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA."); -MODULE_LICENSE("GPL"); - -#ifdef CONFIG_SND_OSSEMUL -static int midi_map[SNDRV_CARDS]; -static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; -module_param_array(midi_map, int, NULL, 0444); -MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device."); -module_param_array(amidi_map, int, NULL, 0444); -MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device."); -#endif /* CONFIG_SND_OSSEMUL */ - -static int snd_rawmidi_free(struct snd_rawmidi *rawmidi); -static int snd_rawmidi_dev_free(struct snd_device *device); -static int snd_rawmidi_dev_register(struct snd_device *device); -static int snd_rawmidi_dev_disconnect(struct snd_device *device); - -static LIST_HEAD(snd_rawmidi_devices); -static DEFINE_MUTEX(register_mutex); - -static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) -{ - struct snd_rawmidi *rawmidi; - - list_for_each_entry(rawmidi, &snd_rawmidi_devices, list) - if (rawmidi->card == card && rawmidi->device == device) - return rawmidi; - return NULL; -} - -static inline unsigned short snd_rawmidi_file_flags(struct file *file) -{ - switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) { - case FMODE_WRITE: - return SNDRV_RAWMIDI_LFLG_OUTPUT; - case FMODE_READ: - return SNDRV_RAWMIDI_LFLG_INPUT; - default: - return SNDRV_RAWMIDI_LFLG_OPEN; - } -} - -static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream) -{ - struct snd_rawmidi_runtime *runtime = substream->runtime; - return runtime->avail >= runtime->avail_min; -} - -static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substream, - size_t count) -{ - struct snd_rawmidi_runtime *runtime = substream->runtime; - return runtime->avail >= runtime->avail_min && - (!substream->append || runtime->avail >= count); -} - -static void snd_rawmidi_input_event_work(struct work_struct *work) -{ - struct snd_rawmidi_runtime *runtime = - container_of(work, struct snd_rawmidi_runtime, event_work); - if (runtime->event) - runtime->event(runtime->substream); -} - -static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) -{ - struct snd_rawmidi_runtime *runtime; - - if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL) - return -ENOMEM; - runtime->substream = substream; - spin_lock_init(&runtime->lock); - init_waitqueue_head(&runtime->sleep); - INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work); - runtime->event = NULL; - runtime->buffer_size = PAGE_SIZE; - runtime->avail_min = 1; - if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) - runtime->avail = 0; - else - runtime->avail = runtime->buffer_size; - if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) { - kfree(runtime); - return -ENOMEM; - } - runtime->appl_ptr = runtime->hw_ptr = 0; - substream->runtime = runtime; - return 0; -} - -static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream) -{ - struct snd_rawmidi_runtime *runtime = substream->runtime; - - kfree(runtime->buffer); - kfree(runtime); - substream->runtime = NULL; - return 0; -} - -static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up) -{ - if (!substream->opened) - return; - substream->ops->trigger(substream, up); -} - -static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - if (!substream->opened) - return; - substream->ops->trigger(substream, up); - if (!up) - cancel_work_sync(&substream->runtime->event_work); -} - -int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - snd_rawmidi_output_trigger(substream, 0); - runtime->drain = 0; - spin_lock_irqsave(&runtime->lock, flags); - runtime->appl_ptr = runtime->hw_ptr = 0; - runtime->avail = runtime->buffer_size; - spin_unlock_irqrestore(&runtime->lock, flags); - return 0; -} - -int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream) -{ - int err; - long timeout; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - err = 0; - runtime->drain = 1; - timeout = wait_event_interruptible_timeout(runtime->sleep, - (runtime->avail >= runtime->buffer_size), - 10*HZ); - if (signal_pending(current)) - err = -ERESTARTSYS; - if (runtime->avail < runtime->buffer_size && !timeout) { - snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size); - err = -EIO; - } - runtime->drain = 0; - if (err != -ERESTARTSYS) { - /* we need wait a while to make sure that Tx FIFOs are empty */ - if (substream->ops->drain) - substream->ops->drain(substream); - else - msleep(50); - snd_rawmidi_drop_output(substream); - } - return err; -} - -int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - snd_rawmidi_input_trigger(substream, 0); - runtime->drain = 0; - spin_lock_irqsave(&runtime->lock, flags); - runtime->appl_ptr = runtime->hw_ptr = 0; - runtime->avail = 0; - spin_unlock_irqrestore(&runtime->lock, flags); - return 0; -} - -/* look for an available substream for the given stream direction; - * if a specific subdevice is given, try to assign it - */ -static int assign_substream(struct snd_rawmidi *rmidi, int subdevice, - int stream, int mode, - struct snd_rawmidi_substream **sub_ret) -{ - struct snd_rawmidi_substream *substream; - struct snd_rawmidi_str *s = &rmidi->streams[stream]; - static unsigned int info_flags[2] = { - [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT, - [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT, - }; - - if (!(rmidi->info_flags & info_flags[stream])) - return -ENXIO; - if (subdevice >= 0 && subdevice >= s->substream_count) - return -ENODEV; - - list_for_each_entry(substream, &s->substreams, list) { - if (substream->opened) { - if (stream == SNDRV_RAWMIDI_STREAM_INPUT || - !(mode & SNDRV_RAWMIDI_LFLG_APPEND) || - !substream->append) - continue; - } - if (subdevice < 0 || subdevice == substream->number) { - *sub_ret = substream; - return 0; - } - } - return -EAGAIN; -} - -/* open and do ref-counting for the given substream */ -static int open_substream(struct snd_rawmidi *rmidi, - struct snd_rawmidi_substream *substream, - int mode) -{ - int err; - - if (substream->use_count == 0) { - err = snd_rawmidi_runtime_create(substream); - if (err < 0) - return err; - err = substream->ops->open(substream); - if (err < 0) { - snd_rawmidi_runtime_free(substream); - return err; - } - substream->opened = 1; - substream->active_sensing = 0; - if (mode & SNDRV_RAWMIDI_LFLG_APPEND) - substream->append = 1; - substream->pid = get_pid(task_pid(current)); - rmidi->streams[substream->stream].substream_opened++; - } - substream->use_count++; - return 0; -} - -static void close_substream(struct snd_rawmidi *rmidi, - struct snd_rawmidi_substream *substream, - int cleanup); - -static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode, - struct snd_rawmidi_file *rfile) -{ - struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL; - int err; - - rfile->input = rfile->output = NULL; - if (mode & SNDRV_RAWMIDI_LFLG_INPUT) { - err = assign_substream(rmidi, subdevice, - SNDRV_RAWMIDI_STREAM_INPUT, - mode, &sinput); - if (err < 0) - return err; - } - if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) { - err = assign_substream(rmidi, subdevice, - SNDRV_RAWMIDI_STREAM_OUTPUT, - mode, &soutput); - if (err < 0) - return err; - } - - if (sinput) { - err = open_substream(rmidi, sinput, mode); - if (err < 0) - return err; - } - if (soutput) { - err = open_substream(rmidi, soutput, mode); - if (err < 0) { - if (sinput) - close_substream(rmidi, sinput, 0); - return err; - } - } - - rfile->rmidi = rmidi; - rfile->input = sinput; - rfile->output = soutput; - return 0; -} - -/* called from sound/core/seq/seq_midi.c */ -int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice, - int mode, struct snd_rawmidi_file * rfile) -{ - struct snd_rawmidi *rmidi; - int err; - - if (snd_BUG_ON(!rfile)) - return -EINVAL; - - mutex_lock(®ister_mutex); - rmidi = snd_rawmidi_search(card, device); - if (rmidi == NULL) { - mutex_unlock(®ister_mutex); - return -ENODEV; - } - if (!try_module_get(rmidi->card->module)) { - mutex_unlock(®ister_mutex); - return -ENXIO; - } - mutex_unlock(®ister_mutex); - - mutex_lock(&rmidi->open_mutex); - err = rawmidi_open_priv(rmidi, subdevice, mode, rfile); - mutex_unlock(&rmidi->open_mutex); - if (err < 0) - module_put(rmidi->card->module); - return err; -} - -static int snd_rawmidi_open(struct inode *inode, struct file *file) -{ - int maj = imajor(inode); - struct snd_card *card; - int subdevice; - unsigned short fflags; - int err; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_file *rawmidi_file = NULL; - wait_queue_t wait; - struct snd_ctl_file *kctl; - - if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) - return -EINVAL; /* invalid combination */ - - err = nonseekable_open(inode, file); - if (err < 0) - return err; - - if (maj == snd_major) { - rmidi = snd_lookup_minor_data(iminor(inode), - SNDRV_DEVICE_TYPE_RAWMIDI); -#ifdef CONFIG_SND_OSSEMUL - } else if (maj == SOUND_MAJOR) { - rmidi = snd_lookup_oss_minor_data(iminor(inode), - SNDRV_OSS_DEVICE_TYPE_MIDI); -#endif - } else - return -ENXIO; - - if (rmidi == NULL) - return -ENODEV; - - if (!try_module_get(rmidi->card->module)) { - snd_card_unref(rmidi->card); - return -ENXIO; - } - - mutex_lock(&rmidi->open_mutex); - card = rmidi->card; - err = snd_card_file_add(card, file); - if (err < 0) - goto __error_card; - fflags = snd_rawmidi_file_flags(file); - if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */ - fflags |= SNDRV_RAWMIDI_LFLG_APPEND; - rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL); - if (rawmidi_file == NULL) { - err = -ENOMEM; - goto __error; - } - init_waitqueue_entry(&wait, current); - add_wait_queue(&rmidi->open_wait, &wait); - while (1) { - subdevice = -1; - read_lock(&card->ctl_files_rwlock); - list_for_each_entry(kctl, &card->ctl_files, list) { - if (kctl->pid == task_pid(current)) { - subdevice = kctl->prefer_rawmidi_subdevice; - if (subdevice != -1) - break; - } - } - read_unlock(&card->ctl_files_rwlock); - err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file); - if (err >= 0) - break; - if (err == -EAGAIN) { - if (file->f_flags & O_NONBLOCK) { - err = -EBUSY; - break; - } - } else - break; - set_current_state(TASK_INTERRUPTIBLE); - mutex_unlock(&rmidi->open_mutex); - schedule(); - mutex_lock(&rmidi->open_mutex); - if (rmidi->card->shutdown) { - err = -ENODEV; - break; - } - if (signal_pending(current)) { - err = -ERESTARTSYS; - break; - } - } - remove_wait_queue(&rmidi->open_wait, &wait); - if (err < 0) { - kfree(rawmidi_file); - goto __error; - } -#ifdef CONFIG_SND_OSSEMUL - if (rawmidi_file->input && rawmidi_file->input->runtime) - rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR); - if (rawmidi_file->output && rawmidi_file->output->runtime) - rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR); -#endif - file->private_data = rawmidi_file; - mutex_unlock(&rmidi->open_mutex); - snd_card_unref(rmidi->card); - return 0; - - __error: - snd_card_file_remove(card, file); - __error_card: - mutex_unlock(&rmidi->open_mutex); - module_put(rmidi->card->module); - snd_card_unref(rmidi->card); - return err; -} - -static void close_substream(struct snd_rawmidi *rmidi, - struct snd_rawmidi_substream *substream, - int cleanup) -{ - if (--substream->use_count) - return; - - if (cleanup) { - if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) - snd_rawmidi_input_trigger(substream, 0); - else { - if (substream->active_sensing) { - unsigned char buf = 0xfe; - /* sending single active sensing message - * to shut the device up - */ - snd_rawmidi_kernel_write(substream, &buf, 1); - } - if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS) - snd_rawmidi_output_trigger(substream, 0); - } - } - substream->ops->close(substream); - if (substream->runtime->private_free) - substream->runtime->private_free(substream); - snd_rawmidi_runtime_free(substream); - substream->opened = 0; - substream->append = 0; - put_pid(substream->pid); - substream->pid = NULL; - rmidi->streams[substream->stream].substream_opened--; -} - -static void rawmidi_release_priv(struct snd_rawmidi_file *rfile) -{ - struct snd_rawmidi *rmidi; - - rmidi = rfile->rmidi; - mutex_lock(&rmidi->open_mutex); - if (rfile->input) { - close_substream(rmidi, rfile->input, 1); - rfile->input = NULL; - } - if (rfile->output) { - close_substream(rmidi, rfile->output, 1); - rfile->output = NULL; - } - rfile->rmidi = NULL; - mutex_unlock(&rmidi->open_mutex); - wake_up(&rmidi->open_wait); -} - -/* called from sound/core/seq/seq_midi.c */ -int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile) -{ - struct snd_rawmidi *rmidi; - - if (snd_BUG_ON(!rfile)) - return -ENXIO; - - rmidi = rfile->rmidi; - rawmidi_release_priv(rfile); - module_put(rmidi->card->module); - return 0; -} - -static int snd_rawmidi_release(struct inode *inode, struct file *file) -{ - struct snd_rawmidi_file *rfile; - struct snd_rawmidi *rmidi; - struct module *module; - - rfile = file->private_data; - rmidi = rfile->rmidi; - rawmidi_release_priv(rfile); - kfree(rfile); - module = rmidi->card->module; - snd_card_file_remove(rmidi->card, file); - module_put(module); - return 0; -} - -static int snd_rawmidi_info(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_info *info) -{ - struct snd_rawmidi *rmidi; - - if (substream == NULL) - return -ENODEV; - rmidi = substream->rmidi; - memset(info, 0, sizeof(*info)); - info->card = rmidi->card->number; - info->device = rmidi->device; - info->subdevice = substream->number; - info->stream = substream->stream; - info->flags = rmidi->info_flags; - strcpy(info->id, rmidi->id); - strcpy(info->name, rmidi->name); - strcpy(info->subname, substream->name); - info->subdevices_count = substream->pstr->substream_count; - info->subdevices_avail = (substream->pstr->substream_count - - substream->pstr->substream_opened); - return 0; -} - -static int snd_rawmidi_info_user(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_info __user * _info) -{ - struct snd_rawmidi_info info; - int err; - if ((err = snd_rawmidi_info(substream, &info)) < 0) - return err; - if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info))) - return -EFAULT; - return 0; -} - -int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info) -{ - struct snd_rawmidi *rmidi; - struct snd_rawmidi_str *pstr; - struct snd_rawmidi_substream *substream; - - mutex_lock(®ister_mutex); - rmidi = snd_rawmidi_search(card, info->device); - mutex_unlock(®ister_mutex); - if (!rmidi) - return -ENXIO; - if (info->stream < 0 || info->stream > 1) - return -EINVAL; - pstr = &rmidi->streams[info->stream]; - if (pstr->substream_count == 0) - return -ENOENT; - if (info->subdevice >= pstr->substream_count) - return -ENXIO; - list_for_each_entry(substream, &pstr->substreams, list) { - if ((unsigned int)substream->number == info->subdevice) - return snd_rawmidi_info(substream, info); - } - return -ENXIO; -} - -static int snd_rawmidi_info_select_user(struct snd_card *card, - struct snd_rawmidi_info __user *_info) -{ - int err; - struct snd_rawmidi_info info; - if (get_user(info.device, &_info->device)) - return -EFAULT; - if (get_user(info.stream, &_info->stream)) - return -EFAULT; - if (get_user(info.subdevice, &_info->subdevice)) - return -EFAULT; - if ((err = snd_rawmidi_info_select(card, &info)) < 0) - return err; - if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info))) - return -EFAULT; - return 0; -} - -int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_params * params) -{ - char *newbuf; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - if (substream->append && substream->use_count > 1) - return -EBUSY; - snd_rawmidi_drain_output(substream); - if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { - return -EINVAL; - } - if (params->avail_min < 1 || params->avail_min > params->buffer_size) { - return -EINVAL; - } - if (params->buffer_size != runtime->buffer_size) { - newbuf = krealloc(runtime->buffer, params->buffer_size, - GFP_KERNEL); - if (!newbuf) - return -ENOMEM; - runtime->buffer = newbuf; - runtime->buffer_size = params->buffer_size; - runtime->avail = runtime->buffer_size; - } - runtime->avail_min = params->avail_min; - substream->active_sensing = !params->no_active_sensing; - return 0; -} - -int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_params * params) -{ - char *newbuf; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - snd_rawmidi_drain_input(substream); - if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) { - return -EINVAL; - } - if (params->avail_min < 1 || params->avail_min > params->buffer_size) { - return -EINVAL; - } - if (params->buffer_size != runtime->buffer_size) { - newbuf = krealloc(runtime->buffer, params->buffer_size, - GFP_KERNEL); - if (!newbuf) - return -ENOMEM; - runtime->buffer = newbuf; - runtime->buffer_size = params->buffer_size; - } - runtime->avail_min = params->avail_min; - return 0; -} - -static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status * status) -{ - struct snd_rawmidi_runtime *runtime = substream->runtime; - - memset(status, 0, sizeof(*status)); - status->stream = SNDRV_RAWMIDI_STREAM_OUTPUT; - spin_lock_irq(&runtime->lock); - status->avail = runtime->avail; - spin_unlock_irq(&runtime->lock); - return 0; -} - -static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream, - struct snd_rawmidi_status * status) -{ - struct snd_rawmidi_runtime *runtime = substream->runtime; - - memset(status, 0, sizeof(*status)); - status->stream = SNDRV_RAWMIDI_STREAM_INPUT; - spin_lock_irq(&runtime->lock); - status->avail = runtime->avail; - status->xruns = runtime->xruns; - runtime->xruns = 0; - spin_unlock_irq(&runtime->lock); - return 0; -} - -static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_rawmidi_file *rfile; - void __user *argp = (void __user *)arg; - - rfile = file->private_data; - if (((cmd >> 8) & 0xff) != 'W') - return -ENOTTY; - switch (cmd) { - case SNDRV_RAWMIDI_IOCTL_PVERSION: - return put_user(SNDRV_RAWMIDI_VERSION, (int __user *)argp) ? -EFAULT : 0; - case SNDRV_RAWMIDI_IOCTL_INFO: - { - int stream; - struct snd_rawmidi_info __user *info = argp; - if (get_user(stream, &info->stream)) - return -EFAULT; - switch (stream) { - case SNDRV_RAWMIDI_STREAM_INPUT: - return snd_rawmidi_info_user(rfile->input, info); - case SNDRV_RAWMIDI_STREAM_OUTPUT: - return snd_rawmidi_info_user(rfile->output, info); - default: - return -EINVAL; - } - } - case SNDRV_RAWMIDI_IOCTL_PARAMS: - { - struct snd_rawmidi_params params; - if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) - return -EFAULT; - switch (params.stream) { - case SNDRV_RAWMIDI_STREAM_OUTPUT: - if (rfile->output == NULL) - return -EINVAL; - return snd_rawmidi_output_params(rfile->output, ¶ms); - case SNDRV_RAWMIDI_STREAM_INPUT: - if (rfile->input == NULL) - return -EINVAL; - return snd_rawmidi_input_params(rfile->input, ¶ms); - default: - return -EINVAL; - } - } - case SNDRV_RAWMIDI_IOCTL_STATUS: - { - int err = 0; - struct snd_rawmidi_status status; - if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status))) - return -EFAULT; - switch (status.stream) { - case SNDRV_RAWMIDI_STREAM_OUTPUT: - if (rfile->output == NULL) - return -EINVAL; - err = snd_rawmidi_output_status(rfile->output, &status); - break; - case SNDRV_RAWMIDI_STREAM_INPUT: - if (rfile->input == NULL) - return -EINVAL; - err = snd_rawmidi_input_status(rfile->input, &status); - break; - default: - return -EINVAL; - } - if (err < 0) - return err; - if (copy_to_user(argp, &status, sizeof(struct snd_rawmidi_status))) - return -EFAULT; - return 0; - } - case SNDRV_RAWMIDI_IOCTL_DROP: - { - int val; - if (get_user(val, (int __user *) argp)) - return -EFAULT; - switch (val) { - case SNDRV_RAWMIDI_STREAM_OUTPUT: - if (rfile->output == NULL) - return -EINVAL; - return snd_rawmidi_drop_output(rfile->output); - default: - return -EINVAL; - } - } - case SNDRV_RAWMIDI_IOCTL_DRAIN: - { - int val; - if (get_user(val, (int __user *) argp)) - return -EFAULT; - switch (val) { - case SNDRV_RAWMIDI_STREAM_OUTPUT: - if (rfile->output == NULL) - return -EINVAL; - return snd_rawmidi_drain_output(rfile->output); - case SNDRV_RAWMIDI_STREAM_INPUT: - if (rfile->input == NULL) - return -EINVAL; - return snd_rawmidi_drain_input(rfile->input); - default: - return -EINVAL; - } - } -#ifdef CONFIG_SND_DEBUG - default: - snd_printk(KERN_WARNING "rawmidi: unknown command = 0x%x\n", cmd); -#endif - } - return -ENOTTY; -} - -static int snd_rawmidi_control_ioctl(struct snd_card *card, - struct snd_ctl_file *control, - unsigned int cmd, - unsigned long arg) -{ - void __user *argp = (void __user *)arg; - - switch (cmd) { - case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE: - { - int device; - - if (get_user(device, (int __user *)argp)) - return -EFAULT; - if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */ - device = SNDRV_RAWMIDI_DEVICES - 1; - mutex_lock(®ister_mutex); - device = device < 0 ? 0 : device + 1; - while (device < SNDRV_RAWMIDI_DEVICES) { - if (snd_rawmidi_search(card, device)) - break; - device++; - } - if (device == SNDRV_RAWMIDI_DEVICES) - device = -1; - mutex_unlock(®ister_mutex); - if (put_user(device, (int __user *)argp)) - return -EFAULT; - return 0; - } - case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE: - { - int val; - - if (get_user(val, (int __user *)argp)) - return -EFAULT; - control->prefer_rawmidi_subdevice = val; - return 0; - } - case SNDRV_CTL_IOCTL_RAWMIDI_INFO: - return snd_rawmidi_info_select_user(card, argp); - } - return -ENOIOCTLCMD; -} - -/** - * snd_rawmidi_receive - receive the input data from the device - * @substream: the rawmidi substream - * @buffer: the buffer pointer - * @count: the data size to read - * - * Reads the data from the internal buffer. - * - * Returns the size of read data, or a negative error code on failure. - */ -int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, - const unsigned char *buffer, int count) -{ - unsigned long flags; - int result = 0, count1; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - if (!substream->opened) - return -EBADFD; - if (runtime->buffer == NULL) { - snd_printd("snd_rawmidi_receive: input is not active!!!\n"); - return -EINVAL; - } - spin_lock_irqsave(&runtime->lock, flags); - if (count == 1) { /* special case, faster code */ - substream->bytes++; - if (runtime->avail < runtime->buffer_size) { - runtime->buffer[runtime->hw_ptr++] = buffer[0]; - runtime->hw_ptr %= runtime->buffer_size; - runtime->avail++; - result++; - } else { - runtime->xruns++; - } - } else { - substream->bytes += count; - count1 = runtime->buffer_size - runtime->hw_ptr; - if (count1 > count) - count1 = count; - if (count1 > (int)(runtime->buffer_size - runtime->avail)) - count1 = runtime->buffer_size - runtime->avail; - memcpy(runtime->buffer + runtime->hw_ptr, buffer, count1); - runtime->hw_ptr += count1; - runtime->hw_ptr %= runtime->buffer_size; - runtime->avail += count1; - count -= count1; - result += count1; - if (count > 0) { - buffer += count1; - count1 = count; - if (count1 > (int)(runtime->buffer_size - runtime->avail)) { - count1 = runtime->buffer_size - runtime->avail; - runtime->xruns += count - count1; - } - if (count1 > 0) { - memcpy(runtime->buffer, buffer, count1); - runtime->hw_ptr = count1; - runtime->avail += count1; - result += count1; - } - } - } - if (result > 0) { - if (runtime->event) - schedule_work(&runtime->event_work); - else if (snd_rawmidi_ready(substream)) - wake_up(&runtime->sleep); - } - spin_unlock_irqrestore(&runtime->lock, flags); - return result; -} - -static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream, - unsigned char __user *userbuf, - unsigned char *kernelbuf, long count) -{ - unsigned long flags; - long result = 0, count1; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - while (count > 0 && runtime->avail) { - count1 = runtime->buffer_size - runtime->appl_ptr; - if (count1 > count) - count1 = count; - spin_lock_irqsave(&runtime->lock, flags); - if (count1 > (int)runtime->avail) - count1 = runtime->avail; - if (kernelbuf) - memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1); - if (userbuf) { - spin_unlock_irqrestore(&runtime->lock, flags); - if (copy_to_user(userbuf + result, - runtime->buffer + runtime->appl_ptr, count1)) { - return result > 0 ? result : -EFAULT; - } - spin_lock_irqsave(&runtime->lock, flags); - } - runtime->appl_ptr += count1; - runtime->appl_ptr %= runtime->buffer_size; - runtime->avail -= count1; - spin_unlock_irqrestore(&runtime->lock, flags); - result += count1; - count -= count1; - } - return result; -} - -long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream, - unsigned char *buf, long count) -{ - snd_rawmidi_input_trigger(substream, 1); - return snd_rawmidi_kernel_read1(substream, NULL/*userbuf*/, buf, count); -} - -static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count, - loff_t *offset) -{ - long result; - int count1; - struct snd_rawmidi_file *rfile; - struct snd_rawmidi_substream *substream; - struct snd_rawmidi_runtime *runtime; - - rfile = file->private_data; - substream = rfile->input; - if (substream == NULL) - return -EIO; - runtime = substream->runtime; - snd_rawmidi_input_trigger(substream, 1); - result = 0; - while (count > 0) { - spin_lock_irq(&runtime->lock); - while (!snd_rawmidi_ready(substream)) { - wait_queue_t wait; - if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { - spin_unlock_irq(&runtime->lock); - return result > 0 ? result : -EAGAIN; - } - init_waitqueue_entry(&wait, current); - add_wait_queue(&runtime->sleep, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(&runtime->lock); - schedule(); - remove_wait_queue(&runtime->sleep, &wait); - if (rfile->rmidi->card->shutdown) - return -ENODEV; - if (signal_pending(current)) - return result > 0 ? result : -ERESTARTSYS; - if (!runtime->avail) - return result > 0 ? result : -EIO; - spin_lock_irq(&runtime->lock); - } - spin_unlock_irq(&runtime->lock); - count1 = snd_rawmidi_kernel_read1(substream, - (unsigned char __user *)buf, - NULL/*kernelbuf*/, - count); - if (count1 < 0) - return result > 0 ? result : count1; - result += count1; - buf += count1; - count -= count1; - } - return result; -} - -/** - * snd_rawmidi_transmit_empty - check whether the output buffer is empty - * @substream: the rawmidi substream - * - * Returns 1 if the internal output buffer is empty, 0 if not. - */ -int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream) -{ - struct snd_rawmidi_runtime *runtime = substream->runtime; - int result; - unsigned long flags; - - if (runtime->buffer == NULL) { - snd_printd("snd_rawmidi_transmit_empty: output is not active!!!\n"); - return 1; - } - spin_lock_irqsave(&runtime->lock, flags); - result = runtime->avail >= runtime->buffer_size; - spin_unlock_irqrestore(&runtime->lock, flags); - return result; -} - -/** - * snd_rawmidi_transmit_peek - copy data from the internal buffer - * @substream: the rawmidi substream - * @buffer: the buffer pointer - * @count: data size to transfer - * - * Copies data from the internal output buffer to the given buffer. - * - * Call this in the interrupt handler when the midi output is ready, - * and call snd_rawmidi_transmit_ack() after the transmission is - * finished. - * - * Returns the size of copied data, or a negative error code on failure. - */ -int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, - unsigned char *buffer, int count) -{ - unsigned long flags; - int result, count1; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - if (runtime->buffer == NULL) { - snd_printd("snd_rawmidi_transmit_peek: output is not active!!!\n"); - return -EINVAL; - } - result = 0; - spin_lock_irqsave(&runtime->lock, flags); - if (runtime->avail >= runtime->buffer_size) { - /* warning: lowlevel layer MUST trigger down the hardware */ - goto __skip; - } - if (count == 1) { /* special case, faster code */ - *buffer = runtime->buffer[runtime->hw_ptr]; - result++; - } else { - count1 = runtime->buffer_size - runtime->hw_ptr; - if (count1 > count) - count1 = count; - if (count1 > (int)(runtime->buffer_size - runtime->avail)) - count1 = runtime->buffer_size - runtime->avail; - memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1); - count -= count1; - result += count1; - if (count > 0) { - if (count > (int)(runtime->buffer_size - runtime->avail - count1)) - count = runtime->buffer_size - runtime->avail - count1; - memcpy(buffer + count1, runtime->buffer, count); - result += count; - } - } - __skip: - spin_unlock_irqrestore(&runtime->lock, flags); - return result; -} - -/** - * snd_rawmidi_transmit_ack - acknowledge the transmission - * @substream: the rawmidi substream - * @count: the tranferred count - * - * Advances the hardware pointer for the internal output buffer with - * the given size and updates the condition. - * Call after the transmission is finished. - * - * Returns the advanced size if successful, or a negative error code on failure. - */ -int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count) -{ - unsigned long flags; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - if (runtime->buffer == NULL) { - snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n"); - return -EINVAL; - } - spin_lock_irqsave(&runtime->lock, flags); - snd_BUG_ON(runtime->avail + count > runtime->buffer_size); - runtime->hw_ptr += count; - runtime->hw_ptr %= runtime->buffer_size; - runtime->avail += count; - substream->bytes += count; - if (count > 0) { - if (runtime->drain || snd_rawmidi_ready(substream)) - wake_up(&runtime->sleep); - } - spin_unlock_irqrestore(&runtime->lock, flags); - return count; -} - -/** - * snd_rawmidi_transmit - copy from the buffer to the device - * @substream: the rawmidi substream - * @buffer: the buffer pointer - * @count: the data size to transfer - * - * Copies data from the buffer to the device and advances the pointer. - * - * Returns the copied size if successful, or a negative error code on failure. - */ -int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, - unsigned char *buffer, int count) -{ - if (!substream->opened) - return -EBADFD; - count = snd_rawmidi_transmit_peek(substream, buffer, count); - if (count < 0) - return count; - return snd_rawmidi_transmit_ack(substream, count); -} - -static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream, - const unsigned char __user *userbuf, - const unsigned char *kernelbuf, - long count) -{ - unsigned long flags; - long count1, result; - struct snd_rawmidi_runtime *runtime = substream->runtime; - - if (snd_BUG_ON(!kernelbuf && !userbuf)) - return -EINVAL; - if (snd_BUG_ON(!runtime->buffer)) - return -EINVAL; - - result = 0; - spin_lock_irqsave(&runtime->lock, flags); - if (substream->append) { - if ((long)runtime->avail < count) { - spin_unlock_irqrestore(&runtime->lock, flags); - return -EAGAIN; - } - } - while (count > 0 && runtime->avail > 0) { - count1 = runtime->buffer_size - runtime->appl_ptr; - if (count1 > count) - count1 = count; - if (count1 > (long)runtime->avail) - count1 = runtime->avail; - if (kernelbuf) - memcpy(runtime->buffer + runtime->appl_ptr, - kernelbuf + result, count1); - else if (userbuf) { - spin_unlock_irqrestore(&runtime->lock, flags); - if (copy_from_user(runtime->buffer + runtime->appl_ptr, - userbuf + result, count1)) { - spin_lock_irqsave(&runtime->lock, flags); - result = result > 0 ? result : -EFAULT; - goto __end; - } - spin_lock_irqsave(&runtime->lock, flags); - } - runtime->appl_ptr += count1; - runtime->appl_ptr %= runtime->buffer_size; - runtime->avail -= count1; - result += count1; - count -= count1; - } - __end: - count1 = runtime->avail < runtime->buffer_size; - spin_unlock_irqrestore(&runtime->lock, flags); - if (count1) - snd_rawmidi_output_trigger(substream, 1); - return result; -} - -long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream, - const unsigned char *buf, long count) -{ - return snd_rawmidi_kernel_write1(substream, NULL, buf, count); -} - -static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, - size_t count, loff_t *offset) -{ - long result, timeout; - int count1; - struct snd_rawmidi_file *rfile; - struct snd_rawmidi_runtime *runtime; - struct snd_rawmidi_substream *substream; - - rfile = file->private_data; - substream = rfile->output; - runtime = substream->runtime; - /* we cannot put an atomic message to our buffer */ - if (substream->append && count > runtime->buffer_size) - return -EIO; - result = 0; - while (count > 0) { - spin_lock_irq(&runtime->lock); - while (!snd_rawmidi_ready_append(substream, count)) { - wait_queue_t wait; - if (file->f_flags & O_NONBLOCK) { - spin_unlock_irq(&runtime->lock); - return result > 0 ? result : -EAGAIN; - } - init_waitqueue_entry(&wait, current); - add_wait_queue(&runtime->sleep, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(&runtime->lock); - timeout = schedule_timeout(30 * HZ); - remove_wait_queue(&runtime->sleep, &wait); - if (rfile->rmidi->card->shutdown) - return -ENODEV; - if (signal_pending(current)) - return result > 0 ? result : -ERESTARTSYS; - if (!runtime->avail && !timeout) - return result > 0 ? result : -EIO; - spin_lock_irq(&runtime->lock); - } - spin_unlock_irq(&runtime->lock); - count1 = snd_rawmidi_kernel_write1(substream, buf, NULL, count); - if (count1 < 0) - return result > 0 ? result : count1; - result += count1; - buf += count1; - if ((size_t)count1 < count && (file->f_flags & O_NONBLOCK)) - break; - count -= count1; - } - if (file->f_flags & O_DSYNC) { - spin_lock_irq(&runtime->lock); - while (runtime->avail != runtime->buffer_size) { - wait_queue_t wait; - unsigned int last_avail = runtime->avail; - init_waitqueue_entry(&wait, current); - add_wait_queue(&runtime->sleep, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(&runtime->lock); - timeout = schedule_timeout(30 * HZ); - remove_wait_queue(&runtime->sleep, &wait); - if (signal_pending(current)) - return result > 0 ? result : -ERESTARTSYS; - if (runtime->avail == last_avail && !timeout) - return result > 0 ? result : -EIO; - spin_lock_irq(&runtime->lock); - } - spin_unlock_irq(&runtime->lock); - } - return result; -} - -static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait) -{ - struct snd_rawmidi_file *rfile; - struct snd_rawmidi_runtime *runtime; - unsigned int mask; - - rfile = file->private_data; - if (rfile->input != NULL) { - runtime = rfile->input->runtime; - snd_rawmidi_input_trigger(rfile->input, 1); - poll_wait(file, &runtime->sleep, wait); - } - if (rfile->output != NULL) { - runtime = rfile->output->runtime; - poll_wait(file, &runtime->sleep, wait); - } - mask = 0; - if (rfile->input != NULL) { - if (snd_rawmidi_ready(rfile->input)) - mask |= POLLIN | POLLRDNORM; - } - if (rfile->output != NULL) { - if (snd_rawmidi_ready(rfile->output)) - mask |= POLLOUT | POLLWRNORM; - } - return mask; -} - -/* - */ -#ifdef CONFIG_COMPAT -#include "rawmidi_compat.c" -#else -#define snd_rawmidi_ioctl_compat NULL -#endif - -/* - - */ - -static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream; - struct snd_rawmidi_runtime *runtime; - - rmidi = entry->private_data; - snd_iprintf(buffer, "%s\n\n", rmidi->name); - mutex_lock(&rmidi->open_mutex); - if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) { - list_for_each_entry(substream, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams, - list) { - snd_iprintf(buffer, - "Output %d\n" - " Tx bytes : %lu\n", - substream->number, - (unsigned long) substream->bytes); - if (substream->opened) { - snd_iprintf(buffer, - " Owner PID : %d\n", - pid_vnr(substream->pid)); - runtime = substream->runtime; - snd_iprintf(buffer, - " Mode : %s\n" - " Buffer size : %lu\n" - " Avail : %lu\n", - runtime->oss ? "OSS compatible" : "native", - (unsigned long) runtime->buffer_size, - (unsigned long) runtime->avail); - } - } - } - if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT) { - list_for_each_entry(substream, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams, - list) { - snd_iprintf(buffer, - "Input %d\n" - " Rx bytes : %lu\n", - substream->number, - (unsigned long) substream->bytes); - if (substream->opened) { - snd_iprintf(buffer, - " Owner PID : %d\n", - pid_vnr(substream->pid)); - runtime = substream->runtime; - snd_iprintf(buffer, - " Buffer size : %lu\n" - " Avail : %lu\n" - " Overruns : %lu\n", - (unsigned long) runtime->buffer_size, - (unsigned long) runtime->avail, - (unsigned long) runtime->xruns); - } - } - } - mutex_unlock(&rmidi->open_mutex); -} - -/* - * Register functions - */ - -static const struct file_operations snd_rawmidi_f_ops = -{ - .owner = THIS_MODULE, - .read = snd_rawmidi_read, - .write = snd_rawmidi_write, - .open = snd_rawmidi_open, - .release = snd_rawmidi_release, - .llseek = no_llseek, - .poll = snd_rawmidi_poll, - .unlocked_ioctl = snd_rawmidi_ioctl, - .compat_ioctl = snd_rawmidi_ioctl_compat, -}; - -static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi, - struct snd_rawmidi_str *stream, - int direction, - int count) -{ - struct snd_rawmidi_substream *substream; - int idx; - - for (idx = 0; idx < count; idx++) { - substream = kzalloc(sizeof(*substream), GFP_KERNEL); - if (substream == NULL) { - snd_printk(KERN_ERR "rawmidi: cannot allocate substream\n"); - return -ENOMEM; - } - substream->stream = direction; - substream->number = idx; - substream->rmidi = rmidi; - substream->pstr = stream; - list_add_tail(&substream->list, &stream->substreams); - stream->substream_count++; - } - return 0; -} - -/** - * snd_rawmidi_new - create a rawmidi instance - * @card: the card instance - * @id: the id string - * @device: the device index - * @output_count: the number of output streams - * @input_count: the number of input streams - * @rrawmidi: the pointer to store the new rawmidi instance - * - * Creates a new rawmidi instance. - * Use snd_rawmidi_set_ops() to set the operators to the new instance. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_rawmidi_new(struct snd_card *card, char *id, int device, - int output_count, int input_count, - struct snd_rawmidi ** rrawmidi) -{ - struct snd_rawmidi *rmidi; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_rawmidi_dev_free, - .dev_register = snd_rawmidi_dev_register, - .dev_disconnect = snd_rawmidi_dev_disconnect, - }; - - if (snd_BUG_ON(!card)) - return -ENXIO; - if (rrawmidi) - *rrawmidi = NULL; - rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL); - if (rmidi == NULL) { - snd_printk(KERN_ERR "rawmidi: cannot allocate\n"); - return -ENOMEM; - } - rmidi->card = card; - rmidi->device = device; - mutex_init(&rmidi->open_mutex); - init_waitqueue_head(&rmidi->open_wait); - INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams); - INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams); - - if (id != NULL) - strlcpy(rmidi->id, id, sizeof(rmidi->id)); - if ((err = snd_rawmidi_alloc_substreams(rmidi, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], - SNDRV_RAWMIDI_STREAM_INPUT, - input_count)) < 0) { - snd_rawmidi_free(rmidi); - return err; - } - if ((err = snd_rawmidi_alloc_substreams(rmidi, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], - SNDRV_RAWMIDI_STREAM_OUTPUT, - output_count)) < 0) { - snd_rawmidi_free(rmidi); - return err; - } - if ((err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops)) < 0) { - snd_rawmidi_free(rmidi); - return err; - } - if (rrawmidi) - *rrawmidi = rmidi; - return 0; -} - -static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream) -{ - struct snd_rawmidi_substream *substream; - - while (!list_empty(&stream->substreams)) { - substream = list_entry(stream->substreams.next, struct snd_rawmidi_substream, list); - list_del(&substream->list); - kfree(substream); - } -} - -static int snd_rawmidi_free(struct snd_rawmidi *rmidi) -{ - if (!rmidi) - return 0; - - snd_info_free_entry(rmidi->proc_entry); - rmidi->proc_entry = NULL; - mutex_lock(®ister_mutex); - if (rmidi->ops && rmidi->ops->dev_unregister) - rmidi->ops->dev_unregister(rmidi); - mutex_unlock(®ister_mutex); - - snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); - snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); - if (rmidi->private_free) - rmidi->private_free(rmidi); - kfree(rmidi); - return 0; -} - -static int snd_rawmidi_dev_free(struct snd_device *device) -{ - struct snd_rawmidi *rmidi = device->device_data; - return snd_rawmidi_free(rmidi); -} - -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) -static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) -{ - struct snd_rawmidi *rmidi = device->private_data; - rmidi->seq_dev = NULL; -} -#endif - -static int snd_rawmidi_dev_register(struct snd_device *device) -{ - int err; - struct snd_info_entry *entry; - char name[16]; - struct snd_rawmidi *rmidi = device->device_data; - - if (rmidi->device >= SNDRV_RAWMIDI_DEVICES) - return -ENOMEM; - mutex_lock(®ister_mutex); - if (snd_rawmidi_search(rmidi->card, rmidi->device)) { - mutex_unlock(®ister_mutex); - return -EBUSY; - } - list_add_tail(&rmidi->list, &snd_rawmidi_devices); - sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device); - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, - rmidi->card, rmidi->device, - &snd_rawmidi_f_ops, rmidi, name)) < 0) { - snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device); - list_del(&rmidi->list); - mutex_unlock(®ister_mutex); - return err; - } - if (rmidi->ops && rmidi->ops->dev_register && - (err = rmidi->ops->dev_register(rmidi)) < 0) { - snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); - list_del(&rmidi->list); - mutex_unlock(®ister_mutex); - return err; - } -#ifdef CONFIG_SND_OSSEMUL - rmidi->ossreg = 0; - if ((int)rmidi->device == midi_map[rmidi->card->number]) { - if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, - rmidi->card, 0, &snd_rawmidi_f_ops, - rmidi, name) < 0) { - snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0); - } else { - rmidi->ossreg++; -#ifdef SNDRV_OSS_INFO_DEV_MIDI - snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number, rmidi->name); -#endif - } - } - if ((int)rmidi->device == amidi_map[rmidi->card->number]) { - if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, - rmidi->card, 1, &snd_rawmidi_f_ops, - rmidi, name) < 0) { - snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1); - } else { - rmidi->ossreg++; - } - } -#endif /* CONFIG_SND_OSSEMUL */ - mutex_unlock(®ister_mutex); - sprintf(name, "midi%d", rmidi->device); - entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root); - if (entry) { - entry->private_data = rmidi; - entry->c.text.read = snd_rawmidi_proc_info_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - rmidi->proc_entry = entry; -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */ - if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) { - rmidi->seq_dev->private_data = rmidi; - rmidi->seq_dev->private_free = snd_rawmidi_dev_seq_free; - sprintf(rmidi->seq_dev->name, "MIDI %d-%d", rmidi->card->number, rmidi->device); - snd_device_register(rmidi->card, rmidi->seq_dev); - } - } -#endif - return 0; -} - -static int snd_rawmidi_dev_disconnect(struct snd_device *device) -{ - struct snd_rawmidi *rmidi = device->device_data; - int dir; - - mutex_lock(®ister_mutex); - mutex_lock(&rmidi->open_mutex); - wake_up(&rmidi->open_wait); - list_del_init(&rmidi->list); - for (dir = 0; dir < 2; dir++) { - struct snd_rawmidi_substream *s; - list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { - if (s->runtime) - wake_up(&s->runtime->sleep); - } - } - -#ifdef CONFIG_SND_OSSEMUL - if (rmidi->ossreg) { - if ((int)rmidi->device == midi_map[rmidi->card->number]) { - snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 0); -#ifdef SNDRV_OSS_INFO_DEV_MIDI - snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number); -#endif - } - if ((int)rmidi->device == amidi_map[rmidi->card->number]) - snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 1); - rmidi->ossreg = 0; - } -#endif /* CONFIG_SND_OSSEMUL */ - snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); - mutex_unlock(&rmidi->open_mutex); - mutex_unlock(®ister_mutex); - return 0; -} - -/** - * snd_rawmidi_set_ops - set the rawmidi operators - * @rmidi: the rawmidi instance - * @stream: the stream direction, SNDRV_RAWMIDI_STREAM_XXX - * @ops: the operator table - * - * Sets the rawmidi operators for the given stream direction. - */ -void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream, - struct snd_rawmidi_ops *ops) -{ - struct snd_rawmidi_substream *substream; - - list_for_each_entry(substream, &rmidi->streams[stream].substreams, list) - substream->ops = ops; -} - -/* - * ENTRY functions - */ - -static int __init alsa_rawmidi_init(void) -{ - - snd_ctl_register_ioctl(snd_rawmidi_control_ioctl); - snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl); -#ifdef CONFIG_SND_OSSEMUL - { int i; - /* check device map table */ - for (i = 0; i < SNDRV_CARDS; i++) { - if (midi_map[i] < 0 || midi_map[i] >= SNDRV_RAWMIDI_DEVICES) { - snd_printk(KERN_ERR "invalid midi_map[%d] = %d\n", i, midi_map[i]); - midi_map[i] = 0; - } - if (amidi_map[i] < 0 || amidi_map[i] >= SNDRV_RAWMIDI_DEVICES) { - snd_printk(KERN_ERR "invalid amidi_map[%d] = %d\n", i, amidi_map[i]); - amidi_map[i] = 1; - } - } - } -#endif /* CONFIG_SND_OSSEMUL */ - return 0; -} - -static void __exit alsa_rawmidi_exit(void) -{ - snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl); - snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl); -} - -module_init(alsa_rawmidi_init) -module_exit(alsa_rawmidi_exit) - -EXPORT_SYMBOL(snd_rawmidi_output_params); -EXPORT_SYMBOL(snd_rawmidi_input_params); -EXPORT_SYMBOL(snd_rawmidi_drop_output); -EXPORT_SYMBOL(snd_rawmidi_drain_output); -EXPORT_SYMBOL(snd_rawmidi_drain_input); -EXPORT_SYMBOL(snd_rawmidi_receive); -EXPORT_SYMBOL(snd_rawmidi_transmit_empty); -EXPORT_SYMBOL(snd_rawmidi_transmit_peek); -EXPORT_SYMBOL(snd_rawmidi_transmit_ack); -EXPORT_SYMBOL(snd_rawmidi_transmit); -EXPORT_SYMBOL(snd_rawmidi_new); -EXPORT_SYMBOL(snd_rawmidi_set_ops); -EXPORT_SYMBOL(snd_rawmidi_info_select); -EXPORT_SYMBOL(snd_rawmidi_kernel_open); -EXPORT_SYMBOL(snd_rawmidi_kernel_release); -EXPORT_SYMBOL(snd_rawmidi_kernel_read); -EXPORT_SYMBOL(snd_rawmidi_kernel_write); diff --git a/ANDROID_3.4.5/sound/core/rawmidi_compat.c b/ANDROID_3.4.5/sound/core/rawmidi_compat.c deleted file mode 100644 index 5268c1f5..00000000 --- a/ANDROID_3.4.5/sound/core/rawmidi_compat.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for raw MIDI API - * Copyright (c) by Takashi Iwai - * - * 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 - * - */ - -/* This file included from rawmidi.c */ - -#include - -struct snd_rawmidi_params32 { - s32 stream; - u32 buffer_size; - u32 avail_min; - unsigned int no_active_sensing; /* avoid bit-field */ - unsigned char reserved[16]; -} __attribute__((packed)); - -static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, - struct snd_rawmidi_params32 __user *src) -{ - struct snd_rawmidi_params params; - unsigned int val; - - if (rfile->output == NULL) - return -EINVAL; - if (get_user(params.stream, &src->stream) || - get_user(params.buffer_size, &src->buffer_size) || - get_user(params.avail_min, &src->avail_min) || - get_user(val, &src->no_active_sensing)) - return -EFAULT; - params.no_active_sensing = val; - switch (params.stream) { - case SNDRV_RAWMIDI_STREAM_OUTPUT: - return snd_rawmidi_output_params(rfile->output, ¶ms); - case SNDRV_RAWMIDI_STREAM_INPUT: - return snd_rawmidi_input_params(rfile->input, ¶ms); - } - return -EINVAL; -} - -struct snd_rawmidi_status32 { - s32 stream; - struct compat_timespec tstamp; - u32 avail; - u32 xruns; - unsigned char reserved[16]; -} __attribute__((packed)); - -static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, - struct snd_rawmidi_status32 __user *src) -{ - int err; - struct snd_rawmidi_status status; - - if (rfile->output == NULL) - return -EINVAL; - if (get_user(status.stream, &src->stream)) - return -EFAULT; - - switch (status.stream) { - case SNDRV_RAWMIDI_STREAM_OUTPUT: - err = snd_rawmidi_output_status(rfile->output, &status); - break; - case SNDRV_RAWMIDI_STREAM_INPUT: - err = snd_rawmidi_input_status(rfile->input, &status); - break; - default: - return -EINVAL; - } - if (err < 0) - return err; - - if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || - put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || - put_user(status.avail, &src->avail) || - put_user(status.xruns, &src->xruns)) - return -EFAULT; - - return 0; -} - -enum { - SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), - SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), -}; - -static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_rawmidi_file *rfile; - void __user *argp = compat_ptr(arg); - - rfile = file->private_data; - switch (cmd) { - case SNDRV_RAWMIDI_IOCTL_PVERSION: - case SNDRV_RAWMIDI_IOCTL_INFO: - case SNDRV_RAWMIDI_IOCTL_DROP: - case SNDRV_RAWMIDI_IOCTL_DRAIN: - return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp); - case SNDRV_RAWMIDI_IOCTL_PARAMS32: - return snd_rawmidi_ioctl_params_compat(rfile, argp); - case SNDRV_RAWMIDI_IOCTL_STATUS32: - return snd_rawmidi_ioctl_status_compat(rfile, argp); - } - return -ENOIOCTLCMD; -} diff --git a/ANDROID_3.4.5/sound/core/rtctimer.c b/ANDROID_3.4.5/sound/core/rtctimer.c deleted file mode 100644 index e85e72ba..00000000 --- a/ANDROID_3.4.5/sound/core/rtctimer.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * RTC based high-frequency timer - * - * Copyright (C) 2000 Takashi Iwai - * based on rtctimer.c by Steve Ratcliffe - * - * 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 - -#if defined(CONFIG_RTC) || defined(CONFIG_RTC_MODULE) - -#include - -#define RTC_FREQ 1024 /* default frequency */ -#define NANO_SEC 1000000000L /* 10^9 in sec */ - -/* - * prototypes - */ -static int rtctimer_open(struct snd_timer *t); -static int rtctimer_close(struct snd_timer *t); -static int rtctimer_start(struct snd_timer *t); -static int rtctimer_stop(struct snd_timer *t); - - -/* - * The hardware dependent description for this timer. - */ -static struct snd_timer_hardware rtc_hw = { - .flags = SNDRV_TIMER_HW_AUTO | - SNDRV_TIMER_HW_FIRST | - SNDRV_TIMER_HW_TASKLET, - .ticks = 100000000L, /* FIXME: XXX */ - .open = rtctimer_open, - .close = rtctimer_close, - .start = rtctimer_start, - .stop = rtctimer_stop, -}; - -static int rtctimer_freq = RTC_FREQ; /* frequency */ -static struct snd_timer *rtctimer; -static struct tasklet_struct rtc_tasklet; -static rtc_task_t rtc_task; - - -static int -rtctimer_open(struct snd_timer *t) -{ - int err; - - err = rtc_register(&rtc_task); - if (err < 0) - return err; - t->private_data = &rtc_task; - return 0; -} - -static int -rtctimer_close(struct snd_timer *t) -{ - rtc_task_t *rtc = t->private_data; - if (rtc) { - rtc_unregister(rtc); - tasklet_kill(&rtc_tasklet); - t->private_data = NULL; - } - return 0; -} - -static int -rtctimer_start(struct snd_timer *timer) -{ - rtc_task_t *rtc = timer->private_data; - if (snd_BUG_ON(!rtc)) - return -EINVAL; - rtc_control(rtc, RTC_IRQP_SET, rtctimer_freq); - rtc_control(rtc, RTC_PIE_ON, 0); - return 0; -} - -static int -rtctimer_stop(struct snd_timer *timer) -{ - rtc_task_t *rtc = timer->private_data; - if (snd_BUG_ON(!rtc)) - return -EINVAL; - rtc_control(rtc, RTC_PIE_OFF, 0); - return 0; -} - -static void rtctimer_tasklet(unsigned long data) -{ - snd_timer_interrupt((struct snd_timer *)data, 1); -} - -/* - * interrupt - */ -static void rtctimer_interrupt(void *private_data) -{ - tasklet_schedule(private_data); -} - - -/* - * ENTRY functions - */ -static int __init rtctimer_init(void) -{ - int err; - struct snd_timer *timer; - - if (rtctimer_freq < 2 || rtctimer_freq > 8192 || - !is_power_of_2(rtctimer_freq)) { - snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", - rtctimer_freq); - return -EINVAL; - } - - /* Create a new timer and set up the fields */ - err = snd_timer_global_new("rtc", SNDRV_TIMER_GLOBAL_RTC, &timer); - if (err < 0) - return err; - - timer->module = THIS_MODULE; - strcpy(timer->name, "RTC timer"); - timer->hw = rtc_hw; - timer->hw.resolution = NANO_SEC / rtctimer_freq; - - tasklet_init(&rtc_tasklet, rtctimer_tasklet, (unsigned long)timer); - - /* set up RTC callback */ - rtc_task.func = rtctimer_interrupt; - rtc_task.private_data = &rtc_tasklet; - - err = snd_timer_global_register(timer); - if (err < 0) { - snd_timer_global_free(timer); - return err; - } - rtctimer = timer; /* remember this */ - - return 0; -} - -static void __exit rtctimer_exit(void) -{ - if (rtctimer) { - snd_timer_global_free(rtctimer); - rtctimer = NULL; - } -} - - -/* - * exported stuff - */ -module_init(rtctimer_init) -module_exit(rtctimer_exit) - -module_param(rtctimer_freq, int, 0444); -MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz"); - -MODULE_LICENSE("GPL"); - -MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC)); - -#endif /* CONFIG_RTC || CONFIG_RTC_MODULE */ diff --git a/ANDROID_3.4.5/sound/core/seq/Kconfig b/ANDROID_3.4.5/sound/core/seq/Kconfig deleted file mode 100644 index b851fd89..00000000 --- a/ANDROID_3.4.5/sound/core/seq/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# define SND_XXX_SEQ to min(SND_SEQUENCER,SND_XXX) - -config SND_RAWMIDI_SEQ - def_tristate SND_SEQUENCER && SND_RAWMIDI - -config SND_OPL3_LIB_SEQ - def_tristate SND_SEQUENCER && SND_OPL3_LIB - -config SND_OPL4_LIB_SEQ - def_tristate SND_SEQUENCER && SND_OPL4_LIB - -config SND_SBAWE_SEQ - def_tristate SND_SEQUENCER && SND_SBAWE - -config SND_EMU10K1_SEQ - def_tristate SND_SEQUENCER && SND_EMU10K1 diff --git a/ANDROID_3.4.5/sound/core/seq/Makefile b/ANDROID_3.4.5/sound/core/seq/Makefile deleted file mode 100644 index 941f64a8..00000000 --- a/ANDROID_3.4.5/sound/core/seq/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 1999 by Jaroslav Kysela -# - -snd-seq-device-objs := seq_device.o -snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ - seq_fifo.o seq_prioq.o seq_timer.o \ - seq_system.o seq_ports.o seq_info.o -snd-seq-midi-objs := seq_midi.o -snd-seq-midi-emul-objs := seq_midi_emul.o -snd-seq-midi-event-objs := seq_midi_event.o -snd-seq-dummy-objs := seq_dummy.o -snd-seq-virmidi-objs := seq_virmidi.o - -obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o -ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) - obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o - obj-$(CONFIG_SND_SEQUENCER) += oss/ -endif -obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o -obj-$(CONFIG_SND_RAWMIDI_SEQ) += snd-seq-midi.o snd-seq-midi-event.o -obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o -obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o -obj-$(CONFIG_SND_SBAWE_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o -obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o diff --git a/ANDROID_3.4.5/sound/core/seq/oss/Makefile b/ANDROID_3.4.5/sound/core/seq/oss/Makefile deleted file mode 100644 index b38406b8..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 1999 by Jaroslav Kysela -# - -snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \ - seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \ - seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o - -obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c deleted file mode 100644 index 8d4d5e85..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * registration of device and proc - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_device.h" -#include "seq_oss_synth.h" - -/* - * module option - */ -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("OSS-compatible sequencer module"); -MODULE_LICENSE("GPL"); -/* Takashi says this is really only for sound-service-0-, but this is OK. */ -MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_SEQUENCER); -MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MUSIC); - -#ifdef SNDRV_SEQ_OSS_DEBUG -module_param(seq_oss_debug, int, 0644); -MODULE_PARM_DESC(seq_oss_debug, "debug option"); -int seq_oss_debug = 0; -#endif - - -/* - * prototypes - */ -static int register_device(void); -static void unregister_device(void); -#ifdef CONFIG_PROC_FS -static int register_proc(void); -static void unregister_proc(void); -#else -static inline int register_proc(void) { return 0; } -static inline void unregister_proc(void) {} -#endif - -static int odev_open(struct inode *inode, struct file *file); -static int odev_release(struct inode *inode, struct file *file); -static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset); -static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset); -static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static unsigned int odev_poll(struct file *file, poll_table * wait); - - -/* - * module interface - */ - -static int __init alsa_seq_oss_init(void) -{ - int rc; - static struct snd_seq_dev_ops ops = { - snd_seq_oss_synth_register, - snd_seq_oss_synth_unregister, - }; - - snd_seq_autoload_lock(); - if ((rc = register_device()) < 0) - goto error; - if ((rc = register_proc()) < 0) { - unregister_device(); - goto error; - } - if ((rc = snd_seq_oss_create_client()) < 0) { - unregister_proc(); - unregister_device(); - goto error; - } - - if ((rc = snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OSS, &ops, - sizeof(struct snd_seq_oss_reg))) < 0) { - snd_seq_oss_delete_client(); - unregister_proc(); - unregister_device(); - goto error; - } - - /* success */ - snd_seq_oss_synth_init(); - - error: - snd_seq_autoload_unlock(); - return rc; -} - -static void __exit alsa_seq_oss_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OSS); - snd_seq_oss_delete_client(); - unregister_proc(); - unregister_device(); -} - -module_init(alsa_seq_oss_init) -module_exit(alsa_seq_oss_exit) - -/* - * ALSA minor device interface - */ - -static DEFINE_MUTEX(register_mutex); - -static int -odev_open(struct inode *inode, struct file *file) -{ - int level, rc; - - if (iminor(inode) == SNDRV_MINOR_OSS_MUSIC) - level = SNDRV_SEQ_OSS_MODE_MUSIC; - else - level = SNDRV_SEQ_OSS_MODE_SYNTH; - - mutex_lock(®ister_mutex); - rc = snd_seq_oss_open(file, level); - mutex_unlock(®ister_mutex); - - return rc; -} - -static int -odev_release(struct inode *inode, struct file *file) -{ - struct seq_oss_devinfo *dp; - - if ((dp = file->private_data) == NULL) - return 0; - - snd_seq_oss_drain_write(dp); - - mutex_lock(®ister_mutex); - snd_seq_oss_release(dp); - mutex_unlock(®ister_mutex); - - return 0; -} - -static ssize_t -odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset) -{ - struct seq_oss_devinfo *dp; - dp = file->private_data; - if (snd_BUG_ON(!dp)) - return -ENXIO; - return snd_seq_oss_read(dp, buf, count); -} - - -static ssize_t -odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) -{ - struct seq_oss_devinfo *dp; - dp = file->private_data; - if (snd_BUG_ON(!dp)) - return -ENXIO; - return snd_seq_oss_write(dp, buf, count, file); -} - -static long -odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct seq_oss_devinfo *dp; - dp = file->private_data; - if (snd_BUG_ON(!dp)) - return -ENXIO; - return snd_seq_oss_ioctl(dp, cmd, arg); -} - -#ifdef CONFIG_COMPAT -#define odev_ioctl_compat odev_ioctl -#else -#define odev_ioctl_compat NULL -#endif - -static unsigned int -odev_poll(struct file *file, poll_table * wait) -{ - struct seq_oss_devinfo *dp; - dp = file->private_data; - if (snd_BUG_ON(!dp)) - return -ENXIO; - return snd_seq_oss_poll(dp, file, wait); -} - -/* - * registration of sequencer minor device - */ - -static const struct file_operations seq_oss_f_ops = -{ - .owner = THIS_MODULE, - .read = odev_read, - .write = odev_write, - .open = odev_open, - .release = odev_release, - .poll = odev_poll, - .unlocked_ioctl = odev_ioctl, - .compat_ioctl = odev_ioctl_compat, - .llseek = noop_llseek, -}; - -static int __init -register_device(void) -{ - int rc; - - mutex_lock(®ister_mutex); - if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, - NULL, 0, - &seq_oss_f_ops, NULL, - SNDRV_SEQ_OSS_DEVNAME)) < 0) { - snd_printk(KERN_ERR "can't register device seq\n"); - mutex_unlock(®ister_mutex); - return rc; - } - if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, - NULL, 0, - &seq_oss_f_ops, NULL, - SNDRV_SEQ_OSS_DEVNAME)) < 0) { - snd_printk(KERN_ERR "can't register device music\n"); - snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); - mutex_unlock(®ister_mutex); - return rc; - } - debug_printk(("device registered\n")); - mutex_unlock(®ister_mutex); - return 0; -} - -static void -unregister_device(void) -{ - mutex_lock(®ister_mutex); - debug_printk(("device unregistered\n")); - if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0) - snd_printk(KERN_ERR "error unregister device music\n"); - if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0) - snd_printk(KERN_ERR "error unregister device seq\n"); - mutex_unlock(®ister_mutex); -} - -/* - * /proc interface - */ - -#ifdef CONFIG_PROC_FS - -static struct snd_info_entry *info_entry; - -static void -info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf) -{ - mutex_lock(®ister_mutex); - snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR); - snd_seq_oss_system_info_read(buf); - snd_seq_oss_synth_info_read(buf); - snd_seq_oss_midi_info_read(buf); - mutex_unlock(®ister_mutex); -} - - -static int __init -register_proc(void) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, SNDRV_SEQ_OSS_PROCNAME, snd_seq_root); - if (entry == NULL) - return -ENOMEM; - - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = NULL; - entry->c.text.read = info_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return -ENOMEM; - } - info_entry = entry; - return 0; -} - -static void -unregister_proc(void) -{ - snd_info_free_entry(info_entry); - info_entry = NULL; -} -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h deleted file mode 100644 index c0154a95..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_device.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 - */ - -#ifndef __SEQ_OSS_DEVICE_H -#define __SEQ_OSS_DEVICE_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* enable debug print */ -#define SNDRV_SEQ_OSS_DEBUG - -/* max. applications */ -#define SNDRV_SEQ_OSS_MAX_CLIENTS 16 -#define SNDRV_SEQ_OSS_MAX_SYNTH_DEVS 16 -#define SNDRV_SEQ_OSS_MAX_MIDI_DEVS 32 - -/* version */ -#define SNDRV_SEQ_OSS_MAJOR_VERSION 0 -#define SNDRV_SEQ_OSS_MINOR_VERSION 1 -#define SNDRV_SEQ_OSS_TINY_VERSION 8 -#define SNDRV_SEQ_OSS_VERSION_STR "0.1.8" - -/* device and proc interface name */ -#define SNDRV_SEQ_OSS_DEVNAME "seq_oss" -#define SNDRV_SEQ_OSS_PROCNAME "oss" - - -/* - * type definitions - */ - -typedef unsigned int reltime_t; -typedef unsigned int abstime_t; - - -/* - * synthesizer channel information - */ -struct seq_oss_chinfo { - int note, vel; -}; - -/* - * synthesizer information - */ -struct seq_oss_synthinfo { - struct snd_seq_oss_arg arg; - struct seq_oss_chinfo *ch; - struct seq_oss_synth_sysex *sysex; - int nr_voices; - int opened; - int is_midi; - int midi_mapped; -}; - - -/* - * sequencer client information - */ - -struct seq_oss_devinfo { - - int index; /* application index */ - int cseq; /* sequencer client number */ - int port; /* sequencer port number */ - int queue; /* sequencer queue number */ - - struct snd_seq_addr addr; /* address of this device */ - - int seq_mode; /* sequencer mode */ - int file_mode; /* file access */ - - /* midi device table */ - int max_mididev; - - /* synth device table */ - int max_synthdev; - struct seq_oss_synthinfo synths[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS]; - int synth_opened; - - /* output queue */ - struct seq_oss_writeq *writeq; - - /* midi input queue */ - struct seq_oss_readq *readq; - - /* timer */ - struct seq_oss_timer *timer; -}; - - -/* - * function prototypes - */ - -/* create/delete OSS sequencer client */ -int snd_seq_oss_create_client(void); -int snd_seq_oss_delete_client(void); - -/* device file interface */ -int snd_seq_oss_open(struct file *file, int level); -void snd_seq_oss_release(struct seq_oss_devinfo *dp); -int snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long arg); -int snd_seq_oss_read(struct seq_oss_devinfo *dev, char __user *buf, int count); -int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, struct file *opt); -unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait); - -void snd_seq_oss_reset(struct seq_oss_devinfo *dp); -void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp); - -/* */ -void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time); - - -/* proc interface */ -void snd_seq_oss_system_info_read(struct snd_info_buffer *buf); -void snd_seq_oss_midi_info_read(struct snd_info_buffer *buf); -void snd_seq_oss_synth_info_read(struct snd_info_buffer *buf); -void snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf); - -/* file mode macros */ -#define is_read_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_READ) -#define is_write_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_WRITE) -#define is_nonblock_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_NONBLOCK) - -/* dispatch event */ -static inline int -snd_seq_oss_dispatch(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int atomic, int hop) -{ - return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop); -} - -/* ioctl */ -static inline int -snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg) -{ - return snd_seq_kernel_client_ctl(dp->cseq, type, arg); -} - -/* fill the addresses in header */ -static inline void -snd_seq_oss_fill_addr(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, - int dest_client, int dest_port) -{ - ev->queue = dp->queue; - ev->source = dp->addr; - ev->dest.client = dest_client; - ev->dest.port = dest_port; -} - - -/* misc. functions for proc interface */ -char *enabled_str(int bool); - - -/* for debug */ -#ifdef SNDRV_SEQ_OSS_DEBUG -extern int seq_oss_debug; -#define debug_printk(x) do { if (seq_oss_debug > 0) snd_printd x; } while (0) -#else -#define debug_printk(x) /**/ -#endif - -#endif /* __SEQ_OSS_DEVICE_H */ diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c deleted file mode 100644 index 066f5f3e..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_device.h" -#include "seq_oss_synth.h" -#include "seq_oss_midi.h" -#include "seq_oss_event.h" -#include "seq_oss_timer.h" -#include -#include "seq_oss_readq.h" -#include "seq_oss_writeq.h" - - -/* - * prototypes - */ -static int extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev); -static int chn_voice_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev); -static int chn_common_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev); -static int timing_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev); -static int local_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev); -static int old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev); -static int note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev); -static int note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev); -static int set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev); -static int set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev); -static int set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev); - - -/* - * convert an OSS event to ALSA event - * return 0 : enqueued - * non-zero : invalid - ignored - */ - -int -snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) -{ - switch (q->s.code) { - case SEQ_EXTENDED: - return extended_event(dp, q, ev); - - case EV_CHN_VOICE: - return chn_voice_event(dp, q, ev); - - case EV_CHN_COMMON: - return chn_common_event(dp, q, ev); - - case EV_TIMING: - return timing_event(dp, q, ev); - - case EV_SEQ_LOCAL: - return local_event(dp, q, ev); - - case EV_SYSEX: - return snd_seq_oss_synth_sysex(dp, q->x.dev, q->x.buf, ev); - - case SEQ_MIDIPUTC: - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) - return -EINVAL; - /* put a midi byte */ - if (! is_write_mode(dp->file_mode)) - break; - if (snd_seq_oss_midi_open(dp, q->s.dev, SNDRV_SEQ_OSS_FILE_WRITE)) - break; - if (snd_seq_oss_midi_filemode(dp, q->s.dev) & SNDRV_SEQ_OSS_FILE_WRITE) - return snd_seq_oss_midi_putc(dp, q->s.dev, q->s.parm1, ev); - break; - - case SEQ_ECHO: - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) - return -EINVAL; - return set_echo_event(dp, q, ev); - - case SEQ_PRIVATE: - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) - return -EINVAL; - return snd_seq_oss_synth_raw_event(dp, q->c[1], q->c, ev); - - default: - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) - return -EINVAL; - return old_event(dp, q, ev); - } - return -EINVAL; -} - -/* old type events: mode1 only */ -static int -old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) -{ - switch (q->s.code) { - case SEQ_NOTEOFF: - return note_off_event(dp, 0, q->n.chn, q->n.note, q->n.vel, ev); - - case SEQ_NOTEON: - return note_on_event(dp, 0, q->n.chn, q->n.note, q->n.vel, ev); - - case SEQ_WAIT: - /* skip */ - break; - - case SEQ_PGMCHANGE: - return set_control_event(dp, 0, SNDRV_SEQ_EVENT_PGMCHANGE, - q->n.chn, 0, q->n.note, ev); - - case SEQ_SYNCTIMER: - return snd_seq_oss_timer_reset(dp->timer); - } - - return -EINVAL; -} - -/* 8bytes extended event: mode1 only */ -static int -extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) -{ - int val; - - switch (q->e.cmd) { - case SEQ_NOTEOFF: - return note_off_event(dp, q->e.dev, q->e.chn, q->e.p1, q->e.p2, ev); - - case SEQ_NOTEON: - return note_on_event(dp, q->e.dev, q->e.chn, q->e.p1, q->e.p2, ev); - - case SEQ_PGMCHANGE: - return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_PGMCHANGE, - q->e.chn, 0, q->e.p1, ev); - - case SEQ_AFTERTOUCH: - return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_CHANPRESS, - q->e.chn, 0, q->e.p1, ev); - - case SEQ_BALANCE: - /* convert -128:127 to 0:127 */ - val = (char)q->e.p1; - val = (val + 128) / 2; - return set_control_event(dp, q->e.dev, SNDRV_SEQ_EVENT_CONTROLLER, - q->e.chn, CTL_PAN, val, ev); - - case SEQ_CONTROLLER: - val = ((short)q->e.p3 << 8) | (short)q->e.p2; - switch (q->e.p1) { - case CTRL_PITCH_BENDER: /* SEQ1 V2 control */ - /* -0x2000:0x1fff */ - return set_control_event(dp, q->e.dev, - SNDRV_SEQ_EVENT_PITCHBEND, - q->e.chn, 0, val, ev); - case CTRL_PITCH_BENDER_RANGE: - /* conversion: 100/semitone -> 128/semitone */ - return set_control_event(dp, q->e.dev, - SNDRV_SEQ_EVENT_REGPARAM, - q->e.chn, 0, val*128/100, ev); - default: - return set_control_event(dp, q->e.dev, - SNDRV_SEQ_EVENT_CONTROL14, - q->e.chn, q->e.p1, val, ev); - } - - case SEQ_VOLMODE: - return snd_seq_oss_synth_raw_event(dp, q->e.dev, q->c, ev); - - } - return -EINVAL; -} - -/* channel voice events: mode1 and 2 */ -static int -chn_voice_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) -{ - if (q->v.chn >= 32) - return -EINVAL; - switch (q->v.cmd) { - case MIDI_NOTEON: - return note_on_event(dp, q->v.dev, q->v.chn, q->v.note, q->v.parm, ev); - - case MIDI_NOTEOFF: - return note_off_event(dp, q->v.dev, q->v.chn, q->v.note, q->v.parm, ev); - - case MIDI_KEY_PRESSURE: - return set_note_event(dp, q->v.dev, SNDRV_SEQ_EVENT_KEYPRESS, - q->v.chn, q->v.note, q->v.parm, ev); - - } - return -EINVAL; -} - -/* channel common events: mode1 and 2 */ -static int -chn_common_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) -{ - if (q->l.chn >= 32) - return -EINVAL; - switch (q->l.cmd) { - case MIDI_PGM_CHANGE: - return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_PGMCHANGE, - q->l.chn, 0, q->l.p1, ev); - - case MIDI_CTL_CHANGE: - return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_CONTROLLER, - q->l.chn, q->l.p1, q->l.val, ev); - - case MIDI_PITCH_BEND: - /* conversion: 0:0x3fff -> -0x2000:0x1fff */ - return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_PITCHBEND, - q->l.chn, 0, q->l.val - 8192, ev); - - case MIDI_CHN_PRESSURE: - return set_control_event(dp, q->l.dev, SNDRV_SEQ_EVENT_CHANPRESS, - q->l.chn, 0, q->l.val, ev); - } - return -EINVAL; -} - -/* timer events: mode1 and mode2 */ -static int -timing_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) -{ - switch (q->t.cmd) { - case TMR_ECHO: - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) - return set_echo_event(dp, q, ev); - else { - union evrec tmp; - memset(&tmp, 0, sizeof(tmp)); - /* XXX: only for little-endian! */ - tmp.echo = (q->t.time << 8) | SEQ_ECHO; - return set_echo_event(dp, &tmp, ev); - } - - case TMR_STOP: - if (dp->seq_mode) - return snd_seq_oss_timer_stop(dp->timer); - return 0; - - case TMR_CONTINUE: - if (dp->seq_mode) - return snd_seq_oss_timer_continue(dp->timer); - return 0; - - case TMR_TEMPO: - if (dp->seq_mode) - return snd_seq_oss_timer_tempo(dp->timer, q->t.time); - return 0; - } - - return -EINVAL; -} - -/* local events: mode1 and 2 */ -static int -local_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) -{ - return -EINVAL; -} - -/* - * process note-on event for OSS synth - * three different modes are available: - * - SNDRV_SEQ_OSS_PROCESS_EVENTS (for one-voice per channel mode) - * Accept note 255 as volume change. - * - SNDRV_SEQ_OSS_PASS_EVENTS - * Pass all events to lowlevel driver anyway - * - SNDRV_SEQ_OSS_PROCESS_KEYPRESS (mostly for Emu8000) - * Use key-pressure if note >= 128 - */ -static int -note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev) -{ - struct seq_oss_synthinfo *info = &dp->synths[dev]; - switch (info->arg.event_passing) { - case SNDRV_SEQ_OSS_PROCESS_EVENTS: - if (! info->ch || ch < 0 || ch >= info->nr_voices) { - /* pass directly */ - return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); - } - - if (note == 255 && info->ch[ch].note >= 0) { - /* volume control */ - int type; - //if (! vel) - /* set volume to zero -- note off */ - // type = SNDRV_SEQ_EVENT_NOTEOFF; - //else - if (info->ch[ch].vel) - /* sample already started -- volume change */ - type = SNDRV_SEQ_EVENT_KEYPRESS; - else - /* sample not started -- start now */ - type = SNDRV_SEQ_EVENT_NOTEON; - info->ch[ch].vel = vel; - return set_note_event(dp, dev, type, ch, info->ch[ch].note, vel, ev); - } else if (note >= 128) - return -EINVAL; /* invalid */ - - if (note != info->ch[ch].note && info->ch[ch].note >= 0) - /* note changed - note off at beginning */ - set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, info->ch[ch].note, 0, ev); - /* set current status */ - info->ch[ch].note = note; - info->ch[ch].vel = vel; - if (vel) /* non-zero velocity - start the note now */ - return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); - return -EINVAL; - - case SNDRV_SEQ_OSS_PASS_EVENTS: - /* pass the event anyway */ - return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); - - case SNDRV_SEQ_OSS_PROCESS_KEYPRESS: - if (note >= 128) /* key pressure: shifted by 128 */ - return set_note_event(dp, dev, SNDRV_SEQ_EVENT_KEYPRESS, ch, note - 128, vel, ev); - else /* normal note-on event */ - return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); - } - return -EINVAL; -} - -/* - * process note-off event for OSS synth - */ -static int -note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev) -{ - struct seq_oss_synthinfo *info = &dp->synths[dev]; - switch (info->arg.event_passing) { - case SNDRV_SEQ_OSS_PROCESS_EVENTS: - if (! info->ch || ch < 0 || ch >= info->nr_voices) { - /* pass directly */ - return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); - } - - if (info->ch[ch].note >= 0) { - note = info->ch[ch].note; - info->ch[ch].vel = 0; - info->ch[ch].note = -1; - return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, note, vel, ev); - } - return -EINVAL; /* invalid */ - - case SNDRV_SEQ_OSS_PASS_EVENTS: - case SNDRV_SEQ_OSS_PROCESS_KEYPRESS: - /* pass the event anyway */ - return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEOFF, ch, note, vel, ev); - - } - return -EINVAL; -} - -/* - * create a note event - */ -static int -set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev) -{ - if (! snd_seq_oss_synth_is_valid(dp, dev)) - return -ENXIO; - - ev->type = type; - snd_seq_oss_synth_addr(dp, dev, ev); - ev->data.note.channel = ch; - ev->data.note.note = note; - ev->data.note.velocity = vel; - - return 0; -} - -/* - * create a control event - */ -static int -set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev) -{ - if (! snd_seq_oss_synth_is_valid(dp, dev)) - return -ENXIO; - - ev->type = type; - snd_seq_oss_synth_addr(dp, dev, ev); - ev->data.control.channel = ch; - ev->data.control.param = param; - ev->data.control.value = val; - - return 0; -} - -/* - * create an echo event - */ -static int -set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev) -{ - ev->type = SNDRV_SEQ_EVENT_ECHO; - /* echo back to itself */ - snd_seq_oss_fill_addr(dp, ev, dp->addr.client, dp->addr.port); - memcpy(&ev->data, rec, LONG_EVENT_SIZE); - return 0; -} - -/* - * event input callback from ALSA sequencer: - * the echo event is processed here. - */ -int -snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data, - int atomic, int hop) -{ - struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data; - union evrec *rec; - - if (ev->type != SNDRV_SEQ_EVENT_ECHO) - return snd_seq_oss_midi_input(ev, direct, private_data); - - if (ev->source.client != dp->cseq) - return 0; /* ignored */ - - rec = (union evrec*)&ev->data; - if (rec->s.code == SEQ_SYNCTIMER) { - /* sync echo back */ - snd_seq_oss_writeq_wakeup(dp->writeq, rec->t.time); - - } else { - /* echo back event */ - if (dp->readq == NULL) - return 0; - snd_seq_oss_readq_put_event(dp->readq, rec); - } - return 0; -} - diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h deleted file mode 100644 index 9a4d9adb..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_event.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * seq_oss_event.h - OSS event queue record - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 - */ - -#ifndef __SEQ_OSS_EVENT_H -#define __SEQ_OSS_EVENT_H - -#include "seq_oss_device.h" - -#define SHORT_EVENT_SIZE 4 -#define LONG_EVENT_SIZE 8 - -/* short event (4bytes) */ -struct evrec_short { - unsigned char code; - unsigned char parm1; - unsigned char dev; - unsigned char parm2; -}; - -/* short note events (4bytes) */ -struct evrec_note { - unsigned char code; - unsigned char chn; - unsigned char note; - unsigned char vel; -}; - -/* long timer events (8bytes) */ -struct evrec_timer { - unsigned char code; - unsigned char cmd; - unsigned char dummy1, dummy2; - unsigned int time; -}; - -/* long extended events (8bytes) */ -struct evrec_extended { - unsigned char code; - unsigned char cmd; - unsigned char dev; - unsigned char chn; - unsigned char p1, p2, p3, p4; -}; - -/* long channel events (8bytes) */ -struct evrec_long { - unsigned char code; - unsigned char dev; - unsigned char cmd; - unsigned char chn; - unsigned char p1, p2; - unsigned short val; -}; - -/* channel voice events (8bytes) */ -struct evrec_voice { - unsigned char code; - unsigned char dev; - unsigned char cmd; - unsigned char chn; - unsigned char note, parm; - unsigned short dummy; -}; - -/* sysex events (8bytes) */ -struct evrec_sysex { - unsigned char code; - unsigned char dev; - unsigned char buf[6]; -}; - -/* event record */ -union evrec { - struct evrec_short s; - struct evrec_note n; - struct evrec_long l; - struct evrec_voice v; - struct evrec_timer t; - struct evrec_extended e; - struct evrec_sysex x; - unsigned int echo; - unsigned char c[LONG_EVENT_SIZE]; -}; - -#define ev_is_long(ev) ((ev)->s.code >= 128) -#define ev_length(ev) ((ev)->s.code >= 128 ? LONG_EVENT_SIZE : SHORT_EVENT_SIZE) - -int snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev); -int snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *q); -int snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop); - - -#endif /* __SEQ_OSS_EVENT_H */ diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c deleted file mode 100644 index e3cb46fe..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_init.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * open/close and reset interface - * - * Copyright (C) 1998-1999 Takashi Iwai - * - * 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 "seq_oss_device.h" -#include "seq_oss_synth.h" -#include "seq_oss_midi.h" -#include "seq_oss_writeq.h" -#include "seq_oss_readq.h" -#include "seq_oss_timer.h" -#include "seq_oss_event.h" -#include -#include -#include -#include - -/* - * common variables - */ -static int maxqlen = SNDRV_SEQ_OSS_MAX_QLEN; -module_param(maxqlen, int, 0444); -MODULE_PARM_DESC(maxqlen, "maximum queue length"); - -static int system_client = -1; /* ALSA sequencer client number */ -static int system_port = -1; - -static int num_clients; -static struct seq_oss_devinfo *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS]; - - -/* - * prototypes - */ -static int receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop); -static int translate_mode(struct file *file); -static int create_port(struct seq_oss_devinfo *dp); -static int delete_port(struct seq_oss_devinfo *dp); -static int alloc_seq_queue(struct seq_oss_devinfo *dp); -static int delete_seq_queue(int queue); -static void free_devinfo(void *private); - -#define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec) - - -/* - * create sequencer client for OSS sequencer - */ -int __init -snd_seq_oss_create_client(void) -{ - int rc; - struct snd_seq_port_info *port; - struct snd_seq_port_callback port_callback; - - port = kmalloc(sizeof(*port), GFP_KERNEL); - if (!port) { - rc = -ENOMEM; - goto __error; - } - - /* create ALSA client */ - rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, - "OSS sequencer"); - if (rc < 0) - goto __error; - - system_client = rc; - debug_printk(("new client = %d\n", rc)); - - /* look up midi devices */ - snd_seq_oss_midi_lookup_ports(system_client); - - /* create annoucement receiver port */ - memset(port, 0, sizeof(*port)); - strcpy(port->name, "Receiver"); - port->addr.client = system_client; - port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */ - port->type = 0; - - memset(&port_callback, 0, sizeof(port_callback)); - /* don't set port_callback.owner here. otherwise the module counter - * is incremented and we can no longer release the module.. - */ - port_callback.event_input = receive_announce; - port->kernel = &port_callback; - - call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port); - if ((system_port = port->addr.port) >= 0) { - struct snd_seq_port_subscribe subs; - - memset(&subs, 0, sizeof(subs)); - subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; - subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; - subs.dest.client = system_client; - subs.dest.port = system_port; - call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs); - } - rc = 0; - - __error: - kfree(port); - return rc; -} - - -/* - * receive annoucement from system port, and check the midi device - */ -static int -receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop) -{ - struct snd_seq_port_info pinfo; - - if (atomic) - return 0; /* it must not happen */ - - switch (ev->type) { - case SNDRV_SEQ_EVENT_PORT_START: - case SNDRV_SEQ_EVENT_PORT_CHANGE: - if (ev->data.addr.client == system_client) - break; /* ignore myself */ - memset(&pinfo, 0, sizeof(pinfo)); - pinfo.addr = ev->data.addr; - if (call_ctl(SNDRV_SEQ_IOCTL_GET_PORT_INFO, &pinfo) >= 0) - snd_seq_oss_midi_check_new_port(&pinfo); - break; - - case SNDRV_SEQ_EVENT_PORT_EXIT: - if (ev->data.addr.client == system_client) - break; /* ignore myself */ - snd_seq_oss_midi_check_exit_port(ev->data.addr.client, - ev->data.addr.port); - break; - } - return 0; -} - - -/* - * delete OSS sequencer client - */ -int -snd_seq_oss_delete_client(void) -{ - if (system_client >= 0) - snd_seq_delete_kernel_client(system_client); - - snd_seq_oss_midi_clear_all(); - - return 0; -} - - -/* - * open sequencer device - */ -int -snd_seq_oss_open(struct file *file, int level) -{ - int i, rc; - struct seq_oss_devinfo *dp; - - dp = kzalloc(sizeof(*dp), GFP_KERNEL); - if (!dp) { - snd_printk(KERN_ERR "can't malloc device info\n"); - return -ENOMEM; - } - debug_printk(("oss_open: dp = %p\n", dp)); - - dp->cseq = system_client; - dp->port = -1; - dp->queue = -1; - - for (i = 0; i < SNDRV_SEQ_OSS_MAX_CLIENTS; i++) { - if (client_table[i] == NULL) - break; - } - - dp->index = i; - if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) { - snd_printk(KERN_ERR "too many applications\n"); - rc = -ENOMEM; - goto _error; - } - - /* look up synth and midi devices */ - snd_seq_oss_synth_setup(dp); - snd_seq_oss_midi_setup(dp); - - if (dp->synth_opened == 0 && dp->max_mididev == 0) { - /* snd_printk(KERN_ERR "no device found\n"); */ - rc = -ENODEV; - goto _error; - } - - /* create port */ - debug_printk(("create new port\n")); - rc = create_port(dp); - if (rc < 0) { - snd_printk(KERN_ERR "can't create port\n"); - goto _error; - } - - /* allocate queue */ - debug_printk(("allocate queue\n")); - rc = alloc_seq_queue(dp); - if (rc < 0) - goto _error; - - /* set address */ - dp->addr.client = dp->cseq; - dp->addr.port = dp->port; - /*dp->addr.queue = dp->queue;*/ - /*dp->addr.channel = 0;*/ - - dp->seq_mode = level; - - /* set up file mode */ - dp->file_mode = translate_mode(file); - - /* initialize read queue */ - debug_printk(("initialize read queue\n")); - if (is_read_mode(dp->file_mode)) { - dp->readq = snd_seq_oss_readq_new(dp, maxqlen); - if (!dp->readq) { - rc = -ENOMEM; - goto _error; - } - } - - /* initialize write queue */ - debug_printk(("initialize write queue\n")); - if (is_write_mode(dp->file_mode)) { - dp->writeq = snd_seq_oss_writeq_new(dp, maxqlen); - if (!dp->writeq) { - rc = -ENOMEM; - goto _error; - } - } - - /* initialize timer */ - debug_printk(("initialize timer\n")); - dp->timer = snd_seq_oss_timer_new(dp); - if (!dp->timer) { - snd_printk(KERN_ERR "can't alloc timer\n"); - rc = -ENOMEM; - goto _error; - } - debug_printk(("timer initialized\n")); - - /* set private data pointer */ - file->private_data = dp; - - /* set up for mode2 */ - if (level == SNDRV_SEQ_OSS_MODE_MUSIC) - snd_seq_oss_synth_setup_midi(dp); - else if (is_read_mode(dp->file_mode)) - snd_seq_oss_midi_open_all(dp, SNDRV_SEQ_OSS_FILE_READ); - - client_table[dp->index] = dp; - num_clients++; - - debug_printk(("open done\n")); - return 0; - - _error: - snd_seq_oss_synth_cleanup(dp); - snd_seq_oss_midi_cleanup(dp); - delete_seq_queue(dp->queue); - delete_port(dp); - - return rc; -} - -/* - * translate file flags to private mode - */ -static int -translate_mode(struct file *file) -{ - int file_mode = 0; - if ((file->f_flags & O_ACCMODE) != O_RDONLY) - file_mode |= SNDRV_SEQ_OSS_FILE_WRITE; - if ((file->f_flags & O_ACCMODE) != O_WRONLY) - file_mode |= SNDRV_SEQ_OSS_FILE_READ; - if (file->f_flags & O_NONBLOCK) - file_mode |= SNDRV_SEQ_OSS_FILE_NONBLOCK; - return file_mode; -} - - -/* - * create sequencer port - */ -static int -create_port(struct seq_oss_devinfo *dp) -{ - int rc; - struct snd_seq_port_info port; - struct snd_seq_port_callback callback; - - memset(&port, 0, sizeof(port)); - port.addr.client = dp->cseq; - sprintf(port.name, "Sequencer-%d", dp->index); - port.capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_WRITE; /* no subscription */ - port.type = SNDRV_SEQ_PORT_TYPE_SPECIFIC; - port.midi_channels = 128; - port.synth_voices = 128; - - memset(&callback, 0, sizeof(callback)); - callback.owner = THIS_MODULE; - callback.private_data = dp; - callback.event_input = snd_seq_oss_event_input; - callback.private_free = free_devinfo; - port.kernel = &callback; - - rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port); - if (rc < 0) - return rc; - - dp->port = port.addr.port; - debug_printk(("new port = %d\n", port.addr.port)); - - return 0; -} - -/* - * delete ALSA port - */ -static int -delete_port(struct seq_oss_devinfo *dp) -{ - if (dp->port < 0) { - kfree(dp); - return 0; - } - - debug_printk(("delete_port %i\n", dp->port)); - return snd_seq_event_port_detach(dp->cseq, dp->port); -} - -/* - * allocate a queue - */ -static int -alloc_seq_queue(struct seq_oss_devinfo *dp) -{ - struct snd_seq_queue_info qinfo; - int rc; - - memset(&qinfo, 0, sizeof(qinfo)); - qinfo.owner = system_client; - qinfo.locked = 1; - strcpy(qinfo.name, "OSS Sequencer Emulation"); - if ((rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo)) < 0) - return rc; - dp->queue = qinfo.queue; - return 0; -} - -/* - * release queue - */ -static int -delete_seq_queue(int queue) -{ - struct snd_seq_queue_info qinfo; - int rc; - - if (queue < 0) - return 0; - memset(&qinfo, 0, sizeof(qinfo)); - qinfo.queue = queue; - rc = call_ctl(SNDRV_SEQ_IOCTL_DELETE_QUEUE, &qinfo); - if (rc < 0) - printk(KERN_ERR "seq-oss: unable to delete queue %d (%d)\n", queue, rc); - return rc; -} - - -/* - * free device informations - private_free callback of port - */ -static void -free_devinfo(void *private) -{ - struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private; - - if (dp->timer) - snd_seq_oss_timer_delete(dp->timer); - - if (dp->writeq) - snd_seq_oss_writeq_delete(dp->writeq); - - if (dp->readq) - snd_seq_oss_readq_delete(dp->readq); - - kfree(dp); -} - - -/* - * close sequencer device - */ -void -snd_seq_oss_release(struct seq_oss_devinfo *dp) -{ - int queue; - - client_table[dp->index] = NULL; - num_clients--; - - debug_printk(("resetting..\n")); - snd_seq_oss_reset(dp); - - debug_printk(("cleaning up..\n")); - snd_seq_oss_synth_cleanup(dp); - snd_seq_oss_midi_cleanup(dp); - - /* clear slot */ - debug_printk(("releasing resource..\n")); - queue = dp->queue; - if (dp->port >= 0) - delete_port(dp); - delete_seq_queue(queue); - - debug_printk(("release done\n")); -} - - -/* - * Wait until the queue is empty (if we don't have nonblock) - */ -void -snd_seq_oss_drain_write(struct seq_oss_devinfo *dp) -{ - if (! dp->timer->running) - return; - if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) && - dp->writeq) { - debug_printk(("syncing..\n")); - while (snd_seq_oss_writeq_sync(dp->writeq)) - ; - } -} - - -/* - * reset sequencer devices - */ -void -snd_seq_oss_reset(struct seq_oss_devinfo *dp) -{ - int i; - - /* reset all synth devices */ - for (i = 0; i < dp->max_synthdev; i++) - snd_seq_oss_synth_reset(dp, i); - - /* reset all midi devices */ - if (dp->seq_mode != SNDRV_SEQ_OSS_MODE_MUSIC) { - for (i = 0; i < dp->max_mididev; i++) - snd_seq_oss_midi_reset(dp, i); - } - - /* remove queues */ - if (dp->readq) - snd_seq_oss_readq_clear(dp->readq); - if (dp->writeq) - snd_seq_oss_writeq_clear(dp->writeq); - - /* reset timer */ - snd_seq_oss_timer_stop(dp->timer); -} - - -#ifdef CONFIG_PROC_FS -/* - * misc. functions for proc interface - */ -char * -enabled_str(int bool) -{ - return bool ? "enabled" : "disabled"; -} - -static char * -filemode_str(int val) -{ - static char *str[] = { - "none", "read", "write", "read/write", - }; - return str[val & SNDRV_SEQ_OSS_FILE_ACMODE]; -} - - -/* - * proc interface - */ -void -snd_seq_oss_system_info_read(struct snd_info_buffer *buf) -{ - int i; - struct seq_oss_devinfo *dp; - - snd_iprintf(buf, "ALSA client number %d\n", system_client); - snd_iprintf(buf, "ALSA receiver port %d\n", system_port); - - snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients); - for (i = 0; i < num_clients; i++) { - snd_iprintf(buf, "\nApplication %d: ", i); - if ((dp = client_table[i]) == NULL) { - snd_iprintf(buf, "*empty*\n"); - continue; - } - snd_iprintf(buf, "port %d : queue %d\n", dp->port, dp->queue); - snd_iprintf(buf, " sequencer mode = %s : file open mode = %s\n", - (dp->seq_mode ? "music" : "synth"), - filemode_str(dp->file_mode)); - if (dp->seq_mode) - snd_iprintf(buf, " timer tempo = %d, timebase = %d\n", - dp->timer->oss_tempo, dp->timer->oss_timebase); - snd_iprintf(buf, " max queue length %d\n", maxqlen); - if (is_read_mode(dp->file_mode) && dp->readq) - snd_seq_oss_readq_info_read(dp->readq, buf); - } -} -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c deleted file mode 100644 index 5ac701c9..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_ioctl.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * OSS compatible i/o control - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_device.h" -#include "seq_oss_readq.h" -#include "seq_oss_writeq.h" -#include "seq_oss_timer.h" -#include "seq_oss_synth.h" -#include "seq_oss_midi.h" -#include "seq_oss_event.h" - -static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg) -{ - struct synth_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0) - return -EINVAL; - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int snd_seq_oss_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg) -{ - struct midi_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0) - return -EINVAL; - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg) -{ - unsigned char ev[8]; - struct snd_seq_event tmpev; - - if (copy_from_user(ev, arg, 8)) - return -EFAULT; - memset(&tmpev, 0, sizeof(tmpev)); - snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client); - tmpev.time.tick = 0; - if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) { - snd_seq_oss_dispatch(dp, &tmpev, 0, 0); - } - return 0; -} - -int -snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg) -{ - int dev, val; - void __user *arg = (void __user *)carg; - int __user *p = arg; - - switch (cmd) { - case SNDCTL_TMR_TIMEBASE: - case SNDCTL_TMR_TEMPO: - case SNDCTL_TMR_START: - case SNDCTL_TMR_STOP: - case SNDCTL_TMR_CONTINUE: - case SNDCTL_TMR_METRONOME: - case SNDCTL_TMR_SOURCE: - case SNDCTL_TMR_SELECT: - case SNDCTL_SEQ_CTRLRATE: - return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg); - - case SNDCTL_SEQ_PANIC: - debug_printk(("panic\n")); - snd_seq_oss_reset(dp); - return -EINVAL; - - case SNDCTL_SEQ_SYNC: - debug_printk(("sync\n")); - if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) - return 0; - while (snd_seq_oss_writeq_sync(dp->writeq)) - ; - if (signal_pending(current)) - return -ERESTARTSYS; - return 0; - - case SNDCTL_SEQ_RESET: - debug_printk(("reset\n")); - snd_seq_oss_reset(dp); - return 0; - - case SNDCTL_SEQ_TESTMIDI: - debug_printk(("test midi\n")); - if (get_user(dev, p)) - return -EFAULT; - return snd_seq_oss_midi_open(dp, dev, dp->file_mode); - - case SNDCTL_SEQ_GETINCOUNT: - debug_printk(("get in count\n")); - if (dp->readq == NULL || ! is_read_mode(dp->file_mode)) - return 0; - return put_user(dp->readq->qlen, p) ? -EFAULT : 0; - - case SNDCTL_SEQ_GETOUTCOUNT: - debug_printk(("get out count\n")); - if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) - return 0; - return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0; - - case SNDCTL_SEQ_GETTIME: - debug_printk(("get time\n")); - return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0; - - case SNDCTL_SEQ_RESETSAMPLES: - debug_printk(("reset samples\n")); - if (get_user(dev, p)) - return -EFAULT; - return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); - - case SNDCTL_SEQ_NRSYNTHS: - debug_printk(("nr synths\n")); - return put_user(dp->max_synthdev, p) ? -EFAULT : 0; - - case SNDCTL_SEQ_NRMIDIS: - debug_printk(("nr midis\n")); - return put_user(dp->max_mididev, p) ? -EFAULT : 0; - - case SNDCTL_SYNTH_MEMAVL: - debug_printk(("mem avail\n")); - if (get_user(dev, p)) - return -EFAULT; - val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); - return put_user(val, p) ? -EFAULT : 0; - - case SNDCTL_FM_4OP_ENABLE: - debug_printk(("4op\n")); - if (get_user(dev, p)) - return -EFAULT; - snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); - return 0; - - case SNDCTL_SYNTH_INFO: - case SNDCTL_SYNTH_ID: - debug_printk(("synth info\n")); - return snd_seq_oss_synth_info_user(dp, arg); - - case SNDCTL_SEQ_OUTOFBAND: - debug_printk(("out of band\n")); - return snd_seq_oss_oob_user(dp, arg); - - case SNDCTL_MIDI_INFO: - debug_printk(("midi info\n")); - return snd_seq_oss_midi_info_user(dp, arg); - - case SNDCTL_SEQ_THRESHOLD: - debug_printk(("threshold\n")); - if (! is_write_mode(dp->file_mode)) - return 0; - if (get_user(val, p)) - return -EFAULT; - if (val < 1) - val = 1; - if (val >= dp->writeq->maxlen) - val = dp->writeq->maxlen - 1; - snd_seq_oss_writeq_set_output(dp->writeq, val); - return 0; - - case SNDCTL_MIDI_PRETIME: - debug_printk(("pretime\n")); - if (dp->readq == NULL || !is_read_mode(dp->file_mode)) - return 0; - if (get_user(val, p)) - return -EFAULT; - if (val <= 0) - val = -1; - else - val = (HZ * val) / 10; - dp->readq->pre_event_timeout = val; - return put_user(val, p) ? -EFAULT : 0; - - default: - debug_printk(("others\n")); - if (! is_write_mode(dp->file_mode)) - return -EIO; - return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg); - } - return 0; -} - diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c deleted file mode 100644 index 677dc845..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * MIDI device handlers - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_midi.h" -#include "seq_oss_readq.h" -#include "seq_oss_timer.h" -#include "seq_oss_event.h" -#include -#include "../seq_lock.h" -#include -#include - - -/* - * constants - */ -#define SNDRV_SEQ_OSS_MAX_MIDI_NAME 30 - -/* - * definition of midi device record - */ -struct seq_oss_midi { - int seq_device; /* device number */ - int client; /* sequencer client number */ - int port; /* sequencer port number */ - unsigned int flags; /* port capability */ - int opened; /* flag for opening */ - unsigned char name[SNDRV_SEQ_OSS_MAX_MIDI_NAME]; - struct snd_midi_event *coder; /* MIDI event coder */ - struct seq_oss_devinfo *devinfo; /* assigned OSSseq device */ - snd_use_lock_t use_lock; -}; - - -/* - * midi device table - */ -static int max_midi_devs; -static struct seq_oss_midi *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS]; - -static DEFINE_SPINLOCK(register_lock); - -/* - * prototypes - */ -static struct seq_oss_midi *get_mdev(int dev); -static struct seq_oss_midi *get_mididev(struct seq_oss_devinfo *dp, int dev); -static int send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev); -static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev); - -/* - * look up the existing ports - * this looks a very exhausting job. - */ -int __init -snd_seq_oss_midi_lookup_ports(int client) -{ - struct snd_seq_client_info *clinfo; - struct snd_seq_port_info *pinfo; - - clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL); - pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL); - if (! clinfo || ! pinfo) { - kfree(clinfo); - kfree(pinfo); - return -ENOMEM; - } - clinfo->client = -1; - while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) { - if (clinfo->client == client) - continue; /* ignore myself */ - pinfo->addr.client = clinfo->client; - pinfo->addr.port = -1; - while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0) - snd_seq_oss_midi_check_new_port(pinfo); - } - kfree(clinfo); - kfree(pinfo); - return 0; -} - - -/* - */ -static struct seq_oss_midi * -get_mdev(int dev) -{ - struct seq_oss_midi *mdev; - unsigned long flags; - - spin_lock_irqsave(®ister_lock, flags); - mdev = midi_devs[dev]; - if (mdev) - snd_use_lock_use(&mdev->use_lock); - spin_unlock_irqrestore(®ister_lock, flags); - return mdev; -} - -/* - * look for the identical slot - */ -static struct seq_oss_midi * -find_slot(int client, int port) -{ - int i; - struct seq_oss_midi *mdev; - unsigned long flags; - - spin_lock_irqsave(®ister_lock, flags); - for (i = 0; i < max_midi_devs; i++) { - mdev = midi_devs[i]; - if (mdev && mdev->client == client && mdev->port == port) { - /* found! */ - snd_use_lock_use(&mdev->use_lock); - spin_unlock_irqrestore(®ister_lock, flags); - return mdev; - } - } - spin_unlock_irqrestore(®ister_lock, flags); - return NULL; -} - - -#define PERM_WRITE (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE) -#define PERM_READ (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ) -/* - * register a new port if it doesn't exist yet - */ -int -snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) -{ - int i; - struct seq_oss_midi *mdev; - unsigned long flags; - - debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port)); - /* the port must include generic midi */ - if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC)) - return 0; - /* either read or write subscribable */ - if ((pinfo->capability & PERM_WRITE) != PERM_WRITE && - (pinfo->capability & PERM_READ) != PERM_READ) - return 0; - - /* - * look for the identical slot - */ - if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) { - /* already exists */ - snd_use_lock_free(&mdev->use_lock); - return 0; - } - - /* - * allocate midi info record - */ - if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "can't malloc midi info\n"); - return -ENOMEM; - } - - /* copy the port information */ - mdev->client = pinfo->addr.client; - mdev->port = pinfo->addr.port; - mdev->flags = pinfo->capability; - mdev->opened = 0; - snd_use_lock_init(&mdev->use_lock); - - /* copy and truncate the name of synth device */ - strlcpy(mdev->name, pinfo->name, sizeof(mdev->name)); - - /* create MIDI coder */ - if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) { - snd_printk(KERN_ERR "can't malloc midi coder\n"); - kfree(mdev); - return -ENOMEM; - } - /* OSS sequencer adds running status to all sequences */ - snd_midi_event_no_status(mdev->coder, 1); - - /* - * look for en empty slot - */ - spin_lock_irqsave(®ister_lock, flags); - for (i = 0; i < max_midi_devs; i++) { - if (midi_devs[i] == NULL) - break; - } - if (i >= max_midi_devs) { - if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) { - spin_unlock_irqrestore(®ister_lock, flags); - snd_midi_event_free(mdev->coder); - kfree(mdev); - return -ENOMEM; - } - max_midi_devs++; - } - mdev->seq_device = i; - midi_devs[mdev->seq_device] = mdev; - spin_unlock_irqrestore(®ister_lock, flags); - - return 0; -} - -/* - * release the midi device if it was registered - */ -int -snd_seq_oss_midi_check_exit_port(int client, int port) -{ - struct seq_oss_midi *mdev; - unsigned long flags; - int index; - - if ((mdev = find_slot(client, port)) != NULL) { - spin_lock_irqsave(®ister_lock, flags); - midi_devs[mdev->seq_device] = NULL; - spin_unlock_irqrestore(®ister_lock, flags); - snd_use_lock_free(&mdev->use_lock); - snd_use_lock_sync(&mdev->use_lock); - if (mdev->coder) - snd_midi_event_free(mdev->coder); - kfree(mdev); - } - spin_lock_irqsave(®ister_lock, flags); - for (index = max_midi_devs - 1; index >= 0; index--) { - if (midi_devs[index]) - break; - } - max_midi_devs = index + 1; - spin_unlock_irqrestore(®ister_lock, flags); - return 0; -} - - -/* - * release the midi device if it was registered - */ -void -snd_seq_oss_midi_clear_all(void) -{ - int i; - struct seq_oss_midi *mdev; - unsigned long flags; - - spin_lock_irqsave(®ister_lock, flags); - for (i = 0; i < max_midi_devs; i++) { - if ((mdev = midi_devs[i]) != NULL) { - if (mdev->coder) - snd_midi_event_free(mdev->coder); - kfree(mdev); - midi_devs[i] = NULL; - } - } - max_midi_devs = 0; - spin_unlock_irqrestore(®ister_lock, flags); -} - - -/* - * set up midi tables - */ -void -snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp) -{ - dp->max_mididev = max_midi_devs; -} - -/* - * clean up midi tables - */ -void -snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp) -{ - int i; - for (i = 0; i < dp->max_mididev; i++) - snd_seq_oss_midi_close(dp, i); - dp->max_mididev = 0; -} - - -/* - * open all midi devices. ignore errors. - */ -void -snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode) -{ - int i; - for (i = 0; i < dp->max_mididev; i++) - snd_seq_oss_midi_open(dp, i, file_mode); -} - - -/* - * get the midi device information - */ -static struct seq_oss_midi * -get_mididev(struct seq_oss_devinfo *dp, int dev) -{ - if (dev < 0 || dev >= dp->max_mididev) - return NULL; - return get_mdev(dev); -} - - -/* - * open the midi device if not opened yet - */ -int -snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode) -{ - int perm; - struct seq_oss_midi *mdev; - struct snd_seq_port_subscribe subs; - - if ((mdev = get_mididev(dp, dev)) == NULL) - return -ENODEV; - - /* already used? */ - if (mdev->opened && mdev->devinfo != dp) { - snd_use_lock_free(&mdev->use_lock); - return -EBUSY; - } - - perm = 0; - if (is_write_mode(fmode)) - perm |= PERM_WRITE; - if (is_read_mode(fmode)) - perm |= PERM_READ; - perm &= mdev->flags; - if (perm == 0) { - snd_use_lock_free(&mdev->use_lock); - return -ENXIO; - } - - /* already opened? */ - if ((mdev->opened & perm) == perm) { - snd_use_lock_free(&mdev->use_lock); - return 0; - } - - perm &= ~mdev->opened; - - memset(&subs, 0, sizeof(subs)); - - if (perm & PERM_WRITE) { - subs.sender = dp->addr; - subs.dest.client = mdev->client; - subs.dest.port = mdev->port; - if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0) - mdev->opened |= PERM_WRITE; - } - if (perm & PERM_READ) { - subs.sender.client = mdev->client; - subs.sender.port = mdev->port; - subs.dest = dp->addr; - subs.flags = SNDRV_SEQ_PORT_SUBS_TIMESTAMP; - subs.queue = dp->queue; /* queue for timestamps */ - if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0) - mdev->opened |= PERM_READ; - } - - if (! mdev->opened) { - snd_use_lock_free(&mdev->use_lock); - return -ENXIO; - } - - mdev->devinfo = dp; - snd_use_lock_free(&mdev->use_lock); - return 0; -} - -/* - * close the midi device if already opened - */ -int -snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev) -{ - struct seq_oss_midi *mdev; - struct snd_seq_port_subscribe subs; - - if ((mdev = get_mididev(dp, dev)) == NULL) - return -ENODEV; - if (! mdev->opened || mdev->devinfo != dp) { - snd_use_lock_free(&mdev->use_lock); - return 0; - } - - debug_printk(("closing client %d port %d mode %d\n", mdev->client, mdev->port, mdev->opened)); - memset(&subs, 0, sizeof(subs)); - if (mdev->opened & PERM_WRITE) { - subs.sender = dp->addr; - subs.dest.client = mdev->client; - subs.dest.port = mdev->port; - snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs); - } - if (mdev->opened & PERM_READ) { - subs.sender.client = mdev->client; - subs.sender.port = mdev->port; - subs.dest = dp->addr; - snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs); - } - - mdev->opened = 0; - mdev->devinfo = NULL; - - snd_use_lock_free(&mdev->use_lock); - return 0; -} - -/* - * change seq capability flags to file mode flags - */ -int -snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev) -{ - struct seq_oss_midi *mdev; - int mode; - - if ((mdev = get_mididev(dp, dev)) == NULL) - return 0; - - mode = 0; - if (mdev->opened & PERM_WRITE) - mode |= SNDRV_SEQ_OSS_FILE_WRITE; - if (mdev->opened & PERM_READ) - mode |= SNDRV_SEQ_OSS_FILE_READ; - - snd_use_lock_free(&mdev->use_lock); - return mode; -} - -/* - * reset the midi device and close it: - * so far, only close the device. - */ -void -snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) -{ - struct seq_oss_midi *mdev; - - if ((mdev = get_mididev(dp, dev)) == NULL) - return; - if (! mdev->opened) { - snd_use_lock_free(&mdev->use_lock); - return; - } - - if (mdev->opened & PERM_WRITE) { - struct snd_seq_event ev; - int c; - - debug_printk(("resetting client %d port %d\n", mdev->client, mdev->port)); - memset(&ev, 0, sizeof(ev)); - ev.dest.client = mdev->client; - ev.dest.port = mdev->port; - ev.queue = dp->queue; - ev.source.port = dp->port; - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) { - ev.type = SNDRV_SEQ_EVENT_SENSING; - snd_seq_oss_dispatch(dp, &ev, 0, 0); - } - for (c = 0; c < 16; c++) { - ev.type = SNDRV_SEQ_EVENT_CONTROLLER; - ev.data.control.channel = c; - ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF; - snd_seq_oss_dispatch(dp, &ev, 0, 0); - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) { - ev.data.control.param = - MIDI_CTL_RESET_CONTROLLERS; - snd_seq_oss_dispatch(dp, &ev, 0, 0); - ev.type = SNDRV_SEQ_EVENT_PITCHBEND; - ev.data.control.value = 0; - snd_seq_oss_dispatch(dp, &ev, 0, 0); - } - } - } - // snd_seq_oss_midi_close(dp, dev); - snd_use_lock_free(&mdev->use_lock); -} - - -/* - * get client/port of the specified MIDI device - */ -void -snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr) -{ - struct seq_oss_midi *mdev; - - if ((mdev = get_mididev(dp, dev)) == NULL) - return; - addr->client = mdev->client; - addr->port = mdev->port; - snd_use_lock_free(&mdev->use_lock); -} - - -/* - * input callback - this can be atomic - */ -int -snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data) -{ - struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data; - struct seq_oss_midi *mdev; - int rc; - - if (dp->readq == NULL) - return 0; - if ((mdev = find_slot(ev->source.client, ev->source.port)) == NULL) - return 0; - if (! (mdev->opened & PERM_READ)) { - snd_use_lock_free(&mdev->use_lock); - return 0; - } - - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) - rc = send_synth_event(dp, ev, mdev->seq_device); - else - rc = send_midi_event(dp, ev, mdev); - - snd_use_lock_free(&mdev->use_lock); - return rc; -} - -/* - * convert ALSA sequencer event to OSS synth event - */ -static int -send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev) -{ - union evrec ossev; - - memset(&ossev, 0, sizeof(ossev)); - - switch (ev->type) { - case SNDRV_SEQ_EVENT_NOTEON: - ossev.v.cmd = MIDI_NOTEON; break; - case SNDRV_SEQ_EVENT_NOTEOFF: - ossev.v.cmd = MIDI_NOTEOFF; break; - case SNDRV_SEQ_EVENT_KEYPRESS: - ossev.v.cmd = MIDI_KEY_PRESSURE; break; - case SNDRV_SEQ_EVENT_CONTROLLER: - ossev.l.cmd = MIDI_CTL_CHANGE; break; - case SNDRV_SEQ_EVENT_PGMCHANGE: - ossev.l.cmd = MIDI_PGM_CHANGE; break; - case SNDRV_SEQ_EVENT_CHANPRESS: - ossev.l.cmd = MIDI_CHN_PRESSURE; break; - case SNDRV_SEQ_EVENT_PITCHBEND: - ossev.l.cmd = MIDI_PITCH_BEND; break; - default: - return 0; /* not supported */ - } - - ossev.v.dev = dev; - - switch (ev->type) { - case SNDRV_SEQ_EVENT_NOTEON: - case SNDRV_SEQ_EVENT_NOTEOFF: - case SNDRV_SEQ_EVENT_KEYPRESS: - ossev.v.code = EV_CHN_VOICE; - ossev.v.note = ev->data.note.note; - ossev.v.parm = ev->data.note.velocity; - ossev.v.chn = ev->data.note.channel; - break; - case SNDRV_SEQ_EVENT_CONTROLLER: - case SNDRV_SEQ_EVENT_PGMCHANGE: - case SNDRV_SEQ_EVENT_CHANPRESS: - ossev.l.code = EV_CHN_COMMON; - ossev.l.p1 = ev->data.control.param; - ossev.l.val = ev->data.control.value; - ossev.l.chn = ev->data.control.channel; - break; - case SNDRV_SEQ_EVENT_PITCHBEND: - ossev.l.code = EV_CHN_COMMON; - ossev.l.val = ev->data.control.value + 8192; - ossev.l.chn = ev->data.control.channel; - break; - } - - snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode); - snd_seq_oss_readq_put_event(dp->readq, &ossev); - - return 0; -} - -/* - * decode event and send MIDI bytes to read queue - */ -static int -send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev) -{ - char msg[32]; - int len; - - snd_seq_oss_readq_put_timestamp(dp->readq, ev->time.tick, dp->seq_mode); - if (!dp->timer->running) - len = snd_seq_oss_timer_start(dp->timer); - if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { - if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE) - snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, - ev->data.ext.ptr, ev->data.ext.len); - } else { - len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev); - if (len > 0) - snd_seq_oss_readq_puts(dp->readq, mdev->seq_device, msg, len); - } - - return 0; -} - - -/* - * dump midi data - * return 0 : enqueued - * non-zero : invalid - ignored - */ -int -snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev) -{ - struct seq_oss_midi *mdev; - - if ((mdev = get_mididev(dp, dev)) == NULL) - return -ENODEV; - if (snd_midi_event_encode_byte(mdev->coder, c, ev) > 0) { - snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port); - snd_use_lock_free(&mdev->use_lock); - return 0; - } - snd_use_lock_free(&mdev->use_lock); - return -EINVAL; -} - -/* - * create OSS compatible midi_info record - */ -int -snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf) -{ - struct seq_oss_midi *mdev; - - if ((mdev = get_mididev(dp, dev)) == NULL) - return -ENXIO; - inf->device = dev; - inf->dev_type = 0; /* FIXME: ?? */ - inf->capabilities = 0; /* FIXME: ?? */ - strlcpy(inf->name, mdev->name, sizeof(inf->name)); - snd_use_lock_free(&mdev->use_lock); - return 0; -} - - -#ifdef CONFIG_PROC_FS -/* - * proc interface - */ -static char * -capmode_str(int val) -{ - val &= PERM_READ|PERM_WRITE; - if (val == (PERM_READ|PERM_WRITE)) - return "read/write"; - else if (val == PERM_READ) - return "read"; - else if (val == PERM_WRITE) - return "write"; - else - return "none"; -} - -void -snd_seq_oss_midi_info_read(struct snd_info_buffer *buf) -{ - int i; - struct seq_oss_midi *mdev; - - snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs); - for (i = 0; i < max_midi_devs; i++) { - snd_iprintf(buf, "\nmidi %d: ", i); - mdev = get_mdev(i); - if (mdev == NULL) { - snd_iprintf(buf, "*empty*\n"); - continue; - } - snd_iprintf(buf, "[%s] ALSA port %d:%d\n", mdev->name, - mdev->client, mdev->port); - snd_iprintf(buf, " capability %s / opened %s\n", - capmode_str(mdev->flags), - capmode_str(mdev->opened)); - snd_use_lock_free(&mdev->use_lock); - } -} -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h deleted file mode 100644 index 84eb866b..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_midi.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * midi device information - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 - */ - -#ifndef __SEQ_OSS_MIDI_H -#define __SEQ_OSS_MIDI_H - -#include "seq_oss_device.h" -#include - -int snd_seq_oss_midi_lookup_ports(int client); -int snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo); -int snd_seq_oss_midi_check_exit_port(int client, int port); -void snd_seq_oss_midi_clear_all(void); - -void snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp); -void snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp); - -int snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int file_mode); -void snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode); -int snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev); -void snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev); -int snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, - struct snd_seq_event *ev); -int snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private); -int snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev); -int snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf); -void snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr); - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c deleted file mode 100644 index 73661c4a..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * seq_oss_readq.c - MIDI input queue - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_readq.h" -#include "seq_oss_event.h" -#include -#include "../seq_lock.h" -#include -#include - -/* - * constants - */ -//#define SNDRV_SEQ_OSS_MAX_TIMEOUT (unsigned long)(-1) -#define SNDRV_SEQ_OSS_MAX_TIMEOUT (HZ * 3600) - - -/* - * prototypes - */ - - -/* - * create a read queue - */ -struct seq_oss_readq * -snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen) -{ - struct seq_oss_readq *q; - - if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "can't malloc read queue\n"); - return NULL; - } - - if ((q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "can't malloc read queue buffer\n"); - kfree(q); - return NULL; - } - - q->maxlen = maxlen; - q->qlen = 0; - q->head = q->tail = 0; - init_waitqueue_head(&q->midi_sleep); - spin_lock_init(&q->lock); - q->pre_event_timeout = SNDRV_SEQ_OSS_MAX_TIMEOUT; - q->input_time = (unsigned long)-1; - - return q; -} - -/* - * delete the read queue - */ -void -snd_seq_oss_readq_delete(struct seq_oss_readq *q) -{ - if (q) { - kfree(q->q); - kfree(q); - } -} - -/* - * reset the read queue - */ -void -snd_seq_oss_readq_clear(struct seq_oss_readq *q) -{ - if (q->qlen) { - q->qlen = 0; - q->head = q->tail = 0; - } - /* if someone sleeping, wake'em up */ - if (waitqueue_active(&q->midi_sleep)) - wake_up(&q->midi_sleep); - q->input_time = (unsigned long)-1; -} - -/* - * put a midi byte - */ -int -snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, int len) -{ - union evrec rec; - int result; - - memset(&rec, 0, sizeof(rec)); - rec.c[0] = SEQ_MIDIPUTC; - rec.c[2] = dev; - - while (len-- > 0) { - rec.c[1] = *data++; - result = snd_seq_oss_readq_put_event(q, &rec); - if (result < 0) - return result; - } - return 0; -} - -/* - * copy an event to input queue: - * return zero if enqueued - */ -int -snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev) -{ - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - if (q->qlen >= q->maxlen - 1) { - spin_unlock_irqrestore(&q->lock, flags); - return -ENOMEM; - } - - memcpy(&q->q[q->tail], ev, sizeof(*ev)); - q->tail = (q->tail + 1) % q->maxlen; - q->qlen++; - - /* wake up sleeper */ - if (waitqueue_active(&q->midi_sleep)) - wake_up(&q->midi_sleep); - - spin_unlock_irqrestore(&q->lock, flags); - - return 0; -} - - -/* - * pop queue - * caller must hold lock - */ -int -snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec) -{ - if (q->qlen == 0) - return -EAGAIN; - memcpy(rec, &q->q[q->head], sizeof(*rec)); - return 0; -} - -/* - * sleep until ready - */ -void -snd_seq_oss_readq_wait(struct seq_oss_readq *q) -{ - wait_event_interruptible_timeout(q->midi_sleep, - (q->qlen > 0 || q->head == q->tail), - q->pre_event_timeout); -} - -/* - * drain one record - * caller must hold lock - */ -void -snd_seq_oss_readq_free(struct seq_oss_readq *q) -{ - if (q->qlen > 0) { - q->head = (q->head + 1) % q->maxlen; - q->qlen--; - } -} - -/* - * polling/select: - * return non-zero if readq is not empty. - */ -unsigned int -snd_seq_oss_readq_poll(struct seq_oss_readq *q, struct file *file, poll_table *wait) -{ - poll_wait(file, &q->midi_sleep, wait); - return q->qlen; -} - -/* - * put a timestamp - */ -int -snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int seq_mode) -{ - if (curt != q->input_time) { - union evrec rec; - memset(&rec, 0, sizeof(rec)); - switch (seq_mode) { - case SNDRV_SEQ_OSS_MODE_SYNTH: - rec.echo = (curt << 8) | SEQ_WAIT; - snd_seq_oss_readq_put_event(q, &rec); - break; - case SNDRV_SEQ_OSS_MODE_MUSIC: - rec.t.code = EV_TIMING; - rec.t.cmd = TMR_WAIT_ABS; - rec.t.time = curt; - snd_seq_oss_readq_put_event(q, &rec); - break; - } - q->input_time = curt; - } - return 0; -} - - -#ifdef CONFIG_PROC_FS -/* - * proc interface - */ -void -snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf) -{ - snd_iprintf(buf, " read queue [%s] length = %d : tick = %ld\n", - (waitqueue_active(&q->midi_sleep) ? "sleeping":"running"), - q->qlen, q->input_time); -} -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h deleted file mode 100644 index f1463f1f..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_readq.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * OSS compatible sequencer driver - * read fifo queue - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 - */ - -#ifndef __SEQ_OSS_READQ_H -#define __SEQ_OSS_READQ_H - -#include "seq_oss_device.h" - - -/* - * definition of read queue - */ -struct seq_oss_readq { - union evrec *q; - int qlen; - int maxlen; - int head, tail; - unsigned long pre_event_timeout; - unsigned long input_time; - wait_queue_head_t midi_sleep; - spinlock_t lock; -}; - -struct seq_oss_readq *snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen); -void snd_seq_oss_readq_delete(struct seq_oss_readq *q); -void snd_seq_oss_readq_clear(struct seq_oss_readq *readq); -unsigned int snd_seq_oss_readq_poll(struct seq_oss_readq *readq, struct file *file, poll_table *wait); -int snd_seq_oss_readq_puts(struct seq_oss_readq *readq, int dev, unsigned char *data, int len); -int snd_seq_oss_readq_put_event(struct seq_oss_readq *readq, union evrec *ev); -int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *readq, unsigned long curt, int seq_mode); -int snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec); -void snd_seq_oss_readq_wait(struct seq_oss_readq *q); -void snd_seq_oss_readq_free(struct seq_oss_readq *q); - -#define snd_seq_oss_readq_lock(q, flags) spin_lock_irqsave(&(q)->lock, flags) -#define snd_seq_oss_readq_unlock(q, flags) spin_unlock_irqrestore(&(q)->lock, flags) - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c deleted file mode 100644 index 6a7b6ace..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_rw.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * read/write/select interface to device file - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_device.h" -#include "seq_oss_readq.h" -#include "seq_oss_writeq.h" -#include "seq_oss_synth.h" -#include -#include "seq_oss_event.h" -#include "seq_oss_timer.h" -#include "../seq_clientmgr.h" - - -/* - * protoypes - */ -static int insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt); - - -/* - * read interface - */ - -int -snd_seq_oss_read(struct seq_oss_devinfo *dp, char __user *buf, int count) -{ - struct seq_oss_readq *readq = dp->readq; - int result = 0, err = 0; - int ev_len; - union evrec rec; - unsigned long flags; - - if (readq == NULL || ! is_read_mode(dp->file_mode)) - return -ENXIO; - - while (count >= SHORT_EVENT_SIZE) { - snd_seq_oss_readq_lock(readq, flags); - err = snd_seq_oss_readq_pick(readq, &rec); - if (err == -EAGAIN && - !is_nonblock_mode(dp->file_mode) && result == 0) { - snd_seq_oss_readq_unlock(readq, flags); - snd_seq_oss_readq_wait(readq); - snd_seq_oss_readq_lock(readq, flags); - if (signal_pending(current)) - err = -ERESTARTSYS; - else - err = snd_seq_oss_readq_pick(readq, &rec); - } - if (err < 0) { - snd_seq_oss_readq_unlock(readq, flags); - break; - } - ev_len = ev_length(&rec); - if (ev_len < count) { - snd_seq_oss_readq_unlock(readq, flags); - break; - } - snd_seq_oss_readq_free(readq); - snd_seq_oss_readq_unlock(readq, flags); - if (copy_to_user(buf, &rec, ev_len)) { - err = -EFAULT; - break; - } - result += ev_len; - buf += ev_len; - count -= ev_len; - } - return result > 0 ? result : err; -} - - -/* - * write interface - */ - -int -snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, struct file *opt) -{ - int result = 0, err = 0; - int ev_size, fmt; - union evrec rec; - - if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) - return -ENXIO; - - while (count >= SHORT_EVENT_SIZE) { - if (copy_from_user(&rec, buf, SHORT_EVENT_SIZE)) { - err = -EFAULT; - break; - } - if (rec.s.code == SEQ_FULLSIZE) { - /* load patch */ - if (result > 0) { - err = -EINVAL; - break; - } - fmt = (*(unsigned short *)rec.c) & 0xffff; - /* FIXME the return value isn't correct */ - return snd_seq_oss_synth_load_patch(dp, rec.s.dev, - fmt, buf, 0, count); - } - if (ev_is_long(&rec)) { - /* extended code */ - if (rec.s.code == SEQ_EXTENDED && - dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) { - err = -EINVAL; - break; - } - ev_size = LONG_EVENT_SIZE; - if (count < ev_size) - break; - /* copy the reset 4 bytes */ - if (copy_from_user(rec.c + SHORT_EVENT_SIZE, - buf + SHORT_EVENT_SIZE, - LONG_EVENT_SIZE - SHORT_EVENT_SIZE)) { - err = -EFAULT; - break; - } - } else { - /* old-type code */ - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) { - err = -EINVAL; - break; - } - ev_size = SHORT_EVENT_SIZE; - } - - /* insert queue */ - if ((err = insert_queue(dp, &rec, opt)) < 0) - break; - - result += ev_size; - buf += ev_size; - count -= ev_size; - } - return result > 0 ? result : err; -} - - -/* - * insert event record to write queue - * return: 0 = OK, non-zero = NG - */ -static int -insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt) -{ - int rc = 0; - struct snd_seq_event event; - - /* if this is a timing event, process the current time */ - if (snd_seq_oss_process_timer_event(dp->timer, rec)) - return 0; /* no need to insert queue */ - - /* parse this event */ - memset(&event, 0, sizeof(event)); - /* set dummy -- to be sure */ - event.type = SNDRV_SEQ_EVENT_NOTEOFF; - snd_seq_oss_fill_addr(dp, &event, dp->addr.port, dp->addr.client); - - if (snd_seq_oss_process_event(dp, rec, &event)) - return 0; /* invalid event - no need to insert queue */ - - event.time.tick = snd_seq_oss_timer_cur_tick(dp->timer); - if (dp->timer->realtime || !dp->timer->running) { - snd_seq_oss_dispatch(dp, &event, 0, 0); - } else { - if (is_nonblock_mode(dp->file_mode)) - rc = snd_seq_kernel_client_enqueue(dp->cseq, &event, 0, 0); - else - rc = snd_seq_kernel_client_enqueue_blocking(dp->cseq, &event, opt, 0, 0); - } - return rc; -} - - -/* - * select / poll - */ - -unsigned int -snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait) -{ - unsigned int mask = 0; - - /* input */ - if (dp->readq && is_read_mode(dp->file_mode)) { - if (snd_seq_oss_readq_poll(dp->readq, file, wait)) - mask |= POLLIN | POLLRDNORM; - } - - /* output */ - if (dp->writeq && is_write_mode(dp->file_mode)) { - if (snd_seq_kernel_client_write_poll(dp->cseq, file, wait)) - mask |= POLLOUT | POLLWRNORM; - } - return mask; -} diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c deleted file mode 100644 index c5b773a1..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * synth device handlers - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_synth.h" -#include "seq_oss_midi.h" -#include "../seq_lock.h" -#include -#include -#include - -/* - * constants - */ -#define SNDRV_SEQ_OSS_MAX_SYNTH_NAME 30 -#define MAX_SYSEX_BUFLEN 128 - - -/* - * definition of synth info records - */ - -/* sysex buffer */ -struct seq_oss_synth_sysex { - int len; - int skip; - unsigned char buf[MAX_SYSEX_BUFLEN]; -}; - -/* synth info */ -struct seq_oss_synth { - int seq_device; - - /* for synth_info */ - int synth_type; - int synth_subtype; - int nr_voices; - - char name[SNDRV_SEQ_OSS_MAX_SYNTH_NAME]; - struct snd_seq_oss_callback oper; - - int opened; - - void *private_data; - snd_use_lock_t use_lock; -}; - - -/* - * device table - */ -static int max_synth_devs; -static struct seq_oss_synth *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS]; -static struct seq_oss_synth midi_synth_dev = { - -1, /* seq_device */ - SYNTH_TYPE_MIDI, /* synth_type */ - 0, /* synth_subtype */ - 16, /* nr_voices */ - "MIDI", /* name */ -}; - -static DEFINE_SPINLOCK(register_lock); - -/* - * prototypes - */ -static struct seq_oss_synth *get_synthdev(struct seq_oss_devinfo *dp, int dev); -static void reset_channels(struct seq_oss_synthinfo *info); - -/* - * global initialization - */ -void __init -snd_seq_oss_synth_init(void) -{ - snd_use_lock_init(&midi_synth_dev.use_lock); -} - -/* - * registration of the synth device - */ -int -snd_seq_oss_synth_register(struct snd_seq_device *dev) -{ - int i; - struct seq_oss_synth *rec; - struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev); - unsigned long flags; - - if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) { - snd_printk(KERN_ERR "can't malloc synth info\n"); - return -ENOMEM; - } - rec->seq_device = -1; - rec->synth_type = reg->type; - rec->synth_subtype = reg->subtype; - rec->nr_voices = reg->nvoices; - rec->oper = reg->oper; - rec->private_data = reg->private_data; - rec->opened = 0; - snd_use_lock_init(&rec->use_lock); - - /* copy and truncate the name of synth device */ - strlcpy(rec->name, dev->name, sizeof(rec->name)); - - /* registration */ - spin_lock_irqsave(®ister_lock, flags); - for (i = 0; i < max_synth_devs; i++) { - if (synth_devs[i] == NULL) - break; - } - if (i >= max_synth_devs) { - if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) { - spin_unlock_irqrestore(®ister_lock, flags); - snd_printk(KERN_ERR "no more synth slot\n"); - kfree(rec); - return -ENOMEM; - } - max_synth_devs++; - } - rec->seq_device = i; - synth_devs[i] = rec; - debug_printk(("synth %s registered %d\n", rec->name, i)); - spin_unlock_irqrestore(®ister_lock, flags); - dev->driver_data = rec; -#ifdef SNDRV_OSS_INFO_DEV_SYNTH - if (i < SNDRV_CARDS) - snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name); -#endif - return 0; -} - - -int -snd_seq_oss_synth_unregister(struct snd_seq_device *dev) -{ - int index; - struct seq_oss_synth *rec = dev->driver_data; - unsigned long flags; - - spin_lock_irqsave(®ister_lock, flags); - for (index = 0; index < max_synth_devs; index++) { - if (synth_devs[index] == rec) - break; - } - if (index >= max_synth_devs) { - spin_unlock_irqrestore(®ister_lock, flags); - snd_printk(KERN_ERR "can't unregister synth\n"); - return -EINVAL; - } - synth_devs[index] = NULL; - if (index == max_synth_devs - 1) { - for (index--; index >= 0; index--) { - if (synth_devs[index]) - break; - } - max_synth_devs = index + 1; - } - spin_unlock_irqrestore(®ister_lock, flags); -#ifdef SNDRV_OSS_INFO_DEV_SYNTH - if (rec->seq_device < SNDRV_CARDS) - snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device); -#endif - - snd_use_lock_sync(&rec->use_lock); - kfree(rec); - - return 0; -} - - -/* - */ -static struct seq_oss_synth * -get_sdev(int dev) -{ - struct seq_oss_synth *rec; - unsigned long flags; - - spin_lock_irqsave(®ister_lock, flags); - rec = synth_devs[dev]; - if (rec) - snd_use_lock_use(&rec->use_lock); - spin_unlock_irqrestore(®ister_lock, flags); - return rec; -} - - -/* - * set up synth tables - */ - -void -snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) -{ - int i; - struct seq_oss_synth *rec; - struct seq_oss_synthinfo *info; - - dp->max_synthdev = max_synth_devs; - dp->synth_opened = 0; - memset(dp->synths, 0, sizeof(dp->synths)); - for (i = 0; i < dp->max_synthdev; i++) { - rec = get_sdev(i); - if (rec == NULL) - continue; - if (rec->oper.open == NULL || rec->oper.close == NULL) { - snd_use_lock_free(&rec->use_lock); - continue; - } - info = &dp->synths[i]; - info->arg.app_index = dp->port; - info->arg.file_mode = dp->file_mode; - info->arg.seq_mode = dp->seq_mode; - if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) - info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS; - else - info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS; - info->opened = 0; - if (!try_module_get(rec->oper.owner)) { - snd_use_lock_free(&rec->use_lock); - continue; - } - if (rec->oper.open(&info->arg, rec->private_data) < 0) { - module_put(rec->oper.owner); - snd_use_lock_free(&rec->use_lock); - continue; - } - info->nr_voices = rec->nr_voices; - if (info->nr_voices > 0) { - info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL); - if (!info->ch) { - snd_printk(KERN_ERR "Cannot malloc\n"); - rec->oper.close(&info->arg); - module_put(rec->oper.owner); - snd_use_lock_free(&rec->use_lock); - continue; - } - reset_channels(info); - } - debug_printk(("synth %d assigned\n", i)); - info->opened++; - rec->opened++; - dp->synth_opened++; - snd_use_lock_free(&rec->use_lock); - } -} - - -/* - * set up synth tables for MIDI emulation - /dev/music mode only - */ - -void -snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp) -{ - int i; - - if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) - return; - - for (i = 0; i < dp->max_mididev; i++) { - struct seq_oss_synthinfo *info; - info = &dp->synths[dp->max_synthdev]; - if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0) - continue; - info->arg.app_index = dp->port; - info->arg.file_mode = dp->file_mode; - info->arg.seq_mode = dp->seq_mode; - info->arg.private_data = info; - info->is_midi = 1; - info->midi_mapped = i; - info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS; - snd_seq_oss_midi_get_addr(dp, i, &info->arg.addr); - info->opened = 1; - midi_synth_dev.opened++; - dp->max_synthdev++; - if (dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) - break; - } -} - - -/* - * clean up synth tables - */ - -void -snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) -{ - int i; - struct seq_oss_synth *rec; - struct seq_oss_synthinfo *info; - - if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) - return; - for (i = 0; i < dp->max_synthdev; i++) { - info = &dp->synths[i]; - if (! info->opened) - continue; - if (info->is_midi) { - if (midi_synth_dev.opened > 0) { - snd_seq_oss_midi_close(dp, info->midi_mapped); - midi_synth_dev.opened--; - } - } else { - rec = get_sdev(i); - if (rec == NULL) - continue; - if (rec->opened > 0) { - debug_printk(("synth %d closed\n", i)); - rec->oper.close(&info->arg); - module_put(rec->oper.owner); - rec->opened = 0; - } - snd_use_lock_free(&rec->use_lock); - } - kfree(info->sysex); - info->sysex = NULL; - kfree(info->ch); - info->ch = NULL; - } - dp->synth_opened = 0; - dp->max_synthdev = 0; -} - -/* - * check if the specified device is MIDI mapped device - */ -static int -is_midi_dev(struct seq_oss_devinfo *dp, int dev) -{ - if (dev < 0 || dev >= dp->max_synthdev) - return 0; - if (dp->synths[dev].is_midi) - return 1; - return 0; -} - -/* - * return synth device information pointer - */ -static struct seq_oss_synth * -get_synthdev(struct seq_oss_devinfo *dp, int dev) -{ - struct seq_oss_synth *rec; - if (dev < 0 || dev >= dp->max_synthdev) - return NULL; - if (! dp->synths[dev].opened) - return NULL; - if (dp->synths[dev].is_midi) - return &midi_synth_dev; - if ((rec = get_sdev(dev)) == NULL) - return NULL; - if (! rec->opened) { - snd_use_lock_free(&rec->use_lock); - return NULL; - } - return rec; -} - - -/* - * reset note and velocity on each channel. - */ -static void -reset_channels(struct seq_oss_synthinfo *info) -{ - int i; - if (info->ch == NULL || ! info->nr_voices) - return; - for (i = 0; i < info->nr_voices; i++) { - info->ch[i].note = -1; - info->ch[i].vel = 0; - } -} - - -/* - * reset synth device: - * call reset callback. if no callback is defined, send a heartbeat - * event to the corresponding port. - */ -void -snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev) -{ - struct seq_oss_synth *rec; - struct seq_oss_synthinfo *info; - - if (snd_BUG_ON(dev < 0 || dev >= dp->max_synthdev)) - return; - info = &dp->synths[dev]; - if (! info->opened) - return; - if (info->sysex) - info->sysex->len = 0; /* reset sysex */ - reset_channels(info); - if (info->is_midi) { - if (midi_synth_dev.opened <= 0) - return; - snd_seq_oss_midi_reset(dp, info->midi_mapped); - /* reopen the device */ - snd_seq_oss_midi_close(dp, dev); - if (snd_seq_oss_midi_open(dp, info->midi_mapped, - dp->file_mode) < 0) { - midi_synth_dev.opened--; - info->opened = 0; - kfree(info->sysex); - info->sysex = NULL; - kfree(info->ch); - info->ch = NULL; - } - return; - } - - rec = get_sdev(dev); - if (rec == NULL) - return; - if (rec->oper.reset) { - rec->oper.reset(&info->arg); - } else { - struct snd_seq_event ev; - memset(&ev, 0, sizeof(ev)); - snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client, - info->arg.addr.port); - ev.type = SNDRV_SEQ_EVENT_RESET; - snd_seq_oss_dispatch(dp, &ev, 0, 0); - } - snd_use_lock_free(&rec->use_lock); -} - - -/* - * load a patch record: - * call load_patch callback function - */ -int -snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, - const char __user *buf, int p, int c) -{ - struct seq_oss_synth *rec; - int rc; - - if (dev < 0 || dev >= dp->max_synthdev) - return -ENXIO; - - if (is_midi_dev(dp, dev)) - return 0; - if ((rec = get_synthdev(dp, dev)) == NULL) - return -ENXIO; - - if (rec->oper.load_patch == NULL) - rc = -ENXIO; - else - rc = rec->oper.load_patch(&dp->synths[dev].arg, fmt, buf, p, c); - snd_use_lock_free(&rec->use_lock); - return rc; -} - -/* - * check if the device is valid synth device - */ -int -snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev) -{ - struct seq_oss_synth *rec; - rec = get_synthdev(dp, dev); - if (rec) { - snd_use_lock_free(&rec->use_lock); - return 1; - } - return 0; -} - - -/* - * receive OSS 6 byte sysex packet: - * the full sysex message will be sent if it reaches to the end of data - * (0xff). - */ -int -snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev) -{ - int i, send; - unsigned char *dest; - struct seq_oss_synth_sysex *sysex; - - if (! snd_seq_oss_synth_is_valid(dp, dev)) - return -ENXIO; - - sysex = dp->synths[dev].sysex; - if (sysex == NULL) { - sysex = kzalloc(sizeof(*sysex), GFP_KERNEL); - if (sysex == NULL) - return -ENOMEM; - dp->synths[dev].sysex = sysex; - } - - send = 0; - dest = sysex->buf + sysex->len; - /* copy 6 byte packet to the buffer */ - for (i = 0; i < 6; i++) { - if (buf[i] == 0xff) { - send = 1; - break; - } - dest[i] = buf[i]; - sysex->len++; - if (sysex->len >= MAX_SYSEX_BUFLEN) { - sysex->len = 0; - sysex->skip = 1; - break; - } - } - - if (sysex->len && send) { - if (sysex->skip) { - sysex->skip = 0; - sysex->len = 0; - return -EINVAL; /* skip */ - } - /* copy the data to event record and send it */ - ev->flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE; - if (snd_seq_oss_synth_addr(dp, dev, ev)) - return -EINVAL; - ev->data.ext.len = sysex->len; - ev->data.ext.ptr = sysex->buf; - sysex->len = 0; - return 0; - } - - return -EINVAL; /* skip */ -} - -/* - * fill the event source/destination addresses - */ -int -snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev) -{ - if (! snd_seq_oss_synth_is_valid(dp, dev)) - return -EINVAL; - snd_seq_oss_fill_addr(dp, ev, dp->synths[dev].arg.addr.client, - dp->synths[dev].arg.addr.port); - return 0; -} - - -/* - * OSS compatible ioctl - */ -int -snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr) -{ - struct seq_oss_synth *rec; - int rc; - - if (is_midi_dev(dp, dev)) - return -ENXIO; - if ((rec = get_synthdev(dp, dev)) == NULL) - return -ENXIO; - if (rec->oper.ioctl == NULL) - rc = -ENXIO; - else - rc = rec->oper.ioctl(&dp->synths[dev].arg, cmd, addr); - snd_use_lock_free(&rec->use_lock); - return rc; -} - - -/* - * send OSS raw events - SEQ_PRIVATE and SEQ_VOLUME - */ -int -snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev) -{ - if (! snd_seq_oss_synth_is_valid(dp, dev) || is_midi_dev(dp, dev)) - return -ENXIO; - ev->type = SNDRV_SEQ_EVENT_OSS; - memcpy(ev->data.raw8.d, data, 8); - return snd_seq_oss_synth_addr(dp, dev, ev); -} - - -/* - * create OSS compatible synth_info record - */ -int -snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf) -{ - struct seq_oss_synth *rec; - - if (dev < 0 || dev >= dp->max_synthdev) - return -ENXIO; - - if (dp->synths[dev].is_midi) { - struct midi_info minf; - snd_seq_oss_midi_make_info(dp, dp->synths[dev].midi_mapped, &minf); - inf->synth_type = SYNTH_TYPE_MIDI; - inf->synth_subtype = 0; - inf->nr_voices = 16; - inf->device = dev; - strlcpy(inf->name, minf.name, sizeof(inf->name)); - } else { - if ((rec = get_synthdev(dp, dev)) == NULL) - return -ENXIO; - inf->synth_type = rec->synth_type; - inf->synth_subtype = rec->synth_subtype; - inf->nr_voices = rec->nr_voices; - inf->device = dev; - strlcpy(inf->name, rec->name, sizeof(inf->name)); - snd_use_lock_free(&rec->use_lock); - } - return 0; -} - - -#ifdef CONFIG_PROC_FS -/* - * proc interface - */ -void -snd_seq_oss_synth_info_read(struct snd_info_buffer *buf) -{ - int i; - struct seq_oss_synth *rec; - - snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs); - for (i = 0; i < max_synth_devs; i++) { - snd_iprintf(buf, "\nsynth %d: ", i); - rec = get_sdev(i); - if (rec == NULL) { - snd_iprintf(buf, "*empty*\n"); - continue; - } - snd_iprintf(buf, "[%s]\n", rec->name); - snd_iprintf(buf, " type 0x%x : subtype 0x%x : voices %d\n", - rec->synth_type, rec->synth_subtype, - rec->nr_voices); - snd_iprintf(buf, " capabilities : ioctl %s / load_patch %s\n", - enabled_str((long)rec->oper.ioctl), - enabled_str((long)rec->oper.load_patch)); - snd_use_lock_free(&rec->use_lock); - } -} -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h deleted file mode 100644 index dbdfcbb8..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_synth.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * synth device information - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 - */ - -#ifndef __SEQ_OSS_SYNTH_H -#define __SEQ_OSS_SYNTH_H - -#include "seq_oss_device.h" -#include -#include - -void snd_seq_oss_synth_init(void); -int snd_seq_oss_synth_register(struct snd_seq_device *dev); -int snd_seq_oss_synth_unregister(struct snd_seq_device *dev); -void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp); -void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp); -void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp); - -void snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev); -int snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, - const char __user *buf, int p, int c); -int snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev); -int snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, - struct snd_seq_event *ev); -int snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev); -int snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, - unsigned long addr); -int snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, - unsigned char *data, struct snd_seq_event *ev); - -int snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf); - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c deleted file mode 100644 index ab59cbfb..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * Timer control routines - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_timer.h" -#include "seq_oss_event.h" -#include -#include - -/* - */ -#define MIN_OSS_TEMPO 8 -#define MAX_OSS_TEMPO 360 -#define MIN_OSS_TIMEBASE 1 -#define MAX_OSS_TIMEBASE 1000 - -/* - */ -static void calc_alsa_tempo(struct seq_oss_timer *timer); -static int send_timer_event(struct seq_oss_devinfo *dp, int type, int value); - - -/* - * create and register a new timer. - * if queue is not started yet, start it. - */ -struct seq_oss_timer * -snd_seq_oss_timer_new(struct seq_oss_devinfo *dp) -{ - struct seq_oss_timer *rec; - - rec = kzalloc(sizeof(*rec), GFP_KERNEL); - if (rec == NULL) - return NULL; - - rec->dp = dp; - rec->cur_tick = 0; - rec->realtime = 0; - rec->running = 0; - rec->oss_tempo = 60; - rec->oss_timebase = 100; - calc_alsa_tempo(rec); - - return rec; -} - - -/* - * delete timer. - * if no more timer exists, stop the queue. - */ -void -snd_seq_oss_timer_delete(struct seq_oss_timer *rec) -{ - if (rec) { - snd_seq_oss_timer_stop(rec); - kfree(rec); - } -} - - -/* - * process one timing event - * return 1 : event proceseed -- skip this event - * 0 : not a timer event -- enqueue this event - */ -int -snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev) -{ - abstime_t parm = ev->t.time; - - if (ev->t.code == EV_TIMING) { - switch (ev->t.cmd) { - case TMR_WAIT_REL: - parm += rec->cur_tick; - rec->realtime = 0; - /* continue to next */ - case TMR_WAIT_ABS: - if (parm == 0) { - rec->realtime = 1; - } else if (parm >= rec->cur_tick) { - rec->realtime = 0; - rec->cur_tick = parm; - } - return 1; /* skip this event */ - - case TMR_START: - snd_seq_oss_timer_start(rec); - return 1; - - } - } else if (ev->s.code == SEQ_WAIT) { - /* time = from 1 to 3 bytes */ - parm = (ev->echo >> 8) & 0xffffff; - if (parm > rec->cur_tick) { - /* set next event time */ - rec->cur_tick = parm; - rec->realtime = 0; - } - return 1; - } - - return 0; -} - - -/* - * convert tempo units - */ -static void -calc_alsa_tempo(struct seq_oss_timer *timer) -{ - timer->tempo = (60 * 1000000) / timer->oss_tempo; - timer->ppq = timer->oss_timebase; -} - - -/* - * dispatch a timer event - */ -static int -send_timer_event(struct seq_oss_devinfo *dp, int type, int value) -{ - struct snd_seq_event ev; - - memset(&ev, 0, sizeof(ev)); - ev.type = type; - ev.source.client = dp->cseq; - ev.source.port = 0; - ev.dest.client = SNDRV_SEQ_CLIENT_SYSTEM; - ev.dest.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; - ev.queue = dp->queue; - ev.data.queue.queue = dp->queue; - ev.data.queue.param.value = value; - return snd_seq_kernel_client_dispatch(dp->cseq, &ev, 1, 0); -} - -/* - * set queue tempo and start queue - */ -int -snd_seq_oss_timer_start(struct seq_oss_timer *timer) -{ - struct seq_oss_devinfo *dp = timer->dp; - struct snd_seq_queue_tempo tmprec; - - if (timer->running) - snd_seq_oss_timer_stop(timer); - - memset(&tmprec, 0, sizeof(tmprec)); - tmprec.queue = dp->queue; - tmprec.ppq = timer->ppq; - tmprec.tempo = timer->tempo; - snd_seq_set_queue_tempo(dp->cseq, &tmprec); - - send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0); - timer->running = 1; - timer->cur_tick = 0; - return 0; -} - - -/* - * stop queue - */ -int -snd_seq_oss_timer_stop(struct seq_oss_timer *timer) -{ - if (! timer->running) - return 0; - send_timer_event(timer->dp, SNDRV_SEQ_EVENT_STOP, 0); - timer->running = 0; - return 0; -} - - -/* - * continue queue - */ -int -snd_seq_oss_timer_continue(struct seq_oss_timer *timer) -{ - if (timer->running) - return 0; - send_timer_event(timer->dp, SNDRV_SEQ_EVENT_CONTINUE, 0); - timer->running = 1; - return 0; -} - - -/* - * change queue tempo - */ -int -snd_seq_oss_timer_tempo(struct seq_oss_timer *timer, int value) -{ - if (value < MIN_OSS_TEMPO) - value = MIN_OSS_TEMPO; - else if (value > MAX_OSS_TEMPO) - value = MAX_OSS_TEMPO; - timer->oss_tempo = value; - calc_alsa_tempo(timer); - if (timer->running) - send_timer_event(timer->dp, SNDRV_SEQ_EVENT_TEMPO, timer->tempo); - return 0; -} - - -/* - * ioctls - */ -int -snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __user *arg) -{ - int value; - - if (cmd == SNDCTL_SEQ_CTRLRATE) { - debug_printk(("ctrl rate\n")); - /* if *arg == 0, just return the current rate */ - if (get_user(value, arg)) - return -EFAULT; - if (value) - return -EINVAL; - value = ((timer->oss_tempo * timer->oss_timebase) + 30) / 60; - return put_user(value, arg) ? -EFAULT : 0; - } - - if (timer->dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) - return 0; - - switch (cmd) { - case SNDCTL_TMR_START: - debug_printk(("timer start\n")); - return snd_seq_oss_timer_start(timer); - case SNDCTL_TMR_STOP: - debug_printk(("timer stop\n")); - return snd_seq_oss_timer_stop(timer); - case SNDCTL_TMR_CONTINUE: - debug_printk(("timer continue\n")); - return snd_seq_oss_timer_continue(timer); - case SNDCTL_TMR_TEMPO: - debug_printk(("timer tempo\n")); - if (get_user(value, arg)) - return -EFAULT; - return snd_seq_oss_timer_tempo(timer, value); - case SNDCTL_TMR_TIMEBASE: - debug_printk(("timer timebase\n")); - if (get_user(value, arg)) - return -EFAULT; - if (value < MIN_OSS_TIMEBASE) - value = MIN_OSS_TIMEBASE; - else if (value > MAX_OSS_TIMEBASE) - value = MAX_OSS_TIMEBASE; - timer->oss_timebase = value; - calc_alsa_tempo(timer); - return 0; - - case SNDCTL_TMR_METRONOME: - case SNDCTL_TMR_SELECT: - case SNDCTL_TMR_SOURCE: - debug_printk(("timer XXX\n")); - /* not supported */ - return 0; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h deleted file mode 100644 index b995bd68..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_timer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * OSS compatible sequencer driver - * timer handling routines - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 - */ - -#ifndef __SEQ_OSS_TIMER_H -#define __SEQ_OSS_TIMER_H - -#include "seq_oss_device.h" - -/* - * timer information definition - */ -struct seq_oss_timer { - struct seq_oss_devinfo *dp; - reltime_t cur_tick; - int realtime; - int running; - int tempo, ppq; /* ALSA queue */ - int oss_tempo, oss_timebase; -}; - - -struct seq_oss_timer *snd_seq_oss_timer_new(struct seq_oss_devinfo *dp); -void snd_seq_oss_timer_delete(struct seq_oss_timer *dp); - -int snd_seq_oss_timer_start(struct seq_oss_timer *timer); -int snd_seq_oss_timer_stop(struct seq_oss_timer *timer); -int snd_seq_oss_timer_continue(struct seq_oss_timer *timer); -int snd_seq_oss_timer_tempo(struct seq_oss_timer *timer, int value); -#define snd_seq_oss_timer_reset snd_seq_oss_timer_start - -int snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __user *arg); - -/* - * get current processed time - */ -static inline abstime_t -snd_seq_oss_timer_cur_tick(struct seq_oss_timer *timer) -{ - return timer->cur_tick; -} - - -/* - * is realtime event? - */ -static inline int -snd_seq_oss_timer_is_realtime(struct seq_oss_timer *timer) -{ - return timer->realtime; -} - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c deleted file mode 100644 index d50338bb..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * OSS compatible sequencer driver - * - * seq_oss_writeq.c - write queue and sync - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 "seq_oss_writeq.h" -#include "seq_oss_event.h" -#include "seq_oss_timer.h" -#include -#include "../seq_lock.h" -#include "../seq_clientmgr.h" -#include -#include - - -/* - * create a write queue record - */ -struct seq_oss_writeq * -snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen) -{ - struct seq_oss_writeq *q; - struct snd_seq_client_pool pool; - - if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) - return NULL; - q->dp = dp; - q->maxlen = maxlen; - spin_lock_init(&q->sync_lock); - q->sync_event_put = 0; - q->sync_time = 0; - init_waitqueue_head(&q->sync_sleep); - - memset(&pool, 0, sizeof(pool)); - pool.client = dp->cseq; - pool.output_pool = maxlen; - pool.output_room = maxlen / 2; - - snd_seq_oss_control(dp, SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, &pool); - - return q; -} - -/* - * delete the write queue - */ -void -snd_seq_oss_writeq_delete(struct seq_oss_writeq *q) -{ - if (q) { - snd_seq_oss_writeq_clear(q); /* to be sure */ - kfree(q); - } -} - - -/* - * reset the write queue - */ -void -snd_seq_oss_writeq_clear(struct seq_oss_writeq *q) -{ - struct snd_seq_remove_events reset; - - memset(&reset, 0, sizeof(reset)); - reset.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT; /* remove all */ - snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_REMOVE_EVENTS, &reset); - - /* wake up sleepers if any */ - snd_seq_oss_writeq_wakeup(q, 0); -} - -/* - * wait until the write buffer has enough room - */ -int -snd_seq_oss_writeq_sync(struct seq_oss_writeq *q) -{ - struct seq_oss_devinfo *dp = q->dp; - abstime_t time; - - time = snd_seq_oss_timer_cur_tick(dp->timer); - if (q->sync_time >= time) - return 0; /* already finished */ - - if (! q->sync_event_put) { - struct snd_seq_event ev; - union evrec *rec; - - /* put echoback event */ - memset(&ev, 0, sizeof(ev)); - ev.flags = 0; - ev.type = SNDRV_SEQ_EVENT_ECHO; - ev.time.tick = time; - /* echo back to itself */ - snd_seq_oss_fill_addr(dp, &ev, dp->addr.client, dp->addr.port); - rec = (union evrec *)&ev.data; - rec->t.code = SEQ_SYNCTIMER; - rec->t.time = time; - q->sync_event_put = 1; - snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0); - } - - wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ); - if (signal_pending(current)) - /* interrupted - return 0 to finish sync */ - q->sync_event_put = 0; - if (! q->sync_event_put || q->sync_time >= time) - return 0; - return 1; -} - -/* - * wake up sync - echo event was catched - */ -void -snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time) -{ - unsigned long flags; - - spin_lock_irqsave(&q->sync_lock, flags); - q->sync_time = time; - q->sync_event_put = 0; - if (waitqueue_active(&q->sync_sleep)) { - wake_up(&q->sync_sleep); - } - spin_unlock_irqrestore(&q->sync_lock, flags); -} - - -/* - * return the unused pool size - */ -int -snd_seq_oss_writeq_get_free_size(struct seq_oss_writeq *q) -{ - struct snd_seq_client_pool pool; - pool.client = q->dp->cseq; - snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, &pool); - return pool.output_free; -} - - -/* - * set output threshold size from ioctl - */ -void -snd_seq_oss_writeq_set_output(struct seq_oss_writeq *q, int val) -{ - struct snd_seq_client_pool pool; - pool.client = q->dp->cseq; - snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, &pool); - pool.output_room = val; - snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, &pool); -} - diff --git a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h b/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h deleted file mode 100644 index c469d296..00000000 --- a/ANDROID_3.4.5/sound/core/seq/oss/seq_oss_writeq.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * OSS compatible sequencer driver - * write priority queue - * - * Copyright (C) 1998,99 Takashi Iwai - * - * 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 - */ - -#ifndef __SEQ_OSS_WRITEQ_H -#define __SEQ_OSS_WRITEQ_H - -#include "seq_oss_device.h" - - -struct seq_oss_writeq { - struct seq_oss_devinfo *dp; - int maxlen; - abstime_t sync_time; - int sync_event_put; - wait_queue_head_t sync_sleep; - spinlock_t sync_lock; -}; - - -/* - * seq_oss_writeq.c - */ -struct seq_oss_writeq *snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen); -void snd_seq_oss_writeq_delete(struct seq_oss_writeq *q); -void snd_seq_oss_writeq_clear(struct seq_oss_writeq *q); -int snd_seq_oss_writeq_sync(struct seq_oss_writeq *q); -void snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time); -int snd_seq_oss_writeq_get_free_size(struct seq_oss_writeq *q); -void snd_seq_oss_writeq_set_output(struct seq_oss_writeq *q, int size); - - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq.c b/ANDROID_3.4.5/sound/core/seq/seq.c deleted file mode 100644 index 71211056..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * ALSA sequencer main module - * Copyright (c) 1998-1999 by Frank van de Pol - * - * - * 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 "seq_clientmgr.h" -#include "seq_memory.h" -#include "seq_queue.h" -#include "seq_lock.h" -#include "seq_timer.h" -#include "seq_system.h" -#include "seq_info.h" -#include -#include - -#if defined(CONFIG_SND_SEQ_DUMMY_MODULE) -int seq_client_load[15] = {[0] = SNDRV_SEQ_CLIENT_DUMMY, [1 ... 14] = -1}; -#else -int seq_client_load[15] = {[0 ... 14] = -1}; -#endif -int seq_default_timer_class = SNDRV_TIMER_CLASS_GLOBAL; -int seq_default_timer_sclass = SNDRV_TIMER_SCLASS_NONE; -int seq_default_timer_card = -1; -int seq_default_timer_device = -#ifdef CONFIG_SND_SEQ_HRTIMER_DEFAULT - SNDRV_TIMER_GLOBAL_HRTIMER -#elif defined(CONFIG_SND_SEQ_RTCTIMER_DEFAULT) - SNDRV_TIMER_GLOBAL_RTC -#else - SNDRV_TIMER_GLOBAL_SYSTEM -#endif - ; -int seq_default_timer_subdevice = 0; -int seq_default_timer_resolution = 0; /* Hz */ - -MODULE_AUTHOR("Frank van de Pol , Jaroslav Kysela "); -MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer."); -MODULE_LICENSE("GPL"); - -module_param_array(seq_client_load, int, NULL, 0444); -MODULE_PARM_DESC(seq_client_load, "The numbers of global (system) clients to load through kmod."); -module_param(seq_default_timer_class, int, 0644); -MODULE_PARM_DESC(seq_default_timer_class, "The default timer class."); -module_param(seq_default_timer_sclass, int, 0644); -MODULE_PARM_DESC(seq_default_timer_sclass, "The default timer slave class."); -module_param(seq_default_timer_card, int, 0644); -MODULE_PARM_DESC(seq_default_timer_card, "The default timer card number."); -module_param(seq_default_timer_device, int, 0644); -MODULE_PARM_DESC(seq_default_timer_device, "The default timer device number."); -module_param(seq_default_timer_subdevice, int, 0644); -MODULE_PARM_DESC(seq_default_timer_subdevice, "The default timer subdevice number."); -module_param(seq_default_timer_resolution, int, 0644); -MODULE_PARM_DESC(seq_default_timer_resolution, "The default timer resolution in Hz."); - -MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_SEQUENCER); -MODULE_ALIAS("devname:snd/seq"); - -/* - * INIT PART - */ - -static int __init alsa_seq_init(void) -{ - int err; - - snd_seq_autoload_lock(); - if ((err = client_init_data()) < 0) - goto error; - - /* init memory, room for selected events */ - if ((err = snd_sequencer_memory_init()) < 0) - goto error; - - /* init event queues */ - if ((err = snd_seq_queues_init()) < 0) - goto error; - - /* register sequencer device */ - if ((err = snd_sequencer_device_init()) < 0) - goto error; - - /* register proc interface */ - if ((err = snd_seq_info_init()) < 0) - goto error; - - /* register our internal client */ - if ((err = snd_seq_system_client_init()) < 0) - goto error; - - error: - snd_seq_autoload_unlock(); - return err; -} - -static void __exit alsa_seq_exit(void) -{ - /* unregister our internal client */ - snd_seq_system_client_done(); - - /* unregister proc interface */ - snd_seq_info_done(); - - /* delete timing queues */ - snd_seq_queues_delete(); - - /* unregister sequencer device */ - snd_sequencer_device_done(); - - /* release event memory */ - snd_sequencer_memory_done(); -} - -module_init(alsa_seq_init) -module_exit(alsa_seq_exit) diff --git a/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c b/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c deleted file mode 100644 index 4dc6bae8..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.c +++ /dev/null @@ -1,2591 +0,0 @@ -/* - * ALSA sequencer Client Manager - * Copyright (c) 1998-2001 by Frank van de Pol - * Jaroslav Kysela - * Takashi Iwai - * - * - * 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 "seq_clientmgr.h" -#include "seq_memory.h" -#include "seq_queue.h" -#include "seq_timer.h" -#include "seq_info.h" -#include "seq_system.h" -#include -#ifdef CONFIG_COMPAT -#include -#endif - -/* Client Manager - - * this module handles the connections of userland and kernel clients - * - */ - -/* - * There are four ranges of client numbers (last two shared): - * 0..15: global clients - * 16..127: statically allocated client numbers for cards 0..27 - * 128..191: dynamically allocated client numbers for cards 28..31 - * 128..191: dynamically allocated client numbers for applications - */ - -/* number of kernel non-card clients */ -#define SNDRV_SEQ_GLOBAL_CLIENTS 16 -/* clients per cards, for static clients */ -#define SNDRV_SEQ_CLIENTS_PER_CARD 4 -/* dynamically allocated client numbers (both kernel drivers and user space) */ -#define SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN 128 - -#define SNDRV_SEQ_LFLG_INPUT 0x0001 -#define SNDRV_SEQ_LFLG_OUTPUT 0x0002 -#define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT) - -static DEFINE_SPINLOCK(clients_lock); -static DEFINE_MUTEX(register_mutex); - -/* - * client table - */ -static char clienttablock[SNDRV_SEQ_MAX_CLIENTS]; -static struct snd_seq_client *clienttab[SNDRV_SEQ_MAX_CLIENTS]; -static struct snd_seq_usage client_usage; - -/* - * prototypes - */ -static int bounce_error_event(struct snd_seq_client *client, - struct snd_seq_event *event, - int err, int atomic, int hop); -static int snd_seq_deliver_single_event(struct snd_seq_client *client, - struct snd_seq_event *event, - int filter, int atomic, int hop); - -/* - */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* - */ -static inline unsigned short snd_seq_file_flags(struct file *file) -{ - switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) { - case FMODE_WRITE: - return SNDRV_SEQ_LFLG_OUTPUT; - case FMODE_READ: - return SNDRV_SEQ_LFLG_INPUT; - default: - return SNDRV_SEQ_LFLG_OPEN; - } -} - -static inline int snd_seq_write_pool_allocated(struct snd_seq_client *client) -{ - return snd_seq_total_cells(client->pool) > 0; -} - -/* return pointer to client structure for specified id */ -static struct snd_seq_client *clientptr(int clientid) -{ - if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) { - snd_printd("Seq: oops. Trying to get pointer to client %d\n", - clientid); - return NULL; - } - return clienttab[clientid]; -} - -struct snd_seq_client *snd_seq_client_use_ptr(int clientid) -{ - unsigned long flags; - struct snd_seq_client *client; - - if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) { - snd_printd("Seq: oops. Trying to get pointer to client %d\n", - clientid); - return NULL; - } - spin_lock_irqsave(&clients_lock, flags); - client = clientptr(clientid); - if (client) - goto __lock; - if (clienttablock[clientid]) { - spin_unlock_irqrestore(&clients_lock, flags); - return NULL; - } - spin_unlock_irqrestore(&clients_lock, flags); -#ifdef CONFIG_MODULES - if (!in_interrupt()) { - static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS]; - static char card_requested[SNDRV_CARDS]; - if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) { - int idx; - - if (!client_requested[clientid]) { - client_requested[clientid] = 1; - for (idx = 0; idx < 15; idx++) { - if (seq_client_load[idx] < 0) - break; - if (seq_client_load[idx] == clientid) { - request_module("snd-seq-client-%i", - clientid); - break; - } - } - } - } else if (clientid < SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) { - int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) / - SNDRV_SEQ_CLIENTS_PER_CARD; - if (card < snd_ecards_limit) { - if (! card_requested[card]) { - card_requested[card] = 1; - snd_request_card(card); - } - snd_seq_device_load_drivers(); - } - } - spin_lock_irqsave(&clients_lock, flags); - client = clientptr(clientid); - if (client) - goto __lock; - spin_unlock_irqrestore(&clients_lock, flags); - } -#endif - return NULL; - - __lock: - snd_use_lock_use(&client->use_lock); - spin_unlock_irqrestore(&clients_lock, flags); - return client; -} - -static void usage_alloc(struct snd_seq_usage *res, int num) -{ - res->cur += num; - if (res->cur > res->peak) - res->peak = res->cur; -} - -static void usage_free(struct snd_seq_usage *res, int num) -{ - res->cur -= num; -} - -/* initialise data structures */ -int __init client_init_data(void) -{ - /* zap out the client table */ - memset(&clienttablock, 0, sizeof(clienttablock)); - memset(&clienttab, 0, sizeof(clienttab)); - return 0; -} - - -static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) -{ - unsigned long flags; - int c; - struct snd_seq_client *client; - - /* init client data */ - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (client == NULL) - return NULL; - client->pool = snd_seq_pool_new(poolsize); - if (client->pool == NULL) { - kfree(client); - return NULL; - } - client->type = NO_CLIENT; - snd_use_lock_init(&client->use_lock); - rwlock_init(&client->ports_lock); - mutex_init(&client->ports_mutex); - INIT_LIST_HEAD(&client->ports_list_head); - - /* find free slot in the client table */ - spin_lock_irqsave(&clients_lock, flags); - if (client_index < 0) { - for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN; - c < SNDRV_SEQ_MAX_CLIENTS; - c++) { - if (clienttab[c] || clienttablock[c]) - continue; - clienttab[client->number = c] = client; - spin_unlock_irqrestore(&clients_lock, flags); - return client; - } - } else { - if (clienttab[client_index] == NULL && !clienttablock[client_index]) { - clienttab[client->number = client_index] = client; - spin_unlock_irqrestore(&clients_lock, flags); - return client; - } - } - spin_unlock_irqrestore(&clients_lock, flags); - snd_seq_pool_delete(&client->pool); - kfree(client); - return NULL; /* no free slot found or busy, return failure code */ -} - - -static int seq_free_client1(struct snd_seq_client *client) -{ - unsigned long flags; - - if (!client) - return 0; - snd_seq_delete_all_ports(client); - snd_seq_queue_client_leave(client->number); - spin_lock_irqsave(&clients_lock, flags); - clienttablock[client->number] = 1; - clienttab[client->number] = NULL; - spin_unlock_irqrestore(&clients_lock, flags); - snd_use_lock_sync(&client->use_lock); - snd_seq_queue_client_termination(client->number); - if (client->pool) - snd_seq_pool_delete(&client->pool); - spin_lock_irqsave(&clients_lock, flags); - clienttablock[client->number] = 0; - spin_unlock_irqrestore(&clients_lock, flags); - return 0; -} - - -static void seq_free_client(struct snd_seq_client * client) -{ - mutex_lock(®ister_mutex); - switch (client->type) { - case NO_CLIENT: - snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n", - client->number); - break; - case USER_CLIENT: - case KERNEL_CLIENT: - seq_free_client1(client); - usage_free(&client_usage, 1); - break; - - default: - snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n", - client->number, client->type); - } - mutex_unlock(®ister_mutex); - - snd_seq_system_client_ev_client_exit(client->number); -} - - - -/* -------------------------------------------------------- */ - -/* create a user client */ -static int snd_seq_open(struct inode *inode, struct file *file) -{ - int c, mode; /* client id */ - struct snd_seq_client *client; - struct snd_seq_user_client *user; - int err; - - err = nonseekable_open(inode, file); - if (err < 0) - return err; - - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; - client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS); - if (client == NULL) { - mutex_unlock(®ister_mutex); - return -ENOMEM; /* failure code */ - } - - mode = snd_seq_file_flags(file); - if (mode & SNDRV_SEQ_LFLG_INPUT) - client->accept_input = 1; - if (mode & SNDRV_SEQ_LFLG_OUTPUT) - client->accept_output = 1; - - user = &client->data.user; - user->fifo = NULL; - user->fifo_pool_size = 0; - - if (mode & SNDRV_SEQ_LFLG_INPUT) { - user->fifo_pool_size = SNDRV_SEQ_DEFAULT_CLIENT_EVENTS; - user->fifo = snd_seq_fifo_new(user->fifo_pool_size); - if (user->fifo == NULL) { - seq_free_client1(client); - kfree(client); - mutex_unlock(®ister_mutex); - return -ENOMEM; - } - } - - usage_alloc(&client_usage, 1); - client->type = USER_CLIENT; - mutex_unlock(®ister_mutex); - - c = client->number; - file->private_data = client; - - /* fill client data */ - user->file = file; - sprintf(client->name, "Client-%d", c); - - /* make others aware this new client */ - snd_seq_system_client_ev_client_start(c); - - return 0; -} - -/* delete a user client */ -static int snd_seq_release(struct inode *inode, struct file *file) -{ - struct snd_seq_client *client = file->private_data; - - if (client) { - seq_free_client(client); - if (client->data.user.fifo) - snd_seq_fifo_delete(&client->data.user.fifo); - kfree(client); - } - - return 0; -} - - -/* handle client read() */ -/* possible error values: - * -ENXIO invalid client or file open mode - * -ENOSPC FIFO overflow (the flag is cleared after this error report) - * -EINVAL no enough user-space buffer to write the whole event - * -EFAULT seg. fault during copy to user space - */ -static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, - loff_t *offset) -{ - struct snd_seq_client *client = file->private_data; - struct snd_seq_fifo *fifo; - int err; - long result = 0; - struct snd_seq_event_cell *cell; - - if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT)) - return -ENXIO; - - if (!access_ok(VERIFY_WRITE, buf, count)) - return -EFAULT; - - /* check client structures are in place */ - if (snd_BUG_ON(!client)) - return -ENXIO; - - if (!client->accept_input || (fifo = client->data.user.fifo) == NULL) - return -ENXIO; - - if (atomic_read(&fifo->overflow) > 0) { - /* buffer overflow is detected */ - snd_seq_fifo_clear(fifo); - /* return error code */ - return -ENOSPC; - } - - cell = NULL; - err = 0; - snd_seq_fifo_lock(fifo); - - /* while data available in queue */ - while (count >= sizeof(struct snd_seq_event)) { - int nonblock; - - nonblock = (file->f_flags & O_NONBLOCK) || result > 0; - if ((err = snd_seq_fifo_cell_out(fifo, &cell, nonblock)) < 0) { - break; - } - if (snd_seq_ev_is_variable(&cell->event)) { - struct snd_seq_event tmpev; - tmpev = cell->event; - tmpev.data.ext.len &= ~SNDRV_SEQ_EXT_MASK; - if (copy_to_user(buf, &tmpev, sizeof(struct snd_seq_event))) { - err = -EFAULT; - break; - } - count -= sizeof(struct snd_seq_event); - buf += sizeof(struct snd_seq_event); - err = snd_seq_expand_var_event(&cell->event, count, - (char __force *)buf, 0, - sizeof(struct snd_seq_event)); - if (err < 0) - break; - result += err; - count -= err; - buf += err; - } else { - if (copy_to_user(buf, &cell->event, sizeof(struct snd_seq_event))) { - err = -EFAULT; - break; - } - count -= sizeof(struct snd_seq_event); - buf += sizeof(struct snd_seq_event); - } - snd_seq_cell_free(cell); - cell = NULL; /* to be sure */ - result += sizeof(struct snd_seq_event); - } - - if (err < 0) { - if (cell) - snd_seq_fifo_cell_putback(fifo, cell); - if (err == -EAGAIN && result > 0) - err = 0; - } - snd_seq_fifo_unlock(fifo); - - return (err < 0) ? err : result; -} - - -/* - * check access permission to the port - */ -static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags) -{ - if ((port->capability & flags) != flags) - return 0; - return flags; -} - -/* - * check if the destination client is available, and return the pointer - * if filter is non-zero, client filter bitmap is tested. - */ -static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event, - int filter) -{ - struct snd_seq_client *dest; - - dest = snd_seq_client_use_ptr(event->dest.client); - if (dest == NULL) - return NULL; - if (! dest->accept_input) - goto __not_avail; - if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) && - ! test_bit(event->type, dest->event_filter)) - goto __not_avail; - if (filter && !(dest->filter & filter)) - goto __not_avail; - - return dest; /* ok - accessible */ -__not_avail: - snd_seq_client_unlock(dest); - return NULL; -} - - -/* - * Return the error event. - * - * If the receiver client is a user client, the original event is - * encapsulated in SNDRV_SEQ_EVENT_BOUNCE as variable length event. If - * the original event is also variable length, the external data is - * copied after the event record. - * If the receiver client is a kernel client, the original event is - * quoted in SNDRV_SEQ_EVENT_KERNEL_ERROR, since this requires no extra - * kmalloc. - */ -static int bounce_error_event(struct snd_seq_client *client, - struct snd_seq_event *event, - int err, int atomic, int hop) -{ - struct snd_seq_event bounce_ev; - int result; - - if (client == NULL || - ! (client->filter & SNDRV_SEQ_FILTER_BOUNCE) || - ! client->accept_input) - return 0; /* ignored */ - - /* set up quoted error */ - memset(&bounce_ev, 0, sizeof(bounce_ev)); - bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR; - bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; - bounce_ev.queue = SNDRV_SEQ_QUEUE_DIRECT; - bounce_ev.source.client = SNDRV_SEQ_CLIENT_SYSTEM; - bounce_ev.source.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; - bounce_ev.dest.client = client->number; - bounce_ev.dest.port = event->source.port; - bounce_ev.data.quote.origin = event->dest; - bounce_ev.data.quote.event = event; - bounce_ev.data.quote.value = -err; /* use positive value */ - result = snd_seq_deliver_single_event(NULL, &bounce_ev, 0, atomic, hop + 1); - if (result < 0) { - client->event_lost++; - return result; - } - - return result; -} - - -/* - * rewrite the time-stamp of the event record with the curren time - * of the given queue. - * return non-zero if updated. - */ -static int update_timestamp_of_queue(struct snd_seq_event *event, - int queue, int real_time) -{ - struct snd_seq_queue *q; - - q = queueptr(queue); - if (! q) - return 0; - event->queue = queue; - event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK; - if (real_time) { - event->time.time = snd_seq_timer_get_cur_time(q->timer); - event->flags |= SNDRV_SEQ_TIME_STAMP_REAL; - } else { - event->time.tick = snd_seq_timer_get_cur_tick(q->timer); - event->flags |= SNDRV_SEQ_TIME_STAMP_TICK; - } - queuefree(q); - return 1; -} - - -/* - * deliver an event to the specified destination. - * if filter is non-zero, client filter bitmap is tested. - * - * RETURN VALUE: 0 : if succeeded - * <0 : error - */ -static int snd_seq_deliver_single_event(struct snd_seq_client *client, - struct snd_seq_event *event, - int filter, int atomic, int hop) -{ - struct snd_seq_client *dest = NULL; - struct snd_seq_client_port *dest_port = NULL; - int result = -ENOENT; - int direct; - - direct = snd_seq_ev_is_direct(event); - - dest = get_event_dest_client(event, filter); - if (dest == NULL) - goto __skip; - dest_port = snd_seq_port_use_ptr(dest, event->dest.port); - if (dest_port == NULL) - goto __skip; - - /* check permission */ - if (! check_port_perm(dest_port, SNDRV_SEQ_PORT_CAP_WRITE)) { - result = -EPERM; - goto __skip; - } - - if (dest_port->timestamping) - update_timestamp_of_queue(event, dest_port->time_queue, - dest_port->time_real); - - switch (dest->type) { - case USER_CLIENT: - if (dest->data.user.fifo) - result = snd_seq_fifo_event_in(dest->data.user.fifo, event); - break; - - case KERNEL_CLIENT: - if (dest_port->event_input == NULL) - break; - result = dest_port->event_input(event, direct, - dest_port->private_data, - atomic, hop); - break; - default: - break; - } - - __skip: - if (dest_port) - snd_seq_port_unlock(dest_port); - if (dest) - snd_seq_client_unlock(dest); - - if (result < 0 && !direct) { - result = bounce_error_event(client, event, result, atomic, hop); - } - return result; -} - - -/* - * send the event to all subscribers: - */ -static int deliver_to_subscribers(struct snd_seq_client *client, - struct snd_seq_event *event, - int atomic, int hop) -{ - struct snd_seq_subscribers *subs; - int err = 0, num_ev = 0; - struct snd_seq_event event_saved; - struct snd_seq_client_port *src_port; - struct snd_seq_port_subs_info *grp; - - src_port = snd_seq_port_use_ptr(client, event->source.port); - if (src_port == NULL) - return -EINVAL; /* invalid source port */ - /* save original event record */ - event_saved = *event; - grp = &src_port->c_src; - - /* lock list */ - if (atomic) - read_lock(&grp->list_lock); - else - down_read(&grp->list_mutex); - list_for_each_entry(subs, &grp->list_head, src_list) { - event->dest = subs->info.dest; - if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) - /* convert time according to flag with subscription */ - update_timestamp_of_queue(event, subs->info.queue, - subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL); - err = snd_seq_deliver_single_event(client, event, - 0, atomic, hop); - if (err < 0) - break; - num_ev++; - /* restore original event record */ - *event = event_saved; - } - if (atomic) - read_unlock(&grp->list_lock); - else - up_read(&grp->list_mutex); - *event = event_saved; /* restore */ - snd_seq_port_unlock(src_port); - return (err < 0) ? err : num_ev; -} - - -#ifdef SUPPORT_BROADCAST -/* - * broadcast to all ports: - */ -static int port_broadcast_event(struct snd_seq_client *client, - struct snd_seq_event *event, - int atomic, int hop) -{ - int num_ev = 0, err = 0; - struct snd_seq_client *dest_client; - struct snd_seq_client_port *port; - - dest_client = get_event_dest_client(event, SNDRV_SEQ_FILTER_BROADCAST); - if (dest_client == NULL) - return 0; /* no matching destination */ - - read_lock(&dest_client->ports_lock); - list_for_each_entry(port, &dest_client->ports_list_head, list) { - event->dest.port = port->addr.port; - /* pass NULL as source client to avoid error bounce */ - err = snd_seq_deliver_single_event(NULL, event, - SNDRV_SEQ_FILTER_BROADCAST, - atomic, hop); - if (err < 0) - break; - num_ev++; - } - read_unlock(&dest_client->ports_lock); - snd_seq_client_unlock(dest_client); - event->dest.port = SNDRV_SEQ_ADDRESS_BROADCAST; /* restore */ - return (err < 0) ? err : num_ev; -} - -/* - * send the event to all clients: - * if destination port is also ADDRESS_BROADCAST, deliver to all ports. - */ -static int broadcast_event(struct snd_seq_client *client, - struct snd_seq_event *event, int atomic, int hop) -{ - int err = 0, num_ev = 0; - int dest; - struct snd_seq_addr addr; - - addr = event->dest; /* save */ - - for (dest = 0; dest < SNDRV_SEQ_MAX_CLIENTS; dest++) { - /* don't send to itself */ - if (dest == client->number) - continue; - event->dest.client = dest; - event->dest.port = addr.port; - if (addr.port == SNDRV_SEQ_ADDRESS_BROADCAST) - err = port_broadcast_event(client, event, atomic, hop); - else - /* pass NULL as source client to avoid error bounce */ - err = snd_seq_deliver_single_event(NULL, event, - SNDRV_SEQ_FILTER_BROADCAST, - atomic, hop); - if (err < 0) - break; - num_ev += err; - } - event->dest = addr; /* restore */ - return (err < 0) ? err : num_ev; -} - - -/* multicast - not supported yet */ -static int multicast_event(struct snd_seq_client *client, struct snd_seq_event *event, - int atomic, int hop) -{ - snd_printd("seq: multicast not supported yet.\n"); - return 0; /* ignored */ -} -#endif /* SUPPORT_BROADCAST */ - - -/* deliver an event to the destination port(s). - * if the event is to subscribers or broadcast, the event is dispatched - * to multiple targets. - * - * RETURN VALUE: n > 0 : the number of delivered events. - * n == 0 : the event was not passed to any client. - * n < 0 : error - event was not processed. - */ -static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_event *event, - int atomic, int hop) -{ - int result; - - hop++; - if (hop >= SNDRV_SEQ_MAX_HOPS) { - snd_printd("too long delivery path (%d:%d->%d:%d)\n", - event->source.client, event->source.port, - event->dest.client, event->dest.port); - return -EMLINK; - } - - if (event->queue == SNDRV_SEQ_ADDRESS_SUBSCRIBERS || - event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) - result = deliver_to_subscribers(client, event, atomic, hop); -#ifdef SUPPORT_BROADCAST - else if (event->queue == SNDRV_SEQ_ADDRESS_BROADCAST || - event->dest.client == SNDRV_SEQ_ADDRESS_BROADCAST) - result = broadcast_event(client, event, atomic, hop); - else if (event->dest.client >= SNDRV_SEQ_MAX_CLIENTS) - result = multicast_event(client, event, atomic, hop); - else if (event->dest.port == SNDRV_SEQ_ADDRESS_BROADCAST) - result = port_broadcast_event(client, event, atomic, hop); -#endif - else - result = snd_seq_deliver_single_event(client, event, 0, atomic, hop); - - return result; -} - -/* - * dispatch an event cell: - * This function is called only from queue check routines in timer - * interrupts or after enqueued. - * The event cell shall be released or re-queued in this function. - * - * RETURN VALUE: n > 0 : the number of delivered events. - * n == 0 : the event was not passed to any client. - * n < 0 : error - event was not processed. - */ -int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop) -{ - struct snd_seq_client *client; - int result; - - if (snd_BUG_ON(!cell)) - return -EINVAL; - - client = snd_seq_client_use_ptr(cell->event.source.client); - if (client == NULL) { - snd_seq_cell_free(cell); /* release this cell */ - return -EINVAL; - } - - if (cell->event.type == SNDRV_SEQ_EVENT_NOTE) { - /* NOTE event: - * the event cell is re-used as a NOTE-OFF event and - * enqueued again. - */ - struct snd_seq_event tmpev, *ev; - - /* reserve this event to enqueue note-off later */ - tmpev = cell->event; - tmpev.type = SNDRV_SEQ_EVENT_NOTEON; - result = snd_seq_deliver_event(client, &tmpev, atomic, hop); - - /* - * This was originally a note event. We now re-use the - * cell for the note-off event. - */ - - ev = &cell->event; - ev->type = SNDRV_SEQ_EVENT_NOTEOFF; - ev->flags |= SNDRV_SEQ_PRIORITY_HIGH; - - /* add the duration time */ - switch (ev->flags & SNDRV_SEQ_TIME_STAMP_MASK) { - case SNDRV_SEQ_TIME_STAMP_TICK: - ev->time.tick += ev->data.note.duration; - break; - case SNDRV_SEQ_TIME_STAMP_REAL: - /* unit for duration is ms */ - ev->time.time.tv_nsec += 1000000 * (ev->data.note.duration % 1000); - ev->time.time.tv_sec += ev->data.note.duration / 1000 + - ev->time.time.tv_nsec / 1000000000; - ev->time.time.tv_nsec %= 1000000000; - break; - } - ev->data.note.velocity = ev->data.note.off_velocity; - - /* Now queue this cell as the note off event */ - if (snd_seq_enqueue_event(cell, atomic, hop) < 0) - snd_seq_cell_free(cell); /* release this cell */ - - } else { - /* Normal events: - * event cell is freed after processing the event - */ - - result = snd_seq_deliver_event(client, &cell->event, atomic, hop); - snd_seq_cell_free(cell); - } - - snd_seq_client_unlock(client); - return result; -} - - -/* Allocate a cell from client pool and enqueue it to queue: - * if pool is empty and blocking is TRUE, sleep until a new cell is - * available. - */ -static int snd_seq_client_enqueue_event(struct snd_seq_client *client, - struct snd_seq_event *event, - struct file *file, int blocking, - int atomic, int hop) -{ - struct snd_seq_event_cell *cell; - int err; - - /* special queue values - force direct passing */ - if (event->queue == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) { - event->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - event->queue = SNDRV_SEQ_QUEUE_DIRECT; - } else -#ifdef SUPPORT_BROADCAST - if (event->queue == SNDRV_SEQ_ADDRESS_BROADCAST) { - event->dest.client = SNDRV_SEQ_ADDRESS_BROADCAST; - event->queue = SNDRV_SEQ_QUEUE_DIRECT; - } -#endif - if (event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) { - /* check presence of source port */ - struct snd_seq_client_port *src_port = snd_seq_port_use_ptr(client, event->source.port); - if (src_port == NULL) - return -EINVAL; - snd_seq_port_unlock(src_port); - } - - /* direct event processing without enqueued */ - if (snd_seq_ev_is_direct(event)) { - if (event->type == SNDRV_SEQ_EVENT_NOTE) - return -EINVAL; /* this event must be enqueued! */ - return snd_seq_deliver_event(client, event, atomic, hop); - } - - /* Not direct, normal queuing */ - if (snd_seq_queue_is_used(event->queue, client->number) <= 0) - return -EINVAL; /* invalid queue */ - if (! snd_seq_write_pool_allocated(client)) - return -ENXIO; /* queue is not allocated */ - - /* allocate an event cell */ - err = snd_seq_event_dup(client->pool, event, &cell, !blocking || atomic, file); - if (err < 0) - return err; - - /* we got a cell. enqueue it. */ - if ((err = snd_seq_enqueue_event(cell, atomic, hop)) < 0) { - snd_seq_cell_free(cell); - return err; - } - - return 0; -} - - -/* - * check validity of event type and data length. - * return non-zero if invalid. - */ -static int check_event_type_and_length(struct snd_seq_event *ev) -{ - switch (snd_seq_ev_length_type(ev)) { - case SNDRV_SEQ_EVENT_LENGTH_FIXED: - if (snd_seq_ev_is_variable_type(ev)) - return -EINVAL; - break; - case SNDRV_SEQ_EVENT_LENGTH_VARIABLE: - if (! snd_seq_ev_is_variable_type(ev) || - (ev->data.ext.len & ~SNDRV_SEQ_EXT_MASK) >= SNDRV_SEQ_MAX_EVENT_LEN) - return -EINVAL; - break; - case SNDRV_SEQ_EVENT_LENGTH_VARUSR: - if (! snd_seq_ev_is_direct(ev)) - return -EINVAL; - break; - } - return 0; -} - - -/* handle write() */ -/* possible error values: - * -ENXIO invalid client or file open mode - * -ENOMEM malloc failed - * -EFAULT seg. fault during copy from user space - * -EINVAL invalid event - * -EAGAIN no space in output pool - * -EINTR interrupts while sleep - * -EMLINK too many hops - * others depends on return value from driver callback - */ -static ssize_t snd_seq_write(struct file *file, const char __user *buf, - size_t count, loff_t *offset) -{ - struct snd_seq_client *client = file->private_data; - int written = 0, len; - int err = -EINVAL; - struct snd_seq_event event; - - if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT)) - return -ENXIO; - - /* check client structures are in place */ - if (snd_BUG_ON(!client)) - return -ENXIO; - - if (!client->accept_output || client->pool == NULL) - return -ENXIO; - - /* allocate the pool now if the pool is not allocated yet */ - if (client->pool->size > 0 && !snd_seq_write_pool_allocated(client)) { - if (snd_seq_pool_init(client->pool) < 0) - return -ENOMEM; - } - - /* only process whole events */ - while (count >= sizeof(struct snd_seq_event)) { - /* Read in the event header from the user */ - len = sizeof(event); - if (copy_from_user(&event, buf, len)) { - err = -EFAULT; - break; - } - event.source.client = client->number; /* fill in client number */ - /* Check for extension data length */ - if (check_event_type_and_length(&event)) { - err = -EINVAL; - break; - } - - /* check for special events */ - if (event.type == SNDRV_SEQ_EVENT_NONE) - goto __skip_event; - else if (snd_seq_ev_is_reserved(&event)) { - err = -EINVAL; - break; - } - - if (snd_seq_ev_is_variable(&event)) { - int extlen = event.data.ext.len & ~SNDRV_SEQ_EXT_MASK; - if ((size_t)(extlen + len) > count) { - /* back out, will get an error this time or next */ - err = -EINVAL; - break; - } - /* set user space pointer */ - event.data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR; - event.data.ext.ptr = (char __force *)buf - + sizeof(struct snd_seq_event); - len += extlen; /* increment data length */ - } else { -#ifdef CONFIG_COMPAT - if (client->convert32 && snd_seq_ev_is_varusr(&event)) { - void *ptr = (void __force *)compat_ptr(event.data.raw32.d[1]); - event.data.ext.ptr = ptr; - } -#endif - } - - /* ok, enqueue it */ - err = snd_seq_client_enqueue_event(client, &event, file, - !(file->f_flags & O_NONBLOCK), - 0, 0); - if (err < 0) - break; - - __skip_event: - /* Update pointers and counts */ - count -= len; - buf += len; - written += len; - } - - return written ? written : err; -} - - -/* - * handle polling - */ -static unsigned int snd_seq_poll(struct file *file, poll_table * wait) -{ - struct snd_seq_client *client = file->private_data; - unsigned int mask = 0; - - /* check client structures are in place */ - if (snd_BUG_ON(!client)) - return -ENXIO; - - if ((snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT) && - client->data.user.fifo) { - - /* check if data is available in the outqueue */ - if (snd_seq_fifo_poll_wait(client->data.user.fifo, file, wait)) - mask |= POLLIN | POLLRDNORM; - } - - if (snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT) { - - /* check if data is available in the pool */ - if (!snd_seq_write_pool_allocated(client) || - snd_seq_pool_poll_wait(client->pool, file, wait)) - mask |= POLLOUT | POLLWRNORM; - } - - return mask; -} - - -/*-----------------------------------------------------*/ - - -/* SYSTEM_INFO ioctl() */ -static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg) -{ - struct snd_seq_system_info info; - - memset(&info, 0, sizeof(info)); - /* fill the info fields */ - info.queues = SNDRV_SEQ_MAX_QUEUES; - info.clients = SNDRV_SEQ_MAX_CLIENTS; - info.ports = 256; /* fixed limit */ - info.channels = 256; /* fixed limit */ - info.cur_clients = client_usage.cur; - info.cur_queues = snd_seq_queue_get_cur_queues(); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - - -/* RUNNING_MODE ioctl() */ -static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void __user *arg) -{ - struct snd_seq_running_info info; - struct snd_seq_client *cptr; - int err = 0; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - /* requested client number */ - cptr = snd_seq_client_use_ptr(info.client); - if (cptr == NULL) - return -ENOENT; /* don't change !!! */ - -#ifdef SNDRV_BIG_ENDIAN - if (! info.big_endian) { - err = -EINVAL; - goto __err; - } -#else - if (info.big_endian) { - err = -EINVAL; - goto __err; - } - -#endif - if (info.cpu_mode > sizeof(long)) { - err = -EINVAL; - goto __err; - } - cptr->convert32 = (info.cpu_mode < sizeof(long)); - __err: - snd_seq_client_unlock(cptr); - return err; -} - -/* CLIENT_INFO ioctl() */ -static void get_client_info(struct snd_seq_client *cptr, - struct snd_seq_client_info *info) -{ - info->client = cptr->number; - - /* fill the info fields */ - info->type = cptr->type; - strcpy(info->name, cptr->name); - info->filter = cptr->filter; - info->event_lost = cptr->event_lost; - memcpy(info->event_filter, cptr->event_filter, 32); - info->num_ports = cptr->num_ports; - memset(info->reserved, 0, sizeof(info->reserved)); -} - -static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client *cptr; - struct snd_seq_client_info client_info; - - if (copy_from_user(&client_info, arg, sizeof(client_info))) - return -EFAULT; - - /* requested client number */ - cptr = snd_seq_client_use_ptr(client_info.client); - if (cptr == NULL) - return -ENOENT; /* don't change !!! */ - - get_client_info(cptr, &client_info); - snd_seq_client_unlock(cptr); - - if (copy_to_user(arg, &client_info, sizeof(client_info))) - return -EFAULT; - return 0; -} - - -/* CLIENT_INFO ioctl() */ -static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client_info client_info; - - if (copy_from_user(&client_info, arg, sizeof(client_info))) - return -EFAULT; - - /* it is not allowed to set the info fields for an another client */ - if (client->number != client_info.client) - return -EPERM; - /* also client type must be set now */ - if (client->type != client_info.type) - return -EINVAL; - - /* fill the info fields */ - if (client_info.name[0]) - strlcpy(client->name, client_info.name, sizeof(client->name)); - - client->filter = client_info.filter; - client->event_lost = client_info.event_lost; - memcpy(client->event_filter, client_info.event_filter, 32); - - return 0; -} - - -/* - * CREATE PORT ioctl() - */ -static int snd_seq_ioctl_create_port(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client_port *port; - struct snd_seq_port_info info; - struct snd_seq_port_callback *callback; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - /* it is not allowed to create the port for an another client */ - if (info.addr.client != client->number) - return -EPERM; - - port = snd_seq_create_port(client, (info.flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info.addr.port : -1); - if (port == NULL) - return -ENOMEM; - - if (client->type == USER_CLIENT && info.kernel) { - snd_seq_delete_port(client, port->addr.port); - return -EINVAL; - } - if (client->type == KERNEL_CLIENT) { - if ((callback = info.kernel) != NULL) { - if (callback->owner) - port->owner = callback->owner; - port->private_data = callback->private_data; - port->private_free = callback->private_free; - port->callback_all = callback->callback_all; - port->event_input = callback->event_input; - port->c_src.open = callback->subscribe; - port->c_src.close = callback->unsubscribe; - port->c_dest.open = callback->use; - port->c_dest.close = callback->unuse; - } - } - - info.addr = port->addr; - - snd_seq_set_port_info(port, &info); - snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - - return 0; -} - -/* - * DELETE PORT ioctl() - */ -static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_port_info info; - int err; - - /* set passed parameters */ - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - /* it is not allowed to remove the port for an another client */ - if (info.addr.client != client->number) - return -EPERM; - - err = snd_seq_delete_port(client, info.addr.port); - if (err >= 0) - snd_seq_system_client_ev_port_exit(client->number, info.addr.port); - return err; -} - - -/* - * GET_PORT_INFO ioctl() (on any client) - */ -static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client *cptr; - struct snd_seq_client_port *port; - struct snd_seq_port_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - cptr = snd_seq_client_use_ptr(info.addr.client); - if (cptr == NULL) - return -ENXIO; - - port = snd_seq_port_use_ptr(cptr, info.addr.port); - if (port == NULL) { - snd_seq_client_unlock(cptr); - return -ENOENT; /* don't change */ - } - - /* get port info */ - snd_seq_get_port_info(port, &info); - snd_seq_port_unlock(port); - snd_seq_client_unlock(cptr); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - - -/* - * SET_PORT_INFO ioctl() (only ports on this/own client) - */ -static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client_port *port; - struct snd_seq_port_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (info.addr.client != client->number) /* only set our own ports ! */ - return -EPERM; - port = snd_seq_port_use_ptr(client, info.addr.port); - if (port) { - snd_seq_set_port_info(port, &info); - snd_seq_port_unlock(port); - } - return 0; -} - - -/* - * port subscription (connection) - */ -#define PERM_RD (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ) -#define PERM_WR (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE) - -static int check_subscription_permission(struct snd_seq_client *client, - struct snd_seq_client_port *sport, - struct snd_seq_client_port *dport, - struct snd_seq_port_subscribe *subs) -{ - if (client->number != subs->sender.client && - client->number != subs->dest.client) { - /* connection by third client - check export permission */ - if (check_port_perm(sport, SNDRV_SEQ_PORT_CAP_NO_EXPORT)) - return -EPERM; - if (check_port_perm(dport, SNDRV_SEQ_PORT_CAP_NO_EXPORT)) - return -EPERM; - } - - /* check read permission */ - /* if sender or receiver is the subscribing client itself, - * no permission check is necessary - */ - if (client->number != subs->sender.client) { - if (! check_port_perm(sport, PERM_RD)) - return -EPERM; - } - /* check write permission */ - if (client->number != subs->dest.client) { - if (! check_port_perm(dport, PERM_WR)) - return -EPERM; - } - return 0; -} - -/* - * send an subscription notify event to user client: - * client must be user client. - */ -int snd_seq_client_notify_subscription(int client, int port, - struct snd_seq_port_subscribe *info, - int evtype) -{ - struct snd_seq_event event; - - memset(&event, 0, sizeof(event)); - event.type = evtype; - event.data.connect.dest = info->dest; - event.data.connect.sender = info->sender; - - return snd_seq_system_notify(client, port, &event); /* non-atomic */ -} - - -/* - * add to port's subscription list IOCTL interface - */ -static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, - void __user *arg) -{ - int result = -EINVAL; - struct snd_seq_client *receiver = NULL, *sender = NULL; - struct snd_seq_client_port *sport = NULL, *dport = NULL; - struct snd_seq_port_subscribe subs; - - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) - goto __end; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) - goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) - goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) - goto __end; - - result = check_subscription_permission(client, sport, dport, &subs); - if (result < 0) - goto __end; - - /* connect them */ - result = snd_seq_port_connect(client, sender, sport, receiver, dport, &subs); - if (! result) /* broadcast announce */ - snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, - &subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); - __end: - if (sport) - snd_seq_port_unlock(sport); - if (dport) - snd_seq_port_unlock(dport); - if (sender) - snd_seq_client_unlock(sender); - if (receiver) - snd_seq_client_unlock(receiver); - return result; -} - - -/* - * remove from port's subscription list - */ -static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, - void __user *arg) -{ - int result = -ENXIO; - struct snd_seq_client *receiver = NULL, *sender = NULL; - struct snd_seq_client_port *sport = NULL, *dport = NULL; - struct snd_seq_port_subscribe subs; - - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) - goto __end; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) - goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) - goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) - goto __end; - - result = check_subscription_permission(client, sport, dport, &subs); - if (result < 0) - goto __end; - - result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, &subs); - if (! result) /* broadcast announce */ - snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, - &subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); - __end: - if (sport) - snd_seq_port_unlock(sport); - if (dport) - snd_seq_port_unlock(dport); - if (sender) - snd_seq_client_unlock(sender); - if (receiver) - snd_seq_client_unlock(receiver); - return result; -} - - -/* CREATE_QUEUE ioctl() */ -static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_queue_info info; - int result; - struct snd_seq_queue *q; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - result = snd_seq_queue_alloc(client->number, info.locked, info.flags); - if (result < 0) - return result; - - q = queueptr(result); - if (q == NULL) - return -EINVAL; - - info.queue = q->queue; - info.locked = q->locked; - info.owner = q->owner; - - /* set queue name */ - if (! info.name[0]) - snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue); - strlcpy(q->name, info.name, sizeof(q->name)); - queuefree(q); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - - return 0; -} - -/* DELETE_QUEUE ioctl() */ -static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_queue_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - return snd_seq_queue_delete(client->number, info.queue); -} - -/* GET_QUEUE_INFO ioctl() */ -static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_queue_info info; - struct snd_seq_queue *q; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - q = queueptr(info.queue); - if (q == NULL) - return -EINVAL; - - memset(&info, 0, sizeof(info)); - info.queue = q->queue; - info.owner = q->owner; - info.locked = q->locked; - strlcpy(info.name, q->name, sizeof(info.name)); - queuefree(q); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - - return 0; -} - -/* SET_QUEUE_INFO ioctl() */ -static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_queue_info info; - struct snd_seq_queue *q; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (info.owner != client->number) - return -EINVAL; - - /* change owner/locked permission */ - if (snd_seq_queue_check_access(info.queue, client->number)) { - if (snd_seq_queue_set_owner(info.queue, client->number, info.locked) < 0) - return -EPERM; - if (info.locked) - snd_seq_queue_use(info.queue, client->number, 1); - } else { - return -EPERM; - } - - q = queueptr(info.queue); - if (! q) - return -EINVAL; - if (q->owner != client->number) { - queuefree(q); - return -EPERM; - } - strlcpy(q->name, info.name, sizeof(q->name)); - queuefree(q); - - return 0; -} - -/* GET_NAMED_QUEUE ioctl() */ -static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void __user *arg) -{ - struct snd_seq_queue_info info; - struct snd_seq_queue *q; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - q = snd_seq_queue_find_name(info.name); - if (q == NULL) - return -EINVAL; - info.queue = q->queue; - info.owner = q->owner; - info.locked = q->locked; - queuefree(q); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - - return 0; -} - -/* GET_QUEUE_STATUS ioctl() */ -static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_queue_status status; - struct snd_seq_queue *queue; - struct snd_seq_timer *tmr; - - if (copy_from_user(&status, arg, sizeof(status))) - return -EFAULT; - - queue = queueptr(status.queue); - if (queue == NULL) - return -EINVAL; - memset(&status, 0, sizeof(status)); - status.queue = queue->queue; - - tmr = queue->timer; - status.events = queue->tickq->cells + queue->timeq->cells; - - status.time = snd_seq_timer_get_cur_time(tmr); - status.tick = snd_seq_timer_get_cur_tick(tmr); - - status.running = tmr->running; - - status.flags = queue->flags; - queuefree(queue); - - if (copy_to_user(arg, &status, sizeof(status))) - return -EFAULT; - return 0; -} - - -/* GET_QUEUE_TEMPO ioctl() */ -static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_queue_tempo tempo; - struct snd_seq_queue *queue; - struct snd_seq_timer *tmr; - - if (copy_from_user(&tempo, arg, sizeof(tempo))) - return -EFAULT; - - queue = queueptr(tempo.queue); - if (queue == NULL) - return -EINVAL; - memset(&tempo, 0, sizeof(tempo)); - tempo.queue = queue->queue; - - tmr = queue->timer; - - tempo.tempo = tmr->tempo; - tempo.ppq = tmr->ppq; - tempo.skew_value = tmr->skew; - tempo.skew_base = tmr->skew_base; - queuefree(queue); - - if (copy_to_user(arg, &tempo, sizeof(tempo))) - return -EFAULT; - return 0; -} - - -/* SET_QUEUE_TEMPO ioctl() */ -int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) -{ - if (!snd_seq_queue_check_access(tempo->queue, client)) - return -EPERM; - return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); -} - -EXPORT_SYMBOL(snd_seq_set_queue_tempo); - -static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, - void __user *arg) -{ - int result; - struct snd_seq_queue_tempo tempo; - - if (copy_from_user(&tempo, arg, sizeof(tempo))) - return -EFAULT; - - result = snd_seq_set_queue_tempo(client->number, &tempo); - return result < 0 ? result : 0; -} - - -/* GET_QUEUE_TIMER ioctl() */ -static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_queue_timer timer; - struct snd_seq_queue *queue; - struct snd_seq_timer *tmr; - - if (copy_from_user(&timer, arg, sizeof(timer))) - return -EFAULT; - - queue = queueptr(timer.queue); - if (queue == NULL) - return -EINVAL; - - if (mutex_lock_interruptible(&queue->timer_mutex)) { - queuefree(queue); - return -ERESTARTSYS; - } - tmr = queue->timer; - memset(&timer, 0, sizeof(timer)); - timer.queue = queue->queue; - - timer.type = tmr->type; - if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { - timer.u.alsa.id = tmr->alsa_id; - timer.u.alsa.resolution = tmr->preferred_resolution; - } - mutex_unlock(&queue->timer_mutex); - queuefree(queue); - - if (copy_to_user(arg, &timer, sizeof(timer))) - return -EFAULT; - return 0; -} - - -/* SET_QUEUE_TIMER ioctl() */ -static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, - void __user *arg) -{ - int result = 0; - struct snd_seq_queue_timer timer; - - if (copy_from_user(&timer, arg, sizeof(timer))) - return -EFAULT; - - if (timer.type != SNDRV_SEQ_TIMER_ALSA) - return -EINVAL; - - if (snd_seq_queue_check_access(timer.queue, client->number)) { - struct snd_seq_queue *q; - struct snd_seq_timer *tmr; - - q = queueptr(timer.queue); - if (q == NULL) - return -ENXIO; - if (mutex_lock_interruptible(&q->timer_mutex)) { - queuefree(q); - return -ERESTARTSYS; - } - tmr = q->timer; - snd_seq_queue_timer_close(timer.queue); - tmr->type = timer.type; - if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { - tmr->alsa_id = timer.u.alsa.id; - tmr->preferred_resolution = timer.u.alsa.resolution; - } - result = snd_seq_queue_timer_open(timer.queue); - mutex_unlock(&q->timer_mutex); - queuefree(q); - } else { - return -EPERM; - } - - return result; -} - - -/* GET_QUEUE_CLIENT ioctl() */ -static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_queue_client info; - int used; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - used = snd_seq_queue_is_used(info.queue, client->number); - if (used < 0) - return -EINVAL; - info.used = used; - info.client = client->number; - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - - -/* SET_QUEUE_CLIENT ioctl() */ -static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client, - void __user *arg) -{ - int err; - struct snd_seq_queue_client info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (info.used >= 0) { - err = snd_seq_queue_use(info.queue, client->number, info.used); - if (err < 0) - return err; - } - - return snd_seq_ioctl_get_queue_client(client, arg); -} - - -/* GET_CLIENT_POOL ioctl() */ -static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client_pool info; - struct snd_seq_client *cptr; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - cptr = snd_seq_client_use_ptr(info.client); - if (cptr == NULL) - return -ENOENT; - memset(&info, 0, sizeof(info)); - info.output_pool = cptr->pool->size; - info.output_room = cptr->pool->room; - info.output_free = info.output_pool; - info.output_free = snd_seq_unused_cells(cptr->pool); - if (cptr->type == USER_CLIENT) { - info.input_pool = cptr->data.user.fifo_pool_size; - info.input_free = info.input_pool; - if (cptr->data.user.fifo) - info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); - } else { - info.input_pool = 0; - info.input_free = 0; - } - snd_seq_client_unlock(cptr); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -/* SET_CLIENT_POOL ioctl() */ -static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client_pool info; - int rc; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (client->number != info.client) - return -EINVAL; /* can't change other clients */ - - if (info.output_pool >= 1 && info.output_pool <= SNDRV_SEQ_MAX_EVENTS && - (! snd_seq_write_pool_allocated(client) || - info.output_pool != client->pool->size)) { - if (snd_seq_write_pool_allocated(client)) { - /* remove all existing cells */ - snd_seq_queue_client_leave_cells(client->number); - snd_seq_pool_done(client->pool); - } - client->pool->size = info.output_pool; - rc = snd_seq_pool_init(client->pool); - if (rc < 0) - return rc; - } - if (client->type == USER_CLIENT && client->data.user.fifo != NULL && - info.input_pool >= 1 && - info.input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && - info.input_pool != client->data.user.fifo_pool_size) { - /* change pool size */ - rc = snd_seq_fifo_resize(client->data.user.fifo, info.input_pool); - if (rc < 0) - return rc; - client->data.user.fifo_pool_size = info.input_pool; - } - if (info.output_room >= 1 && - info.output_room <= client->pool->size) { - client->pool->room = info.output_room; - } - - return snd_seq_ioctl_get_client_pool(client, arg); -} - - -/* REMOVE_EVENTS ioctl() */ -static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_remove_events info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - /* - * Input mostly not implemented XXX. - */ - if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) { - /* - * No restrictions so for a user client we can clear - * the whole fifo - */ - if (client->type == USER_CLIENT) - snd_seq_fifo_clear(client->data.user.fifo); - } - - if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) - snd_seq_queue_remove_cells(client->number, &info); - - return 0; -} - - -/* - * get subscription info - */ -static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, - void __user *arg) -{ - int result; - struct snd_seq_client *sender = NULL; - struct snd_seq_client_port *sport = NULL; - struct snd_seq_port_subscribe subs; - struct snd_seq_subscribers *p; - - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - result = -EINVAL; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) - goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) - goto __end; - p = snd_seq_port_get_subscription(&sport->c_src, &subs.dest); - if (p) { - result = 0; - subs = p->info; - } else - result = -ENOENT; - - __end: - if (sport) - snd_seq_port_unlock(sport); - if (sender) - snd_seq_client_unlock(sender); - if (result >= 0) { - if (copy_to_user(arg, &subs, sizeof(subs))) - return -EFAULT; - } - return result; -} - - -/* - * get subscription info - check only its presence - */ -static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, - void __user *arg) -{ - int result = -ENXIO; - struct snd_seq_client *cptr = NULL; - struct snd_seq_client_port *port = NULL; - struct snd_seq_query_subs subs; - struct snd_seq_port_subs_info *group; - struct list_head *p; - int i; - - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL) - goto __end; - if ((port = snd_seq_port_use_ptr(cptr, subs.root.port)) == NULL) - goto __end; - - switch (subs.type) { - case SNDRV_SEQ_QUERY_SUBS_READ: - group = &port->c_src; - break; - case SNDRV_SEQ_QUERY_SUBS_WRITE: - group = &port->c_dest; - break; - default: - goto __end; - } - - down_read(&group->list_mutex); - /* search for the subscriber */ - subs.num_subs = group->count; - i = 0; - result = -ENOENT; - list_for_each(p, &group->list_head) { - if (i++ == subs.index) { - /* found! */ - struct snd_seq_subscribers *s; - if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) { - s = list_entry(p, struct snd_seq_subscribers, src_list); - subs.addr = s->info.dest; - } else { - s = list_entry(p, struct snd_seq_subscribers, dest_list); - subs.addr = s->info.sender; - } - subs.flags = s->info.flags; - subs.queue = s->info.queue; - result = 0; - break; - } - } - up_read(&group->list_mutex); - - __end: - if (port) - snd_seq_port_unlock(port); - if (cptr) - snd_seq_client_unlock(cptr); - if (result >= 0) { - if (copy_to_user(arg, &subs, sizeof(subs))) - return -EFAULT; - } - return result; -} - - -/* - * query next client - */ -static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client *cptr = NULL; - struct snd_seq_client_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - /* search for next client */ - info.client++; - if (info.client < 0) - info.client = 0; - for (; info.client < SNDRV_SEQ_MAX_CLIENTS; info.client++) { - cptr = snd_seq_client_use_ptr(info.client); - if (cptr) - break; /* found */ - } - if (cptr == NULL) - return -ENOENT; - - get_client_info(cptr, &info); - snd_seq_client_unlock(cptr); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -/* - * query next port - */ -static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client, - void __user *arg) -{ - struct snd_seq_client *cptr; - struct snd_seq_client_port *port = NULL; - struct snd_seq_port_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - cptr = snd_seq_client_use_ptr(info.addr.client); - if (cptr == NULL) - return -ENXIO; - - /* search for next port */ - info.addr.port++; - port = snd_seq_port_query_nearest(cptr, &info); - if (port == NULL) { - snd_seq_client_unlock(cptr); - return -ENOENT; - } - - /* get port info */ - info.addr = port->addr; - snd_seq_get_port_info(port, &info); - snd_seq_port_unlock(port); - snd_seq_client_unlock(cptr); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -/* -------------------------------------------------------- */ - -static struct seq_ioctl_table { - unsigned int cmd; - int (*func)(struct snd_seq_client *client, void __user * arg); -} ioctl_tables[] = { - { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info }, - { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode }, - { SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info }, - { SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, snd_seq_ioctl_set_client_info }, - { SNDRV_SEQ_IOCTL_CREATE_PORT, snd_seq_ioctl_create_port }, - { SNDRV_SEQ_IOCTL_DELETE_PORT, snd_seq_ioctl_delete_port }, - { SNDRV_SEQ_IOCTL_GET_PORT_INFO, snd_seq_ioctl_get_port_info }, - { SNDRV_SEQ_IOCTL_SET_PORT_INFO, snd_seq_ioctl_set_port_info }, - { SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, snd_seq_ioctl_subscribe_port }, - { SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, snd_seq_ioctl_unsubscribe_port }, - { SNDRV_SEQ_IOCTL_CREATE_QUEUE, snd_seq_ioctl_create_queue }, - { SNDRV_SEQ_IOCTL_DELETE_QUEUE, snd_seq_ioctl_delete_queue }, - { SNDRV_SEQ_IOCTL_GET_QUEUE_INFO, snd_seq_ioctl_get_queue_info }, - { SNDRV_SEQ_IOCTL_SET_QUEUE_INFO, snd_seq_ioctl_set_queue_info }, - { SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE, snd_seq_ioctl_get_named_queue }, - { SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS, snd_seq_ioctl_get_queue_status }, - { SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO, snd_seq_ioctl_get_queue_tempo }, - { SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, snd_seq_ioctl_set_queue_tempo }, - { SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER, snd_seq_ioctl_get_queue_timer }, - { SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER, snd_seq_ioctl_set_queue_timer }, - { SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT, snd_seq_ioctl_get_queue_client }, - { SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT, snd_seq_ioctl_set_queue_client }, - { SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, snd_seq_ioctl_get_client_pool }, - { SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, snd_seq_ioctl_set_client_pool }, - { SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION, snd_seq_ioctl_get_subscription }, - { SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, snd_seq_ioctl_query_next_client }, - { SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, snd_seq_ioctl_query_next_port }, - { SNDRV_SEQ_IOCTL_REMOVE_EVENTS, snd_seq_ioctl_remove_events }, - { SNDRV_SEQ_IOCTL_QUERY_SUBS, snd_seq_ioctl_query_subs }, - { 0, NULL }, -}; - -static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, - void __user *arg) -{ - struct seq_ioctl_table *p; - - switch (cmd) { - case SNDRV_SEQ_IOCTL_PVERSION: - /* return sequencer version number */ - return put_user(SNDRV_SEQ_VERSION, (int __user *)arg) ? -EFAULT : 0; - case SNDRV_SEQ_IOCTL_CLIENT_ID: - /* return the id of this client */ - return put_user(client->number, (int __user *)arg) ? -EFAULT : 0; - } - - if (! arg) - return -EFAULT; - for (p = ioctl_tables; p->cmd; p++) { - if (p->cmd == cmd) - return p->func(client, arg); - } - snd_printd("seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", - cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); - return -ENOTTY; -} - - -static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_seq_client *client = file->private_data; - - if (snd_BUG_ON(!client)) - return -ENXIO; - - return snd_seq_do_ioctl(client, cmd, (void __user *) arg); -} - -#ifdef CONFIG_COMPAT -#include "seq_compat.c" -#else -#define snd_seq_ioctl_compat NULL -#endif - -/* -------------------------------------------------------- */ - - -/* exported to kernel modules */ -int snd_seq_create_kernel_client(struct snd_card *card, int client_index, - const char *name_fmt, ...) -{ - struct snd_seq_client *client; - va_list args; - - if (snd_BUG_ON(in_interrupt())) - return -EBUSY; - - if (card && client_index >= SNDRV_SEQ_CLIENTS_PER_CARD) - return -EINVAL; - if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS) - return -EINVAL; - - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; - - if (card) { - client_index += SNDRV_SEQ_GLOBAL_CLIENTS - + card->number * SNDRV_SEQ_CLIENTS_PER_CARD; - if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) - client_index = -1; - } - - /* empty write queue as default */ - client = seq_create_client1(client_index, 0); - if (client == NULL) { - mutex_unlock(®ister_mutex); - return -EBUSY; /* failure code */ - } - usage_alloc(&client_usage, 1); - - client->accept_input = 1; - client->accept_output = 1; - - va_start(args, name_fmt); - vsnprintf(client->name, sizeof(client->name), name_fmt, args); - va_end(args); - - client->type = KERNEL_CLIENT; - mutex_unlock(®ister_mutex); - - /* make others aware this new client */ - snd_seq_system_client_ev_client_start(client->number); - - /* return client number to caller */ - return client->number; -} - -EXPORT_SYMBOL(snd_seq_create_kernel_client); - -/* exported to kernel modules */ -int snd_seq_delete_kernel_client(int client) -{ - struct snd_seq_client *ptr; - - if (snd_BUG_ON(in_interrupt())) - return -EBUSY; - - ptr = clientptr(client); - if (ptr == NULL) - return -EINVAL; - - seq_free_client(ptr); - kfree(ptr); - return 0; -} - -EXPORT_SYMBOL(snd_seq_delete_kernel_client); - -/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue - * and snd_seq_kernel_client_enqueue_blocking - */ -static int kernel_client_enqueue(int client, struct snd_seq_event *ev, - struct file *file, int blocking, - int atomic, int hop) -{ - struct snd_seq_client *cptr; - int result; - - if (snd_BUG_ON(!ev)) - return -EINVAL; - - if (ev->type == SNDRV_SEQ_EVENT_NONE) - return 0; /* ignore this */ - if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR) - return -EINVAL; /* quoted events can't be enqueued */ - - /* fill in client number */ - ev->source.client = client; - - if (check_event_type_and_length(ev)) - return -EINVAL; - - cptr = snd_seq_client_use_ptr(client); - if (cptr == NULL) - return -EINVAL; - - if (! cptr->accept_output) - result = -EPERM; - else /* send it */ - result = snd_seq_client_enqueue_event(cptr, ev, file, blocking, atomic, hop); - - snd_seq_client_unlock(cptr); - return result; -} - -/* - * exported, called by kernel clients to enqueue events (w/o blocking) - * - * RETURN VALUE: zero if succeed, negative if error - */ -int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev, - int atomic, int hop) -{ - return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); -} - -EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); - -/* - * exported, called by kernel clients to enqueue events (with blocking) - * - * RETURN VALUE: zero if succeed, negative if error - */ -int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev, - struct file *file, - int atomic, int hop) -{ - return kernel_client_enqueue(client, ev, file, 1, atomic, hop); -} - -EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); - -/* - * exported, called by kernel clients to dispatch events directly to other - * clients, bypassing the queues. Event time-stamp will be updated. - * - * RETURN VALUE: negative = delivery failed, - * zero, or positive: the number of delivered events - */ -int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, - int atomic, int hop) -{ - struct snd_seq_client *cptr; - int result; - - if (snd_BUG_ON(!ev)) - return -EINVAL; - - /* fill in client number */ - ev->queue = SNDRV_SEQ_QUEUE_DIRECT; - ev->source.client = client; - - if (check_event_type_and_length(ev)) - return -EINVAL; - - cptr = snd_seq_client_use_ptr(client); - if (cptr == NULL) - return -EINVAL; - - if (!cptr->accept_output) - result = -EPERM; - else - result = snd_seq_deliver_event(cptr, ev, atomic, hop); - - snd_seq_client_unlock(cptr); - return result; -} - -EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); - -/* - * exported, called by kernel clients to perform same functions as with - * userland ioctl() - */ -int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) -{ - struct snd_seq_client *client; - mm_segment_t fs; - int result; - - client = clientptr(clientid); - if (client == NULL) - return -ENXIO; - fs = snd_enter_user(); - result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg); - snd_leave_user(fs); - return result; -} - -EXPORT_SYMBOL(snd_seq_kernel_client_ctl); - -/* exported (for OSS emulator) */ -int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait) -{ - struct snd_seq_client *client; - - client = clientptr(clientid); - if (client == NULL) - return -ENXIO; - - if (! snd_seq_write_pool_allocated(client)) - return 1; - if (snd_seq_pool_poll_wait(client->pool, file, wait)) - return 1; - return 0; -} - -EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); - -/*---------------------------------------------------------------------------*/ - -#ifdef CONFIG_PROC_FS -/* - * /proc interface - */ -static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer, - struct snd_seq_port_subs_info *group, - int is_src, char *msg) -{ - struct list_head *p; - struct snd_seq_subscribers *s; - int count = 0; - - down_read(&group->list_mutex); - if (list_empty(&group->list_head)) { - up_read(&group->list_mutex); - return; - } - snd_iprintf(buffer, msg); - list_for_each(p, &group->list_head) { - if (is_src) - s = list_entry(p, struct snd_seq_subscribers, src_list); - else - s = list_entry(p, struct snd_seq_subscribers, dest_list); - if (count++) - snd_iprintf(buffer, ", "); - snd_iprintf(buffer, "%d:%d", - is_src ? s->info.dest.client : s->info.sender.client, - is_src ? s->info.dest.port : s->info.sender.port); - if (s->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) - snd_iprintf(buffer, "[%c:%d]", ((s->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) ? 'r' : 't'), s->info.queue); - if (group->exclusive) - snd_iprintf(buffer, "[ex]"); - } - up_read(&group->list_mutex); - snd_iprintf(buffer, "\n"); -} - -#define FLAG_PERM_RD(perm) ((perm) & SNDRV_SEQ_PORT_CAP_READ ? ((perm) & SNDRV_SEQ_PORT_CAP_SUBS_READ ? 'R' : 'r') : '-') -#define FLAG_PERM_WR(perm) ((perm) & SNDRV_SEQ_PORT_CAP_WRITE ? ((perm) & SNDRV_SEQ_PORT_CAP_SUBS_WRITE ? 'W' : 'w') : '-') -#define FLAG_PERM_EX(perm) ((perm) & SNDRV_SEQ_PORT_CAP_NO_EXPORT ? '-' : 'e') - -#define FLAG_PERM_DUPLEX(perm) ((perm) & SNDRV_SEQ_PORT_CAP_DUPLEX ? 'X' : '-') - -static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, - struct snd_seq_client *client) -{ - struct snd_seq_client_port *p; - - mutex_lock(&client->ports_mutex); - list_for_each_entry(p, &client->ports_list_head, list) { - snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c)\n", - p->addr.port, p->name, - FLAG_PERM_RD(p->capability), - FLAG_PERM_WR(p->capability), - FLAG_PERM_EX(p->capability), - FLAG_PERM_DUPLEX(p->capability)); - snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: "); - snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: "); - } - mutex_unlock(&client->ports_mutex); -} - - -/* exported to seq_info.c */ -void snd_seq_info_clients_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - int c; - struct snd_seq_client *client; - - snd_iprintf(buffer, "Client info\n"); - snd_iprintf(buffer, " cur clients : %d\n", client_usage.cur); - snd_iprintf(buffer, " peak clients : %d\n", client_usage.peak); - snd_iprintf(buffer, " max clients : %d\n", SNDRV_SEQ_MAX_CLIENTS); - snd_iprintf(buffer, "\n"); - - /* list the client table */ - for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) { - client = snd_seq_client_use_ptr(c); - if (client == NULL) - continue; - if (client->type == NO_CLIENT) { - snd_seq_client_unlock(client); - continue; - } - - snd_iprintf(buffer, "Client %3d : \"%s\" [%s]\n", - c, client->name, - client->type == USER_CLIENT ? "User" : "Kernel"); - snd_seq_info_dump_ports(buffer, client); - if (snd_seq_write_pool_allocated(client)) { - snd_iprintf(buffer, " Output pool :\n"); - snd_seq_info_pool(buffer, client->pool, " "); - } - if (client->type == USER_CLIENT && client->data.user.fifo && - client->data.user.fifo->pool) { - snd_iprintf(buffer, " Input pool :\n"); - snd_seq_info_pool(buffer, client->data.user.fifo->pool, " "); - } - snd_seq_client_unlock(client); - } -} -#endif /* CONFIG_PROC_FS */ - -/*---------------------------------------------------------------------------*/ - - -/* - * REGISTRATION PART - */ - -static const struct file_operations snd_seq_f_ops = -{ - .owner = THIS_MODULE, - .read = snd_seq_read, - .write = snd_seq_write, - .open = snd_seq_open, - .release = snd_seq_release, - .llseek = no_llseek, - .poll = snd_seq_poll, - .unlocked_ioctl = snd_seq_ioctl, - .compat_ioctl = snd_seq_ioctl_compat, -}; - -/* - * register sequencer device - */ -int __init snd_sequencer_device_init(void) -{ - int err; - - if (mutex_lock_interruptible(®ister_mutex)) - return -ERESTARTSYS; - - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, - &snd_seq_f_ops, NULL, "seq")) < 0) { - mutex_unlock(®ister_mutex); - return err; - } - - mutex_unlock(®ister_mutex); - - return 0; -} - - - -/* - * unregister sequencer device - */ -void __exit snd_sequencer_device_done(void) -{ - snd_unregister_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0); -} diff --git a/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h b/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h deleted file mode 100644 index 20f0a725..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_clientmgr.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ALSA sequencer Client Manager - * Copyright (c) 1998-1999 by Frank van de Pol - * - * - * 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 - * - */ -#ifndef __SND_SEQ_CLIENTMGR_H -#define __SND_SEQ_CLIENTMGR_H - -#include -#include -#include "seq_fifo.h" -#include "seq_ports.h" -#include "seq_lock.h" - - -/* client manager */ - -struct snd_seq_user_client { - struct file *file; /* file struct of client */ - /* ... */ - - /* fifo */ - struct snd_seq_fifo *fifo; /* queue for incoming events */ - int fifo_pool_size; -}; - -struct snd_seq_kernel_client { - /* ... */ -}; - - -struct snd_seq_client { - snd_seq_client_type_t type; - unsigned int accept_input: 1, - accept_output: 1; - char name[64]; /* client name */ - int number; /* client number */ - unsigned int filter; /* filter flags */ - DECLARE_BITMAP(event_filter, 256); - snd_use_lock_t use_lock; - int event_lost; - /* ports */ - int num_ports; /* number of ports */ - struct list_head ports_list_head; - rwlock_t ports_lock; - struct mutex ports_mutex; - int convert32; /* convert 32->64bit */ - - /* output pool */ - struct snd_seq_pool *pool; /* memory pool for this client */ - - union { - struct snd_seq_user_client user; - struct snd_seq_kernel_client kernel; - } data; -}; - -/* usage statistics */ -struct snd_seq_usage { - int cur; - int peak; -}; - - -int client_init_data(void); -int snd_sequencer_device_init(void); -void snd_sequencer_device_done(void); - -/* get locked pointer to client */ -struct snd_seq_client *snd_seq_client_use_ptr(int clientid); - -/* unlock pointer to client */ -#define snd_seq_client_unlock(client) snd_use_lock_free(&(client)->use_lock) - -/* dispatch event to client(s) */ -int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop); - -/* exported to other modules */ -int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, int atomic, int hop); -int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev, - struct file *file, int atomic, int hop); -int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait); -int snd_seq_client_notify_subscription(int client, int port, - struct snd_seq_port_subscribe *info, int evtype); - -extern int seq_client_load[15]; - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_compat.c b/ANDROID_3.4.5/sound/core/seq/seq_compat.c deleted file mode 100644 index 81f7c109..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_compat.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for sequencer API - * Copyright (c) by Takashi Iwai - * - * 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 - * - */ - -/* This file included from seq.c */ - -#include -#include - -struct snd_seq_port_info32 { - struct snd_seq_addr addr; /* client/port numbers */ - char name[64]; /* port name */ - - u32 capability; /* port capability bits */ - u32 type; /* port type bits */ - s32 midi_channels; /* channels per MIDI port */ - s32 midi_voices; /* voices per MIDI port */ - s32 synth_voices; /* voices per SYNTH port */ - - s32 read_use; /* R/O: subscribers for output (from this port) */ - s32 write_use; /* R/O: subscribers for input (to this port) */ - - u32 kernel; /* reserved for kernel use (must be NULL) */ - u32 flags; /* misc. conditioning */ - unsigned char time_queue; /* queue # for timestamping */ - char reserved[59]; /* for future use */ -}; - -static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd, - struct snd_seq_port_info32 __user *data32) -{ - int err = -EFAULT; - struct snd_seq_port_info *data; - mm_segment_t fs; - - data = memdup_user(data32, sizeof(*data32)); - if (IS_ERR(data)) - return PTR_ERR(data); - - if (get_user(data->flags, &data32->flags) || - get_user(data->time_queue, &data32->time_queue)) - goto error; - data->kernel = NULL; - - fs = snd_enter_user(); - err = snd_seq_do_ioctl(client, cmd, data); - snd_leave_user(fs); - if (err < 0) - goto error; - - if (copy_to_user(data32, data, sizeof(*data32)) || - put_user(data->flags, &data32->flags) || - put_user(data->time_queue, &data32->time_queue)) - err = -EFAULT; - - error: - kfree(data); - return err; -} - - - -/* - */ - -enum { - SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct snd_seq_port_info32), - SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct snd_seq_port_info32), - SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct snd_seq_port_info32), - SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct snd_seq_port_info32), - SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct snd_seq_port_info32), -}; - -static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_seq_client *client = file->private_data; - void __user *argp = compat_ptr(arg); - - if (snd_BUG_ON(!client)) - return -ENXIO; - - switch (cmd) { - case SNDRV_SEQ_IOCTL_PVERSION: - case SNDRV_SEQ_IOCTL_CLIENT_ID: - case SNDRV_SEQ_IOCTL_SYSTEM_INFO: - case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO: - case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO: - case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT: - case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT: - case SNDRV_SEQ_IOCTL_CREATE_QUEUE: - case SNDRV_SEQ_IOCTL_DELETE_QUEUE: - case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO: - case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO: - case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE: - case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS: - case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO: - case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO: - case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER: - case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER: - case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT: - case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT: - case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL: - case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL: - case SNDRV_SEQ_IOCTL_REMOVE_EVENTS: - case SNDRV_SEQ_IOCTL_QUERY_SUBS: - case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: - case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: - case SNDRV_SEQ_IOCTL_RUNNING_MODE: - return snd_seq_do_ioctl(client, cmd, argp); - case SNDRV_SEQ_IOCTL_CREATE_PORT32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); - case SNDRV_SEQ_IOCTL_DELETE_PORT32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp); - case SNDRV_SEQ_IOCTL_GET_PORT_INFO32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp); - case SNDRV_SEQ_IOCTL_SET_PORT_INFO32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp); - case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32: - return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp); - } - return -ENOIOCTLCMD; -} diff --git a/ANDROID_3.4.5/sound/core/seq/seq_device.c b/ANDROID_3.4.5/sound/core/seq/seq_device.c deleted file mode 100644 index 5cf8d65e..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_device.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * ALSA sequencer device management - * Copyright (c) 1999 by Takashi Iwai - * - * 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 - * - * - *---------------------------------------------------------------- - * - * This device handler separates the card driver module from sequencer - * stuff (sequencer core, synth drivers, etc), so that user can avoid - * to spend unnecessary resources e.g. if he needs only listening to - * MP3s. - * - * The card (or lowlevel) driver creates a sequencer device entry - * via snd_seq_device_new(). This is an entry pointer to communicate - * with the sequencer device "driver", which is involved with the - * actual part to communicate with the sequencer core. - * Each sequencer device entry has an id string and the corresponding - * driver with the same id is loaded when required. For example, - * lowlevel codes to access emu8000 chip on sbawe card are included in - * emu8000-synth module. To activate this module, the hardware - * resources like i/o port are passed via snd_seq_device argument. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("ALSA sequencer device management"); -MODULE_LICENSE("GPL"); - -/* driver state */ -#define DRIVER_EMPTY 0 -#define DRIVER_LOADED (1<<0) -#define DRIVER_REQUESTED (1<<1) -#define DRIVER_LOCKED (1<<2) - -struct ops_list { - char id[ID_LEN]; /* driver id */ - int driver; /* driver state */ - int used; /* reference counter */ - int argsize; /* argument size */ - - /* operators */ - struct snd_seq_dev_ops ops; - - /* registred devices */ - struct list_head dev_list; /* list of devices */ - int num_devices; /* number of associated devices */ - int num_init_devices; /* number of initialized devices */ - struct mutex reg_mutex; - - struct list_head list; /* next driver */ -}; - - -static LIST_HEAD(opslist); -static int num_ops; -static DEFINE_MUTEX(ops_mutex); -#ifdef CONFIG_PROC_FS -static struct snd_info_entry *info_entry; -#endif - -/* - * prototypes - */ -static int snd_seq_device_free(struct snd_seq_device *dev); -static int snd_seq_device_dev_free(struct snd_device *device); -static int snd_seq_device_dev_register(struct snd_device *device); -static int snd_seq_device_dev_disconnect(struct snd_device *device); - -static int init_device(struct snd_seq_device *dev, struct ops_list *ops); -static int free_device(struct snd_seq_device *dev, struct ops_list *ops); -static struct ops_list *find_driver(char *id, int create_if_empty); -static struct ops_list *create_driver(char *id); -static void unlock_driver(struct ops_list *ops); -static void remove_drivers(void); - -/* - * show all drivers and their status - */ - -#ifdef CONFIG_PROC_FS -static void snd_seq_device_info(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct ops_list *ops; - - mutex_lock(&ops_mutex); - list_for_each_entry(ops, &opslist, list) { - snd_iprintf(buffer, "snd-%s%s%s%s,%d\n", - ops->id, - ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""), - ops->driver & DRIVER_REQUESTED ? ",requested" : "", - ops->driver & DRIVER_LOCKED ? ",locked" : "", - ops->num_devices); - } - mutex_unlock(&ops_mutex); -} -#endif - -/* - * load all registered drivers (called from seq_clientmgr.c) - */ - -#ifdef CONFIG_MODULES -/* avoid auto-loading during module_init() */ -static int snd_seq_in_init; -void snd_seq_autoload_lock(void) -{ - snd_seq_in_init++; -} - -void snd_seq_autoload_unlock(void) -{ - snd_seq_in_init--; -} -#endif - -void snd_seq_device_load_drivers(void) -{ -#ifdef CONFIG_MODULES - struct ops_list *ops; - - /* Calling request_module during module_init() - * may cause blocking. - */ - if (snd_seq_in_init) - return; - - mutex_lock(&ops_mutex); - list_for_each_entry(ops, &opslist, list) { - if (! (ops->driver & DRIVER_LOADED) && - ! (ops->driver & DRIVER_REQUESTED)) { - ops->used++; - mutex_unlock(&ops_mutex); - ops->driver |= DRIVER_REQUESTED; - request_module("snd-%s", ops->id); - mutex_lock(&ops_mutex); - ops->used--; - } - } - mutex_unlock(&ops_mutex); -#endif -} - -/* - * register a sequencer device - * card = card info (NULL allowed) - * device = device number (if any) - * id = id of driver - * result = return pointer (NULL allowed if unnecessary) - */ -int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, - struct snd_seq_device **result) -{ - struct snd_seq_device *dev; - struct ops_list *ops; - int err; - static struct snd_device_ops dops = { - .dev_free = snd_seq_device_dev_free, - .dev_register = snd_seq_device_dev_register, - .dev_disconnect = snd_seq_device_dev_disconnect, - }; - - if (result) - *result = NULL; - - if (snd_BUG_ON(!id)) - return -EINVAL; - - ops = find_driver(id, 1); - if (ops == NULL) - return -ENOMEM; - - dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL); - if (dev == NULL) { - unlock_driver(ops); - return -ENOMEM; - } - - /* set up device info */ - dev->card = card; - dev->device = device; - strlcpy(dev->id, id, sizeof(dev->id)); - dev->argsize = argsize; - dev->status = SNDRV_SEQ_DEVICE_FREE; - - /* add this device to the list */ - mutex_lock(&ops->reg_mutex); - list_add_tail(&dev->list, &ops->dev_list); - ops->num_devices++; - mutex_unlock(&ops->reg_mutex); - - unlock_driver(ops); - - if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) { - snd_seq_device_free(dev); - return err; - } - - if (result) - *result = dev; - - return 0; -} - -/* - * free the existing device - */ -static int snd_seq_device_free(struct snd_seq_device *dev) -{ - struct ops_list *ops; - - if (snd_BUG_ON(!dev)) - return -EINVAL; - - ops = find_driver(dev->id, 0); - if (ops == NULL) - return -ENXIO; - - /* remove the device from the list */ - mutex_lock(&ops->reg_mutex); - list_del(&dev->list); - ops->num_devices--; - mutex_unlock(&ops->reg_mutex); - - free_device(dev, ops); - if (dev->private_free) - dev->private_free(dev); - kfree(dev); - - unlock_driver(ops); - - return 0; -} - -static int snd_seq_device_dev_free(struct snd_device *device) -{ - struct snd_seq_device *dev = device->device_data; - return snd_seq_device_free(dev); -} - -/* - * register the device - */ -static int snd_seq_device_dev_register(struct snd_device *device) -{ - struct snd_seq_device *dev = device->device_data; - struct ops_list *ops; - - ops = find_driver(dev->id, 0); - if (ops == NULL) - return -ENOENT; - - /* initialize this device if the corresponding driver was - * already loaded - */ - if (ops->driver & DRIVER_LOADED) - init_device(dev, ops); - - unlock_driver(ops); - return 0; -} - -/* - * disconnect the device - */ -static int snd_seq_device_dev_disconnect(struct snd_device *device) -{ - struct snd_seq_device *dev = device->device_data; - struct ops_list *ops; - - ops = find_driver(dev->id, 0); - if (ops == NULL) - return -ENOENT; - - free_device(dev, ops); - - unlock_driver(ops); - return 0; -} - -/* - * register device driver - * id = driver id - * entry = driver operators - duplicated to each instance - */ -int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, - int argsize) -{ - struct ops_list *ops; - struct snd_seq_device *dev; - - if (id == NULL || entry == NULL || - entry->init_device == NULL || entry->free_device == NULL) - return -EINVAL; - - snd_seq_autoload_lock(); - ops = find_driver(id, 1); - if (ops == NULL) { - snd_seq_autoload_unlock(); - return -ENOMEM; - } - if (ops->driver & DRIVER_LOADED) { - snd_printk(KERN_WARNING "driver_register: driver '%s' already exists\n", id); - unlock_driver(ops); - snd_seq_autoload_unlock(); - return -EBUSY; - } - - mutex_lock(&ops->reg_mutex); - /* copy driver operators */ - ops->ops = *entry; - ops->driver |= DRIVER_LOADED; - ops->argsize = argsize; - - /* initialize existing devices if necessary */ - list_for_each_entry(dev, &ops->dev_list, list) { - init_device(dev, ops); - } - mutex_unlock(&ops->reg_mutex); - - unlock_driver(ops); - snd_seq_autoload_unlock(); - - return 0; -} - - -/* - * create driver record - */ -static struct ops_list * create_driver(char *id) -{ - struct ops_list *ops; - - ops = kzalloc(sizeof(*ops), GFP_KERNEL); - if (ops == NULL) - return ops; - - /* set up driver entry */ - strlcpy(ops->id, id, sizeof(ops->id)); - mutex_init(&ops->reg_mutex); - /* - * The ->reg_mutex locking rules are per-driver, so we create - * separate per-driver lock classes: - */ - lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id); - - ops->driver = DRIVER_EMPTY; - INIT_LIST_HEAD(&ops->dev_list); - /* lock this instance */ - ops->used = 1; - - /* register driver entry */ - mutex_lock(&ops_mutex); - list_add_tail(&ops->list, &opslist); - num_ops++; - mutex_unlock(&ops_mutex); - - return ops; -} - - -/* - * unregister the specified driver - */ -int snd_seq_device_unregister_driver(char *id) -{ - struct ops_list *ops; - struct snd_seq_device *dev; - - ops = find_driver(id, 0); - if (ops == NULL) - return -ENXIO; - if (! (ops->driver & DRIVER_LOADED) || - (ops->driver & DRIVER_LOCKED)) { - snd_printk(KERN_ERR "driver_unregister: cannot unload driver '%s': status=%x\n", - id, ops->driver); - unlock_driver(ops); - return -EBUSY; - } - - /* close and release all devices associated with this driver */ - mutex_lock(&ops->reg_mutex); - ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */ - list_for_each_entry(dev, &ops->dev_list, list) { - free_device(dev, ops); - } - - ops->driver = 0; - if (ops->num_init_devices > 0) - snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n", - ops->num_init_devices); - mutex_unlock(&ops->reg_mutex); - - unlock_driver(ops); - - /* remove empty driver entries */ - remove_drivers(); - - return 0; -} - - -/* - * remove empty driver entries - */ -static void remove_drivers(void) -{ - struct list_head *head; - - mutex_lock(&ops_mutex); - head = opslist.next; - while (head != &opslist) { - struct ops_list *ops = list_entry(head, struct ops_list, list); - if (! (ops->driver & DRIVER_LOADED) && - ops->used == 0 && ops->num_devices == 0) { - head = head->next; - list_del(&ops->list); - kfree(ops); - num_ops--; - } else - head = head->next; - } - mutex_unlock(&ops_mutex); -} - -/* - * initialize the device - call init_device operator - */ -static int init_device(struct snd_seq_device *dev, struct ops_list *ops) -{ - if (! (ops->driver & DRIVER_LOADED)) - return 0; /* driver is not loaded yet */ - if (dev->status != SNDRV_SEQ_DEVICE_FREE) - return 0; /* already initialized */ - if (ops->argsize != dev->argsize) { - snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n", - dev->name, ops->id, ops->argsize, dev->argsize); - return -EINVAL; - } - if (ops->ops.init_device(dev) >= 0) { - dev->status = SNDRV_SEQ_DEVICE_REGISTERED; - ops->num_init_devices++; - } else { - snd_printk(KERN_ERR "init_device failed: %s: %s\n", - dev->name, dev->id); - } - - return 0; -} - -/* - * release the device - call free_device operator - */ -static int free_device(struct snd_seq_device *dev, struct ops_list *ops) -{ - int result; - - if (! (ops->driver & DRIVER_LOADED)) - return 0; /* driver is not loaded yet */ - if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED) - return 0; /* not registered */ - if (ops->argsize != dev->argsize) { - snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n", - dev->name, ops->id, ops->argsize, dev->argsize); - return -EINVAL; - } - if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) { - dev->status = SNDRV_SEQ_DEVICE_FREE; - dev->driver_data = NULL; - ops->num_init_devices--; - } else { - snd_printk(KERN_ERR "free_device failed: %s: %s\n", - dev->name, dev->id); - } - - return 0; -} - -/* - * find the matching driver with given id - */ -static struct ops_list * find_driver(char *id, int create_if_empty) -{ - struct ops_list *ops; - - mutex_lock(&ops_mutex); - list_for_each_entry(ops, &opslist, list) { - if (strcmp(ops->id, id) == 0) { - ops->used++; - mutex_unlock(&ops_mutex); - return ops; - } - } - mutex_unlock(&ops_mutex); - if (create_if_empty) - return create_driver(id); - return NULL; -} - -static void unlock_driver(struct ops_list *ops) -{ - mutex_lock(&ops_mutex); - ops->used--; - mutex_unlock(&ops_mutex); -} - - -/* - * module part - */ - -static int __init alsa_seq_device_init(void) -{ -#ifdef CONFIG_PROC_FS - info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", - snd_seq_root); - if (info_entry == NULL) - return -ENOMEM; - info_entry->content = SNDRV_INFO_CONTENT_TEXT; - info_entry->c.text.read = snd_seq_device_info; - if (snd_info_register(info_entry) < 0) { - snd_info_free_entry(info_entry); - return -ENOMEM; - } -#endif - return 0; -} - -static void __exit alsa_seq_device_exit(void) -{ - remove_drivers(); -#ifdef CONFIG_PROC_FS - snd_info_free_entry(info_entry); -#endif - if (num_ops) - snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops); -} - -module_init(alsa_seq_device_init) -module_exit(alsa_seq_device_exit) - -EXPORT_SYMBOL(snd_seq_device_load_drivers); -EXPORT_SYMBOL(snd_seq_device_new); -EXPORT_SYMBOL(snd_seq_device_register_driver); -EXPORT_SYMBOL(snd_seq_device_unregister_driver); -EXPORT_SYMBOL(snd_seq_autoload_lock); -EXPORT_SYMBOL(snd_seq_autoload_unlock); diff --git a/ANDROID_3.4.5/sound/core/seq/seq_dummy.c b/ANDROID_3.4.5/sound/core/seq/seq_dummy.c deleted file mode 100644 index dbc55071..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_dummy.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * ALSA sequencer MIDI-through client - * Copyright (c) 1999-2000 by Takashi Iwai - * - * 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 "seq_clientmgr.h" -#include -#include - -/* - - Sequencer MIDI-through client - - This gives a simple midi-through client. All the normal input events - are redirected to output port immediately. - The routing can be done via aconnect program in alsa-utils. - - Each client has a static client number 62 (= SNDRV_SEQ_CLIENT_DUMMY). - If you want to auto-load this module, you may add the following alias - in your /etc/conf.modules file. - - alias snd-seq-client-62 snd-seq-dummy - - The module is loaded on demand for client 62, or /proc/asound/seq/ - is accessed. If you don't need this module to be loaded, alias - snd-seq-client-62 as "off". This will help modprobe. - - The number of ports to be created can be specified via the module - parameter "ports". For example, to create four ports, add the - following option in a configuration file under /etc/modprobe.d/: - - option snd-seq-dummy ports=4 - - The model option "duplex=1" enables duplex operation to the port. - In duplex mode, a pair of ports are created instead of single port, - and events are tunneled between pair-ports. For example, input to - port A is sent to output port of another port B and vice versa. - In duplex mode, each port has DUPLEX capability. - - */ - - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("ALSA sequencer MIDI-through client"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY)); - -static int ports = 1; -static bool duplex; - -module_param(ports, int, 0444); -MODULE_PARM_DESC(ports, "number of ports to be created"); -module_param(duplex, bool, 0444); -MODULE_PARM_DESC(duplex, "create DUPLEX ports"); - -struct snd_seq_dummy_port { - int client; - int port; - int duplex; - int connect; -}; - -static int my_client = -1; - -/* - * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events - * to subscribers. - * Note: this callback is called only after all subscribers are removed. - */ -static int -dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info) -{ - struct snd_seq_dummy_port *p; - int i; - struct snd_seq_event ev; - - p = private_data; - memset(&ev, 0, sizeof(ev)); - if (p->duplex) - ev.source.port = p->connect; - else - ev.source.port = p->port; - ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - ev.type = SNDRV_SEQ_EVENT_CONTROLLER; - for (i = 0; i < 16; i++) { - ev.data.control.channel = i; - ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF; - snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); - ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS; - snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); - } - return 0; -} - -/* - * event input callback - just redirect events to subscribers - */ -static int -dummy_input(struct snd_seq_event *ev, int direct, void *private_data, - int atomic, int hop) -{ - struct snd_seq_dummy_port *p; - struct snd_seq_event tmpev; - - p = private_data; - if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM || - ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR) - return 0; /* ignore system messages */ - tmpev = *ev; - if (p->duplex) - tmpev.source.port = p->connect; - else - tmpev.source.port = p->port; - tmpev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - return snd_seq_kernel_client_dispatch(p->client, &tmpev, atomic, hop); -} - -/* - * free_private callback - */ -static void -dummy_free(void *private_data) -{ - kfree(private_data); -} - -/* - * create a port - */ -static struct snd_seq_dummy_port __init * -create_port(int idx, int type) -{ - struct snd_seq_port_info pinfo; - struct snd_seq_port_callback pcb; - struct snd_seq_dummy_port *rec; - - if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) - return NULL; - - rec->client = my_client; - rec->duplex = duplex; - rec->connect = 0; - memset(&pinfo, 0, sizeof(pinfo)); - pinfo.addr.client = my_client; - if (duplex) - sprintf(pinfo.name, "Midi Through Port-%d:%c", idx, - (type ? 'B' : 'A')); - else - sprintf(pinfo.name, "Midi Through Port-%d", idx); - pinfo.capability = SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; - pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; - if (duplex) - pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; - pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC - | SNDRV_SEQ_PORT_TYPE_SOFTWARE - | SNDRV_SEQ_PORT_TYPE_PORT; - memset(&pcb, 0, sizeof(pcb)); - pcb.owner = THIS_MODULE; - pcb.unuse = dummy_unuse; - pcb.event_input = dummy_input; - pcb.private_free = dummy_free; - pcb.private_data = rec; - pinfo.kernel = &pcb; - if (snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo) < 0) { - kfree(rec); - return NULL; - } - rec->port = pinfo.addr.port; - return rec; -} - -/* - * register client and create ports - */ -static int __init -register_client(void) -{ - struct snd_seq_dummy_port *rec1, *rec2; - int i; - - if (ports < 1) { - snd_printk(KERN_ERR "invalid number of ports %d\n", ports); - return -EINVAL; - } - - /* create client */ - my_client = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_DUMMY, - "Midi Through"); - if (my_client < 0) - return my_client; - - /* create ports */ - for (i = 0; i < ports; i++) { - rec1 = create_port(i, 0); - if (rec1 == NULL) { - snd_seq_delete_kernel_client(my_client); - return -ENOMEM; - } - if (duplex) { - rec2 = create_port(i, 1); - if (rec2 == NULL) { - snd_seq_delete_kernel_client(my_client); - return -ENOMEM; - } - rec1->connect = rec2->port; - rec2->connect = rec1->port; - } - } - - return 0; -} - -/* - * delete client if exists - */ -static void __exit -delete_client(void) -{ - if (my_client >= 0) - snd_seq_delete_kernel_client(my_client); -} - -/* - * Init part - */ - -static int __init alsa_seq_dummy_init(void) -{ - int err; - snd_seq_autoload_lock(); - err = register_client(); - snd_seq_autoload_unlock(); - return err; -} - -static void __exit alsa_seq_dummy_exit(void) -{ - delete_client(); -} - -module_init(alsa_seq_dummy_init) -module_exit(alsa_seq_dummy_exit) diff --git a/ANDROID_3.4.5/sound/core/seq/seq_fifo.c b/ANDROID_3.4.5/sound/core/seq/seq_fifo.c deleted file mode 100644 index 0d75afa7..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_fifo.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * ALSA sequencer FIFO - * Copyright (c) 1998 by Frank van de Pol - * - * - * 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 "seq_fifo.h" -#include "seq_lock.h" - - -/* FIFO */ - -/* create new fifo */ -struct snd_seq_fifo *snd_seq_fifo_new(int poolsize) -{ - struct snd_seq_fifo *f; - - f = kzalloc(sizeof(*f), GFP_KERNEL); - if (f == NULL) { - snd_printd("malloc failed for snd_seq_fifo_new() \n"); - return NULL; - } - - f->pool = snd_seq_pool_new(poolsize); - if (f->pool == NULL) { - kfree(f); - return NULL; - } - if (snd_seq_pool_init(f->pool) < 0) { - snd_seq_pool_delete(&f->pool); - kfree(f); - return NULL; - } - - spin_lock_init(&f->lock); - snd_use_lock_init(&f->use_lock); - init_waitqueue_head(&f->input_sleep); - atomic_set(&f->overflow, 0); - - f->head = NULL; - f->tail = NULL; - f->cells = 0; - - return f; -} - -void snd_seq_fifo_delete(struct snd_seq_fifo **fifo) -{ - struct snd_seq_fifo *f; - - if (snd_BUG_ON(!fifo)) - return; - f = *fifo; - if (snd_BUG_ON(!f)) - return; - *fifo = NULL; - - snd_seq_fifo_clear(f); - - /* wake up clients if any */ - if (waitqueue_active(&f->input_sleep)) - wake_up(&f->input_sleep); - - /* release resources...*/ - /*....................*/ - - if (f->pool) { - snd_seq_pool_done(f->pool); - snd_seq_pool_delete(&f->pool); - } - - kfree(f); -} - -static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f); - -/* clear queue */ -void snd_seq_fifo_clear(struct snd_seq_fifo *f) -{ - struct snd_seq_event_cell *cell; - unsigned long flags; - - /* clear overflow flag */ - atomic_set(&f->overflow, 0); - - snd_use_lock_sync(&f->use_lock); - spin_lock_irqsave(&f->lock, flags); - /* drain the fifo */ - while ((cell = fifo_cell_out(f)) != NULL) { - snd_seq_cell_free(cell); - } - spin_unlock_irqrestore(&f->lock, flags); -} - - -/* enqueue event to fifo */ -int snd_seq_fifo_event_in(struct snd_seq_fifo *f, - struct snd_seq_event *event) -{ - struct snd_seq_event_cell *cell; - unsigned long flags; - int err; - - if (snd_BUG_ON(!f)) - return -EINVAL; - - snd_use_lock_use(&f->use_lock); - err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL); /* always non-blocking */ - if (err < 0) { - if (err == -ENOMEM) - atomic_inc(&f->overflow); - snd_use_lock_free(&f->use_lock); - return err; - } - - /* append new cells to fifo */ - spin_lock_irqsave(&f->lock, flags); - if (f->tail != NULL) - f->tail->next = cell; - f->tail = cell; - if (f->head == NULL) - f->head = cell; - f->cells++; - spin_unlock_irqrestore(&f->lock, flags); - - /* wakeup client */ - if (waitqueue_active(&f->input_sleep)) - wake_up(&f->input_sleep); - - snd_use_lock_free(&f->use_lock); - - return 0; /* success */ - -} - -/* dequeue cell from fifo */ -static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f) -{ - struct snd_seq_event_cell *cell; - - if ((cell = f->head) != NULL) { - f->head = cell->next; - - /* reset tail if this was the last element */ - if (f->tail == cell) - f->tail = NULL; - - cell->next = NULL; - f->cells--; - } - - return cell; -} - -/* dequeue cell from fifo and copy on user space */ -int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, - struct snd_seq_event_cell **cellp, int nonblock) -{ - struct snd_seq_event_cell *cell; - unsigned long flags; - wait_queue_t wait; - - if (snd_BUG_ON(!f)) - return -EINVAL; - - *cellp = NULL; - init_waitqueue_entry(&wait, current); - spin_lock_irqsave(&f->lock, flags); - while ((cell = fifo_cell_out(f)) == NULL) { - if (nonblock) { - /* non-blocking - return immediately */ - spin_unlock_irqrestore(&f->lock, flags); - return -EAGAIN; - } - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&f->input_sleep, &wait); - spin_unlock_irq(&f->lock); - schedule(); - spin_lock_irq(&f->lock); - remove_wait_queue(&f->input_sleep, &wait); - if (signal_pending(current)) { - spin_unlock_irqrestore(&f->lock, flags); - return -ERESTARTSYS; - } - } - spin_unlock_irqrestore(&f->lock, flags); - *cellp = cell; - - return 0; -} - - -void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f, - struct snd_seq_event_cell *cell) -{ - unsigned long flags; - - if (cell) { - spin_lock_irqsave(&f->lock, flags); - cell->next = f->head; - f->head = cell; - f->cells++; - spin_unlock_irqrestore(&f->lock, flags); - } -} - - -/* polling; return non-zero if queue is available */ -int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, - poll_table *wait) -{ - poll_wait(file, &f->input_sleep, wait); - return (f->cells > 0); -} - -/* change the size of pool; all old events are removed */ -int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) -{ - unsigned long flags; - struct snd_seq_pool *newpool, *oldpool; - struct snd_seq_event_cell *cell, *next, *oldhead; - - if (snd_BUG_ON(!f || !f->pool)) - return -EINVAL; - - /* allocate new pool */ - newpool = snd_seq_pool_new(poolsize); - if (newpool == NULL) - return -ENOMEM; - if (snd_seq_pool_init(newpool) < 0) { - snd_seq_pool_delete(&newpool); - return -ENOMEM; - } - - spin_lock_irqsave(&f->lock, flags); - /* remember old pool */ - oldpool = f->pool; - oldhead = f->head; - /* exchange pools */ - f->pool = newpool; - f->head = NULL; - f->tail = NULL; - f->cells = 0; - /* NOTE: overflow flag is not cleared */ - spin_unlock_irqrestore(&f->lock, flags); - - /* release cells in old pool */ - for (cell = oldhead; cell; cell = next) { - next = cell->next; - snd_seq_cell_free(cell); - } - snd_seq_pool_delete(&oldpool); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/core/seq/seq_fifo.h b/ANDROID_3.4.5/sound/core/seq/seq_fifo.h deleted file mode 100644 index 062c446e..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_fifo.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ALSA sequencer FIFO - * Copyright (c) 1998 by Frank van de Pol - * - * - * 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 - * - */ -#ifndef __SND_SEQ_FIFO_H -#define __SND_SEQ_FIFO_H - -#include "seq_memory.h" -#include "seq_lock.h" - - -/* === FIFO === */ - -struct snd_seq_fifo { - struct snd_seq_pool *pool; /* FIFO pool */ - struct snd_seq_event_cell *head; /* pointer to head of fifo */ - struct snd_seq_event_cell *tail; /* pointer to tail of fifo */ - int cells; - spinlock_t lock; - snd_use_lock_t use_lock; - wait_queue_head_t input_sleep; - atomic_t overflow; - -}; - -/* create new fifo (constructor) */ -struct snd_seq_fifo *snd_seq_fifo_new(int poolsize); - -/* delete fifo (destructor) */ -void snd_seq_fifo_delete(struct snd_seq_fifo **f); - - -/* enqueue event to fifo */ -int snd_seq_fifo_event_in(struct snd_seq_fifo *f, struct snd_seq_event *event); - -/* lock fifo from release */ -#define snd_seq_fifo_lock(fifo) snd_use_lock_use(&(fifo)->use_lock) -#define snd_seq_fifo_unlock(fifo) snd_use_lock_free(&(fifo)->use_lock) - -/* get a cell from fifo - fifo should be locked */ -int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, struct snd_seq_event_cell **cellp, int nonblock); - -/* free dequeued cell - fifo should be locked */ -void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f, struct snd_seq_event_cell *cell); - -/* clean up queue */ -void snd_seq_fifo_clear(struct snd_seq_fifo *f); - -/* polling */ -int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, poll_table *wait); - -/* resize pool in fifo */ -int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize); - - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_info.c b/ANDROID_3.4.5/sound/core/seq/seq_info.c deleted file mode 100644 index acf77694..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_info.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ALSA sequencer /proc interface - * Copyright (c) 1998 by Frank van de Pol - * - * - * 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 "seq_info.h" -#include "seq_clientmgr.h" -#include "seq_timer.h" - -#ifdef CONFIG_PROC_FS -static struct snd_info_entry *queues_entry; -static struct snd_info_entry *clients_entry; -static struct snd_info_entry *timer_entry; - - -static struct snd_info_entry * __init -create_info_entry(char *name, void (*read)(struct snd_info_entry *, - struct snd_info_buffer *)) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, name, snd_seq_root); - if (entry == NULL) - return NULL; - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->c.text.read = read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - return NULL; - } - return entry; -} - -/* create all our /proc entries */ -int __init snd_seq_info_init(void) -{ - queues_entry = create_info_entry("queues", - snd_seq_info_queues_read); - clients_entry = create_info_entry("clients", - snd_seq_info_clients_read); - timer_entry = create_info_entry("timer", snd_seq_info_timer_read); - return 0; -} - -int __exit snd_seq_info_done(void) -{ - snd_info_free_entry(queues_entry); - snd_info_free_entry(clients_entry); - snd_info_free_entry(timer_entry); - return 0; -} -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_info.h b/ANDROID_3.4.5/sound/core/seq/seq_info.h deleted file mode 100644 index 4892a7f3..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_info.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * ALSA sequencer /proc info - * Copyright (c) 1998 by Frank van de Pol - * - * - * 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 - * - */ -#ifndef __SND_SEQ_INFO_H -#define __SND_SEQ_INFO_H - -#include -#include - -void snd_seq_info_clients_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); -void snd_seq_info_timer_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); -void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); - - -#ifdef CONFIG_PROC_FS -int snd_seq_info_init( void ); -int snd_seq_info_done( void ); -#else -static inline int snd_seq_info_init(void) { return 0; } -static inline int snd_seq_info_done(void) { return 0; } -#endif - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_lock.c b/ANDROID_3.4.5/sound/core/seq/seq_lock.c deleted file mode 100644 index 2cfe50c7..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_lock.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Do sleep inside a spin-lock - * Copyright (c) 1999 by Takashi Iwai - * - * - * 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 "seq_lock.h" - -#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG) - -/* wait until all locks are released */ -void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) -{ - int max_count = 5 * HZ; - - if (atomic_read(lockp) < 0) { - printk(KERN_WARNING "seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line); - return; - } - while (atomic_read(lockp) > 0) { - if (max_count == 0) { - snd_printk(KERN_WARNING "seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line); - break; - } - schedule_timeout_uninterruptible(1); - max_count--; - } -} - -EXPORT_SYMBOL(snd_use_lock_sync_helper); - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_lock.h b/ANDROID_3.4.5/sound/core/seq/seq_lock.h deleted file mode 100644 index 54044bc2..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_lock.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __SND_SEQ_LOCK_H -#define __SND_SEQ_LOCK_H - -#include - -#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG) - -typedef atomic_t snd_use_lock_t; - -/* initialize lock */ -#define snd_use_lock_init(lockp) atomic_set(lockp, 0) - -/* increment lock */ -#define snd_use_lock_use(lockp) atomic_inc(lockp) - -/* release lock */ -#define snd_use_lock_free(lockp) atomic_dec(lockp) - -/* wait until all locks are released */ -void snd_use_lock_sync_helper(snd_use_lock_t *lock, const char *file, int line); -#define snd_use_lock_sync(lockp) snd_use_lock_sync_helper(lockp, __BASE_FILE__, __LINE__) - -#else /* SMP || CONFIG_SND_DEBUG */ - -typedef spinlock_t snd_use_lock_t; /* dummy */ -#define snd_use_lock_init(lockp) /**/ -#define snd_use_lock_use(lockp) /**/ -#define snd_use_lock_free(lockp) /**/ -#define snd_use_lock_sync(lockp) /**/ - -#endif /* SMP || CONFIG_SND_DEBUG */ - -#endif /* __SND_SEQ_LOCK_H */ diff --git a/ANDROID_3.4.5/sound/core/seq/seq_memory.c b/ANDROID_3.4.5/sound/core/seq/seq_memory.c deleted file mode 100644 index f478f770..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_memory.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - * ALSA sequencer Memory Manager - * Copyright (c) 1998 by Frank van de Pol - * Jaroslav Kysela - * 2000 by Takashi Iwai - * - * 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 "seq_memory.h" -#include "seq_queue.h" -#include "seq_info.h" -#include "seq_lock.h" - -static inline int snd_seq_pool_available(struct snd_seq_pool *pool) -{ - return pool->total_elements - atomic_read(&pool->counter); -} - -static inline int snd_seq_output_ok(struct snd_seq_pool *pool) -{ - return snd_seq_pool_available(pool) >= pool->room; -} - -/* - * Variable length event: - * The event like sysex uses variable length type. - * The external data may be stored in three different formats. - * 1) kernel space - * This is the normal case. - * ext.data.len = length - * ext.data.ptr = buffer pointer - * 2) user space - * When an event is generated via read(), the external data is - * kept in user space until expanded. - * ext.data.len = length | SNDRV_SEQ_EXT_USRPTR - * ext.data.ptr = userspace pointer - * 3) chained cells - * When the variable length event is enqueued (in prioq or fifo), - * the external data is decomposed to several cells. - * ext.data.len = length | SNDRV_SEQ_EXT_CHAINED - * ext.data.ptr = the additiona cell head - * -> cell.next -> cell.next -> .. - */ - -/* - * exported: - * call dump function to expand external data. - */ - -static int get_var_len(const struct snd_seq_event *event) -{ - if ((event->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) - return -EINVAL; - - return event->data.ext.len & ~SNDRV_SEQ_EXT_MASK; -} - -int snd_seq_dump_var_event(const struct snd_seq_event *event, - snd_seq_dump_func_t func, void *private_data) -{ - int len, err; - struct snd_seq_event_cell *cell; - - if ((len = get_var_len(event)) <= 0) - return len; - - if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { - char buf[32]; - char __user *curptr = (char __force __user *)event->data.ext.ptr; - while (len > 0) { - int size = sizeof(buf); - if (len < size) - size = len; - if (copy_from_user(buf, curptr, size)) - return -EFAULT; - err = func(private_data, buf, size); - if (err < 0) - return err; - curptr += size; - len -= size; - } - return 0; - } if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) { - return func(private_data, event->data.ext.ptr, len); - } - - cell = (struct snd_seq_event_cell *)event->data.ext.ptr; - for (; len > 0 && cell; cell = cell->next) { - int size = sizeof(struct snd_seq_event); - if (len < size) - size = len; - err = func(private_data, &cell->event, size); - if (err < 0) - return err; - len -= size; - } - return 0; -} - -EXPORT_SYMBOL(snd_seq_dump_var_event); - - -/* - * exported: - * expand the variable length event to linear buffer space. - */ - -static int seq_copy_in_kernel(char **bufptr, const void *src, int size) -{ - memcpy(*bufptr, src, size); - *bufptr += size; - return 0; -} - -static int seq_copy_in_user(char __user **bufptr, const void *src, int size) -{ - if (copy_to_user(*bufptr, src, size)) - return -EFAULT; - *bufptr += size; - return 0; -} - -int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char *buf, - int in_kernel, int size_aligned) -{ - int len, newlen; - int err; - - if ((len = get_var_len(event)) < 0) - return len; - newlen = len; - if (size_aligned > 0) - newlen = roundup(len, size_aligned); - if (count < newlen) - return -EAGAIN; - - if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { - if (! in_kernel) - return -EINVAL; - if (copy_from_user(buf, (void __force __user *)event->data.ext.ptr, len)) - return -EFAULT; - return newlen; - } - err = snd_seq_dump_var_event(event, - in_kernel ? (snd_seq_dump_func_t)seq_copy_in_kernel : - (snd_seq_dump_func_t)seq_copy_in_user, - &buf); - return err < 0 ? err : newlen; -} - -EXPORT_SYMBOL(snd_seq_expand_var_event); - -/* - * release this cell, free extended data if available - */ - -static inline void free_cell(struct snd_seq_pool *pool, - struct snd_seq_event_cell *cell) -{ - cell->next = pool->free; - pool->free = cell; - atomic_dec(&pool->counter); -} - -void snd_seq_cell_free(struct snd_seq_event_cell * cell) -{ - unsigned long flags; - struct snd_seq_pool *pool; - - if (snd_BUG_ON(!cell)) - return; - pool = cell->pool; - if (snd_BUG_ON(!pool)) - return; - - spin_lock_irqsave(&pool->lock, flags); - free_cell(pool, cell); - if (snd_seq_ev_is_variable(&cell->event)) { - if (cell->event.data.ext.len & SNDRV_SEQ_EXT_CHAINED) { - struct snd_seq_event_cell *curp, *nextptr; - curp = cell->event.data.ext.ptr; - for (; curp; curp = nextptr) { - nextptr = curp->next; - curp->next = pool->free; - free_cell(pool, curp); - } - } - } - if (waitqueue_active(&pool->output_sleep)) { - /* has enough space now? */ - if (snd_seq_output_ok(pool)) - wake_up(&pool->output_sleep); - } - spin_unlock_irqrestore(&pool->lock, flags); -} - - -/* - * allocate an event cell. - */ -static int snd_seq_cell_alloc(struct snd_seq_pool *pool, - struct snd_seq_event_cell **cellp, - int nonblock, struct file *file) -{ - struct snd_seq_event_cell *cell; - unsigned long flags; - int err = -EAGAIN; - wait_queue_t wait; - - if (pool == NULL) - return -EINVAL; - - *cellp = NULL; - - init_waitqueue_entry(&wait, current); - spin_lock_irqsave(&pool->lock, flags); - if (pool->ptr == NULL) { /* not initialized */ - snd_printd("seq: pool is not initialized\n"); - err = -EINVAL; - goto __error; - } - while (pool->free == NULL && ! nonblock && ! pool->closing) { - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&pool->output_sleep, &wait); - spin_unlock_irq(&pool->lock); - schedule(); - spin_lock_irq(&pool->lock); - remove_wait_queue(&pool->output_sleep, &wait); - /* interrupted? */ - if (signal_pending(current)) { - err = -ERESTARTSYS; - goto __error; - } - } - if (pool->closing) { /* closing.. */ - err = -ENOMEM; - goto __error; - } - - cell = pool->free; - if (cell) { - int used; - pool->free = cell->next; - atomic_inc(&pool->counter); - used = atomic_read(&pool->counter); - if (pool->max_used < used) - pool->max_used = used; - pool->event_alloc_success++; - /* clear cell pointers */ - cell->next = NULL; - err = 0; - } else - pool->event_alloc_failures++; - *cellp = cell; - -__error: - spin_unlock_irqrestore(&pool->lock, flags); - return err; -} - - -/* - * duplicate the event to a cell. - * if the event has external data, the data is decomposed to additional - * cells. - */ -int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event, - struct snd_seq_event_cell **cellp, int nonblock, - struct file *file) -{ - int ncells, err; - unsigned int extlen; - struct snd_seq_event_cell *cell; - - *cellp = NULL; - - ncells = 0; - extlen = 0; - if (snd_seq_ev_is_variable(event)) { - extlen = event->data.ext.len & ~SNDRV_SEQ_EXT_MASK; - ncells = (extlen + sizeof(struct snd_seq_event) - 1) / sizeof(struct snd_seq_event); - } - if (ncells >= pool->total_elements) - return -ENOMEM; - - err = snd_seq_cell_alloc(pool, &cell, nonblock, file); - if (err < 0) - return err; - - /* copy the event */ - cell->event = *event; - - /* decompose */ - if (snd_seq_ev_is_variable(event)) { - int len = extlen; - int is_chained = event->data.ext.len & SNDRV_SEQ_EXT_CHAINED; - int is_usrptr = event->data.ext.len & SNDRV_SEQ_EXT_USRPTR; - struct snd_seq_event_cell *src, *tmp, *tail; - char *buf; - - cell->event.data.ext.len = extlen | SNDRV_SEQ_EXT_CHAINED; - cell->event.data.ext.ptr = NULL; - - src = (struct snd_seq_event_cell *)event->data.ext.ptr; - buf = (char *)event->data.ext.ptr; - tail = NULL; - - while (ncells-- > 0) { - int size = sizeof(struct snd_seq_event); - if (len < size) - size = len; - err = snd_seq_cell_alloc(pool, &tmp, nonblock, file); - if (err < 0) - goto __error; - if (cell->event.data.ext.ptr == NULL) - cell->event.data.ext.ptr = tmp; - if (tail) - tail->next = tmp; - tail = tmp; - /* copy chunk */ - if (is_chained && src) { - tmp->event = src->event; - src = src->next; - } else if (is_usrptr) { - if (copy_from_user(&tmp->event, (char __force __user *)buf, size)) { - err = -EFAULT; - goto __error; - } - } else { - memcpy(&tmp->event, buf, size); - } - buf += size; - len -= size; - } - } - - *cellp = cell; - return 0; - -__error: - snd_seq_cell_free(cell); - return err; -} - - -/* poll wait */ -int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, - poll_table *wait) -{ - poll_wait(file, &pool->output_sleep, wait); - return snd_seq_output_ok(pool); -} - - -/* allocate room specified number of events */ -int snd_seq_pool_init(struct snd_seq_pool *pool) -{ - int cell; - struct snd_seq_event_cell *cellptr; - unsigned long flags; - - if (snd_BUG_ON(!pool)) - return -EINVAL; - if (pool->ptr) /* should be atomic? */ - return 0; - - pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size); - if (pool->ptr == NULL) { - snd_printd("seq: malloc for sequencer events failed\n"); - return -ENOMEM; - } - - /* add new cells to the free cell list */ - spin_lock_irqsave(&pool->lock, flags); - pool->free = NULL; - - for (cell = 0; cell < pool->size; cell++) { - cellptr = pool->ptr + cell; - cellptr->pool = pool; - cellptr->next = pool->free; - pool->free = cellptr; - } - pool->room = (pool->size + 1) / 2; - - /* init statistics */ - pool->max_used = 0; - pool->total_elements = pool->size; - spin_unlock_irqrestore(&pool->lock, flags); - return 0; -} - -/* remove events */ -int snd_seq_pool_done(struct snd_seq_pool *pool) -{ - unsigned long flags; - struct snd_seq_event_cell *ptr; - int max_count = 5 * HZ; - - if (snd_BUG_ON(!pool)) - return -EINVAL; - - /* wait for closing all threads */ - spin_lock_irqsave(&pool->lock, flags); - pool->closing = 1; - spin_unlock_irqrestore(&pool->lock, flags); - - if (waitqueue_active(&pool->output_sleep)) - wake_up(&pool->output_sleep); - - while (atomic_read(&pool->counter) > 0) { - if (max_count == 0) { - snd_printk(KERN_WARNING "snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter)); - break; - } - schedule_timeout_uninterruptible(1); - max_count--; - } - - /* release all resources */ - spin_lock_irqsave(&pool->lock, flags); - ptr = pool->ptr; - pool->ptr = NULL; - pool->free = NULL; - pool->total_elements = 0; - spin_unlock_irqrestore(&pool->lock, flags); - - vfree(ptr); - - spin_lock_irqsave(&pool->lock, flags); - pool->closing = 0; - spin_unlock_irqrestore(&pool->lock, flags); - - return 0; -} - - -/* init new memory pool */ -struct snd_seq_pool *snd_seq_pool_new(int poolsize) -{ - struct snd_seq_pool *pool; - - /* create pool block */ - pool = kzalloc(sizeof(*pool), GFP_KERNEL); - if (pool == NULL) { - snd_printd("seq: malloc failed for pool\n"); - return NULL; - } - spin_lock_init(&pool->lock); - pool->ptr = NULL; - pool->free = NULL; - pool->total_elements = 0; - atomic_set(&pool->counter, 0); - pool->closing = 0; - init_waitqueue_head(&pool->output_sleep); - - pool->size = poolsize; - - /* init statistics */ - pool->max_used = 0; - return pool; -} - -/* remove memory pool */ -int snd_seq_pool_delete(struct snd_seq_pool **ppool) -{ - struct snd_seq_pool *pool = *ppool; - - *ppool = NULL; - if (pool == NULL) - return 0; - snd_seq_pool_done(pool); - kfree(pool); - return 0; -} - -/* initialize sequencer memory */ -int __init snd_sequencer_memory_init(void) -{ - return 0; -} - -/* release sequencer memory */ -void __exit snd_sequencer_memory_done(void) -{ -} - - -/* exported to seq_clientmgr.c */ -void snd_seq_info_pool(struct snd_info_buffer *buffer, - struct snd_seq_pool *pool, char *space) -{ - if (pool == NULL) - return; - snd_iprintf(buffer, "%sPool size : %d\n", space, pool->total_elements); - snd_iprintf(buffer, "%sCells in use : %d\n", space, atomic_read(&pool->counter)); - snd_iprintf(buffer, "%sPeak cells in use : %d\n", space, pool->max_used); - snd_iprintf(buffer, "%sAlloc success : %d\n", space, pool->event_alloc_success); - snd_iprintf(buffer, "%sAlloc failures : %d\n", space, pool->event_alloc_failures); -} diff --git a/ANDROID_3.4.5/sound/core/seq/seq_memory.h b/ANDROID_3.4.5/sound/core/seq/seq_memory.h deleted file mode 100644 index 4a2ec779..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_memory.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * ALSA sequencer Memory Manager - * Copyright (c) 1998 by Frank van de Pol - * - * - * 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 - * - */ -#ifndef __SND_SEQ_MEMORYMGR_H -#define __SND_SEQ_MEMORYMGR_H - -#include -#include - -struct snd_info_buffer; - -/* container for sequencer event (internal use) */ -struct snd_seq_event_cell { - struct snd_seq_event event; - struct snd_seq_pool *pool; /* used pool */ - struct snd_seq_event_cell *next; /* next cell */ -}; - -/* design note: the pool is a contiguous block of memory, if we dynamicly - want to add additional cells to the pool be better store this in another - pool as we need to know the base address of the pool when releasing - memory. */ - -struct snd_seq_pool { - struct snd_seq_event_cell *ptr; /* pointer to first event chunk */ - struct snd_seq_event_cell *free; /* pointer to the head of the free list */ - - int total_elements; /* pool size actually allocated */ - atomic_t counter; /* cells free */ - - int size; /* pool size to be allocated */ - int room; /* watermark for sleep/wakeup */ - - int closing; - - /* statistics */ - int max_used; - int event_alloc_nopool; - int event_alloc_failures; - int event_alloc_success; - - /* Write locking */ - wait_queue_head_t output_sleep; - - /* Pool lock */ - spinlock_t lock; -}; - -void snd_seq_cell_free(struct snd_seq_event_cell *cell); - -int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event, - struct snd_seq_event_cell **cellp, int nonblock, struct file *file); - -/* return number of unused (free) cells */ -static inline int snd_seq_unused_cells(struct snd_seq_pool *pool) -{ - return pool ? pool->total_elements - atomic_read(&pool->counter) : 0; -} - -/* return total number of allocated cells */ -static inline int snd_seq_total_cells(struct snd_seq_pool *pool) -{ - return pool ? pool->total_elements : 0; -} - -/* init pool - allocate events */ -int snd_seq_pool_init(struct snd_seq_pool *pool); - -/* done pool - free events */ -int snd_seq_pool_done(struct snd_seq_pool *pool); - -/* create pool */ -struct snd_seq_pool *snd_seq_pool_new(int poolsize); - -/* remove pool */ -int snd_seq_pool_delete(struct snd_seq_pool **pool); - -/* init memory */ -int snd_sequencer_memory_init(void); - -/* release event memory */ -void snd_sequencer_memory_done(void); - -/* polling */ -int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait); - -void snd_seq_info_pool(struct snd_info_buffer *buffer, - struct snd_seq_pool *pool, char *space); - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_midi.c b/ANDROID_3.4.5/sound/core/seq/seq_midi.c deleted file mode 100644 index 64069dbf..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_midi.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Generic MIDI synth driver for ALSA sequencer - * Copyright (c) 1998 by Frank van de Pol - * Jaroslav Kysela - * - * 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 - * - */ - -/* -Possible options for midisynth module: - - automatic opening of midi ports on first received event or subscription - (close will be performed when client leaves) -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Frank van de Pol , Jaroslav Kysela "); -MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth."); -MODULE_LICENSE("GPL"); -static int output_buffer_size = PAGE_SIZE; -module_param(output_buffer_size, int, 0644); -MODULE_PARM_DESC(output_buffer_size, "Output buffer size in bytes."); -static int input_buffer_size = PAGE_SIZE; -module_param(input_buffer_size, int, 0644); -MODULE_PARM_DESC(input_buffer_size, "Input buffer size in bytes."); - -/* data for this midi synth driver */ -struct seq_midisynth { - struct snd_card *card; - int device; - int subdevice; - struct snd_rawmidi_file input_rfile; - struct snd_rawmidi_file output_rfile; - int seq_client; - int seq_port; - struct snd_midi_event *parser; -}; - -struct seq_midisynth_client { - int seq_client; - int num_ports; - int ports_per_device[SNDRV_RAWMIDI_DEVICES]; - struct seq_midisynth *ports[SNDRV_RAWMIDI_DEVICES]; -}; - -static struct seq_midisynth_client *synths[SNDRV_CARDS]; -static DEFINE_MUTEX(register_mutex); - -/* handle rawmidi input event (MIDI v1.0 stream) */ -static void snd_midi_input_event(struct snd_rawmidi_substream *substream) -{ - struct snd_rawmidi_runtime *runtime; - struct seq_midisynth *msynth; - struct snd_seq_event ev; - char buf[16], *pbuf; - long res, count; - - if (substream == NULL) - return; - runtime = substream->runtime; - msynth = runtime->private_data; - if (msynth == NULL) - return; - memset(&ev, 0, sizeof(ev)); - while (runtime->avail > 0) { - res = snd_rawmidi_kernel_read(substream, buf, sizeof(buf)); - if (res <= 0) - continue; - if (msynth->parser == NULL) - continue; - pbuf = buf; - while (res > 0) { - count = snd_midi_event_encode(msynth->parser, pbuf, res, &ev); - if (count < 0) - break; - pbuf += count; - res -= count; - if (ev.type != SNDRV_SEQ_EVENT_NONE) { - ev.source.port = msynth->seq_port; - ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0); - /* clear event and reset header */ - memset(&ev, 0, sizeof(ev)); - } - } - } -} - -static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, int count) -{ - struct snd_rawmidi_runtime *runtime; - int tmp; - - if (snd_BUG_ON(!substream || !buf)) - return -EINVAL; - runtime = substream->runtime; - if ((tmp = runtime->avail) < count) { - if (printk_ratelimit()) - snd_printk(KERN_ERR "MIDI output buffer overrun\n"); - return -ENOMEM; - } - if (snd_rawmidi_kernel_write(substream, buf, count) < count) - return -EINVAL; - return 0; -} - -static int event_process_midi(struct snd_seq_event *ev, int direct, - void *private_data, int atomic, int hop) -{ - struct seq_midisynth *msynth = private_data; - unsigned char msg[10]; /* buffer for constructing midi messages */ - struct snd_rawmidi_substream *substream; - int len; - - if (snd_BUG_ON(!msynth)) - return -EINVAL; - substream = msynth->output_rfile.output; - if (substream == NULL) - return -ENODEV; - if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { /* special case, to save space */ - if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) { - /* invalid event */ - snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); - return 0; - } - snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); - snd_midi_event_reset_decode(msynth->parser); - } else { - if (msynth->parser == NULL) - return -EIO; - len = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev); - if (len < 0) - return 0; - if (dump_midi(substream, msg, len) < 0) - snd_midi_event_reset_decode(msynth->parser); - } - return 0; -} - - -static int snd_seq_midisynth_new(struct seq_midisynth *msynth, - struct snd_card *card, - int device, - int subdevice) -{ - if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &msynth->parser) < 0) - return -ENOMEM; - msynth->card = card; - msynth->device = device; - msynth->subdevice = subdevice; - return 0; -} - -/* open associated midi device for input */ -static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe *info) -{ - int err; - struct seq_midisynth *msynth = private_data; - struct snd_rawmidi_runtime *runtime; - struct snd_rawmidi_params params; - - /* open midi port */ - if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, - msynth->subdevice, - SNDRV_RAWMIDI_LFLG_INPUT, - &msynth->input_rfile)) < 0) { - snd_printd("midi input open failed!!!\n"); - return err; - } - runtime = msynth->input_rfile.input->runtime; - memset(¶ms, 0, sizeof(params)); - params.avail_min = 1; - params.buffer_size = input_buffer_size; - if ((err = snd_rawmidi_input_params(msynth->input_rfile.input, ¶ms)) < 0) { - snd_rawmidi_kernel_release(&msynth->input_rfile); - return err; - } - snd_midi_event_reset_encode(msynth->parser); - runtime->event = snd_midi_input_event; - runtime->private_data = msynth; - snd_rawmidi_kernel_read(msynth->input_rfile.input, NULL, 0); - return 0; -} - -/* close associated midi device for input */ -static int midisynth_unsubscribe(void *private_data, struct snd_seq_port_subscribe *info) -{ - int err; - struct seq_midisynth *msynth = private_data; - - if (snd_BUG_ON(!msynth->input_rfile.input)) - return -EINVAL; - err = snd_rawmidi_kernel_release(&msynth->input_rfile); - return err; -} - -/* open associated midi device for output */ -static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info) -{ - int err; - struct seq_midisynth *msynth = private_data; - struct snd_rawmidi_params params; - - /* open midi port */ - if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, - msynth->subdevice, - SNDRV_RAWMIDI_LFLG_OUTPUT, - &msynth->output_rfile)) < 0) { - snd_printd("midi output open failed!!!\n"); - return err; - } - memset(¶ms, 0, sizeof(params)); - params.avail_min = 1; - params.buffer_size = output_buffer_size; - params.no_active_sensing = 1; - if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms)) < 0) { - snd_rawmidi_kernel_release(&msynth->output_rfile); - return err; - } - snd_midi_event_reset_decode(msynth->parser); - return 0; -} - -/* close associated midi device for output */ -static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info) -{ - struct seq_midisynth *msynth = private_data; - - if (snd_BUG_ON(!msynth->output_rfile.output)) - return -EINVAL; - snd_rawmidi_drain_output(msynth->output_rfile.output); - return snd_rawmidi_kernel_release(&msynth->output_rfile); -} - -/* delete given midi synth port */ -static void snd_seq_midisynth_delete(struct seq_midisynth *msynth) -{ - if (msynth == NULL) - return; - - if (msynth->seq_client > 0) { - /* delete port */ - snd_seq_event_port_detach(msynth->seq_client, msynth->seq_port); - } - - if (msynth->parser) - snd_midi_event_free(msynth->parser); -} - -/* register new midi synth port */ -static int -snd_seq_midisynth_register_port(struct snd_seq_device *dev) -{ - struct seq_midisynth_client *client; - struct seq_midisynth *msynth, *ms; - struct snd_seq_port_info *port; - struct snd_rawmidi_info *info; - struct snd_rawmidi *rmidi = dev->private_data; - int newclient = 0; - unsigned int p, ports; - struct snd_seq_port_callback pcallbacks; - struct snd_card *card = dev->card; - int device = dev->device; - unsigned int input_count = 0, output_count = 0; - - if (snd_BUG_ON(!card || device < 0 || device >= SNDRV_RAWMIDI_DEVICES)) - return -EINVAL; - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (! info) - return -ENOMEM; - info->device = device; - info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT; - info->subdevice = 0; - if (snd_rawmidi_info_select(card, info) >= 0) - output_count = info->subdevices_count; - info->stream = SNDRV_RAWMIDI_STREAM_INPUT; - if (snd_rawmidi_info_select(card, info) >= 0) { - input_count = info->subdevices_count; - } - ports = output_count; - if (ports < input_count) - ports = input_count; - if (ports == 0) { - kfree(info); - return -ENODEV; - } - if (ports > (256 / SNDRV_RAWMIDI_DEVICES)) - ports = 256 / SNDRV_RAWMIDI_DEVICES; - - mutex_lock(®ister_mutex); - client = synths[card->number]; - if (client == NULL) { - newclient = 1; - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (client == NULL) { - mutex_unlock(®ister_mutex); - kfree(info); - return -ENOMEM; - } - client->seq_client = - snd_seq_create_kernel_client( - card, 0, "%s", card->shortname[0] ? - (const char *)card->shortname : "External MIDI"); - if (client->seq_client < 0) { - kfree(client); - mutex_unlock(®ister_mutex); - kfree(info); - return -ENOMEM; - } - } - - msynth = kcalloc(ports, sizeof(struct seq_midisynth), GFP_KERNEL); - port = kmalloc(sizeof(*port), GFP_KERNEL); - if (msynth == NULL || port == NULL) - goto __nomem; - - for (p = 0; p < ports; p++) { - ms = &msynth[p]; - - if (snd_seq_midisynth_new(ms, card, device, p) < 0) - goto __nomem; - - /* declare port */ - memset(port, 0, sizeof(*port)); - port->addr.client = client->seq_client; - port->addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p; - port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; - memset(info, 0, sizeof(*info)); - info->device = device; - if (p < output_count) - info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT; - else - info->stream = SNDRV_RAWMIDI_STREAM_INPUT; - info->subdevice = p; - if (snd_rawmidi_info_select(card, info) >= 0) - strcpy(port->name, info->subname); - if (! port->name[0]) { - if (info->name[0]) { - if (ports > 1) - snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p); - else - snprintf(port->name, sizeof(port->name), "%s", info->name); - } else { - /* last resort */ - if (ports > 1) - sprintf(port->name, "MIDI %d-%d-%d", card->number, device, p); - else - sprintf(port->name, "MIDI %d-%d", card->number, device); - } - } - if ((info->flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count) - port->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; - if ((info->flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count) - port->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; - if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && - info->flags & SNDRV_RAWMIDI_INFO_DUPLEX) - port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; - port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC - | SNDRV_SEQ_PORT_TYPE_HARDWARE - | SNDRV_SEQ_PORT_TYPE_PORT; - port->midi_channels = 16; - memset(&pcallbacks, 0, sizeof(pcallbacks)); - pcallbacks.owner = THIS_MODULE; - pcallbacks.private_data = ms; - pcallbacks.subscribe = midisynth_subscribe; - pcallbacks.unsubscribe = midisynth_unsubscribe; - pcallbacks.use = midisynth_use; - pcallbacks.unuse = midisynth_unuse; - pcallbacks.event_input = event_process_midi; - port->kernel = &pcallbacks; - if (rmidi->ops && rmidi->ops->get_port_info) - rmidi->ops->get_port_info(rmidi, p, port); - if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0) - goto __nomem; - ms->seq_client = client->seq_client; - ms->seq_port = port->addr.port; - } - client->ports_per_device[device] = ports; - client->ports[device] = msynth; - client->num_ports++; - if (newclient) - synths[card->number] = client; - mutex_unlock(®ister_mutex); - kfree(info); - kfree(port); - return 0; /* success */ - - __nomem: - if (msynth != NULL) { - for (p = 0; p < ports; p++) - snd_seq_midisynth_delete(&msynth[p]); - kfree(msynth); - } - if (newclient) { - snd_seq_delete_kernel_client(client->seq_client); - kfree(client); - } - kfree(info); - kfree(port); - mutex_unlock(®ister_mutex); - return -ENOMEM; -} - -/* release midi synth port */ -static int -snd_seq_midisynth_unregister_port(struct snd_seq_device *dev) -{ - struct seq_midisynth_client *client; - struct seq_midisynth *msynth; - struct snd_card *card = dev->card; - int device = dev->device, p, ports; - - mutex_lock(®ister_mutex); - client = synths[card->number]; - if (client == NULL || client->ports[device] == NULL) { - mutex_unlock(®ister_mutex); - return -ENODEV; - } - ports = client->ports_per_device[device]; - client->ports_per_device[device] = 0; - msynth = client->ports[device]; - client->ports[device] = NULL; - for (p = 0; p < ports; p++) - snd_seq_midisynth_delete(&msynth[p]); - kfree(msynth); - client->num_ports--; - if (client->num_ports <= 0) { - snd_seq_delete_kernel_client(client->seq_client); - synths[card->number] = NULL; - kfree(client); - } - mutex_unlock(®ister_mutex); - return 0; -} - - -static int __init alsa_seq_midi_init(void) -{ - static struct snd_seq_dev_ops ops = { - snd_seq_midisynth_register_port, - snd_seq_midisynth_unregister_port, - }; - memset(&synths, 0, sizeof(synths)); - snd_seq_autoload_lock(); - snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH, &ops, 0); - snd_seq_autoload_unlock(); - return 0; -} - -static void __exit alsa_seq_midi_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH); -} - -module_init(alsa_seq_midi_init) -module_exit(alsa_seq_midi_exit) diff --git a/ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c b/ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c deleted file mode 100644 index 6f64471d..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_midi_emul.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * GM/GS/XG midi module. - * - * Copyright (C) 1999 Steve Ratcliffe - * - * Based on awe_wave.c by Takashi Iwai - * - * 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 - * - */ -/* - * This module is used to keep track of the current midi state. - * It can be used for drivers that are required to emulate midi when - * the hardware doesn't. - * - * It was written for a AWE64 driver, but there should be no AWE specific - * code in here. If there is it should be reported as a bug. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Takashi Iwai / Steve Ratcliffe"); -MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation."); -MODULE_LICENSE("GPL"); - -/* Prototypes for static functions */ -static void note_off(struct snd_midi_op *ops, void *drv, - struct snd_midi_channel *chan, - int note, int vel); -static void do_control(struct snd_midi_op *ops, void *private, - struct snd_midi_channel_set *chset, - struct snd_midi_channel *chan, - int control, int value); -static void rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, - struct snd_midi_channel_set *chset); -static void nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, - struct snd_midi_channel_set *chset); -static void sysex(struct snd_midi_op *ops, void *private, unsigned char *sysex, - int len, struct snd_midi_channel_set *chset); -static void all_sounds_off(struct snd_midi_op *ops, void *private, - struct snd_midi_channel *chan); -static void all_notes_off(struct snd_midi_op *ops, void *private, - struct snd_midi_channel *chan); -static void snd_midi_reset_controllers(struct snd_midi_channel *chan); -static void reset_all_channels(struct snd_midi_channel_set *chset); - - -/* - * Process an event in a driver independent way. This means dealing - * with RPN, NRPN, SysEx etc that are defined for common midi applications - * such as GM, GS and XG. - * There modes that this module will run in are: - * Generic MIDI - no interpretation at all, it will just save current values - * of controllers etc. - * GM - You can use all gm_ prefixed elements of chan. Controls, RPN, NRPN, - * SysEx will be interpreded as defined in General Midi. - * GS - You can use all gs_ prefixed elements of chan. Codes for GS will be - * interpreted. - * XG - You can use all xg_ prefixed elements of chan. Codes for XG will - * be interpreted. - */ -void -snd_midi_process_event(struct snd_midi_op *ops, - struct snd_seq_event *ev, - struct snd_midi_channel_set *chanset) -{ - struct snd_midi_channel *chan; - void *drv; - int dest_channel = 0; - - if (ev == NULL || chanset == NULL) { - snd_printd("ev or chanbase NULL (snd_midi_process_event)\n"); - return; - } - if (chanset->channels == NULL) - return; - - if (snd_seq_ev_is_channel_type(ev)) { - dest_channel = ev->data.note.channel; - if (dest_channel >= chanset->max_channels) { - snd_printd("dest channel is %d, max is %d\n", - dest_channel, chanset->max_channels); - return; - } - } - - chan = chanset->channels + dest_channel; - drv = chanset->private_data; - - /* EVENT_NOTE should be processed before queued */ - if (ev->type == SNDRV_SEQ_EVENT_NOTE) - return; - - /* Make sure that we don't have a note on that should really be - * a note off */ - if (ev->type == SNDRV_SEQ_EVENT_NOTEON && ev->data.note.velocity == 0) - ev->type = SNDRV_SEQ_EVENT_NOTEOFF; - - /* Make sure the note is within array range */ - if (ev->type == SNDRV_SEQ_EVENT_NOTEON || - ev->type == SNDRV_SEQ_EVENT_NOTEOFF || - ev->type == SNDRV_SEQ_EVENT_KEYPRESS) { - if (ev->data.note.note >= 128) - return; - } - - switch (ev->type) { - case SNDRV_SEQ_EVENT_NOTEON: - if (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON) { - if (ops->note_off) - ops->note_off(drv, ev->data.note.note, 0, chan); - } - chan->note[ev->data.note.note] = SNDRV_MIDI_NOTE_ON; - if (ops->note_on) - ops->note_on(drv, ev->data.note.note, ev->data.note.velocity, chan); - break; - case SNDRV_SEQ_EVENT_NOTEOFF: - if (! (chan->note[ev->data.note.note] & SNDRV_MIDI_NOTE_ON)) - break; - if (ops->note_off) - note_off(ops, drv, chan, ev->data.note.note, ev->data.note.velocity); - break; - case SNDRV_SEQ_EVENT_KEYPRESS: - if (ops->key_press) - ops->key_press(drv, ev->data.note.note, ev->data.note.velocity, chan); - break; - case SNDRV_SEQ_EVENT_CONTROLLER: - do_control(ops, drv, chanset, chan, - ev->data.control.param, ev->data.control.value); - break; - case SNDRV_SEQ_EVENT_PGMCHANGE: - chan->midi_program = ev->data.control.value; - break; - case SNDRV_SEQ_EVENT_PITCHBEND: - chan->midi_pitchbend = ev->data.control.value; - if (ops->control) - ops->control(drv, MIDI_CTL_PITCHBEND, chan); - break; - case SNDRV_SEQ_EVENT_CHANPRESS: - chan->midi_pressure = ev->data.control.value; - if (ops->control) - ops->control(drv, MIDI_CTL_CHAN_PRESSURE, chan); - break; - case SNDRV_SEQ_EVENT_CONTROL14: - /* Best guess is that this is any of the 14 bit controller values */ - if (ev->data.control.param < 32) { - /* set low part first */ - chan->control[ev->data.control.param + 32] = - ev->data.control.value & 0x7f; - do_control(ops, drv, chanset, chan, - ev->data.control.param, - ((ev->data.control.value>>7) & 0x7f)); - } else - do_control(ops, drv, chanset, chan, - ev->data.control.param, - ev->data.control.value); - break; - case SNDRV_SEQ_EVENT_NONREGPARAM: - /* Break it back into its controller values */ - chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED; - chan->control[MIDI_CTL_MSB_DATA_ENTRY] - = (ev->data.control.value >> 7) & 0x7f; - chan->control[MIDI_CTL_LSB_DATA_ENTRY] - = ev->data.control.value & 0x7f; - chan->control[MIDI_CTL_NONREG_PARM_NUM_MSB] - = (ev->data.control.param >> 7) & 0x7f; - chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB] - = ev->data.control.param & 0x7f; - nrpn(ops, drv, chan, chanset); - break; - case SNDRV_SEQ_EVENT_REGPARAM: - /* Break it back into its controller values */ - chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED; - chan->control[MIDI_CTL_MSB_DATA_ENTRY] - = (ev->data.control.value >> 7) & 0x7f; - chan->control[MIDI_CTL_LSB_DATA_ENTRY] - = ev->data.control.value & 0x7f; - chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB] - = (ev->data.control.param >> 7) & 0x7f; - chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB] - = ev->data.control.param & 0x7f; - rpn(ops, drv, chan, chanset); - break; - case SNDRV_SEQ_EVENT_SYSEX: - if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE) { - unsigned char sysexbuf[64]; - int len; - len = snd_seq_expand_var_event(ev, sizeof(sysexbuf), sysexbuf, 1, 0); - if (len > 0) - sysex(ops, drv, sysexbuf, len, chanset); - } - break; - case SNDRV_SEQ_EVENT_SONGPOS: - case SNDRV_SEQ_EVENT_SONGSEL: - case SNDRV_SEQ_EVENT_CLOCK: - case SNDRV_SEQ_EVENT_START: - case SNDRV_SEQ_EVENT_CONTINUE: - case SNDRV_SEQ_EVENT_STOP: - case SNDRV_SEQ_EVENT_QFRAME: - case SNDRV_SEQ_EVENT_TEMPO: - case SNDRV_SEQ_EVENT_TIMESIGN: - case SNDRV_SEQ_EVENT_KEYSIGN: - goto not_yet; - case SNDRV_SEQ_EVENT_SENSING: - break; - case SNDRV_SEQ_EVENT_CLIENT_START: - case SNDRV_SEQ_EVENT_CLIENT_EXIT: - case SNDRV_SEQ_EVENT_CLIENT_CHANGE: - case SNDRV_SEQ_EVENT_PORT_START: - case SNDRV_SEQ_EVENT_PORT_EXIT: - case SNDRV_SEQ_EVENT_PORT_CHANGE: - case SNDRV_SEQ_EVENT_ECHO: - not_yet: - default: - /*snd_printd("Unimplemented event %d\n", ev->type);*/ - break; - } -} - - -/* - * release note - */ -static void -note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, - int note, int vel) -{ - if (chan->gm_hold) { - /* Hold this note until pedal is turned off */ - chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED; - } else if (chan->note[note] & SNDRV_MIDI_NOTE_SOSTENUTO) { - /* Mark this note as release; it will be turned off when sostenuto - * is turned off */ - chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED; - } else { - chan->note[note] = 0; - if (ops->note_off) - ops->note_off(drv, note, vel, chan); - } -} - -/* - * Do all driver independent operations for this controller and pass - * events that need to take place immediately to the driver. - */ -static void -do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chset, - struct snd_midi_channel *chan, int control, int value) -{ - int i; - - /* Switches */ - if ((control >=64 && control <=69) || (control >= 80 && control <= 83)) { - /* These are all switches; either off or on so set to 0 or 127 */ - value = (value >= 64)? 127: 0; - } - chan->control[control] = value; - - switch (control) { - case MIDI_CTL_SUSTAIN: - if (value == 0) { - /* Sustain has been released, turn off held notes */ - for (i = 0; i < 128; i++) { - if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) { - chan->note[i] = SNDRV_MIDI_NOTE_OFF; - if (ops->note_off) - ops->note_off(drv, i, 0, chan); - } - } - } - break; - case MIDI_CTL_PORTAMENTO: - break; - case MIDI_CTL_SOSTENUTO: - if (value) { - /* Mark each note that is currently held down */ - for (i = 0; i < 128; i++) { - if (chan->note[i] & SNDRV_MIDI_NOTE_ON) - chan->note[i] |= SNDRV_MIDI_NOTE_SOSTENUTO; - } - } else { - /* release all notes that were held */ - for (i = 0; i < 128; i++) { - if (chan->note[i] & SNDRV_MIDI_NOTE_SOSTENUTO) { - chan->note[i] &= ~SNDRV_MIDI_NOTE_SOSTENUTO; - if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) { - chan->note[i] = SNDRV_MIDI_NOTE_OFF; - if (ops->note_off) - ops->note_off(drv, i, 0, chan); - } - } - } - } - break; - case MIDI_CTL_MSB_DATA_ENTRY: - chan->control[MIDI_CTL_LSB_DATA_ENTRY] = 0; - /* go through here */ - case MIDI_CTL_LSB_DATA_ENTRY: - if (chan->param_type == SNDRV_MIDI_PARAM_TYPE_REGISTERED) - rpn(ops, drv, chan, chset); - else - nrpn(ops, drv, chan, chset); - break; - case MIDI_CTL_REGIST_PARM_NUM_LSB: - case MIDI_CTL_REGIST_PARM_NUM_MSB: - chan->param_type = SNDRV_MIDI_PARAM_TYPE_REGISTERED; - break; - case MIDI_CTL_NONREG_PARM_NUM_LSB: - case MIDI_CTL_NONREG_PARM_NUM_MSB: - chan->param_type = SNDRV_MIDI_PARAM_TYPE_NONREGISTERED; - break; - - case MIDI_CTL_ALL_SOUNDS_OFF: - all_sounds_off(ops, drv, chan); - break; - - case MIDI_CTL_ALL_NOTES_OFF: - all_notes_off(ops, drv, chan); - break; - - case MIDI_CTL_MSB_BANK: - if (chset->midi_mode == SNDRV_MIDI_MODE_XG) { - if (value == 127) - chan->drum_channel = 1; - else - chan->drum_channel = 0; - } - break; - case MIDI_CTL_LSB_BANK: - break; - - case MIDI_CTL_RESET_CONTROLLERS: - snd_midi_reset_controllers(chan); - break; - - case MIDI_CTL_SOFT_PEDAL: - case MIDI_CTL_LEGATO_FOOTSWITCH: - case MIDI_CTL_HOLD2: - case MIDI_CTL_SC1_SOUND_VARIATION: - case MIDI_CTL_SC2_TIMBRE: - case MIDI_CTL_SC3_RELEASE_TIME: - case MIDI_CTL_SC4_ATTACK_TIME: - case MIDI_CTL_SC5_BRIGHTNESS: - case MIDI_CTL_E1_REVERB_DEPTH: - case MIDI_CTL_E2_TREMOLO_DEPTH: - case MIDI_CTL_E3_CHORUS_DEPTH: - case MIDI_CTL_E4_DETUNE_DEPTH: - case MIDI_CTL_E5_PHASER_DEPTH: - goto notyet; - notyet: - default: - if (ops->control) - ops->control(drv, control, chan); - break; - } -} - - -/* - * initialize the MIDI status - */ -void -snd_midi_channel_set_clear(struct snd_midi_channel_set *chset) -{ - int i; - - chset->midi_mode = SNDRV_MIDI_MODE_GM; - chset->gs_master_volume = 127; - - for (i = 0; i < chset->max_channels; i++) { - struct snd_midi_channel *chan = chset->channels + i; - memset(chan->note, 0, sizeof(chan->note)); - - chan->midi_aftertouch = 0; - chan->midi_pressure = 0; - chan->midi_program = 0; - chan->midi_pitchbend = 0; - snd_midi_reset_controllers(chan); - chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */ - chan->gm_rpn_fine_tuning = 0; - chan->gm_rpn_coarse_tuning = 0; - - if (i == 9) - chan->drum_channel = 1; - else - chan->drum_channel = 0; - } -} - -/* - * Process a rpn message. - */ -static void -rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, - struct snd_midi_channel_set *chset) -{ - int type; - int val; - - if (chset->midi_mode != SNDRV_MIDI_MODE_NONE) { - type = (chan->control[MIDI_CTL_REGIST_PARM_NUM_MSB] << 8) | - chan->control[MIDI_CTL_REGIST_PARM_NUM_LSB]; - val = (chan->control[MIDI_CTL_MSB_DATA_ENTRY] << 7) | - chan->control[MIDI_CTL_LSB_DATA_ENTRY]; - - switch (type) { - case 0x0000: /* Pitch bend sensitivity */ - /* MSB only / 1 semitone per 128 */ - chan->gm_rpn_pitch_bend_range = val; - break; - - case 0x0001: /* fine tuning: */ - /* MSB/LSB, 8192=center, 100/8192 cent step */ - chan->gm_rpn_fine_tuning = val - 8192; - break; - - case 0x0002: /* coarse tuning */ - /* MSB only / 8192=center, 1 semitone per 128 */ - chan->gm_rpn_coarse_tuning = val - 8192; - break; - - case 0x7F7F: /* "lock-in" RPN */ - /* ignored */ - break; - } - } - /* should call nrpn or rpn callback here.. */ -} - -/* - * Process an nrpn message. - */ -static void -nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan, - struct snd_midi_channel_set *chset) -{ - /* parse XG NRPNs here if possible */ - if (ops->nrpn) - ops->nrpn(drv, chan, chset); -} - - -/* - * convert channel parameter in GS sysex - */ -static int -get_channel(unsigned char cmd) -{ - int p = cmd & 0x0f; - if (p == 0) - p = 9; - else if (p < 10) - p--; - return p; -} - - -/* - * Process a sysex message. - */ -static void -sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len, - struct snd_midi_channel_set *chset) -{ - /* GM on */ - static unsigned char gm_on_macro[] = { - 0x7e,0x7f,0x09,0x01, - }; - /* XG on */ - static unsigned char xg_on_macro[] = { - 0x43,0x10,0x4c,0x00,0x00,0x7e,0x00, - }; - /* GS prefix - * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off - * reverb mode: XX=0x01, YY=0x30, ZZ=0-7 - * chorus mode: XX=0x01, YY=0x38, ZZ=0-7 - * master vol: XX=0x00, YY=0x04, ZZ=0-127 - */ - static unsigned char gs_pfx_macro[] = { - 0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/ - }; - - int parsed = SNDRV_MIDI_SYSEX_NOT_PARSED; - - if (len <= 0 || buf[0] != 0xf0) - return; - /* skip first byte */ - buf++; - len--; - - /* GM on */ - if (len >= (int)sizeof(gm_on_macro) && - memcmp(buf, gm_on_macro, sizeof(gm_on_macro)) == 0) { - if (chset->midi_mode != SNDRV_MIDI_MODE_GS && - chset->midi_mode != SNDRV_MIDI_MODE_XG) { - chset->midi_mode = SNDRV_MIDI_MODE_GM; - reset_all_channels(chset); - parsed = SNDRV_MIDI_SYSEX_GM_ON; - } - } - - /* GS macros */ - else if (len >= 8 && - memcmp(buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) { - if (chset->midi_mode != SNDRV_MIDI_MODE_GS && - chset->midi_mode != SNDRV_MIDI_MODE_XG) - chset->midi_mode = SNDRV_MIDI_MODE_GS; - - if (buf[5] == 0x00 && buf[6] == 0x7f && buf[7] == 0x00) { - /* GS reset */ - parsed = SNDRV_MIDI_SYSEX_GS_RESET; - reset_all_channels(chset); - } - - else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x15) { - /* drum pattern */ - int p = get_channel(buf[5]); - if (p < chset->max_channels) { - parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL; - if (buf[7]) - chset->channels[p].drum_channel = 1; - else - chset->channels[p].drum_channel = 0; - } - - } else if ((buf[5] & 0xf0) == 0x10 && buf[6] == 0x21) { - /* program */ - int p = get_channel(buf[5]); - if (p < chset->max_channels && - ! chset->channels[p].drum_channel) { - parsed = SNDRV_MIDI_SYSEX_GS_DRUM_CHANNEL; - chset->channels[p].midi_program = buf[7]; - } - - } else if (buf[5] == 0x01 && buf[6] == 0x30) { - /* reverb mode */ - parsed = SNDRV_MIDI_SYSEX_GS_REVERB_MODE; - chset->gs_reverb_mode = buf[7]; - - } else if (buf[5] == 0x01 && buf[6] == 0x38) { - /* chorus mode */ - parsed = SNDRV_MIDI_SYSEX_GS_CHORUS_MODE; - chset->gs_chorus_mode = buf[7]; - - } else if (buf[5] == 0x00 && buf[6] == 0x04) { - /* master volume */ - parsed = SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME; - chset->gs_master_volume = buf[7]; - - } - } - - /* XG on */ - else if (len >= (int)sizeof(xg_on_macro) && - memcmp(buf, xg_on_macro, sizeof(xg_on_macro)) == 0) { - int i; - chset->midi_mode = SNDRV_MIDI_MODE_XG; - parsed = SNDRV_MIDI_SYSEX_XG_ON; - /* reset CC#0 for drums */ - for (i = 0; i < chset->max_channels; i++) { - if (chset->channels[i].drum_channel) - chset->channels[i].control[MIDI_CTL_MSB_BANK] = 127; - else - chset->channels[i].control[MIDI_CTL_MSB_BANK] = 0; - } - } - - if (ops->sysex) - ops->sysex(private, buf - 1, len + 1, parsed, chset); -} - -/* - * all sound off - */ -static void -all_sounds_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan) -{ - int n; - - if (! ops->note_terminate) - return; - for (n = 0; n < 128; n++) { - if (chan->note[n]) { - ops->note_terminate(drv, n, chan); - chan->note[n] = 0; - } - } -} - -/* - * all notes off - */ -static void -all_notes_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan) -{ - int n; - - if (! ops->note_off) - return; - for (n = 0; n < 128; n++) { - if (chan->note[n] == SNDRV_MIDI_NOTE_ON) - note_off(ops, drv, chan, n, 0); - } -} - -/* - * Initialise a single midi channel control block. - */ -static void snd_midi_channel_init(struct snd_midi_channel *p, int n) -{ - if (p == NULL) - return; - - memset(p, 0, sizeof(struct snd_midi_channel)); - p->private = NULL; - p->number = n; - - snd_midi_reset_controllers(p); - p->gm_rpn_pitch_bend_range = 256; /* 2 semitones */ - p->gm_rpn_fine_tuning = 0; - p->gm_rpn_coarse_tuning = 0; - - if (n == 9) - p->drum_channel = 1; /* Default ch 10 as drums */ -} - -/* - * Allocate and initialise a set of midi channel control blocks. - */ -static struct snd_midi_channel *snd_midi_channel_init_set(int n) -{ - struct snd_midi_channel *chan; - int i; - - chan = kmalloc(n * sizeof(struct snd_midi_channel), GFP_KERNEL); - if (chan) { - for (i = 0; i < n; i++) - snd_midi_channel_init(chan+i, i); - } - - return chan; -} - -/* - * reset all midi channels - */ -static void -reset_all_channels(struct snd_midi_channel_set *chset) -{ - int ch; - for (ch = 0; ch < chset->max_channels; ch++) { - struct snd_midi_channel *chan = chset->channels + ch; - snd_midi_reset_controllers(chan); - chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */ - chan->gm_rpn_fine_tuning = 0; - chan->gm_rpn_coarse_tuning = 0; - - if (ch == 9) - chan->drum_channel = 1; - else - chan->drum_channel = 0; - } -} - - -/* - * Allocate and initialise a midi channel set. - */ -struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n) -{ - struct snd_midi_channel_set *chset; - - chset = kmalloc(sizeof(*chset), GFP_KERNEL); - if (chset) { - chset->channels = snd_midi_channel_init_set(n); - chset->private_data = NULL; - chset->max_channels = n; - } - return chset; -} - -/* - * Reset the midi controllers on a particular channel to default values. - */ -static void snd_midi_reset_controllers(struct snd_midi_channel *chan) -{ - memset(chan->control, 0, sizeof(chan->control)); - chan->gm_volume = 127; - chan->gm_expression = 127; - chan->gm_pan = 64; -} - - -/* - * Free a midi channel set. - */ -void snd_midi_channel_free_set(struct snd_midi_channel_set *chset) -{ - if (chset == NULL) - return; - kfree(chset->channels); - kfree(chset); -} - -static int __init alsa_seq_midi_emul_init(void) -{ - return 0; -} - -static void __exit alsa_seq_midi_emul_exit(void) -{ -} - -module_init(alsa_seq_midi_emul_init) -module_exit(alsa_seq_midi_emul_exit) - -EXPORT_SYMBOL(snd_midi_process_event); -EXPORT_SYMBOL(snd_midi_channel_set_clear); -EXPORT_SYMBOL(snd_midi_channel_alloc_set); -EXPORT_SYMBOL(snd_midi_channel_free_set); diff --git a/ANDROID_3.4.5/sound/core/seq/seq_midi_event.c b/ANDROID_3.4.5/sound/core/seq/seq_midi_event.c deleted file mode 100644 index 37db7ba4..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_midi_event.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - * MIDI byte <-> sequencer event coder - * - * Copyright (C) 1998,99 Takashi Iwai , - * Jaroslav Kysela - * - * 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 - -MODULE_AUTHOR("Takashi Iwai , Jaroslav Kysela "); -MODULE_DESCRIPTION("MIDI byte <-> sequencer event coder"); -MODULE_LICENSE("GPL"); - -/* event type, index into status_event[] */ -/* from 0 to 6 are normal commands (note off, on, etc.) for 0x9?-0xe? */ -#define ST_INVALID 7 -#define ST_SPECIAL 8 -#define ST_SYSEX ST_SPECIAL -/* from 8 to 15 are events for 0xf0-0xf7 */ - - -/* - * prototypes - */ -static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev); -static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); -static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); -static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev); -static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev); -static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev); -static void note_decode(struct snd_seq_event *ev, unsigned char *buf); -static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf); -static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf); -static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf); -static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf); - -/* - * event list - */ -static struct status_event_list { - int event; - int qlen; - void (*encode)(struct snd_midi_event *dev, struct snd_seq_event *ev); - void (*decode)(struct snd_seq_event *ev, unsigned char *buf); -} status_event[] = { - /* 0x80 - 0xef */ - {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, - {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, - {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, - {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, - {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, - {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, - {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, - /* invalid */ - {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, - /* 0xf0 - 0xff */ - {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ - {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ - {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ - {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ - {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf4 */ - {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf5 */ - {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ - {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf7 */ - {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ - {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xf9 */ - {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ - {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ - {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ - {SNDRV_SEQ_EVENT_NONE, -1, NULL, NULL}, /* 0xfd */ - {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ - {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ -}; - -static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len, - struct snd_seq_event *ev); -static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, int count, - struct snd_seq_event *ev); - -static struct extra_event_list { - int event; - int (*decode)(struct snd_midi_event *dev, unsigned char *buf, int len, - struct snd_seq_event *ev); -} extra_event[] = { - {SNDRV_SEQ_EVENT_CONTROL14, extra_decode_ctrl14}, - {SNDRV_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn}, - {SNDRV_SEQ_EVENT_REGPARAM, extra_decode_xrpn}, -}; - -/* - * new/delete record - */ - -int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev) -{ - struct snd_midi_event *dev; - - *rdev = NULL; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) - return -ENOMEM; - if (bufsize > 0) { - dev->buf = kmalloc(bufsize, GFP_KERNEL); - if (dev->buf == NULL) { - kfree(dev); - return -ENOMEM; - } - } - dev->bufsize = bufsize; - dev->lastcmd = 0xff; - dev->type = ST_INVALID; - spin_lock_init(&dev->lock); - *rdev = dev; - return 0; -} - -void snd_midi_event_free(struct snd_midi_event *dev) -{ - if (dev != NULL) { - kfree(dev->buf); - kfree(dev); - } -} - -/* - * initialize record - */ -static inline void reset_encode(struct snd_midi_event *dev) -{ - dev->read = 0; - dev->qlen = 0; - dev->type = ST_INVALID; -} - -void snd_midi_event_reset_encode(struct snd_midi_event *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - reset_encode(dev); - spin_unlock_irqrestore(&dev->lock, flags); -} - -void snd_midi_event_reset_decode(struct snd_midi_event *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - dev->lastcmd = 0xff; - spin_unlock_irqrestore(&dev->lock, flags); -} - -#if 0 -void snd_midi_event_init(struct snd_midi_event *dev) -{ - snd_midi_event_reset_encode(dev); - snd_midi_event_reset_decode(dev); -} -#endif /* 0 */ - -void snd_midi_event_no_status(struct snd_midi_event *dev, int on) -{ - dev->nostat = on ? 1 : 0; -} - -/* - * resize buffer - */ -#if 0 -int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize) -{ - unsigned char *new_buf, *old_buf; - unsigned long flags; - - if (bufsize == dev->bufsize) - return 0; - new_buf = kmalloc(bufsize, GFP_KERNEL); - if (new_buf == NULL) - return -ENOMEM; - spin_lock_irqsave(&dev->lock, flags); - old_buf = dev->buf; - dev->buf = new_buf; - dev->bufsize = bufsize; - reset_encode(dev); - spin_unlock_irqrestore(&dev->lock, flags); - kfree(old_buf); - return 0; -} -#endif /* 0 */ - -/* - * read bytes and encode to sequencer event if finished - * return the size of encoded bytes - */ -long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count, - struct snd_seq_event *ev) -{ - long result = 0; - int rc; - - ev->type = SNDRV_SEQ_EVENT_NONE; - - while (count-- > 0) { - rc = snd_midi_event_encode_byte(dev, *buf++, ev); - result++; - if (rc < 0) - return rc; - else if (rc > 0) - return result; - } - - return result; -} - -/* - * read one byte and encode to sequencer event: - * return 1 if MIDI bytes are encoded to an event - * 0 data is not finished - * negative for error - */ -int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, - struct snd_seq_event *ev) -{ - int rc = 0; - unsigned long flags; - - c &= 0xff; - - if (c >= MIDI_CMD_COMMON_CLOCK) { - /* real-time event */ - ev->type = status_event[ST_SPECIAL + c - 0xf0].event; - ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; - return ev->type != SNDRV_SEQ_EVENT_NONE; - } - - spin_lock_irqsave(&dev->lock, flags); - if ((c & 0x80) && - (c != MIDI_CMD_COMMON_SYSEX_END || dev->type != ST_SYSEX)) { - /* new command */ - dev->buf[0] = c; - if ((c & 0xf0) == 0xf0) /* system messages */ - dev->type = (c & 0x0f) + ST_SPECIAL; - else - dev->type = (c >> 4) & 0x07; - dev->read = 1; - dev->qlen = status_event[dev->type].qlen; - } else { - if (dev->qlen > 0) { - /* rest of command */ - dev->buf[dev->read++] = c; - if (dev->type != ST_SYSEX) - dev->qlen--; - } else { - /* running status */ - dev->buf[1] = c; - dev->qlen = status_event[dev->type].qlen - 1; - dev->read = 2; - } - } - if (dev->qlen == 0) { - ev->type = status_event[dev->type].event; - ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; - if (status_event[dev->type].encode) /* set data values */ - status_event[dev->type].encode(dev, ev); - if (dev->type >= ST_SPECIAL) - dev->type = ST_INVALID; - rc = 1; - } else if (dev->type == ST_SYSEX) { - if (c == MIDI_CMD_COMMON_SYSEX_END || - dev->read >= dev->bufsize) { - ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE; - ev->type = SNDRV_SEQ_EVENT_SYSEX; - ev->data.ext.len = dev->read; - ev->data.ext.ptr = dev->buf; - if (c != MIDI_CMD_COMMON_SYSEX_END) - dev->read = 0; /* continue to parse */ - else - reset_encode(dev); /* all parsed */ - rc = 1; - } - } - - spin_unlock_irqrestore(&dev->lock, flags); - return rc; -} - -/* encode note event */ -static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev) -{ - ev->data.note.channel = dev->buf[0] & 0x0f; - ev->data.note.note = dev->buf[1]; - ev->data.note.velocity = dev->buf[2]; -} - -/* encode one parameter controls */ -static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) -{ - ev->data.control.channel = dev->buf[0] & 0x0f; - ev->data.control.value = dev->buf[1]; -} - -/* encode pitch wheel change */ -static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) -{ - ev->data.control.channel = dev->buf[0] & 0x0f; - ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1] - 8192; -} - -/* encode midi control change */ -static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev) -{ - ev->data.control.channel = dev->buf[0] & 0x0f; - ev->data.control.param = dev->buf[1]; - ev->data.control.value = dev->buf[2]; -} - -/* encode one parameter value*/ -static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev) -{ - ev->data.control.value = dev->buf[1]; -} - -/* encode song position */ -static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev) -{ - ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1]; -} - -/* - * decode from a sequencer event to midi bytes - * return the size of decoded midi events - */ -long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count, - struct snd_seq_event *ev) -{ - unsigned int cmd, type; - - if (ev->type == SNDRV_SEQ_EVENT_NONE) - return -ENOENT; - - for (type = 0; type < ARRAY_SIZE(status_event); type++) { - if (ev->type == status_event[type].event) - goto __found; - } - for (type = 0; type < ARRAY_SIZE(extra_event); type++) { - if (ev->type == extra_event[type].event) - return extra_event[type].decode(dev, buf, count, ev); - } - return -ENOENT; - - __found: - if (type >= ST_SPECIAL) - cmd = 0xf0 + (type - ST_SPECIAL); - else - /* data.note.channel and data.control.channel is identical */ - cmd = 0x80 | (type << 4) | (ev->data.note.channel & 0x0f); - - - if (cmd == MIDI_CMD_COMMON_SYSEX) { - snd_midi_event_reset_decode(dev); - return snd_seq_expand_var_event(ev, count, buf, 1, 0); - } else { - int qlen; - unsigned char xbuf[4]; - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - if ((cmd & 0xf0) == 0xf0 || dev->lastcmd != cmd || dev->nostat) { - dev->lastcmd = cmd; - spin_unlock_irqrestore(&dev->lock, flags); - xbuf[0] = cmd; - if (status_event[type].decode) - status_event[type].decode(ev, xbuf + 1); - qlen = status_event[type].qlen + 1; - } else { - spin_unlock_irqrestore(&dev->lock, flags); - if (status_event[type].decode) - status_event[type].decode(ev, xbuf + 0); - qlen = status_event[type].qlen; - } - if (count < qlen) - return -ENOMEM; - memcpy(buf, xbuf, qlen); - return qlen; - } -} - - -/* decode note event */ -static void note_decode(struct snd_seq_event *ev, unsigned char *buf) -{ - buf[0] = ev->data.note.note & 0x7f; - buf[1] = ev->data.note.velocity & 0x7f; -} - -/* decode one parameter controls */ -static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf) -{ - buf[0] = ev->data.control.value & 0x7f; -} - -/* decode pitch wheel change */ -static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf) -{ - int value = ev->data.control.value + 8192; - buf[0] = value & 0x7f; - buf[1] = (value >> 7) & 0x7f; -} - -/* decode midi control change */ -static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf) -{ - buf[0] = ev->data.control.param & 0x7f; - buf[1] = ev->data.control.value & 0x7f; -} - -/* decode song position */ -static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf) -{ - buf[0] = ev->data.control.value & 0x7f; - buf[1] = (ev->data.control.value >> 7) & 0x7f; -} - -/* decode 14bit control */ -static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, - int count, struct snd_seq_event *ev) -{ - unsigned char cmd; - int idx = 0; - - cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); - if (ev->data.control.param < 0x20) { - if (count < 4) - return -ENOMEM; - if (dev->nostat && count < 6) - return -ENOMEM; - if (cmd != dev->lastcmd || dev->nostat) { - if (count < 5) - return -ENOMEM; - buf[idx++] = dev->lastcmd = cmd; - } - buf[idx++] = ev->data.control.param; - buf[idx++] = (ev->data.control.value >> 7) & 0x7f; - if (dev->nostat) - buf[idx++] = cmd; - buf[idx++] = ev->data.control.param + 0x20; - buf[idx++] = ev->data.control.value & 0x7f; - } else { - if (count < 2) - return -ENOMEM; - if (cmd != dev->lastcmd || dev->nostat) { - if (count < 3) - return -ENOMEM; - buf[idx++] = dev->lastcmd = cmd; - } - buf[idx++] = ev->data.control.param & 0x7f; - buf[idx++] = ev->data.control.value & 0x7f; - } - return idx; -} - -/* decode reg/nonreg param */ -static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, - int count, struct snd_seq_event *ev) -{ - unsigned char cmd; - char *cbytes; - static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB, - MIDI_CTL_NONREG_PARM_NUM_LSB, - MIDI_CTL_MSB_DATA_ENTRY, - MIDI_CTL_LSB_DATA_ENTRY }; - static char cbytes_rpn[4] = { MIDI_CTL_REGIST_PARM_NUM_MSB, - MIDI_CTL_REGIST_PARM_NUM_LSB, - MIDI_CTL_MSB_DATA_ENTRY, - MIDI_CTL_LSB_DATA_ENTRY }; - unsigned char bytes[4]; - int idx = 0, i; - - if (count < 8) - return -ENOMEM; - if (dev->nostat && count < 12) - return -ENOMEM; - cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); - bytes[0] = (ev->data.control.param & 0x3f80) >> 7; - bytes[1] = ev->data.control.param & 0x007f; - bytes[2] = (ev->data.control.value & 0x3f80) >> 7; - bytes[3] = ev->data.control.value & 0x007f; - if (cmd != dev->lastcmd && !dev->nostat) { - if (count < 9) - return -ENOMEM; - buf[idx++] = dev->lastcmd = cmd; - } - cbytes = ev->type == SNDRV_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn; - for (i = 0; i < 4; i++) { - if (dev->nostat) - buf[idx++] = dev->lastcmd = cmd; - buf[idx++] = cbytes[i]; - buf[idx++] = bytes[i]; - } - return idx; -} - -/* - * exports - */ - -EXPORT_SYMBOL(snd_midi_event_new); -EXPORT_SYMBOL(snd_midi_event_free); -EXPORT_SYMBOL(snd_midi_event_reset_encode); -EXPORT_SYMBOL(snd_midi_event_reset_decode); -EXPORT_SYMBOL(snd_midi_event_no_status); -EXPORT_SYMBOL(snd_midi_event_encode); -EXPORT_SYMBOL(snd_midi_event_encode_byte); -EXPORT_SYMBOL(snd_midi_event_decode); - -static int __init alsa_seq_midi_event_init(void) -{ - return 0; -} - -static void __exit alsa_seq_midi_event_exit(void) -{ -} - -module_init(alsa_seq_midi_event_init) -module_exit(alsa_seq_midi_event_exit) diff --git a/ANDROID_3.4.5/sound/core/seq/seq_ports.c b/ANDROID_3.4.5/sound/core/seq/seq_ports.c deleted file mode 100644 index 9516e5ce..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_ports.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * ALSA sequencer Ports - * Copyright (c) 1998 by Frank van de Pol - * Jaroslav Kysela - * - * - * 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 "seq_system.h" -#include "seq_ports.h" -#include "seq_clientmgr.h" - -/* - - registration of client ports - - */ - - -/* - -NOTE: the current implementation of the port structure as a linked list is -not optimal for clients that have many ports. For sending messages to all -subscribers of a port we first need to find the address of the port -structure, which means we have to traverse the list. A direct access table -(array) would be better, but big preallocated arrays waste memory. - -Possible actions: - -1) leave it this way, a client does normaly does not have more than a few -ports - -2) replace the linked list of ports by a array of pointers which is -dynamicly kmalloced. When a port is added or deleted we can simply allocate -a new array, copy the corresponding pointers, and delete the old one. We -then only need a pointer to this array, and an integer that tells us how -much elements are in array. - -*/ - -/* return pointer to port structure - port is locked if found */ -struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client, - int num) -{ - struct snd_seq_client_port *port; - - if (client == NULL) - return NULL; - read_lock(&client->ports_lock); - list_for_each_entry(port, &client->ports_list_head, list) { - if (port->addr.port == num) { - if (port->closing) - break; /* deleting now */ - snd_use_lock_use(&port->use_lock); - read_unlock(&client->ports_lock); - return port; - } - } - read_unlock(&client->ports_lock); - return NULL; /* not found */ -} - - -/* search for the next port - port is locked if found */ -struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client, - struct snd_seq_port_info *pinfo) -{ - int num; - struct snd_seq_client_port *port, *found; - - num = pinfo->addr.port; - found = NULL; - read_lock(&client->ports_lock); - list_for_each_entry(port, &client->ports_list_head, list) { - if (port->addr.port < num) - continue; - if (port->addr.port == num) { - found = port; - break; - } - if (found == NULL || port->addr.port < found->addr.port) - found = port; - } - if (found) { - if (found->closing) - found = NULL; - else - snd_use_lock_use(&found->use_lock); - } - read_unlock(&client->ports_lock); - return found; -} - - -/* initialize snd_seq_port_subs_info */ -static void port_subs_info_init(struct snd_seq_port_subs_info *grp) -{ - INIT_LIST_HEAD(&grp->list_head); - grp->count = 0; - grp->exclusive = 0; - rwlock_init(&grp->list_lock); - init_rwsem(&grp->list_mutex); - grp->open = NULL; - grp->close = NULL; -} - - -/* create a port, port number is returned (-1 on failure) */ -struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, - int port) -{ - unsigned long flags; - struct snd_seq_client_port *new_port, *p; - int num = -1; - - /* sanity check */ - if (snd_BUG_ON(!client)) - return NULL; - - if (client->num_ports >= SNDRV_SEQ_MAX_PORTS - 1) { - snd_printk(KERN_WARNING "too many ports for client %d\n", client->number); - return NULL; - } - - /* create a new port */ - new_port = kzalloc(sizeof(*new_port), GFP_KERNEL); - if (! new_port) { - snd_printd("malloc failed for registering client port\n"); - return NULL; /* failure, out of memory */ - } - /* init port data */ - new_port->addr.client = client->number; - new_port->addr.port = -1; - new_port->owner = THIS_MODULE; - sprintf(new_port->name, "port-%d", num); - snd_use_lock_init(&new_port->use_lock); - port_subs_info_init(&new_port->c_src); - port_subs_info_init(&new_port->c_dest); - - num = port >= 0 ? port : 0; - mutex_lock(&client->ports_mutex); - write_lock_irqsave(&client->ports_lock, flags); - list_for_each_entry(p, &client->ports_list_head, list) { - if (p->addr.port > num) - break; - if (port < 0) /* auto-probe mode */ - num = p->addr.port + 1; - } - /* insert the new port */ - list_add_tail(&new_port->list, &p->list); - client->num_ports++; - new_port->addr.port = num; /* store the port number in the port */ - write_unlock_irqrestore(&client->ports_lock, flags); - mutex_unlock(&client->ports_mutex); - sprintf(new_port->name, "port-%d", num); - - return new_port; -} - -/* */ -enum group_type { - SRC_LIST, DEST_LIST -}; - -static int subscribe_port(struct snd_seq_client *client, - struct snd_seq_client_port *port, - struct snd_seq_port_subs_info *grp, - struct snd_seq_port_subscribe *info, int send_ack); -static int unsubscribe_port(struct snd_seq_client *client, - struct snd_seq_client_port *port, - struct snd_seq_port_subs_info *grp, - struct snd_seq_port_subscribe *info, int send_ack); - - -static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr, - struct snd_seq_client **cp) -{ - struct snd_seq_client_port *p; - *cp = snd_seq_client_use_ptr(addr->client); - if (*cp) { - p = snd_seq_port_use_ptr(*cp, addr->port); - if (! p) { - snd_seq_client_unlock(*cp); - *cp = NULL; - } - return p; - } - return NULL; -} - -/* - * remove all subscribers on the list - * this is called from port_delete, for each src and dest list. - */ -static void clear_subscriber_list(struct snd_seq_client *client, - struct snd_seq_client_port *port, - struct snd_seq_port_subs_info *grp, - int grptype) -{ - struct list_head *p, *n; - - list_for_each_safe(p, n, &grp->list_head) { - struct snd_seq_subscribers *subs; - struct snd_seq_client *c; - struct snd_seq_client_port *aport; - - if (grptype == SRC_LIST) { - subs = list_entry(p, struct snd_seq_subscribers, src_list); - aport = get_client_port(&subs->info.dest, &c); - } else { - subs = list_entry(p, struct snd_seq_subscribers, dest_list); - aport = get_client_port(&subs->info.sender, &c); - } - list_del(p); - unsubscribe_port(client, port, grp, &subs->info, 0); - if (!aport) { - /* looks like the connected port is being deleted. - * we decrease the counter, and when both ports are deleted - * remove the subscriber info - */ - if (atomic_dec_and_test(&subs->ref_count)) - kfree(subs); - } else { - /* ok we got the connected port */ - struct snd_seq_port_subs_info *agrp; - agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src; - down_write(&agrp->list_mutex); - if (grptype == SRC_LIST) - list_del(&subs->dest_list); - else - list_del(&subs->src_list); - up_write(&agrp->list_mutex); - unsubscribe_port(c, aport, agrp, &subs->info, 1); - kfree(subs); - snd_seq_port_unlock(aport); - snd_seq_client_unlock(c); - } - } -} - -/* delete port data */ -static int port_delete(struct snd_seq_client *client, - struct snd_seq_client_port *port) -{ - /* set closing flag and wait for all port access are gone */ - port->closing = 1; - snd_use_lock_sync(&port->use_lock); - - /* clear subscribers info */ - clear_subscriber_list(client, port, &port->c_src, SRC_LIST); - clear_subscriber_list(client, port, &port->c_dest, DEST_LIST); - - if (port->private_free) - port->private_free(port->private_data); - - snd_BUG_ON(port->c_src.count != 0); - snd_BUG_ON(port->c_dest.count != 0); - - kfree(port); - return 0; -} - - -/* delete a port with the given port id */ -int snd_seq_delete_port(struct snd_seq_client *client, int port) -{ - unsigned long flags; - struct snd_seq_client_port *found = NULL, *p; - - mutex_lock(&client->ports_mutex); - write_lock_irqsave(&client->ports_lock, flags); - list_for_each_entry(p, &client->ports_list_head, list) { - if (p->addr.port == port) { - /* ok found. delete from the list at first */ - list_del(&p->list); - client->num_ports--; - found = p; - break; - } - } - write_unlock_irqrestore(&client->ports_lock, flags); - mutex_unlock(&client->ports_mutex); - if (found) - return port_delete(client, found); - else - return -ENOENT; -} - -/* delete the all ports belonging to the given client */ -int snd_seq_delete_all_ports(struct snd_seq_client *client) -{ - unsigned long flags; - struct list_head deleted_list; - struct snd_seq_client_port *port, *tmp; - - /* move the port list to deleted_list, and - * clear the port list in the client data. - */ - mutex_lock(&client->ports_mutex); - write_lock_irqsave(&client->ports_lock, flags); - if (! list_empty(&client->ports_list_head)) { - list_add(&deleted_list, &client->ports_list_head); - list_del_init(&client->ports_list_head); - } else { - INIT_LIST_HEAD(&deleted_list); - } - client->num_ports = 0; - write_unlock_irqrestore(&client->ports_lock, flags); - - /* remove each port in deleted_list */ - list_for_each_entry_safe(port, tmp, &deleted_list, list) { - list_del(&port->list); - snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port); - port_delete(client, port); - } - mutex_unlock(&client->ports_mutex); - return 0; -} - -/* set port info fields */ -int snd_seq_set_port_info(struct snd_seq_client_port * port, - struct snd_seq_port_info * info) -{ - if (snd_BUG_ON(!port || !info)) - return -EINVAL; - - /* set port name */ - if (info->name[0]) - strlcpy(port->name, info->name, sizeof(port->name)); - - /* set capabilities */ - port->capability = info->capability; - - /* get port type */ - port->type = info->type; - - /* information about supported channels/voices */ - port->midi_channels = info->midi_channels; - port->midi_voices = info->midi_voices; - port->synth_voices = info->synth_voices; - - /* timestamping */ - port->timestamping = (info->flags & SNDRV_SEQ_PORT_FLG_TIMESTAMP) ? 1 : 0; - port->time_real = (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0; - port->time_queue = info->time_queue; - - return 0; -} - -/* get port info fields */ -int snd_seq_get_port_info(struct snd_seq_client_port * port, - struct snd_seq_port_info * info) -{ - if (snd_BUG_ON(!port || !info)) - return -EINVAL; - - /* get port name */ - strlcpy(info->name, port->name, sizeof(info->name)); - - /* get capabilities */ - info->capability = port->capability; - - /* get port type */ - info->type = port->type; - - /* information about supported channels/voices */ - info->midi_channels = port->midi_channels; - info->midi_voices = port->midi_voices; - info->synth_voices = port->synth_voices; - - /* get subscriber counts */ - info->read_use = port->c_src.count; - info->write_use = port->c_dest.count; - - /* timestamping */ - info->flags = 0; - if (port->timestamping) { - info->flags |= SNDRV_SEQ_PORT_FLG_TIMESTAMP; - if (port->time_real) - info->flags |= SNDRV_SEQ_PORT_FLG_TIME_REAL; - info->time_queue = port->time_queue; - } - - return 0; -} - - - -/* - * call callback functions (if any): - * the callbacks are invoked only when the first (for connection) or - * the last subscription (for disconnection) is done. Second or later - * subscription results in increment of counter, but no callback is - * invoked. - * This feature is useful if these callbacks are associated with - * initialization or termination of devices (see seq_midi.c). - * - * If callback_all option is set, the callback function is invoked - * at each connection/disconnection. - */ - -static int subscribe_port(struct snd_seq_client *client, - struct snd_seq_client_port *port, - struct snd_seq_port_subs_info *grp, - struct snd_seq_port_subscribe *info, - int send_ack) -{ - int err = 0; - - if (!try_module_get(port->owner)) - return -EFAULT; - grp->count++; - if (grp->open && (port->callback_all || grp->count == 1)) { - err = grp->open(port->private_data, info); - if (err < 0) { - module_put(port->owner); - grp->count--; - } - } - if (err >= 0 && send_ack && client->type == USER_CLIENT) - snd_seq_client_notify_subscription(port->addr.client, port->addr.port, - info, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); - - return err; -} - -static int unsubscribe_port(struct snd_seq_client *client, - struct snd_seq_client_port *port, - struct snd_seq_port_subs_info *grp, - struct snd_seq_port_subscribe *info, - int send_ack) -{ - int err = 0; - - if (! grp->count) - return -EINVAL; - grp->count--; - if (grp->close && (port->callback_all || grp->count == 0)) - err = grp->close(port->private_data, info); - if (send_ack && client->type == USER_CLIENT) - snd_seq_client_notify_subscription(port->addr.client, port->addr.port, - info, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); - module_put(port->owner); - return err; -} - - - -/* check if both addresses are identical */ -static inline int addr_match(struct snd_seq_addr *r, struct snd_seq_addr *s) -{ - return (r->client == s->client) && (r->port == s->port); -} - -/* check the two subscribe info match */ -/* if flags is zero, checks only sender and destination addresses */ -static int match_subs_info(struct snd_seq_port_subscribe *r, - struct snd_seq_port_subscribe *s) -{ - if (addr_match(&r->sender, &s->sender) && - addr_match(&r->dest, &s->dest)) { - if (r->flags && r->flags == s->flags) - return r->queue == s->queue; - else if (! r->flags) - return 1; - } - return 0; -} - - -/* connect two ports */ -int snd_seq_port_connect(struct snd_seq_client *connector, - struct snd_seq_client *src_client, - struct snd_seq_client_port *src_port, - struct snd_seq_client *dest_client, - struct snd_seq_client_port *dest_port, - struct snd_seq_port_subscribe *info) -{ - struct snd_seq_port_subs_info *src = &src_port->c_src; - struct snd_seq_port_subs_info *dest = &dest_port->c_dest; - struct snd_seq_subscribers *subs, *s; - int err, src_called = 0; - unsigned long flags; - int exclusive; - - subs = kzalloc(sizeof(*subs), GFP_KERNEL); - if (! subs) - return -ENOMEM; - - subs->info = *info; - atomic_set(&subs->ref_count, 2); - - down_write(&src->list_mutex); - down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING); - - exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0; - err = -EBUSY; - if (exclusive) { - if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head)) - goto __error; - } else { - if (src->exclusive || dest->exclusive) - goto __error; - /* check whether already exists */ - list_for_each_entry(s, &src->list_head, src_list) { - if (match_subs_info(info, &s->info)) - goto __error; - } - list_for_each_entry(s, &dest->list_head, dest_list) { - if (match_subs_info(info, &s->info)) - goto __error; - } - } - - if ((err = subscribe_port(src_client, src_port, src, info, - connector->number != src_client->number)) < 0) - goto __error; - src_called = 1; - - if ((err = subscribe_port(dest_client, dest_port, dest, info, - connector->number != dest_client->number)) < 0) - goto __error; - - /* add to list */ - write_lock_irqsave(&src->list_lock, flags); - // write_lock(&dest->list_lock); // no other lock yet - list_add_tail(&subs->src_list, &src->list_head); - list_add_tail(&subs->dest_list, &dest->list_head); - // write_unlock(&dest->list_lock); // no other lock yet - write_unlock_irqrestore(&src->list_lock, flags); - - src->exclusive = dest->exclusive = exclusive; - - up_write(&dest->list_mutex); - up_write(&src->list_mutex); - return 0; - - __error: - if (src_called) - unsubscribe_port(src_client, src_port, src, info, - connector->number != src_client->number); - kfree(subs); - up_write(&dest->list_mutex); - up_write(&src->list_mutex); - return err; -} - - -/* remove the connection */ -int snd_seq_port_disconnect(struct snd_seq_client *connector, - struct snd_seq_client *src_client, - struct snd_seq_client_port *src_port, - struct snd_seq_client *dest_client, - struct snd_seq_client_port *dest_port, - struct snd_seq_port_subscribe *info) -{ - struct snd_seq_port_subs_info *src = &src_port->c_src; - struct snd_seq_port_subs_info *dest = &dest_port->c_dest; - struct snd_seq_subscribers *subs; - int err = -ENOENT; - unsigned long flags; - - down_write(&src->list_mutex); - down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING); - - /* look for the connection */ - list_for_each_entry(subs, &src->list_head, src_list) { - if (match_subs_info(info, &subs->info)) { - write_lock_irqsave(&src->list_lock, flags); - // write_lock(&dest->list_lock); // no lock yet - list_del(&subs->src_list); - list_del(&subs->dest_list); - // write_unlock(&dest->list_lock); - write_unlock_irqrestore(&src->list_lock, flags); - src->exclusive = dest->exclusive = 0; - unsubscribe_port(src_client, src_port, src, info, - connector->number != src_client->number); - unsubscribe_port(dest_client, dest_port, dest, info, - connector->number != dest_client->number); - kfree(subs); - err = 0; - break; - } - } - - up_write(&dest->list_mutex); - up_write(&src->list_mutex); - return err; -} - - -/* get matched subscriber */ -struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, - struct snd_seq_addr *dest_addr) -{ - struct snd_seq_subscribers *s, *found = NULL; - - down_read(&src_grp->list_mutex); - list_for_each_entry(s, &src_grp->list_head, src_list) { - if (addr_match(dest_addr, &s->info.dest)) { - found = s; - break; - } - } - up_read(&src_grp->list_mutex); - return found; -} - -/* - * Attach a device driver that wants to receive events from the - * sequencer. Returns the new port number on success. - * A driver that wants to receive the events converted to midi, will - * use snd_seq_midisynth_register_port(). - */ -/* exported */ -int snd_seq_event_port_attach(int client, - struct snd_seq_port_callback *pcbp, - int cap, int type, int midi_channels, - int midi_voices, char *portname) -{ - struct snd_seq_port_info portinfo; - int ret; - - /* Set up the port */ - memset(&portinfo, 0, sizeof(portinfo)); - portinfo.addr.client = client; - strlcpy(portinfo.name, portname ? portname : "Unamed port", - sizeof(portinfo.name)); - - portinfo.capability = cap; - portinfo.type = type; - portinfo.kernel = pcbp; - portinfo.midi_channels = midi_channels; - portinfo.midi_voices = midi_voices; - - /* Create it */ - ret = snd_seq_kernel_client_ctl(client, - SNDRV_SEQ_IOCTL_CREATE_PORT, - &portinfo); - - if (ret >= 0) - ret = portinfo.addr.port; - - return ret; -} - -EXPORT_SYMBOL(snd_seq_event_port_attach); - -/* - * Detach the driver from a port. - */ -/* exported */ -int snd_seq_event_port_detach(int client, int port) -{ - struct snd_seq_port_info portinfo; - int err; - - memset(&portinfo, 0, sizeof(portinfo)); - portinfo.addr.client = client; - portinfo.addr.port = port; - err = snd_seq_kernel_client_ctl(client, - SNDRV_SEQ_IOCTL_DELETE_PORT, - &portinfo); - - return err; -} - -EXPORT_SYMBOL(snd_seq_event_port_detach); diff --git a/ANDROID_3.4.5/sound/core/seq/seq_ports.h b/ANDROID_3.4.5/sound/core/seq/seq_ports.h deleted file mode 100644 index 9d711711..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_ports.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * ALSA sequencer Ports - * Copyright (c) 1998 by Frank van de Pol - * - * - * 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 - * - */ -#ifndef __SND_SEQ_PORTS_H -#define __SND_SEQ_PORTS_H - -#include -#include "seq_lock.h" - -/* list of 'exported' ports */ - -/* Client ports that are not exported are still accessible, but are - anonymous ports. - - If a port supports SUBSCRIPTION, that port can send events to all - subscribersto a special address, with address - (queue==SNDRV_SEQ_ADDRESS_SUBSCRIBERS). The message is then send to all - recipients that are registered in the subscription list. A typical - application for these SUBSCRIPTION events is handling of incoming MIDI - data. The port doesn't 'know' what other clients are interested in this - message. If for instance a MIDI recording application would like to receive - the events from that port, it will first have to subscribe with that port. - -*/ - -struct snd_seq_subscribers { - struct snd_seq_port_subscribe info; /* additional info */ - struct list_head src_list; /* link of sources */ - struct list_head dest_list; /* link of destinations */ - atomic_t ref_count; -}; - -struct snd_seq_port_subs_info { - struct list_head list_head; /* list of subscribed ports */ - unsigned int count; /* count of subscribers */ - unsigned int exclusive: 1; /* exclusive mode */ - struct rw_semaphore list_mutex; - rwlock_t list_lock; - int (*open)(void *private_data, struct snd_seq_port_subscribe *info); - int (*close)(void *private_data, struct snd_seq_port_subscribe *info); -}; - -struct snd_seq_client_port { - - struct snd_seq_addr addr; /* client/port number */ - struct module *owner; /* owner of this port */ - char name[64]; /* port name */ - struct list_head list; /* port list */ - snd_use_lock_t use_lock; - - /* subscribers */ - struct snd_seq_port_subs_info c_src; /* read (sender) list */ - struct snd_seq_port_subs_info c_dest; /* write (dest) list */ - - int (*event_input)(struct snd_seq_event *ev, int direct, void *private_data, - int atomic, int hop); - void (*private_free)(void *private_data); - void *private_data; - unsigned int callback_all : 1; - unsigned int closing : 1; - unsigned int timestamping: 1; - unsigned int time_real: 1; - int time_queue; - - /* capability, inport, output, sync */ - unsigned int capability; /* port capability bits */ - unsigned int type; /* port type bits */ - - /* supported channels */ - int midi_channels; - int midi_voices; - int synth_voices; - -}; - -struct snd_seq_client; - -/* return pointer to port structure and lock port */ -struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client, int num); - -/* search for next port - port is locked if found */ -struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client, - struct snd_seq_port_info *pinfo); - -/* unlock the port */ -#define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock) - -/* create a port, port number is returned (-1 on failure) */ -struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, int port_index); - -/* delete a port */ -int snd_seq_delete_port(struct snd_seq_client *client, int port); - -/* delete all ports */ -int snd_seq_delete_all_ports(struct snd_seq_client *client); - -/* set port info fields */ -int snd_seq_set_port_info(struct snd_seq_client_port *port, - struct snd_seq_port_info *info); - -/* get port info fields */ -int snd_seq_get_port_info(struct snd_seq_client_port *port, - struct snd_seq_port_info *info); - -/* add subscriber to subscription list */ -int snd_seq_port_connect(struct snd_seq_client *caller, - struct snd_seq_client *s, struct snd_seq_client_port *sp, - struct snd_seq_client *d, struct snd_seq_client_port *dp, - struct snd_seq_port_subscribe *info); - -/* remove subscriber from subscription list */ -int snd_seq_port_disconnect(struct snd_seq_client *caller, - struct snd_seq_client *s, struct snd_seq_client_port *sp, - struct snd_seq_client *d, struct snd_seq_client_port *dp, - struct snd_seq_port_subscribe *info); - -/* subscribe port */ -int snd_seq_port_subscribe(struct snd_seq_client_port *port, - struct snd_seq_port_subscribe *info); - -/* get matched subscriber */ -struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, - struct snd_seq_addr *dest_addr); - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_prioq.c b/ANDROID_3.4.5/sound/core/seq/seq_prioq.c deleted file mode 100644 index 29896ab2..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_prioq.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * ALSA sequencer Priority Queue - * Copyright (c) 1998-1999 by Frank van de Pol - * - * - * 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 "seq_timer.h" -#include "seq_prioq.h" - - -/* Implementation is a simple linked list for now... - - This priority queue orders the events on timestamp. For events with an - equeal timestamp the queue behaves as a FIFO. - - * - * +-------+ - * Head --> | first | - * +-------+ - * |next - * +-----v-+ - * | | - * +-------+ - * | - * +-----v-+ - * | | - * +-------+ - * | - * +-----v-+ - * Tail --> | last | - * +-------+ - * - - */ - - - -/* create new prioq (constructor) */ -struct snd_seq_prioq *snd_seq_prioq_new(void) -{ - struct snd_seq_prioq *f; - - f = kzalloc(sizeof(*f), GFP_KERNEL); - if (f == NULL) { - snd_printd("oops: malloc failed for snd_seq_prioq_new()\n"); - return NULL; - } - - spin_lock_init(&f->lock); - f->head = NULL; - f->tail = NULL; - f->cells = 0; - - return f; -} - -/* delete prioq (destructor) */ -void snd_seq_prioq_delete(struct snd_seq_prioq **fifo) -{ - struct snd_seq_prioq *f = *fifo; - *fifo = NULL; - - if (f == NULL) { - snd_printd("oops: snd_seq_prioq_delete() called with NULL prioq\n"); - return; - } - - /* release resources...*/ - /*....................*/ - - if (f->cells > 0) { - /* drain prioQ */ - while (f->cells > 0) - snd_seq_cell_free(snd_seq_prioq_cell_out(f)); - } - - kfree(f); -} - - - - -/* compare timestamp between events */ -/* return 1 if a >= b; 0 */ -static inline int compare_timestamp(struct snd_seq_event *a, - struct snd_seq_event *b) -{ - if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) { - /* compare ticks */ - return (snd_seq_compare_tick_time(&a->time.tick, &b->time.tick)); - } else { - /* compare real time */ - return (snd_seq_compare_real_time(&a->time.time, &b->time.time)); - } -} - -/* compare timestamp between events */ -/* return negative if a < b; - * zero if a = b; - * positive if a > b; - */ -static inline int compare_timestamp_rel(struct snd_seq_event *a, - struct snd_seq_event *b) -{ - if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) { - /* compare ticks */ - if (a->time.tick > b->time.tick) - return 1; - else if (a->time.tick == b->time.tick) - return 0; - else - return -1; - } else { - /* compare real time */ - if (a->time.time.tv_sec > b->time.time.tv_sec) - return 1; - else if (a->time.time.tv_sec == b->time.time.tv_sec) { - if (a->time.time.tv_nsec > b->time.time.tv_nsec) - return 1; - else if (a->time.time.tv_nsec == b->time.time.tv_nsec) - return 0; - else - return -1; - } else - return -1; - } -} - -/* enqueue cell to prioq */ -int snd_seq_prioq_cell_in(struct snd_seq_prioq * f, - struct snd_seq_event_cell * cell) -{ - struct snd_seq_event_cell *cur, *prev; - unsigned long flags; - int count; - int prior; - - if (snd_BUG_ON(!f || !cell)) - return -EINVAL; - - /* check flags */ - prior = (cell->event.flags & SNDRV_SEQ_PRIORITY_MASK); - - spin_lock_irqsave(&f->lock, flags); - - /* check if this element needs to inserted at the end (ie. ordered - data is inserted) This will be very likeley if a sequencer - application or midi file player is feeding us (sequential) data */ - if (f->tail && !prior) { - if (compare_timestamp(&cell->event, &f->tail->event)) { - /* add new cell to tail of the fifo */ - f->tail->next = cell; - f->tail = cell; - cell->next = NULL; - f->cells++; - spin_unlock_irqrestore(&f->lock, flags); - return 0; - } - } - /* traverse list of elements to find the place where the new cell is - to be inserted... Note that this is a order n process ! */ - - prev = NULL; /* previous cell */ - cur = f->head; /* cursor */ - - count = 10000; /* FIXME: enough big, isn't it? */ - while (cur != NULL) { - /* compare timestamps */ - int rel = compare_timestamp_rel(&cell->event, &cur->event); - if (rel < 0) - /* new cell has earlier schedule time, */ - break; - else if (rel == 0 && prior) - /* equal schedule time and prior to others */ - break; - /* new cell has equal or larger schedule time, */ - /* move cursor to next cell */ - prev = cur; - cur = cur->next; - if (! --count) { - spin_unlock_irqrestore(&f->lock, flags); - snd_printk(KERN_ERR "cannot find a pointer.. infinite loop?\n"); - return -EINVAL; - } - } - - /* insert it before cursor */ - if (prev != NULL) - prev->next = cell; - cell->next = cur; - - if (f->head == cur) /* this is the first cell, set head to it */ - f->head = cell; - if (cur == NULL) /* reached end of the list */ - f->tail = cell; - f->cells++; - spin_unlock_irqrestore(&f->lock, flags); - return 0; -} - -/* dequeue cell from prioq */ -struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f) -{ - struct snd_seq_event_cell *cell; - unsigned long flags; - - if (f == NULL) { - snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n"); - return NULL; - } - spin_lock_irqsave(&f->lock, flags); - - cell = f->head; - if (cell) { - f->head = cell->next; - - /* reset tail if this was the last element */ - if (f->tail == cell) - f->tail = NULL; - - cell->next = NULL; - f->cells--; - } - - spin_unlock_irqrestore(&f->lock, flags); - return cell; -} - -/* return number of events available in prioq */ -int snd_seq_prioq_avail(struct snd_seq_prioq * f) -{ - if (f == NULL) { - snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n"); - return 0; - } - return f->cells; -} - - -/* peek at cell at the head of the prioq */ -struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq * f) -{ - if (f == NULL) { - snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n"); - return NULL; - } - return f->head; -} - - -static inline int prioq_match(struct snd_seq_event_cell *cell, - int client, int timestamp) -{ - if (cell->event.source.client == client || - cell->event.dest.client == client) - return 1; - if (!timestamp) - return 0; - switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) { - case SNDRV_SEQ_TIME_STAMP_TICK: - if (cell->event.time.tick) - return 1; - break; - case SNDRV_SEQ_TIME_STAMP_REAL: - if (cell->event.time.time.tv_sec || - cell->event.time.time.tv_nsec) - return 1; - break; - } - return 0; -} - -/* remove cells for left client */ -void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp) -{ - register struct snd_seq_event_cell *cell, *next; - unsigned long flags; - struct snd_seq_event_cell *prev = NULL; - struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext; - - /* collect all removed cells */ - spin_lock_irqsave(&f->lock, flags); - cell = f->head; - while (cell) { - next = cell->next; - if (prioq_match(cell, client, timestamp)) { - /* remove cell from prioq */ - if (cell == f->head) { - f->head = cell->next; - } else { - prev->next = cell->next; - } - if (cell == f->tail) - f->tail = cell->next; - f->cells--; - /* add cell to free list */ - cell->next = NULL; - if (freefirst == NULL) { - freefirst = cell; - } else { - freeprev->next = cell; - } - freeprev = cell; - } else { -#if 0 - printk(KERN_DEBUG "type = %i, source = %i, dest = %i, " - "client = %i\n", - cell->event.type, - cell->event.source.client, - cell->event.dest.client, - client); -#endif - prev = cell; - } - cell = next; - } - spin_unlock_irqrestore(&f->lock, flags); - - /* remove selected cells */ - while (freefirst) { - freenext = freefirst->next; - snd_seq_cell_free(freefirst); - freefirst = freenext; - } -} - -static int prioq_remove_match(struct snd_seq_remove_events *info, - struct snd_seq_event *ev) -{ - int res; - - if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) { - if (ev->dest.client != info->dest.client || - ev->dest.port != info->dest.port) - return 0; - } - if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) { - if (! snd_seq_ev_is_channel_type(ev)) - return 0; - /* data.note.channel and data.control.channel are identical */ - if (ev->data.note.channel != info->channel) - return 0; - } - if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) { - if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK) - res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick); - else - res = snd_seq_compare_real_time(&ev->time.time, &info->time.time); - if (!res) - return 0; - } - if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) { - if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK) - res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick); - else - res = snd_seq_compare_real_time(&ev->time.time, &info->time.time); - if (res) - return 0; - } - if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) { - if (ev->type != info->type) - return 0; - } - if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) { - /* Do not remove off events */ - switch (ev->type) { - case SNDRV_SEQ_EVENT_NOTEOFF: - /* case SNDRV_SEQ_EVENT_SAMPLE_STOP: */ - return 0; - default: - break; - } - } - if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) { - if (info->tag != ev->tag) - return 0; - } - - return 1; -} - -/* remove cells matching remove criteria */ -void snd_seq_prioq_remove_events(struct snd_seq_prioq * f, int client, - struct snd_seq_remove_events *info) -{ - struct snd_seq_event_cell *cell, *next; - unsigned long flags; - struct snd_seq_event_cell *prev = NULL; - struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext; - - /* collect all removed cells */ - spin_lock_irqsave(&f->lock, flags); - cell = f->head; - - while (cell) { - next = cell->next; - if (cell->event.source.client == client && - prioq_remove_match(info, &cell->event)) { - - /* remove cell from prioq */ - if (cell == f->head) { - f->head = cell->next; - } else { - prev->next = cell->next; - } - - if (cell == f->tail) - f->tail = cell->next; - f->cells--; - - /* add cell to free list */ - cell->next = NULL; - if (freefirst == NULL) { - freefirst = cell; - } else { - freeprev->next = cell; - } - - freeprev = cell; - } else { - prev = cell; - } - cell = next; - } - spin_unlock_irqrestore(&f->lock, flags); - - /* remove selected cells */ - while (freefirst) { - freenext = freefirst->next; - snd_seq_cell_free(freefirst); - freefirst = freenext; - } -} - - diff --git a/ANDROID_3.4.5/sound/core/seq/seq_prioq.h b/ANDROID_3.4.5/sound/core/seq/seq_prioq.h deleted file mode 100644 index d38bb78d..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_prioq.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ALSA sequencer Priority Queue - * Copyright (c) 1998 by Frank van de Pol - * - * - * 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 - * - */ -#ifndef __SND_SEQ_PRIOQ_H -#define __SND_SEQ_PRIOQ_H - -#include "seq_memory.h" - - -/* === PRIOQ === */ - -struct snd_seq_prioq { - struct snd_seq_event_cell *head; /* pointer to head of prioq */ - struct snd_seq_event_cell *tail; /* pointer to tail of prioq */ - int cells; - spinlock_t lock; -}; - - -/* create new prioq (constructor) */ -struct snd_seq_prioq *snd_seq_prioq_new(void); - -/* delete prioq (destructor) */ -void snd_seq_prioq_delete(struct snd_seq_prioq **fifo); - -/* enqueue cell to prioq */ -int snd_seq_prioq_cell_in(struct snd_seq_prioq *f, struct snd_seq_event_cell *cell); - -/* dequeue cell from prioq */ -struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f); - -/* return number of events available in prioq */ -int snd_seq_prioq_avail(struct snd_seq_prioq *f); - -/* peek at cell at the head of the prioq */ -struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq *f); - -/* client left queue */ -void snd_seq_prioq_leave(struct snd_seq_prioq *f, int client, int timestamp); - -/* Remove events */ -void snd_seq_prioq_remove_events(struct snd_seq_prioq *f, int client, - struct snd_seq_remove_events *info); - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_queue.c b/ANDROID_3.4.5/sound/core/seq/seq_queue.c deleted file mode 100644 index f9077361..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_queue.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * ALSA sequencer Timing queue handling - * Copyright (c) 1998-1999 by Frank van de Pol - * - * 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 - * - * MAJOR CHANGES - * Nov. 13, 1999 Takashi Iwai - * - Queues are allocated dynamically via ioctl. - * - When owner client is deleted, all owned queues are deleted, too. - * - Owner of unlocked queue is kept unmodified even if it is - * manipulated by other clients. - * - Owner field in SET_QUEUE_OWNER ioctl must be identical with the - * caller client. i.e. Changing owner to a third client is not - * allowed. - * - * Aug. 30, 2000 Takashi Iwai - * - Queues are managed in static array again, but with better way. - * The API itself is identical. - * - The queue is locked when struct snd_seq_queue pointer is returned via - * queueptr(). This pointer *MUST* be released afterward by - * queuefree(ptr). - * - Addition of experimental sync support. - */ - -#include -#include -#include - -#include "seq_memory.h" -#include "seq_queue.h" -#include "seq_clientmgr.h" -#include "seq_fifo.h" -#include "seq_timer.h" -#include "seq_info.h" - -/* list of allocated queues */ -static struct snd_seq_queue *queue_list[SNDRV_SEQ_MAX_QUEUES]; -static DEFINE_SPINLOCK(queue_list_lock); -/* number of queues allocated */ -static int num_queues; - -int snd_seq_queue_get_cur_queues(void) -{ - return num_queues; -} - -/*----------------------------------------------------------------*/ - -/* assign queue id and insert to list */ -static int queue_list_add(struct snd_seq_queue *q) -{ - int i; - unsigned long flags; - - spin_lock_irqsave(&queue_list_lock, flags); - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if (! queue_list[i]) { - queue_list[i] = q; - q->queue = i; - num_queues++; - spin_unlock_irqrestore(&queue_list_lock, flags); - return i; - } - } - spin_unlock_irqrestore(&queue_list_lock, flags); - return -1; -} - -static struct snd_seq_queue *queue_list_remove(int id, int client) -{ - struct snd_seq_queue *q; - unsigned long flags; - - spin_lock_irqsave(&queue_list_lock, flags); - q = queue_list[id]; - if (q) { - spin_lock(&q->owner_lock); - if (q->owner == client) { - /* found */ - q->klocked = 1; - spin_unlock(&q->owner_lock); - queue_list[id] = NULL; - num_queues--; - spin_unlock_irqrestore(&queue_list_lock, flags); - return q; - } - spin_unlock(&q->owner_lock); - } - spin_unlock_irqrestore(&queue_list_lock, flags); - return NULL; -} - -/*----------------------------------------------------------------*/ - -/* create new queue (constructor) */ -static struct snd_seq_queue *queue_new(int owner, int locked) -{ - struct snd_seq_queue *q; - - q = kzalloc(sizeof(*q), GFP_KERNEL); - if (q == NULL) { - snd_printd("malloc failed for snd_seq_queue_new()\n"); - return NULL; - } - - spin_lock_init(&q->owner_lock); - spin_lock_init(&q->check_lock); - mutex_init(&q->timer_mutex); - snd_use_lock_init(&q->use_lock); - q->queue = -1; - - q->tickq = snd_seq_prioq_new(); - q->timeq = snd_seq_prioq_new(); - q->timer = snd_seq_timer_new(); - if (q->tickq == NULL || q->timeq == NULL || q->timer == NULL) { - snd_seq_prioq_delete(&q->tickq); - snd_seq_prioq_delete(&q->timeq); - snd_seq_timer_delete(&q->timer); - kfree(q); - return NULL; - } - - q->owner = owner; - q->locked = locked; - q->klocked = 0; - - return q; -} - -/* delete queue (destructor) */ -static void queue_delete(struct snd_seq_queue *q) -{ - /* stop and release the timer */ - snd_seq_timer_stop(q->timer); - snd_seq_timer_close(q); - /* wait until access free */ - snd_use_lock_sync(&q->use_lock); - /* release resources... */ - snd_seq_prioq_delete(&q->tickq); - snd_seq_prioq_delete(&q->timeq); - snd_seq_timer_delete(&q->timer); - - kfree(q); -} - - -/*----------------------------------------------------------------*/ - -/* setup queues */ -int __init snd_seq_queues_init(void) -{ - /* - memset(queue_list, 0, sizeof(queue_list)); - num_queues = 0; - */ - return 0; -} - -/* delete all existing queues */ -void __exit snd_seq_queues_delete(void) -{ - int i; - - /* clear list */ - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if (queue_list[i]) - queue_delete(queue_list[i]); - } -} - -/* allocate a new queue - - * return queue index value or negative value for error - */ -int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags) -{ - struct snd_seq_queue *q; - - q = queue_new(client, locked); - if (q == NULL) - return -ENOMEM; - q->info_flags = info_flags; - if (queue_list_add(q) < 0) { - queue_delete(q); - return -ENOMEM; - } - snd_seq_queue_use(q->queue, client, 1); /* use this queue */ - return q->queue; -} - -/* delete a queue - queue must be owned by the client */ -int snd_seq_queue_delete(int client, int queueid) -{ - struct snd_seq_queue *q; - - if (queueid < 0 || queueid >= SNDRV_SEQ_MAX_QUEUES) - return -EINVAL; - q = queue_list_remove(queueid, client); - if (q == NULL) - return -EINVAL; - queue_delete(q); - - return 0; -} - - -/* return pointer to queue structure for specified id */ -struct snd_seq_queue *queueptr(int queueid) -{ - struct snd_seq_queue *q; - unsigned long flags; - - if (queueid < 0 || queueid >= SNDRV_SEQ_MAX_QUEUES) - return NULL; - spin_lock_irqsave(&queue_list_lock, flags); - q = queue_list[queueid]; - if (q) - snd_use_lock_use(&q->use_lock); - spin_unlock_irqrestore(&queue_list_lock, flags); - return q; -} - -/* return the (first) queue matching with the specified name */ -struct snd_seq_queue *snd_seq_queue_find_name(char *name) -{ - int i; - struct snd_seq_queue *q; - - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) != NULL) { - if (strncmp(q->name, name, sizeof(q->name)) == 0) - return q; - queuefree(q); - } - } - return NULL; -} - - -/* -------------------------------------------------------- */ - -void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop) -{ - unsigned long flags; - struct snd_seq_event_cell *cell; - - if (q == NULL) - return; - - /* make this function non-reentrant */ - spin_lock_irqsave(&q->check_lock, flags); - if (q->check_blocked) { - q->check_again = 1; - spin_unlock_irqrestore(&q->check_lock, flags); - return; /* other thread is already checking queues */ - } - q->check_blocked = 1; - spin_unlock_irqrestore(&q->check_lock, flags); - - __again: - /* Process tick queue... */ - while ((cell = snd_seq_prioq_cell_peek(q->tickq)) != NULL) { - if (snd_seq_compare_tick_time(&q->timer->tick.cur_tick, - &cell->event.time.tick)) { - cell = snd_seq_prioq_cell_out(q->tickq); - if (cell) - snd_seq_dispatch_event(cell, atomic, hop); - } else { - /* event remains in the queue */ - break; - } - } - - - /* Process time queue... */ - while ((cell = snd_seq_prioq_cell_peek(q->timeq)) != NULL) { - if (snd_seq_compare_real_time(&q->timer->cur_time, - &cell->event.time.time)) { - cell = snd_seq_prioq_cell_out(q->timeq); - if (cell) - snd_seq_dispatch_event(cell, atomic, hop); - } else { - /* event remains in the queue */ - break; - } - } - - /* free lock */ - spin_lock_irqsave(&q->check_lock, flags); - if (q->check_again) { - q->check_again = 0; - spin_unlock_irqrestore(&q->check_lock, flags); - goto __again; - } - q->check_blocked = 0; - spin_unlock_irqrestore(&q->check_lock, flags); -} - - -/* enqueue a event to singe queue */ -int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop) -{ - int dest, err; - struct snd_seq_queue *q; - - if (snd_BUG_ON(!cell)) - return -EINVAL; - dest = cell->event.queue; /* destination queue */ - q = queueptr(dest); - if (q == NULL) - return -EINVAL; - /* handle relative time stamps, convert them into absolute */ - if ((cell->event.flags & SNDRV_SEQ_TIME_MODE_MASK) == SNDRV_SEQ_TIME_MODE_REL) { - switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) { - case SNDRV_SEQ_TIME_STAMP_TICK: - cell->event.time.tick += q->timer->tick.cur_tick; - break; - - case SNDRV_SEQ_TIME_STAMP_REAL: - snd_seq_inc_real_time(&cell->event.time.time, - &q->timer->cur_time); - break; - } - cell->event.flags &= ~SNDRV_SEQ_TIME_MODE_MASK; - cell->event.flags |= SNDRV_SEQ_TIME_MODE_ABS; - } - /* enqueue event in the real-time or midi queue */ - switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) { - case SNDRV_SEQ_TIME_STAMP_TICK: - err = snd_seq_prioq_cell_in(q->tickq, cell); - break; - - case SNDRV_SEQ_TIME_STAMP_REAL: - default: - err = snd_seq_prioq_cell_in(q->timeq, cell); - break; - } - - if (err < 0) { - queuefree(q); /* unlock */ - return err; - } - - /* trigger dispatching */ - snd_seq_check_queue(q, atomic, hop); - - queuefree(q); /* unlock */ - - return 0; -} - - -/*----------------------------------------------------------------*/ - -static inline int check_access(struct snd_seq_queue *q, int client) -{ - return (q->owner == client) || (!q->locked && !q->klocked); -} - -/* check if the client has permission to modify queue parameters. - * if it does, lock the queue - */ -static int queue_access_lock(struct snd_seq_queue *q, int client) -{ - unsigned long flags; - int access_ok; - - spin_lock_irqsave(&q->owner_lock, flags); - access_ok = check_access(q, client); - if (access_ok) - q->klocked = 1; - spin_unlock_irqrestore(&q->owner_lock, flags); - return access_ok; -} - -/* unlock the queue */ -static inline void queue_access_unlock(struct snd_seq_queue *q) -{ - unsigned long flags; - - spin_lock_irqsave(&q->owner_lock, flags); - q->klocked = 0; - spin_unlock_irqrestore(&q->owner_lock, flags); -} - -/* exported - only checking permission */ -int snd_seq_queue_check_access(int queueid, int client) -{ - struct snd_seq_queue *q = queueptr(queueid); - int access_ok; - unsigned long flags; - - if (! q) - return 0; - spin_lock_irqsave(&q->owner_lock, flags); - access_ok = check_access(q, client); - spin_unlock_irqrestore(&q->owner_lock, flags); - queuefree(q); - return access_ok; -} - -/*----------------------------------------------------------------*/ - -/* - * change queue's owner and permission - */ -int snd_seq_queue_set_owner(int queueid, int client, int locked) -{ - struct snd_seq_queue *q = queueptr(queueid); - - if (q == NULL) - return -EINVAL; - - if (! queue_access_lock(q, client)) { - queuefree(q); - return -EPERM; - } - - q->locked = locked ? 1 : 0; - q->owner = client; - queue_access_unlock(q); - queuefree(q); - - return 0; -} - - -/*----------------------------------------------------------------*/ - -/* open timer - - * q->use mutex should be down before calling this function to avoid - * confliction with snd_seq_queue_use() - */ -int snd_seq_queue_timer_open(int queueid) -{ - int result = 0; - struct snd_seq_queue *queue; - struct snd_seq_timer *tmr; - - queue = queueptr(queueid); - if (queue == NULL) - return -EINVAL; - tmr = queue->timer; - if ((result = snd_seq_timer_open(queue)) < 0) { - snd_seq_timer_defaults(tmr); - result = snd_seq_timer_open(queue); - } - queuefree(queue); - return result; -} - -/* close timer - - * q->use mutex should be down before calling this function - */ -int snd_seq_queue_timer_close(int queueid) -{ - struct snd_seq_queue *queue; - int result = 0; - - queue = queueptr(queueid); - if (queue == NULL) - return -EINVAL; - snd_seq_timer_close(queue); - queuefree(queue); - return result; -} - -/* change queue tempo and ppq */ -int snd_seq_queue_timer_set_tempo(int queueid, int client, - struct snd_seq_queue_tempo *info) -{ - struct snd_seq_queue *q = queueptr(queueid); - int result; - - if (q == NULL) - return -EINVAL; - if (! queue_access_lock(q, client)) { - queuefree(q); - return -EPERM; - } - - result = snd_seq_timer_set_tempo(q->timer, info->tempo); - if (result >= 0) - result = snd_seq_timer_set_ppq(q->timer, info->ppq); - if (result >= 0 && info->skew_base > 0) - result = snd_seq_timer_set_skew(q->timer, info->skew_value, - info->skew_base); - queue_access_unlock(q); - queuefree(q); - return result; -} - - -/* use or unuse this queue - - * if it is the first client, starts the timer. - * if it is not longer used by any clients, stop the timer. - */ -int snd_seq_queue_use(int queueid, int client, int use) -{ - struct snd_seq_queue *queue; - - queue = queueptr(queueid); - if (queue == NULL) - return -EINVAL; - mutex_lock(&queue->timer_mutex); - if (use) { - if (!test_and_set_bit(client, queue->clients_bitmap)) - queue->clients++; - } else { - if (test_and_clear_bit(client, queue->clients_bitmap)) - queue->clients--; - } - if (queue->clients) { - if (use && queue->clients == 1) - snd_seq_timer_defaults(queue->timer); - snd_seq_timer_open(queue); - } else { - snd_seq_timer_close(queue); - } - mutex_unlock(&queue->timer_mutex); - queuefree(queue); - return 0; -} - -/* - * check if queue is used by the client - * return negative value if the queue is invalid. - * return 0 if not used, 1 if used. - */ -int snd_seq_queue_is_used(int queueid, int client) -{ - struct snd_seq_queue *q; - int result; - - q = queueptr(queueid); - if (q == NULL) - return -EINVAL; /* invalid queue */ - result = test_bit(client, q->clients_bitmap) ? 1 : 0; - queuefree(q); - return result; -} - - -/*----------------------------------------------------------------*/ - -/* notification that client has left the system - - * stop the timer on all queues owned by this client - */ -void snd_seq_queue_client_termination(int client) -{ - unsigned long flags; - int i; - struct snd_seq_queue *q; - - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) - continue; - spin_lock_irqsave(&q->owner_lock, flags); - if (q->owner == client) - q->klocked = 1; - spin_unlock_irqrestore(&q->owner_lock, flags); - if (q->owner == client) { - if (q->timer->running) - snd_seq_timer_stop(q->timer); - snd_seq_timer_reset(q->timer); - } - queuefree(q); - } -} - -/* final stage notification - - * remove cells for no longer exist client (for non-owned queue) - * or delete this queue (for owned queue) - */ -void snd_seq_queue_client_leave(int client) -{ - int i; - struct snd_seq_queue *q; - - /* delete own queues from queue list */ - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queue_list_remove(i, client)) != NULL) - queue_delete(q); - } - - /* remove cells from existing queues - - * they are not owned by this client - */ - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) - continue; - if (test_bit(client, q->clients_bitmap)) { - snd_seq_prioq_leave(q->tickq, client, 0); - snd_seq_prioq_leave(q->timeq, client, 0); - snd_seq_queue_use(q->queue, client, 0); - } - queuefree(q); - } -} - - - -/*----------------------------------------------------------------*/ - -/* remove cells from all queues */ -void snd_seq_queue_client_leave_cells(int client) -{ - int i; - struct snd_seq_queue *q; - - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) - continue; - snd_seq_prioq_leave(q->tickq, client, 0); - snd_seq_prioq_leave(q->timeq, client, 0); - queuefree(q); - } -} - -/* remove cells based on flush criteria */ -void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info) -{ - int i; - struct snd_seq_queue *q; - - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) - continue; - if (test_bit(client, q->clients_bitmap) && - (! (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) || - q->queue == info->queue)) { - snd_seq_prioq_remove_events(q->tickq, client, info); - snd_seq_prioq_remove_events(q->timeq, client, info); - } - queuefree(q); - } -} - -/*----------------------------------------------------------------*/ - -/* - * send events to all subscribed ports - */ -static void queue_broadcast_event(struct snd_seq_queue *q, struct snd_seq_event *ev, - int atomic, int hop) -{ - struct snd_seq_event sev; - - sev = *ev; - - sev.flags = SNDRV_SEQ_TIME_STAMP_TICK|SNDRV_SEQ_TIME_MODE_ABS; - sev.time.tick = q->timer->tick.cur_tick; - sev.queue = q->queue; - sev.data.queue.queue = q->queue; - - /* broadcast events from Timer port */ - sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM; - sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; - sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop); -} - -/* - * process a received queue-control event. - * this function is exported for seq_sync.c. - */ -static void snd_seq_queue_process_event(struct snd_seq_queue *q, - struct snd_seq_event *ev, - int atomic, int hop) -{ - switch (ev->type) { - case SNDRV_SEQ_EVENT_START: - snd_seq_prioq_leave(q->tickq, ev->source.client, 1); - snd_seq_prioq_leave(q->timeq, ev->source.client, 1); - if (! snd_seq_timer_start(q->timer)) - queue_broadcast_event(q, ev, atomic, hop); - break; - - case SNDRV_SEQ_EVENT_CONTINUE: - if (! snd_seq_timer_continue(q->timer)) - queue_broadcast_event(q, ev, atomic, hop); - break; - - case SNDRV_SEQ_EVENT_STOP: - snd_seq_timer_stop(q->timer); - queue_broadcast_event(q, ev, atomic, hop); - break; - - case SNDRV_SEQ_EVENT_TEMPO: - snd_seq_timer_set_tempo(q->timer, ev->data.queue.param.value); - queue_broadcast_event(q, ev, atomic, hop); - break; - - case SNDRV_SEQ_EVENT_SETPOS_TICK: - if (snd_seq_timer_set_position_tick(q->timer, ev->data.queue.param.time.tick) == 0) { - queue_broadcast_event(q, ev, atomic, hop); - } - break; - - case SNDRV_SEQ_EVENT_SETPOS_TIME: - if (snd_seq_timer_set_position_time(q->timer, ev->data.queue.param.time.time) == 0) { - queue_broadcast_event(q, ev, atomic, hop); - } - break; - case SNDRV_SEQ_EVENT_QUEUE_SKEW: - if (snd_seq_timer_set_skew(q->timer, - ev->data.queue.param.skew.value, - ev->data.queue.param.skew.base) == 0) { - queue_broadcast_event(q, ev, atomic, hop); - } - break; - } -} - - -/* - * Queue control via timer control port: - * this function is exported as a callback of timer port. - */ -int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop) -{ - struct snd_seq_queue *q; - - if (snd_BUG_ON(!ev)) - return -EINVAL; - q = queueptr(ev->data.queue.queue); - - if (q == NULL) - return -EINVAL; - - if (! queue_access_lock(q, ev->source.client)) { - queuefree(q); - return -EPERM; - } - - snd_seq_queue_process_event(q, ev, atomic, hop); - - queue_access_unlock(q); - queuefree(q); - return 0; -} - - -/*----------------------------------------------------------------*/ - -#ifdef CONFIG_PROC_FS -/* exported to seq_info.c */ -void snd_seq_info_queues_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - int i, bpm; - struct snd_seq_queue *q; - struct snd_seq_timer *tmr; - - for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) - continue; - - tmr = q->timer; - if (tmr->tempo) - bpm = 60000000 / tmr->tempo; - else - bpm = 0; - - snd_iprintf(buffer, "queue %d: [%s]\n", q->queue, q->name); - snd_iprintf(buffer, "owned by client : %d\n", q->owner); - snd_iprintf(buffer, "lock status : %s\n", q->locked ? "Locked" : "Free"); - snd_iprintf(buffer, "queued time events : %d\n", snd_seq_prioq_avail(q->timeq)); - snd_iprintf(buffer, "queued tick events : %d\n", snd_seq_prioq_avail(q->tickq)); - snd_iprintf(buffer, "timer state : %s\n", tmr->running ? "Running" : "Stopped"); - snd_iprintf(buffer, "timer PPQ : %d\n", tmr->ppq); - snd_iprintf(buffer, "current tempo : %d\n", tmr->tempo); - snd_iprintf(buffer, "current BPM : %d\n", bpm); - snd_iprintf(buffer, "current time : %d.%09d s\n", tmr->cur_time.tv_sec, tmr->cur_time.tv_nsec); - snd_iprintf(buffer, "current tick : %d\n", tmr->tick.cur_tick); - snd_iprintf(buffer, "\n"); - queuefree(q); - } -} -#endif /* CONFIG_PROC_FS */ - diff --git a/ANDROID_3.4.5/sound/core/seq/seq_queue.h b/ANDROID_3.4.5/sound/core/seq/seq_queue.h deleted file mode 100644 index 30c81114..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_queue.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * ALSA sequencer Queue handling - * Copyright (c) 1998-1999 by Frank van de Pol - * - * 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 - * - */ -#ifndef __SND_SEQ_QUEUE_H -#define __SND_SEQ_QUEUE_H - -#include "seq_memory.h" -#include "seq_prioq.h" -#include "seq_timer.h" -#include "seq_lock.h" -#include -#include -#include - -#define SEQ_QUEUE_NO_OWNER (-1) - -struct snd_seq_queue { - int queue; /* queue number */ - - char name[64]; /* name of this queue */ - - struct snd_seq_prioq *tickq; /* midi tick event queue */ - struct snd_seq_prioq *timeq; /* real-time event queue */ - - struct snd_seq_timer *timer; /* time keeper for this queue */ - int owner; /* client that 'owns' the timer */ - unsigned int locked:1, /* timer is only accesibble by owner if set */ - klocked:1, /* kernel lock (after START) */ - check_again:1, - check_blocked:1; - - unsigned int flags; /* status flags */ - unsigned int info_flags; /* info for sync */ - - spinlock_t owner_lock; - spinlock_t check_lock; - - /* clients which uses this queue (bitmap) */ - DECLARE_BITMAP(clients_bitmap, SNDRV_SEQ_MAX_CLIENTS); - unsigned int clients; /* users of this queue */ - struct mutex timer_mutex; - - snd_use_lock_t use_lock; -}; - - -/* get the number of current queues */ -int snd_seq_queue_get_cur_queues(void); - -/* init queues structure */ -int snd_seq_queues_init(void); - -/* delete queues */ -void snd_seq_queues_delete(void); - - -/* create new queue (constructor) */ -int snd_seq_queue_alloc(int client, int locked, unsigned int flags); - -/* delete queue (destructor) */ -int snd_seq_queue_delete(int client, int queueid); - -/* notification that client has left the system */ -void snd_seq_queue_client_termination(int client); - -/* final stage */ -void snd_seq_queue_client_leave(int client); - -/* enqueue a event received from one the clients */ -int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop); - -/* Remove events */ -void snd_seq_queue_client_leave_cells(int client); -void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info); - -/* return pointer to queue structure for specified id */ -struct snd_seq_queue *queueptr(int queueid); -/* unlock */ -#define queuefree(q) snd_use_lock_free(&(q)->use_lock) - -/* return the (first) queue matching with the specified name */ -struct snd_seq_queue *snd_seq_queue_find_name(char *name); - -/* check single queue and dispatch events */ -void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop); - -/* access to queue's parameters */ -int snd_seq_queue_check_access(int queueid, int client); -int snd_seq_queue_timer_set_tempo(int queueid, int client, struct snd_seq_queue_tempo *info); -int snd_seq_queue_set_owner(int queueid, int client, int locked); -int snd_seq_queue_set_locked(int queueid, int client, int locked); -int snd_seq_queue_timer_open(int queueid); -int snd_seq_queue_timer_close(int queueid); -int snd_seq_queue_use(int queueid, int client, int use); -int snd_seq_queue_is_used(int queueid, int client); - -int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop); - -/* - * 64bit division - for sync stuff.. - */ -#if defined(i386) || defined(i486) - -#define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("divl %4" \ - : "=a" ((u32)(q)), \ - "=d" ((u32)(r)) \ - : "0" ((u32)(n0)), \ - "1" ((u32)(n1)), \ - "rm" ((u32)(d))) - -#define u64_div(x,y,q) do {u32 __tmp; udiv_qrnnd(q, __tmp, (x)>>32, x, y);} while (0) -#define u64_mod(x,y,r) do {u32 __tmp; udiv_qrnnd(__tmp, q, (x)>>32, x, y);} while (0) -#define u64_divmod(x,y,q,r) udiv_qrnnd(q, r, (x)>>32, x, y) - -#else -#define u64_div(x,y,q) ((q) = (u32)((u64)(x) / (u64)(y))) -#define u64_mod(x,y,r) ((r) = (u32)((u64)(x) % (u64)(y))) -#define u64_divmod(x,y,q,r) (u64_div(x,y,q), u64_mod(x,y,r)) -#endif - - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_system.c b/ANDROID_3.4.5/sound/core/seq/seq_system.c deleted file mode 100644 index 8ce1d0b4..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_system.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * ALSA sequencer System services Client - * Copyright (c) 1998-1999 by Frank van de Pol - * - * - * 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 "seq_system.h" -#include "seq_timer.h" -#include "seq_queue.h" - -/* internal client that provide system services, access to timer etc. */ - -/* - * Port "Timer" - * - send tempo /start/stop etc. events to this port to manipulate the - * queue's timer. The queue address is specified in - * data.queue.queue. - * - this port supports subscription. The received timer events are - * broadcasted to all subscribed clients. The modified tempo - * value is stored on data.queue.value. - * The modifier client/port is not send. - * - * Port "Announce" - * - does not receive message - * - supports supscription. For each client or port attaching to or - * detaching from the system an announcement is send to the subscribed - * clients. - * - * Idea: the subscription mechanism might also work handy for distributing - * synchronisation and timing information. In this case we would ideally have - * a list of subscribers for each type of sync (time, tick), for each timing - * queue. - * - * NOTE: the queue to be started, stopped, etc. must be specified - * in data.queue.addr.queue field. queue is used only for - * scheduling, and no longer referred as affected queue. - * They are used only for timer broadcast (see above). - * -- iwai - */ - - -/* client id of our system client */ -static int sysclient = -1; - -/* port id numbers for this client */ -static int announce_port = -1; - - - -/* fill standard header data, source port & channel are filled in */ -static int setheader(struct snd_seq_event * ev, int client, int port) -{ - if (announce_port < 0) - return -ENODEV; - - memset(ev, 0, sizeof(struct snd_seq_event)); - - ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; - - ev->source.client = sysclient; - ev->source.port = announce_port; - ev->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - - /* fill data */ - /*ev->data.addr.queue = SNDRV_SEQ_ADDRESS_UNKNOWN;*/ - ev->data.addr.client = client; - ev->data.addr.port = port; - - return 0; -} - - -/* entry points for broadcasting system events */ -void snd_seq_system_broadcast(int client, int port, int type) -{ - struct snd_seq_event ev; - - if (setheader(&ev, client, port) < 0) - return; - ev.type = type; - snd_seq_kernel_client_dispatch(sysclient, &ev, 0, 0); -} - -/* entry points for broadcasting system events */ -int snd_seq_system_notify(int client, int port, struct snd_seq_event *ev) -{ - ev->flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; - ev->source.client = sysclient; - ev->source.port = announce_port; - ev->dest.client = client; - ev->dest.port = port; - return snd_seq_kernel_client_dispatch(sysclient, ev, 0, 0); -} - -/* call-back handler for timer events */ -static int event_input_timer(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop) -{ - return snd_seq_control_queue(ev, atomic, hop); -} - -/* register our internal client */ -int __init snd_seq_system_client_init(void) -{ - struct snd_seq_port_callback pcallbacks; - struct snd_seq_port_info *port; - - port = kzalloc(sizeof(*port), GFP_KERNEL); - if (!port) - return -ENOMEM; - - memset(&pcallbacks, 0, sizeof(pcallbacks)); - pcallbacks.owner = THIS_MODULE; - pcallbacks.event_input = event_input_timer; - - /* register client */ - sysclient = snd_seq_create_kernel_client(NULL, 0, "System"); - - /* register timer */ - strcpy(port->name, "Timer"); - port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */ - port->capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */ - port->kernel = &pcallbacks; - port->type = 0; - port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; - port->addr.client = sysclient; - port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; - snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port); - - /* register announcement port */ - strcpy(port->name, "Announce"); - port->capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */ - port->kernel = NULL; - port->type = 0; - port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; - port->addr.client = sysclient; - port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; - snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port); - announce_port = port->addr.port; - - kfree(port); - return 0; -} - - -/* unregister our internal client */ -void __exit snd_seq_system_client_done(void) -{ - int oldsysclient = sysclient; - - if (oldsysclient >= 0) { - sysclient = -1; - announce_port = -1; - snd_seq_delete_kernel_client(oldsysclient); - } -} diff --git a/ANDROID_3.4.5/sound/core/seq/seq_system.h b/ANDROID_3.4.5/sound/core/seq/seq_system.h deleted file mode 100644 index cf2cfa23..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_system.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ALSA sequencer System Client - * Copyright (c) 1998 by Frank van de Pol - * - * - * 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 - * - */ -#ifndef __SND_SEQ_SYSTEM_H -#define __SND_SEQ_SYSTEM_H - -#include - - -/* entry points for broadcasting system events */ -void snd_seq_system_broadcast(int client, int port, int type); - -#define snd_seq_system_client_ev_client_start(client) snd_seq_system_broadcast(client, 0, SNDRV_SEQ_EVENT_CLIENT_START) -#define snd_seq_system_client_ev_client_exit(client) snd_seq_system_broadcast(client, 0, SNDRV_SEQ_EVENT_CLIENT_EXIT) -#define snd_seq_system_client_ev_client_change(client) snd_seq_system_broadcast(client, 0, SNDRV_SEQ_EVENT_CLIENT_CHANGE) -#define snd_seq_system_client_ev_port_start(client, port) snd_seq_system_broadcast(client, port, SNDRV_SEQ_EVENT_PORT_START) -#define snd_seq_system_client_ev_port_exit(client, port) snd_seq_system_broadcast(client, port, SNDRV_SEQ_EVENT_PORT_EXIT) -#define snd_seq_system_client_ev_port_change(client, port) snd_seq_system_broadcast(client, port, SNDRV_SEQ_EVENT_PORT_CHANGE) - -int snd_seq_system_notify(int client, int port, struct snd_seq_event *ev); - -/* register our internal client */ -int snd_seq_system_client_init(void); - -/* unregister our internal client */ -void snd_seq_system_client_done(void); - - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_timer.c b/ANDROID_3.4.5/sound/core/seq/seq_timer.c deleted file mode 100644 index 160b1bd0..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_timer.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * ALSA sequencer Timer - * Copyright (c) 1998-1999 by Frank van de Pol - * Jaroslav Kysela - * - * - * 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 "seq_timer.h" -#include "seq_queue.h" -#include "seq_info.h" - -/* allowed sequencer timer frequencies, in Hz */ -#define MIN_FREQUENCY 10 -#define MAX_FREQUENCY 6250 -#define DEFAULT_FREQUENCY 1000 - -#define SKEW_BASE 0x10000 /* 16bit shift */ - -static void snd_seq_timer_set_tick_resolution(struct snd_seq_timer *tmr) -{ - if (tmr->tempo < 1000000) - tmr->tick.resolution = (tmr->tempo * 1000) / tmr->ppq; - else { - /* might overflow.. */ - unsigned int s; - s = tmr->tempo % tmr->ppq; - s = (s * 1000) / tmr->ppq; - tmr->tick.resolution = (tmr->tempo / tmr->ppq) * 1000; - tmr->tick.resolution += s; - } - if (tmr->tick.resolution <= 0) - tmr->tick.resolution = 1; - snd_seq_timer_update_tick(&tmr->tick, 0); -} - -/* create new timer (constructor) */ -struct snd_seq_timer *snd_seq_timer_new(void) -{ - struct snd_seq_timer *tmr; - - tmr = kzalloc(sizeof(*tmr), GFP_KERNEL); - if (tmr == NULL) { - snd_printd("malloc failed for snd_seq_timer_new() \n"); - return NULL; - } - spin_lock_init(&tmr->lock); - - /* reset setup to defaults */ - snd_seq_timer_defaults(tmr); - - /* reset time */ - snd_seq_timer_reset(tmr); - - return tmr; -} - -/* delete timer (destructor) */ -void snd_seq_timer_delete(struct snd_seq_timer **tmr) -{ - struct snd_seq_timer *t = *tmr; - *tmr = NULL; - - if (t == NULL) { - snd_printd("oops: snd_seq_timer_delete() called with NULL timer\n"); - return; - } - t->running = 0; - - /* reset time */ - snd_seq_timer_stop(t); - snd_seq_timer_reset(t); - - kfree(t); -} - -void snd_seq_timer_defaults(struct snd_seq_timer * tmr) -{ - /* setup defaults */ - tmr->ppq = 96; /* 96 PPQ */ - tmr->tempo = 500000; /* 120 BPM */ - snd_seq_timer_set_tick_resolution(tmr); - tmr->running = 0; - - tmr->type = SNDRV_SEQ_TIMER_ALSA; - tmr->alsa_id.dev_class = seq_default_timer_class; - tmr->alsa_id.dev_sclass = seq_default_timer_sclass; - tmr->alsa_id.card = seq_default_timer_card; - tmr->alsa_id.device = seq_default_timer_device; - tmr->alsa_id.subdevice = seq_default_timer_subdevice; - tmr->preferred_resolution = seq_default_timer_resolution; - - tmr->skew = tmr->skew_base = SKEW_BASE; -} - -void snd_seq_timer_reset(struct snd_seq_timer * tmr) -{ - unsigned long flags; - - spin_lock_irqsave(&tmr->lock, flags); - - /* reset time & songposition */ - tmr->cur_time.tv_sec = 0; - tmr->cur_time.tv_nsec = 0; - - tmr->tick.cur_tick = 0; - tmr->tick.fraction = 0; - - spin_unlock_irqrestore(&tmr->lock, flags); -} - - -/* called by timer interrupt routine. the period time since previous invocation is passed */ -static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri, - unsigned long resolution, - unsigned long ticks) -{ - unsigned long flags; - struct snd_seq_queue *q = timeri->callback_data; - struct snd_seq_timer *tmr; - - if (q == NULL) - return; - tmr = q->timer; - if (tmr == NULL) - return; - if (!tmr->running) - return; - - resolution *= ticks; - if (tmr->skew != tmr->skew_base) { - /* FIXME: assuming skew_base = 0x10000 */ - resolution = (resolution >> 16) * tmr->skew + - (((resolution & 0xffff) * tmr->skew) >> 16); - } - - spin_lock_irqsave(&tmr->lock, flags); - - /* update timer */ - snd_seq_inc_time_nsec(&tmr->cur_time, resolution); - - /* calculate current tick */ - snd_seq_timer_update_tick(&tmr->tick, resolution); - - /* register actual time of this timer update */ - do_gettimeofday(&tmr->last_update); - - spin_unlock_irqrestore(&tmr->lock, flags); - - /* check queues and dispatch events */ - snd_seq_check_queue(q, 1, 0); -} - -/* set current tempo */ -int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo) -{ - unsigned long flags; - - if (snd_BUG_ON(!tmr)) - return -EINVAL; - if (tempo <= 0) - return -EINVAL; - spin_lock_irqsave(&tmr->lock, flags); - if ((unsigned int)tempo != tmr->tempo) { - tmr->tempo = tempo; - snd_seq_timer_set_tick_resolution(tmr); - } - spin_unlock_irqrestore(&tmr->lock, flags); - return 0; -} - -/* set current ppq */ -int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq) -{ - unsigned long flags; - - if (snd_BUG_ON(!tmr)) - return -EINVAL; - if (ppq <= 0) - return -EINVAL; - spin_lock_irqsave(&tmr->lock, flags); - if (tmr->running && (ppq != tmr->ppq)) { - /* refuse to change ppq on running timers */ - /* because it will upset the song position (ticks) */ - spin_unlock_irqrestore(&tmr->lock, flags); - snd_printd("seq: cannot change ppq of a running timer\n"); - return -EBUSY; - } - - tmr->ppq = ppq; - snd_seq_timer_set_tick_resolution(tmr); - spin_unlock_irqrestore(&tmr->lock, flags); - return 0; -} - -/* set current tick position */ -int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, - snd_seq_tick_time_t position) -{ - unsigned long flags; - - if (snd_BUG_ON(!tmr)) - return -EINVAL; - - spin_lock_irqsave(&tmr->lock, flags); - tmr->tick.cur_tick = position; - tmr->tick.fraction = 0; - spin_unlock_irqrestore(&tmr->lock, flags); - return 0; -} - -/* set current real-time position */ -int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, - snd_seq_real_time_t position) -{ - unsigned long flags; - - if (snd_BUG_ON(!tmr)) - return -EINVAL; - - snd_seq_sanity_real_time(&position); - spin_lock_irqsave(&tmr->lock, flags); - tmr->cur_time = position; - spin_unlock_irqrestore(&tmr->lock, flags); - return 0; -} - -/* set timer skew */ -int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, - unsigned int base) -{ - unsigned long flags; - - if (snd_BUG_ON(!tmr)) - return -EINVAL; - - /* FIXME */ - if (base != SKEW_BASE) { - snd_printd("invalid skew base 0x%x\n", base); - return -EINVAL; - } - spin_lock_irqsave(&tmr->lock, flags); - tmr->skew = skew; - spin_unlock_irqrestore(&tmr->lock, flags); - return 0; -} - -int snd_seq_timer_open(struct snd_seq_queue *q) -{ - struct snd_timer_instance *t; - struct snd_seq_timer *tmr; - char str[32]; - int err; - - tmr = q->timer; - if (snd_BUG_ON(!tmr)) - return -EINVAL; - if (tmr->timeri) - return -EBUSY; - sprintf(str, "sequencer queue %i", q->queue); - if (tmr->type != SNDRV_SEQ_TIMER_ALSA) /* standard ALSA timer */ - return -EINVAL; - if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE) - tmr->alsa_id.dev_sclass = SNDRV_TIMER_SCLASS_SEQUENCER; - err = snd_timer_open(&t, str, &tmr->alsa_id, q->queue); - if (err < 0 && tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE) { - if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_GLOBAL || - tmr->alsa_id.device != SNDRV_TIMER_GLOBAL_SYSTEM) { - struct snd_timer_id tid; - memset(&tid, 0, sizeof(tid)); - tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; - tid.dev_sclass = SNDRV_TIMER_SCLASS_SEQUENCER; - tid.card = -1; - tid.device = SNDRV_TIMER_GLOBAL_SYSTEM; - err = snd_timer_open(&t, str, &tid, q->queue); - } - if (err < 0) { - snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err); - return err; - } - } - t->callback = snd_seq_timer_interrupt; - t->callback_data = q; - t->flags |= SNDRV_TIMER_IFLG_AUTO; - tmr->timeri = t; - return 0; -} - -int snd_seq_timer_close(struct snd_seq_queue *q) -{ - struct snd_seq_timer *tmr; - - tmr = q->timer; - if (snd_BUG_ON(!tmr)) - return -EINVAL; - if (tmr->timeri) { - snd_timer_stop(tmr->timeri); - snd_timer_close(tmr->timeri); - tmr->timeri = NULL; - } - return 0; -} - -int snd_seq_timer_stop(struct snd_seq_timer * tmr) -{ - if (! tmr->timeri) - return -EINVAL; - if (!tmr->running) - return 0; - tmr->running = 0; - snd_timer_pause(tmr->timeri); - return 0; -} - -static int initialize_timer(struct snd_seq_timer *tmr) -{ - struct snd_timer *t; - unsigned long freq; - - t = tmr->timeri->timer; - if (snd_BUG_ON(!t)) - return -EINVAL; - - freq = tmr->preferred_resolution; - if (!freq) - freq = DEFAULT_FREQUENCY; - else if (freq < MIN_FREQUENCY) - freq = MIN_FREQUENCY; - else if (freq > MAX_FREQUENCY) - freq = MAX_FREQUENCY; - - tmr->ticks = 1; - if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { - unsigned long r = t->hw.resolution; - if (! r && t->hw.c_resolution) - r = t->hw.c_resolution(t); - if (r) { - tmr->ticks = (unsigned int)(1000000000uL / (r * freq)); - if (! tmr->ticks) - tmr->ticks = 1; - } - } - tmr->initialized = 1; - return 0; -} - -int snd_seq_timer_start(struct snd_seq_timer * tmr) -{ - if (! tmr->timeri) - return -EINVAL; - if (tmr->running) - snd_seq_timer_stop(tmr); - snd_seq_timer_reset(tmr); - if (initialize_timer(tmr) < 0) - return -EINVAL; - snd_timer_start(tmr->timeri, tmr->ticks); - tmr->running = 1; - do_gettimeofday(&tmr->last_update); - return 0; -} - -int snd_seq_timer_continue(struct snd_seq_timer * tmr) -{ - if (! tmr->timeri) - return -EINVAL; - if (tmr->running) - return -EBUSY; - if (! tmr->initialized) { - snd_seq_timer_reset(tmr); - if (initialize_timer(tmr) < 0) - return -EINVAL; - } - snd_timer_start(tmr->timeri, tmr->ticks); - tmr->running = 1; - do_gettimeofday(&tmr->last_update); - return 0; -} - -/* return current 'real' time. use timeofday() to get better granularity. */ -snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) -{ - snd_seq_real_time_t cur_time; - - cur_time = tmr->cur_time; - if (tmr->running) { - struct timeval tm; - int usec; - do_gettimeofday(&tm); - usec = (int)(tm.tv_usec - tmr->last_update.tv_usec); - if (usec < 0) { - cur_time.tv_nsec += (1000000 + usec) * 1000; - cur_time.tv_sec += tm.tv_sec - tmr->last_update.tv_sec - 1; - } else { - cur_time.tv_nsec += usec * 1000; - cur_time.tv_sec += tm.tv_sec - tmr->last_update.tv_sec; - } - snd_seq_sanity_real_time(&cur_time); - } - - return cur_time; -} - -/* TODO: use interpolation on tick queue (will only be useful for very - high PPQ values) */ -snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr) -{ - return tmr->tick.cur_tick; -} - - -#ifdef CONFIG_PROC_FS -/* exported to seq_info.c */ -void snd_seq_info_timer_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - int idx; - struct snd_seq_queue *q; - struct snd_seq_timer *tmr; - struct snd_timer_instance *ti; - unsigned long resolution; - - for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) { - q = queueptr(idx); - if (q == NULL) - continue; - if ((tmr = q->timer) == NULL || - (ti = tmr->timeri) == NULL) { - queuefree(q); - continue; - } - snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name); - resolution = snd_timer_resolution(ti) * tmr->ticks; - snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000); - snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base); - queuefree(q); - } -} -#endif /* CONFIG_PROC_FS */ - diff --git a/ANDROID_3.4.5/sound/core/seq/seq_timer.h b/ANDROID_3.4.5/sound/core/seq/seq_timer.h deleted file mode 100644 index 88dfb718..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_timer.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * ALSA sequencer Timer - * Copyright (c) 1998-1999 by Frank van de Pol - * - * - * 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 - * - */ -#ifndef __SND_SEQ_TIMER_H -#define __SND_SEQ_TIMER_H - -#include -#include - -struct snd_seq_timer_tick { - snd_seq_tick_time_t cur_tick; /* current tick */ - unsigned long resolution; /* time per tick in nsec */ - unsigned long fraction; /* current time per tick in nsec */ -}; - -struct snd_seq_timer { - /* ... tempo / offset / running state */ - - unsigned int running:1, /* running state of queue */ - initialized:1; /* timer is initialized */ - - unsigned int tempo; /* current tempo, us/tick */ - int ppq; /* time resolution, ticks/quarter */ - - snd_seq_real_time_t cur_time; /* current time */ - struct snd_seq_timer_tick tick; /* current tick */ - int tick_updated; - - int type; /* timer type */ - struct snd_timer_id alsa_id; /* ALSA's timer ID */ - struct snd_timer_instance *timeri; /* timer instance */ - unsigned int ticks; - unsigned long preferred_resolution; /* timer resolution, ticks/sec */ - - unsigned int skew; - unsigned int skew_base; - - struct timeval last_update; /* time of last clock update, used for interpolation */ - - spinlock_t lock; -}; - - -/* create new timer (constructor) */ -struct snd_seq_timer *snd_seq_timer_new(void); - -/* delete timer (destructor) */ -void snd_seq_timer_delete(struct snd_seq_timer **tmr); - -/* */ -static inline void snd_seq_timer_update_tick(struct snd_seq_timer_tick *tick, - unsigned long resolution) -{ - if (tick->resolution > 0) { - tick->fraction += resolution; - tick->cur_tick += (unsigned int)(tick->fraction / tick->resolution); - tick->fraction %= tick->resolution; - } -} - - -/* compare timestamp between events */ -/* return 1 if a >= b; otherwise return 0 */ -static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, snd_seq_tick_time_t *b) -{ - /* compare ticks */ - return (*a >= *b); -} - -static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, snd_seq_real_time_t *b) -{ - /* compare real time */ - if (a->tv_sec > b->tv_sec) - return 1; - if ((a->tv_sec == b->tv_sec) && (a->tv_nsec >= b->tv_nsec)) - return 1; - return 0; -} - - -static inline void snd_seq_sanity_real_time(snd_seq_real_time_t *tm) -{ - while (tm->tv_nsec >= 1000000000) { - /* roll-over */ - tm->tv_nsec -= 1000000000; - tm->tv_sec++; - } -} - - -/* increment timestamp */ -static inline void snd_seq_inc_real_time(snd_seq_real_time_t *tm, snd_seq_real_time_t *inc) -{ - tm->tv_sec += inc->tv_sec; - tm->tv_nsec += inc->tv_nsec; - snd_seq_sanity_real_time(tm); -} - -static inline void snd_seq_inc_time_nsec(snd_seq_real_time_t *tm, unsigned long nsec) -{ - tm->tv_nsec += nsec; - snd_seq_sanity_real_time(tm); -} - -/* called by timer isr */ -struct snd_seq_queue; -int snd_seq_timer_open(struct snd_seq_queue *q); -int snd_seq_timer_close(struct snd_seq_queue *q); -int snd_seq_timer_midi_open(struct snd_seq_queue *q); -int snd_seq_timer_midi_close(struct snd_seq_queue *q); -void snd_seq_timer_defaults(struct snd_seq_timer *tmr); -void snd_seq_timer_reset(struct snd_seq_timer *tmr); -int snd_seq_timer_stop(struct snd_seq_timer *tmr); -int snd_seq_timer_start(struct snd_seq_timer *tmr); -int snd_seq_timer_continue(struct snd_seq_timer *tmr); -int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo); -int snd_seq_timer_set_ppq(struct snd_seq_timer *tmr, int ppq); -int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position); -int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position); -int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base); -snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr); -snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr); - -extern int seq_default_timer_class; -extern int seq_default_timer_sclass; -extern int seq_default_timer_card; -extern int seq_default_timer_device; -extern int seq_default_timer_subdevice; -extern int seq_default_timer_resolution; - -#endif diff --git a/ANDROID_3.4.5/sound/core/seq/seq_virmidi.c b/ANDROID_3.4.5/sound/core/seq/seq_virmidi.c deleted file mode 100644 index 4b50e604..00000000 --- a/ANDROID_3.4.5/sound/core/seq/seq_virmidi.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Virtual Raw MIDI client on Sequencer - * - * Copyright (c) 2000 by Takashi Iwai , - * Jaroslav Kysela - * - * 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 - * - */ - -/* - * Virtual Raw MIDI client - * - * The virtual rawmidi client is a sequencer client which associate - * a rawmidi device file. The created rawmidi device file can be - * accessed as a normal raw midi, but its MIDI source and destination - * are arbitrary. For example, a user-client software synth connected - * to this port can be used as a normal midi device as well. - * - * The virtual rawmidi device accepts also multiple opens. Each file - * has its own input buffer, so that no conflict would occur. The drain - * of input/output buffer acts only to the local buffer. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("Virtual Raw MIDI client on Sequencer"); -MODULE_LICENSE("GPL"); - -/* - * initialize an event record - */ -static void snd_virmidi_init_event(struct snd_virmidi *vmidi, - struct snd_seq_event *ev) -{ - memset(ev, 0, sizeof(*ev)); - ev->source.port = vmidi->port; - switch (vmidi->seq_mode) { - case SNDRV_VIRMIDI_SEQ_DISPATCH: - ev->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; - break; - case SNDRV_VIRMIDI_SEQ_ATTACH: - /* FIXME: source and destination are same - not good.. */ - ev->dest.client = vmidi->client; - ev->dest.port = vmidi->port; - break; - } - ev->type = SNDRV_SEQ_EVENT_NONE; -} - -/* - * decode input event and put to read buffer of each opened file - */ -static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, - struct snd_seq_event *ev) -{ - struct snd_virmidi *vmidi; - unsigned char msg[4]; - int len; - - read_lock(&rdev->filelist_lock); - list_for_each_entry(vmidi, &rdev->filelist, list) { - if (!vmidi->trigger) - continue; - if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { - if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) - continue; - snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream); - } else { - len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev); - if (len > 0) - snd_rawmidi_receive(vmidi->substream, msg, len); - } - } - read_unlock(&rdev->filelist_lock); - - return 0; -} - -/* - * receive an event from the remote virmidi port - * - * for rawmidi inputs, you can call this function from the event - * handler of a remote port which is attached to the virmidi via - * SNDRV_VIRMIDI_SEQ_ATTACH. - */ -#if 0 -int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev) -{ - struct snd_virmidi_dev *rdev; - - rdev = rmidi->private_data; - return snd_virmidi_dev_receive_event(rdev, ev); -} -#endif /* 0 */ - -/* - * event handler of virmidi port - */ -static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct, - void *private_data, int atomic, int hop) -{ - struct snd_virmidi_dev *rdev; - - rdev = private_data; - if (!(rdev->flags & SNDRV_VIRMIDI_USE)) - return 0; /* ignored */ - return snd_virmidi_dev_receive_event(rdev, ev); -} - -/* - * trigger rawmidi stream for input - */ -static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_virmidi *vmidi = substream->runtime->private_data; - - if (up) { - vmidi->trigger = 1; - } else { - vmidi->trigger = 0; - } -} - -/* - * trigger rawmidi stream for output - */ -static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_virmidi *vmidi = substream->runtime->private_data; - int count, res; - unsigned char buf[32], *pbuf; - - if (up) { - vmidi->trigger = 1; - if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH && - !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) { - snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - substream->runtime->avail); - return; /* ignored */ - } - if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { - if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0) - return; - vmidi->event.type = SNDRV_SEQ_EVENT_NONE; - } - while (1) { - count = snd_rawmidi_transmit_peek(substream, buf, sizeof(buf)); - if (count <= 0) - break; - pbuf = buf; - while (count > 0) { - res = snd_midi_event_encode(vmidi->parser, pbuf, count, &vmidi->event); - if (res < 0) { - snd_midi_event_reset_encode(vmidi->parser); - continue; - } - snd_rawmidi_transmit_ack(substream, res); - pbuf += res; - count -= res; - if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { - if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0) - return; - vmidi->event.type = SNDRV_SEQ_EVENT_NONE; - } - } - } - } else { - vmidi->trigger = 0; - } -} - -/* - * open rawmidi handle for input - */ -static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_virmidi_dev *rdev = substream->rmidi->private_data; - struct snd_rawmidi_runtime *runtime = substream->runtime; - struct snd_virmidi *vmidi; - unsigned long flags; - - vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL); - if (vmidi == NULL) - return -ENOMEM; - vmidi->substream = substream; - if (snd_midi_event_new(0, &vmidi->parser) < 0) { - kfree(vmidi); - return -ENOMEM; - } - vmidi->seq_mode = rdev->seq_mode; - vmidi->client = rdev->client; - vmidi->port = rdev->port; - runtime->private_data = vmidi; - write_lock_irqsave(&rdev->filelist_lock, flags); - list_add_tail(&vmidi->list, &rdev->filelist); - write_unlock_irqrestore(&rdev->filelist_lock, flags); - vmidi->rdev = rdev; - return 0; -} - -/* - * open rawmidi handle for output - */ -static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream) -{ - struct snd_virmidi_dev *rdev = substream->rmidi->private_data; - struct snd_rawmidi_runtime *runtime = substream->runtime; - struct snd_virmidi *vmidi; - - vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL); - if (vmidi == NULL) - return -ENOMEM; - vmidi->substream = substream; - if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &vmidi->parser) < 0) { - kfree(vmidi); - return -ENOMEM; - } - vmidi->seq_mode = rdev->seq_mode; - vmidi->client = rdev->client; - vmidi->port = rdev->port; - snd_virmidi_init_event(vmidi, &vmidi->event); - vmidi->rdev = rdev; - runtime->private_data = vmidi; - return 0; -} - -/* - * close rawmidi handle for input - */ -static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_virmidi *vmidi = substream->runtime->private_data; - snd_midi_event_free(vmidi->parser); - list_del(&vmidi->list); - substream->runtime->private_data = NULL; - kfree(vmidi); - return 0; -} - -/* - * close rawmidi handle for output - */ -static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_virmidi *vmidi = substream->runtime->private_data; - snd_midi_event_free(vmidi->parser); - substream->runtime->private_data = NULL; - kfree(vmidi); - return 0; -} - -/* - * subscribe callback - allow output to rawmidi device - */ -static int snd_virmidi_subscribe(void *private_data, - struct snd_seq_port_subscribe *info) -{ - struct snd_virmidi_dev *rdev; - - rdev = private_data; - if (!try_module_get(rdev->card->module)) - return -EFAULT; - rdev->flags |= SNDRV_VIRMIDI_SUBSCRIBE; - return 0; -} - -/* - * unsubscribe callback - disallow output to rawmidi device - */ -static int snd_virmidi_unsubscribe(void *private_data, - struct snd_seq_port_subscribe *info) -{ - struct snd_virmidi_dev *rdev; - - rdev = private_data; - rdev->flags &= ~SNDRV_VIRMIDI_SUBSCRIBE; - module_put(rdev->card->module); - return 0; -} - - -/* - * use callback - allow input to rawmidi device - */ -static int snd_virmidi_use(void *private_data, - struct snd_seq_port_subscribe *info) -{ - struct snd_virmidi_dev *rdev; - - rdev = private_data; - if (!try_module_get(rdev->card->module)) - return -EFAULT; - rdev->flags |= SNDRV_VIRMIDI_USE; - return 0; -} - -/* - * unuse callback - disallow input to rawmidi device - */ -static int snd_virmidi_unuse(void *private_data, - struct snd_seq_port_subscribe *info) -{ - struct snd_virmidi_dev *rdev; - - rdev = private_data; - rdev->flags &= ~SNDRV_VIRMIDI_USE; - module_put(rdev->card->module); - return 0; -} - - -/* - * Register functions - */ - -static struct snd_rawmidi_ops snd_virmidi_input_ops = { - .open = snd_virmidi_input_open, - .close = snd_virmidi_input_close, - .trigger = snd_virmidi_input_trigger, -}; - -static struct snd_rawmidi_ops snd_virmidi_output_ops = { - .open = snd_virmidi_output_open, - .close = snd_virmidi_output_close, - .trigger = snd_virmidi_output_trigger, -}; - -/* - * create a sequencer client and a port - */ -static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev) -{ - int client; - struct snd_seq_port_callback pcallbacks; - struct snd_seq_port_info *pinfo; - int err; - - if (rdev->client >= 0) - return 0; - - pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL); - if (!pinfo) { - err = -ENOMEM; - goto __error; - } - - client = snd_seq_create_kernel_client(rdev->card, rdev->device, - "%s %d-%d", rdev->rmidi->name, - rdev->card->number, - rdev->device); - if (client < 0) { - err = client; - goto __error; - } - rdev->client = client; - - /* create a port */ - pinfo->addr.client = client; - sprintf(pinfo->name, "VirMIDI %d-%d", rdev->card->number, rdev->device); - /* set all capabilities */ - pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; - pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; - pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; - pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC - | SNDRV_SEQ_PORT_TYPE_SOFTWARE - | SNDRV_SEQ_PORT_TYPE_PORT; - pinfo->midi_channels = 16; - memset(&pcallbacks, 0, sizeof(pcallbacks)); - pcallbacks.owner = THIS_MODULE; - pcallbacks.private_data = rdev; - pcallbacks.subscribe = snd_virmidi_subscribe; - pcallbacks.unsubscribe = snd_virmidi_unsubscribe; - pcallbacks.use = snd_virmidi_use; - pcallbacks.unuse = snd_virmidi_unuse; - pcallbacks.event_input = snd_virmidi_event_input; - pinfo->kernel = &pcallbacks; - err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo); - if (err < 0) { - snd_seq_delete_kernel_client(client); - rdev->client = -1; - goto __error; - } - - rdev->port = pinfo->addr.port; - err = 0; /* success */ - - __error: - kfree(pinfo); - return err; -} - - -/* - * release the sequencer client - */ -static void snd_virmidi_dev_detach_seq(struct snd_virmidi_dev *rdev) -{ - if (rdev->client >= 0) { - snd_seq_delete_kernel_client(rdev->client); - rdev->client = -1; - } -} - -/* - * register the device - */ -static int snd_virmidi_dev_register(struct snd_rawmidi *rmidi) -{ - struct snd_virmidi_dev *rdev = rmidi->private_data; - int err; - - switch (rdev->seq_mode) { - case SNDRV_VIRMIDI_SEQ_DISPATCH: - err = snd_virmidi_dev_attach_seq(rdev); - if (err < 0) - return err; - break; - case SNDRV_VIRMIDI_SEQ_ATTACH: - if (rdev->client == 0) - return -EINVAL; - /* should check presence of port more strictly.. */ - break; - default: - snd_printk(KERN_ERR "seq_mode is not set: %d\n", rdev->seq_mode); - return -EINVAL; - } - return 0; -} - - -/* - * unregister the device - */ -static int snd_virmidi_dev_unregister(struct snd_rawmidi *rmidi) -{ - struct snd_virmidi_dev *rdev = rmidi->private_data; - - if (rdev->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH) - snd_virmidi_dev_detach_seq(rdev); - return 0; -} - -/* - * - */ -static struct snd_rawmidi_global_ops snd_virmidi_global_ops = { - .dev_register = snd_virmidi_dev_register, - .dev_unregister = snd_virmidi_dev_unregister, -}; - -/* - * free device - */ -static void snd_virmidi_free(struct snd_rawmidi *rmidi) -{ - struct snd_virmidi_dev *rdev = rmidi->private_data; - kfree(rdev); -} - -/* - * create a new device - * - */ -/* exported */ -int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmidi) -{ - struct snd_rawmidi *rmidi; - struct snd_virmidi_dev *rdev; - int err; - - *rrmidi = NULL; - if ((err = snd_rawmidi_new(card, "VirMidi", device, - 16, /* may be configurable */ - 16, /* may be configurable */ - &rmidi)) < 0) - return err; - strcpy(rmidi->name, rmidi->id); - rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); - if (rdev == NULL) { - snd_device_free(card, rmidi); - return -ENOMEM; - } - rdev->card = card; - rdev->rmidi = rmidi; - rdev->device = device; - rdev->client = -1; - rwlock_init(&rdev->filelist_lock); - INIT_LIST_HEAD(&rdev->filelist); - rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH; - rmidi->private_data = rdev; - rmidi->private_free = snd_virmidi_free; - rmidi->ops = &snd_virmidi_global_ops; - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_virmidi_input_ops); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_virmidi_output_ops); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - *rrmidi = rmidi; - return 0; -} - -/* - * ENTRY functions - */ - -static int __init alsa_virmidi_init(void) -{ - return 0; -} - -static void __exit alsa_virmidi_exit(void) -{ -} - -module_init(alsa_virmidi_init) -module_exit(alsa_virmidi_exit) - -EXPORT_SYMBOL(snd_virmidi_new); diff --git a/ANDROID_3.4.5/sound/core/sgbuf.c b/ANDROID_3.4.5/sound/core/sgbuf.c deleted file mode 100644 index 4e7ec2b4..00000000 --- a/ANDROID_3.4.5/sound/core/sgbuf.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Scatter-Gather buffer - * - * Copyright (c) by Takashi Iwai - * - * 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 - - -/* table entries are align to 32 */ -#define SGBUF_TBL_ALIGN 32 -#define sgbuf_align_table(tbl) ALIGN((tbl), SGBUF_TBL_ALIGN) - -int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) -{ - struct snd_sg_buf *sgbuf = dmab->private_data; - struct snd_dma_buffer tmpb; - int i; - - if (! sgbuf) - return -EINVAL; - - if (dmab->area) - vunmap(dmab->area); - dmab->area = NULL; - - tmpb.dev.type = SNDRV_DMA_TYPE_DEV; - tmpb.dev.dev = sgbuf->dev; - for (i = 0; i < sgbuf->pages; i++) { - if (!(sgbuf->table[i].addr & ~PAGE_MASK)) - continue; /* continuous pages */ - tmpb.area = sgbuf->table[i].buf; - tmpb.addr = sgbuf->table[i].addr & PAGE_MASK; - tmpb.bytes = (sgbuf->table[i].addr & ~PAGE_MASK) << PAGE_SHIFT; - snd_dma_free_pages(&tmpb); - } - - kfree(sgbuf->table); - kfree(sgbuf->page_table); - kfree(sgbuf); - dmab->private_data = NULL; - - return 0; -} - -#define MAX_ALLOC_PAGES 32 - -void *snd_malloc_sgbuf_pages(struct device *device, - size_t size, struct snd_dma_buffer *dmab, - size_t *res_size) -{ - struct snd_sg_buf *sgbuf; - unsigned int i, pages, chunk, maxpages; - struct snd_dma_buffer tmpb; - struct snd_sg_page *table; - struct page **pgtable; - - dmab->area = NULL; - dmab->addr = 0; - dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL); - if (! sgbuf) - return NULL; - sgbuf->dev = device; - pages = snd_sgbuf_aligned_pages(size); - sgbuf->tblsize = sgbuf_align_table(pages); - table = kcalloc(sgbuf->tblsize, sizeof(*table), GFP_KERNEL); - if (!table) - goto _failed; - sgbuf->table = table; - pgtable = kcalloc(sgbuf->tblsize, sizeof(*pgtable), GFP_KERNEL); - if (!pgtable) - goto _failed; - sgbuf->page_table = pgtable; - - /* allocate pages */ - maxpages = MAX_ALLOC_PAGES; - while (pages > 0) { - chunk = pages; - /* don't be too eager to take a huge chunk */ - if (chunk > maxpages) - chunk = maxpages; - chunk <<= PAGE_SHIFT; - if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device, - chunk, &tmpb) < 0) { - if (!sgbuf->pages) - return NULL; - if (!res_size) - goto _failed; - size = sgbuf->pages * PAGE_SIZE; - break; - } - chunk = tmpb.bytes >> PAGE_SHIFT; - for (i = 0; i < chunk; i++) { - table->buf = tmpb.area; - table->addr = tmpb.addr; - if (!i) - table->addr |= chunk; /* mark head */ - table++; - *pgtable++ = virt_to_page(tmpb.area); - tmpb.area += PAGE_SIZE; - tmpb.addr += PAGE_SIZE; - } - sgbuf->pages += chunk; - pages -= chunk; - if (chunk < maxpages) - maxpages = chunk; - } - - sgbuf->size = size; - dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, PAGE_KERNEL); - if (! dmab->area) - goto _failed; - if (res_size) - *res_size = sgbuf->size; - return dmab->area; - - _failed: - snd_free_sgbuf_pages(dmab); /* free the table */ - return NULL; -} diff --git a/ANDROID_3.4.5/sound/core/sound.c b/ANDROID_3.4.5/sound/core/sound.c deleted file mode 100644 index 3700d96f..00000000 --- a/ANDROID_3.4.5/sound/core/sound.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Advanced Linux Sound Architecture - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#include - -static int major = CONFIG_SND_MAJOR; -int snd_major; -EXPORT_SYMBOL(snd_major); - -static int cards_limit = 1; - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards."); -MODULE_LICENSE("GPL"); -module_param(major, int, 0444); -MODULE_PARM_DESC(major, "Major # for sound driver."); -module_param(cards_limit, int, 0444); -MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards."); -MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); - -/* this one holds the actual max. card number currently available. - * as default, it's identical with cards_limit option. when more - * modules are loaded manually, this limit number increases, too. - */ -int snd_ecards_limit; -EXPORT_SYMBOL(snd_ecards_limit); - -static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; -static DEFINE_MUTEX(sound_mutex); - -#ifdef CONFIG_MODULES - -/** - * snd_request_card - try to load the card module - * @card: the card number - * - * Tries to load the module "snd-card-X" for the given card number - * via request_module. Returns immediately if already loaded. - */ -void snd_request_card(int card) -{ - if (snd_card_locked(card)) - return; - if (card < 0 || card >= cards_limit) - return; - request_module("snd-card-%i", card); -} - -EXPORT_SYMBOL(snd_request_card); - -static void snd_request_other(int minor) -{ - char *str; - - switch (minor) { - case SNDRV_MINOR_SEQUENCER: str = "snd-seq"; break; - case SNDRV_MINOR_TIMER: str = "snd-timer"; break; - default: return; - } - request_module(str); -} - -#endif /* modular kernel */ - -/** - * snd_lookup_minor_data - get user data of a registered device - * @minor: the minor number - * @type: device type (SNDRV_DEVICE_TYPE_XXX) - * - * Checks that a minor device with the specified type is registered, and returns - * its user data pointer. - * - * This function increments the reference counter of the card instance - * if an associated instance with the given minor number and type is found. - * The caller must call snd_card_unref() appropriately later. - */ -void *snd_lookup_minor_data(unsigned int minor, int type) -{ - struct snd_minor *mreg; - void *private_data; - - if (minor >= ARRAY_SIZE(snd_minors)) - return NULL; - mutex_lock(&sound_mutex); - mreg = snd_minors[minor]; - if (mreg && mreg->type == type) { - private_data = mreg->private_data; - if (private_data && mreg->card_ptr) - atomic_inc(&mreg->card_ptr->refcount); - } else - private_data = NULL; - mutex_unlock(&sound_mutex); - return private_data; -} - -EXPORT_SYMBOL(snd_lookup_minor_data); - -#ifdef CONFIG_MODULES -static struct snd_minor *autoload_device(unsigned int minor) -{ - int dev; - mutex_unlock(&sound_mutex); /* release lock temporarily */ - dev = SNDRV_MINOR_DEVICE(minor); - if (dev == SNDRV_MINOR_CONTROL) { - /* /dev/aloadC? */ - int card = SNDRV_MINOR_CARD(minor); - if (snd_cards[card] == NULL) - snd_request_card(card); - } else if (dev == SNDRV_MINOR_GLOBAL) { - /* /dev/aloadSEQ */ - snd_request_other(minor); - } - mutex_lock(&sound_mutex); /* reacuire lock */ - return snd_minors[minor]; -} -#else /* !CONFIG_MODULES */ -#define autoload_device(minor) NULL -#endif /* CONFIG_MODULES */ - -static int snd_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - struct snd_minor *mptr = NULL; - const struct file_operations *old_fops; - int err = 0; - - if (minor >= ARRAY_SIZE(snd_minors)) - return -ENODEV; - mutex_lock(&sound_mutex); - mptr = snd_minors[minor]; - if (mptr == NULL) { - mptr = autoload_device(minor); - if (!mptr) { - mutex_unlock(&sound_mutex); - return -ENODEV; - } - } - old_fops = file->f_op; - file->f_op = fops_get(mptr->f_ops); - if (file->f_op == NULL) { - file->f_op = old_fops; - err = -ENODEV; - } - mutex_unlock(&sound_mutex); - if (err < 0) - return err; - - if (file->f_op->open) { - err = file->f_op->open(inode, file); - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); - } - } - fops_put(old_fops); - return err; -} - -static const struct file_operations snd_fops = -{ - .owner = THIS_MODULE, - .open = snd_open, - .llseek = noop_llseek, -}; - -#ifdef CONFIG_SND_DYNAMIC_MINORS -static int snd_find_free_minor(int type) -{ - int minor; - - /* static minors for module auto loading */ - if (type == SNDRV_DEVICE_TYPE_SEQUENCER) - return SNDRV_MINOR_SEQUENCER; - if (type == SNDRV_DEVICE_TYPE_TIMER) - return SNDRV_MINOR_TIMER; - - for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) { - /* skip static minors still used for module auto loading */ - if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL) - continue; - if (minor == SNDRV_MINOR_SEQUENCER || - minor == SNDRV_MINOR_TIMER) - continue; - if (!snd_minors[minor]) - return minor; - } - return -EBUSY; -} -#else -static int snd_kernel_minor(int type, struct snd_card *card, int dev) -{ - int minor; - - switch (type) { - case SNDRV_DEVICE_TYPE_SEQUENCER: - case SNDRV_DEVICE_TYPE_TIMER: - minor = type; - break; - case SNDRV_DEVICE_TYPE_CONTROL: - if (snd_BUG_ON(!card)) - return -EINVAL; - minor = SNDRV_MINOR(card->number, type); - break; - case SNDRV_DEVICE_TYPE_HWDEP: - case SNDRV_DEVICE_TYPE_RAWMIDI: - case SNDRV_DEVICE_TYPE_PCM_PLAYBACK: - case SNDRV_DEVICE_TYPE_PCM_CAPTURE: - case SNDRV_DEVICE_TYPE_COMPRESS: - if (snd_BUG_ON(!card)) - return -EINVAL; - minor = SNDRV_MINOR(card->number, type + dev); - break; - default: - return -EINVAL; - } - if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OS_MINORS)) - return -EINVAL; - return minor; -} -#endif - -/** - * snd_register_device_for_dev - Register the ALSA device file for the card - * @type: the device type, SNDRV_DEVICE_TYPE_XXX - * @card: the card instance - * @dev: the device index - * @f_ops: the file operations - * @private_data: user pointer for f_ops->open() - * @name: the device file name - * @device: the &struct device to link this new device to - * - * Registers an ALSA device file for the given card. - * The operators have to be set in reg parameter. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_register_device_for_dev(int type, struct snd_card *card, int dev, - const struct file_operations *f_ops, - void *private_data, - const char *name, struct device *device) -{ - int minor; - struct snd_minor *preg; - - if (snd_BUG_ON(!name)) - return -EINVAL; - preg = kmalloc(sizeof *preg, GFP_KERNEL); - if (preg == NULL) - return -ENOMEM; - preg->type = type; - preg->card = card ? card->number : -1; - preg->device = dev; - preg->f_ops = f_ops; - preg->private_data = private_data; - preg->card_ptr = card; - mutex_lock(&sound_mutex); -#ifdef CONFIG_SND_DYNAMIC_MINORS - minor = snd_find_free_minor(type); -#else - minor = snd_kernel_minor(type, card, dev); - if (minor >= 0 && snd_minors[minor]) - minor = -EBUSY; -#endif - if (minor < 0) { - mutex_unlock(&sound_mutex); - kfree(preg); - return minor; - } - snd_minors[minor] = preg; - preg->dev = device_create(sound_class, device, MKDEV(major, minor), - private_data, "%s", name); - if (IS_ERR(preg->dev)) { - snd_minors[minor] = NULL; - mutex_unlock(&sound_mutex); - minor = PTR_ERR(preg->dev); - kfree(preg); - return minor; - } - - mutex_unlock(&sound_mutex); - return 0; -} - -EXPORT_SYMBOL(snd_register_device_for_dev); - -/* find the matching minor record - * return the index of snd_minor, or -1 if not found - */ -static int find_snd_minor(int type, struct snd_card *card, int dev) -{ - int cardnum, minor; - struct snd_minor *mptr; - - cardnum = card ? card->number : -1; - for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) - if ((mptr = snd_minors[minor]) != NULL && - mptr->type == type && - mptr->card == cardnum && - mptr->device == dev) - return minor; - return -1; -} - -/** - * snd_unregister_device - unregister the device on the given card - * @type: the device type, SNDRV_DEVICE_TYPE_XXX - * @card: the card instance - * @dev: the device index - * - * Unregisters the device file already registered via - * snd_register_device(). - * - * Returns zero if sucecessful, or a negative error code on failure - */ -int snd_unregister_device(int type, struct snd_card *card, int dev) -{ - int minor; - - mutex_lock(&sound_mutex); - minor = find_snd_minor(type, card, dev); - if (minor < 0) { - mutex_unlock(&sound_mutex); - return -EINVAL; - } - - device_destroy(sound_class, MKDEV(major, minor)); - - kfree(snd_minors[minor]); - snd_minors[minor] = NULL; - mutex_unlock(&sound_mutex); - return 0; -} - -EXPORT_SYMBOL(snd_unregister_device); - -int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, - struct device_attribute *attr) -{ - int minor, ret = -EINVAL; - struct device *d; - - mutex_lock(&sound_mutex); - minor = find_snd_minor(type, card, dev); - if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL) - ret = device_create_file(d, attr); - mutex_unlock(&sound_mutex); - return ret; - -} - -EXPORT_SYMBOL(snd_add_device_sysfs_file); - -#ifdef CONFIG_PROC_FS -/* - * INFO PART - */ - -static struct snd_info_entry *snd_minor_info_entry; - -static const char *snd_device_type_name(int type) -{ - switch (type) { - case SNDRV_DEVICE_TYPE_CONTROL: - return "control"; - case SNDRV_DEVICE_TYPE_HWDEP: - return "hardware dependent"; - case SNDRV_DEVICE_TYPE_RAWMIDI: - return "raw midi"; - case SNDRV_DEVICE_TYPE_PCM_PLAYBACK: - return "digital audio playback"; - case SNDRV_DEVICE_TYPE_PCM_CAPTURE: - return "digital audio capture"; - case SNDRV_DEVICE_TYPE_SEQUENCER: - return "sequencer"; - case SNDRV_DEVICE_TYPE_TIMER: - return "timer"; - default: - return "?"; - } -} - -static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - int minor; - struct snd_minor *mptr; - - mutex_lock(&sound_mutex); - for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) { - if (!(mptr = snd_minors[minor])) - continue; - if (mptr->card >= 0) { - if (mptr->device >= 0) - snd_iprintf(buffer, "%3i: [%2i-%2i]: %s\n", - minor, mptr->card, mptr->device, - snd_device_type_name(mptr->type)); - else - snd_iprintf(buffer, "%3i: [%2i] : %s\n", - minor, mptr->card, - snd_device_type_name(mptr->type)); - } else - snd_iprintf(buffer, "%3i: : %s\n", minor, - snd_device_type_name(mptr->type)); - } - mutex_unlock(&sound_mutex); -} - -int __init snd_minor_info_init(void) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); - if (entry) { - entry->c.text.read = snd_minor_info_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_minor_info_entry = entry; - return 0; -} - -int __exit snd_minor_info_done(void) -{ - snd_info_free_entry(snd_minor_info_entry); - return 0; -} -#endif /* CONFIG_PROC_FS */ - -/* - * INIT PART - */ - -static int __init alsa_sound_init(void) -{ - snd_major = major; - snd_ecards_limit = cards_limit; - if (register_chrdev(major, "alsa", &snd_fops)) { - snd_printk(KERN_ERR "unable to register native major device number %d\n", major); - return -EIO; - } - if (snd_info_init() < 0) { - unregister_chrdev(major, "alsa"); - return -ENOMEM; - } - snd_info_minor_register(); -#ifndef MODULE - printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); -#endif - return 0; -} - -static void __exit alsa_sound_exit(void) -{ - snd_info_minor_unregister(); - snd_info_done(); - unregister_chrdev(major, "alsa"); -} - -subsys_initcall(alsa_sound_init); -module_exit(alsa_sound_exit); diff --git a/ANDROID_3.4.5/sound/core/sound_oss.c b/ANDROID_3.4.5/sound/core/sound_oss.c deleted file mode 100644 index ec860091..00000000 --- a/ANDROID_3.4.5/sound/core/sound_oss.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Advanced Linux Sound Architecture - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -#ifdef CONFIG_SND_OSSEMUL - -#if !defined(CONFIG_SOUND) && !(defined(MODULE) && defined(CONFIG_SOUND_MODULE)) -#error "Enable the OSS soundcore multiplexer (CONFIG_SOUND) in the kernel." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SNDRV_OSS_MINORS 128 - -static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; -static DEFINE_MUTEX(sound_oss_mutex); - -/* NOTE: This function increments the refcount of the associated card like - * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately - */ -void *snd_lookup_oss_minor_data(unsigned int minor, int type) -{ - struct snd_minor *mreg; - void *private_data; - - if (minor >= ARRAY_SIZE(snd_oss_minors)) - return NULL; - mutex_lock(&sound_oss_mutex); - mreg = snd_oss_minors[minor]; - if (mreg && mreg->type == type) { - private_data = mreg->private_data; - if (private_data && mreg->card_ptr) - atomic_inc(&mreg->card_ptr->refcount); - } else - private_data = NULL; - mutex_unlock(&sound_oss_mutex); - return private_data; -} - -EXPORT_SYMBOL(snd_lookup_oss_minor_data); - -static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) -{ - int minor; - - switch (type) { - case SNDRV_OSS_DEVICE_TYPE_MIXER: - if (snd_BUG_ON(!card || dev < 0 || dev > 1)) - return -EINVAL; - minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIXER1 : SNDRV_MINOR_OSS_MIXER)); - break; - case SNDRV_OSS_DEVICE_TYPE_SEQUENCER: - minor = SNDRV_MINOR_OSS_SEQUENCER; - break; - case SNDRV_OSS_DEVICE_TYPE_MUSIC: - minor = SNDRV_MINOR_OSS_MUSIC; - break; - case SNDRV_OSS_DEVICE_TYPE_PCM: - if (snd_BUG_ON(!card || dev < 0 || dev > 1)) - return -EINVAL; - minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_PCM1 : SNDRV_MINOR_OSS_PCM)); - break; - case SNDRV_OSS_DEVICE_TYPE_MIDI: - if (snd_BUG_ON(!card || dev < 0 || dev > 1)) - return -EINVAL; - minor = SNDRV_MINOR_OSS(card->number, (dev ? SNDRV_MINOR_OSS_MIDI1 : SNDRV_MINOR_OSS_MIDI)); - break; - case SNDRV_OSS_DEVICE_TYPE_DMFM: - minor = SNDRV_MINOR_OSS(card->number, SNDRV_MINOR_OSS_DMFM); - break; - case SNDRV_OSS_DEVICE_TYPE_SNDSTAT: - minor = SNDRV_MINOR_OSS_SNDSTAT; - break; - default: - return -EINVAL; - } - if (minor < 0 || minor >= SNDRV_OSS_MINORS) - return -EINVAL; - return minor; -} - -int snd_register_oss_device(int type, struct snd_card *card, int dev, - const struct file_operations *f_ops, void *private_data, - const char *name) -{ - int minor = snd_oss_kernel_minor(type, card, dev); - int minor_unit; - struct snd_minor *preg; - int cidx = SNDRV_MINOR_OSS_CARD(minor); - int track2 = -1; - int register1 = -1, register2 = -1; - struct device *carddev = snd_card_get_device_link(card); - - if (card && card->number >= 8) - return 0; /* ignore silently */ - if (minor < 0) - return minor; - preg = kmalloc(sizeof(struct snd_minor), GFP_KERNEL); - if (preg == NULL) - return -ENOMEM; - preg->type = type; - preg->card = card ? card->number : -1; - preg->device = dev; - preg->f_ops = f_ops; - preg->private_data = private_data; - preg->card_ptr = card; - mutex_lock(&sound_oss_mutex); - snd_oss_minors[minor] = preg; - minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); - switch (minor_unit) { - case SNDRV_MINOR_OSS_PCM: - track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO); - break; - case SNDRV_MINOR_OSS_MIDI: - track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI); - break; - case SNDRV_MINOR_OSS_MIDI1: - track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); - break; - } - register1 = register_sound_special_device(f_ops, minor, carddev); - if (register1 != minor) - goto __end; - if (track2 >= 0) { - register2 = register_sound_special_device(f_ops, track2, - carddev); - if (register2 != track2) - goto __end; - snd_oss_minors[track2] = preg; - } - mutex_unlock(&sound_oss_mutex); - return 0; - - __end: - if (register2 >= 0) - unregister_sound_special(register2); - if (register1 >= 0) - unregister_sound_special(register1); - snd_oss_minors[minor] = NULL; - mutex_unlock(&sound_oss_mutex); - kfree(preg); - return -EBUSY; -} - -EXPORT_SYMBOL(snd_register_oss_device); - -int snd_unregister_oss_device(int type, struct snd_card *card, int dev) -{ - int minor = snd_oss_kernel_minor(type, card, dev); - int cidx = SNDRV_MINOR_OSS_CARD(minor); - int track2 = -1; - struct snd_minor *mptr; - - if (card && card->number >= 8) - return 0; - if (minor < 0) - return minor; - mutex_lock(&sound_oss_mutex); - mptr = snd_oss_minors[minor]; - if (mptr == NULL) { - mutex_unlock(&sound_oss_mutex); - return -ENOENT; - } - unregister_sound_special(minor); - switch (SNDRV_MINOR_OSS_DEVICE(minor)) { - case SNDRV_MINOR_OSS_PCM: - track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO); - break; - case SNDRV_MINOR_OSS_MIDI: - track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI); - break; - case SNDRV_MINOR_OSS_MIDI1: - track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); - break; - } - if (track2 >= 0) { - unregister_sound_special(track2); - snd_oss_minors[track2] = NULL; - } - snd_oss_minors[minor] = NULL; - mutex_unlock(&sound_oss_mutex); - kfree(mptr); - return 0; -} - -EXPORT_SYMBOL(snd_unregister_oss_device); - -/* - * INFO PART - */ - -#ifdef CONFIG_PROC_FS - -static struct snd_info_entry *snd_minor_info_oss_entry; - -static const char *snd_oss_device_type_name(int type) -{ - switch (type) { - case SNDRV_OSS_DEVICE_TYPE_MIXER: - return "mixer"; - case SNDRV_OSS_DEVICE_TYPE_SEQUENCER: - case SNDRV_OSS_DEVICE_TYPE_MUSIC: - return "sequencer"; - case SNDRV_OSS_DEVICE_TYPE_PCM: - return "digital audio"; - case SNDRV_OSS_DEVICE_TYPE_MIDI: - return "raw midi"; - case SNDRV_OSS_DEVICE_TYPE_DMFM: - return "hardware dependent"; - default: - return "?"; - } -} - -static void snd_minor_info_oss_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - int minor; - struct snd_minor *mptr; - - mutex_lock(&sound_oss_mutex); - for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) { - if (!(mptr = snd_oss_minors[minor])) - continue; - if (mptr->card >= 0) - snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor, - mptr->card, mptr->device, - snd_oss_device_type_name(mptr->type)); - else - snd_iprintf(buffer, "%3i: : %s\n", minor, - snd_oss_device_type_name(mptr->type)); - } - mutex_unlock(&sound_oss_mutex); -} - - -int __init snd_minor_info_oss_init(void) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root); - if (entry) { - entry->c.text.read = snd_minor_info_oss_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_minor_info_oss_entry = entry; - return 0; -} - -int __exit snd_minor_info_oss_done(void) -{ - snd_info_free_entry(snd_minor_info_oss_entry); - return 0; -} -#endif /* CONFIG_PROC_FS */ - -#endif /* CONFIG_SND_OSSEMUL */ diff --git a/ANDROID_3.4.5/sound/core/timer.c b/ANDROID_3.4.5/sound/core/timer.c deleted file mode 100644 index 6ddcf06f..00000000 --- a/ANDROID_3.4.5/sound/core/timer.c +++ /dev/null @@ -1,1999 +0,0 @@ -/* - * Timers abstract layer - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_SND_HRTIMER) || defined(CONFIG_SND_HRTIMER_MODULE) -#define DEFAULT_TIMER_LIMIT 4 -#elif defined(CONFIG_SND_RTCTIMER) || defined(CONFIG_SND_RTCTIMER_MODULE) -#define DEFAULT_TIMER_LIMIT 2 -#else -#define DEFAULT_TIMER_LIMIT 1 -#endif - -static int timer_limit = DEFAULT_TIMER_LIMIT; -static int timer_tstamp_monotonic = 1; -MODULE_AUTHOR("Jaroslav Kysela , Takashi Iwai "); -MODULE_DESCRIPTION("ALSA timer interface"); -MODULE_LICENSE("GPL"); -module_param(timer_limit, int, 0444); -MODULE_PARM_DESC(timer_limit, "Maximum global timers in system."); -module_param(timer_tstamp_monotonic, int, 0444); -MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for timestamps (default)."); - -MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER); -MODULE_ALIAS("devname:snd/timer"); - -struct snd_timer_user { - struct snd_timer_instance *timeri; - int tread; /* enhanced read with timestamps and events */ - unsigned long ticks; - unsigned long overrun; - int qhead; - int qtail; - int qused; - int queue_size; - struct snd_timer_read *queue; - struct snd_timer_tread *tqueue; - spinlock_t qlock; - unsigned long last_resolution; - unsigned int filter; - struct timespec tstamp; /* trigger tstamp */ - wait_queue_head_t qchange_sleep; - struct fasync_struct *fasync; - struct mutex tread_sem; -}; - -/* list of timers */ -static LIST_HEAD(snd_timer_list); - -/* list of slave instances */ -static LIST_HEAD(snd_timer_slave_list); - -/* lock for slave active lists */ -static DEFINE_SPINLOCK(slave_active_lock); - -static DEFINE_MUTEX(register_mutex); - -static int snd_timer_free(struct snd_timer *timer); -static int snd_timer_dev_free(struct snd_device *device); -static int snd_timer_dev_register(struct snd_device *device); -static int snd_timer_dev_disconnect(struct snd_device *device); - -static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left); - -/* - * create a timer instance with the given owner string. - * when timer is not NULL, increments the module counter - */ -static struct snd_timer_instance *snd_timer_instance_new(char *owner, - struct snd_timer *timer) -{ - struct snd_timer_instance *timeri; - timeri = kzalloc(sizeof(*timeri), GFP_KERNEL); - if (timeri == NULL) - return NULL; - timeri->owner = kstrdup(owner, GFP_KERNEL); - if (! timeri->owner) { - kfree(timeri); - return NULL; - } - INIT_LIST_HEAD(&timeri->open_list); - INIT_LIST_HEAD(&timeri->active_list); - INIT_LIST_HEAD(&timeri->ack_list); - INIT_LIST_HEAD(&timeri->slave_list_head); - INIT_LIST_HEAD(&timeri->slave_active_head); - - timeri->timer = timer; - if (timer && !try_module_get(timer->module)) { - kfree(timeri->owner); - kfree(timeri); - return NULL; - } - - return timeri; -} - -/* - * find a timer instance from the given timer id - */ -static struct snd_timer *snd_timer_find(struct snd_timer_id *tid) -{ - struct snd_timer *timer = NULL; - - list_for_each_entry(timer, &snd_timer_list, device_list) { - if (timer->tmr_class != tid->dev_class) - continue; - if ((timer->tmr_class == SNDRV_TIMER_CLASS_CARD || - timer->tmr_class == SNDRV_TIMER_CLASS_PCM) && - (timer->card == NULL || - timer->card->number != tid->card)) - continue; - if (timer->tmr_device != tid->device) - continue; - if (timer->tmr_subdevice != tid->subdevice) - continue; - return timer; - } - return NULL; -} - -#ifdef CONFIG_MODULES - -static void snd_timer_request(struct snd_timer_id *tid) -{ - switch (tid->dev_class) { - case SNDRV_TIMER_CLASS_GLOBAL: - if (tid->device < timer_limit) - request_module("snd-timer-%i", tid->device); - break; - case SNDRV_TIMER_CLASS_CARD: - case SNDRV_TIMER_CLASS_PCM: - if (tid->card < snd_ecards_limit) - request_module("snd-card-%i", tid->card); - break; - default: - break; - } -} - -#endif - -/* - * look for a master instance matching with the slave id of the given slave. - * when found, relink the open_link of the slave. - * - * call this with register_mutex down. - */ -static void snd_timer_check_slave(struct snd_timer_instance *slave) -{ - struct snd_timer *timer; - struct snd_timer_instance *master; - - /* FIXME: it's really dumb to look up all entries.. */ - list_for_each_entry(timer, &snd_timer_list, device_list) { - list_for_each_entry(master, &timer->open_list_head, open_list) { - if (slave->slave_class == master->slave_class && - slave->slave_id == master->slave_id) { - list_move_tail(&slave->open_list, - &master->slave_list_head); - spin_lock_irq(&slave_active_lock); - slave->master = master; - slave->timer = master->timer; - spin_unlock_irq(&slave_active_lock); - return; - } - } - } -} - -/* - * look for slave instances matching with the slave id of the given master. - * when found, relink the open_link of slaves. - * - * call this with register_mutex down. - */ -static void snd_timer_check_master(struct snd_timer_instance *master) -{ - struct snd_timer_instance *slave, *tmp; - - /* check all pending slaves */ - list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) { - if (slave->slave_class == master->slave_class && - slave->slave_id == master->slave_id) { - list_move_tail(&slave->open_list, &master->slave_list_head); - spin_lock_irq(&slave_active_lock); - slave->master = master; - slave->timer = master->timer; - if (slave->flags & SNDRV_TIMER_IFLG_RUNNING) - list_add_tail(&slave->active_list, - &master->slave_active_head); - spin_unlock_irq(&slave_active_lock); - } - } -} - -/* - * open a timer instance - * when opening a master, the slave id must be here given. - */ -int snd_timer_open(struct snd_timer_instance **ti, - char *owner, struct snd_timer_id *tid, - unsigned int slave_id) -{ - struct snd_timer *timer; - struct snd_timer_instance *timeri = NULL; - - if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) { - /* open a slave instance */ - if (tid->dev_sclass <= SNDRV_TIMER_SCLASS_NONE || - tid->dev_sclass > SNDRV_TIMER_SCLASS_OSS_SEQUENCER) { - snd_printd("invalid slave class %i\n", tid->dev_sclass); - return -EINVAL; - } - mutex_lock(®ister_mutex); - timeri = snd_timer_instance_new(owner, NULL); - if (!timeri) { - mutex_unlock(®ister_mutex); - return -ENOMEM; - } - timeri->slave_class = tid->dev_sclass; - timeri->slave_id = tid->device; - timeri->flags |= SNDRV_TIMER_IFLG_SLAVE; - list_add_tail(&timeri->open_list, &snd_timer_slave_list); - snd_timer_check_slave(timeri); - mutex_unlock(®ister_mutex); - *ti = timeri; - return 0; - } - - /* open a master instance */ - mutex_lock(®ister_mutex); - timer = snd_timer_find(tid); -#ifdef CONFIG_MODULES - if (!timer) { - mutex_unlock(®ister_mutex); - snd_timer_request(tid); - mutex_lock(®ister_mutex); - timer = snd_timer_find(tid); - } -#endif - if (!timer) { - mutex_unlock(®ister_mutex); - return -ENODEV; - } - if (!list_empty(&timer->open_list_head)) { - timeri = list_entry(timer->open_list_head.next, - struct snd_timer_instance, open_list); - if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) { - mutex_unlock(®ister_mutex); - return -EBUSY; - } - } - timeri = snd_timer_instance_new(owner, timer); - if (!timeri) { - mutex_unlock(®ister_mutex); - return -ENOMEM; - } - timeri->slave_class = tid->dev_sclass; - timeri->slave_id = slave_id; - if (list_empty(&timer->open_list_head) && timer->hw.open) - timer->hw.open(timer); - list_add_tail(&timeri->open_list, &timer->open_list_head); - snd_timer_check_master(timeri); - mutex_unlock(®ister_mutex); - *ti = timeri; - return 0; -} - -static int _snd_timer_stop(struct snd_timer_instance *timeri, - int keep_flag, int event); - -/* - * close a timer instance - */ -int snd_timer_close(struct snd_timer_instance *timeri) -{ - struct snd_timer *timer = NULL; - struct snd_timer_instance *slave, *tmp; - - if (snd_BUG_ON(!timeri)) - return -ENXIO; - - /* force to stop the timer */ - snd_timer_stop(timeri); - - if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { - /* wait, until the active callback is finished */ - spin_lock_irq(&slave_active_lock); - while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { - spin_unlock_irq(&slave_active_lock); - udelay(10); - spin_lock_irq(&slave_active_lock); - } - spin_unlock_irq(&slave_active_lock); - mutex_lock(®ister_mutex); - list_del(&timeri->open_list); - mutex_unlock(®ister_mutex); - } else { - timer = timeri->timer; - if (snd_BUG_ON(!timer)) - goto out; - /* wait, until the active callback is finished */ - spin_lock_irq(&timer->lock); - while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { - spin_unlock_irq(&timer->lock); - udelay(10); - spin_lock_irq(&timer->lock); - } - spin_unlock_irq(&timer->lock); - mutex_lock(®ister_mutex); - list_del(&timeri->open_list); - if (timer && list_empty(&timer->open_list_head) && - timer->hw.close) - timer->hw.close(timer); - /* remove slave links */ - list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, - open_list) { - spin_lock_irq(&slave_active_lock); - _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION); - list_move_tail(&slave->open_list, &snd_timer_slave_list); - slave->master = NULL; - slave->timer = NULL; - spin_unlock_irq(&slave_active_lock); - } - mutex_unlock(®ister_mutex); - } - out: - if (timeri->private_free) - timeri->private_free(timeri); - kfree(timeri->owner); - kfree(timeri); - if (timer) - module_put(timer->module); - return 0; -} - -unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) -{ - struct snd_timer * timer; - - if (timeri == NULL) - return 0; - if ((timer = timeri->timer) != NULL) { - if (timer->hw.c_resolution) - return timer->hw.c_resolution(timer); - return timer->hw.resolution; - } - return 0; -} - -static void snd_timer_notify1(struct snd_timer_instance *ti, int event) -{ - struct snd_timer *timer; - unsigned long flags; - unsigned long resolution = 0; - struct snd_timer_instance *ts; - struct timespec tstamp; - - if (timer_tstamp_monotonic) - do_posix_clock_monotonic_gettime(&tstamp); - else - getnstimeofday(&tstamp); - if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START || - event > SNDRV_TIMER_EVENT_PAUSE)) - return; - if (event == SNDRV_TIMER_EVENT_START || - event == SNDRV_TIMER_EVENT_CONTINUE) - resolution = snd_timer_resolution(ti); - if (ti->ccallback) - ti->ccallback(ti, event, &tstamp, resolution); - if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) - return; - timer = ti->timer; - if (timer == NULL) - return; - if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) - return; - spin_lock_irqsave(&timer->lock, flags); - list_for_each_entry(ts, &ti->slave_active_head, active_list) - if (ts->ccallback) - ts->ccallback(ti, event + 100, &tstamp, resolution); - spin_unlock_irqrestore(&timer->lock, flags); -} - -static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri, - unsigned long sticks) -{ - list_move_tail(&timeri->active_list, &timer->active_list_head); - if (timer->running) { - if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) - goto __start_now; - timer->flags |= SNDRV_TIMER_FLG_RESCHED; - timeri->flags |= SNDRV_TIMER_IFLG_START; - return 1; /* delayed start */ - } else { - timer->sticks = sticks; - timer->hw.start(timer); - __start_now: - timer->running++; - timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; - return 0; - } -} - -static int snd_timer_start_slave(struct snd_timer_instance *timeri) -{ - unsigned long flags; - - spin_lock_irqsave(&slave_active_lock, flags); - timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; - if (timeri->master) - list_add_tail(&timeri->active_list, - &timeri->master->slave_active_head); - spin_unlock_irqrestore(&slave_active_lock, flags); - return 1; /* delayed start */ -} - -/* - * start the timer instance - */ -int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) -{ - struct snd_timer *timer; - int result = -EINVAL; - unsigned long flags; - - if (timeri == NULL || ticks < 1) - return -EINVAL; - if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { - result = snd_timer_start_slave(timeri); - snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); - return result; - } - timer = timeri->timer; - if (timer == NULL) - return -EINVAL; - spin_lock_irqsave(&timer->lock, flags); - timeri->ticks = timeri->cticks = ticks; - timeri->pticks = 0; - result = snd_timer_start1(timer, timeri, ticks); - spin_unlock_irqrestore(&timer->lock, flags); - snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); - return result; -} - -static int _snd_timer_stop(struct snd_timer_instance * timeri, - int keep_flag, int event) -{ - struct snd_timer *timer; - unsigned long flags; - - if (snd_BUG_ON(!timeri)) - return -ENXIO; - - if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { - if (!keep_flag) { - spin_lock_irqsave(&slave_active_lock, flags); - timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; - spin_unlock_irqrestore(&slave_active_lock, flags); - } - goto __end; - } - timer = timeri->timer; - if (!timer) - return -EINVAL; - spin_lock_irqsave(&timer->lock, flags); - list_del_init(&timeri->ack_list); - list_del_init(&timeri->active_list); - if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && - !(--timer->running)) { - timer->hw.stop(timer); - if (timer->flags & SNDRV_TIMER_FLG_RESCHED) { - timer->flags &= ~SNDRV_TIMER_FLG_RESCHED; - snd_timer_reschedule(timer, 0); - if (timer->flags & SNDRV_TIMER_FLG_CHANGE) { - timer->flags &= ~SNDRV_TIMER_FLG_CHANGE; - timer->hw.start(timer); - } - } - } - if (!keep_flag) - timeri->flags &= - ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); - spin_unlock_irqrestore(&timer->lock, flags); - __end: - if (event != SNDRV_TIMER_EVENT_RESOLUTION) - snd_timer_notify1(timeri, event); - return 0; -} - -/* - * stop the timer instance. - * - * do not call this from the timer callback! - */ -int snd_timer_stop(struct snd_timer_instance *timeri) -{ - struct snd_timer *timer; - unsigned long flags; - int err; - - err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP); - if (err < 0) - return err; - timer = timeri->timer; - if (!timer) - return -EINVAL; - spin_lock_irqsave(&timer->lock, flags); - timeri->cticks = timeri->ticks; - timeri->pticks = 0; - spin_unlock_irqrestore(&timer->lock, flags); - return 0; -} - -/* - * start again.. the tick is kept. - */ -int snd_timer_continue(struct snd_timer_instance *timeri) -{ - struct snd_timer *timer; - int result = -EINVAL; - unsigned long flags; - - if (timeri == NULL) - return result; - if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) - return snd_timer_start_slave(timeri); - timer = timeri->timer; - if (! timer) - return -EINVAL; - spin_lock_irqsave(&timer->lock, flags); - if (!timeri->cticks) - timeri->cticks = 1; - timeri->pticks = 0; - result = snd_timer_start1(timer, timeri, timer->sticks); - spin_unlock_irqrestore(&timer->lock, flags); - snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE); - return result; -} - -/* - * pause.. remember the ticks left - */ -int snd_timer_pause(struct snd_timer_instance * timeri) -{ - return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE); -} - -/* - * reschedule the timer - * - * start pending instances and check the scheduling ticks. - * when the scheduling ticks is changed set CHANGE flag to reprogram the timer. - */ -static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left) -{ - struct snd_timer_instance *ti; - unsigned long ticks = ~0UL; - - list_for_each_entry(ti, &timer->active_list_head, active_list) { - if (ti->flags & SNDRV_TIMER_IFLG_START) { - ti->flags &= ~SNDRV_TIMER_IFLG_START; - ti->flags |= SNDRV_TIMER_IFLG_RUNNING; - timer->running++; - } - if (ti->flags & SNDRV_TIMER_IFLG_RUNNING) { - if (ticks > ti->cticks) - ticks = ti->cticks; - } - } - if (ticks == ~0UL) { - timer->flags &= ~SNDRV_TIMER_FLG_RESCHED; - return; - } - if (ticks > timer->hw.ticks) - ticks = timer->hw.ticks; - if (ticks_left != ticks) - timer->flags |= SNDRV_TIMER_FLG_CHANGE; - timer->sticks = ticks; -} - -/* - * timer tasklet - * - */ -static void snd_timer_tasklet(unsigned long arg) -{ - struct snd_timer *timer = (struct snd_timer *) arg; - struct snd_timer_instance *ti; - struct list_head *p; - unsigned long resolution, ticks; - unsigned long flags; - - spin_lock_irqsave(&timer->lock, flags); - /* now process all callbacks */ - while (!list_empty(&timer->sack_list_head)) { - p = timer->sack_list_head.next; /* get first item */ - ti = list_entry(p, struct snd_timer_instance, ack_list); - - /* remove from ack_list and make empty */ - list_del_init(p); - - ticks = ti->pticks; - ti->pticks = 0; - resolution = ti->resolution; - - ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; - spin_unlock(&timer->lock); - if (ti->callback) - ti->callback(ti, resolution, ticks); - spin_lock(&timer->lock); - ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; - } - spin_unlock_irqrestore(&timer->lock, flags); -} - -/* - * timer interrupt - * - * ticks_left is usually equal to timer->sticks. - * - */ -void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) -{ - struct snd_timer_instance *ti, *ts, *tmp; - unsigned long resolution, ticks; - struct list_head *p, *ack_list_head; - unsigned long flags; - int use_tasklet = 0; - - if (timer == NULL) - return; - - spin_lock_irqsave(&timer->lock, flags); - - /* remember the current resolution */ - if (timer->hw.c_resolution) - resolution = timer->hw.c_resolution(timer); - else - resolution = timer->hw.resolution; - - /* loop for all active instances - * Here we cannot use list_for_each_entry because the active_list of a - * processed instance is relinked to done_list_head before the callback - * is called. - */ - list_for_each_entry_safe(ti, tmp, &timer->active_list_head, - active_list) { - if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING)) - continue; - ti->pticks += ticks_left; - ti->resolution = resolution; - if (ti->cticks < ticks_left) - ti->cticks = 0; - else - ti->cticks -= ticks_left; - if (ti->cticks) /* not expired */ - continue; - if (ti->flags & SNDRV_TIMER_IFLG_AUTO) { - ti->cticks = ti->ticks; - } else { - ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING; - if (--timer->running) - list_del(&ti->active_list); - } - if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || - (ti->flags & SNDRV_TIMER_IFLG_FAST)) - ack_list_head = &timer->ack_list_head; - else - ack_list_head = &timer->sack_list_head; - if (list_empty(&ti->ack_list)) - list_add_tail(&ti->ack_list, ack_list_head); - list_for_each_entry(ts, &ti->slave_active_head, active_list) { - ts->pticks = ti->pticks; - ts->resolution = resolution; - if (list_empty(&ts->ack_list)) - list_add_tail(&ts->ack_list, ack_list_head); - } - } - if (timer->flags & SNDRV_TIMER_FLG_RESCHED) - snd_timer_reschedule(timer, timer->sticks); - if (timer->running) { - if (timer->hw.flags & SNDRV_TIMER_HW_STOP) { - timer->hw.stop(timer); - timer->flags |= SNDRV_TIMER_FLG_CHANGE; - } - if (!(timer->hw.flags & SNDRV_TIMER_HW_AUTO) || - (timer->flags & SNDRV_TIMER_FLG_CHANGE)) { - /* restart timer */ - timer->flags &= ~SNDRV_TIMER_FLG_CHANGE; - timer->hw.start(timer); - } - } else { - timer->hw.stop(timer); - } - - /* now process all fast callbacks */ - while (!list_empty(&timer->ack_list_head)) { - p = timer->ack_list_head.next; /* get first item */ - ti = list_entry(p, struct snd_timer_instance, ack_list); - - /* remove from ack_list and make empty */ - list_del_init(p); - - ticks = ti->pticks; - ti->pticks = 0; - - ti->flags |= SNDRV_TIMER_IFLG_CALLBACK; - spin_unlock(&timer->lock); - if (ti->callback) - ti->callback(ti, resolution, ticks); - spin_lock(&timer->lock); - ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK; - } - - /* do we have any slow callbacks? */ - use_tasklet = !list_empty(&timer->sack_list_head); - spin_unlock_irqrestore(&timer->lock, flags); - - if (use_tasklet) - tasklet_schedule(&timer->task_queue); -} - -/* - - */ - -int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, - struct snd_timer **rtimer) -{ - struct snd_timer *timer; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_timer_dev_free, - .dev_register = snd_timer_dev_register, - .dev_disconnect = snd_timer_dev_disconnect, - }; - - if (snd_BUG_ON(!tid)) - return -EINVAL; - if (rtimer) - *rtimer = NULL; - timer = kzalloc(sizeof(*timer), GFP_KERNEL); - if (timer == NULL) { - snd_printk(KERN_ERR "timer: cannot allocate\n"); - return -ENOMEM; - } - timer->tmr_class = tid->dev_class; - timer->card = card; - timer->tmr_device = tid->device; - timer->tmr_subdevice = tid->subdevice; - if (id) - strlcpy(timer->id, id, sizeof(timer->id)); - INIT_LIST_HEAD(&timer->device_list); - INIT_LIST_HEAD(&timer->open_list_head); - INIT_LIST_HEAD(&timer->active_list_head); - INIT_LIST_HEAD(&timer->ack_list_head); - INIT_LIST_HEAD(&timer->sack_list_head); - spin_lock_init(&timer->lock); - tasklet_init(&timer->task_queue, snd_timer_tasklet, - (unsigned long)timer); - if (card != NULL) { - timer->module = card->module; - err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops); - if (err < 0) { - snd_timer_free(timer); - return err; - } - } - if (rtimer) - *rtimer = timer; - return 0; -} - -static int snd_timer_free(struct snd_timer *timer) -{ - if (!timer) - return 0; - - mutex_lock(®ister_mutex); - if (! list_empty(&timer->open_list_head)) { - struct list_head *p, *n; - struct snd_timer_instance *ti; - snd_printk(KERN_WARNING "timer %p is busy?\n", timer); - list_for_each_safe(p, n, &timer->open_list_head) { - list_del_init(p); - ti = list_entry(p, struct snd_timer_instance, open_list); - ti->timer = NULL; - } - } - list_del(&timer->device_list); - mutex_unlock(®ister_mutex); - - if (timer->private_free) - timer->private_free(timer); - kfree(timer); - return 0; -} - -static int snd_timer_dev_free(struct snd_device *device) -{ - struct snd_timer *timer = device->device_data; - return snd_timer_free(timer); -} - -static int snd_timer_dev_register(struct snd_device *dev) -{ - struct snd_timer *timer = dev->device_data; - struct snd_timer *timer1; - - if (snd_BUG_ON(!timer || !timer->hw.start || !timer->hw.stop)) - return -ENXIO; - if (!(timer->hw.flags & SNDRV_TIMER_HW_SLAVE) && - !timer->hw.resolution && timer->hw.c_resolution == NULL) - return -EINVAL; - - mutex_lock(®ister_mutex); - list_for_each_entry(timer1, &snd_timer_list, device_list) { - if (timer1->tmr_class > timer->tmr_class) - break; - if (timer1->tmr_class < timer->tmr_class) - continue; - if (timer1->card && timer->card) { - if (timer1->card->number > timer->card->number) - break; - if (timer1->card->number < timer->card->number) - continue; - } - if (timer1->tmr_device > timer->tmr_device) - break; - if (timer1->tmr_device < timer->tmr_device) - continue; - if (timer1->tmr_subdevice > timer->tmr_subdevice) - break; - if (timer1->tmr_subdevice < timer->tmr_subdevice) - continue; - /* conflicts.. */ - mutex_unlock(®ister_mutex); - return -EBUSY; - } - list_add_tail(&timer->device_list, &timer1->device_list); - mutex_unlock(®ister_mutex); - return 0; -} - -static int snd_timer_dev_disconnect(struct snd_device *device) -{ - struct snd_timer *timer = device->device_data; - mutex_lock(®ister_mutex); - list_del_init(&timer->device_list); - mutex_unlock(®ister_mutex); - return 0; -} - -void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp) -{ - unsigned long flags; - unsigned long resolution = 0; - struct snd_timer_instance *ti, *ts; - - if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) - return; - if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART || - event > SNDRV_TIMER_EVENT_MRESUME)) - return; - spin_lock_irqsave(&timer->lock, flags); - if (event == SNDRV_TIMER_EVENT_MSTART || - event == SNDRV_TIMER_EVENT_MCONTINUE || - event == SNDRV_TIMER_EVENT_MRESUME) { - if (timer->hw.c_resolution) - resolution = timer->hw.c_resolution(timer); - else - resolution = timer->hw.resolution; - } - list_for_each_entry(ti, &timer->active_list_head, active_list) { - if (ti->ccallback) - ti->ccallback(ti, event, tstamp, resolution); - list_for_each_entry(ts, &ti->slave_active_head, active_list) - if (ts->ccallback) - ts->ccallback(ts, event, tstamp, resolution); - } - spin_unlock_irqrestore(&timer->lock, flags); -} - -/* - * exported functions for global timers - */ -int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer) -{ - struct snd_timer_id tid; - - tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = -1; - tid.device = device; - tid.subdevice = 0; - return snd_timer_new(NULL, id, &tid, rtimer); -} - -int snd_timer_global_free(struct snd_timer *timer) -{ - return snd_timer_free(timer); -} - -int snd_timer_global_register(struct snd_timer *timer) -{ - struct snd_device dev; - - memset(&dev, 0, sizeof(dev)); - dev.device_data = timer; - return snd_timer_dev_register(&dev); -} - -/* - * System timer - */ - -struct snd_timer_system_private { - struct timer_list tlist; - unsigned long last_expires; - unsigned long last_jiffies; - unsigned long correction; -}; - -static void snd_timer_s_function(unsigned long data) -{ - struct snd_timer *timer = (struct snd_timer *)data; - struct snd_timer_system_private *priv = timer->private_data; - unsigned long jiff = jiffies; - if (time_after(jiff, priv->last_expires)) - priv->correction += (long)jiff - (long)priv->last_expires; - snd_timer_interrupt(timer, (long)jiff - (long)priv->last_jiffies); -} - -static int snd_timer_s_start(struct snd_timer * timer) -{ - struct snd_timer_system_private *priv; - unsigned long njiff; - - priv = (struct snd_timer_system_private *) timer->private_data; - njiff = (priv->last_jiffies = jiffies); - if (priv->correction > timer->sticks - 1) { - priv->correction -= timer->sticks - 1; - njiff++; - } else { - njiff += timer->sticks - priv->correction; - priv->correction = 0; - } - priv->last_expires = priv->tlist.expires = njiff; - add_timer(&priv->tlist); - return 0; -} - -static int snd_timer_s_stop(struct snd_timer * timer) -{ - struct snd_timer_system_private *priv; - unsigned long jiff; - - priv = (struct snd_timer_system_private *) timer->private_data; - del_timer(&priv->tlist); - jiff = jiffies; - if (time_before(jiff, priv->last_expires)) - timer->sticks = priv->last_expires - jiff; - else - timer->sticks = 1; - priv->correction = 0; - return 0; -} - -static struct snd_timer_hardware snd_timer_system = -{ - .flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET, - .resolution = 1000000000L / HZ, - .ticks = 10000000L, - .start = snd_timer_s_start, - .stop = snd_timer_s_stop -}; - -static void snd_timer_free_system(struct snd_timer *timer) -{ - kfree(timer->private_data); -} - -static int snd_timer_register_system(void) -{ - struct snd_timer *timer; - struct snd_timer_system_private *priv; - int err; - - err = snd_timer_global_new("system", SNDRV_TIMER_GLOBAL_SYSTEM, &timer); - if (err < 0) - return err; - strcpy(timer->name, "system timer"); - timer->hw = snd_timer_system; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) { - snd_timer_free(timer); - return -ENOMEM; - } - init_timer(&priv->tlist); - priv->tlist.function = snd_timer_s_function; - priv->tlist.data = (unsigned long) timer; - timer->private_data = priv; - timer->private_free = snd_timer_free_system; - return snd_timer_global_register(timer); -} - -#ifdef CONFIG_PROC_FS -/* - * Info interface - */ - -static void snd_timer_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_timer *timer; - struct snd_timer_instance *ti; - - mutex_lock(®ister_mutex); - list_for_each_entry(timer, &snd_timer_list, device_list) { - switch (timer->tmr_class) { - case SNDRV_TIMER_CLASS_GLOBAL: - snd_iprintf(buffer, "G%i: ", timer->tmr_device); - break; - case SNDRV_TIMER_CLASS_CARD: - snd_iprintf(buffer, "C%i-%i: ", - timer->card->number, timer->tmr_device); - break; - case SNDRV_TIMER_CLASS_PCM: - snd_iprintf(buffer, "P%i-%i-%i: ", timer->card->number, - timer->tmr_device, timer->tmr_subdevice); - break; - default: - snd_iprintf(buffer, "?%i-%i-%i-%i: ", timer->tmr_class, - timer->card ? timer->card->number : -1, - timer->tmr_device, timer->tmr_subdevice); - } - snd_iprintf(buffer, "%s :", timer->name); - if (timer->hw.resolution) - snd_iprintf(buffer, " %lu.%03luus (%lu ticks)", - timer->hw.resolution / 1000, - timer->hw.resolution % 1000, - timer->hw.ticks); - if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) - snd_iprintf(buffer, " SLAVE"); - snd_iprintf(buffer, "\n"); - list_for_each_entry(ti, &timer->open_list_head, open_list) - snd_iprintf(buffer, " Client %s : %s\n", - ti->owner ? ti->owner : "unknown", - ti->flags & (SNDRV_TIMER_IFLG_START | - SNDRV_TIMER_IFLG_RUNNING) - ? "running" : "stopped"); - } - mutex_unlock(®ister_mutex); -} - -static struct snd_info_entry *snd_timer_proc_entry; - -static void __init snd_timer_proc_init(void) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL); - if (entry != NULL) { - entry->c.text.read = snd_timer_proc_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - snd_timer_proc_entry = entry; -} - -static void __exit snd_timer_proc_done(void) -{ - snd_info_free_entry(snd_timer_proc_entry); -} -#else /* !CONFIG_PROC_FS */ -#define snd_timer_proc_init() -#define snd_timer_proc_done() -#endif - -/* - * USER SPACE interface - */ - -static void snd_timer_user_interrupt(struct snd_timer_instance *timeri, - unsigned long resolution, - unsigned long ticks) -{ - struct snd_timer_user *tu = timeri->callback_data; - struct snd_timer_read *r; - int prev; - - spin_lock(&tu->qlock); - if (tu->qused > 0) { - prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; - r = &tu->queue[prev]; - if (r->resolution == resolution) { - r->ticks += ticks; - goto __wake; - } - } - if (tu->qused >= tu->queue_size) { - tu->overrun++; - } else { - r = &tu->queue[tu->qtail++]; - tu->qtail %= tu->queue_size; - r->resolution = resolution; - r->ticks = ticks; - tu->qused++; - } - __wake: - spin_unlock(&tu->qlock); - kill_fasync(&tu->fasync, SIGIO, POLL_IN); - wake_up(&tu->qchange_sleep); -} - -static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu, - struct snd_timer_tread *tread) -{ - if (tu->qused >= tu->queue_size) { - tu->overrun++; - } else { - memcpy(&tu->tqueue[tu->qtail++], tread, sizeof(*tread)); - tu->qtail %= tu->queue_size; - tu->qused++; - } -} - -static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, - int event, - struct timespec *tstamp, - unsigned long resolution) -{ - struct snd_timer_user *tu = timeri->callback_data; - struct snd_timer_tread r1; - unsigned long flags; - - if (event >= SNDRV_TIMER_EVENT_START && - event <= SNDRV_TIMER_EVENT_PAUSE) - tu->tstamp = *tstamp; - if ((tu->filter & (1 << event)) == 0 || !tu->tread) - return; - r1.event = event; - r1.tstamp = *tstamp; - r1.val = resolution; - spin_lock_irqsave(&tu->qlock, flags); - snd_timer_user_append_to_tqueue(tu, &r1); - spin_unlock_irqrestore(&tu->qlock, flags); - kill_fasync(&tu->fasync, SIGIO, POLL_IN); - wake_up(&tu->qchange_sleep); -} - -static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, - unsigned long resolution, - unsigned long ticks) -{ - struct snd_timer_user *tu = timeri->callback_data; - struct snd_timer_tread *r, r1; - struct timespec tstamp; - int prev, append = 0; - - memset(&tstamp, 0, sizeof(tstamp)); - spin_lock(&tu->qlock); - if ((tu->filter & ((1 << SNDRV_TIMER_EVENT_RESOLUTION) | - (1 << SNDRV_TIMER_EVENT_TICK))) == 0) { - spin_unlock(&tu->qlock); - return; - } - if (tu->last_resolution != resolution || ticks > 0) { - if (timer_tstamp_monotonic) - do_posix_clock_monotonic_gettime(&tstamp); - else - getnstimeofday(&tstamp); - } - if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) && - tu->last_resolution != resolution) { - r1.event = SNDRV_TIMER_EVENT_RESOLUTION; - r1.tstamp = tstamp; - r1.val = resolution; - snd_timer_user_append_to_tqueue(tu, &r1); - tu->last_resolution = resolution; - append++; - } - if ((tu->filter & (1 << SNDRV_TIMER_EVENT_TICK)) == 0) - goto __wake; - if (ticks == 0) - goto __wake; - if (tu->qused > 0) { - prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1; - r = &tu->tqueue[prev]; - if (r->event == SNDRV_TIMER_EVENT_TICK) { - r->tstamp = tstamp; - r->val += ticks; - append++; - goto __wake; - } - } - r1.event = SNDRV_TIMER_EVENT_TICK; - r1.tstamp = tstamp; - r1.val = ticks; - snd_timer_user_append_to_tqueue(tu, &r1); - append++; - __wake: - spin_unlock(&tu->qlock); - if (append == 0) - return; - kill_fasync(&tu->fasync, SIGIO, POLL_IN); - wake_up(&tu->qchange_sleep); -} - -static int snd_timer_user_open(struct inode *inode, struct file *file) -{ - struct snd_timer_user *tu; - int err; - - err = nonseekable_open(inode, file); - if (err < 0) - return err; - - tu = kzalloc(sizeof(*tu), GFP_KERNEL); - if (tu == NULL) - return -ENOMEM; - spin_lock_init(&tu->qlock); - init_waitqueue_head(&tu->qchange_sleep); - mutex_init(&tu->tread_sem); - tu->ticks = 1; - tu->queue_size = 128; - tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), - GFP_KERNEL); - if (tu->queue == NULL) { - kfree(tu); - return -ENOMEM; - } - file->private_data = tu; - return 0; -} - -static int snd_timer_user_release(struct inode *inode, struct file *file) -{ - struct snd_timer_user *tu; - - if (file->private_data) { - tu = file->private_data; - file->private_data = NULL; - if (tu->timeri) - snd_timer_close(tu->timeri); - kfree(tu->queue); - kfree(tu->tqueue); - kfree(tu); - } - return 0; -} - -static void snd_timer_user_zero_id(struct snd_timer_id *id) -{ - id->dev_class = SNDRV_TIMER_CLASS_NONE; - id->dev_sclass = SNDRV_TIMER_SCLASS_NONE; - id->card = -1; - id->device = -1; - id->subdevice = -1; -} - -static void snd_timer_user_copy_id(struct snd_timer_id *id, struct snd_timer *timer) -{ - id->dev_class = timer->tmr_class; - id->dev_sclass = SNDRV_TIMER_SCLASS_NONE; - id->card = timer->card ? timer->card->number : -1; - id->device = timer->tmr_device; - id->subdevice = timer->tmr_subdevice; -} - -static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) -{ - struct snd_timer_id id; - struct snd_timer *timer; - struct list_head *p; - - if (copy_from_user(&id, _tid, sizeof(id))) - return -EFAULT; - mutex_lock(®ister_mutex); - if (id.dev_class < 0) { /* first item */ - if (list_empty(&snd_timer_list)) - snd_timer_user_zero_id(&id); - else { - timer = list_entry(snd_timer_list.next, - struct snd_timer, device_list); - snd_timer_user_copy_id(&id, timer); - } - } else { - switch (id.dev_class) { - case SNDRV_TIMER_CLASS_GLOBAL: - id.device = id.device < 0 ? 0 : id.device + 1; - list_for_each(p, &snd_timer_list) { - timer = list_entry(p, struct snd_timer, device_list); - if (timer->tmr_class > SNDRV_TIMER_CLASS_GLOBAL) { - snd_timer_user_copy_id(&id, timer); - break; - } - if (timer->tmr_device >= id.device) { - snd_timer_user_copy_id(&id, timer); - break; - } - } - if (p == &snd_timer_list) - snd_timer_user_zero_id(&id); - break; - case SNDRV_TIMER_CLASS_CARD: - case SNDRV_TIMER_CLASS_PCM: - if (id.card < 0) { - id.card = 0; - } else { - if (id.card < 0) { - id.card = 0; - } else { - if (id.device < 0) { - id.device = 0; - } else { - if (id.subdevice < 0) { - id.subdevice = 0; - } else { - id.subdevice++; - } - } - } - } - list_for_each(p, &snd_timer_list) { - timer = list_entry(p, struct snd_timer, device_list); - if (timer->tmr_class > id.dev_class) { - snd_timer_user_copy_id(&id, timer); - break; - } - if (timer->tmr_class < id.dev_class) - continue; - if (timer->card->number > id.card) { - snd_timer_user_copy_id(&id, timer); - break; - } - if (timer->card->number < id.card) - continue; - if (timer->tmr_device > id.device) { - snd_timer_user_copy_id(&id, timer); - break; - } - if (timer->tmr_device < id.device) - continue; - if (timer->tmr_subdevice > id.subdevice) { - snd_timer_user_copy_id(&id, timer); - break; - } - if (timer->tmr_subdevice < id.subdevice) - continue; - snd_timer_user_copy_id(&id, timer); - break; - } - if (p == &snd_timer_list) - snd_timer_user_zero_id(&id); - break; - default: - snd_timer_user_zero_id(&id); - } - } - mutex_unlock(®ister_mutex); - if (copy_to_user(_tid, &id, sizeof(*_tid))) - return -EFAULT; - return 0; -} - -static int snd_timer_user_ginfo(struct file *file, - struct snd_timer_ginfo __user *_ginfo) -{ - struct snd_timer_ginfo *ginfo; - struct snd_timer_id tid; - struct snd_timer *t; - struct list_head *p; - int err = 0; - - 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; - mutex_lock(®ister_mutex); - t = snd_timer_find(&tid); - if (t != NULL) { - ginfo->card = t->card ? t->card->number : -1; - if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) - ginfo->flags |= SNDRV_TIMER_FLG_SLAVE; - strlcpy(ginfo->id, t->id, sizeof(ginfo->id)); - strlcpy(ginfo->name, t->name, sizeof(ginfo->name)); - ginfo->resolution = t->hw.resolution; - if (t->hw.resolution_min > 0) { - ginfo->resolution_min = t->hw.resolution_min; - ginfo->resolution_max = t->hw.resolution_max; - } - list_for_each(p, &t->open_list_head) { - ginfo->clients++; - } - } else { - err = -ENODEV; - } - mutex_unlock(®ister_mutex); - if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo))) - err = -EFAULT; - kfree(ginfo); - return err; -} - -static int snd_timer_user_gparams(struct file *file, - struct snd_timer_gparams __user *_gparams) -{ - struct snd_timer_gparams gparams; - struct snd_timer *t; - int err; - - if (copy_from_user(&gparams, _gparams, sizeof(gparams))) - return -EFAULT; - mutex_lock(®ister_mutex); - t = snd_timer_find(&gparams.tid); - if (!t) { - err = -ENODEV; - goto _error; - } - if (!list_empty(&t->open_list_head)) { - err = -EBUSY; - goto _error; - } - if (!t->hw.set_period) { - err = -ENOSYS; - goto _error; - } - err = t->hw.set_period(t, gparams.period_num, gparams.period_den); -_error: - mutex_unlock(®ister_mutex); - return err; -} - -static int snd_timer_user_gstatus(struct file *file, - struct snd_timer_gstatus __user *_gstatus) -{ - struct snd_timer_gstatus gstatus; - struct snd_timer_id tid; - struct snd_timer *t; - int err = 0; - - if (copy_from_user(&gstatus, _gstatus, sizeof(gstatus))) - return -EFAULT; - tid = gstatus.tid; - memset(&gstatus, 0, sizeof(gstatus)); - gstatus.tid = tid; - mutex_lock(®ister_mutex); - t = snd_timer_find(&tid); - if (t != NULL) { - if (t->hw.c_resolution) - gstatus.resolution = t->hw.c_resolution(t); - else - gstatus.resolution = t->hw.resolution; - if (t->hw.precise_resolution) { - t->hw.precise_resolution(t, &gstatus.resolution_num, - &gstatus.resolution_den); - } else { - gstatus.resolution_num = gstatus.resolution; - gstatus.resolution_den = 1000000000uL; - } - } else { - err = -ENODEV; - } - mutex_unlock(®ister_mutex); - if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus))) - err = -EFAULT; - return err; -} - -static int snd_timer_user_tselect(struct file *file, - struct snd_timer_select __user *_tselect) -{ - struct snd_timer_user *tu; - struct snd_timer_select tselect; - char str[32]; - int err = 0; - - tu = file->private_data; - mutex_lock(&tu->tread_sem); - if (tu->timeri) { - snd_timer_close(tu->timeri); - tu->timeri = NULL; - } - if (copy_from_user(&tselect, _tselect, sizeof(tselect))) { - err = -EFAULT; - goto __err; - } - sprintf(str, "application %i", current->pid); - if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) - tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; - err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid); - if (err < 0) - goto __err; - - kfree(tu->queue); - tu->queue = NULL; - kfree(tu->tqueue); - tu->tqueue = NULL; - if (tu->tread) { - tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread), - GFP_KERNEL); - if (tu->tqueue == NULL) - err = -ENOMEM; - } else { - tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), - GFP_KERNEL); - if (tu->queue == NULL) - err = -ENOMEM; - } - - if (err < 0) { - snd_timer_close(tu->timeri); - tu->timeri = NULL; - } else { - tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; - tu->timeri->callback = tu->tread - ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; - tu->timeri->ccallback = snd_timer_user_ccallback; - tu->timeri->callback_data = (void *)tu; - } - - __err: - mutex_unlock(&tu->tread_sem); - return err; -} - -static int snd_timer_user_info(struct file *file, - struct snd_timer_info __user *_info) -{ - struct snd_timer_user *tu; - struct snd_timer_info *info; - struct snd_timer *t; - int err = 0; - - tu = file->private_data; - if (!tu->timeri) - return -EBADFD; - t = tu->timeri->timer; - if (!t) - return -EBADFD; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (! info) - return -ENOMEM; - info->card = t->card ? t->card->number : -1; - if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) - info->flags |= SNDRV_TIMER_FLG_SLAVE; - strlcpy(info->id, t->id, sizeof(info->id)); - strlcpy(info->name, t->name, sizeof(info->name)); - info->resolution = t->hw.resolution; - if (copy_to_user(_info, info, sizeof(*_info))) - err = -EFAULT; - kfree(info); - return err; -} - -static int snd_timer_user_params(struct file *file, - struct snd_timer_params __user *_params) -{ - struct snd_timer_user *tu; - struct snd_timer_params params; - struct snd_timer *t; - struct snd_timer_read *tr; - struct snd_timer_tread *ttr; - int err; - - tu = file->private_data; - if (!tu->timeri) - return -EBADFD; - t = tu->timeri->timer; - if (!t) - return -EBADFD; - if (copy_from_user(¶ms, _params, sizeof(params))) - return -EFAULT; - if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) { - err = -EINVAL; - goto _end; - } - if (params.queue_size > 0 && - (params.queue_size < 32 || params.queue_size > 1024)) { - err = -EINVAL; - goto _end; - } - if (params.filter & ~((1<timeri); - spin_lock_irq(&t->lock); - tu->timeri->flags &= ~(SNDRV_TIMER_IFLG_AUTO| - SNDRV_TIMER_IFLG_EXCLUSIVE| - SNDRV_TIMER_IFLG_EARLY_EVENT); - if (params.flags & SNDRV_TIMER_PSFLG_AUTO) - tu->timeri->flags |= SNDRV_TIMER_IFLG_AUTO; - if (params.flags & SNDRV_TIMER_PSFLG_EXCLUSIVE) - tu->timeri->flags |= SNDRV_TIMER_IFLG_EXCLUSIVE; - if (params.flags & SNDRV_TIMER_PSFLG_EARLY_EVENT) - tu->timeri->flags |= SNDRV_TIMER_IFLG_EARLY_EVENT; - spin_unlock_irq(&t->lock); - if (params.queue_size > 0 && - (unsigned int)tu->queue_size != params.queue_size) { - if (tu->tread) { - ttr = kmalloc(params.queue_size * sizeof(*ttr), - GFP_KERNEL); - if (ttr) { - kfree(tu->tqueue); - tu->queue_size = params.queue_size; - tu->tqueue = ttr; - } - } else { - tr = kmalloc(params.queue_size * sizeof(*tr), - GFP_KERNEL); - if (tr) { - kfree(tu->queue); - tu->queue_size = params.queue_size; - tu->queue = tr; - } - } - } - tu->qhead = tu->qtail = tu->qused = 0; - if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { - if (tu->tread) { - struct snd_timer_tread tread; - tread.event = SNDRV_TIMER_EVENT_EARLY; - tread.tstamp.tv_sec = 0; - tread.tstamp.tv_nsec = 0; - tread.val = 0; - snd_timer_user_append_to_tqueue(tu, &tread); - } else { - struct snd_timer_read *r = &tu->queue[0]; - r->resolution = 0; - r->ticks = 0; - tu->qused++; - tu->qtail++; - } - } - tu->filter = params.filter; - tu->ticks = params.ticks; - err = 0; - _end: - if (copy_to_user(_params, ¶ms, sizeof(params))) - return -EFAULT; - return err; -} - -static int snd_timer_user_status(struct file *file, - struct snd_timer_status __user *_status) -{ - struct snd_timer_user *tu; - struct snd_timer_status status; - - tu = file->private_data; - if (!tu->timeri) - return -EBADFD; - memset(&status, 0, sizeof(status)); - status.tstamp = tu->tstamp; - status.resolution = snd_timer_resolution(tu->timeri); - status.lost = tu->timeri->lost; - status.overrun = tu->overrun; - spin_lock_irq(&tu->qlock); - status.queue = tu->qused; - spin_unlock_irq(&tu->qlock); - if (copy_to_user(_status, &status, sizeof(status))) - return -EFAULT; - return 0; -} - -static int snd_timer_user_start(struct file *file) -{ - int err; - struct snd_timer_user *tu; - - tu = file->private_data; - if (!tu->timeri) - return -EBADFD; - snd_timer_stop(tu->timeri); - tu->timeri->lost = 0; - tu->last_resolution = 0; - return (err = snd_timer_start(tu->timeri, tu->ticks)) < 0 ? err : 0; -} - -static int snd_timer_user_stop(struct file *file) -{ - int err; - struct snd_timer_user *tu; - - tu = file->private_data; - if (!tu->timeri) - return -EBADFD; - return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0; -} - -static int snd_timer_user_continue(struct file *file) -{ - int err; - struct snd_timer_user *tu; - - tu = file->private_data; - if (!tu->timeri) - return -EBADFD; - tu->timeri->lost = 0; - return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; -} - -static int snd_timer_user_pause(struct file *file) -{ - int err; - struct snd_timer_user *tu; - - tu = file->private_data; - if (!tu->timeri) - return -EBADFD; - return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; -} - -enum { - SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20), - SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21), - SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22), - SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), -}; - -static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct snd_timer_user *tu; - void __user *argp = (void __user *)arg; - int __user *p = argp; - - tu = file->private_data; - switch (cmd) { - case SNDRV_TIMER_IOCTL_PVERSION: - return put_user(SNDRV_TIMER_VERSION, p) ? -EFAULT : 0; - case SNDRV_TIMER_IOCTL_NEXT_DEVICE: - return snd_timer_user_next_device(argp); - case SNDRV_TIMER_IOCTL_TREAD: - { - int xarg; - - mutex_lock(&tu->tread_sem); - if (tu->timeri) { /* too late */ - mutex_unlock(&tu->tread_sem); - return -EBUSY; - } - if (get_user(xarg, p)) { - mutex_unlock(&tu->tread_sem); - return -EFAULT; - } - tu->tread = xarg ? 1 : 0; - mutex_unlock(&tu->tread_sem); - return 0; - } - case SNDRV_TIMER_IOCTL_GINFO: - return snd_timer_user_ginfo(file, argp); - case SNDRV_TIMER_IOCTL_GPARAMS: - return snd_timer_user_gparams(file, argp); - case SNDRV_TIMER_IOCTL_GSTATUS: - return snd_timer_user_gstatus(file, argp); - case SNDRV_TIMER_IOCTL_SELECT: - return snd_timer_user_tselect(file, argp); - case SNDRV_TIMER_IOCTL_INFO: - return snd_timer_user_info(file, argp); - case SNDRV_TIMER_IOCTL_PARAMS: - return snd_timer_user_params(file, argp); - case SNDRV_TIMER_IOCTL_STATUS: - return snd_timer_user_status(file, argp); - case SNDRV_TIMER_IOCTL_START: - case SNDRV_TIMER_IOCTL_START_OLD: - return snd_timer_user_start(file); - case SNDRV_TIMER_IOCTL_STOP: - case SNDRV_TIMER_IOCTL_STOP_OLD: - return snd_timer_user_stop(file); - case SNDRV_TIMER_IOCTL_CONTINUE: - case SNDRV_TIMER_IOCTL_CONTINUE_OLD: - return snd_timer_user_continue(file); - case SNDRV_TIMER_IOCTL_PAUSE: - case SNDRV_TIMER_IOCTL_PAUSE_OLD: - return snd_timer_user_pause(file); - } - return -ENOTTY; -} - -static int snd_timer_user_fasync(int fd, struct file * file, int on) -{ - struct snd_timer_user *tu; - - tu = file->private_data; - return fasync_helper(fd, file, on, &tu->fasync); -} - -static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, - size_t count, loff_t *offset) -{ - struct snd_timer_user *tu; - long result = 0, unit; - int err = 0; - - tu = file->private_data; - unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read); - spin_lock_irq(&tu->qlock); - while ((long)count - result >= unit) { - while (!tu->qused) { - wait_queue_t wait; - - if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { - err = -EAGAIN; - break; - } - - set_current_state(TASK_INTERRUPTIBLE); - init_waitqueue_entry(&wait, current); - add_wait_queue(&tu->qchange_sleep, &wait); - - spin_unlock_irq(&tu->qlock); - schedule(); - spin_lock_irq(&tu->qlock); - - remove_wait_queue(&tu->qchange_sleep, &wait); - - if (signal_pending(current)) { - err = -ERESTARTSYS; - break; - } - } - - spin_unlock_irq(&tu->qlock); - if (err < 0) - goto _error; - - if (tu->tread) { - if (copy_to_user(buffer, &tu->tqueue[tu->qhead++], - sizeof(struct snd_timer_tread))) { - err = -EFAULT; - goto _error; - } - } else { - if (copy_to_user(buffer, &tu->queue[tu->qhead++], - sizeof(struct snd_timer_read))) { - err = -EFAULT; - goto _error; - } - } - - tu->qhead %= tu->queue_size; - - result += unit; - buffer += unit; - - spin_lock_irq(&tu->qlock); - tu->qused--; - } - spin_unlock_irq(&tu->qlock); - _error: - return result > 0 ? result : err; -} - -static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) -{ - unsigned int mask; - struct snd_timer_user *tu; - - tu = file->private_data; - - poll_wait(file, &tu->qchange_sleep, wait); - - mask = 0; - if (tu->qused) - mask |= POLLIN | POLLRDNORM; - - return mask; -} - -#ifdef CONFIG_COMPAT -#include "timer_compat.c" -#else -#define snd_timer_user_ioctl_compat NULL -#endif - -static const struct file_operations snd_timer_f_ops = -{ - .owner = THIS_MODULE, - .read = snd_timer_user_read, - .open = snd_timer_user_open, - .release = snd_timer_user_release, - .llseek = no_llseek, - .poll = snd_timer_user_poll, - .unlocked_ioctl = snd_timer_user_ioctl, - .compat_ioctl = snd_timer_user_ioctl_compat, - .fasync = snd_timer_user_fasync, -}; - -/* - * ENTRY functions - */ - -static int __init alsa_timer_init(void) -{ - int err; - -#ifdef SNDRV_OSS_INFO_DEV_TIMERS - snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1, - "system timer"); -#endif - - if ((err = snd_timer_register_system()) < 0) - snd_printk(KERN_ERR "unable to register system timer (%i)\n", - err); - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0, - &snd_timer_f_ops, NULL, "timer")) < 0) - snd_printk(KERN_ERR "unable to register timer device (%i)\n", - err); - snd_timer_proc_init(); - return 0; -} - -static void __exit alsa_timer_exit(void) -{ - struct list_head *p, *n; - - snd_unregister_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0); - /* unregister the system timer */ - list_for_each_safe(p, n, &snd_timer_list) { - struct snd_timer *timer = list_entry(p, struct snd_timer, device_list); - snd_timer_free(timer); - } - snd_timer_proc_done(); -#ifdef SNDRV_OSS_INFO_DEV_TIMERS - snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1); -#endif -} - -module_init(alsa_timer_init) -module_exit(alsa_timer_exit) - -EXPORT_SYMBOL(snd_timer_open); -EXPORT_SYMBOL(snd_timer_close); -EXPORT_SYMBOL(snd_timer_resolution); -EXPORT_SYMBOL(snd_timer_start); -EXPORT_SYMBOL(snd_timer_stop); -EXPORT_SYMBOL(snd_timer_continue); -EXPORT_SYMBOL(snd_timer_pause); -EXPORT_SYMBOL(snd_timer_new); -EXPORT_SYMBOL(snd_timer_notify); -EXPORT_SYMBOL(snd_timer_global_new); -EXPORT_SYMBOL(snd_timer_global_free); -EXPORT_SYMBOL(snd_timer_global_register); -EXPORT_SYMBOL(snd_timer_interrupt); diff --git a/ANDROID_3.4.5/sound/core/timer_compat.c b/ANDROID_3.4.5/sound/core/timer_compat.c deleted file mode 100644 index e05802ae..00000000 --- a/ANDROID_3.4.5/sound/core/timer_compat.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 32bit -> 64bit ioctl wrapper for timer API - * Copyright (c) by Takashi Iwai - * - * 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 - * - */ - -/* This file included from timer.c */ - -#include - -struct snd_timer_info32 { - u32 flags; - s32 card; - unsigned char id[64]; - unsigned char name[80]; - u32 reserved0; - u32 resolution; - unsigned char reserved[64]; -}; - -static int snd_timer_user_info_compat(struct file *file, - struct snd_timer_info32 __user *_info) -{ - struct snd_timer_user *tu; - struct snd_timer_info32 info; - struct snd_timer *t; - - tu = file->private_data; - if (snd_BUG_ON(!tu->timeri)) - return -ENXIO; - t = tu->timeri->timer; - if (snd_BUG_ON(!t)) - return -ENXIO; - memset(&info, 0, sizeof(info)); - info.card = t->card ? t->card->number : -1; - if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) - info.flags |= SNDRV_TIMER_FLG_SLAVE; - strlcpy(info.id, t->id, sizeof(info.id)); - strlcpy(info.name, t->name, sizeof(info.name)); - info.resolution = t->hw.resolution; - if (copy_to_user(_info, &info, sizeof(*_info))) - return -EFAULT; - return 0; -} - -struct snd_timer_status32 { - struct compat_timespec tstamp; - u32 resolution; - u32 lost; - u32 overrun; - u32 queue; - unsigned char reserved[64]; -}; - -static int snd_timer_user_status_compat(struct file *file, - struct snd_timer_status32 __user *_status) -{ - struct snd_timer_user *tu; - struct snd_timer_status status; - - tu = file->private_data; - if (snd_BUG_ON(!tu->timeri)) - return -ENXIO; - memset(&status, 0, sizeof(status)); - status.tstamp = tu->tstamp; - status.resolution = snd_timer_resolution(tu->timeri); - status.lost = tu->timeri->lost; - status.overrun = tu->overrun; - spin_lock_irq(&tu->qlock); - status.queue = tu->qused; - spin_unlock_irq(&tu->qlock); - if (copy_to_user(_status, &status, sizeof(status))) - return -EFAULT; - return 0; -} - -/* - */ - -enum { - SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), - SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), -}; - -static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) -{ - void __user *argp = compat_ptr(arg); - - switch (cmd) { - case SNDRV_TIMER_IOCTL_PVERSION: - case SNDRV_TIMER_IOCTL_TREAD: - case SNDRV_TIMER_IOCTL_GINFO: - case SNDRV_TIMER_IOCTL_GPARAMS: - case SNDRV_TIMER_IOCTL_GSTATUS: - case SNDRV_TIMER_IOCTL_SELECT: - case SNDRV_TIMER_IOCTL_PARAMS: - case SNDRV_TIMER_IOCTL_START: - case SNDRV_TIMER_IOCTL_START_OLD: - case SNDRV_TIMER_IOCTL_STOP: - case SNDRV_TIMER_IOCTL_STOP_OLD: - case SNDRV_TIMER_IOCTL_CONTINUE: - case SNDRV_TIMER_IOCTL_CONTINUE_OLD: - case SNDRV_TIMER_IOCTL_PAUSE: - case SNDRV_TIMER_IOCTL_PAUSE_OLD: - case SNDRV_TIMER_IOCTL_NEXT_DEVICE: - return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); - case SNDRV_TIMER_IOCTL_INFO32: - return snd_timer_user_info_compat(file, argp); - case SNDRV_TIMER_IOCTL_STATUS32: - return snd_timer_user_status_compat(file, argp); - } - return -ENOIOCTLCMD; -} diff --git a/ANDROID_3.4.5/sound/core/vmaster.c b/ANDROID_3.4.5/sound/core/vmaster.c deleted file mode 100644 index 85758613..00000000 --- a/ANDROID_3.4.5/sound/core/vmaster.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Virtual master and slave controls - * - * Copyright (c) 2008 by Takashi Iwai - * - * 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, version 2. - * - */ - -#include -#include -#include -#include -#include - -/* - * a subset of information returned via ctl info callback - */ -struct link_ctl_info { - snd_ctl_elem_type_t type; /* value type */ - int count; /* item count */ - int min_val, max_val; /* min, max values */ -}; - -/* - * link master - this contains a list of slave controls that are - * identical types, i.e. info returns the same value type and value - * ranges, but may have different number of counts. - * - * The master control is so far only mono volume/switch for simplicity. - * The same value will be applied to all slaves. - */ -struct link_master { - struct list_head slaves; - struct link_ctl_info info; - int val; /* the master value */ - unsigned int tlv[4]; - void (*hook)(void *private_data, int); - void *hook_private_data; -}; - -/* - * link slave - this contains a slave control element - * - * It fakes the control callbacsk with additional attenuation by the - * master control. A slave may have either one or two channels. - */ - -struct link_slave { - struct list_head list; - struct link_master *master; - struct link_ctl_info info; - int vals[2]; /* current values */ - unsigned int flags; - struct snd_kcontrol *kctl; /* original kcontrol pointer */ - struct snd_kcontrol slave; /* the copy of original control entry */ -}; - -static int slave_update(struct link_slave *slave) -{ - struct snd_ctl_elem_value *uctl; - int err, ch; - - uctl = kmalloc(sizeof(*uctl), GFP_KERNEL); - if (!uctl) - return -ENOMEM; - uctl->id = slave->slave.id; - err = slave->slave.get(&slave->slave, uctl); - for (ch = 0; ch < slave->info.count; ch++) - slave->vals[ch] = uctl->value.integer.value[ch]; - kfree(uctl); - return 0; -} - -/* get the slave ctl info and save the initial values */ -static int slave_init(struct link_slave *slave) -{ - struct snd_ctl_elem_info *uinfo; - int err; - - if (slave->info.count) { - /* already initialized */ - if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE) - return slave_update(slave); - return 0; - } - - uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); - if (!uinfo) - return -ENOMEM; - uinfo->id = slave->slave.id; - err = slave->slave.info(&slave->slave, uinfo); - if (err < 0) { - kfree(uinfo); - return err; - } - slave->info.type = uinfo->type; - slave->info.count = uinfo->count; - if (slave->info.count > 2 || - (slave->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER && - slave->info.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN)) { - snd_printk(KERN_ERR "invalid slave element\n"); - kfree(uinfo); - return -EINVAL; - } - slave->info.min_val = uinfo->value.integer.min; - slave->info.max_val = uinfo->value.integer.max; - kfree(uinfo); - - return slave_update(slave); -} - -/* initialize master volume */ -static int master_init(struct link_master *master) -{ - struct link_slave *slave; - - if (master->info.count) - return 0; /* already initialized */ - - list_for_each_entry(slave, &master->slaves, list) { - int err = slave_init(slave); - if (err < 0) - return err; - master->info = slave->info; - master->info.count = 1; /* always mono */ - /* set full volume as default (= no attenuation) */ - master->val = master->info.max_val; - if (master->hook) - master->hook(master->hook_private_data, master->val); - return 1; - } - return -ENOENT; -} - -static int slave_get_val(struct link_slave *slave, - struct snd_ctl_elem_value *ucontrol) -{ - int err, ch; - - err = slave_init(slave); - if (err < 0) - return err; - for (ch = 0; ch < slave->info.count; ch++) - ucontrol->value.integer.value[ch] = slave->vals[ch]; - return 0; -} - -static int slave_put_val(struct link_slave *slave, - struct snd_ctl_elem_value *ucontrol) -{ - int err, ch, vol; - - err = master_init(slave->master); - if (err < 0) - return err; - - switch (slave->info.type) { - case SNDRV_CTL_ELEM_TYPE_BOOLEAN: - for (ch = 0; ch < slave->info.count; ch++) - ucontrol->value.integer.value[ch] &= - !!slave->master->val; - break; - case SNDRV_CTL_ELEM_TYPE_INTEGER: - for (ch = 0; ch < slave->info.count; ch++) { - /* max master volume is supposed to be 0 dB */ - vol = ucontrol->value.integer.value[ch]; - vol += slave->master->val - slave->master->info.max_val; - if (vol < slave->info.min_val) - vol = slave->info.min_val; - else if (vol > slave->info.max_val) - vol = slave->info.max_val; - ucontrol->value.integer.value[ch] = vol; - } - break; - } - return slave->slave.put(&slave->slave, ucontrol); -} - -/* - * ctl callbacks for slaves - */ -static int slave_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct link_slave *slave = snd_kcontrol_chip(kcontrol); - return slave->slave.info(&slave->slave, uinfo); -} - -static int slave_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct link_slave *slave = snd_kcontrol_chip(kcontrol); - return slave_get_val(slave, ucontrol); -} - -static int slave_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct link_slave *slave = snd_kcontrol_chip(kcontrol); - int err, ch, changed = 0; - - err = slave_init(slave); - if (err < 0) - return err; - for (ch = 0; ch < slave->info.count; ch++) { - if (slave->vals[ch] != ucontrol->value.integer.value[ch]) { - changed = 1; - slave->vals[ch] = ucontrol->value.integer.value[ch]; - } - } - if (!changed) - return 0; - return slave_put_val(slave, ucontrol); -} - -static int slave_tlv_cmd(struct snd_kcontrol *kcontrol, - int op_flag, unsigned int size, - unsigned int __user *tlv) -{ - struct link_slave *slave = snd_kcontrol_chip(kcontrol); - /* FIXME: this assumes that the max volume is 0 dB */ - return slave->slave.tlv.c(&slave->slave, op_flag, size, tlv); -} - -static void slave_free(struct snd_kcontrol *kcontrol) -{ - struct link_slave *slave = snd_kcontrol_chip(kcontrol); - if (slave->slave.private_free) - slave->slave.private_free(&slave->slave); - if (slave->master) - list_del(&slave->list); - kfree(slave); -} - -/* - * Add a slave control to the group with the given master control - * - * All slaves must be the same type (returning the same information - * via info callback). The function doesn't check it, so it's your - * responsibility. - * - * Also, some additional limitations: - * - at most two channels - * - logarithmic volume control (dB level), no linear volume - * - master can only attenuate the volume, no gain - */ -int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, - unsigned int flags) -{ - struct link_master *master_link = snd_kcontrol_chip(master); - struct link_slave *srec; - - srec = kzalloc(sizeof(*srec) + - slave->count * sizeof(*slave->vd), GFP_KERNEL); - if (!srec) - return -ENOMEM; - srec->kctl = slave; - srec->slave = *slave; - memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd)); - srec->master = master_link; - srec->flags = flags; - - /* override callbacks */ - slave->info = slave_info; - slave->get = slave_get; - slave->put = slave_put; - if (slave->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) - slave->tlv.c = slave_tlv_cmd; - slave->private_data = srec; - slave->private_free = slave_free; - - list_add_tail(&srec->list, &master_link->slaves); - return 0; -} -EXPORT_SYMBOL(_snd_ctl_add_slave); - -/* - * ctl callbacks for master controls - */ -static int master_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct link_master *master = snd_kcontrol_chip(kcontrol); - int ret; - - ret = master_init(master); - if (ret < 0) - return ret; - uinfo->type = master->info.type; - uinfo->count = master->info.count; - uinfo->value.integer.min = master->info.min_val; - uinfo->value.integer.max = master->info.max_val; - return 0; -} - -static int master_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct link_master *master = snd_kcontrol_chip(kcontrol); - int err = master_init(master); - if (err < 0) - return err; - ucontrol->value.integer.value[0] = master->val; - return 0; -} - -static int master_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct link_master *master = snd_kcontrol_chip(kcontrol); - struct link_slave *slave; - struct snd_ctl_elem_value *uval; - int err, old_val; - - err = master_init(master); - if (err < 0) - return err; - old_val = master->val; - if (ucontrol->value.integer.value[0] == old_val) - return 0; - - uval = kmalloc(sizeof(*uval), GFP_KERNEL); - if (!uval) - return -ENOMEM; - list_for_each_entry(slave, &master->slaves, list) { - master->val = old_val; - uval->id = slave->slave.id; - slave_get_val(slave, uval); - master->val = ucontrol->value.integer.value[0]; - slave_put_val(slave, uval); - } - kfree(uval); - if (master->hook && !err) - master->hook(master->hook_private_data, master->val); - return 1; -} - -static void master_free(struct snd_kcontrol *kcontrol) -{ - struct link_master *master = snd_kcontrol_chip(kcontrol); - struct link_slave *slave, *n; - - /* free all slave links and retore the original slave kctls */ - list_for_each_entry_safe(slave, n, &master->slaves, list) { - struct snd_kcontrol *sctl = slave->kctl; - struct list_head olist = sctl->list; - memcpy(sctl, &slave->slave, sizeof(*sctl)); - memcpy(sctl->vd, slave->slave.vd, - sctl->count * sizeof(*sctl->vd)); - sctl->list = olist; /* keep the current linked-list */ - kfree(slave); - } - kfree(master); -} - - -/** - * snd_ctl_make_virtual_master - Create a virtual master control - * @name: name string of the control element to create - * @tlv: optional TLV int array for dB information - * - * Creates a virtual matster control with the given name string. - * Returns the created control element, or NULL for errors (ENOMEM). - * - * After creating a vmaster element, you can add the slave controls - * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached(). - * - * The optional argument @tlv can be used to specify the TLV information - * for dB scale of the master control. It should be a single element - * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or - * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB. - */ -struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, - const unsigned int *tlv) -{ - struct link_master *master; - struct snd_kcontrol *kctl; - struct snd_kcontrol_new knew; - - memset(&knew, 0, sizeof(knew)); - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.name = name; - knew.info = master_info; - - master = kzalloc(sizeof(*master), GFP_KERNEL); - if (!master) - return NULL; - INIT_LIST_HEAD(&master->slaves); - - kctl = snd_ctl_new1(&knew, master); - if (!kctl) { - kfree(master); - return NULL; - } - /* override some callbacks */ - kctl->info = master_info; - kctl->get = master_get; - kctl->put = master_put; - kctl->private_free = master_free; - - /* additional (constant) TLV read */ - if (tlv && - (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE || - tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX || - tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) { - kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - memcpy(master->tlv, tlv, sizeof(master->tlv)); - kctl->tlv.p = master->tlv; - } - - return kctl; -} -EXPORT_SYMBOL(snd_ctl_make_virtual_master); - -/** - * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control - * @kcontrol: vmaster kctl element - * @hook: the hook function - * @private_data: the private_data pointer to be saved - * - * Adds the given hook to the vmaster control element so that it's called - * at each time when the value is changed. - */ -int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol, - void (*hook)(void *private_data, int), - void *private_data) -{ - struct link_master *master = snd_kcontrol_chip(kcontrol); - master->hook = hook; - master->hook_private_data = private_data; - return 0; -} -EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook); - -/** - * snd_ctl_sync_vmaster_hook - Sync the vmaster hook - * @kcontrol: vmaster kctl element - * - * Call the hook function to synchronize with the current value of the given - * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't - * exist. - */ -void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol) -{ - struct link_master *master; - if (!kcontrol) - return; - master = snd_kcontrol_chip(kcontrol); - if (master->hook) - master->hook(master->hook_private_data, master->val); -} -EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook); diff --git a/ANDROID_3.4.5/sound/drivers/Kconfig b/ANDROID_3.4.5/sound/drivers/Kconfig deleted file mode 100644 index fe5ae09f..00000000 --- a/ANDROID_3.4.5/sound/drivers/Kconfig +++ /dev/null @@ -1,223 +0,0 @@ -config SND_MPU401_UART - tristate - select SND_RAWMIDI - -config SND_OPL3_LIB - tristate - select SND_TIMER - select SND_HWDEP - -config SND_OPL4_LIB - tristate - select SND_TIMER - select SND_HWDEP - -config SND_VX_LIB - tristate - select SND_HWDEP - select SND_PCM - -config SND_AC97_CODEC - tristate - select SND_PCM - select AC97_BUS - select SND_VMASTER - -menuconfig SND_DRIVERS - bool "Generic sound devices" - default y - help - Support for generic sound devices. - -if SND_DRIVERS - -config SND_PCSP - tristate "PC-Speaker support (READ HELP!)" - depends on PCSPKR_PLATFORM && X86 && HIGH_RES_TIMERS - depends on INPUT - depends on EXPERIMENTAL - select SND_PCM - help - If you don't have a sound card in your computer, you can include a - driver for the PC speaker which allows it to act like a primitive - sound card. - This driver also replaces the pcspkr driver for beeps. - - You can compile this as a module which will be called snd-pcsp. - - WARNING: if you already have a soundcard, enabling this - driver may lead to a problem. Namely, it may get loaded - before the other sound driver of yours, making the - pc-speaker a default sound device. Which is likely not - what you want. To make this driver play nicely with other - sound driver, you can add this in a configuration file under - /etc/modprobe.d/ directory: - options snd-pcsp index=2 - - You don't need this driver if you only want your pc-speaker to beep. - You don't need this driver if you have a tablet piezo beeper - in your PC instead of the real speaker. - - Say N if you have a sound card. - Say M if you don't. - Say Y only if you really know what you do. - -config SND_DUMMY - tristate "Dummy (/dev/null) soundcard" - select SND_PCM - help - Say Y here to include the dummy driver. This driver does - nothing, but emulates various mixer controls and PCM devices. - - You don't need this unless you're testing the hardware support - of programs using the ALSA API. - - To compile this driver as a module, choose M here: the module - will be called snd-dummy. - -config SND_ALOOP - tristate "Generic loopback driver (PCM)" - select SND_PCM - help - Say 'Y' or 'M' to include support for the PCM loopback device. - This module returns played samples back to the user space using - the standard ALSA PCM device. The devices are routed 0->1 and - 1->0, where first number is the playback PCM device and second - number is the capture device. Module creates two PCM devices and - configured number of substreams (see the pcm_substreams module - parameter). - - The looback device allow time sychronization with an external - timing source using the time shift universal control (+-20% - of system time). - - To compile this driver as a module, choose M here: the module - will be called snd-aloop. - -config SND_VIRMIDI - tristate "Virtual MIDI soundcard" - depends on SND_SEQUENCER - select SND_TIMER - select SND_RAWMIDI - help - Say Y here to include the virtual MIDI driver. This driver - allows to connect applications using raw MIDI devices to - sequencer clients. - - If you don't know what MIDI is, say N here. - - To compile this driver as a module, choose M here: the module - will be called snd-virmidi. - -config SND_MTPAV - tristate "MOTU MidiTimePiece AV multiport MIDI" - select SND_RAWMIDI - help - To use a MOTU MidiTimePiece AV multiport MIDI adapter - connected to the parallel port, say Y here and make sure that - the standard parallel port driver isn't used for the port. - - To compile this driver as a module, choose M here: the module - will be called snd-mtpav. - -config SND_MTS64 - tristate "ESI Miditerminal 4140 driver" - depends on PARPORT - select SND_RAWMIDI - help - The ESI Miditerminal 4140 is a 4 In 4 Out MIDI Interface with - additional SMPTE Timecode capabilities for the parallel port. - - Say 'Y' to include support for this device. - - To compile this driver as a module, chose 'M' here: the module - will be called snd-mts64. - -config SND_SERIAL_U16550 - tristate "UART16550 serial MIDI driver" - select SND_RAWMIDI - help - To include support for MIDI serial port interfaces, say Y here - and read . - This driver works with serial UARTs 16550 and better. - - This driver accesses the serial port hardware directly, so - make sure that the standard serial driver isn't used or - deactivated with setserial before loading this driver. - - To compile this driver as a module, choose M here: the module - will be called snd-serial-u16550. - -config SND_MPU401 - tristate "Generic MPU-401 UART driver" - select SND_MPU401_UART - help - Say Y here to include support for MIDI ports compatible with - the Roland MPU-401 interface in UART mode. - - To compile this driver as a module, choose M here: the module - will be called snd-mpu401. - -config SND_PORTMAN2X4 - tristate "Portman 2x4 driver" - depends on PARPORT - select SND_RAWMIDI - help - Say Y here to include support for Midiman Portman 2x4 parallel - port MIDI device. - - To compile this driver as a module, choose M here: the module - will be called snd-portman2x4. - -config SND_ML403_AC97CR - tristate "Xilinx ML403 AC97 Controller Reference" - depends on XILINX_VIRTEX - select SND_AC97_CODEC - help - Say Y here to include support for the - opb_ac97_controller_ref_v1_00_a ip core found in Xilinx's ML403 - reference design. - - To compile this driver as a module, choose M here: the module - will be called snd-ml403_ac97cr. - -config SND_AC97_POWER_SAVE - bool "AC97 Power-Saving Mode" - depends on SND_AC97_CODEC - default n - help - Say Y here to enable the aggressive power-saving support of - AC97 codecs. In this mode, the power-mode is dynamically - controlled at each open/close. - - The mode is activated by passing 'power_save=X' to the - snd-ac97-codec driver module, where 'X' is the time-out - value, a nonnegative integer that specifies how many - seconds of idle time the driver must count before it may - put the AC97 into power-save mode; a value of 0 (zero) - disables the use of this power-save mode. - - After the snd-ac97-codec driver module has been loaded, - the 'power_save' parameter can be set via sysfs as follows: - - echo 10 > /sys/module/snd_ac97_codec/parameters/power_save - - In this case, the time-out is set to 10 seconds; setting - the time-out to 1 second (the minimum activation value) - isn't recommended because many applications try to reopen - the device frequently. A value of 10 seconds would be a - good choice for normal operations. - - See Documentation/sound/alsa/powersave.txt for more details. - -config SND_AC97_POWER_SAVE_DEFAULT - int "Default time-out for AC97 power-save mode" - depends on SND_AC97_POWER_SAVE - default 0 - help - The default time-out value in seconds for AC97 automatic - power-save mode. 0 means to disable the power-save mode. - - See SND_AC97_POWER_SAVE for more details. - -endif # SND_DRIVERS diff --git a/ANDROID_3.4.5/sound/drivers/Makefile b/ANDROID_3.4.5/sound/drivers/Makefile deleted file mode 100644 index 1a8440c8..00000000 --- a/ANDROID_3.4.5/sound/drivers/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-dummy-objs := dummy.o -snd-aloop-objs := aloop.o -snd-mtpav-objs := mtpav.o -snd-mts64-objs := mts64.o -snd-portman2x4-objs := portman2x4.o -snd-serial-u16550-objs := serial-u16550.o -snd-virmidi-objs := virmidi.o -snd-ml403-ac97cr-objs := ml403-ac97cr.o pcm-indirect2.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_DUMMY) += snd-dummy.o -obj-$(CONFIG_SND_ALOOP) += snd-aloop.o -obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o -obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o -obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o -obj-$(CONFIG_SND_MTS64) += snd-mts64.o -obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o -obj-$(CONFIG_SND_ML403_AC97CR) += snd-ml403-ac97cr.o - -obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ pcsp/ diff --git a/ANDROID_3.4.5/sound/drivers/aloop.c b/ANDROID_3.4.5/sound/drivers/aloop.c deleted file mode 100644 index ad079b63..00000000 --- a/ANDROID_3.4.5/sound/drivers/aloop.c +++ /dev/null @@ -1,1258 +0,0 @@ -/* - * Loopback soundcard - * - * Original code: - * Copyright (c) by Jaroslav Kysela - * - * More accurate positioning and full-duplex support: - * Copyright (c) Ahmet İnan - * - * Major (almost complete) rewrite: - * Copyright (c) by Takashi Iwai - * - * A next major update in 2010 (separate timers for playback and capture): - * Copyright (c) Jaroslav Kysela - * - * 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 -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("A loopback soundcard"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}"); - -#define MAX_PCM_SUBSTREAMS 8 - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; -static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; -static int pcm_notify[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for loopback soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for loopback soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this loopback soundcard."); -module_param_array(pcm_substreams, int, NULL, 0444); -MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-8) for loopback driver."); -module_param_array(pcm_notify, int, NULL, 0444); -MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels changes."); - -#define NO_PITCH 100000 - -struct loopback_pcm; - -struct loopback_cable { - spinlock_t lock; - struct loopback_pcm *streams[2]; - struct snd_pcm_hardware hw; - /* flags */ - unsigned int valid; - unsigned int running; - unsigned int pause; -}; - -struct loopback_setup { - unsigned int notify: 1; - unsigned int rate_shift; - unsigned int format; - unsigned int rate; - unsigned int channels; - struct snd_ctl_elem_id active_id; - struct snd_ctl_elem_id format_id; - struct snd_ctl_elem_id rate_id; - struct snd_ctl_elem_id channels_id; -}; - -struct loopback { - struct snd_card *card; - struct mutex cable_lock; - struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2]; - struct snd_pcm *pcm[2]; - struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2]; -}; - -struct loopback_pcm { - struct loopback *loopback; - struct snd_pcm_substream *substream; - struct loopback_cable *cable; - unsigned int pcm_buffer_size; - unsigned int buf_pos; /* position in buffer */ - unsigned int silent_size; - /* PCM parameters */ - unsigned int pcm_period_size; - unsigned int pcm_bps; /* bytes per second */ - unsigned int pcm_salign; /* bytes per sample * channels */ - unsigned int pcm_rate_shift; /* rate shift value */ - /* flags */ - unsigned int period_update_pending :1; - /* timer stuff */ - unsigned int irq_pos; /* fractional IRQ position */ - unsigned int period_size_frac; - unsigned long last_jiffies; - struct timer_list timer; -}; - -static struct platform_device *devices[SNDRV_CARDS]; - -static inline unsigned int byte_pos(struct loopback_pcm *dpcm, unsigned int x) -{ - if (dpcm->pcm_rate_shift == NO_PITCH) { - x /= HZ; - } else { - x = div_u64(NO_PITCH * (unsigned long long)x, - HZ * (unsigned long long)dpcm->pcm_rate_shift); - } - return x - (x % dpcm->pcm_salign); -} - -static inline unsigned int frac_pos(struct loopback_pcm *dpcm, unsigned int x) -{ - if (dpcm->pcm_rate_shift == NO_PITCH) { /* no pitch */ - return x * HZ; - } else { - x = div_u64(dpcm->pcm_rate_shift * (unsigned long long)x * HZ, - NO_PITCH); - } - return x; -} - -static inline struct loopback_setup *get_setup(struct loopback_pcm *dpcm) -{ - int device = dpcm->substream->pstr->pcm->device; - - if (dpcm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - device ^= 1; - return &dpcm->loopback->setup[dpcm->substream->number][device]; -} - -static inline unsigned int get_notify(struct loopback_pcm *dpcm) -{ - return get_setup(dpcm)->notify; -} - -static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm) -{ - return get_setup(dpcm)->rate_shift; -} - -static void loopback_timer_start(struct loopback_pcm *dpcm) -{ - unsigned long tick; - unsigned int rate_shift = get_rate_shift(dpcm); - - if (rate_shift != dpcm->pcm_rate_shift) { - dpcm->pcm_rate_shift = rate_shift; - dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); - } - if (dpcm->period_size_frac <= dpcm->irq_pos) { - dpcm->irq_pos %= dpcm->period_size_frac; - dpcm->period_update_pending = 1; - } - tick = dpcm->period_size_frac - dpcm->irq_pos; - tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; - dpcm->timer.expires = jiffies + tick; - add_timer(&dpcm->timer); -} - -static inline void loopback_timer_stop(struct loopback_pcm *dpcm) -{ - del_timer(&dpcm->timer); - dpcm->timer.expires = 0; -} - -#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) -#define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE) -#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE) - -static int loopback_check_format(struct loopback_cable *cable, int stream) -{ - struct snd_pcm_runtime *runtime, *cruntime; - struct loopback_setup *setup; - struct snd_card *card; - int check; - - if (cable->valid != CABLE_VALID_BOTH) { - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - goto __notify; - return 0; - } - runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]-> - substream->runtime; - cruntime = cable->streams[SNDRV_PCM_STREAM_CAPTURE]-> - substream->runtime; - check = runtime->format != cruntime->format || - runtime->rate != cruntime->rate || - runtime->channels != cruntime->channels; - if (!check) - return 0; - if (stream == SNDRV_PCM_STREAM_CAPTURE) { - return -EIO; - } else { - snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]-> - substream, SNDRV_PCM_STATE_DRAINING); - __notify: - runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]-> - substream->runtime; - setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]); - card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card; - if (setup->format != runtime->format) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &setup->format_id); - setup->format = runtime->format; - } - if (setup->rate != runtime->rate) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &setup->rate_id); - setup->rate = runtime->rate; - } - if (setup->channels != runtime->channels) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &setup->channels_id); - setup->channels = runtime->channels; - } - } - return 0; -} - -static void loopback_active_notify(struct loopback_pcm *dpcm) -{ - snd_ctl_notify(dpcm->loopback->card, - SNDRV_CTL_EVENT_MASK_VALUE, - &get_setup(dpcm)->active_id); -} - -static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - struct loopback_cable *cable = dpcm->cable; - int err, stream = 1 << substream->stream; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - err = loopback_check_format(cable, substream->stream); - if (err < 0) - return err; - dpcm->last_jiffies = jiffies; - dpcm->pcm_rate_shift = 0; - spin_lock(&cable->lock); - cable->running |= stream; - cable->pause &= ~stream; - spin_unlock(&cable->lock); - loopback_timer_start(dpcm); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - loopback_active_notify(dpcm); - break; - case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&cable->lock); - cable->running &= ~stream; - cable->pause &= ~stream; - spin_unlock(&cable->lock); - loopback_timer_stop(dpcm); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - loopback_active_notify(dpcm); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock(&cable->lock); - cable->pause |= stream; - spin_unlock(&cable->lock); - loopback_timer_stop(dpcm); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock(&cable->lock); - dpcm->last_jiffies = jiffies; - cable->pause &= ~stream; - spin_unlock(&cable->lock); - loopback_timer_start(dpcm); - break; - default: - return -EINVAL; - } - return 0; -} - -static void params_change_substream(struct loopback_pcm *dpcm, - struct snd_pcm_runtime *runtime) -{ - struct snd_pcm_runtime *dst_runtime; - - if (dpcm == NULL || dpcm->substream == NULL) - return; - dst_runtime = dpcm->substream->runtime; - if (dst_runtime == NULL) - return; - dst_runtime->hw = dpcm->cable->hw; -} - -static void params_change(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - struct loopback_cable *cable = dpcm->cable; - - cable->hw.formats = (1ULL << runtime->format); - cable->hw.rate_min = runtime->rate; - cable->hw.rate_max = runtime->rate; - cable->hw.channels_min = runtime->channels; - cable->hw.channels_max = runtime->channels; - params_change_substream(cable->streams[SNDRV_PCM_STREAM_PLAYBACK], - runtime); - params_change_substream(cable->streams[SNDRV_PCM_STREAM_CAPTURE], - runtime); -} - -static int loopback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - struct loopback_cable *cable = dpcm->cable; - int bps, salign; - - salign = (snd_pcm_format_width(runtime->format) * - runtime->channels) / 8; - bps = salign * runtime->rate; - if (bps <= 0 || salign <= 0) - return -EINVAL; - - dpcm->buf_pos = 0; - dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size); - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - /* clear capture buffer */ - dpcm->silent_size = dpcm->pcm_buffer_size; - snd_pcm_format_set_silence(runtime->format, runtime->dma_area, - runtime->buffer_size * runtime->channels); - } - - dpcm->irq_pos = 0; - dpcm->period_update_pending = 0; - dpcm->pcm_bps = bps; - dpcm->pcm_salign = salign; - dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size); - - mutex_lock(&dpcm->loopback->cable_lock); - if (!(cable->valid & ~(1 << substream->stream)) || - (get_setup(dpcm)->notify && - substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) - params_change(substream); - cable->valid |= 1 << substream->stream; - mutex_unlock(&dpcm->loopback->cable_lock); - - return 0; -} - -static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes) -{ - struct snd_pcm_runtime *runtime = dpcm->substream->runtime; - char *dst = runtime->dma_area; - unsigned int dst_off = dpcm->buf_pos; - - if (dpcm->silent_size >= dpcm->pcm_buffer_size) - return; - if (dpcm->silent_size + bytes > dpcm->pcm_buffer_size) - bytes = dpcm->pcm_buffer_size - dpcm->silent_size; - - for (;;) { - unsigned int size = bytes; - if (dst_off + size > dpcm->pcm_buffer_size) - size = dpcm->pcm_buffer_size - dst_off; - snd_pcm_format_set_silence(runtime->format, dst + dst_off, - bytes_to_frames(runtime, size) * - runtime->channels); - dpcm->silent_size += size; - bytes -= size; - if (!bytes) - break; - dst_off = 0; - } -} - -static void copy_play_buf(struct loopback_pcm *play, - struct loopback_pcm *capt, - unsigned int bytes) -{ - struct snd_pcm_runtime *runtime = play->substream->runtime; - char *src = runtime->dma_area; - char *dst = capt->substream->runtime->dma_area; - unsigned int src_off = play->buf_pos; - unsigned int dst_off = capt->buf_pos; - unsigned int clear_bytes = 0; - - /* check if playback is draining, trim the capture copy size - * when our pointer is at the end of playback ring buffer */ - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && - snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) { - snd_pcm_uframes_t appl_ptr, appl_ptr1, diff; - appl_ptr = appl_ptr1 = runtime->control->appl_ptr; - appl_ptr1 -= appl_ptr1 % runtime->buffer_size; - appl_ptr1 += play->buf_pos / play->pcm_salign; - if (appl_ptr < appl_ptr1) - appl_ptr1 -= runtime->buffer_size; - diff = (appl_ptr - appl_ptr1) * play->pcm_salign; - if (diff < bytes) { - clear_bytes = bytes - diff; - bytes = diff; - } - } - - for (;;) { - unsigned int size = bytes; - if (src_off + size > play->pcm_buffer_size) - size = play->pcm_buffer_size - src_off; - if (dst_off + size > capt->pcm_buffer_size) - size = capt->pcm_buffer_size - dst_off; - memcpy(dst + dst_off, src + src_off, size); - capt->silent_size = 0; - bytes -= size; - if (!bytes) - break; - src_off = (src_off + size) % play->pcm_buffer_size; - dst_off = (dst_off + size) % capt->pcm_buffer_size; - } - - if (clear_bytes > 0) { - clear_capture_buf(capt, clear_bytes); - capt->silent_size = 0; - } -} - -#define BYTEPOS_UPDATE_POSONLY 0 -#define BYTEPOS_UPDATE_CLEAR 1 -#define BYTEPOS_UPDATE_COPY 2 - -static void loopback_bytepos_update(struct loopback_pcm *dpcm, - unsigned int delta, - unsigned int cmd) -{ - unsigned int count; - unsigned long last_pos; - - last_pos = byte_pos(dpcm, dpcm->irq_pos); - dpcm->irq_pos += delta * dpcm->pcm_bps; - count = byte_pos(dpcm, dpcm->irq_pos) - last_pos; - if (!count) - return; - if (cmd == BYTEPOS_UPDATE_CLEAR) - clear_capture_buf(dpcm, count); - else if (cmd == BYTEPOS_UPDATE_COPY) - copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK], - dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE], - count); - dpcm->buf_pos += count; - dpcm->buf_pos %= dpcm->pcm_buffer_size; - if (dpcm->irq_pos >= dpcm->period_size_frac) { - dpcm->irq_pos %= dpcm->period_size_frac; - dpcm->period_update_pending = 1; - } -} - -static unsigned int loopback_pos_update(struct loopback_cable *cable) -{ - struct loopback_pcm *dpcm_play = - cable->streams[SNDRV_PCM_STREAM_PLAYBACK]; - struct loopback_pcm *dpcm_capt = - cable->streams[SNDRV_PCM_STREAM_CAPTURE]; - unsigned long delta_play = 0, delta_capt = 0; - unsigned int running; - unsigned long flags; - - spin_lock_irqsave(&cable->lock, flags); - running = cable->running ^ cable->pause; - if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { - delta_play = jiffies - dpcm_play->last_jiffies; - dpcm_play->last_jiffies += delta_play; - } - - if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) { - delta_capt = jiffies - dpcm_capt->last_jiffies; - dpcm_capt->last_jiffies += delta_capt; - } - - if (delta_play == 0 && delta_capt == 0) - goto unlock; - - if (delta_play > delta_capt) { - loopback_bytepos_update(dpcm_play, delta_play - delta_capt, - BYTEPOS_UPDATE_POSONLY); - delta_play = delta_capt; - } else if (delta_play < delta_capt) { - loopback_bytepos_update(dpcm_capt, delta_capt - delta_play, - BYTEPOS_UPDATE_CLEAR); - delta_capt = delta_play; - } - - if (delta_play == 0 && delta_capt == 0) - goto unlock; - - /* note delta_capt == delta_play at this moment */ - loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); - loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); - unlock: - spin_unlock_irqrestore(&cable->lock, flags); - return running; -} - -static void loopback_timer_function(unsigned long data) -{ - struct loopback_pcm *dpcm = (struct loopback_pcm *)data; - unsigned int running; - - running = loopback_pos_update(dpcm->cable); - if (running & (1 << dpcm->substream->stream)) { - loopback_timer_start(dpcm); - if (dpcm->period_update_pending) { - dpcm->period_update_pending = 0; - snd_pcm_period_elapsed(dpcm->substream); - } - } -} - -static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - - loopback_pos_update(dpcm->cable); - return bytes_to_frames(runtime, dpcm->buf_pos); -} - -static struct snd_pcm_hardware loopback_pcm_hardware = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | - SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 32, - .buffer_bytes_max = 2 * 1024 * 1024, - .period_bytes_min = 64, - /* note check overflow in frac_pos() using pcm_rate_shift before - changing period_bytes_max value */ - .period_bytes_max = 1024 * 1024, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static void loopback_runtime_free(struct snd_pcm_runtime *runtime) -{ - struct loopback_pcm *dpcm = runtime->private_data; - kfree(dpcm); -} - -static int loopback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(params)); -} - -static int loopback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback_pcm *dpcm = runtime->private_data; - struct loopback_cable *cable = dpcm->cable; - - mutex_lock(&dpcm->loopback->cable_lock); - cable->valid &= ~(1 << substream->stream); - mutex_unlock(&dpcm->loopback->cable_lock); - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static unsigned int get_cable_index(struct snd_pcm_substream *substream) -{ - if (!substream->pcm->device) - return substream->stream; - else - return !substream->stream; -} - -static int rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - - struct snd_pcm_hardware *hw = rule->private; - struct snd_mask *maskp = hw_param_mask(params, rule->var); - - maskp->bits[0] &= (u_int32_t)hw->formats; - maskp->bits[1] &= (u_int32_t)(hw->formats >> 32); - memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */ - if (! maskp->bits[0] && ! maskp->bits[1]) - return -EINVAL; - return 0; -} - -static int rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pcm_hardware *hw = rule->private; - struct snd_interval t; - - t.min = hw->rate_min; - t.max = hw->rate_max; - t.openmin = t.openmax = 0; - t.integer = 0; - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -static int rule_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pcm_hardware *hw = rule->private; - struct snd_interval t; - - t.min = hw->channels_min; - t.max = hw->channels_max; - t.openmin = t.openmax = 0; - t.integer = 0; - return snd_interval_refine(hw_param_interval(params, rule->var), &t); -} - -static int loopback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct loopback *loopback = substream->private_data; - struct loopback_pcm *dpcm; - struct loopback_cable *cable; - int err = 0; - int dev = get_cable_index(substream); - - mutex_lock(&loopback->cable_lock); - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (!dpcm) { - err = -ENOMEM; - goto unlock; - } - dpcm->loopback = loopback; - dpcm->substream = substream; - setup_timer(&dpcm->timer, loopback_timer_function, - (unsigned long)dpcm); - - cable = loopback->cables[substream->number][dev]; - if (!cable) { - cable = kzalloc(sizeof(*cable), GFP_KERNEL); - if (!cable) { - kfree(dpcm); - err = -ENOMEM; - goto unlock; - } - spin_lock_init(&cable->lock); - cable->hw = loopback_pcm_hardware; - loopback->cables[substream->number][dev] = cable; - } - dpcm->cable = cable; - cable->streams[substream->stream] = dpcm; - - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - - /* use dynamic rules based on actual runtime->hw values */ - /* note that the default rules created in the PCM midlevel code */ - /* are cached -> they do not reflect the actual state */ - err = snd_pcm_hw_rule_add(runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - rule_format, &runtime->hw, - SNDRV_PCM_HW_PARAM_FORMAT, -1); - if (err < 0) - goto unlock; - err = snd_pcm_hw_rule_add(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - rule_rate, &runtime->hw, - SNDRV_PCM_HW_PARAM_RATE, -1); - if (err < 0) - goto unlock; - err = snd_pcm_hw_rule_add(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - rule_channels, &runtime->hw, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - if (err < 0) - goto unlock; - - runtime->private_data = dpcm; - runtime->private_free = loopback_runtime_free; - if (get_notify(dpcm)) - runtime->hw = loopback_pcm_hardware; - else - runtime->hw = cable->hw; - unlock: - mutex_unlock(&loopback->cable_lock); - return err; -} - -static int loopback_close(struct snd_pcm_substream *substream) -{ - struct loopback *loopback = substream->private_data; - struct loopback_pcm *dpcm = substream->runtime->private_data; - struct loopback_cable *cable; - int dev = get_cable_index(substream); - - loopback_timer_stop(dpcm); - mutex_lock(&loopback->cable_lock); - cable = loopback->cables[substream->number][dev]; - if (cable->streams[!substream->stream]) { - /* other stream is still alive */ - cable->streams[substream->stream] = NULL; - } else { - /* free the cable */ - loopback->cables[substream->number][dev] = NULL; - kfree(cable); - } - mutex_unlock(&loopback->cable_lock); - return 0; -} - -static struct snd_pcm_ops loopback_playback_ops = { - .open = loopback_open, - .close = loopback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = loopback_hw_params, - .hw_free = loopback_hw_free, - .prepare = loopback_prepare, - .trigger = loopback_trigger, - .pointer = loopback_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static struct snd_pcm_ops loopback_capture_ops = { - .open = loopback_open, - .close = loopback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = loopback_hw_params, - .hw_free = loopback_hw_free, - .prepare = loopback_prepare, - .trigger = loopback_trigger, - .pointer = loopback_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static int __devinit loopback_pcm_new(struct loopback *loopback, - int device, int substreams) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(loopback->card, "Loopback PCM", device, - substreams, substreams, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_capture_ops); - - pcm->private_data = loopback; - pcm->info_flags = 0; - strcpy(pcm->name, "Loopback PCM"); - - loopback->pcm[device] = pcm; - return 0; -} - -static int loopback_rate_shift_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 80000; - uinfo->value.integer.max = 120000; - uinfo->value.integer.step = 1; - return 0; -} - -static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].rate_shift; - return 0; -} - -static int loopback_rate_shift_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.integer.value[0]; - if (val < 80000) - val = 80000; - if (val > 120000) - val = 120000; - mutex_lock(&loopback->cable_lock); - if (val != loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].rate_shift) { - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].rate_shift = val; - change = 1; - } - mutex_unlock(&loopback->cable_lock); - return change; -} - -static int loopback_notify_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].notify; - return 0; -} - -static int loopback_notify_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.integer.value[0] ? 1 : 0; - if (val != loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].notify) { - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].notify = val; - change = 1; - } - return change; -} - -static int loopback_active_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - struct loopback_cable *cable = loopback->cables - [kcontrol->id.subdevice][kcontrol->id.device ^ 1]; - unsigned int val = 0; - - if (cable != NULL) - val = (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? - 1 : 0; - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int loopback_format_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST; - uinfo->value.integer.step = 1; - return 0; -} - -static int loopback_format_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].format; - return 0; -} - -static int loopback_rate_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 192000; - uinfo->value.integer.step = 1; - return 0; -} - -static int loopback_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].rate; - return 0; -} - -static int loopback_channels_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 1; - uinfo->value.integer.max = 1024; - uinfo->value.integer.step = 1; - return 0; -} - -static int loopback_channels_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct loopback *loopback = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - loopback->setup[kcontrol->id.subdevice] - [kcontrol->id.device].channels; - return 0; -} - -static struct snd_kcontrol_new loopback_controls[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Rate Shift 100000", - .info = loopback_rate_shift_info, - .get = loopback_rate_shift_get, - .put = loopback_rate_shift_put, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Notify", - .info = snd_ctl_boolean_mono_info, - .get = loopback_notify_get, - .put = loopback_notify_put, -}, -#define ACTIVE_IDX 2 -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Slave Active", - .info = snd_ctl_boolean_mono_info, - .get = loopback_active_get, -}, -#define FORMAT_IDX 3 -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Slave Format", - .info = loopback_format_info, - .get = loopback_format_get -}, -#define RATE_IDX 4 -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Slave Rate", - .info = loopback_rate_info, - .get = loopback_rate_get -}, -#define CHANNELS_IDX 5 -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Slave Channels", - .info = loopback_channels_info, - .get = loopback_channels_get -} -}; - -static int __devinit loopback_mixer_new(struct loopback *loopback, int notify) -{ - struct snd_card *card = loopback->card; - struct snd_pcm *pcm; - struct snd_kcontrol *kctl; - struct loopback_setup *setup; - int err, dev, substr, substr_count, idx; - - strcpy(card->mixername, "Loopback Mixer"); - for (dev = 0; dev < 2; dev++) { - pcm = loopback->pcm[dev]; - substr_count = - pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count; - for (substr = 0; substr < substr_count; substr++) { - setup = &loopback->setup[substr][dev]; - setup->notify = notify; - setup->rate_shift = NO_PITCH; - setup->format = SNDRV_PCM_FORMAT_S16_LE; - setup->rate = 48000; - setup->channels = 2; - for (idx = 0; idx < ARRAY_SIZE(loopback_controls); - idx++) { - kctl = snd_ctl_new1(&loopback_controls[idx], - loopback); - if (!kctl) - return -ENOMEM; - kctl->id.device = dev; - kctl->id.subdevice = substr; - switch (idx) { - case ACTIVE_IDX: - setup->active_id = kctl->id; - break; - case FORMAT_IDX: - setup->format_id = kctl->id; - break; - case RATE_IDX: - setup->rate_id = kctl->id; - break; - case CHANNELS_IDX: - setup->channels_id = kctl->id; - break; - default: - break; - } - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - } - } - } - return 0; -} - -#ifdef CONFIG_PROC_FS - -static void print_dpcm_info(struct snd_info_buffer *buffer, - struct loopback_pcm *dpcm, - const char *id) -{ - snd_iprintf(buffer, " %s\n", id); - if (dpcm == NULL) { - snd_iprintf(buffer, " inactive\n"); - return; - } - snd_iprintf(buffer, " buffer_size:\t%u\n", dpcm->pcm_buffer_size); - snd_iprintf(buffer, " buffer_pos:\t\t%u\n", dpcm->buf_pos); - snd_iprintf(buffer, " silent_size:\t%u\n", dpcm->silent_size); - snd_iprintf(buffer, " period_size:\t%u\n", dpcm->pcm_period_size); - snd_iprintf(buffer, " bytes_per_sec:\t%u\n", dpcm->pcm_bps); - snd_iprintf(buffer, " sample_align:\t%u\n", dpcm->pcm_salign); - snd_iprintf(buffer, " rate_shift:\t\t%u\n", dpcm->pcm_rate_shift); - snd_iprintf(buffer, " update_pending:\t%u\n", - dpcm->period_update_pending); - snd_iprintf(buffer, " irq_pos:\t\t%u\n", dpcm->irq_pos); - snd_iprintf(buffer, " period_frac:\t%u\n", dpcm->period_size_frac); - snd_iprintf(buffer, " last_jiffies:\t%lu (%lu)\n", - dpcm->last_jiffies, jiffies); - snd_iprintf(buffer, " timer_expires:\t%lu\n", dpcm->timer.expires); -} - -static void print_substream_info(struct snd_info_buffer *buffer, - struct loopback *loopback, - int sub, - int num) -{ - struct loopback_cable *cable = loopback->cables[sub][num]; - - snd_iprintf(buffer, "Cable %i substream %i:\n", num, sub); - if (cable == NULL) { - snd_iprintf(buffer, " inactive\n"); - return; - } - snd_iprintf(buffer, " valid: %u\n", cable->valid); - snd_iprintf(buffer, " running: %u\n", cable->running); - snd_iprintf(buffer, " pause: %u\n", cable->pause); - print_dpcm_info(buffer, cable->streams[0], "Playback"); - print_dpcm_info(buffer, cable->streams[1], "Capture"); -} - -static void print_cable_info(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct loopback *loopback = entry->private_data; - int sub, num; - - mutex_lock(&loopback->cable_lock); - num = entry->name[strlen(entry->name)-1]; - num = num == '0' ? 0 : 1; - for (sub = 0; sub < MAX_PCM_SUBSTREAMS; sub++) - print_substream_info(buffer, loopback, sub, num); - mutex_unlock(&loopback->cable_lock); -} - -static int __devinit loopback_proc_new(struct loopback *loopback, int cidx) -{ - char name[32]; - struct snd_info_entry *entry; - int err; - - snprintf(name, sizeof(name), "cable#%d", cidx); - err = snd_card_proc_new(loopback->card, name, &entry); - if (err < 0) - return err; - - snd_info_set_text_ops(entry, loopback, print_cable_info); - return 0; -} - -#else /* !CONFIG_PROC_FS */ - -#define loopback_proc_new(loopback, cidx) do { } while (0) - -#endif - -static int __devinit loopback_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct loopback *loopback; - int dev = devptr->id; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct loopback), &card); - if (err < 0) - return err; - loopback = card->private_data; - - if (pcm_substreams[dev] < 1) - pcm_substreams[dev] = 1; - if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS) - pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; - - loopback->card = card; - mutex_init(&loopback->cable_lock); - - err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]); - if (err < 0) - goto __nodev; - err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]); - if (err < 0) - goto __nodev; - err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0); - if (err < 0) - goto __nodev; - loopback_proc_new(loopback, 0); - loopback_proc_new(loopback, 1); - strcpy(card->driver, "Loopback"); - strcpy(card->shortname, "Loopback"); - sprintf(card->longname, "Loopback %i", dev + 1); - err = snd_card_register(card); - if (!err) { - platform_set_drvdata(devptr, card); - return 0; - } - __nodev: - snd_card_free(card); - return err; -} - -static int __devexit loopback_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int loopback_suspend(struct platform_device *pdev, - pm_message_t state) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct loopback *loopback = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(loopback->pcm[0]); - snd_pcm_suspend_all(loopback->pcm[1]); - return 0; -} - -static int loopback_resume(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -#define SND_LOOPBACK_DRIVER "snd_aloop" - -static struct platform_driver loopback_driver = { - .probe = loopback_probe, - .remove = __devexit_p(loopback_remove), -#ifdef CONFIG_PM - .suspend = loopback_suspend, - .resume = loopback_resume, -#endif - .driver = { - .name = SND_LOOPBACK_DRIVER - }, -}; - -static void loopback_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&loopback_driver); -} - -static int __init alsa_card_loopback_init(void) -{ - int i, err, cards; - - err = platform_driver_register(&loopback_driver); - if (err < 0) - return err; - - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (!enable[i]) - continue; - device = platform_device_register_simple(SND_LOOPBACK_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "aloop: No loopback enabled\n"); -#endif - loopback_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_loopback_exit(void) -{ - loopback_unregister_all(); -} - -module_init(alsa_card_loopback_init) -module_exit(alsa_card_loopback_exit) diff --git a/ANDROID_3.4.5/sound/drivers/dummy.c b/ANDROID_3.4.5/sound/drivers/dummy.c deleted file mode 100644 index ad9434fd..00000000 --- a/ANDROID_3.4.5/sound/drivers/dummy.c +++ /dev/null @@ -1,1157 +0,0 @@ -/* - * Dummy soundcard - * Copyright (c) by Jaroslav Kysela - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Dummy soundcard (/dev/null)"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}"); - -#define MAX_PCM_DEVICES 4 -#define MAX_PCM_SUBSTREAMS 128 -#define MAX_MIDI_DEVICES 2 - -/* defaults */ -#define MAX_BUFFER_SIZE (64*1024) -#define MIN_PERIOD_SIZE 64 -#define MAX_PERIOD_SIZE MAX_BUFFER_SIZE -#define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE) -#define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000 -#define USE_RATE_MIN 5500 -#define USE_RATE_MAX 48000 -#define USE_CHANNELS_MIN 1 -#define USE_CHANNELS_MAX 2 -#define USE_PERIODS_MIN 1 -#define USE_PERIODS_MAX 1024 - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; -static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL}; -static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; -//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; -#ifdef CONFIG_HIGH_RES_TIMERS -static bool hrtimer = 1; -#endif -static bool fake_buffer = 1; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for dummy soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for dummy soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this dummy soundcard."); -module_param_array(model, charp, NULL, 0444); -MODULE_PARM_DESC(model, "Soundcard model."); -module_param_array(pcm_devs, int, NULL, 0444); -MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver."); -module_param_array(pcm_substreams, int, NULL, 0444); -MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver."); -//module_param_array(midi_devs, int, NULL, 0444); -//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver."); -module_param(fake_buffer, bool, 0444); -MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations."); -#ifdef CONFIG_HIGH_RES_TIMERS -module_param(hrtimer, bool, 0644); -MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source."); -#endif - -static struct platform_device *devices[SNDRV_CARDS]; - -#define MIXER_ADDR_MASTER 0 -#define MIXER_ADDR_LINE 1 -#define MIXER_ADDR_MIC 2 -#define MIXER_ADDR_SYNTH 3 -#define MIXER_ADDR_CD 4 -#define MIXER_ADDR_LAST 4 - -struct dummy_timer_ops { - int (*create)(struct snd_pcm_substream *); - void (*free)(struct snd_pcm_substream *); - int (*prepare)(struct snd_pcm_substream *); - int (*start)(struct snd_pcm_substream *); - int (*stop)(struct snd_pcm_substream *); - snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); -}; - -struct dummy_model { - const char *name; - int (*playback_constraints)(struct snd_pcm_runtime *runtime); - int (*capture_constraints)(struct snd_pcm_runtime *runtime); - u64 formats; - size_t buffer_bytes_max; - size_t period_bytes_min; - size_t period_bytes_max; - unsigned int periods_min; - unsigned int periods_max; - unsigned int rates; - unsigned int rate_min; - unsigned int rate_max; - unsigned int channels_min; - unsigned int channels_max; -}; - -struct snd_dummy { - struct snd_card *card; - struct dummy_model *model; - struct snd_pcm *pcm; - struct snd_pcm_hardware pcm_hw; - spinlock_t mixer_lock; - int mixer_volume[MIXER_ADDR_LAST+1][2]; - int capture_source[MIXER_ADDR_LAST+1][2]; - const struct dummy_timer_ops *timer_ops; -}; - -/* - * card models - */ - -static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime) -{ - int err; - err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) - return err; - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX); - if (err < 0) - return err; - return 0; -} - -struct dummy_model model_emu10k1 = { - .name = "emu10k1", - .playback_constraints = emu10k1_playback_constraints, - .buffer_bytes_max = 128 * 1024, -}; - -struct dummy_model model_rme9652 = { - .name = "rme9652", - .buffer_bytes_max = 26 * 64 * 1024, - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .channels_min = 26, - .channels_max = 26, - .periods_min = 2, - .periods_max = 2, -}; - -struct dummy_model model_ice1712 = { - .name = "ice1712", - .buffer_bytes_max = 256 * 1024, - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .channels_min = 10, - .channels_max = 10, - .periods_min = 1, - .periods_max = 1024, -}; - -struct dummy_model model_uda1341 = { - .name = "uda1341", - .buffer_bytes_max = 16380, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 2, - .channels_max = 2, - .periods_min = 2, - .periods_max = 255, -}; - -struct dummy_model model_ac97 = { - .name = "ac97", - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, -}; - -struct dummy_model model_ca0106 = { - .name = "ca0106", - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .buffer_bytes_max = ((65536-64)*8), - .period_bytes_max = (65536-64), - .periods_min = 2, - .periods_max = 8, - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000, - .rate_min = 48000, - .rate_max = 192000, -}; - -struct dummy_model *dummy_models[] = { - &model_emu10k1, - &model_rme9652, - &model_ice1712, - &model_uda1341, - &model_ac97, - &model_ca0106, - NULL -}; - -/* - * system timer interface - */ - -struct dummy_systimer_pcm { - spinlock_t lock; - struct timer_list timer; - unsigned long base_time; - unsigned int frac_pos; /* fractional sample position (based HZ) */ - unsigned int frac_period_rest; - unsigned int frac_buffer_size; /* buffer_size * HZ */ - unsigned int frac_period_size; /* period_size * HZ */ - unsigned int rate; - int elapsed; - struct snd_pcm_substream *substream; -}; - -static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm) -{ - dpcm->timer.expires = jiffies + - (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate; - add_timer(&dpcm->timer); -} - -static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm) -{ - unsigned long delta; - - delta = jiffies - dpcm->base_time; - if (!delta) - return; - dpcm->base_time += delta; - delta *= dpcm->rate; - dpcm->frac_pos += delta; - while (dpcm->frac_pos >= dpcm->frac_buffer_size) - dpcm->frac_pos -= dpcm->frac_buffer_size; - while (dpcm->frac_period_rest <= delta) { - dpcm->elapsed++; - dpcm->frac_period_rest += dpcm->frac_period_size; - } - dpcm->frac_period_rest -= delta; -} - -static int dummy_systimer_start(struct snd_pcm_substream *substream) -{ - struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - spin_lock(&dpcm->lock); - dpcm->base_time = jiffies; - dummy_systimer_rearm(dpcm); - spin_unlock(&dpcm->lock); - return 0; -} - -static int dummy_systimer_stop(struct snd_pcm_substream *substream) -{ - struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - spin_lock(&dpcm->lock); - del_timer(&dpcm->timer); - spin_unlock(&dpcm->lock); - return 0; -} - -static int dummy_systimer_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct dummy_systimer_pcm *dpcm = runtime->private_data; - - dpcm->frac_pos = 0; - dpcm->rate = runtime->rate; - dpcm->frac_buffer_size = runtime->buffer_size * HZ; - dpcm->frac_period_size = runtime->period_size * HZ; - dpcm->frac_period_rest = dpcm->frac_period_size; - dpcm->elapsed = 0; - - return 0; -} - -static void dummy_systimer_callback(unsigned long data) -{ - struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data; - unsigned long flags; - int elapsed = 0; - - spin_lock_irqsave(&dpcm->lock, flags); - dummy_systimer_update(dpcm); - dummy_systimer_rearm(dpcm); - elapsed = dpcm->elapsed; - dpcm->elapsed = 0; - spin_unlock_irqrestore(&dpcm->lock, flags); - if (elapsed) - snd_pcm_period_elapsed(dpcm->substream); -} - -static snd_pcm_uframes_t -dummy_systimer_pointer(struct snd_pcm_substream *substream) -{ - struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; - snd_pcm_uframes_t pos; - - spin_lock(&dpcm->lock); - dummy_systimer_update(dpcm); - pos = dpcm->frac_pos / HZ; - spin_unlock(&dpcm->lock); - return pos; -} - -static int dummy_systimer_create(struct snd_pcm_substream *substream) -{ - struct dummy_systimer_pcm *dpcm; - - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (!dpcm) - return -ENOMEM; - substream->runtime->private_data = dpcm; - init_timer(&dpcm->timer); - dpcm->timer.data = (unsigned long) dpcm; - dpcm->timer.function = dummy_systimer_callback; - spin_lock_init(&dpcm->lock); - dpcm->substream = substream; - return 0; -} - -static void dummy_systimer_free(struct snd_pcm_substream *substream) -{ - kfree(substream->runtime->private_data); -} - -static struct dummy_timer_ops dummy_systimer_ops = { - .create = dummy_systimer_create, - .free = dummy_systimer_free, - .prepare = dummy_systimer_prepare, - .start = dummy_systimer_start, - .stop = dummy_systimer_stop, - .pointer = dummy_systimer_pointer, -}; - -#ifdef CONFIG_HIGH_RES_TIMERS -/* - * hrtimer interface - */ - -struct dummy_hrtimer_pcm { - ktime_t base_time; - ktime_t period_time; - atomic_t running; - struct hrtimer timer; - struct tasklet_struct tasklet; - struct snd_pcm_substream *substream; -}; - -static void dummy_hrtimer_pcm_elapsed(unsigned long priv) -{ - struct dummy_hrtimer_pcm *dpcm = (struct dummy_hrtimer_pcm *)priv; - if (atomic_read(&dpcm->running)) - snd_pcm_period_elapsed(dpcm->substream); -} - -static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer) -{ - struct dummy_hrtimer_pcm *dpcm; - - dpcm = container_of(timer, struct dummy_hrtimer_pcm, timer); - if (!atomic_read(&dpcm->running)) - return HRTIMER_NORESTART; - tasklet_schedule(&dpcm->tasklet); - hrtimer_forward_now(timer, dpcm->period_time); - return HRTIMER_RESTART; -} - -static int dummy_hrtimer_start(struct snd_pcm_substream *substream) -{ - struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; - - dpcm->base_time = hrtimer_cb_get_time(&dpcm->timer); - hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL); - atomic_set(&dpcm->running, 1); - return 0; -} - -static int dummy_hrtimer_stop(struct snd_pcm_substream *substream) -{ - struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; - - atomic_set(&dpcm->running, 0); - hrtimer_cancel(&dpcm->timer); - return 0; -} - -static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm) -{ - tasklet_kill(&dpcm->tasklet); -} - -static snd_pcm_uframes_t -dummy_hrtimer_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct dummy_hrtimer_pcm *dpcm = runtime->private_data; - u64 delta; - u32 pos; - - delta = ktime_us_delta(hrtimer_cb_get_time(&dpcm->timer), - dpcm->base_time); - delta = div_u64(delta * runtime->rate + 999999, 1000000); - div_u64_rem(delta, runtime->buffer_size, &pos); - return pos; -} - -static int dummy_hrtimer_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct dummy_hrtimer_pcm *dpcm = runtime->private_data; - unsigned int period, rate; - long sec; - unsigned long nsecs; - - dummy_hrtimer_sync(dpcm); - period = runtime->period_size; - rate = runtime->rate; - sec = period / rate; - period %= rate; - nsecs = div_u64((u64)period * 1000000000UL + rate - 1, rate); - dpcm->period_time = ktime_set(sec, nsecs); - - return 0; -} - -static int dummy_hrtimer_create(struct snd_pcm_substream *substream) -{ - struct dummy_hrtimer_pcm *dpcm; - - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (!dpcm) - return -ENOMEM; - substream->runtime->private_data = dpcm; - hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - dpcm->timer.function = dummy_hrtimer_callback; - dpcm->substream = substream; - atomic_set(&dpcm->running, 0); - tasklet_init(&dpcm->tasklet, dummy_hrtimer_pcm_elapsed, - (unsigned long)dpcm); - return 0; -} - -static void dummy_hrtimer_free(struct snd_pcm_substream *substream) -{ - struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; - dummy_hrtimer_sync(dpcm); - kfree(dpcm); -} - -static struct dummy_timer_ops dummy_hrtimer_ops = { - .create = dummy_hrtimer_create, - .free = dummy_hrtimer_free, - .prepare = dummy_hrtimer_prepare, - .start = dummy_hrtimer_start, - .stop = dummy_hrtimer_stop, - .pointer = dummy_hrtimer_pointer, -}; - -#endif /* CONFIG_HIGH_RES_TIMERS */ - -/* - * PCM interface - */ - -static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - return dummy->timer_ops->start(substream); - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - return dummy->timer_ops->stop(substream); - } - return -EINVAL; -} - -static int dummy_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - - return dummy->timer_ops->prepare(substream); -} - -static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - - return dummy->timer_ops->pointer(substream); -} - -static struct snd_pcm_hardware dummy_pcm_hardware = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = USE_FORMATS, - .rates = USE_RATE, - .rate_min = USE_RATE_MIN, - .rate_max = USE_RATE_MAX, - .channels_min = USE_CHANNELS_MIN, - .channels_max = USE_CHANNELS_MAX, - .buffer_bytes_max = MAX_BUFFER_SIZE, - .period_bytes_min = MIN_PERIOD_SIZE, - .period_bytes_max = MAX_PERIOD_SIZE, - .periods_min = USE_PERIODS_MIN, - .periods_max = USE_PERIODS_MAX, - .fifo_size = 0, -}; - -static int dummy_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - if (fake_buffer) { - /* runtime->dma_bytes has to be set manually to allow mmap */ - substream->runtime->dma_bytes = params_buffer_bytes(hw_params); - return 0; - } - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int dummy_pcm_hw_free(struct snd_pcm_substream *substream) -{ - if (fake_buffer) - return 0; - return snd_pcm_lib_free_pages(substream); -} - -static int dummy_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - struct dummy_model *model = dummy->model; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - dummy->timer_ops = &dummy_systimer_ops; -#ifdef CONFIG_HIGH_RES_TIMERS - if (hrtimer) - dummy->timer_ops = &dummy_hrtimer_ops; -#endif - - err = dummy->timer_ops->create(substream); - if (err < 0) - return err; - - runtime->hw = dummy->pcm_hw; - if (substream->pcm->device & 1) { - runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; - runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; - } - if (substream->pcm->device & 2) - runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID); - - if (model == NULL) - return 0; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (model->playback_constraints) - err = model->playback_constraints(substream->runtime); - } else { - if (model->capture_constraints) - err = model->capture_constraints(substream->runtime); - } - if (err < 0) { - dummy->timer_ops->free(substream); - return err; - } - return 0; -} - -static int dummy_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_dummy *dummy = snd_pcm_substream_chip(substream); - dummy->timer_ops->free(substream); - return 0; -} - -/* - * dummy buffer handling - */ - -static void *dummy_page[2]; - -static void free_fake_buffer(void) -{ - if (fake_buffer) { - int i; - for (i = 0; i < 2; i++) - if (dummy_page[i]) { - free_page((unsigned long)dummy_page[i]); - dummy_page[i] = NULL; - } - } -} - -static int alloc_fake_buffer(void) -{ - int i; - - if (!fake_buffer) - return 0; - for (i = 0; i < 2; i++) { - dummy_page[i] = (void *)get_zeroed_page(GFP_KERNEL); - if (!dummy_page[i]) { - free_fake_buffer(); - return -ENOMEM; - } - } - return 0; -} - -static int dummy_pcm_copy(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - void __user *dst, snd_pcm_uframes_t count) -{ - return 0; /* do nothing */ -} - -static int dummy_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - return 0; /* do nothing */ -} - -static struct page *dummy_pcm_page(struct snd_pcm_substream *substream, - unsigned long offset) -{ - return virt_to_page(dummy_page[substream->stream]); /* the same page */ -} - -static struct snd_pcm_ops dummy_pcm_ops = { - .open = dummy_pcm_open, - .close = dummy_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = dummy_pcm_hw_params, - .hw_free = dummy_pcm_hw_free, - .prepare = dummy_pcm_prepare, - .trigger = dummy_pcm_trigger, - .pointer = dummy_pcm_pointer, -}; - -static struct snd_pcm_ops dummy_pcm_ops_no_buf = { - .open = dummy_pcm_open, - .close = dummy_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = dummy_pcm_hw_params, - .hw_free = dummy_pcm_hw_free, - .prepare = dummy_pcm_prepare, - .trigger = dummy_pcm_trigger, - .pointer = dummy_pcm_pointer, - .copy = dummy_pcm_copy, - .silence = dummy_pcm_silence, - .page = dummy_pcm_page, -}; - -static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, - int substreams) -{ - struct snd_pcm *pcm; - struct snd_pcm_ops *ops; - int err; - - err = snd_pcm_new(dummy->card, "Dummy PCM", device, - substreams, substreams, &pcm); - if (err < 0) - return err; - dummy->pcm = pcm; - if (fake_buffer) - ops = &dummy_pcm_ops_no_buf; - else - ops = &dummy_pcm_ops; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, ops); - pcm->private_data = dummy; - pcm->info_flags = 0; - strcpy(pcm->name, "Dummy PCM"); - if (!fake_buffer) { - snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 0, 64*1024); - } - return 0; -} - -/* - * mixer interface - */ - -#define DUMMY_VOLUME(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_dummy_volume_info, \ - .get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \ - .private_value = addr, \ - .tlv = { .p = db_scale_dummy } } - -static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = -50; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int addr = kcontrol->private_value; - - spin_lock_irq(&dummy->mixer_lock); - ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0]; - ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1]; - spin_unlock_irq(&dummy->mixer_lock); - return 0; -} - -static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int change, addr = kcontrol->private_value; - int left, right; - - left = ucontrol->value.integer.value[0]; - if (left < -50) - left = -50; - if (left > 100) - left = 100; - right = ucontrol->value.integer.value[1]; - if (right < -50) - right = -50; - if (right > 100) - right = 100; - spin_lock_irq(&dummy->mixer_lock); - change = dummy->mixer_volume[addr][0] != left || - dummy->mixer_volume[addr][1] != right; - dummy->mixer_volume[addr][0] = left; - dummy->mixer_volume[addr][1] = right; - spin_unlock_irq(&dummy->mixer_lock); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); - -#define DUMMY_CAPSRC(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_dummy_capsrc_info, \ - .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \ - .private_value = addr } - -#define snd_dummy_capsrc_info snd_ctl_boolean_stereo_info - -static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int addr = kcontrol->private_value; - - spin_lock_irq(&dummy->mixer_lock); - ucontrol->value.integer.value[0] = dummy->capture_source[addr][0]; - ucontrol->value.integer.value[1] = dummy->capture_source[addr][1]; - spin_unlock_irq(&dummy->mixer_lock); - return 0; -} - -static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol); - int change, addr = kcontrol->private_value; - int left, right; - - left = ucontrol->value.integer.value[0] & 1; - right = ucontrol->value.integer.value[1] & 1; - spin_lock_irq(&dummy->mixer_lock); - change = dummy->capture_source[addr][0] != left && - dummy->capture_source[addr][1] != right; - dummy->capture_source[addr][0] = left; - dummy->capture_source[addr][1] = right; - spin_unlock_irq(&dummy->mixer_lock); - return change; -} - -static struct snd_kcontrol_new snd_dummy_controls[] = { -DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER), -DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER), -DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH), -DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_SYNTH), -DUMMY_VOLUME("Line Volume", 0, MIXER_ADDR_LINE), -DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE), -DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC), -DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC), -DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD), -DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD) -}; - -static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) -{ - struct snd_card *card = dummy->card; - unsigned int idx; - int err; - - spin_lock_init(&dummy->mixer_lock); - strcpy(card->mixername, "Dummy Mixer"); - - for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy)); - if (err < 0) - return err; - } - return 0; -} - -#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_PROC_FS) -/* - * proc interface - */ -static void print_formats(struct snd_dummy *dummy, - struct snd_info_buffer *buffer) -{ - int i; - - for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { - if (dummy->pcm_hw.formats & (1ULL << i)) - snd_iprintf(buffer, " %s", snd_pcm_format_name(i)); - } -} - -static void print_rates(struct snd_dummy *dummy, - struct snd_info_buffer *buffer) -{ - static int rates[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, - 64000, 88200, 96000, 176400, 192000, - }; - int i; - - if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_CONTINUOUS) - snd_iprintf(buffer, " continuous"); - if (dummy->pcm_hw.rates & SNDRV_PCM_RATE_KNOT) - snd_iprintf(buffer, " knot"); - for (i = 0; i < ARRAY_SIZE(rates); i++) - if (dummy->pcm_hw.rates & (1 << i)) - snd_iprintf(buffer, " %d", rates[i]); -} - -#define get_dummy_int_ptr(dummy, ofs) \ - (unsigned int *)((char *)&((dummy)->pcm_hw) + (ofs)) -#define get_dummy_ll_ptr(dummy, ofs) \ - (unsigned long long *)((char *)&((dummy)->pcm_hw) + (ofs)) - -struct dummy_hw_field { - const char *name; - const char *format; - unsigned int offset; - unsigned int size; -}; -#define FIELD_ENTRY(item, fmt) { \ - .name = #item, \ - .format = fmt, \ - .offset = offsetof(struct snd_pcm_hardware, item), \ - .size = sizeof(dummy_pcm_hardware.item) } - -static struct dummy_hw_field fields[] = { - FIELD_ENTRY(formats, "%#llx"), - FIELD_ENTRY(rates, "%#x"), - FIELD_ENTRY(rate_min, "%d"), - FIELD_ENTRY(rate_max, "%d"), - FIELD_ENTRY(channels_min, "%d"), - FIELD_ENTRY(channels_max, "%d"), - FIELD_ENTRY(buffer_bytes_max, "%ld"), - FIELD_ENTRY(period_bytes_min, "%ld"), - FIELD_ENTRY(period_bytes_max, "%ld"), - FIELD_ENTRY(periods_min, "%d"), - FIELD_ENTRY(periods_max, "%d"), -}; - -static void dummy_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_dummy *dummy = entry->private_data; - int i; - - for (i = 0; i < ARRAY_SIZE(fields); i++) { - snd_iprintf(buffer, "%s ", fields[i].name); - if (fields[i].size == sizeof(int)) - snd_iprintf(buffer, fields[i].format, - *get_dummy_int_ptr(dummy, fields[i].offset)); - else - snd_iprintf(buffer, fields[i].format, - *get_dummy_ll_ptr(dummy, fields[i].offset)); - if (!strcmp(fields[i].name, "formats")) - print_formats(dummy, buffer); - else if (!strcmp(fields[i].name, "rates")) - print_rates(dummy, buffer); - snd_iprintf(buffer, "\n"); - } -} - -static void dummy_proc_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_dummy *dummy = entry->private_data; - char line[64]; - - while (!snd_info_get_line(buffer, line, sizeof(line))) { - char item[20]; - const char *ptr; - unsigned long long val; - int i; - - ptr = snd_info_get_str(item, line, sizeof(item)); - for (i = 0; i < ARRAY_SIZE(fields); i++) { - if (!strcmp(item, fields[i].name)) - break; - } - if (i >= ARRAY_SIZE(fields)) - continue; - snd_info_get_str(item, ptr, sizeof(item)); - if (strict_strtoull(item, 0, &val)) - continue; - if (fields[i].size == sizeof(int)) - *get_dummy_int_ptr(dummy, fields[i].offset) = val; - else - *get_dummy_ll_ptr(dummy, fields[i].offset) = val; - } -} - -static void __devinit dummy_proc_init(struct snd_dummy *chip) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(chip->card, "dummy_pcm", &entry)) { - snd_info_set_text_ops(entry, chip, dummy_proc_read); - entry->c.text.write = dummy_proc_write; - entry->mode |= S_IWUSR; - entry->private_data = chip; - } -} -#else -#define dummy_proc_init(x) -#endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */ - -static int __devinit snd_dummy_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct snd_dummy *dummy; - struct dummy_model *m = NULL, **mdl; - int idx, err; - int dev = devptr->id; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_dummy), &card); - if (err < 0) - return err; - dummy = card->private_data; - dummy->card = card; - for (mdl = dummy_models; *mdl && model[dev]; mdl++) { - if (strcmp(model[dev], (*mdl)->name) == 0) { - printk(KERN_INFO - "snd-dummy: Using model '%s' for card %i\n", - (*mdl)->name, card->number); - m = dummy->model = *mdl; - break; - } - } - for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) { - if (pcm_substreams[dev] < 1) - pcm_substreams[dev] = 1; - if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS) - pcm_substreams[dev] = MAX_PCM_SUBSTREAMS; - err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev]); - if (err < 0) - goto __nodev; - } - - dummy->pcm_hw = dummy_pcm_hardware; - if (m) { - if (m->formats) - dummy->pcm_hw.formats = m->formats; - if (m->buffer_bytes_max) - dummy->pcm_hw.buffer_bytes_max = m->buffer_bytes_max; - if (m->period_bytes_min) - dummy->pcm_hw.period_bytes_min = m->period_bytes_min; - if (m->period_bytes_max) - dummy->pcm_hw.period_bytes_max = m->period_bytes_max; - if (m->periods_min) - dummy->pcm_hw.periods_min = m->periods_min; - if (m->periods_max) - dummy->pcm_hw.periods_max = m->periods_max; - if (m->rates) - dummy->pcm_hw.rates = m->rates; - if (m->rate_min) - dummy->pcm_hw.rate_min = m->rate_min; - if (m->rate_max) - dummy->pcm_hw.rate_max = m->rate_max; - if (m->channels_min) - dummy->pcm_hw.channels_min = m->channels_min; - if (m->channels_max) - dummy->pcm_hw.channels_max = m->channels_max; - } - - err = snd_card_dummy_new_mixer(dummy); - if (err < 0) - goto __nodev; - strcpy(card->driver, "Dummy"); - strcpy(card->shortname, "Dummy"); - sprintf(card->longname, "Dummy %i", dev + 1); - - dummy_proc_init(dummy); - - snd_card_set_dev(card, &devptr->dev); - - err = snd_card_register(card); - if (err == 0) { - platform_set_drvdata(devptr, card); - return 0; - } - __nodev: - snd_card_free(card); - return err; -} - -static int __devexit snd_dummy_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct snd_dummy *dummy = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(dummy->pcm); - return 0; -} - -static int snd_dummy_resume(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -#define SND_DUMMY_DRIVER "snd_dummy" - -static struct platform_driver snd_dummy_driver = { - .probe = snd_dummy_probe, - .remove = __devexit_p(snd_dummy_remove), -#ifdef CONFIG_PM - .suspend = snd_dummy_suspend, - .resume = snd_dummy_resume, -#endif - .driver = { - .name = SND_DUMMY_DRIVER - }, -}; - -static void snd_dummy_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_dummy_driver); - free_fake_buffer(); -} - -static int __init alsa_card_dummy_init(void) -{ - int i, cards, err; - - err = platform_driver_register(&snd_dummy_driver); - if (err < 0) - return err; - - err = alloc_fake_buffer(); - if (err < 0) { - platform_driver_unregister(&snd_dummy_driver); - return err; - } - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_DUMMY_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "Dummy soundcard not found or device busy\n"); -#endif - snd_dummy_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_dummy_exit(void) -{ - snd_dummy_unregister_all(); -} - -module_init(alsa_card_dummy_init) -module_exit(alsa_card_dummy_exit) diff --git a/ANDROID_3.4.5/sound/drivers/ml403-ac97cr.c b/ANDROID_3.4.5/sound/drivers/ml403-ac97cr.c deleted file mode 100644 index 6c83b1ae..00000000 --- a/ANDROID_3.4.5/sound/drivers/ml403-ac97cr.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* - * ALSA driver for Xilinx ML403 AC97 Controller Reference - * IP: opb_ac97_controller_ref_v1_00_a (EDK 8.1i) - * IP: opb_ac97_controller_ref_v1_00_a (EDK 9.1i) - * - * Copyright (c) by 2007 Joachim Foerster - * - * 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 - * - */ - -/* Some notes / status of this driver: - * - * - Don't wonder about some strange implementations of things - especially the - * (heavy) shadowing of codec registers, with which I tried to reduce read - * accesses to a minimum, because after a variable amount of accesses, the AC97 - * controller doesn't raise the register access finished bit anymore ... - * - * - Playback support seems to be pretty stable - no issues here. - * - Capture support "works" now, too. Overruns don't happen any longer so often. - * But there might still be some ... - */ - -#include -#include - -#include - -#include -#include -#include -#include - -/* HZ */ -#include -/* jiffies, time_*() */ -#include -/* schedule_timeout*() */ -#include -/* spin_lock*() */ -#include -/* struct mutex, mutex_init(), mutex_*lock() */ -#include - -/* snd_printk(), snd_printd() */ -#include -#include -#include -#include -#include - -#include "pcm-indirect2.h" - - -#define SND_ML403_AC97CR_DRIVER "ml403-ac97cr" - -MODULE_AUTHOR("Joachim Foerster "); -MODULE_DESCRIPTION("Xilinx ML403 AC97 Controller Reference"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Xilinx,ML403 AC97 Controller Reference}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ML403 AC97 Controller Reference."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ML403 AC97 Controller Reference."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this ML403 AC97 Controller Reference."); - -/* Special feature options */ -/*#define CODEC_WRITE_CHECK_RAF*/ /* don't return after a write to a codec - * register, while RAF bit is not set - */ -/* Debug options for code which may be removed completely in a final version */ -#ifdef CONFIG_SND_DEBUG -/*#define CODEC_STAT*/ /* turn on some minimal "statistics" - * about codec register usage - */ -#define SND_PCM_INDIRECT2_STAT /* turn on some "statistics" about the - * process of copying bytes from the - * intermediate buffer to the hardware - * fifo and the other way round - */ -#endif - -/* Definition of a "level/facility dependent" printk(); may be removed - * completely in a final version - */ -#undef PDEBUG -#ifdef CONFIG_SND_DEBUG -/* "facilities" for PDEBUG */ -#define UNKNOWN (1<<0) -#define CODEC_SUCCESS (1<<1) -#define CODEC_FAKE (1<<2) -#define INIT_INFO (1<<3) -#define INIT_FAILURE (1<<4) -#define WORK_INFO (1<<5) -#define WORK_FAILURE (1<<6) - -#define PDEBUG_FACILITIES (UNKNOWN | INIT_FAILURE | WORK_FAILURE) - -#define PDEBUG(fac, fmt, args...) do { \ - if (fac & PDEBUG_FACILITIES) \ - snd_printd(KERN_DEBUG SND_ML403_AC97CR_DRIVER ": " \ - fmt, ##args); \ - } while (0) -#else -#define PDEBUG(fac, fmt, args...) /* nothing */ -#endif - - - -/* Defines for "waits"/timeouts (portions of HZ=250 on arch/ppc by default) */ -#define CODEC_TIMEOUT_ON_INIT 5 /* timeout for checking for codec - * readiness (after insmod) - */ -#ifndef CODEC_WRITE_CHECK_RAF -#define CODEC_WAIT_AFTER_WRITE 100 /* general, static wait after a write - * access to a codec register, may be - * 0 to completely remove wait - */ -#else -#define CODEC_TIMEOUT_AFTER_WRITE 5 /* timeout after a write access to a - * codec register, if RAF bit is used - */ -#endif -#define CODEC_TIMEOUT_AFTER_READ 5 /* timeout after a read access to a - * codec register (checking RAF bit) - */ - -/* Infrastructure for codec register shadowing */ -#define LM4550_REG_OK (1<<0) /* register exists */ -#define LM4550_REG_DONEREAD (1<<1) /* read register once, value should be - * the same currently in the register - */ -#define LM4550_REG_NOSAVE (1<<2) /* values written to this register will - * not be saved in the register - */ -#define LM4550_REG_NOSHADOW (1<<3) /* don't do register shadowing, use plain - * hardware access - */ -#define LM4550_REG_READONLY (1<<4) /* register is read only */ -#define LM4550_REG_FAKEPROBE (1<<5) /* fake write _and_ read actions during - * probe() correctly - */ -#define LM4550_REG_FAKEREAD (1<<6) /* fake read access, always return - * default value - */ -#define LM4550_REG_ALLFAKE (LM4550_REG_FAKEREAD | LM4550_REG_FAKEPROBE) - -struct lm4550_reg { - u16 value; - u16 flag; - u16 wmask; - u16 def; -}; - -struct lm4550_reg lm4550_regfile[64] = { - [AC97_RESET / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_NOSAVE \ - | LM4550_REG_FAKEREAD, - .def = 0x0D50}, - [AC97_MASTER / 2] = {.flag = LM4550_REG_OK - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8000}, - [AC97_HEADPHONE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8000}, - [AC97_MASTER_MONO / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x801F, - .def = 0x8000}, - [AC97_PC_BEEP / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x801E, - .def = 0x0}, - [AC97_PHONE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x801F, - .def = 0x8008}, - [AC97_MIC / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x805F, - .def = 0x8008}, - [AC97_LINE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8808}, - [AC97_CD / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8808}, - [AC97_VIDEO / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8808}, - [AC97_AUX / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8808}, - [AC97_PCM / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x9F1F, - .def = 0x8008}, - [AC97_REC_SEL / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x707, - .def = 0x0}, - [AC97_REC_GAIN / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .wmask = 0x8F0F, - .def = 0x8000}, - [AC97_GENERAL_PURPOSE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .def = 0x0, - .wmask = 0xA380}, - [AC97_3D_CONTROL / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEREAD \ - | LM4550_REG_READONLY, - .def = 0x0101}, - [AC97_POWERDOWN / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_NOSHADOW \ - | LM4550_REG_NOSAVE, - .wmask = 0xFF00}, - /* may not write ones to - * REF/ANL/DAC/ADC bits - * FIXME: Is this ok? - */ - [AC97_EXTENDED_ID / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEREAD \ - | LM4550_REG_READONLY, - .def = 0x0201}, /* primary codec */ - [AC97_EXTENDED_STATUS / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_NOSHADOW \ - | LM4550_REG_NOSAVE, - .wmask = 0x1}, - [AC97_PCM_FRONT_DAC_RATE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .def = 0xBB80, - .wmask = 0xFFFF}, - [AC97_PCM_LR_ADC_RATE / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_FAKEPROBE, - .def = 0xBB80, - .wmask = 0xFFFF}, - [AC97_VENDOR_ID1 / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_READONLY \ - | LM4550_REG_FAKEREAD, - .def = 0x4E53}, - [AC97_VENDOR_ID2 / 2] = {.flag = LM4550_REG_OK \ - | LM4550_REG_READONLY \ - | LM4550_REG_FAKEREAD, - .def = 0x4350} -}; - -#define LM4550_RF_OK(reg) (lm4550_regfile[reg / 2].flag & LM4550_REG_OK) - -static void lm4550_regfile_init(void) -{ - int i; - for (i = 0; i < 64; i++) - if (lm4550_regfile[i].flag & LM4550_REG_FAKEPROBE) - lm4550_regfile[i].value = lm4550_regfile[i].def; -} - -static void lm4550_regfile_write_values_after_init(struct snd_ac97 *ac97) -{ - int i; - for (i = 0; i < 64; i++) - if ((lm4550_regfile[i].flag & LM4550_REG_FAKEPROBE) && - (lm4550_regfile[i].value != lm4550_regfile[i].def)) { - PDEBUG(CODEC_FAKE, "lm4550_regfile_write_values_after_" - "init(): reg=0x%x value=0x%x / %d is different " - "from def=0x%x / %d\n", - i, lm4550_regfile[i].value, - lm4550_regfile[i].value, lm4550_regfile[i].def, - lm4550_regfile[i].def); - snd_ac97_write(ac97, i * 2, lm4550_regfile[i].value); - lm4550_regfile[i].flag |= LM4550_REG_DONEREAD; - } -} - - -/* direct registers */ -#define CR_REG(ml403_ac97cr, x) ((ml403_ac97cr)->port + CR_REG_##x) - -#define CR_REG_PLAYFIFO 0x00 -#define CR_PLAYDATA(a) ((a) & 0xFFFF) - -#define CR_REG_RECFIFO 0x04 -#define CR_RECDATA(a) ((a) & 0xFFFF) - -#define CR_REG_STATUS 0x08 -#define CR_RECOVER (1<<7) -#define CR_PLAYUNDER (1<<6) -#define CR_CODECREADY (1<<5) -#define CR_RAF (1<<4) -#define CR_RECEMPTY (1<<3) -#define CR_RECFULL (1<<2) -#define CR_PLAYHALF (1<<1) -#define CR_PLAYFULL (1<<0) - -#define CR_REG_RESETFIFO 0x0C -#define CR_RECRESET (1<<1) -#define CR_PLAYRESET (1<<0) - -#define CR_REG_CODEC_ADDR 0x10 -/* UG082 says: - * #define CR_CODEC_ADDR(a) ((a) << 1) - * #define CR_CODEC_READ (1<<0) - * #define CR_CODEC_WRITE (0<<0) - */ -/* RefDesign example says: */ -#define CR_CODEC_ADDR(a) ((a) << 0) -#define CR_CODEC_READ (1<<7) -#define CR_CODEC_WRITE (0<<7) - -#define CR_REG_CODEC_DATAREAD 0x14 -#define CR_CODEC_DATAREAD(v) ((v) & 0xFFFF) - -#define CR_REG_CODEC_DATAWRITE 0x18 -#define CR_CODEC_DATAWRITE(v) ((v) & 0xFFFF) - -#define CR_FIFO_SIZE 32 - -struct snd_ml403_ac97cr { - /* lock for access to (controller) registers */ - spinlock_t reg_lock; - /* mutex for the whole sequence of accesses to (controller) registers - * which affect codec registers - */ - struct mutex cdc_mutex; - - int irq; /* for playback */ - int enable_irq; /* for playback */ - - int capture_irq; - int enable_capture_irq; - - struct resource *res_port; - void *port; - - struct snd_ac97 *ac97; - int ac97_fake; -#ifdef CODEC_STAT - int ac97_read; - int ac97_write; -#endif - - struct platform_device *pfdev; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - - struct snd_pcm_indirect2 ind_rec; /* for playback */ - struct snd_pcm_indirect2 capture_ind2_rec; -}; - -static struct snd_pcm_hardware snd_ml403_ac97cr_playback = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000), - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = CR_FIFO_SIZE/2, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = (128*1024)/(CR_FIFO_SIZE/2), - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_ml403_ac97cr_capture = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000), - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = CR_FIFO_SIZE/2, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = (128*1024)/(CR_FIFO_SIZE/2), - .fifo_size = 0, -}; - -static size_t -snd_ml403_ac97cr_playback_ind2_zero(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int copied_words = 0; - u32 full = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - spin_lock(&ml403_ac97cr->reg_lock); - while ((full = (in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_PLAYFULL)) != CR_PLAYFULL) { - out_be32(CR_REG(ml403_ac97cr, PLAYFIFO), 0); - copied_words++; - } - rec->hw_ready = 0; - spin_unlock(&ml403_ac97cr->reg_lock); - - return (size_t) (copied_words * 2); -} - -static size_t -snd_ml403_ac97cr_playback_ind2_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - size_t bytes) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - u16 *src; - int copied_words = 0; - u32 full = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - src = (u16 *)(substream->runtime->dma_area + rec->sw_data); - - spin_lock(&ml403_ac97cr->reg_lock); - while (((full = (in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_PLAYFULL)) != CR_PLAYFULL) && (bytes > 1)) { - out_be32(CR_REG(ml403_ac97cr, PLAYFIFO), - CR_PLAYDATA(src[copied_words])); - copied_words++; - bytes = bytes - 2; - } - if (full != CR_PLAYFULL) - rec->hw_ready = 1; - else - rec->hw_ready = 0; - spin_unlock(&ml403_ac97cr->reg_lock); - - return (size_t) (copied_words * 2); -} - -static size_t -snd_ml403_ac97cr_capture_ind2_null(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int copied_words = 0; - u32 empty = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - spin_lock(&ml403_ac97cr->reg_lock); - while ((empty = (in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_RECEMPTY)) != CR_RECEMPTY) { - volatile u32 trash; - - trash = CR_RECDATA(in_be32(CR_REG(ml403_ac97cr, RECFIFO))); - /* Hmmmm, really necessary? Don't want call to in_be32() - * to be optimised away! - */ - trash++; - copied_words++; - } - rec->hw_ready = 0; - spin_unlock(&ml403_ac97cr->reg_lock); - - return (size_t) (copied_words * 2); -} - -static size_t -snd_ml403_ac97cr_capture_ind2_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, size_t bytes) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - u16 *dst; - int copied_words = 0; - u32 empty = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - dst = (u16 *)(substream->runtime->dma_area + rec->sw_data); - - spin_lock(&ml403_ac97cr->reg_lock); - while (((empty = (in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_RECEMPTY)) != CR_RECEMPTY) && (bytes > 1)) { - dst[copied_words] = CR_RECDATA(in_be32(CR_REG(ml403_ac97cr, - RECFIFO))); - copied_words++; - bytes = bytes - 2; - } - if (empty != CR_RECEMPTY) - rec->hw_ready = 1; - else - rec->hw_ready = 0; - spin_unlock(&ml403_ac97cr->reg_lock); - - return (size_t) (copied_words * 2); -} - -static snd_pcm_uframes_t -snd_ml403_ac97cr_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_indirect2 *ind2_rec = NULL; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - if (substream == ml403_ac97cr->playback_substream) - ind2_rec = &ml403_ac97cr->ind_rec; - if (substream == ml403_ac97cr->capture_substream) - ind2_rec = &ml403_ac97cr->capture_ind2_rec; - - if (ind2_rec != NULL) - return snd_pcm_indirect2_pointer(substream, ind2_rec); - return (snd_pcm_uframes_t) 0; -} - -static int -snd_ml403_ac97cr_pcm_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int err = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - PDEBUG(WORK_INFO, "trigger(playback): START\n"); - ml403_ac97cr->ind_rec.hw_ready = 1; - - /* clear play FIFO */ - out_be32(CR_REG(ml403_ac97cr, RESETFIFO), CR_PLAYRESET); - - /* enable play irq */ - ml403_ac97cr->enable_irq = 1; - enable_irq(ml403_ac97cr->irq); - break; - case SNDRV_PCM_TRIGGER_STOP: - PDEBUG(WORK_INFO, "trigger(playback): STOP\n"); - ml403_ac97cr->ind_rec.hw_ready = 0; -#ifdef SND_PCM_INDIRECT2_STAT - snd_pcm_indirect2_stat(substream, &ml403_ac97cr->ind_rec); -#endif - /* disable play irq */ - disable_irq_nosync(ml403_ac97cr->irq); - ml403_ac97cr->enable_irq = 0; - break; - default: - err = -EINVAL; - break; - } - PDEBUG(WORK_INFO, "trigger(playback): (done)\n"); - return err; -} - -static int -snd_ml403_ac97cr_pcm_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int err = 0; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - PDEBUG(WORK_INFO, "trigger(capture): START\n"); - ml403_ac97cr->capture_ind2_rec.hw_ready = 0; - - /* clear record FIFO */ - out_be32(CR_REG(ml403_ac97cr, RESETFIFO), CR_RECRESET); - - /* enable record irq */ - ml403_ac97cr->enable_capture_irq = 1; - enable_irq(ml403_ac97cr->capture_irq); - break; - case SNDRV_PCM_TRIGGER_STOP: - PDEBUG(WORK_INFO, "trigger(capture): STOP\n"); - ml403_ac97cr->capture_ind2_rec.hw_ready = 0; -#ifdef SND_PCM_INDIRECT2_STAT - snd_pcm_indirect2_stat(substream, - &ml403_ac97cr->capture_ind2_rec); -#endif - /* disable capture irq */ - disable_irq_nosync(ml403_ac97cr->capture_irq); - ml403_ac97cr->enable_capture_irq = 0; - break; - default: - err = -EINVAL; - break; - } - PDEBUG(WORK_INFO, "trigger(capture): (done)\n"); - return err; -} - -static int -snd_ml403_ac97cr_pcm_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_runtime *runtime; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - PDEBUG(WORK_INFO, - "prepare(): period_bytes=%d, minperiod_bytes=%d\n", - snd_pcm_lib_period_bytes(substream), CR_FIFO_SIZE / 2); - - /* set sampling rate */ - snd_ac97_set_rate(ml403_ac97cr->ac97, AC97_PCM_FRONT_DAC_RATE, - runtime->rate); - PDEBUG(WORK_INFO, "prepare(): rate=%d\n", runtime->rate); - - /* init struct for intermediate buffer */ - memset(&ml403_ac97cr->ind_rec, 0, - sizeof(struct snd_pcm_indirect2)); - ml403_ac97cr->ind_rec.hw_buffer_size = CR_FIFO_SIZE; - ml403_ac97cr->ind_rec.sw_buffer_size = - snd_pcm_lib_buffer_bytes(substream); - ml403_ac97cr->ind_rec.min_periods = -1; - ml403_ac97cr->ind_rec.min_multiple = - snd_pcm_lib_period_bytes(substream) / (CR_FIFO_SIZE / 2); - PDEBUG(WORK_INFO, "prepare(): hw_buffer_size=%d, " - "sw_buffer_size=%d, min_multiple=%d\n", - CR_FIFO_SIZE, ml403_ac97cr->ind_rec.sw_buffer_size, - ml403_ac97cr->ind_rec.min_multiple); - return 0; -} - -static int -snd_ml403_ac97cr_pcm_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_runtime *runtime; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - PDEBUG(WORK_INFO, - "prepare(capture): period_bytes=%d, minperiod_bytes=%d\n", - snd_pcm_lib_period_bytes(substream), CR_FIFO_SIZE / 2); - - /* set sampling rate */ - snd_ac97_set_rate(ml403_ac97cr->ac97, AC97_PCM_LR_ADC_RATE, - runtime->rate); - PDEBUG(WORK_INFO, "prepare(capture): rate=%d\n", runtime->rate); - - /* init struct for intermediate buffer */ - memset(&ml403_ac97cr->capture_ind2_rec, 0, - sizeof(struct snd_pcm_indirect2)); - ml403_ac97cr->capture_ind2_rec.hw_buffer_size = CR_FIFO_SIZE; - ml403_ac97cr->capture_ind2_rec.sw_buffer_size = - snd_pcm_lib_buffer_bytes(substream); - ml403_ac97cr->capture_ind2_rec.min_multiple = - snd_pcm_lib_period_bytes(substream) / (CR_FIFO_SIZE / 2); - PDEBUG(WORK_INFO, "prepare(capture): hw_buffer_size=%d, " - "sw_buffer_size=%d, min_multiple=%d\n", CR_FIFO_SIZE, - ml403_ac97cr->capture_ind2_rec.sw_buffer_size, - ml403_ac97cr->capture_ind2_rec.min_multiple); - return 0; -} - -static int snd_ml403_ac97cr_hw_free(struct snd_pcm_substream *substream) -{ - PDEBUG(WORK_INFO, "hw_free()\n"); - return snd_pcm_lib_free_pages(substream); -} - -static int -snd_ml403_ac97cr_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - PDEBUG(WORK_INFO, "hw_params(): desired buffer bytes=%d, desired " - "period bytes=%d\n", - params_buffer_bytes(hw_params), params_period_bytes(hw_params)); - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int snd_ml403_ac97cr_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_runtime *runtime; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - PDEBUG(WORK_INFO, "open(playback)\n"); - ml403_ac97cr->playback_substream = substream; - runtime->hw = snd_ml403_ac97cr_playback; - - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - CR_FIFO_SIZE / 2); - return 0; -} - -static int snd_ml403_ac97cr_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct snd_pcm_runtime *runtime; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - PDEBUG(WORK_INFO, "open(capture)\n"); - ml403_ac97cr->capture_substream = substream; - runtime->hw = snd_ml403_ac97cr_capture; - - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - CR_FIFO_SIZE / 2); - return 0; -} - -static int snd_ml403_ac97cr_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - PDEBUG(WORK_INFO, "close(playback)\n"); - ml403_ac97cr->playback_substream = NULL; - return 0; -} - -static int snd_ml403_ac97cr_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - - ml403_ac97cr = snd_pcm_substream_chip(substream); - - PDEBUG(WORK_INFO, "close(capture)\n"); - ml403_ac97cr->capture_substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_ml403_ac97cr_playback_ops = { - .open = snd_ml403_ac97cr_playback_open, - .close = snd_ml403_ac97cr_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ml403_ac97cr_hw_params, - .hw_free = snd_ml403_ac97cr_hw_free, - .prepare = snd_ml403_ac97cr_pcm_playback_prepare, - .trigger = snd_ml403_ac97cr_pcm_playback_trigger, - .pointer = snd_ml403_ac97cr_pcm_pointer, -}; - -static struct snd_pcm_ops snd_ml403_ac97cr_capture_ops = { - .open = snd_ml403_ac97cr_capture_open, - .close = snd_ml403_ac97cr_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ml403_ac97cr_hw_params, - .hw_free = snd_ml403_ac97cr_hw_free, - .prepare = snd_ml403_ac97cr_pcm_capture_prepare, - .trigger = snd_ml403_ac97cr_pcm_capture_trigger, - .pointer = snd_ml403_ac97cr_pcm_pointer, -}; - -static irqreturn_t snd_ml403_ac97cr_irq(int irq, void *dev_id) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - struct platform_device *pfdev; - int cmp_irq; - - ml403_ac97cr = (struct snd_ml403_ac97cr *)dev_id; - if (ml403_ac97cr == NULL) - return IRQ_NONE; - - pfdev = ml403_ac97cr->pfdev; - - /* playback interrupt */ - cmp_irq = platform_get_irq(pfdev, 0); - if (irq == cmp_irq) { - if (ml403_ac97cr->enable_irq) - snd_pcm_indirect2_playback_interrupt( - ml403_ac97cr->playback_substream, - &ml403_ac97cr->ind_rec, - snd_ml403_ac97cr_playback_ind2_copy, - snd_ml403_ac97cr_playback_ind2_zero); - else - goto __disable_irq; - } else { - /* record interrupt */ - cmp_irq = platform_get_irq(pfdev, 1); - if (irq == cmp_irq) { - if (ml403_ac97cr->enable_capture_irq) - snd_pcm_indirect2_capture_interrupt( - ml403_ac97cr->capture_substream, - &ml403_ac97cr->capture_ind2_rec, - snd_ml403_ac97cr_capture_ind2_copy, - snd_ml403_ac97cr_capture_ind2_null); - else - goto __disable_irq; - } else - return IRQ_NONE; - } - return IRQ_HANDLED; - -__disable_irq: - PDEBUG(INIT_INFO, "irq(): irq %d is meant to be disabled! So, now try " - "to disable it _really_!\n", irq); - disable_irq_nosync(irq); - return IRQ_HANDLED; -} - -static unsigned short -snd_ml403_ac97cr_codec_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_ml403_ac97cr *ml403_ac97cr = ac97->private_data; -#ifdef CODEC_STAT - u32 stat; - u32 rafaccess = 0; -#endif - unsigned long end_time; - u16 value = 0; - - if (!LM4550_RF_OK(reg)) { - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "access to unknown/unused codec register 0x%x " - "ignored!\n", reg); - return 0; - } - /* check if we can fake/answer this access from our shadow register */ - if ((lm4550_regfile[reg / 2].flag & - (LM4550_REG_DONEREAD | LM4550_REG_ALLFAKE)) && - !(lm4550_regfile[reg / 2].flag & LM4550_REG_NOSHADOW)) { - if (lm4550_regfile[reg / 2].flag & LM4550_REG_FAKEREAD) { - PDEBUG(CODEC_FAKE, "codec_read(): faking read from " - "reg=0x%x, val=0x%x / %d\n", - reg, lm4550_regfile[reg / 2].def, - lm4550_regfile[reg / 2].def); - return lm4550_regfile[reg / 2].def; - } else if ((lm4550_regfile[reg / 2].flag & - LM4550_REG_FAKEPROBE) && - ml403_ac97cr->ac97_fake) { - PDEBUG(CODEC_FAKE, "codec_read(): faking read from " - "reg=0x%x, val=0x%x / %d (probe)\n", - reg, lm4550_regfile[reg / 2].value, - lm4550_regfile[reg / 2].value); - return lm4550_regfile[reg / 2].value; - } else { -#ifdef CODEC_STAT - PDEBUG(CODEC_FAKE, "codec_read(): read access " - "answered by shadow register 0x%x (value=0x%x " - "/ %d) (cw=%d cr=%d)\n", - reg, lm4550_regfile[reg / 2].value, - lm4550_regfile[reg / 2].value, - ml403_ac97cr->ac97_write, - ml403_ac97cr->ac97_read); -#else - PDEBUG(CODEC_FAKE, "codec_read(): read access " - "answered by shadow register 0x%x (value=0x%x " - "/ %d)\n", - reg, lm4550_regfile[reg / 2].value, - lm4550_regfile[reg / 2].value); -#endif - return lm4550_regfile[reg / 2].value; - } - } - /* if we are here, we _have_ to access the codec really, no faking */ - if (mutex_lock_interruptible(&ml403_ac97cr->cdc_mutex) != 0) - return 0; -#ifdef CODEC_STAT - ml403_ac97cr->ac97_read++; -#endif - spin_lock(&ml403_ac97cr->reg_lock); - out_be32(CR_REG(ml403_ac97cr, CODEC_ADDR), - CR_CODEC_ADDR(reg) | CR_CODEC_READ); - spin_unlock(&ml403_ac97cr->reg_lock); - end_time = jiffies + (HZ / CODEC_TIMEOUT_AFTER_READ); - do { - spin_lock(&ml403_ac97cr->reg_lock); -#ifdef CODEC_STAT - rafaccess++; - stat = in_be32(CR_REG(ml403_ac97cr, STATUS)); - if ((stat & CR_RAF) == CR_RAF) { - value = CR_CODEC_DATAREAD( - in_be32(CR_REG(ml403_ac97cr, CODEC_DATAREAD))); - PDEBUG(CODEC_SUCCESS, "codec_read(): (done) reg=0x%x, " - "value=0x%x / %d (STATUS=0x%x)\n", - reg, value, value, stat); -#else - if ((in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_RAF) == CR_RAF) { - value = CR_CODEC_DATAREAD( - in_be32(CR_REG(ml403_ac97cr, CODEC_DATAREAD))); - PDEBUG(CODEC_SUCCESS, "codec_read(): (done) " - "reg=0x%x, value=0x%x / %d\n", - reg, value, value); -#endif - lm4550_regfile[reg / 2].value = value; - lm4550_regfile[reg / 2].flag |= LM4550_REG_DONEREAD; - spin_unlock(&ml403_ac97cr->reg_lock); - mutex_unlock(&ml403_ac97cr->cdc_mutex); - return value; - } - spin_unlock(&ml403_ac97cr->reg_lock); - schedule_timeout_uninterruptible(1); - } while (time_after(end_time, jiffies)); - /* read the DATAREAD register anyway, see comment below */ - spin_lock(&ml403_ac97cr->reg_lock); - value = - CR_CODEC_DATAREAD(in_be32(CR_REG(ml403_ac97cr, CODEC_DATAREAD))); - spin_unlock(&ml403_ac97cr->reg_lock); -#ifdef CODEC_STAT - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "timeout while codec read! " - "(reg=0x%x, last STATUS=0x%x, DATAREAD=0x%x / %d, %d) " - "(cw=%d, cr=%d)\n", - reg, stat, value, value, rafaccess, - ml403_ac97cr->ac97_write, ml403_ac97cr->ac97_read); -#else - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "timeout while codec read! " - "(reg=0x%x, DATAREAD=0x%x / %d)\n", - reg, value, value); -#endif - /* BUG: This is PURE speculation! But after _most_ read timeouts the - * value in the register is ok! - */ - lm4550_regfile[reg / 2].value = value; - lm4550_regfile[reg / 2].flag |= LM4550_REG_DONEREAD; - mutex_unlock(&ml403_ac97cr->cdc_mutex); - return value; -} - -static void -snd_ml403_ac97cr_codec_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct snd_ml403_ac97cr *ml403_ac97cr = ac97->private_data; - -#ifdef CODEC_STAT - u32 stat; - u32 rafaccess = 0; -#endif -#ifdef CODEC_WRITE_CHECK_RAF - unsigned long end_time; -#endif - - if (!LM4550_RF_OK(reg)) { - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "access to unknown/unused codec register 0x%x " - "ignored!\n", reg); - return; - } - if (lm4550_regfile[reg / 2].flag & LM4550_REG_READONLY) { - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "write access to read only codec register 0x%x " - "ignored!\n", reg); - return; - } - if ((val & lm4550_regfile[reg / 2].wmask) != val) { - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "write access to codec register 0x%x " - "with bad value 0x%x / %d!\n", - reg, val, val); - val = val & lm4550_regfile[reg / 2].wmask; - } - if (((lm4550_regfile[reg / 2].flag & LM4550_REG_FAKEPROBE) && - ml403_ac97cr->ac97_fake) && - !(lm4550_regfile[reg / 2].flag & LM4550_REG_NOSHADOW)) { - PDEBUG(CODEC_FAKE, "codec_write(): faking write to reg=0x%x, " - "val=0x%x / %d\n", reg, val, val); - lm4550_regfile[reg / 2].value = (val & - lm4550_regfile[reg / 2].wmask); - return; - } - if (mutex_lock_interruptible(&ml403_ac97cr->cdc_mutex) != 0) - return; -#ifdef CODEC_STAT - ml403_ac97cr->ac97_write++; -#endif - spin_lock(&ml403_ac97cr->reg_lock); - out_be32(CR_REG(ml403_ac97cr, CODEC_DATAWRITE), - CR_CODEC_DATAWRITE(val)); - out_be32(CR_REG(ml403_ac97cr, CODEC_ADDR), - CR_CODEC_ADDR(reg) | CR_CODEC_WRITE); - spin_unlock(&ml403_ac97cr->reg_lock); -#ifdef CODEC_WRITE_CHECK_RAF - /* check CR_CODEC_RAF bit to see if write access to register is done; - * loop until bit is set or timeout happens - */ - end_time = jiffies + HZ / CODEC_TIMEOUT_AFTER_WRITE; - do { - spin_lock(&ml403_ac97cr->reg_lock); -#ifdef CODEC_STAT - rafaccess++; - stat = in_be32(CR_REG(ml403_ac97cr, STATUS)) - if ((stat & CR_RAF) == CR_RAF) { -#else - if ((in_be32(CR_REG(ml403_ac97cr, STATUS)) & - CR_RAF) == CR_RAF) { -#endif - PDEBUG(CODEC_SUCCESS, "codec_write(): (done) " - "reg=0x%x, value=%d / 0x%x\n", - reg, val, val); - if (!(lm4550_regfile[reg / 2].flag & - LM4550_REG_NOSHADOW) && - !(lm4550_regfile[reg / 2].flag & - LM4550_REG_NOSAVE)) - lm4550_regfile[reg / 2].value = val; - lm4550_regfile[reg / 2].flag |= LM4550_REG_DONEREAD; - spin_unlock(&ml403_ac97cr->reg_lock); - mutex_unlock(&ml403_ac97cr->cdc_mutex); - return; - } - spin_unlock(&ml403_ac97cr->reg_lock); - schedule_timeout_uninterruptible(1); - } while (time_after(end_time, jiffies)); -#ifdef CODEC_STAT - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "timeout while codec write " - "(reg=0x%x, val=0x%x / %d, last STATUS=0x%x, %d) " - "(cw=%d, cr=%d)\n", - reg, val, val, stat, rafaccess, ml403_ac97cr->ac97_write, - ml403_ac97cr->ac97_read); -#else - snd_printk(KERN_WARNING SND_ML403_AC97CR_DRIVER ": " - "timeout while codec write (reg=0x%x, val=0x%x / %d)\n", - reg, val, val); -#endif -#else /* CODEC_WRITE_CHECK_RAF */ -#if CODEC_WAIT_AFTER_WRITE > 0 - /* officially, in AC97 spec there is no possibility for a AC97 - * controller to determine, if write access is done or not - so: How - * is Xilinx able to provide a RAF bit for write access? - * => very strange, thus just don't check RAF bit (compare with - * Xilinx's example app in EDK 8.1i) and wait - */ - schedule_timeout_uninterruptible(HZ / CODEC_WAIT_AFTER_WRITE); -#endif - PDEBUG(CODEC_SUCCESS, "codec_write(): (done) " - "reg=0x%x, value=%d / 0x%x (no RAF check)\n", - reg, val, val); -#endif - mutex_unlock(&ml403_ac97cr->cdc_mutex); - return; -} - -static int __devinit -snd_ml403_ac97cr_chip_init(struct snd_ml403_ac97cr *ml403_ac97cr) -{ - unsigned long end_time; - PDEBUG(INIT_INFO, "chip_init():\n"); - end_time = jiffies + HZ / CODEC_TIMEOUT_ON_INIT; - do { - if (in_be32(CR_REG(ml403_ac97cr, STATUS)) & CR_CODECREADY) { - /* clear both hardware FIFOs */ - out_be32(CR_REG(ml403_ac97cr, RESETFIFO), - CR_RECRESET | CR_PLAYRESET); - PDEBUG(INIT_INFO, "chip_init(): (done)\n"); - return 0; - } - schedule_timeout_uninterruptible(1); - } while (time_after(end_time, jiffies)); - snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " - "timeout while waiting for codec, " - "not ready!\n"); - return -EBUSY; -} - -static int snd_ml403_ac97cr_free(struct snd_ml403_ac97cr *ml403_ac97cr) -{ - PDEBUG(INIT_INFO, "free():\n"); - /* irq release */ - if (ml403_ac97cr->irq >= 0) - free_irq(ml403_ac97cr->irq, ml403_ac97cr); - if (ml403_ac97cr->capture_irq >= 0) - free_irq(ml403_ac97cr->capture_irq, ml403_ac97cr); - /* give back "port" */ - if (ml403_ac97cr->port != NULL) - iounmap(ml403_ac97cr->port); - kfree(ml403_ac97cr); - PDEBUG(INIT_INFO, "free(): (done)\n"); - return 0; -} - -static int snd_ml403_ac97cr_dev_free(struct snd_device *snddev) -{ - struct snd_ml403_ac97cr *ml403_ac97cr = snddev->device_data; - PDEBUG(INIT_INFO, "dev_free():\n"); - return snd_ml403_ac97cr_free(ml403_ac97cr); -} - -static int __devinit -snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev, - struct snd_ml403_ac97cr **rml403_ac97cr) -{ - struct snd_ml403_ac97cr *ml403_ac97cr; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_ml403_ac97cr_dev_free, - }; - struct resource *resource; - int irq; - - *rml403_ac97cr = NULL; - ml403_ac97cr = kzalloc(sizeof(*ml403_ac97cr), GFP_KERNEL); - if (ml403_ac97cr == NULL) - return -ENOMEM; - spin_lock_init(&ml403_ac97cr->reg_lock); - mutex_init(&ml403_ac97cr->cdc_mutex); - ml403_ac97cr->card = card; - ml403_ac97cr->pfdev = pfdev; - ml403_ac97cr->irq = -1; - ml403_ac97cr->enable_irq = 0; - ml403_ac97cr->capture_irq = -1; - ml403_ac97cr->enable_capture_irq = 0; - ml403_ac97cr->port = NULL; - ml403_ac97cr->res_port = NULL; - - PDEBUG(INIT_INFO, "Trying to reserve resources now ...\n"); - resource = platform_get_resource(pfdev, IORESOURCE_MEM, 0); - /* get "port" */ - ml403_ac97cr->port = ioremap_nocache(resource->start, - (resource->end) - - (resource->start) + 1); - if (ml403_ac97cr->port == NULL) { - snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " - "unable to remap memory region (%pR)\n", - resource); - snd_ml403_ac97cr_free(ml403_ac97cr); - return -EBUSY; - } - snd_printk(KERN_INFO SND_ML403_AC97CR_DRIVER ": " - "remap controller memory region to " - "0x%x done\n", (unsigned int)ml403_ac97cr->port); - /* get irq */ - irq = platform_get_irq(pfdev, 0); - if (request_irq(irq, snd_ml403_ac97cr_irq, 0, - dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { - snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " - "unable to grab IRQ %d\n", - irq); - snd_ml403_ac97cr_free(ml403_ac97cr); - return -EBUSY; - } - ml403_ac97cr->irq = irq; - snd_printk(KERN_INFO SND_ML403_AC97CR_DRIVER ": " - "request (playback) irq %d done\n", - ml403_ac97cr->irq); - irq = platform_get_irq(pfdev, 1); - if (request_irq(irq, snd_ml403_ac97cr_irq, 0, - dev_name(&pfdev->dev), (void *)ml403_ac97cr)) { - snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": " - "unable to grab IRQ %d\n", - irq); - snd_ml403_ac97cr_free(ml403_ac97cr); - return -EBUSY; - } - ml403_ac97cr->capture_irq = irq; - snd_printk(KERN_INFO SND_ML403_AC97CR_DRIVER ": " - "request (capture) irq %d done\n", - ml403_ac97cr->capture_irq); - - err = snd_ml403_ac97cr_chip_init(ml403_ac97cr); - if (err < 0) { - snd_ml403_ac97cr_free(ml403_ac97cr); - return err; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ml403_ac97cr, &ops); - if (err < 0) { - PDEBUG(INIT_FAILURE, "probe(): snd_device_new() failed!\n"); - snd_ml403_ac97cr_free(ml403_ac97cr); - return err; - } - - *rml403_ac97cr = ml403_ac97cr; - return 0; -} - -static void snd_ml403_ac97cr_mixer_free(struct snd_ac97 *ac97) -{ - struct snd_ml403_ac97cr *ml403_ac97cr = ac97->private_data; - PDEBUG(INIT_INFO, "mixer_free():\n"); - ml403_ac97cr->ac97 = NULL; - PDEBUG(INIT_INFO, "mixer_free(): (done)\n"); -} - -static int __devinit -snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr) -{ - struct snd_ac97_bus *bus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_ml403_ac97cr_codec_write, - .read = snd_ml403_ac97cr_codec_read, - }; - PDEBUG(INIT_INFO, "mixer():\n"); - err = snd_ac97_bus(ml403_ac97cr->card, 0, &ops, NULL, &bus); - if (err < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ml403_ac97cr->ac97_fake = 1; - lm4550_regfile_init(); -#ifdef CODEC_STAT - ml403_ac97cr->ac97_read = 0; - ml403_ac97cr->ac97_write = 0; -#endif - ac97.private_data = ml403_ac97cr; - ac97.private_free = snd_ml403_ac97cr_mixer_free; - ac97.scaps = AC97_SCAP_AUDIO | AC97_SCAP_SKIP_MODEM | - AC97_SCAP_NO_SPDIF; - err = snd_ac97_mixer(bus, &ac97, &ml403_ac97cr->ac97); - ml403_ac97cr->ac97_fake = 0; - lm4550_regfile_write_values_after_init(ml403_ac97cr->ac97); - PDEBUG(INIT_INFO, "mixer(): (done) snd_ac97_mixer()=%d\n", err); - return err; -} - -static int __devinit -snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device, - struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - err = snd_pcm_new(ml403_ac97cr->card, "ML403AC97CR/1", device, 1, 1, - &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_ml403_ac97cr_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_ml403_ac97cr_capture_ops); - pcm->private_data = ml403_ac97cr; - pcm->info_flags = 0; - strcpy(pcm->name, "ML403AC97CR DAC/ADC"); - ml403_ac97cr->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 64 * 1024, - 128 * 1024); - if (rpcm) - *rpcm = pcm; - return 0; -} - -static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev) -{ - struct snd_card *card; - struct snd_ml403_ac97cr *ml403_ac97cr = NULL; - int err; - int dev = pfdev->id; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) - return -ENOENT; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr); - if (err < 0) { - PDEBUG(INIT_FAILURE, "probe(): create failed!\n"); - snd_card_free(card); - return err; - } - PDEBUG(INIT_INFO, "probe(): create done\n"); - card->private_data = ml403_ac97cr; - err = snd_ml403_ac97cr_mixer(ml403_ac97cr); - if (err < 0) { - snd_card_free(card); - return err; - } - PDEBUG(INIT_INFO, "probe(): mixer done\n"); - err = snd_ml403_ac97cr_pcm(ml403_ac97cr, 0, NULL); - if (err < 0) { - snd_card_free(card); - return err; - } - PDEBUG(INIT_INFO, "probe(): PCM done\n"); - strcpy(card->driver, SND_ML403_AC97CR_DRIVER); - strcpy(card->shortname, "ML403 AC97 Controller Reference"); - sprintf(card->longname, "%s %s at 0x%lx, irq %i & %i, device %i", - card->shortname, card->driver, - (unsigned long)ml403_ac97cr->port, ml403_ac97cr->irq, - ml403_ac97cr->capture_irq, dev + 1); - - snd_card_set_dev(card, &pfdev->dev); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - platform_set_drvdata(pfdev, card); - PDEBUG(INIT_INFO, "probe(): (done)\n"); - return 0; -} - -static int snd_ml403_ac97cr_remove(struct platform_device *pfdev) -{ - snd_card_free(platform_get_drvdata(pfdev)); - platform_set_drvdata(pfdev, NULL); - return 0; -} - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:" SND_ML403_AC97CR_DRIVER); - -static struct platform_driver snd_ml403_ac97cr_driver = { - .probe = snd_ml403_ac97cr_probe, - .remove = snd_ml403_ac97cr_remove, - .driver = { - .name = SND_ML403_AC97CR_DRIVER, - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(snd_ml403_ac97cr_driver); diff --git a/ANDROID_3.4.5/sound/drivers/mpu401/Makefile b/ANDROID_3.4.5/sound/drivers/mpu401/Makefile deleted file mode 100644 index 918f83f3..00000000 --- a/ANDROID_3.4.5/sound/drivers/mpu401/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-mpu401-objs := mpu401.o -snd-mpu401-uart-objs := mpu401_uart.o - -obj-$(CONFIG_SND_MPU401_UART) += snd-mpu401-uart.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_MPU401) += snd-mpu401.o diff --git a/ANDROID_3.4.5/sound/drivers/mpu401/mpu401.c b/ANDROID_3.4.5/sound/drivers/mpu401/mpu401.c deleted file mode 100644 index 86f5fbc2..00000000 --- a/ANDROID_3.4.5/sound/drivers/mpu401/mpu401.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Driver for generic MPU-401 boards (UART mode only) - * Copyright (c) by Jaroslav Kysela - * Copyright (c) 2004 by Castet Matthieu - * - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("MPU-401 UART"); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -#ifdef CONFIG_PNP -static bool pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */ -static bool uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for MPU-401 device."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for MPU-401 device."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable MPU-401 device."); -#ifdef CONFIG_PNP -module_param_array(pnp, bool, NULL, 0444); -MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for MPU-401 device."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); -module_param_array(uart_enter, bool, NULL, 0444); -MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open."); - -static struct platform_device *platform_devices[SNDRV_CARDS]; -static int pnp_registered; -static unsigned int snd_mpu401_devices; - -static int snd_mpu401_create(int dev, struct snd_card **rcard) -{ - struct snd_card *card; - int err; - - if (!uart_enter[dev]) - snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); - - *rcard = NULL; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - strcpy(card->driver, "MPU-401 UART"); - strcpy(card->shortname, card->driver); - sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); - if (irq[dev] >= 0) { - sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]); - } else { - strcat(card->longname, "polled"); - } - - err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, - irq[dev], NULL); - if (err < 0) { - printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); - goto _err; - } - - *rcard = card; - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devinit snd_mpu401_probe(struct platform_device *devptr) -{ - int dev = devptr->id; - int err; - struct snd_card *card; - - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify port\n"); - return -EINVAL; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - snd_printk(KERN_ERR "specify or disable IRQ\n"); - return -EINVAL; - } - err = snd_mpu401_create(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, &devptr->dev); - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - platform_set_drvdata(devptr, card); - return 0; -} - -static int __devexit snd_mpu401_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SND_MPU401_DRIVER "snd_mpu401" - -static struct platform_driver snd_mpu401_driver = { - .probe = snd_mpu401_probe, - .remove = __devexit_p(snd_mpu401_remove), - .driver = { - .name = SND_MPU401_DRIVER - }, -}; - - -#ifdef CONFIG_PNP - -#define IO_EXTENT 2 - -static struct pnp_device_id snd_mpu401_pnpids[] = { - { .id = "PNPb006" }, - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids); - -static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device, - const struct pnp_device_id *id) -{ - if (!pnp_port_valid(device, 0) || - pnp_port_flags(device, 0) & IORESOURCE_DISABLED) { - snd_printk(KERN_ERR "no PnP port\n"); - return -ENODEV; - } - if (pnp_port_len(device, 0) < IO_EXTENT) { - snd_printk(KERN_ERR "PnP port length is %llu, expected %d\n", - (unsigned long long)pnp_port_len(device, 0), - IO_EXTENT); - return -ENODEV; - } - port[dev] = pnp_port_start(device, 0); - - if (!pnp_irq_valid(device, 0) || - pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) { - snd_printk(KERN_WARNING "no PnP irq, using polling\n"); - irq[dev] = -1; - } else { - irq[dev] = pnp_irq(device, 0); - } - return 0; -} - -static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, - const struct pnp_device_id *id) -{ - static int dev; - struct snd_card *card; - int err; - - for ( ; dev < SNDRV_CARDS; ++dev) { - if (!enable[dev] || !pnp[dev]) - continue; - err = snd_mpu401_pnp(dev, pnp_dev, id); - if (err < 0) - return err; - err = snd_mpu401_create(dev, &card); - if (err < 0) - return err; - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pnp_dev->dev); - pnp_set_drvdata(pnp_dev, card); - snd_mpu401_devices++; - ++dev; - return 0; - } - return -ENODEV; -} - -static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev) -{ - struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev); - - snd_card_disconnect(card); - snd_card_free_when_closed(card); -} - -static struct pnp_driver snd_mpu401_pnp_driver = { - .name = "mpu401", - .id_table = snd_mpu401_pnpids, - .probe = snd_mpu401_pnp_probe, - .remove = __devexit_p(snd_mpu401_pnp_remove), -}; -#else -static struct pnp_driver snd_mpu401_pnp_driver; -#endif - -static void snd_mpu401_unregister_all(void) -{ - int i; - - if (pnp_registered) - pnp_unregister_driver(&snd_mpu401_pnp_driver); - for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) - platform_device_unregister(platform_devices[i]); - platform_driver_unregister(&snd_mpu401_driver); -} - -static int __init alsa_card_mpu401_init(void) -{ - int i, err; - - if ((err = platform_driver_register(&snd_mpu401_driver)) < 0) - return err; - - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; -#ifdef CONFIG_PNP - if (pnp[i]) - continue; -#endif - device = platform_device_register_simple(SND_MPU401_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - platform_devices[i] = device; - snd_mpu401_devices++; - } - err = pnp_register_driver(&snd_mpu401_pnp_driver); - if (!err) - pnp_registered = 1; - - if (!snd_mpu401_devices) { -#ifdef MODULE - printk(KERN_ERR "MPU-401 device not found or device busy\n"); -#endif - snd_mpu401_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_mpu401_exit(void) -{ - snd_mpu401_unregister_all(); -} - -module_init(alsa_card_mpu401_init) -module_exit(alsa_card_mpu401_exit) diff --git a/ANDROID_3.4.5/sound/drivers/mpu401/mpu401_uart.c b/ANDROID_3.4.5/sound/drivers/mpu401/mpu401_uart.c deleted file mode 100644 index 1cff331a..00000000 --- a/ANDROID_3.4.5/sound/drivers/mpu401/mpu401_uart.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of MPU-401 in UART mode - * - * MPU-401 supports UART mode which is not capable generate transmit - * interrupts thus output is done via polling. Without interrupt, - * input is done also via polling. Do not expect good performance. - * - * - * 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 - * - * 13-03-2003: - * Added support for different kind of hardware I/O. Build in choices - * are port and mmio. For other kind of I/O, set mpu->read and - * mpu->write to your own I/O functions. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode"); -MODULE_LICENSE("GPL"); - -static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu); -static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu); - -/* - - */ - -#define snd_mpu401_input_avail(mpu) \ - (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY)) -#define snd_mpu401_output_ready(mpu) \ - (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL)) - -/* Build in lowlevel io */ -static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, - unsigned long addr) -{ - outb(data, addr); -} - -static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, - unsigned long addr) -{ - return inb(addr); -} - -static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, - unsigned long addr) -{ - writeb(data, (void __iomem *)addr); -} - -static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, - unsigned long addr) -{ - return readb((void __iomem *)addr); -} -/* */ - -static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) -{ - int timeout = 100000; - for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--) - mpu->read(mpu, MPU401D(mpu)); -#ifdef CONFIG_SND_DEBUG - if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", - mpu->read(mpu, MPU401C(mpu))); -#endif -} - -static void uart_interrupt_tx(struct snd_mpu401 *mpu) -{ - unsigned long flags; - - if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && - test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { - spin_lock_irqsave(&mpu->output_lock, flags); - snd_mpu401_uart_output_write(mpu); - spin_unlock_irqrestore(&mpu->output_lock, flags); - } -} - -static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) -{ - unsigned long flags; - - if (mpu->info_flags & MPU401_INFO_INPUT) { - spin_lock_irqsave(&mpu->input_lock, flags); - if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) - snd_mpu401_uart_input_read(mpu); - else - snd_mpu401_uart_clear_rx(mpu); - spin_unlock_irqrestore(&mpu->input_lock, flags); - } - if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) - /* ok. for better Tx performance try do some output - when input is done */ - uart_interrupt_tx(mpu); -} - -/** - * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler - * @irq: the irq number - * @dev_id: mpu401 instance - * - * Processes the interrupt for MPU401-UART i/o. - */ -irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id) -{ - struct snd_mpu401 *mpu = dev_id; - - if (mpu == NULL) - return IRQ_NONE; - _snd_mpu401_uart_interrupt(mpu); - return IRQ_HANDLED; -} - -EXPORT_SYMBOL(snd_mpu401_uart_interrupt); - -/** - * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler - * @irq: the irq number - * @dev_id: mpu401 instance - * - * Processes the interrupt for MPU401-UART output. - */ -irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id) -{ - struct snd_mpu401 *mpu = dev_id; - - if (mpu == NULL) - return IRQ_NONE; - uart_interrupt_tx(mpu); - return IRQ_HANDLED; -} - -EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx); - -/* - * timer callback - * reprogram the timer and call the interrupt job - */ -static void snd_mpu401_uart_timer(unsigned long data) -{ - struct snd_mpu401 *mpu = (struct snd_mpu401 *)data; - unsigned long flags; - - spin_lock_irqsave(&mpu->timer_lock, flags); - /*mpu->mode |= MPU401_MODE_TIMER;*/ - mpu->timer.expires = 1 + jiffies; - add_timer(&mpu->timer); - spin_unlock_irqrestore(&mpu->timer_lock, flags); - if (mpu->rmidi) - _snd_mpu401_uart_interrupt(mpu); -} - -/* - * initialize the timer callback if not programmed yet - */ -static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input) -{ - unsigned long flags; - - spin_lock_irqsave (&mpu->timer_lock, flags); - if (mpu->timer_invoked == 0) { - init_timer(&mpu->timer); - mpu->timer.data = (unsigned long)mpu; - mpu->timer.function = snd_mpu401_uart_timer; - mpu->timer.expires = 1 + jiffies; - add_timer(&mpu->timer); - } - mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : - MPU401_MODE_OUTPUT_TIMER; - spin_unlock_irqrestore (&mpu->timer_lock, flags); -} - -/* - * remove the timer callback if still active - */ -static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) -{ - unsigned long flags; - - spin_lock_irqsave (&mpu->timer_lock, flags); - if (mpu->timer_invoked) { - mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : - ~MPU401_MODE_OUTPUT_TIMER; - if (! mpu->timer_invoked) - del_timer(&mpu->timer); - } - spin_unlock_irqrestore (&mpu->timer_lock, flags); -} - -/* - * send a UART command - * return zero if successful, non-zero for some errors - */ - -static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, - int ack) -{ - unsigned long flags; - int timeout, ok; - - spin_lock_irqsave(&mpu->input_lock, flags); - if (mpu->hardware != MPU401_HW_TRID4DWAVE) { - mpu->write(mpu, 0x00, MPU401D(mpu)); - /*snd_mpu401_uart_clear_rx(mpu);*/ - } - /* ok. standard MPU-401 initialization */ - if (mpu->hardware != MPU401_HW_SB) { - for (timeout = 1000; timeout > 0 && - !snd_mpu401_output_ready(mpu); timeout--) - udelay(10); -#ifdef CONFIG_SND_DEBUG - if (!timeout) - snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n", - mpu->read(mpu, MPU401C(mpu))); -#endif - } - mpu->write(mpu, cmd, MPU401C(mpu)); - if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (snd_mpu401_input_avail(mpu)) { - if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) - ok = 1; - } - } - if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) - ok = 1; - } else - ok = 1; - spin_unlock_irqrestore(&mpu->input_lock, flags); - if (!ok) { - snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx " - "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port, - mpu->read(mpu, MPU401C(mpu)), - mpu->read(mpu, MPU401D(mpu))); - return 1; - } - return 0; -} - -static int snd_mpu401_do_reset(struct snd_mpu401 *mpu) -{ - if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) - return -EIO; - if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 0)) - return -EIO; - return 0; -} - -/* - * input/output open/close - protected by open_mutex in rawmidi.c - */ -static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_mpu401 *mpu; - int err; - - mpu = substream->rmidi->private_data; - if (mpu->open_input && (err = mpu->open_input(mpu)) < 0) - return err; - if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { - if (snd_mpu401_do_reset(mpu) < 0) - goto error_out; - } - mpu->substream_input = substream; - set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); - return 0; - -error_out: - if (mpu->open_input && mpu->close_input) - mpu->close_input(mpu); - return -EIO; -} - -static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) -{ - struct snd_mpu401 *mpu; - int err; - - mpu = substream->rmidi->private_data; - if (mpu->open_output && (err = mpu->open_output(mpu)) < 0) - return err; - if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { - if (snd_mpu401_do_reset(mpu) < 0) - goto error_out; - } - mpu->substream_output = substream; - set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); - return 0; - -error_out: - if (mpu->open_output && mpu->close_output) - mpu->close_output(mpu); - return -EIO; -} - -static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_mpu401 *mpu; - int err = 0; - - mpu = substream->rmidi->private_data; - clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); - mpu->substream_input = NULL; - if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) - err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); - if (mpu->close_input) - mpu->close_input(mpu); - if (err) - return -EIO; - return 0; -} - -static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_mpu401 *mpu; - int err = 0; - - mpu = substream->rmidi->private_data; - clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); - mpu->substream_output = NULL; - if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) - err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); - if (mpu->close_output) - mpu->close_output(mpu); - if (err) - return -EIO; - return 0; -} - -/* - * trigger input callback - */ -static void -snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_mpu401 *mpu; - int max = 64; - - mpu = substream->rmidi->private_data; - if (up) { - if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, - &mpu->mode)) { - /* first time - flush FIFO */ - while (max-- > 0) - mpu->read(mpu, MPU401D(mpu)); - if (mpu->info_flags & MPU401_INFO_USE_TIMER) - snd_mpu401_uart_add_timer(mpu, 1); - } - - /* read data in advance */ - spin_lock_irqsave(&mpu->input_lock, flags); - snd_mpu401_uart_input_read(mpu); - spin_unlock_irqrestore(&mpu->input_lock, flags); - } else { - if (mpu->info_flags & MPU401_INFO_USE_TIMER) - snd_mpu401_uart_remove_timer(mpu, 1); - clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode); - } - -} - -/* - * transfer input pending data - * call with input_lock spinlock held - */ -static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu) -{ - int max = 128; - unsigned char byte; - - while (max-- > 0) { - if (! snd_mpu401_input_avail(mpu)) - break; /* input not available */ - byte = mpu->read(mpu, MPU401D(mpu)); - if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) - snd_rawmidi_receive(mpu->substream_input, &byte, 1); - } -} - -/* - * Tx FIFO sizes: - * CS4237B - 16 bytes - * AudioDrive ES1688 - 12 bytes - * S3 SonicVibes - 8 bytes - * SoundBlaster AWE 64 - 2 bytes (ugly hardware) - */ - -/* - * write output pending bytes - * call with output_lock spinlock held - */ -static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu) -{ - unsigned char byte; - int max = 256; - - do { - if (snd_rawmidi_transmit_peek(mpu->substream_output, - &byte, 1) == 1) { - /* - * Try twice because there is hardware that insists on - * setting the output busy bit after each write. - */ - if (!snd_mpu401_output_ready(mpu) && - !snd_mpu401_output_ready(mpu)) - break; /* Tx FIFO full - try again later */ - mpu->write(mpu, byte, MPU401D(mpu)); - snd_rawmidi_transmit_ack(mpu->substream_output, 1); - } else { - snd_mpu401_uart_remove_timer (mpu, 0); - break; /* no other data - leave the tx loop */ - } - } while (--max > 0); -} - -/* - * output trigger callback - */ -static void -snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_mpu401 *mpu; - - mpu = substream->rmidi->private_data; - if (up) { - set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); - - /* try to add the timer at each output trigger, - * since the output timer might have been removed in - * snd_mpu401_uart_output_write(). - */ - if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) - snd_mpu401_uart_add_timer(mpu, 0); - - /* output pending data */ - spin_lock_irqsave(&mpu->output_lock, flags); - snd_mpu401_uart_output_write(mpu); - spin_unlock_irqrestore(&mpu->output_lock, flags); - } else { - if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) - snd_mpu401_uart_remove_timer(mpu, 0); - clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); - } -} - -/* - - */ - -static struct snd_rawmidi_ops snd_mpu401_uart_output = -{ - .open = snd_mpu401_uart_output_open, - .close = snd_mpu401_uart_output_close, - .trigger = snd_mpu401_uart_output_trigger, -}; - -static struct snd_rawmidi_ops snd_mpu401_uart_input = -{ - .open = snd_mpu401_uart_input_open, - .close = snd_mpu401_uart_input_close, - .trigger = snd_mpu401_uart_input_trigger, -}; - -static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) -{ - struct snd_mpu401 *mpu = rmidi->private_data; - if (mpu->irq >= 0) - free_irq(mpu->irq, (void *) mpu); - release_and_free_resource(mpu->res); - kfree(mpu); -} - -/** - * snd_mpu401_uart_new - create an MPU401-UART instance - * @card: the card instance - * @device: the device index, zero-based - * @hardware: the hardware type, MPU401_HW_XXXX - * @port: the base address of MPU401 port - * @info_flags: bitflags MPU401_INFO_XXX - * @irq: the ISA irq number, -1 if not to be allocated - * @rrawmidi: the pointer to store the new rawmidi instance - * - * Creates a new MPU-401 instance. - * - * Note that the rawmidi instance is returned on the rrawmidi argument, - * not the mpu401 instance itself. To access to the mpu401 instance, - * cast from rawmidi->private_data (with struct snd_mpu401 magic-cast). - * - * Returns zero if successful, or a negative error code. - */ -int snd_mpu401_uart_new(struct snd_card *card, int device, - unsigned short hardware, - unsigned long port, - unsigned int info_flags, - int irq, - struct snd_rawmidi ** rrawmidi) -{ - struct snd_mpu401 *mpu; - struct snd_rawmidi *rmidi; - int in_enable, out_enable; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT))) - info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT; - in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0; - out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0; - if ((err = snd_rawmidi_new(card, "MPU-401U", device, - out_enable, in_enable, &rmidi)) < 0) - return err; - mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); - if (mpu == NULL) { - snd_printk(KERN_ERR "mpu401_uart: cannot allocate\n"); - snd_device_free(card, rmidi); - return -ENOMEM; - } - rmidi->private_data = mpu; - rmidi->private_free = snd_mpu401_uart_free; - spin_lock_init(&mpu->input_lock); - spin_lock_init(&mpu->output_lock); - spin_lock_init(&mpu->timer_lock); - mpu->hardware = hardware; - if (! (info_flags & MPU401_INFO_INTEGRATED)) { - int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; - mpu->res = request_region(port, res_size, "MPU401 UART"); - if (mpu->res == NULL) { - snd_printk(KERN_ERR "mpu401_uart: " - "unable to grab port 0x%lx size %d\n", - port, res_size); - snd_device_free(card, rmidi); - return -EBUSY; - } - } - if (info_flags & MPU401_INFO_MMIO) { - mpu->write = mpu401_write_mmio; - mpu->read = mpu401_read_mmio; - } else { - mpu->write = mpu401_write_port; - mpu->read = mpu401_read_port; - } - mpu->port = port; - if (hardware == MPU401_HW_PC98II) - mpu->cport = port + 2; - else - mpu->cport = port + 1; - if (irq >= 0) { - if (request_irq(irq, snd_mpu401_uart_interrupt, 0, - "MPU401 UART", (void *) mpu)) { - snd_printk(KERN_ERR "mpu401_uart: " - "unable to grab IRQ %d\n", irq); - snd_device_free(card, rmidi); - return -EBUSY; - } - } - if (irq < 0 && !(info_flags & MPU401_INFO_IRQ_HOOK)) - info_flags |= MPU401_INFO_USE_TIMER; - mpu->info_flags = info_flags; - mpu->irq = irq; - if (card->shortname[0]) - snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", - card->shortname); - else - sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device); - if (out_enable) { - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_mpu401_uart_output); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; - } - if (in_enable) { - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_mpu401_uart_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; - if (out_enable) - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; - } - mpu->rmidi = rmidi; - if (rrawmidi) - *rrawmidi = rmidi; - return 0; -} - -EXPORT_SYMBOL(snd_mpu401_uart_new); - -/* - * INIT part - */ - -static int __init alsa_mpu401_uart_init(void) -{ - return 0; -} - -static void __exit alsa_mpu401_uart_exit(void) -{ -} - -module_init(alsa_mpu401_uart_init) -module_exit(alsa_mpu401_uart_exit) diff --git a/ANDROID_3.4.5/sound/drivers/mtpav.c b/ANDROID_3.4.5/sound/drivers/mtpav.c deleted file mode 100644 index 76930793..00000000 --- a/ANDROID_3.4.5/sound/drivers/mtpav.c +++ /dev/null @@ -1,792 +0,0 @@ -/* - * MOTU Midi Timepiece ALSA Main routines - * Copyright by Michael T. Mayers (c) Jan 09, 2000 - * mail: michael@tweakoz.com - * Thanks to John Galbraith - * - * 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 - * - * - * This driver is for the 'Mark Of The Unicorn' (MOTU) - * MidiTimePiece AV multiport MIDI interface - * - * IOPORTS - * ------- - * 8 MIDI Ins and 8 MIDI outs - * Video Sync In (BNC), Word Sync Out (BNC), - * ADAT Sync Out (DB9) - * SMPTE in/out (1/4") - * 2 programmable pedal/footswitch inputs and 4 programmable MIDI controller knobs. - * Macintosh RS422 serial port - * RS422 "network" port for ganging multiple MTP's - * PC Parallel Port ( which this driver currently uses ) - * - * MISC FEATURES - * ------------- - * Hardware MIDI routing, merging, and filtering - * MIDI Synchronization to Video, ADAT, SMPTE and other Clock sources - * 128 'scene' memories, recallable from MIDI program change - * - * - * ChangeLog - * Jun 11 2001 Takashi Iwai - * - Recoded & debugged - * - Added timer interrupt for midi outputs - * - hwports is between 1 and 8, which specifies the number of hardware ports. - * The three global ports, computer, adat and broadcast ports, are created - * always after h/w and remote ports. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * globals - */ -MODULE_AUTHOR("Michael T. Mayers"); -MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{MOTU,MidiTimePiece AV multiport MIDI}}"); - -// io resources -#define MTPAV_IOBASE 0x378 -#define MTPAV_IRQ 7 -#define MTPAV_MAX_PORTS 8 - -static int index = SNDRV_DEFAULT_IDX1; -static char *id = SNDRV_DEFAULT_STR1; -static long port = MTPAV_IOBASE; /* 0x378, 0x278 */ -static int irq = MTPAV_IRQ; /* 7, 5 */ -static int hwports = MTPAV_MAX_PORTS; /* use hardware ports 1-8 */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI."); -module_param(port, long, 0444); -MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI."); -module_param(irq, int, 0444); -MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI."); -module_param(hwports, int, 0444); -MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI."); - -static struct platform_device *device; - -/* - * defines - */ -//#define USE_FAKE_MTP // don't actually read/write to MTP device (for debugging without an actual unit) (does not work yet) - -// parallel port usage masks -#define SIGS_BYTE 0x08 -#define SIGS_RFD 0x80 -#define SIGS_IRQ 0x40 -#define SIGS_IN0 0x10 -#define SIGS_IN1 0x20 - -#define SIGC_WRITE 0x04 -#define SIGC_READ 0x08 -#define SIGC_INTEN 0x10 - -#define DREG 0 -#define SREG 1 -#define CREG 2 - -// -#define MTPAV_MODE_INPUT_OPENED 0x01 -#define MTPAV_MODE_OUTPUT_OPENED 0x02 -#define MTPAV_MODE_INPUT_TRIGGERED 0x04 -#define MTPAV_MODE_OUTPUT_TRIGGERED 0x08 - -#define NUMPORTS (0x12+1) - - -/* - */ - -struct mtpav_port { - u8 number; - u8 hwport; - u8 mode; - u8 running_status; - struct snd_rawmidi_substream *input; - struct snd_rawmidi_substream *output; -}; - -struct mtpav { - struct snd_card *card; - unsigned long port; - struct resource *res_port; - int irq; /* interrupt (for inputs) */ - spinlock_t spinlock; - int share_irq; /* number of accesses to input interrupts */ - int istimer; /* number of accesses to timer interrupts */ - struct timer_list timer; /* timer interrupts for outputs */ - struct snd_rawmidi *rmidi; - int num_ports; /* number of hw ports (1-8) */ - struct mtpav_port ports[NUMPORTS]; /* all ports including computer, adat and bc */ - - u32 inmidiport; /* selected input midi port */ - u32 inmidistate; /* during midi command 0xf5 */ - - u32 outmidihwport; /* selected output midi hw port */ -}; - - -/* - * possible hardware ports (selected by 0xf5 port message) - * 0x00 all ports - * 0x01 .. 0x08 this MTP's ports 1..8 - * 0x09 .. 0x10 networked MTP's ports (9..16) - * 0x11 networked MTP's computer port - * 0x63 to ADAT - * - * mappig: - * subdevice 0 - (X-1) ports - * X - (2*X-1) networked ports - * X computer - * X+1 ADAT - * X+2 all ports - * - * where X = chip->num_ports - */ - -#define MTPAV_PIDX_COMPUTER 0 -#define MTPAV_PIDX_ADAT 1 -#define MTPAV_PIDX_BROADCAST 2 - - -static int translate_subdevice_to_hwport(struct mtpav *chip, int subdev) -{ - if (subdev < 0) - return 0x01; /* invalid - use port 0 as default */ - else if (subdev < chip->num_ports) - return subdev + 1; /* single mtp port */ - else if (subdev < chip->num_ports * 2) - return subdev - chip->num_ports + 0x09; /* remote port */ - else if (subdev == chip->num_ports * 2 + MTPAV_PIDX_COMPUTER) - return 0x11; /* computer port */ - else if (subdev == chip->num_ports + MTPAV_PIDX_ADAT) - return 0x63; /* ADAT */ - return 0; /* all ports */ -} - -static int translate_hwport_to_subdevice(struct mtpav *chip, int hwport) -{ - int p; - if (hwport <= 0x00) /* all ports */ - return chip->num_ports + MTPAV_PIDX_BROADCAST; - else if (hwport <= 0x08) { /* single port */ - p = hwport - 1; - if (p >= chip->num_ports) - p = 0; - return p; - } else if (hwport <= 0x10) { /* remote port */ - p = hwport - 0x09 + chip->num_ports; - if (p >= chip->num_ports * 2) - p = chip->num_ports; - return p; - } else if (hwport == 0x11) /* computer port */ - return chip->num_ports + MTPAV_PIDX_COMPUTER; - else /* ADAT */ - return chip->num_ports + MTPAV_PIDX_ADAT; -} - - -/* - */ - -static u8 snd_mtpav_getreg(struct mtpav *chip, u16 reg) -{ - u8 rval = 0; - - if (reg == SREG) { - rval = inb(chip->port + SREG); - rval = (rval & 0xf8); - } else if (reg == CREG) { - rval = inb(chip->port + CREG); - rval = (rval & 0x1c); - } - - return rval; -} - -/* - */ - -static inline void snd_mtpav_mputreg(struct mtpav *chip, u16 reg, u8 val) -{ - if (reg == DREG || reg == CREG) - outb(val, chip->port + reg); -} - -/* - */ - -static void snd_mtpav_wait_rfdhi(struct mtpav *chip) -{ - int counts = 10000; - u8 sbyte; - - sbyte = snd_mtpav_getreg(chip, SREG); - while (!(sbyte & SIGS_RFD) && counts--) { - sbyte = snd_mtpav_getreg(chip, SREG); - udelay(10); - } -} - -static void snd_mtpav_send_byte(struct mtpav *chip, u8 byte) -{ - u8 tcbyt; - u8 clrwrite; - u8 setwrite; - - snd_mtpav_wait_rfdhi(chip); - - ///////////////// - - tcbyt = snd_mtpav_getreg(chip, CREG); - clrwrite = tcbyt & (SIGC_WRITE ^ 0xff); - setwrite = tcbyt | SIGC_WRITE; - - snd_mtpav_mputreg(chip, DREG, byte); - snd_mtpav_mputreg(chip, CREG, clrwrite); // clear write bit - - snd_mtpav_mputreg(chip, CREG, setwrite); // set write bit - -} - - -/* - */ - -/* call this with spin lock held */ -static void snd_mtpav_output_port_write(struct mtpav *mtp_card, - struct mtpav_port *portp, - struct snd_rawmidi_substream *substream) -{ - u8 outbyte; - - // Get the outbyte first, so we can emulate running status if - // necessary - if (snd_rawmidi_transmit(substream, &outbyte, 1) != 1) - return; - - // send port change command if necessary - - if (portp->hwport != mtp_card->outmidihwport) { - mtp_card->outmidihwport = portp->hwport; - - snd_mtpav_send_byte(mtp_card, 0xf5); - snd_mtpav_send_byte(mtp_card, portp->hwport); - /* - snd_printk(KERN_DEBUG "new outport: 0x%x\n", - (unsigned int) portp->hwport); - */ - if (!(outbyte & 0x80) && portp->running_status) - snd_mtpav_send_byte(mtp_card, portp->running_status); - } - - // send data - - do { - if (outbyte & 0x80) - portp->running_status = outbyte; - - snd_mtpav_send_byte(mtp_card, outbyte); - } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1); -} - -static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - snd_mtpav_output_port_write(mtp_card, portp, substream); - spin_unlock_irqrestore(&mtp_card->spinlock, flags); -} - - -/* - * mtpav control - */ - -static void snd_mtpav_portscan(struct mtpav *chip) // put mtp into smart routing mode -{ - u8 p; - - for (p = 0; p < 8; p++) { - snd_mtpav_send_byte(chip, 0xf5); - snd_mtpav_send_byte(chip, p); - snd_mtpav_send_byte(chip, 0xfe); - } -} - -/* - */ - -static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - portp->mode |= MTPAV_MODE_INPUT_OPENED; - portp->input = substream; - if (mtp_card->share_irq++ == 0) - snd_mtpav_mputreg(mtp_card, CREG, (SIGC_INTEN | SIGC_WRITE)); // enable pport interrupts - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - return 0; -} - -/* - */ - -static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - portp->mode &= ~MTPAV_MODE_INPUT_OPENED; - portp->input = NULL; - if (--mtp_card->share_irq == 0) - snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - return 0; -} - -/* - */ - -static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - if (up) - portp->mode |= MTPAV_MODE_INPUT_TRIGGERED; - else - portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - -} - - -/* - * timer interrupt for outputs - */ - -static void snd_mtpav_output_timer(unsigned long data) -{ - unsigned long flags; - struct mtpav *chip = (struct mtpav *)data; - int p; - - spin_lock_irqsave(&chip->spinlock, flags); - /* reprogram timer */ - chip->timer.expires = 1 + jiffies; - add_timer(&chip->timer); - /* process each port */ - for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) { - struct mtpav_port *portp = &chip->ports[p]; - if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output) - snd_mtpav_output_port_write(chip, portp, portp->output); - } - spin_unlock_irqrestore(&chip->spinlock, flags); -} - -/* spinlock held! */ -static void snd_mtpav_add_output_timer(struct mtpav *chip) -{ - chip->timer.expires = 1 + jiffies; - add_timer(&chip->timer); -} - -/* spinlock held! */ -static void snd_mtpav_remove_output_timer(struct mtpav *chip) -{ - del_timer(&chip->timer); -} - -/* - */ - -static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - portp->mode |= MTPAV_MODE_OUTPUT_OPENED; - portp->output = substream; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - return 0; -}; - -/* - */ - -static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED; - portp->output = NULL; - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - return 0; -}; - -/* - */ - -static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct mtpav *mtp_card = substream->rmidi->private_data; - struct mtpav_port *portp = &mtp_card->ports[substream->number]; - unsigned long flags; - - spin_lock_irqsave(&mtp_card->spinlock, flags); - if (up) { - if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) { - if (mtp_card->istimer++ == 0) - snd_mtpav_add_output_timer(mtp_card); - portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED; - } - } else { - portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED; - if (--mtp_card->istimer == 0) - snd_mtpav_remove_output_timer(mtp_card); - } - spin_unlock_irqrestore(&mtp_card->spinlock, flags); - - if (up) - snd_mtpav_output_write(substream); -} - -/* - * midi interrupt for inputs - */ - -static void snd_mtpav_inmidi_process(struct mtpav *mcrd, u8 inbyte) -{ - struct mtpav_port *portp; - - if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST) - return; - - portp = &mcrd->ports[mcrd->inmidiport]; - if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(portp->input, &inbyte, 1); -} - -static void snd_mtpav_inmidi_h(struct mtpav *mcrd, u8 inbyte) -{ - if (inbyte >= 0xf8) { - /* real-time midi code */ - snd_mtpav_inmidi_process(mcrd, inbyte); - return; - } - - if (mcrd->inmidistate == 0) { // awaiting command - if (inbyte == 0xf5) // MTP port # - mcrd->inmidistate = 1; - else - snd_mtpav_inmidi_process(mcrd, inbyte); - } else if (mcrd->inmidistate) { - mcrd->inmidiport = translate_hwport_to_subdevice(mcrd, inbyte); - mcrd->inmidistate = 0; - } -} - -static void snd_mtpav_read_bytes(struct mtpav *mcrd) -{ - u8 clrread, setread; - u8 mtp_read_byte; - u8 sr, cbyt; - int i; - - u8 sbyt = snd_mtpav_getreg(mcrd, SREG); - - /* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */ - - if (!(sbyt & SIGS_BYTE)) - return; - - cbyt = snd_mtpav_getreg(mcrd, CREG); - clrread = cbyt & (SIGC_READ ^ 0xff); - setread = cbyt | SIGC_READ; - - do { - - mtp_read_byte = 0; - for (i = 0; i < 4; i++) { - snd_mtpav_mputreg(mcrd, CREG, setread); - sr = snd_mtpav_getreg(mcrd, SREG); - snd_mtpav_mputreg(mcrd, CREG, clrread); - - sr &= SIGS_IN0 | SIGS_IN1; - sr >>= 4; - mtp_read_byte |= sr << (i * 2); - } - - snd_mtpav_inmidi_h(mcrd, mtp_read_byte); - - sbyt = snd_mtpav_getreg(mcrd, SREG); - - } while (sbyt & SIGS_BYTE); -} - -static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) -{ - struct mtpav *mcard = dev_id; - - spin_lock(&mcard->spinlock); - snd_mtpav_read_bytes(mcard); - spin_unlock(&mcard->spinlock); - return IRQ_HANDLED; -} - -/* - * get ISA resources - */ -static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard) -{ - if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { - snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port); - return -EBUSY; - } - mcard->port = port; - if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) { - snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq); - return -EBUSY; - } - mcard->irq = irq; - return 0; -} - - -/* - */ - -static struct snd_rawmidi_ops snd_mtpav_output = { - .open = snd_mtpav_output_open, - .close = snd_mtpav_output_close, - .trigger = snd_mtpav_output_trigger, -}; - -static struct snd_rawmidi_ops snd_mtpav_input = { - .open = snd_mtpav_input_open, - .close = snd_mtpav_input_close, - .trigger = snd_mtpav_input_trigger, -}; - - -/* - * get RAWMIDI resources - */ - -static void __devinit snd_mtpav_set_name(struct mtpav *chip, - struct snd_rawmidi_substream *substream) -{ - if (substream->number >= 0 && substream->number < chip->num_ports) - sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1); - else if (substream->number >= 8 && substream->number < chip->num_ports * 2) - sprintf(substream->name, "MTP remote %d", (substream->number % chip->num_ports) + 1); - else if (substream->number == chip->num_ports * 2) - strcpy(substream->name, "MTP computer"); - else if (substream->number == chip->num_ports * 2 + 1) - strcpy(substream->name, "MTP ADAT"); - else - strcpy(substream->name, "MTP broadcast"); -} - -static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard) -{ - int rval; - struct snd_rawmidi *rawmidi; - struct snd_rawmidi_substream *substream; - struct list_head *list; - - if (hwports < 1) - hwports = 1; - else if (hwports > 8) - hwports = 8; - mcard->num_ports = hwports; - - if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0, - mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, - mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, - &mcard->rmidi)) < 0) - return rval; - rawmidi = mcard->rmidi; - rawmidi->private_data = mcard; - - list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - snd_mtpav_set_name(mcard, substream); - substream->ops = &snd_mtpav_input; - } - list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - snd_mtpav_set_name(mcard, substream); - substream->ops = &snd_mtpav_output; - mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number); - } - rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - sprintf(rawmidi->name, "MTP AV MIDI"); - return 0; -} - -/* - */ - -static void snd_mtpav_free(struct snd_card *card) -{ - struct mtpav *crd = card->private_data; - unsigned long flags; - - spin_lock_irqsave(&crd->spinlock, flags); - if (crd->istimer > 0) - snd_mtpav_remove_output_timer(crd); - spin_unlock_irqrestore(&crd->spinlock, flags); - if (crd->irq >= 0) - free_irq(crd->irq, (void *)crd); - release_and_free_resource(crd->res_port); -} - -/* - */ -static int __devinit snd_mtpav_probe(struct platform_device *dev) -{ - struct snd_card *card; - int err; - struct mtpav *mtp_card; - - err = snd_card_create(index, id, THIS_MODULE, sizeof(*mtp_card), &card); - if (err < 0) - return err; - - mtp_card = card->private_data; - spin_lock_init(&mtp_card->spinlock); - init_timer(&mtp_card->timer); - mtp_card->card = card; - mtp_card->irq = -1; - mtp_card->share_irq = 0; - mtp_card->inmidistate = 0; - mtp_card->outmidihwport = 0xffffffff; - init_timer(&mtp_card->timer); - mtp_card->timer.function = snd_mtpav_output_timer; - mtp_card->timer.data = (unsigned long) mtp_card; - - card->private_free = snd_mtpav_free; - - err = snd_mtpav_get_RAWMIDI(mtp_card); - if (err < 0) - goto __error; - - mtp_card->inmidiport = mtp_card->num_ports + MTPAV_PIDX_BROADCAST; - - err = snd_mtpav_get_ISA(mtp_card); - if (err < 0) - goto __error; - - strcpy(card->driver, "MTPAV"); - strcpy(card->shortname, "MTPAV on parallel port"); - snprintf(card->longname, sizeof(card->longname), - "MTPAV on parallel port at 0x%lx", port); - - snd_mtpav_portscan(mtp_card); - - snd_card_set_dev(card, &dev->dev); - err = snd_card_register(mtp_card->card); - if (err < 0) - goto __error; - - platform_set_drvdata(dev, card); - printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port); - return 0; - - __error: - snd_card_free(card); - return err; -} - -static int __devexit snd_mtpav_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SND_MTPAV_DRIVER "snd_mtpav" - -static struct platform_driver snd_mtpav_driver = { - .probe = snd_mtpav_probe, - .remove = __devexit_p(snd_mtpav_remove), - .driver = { - .name = SND_MTPAV_DRIVER - }, -}; - -static int __init alsa_card_mtpav_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_mtpav_driver)) < 0) - return err; - - device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); - if (!IS_ERR(device)) { - if (platform_get_drvdata(device)) - return 0; - platform_device_unregister(device); - err = -ENODEV; - } else - err = PTR_ERR(device); - platform_driver_unregister(&snd_mtpav_driver); - return err; -} - -static void __exit alsa_card_mtpav_exit(void) -{ - platform_device_unregister(device); - platform_driver_unregister(&snd_mtpav_driver); -} - -module_init(alsa_card_mtpav_init) -module_exit(alsa_card_mtpav_exit) diff --git a/ANDROID_3.4.5/sound/drivers/mts64.c b/ANDROID_3.4.5/sound/drivers/mts64.c deleted file mode 100644 index 621e60e2..00000000 --- a/ANDROID_3.4.5/sound/drivers/mts64.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * ALSA Driver for Ego Systems Inc. (ESI) Miditerminal 4140 - * Copyright (c) 2006 by Matthias König - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CARD_NAME "Miditerminal 4140" -#define DRIVER_NAME "MTS64" -#define PLATFORM_DRIVER "snd_mts64" - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -static struct platform_device *platform_devices[SNDRV_CARDS]; -static int device_count; - -module_param_array(index, int, NULL, S_IRUGO); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, S_IRUGO); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, S_IRUGO); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - -MODULE_AUTHOR("Matthias Koenig "); -MODULE_DESCRIPTION("ESI Miditerminal 4140"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESI,Miditerminal 4140}}"); - -/********************************************************************* - * Chip specific - *********************************************************************/ -#define MTS64_NUM_INPUT_PORTS 5 -#define MTS64_NUM_OUTPUT_PORTS 4 -#define MTS64_SMPTE_SUBSTREAM 4 - -struct mts64 { - spinlock_t lock; - struct snd_card *card; - struct snd_rawmidi *rmidi; - struct pardevice *pardev; - int pardev_claimed; - - int open_count; - int current_midi_output_port; - int current_midi_input_port; - u8 mode[MTS64_NUM_INPUT_PORTS]; - struct snd_rawmidi_substream *midi_input_substream[MTS64_NUM_INPUT_PORTS]; - int smpte_switch; - u8 time[4]; /* [0]=hh, [1]=mm, [2]=ss, [3]=ff */ - u8 fps; -}; - -static int snd_mts64_free(struct mts64 *mts) -{ - kfree(mts); - return 0; -} - -static int __devinit snd_mts64_create(struct snd_card *card, - struct pardevice *pardev, - struct mts64 **rchip) -{ - struct mts64 *mts; - - *rchip = NULL; - - mts = kzalloc(sizeof(struct mts64), GFP_KERNEL); - if (mts == NULL) - return -ENOMEM; - - /* Init chip specific data */ - spin_lock_init(&mts->lock); - mts->card = card; - mts->pardev = pardev; - mts->current_midi_output_port = -1; - mts->current_midi_input_port = -1; - - *rchip = mts; - - return 0; -} - -/********************************************************************* - * HW register related constants - *********************************************************************/ - -/* Status Bits */ -#define MTS64_STAT_BSY 0x80 -#define MTS64_STAT_BIT_SET 0x20 /* readout process, bit is set */ -#define MTS64_STAT_PORT 0x10 /* read byte is a port number */ - -/* Control Bits */ -#define MTS64_CTL_READOUT 0x08 /* enable readout */ -#define MTS64_CTL_WRITE_CMD 0x06 -#define MTS64_CTL_WRITE_DATA 0x02 -#define MTS64_CTL_STROBE 0x01 - -/* Command */ -#define MTS64_CMD_RESET 0xfe -#define MTS64_CMD_PROBE 0x8f /* Used in probing procedure */ -#define MTS64_CMD_SMPTE_SET_TIME 0xe8 -#define MTS64_CMD_SMPTE_SET_FPS 0xee -#define MTS64_CMD_SMPTE_STOP 0xef -#define MTS64_CMD_SMPTE_FPS_24 0xe3 -#define MTS64_CMD_SMPTE_FPS_25 0xe2 -#define MTS64_CMD_SMPTE_FPS_2997 0xe4 -#define MTS64_CMD_SMPTE_FPS_30D 0xe1 -#define MTS64_CMD_SMPTE_FPS_30 0xe0 -#define MTS64_CMD_COM_OPEN 0xf8 /* setting the communication mode */ -#define MTS64_CMD_COM_CLOSE1 0xff /* clearing communication mode */ -#define MTS64_CMD_COM_CLOSE2 0xf5 - -/********************************************************************* - * Hardware specific functions - *********************************************************************/ -static void mts64_enable_readout(struct parport *p); -static void mts64_disable_readout(struct parport *p); -static int mts64_device_ready(struct parport *p); -static int mts64_device_init(struct parport *p); -static int mts64_device_open(struct mts64 *mts); -static int mts64_device_close(struct mts64 *mts); -static u8 mts64_map_midi_input(u8 c); -static int mts64_probe(struct parport *p); -static u16 mts64_read(struct parport *p); -static u8 mts64_read_char(struct parport *p); -static void mts64_smpte_start(struct parport *p, - u8 hours, u8 minutes, - u8 seconds, u8 frames, - u8 idx); -static void mts64_smpte_stop(struct parport *p); -static void mts64_write_command(struct parport *p, u8 c); -static void mts64_write_data(struct parport *p, u8 c); -static void mts64_write_midi(struct mts64 *mts, u8 c, int midiport); - - -/* Enables the readout procedure - * - * Before we can read a midi byte from the device, we have to set - * bit 3 of control port. - */ -static void mts64_enable_readout(struct parport *p) -{ - u8 c; - - c = parport_read_control(p); - c |= MTS64_CTL_READOUT; - parport_write_control(p, c); -} - -/* Disables readout - * - * Readout is disabled by clearing bit 3 of control - */ -static void mts64_disable_readout(struct parport *p) -{ - u8 c; - - c = parport_read_control(p); - c &= ~MTS64_CTL_READOUT; - parport_write_control(p, c); -} - -/* waits for device ready - * - * Checks if BUSY (Bit 7 of status) is clear - * 1 device ready - * 0 failure - */ -static int mts64_device_ready(struct parport *p) -{ - int i; - u8 c; - - for (i = 0; i < 0xffff; ++i) { - c = parport_read_status(p); - c &= MTS64_STAT_BSY; - if (c != 0) - return 1; - } - - return 0; -} - -/* Init device (LED blinking startup magic) - * - * Returns: - * 0 init ok - * -EIO failure - */ -static int __devinit mts64_device_init(struct parport *p) -{ - int i; - - mts64_write_command(p, MTS64_CMD_RESET); - - for (i = 0; i < 64; ++i) { - msleep(100); - - if (mts64_probe(p) == 0) { - /* success */ - mts64_disable_readout(p); - return 0; - } - } - mts64_disable_readout(p); - - return -EIO; -} - -/* - * Opens the device (set communication mode) - */ -static int mts64_device_open(struct mts64 *mts) -{ - int i; - struct parport *p = mts->pardev->port; - - for (i = 0; i < 5; ++i) - mts64_write_command(p, MTS64_CMD_COM_OPEN); - - return 0; -} - -/* - * Close device (clear communication mode) - */ -static int mts64_device_close(struct mts64 *mts) -{ - int i; - struct parport *p = mts->pardev->port; - - for (i = 0; i < 5; ++i) { - mts64_write_command(p, MTS64_CMD_COM_CLOSE1); - mts64_write_command(p, MTS64_CMD_COM_CLOSE2); - } - - return 0; -} - -/* map hardware port to substream number - * - * When reading a byte from the device, the device tells us - * on what port the byte is. This HW port has to be mapped to - * the midiport (substream number). - * substream 0-3 are Midiports 1-4 - * substream 4 is SMPTE Timecode - * The mapping is done by the table: - * HW | 0 | 1 | 2 | 3 | 4 - * SW | 0 | 1 | 4 | 2 | 3 - */ -static u8 mts64_map_midi_input(u8 c) -{ - static u8 map[] = { 0, 1, 4, 2, 3 }; - - return map[c]; -} - - -/* Probe parport for device - * - * Do we have a Miditerminal 4140 on parport? - * Returns: - * 0 device found - * -ENODEV no device - */ -static int __devinit mts64_probe(struct parport *p) -{ - u8 c; - - mts64_smpte_stop(p); - mts64_write_command(p, MTS64_CMD_PROBE); - - msleep(50); - - c = mts64_read(p); - - c &= 0x00ff; - if (c != MTS64_CMD_PROBE) - return -ENODEV; - else - return 0; - -} - -/* Read byte incl. status from device - * - * Returns: - * data in lower 8 bits and status in upper 8 bits - */ -static u16 mts64_read(struct parport *p) -{ - u8 data, status; - - mts64_device_ready(p); - mts64_enable_readout(p); - status = parport_read_status(p); - data = mts64_read_char(p); - mts64_disable_readout(p); - - return (status << 8) | data; -} - -/* Read a byte from device - * - * Note, that readout mode has to be enabled. - * readout procedure is as follows: - * - Write number of the Bit to read to DATA - * - Read STATUS - * - Bit 5 of STATUS indicates if Bit is set - * - * Returns: - * Byte read from device - */ -static u8 mts64_read_char(struct parport *p) -{ - u8 c = 0; - u8 status; - u8 i; - - for (i = 0; i < 8; ++i) { - parport_write_data(p, i); - c >>= 1; - status = parport_read_status(p); - if (status & MTS64_STAT_BIT_SET) - c |= 0x80; - } - - return c; -} - -/* Starts SMPTE Timecode generation - * - * The device creates SMPTE Timecode by hardware. - * 0 24 fps - * 1 25 fps - * 2 29.97 fps - * 3 30 fps (Drop-frame) - * 4 30 fps - */ -static void mts64_smpte_start(struct parport *p, - u8 hours, u8 minutes, - u8 seconds, u8 frames, - u8 idx) -{ - static u8 fps[5] = { MTS64_CMD_SMPTE_FPS_24, - MTS64_CMD_SMPTE_FPS_25, - MTS64_CMD_SMPTE_FPS_2997, - MTS64_CMD_SMPTE_FPS_30D, - MTS64_CMD_SMPTE_FPS_30 }; - - mts64_write_command(p, MTS64_CMD_SMPTE_SET_TIME); - mts64_write_command(p, frames); - mts64_write_command(p, seconds); - mts64_write_command(p, minutes); - mts64_write_command(p, hours); - - mts64_write_command(p, MTS64_CMD_SMPTE_SET_FPS); - mts64_write_command(p, fps[idx]); -} - -/* Stops SMPTE Timecode generation - */ -static void mts64_smpte_stop(struct parport *p) -{ - mts64_write_command(p, MTS64_CMD_SMPTE_STOP); -} - -/* Write a command byte to device - */ -static void mts64_write_command(struct parport *p, u8 c) -{ - mts64_device_ready(p); - - parport_write_data(p, c); - - parport_write_control(p, MTS64_CTL_WRITE_CMD); - parport_write_control(p, MTS64_CTL_WRITE_CMD | MTS64_CTL_STROBE); - parport_write_control(p, MTS64_CTL_WRITE_CMD); -} - -/* Write a data byte to device - */ -static void mts64_write_data(struct parport *p, u8 c) -{ - mts64_device_ready(p); - - parport_write_data(p, c); - - parport_write_control(p, MTS64_CTL_WRITE_DATA); - parport_write_control(p, MTS64_CTL_WRITE_DATA | MTS64_CTL_STROBE); - parport_write_control(p, MTS64_CTL_WRITE_DATA); -} - -/* Write a MIDI byte to midiport - * - * midiport ranges from 0-3 and maps to Ports 1-4 - * assumptions: communication mode is on - */ -static void mts64_write_midi(struct mts64 *mts, u8 c, - int midiport) -{ - struct parport *p = mts->pardev->port; - - /* check current midiport */ - if (mts->current_midi_output_port != midiport) - mts64_write_command(p, midiport); - - /* write midi byte */ - mts64_write_data(p, c); -} - -/********************************************************************* - * Control elements - *********************************************************************/ - -/* SMPTE Switch */ -#define snd_mts64_ctl_smpte_switch_info snd_ctl_boolean_mono_info - -static int snd_mts64_ctl_smpte_switch_get(struct snd_kcontrol* kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - - spin_lock_irq(&mts->lock); - uctl->value.integer.value[0] = mts->smpte_switch; - spin_unlock_irq(&mts->lock); - - return 0; -} - -/* smpte_switch is not accessed from IRQ handler, so we just need - to protect the HW access */ -static int snd_mts64_ctl_smpte_switch_put(struct snd_kcontrol* kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int changed = 0; - int val = !!uctl->value.integer.value[0]; - - spin_lock_irq(&mts->lock); - if (mts->smpte_switch == val) - goto __out; - - changed = 1; - mts->smpte_switch = val; - if (mts->smpte_switch) { - mts64_smpte_start(mts->pardev->port, - mts->time[0], mts->time[1], - mts->time[2], mts->time[3], - mts->fps); - } else { - mts64_smpte_stop(mts->pardev->port); - } -__out: - spin_unlock_irq(&mts->lock); - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_switch __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Playback Switch", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_switch_info, - .get = snd_mts64_ctl_smpte_switch_get, - .put = snd_mts64_ctl_smpte_switch_put -}; - -/* Time */ -static int snd_mts64_ctl_smpte_time_h_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 23; - return 0; -} - -static int snd_mts64_ctl_smpte_time_f_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 99; - return 0; -} - -static int snd_mts64_ctl_smpte_time_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 59; - return 0; -} - -static int snd_mts64_ctl_smpte_time_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int idx = kctl->private_value; - - spin_lock_irq(&mts->lock); - uctl->value.integer.value[0] = mts->time[idx]; - spin_unlock_irq(&mts->lock); - - return 0; -} - -static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int idx = kctl->private_value; - unsigned int time = uctl->value.integer.value[0] % 60; - int changed = 0; - - spin_lock_irq(&mts->lock); - if (mts->time[idx] != time) { - changed = 1; - mts->time[idx] = time; - } - spin_unlock_irq(&mts->lock); - - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Hours", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_time_h_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Minutes", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 1, - .info = snd_mts64_ctl_smpte_time_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Seconds", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 2, - .info = snd_mts64_ctl_smpte_time_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_frames __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Frames", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 3, - .info = snd_mts64_ctl_smpte_time_f_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -/* FPS */ -static int snd_mts64_ctl_smpte_fps_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[5] = { "24", - "25", - "29.97", - "30D", - "30" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_mts64_ctl_smpte_fps_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - - spin_lock_irq(&mts->lock); - uctl->value.enumerated.item[0] = mts->fps; - spin_unlock_irq(&mts->lock); - - return 0; -} - -static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int changed = 0; - - if (uctl->value.enumerated.item[0] >= 5) - return -EINVAL; - spin_lock_irq(&mts->lock); - if (mts->fps != uctl->value.enumerated.item[0]) { - changed = 1; - mts->fps = uctl->value.enumerated.item[0]; - } - spin_unlock_irq(&mts->lock); - - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Fps", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_fps_info, - .get = snd_mts64_ctl_smpte_fps_get, - .put = snd_mts64_ctl_smpte_fps_put -}; - - -static int __devinit snd_mts64_ctl_create(struct snd_card *card, - struct mts64 *mts) -{ - int err, i; - static struct snd_kcontrol_new *control[] __devinitdata = { - &mts64_ctl_smpte_switch, - &mts64_ctl_smpte_time_hours, - &mts64_ctl_smpte_time_minutes, - &mts64_ctl_smpte_time_seconds, - &mts64_ctl_smpte_time_frames, - &mts64_ctl_smpte_fps, - NULL }; - - for (i = 0; control[i]; ++i) { - err = snd_ctl_add(card, snd_ctl_new1(control[i], mts)); - if (err < 0) { - snd_printd("Cannot create control: %s\n", - control[i]->name); - return err; - } - } - - return 0; -} - -/********************************************************************* - * Rawmidi - *********************************************************************/ -#define MTS64_MODE_INPUT_TRIGGERED 0x01 - -static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream) -{ - struct mts64 *mts = substream->rmidi->private_data; - - if (mts->open_count == 0) { - /* We don't need a spinlock here, because this is just called - if the device has not been opened before. - So there aren't any IRQs from the device */ - mts64_device_open(mts); - - msleep(50); - } - ++(mts->open_count); - - return 0; -} - -static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream) -{ - struct mts64 *mts = substream->rmidi->private_data; - unsigned long flags; - - --(mts->open_count); - if (mts->open_count == 0) { - /* We need the spinlock_irqsave here because we can still - have IRQs at this point */ - spin_lock_irqsave(&mts->lock, flags); - mts64_device_close(mts); - spin_unlock_irqrestore(&mts->lock, flags); - - msleep(500); - - } else if (mts->open_count < 0) - mts->open_count = 0; - - return 0; -} - -static void snd_mts64_rawmidi_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct mts64 *mts = substream->rmidi->private_data; - u8 data; - unsigned long flags; - - spin_lock_irqsave(&mts->lock, flags); - while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) { - mts64_write_midi(mts, data, substream->number+1); - snd_rawmidi_transmit_ack(substream, 1); - } - spin_unlock_irqrestore(&mts->lock, flags); -} - -static void snd_mts64_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct mts64 *mts = substream->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&mts->lock, flags); - if (up) - mts->mode[substream->number] |= MTS64_MODE_INPUT_TRIGGERED; - else - mts->mode[substream->number] &= ~MTS64_MODE_INPUT_TRIGGERED; - - spin_unlock_irqrestore(&mts->lock, flags); -} - -static struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = { - .open = snd_mts64_rawmidi_open, - .close = snd_mts64_rawmidi_close, - .trigger = snd_mts64_rawmidi_output_trigger -}; - -static struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = { - .open = snd_mts64_rawmidi_open, - .close = snd_mts64_rawmidi_close, - .trigger = snd_mts64_rawmidi_input_trigger -}; - -/* Create and initialize the rawmidi component */ -static int __devinit snd_mts64_rawmidi_create(struct snd_card *card) -{ - struct mts64 *mts = card->private_data; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream; - struct list_head *list; - int err; - - err = snd_rawmidi_new(card, CARD_NAME, 0, - MTS64_NUM_OUTPUT_PORTS, - MTS64_NUM_INPUT_PORTS, - &rmidi); - if (err < 0) - return err; - - rmidi->private_data = mts; - strcpy(rmidi->name, CARD_NAME); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - mts->rmidi = rmidi; - - /* register rawmidi ops */ - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_mts64_rawmidi_output_ops); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_mts64_rawmidi_input_ops); - - /* name substreams */ - /* output */ - list_for_each(list, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - sprintf(substream->name, - "Miditerminal %d", substream->number+1); - } - /* input */ - list_for_each(list, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - mts->midi_input_substream[substream->number] = substream; - switch(substream->number) { - case MTS64_SMPTE_SUBSTREAM: - strcpy(substream->name, "Miditerminal SMPTE"); - break; - default: - sprintf(substream->name, - "Miditerminal %d", substream->number+1); - } - } - - /* controls */ - err = snd_mts64_ctl_create(card, mts); - - return err; -} - -/********************************************************************* - * parport stuff - *********************************************************************/ -static void snd_mts64_interrupt(void *private) -{ - struct mts64 *mts = ((struct snd_card*)private)->private_data; - u16 ret; - u8 status, data; - struct snd_rawmidi_substream *substream; - - spin_lock(&mts->lock); - ret = mts64_read(mts->pardev->port); - data = ret & 0x00ff; - status = ret >> 8; - - if (status & MTS64_STAT_PORT) { - mts->current_midi_input_port = mts64_map_midi_input(data); - } else { - if (mts->current_midi_input_port == -1) - goto __out; - substream = mts->midi_input_substream[mts->current_midi_input_port]; - if (mts->mode[substream->number] & MTS64_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(substream, &data, 1); - } -__out: - spin_unlock(&mts->lock); -} - -static int __devinit snd_mts64_probe_port(struct parport *p) -{ - struct pardevice *pardev; - int res; - - pardev = parport_register_device(p, DRIVER_NAME, - NULL, NULL, NULL, - 0, NULL); - if (!pardev) - return -EIO; - - if (parport_claim(pardev)) { - parport_unregister_device(pardev); - return -EIO; - } - - res = mts64_probe(p); - - parport_release(pardev); - parport_unregister_device(pardev); - - return res; -} - -static void __devinit snd_mts64_attach(struct parport *p) -{ - struct platform_device *device; - - device = platform_device_alloc(PLATFORM_DRIVER, device_count); - if (!device) - return; - - /* Temporary assignment to forward the parport */ - platform_set_drvdata(device, p); - - if (platform_device_add(device) < 0) { - platform_device_put(device); - return; - } - - /* Since we dont get the return value of probe - * We need to check if device probing succeeded or not */ - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - return; - } - - /* register device in global table */ - platform_devices[device_count] = device; - device_count++; -} - -static void snd_mts64_detach(struct parport *p) -{ - /* nothing to do here */ -} - -static struct parport_driver mts64_parport_driver = { - .name = "mts64", - .attach = snd_mts64_attach, - .detach = snd_mts64_detach -}; - -/********************************************************************* - * platform stuff - *********************************************************************/ -static void snd_mts64_card_private_free(struct snd_card *card) -{ - struct mts64 *mts = card->private_data; - struct pardevice *pardev = mts->pardev; - - if (pardev) { - if (mts->pardev_claimed) - parport_release(pardev); - parport_unregister_device(pardev); - } - - snd_mts64_free(mts); -} - -static int __devinit snd_mts64_probe(struct platform_device *pdev) -{ - struct pardevice *pardev; - struct parport *p; - int dev = pdev->id; - struct snd_card *card = NULL; - struct mts64 *mts = NULL; - int err; - - p = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) - return -ENOENT; - if ((err = snd_mts64_probe_port(p)) < 0) - return err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printd("Cannot create card\n"); - return err; - } - strcpy(card->driver, DRIVER_NAME); - strcpy(card->shortname, "ESI " CARD_NAME); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, p->base, p->irq); - - pardev = parport_register_device(p, /* port */ - DRIVER_NAME, /* name */ - NULL, /* preempt */ - NULL, /* wakeup */ - snd_mts64_interrupt, /* ISR */ - PARPORT_DEV_EXCL, /* flags */ - (void *)card); /* private */ - if (pardev == NULL) { - snd_printd("Cannot register pardevice\n"); - err = -EIO; - goto __err; - } - - if ((err = snd_mts64_create(card, pardev, &mts)) < 0) { - snd_printd("Cannot create main component\n"); - parport_unregister_device(pardev); - goto __err; - } - card->private_data = mts; - card->private_free = snd_mts64_card_private_free; - - if ((err = snd_mts64_rawmidi_create(card)) < 0) { - snd_printd("Creating Rawmidi component failed\n"); - goto __err; - } - - /* claim parport */ - if (parport_claim(pardev)) { - snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); - err = -EIO; - goto __err; - } - mts->pardev_claimed = 1; - - /* init device */ - if ((err = mts64_device_init(p)) < 0) - goto __err; - - platform_set_drvdata(pdev, card); - - snd_card_set_dev(card, &pdev->dev); - - /* At this point card will be usable */ - if ((err = snd_card_register(card)) < 0) { - snd_printd("Cannot register card\n"); - goto __err; - } - - snd_printk(KERN_INFO "ESI Miditerminal 4140 on 0x%lx\n", p->base); - return 0; - -__err: - snd_card_free(card); - return err; -} - -static int __devexit snd_mts64_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - if (card) - snd_card_free(card); - - return 0; -} - - -static struct platform_driver snd_mts64_driver = { - .probe = snd_mts64_probe, - .remove = __devexit_p(snd_mts64_remove), - .driver = { - .name = PLATFORM_DRIVER - } -}; - -/********************************************************************* - * module init stuff - *********************************************************************/ -static void snd_mts64_unregister_all(void) -{ - int i; - - for (i = 0; i < SNDRV_CARDS; ++i) { - if (platform_devices[i]) { - platform_device_unregister(platform_devices[i]); - platform_devices[i] = NULL; - } - } - platform_driver_unregister(&snd_mts64_driver); - parport_unregister_driver(&mts64_parport_driver); -} - -static int __init snd_mts64_module_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_mts64_driver)) < 0) - return err; - - if (parport_register_driver(&mts64_parport_driver) != 0) { - platform_driver_unregister(&snd_mts64_driver); - return -EIO; - } - - if (device_count == 0) { - snd_mts64_unregister_all(); - return -ENODEV; - } - - return 0; -} - -static void __exit snd_mts64_module_exit(void) -{ - snd_mts64_unregister_all(); -} - -module_init(snd_mts64_module_init); -module_exit(snd_mts64_module_exit); diff --git a/ANDROID_3.4.5/sound/drivers/opl3/Makefile b/ANDROID_3.4.5/sound/drivers/opl3/Makefile deleted file mode 100644 index 7f2c2a10..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-opl3-lib-objs := opl3_lib.o opl3_synth.o -snd-opl3-synth-y := opl3_seq.o opl3_midi.o opl3_drums.o -snd-opl3-synth-$(CONFIG_SND_SEQUENCER_OSS) += opl3_oss.o - -obj-$(CONFIG_SND_OPL3_LIB) += snd-opl3-lib.o -obj-$(CONFIG_SND_OPL4_LIB) += snd-opl3-lib.o -obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-opl3-synth.o diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_drums.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_drums.c deleted file mode 100644 index 73694380..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_drums.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) by Uros Bizjak - * - * OPL2/OPL3/OPL4 FM routines for internal percussion channels - * - * 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 "opl3_voice.h" - -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - -static char snd_opl3_drum_table[47] = -{ - OPL3_BASSDRUM_ON, OPL3_BASSDRUM_ON, OPL3_HIHAT_ON, /* 35 - 37 */ - OPL3_SNAREDRUM_ON, OPL3_HIHAT_ON, OPL3_SNAREDRUM_ON, /* 38 - 40 */ - OPL3_BASSDRUM_ON, OPL3_HIHAT_ON, OPL3_BASSDRUM_ON, /* 41 - 43 */ - OPL3_HIHAT_ON, OPL3_TOMTOM_ON, OPL3_HIHAT_ON, /* 44 - 46 */ - OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_CYMBAL_ON, /* 47 - 49 */ - - OPL3_TOMTOM_ON, OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, /* 50 - 52 */ - OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, /* 53 - 55 */ - OPL3_HIHAT_ON, OPL3_CYMBAL_ON, OPL3_TOMTOM_ON, /* 56 - 58 */ - OPL3_CYMBAL_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 59 - 61 */ - OPL3_HIHAT_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 62 - 64 */ - - OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 65 - 67 */ - OPL3_TOMTOM_ON, OPL3_HIHAT_ON, OPL3_HIHAT_ON, /* 68 - 70 */ - OPL3_HIHAT_ON, OPL3_HIHAT_ON, OPL3_TOMTOM_ON, /* 71 - 73 */ - OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 74 - 76 */ - OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 77 - 79 */ - OPL3_CYMBAL_ON, OPL3_CYMBAL_ON /* 80 - 81 */ -}; - -struct snd_opl3_drum_voice { - int voice; - int op; - unsigned char am_vib; - unsigned char ksl_level; - unsigned char attack_decay; - unsigned char sustain_release; - unsigned char feedback_connection; - unsigned char wave_select; -}; - -struct snd_opl3_drum_note { - int voice; - unsigned char fnum; - unsigned char octave_f; - unsigned char feedback_connection; -}; - -static struct snd_opl3_drum_voice bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00}; -static struct snd_opl3_drum_voice bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00}; -static struct snd_opl3_drum_note bass_note = {6, 0x90, 0x09}; - -static struct snd_opl3_drum_voice hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00}; - -static struct snd_opl3_drum_voice snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02}; -static struct snd_opl3_drum_note snare_note = {7, 0xf4, 0x0d}; - -static struct snd_opl3_drum_voice tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00}; -static struct snd_opl3_drum_note tomtom_note = {8, 0xf4, 0x09}; - -static struct snd_opl3_drum_voice cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00}; - -/* - * set drum voice characteristics - */ -static void snd_opl3_drum_voice_set(struct snd_opl3 *opl3, - struct snd_opl3_drum_voice *data) -{ - unsigned char op_offset = snd_opl3_regmap[data->voice][data->op]; - unsigned char voice_offset = data->voice; - unsigned short opl3_reg; - - /* Set OPL3 AM_VIB register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_AM_VIB + op_offset); - opl3->command(opl3, opl3_reg, data->am_vib); - - /* Set OPL3 KSL_LEVEL register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_KSL_LEVEL + op_offset); - opl3->command(opl3, opl3_reg, data->ksl_level); - - /* Set OPL3 ATTACK_DECAY register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_ATTACK_DECAY + op_offset); - opl3->command(opl3, opl3_reg, data->attack_decay); - - /* Set OPL3 SUSTAIN_RELEASE register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_SUSTAIN_RELEASE + op_offset); - opl3->command(opl3, opl3_reg, data->sustain_release); - - /* Set OPL3 FEEDBACK_CONNECTION register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); - opl3->command(opl3, opl3_reg, data->feedback_connection); - - /* Select waveform */ - opl3_reg = OPL3_LEFT | (OPL3_REG_WAVE_SELECT + op_offset); - opl3->command(opl3, opl3_reg, data->wave_select); -} - -/* - * Set drum voice pitch - */ -static void snd_opl3_drum_note_set(struct snd_opl3 *opl3, - struct snd_opl3_drum_note *data) -{ - unsigned char voice_offset = data->voice; - unsigned short opl3_reg; - - /* Set OPL3 FNUM_LOW register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_FNUM_LOW + voice_offset); - opl3->command(opl3, opl3_reg, data->fnum); - - /* Set OPL3 KEYON_BLOCK register */ - opl3_reg = OPL3_LEFT | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, data->octave_f); -} - -/* - * Set drum voice volume and position - */ -static void snd_opl3_drum_vol_set(struct snd_opl3 *opl3, - struct snd_opl3_drum_voice *data, - int vel, struct snd_midi_channel *chan) -{ - unsigned char op_offset = snd_opl3_regmap[data->voice][data->op]; - unsigned char voice_offset = data->voice; - unsigned char reg_val; - unsigned short opl3_reg; - - /* Set OPL3 KSL_LEVEL register */ - reg_val = data->ksl_level; - snd_opl3_calc_volume(®_val, vel, chan); - opl3_reg = OPL3_LEFT | (OPL3_REG_KSL_LEVEL + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set OPL3 FEEDBACK_CONNECTION register */ - /* Set output voice connection */ - reg_val = data->feedback_connection | OPL3_STEREO_BITS; - if (chan->gm_pan < 43) - reg_val &= ~OPL3_VOICE_TO_RIGHT; - if (chan->gm_pan > 85) - reg_val &= ~OPL3_VOICE_TO_LEFT; - opl3_reg = OPL3_LEFT | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); -} - -/* - * Loads drum voices at init time - */ -void snd_opl3_load_drums(struct snd_opl3 *opl3) -{ - snd_opl3_drum_voice_set(opl3, &bass_op0); - snd_opl3_drum_voice_set(opl3, &bass_op1); - snd_opl3_drum_note_set(opl3, &bass_note); - - snd_opl3_drum_voice_set(opl3, &hihat); - - snd_opl3_drum_voice_set(opl3, &snare); - snd_opl3_drum_note_set(opl3, &snare_note); - - snd_opl3_drum_voice_set(opl3, &tomtom); - snd_opl3_drum_note_set(opl3, &tomtom_note); - - snd_opl3_drum_voice_set(opl3, &cymbal); -} - -/* - * Switch drum voice on or off - */ -void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int vel, int on_off, - struct snd_midi_channel *chan) -{ - unsigned char drum_mask; - struct snd_opl3_drum_voice *drum_voice; - - if (!(opl3->drum_reg & OPL3_PERCUSSION_ENABLE)) - return; - - if ((note < 35) || (note > 81)) - return; - drum_mask = snd_opl3_drum_table[note - 35]; - - if (on_off) { - switch (drum_mask) { - case OPL3_BASSDRUM_ON: - drum_voice = &bass_op1; - break; - case OPL3_HIHAT_ON: - drum_voice = &hihat; - break; - case OPL3_SNAREDRUM_ON: - drum_voice = &snare; - break; - case OPL3_TOMTOM_ON: - drum_voice = &tomtom; - break; - case OPL3_CYMBAL_ON: - drum_voice = &cymbal; - break; - default: - drum_voice = &tomtom; - } - - snd_opl3_drum_vol_set(opl3, drum_voice, vel, chan); - opl3->drum_reg |= drum_mask; - } else { - opl3->drum_reg &= ~drum_mask; - } - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, - opl3->drum_reg); -} diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_lib.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_lib.c deleted file mode 100644 index 33d9a857..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_lib.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela , - * Hannu Savolainen 1993-1996, - * Rob Hooft - * - * Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips) - * - * Most if code is ported from OSS/Lite. - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela , Hannu Savolainen 1993-1996, Rob Hooft"); -MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)"); -MODULE_LICENSE("GPL"); - -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - -static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) -{ - unsigned long flags; - unsigned long port; - - /* - * The original 2-OP synth requires a quite long delay - * after writing to a register. - */ - - port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port; - - spin_lock_irqsave(&opl3->reg_lock, flags); - - outb((unsigned char) cmd, port); - udelay(10); - - outb((unsigned char) val, port + 1); - udelay(30); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); -} - -static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) -{ - unsigned long flags; - unsigned long port; - - /* - * The OPL-3 survives with just two INBs - * after writing to a register. - */ - - port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port; - - spin_lock_irqsave(&opl3->reg_lock, flags); - - outb((unsigned char) cmd, port); - inb(opl3->l_port); - inb(opl3->l_port); - - outb((unsigned char) val, port + 1); - inb(opl3->l_port); - inb(opl3->l_port); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); -} - -static int snd_opl3_detect(struct snd_opl3 * opl3) -{ - /* - * This function returns 1 if the FM chip is present at the given I/O port - * The detection algorithm plays with the timer built in the FM chip and - * looks for a change in the status register. - * - * Note! The timers of the FM chip are not connected to AdLib (and compatible) - * boards. - * - * Note2! The chip is initialized if detected. - */ - - unsigned char stat1, stat2, signature; - - /* Reset timers 1 and 2 */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK); - /* Reset the IRQ of the FM chip */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET); - signature = stat1 = inb(opl3->l_port); /* Status register */ - if ((stat1 & 0xe0) != 0x00) { /* Should be 0x00 */ - snd_printd("OPL3: stat1 = 0x%x\n", stat1); - return -ENODEV; - } - /* Set timer1 to 0xff */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 0xff); - /* Unmask and start timer 1 */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER2_MASK | OPL3_TIMER1_START); - /* Now we have to delay at least 80us */ - udelay(200); - /* Read status after timers have expired */ - stat2 = inb(opl3->l_port); - /* Stop the timers */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK); - /* Reset the IRQ of the FM chip */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET); - if ((stat2 & 0xe0) != 0xc0) { /* There is no YM3812 */ - snd_printd("OPL3: stat2 = 0x%x\n", stat2); - return -ENODEV; - } - - /* If the toplevel code knows exactly the type of chip, don't try - to detect it. */ - if (opl3->hardware != OPL3_HW_AUTO) - return 0; - - /* There is a FM chip on this address. Detect the type (OPL2 to OPL4) */ - if (signature == 0x06) { /* OPL2 */ - opl3->hardware = OPL3_HW_OPL2; - } else { - /* - * If we had an OPL4 chip, opl3->hardware would have been set - * by the OPL4 driver; so we can assume OPL3 here. - */ - if (snd_BUG_ON(!opl3->r_port)) - return -ENODEV; - opl3->hardware = OPL3_HW_OPL3; - } - return 0; -} - -/* - * AdLib timers - */ - -/* - * Timer 1 - 80us - */ - -static int snd_opl3_timer1_start(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - unsigned int ticks; - struct snd_opl3 *opl3; - - opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); - ticks = timer->sticks; - tmp = (opl3->timer_enable | OPL3_TIMER1_START) & ~OPL3_TIMER1_MASK; - opl3->timer_enable = tmp; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 256 - ticks); /* timer 1 count */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); - return 0; -} - -static int snd_opl3_timer1_stop(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - struct snd_opl3 *opl3; - - opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); - tmp = (opl3->timer_enable | OPL3_TIMER1_MASK) & ~OPL3_TIMER1_START; - opl3->timer_enable = tmp; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); - return 0; -} - -/* - * Timer 2 - 320us - */ - -static int snd_opl3_timer2_start(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - unsigned int ticks; - struct snd_opl3 *opl3; - - opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); - ticks = timer->sticks; - tmp = (opl3->timer_enable | OPL3_TIMER2_START) & ~OPL3_TIMER2_MASK; - opl3->timer_enable = tmp; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER2, 256 - ticks); /* timer 1 count */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); - return 0; -} - -static int snd_opl3_timer2_stop(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - struct snd_opl3 *opl3; - - opl3 = snd_timer_chip(timer); - spin_lock_irqsave(&opl3->timer_lock, flags); - tmp = (opl3->timer_enable | OPL3_TIMER2_MASK) & ~OPL3_TIMER2_START; - opl3->timer_enable = tmp; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&opl3->timer_lock, flags); - return 0; -} - -/* - - */ - -static struct snd_timer_hardware snd_opl3_timer1 = -{ - .flags = SNDRV_TIMER_HW_STOP, - .resolution = 80000, - .ticks = 256, - .start = snd_opl3_timer1_start, - .stop = snd_opl3_timer1_stop, -}; - -static struct snd_timer_hardware snd_opl3_timer2 = -{ - .flags = SNDRV_TIMER_HW_STOP, - .resolution = 320000, - .ticks = 256, - .start = snd_opl3_timer2_start, - .stop = snd_opl3_timer2_stop, -}; - -static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no) -{ - struct snd_timer *timer = NULL; - struct snd_timer_id tid; - int err; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = opl3->card->number; - tid.device = timer_no; - tid.subdevice = 0; - if ((err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer)) >= 0) { - strcpy(timer->name, "AdLib timer #1"); - timer->private_data = opl3; - timer->hw = snd_opl3_timer1; - } - opl3->timer1 = timer; - return err; -} - -static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no) -{ - struct snd_timer *timer = NULL; - struct snd_timer_id tid; - int err; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = opl3->card->number; - tid.device = timer_no; - tid.subdevice = 0; - if ((err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer)) >= 0) { - strcpy(timer->name, "AdLib timer #2"); - timer->private_data = opl3; - timer->hw = snd_opl3_timer2; - } - opl3->timer2 = timer; - return err; -} - -/* - - */ - -void snd_opl3_interrupt(struct snd_hwdep * hw) -{ - unsigned char status; - struct snd_opl3 *opl3; - struct snd_timer *timer; - - if (hw == NULL) - return; - - opl3 = hw->private_data; - status = inb(opl3->l_port); -#if 0 - snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status); -#endif - if (!(status & 0x80)) - return; - - if (status & 0x40) { - timer = opl3->timer1; - snd_timer_interrupt(timer, timer->sticks); - } - if (status & 0x20) { - timer = opl3->timer2; - snd_timer_interrupt(timer, timer->sticks); - } -} - -EXPORT_SYMBOL(snd_opl3_interrupt); - -/* - - */ - -static int snd_opl3_free(struct snd_opl3 *opl3) -{ - if (snd_BUG_ON(!opl3)) - return -ENXIO; - if (opl3->private_free) - opl3->private_free(opl3); - snd_opl3_clear_patches(opl3); - release_and_free_resource(opl3->res_l_port); - release_and_free_resource(opl3->res_r_port); - kfree(opl3); - return 0; -} - -static int snd_opl3_dev_free(struct snd_device *device) -{ - struct snd_opl3 *opl3 = device->device_data; - return snd_opl3_free(opl3); -} - -int snd_opl3_new(struct snd_card *card, - unsigned short hardware, - struct snd_opl3 **ropl3) -{ - static struct snd_device_ops ops = { - .dev_free = snd_opl3_dev_free, - }; - struct snd_opl3 *opl3; - int err; - - *ropl3 = NULL; - opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL); - if (opl3 == NULL) { - snd_printk(KERN_ERR "opl3: cannot allocate\n"); - return -ENOMEM; - } - - opl3->card = card; - opl3->hardware = hardware; - spin_lock_init(&opl3->reg_lock); - spin_lock_init(&opl3->timer_lock); - - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 0) { - snd_opl3_free(opl3); - return err; - } - - *ropl3 = opl3; - return 0; -} - -EXPORT_SYMBOL(snd_opl3_new); - -int snd_opl3_init(struct snd_opl3 *opl3) -{ - if (! opl3->command) { - printk(KERN_ERR "snd_opl3_init: command not defined!\n"); - return -EINVAL; - } - - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT); - /* Melodic mode */ - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); - - switch (opl3->hardware & OPL3_HW_MASK) { - case OPL3_HW_OPL2: - opl3->max_voices = MAX_OPL2_VOICES; - break; - case OPL3_HW_OPL3: - case OPL3_HW_OPL4: - opl3->max_voices = MAX_OPL3_VOICES; - /* Enter OPL3 mode */ - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE); - } - return 0; -} - -EXPORT_SYMBOL(snd_opl3_init); - -int snd_opl3_create(struct snd_card *card, - unsigned long l_port, - unsigned long r_port, - unsigned short hardware, - int integrated, - struct snd_opl3 ** ropl3) -{ - struct snd_opl3 *opl3; - int err; - - *ropl3 = NULL; - if ((err = snd_opl3_new(card, hardware, &opl3)) < 0) - return err; - if (! integrated) { - if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) { - snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port); - snd_device_free(card, opl3); - return -EBUSY; - } - if (r_port != 0 && - (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) { - snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port); - snd_device_free(card, opl3); - return -EBUSY; - } - } - opl3->l_port = l_port; - opl3->r_port = r_port; - - switch (opl3->hardware) { - /* some hardware doesn't support timers */ - case OPL3_HW_OPL3_SV: - case OPL3_HW_OPL3_CS: - case OPL3_HW_OPL3_FM801: - opl3->command = &snd_opl3_command; - break; - default: - opl3->command = &snd_opl2_command; - if ((err = snd_opl3_detect(opl3)) < 0) { - snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n", - opl3->l_port, opl3->r_port); - snd_device_free(card, opl3); - return err; - } - /* detect routine returns correct hardware type */ - switch (opl3->hardware & OPL3_HW_MASK) { - case OPL3_HW_OPL3: - case OPL3_HW_OPL4: - opl3->command = &snd_opl3_command; - } - } - - snd_opl3_init(opl3); - - *ropl3 = opl3; - return 0; -} - -EXPORT_SYMBOL(snd_opl3_create); - -int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) -{ - int err; - - if (timer1_dev >= 0) - if ((err = snd_opl3_timer1_init(opl3, timer1_dev)) < 0) - return err; - if (timer2_dev >= 0) { - if ((err = snd_opl3_timer2_init(opl3, timer2_dev)) < 0) { - snd_device_free(opl3->card, opl3->timer1); - opl3->timer1 = NULL; - return err; - } - } - return 0; -} - -EXPORT_SYMBOL(snd_opl3_timer_new); - -int snd_opl3_hwdep_new(struct snd_opl3 * opl3, - int device, int seq_device, - struct snd_hwdep ** rhwdep) -{ - struct snd_hwdep *hw; - struct snd_card *card = opl3->card; - int err; - - if (rhwdep) - *rhwdep = NULL; - - /* create hardware dependent device (direct FM) */ - - if ((err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw)) < 0) { - snd_device_free(card, opl3); - return err; - } - hw->private_data = opl3; - hw->exclusive = 1; -#ifdef CONFIG_SND_OSSEMUL - if (device == 0) { - hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM; - sprintf(hw->oss_dev, "dmfm%i", card->number); - } -#endif - strcpy(hw->name, hw->id); - switch (opl3->hardware & OPL3_HW_MASK) { - case OPL3_HW_OPL2: - strcpy(hw->name, "OPL2 FM"); - hw->iface = SNDRV_HWDEP_IFACE_OPL2; - break; - case OPL3_HW_OPL3: - strcpy(hw->name, "OPL3 FM"); - hw->iface = SNDRV_HWDEP_IFACE_OPL3; - break; - case OPL3_HW_OPL4: - strcpy(hw->name, "OPL4 FM"); - hw->iface = SNDRV_HWDEP_IFACE_OPL4; - break; - } - - /* operators - only ioctl */ - hw->ops.open = snd_opl3_open; - hw->ops.ioctl = snd_opl3_ioctl; - hw->ops.write = snd_opl3_write; - hw->ops.release = snd_opl3_release; - - opl3->hwdep = hw; - opl3->seq_dev_num = seq_device; -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3, - sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) { - strcpy(opl3->seq_dev->name, hw->name); - *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3; - } -#endif - if (rhwdep) - *rhwdep = hw; - return 0; -} - -EXPORT_SYMBOL(snd_opl3_hwdep_new); - -/* - * INIT part - */ - -static int __init alsa_opl3_init(void) -{ - return 0; -} - -static void __exit alsa_opl3_exit(void) -{ -} - -module_init(alsa_opl3_init) -module_exit(alsa_opl3_exit) diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_midi.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_midi.c deleted file mode 100644 index 2bfe4bcb..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_midi.c +++ /dev/null @@ -1,881 +0,0 @@ -/* - * Copyright (c) by Uros Bizjak - * - * Midi synth routines for OPL2/OPL3/OPL4 FM - * - * 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 - * - */ - -#undef DEBUG_ALLOC -#undef DEBUG_MIDI - -#include "opl3_voice.h" -#include - -extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; - -extern bool use_internal_drums; - -static void snd_opl3_note_off_unsafe(void *p, int note, int vel, - struct snd_midi_channel *chan); -/* - * The next table looks magical, but it certainly is not. Its values have - * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception - * for i=0. This log-table converts a linear volume-scaling (0..127) to a - * logarithmic scaling as present in the FM-synthesizer chips. so : Volume - * 64 = 0 db = relative volume 0 and: Volume 32 = -6 db = relative - * volume -8 it was implemented as a table because it is only 128 bytes and - * it saves a lot of log() calculations. (Rob Hooft ) - */ - -static char opl3_volume_table[128] = -{ - -63, -48, -40, -35, -32, -29, -27, -26, - -24, -23, -21, -20, -19, -18, -18, -17, - -16, -15, -15, -14, -13, -13, -12, -12, - -11, -11, -10, -10, -10, -9, -9, -8, - -8, -8, -7, -7, -7, -6, -6, -6, - -5, -5, -5, -5, -4, -4, -4, -4, - -3, -3, -3, -3, -2, -2, -2, -2, - -2, -1, -1, -1, -1, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 4, - 4, 4, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 8, 8 -}; - -void snd_opl3_calc_volume(unsigned char *volbyte, int vel, - struct snd_midi_channel *chan) -{ - int oldvol, newvol, n; - int volume; - - volume = (vel * chan->gm_volume * chan->gm_expression) / (127*127); - if (volume > 127) - volume = 127; - - oldvol = OPL3_TOTAL_LEVEL_MASK - (*volbyte & OPL3_TOTAL_LEVEL_MASK); - - newvol = opl3_volume_table[volume] + oldvol; - if (newvol > OPL3_TOTAL_LEVEL_MASK) - newvol = OPL3_TOTAL_LEVEL_MASK; - else if (newvol < 0) - newvol = 0; - - n = OPL3_TOTAL_LEVEL_MASK - (newvol & OPL3_TOTAL_LEVEL_MASK); - - *volbyte = (*volbyte & OPL3_KSL_MASK) | (n & OPL3_TOTAL_LEVEL_MASK); -} - -/* - * Converts the note frequency to block and fnum values for the FM chip - */ -static short opl3_note_table[16] = -{ - 305, 323, /* for pitch bending, -2 semitones */ - 343, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647, - 686, 726 /* for pitch bending, +2 semitones */ -}; - -static void snd_opl3_calc_pitch(unsigned char *fnum, unsigned char *blocknum, - int note, struct snd_midi_channel *chan) -{ - int block = ((note / 12) & 0x07) - 1; - int idx = (note % 12) + 2; - int freq; - - if (chan->midi_pitchbend) { - int pitchbend = chan->midi_pitchbend; - int segment; - - if (pitchbend > 0x1FFF) - pitchbend = 0x1FFF; - - segment = pitchbend / 0x1000; - freq = opl3_note_table[idx+segment]; - freq += ((opl3_note_table[idx+segment+1] - freq) * - (pitchbend % 0x1000)) / 0x1000; - } else { - freq = opl3_note_table[idx]; - } - - *fnum = (unsigned char) freq; - *blocknum = ((freq >> 8) & OPL3_FNUM_HIGH_MASK) | - ((block << 2) & OPL3_BLOCKNUM_MASK); -} - - -#ifdef DEBUG_ALLOC -static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) { - int i; - char *str = "x.24"; - - printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); - for (i = 0; i < opl3->max_voices; i++) - printk("%c", *(str + opl3->voices[i].state + 1)); - printk("\n"); -} -#endif - -/* - * Get a FM voice (channel) to play a note on. - */ -static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, - struct snd_midi_channel *chan) { - int chan_4op_1; /* first voice for 4op instrument */ - int chan_4op_2; /* second voice for 4op instrument */ - - struct snd_opl3_voice *vp, *vp2; - unsigned int voice_time; - int i; - -#ifdef DEBUG_ALLOC - char *alloc_type[3] = { "FREE ", "CHEAP ", "EXPENSIVE" }; -#endif - - /* This is our "allocation cost" table */ - enum { - FREE = 0, CHEAP, EXPENSIVE, END - }; - - /* Keeps track of what we are finding */ - struct best { - unsigned int time; - int voice; - } best[END]; - struct best *bp; - - for (i = 0; i < END; i++) { - best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */; - best[i].voice = -1; - } - - /* Look through all the channels for the most suitable. */ - for (i = 0; i < opl3->max_voices; i++) { - vp = &opl3->voices[i]; - - if (vp->state == SNDRV_OPL3_ST_NOT_AVAIL) - /* skip unavailable channels, allocated by - drum voices or by bounded 4op voices) */ - continue; - - voice_time = vp->time; - bp = best; - - chan_4op_1 = ((i < 3) || (i > 8 && i < 12)); - chan_4op_2 = ((i > 2 && i < 6) || (i > 11 && i < 15)); - if (instr_4op) { - /* allocate 4op voice */ - /* skip channels unavailable to 4op instrument */ - if (!chan_4op_1) - continue; - - if (vp->state) - /* kill one voice, CHEAP */ - bp++; - /* get state of bounded 2op channel - to be allocated for 4op instrument */ - vp2 = &opl3->voices[i + 3]; - if (vp2->state == SNDRV_OPL3_ST_ON_2OP) { - /* kill two voices, EXPENSIVE */ - bp++; - voice_time = (voice_time > vp->time) ? - voice_time : vp->time; - } - } else { - /* allocate 2op voice */ - if ((chan_4op_1) || (chan_4op_2)) - /* use bounded channels for 2op, CHEAP */ - bp++; - else if (vp->state) - /* kill one voice on 2op channel, CHEAP */ - bp++; - /* raise kill cost to EXPENSIVE for all channels */ - if (vp->state) - bp++; - } - if (voice_time < bp->time) { - bp->time = voice_time; - bp->voice = i; - } - } - - for (i = 0; i < END; i++) { - if (best[i].voice >= 0) { -#ifdef DEBUG_ALLOC - printk(KERN_DEBUG "%s %iop allocation on voice %i\n", - alloc_type[i], instr_4op ? 4 : 2, - best[i].voice); -#endif - return best[i].voice; - } - } - /* not found */ - return -1; -} - -/* ------------------------------ */ - -/* - * System timer interrupt function - */ -void snd_opl3_timer_func(unsigned long data) -{ - - struct snd_opl3 *opl3 = (struct snd_opl3 *)data; - unsigned long flags; - int again = 0; - int i; - - spin_lock_irqsave(&opl3->voice_lock, flags); - for (i = 0; i < opl3->max_voices; i++) { - struct snd_opl3_voice *vp = &opl3->voices[i]; - if (vp->state > 0 && vp->note_off_check) { - if (vp->note_off == jiffies) - snd_opl3_note_off_unsafe(opl3, vp->note, 0, - vp->chan); - else - again++; - } - } - spin_unlock_irqrestore(&opl3->voice_lock, flags); - - spin_lock_irqsave(&opl3->sys_timer_lock, flags); - if (again) { - opl3->tlist.expires = jiffies + 1; /* invoke again */ - add_timer(&opl3->tlist); - } else { - opl3->sys_timer_status = 0; - } - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); -} - -/* - * Start system timer - */ -static void snd_opl3_start_timer(struct snd_opl3 *opl3) -{ - unsigned long flags; - spin_lock_irqsave(&opl3->sys_timer_lock, flags); - if (! opl3->sys_timer_status) { - opl3->tlist.expires = jiffies + 1; - add_timer(&opl3->tlist); - opl3->sys_timer_status = 1; - } - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); -} - -/* ------------------------------ */ - - -static int snd_opl3_oss_map[MAX_OPL3_VOICES] = { - 0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17, 3, 4 ,5, 12, 13, 14 -}; - -/* - * Start a note. - */ -void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - int instr_4op; - - int voice; - struct snd_opl3_voice *vp, *vp2; - unsigned short connect_mask; - unsigned char connection; - unsigned char vol_op[4]; - - int extra_prg = 0; - - unsigned short reg_side; - unsigned char op_offset; - unsigned char voice_offset; - unsigned short opl3_reg; - unsigned char reg_val; - unsigned char prg, bank; - - int key = note; - unsigned char fnum, blocknum; - int i; - - struct fm_patch *patch; - struct fm_instrument *fm; - unsigned long flags; - - opl3 = p; - -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n", - chan->number, chan->midi_program, note, vel); -#endif - - /* in SYNTH mode, application takes care of voices */ - /* in SEQ mode, drum voice numbers are notes on drum channel */ - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { - if (chan->drum_channel) { - /* percussion instruments are located in bank 128 */ - bank = 128; - prg = note; - } else { - bank = chan->gm_bank_select; - prg = chan->midi_program; - } - } else { - /* Prepare for OSS mode */ - if (chan->number >= MAX_OPL3_VOICES) - return; - - /* OSS instruments are located in bank 127 */ - bank = 127; - prg = chan->midi_program; - } - - spin_lock_irqsave(&opl3->voice_lock, flags); - - if (use_internal_drums) { - snd_opl3_drum_switch(opl3, note, vel, 1, chan); - spin_unlock_irqrestore(&opl3->voice_lock, flags); - return; - } - - __extra_prg: - patch = snd_opl3_find_patch(opl3, prg, bank, 0); - if (!patch) { - spin_unlock_irqrestore(&opl3->voice_lock, flags); - return; - } - - fm = &patch->inst; - switch (patch->type) { - case FM_PATCH_OPL2: - instr_4op = 0; - break; - case FM_PATCH_OPL3: - if (opl3->hardware >= OPL3_HW_OPL3) { - instr_4op = 1; - break; - } - default: - spin_unlock_irqrestore(&opl3->voice_lock, flags); - return; - } -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> OPL%i instrument: %s\n", - instr_4op ? 3 : 2, patch->name); -#endif - /* in SYNTH mode, application takes care of voices */ - /* in SEQ mode, allocate voice on free OPL3 channel */ - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { - voice = opl3_get_voice(opl3, instr_4op, chan); - } else { - /* remap OSS voice */ - voice = snd_opl3_oss_map[chan->number]; - } - - if (voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = voice; - connect_mask = (OPL3_LEFT_4OP_0 << voice_offset) & 0x07; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = voice - MAX_OPL2_VOICES; - connect_mask = (OPL3_RIGHT_4OP_0 << voice_offset) & 0x38; - } - - /* kill voice on channel */ - vp = &opl3->voices[voice]; - if (vp->state > 0) { - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT; - opl3->command(opl3, opl3_reg, reg_val); - } - if (instr_4op) { - vp2 = &opl3->voices[voice + 3]; - if (vp->state > 0) { - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + - voice_offset + 3); - reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT; - opl3->command(opl3, opl3_reg, reg_val); - } - } - - /* set connection register */ - if (instr_4op) { - if ((opl3->connection_reg ^ connect_mask) & connect_mask) { - opl3->connection_reg |= connect_mask; - /* set connection bit */ - opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT; - opl3->command(opl3, opl3_reg, opl3->connection_reg); - } - } else { - if ((opl3->connection_reg ^ ~connect_mask) & connect_mask) { - opl3->connection_reg &= ~connect_mask; - /* clear connection bit */ - opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT; - opl3->command(opl3, opl3_reg, opl3->connection_reg); - } - } - -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> setting OPL3 connection: 0x%x\n", - opl3->connection_reg); -#endif - /* - * calculate volume depending on connection - * between FM operators (see include/opl3.h) - */ - for (i = 0; i < (instr_4op ? 4 : 2); i++) - vol_op[i] = fm->op[i].ksl_level; - - connection = fm->feedback_connection[0] & 0x01; - if (instr_4op) { - connection <<= 1; - connection |= fm->feedback_connection[1] & 0x01; - - snd_opl3_calc_volume(&vol_op[3], vel, chan); - switch (connection) { - case 0x03: - snd_opl3_calc_volume(&vol_op[2], vel, chan); - /* fallthru */ - case 0x02: - snd_opl3_calc_volume(&vol_op[0], vel, chan); - break; - case 0x01: - snd_opl3_calc_volume(&vol_op[1], vel, chan); - } - } else { - snd_opl3_calc_volume(&vol_op[1], vel, chan); - if (connection) - snd_opl3_calc_volume(&vol_op[0], vel, chan); - } - - /* Program the FM voice characteristics */ - for (i = 0; i < (instr_4op ? 4 : 2); i++) { -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> programming operator %i\n", i); -#endif - op_offset = snd_opl3_regmap[voice_offset][i]; - - /* Set OPL3 AM_VIB register of requested voice/operator */ - reg_val = fm->op[i].am_vib; - opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set OPL3 KSL_LEVEL register of requested voice/operator */ - reg_val = vol_op[i]; - opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set OPL3 ATTACK_DECAY register of requested voice/operator */ - reg_val = fm->op[i].attack_decay; - opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ - reg_val = fm->op[i].sustain_release; - opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Select waveform */ - reg_val = fm->op[i].wave_select; - opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - } - - /* Set operator feedback and 2op inter-operator connection */ - reg_val = fm->feedback_connection[0]; - /* Set output voice connection */ - reg_val |= OPL3_STEREO_BITS; - if (chan->gm_pan < 43) - reg_val &= ~OPL3_VOICE_TO_RIGHT; - if (chan->gm_pan > 85) - reg_val &= ~OPL3_VOICE_TO_LEFT; - opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); - - if (instr_4op) { - /* Set 4op inter-operator connection */ - reg_val = fm->feedback_connection[1] & OPL3_CONNECTION_BIT; - /* Set output voice connection */ - reg_val |= OPL3_STEREO_BITS; - if (chan->gm_pan < 43) - reg_val &= ~OPL3_VOICE_TO_RIGHT; - if (chan->gm_pan > 85) - reg_val &= ~OPL3_VOICE_TO_LEFT; - opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + - voice_offset + 3); - opl3->command(opl3, opl3_reg, reg_val); - } - - /* - * Special treatment of percussion notes for fm: - * Requested pitch is really program, and pitch for - * device is whatever was specified in the patch library. - */ - if (fm->fix_key) - note = fm->fix_key; - /* - * use transpose if defined in patch library - */ - if (fm->trnsps) - note += (fm->trnsps - 64); - - snd_opl3_calc_pitch(&fnum, &blocknum, note, chan); - - /* Set OPL3 FNUM_LOW register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset); - opl3->command(opl3, opl3_reg, fnum); - - opl3->voices[voice].keyon_reg = blocknum; - - /* Set output sound flag */ - blocknum |= OPL3_KEYON_BIT; - -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> trigger voice %i\n", voice); -#endif - /* Set OPL3 KEYON_BLOCK register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, blocknum); - - /* kill note after fixed duration (in centiseconds) */ - if (fm->fix_dur) { - opl3->voices[voice].note_off = jiffies + - (fm->fix_dur * HZ) / 100; - snd_opl3_start_timer(opl3); - opl3->voices[voice].note_off_check = 1; - } else - opl3->voices[voice].note_off_check = 0; - - /* get extra pgm, but avoid possible loops */ - extra_prg = (extra_prg) ? 0 : fm->modes; - - /* do the bookkeeping */ - vp->time = opl3->use_time++; - vp->note = key; - vp->chan = chan; - - if (instr_4op) { - vp->state = SNDRV_OPL3_ST_ON_4OP; - - vp2 = &opl3->voices[voice + 3]; - vp2->time = opl3->use_time++; - vp2->note = key; - vp2->chan = chan; - vp2->state = SNDRV_OPL3_ST_NOT_AVAIL; - } else { - if (vp->state == SNDRV_OPL3_ST_ON_4OP) { - /* 4op killed by 2op, release bounded voice */ - vp2 = &opl3->voices[voice + 3]; - vp2->time = opl3->use_time++; - vp2->state = SNDRV_OPL3_ST_OFF; - } - vp->state = SNDRV_OPL3_ST_ON_2OP; - } - -#ifdef DEBUG_ALLOC - debug_alloc(opl3, "note on ", voice); -#endif - - /* allocate extra program if specified in patch library */ - if (extra_prg) { - if (extra_prg > 128) { - bank = 128; - /* percussions start at 35 */ - prg = extra_prg - 128 + 35 - 1; - } else { - bank = 0; - prg = extra_prg - 1; - } -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " *** allocating extra program\n"); -#endif - goto __extra_prg; - } - spin_unlock_irqrestore(&opl3->voice_lock, flags); -} - -static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) -{ - unsigned short reg_side; - unsigned char voice_offset; - unsigned short opl3_reg; - - struct snd_opl3_voice *vp, *vp2; - - if (snd_BUG_ON(voice >= MAX_OPL3_VOICES)) - return; - - vp = &opl3->voices[voice]; - if (voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = voice; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = voice - MAX_OPL2_VOICES; - } - - /* kill voice */ -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG " --> kill voice %i\n", voice); -#endif - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - /* clear Key ON bit */ - opl3->command(opl3, opl3_reg, vp->keyon_reg); - - /* do the bookkeeping */ - vp->time = opl3->use_time++; - - if (vp->state == SNDRV_OPL3_ST_ON_4OP) { - vp2 = &opl3->voices[voice + 3]; - - vp2->time = opl3->use_time++; - vp2->state = SNDRV_OPL3_ST_OFF; - } - vp->state = SNDRV_OPL3_ST_OFF; -#ifdef DEBUG_ALLOC - debug_alloc(opl3, "note off", voice); -#endif - -} - -/* - * Release a note in response to a midi note off. - */ -static void snd_opl3_note_off_unsafe(void *p, int note, int vel, - struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - - int voice; - struct snd_opl3_voice *vp; - - opl3 = p; - -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n", - chan->number, chan->midi_program, note); -#endif - - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { - if (chan->drum_channel && use_internal_drums) { - snd_opl3_drum_switch(opl3, note, vel, 0, chan); - return; - } - /* this loop will hopefully kill all extra voices, because - they are grouped by the same channel and note values */ - for (voice = 0; voice < opl3->max_voices; voice++) { - vp = &opl3->voices[voice]; - if (vp->state > 0 && vp->chan == chan && vp->note == note) { - snd_opl3_kill_voice(opl3, voice); - } - } - } else { - /* remap OSS voices */ - if (chan->number < MAX_OPL3_VOICES) { - voice = snd_opl3_oss_map[chan->number]; - snd_opl3_kill_voice(opl3, voice); - } - } -} - -void snd_opl3_note_off(void *p, int note, int vel, - struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3 = p; - unsigned long flags; - - spin_lock_irqsave(&opl3->voice_lock, flags); - snd_opl3_note_off_unsafe(p, note, vel, chan); - spin_unlock_irqrestore(&opl3->voice_lock, flags); -} - -/* - * key pressure change - */ -void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif -} - -/* - * terminate note - */ -void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif -} - -static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice) -{ - unsigned short reg_side; - unsigned char voice_offset; - unsigned short opl3_reg; - - unsigned char fnum, blocknum; - - struct snd_opl3_voice *vp; - - if (snd_BUG_ON(voice >= MAX_OPL3_VOICES)) - return; - - vp = &opl3->voices[voice]; - if (vp->chan == NULL) - return; /* not allocated? */ - - if (voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = voice; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = voice - MAX_OPL2_VOICES; - } - - snd_opl3_calc_pitch(&fnum, &blocknum, vp->note, vp->chan); - - /* Set OPL3 FNUM_LOW register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset); - opl3->command(opl3, opl3_reg, fnum); - - vp->keyon_reg = blocknum; - - /* Set output sound flag */ - blocknum |= OPL3_KEYON_BIT; - - /* Set OPL3 KEYON_BLOCK register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, blocknum); - - vp->time = opl3->use_time++; -} - -/* - * Update voice pitch controller - */ -static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel *chan) -{ - int voice; - struct snd_opl3_voice *vp; - - unsigned long flags; - - spin_lock_irqsave(&opl3->voice_lock, flags); - - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { - for (voice = 0; voice < opl3->max_voices; voice++) { - vp = &opl3->voices[voice]; - if (vp->state > 0 && vp->chan == chan) { - snd_opl3_update_pitch(opl3, voice); - } - } - } else { - /* remap OSS voices */ - if (chan->number < MAX_OPL3_VOICES) { - voice = snd_opl3_oss_map[chan->number]; - snd_opl3_update_pitch(opl3, voice); - } - } - spin_unlock_irqrestore(&opl3->voice_lock, flags); -} - -/* - * Deal with a controller type event. This includes all types of - * control events, not just the midi controllers - */ -void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n", - type, chan->number, chan->midi_program); -#endif - - switch (type) { - case MIDI_CTL_MSB_MODWHEEL: - if (chan->control[MIDI_CTL_MSB_MODWHEEL] > 63) - opl3->drum_reg |= OPL3_VIBRATO_DEPTH; - else - opl3->drum_reg &= ~OPL3_VIBRATO_DEPTH; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, - opl3->drum_reg); - break; - case MIDI_CTL_E2_TREMOLO_DEPTH: - if (chan->control[MIDI_CTL_E2_TREMOLO_DEPTH] > 63) - opl3->drum_reg |= OPL3_TREMOLO_DEPTH; - else - opl3->drum_reg &= ~OPL3_TREMOLO_DEPTH; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, - opl3->drum_reg); - break; - case MIDI_CTL_PITCHBEND: - snd_opl3_pitch_ctrl(opl3, chan); - break; - } -} - -/* - * NRPN events - */ -void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, - struct snd_midi_channel_set *chset) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n", - chan->number, chan->midi_program); -#endif -} - -/* - * receive sysex - */ -void snd_opl3_sysex(void *p, unsigned char *buf, int len, - int parsed, struct snd_midi_channel_set *chset) -{ - struct snd_opl3 *opl3; - - opl3 = p; -#ifdef DEBUG_MIDI - snd_printk(KERN_DEBUG "SYSEX\n"); -#endif -} diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_oss.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_oss.c deleted file mode 100644 index c1cb249a..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_oss.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Interface for OSS sequencer emulation - * - * Copyright (C) 2000 Uros Bizjak - * - * 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 "opl3_voice.h" - -static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure); -static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg); -static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg); -static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count); -static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg); - -/* */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* operators */ - -extern struct snd_midi_op opl3_ops; - -static struct snd_seq_oss_callback oss_callback = { - .owner = THIS_MODULE, - .open = snd_opl3_open_seq_oss, - .close = snd_opl3_close_seq_oss, - .ioctl = snd_opl3_ioctl_seq_oss, - .load_patch = snd_opl3_load_patch_seq_oss, - .reset = snd_opl3_reset_seq_oss, -}; - -static int snd_opl3_oss_event_input(struct snd_seq_event *ev, int direct, - void *private_data, int atomic, int hop) -{ - struct snd_opl3 *opl3 = private_data; - - if (ev->type != SNDRV_SEQ_EVENT_OSS) - snd_midi_process_event(&opl3_ops, ev, opl3->oss_chset); - return 0; -} - -/* ------------------------------ */ - -static void snd_opl3_oss_free_port(void *private_data) -{ - struct snd_opl3 *opl3 = private_data; - - snd_midi_channel_free_set(opl3->oss_chset); -} - -static int snd_opl3_oss_create_port(struct snd_opl3 * opl3) -{ - struct snd_seq_port_callback callbacks; - char name[32]; - int voices, opl_ver; - - voices = (opl3->hardware < OPL3_HW_OPL3) ? - MAX_OPL2_VOICES : MAX_OPL3_VOICES; - opl3->oss_chset = snd_midi_channel_alloc_set(voices); - if (opl3->oss_chset == NULL) - return -ENOMEM; - opl3->oss_chset->private_data = opl3; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.owner = THIS_MODULE; - callbacks.event_input = snd_opl3_oss_event_input; - callbacks.private_free = snd_opl3_oss_free_port; - callbacks.private_data = opl3; - - opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; - sprintf(name, "OPL%i OSS Port", opl_ver); - - opl3->oss_chset->client = opl3->seq_client; - opl3->oss_chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks, - SNDRV_SEQ_PORT_CAP_WRITE, - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_HARDWARE | - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, - voices, voices, - name); - if (opl3->oss_chset->port < 0) { - int port; - port = opl3->oss_chset->port; - snd_midi_channel_free_set(opl3->oss_chset); - return port; - } - return 0; -} - -/* ------------------------------ */ - -/* register OSS synth */ -void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name) -{ - struct snd_seq_oss_reg *arg; - struct snd_seq_device *dev; - - if (snd_seq_device_new(opl3->card, 0, SNDRV_SEQ_DEV_ID_OSS, - sizeof(struct snd_seq_oss_reg), &dev) < 0) - return; - - opl3->oss_seq_dev = dev; - strlcpy(dev->name, name, sizeof(dev->name)); - arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); - arg->type = SYNTH_TYPE_FM; - if (opl3->hardware < OPL3_HW_OPL3) { - arg->subtype = FM_TYPE_ADLIB; - arg->nvoices = MAX_OPL2_VOICES; - } else { - arg->subtype = FM_TYPE_OPL3; - arg->nvoices = MAX_OPL3_VOICES; - } - arg->oper = oss_callback; - arg->private_data = opl3; - - if (snd_opl3_oss_create_port(opl3)) { - /* register to OSS synth table */ - snd_device_register(opl3->card, dev); - } -} - -/* unregister */ -void snd_opl3_free_seq_oss(struct snd_opl3 *opl3) -{ - if (opl3->oss_seq_dev) { - /* The instance should have been released in prior */ - opl3->oss_seq_dev = NULL; - } -} - -/* ------------------------------ */ - -/* open OSS sequencer */ -static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) -{ - struct snd_opl3 *opl3 = closure; - int err; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - - if ((err = snd_opl3_synth_setup(opl3)) < 0) - return err; - - /* fill the argument data */ - arg->private_data = opl3; - arg->addr.client = opl3->oss_chset->client; - arg->addr.port = opl3->oss_chset->port; - - if ((err = snd_opl3_synth_use_inc(opl3)) < 0) - return err; - - opl3->synth_mode = SNDRV_OPL3_MODE_SYNTH; - return 0; -} - -/* close OSS sequencer */ -static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg) -{ - struct snd_opl3 *opl3; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - opl3 = arg->private_data; - - snd_opl3_synth_cleanup(opl3); - - snd_opl3_synth_use_dec(opl3); - return 0; -} - -/* load patch */ - -/* from sound_config.h */ -#define SBFM_MAXINSTR 256 - -static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, - const char __user *buf, int offs, int count) -{ - struct snd_opl3 *opl3; - struct sbi_instrument sbi; - char name[32]; - int err, type; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - opl3 = arg->private_data; - - if (format == FM_PATCH) - type = FM_PATCH_OPL2; - else if (format == OPL3_PATCH) - type = FM_PATCH_OPL3; - else - return -EINVAL; - - if (count < (int)sizeof(sbi)) { - snd_printk(KERN_ERR "FM Error: Patch record too short\n"); - return -EINVAL; - } - if (copy_from_user(&sbi, buf, sizeof(sbi))) - return -EFAULT; - - if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { - snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n", - sbi.channel); - return -EINVAL; - } - - memset(name, 0, sizeof(name)); - sprintf(name, "Chan%d", sbi.channel); - - err = snd_opl3_load_patch(opl3, sbi.channel, 127, type, name, NULL, - sbi.operators); - if (err < 0) - return err; - - return sizeof(sbi); -} - -/* ioctl */ -static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, - unsigned long ioarg) -{ - struct snd_opl3 *opl3; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - opl3 = arg->private_data; - switch (cmd) { - case SNDCTL_FM_LOAD_INSTR: - snd_printk(KERN_ERR "OPL3: " - "Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. " - "Fix the program.\n"); - return -EINVAL; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - - case SNDCTL_FM_4OP_ENABLE: - // handled automatically by OPL instrument type - return 0; - - default: - return -EINVAL; - } - return 0; -} - -/* reset device */ -static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg) -{ - struct snd_opl3 *opl3; - - if (snd_BUG_ON(!arg)) - return -ENXIO; - opl3 = arg->private_data; - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_seq.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_seq.c deleted file mode 100644 index 68399538..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_seq.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) by Uros Bizjak - * - * Midi Sequencer interface routines for OPL2/OPL3/OPL4 FM - * - * OPL2/3 FM instrument loader: - * alsa-tools/seq/sbiload/ - * - * 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 "opl3_voice.h" -#include -#include -#include -#include - -MODULE_AUTHOR("Uros Bizjak "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ALSA driver for OPL3 FM synth"); - -bool use_internal_drums = 0; -module_param(use_internal_drums, bool, 0444); -MODULE_PARM_DESC(use_internal_drums, "Enable internal OPL2/3 drums."); - -int snd_opl3_synth_use_inc(struct snd_opl3 * opl3) -{ - if (!try_module_get(opl3->card->module)) - return -EFAULT; - return 0; - -} - -void snd_opl3_synth_use_dec(struct snd_opl3 * opl3) -{ - module_put(opl3->card->module); -} - -int snd_opl3_synth_setup(struct snd_opl3 * opl3) -{ - int idx; - struct snd_hwdep *hwdep = opl3->hwdep; - - mutex_lock(&hwdep->open_mutex); - if (hwdep->used) { - mutex_unlock(&hwdep->open_mutex); - return -EBUSY; - } - hwdep->used++; - mutex_unlock(&hwdep->open_mutex); - - snd_opl3_reset(opl3); - - for (idx = 0; idx < MAX_OPL3_VOICES; idx++) { - opl3->voices[idx].state = SNDRV_OPL3_ST_OFF; - opl3->voices[idx].time = 0; - opl3->voices[idx].keyon_reg = 0x00; - } - opl3->use_time = 0; - opl3->connection_reg = 0x00; - if (opl3->hardware >= OPL3_HW_OPL3) { - /* Clear 4-op connections */ - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, - opl3->connection_reg); - opl3->max_voices = MAX_OPL3_VOICES; - } - return 0; -} - -void snd_opl3_synth_cleanup(struct snd_opl3 * opl3) -{ - unsigned long flags; - struct snd_hwdep *hwdep; - - /* Stop system timer */ - spin_lock_irqsave(&opl3->sys_timer_lock, flags); - if (opl3->sys_timer_status) { - del_timer(&opl3->tlist); - opl3->sys_timer_status = 0; - } - spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); - - snd_opl3_reset(opl3); - hwdep = opl3->hwdep; - mutex_lock(&hwdep->open_mutex); - hwdep->used--; - mutex_unlock(&hwdep->open_mutex); - wake_up(&hwdep->open_wait); -} - -static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe * info) -{ - struct snd_opl3 *opl3 = private_data; - int err; - - if ((err = snd_opl3_synth_setup(opl3)) < 0) - return err; - - if (use_internal_drums) { - /* Percussion mode */ - opl3->voices[6].state = opl3->voices[7].state = - opl3->voices[8].state = SNDRV_OPL3_ST_NOT_AVAIL; - snd_opl3_load_drums(opl3); - opl3->drum_reg = OPL3_PERCUSSION_ENABLE; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, opl3->drum_reg); - } else { - opl3->drum_reg = 0x00; - } - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { - if ((err = snd_opl3_synth_use_inc(opl3)) < 0) - return err; - } - opl3->synth_mode = SNDRV_OPL3_MODE_SEQ; - return 0; -} - -static int snd_opl3_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info) -{ - struct snd_opl3 *opl3 = private_data; - - snd_opl3_synth_cleanup(opl3); - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) - snd_opl3_synth_use_dec(opl3); - return 0; -} - -/* - * MIDI emulation operators - */ -struct snd_midi_op opl3_ops = { - .note_on = snd_opl3_note_on, - .note_off = snd_opl3_note_off, - .key_press = snd_opl3_key_press, - .note_terminate = snd_opl3_terminate_note, - .control = snd_opl3_control, - .nrpn = snd_opl3_nrpn, - .sysex = snd_opl3_sysex, -}; - -static int snd_opl3_synth_event_input(struct snd_seq_event * ev, int direct, - void *private_data, int atomic, int hop) -{ - struct snd_opl3 *opl3 = private_data; - - snd_midi_process_event(&opl3_ops, ev, opl3->chset); - return 0; -} - -/* ------------------------------ */ - -static void snd_opl3_synth_free_port(void *private_data) -{ - struct snd_opl3 *opl3 = private_data; - - snd_midi_channel_free_set(opl3->chset); -} - -static int snd_opl3_synth_create_port(struct snd_opl3 * opl3) -{ - struct snd_seq_port_callback callbacks; - char name[32]; - int voices, opl_ver; - - voices = (opl3->hardware < OPL3_HW_OPL3) ? - MAX_OPL2_VOICES : MAX_OPL3_VOICES; - opl3->chset = snd_midi_channel_alloc_set(16); - if (opl3->chset == NULL) - return -ENOMEM; - opl3->chset->private_data = opl3; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.owner = THIS_MODULE; - callbacks.use = snd_opl3_synth_use; - callbacks.unuse = snd_opl3_synth_unuse; - callbacks.event_input = snd_opl3_synth_event_input; - callbacks.private_free = snd_opl3_synth_free_port; - callbacks.private_data = opl3; - - opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; - sprintf(name, "OPL%i FM Port", opl_ver); - - opl3->chset->client = opl3->seq_client; - opl3->chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks, - SNDRV_SEQ_PORT_CAP_WRITE | - SNDRV_SEQ_PORT_CAP_SUBS_WRITE, - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | - SNDRV_SEQ_PORT_TYPE_HARDWARE | - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, - 16, voices, - name); - if (opl3->chset->port < 0) { - int port; - port = opl3->chset->port; - snd_midi_channel_free_set(opl3->chset); - return port; - } - return 0; -} - -/* ------------------------------ */ - -static int snd_opl3_seq_new_device(struct snd_seq_device *dev) -{ - struct snd_opl3 *opl3; - int client, err; - char name[32]; - int opl_ver; - - opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (opl3 == NULL) - return -EINVAL; - - spin_lock_init(&opl3->voice_lock); - - opl3->seq_client = -1; - - /* allocate new client */ - opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; - sprintf(name, "OPL%i FM synth", opl_ver); - client = opl3->seq_client = - snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num, - name); - if (client < 0) - return client; - - if ((err = snd_opl3_synth_create_port(opl3)) < 0) { - snd_seq_delete_kernel_client(client); - opl3->seq_client = -1; - return err; - } - - /* setup system timer */ - init_timer(&opl3->tlist); - opl3->tlist.function = snd_opl3_timer_func; - opl3->tlist.data = (unsigned long) opl3; - spin_lock_init(&opl3->sys_timer_lock); - opl3->sys_timer_status = 0; - -#ifdef CONFIG_SND_SEQUENCER_OSS - snd_opl3_init_seq_oss(opl3, name); -#endif - return 0; -} - -static int snd_opl3_seq_delete_device(struct snd_seq_device *dev) -{ - struct snd_opl3 *opl3; - - opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (opl3 == NULL) - return -EINVAL; - -#ifdef CONFIG_SND_SEQUENCER_OSS - snd_opl3_free_seq_oss(opl3); -#endif - if (opl3->seq_client >= 0) { - snd_seq_delete_kernel_client(opl3->seq_client); - opl3->seq_client = -1; - } - return 0; -} - -static int __init alsa_opl3_seq_init(void) -{ - static struct snd_seq_dev_ops ops = - { - snd_opl3_seq_new_device, - snd_opl3_seq_delete_device - }; - - return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL3, &ops, - sizeof(struct snd_opl3 *)); -} - -static void __exit alsa_opl3_seq_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL3); -} - -module_init(alsa_opl3_seq_init) -module_exit(alsa_opl3_seq_exit) diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_synth.c b/ANDROID_3.4.5/sound/drivers/opl3/opl3_synth.c deleted file mode 100644 index 742a4b64..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_synth.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Copyright (c) by Uros Bizjak - * - * Routines for OPL2/OPL3/OPL4 control - * - * 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 - -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) -#define OPL3_SUPPORT_SYNTH -#endif - -/* - * There is 18 possible 2 OP voices - * (9 in the left and 9 in the right). - * The first OP is the modulator and 2nd is the carrier. - * - * The first three voices in the both sides may be connected - * with another voice to a 4 OP voice. For example voice 0 - * can be connected with voice 3. The operators of voice 3 are - * used as operators 3 and 4 of the new 4 OP voice. - * In this case the 2 OP voice number 0 is the 'first half' and - * voice 3 is the second. - */ - - -/* - * Register offset table for OPL2/3 voices, - * OPL2 / one OPL3 register array side only - */ - -char snd_opl3_regmap[MAX_OPL2_VOICES][4] = -{ -/* OP1 OP2 OP3 OP4 */ -/* ------------------------ */ - { 0x00, 0x03, 0x08, 0x0b }, - { 0x01, 0x04, 0x09, 0x0c }, - { 0x02, 0x05, 0x0a, 0x0d }, - - { 0x08, 0x0b, 0x00, 0x00 }, - { 0x09, 0x0c, 0x00, 0x00 }, - { 0x0a, 0x0d, 0x00, 0x00 }, - - { 0x10, 0x13, 0x00, 0x00 }, /* used by percussive voices */ - { 0x11, 0x14, 0x00, 0x00 }, /* if the percussive mode */ - { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */ -}; - -EXPORT_SYMBOL(snd_opl3_regmap); - -/* - * prototypes - */ -static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note); -static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice); -static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params); -static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode); -static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection); - -/* ------------------------------ */ - -/* - * open the device exclusively - */ -int snd_opl3_open(struct snd_hwdep * hw, struct file *file) -{ - return 0; -} - -/* - * ioctl for hwdep device: - */ -int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct snd_opl3 *opl3 = hw->private_data; - void __user *argp = (void __user *)arg; - - if (snd_BUG_ON(!opl3)) - return -EINVAL; - - switch (cmd) { - /* get information */ - case SNDRV_DM_FM_IOCTL_INFO: - { - struct snd_dm_fm_info info; - - info.fm_mode = opl3->fm_mode; - info.rhythm = opl3->rhythm; - if (copy_to_user(argp, &info, sizeof(struct snd_dm_fm_info))) - return -EFAULT; - return 0; - } - - case SNDRV_DM_FM_IOCTL_RESET: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_RESET: -#endif - snd_opl3_reset(opl3); - return 0; - - case SNDRV_DM_FM_IOCTL_PLAY_NOTE: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE: -#endif - { - struct snd_dm_fm_note note; - if (copy_from_user(¬e, argp, sizeof(struct snd_dm_fm_note))) - return -EFAULT; - return snd_opl3_play_note(opl3, ¬e); - } - - case SNDRV_DM_FM_IOCTL_SET_VOICE: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_SET_VOICE: -#endif - { - struct snd_dm_fm_voice voice; - if (copy_from_user(&voice, argp, sizeof(struct snd_dm_fm_voice))) - return -EFAULT; - return snd_opl3_set_voice(opl3, &voice); - } - - case SNDRV_DM_FM_IOCTL_SET_PARAMS: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS: -#endif - { - struct snd_dm_fm_params params; - if (copy_from_user(¶ms, argp, sizeof(struct snd_dm_fm_params))) - return -EFAULT; - return snd_opl3_set_params(opl3, ¶ms); - } - - case SNDRV_DM_FM_IOCTL_SET_MODE: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_SET_MODE: -#endif - return snd_opl3_set_mode(opl3, (int) arg); - - case SNDRV_DM_FM_IOCTL_SET_CONNECTION: -#ifdef CONFIG_SND_OSSEMUL - case SNDRV_DM_FM_OSS_IOCTL_SET_OPL: -#endif - return snd_opl3_set_connection(opl3, (int) arg); - -#ifdef OPL3_SUPPORT_SYNTH - case SNDRV_DM_FM_IOCTL_CLEAR_PATCHES: - snd_opl3_clear_patches(opl3); - return 0; -#endif - -#ifdef CONFIG_SND_DEBUG - default: - snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd); -#endif - } - return -ENOTTY; -} - -/* - * close the device - */ -int snd_opl3_release(struct snd_hwdep * hw, struct file *file) -{ - struct snd_opl3 *opl3 = hw->private_data; - - snd_opl3_reset(opl3); - return 0; -} - -#ifdef OPL3_SUPPORT_SYNTH -/* - * write the device - load patches - */ -long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count, - loff_t *offset) -{ - struct snd_opl3 *opl3 = hw->private_data; - long result = 0; - int err = 0; - struct sbi_patch inst; - - while (count >= sizeof(inst)) { - unsigned char type; - if (copy_from_user(&inst, buf, sizeof(inst))) - return -EFAULT; - if (!memcmp(inst.key, FM_KEY_SBI, 4) || - !memcmp(inst.key, FM_KEY_2OP, 4)) - type = FM_PATCH_OPL2; - else if (!memcmp(inst.key, FM_KEY_4OP, 4)) - type = FM_PATCH_OPL3; - else /* invalid type */ - break; - err = snd_opl3_load_patch(opl3, inst.prog, inst.bank, type, - inst.name, inst.extension, - inst.data); - if (err < 0) - break; - result += sizeof(inst); - count -= sizeof(inst); - } - return result > 0 ? result : err; -} - - -/* - * Patch management - */ - -/* offsets for SBI params */ -#define AM_VIB 0 -#define KSL_LEVEL 2 -#define ATTACK_DECAY 4 -#define SUSTAIN_RELEASE 6 -#define WAVE_SELECT 8 - -/* offset for SBI instrument */ -#define CONNECTION 10 -#define OFFSET_4OP 11 - -/* - * load a patch, obviously. - * - * loaded on the given program and bank numbers with the given type - * (FM_PATCH_OPLx). - * data is the pointer of SBI record _without_ header (key and name). - * name is the name string of the patch. - * ext is the extension data of 7 bytes long (stored in name of SBI - * data up to offset 25), or NULL to skip. - * return 0 if successful or a negative error code. - */ -int snd_opl3_load_patch(struct snd_opl3 *opl3, - int prog, int bank, int type, - const char *name, - const unsigned char *ext, - const unsigned char *data) -{ - struct fm_patch *patch; - int i; - - patch = snd_opl3_find_patch(opl3, prog, bank, 1); - if (!patch) - return -ENOMEM; - - patch->type = type; - - for (i = 0; i < 2; i++) { - patch->inst.op[i].am_vib = data[AM_VIB + i]; - patch->inst.op[i].ksl_level = data[KSL_LEVEL + i]; - patch->inst.op[i].attack_decay = data[ATTACK_DECAY + i]; - patch->inst.op[i].sustain_release = data[SUSTAIN_RELEASE + i]; - patch->inst.op[i].wave_select = data[WAVE_SELECT + i]; - } - patch->inst.feedback_connection[0] = data[CONNECTION]; - - if (type == FM_PATCH_OPL3) { - for (i = 0; i < 2; i++) { - patch->inst.op[i+2].am_vib = - data[OFFSET_4OP + AM_VIB + i]; - patch->inst.op[i+2].ksl_level = - data[OFFSET_4OP + KSL_LEVEL + i]; - patch->inst.op[i+2].attack_decay = - data[OFFSET_4OP + ATTACK_DECAY + i]; - patch->inst.op[i+2].sustain_release = - data[OFFSET_4OP + SUSTAIN_RELEASE + i]; - patch->inst.op[i+2].wave_select = - data[OFFSET_4OP + WAVE_SELECT + i]; - } - patch->inst.feedback_connection[1] = - data[OFFSET_4OP + CONNECTION]; - } - - if (ext) { - patch->inst.echo_delay = ext[0]; - patch->inst.echo_atten = ext[1]; - patch->inst.chorus_spread = ext[2]; - patch->inst.trnsps = ext[3]; - patch->inst.fix_dur = ext[4]; - patch->inst.modes = ext[5]; - patch->inst.fix_key = ext[6]; - } - - if (name) - strlcpy(patch->name, name, sizeof(patch->name)); - - return 0; -} -EXPORT_SYMBOL(snd_opl3_load_patch); - -/* - * find a patch with the given program and bank numbers, returns its pointer - * if no matching patch is found and create_patch is set, it creates a - * new patch object. - */ -struct fm_patch *snd_opl3_find_patch(struct snd_opl3 *opl3, int prog, int bank, - int create_patch) -{ - /* pretty dumb hash key */ - unsigned int key = (prog + bank) % OPL3_PATCH_HASH_SIZE; - struct fm_patch *patch; - - for (patch = opl3->patch_table[key]; patch; patch = patch->next) { - if (patch->prog == prog && patch->bank == bank) - return patch; - } - if (!create_patch) - return NULL; - - patch = kzalloc(sizeof(*patch), GFP_KERNEL); - if (!patch) - return NULL; - patch->prog = prog; - patch->bank = bank; - patch->next = opl3->patch_table[key]; - opl3->patch_table[key] = patch; - return patch; -} -EXPORT_SYMBOL(snd_opl3_find_patch); - -/* - * Clear all patches of the given OPL3 instance - */ -void snd_opl3_clear_patches(struct snd_opl3 *opl3) -{ - int i; - for (i = 0; i < OPL3_PATCH_HASH_SIZE; i++) { - struct fm_patch *patch, *next; - for (patch = opl3->patch_table[i]; patch; patch = next) { - next = patch->next; - kfree(patch); - } - } - memset(opl3->patch_table, 0, sizeof(opl3->patch_table)); -} -#endif /* OPL3_SUPPORT_SYNTH */ - -/* ------------------------------ */ - -void snd_opl3_reset(struct snd_opl3 * opl3) -{ - unsigned short opl3_reg; - - unsigned short reg_side; - unsigned char voice_offset; - - int max_voices, i; - - max_voices = (opl3->hardware < OPL3_HW_OPL3) ? - MAX_OPL2_VOICES : MAX_OPL3_VOICES; - - for (i = 0; i < max_voices; i++) { - /* Get register array side and offset of voice */ - if (i < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = i; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = i - MAX_OPL2_VOICES; - } - opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][0]); - opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 1 volume */ - opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][1]); - opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 2 volume */ - - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, 0x00); /* Note off */ - } - - opl3->max_voices = MAX_OPL2_VOICES; - opl3->fm_mode = SNDRV_DM_FM_MODE_OPL2; - - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT); - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); /* Melodic mode */ - opl3->rhythm = 0; -} - -EXPORT_SYMBOL(snd_opl3_reset); - -static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note) -{ - unsigned short reg_side; - unsigned char voice_offset; - - unsigned short opl3_reg; - unsigned char reg_val; - - /* Voices 0 - 8 in OPL2 mode */ - /* Voices 0 - 17 in OPL3 mode */ - if (note->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ? - MAX_OPL3_VOICES : MAX_OPL2_VOICES)) - return -EINVAL; - - /* Get register array side and offset of voice */ - if (note->voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = note->voice; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = note->voice - MAX_OPL2_VOICES; - } - - /* Set lower 8 bits of note frequency */ - reg_val = (unsigned char) note->fnum; - opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); - - reg_val = 0x00; - /* Set output sound flag */ - if (note->key_on) - reg_val |= OPL3_KEYON_BIT; - /* Set octave */ - reg_val |= (note->octave << 2) & OPL3_BLOCKNUM_MASK; - /* Set higher 2 bits of note frequency */ - reg_val |= (unsigned char) (note->fnum >> 8) & OPL3_FNUM_HIGH_MASK; - - /* Set OPL3 KEYON_BLOCK register of requested voice */ - opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); - - return 0; -} - - -static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice) -{ - unsigned short reg_side; - unsigned char op_offset; - unsigned char voice_offset; - - unsigned short opl3_reg; - unsigned char reg_val; - - /* Only operators 1 and 2 */ - if (voice->op > 1) - return -EINVAL; - /* Voices 0 - 8 in OPL2 mode */ - /* Voices 0 - 17 in OPL3 mode */ - if (voice->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ? - MAX_OPL3_VOICES : MAX_OPL2_VOICES)) - return -EINVAL; - - /* Get register array side and offset of voice */ - if (voice->voice < MAX_OPL2_VOICES) { - /* Left register block for voices 0 .. 8 */ - reg_side = OPL3_LEFT; - voice_offset = voice->voice; - } else { - /* Right register block for voices 9 .. 17 */ - reg_side = OPL3_RIGHT; - voice_offset = voice->voice - MAX_OPL2_VOICES; - } - /* Get register offset of operator */ - op_offset = snd_opl3_regmap[voice_offset][voice->op]; - - reg_val = 0x00; - /* Set amplitude modulation (tremolo) effect */ - if (voice->am) - reg_val |= OPL3_TREMOLO_ON; - /* Set vibrato effect */ - if (voice->vibrato) - reg_val |= OPL3_VIBRATO_ON; - /* Set sustaining sound phase */ - if (voice->do_sustain) - reg_val |= OPL3_SUSTAIN_ON; - /* Set keyboard scaling bit */ - if (voice->kbd_scale) - reg_val |= OPL3_KSR; - /* Set harmonic or frequency multiplier */ - reg_val |= voice->harmonic & OPL3_MULTIPLE_MASK; - - /* Set OPL3 AM_VIB register of requested voice/operator */ - opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set decreasing volume of higher notes */ - reg_val = (voice->scale_level << 6) & OPL3_KSL_MASK; - /* Set output volume */ - reg_val |= ~voice->volume & OPL3_TOTAL_LEVEL_MASK; - - /* Set OPL3 KSL_LEVEL register of requested voice/operator */ - opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set attack phase level */ - reg_val = (voice->attack << 4) & OPL3_ATTACK_MASK; - /* Set decay phase level */ - reg_val |= voice->decay & OPL3_DECAY_MASK; - - /* Set OPL3 ATTACK_DECAY register of requested voice/operator */ - opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set sustain phase level */ - reg_val = (voice->sustain << 4) & OPL3_SUSTAIN_MASK; - /* Set release phase level */ - reg_val |= voice->release & OPL3_RELEASE_MASK; - - /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ - opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Set inter-operator feedback */ - reg_val = (voice->feedback << 1) & OPL3_FEEDBACK_MASK; - /* Set inter-operator connection */ - if (voice->connection) - reg_val |= OPL3_CONNECTION_BIT; - /* OPL-3 only */ - if (opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) { - if (voice->left) - reg_val |= OPL3_VOICE_TO_LEFT; - if (voice->right) - reg_val |= OPL3_VOICE_TO_RIGHT; - } - /* Feedback/connection bits are applicable to voice */ - opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); - opl3->command(opl3, opl3_reg, reg_val); - - /* Select waveform */ - reg_val = voice->waveform & OPL3_WAVE_SELECT_MASK; - opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset); - opl3->command(opl3, opl3_reg, reg_val); - - return 0; -} - -static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params) -{ - unsigned char reg_val; - - reg_val = 0x00; - /* Set keyboard split method */ - if (params->kbd_split) - reg_val |= OPL3_KEYBOARD_SPLIT; - opl3->command(opl3, OPL3_LEFT | OPL3_REG_KBD_SPLIT, reg_val); - - reg_val = 0x00; - /* Set amplitude modulation (tremolo) depth */ - if (params->am_depth) - reg_val |= OPL3_TREMOLO_DEPTH; - /* Set vibrato depth */ - if (params->vib_depth) - reg_val |= OPL3_VIBRATO_DEPTH; - /* Set percussion mode */ - if (params->rhythm) { - reg_val |= OPL3_PERCUSSION_ENABLE; - opl3->rhythm = 1; - } else { - opl3->rhythm = 0; - } - /* Play percussion instruments */ - if (params->bass) - reg_val |= OPL3_BASSDRUM_ON; - if (params->snare) - reg_val |= OPL3_SNAREDRUM_ON; - if (params->tomtom) - reg_val |= OPL3_TOMTOM_ON; - if (params->cymbal) - reg_val |= OPL3_CYMBAL_ON; - if (params->hihat) - reg_val |= OPL3_HIHAT_ON; - - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, reg_val); - return 0; -} - -static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode) -{ - if ((mode == SNDRV_DM_FM_MODE_OPL3) && (opl3->hardware < OPL3_HW_OPL3)) - return -EINVAL; - - opl3->fm_mode = mode; - if (opl3->hardware >= OPL3_HW_OPL3) - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, 0x00); /* Clear 4-op connections */ - - return 0; -} - -static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection) -{ - unsigned char reg_val; - - /* OPL-3 only */ - if (opl3->fm_mode != SNDRV_DM_FM_MODE_OPL3) - return -EINVAL; - - reg_val = connection & (OPL3_RIGHT_4OP_0 | OPL3_RIGHT_4OP_1 | OPL3_RIGHT_4OP_2 | - OPL3_LEFT_4OP_0 | OPL3_LEFT_4OP_1 | OPL3_LEFT_4OP_2); - /* Set 4-op connections */ - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, reg_val); - - return 0; -} - diff --git a/ANDROID_3.4.5/sound/drivers/opl3/opl3_voice.h b/ANDROID_3.4.5/sound/drivers/opl3/opl3_voice.h deleted file mode 100644 index a371c075..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl3/opl3_voice.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __OPL3_VOICE_H -#define __OPL3_VOICE_H - -/* - * Copyright (c) 2000 Uros Bizjak - * - * 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 - -/* Prototypes for opl3_seq.c */ -int snd_opl3_synth_use_inc(struct snd_opl3 * opl3); -void snd_opl3_synth_use_dec(struct snd_opl3 * opl3); -int snd_opl3_synth_setup(struct snd_opl3 * opl3); -void snd_opl3_synth_cleanup(struct snd_opl3 * opl3); - -/* Prototypes for opl3_midi.c */ -void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan); -void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan); -void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, struct snd_midi_channel_set *chset); -void snd_opl3_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset); - -void snd_opl3_calc_volume(unsigned char *reg, int vel, struct snd_midi_channel *chan); -void snd_opl3_timer_func(unsigned long data); - -/* Prototypes for opl3_drums.c */ -void snd_opl3_load_drums(struct snd_opl3 *opl3); -void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int on_off, int vel, struct snd_midi_channel *chan); - -/* Prototypes for opl3_oss.c */ -#ifdef CONFIG_SND_SEQUENCER_OSS -void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name); -void snd_opl3_free_seq_oss(struct snd_opl3 *opl3); -#endif - -#endif diff --git a/ANDROID_3.4.5/sound/drivers/opl4/Makefile b/ANDROID_3.4.5/sound/drivers/opl4/Makefile deleted file mode 100644 index b94009b0..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o opl4_proc.o -snd-opl4-synth-objs := opl4_seq.o opl4_synth.o yrw801.o - -obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o -obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-opl4-synth.o diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_lib.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_lib.c deleted file mode 100644 index b953fb4a..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_lib.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Functions for accessing OPL4 devices - * Copyright (c) 2003 by Clemens Ladisch - * - * 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 "opl4_local.h" -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_DESCRIPTION("OPL4 driver"); -MODULE_LICENSE("GPL"); - -static void inline snd_opl4_wait(struct snd_opl4 *opl4) -{ - int timeout = 10; - while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0) - ; -} - -void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value) -{ - snd_opl4_wait(opl4); - outb(reg, opl4->pcm_port); - - snd_opl4_wait(opl4); - outb(value, opl4->pcm_port + 1); -} - -EXPORT_SYMBOL(snd_opl4_write); - -u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) -{ - snd_opl4_wait(opl4); - outb(reg, opl4->pcm_port); - - snd_opl4_wait(opl4); - return inb(opl4->pcm_port + 1); -} - -EXPORT_SYMBOL(snd_opl4_read); - -void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size) -{ - unsigned long flags; - u8 memcfg; - - spin_lock_irqsave(&opl4->reg_lock, flags); - - memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); - - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16); - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8); - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset); - - snd_opl4_wait(opl4); - outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port); - snd_opl4_wait(opl4); - insb(opl4->pcm_port + 1, buf, size); - - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); - - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -EXPORT_SYMBOL(snd_opl4_read_memory); - -void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) -{ - unsigned long flags; - u8 memcfg; - - spin_lock_irqsave(&opl4->reg_lock, flags); - - memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT); - - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16); - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8); - snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset); - - snd_opl4_wait(opl4); - outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port); - snd_opl4_wait(opl4); - outsb(opl4->pcm_port + 1, buf, size); - - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg); - - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -EXPORT_SYMBOL(snd_opl4_write_memory); - -static void snd_opl4_enable_opl4(struct snd_opl4 *opl4) -{ - outb(OPL3_REG_MODE, opl4->fm_port + 2); - inb(opl4->fm_port); - inb(opl4->fm_port); - outb(OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE, opl4->fm_port + 3); - inb(opl4->fm_port); - inb(opl4->fm_port); -} - -static int snd_opl4_detect(struct snd_opl4 *opl4) -{ - u8 id1, id2; - - snd_opl4_enable_opl4(opl4); - - id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION); - snd_printdd("OPL4[02]=%02x\n", id1); - switch (id1 & OPL4_DEVICE_ID_MASK) { - case 0x20: - opl4->hardware = OPL3_HW_OPL4; - break; - case 0x40: - opl4->hardware = OPL3_HW_OPL4_ML; - break; - default: - return -ENODEV; - } - - snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x00); - snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff); - id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM); - id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM); - snd_printdd("OPL4 id1=%02x id2=%02x\n", id1, id2); - if (id1 != 0x00 || id2 != 0xff) - return -ENODEV; - - snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x3f); - snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0x3f); - snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, 0x00); - return 0; -} - -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) -static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev) -{ - struct snd_opl4 *opl4 = seq_dev->private_data; - opl4->seq_dev = NULL; -} - -static int snd_opl4_create_seq_dev(struct snd_opl4 *opl4, int seq_device) -{ - opl4->seq_dev_num = seq_device; - if (snd_seq_device_new(opl4->card, seq_device, SNDRV_SEQ_DEV_ID_OPL4, - sizeof(struct snd_opl4 *), &opl4->seq_dev) >= 0) { - strcpy(opl4->seq_dev->name, "OPL4 Wavetable"); - *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4; - opl4->seq_dev->private_data = opl4; - opl4->seq_dev->private_free = snd_opl4_seq_dev_free; - } - return 0; -} -#endif - -static void snd_opl4_free(struct snd_opl4 *opl4) -{ -#ifdef CONFIG_PROC_FS - snd_opl4_free_proc(opl4); -#endif - release_and_free_resource(opl4->res_fm_port); - release_and_free_resource(opl4->res_pcm_port); - kfree(opl4); -} - -static int snd_opl4_dev_free(struct snd_device *device) -{ - struct snd_opl4 *opl4 = device->device_data; - snd_opl4_free(opl4); - return 0; -} - -int snd_opl4_create(struct snd_card *card, - unsigned long fm_port, unsigned long pcm_port, - int seq_device, - struct snd_opl3 **ropl3, struct snd_opl4 **ropl4) -{ - struct snd_opl4 *opl4; - struct snd_opl3 *opl3; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_opl4_dev_free - }; - - if (ropl3) - *ropl3 = NULL; - if (ropl4) - *ropl4 = NULL; - - opl4 = kzalloc(sizeof(*opl4), GFP_KERNEL); - if (!opl4) - return -ENOMEM; - - opl4->res_fm_port = request_region(fm_port, 8, "OPL4 FM"); - opl4->res_pcm_port = request_region(pcm_port, 8, "OPL4 PCM/MIX"); - if (!opl4->res_fm_port || !opl4->res_pcm_port) { - snd_printk(KERN_ERR "opl4: can't grab ports 0x%lx, 0x%lx\n", fm_port, pcm_port); - snd_opl4_free(opl4); - return -EBUSY; - } - - opl4->card = card; - opl4->fm_port = fm_port; - opl4->pcm_port = pcm_port; - spin_lock_init(&opl4->reg_lock); - mutex_init(&opl4->access_mutex); - - err = snd_opl4_detect(opl4); - if (err < 0) { - snd_opl4_free(opl4); - snd_printd("OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port); - return err; - } - - err = snd_device_new(card, SNDRV_DEV_CODEC, opl4, &ops); - if (err < 0) { - snd_opl4_free(opl4); - return err; - } - - err = snd_opl3_create(card, fm_port, fm_port + 2, opl4->hardware, 1, &opl3); - if (err < 0) { - snd_device_free(card, opl4); - return err; - } - - /* opl3 initialization disabled opl4, so reenable */ - snd_opl4_enable_opl4(opl4); - - snd_opl4_create_mixer(opl4); -#ifdef CONFIG_PROC_FS - snd_opl4_create_proc(opl4); -#endif - -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - opl4->seq_client = -1; - if (opl4->hardware < OPL3_HW_OPL4_ML) - snd_opl4_create_seq_dev(opl4, seq_device); -#endif - - if (ropl3) - *ropl3 = opl3; - if (ropl4) - *ropl4 = opl4; - return 0; -} - -EXPORT_SYMBOL(snd_opl4_create); - -static int __init alsa_opl4_init(void) -{ - return 0; -} - -static void __exit alsa_opl4_exit(void) -{ -} - -module_init(alsa_opl4_init) -module_exit(alsa_opl4_exit) diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_local.h b/ANDROID_3.4.5/sound/drivers/opl4/opl4_local.h deleted file mode 100644 index 470e5a75..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_local.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Local definitions for the OPL4 driver - * - * Copyright (c) 2003 by Clemens Ladisch - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified 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 SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef __OPL4_LOCAL_H -#define __OPL4_LOCAL_H - -#include - -/* - * Register numbers - */ - -#define OPL4_REG_TEST0 0x00 -#define OPL4_REG_TEST1 0x01 - -#define OPL4_REG_MEMORY_CONFIGURATION 0x02 -#define OPL4_MODE_BIT 0x01 -#define OPL4_MTYPE_BIT 0x02 -#define OPL4_TONE_HEADER_MASK 0x1c -#define OPL4_DEVICE_ID_MASK 0xe0 - -#define OPL4_REG_MEMORY_ADDRESS_HIGH 0x03 -#define OPL4_REG_MEMORY_ADDRESS_MID 0x04 -#define OPL4_REG_MEMORY_ADDRESS_LOW 0x05 -#define OPL4_REG_MEMORY_DATA 0x06 - -/* - * Offsets to the register banks for voices. To get the - * register number just add the voice number to the bank offset. - * - * Wave Table Number low bits (0x08 to 0x1F) - */ -#define OPL4_REG_TONE_NUMBER 0x08 - -/* Wave Table Number high bit, F-Number low bits (0x20 to 0x37) */ -#define OPL4_REG_F_NUMBER 0x20 -#define OPL4_TONE_NUMBER_BIT8 0x01 -#define OPL4_F_NUMBER_LOW_MASK 0xfe - -/* F-Number high bits, Octave, Pseudo-Reverb (0x38 to 0x4F) */ -#define OPL4_REG_OCTAVE 0x38 -#define OPL4_F_NUMBER_HIGH_MASK 0x07 -#define OPL4_BLOCK_MASK 0xf0 -#define OPL4_PSEUDO_REVERB_BIT 0x08 - -/* Total Level, Level Direct (0x50 to 0x67) */ -#define OPL4_REG_LEVEL 0x50 -#define OPL4_TOTAL_LEVEL_MASK 0xfe -#define OPL4_LEVEL_DIRECT_BIT 0x01 - -/* Key On, Damp, LFO RST, CH, Panpot (0x68 to 0x7F) */ -#define OPL4_REG_MISC 0x68 -#define OPL4_KEY_ON_BIT 0x80 -#define OPL4_DAMP_BIT 0x40 -#define OPL4_LFO_RESET_BIT 0x20 -#define OPL4_OUTPUT_CHANNEL_BIT 0x10 -#define OPL4_PAN_POT_MASK 0x0f - -/* LFO, VIB (0x80 to 0x97) */ -#define OPL4_REG_LFO_VIBRATO 0x80 -#define OPL4_LFO_FREQUENCY_MASK 0x38 -#define OPL4_VIBRATO_DEPTH_MASK 0x07 -#define OPL4_CHORUS_SEND_MASK 0xc0 /* ML only */ - -/* Attack / Decay 1 rate (0x98 to 0xAF) */ -#define OPL4_REG_ATTACK_DECAY1 0x98 -#define OPL4_ATTACK_RATE_MASK 0xf0 -#define OPL4_DECAY1_RATE_MASK 0x0f - -/* Decay level / 2 rate (0xB0 to 0xC7) */ -#define OPL4_REG_LEVEL_DECAY2 0xb0 -#define OPL4_DECAY_LEVEL_MASK 0xf0 -#define OPL4_DECAY2_RATE_MASK 0x0f - -/* Release rate / Rate correction (0xC8 to 0xDF) */ -#define OPL4_REG_RELEASE_CORRECTION 0xc8 -#define OPL4_RELEASE_RATE_MASK 0x0f -#define OPL4_RATE_INTERPOLATION_MASK 0xf0 - -/* AM (0xE0 to 0xF7) */ -#define OPL4_REG_TREMOLO 0xe0 -#define OPL4_TREMOLO_DEPTH_MASK 0x07 -#define OPL4_REVERB_SEND_MASK 0xe0 /* ML only */ - -/* Mixer */ -#define OPL4_REG_MIX_CONTROL_FM 0xf8 -#define OPL4_REG_MIX_CONTROL_PCM 0xf9 -#define OPL4_MIX_LEFT_MASK 0x07 -#define OPL4_MIX_RIGHT_MASK 0x38 - -#define OPL4_REG_ATC 0xfa -#define OPL4_ATC_BIT 0x01 /* ???, ML only */ - -/* bits in the OPL3 Status register */ -#define OPL4_STATUS_BUSY 0x01 -#define OPL4_STATUS_LOAD 0x02 - - -#define OPL4_MAX_VOICES 24 - -#define SNDRV_SEQ_DEV_ID_OPL4 "opl4-synth" - - -struct opl4_sound { - u16 tone; - s16 pitch_offset; - u8 key_scaling; - s8 panpot; - u8 vibrato; - u8 tone_attenuate; - u8 volume_factor; - u8 reg_lfo_vibrato; - u8 reg_attack_decay1; - u8 reg_level_decay2; - u8 reg_release_correction; - u8 reg_tremolo; -}; - -struct opl4_region { - u8 key_min, key_max; - struct opl4_sound sound; -}; - -struct opl4_region_ptr { - int count; - const struct opl4_region *regions; -}; - -struct opl4_voice { - struct list_head list; - int number; - struct snd_midi_channel *chan; - int note; - int velocity; - const struct opl4_sound *sound; - u8 level_direct; - u8 reg_f_number; - u8 reg_misc; - u8 reg_lfo_vibrato; -}; - -struct snd_opl4 { - unsigned long fm_port; - unsigned long pcm_port; - struct resource *res_fm_port; - struct resource *res_pcm_port; - unsigned short hardware; - spinlock_t reg_lock; - struct snd_card *card; - -#ifdef CONFIG_PROC_FS - struct snd_info_entry *proc_entry; - int memory_access; -#endif - struct mutex access_mutex; - -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) - int used; - - int seq_dev_num; - int seq_client; - struct snd_seq_device *seq_dev; - - struct snd_midi_channel_set *chset; - struct opl4_voice voices[OPL4_MAX_VOICES]; - struct list_head off_voices; - struct list_head on_voices; -#endif -}; - -/* opl4_lib.c */ -void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value); -u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg); -void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size); -void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size); - -/* opl4_mixer.c */ -int snd_opl4_create_mixer(struct snd_opl4 *opl4); - -#ifdef CONFIG_PROC_FS -/* opl4_proc.c */ -int snd_opl4_create_proc(struct snd_opl4 *opl4); -void snd_opl4_free_proc(struct snd_opl4 *opl4); -#endif - -/* opl4_seq.c */ -extern int volume_boost; - -/* opl4_synth.c */ -void snd_opl4_synth_reset(struct snd_opl4 *opl4); -void snd_opl4_synth_shutdown(struct snd_opl4 *opl4); -void snd_opl4_note_on(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl4_note_off(void *p, int note, int vel, struct snd_midi_channel *chan); -void snd_opl4_terminate_note(void *p, int note, struct snd_midi_channel *chan); -void snd_opl4_control(void *p, int type, struct snd_midi_channel *chan); -void snd_opl4_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset); - -/* yrw801.c */ -int snd_yrw801_detect(struct snd_opl4 *opl4); -extern const struct opl4_region_ptr snd_yrw801_regions[]; - -#endif /* __OPL4_LOCAL_H */ diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_mixer.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_mixer.c deleted file mode 100644 index 04079de4..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_mixer.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * OPL4 mixer functions - * Copyright (c) 2003 by Clemens Ladisch - * - * 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 "opl4_local.h" -#include - -static int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 7; - return 0; -} - -static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); - unsigned long flags; - u8 reg = kcontrol->private_value; - u8 value; - - spin_lock_irqsave(&opl4->reg_lock, flags); - value = snd_opl4_read(opl4, reg); - spin_unlock_irqrestore(&opl4->reg_lock, flags); - ucontrol->value.integer.value[0] = 7 - (value & 7); - ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7); - return 0; -} - -static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol); - unsigned long flags; - u8 reg = kcontrol->private_value; - u8 value, old_value; - - value = (7 - (ucontrol->value.integer.value[0] & 7)) | - ((7 - (ucontrol->value.integer.value[1] & 7)) << 3); - spin_lock_irqsave(&opl4->reg_lock, flags); - old_value = snd_opl4_read(opl4, reg); - snd_opl4_write(opl4, reg, value); - spin_unlock_irqrestore(&opl4->reg_lock, flags); - return value != old_value; -} - -static struct snd_kcontrol_new snd_opl4_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "FM Playback Volume", - .info = snd_opl4_ctl_info, - .get = snd_opl4_ctl_get, - .put = snd_opl4_ctl_put, - .private_value = OPL4_REG_MIX_CONTROL_FM - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Wavetable Playback Volume", - .info = snd_opl4_ctl_info, - .get = snd_opl4_ctl_get, - .put = snd_opl4_ctl_put, - .private_value = OPL4_REG_MIX_CONTROL_PCM - } -}; - -int snd_opl4_create_mixer(struct snd_opl4 *opl4) -{ - struct snd_card *card = opl4->card; - int i, err; - - strcat(card->mixername, ",OPL4"); - - for (i = 0; i < 2; ++i) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4)); - if (err < 0) - return err; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_proc.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_proc.c deleted file mode 100644 index 9b824bfc..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_proc.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Functions for the OPL4 proc file - * Copyright (c) 2003 by Clemens Ladisch - * - * 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 "opl4_local.h" -#include -#include -#include - -#ifdef CONFIG_PROC_FS - -static int snd_opl4_mem_proc_open(struct snd_info_entry *entry, - unsigned short mode, void **file_private_data) -{ - struct snd_opl4 *opl4 = entry->private_data; - - mutex_lock(&opl4->access_mutex); - if (opl4->memory_access) { - mutex_unlock(&opl4->access_mutex); - return -EBUSY; - } - opl4->memory_access++; - mutex_unlock(&opl4->access_mutex); - return 0; -} - -static int snd_opl4_mem_proc_release(struct snd_info_entry *entry, - unsigned short mode, void *file_private_data) -{ - struct snd_opl4 *opl4 = entry->private_data; - - mutex_lock(&opl4->access_mutex); - opl4->memory_access--; - mutex_unlock(&opl4->access_mutex); - return 0; -} - -static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *_buf, - size_t count, loff_t pos) -{ - struct snd_opl4 *opl4 = entry->private_data; - char* buf; - - buf = vmalloc(count); - if (!buf) - return -ENOMEM; - snd_opl4_read_memory(opl4, buf, pos, count); - if (copy_to_user(_buf, buf, count)) { - vfree(buf); - return -EFAULT; - } - vfree(buf); - return count; -} - -static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, - const char __user *_buf, - size_t count, loff_t pos) -{ - struct snd_opl4 *opl4 = entry->private_data; - char *buf; - - buf = vmalloc(count); - if (!buf) - return -ENOMEM; - if (copy_from_user(buf, _buf, count)) { - vfree(buf); - return -EFAULT; - } - snd_opl4_write_memory(opl4, buf, pos, count); - vfree(buf); - return count; -} - -static struct snd_info_entry_ops snd_opl4_mem_proc_ops = { - .open = snd_opl4_mem_proc_open, - .release = snd_opl4_mem_proc_release, - .read = snd_opl4_mem_proc_read, - .write = snd_opl4_mem_proc_write, -}; - -int snd_opl4_create_proc(struct snd_opl4 *opl4) -{ - struct snd_info_entry *entry; - - entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root); - if (entry) { - if (opl4->hardware < OPL3_HW_OPL4_ML) { - /* OPL4 can access 4 MB external ROM/SRAM */ - entry->mode |= S_IWUSR; - entry->size = 4 * 1024 * 1024; - } else { - /* OPL4-ML has 1 MB internal ROM */ - entry->size = 1 * 1024 * 1024; - } - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->c.ops = &snd_opl4_mem_proc_ops; - entry->module = THIS_MODULE; - entry->private_data = opl4; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - opl4->proc_entry = entry; - return 0; -} - -void snd_opl4_free_proc(struct snd_opl4 *opl4) -{ - snd_info_free_entry(opl4->proc_entry); -} - -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_seq.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_seq.c deleted file mode 100644 index 99197699..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_seq.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * OPL4 sequencer functions - * - * Copyright (c) 2003 by Clemens Ladisch - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified 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 SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "opl4_local.h" -#include -#include -#include -#include - -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_DESCRIPTION("OPL4 wavetable synth driver"); -MODULE_LICENSE("Dual BSD/GPL"); - -int volume_boost = 8; - -module_param(volume_boost, int, 0644); -MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds."); - -static int snd_opl4_seq_use_inc(struct snd_opl4 *opl4) -{ - if (!try_module_get(opl4->card->module)) - return -EFAULT; - return 0; -} - -static void snd_opl4_seq_use_dec(struct snd_opl4 *opl4) -{ - module_put(opl4->card->module); -} - -static int snd_opl4_seq_use(void *private_data, struct snd_seq_port_subscribe *info) -{ - struct snd_opl4 *opl4 = private_data; - int err; - - mutex_lock(&opl4->access_mutex); - - if (opl4->used) { - mutex_unlock(&opl4->access_mutex); - return -EBUSY; - } - opl4->used++; - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { - err = snd_opl4_seq_use_inc(opl4); - if (err < 0) { - mutex_unlock(&opl4->access_mutex); - return err; - } - } - - mutex_unlock(&opl4->access_mutex); - - snd_opl4_synth_reset(opl4); - return 0; -} - -static int snd_opl4_seq_unuse(void *private_data, struct snd_seq_port_subscribe *info) -{ - struct snd_opl4 *opl4 = private_data; - - snd_opl4_synth_shutdown(opl4); - - mutex_lock(&opl4->access_mutex); - opl4->used--; - mutex_unlock(&opl4->access_mutex); - - if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) - snd_opl4_seq_use_dec(opl4); - return 0; -} - -static struct snd_midi_op opl4_ops = { - .note_on = snd_opl4_note_on, - .note_off = snd_opl4_note_off, - .note_terminate = snd_opl4_terminate_note, - .control = snd_opl4_control, - .sysex = snd_opl4_sysex, -}; - -static int snd_opl4_seq_event_input(struct snd_seq_event *ev, int direct, - void *private_data, int atomic, int hop) -{ - struct snd_opl4 *opl4 = private_data; - - snd_midi_process_event(&opl4_ops, ev, opl4->chset); - return 0; -} - -static void snd_opl4_seq_free_port(void *private_data) -{ - struct snd_opl4 *opl4 = private_data; - - snd_midi_channel_free_set(opl4->chset); -} - -static int snd_opl4_seq_new_device(struct snd_seq_device *dev) -{ - struct snd_opl4 *opl4; - int client; - struct snd_seq_port_callback pcallbacks; - - opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (!opl4) - return -EINVAL; - - if (snd_yrw801_detect(opl4) < 0) - return -ENODEV; - - opl4->chset = snd_midi_channel_alloc_set(16); - if (!opl4->chset) - return -ENOMEM; - opl4->chset->private_data = opl4; - - /* allocate new client */ - client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num, - "OPL4 Wavetable"); - if (client < 0) { - snd_midi_channel_free_set(opl4->chset); - return client; - } - opl4->seq_client = client; - opl4->chset->client = client; - - /* create new port */ - memset(&pcallbacks, 0, sizeof(pcallbacks)); - pcallbacks.owner = THIS_MODULE; - pcallbacks.use = snd_opl4_seq_use; - pcallbacks.unuse = snd_opl4_seq_unuse; - pcallbacks.event_input = snd_opl4_seq_event_input; - pcallbacks.private_free = snd_opl4_seq_free_port; - pcallbacks.private_data = opl4; - - opl4->chset->port = snd_seq_event_port_attach(client, &pcallbacks, - SNDRV_SEQ_PORT_CAP_WRITE | - SNDRV_SEQ_PORT_CAP_SUBS_WRITE, - SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | - SNDRV_SEQ_PORT_TYPE_MIDI_GM | - SNDRV_SEQ_PORT_TYPE_HARDWARE | - SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, - 16, 24, - "OPL4 Wavetable Port"); - if (opl4->chset->port < 0) { - int err = opl4->chset->port; - snd_midi_channel_free_set(opl4->chset); - snd_seq_delete_kernel_client(client); - opl4->seq_client = -1; - return err; - } - return 0; -} - -static int snd_opl4_seq_delete_device(struct snd_seq_device *dev) -{ - struct snd_opl4 *opl4; - - opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (!opl4) - return -EINVAL; - - if (opl4->seq_client >= 0) { - snd_seq_delete_kernel_client(opl4->seq_client); - opl4->seq_client = -1; - } - return 0; -} - -static int __init alsa_opl4_synth_init(void) -{ - static struct snd_seq_dev_ops ops = { - snd_opl4_seq_new_device, - snd_opl4_seq_delete_device - }; - - return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL4, &ops, - sizeof(struct snd_opl4 *)); -} - -static void __exit alsa_opl4_synth_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL4); -} - -module_init(alsa_opl4_synth_init) -module_exit(alsa_opl4_synth_exit) diff --git a/ANDROID_3.4.5/sound/drivers/opl4/opl4_synth.c b/ANDROID_3.4.5/sound/drivers/opl4/opl4_synth.c deleted file mode 100644 index 49b9e240..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/opl4_synth.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * OPL4 MIDI synthesizer functions - * - * Copyright (c) 2003 by Clemens Ladisch - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified 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 SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "opl4_local.h" -#include -#include -#include - -/* GM2 controllers */ -#ifndef MIDI_CTL_RELEASE_TIME -#define MIDI_CTL_RELEASE_TIME 0x48 -#define MIDI_CTL_ATTACK_TIME 0x49 -#define MIDI_CTL_DECAY_TIME 0x4b -#define MIDI_CTL_VIBRATO_RATE 0x4c -#define MIDI_CTL_VIBRATO_DEPTH 0x4d -#define MIDI_CTL_VIBRATO_DELAY 0x4e -#endif - -/* - * This table maps 100/128 cents to F_NUMBER. - */ -static const s16 snd_opl4_pitch_map[0x600] = { - 0x000,0x000,0x001,0x001,0x002,0x002,0x003,0x003, - 0x004,0x004,0x005,0x005,0x006,0x006,0x006,0x007, - 0x007,0x008,0x008,0x009,0x009,0x00a,0x00a,0x00b, - 0x00b,0x00c,0x00c,0x00d,0x00d,0x00d,0x00e,0x00e, - 0x00f,0x00f,0x010,0x010,0x011,0x011,0x012,0x012, - 0x013,0x013,0x014,0x014,0x015,0x015,0x015,0x016, - 0x016,0x017,0x017,0x018,0x018,0x019,0x019,0x01a, - 0x01a,0x01b,0x01b,0x01c,0x01c,0x01d,0x01d,0x01e, - 0x01e,0x01e,0x01f,0x01f,0x020,0x020,0x021,0x021, - 0x022,0x022,0x023,0x023,0x024,0x024,0x025,0x025, - 0x026,0x026,0x027,0x027,0x028,0x028,0x029,0x029, - 0x029,0x02a,0x02a,0x02b,0x02b,0x02c,0x02c,0x02d, - 0x02d,0x02e,0x02e,0x02f,0x02f,0x030,0x030,0x031, - 0x031,0x032,0x032,0x033,0x033,0x034,0x034,0x035, - 0x035,0x036,0x036,0x037,0x037,0x038,0x038,0x038, - 0x039,0x039,0x03a,0x03a,0x03b,0x03b,0x03c,0x03c, - 0x03d,0x03d,0x03e,0x03e,0x03f,0x03f,0x040,0x040, - 0x041,0x041,0x042,0x042,0x043,0x043,0x044,0x044, - 0x045,0x045,0x046,0x046,0x047,0x047,0x048,0x048, - 0x049,0x049,0x04a,0x04a,0x04b,0x04b,0x04c,0x04c, - 0x04d,0x04d,0x04e,0x04e,0x04f,0x04f,0x050,0x050, - 0x051,0x051,0x052,0x052,0x053,0x053,0x054,0x054, - 0x055,0x055,0x056,0x056,0x057,0x057,0x058,0x058, - 0x059,0x059,0x05a,0x05a,0x05b,0x05b,0x05c,0x05c, - 0x05d,0x05d,0x05e,0x05e,0x05f,0x05f,0x060,0x060, - 0x061,0x061,0x062,0x062,0x063,0x063,0x064,0x064, - 0x065,0x065,0x066,0x066,0x067,0x067,0x068,0x068, - 0x069,0x069,0x06a,0x06a,0x06b,0x06b,0x06c,0x06c, - 0x06d,0x06d,0x06e,0x06e,0x06f,0x06f,0x070,0x071, - 0x071,0x072,0x072,0x073,0x073,0x074,0x074,0x075, - 0x075,0x076,0x076,0x077,0x077,0x078,0x078,0x079, - 0x079,0x07a,0x07a,0x07b,0x07b,0x07c,0x07c,0x07d, - 0x07d,0x07e,0x07e,0x07f,0x07f,0x080,0x081,0x081, - 0x082,0x082,0x083,0x083,0x084,0x084,0x085,0x085, - 0x086,0x086,0x087,0x087,0x088,0x088,0x089,0x089, - 0x08a,0x08a,0x08b,0x08b,0x08c,0x08d,0x08d,0x08e, - 0x08e,0x08f,0x08f,0x090,0x090,0x091,0x091,0x092, - 0x092,0x093,0x093,0x094,0x094,0x095,0x096,0x096, - 0x097,0x097,0x098,0x098,0x099,0x099,0x09a,0x09a, - 0x09b,0x09b,0x09c,0x09c,0x09d,0x09d,0x09e,0x09f, - 0x09f,0x0a0,0x0a0,0x0a1,0x0a1,0x0a2,0x0a2,0x0a3, - 0x0a3,0x0a4,0x0a4,0x0a5,0x0a6,0x0a6,0x0a7,0x0a7, - 0x0a8,0x0a8,0x0a9,0x0a9,0x0aa,0x0aa,0x0ab,0x0ab, - 0x0ac,0x0ad,0x0ad,0x0ae,0x0ae,0x0af,0x0af,0x0b0, - 0x0b0,0x0b1,0x0b1,0x0b2,0x0b2,0x0b3,0x0b4,0x0b4, - 0x0b5,0x0b5,0x0b6,0x0b6,0x0b7,0x0b7,0x0b8,0x0b8, - 0x0b9,0x0ba,0x0ba,0x0bb,0x0bb,0x0bc,0x0bc,0x0bd, - 0x0bd,0x0be,0x0be,0x0bf,0x0c0,0x0c0,0x0c1,0x0c1, - 0x0c2,0x0c2,0x0c3,0x0c3,0x0c4,0x0c4,0x0c5,0x0c6, - 0x0c6,0x0c7,0x0c7,0x0c8,0x0c8,0x0c9,0x0c9,0x0ca, - 0x0cb,0x0cb,0x0cc,0x0cc,0x0cd,0x0cd,0x0ce,0x0ce, - 0x0cf,0x0d0,0x0d0,0x0d1,0x0d1,0x0d2,0x0d2,0x0d3, - 0x0d3,0x0d4,0x0d5,0x0d5,0x0d6,0x0d6,0x0d7,0x0d7, - 0x0d8,0x0d8,0x0d9,0x0da,0x0da,0x0db,0x0db,0x0dc, - 0x0dc,0x0dd,0x0de,0x0de,0x0df,0x0df,0x0e0,0x0e0, - 0x0e1,0x0e1,0x0e2,0x0e3,0x0e3,0x0e4,0x0e4,0x0e5, - 0x0e5,0x0e6,0x0e7,0x0e7,0x0e8,0x0e8,0x0e9,0x0e9, - 0x0ea,0x0eb,0x0eb,0x0ec,0x0ec,0x0ed,0x0ed,0x0ee, - 0x0ef,0x0ef,0x0f0,0x0f0,0x0f1,0x0f1,0x0f2,0x0f3, - 0x0f3,0x0f4,0x0f4,0x0f5,0x0f5,0x0f6,0x0f7,0x0f7, - 0x0f8,0x0f8,0x0f9,0x0f9,0x0fa,0x0fb,0x0fb,0x0fc, - 0x0fc,0x0fd,0x0fd,0x0fe,0x0ff,0x0ff,0x100,0x100, - 0x101,0x101,0x102,0x103,0x103,0x104,0x104,0x105, - 0x106,0x106,0x107,0x107,0x108,0x108,0x109,0x10a, - 0x10a,0x10b,0x10b,0x10c,0x10c,0x10d,0x10e,0x10e, - 0x10f,0x10f,0x110,0x111,0x111,0x112,0x112,0x113, - 0x114,0x114,0x115,0x115,0x116,0x116,0x117,0x118, - 0x118,0x119,0x119,0x11a,0x11b,0x11b,0x11c,0x11c, - 0x11d,0x11e,0x11e,0x11f,0x11f,0x120,0x120,0x121, - 0x122,0x122,0x123,0x123,0x124,0x125,0x125,0x126, - 0x126,0x127,0x128,0x128,0x129,0x129,0x12a,0x12b, - 0x12b,0x12c,0x12c,0x12d,0x12e,0x12e,0x12f,0x12f, - 0x130,0x131,0x131,0x132,0x132,0x133,0x134,0x134, - 0x135,0x135,0x136,0x137,0x137,0x138,0x138,0x139, - 0x13a,0x13a,0x13b,0x13b,0x13c,0x13d,0x13d,0x13e, - 0x13e,0x13f,0x140,0x140,0x141,0x141,0x142,0x143, - 0x143,0x144,0x144,0x145,0x146,0x146,0x147,0x148, - 0x148,0x149,0x149,0x14a,0x14b,0x14b,0x14c,0x14c, - 0x14d,0x14e,0x14e,0x14f,0x14f,0x150,0x151,0x151, - 0x152,0x153,0x153,0x154,0x154,0x155,0x156,0x156, - 0x157,0x157,0x158,0x159,0x159,0x15a,0x15b,0x15b, - 0x15c,0x15c,0x15d,0x15e,0x15e,0x15f,0x160,0x160, - 0x161,0x161,0x162,0x163,0x163,0x164,0x165,0x165, - 0x166,0x166,0x167,0x168,0x168,0x169,0x16a,0x16a, - 0x16b,0x16b,0x16c,0x16d,0x16d,0x16e,0x16f,0x16f, - 0x170,0x170,0x171,0x172,0x172,0x173,0x174,0x174, - 0x175,0x175,0x176,0x177,0x177,0x178,0x179,0x179, - 0x17a,0x17a,0x17b,0x17c,0x17c,0x17d,0x17e,0x17e, - 0x17f,0x180,0x180,0x181,0x181,0x182,0x183,0x183, - 0x184,0x185,0x185,0x186,0x187,0x187,0x188,0x188, - 0x189,0x18a,0x18a,0x18b,0x18c,0x18c,0x18d,0x18e, - 0x18e,0x18f,0x190,0x190,0x191,0x191,0x192,0x193, - 0x193,0x194,0x195,0x195,0x196,0x197,0x197,0x198, - 0x199,0x199,0x19a,0x19a,0x19b,0x19c,0x19c,0x19d, - 0x19e,0x19e,0x19f,0x1a0,0x1a0,0x1a1,0x1a2,0x1a2, - 0x1a3,0x1a4,0x1a4,0x1a5,0x1a6,0x1a6,0x1a7,0x1a8, - 0x1a8,0x1a9,0x1a9,0x1aa,0x1ab,0x1ab,0x1ac,0x1ad, - 0x1ad,0x1ae,0x1af,0x1af,0x1b0,0x1b1,0x1b1,0x1b2, - 0x1b3,0x1b3,0x1b4,0x1b5,0x1b5,0x1b6,0x1b7,0x1b7, - 0x1b8,0x1b9,0x1b9,0x1ba,0x1bb,0x1bb,0x1bc,0x1bd, - 0x1bd,0x1be,0x1bf,0x1bf,0x1c0,0x1c1,0x1c1,0x1c2, - 0x1c3,0x1c3,0x1c4,0x1c5,0x1c5,0x1c6,0x1c7,0x1c7, - 0x1c8,0x1c9,0x1c9,0x1ca,0x1cb,0x1cb,0x1cc,0x1cd, - 0x1cd,0x1ce,0x1cf,0x1cf,0x1d0,0x1d1,0x1d1,0x1d2, - 0x1d3,0x1d3,0x1d4,0x1d5,0x1d5,0x1d6,0x1d7,0x1d7, - 0x1d8,0x1d9,0x1d9,0x1da,0x1db,0x1db,0x1dc,0x1dd, - 0x1dd,0x1de,0x1df,0x1df,0x1e0,0x1e1,0x1e1,0x1e2, - 0x1e3,0x1e4,0x1e4,0x1e5,0x1e6,0x1e6,0x1e7,0x1e8, - 0x1e8,0x1e9,0x1ea,0x1ea,0x1eb,0x1ec,0x1ec,0x1ed, - 0x1ee,0x1ee,0x1ef,0x1f0,0x1f0,0x1f1,0x1f2,0x1f3, - 0x1f3,0x1f4,0x1f5,0x1f5,0x1f6,0x1f7,0x1f7,0x1f8, - 0x1f9,0x1f9,0x1fa,0x1fb,0x1fb,0x1fc,0x1fd,0x1fe, - 0x1fe,0x1ff,0x200,0x200,0x201,0x202,0x202,0x203, - 0x204,0x205,0x205,0x206,0x207,0x207,0x208,0x209, - 0x209,0x20a,0x20b,0x20b,0x20c,0x20d,0x20e,0x20e, - 0x20f,0x210,0x210,0x211,0x212,0x212,0x213,0x214, - 0x215,0x215,0x216,0x217,0x217,0x218,0x219,0x21a, - 0x21a,0x21b,0x21c,0x21c,0x21d,0x21e,0x21e,0x21f, - 0x220,0x221,0x221,0x222,0x223,0x223,0x224,0x225, - 0x226,0x226,0x227,0x228,0x228,0x229,0x22a,0x22b, - 0x22b,0x22c,0x22d,0x22d,0x22e,0x22f,0x230,0x230, - 0x231,0x232,0x232,0x233,0x234,0x235,0x235,0x236, - 0x237,0x237,0x238,0x239,0x23a,0x23a,0x23b,0x23c, - 0x23c,0x23d,0x23e,0x23f,0x23f,0x240,0x241,0x241, - 0x242,0x243,0x244,0x244,0x245,0x246,0x247,0x247, - 0x248,0x249,0x249,0x24a,0x24b,0x24c,0x24c,0x24d, - 0x24e,0x24f,0x24f,0x250,0x251,0x251,0x252,0x253, - 0x254,0x254,0x255,0x256,0x257,0x257,0x258,0x259, - 0x259,0x25a,0x25b,0x25c,0x25c,0x25d,0x25e,0x25f, - 0x25f,0x260,0x261,0x262,0x262,0x263,0x264,0x265, - 0x265,0x266,0x267,0x267,0x268,0x269,0x26a,0x26a, - 0x26b,0x26c,0x26d,0x26d,0x26e,0x26f,0x270,0x270, - 0x271,0x272,0x273,0x273,0x274,0x275,0x276,0x276, - 0x277,0x278,0x279,0x279,0x27a,0x27b,0x27c,0x27c, - 0x27d,0x27e,0x27f,0x27f,0x280,0x281,0x282,0x282, - 0x283,0x284,0x285,0x285,0x286,0x287,0x288,0x288, - 0x289,0x28a,0x28b,0x28b,0x28c,0x28d,0x28e,0x28e, - 0x28f,0x290,0x291,0x291,0x292,0x293,0x294,0x294, - 0x295,0x296,0x297,0x298,0x298,0x299,0x29a,0x29b, - 0x29b,0x29c,0x29d,0x29e,0x29e,0x29f,0x2a0,0x2a1, - 0x2a1,0x2a2,0x2a3,0x2a4,0x2a5,0x2a5,0x2a6,0x2a7, - 0x2a8,0x2a8,0x2a9,0x2aa,0x2ab,0x2ab,0x2ac,0x2ad, - 0x2ae,0x2af,0x2af,0x2b0,0x2b1,0x2b2,0x2b2,0x2b3, - 0x2b4,0x2b5,0x2b5,0x2b6,0x2b7,0x2b8,0x2b9,0x2b9, - 0x2ba,0x2bb,0x2bc,0x2bc,0x2bd,0x2be,0x2bf,0x2c0, - 0x2c0,0x2c1,0x2c2,0x2c3,0x2c4,0x2c4,0x2c5,0x2c6, - 0x2c7,0x2c7,0x2c8,0x2c9,0x2ca,0x2cb,0x2cb,0x2cc, - 0x2cd,0x2ce,0x2ce,0x2cf,0x2d0,0x2d1,0x2d2,0x2d2, - 0x2d3,0x2d4,0x2d5,0x2d6,0x2d6,0x2d7,0x2d8,0x2d9, - 0x2da,0x2da,0x2db,0x2dc,0x2dd,0x2dd,0x2de,0x2df, - 0x2e0,0x2e1,0x2e1,0x2e2,0x2e3,0x2e4,0x2e5,0x2e5, - 0x2e6,0x2e7,0x2e8,0x2e9,0x2e9,0x2ea,0x2eb,0x2ec, - 0x2ed,0x2ed,0x2ee,0x2ef,0x2f0,0x2f1,0x2f1,0x2f2, - 0x2f3,0x2f4,0x2f5,0x2f5,0x2f6,0x2f7,0x2f8,0x2f9, - 0x2f9,0x2fa,0x2fb,0x2fc,0x2fd,0x2fd,0x2fe,0x2ff, - 0x300,0x301,0x302,0x302,0x303,0x304,0x305,0x306, - 0x306,0x307,0x308,0x309,0x30a,0x30a,0x30b,0x30c, - 0x30d,0x30e,0x30f,0x30f,0x310,0x311,0x312,0x313, - 0x313,0x314,0x315,0x316,0x317,0x318,0x318,0x319, - 0x31a,0x31b,0x31c,0x31c,0x31d,0x31e,0x31f,0x320, - 0x321,0x321,0x322,0x323,0x324,0x325,0x326,0x326, - 0x327,0x328,0x329,0x32a,0x32a,0x32b,0x32c,0x32d, - 0x32e,0x32f,0x32f,0x330,0x331,0x332,0x333,0x334, - 0x334,0x335,0x336,0x337,0x338,0x339,0x339,0x33a, - 0x33b,0x33c,0x33d,0x33e,0x33e,0x33f,0x340,0x341, - 0x342,0x343,0x343,0x344,0x345,0x346,0x347,0x348, - 0x349,0x349,0x34a,0x34b,0x34c,0x34d,0x34e,0x34e, - 0x34f,0x350,0x351,0x352,0x353,0x353,0x354,0x355, - 0x356,0x357,0x358,0x359,0x359,0x35a,0x35b,0x35c, - 0x35d,0x35e,0x35f,0x35f,0x360,0x361,0x362,0x363, - 0x364,0x364,0x365,0x366,0x367,0x368,0x369,0x36a, - 0x36a,0x36b,0x36c,0x36d,0x36e,0x36f,0x370,0x370, - 0x371,0x372,0x373,0x374,0x375,0x376,0x377,0x377, - 0x378,0x379,0x37a,0x37b,0x37c,0x37d,0x37d,0x37e, - 0x37f,0x380,0x381,0x382,0x383,0x383,0x384,0x385, - 0x386,0x387,0x388,0x389,0x38a,0x38a,0x38b,0x38c, - 0x38d,0x38e,0x38f,0x390,0x391,0x391,0x392,0x393, - 0x394,0x395,0x396,0x397,0x398,0x398,0x399,0x39a, - 0x39b,0x39c,0x39d,0x39e,0x39f,0x39f,0x3a0,0x3a1, - 0x3a2,0x3a3,0x3a4,0x3a5,0x3a6,0x3a7,0x3a7,0x3a8, - 0x3a9,0x3aa,0x3ab,0x3ac,0x3ad,0x3ae,0x3ae,0x3af, - 0x3b0,0x3b1,0x3b2,0x3b3,0x3b4,0x3b5,0x3b6,0x3b6, - 0x3b7,0x3b8,0x3b9,0x3ba,0x3bb,0x3bc,0x3bd,0x3be, - 0x3bf,0x3bf,0x3c0,0x3c1,0x3c2,0x3c3,0x3c4,0x3c5, - 0x3c6,0x3c7,0x3c7,0x3c8,0x3c9,0x3ca,0x3cb,0x3cc, - 0x3cd,0x3ce,0x3cf,0x3d0,0x3d1,0x3d1,0x3d2,0x3d3, - 0x3d4,0x3d5,0x3d6,0x3d7,0x3d8,0x3d9,0x3da,0x3da, - 0x3db,0x3dc,0x3dd,0x3de,0x3df,0x3e0,0x3e1,0x3e2, - 0x3e3,0x3e4,0x3e4,0x3e5,0x3e6,0x3e7,0x3e8,0x3e9, - 0x3ea,0x3eb,0x3ec,0x3ed,0x3ee,0x3ef,0x3ef,0x3f0, - 0x3f1,0x3f2,0x3f3,0x3f4,0x3f5,0x3f6,0x3f7,0x3f8, - 0x3f9,0x3fa,0x3fa,0x3fb,0x3fc,0x3fd,0x3fe,0x3ff -}; - -/* - * Attenuation according to GM recommendations, in -0.375 dB units. - * table[v] = 40 * log(v / 127) / -0.375 - */ -static unsigned char snd_opl4_volume_table[128] = { - 255,224,192,173,160,150,141,134, - 128,122,117,113,109,105,102, 99, - 96, 93, 90, 88, 85, 83, 81, 79, - 77, 75, 73, 71, 70, 68, 67, 65, - 64, 62, 61, 59, 58, 57, 56, 54, - 53, 52, 51, 50, 49, 48, 47, 46, - 45, 44, 43, 42, 41, 40, 39, 39, - 38, 37, 36, 35, 34, 34, 33, 32, - 31, 31, 30, 29, 29, 28, 27, 27, - 26, 25, 25, 24, 24, 23, 22, 22, - 21, 21, 20, 19, 19, 18, 18, 17, - 17, 16, 16, 15, 15, 14, 14, 13, - 13, 12, 12, 11, 11, 10, 10, 9, - 9, 9, 8, 8, 7, 7, 6, 6, - 6, 5, 5, 4, 4, 4, 3, 3, - 2, 2, 2, 1, 1, 0, 0, 0 -}; - -/* - * Initializes all voices. - */ -void snd_opl4_synth_reset(struct snd_opl4 *opl4) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) - snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT); - spin_unlock_irqrestore(&opl4->reg_lock, flags); - - INIT_LIST_HEAD(&opl4->off_voices); - INIT_LIST_HEAD(&opl4->on_voices); - memset(opl4->voices, 0, sizeof(opl4->voices)); - for (i = 0; i < OPL4_MAX_VOICES; i++) { - opl4->voices[i].number = i; - list_add_tail(&opl4->voices[i].list, &opl4->off_voices); - } - - snd_midi_channel_set_clear(opl4->chset); -} - -/* - * Shuts down all voices. - */ -void snd_opl4_synth_shutdown(struct snd_opl4 *opl4) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) - snd_opl4_write(opl4, OPL4_REG_MISC + i, - opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT); - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -/* - * Executes the callback for all voices playing the specified note. - */ -static void snd_opl4_do_for_note(struct snd_opl4 *opl4, int note, struct snd_midi_channel *chan, - void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) -{ - int i; - unsigned long flags; - struct opl4_voice *voice; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) { - voice = &opl4->voices[i]; - if (voice->chan == chan && voice->note == note) { - func(opl4, voice); - } - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -/* - * Executes the callback for all voices of to the specified channel. - */ -static void snd_opl4_do_for_channel(struct snd_opl4 *opl4, - struct snd_midi_channel *chan, - void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) -{ - int i; - unsigned long flags; - struct opl4_voice *voice; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) { - voice = &opl4->voices[i]; - if (voice->chan == chan) { - func(opl4, voice); - } - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -/* - * Executes the callback for all active voices. - */ -static void snd_opl4_do_for_all(struct snd_opl4 *opl4, - void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice)) -{ - int i; - unsigned long flags; - struct opl4_voice *voice; - - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < OPL4_MAX_VOICES; i++) { - voice = &opl4->voices[i]; - if (voice->chan) - func(opl4, voice); - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -static void snd_opl4_update_volume(struct snd_opl4 *opl4, struct opl4_voice *voice) -{ - int att; - - att = voice->sound->tone_attenuate; - att += snd_opl4_volume_table[opl4->chset->gs_master_volume & 0x7f]; - att += snd_opl4_volume_table[voice->chan->gm_volume & 0x7f]; - att += snd_opl4_volume_table[voice->chan->gm_expression & 0x7f]; - att += snd_opl4_volume_table[voice->velocity]; - att = 0x7f - (0x7f - att) * (voice->sound->volume_factor) / 0xfe - volume_boost; - if (att < 0) - att = 0; - else if (att > 0x7e) - att = 0x7e; - snd_opl4_write(opl4, OPL4_REG_LEVEL + voice->number, - (att << 1) | voice->level_direct); - voice->level_direct = 0; -} - -static void snd_opl4_update_pan(struct snd_opl4 *opl4, struct opl4_voice *voice) -{ - int pan = voice->sound->panpot; - - if (!voice->chan->drum_channel) - pan += (voice->chan->control[MIDI_CTL_MSB_PAN] - 0x40) >> 3; - if (pan < -7) - pan = -7; - else if (pan > 7) - pan = 7; - voice->reg_misc = (voice->reg_misc & ~OPL4_PAN_POT_MASK) - | (pan & OPL4_PAN_POT_MASK); - snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); -} - -static void snd_opl4_update_vibrato_depth(struct snd_opl4 *opl4, - struct opl4_voice *voice) -{ - int depth; - - if (voice->chan->drum_channel) - return; - depth = (7 - voice->sound->vibrato) - * (voice->chan->control[MIDI_CTL_VIBRATO_DEPTH] & 0x7f); - depth = (depth >> 7) + voice->sound->vibrato; - voice->reg_lfo_vibrato &= ~OPL4_VIBRATO_DEPTH_MASK; - voice->reg_lfo_vibrato |= depth & OPL4_VIBRATO_DEPTH_MASK; - snd_opl4_write(opl4, OPL4_REG_LFO_VIBRATO + voice->number, - voice->reg_lfo_vibrato); -} - -static void snd_opl4_update_pitch(struct snd_opl4 *opl4, - struct opl4_voice *voice) -{ - struct snd_midi_channel *chan = voice->chan; - int note, pitch, octave; - - note = chan->drum_channel ? 60 : voice->note; - /* - * pitch is in 100/128 cents, so 0x80 is one semitone and - * 0x600 is one octave. - */ - pitch = ((note - 60) << 7) * voice->sound->key_scaling / 100 + (60 << 7); - pitch += voice->sound->pitch_offset; - if (!chan->drum_channel) - pitch += chan->gm_rpn_coarse_tuning; - pitch += chan->gm_rpn_fine_tuning >> 7; - pitch += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 0x2000; - if (pitch < 0) - pitch = 0; - else if (pitch >= 0x6000) - pitch = 0x5fff; - octave = pitch / 0x600 - 8; - pitch = snd_opl4_pitch_map[pitch % 0x600]; - - snd_opl4_write(opl4, OPL4_REG_OCTAVE + voice->number, - (octave << 4) | ((pitch >> 7) & OPL4_F_NUMBER_HIGH_MASK)); - voice->reg_f_number = (voice->reg_f_number & OPL4_TONE_NUMBER_BIT8) - | ((pitch << 1) & OPL4_F_NUMBER_LOW_MASK); - snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice->number, voice->reg_f_number); -} - -static void snd_opl4_update_tone_parameters(struct snd_opl4 *opl4, - struct opl4_voice *voice) -{ - snd_opl4_write(opl4, OPL4_REG_ATTACK_DECAY1 + voice->number, - voice->sound->reg_attack_decay1); - snd_opl4_write(opl4, OPL4_REG_LEVEL_DECAY2 + voice->number, - voice->sound->reg_level_decay2); - snd_opl4_write(opl4, OPL4_REG_RELEASE_CORRECTION + voice->number, - voice->sound->reg_release_correction); - snd_opl4_write(opl4, OPL4_REG_TREMOLO + voice->number, - voice->sound->reg_tremolo); -} - -/* allocate one voice */ -static struct opl4_voice *snd_opl4_get_voice(struct snd_opl4 *opl4) -{ - /* first, try to get the oldest key-off voice */ - if (!list_empty(&opl4->off_voices)) - return list_entry(opl4->off_voices.next, struct opl4_voice, list); - /* then get the oldest key-on voice */ - snd_BUG_ON(list_empty(&opl4->on_voices)); - return list_entry(opl4->on_voices.next, struct opl4_voice, list); -} - -static void snd_opl4_wait_for_wave_headers(struct snd_opl4 *opl4) -{ - int timeout = 200; - - while ((inb(opl4->fm_port) & OPL4_STATUS_LOAD) && --timeout > 0) - udelay(10); -} - -void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_opl4 *opl4 = private_data; - const struct opl4_region_ptr *regions; - struct opl4_voice *voice[2]; - const struct opl4_sound *sound[2]; - int voices = 0, i; - unsigned long flags; - - /* determine the number of voices and voice parameters */ - i = chan->drum_channel ? 0x80 : (chan->midi_program & 0x7f); - regions = &snd_yrw801_regions[i]; - for (i = 0; i < regions->count; i++) { - if (note >= regions->regions[i].key_min && - note <= regions->regions[i].key_max) { - sound[voices] = ®ions->regions[i].sound; - if (++voices >= 2) - break; - } - } - - /* allocate and initialize the needed voices */ - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < voices; i++) { - voice[i] = snd_opl4_get_voice(opl4); - list_del(&voice[i]->list); - list_add_tail(&voice[i]->list, &opl4->on_voices); - voice[i]->chan = chan; - voice[i]->note = note; - voice[i]->velocity = vel & 0x7f; - voice[i]->sound = sound[i]; - } - - /* set tone number (triggers header loading) */ - for (i = 0; i < voices; i++) { - voice[i]->reg_f_number = - (sound[i]->tone >> 8) & OPL4_TONE_NUMBER_BIT8; - snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice[i]->number, - voice[i]->reg_f_number); - snd_opl4_write(opl4, OPL4_REG_TONE_NUMBER + voice[i]->number, - sound[i]->tone & 0xff); - } - - /* set parameters which can be set while loading */ - for (i = 0; i < voices; i++) { - voice[i]->reg_misc = OPL4_LFO_RESET_BIT; - snd_opl4_update_pan(opl4, voice[i]); - snd_opl4_update_pitch(opl4, voice[i]); - voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT; - snd_opl4_update_volume(opl4, voice[i]); - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); - - /* wait for completion of loading */ - snd_opl4_wait_for_wave_headers(opl4); - - /* set remaining parameters */ - spin_lock_irqsave(&opl4->reg_lock, flags); - for (i = 0; i < voices; i++) { - snd_opl4_update_tone_parameters(opl4, voice[i]); - voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato; - snd_opl4_update_vibrato_depth(opl4, voice[i]); - } - - /* finally, switch on all voices */ - for (i = 0; i < voices; i++) { - voice[i]->reg_misc = - (voice[i]->reg_misc & 0x1f) | OPL4_KEY_ON_BIT; - snd_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number, - voice[i]->reg_misc); - } - spin_unlock_irqrestore(&opl4->reg_lock, flags); -} - -static void snd_opl4_voice_off(struct snd_opl4 *opl4, struct opl4_voice *voice) -{ - list_del(&voice->list); - list_add_tail(&voice->list, &opl4->off_voices); - - voice->reg_misc &= ~OPL4_KEY_ON_BIT; - snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); -} - -void snd_opl4_note_off(void *private_data, int note, int vel, struct snd_midi_channel *chan) -{ - struct snd_opl4 *opl4 = private_data; - - snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off); -} - -static void snd_opl4_terminate_voice(struct snd_opl4 *opl4, struct opl4_voice *voice) -{ - list_del(&voice->list); - list_add_tail(&voice->list, &opl4->off_voices); - - voice->reg_misc = (voice->reg_misc & ~OPL4_KEY_ON_BIT) | OPL4_DAMP_BIT; - snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); -} - -void snd_opl4_terminate_note(void *private_data, int note, struct snd_midi_channel *chan) -{ - struct snd_opl4 *opl4 = private_data; - - snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice); -} - -void snd_opl4_control(void *private_data, int type, struct snd_midi_channel *chan) -{ - struct snd_opl4 *opl4 = private_data; - - switch (type) { - case MIDI_CTL_MSB_MODWHEEL: - chan->control[MIDI_CTL_VIBRATO_DEPTH] = chan->control[MIDI_CTL_MSB_MODWHEEL]; - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth); - break; - case MIDI_CTL_MSB_MAIN_VOLUME: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume); - break; - case MIDI_CTL_MSB_PAN: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pan); - break; - case MIDI_CTL_MSB_EXPRESSION: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume); - break; - case MIDI_CTL_VIBRATO_RATE: - /* not yet supported */ - break; - case MIDI_CTL_VIBRATO_DEPTH: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth); - break; - case MIDI_CTL_VIBRATO_DELAY: - /* not yet supported */ - break; - case MIDI_CTL_E1_REVERB_DEPTH: - /* - * Each OPL4 voice has a bit called "Pseudo-Reverb", but - * IMHO _not_ using it enhances the listening experience. - */ - break; - case MIDI_CTL_PITCHBEND: - snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pitch); - break; - } -} - -void snd_opl4_sysex(void *private_data, unsigned char *buf, int len, - int parsed, struct snd_midi_channel_set *chset) -{ - struct snd_opl4 *opl4 = private_data; - - if (parsed == SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME) - snd_opl4_do_for_all(opl4, snd_opl4_update_volume); -} diff --git a/ANDROID_3.4.5/sound/drivers/opl4/yrw801.c b/ANDROID_3.4.5/sound/drivers/opl4/yrw801.c deleted file mode 100644 index 6c335492..00000000 --- a/ANDROID_3.4.5/sound/drivers/opl4/yrw801.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Information about the Yamaha YRW801 wavetable ROM chip - * - * Copyright (c) 2003 by Clemens Ladisch - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed and/or modified 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 SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "opl4_local.h" - -int snd_yrw801_detect(struct snd_opl4 *opl4) -{ - char buf[15]; - - snd_opl4_read_memory(opl4, buf, 0x001200, 15); - if (memcmp(buf, "CopyrightYAMAHA", 15)) - return -ENODEV; - snd_opl4_read_memory(opl4, buf, 0x1ffffe, 2); - if (buf[0] != 0x01) - return -ENODEV; - snd_printdd("YRW801 ROM version %02x.%02x\n", buf[0], buf[1]); - return 0; -} - -/* - * The instrument definitions are stored statically because, in practice, the - * OPL4 is always coupled with a YRW801. Dynamic instrument loading would be - * required if downloading sample data to external SRAM was actually supported - * by this driver. - */ - -static const struct opl4_region regions_00[] = { /* Acoustic Grand Piano */ - {0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}}, - {0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12f,5290,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x130,4260,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x131,3625,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x132,3116,100, 0,0,0x04,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x133,2081,100, 0,0,0x03,0xc8,0x20,0xf2,0x14,0x18,0x0}}, - {0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xc8,0x20,0xf3,0x14,0x18,0x0}}, - {0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}} -}; -static const struct opl4_region regions_01[] = { /* Bright Acoustic Piano */ - {0x14, 0x2d, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}}, - {0x2e, 0x33, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x12f,5290,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x130,4260,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x131,3625,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x132,3116,100, 0,0,0x04,0xc8,0x20,0xf2,0x14,0x08,0x0}}, - {0x53, 0x58, {0x133,2081,100, 0,0,0x07,0xc8,0x20,0xf2,0x14,0x18,0x0}}, - {0x59, 0x5e, {0x134,1444,100, 0,0,0x0a,0xc8,0x20,0xf3,0x14,0x18,0x0}}, - {0x5f, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}} -}; -static const struct opl4_region regions_02[] = { /* Electric Grand Piano */ - {0x14, 0x2d, {0x12c,7476,100, 1,0,0x00,0xae,0x20,0xf2,0x13,0x07,0x0}}, - {0x2e, 0x33, {0x12d,6818,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x34, 0x39, {0x12e,5901,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x3a, 0x3f, {0x12f,5292,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x40, 0x45, {0x130,4262,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x46, 0x4b, {0x131,3627,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x4c, 0x52, {0x132,3118,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}}, - {0x53, 0x58, {0x133,2083,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x17,0x0}}, - {0x59, 0x5e, {0x134,1446,100, 1,0,0x00,0xae,0x20,0xf3,0x14,0x17,0x0}}, - {0x5f, 0x6d, {0x135,1917,100, 1,0,0x00,0xae,0x20,0xf4,0x15,0x07,0x0}}, - {0x00, 0x7f, {0x06c,6375,100,-1,0,0x00,0xc2,0x28,0xf4,0x23,0x18,0x0}} -}; -static const struct opl4_region regions_03[] = { /* Honky-Tonk Piano */ - {0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}}, - {0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12f,5290,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x130,4260,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x131,3625,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x132,3116,100, 0,0,0x04,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x133,2081,100, 0,0,0x03,0xb4,0x20,0xf2,0x14,0x18,0x0}}, - {0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xb4,0x20,0xf3,0x14,0x18,0x0}}, - {0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}}, - {0x14, 0x27, {0x12c,7486,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}}, - {0x28, 0x2d, {0x12d,6803,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x2e, 0x33, {0x12e,5912,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12f,5275,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x130,4274,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x131,3611,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x132,3129,100, 0,0,0x04,0xb4,0x20,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x133,2074,100, 0,0,0x07,0xb4,0x20,0xf2,0x14,0x18,0x0}}, - {0x53, 0x58, {0x134,1457,100, 0,0,0x01,0xb4,0x20,0xf3,0x14,0x18,0x0}}, - {0x59, 0x6d, {0x135,1903,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}} -}; -static const struct opl4_region regions_04[] = { /* Electric Piano 1 */ - {0x15, 0x6c, {0x00b,6570,100, 0,0,0x00,0x28,0x38,0xf0,0x00,0x0c,0x0}}, - {0x00, 0x7f, {0x06c,6375,100, 0,2,0x00,0xb0,0x22,0xf4,0x23,0x19,0x0}} -}; -static const struct opl4_region regions_05[] = { /* Electric Piano 2 */ - {0x14, 0x27, {0x12c,7476,100, 0,3,0x00,0xa2,0x1b,0xf2,0x13,0x08,0x0}}, - {0x28, 0x2d, {0x12d,6818,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x2e, 0x33, {0x12e,5901,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12f,5292,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x130,4262,100, 0,3,0x0a,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x131,3627,100, 0,3,0x0a,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x132,3118,100, 0,3,0x04,0xa2,0x1b,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x133,2083,100, 0,3,0x03,0xa2,0x1b,0xf2,0x14,0x18,0x0}}, - {0x53, 0x58, {0x134,1446,100, 0,3,0x07,0xa2,0x1b,0xf3,0x14,0x18,0x0}}, - {0x59, 0x6d, {0x135,1917,100, 0,3,0x00,0xa2,0x1b,0xf4,0x15,0x08,0x0}}, - {0x14, 0x2d, {0x12c,7472,100, 0,0,0x00,0xa2,0x18,0xf2,0x13,0x08,0x0}}, - {0x2e, 0x33, {0x12d,6814,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x34, 0x39, {0x12e,5897,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x3a, 0x3f, {0x12f,5288,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x40, 0x45, {0x130,4258,100, 0,0,0x0a,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x46, 0x4b, {0x131,3623,100, 0,0,0x0a,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x4c, 0x52, {0x132,3114,100, 0,0,0x04,0xa2,0x18,0xf2,0x14,0x08,0x0}}, - {0x53, 0x58, {0x133,2079,100, 0,0,0x07,0xa2,0x18,0xf2,0x14,0x18,0x0}}, - {0x59, 0x5e, {0x134,1442,100, 0,0,0x0a,0xa2,0x18,0xf3,0x14,0x18,0x0}}, - {0x5f, 0x6d, {0x135,1913,100, 0,0,0x00,0xa2,0x18,0xf4,0x15,0x08,0x0}} -}; -static const struct opl4_region regions_06[] = { /* Harpsichord */ - {0x15, 0x39, {0x080,5158,100, 0,0,0x00,0xb2,0x20,0xf5,0x24,0x19,0x0}}, - {0x3a, 0x3f, {0x081,4408,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}}, - {0x40, 0x45, {0x082,3622,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}}, - {0x46, 0x4d, {0x083,2843,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x19,0x0}}, - {0x4e, 0x6c, {0x084,1307,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x29,0x0}} -}; -static const struct opl4_region regions_07[] = { /* Clavinet */ - {0x15, 0x51, {0x027,5009,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x2b,0x0}}, - {0x52, 0x6c, {0x028,3495,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x3b,0x0}} -}; -static const struct opl4_region regions_08[] = { /* Celesta */ - {0x15, 0x6c, {0x02b,3267,100, 0,0,0x00,0xdc,0x20,0xf4,0x15,0x07,0x3}} -}; -static const struct opl4_region regions_09[] = { /* Glockenspiel */ - {0x15, 0x78, {0x0f3, 285,100, 0,0,0x00,0xc2,0x28,0xf6,0x25,0x25,0x0}} -}; -static const struct opl4_region regions_0a[] = { /* Music Box */ - {0x15, 0x6c, {0x0f3,3362,100, 0,0,0x00,0xb6,0x20,0xa6,0x25,0x25,0x0}}, - {0x15, 0x6c, {0x101,4773,100, 0,0,0x00,0xaa,0x20,0xd4,0x14,0x16,0x0}} -}; -static const struct opl4_region regions_0b[] = { /* Vibraphone */ - {0x15, 0x6c, {0x101,4778,100, 0,0,0x00,0xc0,0x28,0xf4,0x14,0x16,0x4}} -}; -static const struct opl4_region regions_0c[] = { /* Marimba */ - {0x15, 0x3f, {0x0f4,4778,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}}, - {0x40, 0x4c, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}}, - {0x4d, 0x5a, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x08,0x0}}, - {0x5b, 0x7f, {0x0f5,3218,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x18,0x0}} -}; -static const struct opl4_region regions_0d[] = { /* Xylophone */ - {0x00, 0x7f, {0x136,1729,100, 0,0,0x00,0xd2,0x38,0xf0,0x06,0x36,0x0}} -}; -static const struct opl4_region regions_0e[] = { /* Tubular Bell */ - {0x01, 0x7f, {0x0ff,3999,100, 0,1,0x00,0x90,0x21,0xf4,0xa3,0x25,0x1}} -}; -static const struct opl4_region regions_0f[] = { /* Dulcimer */ - {0x00, 0x7f, {0x03f,4236,100, 0,1,0x00,0xbc,0x29,0xf5,0x16,0x07,0x0}}, - {0x00, 0x7f, {0x040,4236,100, 0,2,0x0e,0x94,0x2a,0xf5,0x16,0x07,0x0}} -}; -static const struct opl4_region regions_10[] = { /* Drawbar Organ */ - {0x01, 0x7f, {0x08e,4394,100, 0,2,0x14,0xc2,0x3a,0xf0,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_11[] = { /* Percussive Organ */ - {0x15, 0x3b, {0x08c,6062,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}}, - {0x3c, 0x6c, {0x08d,2984,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_12[] = { /* Rock Organ */ - {0x15, 0x30, {0x128,6574,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, - {0x31, 0x3c, {0x129,5040,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, - {0x3d, 0x48, {0x12a,3498,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, - {0x49, 0x54, {0x12b,1957,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}, - {0x55, 0x6c, {0x127, 423,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_13[] = { /* Church Organ */ - {0x15, 0x29, {0x087,7466,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, - {0x2a, 0x30, {0x088,6456,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, - {0x31, 0x38, {0x089,5428,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, - {0x39, 0x41, {0x08a,4408,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}, - {0x42, 0x6c, {0x08b,3406,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_14[] = { /* Reed Organ */ - {0x00, 0x53, {0x0ac,5570,100, 0,0,0x06,0xc0,0x38,0xf0,0x00,0x09,0x1}}, - {0x54, 0x7f, {0x0ad,2497,100, 0,0,0x00,0xc0,0x38,0xf0,0x00,0x09,0x1}} -}; -static const struct opl4_region regions_15[] = { /* Accordion */ - {0x15, 0x4c, {0x006,4261,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}}, - {0x4d, 0x6c, {0x007,1530,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}}, - {0x15, 0x6c, {0x070,4391,100, 0,3,0x00,0x8a,0x23,0xa0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_16[] = { /* Harmonica */ - {0x15, 0x6c, {0x070,4408,100, 0,0,0x00,0xae,0x30,0xa0,0x00,0x09,0x2}} -}; -static const struct opl4_region regions_17[] = { /* Tango Accordion */ - {0x00, 0x53, {0x0ac,5573,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}}, - {0x54, 0x7f, {0x0ad,2500,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}}, - {0x15, 0x6c, {0x041,8479,100, 0,2,0x00,0x6a,0x3a,0x75,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_18[] = { /* Nylon Guitar */ - {0x15, 0x2f, {0x0b3,6964,100, 0,0,0x05,0xca,0x28,0xf5,0x34,0x09,0x0}}, - {0x30, 0x36, {0x0b7,5567,100, 0,0,0x0c,0xca,0x28,0xf5,0x34,0x09,0x0}}, - {0x37, 0x3c, {0x0b5,4653,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, - {0x3d, 0x43, {0x0b4,3892,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x09,0x0}}, - {0x44, 0x60, {0x0b6,2723,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x19,0x0}} -}; -static const struct opl4_region regions_19[] = { /* Steel Guitar */ - {0x15, 0x31, {0x00c,6937,100, 0,0,0x00,0xbc,0x28,0xf0,0x04,0x19,0x0}}, - {0x32, 0x38, {0x00d,5410,100, 0,0,0x00,0xbc,0x28,0xf0,0x05,0x09,0x0}}, - {0x39, 0x47, {0x00e,4379,100, 0,0,0x00,0xbc,0x28,0xf5,0x94,0x09,0x0}}, - {0x48, 0x6c, {0x00f,2843,100, 0,0,0x00,0xbc,0x28,0xf6,0x95,0x09,0x0}} -}; -static const struct opl4_region regions_1a[] = { /* Jazz Guitar */ - {0x15, 0x31, {0x05a,6832,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, - {0x32, 0x3f, {0x05b,4897,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}, - {0x40, 0x6c, {0x05c,3218,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}} -}; -static const struct opl4_region regions_1b[] = { /* Clean Guitar */ - {0x15, 0x2c, {0x061,7053,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}}, - {0x2d, 0x31, {0x060,6434,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}}, - {0x32, 0x38, {0x063,5764,100, 0,1,0x00,0xbe,0x29,0xf5,0x55,0x0a,0x0}}, - {0x39, 0x3f, {0x062,4627,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x0a,0x0}}, - {0x40, 0x44, {0x065,3963,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x1a,0x0}}, - {0x45, 0x4b, {0x064,3313,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x1a,0x0}}, - {0x4c, 0x54, {0x066,2462,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x2a,0x0}}, - {0x55, 0x6c, {0x067,1307,100, 0,1,0x00,0xb4,0x29,0xf6,0x56,0x0a,0x0}} -}; -static const struct opl4_region regions_1c[] = { /* Muted Guitar */ - {0x01, 0x7f, {0x068,4408,100, 0,0,0x00,0xcc,0x28,0xf6,0x15,0x09,0x0}} -}; -static const struct opl4_region regions_1d[] = { /* Overdriven Guitar */ - {0x00, 0x40, {0x0a5,6589,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}}, - {0x41, 0x7f, {0x0a6,5428,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}} -}; -static const struct opl4_region regions_1e[] = { /* Distortion Guitar */ - {0x15, 0x2a, {0x051,6928,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x2b, 0x2e, {0x052,6433,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x2f, 0x32, {0x053,5944,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x33, 0x36, {0x054,5391,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x37, 0x3a, {0x055,4897,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x3b, 0x3e, {0x056,4408,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x3f, 0x42, {0x057,3892,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x43, 0x46, {0x058,3361,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}, - {0x47, 0x6c, {0x059,2784,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}} -}; -static const struct opl4_region regions_1f[] = { /* Guitar Harmonics */ - {0x15, 0x44, {0x05e,5499,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}}, - {0x45, 0x49, {0x05d,4850,100, 0,0,0x00,0xe2,0x28,0xf4,0x24,0x09,0x0}}, - {0x4a, 0x6c, {0x05f,4259,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}} -}; -static const struct opl4_region regions_20[] = { /* Acoustic Bass */ - {0x15, 0x30, {0x004,8053,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}}, - {0x31, 0x6c, {0x005,4754,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}} -}; -static const struct opl4_region regions_21[] = { /* Fingered Bass */ - {0x01, 0x20, {0x04a,8762,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, - {0x21, 0x25, {0x04b,8114,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, - {0x26, 0x2a, {0x04c,7475,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}, - {0x2b, 0x7f, {0x04d,6841,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}} -}; -static const struct opl4_region regions_22[] = { /* Picked Bass */ - {0x15, 0x23, {0x04f,7954,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x0a,0x0}}, - {0x24, 0x2a, {0x050,7318,100, 0,0,0x05,0xcc,0x18,0xf3,0x90,0x1a,0x0}}, - {0x2b, 0x2f, {0x06b,6654,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x2a,0x0}}, - {0x30, 0x47, {0x069,6031,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}}, - {0x48, 0x6c, {0x06a,5393,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}} -}; -static const struct opl4_region regions_23[] = { /* Fretless Bass */ - {0x01, 0x7f, {0x04e,5297,100, 0,0,0x00,0xd2,0x10,0xf3,0x63,0x19,0x0}} -}; -static const struct opl4_region regions_24[] = { /* Slap Bass 1 */ - {0x15, 0x6c, {0x0a3,7606,100, 0,1,0x00,0xde,0x19,0xf5,0x32,0x1a,0x0}} -}; -static const struct opl4_region regions_25[] = { /* Slap Bass 2 */ - {0x01, 0x7f, {0x0a2,6694,100, 0,0,0x00,0xda,0x20,0xb0,0x02,0x09,0x0}} -}; -static const struct opl4_region regions_26[] = { /* Synth Bass 1 */ - {0x15, 0x6c, {0x0be,7466,100, 0,1,0x00,0xb8,0x39,0xf4,0x14,0x09,0x0}} -}; -static const struct opl4_region regions_27[] = { /* Synth Bass 2 */ - {0x00, 0x7f, {0x117,8103,100, 0,1,0x00,0xca,0x39,0xf3,0x50,0x08,0x0}} -}; -static const struct opl4_region regions_28[] = { /* Violin */ - {0x15, 0x3a, {0x105,5158,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x3b, 0x3f, {0x102,4754,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x40, 0x41, {0x106,4132,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x42, 0x44, {0x107,4033,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x45, 0x47, {0x108,3580,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x48, 0x4a, {0x10a,2957,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x4b, 0x4c, {0x10b,2724,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x4d, 0x4e, {0x10c,2530,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x4f, 0x51, {0x10d,2166,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}, - {0x52, 0x6c, {0x109,1825,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}} -}; -static const struct opl4_region regions_29[] = { /* Viola */ - {0x15, 0x32, {0x103,5780,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x33, 0x35, {0x104,5534,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x36, 0x38, {0x105,5158,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x39, 0x3d, {0x102,4754,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, - {0x3e, 0x3f, {0x106,4132,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x40, 0x42, {0x107,4033,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}}, - {0x43, 0x45, {0x108,3580,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, - {0x46, 0x48, {0x10a,2957,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, - {0x49, 0x4a, {0x10b,2724,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, - {0x4b, 0x4c, {0x10c,2530,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}}, - {0x4d, 0x4f, {0x10d,2166,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}, - {0x50, 0x6c, {0x109,1825,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}} -}; -static const struct opl4_region regions_2a[] = { /* Cello */ - {0x15, 0x2d, {0x112,6545,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}}, - {0x2e, 0x37, {0x113,5764,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}}, - {0x38, 0x3e, {0x115,4378,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}}, - {0x3f, 0x44, {0x116,3998,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}}, - {0x45, 0x6c, {0x114,3218,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}} -}; -static const struct opl4_region regions_2b[] = { /* Contrabass */ - {0x15, 0x29, {0x110,7713,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}}, - {0x2a, 0x6c, {0x111,6162,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_2c[] = { /* Tremolo Strings */ - {0x15, 0x3b, {0x0b0,4810,100, 0,0,0x0a,0xde,0x38,0xf0,0x00,0x07,0x6}}, - {0x3c, 0x41, {0x035,4035,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, - {0x42, 0x47, {0x033,3129,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, - {0x48, 0x52, {0x034,2625,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}}, - {0x53, 0x6c, {0x0af, 936,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x07,0x6}} -}; -static const struct opl4_region regions_2d[] = { /* Pizzicato Strings */ - {0x15, 0x32, {0x0b8,6186,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, - {0x33, 0x3b, {0x0b9,5031,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, - {0x3c, 0x42, {0x0bb,4146,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}, - {0x43, 0x48, {0x0ba,3245,100, 0,0,0x00,0xc2,0x28,0xf0,0x00,0x05,0x0}}, - {0x49, 0x6c, {0x0bc,2352,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}} -}; -static const struct opl4_region regions_2e[] = { /* Harp */ - {0x15, 0x46, {0x07e,3740,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}}, - {0x47, 0x6c, {0x07f,2319,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}} -}; -static const struct opl4_region regions_2f[] = { /* Timpani */ - {0x15, 0x6c, {0x100,6570,100, 0,0,0x00,0xf8,0x28,0xf0,0x05,0x16,0x0}} -}; -static const struct opl4_region regions_30[] = { /* Strings */ - {0x15, 0x3b, {0x13c,4806,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, - {0x3c, 0x41, {0x13e,4035,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, - {0x42, 0x47, {0x13d,3122,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}}, - {0x48, 0x52, {0x13f,2629,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}}, - {0x53, 0x6c, {0x140, 950,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}} -}; -static const struct opl4_region regions_31[] = { /* Slow Strings */ - {0x15, 0x3b, {0x0b0,4810,100, 0,1,0x0a,0xbe,0x19,0xf0,0x00,0x07,0x0}}, - {0x3c, 0x41, {0x035,4035,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, - {0x42, 0x47, {0x033,3129,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, - {0x48, 0x52, {0x034,2625,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}}, - {0x53, 0x6c, {0x0af, 936,100, 0,1,0x00,0xbe,0x19,0xf0,0x00,0x07,0x0}} -}; -static const struct opl4_region regions_32[] = { /* Synth Strings 1 */ - {0x05, 0x71, {0x002,6045,100,-2,0,0x00,0xa6,0x20,0x93,0x22,0x06,0x0}}, - {0x15, 0x6c, {0x0ae,3261,100, 2,0,0x00,0xc6,0x20,0x70,0x01,0x06,0x0}} -}; -static const struct opl4_region regions_33[] = { /* Synth Strings 2 */ - {0x15, 0x6c, {0x002,4513,100, 5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}}, - {0x15, 0x6c, {0x002,4501,100,-5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}} -}; -static const struct opl4_region regions_34[] = { /* Choir Aahs */ - {0x15, 0x3a, {0x018,5010,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, - {0x3b, 0x40, {0x019,4370,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, - {0x41, 0x47, {0x01a,3478,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}, - {0x48, 0x6c, {0x01b,2197,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}} -}; -static const struct opl4_region regions_35[] = { /* Voice Oohs */ - {0x15, 0x6c, {0x029,3596,100, 0,0,0x00,0xe6,0x20,0xf7,0x20,0x08,0x0}} -}; -static const struct opl4_region regions_36[] = { /* Synth Voice */ - {0x15, 0x6c, {0x02a,3482,100, 0,1,0x00,0xc2,0x19,0x85,0x21,0x07,0x0}} -}; -static const struct opl4_region regions_37[] = { /* Orchestra Hit */ - {0x15, 0x6c, {0x049,4394,100, 0,0,0x00,0xfe,0x30,0x80,0x05,0x05,0x0}} -}; -static const struct opl4_region regions_38[] = { /* Trumpet */ - {0x15, 0x3c, {0x0f6,4706,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x3d, 0x43, {0x0f8,3894,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x44, 0x48, {0x0f7,3118,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x49, 0x4e, {0x0fa,2322,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x4f, 0x55, {0x0f9,1634,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}, - {0x56, 0x6c, {0x0fb, 786,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_39[] = { /* Trombone */ - {0x15, 0x3a, {0x0f0,5053,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}}, - {0x3b, 0x3f, {0x0f1,4290,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}}, - {0x40, 0x6c, {0x0f2,3580,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_3a[] = { /* Tuba */ - {0x15, 0x2d, {0x085,7096,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}}, - {0x2e, 0x6c, {0x086,6014,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}} -}; -static const struct opl4_region regions_3b[] = { /* Muted Trumpet */ - {0x15, 0x45, {0x0b1,4135,100, 0,0,0x00,0xcc,0x28,0xf3,0x10,0x0a,0x1}}, - {0x46, 0x6c, {0x0b2,2599,100, 0,0,0x00,0xcc,0x28,0x83,0x10,0x0a,0x1}} -}; -static const struct opl4_region regions_3c[] = { /* French Horns */ - {0x15, 0x49, {0x07c,3624,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}}, - {0x4a, 0x6c, {0x07d,2664,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_3d[] = { /* Brass Section */ - {0x15, 0x42, {0x0fc,4375,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}}, - {0x43, 0x6c, {0x0fd,2854,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_3e[] = { /* Synth Brass 1 */ - {0x01, 0x27, {0x0d3,9094,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x28, 0x2d, {0x0da,8335,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x2e, 0x33, {0x0d4,7558,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x34, 0x39, {0x0db,6785,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x3a, 0x3f, {0x0d5,6042,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x40, 0x45, {0x0dc,5257,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x46, 0x4b, {0x0d6,4493,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x4c, 0x51, {0x0dd,3741,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x52, 0x57, {0x0d7,3012,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x58, 0x5d, {0x0de,2167,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x5e, 0x63, {0x0d8,1421,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x64, 0x7f, {0x0d9,-115,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}}, - {0x01, 0x27, {0x118,9103,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x28, 0x2d, {0x119,8340,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x2e, 0x33, {0x11a,7565,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x34, 0x39, {0x11b,6804,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x3a, 0x3f, {0x11c,6042,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x40, 0x45, {0x11d,5277,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x46, 0x4b, {0x11e,4520,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x4c, 0x51, {0x11f,3741,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x52, 0x57, {0x120,3012,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x58, 0x5d, {0x121,2166,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x5e, 0x64, {0x122,1421,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}, - {0x65, 0x7f, {0x123,-115,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}} -}; -static const struct opl4_region regions_3f[] = { /* Synth Brass 2 */ - {0x01, 0x27, {0x118,9113,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x28, 0x2d, {0x119,8350,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x2e, 0x33, {0x11a,7575,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x34, 0x39, {0x11b,6814,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x3a, 0x3f, {0x11c,6052,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x40, 0x45, {0x11d,5287,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x46, 0x4b, {0x11e,4530,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x4c, 0x51, {0x11f,3751,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x52, 0x57, {0x120,3022,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x58, 0x5d, {0x121,2176,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x5e, 0x64, {0x122,1431,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x65, 0x7f, {0x123,-105,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}}, - {0x00, 0x7f, {0x124,4034,100,-3,2,0x00,0xea,0x22,0x85,0x23,0x08,0x0}} -}; -static const struct opl4_region regions_40[] = { /* Soprano Sax */ - {0x15, 0x3f, {0x0e3,4228,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}}, - {0x40, 0x45, {0x0e4,3495,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}}, - {0x46, 0x4b, {0x0e5,2660,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, - {0x4c, 0x51, {0x0e6,2002,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, - {0x52, 0x59, {0x0e7,1186,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}}, - {0x59, 0x6c, {0x0e8,1730,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_41[] = { /* Alto Sax */ - {0x15, 0x32, {0x092,6204,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x33, 0x35, {0x096,5812,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x36, 0x3a, {0x099,5318,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x3b, 0x3b, {0x08f,5076,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x3c, 0x3e, {0x093,4706,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x3f, 0x41, {0x097,4321,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x42, 0x44, {0x09a,3893,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x45, 0x47, {0x090,3497,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x48, 0x4a, {0x094,3119,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x4b, 0x4d, {0x098,2726,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x4e, 0x50, {0x09b,2393,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x51, 0x53, {0x091,2088,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}, - {0x54, 0x6c, {0x095,1732,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}} -}; -static const struct opl4_region regions_42[] = { /* Tenor Sax */ - {0x24, 0x30, {0x0e9,6301,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x31, 0x34, {0x0ea,5781,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x35, 0x3a, {0x0eb,5053,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x3b, 0x41, {0x0ed,4165,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x42, 0x47, {0x0ec,3218,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x48, 0x51, {0x0ee,2462,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}, - {0x52, 0x6c, {0x0ef,1421,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}} -}; -static const struct opl4_region regions_43[] = { /* Baritone Sax */ - {0x15, 0x2d, {0x0df,6714,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, - {0x2e, 0x34, {0x0e1,5552,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, - {0x35, 0x39, {0x0e2,5178,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}, - {0x3a, 0x6c, {0x0e0,4437,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_44[] = { /* Oboe */ - {0x15, 0x3c, {0x042,4493,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}}, - {0x3d, 0x43, {0x044,3702,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, - {0x44, 0x49, {0x043,2956,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, - {0x4a, 0x4f, {0x046,2166,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, - {0x50, 0x55, {0x045,1420,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}}, - {0x56, 0x6c, {0x047, 630,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}} -}; -static const struct opl4_region regions_45[] = { /* English Horn */ - {0x15, 0x38, {0x03c,5098,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}}, - {0x39, 0x3e, {0x03b,4291,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}}, - {0x3f, 0x6c, {0x03d,3540,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_46[] = { /* Bassoon */ - {0x15, 0x22, {0x038,7833,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}}, - {0x23, 0x2e, {0x03a,7070,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}}, - {0x2f, 0x6c, {0x039,6302,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}} -}; -static const struct opl4_region regions_47[] = { /* Clarinet */ - {0x15, 0x3b, {0x09e,5900,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, - {0x3c, 0x41, {0x0a0,5158,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, - {0x42, 0x4a, {0x09f,4260,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}, - {0x4b, 0x6c, {0x0a1,2957,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_48[] = { /* Piccolo */ - {0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, - {0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, - {0x4e, 0x53, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, - {0x54, 0x5f, {0x074,2085,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}, - {0x60, 0x6c, {0x075,1421,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}} -}; -static const struct opl4_region regions_49[] = { /* Flute */ - {0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}}, - {0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}}, - {0x4e, 0x6c, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}} -}; -static const struct opl4_region regions_4a[] = { /* Recorder */ - {0x15, 0x6f, {0x0bd,4897,100, 0,0,0x00,0xec,0x30,0x70,0x00,0x09,0x1}} -}; -static const struct opl4_region regions_4b[] = { /* Pan Flute */ - {0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x09,0x3}} -}; -static const struct opl4_region regions_4c[] = { /* Bottle Blow */ - {0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xc8,0x38,0xf0,0x00,0x09,0x1}}, - {0x01, 0x7f, {0x125,7372,100, 0,0,0x1e,0x80,0x00,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_4d[] = { /* Shakuhachi */ - {0x00, 0x7f, {0x0ab,4548,100, 0,0,0x00,0xd6,0x30,0xf0,0x00,0x0a,0x3}}, - {0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xa2,0x28,0x70,0x00,0x09,0x2}} -}; -static const struct opl4_region regions_4e[] = { /* Whistle */ - {0x00, 0x7f, {0x0aa,1731,100, 0,4,0x00,0xd2,0x2c,0x70,0x00,0x0a,0x0}} -}; -static const struct opl4_region regions_4f[] = { /* Ocarina */ - {0x00, 0x7f, {0x0aa,1731,100, 0,1,0x00,0xce,0x29,0x90,0x00,0x0a,0x1}} -}; -static const struct opl4_region regions_50[] = { /* Square Lead */ - {0x01, 0x2a, {0x0cc,9853,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x2b, 0x36, {0x0cd,6785,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x37, 0x42, {0x0ca,5248,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x43, 0x4e, {0x0cf,3713,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x4f, 0x5a, {0x0ce,2176,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x5b, 0x7f, {0x0cb, 640,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}}, - {0x01, 0x2a, {0x0cc,9844,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x2b, 0x36, {0x0cd,6776,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x37, 0x42, {0x0ca,5239,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x43, 0x4e, {0x0cf,3704,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x4f, 0x5a, {0x0ce,2167,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}, - {0x5b, 0x7f, {0x0cb, 631,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}} -}; -static const struct opl4_region regions_51[] = { /* Sawtooth Lead */ - {0x01, 0x27, {0x118,9108,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x28, 0x2d, {0x119,8345,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x2e, 0x33, {0x11a,7570,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x34, 0x39, {0x11b,6809,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x3a, 0x3f, {0x11c,6047,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x40, 0x45, {0x11d,5282,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x46, 0x4b, {0x11e,4525,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x4c, 0x51, {0x11f,3746,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x52, 0x57, {0x120,3017,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x58, 0x5d, {0x121,2171,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x5e, 0x66, {0x122,1426,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x67, 0x7f, {0x123,-110,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x01, 0x27, {0x118,9098,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x28, 0x2d, {0x119,8335,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x2e, 0x33, {0x11a,7560,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x34, 0x39, {0x11b,6799,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x3a, 0x3f, {0x11c,6037,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x40, 0x45, {0x11d,5272,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x46, 0x4b, {0x11e,4515,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x4c, 0x51, {0x11f,3736,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x52, 0x57, {0x120,3007,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x58, 0x5d, {0x121,2161,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x5e, 0x66, {0x122,1416,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}, - {0x67, 0x7f, {0x123,-120,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}} -}; -static const struct opl4_region regions_52[] = { /* Calliope Lead */ - {0x00, 0x7f, {0x0aa,1731,100, 0,0,0x00,0xc2,0x28,0x90,0x00,0x0a,0x2}}, - {0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xb6,0x28,0xb0,0x00,0x09,0x2}} -}; -static const struct opl4_region regions_53[] = { /* Chiffer Lead */ - {0x00, 0x7f, {0x13a,3665,100, 0,2,0x00,0xcc,0x2a,0xf0,0x10,0x09,0x1}}, - {0x01, 0x7f, {0x0fe,3660,100, 0,0,0x00,0xbe,0x28,0xf3,0x10,0x17,0x0}} -}; -static const struct opl4_region regions_54[] = { /* Charang Lead */ - {0x00, 0x40, {0x0a5,6594,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}}, - {0x41, 0x7f, {0x0a6,5433,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}}, - {0x01, 0x27, {0x118,9098,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x28, 0x2d, {0x119,8335,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x2e, 0x33, {0x11a,7560,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x34, 0x39, {0x11b,6799,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x3a, 0x3f, {0x11c,6037,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x40, 0x45, {0x11d,5272,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x46, 0x4b, {0x11e,4515,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x4c, 0x51, {0x11f,3736,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x52, 0x57, {0x120,3007,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x58, 0x5d, {0x121,2161,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x5e, 0x66, {0x122,1416,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}, - {0x67, 0x7f, {0x123,-120,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}} -}; -static const struct opl4_region regions_55[] = { /* Voice Lead */ - {0x00, 0x7f, {0x0aa,1739,100, 0,6,0x00,0x8c,0x2e,0x90,0x00,0x0a,0x0}}, - {0x15, 0x6c, {0x02a,3474,100, 0,1,0x00,0xd8,0x29,0xf0,0x05,0x0a,0x0}} -}; -static const struct opl4_region regions_56[] = { /* 5ths Lead */ - {0x01, 0x27, {0x118,8468,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x28, 0x2d, {0x119,7705,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x2e, 0x33, {0x11a,6930,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x34, 0x39, {0x11b,6169,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x3a, 0x3f, {0x11c,5407,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x40, 0x45, {0x11d,4642,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x46, 0x4b, {0x11e,3885,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x4c, 0x51, {0x11f,3106,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x52, 0x57, {0x120,2377,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x58, 0x5d, {0x121,1531,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x5e, 0x64, {0x122, 786,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x65, 0x7f, {0x123,-750,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}}, - {0x05, 0x71, {0x002,4503,100, 0,1,0x00,0xb8,0x31,0xb3,0x20,0x0b,0x0}} -}; -static const struct opl4_region regions_57[] = { /* Bass & Lead */ - {0x00, 0x7f, {0x117,8109,100, 0,1,0x00,0xbc,0x29,0xf3,0x50,0x08,0x0}}, - {0x01, 0x27, {0x118,9097,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x28, 0x2d, {0x119,8334,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x2e, 0x33, {0x11a,7559,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x34, 0x39, {0x11b,6798,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x3a, 0x3f, {0x11c,6036,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x40, 0x45, {0x11d,5271,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x46, 0x4b, {0x11e,4514,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x4c, 0x51, {0x11f,3735,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x52, 0x57, {0x120,3006,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x58, 0x5d, {0x121,2160,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x5e, 0x66, {0x122,1415,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}, - {0x67, 0x7f, {0x123,-121,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}} -}; -static const struct opl4_region regions_58[] = { /* New Age Pad */ - {0x15, 0x6c, {0x002,4501,100, 0,4,0x00,0xa4,0x24,0x80,0x01,0x05,0x0}}, - {0x15, 0x6c, {0x0f3,4253,100, 0,3,0x00,0x8c,0x23,0xa2,0x14,0x06,0x1}} -}; -static const struct opl4_region regions_59[] = { /* Warm Pad */ - {0x15, 0x6c, {0x04e,5306,100, 2,2,0x00,0x92,0x2a,0x34,0x23,0x05,0x2}}, - {0x15, 0x6c, {0x029,3575,100,-2,2,0x00,0xbe,0x22,0x31,0x23,0x06,0x0}} -}; -static const struct opl4_region regions_5a[] = { /* Polysynth Pad */ - {0x01, 0x27, {0x118,9111,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x28, 0x2d, {0x119,8348,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x2e, 0x33, {0x11a,7573,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x34, 0x39, {0x11b,6812,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x3a, 0x3f, {0x11c,6050,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x40, 0x45, {0x11d,5285,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x46, 0x4b, {0x11e,4528,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x4c, 0x51, {0x11f,3749,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x52, 0x57, {0x120,3020,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x58, 0x5d, {0x121,2174,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x5e, 0x66, {0x122,1429,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x67, 0x7f, {0x123,-107,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}}, - {0x00, 0x7f, {0x124,4024,100, 0,2,0x00,0xae,0x22,0xe5,0x20,0x08,0x0}} -}; -static const struct opl4_region regions_5b[] = { /* Choir Pad */ - {0x15, 0x3a, {0x018,5010,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, - {0x3b, 0x40, {0x019,4370,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, - {0x41, 0x47, {0x01a,3478,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, - {0x48, 0x6c, {0x01b,2197,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}}, - {0x15, 0x6c, {0x02a,3482,100, 0,4,0x00,0x98,0x24,0x65,0x21,0x06,0x0}} -}; -static const struct opl4_region regions_5c[] = { /* Bowed Pad */ - {0x15, 0x6c, {0x101,4790,100,-1,1,0x00,0xbe,0x19,0x44,0x14,0x16,0x0}}, - {0x00, 0x7f, {0x0aa,1720,100, 1,1,0x00,0x94,0x19,0x40,0x00,0x06,0x0}} -}; -static const struct opl4_region regions_5d[] = { /* Metallic Pad */ - {0x15, 0x31, {0x00c,6943,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, - {0x32, 0x38, {0x00d,5416,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, - {0x39, 0x47, {0x00e,4385,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, - {0x48, 0x6c, {0x00f,2849,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}}, - {0x00, 0x7f, {0x03f,4224,100, 0,1,0x00,0x9c,0x31,0x65,0x16,0x07,0x0}} -}; -static const struct opl4_region regions_5e[] = { /* Halo Pad */ - {0x00, 0x7f, {0x124,4038,100, 0,2,0x00,0xa6,0x1a,0x85,0x23,0x08,0x0}}, - {0x15, 0x6c, {0x02a,3471,100, 0,3,0x00,0xc0,0x1b,0xc0,0x05,0x06,0x0}} -}; -static const struct opl4_region regions_5f[] = { /* Sweep Pad */ - {0x01, 0x27, {0x0d3,9100,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x28, 0x2d, {0x0da,8341,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x2e, 0x33, {0x0d4,7564,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x34, 0x39, {0x0db,6791,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x3a, 0x3f, {0x0d5,6048,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x40, 0x45, {0x0dc,5263,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x46, 0x4b, {0x0d6,4499,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x4c, 0x51, {0x0dd,3747,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x52, 0x57, {0x0d7,3018,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x58, 0x5d, {0x0de,2173,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x5e, 0x63, {0x0d8,1427,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x64, 0x7f, {0x0d9,-109,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}}, - {0x01, 0x27, {0x0d3,9088,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x28, 0x2d, {0x0da,8329,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x2e, 0x33, {0x0d4,7552,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x34, 0x39, {0x0db,6779,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x3a, 0x3f, {0x0d5,6036,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x40, 0x45, {0x0dc,5251,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x46, 0x4b, {0x0d6,4487,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x4c, 0x51, {0x0dd,3735,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x52, 0x57, {0x0d7,3006,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x58, 0x5d, {0x0de,2161,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x5e, 0x63, {0x0d8,1415,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}, - {0x64, 0x7f, {0x0d9,-121,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}} -}; -static const struct opl4_region regions_60[] = { /* Ice Rain */ - {0x01, 0x7f, {0x04e,9345,100, 0,2,0x00,0xcc,0x22,0xa3,0x63,0x17,0x0}}, - {0x00, 0x7f, {0x143,5586, 20, 0,2,0x00,0x6e,0x2a,0xf0,0x05,0x05,0x0}} -}; -static const struct opl4_region regions_61[] = { /* Soundtrack */ - {0x15, 0x6c, {0x002,4501,100, 0,2,0x00,0xb6,0x2a,0x60,0x01,0x05,0x0}}, - {0x15, 0x6c, {0x0f3,1160,100, 0,5,0x00,0xa8,0x2d,0x52,0x14,0x06,0x2}} -}; -static const struct opl4_region regions_62[] = { /* Crystal */ - {0x15, 0x6c, {0x0f3,1826,100, 0,3,0x00,0xb8,0x33,0xf6,0x25,0x25,0x0}}, - {0x15, 0x2c, {0x06d,7454,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}}, - {0x2d, 0x36, {0x06e,5925,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}}, - {0x37, 0x6c, {0x06f,4403,100, 0,3,0x09,0xac,0x3b,0x85,0x24,0x06,0x0}} -}; -static const struct opl4_region regions_63[] = { /* Atmosphere */ - {0x05, 0x71, {0x002,4509,100, 0,2,0x00,0xc8,0x32,0x73,0x22,0x06,0x1}}, - {0x15, 0x2f, {0x0b3,6964,100, 0,2,0x05,0xc2,0x32,0xf5,0x34,0x07,0x2}}, - {0x30, 0x36, {0x0b7,5567,100, 0,2,0x0c,0xc2,0x32,0xf5,0x34,0x07,0x2}}, - {0x37, 0x3c, {0x0b5,4653,100, 0,2,0x00,0xc2,0x32,0xf6,0x34,0x07,0x2}}, - {0x3d, 0x43, {0x0b4,3892,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x07,0x2}}, - {0x44, 0x60, {0x0b6,2723,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x17,0x2}} -}; -static const struct opl4_region regions_64[] = { /* Brightness */ - {0x00, 0x7f, {0x137,5285,100, 0,2,0x00,0xbe,0x2a,0xa5,0x18,0x08,0x0}}, - {0x15, 0x6c, {0x02a,3481,100, 0,1,0x00,0xc8,0x29,0x80,0x05,0x05,0x0}} -}; -static const struct opl4_region regions_65[] = { /* Goblins */ - {0x15, 0x6c, {0x002,4501,100,-1,2,0x00,0xca,0x2a,0x40,0x01,0x05,0x0}}, - {0x15, 0x6c, {0x009,9679, 20, 1,4,0x00,0x3c,0x0c,0x22,0x11,0x06,0x0}} -}; -static const struct opl4_region regions_66[] = { /* Echoes */ - {0x15, 0x6c, {0x02a,3487,100, 0,3,0x00,0xae,0x2b,0xf5,0x21,0x06,0x0}}, - {0x00, 0x7f, {0x124,4027,100, 0,3,0x00,0xae,0x2b,0x85,0x23,0x07,0x0}} -}; -static const struct opl4_region regions_67[] = { /* Sci-Fi */ - {0x15, 0x31, {0x00c,6940,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, - {0x32, 0x38, {0x00d,5413,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, - {0x39, 0x47, {0x00e,4382,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, - {0x48, 0x6c, {0x00f,2846,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}}, - {0x15, 0x6c, {0x002,4498,100, 0,2,0x00,0xd4,0x22,0x80,0x01,0x05,0x0}} -}; -static const struct opl4_region regions_68[] = { /* Sitar */ - {0x00, 0x7f, {0x10f,4408,100, 0,2,0x00,0xc4,0x32,0xf4,0x15,0x16,0x1}} -}; -static const struct opl4_region regions_69[] = { /* Banjo */ - {0x15, 0x34, {0x013,5685,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x35, 0x38, {0x014,5009,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x39, 0x3c, {0x012,4520,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x3d, 0x44, {0x015,3622,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x45, 0x4c, {0x017,2661,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}, - {0x4d, 0x6d, {0x016,1632,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}} -}; -static const struct opl4_region regions_6a[] = { /* Shamisen */ - {0x15, 0x6c, {0x10e,3273,100, 0,0,0x00,0xc0,0x28,0xf7,0x76,0x08,0x0}} -}; -static const struct opl4_region regions_6b[] = { /* Koto */ - {0x00, 0x7f, {0x0a9,4033,100, 0,0,0x00,0xc6,0x20,0xf0,0x06,0x07,0x0}} -}; -static const struct opl4_region regions_6c[] = { /* Kalimba */ - {0x00, 0x7f, {0x137,3749,100, 0,0,0x00,0xce,0x38,0xf5,0x18,0x08,0x0}} -}; -static const struct opl4_region regions_6d[] = { /* Bagpipe */ - {0x15, 0x39, {0x0a4,7683,100, 0,4,0x00,0xc0,0x1c,0xf0,0x00,0x09,0x0}}, - {0x15, 0x39, {0x0a7,7680,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}}, - {0x3a, 0x6c, {0x0a8,3697,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_6e[] = { /* Fiddle */ - {0x15, 0x3a, {0x105,5158,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x3b, 0x3f, {0x102,4754,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x40, 0x41, {0x106,4132,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x42, 0x44, {0x107,4033,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x45, 0x47, {0x108,3580,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x48, 0x4a, {0x10a,2957,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x4b, 0x4c, {0x10b,2724,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x4d, 0x4e, {0x10c,2530,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x4f, 0x51, {0x10d,2166,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}, - {0x52, 0x6c, {0x109,1825,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}} -}; -static const struct opl4_region regions_6f[] = { /* Shanai */ - {0x15, 0x6c, {0x041,6946,100, 0,1,0x00,0xc4,0x31,0x95,0x20,0x09,0x0}} -}; -static const struct opl4_region regions_70[] = { /* Tinkle Bell */ - {0x15, 0x73, {0x0f3,1821,100, 0,3,0x00,0xc8,0x3b,0xd6,0x25,0x25,0x0}}, - {0x00, 0x7f, {0x137,5669,100, 0,3,0x00,0x66,0x3b,0xf5,0x18,0x08,0x0}} -}; -static const struct opl4_region regions_71[] = { /* Agogo */ - {0x15, 0x74, {0x00b,2474,100, 0,0,0x00,0xd2,0x38,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_72[] = { /* Steel Drums */ - {0x01, 0x7f, {0x0fe,3670,100, 0,0,0x00,0xca,0x38,0xf3,0x06,0x17,0x1}}, - {0x15, 0x6c, {0x100,9602,100, 0,0,0x00,0x54,0x38,0xb0,0x05,0x16,0x1}} -}; -static const struct opl4_region regions_73[] = { /* Woodblock */ - {0x15, 0x6c, {0x02c,2963, 50, 0,0,0x07,0xd4,0x00,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_74[] = { /* Taiko Drum */ - {0x13, 0x6c, {0x03e,1194, 50, 0,0,0x00,0xaa,0x38,0xf0,0x04,0x04,0x0}} -}; -static const struct opl4_region regions_75[] = { /* Melodic Tom */ - {0x15, 0x6c, {0x0c7,6418, 50, 0,0,0x00,0xe4,0x38,0xf0,0x05,0x01,0x0}} -}; -static const struct opl4_region regions_76[] = { /* Synth Drum */ - {0x15, 0x6c, {0x026,3898, 50, 0,0,0x00,0xd0,0x38,0xf0,0x04,0x04,0x0}} -}; -static const struct opl4_region regions_77[] = { /* Reverse Cymbal */ - {0x15, 0x6c, {0x031,4138, 50, 0,0,0x00,0xfe,0x38,0x3a,0xf0,0x09,0x0}} -}; -static const struct opl4_region regions_78[] = { /* Guitar Fret Noise */ - {0x15, 0x6c, {0x138,5266,100, 0,0,0x00,0xa0,0x38,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_79[] = { /* Breath Noise */ - {0x01, 0x7f, {0x125,4269,100, 0,0,0x1e,0xd0,0x38,0xf0,0x00,0x09,0x0}} -}; -static const struct opl4_region regions_7a[] = { /* Seashore */ - {0x15, 0x6c, {0x008,2965, 20,-2,0,0x00,0xfe,0x00,0x20,0x03,0x04,0x0}}, - {0x01, 0x7f, {0x037,4394, 20, 2,0,0x14,0xfe,0x00,0x20,0x04,0x05,0x0}} -}; -static const struct opl4_region regions_7b[] = { /* Bird Tweet */ - {0x15, 0x6c, {0x009,8078, 5,-4,7,0x00,0xc2,0x0f,0x22,0x12,0x07,0x0}}, - {0x15, 0x6c, {0x009,3583, 5, 4,5,0x00,0xae,0x15,0x72,0x12,0x07,0x0}} -}; -static const struct opl4_region regions_7c[] = { /* Telephone Ring */ - {0x15, 0x6c, {0x003,3602, 10, 0,0,0x00,0xce,0x00,0xf0,0x00,0x0f,0x0}} -}; -static const struct opl4_region regions_7d[] = { /* Helicopter */ - {0x0c, 0x7f, {0x001,2965, 10,-2,0,0x00,0xe0,0x08,0x30,0x01,0x07,0x0}}, - {0x01, 0x7f, {0x037,4394, 10, 2,0,0x44,0x76,0x00,0x30,0x01,0x07,0x0}} -}; -static const struct opl4_region regions_7e[] = { /* Applause */ - {0x15, 0x6c, {0x036,8273, 20,-6,7,0x00,0xc4,0x0f,0x70,0x01,0x05,0x0}}, - {0x15, 0x6c, {0x036,8115, 5, 6,7,0x00,0xc6,0x07,0x70,0x01,0x05,0x0}} -}; -static const struct opl4_region regions_7f[] = { /* Gun Shot */ - {0x15, 0x6c, {0x139,2858, 20, 0,0,0x00,0xbe,0x38,0xf0,0x03,0x00,0x0}} -}; -static const struct opl4_region regions_drums[] = { - {0x18, 0x18, {0x0cb,6397,100, 3,0,0x00,0xf4,0x38,0xc9,0x1c,0x0c,0x0}}, - {0x19, 0x19, {0x0c4,3714,100, 0,0,0x00,0xe0,0x00,0x97,0x19,0x09,0x0}}, - {0x1a, 0x1a, {0x0c4,3519,100, 0,0,0x00,0xea,0x00,0x61,0x01,0x07,0x0}}, - {0x1b, 0x1b, {0x0c4,3586,100, 0,0,0x00,0xea,0x00,0xf7,0x19,0x09,0x0}}, - {0x1c, 0x1c, {0x0c4,3586,100, 0,0,0x00,0xea,0x00,0x81,0x01,0x07,0x0}}, - {0x1e, 0x1e, {0x0c3,4783,100, 0,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x1f, 0x1f, {0x0d1,4042,100, 0,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, - {0x20, 0x20, {0x0d2,5943,100, 0,0,0x00,0xcc,0x00,0xf0,0x00,0x09,0x0}}, - {0x21, 0x21, {0x011,3842,100, 0,0,0x00,0xea,0x00,0xf0,0x16,0x06,0x0}}, - {0x23, 0x23, {0x011,4098,100, 0,0,0x00,0xea,0x00,0xf0,0x16,0x06,0x0}}, - {0x24, 0x24, {0x011,4370,100, 0,0,0x00,0xea,0x00,0xf0,0x00,0x06,0x0}}, - {0x25, 0x25, {0x0d2,4404,100, 0,0,0x00,0xd6,0x00,0xf0,0x00,0x06,0x0}}, - {0x26, 0x26, {0x0d1,4298,100, 0,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, - {0x27, 0x27, {0x00a,4403,100,-1,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x28, 0x28, {0x0d1,4554,100, 0,0,0x00,0xdc,0x00,0xf0,0x07,0x07,0x0}}, - {0x29, 0x29, {0x0c8,4242,100,-4,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, - {0x2a, 0x2a, {0x079,6160,100, 2,0,0x00,0xe0,0x00,0xf5,0x19,0x09,0x0}}, - {0x2b, 0x2b, {0x0c8,4626,100,-3,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, - {0x2c, 0x2c, {0x07b,6039,100, 2,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x2d, 0x2d, {0x0c8,5394,100,-2,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}}, - {0x2e, 0x2e, {0x07a,5690,100, 2,0,0x00,0xd6,0x00,0xf0,0x00,0x05,0x0}}, - {0x2f, 0x2f, {0x0c7,5185,100, 2,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, - {0x30, 0x30, {0x0c7,5650,100, 3,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, - {0x31, 0x31, {0x031,4395,100, 2,0,0x00,0xea,0x00,0xf0,0x05,0x05,0x0}}, - {0x32, 0x32, {0x0c7,6162,100, 4,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}}, - {0x33, 0x33, {0x02e,4391,100,-2,0,0x00,0xea,0x00,0xf0,0x05,0x05,0x0}}, - {0x34, 0x34, {0x07a,3009,100,-2,0,0x00,0xea,0x00,0xf2,0x15,0x05,0x0}}, - {0x35, 0x35, {0x021,4522,100,-3,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}}, - {0x36, 0x36, {0x025,5163,100, 1,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, - {0x37, 0x37, {0x031,5287,100,-1,0,0x00,0xea,0x00,0xf5,0x16,0x06,0x0}}, - {0x38, 0x38, {0x01d,4395,100, 2,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, - {0x39, 0x39, {0x031,4647,100,-2,0,0x00,0xea,0x00,0xf4,0x16,0x06,0x0}}, - {0x3a, 0x3a, {0x09d,4426,100,-4,0,0x00,0xe0,0x00,0xf4,0x17,0x07,0x0}}, - {0x3b, 0x3b, {0x02e,4659,100,-2,0,0x00,0xea,0x00,0xf0,0x06,0x06,0x0}}, - {0x3c, 0x3c, {0x01c,4769,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x3d, 0x3d, {0x01c,4611,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x3e, 0x3e, {0x01e,4402,100,-3,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x3f, 0x3f, {0x01f,4387,100,-3,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x40, 0x40, {0x01f,3983,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x41, 0x41, {0x09c,4526,100, 2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x42, 0x42, {0x09c,4016,100, 2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x43, 0x43, {0x00b,4739,100,-4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x44, 0x44, {0x00b,4179,100,-4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x45, 0x45, {0x02f,4787,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x46, 0x46, {0x030,4665,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x47, 0x47, {0x144,4519,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x0b,0x0}}, - {0x48, 0x48, {0x144,4111,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x0b,0x0}}, - {0x49, 0x49, {0x024,6408,100, 3,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, - {0x4a, 0x4a, {0x024,4144,100, 3,0,0x00,0xcc,0x00,0xf0,0x00,0x09,0x0}}, - {0x4b, 0x4b, {0x020,4001,100, 2,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}}, - {0x4c, 0x4c, {0x02c,4402,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x4d, 0x4d, {0x02c,3612,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x4e, 0x4e, {0x022,4129,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x4f, 0x4f, {0x023,4147,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}}, - {0x50, 0x50, {0x032,4412,100,-4,0,0x00,0xd6,0x00,0xf0,0x08,0x09,0x0}}, - {0x51, 0x51, {0x032,4385,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}, - {0x52, 0x52, {0x02f,5935,100,-1,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}} -}; - -#define REGION(num) { ARRAY_SIZE(regions ## num), regions ## num } -const struct opl4_region_ptr snd_yrw801_regions[0x81] = { - REGION(_00), REGION(_01), REGION(_02), REGION(_03), - REGION(_04), REGION(_05), REGION(_06), REGION(_07), - REGION(_08), REGION(_09), REGION(_0a), REGION(_0b), - REGION(_0c), REGION(_0d), REGION(_0e), REGION(_0f), - REGION(_10), REGION(_11), REGION(_12), REGION(_13), - REGION(_14), REGION(_15), REGION(_16), REGION(_17), - REGION(_18), REGION(_19), REGION(_1a), REGION(_1b), - REGION(_1c), REGION(_1d), REGION(_1e), REGION(_1f), - REGION(_20), REGION(_21), REGION(_22), REGION(_23), - REGION(_24), REGION(_25), REGION(_26), REGION(_27), - REGION(_28), REGION(_29), REGION(_2a), REGION(_2b), - REGION(_2c), REGION(_2d), REGION(_2e), REGION(_2f), - REGION(_30), REGION(_31), REGION(_32), REGION(_33), - REGION(_34), REGION(_35), REGION(_36), REGION(_37), - REGION(_38), REGION(_39), REGION(_3a), REGION(_3b), - REGION(_3c), REGION(_3d), REGION(_3e), REGION(_3f), - REGION(_40), REGION(_41), REGION(_42), REGION(_43), - REGION(_44), REGION(_45), REGION(_46), REGION(_47), - REGION(_48), REGION(_49), REGION(_4a), REGION(_4b), - REGION(_4c), REGION(_4d), REGION(_4e), REGION(_4f), - REGION(_50), REGION(_51), REGION(_52), REGION(_53), - REGION(_54), REGION(_55), REGION(_56), REGION(_57), - REGION(_58), REGION(_59), REGION(_5a), REGION(_5b), - REGION(_5c), REGION(_5d), REGION(_5e), REGION(_5f), - REGION(_60), REGION(_61), REGION(_62), REGION(_63), - REGION(_64), REGION(_65), REGION(_66), REGION(_67), - REGION(_68), REGION(_69), REGION(_6a), REGION(_6b), - REGION(_6c), REGION(_6d), REGION(_6e), REGION(_6f), - REGION(_70), REGION(_71), REGION(_72), REGION(_73), - REGION(_74), REGION(_75), REGION(_76), REGION(_77), - REGION(_78), REGION(_79), REGION(_7a), REGION(_7b), - REGION(_7c), REGION(_7d), REGION(_7e), REGION(_7f), - REGION(_drums) -}; diff --git a/ANDROID_3.4.5/sound/drivers/pcm-indirect2.c b/ANDROID_3.4.5/sound/drivers/pcm-indirect2.c deleted file mode 100644 index e73fafd7..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcm-indirect2.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Helper functions for indirect PCM data transfer to a simple FIFO in - * hardware (small, no possibility to read "hardware io position", - * updating position done by interrupt, ...) - * - * Copyright (c) by 2007 Joachim Foerster - * - * Based on "pcm-indirect.h" (alsa-driver-1.0.13) by - * - * Copyright (c) by Takashi Iwai - * Jaroslav Kysela - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* snd_printk/d() */ -#include -/* struct snd_pcm_substream, struct snd_pcm_runtime, snd_pcm_uframes_t - * snd_pcm_period_elapsed() */ -#include - -#include "pcm-indirect2.h" - -#ifdef SND_PCM_INDIRECT2_STAT -/* jiffies */ -#include - -void snd_pcm_indirect2_stat(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int i; - int j; - int k; - int seconds = (rec->lastbytetime - rec->firstbytetime) / HZ; - - snd_printk(KERN_DEBUG "STAT: mul_elapsed: %u, mul_elapsed_real: %d, " - "irq_occured: %d\n", - rec->mul_elapsed, rec->mul_elapsed_real, rec->irq_occured); - snd_printk(KERN_DEBUG "STAT: min_multiple: %d (irqs/period)\n", - rec->min_multiple); - snd_printk(KERN_DEBUG "STAT: firstbytetime: %lu, lastbytetime: %lu, " - "firstzerotime: %lu\n", - rec->firstbytetime, rec->lastbytetime, rec->firstzerotime); - snd_printk(KERN_DEBUG "STAT: bytes2hw: %u Bytes => (by runtime->rate) " - "length: %d s\n", - rec->bytes2hw, rec->bytes2hw / 2 / 2 / runtime->rate); - snd_printk(KERN_DEBUG "STAT: (by measurement) length: %d => " - "rate: %d Bytes/s = %d Frames/s|Hz\n", - seconds, rec->bytes2hw / seconds, - rec->bytes2hw / 2 / 2 / seconds); - snd_printk(KERN_DEBUG - "STAT: zeros2hw: %u = %d ms ~ %d * %d zero copies\n", - rec->zeros2hw, ((rec->zeros2hw / 2 / 2) * 1000) / - runtime->rate, - rec->zeros2hw / (rec->hw_buffer_size / 2), - (rec->hw_buffer_size / 2)); - snd_printk(KERN_DEBUG "STAT: pointer_calls: %u, lastdifftime: %u\n", - rec->pointer_calls, rec->lastdifftime); - snd_printk(KERN_DEBUG "STAT: sw_io: %d, sw_data: %d\n", rec->sw_io, - rec->sw_data); - snd_printk(KERN_DEBUG "STAT: byte_sizes[]:\n"); - k = 0; - for (j = 0; j < 8; j++) { - for (i = j * 8; i < (j + 1) * 8; i++) - if (rec->byte_sizes[i] != 0) { - snd_printk(KERN_DEBUG "%u: %u", - i, rec->byte_sizes[i]); - k++; - } - if (((k % 8) == 0) && (k != 0)) { - snd_printk(KERN_DEBUG "\n"); - k = 0; - } - } - snd_printk(KERN_DEBUG "\n"); - snd_printk(KERN_DEBUG "STAT: zero_sizes[]:\n"); - for (j = 0; j < 8; j++) { - k = 0; - for (i = j * 8; i < (j + 1) * 8; i++) - if (rec->zero_sizes[i] != 0) - snd_printk(KERN_DEBUG "%u: %u", - i, rec->zero_sizes[i]); - else - k++; - if (!k) - snd_printk(KERN_DEBUG "\n"); - } - snd_printk(KERN_DEBUG "\n"); - snd_printk(KERN_DEBUG "STAT: min_adds[]:\n"); - for (j = 0; j < 8; j++) { - if (rec->min_adds[j] != 0) - snd_printk(KERN_DEBUG "%u: %u", j, rec->min_adds[j]); - } - snd_printk(KERN_DEBUG "\n"); - snd_printk(KERN_DEBUG "STAT: mul_adds[]:\n"); - for (j = 0; j < 8; j++) { - if (rec->mul_adds[j] != 0) - snd_printk(KERN_DEBUG "%u: %u", j, rec->mul_adds[j]); - } - snd_printk(KERN_DEBUG "\n"); - snd_printk(KERN_DEBUG - "STAT: zero_times_saved: %d, zero_times_notsaved: %d\n", - rec->zero_times_saved, rec->zero_times_notsaved); - /* snd_printk(KERN_DEBUG "STAT: zero_times[]\n"); - i = 0; - for (j = 0; j < 3750; j++) { - if (rec->zero_times[j] != 0) { - snd_printk(KERN_DEBUG "%u: %u", j, rec->zero_times[j]); - i++; - } - if (((i % 8) == 0) && (i != 0)) - snd_printk(KERN_DEBUG "\n"); - } - snd_printk(KERN_DEBUG "\n"); */ - return; -} -#endif - -/* - * _internal_ helper function for playback/capture transfer function - */ -static void -snd_pcm_indirect2_increase_min_periods(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - int isplay, int iscopy, - unsigned int bytes) -{ - if (rec->min_periods >= 0) { - if (iscopy) { - rec->sw_io += bytes; - if (rec->sw_io >= rec->sw_buffer_size) - rec->sw_io -= rec->sw_buffer_size; - } else if (isplay) { - /* If application does not write data in multiples of - * a period, move sw_data to the next correctly aligned - * position, so that sw_io can converge to it (in the - * next step). - */ - if (!rec->check_alignment) { - if (rec->bytes2hw % - snd_pcm_lib_period_bytes(substream)) { - unsigned bytes2hw_aligned = - (1 + - (rec->bytes2hw / - snd_pcm_lib_period_bytes - (substream))) * - snd_pcm_lib_period_bytes - (substream); - rec->sw_data = - bytes2hw_aligned % - rec->sw_buffer_size; -#ifdef SND_PCM_INDIRECT2_STAT - snd_printk(KERN_DEBUG - "STAT: @re-align: aligned " - "bytes2hw to next period " - "size boundary: %d " - "(instead of %d)\n", - bytes2hw_aligned, - rec->bytes2hw); - snd_printk(KERN_DEBUG - "STAT: @re-align: sw_data " - "moves to: %d\n", - rec->sw_data); -#endif - } - rec->check_alignment = 1; - } - /* We are at the end and are copying zeros into the - * fifo. - * Now, we have to make sure that sw_io is increased - * until the position of sw_data: Filling the fifo with - * the first zeros means, the last bytes were played. - */ - if (rec->sw_io != rec->sw_data) { - unsigned int diff; - if (rec->sw_data > rec->sw_io) - diff = rec->sw_data - rec->sw_io; - else - diff = (rec->sw_buffer_size - - rec->sw_io) + - rec->sw_data; - if (bytes >= diff) - rec->sw_io = rec->sw_data; - else { - rec->sw_io += bytes; - if (rec->sw_io >= rec->sw_buffer_size) - rec->sw_io -= - rec->sw_buffer_size; - } - } - } - rec->min_period_count += bytes; - if (rec->min_period_count >= (rec->hw_buffer_size / 2)) { - rec->min_periods += (rec->min_period_count / - (rec->hw_buffer_size / 2)); -#ifdef SND_PCM_INDIRECT2_STAT - if ((rec->min_period_count / - (rec->hw_buffer_size / 2)) > 7) - snd_printk(KERN_DEBUG - "STAT: more than 7 (%d) min_adds " - "at once - too big to save!\n", - (rec->min_period_count / - (rec->hw_buffer_size / 2))); - else - rec->min_adds[(rec->min_period_count / - (rec->hw_buffer_size / 2))]++; -#endif - rec->min_period_count = (rec->min_period_count % - (rec->hw_buffer_size / 2)); - } - } else if (isplay && iscopy) - rec->min_periods = 0; -} - -/* - * helper function for playback/capture pointer callback - */ -snd_pcm_uframes_t -snd_pcm_indirect2_pointer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec) -{ -#ifdef SND_PCM_INDIRECT2_STAT - rec->pointer_calls++; -#endif - return bytes_to_frames(substream->runtime, rec->sw_io); -} - -/* - * _internal_ helper function for playback interrupt callback - */ -static void -snd_pcm_indirect2_playback_transfer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t zero) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; - - /* runtime->control->appl_ptr: position where ALSA will write next time - * rec->appl_ptr: position where ALSA was last time - * diff: obviously ALSA wrote that much bytes into the intermediate - * buffer since we checked last time - */ - snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr; - - if (diff) { -#ifdef SND_PCM_INDIRECT2_STAT - rec->lastdifftime = jiffies; -#endif - if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) - diff += runtime->boundary; - /* number of bytes "added" by ALSA increases the number of - * bytes which are ready to "be transferred to HW"/"played" - * Then, set rec->appl_ptr to not count bytes twice next time. - */ - rec->sw_ready += (int)frames_to_bytes(runtime, diff); - rec->appl_ptr = appl_ptr; - } - if (rec->hw_ready && (rec->sw_ready <= 0)) { - unsigned int bytes; - -#ifdef SND_PCM_INDIRECT2_STAT - if (rec->firstzerotime == 0) { - rec->firstzerotime = jiffies; - snd_printk(KERN_DEBUG - "STAT: @firstzerotime: mul_elapsed: %d, " - "min_period_count: %d\n", - rec->mul_elapsed, rec->min_period_count); - snd_printk(KERN_DEBUG - "STAT: @firstzerotime: sw_io: %d, " - "sw_data: %d, appl_ptr: %u\n", - rec->sw_io, rec->sw_data, - (unsigned int)appl_ptr); - } - if ((jiffies - rec->firstzerotime) < 3750) { - rec->zero_times[(jiffies - rec->firstzerotime)]++; - rec->zero_times_saved++; - } else - rec->zero_times_notsaved++; -#endif - bytes = zero(substream, rec); - -#ifdef SND_PCM_INDIRECT2_STAT - rec->zeros2hw += bytes; - if (bytes < 64) - rec->zero_sizes[bytes]++; - else - snd_printk(KERN_DEBUG - "STAT: %d zero Bytes copied to hardware at " - "once - too big to save!\n", - bytes); -#endif - snd_pcm_indirect2_increase_min_periods(substream, rec, 1, 0, - bytes); - return; - } - while (rec->hw_ready && (rec->sw_ready > 0)) { - /* sw_to_end: max. number of bytes that can be read/take from - * the current position (sw_data) in _one_ step - */ - unsigned int sw_to_end = rec->sw_buffer_size - rec->sw_data; - - /* bytes: number of bytes we have available (for reading) */ - unsigned int bytes = rec->sw_ready; - - if (sw_to_end < bytes) - bytes = sw_to_end; - if (!bytes) - break; - -#ifdef SND_PCM_INDIRECT2_STAT - if (rec->firstbytetime == 0) - rec->firstbytetime = jiffies; - rec->lastbytetime = jiffies; -#endif - /* copy bytes from intermediate buffer position sw_data to the - * HW and return number of bytes actually written - * Furthermore, set hw_ready to 0, if the fifo isn't empty - * now => more could be transferred to fifo - */ - bytes = copy(substream, rec, bytes); - rec->bytes2hw += bytes; - -#ifdef SND_PCM_INDIRECT2_STAT - if (bytes < 64) - rec->byte_sizes[bytes]++; - else - snd_printk(KERN_DEBUG - "STAT: %d Bytes copied to hardware at once " - "- too big to save!\n", - bytes); -#endif - /* increase sw_data by the number of actually written bytes - * (= number of taken bytes from intermediate buffer) - */ - rec->sw_data += bytes; - if (rec->sw_data == rec->sw_buffer_size) - rec->sw_data = 0; - /* now sw_data is the position where ALSA is going to write - * in the intermediate buffer next time = position we are going - * to read from next time - */ - - snd_pcm_indirect2_increase_min_periods(substream, rec, 1, 1, - bytes); - - /* we read bytes from intermediate buffer, so we need to say - * that the number of bytes ready for transfer are decreased - * now - */ - rec->sw_ready -= bytes; - } - return; -} - -/* - * helper function for playback interrupt routine - */ -void -snd_pcm_indirect2_playback_interrupt(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t zero) -{ -#ifdef SND_PCM_INDIRECT2_STAT - rec->irq_occured++; -#endif - /* hardware played some bytes, so there is room again (in fifo) */ - rec->hw_ready = 1; - - /* don't call ack() now, instead call transfer() function directly - * (normally called by ack() ) - */ - snd_pcm_indirect2_playback_transfer(substream, rec, copy, zero); - - if (rec->min_periods >= rec->min_multiple) { -#ifdef SND_PCM_INDIRECT2_STAT - if ((rec->min_periods / rec->min_multiple) > 7) - snd_printk(KERN_DEBUG - "STAT: more than 7 (%d) mul_adds - too big " - "to save!\n", - (rec->min_periods / rec->min_multiple)); - else - rec->mul_adds[(rec->min_periods / - rec->min_multiple)]++; - rec->mul_elapsed_real += (rec->min_periods / - rec->min_multiple); - rec->mul_elapsed++; -#endif - rec->min_periods = (rec->min_periods % rec->min_multiple); - snd_pcm_period_elapsed(substream); - } -} - -/* - * _internal_ helper function for capture interrupt callback - */ -static void -snd_pcm_indirect2_capture_transfer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t null) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr; - snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr; - - if (diff) { -#ifdef SND_PCM_INDIRECT2_STAT - rec->lastdifftime = jiffies; -#endif - if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2)) - diff += runtime->boundary; - rec->sw_ready -= frames_to_bytes(runtime, diff); - rec->appl_ptr = appl_ptr; - } - /* if hardware has something, but the intermediate buffer is full - * => skip contents of buffer - */ - if (rec->hw_ready && (rec->sw_ready >= (int)rec->sw_buffer_size)) { - unsigned int bytes; - -#ifdef SND_PCM_INDIRECT2_STAT - if (rec->firstzerotime == 0) { - rec->firstzerotime = jiffies; - snd_printk(KERN_DEBUG "STAT: (capture) " - "@firstzerotime: mul_elapsed: %d, " - "min_period_count: %d\n", - rec->mul_elapsed, rec->min_period_count); - snd_printk(KERN_DEBUG "STAT: (capture) " - "@firstzerotime: sw_io: %d, sw_data: %d, " - "appl_ptr: %u\n", - rec->sw_io, rec->sw_data, - (unsigned int)appl_ptr); - } - if ((jiffies - rec->firstzerotime) < 3750) { - rec->zero_times[(jiffies - rec->firstzerotime)]++; - rec->zero_times_saved++; - } else - rec->zero_times_notsaved++; -#endif - bytes = null(substream, rec); - -#ifdef SND_PCM_INDIRECT2_STAT - rec->zeros2hw += bytes; - if (bytes < 64) - rec->zero_sizes[bytes]++; - else - snd_printk(KERN_DEBUG - "STAT: (capture) %d zero Bytes copied to " - "hardware at once - too big to save!\n", - bytes); -#endif - snd_pcm_indirect2_increase_min_periods(substream, rec, 0, 0, - bytes); - /* report an overrun */ - rec->sw_io = SNDRV_PCM_POS_XRUN; - return; - } - while (rec->hw_ready && (rec->sw_ready < (int)rec->sw_buffer_size)) { - /* sw_to_end: max. number of bytes that we can write to the - * intermediate buffer (until it's end) - */ - size_t sw_to_end = rec->sw_buffer_size - rec->sw_data; - - /* bytes: max. number of bytes, which may be copied to the - * intermediate buffer without overflow (in _one_ step) - */ - size_t bytes = rec->sw_buffer_size - rec->sw_ready; - - /* limit number of bytes (for transfer) by available room in - * the intermediate buffer - */ - if (sw_to_end < bytes) - bytes = sw_to_end; - if (!bytes) - break; - -#ifdef SND_PCM_INDIRECT2_STAT - if (rec->firstbytetime == 0) - rec->firstbytetime = jiffies; - rec->lastbytetime = jiffies; -#endif - /* copy bytes from the intermediate buffer (position sw_data) - * to the HW at most and return number of bytes actually copied - * from HW - * Furthermore, set hw_ready to 0, if the fifo is empty now. - */ - bytes = copy(substream, rec, bytes); - rec->bytes2hw += bytes; - -#ifdef SND_PCM_INDIRECT2_STAT - if (bytes < 64) - rec->byte_sizes[bytes]++; - else - snd_printk(KERN_DEBUG - "STAT: (capture) %d Bytes copied to " - "hardware at once - too big to save!\n", - bytes); -#endif - /* increase sw_data by the number of actually copied bytes from - * HW - */ - rec->sw_data += bytes; - if (rec->sw_data == rec->sw_buffer_size) - rec->sw_data = 0; - - snd_pcm_indirect2_increase_min_periods(substream, rec, 0, 1, - bytes); - - /* number of bytes in the intermediate buffer, which haven't - * been fetched by ALSA yet. - */ - rec->sw_ready += bytes; - } - return; -} - -/* - * helper function for capture interrupt routine - */ -void -snd_pcm_indirect2_capture_interrupt(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t null) -{ -#ifdef SND_PCM_INDIRECT2_STAT - rec->irq_occured++; -#endif - /* hardware recorded some bytes, so there is something to read from the - * record fifo: - */ - rec->hw_ready = 1; - - /* don't call ack() now, instead call transfer() function directly - * (normally called by ack() ) - */ - snd_pcm_indirect2_capture_transfer(substream, rec, copy, null); - - if (rec->min_periods >= rec->min_multiple) { - -#ifdef SND_PCM_INDIRECT2_STAT - if ((rec->min_periods / rec->min_multiple) > 7) - snd_printk(KERN_DEBUG - "STAT: more than 7 (%d) mul_adds - " - "too big to save!\n", - (rec->min_periods / rec->min_multiple)); - else - rec->mul_adds[(rec->min_periods / - rec->min_multiple)]++; - rec->mul_elapsed_real += (rec->min_periods / - rec->min_multiple); - rec->mul_elapsed++; -#endif - rec->min_periods = (rec->min_periods % rec->min_multiple); - snd_pcm_period_elapsed(substream); - } -} diff --git a/ANDROID_3.4.5/sound/drivers/pcm-indirect2.h b/ANDROID_3.4.5/sound/drivers/pcm-indirect2.h deleted file mode 100644 index 2ea6e460..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcm-indirect2.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Helper functions for indirect PCM data transfer to a simple FIFO in - * hardware (small, no possibility to read "hardware io position", - * updating position done by interrupt, ...) - * - * Copyright (c) by 2007 Joachim Foerster - * - * Based on "pcm-indirect.h" (alsa-driver-1.0.13) by - * - * Copyright (c) by Takashi Iwai - * Jaroslav Kysela - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __SOUND_PCM_INDIRECT2_H -#define __SOUND_PCM_INDIRECT2_H - -/* struct snd_pcm_substream, struct snd_pcm_runtime, snd_pcm_uframes_t */ -#include - -/* Debug options for code which may be removed completely in a final version */ -#ifdef CONFIG_SND_DEBUG -#define SND_PCM_INDIRECT2_STAT /* turn on some "statistics" about the - * process of copying bytes from the - * intermediate buffer to the hardware - * fifo and the other way round - */ -#endif - -struct snd_pcm_indirect2 { - unsigned int hw_buffer_size; /* Byte size of hardware buffer */ - int hw_ready; /* playback: 1 = hw fifo has room left, - * 0 = hw fifo is full - */ - unsigned int min_multiple; - int min_periods; /* counts number of min. periods until - * min_multiple is reached - */ - int min_period_count; /* counts bytes to count number of - * min. periods - */ - - unsigned int sw_buffer_size; /* Byte size of software buffer */ - - /* sw_data: position in intermediate buffer, where we will read (or - * write) from/to next time (to transfer data to/from HW) - */ - unsigned int sw_data; /* Offset to next dst (or src) in sw - * ring buffer - */ - /* easiest case (playback): - * sw_data is nearly the same as ~ runtime->control->appl_ptr, with the - * exception that sw_data is "behind" by the number if bytes ALSA wrote - * to the intermediate buffer last time. - * A call to ack() callback synchronizes both indirectly. - */ - - /* We have no real sw_io pointer here. Usually sw_io is pointing to the - * current playback/capture position _inside_ the hardware. Devices - * with plain FIFOs often have no possibility to publish this position. - * So we say: if sw_data is updated, that means bytes were copied to - * the hardware, we increase sw_io by that amount, because there have - * to be as much bytes which were played. So sw_io will stay behind - * sw_data all the time and has to converge to sw_data at the end of - * playback. - */ - unsigned int sw_io; /* Current software pointer in bytes */ - - /* sw_ready: number of bytes ALSA copied to the intermediate buffer, so - * it represents the number of bytes which wait for transfer to the HW - */ - int sw_ready; /* Bytes ready to be transferred to/from hw */ - - /* appl_ptr: last known position of ALSA (where ALSA is going to write - * next time into the intermediate buffer - */ - snd_pcm_uframes_t appl_ptr; /* Last seen appl_ptr */ - - unsigned int bytes2hw; - int check_alignment; - -#ifdef SND_PCM_INDIRECT2_STAT - unsigned int zeros2hw; - unsigned int mul_elapsed; - unsigned int mul_elapsed_real; - unsigned long firstbytetime; - unsigned long lastbytetime; - unsigned long firstzerotime; - unsigned int byte_sizes[64]; - unsigned int zero_sizes[64]; - unsigned int min_adds[8]; - unsigned int mul_adds[8]; - unsigned int zero_times[3750]; /* = 15s */ - unsigned int zero_times_saved; - unsigned int zero_times_notsaved; - unsigned int irq_occured; - unsigned int pointer_calls; - unsigned int lastdifftime; -#endif -}; - -typedef size_t (*snd_pcm_indirect2_copy_t) (struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - size_t bytes); -typedef size_t (*snd_pcm_indirect2_zero_t) (struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec); - -#ifdef SND_PCM_INDIRECT2_STAT -void snd_pcm_indirect2_stat(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec); -#endif - -snd_pcm_uframes_t -snd_pcm_indirect2_pointer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec); -void -snd_pcm_indirect2_playback_interrupt(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t zero); -void -snd_pcm_indirect2_capture_interrupt(struct snd_pcm_substream *substream, - struct snd_pcm_indirect2 *rec, - snd_pcm_indirect2_copy_t copy, - snd_pcm_indirect2_zero_t null); - -#endif /* __SOUND_PCM_INDIRECT2_H */ diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/Makefile b/ANDROID_3.4.5/sound/drivers/pcsp/Makefile deleted file mode 100644 index b19555b4..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -snd-pcsp-objs := pcsp.o pcsp_lib.o pcsp_mixer.o pcsp_input.o -obj-$(CONFIG_SND_PCSP) += snd-pcsp.o diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.c b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.c deleted file mode 100644 index 99704e6a..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Copyright (C) 1997-2001 David Woodhouse - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pcsp_input.h" -#include "pcsp.h" - -MODULE_AUTHOR("Stas Sergeev "); -MODULE_DESCRIPTION("PC-Speaker driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{PC-Speaker, pcsp}}"); -MODULE_ALIAS("platform:pcspkr"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ -static bool nopcm; /* Disable PCM capability of the driver */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for pcsp soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for pcsp soundcard."); -module_param(enable, bool, 0444); -MODULE_PARM_DESC(enable, "Enable PC-Speaker sound."); -module_param(nopcm, bool, 0444); -MODULE_PARM_DESC(nopcm, "Disable PC-Speaker PCM sound. Only beeps remain."); - -struct snd_pcsp pcsp_chip; - -static int __devinit snd_pcsp_create(struct snd_card *card) -{ - static struct snd_device_ops ops = { }; - struct timespec tp; - int err; - int div, min_div, order; - - if (!nopcm) { - hrtimer_get_res(CLOCK_MONOTONIC, &tp); - if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) { - printk(KERN_ERR "PCSP: Timer resolution is not sufficient " - "(%linS)\n", tp.tv_nsec); - printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " - "enabled.\n"); - printk(KERN_ERR "PCSP: Turned into nopcm mode.\n"); - nopcm = 1; - } - } - - if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS) - min_div = MIN_DIV; - else - min_div = MAX_DIV; -#if PCSP_DEBUG - printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%li\n", - loops_per_jiffy, min_div, tp.tv_nsec); -#endif - - div = MAX_DIV / min_div; - order = fls(div) - 1; - - pcsp_chip.max_treble = min(order, PCSP_MAX_TREBLE); - pcsp_chip.treble = min(pcsp_chip.max_treble, PCSP_DEFAULT_TREBLE); - pcsp_chip.playback_ptr = 0; - pcsp_chip.period_ptr = 0; - atomic_set(&pcsp_chip.timer_active, 0); - pcsp_chip.enable = 1; - pcsp_chip.pcspkr = 1; - - spin_lock_init(&pcsp_chip.substream_lock); - - pcsp_chip.card = card; - pcsp_chip.port = 0x61; - pcsp_chip.irq = -1; - pcsp_chip.dma = -1; - - /* Register device */ - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, &pcsp_chip, &ops); - if (err < 0) - return err; - - return 0; -} - -static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) -{ - struct snd_card *card; - int err; - - if (devnum != 0) - return -EINVAL; - - hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - pcsp_chip.timer.function = pcsp_do_timer; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_pcsp_create(card); - if (err < 0) { - snd_card_free(card); - return err; - } - if (!nopcm) { - err = snd_pcsp_new_pcm(&pcsp_chip); - if (err < 0) { - snd_card_free(card); - return err; - } - } - err = snd_pcsp_new_mixer(&pcsp_chip, nopcm); - if (err < 0) { - snd_card_free(card); - return err; - } - - snd_card_set_dev(pcsp_chip.card, dev); - - strcpy(card->driver, "PC-Speaker"); - strcpy(card->shortname, "pcsp"); - sprintf(card->longname, "Internal PC-Speaker at port 0x%x", - pcsp_chip.port); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - - return 0; -} - -static int __devinit alsa_card_pcsp_init(struct device *dev) -{ - int err; - - err = snd_card_pcsp_probe(0, dev); - if (err) { - printk(KERN_ERR "PC-Speaker initialization failed.\n"); - return err; - } - -#ifdef CONFIG_DEBUG_PAGEALLOC - /* Well, CONFIG_DEBUG_PAGEALLOC makes the sound horrible. Lets alert */ - printk(KERN_WARNING "PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, " - "which may make the sound noisy.\n"); -#endif - - return 0; -} - -static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip) -{ - snd_card_free(chip->card); -} - -static int __devinit pcsp_probe(struct platform_device *dev) -{ - int err; - - err = pcspkr_input_init(&pcsp_chip.input_dev, &dev->dev); - if (err < 0) - return err; - - err = alsa_card_pcsp_init(&dev->dev); - if (err < 0) { - pcspkr_input_remove(pcsp_chip.input_dev); - return err; - } - - platform_set_drvdata(dev, &pcsp_chip); - return 0; -} - -static int __devexit pcsp_remove(struct platform_device *dev) -{ - struct snd_pcsp *chip = platform_get_drvdata(dev); - alsa_card_pcsp_exit(chip); - pcspkr_input_remove(chip->input_dev); - platform_set_drvdata(dev, NULL); - return 0; -} - -static void pcsp_stop_beep(struct snd_pcsp *chip) -{ - pcsp_sync_stop(chip); - pcspkr_stop_sound(); -} - -#ifdef CONFIG_PM -static int pcsp_suspend(struct platform_device *dev, pm_message_t state) -{ - struct snd_pcsp *chip = platform_get_drvdata(dev); - pcsp_stop_beep(chip); - snd_pcm_suspend_all(chip->pcm); - return 0; -} -#else -#define pcsp_suspend NULL -#endif /* CONFIG_PM */ - -static void pcsp_shutdown(struct platform_device *dev) -{ - struct snd_pcsp *chip = platform_get_drvdata(dev); - pcsp_stop_beep(chip); -} - -static struct platform_driver pcsp_platform_driver = { - .driver = { - .name = "pcspkr", - .owner = THIS_MODULE, - }, - .probe = pcsp_probe, - .remove = __devexit_p(pcsp_remove), - .suspend = pcsp_suspend, - .shutdown = pcsp_shutdown, -}; - -static int __init pcsp_init(void) -{ - if (!enable) - return -ENODEV; - return platform_driver_register(&pcsp_platform_driver); -} - -static void __exit pcsp_exit(void) -{ - platform_driver_unregister(&pcsp_platform_driver); -} - -module_init(pcsp_init); -module_exit(pcsp_exit); diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.h b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.h deleted file mode 100644 index fc7a2dc4..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Copyright (C) 1993-1997 Michael Beck - * Copyright (C) 1997-2001 David Woodhouse - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#ifndef __PCSP_H__ -#define __PCSP_H__ - -#include -#include -#include - -#define PCSP_SOUND_VERSION 0x400 /* read 4.00 */ -#define PCSP_DEBUG 0 - -/* default timer freq for PC-Speaker: 18643 Hz */ -#define DIV_18KHZ 64 -#define MAX_DIV DIV_18KHZ -#define CALC_DIV(d) (MAX_DIV >> (d)) -#define CUR_DIV() CALC_DIV(chip->treble) -#define PCSP_MAX_TREBLE 1 - -/* unfortunately, with hrtimers 37KHz does not work very well :( */ -#define PCSP_DEFAULT_TREBLE 0 -#define MIN_DIV (MAX_DIV >> PCSP_MAX_TREBLE) - -/* wild guess */ -#define PCSP_MIN_LPJ 1000000 -#define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1) -#define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV) -#define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble)) -#define PCSP_CALC_RATE(i) (PIT_TICK_RATE / CALC_DIV(i)) -#define PCSP_RATE() PCSP_CALC_RATE(chip->treble) -#define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE -#define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE -#define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1) -#define PCSP_MIN_PERIOD_NS (1000000000ULL * PCSP_MAX_RATE__1) -#define PCSP_CALC_NS(div) ({ \ - u64 __val = 1000000000ULL * (div); \ - do_div(__val, PIT_TICK_RATE); \ - __val; \ -}) -#define PCSP_PERIOD_NS() PCSP_CALC_NS(CUR_DIV()) - -#define PCSP_MAX_PERIOD_SIZE (64*1024) -#define PCSP_MAX_PERIODS 512 -#define PCSP_BUFFER_SIZE (128*1024) - -struct snd_pcsp { - struct snd_card *card; - struct snd_pcm *pcm; - struct input_dev *input_dev; - struct hrtimer timer; - unsigned short port, irq, dma; - spinlock_t substream_lock; - struct snd_pcm_substream *playback_substream; - unsigned int fmt_size; - unsigned int is_signed; - size_t playback_ptr; - size_t period_ptr; - atomic_t timer_active; - int thalf; - u64 ns_rem; - unsigned char val61; - int enable; - int max_treble; - int treble; - int pcspkr; -}; - -extern struct snd_pcsp pcsp_chip; - -extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); -extern void pcsp_sync_stop(struct snd_pcsp *chip); - -extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); -extern int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm); - -#endif diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.c b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.c deleted file mode 100644 index b5e2b54c..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * PC Speaker beeper driver for Linux - * - * Copyright (c) 2002 Vojtech Pavlik - * Copyright (c) 1992 Orest Zborowski - * - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation - */ - -#include -#include -#include -#include "pcsp.h" - -static void pcspkr_do_sound(unsigned int count) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&i8253_lock, flags); - - if (count) { - /* set command for counter 2, 2 byte write */ - outb_p(0xB6, 0x43); - /* select desired HZ */ - outb_p(count & 0xff, 0x42); - outb((count >> 8) & 0xff, 0x42); - /* enable counter 2 */ - outb_p(inb_p(0x61) | 3, 0x61); - } else { - /* disable counter 2 */ - outb(inb_p(0x61) & 0xFC, 0x61); - } - - raw_spin_unlock_irqrestore(&i8253_lock, flags); -} - -void pcspkr_stop_sound(void) -{ - pcspkr_do_sound(0); -} - -static int pcspkr_input_event(struct input_dev *dev, unsigned int type, - unsigned int code, int value) -{ - unsigned int count = 0; - - if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr) - return 0; - - switch (type) { - case EV_SND: - switch (code) { - case SND_BELL: - if (value) - value = 1000; - case SND_TONE: - break; - default: - return -1; - } - break; - - default: - return -1; - } - - if (value > 20 && value < 32767) - count = PIT_TICK_RATE / value; - - pcspkr_do_sound(count); - - return 0; -} - -int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev) -{ - int err; - - struct input_dev *input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - - input_dev->name = "PC Speaker"; - input_dev->phys = "isa0061/input0"; - input_dev->id.bustype = BUS_ISA; - input_dev->id.vendor = 0x001f; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - input_dev->dev.parent = dev; - - input_dev->evbit[0] = BIT(EV_SND); - input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); - input_dev->event = pcspkr_input_event; - - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } - - *rdev = input_dev; - return 0; -} - -int pcspkr_input_remove(struct input_dev *dev) -{ - pcspkr_stop_sound(); - input_unregister_device(dev); /* this also does kfree() */ - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.h b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.h deleted file mode 100644 index e66738c7..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_input.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#ifndef __PCSP_INPUT_H__ -#define __PCSP_INPUT_H__ - -int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev); -int pcspkr_input_remove(struct input_dev *dev); -void pcspkr_stop_sound(void); - -#endif diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_lib.c b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_lib.c deleted file mode 100644 index 434981dd..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_lib.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Copyright (C) 1993-1997 Michael Beck - * Copyright (C) 1997-2001 David Woodhouse - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#include -#include -#include -#include -#include -#include -#include "pcsp.h" - -static bool nforce_wa; -module_param(nforce_wa, bool, 0444); -MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " - "(expect bad sound)"); - -#define DMIX_WANTS_S16 1 - -/* - * Call snd_pcm_period_elapsed in a tasklet - * This avoids spinlock messes and long-running irq contexts - */ -static void pcsp_call_pcm_elapsed(unsigned long priv) -{ - if (atomic_read(&pcsp_chip.timer_active)) { - struct snd_pcm_substream *substream; - substream = pcsp_chip.playback_substream; - if (substream) - snd_pcm_period_elapsed(substream); - } -} - -static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0); - -/* write the port and returns the next expire time in ns; - * called at the trigger-start and in hrtimer callback - */ -static u64 pcsp_timer_update(struct snd_pcsp *chip) -{ - unsigned char timer_cnt, val; - u64 ns; - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - unsigned long flags; - - if (chip->thalf) { - outb(chip->val61, 0x61); - chip->thalf = 0; - return chip->ns_rem; - } - - substream = chip->playback_substream; - if (!substream) - return 0; - - runtime = substream->runtime; - /* assume it is mono! */ - val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1]; - if (chip->is_signed) - val ^= 0x80; - timer_cnt = val * CUR_DIV() / 256; - - if (timer_cnt && chip->enable) { - raw_spin_lock_irqsave(&i8253_lock, flags); - if (!nforce_wa) { - outb_p(chip->val61, 0x61); - outb_p(timer_cnt, 0x42); - outb(chip->val61 ^ 1, 0x61); - } else { - outb(chip->val61 ^ 2, 0x61); - chip->thalf = 1; - } - raw_spin_unlock_irqrestore(&i8253_lock, flags); - } - - chip->ns_rem = PCSP_PERIOD_NS(); - ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); - chip->ns_rem -= ns; - return ns; -} - -static void pcsp_pointer_update(struct snd_pcsp *chip) -{ - struct snd_pcm_substream *substream; - size_t period_bytes, buffer_bytes; - int periods_elapsed; - unsigned long flags; - - /* update the playback position */ - substream = chip->playback_substream; - if (!substream) - return; - - period_bytes = snd_pcm_lib_period_bytes(substream); - buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - - spin_lock_irqsave(&chip->substream_lock, flags); - chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size; - periods_elapsed = chip->playback_ptr - chip->period_ptr; - if (periods_elapsed < 0) { -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: buffer_bytes mod period_bytes != 0 ? " - "(%zi %zi %zi)\n", - chip->playback_ptr, period_bytes, buffer_bytes); -#endif - periods_elapsed += buffer_bytes; - } - periods_elapsed /= period_bytes; - /* wrap the pointer _before_ calling snd_pcm_period_elapsed(), - * or ALSA will BUG on us. */ - chip->playback_ptr %= buffer_bytes; - - if (periods_elapsed) { - chip->period_ptr += periods_elapsed * period_bytes; - chip->period_ptr %= buffer_bytes; - } - spin_unlock_irqrestore(&chip->substream_lock, flags); - - if (periods_elapsed) - tasklet_schedule(&pcsp_pcm_tasklet); -} - -enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) -{ - struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); - int pointer_update; - u64 ns; - - if (!atomic_read(&chip->timer_active) || !chip->playback_substream) - return HRTIMER_NORESTART; - - pointer_update = !chip->thalf; - ns = pcsp_timer_update(chip); - if (!ns) { - printk(KERN_WARNING "PCSP: unexpected stop\n"); - return HRTIMER_NORESTART; - } - - if (pointer_update) - pcsp_pointer_update(chip); - - hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns)); - - return HRTIMER_RESTART; -} - -static int pcsp_start_playing(struct snd_pcsp *chip) -{ -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: start_playing called\n"); -#endif - if (atomic_read(&chip->timer_active)) { - printk(KERN_ERR "PCSP: Timer already active\n"); - return -EIO; - } - - raw_spin_lock(&i8253_lock); - chip->val61 = inb(0x61) | 0x03; - outb_p(0x92, 0x43); /* binary, mode 1, LSB only, ch 2 */ - raw_spin_unlock(&i8253_lock); - atomic_set(&chip->timer_active, 1); - chip->thalf = 0; - - hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); - return 0; -} - -static void pcsp_stop_playing(struct snd_pcsp *chip) -{ -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: stop_playing called\n"); -#endif - if (!atomic_read(&chip->timer_active)) - return; - - atomic_set(&chip->timer_active, 0); - raw_spin_lock(&i8253_lock); - /* restore the timer */ - outb_p(0xb6, 0x43); /* binary, mode 3, LSB/MSB, ch 2 */ - outb(chip->val61 & 0xFC, 0x61); - raw_spin_unlock(&i8253_lock); -} - -/* - * Force to stop and sync the stream - */ -void pcsp_sync_stop(struct snd_pcsp *chip) -{ - local_irq_disable(); - pcsp_stop_playing(chip); - local_irq_enable(); - hrtimer_cancel(&chip->timer); - tasklet_kill(&pcsp_pcm_tasklet); -} - -static int snd_pcsp_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: close called\n"); -#endif - pcsp_sync_stop(chip); - chip->playback_substream = NULL; - return 0; -} - -static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - int err; - pcsp_sync_stop(chip); - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - return 0; -} - -static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: hw_free called\n"); -#endif - pcsp_sync_stop(chip); - return snd_pcm_lib_free_pages(substream); -} - -static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - pcsp_sync_stop(chip); - chip->playback_ptr = 0; - chip->period_ptr = 0; - chip->fmt_size = - snd_pcm_format_physical_width(substream->runtime->format) >> 3; - chip->is_signed = snd_pcm_format_signed(substream->runtime->format); -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: prepare called, " - "size=%zi psize=%zi f=%zi f1=%i fsize=%i\n", - snd_pcm_lib_buffer_bytes(substream), - snd_pcm_lib_period_bytes(substream), - snd_pcm_lib_buffer_bytes(substream) / - snd_pcm_lib_period_bytes(substream), - substream->runtime->periods, - chip->fmt_size); -#endif - return 0; -} - -static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: trigger called\n"); -#endif - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - return pcsp_start_playing(chip); - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - pcsp_stop_playing(chip); - break; - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream - *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - unsigned int pos; - spin_lock(&chip->substream_lock); - pos = chip->playback_ptr; - spin_unlock(&chip->substream_lock); - return bytes_to_frames(substream->runtime, pos); -} - -static struct snd_pcm_hardware snd_pcsp_playback = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_HALF_DUPLEX | - SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_U8 -#if DMIX_WANTS_S16 - | SNDRV_PCM_FMTBIT_S16_LE -#endif - ), - .rates = SNDRV_PCM_RATE_KNOT, - .rate_min = PCSP_DEFAULT_SRATE, - .rate_max = PCSP_DEFAULT_SRATE, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = PCSP_BUFFER_SIZE, - .period_bytes_min = 64, - .period_bytes_max = PCSP_MAX_PERIOD_SIZE, - .periods_min = 2, - .periods_max = PCSP_MAX_PERIODS, - .fifo_size = 0, -}; - -static int snd_pcsp_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcsp *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: open called\n"); -#endif - if (atomic_read(&chip->timer_active)) { - printk(KERN_ERR "PCSP: still active!!\n"); - return -EBUSY; - } - runtime->hw = snd_pcsp_playback; - chip->playback_substream = substream; - return 0; -} - -static struct snd_pcm_ops snd_pcsp_playback_ops = { - .open = snd_pcsp_playback_open, - .close = snd_pcsp_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_pcsp_playback_hw_params, - .hw_free = snd_pcsp_playback_hw_free, - .prepare = snd_pcsp_playback_prepare, - .trigger = snd_pcsp_trigger, - .pointer = snd_pcsp_playback_pointer, -}; - -int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip) -{ - int err; - - err = snd_pcm_new(chip->card, "pcspeaker", 0, 1, 0, &chip->pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(chip->pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_pcsp_playback_ops); - - chip->pcm->private_data = chip; - chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - strcpy(chip->pcm->name, "pcsp"); - - snd_pcm_lib_preallocate_pages_for_all(chip->pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data - (GFP_KERNEL), PCSP_BUFFER_SIZE, - PCSP_BUFFER_SIZE); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_mixer.c b/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_mixer.c deleted file mode 100644 index 6f633f4f..00000000 --- a/ANDROID_3.4.5/sound/drivers/pcsp/pcsp_mixer.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * PC-Speaker driver for Linux - * - * Mixer implementation. - * Copyright (C) 2001-2008 Stas Sergeev - */ - -#include -#include -#include "pcsp.h" - - -static int pcsp_enable_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int pcsp_enable_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->enable; - return 0; -} - -static int pcsp_enable_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int enab = ucontrol->value.integer.value[0]; - if (enab != chip->enable) { - chip->enable = enab; - changed = 1; - } - return changed; -} - -static int pcsp_treble_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = chip->max_treble + 1; - if (uinfo->value.enumerated.item > chip->max_treble) - uinfo->value.enumerated.item = chip->max_treble; - sprintf(uinfo->value.enumerated.name, "%lu", - (unsigned long)PCSP_CALC_RATE(uinfo->value.enumerated.item)); - return 0; -} - -static int pcsp_treble_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = chip->treble; - return 0; -} - -static int pcsp_treble_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int treble = ucontrol->value.enumerated.item[0]; - if (treble != chip->treble) { - chip->treble = treble; -#if PCSP_DEBUG - printk(KERN_INFO "PCSP: rate set to %li\n", PCSP_RATE()); -#endif - changed = 1; - } - return changed; -} - -static int pcsp_pcspkr_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int pcsp_pcspkr_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->pcspkr; - return 0; -} - -static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcsp *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int spkr = ucontrol->value.integer.value[0]; - if (spkr != chip->pcspkr) { - chip->pcspkr = spkr; - changed = 1; - } - return changed; -} - -#define PCSP_MIXER_CONTROL(ctl_type, ctl_name) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = ctl_name, \ - .info = pcsp_##ctl_type##_info, \ - .get = pcsp_##ctl_type##_get, \ - .put = pcsp_##ctl_type##_put, \ -} - -static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_pcm[] = { - PCSP_MIXER_CONTROL(enable, "Master Playback Switch"), - PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"), -}; - -static struct snd_kcontrol_new __devinitdata snd_pcsp_controls_spkr[] = { - PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"), -}; - -static int __devinit snd_pcsp_ctls_add(struct snd_pcsp *chip, - struct snd_kcontrol_new *ctls, int num) -{ - int i, err; - struct snd_card *card = chip->card; - for (i = 0; i < num; i++) { - err = snd_ctl_add(card, snd_ctl_new1(ctls + i, chip)); - if (err < 0) - return err; - } - return 0; -} - -int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm) -{ - int err; - struct snd_card *card = chip->card; - - if (!nopcm) { - err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_pcm, - ARRAY_SIZE(snd_pcsp_controls_pcm)); - if (err < 0) - return err; - } - err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_spkr, - ARRAY_SIZE(snd_pcsp_controls_spkr)); - if (err < 0) - return err; - - strcpy(card->mixername, "PC-Speaker"); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/portman2x4.c b/ANDROID_3.4.5/sound/drivers/portman2x4.c deleted file mode 100644 index 3e32bd3d..00000000 --- a/ANDROID_3.4.5/sound/drivers/portman2x4.c +++ /dev/null @@ -1,879 +0,0 @@ -/* - * Driver for Midiman Portman2x4 parallel port midi interface - * - * Copyright (c) by Levent Guendogdu - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * ChangeLog - * Jan 24 2007 Matthias Koenig - * - cleanup and rewrite - * Sep 30 2004 Tobias Gehrig - * - source code cleanup - * Sep 03 2004 Tobias Gehrig - * - fixed compilation problem with alsa 1.0.6a (removed MODULE_CLASSES, - * MODULE_PARM_SYNTAX and changed MODULE_DEVICES to - * MODULE_SUPPORTED_DEVICE) - * Mar 24 2004 Tobias Gehrig - * - added 2.6 kernel support - * Mar 18 2004 Tobias Gehrig - * - added parport_unregister_driver to the startup routine if the driver fails to detect a portman - * - added support for all 4 output ports in portman_putmidi - * Mar 17 2004 Tobias Gehrig - * - added checks for opened input device in interrupt handler - * Feb 20 2004 Tobias Gehrig - * - ported from alsa 0.5 to 1.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CARD_NAME "Portman 2x4" -#define DRIVER_NAME "portman" -#define PLATFORM_DRIVER "snd_portman2x4" - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -static struct platform_device *platform_devices[SNDRV_CARDS]; -static int device_count; - -module_param_array(index, int, NULL, S_IRUGO); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, S_IRUGO); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, S_IRUGO); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - -MODULE_AUTHOR("Levent Guendogdu, Tobias Gehrig, Matthias Koenig"); -MODULE_DESCRIPTION("Midiman Portman2x4"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Midiman,Portman2x4}}"); - -/********************************************************************* - * Chip specific - *********************************************************************/ -#define PORTMAN_NUM_INPUT_PORTS 2 -#define PORTMAN_NUM_OUTPUT_PORTS 4 - -struct portman { - spinlock_t reg_lock; - struct snd_card *card; - struct snd_rawmidi *rmidi; - struct pardevice *pardev; - int pardev_claimed; - - int open_count; - int mode[PORTMAN_NUM_INPUT_PORTS]; - struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS]; -}; - -static int portman_free(struct portman *pm) -{ - kfree(pm); - return 0; -} - -static int __devinit portman_create(struct snd_card *card, - struct pardevice *pardev, - struct portman **rchip) -{ - struct portman *pm; - - *rchip = NULL; - - pm = kzalloc(sizeof(struct portman), GFP_KERNEL); - if (pm == NULL) - return -ENOMEM; - - /* Init chip specific data */ - spin_lock_init(&pm->reg_lock); - pm->card = card; - pm->pardev = pardev; - - *rchip = pm; - - return 0; -} - -/********************************************************************* - * HW related constants - *********************************************************************/ - -/* Standard PC parallel port status register equates. */ -#define PP_STAT_BSY 0x80 /* Busy status. Inverted. */ -#define PP_STAT_ACK 0x40 /* Acknowledge. Non-Inverted. */ -#define PP_STAT_POUT 0x20 /* Paper Out. Non-Inverted. */ -#define PP_STAT_SEL 0x10 /* Select. Non-Inverted. */ -#define PP_STAT_ERR 0x08 /* Error. Non-Inverted. */ - -/* Standard PC parallel port command register equates. */ -#define PP_CMD_IEN 0x10 /* IRQ Enable. Non-Inverted. */ -#define PP_CMD_SELI 0x08 /* Select Input. Inverted. */ -#define PP_CMD_INIT 0x04 /* Init Printer. Non-Inverted. */ -#define PP_CMD_FEED 0x02 /* Auto Feed. Inverted. */ -#define PP_CMD_STB 0x01 /* Strobe. Inverted. */ - -/* Parallel Port Command Register as implemented by PCP2x4. */ -#define INT_EN PP_CMD_IEN /* Interrupt enable. */ -#define STROBE PP_CMD_STB /* Command strobe. */ - -/* The parallel port command register field (b1..b3) selects the - * various "registers" within the PC/P 2x4. These are the internal - * address of these "registers" that must be written to the parallel - * port command register. - */ -#define RXDATA0 (0 << 1) /* PCP RxData channel 0. */ -#define RXDATA1 (1 << 1) /* PCP RxData channel 1. */ -#define GEN_CTL (2 << 1) /* PCP General Control Register. */ -#define SYNC_CTL (3 << 1) /* PCP Sync Control Register. */ -#define TXDATA0 (4 << 1) /* PCP TxData channel 0. */ -#define TXDATA1 (5 << 1) /* PCP TxData channel 1. */ -#define TXDATA2 (6 << 1) /* PCP TxData channel 2. */ -#define TXDATA3 (7 << 1) /* PCP TxData channel 3. */ - -/* Parallel Port Status Register as implemented by PCP2x4. */ -#define ESTB PP_STAT_POUT /* Echoed strobe. */ -#define INT_REQ PP_STAT_ACK /* Input data int request. */ -#define BUSY PP_STAT_ERR /* Interface Busy. */ - -/* Parallel Port Status Register BUSY and SELECT lines are multiplexed - * between several functions. Depending on which 2x4 "register" is - * currently selected (b1..b3), the BUSY and SELECT lines are - * assigned as follows: - * - * SELECT LINE: A3 A2 A1 - * -------- - */ -#define RXAVAIL PP_STAT_SEL /* Rx Available, channel 0. 0 0 0 */ -// RXAVAIL1 PP_STAT_SEL /* Rx Available, channel 1. 0 0 1 */ -#define SYNC_STAT PP_STAT_SEL /* Reserved - Sync Status. 0 1 0 */ -// /* Reserved. 0 1 1 */ -#define TXEMPTY PP_STAT_SEL /* Tx Empty, channel 0. 1 0 0 */ -// TXEMPTY1 PP_STAT_SEL /* Tx Empty, channel 1. 1 0 1 */ -// TXEMPTY2 PP_STAT_SEL /* Tx Empty, channel 2. 1 1 0 */ -// TXEMPTY3 PP_STAT_SEL /* Tx Empty, channel 3. 1 1 1 */ - -/* BUSY LINE: A3 A2 A1 - * -------- - */ -#define RXDATA PP_STAT_BSY /* Rx Input Data, channel 0. 0 0 0 */ -// RXDATA1 PP_STAT_BSY /* Rx Input Data, channel 1. 0 0 1 */ -#define SYNC_DATA PP_STAT_BSY /* Reserved - Sync Data. 0 1 0 */ - /* Reserved. 0 1 1 */ -#define DATA_ECHO PP_STAT_BSY /* Parallel Port Data Echo. 1 0 0 */ -#define A0_ECHO PP_STAT_BSY /* Address 0 Echo. 1 0 1 */ -#define A1_ECHO PP_STAT_BSY /* Address 1 Echo. 1 1 0 */ -#define A2_ECHO PP_STAT_BSY /* Address 2 Echo. 1 1 1 */ - -#define PORTMAN2X4_MODE_INPUT_TRIGGERED 0x01 - -/********************************************************************* - * Hardware specific functions - *********************************************************************/ -static inline void portman_write_command(struct portman *pm, u8 value) -{ - parport_write_control(pm->pardev->port, value); -} - -static inline u8 portman_read_command(struct portman *pm) -{ - return parport_read_control(pm->pardev->port); -} - -static inline u8 portman_read_status(struct portman *pm) -{ - return parport_read_status(pm->pardev->port); -} - -static inline u8 portman_read_data(struct portman *pm) -{ - return parport_read_data(pm->pardev->port); -} - -static inline void portman_write_data(struct portman *pm, u8 value) -{ - parport_write_data(pm->pardev->port, value); -} - -static void portman_write_midi(struct portman *pm, - int port, u8 mididata) -{ - int command = ((port + 4) << 1); - - /* Get entering data byte and port number in BL and BH respectively. - * Set up Tx Channel address field for use with PP Cmd Register. - * Store address field in BH register. - * Inputs: AH = Output port number (0..3). - * AL = Data byte. - * command = TXDATA0 | INT_EN; - * Align port num with address field (b1...b3), - * set address for TXDatax, Strobe=0 - */ - command |= INT_EN; - - /* Disable interrupts so that the process is not interrupted, then - * write the address associated with the current Tx channel to the - * PP Command Reg. Do not set the Strobe signal yet. - */ - - do { - portman_write_command(pm, command); - - /* While the address lines settle, write parallel output data to - * PP Data Reg. This has no effect until Strobe signal is asserted. - */ - - portman_write_data(pm, mididata); - - /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP - * Status Register), then go write data. Else go back and wait. - */ - } while ((portman_read_status(pm) & TXEMPTY) != TXEMPTY); - - /* TxEmpty is set. Maintain PC/P destination address and assert - * Strobe through the PP Command Reg. This will Strobe data into - * the PC/P transmitter and set the PC/P BUSY signal. - */ - - portman_write_command(pm, command | STROBE); - - /* Wait for strobe line to settle and echo back through hardware. - * Once it has echoed back, assume that the address and data lines - * have settled! - */ - - while ((portman_read_status(pm) & ESTB) == 0) - cpu_relax(); - - /* Release strobe and immediately re-allow interrupts. */ - portman_write_command(pm, command); - - while ((portman_read_status(pm) & ESTB) == ESTB) - cpu_relax(); - - /* PC/P BUSY is now set. We must wait until BUSY resets itself. - * We'll reenable ints while we're waiting. - */ - - while ((portman_read_status(pm) & BUSY) == BUSY) - cpu_relax(); - - /* Data sent. */ -} - - -/* - * Read MIDI byte from port - * Attempt to read input byte from specified hardware input port (0..). - * Return -1 if no data - */ -static int portman_read_midi(struct portman *pm, int port) -{ - unsigned char midi_data = 0; - unsigned char cmdout; /* Saved address+IE bit. */ - - /* Make sure clocking edge is down before starting... */ - portman_write_data(pm, 0); /* Make sure edge is down. */ - - /* Set destination address to PCP. */ - cmdout = (port << 1) | INT_EN; /* Address + IE + No Strobe. */ - portman_write_command(pm, cmdout); - - while ((portman_read_status(pm) & ESTB) == ESTB) - cpu_relax(); /* Wait for strobe echo. */ - - /* After the address lines settle, check multiplexed RxAvail signal. - * If data is available, read it. - */ - if ((portman_read_status(pm) & RXAVAIL) == 0) - return -1; /* No data. */ - - /* Set the Strobe signal to enable the Rx clocking circuitry. */ - portman_write_command(pm, cmdout | STROBE); /* Write address+IE+Strobe. */ - - while ((portman_read_status(pm) & ESTB) == 0) - cpu_relax(); /* Wait for strobe echo. */ - - /* The first data bit (msb) is already sitting on the input line. */ - midi_data = (portman_read_status(pm) & 128); - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 6. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 1) & 64; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 5. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 2) & 32; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 4. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 3) & 16; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 3. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 4) & 8; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 2. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 5) & 4; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 1. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 6) & 2; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - - /* Data bit 0. */ - portman_write_data(pm, 0); /* Cause falling edge while data settles. */ - midi_data |= (portman_read_status(pm) >> 7) & 1; - portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */ - portman_write_data(pm, 0); /* Return data clock low. */ - - - /* De-assert Strobe and return data. */ - portman_write_command(pm, cmdout); /* Output saved address+IE. */ - - /* Wait for strobe echo. */ - while ((portman_read_status(pm) & ESTB) == ESTB) - cpu_relax(); - - return (midi_data & 255); /* Shift back and return value. */ -} - -/* - * Checks if any input data on the given channel is available - * Checks RxAvail - */ -static int portman_data_avail(struct portman *pm, int channel) -{ - int command = INT_EN; - switch (channel) { - case 0: - command |= RXDATA0; - break; - case 1: - command |= RXDATA1; - break; - } - /* Write hardware (assumme STROBE=0) */ - portman_write_command(pm, command); - /* Check multiplexed RxAvail signal */ - if ((portman_read_status(pm) & RXAVAIL) == RXAVAIL) - return 1; /* Data available */ - - /* No Data available */ - return 0; -} - - -/* - * Flushes any input - */ -static void portman_flush_input(struct portman *pm, unsigned char port) -{ - /* Local variable for counting things */ - unsigned int i = 0; - unsigned char command = 0; - - switch (port) { - case 0: - command = RXDATA0; - break; - case 1: - command = RXDATA1; - break; - default: - snd_printk(KERN_WARNING - "portman_flush_input() Won't flush port %i\n", - port); - return; - } - - /* Set address for specified channel in port and allow to settle. */ - portman_write_command(pm, command); - - /* Assert the Strobe and wait for echo back. */ - portman_write_command(pm, command | STROBE); - - /* Wait for ESTB */ - while ((portman_read_status(pm) & ESTB) == 0) - cpu_relax(); - - /* Output clock cycles to the Rx circuitry. */ - portman_write_data(pm, 0); - - /* Flush 250 bits... */ - for (i = 0; i < 250; i++) { - portman_write_data(pm, 1); - portman_write_data(pm, 0); - } - - /* Deassert the Strobe signal of the port and wait for it to settle. */ - portman_write_command(pm, command | INT_EN); - - /* Wait for settling */ - while ((portman_read_status(pm) & ESTB) == ESTB) - cpu_relax(); -} - -static int portman_probe(struct parport *p) -{ - /* Initialize the parallel port data register. Will set Rx clocks - * low in case we happen to be addressing the Rx ports at this time. - */ - /* 1 */ - parport_write_data(p, 0); - - /* Initialize the parallel port command register, thus initializing - * hardware handshake lines to midi box: - * - * Strobe = 0 - * Interrupt Enable = 0 - */ - /* 2 */ - parport_write_control(p, 0); - - /* Check if Portman PC/P 2x4 is out there. */ - /* 3 */ - parport_write_control(p, RXDATA0); /* Write Strobe=0 to command reg. */ - - /* Check for ESTB to be clear */ - /* 4 */ - if ((parport_read_status(p) & ESTB) == ESTB) - return 1; /* CODE 1 - Strobe Failure. */ - - /* Set for RXDATA0 where no damage will be done. */ - /* 5 */ - parport_write_control(p, RXDATA0 + STROBE); /* Write Strobe=1 to command reg. */ - - /* 6 */ - if ((parport_read_status(p) & ESTB) != ESTB) - return 1; /* CODE 1 - Strobe Failure. */ - - /* 7 */ - parport_write_control(p, 0); /* Reset Strobe=0. */ - - /* Check if Tx circuitry is functioning properly. If initialized - * unit TxEmpty is false, send out char and see if if goes true. - */ - /* 8 */ - parport_write_control(p, TXDATA0); /* Tx channel 0, strobe off. */ - - /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP - * Status Register), then go write data. Else go back and wait. - */ - /* 9 */ - if ((parport_read_status(p) & TXEMPTY) == 0) - return 2; - - /* Return OK status. */ - return 0; -} - -static int portman_device_init(struct portman *pm) -{ - portman_flush_input(pm, 0); - portman_flush_input(pm, 1); - - return 0; -} - -/********************************************************************* - * Rawmidi - *********************************************************************/ -static int snd_portman_midi_open(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static int snd_portman_midi_close(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct portman *pm = substream->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&pm->reg_lock, flags); - if (up) - pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED; - else - pm->mode[substream->number] &= ~PORTMAN2X4_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&pm->reg_lock, flags); -} - -static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct portman *pm = substream->rmidi->private_data; - unsigned long flags; - unsigned char byte; - - spin_lock_irqsave(&pm->reg_lock, flags); - if (up) { - while ((snd_rawmidi_transmit(substream, &byte, 1) == 1)) - portman_write_midi(pm, substream->number, byte); - } - spin_unlock_irqrestore(&pm->reg_lock, flags); -} - -static struct snd_rawmidi_ops snd_portman_midi_output = { - .open = snd_portman_midi_open, - .close = snd_portman_midi_close, - .trigger = snd_portman_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_portman_midi_input = { - .open = snd_portman_midi_open, - .close = snd_portman_midi_close, - .trigger = snd_portman_midi_input_trigger, -}; - -/* Create and initialize the rawmidi component */ -static int __devinit snd_portman_rawmidi_create(struct snd_card *card) -{ - struct portman *pm = card->private_data; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream; - int err; - - err = snd_rawmidi_new(card, CARD_NAME, 0, - PORTMAN_NUM_OUTPUT_PORTS, - PORTMAN_NUM_INPUT_PORTS, - &rmidi); - if (err < 0) - return err; - - rmidi->private_data = pm; - strcpy(rmidi->name, CARD_NAME); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - pm->rmidi = rmidi; - - /* register rawmidi ops */ - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_portman_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_portman_midi_input); - - /* name substreams */ - /* output */ - list_for_each_entry(substream, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams, - list) { - sprintf(substream->name, - "Portman2x4 %d", substream->number+1); - } - /* input */ - list_for_each_entry(substream, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams, - list) { - pm->midi_input[substream->number] = substream; - sprintf(substream->name, - "Portman2x4 %d", substream->number+1); - } - - return err; -} - -/********************************************************************* - * parport stuff - *********************************************************************/ -static void snd_portman_interrupt(void *userdata) -{ - unsigned char midivalue = 0; - struct portman *pm = ((struct snd_card*)userdata)->private_data; - - spin_lock(&pm->reg_lock); - - /* While any input data is waiting */ - while ((portman_read_status(pm) & INT_REQ) == INT_REQ) { - /* If data available on channel 0, - read it and stuff it into the queue. */ - if (portman_data_avail(pm, 0)) { - /* Read Midi */ - midivalue = portman_read_midi(pm, 0); - /* put midi into queue... */ - if (pm->mode[0] & PORTMAN2X4_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(pm->midi_input[0], - &midivalue, 1); - - } - /* If data available on channel 1, - read it and stuff it into the queue. */ - if (portman_data_avail(pm, 1)) { - /* Read Midi */ - midivalue = portman_read_midi(pm, 1); - /* put midi into queue... */ - if (pm->mode[1] & PORTMAN2X4_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(pm->midi_input[1], - &midivalue, 1); - } - - } - - spin_unlock(&pm->reg_lock); -} - -static int __devinit snd_portman_probe_port(struct parport *p) -{ - struct pardevice *pardev; - int res; - - pardev = parport_register_device(p, DRIVER_NAME, - NULL, NULL, NULL, - 0, NULL); - if (!pardev) - return -EIO; - - if (parport_claim(pardev)) { - parport_unregister_device(pardev); - return -EIO; - } - - res = portman_probe(p); - - parport_release(pardev); - parport_unregister_device(pardev); - - return res ? -EIO : 0; -} - -static void __devinit snd_portman_attach(struct parport *p) -{ - struct platform_device *device; - - device = platform_device_alloc(PLATFORM_DRIVER, device_count); - if (!device) - return; - - /* Temporary assignment to forward the parport */ - platform_set_drvdata(device, p); - - if (platform_device_add(device) < 0) { - platform_device_put(device); - return; - } - - /* Since we dont get the return value of probe - * We need to check if device probing succeeded or not */ - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - return; - } - - /* register device in global table */ - platform_devices[device_count] = device; - device_count++; -} - -static void snd_portman_detach(struct parport *p) -{ - /* nothing to do here */ -} - -static struct parport_driver portman_parport_driver = { - .name = "portman2x4", - .attach = snd_portman_attach, - .detach = snd_portman_detach -}; - -/********************************************************************* - * platform stuff - *********************************************************************/ -static void snd_portman_card_private_free(struct snd_card *card) -{ - struct portman *pm = card->private_data; - struct pardevice *pardev = pm->pardev; - - if (pardev) { - if (pm->pardev_claimed) - parport_release(pardev); - parport_unregister_device(pardev); - } - - portman_free(pm); -} - -static int __devinit snd_portman_probe(struct platform_device *pdev) -{ - struct pardevice *pardev; - struct parport *p; - int dev = pdev->id; - struct snd_card *card = NULL; - struct portman *pm = NULL; - int err; - - p = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) - return -ENOENT; - - if ((err = snd_portman_probe_port(p)) < 0) - return err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printd("Cannot create card\n"); - return err; - } - strcpy(card->driver, DRIVER_NAME); - strcpy(card->shortname, CARD_NAME); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, p->base, p->irq); - - pardev = parport_register_device(p, /* port */ - DRIVER_NAME, /* name */ - NULL, /* preempt */ - NULL, /* wakeup */ - snd_portman_interrupt, /* ISR */ - PARPORT_DEV_EXCL, /* flags */ - (void *)card); /* private */ - if (pardev == NULL) { - snd_printd("Cannot register pardevice\n"); - err = -EIO; - goto __err; - } - - if ((err = portman_create(card, pardev, &pm)) < 0) { - snd_printd("Cannot create main component\n"); - parport_unregister_device(pardev); - goto __err; - } - card->private_data = pm; - card->private_free = snd_portman_card_private_free; - - if ((err = snd_portman_rawmidi_create(card)) < 0) { - snd_printd("Creating Rawmidi component failed\n"); - goto __err; - } - - /* claim parport */ - if (parport_claim(pardev)) { - snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); - err = -EIO; - goto __err; - } - pm->pardev_claimed = 1; - - /* init device */ - if ((err = portman_device_init(pm)) < 0) - goto __err; - - platform_set_drvdata(pdev, card); - - snd_card_set_dev(card, &pdev->dev); - - /* At this point card will be usable */ - if ((err = snd_card_register(card)) < 0) { - snd_printd("Cannot register card\n"); - goto __err; - } - - snd_printk(KERN_INFO "Portman 2x4 on 0x%lx\n", p->base); - return 0; - -__err: - snd_card_free(card); - return err; -} - -static int __devexit snd_portman_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - if (card) - snd_card_free(card); - - return 0; -} - - -static struct platform_driver snd_portman_driver = { - .probe = snd_portman_probe, - .remove = __devexit_p(snd_portman_remove), - .driver = { - .name = PLATFORM_DRIVER - } -}; - -/********************************************************************* - * module init stuff - *********************************************************************/ -static void snd_portman_unregister_all(void) -{ - int i; - - for (i = 0; i < SNDRV_CARDS; ++i) { - if (platform_devices[i]) { - platform_device_unregister(platform_devices[i]); - platform_devices[i] = NULL; - } - } - platform_driver_unregister(&snd_portman_driver); - parport_unregister_driver(&portman_parport_driver); -} - -static int __init snd_portman_module_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_portman_driver)) < 0) - return err; - - if (parport_register_driver(&portman_parport_driver) != 0) { - platform_driver_unregister(&snd_portman_driver); - return -EIO; - } - - if (device_count == 0) { - snd_portman_unregister_all(); - return -ENODEV; - } - - return 0; -} - -static void __exit snd_portman_module_exit(void) -{ - snd_portman_unregister_all(); -} - -module_init(snd_portman_module_init); -module_exit(snd_portman_module_exit); diff --git a/ANDROID_3.4.5/sound/drivers/serial-u16550.c b/ANDROID_3.4.5/sound/drivers/serial-u16550.c deleted file mode 100644 index b2d0e8e4..00000000 --- a/ANDROID_3.4.5/sound/drivers/serial-u16550.c +++ /dev/null @@ -1,1050 +0,0 @@ -/* - * serial.c - * Copyright (c) by Jaroslav Kysela , - * Isaku Yamahata , - * George Hansper , - * Hannu Savolainen - * - * This code is based on the code from ALSA 0.5.9, but heavily rewritten. - * - * 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 - * - * Sat Mar 31 17:27:57 PST 2001 tim.mann@compaq.com - * Added support for the Midiator MS-124T and for the MS-124W in - * Single Addressed (S/A) or Multiple Burst (M/B) mode, with - * power derived either parasitically from the serial port or - * from a separate power supply. - * - * More documentation can be found in serial-u16550.txt. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -MODULE_DESCRIPTION("MIDI serial u16550"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}"); - -#define SNDRV_SERIAL_SOUNDCANVAS 0 /* Roland Soundcanvas; F5 NN selects part */ -#define SNDRV_SERIAL_MS124T 1 /* Midiator MS-124T */ -#define SNDRV_SERIAL_MS124W_SA 2 /* Midiator MS-124W in S/A mode */ -#define SNDRV_SERIAL_MS124W_MB 3 /* Midiator MS-124W in M/B mode */ -#define SNDRV_SERIAL_GENERIC 4 /* Generic Interface */ -#define SNDRV_SERIAL_MAX_ADAPTOR SNDRV_SERIAL_GENERIC -static char *adaptor_names[] = { - "Soundcanvas", - "MS-124T", - "MS-124W S/A", - "MS-124W M/B", - "Generic" -}; - -#define SNDRV_SERIAL_NORMALBUFF 0 /* Normal blocking buffer operation */ -#define SNDRV_SERIAL_DROPBUFF 1 /* Non-blocking discard operation */ - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x3f8,0x2f8,0x3e8,0x2e8 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,4,5,7,9,10,11,14,15 */ -static int speed[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 38400}; /* 9600,19200,38400,57600,115200 */ -static int base[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 115200}; /* baud base */ -static int outs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */ -static int ins[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */ -static int adaptor[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = SNDRV_SERIAL_SOUNDCANVAS}; -static bool droponfull[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS -1)] = SNDRV_SERIAL_NORMALBUFF }; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Serial MIDI."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Serial MIDI."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable UART16550A chip."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for UART16550A chip."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for UART16550A chip."); -module_param_array(speed, int, NULL, 0444); -MODULE_PARM_DESC(speed, "Speed in bauds."); -module_param_array(base, int, NULL, 0444); -MODULE_PARM_DESC(base, "Base for divisor in bauds."); -module_param_array(outs, int, NULL, 0444); -MODULE_PARM_DESC(outs, "Number of MIDI outputs."); -module_param_array(ins, int, NULL, 0444); -MODULE_PARM_DESC(ins, "Number of MIDI inputs."); -module_param_array(droponfull, bool, NULL, 0444); -MODULE_PARM_DESC(droponfull, "Flag to enable drop-on-full buffer mode"); - -module_param_array(adaptor, int, NULL, 0444); -MODULE_PARM_DESC(adaptor, "Type of adaptor."); - -/*#define SNDRV_SERIAL_MS124W_MB_NOCOMBO 1*/ /* Address outs as 0-3 instead of bitmap */ - -#define SNDRV_SERIAL_MAX_OUTS 16 /* max 64, min 16 */ -#define SNDRV_SERIAL_MAX_INS 16 /* max 64, min 16 */ - -#define TX_BUFF_SIZE (1<<15) /* Must be 2^n */ -#define TX_BUFF_MASK (TX_BUFF_SIZE - 1) - -#define SERIAL_MODE_NOT_OPENED (0) -#define SERIAL_MODE_INPUT_OPEN (1 << 0) -#define SERIAL_MODE_OUTPUT_OPEN (1 << 1) -#define SERIAL_MODE_INPUT_TRIGGERED (1 << 2) -#define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3) - -struct snd_uart16550 { - struct snd_card *card; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS]; - struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS]; - - int filemode; /* open status of file */ - - spinlock_t open_lock; - - int irq; - - unsigned long base; - struct resource *res_base; - - unsigned int speed; - unsigned int speed_base; - unsigned char divisor; - - unsigned char old_divisor_lsb; - unsigned char old_divisor_msb; - unsigned char old_line_ctrl_reg; - - /* parameter for using of write loop */ - short int fifo_limit; /* used in uart16550 */ - short int fifo_count; /* used in uart16550 */ - - /* type of adaptor */ - int adaptor; - - /* inputs */ - int prev_in; - unsigned char rstatus; - - /* outputs */ - int prev_out; - unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS]; - - /* write buffer and its writing/reading position */ - unsigned char tx_buff[TX_BUFF_SIZE]; - int buff_in_count; - int buff_in; - int buff_out; - int drop_on_full; - - /* wait timer */ - unsigned int timer_running:1; - struct timer_list buffer_timer; - -}; - -static struct platform_device *devices[SNDRV_CARDS]; - -static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart) -{ - if (!uart->timer_running) { - /* timer 38600bps * 10bit * 16byte */ - uart->buffer_timer.expires = jiffies + (HZ+255)/256; - uart->timer_running = 1; - add_timer(&uart->buffer_timer); - } -} - -static inline void snd_uart16550_del_timer(struct snd_uart16550 *uart) -{ - if (uart->timer_running) { - del_timer(&uart->buffer_timer); - uart->timer_running = 0; - } -} - -/* This macro is only used in snd_uart16550_io_loop */ -static inline void snd_uart16550_buffer_output(struct snd_uart16550 *uart) -{ - unsigned short buff_out = uart->buff_out; - if (uart->buff_in_count > 0) { - outb(uart->tx_buff[buff_out], uart->base + UART_TX); - uart->fifo_count++; - buff_out++; - buff_out &= TX_BUFF_MASK; - uart->buff_out = buff_out; - uart->buff_in_count--; - } -} - -/* This loop should be called with interrupts disabled - * We don't want to interrupt this, - * as we're already handling an interrupt - */ -static void snd_uart16550_io_loop(struct snd_uart16550 * uart) -{ - unsigned char c, status; - int substream; - - /* recall previous stream */ - substream = uart->prev_in; - - /* Read Loop */ - while ((status = inb(uart->base + UART_LSR)) & UART_LSR_DR) { - /* while receive data ready */ - c = inb(uart->base + UART_RX); - - /* keep track of last status byte */ - if (c & 0x80) - uart->rstatus = c; - - /* handle stream switch */ - if (uart->adaptor == SNDRV_SERIAL_GENERIC) { - if (uart->rstatus == 0xf5) { - if (c <= SNDRV_SERIAL_MAX_INS && c > 0) - substream = c - 1; - if (c != 0xf5) - /* prevent future bytes from being - interpreted as streams */ - uart->rstatus = 0; - } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) - && uart->midi_input[substream]) - snd_rawmidi_receive(uart->midi_input[substream], - &c, 1); - } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && - uart->midi_input[substream]) - snd_rawmidi_receive(uart->midi_input[substream], &c, 1); - - if (status & UART_LSR_OE) - snd_printk(KERN_WARNING - "%s: Overrun on device at 0x%lx\n", - uart->rmidi->name, uart->base); - } - - /* remember the last stream */ - uart->prev_in = substream; - - /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not, - buffer is never filled. */ - /* Check write status */ - if (status & UART_LSR_THRE) - uart->fifo_count = 0; - if (uart->adaptor == SNDRV_SERIAL_MS124W_SA - || uart->adaptor == SNDRV_SERIAL_GENERIC) { - /* Can't use FIFO, must send only when CTS is true */ - status = inb(uart->base + UART_MSR); - while (uart->fifo_count == 0 && (status & UART_MSR_CTS) && - uart->buff_in_count > 0) { - snd_uart16550_buffer_output(uart); - status = inb(uart->base + UART_MSR); - } - } else { - /* Write loop */ - while (uart->fifo_count < uart->fifo_limit /* Can we write ? */ - && uart->buff_in_count > 0) /* Do we want to? */ - snd_uart16550_buffer_output(uart); - } - if (uart->irq < 0 && uart->buff_in_count > 0) - snd_uart16550_add_timer(uart); -} - -/* NOTES ON SERVICING INTERUPTS - * --------------------------- - * After receiving a interrupt, it is important to indicate to the UART that - * this has been done. - * For a Rx interrupt, this is done by reading the received byte. - * For a Tx interrupt this is done by either: - * a) Writing a byte - * b) Reading the IIR - * It is particularly important to read the IIR if a Tx interrupt is received - * when there is no data in tx_buff[], as in this case there no other - * indication that the interrupt has been serviced, and it remains outstanding - * indefinitely. This has the curious side effect that and no further interrupts - * will be generated from this device AT ALL!!. - * It is also desirable to clear outstanding interrupts when the device is - * opened/closed. - * - * - * Note that some devices need OUT2 to be set before they will generate - * interrupts at all. (Possibly tied to an internal pull-up on CTS?) - */ -static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) -{ - struct snd_uart16550 *uart; - - uart = dev_id; - spin_lock(&uart->open_lock); - if (uart->filemode == SERIAL_MODE_NOT_OPENED) { - spin_unlock(&uart->open_lock); - return IRQ_NONE; - } - /* indicate to the UART that the interrupt has been serviced */ - inb(uart->base + UART_IIR); - snd_uart16550_io_loop(uart); - spin_unlock(&uart->open_lock); - return IRQ_HANDLED; -} - -/* When the polling mode, this function calls snd_uart16550_io_loop. */ -static void snd_uart16550_buffer_timer(unsigned long data) -{ - unsigned long flags; - struct snd_uart16550 *uart; - - uart = (struct snd_uart16550 *)data; - spin_lock_irqsave(&uart->open_lock, flags); - snd_uart16550_del_timer(uart); - snd_uart16550_io_loop(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); -} - -/* - * this method probes, if an uart sits on given port - * return 0 if found - * return negative error if not found - */ -static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart) -{ - unsigned long io_base = uart->base; - int ok; - unsigned char c; - - /* Do some vague tests for the presence of the uart */ - if (io_base == 0 || io_base == SNDRV_AUTO_PORT) { - return -ENODEV; /* Not configured */ - } - - uart->res_base = request_region(io_base, 8, "Serial MIDI"); - if (uart->res_base == NULL) { - snd_printk(KERN_ERR "u16550: can't grab port 0x%lx\n", io_base); - return -EBUSY; - } - - /* uart detected unless one of the following tests should fail */ - ok = 1; - /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */ - outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */ - c = inb(io_base + UART_IER); - /* The top four bits of the IER should always == 0 */ - if ((c & 0xf0) != 0) - ok = 0; /* failed */ - - outb(0xaa, io_base + UART_SCR); - /* Write arbitrary data into the scratch reg */ - c = inb(io_base + UART_SCR); - /* If it comes back, it's OK */ - if (c != 0xaa) - ok = 0; /* failed */ - - outb(0x55, io_base + UART_SCR); - /* Write arbitrary data into the scratch reg */ - c = inb(io_base + UART_SCR); - /* If it comes back, it's OK */ - if (c != 0x55) - ok = 0; /* failed */ - - return ok; -} - -static void snd_uart16550_do_open(struct snd_uart16550 * uart) -{ - char byte; - - /* Initialize basic variables */ - uart->buff_in_count = 0; - uart->buff_in = 0; - uart->buff_out = 0; - uart->fifo_limit = 1; - uart->fifo_count = 0; - uart->timer_running = 0; - - outb(UART_FCR_ENABLE_FIFO /* Enable FIFO's (if available) */ - | UART_FCR_CLEAR_RCVR /* Clear receiver FIFO */ - | UART_FCR_CLEAR_XMIT /* Clear transmitter FIFO */ - | UART_FCR_TRIGGER_4 /* Set FIFO trigger at 4-bytes */ - /* NOTE: interrupt generated after T=(time)4-bytes - * if less than UART_FCR_TRIGGER bytes received - */ - ,uart->base + UART_FCR); /* FIFO Control Register */ - - if ((inb(uart->base + UART_IIR) & 0xf0) == 0xc0) - uart->fifo_limit = 16; - if (uart->divisor != 0) { - uart->old_line_ctrl_reg = inb(uart->base + UART_LCR); - outb(UART_LCR_DLAB /* Divisor latch access bit */ - ,uart->base + UART_LCR); /* Line Control Register */ - uart->old_divisor_lsb = inb(uart->base + UART_DLL); - uart->old_divisor_msb = inb(uart->base + UART_DLM); - - outb(uart->divisor - ,uart->base + UART_DLL); /* Divisor Latch Low */ - outb(0 - ,uart->base + UART_DLM); /* Divisor Latch High */ - /* DLAB is reset to 0 in next outb() */ - } - /* Set serial parameters (parity off, etc) */ - outb(UART_LCR_WLEN8 /* 8 data-bits */ - | 0 /* 1 stop-bit */ - | 0 /* parity off */ - | 0 /* DLAB = 0 */ - ,uart->base + UART_LCR); /* Line Control Register */ - - switch (uart->adaptor) { - default: - outb(UART_MCR_RTS /* Set Request-To-Send line active */ - | UART_MCR_DTR /* Set Data-Terminal-Ready line active */ - | UART_MCR_OUT2 /* Set OUT2 - not always required, but when - * it is, it is ESSENTIAL for enabling interrupts - */ - ,uart->base + UART_MCR); /* Modem Control Register */ - break; - case SNDRV_SERIAL_MS124W_SA: - case SNDRV_SERIAL_MS124W_MB: - /* MS-124W can draw power from RTS and DTR if they - are in opposite states. */ - outb(UART_MCR_RTS | (0&UART_MCR_DTR) | UART_MCR_OUT2, - uart->base + UART_MCR); - break; - case SNDRV_SERIAL_MS124T: - /* MS-124T can draw power from RTS and/or DTR (preferably - both) if they are both asserted. */ - outb(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2, - uart->base + UART_MCR); - break; - } - - if (uart->irq < 0) { - byte = (0 & UART_IER_RDI) /* Disable Receiver data interrupt */ - |(0 & UART_IER_THRI) /* Disable Transmitter holding register empty interrupt */ - ; - } else if (uart->adaptor == SNDRV_SERIAL_MS124W_SA) { - byte = UART_IER_RDI /* Enable Receiver data interrupt */ - | UART_IER_MSI /* Enable Modem status interrupt */ - ; - } else if (uart->adaptor == SNDRV_SERIAL_GENERIC) { - byte = UART_IER_RDI /* Enable Receiver data interrupt */ - | UART_IER_MSI /* Enable Modem status interrupt */ - | UART_IER_THRI /* Enable Transmitter holding register empty interrupt */ - ; - } else { - byte = UART_IER_RDI /* Enable Receiver data interrupt */ - | UART_IER_THRI /* Enable Transmitter holding register empty interrupt */ - ; - } - outb(byte, uart->base + UART_IER); /* Interrupt enable Register */ - - inb(uart->base + UART_LSR); /* Clear any pre-existing overrun indication */ - inb(uart->base + UART_IIR); /* Clear any pre-existing transmit interrupt */ - inb(uart->base + UART_RX); /* Clear any pre-existing receive interrupt */ -} - -static void snd_uart16550_do_close(struct snd_uart16550 * uart) -{ - if (uart->irq < 0) - snd_uart16550_del_timer(uart); - - /* NOTE: may need to disable interrupts before de-registering out handler. - * For now, the consequences are harmless. - */ - - outb((0 & UART_IER_RDI) /* Disable Receiver data interrupt */ - |(0 & UART_IER_THRI) /* Disable Transmitter holding register empty interrupt */ - ,uart->base + UART_IER); /* Interrupt enable Register */ - - switch (uart->adaptor) { - default: - outb((0 & UART_MCR_RTS) /* Deactivate Request-To-Send line */ - |(0 & UART_MCR_DTR) /* Deactivate Data-Terminal-Ready line */ - |(0 & UART_MCR_OUT2) /* Deactivate OUT2 */ - ,uart->base + UART_MCR); /* Modem Control Register */ - break; - case SNDRV_SERIAL_MS124W_SA: - case SNDRV_SERIAL_MS124W_MB: - /* MS-124W can draw power from RTS and DTR if they - are in opposite states; leave it powered. */ - outb(UART_MCR_RTS | (0&UART_MCR_DTR) | (0&UART_MCR_OUT2), - uart->base + UART_MCR); - break; - case SNDRV_SERIAL_MS124T: - /* MS-124T can draw power from RTS and/or DTR (preferably - both) if they are both asserted; leave it powered. */ - outb(UART_MCR_RTS | UART_MCR_DTR | (0&UART_MCR_OUT2), - uart->base + UART_MCR); - break; - } - - inb(uart->base + UART_IIR); /* Clear any outstanding interrupts */ - - /* Restore old divisor */ - if (uart->divisor != 0) { - outb(UART_LCR_DLAB /* Divisor latch access bit */ - ,uart->base + UART_LCR); /* Line Control Register */ - outb(uart->old_divisor_lsb - ,uart->base + UART_DLL); /* Divisor Latch Low */ - outb(uart->old_divisor_msb - ,uart->base + UART_DLM); /* Divisor Latch High */ - /* Restore old LCR (data bits, stop bits, parity, DLAB) */ - outb(uart->old_line_ctrl_reg - ,uart->base + UART_LCR); /* Line Control Register */ - } -} - -static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - if (uart->filemode == SERIAL_MODE_NOT_OPENED) - snd_uart16550_do_open(uart); - uart->filemode |= SERIAL_MODE_INPUT_OPEN; - uart->midi_input[substream->number] = substream; - spin_unlock_irqrestore(&uart->open_lock, flags); - return 0; -} - -static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - uart->filemode &= ~SERIAL_MODE_INPUT_OPEN; - uart->midi_input[substream->number] = NULL; - if (uart->filemode == SERIAL_MODE_NOT_OPENED) - snd_uart16550_do_close(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); - return 0; -} - -static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - if (up) - uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED; - else - uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED; - spin_unlock_irqrestore(&uart->open_lock, flags); -} - -static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - if (uart->filemode == SERIAL_MODE_NOT_OPENED) - snd_uart16550_do_open(uart); - uart->filemode |= SERIAL_MODE_OUTPUT_OPEN; - uart->midi_output[substream->number] = substream; - spin_unlock_irqrestore(&uart->open_lock, flags); - return 0; -}; - -static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN; - uart->midi_output[substream->number] = NULL; - if (uart->filemode == SERIAL_MODE_NOT_OPENED) - snd_uart16550_do_close(uart); - spin_unlock_irqrestore(&uart->open_lock, flags); - return 0; -}; - -static inline int snd_uart16550_buffer_can_write(struct snd_uart16550 *uart, - int Num) -{ - if (uart->buff_in_count + Num < TX_BUFF_SIZE) - return 1; - else - return 0; -} - -static inline int snd_uart16550_write_buffer(struct snd_uart16550 *uart, - unsigned char byte) -{ - unsigned short buff_in = uart->buff_in; - if (uart->buff_in_count < TX_BUFF_SIZE) { - uart->tx_buff[buff_in] = byte; - buff_in++; - buff_in &= TX_BUFF_MASK; - uart->buff_in = buff_in; - uart->buff_in_count++; - if (uart->irq < 0) /* polling mode */ - snd_uart16550_add_timer(uart); - return 1; - } else - return 0; -} - -static int snd_uart16550_output_byte(struct snd_uart16550 *uart, - struct snd_rawmidi_substream *substream, - unsigned char midi_byte) -{ - if (uart->buff_in_count == 0 /* Buffer empty? */ - && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA && - uart->adaptor != SNDRV_SERIAL_GENERIC) || - (uart->fifo_count == 0 /* FIFO empty? */ - && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */ - - /* Tx Buffer Empty - try to write immediately */ - if ((inb(uart->base + UART_LSR) & UART_LSR_THRE) != 0) { - /* Transmitter holding register (and Tx FIFO) empty */ - uart->fifo_count = 1; - outb(midi_byte, uart->base + UART_TX); - } else { - if (uart->fifo_count < uart->fifo_limit) { - uart->fifo_count++; - outb(midi_byte, uart->base + UART_TX); - } else { - /* Cannot write (buffer empty) - - * put char in buffer */ - snd_uart16550_write_buffer(uart, midi_byte); - } - } - } else { - if (!snd_uart16550_write_buffer(uart, midi_byte)) { - snd_printk(KERN_WARNING - "%s: Buffer overrun on device at 0x%lx\n", - uart->rmidi->name, uart->base); - return 0; - } - } - - return 1; -} - -static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - unsigned char midi_byte, addr_byte; - struct snd_uart16550 *uart = substream->rmidi->private_data; - char first; - static unsigned long lasttime = 0; - - /* Interrupts are disabled during the updating of the tx_buff, - * since it is 'bad' to have two processes updating the same - * variables (ie buff_in & buff_out) - */ - - spin_lock_irqsave(&uart->open_lock, flags); - - if (uart->irq < 0) /* polling */ - snd_uart16550_io_loop(uart); - - if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) { - while (1) { - /* buffer full? */ - /* in this mode we need two bytes of space */ - if (uart->buff_in_count > TX_BUFF_SIZE - 2) - break; - if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1) - break; -#ifdef SNDRV_SERIAL_MS124W_MB_NOCOMBO - /* select exactly one of the four ports */ - addr_byte = (1 << (substream->number + 4)) | 0x08; -#else - /* select any combination of the four ports */ - addr_byte = (substream->number << 4) | 0x08; - /* ...except none */ - if (addr_byte == 0x08) - addr_byte = 0xf8; -#endif - snd_uart16550_output_byte(uart, substream, addr_byte); - /* send midi byte */ - snd_uart16550_output_byte(uart, substream, midi_byte); - } - } else { - first = 0; - while (snd_rawmidi_transmit_peek(substream, &midi_byte, 1) == 1) { - /* Also send F5 after 3 seconds with no data - * to handle device disconnect */ - if (first == 0 && - (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS || - uart->adaptor == SNDRV_SERIAL_GENERIC) && - (uart->prev_out != substream->number || - time_after(jiffies, lasttime + 3*HZ))) { - - if (snd_uart16550_buffer_can_write(uart, 3)) { - /* Roland Soundcanvas part selection */ - /* If this substream of the data is - * different previous substream - * in this uart, send the change part - * event - */ - uart->prev_out = substream->number; - /* change part */ - snd_uart16550_output_byte(uart, substream, - 0xf5); - /* data */ - snd_uart16550_output_byte(uart, substream, - uart->prev_out + 1); - /* If midi_byte is a data byte, - * send the previous status byte */ - if (midi_byte < 0x80 && - uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS) - snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); - } else if (!uart->drop_on_full) - break; - - } - - /* send midi byte */ - if (!snd_uart16550_output_byte(uart, substream, midi_byte) && - !uart->drop_on_full ) - break; - - if (midi_byte >= 0x80 && midi_byte < 0xf0) - uart->prev_status[uart->prev_out] = midi_byte; - first = 1; - - snd_rawmidi_transmit_ack( substream, 1 ); - } - lasttime = jiffies; - } - spin_unlock_irqrestore(&uart->open_lock, flags); -} - -static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - unsigned long flags; - struct snd_uart16550 *uart = substream->rmidi->private_data; - - spin_lock_irqsave(&uart->open_lock, flags); - if (up) - uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED; - else - uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED; - spin_unlock_irqrestore(&uart->open_lock, flags); - if (up) - snd_uart16550_output_write(substream); -} - -static struct snd_rawmidi_ops snd_uart16550_output = -{ - .open = snd_uart16550_output_open, - .close = snd_uart16550_output_close, - .trigger = snd_uart16550_output_trigger, -}; - -static struct snd_rawmidi_ops snd_uart16550_input = -{ - .open = snd_uart16550_input_open, - .close = snd_uart16550_input_close, - .trigger = snd_uart16550_input_trigger, -}; - -static int snd_uart16550_free(struct snd_uart16550 *uart) -{ - if (uart->irq >= 0) - free_irq(uart->irq, uart); - release_and_free_resource(uart->res_base); - kfree(uart); - return 0; -}; - -static int snd_uart16550_dev_free(struct snd_device *device) -{ - struct snd_uart16550 *uart = device->device_data; - return snd_uart16550_free(uart); -} - -static int __devinit snd_uart16550_create(struct snd_card *card, - unsigned long iobase, - int irq, - unsigned int speed, - unsigned int base, - int adaptor, - int droponfull, - struct snd_uart16550 **ruart) -{ - static struct snd_device_ops ops = { - .dev_free = snd_uart16550_dev_free, - }; - struct snd_uart16550 *uart; - int err; - - - if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL) - return -ENOMEM; - uart->adaptor = adaptor; - uart->card = card; - spin_lock_init(&uart->open_lock); - uart->irq = -1; - uart->base = iobase; - uart->drop_on_full = droponfull; - - if ((err = snd_uart16550_detect(uart)) <= 0) { - printk(KERN_ERR "no UART detected at 0x%lx\n", iobase); - snd_uart16550_free(uart); - return -ENODEV; - } - - if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { - if (request_irq(irq, snd_uart16550_interrupt, - 0, "Serial MIDI", uart)) { - snd_printk(KERN_WARNING - "irq %d busy. Using Polling.\n", irq); - } else { - uart->irq = irq; - } - } - uart->divisor = base / speed; - uart->speed = base / (unsigned int)uart->divisor; - uart->speed_base = base; - uart->prev_out = -1; - uart->prev_in = 0; - uart->rstatus = 0; - memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS); - init_timer(&uart->buffer_timer); - uart->buffer_timer.function = snd_uart16550_buffer_timer; - uart->buffer_timer.data = (unsigned long)uart; - uart->timer_running = 0; - - /* Register device */ - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops)) < 0) { - snd_uart16550_free(uart); - return err; - } - - switch (uart->adaptor) { - case SNDRV_SERIAL_MS124W_SA: - case SNDRV_SERIAL_MS124W_MB: - /* MS-124W can draw power from RTS and DTR if they - are in opposite states. */ - outb(UART_MCR_RTS | (0&UART_MCR_DTR), uart->base + UART_MCR); - break; - case SNDRV_SERIAL_MS124T: - /* MS-124T can draw power from RTS and/or DTR (preferably - both) if they are asserted. */ - outb(UART_MCR_RTS | UART_MCR_DTR, uart->base + UART_MCR); - break; - default: - break; - } - - if (ruart) - *ruart = uart; - - return 0; -} - -static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream) -{ - struct snd_rawmidi_substream *substream; - - list_for_each_entry(substream, &stream->substreams, list) { - sprintf(substream->name, "Serial MIDI %d", substream->number + 1); - } -} - -static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device, - int outs, int ins, - struct snd_rawmidi **rmidi) -{ - struct snd_rawmidi *rrawmidi; - int err; - - err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, - outs, ins, &rrawmidi); - if (err < 0) - return err; - snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_uart16550_input); - snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_uart16550_output); - strcpy(rrawmidi->name, "Serial MIDI"); - snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); - snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); - rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rrawmidi->private_data = uart; - if (rmidi) - *rmidi = rrawmidi; - return 0; -} - -static int __devinit snd_serial_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct snd_uart16550 *uart; - int err; - int dev = devptr->id; - - switch (adaptor[dev]) { - case SNDRV_SERIAL_SOUNDCANVAS: - ins[dev] = 1; - break; - case SNDRV_SERIAL_MS124T: - case SNDRV_SERIAL_MS124W_SA: - outs[dev] = 1; - ins[dev] = 1; - break; - case SNDRV_SERIAL_MS124W_MB: - outs[dev] = 16; - ins[dev] = 1; - break; - case SNDRV_SERIAL_GENERIC: - break; - default: - snd_printk(KERN_ERR - "Adaptor type is out of range 0-%d (%d)\n", - SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]); - return -ENODEV; - } - - if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) { - snd_printk(KERN_ERR - "Count of outputs is out of range 1-%d (%d)\n", - SNDRV_SERIAL_MAX_OUTS, outs[dev]); - return -ENODEV; - } - - if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) { - snd_printk(KERN_ERR - "Count of inputs is out of range 1-%d (%d)\n", - SNDRV_SERIAL_MAX_INS, ins[dev]); - return -ENODEV; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - strcpy(card->driver, "Serial"); - strcpy(card->shortname, "Serial MIDI (UART16550A)"); - - if ((err = snd_uart16550_create(card, - port[dev], - irq[dev], - speed[dev], - base[dev], - adaptor[dev], - droponfull[dev], - &uart)) < 0) - goto _err; - - err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi); - if (err < 0) - goto _err; - - sprintf(card->longname, "%s [%s] at %#lx, irq %d", - card->shortname, - adaptor_names[uart->adaptor], - uart->base, - uart->irq); - - snd_card_set_dev(card, &devptr->dev); - - if ((err = snd_card_register(card)) < 0) - goto _err; - - platform_set_drvdata(devptr, card); - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devexit snd_serial_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SND_SERIAL_DRIVER "snd_serial_u16550" - -static struct platform_driver snd_serial_driver = { - .probe = snd_serial_probe, - .remove = __devexit_p( snd_serial_remove), - .driver = { - .name = SND_SERIAL_DRIVER - }, -}; - -static void snd_serial_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_serial_driver); -} - -static int __init alsa_card_serial_init(void) -{ - int i, cards, err; - - if ((err = platform_driver_register(&snd_serial_driver)) < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_SERIAL_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (! cards) { -#ifdef MODULE - printk(KERN_ERR "serial midi soundcard not found or device busy\n"); -#endif - snd_serial_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_serial_exit(void) -{ - snd_serial_unregister_all(); -} - -module_init(alsa_card_serial_init) -module_exit(alsa_card_serial_exit) diff --git a/ANDROID_3.4.5/sound/drivers/virmidi.c b/ANDROID_3.4.5/sound/drivers/virmidi.c deleted file mode 100644 index 9d97478a..00000000 --- a/ANDROID_3.4.5/sound/drivers/virmidi.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Dummy soundcard for virtual rawmidi devices - * - * Copyright (c) 2000 by Takashi Iwai - * - * 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 - * - */ - -/* - * VIRTUAL RAW MIDI DEVICE CARDS - * - * This dummy card contains up to 4 virtual rawmidi devices. - * They are not real rawmidi devices but just associated with sequencer - * clients, so that any input/output sources can be connected as a raw - * MIDI device arbitrary. - * Also, multiple access is allowed to a single rawmidi device. - * - * Typical usage is like following: - * - Load snd-virmidi module. - * # modprobe snd-virmidi index=2 - * Then, sequencer clients 72:0 to 75:0 will be created, which are - * mapped from /dev/snd/midiC1D0 to /dev/snd/midiC1D3, respectively. - * - * - Connect input/output via aconnect. - * % aconnect 64:0 72:0 # keyboard input redirection 64:0 -> 72:0 - * % aconnect 72:0 65:0 # output device redirection 72:0 -> 65:0 - * - * - Run application using a midi device (eg. /dev/snd/midiC1D0) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* hack: OSS defines midi_devs, so undefine it (versioned symbols) */ -#undef midi_devs - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("Dummy soundcard for virtual rawmidi devices"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}"); - -#define MAX_MIDI_DEVICES 4 - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; -static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for virmidi soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for virmidi soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this soundcard."); -module_param_array(midi_devs, int, NULL, 0444); -MODULE_PARM_DESC(midi_devs, "MIDI devices # (1-4)"); - -struct snd_card_virmidi { - struct snd_card *card; - struct snd_rawmidi *midi[MAX_MIDI_DEVICES]; -}; - -static struct platform_device *devices[SNDRV_CARDS]; - - -static int __devinit snd_virmidi_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct snd_card_virmidi *vmidi; - int idx, err; - int dev = devptr->id; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_virmidi), &card); - if (err < 0) - return err; - vmidi = card->private_data; - vmidi->card = card; - - if (midi_devs[dev] > MAX_MIDI_DEVICES) { - snd_printk(KERN_WARNING - "too much midi devices for virmidi %d: " - "force to use %d\n", dev, MAX_MIDI_DEVICES); - midi_devs[dev] = MAX_MIDI_DEVICES; - } - for (idx = 0; idx < midi_devs[dev]; idx++) { - struct snd_rawmidi *rmidi; - struct snd_virmidi_dev *rdev; - if ((err = snd_virmidi_new(card, idx, &rmidi)) < 0) - goto __nodev; - rdev = rmidi->private_data; - vmidi->midi[idx] = rmidi; - strcpy(rmidi->name, "Virtual Raw MIDI"); - rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH; - } - - strcpy(card->driver, "VirMIDI"); - strcpy(card->shortname, "VirMIDI"); - sprintf(card->longname, "Virtual MIDI Card %i", dev + 1); - - snd_card_set_dev(card, &devptr->dev); - - if ((err = snd_card_register(card)) == 0) { - platform_set_drvdata(devptr, card); - return 0; - } - __nodev: - snd_card_free(card); - return err; -} - -static int __devexit snd_virmidi_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#define SND_VIRMIDI_DRIVER "snd_virmidi" - -static struct platform_driver snd_virmidi_driver = { - .probe = snd_virmidi_probe, - .remove = __devexit_p(snd_virmidi_remove), - .driver = { - .name = SND_VIRMIDI_DRIVER - }, -}; - -static void snd_virmidi_unregister_all(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(devices); ++i) - platform_device_unregister(devices[i]); - platform_driver_unregister(&snd_virmidi_driver); -} - -static int __init alsa_card_virmidi_init(void) -{ - int i, cards, err; - - if ((err = platform_driver_register(&snd_virmidi_driver)) < 0) - return err; - - cards = 0; - for (i = 0; i < SNDRV_CARDS; i++) { - struct platform_device *device; - if (! enable[i]) - continue; - device = platform_device_register_simple(SND_VIRMIDI_DRIVER, - i, NULL, 0); - if (IS_ERR(device)) - continue; - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - continue; - } - devices[i] = device; - cards++; - } - if (!cards) { -#ifdef MODULE - printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n"); -#endif - snd_virmidi_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_virmidi_exit(void) -{ - snd_virmidi_unregister_all(); -} - -module_init(alsa_card_virmidi_init) -module_exit(alsa_card_virmidi_exit) diff --git a/ANDROID_3.4.5/sound/drivers/vx/Makefile b/ANDROID_3.4.5/sound/drivers/vx/Makefile deleted file mode 100644 index 9a168a3c..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-vx-lib-objs := vx_core.o vx_hwdep.o vx_pcm.o vx_mixer.o vx_cmd.o vx_uer.o - -obj-$(CONFIG_SND_VX_LIB) += snd-vx-lib.o diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.c b/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.c deleted file mode 100644 index 23f4857f..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * DSP commands - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 "vx_cmd.h" - -/* - * Array of DSP commands - */ -static struct vx_cmd_info vx_dsp_cmds[] = { -[CMD_VERSION] = { 0x010000, 2, RMH_SSIZE_FIXED, 1 }, -[CMD_SUPPORTED] = { 0x020000, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_SEND_IRQA] = { 0x070001, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_IBL] = { 0x080000, 1, RMH_SSIZE_FIXED, 4 }, -[CMD_ASYNC] = { 0x0A0000, 1, RMH_SSIZE_ARG, 0 }, -[CMD_RES_PIPE] = { 0x400000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_FREE_PIPE] = { 0x410000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_CONF_PIPE] = { 0x42A101, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_ABORT_CONF_PIPE] = { 0x42A100, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_PARAM_OUTPUT_PIPE] = { 0x43A000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_STOP_PIPE] = { 0x470004, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_PIPE_STATE] = { 0x480000, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_PIPE_SPL_COUNT] = { 0x49A000, 2, RMH_SSIZE_FIXED, 2 }, -[CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_SIZE_HBUFFER] = { 0x4C0000, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_START_STREAM] = { 0x80A000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_START_ONE_STREAM] = { 0x800000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_PAUSE_STREAM] = { 0x81A000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_PAUSE_ONE_STREAM] = { 0x810000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x828000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_STOP_STREAM] = { 0x830000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_FORMAT_STREAM_OUT] = { 0x868000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_FORMAT_STREAM_IN] = { 0x878800, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_STREAM_STATE] = { 0x890001, 2, RMH_SSIZE_FIXED, 1 }, -[CMD_DROP_BYTES_AWAY] = { 0x8A8000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_REMAINING_BYTES] = { 0x8D0800, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_CONNECT_AUDIO] = { 0xC10000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_AUDIO_LEVEL_ADJUST] = { 0xC2A000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_AUDIO_VU_PIC_METER] = { 0xC3A003, 2, RMH_SSIZE_FIXED, 1 }, -[CMD_GET_AUDIO_LEVELS] = { 0xC4A000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_NOTIFY_EVENT] = { 0x4D0000, 1, RMH_SSIZE_ARG, 0 }, -[CMD_INFO_NOTIFIED] = { 0x0B0000, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_ACCESS_IO_FCT] = { 0x098000, 1, RMH_SSIZE_ARG, 0 }, -[CMD_STATUS_R_BUFFERS] = { 0x440000, 1, RMH_SSIZE_ARG, 0 }, -[CMD_UPDATE_R_BUFFERS] = { 0x848000, 4, RMH_SSIZE_FIXED, 0 }, -[CMD_LOAD_EFFECT_CONTEXT] = { 0x0c8000, 3, RMH_SSIZE_FIXED, 1 }, -[CMD_EFFECT_ONE_PIPE] = { 0x458000, 0, RMH_SSIZE_FIXED, 0 }, -[CMD_MODIFY_CLOCK] = { 0x0d0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_STREAM1_OUT_SET_N_LEVELS] ={ 0x858000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_PURGE_STREAM_DCMDS] = { 0x8b8000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_NOTIFY_PIPE_TIME] = { 0x4e0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_LOAD_EFFECT_CONTEXT_PACKET] = { 0x0c8000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_RELIC_R_BUFFER] = { 0x8e0800, 1, RMH_SSIZE_FIXED, 1 }, -[CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_NOTIFY_STREAM_TIME] = { 0x8f0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_STREAM_SAMPLE_COUNT] = { 0x900000, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_CONFIG_TIME_CODE] = { 0x050000, 2, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_TIME_CODE] = { 0x060000, 1, RMH_SSIZE_FIXED, 5 }, -[CMD_MANAGE_SIGNAL] = { 0x0f0000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_PARAMETER_STREAM_OUT] = { 0x91A000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_READ_BOARD_FREQ] = { 0x030000, 1, RMH_SSIZE_FIXED, 2 }, -[CMD_GET_STREAM_LEVELS] = { 0x8c0000, 1, RMH_SSIZE_FIXED, 3 }, -[CMD_PURGE_PIPE_DCMDS] = { 0x4f8000, 3, RMH_SSIZE_FIXED, 0 }, -// [CMD_SET_STREAM_OUT_EFFECTS] = { 0x888000, 34, RMH_SSIZE_FIXED, 0 }, -// [CMD_GET_STREAM_OUT_EFFECTS] = { 0x928000, 2, RMH_SSIZE_FIXED, 32 }, -[CMD_CONNECT_MONITORING] = { 0xC00000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_STREAM2_OUT_SET_N_LEVELS] = { 0x938000, 3, RMH_SSIZE_FIXED, 0 }, -[CMD_CANCEL_R_BUFFERS] = { 0x948000, 4, RMH_SSIZE_FIXED, 0 }, -[CMD_NOTIFY_END_OF_BUFFER] = { 0x950000, 1, RMH_SSIZE_FIXED, 0 }, -[CMD_GET_STREAM_VU_METER] = { 0x95A000, 2, RMH_SSIZE_ARG, 0 }, -}; - -/** - * vx_init_rmh - initialize the RMH instance - * @rmh: the rmh pointer to be initialized - * @cmd: the rmh command to be set - */ -void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd) -{ - if (snd_BUG_ON(cmd >= CMD_LAST_INDEX)) - return; - rmh->LgCmd = vx_dsp_cmds[cmd].length; - rmh->LgStat = vx_dsp_cmds[cmd].st_length; - rmh->DspStat = vx_dsp_cmds[cmd].st_type; - rmh->Cmd[0] = vx_dsp_cmds[cmd].opcode; -} - diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.h b/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.h deleted file mode 100644 index a85248ba..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_cmd.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * Definitions of DSP commands - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 - */ - -#ifndef __VX_CMD_H -#define __VX_CMD_H - -enum { - CMD_VERSION, - CMD_SUPPORTED, - CMD_TEST_IT, - CMD_SEND_IRQA, - CMD_IBL, - CMD_ASYNC, - CMD_RES_PIPE, - CMD_FREE_PIPE, - CMD_CONF_PIPE, - CMD_ABORT_CONF_PIPE, - CMD_PARAM_OUTPUT_PIPE, - CMD_STOP_PIPE, - CMD_PIPE_STATE, - CMD_PIPE_SPL_COUNT, - CMD_CAN_START_PIPE, - CMD_SIZE_HBUFFER, - CMD_START_STREAM, - CMD_START_ONE_STREAM, - CMD_PAUSE_STREAM, - CMD_PAUSE_ONE_STREAM, - CMD_STREAM_OUT_LEVEL_ADJUST, - CMD_STOP_STREAM, - CMD_FORMAT_STREAM_OUT, - CMD_FORMAT_STREAM_IN, - CMD_GET_STREAM_STATE, - CMD_DROP_BYTES_AWAY, - CMD_GET_REMAINING_BYTES, - CMD_CONNECT_AUDIO, - CMD_AUDIO_LEVEL_ADJUST, - CMD_AUDIO_VU_PIC_METER, - CMD_GET_AUDIO_LEVELS, - CMD_GET_NOTIFY_EVENT, - CMD_INFO_NOTIFIED, - CMD_ACCESS_IO_FCT, - CMD_STATUS_R_BUFFERS, - CMD_UPDATE_R_BUFFERS, - CMD_LOAD_EFFECT_CONTEXT, - CMD_EFFECT_ONE_PIPE, - CMD_MODIFY_CLOCK, - CMD_STREAM1_OUT_SET_N_LEVELS, - CMD_PURGE_STREAM_DCMDS, - CMD_NOTIFY_PIPE_TIME, - CMD_LOAD_EFFECT_CONTEXT_PACKET, - CMD_RELIC_R_BUFFER, - CMD_RESYNC_AUDIO_INPUTS, - CMD_NOTIFY_STREAM_TIME, - CMD_STREAM_SAMPLE_COUNT, - CMD_CONFIG_TIME_CODE, - CMD_GET_TIME_CODE, - CMD_MANAGE_SIGNAL, - CMD_PARAMETER_STREAM_OUT, - CMD_READ_BOARD_FREQ, - CMD_GET_STREAM_LEVELS, - CMD_PURGE_PIPE_DCMDS, - // CMD_SET_STREAM_OUT_EFFECTS, - // CMD_GET_STREAM_OUT_EFFECTS, - CMD_CONNECT_MONITORING, - CMD_STREAM2_OUT_SET_N_LEVELS, - CMD_CANCEL_R_BUFFERS, - CMD_NOTIFY_END_OF_BUFFER, - CMD_GET_STREAM_VU_METER, - CMD_LAST_INDEX -}; - -struct vx_cmd_info { - unsigned int opcode; /* command word */ - int length; /* command length (in words) */ - int st_type; /* status type (RMH_SSIZE_XXX) */ - int st_length; /* fixed length */ -}; - -/* Family and code op of some DSP requests. */ -#define CODE_OP_PIPE_TIME 0x004e0000 -#define CODE_OP_START_STREAM 0x00800000 -#define CODE_OP_PAUSE_STREAM 0x00810000 -#define CODE_OP_OUT_STREAM_LEVEL 0x00820000 -#define CODE_OP_UPDATE_R_BUFFERS 0x00840000 -#define CODE_OP_OUT_STREAM1_LEVEL_CURVE 0x00850000 -#define CODE_OP_OUT_STREAM2_LEVEL_CURVE 0x00930000 -#define CODE_OP_OUT_STREAM_FORMAT 0x00860000 -#define CODE_OP_STREAM_TIME 0x008f0000 -#define CODE_OP_OUT_STREAM_EXTRAPARAMETER 0x00910000 -#define CODE_OP_OUT_AUDIO_LEVEL 0x00c20000 - -#define NOTIFY_LAST_COMMAND 0x00400000 - -/* Values for a user delay */ -#define DC_DIFFERED_DELAY (1<Cmd[0] |= COMMAND_RECORD_MASK; - rmh->Cmd[0] |= (((u32)param1 & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD; - - if (param2) - rmh->Cmd[0] |= ((u32)param2 & MASK_FIRST_FIELD) & MASK_DSP_WORD; - -} - -/** - * vx_set_stream_cmd_params - fill first command word for stream commands - * @rmh: the rmh to be modified - * @is_capture: 0 = playback, 1 = capture operation - * @pipe: the pipe index (zero-based) - */ -static inline void vx_set_stream_cmd_params(struct vx_rmh *rmh, int is_capture, int pipe) -{ - if (is_capture) - rmh->Cmd[0] |= COMMAND_RECORD_MASK; - rmh->Cmd[0] |= (((u32)pipe & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD; -} - -#endif /* __VX_CMD_H */ diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_core.c b/ANDROID_3.4.5/sound/drivers/vx/vx_core.c deleted file mode 100644 index b8e51599..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_core.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * Hardware core part - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include "vx_cmd.h" - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("Common routines for Digigram VX drivers"); -MODULE_LICENSE("GPL"); - - -/* - * vx_check_reg_bit - wait for the specified bit is set/reset on a register - * @reg: register to check - * @mask: bit mask - * @bit: resultant bit to be checked - * @time: time-out of loop in msec - * - * returns zero if a bit matches, or a negative error code. - */ -int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int time) -{ - unsigned long end_time = jiffies + (time * HZ + 999) / 1000; -#ifdef CONFIG_SND_DEBUG - static char *reg_names[VX_REG_MAX] = { - "ICR", "CVR", "ISR", "IVR", "RXH", "RXM", "RXL", - "DMA", "CDSP", "RFREQ", "RUER/V2", "DATA", "MEMIRQ", - "ACQ", "BIT0", "BIT1", "MIC0", "MIC1", "MIC2", - "MIC3", "INTCSR", "CNTRL", "GPIOC", - "LOFREQ", "HIFREQ", "CSUER", "RUER" - }; -#endif - do { - if ((snd_vx_inb(chip, reg) & mask) == bit) - return 0; - //msleep(10); - } while (time_after_eq(end_time, jiffies)); - snd_printd(KERN_DEBUG "vx_check_reg_bit: timeout, reg=%s, mask=0x%x, val=0x%x\n", reg_names[reg], mask, snd_vx_inb(chip, reg)); - return -EIO; -} - -EXPORT_SYMBOL(snd_vx_check_reg_bit); - -/* - * vx_send_irq_dsp - set command irq bit - * @num: the requested IRQ type, IRQ_XXX - * - * this triggers the specified IRQ request - * returns 0 if successful, or a negative error code. - * - */ -static int vx_send_irq_dsp(struct vx_core *chip, int num) -{ - int nirq; - - /* wait for Hc = 0 */ - if (snd_vx_check_reg_bit(chip, VX_CVR, CVR_HC, 0, 200) < 0) - return -EIO; - - nirq = num; - if (vx_has_new_dsp(chip)) - nirq += VXP_IRQ_OFFSET; - vx_outb(chip, CVR, (nirq >> 1) | CVR_HC); - return 0; -} - - -/* - * vx_reset_chk - reset CHK bit on ISR - * - * returns 0 if successful, or a negative error code. - */ -static int vx_reset_chk(struct vx_core *chip) -{ - /* Reset irq CHK */ - if (vx_send_irq_dsp(chip, IRQ_RESET_CHK) < 0) - return -EIO; - /* Wait until CHK = 0 */ - if (vx_check_isr(chip, ISR_CHK, 0, 200) < 0) - return -EIO; - return 0; -} - -/* - * vx_transfer_end - terminate message transfer - * @cmd: IRQ message to send (IRQ_MESS_XXX_END) - * - * returns 0 if successful, or a negative error code. - * the error code can be VX-specific, retrieved via vx_get_error(). - * NB: call with spinlock held! - */ -static int vx_transfer_end(struct vx_core *chip, int cmd) -{ - int err; - - if ((err = vx_reset_chk(chip)) < 0) - return err; - - /* irq MESS_READ/WRITE_END */ - if ((err = vx_send_irq_dsp(chip, cmd)) < 0) - return err; - - /* Wait CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) - return err; - - /* If error, Read RX */ - if ((err = vx_inb(chip, ISR)) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) { - snd_printd(KERN_DEBUG "transfer_end: error in rx_full\n"); - return err; - } - err = vx_inb(chip, RXH) << 16; - err |= vx_inb(chip, RXM) << 8; - err |= vx_inb(chip, RXL); - snd_printd(KERN_DEBUG "transfer_end: error = 0x%x\n", err); - return -(VX_ERR_MASK | err); - } - return 0; -} - -/* - * vx_read_status - return the status rmh - * @rmh: rmh record to store the status - * - * returns 0 if successful, or a negative error code. - * the error code can be VX-specific, retrieved via vx_get_error(). - * NB: call with spinlock held! - */ -static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh) -{ - int i, err, val, size; - - /* no read necessary? */ - if (rmh->DspStat == RMH_SSIZE_FIXED && rmh->LgStat == 0) - return 0; - - /* Wait for RX full (with timeout protection) - * The first word of status is in RX - */ - err = vx_wait_for_rx_full(chip); - if (err < 0) - return err; - - /* Read RX */ - val = vx_inb(chip, RXH) << 16; - val |= vx_inb(chip, RXM) << 8; - val |= vx_inb(chip, RXL); - - /* If status given by DSP, let's decode its size */ - switch (rmh->DspStat) { - case RMH_SSIZE_ARG: - size = val & 0xff; - rmh->Stat[0] = val & 0xffff00; - rmh->LgStat = size + 1; - break; - case RMH_SSIZE_MASK: - /* Let's count the arg numbers from a mask */ - rmh->Stat[0] = val; - size = 0; - while (val) { - if (val & 0x01) - size++; - val >>= 1; - } - rmh->LgStat = size + 1; - break; - default: - /* else retrieve the status length given by the driver */ - size = rmh->LgStat; - rmh->Stat[0] = val; /* Val is the status 1st word */ - size--; /* hence adjust remaining length */ - break; - } - - if (size < 1) - return 0; - if (snd_BUG_ON(size > SIZE_MAX_STATUS)) - return -EINVAL; - - for (i = 1; i <= size; i++) { - /* trigger an irq MESS_WRITE_NEXT */ - err = vx_send_irq_dsp(chip, IRQ_MESS_WRITE_NEXT); - if (err < 0) - return err; - /* Wait for RX full (with timeout protection) */ - err = vx_wait_for_rx_full(chip); - if (err < 0) - return err; - rmh->Stat[i] = vx_inb(chip, RXH) << 16; - rmh->Stat[i] |= vx_inb(chip, RXM) << 8; - rmh->Stat[i] |= vx_inb(chip, RXL); - } - - return vx_transfer_end(chip, IRQ_MESS_WRITE_END); -} - - -#define MASK_MORE_THAN_1_WORD_COMMAND 0x00008000 -#define MASK_1_WORD_COMMAND 0x00ff7fff - -/* - * vx_send_msg_nolock - send a DSP message and read back the status - * @rmh: the rmh record to send and receive - * - * returns 0 if successful, or a negative error code. - * the error code can be VX-specific, retrieved via vx_get_error(). - * - * this function doesn't call spinlock at all. - */ -int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) -{ - int i, err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - if ((err = vx_reset_chk(chip)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: vx_reset_chk error\n"); - return err; - } - -#if 0 - printk(KERN_DEBUG "rmh: cmd = 0x%06x, length = %d, stype = %d\n", - rmh->Cmd[0], rmh->LgCmd, rmh->DspStat); - if (rmh->LgCmd > 1) { - printk(KERN_DEBUG " "); - for (i = 1; i < rmh->LgCmd; i++) - printk("0x%06x ", rmh->Cmd[i]); - printk("\n"); - } -#endif - /* Check bit M is set according to length of the command */ - if (rmh->LgCmd > 1) - rmh->Cmd[0] |= MASK_MORE_THAN_1_WORD_COMMAND; - else - rmh->Cmd[0] &= MASK_1_WORD_COMMAND; - - /* Wait for TX empty */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: wait tx empty error\n"); - return err; - } - - /* Write Cmd[0] */ - vx_outb(chip, TXH, (rmh->Cmd[0] >> 16) & 0xff); - vx_outb(chip, TXM, (rmh->Cmd[0] >> 8) & 0xff); - vx_outb(chip, TXL, rmh->Cmd[0] & 0xff); - - /* Trigger irq MESSAGE */ - if ((err = vx_send_irq_dsp(chip, IRQ_MESSAGE)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: send IRQ_MESSAGE error\n"); - return err; - } - - /* Wait for CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) - return err; - - /* If error, get error value from RX */ - if (vx_inb(chip, ISR) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: rx_full read error\n"); - return err; - } - err = vx_inb(chip, RXH) << 16; - err |= vx_inb(chip, RXM) << 8; - err |= vx_inb(chip, RXL); - snd_printd(KERN_DEBUG "msg got error = 0x%x at cmd[0]\n", err); - err = -(VX_ERR_MASK | err); - return err; - } - - /* Send the other words */ - if (rmh->LgCmd > 1) { - for (i = 1; i < rmh->LgCmd; i++) { - /* Wait for TX ready */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: tx_ready error\n"); - return err; - } - - /* Write Cmd[i] */ - vx_outb(chip, TXH, (rmh->Cmd[i] >> 16) & 0xff); - vx_outb(chip, TXM, (rmh->Cmd[i] >> 8) & 0xff); - vx_outb(chip, TXL, rmh->Cmd[i] & 0xff); - - /* Trigger irq MESS_READ_NEXT */ - if ((err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: IRQ_READ_NEXT error\n"); - return err; - } - } - /* Wait for TX empty */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) { - snd_printd(KERN_DEBUG "vx_send_msg: TX_READY error\n"); - return err; - } - /* End of transfer */ - err = vx_transfer_end(chip, IRQ_MESS_READ_END); - if (err < 0) - return err; - } - - return vx_read_status(chip, rmh); -} - - -/* - * vx_send_msg - send a DSP message with spinlock - * @rmh: the rmh record to send and receive - * - * returns 0 if successful, or a negative error code. - * see vx_send_msg_nolock(). - */ -int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&chip->lock, flags); - err = vx_send_msg_nolock(chip, rmh); - spin_unlock_irqrestore(&chip->lock, flags); - return err; -} - - -/* - * vx_send_rih_nolock - send an RIH to xilinx - * @cmd: the command to send - * - * returns 0 if successful, or a negative error code. - * the error code can be VX-specific, retrieved via vx_get_error(). - * - * this function doesn't call spinlock at all. - * - * unlike RMH, no command is sent to DSP. - */ -int vx_send_rih_nolock(struct vx_core *chip, int cmd) -{ - int err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - -#if 0 - printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd); -#endif - if ((err = vx_reset_chk(chip)) < 0) - return err; - /* send the IRQ */ - if ((err = vx_send_irq_dsp(chip, cmd)) < 0) - return err; - /* Wait CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) - return err; - /* If error, read RX */ - if (vx_inb(chip, ISR) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) - return err; - err = vx_inb(chip, RXH) << 16; - err |= vx_inb(chip, RXM) << 8; - err |= vx_inb(chip, RXL); - return -(VX_ERR_MASK | err); - } - return 0; -} - - -/* - * vx_send_rih - send an RIH with spinlock - * @cmd: the command to send - * - * see vx_send_rih_nolock(). - */ -int vx_send_rih(struct vx_core *chip, int cmd) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&chip->lock, flags); - err = vx_send_rih_nolock(chip, cmd); - spin_unlock_irqrestore(&chip->lock, flags); - return err; -} - -#define END_OF_RESET_WAIT_TIME 500 /* us */ - -/** - * snd_vx_boot_xilinx - boot up the xilinx interface - * @boot: the boot record to load - */ -int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot) -{ - unsigned int i; - int no_fillup = vx_has_new_dsp(chip); - - /* check the length of boot image */ - if (boot->size <= 0) - return -EINVAL; - if (boot->size % 3) - return -EINVAL; -#if 0 - { - /* more strict check */ - unsigned int c = ((u32)boot->data[0] << 16) | ((u32)boot->data[1] << 8) | boot->data[2]; - if (boot->size != (c + 2) * 3) - return -EINVAL; - } -#endif - - /* reset dsp */ - vx_reset_dsp(chip); - - udelay(END_OF_RESET_WAIT_TIME); /* another wait? */ - - /* download boot strap */ - for (i = 0; i < 0x600; i += 3) { - if (i >= boot->size) { - if (no_fillup) - break; - if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) { - snd_printk(KERN_ERR "dsp boot failed at %d\n", i); - return -EIO; - } - vx_outb(chip, TXH, 0); - vx_outb(chip, TXM, 0); - vx_outb(chip, TXL, 0); - } else { - const unsigned char *image = boot->data + i; - if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) { - snd_printk(KERN_ERR "dsp boot failed at %d\n", i); - return -EIO; - } - vx_outb(chip, TXH, image[0]); - vx_outb(chip, TXM, image[1]); - vx_outb(chip, TXL, image[2]); - } - } - return 0; -} - -EXPORT_SYMBOL(snd_vx_load_boot_image); - -/* - * vx_test_irq_src - query the source of interrupts - * - * called from irq handler only - */ -static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret) -{ - int err; - - vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT); - spin_lock(&chip->lock); - err = vx_send_msg_nolock(chip, &chip->irq_rmh); - if (err < 0) - *ret = 0; - else - *ret = chip->irq_rmh.Stat[0]; - spin_unlock(&chip->lock); - return err; -} - - -/* - * vx_interrupt - soft irq handler - */ -static void vx_interrupt(unsigned long private_data) -{ - struct vx_core *chip = (struct vx_core *) private_data; - unsigned int events; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - if (vx_test_irq_src(chip, &events) < 0) - return; - -#if 0 - if (events & 0x000800) - printk(KERN_ERR "DSP Stream underrun ! IRQ events = 0x%x\n", events); -#endif - // printk(KERN_DEBUG "IRQ events = 0x%x\n", events); - - /* We must prevent any application using this DSP - * and block any further request until the application - * either unregisters or reloads the DSP - */ - if (events & FATAL_DSP_ERROR) { - snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n"); - return; - } - - /* The start on time code conditions are filled (ie the time code - * received by the board is equal to one of those given to it). - */ - if (events & TIME_CODE_EVENT_PENDING) - ; /* so far, nothing to do yet */ - - /* The frequency has changed on the board (UER mode). */ - if (events & FREQUENCY_CHANGE_EVENT_PENDING) - vx_change_frequency(chip); - - /* update the pcm streams */ - vx_pcm_update_intr(chip, events); -} - - -/** - * snd_vx_irq_handler - interrupt handler - */ -irqreturn_t snd_vx_irq_handler(int irq, void *dev) -{ - struct vx_core *chip = dev; - - if (! (chip->chip_status & VX_STAT_CHIP_INIT) || - (chip->chip_status & VX_STAT_IS_STALE)) - return IRQ_NONE; - if (! vx_test_and_ack(chip)) - tasklet_schedule(&chip->tq); - return IRQ_HANDLED; -} - -EXPORT_SYMBOL(snd_vx_irq_handler); - -/* - */ -static void vx_reset_board(struct vx_core *chip, int cold_reset) -{ - if (snd_BUG_ON(!chip->ops->reset_board)) - return; - - /* current source, later sync'ed with target */ - chip->audio_source = VX_AUDIO_SRC_LINE; - if (cold_reset) { - chip->audio_source_target = chip->audio_source; - chip->clock_source = INTERNAL_QUARTZ; - chip->clock_mode = VX_CLOCK_MODE_AUTO; - chip->freq = 48000; - chip->uer_detected = VX_UER_MODE_NOT_PRESENT; - chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF; - } - - chip->ops->reset_board(chip, cold_reset); - - vx_reset_codec(chip, cold_reset); - - vx_set_internal_clock(chip, chip->freq); - - /* Reset the DSP */ - vx_reset_dsp(chip); - - if (vx_is_pcmcia(chip)) { - /* Acknowledge any pending IRQ and reset the MEMIRQ flag. */ - vx_test_and_ack(chip); - vx_validate_irq(chip, 1); - } - - /* init CBits */ - vx_set_iec958_status(chip, chip->uer_bits); -} - - -/* - * proc interface - */ - -static void vx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct vx_core *chip = entry->private_data; - static char *audio_src_vxp[] = { "Line", "Mic", "Digital" }; - static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" }; - static char *clock_mode[] = { "Auto", "Internal", "External" }; - static char *clock_src[] = { "Internal", "External" }; - static char *uer_type[] = { "Consumer", "Professional", "Not Present" }; - - snd_iprintf(buffer, "%s\n", chip->card->longname); - snd_iprintf(buffer, "Xilinx Firmware: %s\n", - chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No"); - snd_iprintf(buffer, "Device Initialized: %s\n", - chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No"); - snd_iprintf(buffer, "DSP audio info:"); - if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME) - snd_iprintf(buffer, " realtime"); - if (chip->audio_info & VX_AUDIO_INFO_OFFLINE) - snd_iprintf(buffer, " offline"); - if (chip->audio_info & VX_AUDIO_INFO_MPEG1) - snd_iprintf(buffer, " mpeg1"); - if (chip->audio_info & VX_AUDIO_INFO_MPEG2) - snd_iprintf(buffer, " mpeg2"); - if (chip->audio_info & VX_AUDIO_INFO_LINEAR_8) - snd_iprintf(buffer, " linear8"); - if (chip->audio_info & VX_AUDIO_INFO_LINEAR_16) - snd_iprintf(buffer, " linear16"); - if (chip->audio_info & VX_AUDIO_INFO_LINEAR_24) - snd_iprintf(buffer, " linear24"); - snd_iprintf(buffer, "\n"); - snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ? - audio_src_vxp[chip->audio_source] : - audio_src_vx2[chip->audio_source]); - snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]); - snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]); - snd_iprintf(buffer, "Frequency: %d\n", chip->freq); - snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected); - snd_iprintf(buffer, "Detected UER type: %s\n", uer_type[chip->uer_detected]); - snd_iprintf(buffer, "Min/Max/Cur IBL: %d/%d/%d (granularity=%d)\n", - chip->ibl.min_size, chip->ibl.max_size, chip->ibl.size, - chip->ibl.granularity); -} - -static void vx_proc_init(struct vx_core *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "vx-status", &entry)) - snd_info_set_text_ops(entry, chip, vx_proc_read); -} - - -/** - * snd_vx_dsp_boot - load the DSP boot - */ -int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot) -{ - int err; - int cold_reset = !(chip->chip_status & VX_STAT_DEVICE_INIT); - - vx_reset_board(chip, cold_reset); - vx_validate_irq(chip, 0); - - if ((err = snd_vx_load_boot_image(chip, boot)) < 0) - return err; - msleep(10); - - return 0; -} - -EXPORT_SYMBOL(snd_vx_dsp_boot); - -/** - * snd_vx_dsp_load - load the DSP image - */ -int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) -{ - unsigned int i; - int err; - unsigned int csum = 0; - const unsigned char *image, *cptr; - - if (dsp->size % 3) - return -EINVAL; - - vx_toggle_dac_mute(chip, 1); - - /* Transfert data buffer from PC to DSP */ - for (i = 0; i < dsp->size; i += 3) { - image = dsp->data + i; - /* Wait DSP ready for a new read */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { - printk(KERN_ERR - "dsp loading error at position %d\n", i); - return err; - } - cptr = image; - csum ^= *cptr; - csum = (csum >> 24) | (csum << 8); - vx_outb(chip, TXH, *cptr++); - csum ^= *cptr; - csum = (csum >> 24) | (csum << 8); - vx_outb(chip, TXM, *cptr++); - csum ^= *cptr; - csum = (csum >> 24) | (csum << 8); - vx_outb(chip, TXL, *cptr++); - } - snd_printdd(KERN_DEBUG "checksum = 0x%08x\n", csum); - - msleep(200); - - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) - return err; - - vx_toggle_dac_mute(chip, 0); - - vx_test_and_ack(chip); - vx_validate_irq(chip, 1); - - return 0; -} - -EXPORT_SYMBOL(snd_vx_dsp_load); - -#ifdef CONFIG_PM -/* - * suspend - */ -int snd_vx_suspend(struct vx_core *chip, pm_message_t state) -{ - unsigned int i; - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - chip->chip_status |= VX_STAT_IN_SUSPEND; - for (i = 0; i < chip->hw->num_codecs; i++) - snd_pcm_suspend_all(chip->pcm[i]); - - return 0; -} - -EXPORT_SYMBOL(snd_vx_suspend); - -/* - * resume - */ -int snd_vx_resume(struct vx_core *chip) -{ - int i, err; - - chip->chip_status &= ~VX_STAT_CHIP_INIT; - - for (i = 0; i < 4; i++) { - if (! chip->firmware[i]) - continue; - err = chip->ops->load_dsp(chip, i, chip->firmware[i]); - if (err < 0) { - snd_printk(KERN_ERR "vx: firmware resume error at DSP %d\n", i); - return -EIO; - } - } - - chip->chip_status |= VX_STAT_CHIP_INIT; - chip->chip_status &= ~VX_STAT_IN_SUSPEND; - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); - return 0; -} - -EXPORT_SYMBOL(snd_vx_resume); -#endif - -/** - * snd_vx_create - constructor for struct vx_core - * @hw: hardware specific record - * - * this function allocates the instance and prepare for the hardware - * initialization. - * - * return the instance pointer if successful, NULL in error. - */ -struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw, - struct snd_vx_ops *ops, - int extra_size) -{ - struct vx_core *chip; - - if (snd_BUG_ON(!card || !hw || !ops)) - return NULL; - - chip = kzalloc(sizeof(*chip) + extra_size, GFP_KERNEL); - if (! chip) { - snd_printk(KERN_ERR "vx_core: no memory\n"); - return NULL; - } - spin_lock_init(&chip->lock); - spin_lock_init(&chip->irq_lock); - chip->irq = -1; - chip->hw = hw; - chip->type = hw->type; - chip->ops = ops; - tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip); - mutex_init(&chip->mixer_mutex); - - chip->card = card; - card->private_data = chip; - strcpy(card->driver, hw->name); - sprintf(card->shortname, "Digigram %s", hw->name); - - vx_proc_init(chip); - - return chip; -} - -EXPORT_SYMBOL(snd_vx_create); - -/* - * module entries - */ -static int __init alsa_vx_core_init(void) -{ - return 0; -} - -static void __exit alsa_vx_core_exit(void) -{ -} - -module_init(alsa_vx_core_init) -module_exit(alsa_vx_core_exit) diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_hwdep.c b/ANDROID_3.4.5/sound/drivers/vx/vx_hwdep.c deleted file mode 100644 index 4a1fae99..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_hwdep.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * DSP firmware management - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 - -#ifdef SND_VX_FW_LOADER - -MODULE_FIRMWARE("vx/bx_1_vxp.b56"); -MODULE_FIRMWARE("vx/bx_1_vp4.b56"); -MODULE_FIRMWARE("vx/x1_1_vx2.xlx"); -MODULE_FIRMWARE("vx/x1_2_v22.xlx"); -MODULE_FIRMWARE("vx/x1_1_vxp.xlx"); -MODULE_FIRMWARE("vx/x1_1_vp4.xlx"); -MODULE_FIRMWARE("vx/bd56002.boot"); -MODULE_FIRMWARE("vx/bd563v2.boot"); -MODULE_FIRMWARE("vx/bd563s3.boot"); -MODULE_FIRMWARE("vx/l_1_vx2.d56"); -MODULE_FIRMWARE("vx/l_1_v22.d56"); -MODULE_FIRMWARE("vx/l_1_vxp.d56"); -MODULE_FIRMWARE("vx/l_1_vp4.d56"); - -int snd_vx_setup_firmware(struct vx_core *chip) -{ - static char *fw_files[VX_TYPE_NUMS][4] = { - [VX_TYPE_BOARD] = { - NULL, "x1_1_vx2.xlx", "bd56002.boot", "l_1_vx2.d56", - }, - [VX_TYPE_V2] = { - NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56", - }, - [VX_TYPE_MIC] = { - NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56", - }, - [VX_TYPE_VXPOCKET] = { - "bx_1_vxp.b56", "x1_1_vxp.xlx", "bd563s3.boot", "l_1_vxp.d56" - }, - [VX_TYPE_VXP440] = { - "bx_1_vp4.b56", "x1_1_vp4.xlx", "bd563s3.boot", "l_1_vp4.d56" - }, - }; - - int i, err; - - for (i = 0; i < 4; i++) { - char path[32]; - const struct firmware *fw; - if (! fw_files[chip->type][i]) - continue; - sprintf(path, "vx/%s", fw_files[chip->type][i]); - if (request_firmware(&fw, path, chip->dev)) { - snd_printk(KERN_ERR "vx: can't load firmware %s\n", path); - return -ENOENT; - } - err = chip->ops->load_dsp(chip, i, fw); - if (err < 0) { - release_firmware(fw); - return err; - } - if (i == 1) - chip->chip_status |= VX_STAT_XILINX_LOADED; -#ifdef CONFIG_PM - chip->firmware[i] = fw; -#else - release_firmware(fw); -#endif - } - - /* ok, we reached to the last one */ - /* create the devices if not built yet */ - if ((err = snd_vx_pcm_new(chip)) < 0) - return err; - - if ((err = snd_vx_mixer_new(chip)) < 0) - return err; - - if (chip->ops->add_controls) - if ((err = chip->ops->add_controls(chip)) < 0) - return err; - - chip->chip_status |= VX_STAT_DEVICE_INIT; - chip->chip_status |= VX_STAT_CHIP_INIT; - - return snd_card_register(chip->card); -} - -/* exported */ -void snd_vx_free_firmware(struct vx_core *chip) -{ -#ifdef CONFIG_PM - int i; - for (i = 0; i < 4; i++) - release_firmware(chip->firmware[i]); -#endif -} - -#else /* old style firmware loading */ - -static int vx_hwdep_dsp_status(struct snd_hwdep *hw, - struct snd_hwdep_dsp_status *info) -{ - static char *type_ids[VX_TYPE_NUMS] = { - [VX_TYPE_BOARD] = "vxboard", - [VX_TYPE_V2] = "vx222", - [VX_TYPE_MIC] = "vx222", - [VX_TYPE_VXPOCKET] = "vxpocket", - [VX_TYPE_VXP440] = "vxp440", - }; - struct vx_core *vx = hw->private_data; - - if (snd_BUG_ON(!type_ids[vx->type])) - return -EINVAL; - strcpy(info->id, type_ids[vx->type]); - if (vx_is_pcmcia(vx)) - info->num_dsps = 4; - else - info->num_dsps = 3; - if (vx->chip_status & VX_STAT_CHIP_INIT) - info->chip_ready = 1; - info->version = VX_DRIVER_VERSION; - return 0; -} - -static void free_fw(const struct firmware *fw) -{ - if (fw) { - vfree(fw->data); - kfree(fw); - } -} - -static int vx_hwdep_dsp_load(struct snd_hwdep *hw, - struct snd_hwdep_dsp_image *dsp) -{ - struct vx_core *vx = hw->private_data; - int index, err; - struct firmware *fw; - - if (snd_BUG_ON(!vx->ops->load_dsp)) - return -ENXIO; - - fw = kmalloc(sizeof(*fw), GFP_KERNEL); - if (! fw) { - snd_printk(KERN_ERR "cannot allocate firmware\n"); - return -ENOMEM; - } - fw->size = dsp->length; - fw->data = vmalloc(fw->size); - if (! fw->data) { - snd_printk(KERN_ERR "cannot allocate firmware image (length=%d)\n", - (int)fw->size); - kfree(fw); - return -ENOMEM; - } - if (copy_from_user((void *)fw->data, dsp->image, dsp->length)) { - free_fw(fw); - return -EFAULT; - } - - index = dsp->index; - if (! vx_is_pcmcia(vx)) - index++; - err = vx->ops->load_dsp(vx, index, fw); - if (err < 0) { - free_fw(fw); - return err; - } -#ifdef CONFIG_PM - vx->firmware[index] = fw; -#else - free_fw(fw); -#endif - - if (index == 1) - vx->chip_status |= VX_STAT_XILINX_LOADED; - if (index < 3) - return 0; - - /* ok, we reached to the last one */ - /* create the devices if not built yet */ - if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) { - if ((err = snd_vx_pcm_new(vx)) < 0) - return err; - - if ((err = snd_vx_mixer_new(vx)) < 0) - return err; - - if (vx->ops->add_controls) - if ((err = vx->ops->add_controls(vx)) < 0) - return err; - - if ((err = snd_card_register(vx->card)) < 0) - return err; - - vx->chip_status |= VX_STAT_DEVICE_INIT; - } - vx->chip_status |= VX_STAT_CHIP_INIT; - return 0; -} - - -/* exported */ -int snd_vx_setup_firmware(struct vx_core *chip) -{ - int err; - struct snd_hwdep *hw; - - if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0) - return err; - - hw->iface = SNDRV_HWDEP_IFACE_VX; - hw->private_data = chip; - hw->ops.dsp_status = vx_hwdep_dsp_status; - hw->ops.dsp_load = vx_hwdep_dsp_load; - hw->exclusive = 1; - sprintf(hw->name, "VX Loader (%s)", chip->card->driver); - chip->hwdep = hw; - - return snd_card_register(chip->card); -} - -/* exported */ -void snd_vx_free_firmware(struct vx_core *chip) -{ -#ifdef CONFIG_PM - int i; - for (i = 0; i < 4; i++) - free_fw(chip->firmware[i]); -#endif -} - -#endif /* SND_VX_FW_LOADER */ - -EXPORT_SYMBOL(snd_vx_setup_firmware); -EXPORT_SYMBOL(snd_vx_free_firmware); diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_mixer.c b/ANDROID_3.4.5/sound/drivers/vx/vx_mixer.c deleted file mode 100644 index c71b8d14..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_mixer.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * Common mixer part - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 "vx_cmd.h" - - -/* - * write a codec data (24bit) - */ -static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data) -{ - unsigned long flags; - - if (snd_BUG_ON(!chip->ops->write_codec)) - return; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - spin_lock_irqsave(&chip->lock, flags); - chip->ops->write_codec(chip, codec, data); - spin_unlock_irqrestore(&chip->lock, flags); -} - -/* - * Data type used to access the Codec - */ -union vx_codec_data { - u32 l; -#ifdef SNDRV_BIG_ENDIAN - struct w { - u16 h; - u16 l; - } w; - struct b { - u8 hh; - u8 mh; - u8 ml; - u8 ll; - } b; -#else /* LITTLE_ENDIAN */ - struct w { - u16 l; - u16 h; - } w; - struct b { - u8 ll; - u8 ml; - u8 mh; - u8 hh; - } b; -#endif -}; - -#define SET_CDC_DATA_SEL(di,s) ((di).b.mh = (u8) (s)) -#define SET_CDC_DATA_REG(di,r) ((di).b.ml = (u8) (r)) -#define SET_CDC_DATA_VAL(di,d) ((di).b.ll = (u8) (d)) -#define SET_CDC_DATA_INIT(di) ((di).l = 0L, SET_CDC_DATA_SEL(di,XX_CODEC_SELECTOR)) - -/* - * set up codec register and write the value - * @codec: the codec id, 0 or 1 - * @reg: register index - * @val: data value - */ -static void vx_set_codec_reg(struct vx_core *chip, int codec, int reg, int val) -{ - union vx_codec_data data; - /* DAC control register */ - SET_CDC_DATA_INIT(data); - SET_CDC_DATA_REG(data, reg); - SET_CDC_DATA_VAL(data, val); - vx_write_codec_reg(chip, codec, data.l); -} - - -/* - * vx_set_analog_output_level - set the output attenuation level - * @codec: the output codec, 0 or 1. (1 for VXP440 only) - * @left: left output level, 0 = mute - * @right: right output level - */ -static void vx_set_analog_output_level(struct vx_core *chip, int codec, int left, int right) -{ - left = chip->hw->output_level_max - left; - right = chip->hw->output_level_max - right; - - if (chip->ops->akm_write) { - chip->ops->akm_write(chip, XX_CODEC_LEVEL_LEFT_REGISTER, left); - chip->ops->akm_write(chip, XX_CODEC_LEVEL_RIGHT_REGISTER, right); - } else { - /* convert to attenuation level: 0 = 0dB (max), 0xe3 = -113.5 dB (min) */ - vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_LEFT_REGISTER, left); - vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_RIGHT_REGISTER, right); - } -} - - -/* - * vx_toggle_dac_mute - mute/unmute DAC - * @mute: 0 = unmute, 1 = mute - */ - -#define DAC_ATTEN_MIN 0x08 -#define DAC_ATTEN_MAX 0x38 - -void vx_toggle_dac_mute(struct vx_core *chip, int mute) -{ - unsigned int i; - for (i = 0; i < chip->hw->num_codecs; i++) { - if (chip->ops->akm_write) - chip->ops->akm_write(chip, XX_CODEC_DAC_CONTROL_REGISTER, mute); /* XXX */ - else - vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER, - mute ? DAC_ATTEN_MAX : DAC_ATTEN_MIN); - } -} - -/* - * vx_reset_codec - reset and initialize the codecs - */ -void vx_reset_codec(struct vx_core *chip, int cold_reset) -{ - unsigned int i; - int port = chip->type >= VX_TYPE_VXPOCKET ? 0x75 : 0x65; - - chip->ops->reset_codec(chip); - - /* AKM codecs should be initialized in reset_codec callback */ - if (! chip->ops->akm_write) { - /* initialize old codecs */ - for (i = 0; i < chip->hw->num_codecs; i++) { - /* DAC control register (change level when zero crossing + mute) */ - vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER, DAC_ATTEN_MAX); - /* ADC control register */ - vx_set_codec_reg(chip, i, XX_CODEC_ADC_CONTROL_REGISTER, 0x00); - /* Port mode register */ - vx_set_codec_reg(chip, i, XX_CODEC_PORT_MODE_REGISTER, port); - /* Clock control register */ - vx_set_codec_reg(chip, i, XX_CODEC_CLOCK_CONTROL_REGISTER, 0x00); - } - } - - /* mute analog output */ - for (i = 0; i < chip->hw->num_codecs; i++) { - chip->output_level[i][0] = 0; - chip->output_level[i][1] = 0; - vx_set_analog_output_level(chip, i, 0, 0); - } -} - -/* - * change the audio input source - * @src: the target source (VX_AUDIO_SRC_XXX) - */ -static void vx_change_audio_source(struct vx_core *chip, int src) -{ - unsigned long flags; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - spin_lock_irqsave(&chip->lock, flags); - chip->ops->change_audio_source(chip, src); - spin_unlock_irqrestore(&chip->lock, flags); -} - - -/* - * change the audio source if necessary and possible - * returns 1 if the source is actually changed. - */ -int vx_sync_audio_source(struct vx_core *chip) -{ - if (chip->audio_source_target == chip->audio_source || - chip->pcm_running) - return 0; - vx_change_audio_source(chip, chip->audio_source_target); - chip->audio_source = chip->audio_source_target; - return 1; -} - - -/* - * audio level, mute, monitoring - */ -struct vx_audio_level { - unsigned int has_level: 1; - unsigned int has_monitor_level: 1; - unsigned int has_mute: 1; - unsigned int has_monitor_mute: 1; - unsigned int mute; - unsigned int monitor_mute; - short level; - short monitor_level; -}; - -static int vx_adjust_audio_level(struct vx_core *chip, int audio, int capture, - struct vx_audio_level *info) -{ - struct vx_rmh rmh; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - vx_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST); - if (capture) - rmh.Cmd[0] |= COMMAND_RECORD_MASK; - /* Add Audio IO mask */ - rmh.Cmd[1] = 1 << audio; - rmh.Cmd[2] = 0; - if (info->has_level) { - rmh.Cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL; - rmh.Cmd[2] |= info->level; - } - if (info->has_monitor_level) { - rmh.Cmd[0] |= VALID_AUDIO_IO_MONITORING_LEVEL; - rmh.Cmd[2] |= ((unsigned int)info->monitor_level << 10); - } - if (info->has_mute) { - rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_LEVEL; - if (info->mute) - rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_LEVEL; - } - if (info->has_monitor_mute) { - /* validate flag for M2 at least to unmute it */ - rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_MONITORING_1 | VALID_AUDIO_IO_MUTE_MONITORING_2; - if (info->monitor_mute) - rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_MONITORING_1; - } - - return vx_send_msg(chip, &rmh); -} - - -#if 0 // not used -static int vx_read_audio_level(struct vx_core *chip, int audio, int capture, - struct vx_audio_level *info) -{ - int err; - struct vx_rmh rmh; - - memset(info, 0, sizeof(*info)); - vx_init_rmh(&rmh, CMD_GET_AUDIO_LEVELS); - if (capture) - rmh.Cmd[0] |= COMMAND_RECORD_MASK; - /* Add Audio IO mask */ - rmh.Cmd[1] = 1 << audio; - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - info.level = rmh.Stat[0] & MASK_DSP_WORD_LEVEL; - info.monitor_level = (rmh.Stat[0] >> 10) & MASK_DSP_WORD_LEVEL; - info.mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_LEVEL) ? 1 : 0; - info.monitor_mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_MONITORING_1) ? 1 : 0; - return 0; -} -#endif // not used - -/* - * set the monitoring level and mute state of the given audio - * no more static, because must be called from vx_pcm to demute monitoring - */ -int vx_set_monitor_level(struct vx_core *chip, int audio, int level, int active) -{ - struct vx_audio_level info; - - memset(&info, 0, sizeof(info)); - info.has_monitor_level = 1; - info.monitor_level = level; - info.has_monitor_mute = 1; - info.monitor_mute = !active; - chip->audio_monitor[audio] = level; - chip->audio_monitor_active[audio] = active; - return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */ -} - - -/* - * set the mute status of the given audio - */ -static int vx_set_audio_switch(struct vx_core *chip, int audio, int active) -{ - struct vx_audio_level info; - - memset(&info, 0, sizeof(info)); - info.has_mute = 1; - info.mute = !active; - chip->audio_active[audio] = active; - return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */ -} - -/* - * set the mute status of the given audio - */ -static int vx_set_audio_gain(struct vx_core *chip, int audio, int capture, int level) -{ - struct vx_audio_level info; - - memset(&info, 0, sizeof(info)); - info.has_level = 1; - info.level = level; - chip->audio_gain[capture][audio] = level; - return vx_adjust_audio_level(chip, audio, capture, &info); -} - -/* - * reset all audio levels - */ -static void vx_reset_audio_levels(struct vx_core *chip) -{ - unsigned int i, c; - struct vx_audio_level info; - - memset(chip->audio_gain, 0, sizeof(chip->audio_gain)); - memset(chip->audio_active, 0, sizeof(chip->audio_active)); - memset(chip->audio_monitor, 0, sizeof(chip->audio_monitor)); - memset(chip->audio_monitor_active, 0, sizeof(chip->audio_monitor_active)); - - for (c = 0; c < 2; c++) { - for (i = 0; i < chip->hw->num_ins * 2; i++) { - memset(&info, 0, sizeof(info)); - if (c == 0) { - info.has_monitor_level = 1; - info.has_mute = 1; - info.has_monitor_mute = 1; - } - info.has_level = 1; - info.level = CVAL_0DB; /* default: 0dB */ - vx_adjust_audio_level(chip, i, c, &info); - chip->audio_gain[c][i] = CVAL_0DB; - chip->audio_monitor[i] = CVAL_0DB; - } - } -} - - -/* - * VU, peak meter record - */ - -#define VU_METER_CHANNELS 2 - -struct vx_vu_meter { - int saturated; - int vu_level; - int peak_level; -}; - -/* - * get the VU and peak meter values - * @audio: the audio index - * @capture: 0 = playback, 1 = capture operation - * @info: the array of vx_vu_meter records (size = 2). - */ -static int vx_get_audio_vu_meter(struct vx_core *chip, int audio, int capture, struct vx_vu_meter *info) -{ - struct vx_rmh rmh; - int i, err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - vx_init_rmh(&rmh, CMD_AUDIO_VU_PIC_METER); - rmh.LgStat += 2 * VU_METER_CHANNELS; - if (capture) - rmh.Cmd[0] |= COMMAND_RECORD_MASK; - - /* Add Audio IO mask */ - rmh.Cmd[1] = 0; - for (i = 0; i < VU_METER_CHANNELS; i++) - rmh.Cmd[1] |= 1 << (audio + i); - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - /* Read response */ - for (i = 0; i < 2 * VU_METER_CHANNELS; i +=2) { - info->saturated = (rmh.Stat[0] & (1 << (audio + i))) ? 1 : 0; - info->vu_level = rmh.Stat[i + 1]; - info->peak_level = rmh.Stat[i + 2]; - info++; - } - return 0; -} - - -/* - * control API entries - */ - -/* - * output level control - */ -static int vx_output_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = chip->hw->output_level_max; - return 0; -} - -static int vx_output_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int codec = kcontrol->id.index; - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->output_level[codec][0]; - ucontrol->value.integer.value[1] = chip->output_level[codec][1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int codec = kcontrol->id.index; - unsigned int val[2], vmax; - - vmax = chip->hw->output_level_max; - val[0] = ucontrol->value.integer.value[0]; - val[1] = ucontrol->value.integer.value[1]; - if (val[0] > vmax || val[1] > vmax) - return -EINVAL; - mutex_lock(&chip->mixer_mutex); - if (val[0] != chip->output_level[codec][0] || - val[1] != chip->output_level[codec][1]) { - vx_set_analog_output_level(chip, codec, val[0], val[1]); - chip->output_level[codec][0] = val[0]; - chip->output_level[codec][1] = val[1]; - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_output_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Master Playback Volume", - .info = vx_output_level_info, - .get = vx_output_level_get, - .put = vx_output_level_put, - /* tlv will be filled later */ -}; - -/* - * audio source select - */ -static int vx_audio_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts_mic[3] = { - "Digital", "Line", "Mic" - }; - static char *texts_vx2[2] = { - "Digital", "Analog" - }; - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - if (chip->type >= VX_TYPE_VXPOCKET) { - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, - texts_mic[uinfo->value.enumerated.item]); - } else { - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - texts_vx2[uinfo->value.enumerated.item]); - } - return 0; -} - -static int vx_audio_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = chip->audio_source_target; - return 0; -} - -static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - - if (chip->type >= VX_TYPE_VXPOCKET) { - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - } else { - if (ucontrol->value.enumerated.item[0] > 1) - return -EINVAL; - } - mutex_lock(&chip->mixer_mutex); - if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) { - chip->audio_source_target = ucontrol->value.enumerated.item[0]; - vx_sync_audio_source(chip); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_audio_src = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = vx_audio_src_info, - .get = vx_audio_src_get, - .put = vx_audio_src_put, -}; - -/* - * clock mode selection - */ -static int vx_clock_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { - "Auto", "Internal", "External" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int vx_clock_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = chip->clock_mode; - return 0; -} - -static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - mutex_lock(&chip->mixer_mutex); - if (chip->clock_mode != ucontrol->value.enumerated.item[0]) { - chip->clock_mode = ucontrol->value.enumerated.item[0]; - vx_set_clock(chip, chip->freq); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_clock_mode = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Clock Mode", - .info = vx_clock_mode_info, - .get = vx_clock_mode_get, - .put = vx_clock_mode_put, -}; - -/* - * Audio Gain - */ -static int vx_audio_gain_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = CVAL_MAX; - return 0; -} - -static int vx_audio_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - int capture = (kcontrol->private_value >> 8) & 1; - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio]; - ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_audio_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - int capture = (kcontrol->private_value >> 8) & 1; - unsigned int val[2]; - - val[0] = ucontrol->value.integer.value[0]; - val[1] = ucontrol->value.integer.value[1]; - if (val[0] > CVAL_MAX || val[1] > CVAL_MAX) - return -EINVAL; - mutex_lock(&chip->mixer_mutex); - if (val[0] != chip->audio_gain[capture][audio] || - val[1] != chip->audio_gain[capture][audio+1]) { - vx_set_audio_gain(chip, audio, capture, val[0]); - vx_set_audio_gain(chip, audio+1, capture, val[1]); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_audio_monitor_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->audio_monitor[audio]; - ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - unsigned int val[2]; - - val[0] = ucontrol->value.integer.value[0]; - val[1] = ucontrol->value.integer.value[1]; - if (val[0] > CVAL_MAX || val[1] > CVAL_MAX) - return -EINVAL; - - mutex_lock(&chip->mixer_mutex); - if (val[0] != chip->audio_monitor[audio] || - val[1] != chip->audio_monitor[audio+1]) { - vx_set_monitor_level(chip, audio, val[0], - chip->audio_monitor_active[audio]); - vx_set_monitor_level(chip, audio+1, val[1], - chip->audio_monitor_active[audio+1]); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -#define vx_audio_sw_info snd_ctl_boolean_stereo_info - -static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->audio_active[audio]; - ucontrol->value.integer.value[1] = chip->audio_active[audio+1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - if (ucontrol->value.integer.value[0] != chip->audio_active[audio] || - ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) { - vx_set_audio_switch(chip, audio, - !!ucontrol->value.integer.value[0]); - vx_set_audio_switch(chip, audio+1, - !!ucontrol->value.integer.value[1]); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio]; - ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1]; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - int audio = kcontrol->private_value & 0xff; - - mutex_lock(&chip->mixer_mutex); - if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] || - ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) { - vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], - !!ucontrol->value.integer.value[0]); - vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], - !!ucontrol->value.integer.value[1]); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); - -static struct snd_kcontrol_new vx_control_audio_gain = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - /* name will be filled later */ - .info = vx_audio_gain_info, - .get = vx_audio_gain_get, - .put = vx_audio_gain_put, - .tlv = { .p = db_scale_audio_gain }, -}; -static struct snd_kcontrol_new vx_control_output_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .info = vx_audio_sw_info, - .get = vx_audio_sw_get, - .put = vx_audio_sw_put -}; -static struct snd_kcontrol_new vx_control_monitor_gain = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitoring Volume", - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .info = vx_audio_gain_info, /* shared */ - .get = vx_audio_monitor_get, - .put = vx_audio_monitor_put, - .tlv = { .p = db_scale_audio_gain }, -}; -static struct snd_kcontrol_new vx_control_monitor_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitoring Switch", - .info = vx_audio_sw_info, /* shared */ - .get = vx_monitor_sw_get, - .put = vx_monitor_sw_put -}; - - -/* - * IEC958 status bits - */ -static int vx_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int vx_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - - mutex_lock(&chip->mixer_mutex); - ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff; - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static int vx_iec958_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - unsigned int val; - - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - mutex_lock(&chip->mixer_mutex); - if (chip->uer_bits != val) { - chip->uer_bits = val; - vx_set_iec958_status(chip, val); - mutex_unlock(&chip->mixer_mutex); - return 1; - } - mutex_unlock(&chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_iec958_mask = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .info = vx_iec958_info, /* shared */ - .get = vx_iec958_mask_get, -}; - -static struct snd_kcontrol_new vx_control_iec958 = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = vx_iec958_info, - .get = vx_iec958_get, - .put = vx_iec958_put -}; - - -/* - * VU meter - */ - -#define METER_MAX 0xff -#define METER_SHIFT 16 - -static int vx_vu_meter_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = METER_MAX; - return 0; -} - -static int vx_vu_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - struct vx_vu_meter meter[2]; - int audio = kcontrol->private_value & 0xff; - int capture = (kcontrol->private_value >> 8) & 1; - - vx_get_audio_vu_meter(chip, audio, capture, meter); - ucontrol->value.integer.value[0] = meter[0].vu_level >> METER_SHIFT; - ucontrol->value.integer.value[1] = meter[1].vu_level >> METER_SHIFT; - return 0; -} - -static int vx_peak_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - struct vx_vu_meter meter[2]; - int audio = kcontrol->private_value & 0xff; - int capture = (kcontrol->private_value >> 8) & 1; - - vx_get_audio_vu_meter(chip, audio, capture, meter); - ucontrol->value.integer.value[0] = meter[0].peak_level >> METER_SHIFT; - ucontrol->value.integer.value[1] = meter[1].peak_level >> METER_SHIFT; - return 0; -} - -#define vx_saturation_info snd_ctl_boolean_stereo_info - -static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *chip = snd_kcontrol_chip(kcontrol); - struct vx_vu_meter meter[2]; - int audio = kcontrol->private_value & 0xff; - - vx_get_audio_vu_meter(chip, audio, 1, meter); /* capture only */ - ucontrol->value.integer.value[0] = meter[0].saturated; - ucontrol->value.integer.value[1] = meter[1].saturated; - return 0; -} - -static struct snd_kcontrol_new vx_control_vu_meter = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - /* name will be filled later */ - .info = vx_vu_meter_info, - .get = vx_vu_meter_get, -}; - -static struct snd_kcontrol_new vx_control_peak_meter = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - /* name will be filled later */ - .info = vx_vu_meter_info, /* shared */ - .get = vx_peak_meter_get, -}; - -static struct snd_kcontrol_new vx_control_saturation = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Saturation", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = vx_saturation_info, - .get = vx_saturation_get, -}; - - - -/* - * - */ - -int snd_vx_mixer_new(struct vx_core *chip) -{ - unsigned int i, c; - int err; - struct snd_kcontrol_new temp; - struct snd_card *card = chip->card; - char name[32]; - - strcpy(card->mixername, card->driver); - - /* output level controls */ - for (i = 0; i < chip->hw->num_outs; i++) { - temp = vx_control_output_level; - temp.index = i; - temp.tlv.p = chip->hw->output_level_db_scale; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - - /* PCM volumes, switches, monitoring */ - for (i = 0; i < chip->hw->num_outs; i++) { - int val = i * 2; - temp = vx_control_audio_gain; - temp.index = i; - temp.name = "PCM Playback Volume"; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - temp = vx_control_output_switch; - temp.index = i; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - temp = vx_control_monitor_gain; - temp.index = i; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - temp = vx_control_monitor_switch; - temp.index = i; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - for (i = 0; i < chip->hw->num_outs; i++) { - temp = vx_control_audio_gain; - temp.index = i; - temp.name = "PCM Capture Volume"; - temp.private_value = (i * 2) | (1 << 8); - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - - /* Audio source */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0) - return err; - /* clock mode */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0) - return err; - /* IEC958 controls */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0) - return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0) - return err; - /* VU, peak, saturation meters */ - for (c = 0; c < 2; c++) { - static char *dir[2] = { "Output", "Input" }; - for (i = 0; i < chip->hw->num_ins; i++) { - int val = (i * 2) | (c << 8); - if (c == 1) { - temp = vx_control_saturation; - temp.index = i; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - sprintf(name, "%s VU Meter", dir[c]); - temp = vx_control_vu_meter; - temp.index = i; - temp.name = name; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - sprintf(name, "%s Peak Meter", dir[c]); - temp = vx_control_peak_meter; - temp.index = i; - temp.name = name; - temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - } - vx_reset_audio_levels(chip); - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_pcm.c b/ANDROID_3.4.5/sound/drivers/vx/vx_pcm.c deleted file mode 100644 index 5e897b23..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_pcm.c +++ /dev/null @@ -1,1283 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * PCM part - * - * Copyright (c) 2002,2003 by Takashi Iwai - * - * 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 - * - * - * STRATEGY - * for playback, we send series of "chunks", which size is equal with the - * IBL size, typically 126 samples. at each end of chunk, the end-of-buffer - * interrupt is notified, and the interrupt handler will feed the next chunk. - * - * the current position is calculated from the sample count RMH. - * pipe->transferred is the counter of data which has been already transferred. - * if this counter reaches to the period size, snd_pcm_period_elapsed() will - * be issued. - * - * for capture, the situation is much easier. - * to get a low latency response, we'll check the capture streams at each - * interrupt (capture stream has no EOB notification). if the pending - * data is accumulated to the period size, snd_pcm_period_elapsed() is - * called and the pointer is updated. - * - * the current point of read buffer is kept in pipe->hw_ptr. note that - * this is in bytes. - * - * - * TODO - * - linked trigger for full-duplex mode. - * - scheduled action on the stream. - */ - -#include -#include -#include -#include -#include -#include -#include "vx_cmd.h" - - -/* - * read three pending pcm bytes via inb() - */ -static void vx_pcm_read_per_bytes(struct vx_core *chip, struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe) -{ - int offset = pipe->hw_ptr; - unsigned char *buf = (unsigned char *)(runtime->dma_area + offset); - *buf++ = vx_inb(chip, RXH); - if (++offset >= pipe->buffer_bytes) { - offset = 0; - buf = (unsigned char *)runtime->dma_area; - } - *buf++ = vx_inb(chip, RXM); - if (++offset >= pipe->buffer_bytes) { - offset = 0; - buf = (unsigned char *)runtime->dma_area; - } - *buf++ = vx_inb(chip, RXL); - if (++offset >= pipe->buffer_bytes) { - offset = 0; - buf = (unsigned char *)runtime->dma_area; - } - pipe->hw_ptr = offset; -} - -/* - * vx_set_pcx_time - convert from the PC time to the RMH status time. - * @pc_time: the pointer for the PC-time to set - * @dsp_time: the pointer for RMH status time array - */ -static void vx_set_pcx_time(struct vx_core *chip, pcx_time_t *pc_time, - unsigned int *dsp_time) -{ - dsp_time[0] = (unsigned int)((*pc_time) >> 24) & PCX_TIME_HI_MASK; - dsp_time[1] = (unsigned int)(*pc_time) & MASK_DSP_WORD; -} - -/* - * vx_set_differed_time - set the differed time if specified - * @rmh: the rmh record to modify - * @pipe: the pipe to be checked - * - * if the pipe is programmed with the differed time, set the DSP time - * on the rmh and changes its command length. - * - * returns the increase of the command length. - */ -static int vx_set_differed_time(struct vx_core *chip, struct vx_rmh *rmh, - struct vx_pipe *pipe) -{ - /* Update The length added to the RMH command by the timestamp */ - if (! (pipe->differed_type & DC_DIFFERED_DELAY)) - return 0; - - /* Set the T bit */ - rmh->Cmd[0] |= DSP_DIFFERED_COMMAND_MASK; - - /* Time stamp is the 1st following parameter */ - vx_set_pcx_time(chip, &pipe->pcx_time, &rmh->Cmd[1]); - - /* Add the flags to a notified differed command */ - if (pipe->differed_type & DC_NOTIFY_DELAY) - rmh->Cmd[1] |= NOTIFY_MASK_TIME_HIGH ; - - /* Add the flags to a multiple differed command */ - if (pipe->differed_type & DC_MULTIPLE_DELAY) - rmh->Cmd[1] |= MULTIPLE_MASK_TIME_HIGH; - - /* Add the flags to a stream-time differed command */ - if (pipe->differed_type & DC_STREAM_TIME_DELAY) - rmh->Cmd[1] |= STREAM_MASK_TIME_HIGH; - - rmh->LgCmd += 2; - return 2; -} - -/* - * vx_set_stream_format - send the stream format command - * @pipe: the affected pipe - * @data: format bitmask - */ -static int vx_set_stream_format(struct vx_core *chip, struct vx_pipe *pipe, - unsigned int data) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, pipe->is_capture ? - CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT); - rmh.Cmd[0] |= pipe->number << FIELD_SIZE; - - /* Command might be longer since we may have to add a timestamp */ - vx_set_differed_time(chip, &rmh, pipe); - - rmh.Cmd[rmh.LgCmd] = (data & 0xFFFFFF00) >> 8; - rmh.Cmd[rmh.LgCmd + 1] = (data & 0xFF) << 16 /*| (datal & 0xFFFF00) >> 8*/; - rmh.LgCmd += 2; - - return vx_send_msg(chip, &rmh); -} - - -/* - * vx_set_format - set the format of a pipe - * @pipe: the affected pipe - * @runtime: pcm runtime instance to be referred - * - * returns 0 if successful, or a negative error code. - */ -static int vx_set_format(struct vx_core *chip, struct vx_pipe *pipe, - struct snd_pcm_runtime *runtime) -{ - unsigned int header = HEADER_FMT_BASE; - - if (runtime->channels == 1) - header |= HEADER_FMT_MONO; - if (snd_pcm_format_little_endian(runtime->format)) - header |= HEADER_FMT_INTEL; - if (runtime->rate < 32000 && runtime->rate > 11025) - header |= HEADER_FMT_UPTO32; - else if (runtime->rate <= 11025) - header |= HEADER_FMT_UPTO11; - - switch (snd_pcm_format_physical_width(runtime->format)) { - // case 8: break; - case 16: header |= HEADER_FMT_16BITS; break; - case 24: header |= HEADER_FMT_24BITS; break; - default : - snd_BUG(); - return -EINVAL; - }; - - return vx_set_stream_format(chip, pipe, header); -} - -/* - * set / query the IBL size - */ -static int vx_set_ibl(struct vx_core *chip, struct vx_ibl_info *info) -{ - int err; - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_IBL); - rmh.Cmd[0] |= info->size & 0x03ffff; - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - info->size = rmh.Stat[0]; - info->max_size = rmh.Stat[1]; - info->min_size = rmh.Stat[2]; - info->granularity = rmh.Stat[3]; - snd_printdd(KERN_DEBUG "vx_set_ibl: size = %d, max = %d, min = %d, gran = %d\n", - info->size, info->max_size, info->min_size, info->granularity); - return 0; -} - - -/* - * vx_get_pipe_state - get the state of a pipe - * @pipe: the pipe to be checked - * @state: the pointer for the returned state - * - * checks the state of a given pipe, and stores the state (1 = running, - * 0 = paused) on the given pointer. - * - * called from trigger callback only - */ -static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *state) -{ - int err; - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_PIPE_STATE); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ - if (! err) - *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0; - return err; -} - - -/* - * vx_query_hbuffer_size - query available h-buffer size in bytes - * @pipe: the pipe to be checked - * - * return the available size on h-buffer in bytes, - * or a negative error code. - * - * NOTE: calling this function always switches to the stream mode. - * you'll need to disconnect the host to get back to the - * normal mode. - */ -static int vx_query_hbuffer_size(struct vx_core *chip, struct vx_pipe *pipe) -{ - int result; - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_SIZE_HBUFFER); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - if (pipe->is_capture) - rmh.Cmd[0] |= 0x00000001; - result = vx_send_msg(chip, &rmh); - if (! result) - result = rmh.Stat[0] & 0xffff; - return result; -} - - -/* - * vx_pipe_can_start - query whether a pipe is ready for start - * @pipe: the pipe to be checked - * - * return 1 if ready, 0 if not ready, and negative value on error. - * - * called from trigger callback only - */ -static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe) -{ - int err; - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_CAN_START_PIPE); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - rmh.Cmd[0] |= 1; - - err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ - if (! err) { - if (rmh.Stat[0]) - err = 1; - } - return err; -} - -/* - * vx_conf_pipe - tell the pipe to stand by and wait for IRQA. - * @pipe: the pipe to be configured - */ -static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_CONF_PIPE); - if (pipe->is_capture) - rmh.Cmd[0] |= COMMAND_RECORD_MASK; - rmh.Cmd[1] = 1 << pipe->number; - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - -/* - * vx_send_irqa - trigger IRQA - */ -static int vx_send_irqa(struct vx_core *chip) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_SEND_IRQA); - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - - -#define MAX_WAIT_FOR_DSP 250 -/* - * vx boards do not support inter-card sync, besides - * only 126 samples require to be prepared before a pipe can start - */ -#define CAN_START_DELAY 2 /* wait 2ms only before asking if the pipe is ready*/ -#define WAIT_STATE_DELAY 2 /* wait 2ms after irqA was requested and check if the pipe state toggled*/ - -/* - * vx_toggle_pipe - start / pause a pipe - * @pipe: the pipe to be triggered - * @state: start = 1, pause = 0 - * - * called from trigger callback only - * - */ -static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state) -{ - int err, i, cur_state; - - /* Check the pipe is not already in the requested state */ - if (vx_get_pipe_state(chip, pipe, &cur_state) < 0) - return -EBADFD; - if (state == cur_state) - return 0; - - /* If a start is requested, ask the DSP to get prepared - * and wait for a positive acknowledge (when there are - * enough sound buffer for this pipe) - */ - if (state) { - for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) { - err = vx_pipe_can_start(chip, pipe); - if (err > 0) - break; - /* Wait for a few, before asking again - * to avoid flooding the DSP with our requests - */ - mdelay(1); - } - } - - if ((err = vx_conf_pipe(chip, pipe)) < 0) - return err; - - if ((err = vx_send_irqa(chip)) < 0) - return err; - - /* If it completes successfully, wait for the pipes - * reaching the expected state before returning - * Check one pipe only (since they are synchronous) - */ - for (i = 0; i < MAX_WAIT_FOR_DSP; i++) { - err = vx_get_pipe_state(chip, pipe, &cur_state); - if (err < 0 || cur_state == state) - break; - err = -EIO; - mdelay(1); - } - return err < 0 ? -EIO : 0; -} - - -/* - * vx_stop_pipe - stop a pipe - * @pipe: the pipe to be stopped - * - * called from trigger callback only - */ -static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - vx_init_rmh(&rmh, CMD_STOP_PIPE); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - - -/* - * vx_alloc_pipe - allocate a pipe and initialize the pipe instance - * @capture: 0 = playback, 1 = capture operation - * @audioid: the audio id to be assigned - * @num_audio: number of audio channels - * @pipep: the returned pipe instance - * - * return 0 on success, or a negative error code. - */ -static int vx_alloc_pipe(struct vx_core *chip, int capture, - int audioid, int num_audio, - struct vx_pipe **pipep) -{ - int err; - struct vx_pipe *pipe; - struct vx_rmh rmh; - int data_mode; - - *pipep = NULL; - vx_init_rmh(&rmh, CMD_RES_PIPE); - vx_set_pipe_cmd_params(&rmh, capture, audioid, num_audio); -#if 0 // NYI - if (underrun_skip_sound) - rmh.Cmd[0] |= BIT_SKIP_SOUND; -#endif // NYI - data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0; - if (! capture && data_mode) - rmh.Cmd[0] |= BIT_DATA_MODE; - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - - /* initialize the pipe record */ - pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); - if (! pipe) { - /* release the pipe */ - vx_init_rmh(&rmh, CMD_FREE_PIPE); - vx_set_pipe_cmd_params(&rmh, capture, audioid, 0); - vx_send_msg(chip, &rmh); - return -ENOMEM; - } - - /* the pipe index should be identical with the audio index */ - pipe->number = audioid; - pipe->is_capture = capture; - pipe->channels = num_audio; - pipe->differed_type = 0; - pipe->pcx_time = 0; - pipe->data_mode = data_mode; - *pipep = pipe; - - return 0; -} - - -/* - * vx_free_pipe - release a pipe - * @pipe: pipe to be released - */ -static int vx_free_pipe(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_FREE_PIPE); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - vx_send_msg(chip, &rmh); - - kfree(pipe); - return 0; -} - - -/* - * vx_start_stream - start the stream - * - * called from trigger callback only - */ -static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_START_ONE_STREAM); - vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); - vx_set_differed_time(chip, &rmh, pipe); - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - - -/* - * vx_stop_stream - stop the stream - * - * called from trigger callback only - */ -static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_STOP_STREAM); - vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number); - return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */ -} - - -/* - * playback hw information - */ - -static struct snd_pcm_hardware vx_pcm_playback_hw = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/ - /*SNDRV_PCM_INFO_RESUME*/), - .formats = (/*SNDRV_PCM_FMTBIT_U8 |*/ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 126, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = VX_MAX_PERIODS, - .fifo_size = 126, -}; - - -static void vx_pcm_delayed_start(unsigned long arg); - -/* - * vx_pcm_playback_open - open callback for playback - */ -static int vx_pcm_playback_open(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe = NULL; - unsigned int audio; - int err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - audio = subs->pcm->device * 2; - if (snd_BUG_ON(audio >= chip->audio_outs)) - return -EINVAL; - - /* playback pipe may have been already allocated for monitoring */ - pipe = chip->playback_pipes[audio]; - if (! pipe) { - /* not allocated yet */ - err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */ - if (err < 0) - return err; - chip->playback_pipes[audio] = pipe; - } - /* open for playback */ - pipe->references++; - - pipe->substream = subs; - tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs); - chip->playback_pipes[audio] = pipe; - - runtime->hw = vx_pcm_playback_hw; - runtime->hw.period_bytes_min = chip->ibl.size; - runtime->private_data = pipe; - - /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); - - return 0; -} - -/* - * vx_pcm_playback_close - close callback for playback - */ -static int vx_pcm_playback_close(struct snd_pcm_substream *subs) -{ - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe; - - if (! subs->runtime->private_data) - return -EINVAL; - - pipe = subs->runtime->private_data; - - if (--pipe->references == 0) { - chip->playback_pipes[pipe->number] = NULL; - vx_free_pipe(chip, pipe); - } - - return 0; - -} - - -/* - * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe - * @pipe: the pipe to notify - * - * NB: call with a certain lock. - */ -static int vx_notify_end_of_buffer(struct vx_core *chip, struct vx_pipe *pipe) -{ - int err; - struct vx_rmh rmh; /* use a temporary rmh here */ - - /* Toggle Dsp Host Interface into Message mode */ - vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT); - vx_init_rmh(&rmh, CMD_NOTIFY_END_OF_BUFFER); - vx_set_stream_cmd_params(&rmh, 0, pipe->number); - err = vx_send_msg_nolock(chip, &rmh); - if (err < 0) - return err; - /* Toggle Dsp Host Interface back to sound transfer mode */ - vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT); - return 0; -} - -/* - * vx_pcm_playback_transfer_chunk - transfer a single chunk - * @subs: substream - * @pipe: the pipe to transfer - * @size: chunk size in bytes - * - * transfer a single buffer chunk. EOB notificaton is added after that. - * called from the interrupt handler, too. - * - * return 0 if ok. - */ -static int vx_pcm_playback_transfer_chunk(struct vx_core *chip, - struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe, int size) -{ - int space, err = 0; - - space = vx_query_hbuffer_size(chip, pipe); - if (space < 0) { - /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ - vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); - snd_printd("error hbuffer\n"); - return space; - } - if (space < size) { - vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT); - snd_printd("no enough hbuffer space %d\n", space); - return -EIO; /* XRUN */ - } - - /* we don't need irqsave here, because this function - * is called from either trigger callback or irq handler - */ - spin_lock(&chip->lock); - vx_pseudo_dma_write(chip, runtime, pipe, size); - err = vx_notify_end_of_buffer(chip, pipe); - /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ - vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); - spin_unlock(&chip->lock); - return err; -} - -/* - * update the position of the given pipe. - * pipe->position is updated and wrapped within the buffer size. - * pipe->transferred is updated, too, but the size is not wrapped, - * so that the caller can check the total transferred size later - * (to call snd_pcm_period_elapsed). - */ -static int vx_update_pipe_position(struct vx_core *chip, - struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe) -{ - struct vx_rmh rmh; - int err, update; - u64 count; - - vx_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT); - vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0); - err = vx_send_msg(chip, &rmh); - if (err < 0) - return err; - - count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1]; - update = (int)(count - pipe->cur_count); - pipe->cur_count = count; - pipe->position += update; - if (pipe->position >= (int)runtime->buffer_size) - pipe->position %= runtime->buffer_size; - pipe->transferred += update; - return 0; -} - -/* - * transfer the pending playback buffer data to DSP - * called from interrupt handler - */ -static void vx_pcm_playback_transfer(struct vx_core *chip, - struct snd_pcm_substream *subs, - struct vx_pipe *pipe, int nchunks) -{ - int i, err; - struct snd_pcm_runtime *runtime = subs->runtime; - - if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) - return; - for (i = 0; i < nchunks; i++) { - if ((err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe, - chip->ibl.size)) < 0) - return; - } -} - -/* - * update the playback position and call snd_pcm_period_elapsed() if necessary - * called from interrupt handler - */ -static void vx_pcm_playback_update(struct vx_core *chip, - struct snd_pcm_substream *subs, - struct vx_pipe *pipe) -{ - int err; - struct snd_pcm_runtime *runtime = subs->runtime; - - if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) { - if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0) - return; - if (pipe->transferred >= (int)runtime->period_size) { - pipe->transferred %= runtime->period_size; - snd_pcm_period_elapsed(subs); - } - } -} - -/* - * start the stream and pipe. - * this function is called from tasklet, which is invoked by the trigger - * START callback. - */ -static void vx_pcm_delayed_start(unsigned long arg) -{ - struct snd_pcm_substream *subs = (struct snd_pcm_substream *)arg; - struct vx_core *chip = subs->pcm->private_data; - struct vx_pipe *pipe = subs->runtime->private_data; - int err; - - /* printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/ - - if ((err = vx_start_stream(chip, pipe)) < 0) { - snd_printk(KERN_ERR "vx: cannot start stream\n"); - return; - } - if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) { - snd_printk(KERN_ERR "vx: cannot start pipe\n"); - return; - } - /* printk( KERN_DEBUG "dddd tasklet delayed start jiffies = %ld \n", jiffies);*/ -} - -/* - * vx_pcm_playback_trigger - trigger callback for playback - */ -static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe = subs->runtime->private_data; - int err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (! pipe->is_capture) - vx_pcm_playback_transfer(chip, subs, pipe, 2); - /* FIXME: - * we trigger the pipe using tasklet, so that the interrupts are - * issued surely after the trigger is completed. - */ - tasklet_schedule(&pipe->start_tq); - chip->pcm_running++; - pipe->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - vx_toggle_pipe(chip, pipe, 0); - vx_stop_pipe(chip, pipe); - vx_stop_stream(chip, pipe); - chip->pcm_running--; - pipe->running = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if ((err = vx_toggle_pipe(chip, pipe, 0)) < 0) - return err; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) - return err; - break; - default: - return -EINVAL; - } - return 0; -} - -/* - * vx_pcm_playback_pointer - pointer callback for playback - */ -static snd_pcm_uframes_t vx_pcm_playback_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_pipe *pipe = runtime->private_data; - return pipe->position; -} - -/* - * vx_pcm_hw_params - hw_params callback for playback and capture - */ -static int vx_pcm_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_alloc_vmalloc_32_buffer - (subs, params_buffer_bytes(hw_params)); -} - -/* - * vx_pcm_hw_free - hw_free callback for playback and capture - */ -static int vx_pcm_hw_free(struct snd_pcm_substream *subs) -{ - return snd_pcm_lib_free_vmalloc_buffer(subs); -} - -/* - * vx_pcm_prepare - prepare callback for playback and capture - */ -static int vx_pcm_prepare(struct snd_pcm_substream *subs) -{ - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_pipe *pipe = runtime->private_data; - int err, data_mode; - // int max_size, nchunks; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0; - if (data_mode != pipe->data_mode && ! pipe->is_capture) { - /* IEC958 status (raw-mode) was changed */ - /* we reopen the pipe */ - struct vx_rmh rmh; - snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode); - vx_init_rmh(&rmh, CMD_FREE_PIPE); - vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0); - if ((err = vx_send_msg(chip, &rmh)) < 0) - return err; - vx_init_rmh(&rmh, CMD_RES_PIPE); - vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels); - if (data_mode) - rmh.Cmd[0] |= BIT_DATA_MODE; - if ((err = vx_send_msg(chip, &rmh)) < 0) - return err; - pipe->data_mode = data_mode; - } - - if (chip->pcm_running && chip->freq != runtime->rate) { - snd_printk(KERN_ERR "vx: cannot set different clock %d " - "from the current %d\n", runtime->rate, chip->freq); - return -EINVAL; - } - vx_set_clock(chip, runtime->rate); - - if ((err = vx_set_format(chip, pipe, runtime)) < 0) - return err; - - if (vx_is_pcmcia(chip)) { - pipe->align = 2; /* 16bit word */ - } else { - pipe->align = 4; /* 32bit word */ - } - - pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); - pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size); - pipe->hw_ptr = 0; - - /* set the timestamp */ - vx_update_pipe_position(chip, runtime, pipe); - /* clear again */ - pipe->transferred = 0; - pipe->position = 0; - - pipe->prepared = 1; - - return 0; -} - - -/* - * operators for PCM playback - */ -static struct snd_pcm_ops vx_pcm_playback_ops = { - .open = vx_pcm_playback_open, - .close = vx_pcm_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = vx_pcm_hw_params, - .hw_free = vx_pcm_hw_free, - .prepare = vx_pcm_prepare, - .trigger = vx_pcm_trigger, - .pointer = vx_pcm_playback_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - - -/* - * playback hw information - */ - -static struct snd_pcm_hardware vx_pcm_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID /*|*/ - /*SNDRV_PCM_INFO_RESUME*/), - .formats = (/*SNDRV_PCM_FMTBIT_U8 |*/ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 126, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = VX_MAX_PERIODS, - .fifo_size = 126, -}; - - -/* - * vx_pcm_capture_open - open callback for capture - */ -static int vx_pcm_capture_open(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe; - struct vx_pipe *pipe_out_monitoring = NULL; - unsigned int audio; - int err; - - if (chip->chip_status & VX_STAT_IS_STALE) - return -EBUSY; - - audio = subs->pcm->device * 2; - if (snd_BUG_ON(audio >= chip->audio_ins)) - return -EINVAL; - err = vx_alloc_pipe(chip, 1, audio, 2, &pipe); - if (err < 0) - return err; - pipe->substream = subs; - tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs); - chip->capture_pipes[audio] = pipe; - - /* check if monitoring is needed */ - if (chip->audio_monitor_active[audio]) { - pipe_out_monitoring = chip->playback_pipes[audio]; - if (! pipe_out_monitoring) { - /* allocate a pipe */ - err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring); - if (err < 0) - return err; - chip->playback_pipes[audio] = pipe_out_monitoring; - } - pipe_out_monitoring->references++; - /* - if an output pipe is available, it's audios still may need to be - unmuted. hence we'll have to call a mixer entry point. - */ - vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], - chip->audio_monitor_active[audio]); - /* assuming stereo */ - vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], - chip->audio_monitor_active[audio+1]); - } - - pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */ - - runtime->hw = vx_pcm_capture_hw; - runtime->hw.period_bytes_min = chip->ibl.size; - runtime->private_data = pipe; - - /* align to 4 bytes (otherwise will be problematic when 24bit is used) */ - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); - - return 0; -} - -/* - * vx_pcm_capture_close - close callback for capture - */ -static int vx_pcm_capture_close(struct snd_pcm_substream *subs) -{ - struct vx_core *chip = snd_pcm_substream_chip(subs); - struct vx_pipe *pipe; - struct vx_pipe *pipe_out_monitoring; - - if (! subs->runtime->private_data) - return -EINVAL; - pipe = subs->runtime->private_data; - chip->capture_pipes[pipe->number] = NULL; - - pipe_out_monitoring = pipe->monitoring_pipe; - - /* - if an output pipe is attached to this input, - check if it needs to be released. - */ - if (pipe_out_monitoring) { - if (--pipe_out_monitoring->references == 0) { - vx_free_pipe(chip, pipe_out_monitoring); - chip->playback_pipes[pipe->number] = NULL; - pipe->monitoring_pipe = NULL; - } - } - - vx_free_pipe(chip, pipe); - return 0; -} - - - -#define DMA_READ_ALIGN 6 /* hardware alignment for read */ - -/* - * vx_pcm_capture_update - update the capture buffer - */ -static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream *subs, - struct vx_pipe *pipe) -{ - int size, space, count; - struct snd_pcm_runtime *runtime = subs->runtime; - - if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) - return; - - size = runtime->buffer_size - snd_pcm_capture_avail(runtime); - if (! size) - return; - size = frames_to_bytes(runtime, size); - space = vx_query_hbuffer_size(chip, pipe); - if (space < 0) - goto _error; - if (size > space) - size = space; - size = (size / 3) * 3; /* align to 3 bytes */ - if (size < DMA_READ_ALIGN) - goto _error; - - /* keep the last 6 bytes, they will be read after disconnection */ - count = size - DMA_READ_ALIGN; - /* read bytes until the current pointer reaches to the aligned position - * for word-transfer - */ - while (count > 0) { - if ((pipe->hw_ptr % pipe->align) == 0) - break; - if (vx_wait_for_rx_full(chip) < 0) - goto _error; - vx_pcm_read_per_bytes(chip, runtime, pipe); - count -= 3; - } - if (count > 0) { - /* ok, let's accelerate! */ - int align = pipe->align * 3; - space = (count / align) * align; - vx_pseudo_dma_read(chip, runtime, pipe, space); - count -= space; - } - /* read the rest of bytes */ - while (count > 0) { - if (vx_wait_for_rx_full(chip) < 0) - goto _error; - vx_pcm_read_per_bytes(chip, runtime, pipe); - count -= 3; - } - /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ - vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); - /* read the last pending 6 bytes */ - count = DMA_READ_ALIGN; - while (count > 0) { - vx_pcm_read_per_bytes(chip, runtime, pipe); - count -= 3; - } - /* update the position */ - pipe->transferred += size; - if (pipe->transferred >= pipe->period_bytes) { - pipe->transferred %= pipe->period_bytes; - snd_pcm_period_elapsed(subs); - } - return; - - _error: - /* disconnect the host, SIZE_HBUF command always switches to the stream mode */ - vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT); - return; -} - -/* - * vx_pcm_capture_pointer - pointer callback for capture - */ -static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct vx_pipe *pipe = runtime->private_data; - return bytes_to_frames(runtime, pipe->hw_ptr); -} - -/* - * operators for PCM capture - */ -static struct snd_pcm_ops vx_pcm_capture_ops = { - .open = vx_pcm_capture_open, - .close = vx_pcm_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = vx_pcm_hw_params, - .hw_free = vx_pcm_hw_free, - .prepare = vx_pcm_prepare, - .trigger = vx_pcm_trigger, - .pointer = vx_pcm_capture_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - - -/* - * interrupt handler for pcm streams - */ -void vx_pcm_update_intr(struct vx_core *chip, unsigned int events) -{ - unsigned int i; - struct vx_pipe *pipe; - -#define EVENT_MASK (END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING) - - if (events & EVENT_MASK) { - vx_init_rmh(&chip->irq_rmh, CMD_ASYNC); - if (events & ASYNC_EVENTS_PENDING) - chip->irq_rmh.Cmd[0] |= 0x00000001; /* SEL_ASYNC_EVENTS */ - if (events & END_OF_BUFFER_EVENTS_PENDING) - chip->irq_rmh.Cmd[0] |= 0x00000002; /* SEL_END_OF_BUF_EVENTS */ - - if (vx_send_msg(chip, &chip->irq_rmh) < 0) { - snd_printdd(KERN_ERR "msg send error!!\n"); - return; - } - - i = 1; - while (i < chip->irq_rmh.LgStat) { - int p, buf, capture, eob; - p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD; - capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0; - eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0; - i++; - if (events & ASYNC_EVENTS_PENDING) - i++; - buf = 1; /* force to transfer */ - if (events & END_OF_BUFFER_EVENTS_PENDING) { - if (eob) - buf = chip->irq_rmh.Stat[i]; - i++; - } - if (capture) - continue; - if (snd_BUG_ON(p < 0 || p >= chip->audio_outs)) - continue; - pipe = chip->playback_pipes[p]; - if (pipe && pipe->substream) { - vx_pcm_playback_update(chip, pipe->substream, pipe); - vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf); - } - } - } - - /* update the capture pcm pointers as frequently as possible */ - for (i = 0; i < chip->audio_ins; i++) { - pipe = chip->capture_pipes[i]; - if (pipe && pipe->substream) - vx_pcm_capture_update(chip, pipe->substream, pipe); - } -} - - -/* - * vx_init_audio_io - check the available audio i/o and allocate pipe arrays - */ -static int vx_init_audio_io(struct vx_core *chip) -{ - struct vx_rmh rmh; - int preferred; - - vx_init_rmh(&rmh, CMD_SUPPORTED); - if (vx_send_msg(chip, &rmh) < 0) { - snd_printk(KERN_ERR "vx: cannot get the supported audio data\n"); - return -ENXIO; - } - - chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD; - chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD; - chip->audio_info = rmh.Stat[1]; - - /* allocate pipes */ - chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL); - if (!chip->playback_pipes) - return -ENOMEM; - chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL); - if (!chip->capture_pipes) { - kfree(chip->playback_pipes); - return -ENOMEM; - } - - preferred = chip->ibl.size; - chip->ibl.size = 0; - vx_set_ibl(chip, &chip->ibl); /* query the info */ - if (preferred > 0) { - chip->ibl.size = ((preferred + chip->ibl.granularity - 1) / - chip->ibl.granularity) * chip->ibl.granularity; - if (chip->ibl.size > chip->ibl.max_size) - chip->ibl.size = chip->ibl.max_size; - } else - chip->ibl.size = chip->ibl.min_size; /* set to the minimum */ - vx_set_ibl(chip, &chip->ibl); - - return 0; -} - - -/* - * free callback for pcm - */ -static void snd_vx_pcm_free(struct snd_pcm *pcm) -{ - struct vx_core *chip = pcm->private_data; - chip->pcm[pcm->device] = NULL; - kfree(chip->playback_pipes); - chip->playback_pipes = NULL; - kfree(chip->capture_pipes); - chip->capture_pipes = NULL; -} - -/* - * snd_vx_pcm_new - create and initialize a pcm - */ -int snd_vx_pcm_new(struct vx_core *chip) -{ - struct snd_pcm *pcm; - unsigned int i; - int err; - - if ((err = vx_init_audio_io(chip)) < 0) - return err; - - for (i = 0; i < chip->hw->num_codecs; i++) { - unsigned int outs, ins; - outs = chip->audio_outs > i * 2 ? 1 : 0; - ins = chip->audio_ins > i * 2 ? 1 : 0; - if (! outs && ! ins) - break; - err = snd_pcm_new(chip->card, "VX PCM", i, - outs, ins, &pcm); - if (err < 0) - return err; - if (outs) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops); - if (ins) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops); - - pcm->private_data = chip; - pcm->private_free = snd_vx_pcm_free; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->shortname); - chip->pcm[i] = pcm; - } - - return 0; -} diff --git a/ANDROID_3.4.5/sound/drivers/vx/vx_uer.c b/ANDROID_3.4.5/sound/drivers/vx/vx_uer.c deleted file mode 100644 index b0560fec..00000000 --- a/ANDROID_3.4.5/sound/drivers/vx/vx_uer.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Driver for Digigram VX soundcards - * - * IEC958 stuff - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 "vx_cmd.h" - - -/* - * vx_modify_board_clock - tell the board that its clock has been modified - * @sync: DSP needs to resynchronize its FIFO - */ -static int vx_modify_board_clock(struct vx_core *chip, int sync) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_MODIFY_CLOCK); - /* Ask the DSP to resynchronize its FIFO. */ - if (sync) - rmh.Cmd[0] |= CMD_MODIFY_CLOCK_S_BIT; - return vx_send_msg(chip, &rmh); -} - -/* - * vx_modify_board_inputs - resync audio inputs - */ -static int vx_modify_board_inputs(struct vx_core *chip) -{ - struct vx_rmh rmh; - - vx_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS); - rmh.Cmd[0] |= 1 << 0; /* reference: AUDIO 0 */ - return vx_send_msg(chip, &rmh); -} - -/* - * vx_read_one_cbit - read one bit from UER config - * @index: the bit index - * returns 0 or 1. - */ -static int vx_read_one_cbit(struct vx_core *chip, int index) -{ - unsigned long flags; - int val; - spin_lock_irqsave(&chip->lock, flags); - if (chip->type >= VX_TYPE_VXPOCKET) { - vx_outb(chip, CSUER, 1); /* read */ - vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); - val = (vx_inb(chip, RUER) >> 7) & 0x01; - } else { - vx_outl(chip, CSUER, 1); /* read */ - vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); - val = (vx_inl(chip, RUER) >> 7) & 0x01; - } - spin_unlock_irqrestore(&chip->lock, flags); - return val; -} - -/* - * vx_write_one_cbit - write one bit to UER config - * @index: the bit index - * @val: bit value, 0 or 1 - */ -static void vx_write_one_cbit(struct vx_core *chip, int index, int val) -{ - unsigned long flags; - val = !!val; /* 0 or 1 */ - spin_lock_irqsave(&chip->lock, flags); - if (vx_is_pcmcia(chip)) { - vx_outb(chip, CSUER, 0); /* write */ - vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); - } else { - vx_outl(chip, CSUER, 0); /* write */ - vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); - } - spin_unlock_irqrestore(&chip->lock, flags); -} - -/* - * vx_read_uer_status - read the current UER status - * @mode: pointer to store the UER mode, VX_UER_MODE_XXX - * - * returns the frequency of UER, or 0 if not sync, - * or a negative error code. - */ -static int vx_read_uer_status(struct vx_core *chip, unsigned int *mode) -{ - int val, freq; - - /* Default values */ - freq = 0; - - /* Read UER status */ - if (vx_is_pcmcia(chip)) - val = vx_inb(chip, CSUER); - else - val = vx_inl(chip, CSUER); - if (val < 0) - return val; - /* If clock is present, read frequency */ - if (val & VX_SUER_CLOCK_PRESENT_MASK) { - switch (val & VX_SUER_FREQ_MASK) { - case VX_SUER_FREQ_32KHz_MASK: - freq = 32000; - break; - case VX_SUER_FREQ_44KHz_MASK: - freq = 44100; - break; - case VX_SUER_FREQ_48KHz_MASK: - freq = 48000; - break; - } - } - if (val & VX_SUER_DATA_PRESENT_MASK) - /* bit 0 corresponds to consumer/professional bit */ - *mode = vx_read_one_cbit(chip, 0) ? - VX_UER_MODE_PROFESSIONAL : VX_UER_MODE_CONSUMER; - else - *mode = VX_UER_MODE_NOT_PRESENT; - - return freq; -} - - -/* - * compute the sample clock value from frequency - * - * The formula is as follows: - * - * HexFreq = (dword) ((double) ((double) 28224000 / (double) Frequency)) - * switch ( HexFreq & 0x00000F00 ) - * case 0x00000100: ; - * case 0x00000200: - * case 0x00000300: HexFreq -= 0x00000201 ; - * case 0x00000400: - * case 0x00000500: - * case 0x00000600: - * case 0x00000700: HexFreq = (dword) (((double) 28224000 / (double) (Frequency*2)) - 1) - * default : HexFreq = (dword) ((double) 28224000 / (double) (Frequency*4)) - 0x000001FF - */ - -static int vx_calc_clock_from_freq(struct vx_core *chip, int freq) -{ - int hexfreq; - - if (snd_BUG_ON(freq <= 0)) - return 0; - - hexfreq = (28224000 * 10) / freq; - hexfreq = (hexfreq + 5) / 10; - - /* max freq = 55125 Hz */ - if (snd_BUG_ON(hexfreq <= 0x00000200)) - return 0; - - if (hexfreq <= 0x03ff) - return hexfreq - 0x00000201; - if (hexfreq <= 0x07ff) - return (hexfreq / 2) - 1; - if (hexfreq <= 0x0fff) - return (hexfreq / 4) + 0x000001ff; - - return 0x5fe; /* min freq = 6893 Hz */ -} - - -/* - * vx_change_clock_source - change the clock source - * @source: the new source - */ -static void vx_change_clock_source(struct vx_core *chip, int source) -{ - unsigned long flags; - - /* we mute DAC to prevent clicks */ - vx_toggle_dac_mute(chip, 1); - spin_lock_irqsave(&chip->lock, flags); - chip->ops->set_clock_source(chip, source); - chip->clock_source = source; - spin_unlock_irqrestore(&chip->lock, flags); - /* unmute */ - vx_toggle_dac_mute(chip, 0); -} - - -/* - * set the internal clock - */ -void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) -{ - int clock; - unsigned long flags; - /* Get real clock value */ - clock = vx_calc_clock_from_freq(chip, freq); - snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq); - spin_lock_irqsave(&chip->lock, flags); - if (vx_is_pcmcia(chip)) { - vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f); - vx_outb(chip, LOFREQ, clock & 0xff); - } else { - vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f); - vx_outl(chip, LOFREQ, clock & 0xff); - } - spin_unlock_irqrestore(&chip->lock, flags); -} - - -/* - * set the iec958 status bits - * @bits: 32-bit status bits - */ -void vx_set_iec958_status(struct vx_core *chip, unsigned int bits) -{ - int i; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - for (i = 0; i < 32; i++) - vx_write_one_cbit(chip, i, bits & (1 << i)); -} - - -/* - * vx_set_clock - change the clock and audio source if necessary - */ -int vx_set_clock(struct vx_core *chip, unsigned int freq) -{ - int src_changed = 0; - - if (chip->chip_status & VX_STAT_IS_STALE) - return 0; - - /* change the audio source if possible */ - vx_sync_audio_source(chip); - - if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL || - (chip->clock_mode == VX_CLOCK_MODE_AUTO && - chip->audio_source == VX_AUDIO_SRC_DIGITAL)) { - if (chip->clock_source != UER_SYNC) { - vx_change_clock_source(chip, UER_SYNC); - mdelay(6); - src_changed = 1; - } - } else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL || - (chip->clock_mode == VX_CLOCK_MODE_AUTO && - chip->audio_source != VX_AUDIO_SRC_DIGITAL)) { - if (chip->clock_source != INTERNAL_QUARTZ) { - vx_change_clock_source(chip, INTERNAL_QUARTZ); - src_changed = 1; - } - if (chip->freq == freq) - return 0; - vx_set_internal_clock(chip, freq); - if (src_changed) - vx_modify_board_inputs(chip); - } - if (chip->freq == freq) - return 0; - chip->freq = freq; - vx_modify_board_clock(chip, 1); - return 0; -} - - -/* - * vx_change_frequency - called from interrupt handler - */ -int vx_change_frequency(struct vx_core *chip) -{ - int freq; - - if (chip->chip_status & VX_STAT_IS_STALE) - return 0; - - if (chip->clock_source == INTERNAL_QUARTZ) - return 0; - /* - * Read the real UER board frequency - */ - freq = vx_read_uer_status(chip, &chip->uer_detected); - if (freq < 0) - return freq; - /* - * The frequency computed by the DSP is good and - * is different from the previous computed. - */ - if (freq == 48000 || freq == 44100 || freq == 32000) - chip->freq_detected = freq; - - return 0; -} diff --git a/ANDROID_3.4.5/sound/firewire/Kconfig b/ANDROID_3.4.5/sound/firewire/Kconfig deleted file mode 100644 index 26071489..00000000 --- a/ANDROID_3.4.5/sound/firewire/Kconfig +++ /dev/null @@ -1,36 +0,0 @@ -menuconfig SND_FIREWIRE - bool "FireWire sound devices" - depends on FIREWIRE - default y - help - Support for IEEE-1394/FireWire/iLink sound devices. - -if SND_FIREWIRE && FIREWIRE - -config SND_FIREWIRE_LIB - tristate - depends on SND_PCM - -config SND_FIREWIRE_SPEAKERS - tristate "FireWire speakers" - select SND_PCM - select SND_FIREWIRE_LIB - help - Say Y here to include support for the Griffin FireWave Surround - and the LaCie FireWire Speakers. - - To compile this driver as a module, choose M here: the module - will be called snd-firewire-speakers. - -config SND_ISIGHT - tristate "Apple iSight microphone" - select SND_PCM - select SND_FIREWIRE_LIB - help - Say Y here to include support for the front and rear microphones - of the Apple iSight web camera. - - To compile this driver as a module, choose M here: the module - will be called snd-isight. - -endif # SND_FIREWIRE diff --git a/ANDROID_3.4.5/sound/firewire/Makefile b/ANDROID_3.4.5/sound/firewire/Makefile deleted file mode 100644 index d71ed893..00000000 --- a/ANDROID_3.4.5/sound/firewire/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \ - fcp.o cmp.o amdtp.o -snd-firewire-speakers-objs := speakers.o -snd-isight-objs := isight.o - -obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o -obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o -obj-$(CONFIG_SND_ISIGHT) += snd-isight.o diff --git a/ANDROID_3.4.5/sound/firewire/amdtp.c b/ANDROID_3.4.5/sound/firewire/amdtp.c deleted file mode 100644 index 87657dd7..00000000 --- a/ANDROID_3.4.5/sound/firewire/amdtp.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Audio and Music Data Transmission Protocol (IEC 61883-6) streams - * with Common Isochronous Packet (IEC 61883-1) headers - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include "amdtp.h" - -#define TICKS_PER_CYCLE 3072 -#define CYCLES_PER_SECOND 8000 -#define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND) - -#define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */ - -#define TAG_CIP 1 - -#define CIP_EOH (1u << 31) -#define CIP_FMT_AM (0x10 << 24) -#define AMDTP_FDF_AM824 (0 << 19) -#define AMDTP_FDF_SFC_SHIFT 16 - -/* TODO: make these configurable */ -#define INTERRUPT_INTERVAL 16 -#define QUEUE_LENGTH 48 - -/** - * amdtp_out_stream_init - initialize an AMDTP output stream structure - * @s: the AMDTP output stream to initialize - * @unit: the target of the stream - * @flags: the packet transmission method to use - */ -int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, - enum cip_out_flags flags) -{ - if (flags != CIP_NONBLOCKING) - return -EINVAL; - - s->unit = fw_unit_get(unit); - s->flags = flags; - s->context = ERR_PTR(-1); - mutex_init(&s->mutex); - s->packet_index = 0; - - return 0; -} -EXPORT_SYMBOL(amdtp_out_stream_init); - -/** - * amdtp_out_stream_destroy - free stream resources - * @s: the AMDTP output stream to destroy - */ -void amdtp_out_stream_destroy(struct amdtp_out_stream *s) -{ - WARN_ON(!IS_ERR(s->context)); - mutex_destroy(&s->mutex); - fw_unit_put(s->unit); -} -EXPORT_SYMBOL(amdtp_out_stream_destroy); - -/** - * amdtp_out_stream_set_rate - set the sample rate - * @s: the AMDTP output stream to configure - * @rate: the sample rate - * - * The sample rate must be set before the stream is started, and must not be - * changed while the stream is running. - */ -void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate) -{ - static const struct { - unsigned int rate; - unsigned int syt_interval; - } rate_info[] = { - [CIP_SFC_32000] = { 32000, 8, }, - [CIP_SFC_44100] = { 44100, 8, }, - [CIP_SFC_48000] = { 48000, 8, }, - [CIP_SFC_88200] = { 88200, 16, }, - [CIP_SFC_96000] = { 96000, 16, }, - [CIP_SFC_176400] = { 176400, 32, }, - [CIP_SFC_192000] = { 192000, 32, }, - }; - unsigned int sfc; - - if (WARN_ON(!IS_ERR(s->context))) - return; - - for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc) - if (rate_info[sfc].rate == rate) { - s->sfc = sfc; - s->syt_interval = rate_info[sfc].syt_interval; - return; - } - WARN_ON(1); -} -EXPORT_SYMBOL(amdtp_out_stream_set_rate); - -/** - * amdtp_out_stream_get_max_payload - get the stream's packet size - * @s: the AMDTP output stream - * - * This function must not be called before the stream has been configured - * with amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and - * amdtp_out_stream_set_midi(). - */ -unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s) -{ - static const unsigned int max_data_blocks[] = { - [CIP_SFC_32000] = 4, - [CIP_SFC_44100] = 6, - [CIP_SFC_48000] = 6, - [CIP_SFC_88200] = 12, - [CIP_SFC_96000] = 12, - [CIP_SFC_176400] = 23, - [CIP_SFC_192000] = 24, - }; - - s->data_block_quadlets = s->pcm_channels; - s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8); - - return 8 + max_data_blocks[s->sfc] * 4 * s->data_block_quadlets; -} -EXPORT_SYMBOL(amdtp_out_stream_get_max_payload); - -static void amdtp_write_s16(struct amdtp_out_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames); -static void amdtp_write_s32(struct amdtp_out_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames); - -/** - * amdtp_out_stream_set_pcm_format - set the PCM format - * @s: the AMDTP output stream to configure - * @format: the format of the ALSA PCM device - * - * The sample format must be set before the stream is started, and must not be - * changed while the stream is running. - */ -void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, - snd_pcm_format_t format) -{ - if (WARN_ON(!IS_ERR(s->context))) - return; - - switch (format) { - default: - WARN_ON(1); - /* fall through */ - case SNDRV_PCM_FORMAT_S16: - s->transfer_samples = amdtp_write_s16; - break; - case SNDRV_PCM_FORMAT_S32: - s->transfer_samples = amdtp_write_s32; - break; - } -} -EXPORT_SYMBOL(amdtp_out_stream_set_pcm_format); - -static unsigned int calculate_data_blocks(struct amdtp_out_stream *s) -{ - unsigned int phase, data_blocks; - - if (!cip_sfc_is_base_44100(s->sfc)) { - /* Sample_rate / 8000 is an integer, and precomputed. */ - data_blocks = s->data_block_state; - } else { - phase = s->data_block_state; - - /* - * This calculates the number of data blocks per packet so that - * 1) the overall rate is correct and exactly synchronized to - * the bus clock, and - * 2) packets with a rounded-up number of blocks occur as early - * as possible in the sequence (to prevent underruns of the - * device's buffer). - */ - if (s->sfc == CIP_SFC_44100) - /* 6 6 5 6 5 6 5 ... */ - data_blocks = 5 + ((phase & 1) ^ - (phase == 0 || phase >= 40)); - else - /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */ - data_blocks = 11 * (s->sfc >> 1) + (phase == 0); - if (++phase >= (80 >> (s->sfc >> 1))) - phase = 0; - s->data_block_state = phase; - } - - return data_blocks; -} - -static unsigned int calculate_syt(struct amdtp_out_stream *s, - unsigned int cycle) -{ - unsigned int syt_offset, phase, index, syt; - - if (s->last_syt_offset < TICKS_PER_CYCLE) { - if (!cip_sfc_is_base_44100(s->sfc)) - syt_offset = s->last_syt_offset + s->syt_offset_state; - else { - /* - * The time, in ticks, of the n'th SYT_INTERVAL sample is: - * n * SYT_INTERVAL * 24576000 / sample_rate - * Modulo TICKS_PER_CYCLE, the difference between successive - * elements is about 1386.23. Rounding the results of this - * formula to the SYT precision results in a sequence of - * differences that begins with: - * 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ... - * This code generates _exactly_ the same sequence. - */ - phase = s->syt_offset_state; - index = phase % 13; - syt_offset = s->last_syt_offset; - syt_offset += 1386 + ((index && !(index & 3)) || - phase == 146); - if (++phase >= 147) - phase = 0; - s->syt_offset_state = phase; - } - } else - syt_offset = s->last_syt_offset - TICKS_PER_CYCLE; - s->last_syt_offset = syt_offset; - - if (syt_offset < TICKS_PER_CYCLE) { - syt_offset += TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; - syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; - syt += syt_offset % TICKS_PER_CYCLE; - - return syt & 0xffff; - } else { - return 0xffff; /* no info */ - } -} - -static void amdtp_write_s32(struct amdtp_out_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) -{ - struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, frame_step, i, c; - const u32 *src; - - channels = s->pcm_channels; - src = (void *)runtime->dma_area + - s->pcm_buffer_pointer * (runtime->frame_bits / 8); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; - frame_step = s->data_block_quadlets - channels; - - for (i = 0; i < frames; ++i) { - for (c = 0; c < channels; ++c) { - *buffer = cpu_to_be32((*src >> 8) | 0x40000000); - src++; - buffer++; - } - buffer += frame_step; - if (--remaining_frames == 0) - src = (void *)runtime->dma_area; - } -} - -static void amdtp_write_s16(struct amdtp_out_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) -{ - struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, frame_step, i, c; - const u16 *src; - - channels = s->pcm_channels; - src = (void *)runtime->dma_area + - s->pcm_buffer_pointer * (runtime->frame_bits / 8); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; - frame_step = s->data_block_quadlets - channels; - - for (i = 0; i < frames; ++i) { - for (c = 0; c < channels; ++c) { - *buffer = cpu_to_be32((*src << 8) | 0x40000000); - src++; - buffer++; - } - buffer += frame_step; - if (--remaining_frames == 0) - src = (void *)runtime->dma_area; - } -} - -static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s, - __be32 *buffer, unsigned int frames) -{ - unsigned int i, c; - - for (i = 0; i < frames; ++i) { - for (c = 0; c < s->pcm_channels; ++c) - buffer[c] = cpu_to_be32(0x40000000); - buffer += s->data_block_quadlets; - } -} - -static void amdtp_fill_midi(struct amdtp_out_stream *s, - __be32 *buffer, unsigned int frames) -{ - unsigned int i; - - for (i = 0; i < frames; ++i) - buffer[s->pcm_channels + i * s->data_block_quadlets] = - cpu_to_be32(0x80000000); -} - -static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle) -{ - __be32 *buffer; - unsigned int index, data_blocks, syt, ptr; - struct snd_pcm_substream *pcm; - struct fw_iso_packet packet; - int err; - - if (s->packet_index < 0) - return; - index = s->packet_index; - - data_blocks = calculate_data_blocks(s); - syt = calculate_syt(s, cycle); - - buffer = s->buffer.packets[index].buffer; - buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | - (s->data_block_quadlets << 16) | - s->data_block_counter); - buffer[1] = cpu_to_be32(CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 | - (s->sfc << AMDTP_FDF_SFC_SHIFT) | syt); - buffer += 2; - - pcm = ACCESS_ONCE(s->pcm); - if (pcm) - s->transfer_samples(s, pcm, buffer, data_blocks); - else - amdtp_fill_pcm_silence(s, buffer, data_blocks); - if (s->midi_ports) - amdtp_fill_midi(s, buffer, data_blocks); - - s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; - - packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; - packet.interrupt = IS_ALIGNED(index + 1, INTERRUPT_INTERVAL); - packet.skip = 0; - packet.tag = TAG_CIP; - packet.sy = 0; - packet.header_length = 0; - - err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer, - s->buffer.packets[index].offset); - if (err < 0) { - dev_err(&s->unit->device, "queueing error: %d\n", err); - s->packet_index = -1; - amdtp_out_stream_pcm_abort(s); - return; - } - - if (++index >= QUEUE_LENGTH) - index = 0; - s->packet_index = index; - - if (pcm) { - ptr = s->pcm_buffer_pointer + data_blocks; - if (ptr >= pcm->runtime->buffer_size) - ptr -= pcm->runtime->buffer_size; - ACCESS_ONCE(s->pcm_buffer_pointer) = ptr; - - s->pcm_period_pointer += data_blocks; - if (s->pcm_period_pointer >= pcm->runtime->period_size) { - s->pcm_period_pointer -= pcm->runtime->period_size; - snd_pcm_period_elapsed(pcm); - } - } -} - -static void out_packet_callback(struct fw_iso_context *context, u32 cycle, - size_t header_length, void *header, void *data) -{ - struct amdtp_out_stream *s = data; - unsigned int i, packets = header_length / 4; - - /* - * Compute the cycle of the last queued packet. - * (We need only the four lowest bits for the SYT, so we can ignore - * that bits 0-11 must wrap around at 3072.) - */ - cycle += QUEUE_LENGTH - packets; - - for (i = 0; i < packets; ++i) - queue_out_packet(s, ++cycle); - fw_iso_context_queue_flush(s->context); -} - -static int queue_initial_skip_packets(struct amdtp_out_stream *s) -{ - struct fw_iso_packet skip_packet = { - .skip = 1, - }; - unsigned int i; - int err; - - for (i = 0; i < QUEUE_LENGTH; ++i) { - skip_packet.interrupt = IS_ALIGNED(s->packet_index + 1, - INTERRUPT_INTERVAL); - err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0); - if (err < 0) - return err; - if (++s->packet_index >= QUEUE_LENGTH) - s->packet_index = 0; - } - - return 0; -} - -/** - * amdtp_out_stream_start - start sending packets - * @s: the AMDTP output stream to start - * @channel: the isochronous channel on the bus - * @speed: firewire speed code - * - * The stream cannot be started until it has been configured with - * amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and - * amdtp_out_stream_set_midi(); and it must be started before any - * PCM or MIDI device can be started. - */ -int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed) -{ - static const struct { - unsigned int data_block; - unsigned int syt_offset; - } initial_state[] = { - [CIP_SFC_32000] = { 4, 3072 }, - [CIP_SFC_48000] = { 6, 1024 }, - [CIP_SFC_96000] = { 12, 1024 }, - [CIP_SFC_192000] = { 24, 1024 }, - [CIP_SFC_44100] = { 0, 67 }, - [CIP_SFC_88200] = { 0, 67 }, - [CIP_SFC_176400] = { 0, 67 }, - }; - int err; - - mutex_lock(&s->mutex); - - if (WARN_ON(!IS_ERR(s->context) || - (!s->pcm_channels && !s->midi_ports))) { - err = -EBADFD; - goto err_unlock; - } - - s->data_block_state = initial_state[s->sfc].data_block; - s->syt_offset_state = initial_state[s->sfc].syt_offset; - s->last_syt_offset = TICKS_PER_CYCLE; - - err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, - amdtp_out_stream_get_max_payload(s), - DMA_TO_DEVICE); - if (err < 0) - goto err_unlock; - - s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, - FW_ISO_CONTEXT_TRANSMIT, - channel, speed, 0, - out_packet_callback, s); - if (IS_ERR(s->context)) { - err = PTR_ERR(s->context); - if (err == -EBUSY) - dev_err(&s->unit->device, - "no free output stream on this controller\n"); - goto err_buffer; - } - - amdtp_out_stream_update(s); - - s->packet_index = 0; - s->data_block_counter = 0; - err = queue_initial_skip_packets(s); - if (err < 0) - goto err_context; - - err = fw_iso_context_start(s->context, -1, 0, 0); - if (err < 0) - goto err_context; - - mutex_unlock(&s->mutex); - - return 0; - -err_context: - fw_iso_context_destroy(s->context); - s->context = ERR_PTR(-1); -err_buffer: - iso_packets_buffer_destroy(&s->buffer, s->unit); -err_unlock: - mutex_unlock(&s->mutex); - - return err; -} -EXPORT_SYMBOL(amdtp_out_stream_start); - -/** - * amdtp_out_stream_update - update the stream after a bus reset - * @s: the AMDTP output stream - */ -void amdtp_out_stream_update(struct amdtp_out_stream *s) -{ - ACCESS_ONCE(s->source_node_id_field) = - (fw_parent_device(s->unit)->card->node_id & 0x3f) << 24; -} -EXPORT_SYMBOL(amdtp_out_stream_update); - -/** - * amdtp_out_stream_stop - stop sending packets - * @s: the AMDTP output stream to stop - * - * All PCM and MIDI devices of the stream must be stopped before the stream - * itself can be stopped. - */ -void amdtp_out_stream_stop(struct amdtp_out_stream *s) -{ - mutex_lock(&s->mutex); - - if (IS_ERR(s->context)) { - mutex_unlock(&s->mutex); - return; - } - - fw_iso_context_stop(s->context); - fw_iso_context_destroy(s->context); - s->context = ERR_PTR(-1); - iso_packets_buffer_destroy(&s->buffer, s->unit); - - mutex_unlock(&s->mutex); -} -EXPORT_SYMBOL(amdtp_out_stream_stop); - -/** - * amdtp_out_stream_pcm_abort - abort the running PCM device - * @s: the AMDTP stream about to be stopped - * - * If the isochronous stream needs to be stopped asynchronously, call this - * function first to stop the PCM device. - */ -void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s) -{ - struct snd_pcm_substream *pcm; - - pcm = ACCESS_ONCE(s->pcm); - if (pcm) { - snd_pcm_stream_lock_irq(pcm); - if (snd_pcm_running(pcm)) - snd_pcm_stop(pcm, SNDRV_PCM_STATE_XRUN); - snd_pcm_stream_unlock_irq(pcm); - } -} -EXPORT_SYMBOL(amdtp_out_stream_pcm_abort); diff --git a/ANDROID_3.4.5/sound/firewire/amdtp.h b/ANDROID_3.4.5/sound/firewire/amdtp.h deleted file mode 100644 index 537a9cb8..00000000 --- a/ANDROID_3.4.5/sound/firewire/amdtp.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED -#define SOUND_FIREWIRE_AMDTP_H_INCLUDED - -#include -#include -#include "packets-buffer.h" - -/** - * enum cip_out_flags - describes details of the streaming protocol - * @CIP_NONBLOCKING: In non-blocking mode, each packet contains - * sample_rate/8000 samples, with rounding up or down to adjust - * for clock skew and left-over fractional samples. This should - * be used if supported by the device. - */ -enum cip_out_flags { - CIP_NONBLOCKING = 0, -}; - -/** - * enum cip_sfc - a stream's sample rate - */ -enum cip_sfc { - CIP_SFC_32000 = 0, - CIP_SFC_44100 = 1, - CIP_SFC_48000 = 2, - CIP_SFC_88200 = 3, - CIP_SFC_96000 = 4, - CIP_SFC_176400 = 5, - CIP_SFC_192000 = 6, -}; - -#define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \ - SNDRV_PCM_FMTBIT_S32) - -struct fw_unit; -struct fw_iso_context; -struct snd_pcm_substream; - -struct amdtp_out_stream { - struct fw_unit *unit; - enum cip_out_flags flags; - struct fw_iso_context *context; - struct mutex mutex; - - enum cip_sfc sfc; - unsigned int data_block_quadlets; - unsigned int pcm_channels; - unsigned int midi_ports; - void (*transfer_samples)(struct amdtp_out_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames); - - unsigned int syt_interval; - unsigned int source_node_id_field; - struct iso_packets_buffer buffer; - - struct snd_pcm_substream *pcm; - - int packet_index; - unsigned int data_block_counter; - - unsigned int data_block_state; - - unsigned int last_syt_offset; - unsigned int syt_offset_state; - - unsigned int pcm_buffer_pointer; - unsigned int pcm_period_pointer; -}; - -int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, - enum cip_out_flags flags); -void amdtp_out_stream_destroy(struct amdtp_out_stream *s); - -void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate); -unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s); - -int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed); -void amdtp_out_stream_update(struct amdtp_out_stream *s); -void amdtp_out_stream_stop(struct amdtp_out_stream *s); - -void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, - snd_pcm_format_t format); -void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s); - -/** - * amdtp_out_stream_set_pcm - configure format of PCM samples - * @s: the AMDTP output stream to be configured - * @pcm_channels: the number of PCM samples in each data block, to be encoded - * as AM824 multi-bit linear audio - * - * This function must not be called while the stream is running. - */ -static inline void amdtp_out_stream_set_pcm(struct amdtp_out_stream *s, - unsigned int pcm_channels) -{ - s->pcm_channels = pcm_channels; -} - -/** - * amdtp_out_stream_set_midi - configure format of MIDI data - * @s: the AMDTP output stream to be configured - * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels) - * - * This function must not be called while the stream is running. - */ -static inline void amdtp_out_stream_set_midi(struct amdtp_out_stream *s, - unsigned int midi_ports) -{ - s->midi_ports = midi_ports; -} - -/** - * amdtp_out_streaming_error - check for streaming error - * @s: the AMDTP output stream - * - * If this function returns true, the stream's packet queue has stopped due to - * an asynchronous error. - */ -static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s) -{ - return s->packet_index < 0; -} - -/** - * amdtp_out_stream_pcm_prepare - prepare PCM device for running - * @s: the AMDTP output stream - * - * This function should be called from the PCM device's .prepare callback. - */ -static inline void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s) -{ - s->pcm_buffer_pointer = 0; - s->pcm_period_pointer = 0; -} - -/** - * amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device - * @s: the AMDTP output stream - * @pcm: the PCM device to be started, or %NULL to stop the current device - * - * Call this function on a running isochronous stream to enable the actual - * transmission of PCM data. This function should be called from the PCM - * device's .trigger callback. - */ -static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s, - struct snd_pcm_substream *pcm) -{ - ACCESS_ONCE(s->pcm) = pcm; -} - -/** - * amdtp_out_stream_pcm_pointer - get the PCM buffer position - * @s: the AMDTP output stream that transports the PCM data - * - * Returns the current buffer position, in frames. - */ -static inline unsigned long -amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s) -{ - return ACCESS_ONCE(s->pcm_buffer_pointer); -} - -static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc) -{ - return sfc & 1; -} - -#endif diff --git a/ANDROID_3.4.5/sound/firewire/cmp.c b/ANDROID_3.4.5/sound/firewire/cmp.c deleted file mode 100644 index 76294f2a..00000000 --- a/ANDROID_3.4.5/sound/firewire/cmp.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Connection Management Procedures (IEC 61883-1) helper functions - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include -#include -#include "lib.h" -#include "iso-resources.h" -#include "cmp.h" - -#define IMPR_SPEED_MASK 0xc0000000 -#define IMPR_SPEED_SHIFT 30 -#define IMPR_XSPEED_MASK 0x00000060 -#define IMPR_XSPEED_SHIFT 5 -#define IMPR_PLUGS_MASK 0x0000001f - -#define IPCR_ONLINE 0x80000000 -#define IPCR_BCAST_CONN 0x40000000 -#define IPCR_P2P_CONN_MASK 0x3f000000 -#define IPCR_P2P_CONN_SHIFT 24 -#define IPCR_CHANNEL_MASK 0x003f0000 -#define IPCR_CHANNEL_SHIFT 16 - -enum bus_reset_handling { - ABORT_ON_BUS_RESET, - SUCCEED_ON_BUS_RESET, -}; - -static __printf(2, 3) -void cmp_error(struct cmp_connection *c, const char *fmt, ...) -{ - va_list va; - - va_start(va, fmt); - dev_err(&c->resources.unit->device, "%cPCR%u: %pV", - 'i', c->pcr_index, &(struct va_format){ fmt, &va }); - va_end(va); -} - -static int pcr_modify(struct cmp_connection *c, - __be32 (*modify)(struct cmp_connection *c, __be32 old), - int (*check)(struct cmp_connection *c, __be32 pcr), - enum bus_reset_handling bus_reset_handling) -{ - struct fw_device *device = fw_parent_device(c->resources.unit); - int generation = c->resources.generation; - int rcode, errors = 0; - __be32 old_arg, buffer[2]; - int err; - - buffer[0] = c->last_pcr_value; - for (;;) { - old_arg = buffer[0]; - buffer[1] = modify(c, buffer[0]); - - rcode = fw_run_transaction( - device->card, TCODE_LOCK_COMPARE_SWAP, - device->node_id, generation, device->max_speed, - CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index), - buffer, 8); - - if (rcode == RCODE_COMPLETE) { - if (buffer[0] == old_arg) /* success? */ - break; - - if (check) { - err = check(c, buffer[0]); - if (err < 0) - return err; - } - } else if (rcode == RCODE_GENERATION) - goto bus_reset; - else if (rcode_is_permanent_error(rcode) || ++errors >= 3) - goto io_error; - } - c->last_pcr_value = buffer[1]; - - return 0; - -io_error: - cmp_error(c, "transaction failed: %s\n", rcode_string(rcode)); - return -EIO; - -bus_reset: - return bus_reset_handling == ABORT_ON_BUS_RESET ? -EAGAIN : 0; -} - - -/** - * cmp_connection_init - initializes a connection manager - * @c: the connection manager to initialize - * @unit: a unit of the target device - * @ipcr_index: the index of the iPCR on the target device - */ -int cmp_connection_init(struct cmp_connection *c, - struct fw_unit *unit, - unsigned int ipcr_index) -{ - __be32 impr_be; - u32 impr; - int err; - - err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, - CSR_REGISTER_BASE + CSR_IMPR, - &impr_be, 4); - if (err < 0) - return err; - impr = be32_to_cpu(impr_be); - - if (ipcr_index >= (impr & IMPR_PLUGS_MASK)) - return -EINVAL; - - err = fw_iso_resources_init(&c->resources, unit); - if (err < 0) - return err; - - c->connected = false; - mutex_init(&c->mutex); - c->last_pcr_value = cpu_to_be32(0x80000000); - c->pcr_index = ipcr_index; - c->max_speed = (impr & IMPR_SPEED_MASK) >> IMPR_SPEED_SHIFT; - if (c->max_speed == SCODE_BETA) - c->max_speed += (impr & IMPR_XSPEED_MASK) >> IMPR_XSPEED_SHIFT; - - return 0; -} -EXPORT_SYMBOL(cmp_connection_init); - -/** - * cmp_connection_destroy - free connection manager resources - * @c: the connection manager - */ -void cmp_connection_destroy(struct cmp_connection *c) -{ - WARN_ON(c->connected); - mutex_destroy(&c->mutex); - fw_iso_resources_destroy(&c->resources); -} -EXPORT_SYMBOL(cmp_connection_destroy); - - -static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) -{ - ipcr &= ~cpu_to_be32(IPCR_BCAST_CONN | - IPCR_P2P_CONN_MASK | - IPCR_CHANNEL_MASK); - ipcr |= cpu_to_be32(1 << IPCR_P2P_CONN_SHIFT); - ipcr |= cpu_to_be32(c->resources.channel << IPCR_CHANNEL_SHIFT); - - return ipcr; -} - -static int ipcr_set_check(struct cmp_connection *c, __be32 ipcr) -{ - if (ipcr & cpu_to_be32(IPCR_BCAST_CONN | - IPCR_P2P_CONN_MASK)) { - cmp_error(c, "plug is already in use\n"); - return -EBUSY; - } - if (!(ipcr & cpu_to_be32(IPCR_ONLINE))) { - cmp_error(c, "plug is not on-line\n"); - return -ECONNREFUSED; - } - - return 0; -} - -/** - * cmp_connection_establish - establish a connection to the target - * @c: the connection manager - * @max_payload_bytes: the amount of data (including CIP headers) per packet - * - * This function establishes a point-to-point connection from the local - * computer to the target by allocating isochronous resources (channel and - * bandwidth) and setting the target's input plug control register. When this - * function succeeds, the caller is responsible for starting transmitting - * packets. - */ -int cmp_connection_establish(struct cmp_connection *c, - unsigned int max_payload_bytes) -{ - int err; - - if (WARN_ON(c->connected)) - return -EISCONN; - - c->speed = min(c->max_speed, - fw_parent_device(c->resources.unit)->max_speed); - - mutex_lock(&c->mutex); - -retry_after_bus_reset: - err = fw_iso_resources_allocate(&c->resources, - max_payload_bytes, c->speed); - if (err < 0) - goto err_mutex; - - err = pcr_modify(c, ipcr_set_modify, ipcr_set_check, - ABORT_ON_BUS_RESET); - if (err == -EAGAIN) { - fw_iso_resources_free(&c->resources); - goto retry_after_bus_reset; - } - if (err < 0) - goto err_resources; - - c->connected = true; - - mutex_unlock(&c->mutex); - - return 0; - -err_resources: - fw_iso_resources_free(&c->resources); -err_mutex: - mutex_unlock(&c->mutex); - - return err; -} -EXPORT_SYMBOL(cmp_connection_establish); - -/** - * cmp_connection_update - update the connection after a bus reset - * @c: the connection manager - * - * This function must be called from the driver's .update handler to reestablish - * any connection that might have been active. - * - * Returns zero on success, or a negative error code. On an error, the - * connection is broken and the caller must stop transmitting iso packets. - */ -int cmp_connection_update(struct cmp_connection *c) -{ - int err; - - mutex_lock(&c->mutex); - - if (!c->connected) { - mutex_unlock(&c->mutex); - return 0; - } - - err = fw_iso_resources_update(&c->resources); - if (err < 0) - goto err_unconnect; - - err = pcr_modify(c, ipcr_set_modify, ipcr_set_check, - SUCCEED_ON_BUS_RESET); - if (err < 0) - goto err_resources; - - mutex_unlock(&c->mutex); - - return 0; - -err_resources: - fw_iso_resources_free(&c->resources); -err_unconnect: - c->connected = false; - mutex_unlock(&c->mutex); - - return err; -} -EXPORT_SYMBOL(cmp_connection_update); - - -static __be32 ipcr_break_modify(struct cmp_connection *c, __be32 ipcr) -{ - return ipcr & ~cpu_to_be32(IPCR_BCAST_CONN | IPCR_P2P_CONN_MASK); -} - -/** - * cmp_connection_break - break the connection to the target - * @c: the connection manager - * - * This function deactives the connection in the target's input plug control - * register, and frees the isochronous resources of the connection. Before - * calling this function, the caller should cease transmitting packets. - */ -void cmp_connection_break(struct cmp_connection *c) -{ - int err; - - mutex_lock(&c->mutex); - - if (!c->connected) { - mutex_unlock(&c->mutex); - return; - } - - err = pcr_modify(c, ipcr_break_modify, NULL, SUCCEED_ON_BUS_RESET); - if (err < 0) - cmp_error(c, "plug is still connected\n"); - - fw_iso_resources_free(&c->resources); - - c->connected = false; - - mutex_unlock(&c->mutex); -} -EXPORT_SYMBOL(cmp_connection_break); diff --git a/ANDROID_3.4.5/sound/firewire/cmp.h b/ANDROID_3.4.5/sound/firewire/cmp.h deleted file mode 100644 index f47de08f..00000000 --- a/ANDROID_3.4.5/sound/firewire/cmp.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef SOUND_FIREWIRE_CMP_H_INCLUDED -#define SOUND_FIREWIRE_CMP_H_INCLUDED - -#include -#include -#include "iso-resources.h" - -struct fw_unit; - -/** - * struct cmp_connection - manages an isochronous connection to a device - * @speed: the connection's actual speed - * - * This structure manages (using CMP) an isochronous stream from the local - * computer to a device's input plug (iPCR). - * - * There is no corresponding oPCR created on the local computer, so it is not - * possible to overlay connections on top of this one. - */ -struct cmp_connection { - int speed; - /* private: */ - bool connected; - struct mutex mutex; - struct fw_iso_resources resources; - __be32 last_pcr_value; - unsigned int pcr_index; - unsigned int max_speed; -}; - -int cmp_connection_init(struct cmp_connection *connection, - struct fw_unit *unit, - unsigned int ipcr_index); -void cmp_connection_destroy(struct cmp_connection *connection); - -int cmp_connection_establish(struct cmp_connection *connection, - unsigned int max_payload); -int cmp_connection_update(struct cmp_connection *connection); -void cmp_connection_break(struct cmp_connection *connection); - -#endif diff --git a/ANDROID_3.4.5/sound/firewire/fcp.c b/ANDROID_3.4.5/sound/firewire/fcp.c deleted file mode 100644 index ec578b5a..00000000 --- a/ANDROID_3.4.5/sound/firewire/fcp.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Function Control Protocol (IEC 61883-1) helper functions - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "fcp.h" -#include "lib.h" - -#define CTS_AVC 0x00 - -#define ERROR_RETRIES 3 -#define ERROR_DELAY_MS 5 -#define FCP_TIMEOUT_MS 125 - -static DEFINE_SPINLOCK(transactions_lock); -static LIST_HEAD(transactions); - -enum fcp_state { - STATE_PENDING, - STATE_BUS_RESET, - STATE_COMPLETE, -}; - -struct fcp_transaction { - struct list_head list; - struct fw_unit *unit; - void *response_buffer; - unsigned int response_size; - unsigned int response_match_bytes; - enum fcp_state state; - wait_queue_head_t wait; -}; - -/** - * fcp_avc_transaction - send an AV/C command and wait for its response - * @unit: a unit on the target device - * @command: a buffer containing the command frame; must be DMA-able - * @command_size: the size of @command - * @response: a buffer for the response frame - * @response_size: the maximum size of @response - * @response_match_bytes: a bitmap specifying the bytes used to detect the - * correct response frame - * - * This function sends a FCP command frame to the target and waits for the - * corresponding response frame to be returned. - * - * Because it is possible for multiple FCP transactions to be active at the - * same time, the correct response frame is detected by the value of certain - * bytes. These bytes must be set in @response before calling this function, - * and the corresponding bits must be set in @response_match_bytes. - * - * @command and @response can point to the same buffer. - * - * Asynchronous operation (INTERIM, NOTIFY) is not supported at the moment. - * - * Returns the actual size of the response frame, or a negative error code. - */ -int fcp_avc_transaction(struct fw_unit *unit, - const void *command, unsigned int command_size, - void *response, unsigned int response_size, - unsigned int response_match_bytes) -{ - struct fcp_transaction t; - int tcode, ret, tries = 0; - - t.unit = unit; - t.response_buffer = response; - t.response_size = response_size; - t.response_match_bytes = response_match_bytes; - t.state = STATE_PENDING; - init_waitqueue_head(&t.wait); - - spin_lock_irq(&transactions_lock); - list_add_tail(&t.list, &transactions); - spin_unlock_irq(&transactions_lock); - - for (;;) { - tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST - : TCODE_WRITE_BLOCK_REQUEST; - ret = snd_fw_transaction(t.unit, tcode, - CSR_REGISTER_BASE + CSR_FCP_COMMAND, - (void *)command, command_size); - if (ret < 0) - break; - - wait_event_timeout(t.wait, t.state != STATE_PENDING, - msecs_to_jiffies(FCP_TIMEOUT_MS)); - - if (t.state == STATE_COMPLETE) { - ret = t.response_size; - break; - } else if (t.state == STATE_BUS_RESET) { - msleep(ERROR_DELAY_MS); - } else if (++tries >= ERROR_RETRIES) { - dev_err(&t.unit->device, "FCP command timed out\n"); - ret = -EIO; - break; - } - } - - spin_lock_irq(&transactions_lock); - list_del(&t.list); - spin_unlock_irq(&transactions_lock); - - return ret; -} -EXPORT_SYMBOL(fcp_avc_transaction); - -/** - * fcp_bus_reset - inform the target handler about a bus reset - * @unit: the unit that might be used by fcp_avc_transaction() - * - * This function must be called from the driver's .update handler to inform - * the FCP transaction handler that a bus reset has happened. Any pending FCP - * transactions are retried. - */ -void fcp_bus_reset(struct fw_unit *unit) -{ - struct fcp_transaction *t; - - spin_lock_irq(&transactions_lock); - list_for_each_entry(t, &transactions, list) { - if (t->unit == unit && - t->state == STATE_PENDING) { - t->state = STATE_BUS_RESET; - wake_up(&t->wait); - } - } - spin_unlock_irq(&transactions_lock); -} -EXPORT_SYMBOL(fcp_bus_reset); - -/* checks whether the response matches the masked bytes in response_buffer */ -static bool is_matching_response(struct fcp_transaction *transaction, - const void *response, size_t length) -{ - const u8 *p1, *p2; - unsigned int mask, i; - - p1 = response; - p2 = transaction->response_buffer; - mask = transaction->response_match_bytes; - - for (i = 0; ; ++i) { - if ((mask & 1) && p1[i] != p2[i]) - return false; - mask >>= 1; - if (!mask) - return true; - if (--length == 0) - return false; - } -} - -static void fcp_response(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, unsigned long long offset, - void *data, size_t length, void *callback_data) -{ - struct fcp_transaction *t; - unsigned long flags; - - if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC) - return; - - spin_lock_irqsave(&transactions_lock, flags); - list_for_each_entry(t, &transactions, list) { - struct fw_device *device = fw_parent_device(t->unit); - if (device->card != card || - device->generation != generation) - continue; - smp_rmb(); /* node_id vs. generation */ - if (device->node_id != source) - continue; - - if (t->state == STATE_PENDING && - is_matching_response(t, data, length)) { - t->state = STATE_COMPLETE; - t->response_size = min((unsigned int)length, - t->response_size); - memcpy(t->response_buffer, data, t->response_size); - wake_up(&t->wait); - } - } - spin_unlock_irqrestore(&transactions_lock, flags); -} - -static struct fw_address_handler response_register_handler = { - .length = 0x200, - .address_callback = fcp_response, -}; - -static int __init fcp_module_init(void) -{ - static const struct fw_address_region response_register_region = { - .start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE, - .end = CSR_REGISTER_BASE + CSR_FCP_END, - }; - - fw_core_add_address_handler(&response_register_handler, - &response_register_region); - - return 0; -} - -static void __exit fcp_module_exit(void) -{ - WARN_ON(!list_empty(&transactions)); - fw_core_remove_address_handler(&response_register_handler); -} - -module_init(fcp_module_init); -module_exit(fcp_module_exit); diff --git a/ANDROID_3.4.5/sound/firewire/fcp.h b/ANDROID_3.4.5/sound/firewire/fcp.h deleted file mode 100644 index 86595688..00000000 --- a/ANDROID_3.4.5/sound/firewire/fcp.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef SOUND_FIREWIRE_FCP_H_INCLUDED -#define SOUND_FIREWIRE_FCP_H_INCLUDED - -struct fw_unit; - -int fcp_avc_transaction(struct fw_unit *unit, - const void *command, unsigned int command_size, - void *response, unsigned int response_size, - unsigned int response_match_bytes); -void fcp_bus_reset(struct fw_unit *unit); - -#endif diff --git a/ANDROID_3.4.5/sound/firewire/isight.c b/ANDROID_3.4.5/sound/firewire/isight.c deleted file mode 100644 index d428ffed..00000000 --- a/ANDROID_3.4.5/sound/firewire/isight.c +++ /dev/null @@ -1,753 +0,0 @@ -/* - * Apple iSight audio driver - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lib.h" -#include "iso-resources.h" -#include "packets-buffer.h" - -#define OUI_APPLE 0x000a27 -#define MODEL_APPLE_ISIGHT 0x000008 -#define SW_ISIGHT_AUDIO 0x000010 - -#define REG_AUDIO_ENABLE 0x000 -#define AUDIO_ENABLE 0x80000000 -#define REG_DEF_AUDIO_GAIN 0x204 -#define REG_GAIN_RAW_START 0x210 -#define REG_GAIN_RAW_END 0x214 -#define REG_GAIN_DB_START 0x218 -#define REG_GAIN_DB_END 0x21c -#define REG_SAMPLE_RATE_INQUIRY 0x280 -#define REG_ISO_TX_CONFIG 0x300 -#define SPEED_SHIFT 16 -#define REG_SAMPLE_RATE 0x400 -#define RATE_48000 0x80000000 -#define REG_GAIN 0x500 -#define REG_MUTE 0x504 - -#define MAX_FRAMES_PER_PACKET 475 - -#define QUEUE_LENGTH 20 - -struct isight { - struct snd_card *card; - struct fw_unit *unit; - struct fw_device *device; - u64 audio_base; - struct snd_pcm_substream *pcm; - struct mutex mutex; - struct iso_packets_buffer buffer; - struct fw_iso_resources resources; - struct fw_iso_context *context; - bool pcm_active; - bool pcm_running; - bool first_packet; - int packet_index; - u32 total_samples; - unsigned int buffer_pointer; - unsigned int period_counter; - s32 gain_min, gain_max; - unsigned int gain_tlv[4]; -}; - -struct audio_payload { - __be32 sample_count; - __be32 signature; - __be32 sample_total; - __be32 reserved; - __be16 samples[2 * MAX_FRAMES_PER_PACKET]; -}; - -MODULE_DESCRIPTION("iSight audio driver"); -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_LICENSE("GPL v2"); - -static struct fw_iso_packet audio_packet = { - .payload_length = sizeof(struct audio_payload), - .interrupt = 1, - .header_length = 4, -}; - -static void isight_update_pointers(struct isight *isight, unsigned int count) -{ - struct snd_pcm_runtime *runtime = isight->pcm->runtime; - unsigned int ptr; - - smp_wmb(); /* update buffer data before buffer pointer */ - - ptr = isight->buffer_pointer; - ptr += count; - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - ACCESS_ONCE(isight->buffer_pointer) = ptr; - - isight->period_counter += count; - if (isight->period_counter >= runtime->period_size) { - isight->period_counter -= runtime->period_size; - snd_pcm_period_elapsed(isight->pcm); - } -} - -static void isight_samples(struct isight *isight, - const __be16 *samples, unsigned int count) -{ - struct snd_pcm_runtime *runtime; - unsigned int count1; - - if (!ACCESS_ONCE(isight->pcm_running)) - return; - - runtime = isight->pcm->runtime; - if (isight->buffer_pointer + count <= runtime->buffer_size) { - memcpy(runtime->dma_area + isight->buffer_pointer * 4, - samples, count * 4); - } else { - count1 = runtime->buffer_size - isight->buffer_pointer; - memcpy(runtime->dma_area + isight->buffer_pointer * 4, - samples, count1 * 4); - samples += count1 * 2; - memcpy(runtime->dma_area, samples, (count - count1) * 4); - } - - isight_update_pointers(isight, count); -} - -static void isight_pcm_abort(struct isight *isight) -{ - unsigned long flags; - - if (ACCESS_ONCE(isight->pcm_active)) { - snd_pcm_stream_lock_irqsave(isight->pcm, flags); - if (snd_pcm_running(isight->pcm)) - snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN); - snd_pcm_stream_unlock_irqrestore(isight->pcm, flags); - } -} - -static void isight_dropped_samples(struct isight *isight, unsigned int total) -{ - struct snd_pcm_runtime *runtime; - u32 dropped; - unsigned int count1; - - if (!ACCESS_ONCE(isight->pcm_running)) - return; - - runtime = isight->pcm->runtime; - dropped = total - isight->total_samples; - if (dropped < runtime->buffer_size) { - if (isight->buffer_pointer + dropped <= runtime->buffer_size) { - memset(runtime->dma_area + isight->buffer_pointer * 4, - 0, dropped * 4); - } else { - count1 = runtime->buffer_size - isight->buffer_pointer; - memset(runtime->dma_area + isight->buffer_pointer * 4, - 0, count1 * 4); - memset(runtime->dma_area, 0, (dropped - count1) * 4); - } - isight_update_pointers(isight, dropped); - } else { - isight_pcm_abort(isight); - } -} - -static void isight_packet(struct fw_iso_context *context, u32 cycle, - size_t header_length, void *header, void *data) -{ - struct isight *isight = data; - const struct audio_payload *payload; - unsigned int index, length, count, total; - int err; - - if (isight->packet_index < 0) - return; - index = isight->packet_index; - payload = isight->buffer.packets[index].buffer; - length = be32_to_cpup(header) >> 16; - - if (likely(length >= 16 && - payload->signature == cpu_to_be32(0x73676874/*"sght"*/))) { - count = be32_to_cpu(payload->sample_count); - if (likely(count <= (length - 16) / 4)) { - total = be32_to_cpu(payload->sample_total); - if (unlikely(total != isight->total_samples)) { - if (!isight->first_packet) - isight_dropped_samples(isight, total); - isight->first_packet = false; - isight->total_samples = total; - } - - isight_samples(isight, payload->samples, count); - isight->total_samples += count; - } - } - - err = fw_iso_context_queue(isight->context, &audio_packet, - &isight->buffer.iso_buffer, - isight->buffer.packets[index].offset); - if (err < 0) { - dev_err(&isight->unit->device, "queueing error: %d\n", err); - isight_pcm_abort(isight); - isight->packet_index = -1; - return; - } - fw_iso_context_queue_flush(isight->context); - - if (++index >= QUEUE_LENGTH) - index = 0; - isight->packet_index = index; -} - -static int isight_connect(struct isight *isight) -{ - int ch, err, rcode, errors = 0; - __be32 value; - -retry_after_bus_reset: - ch = fw_iso_resources_allocate(&isight->resources, - sizeof(struct audio_payload), - isight->device->max_speed); - if (ch < 0) { - err = ch; - goto error; - } - - value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT)); - for (;;) { - rcode = fw_run_transaction( - isight->device->card, - TCODE_WRITE_QUADLET_REQUEST, - isight->device->node_id, - isight->resources.generation, - isight->device->max_speed, - isight->audio_base + REG_ISO_TX_CONFIG, - &value, 4); - if (rcode == RCODE_COMPLETE) { - return 0; - } else if (rcode == RCODE_GENERATION) { - fw_iso_resources_free(&isight->resources); - goto retry_after_bus_reset; - } else if (rcode_is_permanent_error(rcode) || ++errors >= 3) { - err = -EIO; - goto err_resources; - } - msleep(5); - } - -err_resources: - fw_iso_resources_free(&isight->resources); -error: - return err; -} - -static int isight_open(struct snd_pcm_substream *substream) -{ - static const struct snd_pcm_hardware hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER, - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 4 * 1024 * 1024, - .period_bytes_min = MAX_FRAMES_PER_PACKET * 4, - .period_bytes_max = 1024 * 1024, - .periods_min = 2, - .periods_max = UINT_MAX, - }; - struct isight *isight = substream->private_data; - - substream->runtime->hw = hardware; - - return iso_packets_buffer_init(&isight->buffer, isight->unit, - QUEUE_LENGTH, - sizeof(struct audio_payload), - DMA_FROM_DEVICE); -} - -static int isight_close(struct snd_pcm_substream *substream) -{ - struct isight *isight = substream->private_data; - - iso_packets_buffer_destroy(&isight->buffer, isight->unit); - - return 0; -} - -static int isight_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct isight *isight = substream->private_data; - int err; - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - ACCESS_ONCE(isight->pcm_active) = true; - - return 0; -} - -static int reg_read(struct isight *isight, int offset, __be32 *value) -{ - return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST, - isight->audio_base + offset, value, 4); -} - -static int reg_write(struct isight *isight, int offset, __be32 value) -{ - return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST, - isight->audio_base + offset, &value, 4); -} - -static void isight_stop_streaming(struct isight *isight) -{ - if (!isight->context) - return; - - fw_iso_context_stop(isight->context); - fw_iso_context_destroy(isight->context); - isight->context = NULL; - fw_iso_resources_free(&isight->resources); - reg_write(isight, REG_AUDIO_ENABLE, 0); -} - -static int isight_hw_free(struct snd_pcm_substream *substream) -{ - struct isight *isight = substream->private_data; - - ACCESS_ONCE(isight->pcm_active) = false; - - mutex_lock(&isight->mutex); - isight_stop_streaming(isight); - mutex_unlock(&isight->mutex); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static int isight_start_streaming(struct isight *isight) -{ - unsigned int i; - int err; - - if (isight->context) { - if (isight->packet_index < 0) - isight_stop_streaming(isight); - else - return 0; - } - - err = reg_write(isight, REG_SAMPLE_RATE, cpu_to_be32(RATE_48000)); - if (err < 0) - goto error; - - err = isight_connect(isight); - if (err < 0) - goto error; - - err = reg_write(isight, REG_AUDIO_ENABLE, cpu_to_be32(AUDIO_ENABLE)); - if (err < 0) - goto err_resources; - - isight->context = fw_iso_context_create(isight->device->card, - FW_ISO_CONTEXT_RECEIVE, - isight->resources.channel, - isight->device->max_speed, - 4, isight_packet, isight); - if (IS_ERR(isight->context)) { - err = PTR_ERR(isight->context); - isight->context = NULL; - goto err_resources; - } - - for (i = 0; i < QUEUE_LENGTH; ++i) { - err = fw_iso_context_queue(isight->context, &audio_packet, - &isight->buffer.iso_buffer, - isight->buffer.packets[i].offset); - if (err < 0) - goto err_context; - } - - isight->first_packet = true; - isight->packet_index = 0; - - err = fw_iso_context_start(isight->context, -1, 0, - FW_ISO_CONTEXT_MATCH_ALL_TAGS/*?*/); - if (err < 0) - goto err_context; - - return 0; - -err_context: - fw_iso_context_destroy(isight->context); - isight->context = NULL; -err_resources: - fw_iso_resources_free(&isight->resources); - reg_write(isight, REG_AUDIO_ENABLE, 0); -error: - return err; -} - -static int isight_prepare(struct snd_pcm_substream *substream) -{ - struct isight *isight = substream->private_data; - int err; - - isight->buffer_pointer = 0; - isight->period_counter = 0; - - mutex_lock(&isight->mutex); - err = isight_start_streaming(isight); - mutex_unlock(&isight->mutex); - - return err; -} - -static int isight_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct isight *isight = substream->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - ACCESS_ONCE(isight->pcm_running) = true; - break; - case SNDRV_PCM_TRIGGER_STOP: - ACCESS_ONCE(isight->pcm_running) = false; - break; - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t isight_pointer(struct snd_pcm_substream *substream) -{ - struct isight *isight = substream->private_data; - - return ACCESS_ONCE(isight->buffer_pointer); -} - -static int isight_create_pcm(struct isight *isight) -{ - static struct snd_pcm_ops ops = { - .open = isight_open, - .close = isight_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = isight_hw_params, - .hw_free = isight_hw_free, - .prepare = isight_prepare, - .trigger = isight_trigger, - .pointer = isight_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, - }; - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(isight->card, "iSight", 0, 0, 1, &pcm); - if (err < 0) - return err; - pcm->private_data = isight; - strcpy(pcm->name, "iSight"); - isight->pcm = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - isight->pcm->ops = &ops; - - return 0; -} - -static int isight_gain_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - struct isight *isight = ctl->private_data; - - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; - info->value.integer.min = isight->gain_min; - info->value.integer.max = isight->gain_max; - - return 0; -} - -static int isight_gain_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct isight *isight = ctl->private_data; - __be32 gain; - int err; - - err = reg_read(isight, REG_GAIN, &gain); - if (err < 0) - return err; - - value->value.integer.value[0] = (s32)be32_to_cpu(gain); - - return 0; -} - -static int isight_gain_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct isight *isight = ctl->private_data; - - if (value->value.integer.value[0] < isight->gain_min || - value->value.integer.value[0] > isight->gain_max) - return -EINVAL; - - return reg_write(isight, REG_GAIN, - cpu_to_be32(value->value.integer.value[0])); -} - -static int isight_mute_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct isight *isight = ctl->private_data; - __be32 mute; - int err; - - err = reg_read(isight, REG_MUTE, &mute); - if (err < 0) - return err; - - value->value.integer.value[0] = !mute; - - return 0; -} - -static int isight_mute_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct isight *isight = ctl->private_data; - - return reg_write(isight, REG_MUTE, - (__force __be32)!value->value.integer.value[0]); -} - -static int isight_create_mixer(struct isight *isight) -{ - static const struct snd_kcontrol_new gain_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Capture Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = isight_gain_info, - .get = isight_gain_get, - .put = isight_gain_put, - }; - static const struct snd_kcontrol_new mute_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Capture Switch", - .info = snd_ctl_boolean_mono_info, - .get = isight_mute_get, - .put = isight_mute_put, - }; - __be32 value; - struct snd_kcontrol *ctl; - int err; - - err = reg_read(isight, REG_GAIN_RAW_START, &value); - if (err < 0) - return err; - isight->gain_min = be32_to_cpu(value); - - err = reg_read(isight, REG_GAIN_RAW_END, &value); - if (err < 0) - return err; - isight->gain_max = be32_to_cpu(value); - - isight->gain_tlv[0] = SNDRV_CTL_TLVT_DB_MINMAX; - isight->gain_tlv[1] = 2 * sizeof(unsigned int); - - err = reg_read(isight, REG_GAIN_DB_START, &value); - if (err < 0) - return err; - isight->gain_tlv[2] = (s32)be32_to_cpu(value) * 100; - - err = reg_read(isight, REG_GAIN_DB_END, &value); - if (err < 0) - return err; - isight->gain_tlv[3] = (s32)be32_to_cpu(value) * 100; - - ctl = snd_ctl_new1(&gain_control, isight); - if (ctl) - ctl->tlv.p = isight->gain_tlv; - err = snd_ctl_add(isight->card, ctl); - if (err < 0) - return err; - - err = snd_ctl_add(isight->card, snd_ctl_new1(&mute_control, isight)); - if (err < 0) - return err; - - return 0; -} - -static void isight_card_free(struct snd_card *card) -{ - struct isight *isight = card->private_data; - - fw_iso_resources_destroy(&isight->resources); - fw_unit_put(isight->unit); - mutex_destroy(&isight->mutex); -} - -static u64 get_unit_base(struct fw_unit *unit) -{ - struct fw_csr_iterator i; - int key, value; - - fw_csr_iterator_init(&i, unit->directory); - while (fw_csr_iterator_next(&i, &key, &value)) - if (key == CSR_OFFSET) - return CSR_REGISTER_BASE + value * 4; - return 0; -} - -static int isight_probe(struct device *unit_dev) -{ - struct fw_unit *unit = fw_unit(unit_dev); - struct fw_device *fw_dev = fw_parent_device(unit); - struct snd_card *card; - struct isight *isight; - int err; - - err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*isight), &card); - if (err < 0) - return err; - snd_card_set_dev(card, unit_dev); - - isight = card->private_data; - isight->card = card; - mutex_init(&isight->mutex); - isight->unit = fw_unit_get(unit); - isight->device = fw_dev; - isight->audio_base = get_unit_base(unit); - if (!isight->audio_base) { - dev_err(&unit->device, "audio unit base not found\n"); - err = -ENXIO; - goto err_unit; - } - fw_iso_resources_init(&isight->resources, unit); - - card->private_free = isight_card_free; - - strcpy(card->driver, "iSight"); - strcpy(card->shortname, "Apple iSight"); - snprintf(card->longname, sizeof(card->longname), - "Apple iSight (GUID %08x%08x) at %s, S%d", - fw_dev->config_rom[3], fw_dev->config_rom[4], - dev_name(&unit->device), 100 << fw_dev->max_speed); - strcpy(card->mixername, "iSight"); - - err = isight_create_pcm(isight); - if (err < 0) - goto error; - - err = isight_create_mixer(isight); - if (err < 0) - goto error; - - err = snd_card_register(card); - if (err < 0) - goto error; - - dev_set_drvdata(unit_dev, isight); - - return 0; - -err_unit: - fw_unit_put(isight->unit); - mutex_destroy(&isight->mutex); -error: - snd_card_free(card); - return err; -} - -static int isight_remove(struct device *dev) -{ - struct isight *isight = dev_get_drvdata(dev); - - isight_pcm_abort(isight); - - snd_card_disconnect(isight->card); - - mutex_lock(&isight->mutex); - isight_stop_streaming(isight); - mutex_unlock(&isight->mutex); - - snd_card_free_when_closed(isight->card); - - return 0; -} - -static void isight_bus_reset(struct fw_unit *unit) -{ - struct isight *isight = dev_get_drvdata(&unit->device); - - if (fw_iso_resources_update(&isight->resources) < 0) { - isight_pcm_abort(isight); - - mutex_lock(&isight->mutex); - isight_stop_streaming(isight); - mutex_unlock(&isight->mutex); - } -} - -static const struct ieee1394_device_id isight_id_table[] = { - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | - IEEE1394_MATCH_VERSION, - .specifier_id = OUI_APPLE, - .version = SW_ISIGHT_AUDIO, - }, - { } -}; -MODULE_DEVICE_TABLE(ieee1394, isight_id_table); - -static struct fw_driver isight_driver = { - .driver = { - .owner = THIS_MODULE, - .name = KBUILD_MODNAME, - .bus = &fw_bus_type, - .probe = isight_probe, - .remove = isight_remove, - }, - .update = isight_bus_reset, - .id_table = isight_id_table, -}; - -static int __init alsa_isight_init(void) -{ - return driver_register(&isight_driver.driver); -} - -static void __exit alsa_isight_exit(void) -{ - driver_unregister(&isight_driver.driver); -} - -module_init(alsa_isight_init); -module_exit(alsa_isight_exit); diff --git a/ANDROID_3.4.5/sound/firewire/iso-resources.c b/ANDROID_3.4.5/sound/firewire/iso-resources.c deleted file mode 100644 index 5f17b77e..00000000 --- a/ANDROID_3.4.5/sound/firewire/iso-resources.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * isochronous resources helper functions - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "iso-resources.h" - -/** - * fw_iso_resources_init - initializes a &struct fw_iso_resources - * @r: the resource manager to initialize - * @unit: the device unit for which the resources will be needed - * - * If the device does not support all channel numbers, change @r->channels_mask - * after calling this function. - */ -int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit) -{ - r->channels_mask = ~0uLL; - r->unit = fw_unit_get(unit); - mutex_init(&r->mutex); - r->allocated = false; - - return 0; -} -EXPORT_SYMBOL(fw_iso_resources_init); - -/** - * fw_iso_resources_destroy - destroy a resource manager - * @r: the resource manager that is no longer needed - */ -void fw_iso_resources_destroy(struct fw_iso_resources *r) -{ - WARN_ON(r->allocated); - mutex_destroy(&r->mutex); - fw_unit_put(r->unit); -} -EXPORT_SYMBOL(fw_iso_resources_destroy); - -static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed) -{ - unsigned int bytes, s400_bytes; - - /* iso packets have three header quadlets and quadlet-aligned payload */ - bytes = 3 * 4 + ALIGN(max_payload_bytes, 4); - - /* convert to bandwidth units (quadlets at S1600 = bytes at S400) */ - if (speed <= SCODE_400) - s400_bytes = bytes * (1 << (SCODE_400 - speed)); - else - s400_bytes = DIV_ROUND_UP(bytes, 1 << (speed - SCODE_400)); - - return s400_bytes; -} - -static int current_bandwidth_overhead(struct fw_card *card) -{ - /* - * Under the usual pessimistic assumption (cable length 4.5 m), the - * isochronous overhead for N cables is 1.797 µs + N * 0.494 µs, or - * 88.3 + N * 24.3 in bandwidth units. - * - * The calculation below tries to deduce N from the current gap count. - * If the gap count has been optimized by measuring the actual packet - * transmission time, this derived overhead should be near the actual - * overhead as well. - */ - return card->gap_count < 63 ? card->gap_count * 97 / 10 + 89 : 512; -} - -static int wait_isoch_resource_delay_after_bus_reset(struct fw_card *card) -{ - for (;;) { - s64 delay = (card->reset_jiffies + HZ) - get_jiffies_64(); - if (delay <= 0) - return 0; - if (schedule_timeout_interruptible(delay) > 0) - return -ERESTARTSYS; - } -} - -/** - * fw_iso_resources_allocate - allocate isochronous channel and bandwidth - * @r: the resource manager - * @max_payload_bytes: the amount of data (including CIP headers) per packet - * @speed: the speed (e.g., SCODE_400) at which the packets will be sent - * - * This function allocates one isochronous channel and enough bandwidth for the - * specified packet size. - * - * Returns the channel number that the caller must use for streaming, or - * a negative error code. Due to potentionally long delays, this function is - * interruptible and can return -ERESTARTSYS. On success, the caller is - * responsible for calling fw_iso_resources_update() on bus resets, and - * fw_iso_resources_free() when the resources are not longer needed. - */ -int fw_iso_resources_allocate(struct fw_iso_resources *r, - unsigned int max_payload_bytes, int speed) -{ - struct fw_card *card = fw_parent_device(r->unit)->card; - int bandwidth, channel, err; - - if (WARN_ON(r->allocated)) - return -EBADFD; - - r->bandwidth = packet_bandwidth(max_payload_bytes, speed); - -retry_after_bus_reset: - spin_lock_irq(&card->lock); - r->generation = card->generation; - r->bandwidth_overhead = current_bandwidth_overhead(card); - spin_unlock_irq(&card->lock); - - err = wait_isoch_resource_delay_after_bus_reset(card); - if (err < 0) - return err; - - mutex_lock(&r->mutex); - - bandwidth = r->bandwidth + r->bandwidth_overhead; - fw_iso_resource_manage(card, r->generation, r->channels_mask, - &channel, &bandwidth, true); - if (channel == -EAGAIN) { - mutex_unlock(&r->mutex); - goto retry_after_bus_reset; - } - if (channel >= 0) { - r->channel = channel; - r->allocated = true; - } else { - if (channel == -EBUSY) - dev_err(&r->unit->device, - "isochronous resources exhausted\n"); - else - dev_err(&r->unit->device, - "isochronous resource allocation failed\n"); - } - - mutex_unlock(&r->mutex); - - return channel; -} -EXPORT_SYMBOL(fw_iso_resources_allocate); - -/** - * fw_iso_resources_update - update resource allocations after a bus reset - * @r: the resource manager - * - * This function must be called from the driver's .update handler to reallocate - * any resources that were allocated before the bus reset. It is safe to call - * this function if no resources are currently allocated. - * - * Returns a negative error code on failure. If this happens, the caller must - * stop streaming. - */ -int fw_iso_resources_update(struct fw_iso_resources *r) -{ - struct fw_card *card = fw_parent_device(r->unit)->card; - int bandwidth, channel; - - mutex_lock(&r->mutex); - - if (!r->allocated) { - mutex_unlock(&r->mutex); - return 0; - } - - spin_lock_irq(&card->lock); - r->generation = card->generation; - r->bandwidth_overhead = current_bandwidth_overhead(card); - spin_unlock_irq(&card->lock); - - bandwidth = r->bandwidth + r->bandwidth_overhead; - - fw_iso_resource_manage(card, r->generation, 1uLL << r->channel, - &channel, &bandwidth, true); - /* - * When another bus reset happens, pretend that the allocation - * succeeded; we will try again for the new generation later. - */ - if (channel < 0 && channel != -EAGAIN) { - r->allocated = false; - if (channel == -EBUSY) - dev_err(&r->unit->device, - "isochronous resources exhausted\n"); - else - dev_err(&r->unit->device, - "isochronous resource allocation failed\n"); - } - - mutex_unlock(&r->mutex); - - return channel; -} -EXPORT_SYMBOL(fw_iso_resources_update); - -/** - * fw_iso_resources_free - frees allocated resources - * @r: the resource manager - * - * This function deallocates the channel and bandwidth, if allocated. - */ -void fw_iso_resources_free(struct fw_iso_resources *r) -{ - struct fw_card *card = fw_parent_device(r->unit)->card; - int bandwidth, channel; - - mutex_lock(&r->mutex); - - if (r->allocated) { - bandwidth = r->bandwidth + r->bandwidth_overhead; - fw_iso_resource_manage(card, r->generation, 1uLL << r->channel, - &channel, &bandwidth, false); - if (channel < 0) - dev_err(&r->unit->device, - "isochronous resource deallocation failed\n"); - - r->allocated = false; - } - - mutex_unlock(&r->mutex); -} -EXPORT_SYMBOL(fw_iso_resources_free); diff --git a/ANDROID_3.4.5/sound/firewire/iso-resources.h b/ANDROID_3.4.5/sound/firewire/iso-resources.h deleted file mode 100644 index 5a9af7c6..00000000 --- a/ANDROID_3.4.5/sound/firewire/iso-resources.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef SOUND_FIREWIRE_ISO_RESOURCES_H_INCLUDED -#define SOUND_FIREWIRE_ISO_RESOURCES_H_INCLUDED - -#include -#include - -struct fw_unit; - -/** - * struct fw_iso_resources - manages channel/bandwidth allocation - * @channels_mask: if the device does not support all channel numbers, set this - * bit mask to something else than the default (all ones) - * - * This structure manages (de)allocation of isochronous resources (channel and - * bandwidth) for one isochronous stream. - */ -struct fw_iso_resources { - u64 channels_mask; - /* private: */ - struct fw_unit *unit; - struct mutex mutex; - unsigned int channel; - unsigned int bandwidth; /* in bandwidth units, without overhead */ - unsigned int bandwidth_overhead; - int generation; /* in which allocation is valid */ - bool allocated; -}; - -int fw_iso_resources_init(struct fw_iso_resources *r, - struct fw_unit *unit); -void fw_iso_resources_destroy(struct fw_iso_resources *r); - -int fw_iso_resources_allocate(struct fw_iso_resources *r, - unsigned int max_payload_bytes, int speed); -int fw_iso_resources_update(struct fw_iso_resources *r); -void fw_iso_resources_free(struct fw_iso_resources *r); - -#endif diff --git a/ANDROID_3.4.5/sound/firewire/lib.c b/ANDROID_3.4.5/sound/firewire/lib.c deleted file mode 100644 index 4750cea2..00000000 --- a/ANDROID_3.4.5/sound/firewire/lib.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * miscellaneous helper functions - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include -#include "lib.h" - -#define ERROR_RETRY_DELAY_MS 5 - -/** - * rcode_string - convert a firewire result code to a string - * @rcode: the result - */ -const char *rcode_string(unsigned int rcode) -{ - static const char *const names[] = { - [RCODE_COMPLETE] = "complete", - [RCODE_CONFLICT_ERROR] = "conflict error", - [RCODE_DATA_ERROR] = "data error", - [RCODE_TYPE_ERROR] = "type error", - [RCODE_ADDRESS_ERROR] = "address error", - [RCODE_SEND_ERROR] = "send error", - [RCODE_CANCELLED] = "cancelled", - [RCODE_BUSY] = "busy", - [RCODE_GENERATION] = "generation", - [RCODE_NO_ACK] = "no ack", - }; - - if (rcode < ARRAY_SIZE(names) && names[rcode]) - return names[rcode]; - else - return "unknown"; -} -EXPORT_SYMBOL(rcode_string); - -/** - * snd_fw_transaction - send a request and wait for its completion - * @unit: the driver's unit on the target device - * @tcode: the transaction code - * @offset: the address in the target's address space - * @buffer: input/output data - * @length: length of @buffer - * - * Submits an asynchronous request to the target device, and waits for the - * response. The node ID and the current generation are derived from @unit. - * On a bus reset or an error, the transaction is retried a few times. - * Returns zero on success, or a negative error code. - */ -int snd_fw_transaction(struct fw_unit *unit, int tcode, - u64 offset, void *buffer, size_t length) -{ - struct fw_device *device = fw_parent_device(unit); - int generation, rcode, tries = 0; - - for (;;) { - generation = device->generation; - smp_rmb(); /* node_id vs. generation */ - rcode = fw_run_transaction(device->card, tcode, - device->node_id, generation, - device->max_speed, offset, - buffer, length); - - if (rcode == RCODE_COMPLETE) - return 0; - - if (rcode_is_permanent_error(rcode) || ++tries >= 3) { - dev_err(&unit->device, "transaction failed: %s\n", - rcode_string(rcode)); - return -EIO; - } - - msleep(ERROR_RETRY_DELAY_MS); - } -} -EXPORT_SYMBOL(snd_fw_transaction); - -MODULE_DESCRIPTION("FireWire audio helper functions"); -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/firewire/lib.h b/ANDROID_3.4.5/sound/firewire/lib.h deleted file mode 100644 index 064f3fd9..00000000 --- a/ANDROID_3.4.5/sound/firewire/lib.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SOUND_FIREWIRE_LIB_H_INCLUDED -#define SOUND_FIREWIRE_LIB_H_INCLUDED - -#include -#include - -struct fw_unit; - -int snd_fw_transaction(struct fw_unit *unit, int tcode, - u64 offset, void *buffer, size_t length); -const char *rcode_string(unsigned int rcode); - -/* returns true if retrying the transaction would not make sense */ -static inline bool rcode_is_permanent_error(int rcode) -{ - return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR; -} - -#endif diff --git a/ANDROID_3.4.5/sound/firewire/packets-buffer.c b/ANDROID_3.4.5/sound/firewire/packets-buffer.c deleted file mode 100644 index ea150667..00000000 --- a/ANDROID_3.4.5/sound/firewire/packets-buffer.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * helpers for managing a buffer for many packets - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include "packets-buffer.h" - -/** - * iso_packets_buffer_init - allocates the memory for packets - * @b: the buffer structure to initialize - * @unit: the device at the other end of the stream - * @count: the number of packets - * @packet_size: the (maximum) size of a packet, in bytes - * @direction: %DMA_TO_DEVICE or %DMA_FROM_DEVICE - */ -int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, - unsigned int count, unsigned int packet_size, - enum dma_data_direction direction) -{ - unsigned int packets_per_page, pages; - unsigned int i, page_index, offset_in_page; - void *p; - int err; - - b->packets = kmalloc(count * sizeof(*b->packets), GFP_KERNEL); - if (!b->packets) { - err = -ENOMEM; - goto error; - } - - packet_size = L1_CACHE_ALIGN(packet_size); - packets_per_page = PAGE_SIZE / packet_size; - if (WARN_ON(!packets_per_page)) { - err = -EINVAL; - goto error; - } - pages = DIV_ROUND_UP(count, packets_per_page); - - err = fw_iso_buffer_init(&b->iso_buffer, fw_parent_device(unit)->card, - pages, direction); - if (err < 0) - goto err_packets; - - for (i = 0; i < count; ++i) { - page_index = i / packets_per_page; - p = page_address(b->iso_buffer.pages[page_index]); - offset_in_page = (i % packets_per_page) * packet_size; - b->packets[i].buffer = p + offset_in_page; - b->packets[i].offset = page_index * PAGE_SIZE + offset_in_page; - } - - return 0; - -err_packets: - kfree(b->packets); -error: - return err; -} -EXPORT_SYMBOL(iso_packets_buffer_init); - -/** - * iso_packets_buffer_destroy - frees packet buffer resources - * @b: the buffer structure to free - * @unit: the device at the other end of the stream - */ -void iso_packets_buffer_destroy(struct iso_packets_buffer *b, - struct fw_unit *unit) -{ - fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card); - kfree(b->packets); -} -EXPORT_SYMBOL(iso_packets_buffer_destroy); diff --git a/ANDROID_3.4.5/sound/firewire/packets-buffer.h b/ANDROID_3.4.5/sound/firewire/packets-buffer.h deleted file mode 100644 index 6513c5cb..00000000 --- a/ANDROID_3.4.5/sound/firewire/packets-buffer.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SOUND_FIREWIRE_PACKETS_BUFFER_H_INCLUDED -#define SOUND_FIREWIRE_PACKETS_BUFFER_H_INCLUDED - -#include -#include - -/** - * struct iso_packets_buffer - manages a buffer for many packets - * @iso_buffer: the memory containing the packets - * @packets: an array, with each element pointing to one packet - */ -struct iso_packets_buffer { - struct fw_iso_buffer iso_buffer; - struct { - void *buffer; - unsigned int offset; - } *packets; -}; - -int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, - unsigned int count, unsigned int packet_size, - enum dma_data_direction direction); -void iso_packets_buffer_destroy(struct iso_packets_buffer *b, - struct fw_unit *unit); - -#endif diff --git a/ANDROID_3.4.5/sound/firewire/speakers.c b/ANDROID_3.4.5/sound/firewire/speakers.c deleted file mode 100644 index 297244e6..00000000 --- a/ANDROID_3.4.5/sound/firewire/speakers.c +++ /dev/null @@ -1,854 +0,0 @@ -/* - * OXFW970-based speakers driver - * - * Copyright (c) Clemens Ladisch - * Licensed under the terms of the GNU General Public License, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cmp.h" -#include "fcp.h" -#include "amdtp.h" -#include "lib.h" - -#define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000) -/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */ - -#define OXFORD_HARDWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x90020) -#define OXFORD_HARDWARE_ID_OXFW970 0x39443841 -#define OXFORD_HARDWARE_ID_OXFW971 0x39373100 - -#define VENDOR_GRIFFIN 0x001292 -#define VENDOR_LACIE 0x00d04b - -#define SPECIFIER_1394TA 0x00a02d -#define VERSION_AVC 0x010001 - -struct device_info { - const char *driver_name; - const char *short_name; - const char *long_name; - int (*pcm_constraints)(struct snd_pcm_runtime *runtime); - unsigned int mixer_channels; - u8 mute_fb_id; - u8 volume_fb_id; -}; - -struct fwspk { - struct snd_card *card; - struct fw_unit *unit; - const struct device_info *device_info; - struct snd_pcm_substream *pcm; - struct mutex mutex; - struct cmp_connection connection; - struct amdtp_out_stream stream; - bool stream_running; - bool mute; - s16 volume[6]; - s16 volume_min; - s16 volume_max; -}; - -MODULE_DESCRIPTION("FireWire speakers driver"); -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_LICENSE("GPL v2"); - -static int firewave_rate_constraint(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - static unsigned int stereo_rates[] = { 48000, 96000 }; - struct snd_interval *channels = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *rate = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - - /* two channels work only at 48/96 kHz */ - if (snd_interval_max(channels) < 6) - return snd_interval_list(rate, 2, stereo_rates, 0); - return 0; -} - -static int firewave_channels_constraint(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - static const struct snd_interval all_channels = { .min = 6, .max = 6 }; - struct snd_interval *rate = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *channels = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - - /* 32/44.1 kHz work only with all six channels */ - if (snd_interval_max(rate) < 48000) - return snd_interval_refine(channels, &all_channels); - return 0; -} - -static int firewave_constraints(struct snd_pcm_runtime *runtime) -{ - static unsigned int channels_list[] = { 2, 6 }; - static struct snd_pcm_hw_constraint_list channels_list_constraint = { - .count = 2, - .list = channels_list, - }; - int err; - - runtime->hw.rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000; - runtime->hw.channels_max = 6; - - err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &channels_list_constraint); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - firewave_rate_constraint, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - firewave_channels_constraint, NULL, - SNDRV_PCM_HW_PARAM_RATE, -1); - if (err < 0) - return err; - - return 0; -} - -static int lacie_speakers_constraints(struct snd_pcm_runtime *runtime) -{ - runtime->hw.rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000; - - return 0; -} - -static int fwspk_open(struct snd_pcm_substream *substream) -{ - static const struct snd_pcm_hardware hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER, - .formats = AMDTP_OUT_PCM_FORMAT_BITS, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 4 * 1024 * 1024, - .period_bytes_min = 1, - .period_bytes_max = UINT_MAX, - .periods_min = 1, - .periods_max = UINT_MAX, - }; - struct fwspk *fwspk = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - runtime->hw = hardware; - - err = fwspk->device_info->pcm_constraints(runtime); - if (err < 0) - return err; - err = snd_pcm_limit_hw_rates(runtime); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_TIME, - 5000, UINT_MAX); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - if (err < 0) - return err; - - return 0; -} - -static int fwspk_close(struct snd_pcm_substream *substream) -{ - return 0; -} - -static void fwspk_stop_stream(struct fwspk *fwspk) -{ - if (fwspk->stream_running) { - amdtp_out_stream_stop(&fwspk->stream); - cmp_connection_break(&fwspk->connection); - fwspk->stream_running = false; - } -} - -static int fwspk_set_rate(struct fwspk *fwspk, unsigned int sfc) -{ - u8 *buf; - int err; - - buf = kmalloc(8, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - buf[0] = 0x00; /* AV/C, CONTROL */ - buf[1] = 0xff; /* unit */ - buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ - buf[3] = 0x00; /* plug 0 */ - buf[4] = 0x90; /* format: audio */ - buf[5] = 0x00 | sfc; /* AM824, frequency */ - buf[6] = 0xff; /* SYT (not used) */ - buf[7] = 0xff; - - err = fcp_avc_transaction(fwspk->unit, buf, 8, buf, 8, - BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5)); - if (err < 0) - goto error; - if (err < 6 || buf[0] != 0x09 /* ACCEPTED */) { - dev_err(&fwspk->unit->device, "failed to set sample rate\n"); - err = -EIO; - goto error; - } - - err = 0; - -error: - kfree(buf); - - return err; -} - -static int fwspk_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct fwspk *fwspk = substream->private_data; - int err; - - mutex_lock(&fwspk->mutex); - fwspk_stop_stream(fwspk); - mutex_unlock(&fwspk->mutex); - - err = snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - goto error; - - amdtp_out_stream_set_rate(&fwspk->stream, params_rate(hw_params)); - amdtp_out_stream_set_pcm(&fwspk->stream, params_channels(hw_params)); - - amdtp_out_stream_set_pcm_format(&fwspk->stream, - params_format(hw_params)); - - err = fwspk_set_rate(fwspk, fwspk->stream.sfc); - if (err < 0) - goto err_buffer; - - return 0; - -err_buffer: - snd_pcm_lib_free_vmalloc_buffer(substream); -error: - return err; -} - -static int fwspk_hw_free(struct snd_pcm_substream *substream) -{ - struct fwspk *fwspk = substream->private_data; - - mutex_lock(&fwspk->mutex); - fwspk_stop_stream(fwspk); - mutex_unlock(&fwspk->mutex); - - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -static int fwspk_prepare(struct snd_pcm_substream *substream) -{ - struct fwspk *fwspk = substream->private_data; - int err; - - mutex_lock(&fwspk->mutex); - - if (amdtp_out_streaming_error(&fwspk->stream)) - fwspk_stop_stream(fwspk); - - if (!fwspk->stream_running) { - err = cmp_connection_establish(&fwspk->connection, - amdtp_out_stream_get_max_payload(&fwspk->stream)); - if (err < 0) - goto err_mutex; - - err = amdtp_out_stream_start(&fwspk->stream, - fwspk->connection.resources.channel, - fwspk->connection.speed); - if (err < 0) - goto err_connection; - - fwspk->stream_running = true; - } - - mutex_unlock(&fwspk->mutex); - - amdtp_out_stream_pcm_prepare(&fwspk->stream); - - return 0; - -err_connection: - cmp_connection_break(&fwspk->connection); -err_mutex: - mutex_unlock(&fwspk->mutex); - - return err; -} - -static int fwspk_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct fwspk *fwspk = substream->private_data; - struct snd_pcm_substream *pcm; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - pcm = substream; - break; - case SNDRV_PCM_TRIGGER_STOP: - pcm = NULL; - break; - default: - return -EINVAL; - } - amdtp_out_stream_pcm_trigger(&fwspk->stream, pcm); - return 0; -} - -static snd_pcm_uframes_t fwspk_pointer(struct snd_pcm_substream *substream) -{ - struct fwspk *fwspk = substream->private_data; - - return amdtp_out_stream_pcm_pointer(&fwspk->stream); -} - -static int fwspk_create_pcm(struct fwspk *fwspk) -{ - static struct snd_pcm_ops ops = { - .open = fwspk_open, - .close = fwspk_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = fwspk_hw_params, - .hw_free = fwspk_hw_free, - .prepare = fwspk_prepare, - .trigger = fwspk_trigger, - .pointer = fwspk_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, - }; - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(fwspk->card, "OXFW970", 0, 1, 0, &pcm); - if (err < 0) - return err; - pcm->private_data = fwspk; - strcpy(pcm->name, fwspk->device_info->short_name); - fwspk->pcm = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - fwspk->pcm->ops = &ops; - return 0; -} - -enum control_action { CTL_READ, CTL_WRITE }; -enum control_attribute { - CTL_MIN = 0x02, - CTL_MAX = 0x03, - CTL_CURRENT = 0x10, -}; - -static int fwspk_mute_command(struct fwspk *fwspk, bool *value, - enum control_action action) -{ - u8 *buf; - u8 response_ok; - int err; - - buf = kmalloc(11, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (action == CTL_READ) { - buf[0] = 0x01; /* AV/C, STATUS */ - response_ok = 0x0c; /* STABLE */ - } else { - buf[0] = 0x00; /* AV/C, CONTROL */ - response_ok = 0x09; /* ACCEPTED */ - } - buf[1] = 0x08; /* audio unit 0 */ - buf[2] = 0xb8; /* FUNCTION BLOCK */ - buf[3] = 0x81; /* function block type: feature */ - buf[4] = fwspk->device_info->mute_fb_id; /* function block ID */ - buf[5] = 0x10; /* control attribute: current */ - buf[6] = 0x02; /* selector length */ - buf[7] = 0x00; /* audio channel number */ - buf[8] = 0x01; /* control selector: mute */ - buf[9] = 0x01; /* control data length */ - if (action == CTL_READ) - buf[10] = 0xff; - else - buf[10] = *value ? 0x70 : 0x60; - - err = fcp_avc_transaction(fwspk->unit, buf, 11, buf, 11, 0x3fe); - if (err < 0) - goto error; - if (err < 11) { - dev_err(&fwspk->unit->device, "short FCP response\n"); - err = -EIO; - goto error; - } - if (buf[0] != response_ok) { - dev_err(&fwspk->unit->device, "mute command failed\n"); - err = -EIO; - goto error; - } - if (action == CTL_READ) - *value = buf[10] == 0x70; - - err = 0; - -error: - kfree(buf); - - return err; -} - -static int fwspk_volume_command(struct fwspk *fwspk, s16 *value, - unsigned int channel, - enum control_attribute attribute, - enum control_action action) -{ - u8 *buf; - u8 response_ok; - int err; - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (action == CTL_READ) { - buf[0] = 0x01; /* AV/C, STATUS */ - response_ok = 0x0c; /* STABLE */ - } else { - buf[0] = 0x00; /* AV/C, CONTROL */ - response_ok = 0x09; /* ACCEPTED */ - } - buf[1] = 0x08; /* audio unit 0 */ - buf[2] = 0xb8; /* FUNCTION BLOCK */ - buf[3] = 0x81; /* function block type: feature */ - buf[4] = fwspk->device_info->volume_fb_id; /* function block ID */ - buf[5] = attribute; /* control attribute */ - buf[6] = 0x02; /* selector length */ - buf[7] = channel; /* audio channel number */ - buf[8] = 0x02; /* control selector: volume */ - buf[9] = 0x02; /* control data length */ - if (action == CTL_READ) { - buf[10] = 0xff; - buf[11] = 0xff; - } else { - buf[10] = *value >> 8; - buf[11] = *value; - } - - err = fcp_avc_transaction(fwspk->unit, buf, 12, buf, 12, 0x3fe); - if (err < 0) - goto error; - if (err < 12) { - dev_err(&fwspk->unit->device, "short FCP response\n"); - err = -EIO; - goto error; - } - if (buf[0] != response_ok) { - dev_err(&fwspk->unit->device, "volume command failed\n"); - err = -EIO; - goto error; - } - if (action == CTL_READ) - *value = (buf[10] << 8) | buf[11]; - - err = 0; - -error: - kfree(buf); - - return err; -} - -static int fwspk_mute_get(struct snd_kcontrol *control, - struct snd_ctl_elem_value *value) -{ - struct fwspk *fwspk = control->private_data; - - value->value.integer.value[0] = !fwspk->mute; - - return 0; -} - -static int fwspk_mute_put(struct snd_kcontrol *control, - struct snd_ctl_elem_value *value) -{ - struct fwspk *fwspk = control->private_data; - bool mute; - int err; - - mute = !value->value.integer.value[0]; - - if (mute == fwspk->mute) - return 0; - - err = fwspk_mute_command(fwspk, &mute, CTL_WRITE); - if (err < 0) - return err; - fwspk->mute = mute; - - return 1; -} - -static int fwspk_volume_info(struct snd_kcontrol *control, - struct snd_ctl_elem_info *info) -{ - struct fwspk *fwspk = control->private_data; - - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = fwspk->device_info->mixer_channels; - info->value.integer.min = fwspk->volume_min; - info->value.integer.max = fwspk->volume_max; - - return 0; -} - -static const u8 channel_map[6] = { 0, 1, 4, 5, 2, 3 }; - -static int fwspk_volume_get(struct snd_kcontrol *control, - struct snd_ctl_elem_value *value) -{ - struct fwspk *fwspk = control->private_data; - unsigned int i; - - for (i = 0; i < fwspk->device_info->mixer_channels; ++i) - value->value.integer.value[channel_map[i]] = fwspk->volume[i]; - - return 0; -} - -static int fwspk_volume_put(struct snd_kcontrol *control, - struct snd_ctl_elem_value *value) -{ - struct fwspk *fwspk = control->private_data; - unsigned int i, changed_channels; - bool equal_values = true; - s16 volume; - int err; - - for (i = 0; i < fwspk->device_info->mixer_channels; ++i) { - if (value->value.integer.value[i] < fwspk->volume_min || - value->value.integer.value[i] > fwspk->volume_max) - return -EINVAL; - if (value->value.integer.value[i] != - value->value.integer.value[0]) - equal_values = false; - } - - changed_channels = 0; - for (i = 0; i < fwspk->device_info->mixer_channels; ++i) - if (value->value.integer.value[channel_map[i]] != - fwspk->volume[i]) - changed_channels |= 1 << (i + 1); - - if (equal_values && changed_channels != 0) - changed_channels = 1 << 0; - - for (i = 0; i <= fwspk->device_info->mixer_channels; ++i) { - volume = value->value.integer.value[channel_map[i ? i - 1 : 0]]; - if (changed_channels & (1 << i)) { - err = fwspk_volume_command(fwspk, &volume, i, - CTL_CURRENT, CTL_WRITE); - if (err < 0) - return err; - } - if (i > 0) - fwspk->volume[i - 1] = volume; - } - - return changed_channels != 0; -} - -static int fwspk_create_mixer(struct fwspk *fwspk) -{ - static const struct snd_kcontrol_new controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = fwspk_mute_get, - .put = fwspk_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .info = fwspk_volume_info, - .get = fwspk_volume_get, - .put = fwspk_volume_put, - }, - }; - unsigned int i, first_ch; - int err; - - err = fwspk_volume_command(fwspk, &fwspk->volume_min, - 0, CTL_MIN, CTL_READ); - if (err < 0) - return err; - err = fwspk_volume_command(fwspk, &fwspk->volume_max, - 0, CTL_MAX, CTL_READ); - if (err < 0) - return err; - - err = fwspk_mute_command(fwspk, &fwspk->mute, CTL_READ); - if (err < 0) - return err; - - first_ch = fwspk->device_info->mixer_channels == 1 ? 0 : 1; - for (i = 0; i < fwspk->device_info->mixer_channels; ++i) { - err = fwspk_volume_command(fwspk, &fwspk->volume[i], - first_ch + i, CTL_CURRENT, CTL_READ); - if (err < 0) - return err; - } - - for (i = 0; i < ARRAY_SIZE(controls); ++i) { - err = snd_ctl_add(fwspk->card, - snd_ctl_new1(&controls[i], fwspk)); - if (err < 0) - return err; - } - - return 0; -} - -static u32 fwspk_read_firmware_version(struct fw_unit *unit) -{ - __be32 data; - int err; - - err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, - OXFORD_FIRMWARE_ID_ADDRESS, &data, 4); - return err >= 0 ? be32_to_cpu(data) : 0; -} - -static void fwspk_card_free(struct snd_card *card) -{ - struct fwspk *fwspk = card->private_data; - - amdtp_out_stream_destroy(&fwspk->stream); - cmp_connection_destroy(&fwspk->connection); - fw_unit_put(fwspk->unit); - mutex_destroy(&fwspk->mutex); -} - -static const struct device_info *__devinit fwspk_detect(struct fw_device *dev) -{ - static const struct device_info griffin_firewave = { - .driver_name = "FireWave", - .short_name = "FireWave", - .long_name = "Griffin FireWave Surround", - .pcm_constraints = firewave_constraints, - .mixer_channels = 6, - .mute_fb_id = 0x01, - .volume_fb_id = 0x02, - }; - static const struct device_info lacie_speakers = { - .driver_name = "FWSpeakers", - .short_name = "FireWire Speakers", - .long_name = "LaCie FireWire Speakers", - .pcm_constraints = lacie_speakers_constraints, - .mixer_channels = 1, - .mute_fb_id = 0x01, - .volume_fb_id = 0x01, - }; - struct fw_csr_iterator i; - int key, value; - - fw_csr_iterator_init(&i, dev->config_rom); - while (fw_csr_iterator_next(&i, &key, &value)) - if (key == CSR_VENDOR) - switch (value) { - case VENDOR_GRIFFIN: - return &griffin_firewave; - case VENDOR_LACIE: - return &lacie_speakers; - } - - return NULL; -} - -static int __devinit fwspk_probe(struct device *unit_dev) -{ - struct fw_unit *unit = fw_unit(unit_dev); - struct fw_device *fw_dev = fw_parent_device(unit); - struct snd_card *card; - struct fwspk *fwspk; - u32 firmware; - int err; - - err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*fwspk), &card); - if (err < 0) - return err; - snd_card_set_dev(card, unit_dev); - - fwspk = card->private_data; - fwspk->card = card; - mutex_init(&fwspk->mutex); - fwspk->unit = fw_unit_get(unit); - fwspk->device_info = fwspk_detect(fw_dev); - if (!fwspk->device_info) { - err = -ENODEV; - goto err_unit; - } - - err = cmp_connection_init(&fwspk->connection, unit, 0); - if (err < 0) - goto err_unit; - - err = amdtp_out_stream_init(&fwspk->stream, unit, CIP_NONBLOCKING); - if (err < 0) - goto err_connection; - - card->private_free = fwspk_card_free; - - strcpy(card->driver, fwspk->device_info->driver_name); - strcpy(card->shortname, fwspk->device_info->short_name); - firmware = fwspk_read_firmware_version(unit); - snprintf(card->longname, sizeof(card->longname), - "%s (OXFW%x %04x), GUID %08x%08x at %s, S%d", - fwspk->device_info->long_name, - firmware >> 20, firmware & 0xffff, - fw_dev->config_rom[3], fw_dev->config_rom[4], - dev_name(&unit->device), 100 << fw_dev->max_speed); - strcpy(card->mixername, "OXFW970"); - - err = fwspk_create_pcm(fwspk); - if (err < 0) - goto error; - - err = fwspk_create_mixer(fwspk); - if (err < 0) - goto error; - - err = snd_card_register(card); - if (err < 0) - goto error; - - dev_set_drvdata(unit_dev, fwspk); - - return 0; - -err_connection: - cmp_connection_destroy(&fwspk->connection); -err_unit: - fw_unit_put(fwspk->unit); - mutex_destroy(&fwspk->mutex); -error: - snd_card_free(card); - return err; -} - -static int __devexit fwspk_remove(struct device *dev) -{ - struct fwspk *fwspk = dev_get_drvdata(dev); - - amdtp_out_stream_pcm_abort(&fwspk->stream); - snd_card_disconnect(fwspk->card); - - mutex_lock(&fwspk->mutex); - fwspk_stop_stream(fwspk); - mutex_unlock(&fwspk->mutex); - - snd_card_free_when_closed(fwspk->card); - - return 0; -} - -static void fwspk_bus_reset(struct fw_unit *unit) -{ - struct fwspk *fwspk = dev_get_drvdata(&unit->device); - - fcp_bus_reset(fwspk->unit); - - if (cmp_connection_update(&fwspk->connection) < 0) { - amdtp_out_stream_pcm_abort(&fwspk->stream); - mutex_lock(&fwspk->mutex); - fwspk_stop_stream(fwspk); - mutex_unlock(&fwspk->mutex); - return; - } - - amdtp_out_stream_update(&fwspk->stream); -} - -static const struct ieee1394_device_id fwspk_id_table[] = { - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID | - IEEE1394_MATCH_SPECIFIER_ID | - IEEE1394_MATCH_VERSION, - .vendor_id = VENDOR_GRIFFIN, - .model_id = 0x00f970, - .specifier_id = SPECIFIER_1394TA, - .version = VERSION_AVC, - }, - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID | - IEEE1394_MATCH_SPECIFIER_ID | - IEEE1394_MATCH_VERSION, - .vendor_id = VENDOR_LACIE, - .model_id = 0x00f970, - .specifier_id = SPECIFIER_1394TA, - .version = VERSION_AVC, - }, - { } -}; -MODULE_DEVICE_TABLE(ieee1394, fwspk_id_table); - -static struct fw_driver fwspk_driver = { - .driver = { - .owner = THIS_MODULE, - .name = KBUILD_MODNAME, - .bus = &fw_bus_type, - .probe = fwspk_probe, - .remove = __devexit_p(fwspk_remove), - }, - .update = fwspk_bus_reset, - .id_table = fwspk_id_table, -}; - -static int __init alsa_fwspk_init(void) -{ - return driver_register(&fwspk_driver.driver); -} - -static void __exit alsa_fwspk_exit(void) -{ - driver_unregister(&fwspk_driver.driver); -} - -module_init(alsa_fwspk_init); -module_exit(alsa_fwspk_exit); diff --git a/ANDROID_3.4.5/sound/i2c/Makefile b/ANDROID_3.4.5/sound/i2c/Makefile deleted file mode 100644 index 36879bf8..00000000 --- a/ANDROID_3.4.5/sound/i2c/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-i2c-objs := i2c.o -snd-cs8427-objs := cs8427.o -snd-tea6330t-objs := tea6330t.o - -obj-$(CONFIG_SND) += other/ - -# Toplevel Module Dependency -obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o -obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o -obj-$(CONFIG_SND_ICE1724) += snd-i2c.o diff --git a/ANDROID_3.4.5/sound/i2c/cs8427.c b/ANDROID_3.4.5/sound/i2c/cs8427.c deleted file mode 100644 index 6c2dc386..00000000 --- a/ANDROID_3.4.5/sound/i2c/cs8427.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Routines for control of the CS8427 via i2c bus - * IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include - -static void snd_cs8427_reset(struct snd_i2c_device *cs8427); - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic"); -MODULE_LICENSE("GPL"); - -#define CS8427_ADDR (0x20>>1) /* fixed address */ - -struct cs8427_stream { - struct snd_pcm_substream *substream; - char hw_status[24]; /* hardware status */ - char def_status[24]; /* default status */ - char pcm_status[24]; /* PCM private status */ - char hw_udata[32]; - struct snd_kcontrol *pcm_ctl; -}; - -struct cs8427 { - unsigned char regmap[0x14]; /* map of first 1 + 13 registers */ - unsigned int rate; - unsigned int reset_timeout; - struct cs8427_stream playback; - struct cs8427_stream capture; -}; - -int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg, - unsigned char val) -{ - int err; - unsigned char buf[2]; - - buf[0] = reg & 0x7f; - buf[1] = val; - if ((err = snd_i2c_sendbytes(device, buf, 2)) != 2) { - snd_printk(KERN_ERR "unable to send bytes 0x%02x:0x%02x " - "to CS8427 (%i)\n", buf[0], buf[1], err); - return err < 0 ? err : -EIO; - } - return 0; -} - -EXPORT_SYMBOL(snd_cs8427_reg_write); - -static int snd_cs8427_reg_read(struct snd_i2c_device *device, unsigned char reg) -{ - int err; - unsigned char buf; - - if ((err = snd_i2c_sendbytes(device, ®, 1)) != 1) { - snd_printk(KERN_ERR "unable to send register 0x%x byte " - "to CS8427\n", reg); - return err < 0 ? err : -EIO; - } - if ((err = snd_i2c_readbytes(device, &buf, 1)) != 1) { - snd_printk(KERN_ERR "unable to read register 0x%x byte " - "from CS8427\n", reg); - return err < 0 ? err : -EIO; - } - return buf; -} - -static int snd_cs8427_select_corudata(struct snd_i2c_device *device, int udata) -{ - struct cs8427 *chip = device->private_data; - int err; - - udata = udata ? CS8427_BSEL : 0; - if (udata != (chip->regmap[CS8427_REG_CSDATABUF] & udata)) { - chip->regmap[CS8427_REG_CSDATABUF] &= ~CS8427_BSEL; - chip->regmap[CS8427_REG_CSDATABUF] |= udata; - err = snd_cs8427_reg_write(device, CS8427_REG_CSDATABUF, - chip->regmap[CS8427_REG_CSDATABUF]); - if (err < 0) - return err; - } - return 0; -} - -static int snd_cs8427_send_corudata(struct snd_i2c_device *device, - int udata, - unsigned char *ndata, - int count) -{ - struct cs8427 *chip = device->private_data; - char *hw_data = udata ? - chip->playback.hw_udata : chip->playback.hw_status; - char data[32]; - int err, idx; - - if (!memcmp(hw_data, ndata, count)) - return 0; - if ((err = snd_cs8427_select_corudata(device, udata)) < 0) - return err; - memcpy(hw_data, ndata, count); - if (udata) { - memset(data, 0, sizeof(data)); - if (memcmp(hw_data, data, count) == 0) { - chip->regmap[CS8427_REG_UDATABUF] &= ~CS8427_UBMMASK; - chip->regmap[CS8427_REG_UDATABUF] |= CS8427_UBMZEROS | - CS8427_EFTUI; - err = snd_cs8427_reg_write(device, CS8427_REG_UDATABUF, - chip->regmap[CS8427_REG_UDATABUF]); - return err < 0 ? err : 0; - } - } - data[0] = CS8427_REG_AUTOINC | CS8427_REG_CORU_DATABUF; - for (idx = 0; idx < count; idx++) - data[idx + 1] = bitrev8(ndata[idx]); - if (snd_i2c_sendbytes(device, data, count + 1) != count + 1) - return -EIO; - return 1; -} - -static void snd_cs8427_free(struct snd_i2c_device *device) -{ - kfree(device->private_data); -} - -int snd_cs8427_create(struct snd_i2c_bus *bus, - unsigned char addr, - unsigned int reset_timeout, - struct snd_i2c_device **r_cs8427) -{ - static unsigned char initvals1[] = { - CS8427_REG_CONTROL1 | CS8427_REG_AUTOINC, - /* CS8427_REG_CONTROL1: RMCK to OMCK, valid PCM audio, disable mutes, - TCBL=output */ - CS8427_SWCLK | CS8427_TCBLDIR, - /* CS8427_REG_CONTROL2: hold last valid audio sample, RMCK=256*Fs, - normal stereo operation */ - 0x00, - /* CS8427_REG_DATAFLOW: output drivers normal operation, Tx<=serial, - Rx=>serial */ - CS8427_TXDSERIAL | CS8427_SPDAES3RECEIVER, - /* CS8427_REG_CLOCKSOURCE: Run off, CMCK=256*Fs, - output time base = OMCK, input time base = recovered input clock, - recovered input clock source is ILRCK changed to AES3INPUT - (workaround, see snd_cs8427_reset) */ - CS8427_RXDILRCK, - /* CS8427_REG_SERIALINPUT: Serial audio input port data format = I2S, - 24-bit, 64*Fsi */ - CS8427_SIDEL | CS8427_SILRPOL, - /* CS8427_REG_SERIALOUTPUT: Serial audio output port data format - = I2S, 24-bit, 64*Fsi */ - CS8427_SODEL | CS8427_SOLRPOL, - }; - static unsigned char initvals2[] = { - CS8427_REG_RECVERRMASK | CS8427_REG_AUTOINC, - /* CS8427_REG_RECVERRMASK: unmask the input PLL clock, V, confidence, - biphase, parity status bits */ - /* CS8427_UNLOCK | CS8427_V | CS8427_CONF | CS8427_BIP | CS8427_PAR,*/ - 0xff, /* set everything */ - /* CS8427_REG_CSDATABUF: - Registers 32-55 window to CS buffer - Inhibit D->E transfers from overwriting first 5 bytes of CS data. - Inhibit D->E transfers (all) of CS data. - Allow E->F transfer of CS data. - One byte mode; both A/B channels get same written CB data. - A channel info is output to chip's EMPH* pin. */ - CS8427_CBMR | CS8427_DETCI, - /* CS8427_REG_UDATABUF: - Use internal buffer to transmit User (U) data. - Chip's U pin is an output. - Transmit all O's for user data. - Inhibit D->E transfers. - Inhibit E->F transfers. */ - CS8427_UD | CS8427_EFTUI | CS8427_DETUI, - }; - int err; - struct cs8427 *chip; - struct snd_i2c_device *device; - unsigned char buf[24]; - - if ((err = snd_i2c_device_create(bus, "CS8427", - CS8427_ADDR | (addr & 7), - &device)) < 0) - return err; - chip = device->private_data = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - snd_i2c_device_free(device); - return -ENOMEM; - } - device->private_free = snd_cs8427_free; - - snd_i2c_lock(bus); - err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER); - if (err != CS8427_VER8427A) { - /* give second chance */ - snd_printk(KERN_WARNING "invalid CS8427 signature 0x%x: " - "let me try again...\n", err); - err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER); - } - if (err != CS8427_VER8427A) { - snd_i2c_unlock(bus); - snd_printk(KERN_ERR "unable to find CS8427 signature " - "(expected 0x%x, read 0x%x),\n", - CS8427_VER8427A, err); - snd_printk(KERN_ERR " initialization is not completed\n"); - return -EFAULT; - } - /* turn off run bit while making changes to configuration */ - err = snd_cs8427_reg_write(device, CS8427_REG_CLOCKSOURCE, 0x00); - if (err < 0) - goto __fail; - /* send initial values */ - memcpy(chip->regmap + (initvals1[0] & 0x7f), initvals1 + 1, 6); - if ((err = snd_i2c_sendbytes(device, initvals1, 7)) != 7) { - err = err < 0 ? err : -EIO; - goto __fail; - } - /* Turn off CS8427 interrupt stuff that is not used in hardware */ - memset(buf, 0, 7); - /* from address 9 to 15 */ - buf[0] = 9; /* register */ - if ((err = snd_i2c_sendbytes(device, buf, 7)) != 7) - goto __fail; - /* send transfer initialization sequence */ - memcpy(chip->regmap + (initvals2[0] & 0x7f), initvals2 + 1, 3); - if ((err = snd_i2c_sendbytes(device, initvals2, 4)) != 4) { - err = err < 0 ? err : -EIO; - goto __fail; - } - /* write default channel status bytes */ - put_unaligned_le32(SNDRV_PCM_DEFAULT_CON_SPDIF, buf); - memset(buf + 4, 0, 24 - 4); - if (snd_cs8427_send_corudata(device, 0, buf, 24) < 0) - goto __fail; - memcpy(chip->playback.def_status, buf, 24); - memcpy(chip->playback.pcm_status, buf, 24); - snd_i2c_unlock(bus); - - /* turn on run bit and rock'n'roll */ - if (reset_timeout < 1) - reset_timeout = 1; - chip->reset_timeout = reset_timeout; - snd_cs8427_reset(device); - -#if 0 // it's nice for read tests - { - char buf[128]; - int xx; - buf[0] = 0x81; - snd_i2c_sendbytes(device, buf, 1); - snd_i2c_readbytes(device, buf, 127); - for (xx = 0; xx < 127; xx++) - printk(KERN_DEBUG "reg[0x%x] = 0x%x\n", xx+1, buf[xx]); - } -#endif - - if (r_cs8427) - *r_cs8427 = device; - return 0; - - __fail: - snd_i2c_unlock(bus); - snd_i2c_device_free(device); - return err < 0 ? err : -EIO; -} - -EXPORT_SYMBOL(snd_cs8427_create); - -/* - * Reset the chip using run bit, also lock PLL using ILRCK and - * put back AES3INPUT. This workaround is described in latest - * CS8427 datasheet, otherwise TXDSERIAL will not work. - */ -static void snd_cs8427_reset(struct snd_i2c_device *cs8427) -{ - struct cs8427 *chip; - unsigned long end_time; - int data, aes3input = 0; - - if (snd_BUG_ON(!cs8427)) - return; - chip = cs8427->private_data; - snd_i2c_lock(cs8427->bus); - if ((chip->regmap[CS8427_REG_CLOCKSOURCE] & CS8427_RXDAES3INPUT) == - CS8427_RXDAES3INPUT) /* AES3 bit is set */ - aes3input = 1; - chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~(CS8427_RUN | CS8427_RXDMASK); - snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, - chip->regmap[CS8427_REG_CLOCKSOURCE]); - udelay(200); - chip->regmap[CS8427_REG_CLOCKSOURCE] |= CS8427_RUN | CS8427_RXDILRCK; - snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, - chip->regmap[CS8427_REG_CLOCKSOURCE]); - udelay(200); - snd_i2c_unlock(cs8427->bus); - end_time = jiffies + chip->reset_timeout; - while (time_after_eq(end_time, jiffies)) { - snd_i2c_lock(cs8427->bus); - data = snd_cs8427_reg_read(cs8427, CS8427_REG_RECVERRORS); - snd_i2c_unlock(cs8427->bus); - if (!(data & CS8427_UNLOCK)) - break; - schedule_timeout_uninterruptible(1); - } - snd_i2c_lock(cs8427->bus); - chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~CS8427_RXDMASK; - if (aes3input) - chip->regmap[CS8427_REG_CLOCKSOURCE] |= CS8427_RXDAES3INPUT; - snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, - chip->regmap[CS8427_REG_CLOCKSOURCE]); - snd_i2c_unlock(cs8427->bus); -} - -static int snd_cs8427_in_status_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_cs8427_in_status_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol); - int data; - - snd_i2c_lock(device->bus); - data = snd_cs8427_reg_read(device, kcontrol->private_value); - snd_i2c_unlock(device->bus); - if (data < 0) - return data; - ucontrol->value.integer.value[0] = data; - return 0; -} - -static int snd_cs8427_qsubcode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = 10; - return 0; -} - -static int snd_cs8427_qsubcode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol); - unsigned char reg = CS8427_REG_QSUBCODE; - int err; - - snd_i2c_lock(device->bus); - if ((err = snd_i2c_sendbytes(device, ®, 1)) != 1) { - snd_printk(KERN_ERR "unable to send register 0x%x byte " - "to CS8427\n", reg); - snd_i2c_unlock(device->bus); - return err < 0 ? err : -EIO; - } - err = snd_i2c_readbytes(device, ucontrol->value.bytes.data, 10); - if (err != 10) { - snd_printk(KERN_ERR "unable to read Q-subcode bytes " - "from CS8427\n"); - snd_i2c_unlock(device->bus); - return err < 0 ? err : -EIO; - } - snd_i2c_unlock(device->bus); - return 0; -} - -static int snd_cs8427_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_cs8427_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol); - struct cs8427 *chip = device->private_data; - - snd_i2c_lock(device->bus); - memcpy(ucontrol->value.iec958.status, chip->playback.def_status, 24); - snd_i2c_unlock(device->bus); - return 0; -} - -static int snd_cs8427_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol); - struct cs8427 *chip = device->private_data; - unsigned char *status = kcontrol->private_value ? - chip->playback.pcm_status : chip->playback.def_status; - struct snd_pcm_runtime *runtime = chip->playback.substream ? - chip->playback.substream->runtime : NULL; - int err, change; - - snd_i2c_lock(device->bus); - change = memcmp(ucontrol->value.iec958.status, status, 24) != 0; - memcpy(status, ucontrol->value.iec958.status, 24); - if (change && (kcontrol->private_value ? - runtime != NULL : runtime == NULL)) { - err = snd_cs8427_send_corudata(device, 0, status, 24); - if (err < 0) - change = err; - } - snd_i2c_unlock(device->bus); - return change; -} - -static int snd_cs8427_spdif_mask_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_cs8427_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - memset(ucontrol->value.iec958.status, 0xff, 24); - return 0; -} - -static struct snd_kcontrol_new snd_cs8427_iec958_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .info = snd_cs8427_in_status_info, - .name = "IEC958 CS8427 Input Status", - .access = (SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE), - .get = snd_cs8427_in_status_get, - .private_value = 15, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .info = snd_cs8427_in_status_info, - .name = "IEC958 CS8427 Error Status", - .access = (SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE), - .get = snd_cs8427_in_status_get, - .private_value = 16, -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .info = snd_cs8427_spdif_mask_info, - .get = snd_cs8427_spdif_mask_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_cs8427_spdif_info, - .get = snd_cs8427_spdif_get, - .put = snd_cs8427_spdif_put, - .private_value = 0 -}, -{ - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_INACTIVE), - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_cs8427_spdif_info, - .get = snd_cs8427_spdif_get, - .put = snd_cs8427_spdif_put, - .private_value = 1 -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .info = snd_cs8427_qsubcode_info, - .name = "IEC958 Q-subcode Capture Default", - .access = (SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE), - .get = snd_cs8427_qsubcode_get -}}; - -int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427, - struct snd_pcm_substream *play_substream, - struct snd_pcm_substream *cap_substream) -{ - struct cs8427 *chip = cs8427->private_data; - struct snd_kcontrol *kctl; - unsigned int idx; - int err; - - if (snd_BUG_ON(!play_substream || !cap_substream)) - return -EINVAL; - for (idx = 0; idx < ARRAY_SIZE(snd_cs8427_iec958_controls); idx++) { - kctl = snd_ctl_new1(&snd_cs8427_iec958_controls[idx], cs8427); - if (kctl == NULL) - return -ENOMEM; - kctl->id.device = play_substream->pcm->device; - kctl->id.subdevice = play_substream->number; - err = snd_ctl_add(cs8427->bus->card, kctl); - if (err < 0) - return err; - if (! strcmp(kctl->id.name, - SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM))) - chip->playback.pcm_ctl = kctl; - } - - chip->playback.substream = play_substream; - chip->capture.substream = cap_substream; - if (snd_BUG_ON(!chip->playback.pcm_ctl)) - return -EIO; - return 0; -} - -EXPORT_SYMBOL(snd_cs8427_iec958_build); - -int snd_cs8427_iec958_active(struct snd_i2c_device *cs8427, int active) -{ - struct cs8427 *chip; - - if (snd_BUG_ON(!cs8427)) - return -ENXIO; - chip = cs8427->private_data; - if (active) - memcpy(chip->playback.pcm_status, - chip->playback.def_status, 24); - chip->playback.pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(cs8427->bus->card, - SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, - &chip->playback.pcm_ctl->id); - return 0; -} - -EXPORT_SYMBOL(snd_cs8427_iec958_active); - -int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate) -{ - struct cs8427 *chip; - char *status; - int err, reset; - - if (snd_BUG_ON(!cs8427)) - return -ENXIO; - chip = cs8427->private_data; - status = chip->playback.pcm_status; - snd_i2c_lock(cs8427->bus); - if (status[0] & IEC958_AES0_PROFESSIONAL) { - status[0] &= ~IEC958_AES0_PRO_FS; - switch (rate) { - case 32000: status[0] |= IEC958_AES0_PRO_FS_32000; break; - case 44100: status[0] |= IEC958_AES0_PRO_FS_44100; break; - case 48000: status[0] |= IEC958_AES0_PRO_FS_48000; break; - default: status[0] |= IEC958_AES0_PRO_FS_NOTID; break; - } - } else { - status[3] &= ~IEC958_AES3_CON_FS; - switch (rate) { - case 32000: status[3] |= IEC958_AES3_CON_FS_32000; break; - case 44100: status[3] |= IEC958_AES3_CON_FS_44100; break; - case 48000: status[3] |= IEC958_AES3_CON_FS_48000; break; - } - } - err = snd_cs8427_send_corudata(cs8427, 0, status, 24); - if (err > 0) - snd_ctl_notify(cs8427->bus->card, - SNDRV_CTL_EVENT_MASK_VALUE, - &chip->playback.pcm_ctl->id); - reset = chip->rate != rate; - chip->rate = rate; - snd_i2c_unlock(cs8427->bus); - if (reset) - snd_cs8427_reset(cs8427); - return err < 0 ? err : 0; -} - -EXPORT_SYMBOL(snd_cs8427_iec958_pcm); - -static int __init alsa_cs8427_module_init(void) -{ - return 0; -} - -static void __exit alsa_cs8427_module_exit(void) -{ -} - -module_init(alsa_cs8427_module_init) -module_exit(alsa_cs8427_module_exit) diff --git a/ANDROID_3.4.5/sound/i2c/i2c.c b/ANDROID_3.4.5/sound/i2c/i2c.c deleted file mode 100644 index 4677037f..00000000 --- a/ANDROID_3.4.5/sound/i2c/i2c.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Generic i2c interface for ALSA - * - * (c) 1998 Gerd Knorr - * Modified for the ALSA driver by Jaroslav Kysela - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Generic i2c interface for ALSA"); -MODULE_LICENSE("GPL"); - -static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device, - unsigned char *bytes, int count); -static int snd_i2c_bit_readbytes(struct snd_i2c_device *device, - unsigned char *bytes, int count); -static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, - unsigned short addr); - -static struct snd_i2c_ops snd_i2c_bit_ops = { - .sendbytes = snd_i2c_bit_sendbytes, - .readbytes = snd_i2c_bit_readbytes, - .probeaddr = snd_i2c_bit_probeaddr, -}; - -static int snd_i2c_bus_free(struct snd_i2c_bus *bus) -{ - struct snd_i2c_bus *slave; - struct snd_i2c_device *device; - - if (snd_BUG_ON(!bus)) - return -EINVAL; - while (!list_empty(&bus->devices)) { - device = snd_i2c_device(bus->devices.next); - snd_i2c_device_free(device); - } - if (bus->master) - list_del(&bus->buses); - else { - while (!list_empty(&bus->buses)) { - slave = snd_i2c_slave_bus(bus->buses.next); - snd_device_free(bus->card, slave); - } - } - if (bus->private_free) - bus->private_free(bus); - kfree(bus); - return 0; -} - -static int snd_i2c_bus_dev_free(struct snd_device *device) -{ - struct snd_i2c_bus *bus = device->device_data; - return snd_i2c_bus_free(bus); -} - -int snd_i2c_bus_create(struct snd_card *card, const char *name, - struct snd_i2c_bus *master, struct snd_i2c_bus **ri2c) -{ - struct snd_i2c_bus *bus; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_i2c_bus_dev_free, - }; - - *ri2c = NULL; - bus = kzalloc(sizeof(*bus), GFP_KERNEL); - if (bus == NULL) - return -ENOMEM; - mutex_init(&bus->lock_mutex); - INIT_LIST_HEAD(&bus->devices); - INIT_LIST_HEAD(&bus->buses); - bus->card = card; - bus->ops = &snd_i2c_bit_ops; - if (master) { - list_add_tail(&bus->buses, &master->buses); - bus->master = master; - } - strlcpy(bus->name, name, sizeof(bus->name)); - err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops); - if (err < 0) { - snd_i2c_bus_free(bus); - return err; - } - *ri2c = bus; - return 0; -} - -EXPORT_SYMBOL(snd_i2c_bus_create); - -int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, - unsigned char addr, struct snd_i2c_device **rdevice) -{ - struct snd_i2c_device *device; - - *rdevice = NULL; - if (snd_BUG_ON(!bus)) - return -EINVAL; - device = kzalloc(sizeof(*device), GFP_KERNEL); - if (device == NULL) - return -ENOMEM; - device->addr = addr; - strlcpy(device->name, name, sizeof(device->name)); - list_add_tail(&device->list, &bus->devices); - device->bus = bus; - *rdevice = device; - return 0; -} - -EXPORT_SYMBOL(snd_i2c_device_create); - -int snd_i2c_device_free(struct snd_i2c_device *device) -{ - if (device->bus) - list_del(&device->list); - if (device->private_free) - device->private_free(device); - kfree(device); - return 0; -} - -EXPORT_SYMBOL(snd_i2c_device_free); - -int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) -{ - return device->bus->ops->sendbytes(device, bytes, count); -} - -EXPORT_SYMBOL(snd_i2c_sendbytes); - -int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) -{ - return device->bus->ops->readbytes(device, bytes, count); -} - -EXPORT_SYMBOL(snd_i2c_readbytes); - -int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) -{ - return bus->ops->probeaddr(bus, addr); -} - -EXPORT_SYMBOL(snd_i2c_probeaddr); - -/* - * bit-operations - */ - -static inline void snd_i2c_bit_hw_start(struct snd_i2c_bus *bus) -{ - if (bus->hw_ops.bit->start) - bus->hw_ops.bit->start(bus); -} - -static inline void snd_i2c_bit_hw_stop(struct snd_i2c_bus *bus) -{ - if (bus->hw_ops.bit->stop) - bus->hw_ops.bit->stop(bus); -} - -static void snd_i2c_bit_direction(struct snd_i2c_bus *bus, int clock, int data) -{ - if (bus->hw_ops.bit->direction) - bus->hw_ops.bit->direction(bus, clock, data); -} - -static void snd_i2c_bit_set(struct snd_i2c_bus *bus, int clock, int data) -{ - bus->hw_ops.bit->setlines(bus, clock, data); -} - -#if 0 -static int snd_i2c_bit_clock(struct snd_i2c_bus *bus) -{ - if (bus->hw_ops.bit->getclock) - return bus->hw_ops.bit->getclock(bus); - return -ENXIO; -} -#endif - -static int snd_i2c_bit_data(struct snd_i2c_bus *bus, int ack) -{ - return bus->hw_ops.bit->getdata(bus, ack); -} - -static void snd_i2c_bit_start(struct snd_i2c_bus *bus) -{ - snd_i2c_bit_hw_start(bus); - snd_i2c_bit_direction(bus, 1, 1); /* SCL - wr, SDA - wr */ - snd_i2c_bit_set(bus, 1, 1); - snd_i2c_bit_set(bus, 1, 0); - snd_i2c_bit_set(bus, 0, 0); -} - -static void snd_i2c_bit_stop(struct snd_i2c_bus *bus) -{ - snd_i2c_bit_set(bus, 0, 0); - snd_i2c_bit_set(bus, 1, 0); - snd_i2c_bit_set(bus, 1, 1); - snd_i2c_bit_hw_stop(bus); -} - -static void snd_i2c_bit_send(struct snd_i2c_bus *bus, int data) -{ - snd_i2c_bit_set(bus, 0, data); - snd_i2c_bit_set(bus, 1, data); - snd_i2c_bit_set(bus, 0, data); -} - -static int snd_i2c_bit_ack(struct snd_i2c_bus *bus) -{ - int ack; - - snd_i2c_bit_set(bus, 0, 1); - snd_i2c_bit_set(bus, 1, 1); - snd_i2c_bit_direction(bus, 1, 0); /* SCL - wr, SDA - rd */ - ack = snd_i2c_bit_data(bus, 1); - snd_i2c_bit_direction(bus, 1, 1); /* SCL - wr, SDA - wr */ - snd_i2c_bit_set(bus, 0, 1); - return ack ? -EIO : 0; -} - -static int snd_i2c_bit_sendbyte(struct snd_i2c_bus *bus, unsigned char data) -{ - int i, err; - - for (i = 7; i >= 0; i--) - snd_i2c_bit_send(bus, !!(data & (1 << i))); - err = snd_i2c_bit_ack(bus); - if (err < 0) - return err; - return 0; -} - -static int snd_i2c_bit_readbyte(struct snd_i2c_bus *bus, int last) -{ - int i; - unsigned char data = 0; - - snd_i2c_bit_set(bus, 0, 1); - snd_i2c_bit_direction(bus, 1, 0); /* SCL - wr, SDA - rd */ - for (i = 7; i >= 0; i--) { - snd_i2c_bit_set(bus, 1, 1); - if (snd_i2c_bit_data(bus, 0)) - data |= (1 << i); - snd_i2c_bit_set(bus, 0, 1); - } - snd_i2c_bit_direction(bus, 1, 1); /* SCL - wr, SDA - wr */ - snd_i2c_bit_send(bus, !!last); - return data; -} - -static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device, - unsigned char *bytes, int count) -{ - struct snd_i2c_bus *bus = device->bus; - int err, res = 0; - - if (device->flags & SND_I2C_DEVICE_ADDRTEN) - return -EIO; /* not yet implemented */ - snd_i2c_bit_start(bus); - err = snd_i2c_bit_sendbyte(bus, device->addr << 1); - if (err < 0) { - snd_i2c_bit_hw_stop(bus); - return err; - } - while (count-- > 0) { - err = snd_i2c_bit_sendbyte(bus, *bytes++); - if (err < 0) { - snd_i2c_bit_hw_stop(bus); - return err; - } - res++; - } - snd_i2c_bit_stop(bus); - return res; -} - -static int snd_i2c_bit_readbytes(struct snd_i2c_device *device, - unsigned char *bytes, int count) -{ - struct snd_i2c_bus *bus = device->bus; - int err, res = 0; - - if (device->flags & SND_I2C_DEVICE_ADDRTEN) - return -EIO; /* not yet implemented */ - snd_i2c_bit_start(bus); - err = snd_i2c_bit_sendbyte(bus, (device->addr << 1) | 1); - if (err < 0) { - snd_i2c_bit_hw_stop(bus); - return err; - } - while (count-- > 0) { - err = snd_i2c_bit_readbyte(bus, count == 0); - if (err < 0) { - snd_i2c_bit_hw_stop(bus); - return err; - } - *bytes++ = (unsigned char)err; - res++; - } - snd_i2c_bit_stop(bus); - return res; -} - -static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) -{ - int err; - - if (addr & 0x8000) /* 10-bit address */ - return -EIO; /* not yet implemented */ - if (addr & 0x7f80) /* invalid address */ - return -EINVAL; - snd_i2c_bit_start(bus); - err = snd_i2c_bit_sendbyte(bus, addr << 1); - snd_i2c_bit_stop(bus); - return err; -} - - -static int __init alsa_i2c_init(void) -{ - return 0; -} - -static void __exit alsa_i2c_exit(void) -{ -} - -module_init(alsa_i2c_init) -module_exit(alsa_i2c_exit) diff --git a/ANDROID_3.4.5/sound/i2c/other/Makefile b/ANDROID_3.4.5/sound/i2c/other/Makefile deleted file mode 100644 index c95d8f1a..00000000 --- a/ANDROID_3.4.5/sound/i2c/other/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2003 by Jaroslav Kysela -# - -snd-ak4114-objs := ak4114.o -snd-ak4117-objs := ak4117.o -snd-ak4113-objs := ak4113.o -snd-ak4xxx-adda-objs := ak4xxx-adda.o -snd-pt2258-objs := pt2258.o -snd-tea575x-tuner-objs := tea575x-tuner.o - -# Module Dependency -obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o -obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o -obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o -obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o diff --git a/ANDROID_3.4.5/sound/i2c/other/ak4113.c b/ANDROID_3.4.5/sound/i2c/other/ak4113.c deleted file mode 100644 index dde5c9c9..00000000 --- a/ANDROID_3.4.5/sound/i2c/other/ak4113.c +++ /dev/null @@ -1,639 +0,0 @@ -/* - * Routines for control of the AK4113 via I2C/4-wire serial interface - * IEC958 (S/PDIF) receiver by Asahi Kasei - * Copyright (c) by Jaroslav Kysela - * Copyright (c) by Pavel Hofman - * - * - * 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 - -MODULE_AUTHOR("Pavel Hofman "); -MODULE_DESCRIPTION("AK4113 IEC958 (S/PDIF) receiver by Asahi Kasei"); -MODULE_LICENSE("GPL"); - -#define AK4113_ADDR 0x00 /* fixed address */ - -static void ak4113_stats(struct work_struct *work); -static void ak4113_init_regs(struct ak4113 *chip); - - -static void reg_write(struct ak4113 *ak4113, unsigned char reg, - unsigned char val) -{ - ak4113->write(ak4113->private_data, reg, val); - if (reg < sizeof(ak4113->regmap)) - ak4113->regmap[reg] = val; -} - -static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg) -{ - return ak4113->read(ak4113->private_data, reg); -} - -static void snd_ak4113_free(struct ak4113 *chip) -{ - chip->init = 1; /* don't schedule new work */ - mb(); - cancel_delayed_work_sync(&chip->work); - kfree(chip); -} - -static int snd_ak4113_dev_free(struct snd_device *device) -{ - struct ak4113 *chip = device->device_data; - snd_ak4113_free(chip); - return 0; -} - -int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, - ak4113_write_t *write, const unsigned char *pgm, - void *private_data, struct ak4113 **r_ak4113) -{ - struct ak4113 *chip; - int err = 0; - unsigned char reg; - static struct snd_device_ops ops = { - .dev_free = snd_ak4113_dev_free, - }; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->lock); - chip->card = card; - chip->read = read; - chip->write = write; - chip->private_data = private_data; - INIT_DELAYED_WORK(&chip->work, ak4113_stats); - - for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) - chip->regmap[reg] = pgm[reg]; - ak4113_init_regs(chip); - - chip->rcs0 = reg_read(chip, AK4113_REG_RCS0) & ~(AK4113_QINT | - AK4113_CINT | AK4113_STC); - chip->rcs1 = reg_read(chip, AK4113_REG_RCS1); - chip->rcs2 = reg_read(chip, AK4113_REG_RCS2); - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) - goto __fail; - - if (r_ak4113) - *r_ak4113 = chip; - return 0; - -__fail: - snd_ak4113_free(chip); - return err < 0 ? err : -EIO; -} -EXPORT_SYMBOL_GPL(snd_ak4113_create); - -void snd_ak4113_reg_write(struct ak4113 *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - if (reg >= AK4113_WRITABLE_REGS) - return; - reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); -} -EXPORT_SYMBOL_GPL(snd_ak4113_reg_write); - -static void ak4113_init_regs(struct ak4113 *chip) -{ - unsigned char old = chip->regmap[AK4113_REG_PWRDN], reg; - - /* bring the chip to reset state and powerdown state */ - reg_write(chip, AK4113_REG_PWRDN, old & ~(AK4113_RST|AK4113_PWN)); - udelay(200); - /* release reset, but leave powerdown */ - reg_write(chip, AK4113_REG_PWRDN, (old | AK4113_RST) & ~AK4113_PWN); - udelay(200); - for (reg = 1; reg < AK4113_WRITABLE_REGS; reg++) - reg_write(chip, reg, chip->regmap[reg]); - /* release powerdown, everything is initialized now */ - reg_write(chip, AK4113_REG_PWRDN, old | AK4113_RST | AK4113_PWN); -} - -void snd_ak4113_reinit(struct ak4113 *chip) -{ - chip->init = 1; - mb(); - flush_delayed_work_sync(&chip->work); - ak4113_init_regs(chip); - /* bring up statistics / event queing */ - chip->init = 0; - if (chip->kctls[0]) - schedule_delayed_work(&chip->work, HZ / 10); -} -EXPORT_SYMBOL_GPL(snd_ak4113_reinit); - -static unsigned int external_rate(unsigned char rcs1) -{ - switch (rcs1 & (AK4113_FS0|AK4113_FS1|AK4113_FS2|AK4113_FS3)) { - case AK4113_FS_8000HZ: - return 8000; - case AK4113_FS_11025HZ: - return 11025; - case AK4113_FS_16000HZ: - return 16000; - case AK4113_FS_22050HZ: - return 22050; - case AK4113_FS_24000HZ: - return 24000; - case AK4113_FS_32000HZ: - return 32000; - case AK4113_FS_44100HZ: - return 44100; - case AK4113_FS_48000HZ: - return 48000; - case AK4113_FS_64000HZ: - return 64000; - case AK4113_FS_88200HZ: - return 88200; - case AK4113_FS_96000HZ: - return 96000; - case AK4113_FS_176400HZ: - return 176400; - case AK4113_FS_192000HZ: - return 192000; - default: - return 0; - } -} - -static int snd_ak4113_in_error_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = LONG_MAX; - return 0; -} - -static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - long *ptr; - - spin_lock_irq(&chip->lock); - ptr = (long *)(((char *)chip) + kcontrol->private_value); - ucontrol->value.integer.value[0] = *ptr; - *ptr = 0; - spin_unlock_irq(&chip->lock); - return 0; -} - -#define snd_ak4113_in_bit_info snd_ctl_boolean_mono_info - -static int snd_ak4113_in_bit_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - unsigned char reg = kcontrol->private_value & 0xff; - unsigned char bit = (kcontrol->private_value >> 8) & 0xff; - unsigned char inv = (kcontrol->private_value >> 31) & 1; - - ucontrol->value.integer.value[0] = - ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; - return 0; -} - -static int snd_ak4113_rx_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 5; - return 0; -} - -static int snd_ak4113_rx_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - (AK4113_IPS(chip->regmap[AK4113_REG_IO1])); - return 0; -} - -static int snd_ak4113_rx_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - int change; - u8 old_val; - - spin_lock_irq(&chip->lock); - old_val = chip->regmap[AK4113_REG_IO1]; - change = ucontrol->value.integer.value[0] != AK4113_IPS(old_val); - if (change) - reg_write(chip, AK4113_REG_IO1, - (old_val & (~AK4113_IPS(0xff))) | - (AK4113_IPS(ucontrol->value.integer.value[0]))); - spin_unlock_irq(&chip->lock); - return change; -} - -static int snd_ak4113_rate_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 192000; - return 0; -} - -static int snd_ak4113_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = external_rate(reg_read(chip, - AK4113_REG_RCS1)); - return 0; -} - -static int snd_ak4113_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ak4113_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - unsigned i; - - for (i = 0; i < AK4113_REG_RXCSB_SIZE; i++) - ucontrol->value.iec958.status[i] = reg_read(chip, - AK4113_REG_RXCSB0 + i); - return 0; -} - -static int snd_ak4113_spdif_mask_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ak4113_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - memset(ucontrol->value.iec958.status, 0xff, AK4113_REG_RXCSB_SIZE); - return 0; -} - -static int snd_ak4113_spdif_pinfo(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xffff; - uinfo->count = 4; - return 0; -} - -static int snd_ak4113_spdif_pget(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - unsigned short tmp; - - ucontrol->value.integer.value[0] = 0xf8f2; - ucontrol->value.integer.value[1] = 0x4e1f; - tmp = reg_read(chip, AK4113_REG_Pc0) | - (reg_read(chip, AK4113_REG_Pc1) << 8); - ucontrol->value.integer.value[2] = tmp; - tmp = reg_read(chip, AK4113_REG_Pd0) | - (reg_read(chip, AK4113_REG_Pd1) << 8); - ucontrol->value.integer.value[3] = tmp; - return 0; -} - -static int snd_ak4113_spdif_qinfo(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = AK4113_REG_QSUB_SIZE; - return 0; -} - -static int snd_ak4113_spdif_qget(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - unsigned i; - - for (i = 0; i < AK4113_REG_QSUB_SIZE; i++) - ucontrol->value.bytes.data[i] = reg_read(chip, - AK4113_REG_QSUB_ADDR + i); - return 0; -} - -/* Don't forget to change AK4113_CONTROLS define!!! */ -static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Parity Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_in_error_info, - .get = snd_ak4113_in_error_get, - .private_value = offsetof(struct ak4113, parity_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 V-Bit Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_in_error_info, - .get = snd_ak4113_in_error_get, - .private_value = offsetof(struct ak4113, v_bit_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 C-CRC Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_in_error_info, - .get = snd_ak4113_in_error_get, - .private_value = offsetof(struct ak4113, ccrc_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Q-CRC Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_in_error_info, - .get = snd_ak4113_in_error_get, - .private_value = offsetof(struct ak4113, qcrc_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 External Rate", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_rate_info, - .get = snd_ak4113_rate_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_ak4113_spdif_mask_info, - .get = snd_ak4113_spdif_mask_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_spdif_info, - .get = snd_ak4113_spdif_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Preample Capture Default", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_spdif_pinfo, - .get = snd_ak4113_spdif_pget, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Q-subcode Capture Default", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_spdif_qinfo, - .get = snd_ak4113_spdif_qget, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Audio", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_in_bit_info, - .get = snd_ak4113_in_bit_get, - .private_value = (1<<31) | (1<<8) | AK4113_REG_RCS0, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Non-PCM Bitstream", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_in_bit_info, - .get = snd_ak4113_in_bit_get, - .private_value = (0<<8) | AK4113_REG_RCS1, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 DTS Bitstream", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4113_in_bit_info, - .get = snd_ak4113_in_bit_get, - .private_value = (1<<8) | AK4113_REG_RCS1, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "AK4113 Input Select", - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_WRITE, - .info = snd_ak4113_rx_info, - .get = snd_ak4113_rx_get, - .put = snd_ak4113_rx_put, -} -}; - -static void snd_ak4113_proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct ak4113 *ak4113 = entry->private_data; - int reg, val; - /* all ak4113 registers 0x00 - 0x1c */ - for (reg = 0; reg < 0x1d; reg++) { - val = reg_read(ak4113, reg); - snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); - } -} - -static void snd_ak4113_proc_init(struct ak4113 *ak4113) -{ - struct snd_info_entry *entry; - if (!snd_card_proc_new(ak4113->card, "ak4113", &entry)) - snd_info_set_text_ops(entry, ak4113, snd_ak4113_proc_regs_read); -} - -int snd_ak4113_build(struct ak4113 *ak4113, - struct snd_pcm_substream *cap_substream) -{ - struct snd_kcontrol *kctl; - unsigned int idx; - int err; - - if (snd_BUG_ON(!cap_substream)) - return -EINVAL; - ak4113->substream = cap_substream; - for (idx = 0; idx < AK4113_CONTROLS; idx++) { - kctl = snd_ctl_new1(&snd_ak4113_iec958_controls[idx], ak4113); - if (kctl == NULL) - return -ENOMEM; - kctl->id.device = cap_substream->pcm->device; - kctl->id.subdevice = cap_substream->number; - err = snd_ctl_add(ak4113->card, kctl); - if (err < 0) - return err; - ak4113->kctls[idx] = kctl; - } - snd_ak4113_proc_init(ak4113); - /* trigger workq */ - schedule_delayed_work(&ak4113->work, HZ / 10); - return 0; -} -EXPORT_SYMBOL_GPL(snd_ak4113_build); - -int snd_ak4113_external_rate(struct ak4113 *ak4113) -{ - unsigned char rcs1; - - rcs1 = reg_read(ak4113, AK4113_REG_RCS1); - return external_rate(rcs1); -} -EXPORT_SYMBOL_GPL(snd_ak4113_external_rate); - -int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags) -{ - struct snd_pcm_runtime *runtime = - ak4113->substream ? ak4113->substream->runtime : NULL; - unsigned long _flags; - int res = 0; - unsigned char rcs0, rcs1, rcs2; - unsigned char c0, c1; - - rcs1 = reg_read(ak4113, AK4113_REG_RCS1); - if (flags & AK4113_CHECK_NO_STAT) - goto __rate; - rcs0 = reg_read(ak4113, AK4113_REG_RCS0); - rcs2 = reg_read(ak4113, AK4113_REG_RCS2); - spin_lock_irqsave(&ak4113->lock, _flags); - if (rcs0 & AK4113_PAR) - ak4113->parity_errors++; - if (rcs0 & AK4113_V) - ak4113->v_bit_errors++; - if (rcs2 & AK4113_CCRC) - ak4113->ccrc_errors++; - if (rcs2 & AK4113_QCRC) - ak4113->qcrc_errors++; - c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | - AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ - (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | - AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)); - c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | - AK4113_DAT | 0xf0)) ^ - (rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM | - AK4113_DAT | 0xf0)); - ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC); - ak4113->rcs1 = rcs1; - ak4113->rcs2 = rcs2; - spin_unlock_irqrestore(&ak4113->lock, _flags); - - if (rcs0 & AK4113_PAR) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[0]->id); - if (rcs0 & AK4113_V) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[1]->id); - if (rcs2 & AK4113_CCRC) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[2]->id); - if (rcs2 & AK4113_QCRC) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[3]->id); - - /* rate change */ - if (c1 & 0xf0) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[4]->id); - - if ((c1 & AK4113_PEM) | (c0 & AK4113_CINT)) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[6]->id); - if (c0 & AK4113_QINT) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[8]->id); - - if (c0 & AK4113_AUDION) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[9]->id); - if (c1 & AK4113_NPCM) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[10]->id); - if (c1 & AK4113_DTSCD) - snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4113->kctls[11]->id); - - if (ak4113->change_callback && (c0 | c1) != 0) - ak4113->change_callback(ak4113, c0, c1); - -__rate: - /* compare rate */ - res = external_rate(rcs1); - if (!(flags & AK4113_CHECK_NO_RATE) && runtime && - (runtime->rate != res)) { - snd_pcm_stream_lock_irqsave(ak4113->substream, _flags); - if (snd_pcm_running(ak4113->substream)) { - /*printk(KERN_DEBUG "rate changed (%i <- %i)\n", - * runtime->rate, res); */ - snd_pcm_stop(ak4113->substream, - SNDRV_PCM_STATE_DRAINING); - wake_up(&runtime->sleep); - res = 1; - } - snd_pcm_stream_unlock_irqrestore(ak4113->substream, _flags); - } - return res; -} -EXPORT_SYMBOL_GPL(snd_ak4113_check_rate_and_errors); - -static void ak4113_stats(struct work_struct *work) -{ - struct ak4113 *chip = container_of(work, struct ak4113, work.work); - - if (!chip->init) - snd_ak4113_check_rate_and_errors(chip, chip->check_flags); - - schedule_delayed_work(&chip->work, HZ / 10); -} diff --git a/ANDROID_3.4.5/sound/i2c/other/ak4114.c b/ANDROID_3.4.5/sound/i2c/other/ak4114.c deleted file mode 100644 index fdf3c1b6..00000000 --- a/ANDROID_3.4.5/sound/i2c/other/ak4114.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * Routines for control of the AK4114 via I2C and 4-wire serial interface - * IEC958 (S/PDIF) receiver by Asahi Kasei - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei"); -MODULE_LICENSE("GPL"); - -#define AK4114_ADDR 0x00 /* fixed address */ - -static void ak4114_stats(struct work_struct *work); -static void ak4114_init_regs(struct ak4114 *chip); - -static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val) -{ - ak4114->write(ak4114->private_data, reg, val); - if (reg <= AK4114_REG_INT1_MASK) - ak4114->regmap[reg] = val; - else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) - ak4114->txcsb[reg-AK4114_REG_TXCSB0] = val; -} - -static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg) -{ - return ak4114->read(ak4114->private_data, reg); -} - -#if 0 -static void reg_dump(struct ak4114 *ak4114) -{ - int i; - - printk(KERN_DEBUG "AK4114 REG DUMP:\n"); - for (i = 0; i < 0x20; i++) - printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < sizeof(ak4114->regmap) ? ak4114->regmap[i] : 0); -} -#endif - -static void snd_ak4114_free(struct ak4114 *chip) -{ - chip->init = 1; /* don't schedule new work */ - mb(); - cancel_delayed_work_sync(&chip->work); - kfree(chip); -} - -static int snd_ak4114_dev_free(struct snd_device *device) -{ - struct ak4114 *chip = device->device_data; - snd_ak4114_free(chip); - return 0; -} - -int snd_ak4114_create(struct snd_card *card, - ak4114_read_t *read, ak4114_write_t *write, - const unsigned char pgm[7], const unsigned char txcsb[5], - void *private_data, struct ak4114 **r_ak4114) -{ - struct ak4114 *chip; - int err = 0; - unsigned char reg; - static struct snd_device_ops ops = { - .dev_free = snd_ak4114_dev_free, - }; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->lock); - chip->card = card; - chip->read = read; - chip->write = write; - chip->private_data = private_data; - INIT_DELAYED_WORK(&chip->work, ak4114_stats); - - for (reg = 0; reg < 7; reg++) - chip->regmap[reg] = pgm[reg]; - for (reg = 0; reg < 5; reg++) - chip->txcsb[reg] = txcsb[reg]; - - ak4114_init_regs(chip); - - chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); - chip->rcs1 = reg_read(chip, AK4114_REG_RCS1); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) - goto __fail; - - if (r_ak4114) - *r_ak4114 = chip; - return 0; - - __fail: - snd_ak4114_free(chip); - return err < 0 ? err : -EIO; -} - -void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val) -{ - if (reg <= AK4114_REG_INT1_MASK) - reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); - else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) - reg_write(chip, reg, - (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); -} - -static void ak4114_init_regs(struct ak4114 *chip) -{ - unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg; - - /* bring the chip to reset state and powerdown state */ - reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN)); - udelay(200); - /* release reset, but leave powerdown */ - reg_write(chip, AK4114_REG_PWRDN, (old | AK4114_RST) & ~AK4114_PWN); - udelay(200); - for (reg = 1; reg < 7; reg++) - reg_write(chip, reg, chip->regmap[reg]); - for (reg = 0; reg < 5; reg++) - reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]); - /* release powerdown, everything is initialized now */ - reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); -} - -void snd_ak4114_reinit(struct ak4114 *chip) -{ - chip->init = 1; - mb(); - flush_delayed_work_sync(&chip->work); - ak4114_init_regs(chip); - /* bring up statistics / event queing */ - chip->init = 0; - if (chip->kctls[0]) - schedule_delayed_work(&chip->work, HZ / 10); -} - -static unsigned int external_rate(unsigned char rcs1) -{ - switch (rcs1 & (AK4114_FS0|AK4114_FS1|AK4114_FS2|AK4114_FS3)) { - case AK4114_FS_32000HZ: return 32000; - case AK4114_FS_44100HZ: return 44100; - case AK4114_FS_48000HZ: return 48000; - case AK4114_FS_88200HZ: return 88200; - case AK4114_FS_96000HZ: return 96000; - case AK4114_FS_176400HZ: return 176400; - case AK4114_FS_192000HZ: return 192000; - default: return 0; - } -} - -static int snd_ak4114_in_error_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = LONG_MAX; - return 0; -} - -static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - long *ptr; - - spin_lock_irq(&chip->lock); - ptr = (long *)(((char *)chip) + kcontrol->private_value); - ucontrol->value.integer.value[0] = *ptr; - *ptr = 0; - spin_unlock_irq(&chip->lock); - return 0; -} - -#define snd_ak4114_in_bit_info snd_ctl_boolean_mono_info - -static int snd_ak4114_in_bit_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - unsigned char reg = kcontrol->private_value & 0xff; - unsigned char bit = (kcontrol->private_value >> 8) & 0xff; - unsigned char inv = (kcontrol->private_value >> 31) & 1; - - ucontrol->value.integer.value[0] = ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; - return 0; -} - -static int snd_ak4114_rate_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 192000; - return 0; -} - -static int snd_ak4114_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4114_REG_RCS1)); - return 0; -} - -static int snd_ak4114_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ak4114_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - unsigned i; - - for (i = 0; i < AK4114_REG_RXCSB_SIZE; i++) - ucontrol->value.iec958.status[i] = reg_read(chip, AK4114_REG_RXCSB0 + i); - return 0; -} - -static int snd_ak4114_spdif_playback_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - unsigned i; - - for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++) - ucontrol->value.iec958.status[i] = chip->txcsb[i]; - return 0; -} - -static int snd_ak4114_spdif_playback_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - unsigned i; - - for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++) - reg_write(chip, AK4114_REG_TXCSB0 + i, ucontrol->value.iec958.status[i]); - return 0; -} - -static int snd_ak4114_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ak4114_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - memset(ucontrol->value.iec958.status, 0xff, AK4114_REG_RXCSB_SIZE); - return 0; -} - -static int snd_ak4114_spdif_pinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xffff; - uinfo->count = 4; - return 0; -} - -static int snd_ak4114_spdif_pget(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - unsigned short tmp; - - ucontrol->value.integer.value[0] = 0xf8f2; - ucontrol->value.integer.value[1] = 0x4e1f; - tmp = reg_read(chip, AK4114_REG_Pc0) | (reg_read(chip, AK4114_REG_Pc1) << 8); - ucontrol->value.integer.value[2] = tmp; - tmp = reg_read(chip, AK4114_REG_Pd0) | (reg_read(chip, AK4114_REG_Pd1) << 8); - ucontrol->value.integer.value[3] = tmp; - return 0; -} - -static int snd_ak4114_spdif_qinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = AK4114_REG_QSUB_SIZE; - return 0; -} - -static int snd_ak4114_spdif_qget(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - unsigned i; - - for (i = 0; i < AK4114_REG_QSUB_SIZE; i++) - ucontrol->value.bytes.data[i] = reg_read(chip, AK4114_REG_QSUB_ADDR + i); - return 0; -} - -/* Don't forget to change AK4114_CONTROLS define!!! */ -static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Parity Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_in_error_info, - .get = snd_ak4114_in_error_get, - .private_value = offsetof(struct ak4114, parity_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 V-Bit Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_in_error_info, - .get = snd_ak4114_in_error_get, - .private_value = offsetof(struct ak4114, v_bit_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 C-CRC Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_in_error_info, - .get = snd_ak4114_in_error_get, - .private_value = offsetof(struct ak4114, ccrc_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Q-CRC Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_in_error_info, - .get = snd_ak4114_in_error_get, - .private_value = offsetof(struct ak4114, qcrc_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 External Rate", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_rate_info, - .get = snd_ak4114_rate_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_ak4114_spdif_mask_info, - .get = snd_ak4114_spdif_mask_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_spdif_info, - .get = snd_ak4114_spdif_playback_get, - .put = snd_ak4114_spdif_playback_put, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_ak4114_spdif_mask_info, - .get = snd_ak4114_spdif_mask_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_spdif_info, - .get = snd_ak4114_spdif_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Preample Capture Default", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_spdif_pinfo, - .get = snd_ak4114_spdif_pget, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Q-subcode Capture Default", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_spdif_qinfo, - .get = snd_ak4114_spdif_qget, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Audio", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_in_bit_info, - .get = snd_ak4114_in_bit_get, - .private_value = (1<<31) | (1<<8) | AK4114_REG_RCS0, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Non-PCM Bitstream", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_in_bit_info, - .get = snd_ak4114_in_bit_get, - .private_value = (6<<8) | AK4114_REG_RCS0, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 DTS Bitstream", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_in_bit_info, - .get = snd_ak4114_in_bit_get, - .private_value = (3<<8) | AK4114_REG_RCS0, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 PPL Lock Status", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4114_in_bit_info, - .get = snd_ak4114_in_bit_get, - .private_value = (1<<31) | (4<<8) | AK4114_REG_RCS0, -} -}; - - -static void snd_ak4114_proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct ak4114 *ak4114 = entry->private_data; - int reg, val; - /* all ak4114 registers 0x00 - 0x1f */ - for (reg = 0; reg < 0x20; reg++) { - val = reg_read(ak4114, reg); - snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); - } -} - -static void snd_ak4114_proc_init(struct ak4114 *ak4114) -{ - struct snd_info_entry *entry; - if (!snd_card_proc_new(ak4114->card, "ak4114", &entry)) - snd_info_set_text_ops(entry, ak4114, snd_ak4114_proc_regs_read); -} - -int snd_ak4114_build(struct ak4114 *ak4114, - struct snd_pcm_substream *ply_substream, - struct snd_pcm_substream *cap_substream) -{ - struct snd_kcontrol *kctl; - unsigned int idx; - int err; - - if (snd_BUG_ON(!cap_substream)) - return -EINVAL; - ak4114->playback_substream = ply_substream; - ak4114->capture_substream = cap_substream; - for (idx = 0; idx < AK4114_CONTROLS; idx++) { - kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114); - if (kctl == NULL) - return -ENOMEM; - if (strstr(kctl->id.name, "Playback")) { - if (ply_substream == NULL) { - snd_ctl_free_one(kctl); - ak4114->kctls[idx] = NULL; - continue; - } - kctl->id.device = ply_substream->pcm->device; - kctl->id.subdevice = ply_substream->number; - } else { - kctl->id.device = cap_substream->pcm->device; - kctl->id.subdevice = cap_substream->number; - } - err = snd_ctl_add(ak4114->card, kctl); - if (err < 0) - return err; - ak4114->kctls[idx] = kctl; - } - snd_ak4114_proc_init(ak4114); - /* trigger workq */ - schedule_delayed_work(&ak4114->work, HZ / 10); - return 0; -} - -/* notify kcontrols if any parameters are changed */ -static void ak4114_notify(struct ak4114 *ak4114, - unsigned char rcs0, unsigned char rcs1, - unsigned char c0, unsigned char c1) -{ - if (!ak4114->kctls[0]) - return; - - if (rcs0 & AK4114_PAR) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[0]->id); - if (rcs0 & AK4114_V) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[1]->id); - if (rcs1 & AK4114_CCRC) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[2]->id); - if (rcs1 & AK4114_QCRC) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[3]->id); - - /* rate change */ - if (c1 & 0xf0) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[4]->id); - - if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT)) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[9]->id); - if (c0 & AK4114_QINT) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[10]->id); - - if (c0 & AK4114_AUDION) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[11]->id); - if (c0 & AK4114_AUTO) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[12]->id); - if (c0 & AK4114_DTSCD) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[13]->id); - if (c0 & AK4114_UNLCK) - snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, - &ak4114->kctls[14]->id); -} - -int snd_ak4114_external_rate(struct ak4114 *ak4114) -{ - unsigned char rcs1; - - rcs1 = reg_read(ak4114, AK4114_REG_RCS1); - return external_rate(rcs1); -} - -int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) -{ - struct snd_pcm_runtime *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL; - unsigned long _flags; - int res = 0; - unsigned char rcs0, rcs1; - unsigned char c0, c1; - - rcs1 = reg_read(ak4114, AK4114_REG_RCS1); - if (flags & AK4114_CHECK_NO_STAT) - goto __rate; - rcs0 = reg_read(ak4114, AK4114_REG_RCS0); - spin_lock_irqsave(&ak4114->lock, _flags); - if (rcs0 & AK4114_PAR) - ak4114->parity_errors++; - if (rcs1 & AK4114_V) - ak4114->v_bit_errors++; - if (rcs1 & AK4114_CCRC) - ak4114->ccrc_errors++; - if (rcs1 & AK4114_QCRC) - ak4114->qcrc_errors++; - c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^ - (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)); - c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0); - ak4114->rcs0 = rcs0 & ~(AK4114_QINT | AK4114_CINT); - ak4114->rcs1 = rcs1; - spin_unlock_irqrestore(&ak4114->lock, _flags); - - ak4114_notify(ak4114, rcs0, rcs1, c0, c1); - if (ak4114->change_callback && (c0 | c1) != 0) - ak4114->change_callback(ak4114, c0, c1); - - __rate: - /* compare rate */ - res = external_rate(rcs1); - if (!(flags & AK4114_CHECK_NO_RATE) && runtime && runtime->rate != res) { - snd_pcm_stream_lock_irqsave(ak4114->capture_substream, _flags); - if (snd_pcm_running(ak4114->capture_substream)) { - // printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res); - snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); - res = 1; - } - snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags); - } - return res; -} - -static void ak4114_stats(struct work_struct *work) -{ - struct ak4114 *chip = container_of(work, struct ak4114, work.work); - - if (!chip->init) - snd_ak4114_check_rate_and_errors(chip, chip->check_flags); - - schedule_delayed_work(&chip->work, HZ / 10); -} - -EXPORT_SYMBOL(snd_ak4114_create); -EXPORT_SYMBOL(snd_ak4114_reg_write); -EXPORT_SYMBOL(snd_ak4114_reinit); -EXPORT_SYMBOL(snd_ak4114_build); -EXPORT_SYMBOL(snd_ak4114_external_rate); -EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors); diff --git a/ANDROID_3.4.5/sound/i2c/other/ak4117.c b/ANDROID_3.4.5/sound/i2c/other/ak4117.c deleted file mode 100644 index b4b2a51f..00000000 --- a/ANDROID_3.4.5/sound/i2c/other/ak4117.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Routines for control of the AK4117 via 4-wire serial interface - * IEC958 (S/PDIF) receiver by Asahi Kasei - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("AK4117 IEC958 (S/PDIF) receiver by Asahi Kasei"); -MODULE_LICENSE("GPL"); - -#define AK4117_ADDR 0x00 /* fixed address */ - -static void snd_ak4117_timer(unsigned long data); - -static void reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char val) -{ - ak4117->write(ak4117->private_data, reg, val); - if (reg < sizeof(ak4117->regmap)) - ak4117->regmap[reg] = val; -} - -static inline unsigned char reg_read(struct ak4117 *ak4117, unsigned char reg) -{ - return ak4117->read(ak4117->private_data, reg); -} - -#if 0 -static void reg_dump(struct ak4117 *ak4117) -{ - int i; - - printk(KERN_DEBUG "AK4117 REG DUMP:\n"); - for (i = 0; i < 0x1b; i++) - printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4117, i), i < sizeof(ak4117->regmap) ? ak4117->regmap[i] : 0); -} -#endif - -static void snd_ak4117_free(struct ak4117 *chip) -{ - del_timer(&chip->timer); - kfree(chip); -} - -static int snd_ak4117_dev_free(struct snd_device *device) -{ - struct ak4117 *chip = device->device_data; - snd_ak4117_free(chip); - return 0; -} - -int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write, - const unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117) -{ - struct ak4117 *chip; - int err = 0; - unsigned char reg; - static struct snd_device_ops ops = { - .dev_free = snd_ak4117_dev_free, - }; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->lock); - chip->card = card; - chip->read = read; - chip->write = write; - chip->private_data = private_data; - init_timer(&chip->timer); - chip->timer.data = (unsigned long)chip; - chip->timer.function = snd_ak4117_timer; - - for (reg = 0; reg < 5; reg++) - chip->regmap[reg] = pgm[reg]; - snd_ak4117_reinit(chip); - - chip->rcs0 = reg_read(chip, AK4117_REG_RCS0) & ~(AK4117_QINT | AK4117_CINT | AK4117_STC); - chip->rcs1 = reg_read(chip, AK4117_REG_RCS1); - chip->rcs2 = reg_read(chip, AK4117_REG_RCS2); - - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops)) < 0) - goto __fail; - - if (r_ak4117) - *r_ak4117 = chip; - return 0; - - __fail: - snd_ak4117_free(chip); - return err < 0 ? err : -EIO; -} - -void snd_ak4117_reg_write(struct ak4117 *chip, unsigned char reg, unsigned char mask, unsigned char val) -{ - if (reg >= 5) - return; - reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); -} - -void snd_ak4117_reinit(struct ak4117 *chip) -{ - unsigned char old = chip->regmap[AK4117_REG_PWRDN], reg; - - del_timer(&chip->timer); - chip->init = 1; - /* bring the chip to reset state and powerdown state */ - reg_write(chip, AK4117_REG_PWRDN, 0); - udelay(200); - /* release reset, but leave powerdown */ - reg_write(chip, AK4117_REG_PWRDN, (old | AK4117_RST) & ~AK4117_PWN); - udelay(200); - for (reg = 1; reg < 5; reg++) - reg_write(chip, reg, chip->regmap[reg]); - /* release powerdown, everything is initialized now */ - reg_write(chip, AK4117_REG_PWRDN, old | AK4117_RST | AK4117_PWN); - chip->init = 0; - chip->timer.expires = 1 + jiffies; - add_timer(&chip->timer); -} - -static unsigned int external_rate(unsigned char rcs1) -{ - switch (rcs1 & (AK4117_FS0|AK4117_FS1|AK4117_FS2|AK4117_FS3)) { - case AK4117_FS_32000HZ: return 32000; - case AK4117_FS_44100HZ: return 44100; - case AK4117_FS_48000HZ: return 48000; - case AK4117_FS_88200HZ: return 88200; - case AK4117_FS_96000HZ: return 96000; - case AK4117_FS_176400HZ: return 176400; - case AK4117_FS_192000HZ: return 192000; - default: return 0; - } -} - -static int snd_ak4117_in_error_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = LONG_MAX; - return 0; -} - -static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - long *ptr; - - spin_lock_irq(&chip->lock); - ptr = (long *)(((char *)chip) + kcontrol->private_value); - ucontrol->value.integer.value[0] = *ptr; - *ptr = 0; - spin_unlock_irq(&chip->lock); - return 0; -} - -#define snd_ak4117_in_bit_info snd_ctl_boolean_mono_info - -static int snd_ak4117_in_bit_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - unsigned char reg = kcontrol->private_value & 0xff; - unsigned char bit = (kcontrol->private_value >> 8) & 0xff; - unsigned char inv = (kcontrol->private_value >> 31) & 1; - - ucontrol->value.integer.value[0] = ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv; - return 0; -} - -static int snd_ak4117_rx_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_ak4117_rx_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = (chip->regmap[AK4117_REG_IO] & AK4117_IPS) ? 1 : 0; - return 0; -} - -static int snd_ak4117_rx_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - int change; - u8 old_val; - - spin_lock_irq(&chip->lock); - old_val = chip->regmap[AK4117_REG_IO]; - change = !!ucontrol->value.integer.value[0] != ((old_val & AK4117_IPS) ? 1 : 0); - if (change) - reg_write(chip, AK4117_REG_IO, (old_val & ~AK4117_IPS) | (ucontrol->value.integer.value[0] ? AK4117_IPS : 0)); - spin_unlock_irq(&chip->lock); - return change; -} - -static int snd_ak4117_rate_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 192000; - return 0; -} - -static int snd_ak4117_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4117_REG_RCS1)); - return 0; -} - -static int snd_ak4117_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ak4117_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - unsigned i; - - for (i = 0; i < AK4117_REG_RXCSB_SIZE; i++) - ucontrol->value.iec958.status[i] = reg_read(chip, AK4117_REG_RXCSB0 + i); - return 0; -} - -static int snd_ak4117_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ak4117_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - memset(ucontrol->value.iec958.status, 0xff, AK4117_REG_RXCSB_SIZE); - return 0; -} - -static int snd_ak4117_spdif_pinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xffff; - uinfo->count = 4; - return 0; -} - -static int snd_ak4117_spdif_pget(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - unsigned short tmp; - - ucontrol->value.integer.value[0] = 0xf8f2; - ucontrol->value.integer.value[1] = 0x4e1f; - tmp = reg_read(chip, AK4117_REG_Pc0) | (reg_read(chip, AK4117_REG_Pc1) << 8); - ucontrol->value.integer.value[2] = tmp; - tmp = reg_read(chip, AK4117_REG_Pd0) | (reg_read(chip, AK4117_REG_Pd1) << 8); - ucontrol->value.integer.value[3] = tmp; - return 0; -} - -static int snd_ak4117_spdif_qinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = AK4117_REG_QSUB_SIZE; - return 0; -} - -static int snd_ak4117_spdif_qget(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - unsigned i; - - for (i = 0; i < AK4117_REG_QSUB_SIZE; i++) - ucontrol->value.bytes.data[i] = reg_read(chip, AK4117_REG_QSUB_ADDR + i); - return 0; -} - -/* Don't forget to change AK4117_CONTROLS define!!! */ -static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Parity Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_in_error_info, - .get = snd_ak4117_in_error_get, - .private_value = offsetof(struct ak4117, parity_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 V-Bit Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_in_error_info, - .get = snd_ak4117_in_error_get, - .private_value = offsetof(struct ak4117, v_bit_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 C-CRC Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_in_error_info, - .get = snd_ak4117_in_error_get, - .private_value = offsetof(struct ak4117, ccrc_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Q-CRC Errors", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_in_error_info, - .get = snd_ak4117_in_error_get, - .private_value = offsetof(struct ak4117, qcrc_errors), -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 External Rate", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_rate_info, - .get = snd_ak4117_rate_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_ak4117_spdif_mask_info, - .get = snd_ak4117_spdif_mask_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_spdif_info, - .get = snd_ak4117_spdif_get, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Preample Capture Default", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_spdif_pinfo, - .get = snd_ak4117_spdif_pget, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Q-subcode Capture Default", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_spdif_qinfo, - .get = snd_ak4117_spdif_qget, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Audio", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_in_bit_info, - .get = snd_ak4117_in_bit_get, - .private_value = (1<<31) | (3<<8) | AK4117_REG_RCS0, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Non-PCM Bitstream", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_in_bit_info, - .get = snd_ak4117_in_bit_get, - .private_value = (5<<8) | AK4117_REG_RCS1, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 DTS Bitstream", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ak4117_in_bit_info, - .get = snd_ak4117_in_bit_get, - .private_value = (6<<8) | AK4117_REG_RCS1, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "AK4117 Input Select", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, - .info = snd_ak4117_rx_info, - .get = snd_ak4117_rx_get, - .put = snd_ak4117_rx_put, -} -}; - -int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *cap_substream) -{ - struct snd_kcontrol *kctl; - unsigned int idx; - int err; - - if (snd_BUG_ON(!cap_substream)) - return -EINVAL; - ak4117->substream = cap_substream; - for (idx = 0; idx < AK4117_CONTROLS; idx++) { - kctl = snd_ctl_new1(&snd_ak4117_iec958_controls[idx], ak4117); - if (kctl == NULL) - return -ENOMEM; - kctl->id.device = cap_substream->pcm->device; - kctl->id.subdevice = cap_substream->number; - err = snd_ctl_add(ak4117->card, kctl); - if (err < 0) - return err; - ak4117->kctls[idx] = kctl; - } - return 0; -} - -int snd_ak4117_external_rate(struct ak4117 *ak4117) -{ - unsigned char rcs1; - - rcs1 = reg_read(ak4117, AK4117_REG_RCS1); - return external_rate(rcs1); -} - -int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags) -{ - struct snd_pcm_runtime *runtime = ak4117->substream ? ak4117->substream->runtime : NULL; - unsigned long _flags; - int res = 0; - unsigned char rcs0, rcs1, rcs2; - unsigned char c0, c1; - - rcs1 = reg_read(ak4117, AK4117_REG_RCS1); - if (flags & AK4117_CHECK_NO_STAT) - goto __rate; - rcs0 = reg_read(ak4117, AK4117_REG_RCS0); - rcs2 = reg_read(ak4117, AK4117_REG_RCS2); - // printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2); - spin_lock_irqsave(&ak4117->lock, _flags); - if (rcs0 & AK4117_PAR) - ak4117->parity_errors++; - if (rcs0 & AK4117_V) - ak4117->v_bit_errors++; - if (rcs2 & AK4117_CCRC) - ak4117->ccrc_errors++; - if (rcs2 & AK4117_QCRC) - ak4117->qcrc_errors++; - c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^ - (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)); - c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^ - (rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)); - ak4117->rcs0 = rcs0 & ~(AK4117_QINT | AK4117_CINT | AK4117_STC); - ak4117->rcs1 = rcs1; - ak4117->rcs2 = rcs2; - spin_unlock_irqrestore(&ak4117->lock, _flags); - - if (rcs0 & AK4117_PAR) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[0]->id); - if (rcs0 & AK4117_V) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[1]->id); - if (rcs2 & AK4117_CCRC) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[2]->id); - if (rcs2 & AK4117_QCRC) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[3]->id); - - /* rate change */ - if (c1 & 0x0f) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[4]->id); - - if ((c1 & AK4117_PEM) | (c0 & AK4117_CINT)) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[6]->id); - if (c0 & AK4117_QINT) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[8]->id); - - if (c0 & AK4117_AUDION) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[9]->id); - if (c1 & AK4117_NPCM) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[10]->id); - if (c1 & AK4117_DTSCD) - snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[11]->id); - - if (ak4117->change_callback && (c0 | c1) != 0) - ak4117->change_callback(ak4117, c0, c1); - - __rate: - /* compare rate */ - res = external_rate(rcs1); - if (!(flags & AK4117_CHECK_NO_RATE) && runtime && runtime->rate != res) { - snd_pcm_stream_lock_irqsave(ak4117->substream, _flags); - if (snd_pcm_running(ak4117->substream)) { - // printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res); - snd_pcm_stop(ak4117->substream, SNDRV_PCM_STATE_DRAINING); - wake_up(&runtime->sleep); - res = 1; - } - snd_pcm_stream_unlock_irqrestore(ak4117->substream, _flags); - } - return res; -} - -static void snd_ak4117_timer(unsigned long data) -{ - struct ak4117 *chip = (struct ak4117 *)data; - - if (chip->init) - return; - snd_ak4117_check_rate_and_errors(chip, 0); - chip->timer.expires = 1 + jiffies; - add_timer(&chip->timer); -} - -EXPORT_SYMBOL(snd_ak4117_create); -EXPORT_SYMBOL(snd_ak4117_reg_write); -EXPORT_SYMBOL(snd_ak4117_reinit); -EXPORT_SYMBOL(snd_ak4117_build); -EXPORT_SYMBOL(snd_ak4117_external_rate); -EXPORT_SYMBOL(snd_ak4117_check_rate_and_errors); diff --git a/ANDROID_3.4.5/sound/i2c/other/ak4xxx-adda.c b/ANDROID_3.4.5/sound/i2c/other/ak4xxx-adda.c deleted file mode 100644 index cef813d2..00000000 --- a/ANDROID_3.4.5/sound/i2c/other/ak4xxx-adda.c +++ /dev/null @@ -1,945 +0,0 @@ -/* - * ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4358 / AK4381 - * AD and DA converters - * - * Copyright (c) 2000-2004 Jaroslav Kysela , - * Takashi Iwai - * - * 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 -#include - -MODULE_AUTHOR("Jaroslav Kysela , Takashi Iwai "); -MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); -MODULE_LICENSE("GPL"); - -/* write the given register and save the data to the cache */ -void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, - unsigned char val) -{ - ak->ops.lock(ak, chip); - ak->ops.write(ak, chip, reg, val); - - /* save the data */ - snd_akm4xxx_set(ak, chip, reg, val); - ak->ops.unlock(ak, chip); -} - -EXPORT_SYMBOL(snd_akm4xxx_write); - -/* reset procedure for AK4524 and AK4528 */ -static void ak4524_reset(struct snd_akm4xxx *ak, int state) -{ - unsigned int chip; - unsigned char reg; - - for (chip = 0; chip < ak->num_dacs/2; chip++) { - snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); - if (state) - continue; - /* DAC volumes */ - for (reg = 0x04; reg < ak->total_regs; reg++) - snd_akm4xxx_write(ak, chip, reg, - snd_akm4xxx_get(ak, chip, reg)); - } -} - -/* reset procedure for AK4355 and AK4358 */ -static void ak435X_reset(struct snd_akm4xxx *ak, int state) -{ - unsigned char reg; - - if (state) { - snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ - return; - } - for (reg = 0x00; reg < ak->total_regs; reg++) - if (reg != 0x01) - snd_akm4xxx_write(ak, 0, reg, - snd_akm4xxx_get(ak, 0, reg)); - snd_akm4xxx_write(ak, 0, 0x01, 0x01); /* un-reset, unmute */ -} - -/* reset procedure for AK4381 */ -static void ak4381_reset(struct snd_akm4xxx *ak, int state) -{ - unsigned int chip; - unsigned char reg; - for (chip = 0; chip < ak->num_dacs/2; chip++) { - snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); - if (state) - continue; - for (reg = 0x01; reg < ak->total_regs; reg++) - snd_akm4xxx_write(ak, chip, reg, - snd_akm4xxx_get(ak, chip, reg)); - } -} - -/* - * reset the AKM codecs - * @state: 1 = reset codec, 0 = restore the registers - * - * assert the reset operation and restores the register values to the chips. - */ -void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) -{ - switch (ak->type) { - case SND_AK4524: - case SND_AK4528: - case SND_AK4620: - ak4524_reset(ak, state); - break; - case SND_AK4529: - /* FIXME: needed for ak4529? */ - break; - case SND_AK4355: - ak435X_reset(ak, state); - break; - case SND_AK4358: - ak435X_reset(ak, state); - break; - case SND_AK4381: - ak4381_reset(ak, state); - break; - default: - break; - } -} - -EXPORT_SYMBOL(snd_akm4xxx_reset); - - -/* - * Volume conversion table for non-linear volumes - * from -63.5dB (mute) to 0dB step 0.5dB - * - * Used for AK4524/AK4620 input/ouput attenuation, AK4528, and - * AK5365 input attenuation - */ -static const unsigned char vol_cvt_datt[128] = { - 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, - 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, - 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a, - 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, - 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1c, - 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x23, - 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2d, - 0x2e, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, - 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x3f, 0x40, - 0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4a, - 0x4b, 0x4d, 0x4e, 0x50, 0x51, 0x52, 0x53, 0x54, - 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x69, - 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x72, 0x73, - 0x75, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f, -}; - -/* - * dB tables - */ -static const DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1); -static const DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); -static const DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); - -/* - * initialize all the ak4xxx chips - */ -void snd_akm4xxx_init(struct snd_akm4xxx *ak) -{ - static const unsigned char inits_ak4524[] = { - 0x00, 0x07, /* 0: all power up */ - 0x01, 0x00, /* 1: ADC/DAC reset */ - 0x02, 0x60, /* 2: 24bit I2S */ - 0x03, 0x19, /* 3: deemphasis off */ - 0x01, 0x03, /* 1: ADC/DAC enable */ - 0x04, 0x00, /* 4: ADC left muted */ - 0x05, 0x00, /* 5: ADC right muted */ - 0x06, 0x00, /* 6: DAC left muted */ - 0x07, 0x00, /* 7: DAC right muted */ - 0xff, 0xff - }; - static const unsigned char inits_ak4528[] = { - 0x00, 0x07, /* 0: all power up */ - 0x01, 0x00, /* 1: ADC/DAC reset */ - 0x02, 0x60, /* 2: 24bit I2S */ - 0x03, 0x0d, /* 3: deemphasis off, turn LR highpass filters on */ - 0x01, 0x03, /* 1: ADC/DAC enable */ - 0x04, 0x00, /* 4: ADC left muted */ - 0x05, 0x00, /* 5: ADC right muted */ - 0xff, 0xff - }; - static const unsigned char inits_ak4529[] = { - 0x09, 0x01, /* 9: ATS=0, RSTN=1 */ - 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */ - 0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */ - 0x01, 0x00, /* 1: ACKS=0, ADC, loop off */ - 0x02, 0xff, /* 2: LOUT1 muted */ - 0x03, 0xff, /* 3: ROUT1 muted */ - 0x04, 0xff, /* 4: LOUT2 muted */ - 0x05, 0xff, /* 5: ROUT2 muted */ - 0x06, 0xff, /* 6: LOUT3 muted */ - 0x07, 0xff, /* 7: ROUT3 muted */ - 0x0b, 0xff, /* B: LOUT4 muted */ - 0x0c, 0xff, /* C: ROUT4 muted */ - 0x08, 0x55, /* 8: deemphasis all off */ - 0xff, 0xff - }; - static const unsigned char inits_ak4355[] = { - 0x01, 0x02, /* 1: reset and soft-mute */ - 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, - * disable DZF, sharp roll-off, RSTN#=0 */ - 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ - // 0x02, 0x2e, /* quad speed */ - 0x03, 0x01, /* 3: de-emphasis off */ - 0x04, 0x00, /* 4: LOUT1 volume muted */ - 0x05, 0x00, /* 5: ROUT1 volume muted */ - 0x06, 0x00, /* 6: LOUT2 volume muted */ - 0x07, 0x00, /* 7: ROUT2 volume muted */ - 0x08, 0x00, /* 8: LOUT3 volume muted */ - 0x09, 0x00, /* 9: ROUT3 volume muted */ - 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */ - 0x01, 0x01, /* 1: un-reset, unmute */ - 0xff, 0xff - }; - static const unsigned char inits_ak4358[] = { - 0x01, 0x02, /* 1: reset and soft-mute */ - 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, - * disable DZF, sharp roll-off, RSTN#=0 */ - 0x02, 0x4e, /* 2: DA's power up, normal speed, RSTN#=0 */ - /* 0x02, 0x6e,*/ /* quad speed */ - 0x03, 0x01, /* 3: de-emphasis off */ - 0x04, 0x00, /* 4: LOUT1 volume muted */ - 0x05, 0x00, /* 5: ROUT1 volume muted */ - 0x06, 0x00, /* 6: LOUT2 volume muted */ - 0x07, 0x00, /* 7: ROUT2 volume muted */ - 0x08, 0x00, /* 8: LOUT3 volume muted */ - 0x09, 0x00, /* 9: ROUT3 volume muted */ - 0x0b, 0x00, /* b: LOUT4 volume muted */ - 0x0c, 0x00, /* c: ROUT4 volume muted */ - 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */ - 0x01, 0x01, /* 1: un-reset, unmute */ - 0xff, 0xff - }; - static const unsigned char inits_ak4381[] = { - 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ - 0x01, 0x02, /* 1: de-emphasis off, normal speed, - * sharp roll-off, DZF off */ - // 0x01, 0x12, /* quad speed */ - 0x02, 0x00, /* 2: DZF disabled */ - 0x03, 0x00, /* 3: LATT 0 */ - 0x04, 0x00, /* 4: RATT 0 */ - 0x00, 0x0f, /* 0: power-up, un-reset */ - 0xff, 0xff - }; - static const unsigned char inits_ak4620[] = { - 0x00, 0x07, /* 0: normal */ - 0x01, 0x00, /* 0: reset */ - 0x01, 0x02, /* 1: RSTAD */ - 0x01, 0x03, /* 1: RSTDA */ - 0x01, 0x0f, /* 1: normal */ - 0x02, 0x60, /* 2: 24bit I2S */ - 0x03, 0x01, /* 3: deemphasis off */ - 0x04, 0x00, /* 4: LIN muted */ - 0x05, 0x00, /* 5: RIN muted */ - 0x06, 0x00, /* 6: LOUT muted */ - 0x07, 0x00, /* 7: ROUT muted */ - 0xff, 0xff - }; - - int chip; - const unsigned char *ptr, *inits; - unsigned char reg, data; - - memset(ak->images, 0, sizeof(ak->images)); - memset(ak->volumes, 0, sizeof(ak->volumes)); - - switch (ak->type) { - case SND_AK4524: - inits = inits_ak4524; - ak->num_chips = ak->num_dacs / 2; - ak->name = "ak4524"; - ak->total_regs = 0x08; - break; - case SND_AK4528: - inits = inits_ak4528; - ak->num_chips = ak->num_dacs / 2; - ak->name = "ak4528"; - ak->total_regs = 0x06; - break; - case SND_AK4529: - inits = inits_ak4529; - ak->num_chips = 1; - ak->name = "ak4529"; - ak->total_regs = 0x0d; - break; - case SND_AK4355: - inits = inits_ak4355; - ak->num_chips = 1; - ak->name = "ak4355"; - ak->total_regs = 0x0b; - break; - case SND_AK4358: - inits = inits_ak4358; - ak->num_chips = 1; - ak->name = "ak4358"; - ak->total_regs = 0x10; - break; - case SND_AK4381: - inits = inits_ak4381; - ak->num_chips = ak->num_dacs / 2; - ak->name = "ak4381"; - ak->total_regs = 0x05; - break; - case SND_AK5365: - /* FIXME: any init sequence? */ - ak->num_chips = 1; - ak->name = "ak5365"; - ak->total_regs = 0x08; - return; - case SND_AK4620: - inits = inits_ak4620; - ak->num_chips = ak->num_dacs / 2; - ak->name = "ak4620"; - ak->total_regs = 0x08; - break; - default: - snd_BUG(); - return; - } - - for (chip = 0; chip < ak->num_chips; chip++) { - ptr = inits; - while (*ptr != 0xff) { - reg = *ptr++; - data = *ptr++; - snd_akm4xxx_write(ak, chip, reg, data); - udelay(10); - } - } -} - -EXPORT_SYMBOL(snd_akm4xxx_init); - -/* - * Mixer callbacks - */ -#define AK_IPGA (1<<20) /* including IPGA */ -#define AK_VOL_CVT (1<<21) /* need dB conversion */ -#define AK_NEEDSMSB (1<<22) /* need MSB update bit */ -#define AK_INVERT (1<<23) /* data is inverted */ -#define AK_GET_CHIP(val) (((val) >> 8) & 0xff) -#define AK_GET_ADDR(val) ((val) & 0xff) -#define AK_GET_SHIFT(val) (((val) >> 16) & 0x0f) -#define AK_GET_VOL_CVT(val) (((val) >> 21) & 1) -#define AK_GET_IPGA(val) (((val) >> 20) & 1) -#define AK_GET_NEEDSMSB(val) (((val) >> 22) & 1) -#define AK_GET_INVERT(val) (((val) >> 23) & 1) -#define AK_GET_MASK(val) (((val) >> 24) & 0xff) -#define AK_COMPOSE(chip,addr,shift,mask) \ - (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) - -static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - unsigned int mask = AK_GET_MASK(kcontrol->private_value); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_akm4xxx_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - - ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); - return 0; -} - -static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr, - unsigned char nval) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - unsigned int mask = AK_GET_MASK(kcontrol->private_value); - int chip = AK_GET_CHIP(kcontrol->private_value); - - if (snd_akm4xxx_get_vol(ak, chip, addr) == nval) - return 0; - - snd_akm4xxx_set_vol(ak, chip, addr, nval); - if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128) - nval = vol_cvt_datt[nval]; - if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128) - nval++; /* need to correct + 1 since both 127 and 128 are 0dB */ - if (AK_GET_INVERT(kcontrol->private_value)) - nval = mask - nval; - if (AK_GET_NEEDSMSB(kcontrol->private_value)) - nval |= 0x80; - /* printk(KERN_DEBUG "DEBUG - AK writing reg: chip %x addr %x, - nval %x\n", chip, addr, nval); */ - snd_akm4xxx_write(ak, chip, addr, nval); - return 1; -} - -static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned int mask = AK_GET_MASK(kcontrol->private_value); - unsigned int val = ucontrol->value.integer.value[0]; - if (val > mask) - return -EINVAL; - return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), val); -} - -static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - unsigned int mask = AK_GET_MASK(kcontrol->private_value); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - - ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); - ucontrol->value.integer.value[1] = snd_akm4xxx_get_vol(ak, chip, addr+1); - return 0; -} - -static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int addr = AK_GET_ADDR(kcontrol->private_value); - unsigned int mask = AK_GET_MASK(kcontrol->private_value); - unsigned int val[2]; - int change; - - val[0] = ucontrol->value.integer.value[0]; - val[1] = ucontrol->value.integer.value[1]; - if (val[0] > mask || val[1] > mask) - return -EINVAL; - change = put_ak_reg(kcontrol, addr, val[0]); - change |= put_ak_reg(kcontrol, addr + 1, val[1]); - return change; -} - -static int snd_akm4xxx_deemphasis_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { - "44.1kHz", "Off", "48kHz", "32kHz", - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= 4) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_akm4xxx_deemphasis_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int shift = AK_GET_SHIFT(kcontrol->private_value); - ucontrol->value.enumerated.item[0] = - (snd_akm4xxx_get(ak, chip, addr) >> shift) & 3; - return 0; -} - -static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int shift = AK_GET_SHIFT(kcontrol->private_value); - unsigned char nval = ucontrol->value.enumerated.item[0] & 3; - int change; - - nval = (nval << shift) | - (snd_akm4xxx_get(ak, chip, addr) & ~(3 << shift)); - change = snd_akm4xxx_get(ak, chip, addr) != nval; - if (change) - snd_akm4xxx_write(ak, chip, addr, nval); - return change; -} - -#define ak4xxx_switch_info snd_ctl_boolean_mono_info - -static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int shift = AK_GET_SHIFT(kcontrol->private_value); - int invert = AK_GET_INVERT(kcontrol->private_value); - /* we observe the (1<value.integer.value[0] = (val & (1<private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int shift = AK_GET_SHIFT(kcontrol->private_value); - int invert = AK_GET_INVERT(kcontrol->private_value); - long flag = ucontrol->value.integer.value[0]; - unsigned char val, oval; - int change; - - if (invert) - flag = ! flag; - oval = snd_akm4xxx_get(ak, chip, addr); - if (flag) - val = oval | (1<adc_info[mixer_ch].input_names; - num_names = 0; - while (num_names < AK5365_NUM_INPUTS && input_names[num_names]) - ++num_names; - return num_names; -} - -static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int mixer_ch = AK_GET_SHIFT(kcontrol->private_value); - const char **input_names; - int num_names, idx; - - num_names = ak4xxx_capture_num_inputs(ak, mixer_ch); - if (!num_names) - return -EINVAL; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = num_names; - idx = uinfo->value.enumerated.item; - if (idx >= num_names) - return -EINVAL; - input_names = ak->adc_info[mixer_ch].input_names; - strncpy(uinfo->value.enumerated.name, input_names[idx], - sizeof(uinfo->value.enumerated.name)); - return 0; -} - -static int ak4xxx_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int mask = AK_GET_MASK(kcontrol->private_value); - unsigned char val; - - val = snd_akm4xxx_get(ak, chip, addr) & mask; - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int mixer_ch = AK_GET_SHIFT(kcontrol->private_value); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int mask = AK_GET_MASK(kcontrol->private_value); - unsigned char oval, val; - int num_names = ak4xxx_capture_num_inputs(ak, mixer_ch); - - if (ucontrol->value.enumerated.item[0] >= num_names) - return -EINVAL; - - oval = snd_akm4xxx_get(ak, chip, addr); - val = oval & ~mask; - val |= ucontrol->value.enumerated.item[0] & mask; - if (val != oval) { - snd_akm4xxx_write(ak, chip, addr, val); - return 1; - } - return 0; -} - -/* - * build AK4xxx controls - */ - -static int build_dac_controls(struct snd_akm4xxx *ak) -{ - int idx, err, mixer_ch, num_stereo; - struct snd_kcontrol_new knew; - - mixer_ch = 0; - for (idx = 0; idx < ak->num_dacs; ) { - /* mute control for Revolution 7.1 - AK4381 */ - if (ak->type == SND_AK4381 - && ak->dac_info[mixer_ch].switch_name) { - memset(&knew, 0, sizeof(knew)); - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.count = 1; - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - knew.name = ak->dac_info[mixer_ch].switch_name; - knew.info = ak4xxx_switch_info; - knew.get = ak4xxx_switch_get; - knew.put = ak4xxx_switch_put; - knew.access = 0; - /* register 1, bit 0 (SMUTE): 0 = normal operation, - 1 = mute */ - knew.private_value = - AK_COMPOSE(idx/2, 1, 0, 0) | AK_INVERT; - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); - if (err < 0) - return err; - } - memset(&knew, 0, sizeof(knew)); - if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) { - knew.name = "DAC Volume"; - knew.index = mixer_ch + ak->idx_offset * 2; - num_stereo = 1; - } else { - knew.name = ak->dac_info[mixer_ch].name; - num_stereo = ak->dac_info[mixer_ch].num_channels; - } - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.count = 1; - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - if (num_stereo == 2) { - knew.info = snd_akm4xxx_stereo_volume_info; - knew.get = snd_akm4xxx_stereo_volume_get; - knew.put = snd_akm4xxx_stereo_volume_put; - } else { - knew.info = snd_akm4xxx_volume_info; - knew.get = snd_akm4xxx_volume_get; - knew.put = snd_akm4xxx_volume_put; - } - switch (ak->type) { - case SND_AK4524: - /* register 6 & 7 */ - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127) | - AK_VOL_CVT; - knew.tlv.p = db_scale_vol_datt; - break; - case SND_AK4528: - /* register 4 & 5 */ - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | - AK_VOL_CVT; - knew.tlv.p = db_scale_vol_datt; - break; - case SND_AK4529: { - /* registers 2-7 and b,c */ - int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; - knew.private_value = - AK_COMPOSE(0, val, 0, 255) | AK_INVERT; - knew.tlv.p = db_scale_8bit; - break; - } - case SND_AK4355: - /* register 4-9, chip #0 only */ - knew.private_value = AK_COMPOSE(0, idx + 4, 0, 255); - knew.tlv.p = db_scale_8bit; - break; - case SND_AK4358: { - /* register 4-9 and 11-12, chip #0 only */ - int addr = idx < 6 ? idx + 4 : idx + 5; - knew.private_value = - AK_COMPOSE(0, addr, 0, 127) | AK_NEEDSMSB; - knew.tlv.p = db_scale_7bit; - break; - } - case SND_AK4381: - /* register 3 & 4 */ - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); - knew.tlv.p = db_scale_linear; - break; - case SND_AK4620: - /* register 6 & 7 */ - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 6, 0, 255); - knew.tlv.p = db_scale_linear; - break; - default: - return -EINVAL; - } - - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); - if (err < 0) - return err; - - idx += num_stereo; - mixer_ch++; - } - return 0; -} - -static int build_adc_controls(struct snd_akm4xxx *ak) -{ - int idx, err, mixer_ch, num_stereo, max_steps; - struct snd_kcontrol_new knew; - - mixer_ch = 0; - if (ak->type == SND_AK4528) - return 0; /* no controls */ - for (idx = 0; idx < ak->num_adcs;) { - memset(&knew, 0, sizeof(knew)); - if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { - knew.name = "ADC Volume"; - knew.index = mixer_ch + ak->idx_offset * 2; - num_stereo = 1; - } else { - knew.name = ak->adc_info[mixer_ch].name; - num_stereo = ak->adc_info[mixer_ch].num_channels; - } - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.count = 1; - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - if (num_stereo == 2) { - knew.info = snd_akm4xxx_stereo_volume_info; - knew.get = snd_akm4xxx_stereo_volume_get; - knew.put = snd_akm4xxx_stereo_volume_put; - } else { - knew.info = snd_akm4xxx_volume_info; - knew.get = snd_akm4xxx_volume_get; - knew.put = snd_akm4xxx_volume_put; - } - /* register 4 & 5 */ - if (ak->type == SND_AK5365) - max_steps = 152; - else - max_steps = 164; - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, max_steps) | - AK_VOL_CVT | AK_IPGA; - knew.tlv.p = db_scale_vol_datt; - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); - if (err < 0) - return err; - - if (ak->type == SND_AK5365 && (idx % 2) == 0) { - if (! ak->adc_info || - ! ak->adc_info[mixer_ch].switch_name) { - knew.name = "Capture Switch"; - knew.index = mixer_ch + ak->idx_offset * 2; - } else - knew.name = ak->adc_info[mixer_ch].switch_name; - knew.info = ak4xxx_switch_info; - knew.get = ak4xxx_switch_get; - knew.put = ak4xxx_switch_put; - knew.access = 0; - /* register 2, bit 0 (SMUTE): 0 = normal operation, - 1 = mute */ - knew.private_value = - AK_COMPOSE(idx/2, 2, 0, 0) | AK_INVERT; - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); - if (err < 0) - return err; - - memset(&knew, 0, sizeof(knew)); - knew.name = ak->adc_info[mixer_ch].selector_name; - if (!knew.name) { - knew.name = "Capture Channel"; - knew.index = mixer_ch + ak->idx_offset * 2; - } - - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.info = ak4xxx_capture_source_info; - knew.get = ak4xxx_capture_source_get; - knew.put = ak4xxx_capture_source_put; - knew.access = 0; - /* input selector control: reg. 1, bits 0-2. - * mis-use 'shift' to pass mixer_ch */ - knew.private_value - = AK_COMPOSE(idx/2, 1, mixer_ch, 0x07); - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); - if (err < 0) - return err; - } - - idx += num_stereo; - mixer_ch++; - } - return 0; -} - -static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) -{ - int idx, err; - struct snd_kcontrol_new knew; - - for (idx = 0; idx < num_emphs; idx++) { - memset(&knew, 0, sizeof(knew)); - knew.name = "Deemphasis"; - knew.index = idx + ak->idx_offset; - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.count = 1; - knew.info = snd_akm4xxx_deemphasis_info; - knew.get = snd_akm4xxx_deemphasis_get; - knew.put = snd_akm4xxx_deemphasis_put; - switch (ak->type) { - case SND_AK4524: - case SND_AK4528: - case SND_AK4620: - /* register 3 */ - knew.private_value = AK_COMPOSE(idx, 3, 0, 0); - break; - case SND_AK4529: { - int shift = idx == 3 ? 6 : (2 - idx) * 2; - /* register 8 with shift */ - knew.private_value = AK_COMPOSE(0, 8, shift, 0); - break; - } - case SND_AK4355: - case SND_AK4358: - knew.private_value = AK_COMPOSE(idx, 3, 0, 0); - break; - case SND_AK4381: - knew.private_value = AK_COMPOSE(idx, 1, 1, 0); - break; - default: - return -EINVAL; - } - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); - if (err < 0) - return err; - } - return 0; -} - -#ifdef CONFIG_PROC_FS -static void proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_akm4xxx *ak = entry->private_data; - int reg, val, chip; - for (chip = 0; chip < ak->num_chips; chip++) { - for (reg = 0; reg < ak->total_regs; reg++) { - val = snd_akm4xxx_get(ak, chip, reg); - snd_iprintf(buffer, "chip %d: 0x%02x = 0x%02x\n", chip, - reg, val); - } - } -} - -static int proc_init(struct snd_akm4xxx *ak) -{ - struct snd_info_entry *entry; - int err; - err = snd_card_proc_new(ak->card, ak->name, &entry); - if (err < 0) - return err; - snd_info_set_text_ops(entry, ak, proc_regs_read); - return 0; -} -#else /* !CONFIG_PROC_FS */ -static int proc_init(struct snd_akm4xxx *ak) { return 0; } -#endif - -int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) -{ - int err, num_emphs; - - err = build_dac_controls(ak); - if (err < 0) - return err; - - err = build_adc_controls(ak); - if (err < 0) - return err; - if (ak->type == SND_AK4355 || ak->type == SND_AK4358) - num_emphs = 1; - else if (ak->type == SND_AK4620) - num_emphs = 0; - else - num_emphs = ak->num_dacs / 2; - err = build_deemphasis(ak, num_emphs); - if (err < 0) - return err; - err = proc_init(ak); - if (err < 0) - return err; - - return 0; -} -EXPORT_SYMBOL(snd_akm4xxx_build_controls); - -static int __init alsa_akm4xxx_module_init(void) -{ - return 0; -} - -static void __exit alsa_akm4xxx_module_exit(void) -{ -} - -module_init(alsa_akm4xxx_module_init) -module_exit(alsa_akm4xxx_module_exit) diff --git a/ANDROID_3.4.5/sound/i2c/other/pt2258.c b/ANDROID_3.4.5/sound/i2c/other/pt2258.c deleted file mode 100644 index 9fa390ba..00000000 --- a/ANDROID_3.4.5/sound/i2c/other/pt2258.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * ALSA Driver for the PT2258 volume controller. - * - * Copyright (c) 2006 Jochen Voss - * - * 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 - -MODULE_AUTHOR("Jochen Voss "); -MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)"); -MODULE_LICENSE("GPL"); - -#define PT2258_CMD_RESET 0xc0 -#define PT2258_CMD_UNMUTE 0xf8 -#define PT2258_CMD_MUTE 0xf9 - -static const unsigned char pt2258_channel_code[12] = { - 0x80, 0x90, /* channel 1: -10dB, -1dB */ - 0x40, 0x50, /* channel 2: -10dB, -1dB */ - 0x00, 0x10, /* channel 3: -10dB, -1dB */ - 0x20, 0x30, /* channel 4: -10dB, -1dB */ - 0x60, 0x70, /* channel 5: -10dB, -1dB */ - 0xa0, 0xb0 /* channel 6: -10dB, -1dB */ -}; - -int snd_pt2258_reset(struct snd_pt2258 *pt) -{ - unsigned char bytes[2]; - int i; - - /* reset chip */ - bytes[0] = PT2258_CMD_RESET; - snd_i2c_lock(pt->i2c_bus); - if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1) - goto __error; - snd_i2c_unlock(pt->i2c_bus); - - /* mute all channels */ - pt->mute = 1; - bytes[0] = PT2258_CMD_MUTE; - snd_i2c_lock(pt->i2c_bus); - if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1) - goto __error; - snd_i2c_unlock(pt->i2c_bus); - - /* set all channels to 0dB */ - for (i = 0; i < 6; ++i) - pt->volume[i] = 0; - bytes[0] = 0xd0; - bytes[1] = 0xe0; - snd_i2c_lock(pt->i2c_bus); - if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2) - goto __error; - snd_i2c_unlock(pt->i2c_bus); - - return 0; - - __error: - snd_i2c_unlock(pt->i2c_bus); - snd_printk(KERN_ERR "PT2258 reset failed\n"); - return -EIO; -} - -static int pt2258_stereo_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 79; - return 0; -} - -static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pt2258 *pt = kcontrol->private_data; - int base = kcontrol->private_value; - - /* chip does not support register reads */ - ucontrol->value.integer.value[0] = 79 - pt->volume[base]; - ucontrol->value.integer.value[1] = 79 - pt->volume[base + 1]; - return 0; -} - -static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pt2258 *pt = kcontrol->private_data; - int base = kcontrol->private_value; - unsigned char bytes[2]; - int val0, val1; - - val0 = 79 - ucontrol->value.integer.value[0]; - val1 = 79 - ucontrol->value.integer.value[1]; - if (val0 < 0 || val0 > 79 || val1 < 0 || val1 > 79) - return -EINVAL; - if (val0 == pt->volume[base] && val1 == pt->volume[base + 1]) - return 0; - - pt->volume[base] = val0; - bytes[0] = pt2258_channel_code[2 * base] | (val0 / 10); - bytes[1] = pt2258_channel_code[2 * base + 1] | (val0 % 10); - snd_i2c_lock(pt->i2c_bus); - if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2) - goto __error; - snd_i2c_unlock(pt->i2c_bus); - - pt->volume[base + 1] = val1; - bytes[0] = pt2258_channel_code[2 * base + 2] | (val1 / 10); - bytes[1] = pt2258_channel_code[2 * base + 3] | (val1 % 10); - snd_i2c_lock(pt->i2c_bus); - if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2) - goto __error; - snd_i2c_unlock(pt->i2c_bus); - - return 1; - - __error: - snd_i2c_unlock(pt->i2c_bus); - snd_printk(KERN_ERR "PT2258 access failed\n"); - return -EIO; -} - -#define pt2258_switch_info snd_ctl_boolean_mono_info - -static int pt2258_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pt2258 *pt = kcontrol->private_data; - - ucontrol->value.integer.value[0] = !pt->mute; - return 0; -} - -static int pt2258_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pt2258 *pt = kcontrol->private_data; - unsigned char bytes[2]; - int val; - - val = !ucontrol->value.integer.value[0]; - if (pt->mute == val) - return 0; - - pt->mute = val; - bytes[0] = val ? PT2258_CMD_MUTE : PT2258_CMD_UNMUTE; - snd_i2c_lock(pt->i2c_bus); - if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1) - goto __error; - snd_i2c_unlock(pt->i2c_bus); - - return 1; - - __error: - snd_i2c_unlock(pt->i2c_bus); - snd_printk(KERN_ERR "PT2258 access failed 2\n"); - return -EIO; -} - -static const DECLARE_TLV_DB_SCALE(pt2258_db_scale, -7900, 100, 0); - -int snd_pt2258_build_controls(struct snd_pt2258 *pt) -{ - struct snd_kcontrol_new knew; - char *names[3] = { - "Mic Loopback Playback Volume", - "Line Loopback Playback Volume", - "CD Loopback Playback Volume" - }; - int i, err; - - for (i = 0; i < 3; ++i) { - memset(&knew, 0, sizeof(knew)); - knew.name = names[i]; - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.count = 1; - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - knew.private_value = 2 * i; - knew.info = pt2258_stereo_volume_info; - knew.get = pt2258_stereo_volume_get; - knew.put = pt2258_stereo_volume_put; - knew.tlv.p = pt2258_db_scale; - - err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt)); - if (err < 0) - return err; - } - - memset(&knew, 0, sizeof(knew)); - knew.name = "Loopback Switch"; - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.info = pt2258_switch_info; - knew.get = pt2258_switch_get; - knew.put = pt2258_switch_put; - knew.access = 0; - err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt)); - if (err < 0) - return err; - - return 0; -} - -EXPORT_SYMBOL(snd_pt2258_reset); -EXPORT_SYMBOL(snd_pt2258_build_controls); diff --git a/ANDROID_3.4.5/sound/i2c/other/tea575x-tuner.c b/ANDROID_3.4.5/sound/i2c/other/tea575x-tuner.c deleted file mode 100644 index a63faec5..00000000 --- a/ANDROID_3.4.5/sound/i2c/other/tea575x-tuner.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips - * - * Copyright (c) 2004 Jaroslav Kysela - * - * - * 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 -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); -MODULE_LICENSE("GPL"); - -#define FREQ_LO (76U * 16000) -#define FREQ_HI (108U * 16000) - -/* - * definitions - */ - -#define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ -#define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ -#define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ -#define TEA575X_BIT_BAND_MASK (3<<20) -#define TEA575X_BIT_BAND_FM (0<<20) -#define TEA575X_BIT_BAND_MW (1<<20) -#define TEA575X_BIT_BAND_LW (1<<21) -#define TEA575X_BIT_BAND_SW (1<<22) -#define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ -#define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ -#define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ -#define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ -#define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ -#define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ -#define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ -#define TEA575X_BIT_DUMMY (1<<15) /* buffer */ -#define TEA575X_BIT_FREQ_MASK 0x7fff - -/* - * lowlevel part - */ - -static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) -{ - u16 l; - u8 data; - - tea->ops->set_direction(tea, 1); - udelay(16); - - for (l = 25; l > 0; l--) { - data = (val >> 24) & TEA575X_DATA; - val <<= 1; /* shift data */ - tea->ops->set_pins(tea, data | TEA575X_WREN); - udelay(2); - tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK); - udelay(2); - tea->ops->set_pins(tea, data | TEA575X_WREN); - udelay(2); - } - - if (!tea->mute) - tea->ops->set_pins(tea, 0); -} - -static u32 snd_tea575x_read(struct snd_tea575x *tea) -{ - u16 l, rdata; - u32 data = 0; - - tea->ops->set_direction(tea, 0); - tea->ops->set_pins(tea, 0); - udelay(16); - - for (l = 24; l--;) { - tea->ops->set_pins(tea, TEA575X_CLK); - udelay(2); - if (!l) - tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1; - tea->ops->set_pins(tea, 0); - udelay(2); - data <<= 1; /* shift data */ - rdata = tea->ops->get_pins(tea); - if (!l) - tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1; - if (rdata & TEA575X_DATA) - data++; - udelay(2); - } - - if (tea->mute) - tea->ops->set_pins(tea, TEA575X_WREN); - - return data; -} - -static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) -{ - u32 freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK; - - if (freq == 0) - return freq; - - /* freq *= 12.5 */ - freq *= 125; - freq /= 10; - /* crystal fixup */ - if (tea->tea5759) - freq += TEA575X_FMIF; - else - freq -= TEA575X_FMIF; - - return clamp(freq * 16, FREQ_LO, FREQ_HI); /* from kHz */ -} - -static void snd_tea575x_set_freq(struct snd_tea575x *tea) -{ - u32 freq = tea->freq; - - freq /= 16; /* to kHz */ - /* crystal fixup */ - if (tea->tea5759) - freq -= TEA575X_FMIF; - else - freq += TEA575X_FMIF; - /* freq /= 12.5 */ - freq *= 10; - freq /= 125; - - tea->val &= ~TEA575X_BIT_FREQ_MASK; - tea->val |= freq & TEA575X_BIT_FREQ_MASK; - snd_tea575x_write(tea, tea->val); -} - -/* - * Linux Video interface - */ - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - - strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); - strlcpy(v->card, tea->card, sizeof(v->card)); - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); - strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); - v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; - if (!tea->cannot_read_data) - v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; - v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - - if (v->index > 0) - return -EINVAL; - - snd_tea575x_read(tea); - - strcpy(v->name, "FM"); - v->type = V4L2_TUNER_RADIO; - v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - v->rangelow = FREQ_LO; - v->rangehigh = FREQ_HI; - v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; - v->audmode = (tea->val & TEA575X_BIT_MONO) ? - V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; - v->signal = tea->tuned ? 0xffff : 0; - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - - if (v->index) - return -EINVAL; - tea->val &= ~TEA575X_BIT_MONO; - if (v->audmode == V4L2_TUNER_MODE_MONO) - tea->val |= TEA575X_BIT_MONO; - snd_tea575x_write(tea, tea->val); - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct snd_tea575x *tea = video_drvdata(file); - - if (f->tuner != 0) - return -EINVAL; - f->type = V4L2_TUNER_RADIO; - f->frequency = tea->freq; - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct snd_tea575x *tea = video_drvdata(file); - - if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) - return -EINVAL; - - tea->val &= ~TEA575X_BIT_SEARCH; - tea->freq = clamp(f->frequency, FREQ_LO, FREQ_HI); - snd_tea575x_set_freq(tea); - return 0; -} - -static int vidioc_s_hw_freq_seek(struct file *file, void *fh, - struct v4l2_hw_freq_seek *a) -{ - struct snd_tea575x *tea = video_drvdata(file); - unsigned long timeout; - int i; - - if (tea->cannot_read_data) - return -ENOTTY; - if (a->tuner || a->wrap_around) - return -EINVAL; - - /* clear the frequency, HW will fill it in */ - tea->val &= ~TEA575X_BIT_FREQ_MASK; - tea->val |= TEA575X_BIT_SEARCH; - if (a->seek_upward) - tea->val |= TEA575X_BIT_UPDOWN; - else - tea->val &= ~TEA575X_BIT_UPDOWN; - snd_tea575x_write(tea, tea->val); - timeout = jiffies + msecs_to_jiffies(10000); - for (;;) { - if (time_after(jiffies, timeout)) - break; - if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { - /* some signal arrived, stop search */ - tea->val &= ~TEA575X_BIT_SEARCH; - snd_tea575x_set_freq(tea); - return -ERESTARTSYS; - } - if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) { - u32 freq; - - /* Found a frequency, wait until it can be read */ - for (i = 0; i < 100; i++) { - msleep(10); - freq = snd_tea575x_get_freq(tea); - if (freq) /* available */ - break; - } - if (freq == 0) /* shouldn't happen */ - break; - /* - * if we moved by less than 50 kHz, or in the wrong - * direction, continue seeking - */ - if (abs(tea->freq - freq) < 16 * 50 || - (a->seek_upward && freq < tea->freq) || - (!a->seek_upward && freq > tea->freq)) { - snd_tea575x_write(tea, tea->val); - continue; - } - tea->freq = freq; - tea->val &= ~TEA575X_BIT_SEARCH; - return 0; - } - } - tea->val &= ~TEA575X_BIT_SEARCH; - snd_tea575x_set_freq(tea); - return -EAGAIN; -} - -static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - tea->mute = ctrl->val; - snd_tea575x_set_freq(tea); - return 0; - } - - return -EINVAL; -} - -static const struct v4l2_file_operations tea575x_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = video_ioctl2, - .open = v4l2_fh_open, - .release = v4l2_fh_release, - .poll = v4l2_ctrl_poll, -}; - -static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct video_device tea575x_radio = { - .fops = &tea575x_fops, - .ioctl_ops = &tea575x_ioctl_ops, - .release = video_device_release_empty, -}; - -static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { - .s_ctrl = tea575x_s_ctrl, -}; - -/* - * initialize all the tea575x chips - */ -int snd_tea575x_init(struct snd_tea575x *tea) -{ - int retval; - - tea->mute = true; - - /* Not all devices can or know how to read the data back. - Such devices can set cannot_read_data to true. */ - if (!tea->cannot_read_data) { - snd_tea575x_write(tea, 0x55AA); - if (snd_tea575x_read(tea) != 0x55AA) - return -ENODEV; - } - - tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28; - tea->freq = 90500 * 16; /* 90.5Mhz default */ - snd_tea575x_set_freq(tea); - - tea->vd = tea575x_radio; - video_set_drvdata(&tea->vd, tea); - mutex_init(&tea->mutex); - strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); - tea->vd.lock = &tea->mutex; - tea->vd.v4l2_dev = tea->v4l2_dev; - tea->vd.ctrl_handler = &tea->ctrl_handler; - set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); - - v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); - v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); - retval = tea->ctrl_handler.error; - if (retval) { - v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } - - if (tea->ext_init) { - retval = tea->ext_init(tea); - if (retval) { - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } - } - - v4l2_ctrl_handler_setup(&tea->ctrl_handler); - - retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); - if (retval) { - v4l2_err(tea->v4l2_dev, "can't register video device!\n"); - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } - - return 0; -} - -void snd_tea575x_exit(struct snd_tea575x *tea) -{ - video_unregister_device(&tea->vd); - v4l2_ctrl_handler_free(&tea->ctrl_handler); -} - -static int __init alsa_tea575x_module_init(void) -{ - return 0; -} - -static void __exit alsa_tea575x_module_exit(void) -{ -} - -module_init(alsa_tea575x_module_init) -module_exit(alsa_tea575x_module_exit) - -EXPORT_SYMBOL(snd_tea575x_init); -EXPORT_SYMBOL(snd_tea575x_exit); diff --git a/ANDROID_3.4.5/sound/i2c/tea6330t.c b/ANDROID_3.4.5/sound/i2c/tea6330t.c deleted file mode 100644 index 2d22310d..00000000 --- a/ANDROID_3.4.5/sound/i2c/tea6330t.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Routines for control of the TEA6330T circuit via i2c bus - * Sound fader control circuit for car radios by Philips Semiconductors - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus"); -MODULE_LICENSE("GPL"); - -#define TEA6330T_ADDR (0x80>>1) /* fixed address */ - -#define TEA6330T_SADDR_VOLUME_LEFT 0x00 /* volume left */ -#define TEA6330T_SADDR_VOLUME_RIGHT 0x01 /* volume right */ -#define TEA6330T_SADDR_BASS 0x02 /* bass control */ -#define TEA6330T_SADDR_TREBLE 0x03 /* treble control */ -#define TEA6330T_SADDR_FADER 0x04 /* fader control */ -#define TEA6330T_MFN 0x20 /* mute control for selected channels */ -#define TEA6330T_FCH 0x10 /* select fader channels - front or rear */ -#define TEA6330T_SADDR_AUDIO_SWITCH 0x05 /* audio switch */ -#define TEA6330T_GMU 0x80 /* mute control, general mute */ -#define TEA6330T_EQN 0x40 /* equalizer switchover (0=equalizer-on) */ - - -struct tea6330t { - struct snd_i2c_device *device; - struct snd_i2c_bus *bus; - int equalizer; - int fader; - unsigned char regs[8]; - unsigned char mleft, mright; - unsigned char bass, treble; - unsigned char max_bass, max_treble; -}; - - -int snd_tea6330t_detect(struct snd_i2c_bus *bus, int equalizer) -{ - int res; - - snd_i2c_lock(bus); - res = snd_i2c_probeaddr(bus, TEA6330T_ADDR); - snd_i2c_unlock(bus); - return res; -} - -#if 0 -static void snd_tea6330t_set(struct tea6330t *tea, - unsigned char addr, unsigned char value) -{ -#if 0 - printk(KERN_DEBUG "set - 0x%x/0x%x\n", addr, value); -#endif - snd_i2c_write(tea->bus, TEA6330T_ADDR, addr, value, 1); -} -#endif - -#define TEA6330T_MASTER_VOLUME(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_tea6330t_info_master_volume, \ - .get = snd_tea6330t_get_master_volume, .put = snd_tea6330t_put_master_volume } - -static int snd_tea6330t_info_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 43; - return 0; -} - -static int snd_tea6330t_get_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - - snd_i2c_lock(tea->bus); - ucontrol->value.integer.value[0] = tea->mleft - 0x14; - ucontrol->value.integer.value[1] = tea->mright - 0x14; - snd_i2c_unlock(tea->bus); - return 0; -} - -static int snd_tea6330t_put_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - int change, count, err; - unsigned char bytes[3]; - unsigned char val1, val2; - - val1 = (ucontrol->value.integer.value[0] % 44) + 0x14; - val2 = (ucontrol->value.integer.value[1] % 44) + 0x14; - snd_i2c_lock(tea->bus); - change = val1 != tea->mleft || val2 != tea->mright; - tea->mleft = val1; - tea->mright = val2; - count = 0; - if (tea->regs[TEA6330T_SADDR_VOLUME_LEFT] != 0) { - bytes[count++] = TEA6330T_SADDR_VOLUME_LEFT; - bytes[count++] = tea->regs[TEA6330T_SADDR_VOLUME_LEFT] = tea->mleft; - } - if (tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] != 0) { - if (count == 0) - bytes[count++] = TEA6330T_SADDR_VOLUME_RIGHT; - bytes[count++] = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] = tea->mright; - } - if (count > 0) { - if ((err = snd_i2c_sendbytes(tea->device, bytes, count)) < 0) - change = err; - } - snd_i2c_unlock(tea->bus); - return change; -} - -#define TEA6330T_MASTER_SWITCH(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_tea6330t_info_master_switch, \ - .get = snd_tea6330t_get_master_switch, .put = snd_tea6330t_put_master_switch } - -#define snd_tea6330t_info_master_switch snd_ctl_boolean_stereo_info - -static int snd_tea6330t_get_master_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - - snd_i2c_lock(tea->bus); - ucontrol->value.integer.value[0] = tea->regs[TEA6330T_SADDR_VOLUME_LEFT] == 0 ? 0 : 1; - ucontrol->value.integer.value[1] = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] == 0 ? 0 : 1; - snd_i2c_unlock(tea->bus); - return 0; -} - -static int snd_tea6330t_put_master_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - int change, err; - unsigned char bytes[3]; - unsigned char oval1, oval2, val1, val2; - - val1 = ucontrol->value.integer.value[0] & 1; - val2 = ucontrol->value.integer.value[1] & 1; - snd_i2c_lock(tea->bus); - oval1 = tea->regs[TEA6330T_SADDR_VOLUME_LEFT] == 0 ? 0 : 1; - oval2 = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] == 0 ? 0 : 1; - change = val1 != oval1 || val2 != oval2; - tea->regs[TEA6330T_SADDR_VOLUME_LEFT] = val1 ? tea->mleft : 0; - tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] = val2 ? tea->mright : 0; - bytes[0] = TEA6330T_SADDR_VOLUME_LEFT; - bytes[1] = tea->regs[TEA6330T_SADDR_VOLUME_LEFT]; - bytes[2] = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT]; - if ((err = snd_i2c_sendbytes(tea->device, bytes, 3)) < 0) - change = err; - snd_i2c_unlock(tea->bus); - return change; -} - -#define TEA6330T_BASS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_tea6330t_info_bass, \ - .get = snd_tea6330t_get_bass, .put = snd_tea6330t_put_bass } - -static int snd_tea6330t_info_bass(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = tea->max_bass; - return 0; -} - -static int snd_tea6330t_get_bass(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = tea->bass; - return 0; -} - -static int snd_tea6330t_put_bass(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - int change, err; - unsigned char bytes[2]; - unsigned char val1; - - val1 = ucontrol->value.integer.value[0] % (tea->max_bass + 1); - snd_i2c_lock(tea->bus); - tea->bass = val1; - val1 += tea->equalizer ? 7 : 3; - change = tea->regs[TEA6330T_SADDR_BASS] != val1; - bytes[0] = TEA6330T_SADDR_BASS; - bytes[1] = tea->regs[TEA6330T_SADDR_BASS] = val1; - if ((err = snd_i2c_sendbytes(tea->device, bytes, 2)) < 0) - change = err; - snd_i2c_unlock(tea->bus); - return change; -} - -#define TEA6330T_TREBLE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_tea6330t_info_treble, \ - .get = snd_tea6330t_get_treble, .put = snd_tea6330t_put_treble } - -static int snd_tea6330t_info_treble(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = tea->max_treble; - return 0; -} - -static int snd_tea6330t_get_treble(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = tea->treble; - return 0; -} - -static int snd_tea6330t_put_treble(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tea6330t *tea = snd_kcontrol_chip(kcontrol); - int change, err; - unsigned char bytes[2]; - unsigned char val1; - - val1 = ucontrol->value.integer.value[0] % (tea->max_treble + 1); - snd_i2c_lock(tea->bus); - tea->treble = val1; - val1 += 3; - change = tea->regs[TEA6330T_SADDR_TREBLE] != val1; - bytes[0] = TEA6330T_SADDR_TREBLE; - bytes[1] = tea->regs[TEA6330T_SADDR_TREBLE] = val1; - if ((err = snd_i2c_sendbytes(tea->device, bytes, 2)) < 0) - change = err; - snd_i2c_unlock(tea->bus); - return change; -} - -static struct snd_kcontrol_new snd_tea6330t_controls[] = { -TEA6330T_MASTER_SWITCH("Master Playback Switch", 0), -TEA6330T_MASTER_VOLUME("Master Playback Volume", 0), -TEA6330T_BASS("Tone Control - Bass", 0), -TEA6330T_TREBLE("Tone Control - Treble", 0) -}; - -static void snd_tea6330_free(struct snd_i2c_device *device) -{ - kfree(device->private_data); -} - -int snd_tea6330t_update_mixer(struct snd_card *card, - struct snd_i2c_bus *bus, - int equalizer, int fader) -{ - struct snd_i2c_device *device; - struct tea6330t *tea; - struct snd_kcontrol_new *knew; - unsigned int idx; - int err = -ENOMEM; - u8 default_treble, default_bass; - unsigned char bytes[7]; - - tea = kzalloc(sizeof(*tea), GFP_KERNEL); - if (tea == NULL) - return -ENOMEM; - if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) { - kfree(tea); - return err; - } - tea->device = device; - tea->bus = bus; - tea->equalizer = equalizer; - tea->fader = fader; - device->private_data = tea; - device->private_free = snd_tea6330_free; - - snd_i2c_lock(bus); - - /* turn fader off and handle equalizer */ - tea->regs[TEA6330T_SADDR_FADER] = 0x3f; - tea->regs[TEA6330T_SADDR_AUDIO_SWITCH] = equalizer ? 0 : TEA6330T_EQN; - /* initialize mixer */ - if (!tea->equalizer) { - tea->max_bass = 9; - tea->max_treble = 8; - default_bass = 3 + 4; - tea->bass = 4; - default_treble = 3 + 4; - tea->treble = 4; - } else { - tea->max_bass = 5; - tea->max_treble = 0; - default_bass = 7 + 4; - tea->bass = 4; - default_treble = 3; - tea->treble = 0; - } - tea->mleft = tea->mright = 0x14; - tea->regs[TEA6330T_SADDR_BASS] = default_bass; - tea->regs[TEA6330T_SADDR_TREBLE] = default_treble; - - /* compose I2C message and put the hardware to initial state */ - bytes[0] = TEA6330T_SADDR_VOLUME_LEFT; - for (idx = 0; idx < 6; idx++) - bytes[idx+1] = tea->regs[idx]; - if ((err = snd_i2c_sendbytes(device, bytes, 7)) < 0) - goto __error; - - strcat(card->mixername, ",TEA6330T"); - if ((err = snd_component_add(card, "TEA6330T")) < 0) - goto __error; - - for (idx = 0; idx < ARRAY_SIZE(snd_tea6330t_controls); idx++) { - knew = &snd_tea6330t_controls[idx]; - if (tea->treble == 0 && !strcmp(knew->name, "Tone Control - Treble")) - continue; - if ((err = snd_ctl_add(card, snd_ctl_new1(knew, tea))) < 0) - goto __error; - } - - snd_i2c_unlock(bus); - return 0; - - __error: - snd_i2c_unlock(bus); - snd_i2c_device_free(device); - return err; -} - -EXPORT_SYMBOL(snd_tea6330t_detect); -EXPORT_SYMBOL(snd_tea6330t_update_mixer); - -/* - * INIT part - */ - -static int __init alsa_tea6330t_init(void) -{ - return 0; -} - -static void __exit alsa_tea6330t_exit(void) -{ -} - -module_init(alsa_tea6330t_init) -module_exit(alsa_tea6330t_exit) diff --git a/ANDROID_3.4.5/sound/isa/Kconfig b/ANDROID_3.4.5/sound/isa/Kconfig deleted file mode 100644 index 52064cfa..00000000 --- a/ANDROID_3.4.5/sound/isa/Kconfig +++ /dev/null @@ -1,446 +0,0 @@ -# ALSA ISA drivers - -config SND_WSS_LIB - tristate - select SND_PCM - -config SND_SB_COMMON - tristate - -config SND_SB8_DSP - tristate - select SND_PCM - select SND_SB_COMMON - -config SND_SB16_DSP - tristate - select SND_PCM - select SND_SB_COMMON - -menuconfig SND_ISA - bool "ISA sound devices" - depends on ISA && ISA_DMA_API - default y - help - Support for sound devices connected via the ISA bus. - -if SND_ISA - -config SND_ADLIB - tristate "AdLib FM card" - select SND_OPL3_LIB - help - Say Y here to include support for AdLib FM cards. - - To compile this driver as a module, choose M here: the module - will be called snd-adlib. - -config SND_AD1816A - tristate "Analog Devices SoundPort AD1816A" - depends on PNP - select ISAPNP - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - Say Y here to include support for Analog Devices SoundPort - AD1816A or compatible sound chips. - - To compile this driver as a module, choose M here: the module - will be called snd-ad1816a. - -config SND_AD1848 - tristate "Generic AD1848/CS4248 driver" - select SND_WSS_LIB - help - Say Y here to include support for AD1848 (Analog Devices) or - CS4248 (Cirrus Logic - Crystal Semiconductors) chips. - - For newer chips from Cirrus Logic, use the CS4231 or CS4232+ - drivers. - - To compile this driver as a module, choose M here: the module - will be called snd-ad1848. - -config SND_ALS100 - tristate "Diamond Tech. DT-019x and Avance Logic ALSxxx" - depends on PNP - select ISAPNP - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_SB16_DSP - help - Say Y here to include support for soundcards based on the - Diamond Technologies DT-019X or Avance Logic chips: ALS007, - ALS100, ALS110, ALS120 and ALS200 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-als100. - -config SND_AZT1605 - tristate "Aztech AZT1605 Driver" - depends on SND - select SND_WSS_LIB - select SND_MPU401_UART - select SND_OPL3_LIB - help - Say Y here to include support for Aztech Sound Galaxy cards - based on the AZT1605 chipset. - - To compile this driver as a module, choose M here: the module - will be called snd-azt1605. - -config SND_AZT2316 - tristate "Aztech AZT2316 Driver" - depends on SND - select SND_WSS_LIB - select SND_MPU401_UART - select SND_OPL3_LIB - help - Say Y here to include support for Aztech Sound Galaxy cards - based on the AZT2316 chipset. - - To compile this driver as a module, choose M here: the module - will be called snd-azt2316. - -config SND_AZT2320 - tristate "Aztech Systems AZT2320" - depends on PNP - select ISAPNP - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for soundcards based on the - Aztech Systems AZT2320 chip. - - To compile this driver as a module, choose M here: the module - will be called snd-azt2320. - -config SND_CMI8330 - tristate "C-Media CMI8330" - select SND_WSS_LIB - select SND_SB16_DSP - select SND_OPL3_LIB - select SND_MPU401_UART - help - Say Y here to include support for soundcards based on the - C-Media CMI8330 chip. - - To compile this driver as a module, choose M here: the module - will be called snd-cmi8330. - -config SND_CS4231 - tristate "Generic Cirrus Logic CS4231 driver" - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for CS4231 chips from Cirrus - Logic - Crystal Semiconductors. - - To compile this driver as a module, choose M here: the module - will be called snd-cs4231. - -config SND_CS4236 - tristate "Generic Cirrus Logic CS4232/CS4236+ driver" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y to include support for CS4232,CS4235,CS4236,CS4237B, - CS4238B,CS4239 chips from Cirrus Logic - Crystal - Semiconductors. - - To compile this driver as a module, choose M here: the module - will be called snd-cs4236. - -config SND_ES1688 - tristate "Generic ESS ES688/ES1688 and ES968 PnP driver" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - Say Y here to include support for ESS AudioDrive ES688 or - ES1688 chips. Also, this module support cards with ES968 PnP chip. - - To compile this driver as a module, choose M here: the module - will be called snd-es1688. - -config SND_ES18XX - tristate "Generic ESS ES18xx driver" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - Say Y here to include support for ESS AudioDrive ES18xx chips. - - To compile this driver as a module, choose M here: the module - will be called snd-es18xx. - -config SND_SC6000 - tristate "Gallant SC-6000/6600/7000 and Audio Excel DSP 16" - depends on HAS_IOPORT - select SND_WSS_LIB - select SND_OPL3_LIB - select SND_MPU401_UART - help - Say Y here to include support for Gallant SC-6000, SC-6600, SC-7000 - cards and clones: - Audio Excel DSP 16 and Zoltrix AV302. - - These cards are based on CompuMedia ASC-9308 or ASC-9408 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-sc6000. - -config SND_GUSCLASSIC - tristate "Gravis UltraSound Classic" - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for Gravis UltraSound Classic - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-gusclassic. - -config SND_GUSEXTREME - tristate "Gravis UltraSound Extreme" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - Say Y here to include support for Gravis UltraSound Extreme - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-gusextreme. - -config SND_GUSMAX - tristate "Gravis UltraSound MAX" - select SND_RAWMIDI - select SND_WSS_LIB - help - Say Y here to include support for Gravis UltraSound MAX - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-gusmax. - -config SND_INTERWAVE - tristate "AMD InterWave, Gravis UltraSound PnP" - depends on PNP - select SND_RAWMIDI - select SND_WSS_LIB - help - Say Y here to include support for AMD InterWave based - soundcards (Gravis UltraSound Plug & Play, STB SoundRage32, - MED3210, Dynasonic Pro, Panasonic PCA761AW). - - To compile this driver as a module, choose M here: the module - will be called snd-interwave. - -config SND_INTERWAVE_STB - tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)" - depends on PNP - select SND_RAWMIDI - select SND_WSS_LIB - help - Say Y here to include support for AMD InterWave based - soundcards with a TEA6330T bass and treble regulator - (UltraSound 32-Pro). - - To compile this driver as a module, choose M here: the module - will be called snd-interwave-stb. - -config SND_JAZZ16 - tristate "Media Vision Jazz16 card and compatibles" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_SB8_DSP - help - Say Y here to include support for soundcards based on the - Media Vision Jazz16 chipset: digital chip MVD1216 (Jazz16), - codec MVA416 (CS4216) and mixer MVA514 (ICS2514). - Media Vision's Jazz16 cards were sold under names Pro Sonic 16, - Premium 3-D and Pro 3-D. There were also OEMs cards with the - Jazz16 chipset. - - To compile this driver as a module, choose M here: the module - will be called snd-jazz16. - -config SND_OPL3SA2 - tristate "Yamaha OPL3-SA2/SA3" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3 - chips. - - To compile this driver as a module, choose M here: the module - will be called snd-opl3sa2. - -config SND_OPTI92X_AD1848 - tristate "OPTi 82C92x - AD1848" - select SND_OPL3_LIB - select SND_OPL4_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for soundcards based on Opti - 82C92x or OTI-601 chips and using an AD1848 codec. - - To compile this driver as a module, choose M here: the module - will be called snd-opti92x-ad1848. - -config SND_OPTI92X_CS4231 - tristate "OPTi 82C92x - CS4231" - select SND_OPL3_LIB - select SND_OPL4_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for soundcards based on Opti - 82C92x chips and using a CS4231 codec. - - To compile this driver as a module, choose M here: the module - will be called snd-opti92x-cs4231. - -config SND_OPTI93X - tristate "OPTi 82C93x" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for soundcards based on Opti - 82C93x chips. - - To compile this driver as a module, choose M here: the module - will be called snd-opti93x. - -config SND_MIRO - tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver" - select SND_OPL4_LIB - select SND_WSS_LIB - select SND_MPU401_UART - select SND_PCM - help - Say 'Y' or 'M' to include support for Miro miroSOUND PCM1 pro, - miroSOUND PCM12 and miroSOUND PCM20 Radio soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-miro. - -config SND_SB8 - tristate "Sound Blaster 1.0/2.0/Pro (8-bit)" - select SND_OPL3_LIB - select SND_RAWMIDI - select SND_SB8_DSP - help - Say Y here to include support for Creative Sound Blaster 1.0/ - 2.0/Pro (8-bit) or 100% compatible soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-sb8. - -config SND_SB16 - tristate "Sound Blaster 16 (PnP)" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_SB16_DSP - help - Say Y here to include support for Sound Blaster 16 soundcards - (including the Plug and Play version). - - To compile this driver as a module, choose M here: the module - will be called snd-sb16. - -config SND_SBAWE - tristate "Sound Blaster AWE (32,64) (PnP)" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_SB16_DSP - help - Say Y here to include support for Sound Blaster AWE soundcards - (including the Plug and Play version). - - To compile this driver as a module, choose M here: the module - will be called snd-sbawe. - -config SND_SB16_CSP - bool "Sound Blaster 16/AWE CSP support" - depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) - select FW_LOADER - help - Say Y here to include support for the CSP core. This special - coprocessor can do variable tasks like various compression and - decompression algorithms. - -config SND_SSCAPE - tristate "Ensoniq SoundScape driver" - select SND_MPU401_UART - select SND_WSS_LIB - select FW_LOADER - help - Say Y here to include support for Ensoniq SoundScape - and Ensoniq OEM soundcards. - - The PCM audio is supported on SoundScape Classic, Elite, PnP - and VIVO cards. The supported OEM cards are SPEA Media FX and - Reveal SC-600. - The MIDI support is very experimental and requires binary - firmware files called "scope.cod" and "sndscape.co?" where the - ? is digit 0, 1, 2, 3 or 4. The firmware files can be found - in DOS or Windows driver packages. One has to put the firmware - files into the /lib/firmware directory. - - To compile this driver as a module, choose M here: the module - will be called snd-sscape. - -config SND_WAVEFRONT - tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" - select FW_LOADER - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for Turtle Beach Maui, Tropez - and Tropez+ soundcards based on the Wavefront chip. - - To compile this driver as a module, choose M here: the module - will be called snd-wavefront. - -config SND_MSND_PINNACLE - tristate "Turtle Beach MultiSound Pinnacle/Fiji driver" - depends on X86 && EXPERIMENTAL - select FW_LOADER - select SND_MPU401_UART - select SND_PCM - help - Say Y to include support for Turtle Beach MultiSound Pinnacle/ - Fiji soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-msnd-pinnacle. - -config SND_MSND_CLASSIC - tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" - depends on X86 && EXPERIMENTAL - select FW_LOADER - select SND_MPU401_UART - select SND_PCM - help - Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or - Monterey (not for the Pinnacle or Fiji). - - See for important information - about this driver. Note that it has been discontinued, but the - Voyetra Turtle Beach knowledge base entry for it is still available - at . - - To compile this driver as a module, choose M here: the module - will be called snd-msnd-classic. - -endif # SND_ISA - diff --git a/ANDROID_3.4.5/sound/isa/Makefile b/ANDROID_3.4.5/sound/isa/Makefile deleted file mode 100644 index 8d781e41..00000000 --- a/ANDROID_3.4.5/sound/isa/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-adlib-objs := adlib.o -snd-als100-objs := als100.o -snd-azt2320-objs := azt2320.o -snd-cmi8330-objs := cmi8330.o -snd-es18xx-objs := es18xx.o -snd-opl3sa2-objs := opl3sa2.o -snd-sc6000-objs := sc6000.o -snd-sscape-objs := sscape.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_ADLIB) += snd-adlib.o -obj-$(CONFIG_SND_ALS100) += snd-als100.o -obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o -obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o -obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o -obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o -obj-$(CONFIG_SND_SC6000) += snd-sc6000.o -obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o - -obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ galaxy/ gus/ msnd/ opti9xx/ \ - sb/ wavefront/ wss/ diff --git a/ANDROID_3.4.5/sound/isa/ad1816a/Makefile b/ANDROID_3.4.5/sound/isa/ad1816a/Makefile deleted file mode 100644 index 487ab238..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1816a/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-ad1816a-objs := ad1816a.o ad1816a_lib.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AD1816A) += snd-ad1816a.o diff --git a/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a.c b/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a.c deleted file mode 100644 index 94b83b6e..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a.c +++ /dev/null @@ -1,294 +0,0 @@ - -/* - card-ad1816a.c - driver for ADI SoundPort AD1816A based soundcards. - Copyright (C) 2000 by Massimo Piccioni - - 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 -#include - -#define PFX "ad1816a: " - -MODULE_AUTHOR("Massimo Piccioni "); -MODULE_DESCRIPTION("AD1816A, AD1815"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Highscreen,Sound-Boostar 16 3D}," - "{Analog Devices,AD1815}," - "{Analog Devices,AD1816A}," - "{TerraTec,Base 64}," - "{TerraTec,AudioSystem EWS64S}," - "{Aztech/Newcom SC-16 3D}," - "{Shark Predator ISA}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 1-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ -static int clockfreq[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ad1816a based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ad1816a based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ad1816a based soundcard."); -module_param_array(clockfreq, int, NULL, 0444); -MODULE_PARM_DESC(clockfreq, "Clock frequency for ad1816a driver (default = 0)."); - -struct snd_card_ad1816a { - struct pnp_dev *dev; - struct pnp_dev *devmpu; -}; - -static struct pnp_card_device_id snd_ad1816a_pnpids[] = { - /* Analog Devices AD1815 */ - { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } }, - /* Analog Device AD1816? */ - { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Analog Devices AD1816A - added by Kenneth Platz */ - { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */ - { .id = "AZT1022", .devs = { { .id = "AZT1018" }, { .id = "AZT2002" } } }, - /* Highscreen Sound-Boostar 16 3D - added by Stefan Behnel */ - { .id = "LWC1061", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Highscreen Sound-Boostar 16 3D */ - { .id = "MDK1605", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Shark Predator ISA - added by Ken Arromdee */ - { .id = "SMM7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */ - { .id = "TER1112", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */ - { .id = "TER1112", .devs = { { .id = "TER1100" }, { .id = "TER1101" } } }, - /* Analog Devices AD1816A - Terratec Base 64 */ - { .id = "TER1411", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* end */ - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_ad1816a_pnpids); - - -#define DRIVER_NAME "snd-card-ad1816a" - - -static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->dev == NULL) - return -EBUSY; - - acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL); - if (acard->devmpu == NULL) { - mpu_port[dev] = -1; - snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n"); - } - - pdev = acard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - printk(KERN_ERR PFX "AUDIO PnP configure failure\n"); - return -EBUSY; - } - - port[dev] = pnp_port_start(pdev, 2); - fm_port[dev] = pnp_port_start(pdev, 1); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - - if (acard->devmpu == NULL) - return 0; - - pdev = acard->devmpu; - - err = pnp_activate_dev(pdev); - if (err < 0) { - printk(KERN_ERR PFX "MPU401 PnP configure failure\n"); - mpu_port[dev] = -1; - acard->devmpu = NULL; - } else { - mpu_port[dev] = pnp_port_start(pdev, 0); - mpu_irq[dev] = pnp_irq(pdev, 0); - } - - return 0; -} - -static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - int error; - struct snd_card *card; - struct snd_card_ad1816a *acard; - struct snd_ad1816a *chip; - struct snd_opl3 *opl3; - struct snd_timer *timer; - - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_ad1816a), &card); - if (error < 0) - return error; - acard = card->private_data; - - if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - - if ((error = snd_ad1816a_create(card, port[dev], - irq[dev], - dma1[dev], - dma2[dev], - &chip)) < 0) { - snd_card_free(card); - return error; - } - if (clockfreq[dev] >= 5000 && clockfreq[dev] <= 100000) - chip->clock_freq = clockfreq[dev]; - - strcpy(card->driver, "AD1816A"); - strcpy(card->shortname, "ADI SoundPort AD1816A"); - sprintf(card->longname, "%s, SS at 0x%lx, irq %d, dma %d&%d", - card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); - - if ((error = snd_ad1816a_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return error; - } - - if ((error = snd_ad1816a_mixer(chip)) < 0) { - snd_card_free(card); - return error; - } - - error = snd_ad1816a_timer(chip, 0, &timer); - if (error < 0) { - snd_card_free(card); - return error; - } - - if (mpu_port[dev] > 0) { - if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port[dev], 0, mpu_irq[dev], - NULL) < 0) - printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]); - } - - if (fm_port[dev] > 0) { - if (snd_opl3_create(card, - fm_port[dev], fm_port[dev] + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2); - } else { - error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (error < 0) { - snd_card_free(card); - return error; - } - } - } - - if ((error = snd_card_register(card)) < 0) { - snd_card_free(card); - return error; - } - pnp_set_card_drvdata(pcard, card); - return 0; -} - -static unsigned int __devinitdata ad1816a_devices; - -static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - static int dev; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev]) - continue; - res = snd_card_ad1816a_probe(dev, card, id); - if (res < 0) - return res; - dev++; - ad1816a_devices++; - return 0; - } - return -ENODEV; -} - -static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static struct pnp_card_driver ad1816a_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "ad1816a", - .id_table = snd_ad1816a_pnpids, - .probe = snd_ad1816a_pnp_detect, - .remove = __devexit_p(snd_ad1816a_pnp_remove), - /* FIXME: suspend/resume */ -}; - -static int __init alsa_card_ad1816a_init(void) -{ - int err; - - err = pnp_register_card_driver(&ad1816a_pnpc_driver); - if (err) - return err; - - if (!ad1816a_devices) { - pnp_unregister_card_driver(&ad1816a_pnpc_driver); -#ifdef MODULE - printk(KERN_ERR "no AD1816A based soundcards found.\n"); -#endif /* MODULE */ - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_ad1816a_exit(void) -{ - pnp_unregister_card_driver(&ad1816a_pnpc_driver); -} - -module_init(alsa_card_ad1816a_init) -module_exit(alsa_card_ad1816a_exit) diff --git a/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a_lib.c b/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a_lib.c deleted file mode 100644 index 177eed32..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a_lib.c +++ /dev/null @@ -1,972 +0,0 @@ -/* - ad1816a.c - lowlevel code for Analog Devices AD1816A chip. - Copyright (C) 1999-2000 by Massimo Piccioni - - 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 -#include - -static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip) -{ - int timeout; - - for (timeout = 1000; timeout-- > 0; udelay(10)) - if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY) - return 0; - - snd_printk(KERN_WARNING "chip busy.\n"); - return -EBUSY; -} - -static inline unsigned char snd_ad1816a_in(struct snd_ad1816a *chip, unsigned char reg) -{ - snd_ad1816a_busy_wait(chip); - return inb(AD1816A_REG(reg)); -} - -static inline void snd_ad1816a_out(struct snd_ad1816a *chip, unsigned char reg, - unsigned char value) -{ - snd_ad1816a_busy_wait(chip); - outb(value, AD1816A_REG(reg)); -} - -static inline void snd_ad1816a_out_mask(struct snd_ad1816a *chip, unsigned char reg, - unsigned char mask, unsigned char value) -{ - snd_ad1816a_out(chip, reg, - (value & mask) | (snd_ad1816a_in(chip, reg) & ~mask)); -} - -static unsigned short snd_ad1816a_read(struct snd_ad1816a *chip, unsigned char reg) -{ - snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f); - return snd_ad1816a_in(chip, AD1816A_INDIR_DATA_LOW) | - (snd_ad1816a_in(chip, AD1816A_INDIR_DATA_HIGH) << 8); -} - -static void snd_ad1816a_write(struct snd_ad1816a *chip, unsigned char reg, - unsigned short value) -{ - snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f); - snd_ad1816a_out(chip, AD1816A_INDIR_DATA_LOW, value & 0xff); - snd_ad1816a_out(chip, AD1816A_INDIR_DATA_HIGH, (value >> 8) & 0xff); -} - -static void snd_ad1816a_write_mask(struct snd_ad1816a *chip, unsigned char reg, - unsigned short mask, unsigned short value) -{ - snd_ad1816a_write(chip, reg, - (value & mask) | (snd_ad1816a_read(chip, reg) & ~mask)); -} - - -static unsigned char snd_ad1816a_get_format(struct snd_ad1816a *chip, - unsigned int format, int channels) -{ - unsigned char retval = AD1816A_FMT_LINEAR_8; - - switch (format) { - case SNDRV_PCM_FORMAT_MU_LAW: - retval = AD1816A_FMT_ULAW_8; - break; - case SNDRV_PCM_FORMAT_A_LAW: - retval = AD1816A_FMT_ALAW_8; - break; - case SNDRV_PCM_FORMAT_S16_LE: - retval = AD1816A_FMT_LINEAR_16_LIT; - break; - case SNDRV_PCM_FORMAT_S16_BE: - retval = AD1816A_FMT_LINEAR_16_BIG; - } - return (channels > 1) ? (retval | AD1816A_FMT_STEREO) : retval; -} - -static int snd_ad1816a_open(struct snd_ad1816a *chip, unsigned int mode) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - if (chip->mode & mode) { - spin_unlock_irqrestore(&chip->lock, flags); - return -EAGAIN; - } - - switch ((mode &= AD1816A_MODE_OPEN)) { - case AD1816A_MODE_PLAYBACK: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_PLAYBACK_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_PLAYBACK_IRQ_ENABLE, 0xffff); - break; - case AD1816A_MODE_CAPTURE: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_CAPTURE_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_CAPTURE_IRQ_ENABLE, 0xffff); - break; - case AD1816A_MODE_TIMER: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_TIMER_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_TIMER_IRQ_ENABLE, 0xffff); - } - chip->mode |= mode; - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static void snd_ad1816a_close(struct snd_ad1816a *chip, unsigned int mode) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - switch ((mode &= AD1816A_MODE_OPEN)) { - case AD1816A_MODE_PLAYBACK: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_PLAYBACK_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_PLAYBACK_IRQ_ENABLE, 0x0000); - break; - case AD1816A_MODE_CAPTURE: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_CAPTURE_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_CAPTURE_IRQ_ENABLE, 0x0000); - break; - case AD1816A_MODE_TIMER: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_TIMER_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_TIMER_IRQ_ENABLE, 0x0000); - } - if (!((chip->mode &= ~mode) & AD1816A_MODE_OPEN)) - chip->mode = 0; - - spin_unlock_irqrestore(&chip->lock, flags); -} - - -static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what, - int channel, int cmd, int iscapture) -{ - int error = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&chip->lock); - cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00; - /* if (what & AD1816A_PLAYBACK_ENABLE) */ - /* That is not valid, because playback and capture enable - * are the same bit pattern, just to different addresses - */ - if (! iscapture) - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_PLAYBACK_ENABLE, cmd); - else - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_CAPTURE_ENABLE, cmd); - spin_unlock(&chip->lock); - break; - default: - snd_printk(KERN_WARNING "invalid trigger mode 0x%x.\n", what); - error = -EINVAL; - } - - return error; -} - -static int snd_ad1816a_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - return snd_ad1816a_trigger(chip, AD1816A_PLAYBACK_ENABLE, - SNDRV_PCM_STREAM_PLAYBACK, cmd, 0); -} - -static int snd_ad1816a_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - return snd_ad1816a_trigger(chip, AD1816A_CAPTURE_ENABLE, - SNDRV_PCM_STREAM_CAPTURE, cmd, 1); -} - -static int snd_ad1816a_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_ad1816a_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_ad1816a_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - unsigned long flags; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size, rate; - - spin_lock_irqsave(&chip->lock, flags); - - chip->p_dma_size = size = snd_pcm_lib_buffer_bytes(substream); - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00); - - snd_dma_program(chip->dma1, runtime->dma_addr, size, - DMA_MODE_WRITE | DMA_AUTOINIT); - - rate = runtime->rate; - if (chip->clock_freq) - rate = (rate * 33000) / chip->clock_freq; - snd_ad1816a_write(chip, AD1816A_PLAYBACK_SAMPLE_RATE, rate); - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_FMT_ALL | AD1816A_FMT_STEREO, - snd_ad1816a_get_format(chip, runtime->format, - runtime->channels)); - - snd_ad1816a_write(chip, AD1816A_PLAYBACK_BASE_COUNT, - snd_pcm_lib_period_bytes(substream) / 4 - 1); - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static int snd_ad1816a_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - unsigned long flags; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size, rate; - - spin_lock_irqsave(&chip->lock, flags); - - chip->c_dma_size = size = snd_pcm_lib_buffer_bytes(substream); - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00); - - snd_dma_program(chip->dma2, runtime->dma_addr, size, - DMA_MODE_READ | DMA_AUTOINIT); - - rate = runtime->rate; - if (chip->clock_freq) - rate = (rate * 33000) / chip->clock_freq; - snd_ad1816a_write(chip, AD1816A_CAPTURE_SAMPLE_RATE, rate); - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_FMT_ALL | AD1816A_FMT_STEREO, - snd_ad1816a_get_format(chip, runtime->format, - runtime->channels)); - - snd_ad1816a_write(chip, AD1816A_CAPTURE_BASE_COUNT, - snd_pcm_lib_period_bytes(substream) / 4 - 1); - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - - -static snd_pcm_uframes_t snd_ad1816a_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - size_t ptr; - if (!(chip->mode & AD1816A_MODE_PLAYBACK)) - return 0; - ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_ad1816a_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - size_t ptr; - if (!(chip->mode & AD1816A_MODE_CAPTURE)) - return 0; - ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - - -static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id) -{ - struct snd_ad1816a *chip = dev_id; - unsigned char status; - - spin_lock(&chip->lock); - status = snd_ad1816a_in(chip, AD1816A_INTERRUPT_STATUS); - spin_unlock(&chip->lock); - - if ((status & AD1816A_PLAYBACK_IRQ_PENDING) && chip->playback_substream) - snd_pcm_period_elapsed(chip->playback_substream); - - if ((status & AD1816A_CAPTURE_IRQ_PENDING) && chip->capture_substream) - snd_pcm_period_elapsed(chip->capture_substream); - - if ((status & AD1816A_TIMER_IRQ_PENDING) && chip->timer) - snd_timer_interrupt(chip->timer, chip->timer->sticks); - - spin_lock(&chip->lock); - snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); - spin_unlock(&chip->lock); - return IRQ_HANDLED; -} - - -static struct snd_pcm_hardware snd_ad1816a_playback = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 55200, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_ad1816a_capture = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 55200, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_ad1816a_timer_close(struct snd_timer *timer) -{ - struct snd_ad1816a *chip = snd_timer_chip(timer); - snd_ad1816a_close(chip, AD1816A_MODE_TIMER); - return 0; -} - -static int snd_ad1816a_timer_open(struct snd_timer *timer) -{ - struct snd_ad1816a *chip = snd_timer_chip(timer); - snd_ad1816a_open(chip, AD1816A_MODE_TIMER); - return 0; -} - -static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer) -{ - if (snd_BUG_ON(!timer)) - return 0; - - return 10000; -} - -static int snd_ad1816a_timer_start(struct snd_timer *timer) -{ - unsigned short bits; - unsigned long flags; - struct snd_ad1816a *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->lock, flags); - bits = snd_ad1816a_read(chip, AD1816A_INTERRUPT_ENABLE); - - if (!(bits & AD1816A_TIMER_ENABLE)) { - snd_ad1816a_write(chip, AD1816A_TIMER_BASE_COUNT, - timer->sticks & 0xffff); - - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_TIMER_ENABLE, 0xffff); - } - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static int snd_ad1816a_timer_stop(struct snd_timer *timer) -{ - unsigned long flags; - struct snd_ad1816a *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->lock, flags); - - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_TIMER_ENABLE, 0x0000); - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static struct snd_timer_hardware snd_ad1816a_timer_table = { - .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 10000, - .ticks = 65535, - .open = snd_ad1816a_timer_open, - .close = snd_ad1816a_timer_close, - .c_resolution = snd_ad1816a_timer_resolution, - .start = snd_ad1816a_timer_start, - .stop = snd_ad1816a_timer_stop, -}; - -static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int error; - - if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0) - return error; - runtime->hw = snd_ad1816a_playback; - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); - chip->playback_substream = substream; - return 0; -} - -static int snd_ad1816a_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int error; - - if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0) - return error; - runtime->hw = snd_ad1816a_capture; - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); - chip->capture_substream = substream; - return 0; -} - -static int snd_ad1816a_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - snd_ad1816a_close(chip, AD1816A_MODE_PLAYBACK); - return 0; -} - -static int snd_ad1816a_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - snd_ad1816a_close(chip, AD1816A_MODE_CAPTURE); - return 0; -} - - -static void __devinit snd_ad1816a_init(struct snd_ad1816a *chip) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00); - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00); - snd_ad1816a_write(chip, AD1816A_INTERRUPT_ENABLE, 0x0000); - snd_ad1816a_write_mask(chip, AD1816A_CHIP_CONFIG, - AD1816A_CAPTURE_NOT_EQUAL | AD1816A_WSS_ENABLE, 0xffff); - snd_ad1816a_write(chip, AD1816A_DSP_CONFIG, 0x0000); - snd_ad1816a_write(chip, AD1816A_POWERDOWN_CTRL, 0x0000); - - spin_unlock_irqrestore(&chip->lock, flags); -} - -static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - switch (chip->version = snd_ad1816a_read(chip, AD1816A_VERSION_ID)) { - case 0: - chip->hardware = AD1816A_HW_AD1815; - break; - case 1: - chip->hardware = AD1816A_HW_AD18MAX10; - break; - case 3: - chip->hardware = AD1816A_HW_AD1816A; - break; - default: - chip->hardware = AD1816A_HW_AUTO; - } - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static int snd_ad1816a_free(struct snd_ad1816a *chip) -{ - release_and_free_resource(chip->res_port); - if (chip->irq >= 0) - free_irq(chip->irq, (void *) chip); - if (chip->dma1 >= 0) { - snd_dma_disable(chip->dma1); - free_dma(chip->dma1); - } - if (chip->dma2 >= 0) { - snd_dma_disable(chip->dma2); - free_dma(chip->dma2); - } - kfree(chip); - return 0; -} - -static int snd_ad1816a_dev_free(struct snd_device *device) -{ - struct snd_ad1816a *chip = device->device_data; - return snd_ad1816a_free(chip); -} - -static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip) -{ - switch (chip->hardware) { - case AD1816A_HW_AD1816A: return "AD1816A"; - case AD1816A_HW_AD1815: return "AD1815"; - case AD1816A_HW_AD18MAX10: return "AD18max10"; - default: - snd_printk(KERN_WARNING "Unknown chip version %d:%d.\n", - chip->version, chip->hardware); - return "AD1816A - unknown"; - } -} - -int __devinit snd_ad1816a_create(struct snd_card *card, - unsigned long port, int irq, int dma1, int dma2, - struct snd_ad1816a **rchip) -{ - static struct snd_device_ops ops = { - .dev_free = snd_ad1816a_dev_free, - }; - int error; - struct snd_ad1816a *chip; - - *rchip = NULL; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - - if ((chip->res_port = request_region(port, 16, "AD1816A")) == NULL) { - snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port); - snd_ad1816a_free(chip); - return -EBUSY; - } - if (request_irq(irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) { - snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq); - snd_ad1816a_free(chip); - return -EBUSY; - } - chip->irq = irq; - if (request_dma(dma1, "AD1816A - 1")) { - snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1); - snd_ad1816a_free(chip); - return -EBUSY; - } - chip->dma1 = dma1; - if (request_dma(dma2, "AD1816A - 2")) { - snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2); - snd_ad1816a_free(chip); - return -EBUSY; - } - chip->dma2 = dma2; - - chip->card = card; - chip->port = port; - spin_lock_init(&chip->lock); - - if ((error = snd_ad1816a_probe(chip))) { - snd_ad1816a_free(chip); - return error; - } - - snd_ad1816a_init(chip); - - /* Register device */ - if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_ad1816a_free(chip); - return error; - } - - *rchip = chip; - return 0; -} - -static struct snd_pcm_ops snd_ad1816a_playback_ops = { - .open = snd_ad1816a_playback_open, - .close = snd_ad1816a_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ad1816a_hw_params, - .hw_free = snd_ad1816a_hw_free, - .prepare = snd_ad1816a_playback_prepare, - .trigger = snd_ad1816a_playback_trigger, - .pointer = snd_ad1816a_playback_pointer, -}; - -static struct snd_pcm_ops snd_ad1816a_capture_ops = { - .open = snd_ad1816a_capture_open, - .close = snd_ad1816a_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ad1816a_hw_params, - .hw_free = snd_ad1816a_hw_free, - .prepare = snd_ad1816a_capture_prepare, - .trigger = snd_ad1816a_capture_trigger, - .pointer = snd_ad1816a_capture_pointer, -}; - -int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm) -{ - int error; - struct snd_pcm *pcm; - - if ((error = snd_pcm_new(chip->card, "AD1816A", device, 1, 1, &pcm))) - return error; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1816a_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1816a_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = (chip->dma1 == chip->dma2 ) ? SNDRV_PCM_INFO_JOINT_DUPLEX : 0; - - strcpy(pcm->name, snd_ad1816a_chip_id(chip)); - snd_ad1816a_init(chip); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); - - chip->pcm = pcm; - if (rpcm) - *rpcm = pcm; - return 0; -} - -int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer) -{ - struct snd_timer *timer; - struct snd_timer_id tid; - int error; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = chip->card->number; - tid.device = device; - tid.subdevice = 0; - if ((error = snd_timer_new(chip->card, "AD1816A", &tid, &timer)) < 0) - return error; - strcpy(timer->name, snd_ad1816a_chip_id(chip)); - timer->private_data = chip; - chip->timer = timer; - timer->hw = snd_ad1816a_timer_table; - if (rtimer) - *rtimer = timer; - return 0; -} - -/* - * - */ - -static int snd_ad1816a_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[8] = { - "Line", "Mix", "CD", "Synth", "Video", - "Mic", "Phone", - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - uinfo->value.enumerated.items = 7; - if (uinfo->value.enumerated.item > 6) - uinfo->value.enumerated.item = 6; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ad1816a_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned short val; - - spin_lock_irqsave(&chip->lock, flags); - val = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL); - spin_unlock_irqrestore(&chip->lock, flags); - ucontrol->value.enumerated.item[0] = (val >> 12) & 7; - ucontrol->value.enumerated.item[1] = (val >> 4) & 7; - return 0; -} - -static int snd_ad1816a_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned short val; - int change; - - if (ucontrol->value.enumerated.item[0] > 6 || - ucontrol->value.enumerated.item[1] > 6) - return -EINVAL; - val = (ucontrol->value.enumerated.item[0] << 12) | - (ucontrol->value.enumerated.item[1] << 4); - spin_lock_irqsave(&chip->lock, flags); - change = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL) != val; - snd_ad1816a_write(chip, AD1816A_ADC_SOURCE_SEL, val); - spin_unlock_irqrestore(&chip->lock, flags); - return change; -} - -#define AD1816A_SINGLE_TLV(xname, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .info = snd_ad1816a_info_single, \ - .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } -#define AD1816A_SINGLE(xname, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_single, \ - .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_ad1816a_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ad1816a_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->lock, flags); - ucontrol->value.integer.value[0] = (snd_ad1816a_read(chip, reg) >> shift) & mask; - spin_unlock_irqrestore(&chip->lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_ad1816a_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short old_val, val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->lock, flags); - old_val = snd_ad1816a_read(chip, reg); - val = (old_val & ~(mask << shift)) | val; - change = val != old_val; - snd_ad1816a_write(chip, reg, val); - spin_unlock_irqrestore(&chip->lock, flags); - return change; -} - -#define AD1816A_DOUBLE_TLV(xname, reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .info = snd_ad1816a_info_double, \ - .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ - .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - -#define AD1816A_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_double, \ - .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ - .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) } - -static int snd_ad1816a_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ad1816a_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned short val; - - spin_lock_irqsave(&chip->lock, flags); - val = snd_ad1816a_read(chip, reg); - ucontrol->value.integer.value[0] = (val >> shift_left) & mask; - ucontrol->value.integer.value[1] = (val >> shift_right) & mask; - spin_unlock_irqrestore(&chip->lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_ad1816a_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short old_val, val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->lock, flags); - old_val = snd_ad1816a_read(chip, reg); - val1 = (old_val & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != old_val; - snd_ad1816a_write(chip, reg, val1); - spin_unlock_irqrestore(&chip->lock, flags); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); - -static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = { -AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1, - db_scale_5bit), -AD1816A_DOUBLE("PCM Playback Switch", AD1816A_VOICE_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("PCM Playback Volume", AD1816A_VOICE_ATT, 8, 0, 63, 1, - db_scale_6bit), -AD1816A_DOUBLE("Line Playback Switch", AD1816A_LINE_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Line Playback Volume", AD1816A_LINE_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), -AD1816A_DOUBLE("CD Playback Switch", AD1816A_CD_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("CD Playback Volume", AD1816A_CD_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), -AD1816A_DOUBLE("Synth Playback Switch", AD1816A_SYNTH_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Synth Playback Volume", AD1816A_SYNTH_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), -AD1816A_DOUBLE("FM Playback Switch", AD1816A_FM_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("FM Playback Volume", AD1816A_FM_ATT, 8, 0, 63, 1, - db_scale_6bit), -AD1816A_SINGLE("Mic Playback Switch", AD1816A_MIC_GAIN_ATT, 15, 1, 1), -AD1816A_SINGLE_TLV("Mic Playback Volume", AD1816A_MIC_GAIN_ATT, 8, 31, 1, - db_scale_5bit_12db_max), -AD1816A_SINGLE("Mic Boost", AD1816A_MIC_GAIN_ATT, 14, 1, 0), -AD1816A_DOUBLE("Video Playback Switch", AD1816A_VID_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Video Playback Volume", AD1816A_VID_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), -AD1816A_SINGLE("Phone Capture Switch", AD1816A_PHONE_IN_GAIN_ATT, 15, 1, 1), -AD1816A_SINGLE_TLV("Phone Capture Volume", AD1816A_PHONE_IN_GAIN_ATT, 0, 15, 1, - db_scale_4bit), -AD1816A_SINGLE("Phone Playback Switch", AD1816A_PHONE_OUT_ATT, 7, 1, 1), -AD1816A_SINGLE_TLV("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1, - db_scale_5bit), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_ad1816a_info_mux, - .get = snd_ad1816a_get_mux, - .put = snd_ad1816a_put_mux, -}, -AD1816A_DOUBLE("Capture Switch", AD1816A_ADC_PGA, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Capture Volume", AD1816A_ADC_PGA, 8, 0, 15, 0, - db_scale_rec_gain), -AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1), -AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0), -}; - -int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip) -{ - struct snd_card *card; - unsigned int idx; - int err; - - if (snd_BUG_ON(!chip || !chip->card)) - return -EINVAL; - - card = chip->card; - - strcpy(card->mixername, snd_ad1816a_chip_id(chip)); - - for (idx = 0; idx < ARRAY_SIZE(snd_ad1816a_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip))) < 0) - return err; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/ad1848/Makefile b/ANDROID_3.4.5/sound/isa/ad1848/Makefile deleted file mode 100644 index 3d6dea3f..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1848/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-ad1848-objs := ad1848.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AD1848) += snd-ad1848.o - diff --git a/ANDROID_3.4.5/sound/isa/ad1848/ad1848.c b/ANDROID_3.4.5/sound/isa/ad1848/ad1848.c deleted file mode 100644 index 2af77fae..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1848/ad1848.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Generic driver for AD1848/AD1847/CS4248 chips (0.1 Alpha) - * Copyright (c) by Tugrul Galatali , - * Jaroslav Kysela - * Based on card-4232.c by Jaroslav Kysela - * - * - * 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 - -#define CRD_NAME "Generic AD1848/AD1847/CS4248" -#define DEV_NAME "ad1848" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Tugrul Galatali , Jaroslav Kysela "); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848}," - "{Analog Devices,AD1847}," - "{Crystal Semiconductors,CS4248}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static bool thinkpad[SNDRV_CARDS]; /* Thinkpad special case */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); -module_param_array(thinkpad, bool, NULL, 0444); -MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series."); - -static int __devinit snd_ad1848_match(struct device *dev, unsigned int n) -{ - if (!enable[n]) - return 0; - - if (port[n] == SNDRV_AUTO_PORT) { - dev_err(dev, "please specify port\n"); - return 0; - } - if (irq[n] == SNDRV_AUTO_IRQ) { - dev_err(dev, "please specify irq\n"); - return 0; - } - if (dma1[n] == SNDRV_AUTO_DMA) { - dev_err(dev, "please specify dma1\n"); - return 0; - } - return 1; -} - -static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_wss *chip; - struct snd_pcm *pcm; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); - if (error < 0) - return error; - - error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1, - thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, - 0, &chip); - if (error < 0) - goto out; - - card->private_data = chip; - - error = snd_wss_pcm(chip, 0, &pcm); - if (error < 0) - goto out; - - error = snd_wss_mixer(chip); - if (error < 0) - goto out; - - strcpy(card->driver, "AD1848"); - strcpy(card->shortname, pcm->name); - - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - pcm->name, chip->port, irq[n], dma1[n]); - if (thinkpad[n]) - strcat(card->longname, " [Thinkpad]"); - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_wss *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->suspend(chip); - return 0; -} - -static int snd_ad1848_resume(struct device *dev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_wss *chip = card->private_data; - - chip->resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct isa_driver snd_ad1848_driver = { - .match = snd_ad1848_match, - .probe = snd_ad1848_probe, - .remove = __devexit_p(snd_ad1848_remove), -#ifdef CONFIG_PM - .suspend = snd_ad1848_suspend, - .resume = snd_ad1848_resume, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_ad1848_init(void) -{ - return isa_register_driver(&snd_ad1848_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_ad1848_exit(void) -{ - isa_unregister_driver(&snd_ad1848_driver); -} - -module_init(alsa_card_ad1848_init); -module_exit(alsa_card_ad1848_exit); diff --git a/ANDROID_3.4.5/sound/isa/adlib.c b/ANDROID_3.4.5/sound/isa/adlib.c deleted file mode 100644 index 4d50c69f..00000000 --- a/ANDROID_3.4.5/sound/isa/adlib.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * AdLib FM card driver. - */ - -#include -#include -#include -#include -#include -#include - -#define CRD_NAME "AdLib FM" -#define DEV_NAME "adlib" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Rene Herman"); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); - -static int __devinit snd_adlib_match(struct device *dev, unsigned int n) -{ - if (!enable[n]) - return 0; - - if (port[n] == SNDRV_AUTO_PORT) { - dev_err(dev, "please specify port\n"); - return 0; - } - return 1; -} - -static void snd_adlib_free(struct snd_card *card) -{ - release_and_free_resource(card->private_data); -} - -static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_opl3 *opl3; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); - if (error < 0) { - dev_err(dev, "could not create card\n"); - return error; - } - - card->private_data = request_region(port[n], 4, CRD_NAME); - if (!card->private_data) { - dev_err(dev, "could not grab ports\n"); - error = -EBUSY; - goto out; - } - card->private_free = snd_adlib_free; - - strcpy(card->driver, DEV_NAME); - strcpy(card->shortname, CRD_NAME); - sprintf(card->longname, CRD_NAME " at %#lx", port[n]); - - error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3); - if (error < 0) { - dev_err(dev, "could not create OPL\n"); - goto out; - } - - error = snd_opl3_hwdep_new(opl3, 0, 0, NULL); - if (error < 0) { - dev_err(dev, "could not create FM\n"); - goto out; - } - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) { - dev_err(dev, "could not register card\n"); - goto out; - } - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_adlib_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_adlib_driver = { - .match = snd_adlib_match, - .probe = snd_adlib_probe, - .remove = __devexit_p(snd_adlib_remove), - - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_adlib_init(void) -{ - return isa_register_driver(&snd_adlib_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_adlib_exit(void) -{ - isa_unregister_driver(&snd_adlib_driver); -} - -module_init(alsa_card_adlib_init); -module_exit(alsa_card_adlib_exit); diff --git a/ANDROID_3.4.5/sound/isa/als100.c b/ANDROID_3.4.5/sound/isa/als100.c deleted file mode 100644 index d1f4351f..00000000 --- a/ANDROID_3.4.5/sound/isa/als100.c +++ /dev/null @@ -1,378 +0,0 @@ - -/* - card-als100.c - driver for Avance Logic ALS100 based soundcards. - Copyright (C) 1999-2000 by Massimo Piccioni - Copyright (C) 1999-2002 by Massimo Piccioni - - Thanks to Pierfrancesco 'qM2' Passerini. - - Generalised for soundcards based on DT-0196 and ALS-007 chips - by Jonathan Woithe : June 2002. - - 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 -#include - -#define PFX "als100: " - -MODULE_DESCRIPTION("Avance Logic ALS007/ALS1X0"); -MODULE_SUPPORTED_DEVICE("{{Diamond Technologies DT-019X}," - "{Avance Logic ALS-007}}" - "{{Avance Logic,ALS100 - PRO16PNP}," - "{Avance Logic,ALS110}," - "{Avance Logic,ALS120}," - "{Avance Logic,ALS200}," - "{3D Melody,MF1000}," - "{Digimate,3D Sound}," - "{Avance Logic,ALS120}," - "{RTL,RTL3000}}"); - -MODULE_AUTHOR("Massimo Piccioni "); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ -static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Avance Logic based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Avance Logic based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Avance Logic based soundcard."); - -MODULE_ALIAS("snd-dt019x"); - -struct snd_card_als100 { - struct pnp_dev *dev; - struct pnp_dev *devmpu; - struct pnp_dev *devopl; - struct snd_sb *chip; -}; - -static struct pnp_card_device_id snd_als100_pnpids[] = { - /* DT197A30 */ - { .id = "RWB1688", - .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } }, - .driver_data = SB_HW_DT019X }, - /* DT0196 / ALS-007 */ - { .id = "ALS0007", - .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } }, - .driver_data = SB_HW_DT019X }, - /* ALS100 - PRO16PNP */ - { .id = "ALS0001", - .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } }, - .driver_data = SB_HW_ALS100 }, - /* ALS110 - MF1000 - Digimate 3D Sound */ - { .id = "ALS0110", - .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" } }, - .driver_data = SB_HW_ALS100 }, - /* ALS120 */ - { .id = "ALS0120", - .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } }, - .driver_data = SB_HW_ALS100 }, - /* ALS200 */ - { .id = "ALS0200", - .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" } }, - .driver_data = SB_HW_ALS100 }, - /* ALS200 OEM */ - { .id = "ALS0200", - .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0020" } }, - .driver_data = SB_HW_ALS100 }, - /* RTL3000 */ - { .id = "RTL3000", - .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } }, - .driver_data = SB_HW_ALS100 }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids); - -static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->dev == NULL) - return -ENODEV; - - acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev); - acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev); - - pdev = acard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); - return err; - } - port[dev] = pnp_port_start(pdev, 0); - if (id->driver_data == SB_HW_DT019X) - dma8[dev] = pnp_dma(pdev, 0); - else { - dma8[dev] = pnp_dma(pdev, 1); - dma16[dev] = pnp_dma(pdev, 0); - } - irq[dev] = pnp_irq(pdev, 0); - - pdev = acard->devmpu; - if (pdev != NULL) { - err = pnp_activate_dev(pdev); - if (err < 0) - goto __mpu_error; - mpu_port[dev] = pnp_port_start(pdev, 0); - mpu_irq[dev] = pnp_irq(pdev, 0); - } else { - __mpu_error: - if (pdev) { - pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n"); - } - acard->devmpu = NULL; - mpu_port[dev] = -1; - } - - pdev = acard->devopl; - if (pdev != NULL) { - err = pnp_activate_dev(pdev); - if (err < 0) - goto __fm_error; - fm_port[dev] = pnp_port_start(pdev, 0); - } else { - __fm_error: - if (pdev) { - pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n"); - } - acard->devopl = NULL; - fm_port[dev] = -1; - } - - return 0; -} - -static int __devinit snd_card_als100_probe(int dev, - struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - int error; - struct snd_sb *chip; - struct snd_card *card; - struct snd_card_als100 *acard; - struct snd_opl3 *opl3; - - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_als100), &card); - if (error < 0) - return error; - acard = card->private_data; - - if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - - if (pid->driver_data == SB_HW_DT019X) - dma16[dev] = -1; - - error = snd_sbdsp_create(card, port[dev], irq[dev], - snd_sb16dsp_interrupt, - dma8[dev], dma16[dev], - pid->driver_data, - &chip); - if (error < 0) { - snd_card_free(card); - return error; - } - acard->chip = chip; - - if (pid->driver_data == SB_HW_DT019X) { - strcpy(card->driver, "DT-019X"); - strcpy(card->shortname, "Diamond Tech. DT-019X"); - sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", - card->shortname, chip->name, chip->port, - irq[dev], dma8[dev]); - } else { - strcpy(card->driver, "ALS100"); - strcpy(card->shortname, "Avance Logic ALS100"); - sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, chip->name, chip->port, - irq[dev], dma8[dev], dma16[dev]); - } - - if ((error = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return error; - } - - if ((error = snd_sbmixer_new(chip)) < 0) { - snd_card_free(card); - return error; - } - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - int mpu_type = MPU401_HW_ALS100; - - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; - - if (pid->driver_data == SB_HW_DT019X) - mpu_type = MPU401_HW_MPU401; - - if (snd_mpu401_uart_new(card, 0, - mpu_type, - mpu_port[dev], 0, - mpu_irq[dev], - NULL) < 0) - snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); - } - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, - fm_port[dev], fm_port[dev] + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); - } else { - if ((error = snd_opl3_timer_new(opl3, 0, 1)) < 0) { - snd_card_free(card); - return error; - } - if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return error; - } - } - } - - if ((error = snd_card_register(card)) < 0) { - snd_card_free(card); - return error; - } - pnp_set_card_drvdata(pcard, card); - return 0; -} - -static unsigned int __devinitdata als100_devices; - -static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - static int dev; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev]) - continue; - res = snd_card_als100_probe(dev, card, id); - if (res < 0) - return res; - dev++; - als100_devices++; - return 0; - } - return -ENODEV; -} - -static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_card_als100 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - return 0; -} - -static int snd_als100_pnp_resume(struct pnp_card_link *pcard) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_card_als100 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pnp_card_driver als100_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "als100", - .id_table = snd_als100_pnpids, - .probe = snd_als100_pnp_detect, - .remove = __devexit_p(snd_als100_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_als100_pnp_suspend, - .resume = snd_als100_pnp_resume, -#endif -}; - -static int __init alsa_card_als100_init(void) -{ - int err; - - err = pnp_register_card_driver(&als100_pnpc_driver); - if (err) - return err; - - if (!als100_devices) { - pnp_unregister_card_driver(&als100_pnpc_driver); -#ifdef MODULE - snd_printk(KERN_ERR "no Avance Logic based soundcards found\n"); -#endif - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_als100_exit(void) -{ - pnp_unregister_card_driver(&als100_pnpc_driver); -} - -module_init(alsa_card_als100_init) -module_exit(alsa_card_als100_exit) diff --git a/ANDROID_3.4.5/sound/isa/azt2320.c b/ANDROID_3.4.5/sound/isa/azt2320.c deleted file mode 100644 index 6a2c78ef..00000000 --- a/ANDROID_3.4.5/sound/isa/azt2320.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - card-azt2320.c - driver for Aztech Systems AZT2320 based soundcards. - Copyright (C) 1999-2000 by Massimo Piccioni - - 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 -*/ - -/* - This driver should provide support for most Aztech AZT2320 based cards. - Several AZT2316 chips are also supported/tested, but autoprobe doesn't - work: all module option have to be set. - - No docs available for us at Aztech headquarters !!! Unbelievable ... - No other help obtained. - - Thanks to Rainer Wiesner for the WSS - activation method (full-duplex audio!). -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PFX "azt2320: " - -MODULE_AUTHOR("Massimo Piccioni "); -MODULE_DESCRIPTION("Aztech Systems AZT2320"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Aztech Systems,PRO16V}," - "{Aztech Systems,AZT2320}," - "{Aztech Systems,AZT3300}," - "{Aztech Systems,AZT2320}," - "{Aztech Systems,AZT3000}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for azt2320 based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for azt2320 based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable azt2320 based soundcard."); - -struct snd_card_azt2320 { - int dev_no; - struct pnp_dev *dev; - struct pnp_dev *devmpu; - struct snd_wss *chip; -}; - -static struct pnp_card_device_id snd_azt2320_pnpids[] = { - /* PRO16V */ - { .id = "AZT1008", .devs = { { "AZT1008" }, { "AZT2001" }, } }, - /* Aztech Sound Galaxy 16 */ - { .id = "AZT2320", .devs = { { "AZT0001" }, { "AZT0002" }, } }, - /* Packard Bell Sound III 336 AM/SP */ - { .id = "AZT3000", .devs = { { "AZT1003" }, { "AZT2001" }, } }, - /* AT3300 */ - { .id = "AZT3002", .devs = { { "AZT1004" }, { "AZT2001" }, } }, - /* --- */ - { .id = "AZT3005", .devs = { { "AZT1003" }, { "AZT2001" }, } }, - /* --- */ - { .id = "AZT3011", .devs = { { "AZT1003" }, { "AZT2001" }, } }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids); - -#define DRIVER_NAME "snd-card-azt2320" - -static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->dev == NULL) - return -ENODEV; - - acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL); - - pdev = acard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); - return err; - } - port[dev] = pnp_port_start(pdev, 0); - fm_port[dev] = pnp_port_start(pdev, 1); - wss_port[dev] = pnp_port_start(pdev, 2); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - - pdev = acard->devmpu; - if (pdev != NULL) { - err = pnp_activate_dev(pdev); - if (err < 0) - goto __mpu_error; - mpu_port[dev] = pnp_port_start(pdev, 0); - mpu_irq[dev] = pnp_irq(pdev, 0); - } else { - __mpu_error: - if (pdev) { - pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n"); - } - acard->devmpu = NULL; - mpu_port[dev] = -1; - } - - return 0; -} - -/* same of snd_sbdsp_command by Jaroslav Kysela */ -static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char val) -{ - int i; - unsigned long limit; - - limit = jiffies + HZ / 10; - for (i = 50000; i && time_after(limit, jiffies); i--) - if (!(inb(port + 0x0c) & 0x80)) { - outb(val, port + 0x0c); - return 0; - } - return -EBUSY; -} - -static int __devinit snd_card_azt2320_enable_wss(unsigned long port) -{ - int error; - - if ((error = snd_card_azt2320_command(port, 0x09))) - return error; - if ((error = snd_card_azt2320_command(port, 0x00))) - return error; - - mdelay(5); - return 0; -} - -static int __devinit snd_card_azt2320_probe(int dev, - struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - int error; - struct snd_card *card; - struct snd_card_azt2320 *acard; - struct snd_wss *chip; - struct snd_opl3 *opl3; - - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_azt2320), &card); - if (error < 0) - return error; - acard = card->private_data; - - if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - - if ((error = snd_card_azt2320_enable_wss(port[dev]))) { - snd_card_free(card); - return error; - } - - error = snd_wss_create(card, wss_port[dev], -1, - irq[dev], - dma1[dev], dma2[dev], - WSS_HW_DETECT, 0, &chip); - if (error < 0) { - snd_card_free(card); - return error; - } - - strcpy(card->driver, "AZT2320"); - strcpy(card->shortname, "Aztech AZT2320"); - sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i", - card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); - - error = snd_wss_pcm(chip, 0, NULL); - if (error < 0) { - snd_card_free(card); - return error; - } - error = snd_wss_mixer(chip); - if (error < 0) { - snd_card_free(card); - return error; - } - error = snd_wss_timer(chip, 0, NULL); - if (error < 0) { - snd_card_free(card); - return error; - } - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320, - mpu_port[dev], 0, - mpu_irq[dev], NULL) < 0) - snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); - } - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, - fm_port[dev], fm_port[dev] + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); - } else { - if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) { - snd_card_free(card); - return error; - } - if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return error; - } - } - } - - if ((error = snd_card_register(card)) < 0) { - snd_card_free(card); - return error; - } - pnp_set_card_drvdata(pcard, card); - return 0; -} - -static unsigned int __devinitdata azt2320_devices; - -static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - static int dev; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev]) - continue; - res = snd_card_azt2320_probe(dev, card, id); - if (res < 0) - return res; - dev++; - azt2320_devices++; - return 0; - } - return -ENODEV; -} - -static void __devexit snd_azt2320_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_card_azt2320 *acard = card->private_data; - struct snd_wss *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->suspend(chip); - return 0; -} - -static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_card_azt2320 *acard = card->private_data; - struct snd_wss *chip = acard->chip; - - chip->resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pnp_card_driver azt2320_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "azt2320", - .id_table = snd_azt2320_pnpids, - .probe = snd_azt2320_pnp_detect, - .remove = __devexit_p(snd_azt2320_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_azt2320_pnp_suspend, - .resume = snd_azt2320_pnp_resume, -#endif -}; - -static int __init alsa_card_azt2320_init(void) -{ - int err; - - err = pnp_register_card_driver(&azt2320_pnpc_driver); - if (err) - return err; - - if (!azt2320_devices) { - pnp_unregister_card_driver(&azt2320_pnpc_driver); -#ifdef MODULE - snd_printk(KERN_ERR "no AZT2320 based soundcards found\n"); -#endif - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_azt2320_exit(void) -{ - pnp_unregister_card_driver(&azt2320_pnpc_driver); -} - -module_init(alsa_card_azt2320_init) -module_exit(alsa_card_azt2320_exit) diff --git a/ANDROID_3.4.5/sound/isa/cmi8330.c b/ANDROID_3.4.5/sound/isa/cmi8330.c deleted file mode 100644 index 7bd5e337..00000000 --- a/ANDROID_3.4.5/sound/isa/cmi8330.c +++ /dev/null @@ -1,782 +0,0 @@ -/* - * Driver for C-Media's CMI8330 and CMI8329 soundcards. - * Copyright (c) by George Talusan - * http://www.undergrad.math.uwaterloo.ca/~gstalusa - * - * 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 - * - */ - -/* - * NOTES - * - * The extended registers contain mixer settings which are largely - * untapped for the time being. - * - * MPU401 and SPDIF are not supported yet. I don't have the hardware - * to aid in coding and testing, so I won't bother. - * - * To quickly load the module, - * - * modprobe -a snd-cmi8330 sbport=0x220 sbirq=5 sbdma8=1 - * sbdma16=5 wssport=0x530 wssirq=11 wssdma=0 fmport=0x388 - * - * This card has two mixers and two PCM devices. I've cheesed it such - * that recording and playback can be done through the same device. - * The driver "magically" routes the capturing to the AD1848 codec, - * and playback to the SB16 codec. This allows for full-duplex mode - * to some extent. - * The utilities in alsa-utils are aware of both devices, so passing - * the appropriate parameters to amixer and alsactl will give you - * full control over both mixers. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - */ -/* #define ENABLE_SB_MIXER */ -#define PLAYBACK_ON_SB - -/* - */ -MODULE_AUTHOR("George Talusan "); -MODULE_DESCRIPTION("C-Media CMI8330/CMI8329"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int sbirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int sbdma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int sbdma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static long fmport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long mpuport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int mpuirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for CMI8330/CMI8329 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for CMI8330/CMI8329 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable CMI8330/CMI8329 soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif - -module_param_array(sbport, long, NULL, 0444); -MODULE_PARM_DESC(sbport, "Port # for CMI8330/CMI8329 SB driver."); -module_param_array(sbirq, int, NULL, 0444); -MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330/CMI8329 SB driver."); -module_param_array(sbdma8, int, NULL, 0444); -MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330/CMI8329 SB driver."); -module_param_array(sbdma16, int, NULL, 0444); -MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330/CMI8329 SB driver."); - -module_param_array(wssport, long, NULL, 0444); -MODULE_PARM_DESC(wssport, "Port # for CMI8330/CMI8329 WSS driver."); -module_param_array(wssirq, int, NULL, 0444); -MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330/CMI8329 WSS driver."); -module_param_array(wssdma, int, NULL, 0444); -MODULE_PARM_DESC(wssdma, "DMA for CMI8330/CMI8329 WSS driver."); - -module_param_array(fmport, long, NULL, 0444); -MODULE_PARM_DESC(fmport, "FM port # for CMI8330/CMI8329 driver."); -module_param_array(mpuport, long, NULL, 0444); -MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330/CMI8329 driver."); -module_param_array(mpuirq, int, NULL, 0444); -MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330/CMI8329 MPU-401 port."); -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -#endif - -#define CMI8330_RMUX3D 16 -#define CMI8330_MUTEMUX 17 -#define CMI8330_OUTPUTVOL 18 -#define CMI8330_MASTVOL 19 -#define CMI8330_LINVOL 20 -#define CMI8330_CDINVOL 21 -#define CMI8330_WAVVOL 22 -#define CMI8330_RECMUX 23 -#define CMI8330_WAVGAIN 24 -#define CMI8330_LINGAIN 25 -#define CMI8330_CDINGAIN 26 - -static unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] = -{ - 0x40, /* 16 - recording mux (SB-mixer-enabled) */ -#ifdef ENABLE_SB_MIXER - 0x40, /* 17 - mute mux (Mode2) */ -#else - 0x0, /* 17 - mute mux */ -#endif - 0x0, /* 18 - vol */ - 0x0, /* 19 - master volume */ - 0x0, /* 20 - line-in volume */ - 0x0, /* 21 - cd-in volume */ - 0x0, /* 22 - wave volume */ - 0x0, /* 23 - mute/rec mux */ - 0x0, /* 24 - wave rec gain */ - 0x0, /* 25 - line-in rec gain */ - 0x0 /* 26 - cd-in rec gain */ -}; - -typedef int (*snd_pcm_open_callback_t)(struct snd_pcm_substream *); - -enum card_type { - CMI8330, - CMI8329 -}; - -struct snd_cmi8330 { -#ifdef CONFIG_PNP - struct pnp_dev *cap; - struct pnp_dev *play; - struct pnp_dev *mpu; -#endif - struct snd_card *card; - struct snd_wss *wss; - struct snd_sb *sb; - - struct snd_pcm *pcm; - struct snd_cmi8330_stream { - struct snd_pcm_ops ops; - snd_pcm_open_callback_t open; - void *private_data; /* sb or wss */ - } streams[2]; - - enum card_type type; -}; - -#ifdef CONFIG_PNP - -static struct pnp_card_device_id snd_cmi8330_pnpids[] = { - { .id = "CMI0001", .devs = { { "@X@0001" }, { "@@@0001" }, { "@H@0001" }, { "A@@0001" } } }, - { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } }, - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids); - -#endif - - -static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = { -WSS_DOUBLE("Master Playback Volume", 0, - CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), -WSS_SINGLE("Loud Playback Switch", 0, - CMI8330_MUTEMUX, 6, 1, 1), -WSS_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), -WSS_DOUBLE("Line Playback Switch", 0, - CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), -WSS_DOUBLE("Line Playback Volume", 0, - CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0), -WSS_DOUBLE("Line Capture Switch", 0, - CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0), -WSS_DOUBLE("Line Capture Volume", 0, - CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0), -WSS_DOUBLE("CD Playback Switch", 0, - CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0), -WSS_DOUBLE("CD Capture Switch", 0, - CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0), -WSS_DOUBLE("CD Playback Volume", 0, - CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0), -WSS_DOUBLE("CD Capture Volume", 0, - CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0), -WSS_SINGLE("Mic Playback Switch", 0, - CMI8330_MUTEMUX, 0, 1, 0), -WSS_SINGLE("Mic Playback Volume", 0, - CMI8330_OUTPUTVOL, 0, 7, 0), -WSS_SINGLE("Mic Capture Switch", 0, - CMI8330_RMUX3D, 0, 1, 0), -WSS_SINGLE("Mic Capture Volume", 0, - CMI8330_OUTPUTVOL, 5, 7, 0), -WSS_DOUBLE("Wavetable Playback Switch", 0, - CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0), -WSS_DOUBLE("Wavetable Playback Volume", 0, - CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0), -WSS_DOUBLE("Wavetable Capture Switch", 0, - CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0), -WSS_DOUBLE("Wavetable Capture Volume", 0, - CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0), -WSS_SINGLE("3D Control - Switch", 0, - CMI8330_RMUX3D, 5, 1, 1), -WSS_SINGLE("Beep Playback Volume", 0, - CMI8330_OUTPUTVOL, 3, 3, 0), -WSS_DOUBLE("FM Playback Switch", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE("FM Playback Volume", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), -WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0, - CMI8330_RMUX3D, 7, 1, 1), -WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0, - CMI8330_MUTEMUX, 7, 1, 1), -}; - -#ifdef ENABLE_SB_MIXER -static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = { -SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31), -SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15), -SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15), -SB_DOUBLE("SB PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31), -SB_DOUBLE("SB Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31), -SB_DOUBLE("SB CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1), -SB_DOUBLE("SB CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31), -SB_DOUBLE("SB Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1), -SB_DOUBLE("SB Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31), -SB_SINGLE("SB Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1), -SB_SINGLE("SB Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), -SB_SINGLE("SB Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3), -SB_DOUBLE("SB Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3), -SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3), -SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1), -}; - -static unsigned char cmi8330_sb_init_values[][2] __devinitdata = { - { SB_DSP4_MASTER_DEV + 0, 0 }, - { SB_DSP4_MASTER_DEV + 1, 0 }, - { SB_DSP4_PCM_DEV + 0, 0 }, - { SB_DSP4_PCM_DEV + 1, 0 }, - { SB_DSP4_SYNTH_DEV + 0, 0 }, - { SB_DSP4_SYNTH_DEV + 1, 0 }, - { SB_DSP4_INPUT_LEFT, 0 }, - { SB_DSP4_INPUT_RIGHT, 0 }, - { SB_DSP4_OUTPUT_SW, 0 }, - { SB_DSP4_SPEAKER_DEV, 0 }, -}; - - -static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip) -{ - int idx, err; - unsigned long flags; - - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, 0x00, 0x00); /* mixer reset */ - spin_unlock_irqrestore(&chip->mixer_lock, flags); - - /* mute and zero volume channels */ - for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_init_values); idx++) { - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, cmi8330_sb_init_values[idx][0], - cmi8330_sb_init_values[idx][1]); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - } - - for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_mixers); idx++) { - if ((err = snd_sbmixer_add_ctl_elem(chip, &cmi8330_sb_mixers[idx])) < 0) - return err; - } - return 0; -} -#endif - -static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard) -{ - unsigned int idx; - int err; - - strcpy(card->mixername, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D"); - - for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_cmi8330_controls[idx], - acard->wss)); - if (err < 0) - return err; - } - -#ifdef ENABLE_SB_MIXER - if ((err = cmi8330_add_sb_mixers(acard->sb)) < 0) - return err; -#endif - return 0; -} - -#ifdef CONFIG_PNP -static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - /* CMI8329 has a device with ID A@@0001, CMI8330 does not */ - acard->type = (id->devs[3].id[0]) ? CMI8329 : CMI8330; - - acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->cap == NULL) - return -EBUSY; - - acard->play = pnp_request_card_device(card, id->devs[1].id, NULL); - if (acard->play == NULL) - return -EBUSY; - - acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); - if (acard->mpu == NULL) - return -EBUSY; - - pdev = acard->cap; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "AD1848 PnP configure failure\n"); - return -EBUSY; - } - wssport[dev] = pnp_port_start(pdev, 0); - wssdma[dev] = pnp_dma(pdev, 0); - wssirq[dev] = pnp_irq(pdev, 0); - if (pnp_port_start(pdev, 1)) - fmport[dev] = pnp_port_start(pdev, 1); - - /* allocate SB16 resources */ - pdev = acard->play; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "SB16 PnP configure failure\n"); - return -EBUSY; - } - sbport[dev] = pnp_port_start(pdev, 0); - sbdma8[dev] = pnp_dma(pdev, 0); - sbdma16[dev] = pnp_dma(pdev, 1); - sbirq[dev] = pnp_irq(pdev, 0); - /* On CMI8239, the OPL3 port might be present in SB16 PnP resources */ - if (fmport[dev] == SNDRV_AUTO_PORT) { - if (pnp_port_start(pdev, 1)) - fmport[dev] = pnp_port_start(pdev, 1); - else - fmport[dev] = 0x388; /* Or hardwired */ - } - - /* allocate MPU-401 resources */ - pdev = acard->mpu; - - err = pnp_activate_dev(pdev); - if (err < 0) - snd_printk(KERN_ERR "MPU-401 PnP configure failure: will be disabled\n"); - else { - mpuport[dev] = pnp_port_start(pdev, 0); - mpuirq[dev] = pnp_irq(pdev, 0); - } - return 0; -} -#endif - -/* - * PCM interface - * - * since we call the different chip interfaces for playback and capture - * directions, we need a trick. - * - * - copy the ops for each direction into a local record. - * - replace the open callback with the new one, which replaces the - * substream->private_data with the corresponding chip instance - * and calls again the original open callback of the chip. - * - */ - -#ifdef PLAYBACK_ON_SB -#define CMI_SB_STREAM SNDRV_PCM_STREAM_PLAYBACK -#define CMI_AD_STREAM SNDRV_PCM_STREAM_CAPTURE -#else -#define CMI_SB_STREAM SNDRV_PCM_STREAM_CAPTURE -#define CMI_AD_STREAM SNDRV_PCM_STREAM_PLAYBACK -#endif - -static int snd_cmi8330_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream); - - /* replace the private_data and call the original open callback */ - substream->private_data = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].private_data; - return chip->streams[SNDRV_PCM_STREAM_PLAYBACK].open(substream); -} - -static int snd_cmi8330_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream); - - /* replace the private_data and call the original open callback */ - substream->private_data = chip->streams[SNDRV_PCM_STREAM_CAPTURE].private_data; - return chip->streams[SNDRV_PCM_STREAM_CAPTURE].open(substream); -} - -static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip) -{ - struct snd_pcm *pcm; - const struct snd_pcm_ops *ops; - int err; - static snd_pcm_open_callback_t cmi_open_callbacks[2] = { - snd_cmi8330_playback_open, - snd_cmi8330_capture_open - }; - - if ((err = snd_pcm_new(card, (chip->type == CMI8329) ? "CMI8329" : "CMI8330", 0, 1, 1, &pcm)) < 0) - return err; - strcpy(pcm->name, (chip->type == CMI8329) ? "CMI8329" : "CMI8330"); - pcm->private_data = chip; - - /* SB16 */ - ops = snd_sb16dsp_get_pcm_ops(CMI_SB_STREAM); - chip->streams[CMI_SB_STREAM].ops = *ops; - chip->streams[CMI_SB_STREAM].open = ops->open; - chip->streams[CMI_SB_STREAM].ops.open = cmi_open_callbacks[CMI_SB_STREAM]; - chip->streams[CMI_SB_STREAM].private_data = chip->sb; - - /* AD1848 */ - ops = snd_wss_get_pcm_ops(CMI_AD_STREAM); - chip->streams[CMI_AD_STREAM].ops = *ops; - chip->streams[CMI_AD_STREAM].open = ops->open; - chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM]; - chip->streams[CMI_AD_STREAM].private_data = chip->wss; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &chip->streams[SNDRV_PCM_STREAM_PLAYBACK].ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &chip->streams[SNDRV_PCM_STREAM_CAPTURE].ops); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, 128*1024); - chip->pcm = pcm; - - return 0; -} - - -#ifdef CONFIG_PM -static int snd_cmi8330_suspend(struct snd_card *card) -{ - struct snd_cmi8330 *acard = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(acard->pcm); - acard->wss->suspend(acard->wss); - snd_sbmixer_suspend(acard->sb); - return 0; -} - -static int snd_cmi8330_resume(struct snd_card *card) -{ - struct snd_cmi8330 *acard = card->private_data; - - snd_sbdsp_reset(acard->sb); - snd_sbmixer_suspend(acard->sb); - acard->wss->resume(acard->wss); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - - -/* - */ - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -#define PFX "cmi8330: " - -static int snd_cmi8330_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - struct snd_cmi8330 *acard; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_cmi8330), &card); - if (err < 0) { - snd_printk(KERN_ERR PFX "could not get a new card\n"); - return err; - } - acard = card->private_data; - acard->card = card; - *cardp = card; - return 0; -} - -static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) -{ - struct snd_cmi8330 *acard; - int i, err; - struct snd_opl3 *opl3; - - acard = card->private_data; - err = snd_wss_create(card, wssport[dev] + 4, -1, - wssirq[dev], - wssdma[dev], -1, - WSS_HW_DETECT, 0, &acard->wss); - if (err < 0) { - snd_printk(KERN_ERR PFX "AD1848 device busy??\n"); - return err; - } - if (acard->wss->hardware != WSS_HW_CMI8330) { - snd_printk(KERN_ERR PFX "AD1848 not found during probe\n"); - return -ENODEV; - } - - if ((err = snd_sbdsp_create(card, sbport[dev], - sbirq[dev], - snd_sb16dsp_interrupt, - sbdma8[dev], - sbdma16[dev], - SB_HW_AUTO, &acard->sb)) < 0) { - snd_printk(KERN_ERR PFX "SB16 device busy??\n"); - return err; - } - if (acard->sb->hardware != SB_HW_16) { - snd_printk(KERN_ERR PFX "SB16 not found during probe\n"); - return err; - } - - snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */ - for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++) - snd_wss_out(acard->wss, i, - snd_cmi8330_image[i - CMI8330_RMUX3D]); - - if ((err = snd_cmi8330_mixer(card, acard)) < 0) { - snd_printk(KERN_ERR PFX "failed to create mixers\n"); - return err; - } - - if ((err = snd_cmi8330_pcm(card, acard)) < 0) { - snd_printk(KERN_ERR PFX "failed to create pcms\n"); - return err; - } - if (fmport[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, - fmport[dev], fmport[dev] + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX - "no OPL device at 0x%lx-0x%lx ?\n", - fmport[dev], fmport[dev] + 2); - } else { - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - return err; - } - } - - if (mpuport[dev] != SNDRV_AUTO_PORT) { - if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpuport[dev], 0, mpuirq[dev], - NULL) < 0) - printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", - mpuport[dev]); - } - - strcpy(card->driver, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D"); - strcpy(card->shortname, (acard->type == CMI8329) ? "C-Media CMI8329" : "C-Media CMI8330/C3D"); - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - card->shortname, - acard->wss->port, - wssirq[dev], - wssdma[dev]); - - return snd_card_register(card); -} - -static int __devinit snd_cmi8330_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev] || is_isapnp_selected(dev)) - return 0; - if (wssport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify wssport\n"); - return 0; - } - if (sbport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify sbport\n"); - return 0; - } - return 1; -} - -static int __devinit snd_cmi8330_isa_probe(struct device *pdev, - unsigned int dev) -{ - struct snd_card *card; - int err; - - err = snd_cmi8330_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, pdev); - if ((err = snd_cmi8330_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_cmi8330_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_cmi8330_suspend(dev_get_drvdata(dev)); -} - -static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n) -{ - return snd_cmi8330_resume(dev_get_drvdata(dev)); -} -#endif - -#define DEV_NAME "cmi8330" - -static struct isa_driver snd_cmi8330_driver = { - .match = snd_cmi8330_isa_match, - .probe = snd_cmi8330_isa_probe, - .remove = __devexit_p(snd_cmi8330_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_cmi8330_isa_suspend, - .resume = snd_cmi8330_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_cmi8330_card_new(dev, &card); - if (res < 0) - return res; - if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) { - snd_printk(KERN_ERR PFX "PnP detection failed\n"); - snd_card_free(card); - return res; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_cmi8330_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_cmi8330_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_cmi8330_suspend(pnp_get_card_drvdata(pcard)); -} - -static int snd_cmi8330_pnp_resume(struct pnp_card_link *pcard) -{ - return snd_cmi8330_resume(pnp_get_card_drvdata(pcard)); -} -#endif - -static struct pnp_card_driver cmi8330_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "cmi8330", - .id_table = snd_cmi8330_pnpids, - .probe = snd_cmi8330_pnp_detect, - .remove = __devexit_p(snd_cmi8330_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_cmi8330_pnp_suspend, - .resume = snd_cmi8330_pnp_resume, -#endif -}; -#endif /* CONFIG_PNP */ - -static int __init alsa_card_cmi8330_init(void) -{ - int err; - - err = isa_register_driver(&snd_cmi8330_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&cmi8330_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_cmi8330_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&cmi8330_pnpc_driver); - - if (isa_registered) -#endif - isa_unregister_driver(&snd_cmi8330_driver); -} - -module_init(alsa_card_cmi8330_init) -module_exit(alsa_card_cmi8330_exit) diff --git a/ANDROID_3.4.5/sound/isa/cs423x/Makefile b/ANDROID_3.4.5/sound/isa/cs423x/Makefile deleted file mode 100644 index 6d397e8d..00000000 --- a/ANDROID_3.4.5/sound/isa/cs423x/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-cs4231-objs := cs4231.o -snd-cs4236-objs := cs4236.o cs4236_lib.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_CS4231) += snd-cs4231.o -obj-$(CONFIG_SND_CS4236) += snd-cs4236.o - - diff --git a/ANDROID_3.4.5/sound/isa/cs423x/cs4231.c b/ANDROID_3.4.5/sound/isa/cs423x/cs4231.c deleted file mode 100644 index 99dda45e..00000000 --- a/ANDROID_3.4.5/sound/isa/cs423x/cs4231.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Generic driver for CS4231 chips - * Copyright (c) by Jaroslav Kysela - * Originally the CS4232/CS4232A driver, modified for use on CS4231 by - * Tugrul Galatali - * - * 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 -#include - -#define CRD_NAME "Generic CS4231" -#define DEV_NAME "cs4231" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver."); - -static int __devinit snd_cs4231_match(struct device *dev, unsigned int n) -{ - if (!enable[n]) - return 0; - - if (port[n] == SNDRV_AUTO_PORT) { - dev_err(dev, "please specify port\n"); - return 0; - } - if (irq[n] == SNDRV_AUTO_IRQ) { - dev_err(dev, "please specify irq\n"); - return 0; - } - if (dma1[n] == SNDRV_AUTO_DMA) { - dev_err(dev, "please specify dma1\n"); - return 0; - } - return 1; -} - -static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_wss *chip; - struct snd_pcm *pcm; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); - if (error < 0) - return error; - - error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n], - WSS_HW_DETECT, 0, &chip); - if (error < 0) - goto out; - - card->private_data = chip; - - error = snd_wss_pcm(chip, 0, &pcm); - if (error < 0) - goto out; - - strcpy(card->driver, "CS4231"); - strcpy(card->shortname, pcm->name); - - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - pcm->name, chip->port, irq[n], dma1[n]); - if (dma2[n] >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]); - - error = snd_wss_mixer(chip); - if (error < 0) - goto out; - - error = snd_wss_timer(chip, 0, NULL); - if (error < 0) - goto out; - - if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) { - if (mpu_irq[n] == SNDRV_AUTO_IRQ) - mpu_irq[n] = -1; - if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, - mpu_port[n], 0, mpu_irq[n], - NULL) < 0) - dev_warn(dev, "MPU401 not detected\n"); - } - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_wss *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->suspend(chip); - return 0; -} - -static int snd_cs4231_resume(struct device *dev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_wss *chip = card->private_data; - - chip->resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct isa_driver snd_cs4231_driver = { - .match = snd_cs4231_match, - .probe = snd_cs4231_probe, - .remove = __devexit_p(snd_cs4231_remove), -#ifdef CONFIG_PM - .suspend = snd_cs4231_suspend, - .resume = snd_cs4231_resume, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_cs4231_init(void) -{ - return isa_register_driver(&snd_cs4231_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_cs4231_exit(void) -{ - isa_unregister_driver(&snd_cs4231_driver); -} - -module_init(alsa_card_cs4231_init); -module_exit(alsa_card_cs4231_exit); diff --git a/ANDROID_3.4.5/sound/isa/cs423x/cs4236.c b/ANDROID_3.4.5/sound/isa/cs423x/cs4236.c deleted file mode 100644 index 740c51a1..00000000 --- a/ANDROID_3.4.5/sound/isa/cs423x/cs4236.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cirrus Logic CS4232-9"); -MODULE_SUPPORTED_DEVICE("{{Turtle Beach,TBS-2000}," - "{Turtle Beach,Tropez Plus}," - "{SIC CrystalWave 32}," - "{Hewlett Packard,Omnibook 5500}," - "{TerraTec,Maestro 32/96}," - "{Philips,PCA70PS}}," - "{{Crystal Semiconductors,CS4235}," - "{Crystal Semiconductors,CS4236}," - "{Crystal Semiconductors,CS4237}," - "{Crystal Semiconductors,CS4238}," - "{Crystal Semiconductors,CS4239}," - "{Acer,AW37}," - "{Acer,AW35/Pro}," - "{Crystal,3D}," - "{Crystal Computer,TidalWave128}," - "{Dell,Optiplex GX1}," - "{Dell,Workstation 400 sound}," - "{EliteGroup,P5TX-LA sound}," - "{Gallant,SC-70P}," - "{Gateway,E1000 Onboard CS4236B}," - "{Genius,Sound Maker 3DJ}," - "{Hewlett Packard,HP6330 sound}," - "{IBM,PC 300PL sound}," - "{IBM,Aptiva 2137 E24}," - "{IBM,IntelliStation M Pro}," - "{Intel,Marlin Spike Mobo CS4235}," - "{Intel PR440FX Onboard}," - "{Guillemot,MaxiSound 16 PnP}," - "{NewClear,3D}," - "{TerraTec,AudioSystem EWS64L/XL}," - "{Typhoon Soundsystem,CS4236B}," - "{Turtle Beach,Malibu}," - "{Unknown,Digital PC 5000 Onboard}}"); - -MODULE_ALIAS("snd_cs4232"); - -#define IDENT "CS4232+" -#define DEV_NAME "cs4232+" - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long sb_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " IDENT " driver."); -module_param_array(cport, long, NULL, 0444); -MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver."); -module_param_array(sb_port, long, NULL, 0444); -MODULE_PARM_DESC(sb_port, "SB port # for " IDENT " driver (optional)."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnpc_registered; -static int pnp_registered; -#endif /* CONFIG_PNP */ - -struct snd_card_cs4236 { - struct snd_wss *chip; - struct resource *res_sb_port; -#ifdef CONFIG_PNP - struct pnp_dev *wss; - struct pnp_dev *ctrl; - struct pnp_dev *mpu; -#endif -}; - -#ifdef CONFIG_PNP - -/* - * PNP BIOS - */ -static const struct pnp_device_id snd_cs423x_pnpbiosids[] = { - { .id = "CSC0100" }, - { .id = "CSC0000" }, - /* Guillemot Turtlebeach something appears to be cs4232 compatible - * (untested) */ - { .id = "GIM0100" }, - { .id = "" } -}; -MODULE_DEVICE_TABLE(pnp, snd_cs423x_pnpbiosids); - -#define CS423X_ISAPNP_DRIVER "cs4232_isapnp" -static struct pnp_card_device_id snd_cs423x_pnpids[] = { - /* Philips PCA70PS */ - { .id = "CSC0d32", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } }, - /* TerraTec Maestro 32/96 (CS4232) */ - { .id = "CSC1a32", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* HP Omnibook 5500 onboard */ - { .id = "CSC4232", .devs = { { "CSC0000" }, { "CSC0002" }, { "CSC0003" } } }, - /* Unnamed CS4236 card (Made in Taiwan) */ - { .id = "CSC4236", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Turtle Beach TBS-2000 (CS4232) */ - { .id = "CSC7532", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSCb006" } } }, - /* Turtle Beach Tropez Plus (CS4232) */ - { .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } }, - /* SIC CrystalWave 32 (CS4232) */ - { .id = "CSCf032", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Netfinity 3000 on-board soundcard */ - { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC010f" } } }, - /* Intel Marlin Spike Motherboard - CS4235 */ - { .id = "CSC0225", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Intel Marlin Spike Motherboard (#2) - CS4235 */ - { .id = "CSC0225", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } }, - /* Unknown Intel mainboard - CS4235 */ - { .id = "CSC0225", .devs = { { "CSC0100" }, { "CSC0110" } } }, - /* Genius Sound Maker 3DJ - CS4237B */ - { .id = "CSC0437", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Digital PC 5000 Onboard - CS4236B */ - { .id = "CSC0735", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* some unknown CS4236B */ - { .id = "CSC0b35", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Intel PR440FX Onboard sound */ - { .id = "CSC0b36", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4235 on mainboard without MPU */ - { .id = "CSC1425", .devs = { { "CSC0100" }, { "CSC0110" } } }, - /* Gateway E1000 Onboard CS4236B */ - { .id = "CSC1335", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* HP 6330 Onboard sound */ - { .id = "CSC1525", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } }, - /* Crystal Computer TidalWave128 */ - { .id = "CSC1e37", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* ACER AW37 - CS4235 */ - { .id = "CSC4236", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* build-in soundcard in EliteGroup P5TX-LA motherboard - CS4237B */ - { .id = "CSC4237", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Crystal 3D - CS4237B */ - { .id = "CSC4336", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Typhoon Soundsystem PnP - CS4236B */ - { .id = "CSC4536", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Crystal CX4235-XQ3 EP - CS4235 */ - { .id = "CSC4625", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } }, - /* Crystal Semiconductors CS4237B */ - { .id = "CSC4637", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* NewClear 3D - CX4237B-XQ3 */ - { .id = "CSC4837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Dell Optiplex GX1 - CS4236B */ - { .id = "CSC6835", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Dell P410 motherboard - CS4236B */ - { .id = "CSC6835", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* Dell Workstation 400 Onboard - CS4236B */ - { .id = "CSC6836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Turtle Beach Malibu - CS4237B */ - { .id = "CSC7537", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4235 - onboard */ - { .id = "CSC8025", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } }, - /* IBM Aptiva 2137 E24 Onboard - CS4237B */ - { .id = "CSC8037", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* IBM IntelliStation M Pro motherboard */ - { .id = "CSCc835", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* Guillemot MaxiSound 16 PnP - CS4236B */ - { .id = "CSC9836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Gallant SC-70P */ - { .id = "CSC9837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Techmakers MF-4236PW */ - { .id = "CSCa736", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* TerraTec AudioSystem EWS64XL - CS4236B */ - { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" }, { "CSCa803" } } }, - /* TerraTec AudioSystem EWS64XL - CS4236B */ - { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" } } }, - /* ACER AW37/Pro - CS4235 */ - { .id = "CSCd925", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* ACER AW35/Pro - CS4237B */ - { .id = "CSCd937", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4235 without MPU401 */ - { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" } } }, - /* Unknown SiS530 - CS4235 */ - { .id = "CSC4825", .devs = { { "CSC0100" }, { "CSC0110" } } }, - /* IBM IntelliStation M Pro 6898 11U - CS4236B */ - { .id = "CSCe835", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* IBM PC 300PL Onboard - CS4236B */ - { .id = "CSCe836", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* Some noname CS4236 based card */ - { .id = "CSCe936", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4236B */ - { .id = "CSCf235", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4236B */ - { .id = "CSCf238", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* --- */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids); - -/* WSS initialization */ -static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " WSS PnP configure failed for WSS (out of resources?)\n"); - return -EBUSY; - } - port[dev] = pnp_port_start(pdev, 0); - if (fm_port[dev] > 0) - fm_port[dev] = pnp_port_start(pdev, 1); - sb_port[dev] = pnp_port_start(pdev, 2); - irq[dev] = pnp_irq(pdev, 0); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1) == 4 ? -1 : (int)pnp_dma(pdev, 1); - snd_printdd("isapnp WSS: wss port=0x%lx, fm port=0x%lx, sb port=0x%lx\n", - port[dev], fm_port[dev], sb_port[dev]); - snd_printdd("isapnp WSS: irq=%i, dma1=%i, dma2=%i\n", - irq[dev], dma1[dev], dma2[dev]); - return 0; -} - -/* CTRL initialization */ -static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n"); - return -EBUSY; - } - cport[dev] = pnp_port_start(pdev, 0); - snd_printdd("isapnp CTRL: control port=0x%lx\n", cport[dev]); - return 0; -} - -/* MPU initialization */ -static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n"); - mpu_port[dev] = SNDRV_AUTO_PORT; - mpu_irq[dev] = SNDRV_AUTO_IRQ; - } else { - mpu_port[dev] = pnp_port_start(pdev, 0); - if (mpu_irq[dev] >= 0 && - pnp_irq_valid(pdev, 0) && pnp_irq(pdev, 0) >= 0) { - mpu_irq[dev] = pnp_irq(pdev, 0); - } else { - mpu_irq[dev] = -1; /* disable interrupt */ - } - } - snd_printdd("isapnp MPU: port=0x%lx, irq=%i\n", mpu_port[dev], mpu_irq[dev]); - return 0; -} - -static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard, - struct pnp_dev *pdev, - struct pnp_dev *cdev) -{ - acard->wss = pdev; - if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0) - return -EBUSY; - if (cdev) - cport[dev] = pnp_port_start(cdev, 0); - else - cport[dev] = -1; - return 0; -} - -static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->wss == NULL) - return -EBUSY; - acard->ctrl = pnp_request_card_device(card, id->devs[1].id, NULL); - if (acard->ctrl == NULL) - return -EBUSY; - if (id->devs[2].id[0]) { - acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); - if (acard->mpu == NULL) - return -EBUSY; - } - - /* WSS initialization */ - if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0) - return -EBUSY; - - /* CTRL initialization */ - if (acard->ctrl && cport[dev] > 0) { - if (snd_cs423x_pnp_init_ctrl(dev, acard->ctrl) < 0) - return -EBUSY; - } - /* MPU initialization */ - if (acard->mpu && mpu_port[dev] > 0) { - if (snd_cs423x_pnp_init_mpu(dev, acard->mpu) < 0) - return -EBUSY; - } - return 0; -} -#endif /* CONFIG_PNP */ - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -static void snd_card_cs4236_free(struct snd_card *card) -{ - struct snd_card_cs4236 *acard = card->private_data; - - release_and_free_resource(acard->res_sb_port); -} - -static int snd_cs423x_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_cs4236), &card); - if (err < 0) - return err; - card->private_free = snd_card_cs4236_free; - *cardp = card; - return 0; -} - -static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) -{ - struct snd_card_cs4236 *acard; - struct snd_pcm *pcm; - struct snd_wss *chip; - struct snd_opl3 *opl3; - int err; - - acard = card->private_data; - if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT) - if ((acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB")) == NULL) { - printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]); - return -EBUSY; - } - - err = snd_cs4236_create(card, port[dev], cport[dev], - irq[dev], - dma1[dev], dma2[dev], - WSS_HW_DETECT3, 0, &chip); - if (err < 0) - return err; - - acard->chip = chip; - if (chip->hardware & WSS_HW_CS4236B_MASK) { - - err = snd_cs4236_pcm(chip, 0, &pcm); - if (err < 0) - return err; - - err = snd_cs4236_mixer(chip); - if (err < 0) - return err; - } else { - err = snd_wss_pcm(chip, 0, &pcm); - if (err < 0) - return err; - - err = snd_wss_mixer(chip); - if (err < 0) - return err; - } - strcpy(card->driver, pcm->name); - strcpy(card->shortname, pcm->name); - sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", - pcm->name, - chip->port, - irq[dev], - dma1[dev]); - if (dma2[dev] >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); - - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) - return err; - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, - fm_port[dev], fm_port[dev] + 2, - OPL3_HW_OPL3_CS, 0, &opl3) < 0) { - printk(KERN_WARNING IDENT ": OPL3 not detected\n"); - } else { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) - return err; - } - } - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; - if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, - mpu_port[dev], 0, - mpu_irq[dev], NULL) < 0) - printk(KERN_WARNING IDENT ": MPU401 not detected\n"); - } - - return snd_card_register(card); -} - -static int __devinit snd_cs423x_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev] || is_isapnp_selected(dev)) - return 0; - - if (port[dev] == SNDRV_AUTO_PORT) { - dev_err(pdev, "please specify port\n"); - return 0; - } - if (cport[dev] == SNDRV_AUTO_PORT) { - dev_err(pdev, "please specify cport\n"); - return 0; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - dev_err(pdev, "please specify irq\n"); - return 0; - } - if (dma1[dev] == SNDRV_AUTO_DMA) { - dev_err(pdev, "please specify dma1\n"); - return 0; - } - return 1; -} - -static int __devinit snd_cs423x_isa_probe(struct device *pdev, - unsigned int dev) -{ - struct snd_card *card; - int err; - - err = snd_cs423x_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, pdev); - if ((err = snd_cs423x_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - - dev_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_cs423x_isa_remove(struct device *pdev, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(pdev)); - dev_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_cs423x_suspend(struct snd_card *card) -{ - struct snd_card_cs4236 *acard = card->private_data; - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - acard->chip->suspend(acard->chip); - return 0; -} - -static int snd_cs423x_resume(struct snd_card *card) -{ - struct snd_card_cs4236 *acard = card->private_data; - acard->chip->resume(acard->chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} - -static int snd_cs423x_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_cs423x_suspend(dev_get_drvdata(dev)); -} - -static int snd_cs423x_isa_resume(struct device *dev, unsigned int n) -{ - return snd_cs423x_resume(dev_get_drvdata(dev)); -} -#endif - -static struct isa_driver cs423x_isa_driver = { - .match = snd_cs423x_isa_match, - .probe = snd_cs423x_isa_probe, - .remove = __devexit_p(snd_cs423x_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_cs423x_isa_suspend, - .resume = snd_cs423x_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev, - const struct pnp_device_id *id) -{ - static int dev; - int err; - struct snd_card *card; - struct pnp_dev *cdev; - char cid[PNP_ID_LEN]; - - if (pnp_device_is_isapnp(pdev)) - return -ENOENT; /* we have another procedure - card */ - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - /* prepare second id */ - strcpy(cid, pdev->id[0].id); - cid[5] = '1'; - cdev = NULL; - list_for_each_entry(cdev, &(pdev->protocol->devices), protocol_list) { - if (!strcmp(cdev->id[0].id, cid)) - break; - } - err = snd_cs423x_card_new(dev, &card); - if (err < 0) - return err; - err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev); - if (err < 0) { - printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n"); - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_cs423x_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_drvdata(pdev, card); - dev++; - return 0; -} - -static void __devexit snd_cs423x_pnp_remove(struct pnp_dev *pdev) -{ - snd_card_free(pnp_get_drvdata(pdev)); - pnp_set_drvdata(pdev, NULL); -} - -#ifdef CONFIG_PM -static int snd_cs423x_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - return snd_cs423x_suspend(pnp_get_drvdata(pdev)); -} - -static int snd_cs423x_pnp_resume(struct pnp_dev *pdev) -{ - return snd_cs423x_resume(pnp_get_drvdata(pdev)); -} -#endif - -static struct pnp_driver cs423x_pnp_driver = { - .name = "cs423x-pnpbios", - .id_table = snd_cs423x_pnpbiosids, - .probe = snd_cs423x_pnpbios_detect, - .remove = __devexit_p(snd_cs423x_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_cs423x_pnp_suspend, - .resume = snd_cs423x_pnp_resume, -#endif -}; - -static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_cs423x_card_new(dev, &card); - if (res < 0) - return res; - if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) { - printk(KERN_ERR "isapnp detection failed and probing for " IDENT - " is not supported\n"); - snd_card_free(card); - return res; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_cs423x_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_cs423x_suspend(pnp_get_card_drvdata(pcard)); -} - -static int snd_cs423x_pnpc_resume(struct pnp_card_link *pcard) -{ - return snd_cs423x_resume(pnp_get_card_drvdata(pcard)); -} -#endif - -static struct pnp_card_driver cs423x_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = CS423X_ISAPNP_DRIVER, - .id_table = snd_cs423x_pnpids, - .probe = snd_cs423x_pnpc_detect, - .remove = __devexit_p(snd_cs423x_pnpc_remove), -#ifdef CONFIG_PM - .suspend = snd_cs423x_pnpc_suspend, - .resume = snd_cs423x_pnpc_resume, -#endif -}; -#endif /* CONFIG_PNP */ - -static int __init alsa_card_cs423x_init(void) -{ - int err; - - err = isa_register_driver(&cs423x_isa_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - err = pnp_register_driver(&cs423x_pnp_driver); - if (!err) - pnp_registered = 1; - err = pnp_register_card_driver(&cs423x_pnpc_driver); - if (!err) - pnpc_registered = 1; - if (pnp_registered) - err = 0; - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_cs423x_exit(void) -{ -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&cs423x_pnpc_driver); - if (pnp_registered) - pnp_unregister_driver(&cs423x_pnp_driver); - if (isa_registered) -#endif - isa_unregister_driver(&cs423x_isa_driver); -} - -module_init(alsa_card_cs423x_init) -module_exit(alsa_card_cs423x_exit) diff --git a/ANDROID_3.4.5/sound/isa/cs423x/cs4236_lib.c b/ANDROID_3.4.5/sound/isa/cs423x/cs4236_lib.c deleted file mode 100644 index c5adca30..00000000 --- a/ANDROID_3.4.5/sound/isa/cs423x/cs4236_lib.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of CS4235/4236B/4237B/4238B/4239 chips - * - * Note: - * ----- - * - * Bugs: - * ----- - * - * 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 - * - */ - -/* - * Indirect control registers (CS4236B+) - * - * C0 - * D8: WSS reset (all chips) - * - * C1 (all chips except CS4236) - * D7-D5: version - * D4-D0: chip id - * 11101 - CS4235 - * 01011 - CS4236B - * 01000 - CS4237B - * 01001 - CS4238B - * 11110 - CS4239 - * - * C2 - * D7-D4: 3D Space (CS4235,CS4237B,CS4238B,CS4239) - * D3-D0: 3D Center (CS4237B); 3D Volume (CS4238B) - * - * C3 - * D7: 3D Enable (CS4237B) - * D6: 3D Mono Enable (CS4237B) - * D5: 3D Serial Output (CS4237B,CS4238B) - * D4: 3D Enable (CS4235,CS4238B,CS4239) - * - * C4 - * D7: consumer serial port enable (CS4237B,CS4238B) - * D6: channels status block reset (CS4237B,CS4238B) - * D5: user bit in sub-frame of digital audio data (CS4237B,CS4238B) - * D4: validity bit bit in sub-frame of digital audio data (CS4237B,CS4238B) - * - * C5 lower channel status (digital serial data description) (CS4237B,CS4238B) - * D7-D6: first two bits of category code - * D5: lock - * D4-D3: pre-emphasis (0 = none, 1 = 50/15us) - * D2: copy/copyright (0 = copy inhibited) - * D1: 0 = digital audio / 1 = non-digital audio - * - * C6 upper channel status (digital serial data description) (CS4237B,CS4238B) - * D7-D6: sample frequency (0 = 44.1kHz) - * D5: generation status (0 = no indication, 1 = original/commercially precaptureed data) - * D4-D0: category code (upper bits) - * - * C7 reserved (must write 0) - * - * C8 wavetable control - * D7: volume control interrupt enable (CS4235,CS4239) - * D6: hardware volume control format (CS4235,CS4239) - * D3: wavetable serial port enable (all chips) - * D2: DSP serial port switch (all chips) - * D1: disable MCLK (all chips) - * D0: force BRESET low (all chips) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * - */ - -static unsigned char snd_cs4236_ext_map[18] = { - /* CS4236_LEFT_LINE */ 0xff, - /* CS4236_RIGHT_LINE */ 0xff, - /* CS4236_LEFT_MIC */ 0xdf, - /* CS4236_RIGHT_MIC */ 0xdf, - /* CS4236_LEFT_MIX_CTRL */ 0xe0 | 0x18, - /* CS4236_RIGHT_MIX_CTRL */ 0xe0, - /* CS4236_LEFT_FM */ 0xbf, - /* CS4236_RIGHT_FM */ 0xbf, - /* CS4236_LEFT_DSP */ 0xbf, - /* CS4236_RIGHT_DSP */ 0xbf, - /* CS4236_RIGHT_LOOPBACK */ 0xbf, - /* CS4236_DAC_MUTE */ 0xe0, - /* CS4236_ADC_RATE */ 0x01, /* 48kHz */ - /* CS4236_DAC_RATE */ 0x01, /* 48kHz */ - /* CS4236_LEFT_MASTER */ 0xbf, - /* CS4236_RIGHT_MASTER */ 0xbf, - /* CS4236_LEFT_WAVE */ 0xbf, - /* CS4236_RIGHT_WAVE */ 0xbf -}; - -/* - * - */ - -static void snd_cs4236_ctrl_out(struct snd_wss *chip, - unsigned char reg, unsigned char val) -{ - outb(reg, chip->cport + 3); - outb(chip->cimage[reg] = val, chip->cport + 4); -} - -static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg) -{ - outb(reg, chip->cport + 3); - return inb(chip->cport + 4); -} - -/* - * PCM - */ - -#define CLOCKS 8 - -static struct snd_ratnum clocks[CLOCKS] = { - { .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 }, - { .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 }, - { .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 }, - { .num = 16934400, .den_min = 1058, .den_max = 1058, .den_step = 1 }, - { .num = 16934400, .den_min = 1764, .den_max = 1764, .den_step = 1 }, - { .num = 16934400, .den_min = 2117, .den_max = 2117, .den_step = 1 }, - { .num = 16934400, .den_min = 2558, .den_max = 2558, .den_step = 1 }, - { .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 } -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { - .nrats = CLOCKS, - .rats = clocks, -}; - -static int snd_cs4236_xrate(struct snd_pcm_runtime *runtime) -{ - return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); -} - -static unsigned char divisor_to_rate_register(unsigned int divisor) -{ - switch (divisor) { - case 353: return 1; - case 529: return 2; - case 617: return 3; - case 1058: return 4; - case 1764: return 5; - case 2117: return 6; - case 2558: return 7; - default: - if (divisor < 21 || divisor > 192) { - snd_BUG(); - return 192; - } - return divisor; - } -} - -static void snd_cs4236_playback_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char pdfr) -{ - unsigned long flags; - unsigned char rate = divisor_to_rate_register(params->rate_den); - - spin_lock_irqsave(&chip->reg_lock, flags); - /* set fast playback format change and clean playback FIFO */ - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | 0x10); - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] & ~0x10); - snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_cs4236_capture_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char cdfr) -{ - unsigned long flags; - unsigned char rate = divisor_to_rate_register(params->rate_den); - - spin_lock_irqsave(&chip->reg_lock, flags); - /* set fast capture format change and clean capture FIFO */ - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | 0x20); - snd_wss_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] & ~0x20); - snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -#ifdef CONFIG_PM - -static void snd_cs4236_suspend(struct snd_wss *chip) -{ - int reg; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) - chip->image[reg] = snd_wss_in(chip, reg); - for (reg = 0; reg < 18; reg++) - chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg)); - for (reg = 2; reg < 9; reg++) - chip->cimage[reg] = snd_cs4236_ctrl_in(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_cs4236_resume(struct snd_wss *chip) -{ - int reg; - unsigned long flags; - - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) { - switch (reg) { - case CS4236_EXT_REG: - case CS4231_VERSION: - case 27: /* why? CS4235 - master left */ - case 29: /* why? CS4235 - master right */ - break; - default: - snd_wss_out(chip, reg, chip->image[reg]); - break; - } - } - for (reg = 0; reg < 18; reg++) - snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), chip->eimage[reg]); - for (reg = 2; reg < 9; reg++) { - switch (reg) { - case 7: - break; - default: - snd_cs4236_ctrl_out(chip, reg, chip->cimage[reg]); - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); -} - -#endif /* CONFIG_PM */ -/* - * This function does no fail if the chip is not CS4236B or compatible. - * It just an equivalent to the snd_wss_create() then. - */ -int snd_cs4236_create(struct snd_card *card, - unsigned long port, - unsigned long cport, - int irq, int dma1, int dma2, - unsigned short hardware, - unsigned short hwshare, - struct snd_wss **rchip) -{ - struct snd_wss *chip; - unsigned char ver1, ver2; - unsigned int reg; - int err; - - *rchip = NULL; - if (hardware == WSS_HW_DETECT) - hardware = WSS_HW_DETECT3; - - err = snd_wss_create(card, port, cport, - irq, dma1, dma2, hardware, hwshare, &chip); - if (err < 0) - return err; - - if ((chip->hardware & WSS_HW_CS4236B_MASK) == 0) { - snd_printd("chip is not CS4236+, hardware=0x%x\n", - chip->hardware); - *rchip = chip; - return 0; - } -#if 0 - { - int idx; - for (idx = 0; idx < 8; idx++) - snd_printk(KERN_DEBUG "CD%i = 0x%x\n", - idx, inb(chip->cport + idx)); - for (idx = 0; idx < 9; idx++) - snd_printk(KERN_DEBUG "C%i = 0x%x\n", - idx, snd_cs4236_ctrl_in(chip, idx)); - } -#endif - if (cport < 0x100 || cport == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "please, specify control port " - "for CS4236+ chips\n"); - snd_device_free(card, chip); - return -ENODEV; - } - ver1 = snd_cs4236_ctrl_in(chip, 1); - ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION); - snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", - cport, ver1, ver2); - if (ver1 != ver2) { - snd_printk(KERN_ERR "CS4236+ chip detected, but " - "control port 0x%lx is not valid\n", cport); - snd_device_free(card, chip); - return -ENODEV; - } - snd_cs4236_ctrl_out(chip, 0, 0x00); - snd_cs4236_ctrl_out(chip, 2, 0xff); - snd_cs4236_ctrl_out(chip, 3, 0x00); - snd_cs4236_ctrl_out(chip, 4, 0x80); - reg = ((IEC958_AES1_CON_PCM_CODER & 3) << 6) | - IEC958_AES0_CON_EMPHASIS_NONE; - snd_cs4236_ctrl_out(chip, 5, reg); - snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2); - snd_cs4236_ctrl_out(chip, 7, 0x00); - /* - * 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958 - * output is working with this setup, other hardware should - * have different signal paths and this value should be - * selectable in the future - */ - snd_cs4236_ctrl_out(chip, 8, 0x8c); - chip->rate_constraint = snd_cs4236_xrate; - chip->set_playback_format = snd_cs4236_playback_format; - chip->set_capture_format = snd_cs4236_capture_format; -#ifdef CONFIG_PM - chip->suspend = snd_cs4236_suspend; - chip->resume = snd_cs4236_resume; -#endif - - /* initialize extended registers */ - for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++) - snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), - snd_cs4236_ext_map[reg]); - - /* initialize compatible but more featured registers */ - snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40); - snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40); - snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff); - snd_wss_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff); - snd_wss_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf); - snd_wss_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf); - snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff); - snd_wss_out(chip, CS4231_LEFT_LINE_IN, 0xff); - snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff); - switch (chip->hardware) { - case WSS_HW_CS4235: - case WSS_HW_CS4239: - snd_wss_out(chip, CS4235_LEFT_MASTER, 0xff); - snd_wss_out(chip, CS4235_RIGHT_MASTER, 0xff); - break; - } - - *rchip = chip; - return 0; -} - -int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - err = snd_wss_pcm(chip, device, &pcm); - if (err < 0) - return err; - pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX; - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* - * MIXER - */ - -#define CS4236_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_single, \ - .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -#define CS4236_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_single, \ - .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - -static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(reg)] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->eimage[CS4236_REG(reg)] & ~(mask << shift)) | val; - change = val != chip->eimage[CS4236_REG(reg)]; - snd_cs4236_ext_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4236_SINGLEC(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_single, \ - .get = snd_cs4236_get_singlec, .put = snd_cs4236_put_singlec, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->cimage[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->cimage[reg] & ~(mask << shift)) | val; - change = val != chip->cimage[reg]; - snd_cs4236_ctrl_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4236_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -#define CS4236_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, \ - shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ - (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(left_reg)] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - val1 = (chip->eimage[CS4236_REG(left_reg)] & ~(mask << shift_left)) | val1; - val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2; - change = val1 != chip->eimage[CS4236_REG(left_reg)] || val2 != chip->eimage[CS4236_REG(right_reg)]; - snd_cs4236_ext_out(chip, left_reg, val1); - snd_cs4236_ext_out(chip, right_reg, val2); - } else { - val1 = (chip->eimage[CS4236_REG(left_reg)] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != chip->eimage[CS4236_REG(left_reg)]; - snd_cs4236_ext_out(chip, left_reg, val1); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, \ - shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -#define CS4236_DOUBLE1_TLV(xname, xindex, left_reg, right_reg, shift_left, \ - shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ - (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; - val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2; - change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)]; - snd_wss_out(chip, left_reg, val1); - snd_cs4236_ext_out(chip, right_reg, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4236_MASTER_DIGITAL(xname, xindex, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \ - .private_value = 71 << 24, \ - .tlv = { .p = (xtlv) } } - -static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol) -{ - return (vol < 64) ? 63 - vol : 64 + (71 - vol); -} - -static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & 0x7f); - ucontrol->value.integer.value[1] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & 0x7f); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1, val2; - - val1 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[0] & 0x7f); - val2 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[1] & 0x7f); - spin_lock_irqsave(&chip->reg_lock, flags); - val1 = (chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & ~0x7f) | val1; - val2 = (chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & ~0x7f) | val2; - change = val1 != chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] || val2 != chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)]; - snd_cs4236_ext_out(chip, CS4236_LEFT_MASTER, val1); - snd_cs4236_ext_out(chip, CS4236_RIGHT_MASTER, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4235_OUTPUT_ACCU(xname, xindex, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \ - .private_value = 3 << 24, \ - .tlv = { .p = (xtlv) } } - -static inline int snd_cs4235_mixer_output_accu_get_volume(int vol) -{ - switch ((vol >> 5) & 3) { - case 0: return 1; - case 1: return 3; - case 2: return 2; - case 3: return 0; - } - return 3; -} - -static inline int snd_cs4235_mixer_output_accu_set_volume(int vol) -{ - switch (vol & 3) { - case 0: return 3 << 5; - case 1: return 0 << 5; - case 2: return 2 << 5; - case 3: return 1 << 5; - } - return 1 << 5; -} - -static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_LEFT_MASTER]); - ucontrol->value.integer.value[1] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_RIGHT_MASTER]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1, val2; - - val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]); - val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]); - spin_lock_irqsave(&chip->reg_lock, flags); - val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1; - val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2; - change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER]; - snd_wss_out(chip, CS4235_LEFT_MASTER, val1); - snd_wss_out(chip, CS4235_RIGHT_MASTER, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_6bit_12db_max, -8250, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_22db_max, -2400, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); - -static struct snd_kcontrol_new snd_cs4236_controls[] = { - -CS4236_DOUBLE("Master Digital Playback Switch", 0, - CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), -CS4236_DOUBLE("Master Digital Capture Switch", 0, - CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), -CS4236_MASTER_DIGITAL("Master Digital Volume", 0, db_scale_7bit), - -CS4236_DOUBLE_TLV("Capture Boost Volume", 0, - CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1, - db_scale_2bit), - -WSS_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), - -CS4236_DOUBLE("DSP Playback Switch", 0, - CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), -CS4236_DOUBLE_TLV("DSP Playback Volume", 0, - CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1, - db_scale_6bit), - -CS4236_DOUBLE("FM Playback Switch", 0, - CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), -CS4236_DOUBLE_TLV("FM Playback Volume", 0, - CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1, - db_scale_6bit), - -CS4236_DOUBLE("Wavetable Playback Switch", 0, - CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), -CS4236_DOUBLE_TLV("Wavetable Playback Volume", 0, - CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1, - db_scale_6bit_12db_max), - -WSS_DOUBLE("Synth Playback Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Synth Volume", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("Synth Capture Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), -WSS_DOUBLE("Synth Capture Bypass", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1), - -CS4236_DOUBLE("Mic Playback Switch", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), -CS4236_DOUBLE("Mic Capture Switch", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), -CS4236_DOUBLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, - 0, 0, 31, 1, db_scale_5bit_22db_max), -CS4236_DOUBLE("Mic Playback Boost (+20dB)", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), - -WSS_DOUBLE("Line Playback Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Line Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("Line Capture Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), -WSS_DOUBLE("Line Capture Bypass", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1), - -WSS_DOUBLE("CD Playback Switch", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("CD Volume", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("CD Capture Switch", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), - -CS4236_DOUBLE1("Mono Output Playback Switch", 0, - CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), -CS4236_DOUBLE1("Beep Playback Switch", 0, - CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), -WSS_SINGLE_TLV("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1, - db_scale_4bit), -WSS_SINGLE("Beep Bypass Playback Switch", 0, CS4231_MONO_CTRL, 5, 1, 0), - -WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, - 0, 0, 15, 0, db_scale_rec_gain), -WSS_DOUBLE("Analog Loopback Capture Switch", 0, - CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), - -WSS_SINGLE("Loopback Digital Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), -CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0, - CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1, - db_scale_6bit), -}; - -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0); - -static struct snd_kcontrol_new snd_cs4235_controls[] = { - -WSS_DOUBLE("Master Playback Switch", 0, - CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Master Playback Volume", 0, - CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1, - db_scale_5bit_6db_max), - -CS4235_OUTPUT_ACCU("Playback Volume", 0, db_scale_2bit_16db_max), - -WSS_DOUBLE("Synth Playback Switch", 1, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -WSS_DOUBLE("Synth Capture Switch", 1, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), -WSS_DOUBLE_TLV("Synth Volume", 1, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1, - db_scale_5bit_12db_max), - -CS4236_DOUBLE_TLV("Capture Volume", 0, - CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1, - db_scale_2bit), - -WSS_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE("PCM Capture Switch", 0, - CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), -WSS_DOUBLE_TLV("PCM Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), - -CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), - -CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), - -CS4236_DOUBLE("Wavetable Switch", 0, - CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), - -CS4236_DOUBLE("Mic Capture Switch", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), -CS4236_DOUBLE("Mic Playback Switch", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), -CS4236_SINGLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1, - db_scale_5bit_22db_max), -CS4236_SINGLE("Mic Boost (+20dB)", 0, CS4236_LEFT_MIC, 5, 1, 0), - -WSS_DOUBLE("Line Playback Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE("Line Capture Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), -WSS_DOUBLE_TLV("Line Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), - -WSS_DOUBLE("CD Playback Switch", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE("CD Capture Switch", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), -WSS_DOUBLE_TLV("CD Volume", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), - -CS4236_DOUBLE1("Beep Playback Switch", 0, - CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), -WSS_SINGLE("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), - -WSS_DOUBLE("Analog Loopback Switch", 0, - CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), -}; - -#define CS4236_IEC958_ENABLE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_single, \ - .get = snd_cs4236_get_iec958_switch, .put = snd_cs4236_put_iec958_switch, \ - .private_value = 1 << 16 } - -static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; -#if 0 - printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " - "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", - snd_wss_in(chip, CS4231_ALT_FEATURE_1), - snd_cs4236_ctrl_in(chip, 3), - snd_cs4236_ctrl_in(chip, 4), - snd_cs4236_ctrl_in(chip, 5), - snd_cs4236_ctrl_in(chip, 6), - snd_cs4236_ctrl_in(chip, 8)); -#endif - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short enable, val; - - enable = ucontrol->value.integer.value[0] & 1; - - mutex_lock(&chip->mce_mutex); - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1); - change = val != chip->image[CS4231_ALT_FEATURE_1]; - snd_wss_out(chip, CS4231_ALT_FEATURE_1, val); - val = snd_cs4236_ctrl_in(chip, 4) | 0xc0; - snd_cs4236_ctrl_out(chip, 4, val); - udelay(100); - val &= ~0x40; - snd_cs4236_ctrl_out(chip, 4, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - mutex_unlock(&chip->mce_mutex); - -#if 0 - printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " - "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", - snd_wss_in(chip, CS4231_ALT_FEATURE_1), - snd_cs4236_ctrl_in(chip, 3), - snd_cs4236_ctrl_in(chip, 4), - snd_cs4236_ctrl_in(chip, 5), - snd_cs4236_ctrl_in(chip, 6), - snd_cs4236_ctrl_in(chip, 8)); -#endif - return change; -} - -static struct snd_kcontrol_new snd_cs4236_iec958_controls[] = { -CS4236_IEC958_ENABLE("IEC958 Output Enable", 0), -CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0), -CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0), -CS4236_SINGLEC("IEC958 Output CSBR", 0, 4, 6, 1, 0), -CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0), -CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0) -}; - -static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4235[] = { -CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0), -CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1) -}; - -static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4237[] = { -CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0), -CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1), -CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1), -CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0), -CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0) -}; - -static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4238[] = { -CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0), -CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1), -CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1), -CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0) -}; - -int snd_cs4236_mixer(struct snd_wss *chip) -{ - struct snd_card *card; - unsigned int idx, count; - int err; - struct snd_kcontrol_new *kcontrol; - - if (snd_BUG_ON(!chip || !chip->card)) - return -EINVAL; - card = chip->card; - strcpy(card->mixername, snd_wss_chip_id(chip)); - - if (chip->hardware == WSS_HW_CS4235 || - chip->hardware == WSS_HW_CS4239) { - for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0) - return err; - } - } else { - for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0) - return err; - } - } - switch (chip->hardware) { - case WSS_HW_CS4235: - case WSS_HW_CS4239: - count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235); - kcontrol = snd_cs4236_3d_controls_cs4235; - break; - case WSS_HW_CS4237B: - count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237); - kcontrol = snd_cs4236_3d_controls_cs4237; - break; - case WSS_HW_CS4238B: - count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238); - kcontrol = snd_cs4236_3d_controls_cs4238; - break; - default: - count = 0; - kcontrol = NULL; - } - for (idx = 0; idx < count; idx++, kcontrol++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0) - return err; - } - if (chip->hardware == WSS_HW_CS4237B || - chip->hardware == WSS_HW_CS4238B) { - for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0) - return err; - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/es1688/Makefile b/ANDROID_3.4.5/sound/isa/es1688/Makefile deleted file mode 100644 index aee1e4dd..00000000 --- a/ANDROID_3.4.5/sound/isa/es1688/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-es1688-lib-objs := es1688_lib.o -snd-es1688-objs := es1688.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_ES1688) += snd-es1688.o snd-es1688-lib.o -obj-$(CONFIG_SND_GUSEXTREME) += snd-es1688-lib.o diff --git a/ANDROID_3.4.5/sound/isa/es1688/es1688.c b/ANDROID_3.4.5/sound/isa/es1688/es1688.c deleted file mode 100644 index b036e60f..00000000 --- a/ANDROID_3.4.5/sound/isa/es1688/es1688.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Driver for generic ESS AudioDrive ESx688 soundcards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -#define CRD_NAME "Generic ESS ES1688/ES688 AudioDrive" -#define DEV_NAME "es1688" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100}," - "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102}," - "{ESS,ES688 AudioDrive,pnp:ESS6881}," - "{ESS,ES1688 AudioDrive,pnp:ESS1681}}"); - -MODULE_ALIAS("snd_es968"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; -#endif -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* Usually 0x388 */ -static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for ES1688 driver."); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver."); - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -static int __devinit snd_es1688_match(struct device *dev, unsigned int n) -{ - return enable[n] && !is_isapnp_selected(n); -} - -static int __devinit snd_es1688_legacy_create(struct snd_card *card, - struct device *dev, unsigned int n) -{ - struct snd_es1688 *chip = card->private_data; - static long possible_ports[] = {0x220, 0x240, 0x260}; - static int possible_irqs[] = {5, 9, 10, 7, -1}; - static int possible_dmas[] = {1, 3, 0, -1}; - - int i, error; - - if (irq[n] == SNDRV_AUTO_IRQ) { - irq[n] = snd_legacy_find_free_irq(possible_irqs); - if (irq[n] < 0) { - dev_err(dev, "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma8[n] == SNDRV_AUTO_DMA) { - dma8[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma8[n] < 0) { - dev_err(dev, "unable to find a free DMA\n"); - return -EBUSY; - } - } - - if (port[n] != SNDRV_AUTO_PORT) - return snd_es1688_create(card, chip, port[n], mpu_port[n], - irq[n], mpu_irq[n], dma8[n], ES1688_HW_AUTO); - - i = 0; - do { - port[n] = possible_ports[i]; - error = snd_es1688_create(card, chip, port[n], mpu_port[n], - irq[n], mpu_irq[n], dma8[n], ES1688_HW_AUTO); - } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); - - return error; -} - -static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n) -{ - struct snd_es1688 *chip = card->private_data; - struct snd_opl3 *opl3; - struct snd_pcm *pcm; - int error; - - error = snd_es1688_pcm(card, chip, 0, &pcm); - if (error < 0) - return error; - - error = snd_es1688_mixer(card, chip); - if (error < 0) - return error; - - strlcpy(card->driver, "ES1688", sizeof(card->driver)); - strlcpy(card->shortname, pcm->name, sizeof(card->shortname)); - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, - chip->irq, chip->dma8); - - if (fm_port[n] == SNDRV_AUTO_PORT) - fm_port[n] = port[n]; /* share the same port */ - - if (fm_port[n] > 0) { - if (snd_opl3_create(card, fm_port[n], fm_port[n] + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) - dev_warn(card->dev, - "opl3 not detected at 0x%lx\n", fm_port[n]); - else { - error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (error < 0) - return error; - } - } - - if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ && - chip->mpu_port > 0) { - error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, - chip->mpu_port, 0, - mpu_irq[n], NULL); - if (error < 0) - return error; - } - - return snd_card_register(card); -} - -static int __devinit snd_es1688_isa_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, - sizeof(struct snd_es1688), &card); - if (error < 0) - return error; - - error = snd_es1688_legacy_create(card, dev, n); - if (error < 0) - goto out; - - snd_card_set_dev(card, dev); - - error = snd_es1688_probe(card, n); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - - return 0; -out: - snd_card_free(card); - return error; -} - -static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_es1688_driver = { - .match = snd_es1688_match, - .probe = snd_es1688_isa_probe, - .remove = __devexit_p(snd_es1688_isa_remove), -#if 0 /* FIXME */ - .suspend = snd_es1688_suspend, - .resume = snd_es1688_resume, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int snd_es968_pnp_is_probed; - -#ifdef CONFIG_PNP -static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n, - struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - struct snd_es1688 *chip = card->private_data; - struct pnp_dev *pdev; - int error; - - pdev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); - if (pdev == NULL) - return -ENODEV; - - error = pnp_activate_dev(pdev); - if (error < 0) { - snd_printk(KERN_ERR "ES968 pnp configure failure\n"); - return error; - } - port[n] = pnp_port_start(pdev, 0); - dma8[n] = pnp_dma(pdev, 0); - irq[n] = pnp_irq(pdev, 0); - - return snd_es1688_create(card, chip, port[n], mpu_port[n], irq[n], - mpu_irq[n], dma8[n], ES1688_HW_AUTO); -} - -static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - struct snd_card *card; - static unsigned int dev; - int error; - struct snd_es1688 *chip; - - if (snd_es968_pnp_is_probed) - return -EBUSY; - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev == SNDRV_CARDS) - return -ENODEV; - - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_es1688), &card); - if (error < 0) - return error; - chip = card->private_data; - - error = snd_card_es968_pnp(card, dev, pcard, pid); - if (error < 0) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - error = snd_es1688_probe(card, dev); - if (error < 0) - return error; - pnp_set_card_drvdata(pcard, card); - snd_es968_pnp_is_probed = 1; - return 0; -} - -static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); - snd_es968_pnp_is_probed = 0; -} - -#ifdef CONFIG_PM -static int snd_es968_pnp_suspend(struct pnp_card_link *pcard, - pm_message_t state) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_es1688 *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - return 0; -} - -static int snd_es968_pnp_resume(struct pnp_card_link *pcard) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_es1688 *chip = card->private_data; - - snd_es1688_reset(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pnp_card_device_id snd_es968_pnpids[] = { - { .id = "ESS0968", .devs = { { "@@@0968" }, } }, - { .id = "ESS0968", .devs = { { "ESS0968" }, } }, - { .id = "", } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids); - -static struct pnp_card_driver es968_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = DEV_NAME " PnP", - .id_table = snd_es968_pnpids, - .probe = snd_es968_pnp_detect, - .remove = __devexit_p(snd_es968_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_es968_pnp_suspend, - .resume = snd_es968_pnp_resume, -#endif -}; -#endif - -static int __init alsa_card_es1688_init(void) -{ -#ifdef CONFIG_PNP - pnp_register_card_driver(&es968_pnpc_driver); - if (snd_es968_pnp_is_probed) - return 0; - pnp_unregister_card_driver(&es968_pnpc_driver); -#endif - return isa_register_driver(&snd_es1688_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_es1688_exit(void) -{ - if (!snd_es968_pnp_is_probed) { - isa_unregister_driver(&snd_es1688_driver); - return; - } -#ifdef CONFIG_PNP - pnp_unregister_card_driver(&es968_pnpc_driver); -#endif -} - -module_init(alsa_card_es1688_init); -module_exit(alsa_card_es1688_exit); diff --git a/ANDROID_3.4.5/sound/isa/es1688/es1688_lib.c b/ANDROID_3.4.5/sound/isa/es1688/es1688_lib.c deleted file mode 100644 index 1d47be81..00000000 --- a/ANDROID_3.4.5/sound/isa/es1688/es1688_lib.c +++ /dev/null @@ -1,1046 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of ESS ES1688/688/488 chip - * - * - * 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 - -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("ESS ESx688 lowlevel module"); -MODULE_LICENSE("GPL"); - -static int snd_es1688_dsp_command(struct snd_es1688 *chip, unsigned char val) -{ - int i; - - for (i = 10000; i; i--) - if ((inb(ES1688P(chip, STATUS)) & 0x80) == 0) { - outb(val, ES1688P(chip, COMMAND)); - return 1; - } -#ifdef CONFIG_SND_DEBUG - printk(KERN_DEBUG "snd_es1688_dsp_command: timeout (0x%x)\n", val); -#endif - return 0; -} - -static int snd_es1688_dsp_get_byte(struct snd_es1688 *chip) -{ - int i; - - for (i = 1000; i; i--) - if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) - return inb(ES1688P(chip, READ)); - snd_printd("es1688 get byte failed: 0x%lx = 0x%x!!!\n", ES1688P(chip, DATA_AVAIL), inb(ES1688P(chip, DATA_AVAIL))); - return -ENODEV; -} - -static int snd_es1688_write(struct snd_es1688 *chip, - unsigned char reg, unsigned char data) -{ - if (!snd_es1688_dsp_command(chip, reg)) - return 0; - return snd_es1688_dsp_command(chip, data); -} - -static int snd_es1688_read(struct snd_es1688 *chip, unsigned char reg) -{ - /* Read a byte from an extended mode register of ES1688 */ - if (!snd_es1688_dsp_command(chip, 0xc0)) - return -1; - if (!snd_es1688_dsp_command(chip, reg)) - return -1; - return snd_es1688_dsp_get_byte(chip); -} - -void snd_es1688_mixer_write(struct snd_es1688 *chip, - unsigned char reg, unsigned char data) -{ - outb(reg, ES1688P(chip, MIXER_ADDR)); - udelay(10); - outb(data, ES1688P(chip, MIXER_DATA)); - udelay(10); -} - -static unsigned char snd_es1688_mixer_read(struct snd_es1688 *chip, unsigned char reg) -{ - unsigned char result; - - outb(reg, ES1688P(chip, MIXER_ADDR)); - udelay(10); - result = inb(ES1688P(chip, MIXER_DATA)); - udelay(10); - return result; -} - -int snd_es1688_reset(struct snd_es1688 *chip) -{ - int i; - - outb(3, ES1688P(chip, RESET)); /* valid only for ESS chips, SB -> 1 */ - udelay(10); - outb(0, ES1688P(chip, RESET)); - udelay(30); - for (i = 0; i < 1000 && !(inb(ES1688P(chip, DATA_AVAIL)) & 0x80); i++); - if (inb(ES1688P(chip, READ)) != 0xaa) { - snd_printd("ess_reset at 0x%lx: failed!!!\n", chip->port); - return -ENODEV; - } - snd_es1688_dsp_command(chip, 0xc6); /* enable extended mode */ - return 0; -} -EXPORT_SYMBOL(snd_es1688_reset); - -static int snd_es1688_probe(struct snd_es1688 *chip) -{ - unsigned long flags; - unsigned short major, minor, hw; - int i; - - /* - * initialization sequence - */ - - spin_lock_irqsave(&chip->reg_lock, flags); /* Some ESS1688 cards need this */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE0)); /* ENABLE0 */ - - if (snd_es1688_reset(chip) < 0) { - snd_printdd("ESS: [0x%lx] reset failed... 0x%x\n", chip->port, inb(ES1688P(chip, READ))); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; - } - snd_es1688_dsp_command(chip, 0xe7); /* return identification */ - - for (i = 1000, major = minor = 0; i; i--) { - if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) { - if (major == 0) { - major = inb(ES1688P(chip, READ)); - } else { - minor = inb(ES1688P(chip, READ)); - } - } - } - - spin_unlock_irqrestore(&chip->reg_lock, flags); - - snd_printdd("ESS: [0x%lx] found.. major = 0x%x, minor = 0x%x\n", chip->port, major, minor); - - chip->version = (major << 8) | minor; - if (!chip->version) - return -ENODEV; /* probably SB */ - - hw = ES1688_HW_AUTO; - switch (chip->version & 0xfff0) { - case 0x4880: - snd_printk(KERN_ERR "[0x%lx] ESS: AudioDrive ES488 detected, " - "but driver is in another place\n", chip->port); - return -ENODEV; - case 0x6880: - hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688; - break; - default: - snd_printk(KERN_ERR "[0x%lx] ESS: unknown AudioDrive chip " - "with version 0x%x (Jazz16 soundcard?)\n", - chip->port, chip->version); - return -ENODEV; - } - - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */ - snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */ - spin_unlock_irqrestore(&chip->reg_lock, flags); - - /* enable joystick, but disable OPL3 */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_es1688_mixer_write(chip, 0x40, 0x01); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - - return 0; -} - -static int snd_es1688_init(struct snd_es1688 * chip, int enable) -{ - static int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1}; - unsigned long flags; - int cfg, irq_bits, dma, dma_bits, tmp, tmp1; - - /* ok.. setup MPU-401 port and joystick and OPL3 */ - cfg = 0x01; /* enable joystick, but disable OPL3 */ - if (enable && chip->mpu_port >= 0x300 && chip->mpu_irq > 0 && chip->hardware != ES1688_HW_688) { - tmp = (chip->mpu_port & 0x0f0) >> 4; - if (tmp <= 3) { - switch (chip->mpu_irq) { - case 9: - tmp1 = 4; - break; - case 5: - tmp1 = 5; - break; - case 7: - tmp1 = 6; - break; - case 10: - tmp1 = 7; - break; - default: - tmp1 = 0; - } - if (tmp1) { - cfg |= (tmp << 3) | (tmp1 << 5); - } - } - } -#if 0 - snd_printk(KERN_DEBUG "mpu cfg = 0x%x\n", cfg); -#endif - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_mixer_write(chip, 0x40, cfg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - /* --- */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_read(chip, 0xb1); - snd_es1688_read(chip, 0xb2); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (enable) { - cfg = 0xf0; /* enable only DMA counter interrupt */ - irq_bits = irqs[chip->irq & 0x0f]; - if (irq_bits < 0) { - snd_printk(KERN_ERR "[0x%lx] ESS: bad IRQ %d " - "for ES1688 chip!!\n", - chip->port, chip->irq); -#if 0 - irq_bits = 0; - cfg = 0x10; -#endif - return -EINVAL; - } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, cfg | (irq_bits << 2)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - cfg = 0xf0; /* extended mode DMA enable */ - dma = chip->dma8; - if (dma > 3 || dma == 2) { - snd_printk(KERN_ERR "[0x%lx] ESS: bad DMA channel %d " - "for ES1688 chip!!\n", chip->port, dma); -#if 0 - dma_bits = 0; - cfg = 0x00; /* disable all DMA */ -#endif - return -EINVAL; - } else { - dma_bits = dma; - if (dma != 3) - dma_bits++; - } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb2, cfg | (dma_bits << 2)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - } else { - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */ - snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */ - spin_unlock_irqrestore(&chip->reg_lock, flags); - } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_read(chip, 0xb1); - snd_es1688_read(chip, 0xb2); - snd_es1688_reset(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -/* - - */ - -static struct snd_ratnum clocks[2] = { - { - .num = 795444, - .den_min = 1, - .den_max = 128, - .den_step = 1, - }, - { - .num = 397722, - .den_min = 1, - .den_max = 128, - .den_step = 1, - } -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { - .nrats = 2, - .rats = clocks, -}; - -static void snd_es1688_set_rate(struct snd_es1688 *chip, struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int bits, divider; - - if (runtime->rate_num == clocks[0].num) - bits = 256 - runtime->rate_den; - else - bits = 128 - runtime->rate_den; - /* set filter register */ - divider = 256 - 7160000*20/(8*82*runtime->rate); - /* write result to hardware */ - snd_es1688_write(chip, 0xa1, bits); - snd_es1688_write(chip, 0xa2, divider); -} - -static int snd_es1688_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char value) -{ - int val; - - if (cmd == SNDRV_PCM_TRIGGER_STOP) { - value = 0x00; - } else if (cmd != SNDRV_PCM_TRIGGER_START) { - return -EINVAL; - } - spin_lock(&chip->reg_lock); - chip->trigger_value = value; - val = snd_es1688_read(chip, 0xb8); - if ((val < 0) || (val & 0x0f) == value) { - spin_unlock(&chip->reg_lock); - return -EINVAL; /* something is wrong */ - } -#if 0 - printk(KERN_DEBUG "trigger: val = 0x%x, value = 0x%x\n", val, value); - printk(KERN_DEBUG "trigger: pointer = 0x%x\n", - snd_dma_pointer(chip->dma8, chip->dma_size)); -#endif - snd_es1688_write(chip, 0xb8, (val & 0xf0) | value); - spin_unlock(&chip->reg_lock); - return 0; -} - -static int snd_es1688_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_es1688_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_es1688_playback_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->dma_size = size; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_reset(chip); - snd_es1688_set_rate(chip, substream); - snd_es1688_write(chip, 0xb8, 4); /* auto init DMA mode */ - snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); - snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ - if (runtime->channels == 1) { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit mono */ - snd_es1688_write(chip, 0xb6, 0x80); - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0xd0); - } else { - /* 16. bit mono */ - snd_es1688_write(chip, 0xb6, 0x00); - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xf4); - } - } else { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit stereo */ - snd_es1688_write(chip, 0xb6, 0x80); - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0x98); - } else { - /* 16. bit stereo */ - snd_es1688_write(chip, 0xb6, 0x00); - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xbc); - } - } - snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); - snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); - snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKON); - spin_unlock_irqrestore(&chip->reg_lock, flags); - /* --- */ - count = -count; - snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xa4, (unsigned char) count); - snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_es1688_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - return snd_es1688_trigger(chip, cmd, 0x05); -} - -static int snd_es1688_capture_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->dma_size = size; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_reset(chip); - snd_es1688_set_rate(chip, substream); - snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKOFF); - snd_es1688_write(chip, 0xb8, 0x0e); /* auto init DMA mode */ - snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); - snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ - if (runtime->channels == 1) { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit mono */ - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0xd0); - } else { - /* 16. bit mono */ - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xf4); - } - } else { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit stereo */ - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0x98); - } else { - /* 16. bit stereo */ - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xbc); - } - } - snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); - snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); - spin_unlock_irqrestore(&chip->reg_lock, flags); - /* --- */ - count = -count; - snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xa4, (unsigned char) count); - snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_es1688_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - return snd_es1688_trigger(chip, cmd, 0x0f); -} - -static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id) -{ - struct snd_es1688 *chip = dev_id; - - if (chip->trigger_value == 0x05) /* ok.. playback is active */ - snd_pcm_period_elapsed(chip->playback_substream); - if (chip->trigger_value == 0x0f) /* ok.. capture is active */ - snd_pcm_period_elapsed(chip->capture_substream); - - inb(ES1688P(chip, DATA_AVAIL)); /* ack interrupt */ - return IRQ_HANDLED; -} - -static snd_pcm_uframes_t snd_es1688_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (chip->trigger_value != 0x05) - return 0; - ptr = snd_dma_pointer(chip->dma8, chip->dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_es1688_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (chip->trigger_value != 0x0f) - return 0; - ptr = snd_dma_pointer(chip->dma8, chip->dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -/* - - */ - -static struct snd_pcm_hardware snd_es1688_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_es1688_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - - */ - -static int snd_es1688_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (chip->capture_substream != NULL) - return -EAGAIN; - chip->playback_substream = substream; - runtime->hw = snd_es1688_playback; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); - return 0; -} - -static int snd_es1688_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (chip->playback_substream != NULL) - return -EAGAIN; - chip->capture_substream = substream; - runtime->hw = snd_es1688_capture; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); - return 0; -} - -static int snd_es1688_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - return 0; -} - -static int snd_es1688_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - return 0; -} - -static int snd_es1688_free(struct snd_es1688 *chip) -{ - if (chip->res_port) { - snd_es1688_init(chip, 0); - release_and_free_resource(chip->res_port); - } - if (chip->irq >= 0) - free_irq(chip->irq, (void *) chip); - if (chip->dma8 >= 0) { - disable_dma(chip->dma8); - free_dma(chip->dma8); - } - return 0; -} - -static int snd_es1688_dev_free(struct snd_device *device) -{ - struct snd_es1688 *chip = device->device_data; - return snd_es1688_free(chip); -} - -static const char *snd_es1688_chip_id(struct snd_es1688 *chip) -{ - static char tmp[16]; - sprintf(tmp, "ES%s688 rev %i", chip->hardware == ES1688_HW_688 ? "" : "1", chip->version & 0x0f); - return tmp; -} - -int snd_es1688_create(struct snd_card *card, - struct snd_es1688 *chip, - unsigned long port, - unsigned long mpu_port, - int irq, - int mpu_irq, - int dma8, - unsigned short hardware) -{ - static struct snd_device_ops ops = { - .dev_free = snd_es1688_dev_free, - }; - - int err; - - if (chip == NULL) - return -ENOMEM; - chip->irq = -1; - chip->dma8 = -1; - - if ((chip->res_port = request_region(port + 4, 12, "ES1688")) == NULL) { - snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4); - return -EBUSY; - } - if (request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip)) { - snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq); - return -EBUSY; - } - chip->irq = irq; - if (request_dma(dma8, "ES1688")) { - snd_printk(KERN_ERR "es1688: can't grab DMA8 %d\n", dma8); - return -EBUSY; - } - chip->dma8 = dma8; - - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->mixer_lock); - chip->port = port; - mpu_port &= ~0x000f; - if (mpu_port < 0x300 || mpu_port > 0x330) - mpu_port = 0; - chip->mpu_port = mpu_port; - chip->mpu_irq = mpu_irq; - chip->hardware = hardware; - - err = snd_es1688_probe(chip); - if (err < 0) - return err; - - err = snd_es1688_init(chip, 1); - if (err < 0) - return err; - - /* Register device */ - return snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); -} - -static struct snd_pcm_ops snd_es1688_playback_ops = { - .open = snd_es1688_playback_open, - .close = snd_es1688_playback_close, - .ioctl = snd_es1688_ioctl, - .hw_params = snd_es1688_hw_params, - .hw_free = snd_es1688_hw_free, - .prepare = snd_es1688_playback_prepare, - .trigger = snd_es1688_playback_trigger, - .pointer = snd_es1688_playback_pointer, -}; - -static struct snd_pcm_ops snd_es1688_capture_ops = { - .open = snd_es1688_capture_open, - .close = snd_es1688_capture_close, - .ioctl = snd_es1688_ioctl, - .hw_params = snd_es1688_hw_params, - .hw_free = snd_es1688_hw_free, - .prepare = snd_es1688_capture_prepare, - .trigger = snd_es1688_capture_trigger, - .pointer = snd_es1688_capture_pointer, -}; - -int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, - int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(card, "ESx688", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1688_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1688_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - sprintf(pcm->name, snd_es1688_chip_id(chip)); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, 64*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* - * MIXER part - */ - -static int snd_es1688_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[9] = { - "Mic", "Mic Master", "CD", "AOUT", - "Mic1", "Mix", "Line", "Master" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item > 7) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_es1688_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = snd_es1688_mixer_read(chip, ES1688_REC_DEV) & 7; - return 0; -} - -static int snd_es1688_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char oval, nval; - int change; - - if (ucontrol->value.enumerated.item[0] > 8) - return -EINVAL; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = snd_es1688_mixer_read(chip, ES1688_REC_DEV); - nval = (ucontrol->value.enumerated.item[0] & 7) | (oval & ~15); - change = nval != oval; - if (change) - snd_es1688_mixer_write(chip, ES1688_REC_DEV, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define ES1688_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es1688_info_single, \ - .get = snd_es1688_get_single, .put = snd_es1688_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_es1688_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es1688_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (snd_es1688_mixer_read(chip, reg) >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_es1688_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned char oval, nval; - - nval = (ucontrol->value.integer.value[0] & mask); - if (invert) - nval = mask - nval; - nval <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = snd_es1688_mixer_read(chip, reg); - nval = (oval & ~(mask << shift)) | nval; - change = nval != oval; - if (change) - snd_es1688_mixer_write(chip, reg, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define ES1688_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es1688_info_double, \ - .get = snd_es1688_get_double, .put = snd_es1688_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -static int snd_es1688_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - unsigned char left, right; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg < 0xa0) - left = snd_es1688_mixer_read(chip, left_reg); - else - left = snd_es1688_read(chip, left_reg); - if (left_reg != right_reg) { - if (right_reg < 0xa0) - right = snd_es1688_mixer_read(chip, right_reg); - else - right = snd_es1688_read(chip, right_reg); - } else - right = left; - spin_unlock_irqrestore(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (left >> shift_left) & mask; - ucontrol->value.integer.value[1] = (right >> shift_right) & mask; - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned char val1, val2, oval1, oval2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - if (left_reg < 0xa0) - oval1 = snd_es1688_mixer_read(chip, left_reg); - else - oval1 = snd_es1688_read(chip, left_reg); - if (right_reg < 0xa0) - oval2 = snd_es1688_mixer_read(chip, right_reg); - else - oval2 = snd_es1688_read(chip, right_reg); - val1 = (oval1 & ~(mask << shift_left)) | val1; - val2 = (oval2 & ~(mask << shift_right)) | val2; - change = val1 != oval1 || val2 != oval2; - if (change) { - if (left_reg < 0xa0) - snd_es1688_mixer_write(chip, left_reg, val1); - else - snd_es1688_write(chip, left_reg, val1); - if (right_reg < 0xa0) - snd_es1688_mixer_write(chip, right_reg, val1); - else - snd_es1688_write(chip, right_reg, val1); - } - } else { - if (left_reg < 0xa0) - oval1 = snd_es1688_mixer_read(chip, left_reg); - else - oval1 = snd_es1688_read(chip, left_reg); - val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != oval1; - if (change) { - if (left_reg < 0xa0) - snd_es1688_mixer_write(chip, left_reg, val1); - else - snd_es1688_write(chip, left_reg, val1); - } - - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_es1688_controls[] = { -ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("Line Playback Volume", 0, ES1688_LINE_DEV, ES1688_LINE_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("CD Playback Volume", 0, ES1688_CD_DEV, ES1688_CD_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0), -ES1688_SINGLE("Beep Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0), -ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0), -ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_es1688_info_mux, - .get = snd_es1688_get_mux, - .put = snd_es1688_put_mux, -}, -}; - -#define ES1688_INIT_TABLE_SIZE (sizeof(snd_es1688_init_table)/2) - -static unsigned char snd_es1688_init_table[][2] = { - { ES1688_MASTER_DEV, 0 }, - { ES1688_PCM_DEV, 0 }, - { ES1688_LINE_DEV, 0 }, - { ES1688_CD_DEV, 0 }, - { ES1688_FM_DEV, 0 }, - { ES1688_MIC_DEV, 0 }, - { ES1688_AUX_DEV, 0 }, - { ES1688_SPEAKER_DEV, 0 }, - { ES1688_RECLEV_DEV, 0 }, - { ES1688_REC_DEV, 0x17 } -}; - -int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip) -{ - unsigned int idx; - int err; - unsigned char reg, val; - - if (snd_BUG_ON(!chip || !card)) - return -EINVAL; - - strcpy(card->mixername, snd_es1688_chip_id(chip)); - - for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0) - return err; - } - for (idx = 0; idx < ES1688_INIT_TABLE_SIZE; idx++) { - reg = snd_es1688_init_table[idx][0]; - val = snd_es1688_init_table[idx][1]; - if (reg < 0xa0) - snd_es1688_mixer_write(chip, reg, val); - else - snd_es1688_write(chip, reg, val); - } - return 0; -} - -EXPORT_SYMBOL(snd_es1688_mixer_write); -EXPORT_SYMBOL(snd_es1688_create); -EXPORT_SYMBOL(snd_es1688_pcm); -EXPORT_SYMBOL(snd_es1688_mixer); - -/* - * INIT part - */ - -static int __init alsa_es1688_init(void) -{ - return 0; -} - -static void __exit alsa_es1688_exit(void) -{ -} - -module_init(alsa_es1688_init) -module_exit(alsa_es1688_exit) diff --git a/ANDROID_3.4.5/sound/isa/es18xx.c b/ANDROID_3.4.5/sound/isa/es18xx.c deleted file mode 100644 index c20baafd..00000000 --- a/ANDROID_3.4.5/sound/isa/es18xx.c +++ /dev/null @@ -1,2434 +0,0 @@ -/* - * Driver for generic ESS AudioDrive ES18xx soundcards - * Copyright (c) by Christian Fischbach - * Copyright (c) by Abramo Bagnara - * - * - * 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 - * - */ -/* GENERAL NOTES: - * - * BUGS: - * - There are pops (we can't delay in trigger function, cause midlevel - * often need to trigger down and then up very quickly). - * Any ideas? - * - Support for 16 bit DMA seems to be broken. I've no hardware to tune it. - */ - -/* - * ES1868 NOTES: - * - The chip has one half duplex pcm (with very limited full duplex support). - * - * - Duplex stereophonic sound is impossible. - * - Record and playback must share the same frequency rate. - * - * - The driver use dma2 for playback and dma1 for capture. - */ - -/* - * ES1869 NOTES: - * - * - there are a first full duplex pcm and a second playback only pcm - * (incompatible with first pcm capture) - * - * - there is support for the capture volume and ESS Spatializer 3D effect. - * - * - contrarily to some pages in DS_1869.PDF the rates can be set - * independently. - * - * - Zoom Video is implemented by sharing the FM DAC, thus the user can - * have either FM playback or Video playback but not both simultaneously. - * The Video Playback Switch mixer control toggles this choice. - * - * BUGS: - * - * - There is a major trouble I noted: - * - * using both channel for playback stereo 16 bit samples at 44100 Hz - * the second pcm (Audio1) DMA slows down irregularly and sound is garbled. - * - * The same happens using Audio1 for captureing. - * - * The Windows driver does not suffer of this (although it use Audio1 - * only for captureing). I'm unable to discover why. - * - */ - -/* - * ES1879 NOTES: - * - When Zoom Video is enabled (reg 0x71 bit 6 toggled on) the PCM playback - * seems to be effected (speaker_test plays a lower frequency). Can't find - * anything in the datasheet to account for this, so a Video Playback Switch - * control has been included to allow ZV to be enabled only when necessary. - * Then again on at least one test system the 0x71 bit 6 enable bit is not - * needed for ZV, so maybe the datasheet is entirely wrong here. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -#define PFX "es18xx: " - -struct snd_es18xx { - unsigned long port; /* port of ESS chip */ - unsigned long ctrl_port; /* Control port of ESS chip */ - struct resource *res_port; - struct resource *res_mpu_port; - struct resource *res_ctrl_port; - int irq; /* IRQ number of ESS chip */ - int dma1; /* DMA1 */ - int dma2; /* DMA2 */ - unsigned short version; /* version of ESS chip */ - int caps; /* Chip capabilities */ - unsigned short audio2_vol; /* volume level of audio2 */ - - unsigned short active; /* active channel mask */ - unsigned int dma1_shift; - unsigned int dma2_shift; - - struct snd_pcm *pcm; - struct snd_pcm_substream *playback_a_substream; - struct snd_pcm_substream *capture_a_substream; - struct snd_pcm_substream *playback_b_substream; - - struct snd_rawmidi *rmidi; - - struct snd_kcontrol *hw_volume; - struct snd_kcontrol *hw_switch; - struct snd_kcontrol *master_volume; - struct snd_kcontrol *master_switch; - - spinlock_t reg_lock; - spinlock_t mixer_lock; -#ifdef CONFIG_PM - unsigned char pm_reg; -#endif -#ifdef CONFIG_PNP - struct pnp_dev *dev; - struct pnp_dev *devc; -#endif -}; - -#define AUDIO1_IRQ 0x01 -#define AUDIO2_IRQ 0x02 -#define HWV_IRQ 0x04 -#define MPU_IRQ 0x08 - -#define ES18XX_PCM2 0x0001 /* Has two useable PCM */ -#define ES18XX_SPATIALIZER 0x0002 /* Has 3D Spatializer */ -#define ES18XX_RECMIX 0x0004 /* Has record mixer */ -#define ES18XX_DUPLEX_MONO 0x0008 /* Has mono duplex only */ -#define ES18XX_DUPLEX_SAME 0x0010 /* Playback and record must share the same rate */ -#define ES18XX_NEW_RATE 0x0020 /* More precise rate setting */ -#define ES18XX_AUXB 0x0040 /* AuxB mixer control */ -#define ES18XX_HWV 0x0080 /* Has separate hardware volume mixer controls*/ -#define ES18XX_MONO 0x0100 /* Mono_in mixer control */ -#define ES18XX_I2S 0x0200 /* I2S mixer control */ -#define ES18XX_MUTEREC 0x0400 /* Record source can be muted */ -#define ES18XX_CONTROL 0x0800 /* Has control ports */ - -/* Power Management */ -#define ES18XX_PM 0x07 -#define ES18XX_PM_GPO0 0x01 -#define ES18XX_PM_GPO1 0x02 -#define ES18XX_PM_PDR 0x04 -#define ES18XX_PM_ANA 0x08 -#define ES18XX_PM_FM 0x020 -#define ES18XX_PM_SUS 0x080 - -/* Lowlevel */ - -#define DAC1 0x01 -#define ADC1 0x02 -#define DAC2 0x04 -#define MILLISECOND 10000 - -static int snd_es18xx_dsp_command(struct snd_es18xx *chip, unsigned char val) -{ - int i; - - for(i = MILLISECOND; i; i--) - if ((inb(chip->port + 0x0C) & 0x80) == 0) { - outb(val, chip->port + 0x0C); - return 0; - } - snd_printk(KERN_ERR "dsp_command: timeout (0x%x)\n", val); - return -EINVAL; -} - -static int snd_es18xx_dsp_get_byte(struct snd_es18xx *chip) -{ - int i; - - for(i = MILLISECOND/10; i; i--) - if (inb(chip->port + 0x0C) & 0x40) - return inb(chip->port + 0x0A); - snd_printk(KERN_ERR "dsp_get_byte failed: 0x%lx = 0x%x!!!\n", - chip->port + 0x0A, inb(chip->port + 0x0A)); - return -ENODEV; -} - -#undef REG_DEBUG - -static int snd_es18xx_write(struct snd_es18xx *chip, - unsigned char reg, unsigned char data) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&chip->reg_lock, flags); - ret = snd_es18xx_dsp_command(chip, reg); - if (ret < 0) - goto end; - ret = snd_es18xx_dsp_command(chip, data); - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x set to %02x\n", reg, data); -#endif - return ret; -} - -static int snd_es18xx_read(struct snd_es18xx *chip, unsigned char reg) -{ - unsigned long flags; - int ret, data; - spin_lock_irqsave(&chip->reg_lock, flags); - ret = snd_es18xx_dsp_command(chip, 0xC0); - if (ret < 0) - goto end; - ret = snd_es18xx_dsp_command(chip, reg); - if (ret < 0) - goto end; - data = snd_es18xx_dsp_get_byte(chip); - ret = data; -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x now is %02x (%d)\n", reg, data, ret); -#endif - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return ret; -} - -/* Return old value */ -static int snd_es18xx_bits(struct snd_es18xx *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - int ret; - unsigned char old, new, oval; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - ret = snd_es18xx_dsp_command(chip, 0xC0); - if (ret < 0) - goto end; - ret = snd_es18xx_dsp_command(chip, reg); - if (ret < 0) - goto end; - ret = snd_es18xx_dsp_get_byte(chip); - if (ret < 0) { - goto end; - } - old = ret; - oval = old & mask; - if (val != oval) { - ret = snd_es18xx_dsp_command(chip, reg); - if (ret < 0) - goto end; - new = (old & ~mask) | (val & mask); - ret = snd_es18xx_dsp_command(chip, new); - if (ret < 0) - goto end; -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x was %02x, set to %02x (%d)\n", - reg, old, new, ret); -#endif - } - ret = oval; - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return ret; -} - -static inline void snd_es18xx_mixer_write(struct snd_es18xx *chip, - unsigned char reg, unsigned char data) -{ - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, chip->port + 0x04); - outb(data, chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x set to %02x\n", reg, data); -#endif -} - -static inline int snd_es18xx_mixer_read(struct snd_es18xx *chip, unsigned char reg) -{ - unsigned long flags; - int data; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, chip->port + 0x04); - data = inb(chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x now is %02x\n", reg, data); -#endif - return data; -} - -/* Return old value */ -static inline int snd_es18xx_mixer_bits(struct snd_es18xx *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - unsigned char old, new, oval; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, chip->port + 0x04); - old = inb(chip->port + 0x05); - oval = old & mask; - if (val != oval) { - new = (old & ~mask) | (val & mask); - outb(new, chip->port + 0x05); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x\n", - reg, old, new); -#endif - } - spin_unlock_irqrestore(&chip->mixer_lock, flags); - return oval; -} - -static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned char reg, - unsigned char mask) -{ - int old, expected, new; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, chip->port + 0x04); - old = inb(chip->port + 0x05); - expected = old ^ mask; - outb(expected, chip->port + 0x05); - new = inb(chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x, now is %02x\n", - reg, old, expected, new); -#endif - return expected == new; -} - - -static int __devinit snd_es18xx_reset(struct snd_es18xx *chip) -{ - int i; - outb(0x03, chip->port + 0x06); - inb(chip->port + 0x06); - outb(0x00, chip->port + 0x06); - for(i = 0; i < MILLISECOND && !(inb(chip->port + 0x0E) & 0x80); i++); - if (inb(chip->port + 0x0A) != 0xAA) - return -1; - return 0; -} - -static int snd_es18xx_reset_fifo(struct snd_es18xx *chip) -{ - outb(0x02, chip->port + 0x06); - inb(chip->port + 0x06); - outb(0x00, chip->port + 0x06); - return 0; -} - -static struct snd_ratnum new_clocks[2] = { - { - .num = 793800, - .den_min = 1, - .den_max = 128, - .den_step = 1, - }, - { - .num = 768000, - .den_min = 1, - .den_max = 128, - .den_step = 1, - } -}; - -static struct snd_pcm_hw_constraint_ratnums new_hw_constraints_clocks = { - .nrats = 2, - .rats = new_clocks, -}; - -static struct snd_ratnum old_clocks[2] = { - { - .num = 795444, - .den_min = 1, - .den_max = 128, - .den_step = 1, - }, - { - .num = 397722, - .den_min = 1, - .den_max = 128, - .den_step = 1, - } -}; - -static struct snd_pcm_hw_constraint_ratnums old_hw_constraints_clocks = { - .nrats = 2, - .rats = old_clocks, -}; - - -static void snd_es18xx_rate_set(struct snd_es18xx *chip, - struct snd_pcm_substream *substream, - int mode) -{ - unsigned int bits, div0; - struct snd_pcm_runtime *runtime = substream->runtime; - if (chip->caps & ES18XX_NEW_RATE) { - if (runtime->rate_num == new_clocks[0].num) - bits = 128 - runtime->rate_den; - else - bits = 256 - runtime->rate_den; - } else { - if (runtime->rate_num == old_clocks[0].num) - bits = 256 - runtime->rate_den; - else - bits = 128 - runtime->rate_den; - } - - /* set filter register */ - div0 = 256 - 7160000*20/(8*82*runtime->rate); - - if ((chip->caps & ES18XX_PCM2) && mode == DAC2) { - snd_es18xx_mixer_write(chip, 0x70, bits); - /* - * Comment from kernel oss driver: - * FKS: fascinating: 0x72 doesn't seem to work. - */ - snd_es18xx_write(chip, 0xA2, div0); - snd_es18xx_mixer_write(chip, 0x72, div0); - } else { - snd_es18xx_write(chip, 0xA1, bits); - snd_es18xx_write(chip, 0xA2, div0); - } -} - -static int snd_es18xx_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - int shift, err; - - shift = 0; - if (params_channels(hw_params) == 2) - shift++; - if (snd_pcm_format_width(params_format(hw_params)) == 16) - shift++; - - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) { - if ((chip->caps & ES18XX_DUPLEX_MONO) && - (chip->capture_a_substream) && - params_channels(hw_params) != 1) { - _snd_pcm_hw_param_setempty(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS); - return -EBUSY; - } - chip->dma2_shift = shift; - } else { - chip->dma1_shift = shift; - } - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - return 0; -} - -static int snd_es18xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_es18xx_playback1_prepare(struct snd_es18xx *chip, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - snd_es18xx_rate_set(chip, substream, DAC2); - - /* Transfer Count Reload */ - count = 0x10000 - count; - snd_es18xx_mixer_write(chip, 0x74, count & 0xff); - snd_es18xx_mixer_write(chip, 0x76, count >> 8); - - /* Set format */ - snd_es18xx_mixer_bits(chip, 0x7A, 0x07, - ((runtime->channels == 1) ? 0x00 : 0x02) | - (snd_pcm_format_width(runtime->format) == 16 ? 0x01 : 0x00) | - (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x04)); - - /* Set DMA controller */ - snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - - return 0; -} - -static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip, - struct snd_pcm_substream *substream, - int cmd) -{ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (chip->active & DAC2) - return 0; - chip->active |= DAC2; - /* Start DMA */ - if (chip->dma2 >= 4) - snd_es18xx_mixer_write(chip, 0x78, 0xb3); - else - snd_es18xx_mixer_write(chip, 0x78, 0x93); -#ifdef AVOID_POPS - /* Avoid pops */ - udelay(100000); - if (chip->caps & ES18XX_PCM2) - /* Restore Audio 2 volume */ - snd_es18xx_mixer_write(chip, 0x7C, chip->audio2_vol); - else - /* Enable PCM output */ - snd_es18xx_dsp_command(chip, 0xD1); -#endif - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (!(chip->active & DAC2)) - return 0; - chip->active &= ~DAC2; - /* Stop DMA */ - snd_es18xx_mixer_write(chip, 0x78, 0x00); -#ifdef AVOID_POPS - udelay(25000); - if (chip->caps & ES18XX_PCM2) - /* Set Audio 2 volume to 0 */ - snd_es18xx_mixer_write(chip, 0x7C, 0); - else - /* Disable PCM output */ - snd_es18xx_dsp_command(chip, 0xD3); -#endif - break; - default: - return -EINVAL; - } - - return 0; -} - -static int snd_es18xx_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - int shift, err; - - shift = 0; - if ((chip->caps & ES18XX_DUPLEX_MONO) && - chip->playback_a_substream && - params_channels(hw_params) != 1) { - _snd_pcm_hw_param_setempty(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS); - return -EBUSY; - } - if (params_channels(hw_params) == 2) - shift++; - if (snd_pcm_format_width(params_format(hw_params)) == 16) - shift++; - chip->dma1_shift = shift; - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - return 0; -} - -static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - snd_es18xx_reset_fifo(chip); - - /* Set stereo/mono */ - snd_es18xx_bits(chip, 0xA8, 0x03, runtime->channels == 1 ? 0x02 : 0x01); - - snd_es18xx_rate_set(chip, substream, ADC1); - - /* Transfer Count Reload */ - count = 0x10000 - count; - snd_es18xx_write(chip, 0xA4, count & 0xff); - snd_es18xx_write(chip, 0xA5, count >> 8); - -#ifdef AVOID_POPS - udelay(100000); -#endif - - /* Set format */ - snd_es18xx_write(chip, 0xB7, - snd_pcm_format_unsigned(runtime->format) ? 0x51 : 0x71); - snd_es18xx_write(chip, 0xB7, 0x90 | - ((runtime->channels == 1) ? 0x40 : 0x08) | - (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) | - (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20)); - - /* Set DMA controller */ - snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - - return 0; -} - -static int snd_es18xx_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (chip->active & ADC1) - return 0; - chip->active |= ADC1; - /* Start DMA */ - snd_es18xx_write(chip, 0xB8, 0x0f); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (!(chip->active & ADC1)) - return 0; - chip->active &= ~ADC1; - /* Stop DMA */ - snd_es18xx_write(chip, 0xB8, 0x00); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int snd_es18xx_playback2_prepare(struct snd_es18xx *chip, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - snd_es18xx_reset_fifo(chip); - - /* Set stereo/mono */ - snd_es18xx_bits(chip, 0xA8, 0x03, runtime->channels == 1 ? 0x02 : 0x01); - - snd_es18xx_rate_set(chip, substream, DAC1); - - /* Transfer Count Reload */ - count = 0x10000 - count; - snd_es18xx_write(chip, 0xA4, count & 0xff); - snd_es18xx_write(chip, 0xA5, count >> 8); - - /* Set format */ - snd_es18xx_write(chip, 0xB6, - snd_pcm_format_unsigned(runtime->format) ? 0x80 : 0x00); - snd_es18xx_write(chip, 0xB7, - snd_pcm_format_unsigned(runtime->format) ? 0x51 : 0x71); - snd_es18xx_write(chip, 0xB7, 0x90 | - (runtime->channels == 1 ? 0x40 : 0x08) | - (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) | - (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20)); - - /* Set DMA controller */ - snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - - return 0; -} - -static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip, - struct snd_pcm_substream *substream, - int cmd) -{ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (chip->active & DAC1) - return 0; - chip->active |= DAC1; - /* Start DMA */ - snd_es18xx_write(chip, 0xB8, 0x05); -#ifdef AVOID_POPS - /* Avoid pops */ - udelay(100000); - /* Enable Audio 1 */ - snd_es18xx_dsp_command(chip, 0xD1); -#endif - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (!(chip->active & DAC1)) - return 0; - chip->active &= ~DAC1; - /* Stop DMA */ - snd_es18xx_write(chip, 0xB8, 0x00); -#ifdef AVOID_POPS - /* Avoid pops */ - udelay(25000); - /* Disable Audio 1 */ - snd_es18xx_dsp_command(chip, 0xD3); -#endif - break; - default: - return -EINVAL; - } - - return 0; -} - -static int snd_es18xx_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) - return snd_es18xx_playback1_prepare(chip, substream); - else - return snd_es18xx_playback2_prepare(chip, substream); -} - -static int snd_es18xx_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) - return snd_es18xx_playback1_trigger(chip, substream, cmd); - else - return snd_es18xx_playback2_trigger(chip, substream, cmd); -} - -static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id) -{ - struct snd_card *card = dev_id; - struct snd_es18xx *chip = card->private_data; - unsigned char status; - - if (chip->caps & ES18XX_CONTROL) { - /* Read Interrupt status */ - status = inb(chip->ctrl_port + 6); - } else { - /* Read Interrupt status */ - status = snd_es18xx_mixer_read(chip, 0x7f) >> 4; - } -#if 0 - else { - status = 0; - if (inb(chip->port + 0x0C) & 0x01) - status |= AUDIO1_IRQ; - if (snd_es18xx_mixer_read(chip, 0x7A) & 0x80) - status |= AUDIO2_IRQ; - if ((chip->caps & ES18XX_HWV) && - snd_es18xx_mixer_read(chip, 0x64) & 0x10) - status |= HWV_IRQ; - } -#endif - - /* Audio 1 & Audio 2 */ - if (status & AUDIO2_IRQ) { - if (chip->active & DAC2) - snd_pcm_period_elapsed(chip->playback_a_substream); - /* ack interrupt */ - snd_es18xx_mixer_bits(chip, 0x7A, 0x80, 0x00); - } - if (status & AUDIO1_IRQ) { - /* ok.. capture is active */ - if (chip->active & ADC1) - snd_pcm_period_elapsed(chip->capture_a_substream); - /* ok.. playback2 is active */ - else if (chip->active & DAC1) - snd_pcm_period_elapsed(chip->playback_b_substream); - /* ack interrupt */ - inb(chip->port + 0x0E); - } - - /* MPU */ - if ((status & MPU_IRQ) && chip->rmidi) - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - - /* Hardware volume */ - if (status & HWV_IRQ) { - int split = 0; - if (chip->caps & ES18XX_HWV) { - split = snd_es18xx_mixer_read(chip, 0x64) & 0x80; - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hw_switch->id); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hw_volume->id); - } - if (!split) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_switch->id); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); - } - /* ack interrupt */ - snd_es18xx_mixer_write(chip, 0x66, 0x00); - } - return IRQ_HANDLED; -} - -static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - int pos; - - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) { - if (!(chip->active & DAC2)) - return 0; - pos = snd_dma_pointer(chip->dma2, size); - return pos >> chip->dma2_shift; - } else { - if (!(chip->active & DAC1)) - return 0; - pos = snd_dma_pointer(chip->dma1, size); - return pos >> chip->dma1_shift; - } -} - -static snd_pcm_uframes_t snd_es18xx_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - int pos; - - if (!(chip->active & ADC1)) - return 0; - pos = snd_dma_pointer(chip->dma1, size); - return pos >> chip->dma1_shift; -} - -static struct snd_pcm_hardware snd_es18xx_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_es18xx_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_es18xx_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) { - if ((chip->caps & ES18XX_DUPLEX_MONO) && - chip->capture_a_substream && - chip->capture_a_substream->runtime->channels != 1) - return -EAGAIN; - chip->playback_a_substream = substream; - } else if (substream->number <= 1) { - if (chip->capture_a_substream) - return -EAGAIN; - chip->playback_b_substream = substream; - } else { - snd_BUG(); - return -EINVAL; - } - substream->runtime->hw = snd_es18xx_playback; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - (chip->caps & ES18XX_NEW_RATE) ? &new_hw_constraints_clocks : &old_hw_constraints_clocks); - return 0; -} - -static int snd_es18xx_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - if (chip->playback_b_substream) - return -EAGAIN; - if ((chip->caps & ES18XX_DUPLEX_MONO) && - chip->playback_a_substream && - chip->playback_a_substream->runtime->channels != 1) - return -EAGAIN; - chip->capture_a_substream = substream; - substream->runtime->hw = snd_es18xx_capture; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - (chip->caps & ES18XX_NEW_RATE) ? &new_hw_constraints_clocks : &old_hw_constraints_clocks); - return 0; -} - -static int snd_es18xx_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) - chip->playback_a_substream = NULL; - else - chip->playback_b_substream = NULL; - - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_es18xx_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - chip->capture_a_substream = NULL; - snd_pcm_lib_free_pages(substream); - return 0; -} - -/* - * MIXER part - */ - -/* Record source mux routines: - * Depending on the chipset this mux switches between 4, 5, or 8 possible inputs. - * bit table for the 4/5 source mux: - * reg 1C: - * b2 b1 b0 muxSource - * x 0 x microphone - * 0 1 x CD - * 1 1 0 line - * 1 1 1 mixer - * if it's "mixer" and it's a 5 source mux chipset then reg 7A bit 3 determines - * either the play mixer or the capture mixer. - * - * "map4Source" translates from source number to reg bit pattern - * "invMap4Source" translates from reg bit pattern to source number - */ - -static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts5Source[5] = { - "Mic", "CD", "Line", "Master", "Mix" - }; - static char *texts8Source[8] = { - "Mic", "Mic Master", "CD", "AOUT", - "Mic1", "Mix", "Line", "Master" - }; - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - switch (chip->version) { - case 0x1868: - case 0x1878: - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, - texts5Source[uinfo->value.enumerated.item]); - break; - case 0x1887: - case 0x1888: - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, texts5Source[uinfo->value.enumerated.item]); - break; - case 0x1869: /* DS somewhat contradictory for 1869: could be be 5 or 8 */ - case 0x1879: - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item > 7) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts8Source[uinfo->value.enumerated.item]); - break; - default: - return -EINVAL; - } - return 0; -} - -static int snd_es18xx_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - static unsigned char invMap4Source[8] = {0, 0, 1, 1, 0, 0, 2, 3}; - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int muxSource = snd_es18xx_mixer_read(chip, 0x1c) & 0x07; - if (!(chip->version == 0x1869 || chip->version == 0x1879)) { - muxSource = invMap4Source[muxSource]; - if (muxSource==3 && - (chip->version == 0x1887 || chip->version == 0x1888) && - (snd_es18xx_mixer_read(chip, 0x7a) & 0x08) - ) - muxSource = 4; - } - ucontrol->value.enumerated.item[0] = muxSource; - return 0; -} - -static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - static unsigned char map4Source[4] = {0, 2, 6, 7}; - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - unsigned char val = ucontrol->value.enumerated.item[0]; - unsigned char retVal = 0; - - switch (chip->version) { - /* 5 source chips */ - case 0x1887: - case 0x1888: - if (val > 4) - return -EINVAL; - if (val == 4) { - retVal = snd_es18xx_mixer_bits(chip, 0x7a, 0x08, 0x08) != 0x08; - val = 3; - } else - retVal = snd_es18xx_mixer_bits(chip, 0x7a, 0x08, 0x00) != 0x00; - /* 4 source chips */ - case 0x1868: - case 0x1878: - if (val > 3) - return -EINVAL; - val = map4Source[val]; - break; - /* 8 source chips */ - case 0x1869: - case 0x1879: - if (val > 7) - return -EINVAL; - break; - default: - return -EINVAL; - } - return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal; -} - -#define snd_es18xx_info_spatializer_enable snd_ctl_boolean_mono_info - -static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - unsigned char val = snd_es18xx_mixer_read(chip, 0x50); - ucontrol->value.integer.value[0] = !!(val & 8); - return 0; -} - -static int snd_es18xx_put_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - unsigned char oval, nval; - int change; - nval = ucontrol->value.integer.value[0] ? 0x0c : 0x04; - oval = snd_es18xx_mixer_read(chip, 0x50) & 0x0c; - change = nval != oval; - if (change) { - snd_es18xx_mixer_write(chip, 0x50, nval & ~0x04); - snd_es18xx_mixer_write(chip, 0x50, nval); - } - return change; -} - -static int snd_es18xx_info_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 63; - return 0; -} - -static int snd_es18xx_get_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = snd_es18xx_mixer_read(chip, 0x61) & 0x3f; - ucontrol->value.integer.value[1] = snd_es18xx_mixer_read(chip, 0x63) & 0x3f; - return 0; -} - -#define snd_es18xx_info_hw_switch snd_ctl_boolean_stereo_info - -static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = !(snd_es18xx_mixer_read(chip, 0x61) & 0x40); - ucontrol->value.integer.value[1] = !(snd_es18xx_mixer_read(chip, 0x63) & 0x40); - return 0; -} - -static void snd_es18xx_hwv_free(struct snd_kcontrol *kcontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - chip->master_volume = NULL; - chip->master_switch = NULL; - chip->hw_volume = NULL; - chip->hw_switch = NULL; -} - -static int snd_es18xx_reg_bits(struct snd_es18xx *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - if (reg < 0xa0) - return snd_es18xx_mixer_bits(chip, reg, mask, val); - else - return snd_es18xx_bits(chip, reg, mask, val); -} - -static int snd_es18xx_reg_read(struct snd_es18xx *chip, unsigned char reg) -{ - if (reg < 0xa0) - return snd_es18xx_mixer_read(chip, reg); - else - return snd_es18xx_read(chip, reg); -} - -#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es18xx_info_single, \ - .get = snd_es18xx_get_single, .put = snd_es18xx_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_es18xx_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es18xx_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int val; - - val = snd_es18xx_reg_read(chip, reg); - ucontrol->value.integer.value[0] = (val >> shift) & mask; - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_es18xx_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned char val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - mask <<= shift; - val <<= shift; - return snd_es18xx_reg_bits(chip, reg, mask, val) != val; -} - -#define ES18XX_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es18xx_info_double, \ - .get = snd_es18xx_get_double, .put = snd_es18xx_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -static int snd_es18xx_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es18xx_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - unsigned char left, right; - - left = snd_es18xx_reg_read(chip, left_reg); - if (left_reg != right_reg) - right = snd_es18xx_reg_read(chip, right_reg); - else - right = left; - ucontrol->value.integer.value[0] = (left >> shift_left) & mask; - ucontrol->value.integer.value[1] = (right >> shift_right) & mask; - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_es18xx_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned char val1, val2, mask1, mask2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - mask1 = mask << shift_left; - mask2 = mask << shift_right; - if (left_reg != right_reg) { - change = 0; - if (snd_es18xx_reg_bits(chip, left_reg, mask1, val1) != val1) - change = 1; - if (snd_es18xx_reg_bits(chip, right_reg, mask2, val2) != val2) - change = 1; - } else { - change = (snd_es18xx_reg_bits(chip, left_reg, mask1 | mask2, - val1 | val2) != (val1 | val2)); - } - return change; -} - -/* Mixer controls - * These arrays contain setup data for mixer controls. - * - * The controls that are universal to all chipsets are fully initialized - * here. - */ -static struct snd_kcontrol_new snd_es18xx_base_controls[] = { -ES18XX_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0), -ES18XX_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1), -ES18XX_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0), -ES18XX_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0), -ES18XX_DOUBLE("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0), -ES18XX_DOUBLE("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0), -ES18XX_DOUBLE("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0), -ES18XX_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0), -ES18XX_DOUBLE("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_es18xx_info_mux, - .get = snd_es18xx_get_mux, - .put = snd_es18xx_put_mux, -} -}; - -static struct snd_kcontrol_new snd_es18xx_recmix_controls[] = { -ES18XX_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0), -ES18XX_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0), -ES18XX_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0), -ES18XX_DOUBLE("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0), -ES18XX_DOUBLE("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0), -ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0) -}; - -/* - * The chipset specific mixer controls - */ -static struct snd_kcontrol_new snd_es18xx_opt_speaker = - ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0); - -static struct snd_kcontrol_new snd_es18xx_opt_1869[] = { -ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), -ES18XX_SINGLE("Video Playback Switch", 0, 0x7f, 0, 1, 0), -ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), -ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0) -}; - -static struct snd_kcontrol_new snd_es18xx_opt_1878 = - ES18XX_DOUBLE("Video Playback Volume", 0, 0x68, 0x68, 4, 0, 15, 0); - -static struct snd_kcontrol_new snd_es18xx_opt_1879[] = { -ES18XX_SINGLE("Video Playback Switch", 0, 0x71, 6, 1, 0), -ES18XX_DOUBLE("Video Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), -ES18XX_DOUBLE("Video Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0) -}; - -static struct snd_kcontrol_new snd_es18xx_pcm1_controls[] = { -ES18XX_DOUBLE("PCM Playback Volume", 0, 0x14, 0x14, 4, 0, 15, 0), -}; - -static struct snd_kcontrol_new snd_es18xx_pcm2_controls[] = { -ES18XX_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0), -ES18XX_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0) -}; - -static struct snd_kcontrol_new snd_es18xx_spatializer_controls[] = { -ES18XX_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "3D Control - Switch", - .info = snd_es18xx_info_spatializer_enable, - .get = snd_es18xx_get_spatializer_enable, - .put = snd_es18xx_put_spatializer_enable, -} -}; - -static struct snd_kcontrol_new snd_es18xx_micpre1_control = -ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0xa9, 2, 1, 0); - -static struct snd_kcontrol_new snd_es18xx_micpre2_control = -ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0); - -static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Hardware Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_es18xx_info_hw_volume, - .get = snd_es18xx_get_hw_volume, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Hardware Master Playback Switch", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_es18xx_info_hw_switch, - .get = snd_es18xx_get_hw_switch, -}, -ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0), -}; - -static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg) -{ - int data; - - outb(reg, chip->ctrl_port); - data = inb(chip->ctrl_port + 1); - return data; -} - -static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip, - unsigned char reg, unsigned char data) -{ - /* No need for spinlocks, this function is used only in - otherwise protected init code */ - outb(reg, chip->ctrl_port); - outb(data, chip->ctrl_port + 1); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Config reg %02x set to %02x\n", reg, data); -#endif -} - -static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip, - unsigned long mpu_port, - unsigned long fm_port) -{ - int mask = 0; - - /* enable extended mode */ - snd_es18xx_dsp_command(chip, 0xC6); - /* Reset mixer registers */ - snd_es18xx_mixer_write(chip, 0x00, 0x00); - - /* Audio 1 DMA demand mode (4 bytes/request) */ - snd_es18xx_write(chip, 0xB9, 2); - if (chip->caps & ES18XX_CONTROL) { - /* Hardware volume IRQ */ - snd_es18xx_config_write(chip, 0x27, chip->irq); - if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { - /* FM I/O */ - snd_es18xx_config_write(chip, 0x62, fm_port >> 8); - snd_es18xx_config_write(chip, 0x63, fm_port & 0xff); - } - if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) { - /* MPU-401 I/O */ - snd_es18xx_config_write(chip, 0x64, mpu_port >> 8); - snd_es18xx_config_write(chip, 0x65, mpu_port & 0xff); - /* MPU-401 IRQ */ - snd_es18xx_config_write(chip, 0x28, chip->irq); - } - /* Audio1 IRQ */ - snd_es18xx_config_write(chip, 0x70, chip->irq); - /* Audio2 IRQ */ - snd_es18xx_config_write(chip, 0x72, chip->irq); - /* Audio1 DMA */ - snd_es18xx_config_write(chip, 0x74, chip->dma1); - /* Audio2 DMA */ - snd_es18xx_config_write(chip, 0x75, chip->dma2); - - /* Enable Audio 1 IRQ */ - snd_es18xx_write(chip, 0xB1, 0x50); - /* Enable Audio 2 IRQ */ - snd_es18xx_mixer_write(chip, 0x7A, 0x40); - /* Enable Audio 1 DMA */ - snd_es18xx_write(chip, 0xB2, 0x50); - /* Enable MPU and hardware volume interrupt */ - snd_es18xx_mixer_write(chip, 0x64, 0x42); - /* Enable ESS wavetable input */ - snd_es18xx_mixer_bits(chip, 0x48, 0x10, 0x10); - } - else { - int irqmask, dma1mask, dma2mask; - switch (chip->irq) { - case 2: - case 9: - irqmask = 0; - break; - case 5: - irqmask = 1; - break; - case 7: - irqmask = 2; - break; - case 10: - irqmask = 3; - break; - default: - snd_printk(KERN_ERR "invalid irq %d\n", chip->irq); - return -ENODEV; - } - switch (chip->dma1) { - case 0: - dma1mask = 1; - break; - case 1: - dma1mask = 2; - break; - case 3: - dma1mask = 3; - break; - default: - snd_printk(KERN_ERR "invalid dma1 %d\n", chip->dma1); - return -ENODEV; - } - switch (chip->dma2) { - case 0: - dma2mask = 0; - break; - case 1: - dma2mask = 1; - break; - case 3: - dma2mask = 2; - break; - case 5: - dma2mask = 3; - break; - default: - snd_printk(KERN_ERR "invalid dma2 %d\n", chip->dma2); - return -ENODEV; - } - - /* Enable and set Audio 1 IRQ */ - snd_es18xx_write(chip, 0xB1, 0x50 | (irqmask << 2)); - /* Enable and set Audio 1 DMA */ - snd_es18xx_write(chip, 0xB2, 0x50 | (dma1mask << 2)); - /* Set Audio 2 DMA */ - snd_es18xx_mixer_bits(chip, 0x7d, 0x07, 0x04 | dma2mask); - /* Enable Audio 2 IRQ and DMA - Set capture mixer input */ - snd_es18xx_mixer_write(chip, 0x7A, 0x68); - /* Enable and set hardware volume interrupt */ - snd_es18xx_mixer_write(chip, 0x64, 0x06); - if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) { - /* MPU401 share irq with audio - Joystick enabled - FM enabled */ - snd_es18xx_mixer_write(chip, 0x40, - 0x43 | (mpu_port & 0xf0) >> 1); - } - snd_es18xx_mixer_write(chip, 0x7f, ((irqmask + 1) << 1) | 0x01); - } - if (chip->caps & ES18XX_NEW_RATE) { - /* Change behaviour of register A1 - 4x oversampling - 2nd channel DAC asynchronous */ - snd_es18xx_mixer_write(chip, 0x71, 0x32); - } - if (!(chip->caps & ES18XX_PCM2)) { - /* Enable DMA FIFO */ - snd_es18xx_write(chip, 0xB7, 0x80); - } - if (chip->caps & ES18XX_SPATIALIZER) { - /* Set spatializer parameters to recommended values */ - snd_es18xx_mixer_write(chip, 0x54, 0x8f); - snd_es18xx_mixer_write(chip, 0x56, 0x95); - snd_es18xx_mixer_write(chip, 0x58, 0x94); - snd_es18xx_mixer_write(chip, 0x5a, 0x80); - } - /* Flip the "enable I2S" bits for those chipsets that need it */ - switch (chip->version) { - case 0x1879: - //Leaving I2S enabled on the 1879 screws up the PCM playback (rate effected somehow) - //so a Switch control has been added to toggle this 0x71 bit on/off: - //snd_es18xx_mixer_bits(chip, 0x71, 0x40, 0x40); - /* Note: we fall through on purpose here. */ - case 0x1878: - snd_es18xx_config_write(chip, 0x29, snd_es18xx_config_read(chip, 0x29) | 0x40); - break; - } - /* Mute input source */ - if (chip->caps & ES18XX_MUTEREC) - mask = 0x10; - if (chip->caps & ES18XX_RECMIX) - snd_es18xx_mixer_write(chip, 0x1c, 0x05 | mask); - else { - snd_es18xx_mixer_write(chip, 0x1c, 0x00 | mask); - snd_es18xx_write(chip, 0xb4, 0x00); - } -#ifndef AVOID_POPS - /* Enable PCM output */ - snd_es18xx_dsp_command(chip, 0xD1); -#endif - - return 0; -} - -static int __devinit snd_es18xx_identify(struct snd_es18xx *chip) -{ - int hi,lo; - - /* reset */ - if (snd_es18xx_reset(chip) < 0) { - snd_printk(KERN_ERR "reset at 0x%lx failed!!!\n", chip->port); - return -ENODEV; - } - - snd_es18xx_dsp_command(chip, 0xe7); - hi = snd_es18xx_dsp_get_byte(chip); - if (hi < 0) { - return hi; - } - lo = snd_es18xx_dsp_get_byte(chip); - if ((lo & 0xf0) != 0x80) { - return -ENODEV; - } - if (hi == 0x48) { - chip->version = 0x488; - return 0; - } - if (hi != 0x68) { - return -ENODEV; - } - if ((lo & 0x0f) < 8) { - chip->version = 0x688; - return 0; - } - - outb(0x40, chip->port + 0x04); - udelay(10); - hi = inb(chip->port + 0x05); - udelay(10); - lo = inb(chip->port + 0x05); - if (hi != lo) { - chip->version = hi << 8 | lo; - chip->ctrl_port = inb(chip->port + 0x05) << 8; - udelay(10); - chip->ctrl_port += inb(chip->port + 0x05); - - if ((chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL")) == NULL) { - snd_printk(KERN_ERR PFX "unable go grab port 0x%lx\n", chip->ctrl_port); - return -EBUSY; - } - - return 0; - } - - /* If has Hardware volume */ - if (snd_es18xx_mixer_writable(chip, 0x64, 0x04)) { - /* If has Audio2 */ - if (snd_es18xx_mixer_writable(chip, 0x70, 0x7f)) { - /* If has volume count */ - if (snd_es18xx_mixer_writable(chip, 0x64, 0x20)) { - chip->version = 0x1887; - } else { - chip->version = 0x1888; - } - } else { - chip->version = 0x1788; - } - } - else - chip->version = 0x1688; - return 0; -} - -static int __devinit snd_es18xx_probe(struct snd_es18xx *chip, - unsigned long mpu_port, - unsigned long fm_port) -{ - if (snd_es18xx_identify(chip) < 0) { - snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port); - return -ENODEV; - } - - switch (chip->version) { - case 0x1868: - chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_CONTROL; - break; - case 0x1869: - chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_MONO | ES18XX_MUTEREC | ES18XX_CONTROL | ES18XX_HWV; - break; - case 0x1878: - chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_I2S | ES18XX_CONTROL; - break; - case 0x1879: - chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV; - break; - case 0x1887: - case 0x1888: - chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME; - break; - default: - snd_printk(KERN_ERR "[0x%lx] unsupported chip ES%x\n", - chip->port, chip->version); - return -ENODEV; - } - - snd_printd("[0x%lx] ESS%x chip found\n", chip->port, chip->version); - - if (chip->dma1 == chip->dma2) - chip->caps &= ~(ES18XX_PCM2 | ES18XX_DUPLEX_SAME); - - return snd_es18xx_initialize(chip, mpu_port, fm_port); -} - -static struct snd_pcm_ops snd_es18xx_playback_ops = { - .open = snd_es18xx_playback_open, - .close = snd_es18xx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_es18xx_playback_hw_params, - .hw_free = snd_es18xx_pcm_hw_free, - .prepare = snd_es18xx_playback_prepare, - .trigger = snd_es18xx_playback_trigger, - .pointer = snd_es18xx_playback_pointer, -}; - -static struct snd_pcm_ops snd_es18xx_capture_ops = { - .open = snd_es18xx_capture_open, - .close = snd_es18xx_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_es18xx_capture_hw_params, - .hw_free = snd_es18xx_pcm_hw_free, - .prepare = snd_es18xx_capture_prepare, - .trigger = snd_es18xx_capture_trigger, - .pointer = snd_es18xx_capture_pointer, -}; - -static int __devinit snd_es18xx_pcm(struct snd_card *card, int device, - struct snd_pcm **rpcm) -{ - struct snd_es18xx *chip = card->private_data; - struct snd_pcm *pcm; - char str[16]; - int err; - - if (rpcm) - *rpcm = NULL; - sprintf(str, "ES%x", chip->version); - if (chip->caps & ES18XX_PCM2) - err = snd_pcm_new(card, str, device, 2, 1, &pcm); - else - err = snd_pcm_new(card, str, device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es18xx_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es18xx_capture_ops); - - /* global setup */ - pcm->private_data = chip; - pcm->info_flags = 0; - if (chip->caps & ES18XX_DUPLEX_SAME) - pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX; - if (! (chip->caps & ES18XX_PCM2)) - pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX; - sprintf(pcm->name, "ESS AudioDrive ES%x", chip->version); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, - chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* Power Management support functions */ -#ifdef CONFIG_PM -static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state) -{ - struct snd_es18xx *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(chip->pcm); - - /* power down */ - chip->pm_reg = (unsigned char)snd_es18xx_read(chip, ES18XX_PM); - chip->pm_reg |= (ES18XX_PM_FM | ES18XX_PM_SUS); - snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg); - snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_SUS); - - return 0; -} - -static int snd_es18xx_resume(struct snd_card *card) -{ - struct snd_es18xx *chip = card->private_data; - - /* restore PM register, we won't wake till (not 0x07) i/o activity though */ - snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -static int snd_es18xx_free(struct snd_card *card) -{ - struct snd_es18xx *chip = card->private_data; - - release_and_free_resource(chip->res_port); - release_and_free_resource(chip->res_ctrl_port); - release_and_free_resource(chip->res_mpu_port); - if (chip->irq >= 0) - free_irq(chip->irq, (void *) card); - if (chip->dma1 >= 0) { - disable_dma(chip->dma1); - free_dma(chip->dma1); - } - if (chip->dma2 >= 0 && chip->dma1 != chip->dma2) { - disable_dma(chip->dma2); - free_dma(chip->dma2); - } - return 0; -} - -static int snd_es18xx_dev_free(struct snd_device *device) -{ - return snd_es18xx_free(device->card); -} - -static int __devinit snd_es18xx_new_device(struct snd_card *card, - unsigned long port, - unsigned long mpu_port, - unsigned long fm_port, - int irq, int dma1, int dma2) -{ - struct snd_es18xx *chip = card->private_data; - static struct snd_device_ops ops = { - .dev_free = snd_es18xx_dev_free, - }; - int err; - - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->mixer_lock); - chip->port = port; - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - chip->audio2_vol = 0x00; - chip->active = 0; - - chip->res_port = request_region(port, 16, "ES18xx"); - if (chip->res_port == NULL) { - snd_es18xx_free(card); - snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1); - return -EBUSY; - } - - if (request_irq(irq, snd_es18xx_interrupt, 0, "ES18xx", - (void *) card)) { - snd_es18xx_free(card); - snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq); - return -EBUSY; - } - chip->irq = irq; - - if (request_dma(dma1, "ES18xx DMA 1")) { - snd_es18xx_free(card); - snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1); - return -EBUSY; - } - chip->dma1 = dma1; - - if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) { - snd_es18xx_free(card); - snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2); - return -EBUSY; - } - chip->dma2 = dma2; - - if (snd_es18xx_probe(chip, mpu_port, fm_port) < 0) { - snd_es18xx_free(card); - return -ENODEV; - } - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_es18xx_free(card); - return err; - } - return 0; -} - -static int __devinit snd_es18xx_mixer(struct snd_card *card) -{ - struct snd_es18xx *chip = card->private_data; - int err; - unsigned int idx; - - strcpy(card->mixername, chip->pcm->name); - - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(&snd_es18xx_base_controls[idx], chip); - if (chip->caps & ES18XX_HWV) { - switch (idx) { - case 0: - chip->master_volume = kctl; - kctl->private_free = snd_es18xx_hwv_free; - break; - case 1: - chip->master_switch = kctl; - kctl->private_free = snd_es18xx_hwv_free; - break; - } - } - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - } - if (chip->caps & ES18XX_PCM2) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_pcm2_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm2_controls[idx], chip))) < 0) - return err; - } - } else { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_pcm1_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm1_controls[idx], chip))) < 0) - return err; - } - } - - if (chip->caps & ES18XX_RECMIX) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_recmix_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_recmix_controls[idx], chip))) < 0) - return err; - } - } - switch (chip->version) { - default: - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre1_control, chip))) < 0) - return err; - break; - case 0x1869: - case 0x1879: - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre2_control, chip))) < 0) - return err; - break; - } - if (chip->caps & ES18XX_SPATIALIZER) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_spatializer_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_spatializer_controls[idx], chip))) < 0) - return err; - } - } - if (chip->caps & ES18XX_HWV) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_hw_volume_controls); idx++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(&snd_es18xx_hw_volume_controls[idx], chip); - if (idx == 0) - chip->hw_volume = kctl; - else - chip->hw_switch = kctl; - kctl->private_free = snd_es18xx_hwv_free; - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - - } - } - /* finish initializing other chipset specific controls - */ - if (chip->version != 0x1868) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_opt_speaker, - chip)); - if (err < 0) - return err; - } - if (chip->version == 0x1869) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_opt_1869); idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_es18xx_opt_1869[idx], - chip)); - if (err < 0) - return err; - } - } else if (chip->version == 0x1878) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_opt_1878, - chip)); - if (err < 0) - return err; - } else if (chip->version == 0x1879) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_opt_1879); idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_es18xx_opt_1879[idx], - chip)); - if (err < 0) - return err; - } - } - return 0; -} - - -/* Card level */ - -MODULE_AUTHOR("Christian Fischbach , Abramo Bagnara "); -MODULE_DESCRIPTION("ESS ES18xx AudioDrive"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESS,ES1868 PnP AudioDrive}," - "{ESS,ES1869 PnP AudioDrive}," - "{ESS,ES1878 PnP AudioDrive}," - "{ESS,ES1879 PnP AudioDrive}," - "{ESS,ES1887 PnP AudioDrive}," - "{ESS,ES1888 PnP AudioDrive}," - "{ESS,ES1887 AudioDrive}," - "{ESS,ES1888 AudioDrive}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */ -#ifndef CONFIG_PNP -static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; -#else -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -#endif -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ES18xx soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ES18xx soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ES18xx soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for ES18xx driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ES18xx driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for ES18xx driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for ES18xx driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -static int pnpc_registered; - -static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { - { .id = "ESS1869" }, - { .id = "ESS1879" }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids); - -/* PnP main device initialization */ -static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n"); - return -EBUSY; - } - /* ok. hack using Vendor-Defined Card-Level registers */ - /* skip csn and logdev initialization - already done in isapnp_configure */ - if (pnp_device_is_isapnp(pdev)) { - isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev)); - isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */ - if (mpu_port[dev] != SNDRV_AUTO_PORT) - isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */ - isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */ - isapnp_cfg_end(); - } - port[dev] = pnp_port_start(pdev, 0); - fm_port[dev] = pnp_port_start(pdev, 1); - mpu_port[dev] = pnp_port_start(pdev, 2); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]); - snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); - return 0; -} - -static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip, - struct pnp_dev *pdev) -{ - chip->dev = pdev; - if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0) - return -EBUSY; - return 0; -} - -static struct pnp_card_device_id snd_audiodrive_pnpids[] = { - /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */ - { .id = "ESS1868", .devs = { { "ESS1868" }, { "ESS0000" } } }, - /* ESS 1868 (integrated on Maxisound Cards) */ - { .id = "ESS1868", .devs = { { "ESS8601" }, { "ESS8600" } } }, - /* ESS 1868 (integrated on Maxisound Cards) */ - { .id = "ESS1868", .devs = { { "ESS8611" }, { "ESS8610" } } }, - /* ESS ES1869 Plug and Play AudioDrive */ - { .id = "ESS0003", .devs = { { "ESS1869" }, { "ESS0006" } } }, - /* ESS 1869 */ - { .id = "ESS1869", .devs = { { "ESS1869" }, { "ESS0006" } } }, - /* ESS 1878 */ - { .id = "ESS1878", .devs = { { "ESS1878" }, { "ESS0004" } } }, - /* ESS 1879 */ - { .id = "ESS1879", .devs = { { "ESS1879" }, { "ESS0009" } } }, - /* --- */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids); - -static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (chip->dev == NULL) - return -EBUSY; - - chip->devc = pnp_request_card_device(card, id->devs[1].id, NULL); - if (chip->devc == NULL) - return -EBUSY; - - /* Control port initialization */ - if (pnp_activate_dev(chip->devc) < 0) { - snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); - return -EAGAIN; - } - snd_printdd("pnp: port=0x%llx\n", - (unsigned long long)pnp_port_start(chip->devc, 0)); - if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0) - return -EBUSY; - - return 0; -} -#endif /* CONFIG_PNP */ - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -static int snd_es18xx_card_new(int dev, struct snd_card **cardp) -{ - return snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_es18xx), cardp); -} - -static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) -{ - struct snd_es18xx *chip = card->private_data; - struct snd_opl3 *opl3; - int err; - - err = snd_es18xx_new_device(card, - port[dev], mpu_port[dev], fm_port[dev], - irq[dev], dma1[dev], dma2[dev]); - if (err < 0) - return err; - - sprintf(card->driver, "ES%x", chip->version); - - sprintf(card->shortname, "ESS AudioDrive ES%x", chip->version); - if (dma1[dev] != dma2[dev]) - sprintf(card->longname, "%s at 0x%lx, irq %d, dma1 %d, dma2 %d", - card->shortname, - chip->port, - irq[dev], dma1[dev], dma2[dev]); - else - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - card->shortname, - chip->port, - irq[dev], dma1[dev]); - - err = snd_es18xx_pcm(card, 0, NULL); - if (err < 0) - return err; - - err = snd_es18xx_mixer(card); - if (err < 0) - return err; - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) { - snd_printk(KERN_WARNING PFX - "opl3 not detected at 0x%lx\n", - fm_port[dev]); - } else { - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - return err; - } - } - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX, - mpu_port[dev], MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi); - if (err < 0) - return err; - } - - return snd_card_register(card); -} - -static int __devinit snd_es18xx_isa_match(struct device *pdev, unsigned int dev) -{ - return enable[dev] && !is_isapnp_selected(dev); -} - -static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr) -{ - struct snd_card *card; - int err; - - err = snd_es18xx_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, devptr); - if ((err = snd_audiodrive_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(devptr, card); - return 0; -} - -static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev) -{ - int err; - static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1}; - static int possible_dmas[] = {1, 0, 3, 5, -1}; - - if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma1[dev] == SNDRV_AUTO_DMA) { - if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); - return -EBUSY; - } - } - if (dma2[dev] == SNDRV_AUTO_DMA) { - if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); - return -EBUSY; - } - } - - if (port[dev] != SNDRV_AUTO_PORT) { - return snd_es18xx_isa_probe1(dev, pdev); - } else { - static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280}; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - port[dev] = possible_ports[i]; - err = snd_es18xx_isa_probe1(dev, pdev); - if (! err) - return 0; - } - return err; - } -} - -static int __devexit snd_es18xx_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_es18xx_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_es18xx_suspend(dev_get_drvdata(dev), state); -} - -static int snd_es18xx_isa_resume(struct device *dev, unsigned int n) -{ - return snd_es18xx_resume(dev_get_drvdata(dev)); -} -#endif - -#define DEV_NAME "es18xx" - -static struct isa_driver snd_es18xx_isa_driver = { - .match = snd_es18xx_isa_match, - .probe = snd_es18xx_isa_probe, - .remove = __devexit_p(snd_es18xx_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_es18xx_isa_suspend, - .resume = snd_es18xx_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, - const struct pnp_device_id *id) -{ - static int dev; - int err; - struct snd_card *card; - - if (pnp_device_is_isapnp(pdev)) - return -ENOENT; /* we have another procedure - card */ - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - err = snd_es18xx_card_new(dev, &card); - if (err < 0) - return err; - if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_audiodrive_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_drvdata(pdev, card); - dev++; - return 0; -} - -static void __devexit snd_audiodrive_pnp_remove(struct pnp_dev * pdev) -{ - snd_card_free(pnp_get_drvdata(pdev)); - pnp_set_drvdata(pdev, NULL); -} - -#ifdef CONFIG_PM -static int snd_audiodrive_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - return snd_es18xx_suspend(pnp_get_drvdata(pdev), state); -} -static int snd_audiodrive_pnp_resume(struct pnp_dev *pdev) -{ - return snd_es18xx_resume(pnp_get_drvdata(pdev)); -} -#endif - -static struct pnp_driver es18xx_pnp_driver = { - .name = "es18xx-pnpbios", - .id_table = snd_audiodrive_pnpbiosids, - .probe = snd_audiodrive_pnp_detect, - .remove = __devexit_p(snd_audiodrive_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_audiodrive_pnp_suspend, - .resume = snd_audiodrive_pnp_resume, -#endif -}; - -static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_es18xx_card_new(dev, &card); - if (res < 0) - return res; - - if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { - snd_card_free(card); - return res; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_audiodrive_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_audiodrive_pnpc_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_audiodrive_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_es18xx_suspend(pnp_get_card_drvdata(pcard), state); -} - -static int snd_audiodrive_pnpc_resume(struct pnp_card_link *pcard) -{ - return snd_es18xx_resume(pnp_get_card_drvdata(pcard)); -} - -#endif - -static struct pnp_card_driver es18xx_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "es18xx", - .id_table = snd_audiodrive_pnpids, - .probe = snd_audiodrive_pnpc_detect, - .remove = __devexit_p(snd_audiodrive_pnpc_remove), -#ifdef CONFIG_PM - .suspend = snd_audiodrive_pnpc_suspend, - .resume = snd_audiodrive_pnpc_resume, -#endif -}; -#endif /* CONFIG_PNP */ - -static int __init alsa_card_es18xx_init(void) -{ - int err; - - err = isa_register_driver(&snd_es18xx_isa_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_driver(&es18xx_pnp_driver); - if (!err) - pnp_registered = 1; - - err = pnp_register_card_driver(&es18xx_pnpc_driver); - if (!err) - pnpc_registered = 1; - - if (isa_registered || pnp_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_es18xx_exit(void) -{ -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&es18xx_pnpc_driver); - if (pnp_registered) - pnp_unregister_driver(&es18xx_pnp_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_es18xx_isa_driver); -} - -module_init(alsa_card_es18xx_init) -module_exit(alsa_card_es18xx_exit) diff --git a/ANDROID_3.4.5/sound/isa/galaxy/Makefile b/ANDROID_3.4.5/sound/isa/galaxy/Makefile deleted file mode 100644 index e307066d..00000000 --- a/ANDROID_3.4.5/sound/isa/galaxy/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-azt1605-objs := azt1605.o -snd-azt2316-objs := azt2316.o - -obj-$(CONFIG_SND_AZT1605) += snd-azt1605.o -obj-$(CONFIG_SND_AZT2316) += snd-azt2316.o diff --git a/ANDROID_3.4.5/sound/isa/galaxy/azt1605.c b/ANDROID_3.4.5/sound/isa/galaxy/azt1605.c deleted file mode 100644 index 9a97643c..00000000 --- a/ANDROID_3.4.5/sound/isa/galaxy/azt1605.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Aztech AZT1605 Driver - * Copyright (C) 2007,2010 Rene Herman - * - * 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, see . - * - */ - -#define AZT1605 - -#define CRD_NAME "Aztech AZT1605" -#define DRV_NAME "AZT1605" -#define DEV_NAME "azt1605" - -#define GALAXY_DSP_MAJOR 2 -#define GALAXY_DSP_MINOR 1 - -#define GALAXY_CONFIG_SIZE 3 - -/* - * 24-bit config register - */ - -#define GALAXY_CONFIG_SBA_220 (0 << 0) -#define GALAXY_CONFIG_SBA_240 (1 << 0) -#define GALAXY_CONFIG_SBA_260 (2 << 0) -#define GALAXY_CONFIG_SBA_280 (3 << 0) -#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280 - -#define GALAXY_CONFIG_MPUA_300 (0 << 2) -#define GALAXY_CONFIG_MPUA_330 (1 << 2) - -#define GALAXY_CONFIG_MPU_ENABLE (1 << 3) - -#define GALAXY_CONFIG_GAME_ENABLE (1 << 4) - -#define GALAXY_CONFIG_CD_PANASONIC (1 << 5) -#define GALAXY_CONFIG_CD_MITSUMI (1 << 6) -#define GALAXY_CONFIG_CD_MASK (\ - GALAXY_CONFIG_CD_PANASONIC | GALAXY_CONFIG_CD_MITSUMI) - -#define GALAXY_CONFIG_UNUSED (1 << 7) -#define GALAXY_CONFIG_UNUSED_MASK GALAXY_CONFIG_UNUSED - -#define GALAXY_CONFIG_SBIRQ_2 (1 << 8) -#define GALAXY_CONFIG_SBIRQ_3 (1 << 9) -#define GALAXY_CONFIG_SBIRQ_5 (1 << 10) -#define GALAXY_CONFIG_SBIRQ_7 (1 << 11) - -#define GALAXY_CONFIG_MPUIRQ_2 (1 << 12) -#define GALAXY_CONFIG_MPUIRQ_3 (1 << 13) -#define GALAXY_CONFIG_MPUIRQ_5 (1 << 14) -#define GALAXY_CONFIG_MPUIRQ_7 (1 << 15) - -#define GALAXY_CONFIG_WSSA_530 (0 << 16) -#define GALAXY_CONFIG_WSSA_604 (1 << 16) -#define GALAXY_CONFIG_WSSA_E80 (2 << 16) -#define GALAXY_CONFIG_WSSA_F40 (3 << 16) - -#define GALAXY_CONFIG_WSS_ENABLE (1 << 18) - -#define GALAXY_CONFIG_CDIRQ_11 (1 << 19) -#define GALAXY_CONFIG_CDIRQ_12 (1 << 20) -#define GALAXY_CONFIG_CDIRQ_15 (1 << 21) -#define GALAXY_CONFIG_CDIRQ_MASK (\ - GALAXY_CONFIG_CDIRQ_11 | GALAXY_CONFIG_CDIRQ_12 |\ - GALAXY_CONFIG_CDIRQ_15) - -#define GALAXY_CONFIG_CDDMA_DISABLE (0 << 22) -#define GALAXY_CONFIG_CDDMA_0 (1 << 22) -#define GALAXY_CONFIG_CDDMA_1 (2 << 22) -#define GALAXY_CONFIG_CDDMA_3 (3 << 22) -#define GALAXY_CONFIG_CDDMA_MASK GALAXY_CONFIG_CDDMA_3 - -#define GALAXY_CONFIG_MASK (\ - GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CD_MASK |\ - GALAXY_CONFIG_UNUSED_MASK | GALAXY_CONFIG_CDIRQ_MASK |\ - GALAXY_CONFIG_CDDMA_MASK) - -#include "galaxy.c" diff --git a/ANDROID_3.4.5/sound/isa/galaxy/azt2316.c b/ANDROID_3.4.5/sound/isa/galaxy/azt2316.c deleted file mode 100644 index 18944114..00000000 --- a/ANDROID_3.4.5/sound/isa/galaxy/azt2316.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Aztech AZT2316 Driver - * Copyright (C) 2007,2010 Rene Herman - * - * 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, see . - * - */ - -#define AZT2316 - -#define CRD_NAME "Aztech AZT2316" -#define DRV_NAME "AZT2316" -#define DEV_NAME "azt2316" - -#define GALAXY_DSP_MAJOR 3 -#define GALAXY_DSP_MINOR 1 - -#define GALAXY_CONFIG_SIZE 4 - -/* - * 32-bit config register - */ - -#define GALAXY_CONFIG_SBA_220 (0 << 0) -#define GALAXY_CONFIG_SBA_240 (1 << 0) -#define GALAXY_CONFIG_SBA_260 (2 << 0) -#define GALAXY_CONFIG_SBA_280 (3 << 0) -#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280 - -#define GALAXY_CONFIG_SBIRQ_2 (1 << 2) -#define GALAXY_CONFIG_SBIRQ_5 (1 << 3) -#define GALAXY_CONFIG_SBIRQ_7 (1 << 4) -#define GALAXY_CONFIG_SBIRQ_10 (1 << 5) - -#define GALAXY_CONFIG_SBDMA_DISABLE (0 << 6) -#define GALAXY_CONFIG_SBDMA_0 (1 << 6) -#define GALAXY_CONFIG_SBDMA_1 (2 << 6) -#define GALAXY_CONFIG_SBDMA_3 (3 << 6) - -#define GALAXY_CONFIG_WSSA_530 (0 << 8) -#define GALAXY_CONFIG_WSSA_604 (1 << 8) -#define GALAXY_CONFIG_WSSA_E80 (2 << 8) -#define GALAXY_CONFIG_WSSA_F40 (3 << 8) - -#define GALAXY_CONFIG_WSS_ENABLE (1 << 10) - -#define GALAXY_CONFIG_GAME_ENABLE (1 << 11) - -#define GALAXY_CONFIG_MPUA_300 (0 << 12) -#define GALAXY_CONFIG_MPUA_330 (1 << 12) - -#define GALAXY_CONFIG_MPU_ENABLE (1 << 13) - -#define GALAXY_CONFIG_CDA_310 (0 << 14) -#define GALAXY_CONFIG_CDA_320 (1 << 14) -#define GALAXY_CONFIG_CDA_340 (2 << 14) -#define GALAXY_CONFIG_CDA_350 (3 << 14) -#define GALAXY_CONFIG_CDA_MASK GALAXY_CONFIG_CDA_350 - -#define GALAXY_CONFIG_CD_DISABLE (0 << 16) -#define GALAXY_CONFIG_CD_PANASONIC (1 << 16) -#define GALAXY_CONFIG_CD_SONY (2 << 16) -#define GALAXY_CONFIG_CD_MITSUMI (3 << 16) -#define GALAXY_CONFIG_CD_AZTECH (4 << 16) -#define GALAXY_CONFIG_CD_UNUSED_5 (5 << 16) -#define GALAXY_CONFIG_CD_UNUSED_6 (6 << 16) -#define GALAXY_CONFIG_CD_UNUSED_7 (7 << 16) -#define GALAXY_CONFIG_CD_MASK GALAXY_CONFIG_CD_UNUSED_7 - -#define GALAXY_CONFIG_CDDMA8_DISABLE (0 << 20) -#define GALAXY_CONFIG_CDDMA8_0 (1 << 20) -#define GALAXY_CONFIG_CDDMA8_1 (2 << 20) -#define GALAXY_CONFIG_CDDMA8_3 (3 << 20) -#define GALAXY_CONFIG_CDDMA8_MASK GALAXY_CONFIG_CDDMA8_3 - -#define GALAXY_CONFIG_CDDMA16_DISABLE (0 << 22) -#define GALAXY_CONFIG_CDDMA16_5 (1 << 22) -#define GALAXY_CONFIG_CDDMA16_6 (2 << 22) -#define GALAXY_CONFIG_CDDMA16_7 (3 << 22) -#define GALAXY_CONFIG_CDDMA16_MASK GALAXY_CONFIG_CDDMA16_7 - -#define GALAXY_CONFIG_MPUIRQ_2 (1 << 24) -#define GALAXY_CONFIG_MPUIRQ_5 (1 << 25) -#define GALAXY_CONFIG_MPUIRQ_7 (1 << 26) -#define GALAXY_CONFIG_MPUIRQ_10 (1 << 27) - -#define GALAXY_CONFIG_CDIRQ_5 (1 << 28) -#define GALAXY_CONFIG_CDIRQ_11 (1 << 29) -#define GALAXY_CONFIG_CDIRQ_12 (1 << 30) -#define GALAXY_CONFIG_CDIRQ_15 (1 << 31) -#define GALAXY_CONFIG_CDIRQ_MASK (\ - GALAXY_CONFIG_CDIRQ_5 | GALAXY_CONFIG_CDIRQ_11 |\ - GALAXY_CONFIG_CDIRQ_12 | GALAXY_CONFIG_CDIRQ_15) - -#define GALAXY_CONFIG_MASK (\ - GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CDA_MASK |\ - GALAXY_CONFIG_CD_MASK | GALAXY_CONFIG_CDDMA16_MASK |\ - GALAXY_CONFIG_CDDMA8_MASK | GALAXY_CONFIG_CDIRQ_MASK) - -#include "galaxy.c" diff --git a/ANDROID_3.4.5/sound/isa/galaxy/galaxy.c b/ANDROID_3.4.5/sound/isa/galaxy/galaxy.c deleted file mode 100644 index 55e20782..00000000 --- a/ANDROID_3.4.5/sound/isa/galaxy/galaxy.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Aztech AZT1605/AZT2316 Driver - * Copyright (C) 2007,2010 Rene Herman - * - * 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, see . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Rene Herman"); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); - -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; - -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(wss_port, long, NULL, 0444); -MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver."); - -/* - * Generic SB DSP support routines - */ - -#define DSP_PORT_RESET 0x6 -#define DSP_PORT_READ 0xa -#define DSP_PORT_COMMAND 0xc -#define DSP_PORT_STATUS 0xc -#define DSP_PORT_DATA_AVAIL 0xe - -#define DSP_SIGNATURE 0xaa - -#define DSP_COMMAND_GET_VERSION 0xe1 - -static int __devinit dsp_get_byte(void __iomem *port, u8 *val) -{ - int loops = 1000; - - while (!(ioread8(port + DSP_PORT_DATA_AVAIL) & 0x80)) { - if (!loops--) - return -EIO; - cpu_relax(); - } - *val = ioread8(port + DSP_PORT_READ); - return 0; -} - -static int __devinit dsp_reset(void __iomem *port) -{ - u8 val; - - iowrite8(1, port + DSP_PORT_RESET); - udelay(10); - iowrite8(0, port + DSP_PORT_RESET); - - if (dsp_get_byte(port, &val) < 0 || val != DSP_SIGNATURE) - return -ENODEV; - - return 0; -} - -static int __devinit dsp_command(void __iomem *port, u8 cmd) -{ - int loops = 1000; - - while (ioread8(port + DSP_PORT_STATUS) & 0x80) { - if (!loops--) - return -EIO; - cpu_relax(); - } - iowrite8(cmd, port + DSP_PORT_COMMAND); - return 0; -} - -static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor) -{ - int err; - - err = dsp_command(port, DSP_COMMAND_GET_VERSION); - if (err < 0) - return err; - - err = dsp_get_byte(port, major); - if (err < 0) - return err; - - err = dsp_get_byte(port, minor); - if (err < 0) - return err; - - return 0; -} - -/* - * Generic WSS support routines - */ - -#define WSS_CONFIG_DMA_0 (1 << 0) -#define WSS_CONFIG_DMA_1 (2 << 0) -#define WSS_CONFIG_DMA_3 (3 << 0) -#define WSS_CONFIG_DUPLEX (1 << 2) -#define WSS_CONFIG_IRQ_7 (1 << 3) -#define WSS_CONFIG_IRQ_9 (2 << 3) -#define WSS_CONFIG_IRQ_10 (3 << 3) -#define WSS_CONFIG_IRQ_11 (4 << 3) - -#define WSS_PORT_CONFIG 0 -#define WSS_PORT_SIGNATURE 3 - -#define WSS_SIGNATURE 4 - -static int __devinit wss_detect(void __iomem *wss_port) -{ - if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE) - return -ENODEV; - - return 0; -} - -static void wss_set_config(void __iomem *wss_port, u8 wss_config) -{ - iowrite8(wss_config, wss_port + WSS_PORT_CONFIG); -} - -/* - * Aztech Sound Galaxy specifics - */ - -#define GALAXY_PORT_CONFIG 1024 -#define CONFIG_PORT_SET 4 - -#define DSP_COMMAND_GALAXY_8 8 -#define GALAXY_COMMAND_GET_TYPE 5 - -#define DSP_COMMAND_GALAXY_9 9 -#define GALAXY_COMMAND_WSSMODE 0 -#define GALAXY_COMMAND_SB8MODE 1 - -#define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE -#define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE - -struct snd_galaxy { - void __iomem *port; - void __iomem *config_port; - void __iomem *wss_port; - u32 config; - struct resource *res_port; - struct resource *res_config_port; - struct resource *res_wss_port; -}; - -static u32 config[SNDRV_CARDS]; -static u8 wss_config[SNDRV_CARDS]; - -static int __devinit snd_galaxy_match(struct device *dev, unsigned int n) -{ - if (!enable[n]) - return 0; - - switch (port[n]) { - case SNDRV_AUTO_PORT: - dev_err(dev, "please specify port\n"); - return 0; - case 0x220: - config[n] |= GALAXY_CONFIG_SBA_220; - break; - case 0x240: - config[n] |= GALAXY_CONFIG_SBA_240; - break; - case 0x260: - config[n] |= GALAXY_CONFIG_SBA_260; - break; - case 0x280: - config[n] |= GALAXY_CONFIG_SBA_280; - break; - default: - dev_err(dev, "invalid port %#lx\n", port[n]); - return 0; - } - - switch (wss_port[n]) { - case SNDRV_AUTO_PORT: - dev_err(dev, "please specify wss_port\n"); - return 0; - case 0x530: - config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_530; - break; - case 0x604: - config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_604; - break; - case 0xe80: - config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_E80; - break; - case 0xf40: - config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_F40; - break; - default: - dev_err(dev, "invalid WSS port %#lx\n", wss_port[n]); - return 0; - } - - switch (irq[n]) { - case SNDRV_AUTO_IRQ: - dev_err(dev, "please specify irq\n"); - return 0; - case 7: - wss_config[n] |= WSS_CONFIG_IRQ_7; - break; - case 2: - irq[n] = 9; - case 9: - wss_config[n] |= WSS_CONFIG_IRQ_9; - break; - case 10: - wss_config[n] |= WSS_CONFIG_IRQ_10; - break; - case 11: - wss_config[n] |= WSS_CONFIG_IRQ_11; - break; - default: - dev_err(dev, "invalid IRQ %d\n", irq[n]); - return 0; - } - - switch (dma1[n]) { - case SNDRV_AUTO_DMA: - dev_err(dev, "please specify dma1\n"); - return 0; - case 0: - wss_config[n] |= WSS_CONFIG_DMA_0; - break; - case 1: - wss_config[n] |= WSS_CONFIG_DMA_1; - break; - case 3: - wss_config[n] |= WSS_CONFIG_DMA_3; - break; - default: - dev_err(dev, "invalid playback DMA %d\n", dma1[n]); - return 0; - } - - if (dma2[n] == SNDRV_AUTO_DMA || dma2[n] == dma1[n]) { - dma2[n] = -1; - goto mpu; - } - - wss_config[n] |= WSS_CONFIG_DUPLEX; - switch (dma2[n]) { - case 0: - break; - case 1: - if (dma1[n] == 0) - break; - default: - dev_err(dev, "invalid capture DMA %d\n", dma2[n]); - return 0; - } - -mpu: - switch (mpu_port[n]) { - case SNDRV_AUTO_PORT: - dev_warn(dev, "mpu_port not specified; not using MPU-401\n"); - mpu_port[n] = -1; - goto fm; - case 0x300: - config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_300; - break; - case 0x330: - config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_330; - break; - default: - dev_err(dev, "invalid MPU port %#lx\n", mpu_port[n]); - return 0; - } - - switch (mpu_irq[n]) { - case SNDRV_AUTO_IRQ: - dev_warn(dev, "mpu_irq not specified: using polling mode\n"); - mpu_irq[n] = -1; - break; - case 2: - mpu_irq[n] = 9; - case 9: - config[n] |= GALAXY_CONFIG_MPUIRQ_2; - break; -#ifdef AZT1605 - case 3: - config[n] |= GALAXY_CONFIG_MPUIRQ_3; - break; -#endif - case 5: - config[n] |= GALAXY_CONFIG_MPUIRQ_5; - break; - case 7: - config[n] |= GALAXY_CONFIG_MPUIRQ_7; - break; -#ifdef AZT2316 - case 10: - config[n] |= GALAXY_CONFIG_MPUIRQ_10; - break; -#endif - default: - dev_err(dev, "invalid MPU IRQ %d\n", mpu_irq[n]); - return 0; - } - - if (mpu_irq[n] == irq[n]) { - dev_err(dev, "cannot share IRQ between WSS and MPU-401\n"); - return 0; - } - -fm: - switch (fm_port[n]) { - case SNDRV_AUTO_PORT: - dev_warn(dev, "fm_port not specified: not using OPL3\n"); - fm_port[n] = -1; - break; - case 0x388: - break; - default: - dev_err(dev, "illegal FM port %#lx\n", fm_port[n]); - return 0; - } - - config[n] |= GALAXY_CONFIG_GAME_ENABLE; - return 1; -} - -static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type) -{ - u8 major; - u8 minor; - int err; - - err = dsp_reset(galaxy->port); - if (err < 0) - return err; - - err = dsp_get_version(galaxy->port, &major, &minor); - if (err < 0) - return err; - - if (major != GALAXY_DSP_MAJOR || minor != GALAXY_DSP_MINOR) - return -ENODEV; - - err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_8); - if (err < 0) - return err; - - err = dsp_command(galaxy->port, GALAXY_COMMAND_GET_TYPE); - if (err < 0) - return err; - - err = dsp_get_byte(galaxy->port, type); - if (err < 0) - return err; - - return 0; -} - -static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode) -{ - int err; - - err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_9); - if (err < 0) - return err; - - err = dsp_command(galaxy->port, mode); - if (err < 0) - return err; - -#ifdef AZT1605 - /* - * Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again - */ - err = dsp_reset(galaxy->port); - if (err < 0) - return err; -#endif - - return 0; -} - -static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config) -{ - u8 tmp = ioread8(galaxy->config_port + CONFIG_PORT_SET); - int i; - - iowrite8(tmp | 0x80, galaxy->config_port + CONFIG_PORT_SET); - for (i = 0; i < GALAXY_CONFIG_SIZE; i++) { - iowrite8(config, galaxy->config_port + i); - config >>= 8; - } - iowrite8(tmp & 0x7f, galaxy->config_port + CONFIG_PORT_SET); - msleep(10); -} - -static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config) -{ - int i; - - for (i = GALAXY_CONFIG_SIZE; i; i--) { - u8 tmp = ioread8(galaxy->config_port + i - 1); - galaxy->config = (galaxy->config << 8) | tmp; - } - config |= galaxy->config & GALAXY_CONFIG_MASK; - galaxy_set_config(galaxy, config); -} - -static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config) -{ - int err; - - err = wss_detect(galaxy->wss_port); - if (err < 0) - return err; - - wss_set_config(galaxy->wss_port, wss_config); - - err = galaxy_set_mode(galaxy, GALAXY_MODE_WSS); - if (err < 0) - return err; - - return 0; -} - -static void snd_galaxy_free(struct snd_card *card) -{ - struct snd_galaxy *galaxy = card->private_data; - - if (galaxy->wss_port) { - wss_set_config(galaxy->wss_port, 0); - ioport_unmap(galaxy->wss_port); - release_and_free_resource(galaxy->res_wss_port); - } - if (galaxy->config_port) { - galaxy_set_config(galaxy, galaxy->config); - ioport_unmap(galaxy->config_port); - release_and_free_resource(galaxy->res_config_port); - } - if (galaxy->port) { - ioport_unmap(galaxy->port); - release_and_free_resource(galaxy->res_port); - } -} - -static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n) -{ - struct snd_galaxy *galaxy; - struct snd_wss *chip; - struct snd_card *card; - u8 type; - int err; - - err = snd_card_create(index[n], id[n], THIS_MODULE, sizeof *galaxy, - &card); - if (err < 0) - return err; - - snd_card_set_dev(card, dev); - - card->private_free = snd_galaxy_free; - galaxy = card->private_data; - - galaxy->res_port = request_region(port[n], 16, DRV_NAME); - if (!galaxy->res_port) { - dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n], - port[n] + 15); - err = -EBUSY; - goto error; - } - galaxy->port = ioport_map(port[n], 16); - - err = galaxy_init(galaxy, &type); - if (err < 0) { - dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]); - goto error; - } - dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]); - - galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG, - 16, DRV_NAME); - if (!galaxy->res_config_port) { - dev_err(dev, "could not grab ports %#lx-%#lx\n", - port[n] + GALAXY_PORT_CONFIG, - port[n] + GALAXY_PORT_CONFIG + 15); - err = -EBUSY; - goto error; - } - galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16); - - galaxy_config(galaxy, config[n]); - - galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME); - if (!galaxy->res_wss_port) { - dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n], - wss_port[n] + 3); - err = -EBUSY; - goto error; - } - galaxy->wss_port = ioport_map(wss_port[n], 4); - - err = galaxy_wss_config(galaxy, wss_config[n]); - if (err < 0) { - dev_err(dev, "could not configure WSS\n"); - goto error; - } - - strcpy(card->driver, DRV_NAME); - strcpy(card->shortname, DRV_NAME); - sprintf(card->longname, "%s at %#lx/%#lx, irq %d, dma %d/%d", - card->shortname, port[n], wss_port[n], irq[n], dma1[n], - dma2[n]); - - err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n], - dma2[n], WSS_HW_DETECT, 0, &chip); - if (err < 0) - goto error; - - err = snd_wss_pcm(chip, 0, NULL); - if (err < 0) - goto error; - - err = snd_wss_mixer(chip); - if (err < 0) - goto error; - - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) - goto error; - - if (mpu_port[n] >= 0) { - err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port[n], 0, mpu_irq[n], NULL); - if (err < 0) - goto error; - } - - if (fm_port[n] >= 0) { - struct snd_opl3 *opl3; - - err = snd_opl3_create(card, fm_port[n], fm_port[n] + 2, - OPL3_HW_AUTO, 0, &opl3); - if (err < 0) { - dev_err(dev, "no OPL device at %#lx\n", fm_port[n]); - goto error; - } - err = snd_opl3_timer_new(opl3, 1, 2); - if (err < 0) - goto error; - - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - goto error; - } - - err = snd_card_register(card); - if (err < 0) - goto error; - - dev_set_drvdata(dev, card); - return 0; - -error: - snd_card_free(card); - return err; -} - -static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_galaxy_driver = { - .match = snd_galaxy_match, - .probe = snd_galaxy_probe, - .remove = __devexit_p(snd_galaxy_remove), - - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_galaxy_init(void) -{ - return isa_register_driver(&snd_galaxy_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_galaxy_exit(void) -{ - isa_unregister_driver(&snd_galaxy_driver); -} - -module_init(alsa_card_galaxy_init); -module_exit(alsa_card_galaxy_exit); diff --git a/ANDROID_3.4.5/sound/isa/gus/Makefile b/ANDROID_3.4.5/sound/isa/gus/Makefile deleted file mode 100644 index 6cd4ee03..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-gus-lib-objs := gus_main.o \ - gus_io.o gus_irq.o gus_timer.o \ - gus_mem.o gus_mem_proc.o gus_dram.o gus_dma.o gus_volume.o \ - gus_pcm.o gus_mixer.o \ - gus_uart.o \ - gus_reset.o - -snd-gusclassic-objs := gusclassic.o -snd-gusextreme-objs := gusextreme.o -snd-gusmax-objs := gusmax.o -snd-interwave-objs := interwave.o -snd-interwave-stb-objs := interwave-stb.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o -obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o -obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o -obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o -obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_dma.c b/ANDROID_3.4.5/sound/isa/gus/gus_dma.c deleted file mode 100644 index 36c27c83..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_dma.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Routines for GF1 DMA control - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -static void snd_gf1_dma_ack(struct snd_gus_card * gus) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, 0x00); - snd_gf1_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -static void snd_gf1_dma_program(struct snd_gus_card * gus, - unsigned int addr, - unsigned long buf_addr, - unsigned int count, - unsigned int cmd) -{ - unsigned long flags; - unsigned int address; - unsigned char dma_cmd; - unsigned int address_high; - - snd_printdd("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", - addr, buf_addr, count); - - if (gus->gf1.dma1 > 3) { - if (gus->gf1.enh_mode) { - address = addr >> 1; - } else { - if (addr & 0x1f) { - snd_printd("snd_gf1_dma_transfer: unaligned address (0x%x)?\n", addr); - return; - } - address = (addr & 0x000c0000) | ((addr & 0x0003ffff) >> 1); - } - } else { - address = addr; - } - - dma_cmd = SNDRV_GF1_DMA_ENABLE | (unsigned short) cmd; -#if 0 - dma_cmd |= 0x08; -#endif - if (dma_cmd & SNDRV_GF1_DMA_16BIT) { - count++; - count &= ~1; /* align */ - } - if (gus->gf1.dma1 > 3) { - dma_cmd |= SNDRV_GF1_DMA_WIDTH16; - count++; - count &= ~1; /* align */ - } - snd_gf1_dma_ack(gus); - snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE); -#if 0 - snd_printk(KERN_DEBUG "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", - address << 1, count, dma_cmd); -#endif - spin_lock_irqsave(&gus->reg_lock, flags); - if (gus->gf1.enh_mode) { - address_high = ((address >> 16) & 0x000000f0) | (address & 0x0000000f); - snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); - snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH, (unsigned char) address_high); - } else - snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); - snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, dma_cmd); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -static struct snd_gf1_dma_block *snd_gf1_dma_next_block(struct snd_gus_card * gus) -{ - struct snd_gf1_dma_block *block; - - /* PCM block have bigger priority than synthesizer one */ - if (gus->gf1.dma_data_pcm) { - block = gus->gf1.dma_data_pcm; - if (gus->gf1.dma_data_pcm_last == block) { - gus->gf1.dma_data_pcm = - gus->gf1.dma_data_pcm_last = NULL; - } else { - gus->gf1.dma_data_pcm = block->next; - } - } else if (gus->gf1.dma_data_synth) { - block = gus->gf1.dma_data_synth; - if (gus->gf1.dma_data_synth_last == block) { - gus->gf1.dma_data_synth = - gus->gf1.dma_data_synth_last = NULL; - } else { - gus->gf1.dma_data_synth = block->next; - } - } else { - block = NULL; - } - if (block) { - gus->gf1.dma_ack = block->ack; - gus->gf1.dma_private_data = block->private_data; - } - return block; -} - - -static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) -{ - struct snd_gf1_dma_block *block; - - snd_gf1_dma_ack(gus); - if (gus->gf1.dma_ack) - gus->gf1.dma_ack(gus, gus->gf1.dma_private_data); - spin_lock(&gus->dma_lock); - if (gus->gf1.dma_data_pcm == NULL && - gus->gf1.dma_data_synth == NULL) { - gus->gf1.dma_ack = NULL; - gus->gf1.dma_flags &= ~SNDRV_GF1_DMA_TRIGGER; - spin_unlock(&gus->dma_lock); - return; - } - block = snd_gf1_dma_next_block(gus); - spin_unlock(&gus->dma_lock); - snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); - kfree(block); -#if 0 - snd_printd(KERN_DEBUG "program dma (IRQ) - " - "addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", - block->addr, block->buf_addr, block->count, block->cmd); -#endif -} - -int snd_gf1_dma_init(struct snd_gus_card * gus) -{ - mutex_lock(&gus->dma_mutex); - gus->gf1.dma_shared++; - if (gus->gf1.dma_shared > 1) { - mutex_unlock(&gus->dma_mutex); - return 0; - } - gus->gf1.interrupt_handler_dma_write = snd_gf1_dma_interrupt; - gus->gf1.dma_data_pcm = - gus->gf1.dma_data_pcm_last = - gus->gf1.dma_data_synth = - gus->gf1.dma_data_synth_last = NULL; - mutex_unlock(&gus->dma_mutex); - return 0; -} - -int snd_gf1_dma_done(struct snd_gus_card * gus) -{ - struct snd_gf1_dma_block *block; - - mutex_lock(&gus->dma_mutex); - gus->gf1.dma_shared--; - if (!gus->gf1.dma_shared) { - snd_dma_disable(gus->gf1.dma1); - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_WRITE); - snd_gf1_dma_ack(gus); - while ((block = gus->gf1.dma_data_pcm)) { - gus->gf1.dma_data_pcm = block->next; - kfree(block); - } - while ((block = gus->gf1.dma_data_synth)) { - gus->gf1.dma_data_synth = block->next; - kfree(block); - } - gus->gf1.dma_data_pcm_last = - gus->gf1.dma_data_synth_last = NULL; - } - mutex_unlock(&gus->dma_mutex); - return 0; -} - -int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, - struct snd_gf1_dma_block * __block, - int atomic, - int synth) -{ - unsigned long flags; - struct snd_gf1_dma_block *block; - - block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL); - if (block == NULL) { - snd_printk(KERN_ERR "gf1: DMA transfer failure; not enough memory\n"); - return -ENOMEM; - } - *block = *__block; - block->next = NULL; - - snd_printdd("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", - block->addr, (long) block->buffer, block->count, - block->cmd); - - snd_printdd("gus->gf1.dma_data_pcm_last = 0x%lx\n", - (long)gus->gf1.dma_data_pcm_last); - snd_printdd("gus->gf1.dma_data_pcm = 0x%lx\n", - (long)gus->gf1.dma_data_pcm); - - spin_lock_irqsave(&gus->dma_lock, flags); - if (synth) { - if (gus->gf1.dma_data_synth_last) { - gus->gf1.dma_data_synth_last->next = block; - gus->gf1.dma_data_synth_last = block; - } else { - gus->gf1.dma_data_synth = - gus->gf1.dma_data_synth_last = block; - } - } else { - if (gus->gf1.dma_data_pcm_last) { - gus->gf1.dma_data_pcm_last->next = block; - gus->gf1.dma_data_pcm_last = block; - } else { - gus->gf1.dma_data_pcm = - gus->gf1.dma_data_pcm_last = block; - } - } - if (!(gus->gf1.dma_flags & SNDRV_GF1_DMA_TRIGGER)) { - gus->gf1.dma_flags |= SNDRV_GF1_DMA_TRIGGER; - block = snd_gf1_dma_next_block(gus); - spin_unlock_irqrestore(&gus->dma_lock, flags); - if (block == NULL) - return 0; - snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); - kfree(block); - return 0; - } - spin_unlock_irqrestore(&gus->dma_lock, flags); - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_dram.c b/ANDROID_3.4.5/sound/isa/gus/gus_dram.c deleted file mode 100644 index fd2e2e2e..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_dram.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * DRAM access routines - * - * - * 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 - - -static int snd_gus_dram_poke(struct snd_gus_card *gus, char __user *_buffer, - unsigned int address, unsigned int size) -{ - unsigned long flags; - unsigned int size1, size2; - char buffer[256], *pbuffer; - - while (size > 0) { - size1 = size > sizeof(buffer) ? sizeof(buffer) : size; - if (copy_from_user(buffer, _buffer, size1)) - return -EFAULT; - if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - snd_gf1_dram_addr(gus, address); - outsb(GUSP(gus, DRAM), buffer, size1); - spin_unlock_irqrestore(&gus->reg_lock, flags); - address += size1; - } else { - pbuffer = buffer; - size2 = size1; - while (size2--) - snd_gf1_poke(gus, address++, *pbuffer++); - } - size -= size1; - _buffer += size1; - } - return 0; -} - - -int snd_gus_dram_write(struct snd_gus_card *gus, char __user *buffer, - unsigned int address, unsigned int size) -{ - return snd_gus_dram_poke(gus, buffer, address, size); -} - -static int snd_gus_dram_peek(struct snd_gus_card *gus, char __user *_buffer, - unsigned int address, unsigned int size, - int rom) -{ - unsigned long flags; - unsigned int size1, size2; - char buffer[256], *pbuffer; - - while (size > 0) { - size1 = size > sizeof(buffer) ? sizeof(buffer) : size; - if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01); - snd_gf1_dram_addr(gus, address); - insb(GUSP(gus, DRAM), buffer, size1); - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - spin_unlock_irqrestore(&gus->reg_lock, flags); - address += size1; - } else { - pbuffer = buffer; - size2 = size1; - while (size2--) - *pbuffer++ = snd_gf1_peek(gus, address++); - } - if (copy_to_user(_buffer, buffer, size1)) - return -EFAULT; - size -= size1; - _buffer += size1; - } - return 0; -} - -int snd_gus_dram_read(struct snd_gus_card *gus, char __user *buffer, - unsigned int address, unsigned int size, - int rom) -{ - return snd_gus_dram_peek(gus, buffer, address, size, rom); -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_instr.c b/ANDROID_3.4.5/sound/isa/gus/gus_instr.c deleted file mode 100644 index 4dc9caf8..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_instr.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Routines for Gravis UltraSound soundcards - Synthesizer - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -/* - * - */ - -int snd_gus_iwffff_put_sample(void *private_data, struct iwffff_wave *wave, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - struct snd_gf1_mem_block *block; - int err; - - if (wave->format & IWFFFF_WAVE_ROM) - return 0; /* it's probably ok - verify the address? */ - if (wave->format & IWFFFF_WAVE_STEREO) - return -EINVAL; /* not supported */ - block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF, - NULL, wave->size, - wave->format & IWFFFF_WAVE_16BIT, 1, - wave->share_id); - if (block == NULL) - return -ENOMEM; - err = snd_gus_dram_write(gus, data, - block->ptr, wave->size); - if (err < 0) { - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); - snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); - return err; - } - wave->address.memory = block->ptr; - return 0; -} - -int snd_gus_iwffff_get_sample(void *private_data, struct iwffff_wave *wave, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, - wave->format & IWFFFF_WAVE_ROM ? 1 : 0); -} - -int snd_gus_iwffff_remove_sample(void *private_data, struct iwffff_wave *wave, - int atomic) -{ - struct snd_gus_card *gus = private_data; - - if (wave->format & IWFFFF_WAVE_ROM) - return 0; /* it's probably ok - verify the address? */ - return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory); -} - -/* - * - */ - -int snd_gus_gf1_put_sample(void *private_data, struct gf1_wave *wave, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - struct snd_gf1_mem_block *block; - int err; - - if (wave->format & GF1_WAVE_STEREO) - return -EINVAL; /* not supported */ - block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_WAVE_GF1, - NULL, wave->size, - wave->format & GF1_WAVE_16BIT, 1, - wave->share_id); - if (block == NULL) - return -ENOMEM; - err = snd_gus_dram_write(gus, data, - block->ptr, wave->size); - if (err < 0) { - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); - snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); - return err; - } - wave->address.memory = block->ptr; - return 0; -} - -int snd_gus_gf1_get_sample(void *private_data, struct gf1_wave *wave, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0); -} - -int snd_gus_gf1_remove_sample(void *private_data, struct gf1_wave *wave, - int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory); -} - -/* - * - */ - -int snd_gus_simple_put_sample(void *private_data, struct simple_instrument *instr, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - struct snd_gf1_mem_block *block; - int err; - - if (instr->format & SIMPLE_WAVE_STEREO) - return -EINVAL; /* not supported */ - block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE, - NULL, instr->size, - instr->format & SIMPLE_WAVE_16BIT, 1, - instr->share_id); - if (block == NULL) - return -ENOMEM; - err = snd_gus_dram_write(gus, data, block->ptr, instr->size); - if (err < 0) { - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); - snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); - return err; - } - instr->address.memory = block->ptr; - return 0; -} - -int snd_gus_simple_get_sample(void *private_data, struct simple_instrument *instr, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0); -} - -int snd_gus_simple_remove_sample(void *private_data, struct simple_instrument *instr, - int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory); -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_io.c b/ANDROID_3.4.5/sound/isa/gus/gus_io.c deleted file mode 100644 index ca79878d..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_io.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * I/O routines for GF1/InterWave synthesizer chips - * - * - * 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 - -void snd_gf1_delay(struct snd_gus_card * gus) -{ - int i; - - for (i = 0; i < 6; i++) { - mb(); - inb(GUSP(gus, DRAM)); - } -} - -/* - * ======================================================================= - */ - -/* - * ok.. stop of control registers (wave & ramp) need some special things.. - * big UltraClick (tm) elimination... - */ - -static inline void __snd_gf1_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) -{ - unsigned char value; - - outb(reg | 0x80, gus->gf1.reg_regsel); - mb(); - value = inb(gus->gf1.reg_data8); - mb(); - outb(reg, gus->gf1.reg_regsel); - mb(); - outb((value | 0x03) & ~(0x80 | 0x20), gus->gf1.reg_data8); - mb(); -} - -static inline void __snd_gf1_write8(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - outb(reg, gus->gf1.reg_regsel); - mb(); - outb(data, gus->gf1.reg_data8); - mb(); -} - -static inline unsigned char __snd_gf1_look8(struct snd_gus_card * gus, - unsigned char reg) -{ - outb(reg, gus->gf1.reg_regsel); - mb(); - return inb(gus->gf1.reg_data8); -} - -static inline void __snd_gf1_write16(struct snd_gus_card * gus, - unsigned char reg, unsigned int data) -{ - outb(reg, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) data, gus->gf1.reg_data16); - mb(); -} - -static inline unsigned short __snd_gf1_look16(struct snd_gus_card * gus, - unsigned char reg) -{ - outb(reg, gus->gf1.reg_regsel); - mb(); - return inw(gus->gf1.reg_data16); -} - -static inline void __snd_gf1_adlib_write(struct snd_gus_card * gus, - unsigned char reg, unsigned char data) -{ - outb(reg, gus->gf1.reg_timerctrl); - inb(gus->gf1.reg_timerctrl); - inb(gus->gf1.reg_timerctrl); - outb(data, gus->gf1.reg_timerdata); - inb(gus->gf1.reg_timerctrl); - inb(gus->gf1.reg_timerctrl); -} - -static inline void __snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg, - unsigned int addr, int w_16bit) -{ - if (gus->gf1.enh_mode) { - if (w_16bit) - addr = ((addr >> 1) & ~0x0000000f) | (addr & 0x0000000f); - __snd_gf1_write8(gus, SNDRV_GF1_VB_UPPER_ADDRESS, (unsigned char) ((addr >> 26) & 0x03)); - } else if (w_16bit) - addr = (addr & 0x00c0000f) | ((addr & 0x003ffff0) >> 1); - __snd_gf1_write16(gus, reg, (unsigned short) (addr >> 11)); - __snd_gf1_write16(gus, reg + 1, (unsigned short) (addr << 5)); -} - -static inline unsigned int __snd_gf1_read_addr(struct snd_gus_card * gus, - unsigned char reg, short w_16bit) -{ - unsigned int res; - - res = ((unsigned int) __snd_gf1_look16(gus, reg | 0x80) << 11) & 0xfff800; - res |= ((unsigned int) __snd_gf1_look16(gus, (reg + 1) | 0x80) >> 5) & 0x0007ff; - if (gus->gf1.enh_mode) { - res |= (unsigned int) __snd_gf1_look8(gus, SNDRV_GF1_VB_UPPER_ADDRESS | 0x80) << 26; - if (w_16bit) - res = ((res << 1) & 0xffffffe0) | (res & 0x0000000f); - } else if (w_16bit) - res = ((res & 0x001ffff0) << 1) | (res & 0x00c0000f); - return res; -} - - -/* - * ======================================================================= - */ - -void snd_gf1_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) -{ - __snd_gf1_ctrl_stop(gus, reg); -} - -void snd_gf1_write8(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - __snd_gf1_write8(gus, reg, data); -} - -unsigned char snd_gf1_look8(struct snd_gus_card * gus, unsigned char reg) -{ - return __snd_gf1_look8(gus, reg); -} - -void snd_gf1_write16(struct snd_gus_card * gus, - unsigned char reg, - unsigned int data) -{ - __snd_gf1_write16(gus, reg, data); -} - -unsigned short snd_gf1_look16(struct snd_gus_card * gus, unsigned char reg) -{ - return __snd_gf1_look16(gus, reg); -} - -void snd_gf1_adlib_write(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - __snd_gf1_adlib_write(gus, reg, data); -} - -void snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg, - unsigned int addr, short w_16bit) -{ - __snd_gf1_write_addr(gus, reg, addr, w_16bit); -} - -unsigned int snd_gf1_read_addr(struct snd_gus_card * gus, - unsigned char reg, - short w_16bit) -{ - return __snd_gf1_read_addr(gus, reg, w_16bit); -} - -/* - - */ - -void snd_gf1_i_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_ctrl_stop(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -void snd_gf1_i_write8(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_write8(gus, reg, data); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -unsigned char snd_gf1_i_look8(struct snd_gus_card * gus, unsigned char reg) -{ - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&gus->reg_lock, flags); - res = __snd_gf1_look8(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} - -void snd_gf1_i_write16(struct snd_gus_card * gus, - unsigned char reg, - unsigned int data) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_write16(gus, reg, data); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -unsigned short snd_gf1_i_look16(struct snd_gus_card * gus, unsigned char reg) -{ - unsigned long flags; - unsigned short res; - - spin_lock_irqsave(&gus->reg_lock, flags); - res = __snd_gf1_look16(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} - -#if 0 - -void snd_gf1_i_adlib_write(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_adlib_write(gus, reg, data); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -void snd_gf1_i_write_addr(struct snd_gus_card * gus, unsigned char reg, - unsigned int addr, short w_16bit) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_write_addr(gus, reg, addr, w_16bit); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -#endif /* 0 */ - -#ifdef CONFIG_SND_DEBUG -static unsigned int snd_gf1_i_read_addr(struct snd_gus_card * gus, - unsigned char reg, short w_16bit) -{ - unsigned int res; - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - res = __snd_gf1_read_addr(gus, reg, w_16bit); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} -#endif - -/* - - */ - -void snd_gf1_dram_addr(struct snd_gus_card * gus, unsigned int addr) -{ - outb(0x43, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(0x44, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); -} - -void snd_gf1_poke(struct snd_gus_card * gus, unsigned int addr, unsigned char data) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - outb(data, gus->gf1.reg_dram); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -unsigned char snd_gf1_peek(struct snd_gus_card * gus, unsigned int addr) -{ - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - res = inb(gus->gf1.reg_dram); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} - -#if 0 - -void snd_gf1_pokew(struct snd_gus_card * gus, unsigned int addr, unsigned short data) -{ - unsigned long flags; - -#ifdef CONFIG_SND_DEBUG - if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_pokew - GF1!!!\n"); -#endif - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); - mb(); - outw(data, gus->gf1.reg_data16); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -unsigned short snd_gf1_peekw(struct snd_gus_card * gus, unsigned int addr) -{ - unsigned long flags; - unsigned short res; - -#ifdef CONFIG_SND_DEBUG - if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_peekw - GF1!!!\n"); -#endif - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); - mb(); - res = inw(gus->gf1.reg_data16); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} - -void snd_gf1_dram_setmem(struct snd_gus_card * gus, unsigned int addr, - unsigned short value, unsigned int count) -{ - unsigned long port; - unsigned long flags; - -#ifdef CONFIG_SND_DEBUG - if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_dram_setmem - GF1!!!\n"); -#endif - addr &= ~1; - count >>= 1; - port = GUSP(gus, GF1DATALOW); - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); - while (count--) - outw(value, port); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -#endif /* 0 */ - -void snd_gf1_select_active_voices(struct snd_gus_card * gus) -{ - unsigned short voices; - - static unsigned short voices_tbl[32 - 14 + 1] = - { - 44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843, - 25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, 19293 - }; - - voices = gus->gf1.active_voices; - if (voices > 32) - voices = 32; - if (voices < 14) - voices = 14; - if (gus->gf1.enh_mode) - voices = 32; - gus->gf1.active_voices = voices; - gus->gf1.playback_freq = - gus->gf1.enh_mode ? 44100 : voices_tbl[voices - 14]; - if (!gus->gf1.enh_mode) { - snd_gf1_i_write8(gus, SNDRV_GF1_GB_ACTIVE_VOICES, 0xc0 | (voices - 1)); - udelay(100); - } -} - -#ifdef CONFIG_SND_DEBUG - -void snd_gf1_print_voice_registers(struct snd_gus_card * gus) -{ - unsigned char mode; - int voice, ctrl; - - voice = gus->gf1.active_voice; - printk(KERN_INFO " -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n", voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d)); - printk(KERN_INFO " -%i- GF1 frequency = 0x%x\n", voice, snd_gf1_i_read16(gus, 1)); - printk(KERN_INFO " -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4), snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4), snd_gf1_i_read_addr(gus, 4, ctrl & 4), snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4)); - printk(KERN_INFO " -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n", voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8), snd_gf1_i_read8(gus, 6)); - printk(KERN_INFO" -%i- GF1 volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 9)); - printk(KERN_INFO " -%i- GF1 position = 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4), snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4)); - if (gus->interwave && snd_gf1_i_read8(gus, 0x19) & 0x01) { /* enhanced mode */ - mode = snd_gf1_i_read8(gus, 0x15); - printk(KERN_INFO " -%i- GFA1 mode = 0x%x\n", voice, mode); - if (mode & 0x01) { /* Effect processor */ - printk(KERN_INFO " -%i- GFA1 effect address = 0x%x\n", voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4)); - printk(KERN_INFO " -%i- GFA1 effect volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x16)); - printk(KERN_INFO " -%i- GFA1 effect volume final = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x1d)); - printk(KERN_INFO " -%i- GFA1 effect acumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14)); - } - if (mode & 0x20) { - printk(KERN_INFO " -%i- GFA1 left offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x13), snd_gf1_i_read16(gus, 0x13) >> 4); - printk(KERN_INFO " -%i- GFA1 left offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1c), snd_gf1_i_read16(gus, 0x1c) >> 4); - printk(KERN_INFO " -%i- GFA1 right offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x0c), snd_gf1_i_read16(gus, 0x0c) >> 4); - printk(KERN_INFO " -%i- GFA1 right offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1b), snd_gf1_i_read16(gus, 0x1b) >> 4); - } else - printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); - } else - printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); -} - -#if 0 - -void snd_gf1_print_global_registers(struct snd_gus_card * gus) -{ - unsigned char global_mode = 0x00; - - printk(KERN_INFO " -G- GF1 active voices = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES)); - if (gus->interwave) { - global_mode = snd_gf1_i_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE); - printk(KERN_INFO " -G- GF1 global mode = 0x%x\n", global_mode); - } - if (global_mode & 0x02) /* LFO enabled? */ - printk(KERN_INFO " -G- GF1 LFO base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE)); - printk(KERN_INFO " -G- GF1 voices IRQ read = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ)); - printk(KERN_INFO " -G- GF1 DRAM DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL)); - printk(KERN_INFO " -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW)); - printk(KERN_INFO " -G- GF1 DRAM IO high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW)); - if (!gus->interwave) - printk(KERN_INFO " -G- GF1 record DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL)); - printk(KERN_INFO " -G- GF1 DRAM IO 16 = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16)); - if (gus->gf1.enh_mode) { - printk(KERN_INFO " -G- GFA1 memory config = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG)); - printk(KERN_INFO " -G- GFA1 memory control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL)); - printk(KERN_INFO " -G- GFA1 FIFO record base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR)); - printk(KERN_INFO " -G- GFA1 FIFO playback base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR)); - printk(KERN_INFO " -G- GFA1 interleave control = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE)); - } -} - -void snd_gf1_print_setup_registers(struct snd_gus_card * gus) -{ - printk(KERN_INFO " -S- mix control = 0x%x\n", inb(GUSP(gus, MIXCNTRLREG))); - printk(KERN_INFO " -S- IRQ status = 0x%x\n", inb(GUSP(gus, IRQSTAT))); - printk(KERN_INFO " -S- timer control = 0x%x\n", inb(GUSP(gus, TIMERCNTRL))); - printk(KERN_INFO " -S- timer data = 0x%x\n", inb(GUSP(gus, TIMERDATA))); - printk(KERN_INFO " -S- status read = 0x%x\n", inb(GUSP(gus, REGCNTRLS))); - printk(KERN_INFO " -S- Sound Blaster control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL)); - printk(KERN_INFO " -S- AdLib timer 1/2 = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1), snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2)); - printk(KERN_INFO " -S- reset = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)); - if (gus->interwave) { - printk(KERN_INFO " -S- compatibility = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY)); - printk(KERN_INFO " -S- decode control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL)); - printk(KERN_INFO " -S- version number = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER)); - printk(KERN_INFO " -S- MPU-401 emul. control A/B = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A), snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B)); - printk(KERN_INFO " -S- emulation IRQ = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ)); - } -} - -void snd_gf1_peek_print_block(struct snd_gus_card * gus, unsigned int addr, int count, int w_16bit) -{ - if (!w_16bit) { - while (count-- > 0) - printk(count > 0 ? "%02x:" : "%02x", snd_gf1_peek(gus, addr++)); - } else { - while (count-- > 0) { - printk(count > 0 ? "%04x:" : "%04x", snd_gf1_peek(gus, addr) | (snd_gf1_peek(gus, addr + 1) << 8)); - addr += 2; - } - } -} - -#endif /* 0 */ - -#endif diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_irq.c b/ANDROID_3.4.5/sound/isa/gus/gus_irq.c deleted file mode 100644 index 2055aff7..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_irq.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Routine for IRQ handling from GF1/InterWave chip - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -#ifdef CONFIG_SND_DEBUG -#define STAT_ADD(x) ((x)++) -#else -#define STAT_ADD(x) while (0) { ; } -#endif - -irqreturn_t snd_gus_interrupt(int irq, void *dev_id) -{ - struct snd_gus_card * gus = dev_id; - unsigned char status; - int loop = 100; - int handled = 0; - -__again: - status = inb(gus->gf1.reg_irqstat); - if (status == 0) - return IRQ_RETVAL(handled); - handled = 1; - /* snd_printk(KERN_DEBUG "IRQ: status = 0x%x\n", status); */ - if (status & 0x02) { - STAT_ADD(gus->gf1.interrupt_stat_midi_in); - if (gus->gf1.interrupt_handler_midi_in) - gus->gf1.interrupt_handler_midi_in(gus); - } - if (status & 0x01) { - STAT_ADD(gus->gf1.interrupt_stat_midi_out); - if (gus->gf1.interrupt_handler_midi_out) - gus->gf1.interrupt_handler_midi_out(gus); - } - if (status & (0x20 | 0x40)) { - unsigned int already, _current_; - unsigned char voice_status, voice; - struct snd_gus_voice *pvoice; - - already = 0; - while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) { - voice = voice_status & 0x1f; - _current_ = 1 << voice; - if (already & _current_) - continue; /* multi request */ - already |= _current_; /* mark request */ -#if 0 - printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, " - "voice_verify = %i\n", - voice, voice_status, inb(GUSP(gus, GF1PAGE))); -#endif - pvoice = &gus->gf1.voices[voice]; - if (pvoice->use) { - if (!(voice_status & 0x80)) { /* voice position IRQ */ - STAT_ADD(pvoice->interrupt_stat_wave); - pvoice->handler_wave(gus, pvoice); - } - if (!(voice_status & 0x40)) { /* volume ramp IRQ */ - STAT_ADD(pvoice->interrupt_stat_volume); - pvoice->handler_volume(gus, pvoice); - } - } else { - STAT_ADD(gus->gf1.interrupt_stat_voice_lost); - snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); - snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - } - } - } - if (status & 0x04) { - STAT_ADD(gus->gf1.interrupt_stat_timer1); - if (gus->gf1.interrupt_handler_timer1) - gus->gf1.interrupt_handler_timer1(gus); - } - if (status & 0x08) { - STAT_ADD(gus->gf1.interrupt_stat_timer2); - if (gus->gf1.interrupt_handler_timer2) - gus->gf1.interrupt_handler_timer2(gus); - } - if (status & 0x80) { - if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { - STAT_ADD(gus->gf1.interrupt_stat_dma_write); - if (gus->gf1.interrupt_handler_dma_write) - gus->gf1.interrupt_handler_dma_write(gus); - } - if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { - STAT_ADD(gus->gf1.interrupt_stat_dma_read); - if (gus->gf1.interrupt_handler_dma_read) - gus->gf1.interrupt_handler_dma_read(gus); - } - } - if (--loop > 0) - goto __again; - return IRQ_NONE; -} - -#ifdef CONFIG_SND_DEBUG -static void snd_gus_irq_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_gus_card *gus; - struct snd_gus_voice *pvoice; - int idx; - - gus = entry->private_data; - snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out); - snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in); - snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1); - snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2); - snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write); - snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read); - snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost); - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n", - idx, - pvoice->interrupt_stat_wave, - pvoice->interrupt_stat_volume); - } -} - -void snd_gus_irq_profile_init(struct snd_gus_card *gus) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(gus->card, "gusirq", &entry)) - snd_info_set_text_ops(entry, gus, snd_gus_irq_info_read); -} - -#endif diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_main.c b/ANDROID_3.4.5/sound/isa/gus/gus_main.c deleted file mode 100644 index 4490ee44..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_main.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Routines for Gravis UltraSound soundcards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards"); -MODULE_LICENSE("GPL"); - -static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches); - -int snd_gus_use_inc(struct snd_gus_card * gus) -{ - if (!try_module_get(gus->card->module)) - return 0; - return 1; -} - -void snd_gus_use_dec(struct snd_gus_card * gus) -{ - module_put(gus->card->module); -} - -static int snd_gus_joystick_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 31; - return 0; -} - -static int snd_gus_joystick_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = gus->joystick_dac & 31; - return 0; -} - -static int snd_gus_joystick_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval; - - nval = ucontrol->value.integer.value[0] & 31; - spin_lock_irqsave(&gus->reg_lock, flags); - change = gus->joystick_dac != nval; - gus->joystick_dac = nval; - snd_gf1_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_gus_joystick_control = { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "Joystick Speed", - .info = snd_gus_joystick_info, - .get = snd_gus_joystick_get, - .put = snd_gus_joystick_put -}; - -static void snd_gus_init_control(struct snd_gus_card *gus) -{ - if (!gus->ace_flag) - snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, gus)); -} - -/* - * - */ - -static int snd_gus_free(struct snd_gus_card *gus) -{ - if (gus->gf1.res_port2 == NULL) - goto __hw_end; - snd_gf1_stop(gus); - snd_gus_init_dma_irq(gus, 0); - __hw_end: - release_and_free_resource(gus->gf1.res_port1); - release_and_free_resource(gus->gf1.res_port2); - if (gus->gf1.irq >= 0) - free_irq(gus->gf1.irq, (void *) gus); - if (gus->gf1.dma1 >= 0) { - disable_dma(gus->gf1.dma1); - free_dma(gus->gf1.dma1); - } - if (!gus->equal_dma && gus->gf1.dma2 >= 0) { - disable_dma(gus->gf1.dma2); - free_dma(gus->gf1.dma2); - } - kfree(gus); - return 0; -} - -static int snd_gus_dev_free(struct snd_device *device) -{ - struct snd_gus_card *gus = device->device_data; - return snd_gus_free(gus); -} - -int snd_gus_create(struct snd_card *card, - unsigned long port, - int irq, int dma1, int dma2, - int timer_dev, - int voices, - int pcm_channels, - int effect, - struct snd_gus_card **rgus) -{ - struct snd_gus_card *gus; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_gus_dev_free, - }; - - *rgus = NULL; - gus = kzalloc(sizeof(*gus), GFP_KERNEL); - if (gus == NULL) - return -ENOMEM; - spin_lock_init(&gus->reg_lock); - spin_lock_init(&gus->voice_alloc); - spin_lock_init(&gus->active_voice_lock); - spin_lock_init(&gus->event_lock); - spin_lock_init(&gus->dma_lock); - spin_lock_init(&gus->pcm_volume_level_lock); - spin_lock_init(&gus->uart_cmd_lock); - mutex_init(&gus->dma_mutex); - gus->gf1.irq = -1; - gus->gf1.dma1 = -1; - gus->gf1.dma2 = -1; - gus->card = card; - gus->gf1.port = port; - /* fill register variables for speedup */ - gus->gf1.reg_page = GUSP(gus, GF1PAGE); - gus->gf1.reg_regsel = GUSP(gus, GF1REGSEL); - gus->gf1.reg_data8 = GUSP(gus, GF1DATAHIGH); - gus->gf1.reg_data16 = GUSP(gus, GF1DATALOW); - gus->gf1.reg_irqstat = GUSP(gus, IRQSTAT); - gus->gf1.reg_dram = GUSP(gus, DRAM); - gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL); - gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA); - /* allocate resources */ - if ((gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)")) == NULL) { - snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port); - snd_gus_free(gus); - return -EBUSY; - } - if ((gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)")) == NULL) { - snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100); - snd_gus_free(gus); - return -EBUSY; - } - if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) { - snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq); - snd_gus_free(gus); - return -EBUSY; - } - gus->gf1.irq = irq; - if (request_dma(dma1, "GUS - 1")) { - snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1); - snd_gus_free(gus); - return -EBUSY; - } - gus->gf1.dma1 = dma1; - if (dma2 >= 0 && dma1 != dma2) { - if (request_dma(dma2, "GUS - 2")) { - snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2); - snd_gus_free(gus); - return -EBUSY; - } - gus->gf1.dma2 = dma2; - } else { - gus->gf1.dma2 = gus->gf1.dma1; - gus->equal_dma = 1; - } - gus->timer_dev = timer_dev; - if (voices < 14) - voices = 14; - if (voices > 32) - voices = 32; - if (pcm_channels < 0) - pcm_channels = 0; - if (pcm_channels > 8) - pcm_channels = 8; - pcm_channels++; - pcm_channels &= ~1; - gus->gf1.effect = effect ? 1 : 0; - gus->gf1.active_voices = voices; - gus->gf1.pcm_channels = pcm_channels; - gus->gf1.volume_ramp = 25; - gus->gf1.smooth_pan = 1; - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { - snd_gus_free(gus); - return err; - } - *rgus = gus; - return 0; -} - -/* - * Memory detection routine for plain GF1 soundcards - */ - -static int snd_gus_detect_memory(struct snd_gus_card * gus) -{ - int l, idx, local; - unsigned char d; - - snd_gf1_poke(gus, 0L, 0xaa); - snd_gf1_poke(gus, 1L, 0x55); - if (snd_gf1_peek(gus, 0L) != 0xaa || snd_gf1_peek(gus, 1L) != 0x55) { - snd_printk(KERN_ERR "plain GF1 card at 0x%lx without onboard DRAM?\n", gus->gf1.port); - return -ENOMEM; - } - for (idx = 1, d = 0xab; idx < 4; idx++, d++) { - local = idx << 18; - snd_gf1_poke(gus, local, d); - snd_gf1_poke(gus, local + 1, d + 1); - if (snd_gf1_peek(gus, local) != d || - snd_gf1_peek(gus, local + 1) != d + 1 || - snd_gf1_peek(gus, 0L) != 0xaa) - break; - } -#if 1 - gus->gf1.memory = idx << 18; -#else - gus->gf1.memory = 256 * 1024; -#endif - for (l = 0, local = gus->gf1.memory; l < 4; l++, local -= 256 * 1024) { - gus->gf1.mem_alloc.banks_8[l].address = - gus->gf1.mem_alloc.banks_8[l].size = 0; - gus->gf1.mem_alloc.banks_16[l].address = l << 18; - gus->gf1.mem_alloc.banks_16[l].size = local > 0 ? 256 * 1024 : 0; - } - gus->gf1.mem_alloc.banks_8[0].size = gus->gf1.memory; - return 0; /* some memory were detected */ -} - -static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches) -{ - struct snd_card *card; - unsigned long flags; - int irq, dma1, dma2; - static unsigned char irqs[16] = - {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7}; - static unsigned char dmas[8] = - {6, 1, 0, 2, 0, 3, 4, 5}; - - if (snd_BUG_ON(!gus)) - return -EINVAL; - card = gus->card; - if (snd_BUG_ON(!card)) - return -EINVAL; - - gus->mix_cntrl_reg &= 0xf8; - gus->mix_cntrl_reg |= 0x01; /* disable MIC, LINE IN, enable LINE OUT */ - if (gus->codec_flag || gus->ess_flag) { - gus->mix_cntrl_reg &= ~1; /* enable LINE IN */ - gus->mix_cntrl_reg |= 4; /* enable MIC */ - } - dma1 = gus->gf1.dma1; - dma1 = abs(dma1); - dma1 = dmas[dma1 & 7]; - dma2 = gus->gf1.dma2; - dma2 = abs(dma2); - dma2 = dmas[dma2 & 7]; - dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3); - - if ((dma1 & 7) == 0 || (dma2 & 7) == 0) { - snd_printk(KERN_ERR "Error! DMA isn't defined.\n"); - return -EINVAL; - } - irq = gus->gf1.irq; - irq = abs(irq); - irq = irqs[irq & 0x0f]; - if (irq == 0) { - snd_printk(KERN_ERR "Error! IRQ isn't defined.\n"); - return -EINVAL; - } - irq |= 0x40; -#if 0 - card->mixer.mix_ctrl_reg |= 0x10; -#endif - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(5, GUSP(gus, REGCNTRLS)); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(0x00, GUSP(gus, IRQDMACNTRLREG)); - outb(0, GUSP(gus, REGCNTRLS)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - - udelay(100); - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(dma1, GUSP(gus, IRQDMACNTRLREG)); - if (latches) { - outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(irq, GUSP(gus, IRQDMACNTRLREG)); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - - udelay(100); - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(dma1, GUSP(gus, IRQDMACNTRLREG)); - if (latches) { - outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(irq, GUSP(gus, IRQDMACNTRLREG)); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - - snd_gf1_delay(gus); - - if (latches) - gus->mix_cntrl_reg |= 0x08; /* enable latches */ - else - gus->mix_cntrl_reg &= ~0x08; /* disable latches */ - spin_lock_irqsave(&gus->reg_lock, flags); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(0, GUSP(gus, GF1PAGE)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - - return 0; -} - -static int snd_gus_check_version(struct snd_gus_card * gus) -{ - unsigned long flags; - unsigned char val, rev; - struct snd_card *card; - - card = gus->card; - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x20, GUSP(gus, REGCNTRLS)); - val = inb(GUSP(gus, REGCNTRLS)); - rev = inb(GUSP(gus, BOARDVERSION)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - snd_printdd("GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus->gf1.port, val, rev); - strcpy(card->driver, "GUS"); - strcpy(card->longname, "Gravis UltraSound Classic (2.4)"); - if ((val != 255 && (val & 0x06)) || (rev >= 5 && rev != 255)) { - if (rev >= 5 && rev <= 9) { - gus->ics_flag = 1; - if (rev == 5) - gus->ics_flipped = 1; - card->longname[27] = '3'; - card->longname[29] = rev == 5 ? '5' : '7'; - } - if (rev >= 10 && rev != 255) { - if (rev >= 10 && rev <= 11) { - strcpy(card->driver, "GUS MAX"); - strcpy(card->longname, "Gravis UltraSound MAX"); - gus->max_flag = 1; - } else if (rev == 0x30) { - strcpy(card->driver, "GUS ACE"); - strcpy(card->longname, "Gravis UltraSound Ace"); - gus->ace_flag = 1; - } else if (rev == 0x50) { - strcpy(card->driver, "GUS Extreme"); - strcpy(card->longname, "Gravis UltraSound Extreme"); - gus->ess_flag = 1; - } else { - snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); - snd_printk(KERN_ERR " please - report to \n"); - } - } - } - strcpy(card->shortname, card->longname); - gus->uart_enable = 1; /* standard GUSes doesn't have midi uart trouble */ - snd_gus_init_control(gus); - return 0; -} - -int snd_gus_initialize(struct snd_gus_card *gus) -{ - int err; - - if (!gus->interwave) { - if ((err = snd_gus_check_version(gus)) < 0) { - snd_printk(KERN_ERR "version check failed\n"); - return err; - } - if ((err = snd_gus_detect_memory(gus)) < 0) - return err; - } - if ((err = snd_gus_init_dma_irq(gus, 1)) < 0) - return err; - snd_gf1_start(gus); - gus->initialized = 1; - return 0; -} - - /* gus_io.c */ -EXPORT_SYMBOL(snd_gf1_delay); -EXPORT_SYMBOL(snd_gf1_write8); -EXPORT_SYMBOL(snd_gf1_look8); -EXPORT_SYMBOL(snd_gf1_write16); -EXPORT_SYMBOL(snd_gf1_look16); -EXPORT_SYMBOL(snd_gf1_i_write8); -EXPORT_SYMBOL(snd_gf1_i_look8); -EXPORT_SYMBOL(snd_gf1_i_look16); -EXPORT_SYMBOL(snd_gf1_dram_addr); -EXPORT_SYMBOL(snd_gf1_write_addr); -EXPORT_SYMBOL(snd_gf1_poke); -EXPORT_SYMBOL(snd_gf1_peek); - /* gus_reset.c */ -EXPORT_SYMBOL(snd_gf1_alloc_voice); -EXPORT_SYMBOL(snd_gf1_free_voice); -EXPORT_SYMBOL(snd_gf1_ctrl_stop); -EXPORT_SYMBOL(snd_gf1_stop_voice); - /* gus_mixer.c */ -EXPORT_SYMBOL(snd_gf1_new_mixer); - /* gus_pcm.c */ -EXPORT_SYMBOL(snd_gf1_pcm_new); - /* gus.c */ -EXPORT_SYMBOL(snd_gus_use_inc); -EXPORT_SYMBOL(snd_gus_use_dec); -EXPORT_SYMBOL(snd_gus_create); -EXPORT_SYMBOL(snd_gus_initialize); - /* gus_irq.c */ -EXPORT_SYMBOL(snd_gus_interrupt); - /* gus_uart.c */ -EXPORT_SYMBOL(snd_gf1_rawmidi_new); - /* gus_dram.c */ -EXPORT_SYMBOL(snd_gus_dram_write); -EXPORT_SYMBOL(snd_gus_dram_read); - /* gus_volume.c */ -EXPORT_SYMBOL(snd_gf1_lvol_to_gvol_raw); -EXPORT_SYMBOL(snd_gf1_translate_freq); - /* gus_mem.c */ -EXPORT_SYMBOL(snd_gf1_mem_alloc); -EXPORT_SYMBOL(snd_gf1_mem_xfree); -EXPORT_SYMBOL(snd_gf1_mem_free); -EXPORT_SYMBOL(snd_gf1_mem_lock); - -/* - * INIT part - */ - -static int __init alsa_gus_init(void) -{ - return 0; -} - -static void __exit alsa_gus_exit(void) -{ -} - -module_init(alsa_gus_init) -module_exit(alsa_gus_exit) diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_mem.c b/ANDROID_3.4.5/sound/isa/gus/gus_mem.c deleted file mode 100644 index af888a02..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_mem.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * GUS's memory allocation routines / bottom layer - * - * - * 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 - -#ifdef CONFIG_SND_DEBUG -static void snd_gf1_mem_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer); -#endif - -void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup) -{ - if (!xup) { - mutex_lock(&alloc->memory_mutex); - } else { - mutex_unlock(&alloc->memory_mutex); - } -} - -static struct snd_gf1_mem_block *snd_gf1_mem_xalloc(struct snd_gf1_mem * alloc, - struct snd_gf1_mem_block * block) -{ - struct snd_gf1_mem_block *pblock, *nblock; - - nblock = kmalloc(sizeof(struct snd_gf1_mem_block), GFP_KERNEL); - if (nblock == NULL) - return NULL; - *nblock = *block; - pblock = alloc->first; - while (pblock) { - if (pblock->ptr > nblock->ptr) { - nblock->prev = pblock->prev; - nblock->next = pblock; - pblock->prev = nblock; - if (pblock == alloc->first) - alloc->first = nblock; - else - nblock->prev->next = nblock; - mutex_unlock(&alloc->memory_mutex); - return NULL; - } - pblock = pblock->next; - } - nblock->next = NULL; - if (alloc->last == NULL) { - nblock->prev = NULL; - alloc->first = alloc->last = nblock; - } else { - nblock->prev = alloc->last; - alloc->last->next = nblock; - alloc->last = nblock; - } - return nblock; -} - -int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block) -{ - if (block->share) { /* ok.. shared block */ - block->share--; - mutex_unlock(&alloc->memory_mutex); - return 0; - } - if (alloc->first == block) { - alloc->first = block->next; - if (block->next) - block->next->prev = NULL; - } else { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - if (alloc->last == block) { - alloc->last = block->prev; - if (block->prev) - block->prev->next = NULL; - } else { - block->next->prev = block->prev; - if (block->prev) - block->prev->next = block->next; - } - kfree(block->name); - kfree(block); - return 0; -} - -static struct snd_gf1_mem_block *snd_gf1_mem_look(struct snd_gf1_mem * alloc, - unsigned int address) -{ - struct snd_gf1_mem_block *block; - - for (block = alloc->first; block; block = block->next) { - if (block->ptr == address) { - return block; - } - } - return NULL; -} - -static struct snd_gf1_mem_block *snd_gf1_mem_share(struct snd_gf1_mem * alloc, - unsigned int *share_id) -{ - struct snd_gf1_mem_block *block; - - if (!share_id[0] && !share_id[1] && - !share_id[2] && !share_id[3]) - return NULL; - for (block = alloc->first; block; block = block->next) - if (!memcmp(share_id, block->share_id, - sizeof(block->share_id))) - return block; - return NULL; -} - -static int snd_gf1_mem_find(struct snd_gf1_mem * alloc, - struct snd_gf1_mem_block * block, - unsigned int size, int w_16, int align) -{ - struct snd_gf1_bank_info *info = w_16 ? alloc->banks_16 : alloc->banks_8; - unsigned int idx, boundary; - int size1; - struct snd_gf1_mem_block *pblock; - unsigned int ptr1, ptr2; - - if (w_16 && align < 2) - align = 2; - block->flags = w_16 ? SNDRV_GF1_MEM_BLOCK_16BIT : 0; - block->owner = SNDRV_GF1_MEM_OWNER_DRIVER; - block->share = 0; - block->share_id[0] = block->share_id[1] = - block->share_id[2] = block->share_id[3] = 0; - block->name = NULL; - block->prev = block->next = NULL; - for (pblock = alloc->first, idx = 0; pblock; pblock = pblock->next) { - while (pblock->ptr >= (boundary = info[idx].address + info[idx].size)) - idx++; - while (pblock->ptr + pblock->size >= (boundary = info[idx].address + info[idx].size)) - idx++; - ptr2 = boundary; - if (pblock->next) { - if (pblock->ptr + pblock->size == pblock->next->ptr) - continue; - if (pblock->next->ptr < boundary) - ptr2 = pblock->next->ptr; - } - ptr1 = ALIGN(pblock->ptr + pblock->size, align); - if (ptr1 >= ptr2) - continue; - size1 = ptr2 - ptr1; - if ((int)size <= size1) { - block->ptr = ptr1; - block->size = size; - return 0; - } - } - while (++idx < 4) { - if (size <= info[idx].size) { - /* I assume that bank address is already aligned.. */ - block->ptr = info[idx].address; - block->size = size; - return 0; - } - } - return -ENOMEM; -} - -struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owner, - char *name, int size, int w_16, int align, - unsigned int *share_id) -{ - struct snd_gf1_mem_block block, *nblock; - - snd_gf1_mem_lock(alloc, 0); - if (share_id != NULL) { - nblock = snd_gf1_mem_share(alloc, share_id); - if (nblock != NULL) { - if (size != (int)nblock->size) { - /* TODO: remove in the future */ - snd_printk(KERN_ERR "snd_gf1_mem_alloc - share: sizes differ\n"); - goto __std; - } - nblock->share++; - snd_gf1_mem_lock(alloc, 1); - return NULL; - } - } - __std: - if (snd_gf1_mem_find(alloc, &block, size, w_16, align) < 0) { - snd_gf1_mem_lock(alloc, 1); - return NULL; - } - if (share_id != NULL) - memcpy(&block.share_id, share_id, sizeof(block.share_id)); - block.owner = owner; - block.name = kstrdup(name, GFP_KERNEL); - nblock = snd_gf1_mem_xalloc(alloc, &block); - snd_gf1_mem_lock(alloc, 1); - return nblock; -} - -int snd_gf1_mem_free(struct snd_gf1_mem * alloc, unsigned int address) -{ - int result; - struct snd_gf1_mem_block *block; - - snd_gf1_mem_lock(alloc, 0); - if ((block = snd_gf1_mem_look(alloc, address)) != NULL) { - result = snd_gf1_mem_xfree(alloc, block); - snd_gf1_mem_lock(alloc, 1); - return result; - } - snd_gf1_mem_lock(alloc, 1); - return -EINVAL; -} - -int snd_gf1_mem_init(struct snd_gus_card * gus) -{ - struct snd_gf1_mem *alloc; - struct snd_gf1_mem_block block; -#ifdef CONFIG_SND_DEBUG - struct snd_info_entry *entry; -#endif - - alloc = &gus->gf1.mem_alloc; - mutex_init(&alloc->memory_mutex); - alloc->first = alloc->last = NULL; - if (!gus->gf1.memory) - return 0; - - memset(&block, 0, sizeof(block)); - block.owner = SNDRV_GF1_MEM_OWNER_DRIVER; - if (gus->gf1.enh_mode) { - block.ptr = 0; - block.size = 1024; - block.name = kstrdup("InterWave LFOs", GFP_KERNEL); - if (snd_gf1_mem_xalloc(alloc, &block) == NULL) - return -ENOMEM; - } - block.ptr = gus->gf1.default_voice_address; - block.size = 4; - block.name = kstrdup("Voice default (NULL's)", GFP_KERNEL); - if (snd_gf1_mem_xalloc(alloc, &block) == NULL) - return -ENOMEM; -#ifdef CONFIG_SND_DEBUG - if (! snd_card_proc_new(gus->card, "gusmem", &entry)) - snd_info_set_text_ops(entry, gus, snd_gf1_mem_info_read); -#endif - return 0; -} - -int snd_gf1_mem_done(struct snd_gus_card * gus) -{ - struct snd_gf1_mem *alloc; - struct snd_gf1_mem_block *block, *nblock; - - alloc = &gus->gf1.mem_alloc; - block = alloc->first; - while (block) { - nblock = block->next; - snd_gf1_mem_xfree(alloc, block); - block = nblock; - } - return 0; -} - -#ifdef CONFIG_SND_DEBUG -static void snd_gf1_mem_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_gus_card *gus; - struct snd_gf1_mem *alloc; - struct snd_gf1_mem_block *block; - unsigned int total, used; - int i; - - gus = entry->private_data; - alloc = &gus->gf1.mem_alloc; - mutex_lock(&alloc->memory_mutex); - snd_iprintf(buffer, "8-bit banks : \n "); - for (i = 0; i < 4; i++) - snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_8[i].address, alloc->banks_8[i].size >> 10, i + 1 < 4 ? "," : ""); - snd_iprintf(buffer, "\n" - "16-bit banks : \n "); - for (i = total = 0; i < 4; i++) { - snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_16[i].address, alloc->banks_16[i].size >> 10, i + 1 < 4 ? "," : ""); - total += alloc->banks_16[i].size; - } - snd_iprintf(buffer, "\n"); - used = 0; - for (block = alloc->first, i = 0; block; block = block->next, i++) { - used += block->size; - snd_iprintf(buffer, "Block %i at 0x%lx onboard 0x%x size %i (0x%x):\n", i, (long) block, block->ptr, block->size, block->size); - if (block->share || - block->share_id[0] || block->share_id[1] || - block->share_id[2] || block->share_id[3]) - snd_iprintf(buffer, " Share : %i [id0 0x%x] [id1 0x%x] [id2 0x%x] [id3 0x%x]\n", - block->share, - block->share_id[0], block->share_id[1], - block->share_id[2], block->share_id[3]); - snd_iprintf(buffer, " Flags :%s\n", - block->flags & SNDRV_GF1_MEM_BLOCK_16BIT ? " 16-bit" : ""); - snd_iprintf(buffer, " Owner : "); - switch (block->owner) { - case SNDRV_GF1_MEM_OWNER_DRIVER: - snd_iprintf(buffer, "driver - %s\n", block->name); - break; - case SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE: - snd_iprintf(buffer, "SIMPLE wave\n"); - break; - case SNDRV_GF1_MEM_OWNER_WAVE_GF1: - snd_iprintf(buffer, "GF1 wave\n"); - break; - case SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF: - snd_iprintf(buffer, "IWFFFF wave\n"); - break; - default: - snd_iprintf(buffer, "unknown\n"); - } - } - snd_iprintf(buffer, " Total: memory = %i, used = %i, free = %i\n", - total, used, total - used); - mutex_unlock(&alloc->memory_mutex); -#if 0 - ultra_iprintf(buffer, " Verify: free = %i, max 8-bit block = %i, max 16-bit block = %i\n", - ultra_memory_free_size(card, &card->gf1.mem_alloc), - ultra_memory_free_block(card, &card->gf1.mem_alloc, 0), - ultra_memory_free_block(card, &card->gf1.mem_alloc, 1)); -#endif -} -#endif diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_mem_proc.c b/ANDROID_3.4.5/sound/isa/gus/gus_mem_proc.c deleted file mode 100644 index 2ccb3fad..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_mem_proc.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * GUS's memory access via proc filesystem - * - * - * 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 - -struct gus_proc_private { - int rom; /* data are in ROM */ - unsigned int address; - unsigned int size; - struct snd_gus_card * gus; -}; - -static ssize_t snd_gf1_mem_proc_dump(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct gus_proc_private *priv = entry->private_data; - struct snd_gus_card *gus = priv->gus; - int err; - - err = snd_gus_dram_read(gus, buf, pos, count, priv->rom); - if (err < 0) - return err; - return count; -} - -static void snd_gf1_mem_proc_free(struct snd_info_entry *entry) -{ - struct gus_proc_private *priv = entry->private_data; - kfree(priv); -} - -static struct snd_info_entry_ops snd_gf1_mem_proc_ops = { - .read = snd_gf1_mem_proc_dump, -}; - -int snd_gf1_mem_proc_init(struct snd_gus_card * gus) -{ - int idx; - char name[16]; - struct gus_proc_private *priv; - struct snd_info_entry *entry; - - for (idx = 0; idx < 4; idx++) { - if (gus->gf1.mem_alloc.banks_8[idx].size > 0) { - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - priv->gus = gus; - sprintf(name, "gus-ram-%i", idx); - if (! snd_card_proc_new(gus->card, name, &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = priv; - entry->private_free = snd_gf1_mem_proc_free; - entry->c.ops = &snd_gf1_mem_proc_ops; - priv->address = gus->gf1.mem_alloc.banks_8[idx].address; - priv->size = entry->size = gus->gf1.mem_alloc.banks_8[idx].size; - } - } - } - for (idx = 0; idx < 4; idx++) { - if (gus->gf1.rom_present & (1 << idx)) { - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - priv->rom = 1; - priv->gus = gus; - sprintf(name, "gus-rom-%i", idx); - if (! snd_card_proc_new(gus->card, name, &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = priv; - entry->private_free = snd_gf1_mem_proc_free; - entry->c.ops = &snd_gf1_mem_proc_ops; - priv->address = idx * 4096 * 1024; - priv->size = entry->size = gus->gf1.rom_memory; - } - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_mixer.c b/ANDROID_3.4.5/sound/isa/gus/gus_mixer.c deleted file mode 100644 index 0dd43414..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_mixer.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of ICS 2101 chip and "mixer" in GF1 chip - * - * - * 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 - -/* - * - */ - -#define GF1_SINGLE(xname, xindex, shift, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_gf1_info_single, \ - .get = snd_gf1_get_single, .put = snd_gf1_put_single, \ - .private_value = shift | (invert << 8) } - -#define snd_gf1_info_single snd_ctl_boolean_mono_info - -static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value >> 8) & 1; - - ucontrol->value.integer.value[0] = (gus->mix_cntrl_reg >> shift) & 1; - if (invert) - ucontrol->value.integer.value[0] ^= 1; - return 0; -} - -static int snd_gf1_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value >> 8) & 1; - int change; - unsigned char oval, nval; - - nval = ucontrol->value.integer.value[0] & 1; - if (invert) - nval ^= 1; - nval <<= shift; - spin_lock_irqsave(&gus->reg_lock, flags); - oval = gus->mix_cntrl_reg; - nval = (oval & ~(1 << shift)) | nval; - change = nval != oval; - outb(gus->mix_cntrl_reg = nval, GUSP(gus, MIXCNTRLREG)); - outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return change; -} - -#define ICS_DOUBLE(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_ics_info_double, \ - .get = snd_ics_get_double, .put = snd_ics_put_double, \ - .private_value = addr } - -static int snd_ics_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 127; - return 0; -} - -static int snd_ics_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int addr = kcontrol->private_value & 0xff; - unsigned char left, right; - - spin_lock_irqsave(&gus->reg_lock, flags); - left = gus->gf1.ics_regs[addr][0]; - right = gus->gf1.ics_regs[addr][1]; - spin_unlock_irqrestore(&gus->reg_lock, flags); - ucontrol->value.integer.value[0] = left & 127; - ucontrol->value.integer.value[1] = right & 127; - return 0; -} - -static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int addr = kcontrol->private_value & 0xff; - int change; - unsigned char val1, val2, oval1, oval2, tmp; - - val1 = ucontrol->value.integer.value[0] & 127; - val2 = ucontrol->value.integer.value[1] & 127; - spin_lock_irqsave(&gus->reg_lock, flags); - oval1 = gus->gf1.ics_regs[addr][0]; - oval2 = gus->gf1.ics_regs[addr][1]; - change = val1 != oval1 || val2 != oval2; - gus->gf1.ics_regs[addr][0] = val1; - gus->gf1.ics_regs[addr][1] = val2; - if (gus->ics_flag && gus->ics_flipped && - (addr == SNDRV_ICS_GF1_DEV || addr == SNDRV_ICS_MASTER_DEV)) { - tmp = val1; - val1 = val2; - val2 = tmp; - } - addr <<= 3; - outb(addr | 0, GUSP(gus, MIXCNTRLPORT)); - outb(1, GUSP(gus, MIXDATAPORT)); - outb(addr | 2, GUSP(gus, MIXCNTRLPORT)); - outb((unsigned char) val1, GUSP(gus, MIXDATAPORT)); - outb(addr | 1, GUSP(gus, MIXCNTRLPORT)); - outb(2, GUSP(gus, MIXDATAPORT)); - outb(addr | 3, GUSP(gus, MIXCNTRLPORT)); - outb((unsigned char) val2, GUSP(gus, MIXDATAPORT)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_gf1_controls[] = { -GF1_SINGLE("Master Playback Switch", 0, 1, 1), -GF1_SINGLE("Line Switch", 0, 0, 1), -GF1_SINGLE("Mic Switch", 0, 2, 0) -}; - -static struct snd_kcontrol_new snd_ics_controls[] = { -GF1_SINGLE("Master Playback Switch", 0, 1, 1), -ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV), -ICS_DOUBLE("Synth Playback Volume", 0, SNDRV_ICS_GF1_DEV), -GF1_SINGLE("Line Switch", 0, 0, 1), -ICS_DOUBLE("Line Playback Volume", 0, SNDRV_ICS_LINE_DEV), -GF1_SINGLE("Mic Switch", 0, 2, 0), -ICS_DOUBLE("Mic Playback Volume", 0, SNDRV_ICS_MIC_DEV), -ICS_DOUBLE("CD Playback Volume", 0, SNDRV_ICS_CD_DEV) -}; - -int snd_gf1_new_mixer(struct snd_gus_card * gus) -{ - struct snd_card *card; - unsigned int idx, max; - int err; - - if (snd_BUG_ON(!gus)) - return -EINVAL; - card = gus->card; - if (snd_BUG_ON(!card)) - return -EINVAL; - - if (gus->ics_flag) - snd_component_add(card, "ICS2101"); - if (card->mixername[0] == '\0') { - strcpy(card->mixername, gus->ics_flag ? "GF1,ICS2101" : "GF1"); - } else { - if (gus->ics_flag) - strcat(card->mixername, ",ICS2101"); - strcat(card->mixername, ",GF1"); - } - - if (!gus->ics_flag) { - max = gus->ess_flag ? 1 : ARRAY_SIZE(snd_gf1_controls); - for (idx = 0; idx < max; idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus))) < 0) - return err; - } - } else { - for (idx = 0; idx < ARRAY_SIZE(snd_ics_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus))) < 0) - return err; - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_pcm.c b/ANDROID_3.4.5/sound/isa/gus/gus_pcm.c deleted file mode 100644 index 2dcf45bf..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_pcm.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of GF1 chip (PCM things) - * - * InterWave chips supports interleaved DMA, but this feature isn't used in - * this code. - * - * This code emulates autoinit DMA transfer for playback, recording by GF1 - * chip doesn't support autoinit DMA. - * - * - * 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 "gus_tables.h" - -/* maximum rate */ - -#define SNDRV_GF1_PCM_RATE 48000 - -#define SNDRV_GF1_PCM_PFLG_NONE 0 -#define SNDRV_GF1_PCM_PFLG_ACTIVE (1<<0) -#define SNDRV_GF1_PCM_PFLG_NEUTRAL (2<<0) - -struct gus_pcm_private { - struct snd_gus_card * gus; - struct snd_pcm_substream *substream; - spinlock_t lock; - unsigned int voices; - struct snd_gus_voice *pvoices[2]; - unsigned int memory; - unsigned short flags; - unsigned char voice_ctrl, ramp_ctrl; - unsigned int bpos; - unsigned int blocks; - unsigned int block_size; - unsigned int dma_size; - wait_queue_head_t sleep; - atomic_t dma_count; - int final_volume; -}; - -static int snd_gf1_pcm_use_dma = 1; - -static void snd_gf1_pcm_block_change_ack(struct snd_gus_card * gus, void *private_data) -{ - struct gus_pcm_private *pcmp = private_data; - - if (pcmp) { - atomic_dec(&pcmp->dma_count); - wake_up(&pcmp->sleep); - } -} - -static int snd_gf1_pcm_block_change(struct snd_pcm_substream *substream, - unsigned int offset, - unsigned int addr, - unsigned int count) -{ - struct snd_gf1_dma_block block; - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - - count += offset & 31; - offset &= ~31; - /* - snd_printk(KERN_DEBUG "block change - offset = 0x%x, count = 0x%x\n", - offset, count); - */ - memset(&block, 0, sizeof(block)); - block.cmd = SNDRV_GF1_DMA_IRQ; - if (snd_pcm_format_unsigned(runtime->format)) - block.cmd |= SNDRV_GF1_DMA_UNSIGNED; - if (snd_pcm_format_width(runtime->format) == 16) - block.cmd |= SNDRV_GF1_DMA_16BIT; - block.addr = addr & ~31; - block.buffer = runtime->dma_area + offset; - block.buf_addr = runtime->dma_addr + offset; - block.count = count; - block.private_data = pcmp; - block.ack = snd_gf1_pcm_block_change_ack; - if (!snd_gf1_dma_transfer_block(pcmp->gus, &block, 0, 0)) - atomic_inc(&pcmp->dma_count); - return 0; -} - -static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - struct snd_gus_card * gus = pcmp->gus; - unsigned long flags; - unsigned char voice_ctrl, ramp_ctrl; - unsigned short rate; - unsigned int curr, begin, end; - unsigned short vol; - unsigned char pan; - unsigned int voice; - - spin_lock_irqsave(&pcmp->lock, flags); - if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) { - spin_unlock_irqrestore(&pcmp->lock, flags); - return; - } - pcmp->flags |= SNDRV_GF1_PCM_PFLG_ACTIVE; - pcmp->final_volume = 0; - spin_unlock_irqrestore(&pcmp->lock, flags); - rate = snd_gf1_translate_freq(gus, runtime->rate << 4); - /* enable WAVE IRQ */ - voice_ctrl = snd_pcm_format_width(runtime->format) == 16 ? 0x24 : 0x20; - /* enable RAMP IRQ + rollover */ - ramp_ctrl = 0x24; - if (pcmp->blocks == 1) { - voice_ctrl |= 0x08; /* loop enable */ - ramp_ctrl &= ~0x04; /* disable rollover */ - } - for (voice = 0; voice < pcmp->voices; voice++) { - begin = pcmp->memory + voice * (pcmp->dma_size / runtime->channels); - curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels; - end = curr + (pcmp->block_size / runtime->channels); - end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1; - /* - snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, " - "ctrl=0x%x, ramp=0x%x, rate=0x%x\n", - curr, begin, end, voice_ctrl, ramp_ctrl, rate); - */ - pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8; - vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number); - snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, pan); - snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, rate); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, begin << 4, voice_ctrl & 4); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, curr << 4, voice_ctrl & 4); - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME << 4); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0x2f); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, vol >> 8); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - if (!gus->gf1.enh_mode) { - snd_gf1_delay(gus); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - } - spin_lock_irqsave(&gus->reg_lock, flags); - for (voice = 0; voice < pcmp->voices; voice++) { - snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number); - if (gus->gf1.enh_mode) - snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, 0x00); /* deactivate voice */ - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - voice_ctrl &= ~0x20; - } - voice_ctrl |= 0x20; - if (!gus->gf1.enh_mode) { - snd_gf1_delay(gus); - for (voice = 0; voice < pcmp->voices; voice++) { - snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number); - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - voice_ctrl &= ~0x20; /* disable IRQ for next voice */ - } - } - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus, - struct snd_gus_voice *pvoice) -{ - struct gus_pcm_private * pcmp; - struct snd_pcm_runtime *runtime; - unsigned char voice_ctrl, ramp_ctrl; - unsigned int idx; - unsigned int end, step; - - if (!pvoice->private_data) { - snd_printd("snd_gf1_pcm: unknown wave irq?\n"); - snd_gf1_smart_stop_voice(gus, pvoice->number); - return; - } - pcmp = pvoice->private_data; - if (pcmp == NULL) { - snd_printd("snd_gf1_pcm: unknown wave irq?\n"); - snd_gf1_smart_stop_voice(gus, pvoice->number); - return; - } - gus = pcmp->gus; - runtime = pcmp->substream->runtime; - - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & ~0x8b; - ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03; -#if 0 - snd_gf1_select_voice(gus, pvoice->number); - printk(KERN_DEBUG "position = 0x%x\n", - (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); - snd_gf1_select_voice(gus, pcmp->pvoices[1]->number); - printk(KERN_DEBUG "position = 0x%x\n", - (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); - snd_gf1_select_voice(gus, pvoice->number); -#endif - pcmp->bpos++; - pcmp->bpos %= pcmp->blocks; - if (pcmp->bpos + 1 >= pcmp->blocks) { /* last block? */ - voice_ctrl |= 0x08; /* enable loop */ - } else { - ramp_ctrl |= 0x04; /* enable rollover */ - } - end = pcmp->memory + (((pcmp->bpos + 1) * pcmp->block_size) / runtime->channels); - end -= voice_ctrl & 4 ? 2 : 1; - step = pcmp->dma_size / runtime->channels; - voice_ctrl |= 0x20; - if (!pcmp->final_volume) { - ramp_ctrl |= 0x20; - ramp_ctrl &= ~0x03; - } - for (idx = 0; idx < pcmp->voices; idx++, end += step) { - snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4); - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - voice_ctrl &= ~0x20; - } - if (!gus->gf1.enh_mode) { - snd_gf1_delay(gus); - voice_ctrl |= 0x20; - for (idx = 0; idx < pcmp->voices; idx++) { - snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number); - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - voice_ctrl &= ~0x20; - } - } - spin_unlock(&gus->reg_lock); - - snd_pcm_period_elapsed(pcmp->substream); -#if 0 - if ((runtime->flags & SNDRV_PCM_FLG_MMAP) && - *runtime->state == SNDRV_PCM_STATE_RUNNING) { - end = pcmp->bpos * pcmp->block_size; - if (runtime->channels > 1) { - snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + (end / 2), pcmp->block_size / 2); - snd_gf1_pcm_block_change(pcmp->substream, end + (pcmp->block_size / 2), pcmp->memory + (pcmp->dma_size / 2) + (end / 2), pcmp->block_size / 2); - } else { - snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + end, pcmp->block_size); - } - } -#endif -} - -static void snd_gf1_pcm_interrupt_volume(struct snd_gus_card * gus, - struct snd_gus_voice * pvoice) -{ - unsigned short vol; - int cvoice; - struct gus_pcm_private *pcmp = pvoice->private_data; - - /* stop ramp, but leave rollover bit untouched */ - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - spin_unlock(&gus->reg_lock); - if (pcmp == NULL) - return; - /* are we active? */ - if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE)) - return; - /* load real volume - better precision */ - cvoice = pcmp->pvoices[0] == pvoice ? 0 : 1; - if (pcmp->substream == NULL) - return; - vol = !cvoice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); - pcmp->final_volume = 1; - spin_unlock(&gus->reg_lock); -} - -static void snd_gf1_pcm_volume_change(struct snd_gus_card * gus) -{ -} - -static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, - unsigned int pos, unsigned int count, - int w16, int invert) -{ - unsigned int len; - unsigned long flags; - - /* - printk(KERN_DEBUG - "poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", - (int)buf, pos, count, gus->gf1.port); - */ - while (count > 0) { - len = count; - if (len > 512) /* limit, to allow IRQ */ - len = 512; - count -= len; - if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01 | (invert ? 0x08 : 0x00)); - snd_gf1_dram_addr(gus, pos); - if (w16) { - outb(SNDRV_GF1_GW_DRAM_IO16, GUSP(gus, GF1REGSEL)); - outsw(GUSP(gus, GF1DATALOW), buf, len >> 1); - } else { - outsb(GUSP(gus, DRAM), buf, len); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - buf += 512; - pos += 512; - } else { - invert = invert ? 0x80 : 0x00; - if (w16) { - len >>= 1; - while (len--) { - snd_gf1_poke(gus, pos++, *buf++); - snd_gf1_poke(gus, pos++, *buf++ ^ invert); - } - } else { - while (len--) - snd_gf1_poke(gus, pos++, *buf++ ^ invert); - } - } - if (count > 0 && !in_interrupt()) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - return -EAGAIN; - } - } - return 0; -} - -static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, - int voice, - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int bpos, len; - - bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); - len = samples_to_bytes(runtime, count); - if (snd_BUG_ON(bpos > pcmp->dma_size)) - return -EIO; - if (snd_BUG_ON(bpos + len > pcmp->dma_size)) - return -EIO; - if (copy_from_user(runtime->dma_area + bpos, src, len)) - return -EFAULT; - if (snd_gf1_pcm_use_dma && len > 32) { - return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); - } else { - struct snd_gus_card *gus = pcmp->gus; - int err, w16, invert; - - w16 = (snd_pcm_format_width(runtime->format) == 16); - invert = snd_pcm_format_unsigned(runtime->format); - if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) - return err; - } - return 0; -} - -static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int bpos, len; - - bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); - len = samples_to_bytes(runtime, count); - if (snd_BUG_ON(bpos > pcmp->dma_size)) - return -EIO; - if (snd_BUG_ON(bpos + len > pcmp->dma_size)) - return -EIO; - snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count); - if (snd_gf1_pcm_use_dma && len > 32) { - return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); - } else { - struct snd_gus_card *gus = pcmp->gus; - int err, w16, invert; - - w16 = (snd_pcm_format_width(runtime->format) == 16); - invert = snd_pcm_format_unsigned(runtime->format); - if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) - return err; - } - return 0; -} - -static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - if (err > 0) { /* change */ - struct snd_gf1_mem_block *block; - if (pcmp->memory > 0) { - snd_gf1_mem_free(&gus->gf1.mem_alloc, pcmp->memory); - pcmp->memory = 0; - } - if ((block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_DRIVER, - "GF1 PCM", - runtime->dma_bytes, 1, 32, - NULL)) == NULL) - return -ENOMEM; - pcmp->memory = block->ptr; - } - pcmp->voices = params_channels(hw_params); - if (pcmp->pvoices[0] == NULL) { - if ((pcmp->pvoices[0] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0)) == NULL) - return -ENOMEM; - pcmp->pvoices[0]->handler_wave = snd_gf1_pcm_interrupt_wave; - pcmp->pvoices[0]->handler_volume = snd_gf1_pcm_interrupt_volume; - pcmp->pvoices[0]->volume_change = snd_gf1_pcm_volume_change; - pcmp->pvoices[0]->private_data = pcmp; - } - if (pcmp->voices > 1 && pcmp->pvoices[1] == NULL) { - if ((pcmp->pvoices[1] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0)) == NULL) - return -ENOMEM; - pcmp->pvoices[1]->handler_wave = snd_gf1_pcm_interrupt_wave; - pcmp->pvoices[1]->handler_volume = snd_gf1_pcm_interrupt_volume; - pcmp->pvoices[1]->volume_change = snd_gf1_pcm_volume_change; - pcmp->pvoices[1]->private_data = pcmp; - } else if (pcmp->voices == 1) { - if (pcmp->pvoices[1]) { - snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[1]); - pcmp->pvoices[1] = NULL; - } - } - return 0; -} - -static int snd_gf1_pcm_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - - snd_pcm_lib_free_pages(substream); - if (pcmp->pvoices[0]) { - snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[0]); - pcmp->pvoices[0] = NULL; - } - if (pcmp->pvoices[1]) { - snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[1]); - pcmp->pvoices[1] = NULL; - } - if (pcmp->memory > 0) { - snd_gf1_mem_free(&pcmp->gus->gf1.mem_alloc, pcmp->memory); - pcmp->memory = 0; - } - return 0; -} - -static int snd_gf1_pcm_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - - pcmp->bpos = 0; - pcmp->dma_size = snd_pcm_lib_buffer_bytes(substream); - pcmp->block_size = snd_pcm_lib_period_bytes(substream); - pcmp->blocks = pcmp->dma_size / pcmp->block_size; - return 0; -} - -static int snd_gf1_pcm_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - int voice; - - if (cmd == SNDRV_PCM_TRIGGER_START) { - snd_gf1_pcm_trigger_up(substream); - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - spin_lock(&pcmp->lock); - pcmp->flags &= ~SNDRV_GF1_PCM_PFLG_ACTIVE; - spin_unlock(&pcmp->lock); - voice = pcmp->pvoices[0]->number; - snd_gf1_stop_voices(gus, voice, voice); - if (pcmp->pvoices[1]) { - voice = pcmp->pvoices[1]->number; - snd_gf1_stop_voices(gus, voice, voice); - } - } else { - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int pos; - unsigned char voice_ctrl; - - pos = 0; - spin_lock(&gus->reg_lock); - if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) { - snd_gf1_select_voice(gus, pcmp->pvoices[0]->number); - voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); - pos = (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4) - pcmp->memory; - if (substream->runtime->channels > 1) - pos <<= 1; - pos = bytes_to_frames(runtime, pos); - } - spin_unlock(&gus->reg_lock); - return pos; -} - -static struct snd_ratnum clock = { - .num = 9878400/16, - .den_min = 2, - .den_max = 257, - .den_step = 1, -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { - .nrats = 1, - .rats = &clock, -}; - -static int snd_gf1_pcm_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - - gus->c_dma_size = params_buffer_bytes(hw_params); - gus->c_period_size = params_period_bytes(hw_params); - gus->c_pos = 0; - gus->gf1.pcm_rcntrl_reg = 0x21; /* IRQ at end, enable & start */ - if (params_channels(hw_params) > 1) - gus->gf1.pcm_rcntrl_reg |= 2; - if (gus->gf1.dma2 > 3) - gus->gf1.pcm_rcntrl_reg |= 4; - if (snd_pcm_format_unsigned(params_format(hw_params))) - gus->gf1.pcm_rcntrl_reg |= 0x80; - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_gf1_pcm_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_gf1_pcm_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RECORD_RATE, runtime->rate_den - 2); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0); /* disable sampling */ - snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); /* Sampling Control Register */ - snd_dma_program(gus->gf1.dma2, runtime->dma_addr, gus->c_period_size, DMA_MODE_READ); - return 0; -} - -static int snd_gf1_pcm_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - int val; - - if (cmd == SNDRV_PCM_TRIGGER_START) { - val = gus->gf1.pcm_rcntrl_reg; - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - val = 0; - } else { - return -EINVAL; - } - - spin_lock(&gus->reg_lock); - snd_gf1_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, val); - snd_gf1_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); - spin_unlock(&gus->reg_lock); - return 0; -} - -static snd_pcm_uframes_t snd_gf1_pcm_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - int pos = snd_dma_pointer(gus->gf1.dma2, gus->c_period_size); - pos = bytes_to_frames(substream->runtime, (gus->c_pos + pos) % gus->c_dma_size); - return pos; -} - -static void snd_gf1_pcm_interrupt_dma_read(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0); /* disable sampling */ - snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); /* Sampling Control Register */ - if (gus->pcm_cap_substream != NULL) { - snd_gf1_pcm_capture_prepare(gus->pcm_cap_substream); - snd_gf1_pcm_capture_trigger(gus->pcm_cap_substream, SNDRV_PCM_TRIGGER_START); - gus->c_pos += gus->c_period_size; - snd_pcm_period_elapsed(gus->pcm_cap_substream); - } -} - -static struct snd_pcm_hardware snd_gf1_pcm_playback = -{ - .info = SNDRV_PCM_INFO_NONINTERLEAVED, - .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5510, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_gf1_pcm_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100, - .rate_min = 5510, - .rate_max = 44100, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static void snd_gf1_pcm_playback_free(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static int snd_gf1_pcm_playback_open(struct snd_pcm_substream *substream) -{ - struct gus_pcm_private *pcmp; - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - pcmp = kzalloc(sizeof(*pcmp), GFP_KERNEL); - if (pcmp == NULL) - return -ENOMEM; - pcmp->gus = gus; - spin_lock_init(&pcmp->lock); - init_waitqueue_head(&pcmp->sleep); - atomic_set(&pcmp->dma_count, 0); - - runtime->private_data = pcmp; - runtime->private_free = snd_gf1_pcm_playback_free; - -#if 0 - printk(KERN_DEBUG "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", - (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); -#endif - if ((err = snd_gf1_dma_init(gus)) < 0) - return err; - pcmp->flags = SNDRV_GF1_PCM_PFLG_NONE; - pcmp->substream = substream; - runtime->hw = snd_gf1_pcm_playback; - snd_pcm_limit_isa_dma_size(gus->gf1.dma1, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(gus->gf1.dma1, &runtime->hw.period_bytes_max); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); - return 0; -} - -static int snd_gf1_pcm_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - - if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ)) - snd_printk(KERN_ERR "gf1 pcm - serious DMA problem\n"); - - snd_gf1_dma_done(gus); - return 0; -} - -static int snd_gf1_pcm_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - - gus->gf1.interrupt_handler_dma_read = snd_gf1_pcm_interrupt_dma_read; - gus->pcm_cap_substream = substream; - substream->runtime->hw = snd_gf1_pcm_capture; - snd_pcm_limit_isa_dma_size(gus->gf1.dma2, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(gus->gf1.dma2, &runtime->hw.period_bytes_max); - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); - return 0; -} - -static int snd_gf1_pcm_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - - gus->pcm_cap_substream = NULL; - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_READ); - return 0; -} - -static int snd_gf1_pcm_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 127; - return 0; -} - -static int snd_gf1_pcm_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&gus->pcm_volume_level_lock, flags); - ucontrol->value.integer.value[0] = gus->gf1.pcm_volume_level_left1; - ucontrol->value.integer.value[1] = gus->gf1.pcm_volume_level_right1; - spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags); - return 0; -} - -static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned int idx; - unsigned short val1, val2, vol; - struct gus_pcm_private *pcmp; - struct snd_gus_voice *pvoice; - - val1 = ucontrol->value.integer.value[0] & 127; - val2 = ucontrol->value.integer.value[1] & 127; - spin_lock_irqsave(&gus->pcm_volume_level_lock, flags); - change = val1 != gus->gf1.pcm_volume_level_left1 || - val2 != gus->gf1.pcm_volume_level_right1; - gus->gf1.pcm_volume_level_left1 = val1; - gus->gf1.pcm_volume_level_right1 = val2; - gus->gf1.pcm_volume_level_left = snd_gf1_lvol_to_gvol_raw(val1 << 9) << 4; - gus->gf1.pcm_volume_level_right = snd_gf1_lvol_to_gvol_raw(val2 << 9) << 4; - spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags); - /* are we active? */ - spin_lock_irqsave(&gus->voice_alloc, flags); - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - if (!pvoice->pcm) - continue; - pcmp = pvoice->private_data; - if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE)) - continue; - /* load real volume - better precision */ - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); - pcmp->final_volume = 1; - spin_unlock(&gus->reg_lock); - } - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return change; -} - -static struct snd_kcontrol_new snd_gf1_pcm_volume_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .info = snd_gf1_pcm_volume_info, - .get = snd_gf1_pcm_volume_get, - .put = snd_gf1_pcm_volume_put -}; - -static struct snd_kcontrol_new snd_gf1_pcm_volume_control1 = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "GPCM Playback Volume", - .info = snd_gf1_pcm_volume_info, - .get = snd_gf1_pcm_volume_get, - .put = snd_gf1_pcm_volume_put -}; - -static struct snd_pcm_ops snd_gf1_pcm_playback_ops = { - .open = snd_gf1_pcm_playback_open, - .close = snd_gf1_pcm_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_gf1_pcm_playback_hw_params, - .hw_free = snd_gf1_pcm_playback_hw_free, - .prepare = snd_gf1_pcm_playback_prepare, - .trigger = snd_gf1_pcm_playback_trigger, - .pointer = snd_gf1_pcm_playback_pointer, - .copy = snd_gf1_pcm_playback_copy, - .silence = snd_gf1_pcm_playback_silence, -}; - -static struct snd_pcm_ops snd_gf1_pcm_capture_ops = { - .open = snd_gf1_pcm_capture_open, - .close = snd_gf1_pcm_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_gf1_pcm_capture_hw_params, - .hw_free = snd_gf1_pcm_capture_hw_free, - .prepare = snd_gf1_pcm_capture_prepare, - .trigger = snd_gf1_pcm_capture_trigger, - .pointer = snd_gf1_pcm_capture_pointer, -}; - -int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, struct snd_pcm ** rpcm) -{ - struct snd_card *card; - struct snd_kcontrol *kctl; - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int capture, err; - - if (rpcm) - *rpcm = NULL; - card = gus->card; - capture = !gus->interwave && !gus->ess_flag && !gus->ace_flag ? 1 : 0; - err = snd_pcm_new(card, - gus->interwave ? "AMD InterWave" : "GF1", - pcm_dev, - gus->gf1.pcm_channels / 2, - capture, - &pcm); - if (err < 0) - return err; - pcm->private_data = gus; - /* playback setup */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_gf1_pcm_playback_ops); - - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) - snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, gus->gf1.dma1 > 3 ? 128*1024 : 64*1024); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - if (capture) { - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_gf1_pcm_capture_ops); - if (gus->gf1.dma2 == gus->gf1.dma1) - pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX; - snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, - SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(), - 64*1024, gus->gf1.dma2 > 3 ? 128*1024 : 64*1024); - } - strcpy(pcm->name, pcm->id); - if (gus->interwave) { - sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); - } - strcat(pcm->name, " (synth)"); - gus->pcm = pcm; - - if (gus->codec_flag) - kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control1, gus); - else - kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control, gus); - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - kctl->id.index = control_index; - - if (rpcm) - *rpcm = pcm; - return 0; -} - diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_reset.c b/ANDROID_3.4.5/sound/isa/gus/gus_reset.c deleted file mode 100644 index 3d1fed0c..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_reset.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -extern void snd_gf1_timers_init(struct snd_gus_card * gus); -extern void snd_gf1_timers_done(struct snd_gus_card * gus); -extern int snd_gf1_synth_init(struct snd_gus_card * gus); -extern void snd_gf1_synth_done(struct snd_gus_card * gus); - -/* - * ok.. default interrupt handlers... - */ - -static void snd_gf1_default_interrupt_handler_midi_out(struct snd_gus_card * gus) -{ - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x20); -} - -static void snd_gf1_default_interrupt_handler_midi_in(struct snd_gus_card * gus) -{ - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x80); -} - -static void snd_gf1_default_interrupt_handler_timer1(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~4); -} - -static void snd_gf1_default_interrupt_handler_timer2(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~8); -} - -static void snd_gf1_default_interrupt_handler_wave_and_volume(struct snd_gus_card * gus, struct snd_gus_voice * voice) -{ - snd_gf1_i_ctrl_stop(gus, 0x00); - snd_gf1_i_ctrl_stop(gus, 0x0d); -} - -static void snd_gf1_default_interrupt_handler_dma_write(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, 0x41, 0x00); -} - -static void snd_gf1_default_interrupt_handler_dma_read(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, 0x49, 0x00); -} - -void snd_gf1_set_default_handlers(struct snd_gus_card * gus, unsigned int what) -{ - if (what & SNDRV_GF1_HANDLER_MIDI_OUT) - gus->gf1.interrupt_handler_midi_out = snd_gf1_default_interrupt_handler_midi_out; - if (what & SNDRV_GF1_HANDLER_MIDI_IN) - gus->gf1.interrupt_handler_midi_in = snd_gf1_default_interrupt_handler_midi_in; - if (what & SNDRV_GF1_HANDLER_TIMER1) - gus->gf1.interrupt_handler_timer1 = snd_gf1_default_interrupt_handler_timer1; - if (what & SNDRV_GF1_HANDLER_TIMER2) - gus->gf1.interrupt_handler_timer2 = snd_gf1_default_interrupt_handler_timer2; - if (what & SNDRV_GF1_HANDLER_VOICE) { - struct snd_gus_voice *voice; - - voice = &gus->gf1.voices[what & 0xffff]; - voice->handler_wave = - voice->handler_volume = snd_gf1_default_interrupt_handler_wave_and_volume; - voice->handler_effect = NULL; - voice->volume_change = NULL; - } - if (what & SNDRV_GF1_HANDLER_DMA_WRITE) - gus->gf1.interrupt_handler_dma_write = snd_gf1_default_interrupt_handler_dma_write; - if (what & SNDRV_GF1_HANDLER_DMA_READ) - gus->gf1.interrupt_handler_dma_read = snd_gf1_default_interrupt_handler_dma_read; -} - -/* - - */ - -static void snd_gf1_clear_regs(struct snd_gus_card * gus) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - inb(GUSP(gus, IRQSTAT)); - snd_gf1_write8(gus, 0x41, 0); /* DRAM DMA Control Register */ - snd_gf1_write8(gus, 0x45, 0); /* Timer Control */ - snd_gf1_write8(gus, 0x49, 0); /* Sampling Control Register */ - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -static void snd_gf1_look_regs(struct snd_gus_card * gus) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_look8(gus, 0x41); /* DRAM DMA Control Register */ - snd_gf1_look8(gus, 0x49); /* Sampling Control Register */ - inb(GUSP(gus, IRQSTAT)); - snd_gf1_read8(gus, 0x0f); /* IRQ Source Register */ - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -/* - * put selected GF1 voices to initial stage... - */ - -void snd_gf1_smart_stop_voice(struct snd_gus_card * gus, unsigned short voice) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, voice); -#if 0 - printk(KERN_DEBUG " -%i- smart stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); -#endif - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, voice); -#if 0 - printk(KERN_DEBUG " -%i- stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); -#endif - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - if (gus->gf1.enh_mode) - snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0); - spin_unlock_irqrestore(&gus->reg_lock, flags); -#if 0 - snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_VIBRATO); - snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_TREMOLO); -#endif -} - -static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min, - unsigned short v_max) -{ - unsigned long flags; - unsigned int daddr; - unsigned short i, w_16; - - daddr = gus->gf1.default_voice_address << 4; - for (i = v_min; i <= v_max; i++) { -#if 0 - if (gus->gf1.syn_voices) - gus->gf1.syn_voices[i].flags = ~VFLG_DYNAMIC; -#endif - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, i); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); /* Voice Control Register = voice stop */ - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); /* Volume Ramp Control Register = ramp off */ - if (gus->gf1.enh_mode) - snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, gus->gf1.memory ? 0x02 : 0x82); /* Deactivate voice */ - w_16 = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & 0x04; - snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, 0x400); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, daddr, w_16); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, daddr, w_16); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, 0); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, 0); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0); - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, daddr, w_16); - snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, 7); - if (gus->gf1.enh_mode) { - snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0); - snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, 0); - snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, 0); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); -#if 0 - snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_VIBRATO); - snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_TREMOLO); -#endif - } -} - -void snd_gf1_stop_voices(struct snd_gus_card * gus, unsigned short v_min, unsigned short v_max) -{ - unsigned long flags; - short i, ramp_ok; - unsigned short ramp_end; - - if (!in_interrupt()) { /* this can't be done in interrupt */ - for (i = v_min, ramp_ok = 0; i <= v_max; i++) { - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, i); - ramp_end = snd_gf1_read16(gus, 9) >> 8; - if (ramp_end > SNDRV_GF1_MIN_OFFSET) { - ramp_ok++; - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 20); /* ramp rate */ - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET); /* ramp start */ - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, ramp_end); /* ramp end */ - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40); /* ramp down */ - if (gus->gf1.enh_mode) { - snd_gf1_delay(gus); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40); - } - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - } - msleep_interruptible(50); - } - snd_gf1_clear_voices(gus, v_min, v_max); -} - -static void snd_gf1_alloc_voice_use(struct snd_gus_card * gus, - struct snd_gus_voice * pvoice, - int type, int client, int port) -{ - pvoice->use = 1; - switch (type) { - case SNDRV_GF1_VOICE_TYPE_PCM: - gus->gf1.pcm_alloc_voices++; - pvoice->pcm = 1; - break; - case SNDRV_GF1_VOICE_TYPE_SYNTH: - pvoice->synth = 1; - pvoice->client = client; - pvoice->port = port; - break; - case SNDRV_GF1_VOICE_TYPE_MIDI: - pvoice->midi = 1; - pvoice->client = client; - pvoice->port = port; - break; - } -} - -struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, int client, int port) -{ - struct snd_gus_voice *pvoice; - unsigned long flags; - int idx; - - spin_lock_irqsave(&gus->voice_alloc, flags); - if (type == SNDRV_GF1_VOICE_TYPE_PCM) { - if (gus->gf1.pcm_alloc_voices >= gus->gf1.pcm_channels) { - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return NULL; - } - } - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - if (!pvoice->use) { - snd_gf1_alloc_voice_use(gus, pvoice, type, client, port); - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return pvoice; - } - } - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - if (pvoice->midi && !pvoice->client) { - snd_gf1_clear_voices(gus, pvoice->number, pvoice->number); - snd_gf1_alloc_voice_use(gus, pvoice, type, client, port); - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return pvoice; - } - } - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return NULL; -} - -void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice) -{ - unsigned long flags; - void (*private_free)(struct snd_gus_voice *voice); - void *private_data; - - if (voice == NULL || !voice->use) - return; - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | voice->number); - snd_gf1_clear_voices(gus, voice->number, voice->number); - spin_lock_irqsave(&gus->voice_alloc, flags); - private_free = voice->private_free; - private_data = voice->private_data; - voice->private_free = NULL; - voice->private_data = NULL; - if (voice->pcm) - gus->gf1.pcm_alloc_voices--; - voice->use = voice->pcm = 0; - voice->sample_ops = NULL; - spin_unlock_irqrestore(&gus->voice_alloc, flags); - if (private_free) - private_free(voice); -} - -/* - * call this function only by start of driver - */ - -int snd_gf1_start(struct snd_gus_card * gus) -{ - unsigned long flags; - unsigned int i; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */ - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac); - - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_ALL); - for (i = 0; i < 32; i++) { - gus->gf1.voices[i].number = i; - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | i); - } - - snd_gf1_uart_cmd(gus, 0x03); /* huh.. this cleanup took me some time... */ - - if (gus->gf1.enh_mode) { /* enhanced mode !!!! */ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - } - snd_gf1_clear_regs(gus); - snd_gf1_select_active_voices(gus); - snd_gf1_delay(gus); - gus->gf1.default_voice_address = gus->gf1.memory > 0 ? 0 : 512 - 8; - /* initialize LFOs & clear LFOs memory */ - if (gus->gf1.enh_mode && gus->gf1.memory) { - gus->gf1.hw_lfo = 1; - gus->gf1.default_voice_address += 1024; - } else { - gus->gf1.sw_lfo = 1; - } -#if 0 - snd_gf1_lfo_init(gus); -#endif - if (gus->gf1.memory > 0) - for (i = 0; i < 4; i++) - snd_gf1_poke(gus, gus->gf1.default_voice_address + i, 0); - snd_gf1_clear_regs(gus); - snd_gf1_clear_voices(gus, 0, 31); - snd_gf1_look_regs(gus); - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 7); /* Reset Register = IRQ enable, DAC enable */ - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 7); /* Reset Register = IRQ enable, DAC enable */ - if (gus->gf1.enh_mode) { /* enhanced mode !!!! */ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - } - while ((snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ) & 0xc0) != 0xc0); - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE)); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - - snd_gf1_timers_init(gus); - snd_gf1_look_regs(gus); - snd_gf1_mem_init(gus); - snd_gf1_mem_proc_init(gus); -#ifdef CONFIG_SND_DEBUG - snd_gus_irq_profile_init(gus); -#endif - -#if 0 - if (gus->pnp_flag) { - if (gus->chip.playback_fifo_size > 0) - snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR, gus->chip.playback_fifo_block->ptr >> 8); - if (gus->chip.record_fifo_size > 0) - snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR, gus->chip.record_fifo_block->ptr >> 8); - snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_SIZE, gus->chip.interwave_fifo_reg); - } -#endif - - return 0; -} - -/* - * call this function only by shutdown of driver - */ - -int snd_gf1_stop(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0); /* stop all timers */ - snd_gf1_stop_voices(gus, 0, 31); /* stop all voices */ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */ - snd_gf1_timers_done(gus); - snd_gf1_mem_done(gus); -#if 0 - snd_gf1_lfo_done(gus); -#endif - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_tables.h b/ANDROID_3.4.5/sound/isa/gus/gus_tables.h deleted file mode 100644 index 42a4ca0d..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_tables.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -#define SNDRV_GF1_SCALE_TABLE_SIZE 128 -#define SNDRV_GF1_ATTEN_TABLE_SIZE 128 - -#ifdef __GUS_TABLES_ALLOC__ - -#if 0 - -unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] = -{ - 8372, 8870, 9397, 9956, 10548, 11175, - 11840, 12544, 13290, 14080, 14917, 15804, - 16744, 17740, 18795, 19912, 21096, 22351, - 23680, 25088, 26580, 28160, 29834, 31609, - 33488, 35479, 37589, 39824, 42192, 44701, - 47359, 50175, 53159, 56320, 59669, 63217, - 66976, 70959, 75178, 79649, 84385, 89402, - 94719, 100351, 106318, 112640, 119338, 126434, - 133952, 141918, 150356, 159297, 168769, 178805, - 189437, 200702, 212636, 225280, 238676, 252868, - 267905, 283835, 300713, 318594, 337539, 357610, - 378874, 401403, 425272, 450560, 477352, 505737, - 535809, 567670, 601425, 637188, 675077, 715219, - 757749, 802807, 850544, 901120, 954703, 1011473, - 1071618, 1135340, 1202851, 1274376, 1350154, 1430439, - 1515497, 1605613, 1701088, 1802240, 1909407, 2022946, - 2143237, 2270680, 2405702, 2548752, 2700309, 2860878, - 3030994, 3211227, 3402176, 3604480, 3818814, 4045892, - 4286473, 4541360, 4811404, 5097505, 5400618, 5721755, - 6061989, 6422453, 6804352, 7208960, 7637627, 8091784, - 8572947, 9082720, 9622807, 10195009, 10801236, 11443511, - 12123977, 12844906 -}; - -#endif /* 0 */ - -unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = { - 4095 /* 0 */,1789 /* 1 */,1533 /* 2 */,1383 /* 3 */,1277 /* 4 */, - 1195 /* 5 */,1127 /* 6 */,1070 /* 7 */,1021 /* 8 */,978 /* 9 */, - 939 /* 10 */,903 /* 11 */,871 /* 12 */,842 /* 13 */,814 /* 14 */, - 789 /* 15 */,765 /* 16 */,743 /* 17 */,722 /* 18 */,702 /* 19 */, - 683 /* 20 */,665 /* 21 */,647 /* 22 */,631 /* 23 */,615 /* 24 */, - 600 /* 25 */,586 /* 26 */,572 /* 27 */,558 /* 28 */,545 /* 29 */, - 533 /* 30 */,521 /* 31 */,509 /* 32 */,498 /* 33 */,487 /* 34 */, - 476 /* 35 */,466 /* 36 */,455 /* 37 */,446 /* 38 */,436 /* 39 */, - 427 /* 40 */,418 /* 41 */,409 /* 42 */,400 /* 43 */,391 /* 44 */, - 383 /* 45 */,375 /* 46 */,367 /* 47 */,359 /* 48 */,352 /* 49 */, - 344 /* 50 */,337 /* 51 */,330 /* 52 */,323 /* 53 */,316 /* 54 */, - 309 /* 55 */,302 /* 56 */,296 /* 57 */,289 /* 58 */,283 /* 59 */, - 277 /* 60 */,271 /* 61 */,265 /* 62 */,259 /* 63 */,253 /* 64 */, - 247 /* 65 */,242 /* 66 */,236 /* 67 */,231 /* 68 */,225 /* 69 */, - 220 /* 70 */,215 /* 71 */,210 /* 72 */,205 /* 73 */,199 /* 74 */, - 195 /* 75 */,190 /* 76 */,185 /* 77 */,180 /* 78 */,175 /* 79 */, - 171 /* 80 */,166 /* 81 */,162 /* 82 */,157 /* 83 */,153 /* 84 */, - 148 /* 85 */,144 /* 86 */,140 /* 87 */,135 /* 88 */,131 /* 89 */, - 127 /* 90 */,123 /* 91 */,119 /* 92 */,115 /* 93 */,111 /* 94 */, - 107 /* 95 */,103 /* 96 */,100 /* 97 */,96 /* 98 */,92 /* 99 */, - 88 /* 100 */,85 /* 101 */,81 /* 102 */,77 /* 103 */,74 /* 104 */, - 70 /* 105 */,67 /* 106 */,63 /* 107 */,60 /* 108 */,56 /* 109 */, - 53 /* 110 */,50 /* 111 */,46 /* 112 */,43 /* 113 */,40 /* 114 */, - 37 /* 115 */,33 /* 116 */,30 /* 117 */,27 /* 118 */,24 /* 119 */, - 21 /* 120 */,18 /* 121 */,15 /* 122 */,12 /* 123 */,9 /* 124 */, - 6 /* 125 */,3 /* 126 */,0 /* 127 */, -}; - -#else - -extern unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE]; -extern unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE]; - -#endif diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_timer.c b/ANDROID_3.4.5/sound/isa/gus/gus_timer.c deleted file mode 100644 index c5372714..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_timer.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Routines for Gravis UltraSound soundcards - Timers - * Copyright (c) by Jaroslav Kysela - * - * GUS have similar timers as AdLib (OPL2/OPL3 chips). - * - * - * 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 - -/* - * Timer 1 - 80us - */ - -static int snd_gf1_timer1_start(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - unsigned int ticks; - struct snd_gus_card *gus; - - gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); - ticks = timer->sticks; - tmp = (gus->gf1.timer_enabled |= 4); - snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1, 256 - ticks); /* timer 1 count */ - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* enable timer 1 IRQ */ - snd_gf1_adlib_write(gus, 0x04, tmp >> 2); /* timer 2 start */ - spin_unlock_irqrestore(&gus->reg_lock, flags); - return 0; -} - -static int snd_gf1_timer1_stop(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - struct snd_gus_card *gus; - - gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); - tmp = (gus->gf1.timer_enabled &= ~4); - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&gus->reg_lock, flags); - return 0; -} - -/* - * Timer 2 - 320us - */ - -static int snd_gf1_timer2_start(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - unsigned int ticks; - struct snd_gus_card *gus; - - gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); - ticks = timer->sticks; - tmp = (gus->gf1.timer_enabled |= 8); - snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2, 256 - ticks); /* timer 2 count */ - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* enable timer 2 IRQ */ - snd_gf1_adlib_write(gus, 0x04, tmp >> 2); /* timer 2 start */ - spin_unlock_irqrestore(&gus->reg_lock, flags); - return 0; -} - -static int snd_gf1_timer2_stop(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - struct snd_gus_card *gus; - - gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); - tmp = (gus->gf1.timer_enabled &= ~8); - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&gus->reg_lock, flags); - return 0; -} - -/* - - */ - -static void snd_gf1_interrupt_timer1(struct snd_gus_card * gus) -{ - struct snd_timer *timer = gus->gf1.timer1; - - if (timer == NULL) - return; - snd_timer_interrupt(timer, timer->sticks); -} - -static void snd_gf1_interrupt_timer2(struct snd_gus_card * gus) -{ - struct snd_timer *timer = gus->gf1.timer2; - - if (timer == NULL) - return; - snd_timer_interrupt(timer, timer->sticks); -} - -/* - - */ - -static struct snd_timer_hardware snd_gf1_timer1 = -{ - .flags = SNDRV_TIMER_HW_STOP, - .resolution = 80000, - .ticks = 256, - .start = snd_gf1_timer1_start, - .stop = snd_gf1_timer1_stop, -}; - -static struct snd_timer_hardware snd_gf1_timer2 = -{ - .flags = SNDRV_TIMER_HW_STOP, - .resolution = 320000, - .ticks = 256, - .start = snd_gf1_timer2_start, - .stop = snd_gf1_timer2_stop, -}; - -static void snd_gf1_timer1_free(struct snd_timer *timer) -{ - struct snd_gus_card *gus = timer->private_data; - gus->gf1.timer1 = NULL; -} - -static void snd_gf1_timer2_free(struct snd_timer *timer) -{ - struct snd_gus_card *gus = timer->private_data; - gus->gf1.timer2 = NULL; -} - -void snd_gf1_timers_init(struct snd_gus_card * gus) -{ - struct snd_timer *timer; - struct snd_timer_id tid; - - if (gus->gf1.timer1 != NULL || gus->gf1.timer2 != NULL) - return; - - gus->gf1.interrupt_handler_timer1 = snd_gf1_interrupt_timer1; - gus->gf1.interrupt_handler_timer2 = snd_gf1_interrupt_timer2; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = gus->card->number; - tid.device = gus->timer_dev; - tid.subdevice = 0; - - if (snd_timer_new(gus->card, "GF1 timer", &tid, &timer) >= 0) { - strcpy(timer->name, "GF1 timer #1"); - timer->private_data = gus; - timer->private_free = snd_gf1_timer1_free; - timer->hw = snd_gf1_timer1; - } - gus->gf1.timer1 = timer; - - tid.device++; - - if (snd_timer_new(gus->card, "GF1 timer", &tid, &timer) >= 0) { - strcpy(timer->name, "GF1 timer #2"); - timer->private_data = gus; - timer->private_free = snd_gf1_timer2_free; - timer->hw = snd_gf1_timer2; - } - gus->gf1.timer2 = timer; -} - -void snd_gf1_timers_done(struct snd_gus_card * gus) -{ - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_TIMER1 | SNDRV_GF1_HANDLER_TIMER2); - if (gus->gf1.timer1) { - snd_device_free(gus->card, gus->gf1.timer1); - gus->gf1.timer1 = NULL; - } - if (gus->gf1.timer2) { - snd_device_free(gus->card, gus->gf1.timer2); - gus->gf1.timer2 = NULL; - } -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_uart.c b/ANDROID_3.4.5/sound/isa/gus/gus_uart.c deleted file mode 100644 index 21cc42e4..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_uart.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for the GF1 MIDI interface - like UART 6850 - * - * - * 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 - -static void snd_gf1_interrupt_midi_in(struct snd_gus_card * gus) -{ - int count; - unsigned char stat, data, byte; - unsigned long flags; - - count = 10; - while (count) { - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - stat = snd_gf1_uart_stat(gus); - if (!(stat & 0x01)) { /* data in Rx FIFO? */ - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - count--; - continue; - } - count = 100; /* arm counter to new value */ - data = snd_gf1_uart_get(gus); - if (!(gus->gf1.uart_cmd & 0x80)) { - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - continue; - } - if (stat & 0x10) { /* framing error */ - gus->gf1.uart_framing++; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - continue; - } - byte = snd_gf1_uart_get(gus); - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - snd_rawmidi_receive(gus->midi_substream_input, &byte, 1); - if (stat & 0x20) { - gus->gf1.uart_overrun++; - } - } -} - -static void snd_gf1_interrupt_midi_out(struct snd_gus_card * gus) -{ - char byte; - unsigned long flags; - - /* try unlock output */ - if (snd_gf1_uart_stat(gus) & 0x01) - snd_gf1_interrupt_midi_in(gus); - - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (snd_gf1_uart_stat(gus) & 0x02) { /* Tx FIFO free? */ - if (snd_rawmidi_transmit(gus->midi_substream_output, &byte, 1) != 1) { /* no other bytes or error */ - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20); /* disable Tx interrupt */ - } else { - snd_gf1_uart_put(gus, byte); - } - } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -} - -static void snd_gf1_uart_reset(struct snd_gus_card * gus, int close) -{ - snd_gf1_uart_cmd(gus, 0x03); /* reset */ - if (!close && gus->uart_enable) { - udelay(160); - snd_gf1_uart_cmd(gus, 0x00); /* normal operations */ - } -} - -static int snd_gf1_uart_output_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_gus_card *gus; - - gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (!(gus->gf1.uart_cmd & 0x80)) { /* input active? */ - snd_gf1_uart_reset(gus, 0); - } - gus->gf1.interrupt_handler_midi_out = snd_gf1_interrupt_midi_out; - gus->midi_substream_output = substream; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -#if 0 - snd_printk(KERN_DEBUG "write init - cmd = 0x%x, stat = 0x%x\n", gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); -#endif - return 0; -} - -static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_gus_card *gus; - int i; - - gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) { - snd_gf1_uart_reset(gus, 0); - } - gus->gf1.interrupt_handler_midi_in = snd_gf1_interrupt_midi_in; - gus->midi_substream_input = substream; - if (gus->uart_enable) { - for (i = 0; i < 1000 && (snd_gf1_uart_stat(gus) & 0x01); i++) - snd_gf1_uart_get(gus); /* clean Rx */ - if (i >= 1000) - snd_printk(KERN_ERR "gus midi uart init read - cleanup error\n"); - } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -#if 0 - snd_printk(KERN_DEBUG - "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", - gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); - snd_printk(KERN_DEBUG - "[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x " - "(page = 0x%x)\n", - gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), - inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102)); -#endif - return 0; -} - -static int snd_gf1_uart_output_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_gus_card *gus; - - gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (gus->gf1.interrupt_handler_midi_in != snd_gf1_interrupt_midi_in) - snd_gf1_uart_reset(gus, 1); - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_OUT); - gus->midi_substream_output = NULL; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - return 0; -} - -static int snd_gf1_uart_input_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_gus_card *gus; - - gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) - snd_gf1_uart_reset(gus, 1); - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_IN); - gus->midi_substream_input = NULL; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - return 0; -} - -static void snd_gf1_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_gus_card *gus; - unsigned long flags; - - gus = substream->rmidi->private_data; - - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (up) { - if ((gus->gf1.uart_cmd & 0x80) == 0) - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x80); /* enable Rx interrupts */ - } else { - if (gus->gf1.uart_cmd & 0x80) - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x80); /* disable Rx interrupts */ - } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -} - -static void snd_gf1_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_gus_card *gus; - char byte; - int timeout; - - gus = substream->rmidi->private_data; - - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (up) { - if ((gus->gf1.uart_cmd & 0x20) == 0) { - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - /* wait for empty Rx - Tx is probably unlocked */ - timeout = 10000; - while (timeout-- > 0 && snd_gf1_uart_stat(gus) & 0x01); - /* Tx FIFO free? */ - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (gus->gf1.uart_cmd & 0x20) { - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - return; - } - if (snd_gf1_uart_stat(gus) & 0x02) { - if (snd_rawmidi_transmit(substream, &byte, 1) != 1) { - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - return; - } - snd_gf1_uart_put(gus, byte); - } - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x20); /* enable Tx interrupt */ - } - } else { - if (gus->gf1.uart_cmd & 0x20) - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20); - } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -} - -static struct snd_rawmidi_ops snd_gf1_uart_output = -{ - .open = snd_gf1_uart_output_open, - .close = snd_gf1_uart_output_close, - .trigger = snd_gf1_uart_output_trigger, -}; - -static struct snd_rawmidi_ops snd_gf1_uart_input = -{ - .open = snd_gf1_uart_input_open, - .close = snd_gf1_uart_input_close, - .trigger = snd_gf1_uart_input_trigger, -}; - -int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi ** rrawmidi) -{ - struct snd_rawmidi *rmidi; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if ((err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi)) < 0) - return err; - strcpy(rmidi->name, gus->interwave ? "AMD InterWave" : "GF1"); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_gf1_uart_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_gf1_uart_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = gus; - gus->midi_uart = rmidi; - if (rrawmidi) - *rrawmidi = rmidi; - return err; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_volume.c b/ANDROID_3.4.5/sound/isa/gus/gus_volume.c deleted file mode 100644 index 3dd841ae..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_volume.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#define __GUS_TABLES_ALLOC__ -#include "gus_tables.h" - -EXPORT_SYMBOL(snd_gf1_atten_table); /* for snd-gus-synth module */ - -unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol) -{ - unsigned short e, m, tmp; - - if (vol > 65535) - vol = 65535; - tmp = vol; - e = 7; - if (tmp < 128) { - while (e > 0 && tmp < (1 << e)) - e--; - } else { - while (tmp > 255) { - tmp >>= 1; - e++; - } - } - m = vol - (1 << e); - if (m > 0) { - if (e > 8) - m >>= e - 8; - else if (e < 8) - m <<= 8 - e; - m &= 255; - } - return (e << 8) | m; -} - -#if 0 - -unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol) -{ - unsigned int rvol; - unsigned short e, m; - - if (!gf1_vol) - return 0; - e = gf1_vol >> 8; - m = (unsigned char) gf1_vol; - rvol = 1 << e; - if (e > 8) - return rvol | (m << (e - 8)); - return rvol | (m >> (8 - e)); -} - -unsigned int snd_gf1_calc_ramp_rate(struct snd_gus_card * gus, - unsigned short start, - unsigned short end, - unsigned int us) -{ - static unsigned char vol_rates[19] = - { - 23, 24, 26, 28, 29, 31, 32, 34, - 36, 37, 39, 40, 42, 44, 45, 47, - 49, 50, 52 - }; - unsigned short range, increment, value, i; - - start >>= 4; - end >>= 4; - if (start < end) - us /= end - start; - else - us /= start - end; - range = 4; - value = gus->gf1.enh_mode ? - vol_rates[0] : - vol_rates[gus->gf1.active_voices - 14]; - for (i = 0; i < 3; i++) { - if (us < value) { - range = i; - break; - } else - value <<= 3; - } - if (range == 4) { - range = 3; - increment = 1; - } else - increment = (value + (value >> 1)) / us; - return (range << 6) | (increment & 0x3f); -} - -#endif /* 0 */ - -unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int freq16) -{ - freq16 >>= 3; - if (freq16 < 50) - freq16 = 50; - if (freq16 & 0xf8000000) { - freq16 = ~0xf8000000; - snd_printk(KERN_ERR "snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16); - } - return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; -} - -#if 0 - -short snd_gf1_compute_vibrato(short cents, unsigned short fc_register) -{ - static short vibrato_table[] = - { - 0, 0, 32, 592, 61, 1175, 93, 1808, - 124, 2433, 152, 3007, 182, 3632, 213, 4290, - 241, 4834, 255, 5200 - }; - - long depth; - short *vi1, *vi2, pcents, v1; - - pcents = cents < 0 ? -cents : cents; - for (vi1 = vibrato_table, vi2 = vi1 + 2; pcents > *vi2; vi1 = vi2, vi2 += 2); - v1 = *(vi1 + 1); - /* The FC table above is a list of pairs. The first number in the pair */ - /* is the cents index from 0-255 cents, and the second number in the */ - /* pair is the FC adjustment needed to change the pitch by the indexed */ - /* number of cents. The table was created for an FC of 32768. */ - /* The following expression does a linear interpolation against the */ - /* approximated log curve in the table above, and then scales the number */ - /* by the FC before the LFO. This calculation also adjusts the output */ - /* value to produce the appropriate depth for the hardware. The depth */ - /* is 2 * desired FC + 1. */ - depth = (((int) (*(vi2 + 1) - *vi1) * (pcents - *vi1) / (*vi2 - *vi1)) + v1) * fc_register >> 14; - if (depth) - depth++; - if (depth > 255) - depth = 255; - return cents < 0 ? -(short) depth : (short) depth; -} - -unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens) -{ - static long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933}; - int wheel, sensitivity; - unsigned int mantissa, f1, f2; - unsigned short semitones, f1_index, f2_index, f1_power, f2_power; - char bend_down = 0; - int bend; - - if (!sens) - return 1024; - wheel = (int) pitchbend - 8192; - sensitivity = ((int) sens * wheel) / 128; - if (sensitivity < 0) { - bend_down = 1; - sensitivity = -sensitivity; - } - semitones = (unsigned int) (sensitivity >> 13); - mantissa = sensitivity % 8192; - f1_index = semitones % 12; - f2_index = (semitones + 1) % 12; - f1_power = semitones / 12; - f2_power = (semitones + 1) / 12; - f1 = log_table[f1_index] << f1_power; - f2 = log_table[f2_index] << f2_power; - bend = (int) ((((f2 - f1) * mantissa) >> 13) + f1); - if (bend_down) - bend = 1048576L / bend; - return bend; -} - -unsigned short snd_gf1_compute_freq(unsigned int freq, - unsigned int rate, - unsigned short mix_rate) -{ - unsigned int fc; - int scale = 0; - - while (freq >= 4194304L) { - scale++; - freq >>= 1; - } - fc = (freq << 10) / rate; - if (fc > 97391L) { - fc = 97391; - snd_printk(KERN_ERR "patch: (1) fc frequency overflow - %u\n", fc); - } - fc = (fc * 44100UL) / mix_rate; - while (scale--) - fc <<= 1; - if (fc > 65535L) { - fc = 65535; - snd_printk(KERN_ERR "patch: (2) fc frequency overflow - %u\n", fc); - } - return (unsigned short) fc; -} - -#endif /* 0 */ diff --git a/ANDROID_3.4.5/sound/isa/gus/gusclassic.c b/ANDROID_3.4.5/sound/isa/gus/gusclassic.c deleted file mode 100644 index bf633367..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gusclassic.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Driver for Gravis UltraSound Classic soundcard - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -#define CRD_NAME "Gravis UltraSound Classic" -#define DEV_NAME "gusclassic" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,5,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; - /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver."); -module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver."); -module_param_array(channels, int, NULL, 0444); -MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver."); - -static int __devinit snd_gusclassic_match(struct device *dev, unsigned int n) -{ - return enable[n]; -} - -static int __devinit snd_gusclassic_create(struct snd_card *card, - struct device *dev, unsigned int n, struct snd_gus_card **rgus) -{ - static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260}; - static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1}; - static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; - - int i, error; - - if (irq[n] == SNDRV_AUTO_IRQ) { - irq[n] = snd_legacy_find_free_irq(possible_irqs); - if (irq[n] < 0) { - dev_err(dev, "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma1[n] == SNDRV_AUTO_DMA) { - dma1[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma1[n] < 0) { - dev_err(dev, "unable to find a free DMA1\n"); - return -EBUSY; - } - } - if (dma2[n] == SNDRV_AUTO_DMA) { - dma2[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma2[n] < 0) { - dev_err(dev, "unable to find a free DMA2\n"); - return -EBUSY; - } - } - - if (port[n] != SNDRV_AUTO_PORT) - return snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n], - 0, channels[n], pcm_channels[n], 0, rgus); - - i = 0; - do { - port[n] = possible_ports[i]; - error = snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n], - 0, channels[n], pcm_channels[n], 0, rgus); - } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); - - return error; -} - -static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus) -{ - unsigned char d; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ - udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - return 0; -} - -static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_gus_card *gus; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); - if (error < 0) - return error; - - if (pcm_channels[n] < 2) - pcm_channels[n] = 2; - - error = snd_gusclassic_create(card, dev, n, &gus); - if (error < 0) - goto out; - - error = snd_gusclassic_detect(gus); - if (error < 0) - goto out; - - gus->joystick_dac = joystick_dac[n]; - - error = snd_gus_initialize(gus); - if (error < 0) - goto out; - - error = -ENODEV; - if (gus->max_flag || gus->ess_flag) { - dev_err(dev, "GUS Classic or ACE soundcard was " - "not detected at 0x%lx\n", gus->gf1.port); - goto out; - } - - error = snd_gf1_new_mixer(gus); - if (error < 0) - goto out; - - error = snd_gf1_pcm_new(gus, 0, 0, NULL); - if (error < 0) - goto out; - - if (!gus->ace_flag) { - error = snd_gf1_rawmidi_new(gus, 0, NULL); - if (error < 0) - goto out; - } - - sprintf(card->longname + strlen(card->longname), - " at 0x%lx, irq %d, dma %d", - gus->gf1.port, gus->gf1.irq, gus->gf1.dma1); - - if (gus->gf1.dma2 >= 0) - sprintf(card->longname + strlen(card->longname), - "&%d", gus->gf1.dma2); - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_gusclassic_driver = { - .match = snd_gusclassic_match, - .probe = snd_gusclassic_probe, - .remove = __devexit_p(snd_gusclassic_remove), -#if 0 /* FIXME */ - .suspend = snd_gusclassic_suspend, - .remove = snd_gusclassic_remove, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_gusclassic_init(void) -{ - return isa_register_driver(&snd_gusclassic_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_gusclassic_exit(void) -{ - isa_unregister_driver(&snd_gusclassic_driver); -} - -module_init(alsa_card_gusclassic_init); -module_exit(alsa_card_gusclassic_exit); diff --git a/ANDROID_3.4.5/sound/isa/gus/gusextreme.c b/ANDROID_3.4.5/sound/isa/gus/gusextreme.c deleted file mode 100644 index bc10cc26..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gusextreme.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Driver for Gravis UltraSound Extreme soundcards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#define SNDRV_LEGACY_AUTO_PROBE -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -#define CRD_NAME "Gravis UltraSound Extreme" -#define DEV_NAME "gusextreme" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ -static long gf1_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS) - 1] = -1}; /* 0x210,0x220,0x230,0x240,0x250,0x260,0x270 */ -static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS) - 1] = -1}; /* 0x300,0x310,0x320 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int gf1_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; - /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(gf1_port, long, NULL, 0444); -MODULE_PARM_DESC(gf1_port, "GF1 port # for " CRD_NAME " driver (optional)."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); -module_param_array(gf1_irq, int, NULL, 0444); -MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for " CRD_NAME " driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "GF1 DMA # for " CRD_NAME " driver."); -module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver."); -module_param_array(channels, int, NULL, 0444); -MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver."); - -static int __devinit snd_gusextreme_match(struct device *dev, unsigned int n) -{ - return enable[n]; -} - -static int __devinit snd_gusextreme_es1688_create(struct snd_card *card, - struct snd_es1688 *chip, struct device *dev, unsigned int n) -{ - static long possible_ports[] = {0x220, 0x240, 0x260}; - static int possible_irqs[] = {5, 9, 10, 7, -1}; - static int possible_dmas[] = {1, 3, 0, -1}; - - int i, error; - - if (irq[n] == SNDRV_AUTO_IRQ) { - irq[n] = snd_legacy_find_free_irq(possible_irqs); - if (irq[n] < 0) { - dev_err(dev, "unable to find a free IRQ for ES1688\n"); - return -EBUSY; - } - } - if (dma8[n] == SNDRV_AUTO_DMA) { - dma8[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma8[n] < 0) { - dev_err(dev, "unable to find a free DMA for ES1688\n"); - return -EBUSY; - } - } - - if (port[n] != SNDRV_AUTO_PORT) - return snd_es1688_create(card, chip, port[n], mpu_port[n], - irq[n], mpu_irq[n], dma8[n], ES1688_HW_1688); - - i = 0; - do { - port[n] = possible_ports[i]; - error = snd_es1688_create(card, chip, port[n], mpu_port[n], - irq[n], mpu_irq[n], dma8[n], ES1688_HW_1688); - } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); - - return error; -} - -static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card, - struct device *dev, unsigned int n, struct snd_gus_card **rgus) -{ - static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1}; - static int possible_dmas[] = {5, 6, 7, 3, 1, -1}; - - if (gf1_irq[n] == SNDRV_AUTO_IRQ) { - gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs); - if (gf1_irq[n] < 0) { - dev_err(dev, "unable to find a free IRQ for GF1\n"); - return -EBUSY; - } - } - if (dma1[n] == SNDRV_AUTO_DMA) { - dma1[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma1[n] < 0) { - dev_err(dev, "unable to find a free DMA for GF1\n"); - return -EBUSY; - } - } - return snd_gus_create(card, gf1_port[n], gf1_irq[n], dma1[n], -1, - 0, channels[n], pcm_channels[n], 0, rgus); -} - -static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus, - struct snd_es1688 *es1688) -{ - unsigned long flags; - unsigned char d; - - /* - * This is main stuff - enable access to GF1 chip... - * I'm not sure, if this will work for card which have - * ES1688 chip in another place than 0x220. - * - * I used reverse-engineering in DOSEMU. [--jk] - * - * ULTRINIT.EXE: - * 0x230 = 0,2,3 - * 0x240 = 2,0,1 - * 0x250 = 2,0,3 - * 0x260 = 2,2,1 - */ - - spin_lock_irqsave(&es1688->mixer_lock, flags); - snd_es1688_mixer_write(es1688, 0x40, 0x0b); /* don't change!!! */ - spin_unlock_irqrestore(&es1688->mixer_lock, flags); - - spin_lock_irqsave(&es1688->reg_lock, flags); - outb(gus->gf1.port & 0x040 ? 2 : 0, ES1688P(es1688, INIT1)); - outb(0, 0x201); - outb(gus->gf1.port & 0x020 ? 2 : 0, ES1688P(es1688, INIT1)); - outb(0, 0x201); - outb(gus->gf1.port & 0x010 ? 3 : 1, ES1688P(es1688, INIT1)); - spin_unlock_irqrestore(&es1688->reg_lock, flags); - - udelay(100); - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -EIO; - } - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ - udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -EIO; - } - - return 0; -} - -static int __devinit snd_gusextreme_mixer(struct snd_card *card) -{ - struct snd_ctl_elem_id id1, id2; - int error; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - - /* reassign AUX to SYNTHESIZER */ - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "Synth Playback Volume"); - error = snd_ctl_rename_id(card, &id1, &id2); - if (error < 0) - return error; - - /* reassign Master Playback Switch to Synth Playback Switch */ - strcpy(id1.name, "Master Playback Switch"); - strcpy(id2.name, "Synth Playback Switch"); - error = snd_ctl_rename_id(card, &id1, &id2); - if (error < 0) - return error; - - return 0; -} - -static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_gus_card *gus; - struct snd_es1688 *es1688; - struct snd_opl3 *opl3; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, - sizeof(struct snd_es1688), &card); - if (error < 0) - return error; - - es1688 = card->private_data; - - if (mpu_port[n] == SNDRV_AUTO_PORT) - mpu_port[n] = 0; - - if (mpu_irq[n] > 15) - mpu_irq[n] = -1; - - error = snd_gusextreme_es1688_create(card, es1688, dev, n); - if (error < 0) - goto out; - - if (gf1_port[n] < 0) - gf1_port[n] = es1688->port + 0x20; - - error = snd_gusextreme_gus_card_create(card, dev, n, &gus); - if (error < 0) - goto out; - - error = snd_gusextreme_detect(gus, es1688); - if (error < 0) - goto out; - - gus->joystick_dac = joystick_dac[n]; - - error = snd_gus_initialize(gus); - if (error < 0) - goto out; - - error = -ENODEV; - if (!gus->ess_flag) { - dev_err(dev, "GUS Extreme soundcard was not " - "detected at 0x%lx\n", gus->gf1.port); - goto out; - } - gus->codec_flag = 1; - - error = snd_es1688_pcm(card, es1688, 0, NULL); - if (error < 0) - goto out; - - error = snd_es1688_mixer(card, es1688); - if (error < 0) - goto out; - - snd_component_add(card, "ES1688"); - - if (pcm_channels[n] > 0) { - error = snd_gf1_pcm_new(gus, 1, 1, NULL); - if (error < 0) - goto out; - } - - error = snd_gf1_new_mixer(gus); - if (error < 0) - goto out; - - error = snd_gusextreme_mixer(card); - if (error < 0) - goto out; - - if (snd_opl3_create(card, es1688->port, es1688->port + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) - dev_warn(dev, "opl3 not detected at 0x%lx\n", es1688->port); - else { - error = snd_opl3_hwdep_new(opl3, 0, 2, NULL); - if (error < 0) - goto out; - } - - if (es1688->mpu_port >= 0x300) { - error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, - es1688->mpu_port, 0, mpu_irq[n], NULL); - if (error < 0) - goto out; - } - - sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, " - "irq %i&%i, dma %i&%i", es1688->port, - gus->gf1.irq, es1688->irq, gus->gf1.dma1, es1688->dma8); - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_gusextreme_driver = { - .match = snd_gusextreme_match, - .probe = snd_gusextreme_probe, - .remove = __devexit_p(snd_gusextreme_remove), -#if 0 /* FIXME */ - .suspend = snd_gusextreme_suspend, - .resume = snd_gusextreme_resume, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_gusextreme_init(void) -{ - return isa_register_driver(&snd_gusextreme_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_gusextreme_exit(void) -{ - isa_unregister_driver(&snd_gusextreme_driver); -} - -module_init(alsa_card_gusextreme_init); -module_exit(alsa_card_gusextreme_exit); diff --git a/ANDROID_3.4.5/sound/isa/gus/gusmax.c b/ANDROID_3.4.5/sound/isa/gus/gusmax.c deleted file mode 100644 index 41c3f448..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gusmax.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Driver for Gravis UltraSound MAX soundcard - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Gravis UltraSound MAX"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; - /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for GUS MAX soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for GUS MAX soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable GUS MAX soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for GUS MAX driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for GUS MAX driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for GUS MAX driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for GUS MAX driver."); -module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS MAX driver."); -module_param_array(channels, int, NULL, 0444); -MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver."); - -struct snd_gusmax { - int irq; - struct snd_card *card; - struct snd_gus_card *gus; - struct snd_wss *wss; - unsigned short gus_status_reg; - unsigned short pcm_status_reg; -}; - -#define PFX "gusmax: " - -static int __devinit snd_gusmax_detect(struct snd_gus_card * gus) -{ - unsigned char d; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ - udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - - return 0; -} - -static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id) -{ - struct snd_gusmax *maxcard = dev_id; - int loop, max = 5; - int handled = 0; - - do { - loop = 0; - if (inb(maxcard->gus_status_reg)) { - handled = 1; - snd_gus_interrupt(irq, maxcard->gus); - loop++; - } - if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */ - handled = 1; - snd_wss_interrupt(irq, maxcard->wss); - loop++; - } - } while (loop && --max > 0); - return IRQ_RETVAL(handled); -} - -static void __devinit snd_gusmax_init(int dev, struct snd_card *card, - struct snd_gus_card * gus) -{ - gus->equal_irq = 1; - gus->codec_flag = 1; - gus->joystick_dac = joystick_dac[dev]; - /* init control register */ - gus->max_cntrl_val = (gus->gf1.port >> 4) & 0x0f; - if (gus->gf1.dma1 > 3) - gus->max_cntrl_val |= 0x10; - if (gus->gf1.dma2 > 3) - gus->max_cntrl_val |= 0x20; - gus->max_cntrl_val |= 0x40; - outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT)); -} - -static int __devinit snd_gusmax_mixer(struct snd_wss *chip) -{ - struct snd_card *card = chip->card; - struct snd_ctl_elem_id id1, id2; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUXA to SYNTHESIZER */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "Synth Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "Synth Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - /* reassign AUXB to CD */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; -#if 0 - /* reassign Mono Input to MIC */ - if (snd_mixer_group_rename(mixer, - SNDRV_MIXER_IN_MONO, 0, - SNDRV_MIXER_IN_MIC, 0) < 0) - goto __error; - if (snd_mixer_elem_rename(mixer, - SNDRV_MIXER_IN_MONO, 0, SNDRV_MIXER_ETYPE_INPUT, - SNDRV_MIXER_IN_MIC, 0) < 0) - goto __error; - if (snd_mixer_elem_rename(mixer, - "Mono Capture Volume", 0, SNDRV_MIXER_ETYPE_VOLUME1, - "Mic Capture Volume", 0) < 0) - goto __error; - if (snd_mixer_elem_rename(mixer, - "Mono Capture Switch", 0, SNDRV_MIXER_ETYPE_SWITCH1, - "Mic Capture Switch", 0) < 0) - goto __error; -#endif - return 0; -} - -static void snd_gusmax_free(struct snd_card *card) -{ - struct snd_gusmax *maxcard = card->private_data; - - if (maxcard == NULL) - return; - if (maxcard->irq >= 0) - free_irq(maxcard->irq, (void *)maxcard); -} - -static int __devinit snd_gusmax_match(struct device *pdev, unsigned int dev) -{ - return enable[dev]; -} - -static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) -{ - static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; - static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; - int xirq, xdma1, xdma2, err; - struct snd_card *card; - struct snd_gus_card *gus = NULL; - struct snd_wss *wss; - struct snd_gusmax *maxcard; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_gusmax), &card); - if (err < 0) - return err; - card->private_free = snd_gusmax_free; - maxcard = card->private_data; - maxcard->card = card; - maxcard->irq = -1; - - xirq = irq[dev]; - if (xirq == SNDRV_AUTO_IRQ) { - if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - err = -EBUSY; - goto _err; - } - } - xdma1 = dma1[dev]; - if (xdma1 == SNDRV_AUTO_DMA) { - if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); - err = -EBUSY; - goto _err; - } - } - xdma2 = dma2[dev]; - if (xdma2 == SNDRV_AUTO_DMA) { - if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); - err = -EBUSY; - goto _err; - } - } - - if (port[dev] != SNDRV_AUTO_PORT) { - err = snd_gus_create(card, - port[dev], - -xirq, xdma1, xdma2, - 0, channels[dev], - pcm_channels[dev], - 0, &gus); - } else { - static unsigned long possible_ports[] = { - 0x220, 0x230, 0x240, 0x250, 0x260 - }; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - err = snd_gus_create(card, - possible_ports[i], - -xirq, xdma1, xdma2, - 0, channels[dev], - pcm_channels[dev], - 0, &gus); - if (err >= 0) { - port[dev] = possible_ports[i]; - break; - } - } - } - if (err < 0) - goto _err; - - if ((err = snd_gusmax_detect(gus)) < 0) - goto _err; - - maxcard->gus_status_reg = gus->gf1.reg_irqstat; - maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; - snd_gusmax_init(dev, card, gus); - if ((err = snd_gus_initialize(gus)) < 0) - goto _err; - - if (!gus->max_flag) { - snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port); - err = -ENODEV; - goto _err; - } - - if (request_irq(xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) { - snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); - err = -EBUSY; - goto _err; - } - maxcard->irq = xirq; - - err = snd_wss_create(card, - gus->gf1.port + 0x10c, -1, xirq, - xdma2 < 0 ? xdma1 : xdma2, xdma1, - WSS_HW_DETECT, - WSS_HWSHARE_IRQ | - WSS_HWSHARE_DMA1 | - WSS_HWSHARE_DMA2, - &wss); - if (err < 0) - goto _err; - - err = snd_wss_pcm(wss, 0, NULL); - if (err < 0) - goto _err; - - err = snd_wss_mixer(wss); - if (err < 0) - goto _err; - - err = snd_wss_timer(wss, 2, NULL); - if (err < 0) - goto _err; - - if (pcm_channels[dev] > 0) { - if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) - goto _err; - } - err = snd_gusmax_mixer(wss); - if (err < 0) - goto _err; - - err = snd_gf1_rawmidi_new(gus, 0, NULL); - if (err < 0) - goto _err; - - sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1); - if (xdma2 >= 0) - sprintf(card->longname + strlen(card->longname), "&%i", xdma2); - - snd_card_set_dev(card, pdev); - - err = snd_card_register(card); - if (err < 0) - goto _err; - - maxcard->gus = gus; - maxcard->wss = wss; - - dev_set_drvdata(pdev, card); - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#define DEV_NAME "gusmax" - -static struct isa_driver snd_gusmax_driver = { - .match = snd_gusmax_match, - .probe = snd_gusmax_probe, - .remove = __devexit_p(snd_gusmax_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DEV_NAME - }, -}; - -static int __init alsa_card_gusmax_init(void) -{ - return isa_register_driver(&snd_gusmax_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_gusmax_exit(void) -{ - isa_unregister_driver(&snd_gusmax_driver); -} - -module_init(alsa_card_gusmax_init) -module_exit(alsa_card_gusmax_exit) diff --git a/ANDROID_3.4.5/sound/isa/gus/interwave-stb.c b/ANDROID_3.4.5/sound/isa/gus/interwave-stb.c deleted file mode 100644 index dbe4f48a..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/interwave-stb.c +++ /dev/null @@ -1,2 +0,0 @@ -#define SNDRV_STB -#include "interwave.c" diff --git a/ANDROID_3.4.5/sound/isa/gus/interwave.c b/ANDROID_3.4.5/sound/isa/gus/interwave.c deleted file mode 100644 index a76bc8d2..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/interwave.c +++ /dev/null @@ -1,947 +0,0 @@ -/* - * Driver for AMD InterWave soundcard - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - * 1999/07/22 Erik Inge Bolso - * * mixer group handlers - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef SNDRV_STB -#include -#endif -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_LICENSE("GPL"); -#ifndef SNDRV_STB -MODULE_DESCRIPTION("AMD InterWave"); -MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Plug & Play}," - "{STB,SoundRage32}," - "{MED,MED3210}," - "{Dynasonix,Dynasonix Pro}," - "{Panasonic,PCA761AW}}"); -#else -MODULE_DESCRIPTION("AMD InterWave STB with TEA6330T"); -MODULE_SUPPORTED_DEVICE("{{AMD,InterWave STB with TEA6330T}}"); -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x210,0x220,0x230,0x240,0x250,0x260 */ -#ifdef SNDRV_STB -static long port_tc[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x350,0x360,0x370,0x380 */ -#endif -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; - /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int midi[SNDRV_CARDS]; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; -static int effect[SNDRV_CARDS]; - -#ifdef SNDRV_STB -#define PFX "interwave-stb: " -#define INTERWAVE_DRIVER "snd_interwave_stb" -#define INTERWAVE_PNP_DRIVER "interwave-stb" -#else -#define PFX "interwave: " -#define INTERWAVE_DRIVER "snd_interwave" -#define INTERWAVE_PNP_DRIVER "interwave" -#endif - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for InterWave soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for InterWave soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable InterWave soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for InterWave driver."); -#ifdef SNDRV_STB -module_param_array(port_tc, long, NULL, 0444); -MODULE_PARM_DESC(port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver."); -#endif -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for InterWave driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for InterWave driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for InterWave driver."); -module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver."); -module_param_array(midi, int, NULL, 0444); -MODULE_PARM_DESC(midi, "MIDI UART enable for InterWave driver."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver."); -module_param_array(effect, int, NULL, 0444); -MODULE_PARM_DESC(effect, "Effects enable for InterWave driver."); - -struct snd_interwave { - int irq; - struct snd_card *card; - struct snd_gus_card *gus; - struct snd_wss *wss; -#ifdef SNDRV_STB - struct resource *i2c_res; -#endif - unsigned short gus_status_reg; - unsigned short pcm_status_reg; -#ifdef CONFIG_PNP - struct pnp_dev *dev; -#ifdef SNDRV_STB - struct pnp_dev *devtc; -#endif -#endif -}; - - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; - -static struct pnp_card_device_id snd_interwave_pnpids[] = { -#ifndef SNDRV_STB - /* Gravis UltraSound Plug & Play */ - { .id = "GRV0001", .devs = { { .id = "GRV0000" } } }, - /* STB SoundRage32 */ - { .id = "STB011a", .devs = { { .id = "STB0010" } } }, - /* MED3210 */ - { .id = "DXP3201", .devs = { { .id = "DXP0010" } } }, - /* Dynasonic Pro */ - /* This device also have CDC1117:DynaSonix Pro Audio Effects Processor */ - { .id = "CDC1111", .devs = { { .id = "CDC1112" } } }, - /* Panasonic PCA761AW Audio Card */ - { .id = "ADV55ff", .devs = { { .id = "ADV0010" } } }, - /* InterWave STB without TEA6330T */ - { .id = "ADV550a", .devs = { { .id = "ADV0010" } } }, -#else - /* InterWave STB with TEA6330T */ - { .id = "ADV550a", .devs = { { .id = "ADV0010" }, { .id = "ADV0015" } } }, -#endif - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_interwave_pnpids); - -#endif /* CONFIG_PNP */ - - -#ifdef SNDRV_STB -static void snd_interwave_i2c_setlines(struct snd_i2c_bus *bus, int ctrl, int data) -{ - unsigned long port = bus->private_value; - -#if 0 - printk(KERN_DEBUG "i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data); -#endif - outb((data << 1) | ctrl, port); - udelay(10); -} - -static int snd_interwave_i2c_getclockline(struct snd_i2c_bus *bus) -{ - unsigned long port = bus->private_value; - unsigned char res; - - res = inb(port) & 1; -#if 0 - printk(KERN_DEBUG "i2c_getclockline - 0x%lx -> %i\n", port, res); -#endif - return res; -} - -static int snd_interwave_i2c_getdataline(struct snd_i2c_bus *bus, int ack) -{ - unsigned long port = bus->private_value; - unsigned char res; - - if (ack) - udelay(10); - res = (inb(port) & 2) >> 1; -#if 0 - printk(KERN_DEBUG "i2c_getdataline - 0x%lx -> %i\n", port, res); -#endif - return res; -} - -static struct snd_i2c_bit_ops snd_interwave_i2c_bit_ops = { - .setlines = snd_interwave_i2c_setlines, - .getclock = snd_interwave_i2c_getclockline, - .getdata = snd_interwave_i2c_getdataline, -}; - -static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard, - struct snd_gus_card * gus, int dev, - struct snd_i2c_bus **rbus) -{ - unsigned long port; - struct snd_i2c_bus *bus; - struct snd_card *card = iwcard->card; - char name[32]; - int err; - - *rbus = NULL; - port = port_tc[dev]; - if (port == SNDRV_AUTO_PORT) { - port = 0x350; - if (gus->gf1.port == 0x250) { - port = 0x360; - } - while (port <= 0x380) { - if ((iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)")) != NULL) - break; - port += 0x10; - } - } else { - iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)"); - } - if (iwcard->i2c_res == NULL) { - snd_printk(KERN_ERR "interwave: can't grab i2c bus port\n"); - return -ENODEV; - } - - sprintf(name, "InterWave-%i", card->number); - if ((err = snd_i2c_bus_create(card, name, NULL, &bus)) < 0) - return err; - bus->private_value = port; - bus->hw_ops.bit = &snd_interwave_i2c_bit_ops; - if ((err = snd_tea6330t_detect(bus, 0)) < 0) - return err; - *rbus = bus; - return 0; -} -#endif - -static int __devinit snd_interwave_detect(struct snd_interwave *iwcard, - struct snd_gus_card * gus, - int dev -#ifdef SNDRV_STB - , struct snd_i2c_bus **rbus -#endif - ) -{ - unsigned long flags; - unsigned char rev1, rev2; - int d; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ - udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - spin_lock_irqsave(&gus->reg_lock, flags); - rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1); - rev2 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, rev1); - spin_unlock_irqrestore(&gus->reg_lock, flags); - snd_printdd("[0x%lx] InterWave check - rev1=0x%x, rev2=0x%x\n", gus->gf1.port, rev1, rev2); - if ((rev1 & 0xf0) == (rev2 & 0xf0) && - (rev1 & 0x0f) != (rev2 & 0x0f)) { - snd_printdd("[0x%lx] InterWave check - passed\n", gus->gf1.port); - gus->interwave = 1; - strcpy(gus->card->shortname, "AMD InterWave"); - gus->revision = rev1 >> 4; -#ifndef SNDRV_STB - return 0; /* ok.. We have an InterWave board */ -#else - return snd_interwave_detect_stb(iwcard, gus, dev, rbus); -#endif - } - snd_printdd("[0x%lx] InterWave check - failed\n", gus->gf1.port); - return -ENODEV; -} - -static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id) -{ - struct snd_interwave *iwcard = dev_id; - int loop, max = 5; - int handled = 0; - - do { - loop = 0; - if (inb(iwcard->gus_status_reg)) { - handled = 1; - snd_gus_interrupt(irq, iwcard->gus); - loop++; - } - if (inb(iwcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */ - handled = 1; - snd_wss_interrupt(irq, iwcard->wss); - loop++; - } - } while (loop && --max > 0); - return IRQ_RETVAL(handled); -} - -static void __devinit snd_interwave_reset(struct snd_gus_card * gus) -{ - snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00); - udelay(160); - snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x01); - udelay(160); -} - -static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *sizes) -{ - unsigned int idx; - unsigned int local; - unsigned char d; - - for (idx = 0; idx < 4; idx++) { - sizes[idx] = 0; - d = 0x55; - for (local = idx << 22; - local < (idx << 22) + 0x400000; - local += 0x40000, d++) { - snd_gf1_poke(gus, local, d); - snd_gf1_poke(gus, local + 1, d + 1); -#if 0 - printk(KERN_DEBUG "d = 0x%x, local = 0x%x, " - "local + 1 = 0x%x, idx << 22 = 0x%x\n", - d, - snd_gf1_peek(gus, local), - snd_gf1_peek(gus, local + 1), - snd_gf1_peek(gus, idx << 22)); -#endif - if (snd_gf1_peek(gus, local) != d || - snd_gf1_peek(gus, local + 1) != d + 1 || - snd_gf1_peek(gus, idx << 22) != 0x55) - break; - sizes[idx]++; - } - } -#if 0 - printk(KERN_DEBUG "sizes: %i %i %i %i\n", - sizes[0], sizes[1], sizes[2], sizes[3]); -#endif -} - -struct rom_hdr { - /* 000 */ unsigned char iwave[8]; - /* 008 */ unsigned char rom_hdr_revision; - /* 009 */ unsigned char series_number; - /* 010 */ unsigned char series_name[16]; - /* 026 */ unsigned char date[10]; - /* 036 */ unsigned short vendor_revision_major; - /* 038 */ unsigned short vendor_revision_minor; - /* 040 */ unsigned int rom_size; - /* 044 */ unsigned char copyright[128]; - /* 172 */ unsigned char vendor_name[64]; - /* 236 */ unsigned char rom_description[128]; - /* 364 */ unsigned char pad[147]; - /* 511 */ unsigned char csum; -}; - -static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus) -{ - static unsigned int lmc[13] = - { - 0x00000001, 0x00000101, 0x01010101, 0x00000401, - 0x04040401, 0x00040101, 0x04040101, 0x00000004, - 0x00000404, 0x04040404, 0x00000010, 0x00001010, - 0x10101010 - }; - - int bank_pos, pages; - unsigned int i, lmct; - int psizes[4]; - unsigned char iwave[8]; - unsigned char csum; - - snd_interwave_reset(gus); - snd_gf1_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); /* enhanced mode */ - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); /* DRAM I/O cycles selected */ - snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xff10) | 0x004c); - /* ok.. simple test of memory size */ - pages = 0; - snd_gf1_poke(gus, 0, 0x55); - snd_gf1_poke(gus, 1, 0xaa); -#if 1 - if (snd_gf1_peek(gus, 0) == 0x55 && snd_gf1_peek(gus, 1) == 0xaa) -#else - if (0) /* ok.. for testing of 0k RAM */ -#endif - { - snd_interwave_bank_sizes(gus, psizes); - lmct = (psizes[3] << 24) | (psizes[2] << 16) | - (psizes[1] << 8) | psizes[0]; -#if 0 - printk(KERN_DEBUG "lmct = 0x%08x\n", lmct); -#endif - for (i = 0; i < ARRAY_SIZE(lmc); i++) - if (lmct == lmc[i]) { -#if 0 - printk(KERN_DEBUG "found !!! %i\n", i); -#endif - snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i); - snd_interwave_bank_sizes(gus, psizes); - break; - } - if (i >= ARRAY_SIZE(lmc) && !gus->gf1.enh_mode) - snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | 2); - for (i = 0; i < 4; i++) { - gus->gf1.mem_alloc.banks_8[i].address = - gus->gf1.mem_alloc.banks_16[i].address = i << 22; - gus->gf1.mem_alloc.banks_8[i].size = - gus->gf1.mem_alloc.banks_16[i].size = psizes[i] << 18; - pages += psizes[i]; - } - } - pages <<= 18; - gus->gf1.memory = pages; - - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x03); /* select ROM */ - snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xff1f) | (4 << 5)); - gus->gf1.rom_banks = 0; - gus->gf1.rom_memory = 0; - for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) { - for (i = 0; i < 8; ++i) - iwave[i] = snd_gf1_peek(gus, bank_pos + i); -#ifdef CONFIG_SND_DEBUG_ROM - printk(KERN_DEBUG "ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos, - iwave[0], iwave[1], iwave[2], iwave[3], - iwave[4], iwave[5], iwave[6], iwave[7]); -#endif - if (strncmp(iwave, "INTRWAVE", 8)) - continue; /* first check */ - csum = 0; - for (i = 0; i < sizeof(struct rom_hdr); i++) - csum += snd_gf1_peek(gus, bank_pos + i); -#ifdef CONFIG_SND_DEBUG_ROM - printk(KERN_DEBUG "ROM checksum = 0x%x (computed)\n", csum); -#endif - if (csum != 0) - continue; /* not valid rom */ - gus->gf1.rom_banks++; - gus->gf1.rom_present |= 1 << (bank_pos >> 22); - gus->gf1.rom_memory = snd_gf1_peek(gus, bank_pos + 40) | - (snd_gf1_peek(gus, bank_pos + 41) << 8) | - (snd_gf1_peek(gus, bank_pos + 42) << 16) | - (snd_gf1_peek(gus, bank_pos + 43) << 24); - } -#if 0 - if (gus->gf1.rom_memory > 0) { - if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8) - gus->card->type = SNDRV_CARD_TYPE_IW_DYNASONIC; - } -#endif - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x00); /* select RAM */ - - if (!gus->gf1.enh_mode) - snd_interwave_reset(gus); -} - -static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus) -{ - unsigned long flags; - - /* ok.. some InterWave specific initialization */ - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0x00); - snd_gf1_write8(gus, SNDRV_GF1_GB_COMPATIBILITY, 0x1f); - snd_gf1_write8(gus, SNDRV_GF1_GB_DECODE_CONTROL, 0x49); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, 0x11); - snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A, 0x00); - snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B, 0x30); - snd_gf1_write8(gus, SNDRV_GF1_GB_EMULATION_IRQ, 0x00); - spin_unlock_irqrestore(&gus->reg_lock, flags); - gus->equal_irq = 1; - gus->codec_flag = 1; - gus->interwave = 1; - gus->max_flag = 1; - gus->joystick_dac = joystick_dac[dev]; - -} - -static struct snd_kcontrol_new snd_interwave_controls[] = { -WSS_DOUBLE("Master Playback Switch", 0, - CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE("Master Playback Volume", 0, - CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1), -WSS_DOUBLE("Mic Playback Switch", 0, - CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1), -WSS_DOUBLE("Mic Playback Volume", 0, - CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1) -}; - -static int __devinit snd_interwave_mixer(struct snd_wss *chip) -{ - struct snd_card *card = chip->card; - struct snd_ctl_elem_id id1, id2; - unsigned int idx; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; -#if 0 - /* remove mono microphone controls */ - strcpy(id1.name, "Mic Playback Switch"); - if ((err = snd_ctl_remove_id(card, &id1)) < 0) - return err; - strcpy(id1.name, "Mic Playback Volume"); - if ((err = snd_ctl_remove_id(card, &id1)) < 0) - return err; -#endif - /* add new master and mic controls */ - for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0) - return err; - snd_wss_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f); - snd_wss_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f); - snd_wss_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f); - snd_wss_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f); - /* reassign AUXA to SYNTHESIZER */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "Synth Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "Synth Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - /* reassign AUXB to CD */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - return 0; -} - -#ifdef CONFIG_PNP - -static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - iwcard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (iwcard->dev == NULL) - return -EBUSY; - -#ifdef SNDRV_STB - iwcard->devtc = pnp_request_card_device(card, id->devs[1].id, NULL); - if (iwcard->devtc == NULL) - return -EBUSY; -#endif - /* Synth & Codec initialization */ - pdev = iwcard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "InterWave PnP configure failure (out of resources?)\n"); - return err; - } - if (pnp_port_start(pdev, 0) + 0x100 != pnp_port_start(pdev, 1) || - pnp_port_start(pdev, 0) + 0x10c != pnp_port_start(pdev, 2)) { - snd_printk(KERN_ERR "PnP configure failure (wrong ports)\n"); - return -ENOENT; - } - port[dev] = pnp_port_start(pdev, 0); - dma1[dev] = pnp_dma(pdev, 0); - if (dma2[dev] >= 0) - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("isapnp IW: sb port=0x%llx, gf1 port=0x%llx, codec port=0x%llx\n", - (unsigned long long)pnp_port_start(pdev, 0), - (unsigned long long)pnp_port_start(pdev, 1), - (unsigned long long)pnp_port_start(pdev, 2)); - snd_printdd("isapnp IW: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); -#ifdef SNDRV_STB - /* Tone Control initialization */ - pdev = iwcard->devtc; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "InterWave ToneControl PnP configure failure (out of resources?)\n"); - return err; - } - port_tc[dev] = pnp_port_start(pdev, 0); - snd_printdd("isapnp IW: tone control port=0x%lx\n", port_tc[dev]); -#endif - return 0; -} -#endif /* CONFIG_PNP */ - -static void snd_interwave_free(struct snd_card *card) -{ - struct snd_interwave *iwcard = card->private_data; - - if (iwcard == NULL) - return; -#ifdef SNDRV_STB - release_and_free_resource(iwcard->i2c_res); -#endif - if (iwcard->irq >= 0) - free_irq(iwcard->irq, (void *)iwcard); -} - -static int snd_interwave_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - struct snd_interwave *iwcard; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_interwave), &card); - if (err < 0) - return err; - iwcard = card->private_data; - iwcard->card = card; - iwcard->irq = -1; - card->private_free = snd_interwave_free; - *cardp = card; - return 0; -} - -static int __devinit snd_interwave_probe(struct snd_card *card, int dev) -{ - int xirq, xdma1, xdma2; - struct snd_interwave *iwcard = card->private_data; - struct snd_wss *wss; - struct snd_gus_card *gus; -#ifdef SNDRV_STB - struct snd_i2c_bus *i2c_bus; -#endif - struct snd_pcm *pcm; - char *str; - int err; - - xirq = irq[dev]; - xdma1 = dma1[dev]; - xdma2 = dma2[dev]; - - if ((err = snd_gus_create(card, - port[dev], - -xirq, xdma1, xdma2, - 0, 32, - pcm_channels[dev], effect[dev], &gus)) < 0) - return err; - - if ((err = snd_interwave_detect(iwcard, gus, dev -#ifdef SNDRV_STB - , &i2c_bus -#endif - )) < 0) - return err; - - iwcard->gus_status_reg = gus->gf1.reg_irqstat; - iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; - - snd_interwave_init(dev, gus); - snd_interwave_detect_memory(gus); - if ((err = snd_gus_initialize(gus)) < 0) - return err; - - if (request_irq(xirq, snd_interwave_interrupt, 0, - "InterWave", iwcard)) { - snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); - return -EBUSY; - } - iwcard->irq = xirq; - - err = snd_wss_create(card, - gus->gf1.port + 0x10c, -1, xirq, - xdma2 < 0 ? xdma1 : xdma2, xdma1, - WSS_HW_INTERWAVE, - WSS_HWSHARE_IRQ | - WSS_HWSHARE_DMA1 | - WSS_HWSHARE_DMA2, - &wss); - if (err < 0) - return err; - - err = snd_wss_pcm(wss, 0, &pcm); - if (err < 0) - return err; - - sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); - strcat(pcm->name, " (codec)"); - - err = snd_wss_timer(wss, 2, NULL); - if (err < 0) - return err; - - err = snd_wss_mixer(wss); - if (err < 0) - return err; - - if (pcm_channels[dev] > 0) { - err = snd_gf1_pcm_new(gus, 1, 1, NULL); - if (err < 0) - return err; - } - err = snd_interwave_mixer(wss); - if (err < 0) - return err; - -#ifdef SNDRV_STB - { - struct snd_ctl_elem_id id1, id2; - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id1.name, "Master Playback Switch"); - strcpy(id2.name, id1.name); - id2.index = 1; - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Master Playback Volume"); - strcpy(id2.name, id1.name); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) - return err; - } -#endif - - gus->uart_enable = midi[dev]; - if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) - return err; - -#ifndef SNDRV_STB - str = "AMD InterWave"; - if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8) - str = "Dynasonic 3-D"; -#else - str = "InterWave STB"; -#endif - strcpy(card->driver, str); - strcpy(card->shortname, str); - sprintf(card->longname, "%s at 0x%lx, irq %i, dma %d", - str, - gus->gf1.port, - xirq, - xdma1); - if (xdma2 >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", xdma2); - - err = snd_card_register(card); - if (err < 0) - return err; - - iwcard->wss = wss; - iwcard->gus = gus; - return 0; -} - -static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr) -{ - struct snd_card *card; - int err; - - err = snd_interwave_card_new(dev, &card); - if (err < 0) - return err; - - snd_card_set_dev(card, devptr); - if ((err = snd_interwave_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(devptr, card); - return 0; -} - -static int __devinit snd_interwave_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev]) - return 0; -#ifdef CONFIG_PNP - if (isapnp[dev]) - return 0; -#endif - return 1; -} - -static int __devinit snd_interwave_isa_probe(struct device *pdev, - unsigned int dev) -{ - int err; - static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; - static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; - - if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma1[dev] == SNDRV_AUTO_DMA) { - if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); - return -EBUSY; - } - } - if (dma2[dev] == SNDRV_AUTO_DMA) { - if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); - return -EBUSY; - } - } - - if (port[dev] != SNDRV_AUTO_PORT) - return snd_interwave_isa_probe1(dev, pdev); - else { - static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260}; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - port[dev] = possible_ports[i]; - err = snd_interwave_isa_probe1(dev, pdev); - if (! err) - return 0; - } - return err; - } -} - -static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -static struct isa_driver snd_interwave_driver = { - .match = snd_interwave_isa_match, - .probe = snd_interwave_isa_probe, - .remove = __devexit_p(snd_interwave_isa_remove), - /* FIXME: suspend,resume */ - .driver = { - .name = INTERWAVE_DRIVER - }, -}; - -#ifdef CONFIG_PNP -static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_interwave_card_new(dev, &card); - if (res < 0) - return res; - - if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { - snd_card_free(card); - return res; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_interwave_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static struct pnp_card_driver interwave_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = INTERWAVE_PNP_DRIVER, - .id_table = snd_interwave_pnpids, - .probe = snd_interwave_pnp_detect, - .remove = __devexit_p(snd_interwave_pnp_remove), - /* FIXME: suspend,resume */ -}; - -#endif /* CONFIG_PNP */ - -static int __init alsa_card_interwave_init(void) -{ - int err; - - err = isa_register_driver(&snd_interwave_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&interwave_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_interwave_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&interwave_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_interwave_driver); -} - -module_init(alsa_card_interwave_init) -module_exit(alsa_card_interwave_exit) diff --git a/ANDROID_3.4.5/sound/isa/msnd/Makefile b/ANDROID_3.4.5/sound/isa/msnd/Makefile deleted file mode 100644 index 2171c0aa..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/Makefile +++ /dev/null @@ -1,9 +0,0 @@ - -snd-msnd-lib-objs := msnd.o msnd_midi.o msnd_pinnacle_mixer.o -snd-msnd-pinnacle-objs := msnd_pinnacle.o -snd-msnd-classic-objs := msnd_classic.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_MSND_PINNACLE) += snd-msnd-pinnacle.o snd-msnd-lib.o -obj-$(CONFIG_SND_MSND_CLASSIC) += snd-msnd-classic.o snd-msnd-lib.o - diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd.c b/ANDROID_3.4.5/sound/isa/msnd/msnd.c deleted file mode 100644 index 1cee18fb..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd.c +++ /dev/null @@ -1,708 +0,0 @@ -/********************************************************************* - * - * 2002/06/30 Karsten Wiese: - * removed kernel-version dependencies. - * ripped from linux kernel 2.4.18 (OSS Implementation) by me. - * In the OSS Version, this file is compiled to a separate MODULE, - * that is used by the pinnacle and the classic driver. - * since there is no classic driver for alsa yet (i dont have a classic - * & writing one blindfold is difficult) this file's object is statically - * linked into the pinnacle-driver-module for now. look for the string - * "uncomment this to make this a module again" - * to do guess what. - * - * the following is a copy of the 2.4.18 OSS FREE file-heading comment: - * - * msnd.c - Driver Base - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Copyright (C) 1998 Andrew Veliath - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "msnd.h" - -#define LOGNAME "msnd" - - -void snd_msnd_init_queue(void *base, int start, int size) -{ - writew(PCTODSP_BASED(start), base + JQS_wStart); - writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize); - writew(0, base + JQS_wHead); - writew(0, base + JQS_wTail); -} -EXPORT_SYMBOL(snd_msnd_init_queue); - -static int snd_msnd_wait_TXDE(struct snd_msnd *dev) -{ - unsigned int io = dev->io; - int timeout = 1000; - - while (timeout-- > 0) - if (inb(io + HP_ISR) & HPISR_TXDE) - return 0; - - return -EIO; -} - -static int snd_msnd_wait_HC0(struct snd_msnd *dev) -{ - unsigned int io = dev->io; - int timeout = 1000; - - while (timeout-- > 0) - if (!(inb(io + HP_CVR) & HPCVR_HC)) - return 0; - - return -EIO; -} - -int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - if (snd_msnd_wait_HC0(dev) == 0) { - outb(cmd, dev->io + HP_CVR); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n"); - - return -EIO; -} -EXPORT_SYMBOL(snd_msnd_send_dsp_cmd); - -int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high, - unsigned char mid, unsigned char low) -{ - unsigned int io = dev->io; - - if (snd_msnd_wait_TXDE(dev) == 0) { - outb(high, io + HP_TXH); - outb(mid, io + HP_TXM); - outb(low, io + HP_TXL); - return 0; - } - - snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n"); - - return -EIO; -} -EXPORT_SYMBOL(snd_msnd_send_word); - -int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len) -{ - int i; - - if (len % 3 != 0) { - snd_printk(KERN_ERR LOGNAME - ": Upload host data not multiple of 3!\n"); - return -EINVAL; - } - - for (i = 0; i < len; i += 3) - if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2])) - return -EIO; - - inb(dev->io + HP_RXL); - inb(dev->io + HP_CVR); - - return 0; -} -EXPORT_SYMBOL(snd_msnd_upload_host); - -int snd_msnd_enable_irq(struct snd_msnd *dev) -{ - unsigned long flags; - - if (dev->irq_ref++) - return 0; - - snd_printdd(LOGNAME ": Enabling IRQ\n"); - - spin_lock_irqsave(&dev->lock, flags); - if (snd_msnd_wait_TXDE(dev) == 0) { - outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR); - if (dev->type == msndClassic) - outb(dev->irqid, dev->io + HP_IRQM); - - outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR); - outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR); - enable_irq(dev->irq); - snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, - dev->dspq_buff_size); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n"); - - return -EIO; -} -EXPORT_SYMBOL(snd_msnd_enable_irq); - -int snd_msnd_disable_irq(struct snd_msnd *dev) -{ - unsigned long flags; - - if (--dev->irq_ref > 0) - return 0; - - if (dev->irq_ref < 0) - snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n", - dev->irq_ref); - - snd_printdd(LOGNAME ": Disabling IRQ\n"); - - spin_lock_irqsave(&dev->lock, flags); - if (snd_msnd_wait_TXDE(dev) == 0) { - outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR); - if (dev->type == msndClassic) - outb(HPIRQ_NONE, dev->io + HP_IRQM); - disable_irq(dev->irq); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n"); - - return -EIO; -} -EXPORT_SYMBOL(snd_msnd_disable_irq); - -static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size) -{ - long tmp = (size * HZ * chip->play_sample_size) / 8; - return tmp / (chip->play_sample_rate * chip->play_channels); -} - -static void snd_msnd_dsp_write_flush(struct snd_msnd *chip) -{ - if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags)) - return; - set_bit(F_WRITEFLUSH, &chip->flags); -/* interruptible_sleep_on_timeout( - &chip->writeflush, - get_play_delay_jiffies(&chip, chip->DAPF.len));*/ - clear_bit(F_WRITEFLUSH, &chip->flags); - if (!signal_pending(current)) - schedule_timeout_interruptible( - get_play_delay_jiffies(chip, chip->play_period_bytes)); - clear_bit(F_WRITING, &chip->flags); -} - -void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file) -{ - if ((file ? file->f_mode : chip->mode) & FMODE_READ) { - clear_bit(F_READING, &chip->flags); - snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); - snd_msnd_disable_irq(chip); - if (file) { - snd_printd(KERN_INFO LOGNAME - ": Stopping read for %p\n", file); - chip->mode &= ~FMODE_READ; - } - clear_bit(F_AUDIO_READ_INUSE, &chip->flags); - } - if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) { - if (test_bit(F_WRITING, &chip->flags)) { - snd_msnd_dsp_write_flush(chip); - snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); - } - snd_msnd_disable_irq(chip); - if (file) { - snd_printd(KERN_INFO - LOGNAME ": Stopping write for %p\n", file); - chip->mode &= ~FMODE_WRITE; - } - clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); - } -} -EXPORT_SYMBOL(snd_msnd_dsp_halt); - - -int snd_msnd_DARQ(struct snd_msnd *chip, int bank) -{ - int /*size, n,*/ timeout = 3; - u16 wTmp; - /* void *DAQD; */ - - /* Increment the tail and check for queue wrap */ - wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size); - if (wTmp > readw(chip->DARQ + JQS_wSize)) - wTmp = 0; - while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--) - udelay(1); - - if (chip->capturePeriods == 2) { - void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF + - bank * DAQDS__size + DAQDS_wStart; - unsigned short offset = 0x3000 + chip->capturePeriodBytes; - - if (readw(pDAQ) != PCTODSP_BASED(0x3000)) - offset = 0x3000; - writew(PCTODSP_BASED(offset), pDAQ); - } - - writew(wTmp, chip->DARQ + JQS_wTail); - -#if 0 - /* Get our digital audio queue struct */ - DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF; - - /* Get length of data */ - size = readw(DAQD + DAQDS_wSize); - - /* Read data from the head (unprotected bank 1 access okay - since this is only called inside an interrupt) */ - outb(HPBLKSEL_1, chip->io + HP_BLKS); - n = msnd_fifo_write(&chip->DARF, - (char *)(chip->base + bank * DAR_BUFF_SIZE), - size, 0); - if (n <= 0) { - outb(HPBLKSEL_0, chip->io + HP_BLKS); - return n; - } - outb(HPBLKSEL_0, chip->io + HP_BLKS); -#endif - - return 1; -} -EXPORT_SYMBOL(snd_msnd_DARQ); - -int snd_msnd_DAPQ(struct snd_msnd *chip, int start) -{ - u16 DAPQ_tail; - int protect = start, nbanks = 0; - void *DAQD; - static int play_banks_submitted; - /* unsigned long flags; - spin_lock_irqsave(&chip->lock, flags); not necessary */ - - DAPQ_tail = readw(chip->DAPQ + JQS_wTail); - while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) { - int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size); - - if (start) { - start = 0; - play_banks_submitted = 0; - } - - /* Get our digital audio queue struct */ - DAQD = bank_num * DAQDS__size + chip->mappedbase + - DAPQ_DATA_BUFF; - - /* Write size of this bank */ - writew(chip->play_period_bytes, DAQD + DAQDS_wSize); - if (play_banks_submitted < 3) - ++play_banks_submitted; - else if (chip->playPeriods == 2) { - unsigned short offset = chip->play_period_bytes; - - if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0)) - offset = 0; - - writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart); - } - ++nbanks; - - /* Then advance the tail */ - /* - if (protect) - snd_printd(KERN_INFO "B %X %lX\n", - bank_num, xtime.tv_usec); - */ - - DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); - writew(DAPQ_tail, chip->DAPQ + JQS_wTail); - /* Tell the DSP to play the bank */ - snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START); - if (protect) - if (2 == bank_num) - break; - } - /* - if (protect) - snd_printd(KERN_INFO "%lX\n", xtime.tv_usec); - */ - /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */ - return nbanks; -} -EXPORT_SYMBOL(snd_msnd_DAPQ); - -static void snd_msnd_play_reset_queue(struct snd_msnd *chip, - unsigned int pcm_periods, - unsigned int pcm_count) -{ - int n; - void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; - - chip->last_playbank = -1; - chip->playLimit = pcm_count * (pcm_periods - 1); - chip->playPeriods = pcm_periods; - writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead); - writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail); - - chip->play_period_bytes = pcm_count; - - for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { - writew(PCTODSP_BASED((u32)(pcm_count * n)), - pDAQ + DAQDS_wStart); - writew(0, pDAQ + DAQDS_wSize); - writew(1, pDAQ + DAQDS_wFormat); - writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); - writew(chip->play_channels, pDAQ + DAQDS_wChannels); - writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); - writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); - writew(n, pDAQ + DAQDS_wFlags); - } -} - -static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, - unsigned int pcm_periods, - unsigned int pcm_count) -{ - int n; - void *pDAQ; - /* unsigned long flags; */ - - /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */ - - chip->last_recbank = 2; - chip->captureLimit = pcm_count * (pcm_periods - 1); - chip->capturePeriods = pcm_periods; - writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead); - writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size), - chip->DARQ + JQS_wTail); - -#if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/ - spin_lock_irqsave(&chip->lock, flags); - outb(HPBLKSEL_1, chip->io + HP_BLKS); - memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3); - outb(HPBLKSEL_0, chip->io + HP_BLKS); - spin_unlock_irqrestore(&chip->lock, flags); -#endif - - chip->capturePeriodBytes = pcm_count; - snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count); - - pDAQ = chip->mappedbase + DARQ_DATA_BUFF; - - for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { - u32 tmp = pcm_count * n; - - writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart); - writew(pcm_count, pDAQ + DAQDS_wSize); - writew(1, pDAQ + DAQDS_wFormat); - writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); - writew(chip->capture_channels, pDAQ + DAQDS_wChannels); - writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); - writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); - writew(n, pDAQ + DAQDS_wFlags); - } -} - -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_BATCH, - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 0x3000, - .period_bytes_min = 0x40, - .period_bytes_max = 0x1800, - .periods_min = 2, - .periods_max = 3, - .fifo_size = 0, -}; - -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_BATCH, - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 0x3000, - .period_bytes_min = 0x40, - .period_bytes_max = 0x1800, - .periods_min = 2, - .periods_max = 3, - .fifo_size = 0, -}; - - -static int snd_msnd_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - set_bit(F_AUDIO_WRITE_INUSE, &chip->flags); - clear_bit(F_WRITING, &chip->flags); - snd_msnd_enable_irq(chip); - - runtime->dma_area = chip->mappedbase; - runtime->dma_bytes = 0x3000; - - chip->playback_substream = substream; - runtime->hw = snd_msnd_playback; - return 0; -} - -static int snd_msnd_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - snd_msnd_disable_irq(chip); - clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); - return 0; -} - - -static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - int i; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; - - chip->play_sample_size = snd_pcm_format_width(params_format(params)); - chip->play_channels = params_channels(params); - chip->play_sample_rate = params_rate(params); - - for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { - writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); - writew(chip->play_channels, pDAQ + DAQDS_wChannels); - writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); - } - /* dont do this here: - * snd_msnd_calibrate_adc(chip->play_sample_rate); - */ - - return 0; -} - -static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); - unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); - unsigned int pcm_periods = pcm_size / pcm_count; - - snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count); - chip->playDMAPos = 0; - return 0; -} - -static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - int result = 0; - - if (cmd == SNDRV_PCM_TRIGGER_START) { - snd_printdd("snd_msnd_playback_trigger(START)\n"); - chip->banksPlayed = 0; - set_bit(F_WRITING, &chip->flags); - snd_msnd_DAPQ(chip, 1); - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - snd_printdd("snd_msnd_playback_trigger(STop)\n"); - /* interrupt diagnostic, comment this out later */ - clear_bit(F_WRITING, &chip->flags); - snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); - } else { - snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n"); - result = -EINVAL; - } - - snd_printdd("snd_msnd_playback_trigger() ENDE\n"); - return result; -} - -static snd_pcm_uframes_t -snd_msnd_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - return bytes_to_frames(substream->runtime, chip->playDMAPos); -} - - -static struct snd_pcm_ops snd_msnd_playback_ops = { - .open = snd_msnd_playback_open, - .close = snd_msnd_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_msnd_playback_hw_params, - .prepare = snd_msnd_playback_prepare, - .trigger = snd_msnd_playback_trigger, - .pointer = snd_msnd_playback_pointer, -}; - -static int snd_msnd_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - set_bit(F_AUDIO_READ_INUSE, &chip->flags); - snd_msnd_enable_irq(chip); - runtime->dma_area = chip->mappedbase + 0x3000; - runtime->dma_bytes = 0x3000; - memset(runtime->dma_area, 0, runtime->dma_bytes); - chip->capture_substream = substream; - runtime->hw = snd_msnd_capture; - return 0; -} - -static int snd_msnd_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - snd_msnd_disable_irq(chip); - clear_bit(F_AUDIO_READ_INUSE, &chip->flags); - return 0; -} - -static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); - unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); - unsigned int pcm_periods = pcm_size / pcm_count; - - snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count); - chip->captureDMAPos = 0; - return 0; -} - -static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - if (cmd == SNDRV_PCM_TRIGGER_START) { - chip->last_recbank = -1; - set_bit(F_READING, &chip->flags); - if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0) - return 0; - - clear_bit(F_READING, &chip->flags); - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - clear_bit(F_READING, &chip->flags); - snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); - return 0; - } - return -EINVAL; -} - - -static snd_pcm_uframes_t -snd_msnd_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - return bytes_to_frames(runtime, chip->captureDMAPos); -} - - -static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - int i; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF; - - chip->capture_sample_size = snd_pcm_format_width(params_format(params)); - chip->capture_channels = params_channels(params); - chip->capture_sample_rate = params_rate(params); - - for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { - writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); - writew(chip->capture_channels, pDAQ + DAQDS_wChannels); - writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); - } - return 0; -} - - -static struct snd_pcm_ops snd_msnd_capture_ops = { - .open = snd_msnd_capture_open, - .close = snd_msnd_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_msnd_capture_hw_params, - .prepare = snd_msnd_capture_prepare, - .trigger = snd_msnd_capture_trigger, - .pointer = snd_msnd_capture_pointer, -}; - - -int snd_msnd_pcm(struct snd_card *card, int device, - struct snd_pcm **rpcm) -{ - struct snd_msnd *chip = card->private_data; - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops); - - pcm->private_data = chip; - strcpy(pcm->name, "Hurricane"); - - - if (rpcm) - *rpcm = pcm; - return 0; -} -EXPORT_SYMBOL(snd_msnd_pcm); - -MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd.h b/ANDROID_3.4.5/sound/isa/msnd/msnd.h deleted file mode 100644 index a168ba33..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd.h +++ /dev/null @@ -1,308 +0,0 @@ -/********************************************************************* - * - * msnd.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_H -#define __MSND_H - -#define DEFSAMPLERATE 44100 -#define DEFSAMPLESIZE SNDRV_PCM_FORMAT_S16 -#define DEFCHANNELS 1 - -#define SRAM_BANK_SIZE 0x8000 -#define SRAM_CNTL_START 0x7F00 -#define SMA_STRUCT_START 0x7F40 - -#define DSP_BASE_ADDR 0x4000 -#define DSP_BANK_BASE 0x4000 - -#define AGND 0x01 -#define SIGNAL 0x02 - -#define EXT_DSP_BIT_DCAL 0x0001 -#define EXT_DSP_BIT_MIDI_CON 0x0002 - -#define BUFFSIZE 0x8000 -#define HOSTQ_SIZE 0x40 - -#define DAP_BUFF_SIZE 0x2400 - -#define DAPQ_STRUCT_SIZE 0x10 -#define DARQ_STRUCT_SIZE 0x10 -#define DAPQ_BUFF_SIZE (3 * 0x10) -#define DARQ_BUFF_SIZE (3 * 0x10) -#define MODQ_BUFF_SIZE 0x400 - -#define DAPQ_DATA_BUFF 0x6C00 -#define DARQ_DATA_BUFF 0x6C30 -#define MODQ_DATA_BUFF 0x6C60 -#define MIDQ_DATA_BUFF 0x7060 - -#define DAPQ_OFFSET SRAM_CNTL_START -#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) -#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) -#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) -#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) - -#define HP_ICR 0x00 -#define HP_CVR 0x01 -#define HP_ISR 0x02 -#define HP_IVR 0x03 -#define HP_NU 0x04 -#define HP_INFO 0x04 -#define HP_TXH 0x05 -#define HP_RXH 0x05 -#define HP_TXM 0x06 -#define HP_RXM 0x06 -#define HP_TXL 0x07 -#define HP_RXL 0x07 - -#define HP_ICR_DEF 0x00 -#define HP_CVR_DEF 0x12 -#define HP_ISR_DEF 0x06 -#define HP_IVR_DEF 0x0f -#define HP_NU_DEF 0x00 - -#define HP_IRQM 0x09 - -#define HPR_BLRC 0x08 -#define HPR_SPR1 0x09 -#define HPR_SPR2 0x0A -#define HPR_TCL0 0x0B -#define HPR_TCL1 0x0C -#define HPR_TCL2 0x0D -#define HPR_TCL3 0x0E -#define HPR_TCL4 0x0F - -#define HPICR_INIT 0x80 -#define HPICR_HM1 0x40 -#define HPICR_HM0 0x20 -#define HPICR_HF1 0x10 -#define HPICR_HF0 0x08 -#define HPICR_TREQ 0x02 -#define HPICR_RREQ 0x01 - -#define HPCVR_HC 0x80 - -#define HPISR_HREQ 0x80 -#define HPISR_DMA 0x40 -#define HPISR_HF3 0x10 -#define HPISR_HF2 0x08 -#define HPISR_TRDY 0x04 -#define HPISR_TXDE 0x02 -#define HPISR_RXDF 0x01 - -#define HPIO_290 0 -#define HPIO_260 1 -#define HPIO_250 2 -#define HPIO_240 3 -#define HPIO_230 4 -#define HPIO_220 5 -#define HPIO_210 6 -#define HPIO_3E0 7 - -#define HPMEM_NONE 0 -#define HPMEM_B000 1 -#define HPMEM_C800 2 -#define HPMEM_D000 3 -#define HPMEM_D400 4 -#define HPMEM_D800 5 -#define HPMEM_E000 6 -#define HPMEM_E800 7 - -#define HPIRQ_NONE 0 -#define HPIRQ_5 1 -#define HPIRQ_7 2 -#define HPIRQ_9 3 -#define HPIRQ_10 4 -#define HPIRQ_11 5 -#define HPIRQ_12 6 -#define HPIRQ_15 7 - -#define HIMT_PLAY_DONE 0x00 -#define HIMT_RECORD_DONE 0x01 -#define HIMT_MIDI_EOS 0x02 -#define HIMT_MIDI_OUT 0x03 - -#define HIMT_MIDI_IN_UCHAR 0x0E -#define HIMT_DSP 0x0F - -#define HDEX_BASE 0x92 -#define HDEX_PLAY_START (0 + HDEX_BASE) -#define HDEX_PLAY_STOP (1 + HDEX_BASE) -#define HDEX_PLAY_PAUSE (2 + HDEX_BASE) -#define HDEX_PLAY_RESUME (3 + HDEX_BASE) -#define HDEX_RECORD_START (4 + HDEX_BASE) -#define HDEX_RECORD_STOP (5 + HDEX_BASE) -#define HDEX_MIDI_IN_START (6 + HDEX_BASE) -#define HDEX_MIDI_IN_STOP (7 + HDEX_BASE) -#define HDEX_MIDI_OUT_START (8 + HDEX_BASE) -#define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE) -#define HDEX_AUX_REQ (10 + HDEX_BASE) - -#define HDEXAR_CLEAR_PEAKS 1 -#define HDEXAR_IN_SET_POTS 2 -#define HDEXAR_AUX_SET_POTS 3 -#define HDEXAR_CAL_A_TO_D 4 -#define HDEXAR_RD_EXT_DSP_BITS 5 - -/* Pinnacle only HDEXAR defs */ -#define HDEXAR_SET_ANA_IN 0 -#define HDEXAR_SET_SYNTH_IN 4 -#define HDEXAR_READ_DAT_IN 5 -#define HDEXAR_MIC_SET_POTS 6 -#define HDEXAR_SET_DAT_IN 7 - -#define HDEXAR_SET_SYNTH_48 8 -#define HDEXAR_SET_SYNTH_44 9 - -#define HIWORD(l) ((u16)((((u32)(l)) >> 16) & 0xFFFF)) -#define LOWORD(l) ((u16)(u32)(l)) -#define HIBYTE(w) ((u8)(((u16)(w) >> 8) & 0xFF)) -#define LOBYTE(w) ((u8)(w)) -#define MAKELONG(low, hi) ((long)(((u16)(low))|(((u32)((u16)(hi)))<<16))) -#define MAKEWORD(low, hi) ((u16)(((u8)(low))|(((u16)((u8)(hi)))<<8))) - -#define PCTODSP_OFFSET(w) (u16)((w)/2) -#define PCTODSP_BASED(w) (u16)(((w)/2) + DSP_BASE_ADDR) -#define DSPTOPC_BASED(w) (((w) - DSP_BASE_ADDR) * 2) - -#ifdef SLOWIO -# undef outb -# undef inb -# define outb outb_p -# define inb inb_p -#endif - -/* JobQueueStruct */ -#define JQS_wStart 0x00 -#define JQS_wSize 0x02 -#define JQS_wHead 0x04 -#define JQS_wTail 0x06 -#define JQS__size 0x08 - -/* DAQueueDataStruct */ -#define DAQDS_wStart 0x00 -#define DAQDS_wSize 0x02 -#define DAQDS_wFormat 0x04 -#define DAQDS_wSampleSize 0x06 -#define DAQDS_wChannels 0x08 -#define DAQDS_wSampleRate 0x0A -#define DAQDS_wIntMsg 0x0C -#define DAQDS_wFlags 0x0E -#define DAQDS__size 0x10 - -#include - -struct snd_msnd { - void __iomem *mappedbase; - int play_period_bytes; - int playLimit; - int playPeriods; - int playDMAPos; - int banksPlayed; - int captureDMAPos; - int capturePeriodBytes; - int captureLimit; - int capturePeriods; - struct snd_card *card; - void *msndmidi_mpu; - struct snd_rawmidi *rmidi; - - /* Hardware resources */ - long io; - int memid, irqid; - int irq, irq_ref; - unsigned long base; - - /* Motorola 56k DSP SMA */ - void __iomem *SMA; - void __iomem *DAPQ; - void __iomem *DARQ; - void __iomem *MODQ; - void __iomem *MIDQ; - void __iomem *DSPQ; - int dspq_data_buff, dspq_buff_size; - - /* State variables */ - enum { msndClassic, msndPinnacle } type; - fmode_t mode; - unsigned long flags; -#define F_RESETTING 0 -#define F_HAVEDIGITAL 1 -#define F_AUDIO_WRITE_INUSE 2 -#define F_WRITING 3 -#define F_WRITEBLOCK 4 -#define F_WRITEFLUSH 5 -#define F_AUDIO_READ_INUSE 6 -#define F_READING 7 -#define F_READBLOCK 8 -#define F_EXT_MIDI_INUSE 9 -#define F_HDR_MIDI_INUSE 10 -#define F_DISABLE_WRITE_NDELAY 11 - spinlock_t lock; - spinlock_t mixer_lock; - int nresets; - unsigned recsrc; -#define LEVEL_ENTRIES 32 - int left_levels[LEVEL_ENTRIES]; - int right_levels[LEVEL_ENTRIES]; - int calibrate_signal; - int play_sample_size, play_sample_rate, play_channels; - int play_ndelay; - int capture_sample_size, capture_sample_rate, capture_channels; - int capture_ndelay; - u8 bCurrentMidiPatch; - - int last_playbank, last_recbank; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - -}; - -void snd_msnd_init_queue(void *base, int start, int size); - -int snd_msnd_send_dsp_cmd(struct snd_msnd *chip, u8 cmd); -int snd_msnd_send_word(struct snd_msnd *chip, - unsigned char high, - unsigned char mid, - unsigned char low); -int snd_msnd_upload_host(struct snd_msnd *chip, - const u8 *bin, int len); -int snd_msnd_enable_irq(struct snd_msnd *chip); -int snd_msnd_disable_irq(struct snd_msnd *chip); -void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file); -int snd_msnd_DAPQ(struct snd_msnd *chip, int start); -int snd_msnd_DARQ(struct snd_msnd *chip, int start); -int snd_msnd_pcm(struct snd_card *card, int device, struct snd_pcm **rpcm); - -int snd_msndmidi_new(struct snd_card *card, int device); -void snd_msndmidi_input_read(void *mpu); - -void snd_msndmix_setup(struct snd_msnd *chip); -int __devinit snd_msndmix_new(struct snd_card *card); -int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc); -#endif /* __MSND_H */ diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.c b/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.c deleted file mode 100644 index 3b23a096..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* The work is in msnd_pinnacle.c, just define MSND_CLASSIC before it. */ -#define MSND_CLASSIC -#include "msnd_pinnacle.c" diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.h b/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.h deleted file mode 100644 index f18d5fa5..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.h +++ /dev/null @@ -1,129 +0,0 @@ -/********************************************************************* - * - * msnd_classic.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_CLASSIC_H -#define __MSND_CLASSIC_H - -#define DSP_NUMIO 0x10 - -#define HP_MEMM 0x08 - -#define HP_BITM 0x0E -#define HP_WAIT 0x0D -#define HP_DSPR 0x0A -#define HP_PROR 0x0B -#define HP_BLKS 0x0C - -#define HPPRORESET_OFF 0 -#define HPPRORESET_ON 1 - -#define HPDSPRESET_OFF 0 -#define HPDSPRESET_ON 1 - -#define HPBLKSEL_0 0 -#define HPBLKSEL_1 1 - -#define HPWAITSTATE_0 0 -#define HPWAITSTATE_1 1 - -#define HPBITMODE_16 0 -#define HPBITMODE_8 1 - -#define HIDSP_INT_PLAY_UNDER 0x00 -#define HIDSP_INT_RECORD_OVER 0x01 -#define HIDSP_INPUT_CLIPPING 0x02 -#define HIDSP_MIDI_IN_OVER 0x10 -#define HIDSP_MIDI_OVERRUN_ERR 0x13 - -#define TIME_PRO_RESET_DONE 0x028A -#define TIME_PRO_SYSEX 0x0040 -#define TIME_PRO_RESET 0x0032 - -#define DAR_BUFF_SIZE 0x2000 - -#define MIDQ_BUFF_SIZE 0x200 -#define DSPQ_BUFF_SIZE 0x40 - -#define DSPQ_DATA_BUFF 0x7260 - -#define MOP_SYNTH 0x10 -#define MOP_EXTOUT 0x32 -#define MOP_EXTTHRU 0x02 -#define MOP_OUTMASK 0x01 - -#define MIP_EXTIN 0x01 -#define MIP_SYNTH 0x00 -#define MIP_INMASK 0x32 - -/* Classic SMA Common Data */ -#define SMA_wCurrPlayBytes 0x0000 -#define SMA_wCurrRecordBytes 0x0002 -#define SMA_wCurrPlayVolLeft 0x0004 -#define SMA_wCurrPlayVolRight 0x0006 -#define SMA_wCurrInVolLeft 0x0008 -#define SMA_wCurrInVolRight 0x000a -#define SMA_wUser_3 0x000c -#define SMA_wUser_4 0x000e -#define SMA_dwUser_5 0x0010 -#define SMA_dwUser_6 0x0014 -#define SMA_wUser_7 0x0018 -#define SMA_wReserved_A 0x001a -#define SMA_wReserved_B 0x001c -#define SMA_wReserved_C 0x001e -#define SMA_wReserved_D 0x0020 -#define SMA_wReserved_E 0x0022 -#define SMA_wReserved_F 0x0024 -#define SMA_wReserved_G 0x0026 -#define SMA_wReserved_H 0x0028 -#define SMA_wCurrDSPStatusFlags 0x002a -#define SMA_wCurrHostStatusFlags 0x002c -#define SMA_wCurrInputTagBits 0x002e -#define SMA_wCurrLeftPeak 0x0030 -#define SMA_wCurrRightPeak 0x0032 -#define SMA_wExtDSPbits 0x0034 -#define SMA_bExtHostbits 0x0036 -#define SMA_bBoardLevel 0x0037 -#define SMA_bInPotPosRight 0x0038 -#define SMA_bInPotPosLeft 0x0039 -#define SMA_bAuxPotPosRight 0x003a -#define SMA_bAuxPotPosLeft 0x003b -#define SMA_wCurrMastVolLeft 0x003c -#define SMA_wCurrMastVolRight 0x003e -#define SMA_bUser_12 0x0040 -#define SMA_bUser_13 0x0041 -#define SMA_wUser_14 0x0042 -#define SMA_wUser_15 0x0044 -#define SMA_wCalFreqAtoD 0x0046 -#define SMA_wUser_16 0x0048 -#define SMA_wUser_17 0x004a -#define SMA__size 0x004c - -#define INITCODEFILE "turtlebeach/msndinit.bin" -#define PERMCODEFILE "turtlebeach/msndperm.bin" -#define LONGNAME "MultiSound (Classic/Monterey/Tahiti)" - -#endif /* __MSND_CLASSIC_H */ diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_midi.c b/ANDROID_3.4.5/sound/isa/msnd/msnd_midi.c deleted file mode 100644 index ffc67fd8..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_midi.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Copyright (c) 2009 by Krzysztof Helt - * Routines for control of MPU-401 in UART mode - * - * MPU-401 supports UART mode which is not capable generate transmit - * interrupts thus output is done via polling. Also, if irq < 0, then - * input is done also via polling. Do not expect good performance. - * - * - * 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 "msnd.h" - -#define MSNDMIDI_MODE_BIT_INPUT 0 -#define MSNDMIDI_MODE_BIT_OUTPUT 1 -#define MSNDMIDI_MODE_BIT_INPUT_TRIGGER 2 -#define MSNDMIDI_MODE_BIT_OUTPUT_TRIGGER 3 - -struct snd_msndmidi { - struct snd_msnd *dev; - - unsigned long mode; /* MSNDMIDI_MODE_XXXX */ - - struct snd_rawmidi_substream *substream_input; - - spinlock_t input_lock; -}; - -/* - * input/output open/close - protected by open_mutex in rawmidi.c - */ -static int snd_msndmidi_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_msndmidi *mpu; - - snd_printdd("snd_msndmidi_input_open()\n"); - - mpu = substream->rmidi->private_data; - - mpu->substream_input = substream; - - snd_msnd_enable_irq(mpu->dev); - - snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_START); - set_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); - return 0; -} - -static int snd_msndmidi_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_msndmidi *mpu; - - mpu = substream->rmidi->private_data; - snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_STOP); - clear_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); - mpu->substream_input = NULL; - snd_msnd_disable_irq(mpu->dev); - return 0; -} - -static void snd_msndmidi_input_drop(struct snd_msndmidi *mpu) -{ - u16 tail; - - tail = readw(mpu->dev->MIDQ + JQS_wTail); - writew(tail, mpu->dev->MIDQ + JQS_wHead); -} - -/* - * trigger input - */ -static void snd_msndmidi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - unsigned long flags; - struct snd_msndmidi *mpu; - - snd_printdd("snd_msndmidi_input_trigger(, %i)\n", up); - - mpu = substream->rmidi->private_data; - spin_lock_irqsave(&mpu->input_lock, flags); - if (up) { - if (!test_and_set_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, - &mpu->mode)) - snd_msndmidi_input_drop(mpu); - } else { - clear_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode); - } - spin_unlock_irqrestore(&mpu->input_lock, flags); - if (up) - snd_msndmidi_input_read(mpu); -} - -void snd_msndmidi_input_read(void *mpuv) -{ - unsigned long flags; - struct snd_msndmidi *mpu = mpuv; - void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; - - spin_lock_irqsave(&mpu->input_lock, flags); - while (readw(mpu->dev->MIDQ + JQS_wTail) != - readw(mpu->dev->MIDQ + JQS_wHead)) { - u16 wTmp, val; - val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead)); - - if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, - &mpu->mode)) - snd_rawmidi_receive(mpu->substream_input, - (unsigned char *)&val, 1); - - wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1; - if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize)) - writew(0, mpu->dev->MIDQ + JQS_wHead); - else - writew(wTmp, mpu->dev->MIDQ + JQS_wHead); - } - spin_unlock_irqrestore(&mpu->input_lock, flags); -} -EXPORT_SYMBOL(snd_msndmidi_input_read); - -static struct snd_rawmidi_ops snd_msndmidi_input = { - .open = snd_msndmidi_input_open, - .close = snd_msndmidi_input_close, - .trigger = snd_msndmidi_input_trigger, -}; - -static void snd_msndmidi_free(struct snd_rawmidi *rmidi) -{ - struct snd_msndmidi *mpu = rmidi->private_data; - kfree(mpu); -} - -int snd_msndmidi_new(struct snd_card *card, int device) -{ - struct snd_msnd *chip = card->private_data; - struct snd_msndmidi *mpu; - struct snd_rawmidi *rmidi; - int err; - - err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi); - if (err < 0) - return err; - mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); - if (mpu == NULL) { - snd_device_free(card, rmidi); - return -ENOMEM; - } - mpu->dev = chip; - chip->msndmidi_mpu = mpu; - rmidi->private_data = mpu; - rmidi->private_free = snd_msndmidi_free; - spin_lock_init(&mpu->input_lock); - strcpy(rmidi->name, "MSND MIDI"); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_msndmidi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.c b/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.c deleted file mode 100644 index 29cc8e16..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.c +++ /dev/null @@ -1,1245 +0,0 @@ -/********************************************************************* - * - * Linux multisound pinnacle/fiji driver for ALSA. - * - * 2002/06/30 Karsten Wiese: - * for now this is only used to build a pinnacle / fiji driver. - * the OSS parent of this code is designed to also support - * the multisound classic via the file msnd_classic.c. - * to make it easier for some brave heart to implemt classic - * support in alsa, i left all the MSND_CLASSIC tokens in this file. - * but for now this untested & undone. - * - * - * ripped from linux kernel 2.4.18 by Karsten Wiese. - * - * the following is a copy of the 2.4.18 OSS FREE file-heading comment: - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * msnd_pinnacle.c / msnd_classic.c - * - * -- If MSND_CLASSIC is defined: - * - * -> driver for Turtle Beach Classic/Monterey/Tahiti - * - * -- Else - * - * -> driver for Turtle Beach Pinnacle/Fiji - * - * 12-3-2000 Modified IO port validation Steve Sycamore - * - * Copyright (C) 1998 Andrew Veliath - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef MSND_CLASSIC -# ifndef __alpha__ -# define SLOWIO -# endif -#endif -#include "msnd.h" -#ifdef MSND_CLASSIC -# include "msnd_classic.h" -# define LOGNAME "msnd_classic" -#else -# include "msnd_pinnacle.h" -# define LOGNAME "snd_msnd_pinnacle" -#endif - -static void __devinit set_default_audio_parameters(struct snd_msnd *chip) -{ - chip->play_sample_size = DEFSAMPLESIZE; - chip->play_sample_rate = DEFSAMPLERATE; - chip->play_channels = DEFCHANNELS; - chip->capture_sample_size = DEFSAMPLESIZE; - chip->capture_sample_rate = DEFSAMPLERATE; - chip->capture_channels = DEFCHANNELS; -} - -static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage) -{ - switch (HIBYTE(wMessage)) { - case HIMT_PLAY_DONE: { - if (chip->banksPlayed < 3) - snd_printdd("%08X: HIMT_PLAY_DONE: %i\n", - (unsigned)jiffies, LOBYTE(wMessage)); - - if (chip->last_playbank == LOBYTE(wMessage)) { - snd_printdd("chip.last_playbank == LOBYTE(wMessage)\n"); - break; - } - chip->banksPlayed++; - - if (test_bit(F_WRITING, &chip->flags)) - snd_msnd_DAPQ(chip, 0); - - chip->last_playbank = LOBYTE(wMessage); - chip->playDMAPos += chip->play_period_bytes; - if (chip->playDMAPos > chip->playLimit) - chip->playDMAPos = 0; - snd_pcm_period_elapsed(chip->playback_substream); - - break; - } - case HIMT_RECORD_DONE: - if (chip->last_recbank == LOBYTE(wMessage)) - break; - chip->last_recbank = LOBYTE(wMessage); - chip->captureDMAPos += chip->capturePeriodBytes; - if (chip->captureDMAPos > (chip->captureLimit)) - chip->captureDMAPos = 0; - - if (test_bit(F_READING, &chip->flags)) - snd_msnd_DARQ(chip, chip->last_recbank); - - snd_pcm_period_elapsed(chip->capture_substream); - break; - - case HIMT_DSP: - switch (LOBYTE(wMessage)) { -#ifndef MSND_CLASSIC - case HIDSP_PLAY_UNDER: -#endif - case HIDSP_INT_PLAY_UNDER: - snd_printd(KERN_WARNING LOGNAME ": Play underflow %i\n", - chip->banksPlayed); - if (chip->banksPlayed > 2) - clear_bit(F_WRITING, &chip->flags); - break; - - case HIDSP_INT_RECORD_OVER: - snd_printd(KERN_WARNING LOGNAME ": Record overflow\n"); - clear_bit(F_READING, &chip->flags); - break; - - default: - snd_printd(KERN_WARNING LOGNAME - ": DSP message %d 0x%02x\n", - LOBYTE(wMessage), LOBYTE(wMessage)); - break; - } - break; - - case HIMT_MIDI_IN_UCHAR: - if (chip->msndmidi_mpu) - snd_msndmidi_input_read(chip->msndmidi_mpu); - break; - - default: - snd_printd(KERN_WARNING LOGNAME ": HIMT message %d 0x%02x\n", - HIBYTE(wMessage), HIBYTE(wMessage)); - break; - } -} - -static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) -{ - struct snd_msnd *chip = dev_id; - void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; - - /* Send ack to DSP */ - /* inb(chip->io + HP_RXL); */ - - /* Evaluate queued DSP messages */ - while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { - u16 wTmp; - - snd_msnd_eval_dsp_msg(chip, - readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); - - wTmp = readw(chip->DSPQ + JQS_wHead) + 1; - if (wTmp > readw(chip->DSPQ + JQS_wSize)) - writew(0, chip->DSPQ + JQS_wHead); - else - writew(wTmp, chip->DSPQ + JQS_wHead); - } - /* Send ack to DSP */ - inb(chip->io + HP_RXL); - return IRQ_HANDLED; -} - - -static int snd_msnd_reset_dsp(long io, unsigned char *info) -{ - int timeout = 100; - - outb(HPDSPRESET_ON, io + HP_DSPR); - msleep(1); -#ifndef MSND_CLASSIC - if (info) - *info = inb(io + HP_INFO); -#endif - outb(HPDSPRESET_OFF, io + HP_DSPR); - msleep(1); - while (timeout-- > 0) { - if (inb(io + HP_CVR) == HP_CVR_DEF) - return 0; - msleep(1); - } - snd_printk(KERN_ERR LOGNAME ": Cannot reset DSP\n"); - - return -EIO; -} - -static int __devinit snd_msnd_probe(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - unsigned char info; -#ifndef MSND_CLASSIC - char *xv, *rev = NULL; - char *pin = "TB Pinnacle", *fiji = "TB Fiji"; - char *pinfiji = "TB Pinnacle/Fiji"; -#endif - - if (!request_region(chip->io, DSP_NUMIO, "probing")) { - snd_printk(KERN_ERR LOGNAME ": I/O port conflict\n"); - return -ENODEV; - } - - if (snd_msnd_reset_dsp(chip->io, &info) < 0) { - release_region(chip->io, DSP_NUMIO); - return -ENODEV; - } - -#ifdef MSND_CLASSIC - strcpy(card->shortname, "Classic/Tahiti/Monterey"); - strcpy(card->longname, "Turtle Beach Multisound"); - printk(KERN_INFO LOGNAME ": %s, " - "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", - card->shortname, - chip->io, chip->io + DSP_NUMIO - 1, - chip->irq, - chip->base, chip->base + 0x7fff); -#else - switch (info >> 4) { - case 0xf: - xv = "<= 1.15"; - break; - case 0x1: - xv = "1.18/1.2"; - break; - case 0x2: - xv = "1.3"; - break; - case 0x3: - xv = "1.4"; - break; - default: - xv = "unknown"; - break; - } - - switch (info & 0x7) { - case 0x0: - rev = "I"; - strcpy(card->shortname, pin); - break; - case 0x1: - rev = "F"; - strcpy(card->shortname, pin); - break; - case 0x2: - rev = "G"; - strcpy(card->shortname, pin); - break; - case 0x3: - rev = "H"; - strcpy(card->shortname, pin); - break; - case 0x4: - rev = "E"; - strcpy(card->shortname, fiji); - break; - case 0x5: - rev = "C"; - strcpy(card->shortname, fiji); - break; - case 0x6: - rev = "D"; - strcpy(card->shortname, fiji); - break; - case 0x7: - rev = "A-B (Fiji) or A-E (Pinnacle)"; - strcpy(card->shortname, pinfiji); - break; - } - strcpy(card->longname, "Turtle Beach Multisound Pinnacle"); - printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, " - "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", - card->shortname, - rev, xv, - chip->io, chip->io + DSP_NUMIO - 1, - chip->irq, - chip->base, chip->base + 0x7fff); -#endif - - release_region(chip->io, DSP_NUMIO); - return 0; -} - -static int snd_msnd_init_sma(struct snd_msnd *chip) -{ - static int initted; - u16 mastVolLeft, mastVolRight; - unsigned long flags; - -#ifdef MSND_CLASSIC - outb(chip->memid, chip->io + HP_MEMM); -#endif - outb(HPBLKSEL_0, chip->io + HP_BLKS); - /* Motorola 56k shared memory base */ - chip->SMA = chip->mappedbase + SMA_STRUCT_START; - - if (initted) { - mastVolLeft = readw(chip->SMA + SMA_wCurrMastVolLeft); - mastVolRight = readw(chip->SMA + SMA_wCurrMastVolRight); - } else - mastVolLeft = mastVolRight = 0; - memset_io(chip->mappedbase, 0, 0x8000); - - /* Critical section: bank 1 access */ - spin_lock_irqsave(&chip->lock, flags); - outb(HPBLKSEL_1, chip->io + HP_BLKS); - memset_io(chip->mappedbase, 0, 0x8000); - outb(HPBLKSEL_0, chip->io + HP_BLKS); - spin_unlock_irqrestore(&chip->lock, flags); - - /* Digital audio play queue */ - chip->DAPQ = chip->mappedbase + DAPQ_OFFSET; - snd_msnd_init_queue(chip->DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE); - - /* Digital audio record queue */ - chip->DARQ = chip->mappedbase + DARQ_OFFSET; - snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); - - /* MIDI out queue */ - chip->MODQ = chip->mappedbase + MODQ_OFFSET; - snd_msnd_init_queue(chip->MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE); - - /* MIDI in queue */ - chip->MIDQ = chip->mappedbase + MIDQ_OFFSET; - snd_msnd_init_queue(chip->MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE); - - /* DSP -> host message queue */ - chip->DSPQ = chip->mappedbase + DSPQ_OFFSET; - snd_msnd_init_queue(chip->DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE); - - /* Setup some DSP values */ -#ifndef MSND_CLASSIC - writew(1, chip->SMA + SMA_wCurrPlayFormat); - writew(chip->play_sample_size, chip->SMA + SMA_wCurrPlaySampleSize); - writew(chip->play_channels, chip->SMA + SMA_wCurrPlayChannels); - writew(chip->play_sample_rate, chip->SMA + SMA_wCurrPlaySampleRate); -#endif - writew(chip->play_sample_rate, chip->SMA + SMA_wCalFreqAtoD); - writew(mastVolLeft, chip->SMA + SMA_wCurrMastVolLeft); - writew(mastVolRight, chip->SMA + SMA_wCurrMastVolRight); -#ifndef MSND_CLASSIC - writel(0x00010000, chip->SMA + SMA_dwCurrPlayPitch); - writel(0x00000001, chip->SMA + SMA_dwCurrPlayRate); -#endif - writew(0x303, chip->SMA + SMA_wCurrInputTagBits); - - initted = 1; - - return 0; -} - - -static int upload_dsp_code(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - const struct firmware *init_fw = NULL, *perm_fw = NULL; - int err; - - outb(HPBLKSEL_0, chip->io + HP_BLKS); - - err = request_firmware(&init_fw, INITCODEFILE, card->dev); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE); - goto cleanup1; - } - err = request_firmware(&perm_fw, PERMCODEFILE, card->dev); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE); - goto cleanup; - } - - memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size); - if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) { - printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); - err = -ENODEV; - goto cleanup; - } - printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n"); - err = 0; - -cleanup: - release_firmware(perm_fw); -cleanup1: - release_firmware(init_fw); - return err; -} - -#ifdef MSND_CLASSIC -static void reset_proteus(struct snd_msnd *chip) -{ - outb(HPPRORESET_ON, chip->io + HP_PROR); - msleep(TIME_PRO_RESET); - outb(HPPRORESET_OFF, chip->io + HP_PROR); - msleep(TIME_PRO_RESET_DONE); -} -#endif - -static int snd_msnd_initialize(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - int err, timeout; - -#ifdef MSND_CLASSIC - outb(HPWAITSTATE_0, chip->io + HP_WAIT); - outb(HPBITMODE_16, chip->io + HP_BITM); - - reset_proteus(chip); -#endif - err = snd_msnd_init_sma(chip); - if (err < 0) { - printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); - return err; - } - - err = snd_msnd_reset_dsp(chip->io, NULL); - if (err < 0) - return err; - - err = upload_dsp_code(card); - if (err < 0) { - printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); - return err; - } - - timeout = 200; - - while (readw(chip->mappedbase)) { - msleep(1); - if (!timeout--) { - snd_printd(KERN_ERR LOGNAME ": DSP reset timeout\n"); - return -EIO; - } - } - - snd_msndmix_setup(chip); - return 0; -} - -static int snd_msnd_dsp_full_reset(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - int rv; - - if (test_bit(F_RESETTING, &chip->flags) || ++chip->nresets > 10) - return 0; - - set_bit(F_RESETTING, &chip->flags); - snd_msnd_dsp_halt(chip, NULL); /* Unconditionally halt */ - - rv = snd_msnd_initialize(card); - if (rv) - printk(KERN_WARNING LOGNAME ": DSP reset failed\n"); - snd_msndmix_force_recsrc(chip, 0); - clear_bit(F_RESETTING, &chip->flags); - return rv; -} - -static int snd_msnd_dev_free(struct snd_device *device) -{ - snd_printdd("snd_msnd_chip_free()\n"); - return 0; -} - -static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd) -{ - if (snd_msnd_send_dsp_cmd(chip, cmd) == 0) - return 0; - snd_msnd_dsp_full_reset(chip->card); - return snd_msnd_send_dsp_cmd(chip, cmd); -} - -static int __devinit snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate) -{ - snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate); - writew(srate, chip->SMA + SMA_wCalFreqAtoD); - if (chip->calibrate_signal == 0) - writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) - | 0x0001, chip->SMA + SMA_wCurrHostStatusFlags); - else - writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) - & ~0x0001, chip->SMA + SMA_wCurrHostStatusFlags); - if (snd_msnd_send_word(chip, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && - snd_msnd_send_dsp_cmd_chk(chip, HDEX_AUX_REQ) == 0) { - schedule_timeout_interruptible(msecs_to_jiffies(333)); - return 0; - } - printk(KERN_WARNING LOGNAME ": ADC calibration failed\n"); - return -EIO; -} - -/* - * ALSA callback function, called when attempting to open the MIDI device. - */ -static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu) -{ - snd_msnd_enable_irq(mpu->private_data); - snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START); - return 0; -} - -static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu) -{ - snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP); - snd_msnd_disable_irq(mpu->private_data); -} - -static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; - -static int __devinit snd_msnd_attach(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_msnd_dev_free, - }; - - err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname, - chip); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); - return err; - } - if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) { - free_irq(chip->irq, chip); - return -EBUSY; - } - - if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) { - printk(KERN_ERR LOGNAME - ": unable to grab memory region 0x%lx-0x%lx\n", - chip->base, chip->base + BUFFSIZE - 1); - release_region(chip->io, DSP_NUMIO); - free_irq(chip->irq, chip); - return -EBUSY; - } - chip->mappedbase = ioremap_nocache(chip->base, 0x8000); - if (!chip->mappedbase) { - printk(KERN_ERR LOGNAME - ": unable to map memory region 0x%lx-0x%lx\n", - chip->base, chip->base + BUFFSIZE - 1); - err = -EIO; - goto err_release_region; - } - - err = snd_msnd_dsp_full_reset(card); - if (err < 0) - goto err_release_region; - - /* Register device */ - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) - goto err_release_region; - - err = snd_msnd_pcm(card, 0, NULL); - if (err < 0) { - printk(KERN_ERR LOGNAME ": error creating new PCM device\n"); - goto err_release_region; - } - - err = snd_msndmix_new(card); - if (err < 0) { - printk(KERN_ERR LOGNAME ": error creating new Mixer device\n"); - goto err_release_region; - } - - - if (mpu_io[0] != SNDRV_AUTO_PORT) { - struct snd_mpu401 *mpu; - - err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_io[0], - MPU401_MODE_INPUT | - MPU401_MODE_OUTPUT, - mpu_irq[0], - &chip->rmidi); - if (err < 0) { - printk(KERN_ERR LOGNAME - ": error creating new Midi device\n"); - goto err_release_region; - } - mpu = chip->rmidi->private_data; - - mpu->open_input = snd_msnd_mpu401_open; - mpu->close_input = snd_msnd_mpu401_close; - mpu->private_data = chip; - } - - disable_irq(chip->irq); - snd_msnd_calibrate_adc(chip, chip->play_sample_rate); - snd_msndmix_force_recsrc(chip, 0); - - err = snd_card_register(card); - if (err < 0) - goto err_release_region; - - return 0; - -err_release_region: - if (chip->mappedbase) - iounmap(chip->mappedbase); - release_mem_region(chip->base, BUFFSIZE); - release_region(chip->io, DSP_NUMIO); - free_irq(chip->irq, chip); - return err; -} - - -static void __devexit snd_msnd_unload(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - - iounmap(chip->mappedbase); - release_mem_region(chip->base, BUFFSIZE); - release_region(chip->io, DSP_NUMIO); - free_irq(chip->irq, chip); - snd_card_free(card); -} - -#ifndef MSND_CLASSIC - -/* Pinnacle/Fiji Logical Device Configuration */ - -static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value) -{ - outb(reg, cfg); - outb(value, cfg + 1); - if (value != inb(cfg + 1)) { - printk(KERN_ERR LOGNAME ": snd_msnd_write_cfg: I/O error\n"); - return -EIO; - } - return 0; -} - -static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io))) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io))) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io))) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io))) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem) -{ - u16 wmem; - - mem >>= 8; - wmem = (u16)(mem & 0xfff); - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem))) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem))) - return -EIO; - if (wmem && snd_msnd_write_cfg(cfg, IREG_MEMCONTROL, - MEMTYPE_HIADDR | MEMTYPE_16BIT)) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_activate_logical(int cfg, int num) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE)) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0, - u16 io1, u16 irq, int mem) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg_io0(cfg, num, io0)) - return -EIO; - if (snd_msnd_write_cfg_io1(cfg, num, io1)) - return -EIO; - if (snd_msnd_write_cfg_irq(cfg, num, irq)) - return -EIO; - if (snd_msnd_write_cfg_mem(cfg, num, mem)) - return -EIO; - if (snd_msnd_activate_logical(cfg, num)) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_pinnacle_cfg_reset(int cfg) -{ - int i; - - /* Reset devices if told to */ - printk(KERN_INFO LOGNAME ": Resetting all devices\n"); - for (i = 0; i < 4; ++i) - if (snd_msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0)) - return -EIO; - - return 0; -} -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ - -module_param_array(index, int, NULL, S_IRUGO); -MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard."); -module_param_array(id, charp, NULL, S_IRUGO); -MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard."); - -static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; - -#ifndef MSND_CLASSIC -static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; - -/* Extra Peripheral Configuration (Default: Disable) */ -static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int ide_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; - -static long joystick_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -/* If we have the digital daugherboard... */ -static int digital[SNDRV_CARDS]; - -/* Extra Peripheral Configuration */ -static int reset[SNDRV_CARDS]; -#endif - -static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; - -static int calibrate_signal; - -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); -#define has_isapnp(x) isapnp[x] -#else -#define has_isapnp(x) 0 -#endif - -MODULE_AUTHOR("Karsten Wiese "); -MODULE_DESCRIPTION("Turtle Beach " LONGNAME " Linux Driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(INITCODEFILE); -MODULE_FIRMWARE(PERMCODEFILE); - -module_param_array(io, long, NULL, S_IRUGO); -MODULE_PARM_DESC(io, "IO port #"); -module_param_array(irq, int, NULL, S_IRUGO); -module_param_array(mem, long, NULL, S_IRUGO); -module_param_array(write_ndelay, int, NULL, S_IRUGO); -module_param(calibrate_signal, int, S_IRUGO); -#ifndef MSND_CLASSIC -module_param_array(digital, int, NULL, S_IRUGO); -module_param_array(cfg, long, NULL, S_IRUGO); -module_param_array(reset, int, 0, S_IRUGO); -module_param_array(mpu_io, long, NULL, S_IRUGO); -module_param_array(mpu_irq, int, NULL, S_IRUGO); -module_param_array(ide_io0, long, NULL, S_IRUGO); -module_param_array(ide_io1, long, NULL, S_IRUGO); -module_param_array(ide_irq, int, NULL, S_IRUGO); -module_param_array(joystick_io, long, NULL, S_IRUGO); -#endif - - -static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i) -{ - if (io[i] == SNDRV_AUTO_PORT) - return 0; - - if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) { - printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); - return 0; - } - -#ifdef MSND_CLASSIC - if (!(io[i] == 0x290 || - io[i] == 0x260 || - io[i] == 0x250 || - io[i] == 0x240 || - io[i] == 0x230 || - io[i] == 0x220 || - io[i] == 0x210 || - io[i] == 0x3e0)) { - printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set " - " to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, " - "or 0x3E0\n"); - return 0; - } -#else - if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) { - printk(KERN_ERR LOGNAME - ": \"io\" - DSP I/O base must within the range 0x100 " - "to 0x3E0 and must be evenly divisible by 0x10\n"); - return 0; - } -#endif /* MSND_CLASSIC */ - - if (!(irq[i] == 5 || - irq[i] == 7 || - irq[i] == 9 || - irq[i] == 10 || - irq[i] == 11 || - irq[i] == 12)) { - printk(KERN_ERR LOGNAME - ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); - return 0; - } - - if (!(mem[i] == 0xb0000 || - mem[i] == 0xc8000 || - mem[i] == 0xd0000 || - mem[i] == 0xd8000 || - mem[i] == 0xe0000 || - mem[i] == 0xe8000)) { - printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " - "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or " - "0xe8000\n"); - return 0; - } - -#ifndef MSND_CLASSIC - if (cfg[i] == SNDRV_AUTO_PORT) { - printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); - } else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) { - printk(KERN_INFO LOGNAME - ": Config port must be 0x250, 0x260 or 0x270 " - "(or unspecified for PnP mode)\n"); - return 0; - } -#endif /* MSND_CLASSIC */ - - return 1; -} - -static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx) -{ - int err; - struct snd_card *card; - struct snd_msnd *chip; - - if (has_isapnp(idx) -#ifndef MSND_CLASSIC - || cfg[idx] == SNDRV_AUTO_PORT -#endif - ) { - printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); - return -ENODEV; - } - - err = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct snd_msnd), &card); - if (err < 0) - return err; - - snd_card_set_dev(card, pdev); - chip = card->private_data; - chip->card = card; - -#ifdef MSND_CLASSIC - switch (irq[idx]) { - case 5: - chip->irqid = HPIRQ_5; break; - case 7: - chip->irqid = HPIRQ_7; break; - case 9: - chip->irqid = HPIRQ_9; break; - case 10: - chip->irqid = HPIRQ_10; break; - case 11: - chip->irqid = HPIRQ_11; break; - case 12: - chip->irqid = HPIRQ_12; break; - } - - switch (mem[idx]) { - case 0xb0000: - chip->memid = HPMEM_B000; break; - case 0xc8000: - chip->memid = HPMEM_C800; break; - case 0xd0000: - chip->memid = HPMEM_D000; break; - case 0xd8000: - chip->memid = HPMEM_D800; break; - case 0xe0000: - chip->memid = HPMEM_E000; break; - case 0xe8000: - chip->memid = HPMEM_E800; break; - } -#else - printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n", - cfg[idx]); - - if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) { - printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n", - cfg[idx]); - snd_card_free(card); - return -EIO; - } - if (reset[idx]) - if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) { - err = -EIO; - goto cfg_error; - } - - /* DSP */ - err = snd_msnd_write_cfg_logical(cfg[idx], 0, - io[idx], 0, - irq[idx], mem[idx]); - - if (err) - goto cfg_error; - - /* The following are Pinnacle specific */ - - /* MPU */ - if (mpu_io[idx] != SNDRV_AUTO_PORT - && mpu_irq[idx] != SNDRV_AUTO_IRQ) { - printk(KERN_INFO LOGNAME - ": Configuring MPU to I/O 0x%lx IRQ %d\n", - mpu_io[idx], mpu_irq[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 1, - mpu_io[idx], 0, - mpu_irq[idx], 0); - - if (err) - goto cfg_error; - } - - /* IDE */ - if (ide_io0[idx] != SNDRV_AUTO_PORT - && ide_io1[idx] != SNDRV_AUTO_PORT - && ide_irq[idx] != SNDRV_AUTO_IRQ) { - printk(KERN_INFO LOGNAME - ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n", - ide_io0[idx], ide_io1[idx], ide_irq[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 2, - ide_io0[idx], ide_io1[idx], - ide_irq[idx], 0); - - if (err) - goto cfg_error; - } - - /* Joystick */ - if (joystick_io[idx] != SNDRV_AUTO_PORT) { - printk(KERN_INFO LOGNAME - ": Configuring joystick to I/O 0x%lx\n", - joystick_io[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 3, - joystick_io[idx], 0, - 0, 0); - - if (err) - goto cfg_error; - } - release_region(cfg[idx], 2); - -#endif /* MSND_CLASSIC */ - - set_default_audio_parameters(chip); -#ifdef MSND_CLASSIC - chip->type = msndClassic; -#else - chip->type = msndPinnacle; -#endif - chip->io = io[idx]; - chip->irq = irq[idx]; - chip->base = mem[idx]; - - chip->calibrate_signal = calibrate_signal ? 1 : 0; - chip->recsrc = 0; - chip->dspq_data_buff = DSPQ_DATA_BUFF; - chip->dspq_buff_size = DSPQ_BUFF_SIZE; - if (write_ndelay[idx]) - clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); - else - set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); -#ifndef MSND_CLASSIC - if (digital[idx]) - set_bit(F_HAVEDIGITAL, &chip->flags); -#endif - spin_lock_init(&chip->lock); - err = snd_msnd_probe(card); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Probe failed\n"); - snd_card_free(card); - return err; - } - - err = snd_msnd_attach(card); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Attach failed\n"); - snd_card_free(card); - return err; - } - dev_set_drvdata(pdev, card); - - return 0; - -#ifndef MSND_CLASSIC -cfg_error: - release_region(cfg[idx], 2); - snd_card_free(card); - return err; -#endif -} - -static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev) -{ - snd_msnd_unload(dev_get_drvdata(pdev)); - dev_set_drvdata(pdev, NULL); - return 0; -} - -#define DEV_NAME "msnd-pinnacle" - -static struct isa_driver snd_msnd_driver = { - .match = snd_msnd_isa_match, - .probe = snd_msnd_isa_probe, - .remove = __devexit_p(snd_msnd_isa_remove), - /* FIXME: suspend, resume */ - .driver = { - .name = DEV_NAME - }, -}; - -#ifdef CONFIG_PNP -static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int idx; - struct pnp_dev *pnp_dev; - struct pnp_dev *mpu_dev; - struct snd_card *card; - struct snd_msnd *chip; - int ret; - - for ( ; idx < SNDRV_CARDS; idx++) { - if (has_isapnp(idx)) - break; - } - if (idx >= SNDRV_CARDS) - return -ENODEV; - - /* - * Check that we still have room for another sound card ... - */ - pnp_dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); - if (!pnp_dev) - return -ENODEV; - - mpu_dev = pnp_request_card_device(pcard, pid->devs[1].id, NULL); - if (!mpu_dev) - return -ENODEV; - - if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) { - printk(KERN_INFO "msnd_pinnacle: device is inactive\n"); - return -EBUSY; - } - - if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) { - printk(KERN_INFO "msnd_pinnacle: MPU device is inactive\n"); - return -EBUSY; - } - - /* - * Create a new ALSA sound card entry, in anticipation - * of detecting our hardware ... - */ - ret = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct snd_msnd), &card); - if (ret < 0) - return ret; - - chip = card->private_data; - chip->card = card; - snd_card_set_dev(card, &pcard->card->dev); - - /* - * Read the correct parameters off the ISA PnP bus ... - */ - io[idx] = pnp_port_start(pnp_dev, 0); - irq[idx] = pnp_irq(pnp_dev, 0); - mem[idx] = pnp_mem_start(pnp_dev, 0); - mpu_io[idx] = pnp_port_start(mpu_dev, 0); - mpu_irq[idx] = pnp_irq(mpu_dev, 0); - - set_default_audio_parameters(chip); -#ifdef MSND_CLASSIC - chip->type = msndClassic; -#else - chip->type = msndPinnacle; -#endif - chip->io = io[idx]; - chip->irq = irq[idx]; - chip->base = mem[idx]; - - chip->calibrate_signal = calibrate_signal ? 1 : 0; - chip->recsrc = 0; - chip->dspq_data_buff = DSPQ_DATA_BUFF; - chip->dspq_buff_size = DSPQ_BUFF_SIZE; - if (write_ndelay[idx]) - clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); - else - set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); -#ifndef MSND_CLASSIC - if (digital[idx]) - set_bit(F_HAVEDIGITAL, &chip->flags); -#endif - spin_lock_init(&chip->lock); - ret = snd_msnd_probe(card); - if (ret < 0) { - printk(KERN_ERR LOGNAME ": Probe failed\n"); - goto _release_card; - } - - ret = snd_msnd_attach(card); - if (ret < 0) { - printk(KERN_ERR LOGNAME ": Attach failed\n"); - goto _release_card; - } - - pnp_set_card_drvdata(pcard, card); - ++idx; - return 0; - -_release_card: - snd_card_free(card); - return ret; -} - -static void __devexit snd_msnd_pnp_remove(struct pnp_card_link *pcard) -{ - snd_msnd_unload(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static int isa_registered; -static int pnp_registered; - -static struct pnp_card_device_id msnd_pnpids[] = { - /* Pinnacle PnP */ - { .id = "BVJ0440", .devs = { { "TBS0000" }, { "TBS0001" } } }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, msnd_pnpids); - -static struct pnp_card_driver msnd_pnpc_driver = { - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - .name = "msnd_pinnacle", - .id_table = msnd_pnpids, - .probe = snd_msnd_pnp_detect, - .remove = __devexit_p(snd_msnd_pnp_remove), -}; -#endif /* CONFIG_PNP */ - -static int __init snd_msnd_init(void) -{ - int err; - - err = isa_register_driver(&snd_msnd_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&msnd_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit snd_msnd_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&msnd_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_msnd_driver); -} - -module_init(snd_msnd_init); -module_exit(snd_msnd_exit); - diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.h b/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.h deleted file mode 100644 index 48318d1e..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.h +++ /dev/null @@ -1,181 +0,0 @@ -/********************************************************************* - * - * msnd_pinnacle.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_PINNACLE_H -#define __MSND_PINNACLE_H - -#define DSP_NUMIO 0x08 - -#define IREG_LOGDEVICE 0x07 -#define IREG_ACTIVATE 0x30 -#define LD_ACTIVATE 0x01 -#define LD_DISACTIVATE 0x00 -#define IREG_EECONTROL 0x3F -#define IREG_MEMBASEHI 0x40 -#define IREG_MEMBASELO 0x41 -#define IREG_MEMCONTROL 0x42 -#define IREG_MEMRANGEHI 0x43 -#define IREG_MEMRANGELO 0x44 -#define MEMTYPE_8BIT 0x00 -#define MEMTYPE_16BIT 0x02 -#define MEMTYPE_RANGE 0x00 -#define MEMTYPE_HIADDR 0x01 -#define IREG_IO0_BASEHI 0x60 -#define IREG_IO0_BASELO 0x61 -#define IREG_IO1_BASEHI 0x62 -#define IREG_IO1_BASELO 0x63 -#define IREG_IRQ_NUMBER 0x70 -#define IREG_IRQ_TYPE 0x71 -#define IRQTYPE_HIGH 0x02 -#define IRQTYPE_LOW 0x00 -#define IRQTYPE_LEVEL 0x01 -#define IRQTYPE_EDGE 0x00 - -#define HP_DSPR 0x04 -#define HP_BLKS 0x04 - -#define HPDSPRESET_OFF 2 -#define HPDSPRESET_ON 0 - -#define HPBLKSEL_0 2 -#define HPBLKSEL_1 3 - -#define HIMT_DAT_OFF 0x03 - -#define HIDSP_PLAY_UNDER 0x00 -#define HIDSP_INT_PLAY_UNDER 0x01 -#define HIDSP_SSI_TX_UNDER 0x02 -#define HIDSP_RECQ_OVERFLOW 0x08 -#define HIDSP_INT_RECORD_OVER 0x09 -#define HIDSP_SSI_RX_OVERFLOW 0x0a - -#define HIDSP_MIDI_IN_OVER 0x10 - -#define HIDSP_MIDI_FRAME_ERR 0x11 -#define HIDSP_MIDI_PARITY_ERR 0x12 -#define HIDSP_MIDI_OVERRUN_ERR 0x13 - -#define HIDSP_INPUT_CLIPPING 0x20 -#define HIDSP_MIX_CLIPPING 0x30 -#define HIDSP_DAT_IN_OFF 0x21 - -#define TIME_PRO_RESET_DONE 0x028A -#define TIME_PRO_SYSEX 0x001E -#define TIME_PRO_RESET 0x0032 - -#define DAR_BUFF_SIZE 0x1000 - -#define MIDQ_BUFF_SIZE 0x800 -#define DSPQ_BUFF_SIZE 0x5A0 - -#define DSPQ_DATA_BUFF 0x7860 - -#define MOP_WAVEHDR 0 -#define MOP_EXTOUT 1 -#define MOP_HWINIT 0xfe -#define MOP_NONE 0xff -#define MOP_MAX 1 - -#define MIP_EXTIN 0 -#define MIP_WAVEHDR 1 -#define MIP_HWINIT 0xfe -#define MIP_MAX 1 - -/* Pinnacle/Fiji SMA Common Data */ -#define SMA_wCurrPlayBytes 0x0000 -#define SMA_wCurrRecordBytes 0x0002 -#define SMA_wCurrPlayVolLeft 0x0004 -#define SMA_wCurrPlayVolRight 0x0006 -#define SMA_wCurrInVolLeft 0x0008 -#define SMA_wCurrInVolRight 0x000a -#define SMA_wCurrMHdrVolLeft 0x000c -#define SMA_wCurrMHdrVolRight 0x000e -#define SMA_dwCurrPlayPitch 0x0010 -#define SMA_dwCurrPlayRate 0x0014 -#define SMA_wCurrMIDIIOPatch 0x0018 -#define SMA_wCurrPlayFormat 0x001a -#define SMA_wCurrPlaySampleSize 0x001c -#define SMA_wCurrPlayChannels 0x001e -#define SMA_wCurrPlaySampleRate 0x0020 -#define SMA_wCurrRecordFormat 0x0022 -#define SMA_wCurrRecordSampleSize 0x0024 -#define SMA_wCurrRecordChannels 0x0026 -#define SMA_wCurrRecordSampleRate 0x0028 -#define SMA_wCurrDSPStatusFlags 0x002a -#define SMA_wCurrHostStatusFlags 0x002c -#define SMA_wCurrInputTagBits 0x002e -#define SMA_wCurrLeftPeak 0x0030 -#define SMA_wCurrRightPeak 0x0032 -#define SMA_bMicPotPosLeft 0x0034 -#define SMA_bMicPotPosRight 0x0035 -#define SMA_bMicPotMaxLeft 0x0036 -#define SMA_bMicPotMaxRight 0x0037 -#define SMA_bInPotPosLeft 0x0038 -#define SMA_bInPotPosRight 0x0039 -#define SMA_bAuxPotPosLeft 0x003a -#define SMA_bAuxPotPosRight 0x003b -#define SMA_bInPotMaxLeft 0x003c -#define SMA_bInPotMaxRight 0x003d -#define SMA_bAuxPotMaxLeft 0x003e -#define SMA_bAuxPotMaxRight 0x003f -#define SMA_bInPotMaxMethod 0x0040 -#define SMA_bAuxPotMaxMethod 0x0041 -#define SMA_wCurrMastVolLeft 0x0042 -#define SMA_wCurrMastVolRight 0x0044 -#define SMA_wCalFreqAtoD 0x0046 -#define SMA_wCurrAuxVolLeft 0x0048 -#define SMA_wCurrAuxVolRight 0x004a -#define SMA_wCurrPlay1VolLeft 0x004c -#define SMA_wCurrPlay1VolRight 0x004e -#define SMA_wCurrPlay2VolLeft 0x0050 -#define SMA_wCurrPlay2VolRight 0x0052 -#define SMA_wCurrPlay3VolLeft 0x0054 -#define SMA_wCurrPlay3VolRight 0x0056 -#define SMA_wCurrPlay4VolLeft 0x0058 -#define SMA_wCurrPlay4VolRight 0x005a -#define SMA_wCurrPlay1PeakLeft 0x005c -#define SMA_wCurrPlay1PeakRight 0x005e -#define SMA_wCurrPlay2PeakLeft 0x0060 -#define SMA_wCurrPlay2PeakRight 0x0062 -#define SMA_wCurrPlay3PeakLeft 0x0064 -#define SMA_wCurrPlay3PeakRight 0x0066 -#define SMA_wCurrPlay4PeakLeft 0x0068 -#define SMA_wCurrPlay4PeakRight 0x006a -#define SMA_wCurrPlayPeakLeft 0x006c -#define SMA_wCurrPlayPeakRight 0x006e -#define SMA_wCurrDATSR 0x0070 -#define SMA_wCurrDATRXCHNL 0x0072 -#define SMA_wCurrDATTXCHNL 0x0074 -#define SMA_wCurrDATRXRate 0x0076 -#define SMA_dwDSPPlayCount 0x0078 -#define SMA__size 0x007c - -#define INITCODEFILE "turtlebeach/pndspini.bin" -#define PERMCODEFILE "turtlebeach/pndsperm.bin" -#define LONGNAME "MultiSound (Pinnacle/Fiji)" - -#endif /* __MSND_PINNACLE_H */ diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle_mixer.c b/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle_mixer.c deleted file mode 100644 index 1de59d44..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle_mixer.c +++ /dev/null @@ -1,344 +0,0 @@ -/*************************************************************************** - msnd_pinnacle_mixer.c - description - ------------------- - begin : Fre Jun 7 2002 - copyright : (C) 2002 by karsten wiese - email : annabellesgarden@yahoo.de - ***************************************************************************/ - -/*************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ - -#include -#include - -#include -#include -#include "msnd.h" -#include "msnd_pinnacle.h" - - -#define MSND_MIXER_VOLUME 0 -#define MSND_MIXER_PCM 1 -#define MSND_MIXER_AUX 2 /* Input source 1 (aux1) */ -#define MSND_MIXER_IMIX 3 /* Recording monitor */ -#define MSND_MIXER_SYNTH 4 -#define MSND_MIXER_SPEAKER 5 -#define MSND_MIXER_LINE 6 -#define MSND_MIXER_MIC 7 -#define MSND_MIXER_RECLEV 11 /* Recording level */ -#define MSND_MIXER_IGAIN 12 /* Input gain */ -#define MSND_MIXER_OGAIN 13 /* Output gain */ -#define MSND_MIXER_DIGITAL 17 /* Digital (input) 1 */ - -/* Device mask bits */ - -#define MSND_MASK_VOLUME (1 << MSND_MIXER_VOLUME) -#define MSND_MASK_SYNTH (1 << MSND_MIXER_SYNTH) -#define MSND_MASK_PCM (1 << MSND_MIXER_PCM) -#define MSND_MASK_SPEAKER (1 << MSND_MIXER_SPEAKER) -#define MSND_MASK_LINE (1 << MSND_MIXER_LINE) -#define MSND_MASK_MIC (1 << MSND_MIXER_MIC) -#define MSND_MASK_IMIX (1 << MSND_MIXER_IMIX) -#define MSND_MASK_RECLEV (1 << MSND_MIXER_RECLEV) -#define MSND_MASK_IGAIN (1 << MSND_MIXER_IGAIN) -#define MSND_MASK_OGAIN (1 << MSND_MIXER_OGAIN) -#define MSND_MASK_AUX (1 << MSND_MIXER_AUX) -#define MSND_MASK_DIGITAL (1 << MSND_MIXER_DIGITAL) - -static int snd_msndmix_info_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { - "Analog", "MASS", "SPDIF", - }; - struct snd_msnd *chip = snd_kcontrol_chip(kcontrol); - unsigned items = test_bit(F_HAVEDIGITAL, &chip->flags) ? 3 : 2; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = items; - if (uinfo->value.enumerated.item >= items) - uinfo->value.enumerated.item = items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_msndmix_get_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_msnd *chip = snd_kcontrol_chip(kcontrol); - /* MSND_MASK_IMIX is the default */ - ucontrol->value.enumerated.item[0] = 0; - - if (chip->recsrc & MSND_MASK_SYNTH) { - ucontrol->value.enumerated.item[0] = 1; - } else if ((chip->recsrc & MSND_MASK_DIGITAL) && - test_bit(F_HAVEDIGITAL, &chip->flags)) { - ucontrol->value.enumerated.item[0] = 2; - } - - - return 0; -} - -static int snd_msndmix_set_mux(struct snd_msnd *chip, int val) -{ - unsigned newrecsrc; - int change; - unsigned char msndbyte; - - switch (val) { - case 0: - newrecsrc = MSND_MASK_IMIX; - msndbyte = HDEXAR_SET_ANA_IN; - break; - case 1: - newrecsrc = MSND_MASK_SYNTH; - msndbyte = HDEXAR_SET_SYNTH_IN; - break; - case 2: - newrecsrc = MSND_MASK_DIGITAL; - msndbyte = HDEXAR_SET_DAT_IN; - break; - default: - return -EINVAL; - } - change = newrecsrc != chip->recsrc; - if (change) { - change = 0; - if (!snd_msnd_send_word(chip, 0, 0, msndbyte)) - if (!snd_msnd_send_dsp_cmd(chip, HDEX_AUX_REQ)) { - chip->recsrc = newrecsrc; - change = 1; - } - } - return change; -} - -static int snd_msndmix_put_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); - return snd_msndmix_set_mux(msnd, ucontrol->value.enumerated.item[0]); -} - - -static int snd_msndmix_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_msndmix_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); - int addr = kcontrol->private_value; - unsigned long flags; - - spin_lock_irqsave(&msnd->mixer_lock, flags); - ucontrol->value.integer.value[0] = msnd->left_levels[addr] * 100; - ucontrol->value.integer.value[0] /= 0xFFFF; - ucontrol->value.integer.value[1] = msnd->right_levels[addr] * 100; - ucontrol->value.integer.value[1] /= 0xFFFF; - spin_unlock_irqrestore(&msnd->mixer_lock, flags); - return 0; -} - -#define update_volm(a, b) \ - do { \ - writew((dev->left_levels[a] >> 1) * \ - readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \ - dev->SMA + SMA_##b##Left); \ - writew((dev->right_levels[a] >> 1) * \ - readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \ - dev->SMA + SMA_##b##Right); \ - } while (0); - -#define update_potm(d, s, ar) \ - do { \ - writeb((dev->left_levels[d] >> 8) * \ - readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \ - dev->SMA + SMA_##s##Left); \ - writeb((dev->right_levels[d] >> 8) * \ - readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \ - dev->SMA + SMA_##s##Right); \ - if (snd_msnd_send_word(dev, 0, 0, ar) == 0) \ - snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); \ - } while (0); - -#define update_pot(d, s, ar) \ - do { \ - writeb(dev->left_levels[d] >> 8, \ - dev->SMA + SMA_##s##Left); \ - writeb(dev->right_levels[d] >> 8, \ - dev->SMA + SMA_##s##Right); \ - if (snd_msnd_send_word(dev, 0, 0, ar) == 0) \ - snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); \ - } while (0); - - -static int snd_msndmix_set(struct snd_msnd *dev, int d, int left, int right) -{ - int bLeft, bRight; - int wLeft, wRight; - int updatemaster = 0; - - if (d >= LEVEL_ENTRIES) - return -EINVAL; - - bLeft = left * 0xff / 100; - wLeft = left * 0xffff / 100; - - bRight = right * 0xff / 100; - wRight = right * 0xffff / 100; - - dev->left_levels[d] = wLeft; - dev->right_levels[d] = wRight; - - switch (d) { - /* master volume unscaled controls */ - case MSND_MIXER_LINE: /* line pot control */ - /* scaled by IMIX in digital mix */ - writeb(bLeft, dev->SMA + SMA_bInPotPosLeft); - writeb(bRight, dev->SMA + SMA_bInPotPosRight); - if (snd_msnd_send_word(dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) - snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); - break; - case MSND_MIXER_MIC: /* mic pot control */ - if (dev->type == msndClassic) - return -EINVAL; - /* scaled by IMIX in digital mix */ - writeb(bLeft, dev->SMA + SMA_bMicPotPosLeft); - writeb(bRight, dev->SMA + SMA_bMicPotPosRight); - if (snd_msnd_send_word(dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0) - snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); - break; - case MSND_MIXER_VOLUME: /* master volume */ - writew(wLeft, dev->SMA + SMA_wCurrMastVolLeft); - writew(wRight, dev->SMA + SMA_wCurrMastVolRight); - /* fall through */ - - case MSND_MIXER_AUX: /* aux pot control */ - /* scaled by master volume */ - /* fall through */ - - /* digital controls */ - case MSND_MIXER_SYNTH: /* synth vol (dsp mix) */ - case MSND_MIXER_PCM: /* pcm vol (dsp mix) */ - case MSND_MIXER_IMIX: /* input monitor (dsp mix) */ - /* scaled by master volume */ - updatemaster = 1; - break; - - default: - return -EINVAL; - } - - if (updatemaster) { - /* update master volume scaled controls */ - update_volm(MSND_MIXER_PCM, wCurrPlayVol); - update_volm(MSND_MIXER_IMIX, wCurrInVol); - if (dev->type == msndPinnacle) - update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); - update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); - } - - return 0; -} - -static int snd_msndmix_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); - int change, addr = kcontrol->private_value; - int left, right; - unsigned long flags; - - left = ucontrol->value.integer.value[0] % 101; - right = ucontrol->value.integer.value[1] % 101; - spin_lock_irqsave(&msnd->mixer_lock, flags); - change = msnd->left_levels[addr] != left - || msnd->right_levels[addr] != right; - snd_msndmix_set(msnd, addr, left, right); - spin_unlock_irqrestore(&msnd->mixer_lock, flags); - return change; -} - - -#define DUMMY_VOLUME(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_msndmix_volume_info, \ - .get = snd_msndmix_volume_get, .put = snd_msndmix_volume_put, \ - .private_value = addr } - - -static struct snd_kcontrol_new snd_msnd_controls[] = { -DUMMY_VOLUME("Master Volume", 0, MSND_MIXER_VOLUME), -DUMMY_VOLUME("PCM Volume", 0, MSND_MIXER_PCM), -DUMMY_VOLUME("Aux Volume", 0, MSND_MIXER_AUX), -DUMMY_VOLUME("Line Volume", 0, MSND_MIXER_LINE), -DUMMY_VOLUME("Mic Volume", 0, MSND_MIXER_MIC), -DUMMY_VOLUME("Monitor", 0, MSND_MIXER_IMIX), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_msndmix_info_mux, - .get = snd_msndmix_get_mux, - .put = snd_msndmix_put_mux, -} -}; - - -int __devinit snd_msndmix_new(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - unsigned int idx; - int err; - - if (snd_BUG_ON(!chip)) - return -EINVAL; - spin_lock_init(&chip->mixer_lock); - strcpy(card->mixername, "MSND Pinnacle Mixer"); - - for (idx = 0; idx < ARRAY_SIZE(snd_msnd_controls); idx++) - err = snd_ctl_add(card, - snd_ctl_new1(snd_msnd_controls + idx, chip)); - if (err < 0) - return err; - - return 0; -} -EXPORT_SYMBOL(snd_msndmix_new); - -void snd_msndmix_setup(struct snd_msnd *dev) -{ - update_pot(MSND_MIXER_LINE, bInPotPos, HDEXAR_IN_SET_POTS); - update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); - update_volm(MSND_MIXER_PCM, wCurrPlayVol); - update_volm(MSND_MIXER_IMIX, wCurrInVol); - if (dev->type == msndPinnacle) { - update_pot(MSND_MIXER_MIC, bMicPotPos, HDEXAR_MIC_SET_POTS); - update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); - } -} -EXPORT_SYMBOL(snd_msndmix_setup); - -int snd_msndmix_force_recsrc(struct snd_msnd *dev, int recsrc) -{ - dev->recsrc = -1; - return snd_msndmix_set_mux(dev, recsrc); -} -EXPORT_SYMBOL(snd_msndmix_force_recsrc); diff --git a/ANDROID_3.4.5/sound/isa/opl3sa2.c b/ANDROID_3.4.5/sound/isa/opl3sa2.c deleted file mode 100644 index f6cc0b91..00000000 --- a/ANDROID_3.4.5/sound/isa/opl3sa2.c +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Driver for Yamaha OPL3-SA[2,3] soundcards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#include - -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Yamaha OPL3SA2+"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S}," - "{Genius,Sound Maker 3DX}," - "{Yamaha,OPL3SA3}," - "{Intel,AL440LX sound}," - "{NeoMagic,MagicWave 3DX}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0xf86,0x370,0x100 */ -static long sb_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ -static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x530,0xe80,0xf40,0x604 */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x388 */ -static long midi_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x330,0x300 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 0,1,3,5,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int opl3sa3_ymode[SNDRV_CARDS]; /* 0,1,2,3 */ /*SL Added*/ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for OPL3-SA soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable OPL3-SA soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for OPL3-SA driver."); -module_param_array(sb_port, long, NULL, 0444); -MODULE_PARM_DESC(sb_port, "SB port # for OPL3-SA driver."); -module_param_array(wss_port, long, NULL, 0444); -MODULE_PARM_DESC(wss_port, "WSS port # for OPL3-SA driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for OPL3-SA driver."); -module_param_array(midi_port, long, NULL, 0444); -MODULE_PARM_DESC(midi_port, "MIDI port # for OPL3-SA driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for OPL3-SA driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for OPL3-SA driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver."); -module_param_array(opl3sa3_ymode, int, NULL, 0444); -MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi."); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -static int pnpc_registered; -#endif - -/* control ports */ -#define OPL3SA2_PM_CTRL 0x01 -#define OPL3SA2_SYS_CTRL 0x02 -#define OPL3SA2_IRQ_CONFIG 0x03 -#define OPL3SA2_IRQ_STATUS 0x04 -#define OPL3SA2_DMA_CONFIG 0x06 -#define OPL3SA2_MASTER_LEFT 0x07 -#define OPL3SA2_MASTER_RIGHT 0x08 -#define OPL3SA2_MIC 0x09 -#define OPL3SA2_MISC 0x0A - -/* opl3sa3 only */ -#define OPL3SA3_DGTL_DOWN 0x12 -#define OPL3SA3_ANLG_DOWN 0x13 -#define OPL3SA3_WIDE 0x14 -#define OPL3SA3_BASS 0x15 -#define OPL3SA3_TREBLE 0x16 - -/* power management bits */ -#define OPL3SA2_PM_ADOWN 0x20 -#define OPL3SA2_PM_PSV 0x04 -#define OPL3SA2_PM_PDN 0x02 -#define OPL3SA2_PM_PDX 0x01 - -#define OPL3SA2_PM_D0 0x00 -#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX) - -struct snd_opl3sa2 { - int version; /* 2 or 3 */ - unsigned long port; /* control port */ - struct resource *res_port; /* control port resource */ - int irq; - int single_dma; - spinlock_t reg_lock; - struct snd_hwdep *synth; - struct snd_rawmidi *rmidi; - struct snd_wss *wss; - unsigned char ctlregs[0x20]; - int ymode; /* SL added */ - struct snd_kcontrol *master_switch; - struct snd_kcontrol *master_volume; -}; - -#define PFX "opl3sa2: " - -#ifdef CONFIG_PNP - -static struct pnp_device_id snd_opl3sa2_pnpbiosids[] = { - { .id = "YMH0021" }, - { .id = "NMX2210" }, /* Gateway Solo 2500 */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp, snd_opl3sa2_pnpbiosids); - -static struct pnp_card_device_id snd_opl3sa2_pnpids[] = { - /* Yamaha YMF719E-S (Genius Sound Maker 3DX) */ - { .id = "YMH0020", .devs = { { "YMH0021" } } }, - /* Yamaha OPL3-SA3 (integrated on Intel's Pentium II AL440LX motherboard) */ - { .id = "YMH0030", .devs = { { "YMH0021" } } }, - /* Yamaha OPL3-SA2 */ - { .id = "YMH0800", .devs = { { "YMH0021" } } }, - /* Yamaha OPL3-SA2 */ - { .id = "YMH0801", .devs = { { "YMH0021" } } }, - /* NeoMagic MagicWave 3DX */ - { .id = "NMX2200", .devs = { { "YMH2210" } } }, - /* NeoMagic MagicWave 3D */ - { .id = "NMX2200", .devs = { { "NMX2210" } } }, - /* --- */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_opl3sa2_pnpids); - -#endif /* CONFIG_PNP */ - - -/* read control port (w/o spinlock) */ -static unsigned char __snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char reg) -{ - unsigned char result; -#if 0 - outb(0x1d, port); /* password */ - printk(KERN_DEBUG "read [0x%lx] = 0x%x\n", port, inb(port)); -#endif - outb(reg, chip->port); /* register */ - result = inb(chip->port + 1); -#if 0 - printk(KERN_DEBUG "read [0x%lx] = 0x%x [0x%x]\n", - port, result, inb(port)); -#endif - return result; -} - -/* read control port (with spinlock) */ -static unsigned char snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char reg) -{ - unsigned long flags; - unsigned char result; - - spin_lock_irqsave(&chip->reg_lock, flags); - result = __snd_opl3sa2_read(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return result; -} - -/* write control port (w/o spinlock) */ -static void __snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsigned char value) -{ -#if 0 - outb(0x1d, port); /* password */ -#endif - outb(reg, chip->port); /* register */ - outb(value, chip->port + 1); - chip->ctlregs[reg] = value; -} - -/* write control port (with spinlock) */ -static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsigned char value) -{ - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - __snd_opl3sa2_write(chip, reg, value); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static int __devinit snd_opl3sa2_detect(struct snd_card *card) -{ - struct snd_opl3sa2 *chip = card->private_data; - unsigned long port; - unsigned char tmp, tmp1; - char str[2]; - - port = chip->port; - if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) { - snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); - return -EBUSY; - } - /* - snd_printk(KERN_DEBUG "REG 0A = 0x%x\n", - snd_opl3sa2_read(chip, 0x0a)); - */ - chip->version = 0; - tmp = snd_opl3sa2_read(chip, OPL3SA2_MISC); - if (tmp == 0xff) { - snd_printd("OPL3-SA [0x%lx] detect = 0x%x\n", port, tmp); - return -ENODEV; - } - switch (tmp & 0x07) { - case 0x01: - chip->version = 2; /* YMF711 */ - break; - default: - chip->version = 3; - /* 0x02 - standard */ - /* 0x03 - YM715B */ - /* 0x04 - YM719 - OPL-SA4? */ - /* 0x05 - OPL3-SA3 - Libretto 100 */ - /* 0x07 - unknown - Neomagic MagicWave 3D */ - break; - } - str[0] = chip->version + '0'; - str[1] = 0; - strcat(card->shortname, str); - snd_opl3sa2_write(chip, OPL3SA2_MISC, tmp ^ 7); - if ((tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MISC)) != tmp) { - snd_printd("OPL3-SA [0x%lx] detect (1) = 0x%x (0x%x)\n", port, tmp, tmp1); - return -ENODEV; - } - /* try if the MIC register is accessible */ - tmp = snd_opl3sa2_read(chip, OPL3SA2_MIC); - snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x8a); - if (((tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MIC)) & 0x9f) != 0x8a) { - snd_printd("OPL3-SA [0x%lx] detect (2) = 0x%x (0x%x)\n", port, tmp, tmp1); - return -ENODEV; - } - snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x9f); - /* initialization */ - /* Power Management - full on */ - snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D0); - if (chip->version > 2) { - /* ymode is bits 4&5 (of 0 to 7) on all but opl3sa2 versions */ - snd_opl3sa2_write(chip, OPL3SA2_SYS_CTRL, (chip->ymode << 4)); - } else { - /* default for opl3sa2 versions */ - snd_opl3sa2_write(chip, OPL3SA2_SYS_CTRL, 0x00); - } - snd_opl3sa2_write(chip, OPL3SA2_IRQ_CONFIG, 0x0d); /* Interrupt Channel Configuration - IRQ A = OPL3 + MPU + WSS */ - if (chip->single_dma) { - snd_opl3sa2_write(chip, OPL3SA2_DMA_CONFIG, 0x03); /* DMA Configuration - DMA A = WSS-R + WSS-P */ - } else { - snd_opl3sa2_write(chip, OPL3SA2_DMA_CONFIG, 0x21); /* DMA Configuration - DMA B = WSS-R, DMA A = WSS-P */ - } - snd_opl3sa2_write(chip, OPL3SA2_MISC, 0x80 | (tmp & 7)); /* Miscellaneous - default */ - if (chip->version > 2) { - snd_opl3sa2_write(chip, OPL3SA3_DGTL_DOWN, 0x00); /* Digital Block Partial Power Down - default */ - snd_opl3sa2_write(chip, OPL3SA3_ANLG_DOWN, 0x00); /* Analog Block Partial Power Down - default */ - } - return 0; -} - -static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id) -{ - unsigned short status; - struct snd_card *card = dev_id; - struct snd_opl3sa2 *chip; - int handled = 0; - - if (card == NULL) - return IRQ_NONE; - - chip = card->private_data; - status = snd_opl3sa2_read(chip, OPL3SA2_IRQ_STATUS); - - if (status & 0x20) { - handled = 1; - snd_opl3_interrupt(chip->synth); - } - - if ((status & 0x10) && chip->rmidi != NULL) { - handled = 1; - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - } - - if (status & 0x07) { /* TI,CI,PI */ - handled = 1; - snd_wss_interrupt(irq, chip->wss); - } - - if (status & 0x40) { /* hardware volume change */ - handled = 1; - /* reading from Master Lch register at 0x07 clears this bit */ - snd_opl3sa2_read(chip, OPL3SA2_MASTER_RIGHT); - snd_opl3sa2_read(chip, OPL3SA2_MASTER_LEFT); - if (chip->master_switch && chip->master_volume) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_switch->id); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); - } - } - return IRQ_RETVAL(handled); -} - -#define OPL3SA2_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_wss_info_single, \ - .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } -#define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_wss_info_single, \ - .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - -static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->ctlregs[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val, oval; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = chip->ctlregs[reg]; - val = (oval & ~(mask << shift)) | val; - change = val != oval; - __snd_opl3sa2_write(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define OPL3SA2_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_wss_info_double, \ - .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } -#define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_wss_info_double, \ - .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->ctlregs[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->ctlregs[right_reg] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2, oval1, oval2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - oval1 = chip->ctlregs[left_reg]; - oval2 = chip->ctlregs[right_reg]; - val1 = (oval1 & ~(mask << shift_left)) | val1; - val2 = (oval2 & ~(mask << shift_right)) | val2; - change = val1 != oval1 || val2 != oval2; - __snd_opl3sa2_write(chip, left_reg, val1); - __snd_opl3sa2_write(chip, right_reg, val2); - } else { - oval1 = chip->ctlregs[left_reg]; - val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != oval1; - __snd_opl3sa2_write(chip, left_reg, val1); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); - -static struct snd_kcontrol_new snd_opl3sa2_controls[] = { -OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1), -OPL3SA2_DOUBLE_TLV("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1, - db_scale_master), -OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1), -OPL3SA2_SINGLE_TLV("Mic Playback Volume", 0, 0x09, 0, 31, 1, - db_scale_5bit_12db_max), -OPL3SA2_SINGLE("ZV Port Switch", 0, 0x02, 0, 1, 0), -}; - -static struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = { -OPL3SA2_DOUBLE("3D Control - Wide", 0, 0x14, 0x14, 4, 0, 7, 0), -OPL3SA2_DOUBLE("Tone Control - Bass", 0, 0x15, 0x15, 4, 0, 7, 0), -OPL3SA2_DOUBLE("Tone Control - Treble", 0, 0x16, 0x16, 4, 0, 7, 0) -}; - -static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - chip->master_switch = NULL; - chip->master_volume = NULL; -} - -static int __devinit snd_opl3sa2_mixer(struct snd_card *card) -{ - struct snd_opl3sa2 *chip = card->private_data; - struct snd_ctl_elem_id id1, id2; - struct snd_kcontrol *kctl; - unsigned int idx; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUX0 to CD */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); - return err; - } - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); - return err; - } - /* reassign AUX1 to FM */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "FM Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); - return err; - } - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "FM Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); - return err; - } - /* add OPL3SA2 controls */ - for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip))) < 0) - return err; - switch (idx) { - case 0: chip->master_switch = kctl; kctl->private_free = snd_opl3sa2_master_free; break; - case 1: chip->master_volume = kctl; kctl->private_free = snd_opl3sa2_master_free; break; - } - } - if (chip->version > 2) { - for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_tone_controls); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opl3sa2_tone_controls[idx], chip))) < 0) - return err; - } - return 0; -} - -/* Power Management support functions */ -#ifdef CONFIG_PM -static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state) -{ - if (card) { - struct snd_opl3sa2 *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->wss->suspend(chip->wss); - /* power down */ - snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); - } - - return 0; -} - -static int snd_opl3sa2_resume(struct snd_card *card) -{ - struct snd_opl3sa2 *chip; - int i; - - if (!card) - return 0; - - chip = card->private_data; - /* power up */ - snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D0); - - /* restore registers */ - for (i = 2; i <= 0x0a; i++) { - if (i != OPL3SA2_IRQ_STATUS) - snd_opl3sa2_write(chip, i, chip->ctlregs[i]); - } - if (chip->version > 2) { - for (i = 0x12; i <= 0x16; i++) - snd_opl3sa2_write(chip, i, chip->ctlregs[i]); - } - /* restore wss */ - chip->wss->resume(chip->wss); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -#ifdef CONFIG_PNP -static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, - struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - snd_printk(KERN_ERR "PnP configure failure (out of resources?)\n"); - return -EBUSY; - } - sb_port[dev] = pnp_port_start(pdev, 0); - wss_port[dev] = pnp_port_start(pdev, 1); - fm_port[dev] = pnp_port_start(pdev, 2); - midi_port[dev] = pnp_port_start(pdev, 3); - port[dev] = pnp_port_start(pdev, 4); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("%sPnP OPL3-SA: sb port=0x%lx, wss port=0x%lx, fm port=0x%lx, midi port=0x%lx\n", - pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", sb_port[dev], wss_port[dev], fm_port[dev], midi_port[dev]); - snd_printdd("%sPnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n", - pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", port[dev], dma1[dev], dma2[dev], irq[dev]); - return 0; -} -#endif /* CONFIG_PNP */ - -static void snd_opl3sa2_free(struct snd_card *card) -{ - struct snd_opl3sa2 *chip = card->private_data; - if (chip->irq >= 0) - free_irq(chip->irq, card); - release_and_free_resource(chip->res_port); -} - -static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - struct snd_opl3sa2 *chip; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_opl3sa2), &card); - if (err < 0) - return err; - strcpy(card->driver, "OPL3SA2"); - strcpy(card->shortname, "Yamaha OPL3-SA"); - chip = card->private_data; - spin_lock_init(&chip->reg_lock); - chip->irq = -1; - card->private_free = snd_opl3sa2_free; - *cardp = card; - return 0; -} - -static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) -{ - int xirq, xdma1, xdma2; - struct snd_opl3sa2 *chip; - struct snd_wss *wss; - struct snd_opl3 *opl3; - int err; - - /* initialise this card from supplied (or default) parameter*/ - chip = card->private_data; - chip->ymode = opl3sa3_ymode[dev] & 0x03 ; - chip->port = port[dev]; - xirq = irq[dev]; - xdma1 = dma1[dev]; - xdma2 = dma2[dev]; - if (xdma2 < 0) - chip->single_dma = 1; - err = snd_opl3sa2_detect(card); - if (err < 0) - return err; - err = request_irq(xirq, snd_opl3sa2_interrupt, 0, - "OPL3-SA2", card); - if (err) { - snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); - return -ENODEV; - } - chip->irq = xirq; - err = snd_wss_create(card, - wss_port[dev] + 4, -1, - xirq, xdma1, xdma2, - WSS_HW_OPL3SA2, WSS_HWSHARE_IRQ, &wss); - if (err < 0) { - snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); - return err; - } - chip->wss = wss; - err = snd_wss_pcm(wss, 0, NULL); - if (err < 0) - return err; - err = snd_wss_mixer(wss); - if (err < 0) - return err; - err = snd_opl3sa2_mixer(card); - if (err < 0) - return err; - err = snd_wss_timer(wss, 0, NULL); - if (err < 0) - return err; - if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { - if ((err = snd_opl3_create(card, fm_port[dev], - fm_port[dev] + 2, - OPL3_HW_OPL3, 0, &opl3)) < 0) - return err; - if ((err = snd_opl3_timer_new(opl3, 1, 2)) < 0) - return err; - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, &chip->synth)) < 0) - return err; - } - if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2, - midi_port[dev], - MPU401_INFO_IRQ_HOOK, -1, - &chip->rmidi)) < 0) - return err; - } - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - card->shortname, chip->port, xirq, xdma1); - if (xdma2 >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", xdma2); - - return snd_card_register(card); -} - -#ifdef CONFIG_PNP -static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, - const struct pnp_device_id *id) -{ - static int dev; - int err; - struct snd_card *card; - - if (pnp_device_is_isapnp(pdev)) - return -ENOENT; /* we have another procedure - card */ - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - err = snd_opl3sa2_card_new(dev, &card); - if (err < 0) - return err; - if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_drvdata(pdev, card); - dev++; - return 0; -} - -static void __devexit snd_opl3sa2_pnp_remove(struct pnp_dev * pdev) -{ - snd_card_free(pnp_get_drvdata(pdev)); - pnp_set_drvdata(pdev, NULL); -} - -#ifdef CONFIG_PM -static int snd_opl3sa2_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - return snd_opl3sa2_suspend(pnp_get_drvdata(pdev), state); -} -static int snd_opl3sa2_pnp_resume(struct pnp_dev *pdev) -{ - return snd_opl3sa2_resume(pnp_get_drvdata(pdev)); -} -#endif - -static struct pnp_driver opl3sa2_pnp_driver = { - .name = "snd-opl3sa2-pnpbios", - .id_table = snd_opl3sa2_pnpbiosids, - .probe = snd_opl3sa2_pnp_detect, - .remove = __devexit_p(snd_opl3sa2_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_opl3sa2_pnp_suspend, - .resume = snd_opl3sa2_pnp_resume, -#endif -}; - -static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *id) -{ - static int dev; - struct pnp_dev *pdev; - int err; - struct snd_card *card; - - pdev = pnp_request_card_device(pcard, id->devs[0].id, NULL); - if (pdev == NULL) { - snd_printk(KERN_ERR PFX "can't get pnp device from id '%s'\n", - id->devs[0].id); - return -EBUSY; - } - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - err = snd_opl3sa2_card_new(dev, &card); - if (err < 0) - return err; - if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_opl3sa2_pnp_csuspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_opl3sa2_suspend(pnp_get_card_drvdata(pcard), state); -} -static int snd_opl3sa2_pnp_cresume(struct pnp_card_link *pcard) -{ - return snd_opl3sa2_resume(pnp_get_card_drvdata(pcard)); -} -#endif - -static struct pnp_card_driver opl3sa2_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "snd-opl3sa2-cpnp", - .id_table = snd_opl3sa2_pnpids, - .probe = snd_opl3sa2_pnp_cdetect, - .remove = __devexit_p(snd_opl3sa2_pnp_cremove), -#ifdef CONFIG_PM - .suspend = snd_opl3sa2_pnp_csuspend, - .resume = snd_opl3sa2_pnp_cresume, -#endif -}; -#endif /* CONFIG_PNP */ - -static int __devinit snd_opl3sa2_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev]) - return 0; -#ifdef CONFIG_PNP - if (isapnp[dev]) - return 0; -#endif - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify port\n"); - return 0; - } - if (wss_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify wss_port\n"); - return 0; - } - if (fm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify fm_port\n"); - return 0; - } - if (midi_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify midi_port\n"); - return 0; - } - return 1; -} - -static int __devinit snd_opl3sa2_isa_probe(struct device *pdev, - unsigned int dev) -{ - struct snd_card *card; - int err; - - err = snd_opl3sa2_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, pdev); - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_opl3sa2_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_opl3sa2_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_opl3sa2_suspend(dev_get_drvdata(dev), state); -} - -static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n) -{ - return snd_opl3sa2_resume(dev_get_drvdata(dev)); -} -#endif - -#define DEV_NAME "opl3sa2" - -static struct isa_driver snd_opl3sa2_isa_driver = { - .match = snd_opl3sa2_isa_match, - .probe = snd_opl3sa2_isa_probe, - .remove = __devexit_p(snd_opl3sa2_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_opl3sa2_isa_suspend, - .resume = snd_opl3sa2_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - -static int __init alsa_card_opl3sa2_init(void) -{ - int err; - - err = isa_register_driver(&snd_opl3sa2_isa_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_driver(&opl3sa2_pnp_driver); - if (!err) - pnp_registered = 1; - - err = pnp_register_card_driver(&opl3sa2_pnpc_driver); - if (!err) - pnpc_registered = 1; - - if (isa_registered || pnp_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_opl3sa2_exit(void) -{ -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&opl3sa2_pnpc_driver); - if (pnp_registered) - pnp_unregister_driver(&opl3sa2_pnp_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_opl3sa2_isa_driver); -} - -module_init(alsa_card_opl3sa2_init) -module_exit(alsa_card_opl3sa2_exit) diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/Makefile b/ANDROID_3.4.5/sound/isa/opti9xx/Makefile deleted file mode 100644 index b4d894db..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-opti92x-ad1848-objs := opti92x-ad1848.o -snd-opti92x-cs4231-objs := opti92x-cs4231.o -snd-opti93x-objs := opti93x.o -snd-miro-objs := miro.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o -obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o -obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o -obj-$(CONFIG_SND_MIRO) += snd-miro.o diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/miro.c b/ANDROID_3.4.5/sound/isa/opti9xx/miro.c deleted file mode 100644 index c24594c8..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/miro.c +++ /dev/null @@ -1,1680 +0,0 @@ -/* - * ALSA soundcard driver for Miro miroSOUND PCM1 pro - * miroSOUND PCM12 - * miroSOUND PCM20 Radio - * - * Copyright (C) 2004-2005 Martin Langer - * - * Based on OSS ACI and ALSA OPTi9xx drivers - * - * 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 -#include -#include -#include -#include -#include -#include -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include -#include - -MODULE_AUTHOR("Martin Langer "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Miro miroSOUND PCM1 pro, PCM12, PCM20 Radio"); -MODULE_SUPPORTED_DEVICE("{{Miro,miroSOUND PCM1 pro}, " - "{Miro,miroSOUND PCM12}, " - "{Miro,miroSOUND PCM20 Radio}}"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */ -static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */ -static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */ -static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */ -static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */ -static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ -static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ -static int wss; -static int ide; -#ifdef CONFIG_PNP -static bool isapnp = 1; /* Enable ISA PnP detection */ -#endif - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for miro soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for miro soundcard."); -module_param(port, long, 0444); -MODULE_PARM_DESC(port, "WSS port # for miro driver."); -module_param(mpu_port, long, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver."); -module_param(fm_port, long, 0444); -MODULE_PARM_DESC(fm_port, "FM Port # for miro driver."); -module_param(irq, int, 0444); -MODULE_PARM_DESC(irq, "WSS irq # for miro driver."); -module_param(mpu_irq, int, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver."); -module_param(dma1, int, 0444); -MODULE_PARM_DESC(dma1, "1st dma # for miro driver."); -module_param(dma2, int, 0444); -MODULE_PARM_DESC(dma2, "2nd dma # for miro driver."); -module_param(wss, int, 0444); -MODULE_PARM_DESC(wss, "wss mode"); -module_param(ide, int, 0444); -MODULE_PARM_DESC(ide, "enable ide port"); -#ifdef CONFIG_PNP -module_param(isapnp, bool, 0444); -MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard."); -#endif - -#define OPTi9XX_HW_DETECT 0 -#define OPTi9XX_HW_82C928 1 -#define OPTi9XX_HW_82C929 2 -#define OPTi9XX_HW_82C924 3 -#define OPTi9XX_HW_82C925 4 -#define OPTi9XX_HW_82C930 5 -#define OPTi9XX_HW_82C931 6 -#define OPTi9XX_HW_82C933 7 -#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933 - -#define OPTi9XX_MC_REG(n) n - -struct snd_miro { - unsigned short hardware; - unsigned char password; - char name[7]; - - struct resource *res_mc_base; - struct resource *res_aci_port; - - unsigned long mc_base; - unsigned long mc_base_size; - unsigned long pwd_reg; - - spinlock_t lock; - struct snd_pcm *pcm; - - long wss_base; - int irq; - int dma1; - int dma2; - - long mpu_port; - int mpu_irq; - - struct snd_miro_aci *aci; -}; - -static struct snd_miro_aci aci_device; - -static char * snd_opti9xx_names[] = { - "unknown", - "82C928", "82C929", - "82C924", "82C925", - "82C930", "82C931", "82C933" -}; - -static int snd_miro_pnp_is_probed; - -#ifdef CONFIG_PNP - -static struct pnp_card_device_id snd_miro_pnpids[] = { - /* PCM20 and PCM12 in PnP mode */ - { .id = "MIR0924", - .devs = { { "MIR0000" }, { "MIR0002" }, { "MIR0005" } }, }, - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_miro_pnpids); - -#endif /* CONFIG_PNP */ - -/* - * ACI control - */ - -static int aci_busy_wait(struct snd_miro_aci *aci) -{ - long timeout; - unsigned char byte; - - for (timeout = 1; timeout <= ACI_MINTIME + 30; timeout++) { - byte = inb(aci->aci_port + ACI_REG_BUSY); - if ((byte & 1) == 0) { - if (timeout >= ACI_MINTIME) - snd_printd("aci ready in round %ld.\n", - timeout-ACI_MINTIME); - return byte; - } - if (timeout >= ACI_MINTIME) { - long out=10*HZ; - switch (timeout-ACI_MINTIME) { - case 0 ... 9: - out /= 10; - case 10 ... 19: - out /= 10; - case 20 ... 30: - out /= 10; - default: - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(out); - break; - } - } - } - snd_printk(KERN_ERR "aci_busy_wait() time out\n"); - return -EBUSY; -} - -static inline int aci_write(struct snd_miro_aci *aci, unsigned char byte) -{ - if (aci_busy_wait(aci) >= 0) { - outb(byte, aci->aci_port + ACI_REG_COMMAND); - return 0; - } else { - snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte); - return -EBUSY; - } -} - -static inline int aci_read(struct snd_miro_aci *aci) -{ - unsigned char byte; - - if (aci_busy_wait(aci) >= 0) { - byte = inb(aci->aci_port + ACI_REG_STATUS); - return byte; - } else { - snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n"); - return -EBUSY; - } -} - -int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3) -{ - int write[] = {write1, write2, write3}; - int value, i; - - if (mutex_lock_interruptible(&aci->aci_mutex)) - return -EINTR; - - for (i=0; i<3; i++) { - if (write[i]< 0 || write[i] > 255) - break; - else { - value = aci_write(aci, write[i]); - if (value < 0) - goto out; - } - } - - value = aci_read(aci); - -out: mutex_unlock(&aci->aci_mutex); - return value; -} -EXPORT_SYMBOL(snd_aci_cmd); - -static int aci_getvalue(struct snd_miro_aci *aci, unsigned char index) -{ - return snd_aci_cmd(aci, ACI_STATUS, index, -1); -} - -static int aci_setvalue(struct snd_miro_aci *aci, unsigned char index, - int value) -{ - return snd_aci_cmd(aci, index, value, -1); -} - -struct snd_miro_aci *snd_aci_get_aci(void) -{ - if (aci_device.aci_port == 0) - return NULL; - return &aci_device; -} -EXPORT_SYMBOL(snd_aci_get_aci); - -/* - * MIXER part - */ - -#define snd_miro_info_capture snd_ctl_boolean_mono_info - -static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int value; - - value = aci_getvalue(miro->aci, ACI_S_GENERAL); - if (value < 0) { - snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", - value); - return value; - } - - ucontrol->value.integer.value[0] = value & 0x20; - - return 0; -} - -static int snd_miro_put_capture(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int change, value, error; - - value = !(ucontrol->value.integer.value[0]); - - error = aci_setvalue(miro->aci, ACI_SET_SOLOMODE, value); - if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", - error); - return error; - } - - change = (value != miro->aci->aci_solomode); - miro->aci->aci_solomode = value; - - return change; -} - -static int snd_miro_info_preamp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 3; - - return 0; -} - -static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int value; - - if (miro->aci->aci_version <= 176) { - - /* - OSS says it's not readable with versions < 176. - But it doesn't work on my card, - which is a PCM12 with aci_version = 176. - */ - - ucontrol->value.integer.value[0] = miro->aci->aci_preamp; - return 0; - } - - value = aci_getvalue(miro->aci, ACI_GET_PREAMP); - if (value < 0) { - snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", - value); - return value; - } - - ucontrol->value.integer.value[0] = value; - - return 0; -} - -static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int error, value, change; - - value = ucontrol->value.integer.value[0]; - - error = aci_setvalue(miro->aci, ACI_SET_PREAMP, value); - if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", - error); - return error; - } - - change = (value != miro->aci->aci_preamp); - miro->aci->aci_preamp = value; - - return change; -} - -#define snd_miro_info_amp snd_ctl_boolean_mono_info - -static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = miro->aci->aci_amp; - - return 0; -} - -static int snd_miro_put_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int error, value, change; - - value = ucontrol->value.integer.value[0]; - - error = aci_setvalue(miro->aci, ACI_SET_POWERAMP, value); - if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error); - return error; - } - - change = (value != miro->aci->aci_amp); - miro->aci->aci_amp = value; - - return change; -} - -#define MIRO_DOUBLE(ctl_name, ctl_index, get_right_reg, set_right_reg) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = ctl_name, \ - .index = ctl_index, \ - .info = snd_miro_info_double, \ - .get = snd_miro_get_double, \ - .put = snd_miro_put_double, \ - .private_value = get_right_reg | (set_right_reg << 8) \ -} - -static int snd_miro_info_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int reg = kcontrol->private_value & 0xff; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - - if ((reg >= ACI_GET_EQ1) && (reg <= ACI_GET_EQ7)) { - - /* equalizer elements */ - - uinfo->value.integer.min = - 0x7f; - uinfo->value.integer.max = 0x7f; - } else { - - /* non-equalizer elements */ - - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0x20; - } - - return 0; -} - -static int snd_miro_get_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *uinfo) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int left_val, right_val; - - int right_reg = kcontrol->private_value & 0xff; - int left_reg = right_reg + 1; - - right_val = aci_getvalue(miro->aci, right_reg); - if (right_val < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val); - return right_val; - } - - left_val = aci_getvalue(miro->aci, left_reg); - if (left_val < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val); - return left_val; - } - - if ((right_reg >= ACI_GET_EQ1) && (right_reg <= ACI_GET_EQ7)) { - - /* equalizer elements */ - - if (left_val < 0x80) { - uinfo->value.integer.value[0] = left_val; - } else { - uinfo->value.integer.value[0] = 0x80 - left_val; - } - - if (right_val < 0x80) { - uinfo->value.integer.value[1] = right_val; - } else { - uinfo->value.integer.value[1] = 0x80 - right_val; - } - - } else { - - /* non-equalizer elements */ - - uinfo->value.integer.value[0] = 0x20 - left_val; - uinfo->value.integer.value[1] = 0x20 - right_val; - } - - return 0; -} - -static int snd_miro_put_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - struct snd_miro_aci *aci = miro->aci; - int left, right, left_old, right_old; - int setreg_left, setreg_right, getreg_left, getreg_right; - int change, error; - - left = ucontrol->value.integer.value[0]; - right = ucontrol->value.integer.value[1]; - - setreg_right = (kcontrol->private_value >> 8) & 0xff; - setreg_left = setreg_right + 8; - if (setreg_right == ACI_SET_MASTER) - setreg_left -= 7; - - getreg_right = kcontrol->private_value & 0xff; - getreg_left = getreg_right + 1; - - left_old = aci_getvalue(aci, getreg_left); - if (left_old < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old); - return left_old; - } - - right_old = aci_getvalue(aci, getreg_right); - if (right_old < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old); - return right_old; - } - - if ((getreg_right >= ACI_GET_EQ1) && (getreg_right <= ACI_GET_EQ7)) { - - /* equalizer elements */ - - if (left < -0x7f || left > 0x7f || - right < -0x7f || right > 0x7f) - return -EINVAL; - - if (left_old > 0x80) - left_old = 0x80 - left_old; - if (right_old > 0x80) - right_old = 0x80 - right_old; - - if (left >= 0) { - error = aci_setvalue(aci, setreg_left, left); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - left, error); - return error; - } - } else { - error = aci_setvalue(aci, setreg_left, 0x80 - left); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x80 - left, error); - return error; - } - } - - if (right >= 0) { - error = aci_setvalue(aci, setreg_right, right); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - right, error); - return error; - } - } else { - error = aci_setvalue(aci, setreg_right, 0x80 - right); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x80 - right, error); - return error; - } - } - - } else { - - /* non-equalizer elements */ - - if (left < 0 || left > 0x20 || - right < 0 || right > 0x20) - return -EINVAL; - - left_old = 0x20 - left_old; - right_old = 0x20 - right_old; - - error = aci_setvalue(aci, setreg_left, 0x20 - left); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x20 - left, error); - return error; - } - error = aci_setvalue(aci, setreg_right, 0x20 - right); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x20 - right, error); - return error; - } - } - - change = (left != left_old) || (right != right_old); - - return change; -} - -static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = { -MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER), -MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC), -MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE), -MIRO_DOUBLE("CD Playback Volume", 0, ACI_GET_CD, ACI_SET_CD), -MIRO_DOUBLE("Synth Playback Volume", 0, ACI_GET_SYNTH, ACI_SET_SYNTH), -MIRO_DOUBLE("PCM Playback Volume", 1, ACI_GET_PCM, ACI_SET_PCM), -MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2), -}; - -/* Equalizer with seven bands (only PCM20) - from -12dB up to +12dB on each band */ -static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = { -MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1), -MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2), -MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3), -MIRO_DOUBLE("Tone Control - 1 kHz", 0, ACI_GET_EQ4, ACI_SET_EQ4), -MIRO_DOUBLE("Tone Control - 2.5 kHz", 0, ACI_GET_EQ5, ACI_SET_EQ5), -MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6), -MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7), -}; - -static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = { -MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1), -}; - -static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = { -MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1), -}; - -static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Boost", - .index = 1, - .info = snd_miro_info_preamp, - .get = snd_miro_get_preamp, - .put = snd_miro_put_preamp, -}}; - -static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Boost", - .index = 0, - .info = snd_miro_info_amp, - .get = snd_miro_get_amp, - .put = snd_miro_put_amp, -}}; - -static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Capture Switch", - .index = 0, - .info = snd_miro_info_capture, - .get = snd_miro_get_capture, - .put = snd_miro_put_capture, -}}; - -static unsigned char aci_init_values[][2] __devinitdata = { - { ACI_SET_MUTE, 0x00 }, - { ACI_SET_POWERAMP, 0x00 }, - { ACI_SET_PREAMP, 0x00 }, - { ACI_SET_SOLOMODE, 0x00 }, - { ACI_SET_MIC + 0, 0x20 }, - { ACI_SET_MIC + 8, 0x20 }, - { ACI_SET_LINE + 0, 0x20 }, - { ACI_SET_LINE + 8, 0x20 }, - { ACI_SET_CD + 0, 0x20 }, - { ACI_SET_CD + 8, 0x20 }, - { ACI_SET_PCM + 0, 0x20 }, - { ACI_SET_PCM + 8, 0x20 }, - { ACI_SET_LINE1 + 0, 0x20 }, - { ACI_SET_LINE1 + 8, 0x20 }, - { ACI_SET_LINE2 + 0, 0x20 }, - { ACI_SET_LINE2 + 8, 0x20 }, - { ACI_SET_SYNTH + 0, 0x20 }, - { ACI_SET_SYNTH + 8, 0x20 }, - { ACI_SET_MASTER + 0, 0x20 }, - { ACI_SET_MASTER + 1, 0x20 }, -}; - -static int __devinit snd_set_aci_init_values(struct snd_miro *miro) -{ - int idx, error; - struct snd_miro_aci *aci = miro->aci; - - /* enable WSS on PCM1 */ - - if ((aci->aci_product == 'A') && wss) { - error = aci_setvalue(aci, ACI_SET_WSS, wss); - if (error < 0) { - snd_printk(KERN_ERR "enabling WSS mode failed\n"); - return error; - } - } - - /* enable IDE port */ - - if (ide) { - error = aci_setvalue(aci, ACI_SET_IDE, ide); - if (error < 0) { - snd_printk(KERN_ERR "enabling IDE port failed\n"); - return error; - } - } - - /* set common aci values */ - - for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) { - error = aci_setvalue(aci, aci_init_values[idx][0], - aci_init_values[idx][1]); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - aci_init_values[idx][0], error); - return error; - } - } - aci->aci_amp = 0; - aci->aci_preamp = 0; - aci->aci_solomode = 1; - - return 0; -} - -static int __devinit snd_miro_mixer(struct snd_card *card, - struct snd_miro *miro) -{ - unsigned int idx; - int err; - - if (snd_BUG_ON(!miro || !card)) - return -EINVAL; - - switch (miro->hardware) { - case OPTi9XX_HW_82C924: - strcpy(card->mixername, "ACI & OPTi924"); - break; - case OPTi9XX_HW_82C929: - strcpy(card->mixername, "ACI & OPTi929"); - break; - default: - snd_BUG(); - break; - } - - for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro))) < 0) - return err; - } - - if ((miro->aci->aci_product == 'A') || - (miro->aci->aci_product == 'B')) { - /* PCM1/PCM12 with power-amp and Line 2 */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0) - return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro))) < 0) - return err; - } - - if ((miro->aci->aci_product == 'B') || - (miro->aci->aci_product == 'C')) { - /* PCM12/PCM20 with mic-preamp */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0) - return err; - if (miro->aci->aci_version >= 176) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0) - return err; - } - - if (miro->aci->aci_product == 'C') { - /* PCM20 with radio and 7 band equalizer */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0) - return err; - for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro))) < 0) - return err; - } - } - - return 0; -} - -static long snd_legacy_find_free_ioport(long *port_table, long size) -{ - while (*port_table != -1) { - struct resource *res; - if ((res = request_region(*port_table, size, - "ALSA test")) != NULL) { - release_and_free_resource(res); - return *port_table; - } - port_table++; - } - return -1; -} - -static int __devinit snd_miro_init(struct snd_miro *chip, - unsigned short hardware) -{ - static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; - - chip->hardware = hardware; - strcpy(chip->name, snd_opti9xx_names[hardware]); - - chip->mc_base_size = opti9xx_mc_size[hardware]; - - spin_lock_init(&chip->lock); - - chip->wss_base = -1; - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - chip->mpu_port = -1; - chip->mpu_irq = -1; - - chip->pwd_reg = 3; - -#ifdef CONFIG_PNP - if (isapnp && chip->mc_base) - /* PnP resource gives the least 10 bits */ - chip->mc_base |= 0xc00; - else -#endif - chip->mc_base = 0xf8c; - - switch (hardware) { - case OPTi9XX_HW_82C929: - chip->password = 0xe3; - break; - - case OPTi9XX_HW_82C924: - chip->password = 0xe5; - break; - - default: - snd_printk(KERN_ERR "sorry, no support for %d\n", hardware); - return -ENODEV; - } - - return 0; -} - -static unsigned char snd_miro_read(struct snd_miro *chip, - unsigned char reg) -{ - unsigned long flags; - unsigned char retval = 0xff; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - - switch (chip->hardware) { - case OPTi9XX_HW_82C924: - if (reg > 7) { - outb(reg, chip->mc_base + 8); - outb(chip->password, chip->mc_base + chip->pwd_reg); - retval = inb(chip->mc_base + 9); - break; - } - - case OPTi9XX_HW_82C929: - retval = inb(chip->mc_base + reg); - break; - - default: - snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware); - } - - spin_unlock_irqrestore(&chip->lock, flags); - return retval; -} - -static void snd_miro_write(struct snd_miro *chip, unsigned char reg, - unsigned char value) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - - switch (chip->hardware) { - case OPTi9XX_HW_82C924: - if (reg > 7) { - outb(reg, chip->mc_base + 8); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(value, chip->mc_base + 9); - break; - } - - case OPTi9XX_HW_82C929: - outb(value, chip->mc_base + reg); - break; - - default: - snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware); - } - - spin_unlock_irqrestore(&chip->lock, flags); -} - - -#define snd_miro_write_mask(chip, reg, value, mask) \ - snd_miro_write(chip, reg, \ - (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask))) - -/* - * Proc Interface - */ - -static void snd_miro_proc_read(struct snd_info_entry * entry, - struct snd_info_buffer *buffer) -{ - struct snd_miro *miro = (struct snd_miro *) entry->private_data; - struct snd_miro_aci *aci = miro->aci; - char* model = "unknown"; - - /* miroSOUND PCM1 pro, early PCM12 */ - - if ((miro->hardware == OPTi9XX_HW_82C929) && - (aci->aci_vendor == 'm') && - (aci->aci_product == 'A')) { - switch (aci->aci_version) { - case 3: - model = "miroSOUND PCM1 pro"; - break; - default: - model = "miroSOUND PCM1 pro / (early) PCM12"; - break; - } - } - - /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */ - - if ((miro->hardware == OPTi9XX_HW_82C924) && - (aci->aci_vendor == 'm') && - (aci->aci_product == 'B')) { - switch (aci->aci_version) { - case 4: - model = "miroSOUND PCM12"; - break; - case 176: - model = "miroSOUND PCM12 (Rev. E)"; - break; - default: - model = "miroSOUND PCM12 / PCM12 pnp"; - break; - } - } - - /* miroSOUND PCM20 radio */ - - if ((miro->hardware == OPTi9XX_HW_82C924) && - (aci->aci_vendor == 'm') && - (aci->aci_product == 'C')) { - switch (aci->aci_version) { - case 7: - model = "miroSOUND PCM20 radio (Rev. E)"; - break; - default: - model = "miroSOUND PCM20 radio"; - break; - } - } - - snd_iprintf(buffer, "\nGeneral information:\n"); - snd_iprintf(buffer, " model : %s\n", model); - snd_iprintf(buffer, " opti : %s\n", miro->name); - snd_iprintf(buffer, " codec : %s\n", miro->pcm->name); - snd_iprintf(buffer, " port : 0x%lx\n", miro->wss_base); - snd_iprintf(buffer, " irq : %d\n", miro->irq); - snd_iprintf(buffer, " dma : %d,%d\n\n", miro->dma1, miro->dma2); - - snd_iprintf(buffer, "MPU-401:\n"); - snd_iprintf(buffer, " port : 0x%lx\n", miro->mpu_port); - snd_iprintf(buffer, " irq : %d\n\n", miro->mpu_irq); - - snd_iprintf(buffer, "ACI information:\n"); - snd_iprintf(buffer, " vendor : "); - switch (aci->aci_vendor) { - case 'm': - snd_iprintf(buffer, "Miro\n"); - break; - default: - snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_vendor); - break; - } - - snd_iprintf(buffer, " product : "); - switch (aci->aci_product) { - case 'A': - snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n"); - break; - case 'B': - snd_iprintf(buffer, "miroSOUND PCM12\n"); - break; - case 'C': - snd_iprintf(buffer, "miroSOUND PCM20 radio\n"); - break; - default: - snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_product); - break; - } - - snd_iprintf(buffer, " firmware: %d (0x%x)\n", - aci->aci_version, aci->aci_version); - snd_iprintf(buffer, " port : 0x%lx-0x%lx\n", - aci->aci_port, aci->aci_port+2); - snd_iprintf(buffer, " wss : 0x%x\n", wss); - snd_iprintf(buffer, " ide : 0x%x\n", ide); - snd_iprintf(buffer, " solomode: 0x%x\n", aci->aci_solomode); - snd_iprintf(buffer, " amp : 0x%x\n", aci->aci_amp); - snd_iprintf(buffer, " preamp : 0x%x\n", aci->aci_preamp); -} - -static void __devinit snd_miro_proc_init(struct snd_card *card, - struct snd_miro *miro) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(card, "miro", &entry)) - snd_info_set_text_ops(entry, miro, snd_miro_proc_read); -} - -/* - * Init - */ - -static int __devinit snd_miro_configure(struct snd_miro *chip) -{ - unsigned char wss_base_bits; - unsigned char irq_bits; - unsigned char dma_bits; - unsigned char mpu_port_bits = 0; - unsigned char mpu_irq_bits; - unsigned long flags; - - snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); - snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */ - snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); - - switch (chip->hardware) { - case OPTi9XX_HW_82C924: - snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); - snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); - break; - case OPTi9XX_HW_82C929: - /* untested init commands for OPTi929 */ - snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c); - break; - default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); - return -EINVAL; - } - - /* PnP resource says it decodes only 10 bits of address */ - switch (chip->wss_base & 0x3ff) { - case 0x130: - chip->wss_base = 0x530; - wss_base_bits = 0x00; - break; - case 0x204: - chip->wss_base = 0x604; - wss_base_bits = 0x03; - break; - case 0x280: - chip->wss_base = 0xe80; - wss_base_bits = 0x01; - break; - case 0x340: - chip->wss_base = 0xf40; - wss_base_bits = 0x02; - break; - default: - snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base); - goto __skip_base; - } - snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); - -__skip_base: - switch (chip->irq) { - case 5: - irq_bits = 0x05; - break; - case 7: - irq_bits = 0x01; - break; - case 9: - irq_bits = 0x02; - break; - case 10: - irq_bits = 0x03; - break; - case 11: - irq_bits = 0x04; - break; - default: - snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq); - goto __skip_resources; - } - - switch (chip->dma1) { - case 0: - dma_bits = 0x01; - break; - case 1: - dma_bits = 0x02; - break; - case 3: - dma_bits = 0x03; - break; - default: - snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1); - goto __skip_resources; - } - - if (chip->dma1 == chip->dma2) { - snd_printk(KERN_ERR "don't want to share dmas\n"); - return -EBUSY; - } - - switch (chip->dma2) { - case 0: - case 1: - break; - default: - snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2); - goto __skip_resources; - } - dma_bits |= 0x04; - - spin_lock_irqsave(&chip->lock, flags); - outb(irq_bits << 3 | dma_bits, chip->wss_base); - spin_unlock_irqrestore(&chip->lock, flags); - -__skip_resources: - if (chip->hardware > OPTi9XX_HW_82C928) { - switch (chip->mpu_port) { - case 0: - case -1: - break; - case 0x300: - mpu_port_bits = 0x03; - break; - case 0x310: - mpu_port_bits = 0x02; - break; - case 0x320: - mpu_port_bits = 0x01; - break; - case 0x330: - mpu_port_bits = 0x00; - break; - default: - snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n", - chip->mpu_port); - goto __skip_mpu; - } - - switch (chip->mpu_irq) { - case 5: - mpu_irq_bits = 0x02; - break; - case 7: - mpu_irq_bits = 0x03; - break; - case 9: - mpu_irq_bits = 0x00; - break; - case 10: - mpu_irq_bits = 0x01; - break; - default: - snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n", - chip->mpu_irq); - goto __skip_mpu; - } - - snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), - (chip->mpu_port <= 0) ? 0x00 : - 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3, - 0xf8); - } -__skip_mpu: - - return 0; -} - -static int __devinit snd_miro_opti_check(struct snd_miro *chip) -{ - unsigned char value; - - chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, - "OPTi9xx MC"); - if (chip->res_mc_base == NULL) - return -ENOMEM; - - value = snd_miro_read(chip, OPTi9XX_MC_REG(1)); - if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1))) - if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1))) - return 0; - - release_and_free_resource(chip->res_mc_base); - chip->res_mc_base = NULL; - - return -ENODEV; -} - -static int __devinit snd_card_miro_detect(struct snd_card *card, - struct snd_miro *chip) -{ - int i, err; - - for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) { - - if ((err = snd_miro_init(chip, i)) < 0) - return err; - - err = snd_miro_opti_check(chip); - if (err == 0) - return 1; - } - - return -ENODEV; -} - -static int __devinit snd_card_miro_aci_detect(struct snd_card *card, - struct snd_miro *miro) -{ - unsigned char regval; - int i; - struct snd_miro_aci *aci = &aci_device; - - miro->aci = aci; - - mutex_init(&aci->aci_mutex); - - /* get ACI port from OPTi9xx MC 4 */ - - regval=inb(miro->mc_base + 4); - aci->aci_port = (regval & 0x10) ? 0x344 : 0x354; - - miro->res_aci_port = request_region(aci->aci_port, 3, "miro aci"); - if (miro->res_aci_port == NULL) { - snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", - aci->aci_port, aci->aci_port+2); - return -ENOMEM; - } - - /* force ACI into a known state */ - for (i = 0; i < 3; i++) - if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) { - snd_printk(KERN_ERR "can't force aci into known state.\n"); - return -ENXIO; - } - - aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); - aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); - if (aci->aci_vendor < 0 || aci->aci_product < 0) { - snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", - aci->aci_port); - return -ENXIO; - } - - aci->aci_version = snd_aci_cmd(aci, ACI_READ_VERSION, -1, -1); - if (aci->aci_version < 0) { - snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", - aci->aci_port); - return -ENXIO; - } - - if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 || - snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || - snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { - snd_printk(KERN_ERR "can't initialize aci.\n"); - return -ENXIO; - } - - return 0; -} - -static void snd_card_miro_free(struct snd_card *card) -{ - struct snd_miro *miro = card->private_data; - - release_and_free_resource(miro->res_aci_port); - if (miro->aci) - miro->aci->aci_port = 0; - release_and_free_resource(miro->res_mc_base); -} - -static int __devinit snd_miro_probe(struct snd_card *card) -{ - int error; - struct snd_miro *miro = card->private_data; - struct snd_wss *codec; - struct snd_timer *timer; - struct snd_pcm *pcm; - struct snd_rawmidi *rmidi; - - if (!miro->res_mc_base) { - miro->res_mc_base = request_region(miro->mc_base, - miro->mc_base_size, - "miro (OPTi9xx MC)"); - if (miro->res_mc_base == NULL) { - snd_printk(KERN_ERR "request for OPTI9xx MC failed\n"); - return -ENOMEM; - } - } - - error = snd_card_miro_aci_detect(card, miro); - if (error < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to detect aci chip\n"); - return -ENODEV; - } - - miro->wss_base = port; - miro->mpu_port = mpu_port; - miro->irq = irq; - miro->mpu_irq = mpu_irq; - miro->dma1 = dma1; - miro->dma2 = dma2; - - /* init proc interface */ - snd_miro_proc_init(card, miro); - - error = snd_miro_configure(miro); - if (error) - return error; - - error = snd_wss_create(card, miro->wss_base + 4, -1, - miro->irq, miro->dma1, miro->dma2, - WSS_HW_DETECT, 0, &codec); - if (error < 0) - return error; - - error = snd_wss_pcm(codec, 0, &pcm); - if (error < 0) - return error; - - error = snd_wss_mixer(codec); - if (error < 0) - return error; - - error = snd_wss_timer(codec, 0, &timer); - if (error < 0) - return error; - - miro->pcm = pcm; - - error = snd_miro_mixer(card, miro); - if (error < 0) - return error; - - if (miro->aci->aci_vendor == 'm') { - /* It looks like a miro sound card. */ - switch (miro->aci->aci_product) { - case 'A': - sprintf(card->shortname, - "miroSOUND PCM1 pro / PCM12"); - break; - case 'B': - sprintf(card->shortname, - "miroSOUND PCM12"); - break; - case 'C': - sprintf(card->shortname, - "miroSOUND PCM20 radio"); - break; - default: - sprintf(card->shortname, - "unknown miro"); - snd_printk(KERN_INFO "unknown miro aci id\n"); - break; - } - } else { - snd_printk(KERN_INFO "found unsupported aci card\n"); - sprintf(card->shortname, "unknown Cardinal Technologies"); - } - - strcpy(card->driver, "miro"); - sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, miro->name, pcm->name, miro->wss_base + 4, - miro->irq, miro->dma1, miro->dma2); - - if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) - rmidi = NULL; - else { - error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port, 0, miro->mpu_irq, &rmidi); - if (error < 0) - snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", - mpu_port); - } - - if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { - struct snd_opl3 *opl3 = NULL; - struct snd_opl4 *opl4; - - if (snd_opl4_create(card, fm_port, fm_port - 8, - 2, &opl3, &opl4) < 0) - snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", - fm_port); - } - - error = snd_set_aci_init_values(miro); - if (error < 0) - return error; - - return snd_card_register(card); -} - -static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n) -{ -#ifdef CONFIG_PNP - if (snd_miro_pnp_is_probed) - return 0; - if (isapnp) - return 0; -#endif - return 1; -} - -static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n) -{ - static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; - static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; - static int possible_irqs[] = {11, 9, 10, 7, -1}; - static int possible_mpu_irqs[] = {10, 5, 9, 7, -1}; - static int possible_dma1s[] = {3, 1, 0, -1}; - static int possible_dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, - {0, -1} }; - - int error; - struct snd_miro *miro; - struct snd_card *card; - - error = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_miro), &card); - if (error < 0) - return error; - - card->private_free = snd_card_miro_free; - miro = card->private_data; - - error = snd_card_miro_detect(card, miro); - if (error < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n"); - return -ENODEV; - } - - if (port == SNDRV_AUTO_PORT) { - port = snd_legacy_find_free_ioport(possible_ports, 4); - if (port < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to find a free WSS port\n"); - return -EBUSY; - } - } - - if (mpu_port == SNDRV_AUTO_PORT) { - mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2); - if (mpu_port < 0) { - snd_card_free(card); - snd_printk(KERN_ERR - "unable to find a free MPU401 port\n"); - return -EBUSY; - } - } - - if (irq == SNDRV_AUTO_IRQ) { - irq = snd_legacy_find_free_irq(possible_irqs); - if (irq < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (mpu_irq == SNDRV_AUTO_IRQ) { - mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs); - if (mpu_irq < 0) { - snd_card_free(card); - snd_printk(KERN_ERR - "unable to find a free MPU401 IRQ\n"); - return -EBUSY; - } - } - if (dma1 == SNDRV_AUTO_DMA) { - dma1 = snd_legacy_find_free_dma(possible_dma1s); - if (dma1 < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to find a free DMA1\n"); - return -EBUSY; - } - } - if (dma2 == SNDRV_AUTO_DMA) { - dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]); - if (dma2 < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to find a free DMA2\n"); - return -EBUSY; - } - } - - snd_card_set_dev(card, devptr); - - error = snd_miro_probe(card); - if (error < 0) { - snd_card_free(card); - return error; - } - - dev_set_drvdata(devptr, card); - return 0; -} - -static int __devexit snd_miro_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#define DEV_NAME "miro" - -static struct isa_driver snd_miro_driver = { - .match = snd_miro_isa_match, - .probe = snd_miro_isa_probe, - .remove = __devexit_p(snd_miro_isa_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DEV_NAME - }, -}; - -#ifdef CONFIG_PNP - -static int __devinit snd_card_miro_pnp(struct snd_miro *chip, - struct pnp_card_link *card, - const struct pnp_card_device_id *pid) -{ - struct pnp_dev *pdev; - int err; - struct pnp_dev *devmpu; - struct pnp_dev *devmc; - - pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); - if (pdev == NULL) - return -EBUSY; - - devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); - if (devmpu == NULL) - return -EBUSY; - - devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); - if (devmc == NULL) - return -EBUSY; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); - return err; - } - - err = pnp_activate_dev(devmc); - if (err < 0) { - snd_printk(KERN_ERR "MC pnp configure failure: %d\n", - err); - return err; - } - - port = pnp_port_start(pdev, 1); - fm_port = pnp_port_start(pdev, 2) + 8; - - /* - * The MC(0) is never accessed and the miroSOUND PCM20 card does not - * include it in the PnP resource range. OPTI93x include it. - */ - chip->mc_base = pnp_port_start(devmc, 0) - 1; - chip->mc_base_size = pnp_port_len(devmc, 0) + 1; - - irq = pnp_irq(pdev, 0); - dma1 = pnp_dma(pdev, 0); - dma2 = pnp_dma(pdev, 1); - - if (mpu_port > 0) { - err = pnp_activate_dev(devmpu); - if (err < 0) { - snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); - mpu_port = -1; - return err; - } - mpu_port = pnp_port_start(devmpu, 0); - mpu_irq = pnp_irq(devmpu, 0); - } - return 0; -} - -static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - struct snd_card *card; - int err; - struct snd_miro *miro; - - if (snd_miro_pnp_is_probed) - return -EBUSY; - if (!isapnp) - return -ENODEV; - err = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_miro), &card); - if (err < 0) - return err; - - card->private_free = snd_card_miro_free; - miro = card->private_data; - - err = snd_card_miro_pnp(miro, pcard, pid); - if (err) { - snd_card_free(card); - return err; - } - - /* only miroSOUND PCM20 and PCM12 == OPTi924 */ - err = snd_miro_init(miro, OPTi9XX_HW_82C924); - if (err) { - snd_card_free(card); - return err; - } - - err = snd_miro_opti_check(miro); - if (err) { - snd_printk(KERN_ERR "OPTI chip not found\n"); - snd_card_free(card); - return err; - } - - snd_card_set_dev(card, &pcard->card->dev); - err = snd_miro_probe(card); - if (err < 0) { - snd_card_free(card); - return err; - } - pnp_set_card_drvdata(pcard, card); - snd_miro_pnp_is_probed = 1; - return 0; -} - -static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); - snd_miro_pnp_is_probed = 0; -} - -static struct pnp_card_driver miro_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "miro", - .id_table = snd_miro_pnpids, - .probe = snd_miro_pnp_probe, - .remove = __devexit_p(snd_miro_pnp_remove), -}; -#endif - -static int __init alsa_card_miro_init(void) -{ -#ifdef CONFIG_PNP - pnp_register_card_driver(&miro_pnpc_driver); - if (snd_miro_pnp_is_probed) - return 0; - pnp_unregister_card_driver(&miro_pnpc_driver); -#endif - return isa_register_driver(&snd_miro_driver, 1); -} - -static void __exit alsa_card_miro_exit(void) -{ - if (!snd_miro_pnp_is_probed) { - isa_unregister_driver(&snd_miro_driver); - return; - } -#ifdef CONFIG_PNP - pnp_unregister_card_driver(&miro_pnpc_driver); -#endif -} - -module_init(alsa_card_miro_init) -module_exit(alsa_card_miro_exit) diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-ad1848.c b/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-ad1848.c deleted file mode 100644 index d7ccf28b..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-ad1848.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* - card-opti92x-ad1848.c - driver for OPTi 82c92x based soundcards. - Copyright (C) 1998-2000 by Massimo Piccioni - - Part of this code was developed at the Italian Ministry of Air Defence, - Sixth Division (oh, che pace ...), Rome. - - Thanks to Maria Grazia Pollarini, Salvatore Vassallo. - - 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 -#include -#include -#include -#include -#ifndef OPTi93X -#include -#endif -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -MODULE_AUTHOR("Massimo Piccioni "); -MODULE_LICENSE("GPL"); -#ifdef OPTi93X -MODULE_DESCRIPTION("OPTi93X"); -MODULE_SUPPORTED_DEVICE("{{OPTi,82C931/3}}"); -#else /* OPTi93X */ -#ifdef CS4231 -MODULE_DESCRIPTION("OPTi92X - CS4231"); -MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (CS4231)}," - "{OPTi,82C925 (CS4231)}}"); -#else /* CS4231 */ -MODULE_DESCRIPTION("OPTi92X - AD1848"); -MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)}," - "{OPTi,82C925 (AD1848)}," - "{OAK,Mozart}}"); -#endif /* CS4231 */ -#endif /* OPTi93X */ - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -//static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp = true; /* Enable ISA PnP detection */ -#endif -static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */ -static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */ -static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */ -static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */ -static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */ -static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ -#if defined(CS4231) || defined(OPTi93X) -static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ -#endif /* CS4231 || OPTi93X */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard."); -//module_param(enable, bool, 0444); -//MODULE_PARM_DESC(enable, "Enable opti9xx soundcard."); -#ifdef CONFIG_PNP -module_param(isapnp, bool, 0444); -MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard."); -#endif -module_param(port, long, 0444); -MODULE_PARM_DESC(port, "WSS port # for opti9xx driver."); -module_param(mpu_port, long, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver."); -module_param(fm_port, long, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver."); -module_param(irq, int, 0444); -MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver."); -module_param(mpu_irq, int, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver."); -module_param(dma1, int, 0444); -MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver."); -#if defined(CS4231) || defined(OPTi93X) -module_param(dma2, int, 0444); -MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver."); -#endif /* CS4231 || OPTi93X */ - -#define OPTi9XX_HW_82C928 1 -#define OPTi9XX_HW_82C929 2 -#define OPTi9XX_HW_82C924 3 -#define OPTi9XX_HW_82C925 4 -#define OPTi9XX_HW_82C930 5 -#define OPTi9XX_HW_82C931 6 -#define OPTi9XX_HW_82C933 7 -#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933 - -#define OPTi9XX_MC_REG(n) n - -#ifdef OPTi93X - -#define OPTi93X_STATUS 0x02 -#define OPTi93X_PORT(chip, r) ((chip)->port + OPTi93X_##r) - -#define OPTi93X_IRQ_PLAYBACK 0x04 -#define OPTi93X_IRQ_CAPTURE 0x08 - -#endif /* OPTi93X */ - -struct snd_opti9xx { - unsigned short hardware; - unsigned char password; - char name[7]; - - unsigned long mc_base; - struct resource *res_mc_base; - unsigned long mc_base_size; -#ifdef OPTi93X - unsigned long mc_indir_index; - unsigned long mc_indir_size; - struct resource *res_mc_indir; - struct snd_wss *codec; -#endif /* OPTi93X */ - unsigned long pwd_reg; - - spinlock_t lock; - - long wss_base; - int irq; -}; - -static int snd_opti9xx_pnp_is_probed; - -#ifdef CONFIG_PNP - -static struct pnp_card_device_id snd_opti9xx_pnpids[] = { -#ifndef OPTi93X - /* OPTi 82C924 */ - { .id = "OPT0924", - .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } }, - .driver_data = 0x0924 }, - /* OPTi 82C925 */ - { .id = "OPT0925", - .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } }, - .driver_data = 0x0925 }, -#else - /* OPTi 82C931/3 */ - { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, - .driver_data = 0x0931 }, -#endif /* OPTi93X */ - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids); - -#endif /* CONFIG_PNP */ - -#ifdef OPTi93X -#define DEV_NAME "opti93x" -#else -#define DEV_NAME "opti92x" -#endif - -static char * snd_opti9xx_names[] = { - "unknown", - "82C928", "82C929", - "82C924", "82C925", - "82C930", "82C931", "82C933" -}; - - -static long __devinit snd_legacy_find_free_ioport(long *port_table, long size) -{ - while (*port_table != -1) { - if (request_region(*port_table, size, "ALSA test")) { - release_region(*port_table, size); - return *port_table; - } - port_table++; - } - return -1; -} - -static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, - unsigned short hardware) -{ - static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; - - chip->hardware = hardware; - strcpy(chip->name, snd_opti9xx_names[hardware]); - - spin_lock_init(&chip->lock); - - chip->irq = -1; - -#ifndef OPTi93X -#ifdef CONFIG_PNP - if (isapnp && chip->mc_base) - /* PnP resource gives the least 10 bits */ - chip->mc_base |= 0xc00; - else -#endif /* CONFIG_PNP */ - { - chip->mc_base = 0xf8c; - chip->mc_base_size = opti9xx_mc_size[hardware]; - } -#else - chip->mc_base_size = opti9xx_mc_size[hardware]; -#endif - - switch (hardware) { -#ifndef OPTi93X - case OPTi9XX_HW_82C928: - case OPTi9XX_HW_82C929: - chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3; - chip->pwd_reg = 3; - break; - - case OPTi9XX_HW_82C924: - case OPTi9XX_HW_82C925: - chip->password = 0xe5; - chip->pwd_reg = 3; - break; -#else /* OPTi93X */ - - case OPTi9XX_HW_82C930: - case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: - chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; - if (!chip->mc_indir_index) { - chip->mc_indir_index = 0xe0e; - chip->mc_indir_size = 2; - } - chip->password = 0xe4; - chip->pwd_reg = 0; - break; -#endif /* OPTi93X */ - - default: - snd_printk(KERN_ERR "chip %d not supported\n", hardware); - return -ENODEV; - } - return 0; -} - -static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, - unsigned char reg) -{ - unsigned long flags; - unsigned char retval = 0xff; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - - switch (chip->hardware) { -#ifndef OPTi93X - case OPTi9XX_HW_82C924: - case OPTi9XX_HW_82C925: - if (reg > 7) { - outb(reg, chip->mc_base + 8); - outb(chip->password, chip->mc_base + chip->pwd_reg); - retval = inb(chip->mc_base + 9); - break; - } - - case OPTi9XX_HW_82C928: - case OPTi9XX_HW_82C929: - retval = inb(chip->mc_base + reg); - break; -#else /* OPTi93X */ - - case OPTi9XX_HW_82C930: - case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: - outb(reg, chip->mc_indir_index); - outb(chip->password, chip->mc_base + chip->pwd_reg); - retval = inb(chip->mc_indir_index + 1); - break; -#endif /* OPTi93X */ - - default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); - } - - spin_unlock_irqrestore(&chip->lock, flags); - return retval; -} - -static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, - unsigned char value) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - - switch (chip->hardware) { -#ifndef OPTi93X - case OPTi9XX_HW_82C924: - case OPTi9XX_HW_82C925: - if (reg > 7) { - outb(reg, chip->mc_base + 8); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(value, chip->mc_base + 9); - break; - } - - case OPTi9XX_HW_82C928: - case OPTi9XX_HW_82C929: - outb(value, chip->mc_base + reg); - break; -#else /* OPTi93X */ - - case OPTi9XX_HW_82C930: - case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: - outb(reg, chip->mc_indir_index); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(value, chip->mc_indir_index + 1); - break; -#endif /* OPTi93X */ - - default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); - } - - spin_unlock_irqrestore(&chip->lock, flags); -} - - -#define snd_opti9xx_write_mask(chip, reg, value, mask) \ - snd_opti9xx_write(chip, reg, \ - (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) - - -static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, - long port, - int irq, int dma1, int dma2, - long mpu_port, int mpu_irq) -{ - unsigned char wss_base_bits; - unsigned char irq_bits; - unsigned char dma_bits; - unsigned char mpu_port_bits = 0; - unsigned char mpu_irq_bits; - - switch (chip->hardware) { -#ifndef OPTi93X - case OPTi9XX_HW_82C924: - /* opti 929 mode (?), OPL3 clock output, audio enable */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); - /* enable wave audio */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); - - case OPTi9XX_HW_82C925: - /* enable WSS mode */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); - /* OPL3 FM synthesis */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); - /* disable Sound Blaster IRQ and DMA */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); -#ifdef CS4231 - /* cs4231/4248 fix enabled */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); -#else - /* cs4231/4248 fix disabled */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); -#endif /* CS4231 */ - break; - - case OPTi9XX_HW_82C928: - case OPTi9XX_HW_82C929: - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); - /* - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xa2, 0xae); - */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c); -#ifdef CS4231 - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); -#else - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); -#endif /* CS4231 */ - break; - -#else /* OPTi93X */ - case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: - /* - * The BTC 1817DW has QS1000 wavetable which is connected - * to the serial digital input of the OPTI931. - */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(21), 0x82, 0xff); - /* - * This bit sets OPTI931 to automaticaly select FM - * or digital input signal. - */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01); - case OPTi9XX_HW_82C930: /* FALL THROUGH */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 | - (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04), - 0x34); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf); - break; -#endif /* OPTi93X */ - - default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); - return -EINVAL; - } - - /* PnP resource says it decodes only 10 bits of address */ - switch (port & 0x3ff) { - case 0x130: - chip->wss_base = 0x530; - wss_base_bits = 0x00; - break; - case 0x204: - chip->wss_base = 0x604; - wss_base_bits = 0x03; - break; - case 0x280: - chip->wss_base = 0xe80; - wss_base_bits = 0x01; - break; - case 0x340: - chip->wss_base = 0xf40; - wss_base_bits = 0x02; - break; - default: - snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port); - goto __skip_base; - } - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); - -__skip_base: - switch (irq) { -//#ifdef OPTi93X - case 5: - irq_bits = 0x05; - break; -//#endif /* OPTi93X */ - case 7: - irq_bits = 0x01; - break; - case 9: - irq_bits = 0x02; - break; - case 10: - irq_bits = 0x03; - break; - case 11: - irq_bits = 0x04; - break; - default: - snd_printk(KERN_WARNING "WSS irq # %d not valid\n", irq); - goto __skip_resources; - } - - switch (dma1) { - case 0: - dma_bits = 0x01; - break; - case 1: - dma_bits = 0x02; - break; - case 3: - dma_bits = 0x03; - break; - default: - snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", dma1); - goto __skip_resources; - } - -#if defined(CS4231) || defined(OPTi93X) - if (dma1 == dma2) { - snd_printk(KERN_ERR "don't want to share dmas\n"); - return -EBUSY; - } - - switch (dma2) { - case 0: - case 1: - break; - default: - snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", dma2); - goto __skip_resources; - } - dma_bits |= 0x04; -#endif /* CS4231 || OPTi93X */ - -#ifndef OPTi93X - outb(irq_bits << 3 | dma_bits, chip->wss_base); -#else /* OPTi93X */ - snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); -#endif /* OPTi93X */ - -__skip_resources: - if (chip->hardware > OPTi9XX_HW_82C928) { - switch (mpu_port) { - case 0: - case -1: - break; - case 0x300: - mpu_port_bits = 0x03; - break; - case 0x310: - mpu_port_bits = 0x02; - break; - case 0x320: - mpu_port_bits = 0x01; - break; - case 0x330: - mpu_port_bits = 0x00; - break; - default: - snd_printk(KERN_WARNING - "MPU-401 port 0x%lx not valid\n", mpu_port); - goto __skip_mpu; - } - - switch (mpu_irq) { - case 5: - mpu_irq_bits = 0x02; - break; - case 7: - mpu_irq_bits = 0x03; - break; - case 9: - mpu_irq_bits = 0x00; - break; - case 10: - mpu_irq_bits = 0x01; - break; - default: - snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n", - mpu_irq); - goto __skip_mpu; - } - - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), - (mpu_port <= 0) ? 0x00 : - 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3, - 0xf8); - } -__skip_mpu: - - return 0; -} - -#ifdef OPTi93X - -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_step, -9300, 300, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_4bit_12db_max, -3300, 300, 0); - -static struct snd_kcontrol_new snd_opti93x_controls[] = { -WSS_DOUBLE("Master Playback Switch", 0, - OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Master Playback Volume", 0, - OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1, - db_scale_5bit_3db_step), -WSS_DOUBLE_TLV("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1, - db_scale_5bit), -WSS_DOUBLE_TLV("FM Playback Volume", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1, - db_scale_4bit_12db_max), -WSS_DOUBLE("Line Playback Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Line Playback Volume", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1, - db_scale_4bit_12db_max), -WSS_DOUBLE("Mic Playback Switch", 0, - OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Mic Playback Volume", 0, - OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1, - db_scale_4bit_12db_max), -WSS_DOUBLE_TLV("CD Playback Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1, - db_scale_4bit_12db_max), -WSS_DOUBLE("Aux Playback Switch", 0, - OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Aux Playback Volume", 0, - OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1, - db_scale_4bit_12db_max), -}; - -static int __devinit snd_opti93x_mixer(struct snd_wss *chip) -{ - struct snd_card *card; - unsigned int idx; - struct snd_ctl_elem_id id1, id2; - int err; - - if (snd_BUG_ON(!chip || !chip->pcm)) - return -EINVAL; - - card = chip->card; - - strcpy(card->mixername, chip->pcm->name); - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUX0 switch to CD */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "CD Playback Switch"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opti93x control\n"); - return err; - } - /* reassign AUX1 switch to FM */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "FM Playback Switch"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opti93x control\n"); - return err; - } - /* remove AUX1 volume */ - strcpy(id1.name, "Aux Playback Volume"); id1.index = 1; - snd_ctl_remove_id(card, &id1); - - /* Replace WSS volume controls with OPTi93x volume controls */ - id1.index = 0; - for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) { - strcpy(id1.name, snd_opti93x_controls[idx].name); - snd_ctl_remove_id(card, &id1); - - err = snd_ctl_add(card, - snd_ctl_new1(&snd_opti93x_controls[idx], chip)); - if (err < 0) - return err; - } - return 0; -} - -static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) -{ - struct snd_opti9xx *chip = dev_id; - struct snd_wss *codec = chip->codec; - unsigned char status; - - if (!codec) - return IRQ_HANDLED; - - status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11)); - if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream) - snd_pcm_period_elapsed(codec->playback_substream); - if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) { - snd_wss_overrange(codec); - snd_pcm_period_elapsed(codec->capture_substream); - } - outb(0x00, OPTi93X_PORT(codec, STATUS)); - return IRQ_HANDLED; -} - -#endif /* OPTi93X */ - -static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) -{ - unsigned char value; -#ifdef OPTi93X - unsigned long flags; -#endif - - chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, - "OPTi9xx MC"); - if (chip->res_mc_base == NULL) - return -EBUSY; -#ifndef OPTi93X - value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)); - if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1))) - if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) - return 0; -#else /* OPTi93X */ - chip->res_mc_indir = request_region(chip->mc_indir_index, - chip->mc_indir_size, - "OPTi93x MC"); - if (chip->res_mc_indir == NULL) - return -EBUSY; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(((chip->mc_indir_index & 0x1f0) >> 4), chip->mc_base); - spin_unlock_irqrestore(&chip->lock, flags); - - value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)); - snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value); - if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value) - return 0; - - release_and_free_resource(chip->res_mc_indir); - chip->res_mc_indir = NULL; -#endif /* OPTi93X */ - release_and_free_resource(chip->res_mc_base); - chip->res_mc_base = NULL; - - return -ENODEV; -} - -static int __devinit snd_card_opti9xx_detect(struct snd_card *card, - struct snd_opti9xx *chip) -{ - int i, err; - -#ifndef OPTi93X - for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) { -#else - for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) { -#endif - err = snd_opti9xx_init(chip, i); - if (err < 0) - return err; - - err = snd_opti9xx_read_check(chip); - if (err == 0) - return 1; -#ifdef OPTi93X - chip->mc_indir_index = 0; -#endif - } - return -ENODEV; -} - -#ifdef CONFIG_PNP -static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, - struct pnp_card_link *card, - const struct pnp_card_device_id *pid) -{ - struct pnp_dev *pdev; - int err; - struct pnp_dev *devmpu; -#ifndef OPTi93X - struct pnp_dev *devmc; -#endif - - pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); - if (pdev == NULL) - return -EBUSY; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); - return err; - } - -#ifdef OPTi93X - port = pnp_port_start(pdev, 0) - 4; - fm_port = pnp_port_start(pdev, 1) + 8; - chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; - chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; -#else - devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); - if (devmc == NULL) - return -EBUSY; - - err = pnp_activate_dev(devmc); - if (err < 0) { - snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); - return err; - } - - port = pnp_port_start(pdev, 1); - fm_port = pnp_port_start(pdev, 2) + 8; - /* - * The MC(0) is never accessed and card does not - * include it in the PnP resource range. OPTI93x include it. - */ - chip->mc_base = pnp_port_start(devmc, 0) - 1; - chip->mc_base_size = pnp_port_len(devmc, 0) + 1; -#endif /* OPTi93X */ - irq = pnp_irq(pdev, 0); - dma1 = pnp_dma(pdev, 0); -#if defined(CS4231) || defined(OPTi93X) - dma2 = pnp_dma(pdev, 1); -#endif /* CS4231 || OPTi93X */ - - devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); - - if (devmpu && mpu_port > 0) { - err = pnp_activate_dev(devmpu); - if (err < 0) { - snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); - mpu_port = -1; - } else { - mpu_port = pnp_port_start(devmpu, 0); - mpu_irq = pnp_irq(devmpu, 0); - } - } - return pid->driver_data; -} -#endif /* CONFIG_PNP */ - -static void snd_card_opti9xx_free(struct snd_card *card) -{ - struct snd_opti9xx *chip = card->private_data; - - if (chip) { -#ifdef OPTi93X - if (chip->irq > 0) { - disable_irq(chip->irq); - free_irq(chip->irq, chip); - } - release_and_free_resource(chip->res_mc_indir); -#endif - release_and_free_resource(chip->res_mc_base); - } -} - -static int __devinit snd_opti9xx_probe(struct snd_card *card) -{ - static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; - int error; - int xdma2; - struct snd_opti9xx *chip = card->private_data; - struct snd_wss *codec; -#ifdef CS4231 - struct snd_timer *timer; -#endif - struct snd_pcm *pcm; - struct snd_rawmidi *rmidi; - struct snd_hwdep *synth; - -#if defined(CS4231) || defined(OPTi93X) - xdma2 = dma2; -#else - xdma2 = -1; -#endif - - if (port == SNDRV_AUTO_PORT) { - port = snd_legacy_find_free_ioport(possible_ports, 4); - if (port < 0) { - snd_printk(KERN_ERR "unable to find a free WSS port\n"); - return -EBUSY; - } - } - error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2, - mpu_port, mpu_irq); - if (error) - return error; - - error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2, -#ifdef OPTi93X - WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, -#else - WSS_HW_DETECT, 0, -#endif - &codec); - if (error < 0) - return error; -#ifdef OPTi93X - chip->codec = codec; -#endif - error = snd_wss_pcm(codec, 0, &pcm); - if (error < 0) - return error; - error = snd_wss_mixer(codec); - if (error < 0) - return error; -#ifdef OPTi93X - error = snd_opti93x_mixer(codec); - if (error < 0) - return error; -#endif -#ifdef CS4231 - error = snd_wss_timer(codec, 0, &timer); - if (error < 0) - return error; -#endif -#ifdef OPTi93X - error = request_irq(irq, snd_opti93x_interrupt, - 0, DEV_NAME" - WSS", chip); - if (error < 0) { - snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq); - return error; - } -#endif - chip->irq = irq; - strcpy(card->driver, chip->name); - sprintf(card->shortname, "OPTi %s", card->driver); -#if defined(CS4231) || defined(OPTi93X) - sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, pcm->name, - chip->wss_base + 4, irq, dma1, xdma2); -#else - sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", - card->shortname, pcm->name, chip->wss_base + 4, irq, dma1); -#endif /* CS4231 || OPTi93X */ - - if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) - rmidi = NULL; - else { - error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port, 0, mpu_irq, &rmidi); - if (error) - snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", - mpu_port); - } - - if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { - struct snd_opl3 *opl3 = NULL; -#ifndef OPTi93X - if (chip->hardware == OPTi9XX_HW_82C928 || - chip->hardware == OPTi9XX_HW_82C929 || - chip->hardware == OPTi9XX_HW_82C924) { - struct snd_opl4 *opl4; - /* assume we have an OPL4 */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), - 0x20, 0x20); - if (snd_opl4_create(card, fm_port, fm_port - 8, - 2, &opl3, &opl4) < 0) { - /* no luck, use OPL3 instead */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), - 0x00, 0x20); - } - } -#endif /* !OPTi93X */ - if (!opl3 && snd_opl3_create(card, fm_port, fm_port + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n", - fm_port, fm_port + 4 - 1); - } - if (opl3) { - error = snd_opl3_hwdep_new(opl3, 0, 1, &synth); - if (error < 0) - return error; - } - } - - return snd_card_register(card); -} - -static int snd_opti9xx_card_new(struct snd_card **cardp) -{ - struct snd_card *card; - int err; - - err = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_opti9xx), &card); - if (err < 0) - return err; - card->private_free = snd_card_opti9xx_free; - *cardp = card; - return 0; -} - -static int __devinit snd_opti9xx_isa_match(struct device *devptr, - unsigned int dev) -{ -#ifdef CONFIG_PNP - if (snd_opti9xx_pnp_is_probed) - return 0; - if (isapnp) - return 0; -#endif - return 1; -} - -static int __devinit snd_opti9xx_isa_probe(struct device *devptr, - unsigned int dev) -{ - struct snd_card *card; - int error; - static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1}; -#ifdef OPTi93X - static int possible_irqs[] = {5, 9, 10, 11, 7, -1}; -#else - static int possible_irqs[] = {9, 10, 11, 7, -1}; -#endif /* OPTi93X */ - static int possible_mpu_irqs[] = {5, 9, 10, 7, -1}; - static int possible_dma1s[] = {3, 1, 0, -1}; -#if defined(CS4231) || defined(OPTi93X) - static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}}; -#endif /* CS4231 || OPTi93X */ - - if (mpu_port == SNDRV_AUTO_PORT) { - if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) { - snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); - return -EBUSY; - } - } - if (irq == SNDRV_AUTO_IRQ) { - if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (mpu_irq == SNDRV_AUTO_IRQ) { - if ((mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) { - snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); - return -EBUSY; - } - } - if (dma1 == SNDRV_AUTO_DMA) { - if ((dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) { - snd_printk(KERN_ERR "unable to find a free DMA1\n"); - return -EBUSY; - } - } -#if defined(CS4231) || defined(OPTi93X) - if (dma2 == SNDRV_AUTO_DMA) { - if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) { - snd_printk(KERN_ERR "unable to find a free DMA2\n"); - return -EBUSY; - } - } -#endif - - error = snd_opti9xx_card_new(&card); - if (error < 0) - return error; - - if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, devptr); - if ((error = snd_opti9xx_probe(card)) < 0) { - snd_card_free(card); - return error; - } - dev_set_drvdata(devptr, card); - return 0; -} - -static int __devexit snd_opti9xx_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -static struct isa_driver snd_opti9xx_driver = { - .match = snd_opti9xx_isa_match, - .probe = snd_opti9xx_isa_probe, - .remove = __devexit_p(snd_opti9xx_isa_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DEV_NAME - }, -}; - -#ifdef CONFIG_PNP -static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - struct snd_card *card; - int error, hw; - struct snd_opti9xx *chip; - - if (snd_opti9xx_pnp_is_probed) - return -EBUSY; - if (! isapnp) - return -ENODEV; - error = snd_opti9xx_card_new(&card); - if (error < 0) - return error; - chip = card->private_data; - - hw = snd_card_opti9xx_pnp(chip, pcard, pid); - switch (hw) { - case 0x0924: - hw = OPTi9XX_HW_82C924; - break; - case 0x0925: - hw = OPTi9XX_HW_82C925; - break; - case 0x0931: - hw = OPTi9XX_HW_82C931; - break; - default: - snd_card_free(card); - return -ENODEV; - } - - if ((error = snd_opti9xx_init(chip, hw))) { - snd_card_free(card); - return error; - } - error = snd_opti9xx_read_check(chip); - if (error) { - snd_printk(KERN_ERR "OPTI chip not found\n"); - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((error = snd_opti9xx_probe(card)) < 0) { - snd_card_free(card); - return error; - } - pnp_set_card_drvdata(pcard, card); - snd_opti9xx_pnp_is_probed = 1; - return 0; -} - -static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); - snd_opti9xx_pnp_is_probed = 0; -} - -static struct pnp_card_driver opti9xx_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "opti9xx", - .id_table = snd_opti9xx_pnpids, - .probe = snd_opti9xx_pnp_probe, - .remove = __devexit_p(snd_opti9xx_pnp_remove), -}; -#endif - -#ifdef OPTi93X -#define CHIP_NAME "82C93x" -#else -#define CHIP_NAME "82C92x" -#endif - -static int __init alsa_card_opti9xx_init(void) -{ -#ifdef CONFIG_PNP - pnp_register_card_driver(&opti9xx_pnpc_driver); - if (snd_opti9xx_pnp_is_probed) - return 0; - pnp_unregister_card_driver(&opti9xx_pnpc_driver); -#endif - return isa_register_driver(&snd_opti9xx_driver, 1); -} - -static void __exit alsa_card_opti9xx_exit(void) -{ - if (!snd_opti9xx_pnp_is_probed) { - isa_unregister_driver(&snd_opti9xx_driver); - return; - } -#ifdef CONFIG_PNP - pnp_unregister_card_driver(&opti9xx_pnpc_driver); -#endif -} - -module_init(alsa_card_opti9xx_init) -module_exit(alsa_card_opti9xx_exit) diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-cs4231.c b/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-cs4231.c deleted file mode 100644 index b17ab19f..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-cs4231.c +++ /dev/null @@ -1,2 +0,0 @@ -#define CS4231 -#include "opti92x-ad1848.c" diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/opti93x.c b/ANDROID_3.4.5/sound/isa/opti9xx/opti93x.c deleted file mode 100644 index bad9da52..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/opti93x.c +++ /dev/null @@ -1,3 +0,0 @@ -#define OPTi93X -#include "opti92x-ad1848.c" - diff --git a/ANDROID_3.4.5/sound/isa/sb/Makefile b/ANDROID_3.4.5/sound/isa/sb/Makefile deleted file mode 100644 index 08b9fb97..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-sb-common-objs := sb_common.o sb_mixer.o -snd-sb8-dsp-objs := sb8_main.o sb8_midi.o -snd-sb16-dsp-objs := sb16_main.o -snd-sb16-csp-objs := sb16_csp.o -snd-sb8-objs := sb8.o -snd-sb16-objs := sb16.o -snd-sbawe-objs := sbawe.o emu8000.o -snd-emu8000-synth-objs := emu8000_synth.o emu8000_callback.o emu8000_patch.o emu8000_pcm.o -snd-jazz16-objs := jazz16.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_SB_COMMON) += snd-sb-common.o -obj-$(CONFIG_SND_SB16_DSP) += snd-sb16-dsp.o -obj-$(CONFIG_SND_SB8_DSP) += snd-sb8-dsp.o -obj-$(CONFIG_SND_SB8) += snd-sb8.o -obj-$(CONFIG_SND_SB16) += snd-sb16.o -obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o -obj-$(CONFIG_SND_JAZZ16) += snd-jazz16.o -ifeq ($(CONFIG_SND_SB16_CSP),y) - obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o - obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o -endif -obj-$(CONFIG_SND_SBAWE_SEQ) += snd-emu8000-synth.o diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000.c b/ANDROID_3.4.5/sound/isa/sb/emu8000.c deleted file mode 100644 index 71887874..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000.c +++ /dev/null @@ -1,1163 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * and (c) 1999 Steve Ratcliffe - * Copyright (C) 1999-2000 Takashi Iwai - * - * Routines for control of EMU8000 chip - * - * 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 -#include -#include -#include -#include -#include - -/* - * emu8000 register controls - */ - -/* - * The following routines read and write registers on the emu8000. They - * should always be called via the EMU8000*READ/WRITE macros and never - * directly. The macros handle the port number and command word. - */ -/* Write a word */ -void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); - if (reg != emu->last_reg) { - outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ - emu->last_reg = reg; - } - outw((unsigned short)val, port); /* Send data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); -} - -/* Read a word */ -unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg) -{ - unsigned short res; - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); - if (reg != emu->last_reg) { - outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ - emu->last_reg = reg; - } - res = inw(port); /* Read data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); - return res; -} - -/* Write a double word */ -void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); - if (reg != emu->last_reg) { - outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ - emu->last_reg = reg; - } - outw((unsigned short)val, port); /* Send low word of data */ - outw((unsigned short)(val>>16), port+2); /* Send high word of data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); -} - -/* Read a double word */ -unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg) -{ - unsigned short low; - unsigned int res; - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); - if (reg != emu->last_reg) { - outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ - emu->last_reg = reg; - } - low = inw(port); /* Read low word of data */ - res = low + (inw(port+2) << 16); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return res; -} - -/* - * Set up / close a channel to be used for DMA. - */ -/*exported*/ void -snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode) -{ - unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0; - mode &= EMU8000_RAM_MODE_MASK; - if (mode == EMU8000_RAM_CLOSE) { - EMU8000_CCCA_WRITE(emu, ch, 0); - EMU8000_DCYSUSV_WRITE(emu, ch, 0x807F); - return; - } - EMU8000_DCYSUSV_WRITE(emu, ch, 0x80); - EMU8000_VTFT_WRITE(emu, ch, 0); - EMU8000_CVCF_WRITE(emu, ch, 0); - EMU8000_PTRX_WRITE(emu, ch, 0x40000000); - EMU8000_CPF_WRITE(emu, ch, 0x40000000); - EMU8000_PSST_WRITE(emu, ch, 0); - EMU8000_CSL_WRITE(emu, ch, 0); - if (mode == EMU8000_RAM_WRITE) /* DMA write */ - EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit); - else /* DMA read */ - EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit); -} - -/* - */ -static void __devinit -snd_emu8000_read_wait(struct snd_emu8000 *emu) -{ - while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } -} - -/* - */ -static void __devinit -snd_emu8000_write_wait(struct snd_emu8000 *emu) -{ - while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } -} - -/* - * detect a card at the given port - */ -static int __devinit -snd_emu8000_detect(struct snd_emu8000 *emu) -{ - /* Initialise */ - EMU8000_HWCF1_WRITE(emu, 0x0059); - EMU8000_HWCF2_WRITE(emu, 0x0020); - EMU8000_HWCF3_WRITE(emu, 0x0000); - /* Check for a recognisable emu8000 */ - /* - if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c) - return -ENODEV; - */ - if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058) - return -ENODEV; - if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003) - return -ENODEV; - - snd_printdd("EMU8000 [0x%lx]: Synth chip found\n", - emu->port1); - return 0; -} - - -/* - * intiailize audio channels - */ -static void __devinit -init_audio(struct snd_emu8000 *emu) -{ - int ch; - - /* turn off envelope engines */ - for (ch = 0; ch < EMU8000_CHANNELS; ch++) - EMU8000_DCYSUSV_WRITE(emu, ch, 0x80); - - /* reset all other parameters to zero */ - for (ch = 0; ch < EMU8000_CHANNELS; ch++) { - EMU8000_ENVVOL_WRITE(emu, ch, 0); - EMU8000_ENVVAL_WRITE(emu, ch, 0); - EMU8000_DCYSUS_WRITE(emu, ch, 0); - EMU8000_ATKHLDV_WRITE(emu, ch, 0); - EMU8000_LFO1VAL_WRITE(emu, ch, 0); - EMU8000_ATKHLD_WRITE(emu, ch, 0); - EMU8000_LFO2VAL_WRITE(emu, ch, 0); - EMU8000_IP_WRITE(emu, ch, 0); - EMU8000_IFATN_WRITE(emu, ch, 0); - EMU8000_PEFE_WRITE(emu, ch, 0); - EMU8000_FMMOD_WRITE(emu, ch, 0); - EMU8000_TREMFRQ_WRITE(emu, ch, 0); - EMU8000_FM2FRQ2_WRITE(emu, ch, 0); - EMU8000_PTRX_WRITE(emu, ch, 0); - EMU8000_VTFT_WRITE(emu, ch, 0); - EMU8000_PSST_WRITE(emu, ch, 0); - EMU8000_CSL_WRITE(emu, ch, 0); - EMU8000_CCCA_WRITE(emu, ch, 0); - } - - for (ch = 0; ch < EMU8000_CHANNELS; ch++) { - EMU8000_CPF_WRITE(emu, ch, 0); - EMU8000_CVCF_WRITE(emu, ch, 0); - } -} - - -/* - * initialize DMA address - */ -static void __devinit -init_dma(struct snd_emu8000 *emu) -{ - EMU8000_SMALR_WRITE(emu, 0); - EMU8000_SMARR_WRITE(emu, 0); - EMU8000_SMALW_WRITE(emu, 0); - EMU8000_SMARW_WRITE(emu, 0); -} - -/* - * initialization arrays; from ADIP - */ -static unsigned short init1[128] /*__devinitdata*/ = { - 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330, - 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730, - 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30, - 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30, - - 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330, - 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730, - 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30, - 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30, - - 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330, - 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730, - 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30, - 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30, - - 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330, - 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730, - 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30, - 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30, -}; - -static unsigned short init2[128] /*__devinitdata*/ = { - 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330, - 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730, - 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30, - 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30, - - 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330, - 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730, - 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30, - 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30, - - 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330, - 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730, - 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30, - 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30, - - 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330, - 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730, - 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30, - 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30, -}; - -static unsigned short init3[128] /*__devinitdata*/ = { - 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, - 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254, - 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234, - 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224, - - 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254, - 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264, - 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294, - 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3, - - 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287, - 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7, - 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386, - 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55, - - 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308, - 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F, - 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319, - 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570, -}; - -static unsigned short init4[128] /*__devinitdata*/ = { - 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, - 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254, - 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234, - 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224, - - 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254, - 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264, - 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294, - 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3, - - 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287, - 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7, - 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386, - 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55, - - 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308, - 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F, - 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319, - 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570, -}; - -/* send an initialization array - * Taken from the oss driver, not obvious from the doc how this - * is meant to work - */ -static void __devinit -send_array(struct snd_emu8000 *emu, unsigned short *data, int size) -{ - int i; - unsigned short *p; - - p = data; - for (i = 0; i < size; i++, p++) - EMU8000_INIT1_WRITE(emu, i, *p); - for (i = 0; i < size; i++, p++) - EMU8000_INIT2_WRITE(emu, i, *p); - for (i = 0; i < size; i++, p++) - EMU8000_INIT3_WRITE(emu, i, *p); - for (i = 0; i < size; i++, p++) - EMU8000_INIT4_WRITE(emu, i, *p); -} - - -/* - * Send initialization arrays to start up, this just follows the - * initialisation sequence in the adip. - */ -static void __devinit -init_arrays(struct snd_emu8000 *emu) -{ - send_array(emu, init1, ARRAY_SIZE(init1)/4); - - msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */ - send_array(emu, init2, ARRAY_SIZE(init2)/4); - send_array(emu, init3, ARRAY_SIZE(init3)/4); - - EMU8000_HWCF4_WRITE(emu, 0); - EMU8000_HWCF5_WRITE(emu, 0x83); - EMU8000_HWCF6_WRITE(emu, 0x8000); - - send_array(emu, init4, ARRAY_SIZE(init4)/4); -} - - -#define UNIQUE_ID1 0xa5b9 -#define UNIQUE_ID2 0x9d53 - -/* - * Size the onboard memory. - * This is written so as not to need arbitrary delays after the write. It - * seems that the only way to do this is to use the one channel and keep - * reallocating between read and write. - */ -static void __devinit -size_dram(struct snd_emu8000 *emu) -{ - int i, size, detected_size; - - if (emu->dram_checked) - return; - - size = 0; - detected_size = 0; - - /* write out a magic number */ - snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE); - snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ); - EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET); - EMU8000_SMLD_WRITE(emu, UNIQUE_ID1); - snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */ - - while (size < EMU8000_MAX_DRAM) { - - size += 512 * 1024; /* increment 512kbytes */ - - /* Write a unique data on the test address. - * if the address is out of range, the data is written on - * 0x200000(=EMU8000_DRAM_OFFSET). Then the id word is - * changed by this data. - */ - /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/ - EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1)); - EMU8000_SMLD_WRITE(emu, UNIQUE_ID2); - snd_emu8000_write_wait(emu); - - /* - * read the data on the just written DRAM address - * if not the same then we have reached the end of ram. - */ - /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/ - EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1)); - /*snd_emu8000_read_wait(emu);*/ - EMU8000_SMLD_READ(emu); /* discard stale data */ - if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2) - break; /* no memory at this address */ - - detected_size = size; - - snd_emu8000_read_wait(emu); - - /* - * If it is the same it could be that the address just - * wraps back to the beginning; so check to see if the - * initial value has been overwritten. - */ - EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET); - EMU8000_SMLD_READ(emu); /* discard stale data */ - if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1) - break; /* we must have wrapped around */ - snd_emu8000_read_wait(emu); - } - - /* wait until FULL bit in SMAxW register is false */ - for (i = 0; i < 10000; i++) { - if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0) - break; - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } - snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE); - snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE); - - snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n", - emu->port1, detected_size/1024); - - emu->mem_size = detected_size; - emu->dram_checked = 1; -} - - -/* - * Initiailise the FM section. You have to do this to use sample RAM - * and therefore lose 2 voices. - */ -/*exported*/ void -snd_emu8000_init_fm(struct snd_emu8000 *emu) -{ - unsigned long flags; - - /* Initialize the last two channels for DRAM refresh and producing - the reverb and chorus effects for Yamaha OPL-3 synthesizer */ - - /* 31: FM left channel, 0xffffe0-0xffffe8 */ - EMU8000_DCYSUSV_WRITE(emu, 30, 0x80); - EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */ - EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24)); - EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8)); - EMU8000_CPF_WRITE(emu, 30, 0); - EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3); - - /* 32: FM right channel, 0xfffff0-0xfffff8 */ - EMU8000_DCYSUSV_WRITE(emu, 31, 0x80); - EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */ - EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24)); - EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8)); - EMU8000_CPF_WRITE(emu, 31, 0x8000); - EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3); - - snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0); - - spin_lock_irqsave(&emu->reg_lock, flags); - while (!(inw(EMU8000_PTR(emu)) & 0x1000)) - ; - while ((inw(EMU8000_PTR(emu)) & 0x1000)) - ; - spin_unlock_irqrestore(&emu->reg_lock, flags); - snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828); - /* this is really odd part.. */ - outb(0x3C, EMU8000_PTR(emu)); - outb(0, EMU8000_DATA1(emu)); - - /* skew volume & cutoff */ - EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF); - EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF); -} - - -/* - * The main initialization routine. - */ -static void __devinit -snd_emu8000_init_hw(struct snd_emu8000 *emu) -{ - int i; - - emu->last_reg = 0xffff; /* reset the last register index */ - - /* initialize hardware configuration */ - EMU8000_HWCF1_WRITE(emu, 0x0059); - EMU8000_HWCF2_WRITE(emu, 0x0020); - - /* disable audio; this seems to reduce a clicking noise a bit.. */ - EMU8000_HWCF3_WRITE(emu, 0); - - /* initialize audio channels */ - init_audio(emu); - - /* initialize DMA */ - init_dma(emu); - - /* initialize init arrays */ - init_arrays(emu); - - /* - * Initialize the FM section of the AWE32, this is needed - * for DRAM refresh as well - */ - snd_emu8000_init_fm(emu); - - /* terminate all voices */ - for (i = 0; i < EMU8000_DRAM_VOICES; i++) - EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F); - - /* check DRAM memory size */ - size_dram(emu); - - /* enable audio */ - EMU8000_HWCF3_WRITE(emu, 0x4); - - /* set equzlier, chorus and reverb modes */ - snd_emu8000_update_equalizer(emu); - snd_emu8000_update_chorus_mode(emu); - snd_emu8000_update_reverb_mode(emu); -} - - -/*---------------------------------------------------------------- - * Bass/Treble Equalizer - *----------------------------------------------------------------*/ - -static unsigned short bass_parm[12][3] = { - {0xD26A, 0xD36A, 0x0000}, /* -12 dB */ - {0xD25B, 0xD35B, 0x0000}, /* -8 */ - {0xD24C, 0xD34C, 0x0000}, /* -6 */ - {0xD23D, 0xD33D, 0x0000}, /* -4 */ - {0xD21F, 0xD31F, 0x0000}, /* -2 */ - {0xC208, 0xC308, 0x0001}, /* 0 (HW default) */ - {0xC219, 0xC319, 0x0001}, /* +2 */ - {0xC22A, 0xC32A, 0x0001}, /* +4 */ - {0xC24C, 0xC34C, 0x0001}, /* +6 */ - {0xC26E, 0xC36E, 0x0001}, /* +8 */ - {0xC248, 0xC384, 0x0002}, /* +10 */ - {0xC26A, 0xC36A, 0x0002}, /* +12 dB */ -}; - -static unsigned short treble_parm[12][9] = { - {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */ - {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */ - {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, - {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002} /* +12 dB */ -}; - - -/* - * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB] - */ -/*exported*/ void -snd_emu8000_update_equalizer(struct snd_emu8000 *emu) -{ - unsigned short w; - int bass = emu->bass_level; - int treble = emu->treble_level; - - if (bass < 0 || bass > 11 || treble < 0 || treble > 11) - return; - EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]); - EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]); - EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]); - EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]); - EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]); - EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]); - EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]); - EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]); - EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]); - EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]); - w = bass_parm[bass][2] + treble_parm[treble][8]; - EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262)); - EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362)); -} - - -/*---------------------------------------------------------------- - * Chorus mode control - *----------------------------------------------------------------*/ - -/* - * chorus mode parameters - */ -#define SNDRV_EMU8000_CHORUS_1 0 -#define SNDRV_EMU8000_CHORUS_2 1 -#define SNDRV_EMU8000_CHORUS_3 2 -#define SNDRV_EMU8000_CHORUS_4 3 -#define SNDRV_EMU8000_CHORUS_FEEDBACK 4 -#define SNDRV_EMU8000_CHORUS_FLANGER 5 -#define SNDRV_EMU8000_CHORUS_SHORTDELAY 6 -#define SNDRV_EMU8000_CHORUS_SHORTDELAY2 7 -#define SNDRV_EMU8000_CHORUS_PREDEFINED 8 -/* user can define chorus modes up to 32 */ -#define SNDRV_EMU8000_CHORUS_NUMBERS 32 - -struct soundfont_chorus_fx { - unsigned short feedback; /* feedback level (0xE600-0xE6FF) */ - unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */ - unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */ - unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */ - unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */ -}; - -/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */ -static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS]; -static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = { - {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */ - {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */ - {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */ - {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */ - {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */ - {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */ - {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */ - {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */ -}; - -/*exported*/ int -snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len) -{ - struct soundfont_chorus_fx rec; - if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) { - snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode); - return -EINVAL; - } - if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec))) - return -EFAULT; - chorus_parm[mode] = rec; - chorus_defined[mode] = 1; - return 0; -} - -/*exported*/ void -snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu) -{ - int effect = emu->chorus_mode; - if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS || - (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect])) - return; - EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback); - EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset); - EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth); - EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay); - EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq); - EMU8000_HWCF6_WRITE(emu, 0x8000); - EMU8000_HWCF7_WRITE(emu, 0x0000); -} - -/*---------------------------------------------------------------- - * Reverb mode control - *----------------------------------------------------------------*/ - -/* - * reverb mode parameters - */ -#define SNDRV_EMU8000_REVERB_ROOM1 0 -#define SNDRV_EMU8000_REVERB_ROOM2 1 -#define SNDRV_EMU8000_REVERB_ROOM3 2 -#define SNDRV_EMU8000_REVERB_HALL1 3 -#define SNDRV_EMU8000_REVERB_HALL2 4 -#define SNDRV_EMU8000_REVERB_PLATE 5 -#define SNDRV_EMU8000_REVERB_DELAY 6 -#define SNDRV_EMU8000_REVERB_PANNINGDELAY 7 -#define SNDRV_EMU8000_REVERB_PREDEFINED 8 -/* user can define reverb modes up to 32 */ -#define SNDRV_EMU8000_REVERB_NUMBERS 32 - -struct soundfont_reverb_fx { - unsigned short parms[28]; -}; - -/* reverb mode settings; write the following 28 data of 16 bit length - * on the corresponding ports in the reverb_cmds array - */ -static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS]; -static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = { -{{ /* room 1 */ - 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4, - 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516, - 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* room 2 */ - 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* room 3 */ - 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516, - 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B, - 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A, -}}, -{{ /* hall 1 */ - 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A, - 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529, -}}, -{{ /* hall 2 */ - 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254, - 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3, - 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* plate */ - 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234, - 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* delay */ - 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204, - 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, - 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, - 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, -}}, -{{ /* panning delay */ - 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204, - 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, - 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, - 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, -}}, -}; - -enum { DATA1, DATA2 }; -#define AWE_INIT1(c) EMU8000_CMD(2,c), DATA1 -#define AWE_INIT2(c) EMU8000_CMD(2,c), DATA2 -#define AWE_INIT3(c) EMU8000_CMD(3,c), DATA1 -#define AWE_INIT4(c) EMU8000_CMD(3,c), DATA2 - -static struct reverb_cmd_pair { - unsigned short cmd, port; -} reverb_cmds[28] = { - {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)}, - {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)}, - {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)}, - {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)}, - {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)}, - {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)}, - {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)}, -}; - -/*exported*/ int -snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len) -{ - struct soundfont_reverb_fx rec; - - if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) { - snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode); - return -EINVAL; - } - if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec))) - return -EFAULT; - reverb_parm[mode] = rec; - reverb_defined[mode] = 1; - return 0; -} - -/*exported*/ void -snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu) -{ - int effect = emu->reverb_mode; - int i; - - if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS || - (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect])) - return; - for (i = 0; i < 28; i++) { - int port; - if (reverb_cmds[i].port == DATA1) - port = EMU8000_DATA1(emu); - else - port = EMU8000_DATA2(emu); - snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]); - } -} - - -/*---------------------------------------------------------------- - * mixer interface - *----------------------------------------------------------------*/ - -/* - * bass/treble - */ -static int mixer_bass_treble_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 11; - return 0; -} - -static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level; - return 0; -} - -static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1; - - val1 = ucontrol->value.integer.value[0] % 12; - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - change = val1 != emu->treble_level; - emu->treble_level = val1; - } else { - change = val1 != emu->bass_level; - emu->bass_level = val1; - } - spin_unlock_irqrestore(&emu->control_lock, flags); - snd_emu8000_update_equalizer(emu); - return change; -} - -static struct snd_kcontrol_new mixer_bass_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Synth Tone Control - Bass", - .info = mixer_bass_treble_info, - .get = mixer_bass_treble_get, - .put = mixer_bass_treble_put, - .private_value = 0, -}; - -static struct snd_kcontrol_new mixer_treble_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Synth Tone Control - Treble", - .info = mixer_bass_treble_info, - .get = mixer_bass_treble_get, - .put = mixer_bass_treble_put, - .private_value = 1, -}; - -/* - * chorus/reverb mode - */ -static int mixer_chorus_reverb_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1); - return 0; -} - -static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode; - return 0; -} - -static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1; - - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS; - change = val1 != emu->chorus_mode; - emu->chorus_mode = val1; - } else { - val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS; - change = val1 != emu->reverb_mode; - emu->reverb_mode = val1; - } - spin_unlock_irqrestore(&emu->control_lock, flags); - if (change) { - if (kcontrol->private_value) - snd_emu8000_update_chorus_mode(emu); - else - snd_emu8000_update_reverb_mode(emu); - } - return change; -} - -static struct snd_kcontrol_new mixer_chorus_mode_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Chorus Mode", - .info = mixer_chorus_reverb_info, - .get = mixer_chorus_reverb_get, - .put = mixer_chorus_reverb_put, - .private_value = 1, -}; - -static struct snd_kcontrol_new mixer_reverb_mode_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Reverb Mode", - .info = mixer_chorus_reverb_info, - .get = mixer_chorus_reverb_get, - .put = mixer_chorus_reverb_put, - .private_value = 0, -}; - -/* - * FM OPL3 chorus/reverb depth - */ -static int mixer_fm_depth_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth; - return 0; -} - -static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1; - - val1 = ucontrol->value.integer.value[0] % 256; - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - change = val1 != emu->fm_chorus_depth; - emu->fm_chorus_depth = val1; - } else { - change = val1 != emu->fm_reverb_depth; - emu->fm_reverb_depth = val1; - } - spin_unlock_irqrestore(&emu->control_lock, flags); - if (change) - snd_emu8000_init_fm(emu); - return change; -} - -static struct snd_kcontrol_new mixer_fm_chorus_depth_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "FM Chorus Depth", - .info = mixer_fm_depth_info, - .get = mixer_fm_depth_get, - .put = mixer_fm_depth_put, - .private_value = 1, -}; - -static struct snd_kcontrol_new mixer_fm_reverb_depth_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "FM Reverb Depth", - .info = mixer_fm_depth_info, - .get = mixer_fm_depth_get, - .put = mixer_fm_depth_put, - .private_value = 0, -}; - - -static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = { - &mixer_bass_control, - &mixer_treble_control, - &mixer_chorus_mode_control, - &mixer_reverb_mode_control, - &mixer_fm_chorus_depth_control, - &mixer_fm_reverb_depth_control, -}; - -/* - * create and attach mixer elements for WaveTable treble/bass controls - */ -static int __devinit -snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) -{ - int i, err = 0; - - if (snd_BUG_ON(!emu || !card)) - return -EINVAL; - - spin_lock_init(&emu->control_lock); - - memset(emu->controls, 0, sizeof(emu->controls)); - for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { - if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0) - goto __error; - } - return 0; - -__error: - for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { - down_write(&card->controls_rwsem); - if (emu->controls[i]) - snd_ctl_remove(card, emu->controls[i]); - up_write(&card->controls_rwsem); - } - return err; -} - - -/* - * free resources - */ -static int snd_emu8000_free(struct snd_emu8000 *hw) -{ - release_and_free_resource(hw->res_port1); - release_and_free_resource(hw->res_port2); - release_and_free_resource(hw->res_port3); - kfree(hw); - return 0; -} - -/* - */ -static int snd_emu8000_dev_free(struct snd_device *device) -{ - struct snd_emu8000 *hw = device->device_data; - return snd_emu8000_free(hw); -} - -/* - * initialize and register emu8000 synth device. - */ -int __devinit -snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, - struct snd_seq_device **awe_ret) -{ - struct snd_seq_device *awe; - struct snd_emu8000 *hw; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_emu8000_dev_free, - }; - - if (awe_ret) - *awe_ret = NULL; - - if (seq_ports <= 0) - return 0; - - hw = kzalloc(sizeof(*hw), GFP_KERNEL); - if (hw == NULL) - return -ENOMEM; - spin_lock_init(&hw->reg_lock); - hw->index = index; - hw->port1 = port; - hw->port2 = port + 0x400; - hw->port3 = port + 0x800; - if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) || - !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) || - !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) { - snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3); - snd_emu8000_free(hw); - return -EBUSY; - } - hw->mem_size = 0; - hw->card = card; - hw->seq_ports = seq_ports; - hw->bass_level = 5; - hw->treble_level = 9; - hw->chorus_mode = 2; - hw->reverb_mode = 4; - hw->fm_chorus_depth = 0; - hw->fm_reverb_depth = 0; - - if (snd_emu8000_detect(hw) < 0) { - snd_emu8000_free(hw); - return -ENODEV; - } - - snd_emu8000_init_hw(hw); - if ((err = snd_emu8000_create_mixer(card, hw)) < 0) { - snd_emu8000_free(hw); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) { - snd_emu8000_free(hw); - return err; - } -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000, - sizeof(struct snd_emu8000*), &awe) >= 0) { - strcpy(awe->name, "EMU-8000"); - *(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw; - } -#else - awe = NULL; -#endif - if (awe_ret) - *awe_ret = awe; - - return 0; -} - - -/* - * exported stuff - */ - -EXPORT_SYMBOL(snd_emu8000_poke); -EXPORT_SYMBOL(snd_emu8000_peek); -EXPORT_SYMBOL(snd_emu8000_poke_dw); -EXPORT_SYMBOL(snd_emu8000_peek_dw); -EXPORT_SYMBOL(snd_emu8000_dma_chan); -EXPORT_SYMBOL(snd_emu8000_init_fm); -EXPORT_SYMBOL(snd_emu8000_load_chorus_fx); -EXPORT_SYMBOL(snd_emu8000_load_reverb_fx); -EXPORT_SYMBOL(snd_emu8000_update_chorus_mode); -EXPORT_SYMBOL(snd_emu8000_update_reverb_mode); -EXPORT_SYMBOL(snd_emu8000_update_equalizer); diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_callback.c b/ANDROID_3.4.5/sound/isa/sb/emu8000_callback.c deleted file mode 100644 index 344b4355..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_callback.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * synth callback routines for the emu8000 (AWE32/64) - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (C) 1999-2000 Takashi Iwai - * - * 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 "emu8000_local.h" -#include -#include - -/* - * prototypes - */ -static struct snd_emux_voice *get_voice(struct snd_emux *emu, - struct snd_emux_port *port); -static int start_voice(struct snd_emux_voice *vp); -static void trigger_voice(struct snd_emux_voice *vp); -static void release_voice(struct snd_emux_voice *vp); -static void update_voice(struct snd_emux_voice *vp, int update); -static void reset_voice(struct snd_emux *emu, int ch); -static void terminate_voice(struct snd_emux_voice *vp); -static void sysex(struct snd_emux *emu, char *buf, int len, int parsed, - struct snd_midi_channel_set *chset); -#ifdef CONFIG_SND_SEQUENCER_OSS -static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2); -#endif -static int load_fx(struct snd_emux *emu, int type, int mode, - const void __user *buf, long len); - -static void set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int ch); - -/* - * Ensure a value is between two points - * macro evaluates its args more than once, so changed to upper-case. - */ -#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0) -#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0) - - -/* - * set up operators - */ -static struct snd_emux_operators emu8000_ops = { - .owner = THIS_MODULE, - .get_voice = get_voice, - .prepare = start_voice, - .trigger = trigger_voice, - .release = release_voice, - .update = update_voice, - .terminate = terminate_voice, - .reset = reset_voice, - .sample_new = snd_emu8000_sample_new, - .sample_free = snd_emu8000_sample_free, - .sample_reset = snd_emu8000_sample_reset, - .load_fx = load_fx, - .sysex = sysex, -#ifdef CONFIG_SND_SEQUENCER_OSS - .oss_ioctl = oss_ioctl, -#endif -}; - -void -snd_emu8000_ops_setup(struct snd_emu8000 *hw) -{ - hw->emu->ops = emu8000_ops; -} - - - -/* - * Terminate a voice - */ -static void -release_voice(struct snd_emux_voice *vp) -{ - int dcysusv; - struct snd_emu8000 *hw; - - hw = vp->hw; - dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease; - EMU8000_DCYSUS_WRITE(hw, vp->ch, dcysusv); - dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease; - EMU8000_DCYSUSV_WRITE(hw, vp->ch, dcysusv); -} - - -/* - */ -static void -terminate_voice(struct snd_emux_voice *vp) -{ - struct snd_emu8000 *hw; - - hw = vp->hw; - EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F); -} - - -/* - */ -static void -update_voice(struct snd_emux_voice *vp, int update) -{ - struct snd_emu8000 *hw; - - hw = vp->hw; - if (update & SNDRV_EMUX_UPDATE_VOLUME) - set_volume(hw, vp); - if (update & SNDRV_EMUX_UPDATE_PITCH) - set_pitch(hw, vp); - if ((update & SNDRV_EMUX_UPDATE_PAN) && - vp->port->ctrls[EMUX_MD_REALTIME_PAN]) - set_pan(hw, vp); - if (update & SNDRV_EMUX_UPDATE_FMMOD) - set_fmmod(hw, vp); - if (update & SNDRV_EMUX_UPDATE_TREMFREQ) - set_tremfreq(hw, vp); - if (update & SNDRV_EMUX_UPDATE_FM2FRQ2) - set_fm2frq2(hw, vp); - if (update & SNDRV_EMUX_UPDATE_Q) - set_filterQ(hw, vp); -} - - -/* - * Find a channel (voice) within the EMU that is not in use or at least - * less in use than other channels. Always returns a valid pointer - * no matter what. If there is a real shortage of voices then one - * will be cut. Such is life. - * - * The channel index (vp->ch) must be initialized in this routine. - * In Emu8k, it is identical with the array index. - */ -static struct snd_emux_voice * -get_voice(struct snd_emux *emu, struct snd_emux_port *port) -{ - int i; - struct snd_emux_voice *vp; - struct snd_emu8000 *hw; - - /* what we are looking for, in order of preference */ - enum { - OFF=0, RELEASED, PLAYING, END - }; - - /* Keeps track of what we are finding */ - struct best { - unsigned int time; - int voice; - } best[END]; - struct best *bp; - - hw = emu->hw; - - for (i = 0; i < END; i++) { - best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */; - best[i].voice = -1; - } - - /* - * Go through them all and get a best one to use. - */ - for (i = 0; i < emu->max_voices; i++) { - int state, val; - - vp = &emu->voices[i]; - state = vp->state; - - if (state == SNDRV_EMUX_ST_OFF) - bp = best + OFF; - else if (state == SNDRV_EMUX_ST_RELEASED || - state == SNDRV_EMUX_ST_PENDING) { - bp = best + RELEASED; - val = (EMU8000_CVCF_READ(hw, vp->ch) >> 16) & 0xffff; - if (! val) - bp = best + OFF; - } - else if (state & SNDRV_EMUX_ST_ON) - bp = best + PLAYING; - else - continue; - - /* check if sample is finished playing (non-looping only) */ - if (state != SNDRV_EMUX_ST_OFF && - (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) { - val = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff; - if (val >= vp->reg.loopstart) - bp = best + OFF; - } - - if (vp->time < bp->time) { - bp->time = vp->time; - bp->voice = i; - } - } - - for (i = 0; i < END; i++) { - if (best[i].voice >= 0) { - vp = &emu->voices[best[i].voice]; - vp->ch = best[i].voice; - return vp; - } - } - - /* not found */ - return NULL; -} - -/* - */ -static int -start_voice(struct snd_emux_voice *vp) -{ - unsigned int temp; - int ch; - int addr; - struct snd_midi_channel *chan; - struct snd_emu8000 *hw; - - hw = vp->hw; - ch = vp->ch; - chan = vp->chan; - - /* channel to be silent and idle */ - EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080); - EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF); - EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF); - EMU8000_PTRX_WRITE(hw, ch, 0); - EMU8000_CPF_WRITE(hw, ch, 0); - - /* set pitch offset */ - set_pitch(hw, vp); - - /* set envelope parameters */ - EMU8000_ENVVAL_WRITE(hw, ch, vp->reg.parm.moddelay); - EMU8000_ATKHLD_WRITE(hw, ch, vp->reg.parm.modatkhld); - EMU8000_DCYSUS_WRITE(hw, ch, vp->reg.parm.moddcysus); - EMU8000_ENVVOL_WRITE(hw, ch, vp->reg.parm.voldelay); - EMU8000_ATKHLDV_WRITE(hw, ch, vp->reg.parm.volatkhld); - /* decay/sustain parameter for volume envelope is used - for triggerg the voice */ - - /* cutoff and volume */ - set_volume(hw, vp); - - /* modulation envelope heights */ - EMU8000_PEFE_WRITE(hw, ch, vp->reg.parm.pefe); - - /* lfo1/2 delay */ - EMU8000_LFO1VAL_WRITE(hw, ch, vp->reg.parm.lfo1delay); - EMU8000_LFO2VAL_WRITE(hw, ch, vp->reg.parm.lfo2delay); - - /* lfo1 pitch & cutoff shift */ - set_fmmod(hw, vp); - /* lfo1 volume & freq */ - set_tremfreq(hw, vp); - /* lfo2 pitch & freq */ - set_fm2frq2(hw, vp); - /* pan & loop start */ - set_pan(hw, vp); - - /* chorus & loop end (chorus 8bit, MSB) */ - addr = vp->reg.loopend - 1; - temp = vp->reg.parm.chorus; - temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10; - LIMITMAX(temp, 255); - temp = (temp <<24) | (unsigned int)addr; - EMU8000_CSL_WRITE(hw, ch, temp); - - /* Q & current address (Q 4bit value, MSB) */ - addr = vp->reg.start - 1; - temp = vp->reg.parm.filterQ; - temp = (temp<<28) | (unsigned int)addr; - EMU8000_CCCA_WRITE(hw, ch, temp); - - /* clear unknown registers */ - EMU8000_00A0_WRITE(hw, ch, 0); - EMU8000_0080_WRITE(hw, ch, 0); - - /* reset volume */ - temp = vp->vtarget << 16; - EMU8000_VTFT_WRITE(hw, ch, temp | vp->ftarget); - EMU8000_CVCF_WRITE(hw, ch, temp | 0xff00); - - return 0; -} - -/* - * Start envelope - */ -static void -trigger_voice(struct snd_emux_voice *vp) -{ - int ch = vp->ch; - unsigned int temp; - struct snd_emu8000 *hw; - - hw = vp->hw; - - /* set reverb and pitch target */ - temp = vp->reg.parm.reverb; - temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10; - LIMITMAX(temp, 255); - temp = (temp << 8) | (vp->ptarget << 16) | vp->aaux; - EMU8000_PTRX_WRITE(hw, ch, temp); - EMU8000_CPF_WRITE(hw, ch, vp->ptarget << 16); - EMU8000_DCYSUSV_WRITE(hw, ch, vp->reg.parm.voldcysus); -} - -/* - * reset voice parameters - */ -static void -reset_voice(struct snd_emux *emu, int ch) -{ - struct snd_emu8000 *hw; - - hw = emu->hw; - EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F); - snd_emu8000_tweak_voice(hw, ch); -} - -/* - * Set the pitch of a possibly playing note. - */ -static void -set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - EMU8000_IP_WRITE(hw, vp->ch, vp->apitch); -} - -/* - * Set the volume of a possibly already playing note - */ -static void -set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - int ifatn; - - ifatn = (unsigned char)vp->acutoff; - ifatn = (ifatn << 8); - ifatn |= (unsigned char)vp->avol; - EMU8000_IFATN_WRITE(hw, vp->ch, ifatn); -} - -/* - * Set pan and loop start address. - */ -static void -set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - unsigned int temp; - - temp = ((unsigned int)vp->apan<<24) | ((unsigned int)vp->reg.loopstart - 1); - EMU8000_PSST_WRITE(hw, vp->ch, temp); -} - -#define MOD_SENSE 18 - -static void -set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - unsigned short fmmod; - short pitch; - unsigned char cutoff; - int modulation; - - pitch = (char)(vp->reg.parm.fmmod>>8); - cutoff = (vp->reg.parm.fmmod & 0xff); - modulation = vp->chan->gm_modulation + vp->chan->midi_pressure; - pitch += (MOD_SENSE * modulation) / 1200; - LIMITVALUE(pitch, -128, 127); - fmmod = ((unsigned char)pitch<<8) | cutoff; - EMU8000_FMMOD_WRITE(hw, vp->ch, fmmod); -} - -/* set tremolo (lfo1) volume & frequency */ -static void -set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - EMU8000_TREMFRQ_WRITE(hw, vp->ch, vp->reg.parm.tremfrq); -} - -/* set lfo2 pitch & frequency */ -static void -set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - unsigned short fm2frq2; - short pitch; - unsigned char freq; - int modulation; - - pitch = (char)(vp->reg.parm.fm2frq2>>8); - freq = vp->reg.parm.fm2frq2 & 0xff; - modulation = vp->chan->gm_modulation + vp->chan->midi_pressure; - pitch += (MOD_SENSE * modulation) / 1200; - LIMITVALUE(pitch, -128, 127); - fm2frq2 = ((unsigned char)pitch<<8) | freq; - EMU8000_FM2FRQ2_WRITE(hw, vp->ch, fm2frq2); -} - -/* set filterQ */ -static void -set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - unsigned int addr; - addr = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff; - addr |= (vp->reg.parm.filterQ << 28); - EMU8000_CCCA_WRITE(hw, vp->ch, addr); -} - -/* - * set the envelope & LFO parameters to the default values - */ -static void -snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int i) -{ - /* set all mod/vol envelope shape to minimum */ - EMU8000_ENVVOL_WRITE(emu, i, 0x8000); - EMU8000_ENVVAL_WRITE(emu, i, 0x8000); - EMU8000_DCYSUS_WRITE(emu, i, 0x7F7F); - EMU8000_ATKHLDV_WRITE(emu, i, 0x7F7F); - EMU8000_ATKHLD_WRITE(emu, i, 0x7F7F); - EMU8000_PEFE_WRITE(emu, i, 0); /* mod envelope height to zero */ - EMU8000_LFO1VAL_WRITE(emu, i, 0x8000); /* no delay for LFO1 */ - EMU8000_LFO2VAL_WRITE(emu, i, 0x8000); - EMU8000_IP_WRITE(emu, i, 0xE000); /* no pitch shift */ - EMU8000_IFATN_WRITE(emu, i, 0xFF00); /* volume to minimum */ - EMU8000_FMMOD_WRITE(emu, i, 0); - EMU8000_TREMFRQ_WRITE(emu, i, 0); - EMU8000_FM2FRQ2_WRITE(emu, i, 0); -} - -/* - * sysex callback - */ -static void -sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_channel_set *chset) -{ - struct snd_emu8000 *hw; - - hw = emu->hw; - - switch (parsed) { - case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE: - hw->chorus_mode = chset->gs_chorus_mode; - snd_emu8000_update_chorus_mode(hw); - break; - - case SNDRV_MIDI_SYSEX_GS_REVERB_MODE: - hw->reverb_mode = chset->gs_reverb_mode; - snd_emu8000_update_reverb_mode(hw); - break; - } -} - - -#ifdef CONFIG_SND_SEQUENCER_OSS -/* - * OSS ioctl callback - */ -static int -oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2) -{ - struct snd_emu8000 *hw; - - hw = emu->hw; - - switch (cmd) { - case _EMUX_OSS_REVERB_MODE: - hw->reverb_mode = p1; - snd_emu8000_update_reverb_mode(hw); - break; - - case _EMUX_OSS_CHORUS_MODE: - hw->chorus_mode = p1; - snd_emu8000_update_chorus_mode(hw); - break; - - case _EMUX_OSS_INITIALIZE_CHIP: - /* snd_emu8000_init(hw); */ /*ignored*/ - break; - - case _EMUX_OSS_EQUALIZER: - hw->bass_level = p1; - hw->treble_level = p2; - snd_emu8000_update_equalizer(hw); - break; - } - return 0; -} -#endif - - -/* - * additional patch keys - */ - -#define SNDRV_EMU8000_LOAD_CHORUS_FX 0x10 /* optarg=mode */ -#define SNDRV_EMU8000_LOAD_REVERB_FX 0x11 /* optarg=mode */ - - -/* - * callback routine - */ - -static int -load_fx(struct snd_emux *emu, int type, int mode, const void __user *buf, long len) -{ - struct snd_emu8000 *hw; - hw = emu->hw; - - /* skip header */ - buf += 16; - len -= 16; - - switch (type) { - case SNDRV_EMU8000_LOAD_CHORUS_FX: - return snd_emu8000_load_chorus_fx(hw, mode, buf, len); - case SNDRV_EMU8000_LOAD_REVERB_FX: - return snd_emu8000_load_reverb_fx(hw, mode, buf, len); - } - return -EINVAL; -} - diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_local.h b/ANDROID_3.4.5/sound/isa/sb/emu8000_local.h deleted file mode 100644 index 7e87c349..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_local.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __EMU8000_LOCAL_H -#define __EMU8000_LOCAL_H -/* - * Local defininitons for the emu8000 (AWE32/64) - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (C) 1999-2000 Takashi Iwai - * - * 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 - -/* emu8000_patch.c */ -int snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *data, long count); -int snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr); -void snd_emu8000_sample_reset(struct snd_emux *rec); - -/* emu8000_callback.c */ -void snd_emu8000_ops_setup(struct snd_emu8000 *emu); - -/* emu8000_pcm.c */ -int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index); - -#endif /* __EMU8000_LOCAL_H */ diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_patch.c b/ANDROID_3.4.5/sound/isa/sb/emu8000_patch.c deleted file mode 100644 index c99c6078..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_patch.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Patch routines for the emu8000 (AWE32/64) - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (C) 1999-2000 Takashi Iwai - * - * 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 "emu8000_local.h" -#include -#include - -static int emu8000_reset_addr; -module_param(emu8000_reset_addr, int, 0444); -MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)"); - - -/* - * Open up channels. - */ -static int -snd_emu8000_open_dma(struct snd_emu8000 *emu, int write) -{ - int i; - - /* reserve all 30 voices for loading */ - for (i = 0; i < EMU8000_DRAM_VOICES; i++) { - snd_emux_lock_voice(emu->emu, i); - snd_emu8000_dma_chan(emu, i, write); - } - - /* assign voice 31 and 32 to ROM */ - EMU8000_VTFT_WRITE(emu, 30, 0); - EMU8000_PSST_WRITE(emu, 30, 0x1d8); - EMU8000_CSL_WRITE(emu, 30, 0x1e0); - EMU8000_CCCA_WRITE(emu, 30, 0x1d8); - EMU8000_VTFT_WRITE(emu, 31, 0); - EMU8000_PSST_WRITE(emu, 31, 0x1d8); - EMU8000_CSL_WRITE(emu, 31, 0x1e0); - EMU8000_CCCA_WRITE(emu, 31, 0x1d8); - - return 0; -} - -/* - * Close all dram channels. - */ -static void -snd_emu8000_close_dma(struct snd_emu8000 *emu) -{ - int i; - - for (i = 0; i < EMU8000_DRAM_VOICES; i++) { - snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE); - snd_emux_unlock_voice(emu->emu, i); - } -} - -/* - */ - -#define BLANK_LOOP_START 4 -#define BLANK_LOOP_END 8 -#define BLANK_LOOP_SIZE 12 -#define BLANK_HEAD_SIZE 48 - -/* - * Read a word from userland, taking care of conversions from - * 8bit samples etc. - */ -static unsigned short -read_word(const void __user *buf, int offset, int mode) -{ - unsigned short c; - if (mode & SNDRV_SFNT_SAMPLE_8BITS) { - unsigned char cc; - get_user(cc, (unsigned char __user *)buf + offset); - c = cc << 8; /* convert 8bit -> 16bit */ - } else { -#ifdef SNDRV_LITTLE_ENDIAN - get_user(c, (unsigned short __user *)buf + offset); -#else - unsigned short cc; - get_user(cc, (unsigned short __user *)buf + offset); - c = swab16(cc); -#endif - } - if (mode & SNDRV_SFNT_SAMPLE_UNSIGNED) - c ^= 0x8000; /* unsigned -> signed */ - return c; -} - -/* - */ -static void -snd_emu8000_write_wait(struct snd_emu8000 *emu) -{ - while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } -} - -/* - * write sample word data - * - * You should not have to keep resetting the address each time - * as the chip is supposed to step on the next address automatically. - * It mostly does, but during writes of some samples at random it - * completely loses words (every one in 16 roughly but with no - * obvious pattern). - * - * This is therefore much slower than need be, but is at least - * working. - */ -static inline void -write_word(struct snd_emu8000 *emu, int *offset, unsigned short data) -{ - if (emu8000_reset_addr) { - if (emu8000_reset_addr > 1) - snd_emu8000_write_wait(emu); - EMU8000_SMALW_WRITE(emu, *offset); - } - EMU8000_SMLD_WRITE(emu, data); - *offset += 1; -} - -/* - * Write the sample to EMU800 memory. This routine is invoked out of - * the generic soundfont routines as a callback. - */ -int -snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *data, long count) -{ - int i; - int rc; - int offset; - int truesize; - int dram_offset, dram_start; - struct snd_emu8000 *emu; - - emu = rec->hw; - if (snd_BUG_ON(!sp)) - return -EINVAL; - - if (sp->v.size == 0) - return 0; - - /* be sure loop points start < end */ - if (sp->v.loopstart > sp->v.loopend) { - int tmp = sp->v.loopstart; - sp->v.loopstart = sp->v.loopend; - sp->v.loopend = tmp; - } - - /* compute true data size to be loaded */ - truesize = sp->v.size; - if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) - truesize += sp->v.loopend - sp->v.loopstart; - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) - truesize += BLANK_LOOP_SIZE; - - sp->block = snd_util_mem_alloc(hdr, truesize * 2); - if (sp->block == NULL) { - /*snd_printd("EMU8000: out of memory\n");*/ - /* not ENOMEM (for compatibility) */ - return -ENOSPC; - } - - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) { - if (!access_ok(VERIFY_READ, data, sp->v.size)) - return -EFAULT; - } else { - if (!access_ok(VERIFY_READ, data, sp->v.size * 2)) - return -EFAULT; - } - - /* recalculate address offset */ - sp->v.end -= sp->v.start; - sp->v.loopstart -= sp->v.start; - sp->v.loopend -= sp->v.start; - sp->v.start = 0; - - /* dram position (in word) -- mem_offset is byte */ - dram_offset = EMU8000_DRAM_OFFSET + (sp->block->offset >> 1); - dram_start = dram_offset; - - /* set the total size (store onto obsolete checksum value) */ - sp->v.truesize = truesize * 2; /* in bytes */ - - snd_emux_terminate_all(emu->emu); - if ((rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE)) != 0) - return rc; - - /* Set the address to start writing at */ - snd_emu8000_write_wait(emu); - EMU8000_SMALW_WRITE(emu, dram_offset); - - /*snd_emu8000_init_fm(emu);*/ - -#if 0 - /* first block - write 48 samples for silence */ - if (! sp->block->offset) { - for (i = 0; i < BLANK_HEAD_SIZE; i++) { - write_word(emu, &dram_offset, 0); - } - } -#endif - - offset = 0; - for (i = 0; i < sp->v.size; i++) { - unsigned short s; - - s = read_word(data, offset, sp->v.mode_flags); - offset++; - write_word(emu, &dram_offset, s); - - /* we may take too long time in this loop. - * so give controls back to kernel if needed. - */ - cond_resched(); - - if (i == sp->v.loopend && - (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))) - { - int looplen = sp->v.loopend - sp->v.loopstart; - int k; - - /* copy reverse loop */ - for (k = 1; k <= looplen; k++) { - s = read_word(data, offset - k, sp->v.mode_flags); - write_word(emu, &dram_offset, s); - } - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) { - sp->v.loopend += looplen; - } else { - sp->v.loopstart += looplen; - sp->v.loopend += looplen; - } - sp->v.end += looplen; - } - } - - /* if no blank loop is attached in the sample, add it */ - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) { - for (i = 0; i < BLANK_LOOP_SIZE; i++) { - write_word(emu, &dram_offset, 0); - } - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) { - sp->v.loopstart = sp->v.end + BLANK_LOOP_START; - sp->v.loopend = sp->v.end + BLANK_LOOP_END; - } - } - - /* add dram offset */ - sp->v.start += dram_start; - sp->v.end += dram_start; - sp->v.loopstart += dram_start; - sp->v.loopend += dram_start; - - snd_emu8000_close_dma(emu); - snd_emu8000_init_fm(emu); - - return 0; -} - -/* - * free a sample block - */ -int -snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr) -{ - if (sp->block) { - snd_util_mem_free(hdr, sp->block); - sp->block = NULL; - } - return 0; -} - - -/* - * sample_reset callback - terminate voices - */ -void -snd_emu8000_sample_reset(struct snd_emux *rec) -{ - snd_emux_terminate_all(rec); -} diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_pcm.c b/ANDROID_3.4.5/sound/isa/sb/emu8000_pcm.c deleted file mode 100644 index 2f85c66f..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_pcm.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * pcm emulation on emu8000 wavetable - * - * Copyright (C) 2002 Takashi Iwai - * - * 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 "emu8000_local.h" -#include -#include -#include -#include - -/* - * define the following if you want to use this pcm with non-interleaved mode - */ -/* #define USE_NONINTERLEAVE */ - -/* NOTE: for using the non-interleaved mode with alsa-lib, you have to set - * mmap_emulation flag to 1 in your .asoundrc, such like - * - * pcm.emu8k { - * type plug - * slave.pcm { - * type hw - * card 0 - * device 1 - * mmap_emulation 1 - * } - * } - * - * besides, for the time being, the non-interleaved mode doesn't work well on - * alsa-lib... - */ - - -struct snd_emu8k_pcm { - struct snd_emu8000 *emu; - struct snd_pcm_substream *substream; - - unsigned int allocated_bytes; - struct snd_util_memblk *block; - unsigned int offset; - unsigned int buf_size; - unsigned int period_size; - unsigned int loop_start[2]; - unsigned int pitch; - int panning[2]; - int last_ptr; - int period_pos; - int voices; - unsigned int dram_opened: 1; - unsigned int running: 1; - unsigned int timer_running: 1; - struct timer_list timer; - spinlock_t timer_lock; -}; - -#define LOOP_BLANK_SIZE 8 - - -/* - * open up channels for the simultaneous data transfer and playback - */ -static int -emu8k_open_dram_for_pcm(struct snd_emu8000 *emu, int channels) -{ - int i; - - /* reserve up to 2 voices for playback */ - snd_emux_lock_voice(emu->emu, 0); - if (channels > 1) - snd_emux_lock_voice(emu->emu, 1); - - /* reserve 28 voices for loading */ - for (i = channels + 1; i < EMU8000_DRAM_VOICES; i++) { - unsigned int mode = EMU8000_RAM_WRITE; - snd_emux_lock_voice(emu->emu, i); -#ifndef USE_NONINTERLEAVE - if (channels > 1 && (i & 1) != 0) - mode |= EMU8000_RAM_RIGHT; -#endif - snd_emu8000_dma_chan(emu, i, mode); - } - - /* assign voice 31 and 32 to ROM */ - EMU8000_VTFT_WRITE(emu, 30, 0); - EMU8000_PSST_WRITE(emu, 30, 0x1d8); - EMU8000_CSL_WRITE(emu, 30, 0x1e0); - EMU8000_CCCA_WRITE(emu, 30, 0x1d8); - EMU8000_VTFT_WRITE(emu, 31, 0); - EMU8000_PSST_WRITE(emu, 31, 0x1d8); - EMU8000_CSL_WRITE(emu, 31, 0x1e0); - EMU8000_CCCA_WRITE(emu, 31, 0x1d8); - - return 0; -} - -/* - */ -static void -snd_emu8000_write_wait(struct snd_emu8000 *emu, int can_schedule) -{ - while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { - if (can_schedule) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } - } -} - -/* - * close all channels - */ -static void -emu8k_close_dram(struct snd_emu8000 *emu) -{ - int i; - - for (i = 0; i < 2; i++) - snd_emux_unlock_voice(emu->emu, i); - for (; i < EMU8000_DRAM_VOICES; i++) { - snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE); - snd_emux_unlock_voice(emu->emu, i); - } -} - -/* - * convert Hz to AWE32 rate offset (see emux/soundfont.c) - */ - -#define OFFSET_SAMPLERATE 1011119 /* base = 44100 */ -#define SAMPLERATE_RATIO 4096 - -static int calc_rate_offset(int hz) -{ - return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO); -} - - -/* - */ - -static struct snd_pcm_hardware emu8k_pcm_hw = { -#ifdef USE_NONINTERLEAVE - .info = SNDRV_PCM_INFO_NONINTERLEAVED, -#else - .info = SNDRV_PCM_INFO_INTERLEAVED, -#endif - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 1024, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, - -}; - -/* - * get the current position at the given channel from CCCA register - */ -static inline int emu8k_get_curpos(struct snd_emu8k_pcm *rec, int ch) -{ - int val = EMU8000_CCCA_READ(rec->emu, ch) & 0xfffffff; - val -= rec->loop_start[ch] - 1; - return val; -} - - -/* - * timer interrupt handler - * check the current position and update the period if necessary. - */ -static void emu8k_pcm_timer_func(unsigned long data) -{ - struct snd_emu8k_pcm *rec = (struct snd_emu8k_pcm *)data; - int ptr, delta; - - spin_lock(&rec->timer_lock); - /* update the current pointer */ - ptr = emu8k_get_curpos(rec, 0); - if (ptr < rec->last_ptr) - delta = ptr + rec->buf_size - rec->last_ptr; - else - delta = ptr - rec->last_ptr; - rec->period_pos += delta; - rec->last_ptr = ptr; - - /* reprogram timer */ - rec->timer.expires = jiffies + 1; - add_timer(&rec->timer); - - /* update period */ - if (rec->period_pos >= (int)rec->period_size) { - rec->period_pos %= rec->period_size; - spin_unlock(&rec->timer_lock); - snd_pcm_period_elapsed(rec->substream); - return; - } - spin_unlock(&rec->timer_lock); -} - - -/* - * open pcm - * creating an instance here - */ -static int emu8k_pcm_open(struct snd_pcm_substream *subs) -{ - struct snd_emu8000 *emu = snd_pcm_substream_chip(subs); - struct snd_emu8k_pcm *rec; - struct snd_pcm_runtime *runtime = subs->runtime; - - rec = kzalloc(sizeof(*rec), GFP_KERNEL); - if (! rec) - return -ENOMEM; - - rec->emu = emu; - rec->substream = subs; - runtime->private_data = rec; - - spin_lock_init(&rec->timer_lock); - init_timer(&rec->timer); - rec->timer.function = emu8k_pcm_timer_func; - rec->timer.data = (unsigned long)rec; - - runtime->hw = emu8k_pcm_hw; - runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3; - runtime->hw.period_bytes_max = runtime->hw.buffer_bytes_max / 2; - - /* use timer to update periods.. (specified in msec) */ - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, - (1000000 + HZ - 1) / HZ, UINT_MAX); - - return 0; -} - -static int emu8k_pcm_close(struct snd_pcm_substream *subs) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - kfree(rec); - subs->runtime->private_data = NULL; - return 0; -} - -/* - * calculate pitch target - */ -static int calc_pitch_target(int pitch) -{ - int ptarget = 1 << (pitch >> 12); - if (pitch & 0x800) ptarget += (ptarget * 0x102e) / 0x2710; - if (pitch & 0x400) ptarget += (ptarget * 0x764) / 0x2710; - if (pitch & 0x200) ptarget += (ptarget * 0x389) / 0x2710; - ptarget += (ptarget >> 1); - if (ptarget > 0xffff) ptarget = 0xffff; - return ptarget; -} - -/* - * set up the voice - */ -static void setup_voice(struct snd_emu8k_pcm *rec, int ch) -{ - struct snd_emu8000 *hw = rec->emu; - unsigned int temp; - - /* channel to be silent and idle */ - EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080); - EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF); - EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF); - EMU8000_PTRX_WRITE(hw, ch, 0); - EMU8000_CPF_WRITE(hw, ch, 0); - - /* pitch offset */ - EMU8000_IP_WRITE(hw, ch, rec->pitch); - /* set envelope parameters */ - EMU8000_ENVVAL_WRITE(hw, ch, 0x8000); - EMU8000_ATKHLD_WRITE(hw, ch, 0x7f7f); - EMU8000_DCYSUS_WRITE(hw, ch, 0x7f7f); - EMU8000_ENVVOL_WRITE(hw, ch, 0x8000); - EMU8000_ATKHLDV_WRITE(hw, ch, 0x7f7f); - /* decay/sustain parameter for volume envelope is used - for triggerg the voice */ - /* modulation envelope heights */ - EMU8000_PEFE_WRITE(hw, ch, 0x0); - /* lfo1/2 delay */ - EMU8000_LFO1VAL_WRITE(hw, ch, 0x8000); - EMU8000_LFO2VAL_WRITE(hw, ch, 0x8000); - /* lfo1 pitch & cutoff shift */ - EMU8000_FMMOD_WRITE(hw, ch, 0); - /* lfo1 volume & freq */ - EMU8000_TREMFRQ_WRITE(hw, ch, 0); - /* lfo2 pitch & freq */ - EMU8000_FM2FRQ2_WRITE(hw, ch, 0); - /* pan & loop start */ - temp = rec->panning[ch]; - temp = (temp <<24) | ((unsigned int)rec->loop_start[ch] - 1); - EMU8000_PSST_WRITE(hw, ch, temp); - /* chorus & loop end (chorus 8bit, MSB) */ - temp = 0; // chorus - temp = (temp << 24) | ((unsigned int)rec->loop_start[ch] + rec->buf_size - 1); - EMU8000_CSL_WRITE(hw, ch, temp); - /* Q & current address (Q 4bit value, MSB) */ - temp = 0; // filterQ - temp = (temp << 28) | ((unsigned int)rec->loop_start[ch] - 1); - EMU8000_CCCA_WRITE(hw, ch, temp); - /* clear unknown registers */ - EMU8000_00A0_WRITE(hw, ch, 0); - EMU8000_0080_WRITE(hw, ch, 0); -} - -/* - * trigger the voice - */ -static void start_voice(struct snd_emu8k_pcm *rec, int ch) -{ - unsigned long flags; - struct snd_emu8000 *hw = rec->emu; - unsigned int temp, aux; - int pt = calc_pitch_target(rec->pitch); - - /* cutoff and volume */ - EMU8000_IFATN_WRITE(hw, ch, 0xff00); - EMU8000_VTFT_WRITE(hw, ch, 0xffff); - EMU8000_CVCF_WRITE(hw, ch, 0xffff); - /* trigger envelope */ - EMU8000_DCYSUSV_WRITE(hw, ch, 0x7f7f); - /* set reverb and pitch target */ - temp = 0; // reverb - if (rec->panning[ch] == 0) - aux = 0xff; - else - aux = (-rec->panning[ch]) & 0xff; - temp = (temp << 8) | (pt << 16) | aux; - EMU8000_PTRX_WRITE(hw, ch, temp); - EMU8000_CPF_WRITE(hw, ch, pt << 16); - - /* start timer */ - spin_lock_irqsave(&rec->timer_lock, flags); - if (! rec->timer_running) { - rec->timer.expires = jiffies + 1; - add_timer(&rec->timer); - rec->timer_running = 1; - } - spin_unlock_irqrestore(&rec->timer_lock, flags); -} - -/* - * stop the voice immediately - */ -static void stop_voice(struct snd_emu8k_pcm *rec, int ch) -{ - unsigned long flags; - struct snd_emu8000 *hw = rec->emu; - - EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F); - - /* stop timer */ - spin_lock_irqsave(&rec->timer_lock, flags); - if (rec->timer_running) { - del_timer(&rec->timer); - rec->timer_running = 0; - } - spin_unlock_irqrestore(&rec->timer_lock, flags); -} - -static int emu8k_pcm_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - int ch; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - for (ch = 0; ch < rec->voices; ch++) - start_voice(rec, ch); - rec->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - rec->running = 0; - for (ch = 0; ch < rec->voices; ch++) - stop_voice(rec, ch); - break; - default: - return -EINVAL; - } - return 0; -} - - -/* - * copy / silence ops - */ - -/* - * this macro should be inserted in the copy/silence loops - * to reduce the latency. without this, the system will hang up - * during the whole loop. - */ -#define CHECK_SCHEDULER() \ -do { \ - cond_resched();\ - if (signal_pending(current))\ - return -EAGAIN;\ -} while (0) - - -#ifdef USE_NONINTERLEAVE -/* copy one channel block */ -static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count) -{ - EMU8000_SMALW_WRITE(emu, offset); - while (count > 0) { - unsigned short sval; - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMLD_WRITE(emu, sval); - buf++; - count--; - } - return 0; -} - -static int emu8k_pcm_copy(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - void *src, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - if (voice == -1) { - unsigned short *buf = src; - int i, err; - count /= rec->voices; - for (i = 0; i < rec->voices; i++) { - err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count); - if (err < 0) - return err; - buf += count; - } - return 0; - } else { - return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count); - } -} - -/* make a channel block silence */ -static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count) -{ - EMU8000_SMALW_WRITE(emu, offset); - while (count > 0) { - CHECK_SCHEDULER(); - EMU8000_SMLD_WRITE(emu, 0); - count--; - } - return 0; -} - -static int emu8k_pcm_silence(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - if (voice == -1 && rec->voices == 1) - voice = 0; - if (voice == -1) { - int err; - err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2); - if (err < 0) - return err; - return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2); - } else { - return emu8k_silence_block(emu, pos + rec->loop_start[voice], count); - } -} - -#else /* interleave */ - -/* - * copy the interleaved data can be done easily by using - * DMA "left" and "right" channels on emu8k engine. - */ -static int emu8k_pcm_copy(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - unsigned short __user *buf = src; - - snd_emu8000_write_wait(emu, 1); - EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); - if (rec->voices > 1) - EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); - - while (count-- > 0) { - unsigned short sval; - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMLD_WRITE(emu, sval); - buf++; - if (rec->voices > 1) { - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMRD_WRITE(emu, sval); - buf++; - } - } - return 0; -} - -static int emu8k_pcm_silence(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos); - if (rec->voices > 1) - EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos); - while (count-- > 0) { - CHECK_SCHEDULER(); - EMU8000_SMLD_WRITE(emu, 0); - if (rec->voices > 1) { - CHECK_SCHEDULER(); - EMU8000_SMRD_WRITE(emu, 0); - } - } - return 0; -} -#endif - - -/* - * allocate a memory block - */ -static int emu8k_pcm_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - - if (rec->block) { - /* reallocation - release the old block */ - snd_util_mem_free(rec->emu->memhdr, rec->block); - rec->block = NULL; - } - - rec->allocated_bytes = params_buffer_bytes(hw_params) + LOOP_BLANK_SIZE * 4; - rec->block = snd_util_mem_alloc(rec->emu->memhdr, rec->allocated_bytes); - if (! rec->block) - return -ENOMEM; - rec->offset = EMU8000_DRAM_OFFSET + (rec->block->offset >> 1); /* in word */ - /* at least dma_bytes must be set for non-interleaved mode */ - subs->dma_buffer.bytes = params_buffer_bytes(hw_params); - - return 0; -} - -/* - * free the memory block - */ -static int emu8k_pcm_hw_free(struct snd_pcm_substream *subs) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - - if (rec->block) { - int ch; - for (ch = 0; ch < rec->voices; ch++) - stop_voice(rec, ch); // to be sure - if (rec->dram_opened) - emu8k_close_dram(rec->emu); - snd_util_mem_free(rec->emu->memhdr, rec->block); - rec->block = NULL; - } - return 0; -} - -/* - */ -static int emu8k_pcm_prepare(struct snd_pcm_substream *subs) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - - rec->pitch = 0xe000 + calc_rate_offset(subs->runtime->rate); - rec->last_ptr = 0; - rec->period_pos = 0; - - rec->buf_size = subs->runtime->buffer_size; - rec->period_size = subs->runtime->period_size; - rec->voices = subs->runtime->channels; - rec->loop_start[0] = rec->offset + LOOP_BLANK_SIZE; - if (rec->voices > 1) - rec->loop_start[1] = rec->loop_start[0] + rec->buf_size + LOOP_BLANK_SIZE; - if (rec->voices > 1) { - rec->panning[0] = 0xff; - rec->panning[1] = 0x00; - } else - rec->panning[0] = 0x80; - - if (! rec->dram_opened) { - int err, i, ch; - - snd_emux_terminate_all(rec->emu->emu); - if ((err = emu8k_open_dram_for_pcm(rec->emu, rec->voices)) != 0) - return err; - rec->dram_opened = 1; - - /* clear loop blanks */ - snd_emu8000_write_wait(rec->emu, 0); - EMU8000_SMALW_WRITE(rec->emu, rec->offset); - for (i = 0; i < LOOP_BLANK_SIZE; i++) - EMU8000_SMLD_WRITE(rec->emu, 0); - for (ch = 0; ch < rec->voices; ch++) { - EMU8000_SMALW_WRITE(rec->emu, rec->loop_start[ch] + rec->buf_size); - for (i = 0; i < LOOP_BLANK_SIZE; i++) - EMU8000_SMLD_WRITE(rec->emu, 0); - } - } - - setup_voice(rec, 0); - if (rec->voices > 1) - setup_voice(rec, 1); - return 0; -} - -static snd_pcm_uframes_t emu8k_pcm_pointer(struct snd_pcm_substream *subs) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - if (rec->running) - return emu8k_get_curpos(rec, 0); - return 0; -} - - -static struct snd_pcm_ops emu8k_pcm_ops = { - .open = emu8k_pcm_open, - .close = emu8k_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = emu8k_pcm_hw_params, - .hw_free = emu8k_pcm_hw_free, - .prepare = emu8k_pcm_prepare, - .trigger = emu8k_pcm_trigger, - .pointer = emu8k_pcm_pointer, - .copy = emu8k_pcm_copy, - .silence = emu8k_pcm_silence, -}; - - -static void snd_emu8000_pcm_free(struct snd_pcm *pcm) -{ - struct snd_emu8000 *emu = pcm->private_data; - emu->pcm = NULL; -} - -int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index) -{ - struct snd_pcm *pcm; - int err; - - if ((err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm)) < 0) - return err; - pcm->private_data = emu; - pcm->private_free = snd_emu8000_pcm_free; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &emu8k_pcm_ops); - emu->pcm = pcm; - - snd_device_register(card, pcm); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_synth.c b/ANDROID_3.4.5/sound/isa/sb/emu8000_synth.c deleted file mode 100644 index 4e3fcfb1..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_synth.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * and (c) 1999 Steve Ratcliffe - * Copyright (C) 1999-2000 Takashi Iwai - * - * Emu8000 synth plug-in routine - * - * 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 "emu8000_local.h" -#include -#include -#include - -MODULE_AUTHOR("Takashi Iwai, Steve Ratcliffe"); -MODULE_DESCRIPTION("Emu8000 synth plug-in routine"); -MODULE_LICENSE("GPL"); - -/*----------------------------------------------------------------*/ - -/* - * create a new hardware dependent device for Emu8000 - */ -static int snd_emu8000_new_device(struct snd_seq_device *dev) -{ - struct snd_emu8000 *hw; - struct snd_emux *emu; - - hw = *(struct snd_emu8000**)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (hw == NULL) - return -EINVAL; - - if (hw->emu) - return -EBUSY; /* already exists..? */ - - if (snd_emux_new(&emu) < 0) - return -ENOMEM; - - hw->emu = emu; - snd_emu8000_ops_setup(hw); - - emu->hw = hw; - emu->max_voices = EMU8000_DRAM_VOICES; - emu->num_ports = hw->seq_ports; - - if (hw->memhdr) { - snd_printk(KERN_ERR "memhdr is already initialized!?\n"); - snd_util_memhdr_free(hw->memhdr); - } - hw->memhdr = snd_util_memhdr_new(hw->mem_size); - if (hw->memhdr == NULL) { - snd_emux_free(emu); - hw->emu = NULL; - return -ENOMEM; - } - - emu->memhdr = hw->memhdr; - emu->midi_ports = hw->seq_ports < 2 ? hw->seq_ports : 2; /* number of virmidi ports */ - emu->midi_devidx = 1; - emu->linear_panning = 1; - emu->hwdep_idx = 2; /* FIXED */ - - if (snd_emux_register(emu, dev->card, hw->index, "Emu8000") < 0) { - snd_emux_free(emu); - snd_util_memhdr_free(hw->memhdr); - hw->emu = NULL; - hw->memhdr = NULL; - return -ENOMEM; - } - - if (hw->mem_size > 0) - snd_emu8000_pcm_new(dev->card, hw, 1); - - dev->driver_data = hw; - - return 0; -} - - -/* - * free all resources - */ -static int snd_emu8000_delete_device(struct snd_seq_device *dev) -{ - struct snd_emu8000 *hw; - - if (dev->driver_data == NULL) - return 0; /* no synth was allocated actually */ - - hw = dev->driver_data; - if (hw->pcm) - snd_device_free(dev->card, hw->pcm); - if (hw->emu) - snd_emux_free(hw->emu); - if (hw->memhdr) - snd_util_memhdr_free(hw->memhdr); - hw->emu = NULL; - hw->memhdr = NULL; - return 0; -} - -/* - * INIT part - */ - -static int __init alsa_emu8000_init(void) -{ - - static struct snd_seq_dev_ops ops = { - snd_emu8000_new_device, - snd_emu8000_delete_device, - }; - return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU8000, &ops, - sizeof(struct snd_emu8000*)); -} - -static void __exit alsa_emu8000_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_EMU8000); -} - -module_init(alsa_emu8000_init) -module_exit(alsa_emu8000_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/jazz16.c b/ANDROID_3.4.5/sound/isa/sb/jazz16.c deleted file mode 100644 index 410758c6..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/jazz16.c +++ /dev/null @@ -1,404 +0,0 @@ - -/* - * jazz16.c - driver for Media Vision Jazz16 based soundcards. - * Copyright (C) 2009 Krzysztof Helt - * Based on patches posted by Rask Ingemann Lambertsen and Rene Herman. - * Based on OSS Sound Blaster driver. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -#define PFX "jazz16: " - -MODULE_DESCRIPTION("Media Vision Jazz16"); -MODULE_SUPPORTED_DEVICE("{{Media Vision ??? }," - "{RTL,RTL3000}}"); - -MODULE_AUTHOR("Krzysztof Helt "); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static unsigned long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static unsigned long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Media Vision Jazz16 based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Media Vision Jazz16 based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Media Vision Jazz16 based soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for jazz16 driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for jazz16 driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for jazz16 driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for jazz16 driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "DMA8 # for jazz16 driver."); -module_param_array(dma16, int, NULL, 0444); -MODULE_PARM_DESC(dma16, "DMA16 # for jazz16 driver."); - -#define SB_JAZZ16_WAKEUP 0xaf -#define SB_JAZZ16_SET_PORTS 0x50 -#define SB_DSP_GET_JAZZ_BRD_REV 0xfa -#define SB_JAZZ16_SET_DMAINTR 0xfb -#define SB_DSP_GET_JAZZ_MODEL 0xfe - -struct snd_card_jazz16 { - struct snd_sb *chip; -}; - -static irqreturn_t jazz16_interrupt(int irq, void *chip) -{ - return snd_sb8dsp_interrupt(chip); -} - -static int __devinit jazz16_configure_ports(unsigned long port, - unsigned long mpu_port, int idx) -{ - unsigned char val; - - if (!request_region(0x201, 1, "jazz16 config")) { - snd_printk(KERN_ERR "config port region is already in use.\n"); - return -EBUSY; - } - outb(SB_JAZZ16_WAKEUP - idx, 0x201); - udelay(100); - outb(SB_JAZZ16_SET_PORTS + idx, 0x201); - udelay(100); - val = port & 0x70; - val |= (mpu_port & 0x30) >> 4; - outb(val, 0x201); - - release_region(0x201, 1); - return 0; -} - -static int __devinit jazz16_detect_board(unsigned long port, - unsigned long mpu_port) -{ - int err; - int val; - struct snd_sb chip; - - if (!request_region(port, 0x10, "jazz16")) { - snd_printk(KERN_ERR "I/O port region is already in use.\n"); - return -EBUSY; - } - /* just to call snd_sbdsp_command/reset/get_byte() */ - chip.port = port; - - err = snd_sbdsp_reset(&chip); - if (err < 0) - for (val = 0; val < 4; val++) { - err = jazz16_configure_ports(port, mpu_port, val); - if (err < 0) - break; - - err = snd_sbdsp_reset(&chip); - if (!err) - break; - } - if (err < 0) { - err = -ENODEV; - goto err_unmap; - } - if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_BRD_REV)) { - err = -EBUSY; - goto err_unmap; - } - val = snd_sbdsp_get_byte(&chip); - if (val >= 0x30) - snd_sbdsp_get_byte(&chip); - - if ((val & 0xf0) != 0x10) { - err = -ENODEV; - goto err_unmap; - } - if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_MODEL)) { - err = -EBUSY; - goto err_unmap; - } - snd_sbdsp_get_byte(&chip); - err = snd_sbdsp_get_byte(&chip); - snd_printd("Media Vision Jazz16 board detected: rev 0x%x, model 0x%x\n", - val, err); - - err = 0; - -err_unmap: - release_region(port, 0x10); - return err; -} - -static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq) -{ - static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4, - 0, 2, 5, 0, 0, 0, 0, 6 }; - static unsigned char jazz_dma_bits[] = { 0, 1, 0, 2, 0, 3, 0, 4 }; - - if (jazz_dma_bits[chip->dma8] == 0 || - jazz_dma_bits[chip->dma16] == 0 || - jazz_irq_bits[chip->irq] == 0) - return -EINVAL; - - if (!snd_sbdsp_command(chip, SB_JAZZ16_SET_DMAINTR)) - return -EBUSY; - - if (!snd_sbdsp_command(chip, - jazz_dma_bits[chip->dma8] | - (jazz_dma_bits[chip->dma16] << 4))) - return -EBUSY; - - if (!snd_sbdsp_command(chip, - jazz_irq_bits[chip->irq] | - (jazz_irq_bits[mpu_irq] << 4))) - return -EBUSY; - - return 0; -} - -static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev) -{ - if (!enable[dev]) - return 0; - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "please specify port\n"); - return 0; - } else if (port[dev] == 0x200 || (port[dev] & ~0x270)) { - snd_printk(KERN_ERR "incorrect port specified\n"); - return 0; - } - if (dma8[dev] != SNDRV_AUTO_DMA && - dma8[dev] != 1 && dma8[dev] != 3) { - snd_printk(KERN_ERR "dma8 must be 1 or 3\n"); - return 0; - } - if (dma16[dev] != SNDRV_AUTO_DMA && - dma16[dev] != 5 && dma16[dev] != 7) { - snd_printk(KERN_ERR "dma16 must be 5 or 7\n"); - return 0; - } - if (mpu_port[dev] != SNDRV_AUTO_PORT && - (mpu_port[dev] & ~0x030) != 0x300) { - snd_printk(KERN_ERR "incorrect mpu_port specified\n"); - return 0; - } - if (mpu_irq[dev] != SNDRV_AUTO_DMA && - mpu_irq[dev] != 2 && mpu_irq[dev] != 3 && - mpu_irq[dev] != 5 && mpu_irq[dev] != 7) { - snd_printk(KERN_ERR "mpu_irq must be 2, 3, 5 or 7\n"); - return 0; - } - return 1; -} - -static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev) -{ - struct snd_card *card; - struct snd_card_jazz16 *jazz16; - struct snd_sb *chip; - struct snd_opl3 *opl3; - static int possible_irqs[] = {2, 3, 5, 7, 9, 10, 15, -1}; - static int possible_dmas8[] = {1, 3, -1}; - static int possible_dmas16[] = {5, 7, -1}; - int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_jazz16), &card); - if (err < 0) - return err; - - jazz16 = card->private_data; - - xirq = irq[dev]; - if (xirq == SNDRV_AUTO_IRQ) { - xirq = snd_legacy_find_free_irq(possible_irqs); - if (xirq < 0) { - snd_printk(KERN_ERR "unable to find a free IRQ\n"); - err = -EBUSY; - goto err_free; - } - } - xdma8 = dma8[dev]; - if (xdma8 == SNDRV_AUTO_DMA) { - xdma8 = snd_legacy_find_free_dma(possible_dmas8); - if (xdma8 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA8\n"); - err = -EBUSY; - goto err_free; - } - } - xdma16 = dma16[dev]; - if (xdma16 == SNDRV_AUTO_DMA) { - xdma16 = snd_legacy_find_free_dma(possible_dmas16); - if (xdma16 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA16\n"); - err = -EBUSY; - goto err_free; - } - } - - xmpu_port = mpu_port[dev]; - if (xmpu_port == SNDRV_AUTO_PORT) - xmpu_port = 0; - err = jazz16_detect_board(port[dev], xmpu_port); - if (err < 0) { - printk(KERN_ERR "Media Vision Jazz16 board not detected\n"); - goto err_free; - } - err = snd_sbdsp_create(card, port[dev], irq[dev], - jazz16_interrupt, - dma8[dev], dma16[dev], - SB_HW_JAZZ16, - &chip); - if (err < 0) - goto err_free; - - xmpu_irq = mpu_irq[dev]; - if (xmpu_irq == SNDRV_AUTO_IRQ || mpu_port[dev] == SNDRV_AUTO_PORT) - xmpu_irq = 0; - err = jazz16_configure_board(chip, xmpu_irq); - if (err < 0) { - printk(KERN_ERR "Media Vision Jazz16 configuration failed\n"); - goto err_free; - } - - jazz16->chip = chip; - - strcpy(card->driver, "jazz16"); - strcpy(card->shortname, "Media Vision Jazz16"); - sprintf(card->longname, - "Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d", - port[dev], xirq, xdma8, xdma16); - - err = snd_sb8dsp_pcm(chip, 0, NULL); - if (err < 0) - goto err_free; - err = snd_sbmixer_new(chip); - if (err < 0) - goto err_free; - - err = snd_opl3_create(card, chip->port, chip->port + 2, - OPL3_HW_AUTO, 1, &opl3); - if (err < 0) - snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n", - chip->port, chip->port + 2); - else { - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - goto err_free; - } - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; - - if (snd_mpu401_uart_new(card, 0, - MPU401_HW_MPU401, - mpu_port[dev], 0, - mpu_irq[dev], - NULL) < 0) - snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n", - mpu_port[dev]); - } - - snd_card_set_dev(card, devptr); - - err = snd_card_register(card); - if (err < 0) - goto err_free; - - dev_set_drvdata(devptr, card); - return 0; - -err_free: - snd_card_free(card); - return err; -} - -static int __devexit snd_jazz16_remove(struct device *devptr, unsigned int dev) -{ - struct snd_card *card = dev_get_drvdata(devptr); - - dev_set_drvdata(devptr, NULL); - snd_card_free(card); - return 0; -} - -#ifdef CONFIG_PM -static int snd_jazz16_suspend(struct device *pdev, unsigned int n, - pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(pdev); - struct snd_card_jazz16 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - return 0; -} - -static int snd_jazz16_resume(struct device *pdev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(pdev); - struct snd_card_jazz16 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct isa_driver snd_jazz16_driver = { - .match = snd_jazz16_match, - .probe = snd_jazz16_probe, - .remove = __devexit_p(snd_jazz16_remove), -#ifdef CONFIG_PM - .suspend = snd_jazz16_suspend, - .resume = snd_jazz16_resume, -#endif - .driver = { - .name = "jazz16" - }, -}; - -static int __init alsa_card_jazz16_init(void) -{ - return isa_register_driver(&snd_jazz16_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_jazz16_exit(void) -{ - isa_unregister_driver(&snd_jazz16_driver); -} - -module_init(alsa_card_jazz16_init) -module_exit(alsa_card_jazz16_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb16.c b/ANDROID_3.4.5/sound/isa/sb/sb16.c deleted file mode 100644 index 39b8eca1..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb16.c +++ /dev/null @@ -1,699 +0,0 @@ -/* - * Driver for SoundBlaster 16/AWE32/AWE64 soundcards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 -#include -#include -#include -#include -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -#ifdef SNDRV_SBAWE -#define PFX "sbawe: " -#else -#define PFX "sb16: " -#endif - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_LICENSE("GPL"); -#ifndef SNDRV_SBAWE -MODULE_DESCRIPTION("Sound Blaster 16"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 16}," - "{Creative Labs,SB Vibra16S}," - "{Creative Labs,SB Vibra16C}," - "{Creative Labs,SB Vibra16CL}," - "{Creative Labs,SB Vibra16X}}"); -#else -MODULE_DESCRIPTION("Sound Blaster AWE"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32}," - "{Creative Labs,SB AWE 64}," - "{Creative Labs,SB AWE 64 Gold}}"); -#endif - -#if 0 -#define SNDRV_DEBUG_IRQ -#endif - -#if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))) -#define SNDRV_SBAWE_EMU8000 -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x330,0x300 */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -#ifdef SNDRV_SBAWE_EMU8000 -static long awe_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -#endif -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ -static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */ -static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#ifdef CONFIG_SND_SB16_CSP -static int csp[SNDRV_CARDS]; -#endif -#ifdef SNDRV_SBAWE_EMU8000 -static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; -#endif - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for SoundBlaster 16 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for SoundBlaster 16 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable SoundBlaster 16 soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for SB16 driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for SB16 driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for SB16 PnP driver."); -#ifdef SNDRV_SBAWE_EMU8000 -module_param_array(awe_port, long, NULL, 0444); -MODULE_PARM_DESC(awe_port, "AWE port # for SB16 PnP driver."); -#endif -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for SB16 driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for SB16 driver."); -module_param_array(dma16, int, NULL, 0444); -MODULE_PARM_DESC(dma16, "16-bit DMA # for SB16 driver."); -module_param_array(mic_agc, int, NULL, 0444); -MODULE_PARM_DESC(mic_agc, "Mic Auto-Gain-Control switch."); -#ifdef CONFIG_SND_SB16_CSP -module_param_array(csp, int, NULL, 0444); -MODULE_PARM_DESC(csp, "ASP/CSP chip support."); -#endif -#ifdef SNDRV_SBAWE_EMU8000 -module_param_array(seq_ports, int, NULL, 0444); -MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth."); -#endif - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -#endif - -struct snd_card_sb16 { - struct resource *fm_res; /* used to block FM i/o region for legacy cards */ - struct snd_sb *chip; -#ifdef CONFIG_PNP - int dev_no; - struct pnp_dev *dev; -#ifdef SNDRV_SBAWE_EMU8000 - struct pnp_dev *devwt; -#endif -#endif -}; - -#ifdef CONFIG_PNP - -static struct pnp_card_device_id snd_sb16_pnpids[] = { -#ifndef SNDRV_SBAWE - /* Sound Blaster 16 PnP */ - { .id = "CTL0024", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0025", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0026", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0027", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0028", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0029", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL002a", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - /* Note: This card has also a CTL0051:StereoEnhance device!!! */ - { .id = "CTL002b", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL002c", .devs = { { "CTL0031" } } }, - /* Sound Blaster Vibra16S */ - { .id = "CTL0051", .devs = { { "CTL0001" } } }, - /* Sound Blaster Vibra16C */ - { .id = "CTL0070", .devs = { { "CTL0001" } } }, - /* Sound Blaster Vibra16CL - added by ctm@ardi.com */ - { .id = "CTL0080", .devs = { { "CTL0041" } } }, - /* Sound Blaster 16 'value' PnP. It says model ct4130 on the pcb, */ - /* but ct4131 on a sticker on the board.. */ - { .id = "CTL0086", .devs = { { "CTL0041" } } }, - /* Sound Blaster Vibra16X */ - { .id = "CTL00f0", .devs = { { "CTL0043" } } }, - /* Sound Blaster 16 (Virtual PC 2004) */ - { .id = "tBA03b0", .devs = { {.id="PNPb003" } } }, -#else /* SNDRV_SBAWE defined */ - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0035", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0039", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0042", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0043", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - /* Note: This card has also a CTL0051:StereoEnhance device!!! */ - { .id = "CTL0044", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - /* Note: This card has also a CTL0051:StereoEnhance device!!! */ - { .id = "CTL0045", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0046", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0047", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0048", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0054", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL009a", .devs = { { "CTL0041" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL009c", .devs = { { "CTL0041" }, { "CTL0021" } } }, - /* Sound Blaster 32 PnP */ - { .id = "CTL009f", .devs = { { "CTL0041" }, { "CTL0021" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL009d", .devs = { { "CTL0042" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP Gold */ - { .id = "CTL009e", .devs = { { "CTL0044" }, { "CTL0023" } } }, - /* Sound Blaster AWE 64 PnP Gold */ - { .id = "CTL00b2", .devs = { { "CTL0044" }, { "CTL0023" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00c1", .devs = { { "CTL0042" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00c3", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00c5", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00c7", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00e4", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00e9", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster 16 PnP (AWE) */ - { .id = "CTL00ed", .devs = { { "CTL0041" }, { "CTL0070" } } }, - /* Generic entries */ - { .id = "CTLXXXX" , .devs = { { "CTL0031" }, { "CTL0021" } } }, - { .id = "CTLXXXX" , .devs = { { "CTL0041" }, { "CTL0021" } } }, - { .id = "CTLXXXX" , .devs = { { "CTL0042" }, { "CTL0022" } } }, - { .id = "CTLXXXX" , .devs = { { "CTL0044" }, { "CTL0023" } } }, - { .id = "CTLXXXX" , .devs = { { "CTL0045" }, { "CTL0022" } } }, -#endif /* SNDRV_SBAWE */ - { .id = "", } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_sb16_pnpids); - -#endif /* CONFIG_PNP */ - -#ifdef SNDRV_SBAWE_EMU8000 -#define DRIVER_NAME "snd-card-sbawe" -#else -#define DRIVER_NAME "snd-card-sb16" -#endif - -#ifdef CONFIG_PNP - -static int __devinit snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->dev == NULL) - return -ENODEV; - -#ifdef SNDRV_SBAWE_EMU8000 - acard->devwt = pnp_request_card_device(card, id->devs[1].id, acard->dev); -#endif - /* Audio initialization */ - pdev = acard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); - return err; - } - port[dev] = pnp_port_start(pdev, 0); - mpu_port[dev] = pnp_port_start(pdev, 1); - fm_port[dev] = pnp_port_start(pdev, 2); - dma8[dev] = pnp_dma(pdev, 0); - dma16[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("pnp SB16: port=0x%lx, mpu port=0x%lx, fm port=0x%lx\n", - port[dev], mpu_port[dev], fm_port[dev]); - snd_printdd("pnp SB16: dma1=%i, dma2=%i, irq=%i\n", - dma8[dev], dma16[dev], irq[dev]); -#ifdef SNDRV_SBAWE_EMU8000 - /* WaveTable initialization */ - pdev = acard->devwt; - if (pdev != NULL) { - err = pnp_activate_dev(pdev); - if (err < 0) { - goto __wt_error; - } - awe_port[dev] = pnp_port_start(pdev, 0); - snd_printdd("pnp SB16: wavetable port=0x%llx\n", - (unsigned long long)pnp_port_start(pdev, 0)); - } else { -__wt_error: - if (pdev) { - pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "WaveTable pnp configure failure\n"); - } - acard->devwt = NULL; - awe_port[dev] = -1; - } -#endif - return 0; -} - -#endif /* CONFIG_PNP */ - -static void snd_sb16_free(struct snd_card *card) -{ - struct snd_card_sb16 *acard = card->private_data; - - if (acard == NULL) - return; - release_and_free_resource(acard->fm_res); -} - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -static int snd_sb16_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_sb16), &card); - if (err < 0) - return err; - card->private_free = snd_sb16_free; - *cardp = card; - return 0; -} - -static int __devinit snd_sb16_probe(struct snd_card *card, int dev) -{ - int xirq, xdma8, xdma16; - struct snd_sb *chip; - struct snd_card_sb16 *acard = card->private_data; - struct snd_opl3 *opl3; - struct snd_hwdep *synth = NULL; -#ifdef CONFIG_SND_SB16_CSP - struct snd_hwdep *xcsp = NULL; -#endif - unsigned long flags; - int err; - - xirq = irq[dev]; - xdma8 = dma8[dev]; - xdma16 = dma16[dev]; - - if ((err = snd_sbdsp_create(card, - port[dev], - xirq, - snd_sb16dsp_interrupt, - xdma8, - xdma16, - SB_HW_AUTO, - &chip)) < 0) - return err; - - acard->chip = chip; - if (chip->hardware != SB_HW_16) { - snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]); - return -ENODEV; - } - chip->mpu_port = mpu_port[dev]; - if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0) - return err; - - if ((err = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) - return err; - - strcpy(card->driver, -#ifdef SNDRV_SBAWE_EMU8000 - awe_port[dev] > 0 ? "SB AWE" : -#endif - "SB16"); - strcpy(card->shortname, chip->name); - sprintf(card->longname, "%s at 0x%lx, irq %i, dma ", - chip->name, - chip->port, - xirq); - if (xdma8 >= 0) - sprintf(card->longname + strlen(card->longname), "%d", xdma8); - if (xdma16 >= 0) - sprintf(card->longname + strlen(card->longname), "%s%d", - xdma8 >= 0 ? "&" : "", xdma16); - - if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, - chip->mpu_port, - MPU401_INFO_IRQ_HOOK, -1, - &chip->rmidi)) < 0) - return err; - chip->rmidi_callback = snd_mpu401_uart_interrupt; - } - -#ifdef SNDRV_SBAWE_EMU8000 - if (awe_port[dev] == SNDRV_AUTO_PORT) - awe_port[dev] = 0; /* disable */ -#endif - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, - OPL3_HW_OPL3, - acard->fm_res != NULL || fm_port[dev] == port[dev], - &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); - } else { -#ifdef SNDRV_SBAWE_EMU8000 - int seqdev = awe_port[dev] > 0 ? 2 : 1; -#else - int seqdev = 1; -#endif - if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) - return err; - } - } - - if ((err = snd_sbmixer_new(chip)) < 0) - return err; - -#ifdef CONFIG_SND_SB16_CSP - /* CSP chip on SB16ASP/AWE32 */ - if ((chip->hardware == SB_HW_16) && csp[dev]) { - snd_sb_csp_new(chip, synth != NULL ? 1 : 0, &xcsp); - if (xcsp) { - chip->csp = xcsp->private_data; - chip->hardware = SB_HW_16CSP; - } else { - snd_printk(KERN_INFO PFX "warning - CSP chip not detected on soundcard #%i\n", dev + 1); - } - } -#endif -#ifdef SNDRV_SBAWE_EMU8000 - if (awe_port[dev] > 0) { - if ((err = snd_emu8000_new(card, 1, awe_port[dev], - seq_ports[dev], NULL)) < 0) { - snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]); - - return err; - } - } -#endif - - /* setup Mic AGC */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, SB_DSP4_MIC_AGC, - (snd_sbmixer_read(chip, SB_DSP4_MIC_AGC) & 0x01) | - (mic_agc[dev] ? 0x00 : 0x01)); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - - if ((err = snd_card_register(card)) < 0) - return err; - - return 0; -} - -#ifdef CONFIG_PM -static int snd_sb16_suspend(struct snd_card *card, pm_message_t state) -{ - struct snd_card_sb16 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - return 0; -} - -static int snd_sb16_resume(struct snd_card *card) -{ - struct snd_card_sb16 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev) -{ - struct snd_card_sb16 *acard; - struct snd_card *card; - int err; - - err = snd_sb16_card_new(dev, &card); - if (err < 0) - return err; - - acard = card->private_data; - /* non-PnP FM port address is hardwired with base port address */ - fm_port[dev] = port[dev]; - /* block the 0x388 port to avoid PnP conflicts */ - acard->fm_res = request_region(0x388, 4, "SoundBlaster FM"); -#ifdef SNDRV_SBAWE_EMU8000 - /* non-PnP AWE port address is hardwired with base port address */ - awe_port[dev] = port[dev] + 0x400; -#endif - - snd_card_set_dev(card, pdev); - if ((err = snd_sb16_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(pdev, card); - return 0; -} - - -static int __devinit snd_sb16_isa_match(struct device *pdev, unsigned int dev) -{ - return enable[dev] && !is_isapnp_selected(dev); -} - -static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev) -{ - int err; - static int possible_irqs[] = {5, 9, 10, 7, -1}; - static int possible_dmas8[] = {1, 3, 0, -1}; - static int possible_dmas16[] = {5, 6, 7, -1}; - - if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma8[dev] == SNDRV_AUTO_DMA) { - if ((dma8[dev] = snd_legacy_find_free_dma(possible_dmas8)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n"); - return -EBUSY; - } - } - if (dma16[dev] == SNDRV_AUTO_DMA) { - if ((dma16[dev] = snd_legacy_find_free_dma(possible_dmas16)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n"); - return -EBUSY; - } - } - - if (port[dev] != SNDRV_AUTO_PORT) - return snd_sb16_isa_probe1(dev, pdev); - else { - static int possible_ports[] = {0x220, 0x240, 0x260, 0x280}; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - port[dev] = possible_ports[i]; - err = snd_sb16_isa_probe1(dev, pdev); - if (! err) - return 0; - } - return err; - } -} - -static int __devexit snd_sb16_isa_remove(struct device *pdev, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(pdev)); - dev_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_sb16_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_sb16_suspend(dev_get_drvdata(dev), state); -} - -static int snd_sb16_isa_resume(struct device *dev, unsigned int n) -{ - return snd_sb16_resume(dev_get_drvdata(dev)); -} -#endif - -#ifdef SNDRV_SBAWE -#define DEV_NAME "sbawe" -#else -#define DEV_NAME "sb16" -#endif - -static struct isa_driver snd_sb16_isa_driver = { - .match = snd_sb16_isa_match, - .probe = snd_sb16_isa_probe, - .remove = __devexit_p(snd_sb16_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_sb16_isa_suspend, - .resume = snd_sb16_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev] || !isapnp[dev]) - continue; - res = snd_sb16_card_new(dev, &card); - if (res < 0) - return res; - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || - (res = snd_sb16_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; - } - - return -ENODEV; -} - -static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_sb16_suspend(pnp_get_card_drvdata(pcard), state); -} -static int snd_sb16_pnp_resume(struct pnp_card_link *pcard) -{ - return snd_sb16_resume(pnp_get_card_drvdata(pcard)); -} -#endif - -static struct pnp_card_driver sb16_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, -#ifdef SNDRV_SBAWE - .name = "sbawe", -#else - .name = "sb16", -#endif - .id_table = snd_sb16_pnpids, - .probe = snd_sb16_pnp_detect, - .remove = __devexit_p(snd_sb16_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_sb16_pnp_suspend, - .resume = snd_sb16_pnp_resume, -#endif -}; - -#endif /* CONFIG_PNP */ - -static int __init alsa_card_sb16_init(void) -{ - int err; - - err = isa_register_driver(&snd_sb16_isa_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&sb16_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_sb16_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&sb16_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_sb16_isa_driver); -} - -module_init(alsa_card_sb16_init) -module_exit(alsa_card_sb16_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb16_csp.c b/ANDROID_3.4.5/sound/isa/sb/sb16_csp.c deleted file mode 100644 index c1aa21ed..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb16_csp.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * Copyright (c) 1999 by Uros Bizjak - * Takashi Iwai - * - * SB16ASP/AWE32 CSP control - * - * CSP microcode loader: - * alsa-tools/sb16_csp/ - * - * 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 - -MODULE_AUTHOR("Uros Bizjak "); -MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("sb16/mulaw_main.csp"); -MODULE_FIRMWARE("sb16/alaw_main.csp"); -MODULE_FIRMWARE("sb16/ima_adpcm_init.csp"); -MODULE_FIRMWARE("sb16/ima_adpcm_playback.csp"); -MODULE_FIRMWARE("sb16/ima_adpcm_capture.csp"); - -#ifdef SNDRV_LITTLE_ENDIAN -#define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24)) -#else -#define CSP_HDR_VALUE(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24)) -#endif - -#define RIFF_HEADER CSP_HDR_VALUE('R', 'I', 'F', 'F') -#define CSP__HEADER CSP_HDR_VALUE('C', 'S', 'P', ' ') -#define LIST_HEADER CSP_HDR_VALUE('L', 'I', 'S', 'T') -#define FUNC_HEADER CSP_HDR_VALUE('f', 'u', 'n', 'c') -#define CODE_HEADER CSP_HDR_VALUE('c', 'o', 'd', 'e') -#define INIT_HEADER CSP_HDR_VALUE('i', 'n', 'i', 't') -#define MAIN_HEADER CSP_HDR_VALUE('m', 'a', 'i', 'n') - -/* - * RIFF data format - */ -struct riff_header { - __u32 name; - __u32 len; -}; - -struct desc_header { - struct riff_header info; - __u16 func_nr; - __u16 VOC_type; - __u16 flags_play_rec; - __u16 flags_16bit_8bit; - __u16 flags_stereo_mono; - __u16 flags_rates; -}; - -/* - * prototypes - */ -static void snd_sb_csp_free(struct snd_hwdep *hw); -static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file); -static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg); -static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file); - -static int csp_detect(struct snd_sb *chip, int *version); -static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val); -static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val); -static int read_register(struct snd_sb *chip, unsigned char reg); -static int set_mode_register(struct snd_sb *chip, unsigned char mode); -static int get_version(struct snd_sb *chip); - -static int snd_sb_csp_riff_load(struct snd_sb_csp * p, - struct snd_sb_csp_microcode __user * code); -static int snd_sb_csp_unload(struct snd_sb_csp * p); -static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags); -static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode); -static int snd_sb_csp_check_version(struct snd_sb_csp * p); - -static int snd_sb_csp_use(struct snd_sb_csp * p); -static int snd_sb_csp_unuse(struct snd_sb_csp * p); -static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels); -static int snd_sb_csp_stop(struct snd_sb_csp * p); -static int snd_sb_csp_pause(struct snd_sb_csp * p); -static int snd_sb_csp_restart(struct snd_sb_csp * p); - -static int snd_sb_qsound_build(struct snd_sb_csp * p); -static void snd_sb_qsound_destroy(struct snd_sb_csp * p); -static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p); - -static int init_proc_entry(struct snd_sb_csp * p, int device); -static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); - -/* - * Detect CSP chip and create a new instance - */ -int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) -{ - struct snd_sb_csp *p; - int uninitialized_var(version); - int err; - struct snd_hwdep *hw; - - if (rhwdep) - *rhwdep = NULL; - - if (csp_detect(chip, &version)) - return -ENODEV; - - if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0) - return err; - - if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) { - snd_device_free(chip->card, hw); - return -ENOMEM; - } - p->chip = chip; - p->version = version; - - /* CSP operators */ - p->ops.csp_use = snd_sb_csp_use; - p->ops.csp_unuse = snd_sb_csp_unuse; - p->ops.csp_autoload = snd_sb_csp_autoload; - p->ops.csp_start = snd_sb_csp_start; - p->ops.csp_stop = snd_sb_csp_stop; - p->ops.csp_qsound_transfer = snd_sb_csp_qsound_transfer; - - mutex_init(&p->access_mutex); - sprintf(hw->name, "CSP v%d.%d", (version >> 4), (version & 0x0f)); - hw->iface = SNDRV_HWDEP_IFACE_SB16CSP; - hw->private_data = p; - hw->private_free = snd_sb_csp_free; - - /* operators - only write/ioctl */ - hw->ops.open = snd_sb_csp_open; - hw->ops.ioctl = snd_sb_csp_ioctl; - hw->ops.release = snd_sb_csp_release; - - /* create a proc entry */ - init_proc_entry(p, device); - if (rhwdep) - *rhwdep = hw; - return 0; -} - -/* - * free_private for hwdep instance - */ -static void snd_sb_csp_free(struct snd_hwdep *hwdep) -{ - int i; - struct snd_sb_csp *p = hwdep->private_data; - if (p) { - if (p->running & SNDRV_SB_CSP_ST_RUNNING) - snd_sb_csp_stop(p); - for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i) - release_firmware(p->csp_programs[i]); - kfree(p); - } -} - -/* ------------------------------ */ - -/* - * open the device exclusively - */ -static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file) -{ - struct snd_sb_csp *p = hw->private_data; - return (snd_sb_csp_use(p)); -} - -/* - * ioctl for hwdep device: - */ -static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_sb_csp *p = hw->private_data; - struct snd_sb_csp_info info; - struct snd_sb_csp_start start_info; - int err; - - if (snd_BUG_ON(!p)) - return -EINVAL; - - if (snd_sb_csp_check_version(p)) - return -ENODEV; - - switch (cmd) { - /* get information */ - case SNDRV_SB_CSP_IOCTL_INFO: - *info.codec_name = *p->codec_name; - info.func_nr = p->func_nr; - info.acc_format = p->acc_format; - info.acc_channels = p->acc_channels; - info.acc_width = p->acc_width; - info.acc_rates = p->acc_rates; - info.csp_mode = p->mode; - info.run_channels = p->run_channels; - info.run_width = p->run_width; - info.version = p->version; - info.state = p->running; - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - err = -EFAULT; - else - err = 0; - break; - - /* load CSP microcode */ - case SNDRV_SB_CSP_IOCTL_LOAD_CODE: - err = (p->running & SNDRV_SB_CSP_ST_RUNNING ? - -EBUSY : snd_sb_csp_riff_load(p, (struct snd_sb_csp_microcode __user *) arg)); - break; - case SNDRV_SB_CSP_IOCTL_UNLOAD_CODE: - err = (p->running & SNDRV_SB_CSP_ST_RUNNING ? - -EBUSY : snd_sb_csp_unload(p)); - break; - - /* change CSP running state */ - case SNDRV_SB_CSP_IOCTL_START: - if (copy_from_user(&start_info, (void __user *) arg, sizeof(start_info))) - err = -EFAULT; - else - err = snd_sb_csp_start(p, start_info.sample_width, start_info.channels); - break; - case SNDRV_SB_CSP_IOCTL_STOP: - err = snd_sb_csp_stop(p); - break; - case SNDRV_SB_CSP_IOCTL_PAUSE: - err = snd_sb_csp_pause(p); - break; - case SNDRV_SB_CSP_IOCTL_RESTART: - err = snd_sb_csp_restart(p); - break; - default: - err = -ENOTTY; - break; - } - - return err; -} - -/* - * close the device - */ -static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file) -{ - struct snd_sb_csp *p = hw->private_data; - return (snd_sb_csp_unuse(p)); -} - -/* ------------------------------ */ - -/* - * acquire device - */ -static int snd_sb_csp_use(struct snd_sb_csp * p) -{ - mutex_lock(&p->access_mutex); - if (p->used) { - mutex_unlock(&p->access_mutex); - return -EAGAIN; - } - p->used++; - mutex_unlock(&p->access_mutex); - - return 0; - -} - -/* - * release device - */ -static int snd_sb_csp_unuse(struct snd_sb_csp * p) -{ - mutex_lock(&p->access_mutex); - p->used--; - mutex_unlock(&p->access_mutex); - - return 0; -} - -/* - * load microcode via ioctl: - * code is user-space pointer - */ -static int snd_sb_csp_riff_load(struct snd_sb_csp * p, - struct snd_sb_csp_microcode __user * mcode) -{ - struct snd_sb_csp_mc_header info; - - unsigned char __user *data_ptr; - unsigned char __user *data_end; - unsigned short func_nr = 0; - - struct riff_header file_h, item_h, code_h; - __u32 item_type; - struct desc_header funcdesc_h; - - unsigned long flags; - int err; - - if (copy_from_user(&info, mcode, sizeof(info))) - return -EFAULT; - data_ptr = mcode->data; - - if (copy_from_user(&file_h, data_ptr, sizeof(file_h))) - return -EFAULT; - if ((file_h.name != RIFF_HEADER) || - (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) { - snd_printd("%s: Invalid RIFF header\n", __func__); - return -EINVAL; - } - data_ptr += sizeof(file_h); - data_end = data_ptr + le32_to_cpu(file_h.len); - - if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) - return -EFAULT; - if (item_type != CSP__HEADER) { - snd_printd("%s: Invalid RIFF file type\n", __func__); - return -EINVAL; - } - data_ptr += sizeof (item_type); - - for (; data_ptr < data_end; data_ptr += le32_to_cpu(item_h.len)) { - if (copy_from_user(&item_h, data_ptr, sizeof(item_h))) - return -EFAULT; - data_ptr += sizeof(item_h); - if (item_h.name != LIST_HEADER) - continue; - - if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) - return -EFAULT; - switch (item_type) { - case FUNC_HEADER: - if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h))) - return -EFAULT; - func_nr = le16_to_cpu(funcdesc_h.func_nr); - break; - case CODE_HEADER: - if (func_nr != info.func_req) - break; /* not required function, try next */ - data_ptr += sizeof(item_type); - - /* destroy QSound mixer element */ - if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { - snd_sb_qsound_destroy(p); - } - /* Clear all flags */ - p->running = 0; - p->mode = 0; - - /* load microcode blocks */ - for (;;) { - if (data_ptr >= data_end) - return -EINVAL; - if (copy_from_user(&code_h, data_ptr, sizeof(code_h))) - return -EFAULT; - - /* init microcode blocks */ - if (code_h.name != INIT_HEADER) - break; - data_ptr += sizeof(code_h); - err = snd_sb_csp_load_user(p, data_ptr, le32_to_cpu(code_h.len), - SNDRV_SB_CSP_LOAD_INITBLOCK); - if (err) - return err; - data_ptr += le32_to_cpu(code_h.len); - } - /* main microcode block */ - if (copy_from_user(&code_h, data_ptr, sizeof(code_h))) - return -EFAULT; - - if (code_h.name != MAIN_HEADER) { - snd_printd("%s: Missing 'main' microcode\n", __func__); - return -EINVAL; - } - data_ptr += sizeof(code_h); - err = snd_sb_csp_load_user(p, data_ptr, - le32_to_cpu(code_h.len), 0); - if (err) - return err; - - /* fill in codec header */ - strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name)); - p->func_nr = func_nr; - p->mode = le16_to_cpu(funcdesc_h.flags_play_rec); - switch (le16_to_cpu(funcdesc_h.VOC_type)) { - case 0x0001: /* QSound decoder */ - if (le16_to_cpu(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) { - if (snd_sb_qsound_build(p) == 0) - /* set QSound flag and clear all other mode flags */ - p->mode = SNDRV_SB_CSP_MODE_QSOUND; - } - p->acc_format = 0; - break; - case 0x0006: /* A Law codec */ - p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; - break; - case 0x0007: /* Mu Law codec */ - p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; - break; - case 0x0011: /* what Creative thinks is IMA ADPCM codec */ - case 0x0200: /* Creative ADPCM codec */ - p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; - break; - case 201: /* Text 2 Speech decoder */ - /* TODO: Text2Speech handling routines */ - p->acc_format = 0; - break; - case 0x0202: /* Fast Speech 8 codec */ - case 0x0203: /* Fast Speech 10 codec */ - p->acc_format = SNDRV_PCM_FMTBIT_SPECIAL; - break; - default: /* other codecs are unsupported */ - p->acc_format = p->acc_width = p->acc_rates = 0; - p->mode = 0; - snd_printd("%s: Unsupported CSP codec type: 0x%04x\n", - __func__, - le16_to_cpu(funcdesc_h.VOC_type)); - return -EINVAL; - } - p->acc_channels = le16_to_cpu(funcdesc_h.flags_stereo_mono); - p->acc_width = le16_to_cpu(funcdesc_h.flags_16bit_8bit); - p->acc_rates = le16_to_cpu(funcdesc_h.flags_rates); - - /* Decouple CSP from IRQ and DMAREQ lines */ - spin_lock_irqsave(&p->chip->reg_lock, flags); - set_mode_register(p->chip, 0xfc); - set_mode_register(p->chip, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - - /* finished loading successfully */ - p->running = SNDRV_SB_CSP_ST_LOADED; /* set LOADED flag */ - return 0; - } - } - snd_printd("%s: Function #%d not found\n", __func__, info.func_req); - return -EINVAL; -} - -/* - * unload CSP microcode - */ -static int snd_sb_csp_unload(struct snd_sb_csp * p) -{ - if (p->running & SNDRV_SB_CSP_ST_RUNNING) - return -EBUSY; - if (!(p->running & SNDRV_SB_CSP_ST_LOADED)) - return -ENXIO; - - /* clear supported formats */ - p->acc_format = 0; - p->acc_channels = p->acc_width = p->acc_rates = 0; - /* destroy QSound mixer element */ - if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { - snd_sb_qsound_destroy(p); - } - /* clear all flags */ - p->running = 0; - p->mode = 0; - return 0; -} - -/* - * send command sequence to DSP - */ -static inline int command_seq(struct snd_sb *chip, const unsigned char *seq, int size) -{ - int i; - for (i = 0; i < size; i++) { - if (!snd_sbdsp_command(chip, seq[i])) - return -EIO; - } - return 0; -} - -/* - * set CSP codec parameter - */ -static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val) -{ - unsigned char dsp_cmd[3]; - - dsp_cmd[0] = 0x05; /* CSP set codec parameter */ - dsp_cmd[1] = val; /* Parameter value */ - dsp_cmd[2] = par; /* Parameter */ - command_seq(chip, dsp_cmd, 3); - snd_sbdsp_command(chip, 0x03); /* DSP read? */ - if (snd_sbdsp_get_byte(chip) != par) - return -EIO; - return 0; -} - -/* - * set CSP register - */ -static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val) -{ - unsigned char dsp_cmd[3]; - - dsp_cmd[0] = 0x0e; /* CSP set register */ - dsp_cmd[1] = reg; /* CSP Register */ - dsp_cmd[2] = val; /* value */ - return command_seq(chip, dsp_cmd, 3); -} - -/* - * read CSP register - * return < 0 -> error - */ -static int read_register(struct snd_sb *chip, unsigned char reg) -{ - unsigned char dsp_cmd[2]; - - dsp_cmd[0] = 0x0f; /* CSP read register */ - dsp_cmd[1] = reg; /* CSP Register */ - command_seq(chip, dsp_cmd, 2); - return snd_sbdsp_get_byte(chip); /* Read DSP value */ -} - -/* - * set CSP mode register - */ -static int set_mode_register(struct snd_sb *chip, unsigned char mode) -{ - unsigned char dsp_cmd[2]; - - dsp_cmd[0] = 0x04; /* CSP set mode register */ - dsp_cmd[1] = mode; /* mode */ - return command_seq(chip, dsp_cmd, 2); -} - -/* - * Detect CSP - * return 0 if CSP exists. - */ -static int csp_detect(struct snd_sb *chip, int *version) -{ - unsigned char csp_test1, csp_test2; - unsigned long flags; - int result = -ENODEV; - - spin_lock_irqsave(&chip->reg_lock, flags); - - set_codec_parameter(chip, 0x00, 0x00); - set_mode_register(chip, 0xfc); /* 0xfc = ?? */ - - csp_test1 = read_register(chip, 0x83); - set_register(chip, 0x83, ~csp_test1); - csp_test2 = read_register(chip, 0x83); - if (csp_test2 != (csp_test1 ^ 0xff)) - goto __fail; - - set_register(chip, 0x83, csp_test1); - csp_test2 = read_register(chip, 0x83); - if (csp_test2 != csp_test1) - goto __fail; - - set_mode_register(chip, 0x00); /* 0x00 = ? */ - - *version = get_version(chip); - snd_sbdsp_reset(chip); /* reset DSP after getversion! */ - if (*version >= 0x10 && *version <= 0x1f) - result = 0; /* valid version id */ - - __fail: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return result; -} - -/* - * get CSP version number - */ -static int get_version(struct snd_sb *chip) -{ - unsigned char dsp_cmd[2]; - - dsp_cmd[0] = 0x08; /* SB_DSP_!something! */ - dsp_cmd[1] = 0x03; /* get chip version id? */ - command_seq(chip, dsp_cmd, 2); - - return (snd_sbdsp_get_byte(chip)); -} - -/* - * check if the CSP version is valid - */ -static int snd_sb_csp_check_version(struct snd_sb_csp * p) -{ - if (p->version < 0x10 || p->version > 0x1f) { - snd_printd("%s: Invalid CSP version: 0x%x\n", __func__, p->version); - return 1; - } - return 0; -} - -/* - * download microcode to CSP (microcode should have one "main" block). - */ -static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int size, int load_flags) -{ - int status, i; - int err; - int result = -EIO; - unsigned long flags; - - spin_lock_irqsave(&p->chip->reg_lock, flags); - snd_sbdsp_command(p->chip, 0x01); /* CSP download command */ - if (snd_sbdsp_get_byte(p->chip)) { - snd_printd("%s: Download command failed\n", __func__); - goto __fail; - } - /* Send CSP low byte (size - 1) */ - snd_sbdsp_command(p->chip, (unsigned char)(size - 1)); - /* Send high byte */ - snd_sbdsp_command(p->chip, (unsigned char)((size - 1) >> 8)); - /* send microcode sequence */ - /* load from kernel space */ - while (size--) { - if (!snd_sbdsp_command(p->chip, *buf++)) - goto __fail; - } - if (snd_sbdsp_get_byte(p->chip)) - goto __fail; - - if (load_flags & SNDRV_SB_CSP_LOAD_INITBLOCK) { - i = 0; - /* some codecs (FastSpeech) take some time to initialize */ - while (1) { - snd_sbdsp_command(p->chip, 0x03); - status = snd_sbdsp_get_byte(p->chip); - if (status == 0x55 || ++i >= 10) - break; - udelay (10); - } - if (status != 0x55) { - snd_printd("%s: Microcode initialization failed\n", __func__); - goto __fail; - } - } else { - /* - * Read mixer register SB_DSP4_DMASETUP after loading 'main' code. - * Start CSP chip if no 16bit DMA channel is set - some kind - * of autorun or perhaps a bugfix? - */ - spin_lock(&p->chip->mixer_lock); - status = snd_sbmixer_read(p->chip, SB_DSP4_DMASETUP); - spin_unlock(&p->chip->mixer_lock); - if (!(status & (SB_DMASETUP_DMA7 | SB_DMASETUP_DMA6 | SB_DMASETUP_DMA5))) { - err = (set_codec_parameter(p->chip, 0xaa, 0x00) || - set_codec_parameter(p->chip, 0xff, 0x00)); - snd_sbdsp_reset(p->chip); /* really! */ - if (err) - goto __fail; - set_mode_register(p->chip, 0xc0); /* c0 = STOP */ - set_mode_register(p->chip, 0x70); /* 70 = RUN */ - } - } - result = 0; - - __fail: - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - return result; -} - -static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags) -{ - 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; -} - -static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags) -{ - static const char *const names[] = { - "sb16/mulaw_main.csp", - "sb16/alaw_main.csp", - "sb16/ima_adpcm_init.csp", - "sb16/ima_adpcm_playback.csp", - "sb16/ima_adpcm_capture.csp", - }; - const struct firmware *program; - - BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT); - program = p->csp_programs[index]; - if (!program) { - int err = request_firmware(&program, names[index], - p->chip->card->dev); - if (err < 0) - return err; - p->csp_programs[index] = program; - } - return snd_sb_csp_load(p, program->data, program->size, flags); -} - -/* - * autoload hardware codec if necessary - * return 0 if CSP is loaded and ready to run (p->running != 0) - */ -static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode) -{ - unsigned long flags; - int err = 0; - - /* if CSP is running or manually loaded then exit */ - if (p->running & (SNDRV_SB_CSP_ST_RUNNING | SNDRV_SB_CSP_ST_LOADED)) - return -EBUSY; - - /* autoload microcode only if requested hardware codec is not already loaded */ - if (((1 << pcm_sfmt) & p->acc_format) && (play_rec_mode & p->mode)) { - p->running = SNDRV_SB_CSP_ST_AUTO; - } else { - switch (pcm_sfmt) { - case SNDRV_PCM_FORMAT_MU_LAW: - err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_MULAW, 0); - p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; - p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; - break; - case SNDRV_PCM_FORMAT_A_LAW: - err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ALAW, 0); - p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; - p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; - break; - case SNDRV_PCM_FORMAT_IMA_ADPCM: - err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ADPCM_INIT, - SNDRV_SB_CSP_LOAD_INITBLOCK); - if (err) - break; - if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) { - err = snd_sb_csp_firmware_load - (p, CSP_PROGRAM_ADPCM_PLAYBACK, 0); - p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE; - } else { - err = snd_sb_csp_firmware_load - (p, CSP_PROGRAM_ADPCM_CAPTURE, 0); - p->mode = SNDRV_SB_CSP_MODE_DSP_READ; - } - p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; - break; - default: - /* Decouple CSP from IRQ and DMAREQ lines */ - if (p->running & SNDRV_SB_CSP_ST_AUTO) { - spin_lock_irqsave(&p->chip->reg_lock, flags); - set_mode_register(p->chip, 0xfc); - set_mode_register(p->chip, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - p->running = 0; /* clear autoloaded flag */ - } - return -EINVAL; - } - if (err) { - p->acc_format = 0; - p->acc_channels = p->acc_width = p->acc_rates = 0; - - p->running = 0; /* clear autoloaded flag */ - p->mode = 0; - return (err); - } else { - p->running = SNDRV_SB_CSP_ST_AUTO; /* set autoloaded flag */ - p->acc_width = SNDRV_SB_CSP_SAMPLE_16BIT; /* only 16 bit data */ - p->acc_channels = SNDRV_SB_CSP_MONO | SNDRV_SB_CSP_STEREO; - p->acc_rates = SNDRV_SB_CSP_RATE_ALL; /* HW codecs accept all rates */ - } - - } - return (p->running & SNDRV_SB_CSP_ST_AUTO) ? 0 : -ENXIO; -} - -/* - * start CSP - */ -static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels) -{ - unsigned char s_type; /* sample type */ - unsigned char mixL, mixR; - int result = -EIO; - unsigned long flags; - - if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) { - snd_printd("%s: Microcode not loaded\n", __func__); - return -ENXIO; - } - if (p->running & SNDRV_SB_CSP_ST_RUNNING) { - snd_printd("%s: CSP already running\n", __func__); - return -EBUSY; - } - if (!(sample_width & p->acc_width)) { - snd_printd("%s: Unsupported PCM sample width\n", __func__); - return -EINVAL; - } - if (!(channels & p->acc_channels)) { - snd_printd("%s: Invalid number of channels\n", __func__); - return -EINVAL; - } - - /* Mute PCM volume */ - spin_lock_irqsave(&p->chip->mixer_lock, flags); - mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); - mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); - - spin_lock(&p->chip->reg_lock); - set_mode_register(p->chip, 0xc0); /* c0 = STOP */ - set_mode_register(p->chip, 0x70); /* 70 = RUN */ - - s_type = 0x00; - if (channels == SNDRV_SB_CSP_MONO) - s_type = 0x11; /* 000n 000n (n = 1 if mono) */ - if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT) - s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */ - - if (set_codec_parameter(p->chip, 0x81, s_type)) { - snd_printd("%s: Set sample type command failed\n", __func__); - goto __fail; - } - if (set_codec_parameter(p->chip, 0x80, 0x00)) { - snd_printd("%s: Codec start command failed\n", __func__); - goto __fail; - } - p->run_width = sample_width; - p->run_channels = channels; - - p->running |= SNDRV_SB_CSP_ST_RUNNING; - - if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) { - set_codec_parameter(p->chip, 0xe0, 0x01); - /* enable QSound decoder */ - set_codec_parameter(p->chip, 0x00, 0xff); - set_codec_parameter(p->chip, 0x01, 0xff); - p->running |= SNDRV_SB_CSP_ST_QSOUND; - /* set QSound startup value */ - snd_sb_csp_qsound_transfer(p); - } - result = 0; - - __fail: - spin_unlock(&p->chip->reg_lock); - - /* restore PCM volume */ - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); - spin_unlock_irqrestore(&p->chip->mixer_lock, flags); - - return result; -} - -/* - * stop CSP - */ -static int snd_sb_csp_stop(struct snd_sb_csp * p) -{ - int result; - unsigned char mixL, mixR; - unsigned long flags; - - if (!(p->running & SNDRV_SB_CSP_ST_RUNNING)) - return 0; - - /* Mute PCM volume */ - spin_lock_irqsave(&p->chip->mixer_lock, flags); - mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); - mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); - - spin_lock(&p->chip->reg_lock); - if (p->running & SNDRV_SB_CSP_ST_QSOUND) { - set_codec_parameter(p->chip, 0xe0, 0x01); - /* disable QSound decoder */ - set_codec_parameter(p->chip, 0x00, 0x00); - set_codec_parameter(p->chip, 0x01, 0x00); - - p->running &= ~SNDRV_SB_CSP_ST_QSOUND; - } - result = set_mode_register(p->chip, 0xc0); /* c0 = STOP */ - spin_unlock(&p->chip->reg_lock); - - /* restore PCM volume */ - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); - spin_unlock_irqrestore(&p->chip->mixer_lock, flags); - - if (!(result)) - p->running &= ~(SNDRV_SB_CSP_ST_PAUSED | SNDRV_SB_CSP_ST_RUNNING); - return result; -} - -/* - * pause CSP codec and hold DMA transfer - */ -static int snd_sb_csp_pause(struct snd_sb_csp * p) -{ - int result; - unsigned long flags; - - if (!(p->running & SNDRV_SB_CSP_ST_RUNNING)) - return -EBUSY; - - spin_lock_irqsave(&p->chip->reg_lock, flags); - result = set_codec_parameter(p->chip, 0x80, 0xff); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - if (!(result)) - p->running |= SNDRV_SB_CSP_ST_PAUSED; - - return result; -} - -/* - * restart CSP codec and resume DMA transfer - */ -static int snd_sb_csp_restart(struct snd_sb_csp * p) -{ - int result; - unsigned long flags; - - if (!(p->running & SNDRV_SB_CSP_ST_PAUSED)) - return -EBUSY; - - spin_lock_irqsave(&p->chip->reg_lock, flags); - result = set_codec_parameter(p->chip, 0x80, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - if (!(result)) - p->running &= ~SNDRV_SB_CSP_ST_PAUSED; - - return result; -} - -/* ------------------------------ */ - -/* - * QSound mixer control for PCM - */ - -#define snd_sb_qsound_switch_info snd_ctl_boolean_mono_info - -static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = p->q_enabled ? 1 : 0; - return 0; -} - -static int snd_sb_qsound_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval; - - nval = ucontrol->value.integer.value[0] & 0x01; - spin_lock_irqsave(&p->q_lock, flags); - change = p->q_enabled != nval; - p->q_enabled = nval; - spin_unlock_irqrestore(&p->q_lock, flags); - return change; -} - -static int snd_sb_qsound_space_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; - return 0; -} - -static int snd_sb_qsound_space_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&p->q_lock, flags); - ucontrol->value.integer.value[0] = p->qpos_left; - ucontrol->value.integer.value[1] = p->qpos_right; - spin_unlock_irqrestore(&p->q_lock, flags); - return 0; -} - -static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval1, nval2; - - nval1 = ucontrol->value.integer.value[0]; - if (nval1 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT) - nval1 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; - nval2 = ucontrol->value.integer.value[1]; - if (nval2 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT) - nval2 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; - spin_lock_irqsave(&p->q_lock, flags); - change = p->qpos_left != nval1 || p->qpos_right != nval2; - p->qpos_left = nval1; - p->qpos_right = nval2; - p->qpos_changed = change; - spin_unlock_irqrestore(&p->q_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_sb_qsound_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "3D Control - Switch", - .info = snd_sb_qsound_switch_info, - .get = snd_sb_qsound_switch_get, - .put = snd_sb_qsound_switch_put -}; - -static struct snd_kcontrol_new snd_sb_qsound_space = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "3D Control - Space", - .info = snd_sb_qsound_space_info, - .get = snd_sb_qsound_space_get, - .put = snd_sb_qsound_space_put -}; - -static int snd_sb_qsound_build(struct snd_sb_csp * p) -{ - struct snd_card *card; - int err; - - if (snd_BUG_ON(!p)) - return -EINVAL; - - card = p->chip->card; - p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2; - p->qpos_changed = 0; - - spin_lock_init(&p->q_lock); - - if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0) - goto __error; - if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0) - goto __error; - - return 0; - - __error: - snd_sb_qsound_destroy(p); - return err; -} - -static void snd_sb_qsound_destroy(struct snd_sb_csp * p) -{ - struct snd_card *card; - unsigned long flags; - - if (snd_BUG_ON(!p)) - return; - - card = p->chip->card; - - down_write(&card->controls_rwsem); - if (p->qsound_switch) - snd_ctl_remove(card, p->qsound_switch); - if (p->qsound_space) - snd_ctl_remove(card, p->qsound_space); - up_write(&card->controls_rwsem); - - /* cancel pending transfer of QSound parameters */ - spin_lock_irqsave (&p->q_lock, flags); - p->qpos_changed = 0; - spin_unlock_irqrestore (&p->q_lock, flags); -} - -/* - * Transfer qsound parameters to CSP, - * function should be called from interrupt routine - */ -static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p) -{ - int err = -ENXIO; - - spin_lock(&p->q_lock); - if (p->running & SNDRV_SB_CSP_ST_QSOUND) { - set_codec_parameter(p->chip, 0xe0, 0x01); - /* left channel */ - set_codec_parameter(p->chip, 0x00, p->qpos_left); - set_codec_parameter(p->chip, 0x02, 0x00); - /* right channel */ - set_codec_parameter(p->chip, 0x00, p->qpos_right); - set_codec_parameter(p->chip, 0x03, 0x00); - err = 0; - } - p->qpos_changed = 0; - spin_unlock(&p->q_lock); - return err; -} - -/* ------------------------------ */ - -/* - * proc interface - */ -static int init_proc_entry(struct snd_sb_csp * p, int device) -{ - char name[16]; - struct snd_info_entry *entry; - sprintf(name, "cspD%d", device); - if (! snd_card_proc_new(p->chip->card, name, &entry)) - snd_info_set_text_ops(entry, p, info_read); - return 0; -} - -static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_sb_csp *p = entry->private_data; - - snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f)); - snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'), - ((p->running & SNDRV_SB_CSP_ST_PAUSED) ? 'P' : '-'), - ((p->running & SNDRV_SB_CSP_ST_RUNNING) ? 'R' : '-'), - ((p->running & SNDRV_SB_CSP_ST_LOADED) ? 'L' : '-')); - if (p->running & SNDRV_SB_CSP_ST_LOADED) { - snd_iprintf(buffer, "Codec: %s [func #%d]\n", p->codec_name, p->func_nr); - snd_iprintf(buffer, "Sample rates: "); - if (p->acc_rates == SNDRV_SB_CSP_RATE_ALL) { - snd_iprintf(buffer, "All\n"); - } else { - snd_iprintf(buffer, "%s%s%s%s\n", - ((p->acc_rates & SNDRV_SB_CSP_RATE_8000) ? "8000Hz " : ""), - ((p->acc_rates & SNDRV_SB_CSP_RATE_11025) ? "11025Hz " : ""), - ((p->acc_rates & SNDRV_SB_CSP_RATE_22050) ? "22050Hz " : ""), - ((p->acc_rates & SNDRV_SB_CSP_RATE_44100) ? "44100Hz" : "")); - } - if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { - snd_iprintf(buffer, "QSound decoder %sabled\n", - p->q_enabled ? "en" : "dis"); - } else { - snd_iprintf(buffer, "PCM format ID: 0x%x (%s/%s) [%s/%s] [%s/%s]\n", - p->acc_format, - ((p->acc_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? "16bit" : "-"), - ((p->acc_width & SNDRV_SB_CSP_SAMPLE_8BIT) ? "8bit" : "-"), - ((p->acc_channels & SNDRV_SB_CSP_MONO) ? "mono" : "-"), - ((p->acc_channels & SNDRV_SB_CSP_STEREO) ? "stereo" : "-"), - ((p->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) ? "playback" : "-"), - ((p->mode & SNDRV_SB_CSP_MODE_DSP_READ) ? "capture" : "-")); - } - } - if (p->running & SNDRV_SB_CSP_ST_AUTO) { - snd_iprintf(buffer, "Autoloaded Mu-Law, A-Law or Ima-ADPCM hardware codec\n"); - } - if (p->running & SNDRV_SB_CSP_ST_RUNNING) { - snd_iprintf(buffer, "Processing %dbit %s PCM samples\n", - ((p->run_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? 16 : 8), - ((p->run_channels & SNDRV_SB_CSP_MONO) ? "mono" : "stereo")); - } - if (p->running & SNDRV_SB_CSP_ST_QSOUND) { - snd_iprintf(buffer, "Qsound position: left = 0x%x, right = 0x%x\n", - p->qpos_left, p->qpos_right); - } -} - -/* */ - -EXPORT_SYMBOL(snd_sb_csp_new); - -/* - * INIT part - */ - -static int __init alsa_sb_csp_init(void) -{ - return 0; -} - -static void __exit alsa_sb_csp_exit(void) -{ -} - -module_init(alsa_sb_csp_init) -module_exit(alsa_sb_csp_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb16_main.c b/ANDROID_3.4.5/sound/isa/sb/sb16_main.c deleted file mode 100644 index 0bbcd471..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb16_main.c +++ /dev/null @@ -1,925 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of 16-bit SoundBlaster cards and clones - * Note: This is very ugly hardware which uses one 8-bit DMA channel and - * second 16-bit DMA channel. Unfortunately 8-bit DMA channel can't - * transfer 16-bit samples and 16-bit DMA channels can't transfer - * 8-bit samples. This make full duplex more complicated than - * can be... People, don't buy these soundcards for full 16-bit - * duplex!!! - * Note: 16-bit wide is assigned to first direction which made request. - * With full duplex - playback is preferred with abstract layer. - * - * Note: Some chip revisions have hardware bug. Changing capture - * channel from full-duplex 8bit DMA to 16bit DMA will block - * 16bit DMA transfers from DSP chip (capture) until 8bit transfer - * to DSP chip (playback) starts. This bug can be avoided with - * "16bit DMA Allocation" setting set to Playback or Capture. - * - * - * 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 -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones"); -MODULE_LICENSE("GPL"); - -#ifdef CONFIG_SND_SB16_CSP -static void snd_sb16_csp_playback_prepare(struct snd_sb *chip, struct snd_pcm_runtime *runtime) -{ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->running & SNDRV_SB_CSP_ST_LOADED) { - /* manually loaded codec */ - if ((csp->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) && - ((1U << runtime->format) == csp->acc_format)) { - /* Supported runtime PCM format for playback */ - if (csp->ops.csp_use(csp) == 0) { - /* If CSP was successfully acquired */ - goto __start_CSP; - } - } else if ((csp->mode & SNDRV_SB_CSP_MODE_QSOUND) && (csp->q_enabled)) { - /* QSound decoder is loaded and enabled */ - if ((1 << runtime->format) & (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE)) { - /* Only for simple PCM formats */ - if (csp->ops.csp_use(csp) == 0) { - /* If CSP was successfully acquired */ - goto __start_CSP; - } - } - } - } else if (csp->ops.csp_use(csp) == 0) { - /* Acquire CSP and try to autoload hardware codec */ - if (csp->ops.csp_autoload(csp, runtime->format, SNDRV_SB_CSP_MODE_DSP_WRITE)) { - /* Unsupported format, release CSP */ - csp->ops.csp_unuse(csp); - } else { - __start_CSP: - /* Try to start CSP */ - if (csp->ops.csp_start(csp, (chip->mode & SB_MODE_PLAYBACK_16) ? - SNDRV_SB_CSP_SAMPLE_16BIT : SNDRV_SB_CSP_SAMPLE_8BIT, - (runtime->channels > 1) ? - SNDRV_SB_CSP_STEREO : SNDRV_SB_CSP_MONO)) { - /* Failed, release CSP */ - csp->ops.csp_unuse(csp); - } else { - /* Success, CSP acquired and running */ - chip->open = SNDRV_SB_CSP_MODE_DSP_WRITE; - } - } - } - } -} - -static void snd_sb16_csp_capture_prepare(struct snd_sb *chip, struct snd_pcm_runtime *runtime) -{ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->running & SNDRV_SB_CSP_ST_LOADED) { - /* manually loaded codec */ - if ((csp->mode & SNDRV_SB_CSP_MODE_DSP_READ) && - ((1U << runtime->format) == csp->acc_format)) { - /* Supported runtime PCM format for capture */ - if (csp->ops.csp_use(csp) == 0) { - /* If CSP was successfully acquired */ - goto __start_CSP; - } - } - } else if (csp->ops.csp_use(csp) == 0) { - /* Acquire CSP and try to autoload hardware codec */ - if (csp->ops.csp_autoload(csp, runtime->format, SNDRV_SB_CSP_MODE_DSP_READ)) { - /* Unsupported format, release CSP */ - csp->ops.csp_unuse(csp); - } else { - __start_CSP: - /* Try to start CSP */ - if (csp->ops.csp_start(csp, (chip->mode & SB_MODE_CAPTURE_16) ? - SNDRV_SB_CSP_SAMPLE_16BIT : SNDRV_SB_CSP_SAMPLE_8BIT, - (runtime->channels > 1) ? - SNDRV_SB_CSP_STEREO : SNDRV_SB_CSP_MONO)) { - /* Failed, release CSP */ - csp->ops.csp_unuse(csp); - } else { - /* Success, CSP acquired and running */ - chip->open = SNDRV_SB_CSP_MODE_DSP_READ; - } - } - } - } -} - -static void snd_sb16_csp_update(struct snd_sb *chip) -{ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->qpos_changed) { - spin_lock(&chip->reg_lock); - csp->ops.csp_qsound_transfer (csp); - spin_unlock(&chip->reg_lock); - } - } -} - -static void snd_sb16_csp_playback_open(struct snd_sb *chip, struct snd_pcm_runtime *runtime) -{ - /* CSP decoders (QSound excluded) support only 16bit transfers */ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->running & SNDRV_SB_CSP_ST_LOADED) { - /* manually loaded codec */ - if (csp->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) { - runtime->hw.formats |= csp->acc_format; - } - } else { - /* autoloaded codecs */ - runtime->hw.formats |= SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_IMA_ADPCM; - } - } -} - -static void snd_sb16_csp_playback_close(struct snd_sb *chip) -{ - if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_WRITE)) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->ops.csp_stop(csp) == 0) { - csp->ops.csp_unuse(csp); - chip->open = 0; - } - } -} - -static void snd_sb16_csp_capture_open(struct snd_sb *chip, struct snd_pcm_runtime *runtime) -{ - /* CSP coders support only 16bit transfers */ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->running & SNDRV_SB_CSP_ST_LOADED) { - /* manually loaded codec */ - if (csp->mode & SNDRV_SB_CSP_MODE_DSP_READ) { - runtime->hw.formats |= csp->acc_format; - } - } else { - /* autoloaded codecs */ - runtime->hw.formats |= SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_IMA_ADPCM; - } - } -} - -static void snd_sb16_csp_capture_close(struct snd_sb *chip) -{ - if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_READ)) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->ops.csp_stop(csp) == 0) { - csp->ops.csp_unuse(csp); - chip->open = 0; - } - } -} -#else -#define snd_sb16_csp_playback_prepare(chip, runtime) /*nop*/ -#define snd_sb16_csp_capture_prepare(chip, runtime) /*nop*/ -#define snd_sb16_csp_update(chip) /*nop*/ -#define snd_sb16_csp_playback_open(chip, runtime) /*nop*/ -#define snd_sb16_csp_playback_close(chip) /*nop*/ -#define snd_sb16_csp_capture_open(chip, runtime) /*nop*/ -#define snd_sb16_csp_capture_close(chip) /*nop*/ -#endif - - -static void snd_sb16_setup_rate(struct snd_sb *chip, - unsigned short rate, - int channel) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->mode & (channel == SNDRV_PCM_STREAM_PLAYBACK ? SB_MODE_PLAYBACK_16 : SB_MODE_CAPTURE_16)) - snd_sb_ack_16bit(chip); - else - snd_sb_ack_8bit(chip); - if (!(chip->mode & SB_RATE_LOCK)) { - chip->locked_rate = rate; - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_IN); - snd_sbdsp_command(chip, rate >> 8); - snd_sbdsp_command(chip, rate & 0xff); - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_OUT); - snd_sbdsp_command(chip, rate >> 8); - snd_sbdsp_command(chip, rate & 0xff); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static int snd_sb16_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_sb16_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_sb16_playback_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned char format; - unsigned int size, count, dma; - - snd_sb16_csp_playback_prepare(chip, runtime); - if (snd_pcm_format_unsigned(runtime->format) > 0) { - format = runtime->channels > 1 ? SB_DSP4_MODE_UNS_STEREO : SB_DSP4_MODE_UNS_MONO; - } else { - format = runtime->channels > 1 ? SB_DSP4_MODE_SIGN_STEREO : SB_DSP4_MODE_SIGN_MONO; - } - - snd_sb16_setup_rate(chip, runtime->rate, SNDRV_PCM_STREAM_PLAYBACK); - size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream); - dma = (chip->mode & SB_MODE_PLAYBACK_8) ? chip->dma8 : chip->dma16; - snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - - count = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->mode & SB_MODE_PLAYBACK_16) { - count >>= 1; - count--; - snd_sbdsp_command(chip, SB_DSP4_OUT16_AI); - snd_sbdsp_command(chip, format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, SB_DSP_DMA16_OFF); - } else { - count--; - snd_sbdsp_command(chip, SB_DSP4_OUT8_AI); - snd_sbdsp_command(chip, format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_sb16_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - int result = 0; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - chip->mode |= SB_RATE_LOCK_PLAYBACK; - snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF); - /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */ - if (chip->mode & SB_RATE_LOCK_CAPTURE) - snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); - chip->mode &= ~SB_RATE_LOCK_PLAYBACK; - break; - default: - result = -EINVAL; - } - spin_unlock(&chip->reg_lock); - return result; -} - -static int snd_sb16_capture_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned char format; - unsigned int size, count, dma; - - snd_sb16_csp_capture_prepare(chip, runtime); - if (snd_pcm_format_unsigned(runtime->format) > 0) { - format = runtime->channels > 1 ? SB_DSP4_MODE_UNS_STEREO : SB_DSP4_MODE_UNS_MONO; - } else { - format = runtime->channels > 1 ? SB_DSP4_MODE_SIGN_STEREO : SB_DSP4_MODE_SIGN_MONO; - } - snd_sb16_setup_rate(chip, runtime->rate, SNDRV_PCM_STREAM_CAPTURE); - size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream); - dma = (chip->mode & SB_MODE_CAPTURE_8) ? chip->dma8 : chip->dma16; - snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - - count = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->mode & SB_MODE_CAPTURE_16) { - count >>= 1; - count--; - snd_sbdsp_command(chip, SB_DSP4_IN16_AI); - snd_sbdsp_command(chip, format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, SB_DSP_DMA16_OFF); - } else { - count--; - snd_sbdsp_command(chip, SB_DSP4_IN8_AI); - snd_sbdsp_command(chip, format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_sb16_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - int result = 0; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - chip->mode |= SB_RATE_LOCK_CAPTURE; - snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF); - /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */ - if (chip->mode & SB_RATE_LOCK_PLAYBACK) - snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); - chip->mode &= ~SB_RATE_LOCK_CAPTURE; - break; - default: - result = -EINVAL; - } - spin_unlock(&chip->reg_lock); - return result; -} - -irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id) -{ - struct snd_sb *chip = dev_id; - unsigned char status; - int ok; - - spin_lock(&chip->mixer_lock); - status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); - spin_unlock(&chip->mixer_lock); - if ((status & SB_IRQTYPE_MPUIN) && chip->rmidi_callback) - chip->rmidi_callback(irq, chip->rmidi->private_data); - if (status & SB_IRQTYPE_8BIT) { - ok = 0; - if (chip->mode & SB_MODE_PLAYBACK_8) { - snd_pcm_period_elapsed(chip->playback_substream); - snd_sb16_csp_update(chip); - ok++; - } - if (chip->mode & SB_MODE_CAPTURE_8) { - snd_pcm_period_elapsed(chip->capture_substream); - ok++; - } - spin_lock(&chip->reg_lock); - if (!ok) - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - snd_sb_ack_8bit(chip); - spin_unlock(&chip->reg_lock); - } - if (status & SB_IRQTYPE_16BIT) { - ok = 0; - if (chip->mode & SB_MODE_PLAYBACK_16) { - snd_pcm_period_elapsed(chip->playback_substream); - snd_sb16_csp_update(chip); - ok++; - } - if (chip->mode & SB_MODE_CAPTURE_16) { - snd_pcm_period_elapsed(chip->capture_substream); - ok++; - } - spin_lock(&chip->reg_lock); - if (!ok) - snd_sbdsp_command(chip, SB_DSP_DMA16_OFF); - snd_sb_ack_16bit(chip); - spin_unlock(&chip->reg_lock); - } - return IRQ_HANDLED; -} - -/* - - */ - -static snd_pcm_uframes_t snd_sb16_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int dma; - size_t ptr; - - dma = (chip->mode & SB_MODE_PLAYBACK_8) ? chip->dma8 : chip->dma16; - ptr = snd_dma_pointer(dma, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_sb16_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int dma; - size_t ptr; - - dma = (chip->mode & SB_MODE_CAPTURE_8) ? chip->dma8 : chip->dma16; - ptr = snd_dma_pointer(dma, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -/* - - */ - -static struct snd_pcm_hardware snd_sb16_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = 0, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100, - .rate_min = 4000, - .rate_max = 44100, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_sb16_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = 0, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100, - .rate_min = 4000, - .rate_max = 44100, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * open/close - */ - -static int snd_sb16_playback_open(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->mode & SB_MODE_PLAYBACK) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - runtime->hw = snd_sb16_playback; - - /* skip if 16 bit DMA was reserved for capture */ - if (chip->force_mode16 & SB_MODE_CAPTURE_16) - goto __skip_16bit; - - if (chip->dma16 >= 0 && !(chip->mode & SB_MODE_CAPTURE_16)) { - chip->mode |= SB_MODE_PLAYBACK_16; - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE; - /* Vibra16X hack */ - if (chip->dma16 <= 3) { - runtime->hw.buffer_bytes_max = - runtime->hw.period_bytes_max = 64 * 1024; - } else { - snd_sb16_csp_playback_open(chip, runtime); - } - goto __open_ok; - } - - __skip_16bit: - if (chip->dma8 >= 0 && !(chip->mode & SB_MODE_CAPTURE_8)) { - chip->mode |= SB_MODE_PLAYBACK_8; - /* DSP v 4.xx can transfer 16bit data through 8bit DMA channel, SBHWPG 2-7 */ - if (chip->dma16 < 0) { - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE; - chip->mode |= SB_MODE_PLAYBACK_16; - } else { - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8; - } - runtime->hw.buffer_bytes_max = - runtime->hw.period_bytes_max = 64 * 1024; - goto __open_ok; - } - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - - __open_ok: - if (chip->hardware == SB_HW_ALS100) - runtime->hw.rate_max = 48000; - if (chip->hardware == SB_HW_CS5530) { - runtime->hw.buffer_bytes_max = 32 * 1024; - runtime->hw.periods_min = 2; - runtime->hw.rate_min = 44100; - } - if (chip->mode & SB_RATE_LOCK) - runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; - chip->playback_substream = substream; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -static int snd_sb16_playback_close(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - - snd_sb16_csp_playback_close(chip); - spin_lock_irqsave(&chip->open_lock, flags); - chip->playback_substream = NULL; - chip->mode &= ~SB_MODE_PLAYBACK; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -static int snd_sb16_capture_open(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->mode & SB_MODE_CAPTURE) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - runtime->hw = snd_sb16_capture; - - /* skip if 16 bit DMA was reserved for playback */ - if (chip->force_mode16 & SB_MODE_PLAYBACK_16) - goto __skip_16bit; - - if (chip->dma16 >= 0 && !(chip->mode & SB_MODE_PLAYBACK_16)) { - chip->mode |= SB_MODE_CAPTURE_16; - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE; - /* Vibra16X hack */ - if (chip->dma16 <= 3) { - runtime->hw.buffer_bytes_max = - runtime->hw.period_bytes_max = 64 * 1024; - } else { - snd_sb16_csp_capture_open(chip, runtime); - } - goto __open_ok; - } - - __skip_16bit: - if (chip->dma8 >= 0 && !(chip->mode & SB_MODE_PLAYBACK_8)) { - chip->mode |= SB_MODE_CAPTURE_8; - /* DSP v 4.xx can transfer 16bit data through 8bit DMA channel, SBHWPG 2-7 */ - if (chip->dma16 < 0) { - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE; - chip->mode |= SB_MODE_CAPTURE_16; - } else { - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8; - } - runtime->hw.buffer_bytes_max = - runtime->hw.period_bytes_max = 64 * 1024; - goto __open_ok; - } - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - - __open_ok: - if (chip->hardware == SB_HW_ALS100) - runtime->hw.rate_max = 48000; - if (chip->hardware == SB_HW_CS5530) { - runtime->hw.buffer_bytes_max = 32 * 1024; - runtime->hw.periods_min = 2; - runtime->hw.rate_min = 44100; - } - if (chip->mode & SB_RATE_LOCK) - runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; - chip->capture_substream = substream; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -static int snd_sb16_capture_close(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - - snd_sb16_csp_capture_close(chip); - spin_lock_irqsave(&chip->open_lock, flags); - chip->capture_substream = NULL; - chip->mode &= ~SB_MODE_CAPTURE; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -/* - * DMA control interface - */ - -static int snd_sb16_set_dma_mode(struct snd_sb *chip, int what) -{ - if (chip->dma8 < 0 || chip->dma16 < 0) { - if (snd_BUG_ON(what)) - return -EINVAL; - return 0; - } - if (what == 0) { - chip->force_mode16 = 0; - } else if (what == 1) { - chip->force_mode16 = SB_MODE_PLAYBACK_16; - } else if (what == 2) { - chip->force_mode16 = SB_MODE_CAPTURE_16; - } else { - return -EINVAL; - } - return 0; -} - -static int snd_sb16_get_dma_mode(struct snd_sb *chip) -{ - if (chip->dma8 < 0 || chip->dma16 < 0) - return 0; - switch (chip->force_mode16) { - case SB_MODE_PLAYBACK_16: - return 1; - case SB_MODE_CAPTURE_16: - return 2; - default: - return 0; - } -} - -static int snd_sb16_dma_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { - "Auto", "Playback", "Capture" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_sb16_dma_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.enumerated.item[0] = snd_sb16_get_dma_mode(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char nval, oval; - int change; - - if ((nval = ucontrol->value.enumerated.item[0]) > 2) - return -EINVAL; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = snd_sb16_get_dma_mode(chip); - change = nval != oval; - snd_sb16_set_dma_mode(chip, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_sb16_dma_control = { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "16-bit DMA Allocation", - .info = snd_sb16_dma_control_info, - .get = snd_sb16_dma_control_get, - .put = snd_sb16_dma_control_put -}; - -/* - * Initialization part - */ - -int snd_sb16dsp_configure(struct snd_sb * chip) -{ - unsigned long flags; - unsigned char irqreg = 0, dmareg = 0, mpureg; - unsigned char realirq, realdma, realmpureg; - /* note: mpu register should be present only on SB16 Vibra soundcards */ - - // printk(KERN_DEBUG "codec->irq=%i, codec->dma8=%i, codec->dma16=%i\n", chip->irq, chip->dma8, chip->dma16); - spin_lock_irqsave(&chip->mixer_lock, flags); - mpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP) & ~0x06; - spin_unlock_irqrestore(&chip->mixer_lock, flags); - switch (chip->irq) { - case 2: - case 9: - irqreg |= SB_IRQSETUP_IRQ9; - break; - case 5: - irqreg |= SB_IRQSETUP_IRQ5; - break; - case 7: - irqreg |= SB_IRQSETUP_IRQ7; - break; - case 10: - irqreg |= SB_IRQSETUP_IRQ10; - break; - default: - return -EINVAL; - } - if (chip->dma8 >= 0) { - switch (chip->dma8) { - case 0: - dmareg |= SB_DMASETUP_DMA0; - break; - case 1: - dmareg |= SB_DMASETUP_DMA1; - break; - case 3: - dmareg |= SB_DMASETUP_DMA3; - break; - default: - return -EINVAL; - } - } - if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) { - switch (chip->dma16) { - case 5: - dmareg |= SB_DMASETUP_DMA5; - break; - case 6: - dmareg |= SB_DMASETUP_DMA6; - break; - case 7: - dmareg |= SB_DMASETUP_DMA7; - break; - default: - return -EINVAL; - } - } - switch (chip->mpu_port) { - case 0x300: - mpureg |= 0x04; - break; - case 0x330: - mpureg |= 0x00; - break; - default: - mpureg |= 0x02; /* disable MPU */ - } - spin_lock_irqsave(&chip->mixer_lock, flags); - - snd_sbmixer_write(chip, SB_DSP4_IRQSETUP, irqreg); - realirq = snd_sbmixer_read(chip, SB_DSP4_IRQSETUP); - - snd_sbmixer_write(chip, SB_DSP4_DMASETUP, dmareg); - realdma = snd_sbmixer_read(chip, SB_DSP4_DMASETUP); - - snd_sbmixer_write(chip, SB_DSP4_MPUSETUP, mpureg); - realmpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP); - - spin_unlock_irqrestore(&chip->mixer_lock, flags); - if ((~realirq) & irqreg || (~realdma) & dmareg) { - snd_printk(KERN_ERR "SB16 [0x%lx]: unable to set DMA & IRQ (PnP device?)\n", chip->port); - snd_printk(KERN_ERR "SB16 [0x%lx]: wanted: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, realirq, realdma, realmpureg); - snd_printk(KERN_ERR "SB16 [0x%lx]: got: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, irqreg, dmareg, mpureg); - return -ENODEV; - } - return 0; -} - -static struct snd_pcm_ops snd_sb16_playback_ops = { - .open = snd_sb16_playback_open, - .close = snd_sb16_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sb16_hw_params, - .hw_free = snd_sb16_hw_free, - .prepare = snd_sb16_playback_prepare, - .trigger = snd_sb16_playback_trigger, - .pointer = snd_sb16_playback_pointer, -}; - -static struct snd_pcm_ops snd_sb16_capture_ops = { - .open = snd_sb16_capture_open, - .close = snd_sb16_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sb16_hw_params, - .hw_free = snd_sb16_hw_free, - .prepare = snd_sb16_capture_prepare, - .trigger = snd_sb16_capture_trigger, - .pointer = snd_sb16_capture_pointer, -}; - -int snd_sb16dsp_pcm(struct snd_sb * chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_card *card = chip->card; - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(card, "SB16 DSP", device, 1, 1, &pcm)) < 0) - return err; - sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops); - - if (chip->dma16 >= 0 && chip->dma8 != chip->dma16) - snd_ctl_add(card, snd_ctl_new1(&snd_sb16_dma_control, chip)); - else - pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, 128*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -const struct snd_pcm_ops *snd_sb16dsp_get_pcm_ops(int direction) -{ - return direction == SNDRV_PCM_STREAM_PLAYBACK ? - &snd_sb16_playback_ops : &snd_sb16_capture_ops; -} - -EXPORT_SYMBOL(snd_sb16dsp_pcm); -EXPORT_SYMBOL(snd_sb16dsp_get_pcm_ops); -EXPORT_SYMBOL(snd_sb16dsp_configure); -EXPORT_SYMBOL(snd_sb16dsp_interrupt); - -/* - * INIT part - */ - -static int __init alsa_sb16_init(void) -{ - return 0; -} - -static void __exit alsa_sb16_exit(void) -{ -} - -module_init(alsa_sb16_init) -module_exit(alsa_sb16_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb8.c b/ANDROID_3.4.5/sound/isa/sb/sb8.c deleted file mode 100644 index ab5cebea..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb8.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Driver for SoundBlaster 1.0/2.0/Pro soundcards and compatible - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Sound Blaster soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Sound Blaster soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Sound Blaster soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for SB8 driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for SB8 driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver."); - -struct snd_sb8 { - struct resource *fm_res; /* used to block FM i/o region for legacy cards */ - struct snd_sb *chip; -}; - -static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id) -{ - struct snd_sb *chip = dev_id; - - if (chip->open & SB_OPEN_PCM) { - return snd_sb8dsp_interrupt(chip); - } else { - return snd_sb8dsp_midi_interrupt(chip); - } -} - -static void snd_sb8_free(struct snd_card *card) -{ - struct snd_sb8 *acard = card->private_data; - - if (acard == NULL) - return; - release_and_free_resource(acard->fm_res); -} - -static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev) -{ - if (!enable[dev]) - return 0; - if (irq[dev] == SNDRV_AUTO_IRQ) { - dev_err(pdev, "please specify irq\n"); - return 0; - } - if (dma8[dev] == SNDRV_AUTO_DMA) { - dev_err(pdev, "please specify dma8\n"); - return 0; - } - return 1; -} - -static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) -{ - struct snd_sb *chip; - struct snd_card *card; - struct snd_sb8 *acard; - struct snd_opl3 *opl3; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_sb8), &card); - if (err < 0) - return err; - acard = card->private_data; - card->private_free = snd_sb8_free; - - /* block the 0x388 port to avoid PnP conflicts */ - acard->fm_res = request_region(0x388, 4, "SoundBlaster FM"); - - if (port[dev] != SNDRV_AUTO_PORT) { - if ((err = snd_sbdsp_create(card, port[dev], irq[dev], - snd_sb8_interrupt, - dma8[dev], - -1, - SB_HW_AUTO, - &chip)) < 0) - goto _err; - } else { - /* auto-probe legacy ports */ - static unsigned long possible_ports[] = { - 0x220, 0x240, 0x260, - }; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - err = snd_sbdsp_create(card, possible_ports[i], - irq[dev], - snd_sb8_interrupt, - dma8[dev], - -1, - SB_HW_AUTO, - &chip); - if (err >= 0) { - port[dev] = possible_ports[i]; - break; - } - } - if (i >= ARRAY_SIZE(possible_ports)) { - err = -EINVAL; - goto _err; - } - } - acard->chip = chip; - - if (chip->hardware >= SB_HW_16) { - if (chip->hardware == SB_HW_ALS100) - snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n", - port[dev]); - else - snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n", - port[dev]); - err = -ENODEV; - goto _err; - } - - if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) - goto _err; - - if ((err = snd_sbmixer_new(chip)) < 0) - goto _err; - - if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) { - if ((err = snd_opl3_create(card, chip->port + 8, 0, - OPL3_HW_AUTO, 1, - &opl3)) < 0) { - snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8); - } - } else { - if ((err = snd_opl3_create(card, chip->port, chip->port + 2, - OPL3_HW_AUTO, 1, - &opl3)) < 0) { - snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n", - chip->port, chip->port + 2); - } - } - if (err >= 0) { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) - goto _err; - } - - if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) - goto _err; - - strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8"); - strcpy(card->shortname, chip->name); - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - chip->name, - chip->port, - irq[dev], dma8[dev]); - - snd_card_set_dev(card, pdev); - - if ((err = snd_card_register(card)) < 0) - goto _err; - - dev_set_drvdata(pdev, card); - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devexit snd_sb8_remove(struct device *pdev, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(pdev)); - dev_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_sb8_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_sb8 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - return 0; -} - -static int snd_sb8_resume(struct device *dev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_sb8 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -#define DEV_NAME "sb8" - -static struct isa_driver snd_sb8_driver = { - .match = snd_sb8_match, - .probe = snd_sb8_probe, - .remove = __devexit_p(snd_sb8_remove), -#ifdef CONFIG_PM - .suspend = snd_sb8_suspend, - .resume = snd_sb8_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - -static int __init alsa_card_sb8_init(void) -{ - return isa_register_driver(&snd_sb8_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_sb8_exit(void) -{ - isa_unregister_driver(&snd_sb8_driver); -} - -module_init(alsa_card_sb8_init) -module_exit(alsa_card_sb8_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb8_main.c b/ANDROID_3.4.5/sound/isa/sb/sb8_main.c deleted file mode 100644 index 24d4121a..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb8_main.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Uros Bizjak - * - * Routines for control of 8-bit SoundBlaster cards and clones - * Please note: I don't have access to old SB8 soundcards. - * - * - * 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 - * - * -- - * - * Thu Apr 29 20:36:17 BST 1999 George David Morrison - * DSP can't respond to commands whilst in "high speed" mode. Caused - * glitching during playback. Fixed. - * - * Wed Jul 12 22:02:55 CEST 2000 Uros Bizjak - * Cleaned up and rewrote lowlevel routines. - */ - -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela , Uros Bizjak "); -MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones"); -MODULE_LICENSE("GPL"); - -#define SB8_CLOCK 1000000 -#define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v)) -#define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v)) - -static struct snd_ratnum clock = { - .num = SB8_CLOCK, - .den_min = 1, - .den_max = 256, - .den_step = 1, -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = { - .nrats = 1, - .rats = &clock, -}; - -static struct snd_ratnum stereo_clocks[] = { - { - .num = SB8_CLOCK, - .den_min = SB8_DEN(22050), - .den_max = SB8_DEN(22050), - .den_step = 1, - }, - { - .num = SB8_CLOCK, - .den_min = SB8_DEN(11025), - .den_max = SB8_DEN(11025), - .den_step = 1, - } -}; - -static int snd_sb8_hw_constraint_rate_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - if (c->min > 1) { - unsigned int num = 0, den = 0; - int err = snd_interval_ratnum(hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE), - 2, stereo_clocks, &num, &den); - if (err >= 0 && den) { - params->rate_num = num; - params->rate_den = den; - } - return err; - } - return 0; -} - -static int snd_sb8_hw_constraint_channels_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (r->min > SB8_RATE(22050) || r->max <= SB8_RATE(11025)) { - struct snd_interval t = { .min = 1, .max = 1 }; - return snd_interval_refine(hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS), &t); - } - return 0; -} - -static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int mixreg, rate, size, count; - unsigned char format; - unsigned char stereo = runtime->channels > 1; - int dma; - - rate = runtime->rate; - switch (chip->hardware) { - case SB_HW_JAZZ16: - if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) { - if (chip->mode & SB_MODE_CAPTURE_16) - return -EBUSY; - else - chip->mode |= SB_MODE_PLAYBACK_16; - } - chip->playback_format = SB_DSP_LO_OUTPUT_AUTO; - break; - case SB_HW_PRO: - if (runtime->channels > 1) { - if (snd_BUG_ON(rate != SB8_RATE(11025) && - rate != SB8_RATE(22050))) - return -EINVAL; - chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; - break; - } - /* fallthru */ - case SB_HW_201: - if (rate > 23000) { - chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; - break; - } - /* fallthru */ - case SB_HW_20: - chip->playback_format = SB_DSP_LO_OUTPUT_AUTO; - break; - case SB_HW_10: - chip->playback_format = SB_DSP_OUTPUT; - break; - default: - return -EINVAL; - } - if (chip->mode & SB_MODE_PLAYBACK_16) { - format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT; - dma = chip->dma16; - } else { - format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT; - chip->mode |= SB_MODE_PLAYBACK_8; - dma = chip->dma8; - } - size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream); - count = chip->p_period_size = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); - if (chip->hardware == SB_HW_JAZZ16) - snd_sbdsp_command(chip, format); - else if (stereo) { - /* set playback stereo mode */ - spin_lock(&chip->mixer_lock); - mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW); - snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02); - spin_unlock(&chip->mixer_lock); - - /* Soundblaster hardware programming reference guide, 3-23 */ - snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT); - runtime->dma_area[0] = 0x80; - snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE); - /* force interrupt */ - snd_sbdsp_command(chip, SB_DSP_OUTPUT); - snd_sbdsp_command(chip, 0); - snd_sbdsp_command(chip, 0); - } - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); - if (stereo) { - snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); - spin_lock(&chip->mixer_lock); - /* save output filter status and turn it off */ - mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT); - snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20); - spin_unlock(&chip->mixer_lock); - /* just use force_mode16 for temporary storate... */ - chip->force_mode16 = mixreg; - } else { - snd_sbdsp_command(chip, 256 - runtime->rate_den); - } - if (chip->playback_format != SB_DSP_OUTPUT) { - if (chip->mode & SB_MODE_PLAYBACK_16) - count /= 2; - count--; - snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_dma_program(dma, runtime->dma_addr, - size, DMA_MODE_WRITE | DMA_AUTOINIT); - return 0; -} - -static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int count; - - spin_lock_irqsave(&chip->reg_lock, flags); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_sbdsp_command(chip, chip->playback_format); - if (chip->playback_format == SB_DSP_OUTPUT) { - count = chip->p_period_size - 1; - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - } - break; - case SNDRV_PCM_TRIGGER_STOP: - if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) { - struct snd_pcm_runtime *runtime = substream->runtime; - snd_sbdsp_reset(chip); - if (runtime->channels > 1) { - spin_lock(&chip->mixer_lock); - /* restore output filter and set hardware to mono mode */ - snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02); - spin_unlock(&chip->mixer_lock); - } - } else { - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - } - snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_sb8_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_sb8_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int mixreg, rate, size, count; - unsigned char format; - unsigned char stereo = runtime->channels > 1; - int dma; - - rate = runtime->rate; - switch (chip->hardware) { - case SB_HW_JAZZ16: - if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) { - if (chip->mode & SB_MODE_PLAYBACK_16) - return -EBUSY; - else - chip->mode |= SB_MODE_CAPTURE_16; - } - chip->capture_format = SB_DSP_LO_INPUT_AUTO; - break; - case SB_HW_PRO: - if (runtime->channels > 1) { - if (snd_BUG_ON(rate != SB8_RATE(11025) && - rate != SB8_RATE(22050))) - return -EINVAL; - chip->capture_format = SB_DSP_HI_INPUT_AUTO; - break; - } - chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO; - break; - case SB_HW_201: - if (rate > 13000) { - chip->capture_format = SB_DSP_HI_INPUT_AUTO; - break; - } - /* fallthru */ - case SB_HW_20: - chip->capture_format = SB_DSP_LO_INPUT_AUTO; - break; - case SB_HW_10: - chip->capture_format = SB_DSP_INPUT; - break; - default: - return -EINVAL; - } - if (chip->mode & SB_MODE_CAPTURE_16) { - format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT; - dma = chip->dma16; - } else { - format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT; - chip->mode |= SB_MODE_CAPTURE_8; - dma = chip->dma8; - } - size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream); - count = chip->c_period_size = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); - if (chip->hardware == SB_HW_JAZZ16) - snd_sbdsp_command(chip, format); - else if (stereo) - snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT); - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); - if (stereo) { - snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); - spin_lock(&chip->mixer_lock); - /* save input filter status and turn it off */ - mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT); - snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20); - spin_unlock(&chip->mixer_lock); - /* just use force_mode16 for temporary storate... */ - chip->force_mode16 = mixreg; - } else { - snd_sbdsp_command(chip, 256 - runtime->rate_den); - } - if (chip->capture_format != SB_DSP_INPUT) { - if (chip->mode & SB_MODE_PLAYBACK_16) - count /= 2; - count--; - snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_dma_program(dma, runtime->dma_addr, - size, DMA_MODE_READ | DMA_AUTOINIT); - return 0; -} - -static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int count; - - spin_lock_irqsave(&chip->reg_lock, flags); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_sbdsp_command(chip, chip->capture_format); - if (chip->capture_format == SB_DSP_INPUT) { - count = chip->c_period_size - 1; - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - } - break; - case SNDRV_PCM_TRIGGER_STOP: - if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) { - struct snd_pcm_runtime *runtime = substream->runtime; - snd_sbdsp_reset(chip); - if (runtime->channels > 1) { - /* restore input filter status */ - spin_lock(&chip->mixer_lock); - snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16); - spin_unlock(&chip->mixer_lock); - /* set hardware to mono mode */ - snd_sbdsp_command(chip, SB_DSP_MONO_8BIT); - } - } else { - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - } - snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - - snd_sb_ack_8bit(chip); - switch (chip->mode) { - case SB_MODE_PLAYBACK_16: /* ok.. playback is active */ - if (chip->hardware != SB_HW_JAZZ16) - break; - /* fallthru */ - case SB_MODE_PLAYBACK_8: - substream = chip->playback_substream; - runtime = substream->runtime; - if (chip->playback_format == SB_DSP_OUTPUT) - snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START); - snd_pcm_period_elapsed(substream); - break; - case SB_MODE_CAPTURE_16: - if (chip->hardware != SB_HW_JAZZ16) - break; - /* fallthru */ - case SB_MODE_CAPTURE_8: - substream = chip->capture_substream; - runtime = substream->runtime; - if (chip->capture_format == SB_DSP_INPUT) - snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START); - snd_pcm_period_elapsed(substream); - break; - } - return IRQ_HANDLED; -} - -static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - size_t ptr; - int dma; - - if (chip->mode & SB_MODE_PLAYBACK_8) - dma = chip->dma8; - else if (chip->mode & SB_MODE_PLAYBACK_16) - dma = chip->dma16; - else - return 0; - ptr = snd_dma_pointer(dma, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - size_t ptr; - int dma; - - if (chip->mode & SB_MODE_CAPTURE_8) - dma = chip->dma8; - else if (chip->mode & SB_MODE_CAPTURE_16) - dma = chip->dma16; - else - return 0; - ptr = snd_dma_pointer(dma, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -/* - - */ - -static struct snd_pcm_hardware snd_sb8_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8, - .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050), - .rate_min = 4000, - .rate_max = 23000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_sb8_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8, - .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_11025), - .rate_min = 4000, - .rate_max = 13000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * - */ - -static int snd_sb8_open(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - chip->open |= SB_OPEN_PCM; - spin_unlock_irqrestore(&chip->open_lock, flags); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - chip->playback_substream = substream; - runtime->hw = snd_sb8_playback; - } else { - chip->capture_substream = substream; - runtime->hw = snd_sb8_capture; - } - switch (chip->hardware) { - case SB_HW_JAZZ16: - if (chip->dma16 == 5 || chip->dma16 == 7) - runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE; - runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000; - runtime->hw.rate_min = 4000; - runtime->hw.rate_max = 50000; - runtime->hw.channels_max = 2; - break; - case SB_HW_PRO: - runtime->hw.rate_max = 44100; - runtime->hw.channels_max = 2; - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_sb8_hw_constraint_rate_channels, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, - SNDRV_PCM_HW_PARAM_RATE, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_sb8_hw_constraint_channels_rate, NULL, - SNDRV_PCM_HW_PARAM_RATE, -1); - break; - case SB_HW_201: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - runtime->hw.rate_max = 44100; - } else { - runtime->hw.rate_max = 15000; - } - default: - break; - } - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clock); - if (chip->dma8 > 3 || chip->dma16 >= 0) { - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2); - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2); - runtime->hw.buffer_bytes_max = 128 * 1024 * 1024; - runtime->hw.period_bytes_max = 128 * 1024 * 1024; - } - return 0; -} - -static int snd_sb8_close(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - chip->capture_substream = NULL; - spin_lock_irqsave(&chip->open_lock, flags); - chip->open &= ~SB_OPEN_PCM; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - chip->mode &= ~SB_MODE_PLAYBACK; - else - chip->mode &= ~SB_MODE_CAPTURE; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -/* - * Initialization part - */ - -static struct snd_pcm_ops snd_sb8_playback_ops = { - .open = snd_sb8_open, - .close = snd_sb8_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sb8_hw_params, - .hw_free = snd_sb8_hw_free, - .prepare = snd_sb8_playback_prepare, - .trigger = snd_sb8_playback_trigger, - .pointer = snd_sb8_playback_pointer, -}; - -static struct snd_pcm_ops snd_sb8_capture_ops = { - .open = snd_sb8_open, - .close = snd_sb8_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sb8_hw_params, - .hw_free = snd_sb8_hw_free, - .prepare = snd_sb8_capture_prepare, - .trigger = snd_sb8_capture_trigger, - .pointer = snd_sb8_capture_pointer, -}; - -int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_card *card = chip->card; - struct snd_pcm *pcm; - int err; - size_t max_prealloc = 64 * 1024; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0) - return err; - sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); - pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops); - - if (chip->dma8 > 3 || chip->dma16 >= 0) - max_prealloc = 128 * 1024; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, max_prealloc); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -EXPORT_SYMBOL(snd_sb8dsp_pcm); -EXPORT_SYMBOL(snd_sb8dsp_interrupt); - /* sb8_midi.c */ -EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt); -EXPORT_SYMBOL(snd_sb8dsp_midi); - -/* - * INIT part - */ - -static int __init alsa_sb8_init(void) -{ - return 0; -} - -static void __exit alsa_sb8_exit(void) -{ -} - -module_init(alsa_sb8_init) -module_exit(alsa_sb8_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb8_midi.c b/ANDROID_3.4.5/sound/isa/sb/sb8_midi.c deleted file mode 100644 index 988a8b73..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb8_midi.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of SoundBlaster cards - MIDI interface - * - * 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 - * - * -- - * - * Sun May 9 22:54:38 BST 1999 George David Morrison - * Fixed typo in snd_sb8dsp_midi_new_device which prevented midi from - * working. - * - * Sun May 11 12:34:56 UTC 2003 Clemens Ladisch - * Added full duplex UART mode for DSP version 2.0 and later. - */ - -#include -#include -#include -#include - - -irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip) -{ - struct snd_rawmidi *rmidi; - int max = 64; - char byte; - - if (!chip) - return IRQ_NONE; - - rmidi = chip->rmidi; - if (!rmidi) { - inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */ - return IRQ_NONE; - } - - spin_lock(&chip->midi_input_lock); - while (max-- > 0) { - if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { - byte = inb(SBP(chip, READ)); - if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) { - snd_rawmidi_receive(chip->midi_substream_input, &byte, 1); - } - } - } - spin_unlock(&chip->midi_input_lock); - return IRQ_HANDLED; -} - -static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - unsigned int valid_open_flags; - - chip = substream->rmidi->private_data; - valid_open_flags = chip->hardware >= SB_HW_20 - ? SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER : 0; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open & ~valid_open_flags) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - chip->open |= SB_OPEN_MIDI_INPUT; - chip->midi_substream_input = substream; - if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - if (chip->hardware >= SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); - } - return 0; -} - -static int snd_sb8dsp_midi_output_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - unsigned int valid_open_flags; - - chip = substream->rmidi->private_data; - valid_open_flags = chip->hardware >= SB_HW_20 - ? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open & ~valid_open_flags) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - chip->open |= SB_OPEN_MIDI_OUTPUT; - chip->midi_substream_output = substream; - if (!(chip->open & SB_OPEN_MIDI_INPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - if (chip->hardware >= SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); - } - return 0; -} - -static int snd_sb8dsp_midi_input_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - - chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER); - chip->midi_substream_input = NULL; - if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); - } - return 0; -} - -static int snd_sb8dsp_midi_output_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - - chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER); - chip->midi_substream_output = NULL; - if (!(chip->open & SB_OPEN_MIDI_INPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); - } - return 0; -} - -static void snd_sb8dsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_sb *chip; - - chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - if (up) { - if (!(chip->open & SB_OPEN_MIDI_INPUT_TRIGGER)) { - if (chip->hardware < SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_INPUT_IRQ); - chip->open |= SB_OPEN_MIDI_INPUT_TRIGGER; - } - } else { - if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) { - if (chip->hardware < SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_INPUT_IRQ); - chip->open &= ~SB_OPEN_MIDI_INPUT_TRIGGER; - } - } - spin_unlock_irqrestore(&chip->open_lock, flags); -} - -static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - char byte; - int max = 32; - - /* how big is Tx FIFO? */ - chip = substream->rmidi->private_data; - while (max-- > 0) { - spin_lock_irqsave(&chip->open_lock, flags); - if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) { - chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER; - del_timer(&chip->midi_timer); - spin_unlock_irqrestore(&chip->open_lock, flags); - break; - } - if (chip->hardware >= SB_HW_20) { - int timeout = 8; - while ((inb(SBP(chip, STATUS)) & 0x80) != 0 && --timeout > 0) - ; - if (timeout == 0) { - /* Tx FIFO full - try again later */ - spin_unlock_irqrestore(&chip->open_lock, flags); - break; - } - outb(byte, SBP(chip, WRITE)); - } else { - snd_sbdsp_command(chip, SB_DSP_MIDI_OUTPUT); - snd_sbdsp_command(chip, byte); - } - snd_rawmidi_transmit_ack(substream, 1); - spin_unlock_irqrestore(&chip->open_lock, flags); - } -} - -static void snd_sb8dsp_midi_output_timer(unsigned long data) -{ - struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *) data; - struct snd_sb * chip = substream->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&chip->open_lock, flags); - chip->midi_timer.expires = 1 + jiffies; - add_timer(&chip->midi_timer); - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sb8dsp_midi_output_write(substream); -} - -static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_sb *chip; - - chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - if (up) { - if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) { - init_timer(&chip->midi_timer); - chip->midi_timer.function = snd_sb8dsp_midi_output_timer; - chip->midi_timer.data = (unsigned long) substream; - chip->midi_timer.expires = 1 + jiffies; - add_timer(&chip->midi_timer); - chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER; - } - } else { - if (chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER) { - chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER; - } - } - spin_unlock_irqrestore(&chip->open_lock, flags); - - if (up) - snd_sb8dsp_midi_output_write(substream); -} - -static struct snd_rawmidi_ops snd_sb8dsp_midi_output = -{ - .open = snd_sb8dsp_midi_output_open, - .close = snd_sb8dsp_midi_output_close, - .trigger = snd_sb8dsp_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_sb8dsp_midi_input = -{ - .open = snd_sb8dsp_midi_input_open, - .close = snd_sb8dsp_midi_input_close, - .trigger = snd_sb8dsp_midi_input_trigger, -}; - -int snd_sb8dsp_midi(struct snd_sb *chip, int device, struct snd_rawmidi ** rrawmidi) -{ - struct snd_rawmidi *rmidi; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if ((err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi)) < 0) - return err; - strcpy(rmidi->name, "SB8 MIDI"); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_sb8dsp_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_sb8dsp_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT; - if (chip->hardware >= SB_HW_20) - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = chip; - chip->rmidi = rmidi; - if (rrawmidi) - *rrawmidi = rmidi; - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/sb/sb_common.c b/ANDROID_3.4.5/sound/isa/sb/sb_common.c deleted file mode 100644 index 3ef99060..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb_common.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Uros Bizjak - * - * Lowlevel routines for control of Sound Blaster cards - * - * 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 - -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards"); -MODULE_LICENSE("GPL"); - -#define BUSY_LOOPS 100000 - -#undef IO_DEBUG - -int snd_sbdsp_command(struct snd_sb *chip, unsigned char val) -{ - int i; -#ifdef IO_DEBUG - snd_printk(KERN_DEBUG "command 0x%x\n", val); -#endif - for (i = BUSY_LOOPS; i; i--) - if ((inb(SBP(chip, STATUS)) & 0x80) == 0) { - outb(val, SBP(chip, COMMAND)); - return 1; - } - snd_printd("%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val); - return 0; -} - -int snd_sbdsp_get_byte(struct snd_sb *chip) -{ - int val; - int i; - for (i = BUSY_LOOPS; i; i--) { - if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { - val = inb(SBP(chip, READ)); -#ifdef IO_DEBUG - snd_printk(KERN_DEBUG "get_byte 0x%x\n", val); -#endif - return val; - } - } - snd_printd("%s [0x%lx]: timeout\n", __func__, chip->port); - return -ENODEV; -} - -int snd_sbdsp_reset(struct snd_sb *chip) -{ - int i; - - outb(1, SBP(chip, RESET)); - udelay(10); - outb(0, SBP(chip, RESET)); - udelay(30); - for (i = BUSY_LOOPS; i; i--) - if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { - if (inb(SBP(chip, READ)) == 0xaa) - return 0; - else - break; - } - snd_printdd("%s [0x%lx] failed...\n", __func__, chip->port); - return -ENODEV; -} - -static int snd_sbdsp_version(struct snd_sb * chip) -{ - unsigned int result = -ENODEV; - - snd_sbdsp_command(chip, SB_DSP_GET_VERSION); - result = (short) snd_sbdsp_get_byte(chip) << 8; - result |= (short) snd_sbdsp_get_byte(chip); - return result; -} - -static int snd_sbdsp_probe(struct snd_sb * chip) -{ - int version; - int major, minor; - char *str; - unsigned long flags; - - /* - * initialization sequence - */ - - spin_lock_irqsave(&chip->reg_lock, flags); - if (snd_sbdsp_reset(chip) < 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; - } - version = snd_sbdsp_version(chip); - if (version < 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - major = version >> 8; - minor = version & 0xff; - snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n", - chip->port, major, minor); - - switch (chip->hardware) { - case SB_HW_AUTO: - switch (major) { - case 1: - chip->hardware = SB_HW_10; - str = "1.0"; - break; - case 2: - if (minor) { - chip->hardware = SB_HW_201; - str = "2.01+"; - } else { - chip->hardware = SB_HW_20; - str = "2.0"; - } - break; - case 3: - chip->hardware = SB_HW_PRO; - str = "Pro"; - break; - case 4: - chip->hardware = SB_HW_16; - str = "16"; - break; - default: - snd_printk(KERN_INFO "SB [0x%lx]: unknown DSP chip version %i.%i\n", - chip->port, major, minor); - return -ENODEV; - } - break; - case SB_HW_ALS100: - str = "16 (ALS-100)"; - break; - case SB_HW_ALS4000: - str = "16 (ALS-4000)"; - break; - case SB_HW_DT019X: - str = "(DT019X/ALS007)"; - break; - case SB_HW_CS5530: - str = "16 (CS5530)"; - break; - case SB_HW_JAZZ16: - str = "Pro (Jazz16)"; - break; - default: - return -ENODEV; - } - sprintf(chip->name, "Sound Blaster %s", str); - chip->version = (major << 8) | minor; - return 0; -} - -static int snd_sbdsp_free(struct snd_sb *chip) -{ - if (chip->res_port) - release_and_free_resource(chip->res_port); - if (chip->irq >= 0) - free_irq(chip->irq, (void *) chip); -#ifdef CONFIG_ISA - if (chip->dma8 >= 0) { - disable_dma(chip->dma8); - free_dma(chip->dma8); - } - if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) { - disable_dma(chip->dma16); - free_dma(chip->dma16); - } -#endif - kfree(chip); - return 0; -} - -static int snd_sbdsp_dev_free(struct snd_device *device) -{ - struct snd_sb *chip = device->device_data; - return snd_sbdsp_free(chip); -} - -int snd_sbdsp_create(struct snd_card *card, - unsigned long port, - int irq, - irq_handler_t irq_handler, - int dma8, - int dma16, - unsigned short hardware, - struct snd_sb **r_chip) -{ - struct snd_sb *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_sbdsp_dev_free, - }; - - if (snd_BUG_ON(!r_chip)) - return -EINVAL; - *r_chip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->open_lock); - spin_lock_init(&chip->midi_input_lock); - spin_lock_init(&chip->mixer_lock); - chip->irq = -1; - chip->dma8 = -1; - chip->dma16 = -1; - chip->port = port; - - if (request_irq(irq, irq_handler, - (hardware == SB_HW_ALS4000 || - hardware == SB_HW_CS5530) ? - IRQF_SHARED : 0, - "SoundBlaster", (void *) chip)) { - snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); - snd_sbdsp_free(chip); - return -EBUSY; - } - chip->irq = irq; - - if (hardware == SB_HW_ALS4000) - goto __skip_allocation; - - if ((chip->res_port = request_region(port, 16, "SoundBlaster")) == NULL) { - snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port); - snd_sbdsp_free(chip); - return -EBUSY; - } - -#ifdef CONFIG_ISA - if (dma8 >= 0 && request_dma(dma8, "SoundBlaster - 8bit")) { - snd_printk(KERN_ERR "sb: can't grab DMA8 %d\n", dma8); - snd_sbdsp_free(chip); - return -EBUSY; - } - chip->dma8 = dma8; - if (dma16 >= 0) { - if (hardware != SB_HW_ALS100 && (dma16 < 5 || dma16 > 7)) { - /* no duplex */ - dma16 = -1; - } else if (request_dma(dma16, "SoundBlaster - 16bit")) { - snd_printk(KERN_ERR "sb: can't grab DMA16 %d\n", dma16); - snd_sbdsp_free(chip); - return -EBUSY; - } - } - chip->dma16 = dma16; -#endif - - __skip_allocation: - chip->card = card; - chip->hardware = hardware; - if ((err = snd_sbdsp_probe(chip)) < 0) { - snd_sbdsp_free(chip); - return err; - } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_sbdsp_free(chip); - return err; - } - *r_chip = chip; - return 0; -} - -EXPORT_SYMBOL(snd_sbdsp_command); -EXPORT_SYMBOL(snd_sbdsp_get_byte); -EXPORT_SYMBOL(snd_sbdsp_reset); -EXPORT_SYMBOL(snd_sbdsp_create); -/* sb_mixer.c */ -EXPORT_SYMBOL(snd_sbmixer_write); -EXPORT_SYMBOL(snd_sbmixer_read); -EXPORT_SYMBOL(snd_sbmixer_new); -EXPORT_SYMBOL(snd_sbmixer_add_ctl); -#ifdef CONFIG_PM -EXPORT_SYMBOL(snd_sbmixer_suspend); -EXPORT_SYMBOL(snd_sbmixer_resume); -#endif - -/* - * INIT part - */ - -static int __init alsa_sb_common_init(void) -{ - return 0; -} - -static void __exit alsa_sb_common_exit(void) -{ -} - -module_init(alsa_sb_common_init) -module_exit(alsa_sb_common_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb_mixer.c b/ANDROID_3.4.5/sound/isa/sb/sb_mixer.c deleted file mode 100644 index 6496822c..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb_mixer.c +++ /dev/null @@ -1,978 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for Sound Blaster mixer control - * - * - * 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 - -#undef IO_DEBUG - -void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data) -{ - outb(reg, SBP(chip, MIXER_ADDR)); - udelay(10); - outb(data, SBP(chip, MIXER_DATA)); - udelay(10); -#ifdef IO_DEBUG - snd_printk(KERN_DEBUG "mixer_write 0x%x 0x%x\n", reg, data); -#endif -} - -unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg) -{ - unsigned char result; - - outb(reg, SBP(chip, MIXER_ADDR)); - udelay(10); - result = inb(SBP(chip, MIXER_DATA)); - udelay(10); -#ifdef IO_DEBUG - snd_printk(KERN_DEBUG "mixer_read 0x%x 0x%x\n", reg, result); -#endif - return result; -} - -/* - * Single channel mixer element - */ - -static int snd_sbmixer_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 16) & 0xff; - int mask = (kcontrol->private_value >> 24) & 0xff; - unsigned char val; - - spin_lock_irqsave(&sb->mixer_lock, flags); - val = (snd_sbmixer_read(sb, reg) >> shift) & mask; - spin_unlock_irqrestore(&sb->mixer_lock, flags); - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int snd_sbmixer_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 16) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned char val, oval; - - val = (ucontrol->value.integer.value[0] & mask) << shift; - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, reg); - val = (oval & ~(mask << shift)) | val; - change = val != oval; - if (change) - snd_sbmixer_write(sb, reg, val); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * Double channel mixer element - */ - -static int snd_sbmixer_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x07; - int right_shift = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - unsigned char left, right; - - spin_lock_irqsave(&sb->mixer_lock, flags); - left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask; - right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask; - spin_unlock_irqrestore(&sb->mixer_lock, flags); - ucontrol->value.integer.value[0] = left; - ucontrol->value.integer.value[1] = right; - return 0; -} - -static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x07; - int right_shift = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned char left, right, oleft, oright; - - left = (ucontrol->value.integer.value[0] & mask) << left_shift; - right = (ucontrol->value.integer.value[1] & mask) << right_shift; - spin_lock_irqsave(&sb->mixer_lock, flags); - if (left_reg == right_reg) { - oleft = snd_sbmixer_read(sb, left_reg); - left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right; - change = left != oleft; - if (change) - snd_sbmixer_write(sb, left_reg, left); - } else { - oleft = snd_sbmixer_read(sb, left_reg); - oright = snd_sbmixer_read(sb, right_reg); - left = (oleft & ~(mask << left_shift)) | left; - right = (oright & ~(mask << right_shift)) | right; - change = left != oleft || right != oright; - if (change) { - snd_sbmixer_write(sb, left_reg, left); - snd_sbmixer_write(sb, right_reg, right); - } - } - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * DT-019x / ALS-007 capture/input switch - */ - -static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[5] = { - "CD", "Mic", "Line", "Synth", "Master" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_dt019x_input_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char oval; - - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - switch (oval & 0x07) { - case SB_DT019X_CAP_CD: - ucontrol->value.enumerated.item[0] = 0; - break; - case SB_DT019X_CAP_MIC: - ucontrol->value.enumerated.item[0] = 1; - break; - case SB_DT019X_CAP_LINE: - ucontrol->value.enumerated.item[0] = 2; - break; - case SB_DT019X_CAP_MAIN: - ucontrol->value.enumerated.item[0] = 4; - break; - /* To record the synth on these cards you must record the main. */ - /* Thus SB_DT019X_CAP_SYNTH == SB_DT019X_CAP_MAIN and would cause */ - /* duplicate case labels if left uncommented. */ - /* case SB_DT019X_CAP_SYNTH: - * ucontrol->value.enumerated.item[0] = 3; - * break; - */ - default: - ucontrol->value.enumerated.item[0] = 4; - break; - } - return 0; -} - -static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval, oval; - - if (ucontrol->value.enumerated.item[0] > 4) - return -EINVAL; - switch (ucontrol->value.enumerated.item[0]) { - case 0: - nval = SB_DT019X_CAP_CD; - break; - case 1: - nval = SB_DT019X_CAP_MIC; - break; - case 2: - nval = SB_DT019X_CAP_LINE; - break; - case 3: - nval = SB_DT019X_CAP_SYNTH; - break; - case 4: - nval = SB_DT019X_CAP_MAIN; - break; - default: - nval = SB_DT019X_CAP_MAIN; - } - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW); - change = nval != oval; - if (change) - snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * ALS4000 mono recording control switch - */ - -static int snd_als4k_mono_capture_route_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[3] = { - "L chan only", "R chan only", "L ch/2 + R ch/2" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_als4k_mono_capture_route_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char oval; - - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - oval >>= 6; - if (oval > 2) - oval = 2; - - ucontrol->value.enumerated.item[0] = oval; - return 0; -} - -static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval, oval; - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL); - - nval = (oval & ~(3 << 6)) - | (ucontrol->value.enumerated.item[0] << 6); - change = nval != oval; - if (change) - snd_sbmixer_write(sb, SB_ALS4000_MONO_IO_CTRL, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * SBPRO input multiplexer - */ - -static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[3] = { - "Mic", "CD", "Line" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - - -static int snd_sb8mixer_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char oval; - - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - switch ((oval >> 0x01) & 0x03) { - case SB_DSP_MIXS_CD: - ucontrol->value.enumerated.item[0] = 1; - break; - case SB_DSP_MIXS_LINE: - ucontrol->value.enumerated.item[0] = 2; - break; - default: - ucontrol->value.enumerated.item[0] = 0; - break; - } - return 0; -} - -static int snd_sb8mixer_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval, oval; - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - switch (ucontrol->value.enumerated.item[0]) { - case 1: - nval = SB_DSP_MIXS_CD; - break; - case 2: - nval = SB_DSP_MIXS_LINE; - break; - default: - nval = SB_DSP_MIXS_MIC; - } - nval <<= 1; - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE); - nval |= oval & ~0x06; - change = nval != oval; - if (change) - snd_sbmixer_write(sb, SB_DSP_CAPTURE_SOURCE, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * SB16 input switch - */ - -static int snd_sb16mixer_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_sb16mixer_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg1 = kcontrol->private_value & 0xff; - int reg2 = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x0f; - int right_shift = (kcontrol->private_value >> 24) & 0x0f; - unsigned char val1, val2; - - spin_lock_irqsave(&sb->mixer_lock, flags); - val1 = snd_sbmixer_read(sb, reg1); - val2 = snd_sbmixer_read(sb, reg2); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - ucontrol->value.integer.value[0] = (val1 >> left_shift) & 0x01; - ucontrol->value.integer.value[1] = (val2 >> left_shift) & 0x01; - ucontrol->value.integer.value[2] = (val1 >> right_shift) & 0x01; - ucontrol->value.integer.value[3] = (val2 >> right_shift) & 0x01; - return 0; -} - -static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg1 = kcontrol->private_value & 0xff; - int reg2 = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x0f; - int right_shift = (kcontrol->private_value >> 24) & 0x0f; - int change; - unsigned char val1, val2, oval1, oval2; - - spin_lock_irqsave(&sb->mixer_lock, flags); - oval1 = snd_sbmixer_read(sb, reg1); - oval2 = snd_sbmixer_read(sb, reg2); - val1 = oval1 & ~((1 << left_shift) | (1 << right_shift)); - val2 = oval2 & ~((1 << left_shift) | (1 << right_shift)); - val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift; - val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift; - val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift; - val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift; - change = val1 != oval1 || val2 != oval2; - if (change) { - snd_sbmixer_write(sb, reg1, val1); - snd_sbmixer_write(sb, reg2, val2); - } - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - - -/* - */ -/* - */ -int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int type, unsigned long value) -{ - static struct snd_kcontrol_new newctls[] = { - [SB_MIX_SINGLE] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_sbmixer_info_single, - .get = snd_sbmixer_get_single, - .put = snd_sbmixer_put_single, - }, - [SB_MIX_DOUBLE] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_sbmixer_info_double, - .get = snd_sbmixer_get_double, - .put = snd_sbmixer_put_double, - }, - [SB_MIX_INPUT_SW] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_sb16mixer_info_input_sw, - .get = snd_sb16mixer_get_input_sw, - .put = snd_sb16mixer_put_input_sw, - }, - [SB_MIX_CAPTURE_PRO] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_sb8mixer_info_mux, - .get = snd_sb8mixer_get_mux, - .put = snd_sb8mixer_put_mux, - }, - [SB_MIX_CAPTURE_DT019X] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_dt019x_input_sw_info, - .get = snd_dt019x_input_sw_get, - .put = snd_dt019x_input_sw_put, - }, - [SB_MIX_MONO_CAPTURE_ALS4K] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_als4k_mono_capture_route_info, - .get = snd_als4k_mono_capture_route_get, - .put = snd_als4k_mono_capture_route_put, - }, - }; - struct snd_kcontrol *ctl; - int err; - - ctl = snd_ctl_new1(&newctls[type], chip); - if (! ctl) - return -ENOMEM; - strlcpy(ctl->id.name, name, sizeof(ctl->id.name)); - ctl->id.index = index; - ctl->private_value = value; - if ((err = snd_ctl_add(chip->card, ctl)) < 0) - return err; - return 0; -} - -/* - * SB 2.0 specific mixer elements - */ - -static struct sbmix_elem snd_sb20_controls[] = { - SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7), - SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3), - SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7), - SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7) -}; - -static unsigned char snd_sb20_init_values[][2] = { - { SB_DSP20_MASTER_DEV, 0 }, - { SB_DSP20_FM_DEV, 0 }, -}; - -/* - * SB Pro specific mixer elements - */ -static struct sbmix_elem snd_sbpro_controls[] = { - SB_DOUBLE("Master Playback Volume", - SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7), - SB_DOUBLE("PCM Playback Volume", - SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7), - SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1), - SB_DOUBLE("Synth Playback Volume", - SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7), - SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7), - SB_DOUBLE("Line Playback Volume", - SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7), - SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3), - { - .name = "Capture Source", - .type = SB_MIX_CAPTURE_PRO - }, - SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1), - SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1) -}; - -static unsigned char snd_sbpro_init_values[][2] = { - { SB_DSP_MASTER_DEV, 0 }, - { SB_DSP_PCM_DEV, 0 }, - { SB_DSP_FM_DEV, 0 }, -}; - -/* - * SB16 specific mixer elements - */ -static struct sbmix_elem snd_sb16_controls[] = { - SB_DOUBLE("Master Playback Volume", - SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31), - SB_DOUBLE("PCM Playback Volume", - SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31), - SB16_INPUT_SW("Synth Capture Route", - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 6, 5), - SB_DOUBLE("Synth Playback Volume", - SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31), - SB16_INPUT_SW("CD Capture Route", - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, 1), - SB_DOUBLE("CD Playback Switch", - SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1), - SB_DOUBLE("CD Playback Volume", - SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31), - SB16_INPUT_SW("Mic Capture Route", - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0), - SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1), - SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), - SB_SINGLE("Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3), - SB_DOUBLE("Capture Volume", - SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3), - SB_DOUBLE("Playback Volume", - SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3), - SB16_INPUT_SW("Line Capture Route", - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3), - SB_DOUBLE("Line Playback Switch", - SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1), - SB_DOUBLE("Line Playback Volume", - SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31), - SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1), - SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1), - SB_DOUBLE("Tone Control - Bass", - SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15), - SB_DOUBLE("Tone Control - Treble", - SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15) -}; - -static unsigned char snd_sb16_init_values[][2] = { - { SB_DSP4_MASTER_DEV + 0, 0 }, - { SB_DSP4_MASTER_DEV + 1, 0 }, - { SB_DSP4_PCM_DEV + 0, 0 }, - { SB_DSP4_PCM_DEV + 1, 0 }, - { SB_DSP4_SYNTH_DEV + 0, 0 }, - { SB_DSP4_SYNTH_DEV + 1, 0 }, - { SB_DSP4_INPUT_LEFT, 0 }, - { SB_DSP4_INPUT_RIGHT, 0 }, - { SB_DSP4_OUTPUT_SW, 0 }, - { SB_DSP4_SPEAKER_DEV, 0 }, -}; - -/* - * DT019x specific mixer elements - */ -static struct sbmix_elem snd_dt019x_controls[] = { - /* ALS4000 below has some parts which we might be lacking, - * e.g. snd_als4000_ctl_mono_playback_switch - check it! */ - SB_DOUBLE("Master Playback Volume", - SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4, 0, 15), - SB_DOUBLE("PCM Playback Switch", - SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1), - SB_DOUBLE("PCM Playback Volume", - SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4, 0, 15), - SB_DOUBLE("Synth Playback Switch", - SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4, 3, 1), - SB_DOUBLE("Synth Playback Volume", - SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4, 0, 15), - SB_DOUBLE("CD Playback Switch", - SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1), - SB_DOUBLE("CD Playback Volume", - SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4, 0, 15), - SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1), - SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7), - SB_SINGLE("Beep Volume", SB_DT019X_SPKR_DEV, 0, 7), - SB_DOUBLE("Line Playback Switch", - SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1), - SB_DOUBLE("Line Playback Volume", - SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4, 0, 15), - { - .name = "Capture Source", - .type = SB_MIX_CAPTURE_DT019X - } -}; - -static unsigned char snd_dt019x_init_values[][2] = { - { SB_DT019X_MASTER_DEV, 0 }, - { SB_DT019X_PCM_DEV, 0 }, - { SB_DT019X_SYNTH_DEV, 0 }, - { SB_DT019X_CD_DEV, 0 }, - { SB_DT019X_MIC_DEV, 0 }, /* Includes PC-speaker in high nibble */ - { SB_DT019X_LINE_DEV, 0 }, - { SB_DSP4_OUTPUT_SW, 0 }, - { SB_DT019X_OUTPUT_SW2, 0 }, - { SB_DT019X_CAPTURE_SW, 0x06 }, -}; - -/* - * ALS4000 specific mixer elements - */ -static struct sbmix_elem snd_als4000_controls[] = { - SB_DOUBLE("PCM Playback Switch", - SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1), - SB_DOUBLE("Synth Playback Switch", - SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4, 3, 1), - SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03), - SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1), - { - .name = "Master Mono Capture Route", - .type = SB_MIX_MONO_CAPTURE_ALS4K - }, - SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1), - SB_SINGLE("Analog Loopback Switch", SB_ALS4000_MIC_IN_GAIN, 7, 0x01), - SB_SINGLE("3D Control - Switch", SB_ALS4000_3D_SND_FX, 6, 0x01), - SB_SINGLE("Digital Loopback Switch", - SB_ALS4000_CR3_CONFIGURATION, 7, 0x01), - /* FIXME: functionality of 3D controls might be swapped, I didn't find - * a description of how to identify what is supposed to be what */ - SB_SINGLE("3D Control - Level", SB_ALS4000_3D_SND_FX, 0, 0x07), - /* FIXME: maybe there's actually some standard 3D ctrl name for it?? */ - SB_SINGLE("3D Control - Freq", SB_ALS4000_3D_SND_FX, 4, 0x03), - /* FIXME: ALS4000a.pdf mentions BBD (Bucket Brigade Device) time delay, - * but what ALSA 3D attribute is that actually? "Center", "Depth", - * "Wide" or "Space" or even "Level"? Assuming "Wide" for now... */ - SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f), - SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01), - SB_SINGLE("Master Playback 8kHz / 20kHz LPF Switch", - SB_ALS4000_FMDAC, 5, 0x01), -#ifdef NOT_AVAILABLE - SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01), - SB_SINGLE("QSound Mode", SB_ALS4000_QSOUND, 1, 0x1f), -#endif -}; - -static unsigned char snd_als4000_init_values[][2] = { - { SB_DSP4_MASTER_DEV + 0, 0 }, - { SB_DSP4_MASTER_DEV + 1, 0 }, - { SB_DSP4_PCM_DEV + 0, 0 }, - { SB_DSP4_PCM_DEV + 1, 0 }, - { SB_DSP4_SYNTH_DEV + 0, 0 }, - { SB_DSP4_SYNTH_DEV + 1, 0 }, - { SB_DSP4_SPEAKER_DEV, 0 }, - { SB_DSP4_OUTPUT_SW, 0 }, - { SB_DSP4_INPUT_LEFT, 0 }, - { SB_DSP4_INPUT_RIGHT, 0 }, - { SB_DT019X_OUTPUT_SW2, 0 }, - { SB_ALS4000_MIC_IN_GAIN, 0 }, -}; - -/* - */ -static int snd_sbmixer_init(struct snd_sb *chip, - struct sbmix_elem *controls, - int controls_count, - unsigned char map[][2], - int map_count, - char *name) -{ - unsigned long flags; - struct snd_card *card = chip->card; - int idx, err; - - /* mixer reset */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, 0x00, 0x00); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - - /* mute and zero volume channels */ - for (idx = 0; idx < map_count; idx++) { - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, map[idx][0], map[idx][1]); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - } - - for (idx = 0; idx < controls_count; idx++) { - err = snd_sbmixer_add_ctl_elem(chip, &controls[idx]); - if (err < 0) - return err; - } - snd_component_add(card, name); - strcpy(card->mixername, name); - return 0; -} - -int snd_sbmixer_new(struct snd_sb *chip) -{ - struct snd_card *card; - int err; - - if (snd_BUG_ON(!chip || !chip->card)) - return -EINVAL; - - card = chip->card; - - switch (chip->hardware) { - case SB_HW_10: - return 0; /* no mixer chip on SB1.x */ - case SB_HW_20: - case SB_HW_201: - if ((err = snd_sbmixer_init(chip, - snd_sb20_controls, - ARRAY_SIZE(snd_sb20_controls), - snd_sb20_init_values, - ARRAY_SIZE(snd_sb20_init_values), - "CTL1335")) < 0) - return err; - break; - case SB_HW_PRO: - case SB_HW_JAZZ16: - if ((err = snd_sbmixer_init(chip, - snd_sbpro_controls, - ARRAY_SIZE(snd_sbpro_controls), - snd_sbpro_init_values, - ARRAY_SIZE(snd_sbpro_init_values), - "CTL1345")) < 0) - return err; - break; - case SB_HW_16: - case SB_HW_ALS100: - case SB_HW_CS5530: - if ((err = snd_sbmixer_init(chip, - snd_sb16_controls, - ARRAY_SIZE(snd_sb16_controls), - snd_sb16_init_values, - ARRAY_SIZE(snd_sb16_init_values), - "CTL1745")) < 0) - return err; - break; - case SB_HW_ALS4000: - /* use only the first 16 controls from SB16 */ - err = snd_sbmixer_init(chip, - snd_sb16_controls, - 16, - snd_sb16_init_values, - ARRAY_SIZE(snd_sb16_init_values), - "ALS4000"); - if (err < 0) - return err; - if ((err = snd_sbmixer_init(chip, - snd_als4000_controls, - ARRAY_SIZE(snd_als4000_controls), - snd_als4000_init_values, - ARRAY_SIZE(snd_als4000_init_values), - "ALS4000")) < 0) - return err; - break; - case SB_HW_DT019X: - if ((err = snd_sbmixer_init(chip, - snd_dt019x_controls, - ARRAY_SIZE(snd_dt019x_controls), - snd_dt019x_init_values, - ARRAY_SIZE(snd_dt019x_init_values), - "DT019X")) < 0) - break; - default: - strcpy(card->mixername, "???"); - } - return 0; -} - -#ifdef CONFIG_PM -static unsigned char sb20_saved_regs[] = { - SB_DSP20_MASTER_DEV, - SB_DSP20_PCM_DEV, - SB_DSP20_FM_DEV, - SB_DSP20_CD_DEV, -}; - -static unsigned char sbpro_saved_regs[] = { - SB_DSP_MASTER_DEV, - SB_DSP_PCM_DEV, - SB_DSP_PLAYBACK_FILT, - SB_DSP_FM_DEV, - SB_DSP_CD_DEV, - SB_DSP_LINE_DEV, - SB_DSP_MIC_DEV, - SB_DSP_CAPTURE_SOURCE, - SB_DSP_CAPTURE_FILT, -}; - -static unsigned char sb16_saved_regs[] = { - SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, - SB_DSP4_3DSE, - SB_DSP4_BASS_DEV, SB_DSP4_BASS_DEV + 1, - SB_DSP4_TREBLE_DEV, SB_DSP4_TREBLE_DEV + 1, - SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, - SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, - SB_DSP4_OUTPUT_SW, - SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, - SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1, - SB_DSP4_MIC_DEV, - SB_DSP4_SPEAKER_DEV, - SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1, - SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1, - SB_DSP4_MIC_AGC -}; - -static unsigned char dt019x_saved_regs[] = { - SB_DT019X_MASTER_DEV, - SB_DT019X_PCM_DEV, - SB_DT019X_SYNTH_DEV, - SB_DT019X_CD_DEV, - SB_DT019X_MIC_DEV, - SB_DT019X_SPKR_DEV, - SB_DT019X_LINE_DEV, - SB_DSP4_OUTPUT_SW, - SB_DT019X_OUTPUT_SW2, - SB_DT019X_CAPTURE_SW, -}; - -static unsigned char als4000_saved_regs[] = { - /* please verify in dsheet whether regs to be added - are actually real H/W or just dummy */ - SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, - SB_DSP4_OUTPUT_SW, - SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, - SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, - SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, - SB_DSP4_MIC_DEV, - SB_DSP4_SPEAKER_DEV, - SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1, - SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1, - SB_DT019X_OUTPUT_SW2, - SB_ALS4000_MONO_IO_CTRL, - SB_ALS4000_MIC_IN_GAIN, - SB_ALS4000_FMDAC, - SB_ALS4000_3D_SND_FX, - SB_ALS4000_3D_TIME_DELAY, - SB_ALS4000_CR3_CONFIGURATION, -}; - -static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) -{ - unsigned char *val = chip->saved_regs; - if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs))) - return; - for (; num_regs; num_regs--) - *val++ = snd_sbmixer_read(chip, *regs++); -} - -static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) -{ - unsigned char *val = chip->saved_regs; - if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs))) - return; - for (; num_regs; num_regs--) - snd_sbmixer_write(chip, *regs++, *val++); -} - -void snd_sbmixer_suspend(struct snd_sb *chip) -{ - switch (chip->hardware) { - case SB_HW_20: - case SB_HW_201: - save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs)); - break; - case SB_HW_PRO: - case SB_HW_JAZZ16: - save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs)); - break; - case SB_HW_16: - case SB_HW_ALS100: - case SB_HW_CS5530: - save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); - break; - case SB_HW_ALS4000: - save_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs)); - break; - case SB_HW_DT019X: - save_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs)); - break; - default: - break; - } -} - -void snd_sbmixer_resume(struct snd_sb *chip) -{ - switch (chip->hardware) { - case SB_HW_20: - case SB_HW_201: - restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs)); - break; - case SB_HW_PRO: - case SB_HW_JAZZ16: - restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs)); - break; - case SB_HW_16: - case SB_HW_ALS100: - case SB_HW_CS5530: - restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); - break; - case SB_HW_ALS4000: - restore_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs)); - break; - case SB_HW_DT019X: - restore_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs)); - break; - default: - break; - } -} -#endif diff --git a/ANDROID_3.4.5/sound/isa/sb/sbawe.c b/ANDROID_3.4.5/sound/isa/sb/sbawe.c deleted file mode 100644 index 2ec52a34..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sbawe.c +++ /dev/null @@ -1,2 +0,0 @@ -#define SNDRV_SBAWE -#include "sb16.c" diff --git a/ANDROID_3.4.5/sound/isa/sc6000.c b/ANDROID_3.4.5/sound/isa/sc6000.c deleted file mode 100644 index d97d0f38..00000000 --- a/ANDROID_3.4.5/sound/isa/sc6000.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Driver for Gallant SC-6000 soundcard. This card is also known as - * Audio Excel DSP 16 or Zoltrix AV302. - * These cards use CompuMedia ASC-9308 chip + AD1848 codec. - * SC-6600 and SC-7000 cards are also supported. They are based on - * CompuMedia ASC-9408 chip and CS4231 codec. - * - * Copyright (C) 2007 Krzysztof Helt - * - * I don't have documentation for this card. I used the driver - * for OSS/Free included in the kernel source as reference. - * - * 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 -#include -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include - -MODULE_AUTHOR("Krzysztof Helt"); -MODULE_DESCRIPTION("Gallant SC-6000"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Gallant, SC-6000}," - "{AudioExcel, Audio Excel DSP 16}," - "{Zoltrix, AV302}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220, 0x240 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 11 */ -static long mss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530, 0xe80 */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; - /* 0x300, 0x310, 0x320, 0x330 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 0 */ -static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0, 1, 3 */ -static bool joystick[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = false }; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for sc-6000 based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for sc-6000 based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable sc-6000 based soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for sc-6000 driver."); -module_param_array(mss_port, long, NULL, 0444); -MODULE_PARM_DESC(mss_port, "MSS Port # for sc-6000 driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for sc-6000 driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for sc-6000 driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for sc-6000 driver."); -module_param_array(dma, int, NULL, 0444); -MODULE_PARM_DESC(dma, "DMA # for sc-6000 driver."); -module_param_array(joystick, bool, NULL, 0444); -MODULE_PARM_DESC(joystick, "Enable gameport."); - -/* - * Commands of SC6000's DSP (SBPRO+special). - * Some of them are COMMAND_xx, in the future they may change. - */ -#define WRITE_MDIRQ_CFG 0x50 /* Set M&I&DRQ mask (the real config) */ -#define COMMAND_52 0x52 /* */ -#define READ_HARD_CFG 0x58 /* Read Hardware Config (I/O base etc) */ -#define COMMAND_5C 0x5c /* */ -#define COMMAND_60 0x60 /* */ -#define COMMAND_66 0x66 /* */ -#define COMMAND_6C 0x6c /* */ -#define COMMAND_6E 0x6e /* */ -#define COMMAND_88 0x88 /* Unknown command */ -#define DSP_INIT_MSS 0x8c /* Enable Microsoft Sound System mode */ -#define COMMAND_C5 0xc5 /* */ -#define GET_DSP_VERSION 0xe1 /* Get DSP Version */ -#define GET_DSP_COPYRIGHT 0xe3 /* Get DSP Copyright */ - -/* - * Offsets of SC6000 DSP I/O ports. The offset is added to base I/O port - * to have the actual I/O port. - * Register permissions are: - * (wo) == Write Only - * (ro) == Read Only - * (w-) == Write - * (r-) == Read - */ -#define DSP_RESET 0x06 /* offset of DSP RESET (wo) */ -#define DSP_READ 0x0a /* offset of DSP READ (ro) */ -#define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */ -#define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */ -#define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */ -#define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */ - -#define PFX "sc6000: " -#define DRV_NAME "SC-6000" - -/* hardware dependent functions */ - -/* - * sc6000_irq_to_softcfg - Decode irq number into cfg code. - */ -static __devinit unsigned char sc6000_irq_to_softcfg(int irq) -{ - unsigned char val = 0; - - switch (irq) { - case 5: - val = 0x28; - break; - case 7: - val = 0x8; - break; - case 9: - val = 0x10; - break; - case 10: - val = 0x18; - break; - case 11: - val = 0x20; - break; - default: - break; - } - return val; -} - -/* - * sc6000_dma_to_softcfg - Decode dma number into cfg code. - */ -static __devinit unsigned char sc6000_dma_to_softcfg(int dma) -{ - unsigned char val = 0; - - switch (dma) { - case 0: - val = 1; - break; - case 1: - val = 2; - break; - case 3: - val = 3; - break; - default: - break; - } - return val; -} - -/* - * sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code. - */ -static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq) -{ - unsigned char val = 0; - - switch (mpu_irq) { - case 5: - val = 4; - break; - case 7: - val = 0x44; - break; - case 9: - val = 0x84; - break; - case 10: - val = 0xc4; - break; - default: - break; - } - return val; -} - -static int sc6000_wait_data(char __iomem *vport) -{ - int loop = 1000; - unsigned char val = 0; - - do { - val = ioread8(vport + DSP_DATAVAIL); - if (val & 0x80) - return 0; - cpu_relax(); - } while (loop--); - - return -EAGAIN; -} - -static int sc6000_read(char __iomem *vport) -{ - if (sc6000_wait_data(vport)) - return -EBUSY; - - return ioread8(vport + DSP_READ); - -} - -static int sc6000_write(char __iomem *vport, int cmd) -{ - unsigned char val; - int loop = 500000; - - do { - val = ioread8(vport + DSP_STATUS); - /* - * DSP ready to receive data if bit 7 of val == 0 - */ - if (!(val & 0x80)) { - iowrite8(cmd, vport + DSP_COMMAND); - return 0; - } - cpu_relax(); - } while (loop--); - - snd_printk(KERN_ERR "DSP Command (0x%x) timeout.\n", cmd); - - return -EIO; -} - -static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command, - char *data, int data_len) -{ - int len = 0; - - if (sc6000_write(vport, command)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", command); - return -EIO; - } - - do { - int val = sc6000_read(vport); - - if (val < 0) - break; - - data[len++] = val; - - } while (len < data_len); - - /* - * If no more data available, return to the caller, no error if len>0. - * We have no other way to know when the string is finished. - */ - return len ? len : -EIO; -} - -static int __devinit sc6000_dsp_reset(char __iomem *vport) -{ - iowrite8(1, vport + DSP_RESET); - udelay(10); - iowrite8(0, vport + DSP_RESET); - udelay(20); - if (sc6000_read(vport) == 0xaa) - return 0; - return -ENODEV; -} - -/* detection and initialization */ -static int __devinit sc6000_hw_cfg_write(char __iomem *vport, const int *cfg) -{ - if (sc6000_write(vport, COMMAND_6C) < 0) { - snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C); - return -EIO; - } - if (sc6000_write(vport, COMMAND_5C) < 0) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_5C); - return -EIO; - } - if (sc6000_write(vport, cfg[0]) < 0) { - snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[0]); - return -EIO; - } - if (sc6000_write(vport, cfg[1]) < 0) { - snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[1]); - return -EIO; - } - if (sc6000_write(vport, COMMAND_C5) < 0) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_C5); - return -EIO; - } - - return 0; -} - -static int sc6000_cfg_write(char __iomem *vport, unsigned char softcfg) -{ - - if (sc6000_write(vport, WRITE_MDIRQ_CFG)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); - return -EIO; - } - if (sc6000_write(vport, softcfg)) { - snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); - return -EIO; - } - return 0; -} - -static int sc6000_setup_board(char __iomem *vport, int config) -{ - int loop = 10; - - do { - if (sc6000_write(vport, COMMAND_88)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", - COMMAND_88); - return -EIO; - } - } while ((sc6000_wait_data(vport) < 0) && loop--); - - if (sc6000_read(vport) < 0) { - snd_printk(KERN_ERR "sc6000_read after CMD 0x%x: failed\n", - COMMAND_88); - return -EIO; - } - - if (sc6000_cfg_write(vport, config)) - return -ENODEV; - - return 0; -} - -static int __devinit sc6000_init_mss(char __iomem *vport, int config, - char __iomem *vmss_port, int mss_config) -{ - if (sc6000_write(vport, DSP_INIT_MSS)) { - snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n", - DSP_INIT_MSS); - return -EIO; - } - - msleep(10); - - if (sc6000_cfg_write(vport, config)) - return -EIO; - - iowrite8(mss_config, vmss_port); - - return 0; -} - -static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg, - long xport, long xmpu, - long xmss_port, int joystick) -{ - cfg[0] = 0; - cfg[1] = 0; - if (xport == 0x240) - cfg[0] |= 1; - if (xmpu != SNDRV_AUTO_PORT) { - cfg[0] |= (xmpu & 0x30) >> 2; - cfg[1] |= 0x20; - } - if (xmss_port == 0xe80) - cfg[0] |= 0x10; - cfg[0] |= 0x40; /* always set */ - if (!joystick) - cfg[0] |= 0x02; - cfg[1] |= 0x80; /* enable WSS system */ - cfg[1] &= ~0x40; /* disable IDE */ - snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]); -} - -static int __devinit sc6000_init_board(char __iomem *vport, - char __iomem *vmss_port, int dev) -{ - char answer[15]; - char version[2]; - int mss_config = sc6000_irq_to_softcfg(irq[dev]) | - sc6000_dma_to_softcfg(dma[dev]); - int config = mss_config | - sc6000_mpu_irq_to_softcfg(mpu_irq[dev]); - int err; - int old = 0; - - err = sc6000_dsp_reset(vport); - if (err < 0) { - snd_printk(KERN_ERR "sc6000_dsp_reset: failed!\n"); - return err; - } - - memset(answer, 0, sizeof(answer)); - err = sc6000_dsp_get_answer(vport, GET_DSP_COPYRIGHT, answer, 15); - if (err <= 0) { - snd_printk(KERN_ERR "sc6000_dsp_copyright: failed!\n"); - return -ENODEV; - } - /* - * My SC-6000 card return "SC-6000" in DSPCopyright, so - * if we have something different, we have to be warned. - */ - if (strncmp("SC-6000", answer, 7)) - snd_printk(KERN_WARNING "Warning: non SC-6000 audio card!\n"); - - if (sc6000_dsp_get_answer(vport, GET_DSP_VERSION, version, 2) < 2) { - snd_printk(KERN_ERR "sc6000_dsp_version: failed!\n"); - return -ENODEV; - } - printk(KERN_INFO PFX "Detected model: %s, DSP version %d.%d\n", - answer, version[0], version[1]); - - /* set configuration */ - sc6000_write(vport, COMMAND_5C); - if (sc6000_read(vport) < 0) - old = 1; - - if (!old) { - int cfg[2]; - sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev], - mss_port[dev], joystick[dev]); - if (sc6000_hw_cfg_write(vport, cfg) < 0) { - snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n"); - return -EIO; - } - } - err = sc6000_setup_board(vport, config); - if (err < 0) { - snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); - return -ENODEV; - } - - sc6000_dsp_reset(vport); - - if (!old) { - sc6000_write(vport, COMMAND_60); - sc6000_write(vport, 0x02); - sc6000_dsp_reset(vport); - } - - err = sc6000_setup_board(vport, config); - if (err < 0) { - snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); - return -ENODEV; - } - err = sc6000_init_mss(vport, config, vmss_port, mss_config); - if (err < 0) { - snd_printk(KERN_ERR "Cannot initialize " - "Microsoft Sound System mode.\n"); - return -ENODEV; - } - - return 0; -} - -static int __devinit snd_sc6000_mixer(struct snd_wss *chip) -{ - struct snd_card *card = chip->card; - struct snd_ctl_elem_id id1, id2; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUX0 to FM */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "FM Playback Switch"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "FM Playback Volume"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) - return err; - /* reassign AUX1 to CD */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "CD Playback Switch"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "CD Playback Volume"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) - return err; - return 0; -} - -static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev) -{ - if (!enable[dev]) - return 0; - if (port[dev] == SNDRV_AUTO_PORT) { - printk(KERN_ERR PFX "specify IO port\n"); - return 0; - } - if (mss_port[dev] == SNDRV_AUTO_PORT) { - printk(KERN_ERR PFX "specify MSS port\n"); - return 0; - } - if (port[dev] != 0x220 && port[dev] != 0x240) { - printk(KERN_ERR PFX "Port must be 0x220 or 0x240\n"); - return 0; - } - if (mss_port[dev] != 0x530 && mss_port[dev] != 0xe80) { - printk(KERN_ERR PFX "MSS port must be 0x530 or 0xe80\n"); - return 0; - } - if (irq[dev] != SNDRV_AUTO_IRQ && !sc6000_irq_to_softcfg(irq[dev])) { - printk(KERN_ERR PFX "invalid IRQ %d\n", irq[dev]); - return 0; - } - if (dma[dev] != SNDRV_AUTO_DMA && !sc6000_dma_to_softcfg(dma[dev])) { - printk(KERN_ERR PFX "invalid DMA %d\n", dma[dev]); - return 0; - } - if (mpu_port[dev] != SNDRV_AUTO_PORT && - (mpu_port[dev] & ~0x30L) != 0x300) { - printk(KERN_ERR PFX "invalid MPU-401 port %lx\n", - mpu_port[dev]); - return 0; - } - if (mpu_port[dev] != SNDRV_AUTO_PORT && - mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] != 0 && - !sc6000_mpu_irq_to_softcfg(mpu_irq[dev])) { - printk(KERN_ERR PFX "invalid MPU-401 IRQ %d\n", mpu_irq[dev]); - return 0; - } - return 1; -} - -static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) -{ - static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 }; - static int possible_dmas[] = { 1, 3, 0, -1 }; - int err; - int xirq = irq[dev]; - int xdma = dma[dev]; - struct snd_card *card; - struct snd_wss *chip; - struct snd_opl3 *opl3; - char __iomem **vport; - char __iomem *vmss_port; - - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(vport), - &card); - if (err < 0) - return err; - - vport = card->private_data; - if (xirq == SNDRV_AUTO_IRQ) { - xirq = snd_legacy_find_free_irq(possible_irqs); - if (xirq < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - err = -EBUSY; - goto err_exit; - } - } - - if (xdma == SNDRV_AUTO_DMA) { - xdma = snd_legacy_find_free_dma(possible_dmas); - if (xdma < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); - err = -EBUSY; - goto err_exit; - } - } - - if (!request_region(port[dev], 0x10, DRV_NAME)) { - snd_printk(KERN_ERR PFX - "I/O port region is already in use.\n"); - err = -EBUSY; - goto err_exit; - } - *vport = devm_ioport_map(devptr, port[dev], 0x10); - if (*vport == NULL) { - snd_printk(KERN_ERR PFX - "I/O port cannot be iomaped.\n"); - err = -EBUSY; - goto err_unmap1; - } - - /* to make it marked as used */ - if (!request_region(mss_port[dev], 4, DRV_NAME)) { - snd_printk(KERN_ERR PFX - "SC-6000 port I/O port region is already in use.\n"); - err = -EBUSY; - goto err_unmap1; - } - vmss_port = devm_ioport_map(devptr, mss_port[dev], 4); - if (!vmss_port) { - snd_printk(KERN_ERR PFX - "MSS port I/O cannot be iomaped.\n"); - err = -EBUSY; - goto err_unmap2; - } - - snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n", - port[dev], xirq, xdma, - mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]); - - err = sc6000_init_board(*vport, vmss_port, dev); - if (err < 0) - goto err_unmap2; - - err = snd_wss_create(card, mss_port[dev] + 4, -1, xirq, xdma, -1, - WSS_HW_DETECT, 0, &chip); - if (err < 0) - goto err_unmap2; - - err = snd_wss_pcm(chip, 0, NULL); - if (err < 0) { - snd_printk(KERN_ERR PFX - "error creating new WSS PCM device\n"); - goto err_unmap2; - } - err = snd_wss_mixer(chip); - if (err < 0) { - snd_printk(KERN_ERR PFX "error creating new WSS mixer\n"); - goto err_unmap2; - } - err = snd_sc6000_mixer(chip); - if (err < 0) { - snd_printk(KERN_ERR PFX "the mixer rewrite failed\n"); - goto err_unmap2; - } - if (snd_opl3_create(card, - 0x388, 0x388 + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", - 0x388, 0x388 + 2); - } else { - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - goto err_unmap2; - } - - if (mpu_port[dev] != SNDRV_AUTO_PORT) { - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; - if (snd_mpu401_uart_new(card, 0, - MPU401_HW_MPU401, - mpu_port[dev], 0, - mpu_irq[dev], NULL) < 0) - snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n", - mpu_port[dev]); - } - - strcpy(card->driver, DRV_NAME); - strcpy(card->shortname, "SC-6000"); - sprintf(card->longname, "Gallant SC-6000 at 0x%lx, irq %d, dma %d", - mss_port[dev], xirq, xdma); - - snd_card_set_dev(card, devptr); - - err = snd_card_register(card); - if (err < 0) - goto err_unmap2; - - dev_set_drvdata(devptr, card); - return 0; - -err_unmap2: - sc6000_setup_board(*vport, 0); - release_region(mss_port[dev], 4); -err_unmap1: - release_region(port[dev], 0x10); -err_exit: - snd_card_free(card); - return err; -} - -static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev) -{ - struct snd_card *card = dev_get_drvdata(devptr); - char __iomem **vport = card->private_data; - - if (sc6000_setup_board(*vport, 0) < 0) - snd_printk(KERN_WARNING "sc6000_setup_board failed on exit!\n"); - - release_region(port[dev], 0x10); - release_region(mss_port[dev], 4); - - dev_set_drvdata(devptr, NULL); - snd_card_free(card); - return 0; -} - -static struct isa_driver snd_sc6000_driver = { - .match = snd_sc6000_match, - .probe = snd_sc6000_probe, - .remove = __devexit_p(snd_sc6000_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DRV_NAME, - }, -}; - - -static int __init alsa_card_sc6000_init(void) -{ - return isa_register_driver(&snd_sc6000_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_sc6000_exit(void) -{ - isa_unregister_driver(&snd_sc6000_driver); -} - -module_init(alsa_card_sc6000_init) -module_exit(alsa_card_sc6000_exit) diff --git a/ANDROID_3.4.5/sound/isa/sscape.c b/ANDROID_3.4.5/sound/isa/sscape.c deleted file mode 100644 index 8490f597..00000000 --- a/ANDROID_3.4.5/sound/isa/sscape.c +++ /dev/null @@ -1,1359 +0,0 @@ -/* - * Low-level ALSA driver for the ENSONIQ SoundScape - * Copyright (c) by Chris Rankin - * - * This driver was written in part using information obtained from - * the OSS/Free SoundScape driver, written by Hannu Savolainen. - * - * - * 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 -#include -#include -#include -#include - - -MODULE_AUTHOR("Chris Rankin"); -MODULE_DESCRIPTION("ENSONIQ SoundScape driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("sndscape.co0"); -MODULE_FIRMWARE("sndscape.co1"); -MODULE_FIRMWARE("sndscape.co2"); -MODULE_FIRMWARE("sndscape.co3"); -MODULE_FIRMWARE("sndscape.co4"); -MODULE_FIRMWARE("scope.cod"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static bool joystick[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index number for SoundScape soundcard"); - -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "Description for SoundScape card"); - -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for SoundScape driver."); - -module_param_array(wss_port, long, NULL, 0444); -MODULE_PARM_DESC(wss_port, "WSS Port # for SoundScape driver."); - -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver."); - -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver."); - -module_param_array(dma, int, NULL, 0444); -MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); - -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver."); - -module_param_array(joystick, bool, NULL, 0444); -MODULE_PARM_DESC(joystick, "Enable gameport."); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; - -static struct pnp_card_device_id sscape_pnpids[] = { - { .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */ - { .id = "ENS4081", .devs = { { "ENS1011" } } }, /* VIVO90 */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids); -#endif - - -#define HOST_CTRL_IO(i) ((i) + 2) -#define HOST_DATA_IO(i) ((i) + 3) -#define ODIE_ADDR_IO(i) ((i) + 4) -#define ODIE_DATA_IO(i) ((i) + 5) -#define CODEC_IO(i) ((i) + 8) - -#define IC_ODIE 1 -#define IC_OPUS 2 - -#define RX_READY 0x01 -#define TX_READY 0x02 - -#define CMD_ACK 0x80 -#define CMD_SET_MIDI_VOL 0x84 -#define CMD_GET_MIDI_VOL 0x85 -#define CMD_XXX_MIDI_VOL 0x86 -#define CMD_SET_EXTMIDI 0x8a -#define CMD_GET_EXTMIDI 0x8b -#define CMD_SET_MT32 0x8c -#define CMD_GET_MT32 0x8d - -enum GA_REG { - GA_INTSTAT_REG = 0, - GA_INTENA_REG, - GA_DMAA_REG, - GA_DMAB_REG, - GA_INTCFG_REG, - GA_DMACFG_REG, - GA_CDCFG_REG, - GA_SMCFGA_REG, - GA_SMCFGB_REG, - GA_HMCTL_REG -}; - -#define DMA_8BIT 0x80 - - -enum card_type { - MEDIA_FX, /* Sequoia S-1000 */ - SSCAPE, /* Sequoia S-2000 */ - SSCAPE_PNP, - SSCAPE_VIVO, -}; - -struct soundscape { - spinlock_t lock; - unsigned io_base; - int ic_type; - enum card_type type; - struct resource *io_res; - struct resource *wss_res; - struct snd_wss *chip; - - unsigned char midi_vol; -}; - -#define INVALID_IRQ ((unsigned)-1) - - -static inline struct soundscape *get_card_soundscape(struct snd_card *c) -{ - return (struct soundscape *) (c->private_data); -} - -/* - * Allocates some kernel memory that we can use for DMA. - * I think this means that the memory has to map to - * contiguous pages of physical memory. - */ -static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, - unsigned long size) -{ - if (buf) { - if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - size, buf) < 0) { - snd_printk(KERN_ERR "sscape: Failed to allocate " - "%lu bytes for DMA\n", - size); - return NULL; - } - } - - return buf; -} - -/* - * Release the DMA-able kernel memory ... - */ -static void free_dmabuf(struct snd_dma_buffer *buf) -{ - if (buf && buf->area) - snd_dma_free_pages(buf); -} - -/* - * This function writes to the SoundScape's control registers, - * but doesn't do any locking. It's up to the caller to do that. - * This is why this function is "unsafe" ... - */ -static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, - unsigned char val) -{ - outb(reg, ODIE_ADDR_IO(io_base)); - outb(val, ODIE_DATA_IO(io_base)); -} - -/* - * Write to the SoundScape's control registers, and do the - * necessary locking ... - */ -static void sscape_write(struct soundscape *s, enum GA_REG reg, - unsigned char val) -{ - unsigned long flags; - - spin_lock_irqsave(&s->lock, flags); - sscape_write_unsafe(s->io_base, reg, val); - spin_unlock_irqrestore(&s->lock, flags); -} - -/* - * Read from the SoundScape's control registers, but leave any - * locking to the caller. This is why the function is "unsafe" ... - */ -static inline unsigned char sscape_read_unsafe(unsigned io_base, - enum GA_REG reg) -{ - outb(reg, ODIE_ADDR_IO(io_base)); - return inb(ODIE_DATA_IO(io_base)); -} - -/* - * Puts the SoundScape into "host" mode, as compared to "MIDI" mode - */ -static inline void set_host_mode_unsafe(unsigned io_base) -{ - outb(0x0, HOST_CTRL_IO(io_base)); -} - -/* - * Puts the SoundScape into "MIDI" mode, as compared to "host" mode - */ -static inline void set_midi_mode_unsafe(unsigned io_base) -{ - outb(0x3, HOST_CTRL_IO(io_base)); -} - -/* - * Read the SoundScape's host-mode control register, but leave - * any locking issues to the caller ... - */ -static inline int host_read_unsafe(unsigned io_base) -{ - int data = -1; - if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0) - data = inb(HOST_DATA_IO(io_base)); - - return data; -} - -/* - * Read the SoundScape's host-mode control register, performing - * a limited amount of busy-waiting if the register isn't ready. - * Also leaves all locking-issues to the caller ... - */ -static int host_read_ctrl_unsafe(unsigned io_base, unsigned timeout) -{ - int data; - - while (((data = host_read_unsafe(io_base)) < 0) && (timeout != 0)) { - udelay(100); - --timeout; - } /* while */ - - return data; -} - -/* - * Write to the SoundScape's host-mode control registers, but - * leave any locking issues to the caller ... - */ -static inline int host_write_unsafe(unsigned io_base, unsigned char data) -{ - if ((inb(HOST_CTRL_IO(io_base)) & TX_READY) != 0) { - outb(data, HOST_DATA_IO(io_base)); - return 1; - } - - return 0; -} - -/* - * Write to the SoundScape's host-mode control registers, performing - * a limited amount of busy-waiting if the register isn't ready. - * Also leaves all locking-issues to the caller ... - */ -static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data, - unsigned timeout) -{ - int err; - - while (!(err = host_write_unsafe(io_base, data)) && (timeout != 0)) { - udelay(100); - --timeout; - } /* while */ - - return err; -} - - -/* - * Check that the MIDI subsystem is operational. If it isn't, - * then we will hang the computer if we try to use it ... - * - * NOTE: This check is based upon observation, not documentation. - */ -static inline int verify_mpu401(const struct snd_mpu401 *mpu) -{ - return ((inb(MPU401C(mpu)) & 0xc0) == 0x80); -} - -/* - * This is apparently the standard way to initailise an MPU-401 - */ -static inline void initialise_mpu401(const struct snd_mpu401 *mpu) -{ - outb(0, MPU401D(mpu)); -} - -/* - * Tell the SoundScape to activate the AD1845 chip (I think). - * The AD1845 detection fails if we *don't* do this, so I - * think that this is a good idea ... - */ -static void activate_ad1845_unsafe(unsigned io_base) -{ - unsigned char val = sscape_read_unsafe(io_base, GA_HMCTL_REG); - sscape_write_unsafe(io_base, GA_HMCTL_REG, (val & 0xcf) | 0x10); - sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80); -} - -/* - * Do the necessary ALSA-level cleanup to deallocate our driver ... - */ -static void soundscape_free(struct snd_card *c) -{ - struct soundscape *sscape = get_card_soundscape(c); - release_and_free_resource(sscape->io_res); - release_and_free_resource(sscape->wss_res); - free_dma(sscape->chip->dma1); -} - -/* - * Tell the SoundScape to begin a DMA tranfer using the given channel. - * All locking issues are left to the caller. - */ -static void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg) -{ - sscape_write_unsafe(io_base, reg, - sscape_read_unsafe(io_base, reg) | 0x01); - sscape_write_unsafe(io_base, reg, - sscape_read_unsafe(io_base, reg) & 0xfe); -} - -/* - * Wait for a DMA transfer to complete. This is a "limited busy-wait", - * and all locking issues are left to the caller. - */ -static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, - unsigned timeout) -{ - while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) { - udelay(100); - --timeout; - } /* while */ - - return sscape_read_unsafe(io_base, reg) & 0x01; -} - -/* - * Wait for the On-Board Processor to return its start-up - * acknowledgement sequence. This wait is too long for - * us to perform "busy-waiting", and so we must sleep. - * This in turn means that we must not be holding any - * spinlocks when we call this function. - */ -static int obp_startup_ack(struct soundscape *s, unsigned timeout) -{ - unsigned long end_time = jiffies + msecs_to_jiffies(timeout); - - do { - unsigned long flags; - int x; - - spin_lock_irqsave(&s->lock, flags); - x = host_read_unsafe(s->io_base); - spin_unlock_irqrestore(&s->lock, flags); - if (x == 0xfe || x == 0xff) - return 1; - - msleep(10); - } while (time_before(jiffies, end_time)); - - return 0; -} - -/* - * Wait for the host to return its start-up acknowledgement - * sequence. This wait is too long for us to perform - * "busy-waiting", and so we must sleep. This in turn means - * that we must not be holding any spinlocks when we call - * this function. - */ -static int host_startup_ack(struct soundscape *s, unsigned timeout) -{ - unsigned long end_time = jiffies + msecs_to_jiffies(timeout); - - do { - unsigned long flags; - int x; - - spin_lock_irqsave(&s->lock, flags); - x = host_read_unsafe(s->io_base); - spin_unlock_irqrestore(&s->lock, flags); - if (x == 0xfe) - return 1; - - msleep(10); - } while (time_before(jiffies, end_time)); - - return 0; -} - -/* - * Upload a byte-stream into the SoundScape using DMA channel A. - */ -static int upload_dma_data(struct soundscape *s, const unsigned char *data, - size_t size) -{ - unsigned long flags; - struct snd_dma_buffer dma; - int ret; - unsigned char val; - - if (!get_dmabuf(&dma, PAGE_ALIGN(32 * 1024))) - return -ENOMEM; - - spin_lock_irqsave(&s->lock, flags); - - /* - * Reset the board ... - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val & 0x3f); - - /* - * Enable the DMA channels and configure them ... - */ - val = (s->chip->dma1 << 4) | DMA_8BIT; - sscape_write_unsafe(s->io_base, GA_DMAA_REG, val); - sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20); - - /* - * Take the board out of reset ... - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x80); - - /* - * Upload the firmware to the SoundScape - * board through the DMA channel ... - */ - while (size != 0) { - unsigned long len; - - len = min(size, dma.bytes); - memcpy(dma.area, data, len); - data += len; - size -= len; - - snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE); - sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG); - if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) { - /* - * Don't forget to release this spinlock we're holding - */ - spin_unlock_irqrestore(&s->lock, flags); - - snd_printk(KERN_ERR - "sscape: DMA upload has timed out\n"); - ret = -EAGAIN; - goto _release_dma; - } - } /* while */ - - set_host_mode_unsafe(s->io_base); - outb(0x0, s->io_base); - - /* - * Boot the board ... (I think) - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x40); - spin_unlock_irqrestore(&s->lock, flags); - - /* - * If all has gone well, then the board should acknowledge - * the new upload and tell us that it has rebooted OK. We - * give it 5 seconds (max) ... - */ - ret = 0; - if (!obp_startup_ack(s, 5000)) { - snd_printk(KERN_ERR "sscape: No response " - "from on-board processor after upload\n"); - ret = -EAGAIN; - } else if (!host_startup_ack(s, 5000)) { - snd_printk(KERN_ERR - "sscape: SoundScape failed to initialise\n"); - ret = -EAGAIN; - } - -_release_dma: - /* - * NOTE!!! We are NOT holding any spinlocks at this point !!! - */ - sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_OPUS ? 0x40 : 0x70)); - free_dmabuf(&dma); - - return ret; -} - -/* - * Upload the bootblock(?) into the SoundScape. The only - * purpose of this block of code seems to be to tell - * us which version of the microcode we should be using. - */ -static int sscape_upload_bootblock(struct snd_card *card) -{ - struct soundscape *sscape = get_card_soundscape(card); - unsigned long flags; - const struct firmware *init_fw = NULL; - int data = 0; - int ret; - - ret = request_firmware(&init_fw, "scope.cod", card->dev); - if (ret < 0) { - snd_printk(KERN_ERR "sscape: Error loading scope.cod"); - return ret; - } - ret = upload_dma_data(sscape, init_fw->data, init_fw->size); - - release_firmware(init_fw); - - spin_lock_irqsave(&sscape->lock, flags); - if (ret == 0) - data = host_read_ctrl_unsafe(sscape->io_base, 100); - - if (data & 0x10) - sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2f); - - spin_unlock_irqrestore(&sscape->lock, flags); - - data &= 0xf; - if (ret == 0 && data > 7) { - snd_printk(KERN_ERR - "sscape: timeout reading firmware version\n"); - ret = -EAGAIN; - } - - return (ret == 0) ? data : ret; -} - -/* - * Upload the microcode into the SoundScape. - */ -static int sscape_upload_microcode(struct snd_card *card, int version) -{ - struct soundscape *sscape = get_card_soundscape(card); - const struct firmware *init_fw = NULL; - char name[14]; - int err; - - snprintf(name, sizeof(name), "sndscape.co%d", version); - - err = request_firmware(&init_fw, name, card->dev); - if (err < 0) { - snd_printk(KERN_ERR "sscape: Error loading sndscape.co%d", - version); - return err; - } - err = upload_dma_data(sscape, init_fw->data, init_fw->size); - if (err == 0) - snd_printk(KERN_INFO "sscape: MIDI firmware loaded %d KBs\n", - init_fw->size >> 10); - - release_firmware(init_fw); - - return err; -} - -/* - * Mixer control for the SoundScape's MIDI device. - */ -static int sscape_midi_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 127; - return 0; -} - -static int sscape_midi_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct snd_wss *chip = snd_kcontrol_chip(kctl); - struct snd_card *card = chip->card; - register struct soundscape *s = get_card_soundscape(card); - unsigned long flags; - - spin_lock_irqsave(&s->lock, flags); - uctl->value.integer.value[0] = s->midi_vol; - spin_unlock_irqrestore(&s->lock, flags); - return 0; -} - -static int sscape_midi_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct snd_wss *chip = snd_kcontrol_chip(kctl); - struct snd_card *card = chip->card; - struct soundscape *s = get_card_soundscape(card); - unsigned long flags; - int change; - unsigned char new_val; - - spin_lock_irqsave(&s->lock, flags); - - new_val = uctl->value.integer.value[0] & 127; - /* - * We need to put the board into HOST mode before we - * can send any volume-changing HOST commands ... - */ - set_host_mode_unsafe(s->io_base); - - /* - * To successfully change the MIDI volume setting, you seem to - * have to write a volume command, write the new volume value, - * and then perform another volume-related command. Perhaps the - * first command is an "open" and the second command is a "close"? - */ - if (s->midi_vol == new_val) { - change = 0; - goto __skip_change; - } - change = host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100) - && host_write_ctrl_unsafe(s->io_base, new_val, 100) - && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100) - && host_write_ctrl_unsafe(s->io_base, new_val, 100); - s->midi_vol = new_val; -__skip_change: - - /* - * Take the board out of HOST mode and back into MIDI mode ... - */ - set_midi_mode_unsafe(s->io_base); - - spin_unlock_irqrestore(&s->lock, flags); - return change; -} - -static struct snd_kcontrol_new midi_mixer_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "MIDI", - .info = sscape_midi_info, - .get = sscape_midi_get, - .put = sscape_midi_put -}; - -/* - * The SoundScape can use two IRQs from a possible set of four. - * These IRQs are encoded as bit patterns so that they can be - * written to the control registers. - */ -static unsigned __devinit get_irq_config(int sscape_type, int irq) -{ - static const int valid_irq[] = { 9, 5, 7, 10 }; - static const int old_irq[] = { 9, 7, 5, 15 }; - unsigned cfg; - - if (sscape_type == MEDIA_FX) { - for (cfg = 0; cfg < ARRAY_SIZE(old_irq); ++cfg) - if (irq == old_irq[cfg]) - return cfg; - } else { - for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg) - if (irq == valid_irq[cfg]) - return cfg; - } - - return INVALID_IRQ; -} - -/* - * Perform certain arcane port-checks to see whether there - * is a SoundScape board lurking behind the given ports. - */ -static int __devinit detect_sscape(struct soundscape *s, long wss_io) -{ - unsigned long flags; - unsigned d; - int retval = 0; - - spin_lock_irqsave(&s->lock, flags); - - /* - * The following code is lifted from the original OSS driver, - * and as I don't have a datasheet I cannot really comment - * on what it is doing... - */ - if ((inb(HOST_CTRL_IO(s->io_base)) & 0x78) != 0) - goto _done; - - d = inb(ODIE_ADDR_IO(s->io_base)) & 0xf0; - if ((d & 0x80) != 0) - goto _done; - - if (d == 0) - s->ic_type = IC_ODIE; - else if ((d & 0x60) != 0) - s->ic_type = IC_OPUS; - else - goto _done; - - outb(0xfa, ODIE_ADDR_IO(s->io_base)); - if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0a) - goto _done; - - outb(0xfe, ODIE_ADDR_IO(s->io_base)); - if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) - goto _done; - - outb(0xfe, ODIE_ADDR_IO(s->io_base)); - d = inb(ODIE_DATA_IO(s->io_base)); - if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e) - goto _done; - - if (s->ic_type == IC_OPUS) - activate_ad1845_unsafe(s->io_base); - - if (s->type == SSCAPE_VIVO) - wss_io += 4; - - d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); - - /* wait for WSS codec */ - for (d = 0; d < 500; d++) { - if ((inb(wss_io) & 0x80) == 0) - break; - spin_unlock_irqrestore(&s->lock, flags); - msleep(1); - spin_lock_irqsave(&s->lock, flags); - } - - if ((inb(wss_io) & 0x80) != 0) - goto _done; - - if (inb(wss_io + 2) == 0xff) - goto _done; - - d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f; - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d); - - if ((inb(wss_io) & 0x80) != 0) - s->type = MEDIA_FX; - - d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); - /* wait for WSS codec */ - for (d = 0; d < 500; d++) { - if ((inb(wss_io) & 0x80) == 0) - break; - spin_unlock_irqrestore(&s->lock, flags); - msleep(1); - spin_lock_irqsave(&s->lock, flags); - } - - /* - * SoundScape successfully detected! - */ - retval = 1; - -_done: - spin_unlock_irqrestore(&s->lock, flags); - return retval; -} - -/* - * ALSA callback function, called when attempting to open the MIDI device. - * Check that the MIDI firmware has been loaded, because we don't want - * to crash the machine. Also check that someone isn't using the hardware - * IOCTL device. - */ -static int mpu401_open(struct snd_mpu401 *mpu) -{ - if (!verify_mpu401(mpu)) { - snd_printk(KERN_ERR "sscape: MIDI disabled, " - "please load firmware\n"); - return -ENODEV; - } - - return 0; -} - -/* - * Initialse an MPU-401 subdevice for MIDI support on the SoundScape. - */ -static int __devinit create_mpu401(struct snd_card *card, int devnum, - unsigned long port, int irq) -{ - struct soundscape *sscape = get_card_soundscape(card); - struct snd_rawmidi *rawmidi; - int err; - - err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port, - MPU401_INFO_INTEGRATED, irq, &rawmidi); - if (err == 0) { - struct snd_mpu401 *mpu = rawmidi->private_data; - mpu->open_input = mpu401_open; - mpu->open_output = mpu401_open; - mpu->private_data = sscape; - - initialise_mpu401(mpu); - } - - return err; -} - - -/* - * Create an AD1845 PCM subdevice on the SoundScape. The AD1845 - * is very much like a CS4231, with a few extra bits. We will - * try to support at least some of the extra bits by overriding - * some of the CS4231 callback. - */ -static int __devinit create_ad1845(struct snd_card *card, unsigned port, - int irq, int dma1, int dma2) -{ - register struct soundscape *sscape = get_card_soundscape(card); - struct snd_wss *chip; - int err; - int codec_type = WSS_HW_DETECT; - - switch (sscape->type) { - case MEDIA_FX: - case SSCAPE: - /* - * There are some freak examples of early Soundscape cards - * with CS4231 instead of AD1848/CS4248. Unfortunately, the - * CS4231 works only in CS4248 compatibility mode on - * these cards so force it. - */ - if (sscape->ic_type != IC_OPUS) - codec_type = WSS_HW_AD1848; - break; - - case SSCAPE_VIVO: - port += 4; - break; - default: - break; - } - - err = snd_wss_create(card, port, -1, irq, dma1, dma2, - codec_type, WSS_HWSHARE_DMA1, &chip); - if (!err) { - unsigned long flags; - struct snd_pcm *pcm; - - if (sscape->type != SSCAPE_VIVO) { - /* - * The input clock frequency on the SoundScape must - * be 14.31818 MHz, because we must set this register - * to get the playback to sound correct ... - */ - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, AD1845_CLOCK, 0x20); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - - } - - err = snd_wss_pcm(chip, 0, &pcm); - if (err < 0) { - snd_printk(KERN_ERR "sscape: No PCM device " - "for AD1845 chip\n"); - goto _error; - } - - err = snd_wss_mixer(chip); - if (err < 0) { - snd_printk(KERN_ERR "sscape: No mixer device " - "for AD1845 chip\n"); - goto _error; - } - if (chip->hardware != WSS_HW_AD1848) { - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) { - snd_printk(KERN_ERR "sscape: No timer device " - "for AD1845 chip\n"); - goto _error; - } - } - - if (sscape->type != SSCAPE_VIVO) { - err = snd_ctl_add(card, - snd_ctl_new1(&midi_mixer_ctl, chip)); - if (err < 0) { - snd_printk(KERN_ERR "sscape: Could not create " - "MIDI mixer control\n"); - goto _error; - } - } - - sscape->chip = chip; - } - -_error: - return err; -} - - -/* - * Create an ALSA soundcard entry for the SoundScape, using - * the given list of port, IRQ and DMA resources. - */ -static int __devinit create_sscape(int dev, struct snd_card *card) -{ - struct soundscape *sscape = get_card_soundscape(card); - unsigned dma_cfg; - unsigned irq_cfg; - unsigned mpu_irq_cfg; - struct resource *io_res; - struct resource *wss_res; - unsigned long flags; - int err; - int val; - const char *name; - - /* - * Grab IO ports that we will need to probe so that we - * can detect and control this hardware ... - */ - io_res = request_region(port[dev], 8, "SoundScape"); - if (!io_res) { - snd_printk(KERN_ERR - "sscape: can't grab port 0x%lx\n", port[dev]); - return -EBUSY; - } - wss_res = NULL; - if (sscape->type == SSCAPE_VIVO) { - wss_res = request_region(wss_port[dev], 4, "SoundScape"); - if (!wss_res) { - snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n", - wss_port[dev]); - err = -EBUSY; - goto _release_region; - } - } - - /* - * Grab one DMA channel ... - */ - err = request_dma(dma[dev], "SoundScape"); - if (err < 0) { - snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]); - goto _release_region; - } - - spin_lock_init(&sscape->lock); - sscape->io_res = io_res; - sscape->wss_res = wss_res; - sscape->io_base = port[dev]; - - if (!detect_sscape(sscape, wss_port[dev])) { - printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", - sscape->io_base); - err = -ENODEV; - goto _release_dma; - } - - switch (sscape->type) { - case MEDIA_FX: - name = "MediaFX/SoundFX"; - break; - case SSCAPE: - name = "Soundscape"; - break; - case SSCAPE_PNP: - name = "Soundscape PnP"; - break; - case SSCAPE_VIVO: - name = "Soundscape VIVO"; - break; - default: - name = "unknown Soundscape"; - break; - } - - printk(KERN_INFO "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n", - name, sscape->io_base, irq[dev], dma[dev]); - - /* - * Check that the user didn't pass us garbage data ... - */ - irq_cfg = get_irq_config(sscape->type, irq[dev]); - if (irq_cfg == INVALID_IRQ) { - snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]); - err = -ENXIO; - goto _release_dma; - } - - mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]); - if (mpu_irq_cfg == INVALID_IRQ) { - snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); - err = -ENXIO; - goto _release_dma; - } - - /* - * Tell the on-board devices where their resources are (I think - - * I can't be sure without a datasheet ... So many magic values!) - */ - spin_lock_irqsave(&sscape->lock, flags); - - sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); - sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); - - /* - * Enable and configure the DMA channels ... - */ - sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); - dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70); - sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); - sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); - - mpu_irq_cfg |= mpu_irq_cfg << 2; - val = sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xF7; - if (joystick[dev]) - val |= 8; - sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0x10); - sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg); - sscape_write_unsafe(sscape->io_base, - GA_CDCFG_REG, 0x09 | DMA_8BIT - | (dma[dev] << 4) | (irq_cfg << 1)); - /* - * Enable the master IRQ ... - */ - sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80); - - spin_unlock_irqrestore(&sscape->lock, flags); - - /* - * We have now enabled the codec chip, and so we should - * detect the AD1845 device ... - */ - err = create_ad1845(card, wss_port[dev], irq[dev], - dma[dev], dma2[dev]); - if (err < 0) { - snd_printk(KERN_ERR - "sscape: No AD1845 device at 0x%lx, IRQ %d\n", - wss_port[dev], irq[dev]); - goto _release_dma; - } - strcpy(card->driver, "SoundScape"); - strcpy(card->shortname, name); - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n", - name, sscape->chip->port, sscape->chip->irq, - sscape->chip->dma1, sscape->chip->dma2); - -#define MIDI_DEVNUM 0 - if (sscape->type != SSCAPE_VIVO) { - err = sscape_upload_bootblock(card); - if (err >= 0) - err = sscape_upload_microcode(card, err); - - if (err == 0) { - err = create_mpu401(card, MIDI_DEVNUM, port[dev], - mpu_irq[dev]); - if (err < 0) { - snd_printk(KERN_ERR "sscape: Failed to create " - "MPU-401 device at 0x%lx\n", - port[dev]); - goto _release_dma; - } - - /* - * Initialize mixer - */ - spin_lock_irqsave(&sscape->lock, flags); - sscape->midi_vol = 0; - host_write_ctrl_unsafe(sscape->io_base, - CMD_SET_MIDI_VOL, 100); - host_write_ctrl_unsafe(sscape->io_base, - sscape->midi_vol, 100); - host_write_ctrl_unsafe(sscape->io_base, - CMD_XXX_MIDI_VOL, 100); - host_write_ctrl_unsafe(sscape->io_base, - sscape->midi_vol, 100); - host_write_ctrl_unsafe(sscape->io_base, - CMD_SET_EXTMIDI, 100); - host_write_ctrl_unsafe(sscape->io_base, - 0, 100); - host_write_ctrl_unsafe(sscape->io_base, CMD_ACK, 100); - - set_midi_mode_unsafe(sscape->io_base); - spin_unlock_irqrestore(&sscape->lock, flags); - } - } - - /* - * Now that we have successfully created this sound card, - * it is safe to store the pointer. - * NOTE: we only register the sound card's "destructor" - * function now that our "constructor" has completed. - */ - card->private_free = soundscape_free; - - return 0; - -_release_dma: - free_dma(dma[dev]); - -_release_region: - release_and_free_resource(wss_res); - release_and_free_resource(io_res); - - return err; -} - - -static int __devinit snd_sscape_match(struct device *pdev, unsigned int i) -{ - /* - * Make sure we were given ALL of the other parameters. - */ - if (port[i] == SNDRV_AUTO_PORT) - return 0; - - if (irq[i] == SNDRV_AUTO_IRQ || - mpu_irq[i] == SNDRV_AUTO_IRQ || - dma[i] == SNDRV_AUTO_DMA) { - printk(KERN_INFO - "sscape: insufficient parameters, " - "need IO, IRQ, MPU-IRQ and DMA\n"); - return 0; - } - - return 1; -} - -static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) -{ - struct snd_card *card; - struct soundscape *sscape; - int ret; - - ret = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct soundscape), &card); - if (ret < 0) - return ret; - - sscape = get_card_soundscape(card); - sscape->type = SSCAPE; - - dma[dev] &= 0x03; - snd_card_set_dev(card, pdev); - - ret = create_sscape(dev, card); - if (ret < 0) - goto _release_card; - - ret = snd_card_register(card); - if (ret < 0) { - snd_printk(KERN_ERR "sscape: Failed to register sound card\n"); - goto _release_card; - } - dev_set_drvdata(pdev, card); - return 0; - -_release_card: - snd_card_free(card); - return ret; -} - -static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#define DEV_NAME "sscape" - -static struct isa_driver snd_sscape_driver = { - .match = snd_sscape_match, - .probe = snd_sscape_probe, - .remove = __devexit_p(snd_sscape_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DEV_NAME - }, -}; - -#ifdef CONFIG_PNP -static inline int __devinit get_next_autoindex(int i) -{ - while (i < SNDRV_CARDS && port[i] != SNDRV_AUTO_PORT) - ++i; - return i; -} - - -static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int idx = 0; - struct pnp_dev *dev; - struct snd_card *card; - struct soundscape *sscape; - int ret; - - /* - * Allow this function to fail *quietly* if all the ISA PnP - * devices were configured using module parameters instead. - */ - idx = get_next_autoindex(idx); - if (idx >= SNDRV_CARDS) - return -ENOSPC; - - /* - * Check that we still have room for another sound card ... - */ - dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); - if (!dev) - return -ENODEV; - - if (!pnp_is_active(dev)) { - if (pnp_activate_dev(dev) < 0) { - snd_printk(KERN_INFO "sscape: device is inactive\n"); - return -EBUSY; - } - } - - /* - * Create a new ALSA sound card entry, in anticipation - * of detecting our hardware ... - */ - ret = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct soundscape), &card); - if (ret < 0) - return ret; - - sscape = get_card_soundscape(card); - - /* - * Identify card model ... - */ - if (!strncmp("ENS4081", pid->id, 7)) - sscape->type = SSCAPE_VIVO; - else - sscape->type = SSCAPE_PNP; - - /* - * Read the correct parameters off the ISA PnP bus ... - */ - port[idx] = pnp_port_start(dev, 0); - irq[idx] = pnp_irq(dev, 0); - mpu_irq[idx] = pnp_irq(dev, 1); - dma[idx] = pnp_dma(dev, 0) & 0x03; - if (sscape->type == SSCAPE_PNP) { - dma2[idx] = dma[idx]; - wss_port[idx] = CODEC_IO(port[idx]); - } else { - wss_port[idx] = pnp_port_start(dev, 1); - dma2[idx] = pnp_dma(dev, 1); - } - snd_card_set_dev(card, &pcard->card->dev); - - ret = create_sscape(idx, card); - if (ret < 0) - goto _release_card; - - ret = snd_card_register(card); - if (ret < 0) { - snd_printk(KERN_ERR "sscape: Failed to register sound card\n"); - goto _release_card; - } - - pnp_set_card_drvdata(pcard, card); - ++idx; - return 0; - -_release_card: - snd_card_free(card); - return ret; -} - -static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static struct pnp_card_driver sscape_pnpc_driver = { - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - .name = "sscape", - .id_table = sscape_pnpids, - .probe = sscape_pnp_detect, - .remove = __devexit_p(sscape_pnp_remove), -}; - -#endif /* CONFIG_PNP */ - -static int __init sscape_init(void) -{ - int err; - - err = isa_register_driver(&snd_sscape_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&sscape_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit sscape_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&sscape_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_sscape_driver); -} - -module_init(sscape_init); -module_exit(sscape_exit); diff --git a/ANDROID_3.4.5/sound/isa/wavefront/Makefile b/ANDROID_3.4.5/sound/isa/wavefront/Makefile deleted file mode 100644 index 601bdddd..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_WAVEFRONT) += snd-wavefront.o diff --git a/ANDROID_3.4.5/sound/isa/wavefront/wavefront.c b/ANDROID_3.4.5/sound/isa/wavefront/wavefront.c deleted file mode 100644 index e0a73271..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/wavefront.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * ALSA card-level driver for Turtle Beach Wavefront cards - * (Maui,Tropez,Tropez+) - * - * Copyright (c) 1997-1999 by Paul Barton-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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Paul Barton-Davis "); -MODULE_DESCRIPTION("Turtle Beach Wavefront"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long cs4232_pcm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int cs4232_pcm_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ -static long cs4232_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int cs4232_mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */ -static long ics2115_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int ics2115_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,9,11,12,15 */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static bool use_cs4232_midi[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for WaveFront soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for WaveFront soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable WaveFront soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "ISA PnP detection for WaveFront soundcards."); -#endif -module_param_array(cs4232_pcm_port, long, NULL, 0444); -MODULE_PARM_DESC(cs4232_pcm_port, "Port # for CS4232 PCM interface."); -module_param_array(cs4232_pcm_irq, int, NULL, 0444); -MODULE_PARM_DESC(cs4232_pcm_irq, "IRQ # for CS4232 PCM interface."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for CS4232 PCM interface."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for CS4232 PCM interface."); -module_param_array(cs4232_mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(cs4232_mpu_port, "port # for CS4232 MPU-401 interface."); -module_param_array(cs4232_mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(cs4232_mpu_irq, "IRQ # for CS4232 MPU-401 interface."); -module_param_array(ics2115_irq, int, NULL, 0444); -MODULE_PARM_DESC(ics2115_irq, "IRQ # for ICS2115."); -module_param_array(ics2115_port, long, NULL, 0444); -MODULE_PARM_DESC(ics2115_port, "Port # for ICS2115."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port #."); -module_param_array(use_cs4232_midi, bool, NULL, 0444); -MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)"); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; - -static struct pnp_card_device_id snd_wavefront_pnpids[] = { - /* Tropez */ - { .id = "CSC7532", .devs = { { "CSC0000" }, { "CSC0010" }, { "PnPb006" }, { "CSC0004" } } }, - /* Tropez+ */ - { .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PnPb006" }, { "CSC0004" } } }, - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_wavefront_pnpids); - -static int __devinit -snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - /* Check for each logical device. */ - - /* CS4232 chip (aka "windows sound system") is logical device 0 */ - - acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->wss == NULL) - return -EBUSY; - - /* there is a game port at logical device 1, but we ignore it completely */ - - /* the control interface is logical device 2, but we ignore it - completely. in fact, nobody even seems to know what it - does. - */ - - /* Only configure the CS4232 MIDI interface if its been - specifically requested. It is logical device 3. - */ - - if (use_cs4232_midi[dev]) { - acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); - if (acard->mpu == NULL) - return -EBUSY; - } - - /* The ICS2115 synth is logical device 4 */ - - acard->synth = pnp_request_card_device(card, id->devs[3].id, NULL); - if (acard->synth == NULL) - return -EBUSY; - - /* PCM/FM initialization */ - - pdev = acard->wss; - - /* An interesting note from the Tropez+ FAQ: - - Q. [Ports] Why is the base address of the WSS I/O ports off by 4? - - A. WSS I/O requires a block of 8 I/O addresses ("ports"). Of these, the first - 4 are used to identify and configure the board. With the advent of PnP, - these first 4 addresses have become obsolete, and software applications - only use the last 4 addresses to control the codec chip. Therefore, the - base address setting "skips past" the 4 unused addresses. - - */ - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "PnP WSS pnp configure failure\n"); - return err; - } - - cs4232_pcm_port[dev] = pnp_port_start(pdev, 0); - fm_port[dev] = pnp_port_start(pdev, 1); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - cs4232_pcm_irq[dev] = pnp_irq(pdev, 0); - - /* Synth initialization */ - - pdev = acard->synth; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "PnP ICS2115 pnp configure failure\n"); - return err; - } - - ics2115_port[dev] = pnp_port_start(pdev, 0); - ics2115_irq[dev] = pnp_irq(pdev, 0); - - /* CS4232 MPU initialization. Configure this only if - explicitly requested, since its physically inaccessible and - consumes another IRQ. - */ - - if (use_cs4232_midi[dev]) { - - pdev = acard->mpu; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "PnP MPU401 pnp configure failure\n"); - cs4232_mpu_port[dev] = SNDRV_AUTO_PORT; - } else { - cs4232_mpu_port[dev] = pnp_port_start(pdev, 0); - cs4232_mpu_irq[dev] = pnp_irq(pdev, 0); - } - - snd_printk (KERN_INFO "CS4232 MPU: port=0x%lx, irq=%i\n", - cs4232_mpu_port[dev], - cs4232_mpu_irq[dev]); - } - - snd_printdd ("CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n", - cs4232_pcm_port[dev], - fm_port[dev], - dma1[dev], - dma2[dev], - cs4232_pcm_irq[dev], - ics2115_port[dev], - ics2115_irq[dev]); - - return 0; -} - -#endif /* CONFIG_PNP */ - -static irqreturn_t snd_wavefront_ics2115_interrupt(int irq, void *dev_id) -{ - snd_wavefront_card_t *acard; - - acard = (snd_wavefront_card_t *) dev_id; - - if (acard == NULL) - return IRQ_NONE; - - if (acard->wavefront.interrupts_are_midi) { - snd_wavefront_midi_interrupt (acard); - } else { - snd_wavefront_internal_interrupt (acard); - } - return IRQ_HANDLED; -} - -static struct snd_hwdep * __devinit -snd_wavefront_new_synth (struct snd_card *card, - int hw_dev, - snd_wavefront_card_t *acard) -{ - struct snd_hwdep *wavefront_synth; - - if (snd_wavefront_detect (acard) < 0) { - return NULL; - } - - if (snd_wavefront_start (&acard->wavefront) < 0) { - return NULL; - } - - if (snd_hwdep_new(card, "WaveFront", hw_dev, &wavefront_synth) < 0) - return NULL; - strcpy (wavefront_synth->name, - "WaveFront (ICS2115) wavetable synthesizer"); - wavefront_synth->ops.open = snd_wavefront_synth_open; - wavefront_synth->ops.release = snd_wavefront_synth_release; - wavefront_synth->ops.ioctl = snd_wavefront_synth_ioctl; - - return wavefront_synth; -} - -static struct snd_hwdep * __devinit -snd_wavefront_new_fx (struct snd_card *card, - int hw_dev, - snd_wavefront_card_t *acard, - unsigned long port) - -{ - struct snd_hwdep *fx_processor; - - if (snd_wavefront_fx_start (&acard->wavefront)) { - snd_printk (KERN_ERR "cannot initialize YSS225 FX processor"); - return NULL; - } - - if (snd_hwdep_new (card, "YSS225", hw_dev, &fx_processor) < 0) - return NULL; - sprintf (fx_processor->name, "YSS225 FX Processor at 0x%lx", port); - fx_processor->ops.open = snd_wavefront_fx_open; - fx_processor->ops.release = snd_wavefront_fx_release; - fx_processor->ops.ioctl = snd_wavefront_fx_ioctl; - - return fx_processor; -} - -static snd_wavefront_mpu_id internal_id = internal_mpu; -static snd_wavefront_mpu_id external_id = external_mpu; - -static struct snd_rawmidi *__devinit -snd_wavefront_new_midi (struct snd_card *card, - int midi_dev, - snd_wavefront_card_t *acard, - unsigned long port, - snd_wavefront_mpu_id mpu) - -{ - struct snd_rawmidi *rmidi; - static int first = 1; - - if (first) { - first = 0; - acard->wavefront.midi.base = port; - if (snd_wavefront_midi_start (acard)) { - snd_printk (KERN_ERR "cannot initialize MIDI interface\n"); - return NULL; - } - } - - if (snd_rawmidi_new (card, "WaveFront MIDI", midi_dev, 1, 1, &rmidi) < 0) - return NULL; - - if (mpu == internal_mpu) { - strcpy(rmidi->name, "WaveFront MIDI (Internal)"); - rmidi->private_data = &internal_id; - } else { - strcpy(rmidi->name, "WaveFront MIDI (External)"); - rmidi->private_data = &external_id; - } - - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_wavefront_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_wavefront_midi_input); - - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - return rmidi; -} - -static void -snd_wavefront_free(struct snd_card *card) -{ - snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data; - - if (acard) { - release_and_free_resource(acard->wavefront.res_base); - if (acard->wavefront.irq > 0) - free_irq(acard->wavefront.irq, (void *)acard); - } -} - -static int snd_wavefront_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - snd_wavefront_card_t *acard; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(snd_wavefront_card_t), &card); - if (err < 0) - return err; - - acard = card->private_data; - acard->wavefront.irq = -1; - spin_lock_init(&acard->wavefront.irq_lock); - init_waitqueue_head(&acard->wavefront.interrupt_sleeper); - spin_lock_init(&acard->wavefront.midi.open); - spin_lock_init(&acard->wavefront.midi.virtual); - acard->wavefront.card = card; - card->private_free = snd_wavefront_free; - - *cardp = card; - return 0; -} - -static int __devinit -snd_wavefront_probe (struct snd_card *card, int dev) -{ - snd_wavefront_card_t *acard = card->private_data; - struct snd_wss *chip; - struct snd_hwdep *wavefront_synth; - struct snd_rawmidi *ics2115_internal_rmidi = NULL; - struct snd_rawmidi *ics2115_external_rmidi = NULL; - struct snd_hwdep *fx_processor; - int hw_dev = 0, midi_dev = 0, err; - - /* --------- PCM --------------- */ - - err = snd_wss_create(card, cs4232_pcm_port[dev], -1, - cs4232_pcm_irq[dev], dma1[dev], dma2[dev], - WSS_HW_DETECT, 0, &chip); - if (err < 0) { - snd_printk(KERN_ERR "can't allocate WSS device\n"); - return err; - } - - err = snd_wss_pcm(chip, 0, NULL); - if (err < 0) - return err; - - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) - return err; - - /* ---------- OPL3 synth --------- */ - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - struct snd_opl3 *opl3; - - err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, - OPL3_HW_OPL3_CS, 0, &opl3); - if (err < 0) { - snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n"); - return err; - } - - err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL); - if (err < 0) - return err; - hw_dev++; - } - - /* ------- ICS2115 Wavetable synth ------- */ - - acard->wavefront.res_base = request_region(ics2115_port[dev], 16, - "ICS2115"); - if (acard->wavefront.res_base == NULL) { - snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", - ics2115_port[dev], ics2115_port[dev] + 16 - 1); - return -EBUSY; - } - if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, - 0, "ICS2115", acard)) { - snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]); - return -EBUSY; - } - - acard->wavefront.irq = ics2115_irq[dev]; - acard->wavefront.base = ics2115_port[dev]; - - wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard); - if (wavefront_synth == NULL) { - snd_printk (KERN_ERR "can't create WaveFront synth device\n"); - return -ENOMEM; - } - - strcpy (wavefront_synth->name, "ICS2115 Wavetable MIDI Synthesizer"); - wavefront_synth->iface = SNDRV_HWDEP_IFACE_ICS2115; - hw_dev++; - - /* --------- Mixer ------------ */ - - err = snd_wss_mixer(chip); - if (err < 0) { - snd_printk (KERN_ERR "can't allocate mixer device\n"); - return err; - } - - /* -------- CS4232 MPU-401 interface -------- */ - - if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { - err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232, - cs4232_mpu_port[dev], 0, - cs4232_mpu_irq[dev], NULL); - if (err < 0) { - snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n"); - return err; - } - midi_dev++; - } - - /* ------ ICS2115 internal MIDI ------------ */ - - if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) { - ics2115_internal_rmidi = - snd_wavefront_new_midi (card, - midi_dev, - acard, - ics2115_port[dev], - internal_mpu); - if (ics2115_internal_rmidi == NULL) { - snd_printk (KERN_ERR "can't setup ICS2115 internal MIDI device\n"); - return -ENOMEM; - } - midi_dev++; - } - - /* ------ ICS2115 external MIDI ------------ */ - - if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) { - ics2115_external_rmidi = - snd_wavefront_new_midi (card, - midi_dev, - acard, - ics2115_port[dev], - external_mpu); - if (ics2115_external_rmidi == NULL) { - snd_printk (KERN_ERR "can't setup ICS2115 external MIDI device\n"); - return -ENOMEM; - } - midi_dev++; - } - - /* FX processor for Tropez+ */ - - if (acard->wavefront.has_fx) { - fx_processor = snd_wavefront_new_fx (card, - hw_dev, - acard, - ics2115_port[dev]); - if (fx_processor == NULL) { - snd_printk (KERN_ERR "can't setup FX device\n"); - return -ENOMEM; - } - - hw_dev++; - - strcpy(card->driver, "Tropez+"); - strcpy(card->shortname, "Turtle Beach Tropez+"); - } else { - /* Need a way to distinguish between Maui and Tropez */ - strcpy(card->driver, "WaveFront"); - strcpy(card->shortname, "Turtle Beach WaveFront"); - } - - /* ----- Register the card --------- */ - - /* Not safe to include "Turtle Beach" in longname, due to - length restrictions - */ - - sprintf(card->longname, "%s PCM 0x%lx irq %d dma %d", - card->driver, - chip->port, - cs4232_pcm_irq[dev], - dma1[dev]); - - if (dma2[dev] >= 0 && dma2[dev] < 8) - sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); - - if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { - sprintf (card->longname + strlen (card->longname), - " MPU-401 0x%lx irq %d", - cs4232_mpu_port[dev], - cs4232_mpu_irq[dev]); - } - - sprintf (card->longname + strlen (card->longname), - " SYNTH 0x%lx irq %d", - ics2115_port[dev], - ics2115_irq[dev]); - - return snd_card_register(card); -} - -static int __devinit snd_wavefront_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev]) - return 0; -#ifdef CONFIG_PNP - if (isapnp[dev]) - return 0; -#endif - if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify CS4232 port\n"); - return 0; - } - if (ics2115_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify ICS2115 port\n"); - return 0; - } - return 1; -} - -static int __devinit snd_wavefront_isa_probe(struct device *pdev, - unsigned int dev) -{ - struct snd_card *card; - int err; - - err = snd_wavefront_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, pdev); - if ((err = snd_wavefront_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - - dev_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_wavefront_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#define DEV_NAME "wavefront" - -static struct isa_driver snd_wavefront_driver = { - .match = snd_wavefront_isa_match, - .probe = snd_wavefront_isa_probe, - .remove = __devexit_p(snd_wavefront_isa_remove), - /* FIXME: suspend, resume */ - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_wavefront_card_new(dev, &card); - if (res < 0) - return res; - - if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) { - if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk (KERN_ERR "isapnp detection failed\n"); - snd_card_free (card); - return -ENODEV; - } - } - snd_card_set_dev(card, &pcard->card->dev); - - if ((res = snd_wavefront_probe(card, dev)) < 0) - return res; - - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_wavefront_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static struct pnp_card_driver wavefront_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "wavefront", - .id_table = snd_wavefront_pnpids, - .probe = snd_wavefront_pnp_detect, - .remove = __devexit_p(snd_wavefront_pnp_remove), - /* FIXME: suspend,resume */ -}; - -#endif /* CONFIG_PNP */ - -static int __init alsa_card_wavefront_init(void) -{ - int err; - - err = isa_register_driver(&snd_wavefront_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&wavefront_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_wavefront_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&wavefront_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_wavefront_driver); -} - -module_init(alsa_card_wavefront_init) -module_exit(alsa_card_wavefront_exit) diff --git a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_fx.c b/ANDROID_3.4.5/sound/isa/wavefront/wavefront_fx.c deleted file mode 100644 index e51e0906..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_fx.c +++ /dev/null @@ -1,285 +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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Control bits for the Load Control Register - */ - -#define FX_LSB_TRANSFER 0x01 /* transfer after DSP LSB byte written */ -#define FX_MSB_TRANSFER 0x02 /* transfer after DSP MSB byte written */ -#define FX_AUTO_INCR 0x04 /* auto-increment DSP address after transfer */ - -#define WAIT_IDLE 0xff - -static int -wavefront_fx_idle (snd_wavefront_t *dev) - -{ - int i; - unsigned int x = 0x80; - - for (i = 0; i < 1000; i++) { - x = inb (dev->fx_status); - if ((x & 0x80) == 0) { - break; - } - } - - if (x & 0x80) { - snd_printk ("FX device never idle.\n"); - return 0; - } - - return (1); -} - -static void -wavefront_fx_mute (snd_wavefront_t *dev, int onoff) - -{ - if (!wavefront_fx_idle(dev)) { - return; - } - - outb (onoff ? 0x02 : 0x00, dev->fx_op); -} - -static int -wavefront_fx_memset (snd_wavefront_t *dev, - int page, - int addr, - int cnt, - unsigned short *data) -{ - if (page < 0 || page > 7) { - snd_printk ("FX memset: " - "page must be >= 0 and <= 7\n"); - return -(EINVAL); - } - - if (addr < 0 || addr > 0x7f) { - snd_printk ("FX memset: " - "addr must be >= 0 and <= 7f\n"); - return -(EINVAL); - } - - if (cnt == 1) { - - outb (FX_LSB_TRANSFER, dev->fx_lcr); - outb (page, dev->fx_dsp_page); - outb (addr, dev->fx_dsp_addr); - outb ((data[0] >> 8), dev->fx_dsp_msb); - outb ((data[0] & 0xff), dev->fx_dsp_lsb); - - snd_printk ("FX: addr %d:%x set to 0x%x\n", - page, addr, data[0]); - - } else { - int i; - - outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr); - outb (page, dev->fx_dsp_page); - outb (addr, dev->fx_dsp_addr); - - for (i = 0; i < cnt; i++) { - outb ((data[i] >> 8), dev->fx_dsp_msb); - outb ((data[i] & 0xff), dev->fx_dsp_lsb); - if (!wavefront_fx_idle (dev)) { - break; - } - } - - if (i != cnt) { - snd_printk ("FX memset " - "(0x%x, 0x%x, 0x%lx, %d) incomplete\n", - page, addr, (unsigned long) data, cnt); - return -(EIO); - } - } - - return 0; -} - -int -snd_wavefront_fx_detect (snd_wavefront_t *dev) - -{ - /* This is a crude check, but its the best one I have for now. - Certainly on the Maui and the Tropez, wavefront_fx_idle() will - report "never idle", which suggests that this test should - work OK. - */ - - if (inb (dev->fx_status) & 0x80) { - snd_printk ("Hmm, probably a Maui or Tropez.\n"); - return -1; - } - - return 0; -} - -int -snd_wavefront_fx_open (struct snd_hwdep *hw, struct file *file) - -{ - if (!try_module_get(hw->card->module)) - return -EFAULT; - file->private_data = hw; - return 0; -} - -int -snd_wavefront_fx_release (struct snd_hwdep *hw, struct file *file) - -{ - module_put(hw->card->module); - return 0; -} - -int -snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file, - unsigned int cmd, unsigned long arg) - -{ - struct snd_card *card; - snd_wavefront_card_t *acard; - snd_wavefront_t *dev; - wavefront_fx_info r; - unsigned short *page_data = NULL; - unsigned short *pd; - int err = 0; - - card = sdev->card; - if (snd_BUG_ON(!card)) - return -ENODEV; - if (snd_BUG_ON(!card->private_data)) - return -ENODEV; - - acard = card->private_data; - dev = &acard->wavefront; - - if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info))) - return -EFAULT; - - switch (r.request) { - case WFFX_MUTE: - wavefront_fx_mute (dev, r.data[0]); - return -EIO; - - case WFFX_MEMSET: - if (r.data[2] <= 0) { - snd_printk ("cannot write " - "<= 0 bytes to FX\n"); - return -EIO; - } else if (r.data[2] == 1) { - pd = (unsigned short *) &r.data[3]; - } else { - if (r.data[2] > 256) { - snd_printk ("cannot write " - "> 512 bytes to FX\n"); - return -EIO; - } - 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; - } - - err = wavefront_fx_memset (dev, - r.data[0], /* page */ - r.data[1], /* addr */ - r.data[2], /* cnt */ - pd); - kfree(page_data); - break; - - default: - snd_printk ("FX: ioctl %d not yet supported\n", - r.request); - return -ENOTTY; - } - return err; -} - -/* YSS225 initialization. - - This code was developed using DOSEMU. The Turtle Beach SETUPSND - utility was run with I/O tracing in DOSEMU enabled, and a reconstruction - of the port I/O done, using the Yamaha faxback document as a guide - to add more logic to the code. Its really pretty weird. - - This is the approach of just dumping the whole I/O - sequence as a series of port/value pairs and a simple loop - that outputs it. -*/ - -int __devinit -snd_wavefront_fx_start (snd_wavefront_t *dev) -{ - unsigned int i; - int err; - const struct firmware *firmware = NULL; - - if (dev->fx_initialized) - return 0; - - err = request_firmware(&firmware, "yamaha/yss225_registers.bin", - dev->card->dev); - if (err < 0) { - err = -1; - goto out; - } - - for (i = 0; i + 1 < firmware->size; i += 2) { - if (firmware->data[i] >= 8 && firmware->data[i] < 16) { - outb(firmware->data[i + 1], - dev->base + firmware->data[i]); - } else if (firmware->data[i] == WAIT_IDLE) { - if (!wavefront_fx_idle(dev)) { - err = -1; - goto out; - } - } else { - snd_printk(KERN_ERR "invalid address" - " in register data\n"); - err = -1; - goto out; - } - } - - dev->fx_initialized = 1; - err = 0; - -out: - release_firmware(firmware); - return err; -} - -MODULE_FIRMWARE("yamaha/yss225_registers.bin"); diff --git a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_midi.c b/ANDROID_3.4.5/sound/isa/wavefront/wavefront_midi.c deleted file mode 100644 index 65329f3a..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_midi.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright (C) by Paul Barton-Davis 1998-1999 - * - * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this - * software for more info. - */ - -/* The low level driver for the WaveFront ICS2115 MIDI interface(s) - * - * Note that there is also an MPU-401 emulation (actually, a UART-401 - * emulation) on the CS4232 on the Tropez and Tropez Plus. This code - * has nothing to do with that interface at all. - * - * The interface is essentially just a UART-401, but is has the - * interesting property of supporting what Turtle Beach called - * "Virtual MIDI" mode. In this mode, there are effectively *two* - * MIDI buses accessible via the interface, one that is routed - * solely to/from the external WaveFront synthesizer and the other - * corresponding to the pin/socket connector used to link external - * MIDI devices to the board. - * - * This driver fully supports this mode, allowing two distinct MIDI - * busses to be used completely independently, giving 32 channels of - * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI - * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1, - * where `n' is the card number. Note that the device numbers may be - * something other than 0 and 1 if the CS4232 UART/MPU-401 interface - * is enabled. - * - * Switching between the two is accomplished externally by the driver - * using the two otherwise unused MIDI bytes. See the code for more details. - * - * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c) - * - * The main reason to turn off Virtual MIDI mode is when you want to - * tightly couple the WaveFront synth with an external MIDI - * device. You won't be able to distinguish the source of any MIDI - * data except via SysEx ID, but thats probably OK, since for the most - * part, the WaveFront won't be sending any MIDI data at all. - * - * The main reason to turn on Virtual MIDI Mode is to provide two - * completely independent 16-channel MIDI buses, one to the - * WaveFront and one to any external MIDI devices. Given the 32 - * voice nature of the WaveFront, its pretty easy to find a use - * for all 16 channels driving just that synth. - * - */ - -#include -#include -#include -#include -#include -#include - -static inline int -wf_mpu_status (snd_wavefront_midi_t *midi) - -{ - return inb (midi->mpu_status_port); -} - -static inline int -input_avail (snd_wavefront_midi_t *midi) - -{ - return !(wf_mpu_status(midi) & INPUT_AVAIL); -} - -static inline int -output_ready (snd_wavefront_midi_t *midi) - -{ - return !(wf_mpu_status(midi) & OUTPUT_READY); -} - -static inline int -read_data (snd_wavefront_midi_t *midi) - -{ - return inb (midi->mpu_data_port); -} - -static inline void -write_data (snd_wavefront_midi_t *midi, unsigned char byte) - -{ - outb (byte, midi->mpu_data_port); -} - -static snd_wavefront_midi_t * -get_wavefront_midi (struct snd_rawmidi_substream *substream) - -{ - struct snd_card *card; - snd_wavefront_card_t *acard; - - if (substream == NULL || substream->rmidi == NULL) - return NULL; - - card = substream->rmidi->card; - - if (card == NULL) - return NULL; - - if (card->private_data == NULL) - return NULL; - - acard = card->private_data; - - return &acard->wavefront.midi; -} - -static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) -{ - snd_wavefront_midi_t *midi = &card->wavefront.midi; - snd_wavefront_mpu_id mpu; - unsigned long flags; - unsigned char midi_byte; - int max = 256, mask = 1; - int timeout; - - /* Its not OK to try to change the status of "virtuality" of - the MIDI interface while we're outputting stuff. See - snd_wavefront_midi_{enable,disable}_virtual () for the - other half of this. - - The first loop attempts to flush any data from the - current output device, and then the second - emits the switch byte (if necessary), and starts - outputting data for the output device currently in use. - */ - - if (midi->substream_output[midi->output_mpu] == NULL) { - goto __second; - } - - while (max > 0) { - - /* XXX fix me - no hard timing loops allowed! */ - - for (timeout = 30000; timeout > 0; timeout--) { - if (output_ready (midi)) - break; - } - - spin_lock_irqsave (&midi->virtual, flags); - if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) { - spin_unlock_irqrestore (&midi->virtual, flags); - goto __second; - } - if (output_ready (midi)) { - if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) { - if (!midi->isvirtual || - (midi_byte != WF_INTERNAL_SWITCH && - midi_byte != WF_EXTERNAL_SWITCH)) - write_data(midi, midi_byte); - max--; - } else { - if (midi->istimer) { - if (--midi->istimer <= 0) - del_timer(&midi->timer); - } - midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; - spin_unlock_irqrestore (&midi->virtual, flags); - goto __second; - } - } else { - spin_unlock_irqrestore (&midi->virtual, flags); - return; - } - spin_unlock_irqrestore (&midi->virtual, flags); - } - - __second: - - if (midi->substream_output[!midi->output_mpu] == NULL) { - return; - } - - while (max > 0) { - - /* XXX fix me - no hard timing loops allowed! */ - - for (timeout = 30000; timeout > 0; timeout--) { - if (output_ready (midi)) - break; - } - - spin_lock_irqsave (&midi->virtual, flags); - if (!midi->isvirtual) - mask = 0; - mpu = midi->output_mpu ^ mask; - mask = 0; /* don't invert the value from now */ - if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) { - spin_unlock_irqrestore (&midi->virtual, flags); - return; - } - if (snd_rawmidi_transmit_empty(midi->substream_output[mpu])) - goto __timer; - if (output_ready (midi)) { - if (mpu != midi->output_mpu) { - write_data(midi, mpu == internal_mpu ? - WF_INTERNAL_SWITCH : - WF_EXTERNAL_SWITCH); - midi->output_mpu = mpu; - } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) { - if (!midi->isvirtual || - (midi_byte != WF_INTERNAL_SWITCH && - midi_byte != WF_EXTERNAL_SWITCH)) - write_data(midi, midi_byte); - max--; - } else { - __timer: - if (midi->istimer) { - if (--midi->istimer <= 0) - del_timer(&midi->timer); - } - midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; - spin_unlock_irqrestore (&midi->virtual, flags); - return; - } - } else { - spin_unlock_irqrestore (&midi->virtual, flags); - return; - } - spin_unlock_irqrestore (&midi->virtual, flags); - } -} - -static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (snd_BUG_ON(!substream || !substream->rmidi)) - return -ENXIO; - if (snd_BUG_ON(!substream->rmidi->private_data)) - return -ENXIO; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) - return -EIO; - - spin_lock_irqsave (&midi->open, flags); - midi->mode[mpu] |= MPU401_MODE_INPUT; - midi->substream_input[mpu] = substream; - spin_unlock_irqrestore (&midi->open, flags); - - return 0; -} - -static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (snd_BUG_ON(!substream || !substream->rmidi)) - return -ENXIO; - if (snd_BUG_ON(!substream->rmidi->private_data)) - return -ENXIO; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) - return -EIO; - - spin_lock_irqsave (&midi->open, flags); - midi->mode[mpu] |= MPU401_MODE_OUTPUT; - midi->substream_output[mpu] = substream; - spin_unlock_irqrestore (&midi->open, flags); - - return 0; -} - -static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (snd_BUG_ON(!substream || !substream->rmidi)) - return -ENXIO; - if (snd_BUG_ON(!substream->rmidi->private_data)) - return -ENXIO; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) - return -EIO; - - spin_lock_irqsave (&midi->open, flags); - midi->mode[mpu] &= ~MPU401_MODE_INPUT; - spin_unlock_irqrestore (&midi->open, flags); - - return 0; -} - -static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (snd_BUG_ON(!substream || !substream->rmidi)) - return -ENXIO; - if (snd_BUG_ON(!substream->rmidi->private_data)) - return -ENXIO; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) - return -EIO; - - spin_lock_irqsave (&midi->open, flags); - midi->mode[mpu] &= ~MPU401_MODE_OUTPUT; - spin_unlock_irqrestore (&midi->open, flags); - return 0; -} - -static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (substream == NULL || substream->rmidi == NULL) - return; - - if (substream->rmidi->private_data == NULL) - return; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) { - return; - } - - spin_lock_irqsave (&midi->virtual, flags); - if (up) { - midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER; - } else { - midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER; - } - spin_unlock_irqrestore (&midi->virtual, flags); -} - -static void snd_wavefront_midi_output_timer(unsigned long data) -{ - snd_wavefront_card_t *card = (snd_wavefront_card_t *)data; - snd_wavefront_midi_t *midi = &card->wavefront.midi; - unsigned long flags; - - spin_lock_irqsave (&midi->virtual, flags); - midi->timer.expires = 1 + jiffies; - add_timer(&midi->timer); - spin_unlock_irqrestore (&midi->virtual, flags); - snd_wavefront_midi_output_write(card); -} - -static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (substream == NULL || substream->rmidi == NULL) - return; - - if (substream->rmidi->private_data == NULL) - return; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) { - return; - } - - spin_lock_irqsave (&midi->virtual, flags); - if (up) { - if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { - if (!midi->istimer) { - init_timer(&midi->timer); - midi->timer.function = snd_wavefront_midi_output_timer; - midi->timer.data = (unsigned long) substream->rmidi->card->private_data; - midi->timer.expires = 1 + jiffies; - add_timer(&midi->timer); - } - midi->istimer++; - midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; - } - } else { - midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; - } - spin_unlock_irqrestore (&midi->virtual, flags); - - if (up) - snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data); -} - -void -snd_wavefront_midi_interrupt (snd_wavefront_card_t *card) - -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - static struct snd_rawmidi_substream *substream = NULL; - static int mpu = external_mpu; - int max = 128; - unsigned char byte; - - midi = &card->wavefront.midi; - - if (!input_avail (midi)) { /* not for us */ - snd_wavefront_midi_output_write(card); - return; - } - - spin_lock_irqsave (&midi->virtual, flags); - while (--max) { - - if (input_avail (midi)) { - byte = read_data (midi); - - if (midi->isvirtual) { - if (byte == WF_EXTERNAL_SWITCH) { - substream = midi->substream_input[external_mpu]; - mpu = external_mpu; - } else if (byte == WF_INTERNAL_SWITCH) { - substream = midi->substream_output[internal_mpu]; - mpu = internal_mpu; - } /* else just leave it as it is */ - } else { - substream = midi->substream_input[internal_mpu]; - mpu = internal_mpu; - } - - if (substream == NULL) { - continue; - } - - if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) { - snd_rawmidi_receive(substream, &byte, 1); - } - } else { - break; - } - } - spin_unlock_irqrestore (&midi->virtual, flags); - - snd_wavefront_midi_output_write(card); -} - -void -snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card) - -{ - unsigned long flags; - - spin_lock_irqsave (&card->wavefront.midi.virtual, flags); - card->wavefront.midi.isvirtual = 1; - card->wavefront.midi.output_mpu = internal_mpu; - card->wavefront.midi.input_mpu = internal_mpu; - spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); -} - -void -snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card) - -{ - unsigned long flags; - - spin_lock_irqsave (&card->wavefront.midi.virtual, flags); - // snd_wavefront_midi_input_close (card->ics2115_external_rmidi); - // snd_wavefront_midi_output_close (card->ics2115_external_rmidi); - card->wavefront.midi.isvirtual = 0; - spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); -} - -int __devinit -snd_wavefront_midi_start (snd_wavefront_card_t *card) - -{ - int ok, i; - unsigned char rbuf[4], wbuf[4]; - snd_wavefront_t *dev; - snd_wavefront_midi_t *midi; - - dev = &card->wavefront; - midi = &dev->midi; - - /* The ICS2115 MPU-401 interface doesn't do anything - until its set into UART mode. - */ - - /* XXX fix me - no hard timing loops allowed! */ - - for (i = 0; i < 30000 && !output_ready (midi); i++); - - if (!output_ready (midi)) { - snd_printk ("MIDI interface not ready for command\n"); - return -1; - } - - /* Any interrupts received from now on - are owned by the MIDI side of things. - */ - - dev->interrupts_are_midi = 1; - - outb (UART_MODE_ON, midi->mpu_command_port); - - for (ok = 0, i = 50000; i > 0 && !ok; i--) { - if (input_avail (midi)) { - if (read_data (midi) == MPU_ACK) { - ok = 1; - break; - } - } - } - - if (!ok) { - snd_printk ("cannot set UART mode for MIDI interface"); - dev->interrupts_are_midi = 0; - return -1; - } - - /* Route external MIDI to WaveFront synth (by default) */ - - if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) { - snd_printk ("can't enable MIDI-IN-2-synth routing.\n"); - /* XXX error ? */ - } - - /* Turn on Virtual MIDI, but first *always* turn it off, - since otherwise consecutive reloads of the driver will - never cause the hardware to generate the initial "internal" or - "external" source bytes in the MIDI data stream. This - is pretty important, since the internal hardware generally will - be used to generate none or very little MIDI output, and - thus the only source of MIDI data is actually external. Without - the switch bytes, the driver will think it all comes from - the internal interface. Duh. - */ - - if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { - snd_printk ("virtual MIDI mode not disabled\n"); - return 0; /* We're OK, but missing the external MIDI dev */ - } - - snd_wavefront_midi_enable_virtual (card); - - if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) { - snd_printk ("cannot enable virtual MIDI mode.\n"); - snd_wavefront_midi_disable_virtual (card); - } - return 0; -} - -struct snd_rawmidi_ops snd_wavefront_midi_output = -{ - .open = snd_wavefront_midi_output_open, - .close = snd_wavefront_midi_output_close, - .trigger = snd_wavefront_midi_output_trigger, -}; - -struct snd_rawmidi_ops snd_wavefront_midi_input = -{ - .open = snd_wavefront_midi_input_open, - .close = snd_wavefront_midi_input_close, - .trigger = snd_wavefront_midi_input_trigger, -}; - diff --git a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_synth.c b/ANDROID_3.4.5/sound/isa/wavefront/wavefront_synth.c deleted file mode 100644 index 405f8b6a..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_synth.c +++ /dev/null @@ -1,2199 +0,0 @@ -/* Copyright (C) by Paul Barton-Davis 1998-1999 - * - * Some portions of this file are taken from work that is - * copyright (C) by Hannu Savolainen 1993-1996 - * - * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - -/* - * An ALSA lowlevel driver for Turtle Beach ICS2115 wavetable synth - * (Maui, Tropez, Tropez Plus) - * - * This driver supports the onboard wavetable synthesizer (an ICS2115), - * including patch, sample and program loading and unloading, conversion - * of GUS patches during loading, and full user-level access to all - * WaveFront commands. It tries to provide semi-intelligent patch and - * sample management as well. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int wf_raw = 0; /* we normally check for "raw state" to firmware - loading. if non-zero, then during driver loading, the - state of the board is ignored, and we reset the - board and load the firmware anyway. - */ - -static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in - whatever state it is when the driver is loaded. - The default is to download the microprogram and - associated coefficients to set it up for "default" - operation, whatever that means. - */ - -static int debug_default = 0; /* you can set this to control debugging - during driver loading. it takes any combination - of the WF_DEBUG_* flags defined in - wavefront.h - */ - -/* XXX this needs to be made firmware and hardware version dependent */ - -#define DEFAULT_OSPATH "wavefront.os" -static char *ospath = DEFAULT_OSPATH; /* the firmware file name */ - -static int wait_usecs = 150; /* This magic number seems to give pretty optimal - throughput based on my limited experimentation. - If you want to play around with it and find a better - value, be my guest. Remember, the idea is to - get a number that causes us to just busy wait - for as many WaveFront commands as possible, without - coming up with a number so large that we hog the - whole CPU. - - Specifically, with this number, out of about 134,000 - status waits, only about 250 result in a sleep. - */ - -static int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */ -static int sleep_tries = 50; /* number of times we'll try to sleep */ - -static int reset_time = 2; /* hundreths of a second we wait after a HW - reset for the expected interrupt. - */ - -static int ramcheck_time = 20; /* time in seconds to wait while ROM code - checks on-board RAM. - */ - -static int osrun_time = 10; /* time in seconds we wait for the OS to - start running. - */ -module_param(wf_raw, int, 0444); -MODULE_PARM_DESC(wf_raw, "if non-zero, assume that we need to boot the OS"); -module_param(fx_raw, int, 0444); -MODULE_PARM_DESC(fx_raw, "if non-zero, assume that the FX process needs help"); -module_param(debug_default, int, 0444); -MODULE_PARM_DESC(debug_default, "debug parameters for card initialization"); -module_param(wait_usecs, int, 0444); -MODULE_PARM_DESC(wait_usecs, "how long to wait without sleeping, usecs"); -module_param(sleep_interval, int, 0444); -MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply"); -module_param(sleep_tries, int, 0444); -MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait"); -module_param(ospath, charp, 0444); -MODULE_PARM_DESC(ospath, "pathname to processed ICS2115 OS firmware"); -module_param(reset_time, int, 0444); -MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect"); -module_param(ramcheck_time, int, 0444); -MODULE_PARM_DESC(ramcheck_time, "how many seconds to wait for the RAM test"); -module_param(osrun_time, int, 0444); -MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS"); - -/* if WF_DEBUG not defined, no run-time debugging messages will - be available via the debug flag setting. Given the current - beta state of the driver, this will remain set until a future - version. -*/ - -#define WF_DEBUG 1 - -#ifdef WF_DEBUG - -#define DPRINT(cond, ...) \ - if ((dev->debug & (cond)) == (cond)) { \ - snd_printk (__VA_ARGS__); \ - } -#else -#define DPRINT(cond, args...) -#endif /* WF_DEBUG */ - -#define LOGNAME "WaveFront: " - -/* bitmasks for WaveFront status port value */ - -#define STAT_RINTR_ENABLED 0x01 -#define STAT_CAN_READ 0x02 -#define STAT_INTR_READ 0x04 -#define STAT_WINTR_ENABLED 0x10 -#define STAT_CAN_WRITE 0x20 -#define STAT_INTR_WRITE 0x40 - -static int wavefront_delete_sample (snd_wavefront_t *, int sampnum); -static int wavefront_find_free_sample (snd_wavefront_t *); - -struct wavefront_command { - int cmd; - char *action; - unsigned int read_cnt; - unsigned int write_cnt; - int need_ack; -}; - -static struct { - int errno; - const char *errstr; -} wavefront_errors[] = { - { 0x01, "Bad sample number" }, - { 0x02, "Out of sample memory" }, - { 0x03, "Bad patch number" }, - { 0x04, "Error in number of voices" }, - { 0x06, "Sample load already in progress" }, - { 0x0B, "No sample load request pending" }, - { 0x0E, "Bad MIDI channel number" }, - { 0x10, "Download Record Error" }, - { 0x80, "Success" }, - { 0x0 } -}; - -#define NEEDS_ACK 1 - -static struct wavefront_command wavefront_commands[] = { - { WFC_SET_SYNTHVOL, "set synthesizer volume", 0, 1, NEEDS_ACK }, - { WFC_GET_SYNTHVOL, "get synthesizer volume", 1, 0, 0}, - { WFC_SET_NVOICES, "set number of voices", 0, 1, NEEDS_ACK }, - { WFC_GET_NVOICES, "get number of voices", 1, 0, 0 }, - { WFC_SET_TUNING, "set synthesizer tuning", 0, 2, NEEDS_ACK }, - { WFC_GET_TUNING, "get synthesizer tuning", 2, 0, 0 }, - { WFC_DISABLE_CHANNEL, "disable synth channel", 0, 1, NEEDS_ACK }, - { WFC_ENABLE_CHANNEL, "enable synth channel", 0, 1, NEEDS_ACK }, - { WFC_GET_CHANNEL_STATUS, "get synth channel status", 3, 0, 0 }, - { WFC_MISYNTH_OFF, "disable midi-in to synth", 0, 0, NEEDS_ACK }, - { WFC_MISYNTH_ON, "enable midi-in to synth", 0, 0, NEEDS_ACK }, - { WFC_VMIDI_ON, "enable virtual midi mode", 0, 0, NEEDS_ACK }, - { WFC_VMIDI_OFF, "disable virtual midi mode", 0, 0, NEEDS_ACK }, - { WFC_MIDI_STATUS, "report midi status", 1, 0, 0 }, - { WFC_FIRMWARE_VERSION, "report firmware version", 2, 0, 0 }, - { WFC_HARDWARE_VERSION, "report hardware version", 2, 0, 0 }, - { WFC_GET_NSAMPLES, "report number of samples", 2, 0, 0 }, - { WFC_INSTOUT_LEVELS, "report instantaneous output levels", 7, 0, 0 }, - { WFC_PEAKOUT_LEVELS, "report peak output levels", 7, 0, 0 }, - { WFC_DOWNLOAD_SAMPLE, "download sample", - 0, WF_SAMPLE_BYTES, NEEDS_ACK }, - { WFC_DOWNLOAD_BLOCK, "download block", 0, 0, NEEDS_ACK}, - { WFC_DOWNLOAD_SAMPLE_HEADER, "download sample header", - 0, WF_SAMPLE_HDR_BYTES, NEEDS_ACK }, - { WFC_UPLOAD_SAMPLE_HEADER, "upload sample header", 13, 2, 0 }, - - /* This command requires a variable number of bytes to be written. - There is a hack in snd_wavefront_cmd() to support this. The actual - count is passed in as the read buffer ptr, cast appropriately. - Ugh. - */ - - { WFC_DOWNLOAD_MULTISAMPLE, "download multisample", 0, 0, NEEDS_ACK }, - - /* This one is a hack as well. We just read the first byte of the - response, don't fetch an ACK, and leave the rest to the - calling function. Ugly, ugly, ugly. - */ - - { WFC_UPLOAD_MULTISAMPLE, "upload multisample", 2, 1, 0 }, - { WFC_DOWNLOAD_SAMPLE_ALIAS, "download sample alias", - 0, WF_ALIAS_BYTES, NEEDS_ACK }, - { WFC_UPLOAD_SAMPLE_ALIAS, "upload sample alias", WF_ALIAS_BYTES, 2, 0}, - { WFC_DELETE_SAMPLE, "delete sample", 0, 2, NEEDS_ACK }, - { WFC_IDENTIFY_SAMPLE_TYPE, "identify sample type", 5, 2, 0 }, - { WFC_UPLOAD_SAMPLE_PARAMS, "upload sample parameters" }, - { WFC_REPORT_FREE_MEMORY, "report free memory", 4, 0, 0 }, - { WFC_DOWNLOAD_PATCH, "download patch", 0, 134, NEEDS_ACK }, - { WFC_UPLOAD_PATCH, "upload patch", 132, 2, 0 }, - { WFC_DOWNLOAD_PROGRAM, "download program", 0, 33, NEEDS_ACK }, - { WFC_UPLOAD_PROGRAM, "upload program", 32, 1, 0 }, - { WFC_DOWNLOAD_EDRUM_PROGRAM, "download enhanced drum program", 0, 9, - NEEDS_ACK}, - { WFC_UPLOAD_EDRUM_PROGRAM, "upload enhanced drum program", 8, 1, 0}, - { WFC_SET_EDRUM_CHANNEL, "set enhanced drum program channel", - 0, 1, NEEDS_ACK }, - { WFC_DISABLE_DRUM_PROGRAM, "disable drum program", 0, 1, NEEDS_ACK }, - { WFC_REPORT_CHANNEL_PROGRAMS, "report channel program numbers", - 32, 0, 0 }, - { WFC_NOOP, "the no-op command", 0, 0, NEEDS_ACK }, - { 0x00 } -}; - -static const char * -wavefront_errorstr (int errnum) - -{ - int i; - - for (i = 0; wavefront_errors[i].errstr; i++) { - if (wavefront_errors[i].errno == errnum) { - return wavefront_errors[i].errstr; - } - } - - return "Unknown WaveFront error"; -} - -static struct wavefront_command * -wavefront_get_command (int cmd) - -{ - int i; - - for (i = 0; wavefront_commands[i].cmd != 0; i++) { - if (cmd == wavefront_commands[i].cmd) { - return &wavefront_commands[i]; - } - } - - return NULL; -} - -static inline int -wavefront_status (snd_wavefront_t *dev) - -{ - return inb (dev->status_port); -} - -static int -wavefront_sleep (int limit) - -{ - schedule_timeout_interruptible(limit); - - return signal_pending(current); -} - -static int -wavefront_wait (snd_wavefront_t *dev, int mask) - -{ - int i; - - /* Spin for a short period of time, because >99% of all - requests to the WaveFront can be serviced inline like this. - */ - - for (i = 0; i < wait_usecs; i += 5) { - if (wavefront_status (dev) & mask) { - return 1; - } - udelay(5); - } - - for (i = 0; i < sleep_tries; i++) { - - if (wavefront_status (dev) & mask) { - return 1; - } - - if (wavefront_sleep (HZ/sleep_interval)) { - return (0); - } - } - - return (0); -} - -static int -wavefront_read (snd_wavefront_t *dev) - -{ - if (wavefront_wait (dev, STAT_CAN_READ)) - return inb (dev->data_port); - - DPRINT (WF_DEBUG_DATA, "read timeout.\n"); - - return -1; -} - -static int -wavefront_write (snd_wavefront_t *dev, unsigned char data) - -{ - if (wavefront_wait (dev, STAT_CAN_WRITE)) { - outb (data, dev->data_port); - return 0; - } - - DPRINT (WF_DEBUG_DATA, "write timeout.\n"); - - return -1; -} - -int -snd_wavefront_cmd (snd_wavefront_t *dev, - int cmd, unsigned char *rbuf, unsigned char *wbuf) - -{ - int ack; - unsigned int i; - int c; - struct wavefront_command *wfcmd; - - if ((wfcmd = wavefront_get_command (cmd)) == NULL) { - snd_printk ("command 0x%x not supported.\n", - cmd); - return 1; - } - - /* Hack to handle the one variable-size write command. See - wavefront_send_multisample() for the other half of this - gross and ugly strategy. - */ - - if (cmd == WFC_DOWNLOAD_MULTISAMPLE) { - wfcmd->write_cnt = (unsigned long) rbuf; - rbuf = NULL; - } - - DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n", - cmd, wfcmd->action, wfcmd->read_cnt, - wfcmd->write_cnt, wfcmd->need_ack); - - if (wavefront_write (dev, cmd)) { - DPRINT ((WF_DEBUG_IO|WF_DEBUG_CMD), "cannot request " - "0x%x [%s].\n", - cmd, wfcmd->action); - return 1; - } - - if (wfcmd->write_cnt > 0) { - DPRINT (WF_DEBUG_DATA, "writing %d bytes " - "for 0x%x\n", - wfcmd->write_cnt, cmd); - - for (i = 0; i < wfcmd->write_cnt; i++) { - if (wavefront_write (dev, wbuf[i])) { - DPRINT (WF_DEBUG_IO, "bad write for byte " - "%d of 0x%x [%s].\n", - i, cmd, wfcmd->action); - return 1; - } - - DPRINT (WF_DEBUG_DATA, "write[%d] = 0x%x\n", - i, wbuf[i]); - } - } - - if (wfcmd->read_cnt > 0) { - DPRINT (WF_DEBUG_DATA, "reading %d ints " - "for 0x%x\n", - wfcmd->read_cnt, cmd); - - for (i = 0; i < wfcmd->read_cnt; i++) { - - if ((c = wavefront_read (dev)) == -1) { - DPRINT (WF_DEBUG_IO, "bad read for byte " - "%d of 0x%x [%s].\n", - i, cmd, wfcmd->action); - return 1; - } - - /* Now handle errors. Lots of special cases here */ - - if (c == 0xff) { - if ((c = wavefront_read (dev)) == -1) { - DPRINT (WF_DEBUG_IO, "bad read for " - "error byte at " - "read byte %d " - "of 0x%x [%s].\n", - i, cmd, - wfcmd->action); - return 1; - } - - /* Can you believe this madness ? */ - - if (c == 1 && - wfcmd->cmd == WFC_IDENTIFY_SAMPLE_TYPE) { - rbuf[0] = WF_ST_EMPTY; - return (0); - - } else if (c == 3 && - wfcmd->cmd == WFC_UPLOAD_PATCH) { - - return 3; - - } else if (c == 1 && - wfcmd->cmd == WFC_UPLOAD_PROGRAM) { - - return 1; - - } else { - - DPRINT (WF_DEBUG_IO, "error %d (%s) " - "during " - "read for byte " - "%d of 0x%x " - "[%s].\n", - c, - wavefront_errorstr (c), - i, cmd, - wfcmd->action); - return 1; - - } - - } else { - rbuf[i] = c; - } - - DPRINT (WF_DEBUG_DATA, "read[%d] = 0x%x\n",i, rbuf[i]); - } - } - - if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) { - - DPRINT (WF_DEBUG_CMD, "reading ACK for 0x%x\n", cmd); - - /* Some commands need an ACK, but return zero instead - of the standard value. - */ - - if ((ack = wavefront_read (dev)) == 0) { - ack = WF_ACK; - } - - if (ack != WF_ACK) { - if (ack == -1) { - DPRINT (WF_DEBUG_IO, "cannot read ack for " - "0x%x [%s].\n", - cmd, wfcmd->action); - return 1; - - } else { - int err = -1; /* something unknown */ - - if (ack == 0xff) { /* explicit error */ - - if ((err = wavefront_read (dev)) == -1) { - DPRINT (WF_DEBUG_DATA, - "cannot read err " - "for 0x%x [%s].\n", - cmd, wfcmd->action); - } - } - - DPRINT (WF_DEBUG_IO, "0x%x [%s] " - "failed (0x%x, 0x%x, %s)\n", - cmd, wfcmd->action, ack, err, - wavefront_errorstr (err)); - - return -err; - } - } - - DPRINT (WF_DEBUG_DATA, "ack received " - "for 0x%x [%s]\n", - cmd, wfcmd->action); - } else { - - DPRINT (WF_DEBUG_CMD, "0x%x [%s] does not need " - "ACK (%d,%d,%d)\n", - cmd, wfcmd->action, wfcmd->read_cnt, - wfcmd->write_cnt, wfcmd->need_ack); - } - - return 0; - -} - -/*********************************************************************** -WaveFront data munging - -Things here are weird. All data written to the board cannot -have its most significant bit set. Any data item with values -potentially > 0x7F (127) must be split across multiple bytes. - -Sometimes, we need to munge numeric values that are represented on -the x86 side as 8-32 bit values. Sometimes, we need to munge data -that is represented on the x86 side as an array of bytes. The most -efficient approach to handling both cases seems to be to use 2 -different functions for munging and 2 for de-munging. This avoids -weird casting and worrying about bit-level offsets. - -**********************************************************************/ - -static unsigned char * -munge_int32 (unsigned int src, - unsigned char *dst, - unsigned int dst_size) -{ - unsigned int i; - - for (i = 0; i < dst_size; i++) { - *dst = src & 0x7F; /* Mask high bit of LSB */ - src = src >> 7; /* Rotate Right 7 bits */ - /* Note: we leave the upper bits in place */ - - dst++; - }; - return dst; -}; - -static int -demunge_int32 (unsigned char* src, int src_size) - -{ - int i; - int outval = 0; - - for (i = src_size - 1; i >= 0; i--) { - outval=(outval<<7)+src[i]; - } - - return outval; -}; - -static -unsigned char * -munge_buf (unsigned char *src, unsigned char *dst, unsigned int dst_size) - -{ - unsigned int i; - unsigned int last = dst_size / 2; - - for (i = 0; i < last; i++) { - *dst++ = src[i] & 0x7f; - *dst++ = src[i] >> 7; - } - return dst; -} - -static -unsigned char * -demunge_buf (unsigned char *src, unsigned char *dst, unsigned int src_bytes) - -{ - int i; - unsigned char *end = src + src_bytes; - - end = src + src_bytes; - - /* NOTE: src and dst *CAN* point to the same address */ - - for (i = 0; src != end; i++) { - dst[i] = *src++; - dst[i] |= (*src++)<<7; - } - - return dst; -} - -/*********************************************************************** -WaveFront: sample, patch and program management. -***********************************************************************/ - -static int -wavefront_delete_sample (snd_wavefront_t *dev, int sample_num) - -{ - unsigned char wbuf[2]; - int x; - - wbuf[0] = sample_num & 0x7f; - wbuf[1] = sample_num >> 7; - - if ((x = snd_wavefront_cmd (dev, WFC_DELETE_SAMPLE, NULL, wbuf)) == 0) { - dev->sample_status[sample_num] = WF_ST_EMPTY; - } - - return x; -} - -static int -wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) - -{ - int i; - unsigned char rbuf[32], wbuf[32]; - unsigned int sc_real, sc_alias, sc_multi; - - /* check sample status */ - - if (snd_wavefront_cmd (dev, WFC_GET_NSAMPLES, rbuf, wbuf)) { - snd_printk ("cannot request sample count.\n"); - return -1; - } - - sc_real = sc_alias = sc_multi = dev->samples_used = 0; - - for (i = 0; i < WF_MAX_SAMPLE; i++) { - - wbuf[0] = i & 0x7f; - wbuf[1] = i >> 7; - - if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { - snd_printk(KERN_WARNING "cannot identify sample " - "type of slot %d\n", i); - dev->sample_status[i] = WF_ST_EMPTY; - continue; - } - - dev->sample_status[i] = (WF_SLOT_FILLED|rbuf[0]); - - if (assume_rom) { - dev->sample_status[i] |= WF_SLOT_ROM; - } - - switch (rbuf[0] & WF_ST_MASK) { - case WF_ST_SAMPLE: - sc_real++; - break; - case WF_ST_MULTISAMPLE: - sc_multi++; - break; - case WF_ST_ALIAS: - sc_alias++; - break; - case WF_ST_EMPTY: - break; - - default: - snd_printk ("unknown sample type for " - "slot %d (0x%x)\n", - i, rbuf[0]); - } - - if (rbuf[0] != WF_ST_EMPTY) { - dev->samples_used++; - } - } - - snd_printk ("%d samples used (%d real, %d aliases, %d multi), " - "%d empty\n", dev->samples_used, sc_real, sc_alias, sc_multi, - WF_MAX_SAMPLE - dev->samples_used); - - - return (0); - -} - -static int -wavefront_get_patch_status (snd_wavefront_t *dev) - -{ - unsigned char patchbuf[WF_PATCH_BYTES]; - unsigned char patchnum[2]; - wavefront_patch *p; - int i, x, cnt, cnt2; - - for (i = 0; i < WF_MAX_PATCH; i++) { - patchnum[0] = i & 0x7f; - patchnum[1] = i >> 7; - - if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PATCH, patchbuf, - patchnum)) == 0) { - - dev->patch_status[i] |= WF_SLOT_FILLED; - p = (wavefront_patch *) patchbuf; - dev->sample_status - [p->sample_number|(p->sample_msb<<7)] |= - WF_SLOT_USED; - - } else if (x == 3) { /* Bad patch number */ - dev->patch_status[i] = 0; - } else { - snd_printk ("upload patch " - "error 0x%x\n", x); - dev->patch_status[i] = 0; - return 1; - } - } - - /* program status has already filled in slot_used bits */ - - for (i = 0, cnt = 0, cnt2 = 0; i < WF_MAX_PATCH; i++) { - if (dev->patch_status[i] & WF_SLOT_FILLED) { - cnt++; - } - if (dev->patch_status[i] & WF_SLOT_USED) { - cnt2++; - } - - } - snd_printk ("%d patch slots filled, %d in use\n", cnt, cnt2); - - return (0); -} - -static int -wavefront_get_program_status (snd_wavefront_t *dev) - -{ - unsigned char progbuf[WF_PROGRAM_BYTES]; - wavefront_program prog; - unsigned char prognum; - int i, x, l, cnt; - - for (i = 0; i < WF_MAX_PROGRAM; i++) { - prognum = i; - - if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PROGRAM, progbuf, - &prognum)) == 0) { - - dev->prog_status[i] |= WF_SLOT_USED; - - demunge_buf (progbuf, (unsigned char *) &prog, - WF_PROGRAM_BYTES); - - for (l = 0; l < WF_NUM_LAYERS; l++) { - if (prog.layer[l].mute) { - dev->patch_status - [prog.layer[l].patch_number] |= - WF_SLOT_USED; - } - } - } else if (x == 1) { /* Bad program number */ - dev->prog_status[i] = 0; - } else { - snd_printk ("upload program " - "error 0x%x\n", x); - dev->prog_status[i] = 0; - } - } - - for (i = 0, cnt = 0; i < WF_MAX_PROGRAM; i++) { - if (dev->prog_status[i]) { - cnt++; - } - } - - snd_printk ("%d programs slots in use\n", cnt); - - return (0); -} - -static int -wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header) - -{ - unsigned char buf[WF_PATCH_BYTES+2]; - unsigned char *bptr; - - DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n", - header->number); - - dev->patch_status[header->number] |= WF_SLOT_FILLED; - - bptr = buf; - bptr = munge_int32 (header->number, buf, 2); - munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES); - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) { - snd_printk ("download patch failed\n"); - return -(EIO); - } - - return (0); -} - -static int -wavefront_send_program (snd_wavefront_t *dev, wavefront_patch_info *header) - -{ - unsigned char buf[WF_PROGRAM_BYTES+1]; - int i; - - DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n", - header->number); - - dev->prog_status[header->number] = WF_SLOT_USED; - - /* XXX need to zero existing SLOT_USED bit for program_status[i] - where `i' is the program that's being (potentially) overwritten. - */ - - for (i = 0; i < WF_NUM_LAYERS; i++) { - if (header->hdr.pr.layer[i].mute) { - dev->patch_status[header->hdr.pr.layer[i].patch_number] |= - WF_SLOT_USED; - - /* XXX need to mark SLOT_USED for sample used by - patch_number, but this means we have to load it. Ick. - */ - } - } - - buf[0] = header->number; - munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES); - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) { - snd_printk ("download patch failed\n"); - return -(EIO); - } - - return (0); -} - -static int -wavefront_freemem (snd_wavefront_t *dev) - -{ - char rbuf[8]; - - if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) { - snd_printk ("can't get memory stats.\n"); - return -1; - } else { - return demunge_int32 (rbuf, 4); - } -} - -static int -wavefront_send_sample (snd_wavefront_t *dev, - wavefront_patch_info *header, - u16 __user *dataptr, - int data_is_unsigned) - -{ - /* samples are downloaded via a 16-bit wide i/o port - (you could think of it as 2 adjacent 8-bit wide ports - but its less efficient that way). therefore, all - the blocksizes and so forth listed in the documentation, - and used conventionally to refer to sample sizes, - which are given in 8-bit units (bytes), need to be - divided by 2. - */ - - u16 sample_short = 0; - u32 length; - u16 __user *data_end = NULL; - unsigned int i; - const unsigned int max_blksize = 4096/2; - unsigned int written; - unsigned int blocksize; - int dma_ack; - int blocknum; - unsigned char sample_hdr[WF_SAMPLE_HDR_BYTES]; - unsigned char *shptr; - int skip = 0; - int initial_skip = 0; - - DPRINT (WF_DEBUG_LOAD_PATCH, "sample %sdownload for slot %d, " - "type %d, %d bytes from 0x%lx\n", - header->size ? "" : "header ", - header->number, header->subkey, - header->size, - (unsigned long) header->dataptr); - - if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) { - int x; - - if ((x = wavefront_find_free_sample (dev)) < 0) { - return -ENOMEM; - } - snd_printk ("unspecified sample => %d\n", x); - header->number = x; - } - - if (header->size) { - - /* XXX it's a debatable point whether or not RDONLY semantics - on the ROM samples should cover just the sample data or - the sample header. For now, it only covers the sample data, - so anyone is free at all times to rewrite sample headers. - - My reason for this is that we have the sample headers - available in the WFB file for General MIDI, and so these - can always be reset if needed. The sample data, however, - cannot be recovered without a complete reset and firmware - reload of the ICS2115, which is a very expensive operation. - - So, doing things this way allows us to honor the notion of - "RESETSAMPLES" reasonably cheaply. Note however, that this - is done purely at user level: there is no WFB parser in - this driver, and so a complete reset (back to General MIDI, - or theoretically some other configuration) is the - responsibility of the user level library. - - To try to do this in the kernel would be a little - crazy: we'd need 158K of kernel space just to hold - a copy of the patch/program/sample header data. - */ - - if (dev->rom_samples_rdonly) { - if (dev->sample_status[header->number] & WF_SLOT_ROM) { - snd_printk ("sample slot %d " - "write protected\n", - header->number); - return -EACCES; - } - } - - wavefront_delete_sample (dev, header->number); - } - - if (header->size) { - dev->freemem = wavefront_freemem (dev); - - if (dev->freemem < (int)header->size) { - snd_printk ("insufficient memory to " - "load %d byte sample.\n", - header->size); - return -ENOMEM; - } - - } - - skip = WF_GET_CHANNEL(&header->hdr.s); - - if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) { - snd_printk ("channel selection only " - "possible on 16-bit samples"); - return -(EINVAL); - } - - switch (skip) { - case 0: - initial_skip = 0; - skip = 1; - break; - case 1: - initial_skip = 0; - skip = 2; - break; - case 2: - initial_skip = 1; - skip = 2; - break; - case 3: - initial_skip = 2; - skip = 3; - break; - case 4: - initial_skip = 3; - skip = 4; - break; - case 5: - initial_skip = 4; - skip = 5; - break; - case 6: - initial_skip = 5; - skip = 6; - break; - } - - DPRINT (WF_DEBUG_LOAD_PATCH, "channel selection: %d => " - "initial skip = %d, skip = %d\n", - WF_GET_CHANNEL (&header->hdr.s), - initial_skip, skip); - - /* Be safe, and zero the "Unused" bits ... */ - - WF_SET_CHANNEL(&header->hdr.s, 0); - - /* adjust size for 16 bit samples by dividing by two. We always - send 16 bits per write, even for 8 bit samples, so the length - is always half the size of the sample data in bytes. - */ - - length = header->size / 2; - - /* the data we're sent has not been munged, and in fact, the - header we have to send isn't just a munged copy either. - so, build the sample header right here. - */ - - shptr = &sample_hdr[0]; - - shptr = munge_int32 (header->number, shptr, 2); - - if (header->size) { - shptr = munge_int32 (length, shptr, 4); - } - - /* Yes, a 4 byte result doesn't contain all of the offset bits, - but the offset only uses 24 bits. - */ - - shptr = munge_int32 (*((u32 *) &header->hdr.s.sampleStartOffset), - shptr, 4); - shptr = munge_int32 (*((u32 *) &header->hdr.s.loopStartOffset), - shptr, 4); - shptr = munge_int32 (*((u32 *) &header->hdr.s.loopEndOffset), - shptr, 4); - shptr = munge_int32 (*((u32 *) &header->hdr.s.sampleEndOffset), - shptr, 4); - - /* This one is truly weird. What kind of weirdo decided that in - a system dominated by 16 and 32 bit integers, they would use - a just 12 bits ? - */ - - shptr = munge_int32 (header->hdr.s.FrequencyBias, shptr, 3); - - /* Why is this nybblified, when the MSB is *always* zero ? - Anyway, we can't take address of bitfield, so make a - good-faith guess at where it starts. - */ - - shptr = munge_int32 (*(&header->hdr.s.FrequencyBias+1), - shptr, 2); - - if (snd_wavefront_cmd (dev, - header->size ? - WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER, - NULL, sample_hdr)) { - snd_printk ("sample %sdownload refused.\n", - header->size ? "" : "header "); - return -(EIO); - } - - if (header->size == 0) { - goto sent; /* Sorry. Just had to have one somewhere */ - } - - data_end = dataptr + length; - - /* Do any initial skip over an unused channel's data */ - - dataptr += initial_skip; - - for (written = 0, blocknum = 0; - written < length; written += max_blksize, blocknum++) { - - if ((length - written) > max_blksize) { - blocksize = max_blksize; - } else { - /* round to nearest 16-byte value */ - blocksize = ALIGN(length - written, 8); - } - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) { - snd_printk ("download block " - "request refused.\n"); - return -(EIO); - } - - for (i = 0; i < blocksize; i++) { - - if (dataptr < data_end) { - - __get_user (sample_short, dataptr); - dataptr += skip; - - if (data_is_unsigned) { /* GUS ? */ - - if (WF_SAMPLE_IS_8BIT(&header->hdr.s)) { - - /* 8 bit sample - resolution, sign - extend both bytes. - */ - - ((unsigned char*) - &sample_short)[0] += 0x7f; - ((unsigned char*) - &sample_short)[1] += 0x7f; - - } else { - - /* 16 bit sample - resolution, sign - extend the MSB. - */ - - sample_short += 0x7fff; - } - } - - } else { - - /* In padding section of final block: - - Don't fetch unsupplied data from - user space, just continue with - whatever the final value was. - */ - } - - if (i < blocksize - 1) { - outw (sample_short, dev->block_port); - } else { - outw (sample_short, dev->last_block_port); - } - } - - /* Get "DMA page acknowledge", even though its really - nothing to do with DMA at all. - */ - - if ((dma_ack = wavefront_read (dev)) != WF_DMA_ACK) { - if (dma_ack == -1) { - snd_printk ("upload sample " - "DMA ack timeout\n"); - return -(EIO); - } else { - snd_printk ("upload sample " - "DMA ack error 0x%x\n", - dma_ack); - return -(EIO); - } - } - } - - dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE); - - /* Note, label is here because sending the sample header shouldn't - alter the sample_status info at all. - */ - - sent: - return (0); -} - -static int -wavefront_send_alias (snd_wavefront_t *dev, wavefront_patch_info *header) - -{ - unsigned char alias_hdr[WF_ALIAS_BYTES]; - - DPRINT (WF_DEBUG_LOAD_PATCH, "download alias, %d is " - "alias for %d\n", - header->number, - header->hdr.a.OriginalSample); - - munge_int32 (header->number, &alias_hdr[0], 2); - munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2); - munge_int32 (*((unsigned int *)&header->hdr.a.sampleStartOffset), - &alias_hdr[4], 4); - munge_int32 (*((unsigned int *)&header->hdr.a.loopStartOffset), - &alias_hdr[8], 4); - munge_int32 (*((unsigned int *)&header->hdr.a.loopEndOffset), - &alias_hdr[12], 4); - munge_int32 (*((unsigned int *)&header->hdr.a.sampleEndOffset), - &alias_hdr[16], 4); - munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3); - munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2); - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) { - snd_printk ("download alias failed.\n"); - return -(EIO); - } - - dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS); - - return (0); -} - -static int -wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header) -{ - int i; - int num_samples; - unsigned char *msample_hdr; - - msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL); - if (! msample_hdr) - return -ENOMEM; - - munge_int32 (header->number, &msample_hdr[0], 2); - - /* You'll recall at this point that the "number of samples" value - in a wavefront_multisample struct is actually the log2 of the - real number of samples. - */ - - num_samples = (1<<(header->hdr.ms.NumberOfSamples&7)); - msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples; - - DPRINT (WF_DEBUG_LOAD_PATCH, "multi %d with %d=%d samples\n", - header->number, - header->hdr.ms.NumberOfSamples, - num_samples); - - for (i = 0; i < num_samples; i++) { - DPRINT(WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA, "sample[%d] = %d\n", - i, header->hdr.ms.SampleNumber[i]); - munge_int32 (header->hdr.ms.SampleNumber[i], - &msample_hdr[3+(i*2)], 2); - } - - /* Need a hack here to pass in the number of bytes - to be written to the synth. This is ugly, and perhaps - one day, I'll fix it. - */ - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE, - (unsigned char *) (long) ((num_samples*2)+3), - msample_hdr)) { - snd_printk ("download of multisample failed.\n"); - kfree(msample_hdr); - return -(EIO); - } - - dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE); - - kfree(msample_hdr); - return (0); -} - -static int -wavefront_fetch_multisample (snd_wavefront_t *dev, - wavefront_patch_info *header) -{ - int i; - unsigned char log_ns[1]; - unsigned char number[2]; - int num_samples; - - munge_int32 (header->number, number, 2); - - if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) { - snd_printk ("upload multisample failed.\n"); - return -(EIO); - } - - DPRINT (WF_DEBUG_DATA, "msample %d has %d samples\n", - header->number, log_ns[0]); - - header->hdr.ms.NumberOfSamples = log_ns[0]; - - /* get the number of samples ... */ - - num_samples = (1 << log_ns[0]); - - for (i = 0; i < num_samples; i++) { - char d[2]; - int val; - - if ((val = wavefront_read (dev)) == -1) { - snd_printk ("upload multisample failed " - "during sample loop.\n"); - return -(EIO); - } - d[0] = val; - - if ((val = wavefront_read (dev)) == -1) { - snd_printk ("upload multisample failed " - "during sample loop.\n"); - return -(EIO); - } - d[1] = val; - - header->hdr.ms.SampleNumber[i] = - demunge_int32 ((unsigned char *) d, 2); - - DPRINT (WF_DEBUG_DATA, "msample sample[%d] = %d\n", - i, header->hdr.ms.SampleNumber[i]); - } - - return (0); -} - - -static int -wavefront_send_drum (snd_wavefront_t *dev, wavefront_patch_info *header) - -{ - unsigned char drumbuf[WF_DRUM_BYTES]; - wavefront_drum *drum = &header->hdr.d; - int i; - - DPRINT (WF_DEBUG_LOAD_PATCH, "downloading edrum for MIDI " - "note %d, patch = %d\n", - header->number, drum->PatchNumber); - - drumbuf[0] = header->number & 0x7f; - - for (i = 0; i < 4; i++) { - munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2); - } - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) { - snd_printk ("download drum failed.\n"); - return -(EIO); - } - - return (0); -} - -static int -wavefront_find_free_sample (snd_wavefront_t *dev) - -{ - int i; - - for (i = 0; i < WF_MAX_SAMPLE; i++) { - if (!(dev->sample_status[i] & WF_SLOT_FILLED)) { - return i; - } - } - snd_printk ("no free sample slots!\n"); - return -1; -} - -#if 0 -static int -wavefront_find_free_patch (snd_wavefront_t *dev) - -{ - int i; - - for (i = 0; i < WF_MAX_PATCH; i++) { - if (!(dev->patch_status[i] & WF_SLOT_FILLED)) { - return i; - } - } - snd_printk ("no free patch slots!\n"); - return -1; -} -#endif - -static int -wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr) -{ - wavefront_patch_info *header; - int err; - - header = kmalloc(sizeof(*header), GFP_KERNEL); - if (! header) - return -ENOMEM; - - if (copy_from_user (header, addr, sizeof(wavefront_patch_info) - - sizeof(wavefront_any))) { - snd_printk ("bad address for load patch.\n"); - err = -EFAULT; - goto __error; - } - - DPRINT (WF_DEBUG_LOAD_PATCH, "download " - "Sample type: %d " - "Sample number: %d " - "Sample size: %d\n", - header->subkey, - header->number, - header->size); - - switch (header->subkey) { - case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */ - - if (copy_from_user (&header->hdr.s, header->hdrptr, - sizeof (wavefront_sample))) { - err = -EFAULT; - break; - } - - err = wavefront_send_sample (dev, header, header->dataptr, 0); - break; - - case WF_ST_MULTISAMPLE: - - if (copy_from_user (&header->hdr.s, header->hdrptr, - sizeof (wavefront_multisample))) { - err = -EFAULT; - break; - } - - err = wavefront_send_multisample (dev, header); - break; - - case WF_ST_ALIAS: - - if (copy_from_user (&header->hdr.a, header->hdrptr, - sizeof (wavefront_alias))) { - err = -EFAULT; - break; - } - - err = wavefront_send_alias (dev, header); - break; - - case WF_ST_DRUM: - if (copy_from_user (&header->hdr.d, header->hdrptr, - sizeof (wavefront_drum))) { - err = -EFAULT; - break; - } - - err = wavefront_send_drum (dev, header); - break; - - case WF_ST_PATCH: - if (copy_from_user (&header->hdr.p, header->hdrptr, - sizeof (wavefront_patch))) { - err = -EFAULT; - break; - } - - err = wavefront_send_patch (dev, header); - break; - - case WF_ST_PROGRAM: - if (copy_from_user (&header->hdr.pr, header->hdrptr, - sizeof (wavefront_program))) { - err = -EFAULT; - break; - } - - err = wavefront_send_program (dev, header); - break; - - default: - snd_printk ("unknown patch type %d.\n", - header->subkey); - err = -EINVAL; - break; - } - - __error: - kfree(header); - return err; -} - -/*********************************************************************** -WaveFront: hardware-dependent interface -***********************************************************************/ - -static void -process_sample_hdr (u8 *buf) - -{ - wavefront_sample s; - u8 *ptr; - - ptr = buf; - - /* The board doesn't send us an exact copy of a "wavefront_sample" - in response to an Upload Sample Header command. Instead, we - have to convert the data format back into our data structure, - just as in the Download Sample command, where we have to do - something very similar in the reverse direction. - */ - - *((u32 *) &s.sampleStartOffset) = demunge_int32 (ptr, 4); ptr += 4; - *((u32 *) &s.loopStartOffset) = demunge_int32 (ptr, 4); ptr += 4; - *((u32 *) &s.loopEndOffset) = demunge_int32 (ptr, 4); ptr += 4; - *((u32 *) &s.sampleEndOffset) = demunge_int32 (ptr, 4); ptr += 4; - *((u32 *) &s.FrequencyBias) = demunge_int32 (ptr, 3); ptr += 3; - - s.SampleResolution = *ptr & 0x3; - s.Loop = *ptr & 0x8; - s.Bidirectional = *ptr & 0x10; - s.Reverse = *ptr & 0x40; - - /* Now copy it back to where it came from */ - - memcpy (buf, (unsigned char *) &s, sizeof (wavefront_sample)); -} - -static int -wavefront_synth_control (snd_wavefront_card_t *acard, - wavefront_control *wc) - -{ - snd_wavefront_t *dev = &acard->wavefront; - unsigned char patchnumbuf[2]; - int i; - - DPRINT (WF_DEBUG_CMD, "synth control with " - "cmd 0x%x\n", wc->cmd); - - /* Pre-handling of or for various commands */ - - switch (wc->cmd) { - - case WFC_DISABLE_INTERRUPTS: - snd_printk ("interrupts disabled.\n"); - outb (0x80|0x20, dev->control_port); - dev->interrupts_are_midi = 1; - return 0; - - case WFC_ENABLE_INTERRUPTS: - snd_printk ("interrupts enabled.\n"); - outb (0x80|0x40|0x20, dev->control_port); - dev->interrupts_are_midi = 1; - return 0; - - case WFC_INTERRUPT_STATUS: - wc->rbuf[0] = dev->interrupts_are_midi; - return 0; - - case WFC_ROMSAMPLES_RDONLY: - dev->rom_samples_rdonly = wc->wbuf[0]; - wc->status = 0; - return 0; - - case WFC_IDENTIFY_SLOT_TYPE: - i = wc->wbuf[0] | (wc->wbuf[1] << 7); - if (i <0 || i >= WF_MAX_SAMPLE) { - snd_printk ("invalid slot ID %d\n", - i); - wc->status = EINVAL; - return -EINVAL; - } - wc->rbuf[0] = dev->sample_status[i]; - wc->status = 0; - return 0; - - case WFC_DEBUG_DRIVER: - dev->debug = wc->wbuf[0]; - snd_printk ("debug = 0x%x\n", dev->debug); - return 0; - - case WFC_UPLOAD_PATCH: - munge_int32 (*((u32 *) wc->wbuf), patchnumbuf, 2); - memcpy (wc->wbuf, patchnumbuf, 2); - break; - - case WFC_UPLOAD_MULTISAMPLE: - /* multisamples have to be handled differently, and - cannot be dealt with properly by snd_wavefront_cmd() alone. - */ - wc->status = wavefront_fetch_multisample - (dev, (wavefront_patch_info *) wc->rbuf); - return 0; - - case WFC_UPLOAD_SAMPLE_ALIAS: - snd_printk ("support for sample alias upload " - "being considered.\n"); - wc->status = EINVAL; - return -EINVAL; - } - - wc->status = snd_wavefront_cmd (dev, wc->cmd, wc->rbuf, wc->wbuf); - - /* Post-handling of certain commands. - - In particular, if the command was an upload, demunge the data - so that the user-level doesn't have to think about it. - */ - - if (wc->status == 0) { - switch (wc->cmd) { - /* intercept any freemem requests so that we know - we are always current with the user-level view - of things. - */ - - case WFC_REPORT_FREE_MEMORY: - dev->freemem = demunge_int32 (wc->rbuf, 4); - break; - - case WFC_UPLOAD_PATCH: - demunge_buf (wc->rbuf, wc->rbuf, WF_PATCH_BYTES); - break; - - case WFC_UPLOAD_PROGRAM: - demunge_buf (wc->rbuf, wc->rbuf, WF_PROGRAM_BYTES); - break; - - case WFC_UPLOAD_EDRUM_PROGRAM: - demunge_buf (wc->rbuf, wc->rbuf, WF_DRUM_BYTES - 1); - break; - - case WFC_UPLOAD_SAMPLE_HEADER: - process_sample_hdr (wc->rbuf); - break; - - case WFC_UPLOAD_SAMPLE_ALIAS: - snd_printk ("support for " - "sample aliases still " - "being considered.\n"); - break; - - case WFC_VMIDI_OFF: - snd_wavefront_midi_disable_virtual (acard); - break; - - case WFC_VMIDI_ON: - snd_wavefront_midi_enable_virtual (acard); - break; - } - } - - return 0; -} - -int -snd_wavefront_synth_open (struct snd_hwdep *hw, struct file *file) - -{ - if (!try_module_get(hw->card->module)) - return -EFAULT; - file->private_data = hw; - return 0; -} - -int -snd_wavefront_synth_release (struct snd_hwdep *hw, struct file *file) - -{ - module_put(hw->card->module); - return 0; -} - -int -snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file, - unsigned int cmd, unsigned long arg) - -{ - struct snd_card *card; - snd_wavefront_t *dev; - snd_wavefront_card_t *acard; - wavefront_control *wc; - void __user *argp = (void __user *)arg; - int err; - - card = (struct snd_card *) hw->card; - - if (snd_BUG_ON(!card)) - return -ENODEV; - if (snd_BUG_ON(!card->private_data)) - return -ENODEV; - - acard = card->private_data; - dev = &acard->wavefront; - - switch (cmd) { - case WFCTL_LOAD_SPP: - if (wavefront_load_patch (dev, argp) != 0) { - return -EIO; - } - break; - - case WFCTL_WFCMD: - 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; - else - err = 0; - kfree(wc); - return err; - - default: - return -EINVAL; - } - - return 0; -} - - -/***********************************************************************/ -/* WaveFront: interface for card-level wavefront module */ -/***********************************************************************/ - -void -snd_wavefront_internal_interrupt (snd_wavefront_card_t *card) -{ - snd_wavefront_t *dev = &card->wavefront; - - /* - Some comments on interrupts. I attempted a version of this - driver that used interrupts throughout the code instead of - doing busy and/or sleep-waiting. Alas, it appears that once - the Motorola firmware is downloaded, the card *never* - generates an RX interrupt. These are successfully generated - during firmware loading, and after that wavefront_status() - reports that an interrupt is pending on the card from time - to time, but it never seems to be delivered to this - driver. Note also that wavefront_status() continues to - report that RX interrupts are enabled, suggesting that I - didn't goof up and disable them by mistake. - - Thus, I stepped back to a prior version of - wavefront_wait(), the only place where this really - matters. Its sad, but I've looked through the code to check - on things, and I really feel certain that the Motorola - firmware prevents RX-ready interrupts. - */ - - if ((wavefront_status(dev) & (STAT_INTR_READ|STAT_INTR_WRITE)) == 0) { - return; - } - - spin_lock(&dev->irq_lock); - dev->irq_ok = 1; - dev->irq_cnt++; - spin_unlock(&dev->irq_lock); - wake_up(&dev->interrupt_sleeper); -} - -/* STATUS REGISTER - -0 Host Rx Interrupt Enable (1=Enabled) -1 Host Rx Register Full (1=Full) -2 Host Rx Interrupt Pending (1=Interrupt) -3 Unused -4 Host Tx Interrupt (1=Enabled) -5 Host Tx Register empty (1=Empty) -6 Host Tx Interrupt Pending (1=Interrupt) -7 Unused -*/ - -static int __devinit -snd_wavefront_interrupt_bits (int irq) - -{ - int bits; - - switch (irq) { - case 9: - bits = 0x00; - break; - case 5: - bits = 0x08; - break; - case 12: - bits = 0x10; - break; - case 15: - bits = 0x18; - break; - - default: - snd_printk ("invalid IRQ %d\n", irq); - bits = -1; - } - - return bits; -} - -static void __devinit -wavefront_should_cause_interrupt (snd_wavefront_t *dev, - int val, int port, unsigned long timeout) - -{ - wait_queue_t wait; - - init_waitqueue_entry(&wait, current); - spin_lock_irq(&dev->irq_lock); - add_wait_queue(&dev->interrupt_sleeper, &wait); - dev->irq_ok = 0; - outb (val,port); - spin_unlock_irq(&dev->irq_lock); - while (!dev->irq_ok && time_before(jiffies, timeout)) { - schedule_timeout_uninterruptible(1); - barrier(); - } -} - -static int __devinit -wavefront_reset_to_cleanliness (snd_wavefront_t *dev) - -{ - int bits; - int hwv[2]; - - /* IRQ already checked */ - - bits = snd_wavefront_interrupt_bits (dev->irq); - - /* try reset of port */ - - outb (0x0, dev->control_port); - - /* At this point, the board is in reset, and the H/W initialization - register is accessed at the same address as the data port. - - Bit 7 - Enable IRQ Driver - 0 - Tri-state the Wave-Board drivers for the PC Bus IRQs - 1 - Enable IRQ selected by bits 5:3 to be driven onto the PC Bus. - - Bit 6 - MIDI Interface Select - - 0 - Use the MIDI Input from the 26-pin WaveBlaster - compatible header as the serial MIDI source - 1 - Use the MIDI Input from the 9-pin D connector as the - serial MIDI source. - - Bits 5:3 - IRQ Selection - 0 0 0 - IRQ 2/9 - 0 0 1 - IRQ 5 - 0 1 0 - IRQ 12 - 0 1 1 - IRQ 15 - 1 0 0 - Reserved - 1 0 1 - Reserved - 1 1 0 - Reserved - 1 1 1 - Reserved - - Bits 2:1 - Reserved - Bit 0 - Disable Boot ROM - 0 - memory accesses to 03FC30-03FFFFH utilize the internal Boot ROM - 1 - memory accesses to 03FC30-03FFFFH are directed to external - storage. - - */ - - /* configure hardware: IRQ, enable interrupts, - plus external 9-pin MIDI interface selected - */ - - outb (0x80 | 0x40 | bits, dev->data_port); - - /* CONTROL REGISTER - - 0 Host Rx Interrupt Enable (1=Enabled) 0x1 - 1 Unused 0x2 - 2 Unused 0x4 - 3 Unused 0x8 - 4 Host Tx Interrupt Enable 0x10 - 5 Mute (0=Mute; 1=Play) 0x20 - 6 Master Interrupt Enable (1=Enabled) 0x40 - 7 Master Reset (0=Reset; 1=Run) 0x80 - - Take us out of reset, mute output, master + TX + RX interrupts on. - - We'll get an interrupt presumably to tell us that the TX - register is clear. - */ - - wavefront_should_cause_interrupt(dev, 0x80|0x40|0x10|0x1, - dev->control_port, - (reset_time*HZ)/100); - - /* Note: data port is now the data port, not the h/w initialization - port. - */ - - if (!dev->irq_ok) { - snd_printk ("intr not received after h/w un-reset.\n"); - goto gone_bad; - } - - /* Note: data port is now the data port, not the h/w initialization - port. - - At this point, only "HW VERSION" or "DOWNLOAD OS" commands - will work. So, issue one of them, and wait for TX - interrupt. This can take a *long* time after a cold boot, - while the ISC ROM does its RAM test. The SDK says up to 4 - seconds - with 12MB of RAM on a Tropez+, it takes a lot - longer than that (~16secs). Note that the card understands - the difference between a warm and a cold boot, so - subsequent ISC2115 reboots (say, caused by module - reloading) will get through this much faster. - - XXX Interesting question: why is no RX interrupt received first ? - */ - - wavefront_should_cause_interrupt(dev, WFC_HARDWARE_VERSION, - dev->data_port, ramcheck_time*HZ); - - if (!dev->irq_ok) { - snd_printk ("post-RAM-check interrupt not received.\n"); - goto gone_bad; - } - - if (!wavefront_wait (dev, STAT_CAN_READ)) { - snd_printk ("no response to HW version cmd.\n"); - goto gone_bad; - } - - if ((hwv[0] = wavefront_read (dev)) == -1) { - snd_printk ("board not responding correctly.\n"); - goto gone_bad; - } - - if (hwv[0] == 0xFF) { /* NAK */ - - /* Board's RAM test failed. Try to read error code, - and tell us about it either way. - */ - - if ((hwv[0] = wavefront_read (dev)) == -1) { - snd_printk ("on-board RAM test failed " - "(bad error code).\n"); - } else { - snd_printk ("on-board RAM test failed " - "(error code: 0x%x).\n", - hwv[0]); - } - goto gone_bad; - } - - /* We're OK, just get the next byte of the HW version response */ - - if ((hwv[1] = wavefront_read (dev)) == -1) { - snd_printk ("incorrect h/w response.\n"); - goto gone_bad; - } - - snd_printk ("hardware version %d.%d\n", - hwv[0], hwv[1]); - - return 0; - - - gone_bad: - return (1); -} - -static int __devinit -wavefront_download_firmware (snd_wavefront_t *dev, char *path) - -{ - const unsigned char *buf; - int len, err; - int section_cnt_downloaded = 0; - const struct firmware *firmware; - - err = request_firmware(&firmware, path, dev->card->dev); - if (err < 0) { - snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path); - return 1; - } - - len = 0; - buf = firmware->data; - for (;;) { - int section_length = *(signed char *)buf; - if (section_length == 0) - break; - if (section_length < 0 || section_length > WF_SECTION_MAX) { - snd_printk(KERN_ERR - "invalid firmware section length %d\n", - section_length); - goto failure; - } - buf++; - len++; - - if (firmware->size < len + section_length) { - snd_printk(KERN_ERR "firmware section read error.\n"); - goto failure; - } - - /* Send command */ - if (wavefront_write(dev, WFC_DOWNLOAD_OS)) - goto failure; - - for (; section_length; section_length--) { - if (wavefront_write(dev, *buf)) - goto failure; - buf++; - len++; - } - - /* get ACK */ - if (!wavefront_wait(dev, STAT_CAN_READ)) { - snd_printk(KERN_ERR "time out for firmware ACK.\n"); - goto failure; - } - err = inb(dev->data_port); - if (err != WF_ACK) { - snd_printk(KERN_ERR - "download of section #%d not " - "acknowledged, ack = 0x%x\n", - section_cnt_downloaded + 1, err); - goto failure; - } - - section_cnt_downloaded++; - } - - release_firmware(firmware); - return 0; - - failure: - release_firmware(firmware); - snd_printk(KERN_ERR "firmware download failed!!!\n"); - return 1; -} - - -static int __devinit -wavefront_do_reset (snd_wavefront_t *dev) - -{ - char voices[1]; - - if (wavefront_reset_to_cleanliness (dev)) { - snd_printk ("hw reset failed.\n"); - goto gone_bad; - } - - if (dev->israw) { - if (wavefront_download_firmware (dev, ospath)) { - goto gone_bad; - } - - dev->israw = 0; - - /* Wait for the OS to get running. The protocol for - this is non-obvious, and was determined by - using port-IO tracing in DOSemu and some - experimentation here. - - Rather than using timed waits, use interrupts creatively. - */ - - wavefront_should_cause_interrupt (dev, WFC_NOOP, - dev->data_port, - (osrun_time*HZ)); - - if (!dev->irq_ok) { - snd_printk ("no post-OS interrupt.\n"); - goto gone_bad; - } - - /* Now, do it again ! */ - - wavefront_should_cause_interrupt (dev, WFC_NOOP, - dev->data_port, (10*HZ)); - - if (!dev->irq_ok) { - snd_printk ("no post-OS interrupt(2).\n"); - goto gone_bad; - } - - /* OK, no (RX/TX) interrupts any more, but leave mute - in effect. - */ - - outb (0x80|0x40, dev->control_port); - } - - /* SETUPSND.EXE asks for sample memory config here, but since i - have no idea how to interpret the result, we'll forget - about it. - */ - - if ((dev->freemem = wavefront_freemem (dev)) < 0) { - goto gone_bad; - } - - snd_printk ("available DRAM %dk\n", dev->freemem / 1024); - - if (wavefront_write (dev, 0xf0) || - wavefront_write (dev, 1) || - (wavefront_read (dev) < 0)) { - dev->debug = 0; - snd_printk ("MPU emulation mode not set.\n"); - goto gone_bad; - } - - voices[0] = 32; - - if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) { - snd_printk ("cannot set number of voices to 32.\n"); - goto gone_bad; - } - - - return 0; - - gone_bad: - /* reset that sucker so that it doesn't bother us. */ - - outb (0x0, dev->control_port); - dev->interrupts_are_midi = 0; - return 1; -} - -int __devinit -snd_wavefront_start (snd_wavefront_t *dev) - -{ - int samples_are_from_rom; - - /* IMPORTANT: assumes that snd_wavefront_detect() and/or - wavefront_reset_to_cleanliness() has already been called - */ - - if (dev->israw) { - samples_are_from_rom = 1; - } else { - /* XXX is this always true ? */ - samples_are_from_rom = 0; - } - - if (dev->israw || fx_raw) { - if (wavefront_do_reset (dev)) { - return -1; - } - } - /* Check for FX device, present only on Tropez+ */ - - dev->has_fx = (snd_wavefront_fx_detect (dev) == 0); - - if (dev->has_fx && fx_raw) { - snd_wavefront_fx_start (dev); - } - - wavefront_get_sample_status (dev, samples_are_from_rom); - wavefront_get_program_status (dev); - wavefront_get_patch_status (dev); - - /* Start normal operation: unreset, master interrupt enabled, no mute - */ - - outb (0x80|0x40|0x20, dev->control_port); - - return (0); -} - -int __devinit -snd_wavefront_detect (snd_wavefront_card_t *card) - -{ - unsigned char rbuf[4], wbuf[4]; - snd_wavefront_t *dev = &card->wavefront; - - /* returns zero if a WaveFront card is successfully detected. - negative otherwise. - */ - - dev->israw = 0; - dev->has_fx = 0; - dev->debug = debug_default; - dev->interrupts_are_midi = 0; - dev->irq_cnt = 0; - dev->rom_samples_rdonly = 1; - - if (snd_wavefront_cmd (dev, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) { - - dev->fw_version[0] = rbuf[0]; - dev->fw_version[1] = rbuf[1]; - - snd_printk ("firmware %d.%d already loaded.\n", - rbuf[0], rbuf[1]); - - /* check that a command actually works */ - - if (snd_wavefront_cmd (dev, WFC_HARDWARE_VERSION, - rbuf, wbuf) == 0) { - dev->hw_version[0] = rbuf[0]; - dev->hw_version[1] = rbuf[1]; - } else { - snd_printk ("not raw, but no " - "hardware version!\n"); - return -1; - } - - if (!wf_raw) { - return 0; - } else { - snd_printk ("reloading firmware as you requested.\n"); - dev->israw = 1; - } - - } else { - - dev->israw = 1; - snd_printk ("no response to firmware probe, assume raw.\n"); - - } - - return 0; -} - -MODULE_FIRMWARE(DEFAULT_OSPATH); diff --git a/ANDROID_3.4.5/sound/isa/wss/Makefile b/ANDROID_3.4.5/sound/isa/wss/Makefile deleted file mode 100644 index 454fee76..00000000 --- a/ANDROID_3.4.5/sound/isa/wss/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2008 by Jaroslav Kysela -# - -snd-wss-lib-objs := wss_lib.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_WSS_LIB) += snd-wss-lib.o - diff --git a/ANDROID_3.4.5/sound/isa/wss/wss_lib.c b/ANDROID_3.4.5/sound/isa/wss/wss_lib.c deleted file mode 100644 index 49c8a0c2..00000000 --- a/ANDROID_3.4.5/sound/isa/wss/wss_lib.c +++ /dev/null @@ -1,2304 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips - * - * Bugs: - * - sometimes record brokes playback with WSS portion of - * Yamaha OPL3-SA3 chip - * - CS4231 (GUS MAX) - still trouble with occasional noises - * - broken initialization? - * - * 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 -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); -MODULE_LICENSE("GPL"); - -#if 0 -#define SNDRV_DEBUG_MCE -#endif - -/* - * Some variables - */ - -static unsigned char freq_bits[14] = { - /* 5510 */ 0x00 | CS4231_XTAL2, - /* 6620 */ 0x0E | CS4231_XTAL2, - /* 8000 */ 0x00 | CS4231_XTAL1, - /* 9600 */ 0x0E | CS4231_XTAL1, - /* 11025 */ 0x02 | CS4231_XTAL2, - /* 16000 */ 0x02 | CS4231_XTAL1, - /* 18900 */ 0x04 | CS4231_XTAL2, - /* 22050 */ 0x06 | CS4231_XTAL2, - /* 27042 */ 0x04 | CS4231_XTAL1, - /* 32000 */ 0x06 | CS4231_XTAL1, - /* 33075 */ 0x0C | CS4231_XTAL2, - /* 37800 */ 0x08 | CS4231_XTAL2, - /* 44100 */ 0x0A | CS4231_XTAL2, - /* 48000 */ 0x0C | CS4231_XTAL1 -}; - -static unsigned int rates[14] = { - 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, - 27042, 32000, 33075, 37800, 44100, 48000 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static int snd_wss_xrate(struct snd_pcm_runtime *runtime) -{ - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates); -} - -static unsigned char snd_wss_original_image[32] = -{ - 0x00, /* 00/00 - lic */ - 0x00, /* 01/01 - ric */ - 0x9f, /* 02/02 - la1ic */ - 0x9f, /* 03/03 - ra1ic */ - 0x9f, /* 04/04 - la2ic */ - 0x9f, /* 05/05 - ra2ic */ - 0xbf, /* 06/06 - loc */ - 0xbf, /* 07/07 - roc */ - 0x20, /* 08/08 - pdfr */ - CS4231_AUTOCALIB, /* 09/09 - ic */ - 0x00, /* 0a/10 - pc */ - 0x00, /* 0b/11 - ti */ - CS4231_MODE2, /* 0c/12 - mi */ - 0xfc, /* 0d/13 - lbc */ - 0x00, /* 0e/14 - pbru */ - 0x00, /* 0f/15 - pbrl */ - 0x80, /* 10/16 - afei */ - 0x01, /* 11/17 - afeii */ - 0x9f, /* 12/18 - llic */ - 0x9f, /* 13/19 - rlic */ - 0x00, /* 14/20 - tlb */ - 0x00, /* 15/21 - thb */ - 0x00, /* 16/22 - la3mic/reserved */ - 0x00, /* 17/23 - ra3mic/reserved */ - 0x00, /* 18/24 - afs */ - 0x00, /* 19/25 - lamoc/version */ - 0xcf, /* 1a/26 - mioc */ - 0x00, /* 1b/27 - ramoc/reserved */ - 0x20, /* 1c/28 - cdfr */ - 0x00, /* 1d/29 - res4 */ - 0x00, /* 1e/30 - cbru */ - 0x00, /* 1f/31 - cbrl */ -}; - -static unsigned char snd_opti93x_original_image[32] = -{ - 0x00, /* 00/00 - l_mixout_outctrl */ - 0x00, /* 01/01 - r_mixout_outctrl */ - 0x88, /* 02/02 - l_cd_inctrl */ - 0x88, /* 03/03 - r_cd_inctrl */ - 0x88, /* 04/04 - l_a1/fm_inctrl */ - 0x88, /* 05/05 - r_a1/fm_inctrl */ - 0x80, /* 06/06 - l_dac_inctrl */ - 0x80, /* 07/07 - r_dac_inctrl */ - 0x00, /* 08/08 - ply_dataform_reg */ - 0x00, /* 09/09 - if_conf */ - 0x00, /* 0a/10 - pin_ctrl */ - 0x00, /* 0b/11 - err_init_reg */ - 0x0a, /* 0c/12 - id_reg */ - 0x00, /* 0d/13 - reserved */ - 0x00, /* 0e/14 - ply_upcount_reg */ - 0x00, /* 0f/15 - ply_lowcount_reg */ - 0x88, /* 10/16 - reserved/l_a1_inctrl */ - 0x88, /* 11/17 - reserved/r_a1_inctrl */ - 0x88, /* 12/18 - l_line_inctrl */ - 0x88, /* 13/19 - r_line_inctrl */ - 0x88, /* 14/20 - l_mic_inctrl */ - 0x88, /* 15/21 - r_mic_inctrl */ - 0x80, /* 16/22 - l_out_outctrl */ - 0x80, /* 17/23 - r_out_outctrl */ - 0x00, /* 18/24 - reserved */ - 0x00, /* 19/25 - reserved */ - 0x00, /* 1a/26 - reserved */ - 0x00, /* 1b/27 - reserved */ - 0x00, /* 1c/28 - cap_dataform_reg */ - 0x00, /* 1d/29 - reserved */ - 0x00, /* 1e/30 - cap_upcount_reg */ - 0x00 /* 1f/31 - cap_lowcount_reg */ -}; - -/* - * Basic I/O functions - */ - -static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val) -{ - outb(val, chip->port + offset); -} - -static inline u8 wss_inb(struct snd_wss *chip, u8 offset) -{ - return inb(chip->port + offset); -} - -static void snd_wss_wait(struct snd_wss *chip) -{ - int timeout; - - for (timeout = 250; - timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); -} - -static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, - unsigned char value) -{ - int timeout; - - for (timeout = 250; - timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); - timeout--) - udelay(10); - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - wss_outb(chip, CS4231P(REG), value); - mb(); -} - -void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value) -{ - snd_wss_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "out: auto calibration time out " - "- reg = 0x%x, value = 0x%x\n", reg, value); -#endif - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - wss_outb(chip, CS4231P(REG), value); - chip->image[reg] = value; - mb(); - snd_printdd("codec out - reg 0x%x = 0x%x\n", - chip->mce_bit | reg, value); -} -EXPORT_SYMBOL(snd_wss_out); - -unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg) -{ - snd_wss_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "in: auto calibration time out " - "- reg = 0x%x\n", reg); -#endif - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - mb(); - return wss_inb(chip, CS4231P(REG)); -} -EXPORT_SYMBOL(snd_wss_in); - -void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg, - unsigned char val) -{ - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17); - wss_outb(chip, CS4231P(REG), - reg | (chip->image[CS4236_EXT_REG] & 0x01)); - wss_outb(chip, CS4231P(REG), val); - chip->eimage[CS4236_REG(reg)] = val; -#if 0 - printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val); -#endif -} -EXPORT_SYMBOL(snd_cs4236_ext_out); - -unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg) -{ - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17); - wss_outb(chip, CS4231P(REG), - reg | (chip->image[CS4236_EXT_REG] & 0x01)); -#if 1 - return wss_inb(chip, CS4231P(REG)); -#else - { - unsigned char res; - res = wss_inb(chip, CS4231P(REG)); - printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n", - reg, res); - return res; - } -#endif -} -EXPORT_SYMBOL(snd_cs4236_ext_in); - -#if 0 - -static void snd_wss_debug(struct snd_wss *chip) -{ - printk(KERN_DEBUG - "CS4231 REGS: INDEX = 0x%02x " - " STATUS = 0x%02x\n", - wss_inb(chip, CS4231P(REGSEL)), - wss_inb(chip, CS4231P(STATUS))); - printk(KERN_DEBUG - " 0x00: left input = 0x%02x " - " 0x10: alt 1 (CFIG 2) = 0x%02x\n", - snd_wss_in(chip, 0x00), - snd_wss_in(chip, 0x10)); - printk(KERN_DEBUG - " 0x01: right input = 0x%02x " - " 0x11: alt 2 (CFIG 3) = 0x%02x\n", - snd_wss_in(chip, 0x01), - snd_wss_in(chip, 0x11)); - printk(KERN_DEBUG - " 0x02: GF1 left input = 0x%02x " - " 0x12: left line in = 0x%02x\n", - snd_wss_in(chip, 0x02), - snd_wss_in(chip, 0x12)); - printk(KERN_DEBUG - " 0x03: GF1 right input = 0x%02x " - " 0x13: right line in = 0x%02x\n", - snd_wss_in(chip, 0x03), - snd_wss_in(chip, 0x13)); - printk(KERN_DEBUG - " 0x04: CD left input = 0x%02x " - " 0x14: timer low = 0x%02x\n", - snd_wss_in(chip, 0x04), - snd_wss_in(chip, 0x14)); - printk(KERN_DEBUG - " 0x05: CD right input = 0x%02x " - " 0x15: timer high = 0x%02x\n", - snd_wss_in(chip, 0x05), - snd_wss_in(chip, 0x15)); - printk(KERN_DEBUG - " 0x06: left output = 0x%02x " - " 0x16: left MIC (PnP) = 0x%02x\n", - snd_wss_in(chip, 0x06), - snd_wss_in(chip, 0x16)); - printk(KERN_DEBUG - " 0x07: right output = 0x%02x " - " 0x17: right MIC (PnP) = 0x%02x\n", - snd_wss_in(chip, 0x07), - snd_wss_in(chip, 0x17)); - printk(KERN_DEBUG - " 0x08: playback format = 0x%02x " - " 0x18: IRQ status = 0x%02x\n", - snd_wss_in(chip, 0x08), - snd_wss_in(chip, 0x18)); - printk(KERN_DEBUG - " 0x09: iface (CFIG 1) = 0x%02x " - " 0x19: left line out = 0x%02x\n", - snd_wss_in(chip, 0x09), - snd_wss_in(chip, 0x19)); - printk(KERN_DEBUG - " 0x0a: pin control = 0x%02x " - " 0x1a: mono control = 0x%02x\n", - snd_wss_in(chip, 0x0a), - snd_wss_in(chip, 0x1a)); - printk(KERN_DEBUG - " 0x0b: init & status = 0x%02x " - " 0x1b: right line out = 0x%02x\n", - snd_wss_in(chip, 0x0b), - snd_wss_in(chip, 0x1b)); - printk(KERN_DEBUG - " 0x0c: revision & mode = 0x%02x " - " 0x1c: record format = 0x%02x\n", - snd_wss_in(chip, 0x0c), - snd_wss_in(chip, 0x1c)); - printk(KERN_DEBUG - " 0x0d: loopback = 0x%02x " - " 0x1d: var freq (PnP) = 0x%02x\n", - snd_wss_in(chip, 0x0d), - snd_wss_in(chip, 0x1d)); - printk(KERN_DEBUG - " 0x0e: ply upr count = 0x%02x " - " 0x1e: ply lwr count = 0x%02x\n", - snd_wss_in(chip, 0x0e), - snd_wss_in(chip, 0x1e)); - printk(KERN_DEBUG - " 0x0f: rec upr count = 0x%02x " - " 0x1f: rec lwr count = 0x%02x\n", - snd_wss_in(chip, 0x0f), - snd_wss_in(chip, 0x1f)); -} - -#endif - -/* - * CS4231 detection / MCE routines - */ - -static void snd_wss_busy_wait(struct snd_wss *chip) -{ - int timeout; - - /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ - for (timeout = 5; timeout > 0; timeout--) - wss_inb(chip, CS4231P(REGSEL)); - /* end of cleanup sequence */ - for (timeout = 25000; - timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); - timeout--) - udelay(10); -} - -void snd_wss_mce_up(struct snd_wss *chip) -{ - unsigned long flags; - int timeout; - - snd_wss_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG - "mce_up - auto calibration time out (0)\n"); -#endif - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit |= CS4231_MCE; - timeout = wss_inb(chip, CS4231P(REGSEL)); - if (timeout == 0x80) - snd_printk(KERN_DEBUG "mce_up [0x%lx]: " - "serious init problem - codec still busy\n", - chip->port); - if (!(timeout & CS4231_MCE)) - wss_outb(chip, CS4231P(REGSEL), - chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} -EXPORT_SYMBOL(snd_wss_mce_up); - -void snd_wss_mce_down(struct snd_wss *chip) -{ - unsigned long flags; - unsigned long end_time; - int timeout; - int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848; - - snd_wss_busy_wait(chip); - -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "mce_down [0x%lx] - " - "auto calibration time out (0)\n", - (long)CS4231P(REGSEL)); -#endif - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit &= ~CS4231_MCE; - timeout = wss_inb(chip, CS4231P(REGSEL)); - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (timeout == 0x80) - snd_printk(KERN_DEBUG "mce_down [0x%lx]: " - "serious init problem - codec still busy\n", - chip->port); - if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask)) - return; - - /* - * Wait for (possible -- during init auto-calibration may not be set) - * calibration process to start. Needs up to 5 sample periods on AD1848 - * which at the slowest possible rate of 5.5125 kHz means 907 us. - */ - msleep(1); - - snd_printdd("(1) jiffies = %lu\n", jiffies); - - /* check condition up to 250 ms */ - end_time = jiffies + msecs_to_jiffies(250); - while (snd_wss_in(chip, CS4231_TEST_INIT) & - CS4231_CALIB_IN_PROGRESS) { - - if (time_after(jiffies, end_time)) { - snd_printk(KERN_ERR "mce_down - " - "auto calibration time out (2)\n"); - return; - } - msleep(1); - } - - snd_printdd("(2) jiffies = %lu\n", jiffies); - - /* check condition up to 100 ms */ - end_time = jiffies + msecs_to_jiffies(100); - while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { - if (time_after(jiffies, end_time)) { - snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); - return; - } - msleep(1); - } - - snd_printdd("(3) jiffies = %lu\n", jiffies); - snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL))); -} -EXPORT_SYMBOL(snd_wss_mce_down); - -static unsigned int snd_wss_get_count(unsigned char format, unsigned int size) -{ - switch (format & 0xe0) { - case CS4231_LINEAR_16: - case CS4231_LINEAR_16_BIG: - size >>= 1; - break; - case CS4231_ADPCM_16: - return size >> 2; - } - if (format & CS4231_STEREO) - size >>= 1; - return size; -} - -static int snd_wss_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - int result = 0; - unsigned int what; - struct snd_pcm_substream *s; - int do_start; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - do_start = 1; break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - do_start = 0; break; - default: - return -EINVAL; - } - - what = 0; - snd_pcm_group_for_each_entry(s, substream) { - if (s == chip->playback_substream) { - what |= CS4231_PLAYBACK_ENABLE; - snd_pcm_trigger_done(s, substream); - } else if (s == chip->capture_substream) { - what |= CS4231_RECORD_ENABLE; - snd_pcm_trigger_done(s, substream); - } - } - spin_lock(&chip->reg_lock); - if (do_start) { - chip->image[CS4231_IFACE_CTRL] |= what; - if (chip->trigger) - chip->trigger(chip, what, 1); - } else { - chip->image[CS4231_IFACE_CTRL] &= ~what; - if (chip->trigger) - chip->trigger(chip, what, 0); - } - snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - spin_unlock(&chip->reg_lock); -#if 0 - snd_wss_debug(chip); -#endif - return result; -} - -/* - * CODEC I/O - */ - -static unsigned char snd_wss_get_rate(unsigned int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(rates); i++) - if (rate == rates[i]) - return freq_bits[i]; - // snd_BUG(); - return freq_bits[ARRAY_SIZE(rates) - 1]; -} - -static unsigned char snd_wss_get_format(struct snd_wss *chip, - int format, - int channels) -{ - unsigned char rformat; - - rformat = CS4231_LINEAR_8; - switch (format) { - case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break; - case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break; - case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break; - case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break; - case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break; - } - if (channels > 1) - rformat |= CS4231_STEREO; -#if 0 - snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode); -#endif - return rformat; -} - -static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) -{ - unsigned long flags; - - mute = mute ? 0x80 : 0; - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->calibrate_mute == mute) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return; - } - if (!mute) { - snd_wss_dout(chip, CS4231_LEFT_INPUT, - chip->image[CS4231_LEFT_INPUT]); - snd_wss_dout(chip, CS4231_RIGHT_INPUT, - chip->image[CS4231_RIGHT_INPUT]); - snd_wss_dout(chip, CS4231_LOOPBACK, - chip->image[CS4231_LOOPBACK]); - } else { - snd_wss_dout(chip, CS4231_LEFT_INPUT, - 0); - snd_wss_dout(chip, CS4231_RIGHT_INPUT, - 0); - snd_wss_dout(chip, CS4231_LOOPBACK, - 0xfd); - } - - snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, - mute | chip->image[CS4231_AUX1_LEFT_INPUT]); - snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, - mute | chip->image[CS4231_AUX1_RIGHT_INPUT]); - snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT, - mute | chip->image[CS4231_AUX2_LEFT_INPUT]); - snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT, - mute | chip->image[CS4231_AUX2_RIGHT_INPUT]); - snd_wss_dout(chip, CS4231_LEFT_OUTPUT, - mute | chip->image[CS4231_LEFT_OUTPUT]); - snd_wss_dout(chip, CS4231_RIGHT_OUTPUT, - mute | chip->image[CS4231_RIGHT_OUTPUT]); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) { - snd_wss_dout(chip, CS4231_LEFT_LINE_IN, - mute | chip->image[CS4231_LEFT_LINE_IN]); - snd_wss_dout(chip, CS4231_RIGHT_LINE_IN, - mute | chip->image[CS4231_RIGHT_LINE_IN]); - snd_wss_dout(chip, CS4231_MONO_CTRL, - mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); - } - if (chip->hardware == WSS_HW_INTERWAVE) { - snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT, - mute | chip->image[CS4231_LEFT_MIC_INPUT]); - snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT, - mute | chip->image[CS4231_RIGHT_MIC_INPUT]); - snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT, - mute | chip->image[CS4231_LINE_LEFT_OUTPUT]); - snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT, - mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]); - } - chip->calibrate_mute = mute; - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_wss_playback_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char pdfr) -{ - unsigned long flags; - int full_calib = 1; - - mutex_lock(&chip->mce_mutex); - if (chip->hardware == WSS_HW_CS4231A || - (chip->hardware & WSS_HW_CS4232_MASK)) { - spin_lock_irqsave(&chip->reg_lock, flags); - if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */ - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | 0x10); - chip->image[CS4231_PLAYBK_FORMAT] = pdfr; - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, - chip->image[CS4231_PLAYBK_FORMAT]); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] &= ~0x10); - udelay(100); /* Fixes audible clicks at least on GUS MAX */ - full_calib = 0; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - } else if (chip->hardware == WSS_HW_AD1845) { - unsigned rate = params_rate(params); - - /* - * Program the AD1845 correctly for the playback stream. - * Note that we do NOT need to toggle the MCE bit because - * the PLAYBACK_ENABLE bit of the Interface Configuration - * register is set. - * - * NOTE: We seem to need to write to the MSB before the LSB - * to get the correct sample frequency. - */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0)); - snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); - snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); - full_calib = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - } - if (full_calib) { - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) { - if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) - pdfr = (pdfr & 0xf0) | - (chip->image[CS4231_REC_FORMAT] & 0x0f); - } else { - chip->image[CS4231_PLAYBK_FORMAT] = pdfr; - } - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (chip->hardware == WSS_HW_OPL3SA2) - udelay(100); /* this seems to help */ - snd_wss_mce_down(chip); - } - mutex_unlock(&chip->mce_mutex); -} - -static void snd_wss_capture_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char cdfr) -{ - unsigned long flags; - int full_calib = 1; - - mutex_lock(&chip->mce_mutex); - if (chip->hardware == WSS_HW_CS4231A || - (chip->hardware & WSS_HW_CS4232_MASK)) { - spin_lock_irqsave(&chip->reg_lock, flags); - if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */ - (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) { - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | 0x20); - snd_wss_out(chip, CS4231_REC_FORMAT, - chip->image[CS4231_REC_FORMAT] = cdfr); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] &= ~0x20); - full_calib = 0; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - } else if (chip->hardware == WSS_HW_AD1845) { - unsigned rate = params_rate(params); - - /* - * Program the AD1845 correctly for the capture stream. - * Note that we do NOT need to toggle the MCE bit because - * the PLAYBACK_ENABLE bit of the Interface Configuration - * register is set. - * - * NOTE: We seem to need to write to the MSB before the LSB - * to get the correct sample frequency. - */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0)); - snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); - snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); - full_calib = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - } - if (full_calib) { - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->hardware != WSS_HW_INTERWAVE && - !(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) { - if (chip->single_dma) - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr); - else - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, - (chip->image[CS4231_PLAYBK_FORMAT] & 0xf0) | - (cdfr & 0x0f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - } - if (chip->hardware & WSS_HW_AD1848_MASK) - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr); - else - snd_wss_out(chip, CS4231_REC_FORMAT, cdfr); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - } - mutex_unlock(&chip->mce_mutex); -} - -/* - * Timer interface - */ - -static unsigned long snd_wss_timer_resolution(struct snd_timer *timer) -{ - struct snd_wss *chip = snd_timer_chip(timer); - if (chip->hardware & WSS_HW_CS4236B_MASK) - return 14467; - else - return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920; -} - -static int snd_wss_timer_start(struct snd_timer *timer) -{ - unsigned long flags; - unsigned int ticks; - struct snd_wss *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); - ticks = timer->sticks; - if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 || - (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] || - (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) { - chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8); - snd_wss_out(chip, CS4231_TIMER_HIGH, - chip->image[CS4231_TIMER_HIGH]); - chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks; - snd_wss_out(chip, CS4231_TIMER_LOW, - chip->image[CS4231_TIMER_LOW]); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | - CS4231_TIMER_ENABLE); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_wss_timer_stop(struct snd_timer *timer) -{ - unsigned long flags; - struct snd_wss *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE; - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static void snd_wss_init(struct snd_wss *chip) -{ - unsigned long flags; - - snd_wss_calibrate_mute(chip, 1); - snd_wss_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (1)\n"); -#endif - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | - CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | - CS4231_RECORD_PIO | - CS4231_CALIB_MODE); - chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; - snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (2)\n"); -#endif - - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; - snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - snd_wss_out(chip, - CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n", - chip->image[CS4231_ALT_FEATURE_1]); -#endif - - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_ALT_FEATURE_2, - chip->image[CS4231_ALT_FEATURE_2]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, - chip->image[CS4231_PLAYBK_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (4)\n"); -#endif - - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - snd_wss_out(chip, CS4231_REC_FORMAT, - chip->image[CS4231_REC_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - snd_wss_calibrate_mute(chip, 0); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (5)\n"); -#endif -} - -static int snd_wss_open(struct snd_wss *chip, unsigned int mode) -{ - unsigned long flags; - - mutex_lock(&chip->open_mutex); - if ((chip->mode & mode) || - ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) { - mutex_unlock(&chip->open_mutex); - return -EAGAIN; - } - if (chip->mode & WSS_MODE_OPEN) { - chip->mode |= mode; - mutex_unlock(&chip->open_mutex); - return 0; - } - /* ok. now enable and ack CODEC IRQ */ - spin_lock_irqsave(&chip->reg_lock, flags); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) { - snd_wss_out(chip, CS4231_IRQ_STATUS, - CS4231_PLAYBACK_IRQ | - CS4231_RECORD_IRQ | - CS4231_TIMER_IRQ); - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); - } - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE; - snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) { - snd_wss_out(chip, CS4231_IRQ_STATUS, - CS4231_PLAYBACK_IRQ | - CS4231_RECORD_IRQ | - CS4231_TIMER_IRQ); - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - - chip->mode = mode; - mutex_unlock(&chip->open_mutex); - return 0; -} - -static void snd_wss_close(struct snd_wss *chip, unsigned int mode) -{ - unsigned long flags; - - mutex_lock(&chip->open_mutex); - chip->mode &= ~mode; - if (chip->mode & WSS_MODE_OPEN) { - mutex_unlock(&chip->open_mutex); - return; - } - /* disable IRQ */ - spin_lock_irqsave(&chip->reg_lock, flags); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE; - snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); - - /* now disable record & playback */ - - if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); - snd_wss_out(chip, CS4231_IFACE_CTRL, - chip->image[CS4231_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - } - - /* clear IRQ again */ - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - spin_unlock_irqrestore(&chip->reg_lock, flags); - - chip->mode = 0; - mutex_unlock(&chip->open_mutex); -} - -/* - * timer open/close - */ - -static int snd_wss_timer_open(struct snd_timer *timer) -{ - struct snd_wss *chip = snd_timer_chip(timer); - snd_wss_open(chip, WSS_MODE_TIMER); - return 0; -} - -static int snd_wss_timer_close(struct snd_timer *timer) -{ - struct snd_wss *chip = snd_timer_chip(timer); - snd_wss_close(chip, WSS_MODE_TIMER); - return 0; -} - -static struct snd_timer_hardware snd_wss_timer_table = -{ - .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 9945, - .ticks = 65535, - .open = snd_wss_timer_open, - .close = snd_wss_timer_close, - .c_resolution = snd_wss_timer_resolution, - .start = snd_wss_timer_start, - .stop = snd_wss_timer_stop, -}; - -/* - * ok.. exported functions.. - */ - -static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - unsigned char new_pdfr; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - new_pdfr = snd_wss_get_format(chip, params_format(hw_params), - params_channels(hw_params)) | - snd_wss_get_rate(params_rate(hw_params)); - chip->set_playback_format(chip, hw_params, new_pdfr); - return 0; -} - -static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_wss_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - spin_lock_irqsave(&chip->reg_lock, flags); - chip->p_dma_size = size; - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO); - snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1; - snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); - snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); -#if 0 - snd_wss_debug(chip); -#endif - return 0; -} - -static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - unsigned char new_cdfr; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - new_cdfr = snd_wss_get_format(chip, params_format(hw_params), - params_channels(hw_params)) | - snd_wss_get_rate(params_rate(hw_params)); - chip->set_capture_format(chip, hw_params, new_cdfr); - return 0; -} - -static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_wss_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - spin_lock_irqsave(&chip->reg_lock, flags); - chip->c_dma_size = size; - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); - snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - if (chip->hardware & WSS_HW_AD1848_MASK) - count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], - count); - else - count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT], - count); - count--; - if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { - snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); - snd_wss_out(chip, CS4231_PLY_UPR_CNT, - (unsigned char) (count >> 8)); - } else { - snd_wss_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count); - snd_wss_out(chip, CS4231_REC_UPR_CNT, - (unsigned char) (count >> 8)); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -void snd_wss_overrange(struct snd_wss *chip) -{ - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&chip->reg_lock, flags); - res = snd_wss_in(chip, CS4231_TEST_INIT); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */ - chip->capture_substream->runtime->overrange++; -} -EXPORT_SYMBOL(snd_wss_overrange); - -irqreturn_t snd_wss_interrupt(int irq, void *dev_id) -{ - struct snd_wss *chip = dev_id; - unsigned char status; - - if (chip->hardware & WSS_HW_AD1848_MASK) - /* pretend it was the only possible irq for AD1848 */ - status = CS4231_PLAYBACK_IRQ; - else - status = snd_wss_in(chip, CS4231_IRQ_STATUS); - if (status & CS4231_TIMER_IRQ) { - if (chip->timer) - snd_timer_interrupt(chip->timer, chip->timer->sticks); - } - if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { - if (status & CS4231_PLAYBACK_IRQ) { - if (chip->mode & WSS_MODE_PLAY) { - if (chip->playback_substream) - snd_pcm_period_elapsed(chip->playback_substream); - } - if (chip->mode & WSS_MODE_RECORD) { - if (chip->capture_substream) { - snd_wss_overrange(chip); - snd_pcm_period_elapsed(chip->capture_substream); - } - } - } - } else { - if (status & CS4231_PLAYBACK_IRQ) { - if (chip->playback_substream) - snd_pcm_period_elapsed(chip->playback_substream); - } - if (status & CS4231_RECORD_IRQ) { - if (chip->capture_substream) { - snd_wss_overrange(chip); - snd_pcm_period_elapsed(chip->capture_substream); - } - } - } - - spin_lock(&chip->reg_lock); - status = ~CS4231_ALL_IRQS | ~status; - if (chip->hardware & WSS_HW_AD1848_MASK) - wss_outb(chip, CS4231P(STATUS), 0); - else - snd_wss_out(chip, CS4231_IRQ_STATUS, status); - spin_unlock(&chip->reg_lock); - return IRQ_HANDLED; -} -EXPORT_SYMBOL(snd_wss_interrupt); - -static snd_pcm_uframes_t snd_wss_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) - return 0; - ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) - return 0; - ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -/* - - */ - -static int snd_ad1848_probe(struct snd_wss *chip) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - unsigned long flags; - unsigned char r; - unsigned short hardware = 0; - int err = 0; - int i; - - while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { - if (time_after(jiffies, timeout)) - return -ENODEV; - cond_resched(); - } - spin_lock_irqsave(&chip->reg_lock, flags); - - /* set CS423x MODE 1 */ - snd_wss_dout(chip, CS4231_MISC_INFO, 0); - - snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */ - r = snd_wss_in(chip, CS4231_RIGHT_INPUT); - if (r != 0x45) { - /* RMGE always high on AD1847 */ - if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) { - err = -ENODEV; - goto out; - } - hardware = WSS_HW_AD1847; - } else { - snd_wss_dout(chip, CS4231_LEFT_INPUT, 0xaa); - r = snd_wss_in(chip, CS4231_LEFT_INPUT); - /* L/RMGE always low on AT2320 */ - if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) { - err = -ENODEV; - goto out; - } - } - - /* clear pending IRQ */ - wss_inb(chip, CS4231P(STATUS)); - wss_outb(chip, CS4231P(STATUS), 0); - mb(); - - if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT) - goto out; - - if (hardware) { - chip->hardware = hardware; - goto out; - } - - r = snd_wss_in(chip, CS4231_MISC_INFO); - - /* set CS423x MODE 2 */ - snd_wss_dout(chip, CS4231_MISC_INFO, CS4231_MODE2); - for (i = 0; i < 16; i++) { - if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) { - /* we have more than 16 registers: check ID */ - if ((r & 0xf) != 0xa) - goto out_mode; - /* - * on CMI8330, CS4231_VERSION is volume control and - * can be set to 0 - */ - snd_wss_dout(chip, CS4231_VERSION, 0); - r = snd_wss_in(chip, CS4231_VERSION) & 0xe7; - if (!r) - chip->hardware = WSS_HW_CMI8330; - goto out_mode; - } - } - if (r & 0x80) - chip->hardware = WSS_HW_CS4248; - else - chip->hardware = WSS_HW_AD1848; -out_mode: - snd_wss_dout(chip, CS4231_MISC_INFO, 0); -out: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return err; -} - -static int snd_wss_probe(struct snd_wss *chip) -{ - unsigned long flags; - int i, id, rev, regnum; - unsigned char *ptr; - unsigned int hw; - - id = snd_ad1848_probe(chip); - if (id < 0) - return id; - - hw = chip->hardware; - if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { - for (i = 0; i < 50; i++) { - mb(); - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - msleep(2); - else { - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_MISC_INFO, - CS4231_MODE2); - id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (id == 0x0a) - break; /* this is valid value */ - } - } - snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); - if (id != 0x0a) - return -ENODEV; /* no valid device found */ - - rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; - snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev); - if (rev == 0x80) { - unsigned char tmp = snd_wss_in(chip, 23); - snd_wss_out(chip, 23, ~tmp); - if (snd_wss_in(chip, 23) != tmp) - chip->hardware = WSS_HW_AD1845; - else - chip->hardware = WSS_HW_CS4231; - } else if (rev == 0xa0) { - chip->hardware = WSS_HW_CS4231A; - } else if (rev == 0xa2) { - chip->hardware = WSS_HW_CS4232; - } else if (rev == 0xb2) { - chip->hardware = WSS_HW_CS4232A; - } else if (rev == 0x83) { - chip->hardware = WSS_HW_CS4236; - } else if (rev == 0x03) { - chip->hardware = WSS_HW_CS4236B; - } else { - snd_printk(KERN_ERR - "unknown CS chip with version 0x%x\n", rev); - return -ENODEV; /* unknown CS4231 chip? */ - } - } - spin_lock_irqsave(&chip->reg_lock, flags); - wss_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); - mb(); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - chip->image[CS4231_MISC_INFO] = CS4231_MODE2; - switch (chip->hardware) { - case WSS_HW_INTERWAVE: - chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3; - break; - case WSS_HW_CS4235: - case WSS_HW_CS4236B: - case WSS_HW_CS4237B: - case WSS_HW_CS4238B: - case WSS_HW_CS4239: - if (hw == WSS_HW_DETECT3) - chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3; - else - chip->hardware = WSS_HW_CS4236; - break; - } - - chip->image[CS4231_IFACE_CTRL] = - (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) | - (chip->single_dma ? CS4231_SINGLE_DMA : 0); - if (chip->hardware != WSS_HW_OPTI93X) { - chip->image[CS4231_ALT_FEATURE_1] = 0x80; - chip->image[CS4231_ALT_FEATURE_2] = - chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; - } - /* enable fine grained frequency selection */ - if (chip->hardware == WSS_HW_AD1845) - chip->image[AD1845_PWR_DOWN] = 8; - - ptr = (unsigned char *) &chip->image; - regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; - snd_wss_mce_down(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (i = 0; i < regnum; i++) /* ok.. fill all registers */ - snd_wss_out(chip, i, *ptr++); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_up(chip); - snd_wss_mce_down(chip); - - mdelay(2); - - /* ok.. try check hardware version for CS4236+ chips */ - if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { - if (chip->hardware == WSS_HW_CS4236B) { - rev = snd_cs4236_ext_in(chip, CS4236_VERSION); - snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff); - id = snd_cs4236_ext_in(chip, CS4236_VERSION); - snd_cs4236_ext_out(chip, CS4236_VERSION, rev); - snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id); - if ((id & 0x1f) == 0x1d) { /* CS4235 */ - chip->hardware = WSS_HW_CS4235; - switch (id >> 5) { - case 4: - case 5: - case 6: - break; - default: - snd_printk(KERN_WARNING - "unknown CS4235 chip " - "(enhanced version = 0x%x)\n", - id); - } - } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */ - switch (id >> 5) { - case 4: - case 5: - case 6: - case 7: - chip->hardware = WSS_HW_CS4236B; - break; - default: - snd_printk(KERN_WARNING - "unknown CS4236 chip " - "(enhanced version = 0x%x)\n", - id); - } - } else if ((id & 0x1f) == 0x08) { /* CS4237B */ - chip->hardware = WSS_HW_CS4237B; - switch (id >> 5) { - case 4: - case 5: - case 6: - case 7: - break; - default: - snd_printk(KERN_WARNING - "unknown CS4237B chip " - "(enhanced version = 0x%x)\n", - id); - } - } else if ((id & 0x1f) == 0x09) { /* CS4238B */ - chip->hardware = WSS_HW_CS4238B; - switch (id >> 5) { - case 5: - case 6: - case 7: - break; - default: - snd_printk(KERN_WARNING - "unknown CS4238B chip " - "(enhanced version = 0x%x)\n", - id); - } - } else if ((id & 0x1f) == 0x1e) { /* CS4239 */ - chip->hardware = WSS_HW_CS4239; - switch (id >> 5) { - case 4: - case 5: - case 6: - break; - default: - snd_printk(KERN_WARNING - "unknown CS4239 chip " - "(enhanced version = 0x%x)\n", - id); - } - } else { - snd_printk(KERN_WARNING - "unknown CS4236/CS423xB chip " - "(enhanced version = 0x%x)\n", id); - } - } - } - return 0; /* all things are ok.. */ -} - -/* - - */ - -static struct snd_pcm_hardware snd_wss_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5510, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_wss_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5510, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - - */ - -static int snd_wss_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - runtime->hw = snd_wss_playback; - - /* hardware limitation of older chipsets */ - if (chip->hardware & WSS_HW_AD1848_MASK) - runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_S16_BE); - - /* hardware bug in InterWave chipset */ - if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3) - runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW; - - /* hardware limitation of cheap chips */ - if (chip->hardware == WSS_HW_CS4235 || - chip->hardware == WSS_HW_CS4239) - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE; - - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); - - if (chip->claim_dma) { - if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0) - return err; - } - - err = snd_wss_open(chip, WSS_MODE_PLAY); - if (err < 0) { - if (chip->release_dma) - chip->release_dma(chip, chip->dma_private_data, chip->dma1); - snd_free_pages(runtime->dma_area, runtime->dma_bytes); - return err; - } - chip->playback_substream = substream; - snd_pcm_set_sync(substream); - chip->rate_constraint(runtime); - return 0; -} - -static int snd_wss_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - runtime->hw = snd_wss_capture; - - /* hardware limitation of older chipsets */ - if (chip->hardware & WSS_HW_AD1848_MASK) - runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_S16_BE); - - /* hardware limitation of cheap chips */ - if (chip->hardware == WSS_HW_CS4235 || - chip->hardware == WSS_HW_CS4239 || - chip->hardware == WSS_HW_OPTI93X) - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE; - - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); - - if (chip->claim_dma) { - if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0) - return err; - } - - err = snd_wss_open(chip, WSS_MODE_RECORD); - if (err < 0) { - if (chip->release_dma) - chip->release_dma(chip, chip->dma_private_data, chip->dma2); - snd_free_pages(runtime->dma_area, runtime->dma_bytes); - return err; - } - chip->capture_substream = substream; - snd_pcm_set_sync(substream); - chip->rate_constraint(runtime); - return 0; -} - -static int snd_wss_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - snd_wss_close(chip, WSS_MODE_PLAY); - return 0; -} - -static int snd_wss_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - snd_wss_close(chip, WSS_MODE_RECORD); - return 0; -} - -static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on) -{ - int tmp; - - if (!chip->thinkpad_flag) - return; - - outb(0x1c, AD1848_THINKPAD_CTL_PORT1); - tmp = inb(AD1848_THINKPAD_CTL_PORT2); - - if (on) - /* turn it on */ - tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT; - else - /* turn it off */ - tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT; - - outb(tmp, AD1848_THINKPAD_CTL_PORT2); -} - -#ifdef CONFIG_PM - -/* lowlevel suspend callback for CS4231 */ -static void snd_wss_suspend(struct snd_wss *chip) -{ - int reg; - unsigned long flags; - - snd_pcm_suspend_all(chip->pcm); - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) - chip->image[reg] = snd_wss_in(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (chip->thinkpad_flag) - snd_wss_thinkpad_twiddle(chip, 0); -} - -/* lowlevel resume callback for CS4231 */ -static void snd_wss_resume(struct snd_wss *chip) -{ - int reg; - unsigned long flags; - /* int timeout; */ - - if (chip->thinkpad_flag) - snd_wss_thinkpad_twiddle(chip, 1); - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) { - switch (reg) { - case CS4231_VERSION: - break; - default: - snd_wss_out(chip, reg, chip->image[reg]); - break; - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); -#if 1 - snd_wss_mce_down(chip); -#else - /* The following is a workaround to avoid freeze after resume on TP600E. - This is the first half of copy of snd_wss_mce_down(), but doesn't - include rescheduling. -- iwai - */ - snd_wss_busy_wait(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit &= ~CS4231_MCE; - timeout = wss_inb(chip, CS4231P(REGSEL)); - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (timeout == 0x80) - snd_printk(KERN_ERR "down [0x%lx]: serious init problem " - "- codec still busy\n", chip->port); - if ((timeout & CS4231_MCE) == 0 || - !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { - return; - } - snd_wss_busy_wait(chip); -#endif -} -#endif /* CONFIG_PM */ - -static int snd_wss_free(struct snd_wss *chip) -{ - release_and_free_resource(chip->res_port); - release_and_free_resource(chip->res_cport); - if (chip->irq >= 0) { - disable_irq(chip->irq); - if (!(chip->hwshare & WSS_HWSHARE_IRQ)) - free_irq(chip->irq, (void *) chip); - } - if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) { - snd_dma_disable(chip->dma1); - free_dma(chip->dma1); - } - if (!(chip->hwshare & WSS_HWSHARE_DMA2) && - chip->dma2 >= 0 && chip->dma2 != chip->dma1) { - snd_dma_disable(chip->dma2); - free_dma(chip->dma2); - } - if (chip->timer) - snd_device_free(chip->card, chip->timer); - kfree(chip); - return 0; -} - -static int snd_wss_dev_free(struct snd_device *device) -{ - struct snd_wss *chip = device->device_data; - return snd_wss_free(chip); -} - -const char *snd_wss_chip_id(struct snd_wss *chip) -{ - switch (chip->hardware) { - case WSS_HW_CS4231: - return "CS4231"; - case WSS_HW_CS4231A: - return "CS4231A"; - case WSS_HW_CS4232: - return "CS4232"; - case WSS_HW_CS4232A: - return "CS4232A"; - case WSS_HW_CS4235: - return "CS4235"; - case WSS_HW_CS4236: - return "CS4236"; - case WSS_HW_CS4236B: - return "CS4236B"; - case WSS_HW_CS4237B: - return "CS4237B"; - case WSS_HW_CS4238B: - return "CS4238B"; - case WSS_HW_CS4239: - return "CS4239"; - case WSS_HW_INTERWAVE: - return "AMD InterWave"; - case WSS_HW_OPL3SA2: - return chip->card->shortname; - case WSS_HW_AD1845: - return "AD1845"; - case WSS_HW_OPTI93X: - return "OPTi 93x"; - case WSS_HW_AD1847: - return "AD1847"; - case WSS_HW_AD1848: - return "AD1848"; - case WSS_HW_CS4248: - return "CS4248"; - case WSS_HW_CMI8330: - return "CMI8330/C3D"; - default: - return "???"; - } -} -EXPORT_SYMBOL(snd_wss_chip_id); - -static int snd_wss_new(struct snd_card *card, - unsigned short hardware, - unsigned short hwshare, - struct snd_wss **rchip) -{ - struct snd_wss *chip; - - *rchip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - chip->hardware = hardware; - chip->hwshare = hwshare; - - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->mce_mutex); - mutex_init(&chip->open_mutex); - chip->card = card; - chip->rate_constraint = snd_wss_xrate; - chip->set_playback_format = snd_wss_playback_format; - chip->set_capture_format = snd_wss_capture_format; - if (chip->hardware == WSS_HW_OPTI93X) - memcpy(&chip->image, &snd_opti93x_original_image, - sizeof(snd_opti93x_original_image)); - else - memcpy(&chip->image, &snd_wss_original_image, - sizeof(snd_wss_original_image)); - if (chip->hardware & WSS_HW_AD1848_MASK) { - chip->image[CS4231_PIN_CTRL] = 0; - chip->image[CS4231_TEST_INIT] = 0; - } - - *rchip = chip; - return 0; -} - -int snd_wss_create(struct snd_card *card, - unsigned long port, - unsigned long cport, - int irq, int dma1, int dma2, - unsigned short hardware, - unsigned short hwshare, - struct snd_wss **rchip) -{ - static struct snd_device_ops ops = { - .dev_free = snd_wss_dev_free, - }; - struct snd_wss *chip; - int err; - - err = snd_wss_new(card, hardware, hwshare, &chip); - if (err < 0) - return err; - - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - - chip->res_port = request_region(port, 4, "WSS"); - if (!chip->res_port) { - snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port); - snd_wss_free(chip); - return -EBUSY; - } - chip->port = port; - if ((long)cport >= 0) { - chip->res_cport = request_region(cport, 8, "CS4232 Control"); - if (!chip->res_cport) { - snd_printk(KERN_ERR - "wss: can't grab control port 0x%lx\n", cport); - snd_wss_free(chip); - return -ENODEV; - } - } - chip->cport = cport; - if (!(hwshare & WSS_HWSHARE_IRQ)) - if (request_irq(irq, snd_wss_interrupt, 0, - "WSS", (void *) chip)) { - snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); - snd_wss_free(chip); - return -EBUSY; - } - chip->irq = irq; - if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) { - snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1); - snd_wss_free(chip); - return -EBUSY; - } - chip->dma1 = dma1; - if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && - dma2 >= 0 && request_dma(dma2, "WSS - 2")) { - snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2); - snd_wss_free(chip); - return -EBUSY; - } - if (dma1 == dma2 || dma2 < 0) { - chip->single_dma = 1; - chip->dma2 = chip->dma1; - } else - chip->dma2 = dma2; - - if (hardware == WSS_HW_THINKPAD) { - chip->thinkpad_flag = 1; - chip->hardware = WSS_HW_DETECT; /* reset */ - snd_wss_thinkpad_twiddle(chip, 1); - } - - /* global setup */ - if (snd_wss_probe(chip) < 0) { - snd_wss_free(chip); - return -ENODEV; - } - snd_wss_init(chip); - -#if 0 - if (chip->hardware & WSS_HW_CS4232_MASK) { - if (chip->res_cport == NULL) - snd_printk(KERN_ERR "CS4232 control port features are " - "not accessible\n"); - } -#endif - - /* Register device */ - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_wss_free(chip); - return err; - } - -#ifdef CONFIG_PM - /* Power Management */ - chip->suspend = snd_wss_suspend; - chip->resume = snd_wss_resume; -#endif - - *rchip = chip; - return 0; -} -EXPORT_SYMBOL(snd_wss_create); - -static struct snd_pcm_ops snd_wss_playback_ops = { - .open = snd_wss_playback_open, - .close = snd_wss_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_wss_playback_hw_params, - .hw_free = snd_wss_playback_hw_free, - .prepare = snd_wss_playback_prepare, - .trigger = snd_wss_trigger, - .pointer = snd_wss_playback_pointer, -}; - -static struct snd_pcm_ops snd_wss_capture_ops = { - .open = snd_wss_capture_open, - .close = snd_wss_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_wss_capture_hw_params, - .hw_free = snd_wss_capture_hw_free, - .prepare = snd_wss_capture_prepare, - .trigger = snd_wss_trigger, - .pointer = snd_wss_capture_pointer, -}; - -int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); - - /* global setup */ - pcm->private_data = chip; - pcm->info_flags = 0; - if (chip->single_dma) - pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX; - if (chip->hardware != WSS_HW_INTERWAVE) - pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX; - strcpy(pcm->name, snd_wss_chip_id(chip)); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); - - chip->pcm = pcm; - if (rpcm) - *rpcm = pcm; - return 0; -} -EXPORT_SYMBOL(snd_wss_pcm); - -static void snd_wss_timer_free(struct snd_timer *timer) -{ - struct snd_wss *chip = timer->private_data; - chip->timer = NULL; -} - -int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer) -{ - struct snd_timer *timer; - struct snd_timer_id tid; - int err; - - /* Timer initialization */ - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = chip->card->number; - tid.device = device; - tid.subdevice = 0; - if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0) - return err; - strcpy(timer->name, snd_wss_chip_id(chip)); - timer->private_data = chip; - timer->private_free = snd_wss_timer_free; - timer->hw = snd_wss_timer_table; - chip->timer = timer; - if (rtimer) - *rtimer = timer; - return 0; -} -EXPORT_SYMBOL(snd_wss_timer); - -/* - * MIXER part - */ - -static int snd_wss_info_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { - "Line", "Aux", "Mic", "Mix" - }; - static char *opl3sa_texts[4] = { - "Line", "CD", "Mic", "Mix" - }; - static char *gusmax_texts[4] = { - "Line", "Synth", "Mic", "Mix" - }; - char **ptexts = texts; - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - - if (snd_BUG_ON(!chip->card)) - return -EINVAL; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - if (!strcmp(chip->card->driver, "GUS MAX")) - ptexts = gusmax_texts; - switch (chip->hardware) { - case WSS_HW_INTERWAVE: - ptexts = gusmax_texts; - break; - case WSS_HW_OPTI93X: - case WSS_HW_OPL3SA2: - ptexts = opl3sa_texts; - break; - } - strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_wss_get_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; - ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6; - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_wss_put_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned short left, right; - int change; - - if (ucontrol->value.enumerated.item[0] > 3 || - ucontrol->value.enumerated.item[1] > 3) - return -EINVAL; - left = ucontrol->value.enumerated.item[0] << 6; - right = ucontrol->value.enumerated.item[1] << 6; - spin_lock_irqsave(&chip->reg_lock, flags); - left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; - right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; - change = left != chip->image[CS4231_LEFT_INPUT] || - right != chip->image[CS4231_RIGHT_INPUT]; - snd_wss_out(chip, CS4231_LEFT_INPUT, left); - snd_wss_out(chip, CS4231_RIGHT_INPUT, right); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -int snd_wss_info_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} -EXPORT_SYMBOL(snd_wss_info_single); - -int snd_wss_get_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} -EXPORT_SYMBOL(snd_wss_get_single); - -int snd_wss_put_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->image[reg] & ~(mask << shift)) | val; - change = val != chip->image[reg]; - snd_wss_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} -EXPORT_SYMBOL(snd_wss_put_single); - -int snd_wss_info_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} -EXPORT_SYMBOL(snd_wss_info_double); - -int snd_wss_get_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} -EXPORT_SYMBOL(snd_wss_get_double); - -int snd_wss_put_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; - val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; - change = val1 != chip->image[left_reg] || - val2 != chip->image[right_reg]; - snd_wss_out(chip, left_reg, val1); - snd_wss_out(chip, right_reg, val2); - } else { - mask = (mask << shift_left) | (mask << shift_right); - val1 = (chip->image[left_reg] & ~mask) | val1 | val2; - change = val1 != chip->image[left_reg]; - snd_wss_out(chip, left_reg, val1); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} -EXPORT_SYMBOL(snd_wss_put_double); - -static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); - -static struct snd_kcontrol_new snd_wss_controls[] = { -WSS_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), -WSS_DOUBLE("Aux Playback Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Aux Playback Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("Aux Playback Switch", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Aux Playback Volume", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, - 0, 0, 15, 0, db_scale_rec_gain), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_wss_info_mux, - .get = snd_wss_get_mux, - .put = snd_wss_put_mux, -}, -WSS_DOUBLE("Mic Boost (+20dB)", 0, - CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), -WSS_SINGLE("Loopback Capture Switch", 0, - CS4231_LOOPBACK, 0, 1, 0), -WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1, - db_scale_6bit), -WSS_DOUBLE("Line Playback Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Line Playback Volume", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_SINGLE("Beep Playback Switch", 0, - CS4231_MONO_CTRL, 7, 1, 1), -WSS_SINGLE_TLV("Beep Playback Volume", 0, - CS4231_MONO_CTRL, 0, 15, 1, - db_scale_4bit), -WSS_SINGLE("Mono Output Playback Switch", 0, - CS4231_MONO_CTRL, 6, 1, 1), -WSS_SINGLE("Beep Bypass Playback Switch", 0, - CS4231_MONO_CTRL, 5, 1, 0), -}; - -int snd_wss_mixer(struct snd_wss *chip) -{ - struct snd_card *card; - unsigned int idx; - int err; - int count = ARRAY_SIZE(snd_wss_controls); - - if (snd_BUG_ON(!chip || !chip->pcm)) - return -EINVAL; - - card = chip->card; - - strcpy(card->mixername, chip->pcm->name); - - /* Use only the first 11 entries on AD1848 */ - if (chip->hardware & WSS_HW_AD1848_MASK) - count = 11; - /* There is no loopback on OPTI93X */ - else if (chip->hardware == WSS_HW_OPTI93X) - count = 9; - - for (idx = 0; idx < count; idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_wss_controls[idx], - chip)); - if (err < 0) - return err; - } - return 0; -} -EXPORT_SYMBOL(snd_wss_mixer); - -const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction) -{ - return direction == SNDRV_PCM_STREAM_PLAYBACK ? - &snd_wss_playback_ops : &snd_wss_capture_ops; -} -EXPORT_SYMBOL(snd_wss_get_pcm_ops); - -/* - * INIT part - */ - -static int __init alsa_wss_init(void) -{ - return 0; -} - -static void __exit alsa_wss_exit(void) -{ -} - -module_init(alsa_wss_init); -module_exit(alsa_wss_exit); diff --git a/ANDROID_3.4.5/sound/last.c b/ANDROID_3.4.5/sound/last.c deleted file mode 100644 index 7ffc182e..00000000 --- a/ANDROID_3.4.5/sound/last.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Advanced Linux Sound Architecture - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -#define SNDRV_MAIN_OBJECT_FILE -#include -#include - -static int __init alsa_sound_last_init(void) -{ - int idx, ok = 0; - - printk(KERN_INFO "ALSA device list:\n"); - for (idx = 0; idx < SNDRV_CARDS; idx++) - if (snd_cards[idx] != NULL) { - printk(KERN_INFO " #%i: %s\n", idx, snd_cards[idx]->longname); - ok++; - } - if (ok == 0) - printk(KERN_INFO " No soundcards found.\n"); - return 0; -} - -late_initcall_sync(alsa_sound_last_init); diff --git a/ANDROID_3.4.5/sound/mips/Kconfig b/ANDROID_3.4.5/sound/mips/Kconfig deleted file mode 100644 index d2f615ab..00000000 --- a/ANDROID_3.4.5/sound/mips/Kconfig +++ /dev/null @@ -1,37 +0,0 @@ -# ALSA MIPS drivers - -menuconfig SND_MIPS - bool "MIPS sound devices" - depends on MIPS - default y - help - Support for sound devices of MIPS architectures. - -if SND_MIPS - -config SND_SGI_O2 - tristate "SGI O2 Audio" - depends on SGI_IP32 - help - Sound support for the SGI O2 Workstation. - -config SND_SGI_HAL2 - tristate "SGI HAL2 Audio" - depends on SGI_HAS_HAL2 - help - Sound support for the SGI Indy and Indigo2 Workstation. - - -config SND_AU1X00 - tristate "Au1x00 AC97 Port Driver (DEPRECATED)" - depends on MIPS_ALCHEMY - select SND_PCM - select SND_AC97_CODEC - help - ALSA Sound driver for the Au1x00's AC97 port. - - Newer drivers for ASoC are available, please do not use - this driver as it will be removed in the future. - -endif # SND_MIPS - diff --git a/ANDROID_3.4.5/sound/mips/Makefile b/ANDROID_3.4.5/sound/mips/Makefile deleted file mode 100644 index 861ec0a5..00000000 --- a/ANDROID_3.4.5/sound/mips/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ALSA -# - -snd-au1x00-objs := au1x00.o -snd-sgi-o2-objs := sgio2audio.o ad1843.o -snd-sgi-hal2-objs := hal2.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AU1X00) += snd-au1x00.o -obj-$(CONFIG_SND_SGI_O2) += snd-sgi-o2.o -obj-$(CONFIG_SND_SGI_HAL2) += snd-sgi-hal2.o diff --git a/ANDROID_3.4.5/sound/mips/ad1843.c b/ANDROID_3.4.5/sound/mips/ad1843.c deleted file mode 100644 index c624510e..00000000 --- a/ANDROID_3.4.5/sound/mips/ad1843.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * AD1843 low level driver - * - * Copyright 2003 Vivien Chappelier - * Copyright 2008 Thomas Bogendoerfer - * - * inspired from vwsnd.c (SGI VW audio driver) - * Copyright 1999 Silicon Graphics, Inc. All rights reserved. - * - * 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 - -/* - * AD1843 bitfield definitions. All are named as in the AD1843 data - * sheet, with ad1843_ prepended and individual bit numbers removed. - * - * E.g., bits LSS0 through LSS2 become ad1843_LSS. - * - * Only the bitfields we need are defined. - */ - -struct ad1843_bitfield { - char reg; - char lo_bit; - char nbits; -}; - -static const struct ad1843_bitfield - ad1843_PDNO = { 0, 14, 1 }, /* Converter Power-Down Flag */ - ad1843_INIT = { 0, 15, 1 }, /* Clock Initialization Flag */ - ad1843_RIG = { 2, 0, 4 }, /* Right ADC Input Gain */ - ad1843_RMGE = { 2, 4, 1 }, /* Right ADC Mic Gain Enable */ - ad1843_RSS = { 2, 5, 3 }, /* Right ADC Source Select */ - ad1843_LIG = { 2, 8, 4 }, /* Left ADC Input Gain */ - ad1843_LMGE = { 2, 12, 1 }, /* Left ADC Mic Gain Enable */ - ad1843_LSS = { 2, 13, 3 }, /* Left ADC Source Select */ - ad1843_RD2M = { 3, 0, 5 }, /* Right DAC 2 Mix Gain/Atten */ - ad1843_RD2MM = { 3, 7, 1 }, /* Right DAC 2 Mix Mute */ - ad1843_LD2M = { 3, 8, 5 }, /* Left DAC 2 Mix Gain/Atten */ - ad1843_LD2MM = { 3, 15, 1 }, /* Left DAC 2 Mix Mute */ - ad1843_RX1M = { 4, 0, 5 }, /* Right Aux 1 Mix Gain/Atten */ - ad1843_RX1MM = { 4, 7, 1 }, /* Right Aux 1 Mix Mute */ - ad1843_LX1M = { 4, 8, 5 }, /* Left Aux 1 Mix Gain/Atten */ - ad1843_LX1MM = { 4, 15, 1 }, /* Left Aux 1 Mix Mute */ - ad1843_RX2M = { 5, 0, 5 }, /* Right Aux 2 Mix Gain/Atten */ - ad1843_RX2MM = { 5, 7, 1 }, /* Right Aux 2 Mix Mute */ - ad1843_LX2M = { 5, 8, 5 }, /* Left Aux 2 Mix Gain/Atten */ - ad1843_LX2MM = { 5, 15, 1 }, /* Left Aux 2 Mix Mute */ - ad1843_RMCM = { 7, 0, 5 }, /* Right Mic Mix Gain/Atten */ - ad1843_RMCMM = { 7, 7, 1 }, /* Right Mic Mix Mute */ - ad1843_LMCM = { 7, 8, 5 }, /* Left Mic Mix Gain/Atten */ - ad1843_LMCMM = { 7, 15, 1 }, /* Left Mic Mix Mute */ - ad1843_HPOS = { 8, 4, 1 }, /* Headphone Output Voltage Swing */ - ad1843_HPOM = { 8, 5, 1 }, /* Headphone Output Mute */ - ad1843_MPOM = { 8, 6, 1 }, /* Mono Output Mute */ - ad1843_RDA1G = { 9, 0, 6 }, /* Right DAC1 Analog/Digital Gain */ - ad1843_RDA1GM = { 9, 7, 1 }, /* Right DAC1 Analog Mute */ - ad1843_LDA1G = { 9, 8, 6 }, /* Left DAC1 Analog/Digital Gain */ - ad1843_LDA1GM = { 9, 15, 1 }, /* Left DAC1 Analog Mute */ - ad1843_RDA2G = { 10, 0, 6 }, /* Right DAC2 Analog/Digital Gain */ - ad1843_RDA2GM = { 10, 7, 1 }, /* Right DAC2 Analog Mute */ - ad1843_LDA2G = { 10, 8, 6 }, /* Left DAC2 Analog/Digital Gain */ - ad1843_LDA2GM = { 10, 15, 1 }, /* Left DAC2 Analog Mute */ - ad1843_RDA1AM = { 11, 7, 1 }, /* Right DAC1 Digital Mute */ - ad1843_LDA1AM = { 11, 15, 1 }, /* Left DAC1 Digital Mute */ - ad1843_RDA2AM = { 12, 7, 1 }, /* Right DAC2 Digital Mute */ - ad1843_LDA2AM = { 12, 15, 1 }, /* Left DAC2 Digital Mute */ - ad1843_ADLC = { 15, 0, 2 }, /* ADC Left Sample Rate Source */ - ad1843_ADRC = { 15, 2, 2 }, /* ADC Right Sample Rate Source */ - ad1843_DA1C = { 15, 8, 2 }, /* DAC1 Sample Rate Source */ - ad1843_DA2C = { 15, 10, 2 }, /* DAC2 Sample Rate Source */ - ad1843_C1C = { 17, 0, 16 }, /* Clock 1 Sample Rate Select */ - ad1843_C2C = { 20, 0, 16 }, /* Clock 2 Sample Rate Select */ - ad1843_C3C = { 23, 0, 16 }, /* Clock 3 Sample Rate Select */ - ad1843_DAADL = { 25, 4, 2 }, /* Digital ADC Left Source Select */ - ad1843_DAADR = { 25, 6, 2 }, /* Digital ADC Right Source Select */ - ad1843_DAMIX = { 25, 14, 1 }, /* DAC Digital Mix Enable */ - ad1843_DRSFLT = { 25, 15, 1 }, /* Digital Reampler Filter Mode */ - ad1843_ADLF = { 26, 0, 2 }, /* ADC Left Channel Data Format */ - ad1843_ADRF = { 26, 2, 2 }, /* ADC Right Channel Data Format */ - ad1843_ADTLK = { 26, 4, 1 }, /* ADC Transmit Lock Mode Select */ - ad1843_SCF = { 26, 7, 1 }, /* SCLK Frequency Select */ - ad1843_DA1F = { 26, 8, 2 }, /* DAC1 Data Format Select */ - ad1843_DA2F = { 26, 10, 2 }, /* DAC2 Data Format Select */ - ad1843_DA1SM = { 26, 14, 1 }, /* DAC1 Stereo/Mono Mode Select */ - ad1843_DA2SM = { 26, 15, 1 }, /* DAC2 Stereo/Mono Mode Select */ - ad1843_ADLEN = { 27, 0, 1 }, /* ADC Left Channel Enable */ - ad1843_ADREN = { 27, 1, 1 }, /* ADC Right Channel Enable */ - ad1843_AAMEN = { 27, 4, 1 }, /* Analog to Analog Mix Enable */ - ad1843_ANAEN = { 27, 7, 1 }, /* Analog Channel Enable */ - ad1843_DA1EN = { 27, 8, 1 }, /* DAC1 Enable */ - ad1843_DA2EN = { 27, 9, 1 }, /* DAC2 Enable */ - ad1843_DDMEN = { 27, 12, 1 }, /* DAC2 to DAC1 Mix Enable */ - ad1843_C1EN = { 28, 11, 1 }, /* Clock Generator 1 Enable */ - ad1843_C2EN = { 28, 12, 1 }, /* Clock Generator 2 Enable */ - ad1843_C3EN = { 28, 13, 1 }, /* Clock Generator 3 Enable */ - ad1843_PDNI = { 28, 15, 1 }; /* Converter Power Down */ - -/* - * The various registers of the AD1843 use three different formats for - * specifying gain. The ad1843_gain structure parameterizes the - * formats. - */ - -struct ad1843_gain { - int negative; /* nonzero if gain is negative. */ - const struct ad1843_bitfield *lfield; - const struct ad1843_bitfield *rfield; - const struct ad1843_bitfield *lmute; - const struct ad1843_bitfield *rmute; -}; - -static const struct ad1843_gain ad1843_gain_RECLEV = { - .negative = 0, - .lfield = &ad1843_LIG, - .rfield = &ad1843_RIG -}; -static const struct ad1843_gain ad1843_gain_LINE = { - .negative = 1, - .lfield = &ad1843_LX1M, - .rfield = &ad1843_RX1M, - .lmute = &ad1843_LX1MM, - .rmute = &ad1843_RX1MM -}; -static const struct ad1843_gain ad1843_gain_LINE_2 = { - .negative = 1, - .lfield = &ad1843_LDA2G, - .rfield = &ad1843_RDA2G, - .lmute = &ad1843_LDA2GM, - .rmute = &ad1843_RDA2GM -}; -static const struct ad1843_gain ad1843_gain_MIC = { - .negative = 1, - .lfield = &ad1843_LMCM, - .rfield = &ad1843_RMCM, - .lmute = &ad1843_LMCMM, - .rmute = &ad1843_RMCMM -}; -static const struct ad1843_gain ad1843_gain_PCM_0 = { - .negative = 1, - .lfield = &ad1843_LDA1G, - .rfield = &ad1843_RDA1G, - .lmute = &ad1843_LDA1GM, - .rmute = &ad1843_RDA1GM -}; -static const struct ad1843_gain ad1843_gain_PCM_1 = { - .negative = 1, - .lfield = &ad1843_LD2M, - .rfield = &ad1843_RD2M, - .lmute = &ad1843_LD2MM, - .rmute = &ad1843_RD2MM -}; - -static const struct ad1843_gain *ad1843_gain[AD1843_GAIN_SIZE] = -{ - &ad1843_gain_RECLEV, - &ad1843_gain_LINE, - &ad1843_gain_LINE_2, - &ad1843_gain_MIC, - &ad1843_gain_PCM_0, - &ad1843_gain_PCM_1, -}; - -/* read the current value of an AD1843 bitfield. */ - -static int ad1843_read_bits(struct snd_ad1843 *ad1843, - const struct ad1843_bitfield *field) -{ - int w; - - w = ad1843->read(ad1843->chip, field->reg); - return w >> field->lo_bit & ((1 << field->nbits) - 1); -} - -/* - * write a new value to an AD1843 bitfield and return the old value. - */ - -static int ad1843_write_bits(struct snd_ad1843 *ad1843, - const struct ad1843_bitfield *field, - int newval) -{ - int w, mask, oldval, newbits; - - w = ad1843->read(ad1843->chip, field->reg); - mask = ((1 << field->nbits) - 1) << field->lo_bit; - oldval = (w & mask) >> field->lo_bit; - newbits = (newval << field->lo_bit) & mask; - w = (w & ~mask) | newbits; - ad1843->write(ad1843->chip, field->reg, w); - - return oldval; -} - -/* - * ad1843_read_multi reads multiple bitfields from the same AD1843 - * register. It uses a single read cycle to do it. (Reading the - * ad1843 requires 256 bit times at 12.288 MHz, or nearly 20 - * microseconds.) - * - * Called like this. - * - * ad1843_read_multi(ad1843, nfields, - * &ad1843_FIELD1, &val1, - * &ad1843_FIELD2, &val2, ...); - */ - -static void ad1843_read_multi(struct snd_ad1843 *ad1843, int argcount, ...) -{ - va_list ap; - const struct ad1843_bitfield *fp; - int w = 0, mask, *value, reg = -1; - - va_start(ap, argcount); - while (--argcount >= 0) { - fp = va_arg(ap, const struct ad1843_bitfield *); - value = va_arg(ap, int *); - if (reg == -1) { - reg = fp->reg; - w = ad1843->read(ad1843->chip, reg); - } - - mask = (1 << fp->nbits) - 1; - *value = w >> fp->lo_bit & mask; - } - va_end(ap); -} - -/* - * ad1843_write_multi stores multiple bitfields into the same AD1843 - * register. It uses one read and one write cycle to do it. - * - * Called like this. - * - * ad1843_write_multi(ad1843, nfields, - * &ad1843_FIELD1, val1, - * &ad1843_FIELF2, val2, ...); - */ - -static void ad1843_write_multi(struct snd_ad1843 *ad1843, int argcount, ...) -{ - va_list ap; - int reg; - const struct ad1843_bitfield *fp; - int value; - int w, m, mask, bits; - - mask = 0; - bits = 0; - reg = -1; - - va_start(ap, argcount); - while (--argcount >= 0) { - fp = va_arg(ap, const struct ad1843_bitfield *); - value = va_arg(ap, int); - if (reg == -1) - reg = fp->reg; - else - BUG_ON(reg != fp->reg); - m = ((1 << fp->nbits) - 1) << fp->lo_bit; - mask |= m; - bits |= (value << fp->lo_bit) & m; - } - va_end(ap); - - if (~mask & 0xFFFF) - w = ad1843->read(ad1843->chip, reg); - else - w = 0; - w = (w & ~mask) | bits; - ad1843->write(ad1843->chip, reg, w); -} - -int ad1843_get_gain_max(struct snd_ad1843 *ad1843, int id) -{ - const struct ad1843_gain *gp = ad1843_gain[id]; - int ret; - - ret = (1 << gp->lfield->nbits); - if (!gp->lmute) - ret -= 1; - return ret; -} - -/* - * ad1843_get_gain reads the specified register and extracts the gain value - * using the supplied gain type. - */ - -int ad1843_get_gain(struct snd_ad1843 *ad1843, int id) -{ - int lg, rg, lm, rm; - const struct ad1843_gain *gp = ad1843_gain[id]; - unsigned short mask = (1 << gp->lfield->nbits) - 1; - - ad1843_read_multi(ad1843, 2, gp->lfield, &lg, gp->rfield, &rg); - if (gp->negative) { - lg = mask - lg; - rg = mask - rg; - } - if (gp->lmute) { - ad1843_read_multi(ad1843, 2, gp->lmute, &lm, gp->rmute, &rm); - if (lm) - lg = 0; - if (rm) - rg = 0; - } - return lg << 0 | rg << 8; -} - -/* - * Set an audio channel's gain. - * - * Returns the new gain, which may be lower than the old gain. - */ - -int ad1843_set_gain(struct snd_ad1843 *ad1843, int id, int newval) -{ - const struct ad1843_gain *gp = ad1843_gain[id]; - unsigned short mask = (1 << gp->lfield->nbits) - 1; - - int lg = (newval >> 0) & mask; - int rg = (newval >> 8) & mask; - int lm = (lg == 0) ? 1 : 0; - int rm = (rg == 0) ? 1 : 0; - - if (gp->negative) { - lg = mask - lg; - rg = mask - rg; - } - if (gp->lmute) - ad1843_write_multi(ad1843, 2, gp->lmute, lm, gp->rmute, rm); - ad1843_write_multi(ad1843, 2, gp->lfield, lg, gp->rfield, rg); - return ad1843_get_gain(ad1843, id); -} - -/* Returns the current recording source */ - -int ad1843_get_recsrc(struct snd_ad1843 *ad1843) -{ - int val = ad1843_read_bits(ad1843, &ad1843_LSS); - - if (val < 0 || val > 2) { - val = 2; - ad1843_write_multi(ad1843, 2, - &ad1843_LSS, val, &ad1843_RSS, val); - } - return val; -} - -/* - * Set recording source. - * - * Returns newsrc on success, -errno on failure. - */ - -int ad1843_set_recsrc(struct snd_ad1843 *ad1843, int newsrc) -{ - if (newsrc < 0 || newsrc > 2) - return -EINVAL; - - ad1843_write_multi(ad1843, 2, &ad1843_LSS, newsrc, &ad1843_RSS, newsrc); - return newsrc; -} - -/* Setup ad1843 for D/A conversion. */ - -void ad1843_setup_dac(struct snd_ad1843 *ad1843, - unsigned int id, - unsigned int framerate, - snd_pcm_format_t fmt, - unsigned int channels) -{ - int ad_fmt = 0, ad_mode = 0; - - switch (fmt) { - case SNDRV_PCM_FORMAT_S8: - ad_fmt = 0; - break; - case SNDRV_PCM_FORMAT_U8: - ad_fmt = 0; - break; - case SNDRV_PCM_FORMAT_S16_LE: - ad_fmt = 1; - break; - case SNDRV_PCM_FORMAT_MU_LAW: - ad_fmt = 2; - break; - case SNDRV_PCM_FORMAT_A_LAW: - ad_fmt = 3; - break; - default: - break; - } - - switch (channels) { - case 2: - ad_mode = 0; - break; - case 1: - ad_mode = 1; - break; - default: - break; - } - - if (id) { - ad1843_write_bits(ad1843, &ad1843_C2C, framerate); - ad1843_write_multi(ad1843, 2, - &ad1843_DA2SM, ad_mode, - &ad1843_DA2F, ad_fmt); - } else { - ad1843_write_bits(ad1843, &ad1843_C1C, framerate); - ad1843_write_multi(ad1843, 2, - &ad1843_DA1SM, ad_mode, - &ad1843_DA1F, ad_fmt); - } -} - -void ad1843_shutdown_dac(struct snd_ad1843 *ad1843, unsigned int id) -{ - if (id) - ad1843_write_bits(ad1843, &ad1843_DA2F, 1); - else - ad1843_write_bits(ad1843, &ad1843_DA1F, 1); -} - -void ad1843_setup_adc(struct snd_ad1843 *ad1843, - unsigned int framerate, - snd_pcm_format_t fmt, - unsigned int channels) -{ - int da_fmt = 0; - - switch (fmt) { - case SNDRV_PCM_FORMAT_S8: da_fmt = 0; break; - case SNDRV_PCM_FORMAT_U8: da_fmt = 0; break; - case SNDRV_PCM_FORMAT_S16_LE: da_fmt = 1; break; - case SNDRV_PCM_FORMAT_MU_LAW: da_fmt = 2; break; - case SNDRV_PCM_FORMAT_A_LAW: da_fmt = 3; break; - default: break; - } - - ad1843_write_bits(ad1843, &ad1843_C3C, framerate); - ad1843_write_multi(ad1843, 2, - &ad1843_ADLF, da_fmt, &ad1843_ADRF, da_fmt); -} - -void ad1843_shutdown_adc(struct snd_ad1843 *ad1843) -{ - /* nothing to do */ -} - -/* - * Fully initialize the ad1843. As described in the AD1843 data - * sheet, section "START-UP SEQUENCE". The numbered comments are - * subsection headings from the data sheet. See the data sheet, pages - * 52-54, for more info. - * - * return 0 on success, -errno on failure. */ - -int ad1843_init(struct snd_ad1843 *ad1843) -{ - unsigned long later; - - if (ad1843_read_bits(ad1843, &ad1843_INIT) != 0) { - printk(KERN_ERR "ad1843: AD1843 won't initialize\n"); - return -EIO; - } - - ad1843_write_bits(ad1843, &ad1843_SCF, 1); - - /* 4. Put the conversion resources into standby. */ - ad1843_write_bits(ad1843, &ad1843_PDNI, 0); - later = jiffies + msecs_to_jiffies(500); - - while (ad1843_read_bits(ad1843, &ad1843_PDNO)) { - if (time_after(jiffies, later)) { - printk(KERN_ERR - "ad1843: AD1843 won't power up\n"); - return -EIO; - } - schedule_timeout_interruptible(5); - } - - /* 5. Power up the clock generators and enable clock output pins. */ - ad1843_write_multi(ad1843, 3, - &ad1843_C1EN, 1, - &ad1843_C2EN, 1, - &ad1843_C3EN, 1); - - /* 6. Configure conversion resources while they are in standby. */ - - /* DAC1/2 use clock 1/2 as source, ADC uses clock 3. Always. */ - ad1843_write_multi(ad1843, 4, - &ad1843_DA1C, 1, - &ad1843_DA2C, 2, - &ad1843_ADLC, 3, - &ad1843_ADRC, 3); - - /* 7. Enable conversion resources. */ - ad1843_write_bits(ad1843, &ad1843_ADTLK, 1); - ad1843_write_multi(ad1843, 7, - &ad1843_ANAEN, 1, - &ad1843_AAMEN, 1, - &ad1843_DA1EN, 1, - &ad1843_DA2EN, 1, - &ad1843_DDMEN, 1, - &ad1843_ADLEN, 1, - &ad1843_ADREN, 1); - - /* 8. Configure conversion resources while they are enabled. */ - - /* set gain to 0 for all channels */ - ad1843_set_gain(ad1843, AD1843_GAIN_RECLEV, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_LINE, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_LINE_2, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_MIC, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_PCM_0, 0); - ad1843_set_gain(ad1843, AD1843_GAIN_PCM_1, 0); - - /* Unmute all channels. */ - /* DAC1 */ - ad1843_write_multi(ad1843, 2, &ad1843_LDA1GM, 0, &ad1843_RDA1GM, 0); - /* DAC2 */ - ad1843_write_multi(ad1843, 2, &ad1843_LDA2GM, 0, &ad1843_RDA2GM, 0); - - /* Set default recording source to Line In and set - * mic gain to +20 dB. - */ - ad1843_set_recsrc(ad1843, 2); - ad1843_write_multi(ad1843, 2, &ad1843_LMGE, 1, &ad1843_RMGE, 1); - - /* Set Speaker Out level to +/- 4V and unmute it. */ - ad1843_write_multi(ad1843, 3, - &ad1843_HPOS, 1, - &ad1843_HPOM, 0, - &ad1843_MPOM, 0); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/mips/au1x00.c b/ANDROID_3.4.5/sound/mips/au1x00.c deleted file mode 100644 index 3f3ec0be..00000000 --- a/ANDROID_3.4.5/sound/mips/au1x00.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Driver for AMD Au1000 MIPS Processor, AC'97 Sound Port - * - * Copyright 2004 Cooper Street Innovations Inc. - * Author: Charles Eidsness - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * History: - * - * 2004-09-09 Charles Eidsness -- Original verion -- based on - * sa11xx-uda1341.c ALSA driver and the - * au1000.c OSS driver. - * 2004-09-09 Matt Porter -- Added support for ALSA 1.0.6 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Charles Eidsness "); -MODULE_DESCRIPTION("Au1000 AC'97 ALSA Driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{AMD,Au1000 AC'97}}"); - -#define PLAYBACK 0 -#define CAPTURE 1 -#define AC97_SLOT_3 0x01 -#define AC97_SLOT_4 0x02 -#define AC97_SLOT_6 0x08 -#define AC97_CMD_IRQ 31 -#define READ 0 -#define WRITE 1 -#define READ_WAIT 2 -#define RW_DONE 3 - -struct au1000_period -{ - u32 start; - u32 relative_end; /*realtive to start of buffer*/ - struct au1000_period * next; -}; - -/*Au1000 AC97 Port Control Reisters*/ -struct au1000_ac97_reg { - u32 volatile config; - u32 volatile status; - u32 volatile data; - u32 volatile cmd; - u32 volatile cntrl; -}; - -struct audio_stream { - struct snd_pcm_substream *substream; - int dma; - spinlock_t dma_lock; - struct au1000_period * buffer; - unsigned int period_size; - unsigned int periods; -}; - -struct snd_au1000 { - struct snd_card *card; - struct au1000_ac97_reg volatile *ac97_ioport; - - struct resource *ac97_res_port; - spinlock_t ac97_lock; - struct snd_ac97 *ac97; - - struct snd_pcm *pcm; - struct audio_stream *stream[2]; /* playback & capture */ -}; - -/*--------------------------- Local Functions --------------------------------*/ -static void -au1000_set_ac97_xmit_slots(struct snd_au1000 *au1000, long xmit_slots) -{ - u32 volatile ac97_config; - - spin_lock(&au1000->ac97_lock); - ac97_config = au1000->ac97_ioport->config; - ac97_config = ac97_config & ~AC97C_XMIT_SLOTS_MASK; - ac97_config |= (xmit_slots << AC97C_XMIT_SLOTS_BIT); - au1000->ac97_ioport->config = ac97_config; - spin_unlock(&au1000->ac97_lock); -} - -static void -au1000_set_ac97_recv_slots(struct snd_au1000 *au1000, long recv_slots) -{ - u32 volatile ac97_config; - - spin_lock(&au1000->ac97_lock); - ac97_config = au1000->ac97_ioport->config; - ac97_config = ac97_config & ~AC97C_RECV_SLOTS_MASK; - ac97_config |= (recv_slots << AC97C_RECV_SLOTS_BIT); - au1000->ac97_ioport->config = ac97_config; - spin_unlock(&au1000->ac97_lock); -} - - -static void -au1000_release_dma_link(struct audio_stream *stream) -{ - struct au1000_period * pointer; - struct au1000_period * pointer_next; - - stream->period_size = 0; - stream->periods = 0; - pointer = stream->buffer; - if (! pointer) - return; - do { - pointer_next = pointer->next; - kfree(pointer); - pointer = pointer_next; - } while (pointer != stream->buffer); - stream->buffer = NULL; -} - -static int -au1000_setup_dma_link(struct audio_stream *stream, unsigned int period_bytes, - unsigned int periods) -{ - struct snd_pcm_substream *substream = stream->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - struct au1000_period *pointer; - unsigned long dma_start; - int i; - - dma_start = virt_to_phys(runtime->dma_area); - - if (stream->period_size == period_bytes && - stream->periods == periods) - return 0; /* not changed */ - - au1000_release_dma_link(stream); - - stream->period_size = period_bytes; - stream->periods = periods; - - stream->buffer = kmalloc(sizeof(struct au1000_period), GFP_KERNEL); - if (! stream->buffer) - return -ENOMEM; - pointer = stream->buffer; - for (i = 0; i < periods; i++) { - pointer->start = (u32)(dma_start + (i * period_bytes)); - pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1); - if (i < periods - 1) { - pointer->next = kmalloc(sizeof(struct au1000_period), GFP_KERNEL); - if (! pointer->next) { - au1000_release_dma_link(stream); - return -ENOMEM; - } - pointer = pointer->next; - } - } - pointer->next = stream->buffer; - return 0; -} - -static void -au1000_dma_stop(struct audio_stream *stream) -{ - if (snd_BUG_ON(!stream->buffer)) - return; - disable_dma(stream->dma); -} - -static void -au1000_dma_start(struct audio_stream *stream) -{ - if (snd_BUG_ON(!stream->buffer)) - return; - - init_dma(stream->dma); - if (get_dma_active_buffer(stream->dma) == 0) { - clear_dma_done0(stream->dma); - set_dma_addr0(stream->dma, stream->buffer->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - set_dma_addr1(stream->dma, stream->buffer->next->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - } else { - clear_dma_done1(stream->dma); - set_dma_addr1(stream->dma, stream->buffer->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - set_dma_addr0(stream->dma, stream->buffer->next->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - } - enable_dma_buffers(stream->dma); - start_dma(stream->dma); -} - -static irqreturn_t -au1000_dma_interrupt(int irq, void *dev_id) -{ - struct audio_stream *stream = (struct audio_stream *) dev_id; - struct snd_pcm_substream *substream = stream->substream; - - spin_lock(&stream->dma_lock); - switch (get_dma_buffer_done(stream->dma)) { - case DMA_D0: - stream->buffer = stream->buffer->next; - clear_dma_done0(stream->dma); - set_dma_addr0(stream->dma, stream->buffer->next->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - enable_dma_buffer0(stream->dma); - break; - case DMA_D1: - stream->buffer = stream->buffer->next; - clear_dma_done1(stream->dma); - set_dma_addr1(stream->dma, stream->buffer->next->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - enable_dma_buffer1(stream->dma); - break; - case (DMA_D0 | DMA_D1): - printk(KERN_ERR "DMA %d missed interrupt.\n",stream->dma); - au1000_dma_stop(stream); - au1000_dma_start(stream); - break; - case (~DMA_D0 & ~DMA_D1): - printk(KERN_ERR "DMA %d empty irq.\n",stream->dma); - } - spin_unlock(&stream->dma_lock); - snd_pcm_period_elapsed(substream); - return IRQ_HANDLED; -} - -/*-------------------------- PCM Audio Streams -------------------------------*/ - -static unsigned int rates[] = {8000, 11025, 16000, 22050}; -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static struct snd_pcm_hardware snd_au1000_hw = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | \ - SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050), - .rate_min = 8000, - .rate_max = 22050, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 128*1024, - .period_bytes_min = 32, - .period_bytes_max = 16*1024, - .periods_min = 8, - .periods_max = 255, - .fifo_size = 16, -}; - -static int -snd_au1000_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - - au1000->stream[PLAYBACK]->substream = substream; - au1000->stream[PLAYBACK]->buffer = NULL; - substream->private_data = au1000->stream[PLAYBACK]; - substream->runtime->hw = snd_au1000_hw; - return (snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0); -} - -static int -snd_au1000_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - - au1000->stream[CAPTURE]->substream = substream; - au1000->stream[CAPTURE]->buffer = NULL; - substream->private_data = au1000->stream[CAPTURE]; - substream->runtime->hw = snd_au1000_hw; - return (snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0); -} - -static int -snd_au1000_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - - au1000->stream[PLAYBACK]->substream = NULL; - return 0; -} - -static int -snd_au1000_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - - au1000->stream[CAPTURE]->substream = NULL; - return 0; -} - -static int -snd_au1000_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct audio_stream *stream = substream->private_data; - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - return au1000_setup_dma_link(stream, - params_period_bytes(hw_params), - params_periods(hw_params)); -} - -static int -snd_au1000_hw_free(struct snd_pcm_substream *substream) -{ - struct audio_stream *stream = substream->private_data; - au1000_release_dma_link(stream); - return snd_pcm_lib_free_pages(substream); -} - -static int -snd_au1000_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (runtime->channels == 1) - au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_4); - else - au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4); - snd_ac97_set_rate(au1000->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate); - return 0; -} - -static int -snd_au1000_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_au1000 *au1000 = substream->pcm->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (runtime->channels == 1) - au1000_set_ac97_recv_slots(au1000, AC97_SLOT_4); - else - au1000_set_ac97_recv_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4); - snd_ac97_set_rate(au1000->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); - return 0; -} - -static int -snd_au1000_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct audio_stream *stream = substream->private_data; - int err = 0; - - spin_lock(&stream->dma_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - au1000_dma_start(stream); - break; - case SNDRV_PCM_TRIGGER_STOP: - au1000_dma_stop(stream); - break; - default: - err = -EINVAL; - break; - } - spin_unlock(&stream->dma_lock); - return err; -} - -static snd_pcm_uframes_t -snd_au1000_pointer(struct snd_pcm_substream *substream) -{ - struct audio_stream *stream = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - long location; - - spin_lock(&stream->dma_lock); - location = get_dma_residue(stream->dma); - spin_unlock(&stream->dma_lock); - location = stream->buffer->relative_end - location; - if (location == -1) - location = 0; - return bytes_to_frames(runtime,location); -} - -static struct snd_pcm_ops snd_card_au1000_playback_ops = { - .open = snd_au1000_playback_open, - .close = snd_au1000_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_au1000_hw_params, - .hw_free = snd_au1000_hw_free, - .prepare = snd_au1000_playback_prepare, - .trigger = snd_au1000_trigger, - .pointer = snd_au1000_pointer, -}; - -static struct snd_pcm_ops snd_card_au1000_capture_ops = { - .open = snd_au1000_capture_open, - .close = snd_au1000_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_au1000_hw_params, - .hw_free = snd_au1000_hw_free, - .prepare = snd_au1000_capture_prepare, - .trigger = snd_au1000_trigger, - .pointer = snd_au1000_pointer, -}; - -static int __devinit -snd_au1000_pcm_new(struct snd_au1000 *au1000) -{ - struct snd_pcm *pcm; - int err; - unsigned long flags; - - if ((err = snd_pcm_new(au1000->card, "AU1000 AC97 PCM", 0, 1, 1, &pcm)) < 0) - return err; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), 128*1024, 128*1024); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_card_au1000_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_card_au1000_capture_ops); - - pcm->private_data = au1000; - pcm->info_flags = 0; - strcpy(pcm->name, "Au1000 AC97 PCM"); - - spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock); - spin_lock_init(&au1000->stream[CAPTURE]->dma_lock); - - flags = claim_dma_lock(); - if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX, - "AC97 TX", au1000_dma_interrupt, 0, - au1000->stream[PLAYBACK])) < 0) { - release_dma_lock(flags); - return -EBUSY; - } - if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX, - "AC97 RX", au1000_dma_interrupt, 0, - au1000->stream[CAPTURE])) < 0){ - release_dma_lock(flags); - return -EBUSY; - } - /* enable DMA coherency in read/write DMA channels */ - set_dma_mode(au1000->stream[PLAYBACK]->dma, - get_dma_mode(au1000->stream[PLAYBACK]->dma) & ~DMA_NC); - set_dma_mode(au1000->stream[CAPTURE]->dma, - get_dma_mode(au1000->stream[CAPTURE]->dma) & ~DMA_NC); - release_dma_lock(flags); - au1000->pcm = pcm; - return 0; -} - - -/*-------------------------- AC97 CODEC Control ------------------------------*/ - -static unsigned short -snd_au1000_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_au1000 *au1000 = ac97->private_data; - u32 volatile cmd; - u16 volatile data; - int i; - - spin_lock(&au1000->ac97_lock); -/* would rather use the interrupt than this polling but it works and I can't -get the interrupt driven case to work efficiently */ - for (i = 0; i < 0x5000; i++) - if (!(au1000->ac97_ioport->status & AC97C_CP)) - break; - if (i == 0x5000) - printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n"); - - cmd = (u32) reg & AC97C_INDEX_MASK; - cmd |= AC97C_READ; - au1000->ac97_ioport->cmd = cmd; - - /* now wait for the data */ - for (i = 0; i < 0x5000; i++) - if (!(au1000->ac97_ioport->status & AC97C_CP)) - break; - if (i == 0x5000) { - printk(KERN_ERR "au1000 AC97: AC97 command read timeout\n"); - spin_unlock(&au1000->ac97_lock); - return 0; - } - - data = au1000->ac97_ioport->cmd & 0xffff; - spin_unlock(&au1000->ac97_lock); - - return data; - -} - - -static void -snd_au1000_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) -{ - struct snd_au1000 *au1000 = ac97->private_data; - u32 cmd; - int i; - - spin_lock(&au1000->ac97_lock); -/* would rather use the interrupt than this polling but it works and I can't -get the interrupt driven case to work efficiently */ - for (i = 0; i < 0x5000; i++) - if (!(au1000->ac97_ioport->status & AC97C_CP)) - break; - if (i == 0x5000) - printk(KERN_ERR "au1000 AC97: AC97 command write timeout\n"); - - cmd = (u32) reg & AC97C_INDEX_MASK; - cmd &= ~AC97C_READ; - cmd |= ((u32) val << AC97C_WD_BIT); - au1000->ac97_ioport->cmd = cmd; - spin_unlock(&au1000->ac97_lock); -} - -static int __devinit -snd_au1000_ac97_new(struct snd_au1000 *au1000) -{ - int err; - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = snd_au1000_ac97_write, - .read = snd_au1000_ac97_read, - }; - - if ((au1000->ac97_res_port = request_mem_region(CPHYSADDR(AC97C_CONFIG), - 0x100000, "Au1x00 AC97")) == NULL) { - snd_printk(KERN_ERR "ALSA AC97: can't grap AC97 port\n"); - return -EBUSY; - } - au1000->ac97_ioport = (struct au1000_ac97_reg *) - KSEG1ADDR(au1000->ac97_res_port->start); - - spin_lock_init(&au1000->ac97_lock); - - /* configure pins for AC'97 - TODO: move to board_setup.c */ - au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC); - - /* Initialise Au1000's AC'97 Control Block */ - au1000->ac97_ioport->cntrl = AC97C_RS | AC97C_CE; - udelay(10); - au1000->ac97_ioport->cntrl = AC97C_CE; - udelay(10); - - /* Initialise External CODEC -- cold reset */ - au1000->ac97_ioport->config = AC97C_RESET; - udelay(10); - au1000->ac97_ioport->config = 0x0; - mdelay(5); - - /* Initialise AC97 middle-layer */ - if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = au1000; - if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0) - return err; - - return 0; -} - -/*------------------------------ Setup / Destroy ----------------------------*/ - -void -snd_au1000_free(struct snd_card *card) -{ - struct snd_au1000 *au1000 = card->private_data; - - if (au1000->ac97_res_port) { - /* put internal AC97 block into reset */ - au1000->ac97_ioport->cntrl = AC97C_RS; - au1000->ac97_ioport = NULL; - release_and_free_resource(au1000->ac97_res_port); - } - - if (au1000->stream[PLAYBACK]) { - if (au1000->stream[PLAYBACK]->dma >= 0) - free_au1000_dma(au1000->stream[PLAYBACK]->dma); - kfree(au1000->stream[PLAYBACK]); - } - - if (au1000->stream[CAPTURE]) { - if (au1000->stream[CAPTURE]->dma >= 0) - free_au1000_dma(au1000->stream[CAPTURE]->dma); - kfree(au1000->stream[CAPTURE]); - } -} - - -static struct snd_card *au1000_card; - -static int __init -au1000_init(void) -{ - int err; - struct snd_card *card; - struct snd_au1000 *au1000; - - err = snd_card_create(-1, "AC97", THIS_MODULE, - sizeof(struct snd_au1000), &card); - if (err < 0) - return err; - - card->private_free = snd_au1000_free; - au1000 = card->private_data; - au1000->card = card; - - au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL); - au1000->stream[CAPTURE ] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL); - /* so that snd_au1000_free will work as intended */ - au1000->ac97_res_port = NULL; - if (au1000->stream[PLAYBACK]) - au1000->stream[PLAYBACK]->dma = -1; - if (au1000->stream[CAPTURE ]) - au1000->stream[CAPTURE ]->dma = -1; - - if (au1000->stream[PLAYBACK] == NULL || - au1000->stream[CAPTURE ] == NULL) { - snd_card_free(card); - return -ENOMEM; - } - - if ((err = snd_au1000_ac97_new(au1000)) < 0 ) { - snd_card_free(card); - return err; - } - - if ((err = snd_au1000_pcm_new(au1000)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "Au1000-AC97"); - strcpy(card->shortname, "AMD Au1000-AC97"); - sprintf(card->longname, "AMD Au1000--AC97 ALSA Driver"); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - printk(KERN_INFO "ALSA AC97: Driver Initialized\n"); - au1000_card = card; - return 0; -} - -static void __exit au1000_exit(void) -{ - snd_card_free(au1000_card); -} - -module_init(au1000_init); -module_exit(au1000_exit); - diff --git a/ANDROID_3.4.5/sound/mips/hal2.c b/ANDROID_3.4.5/sound/mips/hal2.c deleted file mode 100644 index 5f88d1f0..00000000 --- a/ANDROID_3.4.5/sound/mips/hal2.c +++ /dev/null @@ -1,938 +0,0 @@ -/* - * Driver for A2 audio system used in SGI machines - * Copyright (c) 2008 Thomas Bogendoerfer - * - * Based on OSS code from Ladislav Michl , which - * was based on code from Ulf Carlsson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include "hal2.h" - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for SGI HAL2 soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for SGI HAL2 soundcard."); -MODULE_DESCRIPTION("ALSA driver for SGI HAL2 audio"); -MODULE_AUTHOR("Thomas Bogendoerfer"); -MODULE_LICENSE("GPL"); - - -#define H2_BLOCK_SIZE 1024 -#define H2_BUF_SIZE 16384 - -struct hal2_pbus { - struct hpc3_pbus_dmacregs *pbus; - int pbusnr; - unsigned int ctrl; /* Current state of pbus->pbdma_ctrl */ -}; - -struct hal2_desc { - struct hpc_dma_desc desc; - u32 pad; /* padding */ -}; - -struct hal2_codec { - struct snd_pcm_indirect pcm_indirect; - struct snd_pcm_substream *substream; - - unsigned char *buffer; - dma_addr_t buffer_dma; - struct hal2_desc *desc; - dma_addr_t desc_dma; - int desc_count; - struct hal2_pbus pbus; - int voices; /* mono/stereo */ - unsigned int sample_rate; - unsigned int master; /* Master frequency */ - unsigned short mod; /* MOD value */ - unsigned short inc; /* INC value */ -}; - -#define H2_MIX_OUTPUT_ATT 0 -#define H2_MIX_INPUT_GAIN 1 - -struct snd_hal2 { - struct snd_card *card; - - struct hal2_ctl_regs *ctl_regs; /* HAL2 ctl registers */ - struct hal2_aes_regs *aes_regs; /* HAL2 aes registers */ - struct hal2_vol_regs *vol_regs; /* HAL2 vol registers */ - struct hal2_syn_regs *syn_regs; /* HAL2 syn registers */ - - struct hal2_codec dac; - struct hal2_codec adc; -}; - -#define H2_INDIRECT_WAIT(regs) while (hal2_read(®s->isr) & H2_ISR_TSTATUS); - -#define H2_READ_ADDR(addr) (addr | (1<<7)) -#define H2_WRITE_ADDR(addr) (addr) - -static inline u32 hal2_read(u32 *reg) -{ - return __raw_readl(reg); -} - -static inline void hal2_write(u32 val, u32 *reg) -{ - __raw_writel(val, reg); -} - - -static u32 hal2_i_read32(struct snd_hal2 *hal2, u16 addr) -{ - u32 ret; - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(H2_READ_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); - ret = hal2_read(®s->idr0) & 0xffff; - hal2_write(H2_READ_ADDR(addr) | 0x1, ®s->iar); - H2_INDIRECT_WAIT(regs); - ret |= (hal2_read(®s->idr0) & 0xffff) << 16; - return ret; -} - -static void hal2_i_write16(struct snd_hal2 *hal2, u16 addr, u16 val) -{ - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(val, ®s->idr0); - hal2_write(0, ®s->idr1); - hal2_write(0, ®s->idr2); - hal2_write(0, ®s->idr3); - hal2_write(H2_WRITE_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); -} - -static void hal2_i_write32(struct snd_hal2 *hal2, u16 addr, u32 val) -{ - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(val & 0xffff, ®s->idr0); - hal2_write(val >> 16, ®s->idr1); - hal2_write(0, ®s->idr2); - hal2_write(0, ®s->idr3); - hal2_write(H2_WRITE_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); -} - -static void hal2_i_setbit16(struct snd_hal2 *hal2, u16 addr, u16 bit) -{ - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(H2_READ_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); - hal2_write((hal2_read(®s->idr0) & 0xffff) | bit, ®s->idr0); - hal2_write(0, ®s->idr1); - hal2_write(0, ®s->idr2); - hal2_write(0, ®s->idr3); - hal2_write(H2_WRITE_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); -} - -static void hal2_i_clearbit16(struct snd_hal2 *hal2, u16 addr, u16 bit) -{ - struct hal2_ctl_regs *regs = hal2->ctl_regs; - - hal2_write(H2_READ_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); - hal2_write((hal2_read(®s->idr0) & 0xffff) & ~bit, ®s->idr0); - hal2_write(0, ®s->idr1); - hal2_write(0, ®s->idr2); - hal2_write(0, ®s->idr3); - hal2_write(H2_WRITE_ADDR(addr), ®s->iar); - H2_INDIRECT_WAIT(regs); -} - -static int hal2_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - switch ((int)kcontrol->private_value) { - case H2_MIX_OUTPUT_ATT: - uinfo->value.integer.max = 31; - break; - case H2_MIX_INPUT_GAIN: - uinfo->value.integer.max = 15; - break; - } - return 0; -} - -static int hal2_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol); - u32 tmp; - int l, r; - - switch ((int)kcontrol->private_value) { - case H2_MIX_OUTPUT_ATT: - tmp = hal2_i_read32(hal2, H2I_DAC_C2); - if (tmp & H2I_C2_MUTE) { - l = 0; - r = 0; - } else { - l = 31 - ((tmp >> H2I_C2_L_ATT_SHIFT) & 31); - r = 31 - ((tmp >> H2I_C2_R_ATT_SHIFT) & 31); - } - break; - case H2_MIX_INPUT_GAIN: - tmp = hal2_i_read32(hal2, H2I_ADC_C2); - l = (tmp >> H2I_C2_L_GAIN_SHIFT) & 15; - r = (tmp >> H2I_C2_R_GAIN_SHIFT) & 15; - break; - } - ucontrol->value.integer.value[0] = l; - ucontrol->value.integer.value[1] = r; - - return 0; -} - -static int hal2_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol); - u32 old, new; - int l, r; - - l = ucontrol->value.integer.value[0]; - r = ucontrol->value.integer.value[1]; - - switch ((int)kcontrol->private_value) { - case H2_MIX_OUTPUT_ATT: - old = hal2_i_read32(hal2, H2I_DAC_C2); - new = old & ~(H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE); - if (l | r) { - l = 31 - l; - r = 31 - r; - new |= (l << H2I_C2_L_ATT_SHIFT); - new |= (r << H2I_C2_R_ATT_SHIFT); - } else - new |= H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE; - hal2_i_write32(hal2, H2I_DAC_C2, new); - break; - case H2_MIX_INPUT_GAIN: - old = hal2_i_read32(hal2, H2I_ADC_C2); - new = old & ~(H2I_C2_L_GAIN_M | H2I_C2_R_GAIN_M); - new |= (l << H2I_C2_L_GAIN_SHIFT); - new |= (r << H2I_C2_R_GAIN_SHIFT); - hal2_i_write32(hal2, H2I_ADC_C2, new); - break; - } - return old != new; -} - -static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = H2_MIX_OUTPUT_ATT, - .info = hal2_gain_info, - .get = hal2_gain_get, - .put = hal2_gain_put, -}; - -static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Capture Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = H2_MIX_INPUT_GAIN, - .info = hal2_gain_info, - .get = hal2_gain_get, - .put = hal2_gain_put, -}; - -static int __devinit hal2_mixer_create(struct snd_hal2 *hal2) -{ - int err; - - /* mute DAC */ - hal2_i_write32(hal2, H2I_DAC_C2, - H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE); - /* mute ADC */ - hal2_i_write32(hal2, H2I_ADC_C2, 0); - - err = snd_ctl_add(hal2->card, - snd_ctl_new1(&hal2_ctrl_headphone, hal2)); - if (err < 0) - return err; - - err = snd_ctl_add(hal2->card, - snd_ctl_new1(&hal2_ctrl_mic, hal2)); - if (err < 0) - return err; - - return 0; -} - -static irqreturn_t hal2_interrupt(int irq, void *dev_id) -{ - struct snd_hal2 *hal2 = dev_id; - irqreturn_t ret = IRQ_NONE; - - /* decide what caused this interrupt */ - if (hal2->dac.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) { - snd_pcm_period_elapsed(hal2->dac.substream); - ret = IRQ_HANDLED; - } - if (hal2->adc.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) { - snd_pcm_period_elapsed(hal2->adc.substream); - ret = IRQ_HANDLED; - } - return ret; -} - -static int hal2_compute_rate(struct hal2_codec *codec, unsigned int rate) -{ - unsigned short mod; - - if (44100 % rate < 48000 % rate) { - mod = 4 * 44100 / rate; - codec->master = 44100; - } else { - mod = 4 * 48000 / rate; - codec->master = 48000; - } - - codec->inc = 4; - codec->mod = mod; - rate = 4 * codec->master / mod; - - return rate; -} - -static void hal2_set_dac_rate(struct snd_hal2 *hal2) -{ - unsigned int master = hal2->dac.master; - int inc = hal2->dac.inc; - int mod = hal2->dac.mod; - - hal2_i_write16(hal2, H2I_BRES1_C1, (master == 44100) ? 1 : 0); - hal2_i_write32(hal2, H2I_BRES1_C2, - ((0xffff & (inc - mod - 1)) << 16) | inc); -} - -static void hal2_set_adc_rate(struct snd_hal2 *hal2) -{ - unsigned int master = hal2->adc.master; - int inc = hal2->adc.inc; - int mod = hal2->adc.mod; - - hal2_i_write16(hal2, H2I_BRES2_C1, (master == 44100) ? 1 : 0); - hal2_i_write32(hal2, H2I_BRES2_C2, - ((0xffff & (inc - mod - 1)) << 16) | inc); -} - -static void hal2_setup_dac(struct snd_hal2 *hal2) -{ - unsigned int fifobeg, fifoend, highwater, sample_size; - struct hal2_pbus *pbus = &hal2->dac.pbus; - - /* Now we set up some PBUS information. The PBUS needs information about - * what portion of the fifo it will use. If it's receiving or - * transmitting, and finally whether the stream is little endian or big - * endian. The information is written later, on the start call. - */ - sample_size = 2 * hal2->dac.voices; - /* Fifo should be set to hold exactly four samples. Highwater mark - * should be set to two samples. */ - highwater = (sample_size * 2) >> 1; /* halfwords */ - fifobeg = 0; /* playback is first */ - fifoend = (sample_size * 4) >> 3; /* doublewords */ - pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_LD | - (highwater << 8) | (fifobeg << 16) | (fifoend << 24); - /* We disable everything before we do anything at all */ - pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; - hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX); - /* Setup the HAL2 for playback */ - hal2_set_dac_rate(hal2); - /* Set endianess */ - hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECTX); - /* Set DMA bus */ - hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr)); - /* We are using 1st Bresenham clock generator for playback */ - hal2_i_write16(hal2, H2I_DAC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT) - | (1 << H2I_C1_CLKID_SHIFT) - | (hal2->dac.voices << H2I_C1_DATAT_SHIFT)); -} - -static void hal2_setup_adc(struct snd_hal2 *hal2) -{ - unsigned int fifobeg, fifoend, highwater, sample_size; - struct hal2_pbus *pbus = &hal2->adc.pbus; - - sample_size = 2 * hal2->adc.voices; - highwater = (sample_size * 2) >> 1; /* halfwords */ - fifobeg = (4 * 4) >> 3; /* record is second */ - fifoend = (4 * 4 + sample_size * 4) >> 3; /* doublewords */ - pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_RCV | HPC3_PDMACTRL_LD | - (highwater << 8) | (fifobeg << 16) | (fifoend << 24); - pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; - hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR); - /* Setup the HAL2 for record */ - hal2_set_adc_rate(hal2); - /* Set endianess */ - hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECR); - /* Set DMA bus */ - hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr)); - /* We are using 2nd Bresenham clock generator for record */ - hal2_i_write16(hal2, H2I_ADC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT) - | (2 << H2I_C1_CLKID_SHIFT) - | (hal2->adc.voices << H2I_C1_DATAT_SHIFT)); -} - -static void hal2_start_dac(struct snd_hal2 *hal2) -{ - struct hal2_pbus *pbus = &hal2->dac.pbus; - - pbus->pbus->pbdma_dptr = hal2->dac.desc_dma; - pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT; - /* enable DAC */ - hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX); -} - -static void hal2_start_adc(struct snd_hal2 *hal2) -{ - struct hal2_pbus *pbus = &hal2->adc.pbus; - - pbus->pbus->pbdma_dptr = hal2->adc.desc_dma; - pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT; - /* enable ADC */ - hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR); -} - -static inline void hal2_stop_dac(struct snd_hal2 *hal2) -{ - hal2->dac.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; - /* The HAL2 itself may remain enabled safely */ -} - -static inline void hal2_stop_adc(struct snd_hal2 *hal2) -{ - hal2->adc.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; -} - -static int hal2_alloc_dmabuf(struct hal2_codec *codec) -{ - struct hal2_desc *desc; - dma_addr_t desc_dma, buffer_dma; - int count = H2_BUF_SIZE / H2_BLOCK_SIZE; - int i; - - codec->buffer = dma_alloc_noncoherent(NULL, H2_BUF_SIZE, - &buffer_dma, GFP_KERNEL); - if (!codec->buffer) - return -ENOMEM; - desc = dma_alloc_noncoherent(NULL, count * sizeof(struct hal2_desc), - &desc_dma, GFP_KERNEL); - if (!desc) { - dma_free_noncoherent(NULL, H2_BUF_SIZE, - codec->buffer, buffer_dma); - return -ENOMEM; - } - codec->buffer_dma = buffer_dma; - codec->desc_dma = desc_dma; - codec->desc = desc; - for (i = 0; i < count; i++) { - desc->desc.pbuf = buffer_dma + i * H2_BLOCK_SIZE; - desc->desc.cntinfo = HPCDMA_XIE | H2_BLOCK_SIZE; - desc->desc.pnext = (i == count - 1) ? - desc_dma : desc_dma + (i + 1) * sizeof(struct hal2_desc); - desc++; - } - dma_cache_sync(NULL, codec->desc, count * sizeof(struct hal2_desc), - DMA_TO_DEVICE); - codec->desc_count = count; - return 0; -} - -static void hal2_free_dmabuf(struct hal2_codec *codec) -{ - dma_free_noncoherent(NULL, codec->desc_count * sizeof(struct hal2_desc), - codec->desc, codec->desc_dma); - dma_free_noncoherent(NULL, H2_BUF_SIZE, codec->buffer, - codec->buffer_dma); -} - -static struct snd_pcm_hardware hal2_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 1024, - .period_bytes_max = 65536, - .periods_min = 2, - .periods_max = 1024, -}; - -static int hal2_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - int err; - - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (err < 0) - return err; - - return 0; -} - -static int hal2_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int hal2_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - int err; - - runtime->hw = hal2_pcm_hw; - - err = hal2_alloc_dmabuf(&hal2->dac); - if (err) - return err; - return 0; -} - -static int hal2_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - - hal2_free_dmabuf(&hal2->dac); - return 0; -} - -static int hal2_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct hal2_codec *dac = &hal2->dac; - - dac->voices = runtime->channels; - dac->sample_rate = hal2_compute_rate(dac, runtime->rate); - memset(&dac->pcm_indirect, 0, sizeof(dac->pcm_indirect)); - dac->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; - dac->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - dac->substream = substream; - hal2_setup_dac(hal2); - return 0; -} - -static int hal2_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - hal2->dac.pcm_indirect.hw_io = hal2->dac.buffer_dma; - hal2->dac.pcm_indirect.hw_data = 0; - substream->ops->ack(substream); - hal2_start_dac(hal2); - break; - case SNDRV_PCM_TRIGGER_STOP: - hal2_stop_dac(hal2); - break; - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t -hal2_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *dac = &hal2->dac; - - return snd_pcm_indirect_playback_pointer(substream, &dac->pcm_indirect, - dac->pbus.pbus->pbdma_bptr); -} - -static void hal2_playback_transfer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - unsigned char *buf = hal2->dac.buffer + rec->hw_data; - - memcpy(buf, substream->runtime->dma_area + rec->sw_data, bytes); - dma_cache_sync(NULL, buf, bytes, DMA_TO_DEVICE); - -} - -static int hal2_playback_ack(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *dac = &hal2->dac; - - dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; - snd_pcm_indirect_playback_transfer(substream, - &dac->pcm_indirect, - hal2_playback_transfer); - return 0; -} - -static int hal2_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *adc = &hal2->adc; - int err; - - runtime->hw = hal2_pcm_hw; - - err = hal2_alloc_dmabuf(adc); - if (err) - return err; - return 0; -} - -static int hal2_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - - hal2_free_dmabuf(&hal2->adc); - return 0; -} - -static int hal2_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct hal2_codec *adc = &hal2->adc; - - adc->voices = runtime->channels; - adc->sample_rate = hal2_compute_rate(adc, runtime->rate); - memset(&adc->pcm_indirect, 0, sizeof(adc->pcm_indirect)); - adc->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; - adc->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; - adc->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - adc->substream = substream; - hal2_setup_adc(hal2); - return 0; -} - -static int hal2_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - hal2->adc.pcm_indirect.hw_io = hal2->adc.buffer_dma; - hal2->adc.pcm_indirect.hw_data = 0; - printk(KERN_DEBUG "buffer_dma %x\n", hal2->adc.buffer_dma); - hal2_start_adc(hal2); - break; - case SNDRV_PCM_TRIGGER_STOP: - hal2_stop_adc(hal2); - break; - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t -hal2_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *adc = &hal2->adc; - - return snd_pcm_indirect_capture_pointer(substream, &adc->pcm_indirect, - adc->pbus.pbus->pbdma_bptr); -} - -static void hal2_capture_transfer(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - unsigned char *buf = hal2->adc.buffer + rec->hw_data; - - dma_cache_sync(NULL, buf, bytes, DMA_FROM_DEVICE); - memcpy(substream->runtime->dma_area + rec->sw_data, buf, bytes); -} - -static int hal2_capture_ack(struct snd_pcm_substream *substream) -{ - struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); - struct hal2_codec *adc = &hal2->adc; - - snd_pcm_indirect_capture_transfer(substream, - &adc->pcm_indirect, - hal2_capture_transfer); - return 0; -} - -static struct snd_pcm_ops hal2_playback_ops = { - .open = hal2_playback_open, - .close = hal2_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = hal2_pcm_hw_params, - .hw_free = hal2_pcm_hw_free, - .prepare = hal2_playback_prepare, - .trigger = hal2_playback_trigger, - .pointer = hal2_playback_pointer, - .ack = hal2_playback_ack, -}; - -static struct snd_pcm_ops hal2_capture_ops = { - .open = hal2_capture_open, - .close = hal2_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = hal2_pcm_hw_params, - .hw_free = hal2_pcm_hw_free, - .prepare = hal2_capture_prepare, - .trigger = hal2_capture_trigger, - .pointer = hal2_capture_pointer, - .ack = hal2_capture_ack, -}; - -static int __devinit hal2_pcm_create(struct snd_hal2 *hal2) -{ - struct snd_pcm *pcm; - int err; - - /* create first pcm device with one outputs and one input */ - err = snd_pcm_new(hal2->card, "SGI HAL2 Audio", 0, 1, 1, &pcm); - if (err < 0) - return err; - - pcm->private_data = hal2; - strcpy(pcm->name, "SGI HAL2"); - - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &hal2_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &hal2_capture_ops); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 0, 1024 * 1024); - - return 0; -} - -static int hal2_dev_free(struct snd_device *device) -{ - struct snd_hal2 *hal2 = device->device_data; - - free_irq(SGI_HPCDMA_IRQ, hal2); - kfree(hal2); - return 0; -} - -static struct snd_device_ops hal2_ops = { - .dev_free = hal2_dev_free, -}; - -static void hal2_init_codec(struct hal2_codec *codec, struct hpc3_regs *hpc3, - int index) -{ - codec->pbus.pbusnr = index; - codec->pbus.pbus = &hpc3->pbdma[index]; -} - -static int hal2_detect(struct snd_hal2 *hal2) -{ - unsigned short board, major, minor; - unsigned short rev; - - /* reset HAL2 */ - hal2_write(0, &hal2->ctl_regs->isr); - - /* release reset */ - hal2_write(H2_ISR_GLOBAL_RESET_N | H2_ISR_CODEC_RESET_N, - &hal2->ctl_regs->isr); - - - hal2_i_write16(hal2, H2I_RELAY_C, H2I_RELAY_C_STATE); - rev = hal2_read(&hal2->ctl_regs->rev); - if (rev & H2_REV_AUDIO_PRESENT) - return -ENODEV; - - board = (rev & H2_REV_BOARD_M) >> 12; - major = (rev & H2_REV_MAJOR_CHIP_M) >> 4; - minor = (rev & H2_REV_MINOR_CHIP_M); - - printk(KERN_INFO "SGI HAL2 revision %i.%i.%i\n", - board, major, minor); - - return 0; -} - -static int hal2_create(struct snd_card *card, struct snd_hal2 **rchip) -{ - struct snd_hal2 *hal2; - struct hpc3_regs *hpc3 = hpc3c0; - int err; - - hal2 = kzalloc(sizeof(struct snd_hal2), GFP_KERNEL); - if (!hal2) - return -ENOMEM; - - hal2->card = card; - - if (request_irq(SGI_HPCDMA_IRQ, hal2_interrupt, IRQF_SHARED, - "SGI HAL2", hal2)) { - printk(KERN_ERR "HAL2: Can't get irq %d\n", SGI_HPCDMA_IRQ); - kfree(hal2); - return -EAGAIN; - } - - hal2->ctl_regs = (struct hal2_ctl_regs *)hpc3->pbus_extregs[0]; - hal2->aes_regs = (struct hal2_aes_regs *)hpc3->pbus_extregs[1]; - hal2->vol_regs = (struct hal2_vol_regs *)hpc3->pbus_extregs[2]; - hal2->syn_regs = (struct hal2_syn_regs *)hpc3->pbus_extregs[3]; - - if (hal2_detect(hal2) < 0) { - kfree(hal2); - return -ENODEV; - } - - hal2_init_codec(&hal2->dac, hpc3, 0); - hal2_init_codec(&hal2->adc, hpc3, 1); - - /* - * All DMA channel interfaces in HAL2 are designed to operate with - * PBUS programmed for 2 cycles in D3, 2 cycles in D4 and 2 cycles - * in D5. HAL2 is a 16-bit device which can accept both big and little - * endian format. It assumes that even address bytes are on high - * portion of PBUS (15:8) and assumes that HPC3 is programmed to - * accept a live (unsynchronized) version of P_DREQ_N from HAL2. - */ -#define HAL2_PBUS_DMACFG ((0 << HPC3_DMACFG_D3R_SHIFT) | \ - (2 << HPC3_DMACFG_D4R_SHIFT) | \ - (2 << HPC3_DMACFG_D5R_SHIFT) | \ - (0 << HPC3_DMACFG_D3W_SHIFT) | \ - (2 << HPC3_DMACFG_D4W_SHIFT) | \ - (2 << HPC3_DMACFG_D5W_SHIFT) | \ - HPC3_DMACFG_DS16 | \ - HPC3_DMACFG_EVENHI | \ - HPC3_DMACFG_RTIME | \ - (8 << HPC3_DMACFG_BURST_SHIFT) | \ - HPC3_DMACFG_DRQLIVE) - /* - * Ignore what's mentioned in the specification and write value which - * works in The Real World (TM) - */ - hpc3->pbus_dmacfg[hal2->dac.pbus.pbusnr][0] = 0x8208844; - hpc3->pbus_dmacfg[hal2->adc.pbus.pbusnr][0] = 0x8208844; - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, hal2, &hal2_ops); - if (err < 0) { - free_irq(SGI_HPCDMA_IRQ, hal2); - kfree(hal2); - return err; - } - *rchip = hal2; - return 0; -} - -static int __devinit hal2_probe(struct platform_device *pdev) -{ - struct snd_card *card; - struct snd_hal2 *chip; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = hal2_create(card, &chip); - if (err < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - - err = hal2_pcm_create(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - err = hal2_mixer_create(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "SGI HAL2 Audio"); - strcpy(card->shortname, "SGI HAL2 Audio"); - sprintf(card->longname, "%s irq %i", - card->shortname, - SGI_HPCDMA_IRQ); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - platform_set_drvdata(pdev, card); - return 0; -} - -static int __devexit hal2_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - snd_card_free(card); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver hal2_driver = { - .probe = hal2_probe, - .remove = __devexit_p(hal2_remove), - .driver = { - .name = "sgihal2", - .owner = THIS_MODULE, - } -}; - -module_platform_driver(hal2_driver); diff --git a/ANDROID_3.4.5/sound/mips/hal2.h b/ANDROID_3.4.5/sound/mips/hal2.h deleted file mode 100644 index f19828bc..00000000 --- a/ANDROID_3.4.5/sound/mips/hal2.h +++ /dev/null @@ -1,245 +0,0 @@ -#ifndef __HAL2_H -#define __HAL2_H - -/* - * Driver for HAL2 sound processors - * Copyright (c) 1999 Ulf Carlsson - * Copyright (c) 2001, 2002, 2003 Ladislav Michl - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include - -/* Indirect status register */ - -#define H2_ISR_TSTATUS 0x01 /* RO: transaction status 1=busy */ -#define H2_ISR_USTATUS 0x02 /* RO: utime status bit 1=armed */ -#define H2_ISR_QUAD_MODE 0x04 /* codec mode 0=indigo 1=quad */ -#define H2_ISR_GLOBAL_RESET_N 0x08 /* chip global reset 0=reset */ -#define H2_ISR_CODEC_RESET_N 0x10 /* codec/synth reset 0=reset */ - -/* Revision register */ - -#define H2_REV_AUDIO_PRESENT 0x8000 /* RO: audio present 0=present */ -#define H2_REV_BOARD_M 0x7000 /* RO: bits 14:12, board revision */ -#define H2_REV_MAJOR_CHIP_M 0x00F0 /* RO: bits 7:4, major chip revision */ -#define H2_REV_MINOR_CHIP_M 0x000F /* RO: bits 3:0, minor chip revision */ - -/* Indirect address register */ - -/* - * Address of indirect internal register to be accessed. A write to this - * register initiates read or write access to the indirect registers in the - * HAL2. Note that there af four indirect data registers for write access to - * registers larger than 16 byte. - */ - -#define H2_IAR_TYPE_M 0xF000 /* bits 15:12, type of functional */ - /* block the register resides in */ - /* 1=DMA Port */ - /* 9=Global DMA Control */ - /* 2=Bresenham */ - /* 3=Unix Timer */ -#define H2_IAR_NUM_M 0x0F00 /* bits 11:8 instance of the */ - /* blockin which the indirect */ - /* register resides */ - /* If IAR_TYPE_M=DMA Port: */ - /* 1=Synth In */ - /* 2=AES In */ - /* 3=AES Out */ - /* 4=DAC Out */ - /* 5=ADC Out */ - /* 6=Synth Control */ - /* If IAR_TYPE_M=Global DMA Control: */ - /* 1=Control */ - /* If IAR_TYPE_M=Bresenham: */ - /* 1=Bresenham Clock Gen 1 */ - /* 2=Bresenham Clock Gen 2 */ - /* 3=Bresenham Clock Gen 3 */ - /* If IAR_TYPE_M=Unix Timer: */ - /* 1=Unix Timer */ -#define H2_IAR_ACCESS_SELECT 0x0080 /* 1=read 0=write */ -#define H2_IAR_PARAM 0x000C /* Parameter Select */ -#define H2_IAR_RB_INDEX_M 0x0003 /* Read Back Index */ - /* 00:word0 */ - /* 01:word1 */ - /* 10:word2 */ - /* 11:word3 */ -/* - * HAL2 internal addressing - * - * The HAL2 has "indirect registers" (idr) which are accessed by writing to the - * Indirect Data registers. Write the address to the Indirect Address register - * to transfer the data. - * - * We define the H2IR_* to the read address and H2IW_* to the write address and - * H2I_* to be fields in whatever register is referred to. - * - * When we write to indirect registers which are larger than one word (16 bit) - * we have to fill more than one indirect register before writing. When we read - * back however we have to read several times, each time with different Read - * Back Indexes (there are defs for doing this easily). - */ - -/* - * Relay Control - */ -#define H2I_RELAY_C 0x9100 -#define H2I_RELAY_C_STATE 0x01 /* state of RELAY pin signal */ - -/* DMA port enable */ - -#define H2I_DMA_PORT_EN 0x9104 -#define H2I_DMA_PORT_EN_SY_IN 0x01 /* Synth_in DMA port */ -#define H2I_DMA_PORT_EN_AESRX 0x02 /* AES receiver DMA port */ -#define H2I_DMA_PORT_EN_AESTX 0x04 /* AES transmitter DMA port */ -#define H2I_DMA_PORT_EN_CODECTX 0x08 /* CODEC transmit DMA port */ -#define H2I_DMA_PORT_EN_CODECR 0x10 /* CODEC receive DMA port */ - -#define H2I_DMA_END 0x9108 /* global dma endian select */ -#define H2I_DMA_END_SY_IN 0x01 /* Synth_in DMA port */ -#define H2I_DMA_END_AESRX 0x02 /* AES receiver DMA port */ -#define H2I_DMA_END_AESTX 0x04 /* AES transmitter DMA port */ -#define H2I_DMA_END_CODECTX 0x08 /* CODEC transmit DMA port */ -#define H2I_DMA_END_CODECR 0x10 /* CODEC receive DMA port */ - /* 0=b_end 1=l_end */ - -#define H2I_DMA_DRV 0x910C /* global PBUS DMA enable */ - -#define H2I_SYNTH_C 0x1104 /* Synth DMA control */ - -#define H2I_AESRX_C 0x1204 /* AES RX dma control */ - -#define H2I_C_TS_EN 0x20 /* Timestamp enable */ -#define H2I_C_TS_FRMT 0x40 /* Timestamp format */ -#define H2I_C_NAUDIO 0x80 /* Sign extend */ - -/* AESRX CTL, 16 bit */ - -#define H2I_AESTX_C 0x1304 /* AES TX DMA control */ -#define H2I_AESTX_C_CLKID_SHIFT 3 /* Bresenham Clock Gen 1-3 */ -#define H2I_AESTX_C_CLKID_M 0x18 -#define H2I_AESTX_C_DATAT_SHIFT 8 /* 1=mono 2=stereo (3=quad) */ -#define H2I_AESTX_C_DATAT_M 0x300 - -/* CODEC registers */ - -#define H2I_DAC_C1 0x1404 /* DAC DMA control, 16 bit */ -#define H2I_DAC_C2 0x1408 /* DAC DMA control, 32 bit */ -#define H2I_ADC_C1 0x1504 /* ADC DMA control, 16 bit */ -#define H2I_ADC_C2 0x1508 /* ADC DMA control, 32 bit */ - -/* Bits in CTL1 register */ - -#define H2I_C1_DMA_SHIFT 0 /* DMA channel */ -#define H2I_C1_DMA_M 0x7 -#define H2I_C1_CLKID_SHIFT 3 /* Bresenham Clock Gen 1-3 */ -#define H2I_C1_CLKID_M 0x18 -#define H2I_C1_DATAT_SHIFT 8 /* 1=mono 2=stereo (3=quad) */ -#define H2I_C1_DATAT_M 0x300 - -/* Bits in CTL2 register */ - -#define H2I_C2_R_GAIN_SHIFT 0 /* right a/d input gain */ -#define H2I_C2_R_GAIN_M 0xf -#define H2I_C2_L_GAIN_SHIFT 4 /* left a/d input gain */ -#define H2I_C2_L_GAIN_M 0xf0 -#define H2I_C2_R_SEL 0x100 /* right input select */ -#define H2I_C2_L_SEL 0x200 /* left input select */ -#define H2I_C2_MUTE 0x400 /* mute */ -#define H2I_C2_DO1 0x00010000 /* digital output port bit 0 */ -#define H2I_C2_DO2 0x00020000 /* digital output port bit 1 */ -#define H2I_C2_R_ATT_SHIFT 18 /* right d/a output - */ -#define H2I_C2_R_ATT_M 0x007c0000 /* attenuation */ -#define H2I_C2_L_ATT_SHIFT 23 /* left d/a output - */ -#define H2I_C2_L_ATT_M 0x0f800000 /* attenuation */ - -#define H2I_SYNTH_MAP_C 0x1104 /* synth dma handshake ctrl */ - -/* Clock generator CTL 1, 16 bit */ - -#define H2I_BRES1_C1 0x2104 -#define H2I_BRES2_C1 0x2204 -#define H2I_BRES3_C1 0x2304 - -#define H2I_BRES_C1_SHIFT 0 /* 0=48.0 1=44.1 2=aes_rx */ -#define H2I_BRES_C1_M 0x03 - -/* Clock generator CTL 2, 32 bit */ - -#define H2I_BRES1_C2 0x2108 -#define H2I_BRES2_C2 0x2208 -#define H2I_BRES3_C2 0x2308 - -#define H2I_BRES_C2_INC_SHIFT 0 /* increment value */ -#define H2I_BRES_C2_INC_M 0xffff -#define H2I_BRES_C2_MOD_SHIFT 16 /* modcontrol value */ -#define H2I_BRES_C2_MOD_M 0xffff0000 /* modctrl=0xffff&(modinc-1) */ - -/* Unix timer, 64 bit */ - -#define H2I_UTIME 0x3104 -#define H2I_UTIME_0_LD 0xffff /* microseconds, LSB's */ -#define H2I_UTIME_1_LD0 0x0f /* microseconds, MSB's */ -#define H2I_UTIME_1_LD1 0xf0 /* tenths of microseconds */ -#define H2I_UTIME_2_LD 0xffff /* seconds, LSB's */ -#define H2I_UTIME_3_LD 0xffff /* seconds, MSB's */ - -struct hal2_ctl_regs { - u32 _unused0[4]; - u32 isr; /* 0x10 Status Register */ - u32 _unused1[3]; - u32 rev; /* 0x20 Revision Register */ - u32 _unused2[3]; - u32 iar; /* 0x30 Indirect Address Register */ - u32 _unused3[3]; - u32 idr0; /* 0x40 Indirect Data Register 0 */ - u32 _unused4[3]; - u32 idr1; /* 0x50 Indirect Data Register 1 */ - u32 _unused5[3]; - u32 idr2; /* 0x60 Indirect Data Register 2 */ - u32 _unused6[3]; - u32 idr3; /* 0x70 Indirect Data Register 3 */ -}; - -struct hal2_aes_regs { - u32 rx_stat[2]; /* Status registers */ - u32 rx_cr[2]; /* Control registers */ - u32 rx_ud[4]; /* User data window */ - u32 rx_st[24]; /* Channel status data */ - - u32 tx_stat[1]; /* Status register */ - u32 tx_cr[3]; /* Control registers */ - u32 tx_ud[4]; /* User data window */ - u32 tx_st[24]; /* Channel status data */ -}; - -struct hal2_vol_regs { - u32 right; /* Right volume */ - u32 left; /* Left volume */ -}; - -struct hal2_syn_regs { - u32 _unused0[2]; - u32 page; /* DOC Page register */ - u32 regsel; /* DOC Register selection */ - u32 dlow; /* DOC Data low */ - u32 dhigh; /* DOC Data high */ - u32 irq; /* IRQ Status */ - u32 dram; /* DRAM Access */ -}; - -#endif /* __HAL2_H */ diff --git a/ANDROID_3.4.5/sound/mips/sgio2audio.c b/ANDROID_3.4.5/sound/mips/sgio2audio.c deleted file mode 100644 index ceaa593e..00000000 --- a/ANDROID_3.4.5/sound/mips/sgio2audio.c +++ /dev/null @@ -1,979 +0,0 @@ -/* - * Sound driver for Silicon Graphics O2 Workstations A/V board audio. - * - * Copyright 2003 Vivien Chappelier - * Copyright 2008 Thomas Bogendoerfer - * Mxier part taken from mace_audio.c: - * Copyright 2007 Thorben Jändling - * - * 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 - -#include -#include - -#include -#include -#include -#define SNDRV_GET_ID -#include -#include - - -MODULE_AUTHOR("Vivien Chappelier "); -MODULE_DESCRIPTION("SGI O2 Audio"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Silicon Graphics, O2 Audio}}"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for SGI O2 soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for SGI O2 soundcard."); - - -#define AUDIO_CONTROL_RESET BIT(0) /* 1: reset audio interface */ -#define AUDIO_CONTROL_CODEC_PRESENT BIT(1) /* 1: codec detected */ - -#define CODEC_CONTROL_WORD_SHIFT 0 -#define CODEC_CONTROL_READ BIT(16) -#define CODEC_CONTROL_ADDRESS_SHIFT 17 - -#define CHANNEL_CONTROL_RESET BIT(10) /* 1: reset channel */ -#define CHANNEL_DMA_ENABLE BIT(9) /* 1: enable DMA transfer */ -#define CHANNEL_INT_THRESHOLD_DISABLED (0 << 5) /* interrupt disabled */ -#define CHANNEL_INT_THRESHOLD_25 (1 << 5) /* int on buffer >25% full */ -#define CHANNEL_INT_THRESHOLD_50 (2 << 5) /* int on buffer >50% full */ -#define CHANNEL_INT_THRESHOLD_75 (3 << 5) /* int on buffer >75% full */ -#define CHANNEL_INT_THRESHOLD_EMPTY (4 << 5) /* int on buffer empty */ -#define CHANNEL_INT_THRESHOLD_NOT_EMPTY (5 << 5) /* int on buffer !empty */ -#define CHANNEL_INT_THRESHOLD_FULL (6 << 5) /* int on buffer empty */ -#define CHANNEL_INT_THRESHOLD_NOT_FULL (7 << 5) /* int on buffer !empty */ - -#define CHANNEL_RING_SHIFT 12 -#define CHANNEL_RING_SIZE (1 << CHANNEL_RING_SHIFT) -#define CHANNEL_RING_MASK (CHANNEL_RING_SIZE - 1) - -#define CHANNEL_LEFT_SHIFT 40 -#define CHANNEL_RIGHT_SHIFT 8 - -struct snd_sgio2audio_chan { - int idx; - struct snd_pcm_substream *substream; - int pos; - snd_pcm_uframes_t size; - spinlock_t lock; -}; - -/* definition of the chip-specific record */ -struct snd_sgio2audio { - struct snd_card *card; - - /* codec */ - struct snd_ad1843 ad1843; - spinlock_t ad1843_lock; - - /* channels */ - struct snd_sgio2audio_chan channel[3]; - - /* resources */ - void *ring_base; - dma_addr_t ring_base_dma; -}; - -/* AD1843 access */ - -/* - * read_ad1843_reg returns the current contents of a 16 bit AD1843 register. - * - * Returns unsigned register value on success, -errno on failure. - */ -static int read_ad1843_reg(void *priv, int reg) -{ - struct snd_sgio2audio *chip = priv; - int val; - unsigned long flags; - - spin_lock_irqsave(&chip->ad1843_lock, flags); - - writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) | - CODEC_CONTROL_READ, &mace->perif.audio.codec_control); - wmb(); - val = readq(&mace->perif.audio.codec_control); /* flush bus */ - udelay(200); - - val = readq(&mace->perif.audio.codec_read); - - spin_unlock_irqrestore(&chip->ad1843_lock, flags); - return val; -} - -/* - * write_ad1843_reg writes the specified value to a 16 bit AD1843 register. - */ -static int write_ad1843_reg(void *priv, int reg, int word) -{ - struct snd_sgio2audio *chip = priv; - int val; - unsigned long flags; - - spin_lock_irqsave(&chip->ad1843_lock, flags); - - writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) | - (word << CODEC_CONTROL_WORD_SHIFT), - &mace->perif.audio.codec_control); - wmb(); - val = readq(&mace->perif.audio.codec_control); /* flush bus */ - udelay(200); - - spin_unlock_irqrestore(&chip->ad1843_lock, flags); - return 0; -} - -static int sgio2audio_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = ad1843_get_gain_max(&chip->ad1843, - (int)kcontrol->private_value); - return 0; -} - -static int sgio2audio_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - int vol; - - vol = ad1843_get_gain(&chip->ad1843, (int)kcontrol->private_value); - - ucontrol->value.integer.value[0] = (vol >> 8) & 0xFF; - ucontrol->value.integer.value[1] = vol & 0xFF; - - return 0; -} - -static int sgio2audio_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - int newvol, oldvol; - - oldvol = ad1843_get_gain(&chip->ad1843, kcontrol->private_value); - newvol = (ucontrol->value.integer.value[0] << 8) | - ucontrol->value.integer.value[1]; - - newvol = ad1843_set_gain(&chip->ad1843, kcontrol->private_value, - newvol); - - return newvol != oldvol; -} - -static int sgio2audio_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[3] = { - "Cam Mic", "Mic", "Line" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= 3) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int sgio2audio_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = ad1843_get_recsrc(&chip->ad1843); - return 0; -} - -static int sgio2audio_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol); - int newsrc, oldsrc; - - oldsrc = ad1843_get_recsrc(&chip->ad1843); - newsrc = ad1843_set_recsrc(&chip->ad1843, - ucontrol->value.enumerated.item[0]); - - return newsrc != oldsrc; -} - -/* dac1/pcm0 mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_PCM_0, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* dac2/pcm1 mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .index = 1, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_PCM_1, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* record level mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_RECLEV, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* record level source control */ -static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = sgio2audio_source_info, - .get = sgio2audio_source_get, - .put = sgio2audio_source_put, -}; - -/* line mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Playback Volume", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_LINE, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* cd mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Playback Volume", - .index = 1, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_LINE_2, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - -/* mic mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = AD1843_GAIN_MIC, - .info = sgio2audio_gain_info, - .get = sgio2audio_gain_get, - .put = sgio2audio_gain_put, -}; - - -static int __devinit snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip) -{ - int err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_pcm0, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_pcm1, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_reclevel, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_recsource, chip)); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_line, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_cd, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&sgio2audio_ctrl_mic, chip)); - if (err < 0) - return err; - - return 0; -} - -/* low-level audio interface DMA */ - -/* get data out of bounce buffer, count must be a multiple of 32 */ -/* returns 1 if a period has elapsed */ -static int snd_sgio2audio_dma_pull_frag(struct snd_sgio2audio *chip, - unsigned int ch, unsigned int count) -{ - int ret; - unsigned long src_base, src_pos, dst_mask; - unsigned char *dst_base; - int dst_pos; - u64 *src; - s16 *dst; - u64 x; - unsigned long flags; - struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime; - - spin_lock_irqsave(&chip->channel[ch].lock, flags); - - src_base = (unsigned long) chip->ring_base | (ch << CHANNEL_RING_SHIFT); - src_pos = readq(&mace->perif.audio.chan[ch].read_ptr); - dst_base = runtime->dma_area; - dst_pos = chip->channel[ch].pos; - dst_mask = frames_to_bytes(runtime, runtime->buffer_size) - 1; - - /* check if a period has elapsed */ - chip->channel[ch].size += (count >> 3); /* in frames */ - ret = chip->channel[ch].size >= runtime->period_size; - chip->channel[ch].size %= runtime->period_size; - - while (count) { - src = (u64 *)(src_base + src_pos); - dst = (s16 *)(dst_base + dst_pos); - - x = *src; - dst[0] = (x >> CHANNEL_LEFT_SHIFT) & 0xffff; - dst[1] = (x >> CHANNEL_RIGHT_SHIFT) & 0xffff; - - src_pos = (src_pos + sizeof(u64)) & CHANNEL_RING_MASK; - dst_pos = (dst_pos + 2 * sizeof(s16)) & dst_mask; - count -= sizeof(u64); - } - - writeq(src_pos, &mace->perif.audio.chan[ch].read_ptr); /* in bytes */ - chip->channel[ch].pos = dst_pos; - - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); - return ret; -} - -/* put some DMA data in bounce buffer, count must be a multiple of 32 */ -/* returns 1 if a period has elapsed */ -static int snd_sgio2audio_dma_push_frag(struct snd_sgio2audio *chip, - unsigned int ch, unsigned int count) -{ - int ret; - s64 l, r; - unsigned long dst_base, dst_pos, src_mask; - unsigned char *src_base; - int src_pos; - u64 *dst; - s16 *src; - unsigned long flags; - struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime; - - spin_lock_irqsave(&chip->channel[ch].lock, flags); - - dst_base = (unsigned long)chip->ring_base | (ch << CHANNEL_RING_SHIFT); - dst_pos = readq(&mace->perif.audio.chan[ch].write_ptr); - src_base = runtime->dma_area; - src_pos = chip->channel[ch].pos; - src_mask = frames_to_bytes(runtime, runtime->buffer_size) - 1; - - /* check if a period has elapsed */ - chip->channel[ch].size += (count >> 3); /* in frames */ - ret = chip->channel[ch].size >= runtime->period_size; - chip->channel[ch].size %= runtime->period_size; - - while (count) { - src = (s16 *)(src_base + src_pos); - dst = (u64 *)(dst_base + dst_pos); - - l = src[0]; /* sign extend */ - r = src[1]; /* sign extend */ - - *dst = ((l & 0x00ffffff) << CHANNEL_LEFT_SHIFT) | - ((r & 0x00ffffff) << CHANNEL_RIGHT_SHIFT); - - dst_pos = (dst_pos + sizeof(u64)) & CHANNEL_RING_MASK; - src_pos = (src_pos + 2 * sizeof(s16)) & src_mask; - count -= sizeof(u64); - } - - writeq(dst_pos, &mace->perif.audio.chan[ch].write_ptr); /* in bytes */ - chip->channel[ch].pos = src_pos; - - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); - return ret; -} - -static int snd_sgio2audio_dma_start(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_sgio2audio_chan *chan = substream->runtime->private_data; - int ch = chan->idx; - - /* reset DMA channel */ - writeq(CHANNEL_CONTROL_RESET, &mace->perif.audio.chan[ch].control); - udelay(10); - writeq(0, &mace->perif.audio.chan[ch].control); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* push a full buffer */ - snd_sgio2audio_dma_push_frag(chip, ch, CHANNEL_RING_SIZE - 32); - } - /* set DMA to wake on 50% empty and enable interrupt */ - writeq(CHANNEL_DMA_ENABLE | CHANNEL_INT_THRESHOLD_50, - &mace->perif.audio.chan[ch].control); - return 0; -} - -static int snd_sgio2audio_dma_stop(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio_chan *chan = substream->runtime->private_data; - - writeq(0, &mace->perif.audio.chan[chan->idx].control); - return 0; -} - -static irqreturn_t snd_sgio2audio_dma_in_isr(int irq, void *dev_id) -{ - struct snd_sgio2audio_chan *chan = dev_id; - struct snd_pcm_substream *substream; - struct snd_sgio2audio *chip; - int count, ch; - - substream = chan->substream; - chip = snd_pcm_substream_chip(substream); - ch = chan->idx; - - /* empty the ring */ - count = CHANNEL_RING_SIZE - - readq(&mace->perif.audio.chan[ch].depth) - 32; - if (snd_sgio2audio_dma_pull_frag(chip, ch, count)) - snd_pcm_period_elapsed(substream); - - return IRQ_HANDLED; -} - -static irqreturn_t snd_sgio2audio_dma_out_isr(int irq, void *dev_id) -{ - struct snd_sgio2audio_chan *chan = dev_id; - struct snd_pcm_substream *substream; - struct snd_sgio2audio *chip; - int count, ch; - - substream = chan->substream; - chip = snd_pcm_substream_chip(substream); - ch = chan->idx; - /* fill the ring */ - count = CHANNEL_RING_SIZE - - readq(&mace->perif.audio.chan[ch].depth) - 32; - if (snd_sgio2audio_dma_push_frag(chip, ch, count)) - snd_pcm_period_elapsed(substream); - - return IRQ_HANDLED; -} - -static irqreturn_t snd_sgio2audio_error_isr(int irq, void *dev_id) -{ - struct snd_sgio2audio_chan *chan = dev_id; - struct snd_pcm_substream *substream; - - substream = chan->substream; - snd_sgio2audio_dma_stop(substream); - snd_sgio2audio_dma_start(substream); - return IRQ_HANDLED; -} - -/* PCM part */ -/* PCM hardware definition */ -static struct snd_pcm_hardware snd_sgio2audio_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = SNDRV_PCM_FMTBIT_S16_BE, - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 32768, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, -}; - -/* PCM playback open callback */ -static int snd_sgio2audio_playback1_open(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_sgio2audio_pcm_hw; - runtime->private_data = &chip->channel[1]; - return 0; -} - -static int snd_sgio2audio_playback2_open(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_sgio2audio_pcm_hw; - runtime->private_data = &chip->channel[2]; - return 0; -} - -/* PCM capture open callback */ -static int snd_sgio2audio_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_sgio2audio_pcm_hw; - runtime->private_data = &chip->channel[0]; - return 0; -} - -/* PCM close callback */ -static int snd_sgio2audio_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->private_data = NULL; - return 0; -} - - -/* hw_params callback */ -static int snd_sgio2audio_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_alloc_vmalloc_buffer(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_sgio2audio_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_vmalloc_buffer(substream); -} - -/* prepare callback */ -static int snd_sgio2audio_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_sgio2audio_chan *chan = substream->runtime->private_data; - int ch = chan->idx; - unsigned long flags; - - spin_lock_irqsave(&chip->channel[ch].lock, flags); - - /* Setup the pseudo-dma transfer pointers. */ - chip->channel[ch].pos = 0; - chip->channel[ch].size = 0; - chip->channel[ch].substream = substream; - - /* set AD1843 format */ - /* hardware format is always S16_LE */ - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - ad1843_setup_dac(&chip->ad1843, - ch - 1, - runtime->rate, - SNDRV_PCM_FORMAT_S16_LE, - runtime->channels); - break; - case SNDRV_PCM_STREAM_CAPTURE: - ad1843_setup_adc(&chip->ad1843, - runtime->rate, - SNDRV_PCM_FORMAT_S16_LE, - runtime->channels); - break; - } - spin_unlock_irqrestore(&chip->channel[ch].lock, flags); - return 0; -} - -/* trigger callback */ -static int snd_sgio2audio_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* start the PCM engine */ - snd_sgio2audio_dma_start(substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - /* stop the PCM engine */ - snd_sgio2audio_dma_stop(substream); - break; - default: - return -EINVAL; - } - return 0; -} - -/* pointer callback */ -static snd_pcm_uframes_t -snd_sgio2audio_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream); - struct snd_sgio2audio_chan *chan = substream->runtime->private_data; - - /* get the current hardware pointer */ - return bytes_to_frames(substream->runtime, - chip->channel[chan->idx].pos); -} - -/* operators */ -static struct snd_pcm_ops snd_sgio2audio_playback1_ops = { - .open = snd_sgio2audio_playback1_open, - .close = snd_sgio2audio_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sgio2audio_pcm_hw_params, - .hw_free = snd_sgio2audio_pcm_hw_free, - .prepare = snd_sgio2audio_pcm_prepare, - .trigger = snd_sgio2audio_pcm_trigger, - .pointer = snd_sgio2audio_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static struct snd_pcm_ops snd_sgio2audio_playback2_ops = { - .open = snd_sgio2audio_playback2_open, - .close = snd_sgio2audio_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sgio2audio_pcm_hw_params, - .hw_free = snd_sgio2audio_pcm_hw_free, - .prepare = snd_sgio2audio_pcm_prepare, - .trigger = snd_sgio2audio_pcm_trigger, - .pointer = snd_sgio2audio_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -static struct snd_pcm_ops snd_sgio2audio_capture_ops = { - .open = snd_sgio2audio_capture_open, - .close = snd_sgio2audio_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sgio2audio_pcm_hw_params, - .hw_free = snd_sgio2audio_pcm_hw_free, - .prepare = snd_sgio2audio_pcm_prepare, - .trigger = snd_sgio2audio_pcm_trigger, - .pointer = snd_sgio2audio_pcm_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - -/* - * definitions of capture are omitted here... - */ - -/* create a pcm device */ -static int __devinit snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip) -{ - struct snd_pcm *pcm; - int err; - - /* create first pcm device with one outputs and one input */ - err = snd_pcm_new(chip->card, "SGI O2 Audio", 0, 1, 1, &pcm); - if (err < 0) - return err; - - pcm->private_data = chip; - strcpy(pcm->name, "SGI O2 DAC1"); - - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_sgio2audio_playback1_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_sgio2audio_capture_ops); - - /* create second pcm device with one outputs and no input */ - err = snd_pcm_new(chip->card, "SGI O2 Audio", 1, 1, 0, &pcm); - if (err < 0) - return err; - - pcm->private_data = chip; - strcpy(pcm->name, "SGI O2 DAC2"); - - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_sgio2audio_playback2_ops); - - return 0; -} - -static struct { - int idx; - int irq; - irqreturn_t (*isr)(int, void *); - const char *desc; -} snd_sgio2_isr_table[] = { - { - .idx = 0, - .irq = MACEISA_AUDIO1_DMAT_IRQ, - .isr = snd_sgio2audio_dma_in_isr, - .desc = "Capture DMA Channel 0" - }, { - .idx = 0, - .irq = MACEISA_AUDIO1_OF_IRQ, - .isr = snd_sgio2audio_error_isr, - .desc = "Capture Overflow" - }, { - .idx = 1, - .irq = MACEISA_AUDIO2_DMAT_IRQ, - .isr = snd_sgio2audio_dma_out_isr, - .desc = "Playback DMA Channel 1" - }, { - .idx = 1, - .irq = MACEISA_AUDIO2_MERR_IRQ, - .isr = snd_sgio2audio_error_isr, - .desc = "Memory Error Channel 1" - }, { - .idx = 2, - .irq = MACEISA_AUDIO3_DMAT_IRQ, - .isr = snd_sgio2audio_dma_out_isr, - .desc = "Playback DMA Channel 2" - }, { - .idx = 2, - .irq = MACEISA_AUDIO3_MERR_IRQ, - .isr = snd_sgio2audio_error_isr, - .desc = "Memory Error Channel 2" - } -}; - -/* ALSA driver */ - -static int snd_sgio2audio_free(struct snd_sgio2audio *chip) -{ - int i; - - /* reset interface */ - writeq(AUDIO_CONTROL_RESET, &mace->perif.audio.control); - udelay(1); - writeq(0, &mace->perif.audio.control); - - /* release IRQ's */ - for (i = 0; i < ARRAY_SIZE(snd_sgio2_isr_table); i++) - free_irq(snd_sgio2_isr_table[i].irq, - &chip->channel[snd_sgio2_isr_table[i].idx]); - - dma_free_coherent(NULL, MACEISA_RINGBUFFERS_SIZE, - chip->ring_base, chip->ring_base_dma); - - /* release card data */ - kfree(chip); - return 0; -} - -static int snd_sgio2audio_dev_free(struct snd_device *device) -{ - struct snd_sgio2audio *chip = device->device_data; - - return snd_sgio2audio_free(chip); -} - -static struct snd_device_ops ops = { - .dev_free = snd_sgio2audio_dev_free, -}; - -static int __devinit snd_sgio2audio_create(struct snd_card *card, - struct snd_sgio2audio **rchip) -{ - struct snd_sgio2audio *chip; - int i, err; - - *rchip = NULL; - - /* check if a codec is attached to the interface */ - /* (Audio or Audio/Video board present) */ - if (!(readq(&mace->perif.audio.control) & AUDIO_CONTROL_CODEC_PRESENT)) - return -ENOENT; - - chip = kzalloc(sizeof(struct snd_sgio2audio), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - - chip->card = card; - - chip->ring_base = dma_alloc_coherent(NULL, MACEISA_RINGBUFFERS_SIZE, - &chip->ring_base_dma, GFP_USER); - if (chip->ring_base == NULL) { - printk(KERN_ERR - "sgio2audio: could not allocate ring buffers\n"); - kfree(chip); - return -ENOMEM; - } - - spin_lock_init(&chip->ad1843_lock); - - /* initialize channels */ - for (i = 0; i < 3; i++) { - spin_lock_init(&chip->channel[i].lock); - chip->channel[i].idx = i; - } - - /* allocate IRQs */ - for (i = 0; i < ARRAY_SIZE(snd_sgio2_isr_table); i++) { - if (request_irq(snd_sgio2_isr_table[i].irq, - snd_sgio2_isr_table[i].isr, - 0, - snd_sgio2_isr_table[i].desc, - &chip->channel[snd_sgio2_isr_table[i].idx])) { - snd_sgio2audio_free(chip); - printk(KERN_ERR "sgio2audio: cannot allocate irq %d\n", - snd_sgio2_isr_table[i].irq); - return -EBUSY; - } - } - - /* reset the interface */ - writeq(AUDIO_CONTROL_RESET, &mace->perif.audio.control); - udelay(1); - writeq(0, &mace->perif.audio.control); - msleep_interruptible(1); /* give time to recover */ - - /* set ring base */ - writeq(chip->ring_base_dma, &mace->perif.ctrl.ringbase); - - /* attach the AD1843 codec */ - chip->ad1843.read = read_ad1843_reg; - chip->ad1843.write = write_ad1843_reg; - chip->ad1843.chip = chip; - - /* initialize the AD1843 codec */ - err = ad1843_init(&chip->ad1843); - if (err < 0) { - snd_sgio2audio_free(chip); - return err; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_sgio2audio_free(chip); - return err; - } - *rchip = chip; - return 0; -} - -static int __devinit snd_sgio2audio_probe(struct platform_device *pdev) -{ - struct snd_card *card; - struct snd_sgio2audio *chip; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_sgio2audio_create(card, &chip); - if (err < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - - err = snd_sgio2audio_new_pcm(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - err = snd_sgio2audio_new_mixer(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "SGI O2 Audio"); - strcpy(card->shortname, "SGI O2 Audio"); - sprintf(card->longname, "%s irq %i-%i", - card->shortname, - MACEISA_AUDIO1_DMAT_IRQ, - MACEISA_AUDIO3_MERR_IRQ); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - platform_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_sgio2audio_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - snd_card_free(card); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver sgio2audio_driver = { - .probe = snd_sgio2audio_probe, - .remove = __devexit_p(snd_sgio2audio_remove), - .driver = { - .name = "sgio2audio", - .owner = THIS_MODULE, - } -}; - -module_platform_driver(sgio2audio_driver); diff --git a/ANDROID_3.4.5/sound/oss/CHANGELOG b/ANDROID_3.4.5/sound/oss/CHANGELOG deleted file mode 100644 index 8706cd66..00000000 --- a/ANDROID_3.4.5/sound/oss/CHANGELOG +++ /dev/null @@ -1,369 +0,0 @@ -Note these changes relate to Hannu's code and don't include the changes -made outside of this for modularising the sound - -Changelog for version 3.8o --------------------------- - -Since 3.8h -- Included support for OPL3-SA1 and SoftOSS - -Since 3.8 -- Fixed SNDCTL_DSP_GETOSPACE -- Compatibility fixes for Linux 2.1.47 - -Since 3.8-beta21 -- Fixed all known bugs (I think). - -Since 3.8-beta8 -- Lot of fixes to audio playback code in dmabuf.c - -Since 3.8-beta6 -- Fixed the famous Quake delay bug. - -Since 3.8-beta5 -- Fixed many bugs in audio playback. - -Since 3.8-beta4 -- Just minor changes. - -Since 3.8-beta1 -- Major rewrite of audio playback handling. -- Added AWE32 support by Takashi Iwai (in ./lowlevel/). - -Since 3.7-beta# -- Passing of ioctl() parameters between soundcard.c and other modules has been -changed so that arg always points to kernel space. -- Some bugfixes. - -Since 3.7-beta5 -- Disabled MIDI input with GUS PnP (Interwave). There seems to be constant -stream of received 0x00 bytes when the MIDI receiver is enabled. - -Since 3.5 -- Changes almost everywhere. -- Support for OPTi 82C924-based sound cards. - -Since 3.5.4-beta8 -- Fixed a bug in handling of non-fragment sized writes in 16 bit/stereo mode - with GUS. -- Limited minimum fragment size with some audio devices (GUS=512 and - SB=32). These devices require more time to "recover" from processing - of each fragment. - -Since 3.5.4-beta6/7 -- There seems to be problems in the OPTi 82C930 so cards based on this - chip don't necessarily work yet. There are problems in detecting the - MIDI interface. Also mixer volumes may be seriously wrong on some systems. - You can safely use this driver version with C930 if it looks to work. - However please don't complain if you have problems with it. C930 support - should be fixed in future releases. -- Got initialization of GUS PnP to work. With this version GUS PnP should - work in GUS compatible mode after initialization using isapnptools. -- Fixed a bug in handling of full duplex cards in write only mode. This has - been causing "audio device opening" errors with RealAudio player. - -Since 3.5.4.beta5 -- Changes to OPTi 82C930 driver. -- Major changes to the Soundscape driver. The driver requires now just one - DMA channel. The extra audio/dsp device (the "Not functional" one) used - for code download in the earlier versions has been eliminated. There is now - just one /dev/dsp# device which is used both for code download and audio. - -Since 3.5.4.beta4 -- Minor changes. - -Since 3.5.4-beta2 -- Fixed silent playback with ESS 688/1688. -- Got SB16 to work without the 16 bit DMA channel (only the 8 bit one - is required for 8 and 16 bit modes). -- Added the "lowlevel" subdirectory for additional low level drivers that - are not part of USS core. See lowlevel/README for more info. -- Included support for ACI mixer (by Markus Kuhn). ACI is a mixer used in - miroPCM sound cards. See lowlevel/aci.readme for more info. -- Support for Aztech Washington chipset (AZT2316 ASIC). - -Since 3.5.4-beta1 -- Reduced clicking with AD1848. -- Support for OPTi 82C930. Only half duplex at this time. 16 bit playback - is sometimes just white noise (occurs randomly). - -Since 3.5.2 -- Major changes to the SB/Jazz16/ESS driver (most parts rewritten). - The most noticeable new feature is support for multiple SB cards at the same - time. -- Renamed sb16_midi.c to uart401.c. Also modified it to work also with - other MPU401 UART compatible cards than SB16/ESS/Jazz. -- Some changes which reduce clicking in audio playback. -- Copying policy is now GPL. - -Since 3.5.1 -- TB Maui initialization support -Since 3.5 -- Improved handling of playback underrun situations. - -Since 3.5-beta10 -- Bug fixing - -Since 3.5-beta9 -- Fixed for compatibility with Linux 1.3.70 and later. -- Changed boot time passing of 16 bit DMA channel number to SB driver. - -Since 3.5-beta8 -- Minor changes - -Since 3.5-beta7 -- enhancements to configure program (by Jeff Tranter): - - prompts are in same format as 1.3.x Linux kernel config program - - on-line help for each question - - fixed some compile warnings detected by gcc/g++ -Wall - - minor grammatical changes to prompts - -Since 3.5-beta6 -- Fixed bugs in mmap() support. -- Minor changes to Maui driver. - -Since 3.5-beta5 -- Fixed crash after recording with ESS688. It's generally a good - idea to stop inbound DMA transfers before freeing the memory - buffer. -- Fixed handling of AD1845 codec (for example Shuttle Sound System). -- Few other fixes. - -Since 3.5-beta4 -- Fixed bug in handling of uninitialized instruments with GUS. - -Since 3.5-beta3 -- Few changes which decrease popping at end/beginning of audio playback. - -Since 3.5-beta2 -- Removed MAD16+CS4231 hack made in previous version since it didn't - help. -- Fixed the above bug in proper way and in proper place. Many thanks - to James Hightower. - -Since 3.5-beta1 -- Bug fixes. -- Full duplex audio with MAD16+CS4231 may work now. The driver configures - SB DMA of MAD16 so that it doesn't conflict with codec's DMA channels. - The side effect is that all 8 bit DMA channels (0,1,3) are populated in - duplex mode. - -Since 3.5-alpha9 -- Bug fixes (mostly in Jazz16 and ESS1688/688 supports). -- Temporarily disabled recording with ESS1688/688 since it causes crash. -- Changed audio buffer partitioning algorithm so that it selects - smaller fragment size than earlier. This improves real time capabilities - of the driver and makes recording to disk to work better. Unfortunately - this change breaks some programs which assume that fragments cannot be - shorter than 4096 bytes. - -Since 3.5-alpha8 -- Bug fixes - -Since 3.5-alpha7 -- Linux kernel compatible configuration (_EXPERIMENTAL_). Enable - using command "cd /linux/drivers/sound;make script" and then - just run kernel's make config normally. -- Minor fixes to the SB support. Hopefully the driver works with - all SB models now. -- Added support for ESS ES1688 "AudioDrive" based cards. - -Since 3.5-alpha6 -- SB Pro and SB16 supports are no longer separately selectable options. - Enabling SB enables them too. -- Changed all #ifndef EXCLUDE_xx stuff to #ifdef CONFIG_xx. Modified -configure to handle this. -- Removed initialization messages from the -modularized version. They can be enabled by using init_trace=1 in -the insmod command line (insmod sound init_trace=1). -- More AIX stuff. -- Added support for synchronizing dsp/audio devices with /dev/sequencer. -- mmap() support for dsp/audio devices. - -Since 3.5-alpha5 -- AIX port. -- Changed some xxx_PATCH macros in soundcard.h to work with - big endian machines. - -Since 3.5-alpha4 -- Removed the 'setfx' stuff from the version distributed with kernel - sources. Running 'setfx' is required again. - -Since 3.5-alpha3 -- Moved stuff from the 'setfx' program to the AudioTrix Pro driver. - -Since 3.5-alpha2 -- Modifications to makefile and configure.c. Unnecessary sources - are no longer compiled. Newly created local.h is also copied to - /etc/soundconf. "make oldconfig" reads /etc/soundconf and produces - new local.h which is compatible with current version of the driver. -- Some fixes to the SB16 support. -- Fixed random protection fault in gus_wave.c - -Since 3.5-alpha1 -- Modified to work with Linux-1.3.33 and later -- Some minor changes - -Since 3.0.2 -- Support for CS4232 based PnP cards (AcerMagic S23 etc). -- Full duplex support for some CS4231, CS4232 and AD1845 based cards -(GUS MAX, AudioTrix Pro, AcerMagic S23 and many MAD16/Mozart cards -having a codec mentioned above). -- Almost fully rewritten loadable modules support. -- Fixed some bugs. -- Huge amount of testing (more testing is still required). -- mmap() support (works with some cards). Requires much more testing. -- Sample/patch/program loading for TB Maui/Tropez. No initialization -since TB doesn't allow me to release that code. -- Using CS4231 compatible codecs as timer for /dev/music. - -Since 3.0.1 -- Added allocation of I/O ports, DMA channels and interrupts -to the initialization code. This may break modules support since -the driver may not free some resources on unload. Should be fixed soon. - -Since 3.0 -- Some important bug fixes. -- select() for /dev/dsp and /dev/audio (Linux only). -(To use select() with read, you have to call read() to start -the recording. Calling write() kills recording immediately so -use select() carefully when you are writing a half duplex app. -Full duplex mode is not implemented yet.) Select works also with -/dev/sequencer and /dev/music. Maybe with /dev/midi## too. - -Since 3.0-beta2 -- Minor fixes. -- Added Readme.cards - -Since 3.0-beta1 -- Minor fixes to the modules support. -- Eliminated call to sb_free_irq() in ad1848.c -- Rewritten MAD16&Mozart support (not tested with MAD16 Pro). -- Fix to DMA initialization of PSS cards. -- Some fixes to ad1848/cs42xx mixer support (GUS MAX, MSS, etc.) -- Fixed some bugs in the PSS driver which caused I/O errors with - the MSS mode (/dev/dsp). - -Since 3.0-950506 -- Recording with GUS MAX fixed. It works when the driver is configured - to use two DMA channels with GUS MAX (16 bit ones recommended). - -Since 3.0-94xxxx -- Too many changes - -Since 3.0-940818 -- Fixes for Linux 1.1.4x. -- Disables Disney Sound System with SG NX Pro 16 (less noise). - -Since 2.90-2 -- Fixes to soundcard.h -- Non blocking mode to /dev/sequencer -- Experimental detection code for Ensoniq Soundscape. - -Since 2.90 -- Minor and major bug fixes - -Since pre-3.0-940712 -- GUS MAX support -- Partially working MSS/WSS support (could work with some cards). -- Hardware u-Law and A-Law support with AD1848/CS4248 and CS4231 codecs - (GUS MAX, GUS16, WSS etc). Hardware ADPCM is possible with GUS16 and - GUS MAX, but it doesn't work yet. -Since pre-3.0-940426 -- AD1848/CS4248/CS4231 codec support (MSS, GUS MAX, Aztec, Orchid etc). -This codec chip is used in various sound cards. This version is developed -for the 16 bit daughtercard of GUS. It should work with other cards also -if the following requirements are met: - - The I/O, IRQ and DMA settings are jumper selectable or - the card is initialized by booting DOS before booting Linux (etc.). - - You add the IO, IRQ and DMA settings manually to the local.h. - (Just define GUS16_BASE, GUS16_IRQ and GUS16_DMA). Note that - the base address bust be the base address of the codec chip not the - card itself. For the GUS16 these are the same but most MSS compatible - cards have the codec located at card_base+4. -- Some minor changes - -Since 2.5 (******* MAJOR REWRITE ***********) - -This version is based on v2.3. I have tried to maintain two versions -together so that this one should have the same features than v2.5. -Something may still be missing. If you notice such things, please let me -know. - -The Readme.v30 contains more details. - -- /dev/midi## devices. -- /dev/sequencer2 - -Since 2.5-beta2 -- Some fine tuning to the GUS v3.7 mixer code. -- Fixed speed limits for the plain SB (1.0 to 2.0). - -Since 2.5-beta -- Fixed OPL-3 detection with SB. Caused problems with PAS16. -- GUS v3.7 mixer support. - -Since 2.4 -- Mixer support for Sound Galaxy NX Pro (define __SGNXPRO__ on your local.h). -- Fixed truncated sound on /dev/dsp when the device is closed. -- Linear volume mode for GUS -- Pitch bends larger than +/- 2 octaves. -- MIDI recording for SB and SB Pro. (Untested). -- Some other fixes. -- SB16 MIDI and DSP drivers only initialized if SB16 actually installed. -- Implemented better detection for OPL-3. This should be useful if you - have an old SB Pro (the non-OPL-3 one) or a SB 2.0 clone which has a OPL-3. -- SVR4.2 support by Ian Hartas. Initial ALPHA TEST version (untested). - -Since 2.3b -- Fixed bug which made it impossible to make long recordings to disk. - Recording was not restarted after a buffer overflow situation. -- Limited mixer support for GUS. -- Numerous improvements to the GUS driver by Andrew Robinson. Including - some click removal etc. - -Since 2.3 -- Fixed some minor bugs in the SB16 driver. - -Since 2.2b -- Full SB16 DSP support. 8/16 bit, mono/stereo -- The SCO and FreeBSD versions should be in sync now. There are some - problems with SB16 and GUS in the FreeBSD versions. - The DMA buffer allocation of the SCO version has been polished but - there could still be some problems. At least it hogs memory. - The DMA channel - configuration method used in the SCO/System is a hack. -- Support for the MPU emulation of the SB16. -- Some big arrays are now allocated boot time. This makes the BSS segment - smaller which makes it possible to use the full driver with - NetBSD. These arrays are not allocated if no suitable sound card is available. -- Fixed a bug in the compute_and_set_volume in gus_wave.c -- Fixed the too fast mono playback problem of SB Pro and PAS16. - -Since 2.2 -- Stereo recording for SB Pro. Somehow it was missing and nobody - had noticed it earlier. -- Minor polishing. -- Interpreting of boot time arguments (sound=) for Linux. -- Breakup of sb_dsp.c. Parts of the code has been moved to - sb_mixer.c and sb_midi.c - -Since 2.1 -- Preliminary support for SB16. - - The SB16 mixer is supported in its native mode. - - Digitized voice capability up to 44.1 kHz/8 bit/mono - (16 bit and stereo support coming in the next release). -- Fixed some bugs in the digitized voice driver for PAS16. -- Proper initialization of the SB emulation of latest PAS16 models. - -- Significantly improved /dev/dsp and /dev/audio support. - - Now supports half duplex mode. It's now possible to record and - playback without closing and reopening the device. - - It's possible to use smaller buffers than earlier. There is a new - ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &n) where n should be 1, 2 or 4. - This call instructs the driver to use smaller buffers. The default - buffer size (0.5 to 1.0 seconds) is divided by n. Should be called - immediately after opening the device. - -Since 2.0 -Just cosmetic changes. diff --git a/ANDROID_3.4.5/sound/oss/Kconfig b/ANDROID_3.4.5/sound/oss/Kconfig deleted file mode 100644 index 5849b129..00000000 --- a/ANDROID_3.4.5/sound/oss/Kconfig +++ /dev/null @@ -1,541 +0,0 @@ -# 18 Apr 1998, Michael Elizabeth Chastain, -# More hacking for modularisation. -# -# Prompt user for primary drivers. - -config SOUND_BCM_CS4297A - tristate "Crystal Sound CS4297a (for Swarm)" - depends on SIBYTE_SWARM - help - The BCM91250A has a Crystal CS4297a on synchronous serial - port B (in addition to the DB-9 serial port). Say Y or M - here to enable the sound chip instead of the UART. Also - note that CONFIG_KGDB should not be enabled at the same - time, since it also attempts to use this UART port. - -config SOUND_VWSND - tristate "SGI Visual Workstation Sound" - depends on X86_VISWS - help - Say Y or M if you have an SGI Visual Workstation and you want to be - able to use its on-board audio. Read - for more info on this driver's - capabilities. - -config SOUND_MSNDCLAS - tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" - depends on (m || !STANDALONE) && ISA - help - Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or - Monterey (not for the Pinnacle or Fiji). - - See for important information - about this driver. Note that it has been discontinued, but the - Voyetra Turtle Beach knowledge base entry for it is still available - at . - -comment "Compiled-in MSND Classic support requires firmware during compilation." - depends on SOUND_PRIME && SOUND_MSNDCLAS=y - -config MSNDCLAS_HAVE_BOOT - bool - depends on SOUND_MSNDCLAS=y && !STANDALONE - default y - -config MSNDCLAS_INIT_FILE - string "Full pathname of MSNDINIT.BIN firmware file" - depends on SOUND_MSNDCLAS - default "/etc/sound/msndinit.bin" - help - The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See - for information on how to - obtain this. - -config MSNDCLAS_PERM_FILE - string "Full pathname of MSNDPERM.BIN firmware file" - depends on SOUND_MSNDCLAS - default "/etc/sound/msndperm.bin" - help - The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See - for information on how to - obtain this. - -config MSNDCLAS_IRQ - int "MSND Classic IRQ 5, 7, 9, 10, 11, 12" - depends on SOUND_MSNDCLAS=y - default "5" - help - Interrupt Request line for the MultiSound Classic and related cards. - -config MSNDCLAS_MEM - hex "MSND Classic memory B0000, C8000, D0000, D8000, E0000, E8000" - depends on SOUND_MSNDCLAS=y - default "D0000" - help - Memory-mapped I/O base address for the MultiSound Classic and - related cards. - -config MSNDCLAS_IO - hex "MSND Classic I/O 210, 220, 230, 240, 250, 260, 290, 3E0" - depends on SOUND_MSNDCLAS=y - default "290" - help - I/O port address for the MultiSound Classic and related cards. - -config SOUND_MSNDPIN - tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji" - depends on (m || !STANDALONE) && ISA - help - Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji. - See for important information - about this driver. Note that it has been discontinued, but the - Voyetra Turtle Beach knowledge base entry for it is still available - at . - -comment "Compiled-in MSND Pinnacle support requires firmware during compilation." - depends on SOUND_PRIME && SOUND_MSNDPIN=y - -config MSNDPIN_HAVE_BOOT - bool - depends on SOUND_MSNDPIN=y - default y - -config MSNDPIN_INIT_FILE - string "Full pathname of PNDSPINI.BIN firmware file" - depends on SOUND_MSNDPIN - default "/etc/sound/pndspini.bin" - help - The MultiSound cards have two firmware files which are required - for operation, and are not currently included. These files can be - obtained from Turtle Beach. See - for information on how to - obtain this. - -config MSNDPIN_PERM_FILE - string "Full pathname of PNDSPERM.BIN firmware file" - depends on SOUND_MSNDPIN - default "/etc/sound/pndsperm.bin" - help - The MultiSound cards have two firmware files which are required for - operation, and are not currently included. These files can be - obtained from Turtle Beach. See - for information on how to - obtain this. - -config MSNDPIN_IRQ - int "MSND Pinnacle IRQ 5, 7, 9, 10, 11, 12" - depends on SOUND_MSNDPIN=y - default "5" - help - Interrupt request line for the primary synthesizer on MultiSound - Pinnacle and Fiji sound cards. - -config MSNDPIN_MEM - hex "MSND Pinnacle memory B0000, C8000, D0000, D8000, E0000, E8000" - depends on SOUND_MSNDPIN=y - default "D0000" - help - Memory-mapped I/O base address for the primary synthesizer on - MultiSound Pinnacle and Fiji sound cards. - -config MSNDPIN_IO - hex "MSND Pinnacle I/O 210, 220, 230, 240, 250, 260, 290, 3E0" - depends on SOUND_MSNDPIN=y - default "290" - help - Memory-mapped I/O base address for the primary synthesizer on - MultiSound Pinnacle and Fiji sound cards. - -config MSNDPIN_DIGITAL - bool "MSND Pinnacle has S/PDIF I/O" - depends on SOUND_MSNDPIN=y - help - If you have the S/PDIF daughter board for the Pinnacle or Fiji, - answer Y here; otherwise, say N. If you have this, you will be able - to play and record from the S/PDIF port (digital signal). See - for information on how to make - use of this capability. - -config MSNDPIN_NONPNP - bool "MSND Pinnacle non-PnP Mode" - depends on SOUND_MSNDPIN=y - help - The Pinnacle and Fiji card resources can be configured either with - PnP, or through a configuration port. Say Y here if your card is NOT - in PnP mode. For the Pinnacle, configuration in non-PnP mode allows - use of the IDE and joystick peripherals on the card as well; these - do not show up when the card is in PnP mode. Specifying zero for any - resource of a device will disable the device. If you are running the - card in PnP mode, you must say N here and use isapnptools to - configure the card's resources. - -comment "MSND Pinnacle DSP section will be configured to above parameters." - depends on SOUND_MSNDPIN=y && MSNDPIN_NONPNP - -config MSNDPIN_CFG - hex "MSND Pinnacle config port 250,260,270" - depends on MSNDPIN_NONPNP - default "250" - help - This is the port which the Pinnacle and Fiji uses to configure the - card's resources when not in PnP mode. If your card is in PnP mode, - then be sure to say N to the previous option, "MSND Pinnacle Non-PnP - Mode". - -comment "Pinnacle-specific Device Configuration (0 disables)" - depends on SOUND_MSNDPIN=y && MSNDPIN_NONPNP - -config MSNDPIN_MPU_IO - hex "MSND Pinnacle MPU I/O (e.g. 330)" - depends on MSNDPIN_NONPNP - default "0" - help - Memory-mapped I/O base address for the Kurzweil daughterboard - synthesizer on MultiSound Pinnacle and Fiji sound cards. - -config MSNDPIN_MPU_IRQ - int "MSND Pinnacle MPU IRQ (e.g. 9)" - depends on MSNDPIN_NONPNP - default "0" - help - Interrupt request number for the Kurzweil daughterboard - synthesizer on MultiSound Pinnacle and Fiji sound cards. - -config MSNDPIN_IDE_IO0 - hex "MSND Pinnacle IDE I/O 0 (e.g. 170)" - depends on MSNDPIN_NONPNP - default "0" - help - CD-ROM drive 0 memory-mapped I/O base address for the MultiSound - Pinnacle and Fiji sound cards. - -config MSNDPIN_IDE_IO1 - hex "MSND Pinnacle IDE I/O 1 (e.g. 376)" - depends on MSNDPIN_NONPNP - default "0" - help - CD-ROM drive 1 memory-mapped I/O base address for the MultiSound - Pinnacle and Fiji sound cards. - -config MSNDPIN_IDE_IRQ - int "MSND Pinnacle IDE IRQ (e.g. 15)" - depends on MSNDPIN_NONPNP - default "0" - help - Interrupt request number for the IDE CD-ROM interface on the - MultiSound Pinnacle and Fiji sound cards. - -config MSNDPIN_JOYSTICK_IO - hex "MSND Pinnacle joystick I/O (e.g. 200)" - depends on MSNDPIN_NONPNP - default "0" - help - Memory-mapped I/O base address for the joystick port on MultiSound - Pinnacle and Fiji sound cards. - -config MSND_FIFOSIZE - int "MSND buffer size (kB)" - depends on SOUND_MSNDPIN=y || SOUND_MSNDCLAS=y - default "128" - help - Configures the size of each audio buffer, in kilobytes, for - recording and playing in the MultiSound drivers (both the Classic - and Pinnacle). Larger values reduce the chance of data overruns at - the expense of overall latency. If unsure, use the default. - -menuconfig SOUND_OSS - tristate "OSS sound modules" - depends on ISA_DMA_API && VIRT_TO_BUS - help - OSS is the Open Sound System suite of sound card drivers. They make - sound programming easier since they provide a common API. Say Y or - M here (the module will be called sound) if you haven't found a - driver for your sound card above, then pick your driver from the - list below. - -if SOUND_OSS - -config SOUND_TRACEINIT - bool "Verbose initialisation" - help - Verbose soundcard initialization -- affects the format of autoprobe - and initialization messages at boot time. - -config SOUND_DMAP - bool "Persistent DMA buffers" - ---help--- - Linux can often have problems allocating DMA buffers for ISA sound - cards on machines with more than 16MB of RAM. This is because ISA - DMA buffers must exist below the 16MB boundary and it is quite - possible that a large enough free block in this region cannot be - found after the machine has been running for a while. If you say Y - here the DMA buffers (64Kb) will be allocated at boot time and kept - until the shutdown. This option is only useful if you said Y to - "OSS sound modules", above. If you said M to "OSS sound modules" - then you can get the persistent DMA buffer functionality by passing - the command-line argument "dmabuf=1" to the sound module. - - Say Y unless you have 16MB or more RAM or a PCI sound card. - -config SOUND_VMIDI - tristate "Loopback MIDI device support" - help - Support for MIDI loopback on port 1 or 2. - -config SOUND_TRIX - tristate "MediaTrix AudioTrix Pro support" - help - Answer Y if you have the AudioTriX Pro sound card manufactured - by MediaTrix. - -config TRIX_HAVE_BOOT - bool "Have TRXPRO.HEX firmware file" - depends on SOUND_TRIX=y && !STANDALONE - help - The MediaTrix AudioTrix Pro has an on-board microcontroller which - needs to be initialized by downloading the code from the file - TRXPRO.HEX in the DOS driver directory. If you don't have the - TRXPRO.HEX file handy you may skip this step. However, the SB and - MPU-401 modes of AudioTrix Pro will not work without this file! - -config TRIX_BOOT_FILE - string "Full pathname of TRXPRO.HEX firmware file" - depends on TRIX_HAVE_BOOT - default "/etc/sound/trxpro.hex" - help - Enter the full pathname of your TRXPRO.HEX file, starting from /. - -config SOUND_MSS - tristate "Microsoft Sound System support" - ---help--- - Again think carefully before answering Y to this question. It's - safe to answer Y if you have the original Windows Sound System card - made by Microsoft or Aztech SG 16 Pro (or NX16 Pro). Also you may - say Y in case your card is NOT among these: - - ATI Stereo F/X, AdLib, Audio Excell DSP16, Cardinal DSP16, - Ensoniq SoundScape (and compatibles made by Reveal and Spea), - Gravis Ultrasound, Gravis Ultrasound ACE, Gravis Ultrasound Max, - Gravis Ultrasound with 16 bit option, Logitech Sound Man 16, - Logitech SoundMan Games, Logitech SoundMan Wave, MAD16 Pro (OPTi - 82C929), Media Vision Jazz16, MediaTriX AudioTriX Pro, Microsoft - Windows Sound System (MSS/WSS), Mozart (OAK OTI-601), Orchid - SW32, Personal Sound System (PSS), Pro Audio Spectrum 16, Pro - Audio Studio 16, Pro Sonic 16, Roland MPU-401 MIDI interface, - Sound Blaster 1.0, Sound Blaster 16, Sound Blaster 16ASP, Sound - Blaster 2.0, Sound Blaster AWE32, Sound Blaster Pro, TI TM4000M - notebook, ThunderBoard, Turtle Beach Tropez, Yamaha FM - synthesizers (OPL2, OPL3 and OPL4), 6850 UART MIDI Interface. - - For cards having native support in VoxWare, consult the card - specific instructions in . - Some drivers have their own MSS support and saying Y to this option - will cause a conflict. - - If you compile the driver into the kernel, you have to add - "ad1848=,,,[,]" to the kernel command - line. - -config SOUND_MPU401 - tristate "MPU-401 support (NOT for SB16)" - ---help--- - Be careful with this question. The MPU401 interface is supported by - all sound cards. However, some natively supported cards have their - own driver for MPU401. Enabling this MPU401 option with these cards - will cause a conflict. Also, enabling MPU401 on a system that - doesn't really have a MPU401 could cause some trouble. If your card - was in the list of supported cards, look at the card specific - instructions in the file. It - is safe to answer Y if you have a true MPU401 MIDI interface card. - - If you compile the driver into the kernel, you have to add - "mpu401=," to the kernel command line. - -config SOUND_PAS - tristate "ProAudioSpectrum 16 support" - ---help--- - Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio - 16 or Logitech SoundMan 16 sound card. Answer N if you have some - other card made by Media Vision or Logitech since those are not - PAS16 compatible. Please read . - It is not necessary to add Sound Blaster support separately; it - is included in PAS support. - - If you compile the driver into the kernel, you have to add - "pas2=,,,,,,, - to the kernel command line. - -config PAS_JOYSTICK - bool "Enable PAS16 joystick port" - depends on SOUND_PAS=y - help - Say Y here to enable the Pro Audio Spectrum 16's auxiliary joystick - port. - -config SOUND_PSS - tristate "PSS (AD1848, ADSP-2115, ESC614) support" - help - Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven - ADSP-16 or some other card based on the PSS chipset (AD1848 codec + - ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). For more information on - how to compile it into the kernel or as a module see the file - . - - If you compile the driver into the kernel, you have to add - "pss=,,,,," to the kernel - command line. - -config PSS_MIXER - bool "Enable PSS mixer (Beethoven ADSP-16 and other compatible)" - depends on SOUND_PSS - help - Answer Y for Beethoven ADSP-16. You may try to say Y also for other - cards if they have master volume, bass, treble, and you can't - control it under Linux. If you answer N for Beethoven ADSP-16, you - can't control master volume, bass, treble and synth volume. - - If you said M to "PSS support" above, you may enable or disable this - PSS mixer with the module parameter pss_mixer. For more information - see the file . - -config PSS_HAVE_BOOT - bool "Have DSPxxx.LD firmware file" - depends on SOUND_PSS && !STANDALONE - help - If you have the DSPxxx.LD file or SYNTH.LD file for you card, say Y - to include this file. Without this file the synth device (OPL) may - not work. - -config PSS_BOOT_FILE - string "Full pathname of DSPxxx.LD firmware file" - depends on PSS_HAVE_BOOT - default "/etc/sound/dsp001.ld" - help - Enter the full pathname of your DSPxxx.LD file or SYNTH.LD file, - starting from /. - -config SOUND_SB - tristate "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support" - ---help--- - Answer Y if you have an original Sound Blaster card made by Creative - Labs or a 100% hardware compatible clone (like the Thunderboard or - SM Games). For an unknown card you may answer Y if the card claims - to be Sound Blaster-compatible. - - Please read the file . - - You should also say Y here for cards based on the Avance Logic - ALS-007 and ALS-1X0 chips (read ) and - for cards based on ESS chips (read - and - ). If you have an IBM Mwave - card, say Y here and read . - - If you compile the driver into the kernel and don't want to use - isapnp, you have to add "sb=,,," to the kernel - command line. - - You can say M here to compile this driver as a module; the module is - called sb. - -config SOUND_YM3812 - tristate "Yamaha FM synthesizer (YM3812/OPL-3) support" - ---help--- - Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). - Answering Y is usually a safe and recommended choice, however some - cards may have software (TSR) FM emulation. Enabling FM support with - these cards may cause trouble (I don't currently know of any such - cards, however). Please read the file - if your card has an OPL3 chip. - - If you compile the driver into the kernel, you have to add - "opl3=" to the kernel command line. - - If unsure, say Y. - -config SOUND_UART6850 - tristate "6850 UART support" - help - This option enables support for MIDI interfaces based on the 6850 - UART chip. This interface is rarely found on sound cards. It's safe - to answer N to this question. - - If you compile the driver into the kernel, you have to add - "uart6850=," to the kernel command line. - -config SOUND_AEDSP16 - tristate "Gallant Audio Cards (SC-6000 and SC-6600 based)" - ---help--- - Answer Y if you have a Gallant's Audio Excel DSP 16 card. This - driver supports Audio Excel DSP 16 but not the III nor PnP versions - of this card. - - The Gallant's Audio Excel DSP 16 card can emulate either an SBPro or - a Microsoft Sound System card, so you should have said Y to either - "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support" - or "Microsoft Sound System support", above, and you need to answer - the "MSS emulation" and "SBPro emulation" questions below - accordingly. You should say Y to one and only one of these two - questions. - - Read the file and the head of - as well as - to get more information - about this driver and its configuration. - -config SC6600 - bool "SC-6600 based audio cards (new Audio Excel DSP 16)" - depends on SOUND_AEDSP16 - help - The SC6600 is the new version of DSP mounted on the Audio Excel DSP - 16 cards. Find in the manual the FCC ID of your audio card and - answer Y if you have an SC6600 DSP. - -config SC6600_JOY - bool "Activate SC-6600 Joystick Interface" - depends on SC6600 - help - Say Y here in order to use the joystick interface of the Audio Excel - DSP 16 card. - -config SC6600_CDROM - int "SC-6600 CDROM Interface (4=None, 3=IDE, 1=Panasonic, 0=?Sony?)" - depends on SC6600 - default "4" - help - This is used to activate the CD-ROM interface of the Audio Excel - DSP 16 card. Enter: 0 for Sony, 1 for Panasonic, 2 for IDE, 4 for no - CD-ROM present. - -config SC6600_CDROMBASE - hex "SC-6600 CDROM Interface I/O Address" - depends on SC6600 - default "0" - help - Base I/O port address for the CD-ROM interface of the Audio Excel - DSP 16 card. - -config SOUND_VIDC - tristate "VIDC 16-bit sound" - depends on ARM && ARCH_ACORN - help - 16-bit support for the VIDC onboard sound hardware found on Acorn - machines. - -config SOUND_WAVEARTIST - tristate "Netwinder WaveArtist" - depends on ARM && ARCH_NETWINDER - help - Say Y here to include support for the Rockwell WaveArtist sound - system. This driver is mainly for the NetWinder. - -config SOUND_KAHLUA - tristate "XpressAudio Sound Blaster emulation" - depends on SOUND_SB - -endif # SOUND_OSS - diff --git a/ANDROID_3.4.5/sound/oss/Makefile b/ANDROID_3.4.5/sound/oss/Makefile deleted file mode 100644 index 77f21b68..00000000 --- a/ANDROID_3.4.5/sound/oss/Makefile +++ /dev/null @@ -1,108 +0,0 @@ -# Makefile for the Linux sound card driver -# -# 18 Apr 1998, Michael Elizabeth Chastain, -# Rewritten to use lists instead of if-statements. - -# Each configuration option enables a list of files. - -obj-$(CONFIG_SOUND_OSS) += sound.o - -# Please leave it as is, cause the link order is significant ! - -obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o -obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o -obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o -obj-$(CONFIG_SOUND_MSS) += ad1848.o -obj-$(CONFIG_SOUND_PAS) += pas2.o sb.o sb_lib.o uart401.o -obj-$(CONFIG_SOUND_SB) += sb.o sb_lib.o uart401.o -obj-$(CONFIG_SOUND_KAHLUA) += kahlua.o -obj-$(CONFIG_SOUND_MPU401) += mpu401.o -obj-$(CONFIG_SOUND_UART6850) += uart6850.o -obj-$(CONFIG_SOUND_YM3812) += opl3.o -obj-$(CONFIG_SOUND_VMIDI) += v_midi.o -obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o -obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o -obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o -obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o -obj-$(CONFIG_SOUND_VWSND) += vwsnd.o -obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o - -obj-$(CONFIG_DMASOUND) += dmasound/ - -# Declare multi-part drivers. - -sound-objs := \ - dev_table.o soundcard.o \ - audio.o dmabuf.o \ - midi_synth.o midibuf.o \ - sequencer.o sound_timer.o sys_timer.o - -pas2-objs := pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o -sb-objs := sb_card.o -sb_lib-objs := sb_common.o sb_audio.o sb_midi.o sb_mixer.o sb_ess.o -vidc_mod-objs := vidc.o vidc_fill.o - -hostprogs-y := bin2hex hex2hex - -# Files generated that shall be removed upon make clean -clean-files := msndperm.c msndinit.c pndsperm.c pndspini.c \ - pss_boot.h trix_boot.h - -# Firmware files that need translation -# -# The translated files are protected by a file that keeps track -# of what name was used to build them. If the name changes, they -# will be forced to be remade. -# - -# Turtle Beach MultiSound - -ifeq ($(CONFIG_MSNDCLAS_HAVE_BOOT),y) - $(obj)/msnd_classic.o: $(obj)/msndperm.c $(obj)/msndinit.c - - $(obj)/msndperm.c: $(patsubst "%", %, $(CONFIG_MSNDCLAS_PERM_FILE)) $(obj)/bin2hex - $(obj)/bin2hex msndperm < $< > $@ - - $(obj)/msndinit.c: $(patsubst "%", %, $(CONFIG_MSNDCLAS_INIT_FILE)) $(obj)/bin2hex - $(obj)/bin2hex msndinit < $< > $@ -endif - -ifeq ($(CONFIG_MSNDPIN_HAVE_BOOT),y) - $(obj)/msnd_pinnacle.o: $(obj)/pndsperm.c $(obj)/pndspini.c - - $(obj)/pndsperm.c: $(patsubst "%", %, $(CONFIG_MSNDPIN_PERM_FILE)) $(obj)/bin2hex - $(obj)/bin2hex pndsperm < $< > $@ - - $(obj)/pndspini.c: $(patsubst "%", %, $(CONFIG_MSNDPIN_INIT_FILE)) $(obj)/bin2hex - $(obj)/bin2hex pndspini < $< > $@ -endif - -# PSS (ECHO-ADI2111) - -$(obj)/pss.o: $(obj)/pss_boot.h - -ifeq ($(CONFIG_PSS_HAVE_BOOT),y) - $(obj)/pss_boot.h: $(patsubst "%", %, $(CONFIG_PSS_BOOT_FILE)) $(obj)/bin2hex - $(obj)/bin2hex pss_synth < $< > $@ -else - $(obj)/pss_boot.h: - $(Q)( \ - echo 'static unsigned char * pss_synth = NULL;'; \ - echo 'static int pss_synthLen = 0;'; \ - ) > $@ -endif - -# MediaTrix AudioTrix Pro - -$(obj)/trix.o: $(obj)/trix_boot.h - -ifeq ($(CONFIG_TRIX_HAVE_BOOT),y) - $(obj)/trix_boot.h: $(patsubst "%", %, $(CONFIG_TRIX_BOOT_FILE)) $(obj)/hex2hex - $(obj)/hex2hex -i trix_boot < $< > $@ -else - $(obj)/trix_boot.h: - $(Q)( \ - echo 'static unsigned char * trix_boot = NULL;'; \ - echo 'static int trix_boot_len = 0;'; \ - ) > $@ -endif diff --git a/ANDROID_3.4.5/sound/oss/README.FIRST b/ANDROID_3.4.5/sound/oss/README.FIRST deleted file mode 100644 index 90fdcf06..00000000 --- a/ANDROID_3.4.5/sound/oss/README.FIRST +++ /dev/null @@ -1,6 +0,0 @@ -The modular sound driver patches were funded by Red Hat Software -(www.redhat.com). The sound driver here is thus a modified version of -Hannu's code. Please bear that in mind when considering the appropriate -forums for bug reporting. - -Alan Cox diff --git a/ANDROID_3.4.5/sound/oss/ad1848.c b/ANDROID_3.4.5/sound/oss/ad1848.c deleted file mode 100644 index 98d23bdc..00000000 --- a/ANDROID_3.4.5/sound/oss/ad1848.c +++ /dev/null @@ -1,3069 +0,0 @@ -/* - * sound/oss/ad1848.c - * - * The low level driver for the AD1848/CS4248 codec chip which - * is used for example in the MS Sound System. - * - * The CS4231 which is used in the GUS MAX and some other cards is - * upwards compatible with AD1848 and this driver is able to drive it. - * - * CS4231A and AD1845 are upward compatible with CS4231. However - * the new features of these chips are different. - * - * CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU). - * CS4232A is an improved version of CS4232. - * - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * general sleep/wakeup clean up. - * Alan Cox : reformatted. Fixed SMP bugs. Moved to kernel alloc/free - * of irqs. Use dev_id. - * Christoph Hellwig : adapted to module_init/module_exit - * Aki Laukkanen : added power management support - * Arnaldo C. de Melo : added missing restore_flags in ad1848_resume - * Miguel Freitas : added ISA PnP support - * Alan Cox : Added CS4236->4239 identification - * Daniel T. Cobra : Alernate config/mixer for later chips - * Alan Cox : Merged chip idents and config code - * - * TODO - * APM save restore assist code on IBM thinkpad - * - * Status: - * Tested. Believed fully functional. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEB(x) -#define DEB1(x) -#include "sound_config.h" - -#include "ad1848.h" -#include "ad1848_mixer.h" - -typedef struct -{ - spinlock_t lock; - int base; - int irq; - int dma1, dma2; - int dual_dma; /* 1, when two DMA channels allocated */ - int subtype; - unsigned char MCE_bit; - unsigned char saved_regs[64]; /* Includes extended register space */ - int debug_flag; - - int audio_flags; - int record_dev, playback_dev; - - int xfer_count; - int audio_mode; - int open_mode; - int intr_active; - char *chip_name, *name; - int model; -#define MD_1848 1 -#define MD_4231 2 -#define MD_4231A 3 -#define MD_1845 4 -#define MD_4232 5 -#define MD_C930 6 -#define MD_IWAVE 7 -#define MD_4235 8 /* Crystal Audio CS4235 */ -#define MD_1845_SSCAPE 9 /* Ensoniq Soundscape PNP*/ -#define MD_4236 10 /* 4236 and higher */ -#define MD_42xB 11 /* CS 42xB */ -#define MD_4239 12 /* CS4239 */ - - /* Mixer parameters */ - int recmask; - int supported_devices, orig_devices; - int supported_rec_devices, orig_rec_devices; - int *levels; - short mixer_reroute[32]; - int dev_no; - volatile unsigned long timer_ticks; - int timer_running; - int irq_ok; - mixer_ents *mix_devices; - int mixer_output_port; -} ad1848_info; - -typedef struct ad1848_port_info -{ - int open_mode; - int speed; - unsigned char speed_bits; - int channels; - int audio_format; - unsigned char format_bits; -} -ad1848_port_info; - -static struct address_info cfg; -static int nr_ad1848_devs; - -static bool deskpro_xl; -static bool deskpro_m; -static bool soundpro; - -static volatile signed char irq2dev[17] = { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -#ifndef EXCLUDE_TIMERS -static int timer_installed = -1; -#endif - -static int loaded; - -static int ad_format_mask[13 /*devc->model */ ] = -{ - 0, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, /* AD1845 */ - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM, - AFMT_U8 | AFMT_S16_LE /* CS4235 */, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW /* Ensoniq Soundscape*/, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM, - AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM -}; - -static ad1848_info adev_info[MAX_AUDIO_DEV]; - -#define io_Index_Addr(d) ((d)->base) -#define io_Indexed_Data(d) ((d)->base+1) -#define io_Status(d) ((d)->base+2) -#define io_Polled_IO(d) ((d)->base+3) - -static struct { - unsigned char flags; -#define CAP_F_TIMER 0x01 -} capabilities [10 /*devc->model */ ] = { - {0} - ,{0} /* MD_1848 */ - ,{CAP_F_TIMER} /* MD_4231 */ - ,{CAP_F_TIMER} /* MD_4231A */ - ,{CAP_F_TIMER} /* MD_1845 */ - ,{CAP_F_TIMER} /* MD_4232 */ - ,{0} /* MD_C930 */ - ,{CAP_F_TIMER} /* MD_IWAVE */ - ,{0} /* MD_4235 */ - ,{CAP_F_TIMER} /* MD_1845_SSCAPE */ -}; - -#ifdef CONFIG_PNP -static int isapnp = 1; -static int isapnpjump; -static bool reverse; - -static int audio_activated; -#else -static int isapnp; -#endif - - - -static int ad1848_open(int dev, int mode); -static void ad1848_close(int dev); -static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag); -static void ad1848_start_input(int dev, unsigned long buf, int count, int intrflag); -static int ad1848_prepare_for_output(int dev, int bsize, int bcount); -static int ad1848_prepare_for_input(int dev, int bsize, int bcount); -static void ad1848_halt(int dev); -static void ad1848_halt_input(int dev); -static void ad1848_halt_output(int dev); -static void ad1848_trigger(int dev, int bits); -static irqreturn_t adintr(int irq, void *dev_id); - -#ifndef EXCLUDE_TIMERS -static int ad1848_tmr_install(int dev); -static void ad1848_tmr_reprogram(int dev); -#endif - -static int ad_read(ad1848_info * devc, int reg) -{ - int x; - int timeout = 900000; - - while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */ - timeout--; - - if(reg < 32) - { - outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc)); - x = inb(io_Indexed_Data(devc)); - } - else - { - int xreg, xra; - - xreg = (reg & 0xff) - 32; - xra = (((xreg & 0x0f) << 4) & 0xf0) | 0x08 | ((xreg & 0x10) >> 2); - outb(((unsigned char) (23 & 0xff) | devc->MCE_bit), io_Index_Addr(devc)); - outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc)); - x = inb(io_Indexed_Data(devc)); - } - - return x; -} - -static void ad_write(ad1848_info * devc, int reg, int data) -{ - int timeout = 900000; - - while (timeout > 0 && inb(devc->base) == 0x80) /* Are we initializing */ - timeout--; - - if(reg < 32) - { - outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc)); - outb(((unsigned char) (data & 0xff)), io_Indexed_Data(devc)); - } - else - { - int xreg, xra; - - xreg = (reg & 0xff) - 32; - xra = (((xreg & 0x0f) << 4) & 0xf0) | 0x08 | ((xreg & 0x10) >> 2); - outb(((unsigned char) (23 & 0xff) | devc->MCE_bit), io_Index_Addr(devc)); - outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc)); - outb((unsigned char) (data & 0xff), io_Indexed_Data(devc)); - } -} - -static void wait_for_calibration(ad1848_info * devc) -{ - int timeout = 0; - - /* - * Wait until the auto calibration process has finished. - * - * 1) Wait until the chip becomes ready (reads don't return 0x80). - * 2) Wait until the ACI bit of I11 gets on and then off. - */ - - timeout = 100000; - while (timeout > 0 && inb(devc->base) == 0x80) - timeout--; - if (inb(devc->base) & 0x80) - printk(KERN_WARNING "ad1848: Auto calibration timed out(1).\n"); - - timeout = 100; - while (timeout > 0 && !(ad_read(devc, 11) & 0x20)) - timeout--; - if (!(ad_read(devc, 11) & 0x20)) - return; - - timeout = 80000; - while (timeout > 0 && (ad_read(devc, 11) & 0x20)) - timeout--; - if (ad_read(devc, 11) & 0x20) - if ((devc->model != MD_1845) && (devc->model != MD_1845_SSCAPE)) - printk(KERN_WARNING "ad1848: Auto calibration timed out(3).\n"); -} - -static void ad_mute(ad1848_info * devc) -{ - int i; - unsigned char prev; - - /* - * Save old register settings and mute output channels - */ - - for (i = 6; i < 8; i++) - { - prev = devc->saved_regs[i] = ad_read(devc, i); - } - -} - -static void ad_unmute(ad1848_info * devc) -{ -} - -static void ad_enter_MCE(ad1848_info * devc) -{ - int timeout = 1000; - unsigned short prev; - - while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */ - timeout--; - - devc->MCE_bit = 0x40; - prev = inb(io_Index_Addr(devc)); - if (prev & 0x40) - { - return; - } - outb((devc->MCE_bit), io_Index_Addr(devc)); -} - -static void ad_leave_MCE(ad1848_info * devc) -{ - unsigned char prev, acal; - int timeout = 1000; - - while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */ - timeout--; - - acal = ad_read(devc, 9); - - devc->MCE_bit = 0x00; - prev = inb(io_Index_Addr(devc)); - outb((0x00), io_Index_Addr(devc)); /* Clear the MCE bit */ - - if ((prev & 0x40) == 0) /* Not in MCE mode */ - { - return; - } - outb((0x00), io_Index_Addr(devc)); /* Clear the MCE bit */ - if (acal & 0x08) /* Auto calibration is enabled */ - wait_for_calibration(devc); -} - -static int ad1848_set_recmask(ad1848_info * devc, int mask) -{ - unsigned char recdev; - int i, n; - unsigned long flags; - - mask &= devc->supported_rec_devices; - - /* Rename the mixer bits if necessary */ - for (i = 0; i < 32; i++) - { - if (devc->mixer_reroute[i] != i) - { - if (mask & (1 << i)) - { - mask &= ~(1 << i); - mask |= (1 << devc->mixer_reroute[i]); - } - } - } - - n = 0; - for (i = 0; i < 32; i++) /* Count selected device bits */ - if (mask & (1 << i)) - n++; - - spin_lock_irqsave(&devc->lock,flags); - if (!soundpro) { - if (n == 0) - mask = SOUND_MASK_MIC; - else if (n != 1) { /* Too many devices selected */ - mask &= ~devc->recmask; /* Filter out active settings */ - - n = 0; - for (i = 0; i < 32; i++) /* Count selected device bits */ - if (mask & (1 << i)) - n++; - - if (n != 1) - mask = SOUND_MASK_MIC; - } - switch (mask) { - case SOUND_MASK_MIC: - recdev = 2; - break; - - case SOUND_MASK_LINE: - case SOUND_MASK_LINE3: - recdev = 0; - break; - - case SOUND_MASK_CD: - case SOUND_MASK_LINE1: - recdev = 1; - break; - - case SOUND_MASK_IMIX: - recdev = 3; - break; - - default: - mask = SOUND_MASK_MIC; - recdev = 2; - } - - recdev <<= 6; - ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev); - ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev); - } else { /* soundpro */ - unsigned char val; - int set_rec_bit; - int j; - - for (i = 0; i < 32; i++) { /* For each bit */ - if ((devc->supported_rec_devices & (1 << i)) == 0) - continue; /* Device not supported */ - - for (j = LEFT_CHN; j <= RIGHT_CHN; j++) { - if (devc->mix_devices[i][j].nbits == 0) /* Inexistent channel */ - continue; - - /* - * This is tricky: - * set_rec_bit becomes 1 if the corresponding bit in mask is set - * then it gets flipped if the polarity is inverse - */ - set_rec_bit = ((mask & (1 << i)) != 0) ^ devc->mix_devices[i][j].recpol; - - val = ad_read(devc, devc->mix_devices[i][j].recreg); - val &= ~(1 << devc->mix_devices[i][j].recpos); - val |= (set_rec_bit << devc->mix_devices[i][j].recpos); - ad_write(devc, devc->mix_devices[i][j].recreg, val); - } - } - } - spin_unlock_irqrestore(&devc->lock,flags); - - /* Rename the mixer bits back if necessary */ - for (i = 0; i < 32; i++) - { - if (devc->mixer_reroute[i] != i) - { - if (mask & (1 << devc->mixer_reroute[i])) - { - mask &= ~(1 << devc->mixer_reroute[i]); - mask |= (1 << i); - } - } - } - devc->recmask = mask; - return mask; -} - -static void oss_change_bits(ad1848_info *devc, unsigned char *regval, - unsigned char *muteval, int dev, int chn, int newval) -{ - unsigned char mask; - int shift; - int mute; - int mutemask; - int set_mute_bit; - - set_mute_bit = (newval == 0) ^ devc->mix_devices[dev][chn].mutepol; - - if (devc->mix_devices[dev][chn].polarity == 1) /* Reverse */ - newval = 100 - newval; - - mask = (1 << devc->mix_devices[dev][chn].nbits) - 1; - shift = devc->mix_devices[dev][chn].bitpos; - - if (devc->mix_devices[dev][chn].mutepos == 8) - { /* if there is no mute bit */ - mute = 0; /* No mute bit; do nothing special */ - mutemask = ~0; /* No mute bit; do nothing special */ - } - else - { - mute = (set_mute_bit << devc->mix_devices[dev][chn].mutepos); - mutemask = ~(1 << devc->mix_devices[dev][chn].mutepos); - } - - newval = (int) ((newval * mask) + 50) / 100; /* Scale it */ - *regval &= ~(mask << shift); /* Clear bits */ - *regval |= (newval & mask) << shift; /* Set new value */ - - *muteval &= mutemask; - *muteval |= mute; -} - -static int ad1848_mixer_get(ad1848_info * devc, int dev) -{ - if (!((1 << dev) & devc->supported_devices)) - return -EINVAL; - - dev = devc->mixer_reroute[dev]; - - return devc->levels[dev]; -} - -static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int channel) -{ - int regoffs, muteregoffs; - unsigned char val, muteval; - unsigned long flags; - - regoffs = devc->mix_devices[dev][channel].regno; - muteregoffs = devc->mix_devices[dev][channel].mutereg; - val = ad_read(devc, regoffs); - - if (muteregoffs != regoffs) { - muteval = ad_read(devc, muteregoffs); - oss_change_bits(devc, &val, &muteval, dev, channel, value); - } - else - oss_change_bits(devc, &val, &val, dev, channel, value); - - spin_lock_irqsave(&devc->lock,flags); - ad_write(devc, regoffs, val); - devc->saved_regs[regoffs] = val; - if (muteregoffs != regoffs) { - ad_write(devc, muteregoffs, muteval); - devc->saved_regs[muteregoffs] = muteval; - } - spin_unlock_irqrestore(&devc->lock,flags); -} - -static int ad1848_mixer_set(ad1848_info * devc, int dev, int value) -{ - int left = value & 0x000000ff; - int right = (value & 0x0000ff00) >> 8; - int retvol; - - if (dev > 31) - return -EINVAL; - - if (!(devc->supported_devices & (1 << dev))) - return -EINVAL; - - dev = devc->mixer_reroute[dev]; - - if (devc->mix_devices[dev][LEFT_CHN].nbits == 0) - return -EINVAL; - - if (left > 100) - left = 100; - if (right > 100) - right = 100; - - if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0) /* Mono control */ - right = left; - - retvol = left | (right << 8); - - /* Scale volumes */ - left = mix_cvt[left]; - right = mix_cvt[right]; - - devc->levels[dev] = retvol; - - /* - * Set the left channel - */ - ad1848_mixer_set_channel(devc, dev, left, LEFT_CHN); - - /* - * Set the right channel - */ - if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0) - goto out; - ad1848_mixer_set_channel(devc, dev, right, RIGHT_CHN); - - out: - return retvol; -} - -static void ad1848_mixer_reset(ad1848_info * devc) -{ - int i; - char name[32]; - unsigned long flags; - - devc->mix_devices = &(ad1848_mix_devices[0]); - - sprintf(name, "%s_%d", devc->chip_name, nr_ad1848_devs); - - for (i = 0; i < 32; i++) - devc->mixer_reroute[i] = i; - - devc->supported_rec_devices = MODE1_REC_DEVICES; - - switch (devc->model) - { - case MD_4231: - case MD_4231A: - case MD_1845: - case MD_1845_SSCAPE: - devc->supported_devices = MODE2_MIXER_DEVICES; - break; - - case MD_C930: - devc->supported_devices = C930_MIXER_DEVICES; - devc->mix_devices = &(c930_mix_devices[0]); - break; - - case MD_IWAVE: - devc->supported_devices = MODE3_MIXER_DEVICES; - devc->mix_devices = &(iwave_mix_devices[0]); - break; - - case MD_42xB: - case MD_4239: - devc->mix_devices = &(cs42xb_mix_devices[0]); - devc->supported_devices = MODE3_MIXER_DEVICES; - break; - case MD_4232: - case MD_4235: - case MD_4236: - devc->supported_devices = MODE3_MIXER_DEVICES; - break; - - case MD_1848: - if (soundpro) { - devc->supported_devices = SPRO_MIXER_DEVICES; - devc->supported_rec_devices = SPRO_REC_DEVICES; - devc->mix_devices = &(spro_mix_devices[0]); - break; - } - - default: - devc->supported_devices = MODE1_MIXER_DEVICES; - } - - devc->orig_devices = devc->supported_devices; - devc->orig_rec_devices = devc->supported_rec_devices; - - devc->levels = load_mixer_volumes(name, default_mixer_levels, 1); - - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - { - if (devc->supported_devices & (1 << i)) - ad1848_mixer_set(devc, i, devc->levels[i]); - } - - ad1848_set_recmask(devc, SOUND_MASK_MIC); - - devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT; - - spin_lock_irqsave(&devc->lock,flags); - if (!soundpro) { - if (devc->mixer_output_port & AUDIO_SPEAKER) - ad_write(devc, 26, ad_read(devc, 26) & ~0x40); /* Unmute mono out */ - else - ad_write(devc, 26, ad_read(devc, 26) | 0x40); /* Mute mono out */ - } else { - /* - * From the "wouldn't it be nice if the mixer API had (better) - * support for custom stuff" category - */ - /* Enable surround mode and SB16 mixer */ - ad_write(devc, 16, 0x60); - } - spin_unlock_irqrestore(&devc->lock,flags); -} - -static int ad1848_mixer_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - ad1848_info *devc = mixer_devs[dev]->devc; - int val; - - if (cmd == SOUND_MIXER_PRIVATE1) - { - if (get_user(val, (int __user *)arg)) - return -EFAULT; - - if (val != 0xffff) - { - unsigned long flags; - val &= (AUDIO_SPEAKER | AUDIO_HEADPHONE | AUDIO_LINE_OUT); - devc->mixer_output_port = val; - val |= AUDIO_HEADPHONE | AUDIO_LINE_OUT; /* Always on */ - devc->mixer_output_port = val; - spin_lock_irqsave(&devc->lock,flags); - if (val & AUDIO_SPEAKER) - ad_write(devc, 26, ad_read(devc, 26) & ~0x40); /* Unmute mono out */ - else - ad_write(devc, 26, ad_read(devc, 26) | 0x40); /* Mute mono out */ - spin_unlock_irqrestore(&devc->lock,flags); - } - val = devc->mixer_output_port; - return put_user(val, (int __user *)arg); - } - if (cmd == SOUND_MIXER_PRIVATE2) - { - if (get_user(val, (int __user *)arg)) - return -EFAULT; - return(ad1848_control(AD1848_MIXER_REROUTE, val)); - } - if (((cmd >> 8) & 0xff) == 'M') - { - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - { - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - if (get_user(val, (int __user *)arg)) - return -EFAULT; - val = ad1848_set_recmask(devc, val); - break; - - default: - if (get_user(val, (int __user *)arg)) - return -EFAULT; - val = ad1848_mixer_set(devc, cmd & 0xff, val); - break; - } - return put_user(val, (int __user *)arg); - } - else - { - switch (cmd & 0xff) - { - /* - * Return parameters - */ - - case SOUND_MIXER_RECSRC: - val = devc->recmask; - break; - - case SOUND_MIXER_DEVMASK: - val = devc->supported_devices; - break; - - case SOUND_MIXER_STEREODEVS: - val = devc->supported_devices; - if (devc->model != MD_C930) - val &= ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX); - break; - - case SOUND_MIXER_RECMASK: - val = devc->supported_rec_devices; - break; - - case SOUND_MIXER_CAPS: - val=SOUND_CAP_EXCL_INPUT; - break; - - default: - val = ad1848_mixer_get(devc, cmd & 0xff); - break; - } - return put_user(val, (int __user *)arg); - } - } - else - return -EINVAL; -} - -static int ad1848_set_speed(int dev, int arg) -{ - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - /* - * The sampling speed is encoded in the least significant nibble of I8. The - * LSB selects the clock source (0=24.576 MHz, 1=16.9344 MHz) and other - * three bits select the divisor (indirectly): - * - * The available speeds are in the following table. Keep the speeds in - * the increasing order. - */ - typedef struct - { - int speed; - unsigned char bits; - } - speed_struct; - - static speed_struct speed_table[] = - { - {5510, (0 << 1) | 1}, - {5510, (0 << 1) | 1}, - {6620, (7 << 1) | 1}, - {8000, (0 << 1) | 0}, - {9600, (7 << 1) | 0}, - {11025, (1 << 1) | 1}, - {16000, (1 << 1) | 0}, - {18900, (2 << 1) | 1}, - {22050, (3 << 1) | 1}, - {27420, (2 << 1) | 0}, - {32000, (3 << 1) | 0}, - {33075, (6 << 1) | 1}, - {37800, (4 << 1) | 1}, - {44100, (5 << 1) | 1}, - {48000, (6 << 1) | 0} - }; - - int i, n, selected = -1; - - n = sizeof(speed_table) / sizeof(speed_struct); - - if (arg <= 0) - return portc->speed; - - if (devc->model == MD_1845 || devc->model == MD_1845_SSCAPE) /* AD1845 has different timer than others */ - { - if (arg < 4000) - arg = 4000; - if (arg > 50000) - arg = 50000; - - portc->speed = arg; - portc->speed_bits = speed_table[3].bits; - return portc->speed; - } - if (arg < speed_table[0].speed) - selected = 0; - if (arg > speed_table[n - 1].speed) - selected = n - 1; - - for (i = 1 /*really */ ; selected == -1 && i < n; i++) - { - if (speed_table[i].speed == arg) - selected = i; - else if (speed_table[i].speed > arg) - { - int diff1, diff2; - - diff1 = arg - speed_table[i - 1].speed; - diff2 = speed_table[i].speed - arg; - - if (diff1 < diff2) - selected = i - 1; - else - selected = i; - } - } - if (selected == -1) - { - printk(KERN_WARNING "ad1848: Can't find speed???\n"); - selected = 3; - } - portc->speed = speed_table[selected].speed; - portc->speed_bits = speed_table[selected].bits; - return portc->speed; -} - -static short ad1848_set_channels(int dev, short arg) -{ - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - if (arg != 1 && arg != 2) - return portc->channels; - - portc->channels = arg; - return arg; -} - -static unsigned int ad1848_set_bits(int dev, unsigned int arg) -{ - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - static struct format_tbl - { - int format; - unsigned char bits; - } - format2bits[] = - { - { - 0, 0 - } - , - { - AFMT_MU_LAW, 1 - } - , - { - AFMT_A_LAW, 3 - } - , - { - AFMT_IMA_ADPCM, 5 - } - , - { - AFMT_U8, 0 - } - , - { - AFMT_S16_LE, 2 - } - , - { - AFMT_S16_BE, 6 - } - , - { - AFMT_S8, 0 - } - , - { - AFMT_U16_LE, 0 - } - , - { - AFMT_U16_BE, 0 - } - }; - int i, n = sizeof(format2bits) / sizeof(struct format_tbl); - - if (arg == 0) - return portc->audio_format; - - if (!(arg & ad_format_mask[devc->model])) - arg = AFMT_U8; - - portc->audio_format = arg; - - for (i = 0; i < n; i++) - if (format2bits[i].format == arg) - { - if ((portc->format_bits = format2bits[i].bits) == 0) - return portc->audio_format = AFMT_U8; /* Was not supported */ - - return arg; - } - /* Still hanging here. Something must be terribly wrong */ - portc->format_bits = 0; - return portc->audio_format = AFMT_U8; -} - -static struct audio_driver ad1848_audio_driver = -{ - .owner = THIS_MODULE, - .open = ad1848_open, - .close = ad1848_close, - .output_block = ad1848_output_block, - .start_input = ad1848_start_input, - .prepare_for_input = ad1848_prepare_for_input, - .prepare_for_output = ad1848_prepare_for_output, - .halt_io = ad1848_halt, - .halt_input = ad1848_halt_input, - .halt_output = ad1848_halt_output, - .trigger = ad1848_trigger, - .set_speed = ad1848_set_speed, - .set_bits = ad1848_set_bits, - .set_channels = ad1848_set_channels -}; - -static struct mixer_operations ad1848_mixer_operations = -{ - .owner = THIS_MODULE, - .id = "SOUNDPORT", - .name = "AD1848/CS4248/CS4231", - .ioctl = ad1848_mixer_ioctl -}; - -static int ad1848_open(int dev, int mode) -{ - ad1848_info *devc; - ad1848_port_info *portc; - unsigned long flags; - - if (dev < 0 || dev >= num_audiodevs) - return -ENXIO; - - devc = (ad1848_info *) audio_devs[dev]->devc; - portc = (ad1848_port_info *) audio_devs[dev]->portc; - - /* here we don't have to protect against intr */ - spin_lock(&devc->lock); - if (portc->open_mode || (devc->open_mode & mode)) - { - spin_unlock(&devc->lock); - return -EBUSY; - } - devc->dual_dma = 0; - - if (audio_devs[dev]->flags & DMA_DUPLEX) - { - devc->dual_dma = 1; - } - devc->intr_active = 0; - devc->audio_mode = 0; - devc->open_mode |= mode; - portc->open_mode = mode; - spin_unlock(&devc->lock); - ad1848_trigger(dev, 0); - - if (mode & OPEN_READ) - devc->record_dev = dev; - if (mode & OPEN_WRITE) - devc->playback_dev = dev; -/* - * Mute output until the playback really starts. This decreases clicking (hope so). - */ - spin_lock_irqsave(&devc->lock,flags); - ad_mute(devc); - spin_unlock_irqrestore(&devc->lock,flags); - - return 0; -} - -static void ad1848_close(int dev) -{ - unsigned long flags; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - DEB(printk("ad1848_close(void)\n")); - - devc->intr_active = 0; - ad1848_halt(dev); - - spin_lock_irqsave(&devc->lock,flags); - - devc->audio_mode = 0; - devc->open_mode &= ~portc->open_mode; - portc->open_mode = 0; - - ad_unmute(devc); - spin_unlock_irqrestore(&devc->lock,flags); -} - -static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag) -{ - unsigned long flags, cnt; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - cnt = count; - - if (portc->audio_format == AFMT_IMA_ADPCM) - { - cnt /= 4; - } - else - { - if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ - cnt >>= 1; - } - if (portc->channels > 1) - cnt >>= 1; - cnt--; - - if ((devc->audio_mode & PCM_ENABLE_OUTPUT) && (audio_devs[dev]->flags & DMA_AUTOMODE) && - intrflag && - cnt == devc->xfer_count) - { - devc->audio_mode |= PCM_ENABLE_OUTPUT; - devc->intr_active = 1; - return; /* - * Auto DMA mode on. No need to react - */ - } - spin_lock_irqsave(&devc->lock,flags); - - ad_write(devc, 15, (unsigned char) (cnt & 0xff)); - ad_write(devc, 14, (unsigned char) ((cnt >> 8) & 0xff)); - - devc->xfer_count = cnt; - devc->audio_mode |= PCM_ENABLE_OUTPUT; - devc->intr_active = 1; - spin_unlock_irqrestore(&devc->lock,flags); -} - -static void ad1848_start_input(int dev, unsigned long buf, int count, int intrflag) -{ - unsigned long flags, cnt; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - cnt = count; - if (portc->audio_format == AFMT_IMA_ADPCM) - { - cnt /= 4; - } - else - { - if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ - cnt >>= 1; - } - if (portc->channels > 1) - cnt >>= 1; - cnt--; - - if ((devc->audio_mode & PCM_ENABLE_INPUT) && (audio_devs[dev]->flags & DMA_AUTOMODE) && - intrflag && - cnt == devc->xfer_count) - { - devc->audio_mode |= PCM_ENABLE_INPUT; - devc->intr_active = 1; - return; /* - * Auto DMA mode on. No need to react - */ - } - spin_lock_irqsave(&devc->lock,flags); - - if (devc->model == MD_1848) - { - ad_write(devc, 15, (unsigned char) (cnt & 0xff)); - ad_write(devc, 14, (unsigned char) ((cnt >> 8) & 0xff)); - } - else - { - ad_write(devc, 31, (unsigned char) (cnt & 0xff)); - ad_write(devc, 30, (unsigned char) ((cnt >> 8) & 0xff)); - } - - ad_unmute(devc); - - devc->xfer_count = cnt; - devc->audio_mode |= PCM_ENABLE_INPUT; - devc->intr_active = 1; - spin_unlock_irqrestore(&devc->lock,flags); -} - -static int ad1848_prepare_for_output(int dev, int bsize, int bcount) -{ - int timeout; - unsigned char fs, old_fs, tmp = 0; - unsigned long flags; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - ad_mute(devc); - - spin_lock_irqsave(&devc->lock,flags); - fs = portc->speed_bits | (portc->format_bits << 5); - - if (portc->channels > 1) - fs |= 0x10; - - ad_enter_MCE(devc); /* Enables changes to the format select reg */ - - if (devc->model == MD_1845 || devc->model == MD_1845_SSCAPE) /* Use alternate speed select registers */ - { - fs &= 0xf0; /* Mask off the rate select bits */ - - ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */ - ad_write(devc, 23, portc->speed & 0xff); /* Speed LSB */ - } - old_fs = ad_read(devc, 8); - - if (devc->model == MD_4232 || devc->model >= MD_4236) - { - tmp = ad_read(devc, 16); - ad_write(devc, 16, tmp | 0x30); - } - if (devc->model == MD_IWAVE) - ad_write(devc, 17, 0xc2); /* Disable variable frequency select */ - - ad_write(devc, 8, fs); - - /* - * Write to I8 starts resynchronization. Wait until it completes. - */ - - timeout = 0; - while (timeout < 100 && inb(devc->base) != 0x80) - timeout++; - timeout = 0; - while (timeout < 10000 && inb(devc->base) == 0x80) - timeout++; - - if (devc->model >= MD_4232) - ad_write(devc, 16, tmp & ~0x30); - - ad_leave_MCE(devc); /* - * Starts the calibration process. - */ - spin_unlock_irqrestore(&devc->lock,flags); - devc->xfer_count = 0; - -#ifndef EXCLUDE_TIMERS - if (dev == timer_installed && devc->timer_running) - if ((fs & 0x01) != (old_fs & 0x01)) - { - ad1848_tmr_reprogram(dev); - } -#endif - ad1848_halt_output(dev); - return 0; -} - -static int ad1848_prepare_for_input(int dev, int bsize, int bcount) -{ - int timeout; - unsigned char fs, old_fs, tmp = 0; - unsigned long flags; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - if (devc->audio_mode) - return 0; - - spin_lock_irqsave(&devc->lock,flags); - fs = portc->speed_bits | (portc->format_bits << 5); - - if (portc->channels > 1) - fs |= 0x10; - - ad_enter_MCE(devc); /* Enables changes to the format select reg */ - - if ((devc->model == MD_1845) || (devc->model == MD_1845_SSCAPE)) /* Use alternate speed select registers */ - { - fs &= 0xf0; /* Mask off the rate select bits */ - - ad_write(devc, 22, (portc->speed >> 8) & 0xff); /* Speed MSB */ - ad_write(devc, 23, portc->speed & 0xff); /* Speed LSB */ - } - if (devc->model == MD_4232) - { - tmp = ad_read(devc, 16); - ad_write(devc, 16, tmp | 0x30); - } - if (devc->model == MD_IWAVE) - ad_write(devc, 17, 0xc2); /* Disable variable frequency select */ - - /* - * If mode >= 2 (CS4231), set I28. It's the capture format register. - */ - - if (devc->model != MD_1848) - { - old_fs = ad_read(devc, 28); - ad_write(devc, 28, fs); - - /* - * Write to I28 starts resynchronization. Wait until it completes. - */ - - timeout = 0; - while (timeout < 100 && inb(devc->base) != 0x80) - timeout++; - - timeout = 0; - while (timeout < 10000 && inb(devc->base) == 0x80) - timeout++; - - if (devc->model != MD_1848 && devc->model != MD_1845 && devc->model != MD_1845_SSCAPE) - { - /* - * CS4231 compatible devices don't have separate sampling rate selection - * register for recording an playback. The I8 register is shared so we have to - * set the speed encoding bits of it too. - */ - unsigned char tmp = portc->speed_bits | (ad_read(devc, 8) & 0xf0); - - ad_write(devc, 8, tmp); - /* - * Write to I8 starts resynchronization. Wait until it completes. - */ - timeout = 0; - while (timeout < 100 && inb(devc->base) != 0x80) - timeout++; - - timeout = 0; - while (timeout < 10000 && inb(devc->base) == 0x80) - timeout++; - } - } - else - { /* For AD1848 set I8. */ - - old_fs = ad_read(devc, 8); - ad_write(devc, 8, fs); - /* - * Write to I8 starts resynchronization. Wait until it completes. - */ - timeout = 0; - while (timeout < 100 && inb(devc->base) != 0x80) - timeout++; - timeout = 0; - while (timeout < 10000 && inb(devc->base) == 0x80) - timeout++; - } - - if (devc->model == MD_4232) - ad_write(devc, 16, tmp & ~0x30); - - ad_leave_MCE(devc); /* - * Starts the calibration process. - */ - spin_unlock_irqrestore(&devc->lock,flags); - devc->xfer_count = 0; - -#ifndef EXCLUDE_TIMERS - if (dev == timer_installed && devc->timer_running) - { - if ((fs & 0x01) != (old_fs & 0x01)) - { - ad1848_tmr_reprogram(dev); - } - } -#endif - ad1848_halt_input(dev); - return 0; -} - -static void ad1848_halt(int dev) -{ - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - - unsigned char bits = ad_read(devc, 9); - - if (bits & 0x01 && (portc->open_mode & OPEN_WRITE)) - ad1848_halt_output(dev); - - if (bits & 0x02 && (portc->open_mode & OPEN_READ)) - ad1848_halt_input(dev); - devc->audio_mode = 0; -} - -static void ad1848_halt_input(int dev) -{ - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - unsigned long flags; - - if (!(ad_read(devc, 9) & 0x02)) - return; /* Capture not enabled */ - - spin_lock_irqsave(&devc->lock,flags); - - ad_mute(devc); - - { - int tmout; - - if(!isa_dma_bridge_buggy) - disable_dma(audio_devs[dev]->dmap_in->dma); - - for (tmout = 0; tmout < 100000; tmout++) - if (ad_read(devc, 11) & 0x10) - break; - ad_write(devc, 9, ad_read(devc, 9) & ~0x02); /* Stop capture */ - - if(!isa_dma_bridge_buggy) - enable_dma(audio_devs[dev]->dmap_in->dma); - devc->audio_mode &= ~PCM_ENABLE_INPUT; - } - - outb(0, io_Status(devc)); /* Clear interrupt status */ - outb(0, io_Status(devc)); /* Clear interrupt status */ - - devc->audio_mode &= ~PCM_ENABLE_INPUT; - - spin_unlock_irqrestore(&devc->lock,flags); -} - -static void ad1848_halt_output(int dev) -{ - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - unsigned long flags; - - if (!(ad_read(devc, 9) & 0x01)) - return; /* Playback not enabled */ - - spin_lock_irqsave(&devc->lock,flags); - - ad_mute(devc); - { - int tmout; - - if(!isa_dma_bridge_buggy) - disable_dma(audio_devs[dev]->dmap_out->dma); - - for (tmout = 0; tmout < 100000; tmout++) - if (ad_read(devc, 11) & 0x10) - break; - ad_write(devc, 9, ad_read(devc, 9) & ~0x01); /* Stop playback */ - - if(!isa_dma_bridge_buggy) - enable_dma(audio_devs[dev]->dmap_out->dma); - - devc->audio_mode &= ~PCM_ENABLE_OUTPUT; - } - - outb((0), io_Status(devc)); /* Clear interrupt status */ - outb((0), io_Status(devc)); /* Clear interrupt status */ - - devc->audio_mode &= ~PCM_ENABLE_OUTPUT; - - spin_unlock_irqrestore(&devc->lock,flags); -} - -static void ad1848_trigger(int dev, int state) -{ - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc; - unsigned long flags; - unsigned char tmp, old; - - spin_lock_irqsave(&devc->lock,flags); - state &= devc->audio_mode; - - tmp = old = ad_read(devc, 9); - - if (portc->open_mode & OPEN_READ) - { - if (state & PCM_ENABLE_INPUT) - tmp |= 0x02; - else - tmp &= ~0x02; - } - if (portc->open_mode & OPEN_WRITE) - { - if (state & PCM_ENABLE_OUTPUT) - tmp |= 0x01; - else - tmp &= ~0x01; - } - /* ad_mute(devc); */ - if (tmp != old) - { - ad_write(devc, 9, tmp); - ad_unmute(devc); - } - spin_unlock_irqrestore(&devc->lock,flags); -} - -static void ad1848_init_hw(ad1848_info * devc) -{ - int i; - int *init_values; - - /* - * Initial values for the indirect registers of CS4248/AD1848. - */ - static int init_values_a[] = - { - 0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00, - - /* Positions 16 to 31 just for CS4231/2 and ad1845 */ - 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static int init_values_b[] = - { - /* - Values for the newer chips - Some of the register initialization values were changed. In - order to get rid of the click that preceded PCM playback, - calibration was disabled on the 10th byte. On that same byte, - dual DMA was enabled; on the 11th byte, ADC dithering was - enabled, since that is theoretically desirable; on the 13th - byte, Mode 3 was selected, to enable access to extended - registers. - */ - 0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x00, 0xe0, 0x01, 0x00, 0x00, - 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - /* - * Select initialisation data - */ - - init_values = init_values_a; - if(devc->model >= MD_4236) - init_values = init_values_b; - - for (i = 0; i < 16; i++) - ad_write(devc, i, init_values[i]); - - - ad_mute(devc); /* Initialize some variables */ - ad_unmute(devc); /* Leave it unmuted now */ - - if (devc->model > MD_1848) - { - if (devc->model == MD_1845_SSCAPE) - ad_write(devc, 12, ad_read(devc, 12) | 0x50); - else - ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */ - - if (devc->model == MD_IWAVE) - ad_write(devc, 12, 0x6c); /* Select codec mode 3 */ - - if (devc->model != MD_1845_SSCAPE) - for (i = 16; i < 32; i++) - ad_write(devc, i, init_values[i]); - - if (devc->model == MD_IWAVE) - ad_write(devc, 16, 0x30); /* Playback and capture counters enabled */ - } - if (devc->model > MD_1848) - { - if (devc->audio_flags & DMA_DUPLEX) - ad_write(devc, 9, ad_read(devc, 9) & ~0x04); /* Dual DMA mode */ - else - ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */ - - if (devc->model == MD_1845 || devc->model == MD_1845_SSCAPE) - ad_write(devc, 27, ad_read(devc, 27) | 0x08); /* Alternate freq select enabled */ - - if (devc->model == MD_IWAVE) - { /* Some magic Interwave specific initialization */ - ad_write(devc, 12, 0x6c); /* Select codec mode 3 */ - ad_write(devc, 16, 0x30); /* Playback and capture counters enabled */ - ad_write(devc, 17, 0xc2); /* Alternate feature enable */ - } - } - else - { - devc->audio_flags &= ~DMA_DUPLEX; - ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */ - if (soundpro) - ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */ - } - - outb((0), io_Status(devc)); /* Clear pending interrupts */ - - /* - * Toggle the MCE bit. It completes the initialization phase. - */ - - ad_enter_MCE(devc); /* In case the bit was off */ - ad_leave_MCE(devc); - - ad1848_mixer_reset(devc); -} - -int ad1848_detect(struct resource *ports, int *ad_flags, int *osp) -{ - unsigned char tmp; - ad1848_info *devc = &adev_info[nr_ad1848_devs]; - unsigned char tmp1 = 0xff, tmp2 = 0xff; - int optiC930 = 0; /* OPTi 82C930 flag */ - int interwave = 0; - int ad1847_flag = 0; - int cs4248_flag = 0; - int sscape_flag = 0; - int io_base = ports->start; - - int i; - - DDB(printk("ad1848_detect(%x)\n", io_base)); - - if (ad_flags) - { - if (*ad_flags == 0x12345678) - { - interwave = 1; - *ad_flags = 0; - } - - if (*ad_flags == 0x87654321) - { - sscape_flag = 1; - *ad_flags = 0; - } - - if (*ad_flags == 0x12345677) - { - cs4248_flag = 1; - *ad_flags = 0; - } - } - if (nr_ad1848_devs >= MAX_AUDIO_DEV) - { - printk(KERN_ERR "ad1848 - Too many audio devices\n"); - return 0; - } - spin_lock_init(&devc->lock); - devc->base = io_base; - devc->irq_ok = 0; - devc->timer_running = 0; - devc->MCE_bit = 0x40; - devc->irq = 0; - devc->open_mode = 0; - devc->chip_name = devc->name = "AD1848"; - devc->model = MD_1848; /* AD1848 or CS4248 */ - devc->levels = NULL; - devc->debug_flag = 0; - - /* - * Check that the I/O address is in use. - * - * The bit 0x80 of the base I/O port is known to be 0 after the - * chip has performed its power on initialization. Just assume - * this has happened before the OS is starting. - * - * If the I/O address is unused, it typically returns 0xff. - */ - - if (inb(devc->base) == 0xff) - { - DDB(printk("ad1848_detect: The base I/O address appears to be dead\n")); - } - - /* - * Wait for the device to stop initialization - */ - - DDB(printk("ad1848_detect() - step 0\n")); - - for (i = 0; i < 10000000; i++) - { - unsigned char x = inb(devc->base); - - if (x == 0xff || !(x & 0x80)) - break; - } - - DDB(printk("ad1848_detect() - step A\n")); - - if (inb(devc->base) == 0x80) /* Not ready. Let's wait */ - ad_leave_MCE(devc); - - if ((inb(devc->base) & 0x80) != 0x00) /* Not a AD1848 */ - { - DDB(printk("ad1848 detect error - step A (%02x)\n", (int) inb(devc->base))); - return 0; - } - - /* - * Test if it's possible to change contents of the indirect registers. - * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only - * so try to avoid using it. - */ - - DDB(printk("ad1848_detect() - step B\n")); - ad_write(devc, 0, 0xaa); - ad_write(devc, 1, 0x45); /* 0x55 with bit 0x10 clear */ - - if ((tmp1 = ad_read(devc, 0)) != 0xaa || (tmp2 = ad_read(devc, 1)) != 0x45) - { - if (tmp2 == 0x65) /* AD1847 has couple of bits hardcoded to 1 */ - ad1847_flag = 1; - else - { - DDB(printk("ad1848 detect error - step B (%x/%x)\n", tmp1, tmp2)); - return 0; - } - } - DDB(printk("ad1848_detect() - step C\n")); - ad_write(devc, 0, 0x45); - ad_write(devc, 1, 0xaa); - - if ((tmp1 = ad_read(devc, 0)) != 0x45 || (tmp2 = ad_read(devc, 1)) != 0xaa) - { - if (tmp2 == 0x8a) /* AD1847 has few bits hardcoded to 1 */ - ad1847_flag = 1; - else - { - DDB(printk("ad1848 detect error - step C (%x/%x)\n", tmp1, tmp2)); - return 0; - } - } - - /* - * The indirect register I12 has some read only bits. Let's - * try to change them. - */ - - DDB(printk("ad1848_detect() - step D\n")); - tmp = ad_read(devc, 12); - ad_write(devc, 12, (~tmp) & 0x0f); - - if ((tmp & 0x0f) != ((tmp1 = ad_read(devc, 12)) & 0x0f)) - { - DDB(printk("ad1848 detect error - step D (%x)\n", tmp1)); - return 0; - } - - /* - * NOTE! Last 4 bits of the reg I12 tell the chip revision. - * 0x01=RevB and 0x0A=RevC. - */ - - /* - * The original AD1848/CS4248 has just 15 indirect registers. This means - * that I0 and I16 should return the same value (etc.). - * However this doesn't work with CS4248. Actually it seems to be impossible - * to detect if the chip is a CS4231 or CS4248. - * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails - * with CS4231. - */ - - /* - * OPTi 82C930 has mode2 control bit in another place. This test will fail - * with it. Accept this situation as a possible indication of this chip. - */ - - DDB(printk("ad1848_detect() - step F\n")); - ad_write(devc, 12, 0); /* Mode2=disabled */ - - for (i = 0; i < 16; i++) - { - if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) - { - DDB(printk("ad1848 detect step F(%d/%x/%x) - OPTi chip???\n", i, tmp1, tmp2)); - if (!ad1847_flag) - optiC930 = 1; - break; - } - } - - /* - * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40). - * The bit 0x80 is always 1 in CS4248 and CS4231. - */ - - DDB(printk("ad1848_detect() - step G\n")); - - if (ad_flags && *ad_flags == 400) - *ad_flags = 0; - else - ad_write(devc, 12, 0x40); /* Set mode2, clear 0x80 */ - - - if (ad_flags) - *ad_flags = 0; - - tmp1 = ad_read(devc, 12); - if (tmp1 & 0x80) - { - if (ad_flags) - *ad_flags |= AD_F_CS4248; - - devc->chip_name = "CS4248"; /* Our best knowledge just now */ - } - if (optiC930 || (tmp1 & 0xc0) == (0x80 | 0x40)) - { - /* - * CS4231 detected - is it? - * - * Verify that setting I0 doesn't change I16. - */ - - DDB(printk("ad1848_detect() - step H\n")); - ad_write(devc, 16, 0); /* Set I16 to known value */ - - ad_write(devc, 0, 0x45); - if ((tmp1 = ad_read(devc, 16)) != 0x45) /* No change -> CS4231? */ - { - ad_write(devc, 0, 0xaa); - if ((tmp1 = ad_read(devc, 16)) == 0xaa) /* Rotten bits? */ - { - DDB(printk("ad1848 detect error - step H(%x)\n", tmp1)); - return 0; - } - - /* - * Verify that some bits of I25 are read only. - */ - - DDB(printk("ad1848_detect() - step I\n")); - tmp1 = ad_read(devc, 25); /* Original bits */ - ad_write(devc, 25, ~tmp1); /* Invert all bits */ - if ((ad_read(devc, 25) & 0xe7) == (tmp1 & 0xe7)) - { - int id; - - /* - * It's at least CS4231 - */ - - devc->chip_name = "CS4231"; - devc->model = MD_4231; - - /* - * It could be an AD1845 or CS4231A as well. - * CS4231 and AD1845 report the same revision info in I25 - * while the CS4231A reports different. - */ - - id = ad_read(devc, 25); - if ((id & 0xe7) == 0x80) /* Device busy??? */ - id = ad_read(devc, 25); - if ((id & 0xe7) == 0x80) /* Device still busy??? */ - id = ad_read(devc, 25); - DDB(printk("ad1848_detect() - step J (%02x/%02x)\n", id, ad_read(devc, 25))); - - if ((id & 0xe7) == 0x80) { - /* - * It must be a CS4231 or AD1845. The register I23 of - * CS4231 is undefined and it appears to be read only. - * AD1845 uses I23 for setting sample rate. Assume - * the chip is AD1845 if I23 is changeable. - */ - - unsigned char tmp = ad_read(devc, 23); - ad_write(devc, 23, ~tmp); - - if (interwave) - { - devc->model = MD_IWAVE; - devc->chip_name = "IWave"; - } - else if (ad_read(devc, 23) != tmp) /* AD1845 ? */ - { - devc->chip_name = "AD1845"; - devc->model = MD_1845; - } - else if (cs4248_flag) - { - if (ad_flags) - *ad_flags |= AD_F_CS4248; - devc->chip_name = "CS4248"; - devc->model = MD_1848; - ad_write(devc, 12, ad_read(devc, 12) & ~0x40); /* Mode2 off */ - } - ad_write(devc, 23, tmp); /* Restore */ - } - else - { - switch (id & 0x1f) { - case 3: /* CS4236/CS4235/CS42xB/CS4239 */ - { - int xid; - ad_write(devc, 12, ad_read(devc, 12) | 0x60); /* switch to mode 3 */ - ad_write(devc, 23, 0x9c); /* select extended register 25 */ - xid = inb(io_Indexed_Data(devc)); - ad_write(devc, 12, ad_read(devc, 12) & ~0x60); /* back to mode 0 */ - switch (xid & 0x1f) - { - case 0x00: - devc->chip_name = "CS4237B(B)"; - devc->model = MD_42xB; - break; - case 0x08: - /* Seems to be a 4238 ?? */ - devc->chip_name = "CS4238"; - devc->model = MD_42xB; - break; - case 0x09: - devc->chip_name = "CS4238B"; - devc->model = MD_42xB; - break; - case 0x0b: - devc->chip_name = "CS4236B"; - devc->model = MD_4236; - break; - case 0x10: - devc->chip_name = "CS4237B"; - devc->model = MD_42xB; - break; - case 0x1d: - devc->chip_name = "CS4235"; - devc->model = MD_4235; - break; - case 0x1e: - devc->chip_name = "CS4239"; - devc->model = MD_4239; - break; - default: - printk("Chip ident is %X.\n", xid&0x1F); - devc->chip_name = "CS42xx"; - devc->model = MD_4232; - break; - } - } - break; - - case 2: /* CS4232/CS4232A */ - devc->chip_name = "CS4232"; - devc->model = MD_4232; - break; - - case 0: - if ((id & 0xe0) == 0xa0) - { - devc->chip_name = "CS4231A"; - devc->model = MD_4231A; - } - else - { - devc->chip_name = "CS4321"; - devc->model = MD_4231; - } - break; - - default: /* maybe */ - DDB(printk("ad1848: I25 = %02x/%02x\n", ad_read(devc, 25), ad_read(devc, 25) & 0xe7)); - if (optiC930) - { - devc->chip_name = "82C930"; - devc->model = MD_C930; - } - else - { - devc->chip_name = "CS4231"; - devc->model = MD_4231; - } - } - } - } - ad_write(devc, 25, tmp1); /* Restore bits */ - - DDB(printk("ad1848_detect() - step K\n")); - } - } else if (tmp1 == 0x0a) { - /* - * Is it perhaps a SoundPro CMI8330? - * If so, then we should be able to change indirect registers - * greater than I15 after activating MODE2, even though reading - * back I12 does not show it. - */ - - /* - * Let's try comparing register values - */ - for (i = 0; i < 16; i++) { - if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) { - DDB(printk("ad1848 detect step H(%d/%x/%x) - SoundPro chip?\n", i, tmp1, tmp2)); - soundpro = 1; - devc->chip_name = "SoundPro CMI 8330"; - break; - } - } - } - - DDB(printk("ad1848_detect() - step L\n")); - if (ad_flags) - { - if (devc->model != MD_1848) - *ad_flags |= AD_F_CS4231; - } - DDB(printk("ad1848_detect() - Detected OK\n")); - - if (devc->model == MD_1848 && ad1847_flag) - devc->chip_name = "AD1847"; - - - if (sscape_flag == 1) - devc->model = MD_1845_SSCAPE; - - return 1; -} - -int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback, - int dma_capture, int share_dma, int *osp, struct module *owner) -{ - /* - * NOTE! If irq < 0, there is another driver which has allocated the IRQ - * so that this driver doesn't need to allocate/deallocate it. - * The actually used IRQ is ABS(irq). - */ - - int my_dev; - char dev_name[100]; - int e; - - ad1848_info *devc = &adev_info[nr_ad1848_devs]; - - ad1848_port_info *portc = NULL; - - devc->irq = (irq > 0) ? irq : 0; - devc->open_mode = 0; - devc->timer_ticks = 0; - devc->dma1 = dma_playback; - devc->dma2 = dma_capture; - devc->subtype = cfg.card_subtype; - devc->audio_flags = DMA_AUTOMODE; - devc->playback_dev = devc->record_dev = 0; - if (name != NULL) - devc->name = name; - - if (name != NULL && name[0] != 0) - sprintf(dev_name, - "%s (%s)", name, devc->chip_name); - else - sprintf(dev_name, - "Generic audio codec (%s)", devc->chip_name); - - rename_region(ports, devc->name); - - conf_printf2(dev_name, devc->base, devc->irq, dma_playback, dma_capture); - - if (devc->model == MD_1848 || devc->model == MD_C930) - devc->audio_flags |= DMA_HARDSTOP; - - if (devc->model > MD_1848) - { - if (devc->dma1 == devc->dma2 || devc->dma2 == -1 || devc->dma1 == -1) - devc->audio_flags &= ~DMA_DUPLEX; - else - devc->audio_flags |= DMA_DUPLEX; - } - - portc = kmalloc(sizeof(ad1848_port_info), GFP_KERNEL); - if(portc==NULL) { - release_region(devc->base, 4); - return -1; - } - - if ((my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, - dev_name, - &ad1848_audio_driver, - sizeof(struct audio_driver), - devc->audio_flags, - ad_format_mask[devc->model], - devc, - dma_playback, - dma_capture)) < 0) - { - release_region(devc->base, 4); - kfree(portc); - return -1; - } - - audio_devs[my_dev]->portc = portc; - audio_devs[my_dev]->mixer_dev = -1; - if (owner) - audio_devs[my_dev]->d->owner = owner; - memset((char *) portc, 0, sizeof(*portc)); - - nr_ad1848_devs++; - - ad1848_init_hw(devc); - - if (irq > 0) - { - devc->dev_no = my_dev; - if (request_irq(devc->irq, adintr, 0, devc->name, - (void *)(long)my_dev) < 0) - { - printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n"); - /* Don't free it either then.. */ - devc->irq = 0; - } - if (capabilities[devc->model].flags & CAP_F_TIMER) - { -#ifndef CONFIG_SMP - int x; - unsigned char tmp = ad_read(devc, 16); -#endif - - devc->timer_ticks = 0; - - ad_write(devc, 21, 0x00); /* Timer MSB */ - ad_write(devc, 20, 0x10); /* Timer LSB */ -#ifndef CONFIG_SMP - ad_write(devc, 16, tmp | 0x40); /* Enable timer */ - for (x = 0; x < 100000 && devc->timer_ticks == 0; x++); - ad_write(devc, 16, tmp & ~0x40); /* Disable timer */ - - if (devc->timer_ticks == 0) - printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", irq); - else - { - DDB(printk("Interrupt test OK\n")); - devc->irq_ok = 1; - } -#else - devc->irq_ok = 1; -#endif - } - else - devc->irq_ok = 1; /* Couldn't test. assume it's OK */ - } else if (irq < 0) - irq2dev[-irq] = devc->dev_no = my_dev; - -#ifndef EXCLUDE_TIMERS - if ((capabilities[devc->model].flags & CAP_F_TIMER) && - devc->irq_ok) - ad1848_tmr_install(my_dev); -#endif - - if (!share_dma) - { - if (sound_alloc_dma(dma_playback, devc->name)) - printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_playback); - - if (dma_capture != dma_playback) - if (sound_alloc_dma(dma_capture, devc->name)) - printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_capture); - } - - if ((e = sound_install_mixer(MIXER_DRIVER_VERSION, - dev_name, - &ad1848_mixer_operations, - sizeof(struct mixer_operations), - devc)) >= 0) - { - audio_devs[my_dev]->mixer_dev = e; - if (owner) - mixer_devs[e]->owner = owner; - } - return my_dev; -} - -int ad1848_control(int cmd, int arg) -{ - ad1848_info *devc; - unsigned long flags; - - if (nr_ad1848_devs < 1) - return -ENODEV; - - devc = &adev_info[nr_ad1848_devs - 1]; - - switch (cmd) - { - case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ - if (devc->model != MD_1845 && devc->model != MD_1845_SSCAPE) - return -EINVAL; - spin_lock_irqsave(&devc->lock,flags); - ad_enter_MCE(devc); - ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5)); - ad_leave_MCE(devc); - spin_unlock_irqrestore(&devc->lock,flags); - break; - - case AD1848_MIXER_REROUTE: - { - int o = (arg >> 8) & 0xff; - int n = arg & 0xff; - - if (o < 0 || o >= SOUND_MIXER_NRDEVICES) - return -EINVAL; - - if (!(devc->supported_devices & (1 << o)) && - !(devc->supported_rec_devices & (1 << o))) - return -EINVAL; - - if (n == SOUND_MIXER_NONE) - { /* Just hide this control */ - ad1848_mixer_set(devc, o, 0); /* Shut up it */ - devc->supported_devices &= ~(1 << o); - devc->supported_rec_devices &= ~(1 << o); - break; - } - - /* Make the mixer control identified by o to appear as n */ - if (n < 0 || n >= SOUND_MIXER_NRDEVICES) - return -EINVAL; - - devc->mixer_reroute[n] = o; /* Rename the control */ - if (devc->supported_devices & (1 << o)) - devc->supported_devices |= (1 << n); - if (devc->supported_rec_devices & (1 << o)) - devc->supported_rec_devices |= (1 << n); - - devc->supported_devices &= ~(1 << o); - devc->supported_rec_devices &= ~(1 << o); - } - break; - } - return 0; -} - -void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int share_dma) -{ - int i, mixer, dev = 0; - ad1848_info *devc = NULL; - - for (i = 0; devc == NULL && i < nr_ad1848_devs; i++) - { - if (adev_info[i].base == io_base) - { - devc = &adev_info[i]; - dev = devc->dev_no; - } - } - - if (devc != NULL) - { - kfree(audio_devs[dev]->portc); - release_region(devc->base, 4); - - if (!share_dma) - { - if (devc->irq > 0) /* There is no point in freeing irq, if it wasn't allocated */ - free_irq(devc->irq, (void *)(long)devc->dev_no); - - sound_free_dma(dma_playback); - - if (dma_playback != dma_capture) - sound_free_dma(dma_capture); - - } - mixer = audio_devs[devc->dev_no]->mixer_dev; - if(mixer>=0) - sound_unload_mixerdev(mixer); - - nr_ad1848_devs--; - for ( ; i < nr_ad1848_devs ; i++) - adev_info[i] = adev_info[i+1]; - } - else - printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base); -} - -static irqreturn_t adintr(int irq, void *dev_id) -{ - unsigned char status; - ad1848_info *devc; - int dev; - int alt_stat = 0xff; - unsigned char c930_stat = 0; - int cnt = 0; - - dev = (long)dev_id; - devc = (ad1848_info *) audio_devs[dev]->devc; - -interrupt_again: /* Jump back here if int status doesn't reset */ - - status = inb(io_Status(devc)); - - if (status == 0x80) - printk(KERN_DEBUG "adintr: Why?\n"); - if (devc->model == MD_1848) - outb((0), io_Status(devc)); /* Clear interrupt status */ - - if (status & 0x01) - { - if (devc->model == MD_C930) - { /* 82C930 has interrupt status register in MAD16 register MC11 */ - - spin_lock(&devc->lock); - - /* 0xe0e is C930 address port - * 0xe0f is C930 data port - */ - outb(11, 0xe0e); - c930_stat = inb(0xe0f); - outb((~c930_stat), 0xe0f); - - spin_unlock(&devc->lock); - - alt_stat = (c930_stat << 2) & 0x30; - } - else if (devc->model != MD_1848) - { - spin_lock(&devc->lock); - alt_stat = ad_read(devc, 24); - ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat); /* Selective ack */ - spin_unlock(&devc->lock); - } - - if ((devc->open_mode & OPEN_READ) && (devc->audio_mode & PCM_ENABLE_INPUT) && (alt_stat & 0x20)) - { - DMAbuf_inputintr(devc->record_dev); - } - if ((devc->open_mode & OPEN_WRITE) && (devc->audio_mode & PCM_ENABLE_OUTPUT) && - (alt_stat & 0x10)) - { - DMAbuf_outputintr(devc->playback_dev, 1); - } - if (devc->model != MD_1848 && (alt_stat & 0x40)) /* Timer interrupt */ - { - devc->timer_ticks++; -#ifndef EXCLUDE_TIMERS - if (timer_installed == dev && devc->timer_running) - sound_timer_interrupt(); -#endif - } - } -/* - * Sometimes playback or capture interrupts occur while a timer interrupt - * is being handled. The interrupt will not be retriggered if we don't - * handle it now. Check if an interrupt is still pending and restart - * the handler in this case. - */ - if (inb(io_Status(devc)) & 0x01 && cnt++ < 4) - { - goto interrupt_again; - } - return IRQ_HANDLED; -} - -/* - * Experimental initialization sequence for the integrated sound system - * of the Compaq Deskpro M. - */ - -static int init_deskpro_m(struct address_info *hw_config) -{ - unsigned char tmp; - - if ((tmp = inb(0xc44)) == 0xff) - { - DDB(printk("init_deskpro_m: Dead port 0xc44\n")); - return 0; - } - - outb(0x10, 0xc44); - outb(0x40, 0xc45); - outb(0x00, 0xc46); - outb(0xe8, 0xc47); - outb(0x14, 0xc44); - outb(0x40, 0xc45); - outb(0x00, 0xc46); - outb(0xe8, 0xc47); - outb(0x10, 0xc44); - - return 1; -} - -/* - * Experimental initialization sequence for the integrated sound system - * of Compaq Deskpro XL. - */ - -static int init_deskpro(struct address_info *hw_config) -{ - unsigned char tmp; - - if ((tmp = inb(0xc44)) == 0xff) - { - DDB(printk("init_deskpro: Dead port 0xc44\n")); - return 0; - } - outb((tmp | 0x04), 0xc44); /* Select bank 1 */ - if (inb(0xc44) != 0x04) - { - DDB(printk("init_deskpro: Invalid bank1 signature in port 0xc44\n")); - return 0; - } - /* - * OK. It looks like a Deskpro so let's proceed. - */ - - /* - * I/O port 0xc44 Audio configuration register. - * - * bits 0xc0: Audio revision bits - * 0x00 = Compaq Business Audio - * 0x40 = MS Sound System Compatible (reset default) - * 0x80 = Reserved - * 0xc0 = Reserved - * bit 0x20: No Wait State Enable - * 0x00 = Disabled (reset default, DMA mode) - * 0x20 = Enabled (programmed I/O mode) - * bit 0x10: MS Sound System Decode Enable - * 0x00 = Decoding disabled (reset default) - * 0x10 = Decoding enabled - * bit 0x08: FM Synthesis Decode Enable - * 0x00 = Decoding Disabled (reset default) - * 0x08 = Decoding enabled - * bit 0x04 Bank select - * 0x00 = Bank 0 - * 0x04 = Bank 1 - * bits 0x03 MSS Base address - * 0x00 = 0x530 (reset default) - * 0x01 = 0x604 - * 0x02 = 0xf40 - * 0x03 = 0xe80 - */ - -#ifdef DEBUGXL - /* Debug printing */ - printk("Port 0xc44 (before): "); - outb((tmp & ~0x04), 0xc44); - printk("%02x ", inb(0xc44)); - outb((tmp | 0x04), 0xc44); - printk("%02x\n", inb(0xc44)); -#endif - - /* Set bank 1 of the register */ - tmp = 0x58; /* MSS Mode, MSS&FM decode enabled */ - - switch (hw_config->io_base) - { - case 0x530: - tmp |= 0x00; - break; - case 0x604: - tmp |= 0x01; - break; - case 0xf40: - tmp |= 0x02; - break; - case 0xe80: - tmp |= 0x03; - break; - default: - DDB(printk("init_deskpro: Invalid MSS port %x\n", hw_config->io_base)); - return 0; - } - outb((tmp & ~0x04), 0xc44); /* Write to bank=0 */ - -#ifdef DEBUGXL - /* Debug printing */ - printk("Port 0xc44 (after): "); - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - printk("%02x ", inb(0xc44)); - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - printk("%02x\n", inb(0xc44)); -#endif - - /* - * I/O port 0xc45 FM Address Decode/MSS ID Register. - * - * bank=0, bits 0xfe: FM synthesis Decode Compare bits 7:1 (default=0x88) - * bank=0, bit 0x01: SBIC Power Control Bit - * 0x00 = Powered up - * 0x01 = Powered down - * bank=1, bits 0xfc: MSS ID (default=0x40) - */ - -#ifdef DEBUGXL - /* Debug printing */ - printk("Port 0xc45 (before): "); - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - printk("%02x ", inb(0xc45)); - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - printk("%02x\n", inb(0xc45)); -#endif - - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - outb((0x88), 0xc45); /* FM base 7:0 = 0x88 */ - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - outb((0x10), 0xc45); /* MSS ID = 0x10 (MSS port returns 0x04) */ - -#ifdef DEBUGXL - /* Debug printing */ - printk("Port 0xc45 (after): "); - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - printk("%02x ", inb(0xc45)); - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - printk("%02x\n", inb(0xc45)); -#endif - - - /* - * I/O port 0xc46 FM Address Decode/Address ASIC Revision Register. - * - * bank=0, bits 0xff: FM synthesis Decode Compare bits 15:8 (default=0x03) - * bank=1, bits 0xff: Audio addressing ASIC id - */ - -#ifdef DEBUGXL - /* Debug printing */ - printk("Port 0xc46 (before): "); - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - printk("%02x ", inb(0xc46)); - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - printk("%02x\n", inb(0xc46)); -#endif - - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - outb((0x03), 0xc46); /* FM base 15:8 = 0x03 */ - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - outb((0x11), 0xc46); /* ASIC ID = 0x11 */ - -#ifdef DEBUGXL - /* Debug printing */ - printk("Port 0xc46 (after): "); - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - printk("%02x ", inb(0xc46)); - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - printk("%02x\n", inb(0xc46)); -#endif - - /* - * I/O port 0xc47 FM Address Decode Register. - * - * bank=0, bits 0xff: Decode enable selection for various FM address bits - * bank=1, bits 0xff: Reserved - */ - -#ifdef DEBUGXL - /* Debug printing */ - printk("Port 0xc47 (before): "); - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - printk("%02x ", inb(0xc47)); - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - printk("%02x\n", inb(0xc47)); -#endif - - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - outb((0x7c), 0xc47); /* FM decode enable bits = 0x7c */ - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - outb((0x00), 0xc47); /* Reserved bank1 = 0x00 */ - -#ifdef DEBUGXL - /* Debug printing */ - printk("Port 0xc47 (after): "); - outb((tmp & ~0x04), 0xc44); /* Select bank=0 */ - printk("%02x ", inb(0xc47)); - outb((tmp | 0x04), 0xc44); /* Select bank=1 */ - printk("%02x\n", inb(0xc47)); -#endif - - /* - * I/O port 0xc6f = Audio Disable Function Register - */ - -#ifdef DEBUGXL - printk("Port 0xc6f (before) = %02x\n", inb(0xc6f)); -#endif - - outb((0x80), 0xc6f); - -#ifdef DEBUGXL - printk("Port 0xc6f (after) = %02x\n", inb(0xc6f)); -#endif - - return 1; -} - -int probe_ms_sound(struct address_info *hw_config, struct resource *ports) -{ - unsigned char tmp; - - DDB(printk("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype)); - - if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */ - { - /* check_opl3(0x388, hw_config); */ - return ad1848_detect(ports, NULL, hw_config->osp); - } - - if (deskpro_xl && hw_config->card_subtype == 2) /* Compaq Deskpro XL */ - { - if (!init_deskpro(hw_config)) - return 0; - } - - if (deskpro_m) /* Compaq Deskpro M */ - { - if (!init_deskpro_m(hw_config)) - return 0; - } - - /* - * Check if the IO port returns valid signature. The original MS Sound - * system returns 0x04 while some cards (AudioTrix Pro for example) - * return 0x00 or 0x0f. - */ - - if ((tmp = inb(hw_config->io_base + 3)) == 0xff) /* Bus float */ - { - int ret; - - DDB(printk("I/O address is inactive (%x)\n", tmp)); - if (!(ret = ad1848_detect(ports, NULL, hw_config->osp))) - return 0; - return 1; - } - DDB(printk("MSS signature = %x\n", tmp & 0x3f)); - if ((tmp & 0x3f) != 0x04 && - (tmp & 0x3f) != 0x0f && - (tmp & 0x3f) != 0x00) - { - int ret; - - MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, (int) inb(hw_config->io_base + 3))); - DDB(printk("Trying to detect codec anyway but IRQ/DMA may not work\n")); - if (!(ret = ad1848_detect(ports, NULL, hw_config->osp))) - return 0; - - hw_config->card_subtype = 1; - return 1; - } - if ((hw_config->irq != 5) && - (hw_config->irq != 7) && - (hw_config->irq != 9) && - (hw_config->irq != 10) && - (hw_config->irq != 11) && - (hw_config->irq != 12)) - { - printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq); - return 0; - } - if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) - { - printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma); - return 0; - } - /* - * Check that DMA0 is not in use with a 8 bit board. - */ - - if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) - { - printk(KERN_ERR "MSS: Can't use DMA0 with a 8 bit card/slot\n"); - return 0; - } - if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80) - { - printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); - return 0; - } - return ad1848_detect(ports, NULL, hw_config->osp); -} - -void attach_ms_sound(struct address_info *hw_config, struct resource *ports, struct module *owner) -{ - static signed char interrupt_bits[12] = - { - -1, -1, -1, -1, -1, 0x00, -1, 0x08, -1, 0x10, 0x18, 0x20 - }; - signed char bits; - char dma2_bit = 0; - - static char dma_bits[4] = - { - 1, 2, 0, 3 - }; - - int config_port = hw_config->io_base + 0; - int version_port = hw_config->io_base + 3; - int dma = hw_config->dma; - int dma2 = hw_config->dma2; - - if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */ - { - hw_config->slots[0] = ad1848_init("MS Sound System", ports, - hw_config->irq, - hw_config->dma, - hw_config->dma2, 0, - hw_config->osp, - owner); - return; - } - /* - * Set the IRQ and DMA addresses. - */ - - bits = interrupt_bits[hw_config->irq]; - if (bits == -1) - { - printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq); - release_region(ports->start, 4); - release_region(ports->start - 4, 4); - return; - } - outb((bits | 0x40), config_port); - if ((inb(version_port) & 0x40) == 0) - printk(KERN_ERR "[MSS: IRQ Conflict?]\n"); - -/* - * Handle the capture DMA channel - */ - - if (dma2 != -1 && dma2 != dma) - { - if (!((dma == 0 && dma2 == 1) || - (dma == 1 && dma2 == 0) || - (dma == 3 && dma2 == 0))) - { /* Unsupported combination. Try to swap channels */ - int tmp = dma; - - dma = dma2; - dma2 = tmp; - } - if ((dma == 0 && dma2 == 1) || - (dma == 1 && dma2 == 0) || - (dma == 3 && dma2 == 0)) - { - dma2_bit = 0x04; /* Enable capture DMA */ - } - else - { - printk(KERN_WARNING "MSS: Invalid capture DMA\n"); - dma2 = dma; - } - } - else - { - dma2 = dma; - } - - hw_config->dma = dma; - hw_config->dma2 = dma2; - - outb((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */ - - hw_config->slots[0] = ad1848_init("MS Sound System", ports, - hw_config->irq, - dma, dma2, 0, - hw_config->osp, - THIS_MODULE); -} - -void unload_ms_sound(struct address_info *hw_config) -{ - ad1848_unload(hw_config->io_base + 4, - hw_config->irq, - hw_config->dma, - hw_config->dma2, 0); - sound_unload_audiodev(hw_config->slots[0]); - release_region(hw_config->io_base, 4); -} - -#ifndef EXCLUDE_TIMERS - -/* - * Timer stuff (for /dev/music). - */ - -static unsigned int current_interval; - -static unsigned int ad1848_tmr_start(int dev, unsigned int usecs) -{ - unsigned long flags; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - unsigned long xtal_nsecs; /* nanoseconds per xtal oscillator tick */ - unsigned long divider; - - spin_lock_irqsave(&devc->lock,flags); - - /* - * Length of the timer interval (in nanoseconds) depends on the - * selected crystal oscillator. Check this from bit 0x01 of I8. - * - * AD1845 has just one oscillator which has cycle time of 10.050 us - * (when a 24.576 MHz xtal oscillator is used). - * - * Convert requested interval to nanoseconds before computing - * the timer divider. - */ - - if (devc->model == MD_1845 || devc->model == MD_1845_SSCAPE) - xtal_nsecs = 10050; - else if (ad_read(devc, 8) & 0x01) - xtal_nsecs = 9920; - else - xtal_nsecs = 9969; - - divider = (usecs * 1000 + xtal_nsecs / 2) / xtal_nsecs; - - if (divider < 100) /* Don't allow shorter intervals than about 1ms */ - divider = 100; - - if (divider > 65535) /* Overflow check */ - divider = 65535; - - ad_write(devc, 21, (divider >> 8) & 0xff); /* Set upper bits */ - ad_write(devc, 20, divider & 0xff); /* Set lower bits */ - ad_write(devc, 16, ad_read(devc, 16) | 0x40); /* Start the timer */ - devc->timer_running = 1; - spin_unlock_irqrestore(&devc->lock,flags); - - return current_interval = (divider * xtal_nsecs + 500) / 1000; -} - -static void ad1848_tmr_reprogram(int dev) -{ - /* - * Audio driver has changed sampling rate so that a different xtal - * oscillator was selected. We have to reprogram the timer rate. - */ - - ad1848_tmr_start(dev, current_interval); - sound_timer_syncinterval(current_interval); -} - -static void ad1848_tmr_disable(int dev) -{ - unsigned long flags; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - - spin_lock_irqsave(&devc->lock,flags); - ad_write(devc, 16, ad_read(devc, 16) & ~0x40); - devc->timer_running = 0; - spin_unlock_irqrestore(&devc->lock,flags); -} - -static void ad1848_tmr_restart(int dev) -{ - unsigned long flags; - ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc; - - if (current_interval == 0) - return; - - spin_lock_irqsave(&devc->lock,flags); - ad_write(devc, 16, ad_read(devc, 16) | 0x40); - devc->timer_running = 1; - spin_unlock_irqrestore(&devc->lock,flags); -} - -static struct sound_lowlev_timer ad1848_tmr = -{ - 0, - 2, - ad1848_tmr_start, - ad1848_tmr_disable, - ad1848_tmr_restart -}; - -static int ad1848_tmr_install(int dev) -{ - if (timer_installed != -1) - return 0; /* Don't install another timer */ - - timer_installed = ad1848_tmr.dev = dev; - sound_timer_init(&ad1848_tmr, audio_devs[dev]->name); - - return 1; -} -#endif /* EXCLUDE_TIMERS */ - -EXPORT_SYMBOL(ad1848_detect); -EXPORT_SYMBOL(ad1848_init); -EXPORT_SYMBOL(ad1848_unload); -EXPORT_SYMBOL(ad1848_control); -EXPORT_SYMBOL(probe_ms_sound); -EXPORT_SYMBOL(attach_ms_sound); -EXPORT_SYMBOL(unload_ms_sound); - -static int __initdata io = -1; -static int __initdata irq = -1; -static int __initdata dma = -1; -static int __initdata dma2 = -1; -static int __initdata type = 0; - -module_param(io, int, 0); /* I/O for a raw AD1848 card */ -module_param(irq, int, 0); /* IRQ to use */ -module_param(dma, int, 0); /* First DMA channel */ -module_param(dma2, int, 0); /* Second DMA channel */ -module_param(type, int, 0); /* Card type */ -module_param(deskpro_xl, bool, 0); /* Special magic for Deskpro XL boxen */ -module_param(deskpro_m, bool, 0); /* Special magic for Deskpro M box */ -module_param(soundpro, bool, 0); /* More special magic for SoundPro chips */ - -#ifdef CONFIG_PNP -module_param(isapnp, int, 0); -module_param(isapnpjump, int, 0); -module_param(reverse, bool, 0); -MODULE_PARM_DESC(isapnp, "When set to 0, Plug & Play support will be disabled"); -MODULE_PARM_DESC(isapnpjump, "Jumps to a specific slot in the driver's PnP table. Use the source, Luke."); -MODULE_PARM_DESC(reverse, "When set to 1, will reverse ISAPnP search order"); - -static struct pnp_dev *ad1848_dev = NULL; - -/* Please add new entries at the end of the table */ -static struct { - char *name; - unsigned short card_vendor, card_device, - vendor, function; - short mss_io, irq, dma, dma2; /* index into isapnp table */ - int type; -} ad1848_isapnp_list[] __initdata = { - {"CMI 8330 SoundPRO", - ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), - ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), - 0, 0, 0,-1, 0}, - {"CS4232 based card", - ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000), - 0, 0, 0, 1, 0}, - {"CS4232 based card", - ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), - 0, 0, 0, 1, 0}, - {"OPL3-SA2 WSS mode", - ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), - 1, 0, 0, 1, 1}, - {"Advanced Gravis InterWave Audio", - ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001), - ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000), - 0, 0, 0, 1, 0}, - {NULL} -}; - -static struct isapnp_device_id id_table[] __devinitdata = { - { ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), - ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 }, - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000), 0 }, - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), 0 }, - /* The main driver for this card is opl3sa2 - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), 0 }, - */ - { ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001), - ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000), 0 }, - {0} -}; - -MODULE_DEVICE_TABLE(isapnp, id_table); - -static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev *dev) -{ - int err; - - err = pnp_device_attach(dev); - if (err < 0) - return(NULL); - - if((err = pnp_activate_dev(dev)) < 0) { - printk(KERN_ERR "ad1848: %s %s config failed (out of resources?)[%d]\n", devname, resname, err); - - pnp_device_detach(dev); - - return(NULL); - } - audio_activated = 1; - return(dev); -} - -static struct pnp_dev __init *ad1848_init_generic(struct pnp_card *bus, - struct address_info *hw_config, int slot) -{ - - /* Configure Audio device */ - if((ad1848_dev = pnp_find_dev(bus, ad1848_isapnp_list[slot].vendor, ad1848_isapnp_list[slot].function, NULL))) - { - if((ad1848_dev = activate_dev(ad1848_isapnp_list[slot].name, "ad1848", ad1848_dev))) - { - hw_config->io_base = pnp_port_start(ad1848_dev, ad1848_isapnp_list[slot].mss_io); - hw_config->irq = pnp_irq(ad1848_dev, ad1848_isapnp_list[slot].irq); - hw_config->dma = pnp_dma(ad1848_dev, ad1848_isapnp_list[slot].dma); - if(ad1848_isapnp_list[slot].dma2 != -1) - hw_config->dma2 = pnp_dma(ad1848_dev, ad1848_isapnp_list[slot].dma2); - else - hw_config->dma2 = -1; - hw_config->card_subtype = ad1848_isapnp_list[slot].type; - } else - return(NULL); - } else - return(NULL); - - return(ad1848_dev); -} - -static int __init ad1848_isapnp_init(struct address_info *hw_config, struct pnp_card *bus, int slot) -{ - char *busname = bus->name[0] ? bus->name : ad1848_isapnp_list[slot].name; - - /* Initialize this baby. */ - - if(ad1848_init_generic(bus, hw_config, slot)) { - /* We got it. */ - - printk(KERN_NOTICE "ad1848: PnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n", - busname, - hw_config->io_base, hw_config->irq, hw_config->dma, - hw_config->dma2); - return 1; - } - return 0; -} - -static int __init ad1848_isapnp_probe(struct address_info *hw_config) -{ - static int first = 1; - int i; - - /* Count entries in sb_isapnp_list */ - for (i = 0; ad1848_isapnp_list[i].card_vendor != 0; i++); - i--; - - /* Check and adjust isapnpjump */ - if( isapnpjump < 0 || isapnpjump > i) { - isapnpjump = reverse ? i : 0; - printk(KERN_ERR "ad1848: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump); - } - - if(!first || !reverse) - i = isapnpjump; - first = 0; - while(ad1848_isapnp_list[i].card_vendor != 0) { - static struct pnp_card *bus = NULL; - - while ((bus = pnp_find_card( - ad1848_isapnp_list[i].card_vendor, - ad1848_isapnp_list[i].card_device, - bus))) { - - if(ad1848_isapnp_init(hw_config, bus, i)) { - isapnpjump = i; /* start next search from here */ - return 0; - } - } - i += reverse ? -1 : 1; - } - - return -ENODEV; -} -#endif - - -static int __init init_ad1848(void) -{ - printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n"); - -#ifdef CONFIG_PNP - if(isapnp && (ad1848_isapnp_probe(&cfg) < 0) ) { - printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n"); - isapnp = 0; - } -#endif - - if(io != -1) { - struct resource *ports; - if( isapnp == 0 ) - { - if(irq == -1 || dma == -1) { - printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n"); - return -EINVAL; - } - - cfg.irq = irq; - cfg.io_base = io; - cfg.dma = dma; - cfg.dma2 = dma2; - cfg.card_subtype = type; - } - - ports = request_region(io + 4, 4, "ad1848"); - - if (!ports) - return -EBUSY; - - if (!request_region(io, 4, "WSS config")) { - release_region(io + 4, 4); - return -EBUSY; - } - - if (!probe_ms_sound(&cfg, ports)) { - release_region(io + 4, 4); - release_region(io, 4); - return -ENODEV; - } - attach_ms_sound(&cfg, ports, THIS_MODULE); - loaded = 1; - } - return 0; -} - -static void __exit cleanup_ad1848(void) -{ - if(loaded) - unload_ms_sound(&cfg); - -#ifdef CONFIG_PNP - if(ad1848_dev){ - if(audio_activated) - pnp_device_detach(ad1848_dev); - } -#endif -} - -module_init(init_ad1848); -module_exit(cleanup_ad1848); - -#ifndef MODULE -static int __init setup_ad1848(char *str) -{ - /* io, irq, dma, dma2, type */ - int ints[6]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - irq = ints[2]; - dma = ints[3]; - dma2 = ints[4]; - type = ints[5]; - - return 1; -} - -__setup("ad1848=", setup_ad1848); -#endif -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/ad1848.h b/ANDROID_3.4.5/sound/oss/ad1848.h deleted file mode 100644 index b95ebe28..00000000 --- a/ANDROID_3.4.5/sound/oss/ad1848.h +++ /dev/null @@ -1,24 +0,0 @@ - -#include - -#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */ -#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */ - -#define AD1848_SET_XTAL 1 -#define AD1848_MIXER_REROUTE 2 - -#define AD1848_REROUTE(oldctl, newctl) \ - ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl)) - - -int ad1848_init(char *name, struct resource *ports, int irq, int dma_playback, - int dma_capture, int share_dma, int *osp, struct module *owner); -void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma); - -int ad1848_detect (struct resource *ports, int *flags, int *osp); -int ad1848_control(int cmd, int arg); - -void attach_ms_sound(struct address_info * hw_config, struct resource *ports, struct module * owner); - -int probe_ms_sound(struct address_info *hw_config, struct resource *ports); -void unload_ms_sound(struct address_info *hw_info); diff --git a/ANDROID_3.4.5/sound/oss/ad1848_mixer.h b/ANDROID_3.4.5/sound/oss/ad1848_mixer.h deleted file mode 100644 index 2cf719b5..00000000 --- a/ANDROID_3.4.5/sound/oss/ad1848_mixer.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * sound/oss/ad1848_mixer.h - * - * Definitions for the mixer of AD1848 and compatible codecs. - */ - -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - - -/* - * The AD1848 codec has generic input lines called Line, Aux1 and Aux2. - * Sound card manufacturers have connected actual inputs (CD, synth, line, - * etc) to these inputs in different order. Therefore it's difficult - * to assign mixer channels to these inputs correctly. The following - * contains two alternative mappings. The first one is for GUS MAX and - * the second is just a generic one (line1, line2 and line3). - * (Actually this is not a mapping but rather some kind of interleaving - * solution). - */ -#define MODE1_REC_DEVICES (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \ - SOUND_MASK_LINE1 | SOUND_MASK_IMIX) - -#define SPRO_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_LINE1) - -#define MODE1_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_MIC | \ - SOUND_MASK_LINE2 | \ - SOUND_MASK_IGAIN | \ - SOUND_MASK_PCM | SOUND_MASK_IMIX) - -#define MODE2_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \ - SOUND_MASK_MIC | \ - SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \ - SOUND_MASK_IGAIN | \ - SOUND_MASK_PCM | SOUND_MASK_IMIX) - -#define MODE3_MIXER_DEVICES (MODE2_MIXER_DEVICES | SOUND_MASK_VOLUME) - -/* OPTi 82C930 has no IMIX level control, but it can still be selected as an - * input - */ -#define C930_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \ - SOUND_MASK_MIC | SOUND_MASK_VOLUME | \ - SOUND_MASK_LINE3 | \ - SOUND_MASK_IGAIN | SOUND_MASK_PCM) - -#define SPRO_MIXER_DEVICES (SOUND_MASK_VOLUME | SOUND_MASK_PCM | \ - SOUND_MASK_LINE | SOUND_MASK_SYNTH | \ - SOUND_MASK_CD | SOUND_MASK_MIC | \ - SOUND_MASK_SPEAKER | SOUND_MASK_LINE1 | \ - SOUND_MASK_OGAIN) - -struct mixer_def { - unsigned int regno:6; /* register number for volume */ - unsigned int polarity:1; /* volume polarity: 0=normal, 1=reversed */ - unsigned int bitpos:3; /* position of bits in register for volume */ - unsigned int nbits:3; /* number of bits in register for volume */ - unsigned int mutereg:6; /* register number for mute bit */ - unsigned int mutepol:1; /* mute polarity: 0=normal, 1=reversed */ - unsigned int mutepos:4; /* position of mute bit in register */ - unsigned int recreg:6; /* register number for recording bit */ - unsigned int recpol:1; /* recording polarity: 0=normal, 1=reversed */ - unsigned int recpos:4; /* position of recording bit in register */ -}; - -static char mix_cvt[101] = { - 0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42, - 43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65, - 65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79, - 80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90, - 91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99, - 100 -}; - -typedef struct mixer_def mixer_ent; -typedef mixer_ent mixer_ents[2]; - -/* - * Most of the mixer entries work in backwards. Setting the polarity field - * makes them to work correctly. - * - * The channel numbering used by individual sound cards is not fixed. Some - * cards have assigned different meanings for the AUX1, AUX2 and LINE inputs. - * The current version doesn't try to compensate this. - */ - -#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit) \ - [name] = {{reg_l, pola_l, pos_l, len_l, reg_l, 0, mute_bit, 0, 0, 8}, \ - {reg_r, pola_r, pos_r, len_r, reg_r, 0, mute_bit, 0, 0, 8}} - -#define MIX_ENT2(name, reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \ - rec_reg_l, rec_pola_l, rec_pos_l, \ - reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r, \ - rec_reg_r, rec_pola_r, rec_pos_r) \ - [name] = {{reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \ - rec_reg_l, rec_pola_l, rec_pos_l}, \ - {reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r, \ - rec_reg_r, rec_pola_r, rec_pos_r}} - -static mixer_ents ad1848_mix_devices[32] = { - MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8), - MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7), - MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8), - MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8), - MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7) -}; - -static mixer_ents iwave_mix_devices[32] = { - MIX_ENT(SOUND_MIXER_VOLUME, 25, 1, 0, 5, 27, 1, 0, 5, 8), - MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7), - MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8), - MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5, 8), - MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8), - MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7) -}; - -static mixer_ents cs42xb_mix_devices[32] = { - /* Digital master volume actually has seven bits, but we only use - six to avoid the discontinuity when the analog gain kicks in. */ - MIX_ENT(SOUND_MIXER_VOLUME, 46, 1, 0, 6, 47, 1, 0, 6, 7), - MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7), - MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_MIC, 34, 1, 0, 5, 35, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7), - /* For the IMIX entry, it was not possible to use the MIX_ENT macro - because the mute bit is in different positions for the two - channels and requires reverse polarity. */ - [SOUND_MIXER_IMIX] = {{13, 1, 2, 6, 13, 1, 0, 0, 0, 8}, - {42, 1, 0, 6, 42, 1, 7, 0, 0, 8}}, - MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8), - MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_LINE3, 38, 1, 0, 6, 39, 1, 0, 6, 7) -}; - -/* OPTi 82C930 has somewhat different port addresses. - * Note: VOLUME == SPEAKER, SYNTH == LINE2, LINE == LINE3, CD == LINE1 - * VOLUME, SYNTH, LINE, CD are not enabled above. - * MIC is level of mic monitoring direct to output. Same for CD, LINE, etc. - */ -static mixer_ents c930_mix_devices[32] = { - MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5, 7), - MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4, 7), - MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5, 7), - MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 1, 5, 23, 1, 1, 5, 7), - MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4, 7), - MIX_ENT(SOUND_MIXER_MIC, 20, 1, 1, 4, 21, 1, 1, 4, 7), - MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7), - MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8), - MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7), - MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7), - MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7) -}; - -static mixer_ents spro_mix_devices[32] = { - MIX_ENT (SOUND_MIXER_VOLUME, 19, 0, 4, 4, 19, 0, 0, 4, 8), - MIX_ENT (SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT (SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT2(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 23, 0, 3, 0, 0, 8, - 5, 1, 1, 4, 23, 0, 3, 0, 0, 8), - MIX_ENT (SOUND_MIXER_PCM, 6, 1, 1, 4, 7, 1, 1, 4, 8), - MIX_ENT (SOUND_MIXER_SPEAKER, 18, 0, 3, 2, 0, 0, 0, 0, 8), - MIX_ENT2(SOUND_MIXER_LINE, 20, 0, 4, 4, 17, 1, 4, 16, 0, 2, - 20, 0, 0, 4, 17, 1, 3, 16, 0, 1), - MIX_ENT2(SOUND_MIXER_MIC, 18, 0, 0, 3, 17, 1, 0, 16, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - MIX_ENT2(SOUND_MIXER_CD, 21, 0, 4, 4, 17, 1, 2, 16, 0, 4, - 21, 0, 0, 4, 17, 1, 1, 16, 0, 3), - MIX_ENT (SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT (SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT (SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT (SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), - MIX_ENT (SOUND_MIXER_OGAIN, 17, 1, 6, 1, 0, 0, 0, 0, 8), - /* This is external wavetable */ - MIX_ENT2(SOUND_MIXER_LINE1, 22, 0, 4, 4, 23, 1, 1, 23, 0, 4, - 22, 0, 0, 4, 23, 1, 0, 23, 0, 5), -}; - -static int default_mixer_levels[32] = -{ - 0x3232, /* Master Volume */ - 0x3232, /* Bass */ - 0x3232, /* Treble */ - 0x4b4b, /* FM */ - 0x3232, /* PCM */ - 0x1515, /* PC Speaker */ - 0x2020, /* Ext Line */ - 0x1010, /* Mic */ - 0x4b4b, /* CD */ - 0x0000, /* Recording monitor */ - 0x4b4b, /* Second PCM */ - 0x4b4b, /* Recording level */ - 0x4b4b, /* Input gain */ - 0x4b4b, /* Output gain */ - 0x2020, /* Line1 */ - 0x2020, /* Line2 */ - 0x1515 /* Line3 (usually line in)*/ -}; - -#define LEFT_CHN 0 -#define RIGHT_CHN 1 - -/* - * Channel enable bits for ioctl(SOUND_MIXER_PRIVATE1) - */ - -#ifndef AUDIO_SPEAKER -#define AUDIO_SPEAKER 0x01 /* Enable mono output */ -#define AUDIO_HEADPHONE 0x02 /* Sparc only */ -#define AUDIO_LINE_OUT 0x04 /* Sparc only */ -#endif diff --git a/ANDROID_3.4.5/sound/oss/aedsp16.c b/ANDROID_3.4.5/sound/oss/aedsp16.c deleted file mode 100644 index 35b5912c..00000000 --- a/ANDROID_3.4.5/sound/oss/aedsp16.c +++ /dev/null @@ -1,1373 +0,0 @@ -/* - sound/oss/aedsp16.c - - Audio Excel DSP 16 software configuration routines - Copyright (C) 1995,1996,1997,1998 Riccardo Facchetti (fizban@tin.it) - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. - - */ -/* - * Include the main OSS Lite header file. It include all the os, OSS Lite, etc - * headers needed by this source. - */ -#include -#include -#include -#include "sound_config.h" - -/* - - READ THIS - - This module started to configure the Audio Excel DSP 16 Sound Card. - Now works with the SC-6000 (old aedsp16) and new SC-6600 based cards. - - NOTE: I have NO idea about Audio Excel DSP 16 III. If someone owns this - audio card and want to see the kernel support for it, please contact me. - - Audio Excel DSP 16 is an SB pro II, Microsoft Sound System and MPU-401 - compatible card. - It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq), - so before this module, the only way to configure the DSP under linux was - boot the MS-DOS loading the sound.sys device driver (this driver soft- - configure the sound board hardware by massaging someone of its registers), - and then ctrl-alt-del to boot linux with the DSP configured by the DOS - driver. - - This module works configuring your Audio Excel DSP 16's irq, dma and - mpu-401-irq. The OSS Lite routines rely on the fact that if the - hardware is there, they can detect it. The problem with AEDSP16 is - that no hardware can be found by the probe routines if the sound card - is not configured properly. Sometimes the kernel probe routines can find - an SBPRO even when the card is not configured (this is the standard setup - of the card), but the SBPRO emulation don't work well if the card is not - properly initialized. For this reason - - aedsp16_init_board() - - routine is called before the OSS Lite probe routines try to detect the - hardware. - - NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS) - - NOTE: Now it works with SC-6000 and SC-6600 based audio cards. The new cards - have no jumper switch at all. No more WSS or MPU-401 I/O port switches. They - have to be configured by software. - - NOTE: The driver is merged with the new OSS Lite sound driver. It works - as a lowlevel driver. - - The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS; - the OSS Lite sound driver can be configured for SBPRO and MSS cards - at the same time, but the aedsp16 can't be two cards!! - When we configure it, we have to choose the SBPRO or the MSS emulation - for AEDSP16. We also can install a *REAL* card of the other type (see [1]). - - NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO - please let me know if it works. - - The MPU-401 support can be compiled in together with one of the other - two operating modes. - - NOTE: This is something like plug-and-play: we have only to plug - the AEDSP16 board in the socket, and then configure and compile - a kernel that uses the AEDSP16 software configuration capability. - No jumper setting is needed! - - For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3 - you have just to make config the OSS Lite package, configuring - the AEDSP16 sound card, then activating the SBPro emulation mode - and at last configuring IRQ and DMA. - Compile the kernel and run it. - - NOTE: This means for SC-6000 cards that you can choose irq and dma, - but not the I/O addresses. To change I/O addresses you have to set - them with jumpers. For SC-6600 cards you have no jumpers so you have - to set up your full card configuration in the make config. - - You can change the irq/dma/mirq settings WITHOUT THE NEED to open - your computer and massage the jumpers (there are no irq/dma/mirq - jumpers to be configured anyway, only I/O BASE values have to be - configured with jumpers) - - For some ununderstandable reason, the card default of irq 7, dma 1, - don't work for me. Seems to be an IRQ or DMA conflict. Under heavy - HDD work, the kernel start to erupt out a lot of messages like: - - 'Sound: DMA timed out - IRQ/DRQ config error?' - - For what I can say, I have NOT any conflict at irq 7 (under linux I'm - using the lp polling driver), and dma line 1 is unused as stated by - /proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so - I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows! - Anyway a setting of irq 10, dma 3 works really fine. - - NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know - the emulation mode, all the installed hardware and the hardware - configuration (irq and dma settings of all the hardware). - - This init module should work with SBPRO+MSS, when one of the two is - the AEDSP16 emulation and the other the real card. (see [1]) - For example: - - AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other - AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other - - MPU401 should work. (see [2]) - - [1] - --- - Date: Mon, 29 Jul 1997 08:35:40 +0100 - From: Mr S J Greenaway - - [...] - Just to let you know got my Audio Excel (emulating a MSS) working - with my original SB16, thanks for the driver! - [...] - --- - - [2] Not tested by me for lack of hardware. - - TODO, WISHES AND TECH - - - About I/O ports allocation - - - Request the 2x0h region (port base) in any case if we are using this card. - - NOTE: the "aedsp16 (base)" string with which we are requesting the aedsp16 - port base region (see code) does not mean necessarily that we are emulating - sbpro. Even if this region is the sbpro I/O ports region, we use this - region to access the control registers of the card, and if emulating - sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro - registers are not used, in no way, to emulate an sbpro: they are - used only for configuration purposes. - - Started Fri Mar 17 16:13:18 MET 1995 - - v0.1 (ALPHA, was a user-level program called AudioExcelDSP16.c) - - Initial code. - v0.2 (ALPHA) - - Cleanups. - - Integrated with Linux voxware v 2.90-2 kernel sound driver. - - SoundBlaster Pro mode configuration. - - Microsoft Sound System mode configuration. - - MPU-401 mode configuration. - v0.3 (ALPHA) - - Cleanups. - - Rearranged the code to let aedsp16_init_board be more general. - - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h - inclusion too. We rely on os.h - - Used the to get a variable - len string (we are not sure about the len of Copyright string). - This works with any SB and compatible. - - Added the code to request_region at device init (should go in - the main body of voxware). - v0.4 (BETA) - - Better configure.c patch for aedsp16 configuration (better - logic of inclusion of AEDSP16 support) - - Modified the conditional compilation to better support more than - one sound card of the emulated type (read the NOTES above) - - Moved the sb init routine from the attach to the very first - probe in sb_card.c - - Rearrangements and cleanups - - Wiped out some unnecessary code and variables: this is kernel - code so it is better save some TEXT and DATA - - Fixed the request_region code. We must allocate the aedsp16 (sbpro) - I/O ports in any case because they are used to access the DSP - configuration registers and we can not allow anyone to get them. - v0.5 - - cleanups on comments - - prep for diffs against v3.0-proto-950402 - v0.6 - - removed the request_region()s when compiling the MODULE sound.o - because we are not allowed (by the actual voxware structure) to - release_region() - v0.7 (pre ALPHA, not distributed) - - started porting this module to kernel 1.3.84. Dummy probe/attach - routines. - v0.8 (ALPHA) - - attached all the init routines. - v0.9 (BETA) - - Integrated with linux-pre2.0.7 - - Integrated with configuration scripts. - - Cleaned up and beautyfied the code. - v0.9.9 (BETA) - - Thanks to Piercarlo Grandi: corrected the conditonal compilation code. - Now only the code configured is compiled in, with some memory saving. - v0.9.10 - - Integration into the sound/lowlevel/ section of the sound driver. - - Re-organized the code. - v0.9.11 (not distributed) - - Rewritten the init interface-routines to initialize the AEDSP16 in - one shot. - - More cosmetics. - - SC-6600 support. - - More soft/hard configuration. - v0.9.12 - - Refined the v0.9.11 code with conditional compilation to distinguish - between SC-6000 and SC-6600 code. - v1.0.0 - - Prep for merging with OSS Lite and Linux kernel 2.1.13 - - Corrected a bug in request/check/release region calls (thanks to the - new kernel exception handling). - v1.1 - - Revamped for integration with new modularized sound drivers: to enhance - the flexibility of modular version, I have removed all the conditional - compilation for SBPRO, MPU and MSS code. Now it is all managed with - the ae_config structure. - v1.2 - - Module informations added. - - Removed aedsp16_delay_10msec(), now using mdelay(10) - - All data and funcs moved to .*.init section. - v1.3 - Arnaldo Carvalho de Melo - 2000/09/27 - - got rid of check_region - - Known Problems: - - Audio Excel DSP 16 III don't work with this driver. - - Credits: - Many thanks to Gerald Britton . He helped me a - lot in testing the 0.9.11 and 0.9.12 versions of this driver. - - */ - - -#define VERSION "1.3" /* Version of Audio Excel DSP 16 driver */ - -#undef AEDSP16_DEBUG /* Define this to 1 to enable debug code */ -#undef AEDSP16_DEBUG_MORE /* Define this to 1 to enable more debug */ -#undef AEDSP16_INFO /* Define this to 1 to enable info code */ - -#if defined(AEDSP16_DEBUG) -# define DBG(x) printk x -# if defined(AEDSP16_DEBUG_MORE) -# define DBG1(x) printk x -# else -# define DBG1(x) -# endif -#else -# define DBG(x) -# define DBG1(x) -#endif - -/* - * Misc definitions - */ -#define TRUE 1 -#define FALSE 0 - -/* - * Region Size for request/check/release region. - */ -#define IOBASE_REGION_SIZE 0x10 - -/* - * Hardware related defaults - */ -#define DEF_AEDSP16_IOB 0x220 /* 0x220(default) 0x240 */ -#define DEF_AEDSP16_IRQ 7 /* 5 7(default) 9 10 11 */ -#define DEF_AEDSP16_MRQ 0 /* 5 7 9 10 0(default), 0 means disable */ -#define DEF_AEDSP16_DMA 1 /* 0 1(default) 3 */ - -/* - * Commands of AEDSP16's DSP (SBPRO+special). - * Some of them are COMMAND_xx, in the future they may change. - */ -#define WRITE_MDIRQ_CFG 0x50 /* Set M&I&DRQ mask (the real config) */ -#define COMMAND_52 0x52 /* */ -#define READ_HARD_CFG 0x58 /* Read Hardware Config (I/O base etc) */ -#define COMMAND_5C 0x5c /* */ -#define COMMAND_60 0x60 /* */ -#define COMMAND_66 0x66 /* */ -#define COMMAND_6C 0x6c /* */ -#define COMMAND_6E 0x6e /* */ -#define COMMAND_88 0x88 /* */ -#define DSP_INIT_MSS 0x8c /* Enable Microsoft Sound System mode */ -#define COMMAND_C5 0xc5 /* */ -#define GET_DSP_VERSION 0xe1 /* Get DSP Version */ -#define GET_DSP_COPYRIGHT 0xe3 /* Get DSP Copyright */ - -/* - * Offsets of AEDSP16 DSP I/O ports. The offset is added to base I/O port - * to have the actual I/O port. - * Register permissions are: - * (wo) == Write Only - * (ro) == Read Only - * (w-) == Write - * (r-) == Read - */ -#define DSP_RESET 0x06 /* offset of DSP RESET (wo) */ -#define DSP_READ 0x0a /* offset of DSP READ (ro) */ -#define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */ -#define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */ -#define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */ -#define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */ - - -#define RETRY 10 /* Various retry values on I/O opera- */ -#define STATUSRETRY 1000 /* tions. Sometimes we have to */ -#define HARDRETRY 500000 /* wait for previous cmd to complete */ - -/* - * Size of character arrays that store name and version of sound card - */ -#define CARDNAMELEN 15 /* Size of the card's name in chars */ -#define CARDVERLEN 10 /* Size of the card's version in chars */ -#define CARDVERDIGITS 2 /* Number of digits in the version */ - -#if defined(CONFIG_SC6600) -/* - * Bitmapped flags of hard configuration - */ -/* - * Decode macros (xl == low byte, xh = high byte) - */ -#define IOBASE(xl) ((xl & 0x01)?0x240:0x220) -#define JOY(xl) (xl & 0x02) -#define MPUADDR(xl) ( \ - (xl & 0x0C)?0x330: \ - (xl & 0x08)?0x320: \ - (xl & 0x04)?0x310: \ - 0x300) -#define WSSADDR(xl) ((xl & 0x10)?0xE80:0x530) -#define CDROM(xh) (xh & 0x20) -#define CDROMADDR(xh) (((xh & 0x1F) << 4) + 0x200) -/* - * Encode macros - */ -#define BLDIOBASE(xl, val) { \ - xl &= ~0x01; \ - if (val == 0x240) \ - xl |= 0x01; \ - } -#define BLDJOY(xl, val) { \ - xl &= ~0x02; \ - if (val == 1) \ - xl |= 0x02; \ - } -#define BLDMPUADDR(xl, val) { \ - xl &= ~0x0C; \ - switch (val) { \ - case 0x330: \ - xl |= 0x0C; \ - break; \ - case 0x320: \ - xl |= 0x08; \ - break; \ - case 0x310: \ - xl |= 0x04; \ - break; \ - case 0x300: \ - xl |= 0x00; \ - break; \ - default: \ - xl |= 0x00; \ - break; \ - } \ - } -#define BLDWSSADDR(xl, val) { \ - xl &= ~0x10; \ - if (val == 0xE80) \ - xl |= 0x10; \ - } -#define BLDCDROM(xh, val) { \ - xh &= ~0x20; \ - if (val == 1) \ - xh |= 0x20; \ - } -#define BLDCDROMADDR(xh, val) { \ - int tmp = val; \ - tmp -= 0x200; \ - tmp >>= 4; \ - tmp &= 0x1F; \ - xh |= tmp; \ - xh &= 0x7F; \ - xh |= 0x40; \ - } -#endif /* CONFIG_SC6600 */ - -/* - * Bit mapped flags for calling aedsp16_init_board(), and saving the current - * emulation mode. - */ -#define INIT_NONE (0 ) -#define INIT_SBPRO (1<<0) -#define INIT_MSS (1<<1) -#define INIT_MPU401 (1<<2) - -static int soft_cfg __initdata = 0; /* bitmapped config */ -static int soft_cfg_mss __initdata = 0; /* bitmapped mss config */ -static int ver[CARDVERDIGITS] __initdata = {0, 0}; /* DSP Ver: - hi->ver[0] lo->ver[1] */ - -#if defined(CONFIG_SC6600) -static int hard_cfg[2] /* lo<-hard_cfg[0] hi<-hard_cfg[1] */ - __initdata = { 0, 0}; -#endif /* CONFIG_SC6600 */ - -#if defined(CONFIG_SC6600) -/* Decoded hard configuration */ -struct d_hcfg { - int iobase; - int joystick; - int mpubase; - int wssbase; - int cdrom; - int cdrombase; -}; - -static struct d_hcfg decoded_hcfg __initdata = {0, }; - -#endif /* CONFIG_SC6600 */ - -/* orVals contain the values to be or'ed */ -struct orVals { - int val; /* irq|mirq|dma */ - int or; /* soft_cfg |= TheStruct.or */ -}; - -/* aedsp16_info contain the audio card configuration */ -struct aedsp16_info { - int base_io; /* base I/O address for accessing card */ - int irq; /* irq value for DSP I/O */ - int mpu_irq; /* irq for mpu401 interface I/O */ - int dma; /* dma value for DSP I/O */ - int mss_base; /* base I/O for Microsoft Sound System */ - int mpu_base; /* base I/O for MPU-401 emulation */ - int init; /* Initialization status of the card */ -}; - -/* - * Magic values that the DSP will eat when configuring irq/mirq/dma - */ -/* DSP IRQ conversion array */ -static struct orVals orIRQ[] __initdata = { - {0x05, 0x28}, - {0x07, 0x08}, - {0x09, 0x10}, - {0x0a, 0x18}, - {0x0b, 0x20}, - {0x00, 0x00} -}; - -/* MPU-401 IRQ conversion array */ -static struct orVals orMIRQ[] __initdata = { - {0x05, 0x04}, - {0x07, 0x44}, - {0x09, 0x84}, - {0x0a, 0xc4}, - {0x00, 0x00} -}; - -/* DMA Channels conversion array */ -static struct orVals orDMA[] __initdata = { - {0x00, 0x01}, - {0x01, 0x02}, - {0x03, 0x03}, - {0x00, 0x00} -}; - -static struct aedsp16_info ae_config = { - DEF_AEDSP16_IOB, - DEF_AEDSP16_IRQ, - DEF_AEDSP16_MRQ, - DEF_AEDSP16_DMA, - -1, - -1, - INIT_NONE -}; - -/* - * Buffers to store audio card informations - */ -static char DSPCopyright[CARDNAMELEN + 1] __initdata = {0, }; -static char DSPVersion[CARDVERLEN + 1] __initdata = {0, }; - -static int __init aedsp16_wait_data(int port) -{ - int loop = STATUSRETRY; - unsigned char ret = 0; - - DBG1(("aedsp16_wait_data (0x%x): ", port)); - - do { - ret = inb(port + DSP_DATAVAIL); - /* - * Wait for data available (bit 7 of ret == 1) - */ - } while (!(ret & 0x80) && loop--); - - if (ret & 0x80) { - DBG1(("success.\n")); - return TRUE; - } - - DBG1(("failure.\n")); - return FALSE; -} - -static int __init aedsp16_read(int port) -{ - int inbyte; - - DBG((" Read DSP Byte (0x%x): ", port)); - - if (aedsp16_wait_data(port) == FALSE) { - DBG(("failure.\n")); - return -1; - } - - inbyte = inb(port + DSP_READ); - - DBG(("read [0x%x]/{%c}.\n", inbyte, inbyte)); - - return inbyte; -} - -static int __init aedsp16_test_dsp(int port) -{ - return ((aedsp16_read(port) == 0xaa) ? TRUE : FALSE); -} - -static int __init aedsp16_dsp_reset(int port) -{ - /* - * Reset DSP - */ - - DBG(("Reset DSP:\n")); - - outb(1, (port + DSP_RESET)); - udelay(10); - outb(0, (port + DSP_RESET)); - udelay(10); - udelay(10); - if (aedsp16_test_dsp(port) == TRUE) { - DBG(("success.\n")); - return TRUE; - } else - DBG(("failure.\n")); - return FALSE; -} - -static int __init aedsp16_write(int port, int cmd) -{ - unsigned char ret; - int loop = HARDRETRY; - - DBG((" Write DSP Byte (0x%x) [0x%x]: ", port, cmd)); - - do { - ret = inb(port + DSP_STATUS); - /* - * DSP ready to receive data if bit 7 of ret == 0 - */ - if (!(ret & 0x80)) { - outb(cmd, port + DSP_COMMAND); - DBG(("success.\n")); - return 0; - } - } while (loop--); - - DBG(("timeout.\n")); - printk("[AEDSP16] DSP Command (0x%x) timeout.\n", cmd); - - return -1; -} - -#if defined(CONFIG_SC6600) - -#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG) -void __init aedsp16_pinfo(void) { - DBG(("\n Base address: %x\n", decoded_hcfg.iobase)); - DBG((" Joystick : %s present\n", decoded_hcfg.joystick?"":" not")); - DBG((" WSS addr : %x\n", decoded_hcfg.wssbase)); - DBG((" MPU-401 addr: %x\n", decoded_hcfg.mpubase)); - DBG((" CDROM : %s present\n", (decoded_hcfg.cdrom!=4)?"":" not")); - DBG((" CDROMADDR : %x\n\n", decoded_hcfg.cdrombase)); -} -#endif - -static void __init aedsp16_hard_decode(void) { - - DBG((" aedsp16_hard_decode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1])); - -/* - * Decode Cfg Bytes. - */ - decoded_hcfg.iobase = IOBASE(hard_cfg[0]); - decoded_hcfg.joystick = JOY(hard_cfg[0]); - decoded_hcfg.wssbase = WSSADDR(hard_cfg[0]); - decoded_hcfg.mpubase = MPUADDR(hard_cfg[0]); - decoded_hcfg.cdrom = CDROM(hard_cfg[1]); - decoded_hcfg.cdrombase = CDROMADDR(hard_cfg[1]); - -#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG) - printk(" Original sound card configuration:\n"); - aedsp16_pinfo(); -#endif - -/* - * Now set up the real kernel configuration. - */ - decoded_hcfg.iobase = ae_config.base_io; - decoded_hcfg.wssbase = ae_config.mss_base; - decoded_hcfg.mpubase = ae_config.mpu_base; - -#if defined(CONFIG_SC6600_JOY) - decoded_hcfg.joystick = CONFIG_SC6600_JOY; /* Enable */ -#endif -#if defined(CONFIG_SC6600_CDROM) - decoded_hcfg.cdrom = CONFIG_SC6600_CDROM; /* 4:N-3:I-2:G-1:P-0:S */ -#endif -#if defined(CONFIG_SC6600_CDROMBASE) - decoded_hcfg.cdrombase = CONFIG_SC6600_CDROMBASE; /* 0 Disable */ -#endif - -#if defined(AEDSP16_DEBUG) - DBG((" New Values:\n")); - aedsp16_pinfo(); -#endif - - DBG(("success.\n")); -} - -static void __init aedsp16_hard_encode(void) { - - DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1])); - - hard_cfg[0] = 0; - hard_cfg[1] = 0; - - hard_cfg[0] |= 0x20; - - BLDIOBASE (hard_cfg[0], decoded_hcfg.iobase); - BLDWSSADDR(hard_cfg[0], decoded_hcfg.wssbase); - BLDMPUADDR(hard_cfg[0], decoded_hcfg.mpubase); - BLDJOY(hard_cfg[0], decoded_hcfg.joystick); - BLDCDROM(hard_cfg[1], decoded_hcfg.cdrom); - BLDCDROMADDR(hard_cfg[1], decoded_hcfg.cdrombase); - -#if defined(AEDSP16_DEBUG) - aedsp16_pinfo(); -#endif - - DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1])); - DBG(("success.\n")); - -} - -static int __init aedsp16_hard_write(int port) { - - DBG(("aedsp16_hard_write:\n")); - - if (aedsp16_write(port, COMMAND_6C)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6C); - DBG(("failure.\n")); - return FALSE; - } - if (aedsp16_write(port, COMMAND_5C)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C); - DBG(("failure.\n")); - return FALSE; - } - if (aedsp16_write(port, hard_cfg[0])) { - printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[0]); - DBG(("failure.\n")); - return FALSE; - } - if (aedsp16_write(port, hard_cfg[1])) { - printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[1]); - DBG(("failure.\n")); - return FALSE; - } - if (aedsp16_write(port, COMMAND_C5)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_C5); - DBG(("failure.\n")); - return FALSE; - } - - DBG(("success.\n")); - - return TRUE; -} - -static int __init aedsp16_hard_read(int port) { - - DBG(("aedsp16_hard_read:\n")); - - if (aedsp16_write(port, READ_HARD_CFG)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", READ_HARD_CFG); - DBG(("failure.\n")); - return FALSE; - } - - if ((hard_cfg[0] = aedsp16_read(port)) == -1) { - printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n", - READ_HARD_CFG); - DBG(("failure.\n")); - return FALSE; - } - if ((hard_cfg[1] = aedsp16_read(port)) == -1) { - printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n", - READ_HARD_CFG); - DBG(("failure.\n")); - return FALSE; - } - if (aedsp16_read(port) == -1) { - printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n", - READ_HARD_CFG); - DBG(("failure.\n")); - return FALSE; - } - - DBG(("success.\n")); - - return TRUE; -} - -static int __init aedsp16_ext_cfg_write(int port) { - - int extcfg, val; - - if (aedsp16_write(port, COMMAND_66)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_66); - return FALSE; - } - - extcfg = 7; - if (decoded_hcfg.cdrom != 2) - extcfg = 0x0F; - if ((decoded_hcfg.cdrom == 4) || - (decoded_hcfg.cdrom == 3)) - extcfg &= ~2; - if (decoded_hcfg.cdrombase == 0) - extcfg &= ~2; - if (decoded_hcfg.mpubase == 0) - extcfg &= ~1; - - if (aedsp16_write(port, extcfg)) { - printk("[AEDSP16] Write extcfg: failed!\n"); - return FALSE; - } - if (aedsp16_write(port, 0)) { - printk("[AEDSP16] Write extcfg: failed!\n"); - return FALSE; - } - if (decoded_hcfg.cdrom == 3) { - if (aedsp16_write(port, COMMAND_52)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52); - return FALSE; - } - if ((val = aedsp16_read(port)) == -1) { - printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n" - , COMMAND_52); - return FALSE; - } - val &= 0x7F; - if (aedsp16_write(port, COMMAND_60)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60); - return FALSE; - } - if (aedsp16_write(port, val)) { - printk("[AEDSP16] Write val: failed!\n"); - return FALSE; - } - } - - return TRUE; -} - -#endif /* CONFIG_SC6600 */ - -static int __init aedsp16_cfg_write(int port) { - if (aedsp16_write(port, WRITE_MDIRQ_CFG)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); - return FALSE; - } - if (aedsp16_write(port, soft_cfg)) { - printk("[AEDSP16] Initialization of (M)IRQ and DMA: failed!\n"); - return FALSE; - } - return TRUE; -} - -static int __init aedsp16_init_mss(int port) -{ - DBG(("aedsp16_init_mss:\n")); - - mdelay(10); - - if (aedsp16_write(port, DSP_INIT_MSS)) { - printk("[AEDSP16] aedsp16_init_mss [0x%x]: failed!\n", - DSP_INIT_MSS); - DBG(("failure.\n")); - return FALSE; - } - - mdelay(10); - - if (aedsp16_cfg_write(port) == FALSE) - return FALSE; - - outb(soft_cfg_mss, ae_config.mss_base); - - DBG(("success.\n")); - - return TRUE; -} - -static int __init aedsp16_setup_board(int port) { - int loop = RETRY; - -#if defined(CONFIG_SC6600) - int val = 0; - - if (aedsp16_hard_read(port) == FALSE) { - printk("[AEDSP16] aedsp16_hard_read: failed!\n"); - return FALSE; - } - - if (aedsp16_write(port, COMMAND_52)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52); - return FALSE; - } - - if ((val = aedsp16_read(port)) == -1) { - printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n", - COMMAND_52); - return FALSE; - } -#endif - - do { - if (aedsp16_write(port, COMMAND_88)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_88); - return FALSE; - } - mdelay(10); - } while ((aedsp16_wait_data(port) == FALSE) && loop--); - - if (aedsp16_read(port) == -1) { - printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n", - COMMAND_88); - return FALSE; - } - -#if !defined(CONFIG_SC6600) - if (aedsp16_write(port, COMMAND_5C)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C); - return FALSE; - } -#endif - - if (aedsp16_cfg_write(port) == FALSE) - return FALSE; - -#if defined(CONFIG_SC6600) - if (aedsp16_write(port, COMMAND_60)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60); - return FALSE; - } - if (aedsp16_write(port, val)) { - printk("[AEDSP16] DATA 0x%x: failed!\n", val); - return FALSE; - } - if (aedsp16_write(port, COMMAND_6E)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6E); - return FALSE; - } - if (aedsp16_write(port, ver[0])) { - printk("[AEDSP16] DATA 0x%x: failed!\n", ver[0]); - return FALSE; - } - if (aedsp16_write(port, ver[1])) { - printk("[AEDSP16] DATA 0x%x: failed!\n", ver[1]); - return FALSE; - } - - if (aedsp16_hard_write(port) == FALSE) { - printk("[AEDSP16] aedsp16_hard_write: failed!\n"); - return FALSE; - } - - if (aedsp16_write(port, COMMAND_5C)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C); - return FALSE; - } - -#if defined(THIS_IS_A_THING_I_HAVE_NOT_TESTED_YET) - if (aedsp16_cfg_write(port) == FALSE) - return FALSE; -#endif - -#endif - - return TRUE; -} - -static int __init aedsp16_stdcfg(int port) { - if (aedsp16_write(port, WRITE_MDIRQ_CFG)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); - return FALSE; - } - /* - * 0x0A == (IRQ 7, DMA 1, MIRQ 0) - */ - if (aedsp16_write(port, 0x0A)) { - printk("[AEDSP16] aedsp16_stdcfg: failed!\n"); - return FALSE; - } - return TRUE; -} - -static int __init aedsp16_dsp_version(int port) -{ - int len = 0; - int ret; - - DBG(("Get DSP Version:\n")); - - if (aedsp16_write(ae_config.base_io, GET_DSP_VERSION)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_VERSION); - DBG(("failed.\n")); - return FALSE; - } - - do { - if ((ret = aedsp16_read(port)) == -1) { - DBG(("failed.\n")); - return FALSE; - } - /* - * We already know how many int are stored (2), so we know when the - * string is finished. - */ - ver[len++] = ret; - } while (len < CARDVERDIGITS); - sprintf(DSPVersion, "%d.%d", ver[0], ver[1]); - - DBG(("success.\n")); - - return TRUE; -} - -static int __init aedsp16_dsp_copyright(int port) -{ - int len = 0; - int ret; - - DBG(("Get DSP Copyright:\n")); - - if (aedsp16_write(ae_config.base_io, GET_DSP_COPYRIGHT)) { - printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_COPYRIGHT); - DBG(("failed.\n")); - return FALSE; - } - - do { - if ((ret = aedsp16_read(port)) == -1) { - /* - * If no more data available, return to the caller, no error if len>0. - * We have no other way to know when the string is finished. - */ - if (len) - break; - else { - DBG(("failed.\n")); - return FALSE; - } - } - - DSPCopyright[len++] = ret; - - } while (len < CARDNAMELEN); - - DBG(("success.\n")); - - return TRUE; -} - -static void __init aedsp16_init_tables(void) -{ - int i = 0; - - memset(DSPCopyright, 0, CARDNAMELEN + 1); - memset(DSPVersion, 0, CARDVERLEN + 1); - - for (i = 0; orIRQ[i].or; i++) - if (orIRQ[i].val == ae_config.irq) { - soft_cfg |= orIRQ[i].or; - soft_cfg_mss |= orIRQ[i].or; - } - - for (i = 0; orMIRQ[i].or; i++) - if (orMIRQ[i].or == ae_config.mpu_irq) - soft_cfg |= orMIRQ[i].or; - - for (i = 0; orDMA[i].or; i++) - if (orDMA[i].val == ae_config.dma) { - soft_cfg |= orDMA[i].or; - soft_cfg_mss |= orDMA[i].or; - } -} - -static int __init aedsp16_init_board(void) -{ - aedsp16_init_tables(); - - if (aedsp16_dsp_reset(ae_config.base_io) == FALSE) { - printk("[AEDSP16] aedsp16_dsp_reset: failed!\n"); - return FALSE; - } - if (aedsp16_dsp_copyright(ae_config.base_io) == FALSE) { - printk("[AEDSP16] aedsp16_dsp_copyright: failed!\n"); - return FALSE; - } - - /* - * My AEDSP16 card return SC-6000 in DSPCopyright, so - * if we have something different, we have to be warned. - */ - if (strcmp("SC-6000", DSPCopyright)) - printk("[AEDSP16] Warning: non SC-6000 audio card!\n"); - - if (aedsp16_dsp_version(ae_config.base_io) == FALSE) { - printk("[AEDSP16] aedsp16_dsp_version: failed!\n"); - return FALSE; - } - - if (aedsp16_stdcfg(ae_config.base_io) == FALSE) { - printk("[AEDSP16] aedsp16_stdcfg: failed!\n"); - return FALSE; - } - -#if defined(CONFIG_SC6600) - if (aedsp16_hard_read(ae_config.base_io) == FALSE) { - printk("[AEDSP16] aedsp16_hard_read: failed!\n"); - return FALSE; - } - - aedsp16_hard_decode(); - - aedsp16_hard_encode(); - - if (aedsp16_hard_write(ae_config.base_io) == FALSE) { - printk("[AEDSP16] aedsp16_hard_write: failed!\n"); - return FALSE; - } - - if (aedsp16_ext_cfg_write(ae_config.base_io) == FALSE) { - printk("[AEDSP16] aedsp16_ext_cfg_write: failed!\n"); - return FALSE; - } -#endif /* CONFIG_SC6600 */ - - if (aedsp16_setup_board(ae_config.base_io) == FALSE) { - printk("[AEDSP16] aedsp16_setup_board: failed!\n"); - return FALSE; - } - - if (ae_config.mss_base != -1) { - if (ae_config.init & INIT_MSS) { - if (aedsp16_init_mss(ae_config.base_io) == FALSE) { - printk("[AEDSP16] Can not initialize" - "Microsoft Sound System mode.\n"); - return FALSE; - } - } - } - -#if !defined(MODULE) || defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG) - - printk("Audio Excel DSP 16 init v%s (%s %s) [", - VERSION, DSPCopyright, - DSPVersion); - - if (ae_config.mpu_base != -1) { - if (ae_config.init & INIT_MPU401) { - printk("MPU401"); - if ((ae_config.init & INIT_MSS) || - (ae_config.init & INIT_SBPRO)) - printk(" "); - } - } - - if (ae_config.mss_base == -1) { - if (ae_config.init & INIT_SBPRO) { - printk("SBPro"); - if (ae_config.init & INIT_MSS) - printk(" "); - } - } - - if (ae_config.mss_base != -1) - if (ae_config.init & INIT_MSS) - printk("MSS"); - - printk("]\n"); -#endif /* MODULE || AEDSP16_INFO || AEDSP16_DEBUG */ - - mdelay(10); - - return TRUE; -} - -static int __init init_aedsp16_sb(void) -{ - DBG(("init_aedsp16_sb: ")); - -/* - * If the card is already init'ed MSS, we can not init it to SBPRO too - * because the board can not emulate simultaneously MSS and SBPRO. - */ - if (ae_config.init & INIT_MSS) - return FALSE; - if (ae_config.init & INIT_SBPRO) - return FALSE; - - ae_config.init |= INIT_SBPRO; - - DBG(("done.\n")); - - return TRUE; -} - -static void uninit_aedsp16_sb(void) -{ - DBG(("uninit_aedsp16_sb: ")); - - ae_config.init &= ~INIT_SBPRO; - - DBG(("done.\n")); -} - -static int __init init_aedsp16_mss(void) -{ - DBG(("init_aedsp16_mss: ")); - -/* - * If the card is already init'ed SBPRO, we can not init it to MSS too - * because the board can not emulate simultaneously MSS and SBPRO. - */ - if (ae_config.init & INIT_SBPRO) - return FALSE; - if (ae_config.init & INIT_MSS) - return FALSE; -/* - * We must allocate the CONFIG_AEDSP16_BASE region too because these are the - * I/O ports to access card's control registers. - */ - if (!(ae_config.init & INIT_MPU401)) { - if (!request_region(ae_config.base_io, IOBASE_REGION_SIZE, - "aedsp16 (base)")) { - printk( - "AEDSP16 BASE I/O port region is already in use.\n"); - return FALSE; - } - } - - ae_config.init |= INIT_MSS; - - DBG(("done.\n")); - - return TRUE; -} - -static void uninit_aedsp16_mss(void) -{ - DBG(("uninit_aedsp16_mss: ")); - - if ((!(ae_config.init & INIT_MPU401)) && - (ae_config.init & INIT_MSS)) { - release_region(ae_config.base_io, IOBASE_REGION_SIZE); - DBG(("AEDSP16 base region released.\n")); - } - - ae_config.init &= ~INIT_MSS; - DBG(("done.\n")); -} - -static int __init init_aedsp16_mpu(void) -{ - DBG(("init_aedsp16_mpu: ")); - - if (ae_config.init & INIT_MPU401) - return FALSE; - -/* - * We must request the CONFIG_AEDSP16_BASE region too because these are the I/O - * ports to access card's control registers. - */ - if (!(ae_config.init & (INIT_MSS | INIT_SBPRO))) { - if (!request_region(ae_config.base_io, IOBASE_REGION_SIZE, - "aedsp16 (base)")) { - printk( - "AEDSP16 BASE I/O port region is already in use.\n"); - return FALSE; - } - } - - ae_config.init |= INIT_MPU401; - - DBG(("done.\n")); - - return TRUE; -} - -static void uninit_aedsp16_mpu(void) -{ - DBG(("uninit_aedsp16_mpu: ")); - - if ((!(ae_config.init & (INIT_MSS | INIT_SBPRO))) && - (ae_config.init & INIT_MPU401)) { - release_region(ae_config.base_io, IOBASE_REGION_SIZE); - DBG(("AEDSP16 base region released.\n")); - } - - ae_config.init &= ~INIT_MPU401; - - DBG(("done.\n")); -} - -static int __init init_aedsp16(void) -{ - int initialized = FALSE; - - DBG(("Initializing BASE[0x%x] IRQ[%d] DMA[%d] MIRQ[%d]\n", - ae_config.base_io,ae_config.irq,ae_config.dma,ae_config.mpu_irq)); - - if (ae_config.mss_base == -1) { - if (init_aedsp16_sb() == FALSE) { - uninit_aedsp16_sb(); - } else { - initialized = TRUE; - } - } - - if (ae_config.mpu_base != -1) { - if (init_aedsp16_mpu() == FALSE) { - uninit_aedsp16_mpu(); - } else { - initialized = TRUE; - } - } - -/* - * In the sequence of init routines, the MSS init MUST be the last! - * This because of the special register programming the MSS mode needs. - * A board reset would disable the MSS mode restoring the default SBPRO - * mode. - */ - if (ae_config.mss_base != -1) { - if (init_aedsp16_mss() == FALSE) { - uninit_aedsp16_mss(); - } else { - initialized = TRUE; - } - } - - if (initialized) - initialized = aedsp16_init_board(); - return initialized; -} - -static void __exit uninit_aedsp16(void) -{ - if (ae_config.mss_base != -1) - uninit_aedsp16_mss(); - else - uninit_aedsp16_sb(); - if (ae_config.mpu_base != -1) - uninit_aedsp16_mpu(); -} - -static int __initdata io = -1; -static int __initdata irq = -1; -static int __initdata dma = -1; -static int __initdata mpu_irq = -1; -static int __initdata mss_base = -1; -static int __initdata mpu_base = -1; - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)"); -module_param(irq, int, 0); -MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)"); -module_param(dma, int, 0); -MODULE_PARM_DESC(dma, "dma line (0 1 3)"); -module_param(mpu_irq, int, 0); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)"); -module_param(mss_base, int, 0); -MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)"); -module_param(mpu_base, int, 0); -MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)"); -MODULE_AUTHOR("Riccardo Facchetti "); -MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION); -MODULE_LICENSE("GPL"); - -static int __init do_init_aedsp16(void) { - printk("Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98\n"); - if (io == -1 || dma == -1 || irq == -1) { - printk(KERN_INFO "aedsp16: I/O, IRQ and DMA are mandatory\n"); - return -EINVAL; - } - - ae_config.base_io = io; - ae_config.irq = irq; - ae_config.dma = dma; - - ae_config.mss_base = mss_base; - ae_config.mpu_base = mpu_base; - ae_config.mpu_irq = mpu_irq; - - if (init_aedsp16() == FALSE) { - printk(KERN_ERR "aedsp16: initialization failed\n"); - /* - * XXX - * What error should we return here ? - */ - return -EINVAL; - } - return 0; -} - -static void __exit cleanup_aedsp16(void) { - uninit_aedsp16(); -} - -module_init(do_init_aedsp16); -module_exit(cleanup_aedsp16); - -#ifndef MODULE -static int __init setup_aedsp16(char *str) -{ - /* io, irq, dma, mss_io, mpu_io, mpu_irq */ - int ints[7]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - irq = ints[2]; - dma = ints[3]; - mss_base = ints[4]; - mpu_base = ints[5]; - mpu_irq = ints[6]; - return 1; -} - -__setup("aedsp16=", setup_aedsp16); -#endif diff --git a/ANDROID_3.4.5/sound/oss/audio.c b/ANDROID_3.4.5/sound/oss/audio.c deleted file mode 100644 index 4b958b1c..00000000 --- a/ANDROID_3.4.5/sound/oss/audio.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - * sound/oss/audio.c - * - * Device file manager for /dev/audio - */ - -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * Thomas Sailer : moved several static variables into struct audio_operations - * (which is grossly misnamed btw.) because they have the same - * lifetime as the rest in there and dynamic allocation saves - * 12k or so - * Thomas Sailer : use more logical O_NONBLOCK semantics - * Daniel Rodriksson: reworked the use of the device specific copy_user - * still generic - * Horst von Brand: Add missing #include - * Chris Rankin : Update the module-usage counter for the coprocessor, - * and decrement the counters again if we cannot open - * the audio device. - */ - -#include -#include -#include - -#include "sound_config.h" -#include "ulaw.h" -#include "coproc.h" - -#define NEUTRAL8 0x80 -#define NEUTRAL16 0x00 - - -static int dma_ioctl(int dev, unsigned int cmd, void __user *arg); - -static int set_format(int dev, int fmt) -{ - if (fmt != AFMT_QUERY) - { - audio_devs[dev]->local_conversion = 0; - - if (!(audio_devs[dev]->format_mask & fmt)) /* Not supported */ - { - if (fmt == AFMT_MU_LAW) - { - fmt = AFMT_U8; - audio_devs[dev]->local_conversion = CNV_MU_LAW; - } - else - fmt = AFMT_U8; /* This is always supported */ - } - audio_devs[dev]->audio_format = audio_devs[dev]->d->set_bits(dev, fmt); - audio_devs[dev]->local_format = fmt; - } - else - return audio_devs[dev]->local_format; - - if (audio_devs[dev]->local_conversion) - return audio_devs[dev]->local_conversion; - else - return audio_devs[dev]->local_format; -} - -int audio_open(int dev, struct file *file) -{ - int ret; - int bits; - int dev_type = dev & 0x0f; - int mode = translate_mode(file); - const struct audio_driver *driver; - const struct coproc_operations *coprocessor; - - dev = dev >> 4; - - if (dev_type == SND_DEV_DSP16) - bits = 16; - else - bits = 8; - - if (dev < 0 || dev >= num_audiodevs) - return -ENXIO; - - driver = audio_devs[dev]->d; - - if (!try_module_get(driver->owner)) - return -ENODEV; - - if ((ret = DMAbuf_open(dev, mode)) < 0) - goto error_1; - - if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) { - if (!try_module_get(coprocessor->owner)) - goto error_2; - - if ((ret = coprocessor->open(coprocessor->devc, COPR_PCM)) < 0) { - printk(KERN_WARNING "Sound: Can't access coprocessor device\n"); - goto error_3; - } - } - - audio_devs[dev]->local_conversion = 0; - - if (dev_type == SND_DEV_AUDIO) - set_format(dev, AFMT_MU_LAW); - else - set_format(dev, bits); - - audio_devs[dev]->audio_mode = AM_NONE; - - return 0; - - /* - * Clean-up stack: this is what needs (un)doing if - * we can't open the audio device ... - */ - error_3: - module_put(coprocessor->owner); - - error_2: - DMAbuf_release(dev, mode); - - error_1: - module_put(driver->owner); - - return ret; -} - -static void sync_output(int dev) -{ - int p, i; - int l; - struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - - if (dmap->fragment_size <= 0) - return; - dmap->flags |= DMA_POST; - - /* Align the write pointer with fragment boundaries */ - - if ((l = dmap->user_counter % dmap->fragment_size) > 0) - { - int len; - unsigned long offs = dmap->user_counter % dmap->bytes_in_use; - - len = dmap->fragment_size - l; - memset(dmap->raw_buf + offs, dmap->neutral_byte, len); - DMAbuf_move_wrpointer(dev, len); - } - - /* - * Clean all unused buffer fragments. - */ - - p = dmap->qtail; - dmap->flags |= DMA_POST; - - for (i = dmap->qlen + 1; i < dmap->nbufs; i++) - { - p = (p + 1) % dmap->nbufs; - if (((dmap->raw_buf + p * dmap->fragment_size) + dmap->fragment_size) > - (dmap->raw_buf + dmap->buffsize)) - printk(KERN_ERR "audio: Buffer error 2\n"); - - memset(dmap->raw_buf + p * dmap->fragment_size, - dmap->neutral_byte, - dmap->fragment_size); - } - - dmap->flags |= DMA_DIRTY; -} - -void audio_release(int dev, struct file *file) -{ - const struct coproc_operations *coprocessor; - int mode = translate_mode(file); - - dev = dev >> 4; - - /* - * We do this in DMAbuf_release(). Why are we doing it - * here? Why don't we test the file mode before setting - * both flags? DMAbuf_release() does. - * ...pester...pester...pester... - */ - audio_devs[dev]->dmap_out->closing = 1; - audio_devs[dev]->dmap_in->closing = 1; - - /* - * We need to make sure we allocated the dmap_out buffer - * before we go mucking around with it in sync_output(). - */ - if (mode & OPEN_WRITE) - sync_output(dev); - - if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) { - coprocessor->close(coprocessor->devc, COPR_PCM); - module_put(coprocessor->owner); - } - DMAbuf_release(dev, mode); - - module_put(audio_devs[dev]->d->owner); -} - -static void translate_bytes(const unsigned char *table, unsigned char *buff, int n) -{ - unsigned long i; - - if (n <= 0) - return; - - for (i = 0; i < n; ++i) - buff[i] = table[buff[i]]; -} - -int audio_write(int dev, struct file *file, const char __user *buf, int count) -{ - int c, p, l, buf_size, used, returned; - int err; - char *dma_buf; - - dev = dev >> 4; - - p = 0; - c = count; - - if(count < 0) - return -EINVAL; - - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EPERM; - - if (audio_devs[dev]->flags & DMA_DUPLEX) - audio_devs[dev]->audio_mode |= AM_WRITE; - else - audio_devs[dev]->audio_mode = AM_WRITE; - - if (!count) /* Flush output */ - { - sync_output(dev); - return 0; - } - - while (c) - { - if ((err = DMAbuf_getwrbuffer(dev, &dma_buf, &buf_size, !!(file->f_flags & O_NONBLOCK))) < 0) - { - /* Handle nonblocking mode */ - if ((file->f_flags & O_NONBLOCK) && err == -EAGAIN) - return p? p : -EAGAIN; /* No more space. Return # of accepted bytes */ - return err; - } - l = c; - - if (l > buf_size) - l = buf_size; - - returned = l; - used = l; - if (!audio_devs[dev]->d->copy_user) - { - if ((dma_buf + l) > - (audio_devs[dev]->dmap_out->raw_buf + audio_devs[dev]->dmap_out->buffsize)) - { - printk(KERN_ERR "audio: Buffer error 3 (%lx,%d), (%lx, %d)\n", (long) dma_buf, l, (long) audio_devs[dev]->dmap_out->raw_buf, (int) audio_devs[dev]->dmap_out->buffsize); - return -EDOM; - } - if (dma_buf < audio_devs[dev]->dmap_out->raw_buf) - { - printk(KERN_ERR "audio: Buffer error 13 (%lx<%lx)\n", (long) dma_buf, (long) audio_devs[dev]->dmap_out->raw_buf); - return -EDOM; - } - if(copy_from_user(dma_buf, &(buf)[p], l)) - return -EFAULT; - } - else audio_devs[dev]->d->copy_user (dev, - dma_buf, 0, - buf, p, - c, buf_size, - &used, &returned, - l); - l = returned; - - if (audio_devs[dev]->local_conversion & CNV_MU_LAW) - { - translate_bytes(ulaw_dsp, (unsigned char *) dma_buf, l); - } - c -= used; - p += used; - DMAbuf_move_wrpointer(dev, l); - - } - - return count; -} - -int audio_read(int dev, struct file *file, char __user *buf, int count) -{ - int c, p, l; - char *dmabuf; - int buf_no; - - dev = dev >> 4; - p = 0; - c = count; - - if (!(audio_devs[dev]->open_mode & OPEN_READ)) - return -EPERM; - - if ((audio_devs[dev]->audio_mode & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) - sync_output(dev); - - if (audio_devs[dev]->flags & DMA_DUPLEX) - audio_devs[dev]->audio_mode |= AM_READ; - else - audio_devs[dev]->audio_mode = AM_READ; - - while(c) - { - if ((buf_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l, !!(file->f_flags & O_NONBLOCK))) < 0) - { - /* - * Nonblocking mode handling. Return current # of bytes - */ - - if (p > 0) /* Avoid throwing away data */ - return p; /* Return it instead */ - - if ((file->f_flags & O_NONBLOCK) && buf_no == -EAGAIN) - return -EAGAIN; - - return buf_no; - } - if (l > c) - l = c; - - /* - * Insert any local processing here. - */ - - if (audio_devs[dev]->local_conversion & CNV_MU_LAW) - { - translate_bytes(dsp_ulaw, (unsigned char *) dmabuf, l); - } - - { - char *fixit = dmabuf; - - if(copy_to_user(&(buf)[p], fixit, l)) - return -EFAULT; - }; - - DMAbuf_rmchars(dev, buf_no, l); - - p += l; - c -= l; - } - - return count - c; -} - -int audio_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg) -{ - int val, count; - unsigned long flags; - struct dma_buffparms *dmap; - int __user *p = arg; - - dev = dev >> 4; - - if (_IOC_TYPE(cmd) == 'C') { - if (audio_devs[dev]->coproc) /* Coprocessor ioctl */ - return audio_devs[dev]->coproc->ioctl(audio_devs[dev]->coproc->devc, cmd, arg, 0); - /* else - printk(KERN_DEBUG"/dev/dsp%d: No coprocessor for this device\n", dev); */ - return -ENXIO; - } - else switch (cmd) - { - case SNDCTL_DSP_SYNC: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return 0; - if (audio_devs[dev]->dmap_out->fragment_size == 0) - return 0; - sync_output(dev); - DMAbuf_sync(dev); - DMAbuf_reset(dev); - return 0; - - case SNDCTL_DSP_POST: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return 0; - if (audio_devs[dev]->dmap_out->fragment_size == 0) - return 0; - audio_devs[dev]->dmap_out->flags |= DMA_POST | DMA_DIRTY; - sync_output(dev); - dma_ioctl(dev, SNDCTL_DSP_POST, NULL); - return 0; - - case SNDCTL_DSP_RESET: - audio_devs[dev]->audio_mode = AM_NONE; - DMAbuf_reset(dev); - return 0; - - case SNDCTL_DSP_GETFMTS: - val = audio_devs[dev]->format_mask | AFMT_MU_LAW; - break; - - case SNDCTL_DSP_SETFMT: - if (get_user(val, p)) - return -EFAULT; - val = set_format(dev, val); - break; - - case SNDCTL_DSP_GETISPACE: - if (!(audio_devs[dev]->open_mode & OPEN_READ)) - return 0; - if ((audio_devs[dev]->audio_mode & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) - return -EBUSY; - return dma_ioctl(dev, cmd, arg); - - case SNDCTL_DSP_GETOSPACE: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EPERM; - if ((audio_devs[dev]->audio_mode & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) - return -EBUSY; - return dma_ioctl(dev, cmd, arg); - - case SNDCTL_DSP_NONBLOCK: - spin_lock(&file->f_lock); - file->f_flags |= O_NONBLOCK; - spin_unlock(&file->f_lock); - return 0; - - case SNDCTL_DSP_GETCAPS: - val = 1 | DSP_CAP_MMAP; /* Revision level of this ioctl() */ - if (audio_devs[dev]->flags & DMA_DUPLEX && - audio_devs[dev]->open_mode == OPEN_READWRITE) - val |= DSP_CAP_DUPLEX; - if (audio_devs[dev]->coproc) - val |= DSP_CAP_COPROC; - if (audio_devs[dev]->d->local_qlen) /* Device has hidden buffers */ - val |= DSP_CAP_BATCH; - if (audio_devs[dev]->d->trigger) /* Supports SETTRIGGER */ - val |= DSP_CAP_TRIGGER; - break; - - case SOUND_PCM_WRITE_RATE: - if (get_user(val, p)) - return -EFAULT; - val = audio_devs[dev]->d->set_speed(dev, val); - break; - - case SOUND_PCM_READ_RATE: - val = audio_devs[dev]->d->set_speed(dev, 0); - break; - - case SNDCTL_DSP_STEREO: - if (get_user(val, p)) - return -EFAULT; - if (val > 1 || val < 0) - return -EINVAL; - val = audio_devs[dev]->d->set_channels(dev, val + 1) - 1; - break; - - case SOUND_PCM_WRITE_CHANNELS: - if (get_user(val, p)) - return -EFAULT; - val = audio_devs[dev]->d->set_channels(dev, val); - break; - - case SOUND_PCM_READ_CHANNELS: - val = audio_devs[dev]->d->set_channels(dev, 0); - break; - - case SOUND_PCM_READ_BITS: - val = audio_devs[dev]->d->set_bits(dev, 0); - break; - - case SNDCTL_DSP_SETDUPLEX: - if (audio_devs[dev]->open_mode != OPEN_READWRITE) - return -EPERM; - return (audio_devs[dev]->flags & DMA_DUPLEX) ? 0 : -EIO; - - case SNDCTL_DSP_PROFILE: - if (get_user(val, p)) - return -EFAULT; - if (audio_devs[dev]->open_mode & OPEN_WRITE) - audio_devs[dev]->dmap_out->applic_profile = val; - if (audio_devs[dev]->open_mode & OPEN_READ) - audio_devs[dev]->dmap_in->applic_profile = val; - return 0; - - case SNDCTL_DSP_GETODELAY: - dmap = audio_devs[dev]->dmap_out; - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EINVAL; - if (!(dmap->flags & DMA_ALLOC_DONE)) - { - val=0; - break; - } - - spin_lock_irqsave(&dmap->lock,flags); - /* Compute number of bytes that have been played */ - count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT); - if (count < dmap->fragment_size && dmap->qhead != 0) - count += dmap->bytes_in_use; /* Pointer wrap not handled yet */ - count += dmap->byte_counter; - - /* Subtract current count from the number of bytes written by app */ - count = dmap->user_counter - count; - if (count < 0) - count = 0; - spin_unlock_irqrestore(&dmap->lock,flags); - val = count; - break; - - default: - return dma_ioctl(dev, cmd, arg); - } - return put_user(val, p); -} - -void audio_init_devices(void) -{ - /* - * NOTE! This routine could be called several times during boot. - */ -} - -void reorganize_buffers(int dev, struct dma_buffparms *dmap, int recording) -{ - /* - * This routine breaks the physical device buffers to logical ones. - */ - - struct audio_operations *dsp_dev = audio_devs[dev]; - - unsigned i, n; - unsigned sr, nc, sz, bsz; - - sr = dsp_dev->d->set_speed(dev, 0); - nc = dsp_dev->d->set_channels(dev, 0); - sz = dsp_dev->d->set_bits(dev, 0); - - if (sz == 8) - dmap->neutral_byte = NEUTRAL8; - else - dmap->neutral_byte = NEUTRAL16; - - if (sr < 1 || nc < 1 || sz < 1) - { -/* printk(KERN_DEBUG "Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n", dev, sr, nc, sz);*/ - sr = DSP_DEFAULT_SPEED; - nc = 1; - sz = 8; - } - - sz = sr * nc * sz; - - sz /= 8; /* #bits -> #bytes */ - dmap->data_rate = sz; - - if (!dmap->needs_reorg) - return; - dmap->needs_reorg = 0; - - if (dmap->fragment_size == 0) - { - /* Compute the fragment size using the default algorithm */ - - /* - * Compute a buffer size for time not exceeding 1 second. - * Usually this algorithm gives a buffer size for 0.5 to 1.0 seconds - * of sound (using the current speed, sample size and #channels). - */ - - bsz = dmap->buffsize; - while (bsz > sz) - bsz /= 2; - - if (bsz == dmap->buffsize) - bsz /= 2; /* Needs at least 2 buffers */ - - /* - * Split the computed fragment to smaller parts. After 3.5a9 - * the default subdivision is 4 which should give better - * results when recording. - */ - - if (dmap->subdivision == 0) /* Not already set */ - { - dmap->subdivision = 4; /* Init to the default value */ - - if ((bsz / dmap->subdivision) > 4096) - dmap->subdivision *= 2; - if ((bsz / dmap->subdivision) < 4096) - dmap->subdivision = 1; - } - bsz /= dmap->subdivision; - - if (bsz < 16) - bsz = 16; /* Just a sanity check */ - - dmap->fragment_size = bsz; - } - else - { - /* - * The process has specified the buffer size with SNDCTL_DSP_SETFRAGMENT or - * the buffer size computation has already been done. - */ - if (dmap->fragment_size > (dmap->buffsize / 2)) - dmap->fragment_size = (dmap->buffsize / 2); - bsz = dmap->fragment_size; - } - - if (audio_devs[dev]->min_fragment) - if (bsz < (1 << audio_devs[dev]->min_fragment)) - bsz = 1 << audio_devs[dev]->min_fragment; - if (audio_devs[dev]->max_fragment) - if (bsz > (1 << audio_devs[dev]->max_fragment)) - bsz = 1 << audio_devs[dev]->max_fragment; - bsz &= ~0x07; /* Force size which is multiple of 8 bytes */ -#ifdef OS_DMA_ALIGN_CHECK - OS_DMA_ALIGN_CHECK(bsz); -#endif - - n = dmap->buffsize / bsz; - if (n > MAX_SUB_BUFFERS) - n = MAX_SUB_BUFFERS; - if (n > dmap->max_fragments) - n = dmap->max_fragments; - - if (n < 2) - { - n = 2; - bsz /= 2; - } - dmap->nbufs = n; - dmap->bytes_in_use = n * bsz; - dmap->fragment_size = bsz; - dmap->max_byte_counter = (dmap->data_rate * 60 * 60) + - dmap->bytes_in_use; /* Approximately one hour */ - - if (dmap->raw_buf) - { - memset(dmap->raw_buf, dmap->neutral_byte, dmap->bytes_in_use); - } - - for (i = 0; i < dmap->nbufs; i++) - { - dmap->counts[i] = 0; - } - - dmap->flags |= DMA_ALLOC_DONE | DMA_EMPTY; -} - -static int dma_subdivide(int dev, struct dma_buffparms *dmap, int fact) -{ - if (fact == 0) - { - fact = dmap->subdivision; - if (fact == 0) - fact = 1; - return fact; - } - if (dmap->subdivision != 0 || dmap->fragment_size) /* Too late to change */ - return -EINVAL; - - if (fact > MAX_REALTIME_FACTOR) - return -EINVAL; - - if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16) - return -EINVAL; - - dmap->subdivision = fact; - return fact; -} - -static int dma_set_fragment(int dev, struct dma_buffparms *dmap, int fact) -{ - int bytes, count; - - if (fact == 0) - return -EIO; - - if (dmap->subdivision != 0 || - dmap->fragment_size) /* Too late to change */ - return -EINVAL; - - bytes = fact & 0xffff; - count = (fact >> 16) & 0x7fff; - - if (count == 0) - count = MAX_SUB_BUFFERS; - else if (count < MAX_SUB_BUFFERS) - count++; - - if (bytes < 4 || bytes > 17) /* <16 || > 512k */ - return -EINVAL; - - if (count < 2) - return -EINVAL; - - if (audio_devs[dev]->min_fragment > 0) - if (bytes < audio_devs[dev]->min_fragment) - bytes = audio_devs[dev]->min_fragment; - - if (audio_devs[dev]->max_fragment > 0) - if (bytes > audio_devs[dev]->max_fragment) - bytes = audio_devs[dev]->max_fragment; - -#ifdef OS_DMA_MINBITS - if (bytes < OS_DMA_MINBITS) - bytes = OS_DMA_MINBITS; -#endif - - dmap->fragment_size = (1 << bytes); - dmap->max_fragments = count; - - if (dmap->fragment_size > dmap->buffsize) - dmap->fragment_size = dmap->buffsize; - - if (dmap->fragment_size == dmap->buffsize && - audio_devs[dev]->flags & DMA_AUTOMODE) - dmap->fragment_size /= 2; /* Needs at least 2 buffers */ - - dmap->subdivision = 1; /* Disable SNDCTL_DSP_SUBDIVIDE */ - return bytes | ((count - 1) << 16); -} - -static int dma_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out; - struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in; - struct dma_buffparms *dmap; - audio_buf_info info; - count_info cinfo; - int fact, ret, changed, bits, count, err; - unsigned long flags; - - switch (cmd) - { - case SNDCTL_DSP_SUBDIVIDE: - ret = 0; - if (get_user(fact, (int __user *)arg)) - return -EFAULT; - if (audio_devs[dev]->open_mode & OPEN_WRITE) - ret = dma_subdivide(dev, dmap_out, fact); - if (ret < 0) - return ret; - if (audio_devs[dev]->open_mode != OPEN_WRITE || - (audio_devs[dev]->flags & DMA_DUPLEX && - audio_devs[dev]->open_mode & OPEN_READ)) - ret = dma_subdivide(dev, dmap_in, fact); - if (ret < 0) - return ret; - break; - - case SNDCTL_DSP_GETISPACE: - case SNDCTL_DSP_GETOSPACE: - dmap = dmap_out; - if (cmd == SNDCTL_DSP_GETISPACE && !(audio_devs[dev]->open_mode & OPEN_READ)) - return -EINVAL; - if (cmd == SNDCTL_DSP_GETOSPACE && !(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EINVAL; - if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX) - dmap = dmap_in; - if (dmap->mapping_flags & DMA_MAP_MAPPED) - return -EINVAL; - if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers(dev, dmap, (cmd == SNDCTL_DSP_GETISPACE)); - info.fragstotal = dmap->nbufs; - if (cmd == SNDCTL_DSP_GETISPACE) - info.fragments = dmap->qlen; - else - { - if (!DMAbuf_space_in_queue(dev)) - info.fragments = 0; - else - { - info.fragments = DMAbuf_space_in_queue(dev); - if (audio_devs[dev]->d->local_qlen) - { - int tmp = audio_devs[dev]->d->local_qlen(dev); - if (tmp && info.fragments) - tmp--; /* - * This buffer has been counted twice - */ - info.fragments -= tmp; - } - } - } - if (info.fragments < 0) - info.fragments = 0; - else if (info.fragments > dmap->nbufs) - info.fragments = dmap->nbufs; - - info.fragsize = dmap->fragment_size; - info.bytes = info.fragments * dmap->fragment_size; - - if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen) - info.bytes -= dmap->counts[dmap->qhead]; - else - { - info.fragments = info.bytes / dmap->fragment_size; - info.bytes -= dmap->user_counter % dmap->fragment_size; - } - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; - - case SNDCTL_DSP_SETTRIGGER: - if (get_user(bits, (int __user *)arg)) - return -EFAULT; - bits &= audio_devs[dev]->open_mode; - if (audio_devs[dev]->d->trigger == NULL) - return -EINVAL; - if (!(audio_devs[dev]->flags & DMA_DUPLEX) && (bits & PCM_ENABLE_INPUT) && - (bits & PCM_ENABLE_OUTPUT)) - return -EINVAL; - - if (bits & PCM_ENABLE_INPUT) - { - spin_lock_irqsave(&dmap_in->lock,flags); - changed = (audio_devs[dev]->enable_bits ^ bits) & PCM_ENABLE_INPUT; - if (changed && audio_devs[dev]->go) - { - reorganize_buffers(dev, dmap_in, 1); - if ((err = audio_devs[dev]->d->prepare_for_input(dev, - dmap_in->fragment_size, dmap_in->nbufs)) < 0) { - spin_unlock_irqrestore(&dmap_in->lock,flags); - return err; - } - dmap_in->dma_mode = DMODE_INPUT; - audio_devs[dev]->enable_bits |= PCM_ENABLE_INPUT; - DMAbuf_activate_recording(dev, dmap_in); - } else - audio_devs[dev]->enable_bits &= ~PCM_ENABLE_INPUT; - spin_unlock_irqrestore(&dmap_in->lock,flags); - } - if (bits & PCM_ENABLE_OUTPUT) - { - spin_lock_irqsave(&dmap_out->lock,flags); - changed = (audio_devs[dev]->enable_bits ^ bits) & PCM_ENABLE_OUTPUT; - if (changed && - (dmap_out->mapping_flags & DMA_MAP_MAPPED || dmap_out->qlen > 0) && - audio_devs[dev]->go) - { - if (!(dmap_out->flags & DMA_ALLOC_DONE)) - reorganize_buffers(dev, dmap_out, 0); - dmap_out->dma_mode = DMODE_OUTPUT; - audio_devs[dev]->enable_bits |= PCM_ENABLE_OUTPUT; - dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size; - DMAbuf_launch_output(dev, dmap_out); - } else - audio_devs[dev]->enable_bits &= ~PCM_ENABLE_OUTPUT; - spin_unlock_irqrestore(&dmap_out->lock,flags); - } -#if 0 - if (changed && audio_devs[dev]->d->trigger) - audio_devs[dev]->d->trigger(dev, bits * audio_devs[dev]->go); -#endif - /* Falls through... */ - - case SNDCTL_DSP_GETTRIGGER: - ret = audio_devs[dev]->enable_bits; - break; - - case SNDCTL_DSP_SETSYNCRO: - if (!audio_devs[dev]->d->trigger) - return -EINVAL; - audio_devs[dev]->d->trigger(dev, 0); - audio_devs[dev]->go = 0; - return 0; - - case SNDCTL_DSP_GETIPTR: - if (!(audio_devs[dev]->open_mode & OPEN_READ)) - return -EINVAL; - spin_lock_irqsave(&dmap_in->lock,flags); - cinfo.bytes = dmap_in->byte_counter; - cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_in, DMODE_INPUT) & ~3; - if (cinfo.ptr < dmap_in->fragment_size && dmap_in->qtail != 0) - cinfo.bytes += dmap_in->bytes_in_use; /* Pointer wrap not handled yet */ - cinfo.blocks = dmap_in->qlen; - cinfo.bytes += cinfo.ptr; - if (dmap_in->mapping_flags & DMA_MAP_MAPPED) - dmap_in->qlen = 0; /* Reset interrupt counter */ - spin_unlock_irqrestore(&dmap_in->lock,flags); - if (copy_to_user(arg, &cinfo, sizeof(cinfo))) - return -EFAULT; - return 0; - - case SNDCTL_DSP_GETOPTR: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EINVAL; - - spin_lock_irqsave(&dmap_out->lock,flags); - cinfo.bytes = dmap_out->byte_counter; - cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_out, DMODE_OUTPUT) & ~3; - if (cinfo.ptr < dmap_out->fragment_size && dmap_out->qhead != 0) - cinfo.bytes += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */ - cinfo.blocks = dmap_out->qlen; - cinfo.bytes += cinfo.ptr; - if (dmap_out->mapping_flags & DMA_MAP_MAPPED) - dmap_out->qlen = 0; /* Reset interrupt counter */ - spin_unlock_irqrestore(&dmap_out->lock,flags); - if (copy_to_user(arg, &cinfo, sizeof(cinfo))) - return -EFAULT; - return 0; - - case SNDCTL_DSP_GETODELAY: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EINVAL; - if (!(dmap_out->flags & DMA_ALLOC_DONE)) - { - ret=0; - break; - } - spin_lock_irqsave(&dmap_out->lock,flags); - /* Compute number of bytes that have been played */ - count = DMAbuf_get_buffer_pointer (dev, dmap_out, DMODE_OUTPUT); - if (count < dmap_out->fragment_size && dmap_out->qhead != 0) - count += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */ - count += dmap_out->byte_counter; - /* Subtract current count from the number of bytes written by app */ - count = dmap_out->user_counter - count; - if (count < 0) - count = 0; - spin_unlock_irqrestore(&dmap_out->lock,flags); - ret = count; - break; - - case SNDCTL_DSP_POST: - if (audio_devs[dev]->dmap_out->qlen > 0) - if (!(audio_devs[dev]->dmap_out->flags & DMA_ACTIVE)) - DMAbuf_launch_output(dev, audio_devs[dev]->dmap_out); - return 0; - - case SNDCTL_DSP_GETBLKSIZE: - dmap = dmap_out; - if (audio_devs[dev]->open_mode & OPEN_WRITE) - reorganize_buffers(dev, dmap_out, (audio_devs[dev]->open_mode == OPEN_READ)); - if (audio_devs[dev]->open_mode == OPEN_READ || - (audio_devs[dev]->flags & DMA_DUPLEX && - audio_devs[dev]->open_mode & OPEN_READ)) - reorganize_buffers(dev, dmap_in, (audio_devs[dev]->open_mode == OPEN_READ)); - if (audio_devs[dev]->open_mode == OPEN_READ) - dmap = dmap_in; - ret = dmap->fragment_size; - break; - - case SNDCTL_DSP_SETFRAGMENT: - ret = 0; - if (get_user(fact, (int __user *)arg)) - return -EFAULT; - if (audio_devs[dev]->open_mode & OPEN_WRITE) - ret = dma_set_fragment(dev, dmap_out, fact); - if (ret < 0) - return ret; - if (audio_devs[dev]->open_mode == OPEN_READ || - (audio_devs[dev]->flags & DMA_DUPLEX && - audio_devs[dev]->open_mode & OPEN_READ)) - ret = dma_set_fragment(dev, dmap_in, fact); - if (ret < 0) - return ret; - if (!arg) /* don't know what this is good for, but preserve old semantics */ - return 0; - break; - - default: - if (!audio_devs[dev]->d->ioctl) - return -EINVAL; - return audio_devs[dev]->d->ioctl(dev, cmd, arg); - } - return put_user(ret, (int __user *)arg); -} diff --git a/ANDROID_3.4.5/sound/oss/bin2hex.c b/ANDROID_3.4.5/sound/oss/bin2hex.c deleted file mode 100644 index b59109eb..00000000 --- a/ANDROID_3.4.5/sound/oss/bin2hex.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include - -int main( int argc, const char * argv [] ) -{ - const char * varname; - int i = 0; - int c; - int id = 0; - - if(argv[1] && strcmp(argv[1],"-i")==0) - { - argv++; - argc--; - id=1; - } - - if(argc==1) - { - fprintf(stderr, "bin2hex: [-i] firmware\n"); - exit(1); - } - - varname = argv[1]; - printf( "/* automatically generated by bin2hex */\n" ); - printf( "static unsigned char %s [] %s =\n{\n", varname , id?"__initdata":""); - - while ( ( c = getchar( ) ) != EOF ) - { - if ( i != 0 && i % 10 == 0 ) - printf( "\n" ); - printf( "0x%02lx,", c & 0xFFl ); - i++; - } - - printf( "};\nstatic int %sLen = %d;\n", varname, i ); - return 0; -} diff --git a/ANDROID_3.4.5/sound/oss/coproc.h b/ANDROID_3.4.5/sound/oss/coproc.h deleted file mode 100644 index 7bec21bb..00000000 --- a/ANDROID_3.4.5/sound/oss/coproc.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Definitions for various on board processors on the sound cards. For - * example DSP processors. - */ - -/* - * Coprocessor access types - */ -#define COPR_CUSTOM 0x0001 /* Custom applications */ -#define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */ -#define COPR_PCM 0x0004 /* Digitized voice applications */ -#define COPR_SYNTH 0x0008 /* Music synthesis */ diff --git a/ANDROID_3.4.5/sound/oss/dev_table.c b/ANDROID_3.4.5/sound/oss/dev_table.c deleted file mode 100644 index d8cf3e58..00000000 --- a/ANDROID_3.4.5/sound/oss/dev_table.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * sound/oss/dev_table.c - * - * Device call tables. - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - -#include - -#include "sound_config.h" - -struct audio_operations *audio_devs[MAX_AUDIO_DEV]; -EXPORT_SYMBOL(audio_devs); - -int num_audiodevs; -EXPORT_SYMBOL(num_audiodevs); - -struct mixer_operations *mixer_devs[MAX_MIXER_DEV]; -EXPORT_SYMBOL(mixer_devs); - -int num_mixers; -EXPORT_SYMBOL(num_mixers); - -struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; -EXPORT_SYMBOL(synth_devs); - -int num_synths; - -struct midi_operations *midi_devs[MAX_MIDI_DEV]; -EXPORT_SYMBOL(midi_devs); - -int num_midis; -EXPORT_SYMBOL(num_midis); - -struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { - &default_sound_timer, NULL -}; -EXPORT_SYMBOL(sound_timer_devs); - -int num_sound_timers = 1; - - -static int sound_alloc_audiodev(void); - -int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, - int driver_size, int flags, unsigned int format_mask, - void *devc, int dma1, int dma2) -{ - struct audio_driver *d; - struct audio_operations *op; - int num; - - if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) { - printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name); - return -(EINVAL); - } - num = sound_alloc_audiodev(); - - if (num == -1) { - printk(KERN_ERR "sound: Too many audio drivers\n"); - return -(EBUSY); - } - d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver))); - sound_nblocks++; - if (sound_nblocks >= MAX_MEM_BLOCKS) - sound_nblocks = MAX_MEM_BLOCKS - 1; - - op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct audio_operations))); - sound_nblocks++; - if (sound_nblocks >= MAX_MEM_BLOCKS) - sound_nblocks = MAX_MEM_BLOCKS - 1; - - if (d == NULL || op == NULL) { - printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); - sound_unload_audiodev(num); - return -(ENOMEM); - } - init_waitqueue_head(&op->in_sleeper); - init_waitqueue_head(&op->out_sleeper); - init_waitqueue_head(&op->poll_sleeper); - if (driver_size < sizeof(struct audio_driver)) - memset((char *) d, 0, sizeof(struct audio_driver)); - - memcpy((char *) d, (char *) driver, driver_size); - - op->d = d; - strlcpy(op->name, name, sizeof(op->name)); - op->flags = flags; - op->format_mask = format_mask; - op->devc = devc; - - /* - * Hardcoded defaults - */ - audio_devs[num] = op; - - DMAbuf_init(num, dma1, dma2); - - audio_init_devices(); - return num; -} -EXPORT_SYMBOL(sound_install_audiodrv); - -int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, - int driver_size, void *devc) -{ - struct mixer_operations *op; - - int n = sound_alloc_mixerdev(); - - if (n == -1) { - printk(KERN_ERR "Sound: Too many mixer drivers\n"); - return -EBUSY; - } - if (vers != MIXER_DRIVER_VERSION || - driver_size > sizeof(struct mixer_operations)) { - printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); - return -EINVAL; - } - - /* FIXME: This leaks a mixer_operations struct every time its called - until you unload sound! */ - - op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct mixer_operations))); - sound_nblocks++; - if (sound_nblocks >= MAX_MEM_BLOCKS) - sound_nblocks = MAX_MEM_BLOCKS - 1; - - if (op == NULL) { - printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); - return -ENOMEM; - } - memcpy((char *) op, (char *) driver, driver_size); - - strlcpy(op->name, name, sizeof(op->name)); - op->devc = devc; - - mixer_devs[n] = op; - return n; -} -EXPORT_SYMBOL(sound_install_mixer); - -void sound_unload_audiodev(int dev) -{ - if (dev != -1) { - DMAbuf_deinit(dev); - audio_devs[dev] = NULL; - unregister_sound_dsp((dev<<4)+3); - } -} -EXPORT_SYMBOL(sound_unload_audiodev); - -static int sound_alloc_audiodev(void) -{ - int i = register_sound_dsp(&oss_sound_fops, -1); - if(i==-1) - return i; - i>>=4; - if(i>=num_audiodevs) - num_audiodevs = i + 1; - return i; -} - -int sound_alloc_mididev(void) -{ - int i = register_sound_midi(&oss_sound_fops, -1); - if(i==-1) - return i; - i>>=4; - if(i>=num_midis) - num_midis = i + 1; - return i; -} -EXPORT_SYMBOL(sound_alloc_mididev); - -int sound_alloc_synthdev(void) -{ - int i; - - for (i = 0; i < MAX_SYNTH_DEV; i++) { - if (synth_devs[i] == NULL) { - if (i >= num_synths) - num_synths++; - return i; - } - } - return -1; -} -EXPORT_SYMBOL(sound_alloc_synthdev); - -int sound_alloc_mixerdev(void) -{ - int i = register_sound_mixer(&oss_sound_fops, -1); - if(i==-1) - return -1; - i>>=4; - if(i>=num_mixers) - num_mixers = i + 1; - return i; -} -EXPORT_SYMBOL(sound_alloc_mixerdev); - -int sound_alloc_timerdev(void) -{ - int i; - - for (i = 0; i < MAX_TIMER_DEV; i++) { - if (sound_timer_devs[i] == NULL) { - if (i >= num_sound_timers) - num_sound_timers++; - return i; - } - } - return -1; -} -EXPORT_SYMBOL(sound_alloc_timerdev); - -void sound_unload_mixerdev(int dev) -{ - if (dev != -1) { - mixer_devs[dev] = NULL; - unregister_sound_mixer(dev<<4); - num_mixers--; - } -} -EXPORT_SYMBOL(sound_unload_mixerdev); - -void sound_unload_mididev(int dev) -{ - if (dev != -1) { - midi_devs[dev] = NULL; - unregister_sound_midi((dev<<4)+2); - } -} -EXPORT_SYMBOL(sound_unload_mididev); - -void sound_unload_synthdev(int dev) -{ - if (dev != -1) - synth_devs[dev] = NULL; -} -EXPORT_SYMBOL(sound_unload_synthdev); - -void sound_unload_timerdev(int dev) -{ - if (dev != -1) - sound_timer_devs[dev] = NULL; -} -EXPORT_SYMBOL(sound_unload_timerdev); - diff --git a/ANDROID_3.4.5/sound/oss/dev_table.h b/ANDROID_3.4.5/sound/oss/dev_table.h deleted file mode 100644 index 0199a317..00000000 --- a/ANDROID_3.4.5/sound/oss/dev_table.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * dev_table.h - * - * Global definitions for device call tables - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - - -#ifndef _DEV_TABLE_H_ -#define _DEV_TABLE_H_ - -#include -/* - * Sound card numbers 27 to 999. (1 to 26 are defined in soundcard.h) - * Numbers 1000 to N are reserved for driver's internal use. - */ - -#define SNDCARD_DESKPROXL 27 /* Compaq Deskpro XL */ -#define SNDCARD_VIDC 28 /* ARMs VIDC */ -#define SNDCARD_SBPNP 29 -#define SNDCARD_SOFTOSS 36 -#define SNDCARD_VMIDI 37 -#define SNDCARD_OPL3SA1 38 /* Note: clash in msnd.h */ -#define SNDCARD_OPL3SA1_SB 39 -#define SNDCARD_OPL3SA1_MPU 40 -#define SNDCARD_WAVEFRONT 41 -#define SNDCARD_OPL3SA2 42 -#define SNDCARD_OPL3SA2_MPU 43 -#define SNDCARD_WAVEARTIST 44 /* Waveartist */ -#define SNDCARD_OPL3SA2_MSS 45 /* Originally missed */ -#define SNDCARD_AD1816 88 - -/* - * NOTE! NOTE! NOTE! NOTE! - * - * If you modify this file, please check the dev_table.c also. - * - * NOTE! NOTE! NOTE! NOTE! - */ - -struct driver_info -{ - char *driver_id; - int card_subtype; /* Driver specific. Usually 0 */ - int card_type; /* From soundcard.h */ - char *name; - void (*attach) (struct address_info *hw_config); - int (*probe) (struct address_info *hw_config); - void (*unload) (struct address_info *hw_config); -}; - -struct card_info -{ - int card_type; /* Link (search key) to the driver list */ - struct address_info config; - int enabled; - void *for_driver_use; -}; - - -/* - * Device specific parameters (used only by dmabuf.c) - */ -#define MAX_SUB_BUFFERS (32*MAX_REALTIME_FACTOR) - -#define DMODE_NONE 0 -#define DMODE_OUTPUT PCM_ENABLE_OUTPUT -#define DMODE_INPUT PCM_ENABLE_INPUT - -struct dma_buffparms -{ - int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */ - int closing; - - /* - * Pointers to raw buffers - */ - - char *raw_buf; - unsigned long raw_buf_phys; - int buffsize; - - /* - * Device state tables - */ - - unsigned long flags; -#define DMA_BUSY 0x00000001 -#define DMA_RESTART 0x00000002 -#define DMA_ACTIVE 0x00000004 -#define DMA_STARTED 0x00000008 -#define DMA_EMPTY 0x00000010 -#define DMA_ALLOC_DONE 0x00000020 -#define DMA_SYNCING 0x00000040 -#define DMA_DIRTY 0x00000080 -#define DMA_POST 0x00000100 -#define DMA_NODMA 0x00000200 -#define DMA_NOTIMEOUT 0x00000400 - - int open_mode; - - /* - * Queue parameters. - */ - int qlen; - int qhead; - int qtail; - spinlock_t lock; - - int cfrag; /* Current incomplete fragment (write) */ - - int nbufs; - int counts[MAX_SUB_BUFFERS]; - int subdivision; - - int fragment_size; - int needs_reorg; - int max_fragments; - - int bytes_in_use; - - int underrun_count; - unsigned long byte_counter; - unsigned long user_counter; - unsigned long max_byte_counter; - int data_rate; /* Bytes/second */ - - int mapping_flags; -#define DMA_MAP_MAPPED 0x00000001 - char neutral_byte; - int dma; /* DMA channel */ - - int applic_profile; /* Application profile (APF_*) */ - /* Interrupt callback stuff */ - void (*audio_callback) (int dev, int parm); - int callback_parm; - - int buf_flags[MAX_SUB_BUFFERS]; -#define BUFF_EOF 0x00000001 /* Increment eof count */ -#define BUFF_DIRTY 0x00000002 /* Buffer written */ -}; - -/* - * Structure for use with various microcontrollers and DSP processors - * in the recent sound cards. - */ -typedef struct coproc_operations -{ - char name[64]; - struct module *owner; - int (*open) (void *devc, int sub_device); - void (*close) (void *devc, int sub_device); - int (*ioctl) (void *devc, unsigned int cmd, void __user * arg, int local); - void (*reset) (void *devc); - - void *devc; /* Driver specific info */ -} coproc_operations; - -struct audio_driver -{ - struct module *owner; - int (*open) (int dev, int mode); - void (*close) (int dev); - void (*output_block) (int dev, unsigned long buf, - int count, int intrflag); - void (*start_input) (int dev, unsigned long buf, - int count, int intrflag); - int (*ioctl) (int dev, unsigned int cmd, void __user * arg); - int (*prepare_for_input) (int dev, int bufsize, int nbufs); - int (*prepare_for_output) (int dev, int bufsize, int nbufs); - void (*halt_io) (int dev); - int (*local_qlen)(int dev); - void (*copy_user) (int dev, - char *localbuf, int localoffs, - const char __user *userbuf, int useroffs, - int max_in, int max_out, - int *used, int *returned, - int len); - void (*halt_input) (int dev); - void (*halt_output) (int dev); - void (*trigger) (int dev, int bits); - int (*set_speed)(int dev, int speed); - unsigned int (*set_bits)(int dev, unsigned int bits); - short (*set_channels)(int dev, short channels); - void (*postprocess_write)(int dev); /* Device spesific postprocessing for written data */ - void (*preprocess_read)(int dev); /* Device spesific preprocessing for read data */ - void (*mmap)(int dev); -}; - -struct audio_operations -{ - char name[128]; - int flags; -#define NOTHING_SPECIAL 0x00 -#define NEEDS_RESTART 0x01 -#define DMA_AUTOMODE 0x02 -#define DMA_DUPLEX 0x04 -#define DMA_PSEUDO_AUTOMODE 0x08 -#define DMA_HARDSTOP 0x10 -#define DMA_EXACT 0x40 -#define DMA_NORESET 0x80 - int format_mask; /* Bitmask for supported audio formats */ - void *devc; /* Driver specific info */ - struct audio_driver *d; - void *portc; /* Driver specific info */ - struct dma_buffparms *dmap_in, *dmap_out; - struct coproc_operations *coproc; - int mixer_dev; - int enable_bits; - int open_mode; - int go; - int min_fragment; /* 0 == unlimited */ - int max_fragment; /* 0 == unlimited */ - int parent_dev; /* 0 -> no parent, 1 to n -> parent=parent_dev+1 */ - - /* fields formerly in dmabuf.c */ - wait_queue_head_t in_sleeper; - wait_queue_head_t out_sleeper; - wait_queue_head_t poll_sleeper; - - /* fields formerly in audio.c */ - int audio_mode; - -#define AM_NONE 0 -#define AM_WRITE OPEN_WRITE -#define AM_READ OPEN_READ - - int local_format; - int audio_format; - int local_conversion; -#define CNV_MU_LAW 0x00000001 - - /* large structures at the end to keep offsets small */ - struct dma_buffparms dmaps[2]; -}; - -int *load_mixer_volumes(char *name, int *levels, int present); - -struct mixer_operations -{ - struct module *owner; - char id[16]; - char name[64]; - int (*ioctl) (int dev, unsigned int cmd, void __user * arg); - - void *devc; - int modify_counter; -}; - -struct synth_operations -{ - struct module *owner; - char *id; /* Unique identifier (ASCII) max 29 char */ - struct synth_info *info; - int midi_dev; - int synth_type; - int synth_subtype; - - int (*open) (int dev, int mode); - void (*close) (int dev); - int (*ioctl) (int dev, unsigned int cmd, void __user * arg); - int (*kill_note) (int dev, int voice, int note, int velocity); - int (*start_note) (int dev, int voice, int note, int velocity); - int (*set_instr) (int dev, int voice, int instr); - void (*reset) (int dev); - void (*hw_control) (int dev, unsigned char *event); - int (*load_patch) (int dev, int format, const char __user *addr, - int count, int pmgr_flag); - void (*aftertouch) (int dev, int voice, int pressure); - void (*controller) (int dev, int voice, int ctrl_num, int value); - void (*panning) (int dev, int voice, int value); - void (*volume_method) (int dev, int mode); - void (*bender) (int dev, int chn, int value); - int (*alloc_voice) (int dev, int chn, int note, struct voice_alloc_info *alloc); - void (*setup_voice) (int dev, int voice, int chn); - int (*send_sysex)(int dev, unsigned char *bytes, int len); - - struct voice_alloc_info alloc; - struct channel_info chn_info[16]; - int emulation; -#define EMU_GM 1 /* General MIDI */ -#define EMU_XG 2 /* Yamaha XG */ -#define MAX_SYSEX_BUF 64 - unsigned char sysex_buf[MAX_SYSEX_BUF]; - int sysex_ptr; -}; - -struct midi_input_info -{ - /* MIDI input scanner variables */ -#define MI_MAX 10 - volatile int m_busy; - unsigned char m_buf[MI_MAX]; - unsigned char m_prev_status; /* For running status */ - int m_ptr; -#define MST_INIT 0 -#define MST_DATA 1 -#define MST_SYSEX 2 - int m_state; - int m_left; -}; - -struct midi_operations -{ - struct module *owner; - struct midi_info info; - struct synth_operations *converter; - struct midi_input_info in_info; - int (*open) (int dev, int mode, - void (*inputintr)(int dev, unsigned char data), - void (*outputintr)(int dev) - ); - void (*close) (int dev); - int (*ioctl) (int dev, unsigned int cmd, void __user * arg); - int (*outputc) (int dev, unsigned char data); - int (*start_read) (int dev); - int (*end_read) (int dev); - void (*kick)(int dev); - int (*command) (int dev, unsigned char *data); - int (*buffer_status) (int dev); - int (*prefix_cmd) (int dev, unsigned char status); - struct coproc_operations *coproc; - void *devc; -}; - -struct sound_lowlev_timer -{ - int dev; - int priority; - unsigned int (*tmr_start)(int dev, unsigned int usecs); - void (*tmr_disable)(int dev); - void (*tmr_restart)(int dev); -}; - -struct sound_timer_operations -{ - struct module *owner; - struct sound_timer_info info; - int priority; - int devlink; - int (*open)(int dev, int mode); - void (*close)(int dev); - int (*event)(int dev, unsigned char *ev); - unsigned long (*get_time)(int dev); - int (*ioctl) (int dev, unsigned int cmd, void __user * arg); - void (*arm_timer)(int dev, long time); -}; - -extern struct sound_timer_operations default_sound_timer; - -extern struct audio_operations *audio_devs[MAX_AUDIO_DEV]; -extern int num_audiodevs; -extern struct mixer_operations *mixer_devs[MAX_MIXER_DEV]; -extern int num_mixers; -extern struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; -extern int num_synths; -extern struct midi_operations *midi_devs[MAX_MIDI_DEV]; -extern int num_midis; -extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV]; -extern int num_sound_timers; - -extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info); -void sound_timer_init (struct sound_lowlev_timer *t, char *name); -void sound_dma_intr (int dev, struct dma_buffparms *dmap, int chan); - -#define AUDIO_DRIVER_VERSION 2 -#define MIXER_DRIVER_VERSION 2 -int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, - int driver_size, int flags, unsigned int format_mask, - void *devc, int dma1, int dma2); -int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, - int driver_size, void *devc); - -void sound_unload_audiodev(int dev); -void sound_unload_mixerdev(int dev); -void sound_unload_mididev(int dev); -void sound_unload_synthdev(int dev); -void sound_unload_timerdev(int dev); -int sound_alloc_mixerdev(void); -int sound_alloc_timerdev(void); -int sound_alloc_synthdev(void); -int sound_alloc_mididev(void); -#endif /* _DEV_TABLE_H_ */ - diff --git a/ANDROID_3.4.5/sound/oss/dmabuf.c b/ANDROID_3.4.5/sound/oss/dmabuf.c deleted file mode 100644 index bcc3e8e0..00000000 --- a/ANDROID_3.4.5/sound/oss/dmabuf.c +++ /dev/null @@ -1,1268 +0,0 @@ -/* - * sound/oss/dmabuf.c - * - * The DMA buffer manager for digitized voice applications - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * Thomas Sailer : moved several static variables into struct audio_operations - * (which is grossly misnamed btw.) because they have the same - * lifetime as the rest in there and dynamic allocation saves - * 12k or so - * Thomas Sailer : remove {in,out}_sleep_flag. It was used for the sleeper to - * determine if it was woken up by the expiring timeout or by - * an explicit wake_up. The return value from schedule_timeout - * can be used instead; if 0, the wakeup was due to the timeout. - * - * Rob Riggs Added persistent DMA buffers (1998/10/17) - */ - -#define BE_CONSERVATIVE -#define SAMPLE_ROUNDUP 0 - -#include -#include -#include "sound_config.h" - -#define DMAP_FREE_ON_CLOSE 0 -#define DMAP_KEEP_ON_CLOSE 1 -extern int sound_dmap_flag; - -static void dma_reset_output(int dev); -static void dma_reset_input(int dev); -static int local_start_dma(struct audio_operations *adev, unsigned long physaddr, int count, int dma_mode); - - - -static int debugmem; /* switched off by default */ -static int dma_buffsize = DSP_BUFFSIZE; - -static long dmabuf_timeout(struct dma_buffparms *dmap) -{ - long tmout; - - tmout = (dmap->fragment_size * HZ) / dmap->data_rate; - tmout += HZ / 5; /* Some safety distance */ - if (tmout < (HZ / 2)) - tmout = HZ / 2; - if (tmout > 20 * HZ) - tmout = 20 * HZ; - return tmout; -} - -static int sound_alloc_dmap(struct dma_buffparms *dmap) -{ - char *start_addr, *end_addr; - int dma_pagesize; - int sz, size; - struct page *page; - - dmap->mapping_flags &= ~DMA_MAP_MAPPED; - - if (dmap->raw_buf != NULL) - return 0; /* Already done */ - if (dma_buffsize < 4096) - dma_buffsize = 4096; - dma_pagesize = (dmap->dma < 4) ? (64 * 1024) : (128 * 1024); - - /* - * Now check for the Cyrix problem. - */ - - if(isa_dma_bridge_buggy==2) - dma_pagesize=32768; - - dmap->raw_buf = NULL; - dmap->buffsize = dma_buffsize; - if (dmap->buffsize > dma_pagesize) - dmap->buffsize = dma_pagesize; - start_addr = NULL; - /* - * Now loop until we get a free buffer. Try to get smaller buffer if - * it fails. Don't accept smaller than 8k buffer for performance - * reasons. - */ - while (start_addr == NULL && dmap->buffsize > PAGE_SIZE) { - for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); - dmap->buffsize = PAGE_SIZE * (1 << sz); - start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA|__GFP_NOWARN, sz); - if (start_addr == NULL) - dmap->buffsize /= 2; - } - - if (start_addr == NULL) { - printk(KERN_WARNING "Sound error: Couldn't allocate DMA buffer\n"); - return -ENOMEM; - } else { - /* make some checks */ - end_addr = start_addr + dmap->buffsize - 1; - - if (debugmem) - printk(KERN_DEBUG "sound: start 0x%lx, end 0x%lx\n", (long) start_addr, (long) end_addr); - - /* now check if it fits into the same dma-pagesize */ - - if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1)) - || end_addr >= (char *) (MAX_DMA_ADDRESS)) { - printk(KERN_ERR "sound: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, dmap->buffsize); - return -EFAULT; - } - } - dmap->raw_buf = start_addr; - dmap->raw_buf_phys = virt_to_bus(start_addr); - - for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) - SetPageReserved(page); - return 0; -} - -static void sound_free_dmap(struct dma_buffparms *dmap) -{ - int sz, size; - struct page *page; - unsigned long start_addr, end_addr; - - if (dmap->raw_buf == NULL) - return; - if (dmap->mapping_flags & DMA_MAP_MAPPED) - return; /* Don't free mmapped buffer. Will use it next time */ - for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); - - start_addr = (unsigned long) dmap->raw_buf; - end_addr = start_addr + dmap->buffsize; - - for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++) - ClearPageReserved(page); - - free_pages((unsigned long) dmap->raw_buf, sz); - dmap->raw_buf = NULL; -} - - -/* Intel version !!!!!!!!! */ - -static int sound_start_dma(struct dma_buffparms *dmap, unsigned long physaddr, int count, int dma_mode) -{ - unsigned long flags; - int chan = dmap->dma; - - /* printk( "Start DMA%d %d, %d\n", chan, (int)(physaddr-dmap->raw_buf_phys), count); */ - - flags = claim_dma_lock(); - disable_dma(chan); - clear_dma_ff(chan); - set_dma_mode(chan, dma_mode); - set_dma_addr(chan, physaddr); - set_dma_count(chan, count); - enable_dma(chan); - release_dma_lock(flags); - - return 0; -} - -static void dma_init_buffers(struct dma_buffparms *dmap) -{ - dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; - dmap->byte_counter = 0; - dmap->max_byte_counter = 8000 * 60 * 60; - dmap->bytes_in_use = dmap->buffsize; - - dmap->dma_mode = DMODE_NONE; - dmap->mapping_flags = 0; - dmap->neutral_byte = 0x80; - dmap->data_rate = 8000; - dmap->cfrag = -1; - dmap->closing = 0; - dmap->nbufs = 1; - dmap->flags = DMA_BUSY; /* Other flags off */ -} - -static int open_dmap(struct audio_operations *adev, int mode, struct dma_buffparms *dmap) -{ - int err; - - if (dmap->flags & DMA_BUSY) - return -EBUSY; - if ((err = sound_alloc_dmap(dmap)) < 0) - return err; - - if (dmap->raw_buf == NULL) { - printk(KERN_WARNING "Sound: DMA buffers not available\n"); - return -ENOSPC; /* Memory allocation failed during boot */ - } - if (dmap->dma >= 0 && sound_open_dma(dmap->dma, adev->name)) { - printk(KERN_WARNING "Unable to grab(2) DMA%d for the audio driver\n", dmap->dma); - return -EBUSY; - } - dma_init_buffers(dmap); - spin_lock_init(&dmap->lock); - dmap->open_mode = mode; - dmap->subdivision = dmap->underrun_count = 0; - dmap->fragment_size = 0; - dmap->max_fragments = 65536; /* Just a large value */ - dmap->byte_counter = 0; - dmap->max_byte_counter = 8000 * 60 * 60; - dmap->applic_profile = APF_NORMAL; - dmap->needs_reorg = 1; - dmap->audio_callback = NULL; - dmap->callback_parm = 0; - return 0; -} - -static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap) -{ - unsigned long flags; - - if (dmap->dma >= 0) { - sound_close_dma(dmap->dma); - flags=claim_dma_lock(); - disable_dma(dmap->dma); - release_dma_lock(flags); - } - if (dmap->flags & DMA_BUSY) - dmap->dma_mode = DMODE_NONE; - dmap->flags &= ~DMA_BUSY; - - if (sound_dmap_flag == DMAP_FREE_ON_CLOSE) - sound_free_dmap(dmap); -} - - -static unsigned int default_set_bits(int dev, unsigned int bits) -{ - mm_segment_t fs = get_fs(); - - set_fs(get_ds()); - audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_SETFMT, (void __user *)&bits); - set_fs(fs); - return bits; -} - -static int default_set_speed(int dev, int speed) -{ - mm_segment_t fs = get_fs(); - - set_fs(get_ds()); - audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_SPEED, (void __user *)&speed); - set_fs(fs); - return speed; -} - -static short default_set_channels(int dev, short channels) -{ - int c = channels; - mm_segment_t fs = get_fs(); - - set_fs(get_ds()); - audio_devs[dev]->d->ioctl(dev, SNDCTL_DSP_CHANNELS, (void __user *)&c); - set_fs(fs); - return c; -} - -static void check_driver(struct audio_driver *d) -{ - if (d->set_speed == NULL) - d->set_speed = default_set_speed; - if (d->set_bits == NULL) - d->set_bits = default_set_bits; - if (d->set_channels == NULL) - d->set_channels = default_set_channels; -} - -int DMAbuf_open(int dev, int mode) -{ - struct audio_operations *adev = audio_devs[dev]; - int retval; - struct dma_buffparms *dmap_in = NULL; - struct dma_buffparms *dmap_out = NULL; - - if (!adev) - return -ENXIO; - if (!(adev->flags & DMA_DUPLEX)) - adev->dmap_in = adev->dmap_out; - check_driver(adev->d); - - if ((retval = adev->d->open(dev, mode)) < 0) - return retval; - dmap_out = adev->dmap_out; - dmap_in = adev->dmap_in; - if (dmap_in == dmap_out) - adev->flags &= ~DMA_DUPLEX; - - if (mode & OPEN_WRITE) { - if ((retval = open_dmap(adev, mode, dmap_out)) < 0) { - adev->d->close(dev); - return retval; - } - } - adev->enable_bits = mode; - - if (mode == OPEN_READ || (mode != OPEN_WRITE && (adev->flags & DMA_DUPLEX))) { - if ((retval = open_dmap(adev, mode, dmap_in)) < 0) { - adev->d->close(dev); - if (mode & OPEN_WRITE) - close_dmap(adev, dmap_out); - return retval; - } - } - adev->open_mode = mode; - adev->go = 1; - - adev->d->set_bits(dev, 8); - adev->d->set_channels(dev, 1); - adev->d->set_speed(dev, DSP_DEFAULT_SPEED); - if (adev->dmap_out->dma_mode == DMODE_OUTPUT) - memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, - adev->dmap_out->bytes_in_use); - return 0; -} -/* MUST not hold the spinlock */ -void DMAbuf_reset(int dev) -{ - if (audio_devs[dev]->open_mode & OPEN_WRITE) - dma_reset_output(dev); - - if (audio_devs[dev]->open_mode & OPEN_READ) - dma_reset_input(dev); -} - -static void dma_reset_output(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - unsigned long flags,f ; - struct dma_buffparms *dmap = adev->dmap_out; - - if (!(dmap->flags & DMA_STARTED)) /* DMA is not active */ - return; - - /* - * First wait until the current fragment has been played completely - */ - spin_lock_irqsave(&dmap->lock,flags); - adev->dmap_out->flags |= DMA_SYNCING; - - adev->dmap_out->underrun_count = 0; - if (!signal_pending(current) && adev->dmap_out->qlen && - adev->dmap_out->underrun_count == 0){ - spin_unlock_irqrestore(&dmap->lock,flags); - interruptible_sleep_on_timeout(&adev->out_sleeper, - dmabuf_timeout(dmap)); - spin_lock_irqsave(&dmap->lock,flags); - } - adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); - - /* - * Finally shut the device off - */ - if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_output) - adev->d->halt_io(dev); - else - adev->d->halt_output(dev); - adev->dmap_out->flags &= ~DMA_STARTED; - - f=claim_dma_lock(); - clear_dma_ff(dmap->dma); - disable_dma(dmap->dma); - release_dma_lock(f); - - dmap->byte_counter = 0; - reorganize_buffers(dev, adev->dmap_out, 0); - dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; - spin_unlock_irqrestore(&dmap->lock,flags); -} - -static void dma_reset_input(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - unsigned long flags; - struct dma_buffparms *dmap = adev->dmap_in; - - spin_lock_irqsave(&dmap->lock,flags); - if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_input) - adev->d->halt_io(dev); - else - adev->d->halt_input(dev); - adev->dmap_in->flags &= ~DMA_STARTED; - - dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; - dmap->byte_counter = 0; - reorganize_buffers(dev, adev->dmap_in, 1); - spin_unlock_irqrestore(&dmap->lock,flags); -} -/* MUST be called with holding the dmap->lock */ -void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap) -{ - struct audio_operations *adev = audio_devs[dev]; - - if (!((adev->enable_bits * adev->go) & PCM_ENABLE_OUTPUT)) - return; /* Don't start DMA yet */ - dmap->dma_mode = DMODE_OUTPUT; - - if (!(dmap->flags & DMA_ACTIVE) || !(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) { - if (!(dmap->flags & DMA_STARTED)) { - reorganize_buffers(dev, dmap, 0); - if (adev->d->prepare_for_output(dev, dmap->fragment_size, dmap->nbufs)) - return; - if (!(dmap->flags & DMA_NODMA)) - local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_WRITE); - dmap->flags |= DMA_STARTED; - } - if (dmap->counts[dmap->qhead] == 0) - dmap->counts[dmap->qhead] = dmap->fragment_size; - dmap->dma_mode = DMODE_OUTPUT; - adev->d->output_block(dev, dmap->raw_buf_phys + dmap->qhead * dmap->fragment_size, - dmap->counts[dmap->qhead], 1); - if (adev->d->trigger) - adev->d->trigger(dev,adev->enable_bits * adev->go); - } - dmap->flags |= DMA_ACTIVE; -} - -int DMAbuf_sync(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - unsigned long flags; - int n = 0; - struct dma_buffparms *dmap; - - if (!adev->go && !(adev->enable_bits & PCM_ENABLE_OUTPUT)) - return 0; - - if (adev->dmap_out->dma_mode == DMODE_OUTPUT) { - dmap = adev->dmap_out; - spin_lock_irqsave(&dmap->lock,flags); - if (dmap->qlen > 0 && !(dmap->flags & DMA_ACTIVE)) - DMAbuf_launch_output(dev, dmap); - adev->dmap_out->flags |= DMA_SYNCING; - adev->dmap_out->underrun_count = 0; - while (!signal_pending(current) && n++ < adev->dmap_out->nbufs && - adev->dmap_out->qlen && adev->dmap_out->underrun_count == 0) { - long t = dmabuf_timeout(dmap); - spin_unlock_irqrestore(&dmap->lock,flags); - /* FIXME: not safe may miss events */ - t = interruptible_sleep_on_timeout(&adev->out_sleeper, t); - spin_lock_irqsave(&dmap->lock,flags); - if (!t) { - adev->dmap_out->flags &= ~DMA_SYNCING; - spin_unlock_irqrestore(&dmap->lock,flags); - return adev->dmap_out->qlen; - } - } - adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); - - /* - * Some devices such as GUS have huge amount of on board RAM for the - * audio data. We have to wait until the device has finished playing. - */ - - /* still holding the lock */ - if (adev->d->local_qlen) { /* Device has hidden buffers */ - while (!signal_pending(current) && - adev->d->local_qlen(dev)){ - spin_unlock_irqrestore(&dmap->lock,flags); - interruptible_sleep_on_timeout(&adev->out_sleeper, - dmabuf_timeout(dmap)); - spin_lock_irqsave(&dmap->lock,flags); - } - } - spin_unlock_irqrestore(&dmap->lock,flags); - } - adev->dmap_out->dma_mode = DMODE_NONE; - return adev->dmap_out->qlen; -} - -int DMAbuf_release(int dev, int mode) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap; - unsigned long flags; - - dmap = adev->dmap_out; - if (adev->open_mode & OPEN_WRITE) - adev->dmap_out->closing = 1; - - if (adev->open_mode & OPEN_READ){ - adev->dmap_in->closing = 1; - dmap = adev->dmap_in; - } - if (adev->open_mode & OPEN_WRITE) - if (!(adev->dmap_out->mapping_flags & DMA_MAP_MAPPED)) - if (!signal_pending(current) && (adev->dmap_out->dma_mode == DMODE_OUTPUT)) - DMAbuf_sync(dev); - if (adev->dmap_out->dma_mode == DMODE_OUTPUT) - memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, adev->dmap_out->bytes_in_use); - - DMAbuf_reset(dev); - spin_lock_irqsave(&dmap->lock,flags); - adev->d->close(dev); - - if (adev->open_mode & OPEN_WRITE) - close_dmap(adev, adev->dmap_out); - - if (adev->open_mode == OPEN_READ || - (adev->open_mode != OPEN_WRITE && - (adev->flags & DMA_DUPLEX))) - close_dmap(adev, adev->dmap_in); - adev->open_mode = 0; - spin_unlock_irqrestore(&dmap->lock,flags); - return 0; -} -/* called with dmap->lock dold */ -int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap) -{ - struct audio_operations *adev = audio_devs[dev]; - int err; - - if (!(adev->open_mode & OPEN_READ)) - return 0; - if (!(adev->enable_bits & PCM_ENABLE_INPUT)) - return 0; - if (dmap->dma_mode == DMODE_OUTPUT) { /* Direction change */ - /* release lock - it's not recursive */ - spin_unlock_irq(&dmap->lock); - DMAbuf_sync(dev); - DMAbuf_reset(dev); - spin_lock_irq(&dmap->lock); - dmap->dma_mode = DMODE_NONE; - } - if (!dmap->dma_mode) { - reorganize_buffers(dev, dmap, 1); - if ((err = adev->d->prepare_for_input(dev, - dmap->fragment_size, dmap->nbufs)) < 0) - return err; - dmap->dma_mode = DMODE_INPUT; - } - if (!(dmap->flags & DMA_ACTIVE)) { - if (dmap->needs_reorg) - reorganize_buffers(dev, dmap, 0); - local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ); - adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, - dmap->fragment_size, 0); - dmap->flags |= DMA_ACTIVE; - if (adev->d->trigger) - adev->d->trigger(dev, adev->enable_bits * adev->go); - } - return 0; -} -/* acquires lock */ -int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock) -{ - struct audio_operations *adev = audio_devs[dev]; - unsigned long flags; - int err = 0, n = 0; - struct dma_buffparms *dmap = adev->dmap_in; - int go; - - if (!(adev->open_mode & OPEN_READ)) - return -EIO; - spin_lock_irqsave(&dmap->lock,flags); - if (dmap->needs_reorg) - reorganize_buffers(dev, dmap, 0); - if (adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) { -/* printk(KERN_WARNING "Sound: Can't read from mmapped device (1)\n");*/ - spin_unlock_irqrestore(&dmap->lock,flags); - return -EINVAL; - } else while (dmap->qlen <= 0 && n++ < 10) { - long timeout = MAX_SCHEDULE_TIMEOUT; - if (!(adev->enable_bits & PCM_ENABLE_INPUT) || !adev->go) { - spin_unlock_irqrestore(&dmap->lock,flags); - return -EAGAIN; - } - if ((err = DMAbuf_activate_recording(dev, dmap)) < 0) { - spin_unlock_irqrestore(&dmap->lock,flags); - return err; - } - /* Wait for the next block */ - - if (dontblock) { - spin_unlock_irqrestore(&dmap->lock,flags); - return -EAGAIN; - } - if ((go = adev->go)) - timeout = dmabuf_timeout(dmap); - - spin_unlock_irqrestore(&dmap->lock,flags); - timeout = interruptible_sleep_on_timeout(&adev->in_sleeper, - timeout); - if (!timeout) { - /* FIXME: include device name */ - err = -EIO; - printk(KERN_WARNING "Sound: DMA (input) timed out - IRQ/DRQ config error?\n"); - dma_reset_input(dev); - } else - err = -EINTR; - spin_lock_irqsave(&dmap->lock,flags); - } - spin_unlock_irqrestore(&dmap->lock,flags); - - if (dmap->qlen <= 0) - return err ? err : -EINTR; - *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]]; - *len = dmap->fragment_size - dmap->counts[dmap->qhead]; - - return dmap->qhead; -} - -int DMAbuf_rmchars(int dev, int buff_no, int c) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = adev->dmap_in; - int p = dmap->counts[dmap->qhead] + c; - - if (dmap->mapping_flags & DMA_MAP_MAPPED) - { -/* printk("Sound: Can't read from mmapped device (2)\n");*/ - return -EINVAL; - } - else if (dmap->qlen <= 0) - return -EIO; - else if (p >= dmap->fragment_size) { /* This buffer is completely empty */ - dmap->counts[dmap->qhead] = 0; - dmap->qlen--; - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - } - else dmap->counts[dmap->qhead] = p; - - return 0; -} -/* MUST be called with dmap->lock hold */ -int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction) -{ - /* - * Try to approximate the active byte position of the DMA pointer within the - * buffer area as well as possible. - */ - - int pos; - unsigned long f; - - if (!(dmap->flags & DMA_ACTIVE)) - pos = 0; - else { - int chan = dmap->dma; - - f=claim_dma_lock(); - clear_dma_ff(chan); - - if(!isa_dma_bridge_buggy) - disable_dma(dmap->dma); - - pos = get_dma_residue(chan); - - pos = dmap->bytes_in_use - pos; - - if (!(dmap->mapping_flags & DMA_MAP_MAPPED)) { - if (direction == DMODE_OUTPUT) { - if (dmap->qhead == 0) - if (pos > dmap->fragment_size) - pos = 0; - } else { - if (dmap->qtail == 0) - if (pos > dmap->fragment_size) - pos = 0; - } - } - if (pos < 0) - pos = 0; - if (pos >= dmap->bytes_in_use) - pos = 0; - - if(!isa_dma_bridge_buggy) - enable_dma(dmap->dma); - - release_dma_lock(f); - } - /* printk( "%04x ", pos); */ - - return pos; -} - -/* - * DMAbuf_start_devices() is called by the /dev/music driver to start - * one or more audio devices at desired moment. - */ - -void DMAbuf_start_devices(unsigned int devmask) -{ - struct audio_operations *adev; - int dev; - - for (dev = 0; dev < num_audiodevs; dev++) { - if (!(devmask & (1 << dev))) - continue; - if (!(adev = audio_devs[dev])) - continue; - if (adev->open_mode == 0) - continue; - if (adev->go) - continue; - /* OK to start the device */ - adev->go = 1; - if (adev->d->trigger) - adev->d->trigger(dev,adev->enable_bits * adev->go); - } -} -/* via poll called without a lock ?*/ -int DMAbuf_space_in_queue(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - int len, max, tmp; - struct dma_buffparms *dmap = adev->dmap_out; - int lim = dmap->nbufs; - - if (lim < 2) - lim = 2; - - if (dmap->qlen >= lim) /* No space at all */ - return 0; - - /* - * Verify that there are no more pending buffers than the limit - * defined by the process. - */ - - max = dmap->max_fragments; - if (max > lim) - max = lim; - len = dmap->qlen; - - if (adev->d->local_qlen) { - tmp = adev->d->local_qlen(dev); - if (tmp && len) - tmp--; /* This buffer has been counted twice */ - len += tmp; - } - if (dmap->byte_counter % dmap->fragment_size) /* There is a partial fragment */ - len = len + 1; - - if (len >= max) - return 0; - return max - len; -} -/* MUST not hold the spinlock - this function may sleep */ -static int output_sleep(int dev, int dontblock) -{ - struct audio_operations *adev = audio_devs[dev]; - int err = 0; - struct dma_buffparms *dmap = adev->dmap_out; - long timeout; - long timeout_value; - - if (dontblock) - return -EAGAIN; - if (!(adev->enable_bits & PCM_ENABLE_OUTPUT)) - return -EAGAIN; - - /* - * Wait for free space - */ - if (signal_pending(current)) - return -EINTR; - timeout = (adev->go && !(dmap->flags & DMA_NOTIMEOUT)); - if (timeout) - timeout_value = dmabuf_timeout(dmap); - else - timeout_value = MAX_SCHEDULE_TIMEOUT; - timeout_value = interruptible_sleep_on_timeout(&adev->out_sleeper, - timeout_value); - if (timeout != MAX_SCHEDULE_TIMEOUT && !timeout_value) { - printk(KERN_WARNING "Sound: DMA (output) timed out - IRQ/DRQ config error?\n"); - dma_reset_output(dev); - } else { - if (signal_pending(current)) - err = -EINTR; - } - return err; -} -/* called with the lock held */ -static int find_output_space(int dev, char **buf, int *size) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = adev->dmap_out; - unsigned long active_offs; - long len, offs; - int maxfrags; - int occupied_bytes = (dmap->user_counter % dmap->fragment_size); - - *buf = dmap->raw_buf; - if (!(maxfrags = DMAbuf_space_in_queue(dev)) && !occupied_bytes) - return 0; - -#ifdef BE_CONSERVATIVE - active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size; -#else - active_offs = max(DMAbuf_get_buffer_pointer(dev, dmap, DMODE_OUTPUT), 0); - /* Check for pointer wrapping situation */ - if (active_offs >= dmap->bytes_in_use) - active_offs = 0; - active_offs += dmap->byte_counter; -#endif - - offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP; - if (offs < 0 || offs >= dmap->bytes_in_use) { - printk(KERN_ERR "Sound: Got unexpected offs %ld. Giving up.\n", offs); - printk("Counter = %ld, bytes=%d\n", dmap->user_counter, dmap->bytes_in_use); - return 0; - } - *buf = dmap->raw_buf + offs; - - len = active_offs + dmap->bytes_in_use - dmap->user_counter; /* Number of unused bytes in buffer */ - - if ((offs + len) > dmap->bytes_in_use) - len = dmap->bytes_in_use - offs; - if (len < 0) { - return 0; - } - if (len > ((maxfrags * dmap->fragment_size) - occupied_bytes)) - len = (maxfrags * dmap->fragment_size) - occupied_bytes; - *size = len & ~SAMPLE_ROUNDUP; - return (*size > 0); -} -/* acquires lock */ -int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock) -{ - struct audio_operations *adev = audio_devs[dev]; - unsigned long flags; - int err = -EIO; - struct dma_buffparms *dmap = adev->dmap_out; - - if (dmap->mapping_flags & DMA_MAP_MAPPED) { -/* printk(KERN_DEBUG "Sound: Can't write to mmapped device (3)\n");*/ - return -EINVAL; - } - spin_lock_irqsave(&dmap->lock,flags); - if (dmap->needs_reorg) - reorganize_buffers(dev, dmap, 0); - - if (dmap->dma_mode == DMODE_INPUT) { /* Direction change */ - spin_unlock_irqrestore(&dmap->lock,flags); - DMAbuf_reset(dev); - spin_lock_irqsave(&dmap->lock,flags); - } - dmap->dma_mode = DMODE_OUTPUT; - - while (find_output_space(dev, buf, size) <= 0) { - spin_unlock_irqrestore(&dmap->lock,flags); - if ((err = output_sleep(dev, dontblock)) < 0) { - return err; - } - spin_lock_irqsave(&dmap->lock,flags); - } - - spin_unlock_irqrestore(&dmap->lock,flags); - return 0; -} -/* has to acquire dmap->lock */ -int DMAbuf_move_wrpointer(int dev, int l) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = adev->dmap_out; - unsigned long ptr; - unsigned long end_ptr, p; - int post; - unsigned long flags; - - spin_lock_irqsave(&dmap->lock,flags); - post= (dmap->flags & DMA_POST); - ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; - - dmap->flags &= ~DMA_POST; - dmap->cfrag = -1; - dmap->user_counter += l; - dmap->flags |= DMA_DIRTY; - - if (dmap->byte_counter >= dmap->max_byte_counter) { - /* Wrap the byte counters */ - long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - end_ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; - - p = (dmap->user_counter - 1) % dmap->bytes_in_use; - dmap->neutral_byte = dmap->raw_buf[p]; - - /* Update the fragment based bookkeeping too */ - while (ptr < end_ptr) { - dmap->counts[dmap->qtail] = dmap->fragment_size; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - dmap->qlen++; - ptr += dmap->fragment_size; - } - - dmap->counts[dmap->qtail] = dmap->user_counter - ptr; - - /* - * Let the low level driver perform some postprocessing to - * the written data. - */ - if (adev->d->postprocess_write) - adev->d->postprocess_write(dev); - - if (!(dmap->flags & DMA_ACTIVE)) - if (dmap->qlen > 1 || (dmap->qlen > 0 && (post || dmap->qlen >= dmap->nbufs - 1))) - DMAbuf_launch_output(dev, dmap); - - spin_unlock_irqrestore(&dmap->lock,flags); - return 0; -} - -int DMAbuf_start_dma(int dev, unsigned long physaddr, int count, int dma_mode) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = (dma_mode == DMA_MODE_WRITE) ? adev->dmap_out : adev->dmap_in; - - if (dmap->raw_buf == NULL) { - printk(KERN_ERR "sound: DMA buffer(1) == NULL\n"); - printk("Device %d, chn=%s\n", dev, (dmap == adev->dmap_out) ? "out" : "in"); - return 0; - } - if (dmap->dma < 0) - return 0; - sound_start_dma(dmap, physaddr, count, dma_mode); - return count; -} -EXPORT_SYMBOL(DMAbuf_start_dma); - -static int local_start_dma(struct audio_operations *adev, unsigned long physaddr, int count, int dma_mode) -{ - struct dma_buffparms *dmap = (dma_mode == DMA_MODE_WRITE) ? adev->dmap_out : adev->dmap_in; - - if (dmap->raw_buf == NULL) { - printk(KERN_ERR "sound: DMA buffer(2) == NULL\n"); - printk(KERN_ERR "Device %s, chn=%s\n", adev->name, (dmap == adev->dmap_out) ? "out" : "in"); - return 0; - } - if (dmap->flags & DMA_NODMA) - return 1; - if (dmap->dma < 0) - return 0; - sound_start_dma(dmap, dmap->raw_buf_phys, dmap->bytes_in_use, dma_mode | DMA_AUTOINIT); - dmap->flags |= DMA_STARTED; - return count; -} - -static void finish_output_interrupt(int dev, struct dma_buffparms *dmap) -{ - struct audio_operations *adev = audio_devs[dev]; - - if (dmap->audio_callback != NULL) - dmap->audio_callback(dev, dmap->callback_parm); - wake_up(&adev->out_sleeper); - wake_up(&adev->poll_sleeper); -} -/* called with dmap->lock held in irq context*/ -static void do_outputintr(int dev, int dummy) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = adev->dmap_out; - int this_fragment; - - if (dmap->raw_buf == NULL) { - printk(KERN_ERR "Sound: Error. Audio interrupt (%d) after freeing buffers.\n", dev); - return; - } - if (dmap->mapping_flags & DMA_MAP_MAPPED) { /* Virtual memory mapped access */ - /* mmapped access */ - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - if (dmap->qhead == 0) { /* Wrapped */ - dmap->byte_counter += dmap->bytes_in_use; - if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ - long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - } - dmap->qlen++; /* Yes increment it (don't decrement) */ - if (!(adev->flags & DMA_AUTOMODE)) - dmap->flags &= ~DMA_ACTIVE; - dmap->counts[dmap->qhead] = dmap->fragment_size; - DMAbuf_launch_output(dev, dmap); - finish_output_interrupt(dev, dmap); - return; - } - - dmap->qlen--; - this_fragment = dmap->qhead; - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - - if (dmap->qhead == 0) { /* Wrapped */ - dmap->byte_counter += dmap->bytes_in_use; - if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ - long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use); - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - } - if (!(adev->flags & DMA_AUTOMODE)) - dmap->flags &= ~DMA_ACTIVE; - - /* - * This is dmap->qlen <= 0 except when closing when - * dmap->qlen < 0 - */ - - while (dmap->qlen <= -dmap->closing) { - dmap->underrun_count++; - dmap->qlen++; - if ((dmap->flags & DMA_DIRTY) && dmap->applic_profile != APF_CPUINTENS) { - dmap->flags &= ~DMA_DIRTY; - memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, - adev->dmap_out->buffsize); - } - dmap->user_counter += dmap->fragment_size; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - } - if (dmap->qlen > 0) - DMAbuf_launch_output(dev, dmap); - finish_output_interrupt(dev, dmap); -} -/* called in irq context */ -void DMAbuf_outputintr(int dev, int notify_only) -{ - struct audio_operations *adev = audio_devs[dev]; - unsigned long flags; - struct dma_buffparms *dmap = adev->dmap_out; - - spin_lock_irqsave(&dmap->lock,flags); - if (!(dmap->flags & DMA_NODMA)) { - int chan = dmap->dma, pos, n; - unsigned long f; - - f=claim_dma_lock(); - - if(!isa_dma_bridge_buggy) - disable_dma(dmap->dma); - clear_dma_ff(chan); - pos = dmap->bytes_in_use - get_dma_residue(chan); - if(!isa_dma_bridge_buggy) - enable_dma(dmap->dma); - release_dma_lock(f); - - pos = pos / dmap->fragment_size; /* Actual qhead */ - if (pos < 0 || pos >= dmap->nbufs) - pos = 0; - n = 0; - while (dmap->qhead != pos && n++ < dmap->nbufs) - do_outputintr(dev, notify_only); - } - else - do_outputintr(dev, notify_only); - spin_unlock_irqrestore(&dmap->lock,flags); -} -EXPORT_SYMBOL(DMAbuf_outputintr); - -/* called with dmap->lock held in irq context */ -static void do_inputintr(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = adev->dmap_in; - - if (dmap->raw_buf == NULL) { - printk(KERN_ERR "Sound: Fatal error. Audio interrupt after freeing buffers.\n"); - return; - } - if (dmap->mapping_flags & DMA_MAP_MAPPED) { - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - if (dmap->qtail == 0) { /* Wrapped */ - dmap->byte_counter += dmap->bytes_in_use; - if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ - long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - } - dmap->qlen++; - - if (!(adev->flags & DMA_AUTOMODE)) { - if (dmap->needs_reorg) - reorganize_buffers(dev, dmap, 0); - local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_READ); - adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, - dmap->fragment_size, 1); - if (adev->d->trigger) - adev->d->trigger(dev, adev->enable_bits * adev->go); - } - dmap->flags |= DMA_ACTIVE; - } else if (dmap->qlen >= (dmap->nbufs - 1)) { - printk(KERN_WARNING "Sound: Recording overrun\n"); - dmap->underrun_count++; - - /* Just throw away the oldest fragment but keep the engine running */ - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - } else if (dmap->qlen >= 0 && dmap->qlen < dmap->nbufs) { - dmap->qlen++; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - if (dmap->qtail == 0) { /* Wrapped */ - dmap->byte_counter += dmap->bytes_in_use; - if (dmap->byte_counter >= dmap->max_byte_counter) { /* Overflow */ - long decr = dmap->byte_counter; - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - } - } - if (!(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) { - local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ); - adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, dmap->fragment_size, 1); - if (adev->d->trigger) - adev->d->trigger(dev,adev->enable_bits * adev->go); - } - dmap->flags |= DMA_ACTIVE; - if (dmap->qlen > 0) - { - wake_up(&adev->in_sleeper); - wake_up(&adev->poll_sleeper); - } -} -/* called in irq context */ -void DMAbuf_inputintr(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = adev->dmap_in; - unsigned long flags; - - spin_lock_irqsave(&dmap->lock,flags); - - if (!(dmap->flags & DMA_NODMA)) { - int chan = dmap->dma, pos, n; - unsigned long f; - - f=claim_dma_lock(); - if(!isa_dma_bridge_buggy) - disable_dma(dmap->dma); - clear_dma_ff(chan); - pos = dmap->bytes_in_use - get_dma_residue(chan); - if(!isa_dma_bridge_buggy) - enable_dma(dmap->dma); - release_dma_lock(f); - - pos = pos / dmap->fragment_size; /* Actual qhead */ - if (pos < 0 || pos >= dmap->nbufs) - pos = 0; - - n = 0; - while (dmap->qtail != pos && ++n < dmap->nbufs) - do_inputintr(dev); - } else - do_inputintr(dev); - spin_unlock_irqrestore(&dmap->lock,flags); -} -EXPORT_SYMBOL(DMAbuf_inputintr); - -void DMAbuf_init(int dev, int dma1, int dma2) -{ - struct audio_operations *adev = audio_devs[dev]; - /* - * NOTE! This routine could be called several times. - */ - - if (adev && adev->dmap_out == NULL) { - if (adev->d == NULL) - panic("OSS: audio_devs[%d]->d == NULL\n", dev); - - if (adev->parent_dev) { /* Use DMA map of the parent dev */ - int parent = adev->parent_dev - 1; - adev->dmap_out = audio_devs[parent]->dmap_out; - adev->dmap_in = audio_devs[parent]->dmap_in; - } else { - adev->dmap_out = adev->dmap_in = &adev->dmaps[0]; - adev->dmap_out->dma = dma1; - if (adev->flags & DMA_DUPLEX) { - adev->dmap_in = &adev->dmaps[1]; - adev->dmap_in->dma = dma2; - } - } - /* Persistent DMA buffers allocated here */ - if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) { - if (adev->dmap_in->raw_buf == NULL) - sound_alloc_dmap(adev->dmap_in); - if (adev->dmap_out->raw_buf == NULL) - sound_alloc_dmap(adev->dmap_out); - } - } -} - -/* No kernel lock - DMAbuf_activate_recording protected by global cli/sti */ -static unsigned int poll_input(struct file * file, int dev, poll_table *wait) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = adev->dmap_in; - - if (!(adev->open_mode & OPEN_READ)) - return 0; - if (dmap->mapping_flags & DMA_MAP_MAPPED) { - if (dmap->qlen) - return POLLIN | POLLRDNORM; - return 0; - } - if (dmap->dma_mode != DMODE_INPUT) { - if (dmap->dma_mode == DMODE_NONE && - adev->enable_bits & PCM_ENABLE_INPUT && - !dmap->qlen && adev->go) { - unsigned long flags; - - spin_lock_irqsave(&dmap->lock,flags); - DMAbuf_activate_recording(dev, dmap); - spin_unlock_irqrestore(&dmap->lock,flags); - } - return 0; - } - if (!dmap->qlen) - return 0; - return POLLIN | POLLRDNORM; -} - -static unsigned int poll_output(struct file * file, int dev, poll_table *wait) -{ - struct audio_operations *adev = audio_devs[dev]; - struct dma_buffparms *dmap = adev->dmap_out; - - if (!(adev->open_mode & OPEN_WRITE)) - return 0; - if (dmap->mapping_flags & DMA_MAP_MAPPED) { - if (dmap->qlen) - return POLLOUT | POLLWRNORM; - return 0; - } - if (dmap->dma_mode == DMODE_INPUT) - return 0; - if (dmap->dma_mode == DMODE_NONE) - return POLLOUT | POLLWRNORM; - if (!DMAbuf_space_in_queue(dev)) - return 0; - return POLLOUT | POLLWRNORM; -} - -unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait) -{ - struct audio_operations *adev = audio_devs[dev]; - poll_wait(file, &adev->poll_sleeper, wait); - return poll_input(file, dev, wait) | poll_output(file, dev, wait); -} - -void DMAbuf_deinit(int dev) -{ - struct audio_operations *adev = audio_devs[dev]; - /* This routine is called when driver is being unloaded */ - if (!adev) - return; - - /* Persistent DMA buffers deallocated here */ - if (sound_dmap_flag == DMAP_KEEP_ON_CLOSE) { - sound_free_dmap(adev->dmap_out); - if (adev->flags & DMA_DUPLEX) - sound_free_dmap(adev->dmap_in); - } -} diff --git a/ANDROID_3.4.5/sound/oss/dmasound/Kconfig b/ANDROID_3.4.5/sound/oss/dmasound/Kconfig deleted file mode 100644 index f456574a..00000000 --- a/ANDROID_3.4.5/sound/oss/dmasound/Kconfig +++ /dev/null @@ -1,45 +0,0 @@ -config DMASOUND_ATARI - tristate "Atari DMA sound support" - depends on ATARI && SOUND - select DMASOUND - help - If you want to use the internal audio of your Atari in Linux, answer - Y to this question. This will provide a Sun-like /dev/audio, - compatible with the Linux/i386 sound system. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -config DMASOUND_PAULA - tristate "Amiga DMA sound support" - depends on AMIGA && SOUND - select DMASOUND - help - If you want to use the internal audio of your Amiga in Linux, answer - Y to this question. This will provide a Sun-like /dev/audio, - compatible with the Linux/i386 sound system. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -config DMASOUND_Q40 - tristate "Q40 sound support" - depends on Q40 && SOUND - select DMASOUND - help - If you want to use the internal audio of your Q40 in Linux, answer - Y to this question. This will provide a Sun-like /dev/audio, - compatible with the Linux/i386 sound system. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you - want). If you want to compile it as a module, say M here and read - . - -config DMASOUND - tristate - select SOUND_OSS_CORE diff --git a/ANDROID_3.4.5/sound/oss/dmasound/Makefile b/ANDROID_3.4.5/sound/oss/dmasound/Makefile deleted file mode 100644 index 3c153165..00000000 --- a/ANDROID_3.4.5/sound/oss/dmasound/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for the DMA sound driver -# - -obj-$(CONFIG_DMASOUND_ATARI) += dmasound_core.o dmasound_atari.o -obj-$(CONFIG_DMASOUND_PAULA) += dmasound_core.o dmasound_paula.o -obj-$(CONFIG_DMASOUND_Q40) += dmasound_core.o dmasound_q40.o diff --git a/ANDROID_3.4.5/sound/oss/dmasound/dmasound.h b/ANDROID_3.4.5/sound/oss/dmasound/dmasound.h deleted file mode 100644 index 1308d8d3..00000000 --- a/ANDROID_3.4.5/sound/oss/dmasound/dmasound.h +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef _dmasound_h_ -/* - * linux/sound/oss/dmasound/dmasound.h - * - * - * Minor numbers for the sound driver. - * - * Unfortunately Creative called the codec chip of SB as a DSP. For this - * reason the /dev/dsp is reserved for digitized audio use. There is a - * device for true DSP processors but it will be called something else. - * In v3.0 it's /dev/sndproc but this could be a temporary solution. - */ -#define _dmasound_h_ - -#include - -#define SND_NDEVS 256 /* Number of supported devices */ -#define SND_DEV_CTL 0 /* Control port /dev/mixer */ -#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM - synthesizer and MIDI output) */ -#define SND_DEV_MIDIN 2 /* Raw midi access */ -#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */ -#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */ -#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */ -#define SND_DEV_STATUS 6 /* /dev/sndstat */ -/* #7 not in use now. Was in 2.4. Free for use after v3.0. */ -#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */ -#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */ -#define SND_DEV_PSS SND_DEV_SNDPROC - -/* switch on various prinks */ -#define DEBUG_DMASOUND 1 - -#define MAX_AUDIO_DEV 5 -#define MAX_MIXER_DEV 4 -#define MAX_SYNTH_DEV 3 -#define MAX_MIDI_DEV 6 -#define MAX_TIMER_DEV 3 - -#define MAX_CATCH_RADIUS 10 - -#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) -#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) - -#define IOCTL_IN(arg, ret) \ - do { int error = get_user(ret, (int __user *)(arg)); \ - if (error) return error; \ - } while (0) -#define IOCTL_OUT(arg, ret) ioctl_return((int __user *)(arg), ret) - -static inline int ioctl_return(int __user *addr, int value) -{ - return value < 0 ? value : put_user(value, addr); -} - - - /* - * Configuration - */ - -#undef HAS_8BIT_TABLES - -#if defined(CONFIG_DMASOUND_ATARI) || defined(CONFIG_DMASOUND_ATARI_MODULE) ||\ - defined(CONFIG_DMASOUND_PAULA) || defined(CONFIG_DMASOUND_PAULA_MODULE) ||\ - defined(CONFIG_DMASOUND_Q40) || defined(CONFIG_DMASOUND_Q40_MODULE) -#define HAS_8BIT_TABLES -#define MIN_BUFFERS 4 -#define MIN_BUFSIZE (1<<12) /* in bytes (- where does this come from ?) */ -#define MIN_FRAG_SIZE 8 /* not 100% sure about this */ -#define MAX_BUFSIZE (1<<17) /* Limit for Amiga is 128 kb */ -#define MAX_FRAG_SIZE 15 /* allow *4 for mono-8 => stereo-16 (for multi) */ - -#else /* is pmac and multi is off */ - -#define MIN_BUFFERS 2 -#define MIN_BUFSIZE (1<<8) /* in bytes */ -#define MIN_FRAG_SIZE 8 -#define MAX_BUFSIZE (1<<18) /* this is somewhat arbitrary for pmac */ -#define MAX_FRAG_SIZE 16 /* need to allow *4 for mono-8 => stereo-16 */ -#endif - -#define DEFAULT_N_BUFFERS 4 -#define DEFAULT_BUFF_SIZE (1<<15) - - /* - * Initialization - */ - -extern int dmasound_init(void); -#ifdef MODULE -extern void dmasound_deinit(void); -#else -#define dmasound_deinit() do { } while (0) -#endif - -/* description of the set-up applies to either hard or soft settings */ - -typedef struct { - int format; /* AFMT_* */ - int stereo; /* 0 = mono, 1 = stereo */ - int size; /* 8/16 bit*/ - int speed; /* speed */ -} SETTINGS; - - /* - * Machine definitions - */ - -typedef struct { - const char *name; - const char *name2; - struct module *owner; - void *(*dma_alloc)(unsigned int, gfp_t); - void (*dma_free)(void *, unsigned int); - int (*irqinit)(void); -#ifdef MODULE - void (*irqcleanup)(void); -#endif - void (*init)(void); - void (*silence)(void); - int (*setFormat)(int); - int (*setVolume)(int); - int (*setBass)(int); - int (*setTreble)(int); - int (*setGain)(int); - void (*play)(void); - void (*record)(void); /* optional */ - void (*mixer_init)(void); /* optional */ - int (*mixer_ioctl)(u_int, u_long); /* optional */ - int (*write_sq_setup)(void); /* optional */ - int (*read_sq_setup)(void); /* optional */ - int (*sq_open)(fmode_t); /* optional */ - int (*state_info)(char *, size_t); /* optional */ - void (*abort_read)(void); /* optional */ - int min_dsp_speed; - int max_dsp_speed; - int version ; - int hardware_afmts ; /* OSS says we only return h'ware info */ - /* when queried via SNDCTL_DSP_GETFMTS */ - int capabilities ; /* low-level reply to SNDCTL_DSP_GETCAPS */ - SETTINGS default_hard ; /* open() or init() should set something valid */ - SETTINGS default_soft ; /* you can make it look like old OSS, if you want to */ -} MACHINE; - - /* - * Low level stuff - */ - -typedef struct { - ssize_t (*ct_ulaw)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_alaw)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s8)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u8)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16be)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16be)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16le)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16le)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); -} TRANS; - -struct sound_settings { - MACHINE mach; /* machine dependent things */ - SETTINGS hard; /* hardware settings */ - SETTINGS soft; /* software settings */ - SETTINGS dsp; /* /dev/dsp default settings */ - TRANS *trans_write; /* supported translations */ - int volume_left; /* volume (range is machine dependent) */ - int volume_right; - int bass; /* tone (range is machine dependent) */ - int treble; - int gain; - int minDev; /* minor device number currently open */ - spinlock_t lock; -}; - -extern struct sound_settings dmasound; - -#ifdef HAS_8BIT_TABLES -extern char dmasound_ulaw2dma8[]; -extern char dmasound_alaw2dma8[]; -#endif - - /* - * Mid level stuff - */ - -static inline int dmasound_set_volume(int volume) -{ - return dmasound.mach.setVolume(volume); -} - -static inline int dmasound_set_bass(int bass) -{ - return dmasound.mach.setBass ? dmasound.mach.setBass(bass) : 50; -} - -static inline int dmasound_set_treble(int treble) -{ - return dmasound.mach.setTreble ? dmasound.mach.setTreble(treble) : 50; -} - -static inline int dmasound_set_gain(int gain) -{ - return dmasound.mach.setGain ? dmasound.mach.setGain(gain) : 100; -} - - - /* - * Sound queue stuff, the heart of the driver - */ - -struct sound_queue { - /* buffers allocated for this queue */ - int numBufs; /* real limits on what the user can have */ - int bufSize; /* in bytes */ - char **buffers; - - /* current parameters */ - int locked ; /* params cannot be modified when != 0 */ - int user_frags ; /* user requests this many */ - int user_frag_size ; /* of this size */ - int max_count; /* actual # fragments <= numBufs */ - int block_size; /* internal block size in bytes */ - int max_active; /* in-use fragments <= max_count */ - - /* it shouldn't be necessary to declare any of these volatile */ - int front, rear, count; - int rear_size; - /* - * The use of the playing field depends on the hardware - * - * Atari, PMac: The number of frames that are loaded/playing - * - * Amiga: Bit 0 is set: a frame is loaded - * Bit 1 is set: a frame is playing - */ - int active; - wait_queue_head_t action_queue, open_queue, sync_queue; - int non_blocking; - int busy, syncing, xruns, died; -}; - -#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ) -#define WAKE_UP(queue) (wake_up_interruptible(&queue)) - -extern struct sound_queue dmasound_write_sq; -#define write_sq dmasound_write_sq - -extern int dmasound_catchRadius; -#define catchRadius dmasound_catchRadius - -/* define the value to be put in the byte-swap reg in mac-io - when we want it to swap for us. -*/ -#define BS_VAL 1 - -#define SW_INPUT_VOLUME_SCALE 4 -#define SW_INPUT_VOLUME_DEFAULT (128 / SW_INPUT_VOLUME_SCALE) - -extern int expand_read_bal; /* Balance factor for reading */ -extern uint software_input_volume; /* software implemented recording volume! */ - -#endif /* _dmasound_h_ */ diff --git a/ANDROID_3.4.5/sound/oss/dmasound/dmasound_atari.c b/ANDROID_3.4.5/sound/oss/dmasound/dmasound_atari.c deleted file mode 100644 index 13c21446..00000000 --- a/ANDROID_3.4.5/sound/oss/dmasound/dmasound_atari.c +++ /dev/null @@ -1,1620 +0,0 @@ -/* - * linux/sound/oss/dmasound/dmasound_atari.c - * - * Atari TT and Falcon DMA Sound Driver - * - * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits - * prior to 28/01/2001 - * - * 28/01/2001 [0.1] Iain Sandoe - * - added versioning - * - put in and populated the hardware_afmts field. - * [0.2] - put in SNDCTL_DSP_GETCAPS value. - * 01/02/2001 [0.3] - put in default hard/soft settings. - */ - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "dmasound.h" - -#define DMASOUND_ATARI_REVISION 0 -#define DMASOUND_ATARI_EDITION 3 - -extern void atari_microwire_cmd(int cmd); - -static int is_falcon; -static int write_sq_ignore_int; /* ++TeSche: used for Falcon */ - -static int expand_bal; /* Balance factor for expanding (not volume!) */ -static int expand_data; /* Data for expanding */ - - -/*** Translations ************************************************************/ - - -/* ++TeSche: radically changed for new expanding purposes... - * - * These two routines now deal with copying/expanding/translating the samples - * from user space into our buffer at the right frequency. They take care about - * how much data there's actually to read, how much buffer space there is and - * to convert samples into the right frequency/encoding. They will only work on - * complete samples so it may happen they leave some bytes in the input stream - * if the user didn't write a multiple of the current sample size. They both - * return the number of bytes they've used from both streams so you may detect - * such a situation. Luckily all programs should be able to cope with that. - * - * I think I've optimized anything as far as one can do in plain C, all - * variables should fit in registers and the loops are really short. There's - * one loop for every possible situation. Writing a more generalized and thus - * parameterized loop would only produce slower code. Feel free to optimize - * this in assembler if you like. :) - * - * I think these routines belong here because they're not yet really hardware - * independent, especially the fact that the Falcon can play 16bit samples - * only in stereo is hardcoded in both of them! - * - * ++geert: split in even more functions (one per format) - */ - -static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); - - -/*** Low level stuff *********************************************************/ - - -static void *AtaAlloc(unsigned int size, gfp_t flags); -static void AtaFree(void *, unsigned int size); -static int AtaIrqInit(void); -#ifdef MODULE -static void AtaIrqCleanUp(void); -#endif /* MODULE */ -static int AtaSetBass(int bass); -static int AtaSetTreble(int treble); -static void TTSilence(void); -static void TTInit(void); -static int TTSetFormat(int format); -static int TTSetVolume(int volume); -static int TTSetGain(int gain); -static void FalconSilence(void); -static void FalconInit(void); -static int FalconSetFormat(int format); -static int FalconSetVolume(int volume); -static void AtaPlayNextFrame(int index); -static void AtaPlay(void); -static irqreturn_t AtaInterrupt(int irq, void *dummy); - -/*** Mid level stuff *********************************************************/ - -static void TTMixerInit(void); -static void FalconMixerInit(void); -static int AtaMixerIoctl(u_int cmd, u_long arg); -static int TTMixerIoctl(u_int cmd, u_long arg); -static int FalconMixerIoctl(u_int cmd, u_long arg); -static int AtaWriteSqSetup(void); -static int AtaSqOpen(fmode_t mode); -static int TTStateInfo(char *buffer, size_t space); -static int FalconStateInfo(char *buffer, size_t space); - - -/*** Translations ************************************************************/ - - -static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8 - : dmasound_alaw2dma8; - ssize_t count, used; - u_char *p = &frame[*frameUsed]; - - count = min_t(unsigned long, userCount, frameLeft); - if (dmasound.soft.stereo) - count &= ~1; - used = count; - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - *p++ = table[data]; - count--; - } - *frameUsed += used; - return used; -} - - -static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - void *p = &frame[*frameUsed]; - - count = min_t(unsigned long, userCount, frameLeft); - if (dmasound.soft.stereo) - count &= ~1; - used = count; - if (copy_from_user(p, userPtr, count)) - return -EFAULT; - *frameUsed += used; - return used; -} - - -static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - if (!dmasound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft); - used = count; - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) - return -EFAULT; - *p++ = data ^ 0x80; - count--; - } - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - *p++ = data ^ 0x8080; - count--; - } - } - *frameUsed += used; - return used; -} - - -static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - if (!dmasound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - void *p = (u_short *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft) & ~3; - used = count; - if (copy_from_user(p, userPtr, count)) - return -EFAULT; - *frameUsed += used; - } - return used; -} - - -static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - if (!dmasound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - data ^= 0x8000; - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft)>>2; - used = count*4; - while (count > 0) { - u_int data; - if (get_user(data, (u_int __user *)userPtr)) - return -EFAULT; - userPtr += 4; - *p++ = data ^ 0x80008000; - count--; - } - *frameUsed += used; - } - return used; -} - - -static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - count = frameLeft; - if (!dmasound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - data = le2be16(data); - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft)>>2; - used = count*4; - while (count > 0) { - u_long data; - if (get_user(data, (u_int __user *)userPtr)) - return -EFAULT; - userPtr += 4; - data = le2be16dbl(data); - *p++ = data; - count--; - } - *frameUsed += used; - } - return used; -} - - -static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - - count = frameLeft; - if (!dmasound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft)>>1; - used = count*2; - while (count > 0) { - u_short data; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - data = le2be16(data) ^ 0x8000; - *p++ = data; - *p++ = data; - } - *frameUsed += used*2; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft)>>2; - used = count; - while (count > 0) { - u_long data; - if (get_user(data, (u_int __user *)userPtr)) - return -EFAULT; - userPtr += 4; - data = le2be16dbl(data) ^ 0x80008000; - *p++ = data; - count--; - } - *frameUsed += used; - } - return used; -} - - -static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8 - : dmasound_alaw2dma8; - /* this should help gcc to stuff everything into registers */ - long bal = expand_bal; - long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!dmasound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - u_char data = expand_data; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (!userCount) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = table[c]; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_data = data; - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = expand_data; - while (frameLeft >= 2) { - u_char c; - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = table[c] << 8; - if (get_user(c, userPtr++)) - return -EFAULT; - data |= table[c]; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - expand_data = data; - } - expand_bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return used; -} - - -static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = expand_bal; - long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!dmasound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - u_char data = expand_data; - while (frameLeft) { - if (bal < 0) { - if (!userCount) - break; - if (get_user(data, userPtr++)) - return -EFAULT; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_data = data; - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = expand_data; - while (frameLeft >= 2) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - expand_data = data; - } - expand_bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return used; -} - - -static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = expand_bal; - long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!dmasound.soft.stereo) { - u_char *p = &frame[*frameUsed]; - u_char data = expand_data; - while (frameLeft) { - if (bal < 0) { - if (!userCount) - break; - if (get_user(data, userPtr++)) - return -EFAULT; - data ^= 0x80; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_data = data; - } else { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = expand_data; - while (frameLeft >= 2) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - data ^= 0x8080; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - expand_data = data; - } - expand_bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return used; -} - - -static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = expand_bal; - long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!dmasound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = expand_data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - expand_data = data; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - u_long data = expand_data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - if (get_user(data, (u_int __user *)userPtr)) - return -EFAULT; - userPtr += 4; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - expand_data = data; - } - expand_bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return used; -} - - -static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = expand_bal; - long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!dmasound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = expand_data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - data ^= 0x8000; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - expand_data = data; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - u_long data = expand_data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - if (get_user(data, (u_int __user *)userPtr)) - return -EFAULT; - userPtr += 4; - data ^= 0x80008000; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - expand_data = data; - } - expand_bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return used; -} - - -static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = expand_bal; - long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!dmasound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = expand_data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - data = le2be16(data); - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - expand_data = data; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - u_long data = expand_data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - if (get_user(data, (u_int __user *)userPtr)) - return -EFAULT; - userPtr += 4; - data = le2be16dbl(data); - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - expand_data = data; - } - expand_bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return used; -} - - -static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - long bal = expand_bal; - long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - ssize_t used, usedf; - - used = userCount; - usedf = frameLeft; - if (!dmasound.soft.stereo) { - u_short *p = (u_short *)&frame[*frameUsed]; - u_short data = expand_data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 2) - break; - if (get_user(data, (u_short __user *)userPtr)) - return -EFAULT; - userPtr += 2; - data = le2be16(data) ^ 0x8000; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - expand_data = data; - } else { - u_long *p = (u_long *)&frame[*frameUsed]; - u_long data = expand_data; - while (frameLeft >= 4) { - if (bal < 0) { - if (userCount < 4) - break; - if (get_user(data, (u_int __user *)userPtr)) - return -EFAULT; - userPtr += 4; - data = le2be16dbl(data) ^ 0x80008000; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - expand_data = data; - } - expand_bal = bal; - used -= userCount; - *frameUsed += usedf-frameLeft; - return used; -} - - -static TRANS transTTNormal = { - .ct_ulaw = ata_ct_law, - .ct_alaw = ata_ct_law, - .ct_s8 = ata_ct_s8, - .ct_u8 = ata_ct_u8, -}; - -static TRANS transTTExpanding = { - .ct_ulaw = ata_ctx_law, - .ct_alaw = ata_ctx_law, - .ct_s8 = ata_ctx_s8, - .ct_u8 = ata_ctx_u8, -}; - -static TRANS transFalconNormal = { - .ct_ulaw = ata_ct_law, - .ct_alaw = ata_ct_law, - .ct_s8 = ata_ct_s8, - .ct_u8 = ata_ct_u8, - .ct_s16be = ata_ct_s16be, - .ct_u16be = ata_ct_u16be, - .ct_s16le = ata_ct_s16le, - .ct_u16le = ata_ct_u16le -}; - -static TRANS transFalconExpanding = { - .ct_ulaw = ata_ctx_law, - .ct_alaw = ata_ctx_law, - .ct_s8 = ata_ctx_s8, - .ct_u8 = ata_ctx_u8, - .ct_s16be = ata_ctx_s16be, - .ct_u16be = ata_ctx_u16be, - .ct_s16le = ata_ctx_s16le, - .ct_u16le = ata_ctx_u16le, -}; - - -/*** Low level stuff *********************************************************/ - - - -/* - * Atari (TT/Falcon) - */ - -static void *AtaAlloc(unsigned int size, gfp_t flags) -{ - return atari_stram_alloc(size, "dmasound"); -} - -static void AtaFree(void *obj, unsigned int size) -{ - atari_stram_free( obj ); -} - -static int __init AtaIrqInit(void) -{ - /* Set up timer A. Timer A - will receive a signal upon end of playing from the sound - hardware. Furthermore Timer A is able to count events - and will cause an interrupt after a programmed number - of events. So all we need to keep the music playing is - to provide the sound hardware with new data upon - an interrupt from timer A. */ - st_mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */ - st_mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ - st_mfp.tim_ct_a = 8; /* Turn on event counting. */ - /* Register interrupt handler. */ - if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound", - AtaInterrupt)) - return 0; - st_mfp.int_en_a |= 0x20; /* Turn interrupt on. */ - st_mfp.int_mk_a |= 0x20; - return 1; -} - -#ifdef MODULE -static void AtaIrqCleanUp(void) -{ - st_mfp.tim_ct_a = 0; /* stop timer */ - st_mfp.int_en_a &= ~0x20; /* turn interrupt off */ - free_irq(IRQ_MFP_TIMA, AtaInterrupt); -} -#endif /* MODULE */ - - -#define TONE_VOXWARE_TO_DB(v) \ - (((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25) -#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50) - - -static int AtaSetBass(int bass) -{ - dmasound.bass = TONE_VOXWARE_TO_DB(bass); - atari_microwire_cmd(MW_LM1992_BASS(dmasound.bass)); - return TONE_DB_TO_VOXWARE(dmasound.bass); -} - - -static int AtaSetTreble(int treble) -{ - dmasound.treble = TONE_VOXWARE_TO_DB(treble); - atari_microwire_cmd(MW_LM1992_TREBLE(dmasound.treble)); - return TONE_DB_TO_VOXWARE(dmasound.treble); -} - - - -/* - * TT - */ - - -static void TTSilence(void) -{ - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */ -} - - -static void TTInit(void) -{ - int mode, i, idx; - const int freq[4] = {50066, 25033, 12517, 6258}; - - /* search a frequency that fits into the allowed error range */ - - idx = -1; - for (i = 0; i < ARRAY_SIZE(freq); i++) - /* this isn't as much useful for a TT than for a Falcon, but - * then it doesn't hurt very much to implement it for a TT too. - */ - if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius) - idx = i; - if (idx > -1) { - dmasound.soft.speed = freq[idx]; - dmasound.trans_write = &transTTNormal; - } else - dmasound.trans_write = &transTTExpanding; - - TTSilence(); - dmasound.hard = dmasound.soft; - - if (dmasound.hard.speed > 50066) { - /* we would need to squeeze the sound, but we won't do that */ - dmasound.hard.speed = 50066; - mode = DMASND_MODE_50KHZ; - dmasound.trans_write = &transTTNormal; - } else if (dmasound.hard.speed > 25033) { - dmasound.hard.speed = 50066; - mode = DMASND_MODE_50KHZ; - } else if (dmasound.hard.speed > 12517) { - dmasound.hard.speed = 25033; - mode = DMASND_MODE_25KHZ; - } else if (dmasound.hard.speed > 6258) { - dmasound.hard.speed = 12517; - mode = DMASND_MODE_12KHZ; - } else { - dmasound.hard.speed = 6258; - mode = DMASND_MODE_6KHZ; - } - - tt_dmasnd.mode = (dmasound.hard.stereo ? - DMASND_MODE_STEREO : DMASND_MODE_MONO) | - DMASND_MODE_8BIT | mode; - - expand_bal = -dmasound.soft.speed; -} - - -static int TTSetFormat(int format) -{ - /* TT sound DMA supports only 8bit modes */ - - switch (format) { - case AFMT_QUERY: - return dmasound.soft.format; - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_S8: - case AFMT_U8: - break; - default: - format = AFMT_S8; - } - - dmasound.soft.format = format; - dmasound.soft.size = 8; - if (dmasound.minDev == SND_DEV_DSP) { - dmasound.dsp.format = format; - dmasound.dsp.size = 8; - } - TTInit(); - - return format; -} - - -#define VOLUME_VOXWARE_TO_DB(v) \ - (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40) -#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2) - - -static int TTSetVolume(int volume) -{ - dmasound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff); - atari_microwire_cmd(MW_LM1992_BALLEFT(dmasound.volume_left)); - dmasound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8); - atari_microwire_cmd(MW_LM1992_BALRIGHT(dmasound.volume_right)); - return VOLUME_DB_TO_VOXWARE(dmasound.volume_left) | - (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8); -} - - -#define GAIN_VOXWARE_TO_DB(v) \ - (((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80) -#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4) - -static int TTSetGain(int gain) -{ - dmasound.gain = GAIN_VOXWARE_TO_DB(gain); - atari_microwire_cmd(MW_LM1992_VOLUME(dmasound.gain)); - return GAIN_DB_TO_VOXWARE(dmasound.gain); -} - - - -/* - * Falcon - */ - - -static void FalconSilence(void) -{ - /* stop playback, set sample rate 50kHz for PSG sound */ - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT; - tt_dmasnd.int_div = 0; /* STE compatible divider */ - tt_dmasnd.int_ctrl = 0x0; - tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */ - tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */ - tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */ - tt_dmasnd.adc_src = 3; /* ADC Input = PSG */ -} - - -static void FalconInit(void) -{ - int divider, i, idx; - const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195}; - - /* search a frequency that fits into the allowed error range */ - - idx = -1; - for (i = 0; i < ARRAY_SIZE(freq); i++) - /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would - * be playable without expanding, but that now a kernel runtime - * option - */ - if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius) - idx = i; - if (idx > -1) { - dmasound.soft.speed = freq[idx]; - dmasound.trans_write = &transFalconNormal; - } else - dmasound.trans_write = &transFalconExpanding; - - FalconSilence(); - dmasound.hard = dmasound.soft; - - if (dmasound.hard.size == 16) { - /* the Falcon can play 16bit samples only in stereo */ - dmasound.hard.stereo = 1; - } - - if (dmasound.hard.speed > 49170) { - /* we would need to squeeze the sound, but we won't do that */ - dmasound.hard.speed = 49170; - divider = 1; - dmasound.trans_write = &transFalconNormal; - } else if (dmasound.hard.speed > 32780) { - dmasound.hard.speed = 49170; - divider = 1; - } else if (dmasound.hard.speed > 24585) { - dmasound.hard.speed = 32780; - divider = 2; - } else if (dmasound.hard.speed > 19668) { - dmasound.hard.speed = 24585; - divider = 3; - } else if (dmasound.hard.speed > 16390) { - dmasound.hard.speed = 19668; - divider = 4; - } else if (dmasound.hard.speed > 12292) { - dmasound.hard.speed = 16390; - divider = 5; - } else if (dmasound.hard.speed > 9834) { - dmasound.hard.speed = 12292; - divider = 7; - } else if (dmasound.hard.speed > 8195) { - dmasound.hard.speed = 9834; - divider = 9; - } else { - dmasound.hard.speed = 8195; - divider = 11; - } - tt_dmasnd.int_div = divider; - - /* Setup Falcon sound DMA for playback */ - tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */ - tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */ - tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */ - tt_dmasnd.cbar_dst = 0x0000; - tt_dmasnd.rec_track_select = 0; - tt_dmasnd.dac_src = 2; /* connect matrix to DAC */ - tt_dmasnd.adc_src = 0; /* ADC Input = Mic */ - - tt_dmasnd.mode = (dmasound.hard.stereo ? - DMASND_MODE_STEREO : DMASND_MODE_MONO) | - ((dmasound.hard.size == 8) ? - DMASND_MODE_8BIT : DMASND_MODE_16BIT) | - DMASND_MODE_6KHZ; - - expand_bal = -dmasound.soft.speed; -} - - -static int FalconSetFormat(int format) -{ - int size; - /* Falcon sound DMA supports 8bit and 16bit modes */ - - switch (format) { - case AFMT_QUERY: - return dmasound.soft.format; - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - size = 8; - format = AFMT_S8; - } - - dmasound.soft.format = format; - dmasound.soft.size = size; - if (dmasound.minDev == SND_DEV_DSP) { - dmasound.dsp.format = format; - dmasound.dsp.size = dmasound.soft.size; - } - - FalconInit(); - - return format; -} - - -/* This is for the Falcon output *attenuation* in 1.5dB steps, - * i.e. output level from 0 to -22.5dB in -1.5dB steps. - */ -#define VOLUME_VOXWARE_TO_ATT(v) \ - ((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20) -#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3) - - -static int FalconSetVolume(int volume) -{ - dmasound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff); - dmasound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8); - tt_dmasnd.output_atten = dmasound.volume_left << 8 | dmasound.volume_right << 4; - return VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) | - VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8; -} - - -static void AtaPlayNextFrame(int index) -{ - char *start, *end; - - /* used by AtaPlay() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = write_sq.buffers[write_sq.front]; - end = start+((write_sq.count == index) ? write_sq.rear_size - : write_sq.block_size); - /* end might not be a legal virtual address. */ - DMASNDSetEnd(virt_to_phys(end - 1) + 1); - DMASNDSetBase(virt_to_phys(start)); - /* Since only an even number of samples per frame can - be played, we might lose one byte here. (TO DO) */ - write_sq.front = (write_sq.front+1) % write_sq.max_count; - write_sq.active++; - tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT; -} - - -static void AtaPlay(void) -{ - /* ++TeSche: Note that write_sq.active is no longer just a flag but - * holds the number of frames the DMA is currently programmed for - * instead, may be 0, 1 (currently being played) or 2 (pre-programmed). - * - * Changes done to write_sq.count and write_sq.active are a bit more - * subtle again so now I must admit I also prefer disabling the irq - * here rather than considering all possible situations. But the point - * is that disabling the irq doesn't have any bad influence on this - * version of the driver as we benefit from having pre-programmed the - * DMA wherever possible: There's no need to reload the DMA at the - * exact time of an interrupt but only at some time while the - * pre-programmed frame is playing! - */ - atari_disable_irq(IRQ_MFP_TIMA); - - if (write_sq.active == 2 || /* DMA is 'full' */ - write_sq.count <= 0) { /* nothing to do */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - - if (write_sq.active == 0) { - /* looks like there's nothing 'in' the DMA yet, so try - * to put two frames into it (at least one is available). - */ - if (write_sq.count == 1 && - write_sq.rear_size < write_sq.block_size && - !write_sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - AtaPlayNextFrame(1); - if (write_sq.count == 1) { - /* no more frames */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - if (write_sq.count == 2 && - write_sq.rear_size < write_sq.block_size && - !write_sq.syncing) { - /* hmmm, there were two frames, but the second - * one is not yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - AtaPlayNextFrame(2); - } else { - /* there's already a frame being played so we may only stuff - * one new into the DMA, but even if this may be the last - * frame existing the previous one is still on write_sq.count. - */ - if (write_sq.count == 2 && - write_sq.rear_size < write_sq.block_size && - !write_sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - AtaPlayNextFrame(2); - } - atari_enable_irq(IRQ_MFP_TIMA); -} - - -static irqreturn_t AtaInterrupt(int irq, void *dummy) -{ -#if 0 - /* ++TeSche: if you should want to test this... */ - static int cnt; - if (write_sq.active == 2) - if (++cnt == 10) { - /* simulate losing an interrupt */ - cnt = 0; - return IRQ_HANDLED; - } -#endif - spin_lock(&dmasound.lock); - if (write_sq_ignore_int && is_falcon) { - /* ++TeSche: Falcon only: ignore first irq because it comes - * immediately after starting a frame. after that, irqs come - * (almost) like on the TT. - */ - write_sq_ignore_int = 0; - goto out; - } - - if (!write_sq.active) { - /* playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(write_sq.sync_queue); - goto out; - } - - /* Probably ;) one frame is finished. Well, in fact it may be that a - * pre-programmed one is also finished because there has been a long - * delay in interrupt delivery and we've completely lost one, but - * there's no way to detect such a situation. In such a case the last - * frame will be played more than once and the situation will recover - * as soon as the irq gets through. - */ - write_sq.count--; - write_sq.active--; - - if (!write_sq.active) { - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - write_sq_ignore_int = 1; - } - - WAKE_UP(write_sq.action_queue); - /* At least one block of the queue is free now - so wake up a writing process blocked because - of a full queue. */ - - if ((write_sq.active != 1) || (write_sq.count != 1)) - /* We must be a bit carefully here: write_sq.count indicates the - * number of buffers used and not the number of frames to be - * played. If write_sq.count==1 and write_sq.active==1 that - * means the only remaining frame was already programmed - * earlier (and is currently running) so we mustn't call - * AtaPlay() here, otherwise we'll play one frame too much. - */ - AtaPlay(); - - if (!write_sq.active) WAKE_UP(write_sq.sync_queue); - /* We are not playing after AtaPlay(), so there - is nothing to play any more. Wake up a process - waiting for audio output to drain. */ -out: - spin_unlock(&dmasound.lock); - return IRQ_HANDLED; -} - - -/*** Mid level stuff *********************************************************/ - - -/* - * /dev/mixer abstraction - */ - -#define RECLEVEL_VOXWARE_TO_GAIN(v) \ - ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20) -#define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3) - - -static void __init TTMixerInit(void) -{ - atari_microwire_cmd(MW_LM1992_VOLUME(0)); - dmasound.volume_left = 0; - atari_microwire_cmd(MW_LM1992_BALLEFT(0)); - dmasound.volume_right = 0; - atari_microwire_cmd(MW_LM1992_BALRIGHT(0)); - atari_microwire_cmd(MW_LM1992_TREBLE(0)); - atari_microwire_cmd(MW_LM1992_BASS(0)); -} - -static void __init FalconMixerInit(void) -{ - dmasound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8; - dmasound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4; -} - -static int AtaMixerIoctl(u_int cmd, u_long arg) -{ - int data; - unsigned long flags; - switch (cmd) { - case SOUND_MIXER_READ_SPEAKER: - if (is_falcon || MACH_IS_TT) { - int porta; - spin_lock_irqsave(&dmasound.lock, flags); - sound_ym.rd_data_reg_sel = 14; - porta = sound_ym.rd_data_reg_sel; - spin_unlock_irqrestore(&dmasound.lock, flags); - return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100); - } - break; - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, dmasound_set_volume(data)); - case SOUND_MIXER_WRITE_SPEAKER: - if (is_falcon || MACH_IS_TT) { - int porta; - IOCTL_IN(arg, data); - spin_lock_irqsave(&dmasound.lock, flags); - sound_ym.rd_data_reg_sel = 14; - porta = (sound_ym.rd_data_reg_sel & ~0x40) | - (data < 50 ? 0x40 : 0); - sound_ym.wd_data = porta; - spin_unlock_irqrestore(&dmasound.lock, flags); - return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100); - } - } - return -EINVAL; -} - - -static int TTMixerIoctl(u_int cmd, u_long arg) -{ - int data; - switch (cmd) { - case SOUND_MIXER_READ_RECMASK: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_DEVMASK: - return IOCTL_OUT(arg, - SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS | - (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0)); - case SOUND_MIXER_READ_STEREODEVS: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME); - case SOUND_MIXER_READ_VOLUME: - return IOCTL_OUT(arg, - VOLUME_DB_TO_VOXWARE(dmasound.volume_left) | - (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8)); - case SOUND_MIXER_READ_BASS: - return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.bass)); - case SOUND_MIXER_READ_TREBLE: - return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.treble)); - case SOUND_MIXER_READ_OGAIN: - return IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(dmasound.gain)); - case SOUND_MIXER_WRITE_BASS: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, dmasound_set_bass(data)); - case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, dmasound_set_treble(data)); - case SOUND_MIXER_WRITE_OGAIN: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, dmasound_set_gain(data)); - } - return AtaMixerIoctl(cmd, arg); -} - -static int FalconMixerIoctl(u_int cmd, u_long arg) -{ - int data; - switch (cmd) { - case SOUND_MIXER_READ_RECMASK: - return IOCTL_OUT(arg, SOUND_MASK_MIC); - case SOUND_MIXER_READ_DEVMASK: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER); - case SOUND_MIXER_READ_STEREODEVS: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC); - case SOUND_MIXER_READ_VOLUME: - return IOCTL_OUT(arg, - VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) | - VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8); - case SOUND_MIXER_READ_CAPS: - return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT); - case SOUND_MIXER_WRITE_MIC: - IOCTL_IN(arg, data); - tt_dmasnd.input_gain = - RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | - RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); - /* fall thru, return set value */ - case SOUND_MIXER_READ_MIC: - return IOCTL_OUT(arg, - RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | - RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8); - } - return AtaMixerIoctl(cmd, arg); -} - -static int AtaWriteSqSetup(void) -{ - write_sq_ignore_int = 0; - return 0 ; -} - -static int AtaSqOpen(fmode_t mode) -{ - write_sq_ignore_int = 1; - return 0 ; -} - -static int TTStateInfo(char *buffer, size_t space) -{ - int len = 0; - len += sprintf(buffer+len, "\tvol left %ddB [-40... 0]\n", - dmasound.volume_left); - len += sprintf(buffer+len, "\tvol right %ddB [-40... 0]\n", - dmasound.volume_right); - len += sprintf(buffer+len, "\tbass %ddB [-12...+12]\n", - dmasound.bass); - len += sprintf(buffer+len, "\ttreble %ddB [-12...+12]\n", - dmasound.treble); - if (len >= space) { - printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ; - len = space ; - } - return len; -} - -static int FalconStateInfo(char *buffer, size_t space) -{ - int len = 0; - len += sprintf(buffer+len, "\tvol left %ddB [-22.5 ... 0]\n", - dmasound.volume_left); - len += sprintf(buffer+len, "\tvol right %ddB [-22.5 ... 0]\n", - dmasound.volume_right); - if (len >= space) { - printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ; - len = space ; - } - return len; -} - - -/*** Machine definitions *****************************************************/ - -static SETTINGS def_hard_falcon = { - .format = AFMT_S8, - .stereo = 0, - .size = 8, - .speed = 8195 -} ; - -static SETTINGS def_hard_tt = { - .format = AFMT_S8, - .stereo = 0, - .size = 8, - .speed = 12517 -} ; - -static SETTINGS def_soft = { - .format = AFMT_U8, - .stereo = 0, - .size = 8, - .speed = 8000 -} ; - -static __initdata MACHINE machTT = { - .name = "Atari", - .name2 = "TT", - .owner = THIS_MODULE, - .dma_alloc = AtaAlloc, - .dma_free = AtaFree, - .irqinit = AtaIrqInit, -#ifdef MODULE - .irqcleanup = AtaIrqCleanUp, -#endif /* MODULE */ - .init = TTInit, - .silence = TTSilence, - .setFormat = TTSetFormat, - .setVolume = TTSetVolume, - .setBass = AtaSetBass, - .setTreble = AtaSetTreble, - .setGain = TTSetGain, - .play = AtaPlay, - .mixer_init = TTMixerInit, - .mixer_ioctl = TTMixerIoctl, - .write_sq_setup = AtaWriteSqSetup, - .sq_open = AtaSqOpen, - .state_info = TTStateInfo, - .min_dsp_speed = 6258, - .version = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION), - .hardware_afmts = AFMT_S8, /* h'ware-supported formats *only* here */ - .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */ -}; - -static __initdata MACHINE machFalcon = { - .name = "Atari", - .name2 = "FALCON", - .dma_alloc = AtaAlloc, - .dma_free = AtaFree, - .irqinit = AtaIrqInit, -#ifdef MODULE - .irqcleanup = AtaIrqCleanUp, -#endif /* MODULE */ - .init = FalconInit, - .silence = FalconSilence, - .setFormat = FalconSetFormat, - .setVolume = FalconSetVolume, - .setBass = AtaSetBass, - .setTreble = AtaSetTreble, - .play = AtaPlay, - .mixer_init = FalconMixerInit, - .mixer_ioctl = FalconMixerIoctl, - .write_sq_setup = AtaWriteSqSetup, - .sq_open = AtaSqOpen, - .state_info = FalconStateInfo, - .min_dsp_speed = 8195, - .version = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION), - .hardware_afmts = (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */ - .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */ -}; - - -/*** Config & Setup **********************************************************/ - - -static int __init dmasound_atari_init(void) -{ - if (MACH_IS_ATARI && ATARIHW_PRESENT(PCM_8BIT)) { - if (ATARIHW_PRESENT(CODEC)) { - dmasound.mach = machFalcon; - dmasound.mach.default_soft = def_soft ; - dmasound.mach.default_hard = def_hard_falcon ; - is_falcon = 1; - } else if (ATARIHW_PRESENT(MICROWIRE)) { - dmasound.mach = machTT; - dmasound.mach.default_soft = def_soft ; - dmasound.mach.default_hard = def_hard_tt ; - is_falcon = 0; - } else - return -ENODEV; - if ((st_mfp.int_en_a & st_mfp.int_mk_a & 0x20) == 0) - return dmasound_init(); - else { - printk("DMA sound driver: Timer A interrupt already in use\n"); - return -EBUSY; - } - } - return -ENODEV; -} - -static void __exit dmasound_atari_cleanup(void) -{ - dmasound_deinit(); -} - -module_init(dmasound_atari_init); -module_exit(dmasound_atari_cleanup); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/dmasound/dmasound_core.c b/ANDROID_3.4.5/sound/oss/dmasound/dmasound_core.c deleted file mode 100644 index c918313c..00000000 --- a/ANDROID_3.4.5/sound/oss/dmasound/dmasound_core.c +++ /dev/null @@ -1,1589 +0,0 @@ -/* - * linux/sound/oss/dmasound/dmasound_core.c - * - * - * OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for - * Linux/m68k - * Extended to support Power Macintosh for Linux/ppc by Paul Mackerras - * - * (c) 1995 by Michael Schlueter & Michael Marte - * - * Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS - * interface and the u-law to signed byte conversion. - * - * Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue, - * /dev/mixer, /dev/sndstat and complemented the VFS interface. He would like - * to thank: - * - Michael Schlueter for initial ideas and documentation on the MFP and - * the DMA sound hardware. - * - Therapy? for their CD 'Troublegum' which really made me rock. - * - * /dev/sndstat is based on code by Hannu Savolainen, the author of the - * VoxWare family of drivers. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - * - * History: - * - * 1995/8/25 First release - * - * 1995/9/02 Roman Hodek: - * - Fixed atari_stram_alloc() call, the timer - * programming and several race conditions - * 1995/9/14 Roman Hodek: - * - After some discussion with Michael Schlueter, - * revised the interrupt disabling - * - Slightly speeded up U8->S8 translation by using - * long operations where possible - * - Added 4:3 interpolation for /dev/audio - * - * 1995/9/20 Torsten Scherer: - * - Fixed a bug in sq_write and changed /dev/audio - * converting to play at 12517Hz instead of 6258Hz. - * - * 1995/9/23 Torsten Scherer: - * - Changed sq_interrupt() and sq_play() to pre-program - * the DMA for another frame while there's still one - * running. This allows the IRQ response to be - * arbitrarily delayed and playing will still continue. - * - * 1995/10/14 Guenther Kelleter, Torsten Scherer: - * - Better support for Falcon audio (the Falcon doesn't - * raise an IRQ at the end of a frame, but at the - * beginning instead!). uses 'if (codec_dma)' in lots - * of places to simply switch between Falcon and TT - * code. - * - * 1995/11/06 Torsten Scherer: - * - Started introducing a hardware abstraction scheme - * (may perhaps also serve for Amigas?) - * - Can now play samples at almost all frequencies by - * means of a more generalized expand routine - * - Takes a good deal of care to cut data only at - * sample sizes - * - Buffer size is now a kernel runtime option - * - Implemented fsync() & several minor improvements - * Guenther Kelleter: - * - Useful hints and bug fixes - * - Cross-checked it for Falcons - * - * 1996/3/9 Geert Uytterhoeven: - * - Support added for Amiga, A-law, 16-bit little - * endian. - * - Unification to drivers/sound/dmasound.c. - * - * 1996/4/6 Martin Mitchell: - * - Updated to 1.3 kernel. - * - * 1996/6/13 Topi Kanerva: - * - Fixed things that were broken (mainly the amiga - * 14-bit routines) - * - /dev/sndstat shows now the real hardware frequency - * - The lowpass filter is disabled by default now - * - * 1996/9/25 Geert Uytterhoeven: - * - Modularization - * - * 1998/6/10 Andreas Schwab: - * - Converted to use sound_core - * - * 1999/12/28 Richard Zidlicky: - * - Added support for Q40 - * - * 2000/2/27 Geert Uytterhoeven: - * - Clean up and split the code into 4 parts: - * o dmasound_core: machine-independent code - * o dmasound_atari: Atari TT and Falcon support - * o dmasound_awacs: Apple PowerMac support - * o dmasound_paula: Amiga support - * - * 2000/3/25 Geert Uytterhoeven: - * - Integration of dmasound_q40 - * - Small clean ups - * - * 2001/01/26 [1.0] Iain Sandoe - * - make /dev/sndstat show revision & edition info. - * - since dmasound.mach.sq_setup() can fail on pmac - * its type has been changed to int and the returns - * are checked. - * [1.1] - stop missing translations from being called. - * 2001/02/08 [1.2] - remove unused translation tables & move machine- - * specific tables to low-level. - * - return correct info. for SNDCTL_DSP_GETFMTS. - * [1.3] - implement SNDCTL_DSP_GETCAPS fully. - * [1.4] - make /dev/sndstat text length usage deterministic. - * - make /dev/sndstat call to low-level - * dmasound.mach.state_info() pass max space to ll driver. - * - tidy startup banners and output info. - * [1.5] - tidy up a little (removed some unused #defines in - * dmasound.h) - * - fix up HAS_RECORD conditionalisation. - * - add record code in places it is missing... - * - change buf-sizes to bytes to allow < 1kb for pmac - * if user param entry is < 256 the value is taken to - * be in kb > 256 is taken to be in bytes. - * - make default buff/frag params conditional on - * machine to allow smaller values for pmac. - * - made the ioctls, read & write comply with the OSS - * rules on setting params. - * - added parsing of _setup() params for record. - * 2001/04/04 [1.6] - fix bug where sample rates higher than maximum were - * being reported as OK. - * - fix open() to return -EBUSY as per OSS doc. when - * audio is in use - this is independent of O_NOBLOCK. - * - fix bug where SNDCTL_DSP_POST was blocking. - */ - - /* Record capability notes 30/01/2001: - * At present these observations apply only to pmac LL driver (the only one - * that can do record, at present). However, if other LL drivers for machines - * with record are added they may apply. - * - * The fragment parameters for the record and play channels are separate. - * However, if the driver is opened O_RDWR there is no way (in the current OSS - * API) to specify their values independently for the record and playback - * channels. Since the only common factor between the input & output is the - * sample rate (on pmac) it should be possible to open /dev/dspX O_WRONLY and - * /dev/dspY O_RDONLY. The input & output channels could then have different - * characteristics (other than the first that sets sample rate claiming the - * right to set it for ever). As it stands, the format, channels, number of - * bits & sample rate are assumed to be common. In the future perhaps these - * should be the responsibility of the LL driver - and then if a card really - * does not share items between record & playback they can be specified - * separately. -*/ - -/* Thread-safeness of shared_resources notes: 31/01/2001 - * If the user opens O_RDWR and then splits record & play between two threads - * both of which inherit the fd - and then starts changing things from both - * - we will have difficulty telling. - * - * It's bad application coding - but ... - * TODO: think about how to sort this out... without bogging everything down in - * semaphores. - * - * Similarly, the OSS spec says "all changes to parameters must be between - * open() and the first read() or write(). - and a bit later on (by - * implication) "between SNDCTL_DSP_RESET and the first read() or write() after - * it". If the app is multi-threaded and this rule is broken between threads - * we will have trouble spotting it - and the fault will be rather obscure :-( - * - * We will try and put out at least a kmsg if we see it happen... but I think - * it will be quite hard to trap it with an -EXXX return... because we can't - * see the fault until after the damage is done. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "dmasound.h" - -#define DMASOUND_CORE_REVISION 1 -#define DMASOUND_CORE_EDITION 6 - - /* - * Declarations - */ - -static DEFINE_MUTEX(dmasound_core_mutex); -int dmasound_catchRadius = 0; -module_param(dmasound_catchRadius, int, 0); - -static unsigned int numWriteBufs = DEFAULT_N_BUFFERS; -module_param(numWriteBufs, int, 0); -static unsigned int writeBufSize = DEFAULT_BUFF_SIZE ; /* in bytes */ -module_param(writeBufSize, int, 0); - -MODULE_LICENSE("GPL"); - -#ifdef MODULE -static int sq_unit = -1; -static int mixer_unit = -1; -static int state_unit = -1; -static int irq_installed; -#endif /* MODULE */ - -/* control over who can modify resources shared between play/record */ -static fmode_t shared_resource_owner; -static int shared_resources_initialised; - - /* - * Mid level stuff - */ - -struct sound_settings dmasound = { - .lock = __SPIN_LOCK_UNLOCKED(dmasound.lock) -}; - -static inline void sound_silence(void) -{ - dmasound.mach.silence(); /* _MUST_ stop DMA */ -} - -static inline int sound_set_format(int format) -{ - return dmasound.mach.setFormat(format); -} - - -static int sound_set_speed(int speed) -{ - if (speed < 0) - return dmasound.soft.speed; - - /* trap out-of-range speed settings. - at present we allow (arbitrarily) low rates - using soft - up-conversion - but we can't allow > max because there is - no soft down-conversion. - */ - if (dmasound.mach.max_dsp_speed && - (speed > dmasound.mach.max_dsp_speed)) - speed = dmasound.mach.max_dsp_speed ; - - dmasound.soft.speed = speed; - - if (dmasound.minDev == SND_DEV_DSP) - dmasound.dsp.speed = dmasound.soft.speed; - - return dmasound.soft.speed; -} - -static int sound_set_stereo(int stereo) -{ - if (stereo < 0) - return dmasound.soft.stereo; - - stereo = !!stereo; /* should be 0 or 1 now */ - - dmasound.soft.stereo = stereo; - if (dmasound.minDev == SND_DEV_DSP) - dmasound.dsp.stereo = stereo; - - return stereo; -} - -static ssize_t sound_copy_translate(TRANS *trans, const u_char __user *userPtr, - size_t userCount, u_char frame[], - ssize_t *frameUsed, ssize_t frameLeft) -{ - ssize_t (*ct_func)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t); - - switch (dmasound.soft.format) { - case AFMT_MU_LAW: - ct_func = trans->ct_ulaw; - break; - case AFMT_A_LAW: - ct_func = trans->ct_alaw; - break; - case AFMT_S8: - ct_func = trans->ct_s8; - break; - case AFMT_U8: - ct_func = trans->ct_u8; - break; - case AFMT_S16_BE: - ct_func = trans->ct_s16be; - break; - case AFMT_U16_BE: - ct_func = trans->ct_u16be; - break; - case AFMT_S16_LE: - ct_func = trans->ct_s16le; - break; - case AFMT_U16_LE: - ct_func = trans->ct_u16le; - break; - default: - return 0; - } - /* if the user has requested a non-existent translation don't try - to call it but just return 0 bytes moved - */ - if (ct_func) - return ct_func(userPtr, userCount, frame, frameUsed, frameLeft); - return 0; -} - - /* - * /dev/mixer abstraction - */ - -static struct { - int busy; - int modify_counter; -} mixer; - -static int mixer_open(struct inode *inode, struct file *file) -{ - mutex_lock(&dmasound_core_mutex); - if (!try_module_get(dmasound.mach.owner)) { - mutex_unlock(&dmasound_core_mutex); - return -ENODEV; - } - mixer.busy = 1; - mutex_unlock(&dmasound_core_mutex); - return 0; -} - -static int mixer_release(struct inode *inode, struct file *file) -{ - mutex_lock(&dmasound_core_mutex); - mixer.busy = 0; - module_put(dmasound.mach.owner); - mutex_unlock(&dmasound_core_mutex); - return 0; -} - -static int mixer_ioctl(struct file *file, u_int cmd, u_long arg) -{ - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - mixer.modify_counter++; - switch (cmd) { - case OSS_GETVERSION: - return IOCTL_OUT(arg, SOUND_VERSION); - case SOUND_MIXER_INFO: - { - mixer_info info; - memset(&info, 0, sizeof(info)); - strlcpy(info.id, dmasound.mach.name2, sizeof(info.id)); - strlcpy(info.name, dmasound.mach.name2, sizeof(info.name)); - info.modify_counter = mixer.modify_counter; - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - } - if (dmasound.mach.mixer_ioctl) - return dmasound.mach.mixer_ioctl(cmd, arg); - return -EINVAL; -} - -static long mixer_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) -{ - int ret; - - mutex_lock(&dmasound_core_mutex); - ret = mixer_ioctl(file, cmd, arg); - mutex_unlock(&dmasound_core_mutex); - - return ret; -} - -static const struct file_operations mixer_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .unlocked_ioctl = mixer_unlocked_ioctl, - .open = mixer_open, - .release = mixer_release, -}; - -static void mixer_init(void) -{ -#ifndef MODULE - int mixer_unit; -#endif - mixer_unit = register_sound_mixer(&mixer_fops, -1); - if (mixer_unit < 0) - return; - - mixer.busy = 0; - dmasound.treble = 0; - dmasound.bass = 0; - if (dmasound.mach.mixer_init) - dmasound.mach.mixer_init(); -} - - - /* - * Sound queue stuff, the heart of the driver - */ - -struct sound_queue dmasound_write_sq; -static void sq_reset_output(void) ; - -static int sq_allocate_buffers(struct sound_queue *sq, int num, int size) -{ - int i; - - if (sq->buffers) - return 0; - sq->numBufs = num; - sq->bufSize = size; - sq->buffers = kmalloc (num * sizeof(char *), GFP_KERNEL); - if (!sq->buffers) - return -ENOMEM; - for (i = 0; i < num; i++) { - sq->buffers[i] = dmasound.mach.dma_alloc(size, GFP_KERNEL); - if (!sq->buffers[i]) { - while (i--) - dmasound.mach.dma_free(sq->buffers[i], size); - kfree(sq->buffers); - sq->buffers = NULL; - return -ENOMEM; - } - } - return 0; -} - -static void sq_release_buffers(struct sound_queue *sq) -{ - int i; - - if (sq->buffers) { - for (i = 0; i < sq->numBufs; i++) - dmasound.mach.dma_free(sq->buffers[i], sq->bufSize); - kfree(sq->buffers); - sq->buffers = NULL; - } -} - - -static int sq_setup(struct sound_queue *sq) -{ - int (*setup_func)(void) = NULL; - int hard_frame ; - - if (sq->locked) { /* are we already set? - and not changeable */ -#ifdef DEBUG_DMASOUND -printk("dmasound_core: tried to sq_setup a locked queue\n") ; -#endif - return -EINVAL ; - } - sq->locked = 1 ; /* don't think we have a race prob. here _check_ */ - - /* make sure that the parameters are set up - This should have been done already... - */ - - dmasound.mach.init(); - - /* OK. If the user has set fragment parameters explicitly, then we - should leave them alone... as long as they are valid. - Invalid user fragment params can occur if we allow the whole buffer - to be used when the user requests the fragments sizes (with no soft - x-lation) and then the user subsequently sets a soft x-lation that - requires increased internal buffering. - - Othwerwise (if the user did not set them) OSS says that we should - select frag params on the basis of 0.5 s output & 0.1 s input - latency. (TODO. For now we will copy in the defaults.) - */ - - if (sq->user_frags <= 0) { - sq->max_count = sq->numBufs ; - sq->max_active = sq->numBufs ; - sq->block_size = sq->bufSize; - /* set up the user info */ - sq->user_frags = sq->numBufs ; - sq->user_frag_size = sq->bufSize ; - sq->user_frag_size *= - (dmasound.soft.size * (dmasound.soft.stereo+1) ) ; - sq->user_frag_size /= - (dmasound.hard.size * (dmasound.hard.stereo+1) ) ; - } else { - /* work out requested block size */ - sq->block_size = sq->user_frag_size ; - sq->block_size *= - (dmasound.hard.size * (dmasound.hard.stereo+1) ) ; - sq->block_size /= - (dmasound.soft.size * (dmasound.soft.stereo+1) ) ; - /* the user wants to write frag-size chunks */ - sq->block_size *= dmasound.hard.speed ; - sq->block_size /= dmasound.soft.speed ; - /* this only works for size values which are powers of 2 */ - hard_frame = - (dmasound.hard.size * (dmasound.hard.stereo+1))/8 ; - sq->block_size += (hard_frame - 1) ; - sq->block_size &= ~(hard_frame - 1) ; /* make sure we are aligned */ - /* let's just check for obvious mistakes */ - if ( sq->block_size <= 0 || sq->block_size > sq->bufSize) { -#ifdef DEBUG_DMASOUND -printk("dmasound_core: invalid frag size (user set %d)\n", sq->user_frag_size) ; -#endif - sq->block_size = sq->bufSize ; - } - if ( sq->user_frags <= sq->numBufs ) { - sq->max_count = sq->user_frags ; - /* if user has set max_active - then use it */ - sq->max_active = (sq->max_active <= sq->max_count) ? - sq->max_active : sq->max_count ; - } else { -#ifdef DEBUG_DMASOUND -printk("dmasound_core: invalid frag count (user set %d)\n", sq->user_frags) ; -#endif - sq->max_count = - sq->max_active = sq->numBufs ; - } - } - sq->front = sq->count = sq->rear_size = 0; - sq->syncing = 0; - sq->active = 0; - - if (sq == &write_sq) { - sq->rear = -1; - setup_func = dmasound.mach.write_sq_setup; - } - if (setup_func) - return setup_func(); - return 0 ; -} - -static inline void sq_play(void) -{ - dmasound.mach.play(); -} - -static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft, - loff_t *ppos) -{ - ssize_t uWritten = 0; - u_char *dest; - ssize_t uUsed = 0, bUsed, bLeft; - unsigned long flags ; - - /* ++TeSche: Is something like this necessary? - * Hey, that's an honest question! Or does any other part of the - * filesystem already checks this situation? I really don't know. - */ - if (uLeft == 0) - return 0; - - /* implement any changes we have made to the soft/hard params. - this is not satisfactory really, all we have done up to now is to - say what we would like - there hasn't been any real checking of capability - */ - - if (shared_resources_initialised == 0) { - dmasound.mach.init() ; - shared_resources_initialised = 1 ; - } - - /* set up the sq if it is not already done. This may seem a dumb place - to do it - but it is what OSS requires. It means that write() can - return memory allocation errors. To avoid this possibility use the - GETBLKSIZE or GETOSPACE ioctls (after you've fiddled with all the - params you want to change) - these ioctls also force the setup. - */ - - if (write_sq.locked == 0) { - if ((uWritten = sq_setup(&write_sq)) < 0) return uWritten ; - uWritten = 0 ; - } - -/* FIXME: I think that this may be the wrong behaviour when we get strapped - for time and the cpu is close to being (or actually) behind in sending data. - - because we've lost the time that the N samples, already in the buffer, - would have given us to get here with the next lot from the user. -*/ - /* The interrupt doesn't start to play the last, incomplete frame. - * Thus we can append to it without disabling the interrupts! (Note - * also that write_sq.rear isn't affected by the interrupt.) - */ - - /* as of 1.6 this behaviour changes if SNDCTL_DSP_POST has been issued: - this will mimic the behaviour of syncing and allow the sq_play() to - queue a partial fragment. Since sq_play() may/will be called from - the IRQ handler - at least on Pmac we have to deal with it. - The strategy - possibly not optimum - is to kill _POST status if we - get here. This seems, at least, reasonable - in the sense that POST - is supposed to indicate that we might not write before the queue - is drained - and if we get here in time then it does not apply. - */ - - spin_lock_irqsave(&dmasound.lock, flags); - write_sq.syncing &= ~2 ; /* take out POST status */ - spin_unlock_irqrestore(&dmasound.lock, flags); - - if (write_sq.count > 0 && - (bLeft = write_sq.block_size-write_sq.rear_size) > 0) { - dest = write_sq.buffers[write_sq.rear]; - bUsed = write_sq.rear_size; - uUsed = sound_copy_translate(dmasound.trans_write, src, uLeft, - dest, &bUsed, bLeft); - if (uUsed <= 0) - return uUsed; - src += uUsed; - uWritten += uUsed; - uLeft = (uUsed <= uLeft) ? (uLeft - uUsed) : 0 ; /* paranoia */ - write_sq.rear_size = bUsed; - } - - while (uLeft) { - while (write_sq.count >= write_sq.max_active) { - sq_play(); - if (write_sq.non_blocking) - return uWritten > 0 ? uWritten : -EAGAIN; - SLEEP(write_sq.action_queue); - if (signal_pending(current)) - return uWritten > 0 ? uWritten : -EINTR; - } - - /* Here, we can avoid disabling the interrupt by first - * copying and translating the data, and then updating - * the write_sq variables. Until this is done, the interrupt - * won't see the new frame and we can work on it - * undisturbed. - */ - - dest = write_sq.buffers[(write_sq.rear+1) % write_sq.max_count]; - bUsed = 0; - bLeft = write_sq.block_size; - uUsed = sound_copy_translate(dmasound.trans_write, src, uLeft, - dest, &bUsed, bLeft); - if (uUsed <= 0) - break; - src += uUsed; - uWritten += uUsed; - uLeft = (uUsed <= uLeft) ? (uLeft - uUsed) : 0 ; /* paranoia */ - if (bUsed) { - write_sq.rear = (write_sq.rear+1) % write_sq.max_count; - write_sq.rear_size = bUsed; - write_sq.count++; - } - } /* uUsed may have been 0 */ - - sq_play(); - - return uUsed < 0? uUsed: uWritten; -} - -static unsigned int sq_poll(struct file *file, struct poll_table_struct *wait) -{ - unsigned int mask = 0; - int retVal; - - if (write_sq.locked == 0) { - if ((retVal = sq_setup(&write_sq)) < 0) - return retVal; - return 0; - } - if (file->f_mode & FMODE_WRITE ) - poll_wait(file, &write_sq.action_queue, wait); - if (file->f_mode & FMODE_WRITE) - if (write_sq.count < write_sq.max_active || write_sq.block_size - write_sq.rear_size > 0) - mask |= POLLOUT | POLLWRNORM; - return mask; - -} - -static inline void sq_init_waitqueue(struct sound_queue *sq) -{ - init_waitqueue_head(&sq->action_queue); - init_waitqueue_head(&sq->open_queue); - init_waitqueue_head(&sq->sync_queue); - sq->busy = 0; -} - -#if 0 /* blocking open() */ -static inline void sq_wake_up(struct sound_queue *sq, struct file *file, - fmode_t mode) -{ - if (file->f_mode & mode) { - sq->busy = 0; /* CHECK: IS THIS OK??? */ - WAKE_UP(sq->open_queue); - } -} -#endif - -static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode, - int numbufs, int bufsize) -{ - int rc = 0; - - if (file->f_mode & mode) { - if (sq->busy) { -#if 0 /* blocking open() */ - rc = -EBUSY; - if (file->f_flags & O_NONBLOCK) - return rc; - rc = -EINTR; - while (sq->busy) { - SLEEP(sq->open_queue); - if (signal_pending(current)) - return rc; - } - rc = 0; -#else - /* OSS manual says we will return EBUSY regardless - of O_NOBLOCK. - */ - return -EBUSY ; -#endif - } - sq->busy = 1; /* Let's play spot-the-race-condition */ - - /* allocate the default number & size of buffers. - (i.e. specified in _setup() or as module params) - can't be changed at the moment - but _could_ be perhaps - in the setfragments ioctl. - */ - if (( rc = sq_allocate_buffers(sq, numbufs, bufsize))) { -#if 0 /* blocking open() */ - sq_wake_up(sq, file, mode); -#else - sq->busy = 0 ; -#endif - return rc; - } - - sq->non_blocking = file->f_flags & O_NONBLOCK; - } - return rc; -} - -#define write_sq_init_waitqueue() sq_init_waitqueue(&write_sq) -#if 0 /* blocking open() */ -#define write_sq_wake_up(file) sq_wake_up(&write_sq, file, FMODE_WRITE) -#endif -#define write_sq_release_buffers() sq_release_buffers(&write_sq) -#define write_sq_open(file) \ - sq_open2(&write_sq, file, FMODE_WRITE, numWriteBufs, writeBufSize ) - -static int sq_open(struct inode *inode, struct file *file) -{ - int rc; - - mutex_lock(&dmasound_core_mutex); - if (!try_module_get(dmasound.mach.owner)) { - mutex_unlock(&dmasound_core_mutex); - return -ENODEV; - } - - rc = write_sq_open(file); /* checks the f_mode */ - if (rc) - goto out; - if (file->f_mode & FMODE_READ) { - /* TODO: if O_RDWR, release any resources grabbed by write part */ - rc = -ENXIO ; /* I think this is what is required by open(2) */ - goto out; - } - - if (dmasound.mach.sq_open) - dmasound.mach.sq_open(file->f_mode); - - /* CHECK whether this is sensible - in the case that dsp0 could be opened - O_RDONLY and dsp1 could be opened O_WRONLY - */ - - dmasound.minDev = iminor(inode) & 0x0f; - - /* OK. - we should make some attempt at consistency. At least the H'ware - options should be set with a valid mode. We will make it that the LL - driver must supply defaults for hard & soft params. - */ - - if (shared_resource_owner == 0) { - /* you can make this AFMT_U8/mono/8K if you want to mimic old - OSS behaviour - while we still have soft translations ;-) */ - dmasound.soft = dmasound.mach.default_soft ; - dmasound.dsp = dmasound.mach.default_soft ; - dmasound.hard = dmasound.mach.default_hard ; - } - -#ifndef DMASOUND_STRICT_OSS_COMPLIANCE - /* none of the current LL drivers can actually do this "native" at the moment - OSS does not really require us to supply /dev/audio if we can't do it. - */ - if (dmasound.minDev == SND_DEV_AUDIO) { - sound_set_speed(8000); - sound_set_stereo(0); - sound_set_format(AFMT_MU_LAW); - } -#endif - mutex_unlock(&dmasound_core_mutex); - return 0; - out: - module_put(dmasound.mach.owner); - mutex_unlock(&dmasound_core_mutex); - return rc; -} - -static void sq_reset_output(void) -{ - sound_silence(); /* this _must_ stop DMA, we might be about to lose the buffers */ - write_sq.active = 0; - write_sq.count = 0; - write_sq.rear_size = 0; - /* write_sq.front = (write_sq.rear+1) % write_sq.max_count;*/ - write_sq.front = 0 ; - write_sq.rear = -1 ; /* same as for set-up */ - - /* OK - we can unlock the parameters and fragment settings */ - write_sq.locked = 0 ; - write_sq.user_frags = 0 ; - write_sq.user_frag_size = 0 ; -} - -static void sq_reset(void) -{ - sq_reset_output() ; - /* we could consider resetting the shared_resources_owner here... but I - think it is probably still rather non-obvious to application writer - */ - - /* we release everything else though */ - shared_resources_initialised = 0 ; -} - -static int sq_fsync(struct file *filp, struct dentry *dentry) -{ - int rc = 0; - int timeout = 5; - - write_sq.syncing |= 1; - sq_play(); /* there may be an incomplete frame waiting */ - - while (write_sq.active) { - SLEEP(write_sq.sync_queue); - if (signal_pending(current)) { - /* While waiting for audio output to drain, an - * interrupt occurred. Stop audio output immediately - * and clear the queue. */ - sq_reset_output(); - rc = -EINTR; - break; - } - if (!--timeout) { - printk(KERN_WARNING "dmasound: Timeout draining output\n"); - sq_reset_output(); - rc = -EIO; - break; - } - } - - /* flag no sync regardless of whether we had a DSP_POST or not */ - write_sq.syncing = 0 ; - return rc; -} - -static int sq_release(struct inode *inode, struct file *file) -{ - int rc = 0; - - mutex_lock(&dmasound_core_mutex); - - if (file->f_mode & FMODE_WRITE) { - if (write_sq.busy) - rc = sq_fsync(file, file->f_path.dentry); - - sq_reset_output() ; /* make sure dma is stopped and all is quiet */ - write_sq_release_buffers(); - write_sq.busy = 0; - } - - if (file->f_mode & shared_resource_owner) { /* it's us that has them */ - shared_resource_owner = 0 ; - shared_resources_initialised = 0 ; - dmasound.hard = dmasound.mach.default_hard ; - } - - module_put(dmasound.mach.owner); - -#if 0 /* blocking open() */ - /* Wake up a process waiting for the queue being released. - * Note: There may be several processes waiting for a call - * to open() returning. */ - - /* Iain: hmm I don't understand this next comment ... */ - /* There is probably a DOS atack here. They change the mode flag. */ - /* XXX add check here,*/ - read_sq_wake_up(file); /* checks f_mode */ - write_sq_wake_up(file); /* checks f_mode */ -#endif /* blocking open() */ - - mutex_unlock(&dmasound_core_mutex); - - return rc; -} - -/* here we see if we have a right to modify format, channels, size and so on - if no-one else has claimed it already then we do... - - TODO: We might change this to mask O_RDWR such that only one or the other channel - is the owner - if we have problems. -*/ - -static int shared_resources_are_mine(fmode_t md) -{ - if (shared_resource_owner) - return (shared_resource_owner & md) != 0; - else { - shared_resource_owner = md ; - return 1 ; - } -} - -/* if either queue is locked we must deny the right to change shared params -*/ - -static int queues_are_quiescent(void) -{ - if (write_sq.locked) - return 0 ; - return 1 ; -} - -/* check and set a queue's fragments per user's wishes... - we will check against the pre-defined literals and the actual sizes. - This is a bit fraught - because soft translations can mess with our - buffer requirements *after* this call - OSS says "call setfrags first" -*/ - -/* It is possible to replace all the -EINVAL returns with an override that - just puts the allowable value in. This may be what many OSS apps require -*/ - -static int set_queue_frags(struct sound_queue *sq, int bufs, int size) -{ - if (sq->locked) { -#ifdef DEBUG_DMASOUND -printk("dmasound_core: tried to set_queue_frags on a locked queue\n") ; -#endif - return -EINVAL ; - } - - if ((size < MIN_FRAG_SIZE) || (size > MAX_FRAG_SIZE)) - return -EINVAL ; - size = (1< sq->bufSize) - return -EINVAL ; /* this might still not work */ - - if (bufs <= 0) - return -EINVAL ; - if (bufs > sq->numBufs) /* the user is allowed say "don't care" with 0x7fff */ - bufs = sq->numBufs ; - - /* there is, currently, no way to specify max_active separately - from max_count. This could be a LL driver issue - I guess - if there is a requirement for these values to be different then - we will have to pass that info. up to this level. - */ - sq->user_frags = - sq->max_active = bufs ; - sq->user_frag_size = size ; - - return 0 ; -} - -static int sq_ioctl(struct file *file, u_int cmd, u_long arg) -{ - int val, result; - u_long fmt; - int data; - int size, nbufs; - audio_buf_info info; - - switch (cmd) { - case SNDCTL_DSP_RESET: - sq_reset(); - return 0; - break ; - case SNDCTL_DSP_GETFMTS: - fmt = dmasound.mach.hardware_afmts ; /* this is what OSS says.. */ - return IOCTL_OUT(arg, fmt); - break ; - case SNDCTL_DSP_GETBLKSIZE: - /* this should tell the caller about bytes that the app can - read/write - the app doesn't care about our internal buffers. - We force sq_setup() here as per OSS 1.1 (which should - compute the values necessary). - Since there is no mechanism to specify read/write separately, for - fds opened O_RDWR, the write_sq values will, arbitrarily, overwrite - the read_sq ones. - */ - size = 0 ; - if (file->f_mode & FMODE_WRITE) { - if ( !write_sq.locked ) - sq_setup(&write_sq) ; - size = write_sq.user_frag_size ; - } - return IOCTL_OUT(arg, size); - break ; - case SNDCTL_DSP_POST: - /* all we are going to do is to tell the LL that any - partial frags can be queued for output. - The LL will have to clear this flag when last output - is queued. - */ - write_sq.syncing |= 0x2 ; - sq_play() ; - return 0 ; - case SNDCTL_DSP_SYNC: - /* This call, effectively, has the same behaviour as SNDCTL_DSP_RESET - except that it waits for output to finish before resetting - everything - read, however, is killed immediately. - */ - result = 0 ; - if (file->f_mode & FMODE_WRITE) { - result = sq_fsync(file, file->f_path.dentry); - sq_reset_output() ; - } - /* if we are the shared resource owner then release them */ - if (file->f_mode & shared_resource_owner) - shared_resources_initialised = 0 ; - return result ; - break ; - case SOUND_PCM_READ_RATE: - return IOCTL_OUT(arg, dmasound.soft.speed); - case SNDCTL_DSP_SPEED: - /* changing this on the fly will have weird effects on the sound. - Where there are rate conversions implemented in soft form - it - will cause the _ctx_xxx() functions to be substituted. - However, there doesn't appear to be any reason to dis-allow it from - a driver pov. - */ - if (shared_resources_are_mine(file->f_mode)) { - IOCTL_IN(arg, data); - data = sound_set_speed(data) ; - shared_resources_initialised = 0 ; - return IOCTL_OUT(arg, data); - } else - return -EINVAL ; - break ; - /* OSS says these next 4 actions are undefined when the device is - busy/active - we will just return -EINVAL. - To be allowed to change one - (a) you have to own the right - (b) the queue(s) must be quiescent - */ - case SNDCTL_DSP_STEREO: - if (shared_resources_are_mine(file->f_mode) && - queues_are_quiescent()) { - IOCTL_IN(arg, data); - shared_resources_initialised = 0 ; - return IOCTL_OUT(arg, sound_set_stereo(data)); - } else - return -EINVAL ; - break ; - case SOUND_PCM_WRITE_CHANNELS: - if (shared_resources_are_mine(file->f_mode) && - queues_are_quiescent()) { - IOCTL_IN(arg, data); - /* the user might ask for 20 channels, we will return 1 or 2 */ - shared_resources_initialised = 0 ; - return IOCTL_OUT(arg, sound_set_stereo(data-1)+1); - } else - return -EINVAL ; - break ; - case SNDCTL_DSP_SETFMT: - if (shared_resources_are_mine(file->f_mode) && - queues_are_quiescent()) { - int format; - IOCTL_IN(arg, data); - shared_resources_initialised = 0 ; - format = sound_set_format(data); - result = IOCTL_OUT(arg, format); - if (result < 0) - return result; - if (format != data && data != AFMT_QUERY) - return -EINVAL; - return 0; - } else - return -EINVAL ; - case SNDCTL_DSP_SUBDIVIDE: - return -EINVAL ; - case SNDCTL_DSP_SETFRAGMENT: - /* we can do this independently for the two queues - with the - proviso that for fds opened O_RDWR we cannot separate the - actions and both queues will be set per the last call. - NOTE: this does *NOT* actually set the queue up - merely - registers our intentions. - */ - IOCTL_IN(arg, data); - result = 0 ; - nbufs = (data >> 16) & 0x7fff ; /* 0x7fff is 'use maximum' */ - size = data & 0xffff; - if (file->f_mode & FMODE_WRITE) { - result = set_queue_frags(&write_sq, nbufs, size) ; - if (result) - return result ; - } - /* NOTE: this return value is irrelevant - OSS specifically says that - the value is 'random' and that the user _must_ check the actual - frags values using SNDCTL_DSP_GETBLKSIZE or similar */ - return IOCTL_OUT(arg, data); - break ; - case SNDCTL_DSP_GETOSPACE: - /* - */ - if (file->f_mode & FMODE_WRITE) { - if ( !write_sq.locked ) - sq_setup(&write_sq) ; - info.fragments = write_sq.max_active - write_sq.count; - info.fragstotal = write_sq.max_active; - info.fragsize = write_sq.user_frag_size; - info.bytes = info.fragments * info.fragsize; - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } else - return -EINVAL ; - break ; - case SNDCTL_DSP_GETCAPS: - val = dmasound.mach.capabilities & 0xffffff00; - return IOCTL_OUT(arg,val); - - default: - return mixer_ioctl(file, cmd, arg); - } - return -EINVAL; -} - -static long sq_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) -{ - int ret; - - mutex_lock(&dmasound_core_mutex); - ret = sq_ioctl(file, cmd, arg); - mutex_unlock(&dmasound_core_mutex); - - return ret; -} - -static const struct file_operations sq_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = sq_write, - .poll = sq_poll, - .unlocked_ioctl = sq_unlocked_ioctl, - .open = sq_open, - .release = sq_release, -}; - -static int sq_init(void) -{ - const struct file_operations *fops = &sq_fops; -#ifndef MODULE - int sq_unit; -#endif - - sq_unit = register_sound_dsp(fops, -1); - if (sq_unit < 0) { - printk(KERN_ERR "dmasound_core: couldn't register fops\n") ; - return sq_unit ; - } - - write_sq_init_waitqueue(); - - /* These parameters will be restored for every clean open() - * in the case of multiple open()s (e.g. dsp0 & dsp1) they - * will be set so long as the shared resources have no owner. - */ - - if (shared_resource_owner == 0) { - dmasound.soft = dmasound.mach.default_soft ; - dmasound.hard = dmasound.mach.default_hard ; - dmasound.dsp = dmasound.mach.default_soft ; - shared_resources_initialised = 0 ; - } - return 0 ; -} - - - /* - * /dev/sndstat - */ - -/* we allow more space for record-enabled because there are extra output lines. - the number here must include the amount we are prepared to give to the low-level - driver. -*/ - -#define STAT_BUFF_LEN 768 - -/* this is how much space we will allow the low-level driver to use - in the stat buffer. Currently, 2 * (80 character line + ). - We do not police this (it is up to the ll driver to be honest). -*/ - -#define LOW_LEVEL_STAT_ALLOC 162 - -static struct { - int busy; - char buf[STAT_BUFF_LEN]; /* state.buf should not overflow! */ - int len, ptr; -} state; - -/* publish this function for use by low-level code, if required */ - -static char *get_afmt_string(int afmt) -{ - switch(afmt) { - case AFMT_MU_LAW: - return "mu-law"; - break; - case AFMT_A_LAW: - return "A-law"; - break; - case AFMT_U8: - return "unsigned 8 bit"; - break; - case AFMT_S8: - return "signed 8 bit"; - break; - case AFMT_S16_BE: - return "signed 16 bit BE"; - break; - case AFMT_U16_BE: - return "unsigned 16 bit BE"; - break; - case AFMT_S16_LE: - return "signed 16 bit LE"; - break; - case AFMT_U16_LE: - return "unsigned 16 bit LE"; - break; - case 0: - return "format not set" ; - break ; - default: - break ; - } - return "ERROR: Unsupported AFMT_XXXX code" ; -} - -static int state_open(struct inode *inode, struct file *file) -{ - char *buffer = state.buf; - int len = 0; - int ret; - - mutex_lock(&dmasound_core_mutex); - ret = -EBUSY; - if (state.busy) - goto out; - - ret = -ENODEV; - if (!try_module_get(dmasound.mach.owner)) - goto out; - - state.ptr = 0; - state.busy = 1; - - len += sprintf(buffer+len, "%sDMA sound driver rev %03d :\n", - dmasound.mach.name, (DMASOUND_CORE_REVISION<<4) + - ((dmasound.mach.version>>8) & 0x0f)); - len += sprintf(buffer+len, - "Core driver edition %02d.%02d : %s driver edition %02d.%02d\n", - DMASOUND_CORE_REVISION, DMASOUND_CORE_EDITION, dmasound.mach.name2, - (dmasound.mach.version >> 8), (dmasound.mach.version & 0xff)) ; - - /* call the low-level module to fill in any stat info. that it has - if present. Maximum buffer usage is specified. - */ - - if (dmasound.mach.state_info) - len += dmasound.mach.state_info(buffer+len, - (size_t) LOW_LEVEL_STAT_ALLOC) ; - - /* make usage of the state buffer as deterministic as poss. - exceptional conditions could cause overrun - and this is flagged as - a kernel error. - */ - - /* formats and settings */ - - len += sprintf(buffer+len,"\t\t === Formats & settings ===\n") ; - len += sprintf(buffer+len,"Parameter %20s%20s\n","soft","hard") ; - len += sprintf(buffer+len,"Format :%20s%20s\n", - get_afmt_string(dmasound.soft.format), - get_afmt_string(dmasound.hard.format)); - - len += sprintf(buffer+len,"Samp Rate:%14d s/sec%14d s/sec\n", - dmasound.soft.speed, dmasound.hard.speed); - - len += sprintf(buffer+len,"Channels :%20s%20s\n", - dmasound.soft.stereo ? "stereo" : "mono", - dmasound.hard.stereo ? "stereo" : "mono" ); - - /* sound queue status */ - - len += sprintf(buffer+len,"\t\t === Sound Queue status ===\n"); - len += sprintf(buffer+len,"Allocated:%8s%6s\n","Buffers","Size") ; - len += sprintf(buffer+len,"%9s:%8d%6d\n", - "write", write_sq.numBufs, write_sq.bufSize) ; - len += sprintf(buffer+len, - "Current : MaxFrg FragSiz MaxAct Frnt Rear " - "Cnt RrSize A B S L xruns\n") ; - len += sprintf(buffer+len,"%9s:%7d%8d%7d%5d%5d%4d%7d%2d%2d%2d%2d%7d\n", - "write", write_sq.max_count, write_sq.block_size, - write_sq.max_active, write_sq.front, write_sq.rear, - write_sq.count, write_sq.rear_size, write_sq.active, - write_sq.busy, write_sq.syncing, write_sq.locked, write_sq.xruns) ; -#ifdef DEBUG_DMASOUND -printk("dmasound: stat buffer used %d bytes\n", len) ; -#endif - - if (len >= STAT_BUFF_LEN) - printk(KERN_ERR "dmasound_core: stat buffer overflowed!\n"); - - state.len = len; - ret = 0; -out: - mutex_unlock(&dmasound_core_mutex); - return ret; -} - -static int state_release(struct inode *inode, struct file *file) -{ - mutex_lock(&dmasound_core_mutex); - state.busy = 0; - module_put(dmasound.mach.owner); - mutex_unlock(&dmasound_core_mutex); - return 0; -} - -static ssize_t state_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - int n = state.len - state.ptr; - if (n > count) - n = count; - if (n <= 0) - return 0; - if (copy_to_user(buf, &state.buf[state.ptr], n)) - return -EFAULT; - state.ptr += n; - return n; -} - -static const struct file_operations state_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = state_read, - .open = state_open, - .release = state_release, -}; - -static int state_init(void) -{ -#ifndef MODULE - int state_unit; -#endif - state_unit = register_sound_special(&state_fops, SND_DEV_STATUS); - if (state_unit < 0) - return state_unit ; - state.busy = 0; - return 0 ; -} - - - /* - * Config & Setup - * - * This function is called by _one_ chipset-specific driver - */ - -int dmasound_init(void) -{ - int res ; -#ifdef MODULE - if (irq_installed) - return -EBUSY; -#endif - - /* Set up sound queue, /dev/audio and /dev/dsp. */ - - /* Set default settings. */ - if ((res = sq_init()) < 0) - return res ; - - /* Set up /dev/sndstat. */ - if ((res = state_init()) < 0) - return res ; - - /* Set up /dev/mixer. */ - mixer_init(); - - if (!dmasound.mach.irqinit()) { - printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n"); - return -ENODEV; - } -#ifdef MODULE - irq_installed = 1; -#endif - - printk(KERN_INFO "%s DMA sound driver rev %03d installed\n", - dmasound.mach.name, (DMASOUND_CORE_REVISION<<4) + - ((dmasound.mach.version>>8) & 0x0f)); - printk(KERN_INFO - "Core driver edition %02d.%02d : %s driver edition %02d.%02d\n", - DMASOUND_CORE_REVISION, DMASOUND_CORE_EDITION, dmasound.mach.name2, - (dmasound.mach.version >> 8), (dmasound.mach.version & 0xff)) ; - printk(KERN_INFO "Write will use %4d fragments of %7d bytes as default\n", - numWriteBufs, writeBufSize) ; - return 0; -} - -#ifdef MODULE - -void dmasound_deinit(void) -{ - if (irq_installed) { - sound_silence(); - dmasound.mach.irqcleanup(); - irq_installed = 0; - } - - write_sq_release_buffers(); - - if (mixer_unit >= 0) - unregister_sound_mixer(mixer_unit); - if (state_unit >= 0) - unregister_sound_special(state_unit); - if (sq_unit >= 0) - unregister_sound_dsp(sq_unit); -} - -#else /* !MODULE */ - -static int dmasound_setup(char *str) -{ - int ints[6], size; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - /* check the bootstrap parameter for "dmasound=" */ - - /* FIXME: other than in the most naive of cases there is no sense in these - * buffers being other than powers of two. This is not checked yet. - */ - - switch (ints[0]) { - case 3: - if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) - printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius); - else - catchRadius = ints[3]; - /* fall through */ - case 2: - if (ints[1] < MIN_BUFFERS) - printk("dmasound_setup: invalid number of buffers, using default = %d\n", numWriteBufs); - else - numWriteBufs = ints[1]; - /* fall through */ - case 1: - if ((size = ints[2]) < 256) /* check for small buffer specs */ - size <<= 10 ; - if (size < MIN_BUFSIZE || size > MAX_BUFSIZE) - printk("dmasound_setup: invalid write buffer size, using default = %d\n", writeBufSize); - else - writeBufSize = size; - case 0: - break; - default: - printk("dmasound_setup: invalid number of arguments\n"); - return 0; - } - return 1; -} - -__setup("dmasound=", dmasound_setup); - -#endif /* !MODULE */ - - /* - * Conversion tables - */ - -#ifdef HAS_8BIT_TABLES -/* 8 bit mu-law */ - -char dmasound_ulaw2dma8[] = { - -126, -122, -118, -114, -110, -106, -102, -98, - -94, -90, -86, -82, -78, -74, -70, -66, - -63, -61, -59, -57, -55, -53, -51, -49, - -47, -45, -43, -41, -39, -37, -35, -33, - -31, -30, -29, -28, -27, -26, -25, -24, - -23, -22, -21, -20, -19, -18, -17, -16, - -16, -15, -15, -14, -14, -13, -13, -12, - -12, -11, -11, -10, -10, -9, -9, -8, - -8, -8, -7, -7, -7, -7, -6, -6, - -6, -6, -5, -5, -5, -5, -4, -4, - -4, -4, -4, -4, -3, -3, -3, -3, - -3, -3, -3, -3, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 0, - 125, 121, 117, 113, 109, 105, 101, 97, - 93, 89, 85, 81, 77, 73, 69, 65, - 62, 60, 58, 56, 54, 52, 50, 48, - 46, 44, 42, 40, 38, 36, 34, 32, - 30, 29, 28, 27, 26, 25, 24, 23, - 22, 21, 20, 19, 18, 17, 16, 15, - 15, 14, 14, 13, 13, 12, 12, 11, - 11, 10, 10, 9, 9, 8, 8, 7, - 7, 7, 6, 6, 6, 6, 5, 5, - 5, 5, 4, 4, 4, 4, 3, 3, - 3, 3, 3, 3, 2, 2, 2, 2, - 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* 8 bit A-law */ - -char dmasound_alaw2dma8[] = { - -22, -21, -24, -23, -18, -17, -20, -19, - -30, -29, -32, -31, -26, -25, -28, -27, - -11, -11, -12, -12, -9, -9, -10, -10, - -15, -15, -16, -16, -13, -13, -14, -14, - -86, -82, -94, -90, -70, -66, -78, -74, - -118, -114, -126, -122, -102, -98, -110, -106, - -43, -41, -47, -45, -35, -33, -39, -37, - -59, -57, -63, -61, -51, -49, -55, -53, - -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -6, -6, -6, -6, -5, -5, -5, -5, - -8, -8, -8, -8, -7, -7, -7, -7, - -3, -3, -3, -3, -3, -3, -3, -3, - -4, -4, -4, -4, -4, -4, -4, -4, - 21, 20, 23, 22, 17, 16, 19, 18, - 29, 28, 31, 30, 25, 24, 27, 26, - 10, 10, 11, 11, 8, 8, 9, 9, - 14, 14, 15, 15, 12, 12, 13, 13, - 86, 82, 94, 90, 70, 66, 78, 74, - 118, 114, 126, 122, 102, 98, 110, 106, - 43, 41, 47, 45, 35, 33, 39, 37, - 59, 57, 63, 61, 51, 49, 55, 53, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 4, 4, 4, 4, - 7, 7, 7, 7, 6, 6, 6, 6, - 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 -}; -#endif /* HAS_8BIT_TABLES */ - - /* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(dmasound); -EXPORT_SYMBOL(dmasound_init); -#ifdef MODULE -EXPORT_SYMBOL(dmasound_deinit); -#endif -EXPORT_SYMBOL(dmasound_write_sq); -EXPORT_SYMBOL(dmasound_catchRadius); -#ifdef HAS_8BIT_TABLES -EXPORT_SYMBOL(dmasound_ulaw2dma8); -EXPORT_SYMBOL(dmasound_alaw2dma8); -#endif diff --git a/ANDROID_3.4.5/sound/oss/dmasound/dmasound_paula.c b/ANDROID_3.4.5/sound/oss/dmasound/dmasound_paula.c deleted file mode 100644 index 87910e99..00000000 --- a/ANDROID_3.4.5/sound/oss/dmasound/dmasound_paula.c +++ /dev/null @@ -1,751 +0,0 @@ -/* - * linux/sound/oss/dmasound/dmasound_paula.c - * - * Amiga `Paula' DMA Sound Driver - * - * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits - * prior to 28/01/2001 - * - * 28/01/2001 [0.1] Iain Sandoe - * - added versioning - * - put in and populated the hardware_afmts field. - * [0.2] - put in SNDCTL_DSP_GETCAPS value. - * [0.3] - put in constraint on state buffer usage. - * [0.4] - put in default hard/soft settings -*/ - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "dmasound.h" - -#define DMASOUND_PAULA_REVISION 0 -#define DMASOUND_PAULA_EDITION 4 - -#define custom amiga_custom - /* - * The minimum period for audio depends on htotal (for OCS/ECS/AGA) - * (Imported from arch/m68k/amiga/amisound.c) - */ - -extern volatile u_short amiga_audio_min_period; - - - /* - * amiga_mksound() should be able to restore the period after beeping - * (Imported from arch/m68k/amiga/amisound.c) - */ - -extern u_short amiga_audio_period; - - - /* - * Audio DMA masks - */ - -#define AMI_AUDIO_OFF (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3) -#define AMI_AUDIO_8 (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1) -#define AMI_AUDIO_14 (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3) - - - /* - * Helper pointers for 16(14)-bit sound - */ - -static int write_sq_block_size_half, write_sq_block_size_quarter; - - -/*** Low level stuff *********************************************************/ - - -static void *AmiAlloc(unsigned int size, gfp_t flags); -static void AmiFree(void *obj, unsigned int size); -static int AmiIrqInit(void); -#ifdef MODULE -static void AmiIrqCleanUp(void); -#endif -static void AmiSilence(void); -static void AmiInit(void); -static int AmiSetFormat(int format); -static int AmiSetVolume(int volume); -static int AmiSetTreble(int treble); -static void AmiPlayNextFrame(int index); -static void AmiPlay(void); -static irqreturn_t AmiInterrupt(int irq, void *dummy); - -#ifdef CONFIG_HEARTBEAT - - /* - * Heartbeat interferes with sound since the 7 kHz low-pass filter and the - * power LED are controlled by the same line. - */ - -static void (*saved_heartbeat)(int) = NULL; - -static inline void disable_heartbeat(void) -{ - if (mach_heartbeat) { - saved_heartbeat = mach_heartbeat; - mach_heartbeat = NULL; - } - AmiSetTreble(dmasound.treble); -} - -static inline void enable_heartbeat(void) -{ - if (saved_heartbeat) - mach_heartbeat = saved_heartbeat; -} -#else /* !CONFIG_HEARTBEAT */ -#define disable_heartbeat() do { } while (0) -#define enable_heartbeat() do { } while (0) -#endif /* !CONFIG_HEARTBEAT */ - - -/*** Mid level stuff *********************************************************/ - -static void AmiMixerInit(void); -static int AmiMixerIoctl(u_int cmd, u_long arg); -static int AmiWriteSqSetup(void); -static int AmiStateInfo(char *buffer, size_t space); - - -/*** Translations ************************************************************/ - -/* ++TeSche: radically changed for new expanding purposes... - * - * These two routines now deal with copying/expanding/translating the samples - * from user space into our buffer at the right frequency. They take care about - * how much data there's actually to read, how much buffer space there is and - * to convert samples into the right frequency/encoding. They will only work on - * complete samples so it may happen they leave some bytes in the input stream - * if the user didn't write a multiple of the current sample size. They both - * return the number of bytes they've used from both streams so you may detect - * such a situation. Luckily all programs should be able to cope with that. - * - * I think I've optimized anything as far as one can do in plain C, all - * variables should fit in registers and the loops are really short. There's - * one loop for every possible situation. Writing a more generalized and thus - * parameterized loop would only produce slower code. Feel free to optimize - * this in assembler if you like. :) - * - * I think these routines belong here because they're not yet really hardware - * independent, especially the fact that the Falcon can play 16bit samples - * only in stereo is hardcoded in both of them! - * - * ++geert: split in even more functions (one per format) - */ - - - /* - * Native format - */ - -static ssize_t ami_ct_s8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) -{ - ssize_t count, used; - - if (!dmasound.soft.stereo) { - void *p = &frame[*frameUsed]; - count = min_t(unsigned long, userCount, frameLeft) & ~1; - used = count; - if (copy_from_user(p, userPtr, count)) - return -EFAULT; - } else { - u_char *left = &frame[*frameUsed>>1]; - u_char *right = left+write_sq_block_size_half; - count = min_t(unsigned long, userCount, frameLeft)>>1 & ~1; - used = count*2; - while (count > 0) { - if (get_user(*left++, userPtr++) - || get_user(*right++, userPtr++)) - return -EFAULT; - count--; - } - } - *frameUsed += used; - return used; -} - - - /* - * Copy and convert 8 bit data - */ - -#define GENERATE_AMI_CT8(funcname, convsample) \ -static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \ - u_char frame[], ssize_t *frameUsed, \ - ssize_t frameLeft) \ -{ \ - ssize_t count, used; \ - \ - if (!dmasound.soft.stereo) { \ - u_char *p = &frame[*frameUsed]; \ - count = min_t(size_t, userCount, frameLeft) & ~1; \ - used = count; \ - while (count > 0) { \ - u_char data; \ - if (get_user(data, userPtr++)) \ - return -EFAULT; \ - *p++ = convsample(data); \ - count--; \ - } \ - } else { \ - u_char *left = &frame[*frameUsed>>1]; \ - u_char *right = left+write_sq_block_size_half; \ - count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \ - used = count*2; \ - while (count > 0) { \ - u_char data; \ - if (get_user(data, userPtr++)) \ - return -EFAULT; \ - *left++ = convsample(data); \ - if (get_user(data, userPtr++)) \ - return -EFAULT; \ - *right++ = convsample(data); \ - count--; \ - } \ - } \ - *frameUsed += used; \ - return used; \ -} - -#define AMI_CT_ULAW(x) (dmasound_ulaw2dma8[(x)]) -#define AMI_CT_ALAW(x) (dmasound_alaw2dma8[(x)]) -#define AMI_CT_U8(x) ((x) ^ 0x80) - -GENERATE_AMI_CT8(ami_ct_ulaw, AMI_CT_ULAW) -GENERATE_AMI_CT8(ami_ct_alaw, AMI_CT_ALAW) -GENERATE_AMI_CT8(ami_ct_u8, AMI_CT_U8) - - - /* - * Copy and convert 16 bit data - */ - -#define GENERATE_AMI_CT_16(funcname, convsample) \ -static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \ - u_char frame[], ssize_t *frameUsed, \ - ssize_t frameLeft) \ -{ \ - const u_short __user *ptr = (const u_short __user *)userPtr; \ - ssize_t count, used; \ - u_short data; \ - \ - if (!dmasound.soft.stereo) { \ - u_char *high = &frame[*frameUsed>>1]; \ - u_char *low = high+write_sq_block_size_half; \ - count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \ - used = count*2; \ - while (count > 0) { \ - if (get_user(data, ptr++)) \ - return -EFAULT; \ - data = convsample(data); \ - *high++ = data>>8; \ - *low++ = (data>>2) & 0x3f; \ - count--; \ - } \ - } else { \ - u_char *lefth = &frame[*frameUsed>>2]; \ - u_char *leftl = lefth+write_sq_block_size_quarter; \ - u_char *righth = lefth+write_sq_block_size_half; \ - u_char *rightl = righth+write_sq_block_size_quarter; \ - count = min_t(size_t, userCount, frameLeft)>>2 & ~1; \ - used = count*4; \ - while (count > 0) { \ - if (get_user(data, ptr++)) \ - return -EFAULT; \ - data = convsample(data); \ - *lefth++ = data>>8; \ - *leftl++ = (data>>2) & 0x3f; \ - if (get_user(data, ptr++)) \ - return -EFAULT; \ - data = convsample(data); \ - *righth++ = data>>8; \ - *rightl++ = (data>>2) & 0x3f; \ - count--; \ - } \ - } \ - *frameUsed += used; \ - return used; \ -} - -#define AMI_CT_S16BE(x) (x) -#define AMI_CT_U16BE(x) ((x) ^ 0x8000) -#define AMI_CT_S16LE(x) (le2be16((x))) -#define AMI_CT_U16LE(x) (le2be16((x)) ^ 0x8000) - -GENERATE_AMI_CT_16(ami_ct_s16be, AMI_CT_S16BE) -GENERATE_AMI_CT_16(ami_ct_u16be, AMI_CT_U16BE) -GENERATE_AMI_CT_16(ami_ct_s16le, AMI_CT_S16LE) -GENERATE_AMI_CT_16(ami_ct_u16le, AMI_CT_U16LE) - - -static TRANS transAmiga = { - .ct_ulaw = ami_ct_ulaw, - .ct_alaw = ami_ct_alaw, - .ct_s8 = ami_ct_s8, - .ct_u8 = ami_ct_u8, - .ct_s16be = ami_ct_s16be, - .ct_u16be = ami_ct_u16be, - .ct_s16le = ami_ct_s16le, - .ct_u16le = ami_ct_u16le, -}; - -/*** Low level stuff *********************************************************/ - -static inline void StopDMA(void) -{ - custom.aud[0].audvol = custom.aud[1].audvol = 0; - custom.aud[2].audvol = custom.aud[3].audvol = 0; - custom.dmacon = AMI_AUDIO_OFF; - enable_heartbeat(); -} - -static void *AmiAlloc(unsigned int size, gfp_t flags) -{ - return amiga_chip_alloc((long)size, "dmasound [Paula]"); -} - -static void AmiFree(void *obj, unsigned int size) -{ - amiga_chip_free (obj); -} - -static int __init AmiIrqInit(void) -{ - /* turn off DMA for audio channels */ - StopDMA(); - - /* Register interrupt handler. */ - if (request_irq(IRQ_AMIGA_AUD0, AmiInterrupt, 0, "DMA sound", - AmiInterrupt)) - return 0; - return 1; -} - -#ifdef MODULE -static void AmiIrqCleanUp(void) -{ - /* turn off DMA for audio channels */ - StopDMA(); - /* release the interrupt */ - free_irq(IRQ_AMIGA_AUD0, AmiInterrupt); -} -#endif /* MODULE */ - -static void AmiSilence(void) -{ - /* turn off DMA for audio channels */ - StopDMA(); -} - - -static void AmiInit(void) -{ - int period, i; - - AmiSilence(); - - if (dmasound.soft.speed) - period = amiga_colorclock/dmasound.soft.speed-1; - else - period = amiga_audio_min_period; - dmasound.hard = dmasound.soft; - dmasound.trans_write = &transAmiga; - - if (period < amiga_audio_min_period) { - /* we would need to squeeze the sound, but we won't do that */ - period = amiga_audio_min_period; - } else if (period > 65535) { - period = 65535; - } - dmasound.hard.speed = amiga_colorclock/(period+1); - - for (i = 0; i < 4; i++) - custom.aud[i].audper = period; - amiga_audio_period = period; -} - - -static int AmiSetFormat(int format) -{ - int size; - - /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */ - - switch (format) { - case AFMT_QUERY: - return dmasound.soft.format; - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - size = 8; - format = AFMT_S8; - } - - dmasound.soft.format = format; - dmasound.soft.size = size; - if (dmasound.minDev == SND_DEV_DSP) { - dmasound.dsp.format = format; - dmasound.dsp.size = dmasound.soft.size; - } - AmiInit(); - - return format; -} - - -#define VOLUME_VOXWARE_TO_AMI(v) \ - (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100) -#define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64) - -static int AmiSetVolume(int volume) -{ - dmasound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff); - custom.aud[0].audvol = dmasound.volume_left; - dmasound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8); - custom.aud[1].audvol = dmasound.volume_right; - if (dmasound.hard.size == 16) { - if (dmasound.volume_left == 64 && dmasound.volume_right == 64) { - custom.aud[2].audvol = 1; - custom.aud[3].audvol = 1; - } else { - custom.aud[2].audvol = 0; - custom.aud[3].audvol = 0; - } - } - return VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) | - (VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8); -} - -static int AmiSetTreble(int treble) -{ - dmasound.treble = treble; - if (treble < 50) - ciaa.pra &= ~0x02; - else - ciaa.pra |= 0x02; - return treble; -} - - -#define AMI_PLAY_LOADED 1 -#define AMI_PLAY_PLAYING 2 -#define AMI_PLAY_MASK 3 - - -static void AmiPlayNextFrame(int index) -{ - u_char *start, *ch0, *ch1, *ch2, *ch3; - u_long size; - - /* used by AmiPlay() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = write_sq.buffers[write_sq.front]; - size = (write_sq.count == index ? write_sq.rear_size - : write_sq.block_size)>>1; - - if (dmasound.hard.stereo) { - ch0 = start; - ch1 = start+write_sq_block_size_half; - size >>= 1; - } else { - ch0 = start; - ch1 = start; - } - - disable_heartbeat(); - custom.aud[0].audvol = dmasound.volume_left; - custom.aud[1].audvol = dmasound.volume_right; - if (dmasound.hard.size == 8) { - custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); - custom.aud[0].audlen = size; - custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); - custom.aud[1].audlen = size; - custom.dmacon = AMI_AUDIO_8; - } else { - size >>= 1; - custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); - custom.aud[0].audlen = size; - custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); - custom.aud[1].audlen = size; - if (dmasound.volume_left == 64 && dmasound.volume_right == 64) { - /* We can play pseudo 14-bit only with the maximum volume */ - ch3 = ch0+write_sq_block_size_quarter; - ch2 = ch1+write_sq_block_size_quarter; - custom.aud[2].audvol = 1; /* we are being affected by the beeps */ - custom.aud[3].audvol = 1; /* restoring volume here helps a bit */ - custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2); - custom.aud[2].audlen = size; - custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3); - custom.aud[3].audlen = size; - custom.dmacon = AMI_AUDIO_14; - } else { - custom.aud[2].audvol = 0; - custom.aud[3].audvol = 0; - custom.dmacon = AMI_AUDIO_8; - } - } - write_sq.front = (write_sq.front+1) % write_sq.max_count; - write_sq.active |= AMI_PLAY_LOADED; -} - - -static void AmiPlay(void) -{ - int minframes = 1; - - custom.intena = IF_AUD0; - - if (write_sq.active & AMI_PLAY_LOADED) { - /* There's already a frame loaded */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - - if (write_sq.active & AMI_PLAY_PLAYING) - /* Increase threshold: frame 1 is already being played */ - minframes = 2; - - if (write_sq.count < minframes) { - /* Nothing to do */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - - if (write_sq.count <= minframes && - write_sq.rear_size < write_sq.block_size && !write_sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - - AmiPlayNextFrame(minframes); - - custom.intena = IF_SETCLR | IF_AUD0; -} - - -static irqreturn_t AmiInterrupt(int irq, void *dummy) -{ - int minframes = 1; - - custom.intena = IF_AUD0; - - if (!write_sq.active) { - /* Playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(write_sq.sync_queue); - return IRQ_HANDLED; - } - - if (write_sq.active & AMI_PLAY_PLAYING) { - /* We've just finished a frame */ - write_sq.count--; - WAKE_UP(write_sq.action_queue); - } - - if (write_sq.active & AMI_PLAY_LOADED) - /* Increase threshold: frame 1 is already being played */ - minframes = 2; - - /* Shift the flags */ - write_sq.active = (write_sq.active<<1) & AMI_PLAY_MASK; - - if (!write_sq.active) - /* No frame is playing, disable audio DMA */ - StopDMA(); - - custom.intena = IF_SETCLR | IF_AUD0; - - if (write_sq.count >= minframes) - /* Try to play the next frame */ - AmiPlay(); - - if (!write_sq.active) - /* Nothing to play anymore. - Wake up a process waiting for audio output to drain. */ - WAKE_UP(write_sq.sync_queue); - return IRQ_HANDLED; -} - -/*** Mid level stuff *********************************************************/ - - -/* - * /dev/mixer abstraction - */ - -static void __init AmiMixerInit(void) -{ - dmasound.volume_left = 64; - dmasound.volume_right = 64; - custom.aud[0].audvol = dmasound.volume_left; - custom.aud[3].audvol = 1; /* For pseudo 14bit */ - custom.aud[1].audvol = dmasound.volume_right; - custom.aud[2].audvol = 1; /* For pseudo 14bit */ - dmasound.treble = 50; -} - -static int AmiMixerIoctl(u_int cmd, u_long arg) -{ - int data; - switch (cmd) { - case SOUND_MIXER_READ_DEVMASK: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE); - case SOUND_MIXER_READ_RECMASK: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_STEREODEVS: - return IOCTL_OUT(arg, SOUND_MASK_VOLUME); - case SOUND_MIXER_READ_VOLUME: - return IOCTL_OUT(arg, - VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) | - VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, dmasound_set_volume(data)); - case SOUND_MIXER_READ_TREBLE: - return IOCTL_OUT(arg, dmasound.treble); - case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, dmasound_set_treble(data)); - } - return -EINVAL; -} - - -static int AmiWriteSqSetup(void) -{ - write_sq_block_size_half = write_sq.block_size>>1; - write_sq_block_size_quarter = write_sq_block_size_half>>1; - return 0; -} - - -static int AmiStateInfo(char *buffer, size_t space) -{ - int len = 0; - len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n", - dmasound.volume_left); - len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n", - dmasound.volume_right); - if (len >= space) { - printk(KERN_ERR "dmasound_paula: overflowed state buffer alloc.\n") ; - len = space ; - } - return len; -} - - -/*** Machine definitions *****************************************************/ - -static SETTINGS def_hard = { - .format = AFMT_S8, - .stereo = 0, - .size = 8, - .speed = 8000 -} ; - -static SETTINGS def_soft = { - .format = AFMT_U8, - .stereo = 0, - .size = 8, - .speed = 8000 -} ; - -static MACHINE machAmiga = { - .name = "Amiga", - .name2 = "AMIGA", - .owner = THIS_MODULE, - .dma_alloc = AmiAlloc, - .dma_free = AmiFree, - .irqinit = AmiIrqInit, -#ifdef MODULE - .irqcleanup = AmiIrqCleanUp, -#endif /* MODULE */ - .init = AmiInit, - .silence = AmiSilence, - .setFormat = AmiSetFormat, - .setVolume = AmiSetVolume, - .setTreble = AmiSetTreble, - .play = AmiPlay, - .mixer_init = AmiMixerInit, - .mixer_ioctl = AmiMixerIoctl, - .write_sq_setup = AmiWriteSqSetup, - .state_info = AmiStateInfo, - .min_dsp_speed = 8000, - .version = ((DMASOUND_PAULA_REVISION<<8) | DMASOUND_PAULA_EDITION), - .hardware_afmts = (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */ - .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */ -}; - - -/*** Config & Setup **********************************************************/ - - -static int __init amiga_audio_probe(struct platform_device *pdev) -{ - dmasound.mach = machAmiga; - dmasound.mach.default_hard = def_hard ; - dmasound.mach.default_soft = def_soft ; - return dmasound_init(); -} - -static int __exit amiga_audio_remove(struct platform_device *pdev) -{ - dmasound_deinit(); - return 0; -} - -static struct platform_driver amiga_audio_driver = { - .remove = __exit_p(amiga_audio_remove), - .driver = { - .name = "amiga-audio", - .owner = THIS_MODULE, - }, -}; - -static int __init amiga_audio_init(void) -{ - return platform_driver_probe(&amiga_audio_driver, amiga_audio_probe); -} - -module_init(amiga_audio_init); - -static void __exit amiga_audio_exit(void) -{ - platform_driver_unregister(&amiga_audio_driver); -} - -module_exit(amiga_audio_exit); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:amiga-audio"); diff --git a/ANDROID_3.4.5/sound/oss/dmasound/dmasound_q40.c b/ANDROID_3.4.5/sound/oss/dmasound/dmasound_q40.c deleted file mode 100644 index 99bcb21c..00000000 --- a/ANDROID_3.4.5/sound/oss/dmasound/dmasound_q40.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * linux/sound/oss/dmasound/dmasound_q40.c - * - * Q40 DMA Sound Driver - * - * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits - * prior to 28/01/2001 - * - * 28/01/2001 [0.1] Iain Sandoe - * - added versioning - * - put in and populated the hardware_afmts field. - * [0.2] - put in SNDCTL_DSP_GETCAPS value. - * [0.3] - put in default hard/soft settings. - */ - - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "dmasound.h" - -#define DMASOUND_Q40_REVISION 0 -#define DMASOUND_Q40_EDITION 3 - -static int expand_bal; /* Balance factor for expanding (not volume!) */ -static int expand_data; /* Data for expanding */ - - -/*** Low level stuff *********************************************************/ - - -static void *Q40Alloc(unsigned int size, gfp_t flags); -static void Q40Free(void *, unsigned int); -static int Q40IrqInit(void); -#ifdef MODULE -static void Q40IrqCleanUp(void); -#endif -static void Q40Silence(void); -static void Q40Init(void); -static int Q40SetFormat(int format); -static int Q40SetVolume(int volume); -static void Q40PlayNextFrame(int index); -static void Q40Play(void); -static irqreturn_t Q40StereoInterrupt(int irq, void *dummy); -static irqreturn_t Q40MonoInterrupt(int irq, void *dummy); -static void Q40Interrupt(void); - - -/*** Mid level stuff *********************************************************/ - - - -/* userCount, frameUsed, frameLeft == byte counts */ -static ssize_t q40_ct_law(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8; - ssize_t count, used; - u_char *p = (u_char *) &frame[*frameUsed]; - - used = count = min_t(size_t, userCount, frameLeft); - if (copy_from_user(p,userPtr,count)) - return -EFAULT; - while (count > 0) { - *p = table[*p]+128; - p++; - count--; - } - *frameUsed += used ; - return used; -} - - -static ssize_t q40_ct_s8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - u_char *p = (u_char *) &frame[*frameUsed]; - - used = count = min_t(size_t, userCount, frameLeft); - if (copy_from_user(p,userPtr,count)) - return -EFAULT; - while (count > 0) { - *p = *p + 128; - p++; - count--; - } - *frameUsed += used; - return used; -} - -static ssize_t q40_ct_u8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - u_char *p = (u_char *) &frame[*frameUsed]; - - used = count = min_t(size_t, userCount, frameLeft); - if (copy_from_user(p,userPtr,count)) - return -EFAULT; - *frameUsed += used; - return used; -} - - -/* a bit too complicated to optimise right now ..*/ -static ssize_t q40_ctx_law(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned char *table = (unsigned char *) - (dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8); - unsigned int data = expand_data; - u_char *p = (u_char *) &frame[*frameUsed]; - int bal = expand_bal; - int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - int utotal, ftotal; - - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = table[c]; - data += 0x80; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft); - utotal -= userCount; - return utotal; -} - - -static ssize_t q40_ctx_s8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - u_char *p = (u_char *) &frame[*frameUsed]; - unsigned int data = expand_data; - int bal = expand_bal; - int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - int utotal, ftotal; - - - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = c ; - data += 0x80; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft); - utotal -= userCount; - return utotal; -} - - -static ssize_t q40_ctx_u8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - u_char *p = (u_char *) &frame[*frameUsed]; - unsigned int data = expand_data; - int bal = expand_bal; - int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - int utotal, ftotal; - - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - if (bal < 0) { - if (userCount == 0) - break; - if (get_user(c, userPtr++)) - return -EFAULT; - data = c ; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) ; - utotal -= userCount; - return utotal; -} - -/* compressing versions */ -static ssize_t q40_ctc_law(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - unsigned char *table = (unsigned char *) - (dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8); - unsigned int data = expand_data; - u_char *p = (u_char *) &frame[*frameUsed]; - int bal = expand_bal; - int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - int utotal, ftotal; - - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - while(bal<0) { - if (userCount == 0) - goto lout; - if (!(bal<(-hSpeed))) { - if (get_user(c, userPtr)) - return -EFAULT; - data = 0x80 + table[c]; - } - userPtr++; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - lout: - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft); - utotal -= userCount; - return utotal; -} - - -static ssize_t q40_ctc_s8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - u_char *p = (u_char *) &frame[*frameUsed]; - unsigned int data = expand_data; - int bal = expand_bal; - int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - int utotal, ftotal; - - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - while (bal < 0) { - if (userCount == 0) - goto lout; - if (!(bal<(-hSpeed))) { - if (get_user(c, userPtr)) - return -EFAULT; - data = c + 0x80; - } - userPtr++; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - lout: - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft); - utotal -= userCount; - return utotal; -} - - -static ssize_t q40_ctc_u8(const u_char __user *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - u_char *p = (u_char *) &frame[*frameUsed]; - unsigned int data = expand_data; - int bal = expand_bal; - int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; - int utotal, ftotal; - - ftotal = frameLeft; - utotal = userCount; - while (frameLeft) { - u_char c; - while (bal < 0) { - if (userCount == 0) - goto lout; - if (!(bal<(-hSpeed))) { - if (get_user(c, userPtr)) - return -EFAULT; - data = c ; - } - userPtr++; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - lout: - expand_bal = bal; - expand_data = data; - *frameUsed += (ftotal - frameLeft) ; - utotal -= userCount; - return utotal; -} - - -static TRANS transQ40Normal = { - q40_ct_law, q40_ct_law, q40_ct_s8, q40_ct_u8, NULL, NULL, NULL, NULL -}; - -static TRANS transQ40Expanding = { - q40_ctx_law, q40_ctx_law, q40_ctx_s8, q40_ctx_u8, NULL, NULL, NULL, NULL -}; - -static TRANS transQ40Compressing = { - q40_ctc_law, q40_ctc_law, q40_ctc_s8, q40_ctc_u8, NULL, NULL, NULL, NULL -}; - - -/*** Low level stuff *********************************************************/ - -static void *Q40Alloc(unsigned int size, gfp_t flags) -{ - return kmalloc(size, flags); /* change to vmalloc */ -} - -static void Q40Free(void *ptr, unsigned int size) -{ - kfree(ptr); -} - -static int __init Q40IrqInit(void) -{ - /* Register interrupt handler. */ - if (request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0, - "DMA sound", Q40Interrupt)) - return 0; - - return(1); -} - - -#ifdef MODULE -static void Q40IrqCleanUp(void) -{ - master_outb(0,SAMPLE_ENABLE_REG); - free_irq(Q40_IRQ_SAMPLE, Q40Interrupt); -} -#endif /* MODULE */ - - -static void Q40Silence(void) -{ - master_outb(0,SAMPLE_ENABLE_REG); - *DAC_LEFT=*DAC_RIGHT=127; -} - -static char *q40_pp; -static unsigned int q40_sc; - -static void Q40PlayNextFrame(int index) -{ - u_char *start; - u_long size; - u_char speed; - int error; - - /* used by Q40Play() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = write_sq.buffers[write_sq.front]; - size = (write_sq.count == index ? write_sq.rear_size : write_sq.block_size); - - q40_pp=start; - q40_sc=size; - - write_sq.front = (write_sq.front+1) % write_sq.max_count; - write_sq.active++; - - speed=(dmasound.hard.speed==10000 ? 0 : 1); - - master_outb( 0,SAMPLE_ENABLE_REG); - free_irq(Q40_IRQ_SAMPLE, Q40Interrupt); - if (dmasound.soft.stereo) - error = request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0, - "Q40 sound", Q40Interrupt); - else - error = request_irq(Q40_IRQ_SAMPLE, Q40MonoInterrupt, 0, - "Q40 sound", Q40Interrupt); - if (error && printk_ratelimit()) - pr_err("Couldn't register sound interrupt\n"); - - master_outb( speed, SAMPLE_RATE_REG); - master_outb( 1,SAMPLE_CLEAR_REG); - master_outb( 1,SAMPLE_ENABLE_REG); -} - -static void Q40Play(void) -{ - unsigned long flags; - - if (write_sq.active || write_sq.count<=0 ) { - /* There's already a frame loaded */ - return; - } - - /* nothing in the queue */ - if (write_sq.count <= 1 && write_sq.rear_size < write_sq.block_size && !write_sq.syncing) { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - return; - } - spin_lock_irqsave(&dmasound.lock, flags); - Q40PlayNextFrame(1); - spin_unlock_irqrestore(&dmasound.lock, flags); -} - -static irqreturn_t Q40StereoInterrupt(int irq, void *dummy) -{ - spin_lock(&dmasound.lock); - if (q40_sc>1){ - *DAC_LEFT=*q40_pp++; - *DAC_RIGHT=*q40_pp++; - q40_sc -=2; - master_outb(1,SAMPLE_CLEAR_REG); - }else Q40Interrupt(); - spin_unlock(&dmasound.lock); - return IRQ_HANDLED; -} -static irqreturn_t Q40MonoInterrupt(int irq, void *dummy) -{ - spin_lock(&dmasound.lock); - if (q40_sc>0){ - *DAC_LEFT=*q40_pp; - *DAC_RIGHT=*q40_pp++; - q40_sc --; - master_outb(1,SAMPLE_CLEAR_REG); - }else Q40Interrupt(); - spin_unlock(&dmasound.lock); - return IRQ_HANDLED; -} -static void Q40Interrupt(void) -{ - if (!write_sq.active) { - /* playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(write_sq.sync_queue); - master_outb(0,SAMPLE_ENABLE_REG); /* better safe */ - goto exit; - } else write_sq.active=0; - write_sq.count--; - Q40Play(); - - if (q40_sc<2) - { /* there was nothing to play, disable irq */ - master_outb(0,SAMPLE_ENABLE_REG); - *DAC_LEFT=*DAC_RIGHT=127; - } - WAKE_UP(write_sq.action_queue); - - exit: - master_outb(1,SAMPLE_CLEAR_REG); -} - - -static void Q40Init(void) -{ - int i, idx; - const int freq[] = {10000, 20000}; - - /* search a frequency that fits into the allowed error range */ - - idx = -1; - for (i = 0; i < 2; i++) - if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) <= catchRadius) - idx = i; - - dmasound.hard = dmasound.soft; - /*sound.hard.stereo=1;*/ /* no longer true */ - dmasound.hard.size=8; - - if (idx > -1) { - dmasound.soft.speed = freq[idx]; - dmasound.trans_write = &transQ40Normal; - } else - dmasound.trans_write = &transQ40Expanding; - - Q40Silence(); - - if (dmasound.hard.speed > 20200) { - /* squeeze the sound, we do that */ - dmasound.hard.speed = 20000; - dmasound.trans_write = &transQ40Compressing; - } else if (dmasound.hard.speed > 10000) { - dmasound.hard.speed = 20000; - } else { - dmasound.hard.speed = 10000; - } - expand_bal = -dmasound.soft.speed; -} - - -static int Q40SetFormat(int format) -{ - /* Q40 sound supports only 8bit modes */ - - switch (format) { - case AFMT_QUERY: - return(dmasound.soft.format); - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_S8: - case AFMT_U8: - break; - default: - format = AFMT_S8; - } - - dmasound.soft.format = format; - dmasound.soft.size = 8; - if (dmasound.minDev == SND_DEV_DSP) { - dmasound.dsp.format = format; - dmasound.dsp.size = 8; - } - Q40Init(); - - return(format); -} - -static int Q40SetVolume(int volume) -{ - return 0; -} - - -/*** Machine definitions *****************************************************/ - -static SETTINGS def_hard = { - .format = AFMT_U8, - .stereo = 0, - .size = 8, - .speed = 10000 -} ; - -static SETTINGS def_soft = { - .format = AFMT_U8, - .stereo = 0, - .size = 8, - .speed = 8000 -} ; - -static MACHINE machQ40 = { - .name = "Q40", - .name2 = "Q40", - .owner = THIS_MODULE, - .dma_alloc = Q40Alloc, - .dma_free = Q40Free, - .irqinit = Q40IrqInit, -#ifdef MODULE - .irqcleanup = Q40IrqCleanUp, -#endif /* MODULE */ - .init = Q40Init, - .silence = Q40Silence, - .setFormat = Q40SetFormat, - .setVolume = Q40SetVolume, - .play = Q40Play, - .min_dsp_speed = 10000, - .version = ((DMASOUND_Q40_REVISION<<8) | DMASOUND_Q40_EDITION), - .hardware_afmts = AFMT_U8, /* h'ware-supported formats *only* here */ - .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */ -}; - - -/*** Config & Setup **********************************************************/ - - -static int __init dmasound_q40_init(void) -{ - if (MACH_IS_Q40) { - dmasound.mach = machQ40; - dmasound.mach.default_hard = def_hard ; - dmasound.mach.default_soft = def_soft ; - return dmasound_init(); - } else - return -ENODEV; -} - -static void __exit dmasound_q40_cleanup(void) -{ - dmasound_deinit(); -} - -module_init(dmasound_q40_init); -module_exit(dmasound_q40_cleanup); - -MODULE_DESCRIPTION("Q40/Q60 sound driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/hex2hex.c b/ANDROID_3.4.5/sound/oss/hex2hex.c deleted file mode 100644 index 041ef5c5..00000000 --- a/ANDROID_3.4.5/sound/oss/hex2hex.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * hex2hex reads stdin in Intel HEX format and produces an - * (unsigned char) array which contains the bytes and writes it - * to stdout using C syntax - */ - -#include -#include -#include - -#define ABANDON(why) { fprintf(stderr, "%s\n", why); exit(1); } -#define MAX_SIZE (256*1024) -unsigned char buf[MAX_SIZE]; - -static int loadhex(FILE *inf, unsigned char *buf) -{ - int l=0, c, i; - - while ((c=getc(inf))!=EOF) - { - if (c == ':') /* Sync with beginning of line */ - { - int n, check; - unsigned char sum; - int addr; - int linetype; - - if (fscanf(inf, "%02x", &n) != 1) - ABANDON("File format error"); - sum = n; - - if (fscanf(inf, "%04x", &addr) != 1) - ABANDON("File format error"); - sum += addr/256; - sum += addr%256; - - if (fscanf(inf, "%02x", &linetype) != 1) - ABANDON("File format error"); - sum += linetype; - - if (linetype != 0) - continue; - - for (i=0;i= MAX_SIZE) - ABANDON("File too large"); - buf[addr++] = c; - if (addr > l) - l = addr; - sum += c; - } - - if (fscanf(inf, "%02x", &check) != 1) - ABANDON("File format error"); - - sum = ~sum + 1; - if (check != sum) - ABANDON("Line checksum error"); - } - } - - return l; -} - -int main( int argc, const char * argv [] ) -{ - const char * varline; - int i,l; - int id=0; - - if(argv[1] && strcmp(argv[1], "-i")==0) - { - argv++; - argc--; - id=1; - } - if(argv[1]==NULL) - { - fprintf(stderr,"hex2hex: [-i] filename\n"); - exit(1); - } - varline = argv[1]; - l = loadhex(stdin, buf); - - printf("/*\n *\t Computer generated file. Do not edit.\n */\n"); - printf("static int %s_len = %d;\n", varline, l); - printf("static unsigned char %s[] %s = {\n", varline, id?"__initdata":""); - - for (i=0;i - * - * XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems. - * The older version (VSA1) provides fairly good soundblaster emulation - * although there are a couple of bugs: large DMA buffers break record, - * and the MPU event handling seems suspect. VSA2 allows the native driver - * to control the AC97 audio engine directly and requires a different driver. - * - * Thanks to National Semiconductor for providing the needed information - * on the XpressAudio(tm) internals. - * - * 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, 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. - * - * TO DO: - * Investigate whether we can portably support Cognac (5520) in the - * same manner. - */ - -#include -#include -#include -#include -#include - -#include "sound_config.h" - -#include "sb.h" - -/* - * Read a soundblaster compatible mixer register. - * In this case we are actually reading an SMI trap - * not real hardware. - */ - -static u8 __devinit mixer_read(unsigned long io, u8 reg) -{ - outb(reg, io + 4); - udelay(20); - reg = inb(io + 5); - udelay(20); - return reg; -} - -static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct address_info *hw_config; - unsigned long base; - void __iomem *mem; - unsigned long io; - u16 map; - u8 irq, dma8, dma16; - int oldquiet; - extern int sb_be_quiet; - - base = pci_resource_start(pdev, 0); - if(base == 0UL) - return 1; - - mem = ioremap(base, 128); - if (!mem) - return 1; - map = readw(mem + 0x18); /* Read the SMI enables */ - iounmap(mem); - - /* Map bits - 0:1 * 0x20 + 0x200 = sb base - 2 sb enable - 3 adlib enable - 5 MPU enable 0x330 - 6 MPU enable 0x300 - - The other bits may be used internally so must be masked */ - - io = 0x220 + 0x20 * (map & 3); - - if(map & (1<<2)) - printk(KERN_INFO "kahlua: XpressAudio at 0x%lx\n", io); - else - return 1; - - if(map & (1<<5)) - printk(KERN_INFO "kahlua: MPU at 0x300\n"); - else if(map & (1<<6)) - printk(KERN_INFO "kahlua: MPU at 0x330\n"); - - irq = mixer_read(io, 0x80) & 0x0F; - dma8 = mixer_read(io, 0x81); - - // printk("IRQ=%x MAP=%x DMA=%x\n", irq, map, dma8); - - if(dma8 & 0x20) - dma16 = 5; - else if(dma8 & 0x40) - dma16 = 6; - else if(dma8 & 0x80) - dma16 = 7; - else - { - printk(KERN_ERR "kahlua: No 16bit DMA enabled.\n"); - return 1; - } - - if(dma8 & 0x01) - dma8 = 0; - else if(dma8 & 0x02) - dma8 = 1; - else if(dma8 & 0x08) - dma8 = 3; - else - { - printk(KERN_ERR "kahlua: No 8bit DMA enabled.\n"); - return 1; - } - - if(irq & 1) - irq = 9; - else if(irq & 2) - irq = 5; - else if(irq & 4) - irq = 7; - else if(irq & 8) - irq = 10; - else - { - printk(KERN_ERR "kahlua: SB IRQ not set.\n"); - return 1; - } - - printk(KERN_INFO "kahlua: XpressAudio on IRQ %d, DMA %d, %d\n", - irq, dma8, dma16); - - hw_config = kzalloc(sizeof(struct address_info), GFP_KERNEL); - if(hw_config == NULL) - { - printk(KERN_ERR "kahlua: out of memory.\n"); - return 1; - } - - pci_set_drvdata(pdev, hw_config); - - hw_config->io_base = io; - hw_config->irq = irq; - hw_config->dma = dma8; - hw_config->dma2 = dma16; - hw_config->name = "Cyrix XpressAudio"; - hw_config->driver_use_1 = SB_NO_MIDI | SB_PCI_IRQ; - - if (!request_region(io, 16, "soundblaster")) - goto err_out_free; - - if(sb_dsp_detect(hw_config, 0, 0, NULL)==0) - { - printk(KERN_ERR "kahlua: audio not responding.\n"); - release_region(io, 16); - goto err_out_free; - } - - oldquiet = sb_be_quiet; - sb_be_quiet = 1; - if(sb_dsp_init(hw_config, THIS_MODULE)) - { - sb_be_quiet = oldquiet; - goto err_out_free; - } - sb_be_quiet = oldquiet; - - return 0; - -err_out_free: - pci_set_drvdata(pdev, NULL); - kfree(hw_config); - return 1; -} - -static void __devexit remove_one(struct pci_dev *pdev) -{ - struct address_info *hw_config = pci_get_drvdata(pdev); - sb_dsp_unload(hw_config, 0); - pci_set_drvdata(pdev, NULL); - kfree(hw_config); -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("Kahlua VSA1 PCI Audio"); -MODULE_LICENSE("GPL"); - -/* - * 5530 only. The 5510/5520 decode is different. - */ - -static DEFINE_PCI_DEVICE_TABLE(id_tbl) = { - { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO), 0 }, - { } -}; - -MODULE_DEVICE_TABLE(pci, id_tbl); - -static struct pci_driver kahlua_driver = { - .name = "kahlua", - .id_table = id_tbl, - .probe = probe_one, - .remove = __devexit_p(remove_one), -}; - - -static int __init kahlua_init_module(void) -{ - printk(KERN_INFO "Cyrix Kahlua VSA1 XpressAudio support (c) Copyright 2003 Red Hat Inc\n"); - return pci_register_driver(&kahlua_driver); -} - -static void __devexit kahlua_cleanup_module(void) -{ - pci_unregister_driver(&kahlua_driver); -} - - -module_init(kahlua_init_module); -module_exit(kahlua_cleanup_module); - diff --git a/ANDROID_3.4.5/sound/oss/midi_ctrl.h b/ANDROID_3.4.5/sound/oss/midi_ctrl.h deleted file mode 100644 index 3353e5a6..00000000 --- a/ANDROID_3.4.5/sound/oss/midi_ctrl.h +++ /dev/null @@ -1,22 +0,0 @@ -static unsigned char ctrl_def_values[128] = -{ - 0x40,0x00,0x40,0x40, 0x40,0x40,0x40,0x7f, /* 0 to 7 */ - 0x40,0x40,0x40,0x7f, 0x40,0x40,0x40,0x40, /* 8 to 15 */ - 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 16 to 23 */ - 0x40,0x40,0x40,0x40, 0x40,0x40,0x40,0x40, /* 24 to 31 */ - - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 32 to 39 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 40 to 47 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 48 to 55 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 56 to 63 */ - - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 64 to 71 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 72 to 79 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 80 to 87 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 88 to 95 */ - - 0x00,0x00,0x7f,0x7f, 0x7f,0x7f,0x00,0x00, /* 96 to 103 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 104 to 111 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 112 to 119 */ - 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, /* 120 to 127 */ -}; diff --git a/ANDROID_3.4.5/sound/oss/midi_synth.c b/ANDROID_3.4.5/sound/oss/midi_synth.c deleted file mode 100644 index 2292c230..00000000 --- a/ANDROID_3.4.5/sound/oss/midi_synth.c +++ /dev/null @@ -1,712 +0,0 @@ -/* - * sound/oss/midi_synth.c - * - * High level midi sequencer manager for dumb MIDI interfaces. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * Andrew Veliath : fixed running status in MIDI input state machine - */ -#define USE_SEQ_MACROS -#define USE_SIMPLE_MACROS - -#include "sound_config.h" - -#define _MIDI_SYNTH_C_ - -#include "midi_synth.h" - -static int midi2synth[MAX_MIDI_DEV]; -static int sysex_state[MAX_MIDI_DEV] = -{0}; -static unsigned char prev_out_status[MAX_MIDI_DEV]; - -#define STORE(cmd) \ -{ \ - int len; \ - unsigned char obuf[8]; \ - cmd; \ - seq_input_event(obuf, len); \ -} - -#define _seqbuf obuf -#define _seqbufptr 0 -#define _SEQ_ADVBUF(x) len=x - -void -do_midi_msg(int synthno, unsigned char *msg, int mlen) -{ - switch (msg[0] & 0xf0) - { - case 0x90: - if (msg[2] != 0) - { - STORE(SEQ_START_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - } - msg[2] = 64; - - case 0x80: - STORE(SEQ_STOP_NOTE(synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - - case 0xA0: - STORE(SEQ_KEY_PRESSURE(synthno, msg[0] & 0x0f, msg[1], msg[2])); - break; - - case 0xB0: - STORE(SEQ_CONTROL(synthno, msg[0] & 0x0f, - msg[1], msg[2])); - break; - - case 0xC0: - STORE(SEQ_SET_PATCH(synthno, msg[0] & 0x0f, msg[1])); - break; - - case 0xD0: - STORE(SEQ_CHN_PRESSURE(synthno, msg[0] & 0x0f, msg[1])); - break; - - case 0xE0: - STORE(SEQ_BENDER(synthno, msg[0] & 0x0f, - (msg[1] & 0x7f) | ((msg[2] & 0x7f) << 7))); - break; - - default: - /* printk( "MPU: Unknown midi channel message %02x\n", msg[0]); */ - ; - } -} -EXPORT_SYMBOL(do_midi_msg); - -static void -midi_outc(int midi_dev, int data) -{ - int timeout; - - for (timeout = 0; timeout < 3200; timeout++) - if (midi_devs[midi_dev]->outputc(midi_dev, (unsigned char) (data & 0xff))) - { - if (data & 0x80) /* - * Status byte - */ - prev_out_status[midi_dev] = - (unsigned char) (data & 0xff); /* - * Store for running status - */ - return; /* - * Mission complete - */ - } - /* - * Sorry! No space on buffers. - */ - printk("Midi send timed out\n"); -} - -static int -prefix_cmd(int midi_dev, unsigned char status) -{ - if ((char *) midi_devs[midi_dev]->prefix_cmd == NULL) - return 1; - - return midi_devs[midi_dev]->prefix_cmd(midi_dev, status); -} - -static void -midi_synth_input(int orig_dev, unsigned char data) -{ - int dev; - struct midi_input_info *inc; - - static unsigned char len_tab[] = /* # of data bytes following a status - */ - { - 2, /* 8x */ - 2, /* 9x */ - 2, /* Ax */ - 2, /* Bx */ - 1, /* Cx */ - 1, /* Dx */ - 2, /* Ex */ - 0 /* Fx */ - }; - - if (orig_dev < 0 || orig_dev > num_midis || midi_devs[orig_dev] == NULL) - return; - - if (data == 0xfe) /* Ignore active sensing */ - return; - - dev = midi2synth[orig_dev]; - inc = &midi_devs[orig_dev]->in_info; - - switch (inc->m_state) - { - case MST_INIT: - if (data & 0x80) /* MIDI status byte */ - { - if ((data & 0xf0) == 0xf0) /* Common message */ - { - switch (data) - { - case 0xf0: /* Sysex */ - inc->m_state = MST_SYSEX; - break; /* Sysex */ - - case 0xf1: /* MTC quarter frame */ - case 0xf3: /* Song select */ - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = 1; - inc->m_buf[0] = data; - break; - - case 0xf2: /* Song position pointer */ - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = 2; - inc->m_buf[0] = data; - break; - - default: - inc->m_buf[0] = data; - inc->m_ptr = 1; - do_midi_msg(dev, inc->m_buf, inc->m_ptr); - inc->m_ptr = 0; - inc->m_left = 0; - } - } else - { - inc->m_state = MST_DATA; - inc->m_ptr = 1; - inc->m_left = len_tab[(data >> 4) - 8]; - inc->m_buf[0] = inc->m_prev_status = data; - } - } else if (inc->m_prev_status & 0x80) { - /* Data byte (use running status) */ - inc->m_ptr = 2; - inc->m_buf[1] = data; - inc->m_buf[0] = inc->m_prev_status; - inc->m_left = len_tab[(inc->m_buf[0] >> 4) - 8] - 1; - if (inc->m_left > 0) - inc->m_state = MST_DATA; /* Not done yet */ - else { - inc->m_state = MST_INIT; - do_midi_msg(dev, inc->m_buf, inc->m_ptr); - inc->m_ptr = 0; - } - } - break; /* MST_INIT */ - - case MST_DATA: - inc->m_buf[inc->m_ptr++] = data; - if (--inc->m_left <= 0) - { - inc->m_state = MST_INIT; - do_midi_msg(dev, inc->m_buf, inc->m_ptr); - inc->m_ptr = 0; - } - break; /* MST_DATA */ - - case MST_SYSEX: - if (data == 0xf7) /* Sysex end */ - { - inc->m_state = MST_INIT; - inc->m_left = 0; - inc->m_ptr = 0; - } - break; /* MST_SYSEX */ - - default: - printk("MIDI%d: Unexpected state %d (%02x)\n", orig_dev, inc->m_state, (int) data); - inc->m_state = MST_INIT; - } -} - -static void -leave_sysex(int dev) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int timeout = 0; - - if (!sysex_state[dev]) - return; - - sysex_state[dev] = 0; - - while (!midi_devs[orig_dev]->outputc(orig_dev, 0xf7) && - timeout < 1000) - timeout++; - - sysex_state[dev] = 0; -} - -static void -midi_synth_output(int dev) -{ - /* - * Currently NOP - */ -} - -int midi_synth_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - /* - * int orig_dev = synth_devs[dev]->midi_dev; - */ - - switch (cmd) { - - case SNDCTL_SYNTH_INFO: - if (__copy_to_user(arg, synth_devs[dev]->info, sizeof(struct synth_info))) - return -EFAULT; - return 0; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - - default: - return -EINVAL; - } -} -EXPORT_SYMBOL(midi_synth_ioctl); - -int -midi_synth_kill_note(int dev, int channel, int note, int velocity) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (note < 0 || note > 127) - return 0; - if (channel < 0 || channel > 15) - return 0; - if (velocity < 0) - velocity = 0; - if (velocity > 127) - velocity = 127; - - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (chn == channel && ((msg == 0x90 && velocity == 64) || msg == 0x80)) - { /* - * Use running status - */ - if (!prefix_cmd(orig_dev, note)) - return 0; - - midi_outc(orig_dev, note); - - if (msg == 0x90) /* - * Running status = Note on - */ - midi_outc(orig_dev, 0); /* - * Note on with velocity 0 == note - * off - */ - else - midi_outc(orig_dev, velocity); - } else - { - if (velocity == 64) - { - if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f))) - return 0; - midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* - * Note on - */ - midi_outc(orig_dev, note); - midi_outc(orig_dev, 0); /* - * Zero G - */ - } else - { - if (!prefix_cmd(orig_dev, 0x80 | (channel & 0x0f))) - return 0; - midi_outc(orig_dev, 0x80 | (channel & 0x0f)); /* - * Note off - */ - midi_outc(orig_dev, note); - midi_outc(orig_dev, velocity); - } - } - - return 0; -} -EXPORT_SYMBOL(midi_synth_kill_note); - -int -midi_synth_set_instr(int dev, int channel, int instr_no) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - if (instr_no < 0 || instr_no > 127) - instr_no = 0; - if (channel < 0 || channel > 15) - return 0; - - leave_sysex(dev); - - if (!prefix_cmd(orig_dev, 0xc0 | (channel & 0x0f))) - return 0; - midi_outc(orig_dev, 0xc0 | (channel & 0x0f)); /* - * Program change - */ - midi_outc(orig_dev, instr_no); - - return 0; -} -EXPORT_SYMBOL(midi_synth_set_instr); - -int -midi_synth_start_note(int dev, int channel, int note, int velocity) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (note < 0 || note > 127) - return 0; - if (channel < 0 || channel > 15) - return 0; - if (velocity < 0) - velocity = 0; - if (velocity > 127) - velocity = 127; - - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (chn == channel && msg == 0x90) - { /* - * Use running status - */ - if (!prefix_cmd(orig_dev, note)) - return 0; - midi_outc(orig_dev, note); - midi_outc(orig_dev, velocity); - } else - { - if (!prefix_cmd(orig_dev, 0x90 | (channel & 0x0f))) - return 0; - midi_outc(orig_dev, 0x90 | (channel & 0x0f)); /* - * Note on - */ - midi_outc(orig_dev, note); - midi_outc(orig_dev, velocity); - } - return 0; -} -EXPORT_SYMBOL(midi_synth_start_note); - -void -midi_synth_reset(int dev) -{ - - leave_sysex(dev); -} -EXPORT_SYMBOL(midi_synth_reset); - -int -midi_synth_open(int dev, int mode) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int err; - struct midi_input_info *inc; - - if (orig_dev < 0 || orig_dev >= num_midis || midi_devs[orig_dev] == NULL) - return -ENXIO; - - midi2synth[orig_dev] = dev; - sysex_state[dev] = 0; - prev_out_status[orig_dev] = 0; - - if ((err = midi_devs[orig_dev]->open(orig_dev, mode, - midi_synth_input, midi_synth_output)) < 0) - return err; - inc = &midi_devs[orig_dev]->in_info; - - /* save_flags(flags); - cli(); - don't know against what irqhandler to protect*/ - inc->m_busy = 0; - inc->m_state = MST_INIT; - inc->m_ptr = 0; - inc->m_left = 0; - inc->m_prev_status = 0x00; - /* restore_flags(flags); */ - - return 1; -} -EXPORT_SYMBOL(midi_synth_open); - -void -midi_synth_close(int dev) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - leave_sysex(dev); - - /* - * Shut up the synths by sending just single active sensing message. - */ - midi_devs[orig_dev]->outputc(orig_dev, 0xfe); - - midi_devs[orig_dev]->close(orig_dev); -} -EXPORT_SYMBOL(midi_synth_close); - -void -midi_synth_hw_control(int dev, unsigned char *event) -{ -} -EXPORT_SYMBOL(midi_synth_hw_control); - -int -midi_synth_load_patch(int dev, int format, const char __user *addr, - int count, int pmgr_flag) -{ - int orig_dev = synth_devs[dev]->midi_dev; - - struct sysex_info sysex; - int i; - unsigned long left, src_offs, eox_seen = 0; - int first_byte = 1; - int hdr_size = (unsigned long) &sysex.data[0] - (unsigned long) &sysex; - - leave_sysex(dev); - - if (!prefix_cmd(orig_dev, 0xf0)) - return 0; - - /* Invalid patch format */ - if (format != SYSEX_PATCH) - return -EINVAL; - - /* Patch header too short */ - if (count < hdr_size) - return -EINVAL; - - count -= hdr_size; - - /* - * Copy the header from user space - */ - - if (copy_from_user(&sysex, addr, hdr_size)) - return -EFAULT; - - /* Sysex record too short */ - if ((unsigned)count < (unsigned)sysex.len) - sysex.len = count; - - left = sysex.len; - src_offs = 0; - - for (i = 0; i < left && !signal_pending(current); i++) - { - unsigned char data; - - if (get_user(data, - (unsigned char __user *)(addr + hdr_size + i))) - return -EFAULT; - - eox_seen = (i > 0 && data & 0x80); /* End of sysex */ - - if (eox_seen && data != 0xf7) - data = 0xf7; - - if (i == 0) - { - if (data != 0xf0) - { - printk(KERN_WARNING "midi_synth: Sysex start missing\n"); - return -EINVAL; - } - } - while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) && - !signal_pending(current)) - schedule(); - - if (!first_byte && data & 0x80) - return 0; - first_byte = 0; - } - - if (!eox_seen) - midi_outc(orig_dev, 0xf7); - return 0; -} -EXPORT_SYMBOL(midi_synth_load_patch); - -void midi_synth_panning(int dev, int channel, int pressure) -{ -} -EXPORT_SYMBOL(midi_synth_panning); - -void midi_synth_aftertouch(int dev, int channel, int pressure) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, chn; - - if (pressure < 0 || pressure > 127) - return; - if (channel < 0 || channel > 15) - return; - - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xd0 || chn != channel) /* - * Test for running status - */ - { - if (!prefix_cmd(orig_dev, 0xd0 | (channel & 0x0f))) - return; - midi_outc(orig_dev, 0xd0 | (channel & 0x0f)); /* - * Channel pressure - */ - } else if (!prefix_cmd(orig_dev, pressure)) - return; - - midi_outc(orig_dev, pressure); -} -EXPORT_SYMBOL(midi_synth_aftertouch); - -void -midi_synth_controller(int dev, int channel, int ctrl_num, int value) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int chn, msg; - - if (ctrl_num < 0 || ctrl_num > 127) - return; - if (channel < 0 || channel > 15) - return; - - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xb0 || chn != channel) - { - if (!prefix_cmd(orig_dev, 0xb0 | (channel & 0x0f))) - return; - midi_outc(orig_dev, 0xb0 | (channel & 0x0f)); - } else if (!prefix_cmd(orig_dev, ctrl_num)) - return; - - midi_outc(orig_dev, ctrl_num); - midi_outc(orig_dev, value & 0x7f); -} -EXPORT_SYMBOL(midi_synth_controller); - -void -midi_synth_bender(int dev, int channel, int value) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int msg, prev_chn; - - if (channel < 0 || channel > 15) - return; - - if (value < 0 || value > 16383) - return; - - leave_sysex(dev); - - msg = prev_out_status[orig_dev] & 0xf0; - prev_chn = prev_out_status[orig_dev] & 0x0f; - - if (msg != 0xd0 || prev_chn != channel) /* - * Test for running status - */ - { - if (!prefix_cmd(orig_dev, 0xe0 | (channel & 0x0f))) - return; - midi_outc(orig_dev, 0xe0 | (channel & 0x0f)); - } else if (!prefix_cmd(orig_dev, value & 0x7f)) - return; - - midi_outc(orig_dev, value & 0x7f); - midi_outc(orig_dev, (value >> 7) & 0x7f); -} -EXPORT_SYMBOL(midi_synth_bender); - -void -midi_synth_setup_voice(int dev, int voice, int channel) -{ -} -EXPORT_SYMBOL(midi_synth_setup_voice); - -int -midi_synth_send_sysex(int dev, unsigned char *bytes, int len) -{ - int orig_dev = synth_devs[dev]->midi_dev; - int i; - - for (i = 0; i < len; i++) - { - switch (bytes[i]) - { - case 0xf0: /* Start sysex */ - if (!prefix_cmd(orig_dev, 0xf0)) - return 0; - sysex_state[dev] = 1; - break; - - case 0xf7: /* End sysex */ - if (!sysex_state[dev]) /* Orphan sysex end */ - return 0; - sysex_state[dev] = 0; - break; - - default: - if (!sysex_state[dev]) - return 0; - - if (bytes[i] & 0x80) /* Error. Another message before sysex end */ - { - bytes[i] = 0xf7; /* Sysex end */ - sysex_state[dev] = 0; - } - } - - if (!midi_devs[orig_dev]->outputc(orig_dev, bytes[i])) - { -/* - * Hardware level buffer is full. Abort the sysex message. - */ - - int timeout = 0; - - bytes[i] = 0xf7; - sysex_state[dev] = 0; - - while (!midi_devs[orig_dev]->outputc(orig_dev, bytes[i]) && - timeout < 1000) - timeout++; - } - if (!sysex_state[dev]) - return 0; - } - - return 0; -} -EXPORT_SYMBOL(midi_synth_send_sysex); - diff --git a/ANDROID_3.4.5/sound/oss/midi_synth.h b/ANDROID_3.4.5/sound/oss/midi_synth.h deleted file mode 100644 index b64ddd6c..00000000 --- a/ANDROID_3.4.5/sound/oss/midi_synth.h +++ /dev/null @@ -1,47 +0,0 @@ -int midi_synth_ioctl (int dev, - unsigned int cmd, void __user * arg); -int midi_synth_kill_note (int dev, int channel, int note, int velocity); -int midi_synth_set_instr (int dev, int channel, int instr_no); -int midi_synth_start_note (int dev, int channel, int note, int volume); -void midi_synth_reset (int dev); -int midi_synth_open (int dev, int mode); -void midi_synth_close (int dev); -void midi_synth_hw_control (int dev, unsigned char *event); -int midi_synth_load_patch (int dev, int format, const char __user * addr, - int count, int pmgr_flag); -void midi_synth_panning (int dev, int channel, int pressure); -void midi_synth_aftertouch (int dev, int channel, int pressure); -void midi_synth_controller (int dev, int channel, int ctrl_num, int value); -void midi_synth_bender (int dev, int chn, int value); -void midi_synth_setup_voice (int dev, int voice, int chn); -int midi_synth_send_sysex(int dev, unsigned char *bytes,int len); - -#ifndef _MIDI_SYNTH_C_ -static struct synth_info std_synth_info = -{MIDI_SYNTH_NAME, 0, SYNTH_TYPE_MIDI, 0, 0, 128, 0, 128, MIDI_SYNTH_CAPS}; - -static struct synth_operations std_midi_synth = -{ - .owner = THIS_MODULE, - .id = "MIDI", - .info = &std_synth_info, - .midi_dev = 0, - .synth_type = SYNTH_TYPE_MIDI, - .synth_subtype = 0, - .open = midi_synth_open, - .close = midi_synth_close, - .ioctl = midi_synth_ioctl, - .kill_note = midi_synth_kill_note, - .start_note = midi_synth_start_note, - .set_instr = midi_synth_set_instr, - .reset = midi_synth_reset, - .hw_control = midi_synth_hw_control, - .load_patch = midi_synth_load_patch, - .aftertouch = midi_synth_aftertouch, - .controller = midi_synth_controller, - .panning = midi_synth_panning, - .bender = midi_synth_bender, - .setup_voice = midi_synth_setup_voice, - .send_sysex = midi_synth_send_sysex -}; -#endif diff --git a/ANDROID_3.4.5/sound/oss/midibuf.c b/ANDROID_3.4.5/sound/oss/midibuf.c deleted file mode 100644 index 8cdb2cfe..00000000 --- a/ANDROID_3.4.5/sound/oss/midibuf.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * sound/oss/midibuf.c - * - * Device file manager for /dev/midi# - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - */ -#include -#include -#include -#define MIDIBUF_C - -#include "sound_config.h" - - -/* - * Don't make MAX_QUEUE_SIZE larger than 4000 - */ - -#define MAX_QUEUE_SIZE 4000 - -static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV]; -static wait_queue_head_t input_sleeper[MAX_MIDI_DEV]; - -struct midi_buf -{ - int len, head, tail; - unsigned char queue[MAX_QUEUE_SIZE]; -}; - -struct midi_parms -{ - long prech_timeout; /* - * Timeout before the first ch - */ -}; - -static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL}; -static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL}; -static struct midi_parms parms[MAX_MIDI_DEV]; - -static void midi_poll(unsigned long dummy); - - -static DEFINE_TIMER(poll_timer, midi_poll, 0, 0); - -static volatile int open_devs; -static DEFINE_SPINLOCK(lock); - -#define DATA_AVAIL(q) (q->len) -#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len) - -#define QUEUE_BYTE(q, data) \ - if (SPACE_AVAIL(q)) \ - { \ - unsigned long flags; \ - spin_lock_irqsave(&lock, flags); \ - q->queue[q->tail] = (data); \ - q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \ - spin_unlock_irqrestore(&lock, flags); \ - } - -#define REMOVE_BYTE(q, data) \ - if (DATA_AVAIL(q)) \ - { \ - unsigned long flags; \ - spin_lock_irqsave(&lock, flags); \ - data = q->queue[q->head]; \ - q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \ - spin_unlock_irqrestore(&lock, flags); \ - } - -static void drain_midi_queue(int dev) -{ - - /* - * Give the Midi driver time to drain its output queues - */ - - if (midi_devs[dev]->buffer_status != NULL) - while (!signal_pending(current) && midi_devs[dev]->buffer_status(dev)) - interruptible_sleep_on_timeout(&midi_sleeper[dev], - HZ/10); -} - -static void midi_input_intr(int dev, unsigned char data) -{ - if (midi_in_buf[dev] == NULL) - return; - - if (data == 0xfe) /* - * Active sensing - */ - return; /* - * Ignore - */ - - if (SPACE_AVAIL(midi_in_buf[dev])) { - QUEUE_BYTE(midi_in_buf[dev], data); - wake_up(&input_sleeper[dev]); - } -} - -static void midi_output_intr(int dev) -{ - /* - * Currently NOP - */ -} - -static void midi_poll(unsigned long dummy) -{ - unsigned long flags; - int dev; - - spin_lock_irqsave(&lock, flags); - if (open_devs) - { - for (dev = 0; dev < num_midis; dev++) - if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL) - { - while (DATA_AVAIL(midi_out_buf[dev])) - { - int ok; - int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head]; - - spin_unlock_irqrestore(&lock,flags);/* Give some time to others */ - ok = midi_devs[dev]->outputc(dev, c); - spin_lock_irqsave(&lock, flags); - if (!ok) - break; - midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE; - midi_out_buf[dev]->len--; - } - - if (DATA_AVAIL(midi_out_buf[dev]) < 100) - wake_up(&midi_sleeper[dev]); - } - poll_timer.expires = (1) + jiffies; - add_timer(&poll_timer); - /* - * Come back later - */ - } - spin_unlock_irqrestore(&lock, flags); -} - -int MIDIbuf_open(int dev, struct file *file) -{ - int mode, err; - - dev = dev >> 4; - mode = translate_mode(file); - - if (num_midis > MAX_MIDI_DEV) - { - printk(KERN_ERR "midi: Too many midi interfaces\n"); - num_midis = MAX_MIDI_DEV; - } - if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) - return -ENXIO; - /* - * Interrupts disabled. Be careful - */ - - module_put(midi_devs[dev]->owner); - - if ((err = midi_devs[dev]->open(dev, mode, - midi_input_intr, midi_output_intr)) < 0) - return err; - - parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT; - midi_in_buf[dev] = vmalloc(sizeof(struct midi_buf)); - - if (midi_in_buf[dev] == NULL) - { - printk(KERN_WARNING "midi: Can't allocate buffer\n"); - midi_devs[dev]->close(dev); - return -EIO; - } - midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; - - midi_out_buf[dev] = vmalloc(sizeof(struct midi_buf)); - - if (midi_out_buf[dev] == NULL) - { - printk(KERN_WARNING "midi: Can't allocate buffer\n"); - midi_devs[dev]->close(dev); - vfree(midi_in_buf[dev]); - midi_in_buf[dev] = NULL; - return -EIO; - } - midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0; - open_devs++; - - init_waitqueue_head(&midi_sleeper[dev]); - init_waitqueue_head(&input_sleeper[dev]); - - if (open_devs < 2) /* This was first open */ - { - poll_timer.expires = 1 + jiffies; - add_timer(&poll_timer); /* Start polling */ - } - return err; -} - -void MIDIbuf_release(int dev, struct file *file) -{ - int mode; - - dev = dev >> 4; - mode = translate_mode(file); - - if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) - return; - - /* - * Wait until the queue is empty - */ - - if (mode != OPEN_READ) - { - midi_devs[dev]->outputc(dev, 0xfe); /* - * Active sensing to shut the - * devices - */ - - while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev])) - interruptible_sleep_on(&midi_sleeper[dev]); - /* - * Sync - */ - - drain_midi_queue(dev); /* - * Ensure the output queues are empty - */ - } - - midi_devs[dev]->close(dev); - - open_devs--; - if (open_devs == 0) - del_timer_sync(&poll_timer); - vfree(midi_in_buf[dev]); - vfree(midi_out_buf[dev]); - midi_in_buf[dev] = NULL; - midi_out_buf[dev] = NULL; - - module_put(midi_devs[dev]->owner); -} - -int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count) -{ - int c, n, i; - unsigned char tmp_data; - - dev = dev >> 4; - - if (!count) - return 0; - - c = 0; - - while (c < count) - { - n = SPACE_AVAIL(midi_out_buf[dev]); - - if (n == 0) { /* - * No space just now. - */ - - if (file->f_flags & O_NONBLOCK) { - c = -EAGAIN; - goto out; - } - - interruptible_sleep_on(&midi_sleeper[dev]); - if (signal_pending(current)) - { - c = -EINTR; - goto out; - } - n = SPACE_AVAIL(midi_out_buf[dev]); - } - if (n > (count - c)) - n = count - c; - - for (i = 0; i < n; i++) - { - /* BROKE BROKE BROKE - CAN'T DO THIS WITH CLI !! */ - /* yes, think the same, so I removed the cli() brackets - QUEUE_BYTE is protected against interrupts */ - if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) { - c = -EFAULT; - goto out; - } - QUEUE_BYTE(midi_out_buf[dev], tmp_data); - c++; - } - } -out: - return c; -} - - -int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count) -{ - int n, c = 0; - unsigned char tmp_data; - - dev = dev >> 4; - - if (!DATA_AVAIL(midi_in_buf[dev])) { /* - * No data yet, wait - */ - if (file->f_flags & O_NONBLOCK) { - c = -EAGAIN; - goto out; - } - interruptible_sleep_on_timeout(&input_sleeper[dev], - parms[dev].prech_timeout); - - if (signal_pending(current)) - c = -EINTR; /* The user is getting restless */ - } - if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) /* - * Got some bytes - */ - { - n = DATA_AVAIL(midi_in_buf[dev]); - if (n > count) - n = count; - c = 0; - - while (c < n) - { - char *fixit; - REMOVE_BYTE(midi_in_buf[dev], tmp_data); - fixit = (char *) &tmp_data; - /* BROKE BROKE BROKE */ - /* yes removed the cli() brackets again - should q->len,tail&head be atomic_t? */ - if (copy_to_user(&(buf)[c], fixit, 1)) { - c = -EFAULT; - goto out; - } - c++; - } - } -out: - return c; -} - -int MIDIbuf_ioctl(int dev, struct file *file, - unsigned int cmd, void __user *arg) -{ - int val; - - dev = dev >> 4; - - if (((cmd >> 8) & 0xff) == 'C') - { - if (midi_devs[dev]->coproc) /* Coprocessor ioctl */ - return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0); -/* printk("/dev/midi%d: No coprocessor for this device\n", dev);*/ - return -ENXIO; - } - else - { - switch (cmd) - { - case SNDCTL_MIDI_PRETIME: - if (get_user(val, (int __user *)arg)) - return -EFAULT; - if (val < 0) - val = 0; - val = (HZ * val) / 10; - parms[dev].prech_timeout = val; - return put_user(val, (int __user *)arg); - - default: - if (!midi_devs[dev]->ioctl) - return -EINVAL; - return midi_devs[dev]->ioctl(dev, cmd, arg); - } - } -} - -/* No kernel lock - fine */ -unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait) -{ - unsigned int mask = 0; - - dev = dev >> 4; - - /* input */ - poll_wait(file, &input_sleeper[dev], wait); - if (DATA_AVAIL(midi_in_buf[dev])) - mask |= POLLIN | POLLRDNORM; - - /* output */ - poll_wait(file, &midi_sleeper[dev], wait); - if (!SPACE_AVAIL(midi_out_buf[dev])) - mask |= POLLOUT | POLLWRNORM; - - return mask; -} - - -int MIDIbuf_avail(int dev) -{ - if (midi_in_buf[dev]) - return DATA_AVAIL (midi_in_buf[dev]); - return 0; -} -EXPORT_SYMBOL(MIDIbuf_avail); - diff --git a/ANDROID_3.4.5/sound/oss/mpu401.c b/ANDROID_3.4.5/sound/oss/mpu401.c deleted file mode 100644 index 25e4609f..00000000 --- a/ANDROID_3.4.5/sound/oss/mpu401.c +++ /dev/null @@ -1,1806 +0,0 @@ -/* - * sound/oss/mpu401.c - * - * The low level driver for Roland MPU-401 compatible Midi cards. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) - * Alan Cox modularisation, use normal request_irq, use dev_id - * Bartlomiej Zolnierkiewicz removed some __init to allow using many drivers - * Chris Rankin Update the module-usage counter for the coprocessor - * Zwane Mwaikambo Changed attach/unload resource freeing - */ - -#include -#include -#include -#include -#include -#define USE_SEQ_MACROS -#define USE_SIMPLE_MACROS - -#include "sound_config.h" - -#include "coproc.h" -#include "mpu401.h" - -static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL; - -struct mpu_config -{ - int base; /* - * I/O base - */ - int irq; - int opened; /* - * Open mode - */ - int devno; - int synthno; - int uart_mode; - int initialized; - int mode; -#define MODE_MIDI 1 -#define MODE_SYNTH 2 - unsigned char version, revision; - unsigned int capabilities; -#define MPU_CAP_INTLG 0x10000000 -#define MPU_CAP_SYNC 0x00000010 -#define MPU_CAP_FSK 0x00000020 -#define MPU_CAP_CLS 0x00000040 -#define MPU_CAP_SMPTE 0x00000080 -#define MPU_CAP_2PORT 0x00000001 - int timer_flag; - -#define MBUF_MAX 10 -#define BUFTEST(dc) if (dc->m_ptr >= MBUF_MAX || dc->m_ptr < 0) \ - {printk( "MPU: Invalid buffer pointer %d/%d, s=%d\n", dc->m_ptr, dc->m_left, dc->m_state);dc->m_ptr--;} - int m_busy; - unsigned char m_buf[MBUF_MAX]; - int m_ptr; - int m_state; - int m_left; - unsigned char last_status; - void (*inputintr) (int dev, unsigned char data); - int shared_irq; - int *osp; - spinlock_t lock; - }; - -#define DATAPORT(base) (base) -#define COMDPORT(base) (base+1) -#define STATPORT(base) (base+1) - - -static void mpu401_close(int dev); - -static inline int mpu401_status(struct mpu_config *devc) -{ - return inb(STATPORT(devc->base)); -} - -#define input_avail(devc) (!(mpu401_status(devc)&INPUT_AVAIL)) -#define output_ready(devc) (!(mpu401_status(devc)&OUTPUT_READY)) - -static inline void write_command(struct mpu_config *devc, unsigned char cmd) -{ - outb(cmd, COMDPORT(devc->base)); -} - -static inline int read_data(struct mpu_config *devc) -{ - return inb(DATAPORT(devc->base)); -} - -static inline void write_data(struct mpu_config *devc, unsigned char byte) -{ - outb(byte, DATAPORT(devc->base)); -} - -#define OUTPUT_READY 0x40 -#define INPUT_AVAIL 0x80 -#define MPU_ACK 0xFE -#define MPU_RESET 0xFF -#define UART_MODE_ON 0x3F - -static struct mpu_config dev_conf[MAX_MIDI_DEV]; - -static int n_mpu_devs; - -static int reset_mpu401(struct mpu_config *devc); -static void set_uart_mode(int dev, struct mpu_config *devc, int arg); - -static int mpu_timer_init(int midi_dev); -static void mpu_timer_interrupt(void); -static void timer_ext_event(struct mpu_config *devc, int event, int parm); - -static struct synth_info mpu_synth_info_proto = { - "MPU-401 MIDI interface", - 0, - SYNTH_TYPE_MIDI, - MIDI_TYPE_MPU401, - 0, 128, - 0, 128, - SYNTH_CAP_INPUT -}; - -static struct synth_info mpu_synth_info[MAX_MIDI_DEV]; - -/* - * States for the input scanner - */ - -#define ST_INIT 0 /* Ready for timing byte or msg */ -#define ST_TIMED 1 /* Leading timing byte rcvd */ -#define ST_DATABYTE 2 /* Waiting for (nr_left) data bytes */ - -#define ST_SYSMSG 100 /* System message (sysx etc). */ -#define ST_SYSEX 101 /* System exclusive msg */ -#define ST_MTC 102 /* Midi Time Code (MTC) qframe msg */ -#define ST_SONGSEL 103 /* Song select */ -#define ST_SONGPOS 104 /* Song position pointer */ - -static unsigned char len_tab[] = /* # of data bytes following a status - */ -{ - 2, /* 8x */ - 2, /* 9x */ - 2, /* Ax */ - 2, /* Bx */ - 1, /* Cx */ - 1, /* Dx */ - 2, /* Ex */ - 0 /* Fx */ -}; - -#define STORE(cmd) \ -{ \ - int len; \ - unsigned char obuf[8]; \ - cmd; \ - seq_input_event(obuf, len); \ -} - -#define _seqbuf obuf -#define _seqbufptr 0 -#define _SEQ_ADVBUF(x) len=x - -static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic) -{ - - switch (devc->m_state) - { - case ST_INIT: - switch (midic) - { - case 0xf8: - /* Timer overflow */ - break; - - case 0xfc: - printk(""); - break; - - case 0xfd: - if (devc->timer_flag) - mpu_timer_interrupt(); - break; - - case 0xfe: - return MPU_ACK; - - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - printk("", midic & 0x0f); - break; - - case 0xf9: - printk(""); - break; - - case 0xff: - devc->m_state = ST_SYSMSG; - break; - - default: - if (midic <= 0xef) - { - /* printk( "mpu time: %d ", midic); */ - devc->m_state = ST_TIMED; - } - else - printk(" ", midic); - } - break; - - case ST_TIMED: - { - int msg = ((int) (midic & 0xf0) >> 4); - - devc->m_state = ST_DATABYTE; - - if (msg < 8) /* Data byte */ - { - /* printk( "midi msg (running status) "); */ - msg = ((int) (devc->last_status & 0xf0) >> 4); - msg -= 8; - devc->m_left = len_tab[msg] - 1; - - devc->m_ptr = 2; - devc->m_buf[0] = devc->last_status; - devc->m_buf[1] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } - else if (msg == 0xf) /* MPU MARK */ - { - devc->m_state = ST_INIT; - - switch (midic) - { - case 0xf8: - /* printk( "NOP "); */ - break; - - case 0xf9: - /* printk( "meas end "); */ - break; - - case 0xfc: - /* printk( "data end "); */ - break; - - default: - printk("Unknown MPU mark %02x\n", midic); - } - } - else - { - devc->last_status = midic; - /* printk( "midi msg "); */ - msg -= 8; - devc->m_left = len_tab[msg]; - - devc->m_ptr = 1; - devc->m_buf[0] = midic; - - if (devc->m_left <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - } - } - break; - - case ST_SYSMSG: - switch (midic) - { - case 0xf0: - printk(""); - devc->m_state = ST_SYSEX; - break; - - case 0xf1: - devc->m_state = ST_MTC; - break; - - case 0xf2: - devc->m_state = ST_SONGPOS; - devc->m_ptr = 0; - break; - - case 0xf3: - devc->m_state = ST_SONGSEL; - break; - - case 0xf6: - /* printk( "tune_request\n"); */ - devc->m_state = ST_INIT; - - /* - * Real time messages - */ - case 0xf8: - /* midi clock */ - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_CLOCK, 0); - break; - - case 0xfA: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_START, 0); - break; - - case 0xFB: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_CONTINUE, 0); - break; - - case 0xFC: - devc->m_state = ST_INIT; - timer_ext_event(devc, TMR_STOP, 0); - break; - - case 0xFE: - /* active sensing */ - devc->m_state = ST_INIT; - break; - - case 0xff: - /* printk( "midi hard reset"); */ - devc->m_state = ST_INIT; - break; - - default: - printk("unknown MIDI sysmsg %0x\n", midic); - devc->m_state = ST_INIT; - } - break; - - case ST_MTC: - devc->m_state = ST_INIT; - printk("MTC frame %x02\n", midic); - break; - - case ST_SYSEX: - if (midic == 0xf7) - { - printk(""); - devc->m_state = ST_INIT; - } - else - printk("%02x ", midic); - break; - - case ST_SONGPOS: - BUFTEST(devc); - devc->m_buf[devc->m_ptr++] = midic; - if (devc->m_ptr == 2) - { - devc->m_state = ST_INIT; - devc->m_ptr = 0; - timer_ext_event(devc, TMR_SPP, - ((devc->m_buf[1] & 0x7f) << 7) | - (devc->m_buf[0] & 0x7f)); - } - break; - - case ST_DATABYTE: - BUFTEST(devc); - devc->m_buf[devc->m_ptr++] = midic; - if ((--devc->m_left) <= 0) - { - devc->m_state = ST_INIT; - do_midi_msg(devc->synthno, devc->m_buf, devc->m_ptr); - devc->m_ptr = 0; - } - break; - - default: - printk("Bad state %d ", devc->m_state); - devc->m_state = ST_INIT; - } - return 1; -} - -static void mpu401_input_loop(struct mpu_config *devc) -{ - unsigned long flags; - int busy; - int n; - - spin_lock_irqsave(&devc->lock,flags); - busy = devc->m_busy; - devc->m_busy = 1; - spin_unlock_irqrestore(&devc->lock,flags); - - if (busy) /* Already inside the scanner */ - return; - - n = 50; - - while (input_avail(devc) && n-- > 0) - { - unsigned char c = read_data(devc); - - if (devc->mode == MODE_SYNTH) - { - mpu_input_scanner(devc, c); - } - else if (devc->opened & OPEN_READ && devc->inputintr != NULL) - devc->inputintr(devc->devno, c); - } - devc->m_busy = 0; -} - -static irqreturn_t mpuintr(int irq, void *dev_id) -{ - struct mpu_config *devc; - int dev = (int)(unsigned long) dev_id; - int handled = 0; - - devc = &dev_conf[dev]; - - if (input_avail(devc)) - { - handled = 1; - if (devc->base != 0 && (devc->opened & OPEN_READ || devc->mode == MODE_SYNTH)) - mpu401_input_loop(devc); - else - { - /* Dummy read (just to acknowledge the interrupt) */ - read_data(devc); - } - } - return IRQ_RETVAL(handled); -} - -static int mpu401_open(int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - int err; - struct mpu_config *devc; - struct coproc_operations *coprocessor; - - if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) - return -ENXIO; - - devc = &dev_conf[dev]; - - if (devc->opened) - return -EBUSY; - /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloading its microcode. - */ - - if (!devc->initialized) - { - if (mpu401_status(devc) == 0xff) /* Bus float */ - { - printk(KERN_ERR "mpu401: Device not initialized properly\n"); - return -EIO; - } - reset_mpu401(devc); - } - - if ( (coprocessor = midi_devs[dev]->coproc) != NULL ) - { - if (!try_module_get(coprocessor->owner)) { - mpu401_close(dev); - return -ENODEV; - } - - if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0) - { - printk(KERN_WARNING "MPU-401: Can't access coprocessor device\n"); - mpu401_close(dev); - return err; - } - } - - set_uart_mode(dev, devc, 1); - devc->mode = MODE_MIDI; - devc->synthno = 0; - - mpu401_input_loop(devc); - - devc->inputintr = input; - devc->opened = mode; - - return 0; -} - -static void mpu401_close(int dev) -{ - struct mpu_config *devc; - struct coproc_operations *coprocessor; - - devc = &dev_conf[dev]; - if (devc->uart_mode) - reset_mpu401(devc); /* - * This disables the UART mode - */ - devc->mode = 0; - devc->inputintr = NULL; - - coprocessor = midi_devs[dev]->coproc; - if (coprocessor) { - coprocessor->close(coprocessor->devc, COPR_MIDI); - module_put(coprocessor->owner); - } - devc->opened = 0; -} - -static int mpu401_out(int dev, unsigned char midi_byte) -{ - int timeout; - unsigned long flags; - - struct mpu_config *devc; - - devc = &dev_conf[dev]; - - /* - * Sometimes it takes about 30000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); - - spin_lock_irqsave(&devc->lock,flags); - if (!output_ready(devc)) - { - printk(KERN_WARNING "mpu401: Send data timeout\n"); - spin_unlock_irqrestore(&devc->lock,flags); - return 0; - } - write_data(devc, midi_byte); - spin_unlock_irqrestore(&devc->lock,flags); - return 1; -} - -static int mpu401_command(int dev, mpu_command_rec * cmd) -{ - int i, timeout, ok; - int ret = 0; - unsigned long flags; - struct mpu_config *devc; - - devc = &dev_conf[dev]; - - if (devc->uart_mode) /* - * Not possible in UART mode - */ - { - printk(KERN_WARNING "mpu401: commands not possible in the UART mode\n"); - return -EINVAL; - } - /* - * Test for input since pending input seems to block the output. - */ - if (input_avail(devc)) - mpu401_input_loop(devc); - - /* - * Sometimes it takes about 50000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - timeout = 50000; -retry: - if (timeout-- <= 0) - { - printk(KERN_WARNING "mpu401: Command (0x%x) timeout\n", (int) cmd->cmd); - return -EIO; - } - spin_lock_irqsave(&devc->lock,flags); - - if (!output_ready(devc)) - { - spin_unlock_irqrestore(&devc->lock,flags); - goto retry; - } - write_command(devc, cmd->cmd); - - ok = 0; - for (timeout = 50000; timeout > 0 && !ok; timeout--) - { - if (input_avail(devc)) - { - if (devc->opened && devc->mode == MODE_SYNTH) - { - if (mpu_input_scanner(devc, read_data(devc)) == MPU_ACK) - ok = 1; - } - else - { - /* Device is not currently open. Use simpler method */ - if (read_data(devc) == MPU_ACK) - ok = 1; - } - } - } - if (!ok) - { - spin_unlock_irqrestore(&devc->lock,flags); - return -EIO; - } - if (cmd->nr_args) - { - for (i = 0; i < cmd->nr_args; i++) - { - for (timeout = 3000; timeout > 0 && !output_ready(devc); timeout--); - - if (!mpu401_out(dev, cmd->data[i])) - { - spin_unlock_irqrestore(&devc->lock,flags); - printk(KERN_WARNING "mpu401: Command (0x%x), parm send failed.\n", (int) cmd->cmd); - return -EIO; - } - } - } - ret = 0; - cmd->data[0] = 0; - - if (cmd->nr_returns) - { - for (i = 0; i < cmd->nr_returns; i++) - { - ok = 0; - for (timeout = 5000; timeout > 0 && !ok; timeout--) - if (input_avail(devc)) - { - cmd->data[i] = read_data(devc); - ok = 1; - } - if (!ok) - { - spin_unlock_irqrestore(&devc->lock,flags); - return -EIO; - } - } - } - spin_unlock_irqrestore(&devc->lock,flags); - return ret; -} - -static int mpu_cmd(int dev, int cmd, int data) -{ - int ret; - - static mpu_command_rec rec; - - rec.cmd = cmd & 0xff; - rec.nr_args = ((cmd & 0xf0) == 0xE0); - rec.nr_returns = ((cmd & 0xf0) == 0xA0); - rec.data[0] = data & 0xff; - - if ((ret = mpu401_command(dev, &rec)) < 0) - return ret; - return (unsigned char) rec.data[0]; -} - -static int mpu401_prefix_cmd(int dev, unsigned char status) -{ - struct mpu_config *devc = &dev_conf[dev]; - - if (devc->uart_mode) - return 1; - - if (status < 0xf0) - { - if (mpu_cmd(dev, 0xD0, 0) < 0) - return 0; - return 1; - } - switch (status) - { - case 0xF0: - if (mpu_cmd(dev, 0xDF, 0) < 0) - return 0; - return 1; - - default: - return 0; - } -} - -static int mpu401_start_read(int dev) -{ - return 0; -} - -static int mpu401_end_read(int dev) -{ - return 0; -} - -static int mpu401_ioctl(int dev, unsigned cmd, void __user *arg) -{ - struct mpu_config *devc; - mpu_command_rec rec; - int val, ret; - - devc = &dev_conf[dev]; - switch (cmd) - { - case SNDCTL_MIDI_MPUMODE: - if (!(devc->capabilities & MPU_CAP_INTLG)) { /* No intelligent mode */ - printk(KERN_WARNING "mpu401: Intelligent mode not supported by the HW\n"); - return -EINVAL; - } - if (get_user(val, (int __user *)arg)) - return -EFAULT; - set_uart_mode(dev, devc, !val); - return 0; - - case SNDCTL_MIDI_MPUCMD: - if (copy_from_user(&rec, arg, sizeof(rec))) - return -EFAULT; - if ((ret = mpu401_command(dev, &rec)) < 0) - return ret; - if (copy_to_user(arg, &rec, sizeof(rec))) - return -EFAULT; - return 0; - - default: - return -EINVAL; - } -} - -static void mpu401_kick(int dev) -{ -} - -static int mpu401_buffer_status(int dev) -{ - return 0; /* - * No data in buffers - */ -} - -static int mpu_synth_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - int midi_dev; - struct mpu_config *devc; - - midi_dev = synth_devs[dev]->midi_dev; - - if (midi_dev < 0 || midi_dev >= num_midis || midi_devs[midi_dev] == NULL) - return -ENXIO; - - devc = &dev_conf[midi_dev]; - - switch (cmd) - { - - case SNDCTL_SYNTH_INFO: - if (copy_to_user(arg, &mpu_synth_info[midi_dev], - sizeof(struct synth_info))) - return -EFAULT; - return 0; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - - default: - return -EINVAL; - } -} - -static int mpu_synth_open(int dev, int mode) -{ - int midi_dev, err; - struct mpu_config *devc; - struct coproc_operations *coprocessor; - - midi_dev = synth_devs[dev]->midi_dev; - - if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev] == NULL) - return -ENXIO; - - devc = &dev_conf[midi_dev]; - - /* - * Verify that the device is really running. - * Some devices (such as Ensoniq SoundScape don't - * work before the on board processor (OBP) is initialized - * by downloading its microcode. - */ - - if (!devc->initialized) - { - if (mpu401_status(devc) == 0xff) /* Bus float */ - { - printk(KERN_ERR "mpu401: Device not initialized properly\n"); - return -EIO; - } - reset_mpu401(devc); - } - if (devc->opened) - return -EBUSY; - devc->mode = MODE_SYNTH; - devc->synthno = dev; - - devc->inputintr = NULL; - - coprocessor = midi_devs[midi_dev]->coproc; - if (coprocessor) { - if (!try_module_get(coprocessor->owner)) - return -ENODEV; - - if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0) - { - printk(KERN_WARNING "mpu401: Can't access coprocessor device\n"); - return err; - } - } - devc->opened = mode; - reset_mpu401(devc); - - if (mode & OPEN_READ) - { - mpu_cmd(midi_dev, 0x8B, 0); /* Enable data in stop mode */ - mpu_cmd(midi_dev, 0x34, 0); /* Return timing bytes in stop mode */ - mpu_cmd(midi_dev, 0x87, 0); /* Enable pitch & controller */ - } - return 0; -} - -static void mpu_synth_close(int dev) -{ - int midi_dev; - struct mpu_config *devc; - struct coproc_operations *coprocessor; - - midi_dev = synth_devs[dev]->midi_dev; - - devc = &dev_conf[midi_dev]; - mpu_cmd(midi_dev, 0x15, 0); /* Stop recording, playback and MIDI */ - mpu_cmd(midi_dev, 0x8a, 0); /* Disable data in stopped mode */ - - devc->inputintr = NULL; - - coprocessor = midi_devs[midi_dev]->coproc; - if (coprocessor) { - coprocessor->close(coprocessor->devc, COPR_MIDI); - module_put(coprocessor->owner); - } - devc->opened = 0; - devc->mode = 0; -} - -#define MIDI_SYNTH_NAME "MPU-401 UART Midi" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include "midi_synth.h" - -static struct synth_operations mpu401_synth_proto = -{ - .owner = THIS_MODULE, - .id = "MPU401", - .info = NULL, - .midi_dev = 0, - .synth_type = SYNTH_TYPE_MIDI, - .synth_subtype = 0, - .open = mpu_synth_open, - .close = mpu_synth_close, - .ioctl = mpu_synth_ioctl, - .kill_note = midi_synth_kill_note, - .start_note = midi_synth_start_note, - .set_instr = midi_synth_set_instr, - .reset = midi_synth_reset, - .hw_control = midi_synth_hw_control, - .load_patch = midi_synth_load_patch, - .aftertouch = midi_synth_aftertouch, - .controller = midi_synth_controller, - .panning = midi_synth_panning, - .bender = midi_synth_bender, - .setup_voice = midi_synth_setup_voice, - .send_sysex = midi_synth_send_sysex -}; - -static struct synth_operations *mpu401_synth_operations[MAX_MIDI_DEV]; - -static struct midi_operations mpu401_midi_proto = -{ - .owner = THIS_MODULE, - .info = {"MPU-401 Midi", 0, MIDI_CAP_MPU401, SNDCARD_MPU401}, - .in_info = {0}, - .open = mpu401_open, - .close = mpu401_close, - .ioctl = mpu401_ioctl, - .outputc = mpu401_out, - .start_read = mpu401_start_read, - .end_read = mpu401_end_read, - .kick = mpu401_kick, - .buffer_status = mpu401_buffer_status, - .prefix_cmd = mpu401_prefix_cmd -}; - -static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV]; - -static void mpu401_chk_version(int n, struct mpu_config *devc) -{ - int tmp; - - devc->version = devc->revision = 0; - - tmp = mpu_cmd(n, 0xAC, 0); - if (tmp < 0) - return; - if ((tmp & 0xf0) > 0x20) /* Why it's larger than 2.x ??? */ - return; - devc->version = tmp; - - if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0) { - devc->version = 0; - return; - } - devc->revision = tmp; -} - -int attach_mpu401(struct address_info *hw_config, struct module *owner) -{ - unsigned long flags; - char revision_char; - - int m, ret; - struct mpu_config *devc; - - hw_config->slots[1] = -1; - m = sound_alloc_mididev(); - if (m == -1) - { - printk(KERN_WARNING "MPU-401: Too many midi devices detected\n"); - ret = -ENOMEM; - goto out_err; - } - devc = &dev_conf[m]; - devc->base = hw_config->io_base; - devc->osp = hw_config->osp; - devc->irq = hw_config->irq; - devc->opened = 0; - devc->uart_mode = 0; - devc->initialized = 0; - devc->version = 0; - devc->revision = 0; - devc->capabilities = 0; - devc->timer_flag = 0; - devc->m_busy = 0; - devc->m_state = ST_INIT; - devc->shared_irq = hw_config->always_detect; - devc->irq = hw_config->irq; - spin_lock_init(&devc->lock); - - if (devc->irq < 0) - { - devc->irq *= -1; - devc->shared_irq = 1; - } - - if (!hw_config->always_detect) - { - /* Verify the hardware again */ - if (!reset_mpu401(devc)) - { - printk(KERN_WARNING "mpu401: Device didn't respond\n"); - ret = -ENODEV; - goto out_mididev; - } - if (!devc->shared_irq) - { - if (request_irq(devc->irq, mpuintr, 0, "mpu401", - hw_config) < 0) - { - printk(KERN_WARNING "mpu401: Failed to allocate IRQ%d\n", devc->irq); - ret = -ENOMEM; - goto out_mididev; - } - } - spin_lock_irqsave(&devc->lock,flags); - mpu401_chk_version(m, devc); - if (devc->version == 0) - mpu401_chk_version(m, devc); - spin_unlock_irqrestore(&devc->lock, flags); - } - - if (devc->version != 0) - if (mpu_cmd(m, 0xC5, 0) >= 0) /* Set timebase OK */ - if (mpu_cmd(m, 0xE0, 120) >= 0) /* Set tempo OK */ - devc->capabilities |= MPU_CAP_INTLG; /* Supports intelligent mode */ - - - mpu401_synth_operations[m] = kmalloc(sizeof(struct synth_operations), GFP_KERNEL); - - if (mpu401_synth_operations[m] == NULL) - { - printk(KERN_ERR "mpu401: Can't allocate memory\n"); - ret = -ENOMEM; - goto out_irq; - } - if (!(devc->capabilities & MPU_CAP_INTLG)) /* No intelligent mode */ - { - memcpy((char *) mpu401_synth_operations[m], - (char *) &std_midi_synth, - sizeof(struct synth_operations)); - } - else - { - memcpy((char *) mpu401_synth_operations[m], - (char *) &mpu401_synth_proto, - sizeof(struct synth_operations)); - } - if (owner) - mpu401_synth_operations[m]->owner = owner; - - memcpy((char *) &mpu401_midi_operations[m], - (char *) &mpu401_midi_proto, - sizeof(struct midi_operations)); - - mpu401_midi_operations[m].converter = mpu401_synth_operations[m]; - - memcpy((char *) &mpu_synth_info[m], - (char *) &mpu_synth_info_proto, - sizeof(struct synth_info)); - - n_mpu_devs++; - - if (devc->version == 0x20 && devc->revision >= 0x07) /* MusicQuest interface */ - { - int ports = (devc->revision & 0x08) ? 32 : 16; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_SMPTE | - MPU_CAP_CLS | MPU_CAP_2PORT; - - revision_char = (devc->revision == 0x7f) ? 'M' : ' '; - sprintf(mpu_synth_info[m].name, "MQX-%d%c MIDI Interface #%d", - ports, - revision_char, - n_mpu_devs); - } - else - { - revision_char = devc->revision ? devc->revision + '@' : ' '; - if ((int) devc->revision > ('Z' - '@')) - revision_char = '+'; - - devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK; - - if (hw_config->name) - sprintf(mpu_synth_info[m].name, "%s (MPU401)", hw_config->name); - else - sprintf(mpu_synth_info[m].name, - "MPU-401 %d.%d%c MIDI #%d", - (int) (devc->version & 0xf0) >> 4, - devc->version & 0x0f, - revision_char, - n_mpu_devs); - } - - strcpy(mpu401_midi_operations[m].info.name, - mpu_synth_info[m].name); - - conf_printf(mpu_synth_info[m].name, hw_config); - - mpu401_synth_operations[m]->midi_dev = devc->devno = m; - mpu401_synth_operations[devc->devno]->info = &mpu_synth_info[devc->devno]; - - if (devc->capabilities & MPU_CAP_INTLG) /* Intelligent mode */ - hw_config->slots[2] = mpu_timer_init(m); - - midi_devs[m] = &mpu401_midi_operations[devc->devno]; - - if (owner) - midi_devs[m]->owner = owner; - - hw_config->slots[1] = m; - sequencer_init(); - - return 0; - -out_irq: - free_irq(devc->irq, hw_config); -out_mididev: - sound_unload_mididev(m); -out_err: - release_region(hw_config->io_base, 2); - return ret; -} - -static int reset_mpu401(struct mpu_config *devc) -{ - unsigned long flags; - int ok, timeout, n; - int timeout_limit; - - /* - * Send the RESET command. Try again if no success at the first time. - * (If the device is in the UART mode, it will not ack the reset cmd). - */ - - ok = 0; - - timeout_limit = devc->initialized ? 30000 : 100000; - devc->initialized = 1; - - for (n = 0; n < 2 && !ok; n++) - { - for (timeout = timeout_limit; timeout > 0 && !ok; timeout--) - ok = output_ready(devc); - - write_command(devc, MPU_RESET); /* - * Send MPU-401 RESET Command - */ - - /* - * Wait at least 25 msec. This method is not accurate so let's make the - * loop bit longer. Cannot sleep since this is called during boot. - */ - - for (timeout = timeout_limit * 2; timeout > 0 && !ok; timeout--) - { - spin_lock_irqsave(&devc->lock,flags); - if (input_avail(devc)) - if (read_data(devc) == MPU_ACK) - ok = 1; - spin_unlock_irqrestore(&devc->lock,flags); - } - - } - - devc->m_state = ST_INIT; - devc->m_ptr = 0; - devc->m_left = 0; - devc->last_status = 0; - devc->uart_mode = 0; - - return ok; -} - -static void set_uart_mode(int dev, struct mpu_config *devc, int arg) -{ - if (!arg && (devc->capabilities & MPU_CAP_INTLG)) - return; - if ((devc->uart_mode == 0) == (arg == 0)) - return; /* Already set */ - reset_mpu401(devc); /* This exits the uart mode */ - - if (arg) - { - if (mpu_cmd(dev, UART_MODE_ON, 0) < 0) - { - printk(KERN_ERR "mpu401: Can't enter UART mode\n"); - devc->uart_mode = 0; - return; - } - } - devc->uart_mode = arg; - -} - -int probe_mpu401(struct address_info *hw_config, struct resource *ports) -{ - int ok = 0; - struct mpu_config tmp_devc; - - tmp_devc.base = hw_config->io_base; - tmp_devc.irq = hw_config->irq; - tmp_devc.initialized = 0; - tmp_devc.opened = 0; - tmp_devc.osp = hw_config->osp; - - if (hw_config->always_detect) - return 1; - - if (inb(hw_config->io_base + 1) == 0xff) - { - DDB(printk("MPU401: Port %x looks dead.\n", hw_config->io_base)); - return 0; /* Just bus float? */ - } - ok = reset_mpu401(&tmp_devc); - - if (!ok) - { - DDB(printk("MPU401: Reset failed on port %x\n", hw_config->io_base)); - } - return ok; -} - -void unload_mpu401(struct address_info *hw_config) -{ - void *p; - int n=hw_config->slots[1]; - - if (n != -1) { - release_region(hw_config->io_base, 2); - if (hw_config->always_detect == 0 && hw_config->irq > 0) - free_irq(hw_config->irq, hw_config); - p=mpu401_synth_operations[n]; - sound_unload_mididev(n); - sound_unload_timerdev(hw_config->slots[2]); - kfree(p); - } -} - -/***************************************************** - * Timer stuff - ****************************************************/ - -static volatile int timer_initialized = 0, timer_open = 0, tmr_running = 0; -static volatile int curr_tempo, curr_timebase, hw_timebase; -static int max_timebase = 8; /* 8*24=192 ppqn */ -static volatile unsigned long next_event_time; -static volatile unsigned long curr_ticks, curr_clocks; -static unsigned long prev_event_time; -static int metronome_mode; - -static unsigned long clocks2ticks(unsigned long clocks) -{ - /* - * The MPU-401 supports just a limited set of possible timebase values. - * Since the applications require more choices, the driver has to - * program the HW to do its best and to convert between the HW and - * actual timebases. - */ - return ((clocks * curr_timebase) + (hw_timebase / 2)) / hw_timebase; -} - -static void set_timebase(int midi_dev, int val) -{ - int hw_val; - - if (val < 48) - val = 48; - if (val > 1000) - val = 1000; - - hw_val = val; - hw_val = (hw_val + 12) / 24; - if (hw_val > max_timebase) - hw_val = max_timebase; - - if (mpu_cmd(midi_dev, 0xC0 | (hw_val & 0x0f), 0) < 0) - { - printk(KERN_WARNING "mpu401: Can't set HW timebase to %d\n", hw_val * 24); - return; - } - hw_timebase = hw_val * 24; - curr_timebase = val; - -} - -static void tmr_reset(struct mpu_config *devc) -{ - unsigned long flags; - - spin_lock_irqsave(&devc->lock,flags); - next_event_time = (unsigned long) -1; - prev_event_time = 0; - curr_ticks = curr_clocks = 0; - spin_unlock_irqrestore(&devc->lock,flags); -} - -static void set_timer_mode(int midi_dev) -{ - if (timer_mode & TMR_MODE_CLS) - mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ - else if (timer_mode & TMR_MODE_SMPTE) - mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ - - if (timer_mode & TMR_INTERNAL) - { - mpu_cmd(midi_dev, 0x80, 0); /* Use MIDI sync */ - } - else - { - if (timer_mode & (TMR_MODE_MIDI | TMR_MODE_CLS)) - { - mpu_cmd(midi_dev, 0x82, 0); /* Use MIDI sync */ - mpu_cmd(midi_dev, 0x91, 0); /* Enable ext MIDI ctrl */ - } - else if (timer_mode & TMR_MODE_FSK) - mpu_cmd(midi_dev, 0x81, 0); /* Use FSK sync */ - } -} - -static void stop_metronome(int midi_dev) -{ - mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */ -} - -static void setup_metronome(int midi_dev) -{ - int numerator, denominator; - int clks_per_click, num_32nds_per_beat; - int beats_per_measure; - - numerator = ((unsigned) metronome_mode >> 24) & 0xff; - denominator = ((unsigned) metronome_mode >> 16) & 0xff; - clks_per_click = ((unsigned) metronome_mode >> 8) & 0xff; - num_32nds_per_beat = (unsigned) metronome_mode & 0xff; - beats_per_measure = (numerator * 4) >> denominator; - - if (!metronome_mode) - mpu_cmd(midi_dev, 0x84, 0); /* Disable metronome */ - else - { - mpu_cmd(midi_dev, 0xE4, clks_per_click); - mpu_cmd(midi_dev, 0xE6, beats_per_measure); - mpu_cmd(midi_dev, 0x83, 0); /* Enable metronome without accents */ - } -} - -static int mpu_start_timer(int midi_dev) -{ - struct mpu_config *devc= &dev_conf[midi_dev]; - - tmr_reset(devc); - set_timer_mode(midi_dev); - - if (tmr_running) - return TIMER_NOT_ARMED; /* Already running */ - - if (timer_mode & TMR_INTERNAL) - { - mpu_cmd(midi_dev, 0x02, 0); /* Send MIDI start */ - tmr_running = 1; - return TIMER_NOT_ARMED; - } - else - { - mpu_cmd(midi_dev, 0x35, 0); /* Enable mode messages to PC */ - mpu_cmd(midi_dev, 0x38, 0); /* Enable sys common messages to PC */ - mpu_cmd(midi_dev, 0x39, 0); /* Enable real time messages to PC */ - mpu_cmd(midi_dev, 0x97, 0); /* Enable system exclusive messages to PC */ - } - return TIMER_ARMED; -} - -static int mpu_timer_open(int dev, int mode) -{ - int midi_dev = sound_timer_devs[dev]->devlink; - struct mpu_config *devc= &dev_conf[midi_dev]; - - if (timer_open) - return -EBUSY; - - tmr_reset(devc); - curr_tempo = 50; - mpu_cmd(midi_dev, 0xE0, 50); - curr_timebase = hw_timebase = 120; - set_timebase(midi_dev, 120); - timer_open = 1; - metronome_mode = 0; - set_timer_mode(midi_dev); - - mpu_cmd(midi_dev, 0xe7, 0x04); /* Send all clocks to host */ - mpu_cmd(midi_dev, 0x95, 0); /* Enable clock to host */ - - return 0; -} - -static void mpu_timer_close(int dev) -{ - int midi_dev = sound_timer_devs[dev]->devlink; - - timer_open = tmr_running = 0; - mpu_cmd(midi_dev, 0x15, 0); /* Stop all */ - mpu_cmd(midi_dev, 0x94, 0); /* Disable clock to host */ - mpu_cmd(midi_dev, 0x8c, 0); /* Disable measure end messages to host */ - stop_metronome(midi_dev); -} - -static int mpu_timer_event(int dev, unsigned char *event) -{ - unsigned char command = event[1]; - unsigned long parm = *(unsigned int *) &event[4]; - int midi_dev = sound_timer_devs[dev]->devlink; - - switch (command) - { - case TMR_WAIT_REL: - parm += prev_event_time; - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - if (parm <= curr_ticks) /* It's the time */ - return TIMER_NOT_ARMED; - time = parm; - next_event_time = prev_event_time = time; - - return TIMER_ARMED; - } - break; - - case TMR_START: - if (tmr_running) - break; - return mpu_start_timer(midi_dev); - - case TMR_STOP: - mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ - stop_metronome(midi_dev); - tmr_running = 0; - break; - - case TMR_CONTINUE: - if (tmr_running) - break; - mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ - setup_metronome(midi_dev); - tmr_running = 1; - break; - - case TMR_TEMPO: - if (parm) - { - if (parm < 8) - parm = 8; - if (parm > 250) - parm = 250; - if (mpu_cmd(midi_dev, 0xE0, parm) < 0) - printk(KERN_WARNING "mpu401: Can't set tempo to %d\n", (int) parm); - curr_tempo = parm; - } - break; - - case TMR_ECHO: - seq_copy_to_input(event, 8); - break; - - case TMR_TIMESIG: - if (metronome_mode) /* Metronome enabled */ - { - metronome_mode = parm; - setup_metronome(midi_dev); - } - break; - - default:; - } - return TIMER_NOT_ARMED; -} - -static unsigned long mpu_timer_get_time(int dev) -{ - if (!timer_open) - return 0; - - return curr_ticks; -} - -static int mpu_timer_ioctl(int dev, unsigned int command, void __user *arg) -{ - int midi_dev = sound_timer_devs[dev]->devlink; - int __user *p = (int __user *)arg; - - switch (command) - { - case SNDCTL_TMR_SOURCE: - { - int parm; - - if (get_user(parm, p)) - return -EFAULT; - parm &= timer_caps; - - if (parm != 0) - { - timer_mode = parm; - - if (timer_mode & TMR_MODE_CLS) - mpu_cmd(midi_dev, 0x3c, 0); /* Use CLS sync */ - else if (timer_mode & TMR_MODE_SMPTE) - mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ - } - if (put_user(timer_mode, p)) - return -EFAULT; - return timer_mode; - } - break; - - case SNDCTL_TMR_START: - mpu_start_timer(midi_dev); - return 0; - - case SNDCTL_TMR_STOP: - tmr_running = 0; - mpu_cmd(midi_dev, 0x01, 0); /* Send MIDI stop */ - stop_metronome(midi_dev); - return 0; - - case SNDCTL_TMR_CONTINUE: - if (tmr_running) - return 0; - tmr_running = 1; - mpu_cmd(midi_dev, 0x03, 0); /* Send MIDI continue */ - return 0; - - case SNDCTL_TMR_TIMEBASE: - { - int val; - if (get_user(val, p)) - return -EFAULT; - if (val) - set_timebase(midi_dev, val); - if (put_user(curr_timebase, p)) - return -EFAULT; - return curr_timebase; - } - break; - - case SNDCTL_TMR_TEMPO: - { - int val; - int ret; - - if (get_user(val, p)) - return -EFAULT; - - if (val) - { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - if ((ret = mpu_cmd(midi_dev, 0xE0, val)) < 0) - { - printk(KERN_WARNING "mpu401: Can't set tempo to %d\n", (int) val); - return ret; - } - curr_tempo = val; - } - if (put_user(curr_tempo, p)) - return -EFAULT; - return curr_tempo; - } - break; - - case SNDCTL_SEQ_CTRLRATE: - { - int val; - if (get_user(val, p)) - return -EFAULT; - - if (val != 0) /* Can't change */ - return -EINVAL; - val = ((curr_tempo * curr_timebase) + 30)/60; - if (put_user(val, p)) - return -EFAULT; - return val; - } - break; - - case SNDCTL_SEQ_GETTIME: - if (put_user(curr_ticks, p)) - return -EFAULT; - return curr_ticks; - - case SNDCTL_TMR_METRONOME: - if (get_user(metronome_mode, p)) - return -EFAULT; - setup_metronome(midi_dev); - return 0; - - default:; - } - return -EINVAL; -} - -static void mpu_timer_arm(int dev, long time) -{ - if (time < 0) - time = curr_ticks + 1; - else if (time <= curr_ticks) /* It's the time */ - return; - next_event_time = prev_event_time = time; - return; -} - -static struct sound_timer_operations mpu_timer = -{ - .owner = THIS_MODULE, - .info = {"MPU-401 Timer", 0}, - .priority = 10, /* Priority */ - .devlink = 0, /* Local device link */ - .open = mpu_timer_open, - .close = mpu_timer_close, - .event = mpu_timer_event, - .get_time = mpu_timer_get_time, - .ioctl = mpu_timer_ioctl, - .arm_timer = mpu_timer_arm -}; - -static void mpu_timer_interrupt(void) -{ - if (!timer_open) - return; - - if (!tmr_running) - return; - - curr_clocks++; - curr_ticks = clocks2ticks(curr_clocks); - - if (curr_ticks >= next_event_time) - { - next_event_time = (unsigned long) -1; - sequencer_timer(0); - } -} - -static void timer_ext_event(struct mpu_config *devc, int event, int parm) -{ - int midi_dev = devc->devno; - - if (!devc->timer_flag) - return; - - switch (event) - { - case TMR_CLOCK: - printk(""); - break; - - case TMR_START: - printk("Ext MIDI start\n"); - if (!tmr_running) - { - if (timer_mode & TMR_EXTERNAL) - { - tmr_running = 1; - setup_metronome(midi_dev); - next_event_time = 0; - STORE(SEQ_START_TIMER()); - } - } - break; - - case TMR_STOP: - printk("Ext MIDI stop\n"); - if (timer_mode & TMR_EXTERNAL) - { - tmr_running = 0; - stop_metronome(midi_dev); - STORE(SEQ_STOP_TIMER()); - } - break; - - case TMR_CONTINUE: - printk("Ext MIDI continue\n"); - if (timer_mode & TMR_EXTERNAL) - { - tmr_running = 1; - setup_metronome(midi_dev); - STORE(SEQ_CONTINUE_TIMER()); - } - break; - - case TMR_SPP: - printk("Songpos: %d\n", parm); - if (timer_mode & TMR_EXTERNAL) - { - STORE(SEQ_SONGPOS(parm)); - } - break; - } -} - -static int mpu_timer_init(int midi_dev) -{ - struct mpu_config *devc; - int n; - - devc = &dev_conf[midi_dev]; - - if (timer_initialized) - return -1; /* There is already a similar timer */ - - timer_initialized = 1; - - mpu_timer.devlink = midi_dev; - dev_conf[midi_dev].timer_flag = 1; - - n = sound_alloc_timerdev(); - if (n == -1) - n = 0; - sound_timer_devs[n] = &mpu_timer; - - if (devc->version < 0x20) /* Original MPU-401 */ - timer_caps = TMR_INTERNAL | TMR_EXTERNAL | TMR_MODE_FSK | TMR_MODE_MIDI; - else - { - /* - * The version number 2.0 is used (at least) by the - * MusicQuest cards and the Roland Super-MPU. - * - * MusicQuest has given a special meaning to the bits of the - * revision number. The Super-MPU returns 0. - */ - - if (devc->revision) - timer_caps |= TMR_EXTERNAL | TMR_MODE_MIDI; - - if (devc->revision & 0x02) - timer_caps |= TMR_MODE_CLS; - - - if (devc->revision & 0x40) - max_timebase = 10; /* Has the 216 and 240 ppqn modes */ - } - - timer_mode = (TMR_INTERNAL | TMR_MODE_MIDI) & timer_caps; - return n; - -} - -EXPORT_SYMBOL(probe_mpu401); -EXPORT_SYMBOL(attach_mpu401); -EXPORT_SYMBOL(unload_mpu401); - -static struct address_info cfg; - -static int io = -1; -static int irq = -1; - -module_param(irq, int, 0); -module_param(io, int, 0); - -static int __init init_mpu401(void) -{ - int ret; - /* Can be loaded either for module use or to provide functions - to others */ - if (io != -1 && irq != -1) { - struct resource *ports; - cfg.irq = irq; - cfg.io_base = io; - ports = request_region(io, 2, "mpu401"); - if (!ports) - return -EBUSY; - if (probe_mpu401(&cfg, ports) == 0) { - release_region(io, 2); - return -ENODEV; - } - if ((ret = attach_mpu401(&cfg, THIS_MODULE))) - return ret; - } - - return 0; -} - -static void __exit cleanup_mpu401(void) -{ - if (io != -1 && irq != -1) { - /* Check for use by, for example, sscape driver */ - unload_mpu401(&cfg); - } -} - -module_init(init_mpu401); -module_exit(cleanup_mpu401); - -#ifndef MODULE -static int __init setup_mpu401(char *str) -{ - /* io, irq */ - int ints[3]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - irq = ints[2]; - - return 1; -} - -__setup("mpu401=", setup_mpu401); -#endif -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/mpu401.h b/ANDROID_3.4.5/sound/oss/mpu401.h deleted file mode 100644 index 0ad1e9ee..00000000 --- a/ANDROID_3.4.5/sound/oss/mpu401.h +++ /dev/null @@ -1,11 +0,0 @@ - -/* From uart401.c */ -int probe_uart401 (struct address_info *hw_config, struct module *owner); -void unload_uart401 (struct address_info *hw_config); - -irqreturn_t uart401intr (int irq, void *dev_id); - -/* From mpu401.c */ -int probe_mpu401(struct address_info *hw_config, struct resource *ports); -int attach_mpu401(struct address_info * hw_config, struct module *owner); -void unload_mpu401(struct address_info *hw_info); diff --git a/ANDROID_3.4.5/sound/oss/msnd.c b/ANDROID_3.4.5/sound/oss/msnd.c deleted file mode 100644 index c0cc951b..00000000 --- a/ANDROID_3.4.5/sound/oss/msnd.c +++ /dev/null @@ -1,413 +0,0 @@ -/********************************************************************* - * - * msnd.c - Driver Base - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Copyright (C) 1998 Andrew Veliath - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "msnd.h" - -#define LOGNAME "msnd" - -#define MSND_MAX_DEVS 4 - -static multisound_dev_t *devs[MSND_MAX_DEVS]; -static int num_devs; - -int msnd_register(multisound_dev_t *dev) -{ - int i; - - for (i = 0; i < MSND_MAX_DEVS; ++i) - if (devs[i] == NULL) - break; - - if (i == MSND_MAX_DEVS) - return -ENOMEM; - - devs[i] = dev; - ++num_devs; - return 0; -} - -void msnd_unregister(multisound_dev_t *dev) -{ - int i; - - for (i = 0; i < MSND_MAX_DEVS; ++i) - if (devs[i] == dev) - break; - - if (i == MSND_MAX_DEVS) { - printk(KERN_WARNING LOGNAME ": Unregistering unknown device\n"); - return; - } - - devs[i] = NULL; - --num_devs; -} - -void msnd_init_queue(void __iomem *base, int start, int size) -{ - writew(PCTODSP_BASED(start), base + JQS_wStart); - writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize); - writew(0, base + JQS_wHead); - writew(0, base + JQS_wTail); -} - -void msnd_fifo_init(msnd_fifo *f) -{ - f->data = NULL; -} - -void msnd_fifo_free(msnd_fifo *f) -{ - vfree(f->data); - f->data = NULL; -} - -int msnd_fifo_alloc(msnd_fifo *f, size_t n) -{ - msnd_fifo_free(f); - f->data = vmalloc(n); - f->n = n; - f->tail = 0; - f->head = 0; - f->len = 0; - - if (!f->data) - return -ENOMEM; - - return 0; -} - -void msnd_fifo_make_empty(msnd_fifo *f) -{ - f->len = f->tail = f->head = 0; -} - -int msnd_fifo_write_io(msnd_fifo *f, char __iomem *buf, size_t len) -{ - int count = 0; - - while ((count < len) && (f->len != f->n)) { - - int nwritten; - - if (f->head <= f->tail) { - nwritten = len - count; - if (nwritten > f->n - f->tail) - nwritten = f->n - f->tail; - } - else { - nwritten = f->head - f->tail; - if (nwritten > len - count) - nwritten = len - count; - } - - memcpy_fromio(f->data + f->tail, buf, nwritten); - - count += nwritten; - buf += nwritten; - f->len += nwritten; - f->tail += nwritten; - f->tail %= f->n; - } - - return count; -} - -int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len) -{ - int count = 0; - - while ((count < len) && (f->len != f->n)) { - - int nwritten; - - if (f->head <= f->tail) { - nwritten = len - count; - if (nwritten > f->n - f->tail) - nwritten = f->n - f->tail; - } - else { - nwritten = f->head - f->tail; - if (nwritten > len - count) - nwritten = len - count; - } - - memcpy(f->data + f->tail, buf, nwritten); - - count += nwritten; - buf += nwritten; - f->len += nwritten; - f->tail += nwritten; - f->tail %= f->n; - } - - return count; -} - -int msnd_fifo_read_io(msnd_fifo *f, char __iomem *buf, size_t len) -{ - int count = 0; - - while ((count < len) && (f->len > 0)) { - - int nread; - - if (f->tail <= f->head) { - nread = len - count; - if (nread > f->n - f->head) - nread = f->n - f->head; - } - else { - nread = f->tail - f->head; - if (nread > len - count) - nread = len - count; - } - - memcpy_toio(buf, f->data + f->head, nread); - - count += nread; - buf += nread; - f->len -= nread; - f->head += nread; - f->head %= f->n; - } - - return count; -} - -int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len) -{ - int count = 0; - - while ((count < len) && (f->len > 0)) { - - int nread; - - if (f->tail <= f->head) { - nread = len - count; - if (nread > f->n - f->head) - nread = f->n - f->head; - } - else { - nread = f->tail - f->head; - if (nread > len - count) - nread = len - count; - } - - memcpy(buf, f->data + f->head, nread); - - count += nread; - buf += nread; - f->len -= nread; - f->head += nread; - f->head %= f->n; - } - - return count; -} - -static int msnd_wait_TXDE(multisound_dev_t *dev) -{ - register unsigned int io = dev->io; - register int timeout = 1000; - - while(timeout-- > 0) - if (msnd_inb(io + HP_ISR) & HPISR_TXDE) - return 0; - - return -EIO; -} - -static int msnd_wait_HC0(multisound_dev_t *dev) -{ - register unsigned int io = dev->io; - register int timeout = 1000; - - while(timeout-- > 0) - if (!(msnd_inb(io + HP_CVR) & HPCVR_HC)) - return 0; - - return -EIO; -} - -int msnd_send_dsp_cmd(multisound_dev_t *dev, BYTE cmd) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - if (msnd_wait_HC0(dev) == 0) { - msnd_outb(cmd, dev->io + HP_CVR); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - printk(KERN_DEBUG LOGNAME ": Send DSP command timeout\n"); - - return -EIO; -} - -int msnd_send_word(multisound_dev_t *dev, unsigned char high, - unsigned char mid, unsigned char low) -{ - register unsigned int io = dev->io; - - if (msnd_wait_TXDE(dev) == 0) { - msnd_outb(high, io + HP_TXH); - msnd_outb(mid, io + HP_TXM); - msnd_outb(low, io + HP_TXL); - return 0; - } - - printk(KERN_DEBUG LOGNAME ": Send host word timeout\n"); - - return -EIO; -} - -int msnd_upload_host(multisound_dev_t *dev, char *bin, int len) -{ - int i; - - if (len % 3 != 0) { - printk(KERN_WARNING LOGNAME ": Upload host data not multiple of 3!\n"); - return -EINVAL; - } - - for (i = 0; i < len; i += 3) - if (msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]) != 0) - return -EIO; - - msnd_inb(dev->io + HP_RXL); - msnd_inb(dev->io + HP_CVR); - - return 0; -} - -int msnd_enable_irq(multisound_dev_t *dev) -{ - unsigned long flags; - - if (dev->irq_ref++) - return 0; - - printk(KERN_DEBUG LOGNAME ": Enabling IRQ\n"); - - spin_lock_irqsave(&dev->lock, flags); - if (msnd_wait_TXDE(dev) == 0) { - msnd_outb(msnd_inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR); - if (dev->type == msndClassic) - msnd_outb(dev->irqid, dev->io + HP_IRQM); - msnd_outb(msnd_inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR); - msnd_outb(msnd_inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR); - enable_irq(dev->irq); - msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, dev->dspq_buff_size); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - printk(KERN_DEBUG LOGNAME ": Enable IRQ failed\n"); - - return -EIO; -} - -int msnd_disable_irq(multisound_dev_t *dev) -{ - unsigned long flags; - - if (--dev->irq_ref > 0) - return 0; - - if (dev->irq_ref < 0) - printk(KERN_DEBUG LOGNAME ": IRQ ref count is %d\n", dev->irq_ref); - - printk(KERN_DEBUG LOGNAME ": Disabling IRQ\n"); - - spin_lock_irqsave(&dev->lock, flags); - if (msnd_wait_TXDE(dev) == 0) { - msnd_outb(msnd_inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR); - if (dev->type == msndClassic) - msnd_outb(HPIRQ_NONE, dev->io + HP_IRQM); - disable_irq(dev->irq); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - printk(KERN_DEBUG LOGNAME ": Disable IRQ failed\n"); - - return -EIO; -} - -#ifndef LINUX20 -EXPORT_SYMBOL(msnd_register); -EXPORT_SYMBOL(msnd_unregister); - -EXPORT_SYMBOL(msnd_init_queue); - -EXPORT_SYMBOL(msnd_fifo_init); -EXPORT_SYMBOL(msnd_fifo_free); -EXPORT_SYMBOL(msnd_fifo_alloc); -EXPORT_SYMBOL(msnd_fifo_make_empty); -EXPORT_SYMBOL(msnd_fifo_write_io); -EXPORT_SYMBOL(msnd_fifo_read_io); -EXPORT_SYMBOL(msnd_fifo_write); -EXPORT_SYMBOL(msnd_fifo_read); - -EXPORT_SYMBOL(msnd_send_dsp_cmd); -EXPORT_SYMBOL(msnd_send_word); -EXPORT_SYMBOL(msnd_upload_host); - -EXPORT_SYMBOL(msnd_enable_irq); -EXPORT_SYMBOL(msnd_disable_irq); -#endif - -#ifdef MODULE -MODULE_AUTHOR ("Andrew Veliath "); -MODULE_DESCRIPTION ("Turtle Beach MultiSound Driver Base"); -MODULE_LICENSE("GPL"); - - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{ -} -#endif diff --git a/ANDROID_3.4.5/sound/oss/msnd.h b/ANDROID_3.4.5/sound/oss/msnd.h deleted file mode 100644 index c8be47ec..00000000 --- a/ANDROID_3.4.5/sound/oss/msnd.h +++ /dev/null @@ -1,278 +0,0 @@ -/********************************************************************* - * - * msnd.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_H -#define __MSND_H - -#define VERSION "0.8.3.1" - -#define DEFSAMPLERATE DSP_DEFAULT_SPEED -#define DEFSAMPLESIZE AFMT_U8 -#define DEFCHANNELS 1 - -#define DEFFIFOSIZE 128 - -#define SNDCARD_MSND 38 - -#define SRAM_BANK_SIZE 0x8000 -#define SRAM_CNTL_START 0x7F00 - -#define DSP_BASE_ADDR 0x4000 -#define DSP_BANK_BASE 0x4000 - -#define HP_ICR 0x00 -#define HP_CVR 0x01 -#define HP_ISR 0x02 -#define HP_IVR 0x03 -#define HP_NU 0x04 -#define HP_INFO 0x04 -#define HP_TXH 0x05 -#define HP_RXH 0x05 -#define HP_TXM 0x06 -#define HP_RXM 0x06 -#define HP_TXL 0x07 -#define HP_RXL 0x07 - -#define HP_ICR_DEF 0x00 -#define HP_CVR_DEF 0x12 -#define HP_ISR_DEF 0x06 -#define HP_IVR_DEF 0x0f -#define HP_NU_DEF 0x00 - -#define HP_IRQM 0x09 - -#define HPR_BLRC 0x08 -#define HPR_SPR1 0x09 -#define HPR_SPR2 0x0A -#define HPR_TCL0 0x0B -#define HPR_TCL1 0x0C -#define HPR_TCL2 0x0D -#define HPR_TCL3 0x0E -#define HPR_TCL4 0x0F - -#define HPICR_INIT 0x80 -#define HPICR_HM1 0x40 -#define HPICR_HM0 0x20 -#define HPICR_HF1 0x10 -#define HPICR_HF0 0x08 -#define HPICR_TREQ 0x02 -#define HPICR_RREQ 0x01 - -#define HPCVR_HC 0x80 - -#define HPISR_HREQ 0x80 -#define HPISR_DMA 0x40 -#define HPISR_HF3 0x10 -#define HPISR_HF2 0x08 -#define HPISR_TRDY 0x04 -#define HPISR_TXDE 0x02 -#define HPISR_RXDF 0x01 - -#define HPIO_290 0 -#define HPIO_260 1 -#define HPIO_250 2 -#define HPIO_240 3 -#define HPIO_230 4 -#define HPIO_220 5 -#define HPIO_210 6 -#define HPIO_3E0 7 - -#define HPMEM_NONE 0 -#define HPMEM_B000 1 -#define HPMEM_C800 2 -#define HPMEM_D000 3 -#define HPMEM_D400 4 -#define HPMEM_D800 5 -#define HPMEM_E000 6 -#define HPMEM_E800 7 - -#define HPIRQ_NONE 0 -#define HPIRQ_5 1 -#define HPIRQ_7 2 -#define HPIRQ_9 3 -#define HPIRQ_10 4 -#define HPIRQ_11 5 -#define HPIRQ_12 6 -#define HPIRQ_15 7 - -#define HIMT_PLAY_DONE 0x00 -#define HIMT_RECORD_DONE 0x01 -#define HIMT_MIDI_EOS 0x02 -#define HIMT_MIDI_OUT 0x03 - -#define HIMT_MIDI_IN_UCHAR 0x0E -#define HIMT_DSP 0x0F - -#define HDEX_BASE 0x92 -#define HDEX_PLAY_START (0 + HDEX_BASE) -#define HDEX_PLAY_STOP (1 + HDEX_BASE) -#define HDEX_PLAY_PAUSE (2 + HDEX_BASE) -#define HDEX_PLAY_RESUME (3 + HDEX_BASE) -#define HDEX_RECORD_START (4 + HDEX_BASE) -#define HDEX_RECORD_STOP (5 + HDEX_BASE) -#define HDEX_MIDI_IN_START (6 + HDEX_BASE) -#define HDEX_MIDI_IN_STOP (7 + HDEX_BASE) -#define HDEX_MIDI_OUT_START (8 + HDEX_BASE) -#define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE) -#define HDEX_AUX_REQ (10 + HDEX_BASE) - -#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF)) -#define LOWORD(l) ((WORD)(DWORD)(l)) -#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) -#define LOBYTE(w) ((BYTE)(w)) -#define MAKELONG(low,hi) ((long)(((WORD)(low))|(((DWORD)((WORD)(hi)))<<16))) -#define MAKEWORD(low,hi) ((WORD)(((BYTE)(low))|(((WORD)((BYTE)(hi)))<<8))) - -#define PCTODSP_OFFSET(w) (USHORT)((w)/2) -#define PCTODSP_BASED(w) (USHORT)(((w)/2) + DSP_BASE_ADDR) -#define DSPTOPC_BASED(w) (((w) - DSP_BASE_ADDR) * 2) - -#ifdef SLOWIO -#define msnd_outb outb_p -#define msnd_inb inb_p -#else -#define msnd_outb outb -#define msnd_inb inb -#endif - -/* JobQueueStruct */ -#define JQS_wStart 0x00 -#define JQS_wSize 0x02 -#define JQS_wHead 0x04 -#define JQS_wTail 0x06 -#define JQS__size 0x08 - -/* DAQueueDataStruct */ -#define DAQDS_wStart 0x00 -#define DAQDS_wSize 0x02 -#define DAQDS_wFormat 0x04 -#define DAQDS_wSampleSize 0x06 -#define DAQDS_wChannels 0x08 -#define DAQDS_wSampleRate 0x0A -#define DAQDS_wIntMsg 0x0C -#define DAQDS_wFlags 0x0E -#define DAQDS__size 0x10 - -typedef u8 BYTE; -typedef u16 USHORT; -typedef u16 WORD; -typedef u32 DWORD; -typedef void __iomem * LPDAQD; - -/* Generic FIFO */ -typedef struct { - size_t n, len; - char *data; - int head, tail; -} msnd_fifo; - -typedef struct multisound_dev { - /* Linux device info */ - char *name; - int dsp_minor, mixer_minor; - int ext_midi_dev, hdr_midi_dev; - - /* Hardware resources */ - int io, numio; - int memid, irqid; - int irq, irq_ref; - unsigned char info; - void __iomem *base; - - /* Motorola 56k DSP SMA */ - void __iomem *SMA; - void __iomem *DAPQ, *DARQ, *MODQ, *MIDQ, *DSPQ; - void __iomem *pwDSPQData, *pwMIDQData, *pwMODQData; - int dspq_data_buff, dspq_buff_size; - - /* State variables */ - enum { msndClassic, msndPinnacle } type; - fmode_t mode; - unsigned long flags; -#define F_RESETTING 0 -#define F_HAVEDIGITAL 1 -#define F_AUDIO_WRITE_INUSE 2 -#define F_WRITING 3 -#define F_WRITEBLOCK 4 -#define F_WRITEFLUSH 5 -#define F_AUDIO_READ_INUSE 6 -#define F_READING 7 -#define F_READBLOCK 8 -#define F_EXT_MIDI_INUSE 9 -#define F_HDR_MIDI_INUSE 10 -#define F_DISABLE_WRITE_NDELAY 11 - wait_queue_head_t writeblock; - wait_queue_head_t readblock; - wait_queue_head_t writeflush; - spinlock_t lock; - int nresets; - unsigned long recsrc; - int left_levels[32]; - int right_levels[32]; - int mixer_mod_count; - int calibrate_signal; - int play_sample_size, play_sample_rate, play_channels; - int play_ndelay; - int rec_sample_size, rec_sample_rate, rec_channels; - int rec_ndelay; - BYTE bCurrentMidiPatch; - - /* Digital audio FIFOs */ - msnd_fifo DAPF, DARF; - int fifosize; - int last_playbank, last_recbank; - - /* MIDI in callback */ - void (*midi_in_interrupt)(struct multisound_dev *); -} multisound_dev_t; - -#ifndef mdelay -# define mdelay(a) udelay((a) * 1000) -#endif - -int msnd_register(multisound_dev_t *dev); -void msnd_unregister(multisound_dev_t *dev); - -void msnd_init_queue(void __iomem *, int start, int size); - -void msnd_fifo_init(msnd_fifo *f); -void msnd_fifo_free(msnd_fifo *f); -int msnd_fifo_alloc(msnd_fifo *f, size_t n); -void msnd_fifo_make_empty(msnd_fifo *f); -int msnd_fifo_write_io(msnd_fifo *f, char __iomem *buf, size_t len); -int msnd_fifo_read_io(msnd_fifo *f, char __iomem *buf, size_t len); -int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len); -int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len); - -int msnd_send_dsp_cmd(multisound_dev_t *dev, BYTE cmd); -int msnd_send_word(multisound_dev_t *dev, unsigned char high, - unsigned char mid, unsigned char low); -int msnd_upload_host(multisound_dev_t *dev, char *bin, int len); -int msnd_enable_irq(multisound_dev_t *dev); -int msnd_disable_irq(multisound_dev_t *dev); - -#endif /* __MSND_H */ diff --git a/ANDROID_3.4.5/sound/oss/msnd_classic.c b/ANDROID_3.4.5/sound/oss/msnd_classic.c deleted file mode 100644 index 3b23a096..00000000 --- a/ANDROID_3.4.5/sound/oss/msnd_classic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* The work is in msnd_pinnacle.c, just define MSND_CLASSIC before it. */ -#define MSND_CLASSIC -#include "msnd_pinnacle.c" diff --git a/ANDROID_3.4.5/sound/oss/msnd_classic.h b/ANDROID_3.4.5/sound/oss/msnd_classic.h deleted file mode 100644 index 1a17dde2..00000000 --- a/ANDROID_3.4.5/sound/oss/msnd_classic.h +++ /dev/null @@ -1,185 +0,0 @@ -/********************************************************************* - * - * msnd_classic.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_CLASSIC_H -#define __MSND_CLASSIC_H - - -#define DSP_NUMIO 0x10 - -#define HP_MEMM 0x08 - -#define HP_BITM 0x0E -#define HP_WAIT 0x0D -#define HP_DSPR 0x0A -#define HP_PROR 0x0B -#define HP_BLKS 0x0C - -#define HPPRORESET_OFF 0 -#define HPPRORESET_ON 1 - -#define HPDSPRESET_OFF 0 -#define HPDSPRESET_ON 1 - -#define HPBLKSEL_0 0 -#define HPBLKSEL_1 1 - -#define HPWAITSTATE_0 0 -#define HPWAITSTATE_1 1 - -#define HPBITMODE_16 0 -#define HPBITMODE_8 1 - -#define HIDSP_INT_PLAY_UNDER 0x00 -#define HIDSP_INT_RECORD_OVER 0x01 -#define HIDSP_INPUT_CLIPPING 0x02 -#define HIDSP_MIDI_IN_OVER 0x10 -#define HIDSP_MIDI_OVERRUN_ERR 0x13 - -#define HDEXAR_CLEAR_PEAKS 1 -#define HDEXAR_IN_SET_POTS 2 -#define HDEXAR_AUX_SET_POTS 3 -#define HDEXAR_CAL_A_TO_D 4 -#define HDEXAR_RD_EXT_DSP_BITS 5 - -#define TIME_PRO_RESET_DONE 0x028A -#define TIME_PRO_SYSEX 0x0040 -#define TIME_PRO_RESET 0x0032 - -#define AGND 0x01 -#define SIGNAL 0x02 - -#define EXT_DSP_BIT_DCAL 0x0001 -#define EXT_DSP_BIT_MIDI_CON 0x0002 - -#define BUFFSIZE 0x8000 -#define HOSTQ_SIZE 0x40 - -#define SRAM_CNTL_START 0x7F00 -#define SMA_STRUCT_START 0x7F40 - -#define DAP_BUFF_SIZE 0x2400 -#define DAR_BUFF_SIZE 0x2000 - -#define DAPQ_STRUCT_SIZE 0x10 -#define DARQ_STRUCT_SIZE 0x10 -#define DAPQ_BUFF_SIZE (3 * 0x10) -#define DARQ_BUFF_SIZE (3 * 0x10) -#define MODQ_BUFF_SIZE 0x400 -#define MIDQ_BUFF_SIZE 0x200 -#define DSPQ_BUFF_SIZE 0x40 - -#define DAPQ_DATA_BUFF 0x6C00 -#define DARQ_DATA_BUFF 0x6C30 -#define MODQ_DATA_BUFF 0x6C60 -#define MIDQ_DATA_BUFF 0x7060 -#define DSPQ_DATA_BUFF 0x7260 - -#define DAPQ_OFFSET SRAM_CNTL_START -#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) -#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) -#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) -#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) - -#define MOP_SYNTH 0x10 -#define MOP_EXTOUT 0x32 -#define MOP_EXTTHRU 0x02 -#define MOP_OUTMASK 0x01 - -#define MIP_EXTIN 0x01 -#define MIP_SYNTH 0x00 -#define MIP_INMASK 0x32 - -/* Classic SMA Common Data */ -#define SMA_wCurrPlayBytes 0x0000 -#define SMA_wCurrRecordBytes 0x0002 -#define SMA_wCurrPlayVolLeft 0x0004 -#define SMA_wCurrPlayVolRight 0x0006 -#define SMA_wCurrInVolLeft 0x0008 -#define SMA_wCurrInVolRight 0x000a -#define SMA_wUser_3 0x000c -#define SMA_wUser_4 0x000e -#define SMA_dwUser_5 0x0010 -#define SMA_dwUser_6 0x0014 -#define SMA_wUser_7 0x0018 -#define SMA_wReserved_A 0x001a -#define SMA_wReserved_B 0x001c -#define SMA_wReserved_C 0x001e -#define SMA_wReserved_D 0x0020 -#define SMA_wReserved_E 0x0022 -#define SMA_wReserved_F 0x0024 -#define SMA_wReserved_G 0x0026 -#define SMA_wReserved_H 0x0028 -#define SMA_wCurrDSPStatusFlags 0x002a -#define SMA_wCurrHostStatusFlags 0x002c -#define SMA_wCurrInputTagBits 0x002e -#define SMA_wCurrLeftPeak 0x0030 -#define SMA_wCurrRightPeak 0x0032 -#define SMA_wExtDSPbits 0x0034 -#define SMA_bExtHostbits 0x0036 -#define SMA_bBoardLevel 0x0037 -#define SMA_bInPotPosRight 0x0038 -#define SMA_bInPotPosLeft 0x0039 -#define SMA_bAuxPotPosRight 0x003a -#define SMA_bAuxPotPosLeft 0x003b -#define SMA_wCurrMastVolLeft 0x003c -#define SMA_wCurrMastVolRight 0x003e -#define SMA_bUser_12 0x0040 -#define SMA_bUser_13 0x0041 -#define SMA_wUser_14 0x0042 -#define SMA_wUser_15 0x0044 -#define SMA_wCalFreqAtoD 0x0046 -#define SMA_wUser_16 0x0048 -#define SMA_wUser_17 0x004a -#define SMA__size 0x004c - -#ifdef HAVE_DSPCODEH -# include "msndperm.c" -# include "msndinit.c" -# define PERMCODE msndperm -# define INITCODE msndinit -# define PERMCODESIZE sizeof(msndperm) -# define INITCODESIZE sizeof(msndinit) -#else -# ifndef CONFIG_MSNDCLAS_INIT_FILE -# define CONFIG_MSNDCLAS_INIT_FILE \ - "/etc/sound/msndinit.bin" -# endif -# ifndef CONFIG_MSNDCLAS_PERM_FILE -# define CONFIG_MSNDCLAS_PERM_FILE \ - "/etc/sound/msndperm.bin" -# endif -# define PERMCODEFILE CONFIG_MSNDCLAS_PERM_FILE -# define INITCODEFILE CONFIG_MSNDCLAS_INIT_FILE -# define PERMCODE dspini -# define INITCODE permini -# define PERMCODESIZE sizeof_dspini -# define INITCODESIZE sizeof_permini -#endif -#define LONGNAME "MultiSound (Classic/Monterey/Tahiti)" - -#endif /* __MSND_CLASSIC_H */ diff --git a/ANDROID_3.4.5/sound/oss/msnd_pinnacle.c b/ANDROID_3.4.5/sound/oss/msnd_pinnacle.c deleted file mode 100644 index 536c4c05..00000000 --- a/ANDROID_3.4.5/sound/oss/msnd_pinnacle.c +++ /dev/null @@ -1,1935 +0,0 @@ -/********************************************************************* - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * Linux 2.0/2.2 Version - * - * msnd_pinnacle.c / msnd_classic.c - * - * -- If MSND_CLASSIC is defined: - * - * -> driver for Turtle Beach Classic/Monterey/Tahiti - * - * -- Else - * - * -> driver for Turtle Beach Pinnacle/Fiji - * - * Copyright (C) 1998 Andrew Veliath - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * 12-3-2000 Modified IO port validation Steve Sycamore - * - ********************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sound_config.h" -#include "sound_firmware.h" -#ifdef MSND_CLASSIC -# ifndef __alpha__ -# define SLOWIO -# endif -#endif -#include "msnd.h" -#ifdef MSND_CLASSIC -# ifdef CONFIG_MSNDCLAS_HAVE_BOOT -# define HAVE_DSPCODEH -# endif -# include "msnd_classic.h" -# define LOGNAME "msnd_classic" -#else -# ifdef CONFIG_MSNDPIN_HAVE_BOOT -# define HAVE_DSPCODEH -# endif -# include "msnd_pinnacle.h" -# define LOGNAME "msnd_pinnacle" -#endif - -#ifndef CONFIG_MSND_WRITE_NDELAY -# define CONFIG_MSND_WRITE_NDELAY 1 -#endif - -#define get_play_delay_jiffies(size) ((size) * HZ * \ - dev.play_sample_size / 8 / \ - dev.play_sample_rate / \ - dev.play_channels) - -#define get_rec_delay_jiffies(size) ((size) * HZ * \ - dev.rec_sample_size / 8 / \ - dev.rec_sample_rate / \ - dev.rec_channels) - -static DEFINE_MUTEX(msnd_pinnacle_mutex); -static multisound_dev_t dev; - -#ifndef HAVE_DSPCODEH -static char *dspini, *permini; -static int sizeof_dspini, sizeof_permini; -#endif - -static int dsp_full_reset(void); -static void dsp_write_flush(void); - -static __inline__ int chk_send_dsp_cmd(multisound_dev_t *dev, register BYTE cmd) -{ - if (msnd_send_dsp_cmd(dev, cmd) == 0) - return 0; - dsp_full_reset(); - return msnd_send_dsp_cmd(dev, cmd); -} - -static void reset_play_queue(void) -{ - int n; - LPDAQD lpDAQ; - - dev.last_playbank = -1; - writew(PCTODSP_OFFSET(0 * DAQDS__size), dev.DAPQ + JQS_wHead); - writew(PCTODSP_OFFSET(0 * DAQDS__size), dev.DAPQ + JQS_wTail); - - for (n = 0, lpDAQ = dev.base + DAPQ_DATA_BUFF; n < 3; ++n, lpDAQ += DAQDS__size) { - writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), lpDAQ + DAQDS_wStart); - writew(0, lpDAQ + DAQDS_wSize); - writew(1, lpDAQ + DAQDS_wFormat); - writew(dev.play_sample_size, lpDAQ + DAQDS_wSampleSize); - writew(dev.play_channels, lpDAQ + DAQDS_wChannels); - writew(dev.play_sample_rate, lpDAQ + DAQDS_wSampleRate); - writew(HIMT_PLAY_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg); - writew(n, lpDAQ + DAQDS_wFlags); - } -} - -static void reset_record_queue(void) -{ - int n; - LPDAQD lpDAQ; - unsigned long flags; - - dev.last_recbank = 2; - writew(PCTODSP_OFFSET(0 * DAQDS__size), dev.DARQ + JQS_wHead); - writew(PCTODSP_OFFSET(dev.last_recbank * DAQDS__size), dev.DARQ + JQS_wTail); - - /* Critical section: bank 1 access */ - spin_lock_irqsave(&dev.lock, flags); - msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS); - memset_io(dev.base, 0, DAR_BUFF_SIZE * 3); - msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS); - spin_unlock_irqrestore(&dev.lock, flags); - - for (n = 0, lpDAQ = dev.base + DARQ_DATA_BUFF; n < 3; ++n, lpDAQ += DAQDS__size) { - writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, lpDAQ + DAQDS_wStart); - writew(DAR_BUFF_SIZE, lpDAQ + DAQDS_wSize); - writew(1, lpDAQ + DAQDS_wFormat); - writew(dev.rec_sample_size, lpDAQ + DAQDS_wSampleSize); - writew(dev.rec_channels, lpDAQ + DAQDS_wChannels); - writew(dev.rec_sample_rate, lpDAQ + DAQDS_wSampleRate); - writew(HIMT_RECORD_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg); - writew(n, lpDAQ + DAQDS_wFlags); - } -} - -static void reset_queues(void) -{ - if (dev.mode & FMODE_WRITE) { - msnd_fifo_make_empty(&dev.DAPF); - reset_play_queue(); - } - if (dev.mode & FMODE_READ) { - msnd_fifo_make_empty(&dev.DARF); - reset_record_queue(); - } -} - -static int dsp_set_format(struct file *file, int val) -{ - int data, i; - LPDAQD lpDAQ, lpDARQ; - - lpDAQ = dev.base + DAPQ_DATA_BUFF; - lpDARQ = dev.base + DARQ_DATA_BUFF; - - switch (val) { - case AFMT_U8: - case AFMT_S16_LE: - data = val; - break; - default: - data = DEFSAMPLESIZE; - break; - } - - for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) { - if (file->f_mode & FMODE_WRITE) - writew(data, lpDAQ + DAQDS_wSampleSize); - if (file->f_mode & FMODE_READ) - writew(data, lpDARQ + DAQDS_wSampleSize); - } - if (file->f_mode & FMODE_WRITE) - dev.play_sample_size = data; - if (file->f_mode & FMODE_READ) - dev.rec_sample_size = data; - - return data; -} - -static int dsp_get_frag_size(void) -{ - int size; - size = dev.fifosize / 4; - if (size > 32 * 1024) - size = 32 * 1024; - return size; -} - -static int dsp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int val, i, data, tmp; - LPDAQD lpDAQ, lpDARQ; - audio_buf_info abinfo; - unsigned long flags; - int __user *p = (int __user *)arg; - - lpDAQ = dev.base + DAPQ_DATA_BUFF; - lpDARQ = dev.base + DARQ_DATA_BUFF; - - switch (cmd) { - case SNDCTL_DSP_SUBDIVIDE: - case SNDCTL_DSP_SETFRAGMENT: - case SNDCTL_DSP_SETDUPLEX: - case SNDCTL_DSP_POST: - return 0; - - case SNDCTL_DSP_GETIPTR: - case SNDCTL_DSP_GETOPTR: - case SNDCTL_DSP_MAPINBUF: - case SNDCTL_DSP_MAPOUTBUF: - return -EINVAL; - - case SNDCTL_DSP_GETOSPACE: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - spin_lock_irqsave(&dev.lock, flags); - abinfo.fragsize = dsp_get_frag_size(); - abinfo.bytes = dev.DAPF.n - dev.DAPF.len; - abinfo.fragstotal = dev.DAPF.n / abinfo.fragsize; - abinfo.fragments = abinfo.bytes / abinfo.fragsize; - spin_unlock_irqrestore(&dev.lock, flags); - return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; - - case SNDCTL_DSP_GETISPACE: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - spin_lock_irqsave(&dev.lock, flags); - abinfo.fragsize = dsp_get_frag_size(); - abinfo.bytes = dev.DARF.n - dev.DARF.len; - abinfo.fragstotal = dev.DARF.n / abinfo.fragsize; - abinfo.fragments = abinfo.bytes / abinfo.fragsize; - spin_unlock_irqrestore(&dev.lock, flags); - return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; - - case SNDCTL_DSP_RESET: - dev.nresets = 0; - reset_queues(); - return 0; - - case SNDCTL_DSP_SYNC: - dsp_write_flush(); - return 0; - - case SNDCTL_DSP_GETBLKSIZE: - tmp = dsp_get_frag_size(); - if (put_user(tmp, p)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_GETFMTS: - val = AFMT_S16_LE | AFMT_U8; - if (put_user(val, p)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_SETFMT: - if (get_user(val, p)) - return -EFAULT; - - if (file->f_mode & FMODE_WRITE) - data = val == AFMT_QUERY - ? dev.play_sample_size - : dsp_set_format(file, val); - else - data = val == AFMT_QUERY - ? dev.rec_sample_size - : dsp_set_format(file, val); - - if (put_user(data, p)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_NONBLOCK: - if (!test_bit(F_DISABLE_WRITE_NDELAY, &dev.flags) && - file->f_mode & FMODE_WRITE) - dev.play_ndelay = 1; - if (file->f_mode & FMODE_READ) - dev.rec_ndelay = 1; - return 0; - - case SNDCTL_DSP_GETCAPS: - val = DSP_CAP_DUPLEX | DSP_CAP_BATCH; - if (put_user(val, p)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_SPEED: - if (get_user(val, p)) - return -EFAULT; - - if (val < 8000) - val = 8000; - - if (val > 48000) - val = 48000; - - data = val; - - for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) { - if (file->f_mode & FMODE_WRITE) - writew(data, lpDAQ + DAQDS_wSampleRate); - if (file->f_mode & FMODE_READ) - writew(data, lpDARQ + DAQDS_wSampleRate); - } - if (file->f_mode & FMODE_WRITE) - dev.play_sample_rate = data; - if (file->f_mode & FMODE_READ) - dev.rec_sample_rate = data; - - if (put_user(data, p)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_CHANNELS: - case SNDCTL_DSP_STEREO: - if (get_user(val, p)) - return -EFAULT; - - if (cmd == SNDCTL_DSP_CHANNELS) { - switch (val) { - case 1: - case 2: - data = val; - break; - default: - val = data = 2; - break; - } - } else { - switch (val) { - case 0: - data = 1; - break; - default: - val = 1; - case 1: - data = 2; - break; - } - } - - for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) { - if (file->f_mode & FMODE_WRITE) - writew(data, lpDAQ + DAQDS_wChannels); - if (file->f_mode & FMODE_READ) - writew(data, lpDARQ + DAQDS_wChannels); - } - if (file->f_mode & FMODE_WRITE) - dev.play_channels = data; - if (file->f_mode & FMODE_READ) - dev.rec_channels = data; - - if (put_user(val, p)) - return -EFAULT; - return 0; - } - - return -EINVAL; -} - -static int mixer_get(int d) -{ - if (d > 31) - return -EINVAL; - - switch (d) { - case SOUND_MIXER_VOLUME: - case SOUND_MIXER_PCM: - case SOUND_MIXER_LINE: - case SOUND_MIXER_IMIX: - case SOUND_MIXER_LINE1: -#ifndef MSND_CLASSIC - case SOUND_MIXER_MIC: - case SOUND_MIXER_SYNTH: -#endif - return (dev.left_levels[d] >> 8) * 100 / 0xff | - (((dev.right_levels[d] >> 8) * 100 / 0xff) << 8); - default: - return 0; - } -} - -#define update_volm(a,b) \ - writew((dev.left_levels[a] >> 1) * \ - readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff, \ - dev.SMA + SMA_##b##Left); \ - writew((dev.right_levels[a] >> 1) * \ - readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff, \ - dev.SMA + SMA_##b##Right); - -#define update_potm(d,s,ar) \ - writeb((dev.left_levels[d] >> 8) * \ - readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff, \ - dev.SMA + SMA_##s##Left); \ - writeb((dev.right_levels[d] >> 8) * \ - readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff, \ - dev.SMA + SMA_##s##Right); \ - if (msnd_send_word(&dev, 0, 0, ar) == 0) \ - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ); - -#define update_pot(d,s,ar) \ - writeb(dev.left_levels[d] >> 8, \ - dev.SMA + SMA_##s##Left); \ - writeb(dev.right_levels[d] >> 8, \ - dev.SMA + SMA_##s##Right); \ - if (msnd_send_word(&dev, 0, 0, ar) == 0) \ - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ); - -static int mixer_set(int d, int value) -{ - int left = value & 0x000000ff; - int right = (value & 0x0000ff00) >> 8; - int bLeft, bRight; - int wLeft, wRight; - int updatemaster = 0; - - if (d > 31) - return -EINVAL; - - bLeft = left * 0xff / 100; - wLeft = left * 0xffff / 100; - - bRight = right * 0xff / 100; - wRight = right * 0xffff / 100; - - dev.left_levels[d] = wLeft; - dev.right_levels[d] = wRight; - - switch (d) { - /* master volume unscaled controls */ - case SOUND_MIXER_LINE: /* line pot control */ - /* scaled by IMIX in digital mix */ - writeb(bLeft, dev.SMA + SMA_bInPotPosLeft); - writeb(bRight, dev.SMA + SMA_bInPotPosRight); - if (msnd_send_word(&dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ); - break; -#ifndef MSND_CLASSIC - case SOUND_MIXER_MIC: /* mic pot control */ - /* scaled by IMIX in digital mix */ - writeb(bLeft, dev.SMA + SMA_bMicPotPosLeft); - writeb(bRight, dev.SMA + SMA_bMicPotPosRight); - if (msnd_send_word(&dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0) - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ); - break; -#endif - case SOUND_MIXER_VOLUME: /* master volume */ - writew(wLeft, dev.SMA + SMA_wCurrMastVolLeft); - writew(wRight, dev.SMA + SMA_wCurrMastVolRight); - /* fall through */ - - case SOUND_MIXER_LINE1: /* aux pot control */ - /* scaled by master volume */ - /* fall through */ - - /* digital controls */ - case SOUND_MIXER_SYNTH: /* synth vol (dsp mix) */ - case SOUND_MIXER_PCM: /* pcm vol (dsp mix) */ - case SOUND_MIXER_IMIX: /* input monitor (dsp mix) */ - /* scaled by master volume */ - updatemaster = 1; - break; - - default: - return 0; - } - - if (updatemaster) { - /* update master volume scaled controls */ - update_volm(SOUND_MIXER_PCM, wCurrPlayVol); - update_volm(SOUND_MIXER_IMIX, wCurrInVol); -#ifndef MSND_CLASSIC - update_volm(SOUND_MIXER_SYNTH, wCurrMHdrVol); -#endif - update_potm(SOUND_MIXER_LINE1, bAuxPotPos, HDEXAR_AUX_SET_POTS); - } - - return mixer_get(d); -} - -static void mixer_setup(void) -{ - update_pot(SOUND_MIXER_LINE, bInPotPos, HDEXAR_IN_SET_POTS); - update_potm(SOUND_MIXER_LINE1, bAuxPotPos, HDEXAR_AUX_SET_POTS); - update_volm(SOUND_MIXER_PCM, wCurrPlayVol); - update_volm(SOUND_MIXER_IMIX, wCurrInVol); -#ifndef MSND_CLASSIC - update_pot(SOUND_MIXER_MIC, bMicPotPos, HDEXAR_MIC_SET_POTS); - update_volm(SOUND_MIXER_SYNTH, wCurrMHdrVol); -#endif -} - -static unsigned long set_recsrc(unsigned long recsrc) -{ - if (dev.recsrc == recsrc) - return dev.recsrc; -#ifdef HAVE_NORECSRC - else if (recsrc == 0) - dev.recsrc = 0; -#endif - else - dev.recsrc ^= recsrc; - -#ifndef MSND_CLASSIC - if (dev.recsrc & SOUND_MASK_IMIX) { - if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0) - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ); - } - else if (dev.recsrc & SOUND_MASK_SYNTH) { - if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_SYNTH_IN) == 0) - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ); - } - else if ((dev.recsrc & SOUND_MASK_DIGITAL1) && test_bit(F_HAVEDIGITAL, &dev.flags)) { - if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_DAT_IN) == 0) - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ); - } - else { -#ifdef HAVE_NORECSRC - /* Select no input (?) */ - dev.recsrc = 0; -#else - dev.recsrc = SOUND_MASK_IMIX; - if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0) - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ); -#endif - } -#endif /* MSND_CLASSIC */ - - return dev.recsrc; -} - -static unsigned long force_recsrc(unsigned long recsrc) -{ - dev.recsrc = 0; - return set_recsrc(recsrc); -} - -#define set_mixer_info() \ - memset(&info, 0, sizeof(info)); \ - strlcpy(info.id, "MSNDMIXER", sizeof(info.id)); \ - strlcpy(info.name, "MultiSound Mixer", sizeof(info.name)); - -static int mixer_ioctl(unsigned int cmd, unsigned long arg) -{ - if (cmd == SOUND_MIXER_INFO) { - mixer_info info; - set_mixer_info(); - info.modify_counter = dev.mixer_mod_count; - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } else if (cmd == SOUND_OLD_MIXER_INFO) { - _old_mixer_info info; - set_mixer_info(); - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } else if (cmd == SOUND_MIXER_PRIVATE1) { - dev.nresets = 0; - dsp_full_reset(); - return 0; - } else if (((cmd >> 8) & 0xff) == 'M') { - int val = 0; - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) { - switch (cmd & 0xff) { - case SOUND_MIXER_RECSRC: - if (get_user(val, (int __user *)arg)) - return -EFAULT; - val = set_recsrc(val); - break; - - default: - if (get_user(val, (int __user *)arg)) - return -EFAULT; - val = mixer_set(cmd & 0xff, val); - break; - } - ++dev.mixer_mod_count; - return put_user(val, (int __user *)arg); - } else { - switch (cmd & 0xff) { - case SOUND_MIXER_RECSRC: - val = dev.recsrc; - break; - - case SOUND_MIXER_DEVMASK: - case SOUND_MIXER_STEREODEVS: - val = SOUND_MASK_PCM | - SOUND_MASK_LINE | - SOUND_MASK_IMIX | - SOUND_MASK_LINE1 | -#ifndef MSND_CLASSIC - SOUND_MASK_MIC | - SOUND_MASK_SYNTH | -#endif - SOUND_MASK_VOLUME; - break; - - case SOUND_MIXER_RECMASK: -#ifdef MSND_CLASSIC - val = 0; -#else - val = SOUND_MASK_IMIX | - SOUND_MASK_SYNTH; - if (test_bit(F_HAVEDIGITAL, &dev.flags)) - val |= SOUND_MASK_DIGITAL1; -#endif - break; - - case SOUND_MIXER_CAPS: - val = SOUND_CAP_EXCL_INPUT; - break; - - default: - if ((val = mixer_get(cmd & 0xff)) < 0) - return -EINVAL; - break; - } - } - - return put_user(val, (int __user *)arg); - } - - return -EINVAL; -} - -static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int minor = iminor(file->f_path.dentry->d_inode); - int ret; - - if (cmd == OSS_GETVERSION) { - int sound_version = SOUND_VERSION; - return put_user(sound_version, (int __user *)arg); - } - - ret = -EINVAL; - - mutex_lock(&msnd_pinnacle_mutex); - if (minor == dev.dsp_minor) - ret = dsp_ioctl(file, cmd, arg); - else if (minor == dev.mixer_minor) - ret = mixer_ioctl(cmd, arg); - mutex_unlock(&msnd_pinnacle_mutex); - - return ret; -} - -static void dsp_write_flush(void) -{ - if (!(dev.mode & FMODE_WRITE) || !test_bit(F_WRITING, &dev.flags)) - return; - set_bit(F_WRITEFLUSH, &dev.flags); - interruptible_sleep_on_timeout( - &dev.writeflush, - get_play_delay_jiffies(dev.DAPF.len)); - clear_bit(F_WRITEFLUSH, &dev.flags); - if (!signal_pending(current)) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(get_play_delay_jiffies(DAP_BUFF_SIZE)); - } - clear_bit(F_WRITING, &dev.flags); -} - -static void dsp_halt(struct file *file) -{ - if ((file ? file->f_mode : dev.mode) & FMODE_READ) { - clear_bit(F_READING, &dev.flags); - chk_send_dsp_cmd(&dev, HDEX_RECORD_STOP); - msnd_disable_irq(&dev); - if (file) { - printk(KERN_DEBUG LOGNAME ": Stopping read for %p\n", file); - dev.mode &= ~FMODE_READ; - } - clear_bit(F_AUDIO_READ_INUSE, &dev.flags); - } - if ((file ? file->f_mode : dev.mode) & FMODE_WRITE) { - if (test_bit(F_WRITING, &dev.flags)) { - dsp_write_flush(); - chk_send_dsp_cmd(&dev, HDEX_PLAY_STOP); - } - msnd_disable_irq(&dev); - if (file) { - printk(KERN_DEBUG LOGNAME ": Stopping write for %p\n", file); - dev.mode &= ~FMODE_WRITE; - } - clear_bit(F_AUDIO_WRITE_INUSE, &dev.flags); - } -} - -static int dsp_release(struct file *file) -{ - dsp_halt(file); - return 0; -} - -static int dsp_open(struct file *file) -{ - if ((file ? file->f_mode : dev.mode) & FMODE_WRITE) { - set_bit(F_AUDIO_WRITE_INUSE, &dev.flags); - clear_bit(F_WRITING, &dev.flags); - msnd_fifo_make_empty(&dev.DAPF); - reset_play_queue(); - if (file) { - printk(KERN_DEBUG LOGNAME ": Starting write for %p\n", file); - dev.mode |= FMODE_WRITE; - } - msnd_enable_irq(&dev); - } - if ((file ? file->f_mode : dev.mode) & FMODE_READ) { - set_bit(F_AUDIO_READ_INUSE, &dev.flags); - clear_bit(F_READING, &dev.flags); - msnd_fifo_make_empty(&dev.DARF); - reset_record_queue(); - if (file) { - printk(KERN_DEBUG LOGNAME ": Starting read for %p\n", file); - dev.mode |= FMODE_READ; - } - msnd_enable_irq(&dev); - } - return 0; -} - -static void set_default_play_audio_parameters(void) -{ - dev.play_sample_size = DEFSAMPLESIZE; - dev.play_sample_rate = DEFSAMPLERATE; - dev.play_channels = DEFCHANNELS; -} - -static void set_default_rec_audio_parameters(void) -{ - dev.rec_sample_size = DEFSAMPLESIZE; - dev.rec_sample_rate = DEFSAMPLERATE; - dev.rec_channels = DEFCHANNELS; -} - -static void set_default_audio_parameters(void) -{ - set_default_play_audio_parameters(); - set_default_rec_audio_parameters(); -} - -static int dev_open(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - int err = 0; - - mutex_lock(&msnd_pinnacle_mutex); - if (minor == dev.dsp_minor) { - if ((file->f_mode & FMODE_WRITE && - test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) || - (file->f_mode & FMODE_READ && - test_bit(F_AUDIO_READ_INUSE, &dev.flags))) { - err = -EBUSY; - goto out; - } - - if ((err = dsp_open(file)) >= 0) { - dev.nresets = 0; - if (file->f_mode & FMODE_WRITE) { - set_default_play_audio_parameters(); - if (!test_bit(F_DISABLE_WRITE_NDELAY, &dev.flags)) - dev.play_ndelay = (file->f_flags & O_NDELAY) ? 1 : 0; - else - dev.play_ndelay = 0; - } - if (file->f_mode & FMODE_READ) { - set_default_rec_audio_parameters(); - dev.rec_ndelay = (file->f_flags & O_NDELAY) ? 1 : 0; - } - } - } - else if (minor == dev.mixer_minor) { - /* nothing */ - } else - err = -EINVAL; -out: - mutex_unlock(&msnd_pinnacle_mutex); - return err; -} - -static int dev_release(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - int err = 0; - - mutex_lock(&msnd_pinnacle_mutex); - if (minor == dev.dsp_minor) - err = dsp_release(file); - else if (minor == dev.mixer_minor) { - /* nothing */ - } else - err = -EINVAL; - mutex_unlock(&msnd_pinnacle_mutex); - return err; -} - -static __inline__ int pack_DARQ_to_DARF(register int bank) -{ - register int size, timeout = 3; - register WORD wTmp; - LPDAQD DAQD; - - /* Increment the tail and check for queue wrap */ - wTmp = readw(dev.DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size); - if (wTmp > readw(dev.DARQ + JQS_wSize)) - wTmp = 0; - while (wTmp == readw(dev.DARQ + JQS_wHead) && timeout--) - udelay(1); - writew(wTmp, dev.DARQ + JQS_wTail); - - /* Get our digital audio queue struct */ - DAQD = bank * DAQDS__size + dev.base + DARQ_DATA_BUFF; - - /* Get length of data */ - size = readw(DAQD + DAQDS_wSize); - - /* Read data from the head (unprotected bank 1 access okay - since this is only called inside an interrupt) */ - msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS); - msnd_fifo_write_io( - &dev.DARF, - dev.base + bank * DAR_BUFF_SIZE, - size); - msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS); - - return 1; -} - -static __inline__ int pack_DAPF_to_DAPQ(register int start) -{ - register WORD DAPQ_tail; - register int protect = start, nbanks = 0; - LPDAQD DAQD; - - DAPQ_tail = readw(dev.DAPQ + JQS_wTail); - while (DAPQ_tail != readw(dev.DAPQ + JQS_wHead) || start) { - register int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size); - register int n; - unsigned long flags; - - /* Write the data to the new tail */ - if (protect) { - /* Critical section: protect fifo in non-interrupt */ - spin_lock_irqsave(&dev.lock, flags); - n = msnd_fifo_read_io( - &dev.DAPF, - dev.base + bank_num * DAP_BUFF_SIZE, - DAP_BUFF_SIZE); - spin_unlock_irqrestore(&dev.lock, flags); - } else { - n = msnd_fifo_read_io( - &dev.DAPF, - dev.base + bank_num * DAP_BUFF_SIZE, - DAP_BUFF_SIZE); - } - if (!n) - break; - - if (start) - start = 0; - - /* Get our digital audio queue struct */ - DAQD = bank_num * DAQDS__size + dev.base + DAPQ_DATA_BUFF; - - /* Write size of this bank */ - writew(n, DAQD + DAQDS_wSize); - ++nbanks; - - /* Then advance the tail */ - DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); - writew(DAPQ_tail, dev.DAPQ + JQS_wTail); - /* Tell the DSP to play the bank */ - msnd_send_dsp_cmd(&dev, HDEX_PLAY_START); - } - return nbanks; -} - -static int dsp_read(char __user *buf, size_t len) -{ - int count = len; - char *page = (char *)__get_free_page(GFP_KERNEL); - - if (!page) - return -ENOMEM; - - while (count > 0) { - int n, k; - unsigned long flags; - - k = PAGE_SIZE; - if (k > count) - k = count; - - /* Critical section: protect fifo in non-interrupt */ - spin_lock_irqsave(&dev.lock, flags); - n = msnd_fifo_read(&dev.DARF, page, k); - spin_unlock_irqrestore(&dev.lock, flags); - if (copy_to_user(buf, page, n)) { - free_page((unsigned long)page); - return -EFAULT; - } - buf += n; - count -= n; - - if (n == k && count) - continue; - - if (!test_bit(F_READING, &dev.flags) && dev.mode & FMODE_READ) { - dev.last_recbank = -1; - if (chk_send_dsp_cmd(&dev, HDEX_RECORD_START) == 0) - set_bit(F_READING, &dev.flags); - } - - if (dev.rec_ndelay) { - free_page((unsigned long)page); - return count == len ? -EAGAIN : len - count; - } - - if (count > 0) { - set_bit(F_READBLOCK, &dev.flags); - if (!interruptible_sleep_on_timeout( - &dev.readblock, - get_rec_delay_jiffies(DAR_BUFF_SIZE))) - clear_bit(F_READING, &dev.flags); - clear_bit(F_READBLOCK, &dev.flags); - if (signal_pending(current)) { - free_page((unsigned long)page); - return -EINTR; - } - } - } - free_page((unsigned long)page); - return len - count; -} - -static int dsp_write(const char __user *buf, size_t len) -{ - int count = len; - char *page = (char *)__get_free_page(GFP_KERNEL); - - if (!page) - return -ENOMEM; - - while (count > 0) { - int n, k; - unsigned long flags; - - k = PAGE_SIZE; - if (k > count) - k = count; - - if (copy_from_user(page, buf, k)) { - free_page((unsigned long)page); - return -EFAULT; - } - - /* Critical section: protect fifo in non-interrupt */ - spin_lock_irqsave(&dev.lock, flags); - n = msnd_fifo_write(&dev.DAPF, page, k); - spin_unlock_irqrestore(&dev.lock, flags); - buf += n; - count -= n; - - if (count && n == k) - continue; - - if (!test_bit(F_WRITING, &dev.flags) && (dev.mode & FMODE_WRITE)) { - dev.last_playbank = -1; - if (pack_DAPF_to_DAPQ(1) > 0) - set_bit(F_WRITING, &dev.flags); - } - - if (dev.play_ndelay) { - free_page((unsigned long)page); - return count == len ? -EAGAIN : len - count; - } - - if (count > 0) { - set_bit(F_WRITEBLOCK, &dev.flags); - interruptible_sleep_on_timeout( - &dev.writeblock, - get_play_delay_jiffies(DAP_BUFF_SIZE)); - clear_bit(F_WRITEBLOCK, &dev.flags); - if (signal_pending(current)) { - free_page((unsigned long)page); - return -EINTR; - } - } - } - - free_page((unsigned long)page); - return len - count; -} - -static ssize_t dev_read(struct file *file, char __user *buf, size_t count, loff_t *off) -{ - int minor = iminor(file->f_path.dentry->d_inode); - if (minor == dev.dsp_minor) - return dsp_read(buf, count); - else - return -EINVAL; -} - -static ssize_t dev_write(struct file *file, const char __user *buf, size_t count, loff_t *off) -{ - int minor = iminor(file->f_path.dentry->d_inode); - if (minor == dev.dsp_minor) - return dsp_write(buf, count); - else - return -EINVAL; -} - -static __inline__ void eval_dsp_msg(register WORD wMessage) -{ - switch (HIBYTE(wMessage)) { - case HIMT_PLAY_DONE: - if (dev.last_playbank == LOBYTE(wMessage) || !test_bit(F_WRITING, &dev.flags)) - break; - dev.last_playbank = LOBYTE(wMessage); - - if (pack_DAPF_to_DAPQ(0) <= 0) { - if (!test_bit(F_WRITEBLOCK, &dev.flags)) { - if (test_and_clear_bit(F_WRITEFLUSH, &dev.flags)) - wake_up_interruptible(&dev.writeflush); - } - clear_bit(F_WRITING, &dev.flags); - } - - if (test_bit(F_WRITEBLOCK, &dev.flags)) - wake_up_interruptible(&dev.writeblock); - break; - - case HIMT_RECORD_DONE: - if (dev.last_recbank == LOBYTE(wMessage)) - break; - dev.last_recbank = LOBYTE(wMessage); - - pack_DARQ_to_DARF(dev.last_recbank); - - if (test_bit(F_READBLOCK, &dev.flags)) - wake_up_interruptible(&dev.readblock); - break; - - case HIMT_DSP: - switch (LOBYTE(wMessage)) { -#ifndef MSND_CLASSIC - case HIDSP_PLAY_UNDER: -#endif - case HIDSP_INT_PLAY_UNDER: -/* printk(KERN_DEBUG LOGNAME ": Play underflow\n"); */ - clear_bit(F_WRITING, &dev.flags); - break; - - case HIDSP_INT_RECORD_OVER: -/* printk(KERN_DEBUG LOGNAME ": Record overflow\n"); */ - clear_bit(F_READING, &dev.flags); - break; - - default: -/* printk(KERN_DEBUG LOGNAME ": DSP message %d 0x%02x\n", - LOBYTE(wMessage), LOBYTE(wMessage)); */ - break; - } - break; - - case HIMT_MIDI_IN_UCHAR: - if (dev.midi_in_interrupt) - (*dev.midi_in_interrupt)(&dev); - break; - - default: -/* printk(KERN_DEBUG LOGNAME ": HIMT message %d 0x%02x\n", HIBYTE(wMessage), HIBYTE(wMessage)); */ - break; - } -} - -static irqreturn_t intr(int irq, void *dev_id) -{ - /* Send ack to DSP */ - msnd_inb(dev.io + HP_RXL); - - /* Evaluate queued DSP messages */ - while (readw(dev.DSPQ + JQS_wTail) != readw(dev.DSPQ + JQS_wHead)) { - register WORD wTmp; - - eval_dsp_msg(readw(dev.pwDSPQData + 2*readw(dev.DSPQ + JQS_wHead))); - - if ((wTmp = readw(dev.DSPQ + JQS_wHead) + 1) > readw(dev.DSPQ + JQS_wSize)) - writew(0, dev.DSPQ + JQS_wHead); - else - writew(wTmp, dev.DSPQ + JQS_wHead); - } - return IRQ_HANDLED; -} - -static const struct file_operations dev_fileops = { - .owner = THIS_MODULE, - .read = dev_read, - .write = dev_write, - .unlocked_ioctl = dev_ioctl, - .open = dev_open, - .release = dev_release, - .llseek = noop_llseek, -}; - -static int reset_dsp(void) -{ - int timeout = 100; - - msnd_outb(HPDSPRESET_ON, dev.io + HP_DSPR); - mdelay(1); -#ifndef MSND_CLASSIC - dev.info = msnd_inb(dev.io + HP_INFO); -#endif - msnd_outb(HPDSPRESET_OFF, dev.io + HP_DSPR); - mdelay(1); - while (timeout-- > 0) { - if (msnd_inb(dev.io + HP_CVR) == HP_CVR_DEF) - return 0; - mdelay(1); - } - printk(KERN_ERR LOGNAME ": Cannot reset DSP\n"); - - return -EIO; -} - -static int __init probe_multisound(void) -{ -#ifndef MSND_CLASSIC - char *xv, *rev = NULL; - char *pin = "Pinnacle", *fiji = "Fiji"; - char *pinfiji = "Pinnacle/Fiji"; -#endif - - if (!request_region(dev.io, dev.numio, "probing")) { - printk(KERN_ERR LOGNAME ": I/O port conflict\n"); - return -ENODEV; - } - - if (reset_dsp() < 0) { - release_region(dev.io, dev.numio); - return -ENODEV; - } - -#ifdef MSND_CLASSIC - dev.name = "Classic/Tahiti/Monterey"; - printk(KERN_INFO LOGNAME ": %s, " -#else - switch (dev.info >> 4) { - case 0xf: xv = "<= 1.15"; break; - case 0x1: xv = "1.18/1.2"; break; - case 0x2: xv = "1.3"; break; - case 0x3: xv = "1.4"; break; - default: xv = "unknown"; break; - } - - switch (dev.info & 0x7) { - case 0x0: rev = "I"; dev.name = pin; break; - case 0x1: rev = "F"; dev.name = pin; break; - case 0x2: rev = "G"; dev.name = pin; break; - case 0x3: rev = "H"; dev.name = pin; break; - case 0x4: rev = "E"; dev.name = fiji; break; - case 0x5: rev = "C"; dev.name = fiji; break; - case 0x6: rev = "D"; dev.name = fiji; break; - case 0x7: - rev = "A-B (Fiji) or A-E (Pinnacle)"; - dev.name = pinfiji; - break; - } - printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, " -#endif /* MSND_CLASSIC */ - "I/O 0x%x-0x%x, IRQ %d, memory mapped to %p-%p\n", - dev.name, -#ifndef MSND_CLASSIC - rev, xv, -#endif - dev.io, dev.io + dev.numio - 1, - dev.irq, - dev.base, dev.base + 0x7fff); - - release_region(dev.io, dev.numio); - return 0; -} - -static int init_sma(void) -{ - static int initted; - WORD mastVolLeft, mastVolRight; - unsigned long flags; - -#ifdef MSND_CLASSIC - msnd_outb(dev.memid, dev.io + HP_MEMM); -#endif - msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS); - if (initted) { - mastVolLeft = readw(dev.SMA + SMA_wCurrMastVolLeft); - mastVolRight = readw(dev.SMA + SMA_wCurrMastVolRight); - } else - mastVolLeft = mastVolRight = 0; - memset_io(dev.base, 0, 0x8000); - - /* Critical section: bank 1 access */ - spin_lock_irqsave(&dev.lock, flags); - msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS); - memset_io(dev.base, 0, 0x8000); - msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS); - spin_unlock_irqrestore(&dev.lock, flags); - - dev.pwDSPQData = (dev.base + DSPQ_DATA_BUFF); - dev.pwMODQData = (dev.base + MODQ_DATA_BUFF); - dev.pwMIDQData = (dev.base + MIDQ_DATA_BUFF); - - /* Motorola 56k shared memory base */ - dev.SMA = dev.base + SMA_STRUCT_START; - - /* Digital audio play queue */ - dev.DAPQ = dev.base + DAPQ_OFFSET; - msnd_init_queue(dev.DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE); - - /* Digital audio record queue */ - dev.DARQ = dev.base + DARQ_OFFSET; - msnd_init_queue(dev.DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); - - /* MIDI out queue */ - dev.MODQ = dev.base + MODQ_OFFSET; - msnd_init_queue(dev.MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE); - - /* MIDI in queue */ - dev.MIDQ = dev.base + MIDQ_OFFSET; - msnd_init_queue(dev.MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE); - - /* DSP -> host message queue */ - dev.DSPQ = dev.base + DSPQ_OFFSET; - msnd_init_queue(dev.DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE); - - /* Setup some DSP values */ -#ifndef MSND_CLASSIC - writew(1, dev.SMA + SMA_wCurrPlayFormat); - writew(dev.play_sample_size, dev.SMA + SMA_wCurrPlaySampleSize); - writew(dev.play_channels, dev.SMA + SMA_wCurrPlayChannels); - writew(dev.play_sample_rate, dev.SMA + SMA_wCurrPlaySampleRate); -#endif - writew(dev.play_sample_rate, dev.SMA + SMA_wCalFreqAtoD); - writew(mastVolLeft, dev.SMA + SMA_wCurrMastVolLeft); - writew(mastVolRight, dev.SMA + SMA_wCurrMastVolRight); -#ifndef MSND_CLASSIC - writel(0x00010000, dev.SMA + SMA_dwCurrPlayPitch); - writel(0x00000001, dev.SMA + SMA_dwCurrPlayRate); -#endif - writew(0x303, dev.SMA + SMA_wCurrInputTagBits); - - initted = 1; - - return 0; -} - -static int __init calibrate_adc(WORD srate) -{ - writew(srate, dev.SMA + SMA_wCalFreqAtoD); - if (dev.calibrate_signal == 0) - writew(readw(dev.SMA + SMA_wCurrHostStatusFlags) - | 0x0001, dev.SMA + SMA_wCurrHostStatusFlags); - else - writew(readw(dev.SMA + SMA_wCurrHostStatusFlags) - & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags); - if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && - chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(HZ / 3); - return 0; - } - printk(KERN_WARNING LOGNAME ": ADC calibration failed\n"); - - return -EIO; -} - -static int upload_dsp_code(void) -{ - int ret = 0; - - msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS); -#ifndef HAVE_DSPCODEH - INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE); - if (!INITCODE) { - printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE); - return -EBUSY; - } - - PERMCODESIZE = mod_firmware_load(PERMCODEFILE, &PERMCODE); - if (!PERMCODE) { - printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE); - vfree(INITCODE); - return -EBUSY; - } -#endif - memcpy_toio(dev.base, PERMCODE, PERMCODESIZE); - if (msnd_upload_host(&dev, INITCODE, INITCODESIZE) < 0) { - printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); - ret = -ENODEV; - goto out; - } -#ifdef HAVE_DSPCODEH - printk(KERN_INFO LOGNAME ": DSP firmware uploaded (resident)\n"); -#else - printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n"); -#endif - -out: -#ifndef HAVE_DSPCODEH - vfree(INITCODE); - vfree(PERMCODE); -#endif - - return ret; -} - -#ifdef MSND_CLASSIC -static void reset_proteus(void) -{ - msnd_outb(HPPRORESET_ON, dev.io + HP_PROR); - mdelay(TIME_PRO_RESET); - msnd_outb(HPPRORESET_OFF, dev.io + HP_PROR); - mdelay(TIME_PRO_RESET_DONE); -} -#endif - -static int initialize(void) -{ - int err, timeout; - -#ifdef MSND_CLASSIC - msnd_outb(HPWAITSTATE_0, dev.io + HP_WAIT); - msnd_outb(HPBITMODE_16, dev.io + HP_BITM); - - reset_proteus(); -#endif - if ((err = init_sma()) < 0) { - printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); - return err; - } - - if ((err = reset_dsp()) < 0) - return err; - - if ((err = upload_dsp_code()) < 0) { - printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); - return err; - } - - timeout = 200; - while (readw(dev.base)) { - mdelay(1); - if (!timeout--) { - printk(KERN_DEBUG LOGNAME ": DSP reset timeout\n"); - return -EIO; - } - } - - mixer_setup(); - - return 0; -} - -static int dsp_full_reset(void) -{ - int rv; - - if (test_bit(F_RESETTING, &dev.flags) || ++dev.nresets > 10) - return 0; - - set_bit(F_RESETTING, &dev.flags); - printk(KERN_INFO LOGNAME ": DSP reset\n"); - dsp_halt(NULL); /* Unconditionally halt */ - if ((rv = initialize())) - printk(KERN_WARNING LOGNAME ": DSP reset failed\n"); - force_recsrc(dev.recsrc); - dsp_open(NULL); - clear_bit(F_RESETTING, &dev.flags); - - return rv; -} - -static int __init attach_multisound(void) -{ - int err; - - if ((err = request_irq(dev.irq, intr, 0, dev.name, &dev)) < 0) { - printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq); - return err; - } - if (request_region(dev.io, dev.numio, dev.name) == NULL) { - free_irq(dev.irq, &dev); - return -EBUSY; - } - - err = dsp_full_reset(); - if (err < 0) { - release_region(dev.io, dev.numio); - free_irq(dev.irq, &dev); - return err; - } - - if ((err = msnd_register(&dev)) < 0) { - printk(KERN_ERR LOGNAME ": Unable to register MultiSound\n"); - release_region(dev.io, dev.numio); - free_irq(dev.irq, &dev); - return err; - } - - if ((dev.dsp_minor = register_sound_dsp(&dev_fileops, -1)) < 0) { - printk(KERN_ERR LOGNAME ": Unable to register DSP operations\n"); - msnd_unregister(&dev); - release_region(dev.io, dev.numio); - free_irq(dev.irq, &dev); - return dev.dsp_minor; - } - - if ((dev.mixer_minor = register_sound_mixer(&dev_fileops, -1)) < 0) { - printk(KERN_ERR LOGNAME ": Unable to register mixer operations\n"); - unregister_sound_mixer(dev.mixer_minor); - msnd_unregister(&dev); - release_region(dev.io, dev.numio); - free_irq(dev.irq, &dev); - return dev.mixer_minor; - } - - dev.ext_midi_dev = dev.hdr_midi_dev = -1; - - disable_irq(dev.irq); - calibrate_adc(dev.play_sample_rate); -#ifndef MSND_CLASSIC - force_recsrc(SOUND_MASK_IMIX); -#endif - - return 0; -} - -static void __exit unload_multisound(void) -{ - release_region(dev.io, dev.numio); - free_irq(dev.irq, &dev); - unregister_sound_mixer(dev.mixer_minor); - unregister_sound_dsp(dev.dsp_minor); - msnd_unregister(&dev); -} - -#ifndef MSND_CLASSIC - -/* Pinnacle/Fiji Logical Device Configuration */ - -static int __init msnd_write_cfg(int cfg, int reg, int value) -{ - msnd_outb(reg, cfg); - msnd_outb(value, cfg + 1); - if (value != msnd_inb(cfg + 1)) { - printk(KERN_ERR LOGNAME ": msnd_write_cfg: I/O error\n"); - return -EIO; - } - return 0; -} - -static int __init msnd_write_cfg_io0(int cfg, int num, WORD io) -{ - if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io))) - return -EIO; - if (msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io))) - return -EIO; - return 0; -} - -static int __init msnd_write_cfg_io1(int cfg, int num, WORD io) -{ - if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io))) - return -EIO; - if (msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io))) - return -EIO; - return 0; -} - -static int __init msnd_write_cfg_irq(int cfg, int num, WORD irq) -{ - if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) - return -EIO; - if (msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) - return -EIO; - return 0; -} - -static int __init msnd_write_cfg_mem(int cfg, int num, int mem) -{ - WORD wmem; - - mem >>= 8; - mem &= 0xfff; - wmem = (WORD)mem; - if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem))) - return -EIO; - if (msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem))) - return -EIO; - if (wmem && msnd_write_cfg(cfg, IREG_MEMCONTROL, (MEMTYPE_HIADDR | MEMTYPE_16BIT))) - return -EIO; - return 0; -} - -static int __init msnd_activate_logical(int cfg, int num) -{ - if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE)) - return -EIO; - return 0; -} - -static int __init msnd_write_cfg_logical(int cfg, int num, WORD io0, WORD io1, WORD irq, int mem) -{ - if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (msnd_write_cfg_io0(cfg, num, io0)) - return -EIO; - if (msnd_write_cfg_io1(cfg, num, io1)) - return -EIO; - if (msnd_write_cfg_irq(cfg, num, irq)) - return -EIO; - if (msnd_write_cfg_mem(cfg, num, mem)) - return -EIO; - if (msnd_activate_logical(cfg, num)) - return -EIO; - return 0; -} - -typedef struct msnd_pinnacle_cfg_device { - WORD io0, io1, irq; - int mem; -} msnd_pinnacle_cfg_t[4]; - -static int __init msnd_pinnacle_cfg_devices(int cfg, int reset, msnd_pinnacle_cfg_t device) -{ - int i; - - /* Reset devices if told to */ - if (reset) { - printk(KERN_INFO LOGNAME ": Resetting all devices\n"); - for (i = 0; i < 4; ++i) - if (msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0)) - return -EIO; - } - - /* Configure specified devices */ - for (i = 0; i < 4; ++i) { - - switch (i) { - case 0: /* DSP */ - if (!(device[i].io0 && device[i].irq && device[i].mem)) - continue; - break; - case 1: /* MPU */ - if (!(device[i].io0 && device[i].irq)) - continue; - printk(KERN_INFO LOGNAME - ": Configuring MPU to I/O 0x%x IRQ %d\n", - device[i].io0, device[i].irq); - break; - case 2: /* IDE */ - if (!(device[i].io0 && device[i].io1 && device[i].irq)) - continue; - printk(KERN_INFO LOGNAME - ": Configuring IDE to I/O 0x%x, 0x%x IRQ %d\n", - device[i].io0, device[i].io1, device[i].irq); - break; - case 3: /* Joystick */ - if (!(device[i].io0)) - continue; - printk(KERN_INFO LOGNAME - ": Configuring joystick to I/O 0x%x\n", - device[i].io0); - break; - } - - /* Configure the device */ - if (msnd_write_cfg_logical(cfg, i, device[i].io0, device[i].io1, device[i].irq, device[i].mem)) - return -EIO; - } - - return 0; -} -#endif - -#ifdef MODULE -MODULE_AUTHOR ("Andrew Veliath "); -MODULE_DESCRIPTION ("Turtle Beach " LONGNAME " Linux Driver"); -MODULE_LICENSE("GPL"); - -static int io __initdata = -1; -static int irq __initdata = -1; -static int mem __initdata = -1; -static int write_ndelay __initdata = -1; - -#ifndef MSND_CLASSIC -/* Pinnacle/Fiji non-PnP Config Port */ -static int cfg __initdata = -1; - -/* Extra Peripheral Configuration */ -static int reset __initdata = 0; -static int mpu_io __initdata = 0; -static int mpu_irq __initdata = 0; -static int ide_io0 __initdata = 0; -static int ide_io1 __initdata = 0; -static int ide_irq __initdata = 0; -static int joystick_io __initdata = 0; - -/* If we have the digital daugherboard... */ -static bool digital __initdata = false; -#endif - -static int fifosize __initdata = DEFFIFOSIZE; -static int calibrate_signal __initdata = 0; - -#else /* not a module */ - -static int write_ndelay __initdata = -1; - -#ifdef MSND_CLASSIC -static int io __initdata = CONFIG_MSNDCLAS_IO; -static int irq __initdata = CONFIG_MSNDCLAS_IRQ; -static int mem __initdata = CONFIG_MSNDCLAS_MEM; -#else /* Pinnacle/Fiji */ - -static int io __initdata = CONFIG_MSNDPIN_IO; -static int irq __initdata = CONFIG_MSNDPIN_IRQ; -static int mem __initdata = CONFIG_MSNDPIN_MEM; - -/* Pinnacle/Fiji non-PnP Config Port */ -#ifdef CONFIG_MSNDPIN_NONPNP -# ifndef CONFIG_MSNDPIN_CFG -# define CONFIG_MSNDPIN_CFG 0x250 -# endif -#else -# ifdef CONFIG_MSNDPIN_CFG -# undef CONFIG_MSNDPIN_CFG -# endif -# define CONFIG_MSNDPIN_CFG -1 -#endif -static int cfg __initdata = CONFIG_MSNDPIN_CFG; -/* If not a module, we don't need to bother with reset=1 */ -static int reset; - -/* Extra Peripheral Configuration (Default: Disable) */ -#ifndef CONFIG_MSNDPIN_MPU_IO -# define CONFIG_MSNDPIN_MPU_IO 0 -#endif -static int mpu_io __initdata = CONFIG_MSNDPIN_MPU_IO; - -#ifndef CONFIG_MSNDPIN_MPU_IRQ -# define CONFIG_MSNDPIN_MPU_IRQ 0 -#endif -static int mpu_irq __initdata = CONFIG_MSNDPIN_MPU_IRQ; - -#ifndef CONFIG_MSNDPIN_IDE_IO0 -# define CONFIG_MSNDPIN_IDE_IO0 0 -#endif -static int ide_io0 __initdata = CONFIG_MSNDPIN_IDE_IO0; - -#ifndef CONFIG_MSNDPIN_IDE_IO1 -# define CONFIG_MSNDPIN_IDE_IO1 0 -#endif -static int ide_io1 __initdata = CONFIG_MSNDPIN_IDE_IO1; - -#ifndef CONFIG_MSNDPIN_IDE_IRQ -# define CONFIG_MSNDPIN_IDE_IRQ 0 -#endif -static int ide_irq __initdata = CONFIG_MSNDPIN_IDE_IRQ; - -#ifndef CONFIG_MSNDPIN_JOYSTICK_IO -# define CONFIG_MSNDPIN_JOYSTICK_IO 0 -#endif -static int joystick_io __initdata = CONFIG_MSNDPIN_JOYSTICK_IO; - -/* Have SPDIF (Digital) Daughterboard */ -#ifndef CONFIG_MSNDPIN_DIGITAL -# define CONFIG_MSNDPIN_DIGITAL 0 -#endif -static bool digital __initdata = CONFIG_MSNDPIN_DIGITAL; - -#endif /* MSND_CLASSIC */ - -#ifndef CONFIG_MSND_FIFOSIZE -# define CONFIG_MSND_FIFOSIZE DEFFIFOSIZE -#endif -static int fifosize __initdata = CONFIG_MSND_FIFOSIZE; - -#ifndef CONFIG_MSND_CALSIGNAL -# define CONFIG_MSND_CALSIGNAL 0 -#endif -static int -calibrate_signal __initdata = CONFIG_MSND_CALSIGNAL; -#endif /* MODULE */ - -module_param (io, int, 0); -module_param (irq, int, 0); -module_param (mem, int, 0); -module_param (write_ndelay, int, 0); -module_param (fifosize, int, 0); -module_param (calibrate_signal, int, 0); -#ifndef MSND_CLASSIC -module_param (digital, bool, 0); -module_param (cfg, int, 0); -module_param (reset, int, 0); -module_param (mpu_io, int, 0); -module_param (mpu_irq, int, 0); -module_param (ide_io0, int, 0); -module_param (ide_io1, int, 0); -module_param (ide_irq, int, 0); -module_param (joystick_io, int, 0); -#endif - -static int __init msnd_init(void) -{ - int err; -#ifndef MSND_CLASSIC - static msnd_pinnacle_cfg_t pinnacle_devs; -#endif /* MSND_CLASSIC */ - - printk(KERN_INFO LOGNAME ": Turtle Beach " LONGNAME " Linux Driver Version " - VERSION ", Copyright (C) 1998 Andrew Veliath\n"); - - if (io == -1 || irq == -1 || mem == -1) - printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); - -#ifdef MSND_CLASSIC - if (io == -1 || - !(io == 0x290 || - io == 0x260 || - io == 0x250 || - io == 0x240 || - io == 0x230 || - io == 0x220 || - io == 0x210 || - io == 0x3e0)) { - printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, or 0x3E0\n"); - return -EINVAL; - } -#else - if (io == -1 || - io < 0x100 || - io > 0x3e0 || - (io % 0x10) != 0) { - printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must within the range 0x100 to 0x3E0 and must be evenly divisible by 0x10\n"); - return -EINVAL; - } -#endif /* MSND_CLASSIC */ - - if (irq == -1 || - !(irq == 5 || - irq == 7 || - irq == 9 || - irq == 10 || - irq == 11 || - irq == 12)) { - printk(KERN_ERR LOGNAME ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); - return -EINVAL; - } - - if (mem == -1 || - !(mem == 0xb0000 || - mem == 0xc8000 || - mem == 0xd0000 || - mem == 0xd8000 || - mem == 0xe0000 || - mem == 0xe8000)) { - printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " - "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000\n"); - return -EINVAL; - } - -#ifdef MSND_CLASSIC - switch (irq) { - case 5: dev.irqid = HPIRQ_5; break; - case 7: dev.irqid = HPIRQ_7; break; - case 9: dev.irqid = HPIRQ_9; break; - case 10: dev.irqid = HPIRQ_10; break; - case 11: dev.irqid = HPIRQ_11; break; - case 12: dev.irqid = HPIRQ_12; break; - } - - switch (mem) { - case 0xb0000: dev.memid = HPMEM_B000; break; - case 0xc8000: dev.memid = HPMEM_C800; break; - case 0xd0000: dev.memid = HPMEM_D000; break; - case 0xd8000: dev.memid = HPMEM_D800; break; - case 0xe0000: dev.memid = HPMEM_E000; break; - case 0xe8000: dev.memid = HPMEM_E800; break; - } -#else - if (cfg == -1) { - printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); - } else if (cfg != 0x250 && cfg != 0x260 && cfg != 0x270) { - printk(KERN_INFO LOGNAME ": Config port must be 0x250, 0x260 or 0x270 (or unspecified for PnP mode)\n"); - return -EINVAL; - } else { - printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%x\n", cfg); - - /* DSP */ - pinnacle_devs[0].io0 = io; - pinnacle_devs[0].irq = irq; - pinnacle_devs[0].mem = mem; - - /* The following are Pinnacle specific */ - - /* MPU */ - pinnacle_devs[1].io0 = mpu_io; - pinnacle_devs[1].irq = mpu_irq; - - /* IDE */ - pinnacle_devs[2].io0 = ide_io0; - pinnacle_devs[2].io1 = ide_io1; - pinnacle_devs[2].irq = ide_irq; - - /* Joystick */ - pinnacle_devs[3].io0 = joystick_io; - - if (!request_region(cfg, 2, "Pinnacle/Fiji Config")) { - printk(KERN_ERR LOGNAME ": Config port 0x%x conflict\n", cfg); - return -EIO; - } - - if (msnd_pinnacle_cfg_devices(cfg, reset, pinnacle_devs)) { - printk(KERN_ERR LOGNAME ": Device configuration error\n"); - release_region(cfg, 2); - return -EIO; - } - release_region(cfg, 2); - } -#endif /* MSND_CLASSIC */ - - if (fifosize < 16) - fifosize = 16; - - if (fifosize > 1024) - fifosize = 1024; - - set_default_audio_parameters(); -#ifdef MSND_CLASSIC - dev.type = msndClassic; -#else - dev.type = msndPinnacle; -#endif - dev.io = io; - dev.numio = DSP_NUMIO; - dev.irq = irq; - dev.base = ioremap(mem, 0x8000); - dev.fifosize = fifosize * 1024; - dev.calibrate_signal = calibrate_signal ? 1 : 0; - dev.recsrc = 0; - dev.dspq_data_buff = DSPQ_DATA_BUFF; - dev.dspq_buff_size = DSPQ_BUFF_SIZE; - if (write_ndelay == -1) - write_ndelay = CONFIG_MSND_WRITE_NDELAY; - if (write_ndelay) - clear_bit(F_DISABLE_WRITE_NDELAY, &dev.flags); - else - set_bit(F_DISABLE_WRITE_NDELAY, &dev.flags); -#ifndef MSND_CLASSIC - if (digital) - set_bit(F_HAVEDIGITAL, &dev.flags); -#endif - init_waitqueue_head(&dev.writeblock); - init_waitqueue_head(&dev.readblock); - init_waitqueue_head(&dev.writeflush); - msnd_fifo_init(&dev.DAPF); - msnd_fifo_init(&dev.DARF); - spin_lock_init(&dev.lock); - printk(KERN_INFO LOGNAME ": %u byte audio FIFOs (x2)\n", dev.fifosize); - if ((err = msnd_fifo_alloc(&dev.DAPF, dev.fifosize)) < 0) { - printk(KERN_ERR LOGNAME ": Couldn't allocate write FIFO\n"); - return err; - } - - if ((err = msnd_fifo_alloc(&dev.DARF, dev.fifosize)) < 0) { - printk(KERN_ERR LOGNAME ": Couldn't allocate read FIFO\n"); - msnd_fifo_free(&dev.DAPF); - return err; - } - - if ((err = probe_multisound()) < 0) { - printk(KERN_ERR LOGNAME ": Probe failed\n"); - msnd_fifo_free(&dev.DAPF); - msnd_fifo_free(&dev.DARF); - return err; - } - - if ((err = attach_multisound()) < 0) { - printk(KERN_ERR LOGNAME ": Attach failed\n"); - msnd_fifo_free(&dev.DAPF); - msnd_fifo_free(&dev.DARF); - return err; - } - - return 0; -} - -static void __exit msdn_cleanup(void) -{ - unload_multisound(); - msnd_fifo_free(&dev.DAPF); - msnd_fifo_free(&dev.DARF); -} - -module_init(msnd_init); -module_exit(msdn_cleanup); diff --git a/ANDROID_3.4.5/sound/oss/msnd_pinnacle.h b/ANDROID_3.4.5/sound/oss/msnd_pinnacle.h deleted file mode 100644 index c18d66cb..00000000 --- a/ANDROID_3.4.5/sound/oss/msnd_pinnacle.h +++ /dev/null @@ -1,246 +0,0 @@ -/********************************************************************* - * - * msnd_pinnacle.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_PINNACLE_H -#define __MSND_PINNACLE_H - - -#define DSP_NUMIO 0x08 - -#define IREG_LOGDEVICE 0x07 -#define IREG_ACTIVATE 0x30 -#define LD_ACTIVATE 0x01 -#define LD_DISACTIVATE 0x00 -#define IREG_EECONTROL 0x3F -#define IREG_MEMBASEHI 0x40 -#define IREG_MEMBASELO 0x41 -#define IREG_MEMCONTROL 0x42 -#define IREG_MEMRANGEHI 0x43 -#define IREG_MEMRANGELO 0x44 -#define MEMTYPE_8BIT 0x00 -#define MEMTYPE_16BIT 0x02 -#define MEMTYPE_RANGE 0x00 -#define MEMTYPE_HIADDR 0x01 -#define IREG_IO0_BASEHI 0x60 -#define IREG_IO0_BASELO 0x61 -#define IREG_IO1_BASEHI 0x62 -#define IREG_IO1_BASELO 0x63 -#define IREG_IRQ_NUMBER 0x70 -#define IREG_IRQ_TYPE 0x71 -#define IRQTYPE_HIGH 0x02 -#define IRQTYPE_LOW 0x00 -#define IRQTYPE_LEVEL 0x01 -#define IRQTYPE_EDGE 0x00 - -#define HP_DSPR 0x04 -#define HP_BLKS 0x04 - -#define HPDSPRESET_OFF 2 -#define HPDSPRESET_ON 0 - -#define HPBLKSEL_0 2 -#define HPBLKSEL_1 3 - -#define HIMT_DAT_OFF 0x03 - -#define HIDSP_PLAY_UNDER 0x00 -#define HIDSP_INT_PLAY_UNDER 0x01 -#define HIDSP_SSI_TX_UNDER 0x02 -#define HIDSP_RECQ_OVERFLOW 0x08 -#define HIDSP_INT_RECORD_OVER 0x09 -#define HIDSP_SSI_RX_OVERFLOW 0x0a - -#define HIDSP_MIDI_IN_OVER 0x10 - -#define HIDSP_MIDI_FRAME_ERR 0x11 -#define HIDSP_MIDI_PARITY_ERR 0x12 -#define HIDSP_MIDI_OVERRUN_ERR 0x13 - -#define HIDSP_INPUT_CLIPPING 0x20 -#define HIDSP_MIX_CLIPPING 0x30 -#define HIDSP_DAT_IN_OFF 0x21 - -#define HDEXAR_SET_ANA_IN 0 -#define HDEXAR_CLEAR_PEAKS 1 -#define HDEXAR_IN_SET_POTS 2 -#define HDEXAR_AUX_SET_POTS 3 -#define HDEXAR_CAL_A_TO_D 4 -#define HDEXAR_RD_EXT_DSP_BITS 5 - -#define HDEXAR_SET_SYNTH_IN 4 -#define HDEXAR_READ_DAT_IN 5 -#define HDEXAR_MIC_SET_POTS 6 -#define HDEXAR_SET_DAT_IN 7 - -#define HDEXAR_SET_SYNTH_48 8 -#define HDEXAR_SET_SYNTH_44 9 - -#define TIME_PRO_RESET_DONE 0x028A -#define TIME_PRO_SYSEX 0x001E -#define TIME_PRO_RESET 0x0032 - -#define AGND 0x01 -#define SIGNAL 0x02 - -#define EXT_DSP_BIT_DCAL 0x0001 -#define EXT_DSP_BIT_MIDI_CON 0x0002 - -#define BUFFSIZE 0x8000 -#define HOSTQ_SIZE 0x40 - -#define SRAM_CNTL_START 0x7F00 -#define SMA_STRUCT_START 0x7F40 - -#define DAP_BUFF_SIZE 0x2400 -#define DAR_BUFF_SIZE 0x2000 - -#define DAPQ_STRUCT_SIZE 0x10 -#define DARQ_STRUCT_SIZE 0x10 -#define DAPQ_BUFF_SIZE (3 * 0x10) -#define DARQ_BUFF_SIZE (3 * 0x10) -#define MODQ_BUFF_SIZE 0x400 -#define MIDQ_BUFF_SIZE 0x800 -#define DSPQ_BUFF_SIZE 0x5A0 - -#define DAPQ_DATA_BUFF 0x6C00 -#define DARQ_DATA_BUFF 0x6C30 -#define MODQ_DATA_BUFF 0x6C60 -#define MIDQ_DATA_BUFF 0x7060 -#define DSPQ_DATA_BUFF 0x7860 - -#define DAPQ_OFFSET SRAM_CNTL_START -#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) -#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) -#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) -#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) - -#define MOP_WAVEHDR 0 -#define MOP_EXTOUT 1 -#define MOP_HWINIT 0xfe -#define MOP_NONE 0xff -#define MOP_MAX 1 - -#define MIP_EXTIN 0 -#define MIP_WAVEHDR 1 -#define MIP_HWINIT 0xfe -#define MIP_MAX 1 - -/* Pinnacle/Fiji SMA Common Data */ -#define SMA_wCurrPlayBytes 0x0000 -#define SMA_wCurrRecordBytes 0x0002 -#define SMA_wCurrPlayVolLeft 0x0004 -#define SMA_wCurrPlayVolRight 0x0006 -#define SMA_wCurrInVolLeft 0x0008 -#define SMA_wCurrInVolRight 0x000a -#define SMA_wCurrMHdrVolLeft 0x000c -#define SMA_wCurrMHdrVolRight 0x000e -#define SMA_dwCurrPlayPitch 0x0010 -#define SMA_dwCurrPlayRate 0x0014 -#define SMA_wCurrMIDIIOPatch 0x0018 -#define SMA_wCurrPlayFormat 0x001a -#define SMA_wCurrPlaySampleSize 0x001c -#define SMA_wCurrPlayChannels 0x001e -#define SMA_wCurrPlaySampleRate 0x0020 -#define SMA_wCurrRecordFormat 0x0022 -#define SMA_wCurrRecordSampleSize 0x0024 -#define SMA_wCurrRecordChannels 0x0026 -#define SMA_wCurrRecordSampleRate 0x0028 -#define SMA_wCurrDSPStatusFlags 0x002a -#define SMA_wCurrHostStatusFlags 0x002c -#define SMA_wCurrInputTagBits 0x002e -#define SMA_wCurrLeftPeak 0x0030 -#define SMA_wCurrRightPeak 0x0032 -#define SMA_bMicPotPosLeft 0x0034 -#define SMA_bMicPotPosRight 0x0035 -#define SMA_bMicPotMaxLeft 0x0036 -#define SMA_bMicPotMaxRight 0x0037 -#define SMA_bInPotPosLeft 0x0038 -#define SMA_bInPotPosRight 0x0039 -#define SMA_bAuxPotPosLeft 0x003a -#define SMA_bAuxPotPosRight 0x003b -#define SMA_bInPotMaxLeft 0x003c -#define SMA_bInPotMaxRight 0x003d -#define SMA_bAuxPotMaxLeft 0x003e -#define SMA_bAuxPotMaxRight 0x003f -#define SMA_bInPotMaxMethod 0x0040 -#define SMA_bAuxPotMaxMethod 0x0041 -#define SMA_wCurrMastVolLeft 0x0042 -#define SMA_wCurrMastVolRight 0x0044 -#define SMA_wCalFreqAtoD 0x0046 -#define SMA_wCurrAuxVolLeft 0x0048 -#define SMA_wCurrAuxVolRight 0x004a -#define SMA_wCurrPlay1VolLeft 0x004c -#define SMA_wCurrPlay1VolRight 0x004e -#define SMA_wCurrPlay2VolLeft 0x0050 -#define SMA_wCurrPlay2VolRight 0x0052 -#define SMA_wCurrPlay3VolLeft 0x0054 -#define SMA_wCurrPlay3VolRight 0x0056 -#define SMA_wCurrPlay4VolLeft 0x0058 -#define SMA_wCurrPlay4VolRight 0x005a -#define SMA_wCurrPlay1PeakLeft 0x005c -#define SMA_wCurrPlay1PeakRight 0x005e -#define SMA_wCurrPlay2PeakLeft 0x0060 -#define SMA_wCurrPlay2PeakRight 0x0062 -#define SMA_wCurrPlay3PeakLeft 0x0064 -#define SMA_wCurrPlay3PeakRight 0x0066 -#define SMA_wCurrPlay4PeakLeft 0x0068 -#define SMA_wCurrPlay4PeakRight 0x006a -#define SMA_wCurrPlayPeakLeft 0x006c -#define SMA_wCurrPlayPeakRight 0x006e -#define SMA_wCurrDATSR 0x0070 -#define SMA_wCurrDATRXCHNL 0x0072 -#define SMA_wCurrDATTXCHNL 0x0074 -#define SMA_wCurrDATRXRate 0x0076 -#define SMA_dwDSPPlayCount 0x0078 -#define SMA__size 0x007c - -#ifdef HAVE_DSPCODEH -# include "pndsperm.c" -# include "pndspini.c" -# define PERMCODE pndsperm -# define INITCODE pndspini -# define PERMCODESIZE sizeof(pndsperm) -# define INITCODESIZE sizeof(pndspini) -#else -# ifndef CONFIG_MSNDPIN_INIT_FILE -# define CONFIG_MSNDPIN_INIT_FILE \ - "/etc/sound/pndspini.bin" -# endif -# ifndef CONFIG_MSNDPIN_PERM_FILE -# define CONFIG_MSNDPIN_PERM_FILE \ - "/etc/sound/pndsperm.bin" -# endif -# define PERMCODEFILE CONFIG_MSNDPIN_PERM_FILE -# define INITCODEFILE CONFIG_MSNDPIN_INIT_FILE -# define PERMCODE dspini -# define INITCODE permini -# define PERMCODESIZE sizeof_dspini -# define INITCODESIZE sizeof_permini -#endif -#define LONGNAME "MultiSound (Pinnacle/Fiji)" - -#endif /* __MSND_PINNACLE_H */ diff --git a/ANDROID_3.4.5/sound/oss/opl3.c b/ANDROID_3.4.5/sound/oss/opl3.c deleted file mode 100644 index 407cd677..00000000 --- a/ANDROID_3.4.5/sound/oss/opl3.c +++ /dev/null @@ -1,1258 +0,0 @@ -/* - * sound/oss/opl3.c - * - * A low level driver for Yamaha YM3812 and OPL-3 -chips - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Changes - * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) - * Alan Cox modularisation, fixed sound_mem allocs. - * Christoph Hellwig Adapted to module_init/module_exit - * Arnaldo C. de Melo get rid of check_region, use request_region for - * OPL4, release it on exit, some cleanups. - * - * Status - * Believed to work. Badly needs rewriting a bit to support multiple - * OPL3 devices. - */ - -#include -#include -#include -#include - -/* - * Major improvements to the FM handling 30AUG92 by Rob Hooft, - * hooft@chem.ruu.nl - */ - -#include "sound_config.h" - -#include "opl3_hw.h" - -#define MAX_VOICE 18 -#define OFFS_4OP 11 - -struct voice_info -{ - unsigned char keyon_byte; - long bender; - long bender_range; - unsigned long orig_freq; - unsigned long current_freq; - int volume; - int mode; - int panning; /* 0xffff means not set */ -}; - -typedef struct opl_devinfo -{ - int base; - int left_io, right_io; - int nr_voice; - int lv_map[MAX_VOICE]; - - struct voice_info voc[MAX_VOICE]; - struct voice_alloc_info *v_alloc; - struct channel_info *chn_info; - - struct sbi_instrument i_map[SBFM_MAXINSTR]; - struct sbi_instrument *act_i[MAX_VOICE]; - - struct synth_info fm_info; - - int busy; - int model; - unsigned char cmask; - - int is_opl4; -} opl_devinfo; - -static struct opl_devinfo *devc = NULL; - -static int detected_model; - -static int store_instr(int instr_no, struct sbi_instrument *instr); -static void freq_to_fnum(int freq, int *block, int *fnum); -static void opl3_command(int io_addr, unsigned int addr, unsigned int val); -static int opl3_kill_note(int dev, int voice, int note, int velocity); - -static void enter_4op_mode(void) -{ - int i; - static int v4op[MAX_VOICE] = { - 0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17 - }; - - devc->cmask = 0x3f; /* Connect all possible 4 OP voice operators */ - opl3_command(devc->right_io, CONNECTION_SELECT_REGISTER, 0x3f); - - for (i = 0; i < 3; i++) - pv_map[i].voice_mode = 4; - for (i = 3; i < 6; i++) - pv_map[i].voice_mode = 0; - - for (i = 9; i < 12; i++) - pv_map[i].voice_mode = 4; - for (i = 12; i < 15; i++) - pv_map[i].voice_mode = 0; - - for (i = 0; i < 12; i++) - devc->lv_map[i] = v4op[i]; - devc->v_alloc->max_voice = devc->nr_voice = 12; -} - -static int opl3_ioctl(int dev, unsigned int cmd, void __user * arg) -{ - struct sbi_instrument ins; - - switch (cmd) { - case SNDCTL_FM_LOAD_INSTR: - printk(KERN_WARNING "Warning: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n"); - if (copy_from_user(&ins, arg, sizeof(ins))) - return -EFAULT; - if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR) { - printk(KERN_WARNING "FM Error: Invalid instrument number %d\n", ins.channel); - return -EINVAL; - } - return store_instr(ins.channel, &ins); - - case SNDCTL_SYNTH_INFO: - devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice; - if (copy_to_user(arg, &devc->fm_info, sizeof(devc->fm_info))) - return -EFAULT; - return 0; - - case SNDCTL_SYNTH_MEMAVL: - return 0x7fffffff; - - case SNDCTL_FM_4OP_ENABLE: - if (devc->model == 2) - enter_4op_mode(); - return 0; - - default: - return -EINVAL; - } -} - -static int opl3_detect(int ioaddr) -{ - /* - * This function returns 1 if the FM chip is present at the given I/O port - * The detection algorithm plays with the timer built in the FM chip and - * looks for a change in the status register. - * - * Note! The timers of the FM chip are not connected to AdLib (and compatible) - * boards. - * - * Note2! The chip is initialized if detected. - */ - - unsigned char stat1, signature; - int i; - - if (devc != NULL) - { - printk(KERN_ERR "opl3: Only one OPL3 supported.\n"); - return 0; - } - - devc = kzalloc(sizeof(*devc), GFP_KERNEL); - - if (devc == NULL) - { - printk(KERN_ERR "opl3: Can't allocate memory for the device control " - "structure \n "); - return 0; - } - - strcpy(devc->fm_info.name, "OPL2"); - - if (!request_region(ioaddr, 4, devc->fm_info.name)) { - printk(KERN_WARNING "opl3: I/O port 0x%x already in use\n", ioaddr); - goto cleanup_devc; - } - - devc->base = ioaddr; - - /* Reset timers 1 and 2 */ - opl3_command(ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK); - - /* Reset the IRQ of the FM chip */ - opl3_command(ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET); - - signature = stat1 = inb(ioaddr); /* Status register */ - - if (signature != 0x00 && signature != 0x06 && signature != 0x02 && - signature != 0x0f) - { - MDB(printk(KERN_INFO "OPL3 not detected %x\n", signature)); - goto cleanup_region; - } - - if (signature == 0x06) /* OPL2 */ - { - detected_model = 2; - } - else if (signature == 0x00 || signature == 0x0f) /* OPL3 or OPL4 */ - { - unsigned char tmp; - - detected_model = 3; - - /* - * Detect availability of OPL4 (_experimental_). Works probably - * only after a cold boot. In addition the OPL4 port - * of the chip may not be connected to the PC bus at all. - */ - - opl3_command(ioaddr + 2, OPL3_MODE_REGISTER, 0x00); - opl3_command(ioaddr + 2, OPL3_MODE_REGISTER, OPL3_ENABLE | OPL4_ENABLE); - - if ((tmp = inb(ioaddr)) == 0x02) /* Have a OPL4 */ - { - detected_model = 4; - } - - if (request_region(ioaddr - 8, 2, "OPL4")) /* OPL4 port was free */ - { - int tmp; - - outb((0x02), ioaddr - 8); /* Select OPL4 ID register */ - udelay(10); - tmp = inb(ioaddr - 7); /* Read it */ - udelay(10); - - if (tmp == 0x20) /* OPL4 should return 0x20 here */ - { - detected_model = 4; - outb((0xF8), ioaddr - 8); /* Select OPL4 FM mixer control */ - udelay(10); - outb((0x1B), ioaddr - 7); /* Write value */ - udelay(10); - } - else - { /* release OPL4 port */ - release_region(ioaddr - 8, 2); - detected_model = 3; - } - } - opl3_command(ioaddr + 2, OPL3_MODE_REGISTER, 0); - } - for (i = 0; i < 9; i++) - opl3_command(ioaddr, KEYON_BLOCK + i, 0); /* - * Note off - */ - - opl3_command(ioaddr, TEST_REGISTER, ENABLE_WAVE_SELECT); - opl3_command(ioaddr, PERCOSSION_REGISTER, 0x00); /* - * Melodic mode. - */ - return 1; -cleanup_region: - release_region(ioaddr, 4); -cleanup_devc: - kfree(devc); - devc = NULL; - return 0; -} - -static int opl3_kill_note (int devno, int voice, int note, int velocity) -{ - struct physical_voice_info *map; - - if (voice < 0 || voice >= devc->nr_voice) - return 0; - - devc->v_alloc->map[voice] = 0; - - map = &pv_map[devc->lv_map[voice]]; - DEB(printk("Kill note %d\n", voice)); - - if (map->voice_mode == 0) - return 0; - - opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num, devc->voc[voice].keyon_byte & ~0x20); - devc->voc[voice].keyon_byte = 0; - devc->voc[voice].bender = 0; - devc->voc[voice].volume = 64; - devc->voc[voice].panning = 0xffff; /* Not set */ - devc->voc[voice].bender_range = 200; - devc->voc[voice].orig_freq = 0; - devc->voc[voice].current_freq = 0; - devc->voc[voice].mode = 0; - return 0; -} - -#define HIHAT 0 -#define CYMBAL 1 -#define TOMTOM 2 -#define SNARE 3 -#define BDRUM 4 -#define UNDEFINED TOMTOM -#define DEFAULT TOMTOM - -static int store_instr(int instr_no, struct sbi_instrument *instr) -{ - if (instr->key != FM_PATCH && (instr->key != OPL3_PATCH || devc->model != 2)) - printk(KERN_WARNING "FM warning: Invalid patch format field (key) 0x%x\n", instr->key); - memcpy((char *) &(devc->i_map[instr_no]), (char *) instr, sizeof(*instr)); - return 0; -} - -static int opl3_set_instr (int dev, int voice, int instr_no) -{ - if (voice < 0 || voice >= devc->nr_voice) - return 0; - if (instr_no < 0 || instr_no >= SBFM_MAXINSTR) - instr_no = 0; /* Acoustic piano (usually) */ - - devc->act_i[voice] = &devc->i_map[instr_no]; - return 0; -} - -/* - * The next table looks magical, but it certainly is not. Its values have - * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception - * for i=0. This log-table converts a linear volume-scaling (0..127) to a - * logarithmic scaling as present in the FM-synthesizer chips. so : Volume - * 64 = 0 db = relative volume 0 and: Volume 32 = -6 db = relative - * volume -8 it was implemented as a table because it is only 128 bytes and - * it saves a lot of log() calculations. (RH) - */ - -static char fm_volume_table[128] = -{ - -64, -48, -40, -35, -32, -29, -27, -26, - -24, -23, -21, -20, -19, -18, -18, -17, - -16, -15, -15, -14, -13, -13, -12, -12, - -11, -11, -10, -10, -10, -9, -9, -8, - -8, -8, -7, -7, -7, -6, -6, -6, - -5, -5, -5, -5, -4, -4, -4, -4, - -3, -3, -3, -3, -2, -2, -2, -2, - -2, -1, -1, -1, -1, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 4, - 4, 4, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 8, 8 -}; - -static void calc_vol(unsigned char *regbyte, int volume, int main_vol) -{ - int level = (~*regbyte & 0x3f); - - if (main_vol > 127) - main_vol = 127; - volume = (volume * main_vol) / 127; - - if (level) - level += fm_volume_table[volume]; - - if (level > 0x3f) - level = 0x3f; - if (level < 0) - level = 0; - - *regbyte = (*regbyte & 0xc0) | (~level & 0x3f); -} - -static void set_voice_volume(int voice, int volume, int main_vol) -{ - unsigned char vol1, vol2, vol3, vol4; - struct sbi_instrument *instr; - struct physical_voice_info *map; - - if (voice < 0 || voice >= devc->nr_voice) - return; - - map = &pv_map[devc->lv_map[voice]]; - instr = devc->act_i[voice]; - - if (!instr) - instr = &devc->i_map[0]; - - if (instr->channel < 0) - return; - - if (devc->voc[voice].mode == 0) - return; - - if (devc->voc[voice].mode == 2) - { - vol1 = instr->operators[2]; - vol2 = instr->operators[3]; - if ((instr->operators[10] & 0x01)) - { - calc_vol(&vol1, volume, main_vol); - calc_vol(&vol2, volume, main_vol); - } - else - { - calc_vol(&vol2, volume, main_vol); - } - opl3_command(map->ioaddr, KSL_LEVEL + map->op[0], vol1); - opl3_command(map->ioaddr, KSL_LEVEL + map->op[1], vol2); - } - else - { /* - * 4 OP voice - */ - int connection; - - vol1 = instr->operators[2]; - vol2 = instr->operators[3]; - vol3 = instr->operators[OFFS_4OP + 2]; - vol4 = instr->operators[OFFS_4OP + 3]; - - /* - * The connection method for 4 OP devc->voc is defined by the rightmost - * bits at the offsets 10 and 10+OFFS_4OP - */ - - connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01); - - switch (connection) - { - case 0: - calc_vol(&vol4, volume, main_vol); - break; - - case 1: - calc_vol(&vol2, volume, main_vol); - calc_vol(&vol4, volume, main_vol); - break; - - case 2: - calc_vol(&vol1, volume, main_vol); - calc_vol(&vol4, volume, main_vol); - break; - - case 3: - calc_vol(&vol1, volume, main_vol); - calc_vol(&vol3, volume, main_vol); - calc_vol(&vol4, volume, main_vol); - break; - - default: - ; - } - opl3_command(map->ioaddr, KSL_LEVEL + map->op[0], vol1); - opl3_command(map->ioaddr, KSL_LEVEL + map->op[1], vol2); - opl3_command(map->ioaddr, KSL_LEVEL + map->op[2], vol3); - opl3_command(map->ioaddr, KSL_LEVEL + map->op[3], vol4); - } -} - -static int opl3_start_note (int dev, int voice, int note, int volume) -{ - unsigned char data, fpc; - int block, fnum, freq, voice_mode, pan; - struct sbi_instrument *instr; - struct physical_voice_info *map; - - if (voice < 0 || voice >= devc->nr_voice) - return 0; - - map = &pv_map[devc->lv_map[voice]]; - pan = devc->voc[voice].panning; - - if (map->voice_mode == 0) - return 0; - - if (note == 255) /* - * Just change the volume - */ - { - set_voice_volume(voice, volume, devc->voc[voice].volume); - return 0; - } - - /* - * Kill previous note before playing - */ - - opl3_command(map->ioaddr, KSL_LEVEL + map->op[1], 0xff); /* - * Carrier - * volume to - * min - */ - opl3_command(map->ioaddr, KSL_LEVEL + map->op[0], 0xff); /* - * Modulator - * volume to - */ - - if (map->voice_mode == 4) - { - opl3_command(map->ioaddr, KSL_LEVEL + map->op[2], 0xff); - opl3_command(map->ioaddr, KSL_LEVEL + map->op[3], 0xff); - } - - opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num, 0x00); /* - * Note - * off - */ - - instr = devc->act_i[voice]; - - if (!instr) - instr = &devc->i_map[0]; - - if (instr->channel < 0) - { - printk(KERN_WARNING "opl3: Initializing voice %d with undefined instrument\n", voice); - return 0; - } - - if (map->voice_mode == 2 && instr->key == OPL3_PATCH) - return 0; /* - * Cannot play - */ - - voice_mode = map->voice_mode; - - if (voice_mode == 4) - { - int voice_shift; - - voice_shift = (map->ioaddr == devc->left_io) ? 0 : 3; - voice_shift += map->voice_num; - - if (instr->key != OPL3_PATCH) /* - * Just 2 OP patch - */ - { - voice_mode = 2; - devc->cmask &= ~(1 << voice_shift); - } - else - { - devc->cmask |= (1 << voice_shift); - } - - opl3_command(devc->right_io, CONNECTION_SELECT_REGISTER, devc->cmask); - } - - /* - * Set Sound Characteristics - */ - - opl3_command(map->ioaddr, AM_VIB + map->op[0], instr->operators[0]); - opl3_command(map->ioaddr, AM_VIB + map->op[1], instr->operators[1]); - - /* - * Set Attack/Decay - */ - - opl3_command(map->ioaddr, ATTACK_DECAY + map->op[0], instr->operators[4]); - opl3_command(map->ioaddr, ATTACK_DECAY + map->op[1], instr->operators[5]); - - /* - * Set Sustain/Release - */ - - opl3_command(map->ioaddr, SUSTAIN_RELEASE + map->op[0], instr->operators[6]); - opl3_command(map->ioaddr, SUSTAIN_RELEASE + map->op[1], instr->operators[7]); - - /* - * Set Wave Select - */ - - opl3_command(map->ioaddr, WAVE_SELECT + map->op[0], instr->operators[8]); - opl3_command(map->ioaddr, WAVE_SELECT + map->op[1], instr->operators[9]); - - /* - * Set Feedback/Connection - */ - - fpc = instr->operators[10]; - - if (pan != 0xffff) - { - fpc &= ~STEREO_BITS; - if (pan < -64) - fpc |= VOICE_TO_LEFT; - else - if (pan > 64) - fpc |= VOICE_TO_RIGHT; - else - fpc |= (VOICE_TO_LEFT | VOICE_TO_RIGHT); - } - - if (!(fpc & 0x30)) - fpc |= 0x30; /* - * Ensure that at least one chn is enabled - */ - opl3_command(map->ioaddr, FEEDBACK_CONNECTION + map->voice_num, fpc); - - /* - * If the voice is a 4 OP one, initialize the operators 3 and 4 also - */ - - if (voice_mode == 4) - { - /* - * Set Sound Characteristics - */ - - opl3_command(map->ioaddr, AM_VIB + map->op[2], instr->operators[OFFS_4OP + 0]); - opl3_command(map->ioaddr, AM_VIB + map->op[3], instr->operators[OFFS_4OP + 1]); - - /* - * Set Attack/Decay - */ - - opl3_command(map->ioaddr, ATTACK_DECAY + map->op[2], instr->operators[OFFS_4OP + 4]); - opl3_command(map->ioaddr, ATTACK_DECAY + map->op[3], instr->operators[OFFS_4OP + 5]); - - /* - * Set Sustain/Release - */ - - opl3_command(map->ioaddr, SUSTAIN_RELEASE + map->op[2], instr->operators[OFFS_4OP + 6]); - opl3_command(map->ioaddr, SUSTAIN_RELEASE + map->op[3], instr->operators[OFFS_4OP + 7]); - - /* - * Set Wave Select - */ - - opl3_command(map->ioaddr, WAVE_SELECT + map->op[2], instr->operators[OFFS_4OP + 8]); - opl3_command(map->ioaddr, WAVE_SELECT + map->op[3], instr->operators[OFFS_4OP + 9]); - - /* - * Set Feedback/Connection - */ - - fpc = instr->operators[OFFS_4OP + 10]; - if (!(fpc & 0x30)) - fpc |= 0x30; /* - * Ensure that at least one chn is enabled - */ - opl3_command(map->ioaddr, FEEDBACK_CONNECTION + map->voice_num + 3, fpc); - } - - devc->voc[voice].mode = voice_mode; - set_voice_volume(voice, volume, devc->voc[voice].volume); - - freq = devc->voc[voice].orig_freq = note_to_freq(note) / 1000; - - /* - * Since the pitch bender may have been set before playing the note, we - * have to calculate the bending now. - */ - - freq = compute_finetune(devc->voc[voice].orig_freq, devc->voc[voice].bender, devc->voc[voice].bender_range, 0); - devc->voc[voice].current_freq = freq; - - freq_to_fnum(freq, &block, &fnum); - - /* - * Play note - */ - - data = fnum & 0xff; /* - * Least significant bits of fnumber - */ - opl3_command(map->ioaddr, FNUM_LOW + map->voice_num, data); - - data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3); - devc->voc[voice].keyon_byte = data; - opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num, data); - if (voice_mode == 4) - opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num + 3, data); - - return 0; -} - -static void freq_to_fnum (int freq, int *block, int *fnum) -{ - int f, octave; - - /* - * Converts the note frequency to block and fnum values for the FM chip - */ - /* - * First try to compute the block -value (octave) where the note belongs - */ - - f = freq; - - octave = 5; - - if (f == 0) - octave = 0; - else if (f < 261) - { - while (f < 261) - { - octave--; - f <<= 1; - } - } - else if (f > 493) - { - while (f > 493) - { - octave++; - f >>= 1; - } - } - - if (octave > 7) - octave = 7; - - *fnum = freq * (1 << (20 - octave)) / 49716; - *block = octave; -} - -static void opl3_command (int io_addr, unsigned int addr, unsigned int val) -{ - int i; - - /* - * The original 2-OP synth requires a quite long delay after writing to a - * register. The OPL-3 survives with just two INBs - */ - - outb(((unsigned char) (addr & 0xff)), io_addr); - - if (devc->model != 2) - udelay(10); - else - for (i = 0; i < 2; i++) - inb(io_addr); - - outb(((unsigned char) (val & 0xff)), io_addr + 1); - - if (devc->model != 2) - udelay(30); - else - for (i = 0; i < 2; i++) - inb(io_addr); -} - -static void opl3_reset(int devno) -{ - int i; - - for (i = 0; i < 18; i++) - devc->lv_map[i] = i; - - for (i = 0; i < devc->nr_voice; i++) - { - opl3_command(pv_map[devc->lv_map[i]].ioaddr, - KSL_LEVEL + pv_map[devc->lv_map[i]].op[0], 0xff); - - opl3_command(pv_map[devc->lv_map[i]].ioaddr, - KSL_LEVEL + pv_map[devc->lv_map[i]].op[1], 0xff); - - if (pv_map[devc->lv_map[i]].voice_mode == 4) - { - opl3_command(pv_map[devc->lv_map[i]].ioaddr, - KSL_LEVEL + pv_map[devc->lv_map[i]].op[2], 0xff); - - opl3_command(pv_map[devc->lv_map[i]].ioaddr, - KSL_LEVEL + pv_map[devc->lv_map[i]].op[3], 0xff); - } - - opl3_kill_note(devno, i, 0, 64); - } - - if (devc->model == 2) - { - devc->v_alloc->max_voice = devc->nr_voice = 18; - - for (i = 0; i < 18; i++) - pv_map[i].voice_mode = 2; - - } -} - -static int opl3_open(int dev, int mode) -{ - int i; - - if (devc->busy) - return -EBUSY; - devc->busy = 1; - - devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9; - devc->v_alloc->timestamp = 0; - - for (i = 0; i < 18; i++) - { - devc->v_alloc->map[i] = 0; - devc->v_alloc->alloc_times[i] = 0; - } - - devc->cmask = 0x00; /* - * Just 2 OP mode - */ - if (devc->model == 2) - opl3_command(devc->right_io, CONNECTION_SELECT_REGISTER, devc->cmask); - return 0; -} - -static void opl3_close(int dev) -{ - devc->busy = 0; - devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9; - - devc->fm_info.nr_drums = 0; - devc->fm_info.perc_mode = 0; - - opl3_reset(dev); -} - -static void opl3_hw_control(int dev, unsigned char *event) -{ -} - -static int opl3_load_patch(int dev, int format, const char __user *addr, - int count, int pmgr_flag) -{ - struct sbi_instrument ins; - - if (count = SBFM_MAXINSTR) - { - printk(KERN_WARNING "FM Error: Invalid instrument number %d\n", ins.channel); - return -EINVAL; - } - ins.key = format; - - return store_instr(ins.channel, &ins); -} - -static void opl3_panning(int dev, int voice, int value) -{ - - if (voice < 0 || voice >= devc->nr_voice) - return; - - devc->voc[voice].panning = value; -} - -static void opl3_volume_method(int dev, int mode) -{ -} - -#define SET_VIBRATO(cell) { \ - tmp = instr->operators[(cell-1)+(((cell-1)/2)*OFFS_4OP)]; \ - if (pressure > 110) \ - tmp |= 0x40; /* Vibrato on */ \ - opl3_command (map->ioaddr, AM_VIB + map->op[cell-1], tmp);} - -static void opl3_aftertouch(int dev, int voice, int pressure) -{ - int tmp; - struct sbi_instrument *instr; - struct physical_voice_info *map; - - if (voice < 0 || voice >= devc->nr_voice) - return; - - map = &pv_map[devc->lv_map[voice]]; - - DEB(printk("Aftertouch %d\n", voice)); - - if (map->voice_mode == 0) - return; - - /* - * Adjust the amount of vibrato depending the pressure - */ - - instr = devc->act_i[voice]; - - if (!instr) - instr = &devc->i_map[0]; - - if (devc->voc[voice].mode == 4) - { - int connection = ((instr->operators[10] & 0x01) << 1) | (instr->operators[10 + OFFS_4OP] & 0x01); - - switch (connection) - { - case 0: - SET_VIBRATO(4); - break; - - case 1: - SET_VIBRATO(2); - SET_VIBRATO(4); - break; - - case 2: - SET_VIBRATO(1); - SET_VIBRATO(4); - break; - - case 3: - SET_VIBRATO(1); - SET_VIBRATO(3); - SET_VIBRATO(4); - break; - - } - /* - * Not implemented yet - */ - } - else - { - SET_VIBRATO(1); - - if ((instr->operators[10] & 0x01)) /* - * Additive synthesis - */ - SET_VIBRATO(2); - } -} - -#undef SET_VIBRATO - -static void bend_pitch(int dev, int voice, int value) -{ - unsigned char data; - int block, fnum, freq; - struct physical_voice_info *map; - - map = &pv_map[devc->lv_map[voice]]; - - if (map->voice_mode == 0) - return; - - devc->voc[voice].bender = value; - if (!value) - return; - if (!(devc->voc[voice].keyon_byte & 0x20)) - return; /* - * Not keyed on - */ - - freq = compute_finetune(devc->voc[voice].orig_freq, devc->voc[voice].bender, devc->voc[voice].bender_range, 0); - devc->voc[voice].current_freq = freq; - - freq_to_fnum(freq, &block, &fnum); - - data = fnum & 0xff; /* - * Least significant bits of fnumber - */ - opl3_command(map->ioaddr, FNUM_LOW + map->voice_num, data); - - data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3); - devc->voc[voice].keyon_byte = data; - opl3_command(map->ioaddr, KEYON_BLOCK + map->voice_num, data); -} - -static void opl3_controller (int dev, int voice, int ctrl_num, int value) -{ - if (voice < 0 || voice >= devc->nr_voice) - return; - - switch (ctrl_num) - { - case CTRL_PITCH_BENDER: - bend_pitch(dev, voice, value); - break; - - case CTRL_PITCH_BENDER_RANGE: - devc->voc[voice].bender_range = value; - break; - - case CTL_MAIN_VOLUME: - devc->voc[voice].volume = value / 128; - break; - - case CTL_PAN: - devc->voc[voice].panning = (value * 2) - 128; - break; - } -} - -static void opl3_bender(int dev, int voice, int value) -{ - if (voice < 0 || voice >= devc->nr_voice) - return; - - bend_pitch(dev, voice, value - 8192); -} - -static int opl3_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc) -{ - int i, p, best, first, avail, best_time = 0x7fffffff; - struct sbi_instrument *instr; - int is4op; - int instr_no; - - if (chn < 0 || chn > 15) - instr_no = 0; - else - instr_no = devc->chn_info[chn].pgm_num; - - instr = &devc->i_map[instr_no]; - if (instr->channel < 0 || /* Instrument not loaded */ - devc->nr_voice != 12) /* Not in 4 OP mode */ - is4op = 0; - else if (devc->nr_voice == 12) /* 4 OP mode */ - is4op = (instr->key == OPL3_PATCH); - else - is4op = 0; - - if (is4op) - { - first = p = 0; - avail = 6; - } - else - { - if (devc->nr_voice == 12) /* 4 OP mode. Use the '2 OP only' operators first */ - first = p = 6; - else - first = p = 0; - avail = devc->nr_voice; - } - - /* - * Now try to find a free voice - */ - best = first; - - for (i = 0; i < avail; i++) - { - if (alloc->map[p] == 0) - { - return p; - } - if (alloc->alloc_times[p] < best_time) /* Find oldest playing note */ - { - best_time = alloc->alloc_times[p]; - best = p; - } - p = (p + 1) % avail; - } - - /* - * Insert some kind of priority mechanism here. - */ - - if (best < 0) - best = 0; - if (best > devc->nr_voice) - best -= devc->nr_voice; - - return best; /* All devc->voc in use. Select the first one. */ -} - -static void opl3_setup_voice(int dev, int voice, int chn) -{ - struct channel_info *info; - - if (voice < 0 || voice >= devc->nr_voice) - return; - - if (chn < 0 || chn > 15) - return; - - info = &synth_devs[dev]->chn_info[chn]; - - opl3_set_instr(dev, voice, info->pgm_num); - - devc->voc[voice].bender = 0; - devc->voc[voice].bender_range = info->bender_range; - devc->voc[voice].volume = info->controllers[CTL_MAIN_VOLUME]; - devc->voc[voice].panning = (info->controllers[CTL_PAN] * 2) - 128; -} - -static struct synth_operations opl3_operations = -{ - .owner = THIS_MODULE, - .id = "OPL", - .info = NULL, - .midi_dev = 0, - .synth_type = SYNTH_TYPE_FM, - .synth_subtype = FM_TYPE_ADLIB, - .open = opl3_open, - .close = opl3_close, - .ioctl = opl3_ioctl, - .kill_note = opl3_kill_note, - .start_note = opl3_start_note, - .set_instr = opl3_set_instr, - .reset = opl3_reset, - .hw_control = opl3_hw_control, - .load_patch = opl3_load_patch, - .aftertouch = opl3_aftertouch, - .controller = opl3_controller, - .panning = opl3_panning, - .volume_method = opl3_volume_method, - .bender = opl3_bender, - .alloc_voice = opl3_alloc_voice, - .setup_voice = opl3_setup_voice -}; - -static int opl3_init(int ioaddr, struct module *owner) -{ - int i; - int me; - - if (devc == NULL) - { - printk(KERN_ERR "opl3: Device control structure not initialized.\n"); - return -1; - } - - if ((me = sound_alloc_synthdev()) == -1) - { - printk(KERN_WARNING "opl3: Too many synthesizers\n"); - return -1; - } - - devc->nr_voice = 9; - - devc->fm_info.device = 0; - devc->fm_info.synth_type = SYNTH_TYPE_FM; - devc->fm_info.synth_subtype = FM_TYPE_ADLIB; - devc->fm_info.perc_mode = 0; - devc->fm_info.nr_voices = 9; - devc->fm_info.nr_drums = 0; - devc->fm_info.instr_bank_size = SBFM_MAXINSTR; - devc->fm_info.capabilities = 0; - devc->left_io = ioaddr; - devc->right_io = ioaddr + 2; - - if (detected_model <= 2) - devc->model = 1; - else - { - devc->model = 2; - if (detected_model == 4) - devc->is_opl4 = 1; - } - - opl3_operations.info = &devc->fm_info; - - synth_devs[me] = &opl3_operations; - - if (owner) - synth_devs[me]->owner = owner; - - sequencer_init(); - devc->v_alloc = &opl3_operations.alloc; - devc->chn_info = &opl3_operations.chn_info[0]; - - if (devc->model == 2) - { - if (devc->is_opl4) - strcpy(devc->fm_info.name, "Yamaha OPL4/OPL3 FM"); - else - strcpy(devc->fm_info.name, "Yamaha OPL3"); - - devc->v_alloc->max_voice = devc->nr_voice = 18; - devc->fm_info.nr_drums = 0; - devc->fm_info.synth_subtype = FM_TYPE_OPL3; - devc->fm_info.capabilities |= SYNTH_CAP_OPL3; - - for (i = 0; i < 18; i++) - { - if (pv_map[i].ioaddr == USE_LEFT) - pv_map[i].ioaddr = devc->left_io; - else - pv_map[i].ioaddr = devc->right_io; - } - opl3_command(devc->right_io, OPL3_MODE_REGISTER, OPL3_ENABLE); - opl3_command(devc->right_io, CONNECTION_SELECT_REGISTER, 0x00); - } - else - { - strcpy(devc->fm_info.name, "Yamaha OPL2"); - devc->v_alloc->max_voice = devc->nr_voice = 9; - devc->fm_info.nr_drums = 0; - - for (i = 0; i < 18; i++) - pv_map[i].ioaddr = devc->left_io; - }; - conf_printf2(devc->fm_info.name, ioaddr, 0, -1, -1); - - for (i = 0; i < SBFM_MAXINSTR; i++) - devc->i_map[i].channel = -1; - - return me; -} - -static int me; - -static int io = -1; - -module_param(io, int, 0); - -static int __init init_opl3 (void) -{ - printk(KERN_INFO "YM3812 and OPL-3 driver Copyright (C) by Hannu Savolainen, Rob Hooft 1993-1996\n"); - - if (io != -1) /* User loading pure OPL3 module */ - { - if (!opl3_detect(io)) - { - return -ENODEV; - } - - me = opl3_init(io, THIS_MODULE); - } - - return 0; -} - -static void __exit cleanup_opl3(void) -{ - if (devc && io != -1) - { - if (devc->base) { - release_region(devc->base,4); - if (devc->is_opl4) - release_region(devc->base - 8, 2); - } - kfree(devc); - devc = NULL; - sound_unload_synthdev(me); - } -} - -module_init(init_opl3); -module_exit(cleanup_opl3); - -#ifndef MODULE -static int __init setup_opl3(char *str) -{ - /* io */ - int ints[2]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - - return 1; -} - -__setup("opl3=", setup_opl3); -#endif -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/opl3_hw.h b/ANDROID_3.4.5/sound/oss/opl3_hw.h deleted file mode 100644 index 8b11c893..00000000 --- a/ANDROID_3.4.5/sound/oss/opl3_hw.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * opl3_hw.h - Definitions of the OPL-3 registers - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * The OPL-3 mode is switched on by writing 0x01, to the offset 5 - * of the right side. - * - * Another special register at the right side is at offset 4. It contains - * a bit mask defining which voices are used as 4 OP voices. - * - * The percussive mode is implemented in the left side only. - * - * With the above exceptions the both sides can be operated independently. - * - * A 4 OP voice can be created by setting the corresponding - * bit at offset 4 of the right side. - * - * For example setting the rightmost bit (0x01) changes the - * first voice on the right side to the 4 OP mode. The fourth - * voice is made inaccessible. - * - * If a voice is set to the 2 OP mode, it works like 2 OP modes - * of the original YM3812 (AdLib). In addition the voice can - * be connected the left, right or both stereo channels. It can - * even be left unconnected. This works with 4 OP voices also. - * - * The stereo connection bits are located in the FEEDBACK_CONNECTION - * register of the voice (0xC0-0xC8). In 4 OP voices these bits are - * in the second half of the voice. - */ - -/* - * Register numbers for the global registers - */ - -#define TEST_REGISTER 0x01 -#define ENABLE_WAVE_SELECT 0x20 - -#define TIMER1_REGISTER 0x02 -#define TIMER2_REGISTER 0x03 -#define TIMER_CONTROL_REGISTER 0x04 /* Left side */ -#define IRQ_RESET 0x80 -#define TIMER1_MASK 0x40 -#define TIMER2_MASK 0x20 -#define TIMER1_START 0x01 -#define TIMER2_START 0x02 - -#define CONNECTION_SELECT_REGISTER 0x04 /* Right side */ -#define RIGHT_4OP_0 0x01 -#define RIGHT_4OP_1 0x02 -#define RIGHT_4OP_2 0x04 -#define LEFT_4OP_0 0x08 -#define LEFT_4OP_1 0x10 -#define LEFT_4OP_2 0x20 - -#define OPL3_MODE_REGISTER 0x05 /* Right side */ -#define OPL3_ENABLE 0x01 -#define OPL4_ENABLE 0x02 - -#define KBD_SPLIT_REGISTER 0x08 /* Left side */ -#define COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */ -#define KEYBOARD_SPLIT 0x40 - -#define PERCOSSION_REGISTER 0xbd /* Left side only */ -#define TREMOLO_DEPTH 0x80 -#define VIBRATO_DEPTH 0x40 -#define PERCOSSION_ENABLE 0x20 -#define BASSDRUM_ON 0x10 -#define SNAREDRUM_ON 0x08 -#define TOMTOM_ON 0x04 -#define CYMBAL_ON 0x02 -#define HIHAT_ON 0x01 - -/* - * Offsets to the register banks for operators. To get the - * register number just add the operator offset to the bank offset - * - * AM/VIB/EG/KSR/Multiple (0x20 to 0x35) - */ -#define AM_VIB 0x20 -#define TREMOLO_ON 0x80 -#define VIBRATO_ON 0x40 -#define SUSTAIN_ON 0x20 -#define KSR 0x10 /* Key scaling rate */ -#define MULTIPLE_MASK 0x0f /* Frequency multiplier */ - - /* - * KSL/Total level (0x40 to 0x55) - */ -#define KSL_LEVEL 0x40 -#define KSL_MASK 0xc0 /* Envelope scaling bits */ -#define TOTAL_LEVEL_MASK 0x3f /* Strength (volume) of OP */ - -/* - * Attack / Decay rate (0x60 to 0x75) - */ -#define ATTACK_DECAY 0x60 -#define ATTACK_MASK 0xf0 -#define DECAY_MASK 0x0f - -/* - * Sustain level / Release rate (0x80 to 0x95) - */ -#define SUSTAIN_RELEASE 0x80 -#define SUSTAIN_MASK 0xf0 -#define RELEASE_MASK 0x0f - -/* - * Wave select (0xE0 to 0xF5) - */ -#define WAVE_SELECT 0xe0 - -/* - * Offsets to the register banks for voices. Just add to the - * voice number to get the register number. - * - * F-Number low bits (0xA0 to 0xA8). - */ -#define FNUM_LOW 0xa0 - -/* - * F-number high bits / Key on / Block (octave) (0xB0 to 0xB8) - */ -#define KEYON_BLOCK 0xb0 -#define KEYON_BIT 0x20 -#define BLOCKNUM_MASK 0x1c -#define FNUM_HIGH_MASK 0x03 - -/* - * Feedback / Connection (0xc0 to 0xc8) - * - * These registers have two new bits when the OPL-3 mode - * is selected. These bits controls connecting the voice - * to the stereo channels. For 4 OP voices this bit is - * defined in the second half of the voice (add 3 to the - * register offset). - * - * For 4 OP voices the connection bit is used in the - * both halves (gives 4 ways to connect the operators). - */ -#define FEEDBACK_CONNECTION 0xc0 -#define FEEDBACK_MASK 0x0e /* Valid just for 1st OP of a voice */ -#define CONNECTION_BIT 0x01 -/* - * In the 4 OP mode there is four possible configurations how the - * operators can be connected together (in 2 OP modes there is just - * AM or FM). The 4 OP connection mode is defined by the rightmost - * bit of the FEEDBACK_CONNECTION (0xC0-0xC8) on the both halves. - * - * First half Second half Mode - * - * +---+ - * v | - * 0 0 >+-1-+--2--3--4--> - * - * - * - * +---+ - * | | - * 0 1 >+-1-+--2-+ - * |-> - * >--3----4-+ - * - * +---+ - * | | - * 1 0 >+-1-+-----+ - * |-> - * >--2--3--4-+ - * - * +---+ - * | | - * 1 1 >+-1-+--+ - * | - * >--2--3-+-> - * | - * >--4----+ - */ -#define STEREO_BITS 0x30 /* OPL-3 only */ -#define VOICE_TO_LEFT 0x10 -#define VOICE_TO_RIGHT 0x20 - -/* - * Definition table for the physical voices - */ - -struct physical_voice_info { - unsigned char voice_num; - unsigned char voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */ - unsigned short ioaddr; /* I/O port (left or right side) */ - unsigned char op[4]; /* Operator offsets */ - }; - -/* - * There is 18 possible 2 OP voices - * (9 in the left and 9 in the right). - * The first OP is the modulator and 2nd is the carrier. - * - * The first three voices in the both sides may be connected - * with another voice to a 4 OP voice. For example voice 0 - * can be connected with voice 3. The operators of voice 3 are - * used as operators 3 and 4 of the new 4 OP voice. - * In this case the 2 OP voice number 0 is the 'first half' and - * voice 3 is the second. - */ - -#define USE_LEFT 0 -#define USE_RIGHT 1 - -static struct physical_voice_info pv_map[18] = -{ -/* No Mode Side OP1 OP2 OP3 OP4 */ -/* --------------------------------------------------- */ - { 0, 2, USE_LEFT, {0x00, 0x03, 0x08, 0x0b}}, - { 1, 2, USE_LEFT, {0x01, 0x04, 0x09, 0x0c}}, - { 2, 2, USE_LEFT, {0x02, 0x05, 0x0a, 0x0d}}, - - { 3, 2, USE_LEFT, {0x08, 0x0b, 0x00, 0x00}}, - { 4, 2, USE_LEFT, {0x09, 0x0c, 0x00, 0x00}}, - { 5, 2, USE_LEFT, {0x0a, 0x0d, 0x00, 0x00}}, - - { 6, 2, USE_LEFT, {0x10, 0x13, 0x00, 0x00}}, /* Used by percussive voices */ - { 7, 2, USE_LEFT, {0x11, 0x14, 0x00, 0x00}}, /* if the percussive mode */ - { 8, 2, USE_LEFT, {0x12, 0x15, 0x00, 0x00}}, /* is selected */ - - { 0, 2, USE_RIGHT, {0x00, 0x03, 0x08, 0x0b}}, - { 1, 2, USE_RIGHT, {0x01, 0x04, 0x09, 0x0c}}, - { 2, 2, USE_RIGHT, {0x02, 0x05, 0x0a, 0x0d}}, - - { 3, 2, USE_RIGHT, {0x08, 0x0b, 0x00, 0x00}}, - { 4, 2, USE_RIGHT, {0x09, 0x0c, 0x00, 0x00}}, - { 5, 2, USE_RIGHT, {0x0a, 0x0d, 0x00, 0x00}}, - - { 6, 2, USE_RIGHT, {0x10, 0x13, 0x00, 0x00}}, - { 7, 2, USE_RIGHT, {0x11, 0x14, 0x00, 0x00}}, - { 8, 2, USE_RIGHT, {0x12, 0x15, 0x00, 0x00}} -}; -/* - * DMA buffer calls - */ diff --git a/ANDROID_3.4.5/sound/oss/os.h b/ANDROID_3.4.5/sound/oss/os.h deleted file mode 100644 index 75ad0cd0..00000000 --- a/ANDROID_3.4.5/sound/oss/os.h +++ /dev/null @@ -1,45 +0,0 @@ -#define ALLOW_SELECT -#undef NO_INLINE_ASM -#define SHORT_BANNERS -#define MANUAL_PNP -#undef DO_TIMINGS - -#include - -#ifdef __KERNEL__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include - -#define FALSE 0 -#define TRUE 1 - -extern int sound_alloc_dma(int chn, char *deviceID); -extern int sound_open_dma(int chn, char *deviceID); -extern void sound_free_dma(int chn); -extern void sound_close_dma(int chn); - -extern void reprogram_timer(void); - -#define USE_AUTOINIT_DMA - -extern void *sound_mem_blocks[1024]; -extern int sound_nblocks; - -#undef PSEUDO_DMA_AUTOINIT -#define ALLOW_BUFFER_MAPPING - -extern const struct file_operations oss_sound_fops; diff --git a/ANDROID_3.4.5/sound/oss/pas2.h b/ANDROID_3.4.5/sound/oss/pas2.h deleted file mode 100644 index fa12c55f..00000000 --- a/ANDROID_3.4.5/sound/oss/pas2.h +++ /dev/null @@ -1,17 +0,0 @@ - -/* From pas_card.c */ -int pas_set_intr(int mask); -int pas_remove_intr(int mask); -unsigned char pas_read(int ioaddr); -void pas_write(unsigned char data, int ioaddr); - -/* From pas_audio.c */ -void pas_pcm_interrupt(unsigned char status, int cause); -void pas_pcm_init(struct address_info *hw_config); - -/* From pas_mixer.c */ -int pas_init_mixer(void); - -/* From pas_midi.c */ -void pas_midi_init(void); -void pas_midi_interrupt(void); diff --git a/ANDROID_3.4.5/sound/oss/pas2_card.c b/ANDROID_3.4.5/sound/oss/pas2_card.c deleted file mode 100644 index dabf8a87..00000000 --- a/ANDROID_3.4.5/sound/oss/pas2_card.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * sound/oss/pas2_card.c - * - * Detection routine for the Pro Audio Spectrum cards. - */ - -#include -#include -#include -#include -#include "sound_config.h" - -#include "pas2.h" -#include "sb.h" - -static unsigned char dma_bits[] = { - 4, 1, 2, 3, 0, 5, 6, 7 -}; - -static unsigned char irq_bits[] = { - 0, 0, 1, 2, 3, 4, 5, 6, 0, 1, 7, 8, 9, 0, 10, 11 -}; - -static unsigned char sb_irq_bits[] = { - 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, - 0x00, 0x08, 0x28, 0x30, 0x38, 0, 0 -}; - -static unsigned char sb_dma_bits[] = { - 0x00, 0x40, 0x80, 0xC0, 0, 0, 0, 0 -}; - -/* - * The Address Translation code is used to convert I/O register addresses to - * be relative to the given base -register - */ - -int pas_translate_code = 0; -static int pas_intr_mask; -static int pas_irq; -static int pas_sb_base; -DEFINE_SPINLOCK(pas_lock); -#ifndef CONFIG_PAS_JOYSTICK -static bool joystick; -#else -static bool joystick = 1; -#endif -#ifdef SYMPHONY_PAS -static bool symphony = 1; -#else -static bool symphony; -#endif -#ifdef BROKEN_BUS_CLOCK -static bool broken_bus_clock = 1; -#else -static bool broken_bus_clock; -#endif - -static struct address_info cfg; -static struct address_info cfg2; - -char pas_model = 0; -static char *pas_model_names[] = { - "", - "Pro AudioSpectrum+", - "CDPC", - "Pro AudioSpectrum 16", - "Pro AudioSpectrum 16D" -}; - -/* - * pas_read() and pas_write() are equivalents of inb and outb - * These routines perform the I/O address translation required - * to support other than the default base address - */ - -extern void mix_write(unsigned char data, int ioaddr); - -unsigned char pas_read(int ioaddr) -{ - return inb(ioaddr + pas_translate_code); -} - -void pas_write(unsigned char data, int ioaddr) -{ - outb((data), ioaddr + pas_translate_code); -} - -/******************* Begin of the Interrupt Handler ********************/ - -static irqreturn_t pasintr(int irq, void *dev_id) -{ - int status; - - status = pas_read(0x0B89); - pas_write(status, 0x0B89); /* Clear interrupt */ - - if (status & 0x08) - { - pas_pcm_interrupt(status, 1); - status &= ~0x08; - } - if (status & 0x10) - { - pas_midi_interrupt(); - status &= ~0x10; - } - return IRQ_HANDLED; -} - -int pas_set_intr(int mask) -{ - if (!mask) - return 0; - - pas_intr_mask |= mask; - - pas_write(pas_intr_mask, 0x0B8B); - return 0; -} - -int pas_remove_intr(int mask) -{ - if (!mask) - return 0; - - pas_intr_mask &= ~mask; - pas_write(pas_intr_mask, 0x0B8B); - - return 0; -} - -/******************* End of the Interrupt handler **********************/ - -/******************* Begin of the Initialization Code ******************/ - -static int __init config_pas_hw(struct address_info *hw_config) -{ - char ok = 1; - unsigned int_ptrs; /* scsi/sound interrupt pointers */ - - pas_irq = hw_config->irq; - - pas_write(0x00, 0x0B8B); - pas_write(0x36, 0x138B); - pas_write(0x36, 0x1388); - pas_write(0, 0x1388); - pas_write(0x74, 0x138B); - pas_write(0x74, 0x1389); - pas_write(0, 0x1389); - - pas_write(0x80 | 0x40 | 0x20 | 1, 0x0B8A); - pas_write(0x80 | 0x20 | 0x10 | 0x08 | 0x01, 0xF8A); - pas_write(0x01 | 0x02 | 0x04 | 0x10 /* - * | - * 0x80 - */ , 0xB88); - - pas_write(0x80 | (joystick ? 0x40 : 0), 0xF388); - - if (pas_irq < 0 || pas_irq > 15) - { - printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq); - hw_config->irq=-1; - ok = 0; - } - else - { - int_ptrs = pas_read(0xF38A); - int_ptrs = (int_ptrs & 0xf0) | irq_bits[pas_irq]; - pas_write(int_ptrs, 0xF38A); - if (!irq_bits[pas_irq]) - { - printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq); - hw_config->irq=-1; - ok = 0; - } - else - { - if (request_irq(pas_irq, pasintr, 0, "PAS16",hw_config) < 0) { - printk(KERN_ERR "PAS16: Cannot allocate IRQ %d\n",pas_irq); - hw_config->irq=-1; - ok = 0; - } - } - } - - if (hw_config->dma < 0 || hw_config->dma > 7) - { - printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma); - hw_config->dma=-1; - ok = 0; - } - else - { - pas_write(dma_bits[hw_config->dma], 0xF389); - if (!dma_bits[hw_config->dma]) - { - printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma); - hw_config->dma=-1; - ok = 0; - } - else - { - if (sound_alloc_dma(hw_config->dma, "PAS16")) - { - printk(KERN_ERR "pas2_card.c: Can't allocate DMA channel\n"); - hw_config->dma=-1; - ok = 0; - } - } - } - - /* - * This fixes the timing problems of the PAS due to the Symphony chipset - * as per Media Vision. Only define this if your PAS doesn't work correctly. - */ - - if(symphony) - { - outb((0x05), 0xa8); - outb((0x60), 0xa9); - } - - if(broken_bus_clock) - pas_write(0x01 | 0x10 | 0x20 | 0x04, 0x8388); - else - /* - * pas_write(0x01, 0x8388); - */ - pas_write(0x01 | 0x10 | 0x20, 0x8388); - - pas_write(0x18, 0x838A); /* ??? */ - pas_write(0x20 | 0x01, 0x0B8A); /* Mute off, filter = 17.897 kHz */ - pas_write(8, 0xBF8A); - - mix_write(0x80 | 5, 0x078B); - mix_write(5, 0x078B); - - { - struct address_info *sb_config; - - sb_config = &cfg2; - if (sb_config->io_base) - { - unsigned char irq_dma; - - /* - * Turn on Sound Blaster compatibility - * bit 1 = SB emulation - * bit 0 = MPU401 emulation (CDPC only :-( ) - */ - - pas_write(0x02, 0xF788); - - /* - * "Emulation address" - */ - - pas_write((sb_config->io_base >> 4) & 0x0f, 0xF789); - pas_sb_base = sb_config->io_base; - - if (!sb_dma_bits[sb_config->dma]) - printk(KERN_ERR "PAS16 Warning: Invalid SB DMA %d\n\n", sb_config->dma); - - if (!sb_irq_bits[sb_config->irq]) - printk(KERN_ERR "PAS16 Warning: Invalid SB IRQ %d\n\n", sb_config->irq); - - irq_dma = sb_dma_bits[sb_config->dma] | - sb_irq_bits[sb_config->irq]; - - pas_write(irq_dma, 0xFB8A); - } - else - pas_write(0x00, 0xF788); - } - - if (!ok) - printk(KERN_WARNING "PAS16: Driver not enabled\n"); - - return ok; -} - -static int __init detect_pas_hw(struct address_info *hw_config) -{ - unsigned char board_id, foo; - - /* - * WARNING: Setting an option like W:1 or so that disables warm boot reset - * of the card will screw up this detect code something fierce. Adding code - * to handle this means possibly interfering with other cards on the bus if - * you have something on base port 0x388. SO be forewarned. - */ - - outb((0xBC), 0x9A01); /* Activate first board */ - outb((hw_config->io_base >> 2), 0x9A01); /* Set base address */ - pas_translate_code = hw_config->io_base - 0x388; - pas_write(1, 0xBF88); /* Select one wait states */ - - board_id = pas_read(0x0B8B); - - if (board_id == 0xff) - return 0; - - /* - * We probably have a PAS-series board, now check for a PAS16-series board - * by trying to change the board revision bits. PAS16-series hardware won't - * let you do this - the bits are read-only. - */ - - foo = board_id ^ 0xe0; - - pas_write(foo, 0x0B8B); - foo = pas_read(0x0B8B); - pas_write(board_id, 0x0B8B); - - if (board_id != foo) - return 0; - - pas_model = pas_read(0xFF88); - - return pas_model; -} - -static void __init attach_pas_card(struct address_info *hw_config) -{ - pas_irq = hw_config->irq; - - if (detect_pas_hw(hw_config)) - { - - if ((pas_model = pas_read(0xFF88))) - { - char temp[100]; - - sprintf(temp, - "%s rev %d", pas_model_names[(int) pas_model], - pas_read(0x2789)); - conf_printf(temp, hw_config); - } - if (config_pas_hw(hw_config)) - { - pas_pcm_init(hw_config); - pas_midi_init(); - pas_init_mixer(); - } - } -} - -static inline int __init probe_pas(struct address_info *hw_config) -{ - return detect_pas_hw(hw_config); -} - -static void __exit unload_pas(struct address_info *hw_config) -{ - extern int pas_audiodev; - extern int pas2_mididev; - - if (hw_config->dma>0) - sound_free_dma(hw_config->dma); - if (hw_config->irq>0) - free_irq(hw_config->irq, hw_config); - - if(pas_audiodev!=-1) - sound_unload_mixerdev(audio_devs[pas_audiodev]->mixer_dev); - if(pas2_mididev!=-1) - sound_unload_mididev(pas2_mididev); - if(pas_audiodev!=-1) - sound_unload_audiodev(pas_audiodev); -} - -static int __initdata io = -1; -static int __initdata irq = -1; -static int __initdata dma = -1; -static int __initdata dma16 = -1; /* Set this for modules that need it */ - -static int __initdata sb_io = 0; -static int __initdata sb_irq = -1; -static int __initdata sb_dma = -1; -static int __initdata sb_dma16 = -1; - -module_param(io, int, 0); -module_param(irq, int, 0); -module_param(dma, int, 0); -module_param(dma16, int, 0); - -module_param(sb_io, int, 0); -module_param(sb_irq, int, 0); -module_param(sb_dma, int, 0); -module_param(sb_dma16, int, 0); - -module_param(joystick, bool, 0); -module_param(symphony, bool, 0); -module_param(broken_bus_clock, bool, 0); - -MODULE_LICENSE("GPL"); - -static int __init init_pas2(void) -{ - printk(KERN_INFO "Pro Audio Spectrum driver Copyright (C) by Hannu Savolainen 1993-1996\n"); - - cfg.io_base = io; - cfg.irq = irq; - cfg.dma = dma; - cfg.dma2 = dma16; - - cfg2.io_base = sb_io; - cfg2.irq = sb_irq; - cfg2.dma = sb_dma; - cfg2.dma2 = sb_dma16; - - if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) { - printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n"); - return -EINVAL; - } - - if (!probe_pas(&cfg)) - return -ENODEV; - attach_pas_card(&cfg); - - return 0; -} - -static void __exit cleanup_pas2(void) -{ - unload_pas(&cfg); -} - -module_init(init_pas2); -module_exit(cleanup_pas2); - -#ifndef MODULE -static int __init setup_pas2(char *str) -{ - /* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, sb_dma2 */ - int ints[9]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - irq = ints[2]; - dma = ints[3]; - dma16 = ints[4]; - - sb_io = ints[5]; - sb_irq = ints[6]; - sb_dma = ints[7]; - sb_dma16 = ints[8]; - - return 1; -} - -__setup("pas2=", setup_pas2); -#endif diff --git a/ANDROID_3.4.5/sound/oss/pas2_midi.c b/ANDROID_3.4.5/sound/oss/pas2_midi.c deleted file mode 100644 index 1122d10a..00000000 --- a/ANDROID_3.4.5/sound/oss/pas2_midi.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * sound/oss/pas2_midi.c - * - * The low level driver for the PAS Midi Interface. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * Bartlomiej Zolnierkiewicz : Added __init to pas_init_mixer() - */ - -#include -#include -#include "sound_config.h" - -#include "pas2.h" - -extern spinlock_t pas_lock; - -static int midi_busy, input_opened; -static int my_dev; - -int pas2_mididev=-1; - -static unsigned char tmp_queue[256]; -static volatile int qlen; -static volatile unsigned char qhead, qtail; - -static void (*midi_input_intr) (int dev, unsigned char data); - -static int pas_midi_open(int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - int err; - unsigned long flags; - unsigned char ctrl; - - - if (midi_busy) - return -EBUSY; - - /* - * Reset input and output FIFO pointers - */ - pas_write(0x20 | 0x40, - 0x178b); - - spin_lock_irqsave(&pas_lock, flags); - - if ((err = pas_set_intr(0x10)) < 0) - { - spin_unlock_irqrestore(&pas_lock, flags); - return err; - } - /* - * Enable input available and output FIFO empty interrupts - */ - - ctrl = 0; - input_opened = 0; - midi_input_intr = input; - - if (mode == OPEN_READ || mode == OPEN_READWRITE) - { - ctrl |= 0x04; /* Enable input */ - input_opened = 1; - } - if (mode == OPEN_WRITE || mode == OPEN_READWRITE) - { - ctrl |= 0x08 | 0x10; /* Enable output */ - } - pas_write(ctrl, 0x178b); - - /* - * Acknowledge any pending interrupts - */ - - pas_write(0xff, 0x1B88); - - spin_unlock_irqrestore(&pas_lock, flags); - - midi_busy = 1; - qlen = qhead = qtail = 0; - return 0; -} - -static void pas_midi_close(int dev) -{ - - /* - * Reset FIFO pointers, disable intrs - */ - pas_write(0x20 | 0x40, 0x178b); - - pas_remove_intr(0x10); - midi_busy = 0; -} - -static int dump_to_midi(unsigned char midi_byte) -{ - int fifo_space, x; - - fifo_space = ((x = pas_read(0x1B89)) >> 4) & 0x0f; - - /* - * The MIDI FIFO space register and it's documentation is nonunderstandable. - * There seem to be no way to differentiate between buffer full and buffer - * empty situations. For this reason we don't never write the buffer - * completely full. In this way we can assume that 0 (or is it 15) - * means that the buffer is empty. - */ - - if (fifo_space < 2 && fifo_space != 0) /* Full (almost) */ - return 0; /* Ask upper layers to retry after some time */ - - pas_write(midi_byte, 0x178A); - - return 1; -} - -static int pas_midi_out(int dev, unsigned char midi_byte) -{ - - unsigned long flags; - - /* - * Drain the local queue first - */ - - spin_lock_irqsave(&pas_lock, flags); - - while (qlen && dump_to_midi(tmp_queue[qhead])) - { - qlen--; - qhead++; - } - - spin_unlock_irqrestore(&pas_lock, flags); - - /* - * Output the byte if the local queue is empty. - */ - - if (!qlen) - if (dump_to_midi(midi_byte)) - return 1; - - /* - * Put to the local queue - */ - - if (qlen >= 256) - return 0; /* Local queue full */ - - spin_lock_irqsave(&pas_lock, flags); - - tmp_queue[qtail] = midi_byte; - qlen++; - qtail++; - - spin_unlock_irqrestore(&pas_lock, flags); - - return 1; -} - -static int pas_midi_start_read(int dev) -{ - return 0; -} - -static int pas_midi_end_read(int dev) -{ - return 0; -} - -static void pas_midi_kick(int dev) -{ -} - -static int pas_buffer_status(int dev) -{ - return qlen; -} - -#define MIDI_SYNTH_NAME "Pro Audio Spectrum Midi" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include "midi_synth.h" - -static struct midi_operations pas_midi_operations = -{ - .owner = THIS_MODULE, - .info = {"Pro Audio Spectrum", 0, 0, SNDCARD_PAS}, - .converter = &std_midi_synth, - .in_info = {0}, - .open = pas_midi_open, - .close = pas_midi_close, - .outputc = pas_midi_out, - .start_read = pas_midi_start_read, - .end_read = pas_midi_end_read, - .kick = pas_midi_kick, - .buffer_status = pas_buffer_status, -}; - -void __init pas_midi_init(void) -{ - int dev = sound_alloc_mididev(); - - if (dev == -1) - { - printk(KERN_WARNING "pas_midi_init: Too many midi devices detected\n"); - return; - } - std_midi_synth.midi_dev = my_dev = dev; - midi_devs[dev] = &pas_midi_operations; - pas2_mididev = dev; - sequencer_init(); -} - -void pas_midi_interrupt(void) -{ - unsigned char stat; - int i, incount; - - stat = pas_read(0x1B88); - - if (stat & 0x04) /* Input data available */ - { - incount = pas_read(0x1B89) & 0x0f; /* Input FIFO size */ - if (!incount) - incount = 16; - - for (i = 0; i < incount; i++) - if (input_opened) - { - midi_input_intr(my_dev, pas_read(0x178A)); - } else - pas_read(0x178A); /* Flush */ - } - if (stat & (0x08 | 0x10)) - { - spin_lock(&pas_lock);/* called in irq context */ - - while (qlen && dump_to_midi(tmp_queue[qhead])) - { - qlen--; - qhead++; - } - - spin_unlock(&pas_lock); - } - if (stat & 0x40) - { - printk(KERN_WARNING "MIDI output overrun %x,%x\n", pas_read(0x1B89), stat); - } - pas_write(stat, 0x1B88); /* Acknowledge interrupts */ -} diff --git a/ANDROID_3.4.5/sound/oss/pas2_mixer.c b/ANDROID_3.4.5/sound/oss/pas2_mixer.c deleted file mode 100644 index a0bcb85c..00000000 --- a/ANDROID_3.4.5/sound/oss/pas2_mixer.c +++ /dev/null @@ -1,336 +0,0 @@ - -/* - * sound/oss/pas2_mixer.c - * - * Mixer routines for the Pro Audio Spectrum cards. - */ - -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * Bartlomiej Zolnierkiewicz : added __init to pas_init_mixer() - */ -#include -#include "sound_config.h" - -#include "pas2.h" - -#ifndef DEB -#define DEB(what) /* (what) */ -#endif - -extern int pas_translate_code; -extern char pas_model; -extern int *pas_osp; -extern int pas_audiodev; - -static int rec_devices = (SOUND_MASK_MIC); /* Default recording source */ -static int mode_control; - -#define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_ALTPCM) - -#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_ALTPCM | SOUND_MASK_IMIX | \ - SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV) - -static int *levels; - -static int default_levels[32] = -{ - 0x3232, /* Master Volume */ - 0x3232, /* Bass */ - 0x3232, /* Treble */ - 0x5050, /* FM */ - 0x4b4b, /* PCM */ - 0x3232, /* PC Speaker */ - 0x4b4b, /* Ext Line */ - 0x4b4b, /* Mic */ - 0x4b4b, /* CD */ - 0x6464, /* Recording monitor */ - 0x4b4b, /* SB PCM */ - 0x6464 /* Recording level */ -}; - -void -mix_write(unsigned char data, int ioaddr) -{ - /* - * The Revision D cards have a problem with their MVA508 interface. The - * kludge-o-rama fix is to make a 16-bit quantity with identical LSB and - * MSBs out of the output byte and to do a 16-bit out to the mixer port - - * 1. We need to do this because it isn't timing problem but chip access - * sequence problem. - */ - - if (pas_model == 4) - { - outw(data | (data << 8), (ioaddr + pas_translate_code) - 1); - outb((0x80), 0); - } else - pas_write(data, ioaddr); -} - -static int -mixer_output(int right_vol, int left_vol, int div, int bits, - int mixer) /* Input or output mixer */ -{ - int left = left_vol * div / 100; - int right = right_vol * div / 100; - - - if (bits & 0x10) - { - left |= mixer; - right |= mixer; - } - if (bits == 0x03 || bits == 0x04) - { - mix_write(0x80 | bits, 0x078B); - mix_write(left, 0x078B); - right_vol = left_vol; - } else - { - mix_write(0x80 | 0x20 | bits, 0x078B); - mix_write(left, 0x078B); - mix_write(0x80 | 0x40 | bits, 0x078B); - mix_write(right, 0x078B); - } - - return (left_vol | (right_vol << 8)); -} - -static void -set_mode(int new_mode) -{ - mix_write(0x80 | 0x05, 0x078B); - mix_write(new_mode, 0x078B); - - mode_control = new_mode; -} - -static int -pas_mixer_set(int whichDev, unsigned int level) -{ - int left, right, devmask, changed, i, mixer = 0; - - DEB(printk("static int pas_mixer_set(int whichDev = %d, unsigned int level = %X)\n", whichDev, level)); - - left = level & 0x7f; - right = (level & 0x7f00) >> 8; - - if (whichDev < SOUND_MIXER_NRDEVICES) { - if ((1 << whichDev) & rec_devices) - mixer = 0x20; - else - mixer = 0x00; - } - - switch (whichDev) - { - case SOUND_MIXER_VOLUME: /* Master volume (0-63) */ - levels[whichDev] = mixer_output(right, left, 63, 0x01, 0); - break; - - /* - * Note! Bass and Treble are mono devices. Will use just the left - * channel. - */ - case SOUND_MIXER_BASS: /* Bass (0-12) */ - levels[whichDev] = mixer_output(right, left, 12, 0x03, 0); - break; - case SOUND_MIXER_TREBLE: /* Treble (0-12) */ - levels[whichDev] = mixer_output(right, left, 12, 0x04, 0); - break; - - case SOUND_MIXER_SYNTH: /* Internal synthesizer (0-31) */ - levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x00, mixer); - break; - case SOUND_MIXER_PCM: /* PAS PCM (0-31) */ - levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x05, mixer); - break; - case SOUND_MIXER_ALTPCM: /* SB PCM (0-31) */ - levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x07, mixer); - break; - case SOUND_MIXER_SPEAKER: /* PC speaker (0-31) */ - levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x06, mixer); - break; - case SOUND_MIXER_LINE: /* External line (0-31) */ - levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x02, mixer); - break; - case SOUND_MIXER_CD: /* CD (0-31) */ - levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x03, mixer); - break; - case SOUND_MIXER_MIC: /* External microphone (0-31) */ - levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x04, mixer); - break; - case SOUND_MIXER_IMIX: /* Recording monitor (0-31) (Output mixer only) */ - levels[whichDev] = mixer_output(right, left, 31, 0x10 | 0x01, - 0x00); - break; - case SOUND_MIXER_RECLEV: /* Recording level (0-15) */ - levels[whichDev] = mixer_output(right, left, 15, 0x02, 0); - break; - - - case SOUND_MIXER_RECSRC: - devmask = level & POSSIBLE_RECORDING_DEVICES; - - changed = devmask ^ rec_devices; - rec_devices = devmask; - - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if (changed & (1 << i)) - { - pas_mixer_set(i, levels[i]); - } - return rec_devices; - break; - - default: - return -EINVAL; - } - - return (levels[whichDev]); -} - -/*****/ - -static void -pas_mixer_reset(void) -{ - int foo; - - DEB(printk("pas2_mixer.c: void pas_mixer_reset(void)\n")); - - for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) - pas_mixer_set(foo, levels[foo]); - - set_mode(0x04 | 0x01); -} - -static int pas_mixer_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - int level,v ; - int __user *p = (int __user *)arg; - - DEB(printk("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg)); - if (cmd == SOUND_MIXER_PRIVATE1) { /* Set loudness bit */ - if (get_user(level, p)) - return -EFAULT; - if (level == -1) /* Return current settings */ - level = (mode_control & 0x04); - else { - mode_control &= ~0x04; - if (level) - mode_control |= 0x04; - set_mode(mode_control); - } - level = !!level; - return put_user(level, p); - } - if (cmd == SOUND_MIXER_PRIVATE2) { /* Set enhance bit */ - if (get_user(level, p)) - return -EFAULT; - if (level == -1) { /* Return current settings */ - if (!(mode_control & 0x03)) - level = 0; - else - level = ((mode_control & 0x03) + 1) * 20; - } else { - int i = 0; - - level &= 0x7f; - if (level) - i = (level / 20) - 1; - mode_control &= ~0x03; - mode_control |= i & 0x03; - set_mode(mode_control); - if (i) - i = (i + 1) * 20; - level = i; - } - return put_user(level, p); - } - if (cmd == SOUND_MIXER_PRIVATE3) { /* Set mute bit */ - if (get_user(level, p)) - return -EFAULT; - if (level == -1) /* Return current settings */ - level = !(pas_read(0x0B8A) & 0x20); - else { - if (level) - pas_write(pas_read(0x0B8A) & (~0x20), 0x0B8A); - else - pas_write(pas_read(0x0B8A) | 0x20, 0x0B8A); - - level = !(pas_read(0x0B8A) & 0x20); - } - return put_user(level, p); - } - if (((cmd >> 8) & 0xff) == 'M') { - if (get_user(v, p)) - return -EFAULT; - if (_SIOC_DIR(cmd) & _SIOC_WRITE) { - v = pas_mixer_set(cmd & 0xff, v); - } else { - switch (cmd & 0xff) { - case SOUND_MIXER_RECSRC: - v = rec_devices; - break; - - case SOUND_MIXER_STEREODEVS: - v = SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE); - break; - - case SOUND_MIXER_DEVMASK: - v = SUPPORTED_MIXER_DEVICES; - break; - - case SOUND_MIXER_RECMASK: - v = POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES; - break; - - case SOUND_MIXER_CAPS: - v = 0; /* No special capabilities */ - break; - - default: - v = levels[cmd & 0xff]; - break; - } - } - return put_user(v, p); - } - return -EINVAL; -} - -static struct mixer_operations pas_mixer_operations = -{ - .owner = THIS_MODULE, - .id = "PAS16", - .name = "Pro Audio Spectrum 16", - .ioctl = pas_mixer_ioctl -}; - -int __init -pas_init_mixer(void) -{ - int d; - - levels = load_mixer_volumes("PAS16_1", default_levels, 1); - - pas_mixer_reset(); - - if ((d = sound_alloc_mixerdev()) != -1) - { - audio_devs[pas_audiodev]->mixer_dev = d; - mixer_devs[d] = &pas_mixer_operations; - } - return 1; -} diff --git a/ANDROID_3.4.5/sound/oss/pas2_pcm.c b/ANDROID_3.4.5/sound/oss/pas2_pcm.c deleted file mode 100644 index 6f13ab4a..00000000 --- a/ANDROID_3.4.5/sound/oss/pas2_pcm.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * pas2_pcm.c Audio routines for PAS16 - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * Alan Cox : Swatted a double allocation of device bug. Made a few - * more things module options. - * Bartlomiej Zolnierkiewicz : Added __init to pas_pcm_init() - */ - -#include -#include -#include -#include "sound_config.h" - -#include "pas2.h" - -#ifndef DEB -#define DEB(WHAT) -#endif - -#define PAS_PCM_INTRBITS (0x08) -/* - * Sample buffer timer interrupt enable - */ - -#define PCM_NON 0 -#define PCM_DAC 1 -#define PCM_ADC 2 - -static unsigned long pcm_speed; /* sampling rate */ -static unsigned char pcm_channels = 1; /* channels (1 or 2) */ -static unsigned char pcm_bits = 8; /* bits/sample (8 or 16) */ -static unsigned char pcm_filter; /* filter FLAG */ -static unsigned char pcm_mode = PCM_NON; -static unsigned long pcm_count; -static unsigned short pcm_bitsok = 8; /* mask of OK bits */ -static int pcm_busy; -int pas_audiodev = -1; -static int open_mode; - -extern spinlock_t pas_lock; - -static int pcm_set_speed(int arg) -{ - int foo, tmp; - unsigned long flags; - - if (arg == 0) - return pcm_speed; - - if (arg > 44100) - arg = 44100; - if (arg < 5000) - arg = 5000; - - if (pcm_channels & 2) - { - foo = ((PIT_TICK_RATE / 2) + (arg / 2)) / arg; - arg = ((PIT_TICK_RATE / 2) + (foo / 2)) / foo; - } - else - { - foo = (PIT_TICK_RATE + (arg / 2)) / arg; - arg = (PIT_TICK_RATE + (foo / 2)) / foo; - } - - pcm_speed = arg; - - tmp = pas_read(0x0B8A); - - /* - * Set anti-aliasing filters according to sample rate. You really *NEED* - * to enable this feature for all normal recording unless you want to - * experiment with aliasing effects. - * These filters apply to the selected "recording" source. - * I (pfw) don't know the encoding of these 5 bits. The values shown - * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/. - * - * I cleared bit 5 of these values, since that bit controls the master - * mute flag. (Olav Wölfelschneider) - * - */ -#if !defined NO_AUTO_FILTER_SET - tmp &= 0xe0; - if (pcm_speed >= 2 * 17897) - tmp |= 0x01; - else if (pcm_speed >= 2 * 15909) - tmp |= 0x02; - else if (pcm_speed >= 2 * 11931) - tmp |= 0x09; - else if (pcm_speed >= 2 * 8948) - tmp |= 0x11; - else if (pcm_speed >= 2 * 5965) - tmp |= 0x19; - else if (pcm_speed >= 2 * 2982) - tmp |= 0x04; - pcm_filter = tmp; -#endif - - spin_lock_irqsave(&pas_lock, flags); - - pas_write(tmp & ~(0x40 | 0x80), 0x0B8A); - pas_write(0x00 | 0x30 | 0x04, 0x138B); - pas_write(foo & 0xff, 0x1388); - pas_write((foo >> 8) & 0xff, 0x1388); - pas_write(tmp, 0x0B8A); - - spin_unlock_irqrestore(&pas_lock, flags); - - return pcm_speed; -} - -static int pcm_set_channels(int arg) -{ - - if ((arg != 1) && (arg != 2)) - return pcm_channels; - - if (arg != pcm_channels) - { - pas_write(pas_read(0xF8A) ^ 0x20, 0xF8A); - - pcm_channels = arg; - pcm_set_speed(pcm_speed); /* The speed must be reinitialized */ - } - return pcm_channels; -} - -static int pcm_set_bits(int arg) -{ - if (arg == 0) - return pcm_bits; - - if ((arg & pcm_bitsok) != arg) - return pcm_bits; - - if (arg != pcm_bits) - { - pas_write(pas_read(0x8389) ^ 0x04, 0x8389); - - pcm_bits = arg; - } - return pcm_bits; -} - -static int pas_audio_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - int val, ret; - int __user *p = arg; - - DEB(printk("pas2_pcm.c: static int pas_audio_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg)); - - switch (cmd) - { - case SOUND_PCM_WRITE_RATE: - if (get_user(val, p)) - return -EFAULT; - ret = pcm_set_speed(val); - break; - - case SOUND_PCM_READ_RATE: - ret = pcm_speed; - break; - - case SNDCTL_DSP_STEREO: - if (get_user(val, p)) - return -EFAULT; - ret = pcm_set_channels(val + 1) - 1; - break; - - case SOUND_PCM_WRITE_CHANNELS: - if (get_user(val, p)) - return -EFAULT; - ret = pcm_set_channels(val); - break; - - case SOUND_PCM_READ_CHANNELS: - ret = pcm_channels; - break; - - case SNDCTL_DSP_SETFMT: - if (get_user(val, p)) - return -EFAULT; - ret = pcm_set_bits(val); - break; - - case SOUND_PCM_READ_BITS: - ret = pcm_bits; - break; - - default: - return -EINVAL; - } - return put_user(ret, p); -} - -static void pas_audio_reset(int dev) -{ - DEB(printk("pas2_pcm.c: static void pas_audio_reset(void)\n")); - - pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); /* Disable PCM */ -} - -static int pas_audio_open(int dev, int mode) -{ - int err; - unsigned long flags; - - DEB(printk("pas2_pcm.c: static int pas_audio_open(int mode = %X)\n", mode)); - - spin_lock_irqsave(&pas_lock, flags); - if (pcm_busy) - { - spin_unlock_irqrestore(&pas_lock, flags); - return -EBUSY; - } - pcm_busy = 1; - spin_unlock_irqrestore(&pas_lock, flags); - - if ((err = pas_set_intr(PAS_PCM_INTRBITS)) < 0) - return err; - - - pcm_count = 0; - open_mode = mode; - - return 0; -} - -static void pas_audio_close(int dev) -{ - unsigned long flags; - - DEB(printk("pas2_pcm.c: static void pas_audio_close(void)\n")); - - spin_lock_irqsave(&pas_lock, flags); - - pas_audio_reset(dev); - pas_remove_intr(PAS_PCM_INTRBITS); - pcm_mode = PCM_NON; - - pcm_busy = 0; - spin_unlock_irqrestore(&pas_lock, flags); -} - -static void pas_audio_output_block(int dev, unsigned long buf, int count, - int intrflag) -{ - unsigned long flags, cnt; - - DEB(printk("pas2_pcm.c: static void pas_audio_output_block(char *buf = %P, int count = %X)\n", buf, count)); - - cnt = count; - if (audio_devs[dev]->dmap_out->dma > 3) - cnt >>= 1; - - if (audio_devs[dev]->flags & DMA_AUTOMODE && - intrflag && - cnt == pcm_count) - return; - - spin_lock_irqsave(&pas_lock, flags); - - pas_write(pas_read(0xF8A) & ~0x40, - 0xF8A); - - /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */ - - if (audio_devs[dev]->dmap_out->dma > 3) - count >>= 1; - - if (count != pcm_count) - { - pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A); - pas_write(0x40 | 0x30 | 0x04, 0x138B); - pas_write(count & 0xff, 0x1389); - pas_write((count >> 8) & 0xff, 0x1389); - pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A); - - pcm_count = count; - } - pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A); -#ifdef NO_TRIGGER - pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A); -#endif - - pcm_mode = PCM_DAC; - - spin_unlock_irqrestore(&pas_lock, flags); -} - -static void pas_audio_start_input(int dev, unsigned long buf, int count, - int intrflag) -{ - unsigned long flags; - int cnt; - - DEB(printk("pas2_pcm.c: static void pas_audio_start_input(char *buf = %P, int count = %X)\n", buf, count)); - - cnt = count; - if (audio_devs[dev]->dmap_out->dma > 3) - cnt >>= 1; - - if (audio_devs[pas_audiodev]->flags & DMA_AUTOMODE && - intrflag && - cnt == pcm_count) - return; - - spin_lock_irqsave(&pas_lock, flags); - - /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */ - - if (audio_devs[dev]->dmap_out->dma > 3) - count >>= 1; - - if (count != pcm_count) - { - pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A); - pas_write(0x40 | 0x30 | 0x04, 0x138B); - pas_write(count & 0xff, 0x1389); - pas_write((count >> 8) & 0xff, 0x1389); - pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A); - - pcm_count = count; - } - pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A); -#ifdef NO_TRIGGER - pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A); -#endif - - pcm_mode = PCM_ADC; - - spin_unlock_irqrestore(&pas_lock, flags); -} - -#ifndef NO_TRIGGER -static void pas_audio_trigger(int dev, int state) -{ - unsigned long flags; - - spin_lock_irqsave(&pas_lock, flags); - state &= open_mode; - - if (state & PCM_ENABLE_OUTPUT) - pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A); - else if (state & PCM_ENABLE_INPUT) - pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A); - else - pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); - - spin_unlock_irqrestore(&pas_lock, flags); -} -#endif - -static int pas_audio_prepare_for_input(int dev, int bsize, int bcount) -{ - pas_audio_reset(dev); - return 0; -} - -static int pas_audio_prepare_for_output(int dev, int bsize, int bcount) -{ - pas_audio_reset(dev); - return 0; -} - -static struct audio_driver pas_audio_driver = -{ - .owner = THIS_MODULE, - .open = pas_audio_open, - .close = pas_audio_close, - .output_block = pas_audio_output_block, - .start_input = pas_audio_start_input, - .ioctl = pas_audio_ioctl, - .prepare_for_input = pas_audio_prepare_for_input, - .prepare_for_output = pas_audio_prepare_for_output, - .halt_io = pas_audio_reset, - .trigger = pas_audio_trigger -}; - -void __init pas_pcm_init(struct address_info *hw_config) -{ - DEB(printk("pas2_pcm.c: long pas_pcm_init()\n")); - - pcm_bitsok = 8; - if (pas_read(0xEF8B) & 0x08) - pcm_bitsok |= 16; - - pcm_set_speed(DSP_DEFAULT_SPEED); - - if ((pas_audiodev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, - "Pro Audio Spectrum", - &pas_audio_driver, - sizeof(struct audio_driver), - DMA_AUTOMODE, - AFMT_U8 | AFMT_S16_LE, - NULL, - hw_config->dma, - hw_config->dma)) < 0) - printk(KERN_WARNING "PAS16: Too many PCM devices available\n"); -} - -void pas_pcm_interrupt(unsigned char status, int cause) -{ - if (cause == 1) - { - /* - * Halt the PCM first. Otherwise we don't have time to start a new - * block before the PCM chip proceeds to the next sample - */ - - if (!(audio_devs[pas_audiodev]->flags & DMA_AUTOMODE)) - pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); - - switch (pcm_mode) - { - case PCM_DAC: - DMAbuf_outputintr(pas_audiodev, 1); - break; - - case PCM_ADC: - DMAbuf_inputintr(pas_audiodev); - break; - - default: - printk(KERN_WARNING "PAS: Unexpected PCM interrupt\n"); - } - } -} diff --git a/ANDROID_3.4.5/sound/oss/pss.c b/ANDROID_3.4.5/sound/oss/pss.c deleted file mode 100644 index 0f32a561..00000000 --- a/ANDROID_3.4.5/sound/oss/pss.c +++ /dev/null @@ -1,1268 +0,0 @@ -/* - * sound/oss/pss.c - * - * The low level driver for the Personal Sound System (ECHO ESC614). - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) - * Alan Cox modularisation, clean up. - * - * 98-02-21: Vladimir Michl - * Added mixer device for Beethoven ADSP-16 (master volume, - * bass, treble, synth), only for speakers. - * Fixed bug in pss_write (exchange parameters) - * Fixed config port of SB - * Requested two regions for PSS (PSS mixer, PSS config) - * Modified pss_download_boot - * To probe_pss_mss added test for initialize AD1848 - * 98-05-28: Vladimir Michl - * Fixed computation of mixer volumes - * 04-05-1999: Anthony Barbachan - * Added code that allows the user to enable his cdrom and/or - * joystick through the module parameters pss_cdrom_port and - * pss_enable_joystick. pss_cdrom_port takes a port address as its - * argument. pss_enable_joystick takes either a 0 or a non-0 as its - * argument. - * 04-06-1999: Anthony Barbachan - * Separated some code into new functions for easier reuse. - * Cleaned up and streamlined new code. Added code to allow a user - * to only use this driver for enabling non-sound components - * through the new module parameter pss_no_sound (flag). Added - * code that would allow a user to decide whether the driver should - * reset the configured hardware settings for the PSS board through - * the module parameter pss_keep_settings (flag). This flag will - * allow a user to free up resources in use by this card if needbe, - * furthermore it allows him to use this driver to just enable the - * emulations and then be unloaded as it is no longer needed. Both - * new settings are only available to this driver if compiled as a - * module. The default settings of all new parameters are set to - * load the driver as it did in previous versions. - * 04-07-1999: Anthony Barbachan - * Added module parameter pss_firmware to allow the user to tell - * the driver where the firmware file is located. The default - * setting is the previous hardcoded setting "/etc/sound/pss_synth". - * 00-03-03: Christoph Hellwig - * Adapted to module_init/module_exit - * 11-10-2000: Bartlomiej Zolnierkiewicz - * Added __init to probe_pss(), attach_pss() and probe_pss_mpu() - * 02-Jan-2001: Chris Rankin - * Specify that this module owns the coprocessor - */ - - -#include -#include -#include - -#include "sound_config.h" -#include "sound_firmware.h" - -#include "ad1848.h" -#include "mpu401.h" - -/* - * PSS registers. - */ -#define REG(x) (devc->base+x) -#define PSS_DATA 0 -#define PSS_STATUS 2 -#define PSS_CONTROL 2 -#define PSS_ID 4 -#define PSS_IRQACK 4 -#define PSS_PIO 0x1a - -/* - * Config registers - */ -#define CONF_PSS 0x10 -#define CONF_WSS 0x12 -#define CONF_SB 0x14 -#define CONF_CDROM 0x16 -#define CONF_MIDI 0x18 - -/* - * Status bits. - */ -#define PSS_FLAG3 0x0800 -#define PSS_FLAG2 0x0400 -#define PSS_FLAG1 0x1000 -#define PSS_FLAG0 0x0800 -#define PSS_WRITE_EMPTY 0x8000 -#define PSS_READ_FULL 0x4000 - -/* - * WSS registers - */ -#define WSS_INDEX 4 -#define WSS_DATA 5 - -/* - * WSS status bits - */ -#define WSS_INITIALIZING 0x80 -#define WSS_AUTOCALIBRATION 0x20 - -#define NO_WSS_MIXER -1 - -#include "coproc.h" - -#include "pss_boot.h" - -/* If compiled into kernel, it enable or disable pss mixer */ -#ifdef CONFIG_PSS_MIXER -static bool pss_mixer = 1; -#else -static bool pss_mixer; -#endif - - -typedef struct pss_mixerdata { - unsigned int volume_l; - unsigned int volume_r; - unsigned int bass; - unsigned int treble; - unsigned int synth; -} pss_mixerdata; - -typedef struct pss_confdata { - int base; - int irq; - int dma; - int *osp; - pss_mixerdata mixer; - int ad_mixer_dev; -} pss_confdata; - -static pss_confdata pss_data; -static pss_confdata *devc = &pss_data; -static DEFINE_SPINLOCK(lock); - -static int pss_initialized; -static int nonstandard_microcode; -static int pss_cdrom_port = -1; /* Parameter for the PSS cdrom port */ -static bool pss_enable_joystick; /* Parameter for enabling the joystick */ -static coproc_operations pss_coproc_operations; - -static void pss_write(pss_confdata *devc, int data) -{ - unsigned long i, limit; - - limit = jiffies + HZ/10; /* The timeout is 0.1 seconds */ - /* - * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes - * called while interrupts are disabled. This means that the timer is - * disabled also. However the timeout situation is a abnormal condition. - * Normally the DSP should be ready to accept commands after just couple of - * loops. - */ - - for (i = 0; i < 5000000 && time_before(jiffies, limit); i++) - { - if (inw(REG(PSS_STATUS)) & PSS_WRITE_EMPTY) - { - outw(data, REG(PSS_DATA)); - return; - } - } - printk(KERN_WARNING "PSS: DSP Command (%04x) Timeout.\n", data); -} - -static int __init probe_pss(struct address_info *hw_config) -{ - unsigned short id; - int irq, dma; - - devc->base = hw_config->io_base; - irq = devc->irq = hw_config->irq; - dma = devc->dma = hw_config->dma; - devc->osp = hw_config->osp; - - if (devc->base != 0x220 && devc->base != 0x240) - if (devc->base != 0x230 && devc->base != 0x250) /* Some cards use these */ - return 0; - - if (!request_region(devc->base, 0x10, "PSS mixer, SB emulation")) { - printk(KERN_ERR "PSS: I/O port conflict\n"); - return 0; - } - id = inw(REG(PSS_ID)); - if ((id >> 8) != 'E') { - printk(KERN_ERR "No PSS signature detected at 0x%x (0x%x)\n", devc->base, id); - release_region(devc->base, 0x10); - return 0; - } - if (!request_region(devc->base + 0x10, 0x9, "PSS config")) { - printk(KERN_ERR "PSS: I/O port conflict\n"); - release_region(devc->base, 0x10); - return 0; - } - return 1; -} - -static int set_irq(pss_confdata * devc, int dev, int irq) -{ - static unsigned short irq_bits[16] = - { - 0x0000, 0x0000, 0x0000, 0x0008, - 0x0000, 0x0010, 0x0000, 0x0018, - 0x0000, 0x0020, 0x0028, 0x0030, - 0x0038, 0x0000, 0x0000, 0x0000 - }; - - unsigned short tmp, bits; - - if (irq < 0 || irq > 15) - return 0; - - tmp = inw(REG(dev)) & ~0x38; /* Load confreg, mask IRQ bits out */ - - if ((bits = irq_bits[irq]) == 0 && irq != 0) - { - printk(KERN_ERR "PSS: Invalid IRQ %d\n", irq); - return 0; - } - outw(tmp | bits, REG(dev)); - return 1; -} - -static void set_io_base(pss_confdata * devc, int dev, int base) -{ - unsigned short tmp = inw(REG(dev)) & 0x003f; - unsigned short bits = (base & 0x0ffc) << 4; - - outw(bits | tmp, REG(dev)); -} - -static int set_dma(pss_confdata * devc, int dev, int dma) -{ - static unsigned short dma_bits[8] = - { - 0x0001, 0x0002, 0x0000, 0x0003, - 0x0000, 0x0005, 0x0006, 0x0007 - }; - - unsigned short tmp, bits; - - if (dma < 0 || dma > 7) - return 0; - - tmp = inw(REG(dev)) & ~0x07; /* Load confreg, mask DMA bits out */ - - if ((bits = dma_bits[dma]) == 0 && dma != 4) - { - printk(KERN_ERR "PSS: Invalid DMA %d\n", dma); - return 0; - } - outw(tmp | bits, REG(dev)); - return 1; -} - -static int pss_reset_dsp(pss_confdata * devc) -{ - unsigned long i, limit = jiffies + HZ/10; - - outw(0x2000, REG(PSS_CONTROL)); - for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) - inw(REG(PSS_CONTROL)); - outw(0x0000, REG(PSS_CONTROL)); - return 1; -} - -static int pss_put_dspword(pss_confdata * devc, unsigned short word) -{ - int i, val; - - for (i = 0; i < 327680; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_WRITE_EMPTY) - { - outw(word, REG(PSS_DATA)); - return 1; - } - } - return 0; -} - -static int pss_get_dspword(pss_confdata * devc, unsigned short *word) -{ - int i, val; - - for (i = 0; i < 327680; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_READ_FULL) - { - *word = inw(REG(PSS_DATA)); - return 1; - } - } - return 0; -} - -static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags) -{ - int i, val, count; - unsigned long limit; - - if (flags & CPF_FIRST) - { -/*_____ Warn DSP software that a boot is coming */ - outw(0x00fe, REG(PSS_DATA)); - - limit = jiffies + HZ/10; - for (i = 0; i < 32768 && time_before(jiffies, limit); i++) - if (inw(REG(PSS_DATA)) == 0x5500) - break; - - outw(*block++, REG(PSS_DATA)); - pss_reset_dsp(devc); - } - count = 1; - while ((flags&CPF_LAST) || count= size && flags & CPF_LAST) - break; - else - { - printk("\n"); - printk(KERN_ERR "PSS: Download timeout problems, byte %d=%d\n", count, size); - return 0; - } - } -/*_____ Send the next byte */ - if (count >= size) - { - /* If not data in block send 0xffff */ - outw (0xffff, REG (PSS_DATA)); - } - else - { - /*_____ Send the next byte */ - outw (*block++, REG (PSS_DATA)); - }; - count++; - } - - if (flags & CPF_LAST) - { -/*_____ Why */ - outw(0, REG(PSS_DATA)); - - limit = jiffies + HZ/10; - for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) - val = inw(REG(PSS_STATUS)); - - limit = jiffies + HZ/10; - for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) - { - val = inw(REG(PSS_STATUS)); - if (val & 0x4000) - break; - } - - /* now read the version */ - for (i = 0; i < 32000; i++) - { - val = inw(REG(PSS_STATUS)); - if (val & PSS_READ_FULL) - break; - } - if (i == 32000) - return 0; - - val = inw(REG(PSS_DATA)); - /* printk( "", val/16, val % 16); */ - } - return 1; -} - -/* Mixer */ -static void set_master_volume(pss_confdata *devc, int left, int right) -{ - static unsigned char log_scale[101] = { - 0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, - 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, - 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, - 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, - 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, - 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, - 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, - 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, - 0xfe, 0xfe, 0xff, 0xff, 0xff - }; - pss_write(devc, 0x0010); - pss_write(devc, log_scale[left] | 0x0000); - pss_write(devc, 0x0010); - pss_write(devc, log_scale[right] | 0x0100); -} - -static void set_synth_volume(pss_confdata *devc, int volume) -{ - int vol = ((0x8000*volume)/100L); - pss_write(devc, 0x0080); - pss_write(devc, vol); - pss_write(devc, 0x0081); - pss_write(devc, vol); -} - -static void set_bass(pss_confdata *devc, int level) -{ - int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0; - pss_write(devc, 0x0010); - pss_write(devc, vol | 0x0200); -}; - -static void set_treble(pss_confdata *devc, int level) -{ - int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0; - pss_write(devc, 0x0010); - pss_write(devc, vol | 0x0300); -}; - -static void pss_mixer_reset(pss_confdata *devc) -{ - set_master_volume(devc, 33, 33); - set_bass(devc, 50); - set_treble(devc, 50); - set_synth_volume(devc, 30); - pss_write (devc, 0x0010); - pss_write (devc, 0x0800 | 0xce); /* Stereo */ - - if(pss_mixer) - { - devc->mixer.volume_l = devc->mixer.volume_r = 33; - devc->mixer.bass = 50; - devc->mixer.treble = 50; - devc->mixer.synth = 30; - } -} - -static int set_volume_mono(unsigned __user *p, unsigned int *aleft) -{ - unsigned int left, volume; - if (get_user(volume, p)) - return -EFAULT; - - left = volume & 0xff; - if (left > 100) - left = 100; - *aleft = left; - return 0; -} - -static int set_volume_stereo(unsigned __user *p, - unsigned int *aleft, - unsigned int *aright) -{ - unsigned int left, right, volume; - if (get_user(volume, p)) - return -EFAULT; - - left = volume & 0xff; - if (left > 100) - left = 100; - right = (volume >> 8) & 0xff; - if (right > 100) - right = 100; - *aleft = left; - *aright = right; - return 0; -} - -static int ret_vol_mono(int left) -{ - return ((left << 8) | left); -} - -static int ret_vol_stereo(int left, int right) -{ - return ((right << 8) | left); -} - -static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg) -{ - if (devc->ad_mixer_dev != NO_WSS_MIXER) - return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg); - else - return -EINVAL; -} - -static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg) -{ - pss_confdata *devc = mixer_devs[dev]->devc; - int cmdf = cmd & 0xff; - - if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) && - (cmdf != SOUND_MIXER_TREBLE) && (cmdf != SOUND_MIXER_SYNTH) && - (cmdf != SOUND_MIXER_DEVMASK) && (cmdf != SOUND_MIXER_STEREODEVS) && - (cmdf != SOUND_MIXER_RECMASK) && (cmdf != SOUND_MIXER_CAPS) && - (cmdf != SOUND_MIXER_RECSRC)) - { - return call_ad_mixer(devc, cmd, arg); - } - - if (((cmd >> 8) & 0xff) != 'M') - return -EINVAL; - - if (_SIOC_DIR (cmd) & _SIOC_WRITE) - { - switch (cmdf) - { - case SOUND_MIXER_RECSRC: - if (devc->ad_mixer_dev != NO_WSS_MIXER) - return call_ad_mixer(devc, cmd, arg); - else - { - int v; - if (get_user(v, (int __user *)arg)) - return -EFAULT; - if (v != 0) - return -EINVAL; - return 0; - } - case SOUND_MIXER_VOLUME: - if (set_volume_stereo(arg, - &devc->mixer.volume_l, - &devc->mixer.volume_r)) - return -EFAULT; - set_master_volume(devc, devc->mixer.volume_l, - devc->mixer.volume_r); - return ret_vol_stereo(devc->mixer.volume_l, - devc->mixer.volume_r); - - case SOUND_MIXER_BASS: - if (set_volume_mono(arg, &devc->mixer.bass)) - return -EFAULT; - set_bass(devc, devc->mixer.bass); - return ret_vol_mono(devc->mixer.bass); - - case SOUND_MIXER_TREBLE: - if (set_volume_mono(arg, &devc->mixer.treble)) - return -EFAULT; - set_treble(devc, devc->mixer.treble); - return ret_vol_mono(devc->mixer.treble); - - case SOUND_MIXER_SYNTH: - if (set_volume_mono(arg, &devc->mixer.synth)) - return -EFAULT; - set_synth_volume(devc, devc->mixer.synth); - return ret_vol_mono(devc->mixer.synth); - - default: - return -EINVAL; - } - } - else - { - int val, and_mask = 0, or_mask = 0; - /* - * Return parameters - */ - switch (cmdf) - { - case SOUND_MIXER_DEVMASK: - if (call_ad_mixer(devc, cmd, arg) == -EINVAL) - break; - and_mask = ~0; - or_mask = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH; - break; - - case SOUND_MIXER_STEREODEVS: - if (call_ad_mixer(devc, cmd, arg) == -EINVAL) - break; - and_mask = ~0; - or_mask = SOUND_MASK_VOLUME; - break; - - case SOUND_MIXER_RECMASK: - if (devc->ad_mixer_dev != NO_WSS_MIXER) - return call_ad_mixer(devc, cmd, arg); - break; - - case SOUND_MIXER_CAPS: - if (devc->ad_mixer_dev != NO_WSS_MIXER) - return call_ad_mixer(devc, cmd, arg); - or_mask = SOUND_CAP_EXCL_INPUT; - break; - - case SOUND_MIXER_RECSRC: - if (devc->ad_mixer_dev != NO_WSS_MIXER) - return call_ad_mixer(devc, cmd, arg); - break; - - case SOUND_MIXER_VOLUME: - or_mask = ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r); - break; - - case SOUND_MIXER_BASS: - or_mask = ret_vol_mono(devc->mixer.bass); - break; - - case SOUND_MIXER_TREBLE: - or_mask = ret_vol_mono(devc->mixer.treble); - break; - - case SOUND_MIXER_SYNTH: - or_mask = ret_vol_mono(devc->mixer.synth); - break; - default: - return -EINVAL; - } - if (get_user(val, (int __user *)arg)) - return -EFAULT; - val &= and_mask; - val |= or_mask; - if (put_user(val, (int __user *)arg)) - return -EFAULT; - return val; - } -} - -static struct mixer_operations pss_mixer_operations = -{ - .owner = THIS_MODULE, - .id = "SOUNDPORT", - .name = "PSS-AD1848", - .ioctl = pss_mixer_ioctl -}; - -static void disable_all_emulations(void) -{ - outw(0x0000, REG(CONF_PSS)); /* 0x0400 enables joystick */ - outw(0x0000, REG(CONF_WSS)); - outw(0x0000, REG(CONF_SB)); - outw(0x0000, REG(CONF_MIDI)); - outw(0x0000, REG(CONF_CDROM)); -} - -static void configure_nonsound_components(void) -{ - /* Configure Joystick port */ - - if(pss_enable_joystick) - { - outw(0x0400, REG(CONF_PSS)); /* 0x0400 enables joystick */ - printk(KERN_INFO "PSS: joystick enabled.\n"); - } - else - { - printk(KERN_INFO "PSS: joystick port not enabled.\n"); - } - - /* Configure CDROM port */ - - if (pss_cdrom_port == -1) { /* If cdrom port enablation wasn't requested */ - printk(KERN_INFO "PSS: CDROM port not enabled.\n"); - } else if (!request_region(pss_cdrom_port, 2, "PSS CDROM")) { - pss_cdrom_port = -1; - printk(KERN_ERR "PSS: CDROM I/O port conflict.\n"); - } else { - set_io_base(devc, CONF_CDROM, pss_cdrom_port); - printk(KERN_INFO "PSS: CDROM I/O port set to 0x%x.\n", pss_cdrom_port); - } -} - -static int __init attach_pss(struct address_info *hw_config) -{ - unsigned short id; - char tmp[100]; - - devc->base = hw_config->io_base; - devc->irq = hw_config->irq; - devc->dma = hw_config->dma; - devc->osp = hw_config->osp; - devc->ad_mixer_dev = NO_WSS_MIXER; - - if (!probe_pss(hw_config)) - return 0; - - id = inw(REG(PSS_ID)) & 0x00ff; - - /* - * Disable all emulations. Will be enabled later (if required). - */ - - disable_all_emulations(); - -#ifdef YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES - if (sound_alloc_dma(hw_config->dma, "PSS")) - { - printk("pss.c: Can't allocate DMA channel.\n"); - release_region(hw_config->io_base, 0x10); - release_region(hw_config->io_base+0x10, 0x9); - return 0; - } - if (!set_irq(devc, CONF_PSS, devc->irq)) - { - printk("PSS: IRQ allocation error.\n"); - release_region(hw_config->io_base, 0x10); - release_region(hw_config->io_base+0x10, 0x9); - return 0; - } - if (!set_dma(devc, CONF_PSS, devc->dma)) - { - printk(KERN_ERR "PSS: DMA allocation error\n"); - release_region(hw_config->io_base, 0x10); - release_region(hw_config->io_base+0x10, 0x9); - return 0; - } -#endif - - configure_nonsound_components(); - pss_initialized = 1; - sprintf(tmp, "ECHO-PSS Rev. %d", id); - conf_printf(tmp, hw_config); - return 1; -} - -static int __init probe_pss_mpu(struct address_info *hw_config) -{ - struct resource *ports; - int timeout; - - if (!pss_initialized) - return 0; - - ports = request_region(hw_config->io_base, 2, "mpu401"); - - if (!ports) { - printk(KERN_ERR "PSS: MPU I/O port conflict\n"); - return 0; - } - set_io_base(devc, CONF_MIDI, hw_config->io_base); - if (!set_irq(devc, CONF_MIDI, hw_config->irq)) { - printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n"); - goto fail; - } - if (!pss_synthLen) { - printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n"); - goto fail; - } - if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) { - printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); - goto fail; - } - - /* - * Finally wait until the DSP algorithm has initialized itself and - * deactivates receive interrupt. - */ - - for (timeout = 900000; timeout > 0; timeout--) - { - if ((inb(hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */ - inb(hw_config->io_base); /* Discard it */ - else - break; /* No more input */ - } - - if (!probe_mpu401(hw_config, ports)) - goto fail; - - attach_mpu401(hw_config, THIS_MODULE); /* Slot 1 */ - if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ - midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations; - return 1; -fail: - release_region(hw_config->io_base, 2); - return 0; -} - -static int pss_coproc_open(void *dev_info, int sub_device) -{ - switch (sub_device) - { - case COPR_MIDI: - if (pss_synthLen == 0) - { - printk(KERN_ERR "PSS: MIDI synth microcode not available.\n"); - return -EIO; - } - if (nonstandard_microcode) - if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) - { - printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); - return -EIO; - } - nonstandard_microcode = 0; - break; - - default: - break; - } - return 0; -} - -static void pss_coproc_close(void *dev_info, int sub_device) -{ - return; -} - -static void pss_coproc_reset(void *dev_info) -{ - if (pss_synthLen) - if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) - { - printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); - } - nonstandard_microcode = 0; -} - -static int download_boot_block(void *dev_info, copr_buffer * buf) -{ - if (buf->len <= 0 || buf->len > sizeof(buf->data)) - return -EINVAL; - - if (!pss_download_boot(devc, buf->data, buf->len, buf->flags)) - { - printk(KERN_ERR "PSS: Unable to load microcode block to DSP.\n"); - return -EIO; - } - nonstandard_microcode = 1; /* The MIDI microcode has been overwritten */ - return 0; -} - -static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local) -{ - copr_buffer *buf; - copr_msg *mbuf; - copr_debug_buf dbuf; - unsigned short tmp; - unsigned long flags; - unsigned short *data; - int i, err; - /* printk( "PSS coproc ioctl %x %x %d\n", cmd, arg, local); */ - - switch (cmd) - { - case SNDCTL_COPR_RESET: - pss_coproc_reset(dev_info); - return 0; - - case SNDCTL_COPR_LOAD: - buf = vmalloc(sizeof(copr_buffer)); - if (buf == NULL) - return -ENOSPC; - if (copy_from_user(buf, arg, sizeof(copr_buffer))) { - vfree(buf); - return -EFAULT; - } - err = download_boot_block(dev_info, buf); - vfree(buf); - return err; - - case SNDCTL_COPR_SENDMSG: - mbuf = vmalloc(sizeof(copr_msg)); - if (mbuf == NULL) - return -ENOSPC; - if (copy_from_user(mbuf, arg, sizeof(copr_msg))) { - vfree(mbuf); - return -EFAULT; - } - data = (unsigned short *)(mbuf->data); - spin_lock_irqsave(&lock, flags); - for (i = 0; i < mbuf->len; i++) { - if (!pss_put_dspword(devc, *data++)) { - spin_unlock_irqrestore(&lock,flags); - mbuf->len = i; /* feed back number of WORDs sent */ - err = copy_to_user(arg, mbuf, sizeof(copr_msg)); - vfree(mbuf); - return err ? -EFAULT : -EIO; - } - } - spin_unlock_irqrestore(&lock,flags); - vfree(mbuf); - return 0; - - case SNDCTL_COPR_RCVMSG: - err = 0; - mbuf = vmalloc(sizeof(copr_msg)); - if (mbuf == NULL) - return -ENOSPC; - data = (unsigned short *)mbuf->data; - spin_lock_irqsave(&lock, flags); - for (i = 0; i < sizeof(mbuf->data)/sizeof(unsigned short); i++) { - mbuf->len = i; /* feed back number of WORDs read */ - if (!pss_get_dspword(devc, data++)) { - if (i == 0) - err = -EIO; - break; - } - } - spin_unlock_irqrestore(&lock,flags); - if (copy_to_user(arg, mbuf, sizeof(copr_msg))) - err = -EFAULT; - vfree(mbuf); - return err; - - case SNDCTL_COPR_RDATA: - if (copy_from_user(&dbuf, arg, sizeof(dbuf))) - return -EFAULT; - spin_lock_irqsave(&lock, flags); - if (!pss_put_dspword(devc, 0x00d0)) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - if (!pss_get_dspword(devc, &tmp)) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - dbuf.parm1 = tmp; - spin_unlock_irqrestore(&lock,flags); - if (copy_to_user(arg, &dbuf, sizeof(dbuf))) - return -EFAULT; - return 0; - - case SNDCTL_COPR_WDATA: - if (copy_from_user(&dbuf, arg, sizeof(dbuf))) - return -EFAULT; - spin_lock_irqsave(&lock, flags); - if (!pss_put_dspword(devc, 0x00d1)) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - if (!pss_put_dspword(devc, (unsigned short) (dbuf.parm1 & 0xffff))) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - tmp = (unsigned int)dbuf.parm2 & 0xffff; - if (!pss_put_dspword(devc, tmp)) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - spin_unlock_irqrestore(&lock,flags); - return 0; - - case SNDCTL_COPR_WCODE: - if (copy_from_user(&dbuf, arg, sizeof(dbuf))) - return -EFAULT; - spin_lock_irqsave(&lock, flags); - if (!pss_put_dspword(devc, 0x00d3)) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - tmp = (unsigned int)dbuf.parm2 & 0x00ff; - if (!pss_put_dspword(devc, tmp)) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - tmp = ((unsigned int)dbuf.parm2 >> 8) & 0xffff; - if (!pss_put_dspword(devc, tmp)) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - spin_unlock_irqrestore(&lock,flags); - return 0; - - case SNDCTL_COPR_RCODE: - if (copy_from_user(&dbuf, arg, sizeof(dbuf))) - return -EFAULT; - spin_lock_irqsave(&lock, flags); - if (!pss_put_dspword(devc, 0x00d2)) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) { - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - if (!pss_get_dspword(devc, &tmp)) { /* Read MSB */ - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - dbuf.parm1 = tmp << 8; - if (!pss_get_dspword(devc, &tmp)) { /* Read LSB */ - spin_unlock_irqrestore(&lock,flags); - return -EIO; - } - dbuf.parm1 |= tmp & 0x00ff; - spin_unlock_irqrestore(&lock,flags); - if (copy_to_user(arg, &dbuf, sizeof(dbuf))) - return -EFAULT; - return 0; - - default: - return -EINVAL; - } - return -EINVAL; -} - -static coproc_operations pss_coproc_operations = -{ - "ADSP-2115", - THIS_MODULE, - pss_coproc_open, - pss_coproc_close, - pss_coproc_ioctl, - pss_coproc_reset, - &pss_data -}; - -static int __init probe_pss_mss(struct address_info *hw_config) -{ - volatile int timeout; - struct resource *ports; - int my_mix = -999; /* gcc shut up */ - - if (!pss_initialized) - return 0; - - if (!request_region(hw_config->io_base, 4, "WSS config")) { - printk(KERN_ERR "PSS: WSS I/O port conflicts.\n"); - return 0; - } - ports = request_region(hw_config->io_base + 4, 4, "ad1848"); - if (!ports) { - printk(KERN_ERR "PSS: WSS I/O port conflicts.\n"); - release_region(hw_config->io_base, 4); - return 0; - } - set_io_base(devc, CONF_WSS, hw_config->io_base); - if (!set_irq(devc, CONF_WSS, hw_config->irq)) { - printk("PSS: WSS IRQ allocation error.\n"); - goto fail; - } - if (!set_dma(devc, CONF_WSS, hw_config->dma)) { - printk(KERN_ERR "PSS: WSS DMA allocation error\n"); - goto fail; - } - /* - * For some reason the card returns 0xff in the WSS status register - * immediately after boot. Probably MIDI+SB emulation algorithm - * downloaded to the ADSP2115 spends some time initializing the card. - * Let's try to wait until it finishes this task. - */ - for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + WSS_INDEX) & - WSS_INITIALIZING); timeout++) - ; - - outb((0x0b), hw_config->io_base + WSS_INDEX); /* Required by some cards */ - - for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) && - (timeout < 100000); timeout++) - ; - - if (!probe_ms_sound(hw_config, ports)) - goto fail; - - devc->ad_mixer_dev = NO_WSS_MIXER; - if (pss_mixer) - { - if ((my_mix = sound_install_mixer (MIXER_DRIVER_VERSION, - "PSS-SPEAKERS and AD1848 (through MSS audio codec)", - &pss_mixer_operations, - sizeof (struct mixer_operations), - devc)) < 0) - { - printk(KERN_ERR "Could not install PSS mixer\n"); - goto fail; - } - } - pss_mixer_reset(devc); - attach_ms_sound(hw_config, ports, THIS_MODULE); /* Slot 0 */ - - if (hw_config->slots[0] != -1) - { - /* The MSS driver installed itself */ - audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations; - if (pss_mixer && (num_mixers == (my_mix + 2))) - { - /* The MSS mixer installed */ - devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev; - } - } - return 1; -fail: - release_region(hw_config->io_base + 4, 4); - release_region(hw_config->io_base, 4); - return 0; -} - -static inline void __exit unload_pss(struct address_info *hw_config) -{ - release_region(hw_config->io_base, 0x10); - release_region(hw_config->io_base+0x10, 0x9); -} - -static inline void __exit unload_pss_mpu(struct address_info *hw_config) -{ - unload_mpu401(hw_config); -} - -static inline void __exit unload_pss_mss(struct address_info *hw_config) -{ - unload_ms_sound(hw_config); -} - - -static struct address_info cfg; -static struct address_info cfg2; -static struct address_info cfg_mpu; - -static int pss_io __initdata = -1; -static int mss_io __initdata = -1; -static int mss_irq __initdata = -1; -static int mss_dma __initdata = -1; -static int mpu_io __initdata = -1; -static int mpu_irq __initdata = -1; -static bool pss_no_sound = 0; /* Just configure non-sound components */ -static bool pss_keep_settings = 1; /* Keep hardware settings at module exit */ -static char *pss_firmware = "/etc/sound/pss_synth"; - -module_param(pss_io, int, 0); -MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)"); -module_param(mss_io, int, 0); -MODULE_PARM_DESC(mss_io, "Set WSS (audio) i/o base (0x530, 0x604, 0xE80, 0xF40, or other. Address must end in 0 or 4 and must be from 0x100 to 0xFF4)"); -module_param(mss_irq, int, 0); -MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)"); -module_param(mss_dma, int, 0); -MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)"); -module_param(mpu_io, int, 0); -MODULE_PARM_DESC(mpu_io, "Set MIDI i/o base (0x330 or other. Address must be on 4 location boundaries and must be from 0x100 to 0xFFC)"); -module_param(mpu_irq, int, 0); -MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)"); -module_param(pss_cdrom_port, int, 0); -MODULE_PARM_DESC(pss_cdrom_port, "Set the PSS CDROM port i/o base (0x340 or other)"); -module_param(pss_enable_joystick, bool, 0); -MODULE_PARM_DESC(pss_enable_joystick, "Enables the PSS joystick port (1 to enable, 0 to disable)"); -module_param(pss_no_sound, bool, 0); -MODULE_PARM_DESC(pss_no_sound, "Configure sound compoents (0 - no, 1 - yes)"); -module_param(pss_keep_settings, bool, 0); -MODULE_PARM_DESC(pss_keep_settings, "Keep hardware setting at driver unloading (0 - no, 1 - yes)"); -module_param(pss_firmware, charp, 0); -MODULE_PARM_DESC(pss_firmware, "Location of the firmware file (default - /etc/sound/pss_synth)"); -module_param(pss_mixer, bool, 0); -MODULE_PARM_DESC(pss_mixer, "Enable (1) or disable (0) PSS mixer (controlling of output volume, bass, treble, synth volume). The mixer is not available on all PSS cards."); -MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl"); -MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards)."); -MODULE_LICENSE("GPL"); - - -static int fw_load = 0; -static int pssmpu = 0, pssmss = 0; - -/* - * Load a PSS sound card module - */ - -static int __init init_pss(void) -{ - - if(pss_no_sound) /* If configuring only nonsound components */ - { - cfg.io_base = pss_io; - if(!probe_pss(&cfg)) - return -ENODEV; - printk(KERN_INFO "ECHO-PSS Rev. %d\n", inw(REG(PSS_ID)) & 0x00ff); - printk(KERN_INFO "PSS: loading in no sound mode.\n"); - disable_all_emulations(); - configure_nonsound_components(); - release_region(pss_io, 0x10); - release_region(pss_io + 0x10, 0x9); - return 0; - } - - cfg.io_base = pss_io; - - cfg2.io_base = mss_io; - cfg2.irq = mss_irq; - cfg2.dma = mss_dma; - - cfg_mpu.io_base = mpu_io; - cfg_mpu.irq = mpu_irq; - - if (cfg.io_base == -1 || cfg2.io_base == -1 || cfg2.irq == -1 || cfg.dma == -1) { - printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n"); - return -EINVAL; - } - - if (!pss_synth) { - fw_load = 1; - pss_synthLen = mod_firmware_load(pss_firmware, (void *) &pss_synth); - } - if (!attach_pss(&cfg)) - return -ENODEV; - /* - * Attach stuff - */ - if (probe_pss_mpu(&cfg_mpu)) - pssmpu = 1; - - if (probe_pss_mss(&cfg2)) - pssmss = 1; - - return 0; -} - -static void __exit cleanup_pss(void) -{ - if(!pss_no_sound) - { - if(fw_load && pss_synth) - vfree(pss_synth); - if(pssmss) - unload_pss_mss(&cfg2); - if(pssmpu) - unload_pss_mpu(&cfg_mpu); - unload_pss(&cfg); - } else if (pss_cdrom_port != -1) - release_region(pss_cdrom_port, 2); - - if(!pss_keep_settings) /* Keep hardware settings if asked */ - { - disable_all_emulations(); - printk(KERN_INFO "Resetting PSS sound card configurations.\n"); - } -} - -module_init(init_pss); -module_exit(cleanup_pss); - -#ifndef MODULE -static int __init setup_pss(char *str) -{ - /* io, mss_io, mss_irq, mss_dma, mpu_io, mpu_irq */ - int ints[7]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - pss_io = ints[1]; - mss_io = ints[2]; - mss_irq = ints[3]; - mss_dma = ints[4]; - mpu_io = ints[5]; - mpu_irq = ints[6]; - - return 1; -} - -__setup("pss=", setup_pss); -#endif diff --git a/ANDROID_3.4.5/sound/oss/sb.h b/ANDROID_3.4.5/sound/oss/sb.h deleted file mode 100644 index 77e8891c..00000000 --- a/ANDROID_3.4.5/sound/oss/sb.h +++ /dev/null @@ -1,185 +0,0 @@ -#define DSP_RESET (devc->base + 0x6) -#define DSP_READ (devc->base + 0xA) -#define DSP_WRITE (devc->base + 0xC) -#define DSP_COMMAND (devc->base + 0xC) -#define DSP_STATUS (devc->base + 0xC) -#define DSP_DATA_AVAIL (devc->base + 0xE) -#define DSP_DATA_AVL16 (devc->base + 0xF) -#define MIXER_ADDR (devc->base + 0x4) -#define MIXER_DATA (devc->base + 0x5) -#define OPL3_LEFT (devc->base + 0x0) -#define OPL3_RIGHT (devc->base + 0x2) -#define OPL3_BOTH (devc->base + 0x8) -/* DSP Commands */ - -#define DSP_CMD_SPKON 0xD1 -#define DSP_CMD_SPKOFF 0xD3 -#define DSP_CMD_DMAON 0xD0 -#define DSP_CMD_DMAOFF 0xD4 - -#define IMODE_NONE 0 -#define IMODE_OUTPUT PCM_ENABLE_OUTPUT -#define IMODE_INPUT PCM_ENABLE_INPUT -#define IMODE_INIT 3 -#define IMODE_MIDI 4 - -#define NORMAL_MIDI 0 -#define UART_MIDI 1 - - -/* - * Device models - */ -#define MDL_NONE 0 -#define MDL_SB1 1 /* SB1.0 or 1.5 */ -#define MDL_SB2 2 /* SB2.0 */ -#define MDL_SB201 3 /* SB2.01 */ -#define MDL_SBPRO 4 /* SB Pro */ -#define MDL_SB16 5 /* SB16/32/AWE */ -#define MDL_SBPNP 6 /* SB16/32/AWE PnP */ -#define MDL_JAZZ 10 /* Media Vision Jazz16 */ -#define MDL_SMW 11 /* Logitech SoundMan Wave (Jazz16) */ -#define MDL_ESS 12 /* ESS ES688 and ES1688 */ -#define MDL_AZTECH 13 /* Aztech Sound Galaxy family */ -#define MDL_ES1868MIDI 14 /* MIDI port of ESS1868 */ -#define MDL_AEDSP 15 /* Audio Excel DSP 16 */ -#define MDL_ESSPCI 16 /* ESS PCI card */ -#define MDL_YMPCI 17 /* Yamaha PCI sb in emulation */ - -#define SUBMDL_ALS007 42 /* ALS-007 differs from SB16 only in mixer */ - /* register assignment */ -#define SUBMDL_ALS100 43 /* ALS-100 allows sampling rates of up */ - /* to 48kHz */ - -/* - * Config flags - */ -#define SB_NO_MIDI 0x00000001 -#define SB_NO_MIXER 0x00000002 -#define SB_NO_AUDIO 0x00000004 -#define SB_NO_RECORDING 0x00000008 /* No audio recording */ -#define SB_MIDI_ONLY (SB_NO_AUDIO|SB_NO_MIXER) -#define SB_PCI_IRQ 0x00000010 /* PCI shared IRQ */ - -struct mixer_def { - unsigned int regno: 8; - unsigned int bitoffs:4; - unsigned int nbits:4; -}; - -typedef struct mixer_def mixer_tab[32][2]; -typedef struct mixer_def mixer_ent; - -struct sb_module_options -{ - int esstype; /* ESS chip type */ - int acer; /* Do acer notebook init? */ - int sm_games; /* Logitech soundman games? */ -}; - -typedef struct sb_devc { - int dev; - - /* Hardware parameters */ - int *osp; - int minor, major; - int type; - int model, submodel; - int caps; -# define SBCAP_STEREO 0x00000001 -# define SBCAP_16BITS 0x00000002 - - /* Hardware resources */ - int base; - int irq; - int dma8, dma16; - - int pcibase; /* For ESS Maestro etc */ - - /* State variables */ - int opened; - /* new audio fields for full duplex support */ - int fullduplex; - int duplex; - int speed, bits, channels; - volatile int irq_ok; - volatile int intr_active, irq_mode; - /* duplicate audio fields for full duplex support */ - volatile int intr_active_16, irq_mode_16; - - /* Mixer fields */ - int *levels; - mixer_tab *iomap; - size_t iomap_sz; /* number or records in the iomap table */ - int mixer_caps, recmask, outmask, supported_devices; - int supported_rec_devices, supported_out_devices; - int my_mixerdev; - int sbmixnum; - - /* Audio fields */ - unsigned long trg_buf; - int trigger_bits; - int trg_bytes; - int trg_intrflag; - int trg_restart; - /* duplicate audio fields for full duplex support */ - unsigned long trg_buf_16; - int trigger_bits_16; - int trg_bytes_16; - int trg_intrflag_16; - int trg_restart_16; - - unsigned char tconst; - - /* MIDI fields */ - int my_mididev; - int input_opened; - int midi_broken; - void (*midi_input_intr) (int dev, unsigned char data); - void *midi_irq_cookie; /* IRQ cookie for the midi */ - - spinlock_t lock; - - struct sb_module_options sbmo; /* Module options */ - - } sb_devc; - -/* - * PCI card types - */ - -#define SB_PCI_ESSMAESTRO 1 /* ESS Maestro Legacy */ -#define SB_PCI_YAMAHA 2 /* Yamaha Legacy */ - -/* - * Functions - */ - -int sb_dsp_command (sb_devc *devc, unsigned char val); -int sb_dsp_get_byte(sb_devc * devc); -int sb_dsp_reset (sb_devc *devc); -void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value); -unsigned int sb_getmixer (sb_devc *devc, unsigned int port); -int sb_dsp_detect (struct address_info *hw_config, int pci, int pciio, struct sb_module_options *sbmo); -int sb_dsp_init (struct address_info *hw_config, struct module *owner); -void sb_dsp_unload(struct address_info *hw_config, int sbmpu); -int sb_mixer_init(sb_devc *devc, struct module *owner); -void sb_mixer_unload(sb_devc *devc); -void sb_mixer_set_stereo (sb_devc *devc, int mode); -void smw_mixer_init(sb_devc *devc); -void sb_dsp_midi_init (sb_devc *devc, struct module *owner); -void sb_audio_init (sb_devc *devc, char *name, struct module *owner); -void sb_midi_interrupt (sb_devc *devc); -void sb_chgmixer (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val); -int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right); - -int sb_audio_open(int dev, int mode); -void sb_audio_close(int dev); - -/* From sb_common.c */ -void sb_dsp_disable_midi(int port); -int probe_sbmpu (struct address_info *hw_config, struct module *owner); -void unload_sbmpu (struct address_info *hw_config); - -void unload_sb16(struct address_info *hw_info); -void unload_sb16midi(struct address_info *hw_info); diff --git a/ANDROID_3.4.5/sound/oss/sb_audio.c b/ANDROID_3.4.5/sound/oss/sb_audio.c deleted file mode 100644 index 733b014e..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_audio.c +++ /dev/null @@ -1,1098 +0,0 @@ -/* - * sound/oss/sb_audio.c - * - * Audio routines for Sound Blaster compatible cards. - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * Changes - * Alan Cox : Formatting and clean ups - * - * Status - * Mostly working. Weird uart bug causing irq storms - * - * Daniel J. Rodriksson: Changes to make sb16 work full duplex. - * Maybe other 16 bit cards in this code could behave - * the same. - * Chris Rankin: Use spinlocks instead of CLI/STI - */ - -#include - -#include "sound_config.h" - -#include "sb_mixer.h" -#include "sb.h" - -#include "sb_ess.h" - -int sb_audio_open(int dev, int mode) -{ - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; - - if (devc == NULL) - { - printk(KERN_ERR "Sound Blaster: incomplete initialization.\n"); - return -ENXIO; - } - if (devc->caps & SB_NO_RECORDING && mode & OPEN_READ) - { - if (mode == OPEN_READ) - return -EPERM; - } - spin_lock_irqsave(&devc->lock, flags); - if (devc->opened) - { - spin_unlock_irqrestore(&devc->lock, flags); - return -EBUSY; - } - if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex) - { - if (sound_open_dma(devc->dma16, "Sound Blaster 16 bit")) - { - spin_unlock_irqrestore(&devc->lock, flags); - return -EBUSY; - } - } - devc->opened = mode; - spin_unlock_irqrestore(&devc->lock, flags); - - devc->irq_mode = IMODE_NONE; - devc->irq_mode_16 = IMODE_NONE; - devc->fullduplex = devc->duplex && - ((mode & OPEN_READ) && (mode & OPEN_WRITE)); - sb_dsp_reset(devc); - - /* At first glance this check isn't enough, some ESS chips might not - * have a RECLEV. However if they don't common_mixer_set will refuse - * cause devc->iomap has no register mapping for RECLEV - */ - if (devc->model == MDL_ESS) ess_mixer_reload (devc, SOUND_MIXER_RECLEV); - - /* The ALS007 seems to require that the DSP be removed from the output */ - /* in order for recording to be activated properly. This is done by */ - /* setting the appropriate bits of the output control register 4ch to */ - /* zero. This code assumes that the output control registers are not */ - /* used anywhere else and therefore the DSP bits are *always* ON for */ - /* output and OFF for sampling. */ - - if (devc->submodel == SUBMDL_ALS007) - { - if (mode & OPEN_READ) - sb_setmixer(devc,ALS007_OUTPUT_CTRL2, - sb_getmixer(devc,ALS007_OUTPUT_CTRL2) & 0xf9); - else - sb_setmixer(devc,ALS007_OUTPUT_CTRL2, - sb_getmixer(devc,ALS007_OUTPUT_CTRL2) | 0x06); - } - return 0; -} - -void sb_audio_close(int dev) -{ - sb_devc *devc = audio_devs[dev]->devc; - - /* fix things if mmap turned off fullduplex */ - if(devc->duplex - && !devc->fullduplex - && (devc->opened & OPEN_READ) && (devc->opened & OPEN_WRITE)) - { - struct dma_buffparms *dmap_temp; - dmap_temp = audio_devs[dev]->dmap_out; - audio_devs[dev]->dmap_out = audio_devs[dev]->dmap_in; - audio_devs[dev]->dmap_in = dmap_temp; - } - audio_devs[dev]->dmap_out->dma = devc->dma8; - audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ? - devc->dma16 : devc->dma8; - - if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex) - sound_close_dma(devc->dma16); - - /* For ALS007, turn DSP output back on if closing the device for read */ - - if ((devc->submodel == SUBMDL_ALS007) && (devc->opened & OPEN_READ)) - { - sb_setmixer(devc,ALS007_OUTPUT_CTRL2, - sb_getmixer(devc,ALS007_OUTPUT_CTRL2) | 0x06); - } - devc->opened = 0; -} - -static void sb_set_output_parms(int dev, unsigned long buf, int nr_bytes, - int intrflag) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (!devc->fullduplex || devc->bits == AFMT_S16_LE) - { - devc->trg_buf = buf; - devc->trg_bytes = nr_bytes; - devc->trg_intrflag = intrflag; - devc->irq_mode = IMODE_OUTPUT; - } - else - { - devc->trg_buf_16 = buf; - devc->trg_bytes_16 = nr_bytes; - devc->trg_intrflag_16 = intrflag; - devc->irq_mode_16 = IMODE_OUTPUT; - } -} - -static void sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (!devc->fullduplex || devc->bits != AFMT_S16_LE) - { - devc->trg_buf = buf; - devc->trg_bytes = count; - devc->trg_intrflag = intrflag; - devc->irq_mode = IMODE_INPUT; - } - else - { - devc->trg_buf_16 = buf; - devc->trg_bytes_16 = count; - devc->trg_intrflag_16 = intrflag; - devc->irq_mode_16 = IMODE_INPUT; - } -} - -/* - * SB1.x compatible routines - */ - -static void sb1_audio_output_block(int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - unsigned long flags; - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - - /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */ - - if (audio_devs[dev]->dmap_out->dma > 3) - count >>= 1; - count--; - - devc->irq_mode = IMODE_OUTPUT; - - spin_lock_irqsave(&devc->lock, flags); - if (sb_dsp_command(devc, 0x14)) /* 8 bit DAC using DMA */ - { - sb_dsp_command(devc, (unsigned char) (count & 0xff)); - sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - } - else - printk(KERN_WARNING "Sound Blaster: unable to start DAC.\n"); - spin_unlock_irqrestore(&devc->lock, flags); - devc->intr_active = 1; -} - -static void sb1_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - unsigned long flags; - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - - /* - * Start a DMA input to the buffer pointed by dmaqtail - */ - - /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */ - - if (audio_devs[dev]->dmap_out->dma > 3) - count >>= 1; - count--; - - devc->irq_mode = IMODE_INPUT; - - spin_lock_irqsave(&devc->lock, flags); - if (sb_dsp_command(devc, 0x24)) /* 8 bit ADC using DMA */ - { - sb_dsp_command(devc, (unsigned char) (count & 0xff)); - sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - } - else - printk(KERN_ERR "Sound Blaster: unable to start ADC.\n"); - spin_unlock_irqrestore(&devc->lock, flags); - - devc->intr_active = 1; -} - -static void sb1_audio_trigger(int dev, int bits) -{ - sb_devc *devc = audio_devs[dev]->devc; - - bits &= devc->irq_mode; - - if (!bits) - sb_dsp_command(devc, 0xd0); /* Halt DMA */ - else - { - switch (devc->irq_mode) - { - case IMODE_INPUT: - sb1_audio_start_input(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - - case IMODE_OUTPUT: - sb1_audio_output_block(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - } - } - devc->trigger_bits = bits; -} - -static int sb1_audio_prepare_for_input(int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; - - spin_lock_irqsave(&devc->lock, flags); - if (sb_dsp_command(devc, 0x40)) - sb_dsp_command(devc, devc->tconst); - sb_dsp_command(devc, DSP_CMD_SPKOFF); - spin_unlock_irqrestore(&devc->lock, flags); - - devc->trigger_bits = 0; - return 0; -} - -static int sb1_audio_prepare_for_output(int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; - - spin_lock_irqsave(&devc->lock, flags); - if (sb_dsp_command(devc, 0x40)) - sb_dsp_command(devc, devc->tconst); - sb_dsp_command(devc, DSP_CMD_SPKON); - spin_unlock_irqrestore(&devc->lock, flags); - devc->trigger_bits = 0; - return 0; -} - -static int sb1_audio_set_speed(int dev, int speed) -{ - int max_speed = 23000; - sb_devc *devc = audio_devs[dev]->devc; - int tmp; - - if (devc->opened & OPEN_READ) - max_speed = 13000; - - if (speed > 0) - { - if (speed < 4000) - speed = 4000; - - if (speed > max_speed) - speed = max_speed; - - devc->tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff; - tmp = 256 - devc->tconst; - speed = (1000000 + tmp / 2) / tmp; - - devc->speed = speed; - } - return devc->speed; -} - -static short sb1_audio_set_channels(int dev, short channels) -{ - sb_devc *devc = audio_devs[dev]->devc; - return devc->channels = 1; -} - -static unsigned int sb1_audio_set_bits(int dev, unsigned int bits) -{ - sb_devc *devc = audio_devs[dev]->devc; - return devc->bits = 8; -} - -static void sb1_audio_halt_xfer(int dev) -{ - unsigned long flags; - sb_devc *devc = audio_devs[dev]->devc; - - spin_lock_irqsave(&devc->lock, flags); - sb_dsp_reset(devc); - spin_unlock_irqrestore(&devc->lock, flags); -} - -/* - * SB 2.0 and SB 2.01 compatible routines - */ - -static void sb20_audio_output_block(int dev, unsigned long buf, int nr_bytes, - int intrflag) -{ - unsigned long flags; - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - unsigned char cmd; - - /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */ - - if (audio_devs[dev]->dmap_out->dma > 3) - count >>= 1; - count--; - - devc->irq_mode = IMODE_OUTPUT; - - spin_lock_irqsave(&devc->lock, flags); - if (sb_dsp_command(devc, 0x48)) /* DSP Block size */ - { - sb_dsp_command(devc, (unsigned char) (count & 0xff)); - sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - - if (devc->speed * devc->channels <= 23000) - cmd = 0x1c; /* 8 bit PCM output */ - else - cmd = 0x90; /* 8 bit high speed PCM output (SB2.01/Pro) */ - - if (!sb_dsp_command(devc, cmd)) - printk(KERN_ERR "Sound Blaster: unable to start DAC.\n"); - } - else - printk(KERN_ERR "Sound Blaster: unable to start DAC.\n"); - spin_unlock_irqrestore(&devc->lock, flags); - devc->intr_active = 1; -} - -static void sb20_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - unsigned long flags; - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - unsigned char cmd; - - /* - * Start a DMA input to the buffer pointed by dmaqtail - */ - - /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */ - - if (audio_devs[dev]->dmap_out->dma > 3) - count >>= 1; - count--; - - devc->irq_mode = IMODE_INPUT; - - spin_lock_irqsave(&devc->lock, flags); - if (sb_dsp_command(devc, 0x48)) /* DSP Block size */ - { - sb_dsp_command(devc, (unsigned char) (count & 0xff)); - sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - - if (devc->speed * devc->channels <= (devc->major == 3 ? 23000 : 13000)) - cmd = 0x2c; /* 8 bit PCM input */ - else - cmd = 0x98; /* 8 bit high speed PCM input (SB2.01/Pro) */ - - if (!sb_dsp_command(devc, cmd)) - printk(KERN_ERR "Sound Blaster: unable to start ADC.\n"); - } - else - printk(KERN_ERR "Sound Blaster: unable to start ADC.\n"); - spin_unlock_irqrestore(&devc->lock, flags); - devc->intr_active = 1; -} - -static void sb20_audio_trigger(int dev, int bits) -{ - sb_devc *devc = audio_devs[dev]->devc; - bits &= devc->irq_mode; - - if (!bits) - sb_dsp_command(devc, 0xd0); /* Halt DMA */ - else - { - switch (devc->irq_mode) - { - case IMODE_INPUT: - sb20_audio_start_input(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - - case IMODE_OUTPUT: - sb20_audio_output_block(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - } - } - devc->trigger_bits = bits; -} - -/* - * SB2.01 specific speed setup - */ - -static int sb201_audio_set_speed(int dev, int speed) -{ - sb_devc *devc = audio_devs[dev]->devc; - int tmp; - int s = speed * devc->channels; - - if (speed > 0) - { - if (speed < 4000) - speed = 4000; - if (speed > 44100) - speed = 44100; - if (devc->opened & OPEN_READ && speed > 15000) - speed = 15000; - devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff; - tmp = 256 - devc->tconst; - speed = ((1000000 + tmp / 2) / tmp) / devc->channels; - - devc->speed = speed; - } - return devc->speed; -} - -/* - * SB Pro specific routines - */ - -static int sbpro_audio_prepare_for_input(int dev, int bsize, int bcount) -{ /* For SB Pro and Jazz16 */ - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; - unsigned char bits = 0; - - if (devc->dma16 >= 0 && devc->dma16 != devc->dma8) - audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma = - devc->bits == 16 ? devc->dma16 : devc->dma8; - - if (devc->model == MDL_JAZZ || devc->model == MDL_SMW) - if (devc->bits == AFMT_S16_LE) - bits = 0x04; /* 16 bit mode */ - - spin_lock_irqsave(&devc->lock, flags); - if (sb_dsp_command(devc, 0x40)) - sb_dsp_command(devc, devc->tconst); - sb_dsp_command(devc, DSP_CMD_SPKOFF); - if (devc->channels == 1) - sb_dsp_command(devc, 0xa0 | bits); /* Mono input */ - else - sb_dsp_command(devc, 0xa8 | bits); /* Stereo input */ - spin_unlock_irqrestore(&devc->lock, flags); - - devc->trigger_bits = 0; - return 0; -} - -static int sbpro_audio_prepare_for_output(int dev, int bsize, int bcount) -{ /* For SB Pro and Jazz16 */ - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; - unsigned char tmp; - unsigned char bits = 0; - - if (devc->dma16 >= 0 && devc->dma16 != devc->dma8) - audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma = devc->bits == 16 ? devc->dma16 : devc->dma8; - if (devc->model == MDL_SBPRO) - sb_mixer_set_stereo(devc, devc->channels == 2); - - spin_lock_irqsave(&devc->lock, flags); - if (sb_dsp_command(devc, 0x40)) - sb_dsp_command(devc, devc->tconst); - sb_dsp_command(devc, DSP_CMD_SPKON); - - if (devc->model == MDL_JAZZ || devc->model == MDL_SMW) - { - if (devc->bits == AFMT_S16_LE) - bits = 0x04; /* 16 bit mode */ - - if (devc->channels == 1) - sb_dsp_command(devc, 0xa0 | bits); /* Mono output */ - else - sb_dsp_command(devc, 0xa8 | bits); /* Stereo output */ - spin_unlock_irqrestore(&devc->lock, flags); - } - else - { - spin_unlock_irqrestore(&devc->lock, flags); - tmp = sb_getmixer(devc, 0x0e); - if (devc->channels == 1) - tmp &= ~0x02; - else - tmp |= 0x02; - sb_setmixer(devc, 0x0e, tmp); - } - devc->trigger_bits = 0; - return 0; -} - -static int sbpro_audio_set_speed(int dev, int speed) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (speed > 0) - { - if (speed < 4000) - speed = 4000; - if (speed > 44100) - speed = 44100; - if (devc->channels > 1 && speed > 22050) - speed = 22050; - sb201_audio_set_speed(dev, speed); - } - return devc->speed; -} - -static short sbpro_audio_set_channels(int dev, short channels) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (channels == 1 || channels == 2) - { - if (channels != devc->channels) - { - devc->channels = channels; - if (devc->model == MDL_SBPRO && devc->channels == 2) - sbpro_audio_set_speed(dev, devc->speed); - } - } - return devc->channels; -} - -static int jazz16_audio_set_speed(int dev, int speed) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (speed > 0) - { - int tmp; - int s = speed * devc->channels; - - if (speed < 5000) - speed = 5000; - if (speed > 44100) - speed = 44100; - - devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff; - - tmp = 256 - devc->tconst; - speed = ((1000000 + tmp / 2) / tmp) / devc->channels; - - devc->speed = speed; - } - return devc->speed; -} - -/* - * SB16 specific routines - */ - -static int sb16_audio_set_speed(int dev, int speed) -{ - sb_devc *devc = audio_devs[dev]->devc; - int max_speed = devc->submodel == SUBMDL_ALS100 ? 48000 : 44100; - - if (speed > 0) - { - if (speed < 5000) - speed = 5000; - - if (speed > max_speed) - speed = max_speed; - - devc->speed = speed; - } - return devc->speed; -} - -static unsigned int sb16_audio_set_bits(int dev, unsigned int bits) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (bits != 0) - { - if (bits == AFMT_U8 || bits == AFMT_S16_LE) - devc->bits = bits; - else - devc->bits = AFMT_U8; - } - - return devc->bits; -} - -static int sb16_audio_prepare_for_input(int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (!devc->fullduplex) - { - audio_devs[dev]->dmap_out->dma = - audio_devs[dev]->dmap_in->dma = - devc->bits == AFMT_S16_LE ? - devc->dma16 : devc->dma8; - } - else if (devc->bits == AFMT_S16_LE) - { - audio_devs[dev]->dmap_out->dma = devc->dma8; - audio_devs[dev]->dmap_in->dma = devc->dma16; - } - else - { - audio_devs[dev]->dmap_out->dma = devc->dma16; - audio_devs[dev]->dmap_in->dma = devc->dma8; - } - - devc->trigger_bits = 0; - return 0; -} - -static int sb16_audio_prepare_for_output(int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (!devc->fullduplex) - { - audio_devs[dev]->dmap_out->dma = - audio_devs[dev]->dmap_in->dma = - devc->bits == AFMT_S16_LE ? - devc->dma16 : devc->dma8; - } - else if (devc->bits == AFMT_S16_LE) - { - audio_devs[dev]->dmap_out->dma = devc->dma8; - audio_devs[dev]->dmap_in->dma = devc->dma16; - } - else - { - audio_devs[dev]->dmap_out->dma = devc->dma16; - audio_devs[dev]->dmap_in->dma = devc->dma8; - } - - devc->trigger_bits = 0; - return 0; -} - -static void sb16_audio_output_block(int dev, unsigned long buf, int count, - int intrflag) -{ - unsigned long flags, cnt; - sb_devc *devc = audio_devs[dev]->devc; - unsigned long bits; - - if (!devc->fullduplex || devc->bits == AFMT_S16_LE) - { - devc->irq_mode = IMODE_OUTPUT; - devc->intr_active = 1; - } - else - { - devc->irq_mode_16 = IMODE_OUTPUT; - devc->intr_active_16 = 1; - } - - /* save value */ - spin_lock_irqsave(&devc->lock, flags); - bits = devc->bits; - if (devc->fullduplex) - devc->bits = (devc->bits == AFMT_S16_LE) ? - AFMT_U8 : AFMT_S16_LE; - spin_unlock_irqrestore(&devc->lock, flags); - - cnt = count; - if (devc->bits == AFMT_S16_LE) - cnt >>= 1; - cnt--; - - spin_lock_irqsave(&devc->lock, flags); - - /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */ - - sb_dsp_command(devc, 0x41); - sb_dsp_command(devc, (unsigned char) ((devc->speed >> 8) & 0xff)); - sb_dsp_command(devc, (unsigned char) (devc->speed & 0xff)); - - sb_dsp_command(devc, (devc->bits == AFMT_S16_LE ? 0xb6 : 0xc6)); - sb_dsp_command(devc, ((devc->channels == 2 ? 0x20 : 0) + - (devc->bits == AFMT_S16_LE ? 0x10 : 0))); - sb_dsp_command(devc, (unsigned char) (cnt & 0xff)); - sb_dsp_command(devc, (unsigned char) (cnt >> 8)); - - /* restore real value after all programming */ - devc->bits = bits; - spin_unlock_irqrestore(&devc->lock, flags); -} - - -/* - * This fails on the Cyrix MediaGX. If you don't have the DMA enabled - * before the first sample arrives it locks up. However even if you - * do enable the DMA in time you just get DMA timeouts and missing - * interrupts and stuff, so for now I've not bothered fixing this either. - */ - -static void sb16_audio_start_input(int dev, unsigned long buf, int count, int intrflag) -{ - unsigned long flags, cnt; - sb_devc *devc = audio_devs[dev]->devc; - - if (!devc->fullduplex || devc->bits != AFMT_S16_LE) - { - devc->irq_mode = IMODE_INPUT; - devc->intr_active = 1; - } - else - { - devc->irq_mode_16 = IMODE_INPUT; - devc->intr_active_16 = 1; - } - - cnt = count; - if (devc->bits == AFMT_S16_LE) - cnt >>= 1; - cnt--; - - spin_lock_irqsave(&devc->lock, flags); - - /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */ - - sb_dsp_command(devc, 0x42); - sb_dsp_command(devc, (unsigned char) ((devc->speed >> 8) & 0xff)); - sb_dsp_command(devc, (unsigned char) (devc->speed & 0xff)); - - sb_dsp_command(devc, (devc->bits == AFMT_S16_LE ? 0xbe : 0xce)); - sb_dsp_command(devc, ((devc->channels == 2 ? 0x20 : 0) + - (devc->bits == AFMT_S16_LE ? 0x10 : 0))); - sb_dsp_command(devc, (unsigned char) (cnt & 0xff)); - sb_dsp_command(devc, (unsigned char) (cnt >> 8)); - - spin_unlock_irqrestore(&devc->lock, flags); -} - -static void sb16_audio_trigger(int dev, int bits) -{ - sb_devc *devc = audio_devs[dev]->devc; - - int bits_16 = bits & devc->irq_mode_16; - bits &= devc->irq_mode; - - if (!bits && !bits_16) - sb_dsp_command(devc, 0xd0); /* Halt DMA */ - else - { - if (bits) - { - switch (devc->irq_mode) - { - case IMODE_INPUT: - sb16_audio_start_input(dev, - devc->trg_buf, - devc->trg_bytes, - devc->trg_intrflag); - break; - - case IMODE_OUTPUT: - sb16_audio_output_block(dev, - devc->trg_buf, - devc->trg_bytes, - devc->trg_intrflag); - break; - } - } - if (bits_16) - { - switch (devc->irq_mode_16) - { - case IMODE_INPUT: - sb16_audio_start_input(dev, - devc->trg_buf_16, - devc->trg_bytes_16, - devc->trg_intrflag_16); - break; - - case IMODE_OUTPUT: - sb16_audio_output_block(dev, - devc->trg_buf_16, - devc->trg_bytes_16, - devc->trg_intrflag_16); - break; - } - } - } - - devc->trigger_bits = bits | bits_16; -} - -static unsigned char lbuf8[2048]; -static signed short *lbuf16 = (signed short *)lbuf8; -#define LBUFCOPYSIZE 1024 -static void -sb16_copy_from_user(int dev, - char *localbuf, int localoffs, - const char __user *userbuf, int useroffs, - int max_in, int max_out, - int *used, int *returned, - int len) -{ - sb_devc *devc = audio_devs[dev]->devc; - int i, c, p, locallen; - unsigned char *buf8; - signed short *buf16; - - /* if not duplex no conversion */ - if (!devc->fullduplex) - { - if (copy_from_user(localbuf + localoffs, - userbuf + useroffs, len)) - return; - *used = len; - *returned = len; - } - else if (devc->bits == AFMT_S16_LE) - { - /* 16 -> 8 */ - /* max_in >> 1, max number of samples in ( 16 bits ) */ - /* max_out, max number of samples out ( 8 bits ) */ - /* len, number of samples that will be taken ( 16 bits )*/ - /* c, count of samples remaining in buffer ( 16 bits )*/ - /* p, count of samples already processed ( 16 bits )*/ - len = ( (max_in >> 1) > max_out) ? max_out : (max_in >> 1); - c = len; - p = 0; - buf8 = (unsigned char *)(localbuf + localoffs); - while (c) - { - locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c); - /* << 1 in order to get 16 bit samples */ - if (copy_from_user(lbuf16, - userbuf + useroffs + (p << 1), - locallen << 1)) - return; - for (i = 0; i < locallen; i++) - { - buf8[p+i] = ~((lbuf16[i] >> 8) & 0xff) ^ 0x80; - } - c -= locallen; p += locallen; - } - /* used = ( samples * 16 bits size ) */ - *used = max_in > ( max_out << 1) ? (max_out << 1) : max_in; - /* returned = ( samples * 8 bits size ) */ - *returned = len; - } - else - { - /* 8 -> 16 */ - /* max_in, max number of samples in ( 8 bits ) */ - /* max_out >> 1, max number of samples out ( 16 bits ) */ - /* len, number of samples that will be taken ( 8 bits )*/ - /* c, count of samples remaining in buffer ( 8 bits )*/ - /* p, count of samples already processed ( 8 bits )*/ - len = max_in > (max_out >> 1) ? (max_out >> 1) : max_in; - c = len; - p = 0; - buf16 = (signed short *)(localbuf + localoffs); - while (c) - { - locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c); - if (copy_from_user(lbuf8, - userbuf+useroffs + p, - locallen)) - return; - for (i = 0; i < locallen; i++) - { - buf16[p+i] = (~lbuf8[i] ^ 0x80) << 8; - } - c -= locallen; p += locallen; - } - /* used = ( samples * 8 bits size ) */ - *used = len; - /* returned = ( samples * 16 bits size ) */ - *returned = len << 1; - } -} - -static void -sb16_audio_mmap(int dev) -{ - sb_devc *devc = audio_devs[dev]->devc; - devc->fullduplex = 0; -} - -static struct audio_driver sb1_audio_driver = /* SB1.x */ -{ - .owner = THIS_MODULE, - .open = sb_audio_open, - .close = sb_audio_close, - .output_block = sb_set_output_parms, - .start_input = sb_set_input_parms, - .prepare_for_input = sb1_audio_prepare_for_input, - .prepare_for_output = sb1_audio_prepare_for_output, - .halt_io = sb1_audio_halt_xfer, - .trigger = sb1_audio_trigger, - .set_speed = sb1_audio_set_speed, - .set_bits = sb1_audio_set_bits, - .set_channels = sb1_audio_set_channels -}; - -static struct audio_driver sb20_audio_driver = /* SB2.0 */ -{ - .owner = THIS_MODULE, - .open = sb_audio_open, - .close = sb_audio_close, - .output_block = sb_set_output_parms, - .start_input = sb_set_input_parms, - .prepare_for_input = sb1_audio_prepare_for_input, - .prepare_for_output = sb1_audio_prepare_for_output, - .halt_io = sb1_audio_halt_xfer, - .trigger = sb20_audio_trigger, - .set_speed = sb1_audio_set_speed, - .set_bits = sb1_audio_set_bits, - .set_channels = sb1_audio_set_channels -}; - -static struct audio_driver sb201_audio_driver = /* SB2.01 */ -{ - .owner = THIS_MODULE, - .open = sb_audio_open, - .close = sb_audio_close, - .output_block = sb_set_output_parms, - .start_input = sb_set_input_parms, - .prepare_for_input = sb1_audio_prepare_for_input, - .prepare_for_output = sb1_audio_prepare_for_output, - .halt_io = sb1_audio_halt_xfer, - .trigger = sb20_audio_trigger, - .set_speed = sb201_audio_set_speed, - .set_bits = sb1_audio_set_bits, - .set_channels = sb1_audio_set_channels -}; - -static struct audio_driver sbpro_audio_driver = /* SB Pro */ -{ - .owner = THIS_MODULE, - .open = sb_audio_open, - .close = sb_audio_close, - .output_block = sb_set_output_parms, - .start_input = sb_set_input_parms, - .prepare_for_input = sbpro_audio_prepare_for_input, - .prepare_for_output = sbpro_audio_prepare_for_output, - .halt_io = sb1_audio_halt_xfer, - .trigger = sb20_audio_trigger, - .set_speed = sbpro_audio_set_speed, - .set_bits = sb1_audio_set_bits, - .set_channels = sbpro_audio_set_channels -}; - -static struct audio_driver jazz16_audio_driver = /* Jazz16 and SM Wave */ -{ - .owner = THIS_MODULE, - .open = sb_audio_open, - .close = sb_audio_close, - .output_block = sb_set_output_parms, - .start_input = sb_set_input_parms, - .prepare_for_input = sbpro_audio_prepare_for_input, - .prepare_for_output = sbpro_audio_prepare_for_output, - .halt_io = sb1_audio_halt_xfer, - .trigger = sb20_audio_trigger, - .set_speed = jazz16_audio_set_speed, - .set_bits = sb16_audio_set_bits, - .set_channels = sbpro_audio_set_channels -}; - -static struct audio_driver sb16_audio_driver = /* SB16 */ -{ - .owner = THIS_MODULE, - .open = sb_audio_open, - .close = sb_audio_close, - .output_block = sb_set_output_parms, - .start_input = sb_set_input_parms, - .prepare_for_input = sb16_audio_prepare_for_input, - .prepare_for_output = sb16_audio_prepare_for_output, - .halt_io = sb1_audio_halt_xfer, - .copy_user = sb16_copy_from_user, - .trigger = sb16_audio_trigger, - .set_speed = sb16_audio_set_speed, - .set_bits = sb16_audio_set_bits, - .set_channels = sbpro_audio_set_channels, - .mmap = sb16_audio_mmap -}; - -void sb_audio_init(sb_devc * devc, char *name, struct module *owner) -{ - int audio_flags = 0; - int format_mask = AFMT_U8; - - struct audio_driver *driver = &sb1_audio_driver; - - switch (devc->model) - { - case MDL_SB1: /* SB1.0 or SB 1.5 */ - DDB(printk("Will use standard SB1.x driver\n")); - audio_flags = DMA_HARDSTOP; - break; - - case MDL_SB2: - DDB(printk("Will use SB2.0 driver\n")); - audio_flags = DMA_AUTOMODE; - driver = &sb20_audio_driver; - break; - - case MDL_SB201: - DDB(printk("Will use SB2.01 (high speed) driver\n")); - audio_flags = DMA_AUTOMODE; - driver = &sb201_audio_driver; - break; - - case MDL_JAZZ: - case MDL_SMW: - DDB(printk("Will use Jazz16 driver\n")); - audio_flags = DMA_AUTOMODE; - format_mask |= AFMT_S16_LE; - driver = &jazz16_audio_driver; - break; - - case MDL_ESS: - DDB(printk("Will use ESS ES688/1688 driver\n")); - driver = ess_audio_init (devc, &audio_flags, &format_mask); - break; - - case MDL_SB16: - DDB(printk("Will use SB16 driver\n")); - audio_flags = DMA_AUTOMODE; - format_mask |= AFMT_S16_LE; - if (devc->dma8 != devc->dma16 && devc->dma16 != -1) - { - audio_flags |= DMA_DUPLEX; - devc->duplex = 1; - } - driver = &sb16_audio_driver; - break; - - default: - DDB(printk("Will use SB Pro driver\n")); - audio_flags = DMA_AUTOMODE; - driver = &sbpro_audio_driver; - } - - if (owner) - driver->owner = owner; - - if ((devc->dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, - name,driver, sizeof(struct audio_driver), - audio_flags, format_mask, devc, - devc->dma8, - devc->duplex ? devc->dma16 : devc->dma8)) < 0) - { - printk(KERN_ERR "Sound Blaster: unable to install audio.\n"); - return; - } - audio_devs[devc->dev]->mixer_dev = devc->my_mixerdev; - audio_devs[devc->dev]->min_fragment = 5; -} diff --git a/ANDROID_3.4.5/sound/oss/sb_card.c b/ANDROID_3.4.5/sound/oss/sb_card.c deleted file mode 100644 index fb5d7250..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_card.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * sound/oss/sb_card.c - * - * Detection routine for the ISA Sound Blaster and compatible sound - * cards. - * - * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this - * software for more info. - * - * This is a complete rewrite of the detection routines. This was - * prompted by the PnP API change during v2.5 and the ugly state the - * code was in. - * - * Copyright (C) by Paul Laufer 2002. Based on code originally by - * Hannu Savolainen which was modified by many others over the - * years. Authors specifically mentioned in the previous version were: - * Daniel Stone, Alessandro Zummo, Jeff Garzik, Arnaldo Carvalho de - * Melo, Daniel Church, and myself. - * - * 02-05-2003 Original Release, Paul Laufer - * 02-07-2003 Bug made it into first release. Take two. - */ - -#include -#include -#include -#include -#include "sound_config.h" -#include "sb_mixer.h" -#include "sb.h" -#ifdef CONFIG_PNP -#include -#endif /* CONFIG_PNP */ -#include "sb_card.h" - -MODULE_DESCRIPTION("OSS Soundblaster ISA PnP and legacy sound driver"); -MODULE_LICENSE("GPL"); - -extern void *smw_free; - -static int __initdata mpu_io = 0; -static int __initdata io = -1; -static int __initdata irq = -1; -static int __initdata dma = -1; -static int __initdata dma16 = -1; -static int __initdata type = 0; /* Can set this to a specific card type */ -static int __initdata esstype = 0; /* ESS chip type */ -static int __initdata acer = 0; /* Do acer notebook init? */ -static int __initdata sm_games = 0; /* Logitech soundman games? */ - -static struct sb_card_config *legacy = NULL; - -#ifdef CONFIG_PNP -static int pnp_registered; -static int __initdata pnp = 1; -/* -static int __initdata uart401 = 0; -*/ -#else -static int __initdata pnp = 0; -#endif - -module_param(io, int, 000); -MODULE_PARM_DESC(io, "Soundblaster i/o base address (0x220,0x240,0x260,0x280)"); -module_param(irq, int, 000); -MODULE_PARM_DESC(irq, "IRQ (5,7,9,10)"); -module_param(dma, int, 000); -MODULE_PARM_DESC(dma, "8-bit DMA channel (0,1,3)"); -module_param(dma16, int, 000); -MODULE_PARM_DESC(dma16, "16-bit DMA channel (5,6,7)"); -module_param(mpu_io, int, 000); -MODULE_PARM_DESC(mpu_io, "MPU base address"); -module_param(type, int, 000); -MODULE_PARM_DESC(type, "You can set this to specific card type (doesn't " \ - "work with pnp)"); -module_param(sm_games, int, 000); -MODULE_PARM_DESC(sm_games, "Enable support for Logitech soundman games " \ - "(doesn't work with pnp)"); -module_param(esstype, int, 000); -MODULE_PARM_DESC(esstype, "ESS chip type (doesn't work with pnp)"); -module_param(acer, int, 000); -MODULE_PARM_DESC(acer, "Set this to detect cards in some ACER notebooks "\ - "(doesn't work with pnp)"); - -#ifdef CONFIG_PNP -module_param(pnp, int, 000); -MODULE_PARM_DESC(pnp, "Went set to 0 will disable detection using PnP. "\ - "Default is 1.\n"); -/* Not done yet.... */ -/* -module_param(uart401, int, 000); -MODULE_PARM_DESC(uart401, "When set to 1, will attempt to detect and enable"\ - "the mpu on some clones"); -*/ -#endif /* CONFIG_PNP */ - -/* OSS subsystem card registration shared by PnP and legacy routines */ -static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo) -{ - if (!request_region(scc->conf.io_base, 16, "soundblaster")) { - printk(KERN_ERR "sb: ports busy.\n"); - kfree(scc); - return -EBUSY; - } - - if (!sb_dsp_detect(&scc->conf, 0, 0, sbmo)) { - release_region(scc->conf.io_base, 16); - printk(KERN_ERR "sb: Failed DSP Detect.\n"); - kfree(scc); - return -ENODEV; - } - if(!sb_dsp_init(&scc->conf, THIS_MODULE)) { - printk(KERN_ERR "sb: Failed DSP init.\n"); - kfree(scc); - return -ENODEV; - } - if(scc->mpucnf.io_base > 0) { - scc->mpu = 1; - printk(KERN_INFO "sb: Turning on MPU\n"); - if(!probe_sbmpu(&scc->mpucnf, THIS_MODULE)) - scc->mpu = 0; - } - - return 1; -} - -static void sb_unload(struct sb_card_config *scc) -{ - sb_dsp_unload(&scc->conf, 0); - if(scc->mpu) - unload_sbmpu(&scc->mpucnf); - kfree(scc); -} - -/* Register legacy card with OSS subsystem */ -static int __init sb_init_legacy(void) -{ - struct sb_module_options sbmo = {0}; - - if((legacy = kzalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) { - printk(KERN_ERR "sb: Error: Could not allocate memory\n"); - return -ENOMEM; - } - - legacy->conf.io_base = io; - legacy->conf.irq = irq; - legacy->conf.dma = dma; - legacy->conf.dma2 = dma16; - legacy->conf.card_subtype = type; - - legacy->mpucnf.io_base = mpu_io; - legacy->mpucnf.irq = -1; - legacy->mpucnf.dma = -1; - legacy->mpucnf.dma2 = -1; - - sbmo.esstype = esstype; - sbmo.sm_games = sm_games; - sbmo.acer = acer; - - return sb_register_oss(legacy, &sbmo); -} - -#ifdef CONFIG_PNP - -/* Populate the OSS subsystem structures with information from PnP */ -static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc) -{ - scc->conf.io_base = -1; - scc->conf.irq = -1; - scc->conf.dma = -1; - scc->conf.dma2 = -1; - scc->mpucnf.io_base = -1; - scc->mpucnf.irq = -1; - scc->mpucnf.dma = -1; - scc->mpucnf.dma2 = -1; - - /* All clones layout their PnP tables differently and some use - different logical devices for the MPU */ - if(!strncmp("CTL",scc->card_id,3)) { - scc->conf.io_base = pnp_port_start(dev,0); - scc->conf.irq = pnp_irq(dev,0); - scc->conf.dma = pnp_dma(dev,0); - scc->conf.dma2 = pnp_dma(dev,1); - scc->mpucnf.io_base = pnp_port_start(dev,1); - return; - } - if(!strncmp("tBA",scc->card_id,3)) { - scc->conf.io_base = pnp_port_start(dev,0); - scc->conf.irq = pnp_irq(dev,0); - scc->conf.dma = pnp_dma(dev,0); - scc->conf.dma2 = pnp_dma(dev,1); - return; - } - if(!strncmp("ESS",scc->card_id,3)) { - scc->conf.io_base = pnp_port_start(dev,0); - scc->conf.irq = pnp_irq(dev,0); - scc->conf.dma = pnp_dma(dev,0); - scc->conf.dma2 = pnp_dma(dev,1); - scc->mpucnf.io_base = pnp_port_start(dev,2); - return; - } - if(!strncmp("CMI",scc->card_id,3)) { - scc->conf.io_base = pnp_port_start(dev,0); - scc->conf.irq = pnp_irq(dev,0); - scc->conf.dma = pnp_dma(dev,0); - scc->conf.dma2 = pnp_dma(dev,1); - return; - } - if(!strncmp("RWB",scc->card_id,3)) { - scc->conf.io_base = pnp_port_start(dev,0); - scc->conf.irq = pnp_irq(dev,0); - scc->conf.dma = pnp_dma(dev,0); - return; - } - if(!strncmp("ALS",scc->card_id,3)) { - if(!strncmp("ALS0007",scc->card_id,7)) { - scc->conf.io_base = pnp_port_start(dev,0); - scc->conf.irq = pnp_irq(dev,0); - scc->conf.dma = pnp_dma(dev,0); - } else { - scc->conf.io_base = pnp_port_start(dev,0); - scc->conf.irq = pnp_irq(dev,0); - scc->conf.dma = pnp_dma(dev,1); - scc->conf.dma2 = pnp_dma(dev,0); - } - return; - } - if(!strncmp("RTL",scc->card_id,3)) { - scc->conf.io_base = pnp_port_start(dev,0); - scc->conf.irq = pnp_irq(dev,0); - scc->conf.dma = pnp_dma(dev,1); - scc->conf.dma2 = pnp_dma(dev,0); - } -} - -static unsigned int sb_pnp_devices; - -/* Probe callback function for the PnP API */ -static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device_id *card_id) -{ - struct sb_card_config *scc; - struct sb_module_options sbmo = {0}; /* Default to 0 for PnP */ - struct pnp_dev *dev = pnp_request_card_device(card, card_id->devs[0].id, NULL); - - if(!dev){ - return -EBUSY; - } - - if((scc = kzalloc(sizeof(struct sb_card_config), GFP_KERNEL)) == NULL) { - printk(KERN_ERR "sb: Error: Could not allocate memory\n"); - return -ENOMEM; - } - - printk(KERN_INFO "sb: PnP: Found Card Named = \"%s\", Card PnP id = " \ - "%s, Device PnP id = %s\n", card->card->name, card_id->id, - dev->id->id); - - scc->card_id = card_id->id; - scc->dev_id = dev->id->id; - sb_dev2cfg(dev, scc); - - printk(KERN_INFO "sb: PnP: Detected at: io=0x%x, irq=%d, " \ - "dma=%d, dma16=%d\n", scc->conf.io_base, scc->conf.irq, - scc->conf.dma, scc->conf.dma2); - - pnp_set_card_drvdata(card, scc); - sb_pnp_devices++; - - return sb_register_oss(scc, &sbmo); -} - -static void sb_pnp_remove(struct pnp_card_link *card) -{ - struct sb_card_config *scc = pnp_get_card_drvdata(card); - - if(!scc) - return; - - printk(KERN_INFO "sb: PnP: Removing %s\n", scc->card_id); - - sb_unload(scc); -} - -static struct pnp_card_driver sb_pnp_driver = { - .name = "OSS SndBlstr", /* 16 character limit */ - .id_table = sb_pnp_card_table, - .probe = sb_pnp_probe, - .remove = sb_pnp_remove, -}; -MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table); -#endif /* CONFIG_PNP */ - -static void sb_unregister_all(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&sb_pnp_driver); -#endif -} - -static int __init sb_init(void) -{ - int lres = 0; - int pres = 0; - - printk(KERN_INFO "sb: Init: Starting Probe...\n"); - - if(io != -1 && irq != -1 && dma != -1) { - printk(KERN_INFO "sb: Probing legacy card with io=%x, "\ - "irq=%d, dma=%d, dma16=%d\n",io, irq, dma, dma16); - lres = sb_init_legacy(); - } else if((io != -1 || irq != -1 || dma != -1) || - (!pnp && (io == -1 && irq == -1 && dma == -1))) - printk(KERN_ERR "sb: Error: At least io, irq, and dma "\ - "must be set for legacy cards.\n"); - -#ifdef CONFIG_PNP - if(pnp) { - int err = pnp_register_card_driver(&sb_pnp_driver); - if (!err) - pnp_registered = 1; - pres = sb_pnp_devices; - } -#endif - printk(KERN_INFO "sb: Init: Done\n"); - - /* If either PnP or Legacy registered a card then return - * success */ - if (pres == 0 && lres <= 0) { - sb_unregister_all(); - return -ENODEV; - } - return 0; -} - -static void __exit sb_exit(void) -{ - printk(KERN_INFO "sb: Unloading...\n"); - - /* Unload legacy card */ - if (legacy) { - printk (KERN_INFO "sb: Unloading legacy card\n"); - sb_unload(legacy); - } - - sb_unregister_all(); - - vfree(smw_free); - smw_free = NULL; -} - -module_init(sb_init); -module_exit(sb_exit); diff --git a/ANDROID_3.4.5/sound/oss/sb_card.h b/ANDROID_3.4.5/sound/oss/sb_card.h deleted file mode 100644 index 5535cff8..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_card.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * sound/oss/sb_card.h - * - * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this - * software for more info. - * - * 02-05-2002 Original Release, Paul Laufer - */ - -struct sb_card_config { - struct address_info conf; - struct address_info mpucnf; - const char *card_id; - const char *dev_id; - int mpu; -}; - -#ifdef CONFIG_PNP - -/* - * SoundBlaster PnP tables and structures. - */ - -/* Card PnP ID Table */ -static struct pnp_card_device_id sb_pnp_card_table[] = { - /* Sound Blaster 16 */ - {.id = "CTL0024", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL0025", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL0026", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL0027", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL0028", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL0029", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL002a", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL002b", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL002c", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL00ed", .driver_data = 0, .devs = { {.id="CTL0041"}, } }, - /* Sound Blaster 16 */ - {.id = "CTL0086", .driver_data = 0, .devs = { {.id="CTL0041"}, } }, - /* Sound Blaster Vibra16S */ - {.id = "CTL0051", .driver_data = 0, .devs = { {.id="CTL0001"}, } }, - /* Sound Blaster Vibra16C */ - {.id = "CTL0070", .driver_data = 0, .devs = { {.id="CTL0001"}, } }, - /* Sound Blaster Vibra16CL */ - {.id = "CTL0080", .driver_data = 0, .devs = { {.id="CTL0041"}, } }, - /* Sound Blaster Vibra16CL */ - {.id = "CTL00F0", .driver_data = 0, .devs = { {.id="CTL0043"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0039", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0042", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0043", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0044", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0045", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0046", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0047", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0048", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL0054", .driver_data = 0, .devs = { {.id="CTL0031"}, } }, - /* Sound Blaster AWE 32 */ - {.id = "CTL009C", .driver_data = 0, .devs = { {.id="CTL0041"}, } }, - /* Createive SB32 PnP */ - {.id = "CTL009F", .driver_data = 0, .devs = { {.id="CTL0041"}, } }, - /* Sound Blaster AWE 64 */ - {.id = "CTL009D", .driver_data = 0, .devs = { {.id="CTL0042"}, } }, - /* Sound Blaster AWE 64 Gold */ - {.id = "CTL009E", .driver_data = 0, .devs = { {.id="CTL0044"}, } }, - /* Sound Blaster AWE 64 Gold */ - {.id = "CTL00B2", .driver_data = 0, .devs = { {.id="CTL0044"}, } }, - /* Sound Blaster AWE 64 */ - {.id = "CTL00C1", .driver_data = 0, .devs = { {.id="CTL0042"}, } }, - /* Sound Blaster AWE 64 */ - {.id = "CTL00C3", .driver_data = 0, .devs = { {.id="CTL0045"}, } }, - /* Sound Blaster AWE 64 */ - {.id = "CTL00C5", .driver_data = 0, .devs = { {.id="CTL0045"}, } }, - /* Sound Blaster AWE 64 */ - {.id = "CTL00C7", .driver_data = 0, .devs = { {.id="CTL0045"}, } }, - /* Sound Blaster AWE 64 */ - {.id = "CTL00E4", .driver_data = 0, .devs = { {.id="CTL0045"}, } }, - /* Sound Blaster AWE 64 */ - {.id = "CTL00E9", .driver_data = 0, .devs = { {.id="CTL0045"}, } }, - /* ESS 1868 */ - {.id = "ESS0968", .driver_data = 0, .devs = { {.id="ESS0968"}, } }, - /* ESS 1868 */ - {.id = "ESS1868", .driver_data = 0, .devs = { {.id="ESS1868"}, } }, - /* ESS 1868 */ - {.id = "ESS1868", .driver_data = 0, .devs = { {.id="ESS8611"}, } }, - /* ESS 1869 PnP AudioDrive */ - {.id = "ESS0003", .driver_data = 0, .devs = { {.id="ESS1869"}, } }, - /* ESS 1869 */ - {.id = "ESS1869", .driver_data = 0, .devs = { {.id="ESS1869"}, } }, - /* ESS 1878 */ - {.id = "ESS1878", .driver_data = 0, .devs = { {.id="ESS1878"}, } }, - /* ESS 1879 */ - {.id = "ESS1879", .driver_data = 0, .devs = { {.id="ESS1879"}, } }, - /* CMI 8330 SoundPRO */ - {.id = "CMI0001", .driver_data = 0, .devs = { {.id="@X@0001"}, - {.id="@H@0001"}, - {.id="@@@0001"}, } }, - /* Diamond DT0197H */ - {.id = "RWR1688", .driver_data = 0, .devs = { {.id="@@@0001"}, - {.id="@X@0001"}, - {.id="@H@0001"}, } }, - /* ALS007 */ - {.id = "ALS0007", .driver_data = 0, .devs = { {.id="@@@0001"}, - {.id="@X@0001"}, - {.id="@H@0001"}, } }, - /* ALS100 */ - {.id = "ALS0001", .driver_data = 0, .devs = { {.id="@@@0001"}, - {.id="@X@0001"}, - {.id="@H@0001"}, } }, - /* ALS110 */ - {.id = "ALS0110", .driver_data = 0, .devs = { {.id="@@@1001"}, - {.id="@X@1001"}, - {.id="@H@0001"}, } }, - /* ALS120 */ - {.id = "ALS0120", .driver_data = 0, .devs = { {.id="@@@2001"}, - {.id="@X@2001"}, - {.id="@H@0001"}, } }, - /* ALS200 */ - {.id = "ALS0200", .driver_data = 0, .devs = { {.id="@@@0020"}, - {.id="@X@0030"}, - {.id="@H@0001"}, } }, - /* ALS200 */ - {.id = "RTL3000", .driver_data = 0, .devs = { {.id="@@@2001"}, - {.id="@X@2001"}, - {.id="@H@0001"}, } }, - /* Sound Blaster 16 (Virtual PC 2004) */ - {.id = "tBA03b0", .driver_data = 0, .devs = { {.id="PNPb003"}, } }, - /* -end- */ - {.id = "", } -}; - -#endif diff --git a/ANDROID_3.4.5/sound/oss/sb_common.c b/ANDROID_3.4.5/sound/oss/sb_common.c deleted file mode 100644 index 7d42c541..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_common.c +++ /dev/null @@ -1,1292 +0,0 @@ -/* - * sound/oss/sb_common.c - * - * Common routines for Sound Blaster compatible cards. - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Daniel J. Rodriksson: Modified sbintr to handle 8 and 16 bit interrupts - * for full duplex support ( only sb16 by now ) - * Rolf Fokkens: Added (BETA?) support for ES1887 chips. - * (fokkensr@vertis.nl) Which means: You can adjust the recording levels. - * - * 2000/01/18 - separated sb_card and sb_common - - * Jeff Garzik - * - * 2000/09/18 - got rid of attach_uart401 - * Arnaldo Carvalho de Melo - * - * 2001/01/26 - replaced CLI/STI with spinlocks - * Chris Rankin - */ - -#include -#include -#include -#include -#include -#include - -#include "sound_config.h" -#include "sound_firmware.h" - -#include "mpu401.h" - -#include "sb_mixer.h" -#include "sb.h" -#include "sb_ess.h" - -/* - * global module flag - */ - -int sb_be_quiet; - -static sb_devc *detected_devc; /* For communication from probe to init */ -static sb_devc *last_devc; /* For MPU401 initialization */ - -static unsigned char jazz_irq_bits[] = { - 0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6 -}; - -static unsigned char jazz_dma_bits[] = { - 0, 1, 0, 2, 0, 3, 0, 4 -}; - -void *smw_free; - -/* - * Jazz16 chipset specific control variables - */ - -static int jazz16_base; /* Not detected */ -static unsigned char jazz16_bits; /* I/O relocation bits */ -static DEFINE_SPINLOCK(jazz16_lock); - -/* - * Logitech Soundman Wave specific initialization code - */ - -#ifdef SMW_MIDI0001_INCLUDED -#include "smw-midi0001.h" -#else -static unsigned char *smw_ucode; -static int smw_ucodeLen; - -#endif - -static sb_devc *last_sb; /* Last sb loaded */ - -int sb_dsp_command(sb_devc * devc, unsigned char val) -{ - int i; - unsigned long limit; - - limit = jiffies + HZ / 10; /* Timeout */ - - /* - * Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes - * called while interrupts are disabled. This means that the timer is - * disabled also. However the timeout situation is a abnormal condition. - * Normally the DSP should be ready to accept commands after just couple of - * loops. - */ - - for (i = 0; i < 500000 && (limit-jiffies)>0; i++) - { - if ((inb(DSP_STATUS) & 0x80) == 0) - { - outb((val), DSP_COMMAND); - return 1; - } - } - printk(KERN_WARNING "Sound Blaster: DSP command(%x) timeout.\n", val); - return 0; -} - -int sb_dsp_get_byte(sb_devc * devc) -{ - int i; - - for (i = 1000; i; i--) - { - if (inb(DSP_DATA_AVAIL) & 0x80) - return inb(DSP_READ); - } - return 0xffff; -} - -static void sb_intr (sb_devc *devc) -{ - int status; - unsigned char src = 0xff; - - if (devc->model == MDL_SB16) - { - src = sb_getmixer(devc, IRQ_STAT); /* Interrupt source register */ - - if (src & 4) /* MPU401 interrupt */ - if(devc->midi_irq_cookie) - uart401intr(devc->irq, devc->midi_irq_cookie); - - if (!(src & 3)) - return; /* Not a DSP interrupt */ - } - if (devc->intr_active && (!devc->fullduplex || (src & 0x01))) - { - switch (devc->irq_mode) - { - case IMODE_OUTPUT: - DMAbuf_outputintr(devc->dev, 1); - break; - - case IMODE_INPUT: - DMAbuf_inputintr(devc->dev); - break; - - case IMODE_INIT: - break; - - case IMODE_MIDI: - sb_midi_interrupt(devc); - break; - - default: - /* printk(KERN_WARNING "Sound Blaster: Unexpected interrupt\n"); */ - ; - } - } - else if (devc->intr_active_16 && (src & 0x02)) - { - switch (devc->irq_mode_16) - { - case IMODE_OUTPUT: - DMAbuf_outputintr(devc->dev, 1); - break; - - case IMODE_INPUT: - DMAbuf_inputintr(devc->dev); - break; - - case IMODE_INIT: - break; - - default: - /* printk(KERN_WARNING "Sound Blaster: Unexpected interrupt\n"); */ - ; - } - } - /* - * Acknowledge interrupts - */ - - if (src & 0x01) - status = inb(DSP_DATA_AVAIL); - - if (devc->model == MDL_SB16 && src & 0x02) - status = inb(DSP_DATA_AVL16); -} - -static void pci_intr(sb_devc *devc) -{ - int src = inb(devc->pcibase+0x1A); - src&=3; - if(src) - sb_intr(devc); -} - -static irqreturn_t sbintr(int irq, void *dev_id) -{ - sb_devc *devc = dev_id; - - devc->irq_ok = 1; - - switch (devc->model) { - case MDL_ESSPCI: - pci_intr (devc); - break; - - case MDL_ESS: - ess_intr (devc); - break; - default: - sb_intr (devc); - break; - } - return IRQ_HANDLED; -} - -int sb_dsp_reset(sb_devc * devc) -{ - int loopc; - - DEB(printk("Entered sb_dsp_reset()\n")); - - if (devc->model == MDL_ESS) return ess_dsp_reset (devc); - - /* This is only for non-ESS chips */ - - outb(1, DSP_RESET); - - udelay(10); - outb(0, DSP_RESET); - udelay(30); - - for (loopc = 0; loopc < 1000 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++); - - if (inb(DSP_READ) != 0xAA) - { - DDB(printk("sb: No response to RESET\n")); - return 0; /* Sorry */ - } - - DEB(printk("sb_dsp_reset() OK\n")); - - return 1; -} - -static void dsp_get_vers(sb_devc * devc) -{ - int i; - - unsigned long flags; - - DDB(printk("Entered dsp_get_vers()\n")); - spin_lock_irqsave(&devc->lock, flags); - devc->major = devc->minor = 0; - sb_dsp_command(devc, 0xe1); /* Get version */ - - for (i = 100000; i; i--) - { - if (inb(DSP_DATA_AVAIL) & 0x80) - { - if (devc->major == 0) - devc->major = inb(DSP_READ); - else - { - devc->minor = inb(DSP_READ); - break; - } - } - } - spin_unlock_irqrestore(&devc->lock, flags); - DDB(printk("DSP version %d.%02d\n", devc->major, devc->minor)); -} - -static int sb16_set_dma_hw(sb_devc * devc) -{ - int bits; - - if (devc->dma8 != 0 && devc->dma8 != 1 && devc->dma8 != 3) - { - printk(KERN_ERR "SB16: Invalid 8 bit DMA (%d)\n", devc->dma8); - return 0; - } - bits = (1 << devc->dma8); - - if (devc->dma16 >= 5 && devc->dma16 <= 7) - bits |= (1 << devc->dma16); - - sb_setmixer(devc, DMA_NR, bits); - return 1; -} - -static void sb16_set_mpu_port(sb_devc * devc, struct address_info *hw_config) -{ - /* - * This routine initializes new MIDI port setup register of SB Vibra (CT2502). - */ - unsigned char bits = sb_getmixer(devc, 0x84) & ~0x06; - - switch (hw_config->io_base) - { - case 0x300: - sb_setmixer(devc, 0x84, bits | 0x04); - break; - - case 0x330: - sb_setmixer(devc, 0x84, bits | 0x00); - break; - - default: - sb_setmixer(devc, 0x84, bits | 0x02); /* Disable MPU */ - printk(KERN_ERR "SB16: Invalid MIDI I/O port %x\n", hw_config->io_base); - } -} - -static int sb16_set_irq_hw(sb_devc * devc, int level) -{ - int ival; - - switch (level) - { - case 5: - ival = 2; - break; - case 7: - ival = 4; - break; - case 9: - ival = 1; - break; - case 10: - ival = 8; - break; - default: - printk(KERN_ERR "SB16: Invalid IRQ%d\n", level); - return 0; - } - sb_setmixer(devc, IRQ_NR, ival); - return 1; -} - -static void relocate_Jazz16(sb_devc * devc, struct address_info *hw_config) -{ - unsigned char bits = 0; - unsigned long flags; - - if (jazz16_base != 0 && jazz16_base != hw_config->io_base) - return; - - switch (hw_config->io_base) - { - case 0x220: - bits = 1; - break; - case 0x240: - bits = 2; - break; - case 0x260: - bits = 3; - break; - default: - return; - } - bits = jazz16_bits = bits << 5; - jazz16_base = hw_config->io_base; - - /* - * Magic wake up sequence by writing to 0x201 (aka Joystick port) - */ - spin_lock_irqsave(&jazz16_lock, flags); - outb((0xAF), 0x201); - outb((0x50), 0x201); - outb((bits), 0x201); - spin_unlock_irqrestore(&jazz16_lock, flags); -} - -static int init_Jazz16(sb_devc * devc, struct address_info *hw_config) -{ - char name[100]; - /* - * First try to check that the card has Jazz16 chip. It identifies itself - * by returning 0x12 as response to DSP command 0xfa. - */ - - if (!sb_dsp_command(devc, 0xfa)) - return 0; - - if (sb_dsp_get_byte(devc) != 0x12) - return 0; - - /* - * OK so far. Now configure the IRQ and DMA channel used by the card. - */ - if (hw_config->irq < 1 || hw_config->irq > 15 || jazz_irq_bits[hw_config->irq] == 0) - { - printk(KERN_ERR "Jazz16: Invalid interrupt (IRQ%d)\n", hw_config->irq); - return 0; - } - if (hw_config->dma < 0 || hw_config->dma > 3 || jazz_dma_bits[hw_config->dma] == 0) - { - printk(KERN_ERR "Jazz16: Invalid 8 bit DMA (DMA%d)\n", hw_config->dma); - return 0; - } - if (hw_config->dma2 < 0) - { - printk(KERN_ERR "Jazz16: No 16 bit DMA channel defined\n"); - return 0; - } - if (hw_config->dma2 < 5 || hw_config->dma2 > 7 || jazz_dma_bits[hw_config->dma2] == 0) - { - printk(KERN_ERR "Jazz16: Invalid 16 bit DMA (DMA%d)\n", hw_config->dma2); - return 0; - } - devc->dma16 = hw_config->dma2; - - if (!sb_dsp_command(devc, 0xfb)) - return 0; - - if (!sb_dsp_command(devc, jazz_dma_bits[hw_config->dma] | - (jazz_dma_bits[hw_config->dma2] << 4))) - return 0; - - if (!sb_dsp_command(devc, jazz_irq_bits[hw_config->irq])) - return 0; - - /* - * Now we have configured a standard Jazz16 device. - */ - devc->model = MDL_JAZZ; - strcpy(name, "Jazz16"); - - hw_config->name = "Jazz16"; - devc->caps |= SB_NO_MIDI; - return 1; -} - -static void relocate_ess1688(sb_devc * devc) -{ - unsigned char bits; - - switch (devc->base) - { - case 0x220: - bits = 0x04; - break; - case 0x230: - bits = 0x05; - break; - case 0x240: - bits = 0x06; - break; - case 0x250: - bits = 0x07; - break; - default: - return; /* Wrong port */ - } - - DDB(printk("Doing ESS1688 address selection\n")); - - /* - * ES1688 supports two alternative ways for software address config. - * First try the so called Read-Sequence-Key method. - */ - - /* Reset the sequence logic */ - inb(0x229); - inb(0x229); - inb(0x229); - - /* Perform the read sequence */ - inb(0x22b); - inb(0x229); - inb(0x22b); - inb(0x229); - inb(0x229); - inb(0x22b); - inb(0x229); - - /* Select the base address by reading from it. Then probe using the port. */ - inb(devc->base); - if (sb_dsp_reset(devc)) /* Bingo */ - return; - -#if 0 /* This causes system lockups (Nokia 386/25 at least) */ - /* - * The last resort is the system control register method. - */ - - outb((0x00), 0xfb); /* 0xFB is the unlock register */ - outb((0x00), 0xe0); /* Select index 0 */ - outb((bits), 0xe1); /* Write the config bits */ - outb((0x00), 0xf9); /* 0xFB is the lock register */ -#endif -} - -int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio, struct sb_module_options *sbmo) -{ - sb_devc sb_info; - sb_devc *devc = &sb_info; - - memset((char *) &sb_info, 0, sizeof(sb_info)); /* Zero everything */ - - /* Copy module options in place */ - if(sbmo) memcpy(&devc->sbmo, sbmo, sizeof(struct sb_module_options)); - - sb_info.my_mididev = -1; - sb_info.my_mixerdev = -1; - sb_info.dev = -1; - - /* - * Initialize variables - */ - - DDB(printk("sb_dsp_detect(%x) entered\n", hw_config->io_base)); - - spin_lock_init(&devc->lock); - devc->type = hw_config->card_subtype; - - devc->base = hw_config->io_base; - devc->irq = hw_config->irq; - devc->dma8 = hw_config->dma; - - devc->dma16 = -1; - devc->pcibase = pciio; - - if(pci == SB_PCI_ESSMAESTRO) - { - devc->model = MDL_ESSPCI; - devc->caps |= SB_PCI_IRQ; - hw_config->driver_use_1 |= SB_PCI_IRQ; - hw_config->card_subtype = MDL_ESSPCI; - } - - if(pci == SB_PCI_YAMAHA) - { - devc->model = MDL_YMPCI; - devc->caps |= SB_PCI_IRQ; - hw_config->driver_use_1 |= SB_PCI_IRQ; - hw_config->card_subtype = MDL_YMPCI; - - printk("Yamaha PCI mode.\n"); - } - - if (devc->sbmo.acer) - { - unsigned long flags; - - spin_lock_irqsave(&devc->lock, flags); - inb(devc->base + 0x09); - inb(devc->base + 0x09); - inb(devc->base + 0x09); - inb(devc->base + 0x0b); - inb(devc->base + 0x09); - inb(devc->base + 0x0b); - inb(devc->base + 0x09); - inb(devc->base + 0x09); - inb(devc->base + 0x0b); - inb(devc->base + 0x09); - inb(devc->base + 0x00); - spin_unlock_irqrestore(&devc->lock, flags); - } - /* - * Detect the device - */ - - if (sb_dsp_reset(devc)) - dsp_get_vers(devc); - else - devc->major = 0; - - if (devc->type == 0 || devc->type == MDL_JAZZ || devc->type == MDL_SMW) - if (devc->major == 0 || (devc->major == 3 && devc->minor == 1)) - relocate_Jazz16(devc, hw_config); - - if (devc->major == 0 && (devc->type == MDL_ESS || devc->type == 0)) - relocate_ess1688(devc); - - if (!sb_dsp_reset(devc)) - { - DDB(printk("SB reset failed\n")); -#ifdef MODULE - printk(KERN_INFO "sb: dsp reset failed.\n"); -#endif - return 0; - } - if (devc->major == 0) - dsp_get_vers(devc); - - if (devc->major == 3 && devc->minor == 1) - { - if (devc->type == MDL_AZTECH) /* SG Washington? */ - { - if (sb_dsp_command(devc, 0x09)) - if (sb_dsp_command(devc, 0x00)) /* Enter WSS mode */ - { - int i; - - /* Have some delay */ - for (i = 0; i < 10000; i++) - inb(DSP_DATA_AVAIL); - devc->caps = SB_NO_AUDIO | SB_NO_MIDI; /* Mixer only */ - devc->model = MDL_AZTECH; - } - } - } - - if(devc->type == MDL_ESSPCI) - devc->model = MDL_ESSPCI; - - if(devc->type == MDL_YMPCI) - { - printk("YMPCI selected\n"); - devc->model = MDL_YMPCI; - } - - /* - * Save device information for sb_dsp_init() - */ - - - detected_devc = kmalloc(sizeof(sb_devc), GFP_KERNEL); - if (detected_devc == NULL) - { - printk(KERN_ERR "sb: Can't allocate memory for device information\n"); - return 0; - } - memcpy(detected_devc, devc, sizeof(sb_devc)); - MDB(printk(KERN_INFO "SB %d.%02d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base)); - return 1; -} - -int sb_dsp_init(struct address_info *hw_config, struct module *owner) -{ - sb_devc *devc; - char name[100]; - extern int sb_be_quiet; - int mixer22, mixer30; - -/* - * Check if we had detected a SB device earlier - */ - DDB(printk("sb_dsp_init(%x) entered\n", hw_config->io_base)); - name[0] = 0; - - if (detected_devc == NULL) - { - MDB(printk("No detected device\n")); - return 0; - } - devc = detected_devc; - detected_devc = NULL; - - if (devc->base != hw_config->io_base) - { - DDB(printk("I/O port mismatch\n")); - release_region(devc->base, 16); - return 0; - } - /* - * Now continue initialization of the device - */ - - devc->caps = hw_config->driver_use_1; - - if (!((devc->caps & SB_NO_AUDIO) && (devc->caps & SB_NO_MIDI)) && hw_config->irq > 0) - { /* IRQ setup */ - - /* - * ESS PCI cards do shared PCI IRQ stuff. Since they - * will get shared PCI irq lines we must cope. - */ - - int i=(devc->caps&SB_PCI_IRQ)?IRQF_SHARED:0; - - if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0) - { - printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq); - release_region(devc->base, 16); - return 0; - } - devc->irq_ok = 0; - - if (devc->major == 4) - if (!sb16_set_irq_hw(devc, devc->irq)) /* Unsupported IRQ */ - { - free_irq(devc->irq, devc); - release_region(devc->base, 16); - return 0; - } - if ((devc->type == 0 || devc->type == MDL_ESS) && - devc->major == 3 && devc->minor == 1) - { /* Handle various chipsets which claim they are SB Pro compatible */ - if ((devc->type != 0 && devc->type != MDL_ESS) || - !ess_init(devc, hw_config)) - { - if ((devc->type != 0 && devc->type != MDL_JAZZ && - devc->type != MDL_SMW) || !init_Jazz16(devc, hw_config)) - { - DDB(printk("This is a genuine SB Pro\n")); - } - } - } - if (devc->major == 4 && devc->minor <= 11 ) /* Won't work */ - devc->irq_ok = 1; - else - { - int n; - - for (n = 0; n < 3 && devc->irq_ok == 0; n++) - { - if (sb_dsp_command(devc, 0xf2)) /* Cause interrupt immediately */ - { - int i; - - for (i = 0; !devc->irq_ok && i < 10000; i++); - } - } - if (!devc->irq_ok) - printk(KERN_WARNING "sb: Interrupt test on IRQ%d failed - Probable IRQ conflict\n", devc->irq); - else - { - DDB(printk("IRQ test OK (IRQ%d)\n", devc->irq)); - } - } - } /* IRQ setup */ - - last_sb = devc; - - switch (devc->major) - { - case 1: /* SB 1.0 or 1.5 */ - devc->model = hw_config->card_subtype = MDL_SB1; - break; - - case 2: /* SB 2.x */ - if (devc->minor == 0) - devc->model = hw_config->card_subtype = MDL_SB2; - else - devc->model = hw_config->card_subtype = MDL_SB201; - break; - - case 3: /* SB Pro and most clones */ - switch (devc->model) { - case 0: - devc->model = hw_config->card_subtype = MDL_SBPRO; - if (hw_config->name == NULL) - hw_config->name = "Sound Blaster Pro (8 BIT ONLY)"; - break; - case MDL_ESS: - ess_dsp_init(devc, hw_config); - break; - } - break; - - case 4: - devc->model = hw_config->card_subtype = MDL_SB16; - /* - * ALS007 and ALS100 return DSP version 4.2 and have 2 post-reset !=0 - * registers at 0x3c and 0x4c (output ctrl registers on ALS007) whereas - * a "standard" SB16 doesn't have a register at 0x4c. ALS100 actively - * updates register 0x22 whenever 0x30 changes, as per the SB16 spec. - * Since ALS007 doesn't, this can be used to differentiate the 2 cards. - */ - if ((devc->minor == 2) && sb_getmixer(devc,0x3c) && sb_getmixer(devc,0x4c)) - { - mixer30 = sb_getmixer(devc,0x30); - sb_setmixer(devc,0x22,(mixer22=sb_getmixer(devc,0x22)) & 0x0f); - sb_setmixer(devc,0x30,0xff); - /* ALS100 will force 0x30 to 0xf8 like SB16; ALS007 will allow 0xff. */ - /* Register 0x22 & 0xf0 on ALS100 == 0xf0; on ALS007 it == 0x10. */ - if ((sb_getmixer(devc,0x30) != 0xff) || ((sb_getmixer(devc,0x22) & 0xf0) != 0x10)) - { - devc->submodel = SUBMDL_ALS100; - if (hw_config->name == NULL) - hw_config->name = "Sound Blaster 16 (ALS-100)"; - } - else - { - sb_setmixer(devc,0x3c,0x1f); /* Enable all inputs */ - sb_setmixer(devc,0x4c,0x1f); - sb_setmixer(devc,0x22,mixer22); /* Restore 0x22 to original value */ - devc->submodel = SUBMDL_ALS007; - if (hw_config->name == NULL) - hw_config->name = "Sound Blaster 16 (ALS-007)"; - } - sb_setmixer(devc,0x30,mixer30); - } - else if (hw_config->name == NULL) - hw_config->name = "Sound Blaster 16"; - - if (hw_config->dma2 == -1) - devc->dma16 = devc->dma8; - else if (hw_config->dma2 < 5 || hw_config->dma2 > 7) - { - printk(KERN_WARNING "SB16: Bad or missing 16 bit DMA channel\n"); - devc->dma16 = devc->dma8; - } - else - devc->dma16 = hw_config->dma2; - - if(!sb16_set_dma_hw(devc)) { - free_irq(devc->irq, devc); - release_region(hw_config->io_base, 16); - return 0; - } - - devc->caps |= SB_NO_MIDI; - } - - if (!(devc->caps & SB_NO_MIXER)) - if (devc->major == 3 || devc->major == 4) - sb_mixer_init(devc, owner); - - if (!(devc->caps & SB_NO_MIDI)) - sb_dsp_midi_init(devc, owner); - - if (hw_config->name == NULL) - hw_config->name = "Sound Blaster (8 BIT/MONO ONLY)"; - - sprintf(name, "%s (%d.%02d)", hw_config->name, devc->major, devc->minor); - conf_printf(name, hw_config); - - /* - * Assuming that a sound card is Sound Blaster (compatible) is the most common - * configuration error and the mother of all problems. Usually sound cards - * emulate SB Pro but in addition they have a 16 bit native mode which should be - * used in Unix. See Readme.cards for more information about configuring OSS/Free - * properly. - */ - if (devc->model <= MDL_SBPRO) - { - if (devc->major == 3 && devc->minor != 1) /* "True" SB Pro should have v3.1 (rare ones may have 3.2). */ - { - printk(KERN_INFO "This sound card may not be fully Sound Blaster Pro compatible.\n"); - printk(KERN_INFO "In many cases there is another way to configure OSS so that\n"); - printk(KERN_INFO "it works properly with OSS (for example in 16 bit mode).\n"); - printk(KERN_INFO "Please ignore this message if you _really_ have a SB Pro.\n"); - } - else if (!sb_be_quiet && devc->model == MDL_SBPRO) - { - printk(KERN_INFO "SB DSP version is just %d.%02d which means that your card is\n", devc->major, devc->minor); - printk(KERN_INFO "several years old (8 bit only device) or alternatively the sound driver\n"); - printk(KERN_INFO "is incorrectly configured.\n"); - } - } - hw_config->card_subtype = devc->model; - hw_config->slots[0]=devc->dev; - last_devc = devc; /* For SB MPU detection */ - - if (!(devc->caps & SB_NO_AUDIO) && devc->dma8 >= 0) - { - if (sound_alloc_dma(devc->dma8, "SoundBlaster8")) - { - printk(KERN_WARNING "Sound Blaster: Can't allocate 8 bit DMA channel %d\n", devc->dma8); - } - if (devc->dma16 >= 0 && devc->dma16 != devc->dma8) - { - if (sound_alloc_dma(devc->dma16, "SoundBlaster16")) - printk(KERN_WARNING "Sound Blaster: can't allocate 16 bit DMA channel %d.\n", devc->dma16); - } - sb_audio_init(devc, name, owner); - hw_config->slots[0]=devc->dev; - } - else - { - MDB(printk("Sound Blaster: no audio devices found.\n")); - } - return 1; -} - -/* if (sbmpu) below we allow mpu401 to manage the midi devs - otherwise we have to unload them. (Andrzej Krzysztofowicz) */ - -void sb_dsp_unload(struct address_info *hw_config, int sbmpu) -{ - sb_devc *devc; - - devc = audio_devs[hw_config->slots[0]]->devc; - - if (devc && devc->base == hw_config->io_base) - { - if ((devc->model & MDL_ESS) && devc->pcibase) - release_region(devc->pcibase, 8); - - release_region(devc->base, 16); - - if (!(devc->caps & SB_NO_AUDIO)) - { - sound_free_dma(devc->dma8); - if (devc->dma16 >= 0) - sound_free_dma(devc->dma16); - } - if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI)) - { - if (devc->irq > 0) - free_irq(devc->irq, devc); - - sb_mixer_unload(devc); - /* We don't have to do this bit any more the UART401 is its own - master -- Krzysztof Halasa */ - /* But we have to do it, if UART401 is not detected */ - if (!sbmpu) - sound_unload_mididev(devc->my_mididev); - sound_unload_audiodev(devc->dev); - } - kfree(devc); - } - else - release_region(hw_config->io_base, 16); - - kfree(detected_devc); -} - -/* - * Mixer access routines - * - * ES1887 modifications: some mixer registers reside in the - * range above 0xa0. These must be accessed in another way. - */ - -void sb_setmixer(sb_devc * devc, unsigned int port, unsigned int value) -{ - unsigned long flags; - - if (devc->model == MDL_ESS) { - ess_setmixer (devc, port, value); - return; - } - - spin_lock_irqsave(&devc->lock, flags); - - outb(((unsigned char) (port & 0xff)), MIXER_ADDR); - udelay(20); - outb(((unsigned char) (value & 0xff)), MIXER_DATA); - udelay(20); - - spin_unlock_irqrestore(&devc->lock, flags); -} - -unsigned int sb_getmixer(sb_devc * devc, unsigned int port) -{ - unsigned int val; - unsigned long flags; - - if (devc->model == MDL_ESS) return ess_getmixer (devc, port); - - spin_lock_irqsave(&devc->lock, flags); - - outb(((unsigned char) (port & 0xff)), MIXER_ADDR); - udelay(20); - val = inb(MIXER_DATA); - udelay(20); - - spin_unlock_irqrestore(&devc->lock, flags); - - return val; -} - -void sb_chgmixer - (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val) -{ - int value; - - value = sb_getmixer(devc, reg); - value = (value & ~mask) | (val & mask); - sb_setmixer(devc, reg, value); -} - -/* - * MPU401 MIDI initialization. - */ - -static void smw_putmem(sb_devc * devc, int base, int addr, unsigned char val) -{ - unsigned long flags; - - spin_lock_irqsave(&jazz16_lock, flags); /* NOT the SB card? */ - - outb((addr & 0xff), base + 1); /* Low address bits */ - outb((addr >> 8), base + 2); /* High address bits */ - outb((val), base); /* Data */ - - spin_unlock_irqrestore(&jazz16_lock, flags); -} - -static unsigned char smw_getmem(sb_devc * devc, int base, int addr) -{ - unsigned long flags; - unsigned char val; - - spin_lock_irqsave(&jazz16_lock, flags); /* NOT the SB card? */ - - outb((addr & 0xff), base + 1); /* Low address bits */ - outb((addr >> 8), base + 2); /* High address bits */ - val = inb(base); /* Data */ - - spin_unlock_irqrestore(&jazz16_lock, flags); - return val; -} - -static int smw_midi_init(sb_devc * devc, struct address_info *hw_config) -{ - int mpu_base = hw_config->io_base; - int mp_base = mpu_base + 4; /* Microcontroller base */ - int i; - unsigned char control; - - - /* - * Reset the microcontroller so that the RAM can be accessed - */ - - control = inb(mpu_base + 7); - outb((control | 3), mpu_base + 7); /* Set last two bits to 1 (?) */ - outb(((control & 0xfe) | 2), mpu_base + 7); /* xxxxxxx0 resets the mc */ - - mdelay(3); /* Wait at least 1ms */ - - outb((control & 0xfc), mpu_base + 7); /* xxxxxx00 enables RAM */ - - /* - * Detect microcontroller by probing the 8k RAM area - */ - smw_putmem(devc, mp_base, 0, 0x00); - smw_putmem(devc, mp_base, 1, 0xff); - udelay(10); - - if (smw_getmem(devc, mp_base, 0) != 0x00 || smw_getmem(devc, mp_base, 1) != 0xff) - { - DDB(printk("SM Wave: No microcontroller RAM detected (%02x, %02x)\n", smw_getmem(devc, mp_base, 0), smw_getmem(devc, mp_base, 1))); - return 0; /* No RAM */ - } - /* - * There is RAM so assume it's really a SM Wave - */ - - devc->model = MDL_SMW; - smw_mixer_init(devc); - -#ifdef MODULE - if (!smw_ucode) - { - smw_ucodeLen = mod_firmware_load("/etc/sound/midi0001.bin", (void *) &smw_ucode); - smw_free = smw_ucode; - } -#endif - if (smw_ucodeLen > 0) - { - if (smw_ucodeLen != 8192) - { - printk(KERN_ERR "SM Wave: Invalid microcode (MIDI0001.BIN) length\n"); - return 1; - } - /* - * Download microcode - */ - - for (i = 0; i < 8192; i++) - smw_putmem(devc, mp_base, i, smw_ucode[i]); - - /* - * Verify microcode - */ - - for (i = 0; i < 8192; i++) - if (smw_getmem(devc, mp_base, i) != smw_ucode[i]) - { - printk(KERN_ERR "SM Wave: Microcode verification failed\n"); - return 0; - } - } - control = 0; -#ifdef SMW_SCSI_IRQ - /* - * Set the SCSI interrupt (IRQ2/9, IRQ3 or IRQ10). The SCSI interrupt - * is disabled by default. - * - * FIXME - make this a module option - * - * BTW the Zilog 5380 SCSI controller is located at MPU base + 0x10. - */ - { - static unsigned char scsi_irq_bits[] = { - 0, 0, 3, 1, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0 - }; - control |= scsi_irq_bits[SMW_SCSI_IRQ] << 6; - } -#endif - -#ifdef SMW_OPL4_ENABLE - /* - * Make the OPL4 chip visible on the PC bus at 0x380. - * - * There is no need to enable this feature since this driver - * doesn't support OPL4 yet. Also there is no RAM in SM Wave so - * enabling OPL4 is pretty useless. - */ - control |= 0x10; /* Uses IRQ12 if bit 0x20 == 0 */ - /* control |= 0x20; Uncomment this if you want to use IRQ7 */ -#endif - outb((control | 0x03), mpu_base + 7); /* xxxxxx11 restarts */ - hw_config->name = "SoundMan Wave"; - return 1; -} - -static int init_Jazz16_midi(sb_devc * devc, struct address_info *hw_config) -{ - int mpu_base = hw_config->io_base; - int sb_base = devc->base; - int irq = hw_config->irq; - - unsigned char bits = 0; - unsigned long flags; - - if (irq < 0) - irq *= -1; - - if (irq < 1 || irq > 15 || - jazz_irq_bits[irq] == 0) - { - printk(KERN_ERR "Jazz16: Invalid MIDI interrupt (IRQ%d)\n", irq); - return 0; - } - switch (sb_base) - { - case 0x220: - bits = 1; - break; - case 0x240: - bits = 2; - break; - case 0x260: - bits = 3; - break; - default: - return 0; - } - bits = jazz16_bits = bits << 5; - switch (mpu_base) - { - case 0x310: - bits |= 1; - break; - case 0x320: - bits |= 2; - break; - case 0x330: - bits |= 3; - break; - default: - printk(KERN_ERR "Jazz16: Invalid MIDI I/O port %x\n", mpu_base); - return 0; - } - /* - * Magic wake up sequence by writing to 0x201 (aka Joystick port) - */ - spin_lock_irqsave(&jazz16_lock, flags); - outb(0xAF, 0x201); - outb(0x50, 0x201); - outb(bits, 0x201); - spin_unlock_irqrestore(&jazz16_lock, flags); - - hw_config->name = "Jazz16"; - smw_midi_init(devc, hw_config); - - if (!sb_dsp_command(devc, 0xfb)) - return 0; - - if (!sb_dsp_command(devc, jazz_dma_bits[devc->dma8] | - (jazz_dma_bits[devc->dma16] << 4))) - return 0; - - if (!sb_dsp_command(devc, jazz_irq_bits[devc->irq] | - (jazz_irq_bits[irq] << 4))) - return 0; - - return 1; -} - -int probe_sbmpu(struct address_info *hw_config, struct module *owner) -{ - sb_devc *devc = last_devc; - int ret; - - if (last_devc == NULL) - return 0; - - last_devc = NULL; - - if (hw_config->io_base <= 0) - { - /* The real vibra16 is fine about this, but we have to go - wipe up after Cyrix again */ - - if(devc->model == MDL_SB16 && devc->minor >= 12) - { - unsigned char bits = sb_getmixer(devc, 0x84) & ~0x06; - sb_setmixer(devc, 0x84, bits | 0x02); /* Disable MPU */ - } - return 0; - } - -#if defined(CONFIG_SOUND_MPU401) - if (devc->model == MDL_ESS) - { - struct resource *ports; - ports = request_region(hw_config->io_base, 2, "mpu401"); - if (!ports) { - printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base); - return 0; - } - if (!ess_midi_init(devc, hw_config)) { - release_region(hw_config->io_base, 2); - return 0; - } - hw_config->name = "ESS1xxx MPU"; - devc->midi_irq_cookie = NULL; - if (!probe_mpu401(hw_config, ports)) { - release_region(hw_config->io_base, 2); - return 0; - } - attach_mpu401(hw_config, owner); - if (last_sb->irq == -hw_config->irq) - last_sb->midi_irq_cookie = - (void *)(long) hw_config->slots[1]; - return 1; - } -#endif - - switch (devc->model) - { - case MDL_SB16: - if (hw_config->io_base != 0x300 && hw_config->io_base != 0x330) - { - printk(KERN_ERR "SB16: Invalid MIDI port %x\n", hw_config->io_base); - return 0; - } - hw_config->name = "Sound Blaster 16"; - if (hw_config->irq < 3 || hw_config->irq == devc->irq) - hw_config->irq = -devc->irq; - if (devc->minor > 12) /* What is Vibra's version??? */ - sb16_set_mpu_port(devc, hw_config); - break; - - case MDL_JAZZ: - if (hw_config->irq < 3 || hw_config->irq == devc->irq) - hw_config->irq = -devc->irq; - if (!init_Jazz16_midi(devc, hw_config)) - return 0; - break; - - case MDL_YMPCI: - hw_config->name = "Yamaha PCI Legacy"; - printk("Yamaha PCI legacy UART401 check.\n"); - break; - default: - return 0; - } - - ret = probe_uart401(hw_config, owner); - if (ret) - last_sb->midi_irq_cookie=midi_devs[hw_config->slots[4]]->devc; - return ret; -} - -void unload_sbmpu(struct address_info *hw_config) -{ -#if defined(CONFIG_SOUND_MPU401) - if (!strcmp (hw_config->name, "ESS1xxx MPU")) { - unload_mpu401(hw_config); - return; - } -#endif - unload_uart401(hw_config); -} - -EXPORT_SYMBOL(sb_dsp_init); -EXPORT_SYMBOL(sb_dsp_detect); -EXPORT_SYMBOL(sb_dsp_unload); -EXPORT_SYMBOL(sb_be_quiet); -EXPORT_SYMBOL(probe_sbmpu); -EXPORT_SYMBOL(unload_sbmpu); -EXPORT_SYMBOL(smw_free); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/sb_ess.c b/ANDROID_3.4.5/sound/oss/sb_ess.c deleted file mode 100644 index 5c773dff..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_ess.c +++ /dev/null @@ -1,1831 +0,0 @@ -#undef FKS_LOGGING -#undef FKS_TEST - -/* - * tabs should be 4 spaces, in vi(m): set tabstop=4 - * - * TODO: consistency speed calculations!! - * cleanup! - * ????: Did I break MIDI support? - * - * History: - * - * Rolf Fokkens (Dec 20 1998): ES188x recording level support on a per - * fokkensr@vertis.nl input basis. - * (Dec 24 1998): Recognition of ES1788, ES1887, ES1888, - * ES1868, ES1869 and ES1878. Could be used for - * specific handling in the future. All except - * ES1887 and ES1888 and ES688 are handled like - * ES1688. - * (Dec 27 1998): RECLEV for all (?) ES1688+ chips. ES188x now - * have the "Dec 20" support + RECLEV - * (Jan 2 1999): Preparation for Full Duplex. This means - * Audio 2 is now used for playback when dma16 - * is specified. The next step would be to use - * Audio 1 and Audio 2 at the same time. - * (Jan 9 1999): Put all ESS stuff into sb_ess.[ch], this - * includes both the ESS stuff that has been in - * sb_*[ch] before I touched it and the ESS support - * I added later - * (Jan 23 1999): Full Duplex seems to work. I wrote a small - * test proggy which works OK. Haven't found - * any applications to test it though. So why did - * I bother to create it anyway?? :) Just for - * fun. - * (May 2 1999): I tried to be too smart by "introducing" - * ess_calc_best_speed (). The idea was that two - * dividers could be used to setup a samplerate, - * ess_calc_best_speed () would choose the best. - * This works for playback, but results in - * recording problems for high samplerates. I - * fixed this by removing ess_calc_best_speed () - * and just doing what the documentation says. - * Andy Sloane (Jun 4 1999): Stole some code from ALSA to fix the playback - * andy@guildsoftware.com speed on ES1869, ES1879, ES1887, and ES1888. - * 1879's were previously ignored by this driver; - * added (untested) support for those. - * Cvetan Ivanov (Oct 27 1999): Fixed ess_dsp_init to call ess_set_dma_hw for - * zezo@inet.bg _ALL_ ESS models, not only ES1887 - * - * This files contains ESS chip specifics. It's based on the existing ESS - * handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This - * file adds features like: - * - Chip Identification (as shown in /proc/sound) - * - RECLEV support for ES1688 and later - * - 6 bits playback level support chips later than ES1688 - * - Recording level support on a per-device basis for ES1887 - * - Full-Duplex for ES1887 - * - * Full duplex is enabled by specifying dma16. While the normal dma must - * be one of 0, 1 or 3, dma16 can be one of 0, 1, 3 or 5. DMA 5 is a 16 bit - * DMA channel, while the others are 8 bit.. - * - * ESS detection isn't full proof (yet). If it fails an additional module - * parameter esstype can be specified to be one of the following: - * -1, 0, 688, 1688, 1868, 1869, 1788, 1887, 1888 - * -1 means: mimic 2.0 behaviour, - * 0 means: auto detect. - * others: explicitly specify chip - * -1 is default, cause auto detect still doesn't work. - */ - -/* - * About the documentation - * - * I don't know if the chips all are OK, but the documentation is buggy. 'cause - * I don't have all the cips myself, there's a lot I cannot verify. I'll try to - * keep track of my latest insights about his here. If you have additional info, - * please enlighten me (fokkensr@vertis.nl)! - * - * I had the impression that ES1688 also has 6 bit master volume control. The - * documentation about ES1888 (rev C, october '95) claims that ES1888 has - * the following features ES1688 doesn't have: - * - 6 bit master volume - * - Full Duplex - * So ES1688 apparently doesn't have 6 bit master volume control, but the - * ES1688 does have RECLEV control. Makes me wonder: does ES688 have it too? - * Without RECLEV ES688 won't be much fun I guess. - * - * From the ES1888 (rev C, october '95) documentation I got the impression - * that registers 0x68 to 0x6e don't exist which means: no recording volume - * controls. To my surprise the ES888 documentation (1/14/96) claims that - * ES888 does have these record mixer registers, but that ES1888 doesn't have - * 0x69 and 0x6b. So the rest should be there. - * - * I'm trying to get ES1887 Full Duplex. Audio 2 is playback only, while Audio 2 - * is both record and playback. I think I should use Audio 2 for all playback. - * - * The documentation is an adventure: it's close but not fully accurate. I - * found out that after a reset some registers are *NOT* reset, though the - * docs say the would be. Interesting ones are 0x7f, 0x7d and 0x7a. They are - * related to the Audio 2 channel. I also was surprised about the consequences - * of writing 0x00 to 0x7f (which should be done by reset): The ES1887 moves - * into ES1888 mode. This means that it claims IRQ 11, which happens to be my - * ISDN adapter. Needless to say it no longer worked. I now understand why - * after rebooting 0x7f already was 0x05, the value of my choice: the BIOS - * did it. - * - * Oh, and this is another trap: in ES1887 docs mixer register 0x70 is - * described as if it's exactly the same as register 0xa1. This is *NOT* true. - * The description of 0x70 in ES1869 docs is accurate however. - * Well, the assumption about ES1869 was wrong: register 0x70 is very much - * like register 0xa1, except that bit 7 is always 1, whatever you want - * it to be. - * - * When using audio 2 mixer register 0x72 seems te be meaningless. Only 0xa2 - * has effect. - * - * Software reset not being able to reset all registers is great! Especially - * the fact that register 0x78 isn't reset is great when you wanna change back - * to single dma operation (simplex): audio 2 is still operational, and uses - * the same dma as audio 1: your ess changes into a funny echo machine. - * - * Received the news that ES1688 is detected as a ES1788. Did some thinking: - * the ES1887 detection scheme suggests in step 2 to try if bit 3 of register - * 0x64 can be changed. This is inaccurate, first I inverted the * check: "If - * can be modified, it's a 1688", which lead to a correct detection - * of my ES1887. It resulted however in bad detection of 1688 (reported by mail) - * and 1868 (if no PnP detection first): they result in a 1788 being detected. - * I don't have docs on 1688, but I do have docs on 1868: The documentation is - * probably inaccurate in the fact that I should check bit 2, not bit 3. This - * is what I do now. - */ - -/* - * About recognition of ESS chips - * - * The distinction of ES688, ES1688, ES1788, ES1887 and ES1888 is described in - * a (preliminary ??) datasheet on ES1887. Its aim is to identify ES1887, but - * during detection the text claims that "this chip may be ..." when a step - * fails. This scheme is used to distinct between the above chips. - * It appears however that some PnP chips like ES1868 are recognized as ES1788 - * by the ES1887 detection scheme. These PnP chips can be detected in another - * way however: ES1868, ES1869 and ES1878 can be recognized (full proof I think) - * by repeatedly reading mixer register 0x40. This is done by ess_identify in - * sb_common.c. - * This results in the following detection steps: - * - distinct between ES688 and ES1688+ (as always done in this driver) - * if ES688 we're ready - * - try to detect ES1868, ES1869 or ES1878 - * if successful we're ready - * - try to detect ES1888, ES1887 or ES1788 - * if successful we're ready - * - Dunno. Must be 1688. Will do in general - * - * About RECLEV support: - * - * The existing ES1688 support didn't take care of the ES1688+ recording - * levels very well. Whenever a device was selected (recmask) for recording - * its recording level was loud, and it couldn't be changed. The fact that - * internal register 0xb4 could take care of RECLEV, didn't work meaning until - * its value was restored every time the chip was reset; this reset the - * value of 0xb4 too. I guess that's what 4front also had (have?) trouble with. - * - * About ES1887 support: - * - * The ES1887 has separate registers to control the recording levels, for all - * inputs. The ES1887 specific software makes these levels the same as their - * corresponding playback levels, unless recmask says they aren't recorded. In - * the latter case the recording volumes are 0. - * Now recording levels of inputs can be controlled, by changing the playback - * levels. Furthermore several devices can be recorded together (which is not - * possible with the ES1688). - * Besides the separate recording level control for each input, the common - * recording level can also be controlled by RECLEV as described above. - * - * Not only ES1887 have this recording mixer. I know the following from the - * documentation: - * ES688 no - * ES1688 no - * ES1868 no - * ES1869 yes - * ES1878 no - * ES1879 yes - * ES1888 no/yes Contradicting documentation; most recent: yes - * ES1946 yes This is a PCI chip; not handled by this driver - */ - -#include -#include -#include - -#include "sound_config.h" -#include "sb_mixer.h" -#include "sb.h" - -#include "sb_ess.h" - -#define ESSTYPE_LIKE20 -1 /* Mimic 2.0 behaviour */ -#define ESSTYPE_DETECT 0 /* Mimic 2.0 behaviour */ - -#define SUBMDL_ES1788 0x10 /* Subtype ES1788 for specific handling */ -#define SUBMDL_ES1868 0x11 /* Subtype ES1868 for specific handling */ -#define SUBMDL_ES1869 0x12 /* Subtype ES1869 for specific handling */ -#define SUBMDL_ES1878 0x13 /* Subtype ES1878 for specific handling */ -#define SUBMDL_ES1879 0x16 /* ES1879 was initially forgotten */ -#define SUBMDL_ES1887 0x14 /* Subtype ES1887 for specific handling */ -#define SUBMDL_ES1888 0x15 /* Subtype ES1888 for specific handling */ - -#define SB_CAP_ES18XX_RATE 0x100 - -#define ES1688_CLOCK1 795444 /* 128 - div */ -#define ES1688_CLOCK2 397722 /* 256 - div */ -#define ES18XX_CLOCK1 793800 /* 128 - div */ -#define ES18XX_CLOCK2 768000 /* 256 - div */ - -#ifdef FKS_LOGGING -static void ess_show_mixerregs (sb_devc *devc); -#endif -static int ess_read (sb_devc * devc, unsigned char reg); -static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data); -static void ess_chgmixer - (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val); - -/**************************************************************************** - * * - * ESS audio * - * * - ****************************************************************************/ - -struct ess_command {short cmd; short data;}; - -/* - * Commands for initializing Audio 1 for input (record) - */ -static struct ess_command ess_i08m[] = /* input 8 bit mono */ - { {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} }; -static struct ess_command ess_i16m[] = /* input 16 bit mono */ - { {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} }; -static struct ess_command ess_i08s[] = /* input 8 bit stereo */ - { {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} }; -static struct ess_command ess_i16s[] = /* input 16 bit stereo */ - { {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} }; - -static struct ess_command *ess_inp_cmds[] = - { ess_i08m, ess_i16m, ess_i08s, ess_i16s }; - - -/* - * Commands for initializing Audio 1 for output (playback) - */ -static struct ess_command ess_o08m[] = /* output 8 bit mono */ - { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} }; -static struct ess_command ess_o16m[] = /* output 16 bit mono */ - { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} }; -static struct ess_command ess_o08s[] = /* output 8 bit stereo */ - { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} }; -static struct ess_command ess_o16s[] = /* output 16 bit stereo */ - { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} }; - -static struct ess_command *ess_out_cmds[] = - { ess_o08m, ess_o16m, ess_o08s, ess_o16s }; - -static void ess_exec_commands - (sb_devc *devc, struct ess_command *cmdtab[]) -{ - struct ess_command *cmd; - - cmd = cmdtab [ ((devc->channels != 1) << 1) + (devc->bits != AFMT_U8) ]; - - while (cmd->cmd != -1) { - ess_write (devc, cmd->cmd, cmd->data); - cmd++; - } -} - -static void ess_change - (sb_devc *devc, unsigned int reg, unsigned int mask, unsigned int val) -{ - int value; - - value = ess_read (devc, reg); - value = (value & ~mask) | (val & mask); - ess_write (devc, reg, value); -} - -static void ess_set_output_parms - (int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (devc->duplex) { - devc->trg_buf_16 = buf; - devc->trg_bytes_16 = nr_bytes; - devc->trg_intrflag_16 = intrflag; - devc->irq_mode_16 = IMODE_OUTPUT; - } else { - devc->trg_buf = buf; - devc->trg_bytes = nr_bytes; - devc->trg_intrflag = intrflag; - devc->irq_mode = IMODE_OUTPUT; - } -} - -static void ess_set_input_parms - (int dev, unsigned long buf, int count, int intrflag) -{ - sb_devc *devc = audio_devs[dev]->devc; - - devc->trg_buf = buf; - devc->trg_bytes = count; - devc->trg_intrflag = intrflag; - devc->irq_mode = IMODE_INPUT; -} - -static int ess_calc_div (int clock, int revert, int *speedp, int *diffp) -{ - int divider; - int speed, diff; - int retval; - - speed = *speedp; - divider = (clock + speed / 2) / speed; - retval = revert - divider; - if (retval > revert - 1) { - retval = revert - 1; - divider = revert - retval; - } - /* This line is suggested. Must be wrong I think - *speedp = (clock + divider / 2) / divider; - So I chose the next one */ - - *speedp = clock / divider; - diff = speed - *speedp; - if (diff < 0) diff =-diff; - *diffp = diff; - - return retval; -} - -static int ess_calc_best_speed - (int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp) -{ - int speed1 = *speedp, speed2 = *speedp; - int div1, div2; - int diff1, diff2; - int retval; - - div1 = ess_calc_div (clock1, rev1, &speed1, &diff1); - div2 = ess_calc_div (clock2, rev2, &speed2, &diff2); - - if (diff1 < diff2) { - *divp = div1; - *speedp = speed1; - retval = 1; - } else { - /* *divp = div2; */ - *divp = 0x80 | div2; - *speedp = speed2; - retval = 2; - } - - return retval; -} - -/* - * Depending on the audiochannel ESS devices can - * have different clock settings. These are made consistent for duplex - * however. - * callers of ess_speed only do an audionum suggestion, which means - * input suggests 1, output suggests 2. This suggestion is only true - * however when doing duplex. - */ -static void ess_common_speed (sb_devc *devc, int *speedp, int *divp) -{ - int diff = 0, div; - - if (devc->duplex) { - /* - * The 0x80 is important for the first audio channel - */ - if (devc->submodel == SUBMDL_ES1888) { - div = 0x80 | ess_calc_div (795500, 256, speedp, &diff); - } else { - div = 0x80 | ess_calc_div (795500, 128, speedp, &diff); - } - } else if(devc->caps & SB_CAP_ES18XX_RATE) { - if (devc->submodel == SUBMDL_ES1888) { - ess_calc_best_speed(397700, 128, 795500, 256, - &div, speedp); - } else { - ess_calc_best_speed(ES18XX_CLOCK1, 128, ES18XX_CLOCK2, 256, - &div, speedp); - } - } else { - if (*speedp > 22000) { - div = 0x80 | ess_calc_div (ES1688_CLOCK1, 256, speedp, &diff); - } else { - div = 0x00 | ess_calc_div (ES1688_CLOCK2, 128, speedp, &diff); - } - } - *divp = div; -} - -static void ess_speed (sb_devc *devc, int audionum) -{ - int speed; - int div, div2; - - ess_common_speed (devc, &(devc->speed), &div); - -#ifdef FKS_REG_LOGGING -printk (KERN_INFO "FKS: ess_speed (%d) b speed = %d, div=%x\n", audionum, devc->speed, div); -#endif - - /* Set filter roll-off to 90% of speed/2 */ - speed = (devc->speed * 9) / 20; - - div2 = 256 - 7160000 / (speed * 82); - - if (!devc->duplex) audionum = 1; - - if (audionum == 1) { - /* Change behaviour of register A1 * - sb_chg_mixer(devc, 0x71, 0x20, 0x20) - * For ES1869 only??? */ - ess_write (devc, 0xa1, div); - ess_write (devc, 0xa2, div2); - } else { - ess_setmixer (devc, 0x70, div); - /* - * FKS: fascinating: 0x72 doesn't seem to work. - */ - ess_write (devc, 0xa2, div2); - ess_setmixer (devc, 0x72, div2); - } -} - -static int ess_audio_prepare_for_input(int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - - ess_speed(devc, 1); - - sb_dsp_command(devc, DSP_CMD_SPKOFF); - - ess_write (devc, 0xb8, 0x0e); /* Auto init DMA mode */ - ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */ - ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ - - ess_exec_commands (devc, ess_inp_cmds); - - ess_change (devc, 0xb1, 0xf0, 0x50); - ess_change (devc, 0xb2, 0xf0, 0x50); - - devc->trigger_bits = 0; - return 0; -} - -static int ess_audio_prepare_for_output_audio1 (int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - - sb_dsp_reset(devc); - ess_speed(devc, 1); - ess_write (devc, 0xb8, 4); /* Auto init DMA mode */ - ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */ - ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/request) */ - - ess_exec_commands (devc, ess_out_cmds); - - ess_change (devc, 0xb1, 0xf0, 0x50); /* Enable DMA */ - ess_change (devc, 0xb2, 0xf0, 0x50); /* Enable IRQ */ - - sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */ - - devc->trigger_bits = 0; - return 0; -} - -static int ess_audio_prepare_for_output_audio2 (int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - unsigned char bits; - -/* FKS: qqq - sb_dsp_reset(devc); -*/ - - /* - * Auto-Initialize: - * DMA mode + demand mode (8 bytes/request, yes I want it all!) - * But leave 16-bit DMA bit untouched! - */ - ess_chgmixer (devc, 0x78, 0xd0, 0xd0); - - ess_speed(devc, 2); - - /* bits 4:3 on ES1887 represent recording source. Keep them! */ - bits = ess_getmixer (devc, 0x7a) & 0x18; - - /* Set stereo/mono */ - if (devc->channels != 1) bits |= 0x02; - - /* Init DACs; UNSIGNED mode for 8 bit; SIGNED mode for 16 bit */ - if (devc->bits != AFMT_U8) bits |= 0x05; /* 16 bit */ - - /* Enable DMA, IRQ will be shared (hopefully)*/ - bits |= 0x60; - - ess_setmixer (devc, 0x7a, bits); - - ess_mixer_reload (devc, SOUND_MIXER_PCM); /* There be sound! */ - - devc->trigger_bits = 0; - return 0; -} - -static int ess_audio_prepare_for_output(int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - -#ifdef FKS_REG_LOGGING -printk(KERN_INFO "ess_audio_prepare_for_output: dma_out=%d,dma_in=%d\n" -, audio_devs[dev]->dmap_out->dma, audio_devs[dev]->dmap_in->dma); -#endif - - if (devc->duplex) { - return ess_audio_prepare_for_output_audio2 (dev, bsize, bcount); - } else { - return ess_audio_prepare_for_output_audio1 (dev, bsize, bcount); - } -} - -static void ess_audio_halt_xfer(int dev) -{ - unsigned long flags; - sb_devc *devc = audio_devs[dev]->devc; - - spin_lock_irqsave(&devc->lock, flags); - sb_dsp_reset(devc); - spin_unlock_irqrestore(&devc->lock, flags); - - /* - * Audio 2 may still be operational! Creates awful sounds! - */ - if (devc->duplex) ess_chgmixer(devc, 0x78, 0x03, 0x00); -} - -static void ess_audio_start_input - (int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - short c = -nr_bytes; - - /* - * Start a DMA input to the buffer pointed by dmaqtail - */ - - if (audio_devs[dev]->dmap_in->dma > 3) count >>= 1; - count--; - - devc->irq_mode = IMODE_INPUT; - - ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff)); - ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff)); - - ess_change (devc, 0xb8, 0x0f, 0x0f); /* Go */ - devc->intr_active = 1; -} - -static void ess_audio_output_block_audio1 - (int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - short c = -nr_bytes; - - if (audio_devs[dev]->dmap_out->dma > 3) - count >>= 1; - count--; - - devc->irq_mode = IMODE_OUTPUT; - - ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff)); - ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff)); - - ess_change (devc, 0xb8, 0x05, 0x05); /* Go */ - devc->intr_active = 1; -} - -static void ess_audio_output_block_audio2 - (int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - short c = -nr_bytes; - - if (audio_devs[dev]->dmap_out->dma > 3) count >>= 1; - count--; - - ess_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff)); - ess_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff)); - ess_chgmixer (devc, 0x78, 0x03, 0x03); /* Go */ - - devc->irq_mode_16 = IMODE_OUTPUT; - devc->intr_active_16 = 1; -} - -static void ess_audio_output_block - (int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (devc->duplex) { - ess_audio_output_block_audio2 (dev, buf, nr_bytes, intrflag); - } else { - ess_audio_output_block_audio1 (dev, buf, nr_bytes, intrflag); - } -} - -/* - * FKS: the if-statements for both bits and bits_16 are quite alike. - * Combine this... - */ -static void ess_audio_trigger(int dev, int bits) -{ - sb_devc *devc = audio_devs[dev]->devc; - - int bits_16 = bits & devc->irq_mode_16; - bits &= devc->irq_mode; - - if (!bits && !bits_16) { - /* FKS oh oh.... wrong?? for dma 16? */ - sb_dsp_command(devc, 0xd0); /* Halt DMA */ - } - - if (bits) { - switch (devc->irq_mode) - { - case IMODE_INPUT: - ess_audio_start_input(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - - case IMODE_OUTPUT: - ess_audio_output_block(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - } - } - - if (bits_16) { - switch (devc->irq_mode_16) { - case IMODE_INPUT: - ess_audio_start_input(dev, devc->trg_buf_16, devc->trg_bytes_16, - devc->trg_intrflag_16); - break; - - case IMODE_OUTPUT: - ess_audio_output_block(dev, devc->trg_buf_16, devc->trg_bytes_16, - devc->trg_intrflag_16); - break; - } - } - - devc->trigger_bits = bits | bits_16; -} - -static int ess_audio_set_speed(int dev, int speed) -{ - sb_devc *devc = audio_devs[dev]->devc; - int minspeed, maxspeed, dummydiv; - - if (speed > 0) { - minspeed = (devc->duplex ? 6215 : 5000 ); - maxspeed = (devc->duplex ? 44100 : 48000); - if (speed < minspeed) speed = minspeed; - if (speed > maxspeed) speed = maxspeed; - - ess_common_speed (devc, &speed, &dummydiv); - - devc->speed = speed; - } - return devc->speed; -} - -/* - * FKS: This is a one-on-one copy of sb1_audio_set_bits - */ -static unsigned int ess_audio_set_bits(int dev, unsigned int bits) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (bits != 0) { - if (bits == AFMT_U8 || bits == AFMT_S16_LE) { - devc->bits = bits; - } else { - devc->bits = AFMT_U8; - } - } - - return devc->bits; -} - -/* - * FKS: This is a one-on-one copy of sbpro_audio_set_channels - * (*) Modified it!! - */ -static short ess_audio_set_channels(int dev, short channels) -{ - sb_devc *devc = audio_devs[dev]->devc; - - if (channels == 1 || channels == 2) devc->channels = channels; - - return devc->channels; -} - -static struct audio_driver ess_audio_driver = /* ESS ES688/1688 */ -{ - .owner = THIS_MODULE, - .open = sb_audio_open, - .close = sb_audio_close, - .output_block = ess_set_output_parms, - .start_input = ess_set_input_parms, - .prepare_for_input = ess_audio_prepare_for_input, - .prepare_for_output = ess_audio_prepare_for_output, - .halt_io = ess_audio_halt_xfer, - .trigger = ess_audio_trigger, - .set_speed = ess_audio_set_speed, - .set_bits = ess_audio_set_bits, - .set_channels = ess_audio_set_channels -}; - -/* - * ess_audio_init must be called from sb_audio_init - */ -struct audio_driver *ess_audio_init - (sb_devc *devc, int *audio_flags, int *format_mask) -{ - *audio_flags = DMA_AUTOMODE; - *format_mask |= AFMT_S16_LE; - - if (devc->duplex) { - int tmp_dma; - /* - * sb_audio_init thinks dma8 is for playback and - * dma16 is for record. Not now! So swap them. - */ - tmp_dma = devc->dma16; - devc->dma16 = devc->dma8; - devc->dma8 = tmp_dma; - - *audio_flags |= DMA_DUPLEX; - } - - return &ess_audio_driver; -} - -/**************************************************************************** - * * - * ESS common * - * * - ****************************************************************************/ -static void ess_handle_channel - (char *channel, int dev, int intr_active, unsigned char flag, int irq_mode) -{ - if (!intr_active || !flag) return; -#ifdef FKS_REG_LOGGING -printk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode); -#endif - switch (irq_mode) { - case IMODE_OUTPUT: - DMAbuf_outputintr (dev, 1); - break; - - case IMODE_INPUT: - DMAbuf_inputintr (dev); - break; - - case IMODE_INIT: - break; - - default:; - /* printk(KERN_WARNING "ESS: Unexpected interrupt\n"); */ - } -} - -/* - * FKS: TODO!!! Finish this! - * - * I think midi stuff uses uart401, without interrupts. - * So IMODE_MIDI isn't a value for devc->irq_mode. - */ -void ess_intr (sb_devc *devc) -{ - int status; - unsigned char src; - - if (devc->submodel == SUBMDL_ES1887) { - src = ess_getmixer (devc, 0x7f) >> 4; - } else { - src = 0xff; - } - -#ifdef FKS_REG_LOGGING -printk(KERN_INFO "FKS: sbintr src=%x\n",(int)src); -#endif - ess_handle_channel - ( "Audio 1" - , devc->dev, devc->intr_active , src & 0x01, devc->irq_mode ); - ess_handle_channel - ( "Audio 2" - , devc->dev, devc->intr_active_16, src & 0x02, devc->irq_mode_16); - /* - * Acknowledge interrupts - */ - if (devc->submodel == SUBMDL_ES1887 && (src & 0x02)) { - ess_chgmixer (devc, 0x7a, 0x80, 0x00); - } - - if (src & 0x01) { - status = inb(DSP_DATA_AVAIL); - } -} - -static void ess_extended (sb_devc * devc) -{ - /* Enable extended mode */ - - sb_dsp_command(devc, 0xc6); -} - -static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data) -{ -#ifdef FKS_REG_LOGGING -printk(KERN_INFO "FKS: write reg %x: %x\n", reg, data); -#endif - /* Write a byte to an extended mode register of ES1688 */ - - if (!sb_dsp_command(devc, reg)) - return 0; - - return sb_dsp_command(devc, data); -} - -static int ess_read (sb_devc * devc, unsigned char reg) -{ - /* Read a byte from an extended mode register of ES1688 */ - - /* Read register command */ - if (!sb_dsp_command(devc, 0xc0)) return -1; - - if (!sb_dsp_command(devc, reg )) return -1; - - return sb_dsp_get_byte(devc); -} - -int ess_dsp_reset(sb_devc * devc) -{ - int loopc; - -#ifdef FKS_REG_LOGGING -printk(KERN_INFO "FKS: ess_dsp_reset 1\n"); -ess_show_mixerregs (devc); -#endif - - DEB(printk("Entered ess_dsp_reset()\n")); - - outb(3, DSP_RESET); /* Reset FIFO too */ - - udelay(10); - outb(0, DSP_RESET); - udelay(30); - - for (loopc = 0; loopc < 1000 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++); - - if (inb(DSP_READ) != 0xAA) { - DDB(printk("sb: No response to RESET\n")); - return 0; /* Sorry */ - } - ess_extended (devc); - - DEB(printk("sb_dsp_reset() OK\n")); - -#ifdef FKS_LOGGING -printk(KERN_INFO "FKS: dsp_reset 2\n"); -ess_show_mixerregs (devc); -#endif - - return 1; -} - -static int ess_irq_bits (int irq) -{ - switch (irq) { - case 2: - case 9: - return 0; - - case 5: - return 1; - - case 7: - return 2; - - case 10: - return 3; - - default: - printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", irq); - return -1; - } -} - -/* - * Set IRQ configuration register for all ESS models - */ -static int ess_common_set_irq_hw (sb_devc * devc) -{ - int irq_bits; - - if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return 0; - - if (!ess_write (devc, 0xb1, 0x50 | (irq_bits << 2))) { - printk(KERN_ERR "ES1688: Failed to write to IRQ config register\n"); - return 0; - } - return 1; -} - -/* - * I wanna use modern ES1887 mixer irq handling. Funny is the - * fact that my BIOS wants the same. But suppose someone's BIOS - * doesn't do this! - * This is independent of duplex. If there's a 1887 this will - * prevent it from going into 1888 mode. - */ -static void ess_es1887_set_irq_hw (sb_devc * devc) -{ - int irq_bits; - - if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return; - - ess_chgmixer (devc, 0x7f, 0x0f, 0x01 | ((irq_bits + 1) << 1)); -} - -static int ess_set_irq_hw (sb_devc * devc) -{ - if (devc->submodel == SUBMDL_ES1887) ess_es1887_set_irq_hw (devc); - - return ess_common_set_irq_hw (devc); -} - -#ifdef FKS_TEST - -/* - * FKS_test: - * for ES1887: 00, 18, non wr bits: 0001 1000 - * for ES1868: 00, b8, non wr bits: 1011 1000 - * for ES1888: 00, f8, non wr bits: 1111 1000 - * for ES1688: 00, f8, non wr bits: 1111 1000 - * + ES968 - */ - -static void FKS_test (sb_devc * devc) -{ - int val1, val2; - val1 = ess_getmixer (devc, 0x64); - ess_setmixer (devc, 0x64, ~val1); - val2 = ess_getmixer (devc, 0x64) ^ ~val1; - ess_setmixer (devc, 0x64, val1); - val1 ^= ess_getmixer (devc, 0x64); -printk (KERN_INFO "FKS: FKS_test %02x, %02x\n", (val1 & 0x0ff), (val2 & 0x0ff)); -}; -#endif - -static unsigned int ess_identify (sb_devc * devc) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&devc->lock, flags); - outb(((unsigned char) (0x40 & 0xff)), MIXER_ADDR); - - udelay(20); - val = inb(MIXER_DATA) << 8; - udelay(20); - val |= inb(MIXER_DATA); - udelay(20); - spin_unlock_irqrestore(&devc->lock, flags); - - return val; -} - -/* - * ESS technology describes a detection scheme in their docs. It involves - * fiddling with the bits in certain mixer registers. ess_probe is supposed - * to help. - * - * FKS: tracing shows ess_probe writes wrong value to 0x64. Bit 3 reads 1, but - * should be written 0 only. Check this. - */ -static int ess_probe (sb_devc * devc, int reg, int xorval) -{ - int val1, val2, val3; - - val1 = ess_getmixer (devc, reg); - val2 = val1 ^ xorval; - ess_setmixer (devc, reg, val2); - val3 = ess_getmixer (devc, reg); - ess_setmixer (devc, reg, val1); - - return (val2 == val3); -} - -int ess_init(sb_devc * devc, struct address_info *hw_config) -{ - unsigned char cfg; - int ess_major = 0, ess_minor = 0; - int i; - static char name[100], modelname[10]; - - /* - * Try to detect ESS chips. - */ - - sb_dsp_command(devc, 0xe7); /* Return identification */ - - for (i = 1000; i; i--) { - if (inb(DSP_DATA_AVAIL) & 0x80) { - if (ess_major == 0) { - ess_major = inb(DSP_READ); - } else { - ess_minor = inb(DSP_READ); - break; - } - } - } - - if (ess_major == 0) return 0; - - if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) { - sprintf(name, "ESS ES488 AudioDrive (rev %d)", - ess_minor & 0x0f); - hw_config->name = name; - devc->model = MDL_SBPRO; - return 1; - } - - /* - * This the detection heuristic of ESS technology, though somewhat - * changed to actually make it work. - * This results in the following detection steps: - * - distinct between ES688 and ES1688+ (as always done in this driver) - * if ES688 we're ready - * - try to detect ES1868, ES1869 or ES1878 (ess_identify) - * if successful we're ready - * - try to detect ES1888, ES1887 or ES1788 (aim: detect ES1887) - * if successful we're ready - * - Dunno. Must be 1688. Will do in general - * - * This is the most BETA part of the software: Will the detection - * always work? - */ - devc->model = MDL_ESS; - devc->submodel = ess_minor & 0x0f; - - if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) { - char *chip = NULL; - int submodel = -1; - - switch (devc->sbmo.esstype) { - case ESSTYPE_DETECT: - case ESSTYPE_LIKE20: - break; - case 688: - submodel = 0x00; - break; - case 1688: - submodel = 0x08; - break; - case 1868: - submodel = SUBMDL_ES1868; - break; - case 1869: - submodel = SUBMDL_ES1869; - break; - case 1788: - submodel = SUBMDL_ES1788; - break; - case 1878: - submodel = SUBMDL_ES1878; - break; - case 1879: - submodel = SUBMDL_ES1879; - break; - case 1887: - submodel = SUBMDL_ES1887; - break; - case 1888: - submodel = SUBMDL_ES1888; - break; - default: - printk (KERN_ERR "Invalid esstype=%d specified\n", devc->sbmo.esstype); - return 0; - }; - if (submodel != -1) { - devc->submodel = submodel; - sprintf (modelname, "ES%d", devc->sbmo.esstype); - chip = modelname; - }; - if (chip == NULL && (ess_minor & 0x0f) < 8) { - chip = "ES688"; - }; -#ifdef FKS_TEST -FKS_test (devc); -#endif - /* - * If Nothing detected yet, and we want 2.0 behaviour... - * Then let's assume it's ES1688. - */ - if (chip == NULL && devc->sbmo.esstype == ESSTYPE_LIKE20) { - chip = "ES1688"; - }; - - if (chip == NULL) { - int type; - - type = ess_identify (devc); - - switch (type) { - case 0x1868: - chip = "ES1868"; - devc->submodel = SUBMDL_ES1868; - break; - case 0x1869: - chip = "ES1869"; - devc->submodel = SUBMDL_ES1869; - break; - case 0x1878: - chip = "ES1878"; - devc->submodel = SUBMDL_ES1878; - break; - case 0x1879: - chip = "ES1879"; - devc->submodel = SUBMDL_ES1879; - break; - default: - if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) { - printk ("ess_init: Unrecognized %04x\n", type); - } - }; - }; -#if 0 - /* - * this one failed: - * the probing of bit 4 is another thought: from ES1788 and up, all - * chips seem to have hardware volume control. Bit 4 is readonly to - * check if a hardware volume interrupt has fired. - * Cause ES688/ES1688 don't have this feature, bit 4 might be writeable - * for these chips. - */ - if (chip == NULL && !ess_probe(devc, 0x64, (1 << 4))) { -#endif - /* - * the probing of bit 2 is my idea. The ES1887 docs want me to probe - * bit 3. This results in ES1688 being detected as ES1788. - * Bit 2 is for "Enable HWV IRQE", but as ES(1)688 chips don't have - * HardWare Volume, I think they don't have this IRQE. - */ - if (chip == NULL && ess_probe(devc, 0x64, (1 << 2))) { - if (ess_probe (devc, 0x70, 0x7f)) { - if (ess_probe (devc, 0x64, (1 << 5))) { - chip = "ES1887"; - devc->submodel = SUBMDL_ES1887; - } else { - chip = "ES1888"; - devc->submodel = SUBMDL_ES1888; - } - } else { - chip = "ES1788"; - devc->submodel = SUBMDL_ES1788; - } - }; - if (chip == NULL) { - chip = "ES1688"; - }; - - printk ( KERN_INFO "ESS chip %s %s%s\n" - , chip - , ( devc->sbmo.esstype == ESSTYPE_DETECT || devc->sbmo.esstype == ESSTYPE_LIKE20 - ? "detected" - : "specified" - ) - , ( devc->sbmo.esstype == ESSTYPE_LIKE20 - ? " (kernel 2.0 compatible)" - : "" - ) - ); - - sprintf(name,"ESS %s AudioDrive (rev %d)", chip, ess_minor & 0x0f); - } else { - strcpy(name, "Jazz16"); - } - - /* AAS: info stolen from ALSA: these boards have different clocks */ - switch(devc->submodel) { -/* APPARENTLY NOT 1869 AND 1887 - case SUBMDL_ES1869: - case SUBMDL_ES1887: -*/ - case SUBMDL_ES1888: - devc->caps |= SB_CAP_ES18XX_RATE; - break; - } - - hw_config->name = name; - /* FKS: sb_dsp_reset to enable extended mode???? */ - sb_dsp_reset(devc); /* Turn on extended mode */ - - /* - * Enable joystick and OPL3 - */ - cfg = ess_getmixer (devc, 0x40); - ess_setmixer (devc, 0x40, cfg | 0x03); - if (devc->submodel >= 8) { /* ES1688 */ - devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */ - } - sb_dsp_reset (devc); - - /* - * This is important! If it's not done, the IRQ probe in sb_dsp_init - * may fail. - */ - return ess_set_irq_hw (devc); -} - -static int ess_set_dma_hw(sb_devc * devc) -{ - unsigned char cfg, dma_bits = 0, dma16_bits; - int dma; - -#ifdef FKS_LOGGING -printk(KERN_INFO "ess_set_dma_hw: dma8=%d,dma16=%d,dup=%d\n" -, devc->dma8, devc->dma16, devc->duplex); -#endif - - /* - * FKS: It seems as if this duplex flag isn't set yet. Check it. - */ - dma = devc->dma8; - - if (dma > 3 || dma < 0 || dma == 2) { - dma_bits = 0; - printk(KERN_ERR "ESS1688: Invalid DMA8 %d\n", dma); - return 0; - } else { - /* Extended mode DMA enable */ - cfg = 0x50; - - if (dma == 3) { - dma_bits = 3; - } else { - dma_bits = dma + 1; - } - } - - if (!ess_write (devc, 0xb2, cfg | (dma_bits << 2))) { - printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n"); - return 0; - } - - if (devc->duplex) { - dma = devc->dma16; - dma16_bits = 0; - - if (dma >= 0) { - switch (dma) { - case 0: - dma_bits = 0x04; - break; - case 1: - dma_bits = 0x05; - break; - case 3: - dma_bits = 0x06; - break; - case 5: - dma_bits = 0x07; - dma16_bits = 0x20; - break; - default: - printk(KERN_ERR "ESS1887: Invalid DMA16 %d\n", dma); - return 0; - }; - ess_chgmixer (devc, 0x78, 0x20, dma16_bits); - ess_chgmixer (devc, 0x7d, 0x07, dma_bits); - } - } - return 1; -} - -/* - * This one is called from sb_dsp_init. - * - * Return values: - * 0: Failed - * 1: Succeeded or doesn't apply (not SUBMDL_ES1887) - */ -int ess_dsp_init (sb_devc *devc, struct address_info *hw_config) -{ - /* - * Caller also checks this, but anyway - */ - if (devc->model != MDL_ESS) { - printk (KERN_INFO "ess_dsp_init for non ESS chip\n"); - return 1; - } - /* - * This for ES1887 to run Full Duplex. Actually ES1888 - * is allowed to do so too. I have no idea yet if this - * will work for ES1888 however. - * - * For SB16 having both dma8 and dma16 means enable - * Full Duplex. Let's try this for ES1887 too - * - */ - if (devc->submodel == SUBMDL_ES1887) { - if (hw_config->dma2 != -1) { - devc->dma16 = hw_config->dma2; - } - /* - * devc->duplex initialization is put here, cause - * ess_set_dma_hw needs it. - */ - if (devc->dma8 != devc->dma16 && devc->dma16 != -1) { - devc->duplex = 1; - } - } - if (!ess_set_dma_hw (devc)) { - free_irq(devc->irq, devc); - return 0; - } - return 1; -} - -/**************************************************************************** - * * - * ESS mixer * - * * - ****************************************************************************/ - -#define ES688_RECORDING_DEVICES \ - ( SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD ) -#define ES688_MIXER_DEVICES \ - ( SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE \ - | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME \ - | SOUND_MASK_LINE2 | SOUND_MASK_SPEAKER ) - -#define ES1688_RECORDING_DEVICES \ - ( ES688_RECORDING_DEVICES ) -#define ES1688_MIXER_DEVICES \ - ( ES688_MIXER_DEVICES | SOUND_MASK_RECLEV ) - -#define ES1887_RECORDING_DEVICES \ - ( ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 | SOUND_MASK_SYNTH) -#define ES1887_MIXER_DEVICES \ - ( ES1688_MIXER_DEVICES ) - -/* - * Mixer registers of ES1887 - * - * These registers specifically take care of recording levels. To make the - * mapping from playback devices to recording devices every recording - * devices = playback device + ES_REC_MIXER_RECDIFF - */ -#define ES_REC_MIXER_RECBASE (SOUND_MIXER_LINE3 + 1) -#define ES_REC_MIXER_RECDIFF (ES_REC_MIXER_RECBASE - SOUND_MIXER_SYNTH) - -#define ES_REC_MIXER_RECSYNTH (SOUND_MIXER_SYNTH + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECPCM (SOUND_MIXER_PCM + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECSPEAKER (SOUND_MIXER_SPEAKER + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECLINE (SOUND_MIXER_LINE + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECMIC (SOUND_MIXER_MIC + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECCD (SOUND_MIXER_CD + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECIMIX (SOUND_MIXER_IMIX + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECRECLEV (SOUND_MIXER_RECLEV + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECIGAIN (SOUND_MIXER_IGAIN + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECOGAIN (SOUND_MIXER_OGAIN + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECLINE1 (SOUND_MIXER_LINE1 + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECLINE2 (SOUND_MIXER_LINE2 + ES_REC_MIXER_RECDIFF) -#define ES_REC_MIXER_RECLINE3 (SOUND_MIXER_LINE3 + ES_REC_MIXER_RECDIFF) - -static mixer_tab es688_mix = { -MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4), -MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4), -MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4), -MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4), -MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4), -MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4), -MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4), -MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0) -}; - -/* - * The ES1688 specifics... hopefully correct... - * - 6 bit master volume - * I was wrong, ES1888 docs say ES1688 didn't have it. - * - RECLEV control - * These may apply to ES688 too. I have no idea. - */ -static mixer_tab es1688_mix = { -MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4), -MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4), -MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4), -MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4), -MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4), -MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4), -MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4), -MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4), -MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0) -}; - -static mixer_tab es1688later_mix = { -MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6), -MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4), -MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4), -MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4), -MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4), -MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4), -MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4), -MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4), -MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0) -}; - -/* - * This one is for all ESS chips with a record mixer. - * It's not used (yet) however - */ -static mixer_tab es_rec_mix = { -MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6), -MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4), -MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4), -MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4), -MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4), -MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4), -MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4), -MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4), -MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4), -MIX_ENT(ES_REC_MIXER_RECPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECSPEAKER, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECLINE, 0x6e, 7, 4, 0x6e, 3, 4), -MIX_ENT(ES_REC_MIXER_RECMIC, 0x68, 7, 4, 0x68, 3, 4), -MIX_ENT(ES_REC_MIXER_RECCD, 0x6a, 7, 4, 0x6a, 3, 4), -MIX_ENT(ES_REC_MIXER_RECIMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECRECLEV, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4), -MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0) -}; - -/* - * This one is for ES1887. It's little different from es_rec_mix: it - * has 0x7c for PCM playback level. This is because ES1887 uses - * Audio 2 for playback. - */ -static mixer_tab es1887_mix = { -MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6), -MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4), -MIX_ENT(SOUND_MIXER_PCM, 0x7c, 7, 4, 0x7c, 3, 4), -MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4), -MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4), -MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4), -MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4), -MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4), -MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4), -MIX_ENT(ES_REC_MIXER_RECPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECSPEAKER, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECLINE, 0x6e, 7, 4, 0x6e, 3, 4), -MIX_ENT(ES_REC_MIXER_RECMIC, 0x68, 7, 4, 0x68, 3, 4), -MIX_ENT(ES_REC_MIXER_RECCD, 0x6a, 7, 4, 0x6a, 3, 4), -MIX_ENT(ES_REC_MIXER_RECIMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECRECLEV, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(ES_REC_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4), -MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0) -}; - -static int ess_has_rec_mixer (int submodel) -{ - switch (submodel) { - case SUBMDL_ES1887: - return 1; - default: - return 0; - }; -}; - -#ifdef FKS_LOGGING -static int ess_mixer_mon_regs[] - = { 0x70, 0x71, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7d, 0x7f - , 0xa1, 0xa2, 0xa4, 0xa5, 0xa8, 0xa9 - , 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb9 - , 0x00}; - -static void ess_show_mixerregs (sb_devc *devc) -{ - int *mp = ess_mixer_mon_regs; - -return; - - while (*mp != 0) { - printk (KERN_INFO "res (%x)=%x\n", *mp, (int)(ess_getmixer (devc, *mp))); - mp++; - } -} -#endif - -void ess_setmixer (sb_devc * devc, unsigned int port, unsigned int value) -{ - unsigned long flags; - -#ifdef FKS_LOGGING -printk(KERN_INFO "FKS: write mixer %x: %x\n", port, value); -#endif - - spin_lock_irqsave(&devc->lock, flags); - if (port >= 0xa0) { - ess_write (devc, port, value); - } else { - outb(((unsigned char) (port & 0xff)), MIXER_ADDR); - - udelay(20); - outb(((unsigned char) (value & 0xff)), MIXER_DATA); - udelay(20); - }; - spin_unlock_irqrestore(&devc->lock, flags); -} - -unsigned int ess_getmixer (sb_devc * devc, unsigned int port) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&devc->lock, flags); - - if (port >= 0xa0) { - val = ess_read (devc, port); - } else { - outb(((unsigned char) (port & 0xff)), MIXER_ADDR); - - udelay(20); - val = inb(MIXER_DATA); - udelay(20); - } - spin_unlock_irqrestore(&devc->lock, flags); - - return val; -} - -static void ess_chgmixer - (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val) -{ - int value; - - value = ess_getmixer (devc, reg); - value = (value & ~mask) | (val & mask); - ess_setmixer (devc, reg, value); -} - -/* - * ess_mixer_init must be called from sb_mixer_init - */ -void ess_mixer_init (sb_devc * devc) -{ - devc->mixer_caps = SOUND_CAP_EXCL_INPUT; - - /* - * Take care of ES1887 specifics... - */ - switch (devc->submodel) { - case SUBMDL_ES1887: - devc->supported_devices = ES1887_MIXER_DEVICES; - devc->supported_rec_devices = ES1887_RECORDING_DEVICES; -#ifdef FKS_LOGGING -printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex); -#endif - if (devc->duplex) { - devc->iomap = &es1887_mix; - devc->iomap_sz = ARRAY_SIZE(es1887_mix); - } else { - devc->iomap = &es_rec_mix; - devc->iomap_sz = ARRAY_SIZE(es_rec_mix); - } - break; - default: - if (devc->submodel < 8) { - devc->supported_devices = ES688_MIXER_DEVICES; - devc->supported_rec_devices = ES688_RECORDING_DEVICES; - devc->iomap = &es688_mix; - devc->iomap_sz = ARRAY_SIZE(es688_mix); - } else { - /* - * es1688 has 4 bits master vol. - * later chips have 6 bits (?) - */ - devc->supported_devices = ES1688_MIXER_DEVICES; - devc->supported_rec_devices = ES1688_RECORDING_DEVICES; - if (devc->submodel < 0x10) { - devc->iomap = &es1688_mix; - devc->iomap_sz = ARRAY_SIZE(es688_mix); - } else { - devc->iomap = &es1688later_mix; - devc->iomap_sz = ARRAY_SIZE(es1688later_mix); - } - } - } -} - -/* - * Changing playback levels at an ESS chip with record mixer means having to - * take care of recording levels of recorded inputs (devc->recmask) too! - */ -int ess_mixer_set(sb_devc *devc, int dev, int left, int right) -{ - if (ess_has_rec_mixer (devc->submodel) && (devc->recmask & (1 << dev))) { - sb_common_mixer_set (devc, dev + ES_REC_MIXER_RECDIFF, left, right); - } - return sb_common_mixer_set (devc, dev, left, right); -} - -/* - * After a sb_dsp_reset extended register 0xb4 (RECLEV) is reset too. After - * sb_dsp_reset RECLEV has to be restored. This is where ess_mixer_reload - * helps. - */ -void ess_mixer_reload (sb_devc *devc, int dev) -{ - int left, right, value; - - value = devc->levels[dev]; - left = value & 0x000000ff; - right = (value & 0x0000ff00) >> 8; - - sb_common_mixer_set(devc, dev, left, right); -} - -static int es_rec_set_recmask(sb_devc * devc, int mask) -{ - int i, i_mask, cur_mask, diff_mask; - int value, left, right; - -#ifdef FKS_LOGGING -printk (KERN_INFO "FKS: es_rec_set_recmask mask = %x\n", mask); -#endif - /* - * Changing the recmask on an ESS chip with recording mixer means: - * (1) Find the differences - * (2) For "turned-on" inputs: make the recording level the playback level - * (3) For "turned-off" inputs: make the recording level zero - */ - cur_mask = devc->recmask; - diff_mask = (cur_mask ^ mask); - - for (i = 0; i < 32; i++) { - i_mask = (1 << i); - if (diff_mask & i_mask) { /* Difference? (1) */ - if (mask & i_mask) { /* Turn it on (2) */ - value = devc->levels[i]; - left = value & 0x000000ff; - right = (value & 0x0000ff00) >> 8; - } else { /* Turn it off (3) */ - left = 0; - right = 0; - } - sb_common_mixer_set(devc, i + ES_REC_MIXER_RECDIFF, left, right); - } - } - return mask; -} - -int ess_set_recmask(sb_devc * devc, int *mask) -{ - /* This applies to ESS chips with record mixers only! */ - - if (ess_has_rec_mixer (devc->submodel)) { - *mask = es_rec_set_recmask (devc, *mask); - return 1; /* Applied */ - } else { - return 0; /* Not applied */ - } -} - -/* - * ess_mixer_reset must be called from sb_mixer_reset - */ -int ess_mixer_reset (sb_devc * devc) -{ - /* - * Separate actions for ESS chips with a record mixer: - */ - if (ess_has_rec_mixer (devc->submodel)) { - switch (devc->submodel) { - case SUBMDL_ES1887: - /* - * Separate actions for ES1887: - * Change registers 7a and 1c to make the record mixer the - * actual recording source. - */ - ess_chgmixer(devc, 0x7a, 0x18, 0x08); - ess_chgmixer(devc, 0x1c, 0x07, 0x07); - break; - }; - /* - * Call set_recmask for proper initialization - */ - devc->recmask = devc->supported_rec_devices; - es_rec_set_recmask(devc, 0); - devc->recmask = 0; - - return 1; /* We took care of recmask. */ - } else { - return 0; /* We didn't take care; caller do it */ - } -} - -/**************************************************************************** - * * - * ESS midi * - * * - ****************************************************************************/ - -/* - * FKS: IRQ may be shared. Hm. And if so? Then What? - */ -int ess_midi_init(sb_devc * devc, struct address_info *hw_config) -{ - unsigned char cfg, tmp; - - cfg = ess_getmixer (devc, 0x40) & 0x03; - - if (devc->submodel < 8) { - ess_setmixer (devc, 0x40, cfg | 0x03); /* Enable OPL3 & joystick */ - return 0; /* ES688 doesn't support MPU401 mode */ - } - tmp = (hw_config->io_base & 0x0f0) >> 4; - - if (tmp > 3) { - ess_setmixer (devc, 0x40, cfg); - return 0; - } - cfg |= tmp << 3; - - tmp = 1; /* MPU enabled without interrupts */ - - /* May be shared: if so the value is -ve */ - - switch (abs(hw_config->irq)) { - case 9: - tmp = 0x4; - break; - case 5: - tmp = 0x5; - break; - case 7: - tmp = 0x6; - break; - case 10: - tmp = 0x7; - break; - default: - return 0; - } - - cfg |= tmp << 5; - ess_setmixer (devc, 0x40, cfg | 0x03); - - return 1; -} - diff --git a/ANDROID_3.4.5/sound/oss/sb_ess.h b/ANDROID_3.4.5/sound/oss/sb_ess.h deleted file mode 100644 index 38aa072e..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_ess.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Created: 9-Jan-1999 Rolf Fokkens - */ - -extern void ess_intr - (sb_devc *devc); -extern int ess_dsp_init - (sb_devc *devc, struct address_info *hw_config); - -extern struct audio_driver *ess_audio_init - (sb_devc *devc, int *audio_flags, int *format_mask); -extern int ess_midi_init - (sb_devc *devc, struct address_info *hw_config); -extern void ess_mixer_init - (sb_devc *devc); - -extern int ess_init - (sb_devc *devc, struct address_info *hw_config); -extern int ess_dsp_reset - (sb_devc *devc); - -extern void ess_setmixer - (sb_devc *devc, unsigned int port, unsigned int value); -extern unsigned int ess_getmixer - (sb_devc *devc, unsigned int port); -extern int ess_mixer_set - (sb_devc *devc, int dev, int left, int right); -extern int ess_mixer_reset - (sb_devc *devc); -extern void ess_mixer_reload - (sb_devc * devc, int dev); -extern int ess_set_recmask - (sb_devc *devc, int *mask); - diff --git a/ANDROID_3.4.5/sound/oss/sb_midi.c b/ANDROID_3.4.5/sound/oss/sb_midi.c deleted file mode 100644 index f139028e..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_midi.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * sound/oss/sb_midi.c - * - * The low level driver for the Sound Blaster DS chips. - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - -#include -#include - -#include "sound_config.h" - -#include "sb.h" -#undef SB_TEST_IRQ - -/* - * The DSP channel can be used either for input or output. Variable - * 'sb_irq_mode' will be set when the program calls read or write first time - * after open. Current version doesn't support mode changes without closing - * and reopening the device. Support for this feature may be implemented in a - * future version of this driver. - */ - - -static int sb_midi_open(int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - sb_devc *devc = midi_devs[dev]->devc; - unsigned long flags; - - if (devc == NULL) - return -ENXIO; - - spin_lock_irqsave(&devc->lock, flags); - if (devc->opened) - { - spin_unlock_irqrestore(&devc->lock, flags); - return -EBUSY; - } - devc->opened = 1; - spin_unlock_irqrestore(&devc->lock, flags); - - devc->irq_mode = IMODE_MIDI; - devc->midi_broken = 0; - - sb_dsp_reset(devc); - - if (!sb_dsp_command(devc, 0x35)) /* Start MIDI UART mode */ - { - devc->opened = 0; - return -EIO; - } - devc->intr_active = 1; - - if (mode & OPEN_READ) - { - devc->input_opened = 1; - devc->midi_input_intr = input; - } - return 0; -} - -static void sb_midi_close(int dev) -{ - sb_devc *devc = midi_devs[dev]->devc; - unsigned long flags; - - if (devc == NULL) - return; - - spin_lock_irqsave(&devc->lock, flags); - sb_dsp_reset(devc); - devc->intr_active = 0; - devc->input_opened = 0; - devc->opened = 0; - spin_unlock_irqrestore(&devc->lock, flags); -} - -static int sb_midi_out(int dev, unsigned char midi_byte) -{ - sb_devc *devc = midi_devs[dev]->devc; - - if (devc == NULL) - return 1; - - if (devc->midi_broken) - return 1; - - if (!sb_dsp_command(devc, midi_byte)) - { - devc->midi_broken = 1; - return 1; - } - return 1; -} - -static int sb_midi_start_read(int dev) -{ - return 0; -} - -static int sb_midi_end_read(int dev) -{ - sb_devc *devc = midi_devs[dev]->devc; - - if (devc == NULL) - return -ENXIO; - - sb_dsp_reset(devc); - devc->intr_active = 0; - return 0; -} - -static int sb_midi_ioctl(int dev, unsigned cmd, void __user *arg) -{ - return -EINVAL; -} - -void sb_midi_interrupt(sb_devc * devc) -{ - unsigned long flags; - unsigned char data; - - if (devc == NULL) - return; - - spin_lock_irqsave(&devc->lock, flags); - - data = inb(DSP_READ); - if (devc->input_opened) - devc->midi_input_intr(devc->my_mididev, data); - - spin_unlock_irqrestore(&devc->lock, flags); -} - -#define MIDI_SYNTH_NAME "Sound Blaster Midi" -#define MIDI_SYNTH_CAPS 0 -#include "midi_synth.h" - -static struct midi_operations sb_midi_operations = -{ - .owner = THIS_MODULE, - .info = {"Sound Blaster", 0, 0, SNDCARD_SB}, - .converter = &std_midi_synth, - .in_info = {0}, - .open = sb_midi_open, - .close = sb_midi_close, - .ioctl = sb_midi_ioctl, - .outputc = sb_midi_out, - .start_read = sb_midi_start_read, - .end_read = sb_midi_end_read, -}; - -void sb_dsp_midi_init(sb_devc * devc, struct module *owner) -{ - int dev; - - if (devc->model < 2) /* No MIDI support for SB 1.x */ - return; - - dev = sound_alloc_mididev(); - - if (dev == -1) - { - printk(KERN_ERR "sb_midi: too many MIDI devices detected\n"); - return; - } - std_midi_synth.midi_dev = devc->my_mididev = dev; - midi_devs[dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL); - if (midi_devs[dev] == NULL) - { - printk(KERN_WARNING "Sound Blaster: failed to allocate MIDI memory.\n"); - sound_unload_mididev(dev); - return; - } - memcpy((char *) midi_devs[dev], (char *) &sb_midi_operations, - sizeof(struct midi_operations)); - - if (owner) - midi_devs[dev]->owner = owner; - - midi_devs[dev]->devc = devc; - - - midi_devs[dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL); - if (midi_devs[dev]->converter == NULL) - { - printk(KERN_WARNING "Sound Blaster: failed to allocate MIDI memory.\n"); - kfree(midi_devs[dev]); - sound_unload_mididev(dev); - return; - } - memcpy((char *) midi_devs[dev]->converter, (char *) &std_midi_synth, - sizeof(struct synth_operations)); - - midi_devs[dev]->converter->id = "SBMIDI"; - sequencer_init(); -} diff --git a/ANDROID_3.4.5/sound/oss/sb_mixer.c b/ANDROID_3.4.5/sound/oss/sb_mixer.c deleted file mode 100644 index f8f3b7a6..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_mixer.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * sound/oss/sb_mixer.c - * - * The low level mixer driver for the Sound Blaster compatible cards. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * Rolf Fokkens (Dec 20 1998) : Moved ESS stuff into sb_ess.[ch] - * Stanislav Voronyi : Support for AWE 3DSE device (Jun 7 1999) - */ - -#include - -#include "sound_config.h" - -#define __SB_MIXER_C__ - -#include "sb.h" -#include "sb_mixer.h" - -#include "sb_ess.h" - -#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD) - -/* Same as SB Pro, unless I find otherwise */ -#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES - -#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | SOUND_MASK_VOLUME) - -/* SG NX Pro has treble and bass settings on the mixer. The 'speaker' - * channel is the COVOX/DisneySoundSource emulation volume control - * on the mixer. It does NOT control speaker volume. Should have own - * mask eventually? - */ -#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \ - SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER ) - -#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD) - -#define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD) - -#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \ - SOUND_MASK_CD | \ - SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \ - SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \ - SOUND_MASK_IMIX) - -/* These are the only devices that are working at the moment. Others could - * be added once they are identified and a method is found to control them. - */ -#define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \ - SOUND_MASK_PCM | SOUND_MASK_MIC | \ - SOUND_MASK_CD | \ - SOUND_MASK_VOLUME) - -static mixer_tab sbpro_mix = { -MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4), -MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4), -MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4), -MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4), -MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4), -MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0) -}; - -static mixer_tab sb16_mix = { -MIX_ENT(SOUND_MIXER_VOLUME, 0x30, 7, 5, 0x31, 7, 5), -MIX_ENT(SOUND_MIXER_BASS, 0x46, 7, 4, 0x47, 7, 4), -MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 7, 4, 0x45, 7, 4), -MIX_ENT(SOUND_MIXER_SYNTH, 0x34, 7, 5, 0x35, 7, 5), -MIX_ENT(SOUND_MIXER_PCM, 0x32, 7, 5, 0x33, 7, 5), -MIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 7, 2, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 0x38, 7, 5, 0x39, 7, 5), -MIX_ENT(SOUND_MIXER_MIC, 0x3a, 7, 5, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_CD, 0x36, 7, 5, 0x37, 7, 5), -MIX_ENT(SOUND_MIXER_IMIX, 0x3c, 0, 1, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */ -MIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2), -MIX_ENT(SOUND_MIXER_OGAIN, 0x41, 7, 2, 0x42, 7, 2) -}; - -static mixer_tab als007_mix = -{ -MIX_ENT(SOUND_MIXER_VOLUME, 0x62, 7, 4, 0x62, 3, 4), -MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_SYNTH, 0x66, 7, 4, 0x66, 3, 4), -MIX_ENT(SOUND_MIXER_PCM, 0x64, 7, 4, 0x64, 3, 4), -MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_LINE, 0x6e, 7, 4, 0x6e, 3, 4), -MIX_ENT(SOUND_MIXER_MIC, 0x6a, 2, 3, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_CD, 0x68, 7, 4, 0x68, 3, 4), -MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */ -MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), -MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0) -}; - - -/* SM_GAMES Master volume is lower and PCM & FM volumes - higher than with SB Pro. This improves the - sound quality */ - -static int smg_default_levels[32] = -{ - 0x2020, /* Master Volume */ - 0x4b4b, /* Bass */ - 0x4b4b, /* Treble */ - 0x6464, /* FM */ - 0x6464, /* PCM */ - 0x4b4b, /* PC Speaker */ - 0x4b4b, /* Ext Line */ - 0x0000, /* Mic */ - 0x4b4b, /* CD */ - 0x4b4b, /* Recording monitor */ - 0x4b4b, /* SB PCM */ - 0x4b4b, /* Recording level */ - 0x4b4b, /* Input gain */ - 0x4b4b, /* Output gain */ - 0x4040, /* Line1 */ - 0x4040, /* Line2 */ - 0x1515 /* Line3 */ -}; - -static int sb_default_levels[32] = -{ - 0x5a5a, /* Master Volume */ - 0x4b4b, /* Bass */ - 0x4b4b, /* Treble */ - 0x4b4b, /* FM */ - 0x4b4b, /* PCM */ - 0x4b4b, /* PC Speaker */ - 0x4b4b, /* Ext Line */ - 0x1010, /* Mic */ - 0x4b4b, /* CD */ - 0x0000, /* Recording monitor */ - 0x4b4b, /* SB PCM */ - 0x4b4b, /* Recording level */ - 0x4b4b, /* Input gain */ - 0x4b4b, /* Output gain */ - 0x4040, /* Line1 */ - 0x4040, /* Line2 */ - 0x1515 /* Line3 */ -}; - -static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] = -{ - 0x00, /* SOUND_MIXER_VOLUME */ - 0x00, /* SOUND_MIXER_BASS */ - 0x00, /* SOUND_MIXER_TREBLE */ - 0x40, /* SOUND_MIXER_SYNTH */ - 0x00, /* SOUND_MIXER_PCM */ - 0x00, /* SOUND_MIXER_SPEAKER */ - 0x10, /* SOUND_MIXER_LINE */ - 0x01, /* SOUND_MIXER_MIC */ - 0x04, /* SOUND_MIXER_CD */ - 0x00, /* SOUND_MIXER_IMIX */ - 0x00, /* SOUND_MIXER_ALTPCM */ - 0x00, /* SOUND_MIXER_RECLEV */ - 0x00, /* SOUND_MIXER_IGAIN */ - 0x00 /* SOUND_MIXER_OGAIN */ -}; - -static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] = -{ - 0x00, /* SOUND_MIXER_VOLUME */ - 0x00, /* SOUND_MIXER_BASS */ - 0x00, /* SOUND_MIXER_TREBLE */ - 0x20, /* SOUND_MIXER_SYNTH */ - 0x00, /* SOUND_MIXER_PCM */ - 0x00, /* SOUND_MIXER_SPEAKER */ - 0x08, /* SOUND_MIXER_LINE */ - 0x01, /* SOUND_MIXER_MIC */ - 0x02, /* SOUND_MIXER_CD */ - 0x00, /* SOUND_MIXER_IMIX */ - 0x00, /* SOUND_MIXER_ALTPCM */ - 0x00, /* SOUND_MIXER_RECLEV */ - 0x00, /* SOUND_MIXER_IGAIN */ - 0x00 /* SOUND_MIXER_OGAIN */ -}; - -static char smw_mix_regs[] = /* Left mixer registers */ -{ - 0x0b, /* SOUND_MIXER_VOLUME */ - 0x0d, /* SOUND_MIXER_BASS */ - 0x0d, /* SOUND_MIXER_TREBLE */ - 0x05, /* SOUND_MIXER_SYNTH */ - 0x09, /* SOUND_MIXER_PCM */ - 0x00, /* SOUND_MIXER_SPEAKER */ - 0x03, /* SOUND_MIXER_LINE */ - 0x01, /* SOUND_MIXER_MIC */ - 0x07, /* SOUND_MIXER_CD */ - 0x00, /* SOUND_MIXER_IMIX */ - 0x00, /* SOUND_MIXER_ALTPCM */ - 0x00, /* SOUND_MIXER_RECLEV */ - 0x00, /* SOUND_MIXER_IGAIN */ - 0x00, /* SOUND_MIXER_OGAIN */ - 0x00, /* SOUND_MIXER_LINE1 */ - 0x00, /* SOUND_MIXER_LINE2 */ - 0x00 /* SOUND_MIXER_LINE3 */ -}; - -static int sbmixnum = 1; - -static void sb_mixer_reset(sb_devc * devc); - -void sb_mixer_set_stereo(sb_devc * devc, int mode) -{ - sb_chgmixer(devc, OUT_FILTER, STEREO_DAC, (mode ? STEREO_DAC : MONO_DAC)); -} - -static int detect_mixer(sb_devc * devc) -{ - /* Just trust the mixer is there */ - return 1; -} - -static void oss_change_bits(sb_devc *devc, unsigned char *regval, int dev, int chn, int newval) -{ - unsigned char mask; - int shift; - - mask = (1 << (*devc->iomap)[dev][chn].nbits) - 1; - newval = (int) ((newval * mask) + 50) / 100; /* Scale */ - - shift = (*devc->iomap)[dev][chn].bitoffs - (*devc->iomap)[dev][LEFT_CHN].nbits + 1; - - *regval &= ~(mask << shift); /* Mask out previous value */ - *regval |= (newval & mask) << shift; /* Set the new value */ -} - -static int sb_mixer_get(sb_devc * devc, int dev) -{ - if (!((1 << dev) & devc->supported_devices)) - return -EINVAL; - return devc->levels[dev]; -} - -void smw_mixer_init(sb_devc * devc) -{ - int i; - - sb_setmixer(devc, 0x00, 0x18); /* Mute unused (Telephone) line */ - sb_setmixer(devc, 0x10, 0x38); /* Config register 2 */ - - devc->supported_devices = 0; - for (i = 0; i < sizeof(smw_mix_regs); i++) - if (smw_mix_regs[i] != 0) - devc->supported_devices |= (1 << i); - - devc->supported_rec_devices = devc->supported_devices & - ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM | SOUND_MASK_VOLUME); - sb_mixer_reset(devc); -} - -int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right) -{ - int regoffs; - unsigned char val; - - if ((dev < 0) || (dev >= devc->iomap_sz)) - return -EINVAL; - - regoffs = (*devc->iomap)[dev][LEFT_CHN].regno; - - if (regoffs == 0) - return -EINVAL; - - val = sb_getmixer(devc, regoffs); - oss_change_bits(devc, &val, dev, LEFT_CHN, left); - - if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /* - * Change register - */ - { - sb_setmixer(devc, regoffs, val); /* - * Save the old one - */ - regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno; - - if (regoffs == 0) - return left | (left << 8); /* - * Just left channel present - */ - - val = sb_getmixer(devc, regoffs); /* - * Read the new one - */ - } - oss_change_bits(devc, &val, dev, RIGHT_CHN, right); - - sb_setmixer(devc, regoffs, val); - - return left | (right << 8); -} - -static int smw_mixer_set(sb_devc * devc, int dev, int left, int right) -{ - int reg, val; - - switch (dev) - { - case SOUND_MIXER_VOLUME: - sb_setmixer(devc, 0x0b, 96 - (96 * left / 100)); /* 96=mute, 0=max */ - sb_setmixer(devc, 0x0c, 96 - (96 * right / 100)); - break; - - case SOUND_MIXER_BASS: - case SOUND_MIXER_TREBLE: - devc->levels[dev] = left | (right << 8); - /* Set left bass and treble values */ - val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4; - val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f; - sb_setmixer(devc, 0x0d, val); - - /* Set right bass and treble values */ - val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4; - val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f; - sb_setmixer(devc, 0x0e, val); - - break; - - default: - /* bounds check */ - if (dev < 0 || dev >= ARRAY_SIZE(smw_mix_regs)) - return -EINVAL; - reg = smw_mix_regs[dev]; - if (reg == 0) - return -EINVAL; - sb_setmixer(devc, reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */ - sb_setmixer(devc, reg + 1, (24 - (24 * right / 100)) | 0x40); - } - - devc->levels[dev] = left | (right << 8); - return left | (right << 8); -} - -static int sb_mixer_set(sb_devc * devc, int dev, int value) -{ - int left = value & 0x000000ff; - int right = (value & 0x0000ff00) >> 8; - int retval; - - if (left > 100) - left = 100; - if (right > 100) - right = 100; - - if ((dev < 0) || (dev > 31)) - return -EINVAL; - - if (!(devc->supported_devices & (1 << dev))) /* - * Not supported - */ - return -EINVAL; - - /* Differentiate depending on the chipsets */ - switch (devc->model) { - case MDL_SMW: - retval = smw_mixer_set(devc, dev, left, right); - break; - case MDL_ESS: - retval = ess_mixer_set(devc, dev, left, right); - break; - default: - retval = sb_common_mixer_set(devc, dev, left, right); - } - if (retval >= 0) devc->levels[dev] = retval; - - return retval; -} - -/* - * set_recsrc doesn't apply to ES188x - */ -static void set_recsrc(sb_devc * devc, int src) -{ - sb_setmixer(devc, RECORD_SRC, (sb_getmixer(devc, RECORD_SRC) & ~7) | (src & 0x7)); -} - -static int set_recmask(sb_devc * devc, int mask) -{ - int devmask, i; - unsigned char regimageL, regimageR; - - devmask = mask & devc->supported_rec_devices; - - switch (devc->model) - { - case MDL_SBPRO: - case MDL_ESS: - case MDL_JAZZ: - case MDL_SMW: - if (devc->model == MDL_ESS && ess_set_recmask (devc, &devmask)) { - break; - }; - if (devmask != SOUND_MASK_MIC && - devmask != SOUND_MASK_LINE && - devmask != SOUND_MASK_CD) - { - /* - * More than one device selected. Drop the - * previous selection - */ - devmask &= ~devc->recmask; - } - if (devmask != SOUND_MASK_MIC && - devmask != SOUND_MASK_LINE && - devmask != SOUND_MASK_CD) - { - /* - * More than one device selected. Default to - * mic - */ - devmask = SOUND_MASK_MIC; - } - if (devmask ^ devc->recmask) /* - * Input source changed - */ - { - switch (devmask) - { - case SOUND_MASK_MIC: - set_recsrc(devc, SRC__MIC); - break; - - case SOUND_MASK_LINE: - set_recsrc(devc, SRC__LINE); - break; - - case SOUND_MASK_CD: - set_recsrc(devc, SRC__CD); - break; - - default: - set_recsrc(devc, SRC__MIC); - } - } - break; - - case MDL_SB16: - if (!devmask) - devmask = SOUND_MASK_MIC; - - if (devc->submodel == SUBMDL_ALS007) - { - switch (devmask) - { - case SOUND_MASK_LINE: - sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_LINE); - break; - case SOUND_MASK_CD: - sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_CD); - break; - case SOUND_MASK_SYNTH: - sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_SYNTH); - break; - default: /* Also takes care of SOUND_MASK_MIC case */ - sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_MIC); - break; - } - } - else - { - regimageL = regimageR = 0; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - { - if ((1 << i) & devmask) - { - regimageL |= sb16_recmasks_L[i]; - regimageR |= sb16_recmasks_R[i]; - } - sb_setmixer (devc, SB16_IMASK_L, regimageL); - sb_setmixer (devc, SB16_IMASK_R, regimageR); - } - } - break; - } - devc->recmask = devmask; - return devc->recmask; -} - -static int set_outmask(sb_devc * devc, int mask) -{ - int devmask, i; - unsigned char regimage; - - devmask = mask & devc->supported_out_devices; - - switch (devc->model) - { - case MDL_SB16: - if (devc->submodel == SUBMDL_ALS007) - break; - else - { - regimage = 0; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - { - if ((1 << i) & devmask) - { - regimage |= (sb16_recmasks_L[i] | sb16_recmasks_R[i]); - } - sb_setmixer (devc, SB16_OMASK, regimage); - } - } - break; - default: - break; - } - - devc->outmask = devmask; - return devc->outmask; -} - -static int sb_mixer_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - sb_devc *devc = mixer_devs[dev]->devc; - int val, ret; - int __user *p = arg; - - /* - * Use ioctl(fd, SOUND_MIXER_AGC, &mode) to turn AGC off (0) or on (1). - * Use ioctl(fd, SOUND_MIXER_3DSE, &mode) to turn 3DSE off (0) or on (1) - * or mode==2 put 3DSE state to mode. - */ - if (devc->model == MDL_SB16) { - if (cmd == SOUND_MIXER_AGC) - { - if (get_user(val, p)) - return -EFAULT; - sb_setmixer(devc, 0x43, (~val) & 0x01); - return 0; - } - if (cmd == SOUND_MIXER_3DSE) - { - /* I put here 15, but I don't know the exact version. - At least my 4.13 havn't 3DSE, 4.16 has it. */ - if (devc->minor < 15) - return -EINVAL; - if (get_user(val, p)) - return -EFAULT; - if (val == 0 || val == 1) - sb_chgmixer(devc, AWE_3DSE, 0x01, val); - else if (val == 2) - { - ret = sb_getmixer(devc, AWE_3DSE)&0x01; - return put_user(ret, p); - } - else - return -EINVAL; - return 0; - } - } - if (((cmd >> 8) & 0xff) == 'M') - { - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - { - if (get_user(val, p)) - return -EFAULT; - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - ret = set_recmask(devc, val); - break; - - case SOUND_MIXER_OUTSRC: - ret = set_outmask(devc, val); - break; - - default: - ret = sb_mixer_set(devc, cmd & 0xff, val); - } - } - else switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - ret = devc->recmask; - break; - - case SOUND_MIXER_OUTSRC: - ret = devc->outmask; - break; - - case SOUND_MIXER_DEVMASK: - ret = devc->supported_devices; - break; - - case SOUND_MIXER_STEREODEVS: - ret = devc->supported_devices; - /* The ESS seems to have stereo mic controls */ - if (devc->model == MDL_ESS) - ret &= ~(SOUND_MASK_SPEAKER|SOUND_MASK_IMIX); - else if (devc->model != MDL_JAZZ && devc->model != MDL_SMW) - ret &= ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX); - break; - - case SOUND_MIXER_RECMASK: - ret = devc->supported_rec_devices; - break; - - case SOUND_MIXER_OUTMASK: - ret = devc->supported_out_devices; - break; - - case SOUND_MIXER_CAPS: - ret = devc->mixer_caps; - break; - - default: - ret = sb_mixer_get(devc, cmd & 0xff); - break; - } - return put_user(ret, p); - } else - return -EINVAL; -} - -static struct mixer_operations sb_mixer_operations = -{ - .owner = THIS_MODULE, - .id = "SB", - .name = "Sound Blaster", - .ioctl = sb_mixer_ioctl -}; - -static struct mixer_operations als007_mixer_operations = -{ - .owner = THIS_MODULE, - .id = "ALS007", - .name = "Avance ALS-007", - .ioctl = sb_mixer_ioctl -}; - -static void sb_mixer_reset(sb_devc * devc) -{ - char name[32]; - int i; - - sprintf(name, "SB_%d", devc->sbmixnum); - - if (devc->sbmo.sm_games) - devc->levels = load_mixer_volumes(name, smg_default_levels, 1); - else - devc->levels = load_mixer_volumes(name, sb_default_levels, 1); - - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - sb_mixer_set(devc, i, devc->levels[i]); - - if (devc->model != MDL_ESS || !ess_mixer_reset (devc)) { - set_recmask(devc, SOUND_MASK_MIC); - }; -} - -int sb_mixer_init(sb_devc * devc, struct module *owner) -{ - int mixer_type = 0; - int m; - - devc->sbmixnum = sbmixnum++; - devc->levels = NULL; - - sb_setmixer(devc, 0x00, 0); /* Reset mixer */ - - if (!(mixer_type = detect_mixer(devc))) - return 0; /* No mixer. Why? */ - - switch (devc->model) - { - case MDL_ESSPCI: - case MDL_YMPCI: - case MDL_SBPRO: - case MDL_AZTECH: - case MDL_JAZZ: - devc->mixer_caps = SOUND_CAP_EXCL_INPUT; - devc->supported_devices = SBPRO_MIXER_DEVICES; - devc->supported_rec_devices = SBPRO_RECORDING_DEVICES; - devc->iomap = &sbpro_mix; - devc->iomap_sz = ARRAY_SIZE(sbpro_mix); - break; - - case MDL_ESS: - ess_mixer_init (devc); - break; - - case MDL_SMW: - devc->mixer_caps = SOUND_CAP_EXCL_INPUT; - devc->supported_devices = 0; - devc->supported_rec_devices = 0; - devc->iomap = &sbpro_mix; - devc->iomap_sz = ARRAY_SIZE(sbpro_mix); - smw_mixer_init(devc); - break; - - case MDL_SB16: - devc->mixer_caps = 0; - devc->supported_rec_devices = SB16_RECORDING_DEVICES; - devc->supported_out_devices = SB16_OUTFILTER_DEVICES; - if (devc->submodel != SUBMDL_ALS007) - { - devc->supported_devices = SB16_MIXER_DEVICES; - devc->iomap = &sb16_mix; - devc->iomap_sz = ARRAY_SIZE(sb16_mix); - } - else - { - devc->supported_devices = ALS007_MIXER_DEVICES; - devc->iomap = &als007_mix; - devc->iomap_sz = ARRAY_SIZE(als007_mix); - } - break; - - default: - printk(KERN_WARNING "sb_mixer: Unsupported mixer type %d\n", devc->model); - return 0; - } - - m = sound_alloc_mixerdev(); - if (m == -1) - return 0; - - mixer_devs[m] = kmalloc(sizeof(struct mixer_operations), GFP_KERNEL); - if (mixer_devs[m] == NULL) - { - printk(KERN_ERR "sb_mixer: Can't allocate memory\n"); - sound_unload_mixerdev(m); - return 0; - } - - if (devc->submodel != SUBMDL_ALS007) - memcpy ((char *) mixer_devs[m], (char *) &sb_mixer_operations, sizeof (struct mixer_operations)); - else - memcpy ((char *) mixer_devs[m], (char *) &als007_mixer_operations, sizeof (struct mixer_operations)); - - mixer_devs[m]->devc = devc; - - if (owner) - mixer_devs[m]->owner = owner; - - devc->my_mixerdev = m; - sb_mixer_reset(devc); - return 1; -} - -void sb_mixer_unload(sb_devc *devc) -{ - if (devc->my_mixerdev == -1) - return; - - kfree(mixer_devs[devc->my_mixerdev]); - sound_unload_mixerdev(devc->my_mixerdev); - sbmixnum--; -} diff --git a/ANDROID_3.4.5/sound/oss/sb_mixer.h b/ANDROID_3.4.5/sound/oss/sb_mixer.h deleted file mode 100644 index 4b9425f0..00000000 --- a/ANDROID_3.4.5/sound/oss/sb_mixer.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * sound/oss/sb_mixer.h - * - * Definitions for the SB Pro and SB16 mixers - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - -/* - * Modified: - * Hunyue Yau Jan 6 1994 - * Added defines for the Sound Galaxy NX Pro mixer. - * - * Rolf Fokkens Dec 20 1998 - * Added defines for some ES188x chips. - * - * Rolf Fokkens Dec 27 1998 - * Moved static stuff to sb_mixer.c - * - */ -/* - * Mixer registers - * - * NOTE! RECORD_SRC == IN_FILTER - */ - -/* - * Mixer registers of SB Pro - */ -#define VOC_VOL 0x04 -#define MIC_VOL 0x0A -#define MIC_MIX 0x0A -#define RECORD_SRC 0x0C -#define IN_FILTER 0x0C -#define OUT_FILTER 0x0E -#define MASTER_VOL 0x22 -#define FM_VOL 0x26 -#define CD_VOL 0x28 -#define LINE_VOL 0x2E -#define IRQ_NR 0x80 -#define DMA_NR 0x81 -#define IRQ_STAT 0x82 -#define OPSW 0x3c - -/* - * Additional registers on the SG NX Pro - */ -#define COVOX_VOL 0x42 -#define TREBLE_LVL 0x44 -#define BASS_LVL 0x46 - -#define FREQ_HI (1 << 3)/* Use High-frequency ANFI filters */ -#define FREQ_LOW 0 /* Use Low-frequency ANFI filters */ -#define FILT_ON 0 /* Yes, 0 to turn it on, 1 for off */ -#define FILT_OFF (1 << 5) - -#define MONO_DAC 0x00 -#define STEREO_DAC 0x02 - -/* - * Mixer registers of SB16 - */ -#define SB16_OMASK 0x3c -#define SB16_IMASK_L 0x3d -#define SB16_IMASK_R 0x3e - -#define LEFT_CHN 0 -#define RIGHT_CHN 1 - -/* - * 3DSE register of AWE32/64 - */ -#define AWE_3DSE 0x90 - -/* - * Mixer registers of ALS007 - */ -#define ALS007_RECORD_SRC 0x6c -#define ALS007_OUTPUT_CTRL1 0x3c -#define ALS007_OUTPUT_CTRL2 0x4c - -#define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r) \ - {{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}} - -/* - * Recording sources (SB Pro) - */ - -#define SRC__MIC 1 /* Select Microphone recording source */ -#define SRC__CD 3 /* Select CD recording source */ -#define SRC__LINE 7 /* Use Line-in for recording source */ - -/* - * Recording sources for ALS-007 - */ - -#define ALS007_MIC 4 -#define ALS007_LINE 6 -#define ALS007_CD 2 -#define ALS007_SYNTH 7 diff --git a/ANDROID_3.4.5/sound/oss/sequencer.c b/ANDROID_3.4.5/sound/oss/sequencer.c deleted file mode 100644 index 30bcfe47..00000000 --- a/ANDROID_3.4.5/sound/oss/sequencer.c +++ /dev/null @@ -1,1671 +0,0 @@ -/* - * sound/oss/sequencer.c - * - * The sequencer personality manager. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * Alan Cox : reformatted and fixed a pair of null pointer bugs - */ -#include -#include -#include "sound_config.h" - -#include "midi_ctrl.h" - -static int sequencer_ok; -static struct sound_timer_operations *tmr; -static int tmr_no = -1; /* Currently selected timer */ -static int pending_timer = -1; /* For timer change operation */ -extern unsigned long seq_time; - -static int obsolete_api_used; -static DEFINE_SPINLOCK(lock); - -/* - * Local counts for number of synth and MIDI devices. These are initialized - * by the sequencer_open. - */ -static int max_mididev; -static int max_synthdev; - -/* - * The seq_mode gives the operating mode of the sequencer: - * 1 = level1 (the default) - * 2 = level2 (extended capabilities) - */ - -#define SEQ_1 1 -#define SEQ_2 2 -static int seq_mode = SEQ_1; - -static DECLARE_WAIT_QUEUE_HEAD(seq_sleeper); -static DECLARE_WAIT_QUEUE_HEAD(midi_sleeper); - -static int midi_opened[MAX_MIDI_DEV]; - -static int midi_written[MAX_MIDI_DEV]; - -static unsigned long prev_input_time; -static int prev_event_time; - -#include "tuning.h" - -#define EV_SZ 8 -#define IEV_SZ 8 - -static unsigned char *queue; -static unsigned char *iqueue; - -static volatile int qhead, qtail, qlen; -static volatile int iqhead, iqtail, iqlen; -static volatile int seq_playing; -static volatile int sequencer_busy; -static int output_threshold; -static long pre_event_timeout; -static unsigned synth_open_mask; - -static int seq_queue(unsigned char *note, char nonblock); -static void seq_startplay(void); -static int seq_sync(void); -static void seq_reset(void); - -#if MAX_SYNTH_DEV > 15 -#error Too many synthesizer devices enabled. -#endif - -int sequencer_read(int dev, struct file *file, char __user *buf, int count) -{ - int c = count, p = 0; - int ev_len; - unsigned long flags; - - dev = dev >> 4; - - ev_len = seq_mode == SEQ_1 ? 4 : 8; - - spin_lock_irqsave(&lock,flags); - - if (!iqlen) - { - spin_unlock_irqrestore(&lock,flags); - if (file->f_flags & O_NONBLOCK) { - return -EAGAIN; - } - - interruptible_sleep_on_timeout(&midi_sleeper, - pre_event_timeout); - spin_lock_irqsave(&lock,flags); - if (!iqlen) - { - spin_unlock_irqrestore(&lock,flags); - return 0; - } - } - while (iqlen && c >= ev_len) - { - char *fixit = (char *) &iqueue[iqhead * IEV_SZ]; - spin_unlock_irqrestore(&lock,flags); - if (copy_to_user(&(buf)[p], fixit, ev_len)) - return count - c; - p += ev_len; - c -= ev_len; - - spin_lock_irqsave(&lock,flags); - iqhead = (iqhead + 1) % SEQ_MAX_QUEUE; - iqlen--; - } - spin_unlock_irqrestore(&lock,flags); - return count - c; -} - -static void sequencer_midi_output(int dev) -{ - /* - * Currently NOP - */ -} - -void seq_copy_to_input(unsigned char *event_rec, int len) -{ - unsigned long flags; - - /* - * Verify that the len is valid for the current mode. - */ - - if (len != 4 && len != 8) - return; - if ((seq_mode == SEQ_1) != (len == 4)) - return; - - if (iqlen >= (SEQ_MAX_QUEUE - 1)) - return; /* Overflow */ - - spin_lock_irqsave(&lock,flags); - memcpy(&iqueue[iqtail * IEV_SZ], event_rec, len); - iqlen++; - iqtail = (iqtail + 1) % SEQ_MAX_QUEUE; - wake_up(&midi_sleeper); - spin_unlock_irqrestore(&lock,flags); -} -EXPORT_SYMBOL(seq_copy_to_input); - -static void sequencer_midi_input(int dev, unsigned char data) -{ - unsigned int tstamp; - unsigned char event_rec[4]; - - if (data == 0xfe) /* Ignore active sensing */ - return; - - tstamp = jiffies - seq_time; - - if (tstamp != prev_input_time) - { - tstamp = (tstamp << 8) | SEQ_WAIT; - seq_copy_to_input((unsigned char *) &tstamp, 4); - prev_input_time = tstamp; - } - event_rec[0] = SEQ_MIDIPUTC; - event_rec[1] = data; - event_rec[2] = dev; - event_rec[3] = 0; - - seq_copy_to_input(event_rec, 4); -} - -void seq_input_event(unsigned char *event_rec, int len) -{ - unsigned long this_time; - - if (seq_mode == SEQ_2) - this_time = tmr->get_time(tmr_no); - else - this_time = jiffies - seq_time; - - if (this_time != prev_input_time) - { - unsigned char tmp_event[8]; - - tmp_event[0] = EV_TIMING; - tmp_event[1] = TMR_WAIT_ABS; - tmp_event[2] = 0; - tmp_event[3] = 0; - *(unsigned int *) &tmp_event[4] = this_time; - - seq_copy_to_input(tmp_event, 8); - prev_input_time = this_time; - } - seq_copy_to_input(event_rec, len); -} -EXPORT_SYMBOL(seq_input_event); - -int sequencer_write(int dev, struct file *file, const char __user *buf, int count) -{ - unsigned char event_rec[EV_SZ], ev_code; - int p = 0, c, ev_size; - int mode = translate_mode(file); - - dev = dev >> 4; - - DEB(printk("sequencer_write(dev=%d, count=%d)\n", dev, count)); - - if (mode == OPEN_READ) - return -EIO; - - c = count; - - while (c >= 4) - { - if (copy_from_user((char *) event_rec, &(buf)[p], 4)) - goto out; - ev_code = event_rec[0]; - - if (ev_code == SEQ_FULLSIZE) - { - int err, fmt; - - dev = *(unsigned short *) &event_rec[2]; - if (dev < 0 || dev >= max_synthdev || synth_devs[dev] == NULL) - return -ENXIO; - - if (!(synth_open_mask & (1 << dev))) - return -ENXIO; - - fmt = (*(short *) &event_rec[0]) & 0xffff; - err = synth_devs[dev]->load_patch(dev, fmt, buf + p, c, 0); - if (err < 0) - return err; - - return err; - } - if (ev_code >= 128) - { - if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED) - { - printk(KERN_WARNING "Sequencer: Invalid level 2 event %x\n", ev_code); - return -EINVAL; - } - ev_size = 8; - - if (c < ev_size) - { - if (!seq_playing) - seq_startplay(); - return count - c; - } - if (copy_from_user((char *)&event_rec[4], - &(buf)[p + 4], 4)) - goto out; - - } - else - { - if (seq_mode == SEQ_2) - { - printk(KERN_WARNING "Sequencer: 4 byte event in level 2 mode\n"); - return -EINVAL; - } - ev_size = 4; - - if (event_rec[0] != SEQ_MIDIPUTC) - obsolete_api_used = 1; - } - - if (event_rec[0] == SEQ_MIDIPUTC) - { - if (!midi_opened[event_rec[2]]) - { - int err, mode; - int dev = event_rec[2]; - - if (dev >= max_mididev || midi_devs[dev]==NULL) - { - /*printk("Sequencer Error: Nonexistent MIDI device %d\n", dev);*/ - return -ENXIO; - } - mode = translate_mode(file); - - if ((err = midi_devs[dev]->open(dev, mode, - sequencer_midi_input, sequencer_midi_output)) < 0) - { - seq_reset(); - printk(KERN_WARNING "Sequencer Error: Unable to open Midi #%d\n", dev); - return err; - } - midi_opened[dev] = 1; - } - } - if (!seq_queue(event_rec, (file->f_flags & (O_NONBLOCK) ? 1 : 0))) - { - int processed = count - c; - - if (!seq_playing) - seq_startplay(); - - if (!processed && (file->f_flags & O_NONBLOCK)) - return -EAGAIN; - else - return processed; - } - p += ev_size; - c -= ev_size; - } - - if (!seq_playing) - seq_startplay(); -out: - return count; -} - -static int seq_queue(unsigned char *note, char nonblock) -{ - - /* - * Test if there is space in the queue - */ - - if (qlen >= SEQ_MAX_QUEUE) - if (!seq_playing) - seq_startplay(); /* - * Give chance to drain the queue - */ - - if (!nonblock && qlen >= SEQ_MAX_QUEUE && !waitqueue_active(&seq_sleeper)) { - /* - * Sleep until there is enough space on the queue - */ - interruptible_sleep_on(&seq_sleeper); - } - if (qlen >= SEQ_MAX_QUEUE) - { - return 0; /* - * To be sure - */ - } - memcpy(&queue[qtail * EV_SZ], note, EV_SZ); - - qtail = (qtail + 1) % SEQ_MAX_QUEUE; - qlen++; - - return 1; -} - -static int extended_event(unsigned char *q) -{ - int dev = q[2]; - - if (dev < 0 || dev >= max_synthdev) - return -ENXIO; - - if (!(synth_open_mask & (1 << dev))) - return -ENXIO; - - switch (q[1]) - { - case SEQ_NOTEOFF: - synth_devs[dev]->kill_note(dev, q[3], q[4], q[5]); - break; - - case SEQ_NOTEON: - if (q[4] > 127 && q[4] != 255) - return 0; - - if (q[5] == 0) - { - synth_devs[dev]->kill_note(dev, q[3], q[4], q[5]); - break; - } - synth_devs[dev]->start_note(dev, q[3], q[4], q[5]); - break; - - case SEQ_PGMCHANGE: - synth_devs[dev]->set_instr(dev, q[3], q[4]); - break; - - case SEQ_AFTERTOUCH: - synth_devs[dev]->aftertouch(dev, q[3], q[4]); - break; - - case SEQ_BALANCE: - synth_devs[dev]->panning(dev, q[3], (char) q[4]); - break; - - case SEQ_CONTROLLER: - synth_devs[dev]->controller(dev, q[3], q[4], (short) (q[5] | (q[6] << 8))); - break; - - case SEQ_VOLMODE: - if (synth_devs[dev]->volume_method != NULL) - synth_devs[dev]->volume_method(dev, q[3]); - break; - - default: - return -EINVAL; - } - return 0; -} - -static int find_voice(int dev, int chn, int note) -{ - unsigned short key; - int i; - - key = (chn << 8) | (note + 1); - for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++) - if (synth_devs[dev]->alloc.map[i] == key) - return i; - return -1; -} - -static int alloc_voice(int dev, int chn, int note) -{ - unsigned short key; - int voice; - - key = (chn << 8) | (note + 1); - - voice = synth_devs[dev]->alloc_voice(dev, chn, note, - &synth_devs[dev]->alloc); - synth_devs[dev]->alloc.map[voice] = key; - synth_devs[dev]->alloc.alloc_times[voice] = - synth_devs[dev]->alloc.timestamp++; - return voice; -} - -static void seq_chn_voice_event(unsigned char *event_rec) -{ -#define dev event_rec[1] -#define cmd event_rec[2] -#define chn event_rec[3] -#define note event_rec[4] -#define parm event_rec[5] - - int voice = -1; - - if ((int) dev > max_synthdev || synth_devs[dev] == NULL) - return; - if (!(synth_open_mask & (1 << dev))) - return; - if (!synth_devs[dev]) - return; - - if (seq_mode == SEQ_2) - { - if (synth_devs[dev]->alloc_voice) - voice = find_voice(dev, chn, note); - - if (cmd == MIDI_NOTEON && parm == 0) - { - cmd = MIDI_NOTEOFF; - parm = 64; - } - } - - switch (cmd) - { - case MIDI_NOTEON: - if (note > 127 && note != 255) /* Not a seq2 feature */ - return; - - if (voice == -1 && seq_mode == SEQ_2 && synth_devs[dev]->alloc_voice) - { - /* Internal synthesizer (FM, GUS, etc) */ - voice = alloc_voice(dev, chn, note); - } - if (voice == -1) - voice = chn; - - if (seq_mode == SEQ_2 && (int) dev < num_synths) - { - /* - * The MIDI channel 10 is a percussive channel. Use the note - * number to select the proper patch (128 to 255) to play. - */ - - if (chn == 9) - { - synth_devs[dev]->set_instr(dev, voice, 128 + note); - synth_devs[dev]->chn_info[chn].pgm_num = 128 + note; - } - synth_devs[dev]->setup_voice(dev, voice, chn); - } - synth_devs[dev]->start_note(dev, voice, note, parm); - break; - - case MIDI_NOTEOFF: - if (voice == -1) - voice = chn; - synth_devs[dev]->kill_note(dev, voice, note, parm); - break; - - case MIDI_KEY_PRESSURE: - if (voice == -1) - voice = chn; - synth_devs[dev]->aftertouch(dev, voice, parm); - break; - - default:; - } -#undef dev -#undef cmd -#undef chn -#undef note -#undef parm -} - - -static void seq_chn_common_event(unsigned char *event_rec) -{ - unsigned char dev = event_rec[1]; - unsigned char cmd = event_rec[2]; - unsigned char chn = event_rec[3]; - unsigned char p1 = event_rec[4]; - - /* unsigned char p2 = event_rec[5]; */ - unsigned short w14 = *(short *) &event_rec[6]; - - if ((int) dev > max_synthdev || synth_devs[dev] == NULL) - return; - if (!(synth_open_mask & (1 << dev))) - return; - if (!synth_devs[dev]) - return; - - switch (cmd) - { - case MIDI_PGM_CHANGE: - if (seq_mode == SEQ_2) - { - synth_devs[dev]->chn_info[chn].pgm_num = p1; - if ((int) dev >= num_synths) - synth_devs[dev]->set_instr(dev, chn, p1); - } - else - synth_devs[dev]->set_instr(dev, chn, p1); - - break; - - case MIDI_CTL_CHANGE: - if (seq_mode == SEQ_2) - { - if (chn > 15 || p1 > 127) - break; - - synth_devs[dev]->chn_info[chn].controllers[p1] = w14 & 0x7f; - - if (p1 < 32) /* Setting MSB should clear LSB to 0 */ - synth_devs[dev]->chn_info[chn].controllers[p1 + 32] = 0; - - if ((int) dev < num_synths) - { - int val = w14 & 0x7f; - int i, key; - - if (p1 < 64) /* Combine MSB and LSB */ - { - val = ((synth_devs[dev]-> - chn_info[chn].controllers[p1 & ~32] & 0x7f) << 7) - | (synth_devs[dev]-> - chn_info[chn].controllers[p1 | 32] & 0x7f); - p1 &= ~32; - } - /* Handle all playing notes on this channel */ - - key = ((int) chn << 8); - - for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++) - if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key) - synth_devs[dev]->controller(dev, i, p1, val); - } - else - synth_devs[dev]->controller(dev, chn, p1, w14); - } - else /* Mode 1 */ - synth_devs[dev]->controller(dev, chn, p1, w14); - break; - - case MIDI_PITCH_BEND: - if (seq_mode == SEQ_2) - { - synth_devs[dev]->chn_info[chn].bender_value = w14; - - if ((int) dev < num_synths) - { - /* Handle all playing notes on this channel */ - int i, key; - - key = (chn << 8); - - for (i = 0; i < synth_devs[dev]->alloc.max_voice; i++) - if ((synth_devs[dev]->alloc.map[i] & 0xff00) == key) - synth_devs[dev]->bender(dev, i, w14); - } - else - synth_devs[dev]->bender(dev, chn, w14); - } - else /* MODE 1 */ - synth_devs[dev]->bender(dev, chn, w14); - break; - - default:; - } -} - -static int seq_timing_event(unsigned char *event_rec) -{ - unsigned char cmd = event_rec[1]; - unsigned int parm = *(int *) &event_rec[4]; - - if (seq_mode == SEQ_2) - { - int ret; - - if ((ret = tmr->event(tmr_no, event_rec)) == TIMER_ARMED) - if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) - wake_up(&seq_sleeper); - return ret; - } - switch (cmd) - { - case TMR_WAIT_REL: - parm += prev_event_time; - - /* - * NOTE! No break here. Execution of TMR_WAIT_REL continues in the - * next case (TMR_WAIT_ABS) - */ - - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - time = parm; - prev_event_time = time; - - seq_playing = 1; - request_sound_timer(time); - - if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) - wake_up(&seq_sleeper); - return TIMER_ARMED; - } - break; - - case TMR_START: - seq_time = jiffies; - prev_input_time = 0; - prev_event_time = 0; - break; - - case TMR_STOP: - break; - - case TMR_CONTINUE: - break; - - case TMR_TEMPO: - break; - - case TMR_ECHO: - if (seq_mode == SEQ_2) - seq_copy_to_input(event_rec, 8); - else - { - parm = (parm << 8 | SEQ_ECHO); - seq_copy_to_input((unsigned char *) &parm, 4); - } - break; - - default:; - } - - return TIMER_NOT_ARMED; -} - -static void seq_local_event(unsigned char *event_rec) -{ - unsigned char cmd = event_rec[1]; - unsigned int parm = *((unsigned int *) &event_rec[4]); - - switch (cmd) - { - case LOCL_STARTAUDIO: - DMAbuf_start_devices(parm); - break; - - default:; - } -} - -static void seq_sysex_message(unsigned char *event_rec) -{ - unsigned int dev = event_rec[1]; - int i, l = 0; - unsigned char *buf = &event_rec[2]; - - if (dev > max_synthdev) - return; - if (!(synth_open_mask & (1 << dev))) - return; - if (!synth_devs[dev]) - return; - - l = 0; - for (i = 0; i < 6 && buf[i] != 0xff; i++) - l = i + 1; - - if (!synth_devs[dev]->send_sysex) - return; - if (l > 0) - synth_devs[dev]->send_sysex(dev, buf, l); -} - -static int play_event(unsigned char *q) -{ - /* - * NOTE! This routine returns - * 0 = normal event played. - * 1 = Timer armed. Suspend playback until timer callback. - * 2 = MIDI output buffer full. Restore queue and suspend until timer - */ - unsigned int *delay; - - switch (q[0]) - { - case SEQ_NOTEOFF: - if (synth_open_mask & (1 << 0)) - if (synth_devs[0]) - synth_devs[0]->kill_note(0, q[1], 255, q[3]); - break; - - case SEQ_NOTEON: - if (q[4] < 128 || q[4] == 255) - if (synth_open_mask & (1 << 0)) - if (synth_devs[0]) - synth_devs[0]->start_note(0, q[1], q[2], q[3]); - break; - - case SEQ_WAIT: - delay = (unsigned int *) q; /* - * Bytes 1 to 3 are containing the * - * delay in 'ticks' - */ - *delay = (*delay >> 8) & 0xffffff; - - if (*delay > 0) - { - long time; - - seq_playing = 1; - time = *delay; - prev_event_time = time; - - request_sound_timer(time); - - if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) - wake_up(&seq_sleeper); - /* - * The timer is now active and will reinvoke this function - * after the timer expires. Return to the caller now. - */ - return 1; - } - break; - - case SEQ_PGMCHANGE: - if (synth_open_mask & (1 << 0)) - if (synth_devs[0]) - synth_devs[0]->set_instr(0, q[1], q[2]); - break; - - case SEQ_SYNCTIMER: /* - * Reset timer - */ - seq_time = jiffies; - prev_input_time = 0; - prev_event_time = 0; - break; - - case SEQ_MIDIPUTC: /* - * Put a midi character - */ - if (midi_opened[q[2]]) - { - int dev; - - dev = q[2]; - - if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) - break; - - if (!midi_devs[dev]->outputc(dev, q[1])) - { - /* - * Output FIFO is full. Wait one timer cycle and try again. - */ - - seq_playing = 1; - request_sound_timer(-1); - return 2; - } - else - midi_written[dev] = 1; - } - break; - - case SEQ_ECHO: - seq_copy_to_input(q, 4); /* - * Echo back to the process - */ - break; - - case SEQ_PRIVATE: - if ((int) q[1] < max_synthdev) - synth_devs[q[1]]->hw_control(q[1], q); - break; - - case SEQ_EXTENDED: - extended_event(q); - break; - - case EV_CHN_VOICE: - seq_chn_voice_event(q); - break; - - case EV_CHN_COMMON: - seq_chn_common_event(q); - break; - - case EV_TIMING: - if (seq_timing_event(q) == TIMER_ARMED) - { - return 1; - } - break; - - case EV_SEQ_LOCAL: - seq_local_event(q); - break; - - case EV_SYSEX: - seq_sysex_message(q); - break; - - default:; - } - return 0; -} - -/* called also as timer in irq context */ -static void seq_startplay(void) -{ - int this_one, action; - unsigned long flags; - - while (qlen > 0) - { - - spin_lock_irqsave(&lock,flags); - qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE; - qlen--; - spin_unlock_irqrestore(&lock,flags); - - seq_playing = 1; - - if ((action = play_event(&queue[this_one * EV_SZ]))) - { /* Suspend playback. Next timer routine invokes this routine again */ - if (action == 2) - { - qlen++; - qhead = this_one; - } - return; - } - } - - seq_playing = 0; - - if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) - wake_up(&seq_sleeper); -} - -static void reset_controllers(int dev, unsigned char *controller, int update_dev) -{ - int i; - for (i = 0; i < 128; i++) - controller[i] = ctrl_def_values[i]; -} - -static void setup_mode2(void) -{ - int dev; - - max_synthdev = num_synths; - - for (dev = 0; dev < num_midis; dev++) - { - if (midi_devs[dev] && midi_devs[dev]->converter != NULL) - { - synth_devs[max_synthdev++] = midi_devs[dev]->converter; - } - } - - for (dev = 0; dev < max_synthdev; dev++) - { - int chn; - - synth_devs[dev]->sysex_ptr = 0; - synth_devs[dev]->emulation = 0; - - for (chn = 0; chn < 16; chn++) - { - synth_devs[dev]->chn_info[chn].pgm_num = 0; - reset_controllers(dev, - synth_devs[dev]->chn_info[chn].controllers,0); - synth_devs[dev]->chn_info[chn].bender_value = (1 << 7); /* Neutral */ - synth_devs[dev]->chn_info[chn].bender_range = 200; - } - } - max_mididev = 0; - seq_mode = SEQ_2; -} - -int sequencer_open(int dev, struct file *file) -{ - int retval, mode, i; - int level, tmp; - - if (!sequencer_ok) - sequencer_init(); - - level = ((dev & 0x0f) == SND_DEV_SEQ2) ? 2 : 1; - - dev = dev >> 4; - mode = translate_mode(file); - - DEB(printk("sequencer_open(dev=%d)\n", dev)); - - if (!sequencer_ok) - { -/* printk("Sound card: sequencer not initialized\n");*/ - return -ENXIO; - } - if (dev) /* Patch manager device (obsolete) */ - return -ENXIO; - - if(synth_devs[dev] == NULL) - request_module("synth0"); - - if (mode == OPEN_READ) - { - if (!num_midis) - { - /*printk("Sequencer: No MIDI devices. Input not possible\n");*/ - sequencer_busy = 0; - return -ENXIO; - } - } - if (sequencer_busy) - { - return -EBUSY; - } - sequencer_busy = 1; - obsolete_api_used = 0; - - max_mididev = num_midis; - max_synthdev = num_synths; - pre_event_timeout = MAX_SCHEDULE_TIMEOUT; - seq_mode = SEQ_1; - - if (pending_timer != -1) - { - tmr_no = pending_timer; - pending_timer = -1; - } - if (tmr_no == -1) /* Not selected yet */ - { - int i, best; - - best = -1; - for (i = 0; i < num_sound_timers; i++) - if (sound_timer_devs[i] && sound_timer_devs[i]->priority > best) - { - tmr_no = i; - best = sound_timer_devs[i]->priority; - } - if (tmr_no == -1) /* Should not be */ - tmr_no = 0; - } - tmr = sound_timer_devs[tmr_no]; - - if (level == 2) - { - if (tmr == NULL) - { - /*printk("sequencer: No timer for level 2\n");*/ - sequencer_busy = 0; - return -ENXIO; - } - setup_mode2(); - } - if (!max_synthdev && !max_mididev) - { - sequencer_busy=0; - return -ENXIO; - } - - synth_open_mask = 0; - - for (i = 0; i < max_mididev; i++) - { - midi_opened[i] = 0; - midi_written[i] = 0; - } - - for (i = 0; i < max_synthdev; i++) - { - if (synth_devs[i]==NULL) - continue; - - if (!try_module_get(synth_devs[i]->owner)) - continue; - - if ((tmp = synth_devs[i]->open(i, mode)) < 0) - { - printk(KERN_WARNING "Sequencer: Warning! Cannot open synth device #%d (%d)\n", i, tmp); - if (synth_devs[i]->midi_dev) - printk(KERN_WARNING "(Maps to MIDI dev #%d)\n", synth_devs[i]->midi_dev); - } - else - { - synth_open_mask |= (1 << i); - if (synth_devs[i]->midi_dev) - midi_opened[synth_devs[i]->midi_dev] = 1; - } - } - - seq_time = jiffies; - - prev_input_time = 0; - prev_event_time = 0; - - if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE)) - { - /* - * Initialize midi input devices - */ - - for (i = 0; i < max_mididev; i++) - if (!midi_opened[i] && midi_devs[i]) - { - if (!try_module_get(midi_devs[i]->owner)) - continue; - - if ((retval = midi_devs[i]->open(i, mode, - sequencer_midi_input, sequencer_midi_output)) >= 0) - { - midi_opened[i] = 1; - } - } - } - - if (seq_mode == SEQ_2) { - if (try_module_get(tmr->owner)) - tmr->open(tmr_no, seq_mode); - } - - init_waitqueue_head(&seq_sleeper); - init_waitqueue_head(&midi_sleeper); - output_threshold = SEQ_MAX_QUEUE / 2; - - return 0; -} - -static void seq_drain_midi_queues(void) -{ - int i, n; - - /* - * Give the Midi drivers time to drain their output queues - */ - - n = 1; - - while (!signal_pending(current) && n) - { - n = 0; - - for (i = 0; i < max_mididev; i++) - if (midi_opened[i] && midi_written[i]) - if (midi_devs[i]->buffer_status != NULL) - if (midi_devs[i]->buffer_status(i)) - n++; - - /* - * Let's have a delay - */ - - if (n) - interruptible_sleep_on_timeout(&seq_sleeper, - HZ/10); - } -} - -void sequencer_release(int dev, struct file *file) -{ - int i; - int mode = translate_mode(file); - - dev = dev >> 4; - - DEB(printk("sequencer_release(dev=%d)\n", dev)); - - /* - * Wait until the queue is empty (if we don't have nonblock) - */ - - if (mode != OPEN_READ && !(file->f_flags & O_NONBLOCK)) - { - while (!signal_pending(current) && qlen > 0) - { - seq_sync(); - interruptible_sleep_on_timeout(&seq_sleeper, - 3*HZ); - /* Extra delay */ - } - } - - if (mode != OPEN_READ) - seq_drain_midi_queues(); /* - * Ensure the output queues are empty - */ - seq_reset(); - if (mode != OPEN_READ) - seq_drain_midi_queues(); /* - * Flush the all notes off messages - */ - - for (i = 0; i < max_synthdev; i++) - { - if (synth_open_mask & (1 << i)) /* - * Actually opened - */ - if (synth_devs[i]) - { - synth_devs[i]->close(i); - - module_put(synth_devs[i]->owner); - - if (synth_devs[i]->midi_dev) - midi_opened[synth_devs[i]->midi_dev] = 0; - } - } - - for (i = 0; i < max_mididev; i++) - { - if (midi_opened[i]) { - midi_devs[i]->close(i); - module_put(midi_devs[i]->owner); - } - } - - if (seq_mode == SEQ_2) { - tmr->close(tmr_no); - module_put(tmr->owner); - } - - if (obsolete_api_used) - printk(KERN_WARNING "/dev/music: Obsolete (4 byte) API was used by %s\n", current->comm); - sequencer_busy = 0; -} - -static int seq_sync(void) -{ - if (qlen && !seq_playing && !signal_pending(current)) - seq_startplay(); - - if (qlen > 0) - interruptible_sleep_on_timeout(&seq_sleeper, HZ); - return qlen; -} - -static void midi_outc(int dev, unsigned char data) -{ - /* - * NOTE! Calls sleep(). Don't call this from interrupt. - */ - - int n; - unsigned long flags; - - /* - * This routine sends one byte to the Midi channel. - * If the output FIFO is full, it waits until there - * is space in the queue - */ - - n = 3 * HZ; /* Timeout */ - - spin_lock_irqsave(&lock,flags); - while (n && !midi_devs[dev]->outputc(dev, data)) { - interruptible_sleep_on_timeout(&seq_sleeper, HZ/25); - n--; - } - spin_unlock_irqrestore(&lock,flags); -} - -static void seq_reset(void) -{ - /* - * NOTE! Calls sleep(). Don't call this from interrupt. - */ - - int i; - int chn; - unsigned long flags; - - sound_stop_timer(); - - seq_time = jiffies; - prev_input_time = 0; - prev_event_time = 0; - - qlen = qhead = qtail = 0; - iqlen = iqhead = iqtail = 0; - - for (i = 0; i < max_synthdev; i++) - if (synth_open_mask & (1 << i)) - if (synth_devs[i]) - synth_devs[i]->reset(i); - - if (seq_mode == SEQ_2) - { - for (chn = 0; chn < 16; chn++) - for (i = 0; i < max_synthdev; i++) - if (synth_open_mask & (1 << i)) - if (synth_devs[i]) - { - synth_devs[i]->controller(i, chn, 123, 0); /* All notes off */ - synth_devs[i]->controller(i, chn, 121, 0); /* Reset all ctl */ - synth_devs[i]->bender(i, chn, 1 << 13); /* Bender off */ - } - } - else /* seq_mode == SEQ_1 */ - { - for (i = 0; i < max_mididev; i++) - if (midi_written[i]) /* - * Midi used. Some notes may still be playing - */ - { - /* - * Sending just a ACTIVE SENSING message should be enough to stop all - * playing notes. Since there are devices not recognizing the - * active sensing, we have to send some all notes off messages also. - */ - midi_outc(i, 0xfe); - - for (chn = 0; chn < 16; chn++) - { - midi_outc(i, (unsigned char) (0xb0 + (chn & 0x0f))); /* control change */ - midi_outc(i, 0x7b); /* All notes off */ - midi_outc(i, 0); /* Dummy parameter */ - } - - midi_devs[i]->close(i); - - midi_written[i] = 0; - midi_opened[i] = 0; - } - } - - seq_playing = 0; - - spin_lock_irqsave(&lock,flags); - - if (waitqueue_active(&seq_sleeper)) { - /* printk( "Sequencer Warning: Unexpected sleeping process - Waking up\n"); */ - wake_up(&seq_sleeper); - } - spin_unlock_irqrestore(&lock,flags); -} - -static void seq_panic(void) -{ - /* - * This routine is called by the application in case the user - * wants to reset the system to the default state. - */ - - seq_reset(); - - /* - * Since some of the devices don't recognize the active sensing and - * all notes off messages, we have to shut all notes manually. - * - * TO BE IMPLEMENTED LATER - */ - - /* - * Also return the controllers to their default states - */ -} - -int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg) -{ - int midi_dev, orig_dev, val, err; - int mode = translate_mode(file); - struct synth_info inf; - struct seq_event_rec event_rec; - unsigned long flags; - int __user *p = arg; - - orig_dev = dev = dev >> 4; - - switch (cmd) - { - case SNDCTL_TMR_TIMEBASE: - case SNDCTL_TMR_TEMPO: - case SNDCTL_TMR_START: - case SNDCTL_TMR_STOP: - case SNDCTL_TMR_CONTINUE: - case SNDCTL_TMR_METRONOME: - case SNDCTL_TMR_SOURCE: - if (seq_mode != SEQ_2) - return -EINVAL; - return tmr->ioctl(tmr_no, cmd, arg); - - case SNDCTL_TMR_SELECT: - if (seq_mode != SEQ_2) - return -EINVAL; - if (get_user(pending_timer, p)) - return -EFAULT; - if (pending_timer < 0 || pending_timer >= num_sound_timers || sound_timer_devs[pending_timer] == NULL) - { - pending_timer = -1; - return -EINVAL; - } - val = pending_timer; - break; - - case SNDCTL_SEQ_PANIC: - seq_panic(); - return -EINVAL; - - case SNDCTL_SEQ_SYNC: - if (mode == OPEN_READ) - return 0; - while (qlen > 0 && !signal_pending(current)) - seq_sync(); - return qlen ? -EINTR : 0; - - case SNDCTL_SEQ_RESET: - seq_reset(); - return 0; - - case SNDCTL_SEQ_TESTMIDI: - if (__get_user(midi_dev, p)) - return -EFAULT; - if (midi_dev < 0 || midi_dev >= max_mididev || !midi_devs[midi_dev]) - return -ENXIO; - - if (!midi_opened[midi_dev] && - (err = midi_devs[midi_dev]->open(midi_dev, mode, sequencer_midi_input, - sequencer_midi_output)) < 0) - return err; - midi_opened[midi_dev] = 1; - return 0; - - case SNDCTL_SEQ_GETINCOUNT: - if (mode == OPEN_WRITE) - return 0; - val = iqlen; - break; - - case SNDCTL_SEQ_GETOUTCOUNT: - if (mode == OPEN_READ) - return 0; - val = SEQ_MAX_QUEUE - qlen; - break; - - case SNDCTL_SEQ_GETTIME: - if (seq_mode == SEQ_2) - return tmr->ioctl(tmr_no, cmd, arg); - val = jiffies - seq_time; - break; - - case SNDCTL_SEQ_CTRLRATE: - /* - * If *arg == 0, just return the current rate - */ - if (seq_mode == SEQ_2) - return tmr->ioctl(tmr_no, cmd, arg); - - if (get_user(val, p)) - return -EFAULT; - if (val != 0) - return -EINVAL; - val = HZ; - break; - - case SNDCTL_SEQ_RESETSAMPLES: - case SNDCTL_SYNTH_REMOVESAMPLE: - case SNDCTL_SYNTH_CONTROL: - if (get_user(dev, p)) - return -EFAULT; - if (dev < 0 || dev >= num_synths || synth_devs[dev] == NULL) - return -ENXIO; - if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return -EBUSY; - return synth_devs[dev]->ioctl(dev, cmd, arg); - - case SNDCTL_SEQ_NRSYNTHS: - val = max_synthdev; - break; - - case SNDCTL_SEQ_NRMIDIS: - val = max_mididev; - break; - - case SNDCTL_SYNTH_MEMAVL: - if (get_user(dev, p)) - return -EFAULT; - if (dev < 0 || dev >= num_synths || synth_devs[dev] == NULL) - return -ENXIO; - if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return -EBUSY; - val = synth_devs[dev]->ioctl(dev, cmd, arg); - break; - - case SNDCTL_FM_4OP_ENABLE: - if (get_user(dev, p)) - return -EFAULT; - if (dev < 0 || dev >= num_synths || synth_devs[dev] == NULL) - return -ENXIO; - if (!(synth_open_mask & (1 << dev))) - return -ENXIO; - synth_devs[dev]->ioctl(dev, cmd, arg); - return 0; - - case SNDCTL_SYNTH_INFO: - if (get_user(dev, &((struct synth_info __user *)arg)->device)) - return -EFAULT; - if (dev < 0 || dev >= max_synthdev) - return -ENXIO; - if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return -EBUSY; - return synth_devs[dev]->ioctl(dev, cmd, arg); - - /* Like SYNTH_INFO but returns ID in the name field */ - case SNDCTL_SYNTH_ID: - if (get_user(dev, &((struct synth_info __user *)arg)->device)) - return -EFAULT; - if (dev < 0 || dev >= max_synthdev) - return -ENXIO; - if (!(synth_open_mask & (1 << dev)) && !orig_dev) - return -EBUSY; - memcpy(&inf, synth_devs[dev]->info, sizeof(inf)); - strlcpy(inf.name, synth_devs[dev]->id, sizeof(inf.name)); - inf.device = dev; - return copy_to_user(arg, &inf, sizeof(inf))?-EFAULT:0; - - case SNDCTL_SEQ_OUTOFBAND: - if (copy_from_user(&event_rec, arg, sizeof(event_rec))) - return -EFAULT; - spin_lock_irqsave(&lock,flags); - play_event(event_rec.arr); - spin_unlock_irqrestore(&lock,flags); - return 0; - - case SNDCTL_MIDI_INFO: - if (get_user(dev, &((struct midi_info __user *)arg)->device)) - return -EFAULT; - if (dev < 0 || dev >= max_mididev || !midi_devs[dev]) - return -ENXIO; - midi_devs[dev]->info.device = dev; - return copy_to_user(arg, &midi_devs[dev]->info, sizeof(struct midi_info))?-EFAULT:0; - - case SNDCTL_SEQ_THRESHOLD: - if (get_user(val, p)) - return -EFAULT; - if (val < 1) - val = 1; - if (val >= SEQ_MAX_QUEUE) - val = SEQ_MAX_QUEUE - 1; - output_threshold = val; - return 0; - - case SNDCTL_MIDI_PRETIME: - if (get_user(val, p)) - return -EFAULT; - if (val < 0) - val = 0; - val = (HZ * val) / 10; - pre_event_timeout = val; - break; - - default: - if (mode == OPEN_READ) - return -EIO; - if (!synth_devs[0]) - return -ENXIO; - if (!(synth_open_mask & (1 << 0))) - return -ENXIO; - if (!synth_devs[0]->ioctl) - return -EINVAL; - return synth_devs[0]->ioctl(0, cmd, arg); - } - return put_user(val, p); -} - -/* No kernel lock - we're using the global irq lock here */ -unsigned int sequencer_poll(int dev, struct file *file, poll_table * wait) -{ - unsigned long flags; - unsigned int mask = 0; - - dev = dev >> 4; - - spin_lock_irqsave(&lock,flags); - /* input */ - poll_wait(file, &midi_sleeper, wait); - if (iqlen) - mask |= POLLIN | POLLRDNORM; - - /* output */ - poll_wait(file, &seq_sleeper, wait); - if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) - mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&lock,flags); - return mask; -} - - -void sequencer_timer(unsigned long dummy) -{ - seq_startplay(); -} -EXPORT_SYMBOL(sequencer_timer); - -int note_to_freq(int note_num) -{ - - /* - * This routine converts a midi note to a frequency (multiplied by 1000) - */ - - int note, octave, note_freq; - static int notes[] = - { - 261632, 277189, 293671, 311132, 329632, 349232, - 369998, 391998, 415306, 440000, 466162, 493880 - }; - -#define BASE_OCTAVE 5 - - octave = note_num / 12; - note = note_num % 12; - - note_freq = notes[note]; - - if (octave < BASE_OCTAVE) - note_freq >>= (BASE_OCTAVE - octave); - else if (octave > BASE_OCTAVE) - note_freq <<= (octave - BASE_OCTAVE); - - /* - * note_freq >>= 1; - */ - - return note_freq; -} -EXPORT_SYMBOL(note_to_freq); - -unsigned long compute_finetune(unsigned long base_freq, int bend, int range, - int vibrato_cents) -{ - unsigned long amount; - int negative, semitones, cents, multiplier = 1; - - if (!bend) - return base_freq; - if (!range) - return base_freq; - - if (!base_freq) - return base_freq; - - if (range >= 8192) - range = 8192; - - bend = bend * range / 8192; /* Convert to cents */ - bend += vibrato_cents; - - if (!bend) - return base_freq; - - negative = bend < 0 ? 1 : 0; - - if (bend < 0) - bend *= -1; - if (bend > range) - bend = range; - - /* - if (bend > 2399) - bend = 2399; - */ - while (bend > 2399) - { - multiplier *= 4; - bend -= 2400; - } - - semitones = bend / 100; - cents = bend % 100; - - amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents]) / 10000; - - if (negative) - return (base_freq * 10000) / amount; /* Bend down */ - else - return (base_freq * amount) / 10000; /* Bend up */ -} -EXPORT_SYMBOL(compute_finetune); - -void sequencer_init(void) -{ - if (sequencer_ok) - return; - queue = vmalloc(SEQ_MAX_QUEUE * EV_SZ); - if (queue == NULL) - { - printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n"); - return; - } - iqueue = vmalloc(SEQ_MAX_QUEUE * IEV_SZ); - if (iqueue == NULL) - { - printk(KERN_ERR "sequencer: Can't allocate memory for sequencer input queue\n"); - vfree(queue); - return; - } - sequencer_ok = 1; -} -EXPORT_SYMBOL(sequencer_init); - -void sequencer_unload(void) -{ - vfree(queue); - vfree(iqueue); - queue = iqueue = NULL; -} diff --git a/ANDROID_3.4.5/sound/oss/sound_calls.h b/ANDROID_3.4.5/sound/oss/sound_calls.h deleted file mode 100644 index 87d8ad4a..00000000 --- a/ANDROID_3.4.5/sound/oss/sound_calls.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * DMA buffer calls - */ - -int DMAbuf_open(int dev, int mode); -int DMAbuf_release(int dev, int mode); -int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock); -int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock); -int DMAbuf_rmchars(int dev, int buff_no, int c); -int DMAbuf_start_output(int dev, int buff_no, int l); -int DMAbuf_move_wrpointer(int dev, int l); -/* int DMAbuf_ioctl(int dev, unsigned int cmd, void __user *arg, int local); */ -void DMAbuf_init(int dev, int dma1, int dma2); -void DMAbuf_deinit(int dev); -int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode); -void DMAbuf_inputintr(int dev); -void DMAbuf_outputintr(int dev, int underflow_flag); -struct dma_buffparms; -int DMAbuf_space_in_queue (int dev); -int DMAbuf_activate_recording (int dev, struct dma_buffparms *dmap); -int DMAbuf_get_buffer_pointer (int dev, struct dma_buffparms *dmap, int direction); -void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap); -unsigned int DMAbuf_poll(struct file *file, int dev, poll_table *wait); -void DMAbuf_start_devices(unsigned int devmask); -void DMAbuf_reset (int dev); -int DMAbuf_sync (int dev); - -/* - * System calls for /dev/dsp and /dev/audio (audio.c) - */ - -int audio_read (int dev, struct file *file, char __user *buf, int count); -int audio_write (int dev, struct file *file, const char __user *buf, int count); -int audio_open (int dev, struct file *file); -void audio_release (int dev, struct file *file); -int audio_ioctl (int dev, struct file *file, - unsigned int cmd, void __user *arg); -void audio_init_devices (void); -void reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording); - -/* - * System calls for the /dev/sequencer - */ - -int sequencer_read (int dev, struct file *file, char __user *buf, int count); -int sequencer_write (int dev, struct file *file, const char __user *buf, int count); -int sequencer_open (int dev, struct file *file); -void sequencer_release (int dev, struct file *file); -int sequencer_ioctl (int dev, struct file *file, unsigned int cmd, void __user *arg); -unsigned int sequencer_poll(int dev, struct file *file, poll_table * wait); - -void sequencer_init (void); -void sequencer_unload (void); -void sequencer_timer(unsigned long dummy); -int note_to_freq(int note_num); -unsigned long compute_finetune(unsigned long base_freq, int bend, int range, - int vibrato_bend); -void seq_input_event(unsigned char *event, int len); -void seq_copy_to_input (unsigned char *event, int len); - -/* - * System calls for the /dev/midi - */ - -int MIDIbuf_read (int dev, struct file *file, char __user *buf, int count); -int MIDIbuf_write (int dev, struct file *file, const char __user *buf, int count); -int MIDIbuf_open (int dev, struct file *file); -void MIDIbuf_release (int dev, struct file *file); -int MIDIbuf_ioctl (int dev, struct file *file, unsigned int cmd, void __user *arg); -unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait); -int MIDIbuf_avail(int dev); - -void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count); - - -/* From soundcard.c */ -void request_sound_timer (int count); -void sound_stop_timer(void); -void conf_printf(char *name, struct address_info *hw_config); -void conf_printf2(char *name, int base, int irq, int dma, int dma2); - -/* From sound_timer.c */ -void sound_timer_interrupt(void); -void sound_timer_syncinterval(unsigned int new_usecs); - -/* From midi_synth.c */ -void do_midi_msg (int synthno, unsigned char *msg, int mlen); diff --git a/ANDROID_3.4.5/sound/oss/sound_config.h b/ANDROID_3.4.5/sound/oss/sound_config.h deleted file mode 100644 index 9d35c4c6..00000000 --- a/ANDROID_3.4.5/sound/oss/sound_config.h +++ /dev/null @@ -1,147 +0,0 @@ -/* sound_config.h - * - * A driver for sound cards, misc. configuration parameters. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - - -#ifndef _SOUND_CONFIG_H_ -#define _SOUND_CONFIG_H_ - -#include -#include - -#include "os.h" -#include "soundvers.h" - - -#ifndef SND_DEFAULT_ENABLE -#define SND_DEFAULT_ENABLE 1 -#endif - -#ifndef MAX_REALTIME_FACTOR -#define MAX_REALTIME_FACTOR 4 -#endif - -/* - * Use always 64k buffer size. There is no reason to use shorter. - */ -#undef DSP_BUFFSIZE -#define DSP_BUFFSIZE (64*1024) - -#ifndef DSP_BUFFCOUNT -#define DSP_BUFFCOUNT 1 /* 1 is recommended. */ -#endif - -#define FM_MONO 0x388 /* This is the I/O address used by AdLib */ - -#ifndef CONFIG_PAS_BASE -#define CONFIG_PAS_BASE 0x388 -#endif - -/* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the - driver. (There is no need to alter this) */ -#define SEQ_MAX_QUEUE 1024 - -#define SBFM_MAXINSTR (256) /* Size of the FM Instrument bank */ -/* 128 instruments for general MIDI setup and 16 unassigned */ - -#define SND_NDEVS 256 /* Number of supported devices */ - -#define DSP_DEFAULT_SPEED 8000 - -#define MAX_AUDIO_DEV 5 -#define MAX_MIXER_DEV 5 -#define MAX_SYNTH_DEV 5 -#define MAX_MIDI_DEV 6 -#define MAX_TIMER_DEV 4 - -struct address_info { - int io_base; - int irq; - int dma; - int dma2; - int always_detect; /* 1=Trust me, it's there */ - char *name; - int driver_use_1; /* Driver defined field 1 */ - int driver_use_2; /* Driver defined field 2 */ - int *osp; /* OS specific info */ - int card_subtype; /* Driver specific. Usually 0 */ - void *memptr; /* Module memory chainer */ - int slots[6]; /* To remember driver slot ids */ -}; - -#define SYNTH_MAX_VOICES 32 - -struct voice_alloc_info { - int max_voice; - int used_voices; - int ptr; /* For device specific use */ - unsigned short map[SYNTH_MAX_VOICES]; /* (ch << 8) | (note+1) */ - int timestamp; - int alloc_times[SYNTH_MAX_VOICES]; - }; - -struct channel_info { - int pgm_num; - int bender_value; - int bender_range; - unsigned char controllers[128]; - }; - -/* - * Process wakeup reasons - */ -#define WK_NONE 0x00 -#define WK_WAKEUP 0x01 -#define WK_TIMEOUT 0x02 -#define WK_SIGNAL 0x04 -#define WK_SLEEP 0x08 -#define WK_SELECT 0x10 -#define WK_ABORT 0x20 - -#define OPEN_READ PCM_ENABLE_INPUT -#define OPEN_WRITE PCM_ENABLE_OUTPUT -#define OPEN_READWRITE (OPEN_READ|OPEN_WRITE) - -static inline int translate_mode(struct file *file) -{ - if (OPEN_READ == (__force int)FMODE_READ && - OPEN_WRITE == (__force int)FMODE_WRITE) - return (__force int)(file->f_mode & (FMODE_READ | FMODE_WRITE)); - else - return ((file->f_mode & FMODE_READ) ? OPEN_READ : 0) | - ((file->f_mode & FMODE_WRITE) ? OPEN_WRITE : 0); -} - -#include "sound_calls.h" -#include "dev_table.h" - -#ifndef DEB -#define DEB(x) -#endif - -#ifndef DDB -#define DDB(x) do {} while (0) -#endif - -#ifndef MDB -#ifdef MODULE -#define MDB(x) x -#else -#define MDB(x) -#endif -#endif - -#define TIMER_ARMED 121234 -#define TIMER_NOT_ARMED 1 - -#define MAX_MEM_BLOCKS 1024 - -#endif diff --git a/ANDROID_3.4.5/sound/oss/sound_firmware.h b/ANDROID_3.4.5/sound/oss/sound_firmware.h deleted file mode 100644 index 0a0cbfdf..00000000 --- a/ANDROID_3.4.5/sound/oss/sound_firmware.h +++ /dev/null @@ -1,2 +0,0 @@ -extern int mod_firmware_load(const char *fn, char **fp); - diff --git a/ANDROID_3.4.5/sound/oss/sound_timer.c b/ANDROID_3.4.5/sound/oss/sound_timer.c deleted file mode 100644 index 8021c85f..00000000 --- a/ANDROID_3.4.5/sound/oss/sound_timer.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * sound/oss/sound_timer.c - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - */ -#include -#include - -#include "sound_config.h" - -static volatile int initialized, opened, tmr_running; -static volatile time_t tmr_offs, tmr_ctr; -static volatile unsigned long ticks_offs; -static volatile int curr_tempo, curr_timebase; -static volatile unsigned long curr_ticks; -static volatile unsigned long next_event_time; -static unsigned long prev_event_time; -static volatile unsigned long usecs_per_tmr; /* Length of the current interval */ - -static struct sound_lowlev_timer *tmr; -static DEFINE_SPINLOCK(lock); - -static unsigned long tmr2ticks(int tmr_value) -{ - /* - * Convert timer ticks to MIDI ticks - */ - - unsigned long tmp; - unsigned long scale; - - tmp = tmr_value * usecs_per_tmr; /* Convert to usecs */ - scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */ - return (tmp + (scale / 2)) / scale; -} - -void reprogram_timer(void) -{ - unsigned long usecs_per_tick; - - /* - * The user is changing the timer rate before setting a timer - * slap, bad bad not allowed. - */ - - if(!tmr) - return; - - usecs_per_tick = (60 * 1000000) / (curr_tempo * curr_timebase); - - /* - * Don't kill the system by setting too high timer rate - */ - if (usecs_per_tick < 2000) - usecs_per_tick = 2000; - - usecs_per_tmr = tmr->tmr_start(tmr->dev, usecs_per_tick); -} - -void sound_timer_syncinterval(unsigned int new_usecs) -{ - /* - * This routine is called by the hardware level if - * the clock frequency has changed for some reason. - */ - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks(tmr_ctr); - tmr_ctr = 0; - usecs_per_tmr = new_usecs; -} -EXPORT_SYMBOL(sound_timer_syncinterval); - -static void tmr_reset(void) -{ - unsigned long flags; - - spin_lock_irqsave(&lock,flags); - tmr_offs = 0; - ticks_offs = 0; - tmr_ctr = 0; - next_event_time = (unsigned long) -1; - prev_event_time = 0; - curr_ticks = 0; - spin_unlock_irqrestore(&lock,flags); -} - -static int timer_open(int dev, int mode) -{ - if (opened) - return -EBUSY; - tmr_reset(); - curr_tempo = 60; - curr_timebase = 100; - opened = 1; - reprogram_timer(); - return 0; -} - -static void timer_close(int dev) -{ - opened = tmr_running = 0; - tmr->tmr_disable(tmr->dev); -} - -static int timer_event(int dev, unsigned char *event) -{ - unsigned char cmd = event[1]; - unsigned long parm = *(int *) &event[4]; - - switch (cmd) - { - case TMR_WAIT_REL: - parm += prev_event_time; - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - if (parm <= curr_ticks) /* It's the time */ - return TIMER_NOT_ARMED; - time = parm; - next_event_time = prev_event_time = time; - return TIMER_ARMED; - } - break; - - case TMR_START: - tmr_reset(); - tmr_running = 1; - reprogram_timer(); - break; - - case TMR_STOP: - tmr_running = 0; - break; - - case TMR_CONTINUE: - tmr_running = 1; - reprogram_timer(); - break; - - case TMR_TEMPO: - if (parm) - { - if (parm < 8) - parm = 8; - if (parm > 250) - parm = 250; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks(tmr_ctr); - tmr_ctr = 0; - curr_tempo = parm; - reprogram_timer(); - } - break; - - case TMR_ECHO: - seq_copy_to_input(event, 8); - break; - - default:; - } - return TIMER_NOT_ARMED; -} - -static unsigned long timer_get_time(int dev) -{ - if (!opened) - return 0; - return curr_ticks; -} - -static int timer_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - int __user *p = arg; - int val; - - switch (cmd) - { - case SNDCTL_TMR_SOURCE: - val = TMR_INTERNAL; - break; - - case SNDCTL_TMR_START: - tmr_reset(); - tmr_running = 1; - return 0; - - case SNDCTL_TMR_STOP: - tmr_running = 0; - return 0; - - case SNDCTL_TMR_CONTINUE: - tmr_running = 1; - return 0; - - case SNDCTL_TMR_TIMEBASE: - if (get_user(val, p)) - return -EFAULT; - if (val) - { - if (val < 1) - val = 1; - if (val > 1000) - val = 1000; - curr_timebase = val; - } - val = curr_timebase; - break; - - case SNDCTL_TMR_TEMPO: - if (get_user(val, p)) - return -EFAULT; - if (val) - { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks(tmr_ctr); - tmr_ctr = 0; - curr_tempo = val; - reprogram_timer(); - } - val = curr_tempo; - break; - - case SNDCTL_SEQ_CTRLRATE: - if (get_user(val, p)) - return -EFAULT; - if (val != 0) /* Can't change */ - return -EINVAL; - val = ((curr_tempo * curr_timebase) + 30) / 60; - break; - - case SNDCTL_SEQ_GETTIME: - val = curr_ticks; - break; - - case SNDCTL_TMR_METRONOME: - default: - return -EINVAL; - } - return put_user(val, p); -} - -static void timer_arm(int dev, long time) -{ - if (time < 0) - time = curr_ticks + 1; - else if (time <= curr_ticks) /* It's the time */ - return; - - next_event_time = prev_event_time = time; - return; -} - -static struct sound_timer_operations sound_timer = -{ - .owner = THIS_MODULE, - .info = {"Sound Timer", 0}, - .priority = 1, /* Priority */ - .devlink = 0, /* Local device link */ - .open = timer_open, - .close = timer_close, - .event = timer_event, - .get_time = timer_get_time, - .ioctl = timer_ioctl, - .arm_timer = timer_arm -}; - -void sound_timer_interrupt(void) -{ - unsigned long flags; - - if (!opened) - return; - - tmr->tmr_restart(tmr->dev); - - if (!tmr_running) - return; - - spin_lock_irqsave(&lock,flags); - tmr_ctr++; - curr_ticks = ticks_offs + tmr2ticks(tmr_ctr); - - if (curr_ticks >= next_event_time) - { - next_event_time = (unsigned long) -1; - sequencer_timer(0); - } - spin_unlock_irqrestore(&lock,flags); -} -EXPORT_SYMBOL(sound_timer_interrupt); - -void sound_timer_init(struct sound_lowlev_timer *t, char *name) -{ - int n; - - if (initialized) - { - if (t->priority <= tmr->priority) - return; /* There is already a similar or better timer */ - tmr = t; - return; - } - initialized = 1; - tmr = t; - - n = sound_alloc_timerdev(); - if (n == -1) - n = 0; /* Overwrite the system timer */ - strlcpy(sound_timer.info.name, name, sizeof(sound_timer.info.name)); - sound_timer_devs[n] = &sound_timer; -} -EXPORT_SYMBOL(sound_timer_init); - diff --git a/ANDROID_3.4.5/sound/oss/soundcard.c b/ANDROID_3.4.5/sound/oss/soundcard.c deleted file mode 100644 index 7c7793a0..00000000 --- a/ANDROID_3.4.5/sound/oss/soundcard.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * linux/sound/oss/soundcard.c - * - * Sound card driver for Linux - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * integrated sound_switch.c - * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat, - * which should disappear in the near future) - * Eric Dumas : devfs support (22-Jan-98) with - * fixups by C. Scott Ananian - * Richard Gooch : moved common (non OSS-specific) devices to sound_core.c - * Rob Riggs : Added persistent DMA buffers support (1998/10/17) - * Christoph Hellwig : Some cleanup work (2000/03/01) - */ - - -#include "sound_config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This ought to be moved into include/asm/dma.h - */ -#ifndef valid_dma -#define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4) -#endif - -/* - * Table for permanently allocated memory (used when unloading the module) - */ -void * sound_mem_blocks[MAX_MEM_BLOCKS]; -static DEFINE_MUTEX(soundcard_mutex); -int sound_nblocks = 0; - -/* Persistent DMA buffers */ -#ifdef CONFIG_SOUND_DMAP -int sound_dmap_flag = 1; -#else -int sound_dmap_flag = 0; -#endif - -static char dma_alloc_map[MAX_DMA_CHANNELS]; - -#define DMA_MAP_UNAVAIL 0 -#define DMA_MAP_FREE 1 -#define DMA_MAP_BUSY 2 - - -unsigned long seq_time = 0; /* Time for /dev/sequencer */ -extern struct class *sound_class; - -/* - * Table for configurable mixer volume handling - */ -static mixer_vol_table mixer_vols[MAX_MIXER_DEV]; -static int num_mixer_volumes; - -int *load_mixer_volumes(char *name, int *levels, int present) -{ - int i, n; - - for (i = 0; i < num_mixer_volumes; i++) { - if (strncmp(name, mixer_vols[i].name, 32) == 0) { - if (present) - mixer_vols[i].num = i; - return mixer_vols[i].levels; - } - } - if (num_mixer_volumes >= MAX_MIXER_DEV) { - printk(KERN_ERR "Sound: Too many mixers (%s)\n", name); - return levels; - } - n = num_mixer_volumes++; - - strncpy(mixer_vols[n].name, name, 32); - - if (present) - mixer_vols[n].num = n; - else - mixer_vols[n].num = -1; - - for (i = 0; i < 32; i++) - mixer_vols[n].levels[i] = levels[i]; - return mixer_vols[n].levels; -} -EXPORT_SYMBOL(load_mixer_volumes); - -static int set_mixer_levels(void __user * arg) -{ - /* mixer_vol_table is 174 bytes, so IMHO no reason to not allocate it on the stack */ - mixer_vol_table buf; - - if (__copy_from_user(&buf, arg, sizeof(buf))) - return -EFAULT; - load_mixer_volumes(buf.name, buf.levels, 0); - if (__copy_to_user(arg, &buf, sizeof(buf))) - return -EFAULT; - return 0; -} - -static int get_mixer_levels(void __user * arg) -{ - int n; - - if (__get_user(n, (int __user *)(&(((mixer_vol_table __user *)arg)->num)))) - return -EFAULT; - if (n < 0 || n >= num_mixer_volumes) - return -EINVAL; - if (__copy_to_user(arg, &mixer_vols[n], sizeof(mixer_vol_table))) - return -EFAULT; - return 0; -} - -/* 4K page size but our output routines use some slack for overruns */ -#define PROC_BLOCK_SIZE (3*1024) - -static ssize_t sound_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) -{ - int dev = iminor(file->f_path.dentry->d_inode); - int ret = -EINVAL; - - /* - * The OSS drivers aren't remotely happy without this locking, - * and unless someone fixes them when they are about to bite the - * big one anyway, we might as well bandage here.. - */ - - mutex_lock(&soundcard_mutex); - - DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count)); - switch (dev & 0x0f) { - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - ret = audio_read(dev, file, buf, count); - break; - - case SND_DEV_SEQ: - case SND_DEV_SEQ2: - ret = sequencer_read(dev, file, buf, count); - break; - - case SND_DEV_MIDIN: - ret = MIDIbuf_read(dev, file, buf, count); - } - mutex_unlock(&soundcard_mutex); - return ret; -} - -static ssize_t sound_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) -{ - int dev = iminor(file->f_path.dentry->d_inode); - int ret = -EINVAL; - - mutex_lock(&soundcard_mutex); - DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count)); - switch (dev & 0x0f) { - case SND_DEV_SEQ: - case SND_DEV_SEQ2: - ret = sequencer_write(dev, file, buf, count); - break; - - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - ret = audio_write(dev, file, buf, count); - break; - - case SND_DEV_MIDIN: - ret = MIDIbuf_write(dev, file, buf, count); - break; - } - mutex_unlock(&soundcard_mutex); - return ret; -} - -static int sound_open(struct inode *inode, struct file *file) -{ - int dev = iminor(inode); - int retval; - - DEB(printk("sound_open(dev=%d)\n", dev)); - if ((dev >= SND_NDEVS) || (dev < 0)) { - printk(KERN_ERR "Invalid minor device %d\n", dev); - return -ENXIO; - } - mutex_lock(&soundcard_mutex); - switch (dev & 0x0f) { - case SND_DEV_CTL: - dev >>= 4; - if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { - request_module("mixer%d", dev); - } - retval = -ENXIO; - if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL)) - break; - - if (!try_module_get(mixer_devs[dev]->owner)) - break; - - retval = 0; - break; - - case SND_DEV_SEQ: - case SND_DEV_SEQ2: - retval = sequencer_open(dev, file); - break; - - case SND_DEV_MIDIN: - retval = MIDIbuf_open(dev, file); - break; - - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - retval = audio_open(dev, file); - break; - - default: - printk(KERN_ERR "Invalid minor device %d\n", dev); - retval = -ENXIO; - } - - mutex_unlock(&soundcard_mutex); - return retval; -} - -static int sound_release(struct inode *inode, struct file *file) -{ - int dev = iminor(inode); - - mutex_lock(&soundcard_mutex); - DEB(printk("sound_release(dev=%d)\n", dev)); - switch (dev & 0x0f) { - case SND_DEV_CTL: - module_put(mixer_devs[dev >> 4]->owner); - break; - - case SND_DEV_SEQ: - case SND_DEV_SEQ2: - sequencer_release(dev, file); - break; - - case SND_DEV_MIDIN: - MIDIbuf_release(dev, file); - break; - - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - audio_release(dev, file); - break; - - default: - printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev); - } - mutex_unlock(&soundcard_mutex); - - return 0; -} - -static int get_mixer_info(int dev, void __user *arg) -{ - mixer_info info; - memset(&info, 0, sizeof(info)); - strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id)); - strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name)); - info.modify_counter = mixer_devs[dev]->modify_counter; - if (__copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int get_old_mixer_info(int dev, void __user *arg) -{ - _old_mixer_info info; - memset(&info, 0, sizeof(info)); - strlcpy(info.id, mixer_devs[dev]->id, sizeof(info.id)); - strlcpy(info.name, mixer_devs[dev]->name, sizeof(info.name)); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int sound_mixer_ioctl(int mixdev, unsigned int cmd, void __user *arg) -{ - if (mixdev < 0 || mixdev >= MAX_MIXER_DEV) - return -ENXIO; - /* Try to load the mixer... */ - if (mixer_devs[mixdev] == NULL) { - request_module("mixer%d", mixdev); - } - if (mixdev >= num_mixers || !mixer_devs[mixdev]) - return -ENXIO; - if (cmd == SOUND_MIXER_INFO) - return get_mixer_info(mixdev, arg); - if (cmd == SOUND_OLD_MIXER_INFO) - return get_old_mixer_info(mixdev, arg); - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - mixer_devs[mixdev]->modify_counter++; - if (!mixer_devs[mixdev]->ioctl) - return -EINVAL; - return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg); -} - -static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int len = 0, dtype; - int dev = iminor(file->f_dentry->d_inode); - long ret = -EINVAL; - void __user *p = (void __user *)arg; - - if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) { - /* - * Have to validate the address given by the process. - */ - len = _SIOC_SIZE(cmd); - if (len < 1 || len > 65536 || !p) - return -EFAULT; - if (_SIOC_DIR(cmd) & _SIOC_WRITE) - if (!access_ok(VERIFY_READ, p, len)) - return -EFAULT; - if (_SIOC_DIR(cmd) & _SIOC_READ) - if (!access_ok(VERIFY_WRITE, p, len)) - return -EFAULT; - } - DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg)); - if (cmd == OSS_GETVERSION) - return __put_user(SOUND_VERSION, (int __user *)p); - - mutex_lock(&soundcard_mutex); - if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */ - (dev & 0x0f) != SND_DEV_CTL) { - dtype = dev & 0x0f; - switch (dtype) { - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - ret = sound_mixer_ioctl(audio_devs[dev >> 4]->mixer_dev, - cmd, p); - break; - default: - ret = sound_mixer_ioctl(dev >> 4, cmd, p); - break; - } - mutex_unlock(&soundcard_mutex); - return ret; - } - - switch (dev & 0x0f) { - case SND_DEV_CTL: - if (cmd == SOUND_MIXER_GETLEVELS) - ret = get_mixer_levels(p); - else if (cmd == SOUND_MIXER_SETLEVELS) - ret = set_mixer_levels(p); - else - ret = sound_mixer_ioctl(dev >> 4, cmd, p); - break; - - case SND_DEV_SEQ: - case SND_DEV_SEQ2: - ret = sequencer_ioctl(dev, file, cmd, p); - break; - - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - ret = audio_ioctl(dev, file, cmd, p); - break; - - case SND_DEV_MIDIN: - ret = MIDIbuf_ioctl(dev, file, cmd, p); - break; - - } - mutex_unlock(&soundcard_mutex); - return ret; -} - -static unsigned int sound_poll(struct file *file, poll_table * wait) -{ - struct inode *inode = file->f_path.dentry->d_inode; - int dev = iminor(inode); - - DEB(printk("sound_poll(dev=%d)\n", dev)); - switch (dev & 0x0f) { - case SND_DEV_SEQ: - case SND_DEV_SEQ2: - return sequencer_poll(dev, file, wait); - - case SND_DEV_MIDIN: - return MIDIbuf_poll(dev, file, wait); - - case SND_DEV_DSP: - case SND_DEV_DSP16: - case SND_DEV_AUDIO: - return DMAbuf_poll(file, dev >> 4, wait); - } - return 0; -} - -static int sound_mmap(struct file *file, struct vm_area_struct *vma) -{ - int dev_class; - unsigned long size; - struct dma_buffparms *dmap = NULL; - int dev = iminor(file->f_path.dentry->d_inode); - - dev_class = dev & 0x0f; - dev >>= 4; - - if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) { - printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n"); - return -EINVAL; - } - mutex_lock(&soundcard_mutex); - if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */ - dmap = audio_devs[dev]->dmap_out; - else if (vma->vm_flags & VM_READ) - dmap = audio_devs[dev]->dmap_in; - else { - printk(KERN_ERR "Sound: Undefined mmap() access\n"); - mutex_unlock(&soundcard_mutex); - return -EINVAL; - } - - if (dmap == NULL) { - printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n"); - mutex_unlock(&soundcard_mutex); - return -EIO; - } - if (dmap->raw_buf == NULL) { - printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n"); - mutex_unlock(&soundcard_mutex); - return -EIO; - } - if (dmap->mapping_flags) { - printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n"); - mutex_unlock(&soundcard_mutex); - return -EIO; - } - if (vma->vm_pgoff != 0) { - printk(KERN_ERR "Sound: mmap() offset must be 0.\n"); - mutex_unlock(&soundcard_mutex); - return -EINVAL; - } - size = vma->vm_end - vma->vm_start; - - if (size != dmap->bytes_in_use) { - printk(KERN_WARNING "Sound: mmap() size = %ld. Should be %d\n", size, dmap->bytes_in_use); - } - if (remap_pfn_range(vma, vma->vm_start, - virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) { - mutex_unlock(&soundcard_mutex); - return -EAGAIN; - } - - dmap->mapping_flags |= DMA_MAP_MAPPED; - - if( audio_devs[dev]->d->mmap) - audio_devs[dev]->d->mmap(dev); - - memset(dmap->raw_buf, - dmap->neutral_byte, - dmap->bytes_in_use); - mutex_unlock(&soundcard_mutex); - return 0; -} - -const struct file_operations oss_sound_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = sound_read, - .write = sound_write, - .poll = sound_poll, - .unlocked_ioctl = sound_ioctl, - .mmap = sound_mmap, - .open = sound_open, - .release = sound_release, -}; - -/* - * Create the required special subdevices - */ - -static int create_special_devices(void) -{ - int seq1,seq2; - seq1=register_sound_special(&oss_sound_fops, 1); - if(seq1==-1) - goto bad; - seq2=register_sound_special(&oss_sound_fops, 8); - if(seq2!=-1) - return 0; - unregister_sound_special(1); -bad: - return -1; -} - - -static int dmabuf; -static int dmabug; - -module_param(dmabuf, int, 0444); -module_param(dmabug, int, 0444); - -/* additional minors for compatibility */ -struct oss_minor_dev { - unsigned short minor; - unsigned int enabled; -} dev_list[] = { - { SND_DEV_DSP16 }, - { SND_DEV_AUDIO }, -}; - -static int __init oss_init(void) -{ - int err; - int i, j; - -#ifdef CONFIG_PCI - if(dmabug) - isa_dma_bridge_buggy = dmabug; -#endif - - err = create_special_devices(); - if (err) { - printk(KERN_ERR "sound: driver already loaded/included in kernel\n"); - return err; - } - - /* Protecting the innocent */ - sound_dmap_flag = (dmabuf > 0 ? 1 : 0); - - for (i = 0; i < ARRAY_SIZE(dev_list); i++) { - j = 0; - do { - unsigned short minor = dev_list[i].minor + j * 0x10; - if (!register_sound_special(&oss_sound_fops, minor)) - dev_list[i].enabled = (1 << j); - } while (++j < num_audiodevs); - } - - if (sound_nblocks >= MAX_MEM_BLOCKS - 1) - printk(KERN_ERR "Sound warning: Deallocation table was too small.\n"); - - return 0; -} - -static void __exit oss_cleanup(void) -{ - int i, j; - - for (i = 0; i < ARRAY_SIZE(dev_list); i++) { - j = 0; - do { - if (dev_list[i].enabled & (1 << j)) - unregister_sound_special(dev_list[i].minor); - } while (++j < num_audiodevs); - } - - unregister_sound_special(1); - unregister_sound_special(8); - - sound_stop_timer(); - - sequencer_unload(); - - for (i = 0; i < MAX_DMA_CHANNELS; i++) - if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) { - printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n", i); - sound_free_dma(i); - } - - for (i = 0; i < sound_nblocks; i++) - vfree(sound_mem_blocks[i]); - -} - -module_init(oss_init); -module_exit(oss_cleanup); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("OSS Sound subsystem"); -MODULE_AUTHOR("Hannu Savolainen, et al."); - - -int sound_alloc_dma(int chn, char *deviceID) -{ - int err; - - if ((err = request_dma(chn, deviceID)) != 0) - return err; - - dma_alloc_map[chn] = DMA_MAP_FREE; - - return 0; -} -EXPORT_SYMBOL(sound_alloc_dma); - -int sound_open_dma(int chn, char *deviceID) -{ - if (!valid_dma(chn)) { - printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn); - return 1; - } - - if (dma_alloc_map[chn] != DMA_MAP_FREE) { - printk("sound_open_dma: DMA channel %d busy or not allocated (%d)\n", chn, dma_alloc_map[chn]); - return 1; - } - dma_alloc_map[chn] = DMA_MAP_BUSY; - return 0; -} -EXPORT_SYMBOL(sound_open_dma); - -void sound_free_dma(int chn) -{ - if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) { - /* printk( "sound_free_dma: Bad access to DMA channel %d\n", chn); */ - return; - } - free_dma(chn); - dma_alloc_map[chn] = DMA_MAP_UNAVAIL; -} -EXPORT_SYMBOL(sound_free_dma); - -void sound_close_dma(int chn) -{ - if (dma_alloc_map[chn] != DMA_MAP_BUSY) { - printk(KERN_ERR "sound_close_dma: Bad access to DMA channel %d\n", chn); - return; - } - dma_alloc_map[chn] = DMA_MAP_FREE; -} -EXPORT_SYMBOL(sound_close_dma); - -static void do_sequencer_timer(unsigned long dummy) -{ - sequencer_timer(0); -} - - -static DEFINE_TIMER(seq_timer, do_sequencer_timer, 0, 0); - -void request_sound_timer(int count) -{ - extern unsigned long seq_time; - - if (count < 0) { - seq_timer.expires = (-count) + jiffies; - add_timer(&seq_timer); - return; - } - count += seq_time; - - count -= jiffies; - - if (count < 1) - count = 1; - - seq_timer.expires = (count) + jiffies; - add_timer(&seq_timer); -} - -void sound_stop_timer(void) -{ - del_timer(&seq_timer); -} - -void conf_printf(char *name, struct address_info *hw_config) -{ -#ifndef CONFIG_SOUND_TRACEINIT - return; -#else - printk("<%s> at 0x%03x", name, hw_config->io_base); - - if (hw_config->irq) - printk(" irq %d", (hw_config->irq > 0) ? hw_config->irq : -hw_config->irq); - - if (hw_config->dma != -1 || hw_config->dma2 != -1) - { - printk(" dma %d", hw_config->dma); - if (hw_config->dma2 != -1) - printk(",%d", hw_config->dma2); - } - printk("\n"); -#endif -} -EXPORT_SYMBOL(conf_printf); - -void conf_printf2(char *name, int base, int irq, int dma, int dma2) -{ -#ifndef CONFIG_SOUND_TRACEINIT - return; -#else - printk("<%s> at 0x%03x", name, base); - - if (irq) - printk(" irq %d", (irq > 0) ? irq : -irq); - - if (dma != -1 || dma2 != -1) - { - printk(" dma %d", dma); - if (dma2 != -1) - printk(",%d", dma2); - } - printk("\n"); -#endif -} -EXPORT_SYMBOL(conf_printf2); - diff --git a/ANDROID_3.4.5/sound/oss/soundvers.h b/ANDROID_3.4.5/sound/oss/soundvers.h deleted file mode 100644 index e9084d2f..00000000 --- a/ANDROID_3.4.5/sound/oss/soundvers.h +++ /dev/null @@ -1,2 +0,0 @@ -#define SOUND_VERSION_STRING "3.8s2++-971130" -#define SOUND_INTERNAL_VERSION 0x030804 diff --git a/ANDROID_3.4.5/sound/oss/swarm_cs4297a.c b/ANDROID_3.4.5/sound/oss/swarm_cs4297a.c deleted file mode 100644 index 09d46484..00000000 --- a/ANDROID_3.4.5/sound/oss/swarm_cs4297a.c +++ /dev/null @@ -1,2768 +0,0 @@ -/******************************************************************************* -* -* "swarm_cs4297a.c" -- Cirrus Logic-Crystal CS4297a linux audio driver. -* -* Copyright (C) 2001 Broadcom Corporation. -* Copyright (C) 2000,2001 Cirrus Logic Corp. -* -- adapted from drivers by Thomas Sailer, -* -- but don't bug him; Problems should go to: -* -- tom woller (twoller@crystal.cirrus.com) or -* (audio@crystal.cirrus.com). -* -- adapted from cs4281 PCI driver for cs4297a on -* BCM1250 Synchronous Serial interface -* (Kip Walker, Broadcom Corp.) -* Copyright (C) 2004 Maciej W. Rozycki -* Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) -* -* 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., 675 Mass Ave, Cambridge, MA 02139, USA. -* -* Module command line parameters: -* none -* -* Supported devices: -* /dev/dsp standard /dev/dsp device, (mostly) OSS compatible -* /dev/mixer standard /dev/mixer device, (mostly) OSS compatible -* /dev/midi simple MIDI UART interface, no ioctl -* -* Modification History -* 08/20/00 trw - silence and no stopping DAC until release -* 08/23/00 trw - added CS_DBG statements, fix interrupt hang issue on DAC stop. -* 09/18/00 trw - added 16bit only record with conversion -* 09/24/00 trw - added Enhanced Full duplex (separate simultaneous -* capture/playback rates) -* 10/03/00 trw - fixed mmap (fixed GRECORD and the XMMS mmap test plugin -* libOSSm.so) -* 10/11/00 trw - modified for 2.4.0-test9 kernel enhancements (NR_MAP removal) -* 11/03/00 trw - fixed interrupt loss/stutter, added debug. -* 11/10/00 bkz - added __devinit to cs4297a_hw_init() -* 11/10/00 trw - fixed SMP and capture spinlock hang. -* 12/04/00 trw - cleaned up CSDEBUG flags and added "defaultorder" moduleparm. -* 12/05/00 trw - fixed polling (myth2), and added underrun swptr fix. -* 12/08/00 trw - added PM support. -* 12/14/00 trw - added wrapper code, builds under 2.4.0, 2.2.17-20, 2.2.17-8 -* (RH/Dell base), 2.2.18, 2.2.12. cleaned up code mods by ident. -* 12/19/00 trw - added PM support for 2.2 base (apm_callback). other PM cleanup. -* 12/21/00 trw - added fractional "defaultorder" inputs. if >100 then use -* defaultorder-100 as power of 2 for the buffer size. example: -* 106 = 2^(106-100) = 2^6 = 64 bytes for the buffer size. -* -*******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -struct cs4297a_state; - -static DEFINE_MUTEX(swarm_cs4297a_mutex); -static void stop_dac(struct cs4297a_state *s); -static void stop_adc(struct cs4297a_state *s); -static void start_dac(struct cs4297a_state *s); -static void start_adc(struct cs4297a_state *s); -#undef OSS_DOCUMENTED_MIXER_SEMANTICS - -// --------------------------------------------------------------------- - -#define CS4297a_MAGIC 0xf00beef1 - -// buffer order determines the size of the dma buffer for the driver. -// under Linux, a smaller buffer allows more responsiveness from many of the -// applications (e.g. games). A larger buffer allows some of the apps (esound) -// to not underrun the dma buffer as easily. As default, use 32k (order=3) -// rather than 64k as some of the games work more responsively. -// log base 2( buff sz = 32k). - -// -// Turn on/off debugging compilation by commenting out "#define CSDEBUG" -// -#define CSDEBUG 0 -#if CSDEBUG -#define CSDEBUG_INTERFACE 1 -#else -#undef CSDEBUG_INTERFACE -#endif -// -// cs_debugmask areas -// -#define CS_INIT 0x00000001 // initialization and probe functions -#define CS_ERROR 0x00000002 // tmp debugging bit placeholder -#define CS_INTERRUPT 0x00000004 // interrupt handler (separate from all other) -#define CS_FUNCTION 0x00000008 // enter/leave functions -#define CS_WAVE_WRITE 0x00000010 // write information for wave -#define CS_WAVE_READ 0x00000020 // read information for wave -#define CS_AC97 0x00000040 // AC97 register access -#define CS_DESCR 0x00000080 // descriptor management -#define CS_OPEN 0x00000400 // all open functions in the driver -#define CS_RELEASE 0x00000800 // all release functions in the driver -#define CS_PARMS 0x00001000 // functional and operational parameters -#define CS_IOCTL 0x00002000 // ioctl (non-mixer) -#define CS_TMP 0x10000000 // tmp debug mask bit - -// -// CSDEBUG is usual mode is set to 1, then use the -// cs_debuglevel and cs_debugmask to turn on or off debugging. -// Debug level of 1 has been defined to be kernel errors and info -// that should be printed on any released driver. -// -#if CSDEBUG -#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask) ) {x;} -#else -#define CS_DBGOUT(mask,level,x) -#endif - -#if CSDEBUG -static unsigned long cs_debuglevel = 4; // levels range from 1-9 -static unsigned long cs_debugmask = CS_INIT /*| CS_IOCTL*/; -module_param(cs_debuglevel, int, 0); -module_param(cs_debugmask, int, 0); -#endif -#define CS_TRUE 1 -#define CS_FALSE 0 - -#define CS_TYPE_ADC 0 -#define CS_TYPE_DAC 1 - -#define SER_BASE (A_SER_BASE_1 + KSEG1) -#define SS_CSR(t) (SER_BASE+t) -#define SS_TXTBL(t) (SER_BASE+R_SER_TX_TABLE_BASE+(t*8)) -#define SS_RXTBL(t) (SER_BASE+R_SER_RX_TABLE_BASE+(t*8)) - -#define FRAME_BYTES 32 -#define FRAME_SAMPLE_BYTES 4 - -/* Should this be variable? */ -#define SAMPLE_BUF_SIZE (16*1024) -#define SAMPLE_FRAME_COUNT (SAMPLE_BUF_SIZE / FRAME_SAMPLE_BYTES) -/* The driver can explode/shrink the frames to/from a smaller sample - buffer */ -#define DMA_BLOAT_FACTOR 1 -#define DMA_DESCR (SAMPLE_FRAME_COUNT / DMA_BLOAT_FACTOR) -#define DMA_BUF_SIZE (DMA_DESCR * FRAME_BYTES) - -/* Use the maxmium count (255 == 5.1 ms between interrupts) */ -#define DMA_INT_CNT ((1 << S_DMA_INT_PKTCNT) - 1) - -/* Figure this out: how many TX DMAs ahead to schedule a reg access */ -#define REG_LATENCY 150 - -#define FRAME_TX_US 20 - -#define SERDMA_NEXTBUF(d,f) (((d)->f+1) % (d)->ringsz) - -static const char invalid_magic[] = - KERN_CRIT "cs4297a: invalid magic value\n"; - -#define VALIDATE_STATE(s) \ -({ \ - if (!(s) || (s)->magic != CS4297a_MAGIC) { \ - printk(invalid_magic); \ - return -ENXIO; \ - } \ -}) - -struct list_head cs4297a_devs = { &cs4297a_devs, &cs4297a_devs }; - -typedef struct serdma_descr_s { - u64 descr_a; - u64 descr_b; -} serdma_descr_t; - -typedef unsigned long paddr_t; - -typedef struct serdma_s { - unsigned ringsz; - serdma_descr_t *descrtab; - serdma_descr_t *descrtab_end; - paddr_t descrtab_phys; - - serdma_descr_t *descr_add; - serdma_descr_t *descr_rem; - - u64 *dma_buf; // buffer for DMA contents (frames) - paddr_t dma_buf_phys; - u16 *sample_buf; // tmp buffer for sample conversions - u16 *sb_swptr; - u16 *sb_hwptr; - u16 *sb_end; - - dma_addr_t dmaaddr; -// unsigned buforder; // Log base 2 of 'dma_buf' size in bytes.. - unsigned numfrag; // # of 'fragments' in the buffer. - unsigned fragshift; // Log base 2 of fragment size. - unsigned hwptr, swptr; - unsigned total_bytes; // # bytes process since open. - unsigned blocks; // last returned blocks value GETOPTR - unsigned wakeup; // interrupt occurred on block - int count; - unsigned underrun; // underrun flag - unsigned error; // over/underrun - wait_queue_head_t wait; - wait_queue_head_t reg_wait; - // redundant, but makes calculations easier - unsigned fragsize; // 2**fragshift.. - unsigned sbufsz; // 2**buforder. - unsigned fragsamples; - // OSS stuff - unsigned mapped:1; // Buffer mapped in cs4297a_mmap()? - unsigned ready:1; // prog_dmabuf_dac()/adc() successful? - unsigned endcleared:1; - unsigned type:1; // adc or dac buffer (CS_TYPE_XXX) - unsigned ossfragshift; - int ossmaxfrags; - unsigned subdivision; -} serdma_t; - -struct cs4297a_state { - // magic - unsigned int magic; - - struct list_head list; - - // soundcore stuff - int dev_audio; - int dev_mixer; - - // hardware resources - unsigned int irq; - - struct { - unsigned int rx_ovrrn; /* FIFO */ - unsigned int rx_overflow; /* staging buffer */ - unsigned int tx_underrun; - unsigned int rx_bad; - unsigned int rx_good; - } stats; - - // mixer registers - struct { - unsigned short vol[10]; - unsigned int recsrc; - unsigned int modcnt; - unsigned short micpreamp; - } mix; - - // wave stuff - struct properties { - unsigned fmt; - unsigned fmt_original; // original requested format - unsigned channels; - unsigned rate; - } prop_dac, prop_adc; - unsigned conversion:1; // conversion from 16 to 8 bit in progress - unsigned ena; - spinlock_t lock; - struct mutex open_mutex; - struct mutex open_sem_adc; - struct mutex open_sem_dac; - fmode_t open_mode; - wait_queue_head_t open_wait; - wait_queue_head_t open_wait_adc; - wait_queue_head_t open_wait_dac; - - dma_addr_t dmaaddr_sample_buf; - unsigned buforder_sample_buf; // Log base 2 of 'dma_buf' size in bytes.. - - serdma_t dma_dac, dma_adc; - - volatile u16 read_value; - volatile u16 read_reg; - volatile u64 reg_request; -}; - -#if 1 -#define prog_codec(a,b) -#define dealloc_dmabuf(a,b); -#endif - -static int prog_dmabuf_adc(struct cs4297a_state *s) -{ - s->dma_adc.ready = 1; - return 0; -} - - -static int prog_dmabuf_dac(struct cs4297a_state *s) -{ - s->dma_dac.ready = 1; - return 0; -} - -static void clear_advance(void *buf, unsigned bsize, unsigned bptr, - unsigned len, unsigned char c) -{ - if (bptr + len > bsize) { - unsigned x = bsize - bptr; - memset(((char *) buf) + bptr, c, x); - bptr = 0; - len -= x; - } - CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO - "cs4297a: clear_advance(): memset %d at 0x%.8x for %d size \n", - (unsigned)c, (unsigned)((char *) buf) + bptr, len)); - memset(((char *) buf) + bptr, c, len); -} - -#if CSDEBUG - -// DEBUG ROUTINES - -#define SOUND_MIXER_CS_GETDBGLEVEL _SIOWR('M',120, int) -#define SOUND_MIXER_CS_SETDBGLEVEL _SIOWR('M',121, int) -#define SOUND_MIXER_CS_GETDBGMASK _SIOWR('M',122, int) -#define SOUND_MIXER_CS_SETDBGMASK _SIOWR('M',123, int) - -static void cs_printioctl(unsigned int x) -{ - unsigned int i; - unsigned char vidx; - // Index of mixtable1[] member is Device ID - // and must be <= SOUND_MIXER_NRDEVICES. - // Value of array member is index into s->mix.vol[] - static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = { - [SOUND_MIXER_PCM] = 1, // voice - [SOUND_MIXER_LINE1] = 2, // AUX - [SOUND_MIXER_CD] = 3, // CD - [SOUND_MIXER_LINE] = 4, // Line - [SOUND_MIXER_SYNTH] = 5, // FM - [SOUND_MIXER_MIC] = 6, // Mic - [SOUND_MIXER_SPEAKER] = 7, // Speaker - [SOUND_MIXER_RECLEV] = 8, // Recording level - [SOUND_MIXER_VOLUME] = 9 // Master Volume - }; - - switch (x) { - case SOUND_MIXER_CS_GETDBGMASK: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_CS_GETDBGMASK:\n")); - break; - case SOUND_MIXER_CS_GETDBGLEVEL: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_CS_GETDBGLEVEL:\n")); - break; - case SOUND_MIXER_CS_SETDBGMASK: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_CS_SETDBGMASK:\n")); - break; - case SOUND_MIXER_CS_SETDBGLEVEL: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_CS_SETDBGLEVEL:\n")); - break; - case OSS_GETVERSION: - CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION:\n")); - break; - case SNDCTL_DSP_SYNC: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC:\n")); - break; - case SNDCTL_DSP_SETDUPLEX: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX:\n")); - break; - case SNDCTL_DSP_GETCAPS: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS:\n")); - break; - case SNDCTL_DSP_RESET: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET:\n")); - break; - case SNDCTL_DSP_SPEED: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED:\n")); - break; - case SNDCTL_DSP_STEREO: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO:\n")); - break; - case SNDCTL_DSP_CHANNELS: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS:\n")); - break; - case SNDCTL_DSP_GETFMTS: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS:\n")); - break; - case SNDCTL_DSP_SETFMT: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT:\n")); - break; - case SNDCTL_DSP_POST: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST:\n")); - break; - case SNDCTL_DSP_GETTRIGGER: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER:\n")); - break; - case SNDCTL_DSP_SETTRIGGER: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER:\n")); - break; - case SNDCTL_DSP_GETOSPACE: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE:\n")); - break; - case SNDCTL_DSP_GETISPACE: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE:\n")); - break; - case SNDCTL_DSP_NONBLOCK: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK:\n")); - break; - case SNDCTL_DSP_GETODELAY: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY:\n")); - break; - case SNDCTL_DSP_GETIPTR: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR:\n")); - break; - case SNDCTL_DSP_GETOPTR: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR:\n")); - break; - case SNDCTL_DSP_GETBLKSIZE: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE:\n")); - break; - case SNDCTL_DSP_SETFRAGMENT: - CS_DBGOUT(CS_IOCTL, 4, - printk("SNDCTL_DSP_SETFRAGMENT:\n")); - break; - case SNDCTL_DSP_SUBDIVIDE: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE:\n")); - break; - case SOUND_PCM_READ_RATE: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE:\n")); - break; - case SOUND_PCM_READ_CHANNELS: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_PCM_READ_CHANNELS:\n")); - break; - case SOUND_PCM_READ_BITS: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS:\n")); - break; - case SOUND_PCM_WRITE_FILTER: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_PCM_WRITE_FILTER:\n")); - break; - case SNDCTL_DSP_SETSYNCRO: - CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO:\n")); - break; - case SOUND_PCM_READ_FILTER: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER:\n")); - break; - case SOUND_MIXER_PRIVATE1: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1:\n")); - break; - case SOUND_MIXER_PRIVATE2: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2:\n")); - break; - case SOUND_MIXER_PRIVATE3: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3:\n")); - break; - case SOUND_MIXER_PRIVATE4: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4:\n")); - break; - case SOUND_MIXER_PRIVATE5: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5:\n")); - break; - case SOUND_MIXER_INFO: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO:\n")); - break; - case SOUND_OLD_MIXER_INFO: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO:\n")); - break; - - default: - switch (_IOC_NR(x)) { - case SOUND_MIXER_VOLUME: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_VOLUME:\n")); - break; - case SOUND_MIXER_SPEAKER: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_SPEAKER:\n")); - break; - case SOUND_MIXER_RECLEV: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_RECLEV:\n")); - break; - case SOUND_MIXER_MIC: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_MIC:\n")); - break; - case SOUND_MIXER_SYNTH: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_SYNTH:\n")); - break; - case SOUND_MIXER_RECSRC: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_RECSRC:\n")); - break; - case SOUND_MIXER_DEVMASK: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_DEVMASK:\n")); - break; - case SOUND_MIXER_RECMASK: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_RECMASK:\n")); - break; - case SOUND_MIXER_STEREODEVS: - CS_DBGOUT(CS_IOCTL, 4, - printk("SOUND_MIXER_STEREODEVS:\n")); - break; - case SOUND_MIXER_CAPS: - CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:\n")); - break; - default: - i = _IOC_NR(x); - if (i >= SOUND_MIXER_NRDEVICES - || !(vidx = mixtable1[i])) { - CS_DBGOUT(CS_IOCTL, 4, printk - ("UNKNOWN IOCTL: 0x%.8x NR=%d\n", - x, i)); - } else { - CS_DBGOUT(CS_IOCTL, 4, printk - ("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d\n", - x, i)); - } - break; - } - } -} -#endif - - -static int ser_init(struct cs4297a_state *s) -{ - int i; - - CS_DBGOUT(CS_INIT, 2, - printk(KERN_INFO "cs4297a: Setting up serial parameters\n")); - - __raw_writeq(M_SYNCSER_CMD_RX_RESET | M_SYNCSER_CMD_TX_RESET, SS_CSR(R_SER_CMD)); - - __raw_writeq(M_SYNCSER_MSB_FIRST, SS_CSR(R_SER_MODE)); - __raw_writeq(32, SS_CSR(R_SER_MINFRM_SZ)); - __raw_writeq(32, SS_CSR(R_SER_MAXFRM_SZ)); - - __raw_writeq(1, SS_CSR(R_SER_TX_RD_THRSH)); - __raw_writeq(4, SS_CSR(R_SER_TX_WR_THRSH)); - __raw_writeq(8, SS_CSR(R_SER_RX_RD_THRSH)); - - /* This looks good from experimentation */ - __raw_writeq((M_SYNCSER_TXSYNC_INT | V_SYNCSER_TXSYNC_DLY(0) | M_SYNCSER_TXCLK_EXT | - M_SYNCSER_RXSYNC_INT | V_SYNCSER_RXSYNC_DLY(1) | M_SYNCSER_RXCLK_EXT | M_SYNCSER_RXSYNC_EDGE), - SS_CSR(R_SER_LINE_MODE)); - - /* This looks good from experimentation */ - __raw_writeq(V_SYNCSER_SEQ_COUNT(14) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_STROBE, - SS_TXTBL(0)); - __raw_writeq(V_SYNCSER_SEQ_COUNT(15) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_BYTE, - SS_TXTBL(1)); - __raw_writeq(V_SYNCSER_SEQ_COUNT(13) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_BYTE, - SS_TXTBL(2)); - __raw_writeq(V_SYNCSER_SEQ_COUNT( 0) | M_SYNCSER_SEQ_ENABLE | - M_SYNCSER_SEQ_STROBE | M_SYNCSER_SEQ_LAST, SS_TXTBL(3)); - - __raw_writeq(V_SYNCSER_SEQ_COUNT(14) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_STROBE, - SS_RXTBL(0)); - __raw_writeq(V_SYNCSER_SEQ_COUNT(15) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_BYTE, - SS_RXTBL(1)); - __raw_writeq(V_SYNCSER_SEQ_COUNT(13) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_BYTE, - SS_RXTBL(2)); - __raw_writeq(V_SYNCSER_SEQ_COUNT( 0) | M_SYNCSER_SEQ_ENABLE | M_SYNCSER_SEQ_STROBE | - M_SYNCSER_SEQ_LAST, SS_RXTBL(3)); - - for (i=4; i<16; i++) { - /* Just in case... */ - __raw_writeq(M_SYNCSER_SEQ_LAST, SS_TXTBL(i)); - __raw_writeq(M_SYNCSER_SEQ_LAST, SS_RXTBL(i)); - } - - return 0; -} - -static int init_serdma(serdma_t *dma) -{ - CS_DBGOUT(CS_INIT, 2, - printk(KERN_ERR "cs4297a: desc - %d sbufsize - %d dbufsize - %d\n", - DMA_DESCR, SAMPLE_BUF_SIZE, DMA_BUF_SIZE)); - - /* Descriptors */ - dma->ringsz = DMA_DESCR; - dma->descrtab = kzalloc(dma->ringsz * sizeof(serdma_descr_t), GFP_KERNEL); - if (!dma->descrtab) { - printk(KERN_ERR "cs4297a: kzalloc descrtab failed\n"); - return -1; - } - dma->descrtab_end = dma->descrtab + dma->ringsz; - /* XXX bloddy mess, use proper DMA API here ... */ - dma->descrtab_phys = CPHYSADDR((long)dma->descrtab); - dma->descr_add = dma->descr_rem = dma->descrtab; - - /* Frame buffer area */ - dma->dma_buf = kzalloc(DMA_BUF_SIZE, GFP_KERNEL); - if (!dma->dma_buf) { - printk(KERN_ERR "cs4297a: kzalloc dma_buf failed\n"); - kfree(dma->descrtab); - return -1; - } - dma->dma_buf_phys = CPHYSADDR((long)dma->dma_buf); - - /* Samples buffer area */ - dma->sbufsz = SAMPLE_BUF_SIZE; - dma->sample_buf = kmalloc(dma->sbufsz, GFP_KERNEL); - if (!dma->sample_buf) { - printk(KERN_ERR "cs4297a: kmalloc sample_buf failed\n"); - kfree(dma->descrtab); - kfree(dma->dma_buf); - return -1; - } - dma->sb_swptr = dma->sb_hwptr = dma->sample_buf; - dma->sb_end = (u16 *)((void *)dma->sample_buf + dma->sbufsz); - dma->fragsize = dma->sbufsz >> 1; - - CS_DBGOUT(CS_INIT, 4, - printk(KERN_ERR "cs4297a: descrtab - %08x dma_buf - %x sample_buf - %x\n", - (int)dma->descrtab, (int)dma->dma_buf, - (int)dma->sample_buf)); - - return 0; -} - -static int dma_init(struct cs4297a_state *s) -{ - int i; - - CS_DBGOUT(CS_INIT, 2, - printk(KERN_INFO "cs4297a: Setting up DMA\n")); - - if (init_serdma(&s->dma_adc) || - init_serdma(&s->dma_dac)) - return -1; - - if (__raw_readq(SS_CSR(R_SER_DMA_DSCR_COUNT_RX))|| - __raw_readq(SS_CSR(R_SER_DMA_DSCR_COUNT_TX))) { - panic("DMA state corrupted?!"); - } - - /* Initialize now - the descr/buffer pairings will never - change... */ - for (i=0; idma_dac.descrtab[i].descr_a = M_DMA_SERRX_SOP | V_DMA_DSCRA_A_SIZE(1) | - (s->dma_dac.dma_buf_phys + i*FRAME_BYTES); - s->dma_dac.descrtab[i].descr_b = V_DMA_DSCRB_PKT_SIZE(FRAME_BYTES); - s->dma_adc.descrtab[i].descr_a = V_DMA_DSCRA_A_SIZE(1) | - (s->dma_adc.dma_buf_phys + i*FRAME_BYTES); - s->dma_adc.descrtab[i].descr_b = 0; - } - - __raw_writeq((M_DMA_EOP_INT_EN | V_DMA_INT_PKTCNT(DMA_INT_CNT) | - V_DMA_RINGSZ(DMA_DESCR) | M_DMA_TDX_EN), - SS_CSR(R_SER_DMA_CONFIG0_RX)); - __raw_writeq(M_DMA_L2CA, SS_CSR(R_SER_DMA_CONFIG1_RX)); - __raw_writeq(s->dma_adc.descrtab_phys, SS_CSR(R_SER_DMA_DSCR_BASE_RX)); - - __raw_writeq(V_DMA_RINGSZ(DMA_DESCR), SS_CSR(R_SER_DMA_CONFIG0_TX)); - __raw_writeq(M_DMA_L2CA | M_DMA_NO_DSCR_UPDT, SS_CSR(R_SER_DMA_CONFIG1_TX)); - __raw_writeq(s->dma_dac.descrtab_phys, SS_CSR(R_SER_DMA_DSCR_BASE_TX)); - - /* Prep the receive DMA descriptor ring */ - __raw_writeq(DMA_DESCR, SS_CSR(R_SER_DMA_DSCR_COUNT_RX)); - - __raw_writeq(M_SYNCSER_DMA_RX_EN | M_SYNCSER_DMA_TX_EN, SS_CSR(R_SER_DMA_ENABLE)); - - __raw_writeq((M_SYNCSER_RX_SYNC_ERR | M_SYNCSER_RX_OVERRUN | M_SYNCSER_RX_EOP_COUNT), - SS_CSR(R_SER_INT_MASK)); - - /* Enable the rx/tx; let the codec warm up to the sync and - start sending good frames before the receive FIFO is - enabled */ - __raw_writeq(M_SYNCSER_CMD_TX_EN, SS_CSR(R_SER_CMD)); - udelay(1000); - __raw_writeq(M_SYNCSER_CMD_RX_EN | M_SYNCSER_CMD_TX_EN, SS_CSR(R_SER_CMD)); - - /* XXXKW is this magic? (the "1" part) */ - while ((__raw_readq(SS_CSR(R_SER_STATUS)) & 0xf1) != 1) - ; - - CS_DBGOUT(CS_INIT, 4, - printk(KERN_INFO "cs4297a: status: %08x\n", - (unsigned int)(__raw_readq(SS_CSR(R_SER_STATUS)) & 0xffffffff))); - - return 0; -} - -static int serdma_reg_access(struct cs4297a_state *s, u64 data) -{ - serdma_t *d = &s->dma_dac; - u64 *data_p; - unsigned swptr; - unsigned long flags; - serdma_descr_t *descr; - - if (s->reg_request) { - printk(KERN_ERR "cs4297a: attempt to issue multiple reg_access\n"); - return -1; - } - - if (s->ena & FMODE_WRITE) { - /* Since a writer has the DSP open, we have to mux the - request in */ - s->reg_request = data; - interruptible_sleep_on(&s->dma_dac.reg_wait); - /* XXXKW how can I deal with the starvation case where - the opener isn't writing? */ - } else { - /* Be safe when changing ring pointers */ - spin_lock_irqsave(&s->lock, flags); - if (d->hwptr != d->swptr) { - printk(KERN_ERR "cs4297a: reg access found bookkeeping error (hw/sw = %d/%d\n", - d->hwptr, d->swptr); - spin_unlock_irqrestore(&s->lock, flags); - return -1; - } - swptr = d->swptr; - d->hwptr = d->swptr = (d->swptr + 1) % d->ringsz; - spin_unlock_irqrestore(&s->lock, flags); - - descr = &d->descrtab[swptr]; - data_p = &d->dma_buf[swptr * 4]; - *data_p = cpu_to_be64(data); - __raw_writeq(1, SS_CSR(R_SER_DMA_DSCR_COUNT_TX)); - CS_DBGOUT(CS_DESCR, 4, - printk(KERN_INFO "cs4297a: add_tx %p (%x -> %x)\n", - data_p, swptr, d->hwptr)); - } - - CS_DBGOUT(CS_FUNCTION, 6, - printk(KERN_INFO "cs4297a: serdma_reg_access()-\n")); - - return 0; -} - -//**************************************************************************** -// "cs4297a_read_ac97" -- Reads an AC97 register -//**************************************************************************** -static int cs4297a_read_ac97(struct cs4297a_state *s, u32 offset, - u32 * value) -{ - CS_DBGOUT(CS_AC97, 1, - printk(KERN_INFO "cs4297a: read reg %2x\n", offset)); - if (serdma_reg_access(s, (0xCLL << 60) | (1LL << 47) | ((u64)(offset & 0x7F) << 40))) - return -1; - - interruptible_sleep_on(&s->dma_adc.reg_wait); - *value = s->read_value; - CS_DBGOUT(CS_AC97, 2, - printk(KERN_INFO "cs4297a: rdr reg %x -> %x\n", s->read_reg, s->read_value)); - - return 0; -} - - -//**************************************************************************** -// "cs4297a_write_ac97()"-- writes an AC97 register -//**************************************************************************** -static int cs4297a_write_ac97(struct cs4297a_state *s, u32 offset, - u32 value) -{ - CS_DBGOUT(CS_AC97, 1, - printk(KERN_INFO "cs4297a: write reg %2x -> %04x\n", offset, value)); - return (serdma_reg_access(s, (0xELL << 60) | ((u64)(offset & 0x7F) << 40) | ((value & 0xffff) << 12))); -} - -static void stop_dac(struct cs4297a_state *s) -{ - unsigned long flags; - - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4297a: stop_dac():\n")); - spin_lock_irqsave(&s->lock, flags); - s->ena &= ~FMODE_WRITE; -#if 0 - /* XXXKW what do I really want here? My theory for now is - that I just flip the "ena" bit, and the interrupt handler - will stop processing the xmit channel */ - __raw_writeq((s->ena & FMODE_READ) ? M_SYNCSER_DMA_RX_EN : 0, - SS_CSR(R_SER_DMA_ENABLE)); -#endif - - spin_unlock_irqrestore(&s->lock, flags); -} - - -static void start_dac(struct cs4297a_state *s) -{ - unsigned long flags; - - CS_DBGOUT(CS_FUNCTION, 3, printk(KERN_INFO "cs4297a: start_dac()+\n")); - spin_lock_irqsave(&s->lock, flags); - if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped || - (s->dma_dac.count > 0 - && s->dma_dac.ready))) { - s->ena |= FMODE_WRITE; - /* XXXKW what do I really want here? My theory for - now is that I just flip the "ena" bit, and the - interrupt handler will start processing the xmit - channel */ - - CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 8, printk(KERN_INFO - "cs4297a: start_dac(): start dma\n")); - - } - spin_unlock_irqrestore(&s->lock, flags); - CS_DBGOUT(CS_FUNCTION, 3, - printk(KERN_INFO "cs4297a: start_dac()-\n")); -} - - -static void stop_adc(struct cs4297a_state *s) -{ - unsigned long flags; - - CS_DBGOUT(CS_FUNCTION, 3, - printk(KERN_INFO "cs4297a: stop_adc()+\n")); - - spin_lock_irqsave(&s->lock, flags); - s->ena &= ~FMODE_READ; - - if (s->conversion == 1) { - s->conversion = 0; - s->prop_adc.fmt = s->prop_adc.fmt_original; - } - /* Nothing to do really, I need to keep the DMA going - XXXKW when do I get here, and is there more I should do? */ - spin_unlock_irqrestore(&s->lock, flags); - CS_DBGOUT(CS_FUNCTION, 3, - printk(KERN_INFO "cs4297a: stop_adc()-\n")); -} - - -static void start_adc(struct cs4297a_state *s) -{ - unsigned long flags; - - CS_DBGOUT(CS_FUNCTION, 2, - printk(KERN_INFO "cs4297a: start_adc()+\n")); - - if (!(s->ena & FMODE_READ) && - (s->dma_adc.mapped || s->dma_adc.count <= - (signed) (s->dma_adc.sbufsz - 2 * s->dma_adc.fragsize)) - && s->dma_adc.ready) { - if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) { - // - // now only use 16 bit capture, due to truncation issue - // in the chip, noticeable distortion occurs. - // allocate buffer and then convert from 16 bit to - // 8 bit for the user buffer. - // - s->prop_adc.fmt_original = s->prop_adc.fmt; - if (s->prop_adc.fmt & AFMT_S8) { - s->prop_adc.fmt &= ~AFMT_S8; - s->prop_adc.fmt |= AFMT_S16_LE; - } - if (s->prop_adc.fmt & AFMT_U8) { - s->prop_adc.fmt &= ~AFMT_U8; - s->prop_adc.fmt |= AFMT_U16_LE; - } - // - // prog_dmabuf_adc performs a stop_adc() but that is - // ok since we really haven't started the DMA yet. - // - prog_codec(s, CS_TYPE_ADC); - - prog_dmabuf_adc(s); - s->conversion = 1; - } - spin_lock_irqsave(&s->lock, flags); - s->ena |= FMODE_READ; - /* Nothing to do really, I am probably already - DMAing... XXXKW when do I get here, and is there - more I should do? */ - spin_unlock_irqrestore(&s->lock, flags); - - CS_DBGOUT(CS_PARMS, 6, printk(KERN_INFO - "cs4297a: start_adc(): start adc\n")); - } - CS_DBGOUT(CS_FUNCTION, 2, - printk(KERN_INFO "cs4297a: start_adc()-\n")); - -} - - -// call with spinlock held! -static void cs4297a_update_ptr(struct cs4297a_state *s, int intflag) -{ - int good_diff, diff, diff2; - u64 *data_p, data; - u32 *s_ptr; - unsigned hwptr; - u32 status; - serdma_t *d; - serdma_descr_t *descr; - - // update ADC pointer - status = intflag ? __raw_readq(SS_CSR(R_SER_STATUS)) : 0; - - if ((s->ena & FMODE_READ) || (status & (M_SYNCSER_RX_EOP_COUNT))) { - d = &s->dma_adc; - hwptr = (unsigned) (((__raw_readq(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_RX)) & M_DMA_CURDSCR_ADDR) - - d->descrtab_phys) / sizeof(serdma_descr_t)); - - if (s->ena & FMODE_READ) { - CS_DBGOUT(CS_FUNCTION, 2, - printk(KERN_INFO "cs4297a: upd_rcv sw->hw->hw %x/%x/%x (int-%d)n", - d->swptr, d->hwptr, hwptr, intflag)); - /* Number of DMA buffers available for software: */ - diff2 = diff = (d->ringsz + hwptr - d->hwptr) % d->ringsz; - d->hwptr = hwptr; - good_diff = 0; - s_ptr = (u32 *)&(d->dma_buf[d->swptr*4]); - descr = &d->descrtab[d->swptr]; - while (diff2--) { - u64 data = be64_to_cpu(*(u64 *)s_ptr); - u64 descr_a; - u16 left, right; - descr_a = descr->descr_a; - descr->descr_a &= ~M_DMA_SERRX_SOP; - if ((descr_a & M_DMA_DSCRA_A_ADDR) != CPHYSADDR((long)s_ptr)) { - printk(KERN_ERR "cs4297a: RX Bad address (read)\n"); - } - if (((data & 0x9800000000000000) != 0x9800000000000000) || - (!(descr_a & M_DMA_SERRX_SOP)) || - (G_DMA_DSCRB_PKT_SIZE(descr->descr_b) != FRAME_BYTES)) { - s->stats.rx_bad++; - printk(KERN_DEBUG "cs4297a: RX Bad attributes (read)\n"); - continue; - } - s->stats.rx_good++; - if ((data >> 61) == 7) { - s->read_value = (data >> 12) & 0xffff; - s->read_reg = (data >> 40) & 0x7f; - wake_up(&d->reg_wait); - } - if (d->count && (d->sb_hwptr == d->sb_swptr)) { - s->stats.rx_overflow++; - printk(KERN_DEBUG "cs4297a: RX overflow\n"); - continue; - } - good_diff++; - left = ((be32_to_cpu(s_ptr[1]) & 0xff) << 8) | - ((be32_to_cpu(s_ptr[2]) >> 24) & 0xff); - right = (be32_to_cpu(s_ptr[2]) >> 4) & 0xffff; - *d->sb_hwptr++ = cpu_to_be16(left); - *d->sb_hwptr++ = cpu_to_be16(right); - if (d->sb_hwptr == d->sb_end) - d->sb_hwptr = d->sample_buf; - descr++; - if (descr == d->descrtab_end) { - descr = d->descrtab; - s_ptr = (u32 *)s->dma_adc.dma_buf; - } else { - s_ptr += 8; - } - } - d->total_bytes += good_diff * FRAME_SAMPLE_BYTES; - d->count += good_diff * FRAME_SAMPLE_BYTES; - if (d->count > d->sbufsz) { - printk(KERN_ERR "cs4297a: bogus receive overflow!!\n"); - } - d->swptr = (d->swptr + diff) % d->ringsz; - __raw_writeq(diff, SS_CSR(R_SER_DMA_DSCR_COUNT_RX)); - if (d->mapped) { - if (d->count >= (signed) d->fragsize) - wake_up(&d->wait); - } else { - if (d->count > 0) { - CS_DBGOUT(CS_WAVE_READ, 4, - printk(KERN_INFO - "cs4297a: update count -> %d\n", d->count)); - wake_up(&d->wait); - } - } - } else { - /* Receive is going even if no one is - listening (for register accesses and to - avoid FIFO overrun) */ - diff2 = diff = (hwptr + d->ringsz - d->hwptr) % d->ringsz; - if (!diff) { - printk(KERN_ERR "cs4297a: RX full or empty?\n"); - } - - descr = &d->descrtab[d->swptr]; - data_p = &d->dma_buf[d->swptr*4]; - - /* Force this to happen at least once; I got - here because of an interrupt, so there must - be a buffer to process. */ - do { - data = be64_to_cpu(*data_p); - if ((descr->descr_a & M_DMA_DSCRA_A_ADDR) != CPHYSADDR((long)data_p)) { - printk(KERN_ERR "cs4297a: RX Bad address %d (%llx %lx)\n", d->swptr, - (long long)(descr->descr_a & M_DMA_DSCRA_A_ADDR), - (long)CPHYSADDR((long)data_p)); - } - if (!(data & (1LL << 63)) || - !(descr->descr_a & M_DMA_SERRX_SOP) || - (G_DMA_DSCRB_PKT_SIZE(descr->descr_b) != FRAME_BYTES)) { - s->stats.rx_bad++; - printk(KERN_DEBUG "cs4297a: RX Bad attributes\n"); - } else { - s->stats.rx_good++; - if ((data >> 61) == 7) { - s->read_value = (data >> 12) & 0xffff; - s->read_reg = (data >> 40) & 0x7f; - wake_up(&d->reg_wait); - } - } - descr->descr_a &= ~M_DMA_SERRX_SOP; - descr++; - d->swptr++; - data_p += 4; - if (descr == d->descrtab_end) { - descr = d->descrtab; - d->swptr = 0; - data_p = d->dma_buf; - } - __raw_writeq(1, SS_CSR(R_SER_DMA_DSCR_COUNT_RX)); - } while (--diff); - d->hwptr = hwptr; - - CS_DBGOUT(CS_DESCR, 6, - printk(KERN_INFO "cs4297a: hw/sw %x/%x\n", d->hwptr, d->swptr)); - } - - CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO - "cs4297a: cs4297a_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", - (unsigned)s, d->hwptr, - d->total_bytes, d->count)); - } - - /* XXXKW worry about s->reg_request -- there is a starvation - case if s->ena has FMODE_WRITE on, but the client isn't - doing writes */ - - // update DAC pointer - // - // check for end of buffer, means that we are going to wait for another interrupt - // to allow silence to fill the fifos on the part, to keep pops down to a minimum. - // - if (s->ena & FMODE_WRITE) { - serdma_t *d = &s->dma_dac; - hwptr = (unsigned) (((__raw_readq(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_TX)) & M_DMA_CURDSCR_ADDR) - - d->descrtab_phys) / sizeof(serdma_descr_t)); - diff = (d->ringsz + hwptr - d->hwptr) % d->ringsz; - CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO - "cs4297a: cs4297a_update_ptr(): hw/hw/sw %x/%x/%x diff %d count %d\n", - d->hwptr, hwptr, d->swptr, diff, d->count)); - d->hwptr = hwptr; - /* XXXKW stereo? conversion? Just assume 2 16-bit samples for now */ - d->total_bytes += diff * FRAME_SAMPLE_BYTES; - if (d->mapped) { - d->count += diff * FRAME_SAMPLE_BYTES; - if (d->count >= d->fragsize) { - d->wakeup = 1; - wake_up(&d->wait); - if (d->count > d->sbufsz) - d->count &= d->sbufsz - 1; - } - } else { - d->count -= diff * FRAME_SAMPLE_BYTES; - if (d->count <= 0) { - // - // fill with silence, and do not shut down the DAC. - // Continue to play silence until the _release. - // - CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO - "cs4297a: cs4297a_update_ptr(): memset %d at 0x%.8x for %d size \n", - (unsigned)(s->prop_dac.fmt & - (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, - (unsigned)d->dma_buf, - d->ringsz)); - memset(d->dma_buf, 0, d->ringsz * FRAME_BYTES); - if (d->count < 0) { - d->underrun = 1; - s->stats.tx_underrun++; - d->count = 0; - CS_DBGOUT(CS_ERROR, 9, printk(KERN_INFO - "cs4297a: cs4297a_update_ptr(): underrun\n")); - } - } else if (d->count <= - (signed) d->fragsize - && !d->endcleared) { - /* XXXKW what is this for? */ - clear_advance(d->dma_buf, - d->sbufsz, - d->swptr, - d->fragsize, - 0); - d->endcleared = 1; - } - if ( (d->count <= (signed) d->sbufsz/2) || intflag) - { - CS_DBGOUT(CS_WAVE_WRITE, 4, - printk(KERN_INFO - "cs4297a: update count -> %d\n", d->count)); - wake_up(&d->wait); - } - } - CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO - "cs4297a: cs4297a_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", - (unsigned) s, d->hwptr, - d->total_bytes, d->count)); - } -} - -static int mixer_ioctl(struct cs4297a_state *s, unsigned int cmd, - unsigned long arg) -{ - // Index to mixer_src[] is value of AC97 Input Mux Select Reg. - // Value of array member is recording source Device ID Mask. - static const unsigned int mixer_src[8] = { - SOUND_MASK_MIC, SOUND_MASK_CD, 0, SOUND_MASK_LINE1, - SOUND_MASK_LINE, SOUND_MASK_VOLUME, 0, 0 - }; - - // Index of mixtable1[] member is Device ID - // and must be <= SOUND_MIXER_NRDEVICES. - // Value of array member is index into s->mix.vol[] - static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = { - [SOUND_MIXER_PCM] = 1, // voice - [SOUND_MIXER_LINE1] = 2, // AUX - [SOUND_MIXER_CD] = 3, // CD - [SOUND_MIXER_LINE] = 4, // Line - [SOUND_MIXER_SYNTH] = 5, // FM - [SOUND_MIXER_MIC] = 6, // Mic - [SOUND_MIXER_SPEAKER] = 7, // Speaker - [SOUND_MIXER_RECLEV] = 8, // Recording level - [SOUND_MIXER_VOLUME] = 9 // Master Volume - }; - - static const unsigned mixreg[] = { - AC97_PCMOUT_VOL, - AC97_AUX_VOL, - AC97_CD_VOL, - AC97_LINEIN_VOL - }; - unsigned char l, r, rl, rr, vidx; - unsigned char attentbl[11] = - { 63, 42, 26, 17, 14, 11, 8, 6, 4, 2, 0 }; - unsigned temp1; - int i, val; - - VALIDATE_STATE(s); - CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO - "cs4297a: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n", - (unsigned) s, cmd)); -#if CSDEBUG - cs_printioctl(cmd); -#endif -#if CSDEBUG_INTERFACE - - if ((cmd == SOUND_MIXER_CS_GETDBGMASK) || - (cmd == SOUND_MIXER_CS_SETDBGMASK) || - (cmd == SOUND_MIXER_CS_GETDBGLEVEL) || - (cmd == SOUND_MIXER_CS_SETDBGLEVEL)) - { - switch (cmd) { - - case SOUND_MIXER_CS_GETDBGMASK: - return put_user(cs_debugmask, - (unsigned long *) arg); - - case SOUND_MIXER_CS_GETDBGLEVEL: - return put_user(cs_debuglevel, - (unsigned long *) arg); - - case SOUND_MIXER_CS_SETDBGMASK: - if (get_user(val, (unsigned long *) arg)) - return -EFAULT; - cs_debugmask = val; - return 0; - - case SOUND_MIXER_CS_SETDBGLEVEL: - if (get_user(val, (unsigned long *) arg)) - return -EFAULT; - cs_debuglevel = val; - return 0; - default: - CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO - "cs4297a: mixer_ioctl(): ERROR unknown debug cmd\n")); - return 0; - } - } -#endif - - if (cmd == SOUND_MIXER_PRIVATE1) { - return -EINVAL; - } - if (cmd == SOUND_MIXER_PRIVATE2) { - // enable/disable/query spatializer - if (get_user(val, (int *) arg)) - return -EFAULT; - if (val != -1) { - temp1 = (val & 0x3f) >> 2; - cs4297a_write_ac97(s, AC97_3D_CONTROL, temp1); - cs4297a_read_ac97(s, AC97_GENERAL_PURPOSE, - &temp1); - cs4297a_write_ac97(s, AC97_GENERAL_PURPOSE, - temp1 | 0x2000); - } - cs4297a_read_ac97(s, AC97_3D_CONTROL, &temp1); - return put_user((temp1 << 2) | 3, (int *) arg); - } - if (cmd == SOUND_MIXER_INFO) { - mixer_info info; - memset(&info, 0, sizeof(info)); - strlcpy(info.id, "CS4297a", sizeof(info.id)); - strlcpy(info.name, "Crystal CS4297a", sizeof(info.name)); - info.modify_counter = s->mix.modcnt; - if (copy_to_user((void *) arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == SOUND_OLD_MIXER_INFO) { - _old_mixer_info info; - memset(&info, 0, sizeof(info)); - strlcpy(info.id, "CS4297a", sizeof(info.id)); - strlcpy(info.name, "Crystal CS4297a", sizeof(info.name)); - if (copy_to_user((void *) arg, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, (int *) arg); - - if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) - return -EINVAL; - - // If ioctl has only the SIOC_READ bit(bit 31) - // on, process the only-read commands. - if (_SIOC_DIR(cmd) == _SIOC_READ) { - switch (_IOC_NR(cmd)) { - case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source - cs4297a_read_ac97(s, AC97_RECORD_SELECT, - &temp1); - return put_user(mixer_src[temp1 & 7], (int *) arg); - - case SOUND_MIXER_DEVMASK: // Arg contains a bit for each supported device - return put_user(SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_VOLUME | SOUND_MASK_RECLEV, - (int *) arg); - - case SOUND_MIXER_RECMASK: // Arg contains a bit for each supported recording source - return put_user(SOUND_MASK_LINE | SOUND_MASK_VOLUME, - (int *) arg); - - case SOUND_MIXER_STEREODEVS: // Mixer channels supporting stereo - return put_user(SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_VOLUME | SOUND_MASK_RECLEV, - (int *) arg); - - case SOUND_MIXER_CAPS: - return put_user(SOUND_CAP_EXCL_INPUT, (int *) arg); - - default: - i = _IOC_NR(cmd); - if (i >= SOUND_MIXER_NRDEVICES - || !(vidx = mixtable1[i])) - return -EINVAL; - return put_user(s->mix.vol[vidx - 1], (int *) arg); - } - } - // If ioctl doesn't have both the SIOC_READ and - // the SIOC_WRITE bit set, return invalid. - if (_SIOC_DIR(cmd) != (_SIOC_READ | _SIOC_WRITE)) - return -EINVAL; - - // Increment the count of volume writes. - s->mix.modcnt++; - - // Isolate the command; it must be a write. - switch (_IOC_NR(cmd)) { - - case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source - if (get_user(val, (int *) arg)) - return -EFAULT; - i = hweight32(val); // i = # bits on in val. - if (i != 1) // One & only 1 bit must be on. - return 0; - for (i = 0; i < sizeof(mixer_src) / sizeof(int); i++) { - if (val == mixer_src[i]) { - temp1 = (i << 8) | i; - cs4297a_write_ac97(s, - AC97_RECORD_SELECT, - temp1); - return 0; - } - } - return 0; - - case SOUND_MIXER_VOLUME: - if (get_user(val, (int *) arg)) - return -EFAULT; - l = val & 0xff; - if (l > 100) - l = 100; // Max soundcard.h vol is 100. - if (l < 6) { - rl = 63; - l = 0; - } else - rl = attentbl[(10 * l) / 100]; // Convert 0-100 vol to 63-0 atten. - - r = (val >> 8) & 0xff; - if (r > 100) - r = 100; // Max right volume is 100, too - if (r < 6) { - rr = 63; - r = 0; - } else - rr = attentbl[(10 * r) / 100]; // Convert volume to attenuation. - - if ((rl > 60) && (rr > 60)) // If both l & r are 'low', - temp1 = 0x8000; // turn on the mute bit. - else - temp1 = 0; - - temp1 |= (rl << 8) | rr; - - cs4297a_write_ac97(s, AC97_MASTER_VOL_STEREO, temp1); - cs4297a_write_ac97(s, AC97_PHONE_VOL, temp1); - -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[8] = ((unsigned int) r << 8) | l; -#else - s->mix.vol[8] = val; -#endif - return put_user(s->mix.vol[8], (int *) arg); - - case SOUND_MIXER_SPEAKER: - if (get_user(val, (int *) arg)) - return -EFAULT; - l = val & 0xff; - if (l > 100) - l = 100; - if (l < 3) { - rl = 0; - l = 0; - } else { - rl = (l * 2 - 5) / 13; // Convert 0-100 range to 0-15. - l = (rl * 13 + 5) / 2; - } - - if (rl < 3) { - temp1 = 0x8000; - rl = 0; - } else - temp1 = 0; - rl = 15 - rl; // Convert volume to attenuation. - temp1 |= rl << 1; - cs4297a_write_ac97(s, AC97_PCBEEP_VOL, temp1); - -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[6] = l << 8; -#else - s->mix.vol[6] = val; -#endif - return put_user(s->mix.vol[6], (int *) arg); - - case SOUND_MIXER_RECLEV: - if (get_user(val, (int *) arg)) - return -EFAULT; - l = val & 0xff; - if (l > 100) - l = 100; - r = (val >> 8) & 0xff; - if (r > 100) - r = 100; - rl = (l * 2 - 5) / 13; // Convert 0-100 scale to 0-15. - rr = (r * 2 - 5) / 13; - if (rl < 3 && rr < 3) - temp1 = 0x8000; - else - temp1 = 0; - - temp1 = temp1 | (rl << 8) | rr; - cs4297a_write_ac97(s, AC97_RECORD_GAIN, temp1); - -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[7] = ((unsigned int) r << 8) | l; -#else - s->mix.vol[7] = val; -#endif - return put_user(s->mix.vol[7], (int *) arg); - - case SOUND_MIXER_MIC: - if (get_user(val, (int *) arg)) - return -EFAULT; - l = val & 0xff; - if (l > 100) - l = 100; - if (l < 1) { - l = 0; - rl = 0; - } else { - rl = ((unsigned) l * 5 - 4) / 16; // Convert 0-100 range to 0-31. - l = (rl * 16 + 4) / 5; - } - cs4297a_read_ac97(s, AC97_MIC_VOL, &temp1); - temp1 &= 0x40; // Isolate 20db gain bit. - if (rl < 3) { - temp1 |= 0x8000; - rl = 0; - } - rl = 31 - rl; // Convert volume to attenuation. - temp1 |= rl; - cs4297a_write_ac97(s, AC97_MIC_VOL, temp1); - -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[5] = val << 8; -#else - s->mix.vol[5] = val; -#endif - return put_user(s->mix.vol[5], (int *) arg); - - - case SOUND_MIXER_SYNTH: - if (get_user(val, (int *) arg)) - return -EFAULT; - l = val & 0xff; - if (l > 100) - l = 100; - if (get_user(val, (int *) arg)) - return -EFAULT; - r = (val >> 8) & 0xff; - if (r > 100) - r = 100; - rl = (l * 2 - 11) / 3; // Convert 0-100 range to 0-63. - rr = (r * 2 - 11) / 3; - if (rl < 3) // If l is low, turn on - temp1 = 0x0080; // the mute bit. - else - temp1 = 0; - - rl = 63 - rl; // Convert vol to attenuation. -// writel(temp1 | rl, s->pBA0 + FMLVC); - if (rr < 3) // If rr is low, turn on - temp1 = 0x0080; // the mute bit. - else - temp1 = 0; - rr = 63 - rr; // Convert vol to attenuation. -// writel(temp1 | rr, s->pBA0 + FMRVC); - -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[4] = (r << 8) | l; -#else - s->mix.vol[4] = val; -#endif - return put_user(s->mix.vol[4], (int *) arg); - - - default: - CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO - "cs4297a: mixer_ioctl(): default\n")); - - i = _IOC_NR(cmd); - if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) - return -EINVAL; - if (get_user(val, (int *) arg)) - return -EFAULT; - l = val & 0xff; - if (l > 100) - l = 100; - if (l < 1) { - l = 0; - rl = 31; - } else - rl = (attentbl[(l * 10) / 100]) >> 1; - - r = (val >> 8) & 0xff; - if (r > 100) - r = 100; - if (r < 1) { - r = 0; - rr = 31; - } else - rr = (attentbl[(r * 10) / 100]) >> 1; - if ((rl > 30) && (rr > 30)) - temp1 = 0x8000; - else - temp1 = 0; - temp1 = temp1 | (rl << 8) | rr; - cs4297a_write_ac97(s, mixreg[vidx - 1], temp1); - -#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[vidx - 1] = ((unsigned int) r << 8) | l; -#else - s->mix.vol[vidx - 1] = val; -#endif - return put_user(s->mix.vol[vidx - 1], (int *) arg); - } -} - - -// --------------------------------------------------------------------- - -static int cs4297a_open_mixdev(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - struct cs4297a_state *s=NULL; - struct list_head *entry; - - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, - printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n")); - - mutex_lock(&swarm_cs4297a_mutex); - list_for_each(entry, &cs4297a_devs) - { - s = list_entry(entry, struct cs4297a_state, list); - if(s->dev_mixer == minor) - break; - } - if (!s) - { - CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, - printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n")); - - mutex_unlock(&swarm_cs4297a_mutex); - return -ENODEV; - } - VALIDATE_STATE(s); - file->private_data = s; - - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, - printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n")); - mutex_unlock(&swarm_cs4297a_mutex); - - return nonseekable_open(inode, file); -} - - -static int cs4297a_release_mixdev(struct inode *inode, struct file *file) -{ - struct cs4297a_state *s = - (struct cs4297a_state *) file->private_data; - - VALIDATE_STATE(s); - return 0; -} - - -static int cs4297a_ioctl_mixdev(struct file *file, - unsigned int cmd, unsigned long arg) -{ - int ret; - mutex_lock(&swarm_cs4297a_mutex); - ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd, - arg); - mutex_unlock(&swarm_cs4297a_mutex); - return ret; -} - - -// ****************************************************************************************** -// Mixer file operations struct. -// ****************************************************************************************** -static const struct file_operations cs4297a_mixer_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .unlocked_ioctl = cs4297a_ioctl_mixdev, - .open = cs4297a_open_mixdev, - .release = cs4297a_release_mixdev, -}; - -// --------------------------------------------------------------------- - - -static int drain_adc(struct cs4297a_state *s, int nonblock) -{ - /* This routine serves no purpose currently - any samples - sitting in the receive queue will just be processed by the - background consumer. This would be different if DMA - actually stopped when there were no clients. */ - return 0; -} - -static int drain_dac(struct cs4297a_state *s, int nonblock) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - unsigned hwptr; - unsigned tmo; - int count; - - if (s->dma_dac.mapped) - return 0; - if (nonblock) - return -EBUSY; - add_wait_queue(&s->dma_dac.wait, &wait); - while ((count = __raw_readq(SS_CSR(R_SER_DMA_DSCR_COUNT_TX))) || - (s->dma_dac.count > 0)) { - if (!signal_pending(current)) { - set_current_state(TASK_INTERRUPTIBLE); - /* XXXKW is this calculation working? */ - tmo = ((count * FRAME_TX_US) * HZ) / 1000000; - schedule_timeout(tmo + 1); - } else { - /* XXXKW do I care if there is a signal pending? */ - } - } - spin_lock_irqsave(&s->lock, flags); - /* Reset the bookkeeping */ - hwptr = (int)(((__raw_readq(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_TX)) & M_DMA_CURDSCR_ADDR) - - s->dma_dac.descrtab_phys) / sizeof(serdma_descr_t)); - s->dma_dac.hwptr = s->dma_dac.swptr = hwptr; - spin_unlock_irqrestore(&s->lock, flags); - remove_wait_queue(&s->dma_dac.wait, &wait); - current->state = TASK_RUNNING; - return 0; -} - - -// --------------------------------------------------------------------- - -static ssize_t cs4297a_read(struct file *file, char *buffer, size_t count, - loff_t * ppos) -{ - struct cs4297a_state *s = - (struct cs4297a_state *) file->private_data; - ssize_t ret; - unsigned long flags; - int cnt, count_fr, cnt_by; - unsigned copied = 0; - - CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, - printk(KERN_INFO "cs4297a: cs4297a_read()+ %d \n", count)); - - VALIDATE_STATE(s); - if (s->dma_adc.mapped) - return -ENXIO; - if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) - return ret; - if (!access_ok(VERIFY_WRITE, buffer, count)) - return -EFAULT; - ret = 0; -// -// "count" is the amount of bytes to read (from app), is decremented each loop -// by the amount of bytes that have been returned to the user buffer. -// "cnt" is the running total of each read from the buffer (changes each loop) -// "buffer" points to the app's buffer -// "ret" keeps a running total of the amount of bytes that have been copied -// to the user buffer. -// "copied" is the total bytes copied into the user buffer for each loop. -// - while (count > 0) { - CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO - "_read() count>0 count=%d .count=%d .swptr=%d .hwptr=%d \n", - count, s->dma_adc.count, - s->dma_adc.swptr, s->dma_adc.hwptr)); - spin_lock_irqsave(&s->lock, flags); - - /* cnt will be the number of available samples (16-bit - stereo); it starts out as the maxmimum consequetive - samples */ - cnt = (s->dma_adc.sb_end - s->dma_adc.sb_swptr) / 2; - count_fr = s->dma_adc.count / FRAME_SAMPLE_BYTES; - - // dma_adc.count is the current total bytes that have not been read. - // if the amount of unread bytes from the current sw pointer to the - // end of the buffer is greater than the current total bytes that - // have not been read, then set the "cnt" (unread bytes) to the - // amount of unread bytes. - - if (count_fr < cnt) - cnt = count_fr; - cnt_by = cnt * FRAME_SAMPLE_BYTES; - spin_unlock_irqrestore(&s->lock, flags); - // - // if we are converting from 8/16 then we need to copy - // twice the number of 16 bit bytes then 8 bit bytes. - // - if (s->conversion) { - if (cnt_by > (count * 2)) { - cnt = (count * 2) / FRAME_SAMPLE_BYTES; - cnt_by = count * 2; - } - } else { - if (cnt_by > count) { - cnt = count / FRAME_SAMPLE_BYTES; - cnt_by = count; - } - } - // - // "cnt" NOW is the smaller of the amount that will be read, - // and the amount that is requested in this read (or partial). - // if there are no bytes in the buffer to read, then start the - // ADC and wait for the interrupt handler to wake us up. - // - if (cnt <= 0) { - - // start up the dma engine and then continue back to the top of - // the loop when wake up occurs. - start_adc(s); - if (file->f_flags & O_NONBLOCK) - return ret ? ret : -EAGAIN; - interruptible_sleep_on(&s->dma_adc.wait); - if (signal_pending(current)) - return ret ? ret : -ERESTARTSYS; - continue; - } - // there are bytes in the buffer to read. - // copy from the hw buffer over to the user buffer. - // user buffer is designated by "buffer" - // virtual address to copy from is dma_buf+swptr - // the "cnt" is the number of bytes to read. - - CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO - "_read() copy_to cnt=%d count=%d ", cnt_by, count)); - CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO - " .sbufsz=%d .count=%d buffer=0x%.8x ret=%d\n", - s->dma_adc.sbufsz, s->dma_adc.count, - (unsigned) buffer, ret)); - - if (copy_to_user (buffer, ((void *)s->dma_adc.sb_swptr), cnt_by)) - return ret ? ret : -EFAULT; - copied = cnt_by; - - /* Return the descriptors */ - spin_lock_irqsave(&s->lock, flags); - CS_DBGOUT(CS_FUNCTION, 2, - printk(KERN_INFO "cs4297a: upd_rcv sw->hw %x/%x\n", s->dma_adc.swptr, s->dma_adc.hwptr)); - s->dma_adc.count -= cnt_by; - s->dma_adc.sb_swptr += cnt * 2; - if (s->dma_adc.sb_swptr == s->dma_adc.sb_end) - s->dma_adc.sb_swptr = s->dma_adc.sample_buf; - spin_unlock_irqrestore(&s->lock, flags); - count -= copied; - buffer += copied; - ret += copied; - start_adc(s); - } - CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, - printk(KERN_INFO "cs4297a: cs4297a_read()- %d\n", ret)); - return ret; -} - - -static ssize_t cs4297a_write(struct file *file, const char *buffer, - size_t count, loff_t * ppos) -{ - struct cs4297a_state *s = - (struct cs4297a_state *) file->private_data; - ssize_t ret; - unsigned long flags; - unsigned swptr, hwptr; - int cnt; - - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, - printk(KERN_INFO "cs4297a: cs4297a_write()+ count=%d\n", - count)); - VALIDATE_STATE(s); - - if (s->dma_dac.mapped) - return -ENXIO; - if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) - return ret; - if (!access_ok(VERIFY_READ, buffer, count)) - return -EFAULT; - ret = 0; - while (count > 0) { - serdma_t *d = &s->dma_dac; - int copy_cnt; - u32 *s_tmpl; - u32 *t_tmpl; - u32 left, right; - int swap = (s->prop_dac.fmt == AFMT_S16_LE) || (s->prop_dac.fmt == AFMT_U16_LE); - - /* XXXXXX this is broken for BLOAT_FACTOR */ - spin_lock_irqsave(&s->lock, flags); - if (d->count < 0) { - d->count = 0; - d->swptr = d->hwptr; - } - if (d->underrun) { - d->underrun = 0; - hwptr = (unsigned) (((__raw_readq(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_TX)) & M_DMA_CURDSCR_ADDR) - - d->descrtab_phys) / sizeof(serdma_descr_t)); - d->swptr = d->hwptr = hwptr; - } - swptr = d->swptr; - cnt = d->sbufsz - (swptr * FRAME_SAMPLE_BYTES); - /* Will this write fill up the buffer? */ - if (d->count + cnt > d->sbufsz) - cnt = d->sbufsz - d->count; - spin_unlock_irqrestore(&s->lock, flags); - if (cnt > count) - cnt = count; - if (cnt <= 0) { - start_dac(s); - if (file->f_flags & O_NONBLOCK) - return ret ? ret : -EAGAIN; - interruptible_sleep_on(&d->wait); - if (signal_pending(current)) - return ret ? ret : -ERESTARTSYS; - continue; - } - if (copy_from_user(d->sample_buf, buffer, cnt)) - return ret ? ret : -EFAULT; - - copy_cnt = cnt; - s_tmpl = (u32 *)d->sample_buf; - t_tmpl = (u32 *)(d->dma_buf + (swptr * 4)); - - /* XXXKW assuming 16-bit stereo! */ - do { - u32 tmp; - - t_tmpl[0] = cpu_to_be32(0x98000000); - - tmp = be32_to_cpu(s_tmpl[0]); - left = tmp & 0xffff; - right = tmp >> 16; - if (swap) { - left = swab16(left); - right = swab16(right); - } - t_tmpl[1] = cpu_to_be32(left >> 8); - t_tmpl[2] = cpu_to_be32(((left & 0xff) << 24) | - (right << 4)); - - s_tmpl++; - t_tmpl += 8; - copy_cnt -= 4; - } while (copy_cnt); - - /* Mux in any pending read/write accesses */ - if (s->reg_request) { - *(u64 *)(d->dma_buf + (swptr * 4)) |= - cpu_to_be64(s->reg_request); - s->reg_request = 0; - wake_up(&s->dma_dac.reg_wait); - } - - CS_DBGOUT(CS_WAVE_WRITE, 4, - printk(KERN_INFO - "cs4297a: copy in %d to swptr %x\n", cnt, swptr)); - - swptr = (swptr + (cnt/FRAME_SAMPLE_BYTES)) % d->ringsz; - __raw_writeq(cnt/FRAME_SAMPLE_BYTES, SS_CSR(R_SER_DMA_DSCR_COUNT_TX)); - spin_lock_irqsave(&s->lock, flags); - d->swptr = swptr; - d->count += cnt; - d->endcleared = 0; - spin_unlock_irqrestore(&s->lock, flags); - count -= cnt; - buffer += cnt; - ret += cnt; - start_dac(s); - } - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, - printk(KERN_INFO "cs4297a: cs4297a_write()- %d\n", ret)); - return ret; -} - - -static unsigned int cs4297a_poll(struct file *file, - struct poll_table_struct *wait) -{ - struct cs4297a_state *s = - (struct cs4297a_state *) file->private_data; - unsigned long flags; - unsigned int mask = 0; - - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, - printk(KERN_INFO "cs4297a: cs4297a_poll()+\n")); - VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) { - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, - printk(KERN_INFO - "cs4297a: cs4297a_poll() wait on FMODE_WRITE\n")); - if(!s->dma_dac.ready && prog_dmabuf_dac(s)) - return 0; - poll_wait(file, &s->dma_dac.wait, wait); - } - if (file->f_mode & FMODE_READ) { - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, - printk(KERN_INFO - "cs4297a: cs4297a_poll() wait on FMODE_READ\n")); - if(!s->dma_dac.ready && prog_dmabuf_adc(s)) - return 0; - poll_wait(file, &s->dma_adc.wait, wait); - } - spin_lock_irqsave(&s->lock, flags); - cs4297a_update_ptr(s,CS_FALSE); - if (file->f_mode & FMODE_WRITE) { - if (s->dma_dac.mapped) { - if (s->dma_dac.count >= - (signed) s->dma_dac.fragsize) { - if (s->dma_dac.wakeup) - mask |= POLLOUT | POLLWRNORM; - else - mask = 0; - s->dma_dac.wakeup = 0; - } - } else { - if ((signed) (s->dma_dac.sbufsz/2) >= s->dma_dac.count) - mask |= POLLOUT | POLLWRNORM; - } - } else if (file->f_mode & FMODE_READ) { - if (s->dma_adc.mapped) { - if (s->dma_adc.count >= (signed) s->dma_adc.fragsize) - mask |= POLLIN | POLLRDNORM; - } else { - if (s->dma_adc.count > 0) - mask |= POLLIN | POLLRDNORM; - } - } - spin_unlock_irqrestore(&s->lock, flags); - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, - printk(KERN_INFO "cs4297a: cs4297a_poll()- 0x%.8x\n", - mask)); - return mask; -} - - -static int cs4297a_mmap(struct file *file, struct vm_area_struct *vma) -{ - /* XXXKW currently no mmap support */ - return -EINVAL; - return 0; -} - - -static int cs4297a_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct cs4297a_state *s = - (struct cs4297a_state *) file->private_data; - unsigned long flags; - audio_buf_info abinfo; - count_info cinfo; - int val, mapped, ret; - - CS_DBGOUT(CS_FUNCTION|CS_IOCTL, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): file=0x%.8x cmd=0x%.8x\n", - (unsigned) file, cmd)); -#if CSDEBUG - cs_printioctl(cmd); -#endif - VALIDATE_STATE(s); - mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || - ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); - switch (cmd) { - case OSS_GETVERSION: - CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): SOUND_VERSION=0x%.8x\n", - SOUND_VERSION)); - return put_user(SOUND_VERSION, (int *) arg); - - case SNDCTL_DSP_SYNC: - CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_SYNC\n")); - if (file->f_mode & FMODE_WRITE) - return drain_dac(s, - 0 /*file->f_flags & O_NONBLOCK */ - ); - return 0; - - case SNDCTL_DSP_SETDUPLEX: - return 0; - - case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | - DSP_CAP_TRIGGER | DSP_CAP_MMAP, - (int *) arg); - - case SNDCTL_DSP_RESET: - CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_RESET\n")); - if (file->f_mode & FMODE_WRITE) { - stop_dac(s); - synchronize_irq(s->irq); - s->dma_dac.count = s->dma_dac.total_bytes = - s->dma_dac.blocks = s->dma_dac.wakeup = 0; - s->dma_dac.swptr = s->dma_dac.hwptr = - (int)(((__raw_readq(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_TX)) & M_DMA_CURDSCR_ADDR) - - s->dma_dac.descrtab_phys) / sizeof(serdma_descr_t)); - } - if (file->f_mode & FMODE_READ) { - stop_adc(s); - synchronize_irq(s->irq); - s->dma_adc.count = s->dma_adc.total_bytes = - s->dma_adc.blocks = s->dma_dac.wakeup = 0; - s->dma_adc.swptr = s->dma_adc.hwptr = - (int)(((__raw_readq(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_RX)) & M_DMA_CURDSCR_ADDR) - - s->dma_adc.descrtab_phys) / sizeof(serdma_descr_t)); - } - return 0; - - case SNDCTL_DSP_SPEED: - if (get_user(val, (int *) arg)) - return -EFAULT; - CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_SPEED val=%d -> 48000\n", val)); - val = 48000; - return put_user(val, (int *) arg); - - case SNDCTL_DSP_STEREO: - if (get_user(val, (int *) arg)) - return -EFAULT; - CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_STEREO val=%d\n", val)); - if (file->f_mode & FMODE_READ) { - stop_adc(s); - s->dma_adc.ready = 0; - s->prop_adc.channels = val ? 2 : 1; - } - if (file->f_mode & FMODE_WRITE) { - stop_dac(s); - s->dma_dac.ready = 0; - s->prop_dac.channels = val ? 2 : 1; - } - return 0; - - case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *) arg)) - return -EFAULT; - CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_CHANNELS val=%d\n", - val)); - if (val != 0) { - if (file->f_mode & FMODE_READ) { - stop_adc(s); - s->dma_adc.ready = 0; - if (val >= 2) - s->prop_adc.channels = 2; - else - s->prop_adc.channels = 1; - } - if (file->f_mode & FMODE_WRITE) { - stop_dac(s); - s->dma_dac.ready = 0; - if (val >= 2) - s->prop_dac.channels = 2; - else - s->prop_dac.channels = 1; - } - } - - if (file->f_mode & FMODE_WRITE) - val = s->prop_dac.channels; - else if (file->f_mode & FMODE_READ) - val = s->prop_adc.channels; - - return put_user(val, (int *) arg); - - case SNDCTL_DSP_GETFMTS: // Returns a mask - CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_GETFMT val=0x%.8x\n", - AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | - AFMT_U8)); - return put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | - AFMT_U8, (int *) arg); - - case SNDCTL_DSP_SETFMT: - if (get_user(val, (int *) arg)) - return -EFAULT; - CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_SETFMT val=0x%.8x\n", - val)); - if (val != AFMT_QUERY) { - if (file->f_mode & FMODE_READ) { - stop_adc(s); - s->dma_adc.ready = 0; - if (val != AFMT_S16_LE - && val != AFMT_U16_LE && val != AFMT_S8 - && val != AFMT_U8) - val = AFMT_U8; - s->prop_adc.fmt = val; - s->prop_adc.fmt_original = s->prop_adc.fmt; - } - if (file->f_mode & FMODE_WRITE) { - stop_dac(s); - s->dma_dac.ready = 0; - if (val != AFMT_S16_LE - && val != AFMT_U16_LE && val != AFMT_S8 - && val != AFMT_U8) - val = AFMT_U8; - s->prop_dac.fmt = val; - s->prop_dac.fmt_original = s->prop_dac.fmt; - } - } else { - if (file->f_mode & FMODE_WRITE) - val = s->prop_dac.fmt_original; - else if (file->f_mode & FMODE_READ) - val = s->prop_adc.fmt_original; - } - CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_SETFMT return val=0x%.8x\n", - val)); - return put_user(val, (int *) arg); - - case SNDCTL_DSP_POST: - CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): DSP_POST\n")); - return 0; - - case SNDCTL_DSP_GETTRIGGER: - val = 0; - if (file->f_mode & s->ena & FMODE_READ) - val |= PCM_ENABLE_INPUT; - if (file->f_mode & s->ena & FMODE_WRITE) - val |= PCM_ENABLE_OUTPUT; - return put_user(val, (int *) arg); - - case SNDCTL_DSP_SETTRIGGER: - if (get_user(val, (int *) arg)) - return -EFAULT; - if (file->f_mode & FMODE_READ) { - if (val & PCM_ENABLE_INPUT) { - if (!s->dma_adc.ready - && (ret = prog_dmabuf_adc(s))) - return ret; - start_adc(s); - } else - stop_adc(s); - } - if (file->f_mode & FMODE_WRITE) { - if (val & PCM_ENABLE_OUTPUT) { - if (!s->dma_dac.ready - && (ret = prog_dmabuf_dac(s))) - return ret; - start_dac(s); - } else - stop_dac(s); - } - return 0; - - case SNDCTL_DSP_GETOSPACE: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s))) - return val; - spin_lock_irqsave(&s->lock, flags); - cs4297a_update_ptr(s,CS_FALSE); - abinfo.fragsize = s->dma_dac.fragsize; - if (s->dma_dac.mapped) - abinfo.bytes = s->dma_dac.sbufsz; - else - abinfo.bytes = - s->dma_dac.sbufsz - s->dma_dac.count; - abinfo.fragstotal = s->dma_dac.numfrag; - abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; - CS_DBGOUT(CS_FUNCTION | CS_PARMS, 4, printk(KERN_INFO - "cs4297a: cs4297a_ioctl(): GETOSPACE .fragsize=%d .bytes=%d .fragstotal=%d .fragments=%d\n", - abinfo.fragsize,abinfo.bytes,abinfo.fragstotal, - abinfo.fragments)); - spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *) arg, &abinfo, - sizeof(abinfo)) ? -EFAULT : 0; - - case SNDCTL_DSP_GETISPACE: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s))) - return val; - spin_lock_irqsave(&s->lock, flags); - cs4297a_update_ptr(s,CS_FALSE); - if (s->conversion) { - abinfo.fragsize = s->dma_adc.fragsize / 2; - abinfo.bytes = s->dma_adc.count / 2; - abinfo.fragstotal = s->dma_adc.numfrag; - abinfo.fragments = - abinfo.bytes >> (s->dma_adc.fragshift - 1); - } else { - abinfo.fragsize = s->dma_adc.fragsize; - abinfo.bytes = s->dma_adc.count; - abinfo.fragstotal = s->dma_adc.numfrag; - abinfo.fragments = - abinfo.bytes >> s->dma_adc.fragshift; - } - spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *) arg, &abinfo, - sizeof(abinfo)) ? -EFAULT : 0; - - case SNDCTL_DSP_NONBLOCK: - spin_lock(&file->f_lock); - file->f_flags |= O_NONBLOCK; - spin_unlock(&file->f_lock); - return 0; - - case SNDCTL_DSP_GETODELAY: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - if(!s->dma_dac.ready && prog_dmabuf_dac(s)) - return 0; - spin_lock_irqsave(&s->lock, flags); - cs4297a_update_ptr(s,CS_FALSE); - val = s->dma_dac.count; - spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *) arg); - - case SNDCTL_DSP_GETIPTR: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - if(!s->dma_adc.ready && prog_dmabuf_adc(s)) - return 0; - spin_lock_irqsave(&s->lock, flags); - cs4297a_update_ptr(s,CS_FALSE); - cinfo.bytes = s->dma_adc.total_bytes; - if (s->dma_adc.mapped) { - cinfo.blocks = - (cinfo.bytes >> s->dma_adc.fragshift) - - s->dma_adc.blocks; - s->dma_adc.blocks = - cinfo.bytes >> s->dma_adc.fragshift; - } else { - if (s->conversion) { - cinfo.blocks = - s->dma_adc.count / - 2 >> (s->dma_adc.fragshift - 1); - } else - cinfo.blocks = - s->dma_adc.count >> s->dma_adc. - fragshift; - } - if (s->conversion) - cinfo.ptr = s->dma_adc.hwptr / 2; - else - cinfo.ptr = s->dma_adc.hwptr; - if (s->dma_adc.mapped) - s->dma_adc.count &= s->dma_adc.fragsize - 1; - spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; - - case SNDCTL_DSP_GETOPTR: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - if(!s->dma_dac.ready && prog_dmabuf_dac(s)) - return 0; - spin_lock_irqsave(&s->lock, flags); - cs4297a_update_ptr(s,CS_FALSE); - cinfo.bytes = s->dma_dac.total_bytes; - if (s->dma_dac.mapped) { - cinfo.blocks = - (cinfo.bytes >> s->dma_dac.fragshift) - - s->dma_dac.blocks; - s->dma_dac.blocks = - cinfo.bytes >> s->dma_dac.fragshift; - } else { - cinfo.blocks = - s->dma_dac.count >> s->dma_dac.fragshift; - } - cinfo.ptr = s->dma_dac.hwptr; - if (s->dma_dac.mapped) - s->dma_dac.count &= s->dma_dac.fragsize - 1; - spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0; - - case SNDCTL_DSP_GETBLKSIZE: - if (file->f_mode & FMODE_WRITE) { - if ((val = prog_dmabuf_dac(s))) - return val; - return put_user(s->dma_dac.fragsize, (int *) arg); - } - if ((val = prog_dmabuf_adc(s))) - return val; - if (s->conversion) - return put_user(s->dma_adc.fragsize / 2, - (int *) arg); - else - return put_user(s->dma_adc.fragsize, (int *) arg); - - case SNDCTL_DSP_SETFRAGMENT: - if (get_user(val, (int *) arg)) - return -EFAULT; - return 0; // Say OK, but do nothing. - - case SNDCTL_DSP_SUBDIVIDE: - if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) - || (file->f_mode & FMODE_WRITE - && s->dma_dac.subdivision)) return -EINVAL; - if (get_user(val, (int *) arg)) - return -EFAULT; - if (val != 1 && val != 2 && val != 4) - return -EINVAL; - if (file->f_mode & FMODE_READ) - s->dma_adc.subdivision = val; - else if (file->f_mode & FMODE_WRITE) - s->dma_dac.subdivision = val; - return 0; - - case SOUND_PCM_READ_RATE: - if (file->f_mode & FMODE_READ) - return put_user(s->prop_adc.rate, (int *) arg); - else if (file->f_mode & FMODE_WRITE) - return put_user(s->prop_dac.rate, (int *) arg); - - case SOUND_PCM_READ_CHANNELS: - if (file->f_mode & FMODE_READ) - return put_user(s->prop_adc.channels, (int *) arg); - else if (file->f_mode & FMODE_WRITE) - return put_user(s->prop_dac.channels, (int *) arg); - - case SOUND_PCM_READ_BITS: - if (file->f_mode & FMODE_READ) - return - put_user( - (s->prop_adc. - fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16, - (int *) arg); - else if (file->f_mode & FMODE_WRITE) - return - put_user( - (s->prop_dac. - fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16, - (int *) arg); - - case SOUND_PCM_WRITE_FILTER: - case SNDCTL_DSP_SETSYNCRO: - case SOUND_PCM_READ_FILTER: - return -EINVAL; - } - return mixer_ioctl(s, cmd, arg); -} - -static long cs4297a_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) -{ - int ret; - - mutex_lock(&swarm_cs4297a_mutex); - ret = cs4297a_ioctl(file, cmd, arg); - mutex_unlock(&swarm_cs4297a_mutex); - - return ret; -} - -static int cs4297a_release(struct inode *inode, struct file *file) -{ - struct cs4297a_state *s = - (struct cs4297a_state *) file->private_data; - - CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk(KERN_INFO - "cs4297a: cs4297a_release(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n", - (unsigned) inode, (unsigned) file, file->f_mode)); - VALIDATE_STATE(s); - - if (file->f_mode & FMODE_WRITE) { - drain_dac(s, file->f_flags & O_NONBLOCK); - mutex_lock(&s->open_sem_dac); - stop_dac(s); - dealloc_dmabuf(s, &s->dma_dac); - s->open_mode &= ~FMODE_WRITE; - mutex_unlock(&s->open_sem_dac); - wake_up(&s->open_wait_dac); - } - if (file->f_mode & FMODE_READ) { - drain_adc(s, file->f_flags & O_NONBLOCK); - mutex_lock(&s->open_sem_adc); - stop_adc(s); - dealloc_dmabuf(s, &s->dma_adc); - s->open_mode &= ~FMODE_READ; - mutex_unlock(&s->open_sem_adc); - wake_up(&s->open_wait_adc); - } - return 0; -} - -static int cs4297a_locked_open(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - struct cs4297a_state *s=NULL; - struct list_head *entry; - - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO - "cs4297a: cs4297a_open(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n", - (unsigned) inode, (unsigned) file, file->f_mode)); - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO - "cs4297a: status = %08x\n", (int)__raw_readq(SS_CSR(R_SER_STATUS_DEBUG)))); - - list_for_each(entry, &cs4297a_devs) - { - s = list_entry(entry, struct cs4297a_state, list); - - if (!((s->dev_audio ^ minor) & ~0xf)) - break; - } - if (entry == &cs4297a_devs) - return -ENODEV; - if (!s) { - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO - "cs4297a: cs4297a_open(): Error - unable to find audio state struct\n")); - return -ENODEV; - } - VALIDATE_STATE(s); - file->private_data = s; - - // wait for device to become free - if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) { - CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, printk(KERN_INFO - "cs4297a: cs4297a_open(): Error - must open READ and/or WRITE\n")); - return -ENODEV; - } - if (file->f_mode & FMODE_WRITE) { - if (__raw_readq(SS_CSR(R_SER_DMA_DSCR_COUNT_TX)) != 0) { - printk(KERN_ERR "cs4297a: TX pipe needs to drain\n"); - while (__raw_readq(SS_CSR(R_SER_DMA_DSCR_COUNT_TX))) - ; - } - - mutex_lock(&s->open_sem_dac); - while (s->open_mode & FMODE_WRITE) { - if (file->f_flags & O_NONBLOCK) { - mutex_unlock(&s->open_sem_dac); - return -EBUSY; - } - mutex_unlock(&s->open_sem_dac); - interruptible_sleep_on(&s->open_wait_dac); - - if (signal_pending(current)) { - printk("open - sig pending\n"); - return -ERESTARTSYS; - } - mutex_lock(&s->open_sem_dac); - } - } - if (file->f_mode & FMODE_READ) { - mutex_lock(&s->open_sem_adc); - while (s->open_mode & FMODE_READ) { - if (file->f_flags & O_NONBLOCK) { - mutex_unlock(&s->open_sem_adc); - return -EBUSY; - } - mutex_unlock(&s->open_sem_adc); - interruptible_sleep_on(&s->open_wait_adc); - - if (signal_pending(current)) { - printk("open - sig pending\n"); - return -ERESTARTSYS; - } - mutex_lock(&s->open_sem_adc); - } - } - s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - if (file->f_mode & FMODE_READ) { - s->prop_adc.fmt = AFMT_S16_BE; - s->prop_adc.fmt_original = s->prop_adc.fmt; - s->prop_adc.channels = 2; - s->prop_adc.rate = 48000; - s->conversion = 0; - s->ena &= ~FMODE_READ; - s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = - s->dma_adc.subdivision = 0; - mutex_unlock(&s->open_sem_adc); - - if (prog_dmabuf_adc(s)) { - CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR - "cs4297a: adc Program dmabufs failed.\n")); - cs4297a_release(inode, file); - return -ENOMEM; - } - } - if (file->f_mode & FMODE_WRITE) { - s->prop_dac.fmt = AFMT_S16_BE; - s->prop_dac.fmt_original = s->prop_dac.fmt; - s->prop_dac.channels = 2; - s->prop_dac.rate = 48000; - s->conversion = 0; - s->ena &= ~FMODE_WRITE; - s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = - s->dma_dac.subdivision = 0; - mutex_unlock(&s->open_sem_dac); - - if (prog_dmabuf_dac(s)) { - CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR - "cs4297a: dac Program dmabufs failed.\n")); - cs4297a_release(inode, file); - return -ENOMEM; - } - } - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, - printk(KERN_INFO "cs4297a: cs4297a_open()- 0\n")); - return nonseekable_open(inode, file); -} - -static int cs4297a_open(struct inode *inode, struct file *file) -{ - int ret; - - mutex_lock(&swarm_cs4297a_mutex); - ret = cs4297a_open(inode, file); - mutex_unlock(&swarm_cs4297a_mutex); - - return ret; -} - -// ****************************************************************************************** -// Wave (audio) file operations struct. -// ****************************************************************************************** -static const struct file_operations cs4297a_audio_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = cs4297a_read, - .write = cs4297a_write, - .poll = cs4297a_poll, - .unlocked_ioctl = cs4297a_unlocked_ioctl, - .mmap = cs4297a_mmap, - .open = cs4297a_open, - .release = cs4297a_release, -}; - -static void cs4297a_interrupt(int irq, void *dev_id) -{ - struct cs4297a_state *s = (struct cs4297a_state *) dev_id; - u32 status; - - status = __raw_readq(SS_CSR(R_SER_STATUS_DEBUG)); - - CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO - "cs4297a: cs4297a_interrupt() HISR=0x%.8x\n", status)); - -#if 0 - /* XXXKW what check *should* be done here? */ - if (!(status & (M_SYNCSER_RX_EOP_COUNT | M_SYNCSER_RX_OVERRUN | M_SYNCSER_RX_SYNC_ERR))) { - status = __raw_readq(SS_CSR(R_SER_STATUS)); - printk(KERN_ERR "cs4297a: unexpected interrupt (status %08x)\n", status); - return; - } -#endif - - if (status & M_SYNCSER_RX_SYNC_ERR) { - status = __raw_readq(SS_CSR(R_SER_STATUS)); - printk(KERN_ERR "cs4297a: rx sync error (status %08x)\n", status); - return; - } - - if (status & M_SYNCSER_RX_OVERRUN) { - int newptr, i; - s->stats.rx_ovrrn++; - printk(KERN_ERR "cs4297a: receive FIFO overrun\n"); - - /* Fix things up: get the receive descriptor pool - clean and give them back to the hardware */ - while (__raw_readq(SS_CSR(R_SER_DMA_DSCR_COUNT_RX))) - ; - newptr = (unsigned) (((__raw_readq(SS_CSR(R_SER_DMA_CUR_DSCR_ADDR_RX)) & M_DMA_CURDSCR_ADDR) - - s->dma_adc.descrtab_phys) / sizeof(serdma_descr_t)); - for (i=0; idma_adc.descrtab[i].descr_a &= ~M_DMA_SERRX_SOP; - } - s->dma_adc.swptr = s->dma_adc.hwptr = newptr; - s->dma_adc.count = 0; - s->dma_adc.sb_swptr = s->dma_adc.sb_hwptr = s->dma_adc.sample_buf; - __raw_writeq(DMA_DESCR, SS_CSR(R_SER_DMA_DSCR_COUNT_RX)); - } - - spin_lock(&s->lock); - cs4297a_update_ptr(s,CS_TRUE); - spin_unlock(&s->lock); - - CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO - "cs4297a: cs4297a_interrupt()-\n")); -} - -#if 0 -static struct initvol { - int mixch; - int vol; -} initvol[] __initdata = { - - {SOUND_MIXER_WRITE_VOLUME, 0x4040}, - {SOUND_MIXER_WRITE_PCM, 0x4040}, - {SOUND_MIXER_WRITE_SYNTH, 0x4040}, - {SOUND_MIXER_WRITE_CD, 0x4040}, - {SOUND_MIXER_WRITE_LINE, 0x4040}, - {SOUND_MIXER_WRITE_LINE1, 0x4040}, - {SOUND_MIXER_WRITE_RECLEV, 0x0000}, - {SOUND_MIXER_WRITE_SPEAKER, 0x4040}, - {SOUND_MIXER_WRITE_MIC, 0x0000} -}; -#endif - -static int __init cs4297a_init(void) -{ - struct cs4297a_state *s; - u32 pwr, id; - mm_segment_t fs; - int rval; -#ifndef CONFIG_BCM_CS4297A_CSWARM - u64 cfg; - int mdio_val; -#endif - - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO - "cs4297a: cs4297a_init_module()+ \n")); - -#ifndef CONFIG_BCM_CS4297A_CSWARM - mdio_val = __raw_readq(KSEG1 + A_MAC_REGISTER(2, R_MAC_MDIO)) & - (M_MAC_MDIO_DIR|M_MAC_MDIO_OUT); - - /* Check syscfg for synchronous serial on port 1 */ - cfg = __raw_readq(KSEG1 + A_SCD_SYSTEM_CFG); - if (!(cfg & M_SYS_SER1_ENABLE)) { - __raw_writeq(cfg | M_SYS_SER1_ENABLE, KSEG1+A_SCD_SYSTEM_CFG); - cfg = __raw_readq(KSEG1 + A_SCD_SYSTEM_CFG); - if (!(cfg & M_SYS_SER1_ENABLE)) { - printk(KERN_INFO "cs4297a: serial port 1 not configured for synchronous operation\n"); - return -1; - } - - printk(KERN_INFO "cs4297a: serial port 1 switching to synchronous operation\n"); - - /* Force the codec (on SWARM) to reset by clearing - GENO, preserving MDIO (no effect on CSWARM) */ - __raw_writeq(mdio_val, KSEG1+A_MAC_REGISTER(2, R_MAC_MDIO)); - udelay(10); - } - - /* Now set GENO */ - __raw_writeq(mdio_val | M_MAC_GENC, KSEG1+A_MAC_REGISTER(2, R_MAC_MDIO)); - /* Give the codec some time to finish resetting (start the bit clock) */ - udelay(100); -#endif - - if (!(s = kzalloc(sizeof(struct cs4297a_state), GFP_KERNEL))) { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR - "cs4297a: probe() no memory for state struct.\n")); - return -1; - } - s->magic = CS4297a_MAGIC; - init_waitqueue_head(&s->dma_adc.wait); - init_waitqueue_head(&s->dma_dac.wait); - init_waitqueue_head(&s->dma_adc.reg_wait); - init_waitqueue_head(&s->dma_dac.reg_wait); - init_waitqueue_head(&s->open_wait); - init_waitqueue_head(&s->open_wait_adc); - init_waitqueue_head(&s->open_wait_dac); - mutex_init(&s->open_sem_adc); - mutex_init(&s->open_sem_dac); - spin_lock_init(&s->lock); - - s->irq = K_INT_SER_1; - - if (request_irq - (s->irq, cs4297a_interrupt, 0, "Crystal CS4297a", s)) { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4297a: irq %u in use\n", s->irq)); - goto err_irq; - } - if ((s->dev_audio = register_sound_dsp(&cs4297a_audio_fops, -1)) < - 0) { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR - "cs4297a: probe() register_sound_dsp() failed.\n")); - goto err_dev1; - } - if ((s->dev_mixer = register_sound_mixer(&cs4297a_mixer_fops, -1)) < - 0) { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR - "cs4297a: probe() register_sound_mixer() failed.\n")); - goto err_dev2; - } - - if (ser_init(s) || dma_init(s)) { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR - "cs4297a: ser_init failed.\n")); - goto err_dev3; - } - - do { - udelay(4000); - rval = cs4297a_read_ac97(s, AC97_POWER_CONTROL, &pwr); - } while (!rval && (pwr != 0xf)); - - if (!rval) { - char *sb1250_duart_present; - - fs = get_fs(); - set_fs(KERNEL_DS); -#if 0 - val = SOUND_MASK_LINE; - mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val); - for (i = 0; i < ARRAY_SIZE(initvol); i++) { - val = initvol[i].vol; - mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val); - } -// cs4297a_write_ac97(s, 0x18, 0x0808); -#else - // cs4297a_write_ac97(s, 0x5e, 0x180); - cs4297a_write_ac97(s, 0x02, 0x0808); - cs4297a_write_ac97(s, 0x18, 0x0808); -#endif - set_fs(fs); - - list_add(&s->list, &cs4297a_devs); - - cs4297a_read_ac97(s, AC97_VENDOR_ID1, &id); - - sb1250_duart_present = symbol_get(sb1250_duart_present); - if (sb1250_duart_present) - sb1250_duart_present[1] = 0; - - printk(KERN_INFO "cs4297a: initialized (vendor id = %x)\n", id); - - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4297a: cs4297a_init_module()-\n")); - - return 0; - } - - err_dev3: - unregister_sound_mixer(s->dev_mixer); - err_dev2: - unregister_sound_dsp(s->dev_audio); - err_dev1: - free_irq(s->irq, s); - err_irq: - kfree(s); - - printk(KERN_INFO "cs4297a: initialization failed\n"); - - return -1; -} - -static void __exit cs4297a_cleanup(void) -{ - /* - XXXKW - disable_irq, free_irq - drain DMA queue - disable DMA - disable TX/RX - free memory - */ - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4297a: cleanup_cs4297a() finished\n")); -} - -// --------------------------------------------------------------------- - -MODULE_AUTHOR("Kip Walker, Broadcom Corp."); -MODULE_DESCRIPTION("Cirrus Logic CS4297a Driver for Broadcom SWARM board"); - -// --------------------------------------------------------------------- - -module_init(cs4297a_init); -module_exit(cs4297a_cleanup); diff --git a/ANDROID_3.4.5/sound/oss/sys_timer.c b/ANDROID_3.4.5/sound/oss/sys_timer.c deleted file mode 100644 index 8db6aefe..00000000 --- a/ANDROID_3.4.5/sound/oss/sys_timer.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * sound/oss/sys_timer.c - * - * The default timer for the Level 2 sequencer interface - * Uses the (1/HZ sec) timer of kernel. - */ -/* - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ -/* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * Andrew Veliath : adapted tmr2ticks from level 1 sequencer (avoid overflow) - */ -#include -#include "sound_config.h" - -static volatile int opened, tmr_running; -static volatile time_t tmr_offs, tmr_ctr; -static volatile unsigned long ticks_offs; -static volatile int curr_tempo, curr_timebase; -static volatile unsigned long curr_ticks; -static volatile unsigned long next_event_time; -static unsigned long prev_event_time; - -static void poll_def_tmr(unsigned long dummy); -static DEFINE_SPINLOCK(lock); -static DEFINE_TIMER(def_tmr, poll_def_tmr, 0, 0); - -static unsigned long -tmr2ticks(int tmr_value) -{ - /* - * Convert timer ticks to MIDI ticks - */ - - unsigned long tmp; - unsigned long scale; - - /* tmr_value (ticks per sec) * - 1000000 (usecs per sec) / HZ (ticks per sec) -=> usecs */ - tmp = tmr_value * (1000000 / HZ); - scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */ - return (tmp + scale / 2) / scale; -} - -static void -poll_def_tmr(unsigned long dummy) -{ - - if (opened) - { - - { - def_tmr.expires = (1) + jiffies; - add_timer(&def_tmr); - }; - - if (tmr_running) - { - spin_lock(&lock); - tmr_ctr++; - curr_ticks = ticks_offs + tmr2ticks(tmr_ctr); - - if (curr_ticks >= next_event_time) - { - next_event_time = (unsigned long) -1; - sequencer_timer(0); - } - spin_unlock(&lock); - } - } -} - -static void -tmr_reset(void) -{ - unsigned long flags; - - spin_lock_irqsave(&lock,flags); - tmr_offs = 0; - ticks_offs = 0; - tmr_ctr = 0; - next_event_time = (unsigned long) -1; - prev_event_time = 0; - curr_ticks = 0; - spin_unlock_irqrestore(&lock,flags); -} - -static int -def_tmr_open(int dev, int mode) -{ - if (opened) - return -EBUSY; - - tmr_reset(); - curr_tempo = 60; - curr_timebase = 100; - opened = 1; - { - def_tmr.expires = (1) + jiffies; - add_timer(&def_tmr); - }; - - return 0; -} - -static void -def_tmr_close(int dev) -{ - opened = tmr_running = 0; - del_timer(&def_tmr); -} - -static int -def_tmr_event(int dev, unsigned char *event) -{ - unsigned char cmd = event[1]; - unsigned long parm = *(int *) &event[4]; - - switch (cmd) - { - case TMR_WAIT_REL: - parm += prev_event_time; - case TMR_WAIT_ABS: - if (parm > 0) - { - long time; - - if (parm <= curr_ticks) /* It's the time */ - return TIMER_NOT_ARMED; - - time = parm; - next_event_time = prev_event_time = time; - - return TIMER_ARMED; - } - break; - - case TMR_START: - tmr_reset(); - tmr_running = 1; - break; - - case TMR_STOP: - tmr_running = 0; - break; - - case TMR_CONTINUE: - tmr_running = 1; - break; - - case TMR_TEMPO: - if (parm) - { - if (parm < 8) - parm = 8; - if (parm > 360) - parm = 360; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks(tmr_ctr); - tmr_ctr = 0; - curr_tempo = parm; - } - break; - - case TMR_ECHO: - seq_copy_to_input(event, 8); - break; - - default:; - } - - return TIMER_NOT_ARMED; -} - -static unsigned long -def_tmr_get_time(int dev) -{ - if (!opened) - return 0; - - return curr_ticks; -} - -/* same as sound_timer.c:timer_ioctl!? */ -static int def_tmr_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - int __user *p = arg; - int val; - - switch (cmd) { - case SNDCTL_TMR_SOURCE: - return __put_user(TMR_INTERNAL, p); - - case SNDCTL_TMR_START: - tmr_reset(); - tmr_running = 1; - return 0; - - case SNDCTL_TMR_STOP: - tmr_running = 0; - return 0; - - case SNDCTL_TMR_CONTINUE: - tmr_running = 1; - return 0; - - case SNDCTL_TMR_TIMEBASE: - if (__get_user(val, p)) - return -EFAULT; - if (val) { - if (val < 1) - val = 1; - if (val > 1000) - val = 1000; - curr_timebase = val; - } - return __put_user(curr_timebase, p); - - case SNDCTL_TMR_TEMPO: - if (__get_user(val, p)) - return -EFAULT; - if (val) { - if (val < 8) - val = 8; - if (val > 250) - val = 250; - tmr_offs = tmr_ctr; - ticks_offs += tmr2ticks(tmr_ctr); - tmr_ctr = 0; - curr_tempo = val; - reprogram_timer(); - } - return __put_user(curr_tempo, p); - - case SNDCTL_SEQ_CTRLRATE: - if (__get_user(val, p)) - return -EFAULT; - if (val != 0) /* Can't change */ - return -EINVAL; - val = ((curr_tempo * curr_timebase) + 30) / 60; - return __put_user(val, p); - - case SNDCTL_SEQ_GETTIME: - return __put_user(curr_ticks, p); - - case SNDCTL_TMR_METRONOME: - /* NOP */ - break; - - default:; - } - return -EINVAL; -} - -static void -def_tmr_arm(int dev, long time) -{ - if (time < 0) - time = curr_ticks + 1; - else if (time <= curr_ticks) /* It's the time */ - return; - - next_event_time = prev_event_time = time; - - return; -} - -struct sound_timer_operations default_sound_timer = -{ - .owner = THIS_MODULE, - .info = {"System clock", 0}, - .priority = 0, /* Priority */ - .devlink = 0, /* Local device link */ - .open = def_tmr_open, - .close = def_tmr_close, - .event = def_tmr_event, - .get_time = def_tmr_get_time, - .ioctl = def_tmr_ioctl, - .arm_timer = def_tmr_arm -}; diff --git a/ANDROID_3.4.5/sound/oss/trix.c b/ANDROID_3.4.5/sound/oss/trix.c deleted file mode 100644 index 944e0c01..00000000 --- a/ANDROID_3.4.5/sound/oss/trix.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * sound/oss/trix.c - * - * Low level driver for the MediaTrix AudioTrix Pro - * (MT-0002-PC Control Chip) - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * Changes - * Alan Cox Modularisation, cleanup. - * Christoph Hellwig Adapted to module_init/module_exit - * Arnaldo C. de Melo Got rid of attach_uart401 - */ - -#include -#include - -#include "sound_config.h" -#include "sb.h" -#include "sound_firmware.h" - -#include "ad1848.h" -#include "mpu401.h" - -#include "trix_boot.h" - -static int mpu; - -static bool joystick; - -static unsigned char trix_read(int addr) -{ - outb(((unsigned char) addr), 0x390); /* MT-0002-PC ASIC address */ - return inb(0x391); /* MT-0002-PC ASIC data */ -} - -static void trix_write(int addr, int data) -{ - outb(((unsigned char) addr), 0x390); /* MT-0002-PC ASIC address */ - outb(((unsigned char) data), 0x391); /* MT-0002-PC ASIC data */ -} - -static void download_boot(int base) -{ - int i = 0, n = trix_boot_len; - - if (trix_boot_len == 0) - return; - - trix_write(0xf8, 0x00); /* ??????? */ - outb((0x01), base + 6); /* Clear the internal data pointer */ - outb((0x00), base + 6); /* Restart */ - - /* - * Write the boot code to the RAM upload/download register. - * Each write increments the internal data pointer. - */ - outb((0x01), base + 6); /* Clear the internal data pointer */ - outb((0x1A), 0x390); /* Select RAM download/upload port */ - - for (i = 0; i < n; i++) - outb((trix_boot[i]), 0x391); - for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */ - outb((0x00), 0x391); - outb((0x00), base + 6); /* Reset */ - outb((0x50), 0x390); /* ?????? */ - -} - -static int trix_set_wss_port(struct address_info *hw_config) -{ - unsigned char addr_bits; - - if (trix_read(0x15) != 0x71) /* No ASIC signature */ - { - MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n")); - return 0; - } - - /* - * Reset some registers. - */ - - trix_write(0x13, 0); - trix_write(0x14, 0); - - /* - * Configure the ASIC to place the codec to the proper I/O location - */ - - switch (hw_config->io_base) - { - case 0x530: - addr_bits = 0; - break; - case 0x604: - addr_bits = 1; - break; - case 0xE80: - addr_bits = 2; - break; - case 0xF40: - addr_bits = 3; - break; - default: - return 0; - } - - trix_write(0x19, (trix_read(0x19) & 0x03) | addr_bits); - return 1; -} - -/* - * Probe and attach routines for the Windows Sound System mode of - * AudioTrix Pro - */ - -static int __init init_trix_wss(struct address_info *hw_config) -{ - static unsigned char dma_bits[4] = { - 1, 2, 0, 3 - }; - struct resource *ports; - int config_port = hw_config->io_base + 0; - int dma1 = hw_config->dma, dma2 = hw_config->dma2; - int old_num_mixers = num_mixers; - u8 config, bits; - int ret; - - switch(hw_config->irq) { - case 7: - bits = 8; - break; - case 9: - bits = 0x10; - break; - case 10: - bits = 0x18; - break; - case 11: - bits = 0x20; - break; - default: - printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq); - return 0; - } - - switch (dma1) { - case 0: - case 1: - case 3: - break; - default: - printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", dma1); - return 0; - } - - switch (dma2) { - case -1: - case 0: - case 1: - case 3: - break; - default: - printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", dma2); - return 0; - } - - /* - * Check if the IO port returns valid signature. The original MS Sound - * system returns 0x04 while some cards (AudioTrix Pro for example) - * return 0x00. - */ - ports = request_region(hw_config->io_base + 4, 4, "ad1848"); - if (!ports) { - printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base); - return 0; - } - - if (!request_region(hw_config->io_base, 4, "MSS config")) { - printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base); - release_region(hw_config->io_base + 4, 4); - return 0; - } - - if (!trix_set_wss_port(hw_config)) - goto fail; - - config = inb(hw_config->io_base + 3); - - if ((config & 0x3f) != 0x00) - { - MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base)); - goto fail; - } - - /* - * Check that DMA0 is not in use with a 8 bit board. - */ - - if (dma1 == 0 && config & 0x80) - { - printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n"); - goto fail; - } - if (hw_config->irq > 9 && config & 0x80) - { - printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq); - goto fail; - } - - ret = ad1848_detect(ports, NULL, hw_config->osp); - if (!ret) - goto fail; - - if (joystick==1) - trix_write(0x15, 0x80); - - /* - * Set the IRQ and DMA addresses. - */ - - outb((bits | 0x40), config_port); - - if (dma2 == -1 || dma2 == dma1) - { - bits |= dma_bits[dma1]; - dma2 = dma1; - } - else - { - unsigned char tmp; - - tmp = trix_read(0x13) & ~30; - trix_write(0x13, tmp | 0x80 | (dma1 << 4)); - - tmp = trix_read(0x14) & ~30; - trix_write(0x14, tmp | 0x80 | (dma2 << 4)); - } - - outb((bits), config_port); /* Write IRQ+DMA setup */ - - hw_config->slots[0] = ad1848_init("AudioTrix Pro", ports, - hw_config->irq, - dma1, - dma2, - 0, - hw_config->osp, - THIS_MODULE); - - if (num_mixers > old_num_mixers) /* Mixer got installed */ - { - AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE); /* Line in */ - AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD); - AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH); /* OPL4 */ - AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM); /* SB */ - } - return 1; - -fail: - release_region(hw_config->io_base, 4); - release_region(hw_config->io_base + 4, 4); - return 0; -} - -static int __init probe_trix_sb(struct address_info *hw_config) -{ - - int tmp; - unsigned char conf; - extern int sb_be_quiet; - int old_quiet; - static signed char irq_translate[] = { - -1, -1, -1, 0, 1, 2, -1, 3 - }; - - if (trix_boot_len == 0) - return 0; /* No boot code -> no fun */ - - if ((hw_config->io_base & 0xffffff8f) != 0x200) - return 0; - - tmp = hw_config->irq; - if (tmp > 7) - return 0; - if (irq_translate[tmp] == -1) - return 0; - - tmp = hw_config->dma; - if (tmp != 1 && tmp != 3) - return 0; - - if (!request_region(hw_config->io_base, 16, "soundblaster")) { - printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base); - return 0; - } - - conf = 0x84; /* DMA and IRQ enable */ - conf |= hw_config->io_base & 0x70; /* I/O address bits */ - conf |= irq_translate[hw_config->irq]; - if (hw_config->dma == 3) - conf |= 0x08; - trix_write(0x1b, conf); - - download_boot(hw_config->io_base); - - hw_config->name = "AudioTrix SB"; - if (!sb_dsp_detect(hw_config, 0, 0, NULL)) { - release_region(hw_config->io_base, 16); - return 0; - } - - hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING; - - /* Prevent false alarms */ - old_quiet = sb_be_quiet; - sb_be_quiet = 1; - - sb_dsp_init(hw_config, THIS_MODULE); - - sb_be_quiet = old_quiet; - return 1; -} - -static int __init probe_trix_mpu(struct address_info *hw_config) -{ - unsigned char conf; - static int irq_bits[] = { - -1, -1, -1, 1, 2, 3, -1, 4, -1, 5 - }; - - if (hw_config->irq > 9) - { - printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq); - return 0; - } - if (irq_bits[hw_config->irq] == -1) - { - printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq); - return 0; - } - switch (hw_config->io_base) - { - case 0x330: - conf = 0x00; - break; - case 0x370: - conf = 0x04; - break; - case 0x3b0: - conf = 0x08; - break; - case 0x3f0: - conf = 0x0c; - break; - default: - return 0; /* Invalid port */ - } - - conf |= irq_bits[hw_config->irq] << 4; - trix_write(0x19, (trix_read(0x19) & 0x83) | conf); - hw_config->name = "AudioTrix Pro"; - return probe_uart401(hw_config, THIS_MODULE); -} - -static void __exit unload_trix_wss(struct address_info *hw_config) -{ - int dma2 = hw_config->dma2; - - if (dma2 == -1) - dma2 = hw_config->dma; - - release_region(0x390, 2); - release_region(hw_config->io_base, 4); - - ad1848_unload(hw_config->io_base + 4, - hw_config->irq, - hw_config->dma, - dma2, - 0); - sound_unload_audiodev(hw_config->slots[0]); -} - -static inline void __exit unload_trix_mpu(struct address_info *hw_config) -{ - unload_uart401(hw_config); -} - -static inline void __exit unload_trix_sb(struct address_info *hw_config) -{ - sb_dsp_unload(hw_config, mpu); -} - -static struct address_info cfg; -static struct address_info cfg2; -static struct address_info cfg_mpu; - -static int sb; -static int fw_load; - -static int __initdata io = -1; -static int __initdata irq = -1; -static int __initdata dma = -1; -static int __initdata dma2 = -1; /* Set this for modules that need it */ -static int __initdata sb_io = -1; -static int __initdata sb_dma = -1; -static int __initdata sb_irq = -1; -static int __initdata mpu_io = -1; -static int __initdata mpu_irq = -1; - -module_param(io, int, 0); -module_param(irq, int, 0); -module_param(dma, int, 0); -module_param(dma2, int, 0); -module_param(sb_io, int, 0); -module_param(sb_dma, int, 0); -module_param(sb_irq, int, 0); -module_param(mpu_io, int, 0); -module_param(mpu_irq, int, 0); -module_param(joystick, bool, 0); - -static int __init init_trix(void) -{ - printk(KERN_INFO "MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); - - cfg.io_base = io; - cfg.irq = irq; - cfg.dma = dma; - cfg.dma2 = dma2; - - cfg2.io_base = sb_io; - cfg2.irq = sb_irq; - cfg2.dma = sb_dma; - - cfg_mpu.io_base = mpu_io; - cfg_mpu.irq = mpu_irq; - - if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) { - printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n"); - return -EINVAL; - } - - if (cfg2.io_base != -1 && (cfg2.irq == -1 || cfg2.dma == -1)) { - printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.\n"); - return -EINVAL; - } - if (cfg_mpu.io_base != -1 && cfg_mpu.irq == -1) { - printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n"); - return -EINVAL; - } - if (!trix_boot) - { - fw_load = 1; - trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin", - (char **) &trix_boot); - } - - if (!request_region(0x390, 2, "AudioTrix")) { - printk(KERN_ERR "AudioTrix: Config port I/O conflict\n"); - return -ENODEV; - } - - if (!init_trix_wss(&cfg)) { - release_region(0x390, 2); - return -ENODEV; - } - - /* - * We must attach in the right order to get the firmware - * loaded up in time. - */ - - if (cfg2.io_base != -1) { - sb = probe_trix_sb(&cfg2); - } - - if (cfg_mpu.io_base != -1) - mpu = probe_trix_mpu(&cfg_mpu); - - return 0; -} - -static void __exit cleanup_trix(void) -{ - if (fw_load && trix_boot) - vfree(trix_boot); - if (sb) - unload_trix_sb(&cfg2); - if (mpu) - unload_trix_mpu(&cfg_mpu); - unload_trix_wss(&cfg); -} - -module_init(init_trix); -module_exit(cleanup_trix); - -#ifndef MODULE -static int __init setup_trix (char *str) -{ - /* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, mpu_io, mpu_irq */ - int ints[9]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - irq = ints[2]; - dma = ints[3]; - dma2 = ints[4]; - sb_io = ints[5]; - sb_irq = ints[6]; - sb_dma = ints[6]; - mpu_io = ints[7]; - mpu_irq = ints[8]; - - return 1; -} - -__setup("trix=", setup_trix); -#endif -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/tuning.h b/ANDROID_3.4.5/sound/oss/tuning.h deleted file mode 100644 index a73e3dd3..00000000 --- a/ANDROID_3.4.5/sound/oss/tuning.h +++ /dev/null @@ -1,23 +0,0 @@ -static unsigned short semitone_tuning[24] = -{ -/* 0 */ 10000, 10595, 11225, 11892, 12599, 13348, 14142, 14983, -/* 8 */ 15874, 16818, 17818, 18877, 20000, 21189, 22449, 23784, -/* 16 */ 25198, 26697, 28284, 29966, 31748, 33636, 35636, 37755 -}; - -static unsigned short cent_tuning[100] = -{ -/* 0 */ 10000, 10006, 10012, 10017, 10023, 10029, 10035, 10041, -/* 8 */ 10046, 10052, 10058, 10064, 10070, 10075, 10081, 10087, -/* 16 */ 10093, 10099, 10105, 10110, 10116, 10122, 10128, 10134, -/* 24 */ 10140, 10145, 10151, 10157, 10163, 10169, 10175, 10181, -/* 32 */ 10187, 10192, 10198, 10204, 10210, 10216, 10222, 10228, -/* 40 */ 10234, 10240, 10246, 10251, 10257, 10263, 10269, 10275, -/* 48 */ 10281, 10287, 10293, 10299, 10305, 10311, 10317, 10323, -/* 56 */ 10329, 10335, 10341, 10347, 10353, 10359, 10365, 10371, -/* 64 */ 10377, 10383, 10389, 10395, 10401, 10407, 10413, 10419, -/* 72 */ 10425, 10431, 10437, 10443, 10449, 10455, 10461, 10467, -/* 80 */ 10473, 10479, 10485, 10491, 10497, 10503, 10509, 10515, -/* 88 */ 10521, 10528, 10534, 10540, 10546, 10552, 10558, 10564, -/* 96 */ 10570, 10576, 10582, 10589 -}; diff --git a/ANDROID_3.4.5/sound/oss/uart401.c b/ANDROID_3.4.5/sound/oss/uart401.c deleted file mode 100644 index 8e514a67..00000000 --- a/ANDROID_3.4.5/sound/oss/uart401.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * sound/oss/uart401.c - * - * MPU-401 UART driver (formerly uart401_midi.c) - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * Changes: - * Alan Cox Reformatted, removed sound_mem usage, use normal Linux - * interrupt allocation. Protect against bogus unload - * Fixed to allow IRQ > 15 - * Christoph Hellwig Adapted to module_init/module_exit - * Arnaldo C. de Melo got rid of check_region - * - * Status: - * Untested - */ - -#include -#include -#include -#include -#include -#include "sound_config.h" - -#include "mpu401.h" - -typedef struct uart401_devc -{ - int base; - int irq; - int *osp; - void (*midi_input_intr) (int dev, unsigned char data); - int opened, disabled; - volatile unsigned char input_byte; - int my_dev; - int share_irq; - spinlock_t lock; -} -uart401_devc; - -#define DATAPORT (devc->base) -#define COMDPORT (devc->base+1) -#define STATPORT (devc->base+1) - -static int uart401_status(uart401_devc * devc) -{ - return inb(STATPORT); -} - -#define input_avail(devc) (!(uart401_status(devc)&INPUT_AVAIL)) -#define output_ready(devc) (!(uart401_status(devc)&OUTPUT_READY)) - -static void uart401_cmd(uart401_devc * devc, unsigned char cmd) -{ - outb((cmd), COMDPORT); -} - -static int uart401_read(uart401_devc * devc) -{ - return inb(DATAPORT); -} - -static void uart401_write(uart401_devc * devc, unsigned char byte) -{ - outb((byte), DATAPORT); -} - -#define OUTPUT_READY 0x40 -#define INPUT_AVAIL 0x80 -#define MPU_ACK 0xFE -#define MPU_RESET 0xFF -#define UART_MODE_ON 0x3F - -static int reset_uart401(uart401_devc * devc); -static void enter_uart_mode(uart401_devc * devc); - -static void uart401_input_loop(uart401_devc * devc) -{ - int work_limit=30000; - - while (input_avail(devc) && --work_limit) - { - unsigned char c = uart401_read(devc); - - if (c == MPU_ACK) - devc->input_byte = c; - else if (devc->opened & OPEN_READ && devc->midi_input_intr) - devc->midi_input_intr(devc->my_dev, c); - } - if(work_limit==0) - printk(KERN_WARNING "Too much work in interrupt on uart401 (0x%X). UART jabbering ??\n", devc->base); -} - -irqreturn_t uart401intr(int irq, void *dev_id) -{ - uart401_devc *devc = dev_id; - - if (devc == NULL) - { - printk(KERN_ERR "uart401: bad devc\n"); - return IRQ_NONE; - } - - if (input_avail(devc)) - uart401_input_loop(devc); - return IRQ_HANDLED; -} - -static int -uart401_open(int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; - - if (devc->opened) - return -EBUSY; - - /* Flush the UART */ - - while (input_avail(devc)) - uart401_read(devc); - - devc->midi_input_intr = input; - devc->opened = mode; - enter_uart_mode(devc); - devc->disabled = 0; - - return 0; -} - -static void uart401_close(int dev) -{ - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; - - reset_uart401(devc); - devc->opened = 0; -} - -static int uart401_out(int dev, unsigned char midi_byte) -{ - int timeout; - unsigned long flags; - uart401_devc *devc = (uart401_devc *) midi_devs[dev]->devc; - - if (devc->disabled) - return 1; - /* - * Test for input since pending input seems to block the output. - */ - - spin_lock_irqsave(&devc->lock,flags); - if (input_avail(devc)) - uart401_input_loop(devc); - - spin_unlock_irqrestore(&devc->lock,flags); - - /* - * Sometimes it takes about 13000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); - - if (!output_ready(devc)) - { - printk(KERN_WARNING "uart401: Timeout - Device not responding\n"); - devc->disabled = 1; - reset_uart401(devc); - enter_uart_mode(devc); - return 1; - } - uart401_write(devc, midi_byte); - return 1; -} - -static inline int uart401_start_read(int dev) -{ - return 0; -} - -static inline int uart401_end_read(int dev) -{ - return 0; -} - -static inline void uart401_kick(int dev) -{ -} - -static inline int uart401_buffer_status(int dev) -{ - return 0; -} - -#define MIDI_SYNTH_NAME "MPU-401 UART" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include "midi_synth.h" - -static const struct midi_operations uart401_operations = -{ - .owner = THIS_MODULE, - .info = {"MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401}, - .converter = &std_midi_synth, - .in_info = {0}, - .open = uart401_open, - .close = uart401_close, - .outputc = uart401_out, - .start_read = uart401_start_read, - .end_read = uart401_end_read, - .kick = uart401_kick, - .buffer_status = uart401_buffer_status, -}; - -static void enter_uart_mode(uart401_devc * devc) -{ - int ok, timeout; - unsigned long flags; - - spin_lock_irqsave(&devc->lock,flags); - for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); - - devc->input_byte = 0; - uart401_cmd(devc, UART_MODE_ON); - - ok = 0; - for (timeout = 50000; timeout > 0 && !ok; timeout--) - if (devc->input_byte == MPU_ACK) - ok = 1; - else if (input_avail(devc)) - if (uart401_read(devc) == MPU_ACK) - ok = 1; - - spin_unlock_irqrestore(&devc->lock,flags); -} - -static int reset_uart401(uart401_devc * devc) -{ - int ok, timeout, n; - - /* - * Send the RESET command. Try again if no success at the first time. - */ - - ok = 0; - - for (n = 0; n < 2 && !ok; n++) - { - for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); - devc->input_byte = 0; - uart401_cmd(devc, MPU_RESET); - - /* - * Wait at least 25 msec. This method is not accurate so let's make the - * loop bit longer. Cannot sleep since this is called during boot. - */ - - for (timeout = 50000; timeout > 0 && !ok; timeout--) - { - if (devc->input_byte == MPU_ACK) /* Interrupt */ - ok = 1; - else if (input_avail(devc)) - { - if (uart401_read(devc) == MPU_ACK) - ok = 1; - } - } - } - - - if (ok) - { - DEB(printk("Reset UART401 OK\n")); - } - else - DDB(printk("Reset UART401 failed - No hardware detected.\n")); - - if (ok) - uart401_input_loop(devc); /* - * Flush input before enabling interrupts - */ - - return ok; -} - -int probe_uart401(struct address_info *hw_config, struct module *owner) -{ - uart401_devc *devc; - char *name = "MPU-401 (UART) MIDI"; - int ok = 0; - unsigned long flags; - - DDB(printk("Entered probe_uart401()\n")); - - /* Default to "not found" */ - hw_config->slots[4] = -1; - - if (!request_region(hw_config->io_base, 4, "MPU-401 UART")) { - printk(KERN_INFO "uart401: could not request_region(%d, 4)\n", hw_config->io_base); - return 0; - } - - devc = kmalloc(sizeof(uart401_devc), GFP_KERNEL); - if (!devc) { - printk(KERN_WARNING "uart401: Can't allocate memory\n"); - goto cleanup_region; - } - - devc->base = hw_config->io_base; - devc->irq = hw_config->irq; - devc->osp = hw_config->osp; - devc->midi_input_intr = NULL; - devc->opened = 0; - devc->input_byte = 0; - devc->my_dev = 0; - devc->share_irq = 0; - spin_lock_init(&devc->lock); - - spin_lock_irqsave(&devc->lock,flags); - ok = reset_uart401(devc); - spin_unlock_irqrestore(&devc->lock,flags); - - if (!ok) - goto cleanup_devc; - - if (hw_config->name) - name = hw_config->name; - - if (devc->irq < 0) { - devc->share_irq = 1; - devc->irq *= -1; - } else - devc->share_irq = 0; - - if (!devc->share_irq) - if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0) { - printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq); - devc->share_irq = 1; - } - devc->my_dev = sound_alloc_mididev(); - enter_uart_mode(devc); - - if (devc->my_dev == -1) { - printk(KERN_INFO "uart401: Too many midi devices detected\n"); - goto cleanup_irq; - } - conf_printf(name, hw_config); - midi_devs[devc->my_dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL); - if (!midi_devs[devc->my_dev]) { - printk(KERN_ERR "uart401: Failed to allocate memory\n"); - goto cleanup_unload_mididev; - } - memcpy(midi_devs[devc->my_dev], &uart401_operations, sizeof(struct midi_operations)); - - if (owner) - midi_devs[devc->my_dev]->owner = owner; - - midi_devs[devc->my_dev]->devc = devc; - midi_devs[devc->my_dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL); - if (!midi_devs[devc->my_dev]->converter) { - printk(KERN_WARNING "uart401: Failed to allocate memory\n"); - goto cleanup_midi_devs; - } - memcpy(midi_devs[devc->my_dev]->converter, &std_midi_synth, sizeof(struct synth_operations)); - strcpy(midi_devs[devc->my_dev]->info.name, name); - midi_devs[devc->my_dev]->converter->id = "UART401"; - midi_devs[devc->my_dev]->converter->midi_dev = devc->my_dev; - - if (owner) - midi_devs[devc->my_dev]->converter->owner = owner; - - hw_config->slots[4] = devc->my_dev; - sequencer_init(); - devc->opened = 0; - return 1; -cleanup_midi_devs: - kfree(midi_devs[devc->my_dev]); -cleanup_unload_mididev: - sound_unload_mididev(devc->my_dev); -cleanup_irq: - if (!devc->share_irq) - free_irq(devc->irq, devc); -cleanup_devc: - kfree(devc); -cleanup_region: - release_region(hw_config->io_base, 4); - return 0; -} - -void unload_uart401(struct address_info *hw_config) -{ - uart401_devc *devc; - int n=hw_config->slots[4]; - - /* Not set up */ - if(n==-1 || midi_devs[n]==NULL) - return; - - /* Not allocated (erm ??) */ - - devc = midi_devs[hw_config->slots[4]]->devc; - if (devc == NULL) - return; - - reset_uart401(devc); - release_region(hw_config->io_base, 4); - - if (!devc->share_irq) - free_irq(devc->irq, devc); - if (devc) - { - kfree(midi_devs[devc->my_dev]->converter); - kfree(midi_devs[devc->my_dev]); - kfree(devc); - devc = NULL; - } - /* This kills midi_devs[x] */ - sound_unload_mididev(hw_config->slots[4]); -} - -EXPORT_SYMBOL(probe_uart401); -EXPORT_SYMBOL(unload_uart401); -EXPORT_SYMBOL(uart401intr); - -static struct address_info cfg_mpu; - -static int io = -1; -static int irq = -1; - -module_param(io, int, 0444); -module_param(irq, int, 0444); - - -static int __init init_uart401(void) -{ - cfg_mpu.irq = irq; - cfg_mpu.io_base = io; - - /* Can be loaded either for module use or to provide functions - to others */ - if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1) { - printk(KERN_INFO "MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997"); - if (!probe_uart401(&cfg_mpu, THIS_MODULE)) - return -ENODEV; - } - - return 0; -} - -static void __exit cleanup_uart401(void) -{ - if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1) - unload_uart401(&cfg_mpu); -} - -module_init(init_uart401); -module_exit(cleanup_uart401); - -#ifndef MODULE -static int __init setup_uart401(char *str) -{ - /* io, irq */ - int ints[3]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - irq = ints[2]; - - return 1; -} - -__setup("uart401=", setup_uart401); -#endif -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/uart6850.c b/ANDROID_3.4.5/sound/oss/uart6850.c deleted file mode 100644 index f3f914aa..00000000 --- a/ANDROID_3.4.5/sound/oss/uart6850.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * sound/oss/uart6850.c - * - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * Extended by Alan Cox for Red Hat Software. Now a loadable MIDI driver. - * 28/4/97 - (C) Copyright Alan Cox. Released under the GPL version 2. - * - * Alan Cox: Updated for new modular code. Removed snd_* irq handling. Now - * uses native linux resources - * Christoph Hellwig: Adapted to module_init/module_exit - * Jeff Garzik: Made it work again, in theory - * FIXME: If the request_irq() succeeds, the probe succeeds. Ug. - * - * Status: Testing required (no shit -jgarzik) - * - * - */ - -#include -#include -#include -#include -/* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: - * added 6850 support, used with COVOX SoundMaster II and custom cards. - */ - -#include "sound_config.h" - -static int uart6850_base = 0x330; - -static int *uart6850_osp; - -#define DATAPORT (uart6850_base) -#define COMDPORT (uart6850_base+1) -#define STATPORT (uart6850_base+1) - -static int uart6850_status(void) -{ - return inb(STATPORT); -} - -#define input_avail() (uart6850_status()&INPUT_AVAIL) -#define output_ready() (uart6850_status()&OUTPUT_READY) - -static void uart6850_cmd(unsigned char cmd) -{ - outb(cmd, COMDPORT); -} - -static int uart6850_read(void) -{ - return inb(DATAPORT); -} - -static void uart6850_write(unsigned char byte) -{ - outb(byte, DATAPORT); -} - -#define OUTPUT_READY 0x02 /* Mask for data ready Bit */ -#define INPUT_AVAIL 0x01 /* Mask for Data Send Ready Bit */ - -#define UART_RESET 0x95 -#define UART_MODE_ON 0x03 - -static int uart6850_opened; -static int uart6850_irq; -static int uart6850_detected; -static int my_dev; -static DEFINE_SPINLOCK(lock); - -static void (*midi_input_intr) (int dev, unsigned char data); -static void poll_uart6850(unsigned long dummy); - - -static DEFINE_TIMER(uart6850_timer, poll_uart6850, 0, 0); - -static void uart6850_input_loop(void) -{ - int count = 10; - - while (count) - { - /* - * Not timed out - */ - if (input_avail()) - { - unsigned char c = uart6850_read(); - count = 100; - if (uart6850_opened & OPEN_READ) - midi_input_intr(my_dev, c); - } - else - { - while (!input_avail() && count) - count--; - } - } -} - -static irqreturn_t m6850intr(int irq, void *dev_id) -{ - if (input_avail()) - uart6850_input_loop(); - return IRQ_HANDLED; -} - -/* - * It looks like there is no input interrupts in the UART mode. Let's try - * polling. - */ - -static void poll_uart6850(unsigned long dummy) -{ - unsigned long flags; - - if (!(uart6850_opened & OPEN_READ)) - return; /* Device has been closed */ - - spin_lock_irqsave(&lock,flags); - if (input_avail()) - uart6850_input_loop(); - - uart6850_timer.expires = 1 + jiffies; - add_timer(&uart6850_timer); - - /* - * Come back later - */ - - spin_unlock_irqrestore(&lock,flags); -} - -static int uart6850_open(int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - if (uart6850_opened) - { -/* printk("Midi6850: Midi busy\n");*/ - return -EBUSY; - }; - - uart6850_cmd(UART_RESET); - uart6850_input_loop(); - midi_input_intr = input; - uart6850_opened = mode; - poll_uart6850(0); /* - * Enable input polling - */ - - return 0; -} - -static void uart6850_close(int dev) -{ - uart6850_cmd(UART_MODE_ON); - del_timer(&uart6850_timer); - uart6850_opened = 0; -} - -static int uart6850_out(int dev, unsigned char midi_byte) -{ - int timeout; - unsigned long flags; - - /* - * Test for input since pending input seems to block the output. - */ - - spin_lock_irqsave(&lock,flags); - - if (input_avail()) - uart6850_input_loop(); - - spin_unlock_irqrestore(&lock,flags); - - /* - * Sometimes it takes about 13000 loops before the output becomes ready - * (After reset). Normally it takes just about 10 loops. - */ - - for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* - * Wait - */ - if (!output_ready()) - { - printk(KERN_WARNING "Midi6850: Timeout\n"); - return 0; - } - uart6850_write(midi_byte); - return 1; -} - -static inline int uart6850_command(int dev, unsigned char *midi_byte) -{ - return 1; -} - -static inline int uart6850_start_read(int dev) -{ - return 0; -} - -static inline int uart6850_end_read(int dev) -{ - return 0; -} - -static inline void uart6850_kick(int dev) -{ -} - -static inline int uart6850_buffer_status(int dev) -{ - return 0; /* - * No data in buffers - */ -} - -#define MIDI_SYNTH_NAME "6850 UART Midi" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT -#include "midi_synth.h" - -static struct midi_operations uart6850_operations = -{ - .owner = THIS_MODULE, - .info = {"6850 UART", 0, 0, SNDCARD_UART6850}, - .converter = &std_midi_synth, - .in_info = {0}, - .open = uart6850_open, - .close = uart6850_close, - .outputc = uart6850_out, - .start_read = uart6850_start_read, - .end_read = uart6850_end_read, - .kick = uart6850_kick, - .command = uart6850_command, - .buffer_status = uart6850_buffer_status -}; - - -static void __init attach_uart6850(struct address_info *hw_config) -{ - int ok, timeout; - unsigned long flags; - - if (!uart6850_detected) - return; - - if ((my_dev = sound_alloc_mididev()) == -1) - { - printk(KERN_INFO "uart6850: Too many midi devices detected\n"); - return; - } - uart6850_base = hw_config->io_base; - uart6850_osp = hw_config->osp; - uart6850_irq = hw_config->irq; - - spin_lock_irqsave(&lock,flags); - - for (timeout = 30000; timeout > 0 && !output_ready(); timeout--); /* - * Wait - */ - uart6850_cmd(UART_MODE_ON); - ok = 1; - spin_unlock_irqrestore(&lock,flags); - - conf_printf("6850 Midi Interface", hw_config); - - std_midi_synth.midi_dev = my_dev; - hw_config->slots[4] = my_dev; - midi_devs[my_dev] = &uart6850_operations; - sequencer_init(); -} - -static inline int reset_uart6850(void) -{ - uart6850_read(); - return 1; /* - * OK - */ -} - -static int __init probe_uart6850(struct address_info *hw_config) -{ - int ok; - - uart6850_osp = hw_config->osp; - uart6850_base = hw_config->io_base; - uart6850_irq = hw_config->irq; - - if (request_irq(uart6850_irq, m6850intr, 0, "MIDI6850", NULL) < 0) - return 0; - - ok = reset_uart6850(); - uart6850_detected = ok; - return ok; -} - -static void __exit unload_uart6850(struct address_info *hw_config) -{ - free_irq(hw_config->irq, NULL); - sound_unload_mididev(hw_config->slots[4]); -} - -static struct address_info cfg_mpu; - -static int __initdata io = -1; -static int __initdata irq = -1; - -module_param(io, int, 0); -module_param(irq, int, 0); - -static int __init init_uart6850(void) -{ - cfg_mpu.io_base = io; - cfg_mpu.irq = irq; - - if (cfg_mpu.io_base == -1 || cfg_mpu.irq == -1) { - printk(KERN_INFO "uart6850: irq and io must be set.\n"); - return -EINVAL; - } - - if (probe_uart6850(&cfg_mpu)) - return -ENODEV; - attach_uart6850(&cfg_mpu); - - return 0; -} - -static void __exit cleanup_uart6850(void) -{ - unload_uart6850(&cfg_mpu); -} - -module_init(init_uart6850); -module_exit(cleanup_uart6850); - -#ifndef MODULE -static int __init setup_uart6850(char *str) -{ - /* io, irq */ - int ints[3]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - irq = ints[2]; - - return 1; -} -__setup("uart6850=", setup_uart6850); -#endif -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/ulaw.h b/ANDROID_3.4.5/sound/oss/ulaw.h deleted file mode 100644 index 0ff8c0a3..00000000 --- a/ANDROID_3.4.5/sound/oss/ulaw.h +++ /dev/null @@ -1,69 +0,0 @@ -static unsigned char ulaw_dsp[] = { - 3, 7, 11, 15, 19, 23, 27, 31, - 35, 39, 43, 47, 51, 55, 59, 63, - 66, 68, 70, 72, 74, 76, 78, 80, - 82, 84, 86, 88, 90, 92, 94, 96, - 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, - 113, 114, 114, 115, 115, 116, 116, 117, - 117, 118, 118, 119, 119, 120, 120, 121, - 121, 121, 122, 122, 122, 122, 123, 123, - 123, 123, 124, 124, 124, 124, 125, 125, - 125, 125, 125, 125, 126, 126, 126, 126, - 126, 126, 126, 126, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 253, 249, 245, 241, 237, 233, 229, 225, - 221, 217, 213, 209, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 174, 172, 170, 168, 166, 164, 162, 160, - 158, 157, 156, 155, 154, 153, 152, 151, - 150, 149, 148, 147, 146, 145, 144, 143, - 143, 142, 142, 141, 141, 140, 140, 139, - 139, 138, 138, 137, 137, 136, 136, 135, - 135, 135, 134, 134, 134, 134, 133, 133, - 133, 133, 132, 132, 132, 132, 131, 131, - 131, 131, 131, 131, 130, 130, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 129, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, -}; - -static unsigned char dsp_ulaw[] = { - 0, 0, 0, 0, 0, 1, 1, 1, - 1, 2, 2, 2, 2, 3, 3, 3, - 3, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, - 7, 8, 8, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 10, 11, 11, 11, - 11, 12, 12, 12, 12, 13, 13, 13, - 13, 14, 14, 14, 14, 15, 15, 15, - 15, 16, 16, 17, 17, 18, 18, 19, - 19, 20, 20, 21, 21, 22, 22, 23, - 23, 24, 24, 25, 25, 26, 26, 27, - 27, 28, 28, 29, 29, 30, 30, 31, - 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, - 47, 49, 51, 53, 55, 57, 59, 61, - 63, 66, 70, 74, 78, 84, 92, 104, - 254, 231, 219, 211, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 175, 174, 173, 172, 171, 170, 169, 168, - 167, 166, 165, 164, 163, 162, 161, 160, - 159, 159, 158, 158, 157, 157, 156, 156, - 155, 155, 154, 154, 153, 153, 152, 152, - 151, 151, 150, 150, 149, 149, 148, 148, - 147, 147, 146, 146, 145, 145, 144, 144, - 143, 143, 143, 143, 142, 142, 142, 142, - 141, 141, 141, 141, 140, 140, 140, 140, - 139, 139, 139, 139, 138, 138, 138, 138, - 137, 137, 137, 137, 136, 136, 136, 136, - 135, 135, 135, 135, 134, 134, 134, 134, - 133, 133, 133, 133, 132, 132, 132, 132, - 131, 131, 131, 131, 130, 130, 130, 130, - 129, 129, 129, 129, 128, 128, 128, 128, -}; diff --git a/ANDROID_3.4.5/sound/oss/v_midi.c b/ANDROID_3.4.5/sound/oss/v_midi.c deleted file mode 100644 index f0b4151d..00000000 --- a/ANDROID_3.4.5/sound/oss/v_midi.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * sound/oss/v_midi.c - * - * The low level driver for the Sound Blaster DS chips. - * - * - * Copyright (C) by Hannu Savolainen 1993-1996 - * - * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * ?? - * - * Changes - * Alan Cox Modularisation, changed memory allocations - * Christoph Hellwig Adapted to module_init/module_exit - * - * Status - * Untested - */ - -#include -#include -#include -#include -#include "sound_config.h" - -#include "v_midi.h" - -static vmidi_devc *v_devc[2] = { NULL, NULL}; -static int midi1,midi2; -static void *midi_mem = NULL; - -/* - * The DSP channel can be used either for input or output. Variable - * 'sb_irq_mode' will be set when the program calls read or write first time - * after open. Current version doesn't support mode changes without closing - * and reopening the device. Support for this feature may be implemented in a - * future version of this driver. - */ - - -static int v_midi_open (int dev, int mode, - void (*input) (int dev, unsigned char data), - void (*output) (int dev) -) -{ - vmidi_devc *devc = midi_devs[dev]->devc; - unsigned long flags; - - if (devc == NULL) - return -(ENXIO); - - spin_lock_irqsave(&devc->lock,flags); - if (devc->opened) - { - spin_unlock_irqrestore(&devc->lock,flags); - return -(EBUSY); - } - devc->opened = 1; - spin_unlock_irqrestore(&devc->lock,flags); - - devc->intr_active = 1; - - if (mode & OPEN_READ) - { - devc->input_opened = 1; - devc->midi_input_intr = input; - } - - return 0; -} - -static void v_midi_close (int dev) -{ - vmidi_devc *devc = midi_devs[dev]->devc; - unsigned long flags; - - if (devc == NULL) - return; - - spin_lock_irqsave(&devc->lock,flags); - devc->intr_active = 0; - devc->input_opened = 0; - devc->opened = 0; - spin_unlock_irqrestore(&devc->lock,flags); -} - -static int v_midi_out (int dev, unsigned char midi_byte) -{ - vmidi_devc *devc = midi_devs[dev]->devc; - vmidi_devc *pdevc; - - if (devc == NULL) - return -ENXIO; - - pdevc = midi_devs[devc->pair_mididev]->devc; - if (pdevc->input_opened > 0){ - if (MIDIbuf_avail(pdevc->my_mididev) > 500) - return 0; - pdevc->midi_input_intr (pdevc->my_mididev, midi_byte); - } - return 1; -} - -static inline int v_midi_start_read (int dev) -{ - return 0; -} - -static int v_midi_end_read (int dev) -{ - vmidi_devc *devc = midi_devs[dev]->devc; - if (devc == NULL) - return -ENXIO; - - devc->intr_active = 0; - return 0; -} - -/* why -EPERM and not -EINVAL?? */ - -static inline int v_midi_ioctl (int dev, unsigned cmd, void __user *arg) -{ - return -EPERM; -} - - -#define MIDI_SYNTH_NAME "Loopback MIDI" -#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT - -#include "midi_synth.h" - -static struct midi_operations v_midi_operations = -{ - .owner = THIS_MODULE, - .info = {"Loopback MIDI Port 1", 0, 0, SNDCARD_VMIDI}, - .converter = &std_midi_synth, - .in_info = {0}, - .open = v_midi_open, - .close = v_midi_close, - .ioctl = v_midi_ioctl, - .outputc = v_midi_out, - .start_read = v_midi_start_read, - .end_read = v_midi_end_read, -}; - -static struct midi_operations v_midi_operations2 = -{ - .owner = THIS_MODULE, - .info = {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI}, - .converter = &std_midi_synth, - .in_info = {0}, - .open = v_midi_open, - .close = v_midi_close, - .ioctl = v_midi_ioctl, - .outputc = v_midi_out, - .start_read = v_midi_start_read, - .end_read = v_midi_end_read, -}; - -/* - * We kmalloc just one of these - it makes life simpler and the code - * cleaner and the memory handling far more efficient - */ - -struct vmidi_memory -{ - /* Must be first */ - struct midi_operations m_ops[2]; - struct synth_operations s_ops[2]; - struct vmidi_devc v_ops[2]; -}; - -static void __init attach_v_midi (struct address_info *hw_config) -{ - struct vmidi_memory *m; - /* printk("Attaching v_midi device.....\n"); */ - - midi1 = sound_alloc_mididev(); - if (midi1 == -1) - { - printk(KERN_ERR "v_midi: Too many midi devices detected\n"); - return; - } - - m = kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL); - if (m == NULL) - { - printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n"); - sound_unload_mididev(midi1); - return; - } - - midi_mem = m; - - midi_devs[midi1] = &m->m_ops[0]; - - - midi2 = sound_alloc_mididev(); - if (midi2 == -1) - { - printk (KERN_ERR "v_midi: Too many midi devices detected\n"); - kfree(m); - sound_unload_mididev(midi1); - return; - } - - midi_devs[midi2] = &m->m_ops[1]; - - /* printk("VMIDI1: %d VMIDI2: %d\n",midi1,midi2); */ - - /* for MIDI-1 */ - v_devc[0] = &m->v_ops[0]; - memcpy ((char *) midi_devs[midi1], (char *) &v_midi_operations, - sizeof (struct midi_operations)); - - v_devc[0]->my_mididev = midi1; - v_devc[0]->pair_mididev = midi2; - v_devc[0]->opened = v_devc[0]->input_opened = 0; - v_devc[0]->intr_active = 0; - v_devc[0]->midi_input_intr = NULL; - spin_lock_init(&v_devc[0]->lock); - - midi_devs[midi1]->devc = v_devc[0]; - - midi_devs[midi1]->converter = &m->s_ops[0]; - std_midi_synth.midi_dev = midi1; - memcpy ((char *) midi_devs[midi1]->converter, (char *) &std_midi_synth, - sizeof (struct synth_operations)); - midi_devs[midi1]->converter->id = "V_MIDI 1"; - - /* for MIDI-2 */ - v_devc[1] = &m->v_ops[1]; - - memcpy ((char *) midi_devs[midi2], (char *) &v_midi_operations2, - sizeof (struct midi_operations)); - - v_devc[1]->my_mididev = midi2; - v_devc[1]->pair_mididev = midi1; - v_devc[1]->opened = v_devc[1]->input_opened = 0; - v_devc[1]->intr_active = 0; - v_devc[1]->midi_input_intr = NULL; - spin_lock_init(&v_devc[1]->lock); - - midi_devs[midi2]->devc = v_devc[1]; - midi_devs[midi2]->converter = &m->s_ops[1]; - - std_midi_synth.midi_dev = midi2; - memcpy ((char *) midi_devs[midi2]->converter, (char *) &std_midi_synth, - sizeof (struct synth_operations)); - midi_devs[midi2]->converter->id = "V_MIDI 2"; - - sequencer_init(); - /* printk("Attached v_midi device\n"); */ -} - -static inline int __init probe_v_midi(struct address_info *hw_config) -{ - return(1); /* always OK */ -} - - -static void __exit unload_v_midi(struct address_info *hw_config) -{ - sound_unload_mididev(midi1); - sound_unload_mididev(midi2); - kfree(midi_mem); -} - -static struct address_info cfg; /* dummy */ - -static int __init init_vmidi(void) -{ - printk("MIDI Loopback device driver\n"); - if (!probe_v_midi(&cfg)) - return -ENODEV; - attach_v_midi(&cfg); - - return 0; -} - -static void __exit cleanup_vmidi(void) -{ - unload_v_midi(&cfg); -} - -module_init(init_vmidi); -module_exit(cleanup_vmidi); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/v_midi.h b/ANDROID_3.4.5/sound/oss/v_midi.h deleted file mode 100644 index 08e2185e..00000000 --- a/ANDROID_3.4.5/sound/oss/v_midi.h +++ /dev/null @@ -1,14 +0,0 @@ -typedef struct vmidi_devc { - int dev; - - /* State variables */ - int opened; - spinlock_t lock; - - /* MIDI fields */ - int my_mididev; - int pair_mididev; - int input_opened; - int intr_active; - void (*midi_input_intr) (int dev, unsigned char data); - } vmidi_devc; diff --git a/ANDROID_3.4.5/sound/oss/vidc.c b/ANDROID_3.4.5/sound/oss/vidc.c deleted file mode 100644 index 92ca5bee..00000000 --- a/ANDROID_3.4.5/sound/oss/vidc.c +++ /dev/null @@ -1,557 +0,0 @@ -/* - * linux/drivers/sound/vidc.c - * - * Copyright (C) 1997-2000 by Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * VIDC20 audio driver. - * - * The VIDC20 sound hardware consists of the VIDC20 itself, a DAC and a DMA - * engine. The DMA transfers fixed-format (16-bit little-endian linear) - * samples to the VIDC20, which then transfers this data serially to the - * DACs. The samplerate is controlled by the VIDC. - * - * We currently support a mixer device, but it is currently non-functional. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sound_config.h" -#include "vidc.h" - -#ifndef _SIOC_TYPE -#define _SIOC_TYPE(x) _IOC_TYPE(x) -#endif -#ifndef _SIOC_NR -#define _SIOC_NR(x) _IOC_NR(x) -#endif - -#define VIDC_SOUND_CLOCK (250000) -#define VIDC_SOUND_CLOCK_EXT (176400) - -/* - * When using SERIAL SOUND mode (external DAC), the number of physical - * channels is fixed at 2. - */ -static int vidc_busy; -static int vidc_adev; -static int vidc_audio_rate; -static char vidc_audio_format; -static char vidc_audio_channels; - -static unsigned char vidc_level_l[SOUND_MIXER_NRDEVICES] = { - 85, /* master */ - 50, /* bass */ - 50, /* treble */ - 0, /* synth */ - 75, /* pcm */ - 0, /* speaker */ - 100, /* ext line */ - 0, /* mic */ - 100, /* CD */ - 0, -}; - -static unsigned char vidc_level_r[SOUND_MIXER_NRDEVICES] = { - 85, /* master */ - 50, /* bass */ - 50, /* treble */ - 0, /* synth */ - 75, /* pcm */ - 0, /* speaker */ - 100, /* ext line */ - 0, /* mic */ - 100, /* CD */ - 0, -}; - -static unsigned int vidc_audio_volume_l; /* left PCM vol, 0 - 65536 */ -static unsigned int vidc_audio_volume_r; /* right PCM vol, 0 - 65536 */ - -extern void vidc_update_filler(int bits, int channels); -extern int softoss_dev; - -static void -vidc_mixer_set(int mdev, unsigned int level) -{ - unsigned int lev_l = level & 0x007f; - unsigned int lev_r = (level & 0x7f00) >> 8; - unsigned int mlev_l, mlev_r; - - if (lev_l > 100) - lev_l = 100; - if (lev_r > 100) - lev_r = 100; - -#define SCALE(lev,master) ((lev) * (master) * 65536 / 10000) - - mlev_l = vidc_level_l[SOUND_MIXER_VOLUME]; - mlev_r = vidc_level_r[SOUND_MIXER_VOLUME]; - - switch (mdev) { - case SOUND_MIXER_VOLUME: - case SOUND_MIXER_PCM: - vidc_level_l[mdev] = lev_l; - vidc_level_r[mdev] = lev_r; - - vidc_audio_volume_l = SCALE(lev_l, mlev_l); - vidc_audio_volume_r = SCALE(lev_r, mlev_r); -/*printk("VIDC: PCM vol %05X %05X\n", vidc_audio_volume_l, vidc_audio_volume_r);*/ - break; - } -#undef SCALE -} - -static int vidc_mixer_ioctl(int dev, unsigned int cmd, void __user *arg) -{ - unsigned int val; - unsigned int mdev; - - if (_SIOC_TYPE(cmd) != 'M') - return -EINVAL; - - mdev = _SIOC_NR(cmd); - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) { - if (get_user(val, (unsigned int __user *)arg)) - return -EFAULT; - - if (mdev < SOUND_MIXER_NRDEVICES) - vidc_mixer_set(mdev, val); - else - return -EINVAL; - } - - /* - * Return parameters - */ - switch (mdev) { - case SOUND_MIXER_RECSRC: - val = 0; - break; - - case SOUND_MIXER_DEVMASK: - val = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH; - break; - - case SOUND_MIXER_STEREODEVS: - val = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH; - break; - - case SOUND_MIXER_RECMASK: - val = 0; - break; - - case SOUND_MIXER_CAPS: - val = 0; - break; - - default: - if (mdev < SOUND_MIXER_NRDEVICES) - val = vidc_level_l[mdev] | vidc_level_r[mdev] << 8; - else - return -EINVAL; - } - - return put_user(val, (unsigned int __user *)arg) ? -EFAULT : 0; -} - -static unsigned int vidc_audio_set_format(int dev, unsigned int fmt) -{ - switch (fmt) { - default: - fmt = AFMT_S16_LE; - case AFMT_U8: - case AFMT_S8: - case AFMT_S16_LE: - vidc_audio_format = fmt; - vidc_update_filler(vidc_audio_format, vidc_audio_channels); - case AFMT_QUERY: - break; - } - return vidc_audio_format; -} - -#define my_abs(i) ((i)<0 ? -(i) : (i)) - -static int vidc_audio_set_speed(int dev, int rate) -{ - if (rate) { - unsigned int hwctrl, hwrate, hwrate_ext, rate_int, rate_ext; - unsigned int diff_int, diff_ext; - unsigned int newsize, new2size; - - hwctrl = 0x00000003; - - /* Using internal clock */ - hwrate = (((VIDC_SOUND_CLOCK * 2) / rate) + 1) >> 1; - if (hwrate < 3) - hwrate = 3; - if (hwrate > 255) - hwrate = 255; - - /* Using exernal clock */ - hwrate_ext = (((VIDC_SOUND_CLOCK_EXT * 2) / rate) + 1) >> 1; - if (hwrate_ext < 3) - hwrate_ext = 3; - if (hwrate_ext > 255) - hwrate_ext = 255; - - rate_int = VIDC_SOUND_CLOCK / hwrate; - rate_ext = VIDC_SOUND_CLOCK_EXT / hwrate_ext; - - /* Chose between external and internal clock */ - diff_int = my_abs(rate_ext-rate); - diff_ext = my_abs(rate_int-rate); - if (diff_ext < diff_int) { - /*printk("VIDC: external %d %d %d\n", rate, rate_ext, hwrate_ext);*/ - hwrate=hwrate_ext; - hwctrl=0x00000002; - /* Allow roughly 0.4% tolerance */ - if (diff_ext > (rate/256)) - rate=rate_ext; - } else { - /*printk("VIDC: internal %d %d %d\n", rate, rate_int, hwrate);*/ - hwctrl=0x00000003; - /* Allow roughly 0.4% tolerance */ - if (diff_int > (rate/256)) - rate=rate_int; - } - - vidc_writel(0xb0000000 | (hwrate - 2)); - vidc_writel(0xb1000000 | hwctrl); - - newsize = (10000 / hwrate) & ~3; - if (newsize < 208) - newsize = 208; - if (newsize > 4096) - newsize = 4096; - for (new2size = 128; new2size < newsize; new2size <<= 1); - if (new2size - newsize > newsize - (new2size >> 1)) - new2size >>= 1; - if (new2size > 4096) { - printk(KERN_ERR "VIDC: error: dma buffer (%d) %d > 4K\n", - newsize, new2size); - new2size = 4096; - } - /*printk("VIDC: dma size %d\n", new2size);*/ - dma_bufsize = new2size; - vidc_audio_rate = rate; - } - return vidc_audio_rate; -} - -static short vidc_audio_set_channels(int dev, short channels) -{ - switch (channels) { - default: - channels = 2; - case 1: - case 2: - vidc_audio_channels = channels; - vidc_update_filler(vidc_audio_format, vidc_audio_channels); - case 0: - break; - } - return vidc_audio_channels; -} - -/* - * Open the device - */ -static int vidc_audio_open(int dev, int mode) -{ - /* This audio device does not have recording capability */ - if (mode == OPEN_READ) - return -EPERM; - - if (vidc_busy) - return -EBUSY; - - vidc_busy = 1; - return 0; -} - -/* - * Close the device - */ -static void vidc_audio_close(int dev) -{ - vidc_busy = 0; -} - -/* - * Output a block via DMA to sound device. - * - * We just set the DMA start and count; the DMA interrupt routine - * will take care of formatting the samples (via the appropriate - * vidc_filler routine), and flag via vidc_audio_dma_interrupt when - * more data is required. - */ -static void -vidc_audio_output_block(int dev, unsigned long buf, int total_count, int one) -{ - struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - unsigned long flags; - - local_irq_save(flags); - dma_start = buf - (unsigned long)dmap->raw_buf_phys + (unsigned long)dmap->raw_buf; - dma_count = total_count; - local_irq_restore(flags); -} - -static void -vidc_audio_start_input(int dev, unsigned long buf, int count, int intrflag) -{ -} - -static int vidc_audio_prepare_for_input(int dev, int bsize, int bcount) -{ - return -EINVAL; -} - -static irqreturn_t vidc_audio_dma_interrupt(void) -{ - DMAbuf_outputintr(vidc_adev, 1); - return IRQ_HANDLED; -} - -/* - * Prepare for outputting samples. - * - * Each buffer that will be passed will be `bsize' bytes long, - * with a total of `bcount' buffers. - */ -static int vidc_audio_prepare_for_output(int dev, int bsize, int bcount) -{ - struct audio_operations *adev = audio_devs[dev]; - - dma_interrupt = NULL; - adev->dmap_out->flags |= DMA_NODMA; - - return 0; -} - -/* - * Stop our current operation. - */ -static void vidc_audio_reset(int dev) -{ - dma_interrupt = NULL; -} - -static int vidc_audio_local_qlen(int dev) -{ - return /*dma_count !=*/ 0; -} - -static void vidc_audio_trigger(int dev, int enable_bits) -{ - struct audio_operations *adev = audio_devs[dev]; - - if (enable_bits & PCM_ENABLE_OUTPUT) { - if (!(adev->dmap_out->flags & DMA_ACTIVE)) { - unsigned long flags; - - local_irq_save(flags); - - /* prevent recusion */ - adev->dmap_out->flags |= DMA_ACTIVE; - - dma_interrupt = vidc_audio_dma_interrupt; - vidc_sound_dma_irq(0, NULL); - iomd_writeb(DMA_CR_E | 0x10, IOMD_SD0CR); - - local_irq_restore(flags); - } - } -} - -static struct audio_driver vidc_audio_driver = -{ - .owner = THIS_MODULE, - .open = vidc_audio_open, - .close = vidc_audio_close, - .output_block = vidc_audio_output_block, - .start_input = vidc_audio_start_input, - .prepare_for_input = vidc_audio_prepare_for_input, - .prepare_for_output = vidc_audio_prepare_for_output, - .halt_io = vidc_audio_reset, - .local_qlen = vidc_audio_local_qlen, - .trigger = vidc_audio_trigger, - .set_speed = vidc_audio_set_speed, - .set_bits = vidc_audio_set_format, - .set_channels = vidc_audio_set_channels -}; - -static struct mixer_operations vidc_mixer_operations = { - .owner = THIS_MODULE, - .id = "VIDC", - .name = "VIDCsound", - .ioctl = vidc_mixer_ioctl -}; - -void vidc_update_filler(int format, int channels) -{ -#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3)) - - switch (TYPE(format, channels)) { - default: - case TYPE(AFMT_U8, 1): - vidc_filler = vidc_fill_1x8_u; - break; - - case TYPE(AFMT_U8, 2): - vidc_filler = vidc_fill_2x8_u; - break; - - case TYPE(AFMT_S8, 1): - vidc_filler = vidc_fill_1x8_s; - break; - - case TYPE(AFMT_S8, 2): - vidc_filler = vidc_fill_2x8_s; - break; - - case TYPE(AFMT_S16_LE, 1): - vidc_filler = vidc_fill_1x16_s; - break; - - case TYPE(AFMT_S16_LE, 2): - vidc_filler = vidc_fill_2x16_s; - break; - } -} - -static void __init attach_vidc(struct address_info *hw_config) -{ - char name[32]; - int i, adev; - - sprintf(name, "VIDC %d-bit sound", hw_config->card_subtype); - conf_printf(name, hw_config); - memset(dma_buf, 0, sizeof(dma_buf)); - - adev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, name, - &vidc_audio_driver, sizeof(vidc_audio_driver), - DMA_AUTOMODE, AFMT_U8 | AFMT_S8 | AFMT_S16_LE, - NULL, hw_config->dma, hw_config->dma2); - - if (adev < 0) - goto audio_failed; - - /* - * 1024 bytes => 64 buffers - */ - audio_devs[adev]->min_fragment = 10; - audio_devs[adev]->mixer_dev = num_mixers; - - audio_devs[adev]->mixer_dev = - sound_install_mixer(MIXER_DRIVER_VERSION, - name, &vidc_mixer_operations, - sizeof(vidc_mixer_operations), NULL); - - if (audio_devs[adev]->mixer_dev < 0) - goto mixer_failed; - - for (i = 0; i < 2; i++) { - dma_buf[i] = get_zeroed_page(GFP_KERNEL); - if (!dma_buf[i]) { - printk(KERN_ERR "%s: can't allocate required buffers\n", - name); - goto mem_failed; - } - dma_pbuf[i] = virt_to_phys((void *)dma_buf[i]); - } - - if (sound_alloc_dma(hw_config->dma, hw_config->name)) { - printk(KERN_ERR "%s: DMA %d is in use\n", name, hw_config->dma); - goto dma_failed; - } - - if (request_irq(hw_config->irq, vidc_sound_dma_irq, 0, - hw_config->name, &dma_start)) { - printk(KERN_ERR "%s: IRQ %d is in use\n", name, hw_config->irq); - goto irq_failed; - } - vidc_adev = adev; - vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8)); - - return; - -irq_failed: - sound_free_dma(hw_config->dma); -dma_failed: -mem_failed: - for (i = 0; i < 2; i++) - free_page(dma_buf[i]); - sound_unload_mixerdev(audio_devs[adev]->mixer_dev); -mixer_failed: - sound_unload_audiodev(adev); -audio_failed: - return; -} - -static int __init probe_vidc(struct address_info *hw_config) -{ - hw_config->irq = IRQ_DMAS0; - hw_config->dma = DMA_VIRTUAL_SOUND; - hw_config->dma2 = -1; - hw_config->card_subtype = 16; - hw_config->name = "VIDC20"; - return 1; -} - -static void __exit unload_vidc(struct address_info *hw_config) -{ - int i, adev = vidc_adev; - - vidc_adev = -1; - - free_irq(hw_config->irq, &dma_start); - sound_free_dma(hw_config->dma); - - if (adev >= 0) { - sound_unload_mixerdev(audio_devs[adev]->mixer_dev); - sound_unload_audiodev(adev); - for (i = 0; i < 2; i++) - free_page(dma_buf[i]); - } -} - -static struct address_info cfg; - -static int __init init_vidc(void) -{ - if (probe_vidc(&cfg) == 0) - return -ENODEV; - - attach_vidc(&cfg); - - return 0; -} - -static void __exit cleanup_vidc(void) -{ - unload_vidc(&cfg); -} - -module_init(init_vidc); -module_exit(cleanup_vidc); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("VIDC20 audio driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/vidc.h b/ANDROID_3.4.5/sound/oss/vidc.h deleted file mode 100644 index 0d142475..00000000 --- a/ANDROID_3.4.5/sound/oss/vidc.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * linux/drivers/sound/vidc.h - * - * Copyright (C) 1997 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * VIDC sound function prototypes - */ - -/* vidc_fill.S */ - -/* - * Filler routines for different channels and sample sizes - */ - -extern unsigned long vidc_fill_1x8_u(unsigned long ibuf, unsigned long iend, - unsigned long obuf, int mask); -extern unsigned long vidc_fill_2x8_u(unsigned long ibuf, unsigned long iend, - unsigned long obuf, int mask); -extern unsigned long vidc_fill_1x8_s(unsigned long ibuf, unsigned long iend, - unsigned long obuf, int mask); -extern unsigned long vidc_fill_2x8_s(unsigned long ibuf, unsigned long iend, - unsigned long obuf, int mask); -extern unsigned long vidc_fill_1x16_s(unsigned long ibuf, unsigned long iend, - unsigned long obuf, int mask); -extern unsigned long vidc_fill_2x16_s(unsigned long ibuf, unsigned long iend, - unsigned long obuf, int mask); - -/* - * DMA Interrupt handler - */ - -extern irqreturn_t vidc_sound_dma_irq(int irqnr, void *ref); - -/* - * Filler routine pointer - */ - -extern unsigned long (*vidc_filler) (unsigned long ibuf, unsigned long iend, - unsigned long obuf, int mask); - -/* - * Virtual DMA buffer exhausted - */ - -extern irqreturn_t (*dma_interrupt) (void); - -/* - * Virtual DMA buffer addresses - */ - -extern unsigned long dma_start, dma_count, dma_bufsize; -extern unsigned long dma_buf[2], dma_pbuf[2]; - -/* vidc_synth.c */ - -extern void vidc_synth_init(struct address_info *hw_config); -extern void vidc_synth_exit(struct address_info *hw_config); -extern int vidc_synth_get_volume(void); -extern int vidc_synth_set_volume(int vol); diff --git a/ANDROID_3.4.5/sound/oss/vidc_fill.S b/ANDROID_3.4.5/sound/oss/vidc_fill.S deleted file mode 100644 index bed34921..00000000 --- a/ANDROID_3.4.5/sound/oss/vidc_fill.S +++ /dev/null @@ -1,218 +0,0 @@ -/* - * linux/drivers/sound/vidc_fill.S - * - * Copyright (C) 1997 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Filler routines for DMA buffers - */ -#include -#include -#include -#include - - .text - -ENTRY(vidc_fill_1x8_u) - mov ip, #0xff00 -1: cmp r0, r1 - bge vidc_clear - ldrb r4, [r0], #1 - eor r4, r4, #0x80 - and r4, ip, r4, lsl #8 - orr r4, r4, r4, lsl #16 - str r4, [r2], #4 - cmp r2, r3 - blt 1b - mov pc, lr - -ENTRY(vidc_fill_2x8_u) - mov ip, #0xff00 -1: cmp r0, r1 - bge vidc_clear - ldr r4, [r0], #2 - and r5, r4, ip - and r4, ip, r4, lsl #8 - orr r4, r4, r5, lsl #16 - orr r4, r4, r4, lsr #8 - str r4, [r2], #4 - cmp r2, r3 - blt 1b - mov pc, lr - -ENTRY(vidc_fill_1x8_s) - mov ip, #0xff00 -1: cmp r0, r1 - bge vidc_clear - ldrb r4, [r0], #1 - and r4, ip, r4, lsl #8 - orr r4, r4, r4, lsl #16 - str r4, [r2], #4 - cmp r2, r3 - blt 1b - mov pc, lr - -ENTRY(vidc_fill_2x8_s) - mov ip, #0xff00 -1: cmp r0, r1 - bge vidc_clear - ldr r4, [r0], #2 - and r5, r4, ip - and r4, ip, r4, lsl #8 - orr r4, r4, r5, lsl #16 - orr r4, r4, r4, lsr #8 - str r4, [r2], #4 - cmp r2, r3 - blt 1b - mov pc, lr - -ENTRY(vidc_fill_1x16_s) - mov ip, #0xff00 - orr ip, ip, ip, lsr #8 -1: cmp r0, r1 - bge vidc_clear - ldr r5, [r0], #2 - and r4, r5, ip - orr r4, r4, r4, lsl #16 - str r4, [r2], #4 - cmp r0, r1 - addlt r0, r0, #2 - andlt r4, r5, ip, lsl #16 - orrlt r4, r4, r4, lsr #16 - strlt r4, [r2], #4 - cmp r2, r3 - blt 1b - mov pc, lr - -ENTRY(vidc_fill_2x16_s) - mov ip, #0xff00 - orr ip, ip, ip, lsr #8 -1: cmp r0, r1 - bge vidc_clear - ldr r4, [r0], #4 - str r4, [r2], #4 - cmp r0, r1 - ldrlt r4, [r0], #4 - strlt r4, [r2], #4 - cmp r2, r3 - blt 1b - mov pc, lr - -ENTRY(vidc_fill_noaudio) - mov r0, #0 - mov r1, #0 -2: mov r4, #0 - mov r5, #0 -1: cmp r2, r3 - stmltia r2!, {r0, r1, r4, r5} - blt 1b - mov pc, lr - -ENTRY(vidc_clear) - mov r0, #0 - mov r1, #0 - tst r2, #4 - str r0, [r2], #4 - tst r2, #8 - stmia r2!, {r0, r1} - b 2b - -/* - * Call filler routines with: - * r0 = phys address - * r1 = phys end - * r2 = buffer - * Returns: - * r0 = new buffer address - * r2 = new buffer finish - * r4 = corrupted - * r5 = corrupted - * ip = corrupted - */ - -ENTRY(vidc_sound_dma_irq) - stmfd sp!, {r4 - r8, lr} - ldr r8, =dma_start - ldmia r8, {r0, r1, r2, r3, r4, r5} - teq r1, #0 - adreq r4, vidc_fill_noaudio - moveq r7, #1 << 31 - movne r7, #0 - mov ip, #IOMD_BASE & 0xff000000 - orr ip, ip, #IOMD_BASE & 0x00ff0000 - ldrb r6, [ip, #IOMD_SD0ST] - tst r6, #DMA_ST_OFL @ Check for overrun - eorne r6, r6, #DMA_ST_AB - tst r6, #DMA_ST_AB - moveq r2, r3 @ DMAing A, update B - add r3, r2, r5 @ End of DMA buffer - add r1, r1, r0 @ End of virtual DMA buffer - mov lr, pc - mov pc, r4 @ Call fill routine (uses r4, ip) - sub r1, r1, r0 @ Remaining length - stmia r8, {r0, r1} - mov r0, #0 - tst r2, #4 @ Round buffer up to 4 words - strne r0, [r2], #4 - tst r2, #8 - strne r0, [r2], #4 - strne r0, [r2], #4 - sub r2, r2, #16 - mov r2, r2, lsl #20 - movs r2, r2, lsr #20 - orreq r2, r2, #1 << 30 @ Set L bit - orr r2, r2, r7 - ldmdb r8, {r3, r4, r5} - tst r6, #DMA_ST_AB - mov ip, #IOMD_BASE & 0xff000000 - orr ip, ip, #IOMD_BASE & 0x00ff0000 - streq r4, [ip, #IOMD_SD0CURB] - strne r5, [ip, #IOMD_SD0CURA] - streq r2, [ip, #IOMD_SD0ENDB] - strne r2, [ip, #IOMD_SD0ENDA] - ldr lr, [ip, #IOMD_SD0ST] - tst lr, #DMA_ST_OFL - bne 1f - tst r6, #DMA_ST_AB - strne r4, [ip, #IOMD_SD0CURB] - streq r5, [ip, #IOMD_SD0CURA] - strne r2, [ip, #IOMD_SD0ENDB] - streq r2, [ip, #IOMD_SD0ENDA] -1: teq r7, #0 - mov r0, #0x10 - strneb r0, [ip, #IOMD_SD0CR] - ldmfd sp!, {r4 - r8, lr} - mov r0, #1 @ IRQ_HANDLED - teq r1, #0 @ If we have no more - movne pc, lr - teq r3, #0 - movne pc, r3 @ Call interrupt routine - mov pc, lr - - .data - .globl dma_interrupt -dma_interrupt: - .long 0 @ r3 - .globl dma_pbuf -dma_pbuf: - .long 0 @ r4 - .long 0 @ r5 - .globl dma_start -dma_start: - .long 0 @ r0 - .globl dma_count -dma_count: - .long 0 @ r1 - .globl dma_buf -dma_buf: - .long 0 @ r2 - .long 0 @ r3 - .globl vidc_filler -vidc_filler: - .long vidc_fill_noaudio @ r4 - .globl dma_bufsize -dma_bufsize: - .long 0x1000 @ r5 diff --git a/ANDROID_3.4.5/sound/oss/vwsnd.c b/ANDROID_3.4.5/sound/oss/vwsnd.c deleted file mode 100644 index 643f1113..00000000 --- a/ANDROID_3.4.5/sound/oss/vwsnd.c +++ /dev/null @@ -1,3498 +0,0 @@ -/* - * Sound driver for Silicon Graphics 320 and 540 Visual Workstations' - * onboard audio. See notes in Documentation/sound/oss/vwsnd . - * - * Copyright 1999 Silicon Graphics, Inc. All rights reserved. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#undef VWSND_DEBUG /* define for debugging */ - -/* - * XXX to do - - * - * External sync. - * Rename swbuf, hwbuf, u&i, hwptr&swptr to something rational. - * Bug - if select() called before read(), pcm_setup() not called. - * Bug - output doesn't stop soon enough if process killed. - */ - -/* - * Things to test - - * - * Will readv/writev work? Write a test. - * - * insmod/rmmod 100 million times. - * - * Run I/O until int ptrs wrap around (roughly 6.2 hours @ DAT - * rate). - * - * Concurrent threads banging on mixer simultaneously, both UP - * and SMP kernels. Especially, watch for thread A changing - * OUTSRC while thread B changes gain -- both write to the same - * ad1843 register. - * - * What happens if a client opens /dev/audio then forks? - * Do two procs have /dev/audio open? Test. - * - * Pump audio through the CD, MIC and line inputs and verify that - * they mix/mute into the output. - * - * Apps: - * amp - * mpg123 - * x11amp - * mxv - * kmedia - * esound - * need more input apps - * - * Run tests while bombarding with signals. setitimer(2) will do it... */ - -/* - * This driver is organized in nine sections. - * The nine sections are: - * - * debug stuff - * low level lithium access - * high level lithium access - * AD1843 access - * PCM I/O - * audio driver - * mixer driver - * probe/attach/unload - * initialization and loadable kernel module interface - * - * That is roughly the order of increasing abstraction, so forward - * dependencies are minimal. - */ - -/* - * Locking Notes - * - * INC_USE_COUNT and DEC_USE_COUNT keep track of the number of - * open descriptors to this driver. They store it in vwsnd_use_count. - * The global device list, vwsnd_dev_list, is immutable when the IN_USE - * is true. - * - * devc->open_lock is a semaphore that is used to enforce the - * single reader/single writer rule for /dev/audio. The rule is - * that each device may have at most one reader and one writer. - * Open will block until the previous client has closed the - * device, unless O_NONBLOCK is specified. - * - * The semaphore devc->io_mutex serializes PCM I/O syscalls. This - * is unnecessary in Linux 2.2, because the kernel lock - * serializes read, write, and ioctl globally, but it's there, - * ready for the brave, new post-kernel-lock world. - * - * Locking between interrupt and baselevel is handled by the - * "lock" spinlock in vwsnd_port (one lock each for read and - * write). Each half holds the lock just long enough to see what - * area it owns and update its pointers. See pcm_output() and - * pcm_input() for most of the gory stuff. - * - * devc->mix_mutex serializes all mixer ioctls. This is also - * redundant because of the kernel lock. - * - * The lowest level lock is lith->lithium_lock. It is a - * spinlock which is held during the two-register tango of - * reading/writing an AD1843 register. See - * li_{read,write}_ad1843_reg(). - */ - -/* - * Sample Format Notes - * - * Lithium's DMA engine has two formats: 16-bit 2's complement - * and 8-bit unsigned . 16-bit transfers the data unmodified, 2 - * bytes per sample. 8-bit unsigned transfers 1 byte per sample - * and XORs each byte with 0x80. Lithium can input or output - * either mono or stereo in either format. - * - * The AD1843 has four formats: 16-bit 2's complement, 8-bit - * unsigned, 8-bit mu-Law and 8-bit A-Law. - * - * This driver supports five formats: AFMT_S8, AFMT_U8, - * AFMT_MU_LAW, AFMT_A_LAW, and AFMT_S16_LE. - * - * For AFMT_U8 output, we keep the AD1843 in 16-bit mode, and - * rely on Lithium's XOR to translate between U8 and S8. - * - * For AFMT_S8, AFMT_MU_LAW and AFMT_A_LAW output, we have to XOR - * the 0x80 bit in software to compensate for Lithium's XOR. - * This happens in pcm_copy_{in,out}(). - * - * Changes: - * 11-10-2000 Bartlomiej Zolnierkiewicz - * Added some __init/__exit - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "sound_config.h" - -/*****************************************************************************/ -/* debug stuff */ - -#ifdef VWSND_DEBUG - -static DEFINE_MUTEX(vwsnd_mutex); -static int shut_up = 1; - -/* - * dbgassert - called when an assertion fails. - */ - -static void dbgassert(const char *fcn, int line, const char *expr) -{ - if (in_interrupt()) - panic("ASSERTION FAILED IN INTERRUPT, %s:%s:%d %s\n", - __FILE__, fcn, line, expr); - else { - int x; - printk(KERN_ERR "ASSERTION FAILED, %s:%s:%d %s\n", - __FILE__, fcn, line, expr); - x = * (volatile int *) 0; /* force proc to exit */ - } -} - -/* - * Bunch of useful debug macros: - * - * ASSERT - print unless e nonzero (panic if in interrupt) - * DBGDO - include arbitrary code if debugging - * DBGX - debug print raw (w/o function name) - * DBGP - debug print w/ function name - * DBGE - debug print function entry - * DBGC - debug print function call - * DBGR - debug print function return - * DBGXV - debug print raw when verbose - * DBGPV - debug print when verbose - * DBGEV - debug print function entry when verbose - * DBGRV - debug print function return when verbose - */ - -#define ASSERT(e) ((e) ? (void) 0 : dbgassert(__func__, __LINE__, #e)) -#define DBGDO(x) x -#define DBGX(fmt, args...) (in_interrupt() ? 0 : printk(KERN_ERR fmt, ##args)) -#define DBGP(fmt, args...) (DBGX("%s: " fmt, __func__ , ##args)) -#define DBGE(fmt, args...) (DBGX("%s" fmt, __func__ , ##args)) -#define DBGC(rtn) (DBGP("calling %s\n", rtn)) -#define DBGR() (DBGP("returning\n")) -#define DBGXV(fmt, args...) (shut_up ? 0 : DBGX(fmt, ##args)) -#define DBGPV(fmt, args...) (shut_up ? 0 : DBGP(fmt, ##args)) -#define DBGEV(fmt, args...) (shut_up ? 0 : DBGE(fmt, ##args)) -#define DBGCV(rtn) (shut_up ? 0 : DBGC(rtn)) -#define DBGRV() (shut_up ? 0 : DBGR()) - -#else /* !VWSND_DEBUG */ - -#define ASSERT(e) ((void) 0) -#define DBGDO(x) /* don't */ -#define DBGX(fmt, args...) ((void) 0) -#define DBGP(fmt, args...) ((void) 0) -#define DBGE(fmt, args...) ((void) 0) -#define DBGC(rtn) ((void) 0) -#define DBGR() ((void) 0) -#define DBGPV(fmt, args...) ((void) 0) -#define DBGXV(fmt, args...) ((void) 0) -#define DBGEV(fmt, args...) ((void) 0) -#define DBGCV(rtn) ((void) 0) -#define DBGRV() ((void) 0) - -#endif /* !VWSND_DEBUG */ - -/*****************************************************************************/ -/* low level lithium access */ - -/* - * We need to talk to Lithium registers on three pages. Here are - * the pages' offsets from the base address (0xFF001000). - */ - -enum { - LI_PAGE0_OFFSET = 0x01000 - 0x1000, /* FF001000 */ - LI_PAGE1_OFFSET = 0x0F000 - 0x1000, /* FF00F000 */ - LI_PAGE2_OFFSET = 0x10000 - 0x1000, /* FF010000 */ -}; - -/* low-level lithium data */ - -typedef struct lithium { - void * page0; /* virtual addresses */ - void * page1; - void * page2; - spinlock_t lock; /* protects codec and UST/MSC access */ -} lithium_t; - -/* - * li_destroy destroys the lithium_t structure and vm mappings. - */ - -static void li_destroy(lithium_t *lith) -{ - if (lith->page0) { - iounmap(lith->page0); - lith->page0 = NULL; - } - if (lith->page1) { - iounmap(lith->page1); - lith->page1 = NULL; - } - if (lith->page2) { - iounmap(lith->page2); - lith->page2 = NULL; - } -} - -/* - * li_create initializes the lithium_t structure and sets up vm mappings - * to access the registers. - * Returns 0 on success, -errno on failure. - */ - -static int __init li_create(lithium_t *lith, unsigned long baseaddr) -{ - spin_lock_init(&lith->lock); - lith->page0 = ioremap_nocache(baseaddr + LI_PAGE0_OFFSET, PAGE_SIZE); - lith->page1 = ioremap_nocache(baseaddr + LI_PAGE1_OFFSET, PAGE_SIZE); - lith->page2 = ioremap_nocache(baseaddr + LI_PAGE2_OFFSET, PAGE_SIZE); - if (!lith->page0 || !lith->page1 || !lith->page2) { - li_destroy(lith); - return -ENOMEM; - } - return 0; -} - -/* - * basic register accessors - read/write long/byte - */ - -static __inline__ unsigned long li_readl(lithium_t *lith, int off) -{ - return * (volatile unsigned long *) (lith->page0 + off); -} - -static __inline__ unsigned char li_readb(lithium_t *lith, int off) -{ - return * (volatile unsigned char *) (lith->page0 + off); -} - -static __inline__ void li_writel(lithium_t *lith, int off, unsigned long val) -{ - * (volatile unsigned long *) (lith->page0 + off) = val; -} - -static __inline__ void li_writeb(lithium_t *lith, int off, unsigned char val) -{ - * (volatile unsigned char *) (lith->page0 + off) = val; -} - -/*****************************************************************************/ -/* High Level Lithium Access */ - -/* - * Lithium DMA Notes - * - * Lithium has two dedicated DMA channels for audio. They are known - * as comm1 and comm2 (communication areas 1 and 2). Comm1 is for - * input, and comm2 is for output. Each is controlled by three - * registers: BASE (base address), CFG (config) and CCTL - * (config/control). - * - * Each DMA channel points to a physically contiguous ring buffer in - * main memory of up to 8 Kbytes. (This driver always uses 8 Kb.) - * There are three pointers into the ring buffer: read, write, and - * trigger. The pointers are 8 bits each. Each pointer points to - * 32-byte "chunks" of data. The DMA engine moves 32 bytes at a time, - * so there is no finer-granularity control. - * - * In comm1, the hardware updates the write ptr, and software updates - * the read ptr. In comm2, it's the opposite: hardware updates the - * read ptr, and software updates the write ptr. I designate the - * hardware-updated ptr as the hwptr, and the software-updated ptr as - * the swptr. - * - * The trigger ptr and trigger mask are used to trigger interrupts. - * From the Lithium spec, section 5.6.8, revision of 12/15/1998: - * - * Trigger Mask Value - * - * A three bit wide field that represents a power of two mask - * that is used whenever the trigger pointer is compared to its - * respective read or write pointer. A value of zero here - * implies a mask of 0xFF and a value of seven implies a mask - * 0x01. This value can be used to sub-divide the ring buffer - * into pie sections so that interrupts monitor the progress of - * hardware from section to section. - * - * My interpretation of that is, whenever the hw ptr is updated, it is - * compared with the trigger ptr, and the result is masked by the - * trigger mask. (Actually, by the complement of the trigger mask.) - * If the result is zero, an interrupt is triggered. I.e., interrupt - * if ((hwptr & ~mask) == (trptr & ~mask)). The mask is formed from - * the trigger register value as mask = (1 << (8 - tmreg)) - 1. - * - * In yet different words, setting tmreg to 0 causes an interrupt after - * every 256 DMA chunks (8192 bytes) or once per traversal of the - * ring buffer. Setting it to 7 caues an interrupt every 2 DMA chunks - * (64 bytes) or 128 times per traversal of the ring buffer. - */ - -/* Lithium register offsets and bit definitions */ - -#define LI_HOST_CONTROLLER 0x000 -# define LI_HC_RESET 0x00008000 -# define LI_HC_LINK_ENABLE 0x00004000 -# define LI_HC_LINK_FAILURE 0x00000004 -# define LI_HC_LINK_CODEC 0x00000002 -# define LI_HC_LINK_READY 0x00000001 - -#define LI_INTR_STATUS 0x010 -#define LI_INTR_MASK 0x014 -# define LI_INTR_LINK_ERR 0x00008000 -# define LI_INTR_COMM2_TRIG 0x00000008 -# define LI_INTR_COMM2_UNDERFLOW 0x00000004 -# define LI_INTR_COMM1_TRIG 0x00000002 -# define LI_INTR_COMM1_OVERFLOW 0x00000001 - -#define LI_CODEC_COMMAND 0x018 -# define LI_CC_BUSY 0x00008000 -# define LI_CC_DIR 0x00000080 -# define LI_CC_DIR_RD LI_CC_DIR -# define LI_CC_DIR_WR (!LI_CC_DIR) -# define LI_CC_ADDR_MASK 0x0000007F - -#define LI_CODEC_DATA 0x01C - -#define LI_COMM1_BASE 0x100 -#define LI_COMM1_CTL 0x104 -# define LI_CCTL_RESET 0x80000000 -# define LI_CCTL_SIZE 0x70000000 -# define LI_CCTL_DMA_ENABLE 0x08000000 -# define LI_CCTL_TMASK 0x07000000 /* trigger mask */ -# define LI_CCTL_TPTR 0x00FF0000 /* trigger pointer */ -# define LI_CCTL_RPTR 0x0000FF00 -# define LI_CCTL_WPTR 0x000000FF -#define LI_COMM1_CFG 0x108 -# define LI_CCFG_LOCK 0x00008000 -# define LI_CCFG_SLOT 0x00000070 -# define LI_CCFG_DIRECTION 0x00000008 -# define LI_CCFG_DIR_IN (!LI_CCFG_DIRECTION) -# define LI_CCFG_DIR_OUT LI_CCFG_DIRECTION -# define LI_CCFG_MODE 0x00000004 -# define LI_CCFG_MODE_MONO (!LI_CCFG_MODE) -# define LI_CCFG_MODE_STEREO LI_CCFG_MODE -# define LI_CCFG_FORMAT 0x00000003 -# define LI_CCFG_FMT_8BIT 0x00000000 -# define LI_CCFG_FMT_16BIT 0x00000001 -#define LI_COMM2_BASE 0x10C -#define LI_COMM2_CTL 0x110 - /* bit definitions are the same as LI_COMM1_CTL */ -#define LI_COMM2_CFG 0x114 - /* bit definitions are the same as LI_COMM1_CFG */ - -#define LI_UST_LOW 0x200 /* 64-bit Unadjusted System Time is */ -#define LI_UST_HIGH 0x204 /* microseconds since boot */ - -#define LI_AUDIO1_UST 0x300 /* UST-MSC pairs */ -#define LI_AUDIO1_MSC 0x304 /* MSC (Media Stream Counter) */ -#define LI_AUDIO2_UST 0x308 /* counts samples actually */ -#define LI_AUDIO2_MSC 0x30C /* processed as of time UST */ - -/* - * Lithium's DMA engine operates on chunks of 32 bytes. We call that - * a DMACHUNK. - */ - -#define DMACHUNK_SHIFT 5 -#define DMACHUNK_SIZE (1 << DMACHUNK_SHIFT) -#define BYTES_TO_CHUNKS(bytes) ((bytes) >> DMACHUNK_SHIFT) -#define CHUNKS_TO_BYTES(chunks) ((chunks) << DMACHUNK_SHIFT) - -/* - * Two convenient macros to shift bitfields into/out of position. - * - * Observe that (mask & -mask) is (1 << low_set_bit_of(mask)). - * As long as mask is constant, we trust the compiler will change the - * multipy and divide into shifts. - */ - -#define SHIFT_FIELD(val, mask) (((val) * ((mask) & -(mask))) & (mask)) -#define UNSHIFT_FIELD(val, mask) (((val) & (mask)) / ((mask) & -(mask))) - -/* - * dma_chan_desc is invariant information about a Lithium - * DMA channel. There are two instances, li_comm1 and li_comm2. - * - * Note that the CCTL register fields are write ptr and read ptr, but what - * we care about are which pointer is updated by software and which by - * hardware. - */ - -typedef struct dma_chan_desc { - int basereg; - int cfgreg; - int ctlreg; - int hwptrreg; - int swptrreg; - int ustreg; - int mscreg; - unsigned long swptrmask; - int ad1843_slot; - int direction; /* LI_CCTL_DIR_IN/OUT */ -} dma_chan_desc_t; - -static const dma_chan_desc_t li_comm1 = { - LI_COMM1_BASE, /* base register offset */ - LI_COMM1_CFG, /* config register offset */ - LI_COMM1_CTL, /* control register offset */ - LI_COMM1_CTL + 0, /* hw ptr reg offset (write ptr) */ - LI_COMM1_CTL + 1, /* sw ptr reg offset (read ptr) */ - LI_AUDIO1_UST, /* ust reg offset */ - LI_AUDIO1_MSC, /* msc reg offset */ - LI_CCTL_RPTR, /* sw ptr bitmask in ctlval */ - 2, /* ad1843 serial slot */ - LI_CCFG_DIR_IN /* direction */ -}; - -static const dma_chan_desc_t li_comm2 = { - LI_COMM2_BASE, /* base register offset */ - LI_COMM2_CFG, /* config register offset */ - LI_COMM2_CTL, /* control register offset */ - LI_COMM2_CTL + 1, /* hw ptr reg offset (read ptr) */ - LI_COMM2_CTL + 0, /* sw ptr reg offset (writr ptr) */ - LI_AUDIO2_UST, /* ust reg offset */ - LI_AUDIO2_MSC, /* msc reg offset */ - LI_CCTL_WPTR, /* sw ptr bitmask in ctlval */ - 2, /* ad1843 serial slot */ - LI_CCFG_DIR_OUT /* direction */ -}; - -/* - * dma_chan is variable information about a Lithium DMA channel. - * - * The desc field points to invariant information. - * The lith field points to a lithium_t which is passed - * to li_read* and li_write* to access the registers. - * The *val fields shadow the lithium registers' contents. - */ - -typedef struct dma_chan { - const dma_chan_desc_t *desc; - lithium_t *lith; - unsigned long baseval; - unsigned long cfgval; - unsigned long ctlval; -} dma_chan_t; - -/* - * ustmsc is a UST/MSC pair (Unadjusted System Time/Media Stream Counter). - * UST is time in microseconds since the system booted, and MSC is a - * counter that increments with every audio sample. - */ - -typedef struct ustmsc { - unsigned long long ust; - unsigned long msc; -} ustmsc_t; - -/* - * li_ad1843_wait waits until lithium says the AD1843 register - * exchange is not busy. Returns 0 on success, -EBUSY on timeout. - * - * Locking: must be called with lithium_lock held. - */ - -static int li_ad1843_wait(lithium_t *lith) -{ - unsigned long later = jiffies + 2; - while (li_readl(lith, LI_CODEC_COMMAND) & LI_CC_BUSY) - if (time_after_eq(jiffies, later)) - return -EBUSY; - return 0; -} - -/* - * li_read_ad1843_reg returns the current contents of a 16 bit AD1843 register. - * - * Returns unsigned register value on success, -errno on failure. - */ - -static int li_read_ad1843_reg(lithium_t *lith, int reg) -{ - int val; - - ASSERT(!in_interrupt()); - spin_lock(&lith->lock); - { - val = li_ad1843_wait(lith); - if (val == 0) { - li_writel(lith, LI_CODEC_COMMAND, LI_CC_DIR_RD | reg); - val = li_ad1843_wait(lith); - } - if (val == 0) - val = li_readl(lith, LI_CODEC_DATA); - } - spin_unlock(&lith->lock); - - DBGXV("li_read_ad1843_reg(lith=0x%p, reg=%d) returns 0x%04x\n", - lith, reg, val); - - return val; -} - -/* - * li_write_ad1843_reg writes the specified value to a 16 bit AD1843 register. - */ - -static void li_write_ad1843_reg(lithium_t *lith, int reg, int newval) -{ - spin_lock(&lith->lock); - { - if (li_ad1843_wait(lith) == 0) { - li_writel(lith, LI_CODEC_DATA, newval); - li_writel(lith, LI_CODEC_COMMAND, LI_CC_DIR_WR | reg); - } - } - spin_unlock(&lith->lock); -} - -/* - * li_setup_dma calculates all the register settings for DMA in a particular - * mode. It takes too many arguments. - */ - -static void li_setup_dma(dma_chan_t *chan, - const dma_chan_desc_t *desc, - lithium_t *lith, - unsigned long buffer_paddr, - int bufshift, - int fragshift, - int channels, - int sampsize) -{ - unsigned long mode, format; - unsigned long size, tmask; - - DBGEV("(chan=0x%p, desc=0x%p, lith=0x%p, buffer_paddr=0x%lx, " - "bufshift=%d, fragshift=%d, channels=%d, sampsize=%d)\n", - chan, desc, lith, buffer_paddr, - bufshift, fragshift, channels, sampsize); - - /* Reset the channel first. */ - - li_writel(lith, desc->ctlreg, LI_CCTL_RESET); - - ASSERT(channels == 1 || channels == 2); - if (channels == 2) - mode = LI_CCFG_MODE_STEREO; - else - mode = LI_CCFG_MODE_MONO; - ASSERT(sampsize == 1 || sampsize == 2); - if (sampsize == 2) - format = LI_CCFG_FMT_16BIT; - else - format = LI_CCFG_FMT_8BIT; - chan->desc = desc; - chan->lith = lith; - - /* - * Lithium DMA address register takes a 40-bit physical - * address, right-shifted by 8 so it fits in 32 bits. Bit 37 - * must be set -- it enables cache coherence. - */ - - ASSERT(!(buffer_paddr & 0xFF)); - chan->baseval = (buffer_paddr >> 8) | 1 << (37 - 8); - - chan->cfgval = ((chan->cfgval & ~LI_CCFG_LOCK) | - SHIFT_FIELD(desc->ad1843_slot, LI_CCFG_SLOT) | - desc->direction | - mode | - format); - - size = bufshift - 6; - tmask = 13 - fragshift; /* See Lithium DMA Notes above. */ - ASSERT(size >= 2 && size <= 7); - ASSERT(tmask >= 1 && tmask <= 7); - chan->ctlval = ((chan->ctlval & ~LI_CCTL_RESET) | - SHIFT_FIELD(size, LI_CCTL_SIZE) | - (chan->ctlval & ~LI_CCTL_DMA_ENABLE) | - SHIFT_FIELD(tmask, LI_CCTL_TMASK) | - SHIFT_FIELD(0, LI_CCTL_TPTR)); - - DBGPV("basereg 0x%x = 0x%lx\n", desc->basereg, chan->baseval); - DBGPV("cfgreg 0x%x = 0x%lx\n", desc->cfgreg, chan->cfgval); - DBGPV("ctlreg 0x%x = 0x%lx\n", desc->ctlreg, chan->ctlval); - - li_writel(lith, desc->basereg, chan->baseval); - li_writel(lith, desc->cfgreg, chan->cfgval); - li_writel(lith, desc->ctlreg, chan->ctlval); - - DBGRV(); -} - -static void li_shutdown_dma(dma_chan_t *chan) -{ - lithium_t *lith = chan->lith; - void * lith1 = lith->page1; - - DBGEV("(chan=0x%p)\n", chan); - - chan->ctlval &= ~LI_CCTL_DMA_ENABLE; - DBGPV("ctlreg 0x%x = 0x%lx\n", chan->desc->ctlreg, chan->ctlval); - li_writel(lith, chan->desc->ctlreg, chan->ctlval); - - /* - * Offset 0x500 on Lithium page 1 is an undocumented, - * unsupported register that holds the zero sample value. - * Lithium is supposed to output zero samples when DMA is - * inactive, and repeat the last sample when DMA underflows. - * But it has a bug, where, after underflow occurs, the zero - * sample is not reset. - * - * I expect this to break in a future rev of Lithium. - */ - - if (lith1 && chan->desc->direction == LI_CCFG_DIR_OUT) - * (volatile unsigned long *) (lith1 + 0x500) = 0; -} - -/* - * li_activate_dma always starts dma at the beginning of the buffer. - * - * N.B., these may be called from interrupt. - */ - -static __inline__ void li_activate_dma(dma_chan_t *chan) -{ - chan->ctlval |= LI_CCTL_DMA_ENABLE; - DBGPV("ctlval = 0x%lx\n", chan->ctlval); - li_writel(chan->lith, chan->desc->ctlreg, chan->ctlval); -} - -static void li_deactivate_dma(dma_chan_t *chan) -{ - lithium_t *lith = chan->lith; - void * lith2 = lith->page2; - - chan->ctlval &= ~(LI_CCTL_DMA_ENABLE | LI_CCTL_RPTR | LI_CCTL_WPTR); - DBGPV("ctlval = 0x%lx\n", chan->ctlval); - DBGPV("ctlreg 0x%x = 0x%lx\n", chan->desc->ctlreg, chan->ctlval); - li_writel(lith, chan->desc->ctlreg, chan->ctlval); - - /* - * Offsets 0x98 and 0x9C on Lithium page 2 are undocumented, - * unsupported registers that are internal copies of the DMA - * read and write pointers. Because of a Lithium bug, these - * registers aren't zeroed correctly when DMA is shut off. So - * we whack them directly. - * - * I expect this to break in a future rev of Lithium. - */ - - if (lith2 && chan->desc->direction == LI_CCFG_DIR_OUT) { - * (volatile unsigned long *) (lith2 + 0x98) = 0; - * (volatile unsigned long *) (lith2 + 0x9C) = 0; - } -} - -/* - * read/write the ring buffer pointers. These routines' arguments and results - * are byte offsets from the beginning of the ring buffer. - */ - -static __inline__ int li_read_swptr(dma_chan_t *chan) -{ - const unsigned long mask = chan->desc->swptrmask; - - return CHUNKS_TO_BYTES(UNSHIFT_FIELD(chan->ctlval, mask)); -} - -static __inline__ int li_read_hwptr(dma_chan_t *chan) -{ - return CHUNKS_TO_BYTES(li_readb(chan->lith, chan->desc->hwptrreg)); -} - -static __inline__ void li_write_swptr(dma_chan_t *chan, int val) -{ - const unsigned long mask = chan->desc->swptrmask; - - ASSERT(!(val & ~CHUNKS_TO_BYTES(0xFF))); - val = BYTES_TO_CHUNKS(val); - chan->ctlval = (chan->ctlval & ~mask) | SHIFT_FIELD(val, mask); - li_writeb(chan->lith, chan->desc->swptrreg, val); -} - -/* li_read_USTMSC() returns a UST/MSC pair for the given channel. */ - -static void li_read_USTMSC(dma_chan_t *chan, ustmsc_t *ustmsc) -{ - lithium_t *lith = chan->lith; - const dma_chan_desc_t *desc = chan->desc; - unsigned long now_low, now_high0, now_high1, chan_ust; - - spin_lock(&lith->lock); - { - /* - * retry until we do all five reads without the - * high word changing. (High word increments - * every 2^32 microseconds, i.e., not often) - */ - do { - now_high0 = li_readl(lith, LI_UST_HIGH); - now_low = li_readl(lith, LI_UST_LOW); - - /* - * Lithium guarantees these two reads will be - * atomic -- ust will not increment after msc - * is read. - */ - - ustmsc->msc = li_readl(lith, desc->mscreg); - chan_ust = li_readl(lith, desc->ustreg); - - now_high1 = li_readl(lith, LI_UST_HIGH); - } while (now_high0 != now_high1); - } - spin_unlock(&lith->lock); - ustmsc->ust = ((unsigned long long) now_high0 << 32 | chan_ust); -} - -static void li_enable_interrupts(lithium_t *lith, unsigned int mask) -{ - DBGEV("(lith=0x%p, mask=0x%x)\n", lith, mask); - - /* clear any already-pending interrupts. */ - - li_writel(lith, LI_INTR_STATUS, mask); - - /* enable the interrupts. */ - - mask |= li_readl(lith, LI_INTR_MASK); - li_writel(lith, LI_INTR_MASK, mask); -} - -static void li_disable_interrupts(lithium_t *lith, unsigned int mask) -{ - unsigned int keepmask; - - DBGEV("(lith=0x%p, mask=0x%x)\n", lith, mask); - - /* disable the interrupts */ - - keepmask = li_readl(lith, LI_INTR_MASK) & ~mask; - li_writel(lith, LI_INTR_MASK, keepmask); - - /* clear any pending interrupts. */ - - li_writel(lith, LI_INTR_STATUS, mask); -} - -/* Get the interrupt status and clear all pending interrupts. */ - -static unsigned int li_get_clear_intr_status(lithium_t *lith) -{ - unsigned int status; - - status = li_readl(lith, LI_INTR_STATUS); - li_writel(lith, LI_INTR_STATUS, ~0); - return status & li_readl(lith, LI_INTR_MASK); -} - -static int li_init(lithium_t *lith) -{ - /* 1. System power supplies stabilize. */ - - /* 2. Assert the ~RESET signal. */ - - li_writel(lith, LI_HOST_CONTROLLER, LI_HC_RESET); - udelay(1); - - /* 3. Deassert the ~RESET signal and enter a wait period to allow - the AD1843 internal clocks and the external crystal oscillator - to stabilize. */ - - li_writel(lith, LI_HOST_CONTROLLER, LI_HC_LINK_ENABLE); - udelay(1); - - return 0; -} - -/*****************************************************************************/ -/* AD1843 access */ - -/* - * AD1843 bitfield definitions. All are named as in the AD1843 data - * sheet, with ad1843_ prepended and individual bit numbers removed. - * - * E.g., bits LSS0 through LSS2 become ad1843_LSS. - * - * Only the bitfields we need are defined. - */ - -typedef struct ad1843_bitfield { - char reg; - char lo_bit; - char nbits; -} ad1843_bitfield_t; - -static const ad1843_bitfield_t - ad1843_PDNO = { 0, 14, 1 }, /* Converter Power-Down Flag */ - ad1843_INIT = { 0, 15, 1 }, /* Clock Initialization Flag */ - ad1843_RIG = { 2, 0, 4 }, /* Right ADC Input Gain */ - ad1843_RMGE = { 2, 4, 1 }, /* Right ADC Mic Gain Enable */ - ad1843_RSS = { 2, 5, 3 }, /* Right ADC Source Select */ - ad1843_LIG = { 2, 8, 4 }, /* Left ADC Input Gain */ - ad1843_LMGE = { 2, 12, 1 }, /* Left ADC Mic Gain Enable */ - ad1843_LSS = { 2, 13, 3 }, /* Left ADC Source Select */ - ad1843_RX1M = { 4, 0, 5 }, /* Right Aux 1 Mix Gain/Atten */ - ad1843_RX1MM = { 4, 7, 1 }, /* Right Aux 1 Mix Mute */ - ad1843_LX1M = { 4, 8, 5 }, /* Left Aux 1 Mix Gain/Atten */ - ad1843_LX1MM = { 4, 15, 1 }, /* Left Aux 1 Mix Mute */ - ad1843_RX2M = { 5, 0, 5 }, /* Right Aux 2 Mix Gain/Atten */ - ad1843_RX2MM = { 5, 7, 1 }, /* Right Aux 2 Mix Mute */ - ad1843_LX2M = { 5, 8, 5 }, /* Left Aux 2 Mix Gain/Atten */ - ad1843_LX2MM = { 5, 15, 1 }, /* Left Aux 2 Mix Mute */ - ad1843_RMCM = { 7, 0, 5 }, /* Right Mic Mix Gain/Atten */ - ad1843_RMCMM = { 7, 7, 1 }, /* Right Mic Mix Mute */ - ad1843_LMCM = { 7, 8, 5 }, /* Left Mic Mix Gain/Atten */ - ad1843_LMCMM = { 7, 15, 1 }, /* Left Mic Mix Mute */ - ad1843_HPOS = { 8, 4, 1 }, /* Headphone Output Voltage Swing */ - ad1843_HPOM = { 8, 5, 1 }, /* Headphone Output Mute */ - ad1843_RDA1G = { 9, 0, 6 }, /* Right DAC1 Analog/Digital Gain */ - ad1843_RDA1GM = { 9, 7, 1 }, /* Right DAC1 Analog Mute */ - ad1843_LDA1G = { 9, 8, 6 }, /* Left DAC1 Analog/Digital Gain */ - ad1843_LDA1GM = { 9, 15, 1 }, /* Left DAC1 Analog Mute */ - ad1843_RDA1AM = { 11, 7, 1 }, /* Right DAC1 Digital Mute */ - ad1843_LDA1AM = { 11, 15, 1 }, /* Left DAC1 Digital Mute */ - ad1843_ADLC = { 15, 0, 2 }, /* ADC Left Sample Rate Source */ - ad1843_ADRC = { 15, 2, 2 }, /* ADC Right Sample Rate Source */ - ad1843_DA1C = { 15, 8, 2 }, /* DAC1 Sample Rate Source */ - ad1843_C1C = { 17, 0, 16 }, /* Clock 1 Sample Rate Select */ - ad1843_C2C = { 20, 0, 16 }, /* Clock 1 Sample Rate Select */ - ad1843_DAADL = { 25, 4, 2 }, /* Digital ADC Left Source Select */ - ad1843_DAADR = { 25, 6, 2 }, /* Digital ADC Right Source Select */ - ad1843_DRSFLT = { 25, 15, 1 }, /* Digital Reampler Filter Mode */ - ad1843_ADLF = { 26, 0, 2 }, /* ADC Left Channel Data Format */ - ad1843_ADRF = { 26, 2, 2 }, /* ADC Right Channel Data Format */ - ad1843_ADTLK = { 26, 4, 1 }, /* ADC Transmit Lock Mode Select */ - ad1843_SCF = { 26, 7, 1 }, /* SCLK Frequency Select */ - ad1843_DA1F = { 26, 8, 2 }, /* DAC1 Data Format Select */ - ad1843_DA1SM = { 26, 14, 1 }, /* DAC1 Stereo/Mono Mode Select */ - ad1843_ADLEN = { 27, 0, 1 }, /* ADC Left Channel Enable */ - ad1843_ADREN = { 27, 1, 1 }, /* ADC Right Channel Enable */ - ad1843_AAMEN = { 27, 4, 1 }, /* Analog to Analog Mix Enable */ - ad1843_ANAEN = { 27, 7, 1 }, /* Analog Channel Enable */ - ad1843_DA1EN = { 27, 8, 1 }, /* DAC1 Enable */ - ad1843_DA2EN = { 27, 9, 1 }, /* DAC2 Enable */ - ad1843_C1EN = { 28, 11, 1 }, /* Clock Generator 1 Enable */ - ad1843_C2EN = { 28, 12, 1 }, /* Clock Generator 2 Enable */ - ad1843_PDNI = { 28, 15, 1 }; /* Converter Power Down */ - -/* - * The various registers of the AD1843 use three different formats for - * specifying gain. The ad1843_gain structure parameterizes the - * formats. - */ - -typedef struct ad1843_gain { - - int negative; /* nonzero if gain is negative. */ - const ad1843_bitfield_t *lfield; - const ad1843_bitfield_t *rfield; - -} ad1843_gain_t; - -static const ad1843_gain_t ad1843_gain_RECLEV - = { 0, &ad1843_LIG, &ad1843_RIG }; -static const ad1843_gain_t ad1843_gain_LINE - = { 1, &ad1843_LX1M, &ad1843_RX1M }; -static const ad1843_gain_t ad1843_gain_CD - = { 1, &ad1843_LX2M, &ad1843_RX2M }; -static const ad1843_gain_t ad1843_gain_MIC - = { 1, &ad1843_LMCM, &ad1843_RMCM }; -static const ad1843_gain_t ad1843_gain_PCM - = { 1, &ad1843_LDA1G, &ad1843_RDA1G }; - -/* read the current value of an AD1843 bitfield. */ - -static int ad1843_read_bits(lithium_t *lith, const ad1843_bitfield_t *field) -{ - int w = li_read_ad1843_reg(lith, field->reg); - int val = w >> field->lo_bit & ((1 << field->nbits) - 1); - - DBGXV("ad1843_read_bits(lith=0x%p, field->{%d %d %d}) returns 0x%x\n", - lith, field->reg, field->lo_bit, field->nbits, val); - - return val; -} - -/* - * write a new value to an AD1843 bitfield and return the old value. - */ - -static int ad1843_write_bits(lithium_t *lith, - const ad1843_bitfield_t *field, - int newval) -{ - int w = li_read_ad1843_reg(lith, field->reg); - int mask = ((1 << field->nbits) - 1) << field->lo_bit; - int oldval = (w & mask) >> field->lo_bit; - int newbits = (newval << field->lo_bit) & mask; - w = (w & ~mask) | newbits; - (void) li_write_ad1843_reg(lith, field->reg, w); - - DBGXV("ad1843_write_bits(lith=0x%p, field->{%d %d %d}, val=0x%x) " - "returns 0x%x\n", - lith, field->reg, field->lo_bit, field->nbits, newval, - oldval); - - return oldval; -} - -/* - * ad1843_read_multi reads multiple bitfields from the same AD1843 - * register. It uses a single read cycle to do it. (Reading the - * ad1843 requires 256 bit times at 12.288 MHz, or nearly 20 - * microseconds.) - * - * Called ike this. - * - * ad1843_read_multi(lith, nfields, - * &ad1843_FIELD1, &val1, - * &ad1843_FIELD2, &val2, ...); - */ - -static void ad1843_read_multi(lithium_t *lith, int argcount, ...) -{ - va_list ap; - const ad1843_bitfield_t *fp; - int w = 0, mask, *value, reg = -1; - - va_start(ap, argcount); - while (--argcount >= 0) { - fp = va_arg(ap, const ad1843_bitfield_t *); - value = va_arg(ap, int *); - if (reg == -1) { - reg = fp->reg; - w = li_read_ad1843_reg(lith, reg); - } - ASSERT(reg == fp->reg); - mask = (1 << fp->nbits) - 1; - *value = w >> fp->lo_bit & mask; - } - va_end(ap); -} - -/* - * ad1843_write_multi stores multiple bitfields into the same AD1843 - * register. It uses one read and one write cycle to do it. - * - * Called like this. - * - * ad1843_write_multi(lith, nfields, - * &ad1843_FIELD1, val1, - * &ad1843_FIELF2, val2, ...); - */ - -static void ad1843_write_multi(lithium_t *lith, int argcount, ...) -{ - va_list ap; - int reg; - const ad1843_bitfield_t *fp; - int value; - int w, m, mask, bits; - - mask = 0; - bits = 0; - reg = -1; - - va_start(ap, argcount); - while (--argcount >= 0) { - fp = va_arg(ap, const ad1843_bitfield_t *); - value = va_arg(ap, int); - if (reg == -1) - reg = fp->reg; - ASSERT(fp->reg == reg); - m = ((1 << fp->nbits) - 1) << fp->lo_bit; - mask |= m; - bits |= (value << fp->lo_bit) & m; - } - va_end(ap); - ASSERT(!(bits & ~mask)); - if (~mask & 0xFFFF) - w = li_read_ad1843_reg(lith, reg); - else - w = 0; - w = (w & ~mask) | bits; - (void) li_write_ad1843_reg(lith, reg, w); -} - -/* - * ad1843_get_gain reads the specified register and extracts the gain value - * using the supplied gain type. It returns the gain in OSS format. - */ - -static int ad1843_get_gain(lithium_t *lith, const ad1843_gain_t *gp) -{ - int lg, rg; - unsigned short mask = (1 << gp->lfield->nbits) - 1; - - ad1843_read_multi(lith, 2, gp->lfield, &lg, gp->rfield, &rg); - if (gp->negative) { - lg = mask - lg; - rg = mask - rg; - } - lg = (lg * 100 + (mask >> 1)) / mask; - rg = (rg * 100 + (mask >> 1)) / mask; - return lg << 0 | rg << 8; -} - -/* - * Set an audio channel's gain. Converts from OSS format to AD1843's - * format. - * - * Returns the new gain, which may be lower than the old gain. - */ - -static int ad1843_set_gain(lithium_t *lith, - const ad1843_gain_t *gp, - int newval) -{ - unsigned short mask = (1 << gp->lfield->nbits) - 1; - - int lg = newval >> 0 & 0xFF; - int rg = newval >> 8; - if (lg < 0 || lg > 100 || rg < 0 || rg > 100) - return -EINVAL; - lg = (lg * mask + (mask >> 1)) / 100; - rg = (rg * mask + (mask >> 1)) / 100; - if (gp->negative) { - lg = mask - lg; - rg = mask - rg; - } - ad1843_write_multi(lith, 2, gp->lfield, lg, gp->rfield, rg); - return ad1843_get_gain(lith, gp); -} - -/* Returns the current recording source, in OSS format. */ - -static int ad1843_get_recsrc(lithium_t *lith) -{ - int ls = ad1843_read_bits(lith, &ad1843_LSS); - - switch (ls) { - case 1: - return SOUND_MASK_MIC; - case 2: - return SOUND_MASK_LINE; - case 3: - return SOUND_MASK_CD; - case 6: - return SOUND_MASK_PCM; - default: - ASSERT(0); - return -1; - } -} - -/* - * Enable/disable digital resample mode in the AD1843. - * - * The AD1843 requires that ADL, ADR, DA1 and DA2 be powered down - * while switching modes. So we save DA1's state (DA2's state is not - * interesting), power them down, switch into/out of resample mode, - * power them up, and restore state. - * - * This will cause audible glitches if D/A or A/D is going on, so the - * driver disallows that (in mixer_write_ioctl()). - * - * The open question is, is this worth doing? I'm leaving it in, - * because it's written, but... - */ - -static void ad1843_set_resample_mode(lithium_t *lith, int onoff) -{ - /* Save DA1 mute and gain (addr 9 is DA1 analog gain/attenuation) */ - int save_da1 = li_read_ad1843_reg(lith, 9); - - /* Power down A/D and D/A. */ - ad1843_write_multi(lith, 4, - &ad1843_DA1EN, 0, - &ad1843_DA2EN, 0, - &ad1843_ADLEN, 0, - &ad1843_ADREN, 0); - - /* Switch mode */ - ASSERT(onoff == 0 || onoff == 1); - ad1843_write_bits(lith, &ad1843_DRSFLT, onoff); - - /* Power up A/D and D/A. */ - ad1843_write_multi(lith, 3, - &ad1843_DA1EN, 1, - &ad1843_ADLEN, 1, - &ad1843_ADREN, 1); - - /* Restore DA1 mute and gain. */ - li_write_ad1843_reg(lith, 9, save_da1); -} - -/* - * Set recording source. Arg newsrc specifies an OSS channel mask. - * - * The complication is that when we switch into/out of loopback mode - * (i.e., src = SOUND_MASK_PCM), we change the AD1843 into/out of - * digital resampling mode. - * - * Returns newsrc on success, -errno on failure. - */ - -static int ad1843_set_recsrc(lithium_t *lith, int newsrc) -{ - int bits; - int oldbits; - - switch (newsrc) { - case SOUND_MASK_PCM: - bits = 6; - break; - - case SOUND_MASK_MIC: - bits = 1; - break; - - case SOUND_MASK_LINE: - bits = 2; - break; - - case SOUND_MASK_CD: - bits = 3; - break; - - default: - return -EINVAL; - } - oldbits = ad1843_read_bits(lith, &ad1843_LSS); - if (newsrc == SOUND_MASK_PCM && oldbits != 6) { - DBGP("enabling digital resample mode\n"); - ad1843_set_resample_mode(lith, 1); - ad1843_write_multi(lith, 2, - &ad1843_DAADL, 2, - &ad1843_DAADR, 2); - } else if (newsrc != SOUND_MASK_PCM && oldbits == 6) { - DBGP("disabling digital resample mode\n"); - ad1843_set_resample_mode(lith, 0); - ad1843_write_multi(lith, 2, - &ad1843_DAADL, 0, - &ad1843_DAADR, 0); - } - ad1843_write_multi(lith, 2, &ad1843_LSS, bits, &ad1843_RSS, bits); - return newsrc; -} - -/* - * Return current output sources, in OSS format. - */ - -static int ad1843_get_outsrc(lithium_t *lith) -{ - int pcm, line, mic, cd; - - pcm = ad1843_read_bits(lith, &ad1843_LDA1GM) ? 0 : SOUND_MASK_PCM; - line = ad1843_read_bits(lith, &ad1843_LX1MM) ? 0 : SOUND_MASK_LINE; - cd = ad1843_read_bits(lith, &ad1843_LX2MM) ? 0 : SOUND_MASK_CD; - mic = ad1843_read_bits(lith, &ad1843_LMCMM) ? 0 : SOUND_MASK_MIC; - - return pcm | line | cd | mic; -} - -/* - * Set output sources. Arg is a mask of active sources in OSS format. - * - * Returns source mask on success, -errno on failure. - */ - -static int ad1843_set_outsrc(lithium_t *lith, int mask) -{ - int pcm, line, mic, cd; - - if (mask & ~(SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_CD | SOUND_MASK_MIC)) - return -EINVAL; - pcm = (mask & SOUND_MASK_PCM) ? 0 : 1; - line = (mask & SOUND_MASK_LINE) ? 0 : 1; - mic = (mask & SOUND_MASK_MIC) ? 0 : 1; - cd = (mask & SOUND_MASK_CD) ? 0 : 1; - - ad1843_write_multi(lith, 2, &ad1843_LDA1GM, pcm, &ad1843_RDA1GM, pcm); - ad1843_write_multi(lith, 2, &ad1843_LX1MM, line, &ad1843_RX1MM, line); - ad1843_write_multi(lith, 2, &ad1843_LX2MM, cd, &ad1843_RX2MM, cd); - ad1843_write_multi(lith, 2, &ad1843_LMCMM, mic, &ad1843_RMCMM, mic); - - return mask; -} - -/* Setup ad1843 for D/A conversion. */ - -static void ad1843_setup_dac(lithium_t *lith, - int framerate, - int fmt, - int channels) -{ - int ad_fmt = 0, ad_mode = 0; - - DBGEV("(lith=0x%p, framerate=%d, fmt=%d, channels=%d)\n", - lith, framerate, fmt, channels); - - switch (fmt) { - case AFMT_S8: ad_fmt = 1; break; - case AFMT_U8: ad_fmt = 1; break; - case AFMT_S16_LE: ad_fmt = 1; break; - case AFMT_MU_LAW: ad_fmt = 2; break; - case AFMT_A_LAW: ad_fmt = 3; break; - default: ASSERT(0); - } - - switch (channels) { - case 2: ad_mode = 0; break; - case 1: ad_mode = 1; break; - default: ASSERT(0); - } - - DBGPV("ad_mode = %d, ad_fmt = %d\n", ad_mode, ad_fmt); - ASSERT(framerate >= 4000 && framerate <= 49000); - ad1843_write_bits(lith, &ad1843_C1C, framerate); - ad1843_write_multi(lith, 2, - &ad1843_DA1SM, ad_mode, &ad1843_DA1F, ad_fmt); -} - -static void ad1843_shutdown_dac(lithium_t *lith) -{ - ad1843_write_bits(lith, &ad1843_DA1F, 1); -} - -static void ad1843_setup_adc(lithium_t *lith, int framerate, int fmt, int channels) -{ - int da_fmt = 0; - - DBGEV("(lith=0x%p, framerate=%d, fmt=%d, channels=%d)\n", - lith, framerate, fmt, channels); - - switch (fmt) { - case AFMT_S8: da_fmt = 1; break; - case AFMT_U8: da_fmt = 1; break; - case AFMT_S16_LE: da_fmt = 1; break; - case AFMT_MU_LAW: da_fmt = 2; break; - case AFMT_A_LAW: da_fmt = 3; break; - default: ASSERT(0); - } - - DBGPV("da_fmt = %d\n", da_fmt); - ASSERT(framerate >= 4000 && framerate <= 49000); - ad1843_write_bits(lith, &ad1843_C2C, framerate); - ad1843_write_multi(lith, 2, - &ad1843_ADLF, da_fmt, &ad1843_ADRF, da_fmt); -} - -static void ad1843_shutdown_adc(lithium_t *lith) -{ - /* nothing to do */ -} - -/* - * Fully initialize the ad1843. As described in the AD1843 data - * sheet, section "START-UP SEQUENCE". The numbered comments are - * subsection headings from the data sheet. See the data sheet, pages - * 52-54, for more info. - * - * return 0 on success, -errno on failure. */ - -static int __init ad1843_init(lithium_t *lith) -{ - unsigned long later; - int err; - - err = li_init(lith); - if (err) - return err; - - if (ad1843_read_bits(lith, &ad1843_INIT) != 0) { - printk(KERN_ERR "vwsnd sound: AD1843 won't initialize\n"); - return -EIO; - } - - ad1843_write_bits(lith, &ad1843_SCF, 1); - - /* 4. Put the conversion resources into standby. */ - - ad1843_write_bits(lith, &ad1843_PDNI, 0); - later = jiffies + HZ / 2; /* roughly half a second */ - DBGDO(shut_up++); - while (ad1843_read_bits(lith, &ad1843_PDNO)) { - if (time_after(jiffies, later)) { - printk(KERN_ERR - "vwsnd audio: AD1843 won't power up\n"); - return -EIO; - } - schedule(); - } - DBGDO(shut_up--); - - /* 5. Power up the clock generators and enable clock output pins. */ - - ad1843_write_multi(lith, 2, &ad1843_C1EN, 1, &ad1843_C2EN, 1); - - /* 6. Configure conversion resources while they are in standby. */ - - /* DAC1 uses clock 1 as source, ADC uses clock 2. Always. */ - - ad1843_write_multi(lith, 3, - &ad1843_DA1C, 1, - &ad1843_ADLC, 2, - &ad1843_ADRC, 2); - - /* 7. Enable conversion resources. */ - - ad1843_write_bits(lith, &ad1843_ADTLK, 1); - ad1843_write_multi(lith, 5, - &ad1843_ANAEN, 1, - &ad1843_AAMEN, 1, - &ad1843_DA1EN, 1, - &ad1843_ADLEN, 1, - &ad1843_ADREN, 1); - - /* 8. Configure conversion resources while they are enabled. */ - - ad1843_write_bits(lith, &ad1843_DA1C, 1); - - /* Unmute all channels. */ - - ad1843_set_outsrc(lith, - (SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_MIC | SOUND_MASK_CD)); - ad1843_write_multi(lith, 2, &ad1843_LDA1AM, 0, &ad1843_RDA1AM, 0); - - /* Set default recording source to Line In and set - * mic gain to +20 dB. - */ - - ad1843_set_recsrc(lith, SOUND_MASK_LINE); - ad1843_write_multi(lith, 2, &ad1843_LMGE, 1, &ad1843_RMGE, 1); - - /* Set Speaker Out level to +/- 4V and unmute it. */ - - ad1843_write_multi(lith, 2, &ad1843_HPOS, 1, &ad1843_HPOM, 0); - - return 0; -} - -/*****************************************************************************/ -/* PCM I/O */ - -#define READ_INTR_MASK (LI_INTR_COMM1_TRIG | LI_INTR_COMM1_OVERFLOW) -#define WRITE_INTR_MASK (LI_INTR_COMM2_TRIG | LI_INTR_COMM2_UNDERFLOW) - -typedef enum vwsnd_port_swstate { /* software state */ - SW_OFF, - SW_INITIAL, - SW_RUN, - SW_DRAIN, -} vwsnd_port_swstate_t; - -typedef enum vwsnd_port_hwstate { /* hardware state */ - HW_STOPPED, - HW_RUNNING, -} vwsnd_port_hwstate_t; - -/* - * These flags are read by ISR, but only written at baseline. - */ - -typedef enum vwsnd_port_flags { - DISABLED = 1 << 0, - ERFLOWN = 1 << 1, /* overflown or underflown */ - HW_BUSY = 1 << 2, -} vwsnd_port_flags_t; - -/* - * vwsnd_port is the per-port data structure. Each device has two - * ports, one for input and one for output. - * - * Locking: - * - * port->lock protects: hwstate, flags, swb_[iu]_avail. - * - * devc->io_mutex protects: swstate, sw_*, swb_[iu]_idx. - * - * everything else is only written by open/release or - * pcm_{setup,shutdown}(), which are serialized by a - * combination of devc->open_mutex and devc->io_mutex. - */ - -typedef struct vwsnd_port { - - spinlock_t lock; - wait_queue_head_t queue; - vwsnd_port_swstate_t swstate; - vwsnd_port_hwstate_t hwstate; - vwsnd_port_flags_t flags; - - int sw_channels; - int sw_samplefmt; - int sw_framerate; - int sample_size; - int frame_size; - unsigned int zero_word; /* zero for the sample format */ - - int sw_fragshift; - int sw_fragcount; - int sw_subdivshift; - - unsigned int hw_fragshift; - unsigned int hw_fragsize; - unsigned int hw_fragcount; - - int hwbuf_size; - unsigned long hwbuf_paddr; - unsigned long hwbuf_vaddr; - void * hwbuf; /* hwbuf == hwbuf_vaddr */ - int hwbuf_max; /* max bytes to preload */ - - void * swbuf; - unsigned int swbuf_size; /* size in bytes */ - unsigned int swb_u_idx; /* index of next user byte */ - unsigned int swb_i_idx; /* index of next intr byte */ - unsigned int swb_u_avail; /* # bytes avail to user */ - unsigned int swb_i_avail; /* # bytes avail to intr */ - - dma_chan_t chan; - - /* Accounting */ - - int byte_count; - int frag_count; - int MSC_offset; - -} vwsnd_port_t; - -/* vwsnd_dev is the per-device data structure. */ - -typedef struct vwsnd_dev { - struct vwsnd_dev *next_dev; - int audio_minor; /* minor number of audio device */ - int mixer_minor; /* minor number of mixer device */ - - struct mutex open_mutex; - struct mutex io_mutex; - struct mutex mix_mutex; - fmode_t open_mode; - wait_queue_head_t open_wait; - - lithium_t lith; - - vwsnd_port_t rport; - vwsnd_port_t wport; -} vwsnd_dev_t; - -static vwsnd_dev_t *vwsnd_dev_list; /* linked list of all devices */ - -static atomic_t vwsnd_use_count = ATOMIC_INIT(0); - -# define INC_USE_COUNT (atomic_inc(&vwsnd_use_count)) -# define DEC_USE_COUNT (atomic_dec(&vwsnd_use_count)) -# define IN_USE (atomic_read(&vwsnd_use_count) != 0) - -/* - * Lithium can only DMA multiples of 32 bytes. Its DMA buffer may - * be up to 8 Kb. This driver always uses 8 Kb. - * - * Memory bug workaround -- I'm not sure what's going on here, but - * somehow pcm_copy_out() was triggering segv's going on to the next - * page of the hw buffer. So, I make the hw buffer one size bigger - * than we actually use. That way, the following page is allocated - * and mapped, and no error. I suspect that something is broken - * in Cobalt, but haven't really investigated. HBO is the actual - * size of the buffer, and HWBUF_ORDER is what we allocate. - */ - -#define HWBUF_SHIFT 13 -#define HWBUF_SIZE (1 << HWBUF_SHIFT) -# define HBO (HWBUF_SHIFT > PAGE_SHIFT ? HWBUF_SHIFT - PAGE_SHIFT : 0) -# define HWBUF_ORDER (HBO + 1) /* next size bigger */ -#define MIN_SPEED 4000 -#define MAX_SPEED 49000 - -#define MIN_FRAGSHIFT (DMACHUNK_SHIFT + 1) -#define MAX_FRAGSHIFT (PAGE_SHIFT) -#define MIN_FRAGSIZE (1 << MIN_FRAGSHIFT) -#define MAX_FRAGSIZE (1 << MAX_FRAGSHIFT) -#define MIN_FRAGCOUNT(fragsize) 3 -#define MAX_FRAGCOUNT(fragsize) (32 * PAGE_SIZE / (fragsize)) -#define DEFAULT_FRAGSHIFT 12 -#define DEFAULT_FRAGCOUNT 16 -#define DEFAULT_SUBDIVSHIFT 0 - -/* - * The software buffer (swbuf) is a ring buffer shared between user - * level and interrupt level. Each level owns some of the bytes in - * the buffer, and may give bytes away by calling swb_inc_{u,i}(). - * User level calls _u for user, and interrupt level calls _i for - * interrupt. - * - * port->swb_{u,i}_avail is the number of bytes available to that level. - * - * port->swb_{u,i}_idx is the index of the first available byte in the - * buffer. - * - * Each level calls swb_inc_{u,i}() to atomically increment its index, - * recalculate the number of bytes available for both sides, and - * return the number of bytes available. Since each side can only - * give away bytes, the other side can only increase the number of - * bytes available to this side. Each side updates its own index - * variable, swb_{u,i}_idx, so no lock is needed to read it. - * - * To query the number of bytes available, call swb_inc_{u,i} with an - * increment of zero. - */ - -static __inline__ unsigned int __swb_inc_u(vwsnd_port_t *port, int inc) -{ - if (inc) { - port->swb_u_idx += inc; - port->swb_u_idx %= port->swbuf_size; - port->swb_u_avail -= inc; - port->swb_i_avail += inc; - } - return port->swb_u_avail; -} - -static __inline__ unsigned int swb_inc_u(vwsnd_port_t *port, int inc) -{ - unsigned long flags; - unsigned int ret; - - spin_lock_irqsave(&port->lock, flags); - { - ret = __swb_inc_u(port, inc); - } - spin_unlock_irqrestore(&port->lock, flags); - return ret; -} - -static __inline__ unsigned int __swb_inc_i(vwsnd_port_t *port, int inc) -{ - if (inc) { - port->swb_i_idx += inc; - port->swb_i_idx %= port->swbuf_size; - port->swb_i_avail -= inc; - port->swb_u_avail += inc; - } - return port->swb_i_avail; -} - -static __inline__ unsigned int swb_inc_i(vwsnd_port_t *port, int inc) -{ - unsigned long flags; - unsigned int ret; - - spin_lock_irqsave(&port->lock, flags); - { - ret = __swb_inc_i(port, inc); - } - spin_unlock_irqrestore(&port->lock, flags); - return ret; -} - -/* - * pcm_setup - this routine initializes all port state after - * mode-setting ioctls have been done, but before the first I/O is - * done. - * - * Locking: called with devc->io_mutex held. - * - * Returns 0 on success, -errno on failure. - */ - -static int pcm_setup(vwsnd_dev_t *devc, - vwsnd_port_t *rport, - vwsnd_port_t *wport) -{ - vwsnd_port_t *aport = rport ? rport : wport; - int sample_size; - unsigned int zero_word; - - DBGEV("(devc=0x%p, rport=0x%p, wport=0x%p)\n", devc, rport, wport); - - ASSERT(aport != NULL); - if (aport->swbuf != NULL) - return 0; - switch (aport->sw_samplefmt) { - case AFMT_MU_LAW: - sample_size = 1; - zero_word = 0xFFFFFFFF ^ 0x80808080; - break; - - case AFMT_A_LAW: - sample_size = 1; - zero_word = 0xD5D5D5D5 ^ 0x80808080; - break; - - case AFMT_U8: - sample_size = 1; - zero_word = 0x80808080; - break; - - case AFMT_S8: - sample_size = 1; - zero_word = 0x00000000; - break; - - case AFMT_S16_LE: - sample_size = 2; - zero_word = 0x00000000; - break; - - default: - sample_size = 0; /* prevent compiler warning */ - zero_word = 0; - ASSERT(0); - } - aport->sample_size = sample_size; - aport->zero_word = zero_word; - aport->frame_size = aport->sw_channels * aport->sample_size; - aport->hw_fragshift = aport->sw_fragshift - aport->sw_subdivshift; - aport->hw_fragsize = 1 << aport->hw_fragshift; - aport->hw_fragcount = aport->sw_fragcount << aport->sw_subdivshift; - ASSERT(aport->hw_fragsize >= MIN_FRAGSIZE); - ASSERT(aport->hw_fragsize <= MAX_FRAGSIZE); - ASSERT(aport->hw_fragcount >= MIN_FRAGCOUNT(aport->hw_fragsize)); - ASSERT(aport->hw_fragcount <= MAX_FRAGCOUNT(aport->hw_fragsize)); - if (rport) { - int hwfrags, swfrags; - rport->hwbuf_max = aport->hwbuf_size - DMACHUNK_SIZE; - hwfrags = rport->hwbuf_max >> aport->hw_fragshift; - swfrags = aport->hw_fragcount - hwfrags; - if (swfrags < 2) - swfrags = 2; - rport->swbuf_size = swfrags * aport->hw_fragsize; - DBGPV("hwfrags = %d, swfrags = %d\n", hwfrags, swfrags); - DBGPV("read hwbuf_max = %d, swbuf_size = %d\n", - rport->hwbuf_max, rport->swbuf_size); - } - if (wport) { - int hwfrags, swfrags; - int total_bytes = aport->hw_fragcount * aport->hw_fragsize; - wport->hwbuf_max = aport->hwbuf_size - DMACHUNK_SIZE; - if (wport->hwbuf_max > total_bytes) - wport->hwbuf_max = total_bytes; - hwfrags = wport->hwbuf_max >> aport->hw_fragshift; - DBGPV("hwfrags = %d\n", hwfrags); - swfrags = aport->hw_fragcount - hwfrags; - if (swfrags < 2) - swfrags = 2; - wport->swbuf_size = swfrags * aport->hw_fragsize; - DBGPV("hwfrags = %d, swfrags = %d\n", hwfrags, swfrags); - DBGPV("write hwbuf_max = %d, swbuf_size = %d\n", - wport->hwbuf_max, wport->swbuf_size); - } - - aport->swb_u_idx = 0; - aport->swb_i_idx = 0; - aport->byte_count = 0; - - /* - * Is this a Cobalt bug? We need to make this buffer extend - * one page further than we actually use -- somehow memcpy - * causes an exceptoin otherwise. I suspect there's a bug in - * Cobalt (or somewhere) where it's generating a fault on a - * speculative load or something. Obviously, I haven't taken - * the time to track it down. - */ - - aport->swbuf = vmalloc(aport->swbuf_size + PAGE_SIZE); - if (!aport->swbuf) - return -ENOMEM; - if (rport && wport) { - ASSERT(aport == rport); - ASSERT(wport->swbuf == NULL); - /* One extra page - see comment above. */ - wport->swbuf = vmalloc(aport->swbuf_size + PAGE_SIZE); - if (!wport->swbuf) { - vfree(aport->swbuf); - aport->swbuf = NULL; - return -ENOMEM; - } - wport->sample_size = rport->sample_size; - wport->zero_word = rport->zero_word; - wport->frame_size = rport->frame_size; - wport->hw_fragshift = rport->hw_fragshift; - wport->hw_fragsize = rport->hw_fragsize; - wport->hw_fragcount = rport->hw_fragcount; - wport->swbuf_size = rport->swbuf_size; - wport->hwbuf_max = rport->hwbuf_max; - wport->swb_u_idx = rport->swb_u_idx; - wport->swb_i_idx = rport->swb_i_idx; - wport->byte_count = rport->byte_count; - } - if (rport) { - rport->swb_u_avail = 0; - rport->swb_i_avail = rport->swbuf_size; - rport->swstate = SW_RUN; - li_setup_dma(&rport->chan, - &li_comm1, - &devc->lith, - rport->hwbuf_paddr, - HWBUF_SHIFT, - rport->hw_fragshift, - rport->sw_channels, - rport->sample_size); - ad1843_setup_adc(&devc->lith, - rport->sw_framerate, - rport->sw_samplefmt, - rport->sw_channels); - li_enable_interrupts(&devc->lith, READ_INTR_MASK); - if (!(rport->flags & DISABLED)) { - ustmsc_t ustmsc; - rport->hwstate = HW_RUNNING; - li_activate_dma(&rport->chan); - li_read_USTMSC(&rport->chan, &ustmsc); - rport->MSC_offset = ustmsc.msc; - } - } - if (wport) { - if (wport->hwbuf_max > wport->swbuf_size) - wport->hwbuf_max = wport->swbuf_size; - wport->flags &= ~ERFLOWN; - wport->swb_u_avail = wport->swbuf_size; - wport->swb_i_avail = 0; - wport->swstate = SW_RUN; - li_setup_dma(&wport->chan, - &li_comm2, - &devc->lith, - wport->hwbuf_paddr, - HWBUF_SHIFT, - wport->hw_fragshift, - wport->sw_channels, - wport->sample_size); - ad1843_setup_dac(&devc->lith, - wport->sw_framerate, - wport->sw_samplefmt, - wport->sw_channels); - li_enable_interrupts(&devc->lith, WRITE_INTR_MASK); - } - DBGRV(); - return 0; -} - -/* - * pcm_shutdown_port - shut down one port (direction) for PCM I/O. - * Only called from pcm_shutdown. - */ - -static void pcm_shutdown_port(vwsnd_dev_t *devc, - vwsnd_port_t *aport, - unsigned int mask) -{ - unsigned long flags; - vwsnd_port_hwstate_t hwstate; - DECLARE_WAITQUEUE(wait, current); - - aport->swstate = SW_INITIAL; - add_wait_queue(&aport->queue, &wait); - while (1) { - set_current_state(TASK_UNINTERRUPTIBLE); - spin_lock_irqsave(&aport->lock, flags); - { - hwstate = aport->hwstate; - } - spin_unlock_irqrestore(&aport->lock, flags); - if (hwstate == HW_STOPPED) - break; - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&aport->queue, &wait); - li_disable_interrupts(&devc->lith, mask); - if (aport == &devc->rport) - ad1843_shutdown_adc(&devc->lith); - else /* aport == &devc->wport) */ - ad1843_shutdown_dac(&devc->lith); - li_shutdown_dma(&aport->chan); - vfree(aport->swbuf); - aport->swbuf = NULL; - aport->byte_count = 0; -} - -/* - * pcm_shutdown undoes what pcm_setup did. - * Also sets the ports' swstate to newstate. - */ - -static void pcm_shutdown(vwsnd_dev_t *devc, - vwsnd_port_t *rport, - vwsnd_port_t *wport) -{ - DBGEV("(devc=0x%p, rport=0x%p, wport=0x%p)\n", devc, rport, wport); - - if (rport && rport->swbuf) { - DBGPV("shutting down rport\n"); - pcm_shutdown_port(devc, rport, READ_INTR_MASK); - } - if (wport && wport->swbuf) { - DBGPV("shutting down wport\n"); - pcm_shutdown_port(devc, wport, WRITE_INTR_MASK); - } - DBGRV(); -} - -static void pcm_copy_in(vwsnd_port_t *rport, int swidx, int hwidx, int nb) -{ - char *src = rport->hwbuf + hwidx; - char *dst = rport->swbuf + swidx; - int fmt = rport->sw_samplefmt; - - DBGPV("swidx = %d, hwidx = %d\n", swidx, hwidx); - ASSERT(rport->hwbuf != NULL); - ASSERT(rport->swbuf != NULL); - ASSERT(nb > 0 && (nb % 32) == 0); - ASSERT(swidx % 32 == 0 && hwidx % 32 == 0); - ASSERT(swidx >= 0 && swidx + nb <= rport->swbuf_size); - ASSERT(hwidx >= 0 && hwidx + nb <= rport->hwbuf_size); - - if (fmt == AFMT_MU_LAW || fmt == AFMT_A_LAW || fmt == AFMT_S8) { - - /* See Sample Format Notes above. */ - - char *end = src + nb; - while (src < end) - *dst++ = *src++ ^ 0x80; - } else - memcpy(dst, src, nb); -} - -static void pcm_copy_out(vwsnd_port_t *wport, int swidx, int hwidx, int nb) -{ - char *src = wport->swbuf + swidx; - char *dst = wport->hwbuf + hwidx; - int fmt = wport->sw_samplefmt; - - ASSERT(nb > 0 && (nb % 32) == 0); - ASSERT(wport->hwbuf != NULL); - ASSERT(wport->swbuf != NULL); - ASSERT(swidx % 32 == 0 && hwidx % 32 == 0); - ASSERT(swidx >= 0 && swidx + nb <= wport->swbuf_size); - ASSERT(hwidx >= 0 && hwidx + nb <= wport->hwbuf_size); - if (fmt == AFMT_MU_LAW || fmt == AFMT_A_LAW || fmt == AFMT_S8) { - - /* See Sample Format Notes above. */ - - char *end = src + nb; - while (src < end) - *dst++ = *src++ ^ 0x80; - } else - memcpy(dst, src, nb); -} - -/* - * pcm_output() is called both from baselevel and from interrupt level. - * This is where audio frames are copied into the hardware-accessible - * ring buffer. - * - * Locking note: The part of this routine that figures out what to do - * holds wport->lock. The longer part releases wport->lock, but sets - * wport->flags & HW_BUSY. Afterward, it reacquires wport->lock, and - * checks for more work to do. - * - * If another thread calls pcm_output() while HW_BUSY is set, it - * returns immediately, knowing that the thread that set HW_BUSY will - * look for more work to do before returning. - * - * This has the advantage that port->lock is held for several short - * periods instead of one long period. Also, when pcm_output is - * called from base level, it reenables interrupts. - */ - -static void pcm_output(vwsnd_dev_t *devc, int erflown, int nb) -{ - vwsnd_port_t *wport = &devc->wport; - const int hwmax = wport->hwbuf_max; - const int hwsize = wport->hwbuf_size; - const int swsize = wport->swbuf_size; - const int fragsize = wport->hw_fragsize; - unsigned long iflags; - - DBGEV("(devc=0x%p, erflown=%d, nb=%d)\n", devc, erflown, nb); - spin_lock_irqsave(&wport->lock, iflags); - if (erflown) - wport->flags |= ERFLOWN; - (void) __swb_inc_u(wport, nb); - if (wport->flags & HW_BUSY) { - spin_unlock_irqrestore(&wport->lock, iflags); - DBGPV("returning: HW BUSY\n"); - return; - } - if (wport->flags & DISABLED) { - spin_unlock_irqrestore(&wport->lock, iflags); - DBGPV("returning: DISABLED\n"); - return; - } - wport->flags |= HW_BUSY; - while (1) { - int swptr, hwptr, hw_avail, sw_avail, swidx; - vwsnd_port_hwstate_t hwstate = wport->hwstate; - vwsnd_port_swstate_t swstate = wport->swstate; - int hw_unavail; - ustmsc_t ustmsc; - - hwptr = li_read_hwptr(&wport->chan); - swptr = li_read_swptr(&wport->chan); - hw_unavail = (swptr - hwptr + hwsize) % hwsize; - hw_avail = (hwmax - hw_unavail) & -fragsize; - sw_avail = wport->swb_i_avail & -fragsize; - if (sw_avail && swstate == SW_RUN) { - if (wport->flags & ERFLOWN) { - wport->flags &= ~ERFLOWN; - } - } else if (swstate == SW_INITIAL || - swstate == SW_OFF || - (swstate == SW_DRAIN && - !sw_avail && - (wport->flags & ERFLOWN))) { - DBGP("stopping. hwstate = %d\n", hwstate); - if (hwstate != HW_STOPPED) { - li_deactivate_dma(&wport->chan); - wport->hwstate = HW_STOPPED; - } - wake_up(&wport->queue); - break; - } - if (!sw_avail || !hw_avail) - break; - spin_unlock_irqrestore(&wport->lock, iflags); - - /* - * We gave up the port lock, but we have the HW_BUSY flag. - * Proceed without accessing any nonlocal state. - * Do not exit the loop -- must check for more work. - */ - - swidx = wport->swb_i_idx; - nb = hw_avail; - if (nb > sw_avail) - nb = sw_avail; - if (nb > hwsize - swptr) - nb = hwsize - swptr; /* don't overflow hwbuf */ - if (nb > swsize - swidx) - nb = swsize - swidx; /* don't overflow swbuf */ - ASSERT(nb > 0); - if (nb % fragsize) { - DBGP("nb = %d, fragsize = %d\n", nb, fragsize); - DBGP("hw_avail = %d\n", hw_avail); - DBGP("sw_avail = %d\n", sw_avail); - DBGP("hwsize = %d, swptr = %d\n", hwsize, swptr); - DBGP("swsize = %d, swidx = %d\n", swsize, swidx); - } - ASSERT(!(nb % fragsize)); - DBGPV("copying swb[%d..%d] to hwb[%d..%d]\n", - swidx, swidx + nb, swptr, swptr + nb); - pcm_copy_out(wport, swidx, swptr, nb); - li_write_swptr(&wport->chan, (swptr + nb) % hwsize); - spin_lock_irqsave(&wport->lock, iflags); - if (hwstate == HW_STOPPED) { - DBGPV("starting\n"); - li_activate_dma(&wport->chan); - wport->hwstate = HW_RUNNING; - li_read_USTMSC(&wport->chan, &ustmsc); - ASSERT(wport->byte_count % wport->frame_size == 0); - wport->MSC_offset = ustmsc.msc - wport->byte_count / wport->frame_size; - } - __swb_inc_i(wport, nb); - wport->byte_count += nb; - wport->frag_count += nb / fragsize; - ASSERT(nb % fragsize == 0); - wake_up(&wport->queue); - } - wport->flags &= ~HW_BUSY; - spin_unlock_irqrestore(&wport->lock, iflags); - DBGRV(); -} - -/* - * pcm_input() is called both from baselevel and from interrupt level. - * This is where audio frames are copied out of the hardware-accessible - * ring buffer. - * - * Locking note: The part of this routine that figures out what to do - * holds rport->lock. The longer part releases rport->lock, but sets - * rport->flags & HW_BUSY. Afterward, it reacquires rport->lock, and - * checks for more work to do. - * - * If another thread calls pcm_input() while HW_BUSY is set, it - * returns immediately, knowing that the thread that set HW_BUSY will - * look for more work to do before returning. - * - * This has the advantage that port->lock is held for several short - * periods instead of one long period. Also, when pcm_input is - * called from base level, it reenables interrupts. - */ - -static void pcm_input(vwsnd_dev_t *devc, int erflown, int nb) -{ - vwsnd_port_t *rport = &devc->rport; - const int hwmax = rport->hwbuf_max; - const int hwsize = rport->hwbuf_size; - const int swsize = rport->swbuf_size; - const int fragsize = rport->hw_fragsize; - unsigned long iflags; - - DBGEV("(devc=0x%p, erflown=%d, nb=%d)\n", devc, erflown, nb); - - spin_lock_irqsave(&rport->lock, iflags); - if (erflown) - rport->flags |= ERFLOWN; - (void) __swb_inc_u(rport, nb); - if (rport->flags & HW_BUSY || !rport->swbuf) { - spin_unlock_irqrestore(&rport->lock, iflags); - DBGPV("returning: HW BUSY or !swbuf\n"); - return; - } - if (rport->flags & DISABLED) { - spin_unlock_irqrestore(&rport->lock, iflags); - DBGPV("returning: DISABLED\n"); - return; - } - rport->flags |= HW_BUSY; - while (1) { - int swptr, hwptr, hw_avail, sw_avail, swidx; - vwsnd_port_hwstate_t hwstate = rport->hwstate; - vwsnd_port_swstate_t swstate = rport->swstate; - - hwptr = li_read_hwptr(&rport->chan); - swptr = li_read_swptr(&rport->chan); - hw_avail = (hwptr - swptr + hwsize) % hwsize & -fragsize; - if (hw_avail > hwmax) - hw_avail = hwmax; - sw_avail = rport->swb_i_avail & -fragsize; - if (swstate != SW_RUN) { - DBGP("stopping. hwstate = %d\n", hwstate); - if (hwstate != HW_STOPPED) { - li_deactivate_dma(&rport->chan); - rport->hwstate = HW_STOPPED; - } - wake_up(&rport->queue); - break; - } - if (!sw_avail || !hw_avail) - break; - spin_unlock_irqrestore(&rport->lock, iflags); - - /* - * We gave up the port lock, but we have the HW_BUSY flag. - * Proceed without accessing any nonlocal state. - * Do not exit the loop -- must check for more work. - */ - - swidx = rport->swb_i_idx; - nb = hw_avail; - if (nb > sw_avail) - nb = sw_avail; - if (nb > hwsize - swptr) - nb = hwsize - swptr; /* don't overflow hwbuf */ - if (nb > swsize - swidx) - nb = swsize - swidx; /* don't overflow swbuf */ - ASSERT(nb > 0); - if (nb % fragsize) { - DBGP("nb = %d, fragsize = %d\n", nb, fragsize); - DBGP("hw_avail = %d\n", hw_avail); - DBGP("sw_avail = %d\n", sw_avail); - DBGP("hwsize = %d, swptr = %d\n", hwsize, swptr); - DBGP("swsize = %d, swidx = %d\n", swsize, swidx); - } - ASSERT(!(nb % fragsize)); - DBGPV("copying hwb[%d..%d] to swb[%d..%d]\n", - swptr, swptr + nb, swidx, swidx + nb); - pcm_copy_in(rport, swidx, swptr, nb); - li_write_swptr(&rport->chan, (swptr + nb) % hwsize); - spin_lock_irqsave(&rport->lock, iflags); - __swb_inc_i(rport, nb); - rport->byte_count += nb; - rport->frag_count += nb / fragsize; - ASSERT(nb % fragsize == 0); - wake_up(&rport->queue); - } - rport->flags &= ~HW_BUSY; - spin_unlock_irqrestore(&rport->lock, iflags); - DBGRV(); -} - -/* - * pcm_flush_frag() writes zero samples to fill the current fragment, - * then flushes it to the hardware. - * - * It is only meaningful to flush output, not input. - */ - -static void pcm_flush_frag(vwsnd_dev_t *devc) -{ - vwsnd_port_t *wport = &devc->wport; - - DBGPV("swstate = %d\n", wport->swstate); - if (wport->swstate == SW_RUN) { - int idx = wport->swb_u_idx; - int end = (idx + wport->hw_fragsize - 1) - >> wport->hw_fragshift - << wport->hw_fragshift; - int nb = end - idx; - DBGPV("clearing %d bytes\n", nb); - if (nb) - memset(wport->swbuf + idx, - (char) wport->zero_word, - nb); - wport->swstate = SW_DRAIN; - pcm_output(devc, 0, nb); - } - DBGRV(); -} - -/* - * Wait for output to drain. This sleeps uninterruptibly because - * there is nothing intelligent we can do if interrupted. This - * means the process will be delayed in responding to the signal. - */ - -static void pcm_write_sync(vwsnd_dev_t *devc) -{ - vwsnd_port_t *wport = &devc->wport; - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - vwsnd_port_hwstate_t hwstate; - - DBGEV("(devc=0x%p)\n", devc); - add_wait_queue(&wport->queue, &wait); - while (1) { - set_current_state(TASK_UNINTERRUPTIBLE); - spin_lock_irqsave(&wport->lock, flags); - { - hwstate = wport->hwstate; - } - spin_unlock_irqrestore(&wport->lock, flags); - if (hwstate == HW_STOPPED) - break; - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&wport->queue, &wait); - DBGPV("swstate = %d, hwstate = %d\n", wport->swstate, wport->hwstate); - DBGRV(); -} - -/*****************************************************************************/ -/* audio driver */ - -/* - * seek on an audio device always fails. - */ - -static void vwsnd_audio_read_intr(vwsnd_dev_t *devc, unsigned int status) -{ - int overflown = status & LI_INTR_COMM1_OVERFLOW; - - if (status & READ_INTR_MASK) - pcm_input(devc, overflown, 0); -} - -static void vwsnd_audio_write_intr(vwsnd_dev_t *devc, unsigned int status) -{ - int underflown = status & LI_INTR_COMM2_UNDERFLOW; - - if (status & WRITE_INTR_MASK) - pcm_output(devc, underflown, 0); -} - -static irqreturn_t vwsnd_audio_intr(int irq, void *dev_id) -{ - vwsnd_dev_t *devc = dev_id; - unsigned int status; - - DBGEV("(irq=%d, dev_id=0x%p)\n", irq, dev_id); - - status = li_get_clear_intr_status(&devc->lith); - vwsnd_audio_read_intr(devc, status); - vwsnd_audio_write_intr(devc, status); - return IRQ_HANDLED; -} - -static ssize_t vwsnd_audio_do_read(struct file *file, - char *buffer, - size_t count, - loff_t *ppos) -{ - vwsnd_dev_t *devc = file->private_data; - vwsnd_port_t *rport = ((file->f_mode & FMODE_READ) ? - &devc->rport : NULL); - int ret, nb; - - DBGEV("(file=0x%p, buffer=0x%p, count=%d, ppos=0x%p)\n", - file, buffer, count, ppos); - - if (!rport) - return -EINVAL; - - if (rport->swbuf == NULL) { - vwsnd_port_t *wport = (file->f_mode & FMODE_WRITE) ? - &devc->wport : NULL; - ret = pcm_setup(devc, rport, wport); - if (ret < 0) - return ret; - } - - if (!access_ok(VERIFY_READ, buffer, count)) - return -EFAULT; - ret = 0; - while (count) { - DECLARE_WAITQUEUE(wait, current); - add_wait_queue(&rport->queue, &wait); - while ((nb = swb_inc_u(rport, 0)) == 0) { - DBGPV("blocking\n"); - set_current_state(TASK_INTERRUPTIBLE); - if (rport->flags & DISABLED || - file->f_flags & O_NONBLOCK) { - current->state = TASK_RUNNING; - remove_wait_queue(&rport->queue, &wait); - return ret ? ret : -EAGAIN; - } - schedule(); - if (signal_pending(current)) { - current->state = TASK_RUNNING; - remove_wait_queue(&rport->queue, &wait); - return ret ? ret : -ERESTARTSYS; - } - } - current->state = TASK_RUNNING; - remove_wait_queue(&rport->queue, &wait); - pcm_input(devc, 0, 0); - /* nb bytes are available in userbuf. */ - if (nb > count) - nb = count; - DBGPV("nb = %d\n", nb); - if (copy_to_user(buffer, rport->swbuf + rport->swb_u_idx, nb)) - return -EFAULT; - (void) swb_inc_u(rport, nb); - buffer += nb; - count -= nb; - ret += nb; - } - DBGPV("returning %d\n", ret); - return ret; -} - -static ssize_t vwsnd_audio_read(struct file *file, - char *buffer, - size_t count, - loff_t *ppos) -{ - vwsnd_dev_t *devc = file->private_data; - ssize_t ret; - - mutex_lock(&devc->io_mutex); - ret = vwsnd_audio_do_read(file, buffer, count, ppos); - mutex_unlock(&devc->io_mutex); - return ret; -} - -static ssize_t vwsnd_audio_do_write(struct file *file, - const char *buffer, - size_t count, - loff_t *ppos) -{ - vwsnd_dev_t *devc = file->private_data; - vwsnd_port_t *wport = ((file->f_mode & FMODE_WRITE) ? - &devc->wport : NULL); - int ret, nb; - - DBGEV("(file=0x%p, buffer=0x%p, count=%d, ppos=0x%p)\n", - file, buffer, count, ppos); - - if (!wport) - return -EINVAL; - - if (wport->swbuf == NULL) { - vwsnd_port_t *rport = (file->f_mode & FMODE_READ) ? - &devc->rport : NULL; - ret = pcm_setup(devc, rport, wport); - if (ret < 0) - return ret; - } - if (!access_ok(VERIFY_WRITE, buffer, count)) - return -EFAULT; - ret = 0; - while (count) { - DECLARE_WAITQUEUE(wait, current); - add_wait_queue(&wport->queue, &wait); - while ((nb = swb_inc_u(wport, 0)) == 0) { - set_current_state(TASK_INTERRUPTIBLE); - if (wport->flags & DISABLED || - file->f_flags & O_NONBLOCK) { - current->state = TASK_RUNNING; - remove_wait_queue(&wport->queue, &wait); - return ret ? ret : -EAGAIN; - } - schedule(); - if (signal_pending(current)) { - current->state = TASK_RUNNING; - remove_wait_queue(&wport->queue, &wait); - return ret ? ret : -ERESTARTSYS; - } - } - current->state = TASK_RUNNING; - remove_wait_queue(&wport->queue, &wait); - /* nb bytes are available in userbuf. */ - if (nb > count) - nb = count; - DBGPV("nb = %d\n", nb); - if (copy_from_user(wport->swbuf + wport->swb_u_idx, buffer, nb)) - return -EFAULT; - pcm_output(devc, 0, nb); - buffer += nb; - count -= nb; - ret += nb; - } - DBGPV("returning %d\n", ret); - return ret; -} - -static ssize_t vwsnd_audio_write(struct file *file, - const char *buffer, - size_t count, - loff_t *ppos) -{ - vwsnd_dev_t *devc = file->private_data; - ssize_t ret; - - mutex_lock(&devc->io_mutex); - ret = vwsnd_audio_do_write(file, buffer, count, ppos); - mutex_unlock(&devc->io_mutex); - return ret; -} - -/* No kernel lock - fine */ -static unsigned int vwsnd_audio_poll(struct file *file, - struct poll_table_struct *wait) -{ - vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data; - vwsnd_port_t *rport = (file->f_mode & FMODE_READ) ? - &devc->rport : NULL; - vwsnd_port_t *wport = (file->f_mode & FMODE_WRITE) ? - &devc->wport : NULL; - unsigned int mask = 0; - - DBGEV("(file=0x%p, wait=0x%p)\n", file, wait); - - ASSERT(rport || wport); - if (rport) { - poll_wait(file, &rport->queue, wait); - if (swb_inc_u(rport, 0)) - mask |= (POLLIN | POLLRDNORM); - } - if (wport) { - poll_wait(file, &wport->queue, wait); - if (wport->swbuf == NULL || swb_inc_u(wport, 0)) - mask |= (POLLOUT | POLLWRNORM); - } - - DBGPV("returning 0x%x\n", mask); - return mask; -} - -static int vwsnd_audio_do_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) -{ - vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data; - vwsnd_port_t *rport = (file->f_mode & FMODE_READ) ? - &devc->rport : NULL; - vwsnd_port_t *wport = (file->f_mode & FMODE_WRITE) ? - &devc->wport : NULL; - vwsnd_port_t *aport = rport ? rport : wport; - struct audio_buf_info buf_info; - struct count_info info; - unsigned long flags; - int ival; - - - DBGEV("(file=0x%p, cmd=0x%x, arg=0x%lx)\n", - file, cmd, arg); - switch (cmd) { - case OSS_GETVERSION: /* _SIOR ('M', 118, int) */ - DBGX("OSS_GETVERSION\n"); - ival = SOUND_VERSION; - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_GETCAPS: /* _SIOR ('P',15, int) */ - DBGX("SNDCTL_DSP_GETCAPS\n"); - ival = DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER; - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_GETFMTS: /* _SIOR ('P',11, int) */ - DBGX("SNDCTL_DSP_GETFMTS\n"); - ival = (AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | - AFMT_U8 | AFMT_S8); - return put_user(ival, (int *) arg); - break; - - case SOUND_PCM_READ_RATE: /* _SIOR ('P', 2, int) */ - DBGX("SOUND_PCM_READ_RATE\n"); - ival = aport->sw_framerate; - return put_user(ival, (int *) arg); - - case SOUND_PCM_READ_CHANNELS: /* _SIOR ('P', 6, int) */ - DBGX("SOUND_PCM_READ_CHANNELS\n"); - ival = aport->sw_channels; - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_SPEED: /* _SIOWR('P', 2, int) */ - if (get_user(ival, (int *) arg)) - return -EFAULT; - DBGX("SNDCTL_DSP_SPEED %d\n", ival); - if (ival) { - if (aport->swstate != SW_INITIAL) { - DBGX("SNDCTL_DSP_SPEED failed: swstate = %d\n", - aport->swstate); - return -EINVAL; - } - if (ival < MIN_SPEED) - ival = MIN_SPEED; - if (ival > MAX_SPEED) - ival = MAX_SPEED; - if (rport) - rport->sw_framerate = ival; - if (wport) - wport->sw_framerate = ival; - } else - ival = aport->sw_framerate; - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_STEREO: /* _SIOWR('P', 3, int) */ - if (get_user(ival, (int *) arg)) - return -EFAULT; - DBGX("SNDCTL_DSP_STEREO %d\n", ival); - if (ival != 0 && ival != 1) - return -EINVAL; - if (aport->swstate != SW_INITIAL) - return -EINVAL; - if (rport) - rport->sw_channels = ival + 1; - if (wport) - wport->sw_channels = ival + 1; - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_CHANNELS: /* _SIOWR('P', 6, int) */ - if (get_user(ival, (int *) arg)) - return -EFAULT; - DBGX("SNDCTL_DSP_CHANNELS %d\n", ival); - if (ival != 1 && ival != 2) - return -EINVAL; - if (aport->swstate != SW_INITIAL) - return -EINVAL; - if (rport) - rport->sw_channels = ival; - if (wport) - wport->sw_channels = ival; - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_GETBLKSIZE: /* _SIOWR('P', 4, int) */ - ival = pcm_setup(devc, rport, wport); - if (ival < 0) { - DBGX("SNDCTL_DSP_GETBLKSIZE failed, errno %d\n", ival); - return ival; - } - ival = 1 << aport->sw_fragshift; - DBGX("SNDCTL_DSP_GETBLKSIZE returning %d\n", ival); - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_SETFRAGMENT: /* _SIOWR('P',10, int) */ - if (get_user(ival, (int *) arg)) - return -EFAULT; - DBGX("SNDCTL_DSP_SETFRAGMENT %d:%d\n", - ival >> 16, ival & 0xFFFF); - if (aport->swstate != SW_INITIAL) - return -EINVAL; - { - int sw_fragshift = ival & 0xFFFF; - int sw_subdivshift = aport->sw_subdivshift; - int hw_fragshift = sw_fragshift - sw_subdivshift; - int sw_fragcount = (ival >> 16) & 0xFFFF; - int hw_fragsize; - if (hw_fragshift < MIN_FRAGSHIFT) - hw_fragshift = MIN_FRAGSHIFT; - if (hw_fragshift > MAX_FRAGSHIFT) - hw_fragshift = MAX_FRAGSHIFT; - sw_fragshift = hw_fragshift + aport->sw_subdivshift; - hw_fragsize = 1 << hw_fragshift; - if (sw_fragcount < MIN_FRAGCOUNT(hw_fragsize)) - sw_fragcount = MIN_FRAGCOUNT(hw_fragsize); - if (sw_fragcount > MAX_FRAGCOUNT(hw_fragsize)) - sw_fragcount = MAX_FRAGCOUNT(hw_fragsize); - DBGPV("sw_fragshift = %d\n", sw_fragshift); - DBGPV("rport = 0x%p, wport = 0x%p\n", rport, wport); - if (rport) { - rport->sw_fragshift = sw_fragshift; - rport->sw_fragcount = sw_fragcount; - } - if (wport) { - wport->sw_fragshift = sw_fragshift; - wport->sw_fragcount = sw_fragcount; - } - ival = sw_fragcount << 16 | sw_fragshift; - } - DBGX("SNDCTL_DSP_SETFRAGMENT returns %d:%d\n", - ival >> 16, ival & 0xFFFF); - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_SUBDIVIDE: /* _SIOWR('P', 9, int) */ - if (get_user(ival, (int *) arg)) - return -EFAULT; - DBGX("SNDCTL_DSP_SUBDIVIDE %d\n", ival); - if (aport->swstate != SW_INITIAL) - return -EINVAL; - { - int subdivshift; - int hw_fragshift, hw_fragsize, hw_fragcount; - switch (ival) { - case 1: subdivshift = 0; break; - case 2: subdivshift = 1; break; - case 4: subdivshift = 2; break; - default: return -EINVAL; - } - hw_fragshift = aport->sw_fragshift - subdivshift; - if (hw_fragshift < MIN_FRAGSHIFT || - hw_fragshift > MAX_FRAGSHIFT) - return -EINVAL; - hw_fragsize = 1 << hw_fragshift; - hw_fragcount = aport->sw_fragcount >> subdivshift; - if (hw_fragcount < MIN_FRAGCOUNT(hw_fragsize) || - hw_fragcount > MAX_FRAGCOUNT(hw_fragsize)) - return -EINVAL; - if (rport) - rport->sw_subdivshift = subdivshift; - if (wport) - wport->sw_subdivshift = subdivshift; - } - return 0; - - case SNDCTL_DSP_SETFMT: /* _SIOWR('P',5, int) */ - if (get_user(ival, (int *) arg)) - return -EFAULT; - DBGX("SNDCTL_DSP_SETFMT %d\n", ival); - if (ival != AFMT_QUERY) { - if (aport->swstate != SW_INITIAL) { - DBGP("SETFMT failed, swstate = %d\n", - aport->swstate); - return -EINVAL; - } - switch (ival) { - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - case AFMT_S16_LE: - if (rport) - rport->sw_samplefmt = ival; - if (wport) - wport->sw_samplefmt = ival; - break; - default: - return -EINVAL; - } - } - ival = aport->sw_samplefmt; - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_GETOSPACE: /* _SIOR ('P',12, audio_buf_info) */ - DBGXV("SNDCTL_DSP_GETOSPACE\n"); - if (!wport) - return -EINVAL; - ival = pcm_setup(devc, rport, wport); - if (ival < 0) - return ival; - ival = swb_inc_u(wport, 0); - buf_info.fragments = ival >> wport->sw_fragshift; - buf_info.fragstotal = wport->sw_fragcount; - buf_info.fragsize = 1 << wport->sw_fragshift; - buf_info.bytes = ival; - DBGXV("SNDCTL_DSP_GETOSPACE returns { %d %d %d %d }\n", - buf_info.fragments, buf_info.fragstotal, - buf_info.fragsize, buf_info.bytes); - if (copy_to_user((void *) arg, &buf_info, sizeof buf_info)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_GETISPACE: /* _SIOR ('P',13, audio_buf_info) */ - DBGX("SNDCTL_DSP_GETISPACE\n"); - if (!rport) - return -EINVAL; - ival = pcm_setup(devc, rport, wport); - if (ival < 0) - return ival; - ival = swb_inc_u(rport, 0); - buf_info.fragments = ival >> rport->sw_fragshift; - buf_info.fragstotal = rport->sw_fragcount; - buf_info.fragsize = 1 << rport->sw_fragshift; - buf_info.bytes = ival; - DBGX("SNDCTL_DSP_GETISPACE returns { %d %d %d %d }\n", - buf_info.fragments, buf_info.fragstotal, - buf_info.fragsize, buf_info.bytes); - if (copy_to_user((void *) arg, &buf_info, sizeof buf_info)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_NONBLOCK: /* _SIO ('P',14) */ - DBGX("SNDCTL_DSP_NONBLOCK\n"); - spin_lock(&file->f_lock); - file->f_flags |= O_NONBLOCK; - spin_unlock(&file->f_lock); - return 0; - - case SNDCTL_DSP_RESET: /* _SIO ('P', 0) */ - DBGX("SNDCTL_DSP_RESET\n"); - /* - * Nothing special needs to be done for input. Input - * samples sit in swbuf, but it will be reinitialized - * to empty when pcm_setup() is called. - */ - if (wport && wport->swbuf) { - wport->swstate = SW_INITIAL; - pcm_output(devc, 0, 0); - pcm_write_sync(devc); - } - pcm_shutdown(devc, rport, wport); - return 0; - - case SNDCTL_DSP_SYNC: /* _SIO ('P', 1) */ - DBGX("SNDCTL_DSP_SYNC\n"); - if (wport) { - pcm_flush_frag(devc); - pcm_write_sync(devc); - } - pcm_shutdown(devc, rport, wport); - return 0; - - case SNDCTL_DSP_POST: /* _SIO ('P', 8) */ - DBGX("SNDCTL_DSP_POST\n"); - if (!wport) - return -EINVAL; - pcm_flush_frag(devc); - return 0; - - case SNDCTL_DSP_GETIPTR: /* _SIOR ('P', 17, count_info) */ - DBGX("SNDCTL_DSP_GETIPTR\n"); - if (!rport) - return -EINVAL; - spin_lock_irqsave(&rport->lock, flags); - { - ustmsc_t ustmsc; - if (rport->hwstate == HW_RUNNING) { - ASSERT(rport->swstate == SW_RUN); - li_read_USTMSC(&rport->chan, &ustmsc); - info.bytes = ustmsc.msc - rport->MSC_offset; - info.bytes *= rport->frame_size; - } else { - info.bytes = rport->byte_count; - } - info.blocks = rport->frag_count; - info.ptr = 0; /* not implemented */ - rport->frag_count = 0; - } - spin_unlock_irqrestore(&rport->lock, flags); - if (copy_to_user((void *) arg, &info, sizeof info)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_GETOPTR: /* _SIOR ('P',18, count_info) */ - DBGX("SNDCTL_DSP_GETOPTR\n"); - if (!wport) - return -EINVAL; - spin_lock_irqsave(&wport->lock, flags); - { - ustmsc_t ustmsc; - if (wport->hwstate == HW_RUNNING) { - ASSERT(wport->swstate == SW_RUN); - li_read_USTMSC(&wport->chan, &ustmsc); - info.bytes = ustmsc.msc - wport->MSC_offset; - info.bytes *= wport->frame_size; - } else { - info.bytes = wport->byte_count; - } - info.blocks = wport->frag_count; - info.ptr = 0; /* not implemented */ - wport->frag_count = 0; - } - spin_unlock_irqrestore(&wport->lock, flags); - if (copy_to_user((void *) arg, &info, sizeof info)) - return -EFAULT; - return 0; - - case SNDCTL_DSP_GETODELAY: /* _SIOR ('P', 23, int) */ - DBGX("SNDCTL_DSP_GETODELAY\n"); - if (!wport) - return -EINVAL; - spin_lock_irqsave(&wport->lock, flags); - { - int fsize = wport->frame_size; - ival = wport->swb_i_avail / fsize; - if (wport->hwstate == HW_RUNNING) { - int swptr, hwptr, hwframes, hwbytes, hwsize; - int totalhwbytes; - ustmsc_t ustmsc; - - hwsize = wport->hwbuf_size; - swptr = li_read_swptr(&wport->chan); - li_read_USTMSC(&wport->chan, &ustmsc); - hwframes = ustmsc.msc - wport->MSC_offset; - totalhwbytes = hwframes * fsize; - hwptr = totalhwbytes % hwsize; - hwbytes = (swptr - hwptr + hwsize) % hwsize; - ival += hwbytes / fsize; - } - } - spin_unlock_irqrestore(&wport->lock, flags); - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_PROFILE: /* _SIOW ('P', 23, int) */ - DBGX("SNDCTL_DSP_PROFILE\n"); - - /* - * Thomas Sailer explains SNDCTL_DSP_PROFILE - * (private email, March 24, 1999): - * - * This gives the sound driver a hint on what it - * should do with partial fragments - * (i.e. fragments partially filled with write). - * This can direct the driver to zero them or - * leave them alone. But don't ask me what this - * is good for, my driver just zeroes the last - * fragment before the receiver stops, no idea - * what good for any other behaviour could - * be. Implementing it as NOP seems safe. - */ - - break; - - case SNDCTL_DSP_GETTRIGGER: /* _SIOR ('P',16, int) */ - DBGX("SNDCTL_DSP_GETTRIGGER\n"); - ival = 0; - if (rport) { - spin_lock_irqsave(&rport->lock, flags); - { - if (!(rport->flags & DISABLED)) - ival |= PCM_ENABLE_INPUT; - } - spin_unlock_irqrestore(&rport->lock, flags); - } - if (wport) { - spin_lock_irqsave(&wport->lock, flags); - { - if (!(wport->flags & DISABLED)) - ival |= PCM_ENABLE_OUTPUT; - } - spin_unlock_irqrestore(&wport->lock, flags); - } - return put_user(ival, (int *) arg); - - case SNDCTL_DSP_SETTRIGGER: /* _SIOW ('P',16, int) */ - if (get_user(ival, (int *) arg)) - return -EFAULT; - DBGX("SNDCTL_DSP_SETTRIGGER %d\n", ival); - - /* - * If user is disabling I/O and port is not in initial - * state, fail with EINVAL. - */ - - if (((rport && !(ival & PCM_ENABLE_INPUT)) || - (wport && !(ival & PCM_ENABLE_OUTPUT))) && - aport->swstate != SW_INITIAL) - return -EINVAL; - - if (rport) { - vwsnd_port_hwstate_t hwstate; - spin_lock_irqsave(&rport->lock, flags); - { - hwstate = rport->hwstate; - if (ival & PCM_ENABLE_INPUT) - rport->flags &= ~DISABLED; - else - rport->flags |= DISABLED; - } - spin_unlock_irqrestore(&rport->lock, flags); - if (hwstate != HW_RUNNING && ival & PCM_ENABLE_INPUT) { - - if (rport->swstate == SW_INITIAL) - pcm_setup(devc, rport, wport); - else - li_activate_dma(&rport->chan); - } - } - if (wport) { - vwsnd_port_flags_t pflags; - spin_lock_irqsave(&wport->lock, flags); - { - pflags = wport->flags; - if (ival & PCM_ENABLE_OUTPUT) - wport->flags &= ~DISABLED; - else - wport->flags |= DISABLED; - } - spin_unlock_irqrestore(&wport->lock, flags); - if (pflags & DISABLED && ival & PCM_ENABLE_OUTPUT) { - if (wport->swstate == SW_RUN) - pcm_output(devc, 0, 0); - } - } - return 0; - - default: - DBGP("unknown ioctl 0x%x\n", cmd); - return -EINVAL; - } - DBGP("unimplemented ioctl 0x%x\n", cmd); - return -EINVAL; -} - -static long vwsnd_audio_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) -{ - vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data; - int ret; - - mutex_lock(&vwsnd_mutex); - mutex_lock(&devc->io_mutex); - ret = vwsnd_audio_do_ioctl(file, cmd, arg); - mutex_unlock(&devc->io_mutex); - mutex_unlock(&vwsnd_mutex); - - return ret; -} - -/* No mmap. */ - -static int vwsnd_audio_mmap(struct file *file, struct vm_area_struct *vma) -{ - DBGE("(file=0x%p, vma=0x%p)\n", file, vma); - return -ENODEV; -} - -/* - * Open the audio device for read and/or write. - * - * Returns 0 on success, -errno on failure. - */ - -static int vwsnd_audio_open(struct inode *inode, struct file *file) -{ - vwsnd_dev_t *devc; - int minor = iminor(inode); - int sw_samplefmt; - - DBGE("(inode=0x%p, file=0x%p)\n", inode, file); - - mutex_lock(&vwsnd_mutex); - INC_USE_COUNT; - for (devc = vwsnd_dev_list; devc; devc = devc->next_dev) - if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F)) - break; - - if (devc == NULL) { - DEC_USE_COUNT; - mutex_unlock(&vwsnd_mutex); - return -ENODEV; - } - - mutex_lock(&devc->open_mutex); - while (devc->open_mode & file->f_mode) { - mutex_unlock(&devc->open_mutex); - if (file->f_flags & O_NONBLOCK) { - DEC_USE_COUNT; - mutex_unlock(&vwsnd_mutex); - return -EBUSY; - } - interruptible_sleep_on(&devc->open_wait); - if (signal_pending(current)) { - DEC_USE_COUNT; - mutex_unlock(&vwsnd_mutex); - return -ERESTARTSYS; - } - mutex_lock(&devc->open_mutex); - } - devc->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - mutex_unlock(&devc->open_mutex); - - /* get default sample format from minor number. */ - - sw_samplefmt = 0; - if ((minor & 0xF) == SND_DEV_DSP) - sw_samplefmt = AFMT_U8; - else if ((minor & 0xF) == SND_DEV_AUDIO) - sw_samplefmt = AFMT_MU_LAW; - else if ((minor & 0xF) == SND_DEV_DSP16) - sw_samplefmt = AFMT_S16_LE; - else - ASSERT(0); - - /* Initialize vwsnd_ports. */ - - mutex_lock(&devc->io_mutex); - { - if (file->f_mode & FMODE_READ) { - devc->rport.swstate = SW_INITIAL; - devc->rport.flags = 0; - devc->rport.sw_channels = 1; - devc->rport.sw_samplefmt = sw_samplefmt; - devc->rport.sw_framerate = 8000; - devc->rport.sw_fragshift = DEFAULT_FRAGSHIFT; - devc->rport.sw_fragcount = DEFAULT_FRAGCOUNT; - devc->rport.sw_subdivshift = DEFAULT_SUBDIVSHIFT; - devc->rport.byte_count = 0; - devc->rport.frag_count = 0; - } - if (file->f_mode & FMODE_WRITE) { - devc->wport.swstate = SW_INITIAL; - devc->wport.flags = 0; - devc->wport.sw_channels = 1; - devc->wport.sw_samplefmt = sw_samplefmt; - devc->wport.sw_framerate = 8000; - devc->wport.sw_fragshift = DEFAULT_FRAGSHIFT; - devc->wport.sw_fragcount = DEFAULT_FRAGCOUNT; - devc->wport.sw_subdivshift = DEFAULT_SUBDIVSHIFT; - devc->wport.byte_count = 0; - devc->wport.frag_count = 0; - } - } - mutex_unlock(&devc->io_mutex); - - file->private_data = devc; - DBGRV(); - mutex_unlock(&vwsnd_mutex); - return 0; -} - -/* - * Release (close) the audio device. - */ - -static int vwsnd_audio_release(struct inode *inode, struct file *file) -{ - vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data; - vwsnd_port_t *wport = NULL, *rport = NULL; - int err = 0; - - mutex_lock(&vwsnd_mutex); - mutex_lock(&devc->io_mutex); - { - DBGEV("(inode=0x%p, file=0x%p)\n", inode, file); - - if (file->f_mode & FMODE_READ) - rport = &devc->rport; - if (file->f_mode & FMODE_WRITE) { - wport = &devc->wport; - pcm_flush_frag(devc); - pcm_write_sync(devc); - } - pcm_shutdown(devc, rport, wport); - if (rport) - rport->swstate = SW_OFF; - if (wport) - wport->swstate = SW_OFF; - } - mutex_unlock(&devc->io_mutex); - - mutex_lock(&devc->open_mutex); - { - devc->open_mode &= ~file->f_mode; - } - mutex_unlock(&devc->open_mutex); - wake_up(&devc->open_wait); - DEC_USE_COUNT; - DBGR(); - mutex_unlock(&vwsnd_mutex); - return err; -} - -static const struct file_operations vwsnd_audio_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = vwsnd_audio_read, - .write = vwsnd_audio_write, - .poll = vwsnd_audio_poll, - .unlocked_ioctl = vwsnd_audio_ioctl, - .mmap = vwsnd_audio_mmap, - .open = vwsnd_audio_open, - .release = vwsnd_audio_release, -}; - -/*****************************************************************************/ -/* mixer driver */ - -/* open the mixer device. */ - -static int vwsnd_mixer_open(struct inode *inode, struct file *file) -{ - vwsnd_dev_t *devc; - - DBGEV("(inode=0x%p, file=0x%p)\n", inode, file); - - INC_USE_COUNT; - mutex_lock(&vwsnd_mutex); - for (devc = vwsnd_dev_list; devc; devc = devc->next_dev) - if (devc->mixer_minor == iminor(inode)) - break; - - if (devc == NULL) { - DEC_USE_COUNT; - mutex_unlock(&vwsnd_mutex); - return -ENODEV; - } - file->private_data = devc; - mutex_unlock(&vwsnd_mutex); - return 0; -} - -/* release (close) the mixer device. */ - -static int vwsnd_mixer_release(struct inode *inode, struct file *file) -{ - DBGEV("(inode=0x%p, file=0x%p)\n", inode, file); - DEC_USE_COUNT; - return 0; -} - -/* mixer_read_ioctl handles all read ioctls on the mixer device. */ - -static int mixer_read_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *arg) -{ - int val = -1; - - DBGEV("(devc=0x%p, nr=0x%x, arg=0x%p)\n", devc, nr, arg); - - switch (nr) { - case SOUND_MIXER_CAPS: - val = SOUND_CAP_EXCL_INPUT; - break; - - case SOUND_MIXER_DEVMASK: - val = (SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_RECLEV); - break; - - case SOUND_MIXER_STEREODEVS: - val = (SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_RECLEV); - break; - - case SOUND_MIXER_OUTMASK: - val = (SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_MIC | SOUND_MASK_CD); - break; - - case SOUND_MIXER_RECMASK: - val = (SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_MIC | SOUND_MASK_CD); - break; - - case SOUND_MIXER_PCM: - val = ad1843_get_gain(&devc->lith, &ad1843_gain_PCM); - break; - - case SOUND_MIXER_LINE: - val = ad1843_get_gain(&devc->lith, &ad1843_gain_LINE); - break; - - case SOUND_MIXER_MIC: - val = ad1843_get_gain(&devc->lith, &ad1843_gain_MIC); - break; - - case SOUND_MIXER_CD: - val = ad1843_get_gain(&devc->lith, &ad1843_gain_CD); - break; - - case SOUND_MIXER_RECLEV: - val = ad1843_get_gain(&devc->lith, &ad1843_gain_RECLEV); - break; - - case SOUND_MIXER_RECSRC: - val = ad1843_get_recsrc(&devc->lith); - break; - - case SOUND_MIXER_OUTSRC: - val = ad1843_get_outsrc(&devc->lith); - break; - - default: - return -EINVAL; - } - return put_user(val, (int __user *) arg); -} - -/* mixer_write_ioctl handles all write ioctls on the mixer device. */ - -static int mixer_write_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *arg) -{ - int val; - int err; - - DBGEV("(devc=0x%p, nr=0x%x, arg=0x%p)\n", devc, nr, arg); - - err = get_user(val, (int __user *) arg); - if (err) - return -EFAULT; - switch (nr) { - case SOUND_MIXER_PCM: - val = ad1843_set_gain(&devc->lith, &ad1843_gain_PCM, val); - break; - - case SOUND_MIXER_LINE: - val = ad1843_set_gain(&devc->lith, &ad1843_gain_LINE, val); - break; - - case SOUND_MIXER_MIC: - val = ad1843_set_gain(&devc->lith, &ad1843_gain_MIC, val); - break; - - case SOUND_MIXER_CD: - val = ad1843_set_gain(&devc->lith, &ad1843_gain_CD, val); - break; - - case SOUND_MIXER_RECLEV: - val = ad1843_set_gain(&devc->lith, &ad1843_gain_RECLEV, val); - break; - - case SOUND_MIXER_RECSRC: - if (devc->rport.swbuf || devc->wport.swbuf) - return -EBUSY; /* can't change recsrc while running */ - val = ad1843_set_recsrc(&devc->lith, val); - break; - - case SOUND_MIXER_OUTSRC: - val = ad1843_set_outsrc(&devc->lith, val); - break; - - default: - return -EINVAL; - } - if (val < 0) - return val; - return put_user(val, (int __user *) arg); -} - -/* This is the ioctl entry to the mixer driver. */ - -static long vwsnd_mixer_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) -{ - vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data; - const unsigned int nrmask = _IOC_NRMASK << _IOC_NRSHIFT; - const unsigned int nr = (cmd & nrmask) >> _IOC_NRSHIFT; - int retval; - - DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg); - - mutex_lock(&vwsnd_mutex); - mutex_lock(&devc->mix_mutex); - { - if ((cmd & ~nrmask) == MIXER_READ(0)) - retval = mixer_read_ioctl(devc, nr, (void __user *) arg); - else if ((cmd & ~nrmask) == MIXER_WRITE(0)) - retval = mixer_write_ioctl(devc, nr, (void __user *) arg); - else - retval = -EINVAL; - } - mutex_unlock(&devc->mix_mutex); - mutex_unlock(&vwsnd_mutex); - return retval; -} - -static const struct file_operations vwsnd_mixer_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .unlocked_ioctl = vwsnd_mixer_ioctl, - .open = vwsnd_mixer_open, - .release = vwsnd_mixer_release, -}; - -/*****************************************************************************/ -/* probe/attach/unload */ - -/* driver probe routine. Return nonzero if hardware is found. */ - -static int __init probe_vwsnd(struct address_info *hw_config) -{ - lithium_t lith; - int w; - unsigned long later; - - DBGEV("(hw_config=0x%p)\n", hw_config); - - /* XXX verify lithium present (to prevent crash on non-vw) */ - - if (li_create(&lith, hw_config->io_base) != 0) { - printk(KERN_WARNING "probe_vwsnd: can't map lithium\n"); - return 0; - } - later = jiffies + 2; - li_writel(&lith, LI_HOST_CONTROLLER, LI_HC_LINK_ENABLE); - do { - w = li_readl(&lith, LI_HOST_CONTROLLER); - } while (w == LI_HC_LINK_ENABLE && time_before(jiffies, later)); - - li_destroy(&lith); - - DBGPV("HC = 0x%04x\n", w); - - if ((w == LI_HC_LINK_ENABLE) || (w & LI_HC_LINK_CODEC)) { - - /* This may indicate a beta machine with no audio, - * or a future machine with different audio. - * On beta-release 320 w/ no audio, HC == 0x4000 */ - - printk(KERN_WARNING "probe_vwsnd: audio codec not found\n"); - return 0; - } - - if (w & LI_HC_LINK_FAILURE) { - printk(KERN_WARNING "probe_vwsnd: can't init audio codec\n"); - return 0; - } - - printk(KERN_INFO "vwsnd: lithium audio at mmio %#x irq %d\n", - hw_config->io_base, hw_config->irq); - - return 1; -} - -/* - * driver attach routine. Initialize driver data structures and - * initialize hardware. A new vwsnd_dev_t is allocated and put - * onto the global list, vwsnd_dev_list. - * - * Return +minor_dev on success, -errno on failure. - */ - -static int __init attach_vwsnd(struct address_info *hw_config) -{ - vwsnd_dev_t *devc = NULL; - int err = -ENOMEM; - - DBGEV("(hw_config=0x%p)\n", hw_config); - - devc = kmalloc(sizeof (vwsnd_dev_t), GFP_KERNEL); - if (devc == NULL) - goto fail0; - - err = li_create(&devc->lith, hw_config->io_base); - if (err) - goto fail1; - - init_waitqueue_head(&devc->open_wait); - - devc->rport.hwbuf_size = HWBUF_SIZE; - devc->rport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER); - if (!devc->rport.hwbuf_vaddr) - goto fail2; - devc->rport.hwbuf = (void *) devc->rport.hwbuf_vaddr; - devc->rport.hwbuf_paddr = virt_to_phys(devc->rport.hwbuf); - - /* - * Quote from the NT driver: - * - * // WARNING!!! HACK to setup output dma!!! - * // This is required because even on output there is some data - * // trickling into the input DMA channel. This is a bug in the - * // Lithium microcode. - * // --sde - * - * We set the input side's DMA base address here. It will remain - * valid until the driver is unloaded. - */ - - li_writel(&devc->lith, LI_COMM1_BASE, - devc->rport.hwbuf_paddr >> 8 | 1 << (37 - 8)); - - devc->wport.hwbuf_size = HWBUF_SIZE; - devc->wport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER); - if (!devc->wport.hwbuf_vaddr) - goto fail3; - devc->wport.hwbuf = (void *) devc->wport.hwbuf_vaddr; - devc->wport.hwbuf_paddr = virt_to_phys(devc->wport.hwbuf); - DBGP("wport hwbuf = 0x%p\n", devc->wport.hwbuf); - - DBGDO(shut_up++); - err = ad1843_init(&devc->lith); - DBGDO(shut_up--); - if (err) - goto fail4; - - /* install interrupt handler */ - - err = request_irq(hw_config->irq, vwsnd_audio_intr, 0, "vwsnd", devc); - if (err) - goto fail5; - - /* register this device's drivers. */ - - devc->audio_minor = register_sound_dsp(&vwsnd_audio_fops, -1); - if ((err = devc->audio_minor) < 0) { - DBGDO(printk(KERN_WARNING - "attach_vwsnd: register_sound_dsp error %d\n", - err)); - goto fail6; - } - devc->mixer_minor = register_sound_mixer(&vwsnd_mixer_fops, - devc->audio_minor >> 4); - if ((err = devc->mixer_minor) < 0) { - DBGDO(printk(KERN_WARNING - "attach_vwsnd: register_sound_mixer error %d\n", - err)); - goto fail7; - } - - /* Squirrel away device indices for unload routine. */ - - hw_config->slots[0] = devc->audio_minor; - - /* Initialize as much of *devc as possible */ - - mutex_init(&devc->open_mutex); - mutex_init(&devc->io_mutex); - mutex_init(&devc->mix_mutex); - devc->open_mode = 0; - spin_lock_init(&devc->rport.lock); - init_waitqueue_head(&devc->rport.queue); - devc->rport.swstate = SW_OFF; - devc->rport.hwstate = HW_STOPPED; - devc->rport.flags = 0; - devc->rport.swbuf = NULL; - spin_lock_init(&devc->wport.lock); - init_waitqueue_head(&devc->wport.queue); - devc->wport.swstate = SW_OFF; - devc->wport.hwstate = HW_STOPPED; - devc->wport.flags = 0; - devc->wport.swbuf = NULL; - - /* Success. Link us onto the local device list. */ - - devc->next_dev = vwsnd_dev_list; - vwsnd_dev_list = devc; - return devc->audio_minor; - - /* So many ways to fail. Undo what we did. */ - - fail7: - unregister_sound_dsp(devc->audio_minor); - fail6: - free_irq(hw_config->irq, devc); - fail5: - fail4: - free_pages(devc->wport.hwbuf_vaddr, HWBUF_ORDER); - fail3: - free_pages(devc->rport.hwbuf_vaddr, HWBUF_ORDER); - fail2: - li_destroy(&devc->lith); - fail1: - kfree(devc); - fail0: - return err; -} - -static int __exit unload_vwsnd(struct address_info *hw_config) -{ - vwsnd_dev_t *devc, **devcp; - - DBGE("()\n"); - - devcp = &vwsnd_dev_list; - while ((devc = *devcp)) { - if (devc->audio_minor == hw_config->slots[0]) { - *devcp = devc->next_dev; - break; - } - devcp = &devc->next_dev; - } - - if (!devc) - return -ENODEV; - - unregister_sound_mixer(devc->mixer_minor); - unregister_sound_dsp(devc->audio_minor); - free_irq(hw_config->irq, devc); - free_pages(devc->wport.hwbuf_vaddr, HWBUF_ORDER); - free_pages(devc->rport.hwbuf_vaddr, HWBUF_ORDER); - li_destroy(&devc->lith); - kfree(devc); - - return 0; -} - -/*****************************************************************************/ -/* initialization and loadable kernel module interface */ - -static struct address_info the_hw_config = { - 0xFF001000, /* lithium phys addr */ - CO_IRQ(CO_APIC_LI_AUDIO) /* irq */ -}; - -MODULE_DESCRIPTION("SGI Visual Workstation sound module"); -MODULE_AUTHOR("Bob Miller "); -MODULE_LICENSE("GPL"); - -static int __init init_vwsnd(void) -{ - int err; - - DBGXV("\n"); - DBGXV("sound::vwsnd::init_module()\n"); - - if (!probe_vwsnd(&the_hw_config)) - return -ENODEV; - - err = attach_vwsnd(&the_hw_config); - if (err < 0) - return err; - return 0; -} - -static void __exit cleanup_vwsnd(void) -{ - DBGX("sound::vwsnd::cleanup_module()\n"); - - unload_vwsnd(&the_hw_config); -} - -module_init(init_vwsnd); -module_exit(cleanup_vwsnd); diff --git a/ANDROID_3.4.5/sound/oss/waveartist.c b/ANDROID_3.4.5/sound/oss/waveartist.c deleted file mode 100644 index 24c430f7..00000000 --- a/ANDROID_3.4.5/sound/oss/waveartist.c +++ /dev/null @@ -1,2024 +0,0 @@ -/* - * linux/sound/oss/waveartist.c - * - * The low level driver for the RWA010 Rockwell Wave Artist - * codec chip used in the Rebel.com NetWinder. - * - * Cleaned up and integrated into 2.1 by Russell King (rmk@arm.linux.org.uk) - * and Pat Beirne (patb@corel.ca) - * - * - * Copyright (C) by Rebel.com 1998-1999 - * - * RWA010 specs received under NDA from Rockwell - * - * Copyright (C) by Hannu Savolainen 1993-1997 - * - * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - * - * Changes: - * 11-10-2000 Bartlomiej Zolnierkiewicz - * Added __init to waveartist_init() - */ - -/* Debugging */ -#define DEBUG_CMD 1 -#define DEBUG_OUT 2 -#define DEBUG_IN 4 -#define DEBUG_INTR 8 -#define DEBUG_MIXER 16 -#define DEBUG_TRIGGER 32 - -#define debug_flg (0) - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "sound_config.h" -#include "waveartist.h" - -#ifdef CONFIG_ARM -#include -#include -#endif - -#ifndef NO_DMA -#define NO_DMA 255 -#endif - -#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH |\ - SOUND_MASK_PCM |\ - SOUND_MASK_LINE |\ - SOUND_MASK_MIC |\ - SOUND_MASK_LINE1 |\ - SOUND_MASK_RECLEV |\ - SOUND_MASK_VOLUME |\ - SOUND_MASK_IMIX) - -static unsigned short levels[SOUND_MIXER_NRDEVICES] = { - 0x5555, /* Master Volume */ - 0x0000, /* Bass */ - 0x0000, /* Treble */ - 0x2323, /* Synth (FM) */ - 0x4b4b, /* PCM */ - 0x6464, /* PC Speaker */ - 0x0000, /* Ext Line */ - 0x0000, /* Mic */ - 0x0000, /* CD */ - 0x6464, /* Recording monitor */ - 0x0000, /* SB PCM (ALT PCM) */ - 0x0000, /* Recording level */ - 0x6464, /* Input gain */ - 0x6464, /* Output gain */ - 0x0000, /* Line1 (Aux1) */ - 0x0000, /* Line2 (Aux2) */ - 0x0000, /* Line3 (Aux3) */ - 0x0000, /* Digital1 */ - 0x0000, /* Digital2 */ - 0x0000, /* Digital3 */ - 0x0000, /* Phone In */ - 0x6464, /* Phone Out */ - 0x0000, /* Video */ - 0x0000, /* Radio */ - 0x0000 /* Monitor */ -}; - -typedef struct { - struct address_info hw; /* hardware */ - char *chip_name; - - int xfer_count; - int audio_mode; - int open_mode; - int audio_flags; - int record_dev; - int playback_dev; - int dev_no; - - /* Mixer parameters */ - const struct waveartist_mixer_info *mix; - - unsigned short *levels; /* cache of volume settings */ - int recmask; /* currently enabled recording device! */ - -#ifdef CONFIG_ARCH_NETWINDER - signed int slider_vol; /* hardware slider volume */ - unsigned int handset_detect :1; - unsigned int telephone_detect:1; - unsigned int no_autoselect :1;/* handset/telephone autoselects a path */ - unsigned int spkr_mute_state :1;/* set by ioctl or autoselect */ - unsigned int line_mute_state :1;/* set by ioctl or autoselect */ - unsigned int use_slider :1;/* use slider setting for o/p vol */ -#endif -} wavnc_info; - -/* - * This is the implementation specific mixer information. - */ -struct waveartist_mixer_info { - unsigned int supported_devs; /* Supported devices */ - unsigned int recording_devs; /* Recordable devies */ - unsigned int stereo_devs; /* Stereo devices */ - - unsigned int (*select_input)(wavnc_info *, unsigned int, - unsigned char *, unsigned char *); - int (*decode_mixer)(wavnc_info *, int, - unsigned char, unsigned char); - int (*get_mixer)(wavnc_info *, int); -}; - -typedef struct wavnc_port_info { - int open_mode; - int speed; - int channels; - int audio_format; -} wavnc_port_info; - -static int nr_waveartist_devs; -static wavnc_info adev_info[MAX_AUDIO_DEV]; -static DEFINE_SPINLOCK(waveartist_lock); - -#ifndef CONFIG_ARCH_NETWINDER -#define machine_is_netwinder() 0 -#else -static struct timer_list vnc_timer; -static void vnc_configure_mixer(wavnc_info *devc, unsigned int input_mask); -static int vnc_private_ioctl(int dev, unsigned int cmd, int __user *arg); -static void vnc_slider_tick(unsigned long data); -#endif - -static inline void -waveartist_set_ctlr(struct address_info *hw, unsigned char clear, unsigned char set) -{ - unsigned int ctlr_port = hw->io_base + CTLR; - - clear = ~clear & inb(ctlr_port); - - outb(clear | set, ctlr_port); -} - -/* Toggle IRQ acknowledge line - */ -static inline void -waveartist_iack(wavnc_info *devc) -{ - unsigned int ctlr_port = devc->hw.io_base + CTLR; - int old_ctlr; - - old_ctlr = inb(ctlr_port) & ~IRQ_ACK; - - outb(old_ctlr | IRQ_ACK, ctlr_port); - outb(old_ctlr, ctlr_port); -} - -static inline int -waveartist_sleep(int timeout_ms) -{ - unsigned int timeout = msecs_to_jiffies(timeout_ms*100); - return schedule_timeout_interruptible(timeout); -} - -static int -waveartist_reset(wavnc_info *devc) -{ - struct address_info *hw = &devc->hw; - unsigned int timeout, res = -1; - - waveartist_set_ctlr(hw, -1, RESET); - waveartist_sleep(2); - waveartist_set_ctlr(hw, RESET, 0); - - timeout = 500; - do { - mdelay(2); - - if (inb(hw->io_base + STATR) & CMD_RF) { - res = inw(hw->io_base + CMDR); - if (res == 0x55aa) - break; - } - } while (--timeout); - - if (timeout == 0) { - printk(KERN_WARNING "WaveArtist: reset timeout "); - if (res != (unsigned int)-1) - printk("(res=%04X)", res); - printk("\n"); - return 1; - } - return 0; -} - -/* Helper function to send and receive words - * from WaveArtist. It handles all the handshaking - * and can send or receive multiple words. - */ -static int -waveartist_cmd(wavnc_info *devc, - int nr_cmd, unsigned int *cmd, - int nr_resp, unsigned int *resp) -{ - unsigned int io_base = devc->hw.io_base; - unsigned int timed_out = 0; - unsigned int i; - - if (debug_flg & DEBUG_CMD) { - printk("waveartist_cmd: cmd="); - - for (i = 0; i < nr_cmd; i++) - printk("%04X ", cmd[i]); - - printk("\n"); - } - - if (inb(io_base + STATR) & CMD_RF) { - int old_data; - - /* flush the port - */ - - old_data = inw(io_base + CMDR); - - if (debug_flg & DEBUG_CMD) - printk("flushed %04X...", old_data); - - udelay(10); - } - - for (i = 0; !timed_out && i < nr_cmd; i++) { - int count; - - for (count = 5000; count; count--) - if (inb(io_base + STATR) & CMD_WE) - break; - - if (!count) - timed_out = 1; - else - outw(cmd[i], io_base + CMDR); - } - - for (i = 0; !timed_out && i < nr_resp; i++) { - int count; - - for (count = 5000; count; count--) - if (inb(io_base + STATR) & CMD_RF) - break; - - if (!count) - timed_out = 1; - else - resp[i] = inw(io_base + CMDR); - } - - if (debug_flg & DEBUG_CMD) { - if (!timed_out) { - printk("waveartist_cmd: resp="); - - for (i = 0; i < nr_resp; i++) - printk("%04X ", resp[i]); - - printk("\n"); - } else - printk("waveartist_cmd: timed out\n"); - } - - return timed_out ? 1 : 0; -} - -/* - * Send one command word - */ -static inline int -waveartist_cmd1(wavnc_info *devc, unsigned int cmd) -{ - return waveartist_cmd(devc, 1, &cmd, 0, NULL); -} - -/* - * Send one command, receive one word - */ -static inline unsigned int -waveartist_cmd1_r(wavnc_info *devc, unsigned int cmd) -{ - unsigned int ret; - - waveartist_cmd(devc, 1, &cmd, 1, &ret); - - return ret; -} - -/* - * Send a double command, receive one - * word (and throw it away) - */ -static inline int -waveartist_cmd2(wavnc_info *devc, unsigned int cmd, unsigned int arg) -{ - unsigned int vals[2]; - - vals[0] = cmd; - vals[1] = arg; - - return waveartist_cmd(devc, 2, vals, 1, vals); -} - -/* - * Send a triple command - */ -static inline int -waveartist_cmd3(wavnc_info *devc, unsigned int cmd, - unsigned int arg1, unsigned int arg2) -{ - unsigned int vals[3]; - - vals[0] = cmd; - vals[1] = arg1; - vals[2] = arg2; - - return waveartist_cmd(devc, 3, vals, 0, NULL); -} - -static int -waveartist_getrev(wavnc_info *devc, char *rev) -{ - unsigned int temp[2]; - unsigned int cmd = WACMD_GETREV; - - waveartist_cmd(devc, 1, &cmd, 2, temp); - - rev[0] = temp[0] >> 8; - rev[1] = temp[0] & 255; - rev[2] = '\0'; - - return temp[0]; -} - -static void waveartist_halt_output(int dev); -static void waveartist_halt_input(int dev); -static void waveartist_halt(int dev); -static void waveartist_trigger(int dev, int state); - -static int -waveartist_open(int dev, int mode) -{ - wavnc_info *devc; - wavnc_port_info *portc; - unsigned long flags; - - if (dev < 0 || dev >= num_audiodevs) - return -ENXIO; - - devc = (wavnc_info *) audio_devs[dev]->devc; - portc = (wavnc_port_info *) audio_devs[dev]->portc; - - spin_lock_irqsave(&waveartist_lock, flags); - if (portc->open_mode || (devc->open_mode & mode)) { - spin_unlock_irqrestore(&waveartist_lock, flags); - return -EBUSY; - } - - devc->audio_mode = 0; - devc->open_mode |= mode; - portc->open_mode = mode; - waveartist_trigger(dev, 0); - - if (mode & OPEN_READ) - devc->record_dev = dev; - if (mode & OPEN_WRITE) - devc->playback_dev = dev; - spin_unlock_irqrestore(&waveartist_lock, flags); - - return 0; -} - -static void -waveartist_close(int dev) -{ - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - unsigned long flags; - - spin_lock_irqsave(&waveartist_lock, flags); - - waveartist_halt(dev); - - devc->audio_mode = 0; - devc->open_mode &= ~portc->open_mode; - portc->open_mode = 0; - - spin_unlock_irqrestore(&waveartist_lock, flags); -} - -static void -waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag) -{ - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - unsigned long flags; - unsigned int count = __count; - - if (debug_flg & DEBUG_OUT) - printk("waveartist: output block, buf=0x%lx, count=0x%x...\n", - buf, count); - /* - * 16 bit data - */ - if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) - count >>= 1; - - if (portc->channels > 1) - count >>= 1; - - count -= 1; - - if (devc->audio_mode & PCM_ENABLE_OUTPUT && - audio_devs[dev]->flags & DMA_AUTOMODE && - intrflag && - count == devc->xfer_count) { - devc->audio_mode |= PCM_ENABLE_OUTPUT; - return; /* - * Auto DMA mode on. No need to react - */ - } - - spin_lock_irqsave(&waveartist_lock, flags); - - /* - * set sample count - */ - waveartist_cmd2(devc, WACMD_OUTPUTSIZE, count); - - devc->xfer_count = count; - devc->audio_mode |= PCM_ENABLE_OUTPUT; - - spin_unlock_irqrestore(&waveartist_lock, flags); -} - -static void -waveartist_start_input(int dev, unsigned long buf, int __count, int intrflag) -{ - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - unsigned long flags; - unsigned int count = __count; - - if (debug_flg & DEBUG_IN) - printk("waveartist: start input, buf=0x%lx, count=0x%x...\n", - buf, count); - - if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */ - count >>= 1; - - if (portc->channels > 1) - count >>= 1; - - count -= 1; - - if (devc->audio_mode & PCM_ENABLE_INPUT && - audio_devs[dev]->flags & DMA_AUTOMODE && - intrflag && - count == devc->xfer_count) { - devc->audio_mode |= PCM_ENABLE_INPUT; - return; /* - * Auto DMA mode on. No need to react - */ - } - - spin_lock_irqsave(&waveartist_lock, flags); - - /* - * set sample count - */ - waveartist_cmd2(devc, WACMD_INPUTSIZE, count); - - devc->xfer_count = count; - devc->audio_mode |= PCM_ENABLE_INPUT; - - spin_unlock_irqrestore(&waveartist_lock, flags); -} - -static int -waveartist_ioctl(int dev, unsigned int cmd, void __user * arg) -{ - return -EINVAL; -} - -static unsigned int -waveartist_get_speed(wavnc_port_info *portc) -{ - unsigned int speed; - - /* - * program the speed, channels, bits - */ - if (portc->speed == 8000) - speed = 0x2E71; - else if (portc->speed == 11025) - speed = 0x4000; - else if (portc->speed == 22050) - speed = 0x8000; - else if (portc->speed == 44100) - speed = 0x0; - else { - /* - * non-standard - just calculate - */ - speed = portc->speed << 16; - - speed = (speed / 44100) & 65535; - } - - return speed; -} - -static unsigned int -waveartist_get_bits(wavnc_port_info *portc) -{ - unsigned int bits; - - if (portc->audio_format == AFMT_S16_LE) - bits = 1; - else if (portc->audio_format == AFMT_S8) - bits = 0; - else - bits = 2; //default AFMT_U8 - - return bits; -} - -static int -waveartist_prepare_for_input(int dev, int bsize, int bcount) -{ - unsigned long flags; - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - unsigned int speed, bits; - - if (devc->audio_mode) - return 0; - - speed = waveartist_get_speed(portc); - bits = waveartist_get_bits(portc); - - spin_lock_irqsave(&waveartist_lock, flags); - - if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits)) - printk(KERN_WARNING "waveartist: error setting the " - "record format to %d\n", portc->audio_format); - - if (waveartist_cmd2(devc, WACMD_INPUTCHANNELS, portc->channels)) - printk(KERN_WARNING "waveartist: error setting record " - "to %d channels\n", portc->channels); - - /* - * write cmd SetSampleSpeedTimeConstant - */ - if (waveartist_cmd2(devc, WACMD_INPUTSPEED, speed)) - printk(KERN_WARNING "waveartist: error setting the record " - "speed to %dHz.\n", portc->speed); - - if (waveartist_cmd2(devc, WACMD_INPUTDMA, 1)) - printk(KERN_WARNING "waveartist: error setting the record " - "data path to 0x%X\n", 1); - - if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits)) - printk(KERN_WARNING "waveartist: error setting the record " - "format to %d\n", portc->audio_format); - - devc->xfer_count = 0; - spin_unlock_irqrestore(&waveartist_lock, flags); - waveartist_halt_input(dev); - - if (debug_flg & DEBUG_INTR) { - printk("WA CTLR reg: 0x%02X.\n", - inb(devc->hw.io_base + CTLR)); - printk("WA STAT reg: 0x%02X.\n", - inb(devc->hw.io_base + STATR)); - printk("WA IRQS reg: 0x%02X.\n", - inb(devc->hw.io_base + IRQSTAT)); - } - - return 0; -} - -static int -waveartist_prepare_for_output(int dev, int bsize, int bcount) -{ - unsigned long flags; - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - unsigned int speed, bits; - - /* - * program the speed, channels, bits - */ - speed = waveartist_get_speed(portc); - bits = waveartist_get_bits(portc); - - spin_lock_irqsave(&waveartist_lock, flags); - - if (waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed) && - waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed)) - printk(KERN_WARNING "waveartist: error setting the playback " - "speed to %dHz.\n", portc->speed); - - if (waveartist_cmd2(devc, WACMD_OUTPUTCHANNELS, portc->channels)) - printk(KERN_WARNING "waveartist: error setting the playback " - "to %d channels\n", portc->channels); - - if (waveartist_cmd2(devc, WACMD_OUTPUTDMA, 0)) - printk(KERN_WARNING "waveartist: error setting the playback " - "data path to 0x%X\n", 0); - - if (waveartist_cmd2(devc, WACMD_OUTPUTFORMAT, bits)) - printk(KERN_WARNING "waveartist: error setting the playback " - "format to %d\n", portc->audio_format); - - devc->xfer_count = 0; - spin_unlock_irqrestore(&waveartist_lock, flags); - waveartist_halt_output(dev); - - if (debug_flg & DEBUG_INTR) { - printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR)); - printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR)); - printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT)); - } - - return 0; -} - -static void -waveartist_halt(int dev) -{ - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - wavnc_info *devc; - - if (portc->open_mode & OPEN_WRITE) - waveartist_halt_output(dev); - - if (portc->open_mode & OPEN_READ) - waveartist_halt_input(dev); - - devc = (wavnc_info *) audio_devs[dev]->devc; - devc->audio_mode = 0; -} - -static void -waveartist_halt_input(int dev) -{ - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - unsigned long flags; - - spin_lock_irqsave(&waveartist_lock, flags); - - /* - * Stop capture - */ - waveartist_cmd1(devc, WACMD_INPUTSTOP); - - devc->audio_mode &= ~PCM_ENABLE_INPUT; - - /* - * Clear interrupt by toggling - * the IRQ_ACK bit in CTRL - */ - if (inb(devc->hw.io_base + STATR) & IRQ_REQ) - waveartist_iack(devc); - -// devc->audio_mode &= ~PCM_ENABLE_INPUT; - - spin_unlock_irqrestore(&waveartist_lock, flags); -} - -static void -waveartist_halt_output(int dev) -{ - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - unsigned long flags; - - spin_lock_irqsave(&waveartist_lock, flags); - - waveartist_cmd1(devc, WACMD_OUTPUTSTOP); - - devc->audio_mode &= ~PCM_ENABLE_OUTPUT; - - /* - * Clear interrupt by toggling - * the IRQ_ACK bit in CTRL - */ - if (inb(devc->hw.io_base + STATR) & IRQ_REQ) - waveartist_iack(devc); - -// devc->audio_mode &= ~PCM_ENABLE_OUTPUT; - - spin_unlock_irqrestore(&waveartist_lock, flags); -} - -static void -waveartist_trigger(int dev, int state) -{ - wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc; - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - unsigned long flags; - - if (debug_flg & DEBUG_TRIGGER) { - printk("wavnc: audio trigger "); - if (state & PCM_ENABLE_INPUT) - printk("in "); - if (state & PCM_ENABLE_OUTPUT) - printk("out"); - printk("\n"); - } - - spin_lock_irqsave(&waveartist_lock, flags); - - state &= devc->audio_mode; - - if (portc->open_mode & OPEN_READ && - state & PCM_ENABLE_INPUT) - /* - * enable ADC Data Transfer to PC - */ - waveartist_cmd1(devc, WACMD_INPUTSTART); - - if (portc->open_mode & OPEN_WRITE && - state & PCM_ENABLE_OUTPUT) - /* - * enable DAC data transfer from PC - */ - waveartist_cmd1(devc, WACMD_OUTPUTSTART); - - spin_unlock_irqrestore(&waveartist_lock, flags); -} - -static int -waveartist_set_speed(int dev, int arg) -{ - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - - if (arg <= 0) - return portc->speed; - - if (arg < 5000) - arg = 5000; - if (arg > 44100) - arg = 44100; - - portc->speed = arg; - return portc->speed; - -} - -static short -waveartist_set_channels(int dev, short arg) -{ - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - - if (arg != 1 && arg != 2) - return portc->channels; - - portc->channels = arg; - return arg; -} - -static unsigned int -waveartist_set_bits(int dev, unsigned int arg) -{ - wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc; - - if (arg == 0) - return portc->audio_format; - - if ((arg != AFMT_U8) && (arg != AFMT_S16_LE) && (arg != AFMT_S8)) - arg = AFMT_U8; - - portc->audio_format = arg; - - return arg; -} - -static struct audio_driver waveartist_audio_driver = { - .owner = THIS_MODULE, - .open = waveartist_open, - .close = waveartist_close, - .output_block = waveartist_output_block, - .start_input = waveartist_start_input, - .ioctl = waveartist_ioctl, - .prepare_for_input = waveartist_prepare_for_input, - .prepare_for_output = waveartist_prepare_for_output, - .halt_io = waveartist_halt, - .halt_input = waveartist_halt_input, - .halt_output = waveartist_halt_output, - .trigger = waveartist_trigger, - .set_speed = waveartist_set_speed, - .set_bits = waveartist_set_bits, - .set_channels = waveartist_set_channels -}; - - -static irqreturn_t -waveartist_intr(int irq, void *dev_id) -{ - wavnc_info *devc = dev_id; - int irqstatus, status; - - spin_lock(&waveartist_lock); - irqstatus = inb(devc->hw.io_base + IRQSTAT); - status = inb(devc->hw.io_base + STATR); - - if (debug_flg & DEBUG_INTR) - printk("waveartist_intr: stat=%02x, irqstat=%02x\n", - status, irqstatus); - - if (status & IRQ_REQ) /* Clear interrupt */ - waveartist_iack(devc); - else - printk(KERN_WARNING "waveartist: unexpected interrupt\n"); - - if (irqstatus & 0x01) { - int temp = 1; - - /* PCM buffer done - */ - if ((status & DMA0) && (devc->audio_mode & PCM_ENABLE_OUTPUT)) { - DMAbuf_outputintr(devc->playback_dev, 1); - temp = 0; - } - if ((status & DMA1) && (devc->audio_mode & PCM_ENABLE_INPUT)) { - DMAbuf_inputintr(devc->record_dev); - temp = 0; - } - if (temp) //default: - printk(KERN_WARNING "waveartist: Unknown interrupt\n"); - } - if (irqstatus & 0x2) - // We do not use SB mode natively... - printk(KERN_WARNING "waveartist: Unexpected SB interrupt...\n"); - spin_unlock(&waveartist_lock); - return IRQ_HANDLED; -} - -/* ------------------------------------------------------------------------- - * Mixer stuff - */ -struct mix_ent { - unsigned char reg_l; - unsigned char reg_r; - unsigned char shift; - unsigned char max; -}; - -static const struct mix_ent mix_devs[SOUND_MIXER_NRDEVICES] = { - { 2, 6, 1, 7 }, /* SOUND_MIXER_VOLUME */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_BASS */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_TREBLE */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_SYNTH */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_PCM */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_SPEAKER */ - { 0, 4, 6, 31 }, /* SOUND_MIXER_LINE */ - { 2, 6, 4, 3 }, /* SOUND_MIXER_MIC */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_CD */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_IMIX */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_ALTPCM */ -#if 0 - { 3, 7, 0, 10 }, /* SOUND_MIXER_RECLEV */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_IGAIN */ -#else - { 0, 0, 0, 0 }, /* SOUND_MIXER_RECLEV */ - { 3, 7, 0, 7 }, /* SOUND_MIXER_IGAIN */ -#endif - { 0, 0, 0, 0 }, /* SOUND_MIXER_OGAIN */ - { 0, 4, 1, 31 }, /* SOUND_MIXER_LINE1 */ - { 1, 5, 6, 31 }, /* SOUND_MIXER_LINE2 */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_LINE3 */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_DIGITAL1 */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_DIGITAL2 */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_DIGITAL3 */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_PHONEIN */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_PHONEOUT */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_VIDEO */ - { 0, 0, 0, 0 }, /* SOUND_MIXER_RADIO */ - { 0, 0, 0, 0 } /* SOUND_MIXER_MONITOR */ -}; - -static void -waveartist_mixer_update(wavnc_info *devc, int whichDev) -{ - unsigned int lev_left, lev_right; - - lev_left = devc->levels[whichDev] & 0xff; - lev_right = devc->levels[whichDev] >> 8; - - if (lev_left > 100) - lev_left = 100; - if (lev_right > 100) - lev_right = 100; - -#define SCALE(lev,max) ((lev) * (max) / 100) - - if (machine_is_netwinder() && whichDev == SOUND_MIXER_PHONEOUT) - whichDev = SOUND_MIXER_VOLUME; - - if (mix_devs[whichDev].reg_l || mix_devs[whichDev].reg_r) { - const struct mix_ent *mix = mix_devs + whichDev; - unsigned int mask, left, right; - - mask = mix->max << mix->shift; - lev_left = SCALE(lev_left, mix->max) << mix->shift; - lev_right = SCALE(lev_right, mix->max) << mix->shift; - - /* read left setting */ - left = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | - mix->reg_l << 8); - - /* read right setting */ - right = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | - mix->reg_r << 8); - - left = (left & ~mask) | (lev_left & mask); - right = (right & ~mask) | (lev_right & mask); - - /* write left,right back */ - waveartist_cmd3(devc, WACMD_SET_MIXER, left, right); - } else { - switch(whichDev) { - case SOUND_MIXER_PCM: - waveartist_cmd3(devc, WACMD_SET_LEVEL, - SCALE(lev_left, 32767), - SCALE(lev_right, 32767)); - break; - - case SOUND_MIXER_SYNTH: - waveartist_cmd3(devc, 0x0100 | WACMD_SET_LEVEL, - SCALE(lev_left, 32767), - SCALE(lev_right, 32767)); - break; - } - } -} - -/* - * Set the ADC MUX to the specified values. We do NOT do any - * checking of the values passed, since we assume that the - * relevant *_select_input function has done that for us. - */ -static void -waveartist_set_adc_mux(wavnc_info *devc, char left_dev, char right_dev) -{ - unsigned int reg_08, reg_09; - - reg_08 = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x0800); - reg_09 = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x0900); - - reg_08 = (reg_08 & ~0x3f) | right_dev << 3 | left_dev; - - waveartist_cmd3(devc, WACMD_SET_MIXER, reg_08, reg_09); -} - -/* - * Decode a recording mask into a mixer selection as follows: - * - * OSS Source WA Source Actual source - * SOUND_MASK_IMIX Mixer Mixer output (same as AD1848) - * SOUND_MASK_LINE Line Line in - * SOUND_MASK_LINE1 Aux 1 Aux 1 in - * SOUND_MASK_LINE2 Aux 2 Aux 2 in - * SOUND_MASK_MIC Mic Microphone - */ -static unsigned int -waveartist_select_input(wavnc_info *devc, unsigned int recmask, - unsigned char *dev_l, unsigned char *dev_r) -{ - unsigned int recdev = ADC_MUX_NONE; - - if (recmask & SOUND_MASK_IMIX) { - recmask = SOUND_MASK_IMIX; - recdev = ADC_MUX_MIXER; - } else if (recmask & SOUND_MASK_LINE2) { - recmask = SOUND_MASK_LINE2; - recdev = ADC_MUX_AUX2; - } else if (recmask & SOUND_MASK_LINE1) { - recmask = SOUND_MASK_LINE1; - recdev = ADC_MUX_AUX1; - } else if (recmask & SOUND_MASK_LINE) { - recmask = SOUND_MASK_LINE; - recdev = ADC_MUX_LINE; - } else if (recmask & SOUND_MASK_MIC) { - recmask = SOUND_MASK_MIC; - recdev = ADC_MUX_MIC; - } - - *dev_l = *dev_r = recdev; - - return recmask; -} - -static int -waveartist_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, - unsigned char lev_r) -{ - switch (dev) { - case SOUND_MIXER_VOLUME: - case SOUND_MIXER_SYNTH: - case SOUND_MIXER_PCM: - case SOUND_MIXER_LINE: - case SOUND_MIXER_MIC: - case SOUND_MIXER_IGAIN: - case SOUND_MIXER_LINE1: - case SOUND_MIXER_LINE2: - devc->levels[dev] = lev_l | lev_r << 8; - break; - - case SOUND_MIXER_IMIX: - break; - - default: - dev = -EINVAL; - break; - } - - return dev; -} - -static int waveartist_get_mixer(wavnc_info *devc, int dev) -{ - return devc->levels[dev]; -} - -static const struct waveartist_mixer_info waveartist_mixer = { - .supported_devs = SUPPORTED_MIXER_DEVICES | SOUND_MASK_IGAIN, - .recording_devs = SOUND_MASK_LINE | SOUND_MASK_MIC | - SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | - SOUND_MASK_IMIX, - .stereo_devs = (SUPPORTED_MIXER_DEVICES | SOUND_MASK_IGAIN) & ~ - (SOUND_MASK_SPEAKER | SOUND_MASK_IMIX), - .select_input = waveartist_select_input, - .decode_mixer = waveartist_decode_mixer, - .get_mixer = waveartist_get_mixer, -}; - -static void -waveartist_set_recmask(wavnc_info *devc, unsigned int recmask) -{ - unsigned char dev_l, dev_r; - - recmask &= devc->mix->recording_devs; - - /* - * If more than one recording device selected, - * disable the device that is currently in use. - */ - if (hweight32(recmask) > 1) - recmask &= ~devc->recmask; - - /* - * Translate the recording device mask into - * the ADC multiplexer settings. - */ - devc->recmask = devc->mix->select_input(devc, recmask, - &dev_l, &dev_r); - - waveartist_set_adc_mux(devc, dev_l, dev_r); -} - -static int -waveartist_set_mixer(wavnc_info *devc, int dev, unsigned int level) -{ - unsigned int lev_left = level & 0x00ff; - unsigned int lev_right = (level & 0xff00) >> 8; - - if (lev_left > 100) - lev_left = 100; - if (lev_right > 100) - lev_right = 100; - - /* - * Mono devices have their right volume forced to their - * left volume. (from ALSA driver OSS emulation). - */ - if (!(devc->mix->stereo_devs & (1 << dev))) - lev_right = lev_left; - - dev = devc->mix->decode_mixer(devc, dev, lev_left, lev_right); - - if (dev >= 0) - waveartist_mixer_update(devc, dev); - - return dev < 0 ? dev : 0; -} - -static int -waveartist_mixer_ioctl(int dev, unsigned int cmd, void __user * arg) -{ - wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc; - int ret = 0, val, nr; - - /* - * All SOUND_MIXER_* ioctls use type 'M' - */ - if (((cmd >> 8) & 255) != 'M') - return -ENOIOCTLCMD; - -#ifdef CONFIG_ARCH_NETWINDER - if (machine_is_netwinder()) { - ret = vnc_private_ioctl(dev, cmd, arg); - if (ret != -ENOIOCTLCMD) - return ret; - else - ret = 0; - } -#endif - - nr = cmd & 0xff; - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) { - if (get_user(val, (int __user *)arg)) - return -EFAULT; - - switch (nr) { - case SOUND_MIXER_RECSRC: - waveartist_set_recmask(devc, val); - break; - - default: - ret = -EINVAL; - if (nr < SOUND_MIXER_NRDEVICES && - devc->mix->supported_devs & (1 << nr)) - ret = waveartist_set_mixer(devc, nr, val); - } - } - - if (ret == 0 && _SIOC_DIR(cmd) & _SIOC_READ) { - ret = -EINVAL; - - switch (nr) { - case SOUND_MIXER_RECSRC: - ret = devc->recmask; - break; - - case SOUND_MIXER_DEVMASK: - ret = devc->mix->supported_devs; - break; - - case SOUND_MIXER_STEREODEVS: - ret = devc->mix->stereo_devs; - break; - - case SOUND_MIXER_RECMASK: - ret = devc->mix->recording_devs; - break; - - case SOUND_MIXER_CAPS: - ret = SOUND_CAP_EXCL_INPUT; - break; - - default: - if (nr < SOUND_MIXER_NRDEVICES) - ret = devc->mix->get_mixer(devc, nr); - break; - } - - if (ret >= 0) - ret = put_user(ret, (int __user *)arg) ? -EFAULT : 0; - } - - return ret; -} - -static struct mixer_operations waveartist_mixer_operations = -{ - .owner = THIS_MODULE, - .id = "WaveArtist", - .name = "WaveArtist", - .ioctl = waveartist_mixer_ioctl -}; - -static void -waveartist_mixer_reset(wavnc_info *devc) -{ - int i; - - if (debug_flg & DEBUG_MIXER) - printk("%s: mixer_reset\n", devc->hw.name); - - /* - * reset mixer cmd - */ - waveartist_cmd1(devc, WACMD_RST_MIXER); - - /* - * set input for ADC to come from 'quiet' - * turn on default modes - */ - waveartist_cmd3(devc, WACMD_SET_MIXER, 0x9800, 0xa836); - - /* - * set mixer input select to none, RX filter gains 0 dB - */ - waveartist_cmd3(devc, WACMD_SET_MIXER, 0x4c00, 0x8c00); - - /* - * set bit 0 reg 2 to 1 - unmute MonoOut - */ - waveartist_cmd3(devc, WACMD_SET_MIXER, 0x2801, 0x6800); - - /* set default input device = internal mic - * current recording device = none - */ - waveartist_set_recmask(devc, 0); - - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - waveartist_mixer_update(devc, i); -} - -static int __init waveartist_init(wavnc_info *devc) -{ - wavnc_port_info *portc; - char rev[3], dev_name[64]; - int my_dev; - - if (waveartist_reset(devc)) - return -ENODEV; - - sprintf(dev_name, "%s (%s", devc->hw.name, devc->chip_name); - - if (waveartist_getrev(devc, rev)) { - strcat(dev_name, " rev. "); - strcat(dev_name, rev); - } - strcat(dev_name, ")"); - - conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq, - devc->hw.dma, devc->hw.dma2); - - portc = kzalloc(sizeof(wavnc_port_info), GFP_KERNEL); - if (portc == NULL) - goto nomem; - - my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name, - &waveartist_audio_driver, sizeof(struct audio_driver), - devc->audio_flags, AFMT_U8 | AFMT_S16_LE | AFMT_S8, - devc, devc->hw.dma, devc->hw.dma2); - - if (my_dev < 0) - goto free; - - audio_devs[my_dev]->portc = portc; - - waveartist_mixer_reset(devc); - - /* - * clear any pending interrupt - */ - waveartist_iack(devc); - - if (request_irq(devc->hw.irq, waveartist_intr, 0, devc->hw.name, devc) < 0) { - printk(KERN_ERR "%s: IRQ %d in use\n", - devc->hw.name, devc->hw.irq); - goto uninstall; - } - - if (sound_alloc_dma(devc->hw.dma, devc->hw.name)) { - printk(KERN_ERR "%s: Can't allocate DMA%d\n", - devc->hw.name, devc->hw.dma); - goto uninstall_irq; - } - - if (devc->hw.dma != devc->hw.dma2 && devc->hw.dma2 != NO_DMA) - if (sound_alloc_dma(devc->hw.dma2, devc->hw.name)) { - printk(KERN_ERR "%s: can't allocate DMA%d\n", - devc->hw.name, devc->hw.dma2); - goto uninstall_dma; - } - - waveartist_set_ctlr(&devc->hw, 0, DMA1_IE | DMA0_IE); - - audio_devs[my_dev]->mixer_dev = - sound_install_mixer(MIXER_DRIVER_VERSION, - dev_name, - &waveartist_mixer_operations, - sizeof(struct mixer_operations), - devc); - - return my_dev; - -uninstall_dma: - sound_free_dma(devc->hw.dma); - -uninstall_irq: - free_irq(devc->hw.irq, devc); - -uninstall: - sound_unload_audiodev(my_dev); - -free: - kfree(portc); - -nomem: - return -1; -} - -static int __init probe_waveartist(struct address_info *hw_config) -{ - wavnc_info *devc = &adev_info[nr_waveartist_devs]; - - if (nr_waveartist_devs >= MAX_AUDIO_DEV) { - printk(KERN_WARNING "waveartist: too many audio devices\n"); - return 0; - } - - if (!request_region(hw_config->io_base, 15, hw_config->name)) { - printk(KERN_WARNING "WaveArtist: I/O port conflict\n"); - return 0; - } - - if (hw_config->irq > 15 || hw_config->irq < 0) { - release_region(hw_config->io_base, 15); - printk(KERN_WARNING "WaveArtist: Bad IRQ %d\n", - hw_config->irq); - return 0; - } - - if (hw_config->dma != 3) { - release_region(hw_config->io_base, 15); - printk(KERN_WARNING "WaveArtist: Bad DMA %d\n", - hw_config->dma); - return 0; - } - - hw_config->name = "WaveArtist"; - devc->hw = *hw_config; - devc->open_mode = 0; - devc->chip_name = "RWA-010"; - - return 1; -} - -static void __init -attach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *mix) -{ - wavnc_info *devc = &adev_info[nr_waveartist_devs]; - - /* - * NOTE! If irq < 0, there is another driver which has allocated the - * IRQ so that this driver doesn't need to allocate/deallocate it. - * The actually used IRQ is ABS(irq). - */ - devc->hw = *hw; - devc->hw.irq = (hw->irq > 0) ? hw->irq : 0; - devc->open_mode = 0; - devc->playback_dev = 0; - devc->record_dev = 0; - devc->audio_flags = DMA_AUTOMODE; - devc->levels = levels; - - if (hw->dma != hw->dma2 && hw->dma2 != NO_DMA) - devc->audio_flags |= DMA_DUPLEX; - - devc->mix = mix; - devc->dev_no = waveartist_init(devc); - - if (devc->dev_no < 0) - release_region(hw->io_base, 15); - else { -#ifdef CONFIG_ARCH_NETWINDER - if (machine_is_netwinder()) { - init_timer(&vnc_timer); - vnc_timer.function = vnc_slider_tick; - vnc_timer.expires = jiffies; - vnc_timer.data = nr_waveartist_devs; - add_timer(&vnc_timer); - - vnc_configure_mixer(devc, 0); - - devc->no_autoselect = 1; - } -#endif - nr_waveartist_devs += 1; - } -} - -static void __exit unload_waveartist(struct address_info *hw) -{ - wavnc_info *devc = NULL; - int i; - - for (i = 0; i < nr_waveartist_devs; i++) - if (hw->io_base == adev_info[i].hw.io_base) { - devc = adev_info + i; - break; - } - - if (devc != NULL) { - int mixer; - -#ifdef CONFIG_ARCH_NETWINDER - if (machine_is_netwinder()) - del_timer(&vnc_timer); -#endif - - release_region(devc->hw.io_base, 15); - - waveartist_set_ctlr(&devc->hw, DMA1_IE|DMA0_IE, 0); - - if (devc->hw.irq >= 0) - free_irq(devc->hw.irq, devc); - - sound_free_dma(devc->hw.dma); - - if (devc->hw.dma != devc->hw.dma2 && - devc->hw.dma2 != NO_DMA) - sound_free_dma(devc->hw.dma2); - - mixer = audio_devs[devc->dev_no]->mixer_dev; - - if (mixer >= 0) - sound_unload_mixerdev(mixer); - - if (devc->dev_no >= 0) - sound_unload_audiodev(devc->dev_no); - - nr_waveartist_devs -= 1; - - for (; i < nr_waveartist_devs; i++) - adev_info[i] = adev_info[i + 1]; - } else - printk(KERN_WARNING "waveartist: can't find device " - "to unload\n"); -} - -#ifdef CONFIG_ARCH_NETWINDER - -/* - * Rebel.com Netwinder specifics... - */ - -#include - -#define VNC_TIMER_PERIOD (HZ/4) //check slider 4 times/sec - -#define MIXER_PRIVATE3_RESET 0x53570000 -#define MIXER_PRIVATE3_READ 0x53570001 -#define MIXER_PRIVATE3_WRITE 0x53570002 - -#define VNC_MUTE_INTERNAL_SPKR 0x01 //the sw mute on/off control bit -#define VNC_MUTE_LINE_OUT 0x10 -#define VNC_PHONE_DETECT 0x20 -#define VNC_HANDSET_DETECT 0x40 -#define VNC_DISABLE_AUTOSWITCH 0x80 - -static inline void -vnc_mute_spkr(wavnc_info *devc) -{ - unsigned long flags; - - spin_lock_irqsave(&nw_gpio_lock, flags); - nw_cpld_modify(CPLD_UNMUTE, devc->spkr_mute_state ? 0 : CPLD_UNMUTE); - spin_unlock_irqrestore(&nw_gpio_lock, flags); -} - -static void -vnc_mute_lout(wavnc_info *devc) -{ - unsigned int left, right; - - left = waveartist_cmd1_r(devc, WACMD_GET_LEVEL); - right = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x400); - - if (devc->line_mute_state) { - left &= ~1; - right &= ~1; - } else { - left |= 1; - right |= 1; - } - waveartist_cmd3(devc, WACMD_SET_MIXER, left, right); - -} - -static int -vnc_volume_slider(wavnc_info *devc) -{ - static signed int old_slider_volume; - unsigned long flags; - signed int volume = 255; - - *CSR_TIMER1_LOAD = 0x00ffffff; - - spin_lock_irqsave(&waveartist_lock, flags); - - outb(0xFF, 0x201); - *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV1; - - while (volume && (inb(0x201) & 0x01)) - volume--; - - *CSR_TIMER1_CNTL = 0; - - spin_unlock_irqrestore(&waveartist_lock,flags); - - volume = 0x00ffffff - *CSR_TIMER1_VALUE; - - -#ifndef REVERSE - volume = 150 - (volume >> 5); -#else - volume = (volume >> 6) - 25; -#endif - - if (volume < 0) - volume = 0; - - if (volume > 100) - volume = 100; - - /* - * slider quite often reads +-8, so debounce this random noise - */ - if (abs(volume - old_slider_volume) > 7) { - old_slider_volume = volume; - - if (debug_flg & DEBUG_MIXER) - printk(KERN_DEBUG "Slider volume: %d.\n", volume); - } - - return old_slider_volume; -} - -/* - * Decode a recording mask into a mixer selection on the NetWinder - * as follows: - * - * OSS Source WA Source Actual source - * SOUND_MASK_IMIX Mixer Mixer output (same as AD1848) - * SOUND_MASK_LINE Line Line in - * SOUND_MASK_LINE1 Left Mic Handset - * SOUND_MASK_PHONEIN Left Aux Telephone microphone - * SOUND_MASK_MIC Right Mic Builtin microphone - */ -static unsigned int -netwinder_select_input(wavnc_info *devc, unsigned int recmask, - unsigned char *dev_l, unsigned char *dev_r) -{ - unsigned int recdev_l = ADC_MUX_NONE, recdev_r = ADC_MUX_NONE; - - if (recmask & SOUND_MASK_IMIX) { - recmask = SOUND_MASK_IMIX; - recdev_l = ADC_MUX_MIXER; - recdev_r = ADC_MUX_MIXER; - } else if (recmask & SOUND_MASK_LINE) { - recmask = SOUND_MASK_LINE; - recdev_l = ADC_MUX_LINE; - recdev_r = ADC_MUX_LINE; - } else if (recmask & SOUND_MASK_LINE1) { - recmask = SOUND_MASK_LINE1; - waveartist_cmd1(devc, WACMD_SET_MONO); /* left */ - recdev_l = ADC_MUX_MIC; - recdev_r = ADC_MUX_NONE; - } else if (recmask & SOUND_MASK_PHONEIN) { - recmask = SOUND_MASK_PHONEIN; - waveartist_cmd1(devc, WACMD_SET_MONO); /* left */ - recdev_l = ADC_MUX_AUX1; - recdev_r = ADC_MUX_NONE; - } else if (recmask & SOUND_MASK_MIC) { - recmask = SOUND_MASK_MIC; - waveartist_cmd1(devc, WACMD_SET_MONO | 0x100); /* right */ - recdev_l = ADC_MUX_NONE; - recdev_r = ADC_MUX_MIC; - } - - *dev_l = recdev_l; - *dev_r = recdev_r; - - return recmask; -} - -static int -netwinder_decode_mixer(wavnc_info *devc, int dev, unsigned char lev_l, - unsigned char lev_r) -{ - switch (dev) { - case SOUND_MIXER_VOLUME: - case SOUND_MIXER_SYNTH: - case SOUND_MIXER_PCM: - case SOUND_MIXER_LINE: - case SOUND_MIXER_IGAIN: - devc->levels[dev] = lev_l | lev_r << 8; - break; - - case SOUND_MIXER_MIC: /* right mic only */ - devc->levels[SOUND_MIXER_MIC] &= 0xff; - devc->levels[SOUND_MIXER_MIC] |= lev_l << 8; - break; - - case SOUND_MIXER_LINE1: /* left mic only */ - devc->levels[SOUND_MIXER_MIC] &= 0xff00; - devc->levels[SOUND_MIXER_MIC] |= lev_l; - dev = SOUND_MIXER_MIC; - break; - - case SOUND_MIXER_PHONEIN: /* left aux only */ - devc->levels[SOUND_MIXER_LINE1] = lev_l; - dev = SOUND_MIXER_LINE1; - break; - - case SOUND_MIXER_IMIX: - case SOUND_MIXER_PHONEOUT: - break; - - default: - dev = -EINVAL; - break; - } - return dev; -} - -static int netwinder_get_mixer(wavnc_info *devc, int dev) -{ - int levels; - - switch (dev) { - case SOUND_MIXER_VOLUME: - case SOUND_MIXER_SYNTH: - case SOUND_MIXER_PCM: - case SOUND_MIXER_LINE: - case SOUND_MIXER_IGAIN: - levels = devc->levels[dev]; - break; - - case SOUND_MIXER_MIC: /* builtin mic: right mic only */ - levels = devc->levels[SOUND_MIXER_MIC] >> 8; - levels |= levels << 8; - break; - - case SOUND_MIXER_LINE1: /* handset mic: left mic only */ - levels = devc->levels[SOUND_MIXER_MIC] & 0xff; - levels |= levels << 8; - break; - - case SOUND_MIXER_PHONEIN: /* phone mic: left aux1 only */ - levels = devc->levels[SOUND_MIXER_LINE1] & 0xff; - levels |= levels << 8; - break; - - default: - levels = 0; - } - - return levels; -} - -/* - * Waveartist specific mixer information. - */ -static const struct waveartist_mixer_info netwinder_mixer = { - .supported_devs = SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | - SOUND_MASK_PCM | SOUND_MASK_SPEAKER | - SOUND_MASK_LINE | SOUND_MASK_MIC | - SOUND_MASK_IMIX | SOUND_MASK_LINE1 | - SOUND_MASK_PHONEIN | SOUND_MASK_PHONEOUT| - SOUND_MASK_IGAIN, - - .recording_devs = SOUND_MASK_LINE | SOUND_MASK_MIC | - SOUND_MASK_IMIX | SOUND_MASK_LINE1 | - SOUND_MASK_PHONEIN, - - .stereo_devs = SOUND_MASK_VOLUME | SOUND_MASK_SYNTH | - SOUND_MASK_PCM | SOUND_MASK_LINE | - SOUND_MASK_IMIX | SOUND_MASK_IGAIN, - - .select_input = netwinder_select_input, - .decode_mixer = netwinder_decode_mixer, - .get_mixer = netwinder_get_mixer, -}; - -static void -vnc_configure_mixer(wavnc_info *devc, unsigned int recmask) -{ - if (!devc->no_autoselect) { - if (devc->handset_detect) { - recmask = SOUND_MASK_LINE1; - devc->spkr_mute_state = devc->line_mute_state = 1; - } else if (devc->telephone_detect) { - recmask = SOUND_MASK_PHONEIN; - devc->spkr_mute_state = devc->line_mute_state = 1; - } else { - /* unless someone has asked for LINE-IN, - * we default to MIC - */ - if ((devc->recmask & SOUND_MASK_LINE) == 0) - devc->recmask = SOUND_MASK_MIC; - devc->spkr_mute_state = devc->line_mute_state = 0; - } - vnc_mute_spkr(devc); - vnc_mute_lout(devc); - - if (recmask != devc->recmask) - waveartist_set_recmask(devc, recmask); - } -} - -static int -vnc_slider(wavnc_info *devc) -{ - signed int slider_volume; - unsigned int temp, old_hs, old_td; - - /* - * read the "buttons" state. - * Bit 4 = 0 means handset present - * Bit 5 = 1 means phone offhook - */ - temp = inb(0x201); - - old_hs = devc->handset_detect; - old_td = devc->telephone_detect; - - devc->handset_detect = !(temp & 0x10); - devc->telephone_detect = !!(temp & 0x20); - - if (!devc->no_autoselect && - (old_hs != devc->handset_detect || - old_td != devc->telephone_detect)) - vnc_configure_mixer(devc, devc->recmask); - - slider_volume = vnc_volume_slider(devc); - - /* - * If we're using software controlled volume, and - * the slider moves by more than 20%, then we - * switch back to slider controlled volume. - */ - if (abs(devc->slider_vol - slider_volume) > 20) - devc->use_slider = 1; - - /* - * use only left channel - */ - temp = levels[SOUND_MIXER_VOLUME] & 0xFF; - - if (slider_volume != temp && devc->use_slider) { - devc->slider_vol = slider_volume; - - waveartist_set_mixer(devc, SOUND_MIXER_VOLUME, - slider_volume | slider_volume << 8); - - return 1; - } - - return 0; -} - -static void -vnc_slider_tick(unsigned long data) -{ - int next_timeout; - - if (vnc_slider(adev_info + data)) - next_timeout = 5; // mixer reported change - else - next_timeout = VNC_TIMER_PERIOD; - - mod_timer(&vnc_timer, jiffies + next_timeout); -} - -static int -vnc_private_ioctl(int dev, unsigned int cmd, int __user * arg) -{ - wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc; - int val; - - switch (cmd) { - case SOUND_MIXER_PRIVATE1: - { - u_int prev_spkr_mute, prev_line_mute, prev_auto_state; - int val; - - if (get_user(val, arg)) - return -EFAULT; - - /* check if parameter is logical */ - if (val & ~(VNC_MUTE_INTERNAL_SPKR | - VNC_MUTE_LINE_OUT | - VNC_DISABLE_AUTOSWITCH)) - return -EINVAL; - - prev_auto_state = devc->no_autoselect; - prev_spkr_mute = devc->spkr_mute_state; - prev_line_mute = devc->line_mute_state; - - devc->no_autoselect = (val & VNC_DISABLE_AUTOSWITCH) ? 1 : 0; - devc->spkr_mute_state = (val & VNC_MUTE_INTERNAL_SPKR) ? 1 : 0; - devc->line_mute_state = (val & VNC_MUTE_LINE_OUT) ? 1 : 0; - - if (prev_spkr_mute != devc->spkr_mute_state) - vnc_mute_spkr(devc); - - if (prev_line_mute != devc->line_mute_state) - vnc_mute_lout(devc); - - if (prev_auto_state != devc->no_autoselect) - vnc_configure_mixer(devc, devc->recmask); - - return 0; - } - - case SOUND_MIXER_PRIVATE2: - if (get_user(val, arg)) - return -EFAULT; - - switch (val) { -#define VNC_SOUND_PAUSE 0x53 //to pause the DSP -#define VNC_SOUND_RESUME 0x57 //to unpause the DSP - case VNC_SOUND_PAUSE: - waveartist_cmd1(devc, 0x16); - break; - - case VNC_SOUND_RESUME: - waveartist_cmd1(devc, 0x18); - break; - - default: - return -EINVAL; - } - return 0; - - /* private ioctl to allow bulk access to waveartist */ - case SOUND_MIXER_PRIVATE3: - { - unsigned long flags; - int mixer_reg[15], i, val; - - if (get_user(val, arg)) - return -EFAULT; - if (copy_from_user(mixer_reg, (void *)val, sizeof(mixer_reg))) - return -EFAULT; - - switch (mixer_reg[14]) { - case MIXER_PRIVATE3_RESET: - waveartist_mixer_reset(devc); - break; - - case MIXER_PRIVATE3_WRITE: - waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[0], mixer_reg[4]); - waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[1], mixer_reg[5]); - waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[2], mixer_reg[6]); - waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[3], mixer_reg[7]); - waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[8], mixer_reg[9]); - - waveartist_cmd3(devc, WACMD_SET_LEVEL, mixer_reg[10], mixer_reg[11]); - waveartist_cmd3(devc, WACMD_SET_LEVEL, mixer_reg[12], mixer_reg[13]); - break; - - case MIXER_PRIVATE3_READ: - spin_lock_irqsave(&waveartist_lock, flags); - - for (i = 0x30; i < 14 << 8; i += 1 << 8) - waveartist_cmd(devc, 1, &i, 1, mixer_reg + (i >> 8)); - - spin_unlock_irqrestore(&waveartist_lock, flags); - - if (copy_to_user((void *)val, mixer_reg, sizeof(mixer_reg))) - return -EFAULT; - break; - - default: - return -EINVAL; - } - return 0; - } - - /* read back the state from PRIVATE1 */ - case SOUND_MIXER_PRIVATE4: - val = (devc->spkr_mute_state ? VNC_MUTE_INTERNAL_SPKR : 0) | - (devc->line_mute_state ? VNC_MUTE_LINE_OUT : 0) | - (devc->handset_detect ? VNC_HANDSET_DETECT : 0) | - (devc->telephone_detect ? VNC_PHONE_DETECT : 0) | - (devc->no_autoselect ? VNC_DISABLE_AUTOSWITCH : 0); - - return put_user(val, arg) ? -EFAULT : 0; - } - - if (_SIOC_DIR(cmd) & _SIOC_WRITE) { - /* - * special case for master volume: if we - * received this call - switch from hw - * volume control to a software volume - * control, till the hw volume is modified - * to signal that user wants to be back in - * hardware... - */ - if ((cmd & 0xff) == SOUND_MIXER_VOLUME) - devc->use_slider = 0; - - /* speaker output */ - if ((cmd & 0xff) == SOUND_MIXER_SPEAKER) { - unsigned int val, l, r; - - if (get_user(val, arg)) - return -EFAULT; - - l = val & 0x7f; - r = (val & 0x7f00) >> 8; - val = (l + r) / 2; - devc->levels[SOUND_MIXER_SPEAKER] = val | (val << 8); - devc->spkr_mute_state = (val <= 50); - vnc_mute_spkr(devc); - return 0; - } - } - - return -ENOIOCTLCMD; -} - -#endif - -static struct address_info cfg; - -static int attached; - -static int __initdata io = 0; -static int __initdata irq = 0; -static int __initdata dma = 0; -static int __initdata dma2 = 0; - - -static int __init init_waveartist(void) -{ - const struct waveartist_mixer_info *mix; - - if (!io && machine_is_netwinder()) { - /* - * The NetWinder WaveArtist is at a fixed address. - * If the user does not supply an address, use the - * well-known parameters. - */ - io = 0x250; - irq = 12; - dma = 3; - dma2 = 7; - } - - mix = &waveartist_mixer; -#ifdef CONFIG_ARCH_NETWINDER - if (machine_is_netwinder()) - mix = &netwinder_mixer; -#endif - - cfg.io_base = io; - cfg.irq = irq; - cfg.dma = dma; - cfg.dma2 = dma2; - - if (!probe_waveartist(&cfg)) - return -ENODEV; - - attach_waveartist(&cfg, mix); - attached = 1; - - return 0; -} - -static void __exit cleanup_waveartist(void) -{ - if (attached) - unload_waveartist(&cfg); -} - -module_init(init_waveartist); -module_exit(cleanup_waveartist); - -#ifndef MODULE -static int __init setup_waveartist(char *str) -{ - /* io, irq, dma, dma2 */ - int ints[5]; - - str = get_options(str, ARRAY_SIZE(ints), ints); - - io = ints[1]; - irq = ints[2]; - dma = ints[3]; - dma2 = ints[4]; - - return 1; -} -__setup("waveartist=", setup_waveartist); -#endif - -MODULE_DESCRIPTION("Rockwell WaveArtist RWA-010 sound driver"); -module_param(io, int, 0); /* IO base */ -module_param(irq, int, 0); /* IRQ */ -module_param(dma, int, 0); /* DMA */ -module_param(dma2, int, 0); /* DMA2 */ -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/oss/waveartist.h b/ANDROID_3.4.5/sound/oss/waveartist.h deleted file mode 100644 index dac4ca91..00000000 --- a/ANDROID_3.4.5/sound/oss/waveartist.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * linux/sound/oss/waveartist.h - * - * def file for Rockwell RWA010 chip set, as installed in Rebel.com NetWinder - */ - -//registers -#define CMDR 0 -#define DATR 2 -#define CTLR 4 -#define STATR 5 -#define IRQSTAT 12 - -//bit defs -//reg STATR -#define CMD_WE 0x80 -#define CMD_RF 0x40 -#define DAT_WE 0x20 -#define DAT_RF 0x10 - -#define IRQ_REQ 0x08 -#define DMA1 0x04 -#define DMA0 0x02 - -//bit defs -//reg CTLR -#define CMD_WEIE 0x80 -#define CMD_RFIE 0x40 -#define DAT_WEIE 0x20 -#define DAT_RFIE 0x10 - -#define RESET 0x08 -#define DMA1_IE 0x04 -#define DMA0_IE 0x02 -#define IRQ_ACK 0x01 - -//commands - -#define WACMD_SYSTEMID 0x00 -#define WACMD_GETREV 0x00 -#define WACMD_INPUTFORMAT 0x10 //0-8S, 1-16S, 2-8U -#define WACMD_INPUTCHANNELS 0x11 //1-Mono, 2-Stereo -#define WACMD_INPUTSPEED 0x12 //sampling rate -#define WACMD_INPUTDMA 0x13 //0-8bit, 1-16bit, 2-PIO -#define WACMD_INPUTSIZE 0x14 //samples to interrupt -#define WACMD_INPUTSTART 0x15 //start ADC -#define WACMD_INPUTPAUSE 0x16 //pause ADC -#define WACMD_INPUTSTOP 0x17 //stop ADC -#define WACMD_INPUTRESUME 0x18 //resume ADC -#define WACMD_INPUTPIO 0x19 //PIO ADC - -#define WACMD_OUTPUTFORMAT 0x20 //0-8S, 1-16S, 2-8U -#define WACMD_OUTPUTCHANNELS 0x21 //1-Mono, 2-Stereo -#define WACMD_OUTPUTSPEED 0x22 //sampling rate -#define WACMD_OUTPUTDMA 0x23 //0-8bit, 1-16bit, 2-PIO -#define WACMD_OUTPUTSIZE 0x24 //samples to interrupt -#define WACMD_OUTPUTSTART 0x25 //start ADC -#define WACMD_OUTPUTPAUSE 0x26 //pause ADC -#define WACMD_OUTPUTSTOP 0x27 //stop ADC -#define WACMD_OUTPUTRESUME 0x28 //resume ADC -#define WACMD_OUTPUTPIO 0x29 //PIO ADC - -#define WACMD_GET_LEVEL 0x30 -#define WACMD_SET_LEVEL 0x31 -#define WACMD_SET_MIXER 0x32 -#define WACMD_RST_MIXER 0x33 -#define WACMD_SET_MONO 0x34 - -/* - * Definitions for left/right recording input mux - */ -#define ADC_MUX_NONE 0 -#define ADC_MUX_MIXER 1 -#define ADC_MUX_LINE 2 -#define ADC_MUX_AUX2 3 -#define ADC_MUX_AUX1 4 -#define ADC_MUX_MIC 5 - -/* - * Definitions for mixer gain settings - */ -#define MIX_GAIN_LINE 0 /* line in */ -#define MIX_GAIN_AUX1 1 /* aux1 */ -#define MIX_GAIN_AUX2 2 /* aux2 */ -#define MIX_GAIN_XMIC 3 /* crossover mic */ -#define MIX_GAIN_MIC 4 /* normal mic */ -#define MIX_GAIN_PREMIC 5 /* preamp mic */ -#define MIX_GAIN_OUT 6 /* output */ -#define MIX_GAIN_MONO 7 /* mono in */ - -int wa_sendcmd(unsigned int cmd); -int wa_writecmd(unsigned int cmd, unsigned int arg); diff --git a/ANDROID_3.4.5/sound/parisc/Kconfig b/ANDROID_3.4.5/sound/parisc/Kconfig deleted file mode 100644 index 9b61d950..00000000 --- a/ANDROID_3.4.5/sound/parisc/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -# ALSA PA-RISC drivers - -menuconfig SND_GSC - bool "GSC sound devices" - depends on GSC - default y - help - Support for GSC sound devices on PA-RISC architectures. - -if SND_GSC - -config SND_HARMONY - tristate "Harmony/Vivace sound chip" - select SND_PCM - help - Say 'Y' or 'M' to include support for the Harmony/Vivace sound - chip found in most GSC-based PA-RISC workstations. It's frequently - provided as part of the Lasi multi-function IC. - -endif # SND_GSC diff --git a/ANDROID_3.4.5/sound/parisc/Makefile b/ANDROID_3.4.5/sound/parisc/Makefile deleted file mode 100644 index b91e750a..00000000 --- a/ANDROID_3.4.5/sound/parisc/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# - -snd-harmony-objs := harmony.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_HARMONY) += snd-harmony.o diff --git a/ANDROID_3.4.5/sound/parisc/harmony.c b/ANDROID_3.4.5/sound/parisc/harmony.c deleted file mode 100644 index f47f9e22..00000000 --- a/ANDROID_3.4.5/sound/parisc/harmony.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* Hewlett-Packard Harmony audio driver - * - * This is a driver for the Harmony audio chipset found - * on the LASI ASIC of various early HP PA-RISC workstations. - * - * Copyright (C) 2004, Kyle McMartin - * - * Based on the previous Harmony incarnations by, - * Copyright 2000 (c) Linuxcare Canada, Alex deVries - * Copyright 2000-2003 (c) Helge Deller - * Copyright 2001 (c) Matthieu Delahaye - * Copyright 2001 (c) Jean-Christophe Vaugeois - * Copyright 2003 (c) Laurent Canet - * Copyright 2004 (c) Stuart Brady - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Notes: - * - graveyard and silence buffers last for lifetime of - * the driver. playback and capture buffers are allocated - * per _open()/_close(). - * - * TODO: - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "harmony.h" - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for Harmony driver."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for Harmony driver."); - - -static struct parisc_device_id snd_harmony_devtable[] = { - /* bushmaster / flounder */ - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, - /* 712 / 715 */ - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, - /* pace */ - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, - /* outfield / coral II */ - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, - { 0, } -}; - -MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable); - -#define NAME "harmony" -#define PFX NAME ": " - -static unsigned int snd_harmony_rates[] = { - 5512, 6615, 8000, 9600, - 11025, 16000, 18900, 22050, - 27428, 32000, 33075, 37800, - 44100, 48000 -}; - -static unsigned int rate_bits[14] = { - HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ, - HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ, - HARMONY_SR_18KHZ, HARMONY_SR_22KHZ, HARMONY_SR_27KHZ, - HARMONY_SR_32KHZ, HARMONY_SR_33KHZ, HARMONY_SR_37KHZ, - HARMONY_SR_44KHZ, HARMONY_SR_48KHZ -}; - -static struct snd_pcm_hw_constraint_list hw_constraint_rates = { - .count = ARRAY_SIZE(snd_harmony_rates), - .list = snd_harmony_rates, - .mask = 0, -}; - -static inline unsigned long -harmony_read(struct snd_harmony *h, unsigned r) -{ - return __raw_readl(h->iobase + r); -} - -static inline void -harmony_write(struct snd_harmony *h, unsigned r, unsigned long v) -{ - __raw_writel(v, h->iobase + r); -} - -static inline void -harmony_wait_for_control(struct snd_harmony *h) -{ - while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ; -} - -static inline void -harmony_reset(struct snd_harmony *h) -{ - harmony_write(h, HARMONY_RESET, 1); - mdelay(50); - harmony_write(h, HARMONY_RESET, 0); -} - -static void -harmony_disable_interrupts(struct snd_harmony *h) -{ - u32 dstatus; - harmony_wait_for_control(h); - dstatus = harmony_read(h, HARMONY_DSTATUS); - dstatus &= ~HARMONY_DSTATUS_IE; - harmony_write(h, HARMONY_DSTATUS, dstatus); -} - -static void -harmony_enable_interrupts(struct snd_harmony *h) -{ - u32 dstatus; - harmony_wait_for_control(h); - dstatus = harmony_read(h, HARMONY_DSTATUS); - dstatus |= HARMONY_DSTATUS_IE; - harmony_write(h, HARMONY_DSTATUS, dstatus); -} - -static void -harmony_mute(struct snd_harmony *h) -{ - unsigned long flags; - - spin_lock_irqsave(&h->mixer_lock, flags); - harmony_wait_for_control(h); - harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE); - spin_unlock_irqrestore(&h->mixer_lock, flags); -} - -static void -harmony_unmute(struct snd_harmony *h) -{ - unsigned long flags; - - spin_lock_irqsave(&h->mixer_lock, flags); - harmony_wait_for_control(h); - harmony_write(h, HARMONY_GAINCTL, h->st.gain); - spin_unlock_irqrestore(&h->mixer_lock, flags); -} - -static void -harmony_set_control(struct snd_harmony *h) -{ - u32 ctrl; - unsigned long flags; - - spin_lock_irqsave(&h->lock, flags); - - ctrl = (HARMONY_CNTL_C | - (h->st.format << 6) | - (h->st.stereo << 5) | - (h->st.rate)); - - harmony_wait_for_control(h); - harmony_write(h, HARMONY_CNTL, ctrl); - - spin_unlock_irqrestore(&h->lock, flags); -} - -static irqreturn_t -snd_harmony_interrupt(int irq, void *dev) -{ - u32 dstatus; - struct snd_harmony *h = dev; - - spin_lock(&h->lock); - harmony_disable_interrupts(h); - harmony_wait_for_control(h); - dstatus = harmony_read(h, HARMONY_DSTATUS); - spin_unlock(&h->lock); - - if (dstatus & HARMONY_DSTATUS_PN) { - if (h->psubs && h->st.playing) { - spin_lock(&h->lock); - h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */ - h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */ - - harmony_write(h, HARMONY_PNXTADD, - h->pbuf.addr + h->pbuf.buf); - h->stats.play_intr++; - spin_unlock(&h->lock); - snd_pcm_period_elapsed(h->psubs); - } else { - spin_lock(&h->lock); - harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); - h->stats.silence_intr++; - spin_unlock(&h->lock); - } - } - - if (dstatus & HARMONY_DSTATUS_RN) { - if (h->csubs && h->st.capturing) { - spin_lock(&h->lock); - h->cbuf.buf += h->cbuf.count; - h->cbuf.buf %= h->cbuf.size; - - harmony_write(h, HARMONY_RNXTADD, - h->cbuf.addr + h->cbuf.buf); - h->stats.rec_intr++; - spin_unlock(&h->lock); - snd_pcm_period_elapsed(h->csubs); - } else { - spin_lock(&h->lock); - harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); - h->stats.graveyard_intr++; - spin_unlock(&h->lock); - } - } - - spin_lock(&h->lock); - harmony_enable_interrupts(h); - spin_unlock(&h->lock); - - return IRQ_HANDLED; -} - -static unsigned int -snd_harmony_rate_bits(int rate) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(snd_harmony_rates); i++) - if (snd_harmony_rates[i] == rate) - return rate_bits[i]; - - return HARMONY_SR_44KHZ; -} - -static struct snd_pcm_hardware snd_harmony_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW | - SNDRV_PCM_FMTBIT_A_LAW), - .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_KNOT), - .rate_min = 5512, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = MAX_BUF_SIZE, - .period_bytes_min = BUF_SIZE, - .period_bytes_max = BUF_SIZE, - .periods_min = 1, - .periods_max = MAX_BUFS, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_harmony_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW | - SNDRV_PCM_FMTBIT_A_LAW), - .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_KNOT), - .rate_min = 5512, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = MAX_BUF_SIZE, - .period_bytes_min = BUF_SIZE, - .period_bytes_max = BUF_SIZE, - .periods_min = 1, - .periods_max = MAX_BUFS, - .fifo_size = 0, -}; - -static int -snd_harmony_playback_trigger(struct snd_pcm_substream *ss, int cmd) -{ - struct snd_harmony *h = snd_pcm_substream_chip(ss); - - if (h->st.capturing) - return -EBUSY; - - spin_lock(&h->lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - h->st.playing = 1; - harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr); - harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); - harmony_unmute(h); - harmony_enable_interrupts(h); - break; - case SNDRV_PCM_TRIGGER_STOP: - h->st.playing = 0; - harmony_mute(h); - harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); - harmony_disable_interrupts(h); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_SUSPEND: - default: - spin_unlock(&h->lock); - snd_BUG(); - return -EINVAL; - } - spin_unlock(&h->lock); - - return 0; -} - -static int -snd_harmony_capture_trigger(struct snd_pcm_substream *ss, int cmd) -{ - struct snd_harmony *h = snd_pcm_substream_chip(ss); - - if (h->st.playing) - return -EBUSY; - - spin_lock(&h->lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - h->st.capturing = 1; - harmony_write(h, HARMONY_PNXTADD, h->sdma.addr); - harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr); - harmony_unmute(h); - harmony_enable_interrupts(h); - break; - case SNDRV_PCM_TRIGGER_STOP: - h->st.capturing = 0; - harmony_mute(h); - harmony_write(h, HARMONY_RNXTADD, h->gdma.addr); - harmony_disable_interrupts(h); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_SUSPEND: - default: - spin_unlock(&h->lock); - snd_BUG(); - return -EINVAL; - } - spin_unlock(&h->lock); - - return 0; -} - -static int -snd_harmony_set_data_format(struct snd_harmony *h, int fmt, int force) -{ - int o = h->st.format; - int n; - - switch(fmt) { - case SNDRV_PCM_FORMAT_S16_BE: - n = HARMONY_DF_16BIT_LINEAR; - break; - case SNDRV_PCM_FORMAT_A_LAW: - n = HARMONY_DF_8BIT_ALAW; - break; - case SNDRV_PCM_FORMAT_MU_LAW: - n = HARMONY_DF_8BIT_ULAW; - break; - default: - n = HARMONY_DF_16BIT_LINEAR; - break; - } - - if (force || o != n) { - snd_pcm_format_set_silence(fmt, h->sdma.area, SILENCE_BUFSZ / - (snd_pcm_format_physical_width(fmt) - / 8)); - } - - return n; -} - -static int -snd_harmony_playback_prepare(struct snd_pcm_substream *ss) -{ - struct snd_harmony *h = snd_pcm_substream_chip(ss); - struct snd_pcm_runtime *rt = ss->runtime; - - if (h->st.capturing) - return -EBUSY; - - h->pbuf.size = snd_pcm_lib_buffer_bytes(ss); - h->pbuf.count = snd_pcm_lib_period_bytes(ss); - if (h->pbuf.buf >= h->pbuf.size) - h->pbuf.buf = 0; - h->st.playing = 0; - - h->st.rate = snd_harmony_rate_bits(rt->rate); - h->st.format = snd_harmony_set_data_format(h, rt->format, 0); - - if (rt->channels == 2) - h->st.stereo = HARMONY_SS_STEREO; - else - h->st.stereo = HARMONY_SS_MONO; - - harmony_set_control(h); - - h->pbuf.addr = rt->dma_addr; - - return 0; -} - -static int -snd_harmony_capture_prepare(struct snd_pcm_substream *ss) -{ - struct snd_harmony *h = snd_pcm_substream_chip(ss); - struct snd_pcm_runtime *rt = ss->runtime; - - if (h->st.playing) - return -EBUSY; - - h->cbuf.size = snd_pcm_lib_buffer_bytes(ss); - h->cbuf.count = snd_pcm_lib_period_bytes(ss); - if (h->cbuf.buf >= h->cbuf.size) - h->cbuf.buf = 0; - h->st.capturing = 0; - - h->st.rate = snd_harmony_rate_bits(rt->rate); - h->st.format = snd_harmony_set_data_format(h, rt->format, 0); - - if (rt->channels == 2) - h->st.stereo = HARMONY_SS_STEREO; - else - h->st.stereo = HARMONY_SS_MONO; - - harmony_set_control(h); - - h->cbuf.addr = rt->dma_addr; - - return 0; -} - -static snd_pcm_uframes_t -snd_harmony_playback_pointer(struct snd_pcm_substream *ss) -{ - struct snd_pcm_runtime *rt = ss->runtime; - struct snd_harmony *h = snd_pcm_substream_chip(ss); - unsigned long pcuradd; - unsigned long played; - - if (!(h->st.playing) || (h->psubs == NULL)) - return 0; - - if ((h->pbuf.addr == 0) || (h->pbuf.size == 0)) - return 0; - - pcuradd = harmony_read(h, HARMONY_PCURADD); - played = pcuradd - h->pbuf.addr; - -#ifdef HARMONY_DEBUG - printk(KERN_DEBUG PFX "playback_pointer is 0x%lx-0x%lx = %d bytes\n", - pcuradd, h->pbuf.addr, played); -#endif - - if (pcuradd > h->pbuf.addr + h->pbuf.size) { - return 0; - } - - return bytes_to_frames(rt, played); -} - -static snd_pcm_uframes_t -snd_harmony_capture_pointer(struct snd_pcm_substream *ss) -{ - struct snd_pcm_runtime *rt = ss->runtime; - struct snd_harmony *h = snd_pcm_substream_chip(ss); - unsigned long rcuradd; - unsigned long caught; - - if (!(h->st.capturing) || (h->csubs == NULL)) - return 0; - - if ((h->cbuf.addr == 0) || (h->cbuf.size == 0)) - return 0; - - rcuradd = harmony_read(h, HARMONY_RCURADD); - caught = rcuradd - h->cbuf.addr; - -#ifdef HARMONY_DEBUG - printk(KERN_DEBUG PFX "capture_pointer is 0x%lx-0x%lx = %d bytes\n", - rcuradd, h->cbuf.addr, caught); -#endif - - if (rcuradd > h->cbuf.addr + h->cbuf.size) { - return 0; - } - - return bytes_to_frames(rt, caught); -} - -static int -snd_harmony_playback_open(struct snd_pcm_substream *ss) -{ - struct snd_harmony *h = snd_pcm_substream_chip(ss); - struct snd_pcm_runtime *rt = ss->runtime; - int err; - - h->psubs = ss; - rt->hw = snd_harmony_playback; - snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraint_rates); - - err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) - return err; - - return 0; -} - -static int -snd_harmony_capture_open(struct snd_pcm_substream *ss) -{ - struct snd_harmony *h = snd_pcm_substream_chip(ss); - struct snd_pcm_runtime *rt = ss->runtime; - int err; - - h->csubs = ss; - rt->hw = snd_harmony_capture; - snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraint_rates); - - err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) - return err; - - return 0; -} - -static int -snd_harmony_playback_close(struct snd_pcm_substream *ss) -{ - struct snd_harmony *h = snd_pcm_substream_chip(ss); - h->psubs = NULL; - return 0; -} - -static int -snd_harmony_capture_close(struct snd_pcm_substream *ss) -{ - struct snd_harmony *h = snd_pcm_substream_chip(ss); - h->csubs = NULL; - return 0; -} - -static int -snd_harmony_hw_params(struct snd_pcm_substream *ss, - struct snd_pcm_hw_params *hw) -{ - int err; - struct snd_harmony *h = snd_pcm_substream_chip(ss); - - err = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw)); - if (err > 0 && h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS) - ss->runtime->dma_addr = __pa(ss->runtime->dma_area); - - return err; -} - -static int -snd_harmony_hw_free(struct snd_pcm_substream *ss) -{ - return snd_pcm_lib_free_pages(ss); -} - -static struct snd_pcm_ops snd_harmony_playback_ops = { - .open = snd_harmony_playback_open, - .close = snd_harmony_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_harmony_hw_params, - .hw_free = snd_harmony_hw_free, - .prepare = snd_harmony_playback_prepare, - .trigger = snd_harmony_playback_trigger, - .pointer = snd_harmony_playback_pointer, -}; - -static struct snd_pcm_ops snd_harmony_capture_ops = { - .open = snd_harmony_capture_open, - .close = snd_harmony_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_harmony_hw_params, - .hw_free = snd_harmony_hw_free, - .prepare = snd_harmony_capture_prepare, - .trigger = snd_harmony_capture_trigger, - .pointer = snd_harmony_capture_pointer, -}; - -static int -snd_harmony_pcm_init(struct snd_harmony *h) -{ - struct snd_pcm *pcm; - int err; - - if (snd_BUG_ON(!h)) - return -EINVAL; - - harmony_disable_interrupts(h); - - err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_harmony_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_harmony_capture_ops); - - pcm->private_data = h; - pcm->info_flags = 0; - strcpy(pcm->name, "harmony"); - h->pcm = pcm; - - h->psubs = NULL; - h->csubs = NULL; - - /* initialize graveyard buffer */ - h->dma.type = SNDRV_DMA_TYPE_DEV; - h->dma.dev = &h->dev->dev; - err = snd_dma_alloc_pages(h->dma.type, - h->dma.dev, - BUF_SIZE*GRAVEYARD_BUFS, - &h->gdma); - if (err < 0) { - printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n"); - return err; - } - - /* initialize silence buffers */ - err = snd_dma_alloc_pages(h->dma.type, - h->dma.dev, - BUF_SIZE*SILENCE_BUFS, - &h->sdma); - if (err < 0) { - printk(KERN_ERR PFX "cannot allocate silence buffer!\n"); - return err; - } - - /* pre-allocate space for DMA */ - err = snd_pcm_lib_preallocate_pages_for_all(pcm, h->dma.type, - h->dma.dev, - MAX_BUF_SIZE, - MAX_BUF_SIZE); - if (err < 0) { - printk(KERN_ERR PFX "buffer allocation error: %d\n", err); - return err; - } - - h->st.format = snd_harmony_set_data_format(h, - SNDRV_PCM_FORMAT_S16_BE, 1); - - return 0; -} - -static void -snd_harmony_set_new_gain(struct snd_harmony *h) -{ - harmony_wait_for_control(h); - harmony_write(h, HARMONY_GAINCTL, h->st.gain); -} - -static int -snd_harmony_mixercontrol_info(struct snd_kcontrol *kc, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kc->private_value >> 16) & 0xff; - int left_shift = (kc->private_value) & 0xff; - int right_shift = (kc->private_value >> 8) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : - SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = left_shift == right_shift ? 1 : 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - - return 0; -} - -static int -snd_harmony_volume_get(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_harmony *h = snd_kcontrol_chip(kc); - int shift_left = (kc->private_value) & 0xff; - int shift_right = (kc->private_value >> 8) & 0xff; - int mask = (kc->private_value >> 16) & 0xff; - int invert = (kc->private_value >> 24) & 0xff; - int left, right; - - spin_lock_irq(&h->mixer_lock); - - left = (h->st.gain >> shift_left) & mask; - right = (h->st.gain >> shift_right) & mask; - if (invert) { - left = mask - left; - right = mask - right; - } - - ucontrol->value.integer.value[0] = left; - if (shift_left != shift_right) - ucontrol->value.integer.value[1] = right; - - spin_unlock_irq(&h->mixer_lock); - - return 0; -} - -static int -snd_harmony_volume_put(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_harmony *h = snd_kcontrol_chip(kc); - int shift_left = (kc->private_value) & 0xff; - int shift_right = (kc->private_value >> 8) & 0xff; - int mask = (kc->private_value >> 16) & 0xff; - int invert = (kc->private_value >> 24) & 0xff; - int left, right; - int old_gain = h->st.gain; - - spin_lock_irq(&h->mixer_lock); - - left = ucontrol->value.integer.value[0] & mask; - if (invert) - left = mask - left; - h->st.gain &= ~( (mask << shift_left ) ); - h->st.gain |= (left << shift_left); - - if (shift_left != shift_right) { - right = ucontrol->value.integer.value[1] & mask; - if (invert) - right = mask - right; - h->st.gain &= ~( (mask << shift_right) ); - h->st.gain |= (right << shift_right); - } - - snd_harmony_set_new_gain(h); - - spin_unlock_irq(&h->mixer_lock); - - return h->st.gain != old_gain; -} - -static int -snd_harmony_captureroute_info(struct snd_kcontrol *kc, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { "Line", "Mic" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int -snd_harmony_captureroute_get(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_harmony *h = snd_kcontrol_chip(kc); - int value; - - spin_lock_irq(&h->mixer_lock); - - value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1; - ucontrol->value.enumerated.item[0] = value; - - spin_unlock_irq(&h->mixer_lock); - - return 0; -} - -static int -snd_harmony_captureroute_put(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_harmony *h = snd_kcontrol_chip(kc); - int value; - int old_gain = h->st.gain; - - spin_lock_irq(&h->mixer_lock); - - value = ucontrol->value.enumerated.item[0] & 1; - h->st.gain &= ~HARMONY_GAIN_IS_MASK; - h->st.gain |= value << HARMONY_GAIN_IS_SHIFT; - - snd_harmony_set_new_gain(h); - - spin_unlock_irq(&h->mixer_lock); - - return h->st.gain != old_gain; -} - -#define HARMONY_CONTROLS ARRAY_SIZE(snd_harmony_controls) - -#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_harmony_mixercontrol_info, \ - .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \ - .private_value = ((left_shift) | ((right_shift) << 8) | \ - ((mask) << 16) | ((invert) << 24)) } - -static struct snd_kcontrol_new snd_harmony_controls[] = { - HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT, - HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1), - HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT, - HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0), - HARMONY_VOLUME("Monitor Volume", HARMONY_GAIN_MA_SHIFT, - HARMONY_GAIN_MA_SHIFT, HARMONY_GAIN_MA, 1), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Route", - .info = snd_harmony_captureroute_info, - .get = snd_harmony_captureroute_get, - .put = snd_harmony_captureroute_put - }, - HARMONY_VOLUME("Internal Speaker Switch", HARMONY_GAIN_SE_SHIFT, - HARMONY_GAIN_SE_SHIFT, 1, 0), - HARMONY_VOLUME("Line-Out Switch", HARMONY_GAIN_LE_SHIFT, - HARMONY_GAIN_LE_SHIFT, 1, 0), - HARMONY_VOLUME("Headphones Switch", HARMONY_GAIN_HE_SHIFT, - HARMONY_GAIN_HE_SHIFT, 1, 0), -}; - -static void __devinit -snd_harmony_mixer_reset(struct snd_harmony *h) -{ - harmony_mute(h); - harmony_reset(h); - h->st.gain = HARMONY_GAIN_DEFAULT; - harmony_unmute(h); -} - -static int __devinit -snd_harmony_mixer_init(struct snd_harmony *h) -{ - struct snd_card *card; - int idx, err; - - if (snd_BUG_ON(!h)) - return -EINVAL; - card = h->card; - strcpy(card->mixername, "Harmony Gain control interface"); - - for (idx = 0; idx < HARMONY_CONTROLS; idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_harmony_controls[idx], h)); - if (err < 0) - return err; - } - - snd_harmony_mixer_reset(h); - - return 0; -} - -static int -snd_harmony_free(struct snd_harmony *h) -{ - if (h->gdma.addr) - snd_dma_free_pages(&h->gdma); - if (h->sdma.addr) - snd_dma_free_pages(&h->sdma); - - if (h->irq >= 0) - free_irq(h->irq, h); - - if (h->iobase) - iounmap(h->iobase); - - parisc_set_drvdata(h->dev, NULL); - - kfree(h); - return 0; -} - -static int -snd_harmony_dev_free(struct snd_device *dev) -{ - struct snd_harmony *h = dev->device_data; - return snd_harmony_free(h); -} - -static int __devinit -snd_harmony_create(struct snd_card *card, - struct parisc_device *padev, - struct snd_harmony **rchip) -{ - int err; - struct snd_harmony *h; - static struct snd_device_ops ops = { - .dev_free = snd_harmony_dev_free, - }; - - *rchip = NULL; - - h = kzalloc(sizeof(*h), GFP_KERNEL); - if (h == NULL) - return -ENOMEM; - - h->hpa = padev->hpa.start; - h->card = card; - h->dev = padev; - h->irq = -1; - h->iobase = ioremap_nocache(padev->hpa.start, HARMONY_SIZE); - if (h->iobase == NULL) { - printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n", - (unsigned long)padev->hpa.start); - err = -EBUSY; - goto free_and_ret; - } - - err = request_irq(padev->irq, snd_harmony_interrupt, 0, - "harmony", h); - if (err) { - printk(KERN_ERR PFX "could not obtain interrupt %d", - padev->irq); - goto free_and_ret; - } - h->irq = padev->irq; - - spin_lock_init(&h->mixer_lock); - spin_lock_init(&h->lock); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - h, &ops)) < 0) { - goto free_and_ret; - } - - snd_card_set_dev(card, &padev->dev); - - *rchip = h; - - return 0; - -free_and_ret: - snd_harmony_free(h); - return err; -} - -static int __devinit -snd_harmony_probe(struct parisc_device *padev) -{ - int err; - struct snd_card *card; - struct snd_harmony *h; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_harmony_create(card, padev, &h); - if (err < 0) - goto free_and_ret; - - err = snd_harmony_pcm_init(h); - if (err < 0) - goto free_and_ret; - - err = snd_harmony_mixer_init(h); - if (err < 0) - goto free_and_ret; - - strcpy(card->driver, "harmony"); - strcpy(card->shortname, "Harmony"); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, h->hpa, h->irq); - - err = snd_card_register(card); - if (err < 0) - goto free_and_ret; - - parisc_set_drvdata(padev, card); - return 0; - -free_and_ret: - snd_card_free(card); - return err; -} - -static int __devexit -snd_harmony_remove(struct parisc_device *padev) -{ - snd_card_free(parisc_get_drvdata(padev)); - parisc_set_drvdata(padev, NULL); - return 0; -} - -static struct parisc_driver snd_harmony_driver = { - .name = "harmony", - .id_table = snd_harmony_devtable, - .probe = snd_harmony_probe, - .remove = __devexit_p(snd_harmony_remove), -}; - -static int __init -alsa_harmony_init(void) -{ - return register_parisc_driver(&snd_harmony_driver); -} - -static void __exit -alsa_harmony_fini(void) -{ - unregister_parisc_driver(&snd_harmony_driver); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kyle McMartin "); -MODULE_DESCRIPTION("Harmony sound driver"); - -module_init(alsa_harmony_init); -module_exit(alsa_harmony_fini); diff --git a/ANDROID_3.4.5/sound/parisc/harmony.h b/ANDROID_3.4.5/sound/parisc/harmony.h deleted file mode 100644 index 2e434523..00000000 --- a/ANDROID_3.4.5/sound/parisc/harmony.h +++ /dev/null @@ -1,154 +0,0 @@ -/* Hewlett-Packard Harmony audio driver - * Copyright (C) 2004, Kyle McMartin - */ - -#ifndef __HARMONY_H__ -#define __HARMONY_H__ - -struct harmony_buffer { - unsigned long addr; - int buf; - int count; - int size; - int coherent; -}; - -struct snd_harmony { - int irq; - - unsigned long hpa; /* hard physical address */ - void __iomem *iobase; /* remapped io address */ - - struct parisc_device *dev; - - struct { - u32 gain; - u32 rate; - u32 format; - u32 stereo; - int playing; - int capturing; - } st; - - struct snd_dma_device dma; /* playback/capture */ - struct harmony_buffer pbuf; - struct harmony_buffer cbuf; - - struct snd_dma_buffer gdma; /* graveyard */ - struct snd_dma_buffer sdma; /* silence */ - - struct { - unsigned long play_intr; - unsigned long rec_intr; - unsigned long graveyard_intr; - unsigned long silence_intr; - } stats; - - struct snd_pcm *pcm; - struct snd_card *card; - struct snd_pcm_substream *psubs; - struct snd_pcm_substream *csubs; - struct snd_info_entry *proc; - - spinlock_t lock; - spinlock_t mixer_lock; -}; - -#define MAX_PCM_DEVICES 1 -#define MAX_PCM_SUBSTREAMS 4 -#define MAX_MIDI_DEVICES 0 - -#define HARMONY_SIZE 64 - -#define BUF_SIZE PAGE_SIZE -#define MAX_BUFS 16 -#define MAX_BUF_SIZE (MAX_BUFS * BUF_SIZE) - -#define PLAYBACK_BUFS MAX_BUFS -#define RECORD_BUFS MAX_BUFS -#define GRAVEYARD_BUFS 1 -#define GRAVEYARD_BUFSZ (GRAVEYARD_BUFS*BUF_SIZE) -#define SILENCE_BUFS 1 -#define SILENCE_BUFSZ (SILENCE_BUFS*BUF_SIZE) - -#define HARMONY_ID 0x000 -#define HARMONY_RESET 0x004 -#define HARMONY_CNTL 0x008 -#define HARMONY_GAINCTL 0x00c -#define HARMONY_PNXTADD 0x010 -#define HARMONY_PCURADD 0x014 -#define HARMONY_RNXTADD 0x018 -#define HARMONY_RCURADD 0x01c -#define HARMONY_DSTATUS 0x020 -#define HARMONY_OV 0x024 -#define HARMONY_PIO 0x028 -#define HARMONY_DIAG 0x03c - -#define HARMONY_CNTL_C 0x80000000 -#define HARMONY_CNTL_ST 0x00000020 -#define HARMONY_CNTL_44100 0x00000015 /* HARMONY_SR_44KHZ */ -#define HARMONY_CNTL_8000 0x00000008 /* HARMONY_SR_8KHZ */ - -#define HARMONY_DSTATUS_ID 0x00000000 /* interrupts off */ -#define HARMONY_DSTATUS_PN 0x00000200 /* playback fill */ -#define HARMONY_DSTATUS_RN 0x00000002 /* record fill */ -#define HARMONY_DSTATUS_IE 0x80000000 /* interrupts on */ - -#define HARMONY_DF_16BIT_LINEAR 0x00000000 -#define HARMONY_DF_8BIT_ULAW 0x00000001 -#define HARMONY_DF_8BIT_ALAW 0x00000002 - -#define HARMONY_SS_MONO 0x00000000 -#define HARMONY_SS_STEREO 0x00000001 - -#define HARMONY_GAIN_SILENCE 0x01F00FFF -#define HARMONY_GAIN_DEFAULT 0x01F00FFF - -#define HARMONY_GAIN_HE_SHIFT 27 /* headphones enabled */ -#define HARMONY_GAIN_HE_MASK (1 << HARMONY_GAIN_HE_SHIFT) -#define HARMONY_GAIN_LE_SHIFT 26 /* line-out enabled */ -#define HARMONY_GAIN_LE_MASK (1 << HARMONY_GAIN_LE_SHIFT) -#define HARMONY_GAIN_SE_SHIFT 25 /* internal-speaker enabled */ -#define HARMONY_GAIN_SE_MASK (1 << HARMONY_GAIN_SE_SHIFT) -#define HARMONY_GAIN_IS_SHIFT 24 /* input select - 0 for line, 1 for mic */ -#define HARMONY_GAIN_IS_MASK (1 << HARMONY_GAIN_IS_SHIFT) - -/* monitor attenuation */ -#define HARMONY_GAIN_MA 0x0f -#define HARMONY_GAIN_MA_SHIFT 20 -#define HARMONY_GAIN_MA_MASK (HARMONY_GAIN_MA << HARMONY_GAIN_MA_SHIFT) - -/* input gain */ -#define HARMONY_GAIN_IN 0x0f -#define HARMONY_GAIN_LI_SHIFT 16 -#define HARMONY_GAIN_LI_MASK (HARMONY_GAIN_IN << HARMONY_GAIN_LI_SHIFT) -#define HARMONY_GAIN_RI_SHIFT 12 -#define HARMONY_GAIN_RI_MASK (HARMONY_GAIN_IN << HARMONY_GAIN_RI_SHIFT) - -/* output gain (master volume) */ -#define HARMONY_GAIN_OUT 0x3f -#define HARMONY_GAIN_LO_SHIFT 6 -#define HARMONY_GAIN_LO_MASK (HARMONY_GAIN_OUT << HARMONY_GAIN_LO_SHIFT) -#define HARMONY_GAIN_RO_SHIFT 0 -#define HARMONY_GAIN_RO_MASK (HARMONY_GAIN_OUT << HARMONY_GAIN_RO_SHIFT) - -#define HARMONY_MAX_OUT (HARMONY_GAIN_RO_MASK >> HARMONY_GAIN_RO_SHIFT) -#define HARMONY_MAX_IN (HARMONY_GAIN_RI_MASK >> HARMONY_GAIN_RI_SHIFT) -#define HARMONY_MAX_MON (HARMONY_GAIN_MA_MASK >> HARMONY_GAIN_MA_SHIFT) - -#define HARMONY_SR_8KHZ 0x08 -#define HARMONY_SR_16KHZ 0x09 -#define HARMONY_SR_27KHZ 0x0A -#define HARMONY_SR_32KHZ 0x0B -#define HARMONY_SR_48KHZ 0x0E -#define HARMONY_SR_9KHZ 0x0F -#define HARMONY_SR_5KHZ 0x10 -#define HARMONY_SR_11KHZ 0x11 -#define HARMONY_SR_18KHZ 0x12 -#define HARMONY_SR_22KHZ 0x13 -#define HARMONY_SR_37KHZ 0x14 -#define HARMONY_SR_44KHZ 0x15 -#define HARMONY_SR_33KHZ 0x16 -#define HARMONY_SR_6KHZ 0x17 - -#endif /* __HARMONY_H__ */ diff --git a/ANDROID_3.4.5/sound/pci/Kconfig b/ANDROID_3.4.5/sound/pci/Kconfig deleted file mode 100644 index 5ca0939e..00000000 --- a/ANDROID_3.4.5/sound/pci/Kconfig +++ /dev/null @@ -1,872 +0,0 @@ -# ALSA PCI drivers - -config SND_TEA575X - tristate - depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO - default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO - -menuconfig SND_PCI - bool "PCI sound devices" - depends on PCI - default y - help - Support for sound devices connected via the PCI bus. - -if SND_PCI - -config SND_AD1889 - tristate "Analog Devices AD1889" - select SND_AC97_CODEC - help - Say Y here to include support for the integrated AC97 sound - device found in particular on the Hewlett-Packard [BCJ]-xxx0 - class PA-RISC workstations, using the AD1819 codec. - - To compile this as a module, choose M here: the module - will be called snd-ad1889. - -config SND_ALS300 - tristate "Avance Logic ALS300/ALS300+" - select SND_PCM - select SND_AC97_CODEC - select SND_OPL3_LIB - help - Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+ - - To compile this driver as a module, choose M here: the module - will be called snd-als300 - -config SND_ALS4000 - tristate "Avance Logic ALS4000" - depends on ISA_DMA_API - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - select SND_SB_COMMON - help - Say Y here to include support for soundcards based on Avance Logic - ALS4000 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-als4000. - -config SND_ALI5451 - tristate "ALi M5451 PCI Audio Controller" - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for the integrated AC97 sound - device on motherboards using the ALi M5451 Audio Controller - (M1535/M1535D/M1535+/M1535D+ south bridges). Newer chipsets - use the "Intel/SiS/nVidia/AMD/ALi AC97 Controller" driver. - - To compile this driver as a module, choose M here: the module - will be called snd-ali5451. - -config SND_ASIHPI - tristate "AudioScience ASIxxxx" - depends on X86 - select FW_LOADER - select SND_PCM - select SND_HWDEP - help - Say Y here to include support for AudioScience ASI sound cards. - - To compile this driver as a module, choose M here: the module - will be called snd-asihpi. - -config SND_ATIIXP - tristate "ATI IXP AC97 Controller" - select SND_AC97_CODEC - help - Say Y here to include support for the integrated AC97 sound - device on motherboards with ATI chipsets (ATI IXP 150/200/250/ - 300/400). - - To compile this driver as a module, choose M here: the module - will be called snd-atiixp. - -config SND_ATIIXP_MODEM - tristate "ATI IXP Modem" - select SND_AC97_CODEC - help - Say Y here to include support for the integrated MC97 modem on - motherboards with ATI chipsets (ATI IXP 150/200/250). - - To compile this driver as a module, choose M here: the module - will be called snd-atiixp-modem. - -config SND_AU8810 - tristate "Aureal Advantage" - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for Aureal Advantage soundcards. - - Supported features: Hardware Mixer, SRC, EQ and SPDIF output. - 3D support code is in place, but not yet useable. For more info, - email the ALSA developer list, or . - - To compile this driver as a module, choose M here: the module - will be called snd-au8810. - -config SND_AU8820 - tristate "Aureal Vortex" - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for Aureal Vortex soundcards. - - Supported features: Hardware Mixer and SRC. For more info, email - the ALSA developer list, or . - - To compile this driver as a module, choose M here: the module - will be called snd-au8820. - -config SND_AU8830 - tristate "Aureal Vortex 2" - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for Aureal Vortex 2 soundcards. - - Supported features: Hardware Mixer, SRC, EQ and SPDIF output. - 3D support code is in place, but not yet useable. For more info, - email the ALSA developer list, or . - - To compile this driver as a module, choose M here: the module - will be called snd-au8830. - -config SND_AW2 - tristate "Emagic Audiowerk 2" - help - Say Y here to include support for Emagic Audiowerk 2 soundcards. - - Supported features: Analog and SPDIF output. Analog or SPDIF input. - Note: Switch between analog and digital input does not always work. - It can produce continuous noise. The workaround is to switch again - (and again) between digital and analog input until it works. - - To compile this driver as a module, choose M here: the module - will be called snd-aw2. - - -config SND_AZT3328 - tristate "Aztech AZF3328 / PCI168" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - select SND_RAWMIDI - select SND_AC97_CODEC - help - Say Y here to include support for Aztech AZF3328 (PCI168) - soundcards. - - Supported features: AC97-"conformant" mixer, MPU401/OPL3, analog I/O - (16bit/8bit, many sample rates [<= 66.2kHz], NO hardware mixing), - Digital Enhanced Game Port, 1.024MHz multimedia sequencer timer, - ext. codec (I2S port), onboard amp (4W/4Ohms/ch), suspend/resume. - - To compile this driver as a module, choose M here: the module - will be called snd-azt3328. - -config SND_BT87X - tristate "Bt87x Audio Capture" - select SND_PCM - help - If you want to record audio from TV cards based on - Brooktree Bt878/Bt879 chips, say Y here and read - . - - To compile this driver as a module, choose M here: the module - will be called snd-bt87x. - -config SND_BT87X_OVERCLOCK - bool "Bt87x Audio overclocking" - depends on SND_BT87X - help - Say Y here if 448000 Hz isn't enough for you and you want to - record from the analog input with up to 1792000 Hz. - - Higher sample rates won't hurt your hardware, but audio - quality may suffer. - -config SND_CA0106 - tristate "SB Audigy LS / Live 24bit" - select SND_AC97_CODEC - select SND_RAWMIDI - select SND_VMASTER - help - Say Y here to include support for the Sound Blaster Audigy LS - and Live 24bit. - - To compile this driver as a module, choose M here: the module - will be called snd-ca0106. - -config SND_CMIPCI - tristate "C-Media 8338, 8738, 8768, 8770" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - If you want to use soundcards based on C-Media CMI8338, CMI8738, - CMI8768 or CMI8770 chips, say Y here and read - . - - To compile this driver as a module, choose M here: the module - will be called snd-cmipci. - -config SND_OXYGEN_LIB - tristate - -config SND_OXYGEN - tristate "C-Media 8786, 8787, 8788 (Oxygen)" - select SND_OXYGEN_LIB - select SND_PCM - select SND_MPU401_UART - help - Say Y here to include support for sound cards based on the - C-Media CMI8788 (Oxygen HD Audio) chip: - * Asound A-8788 - * Asus Xonar DG - * AuzenTech X-Meridian - * AuzenTech X-Meridian 2G - * Bgears b-Enspirer - * Club3D Theatron DTS - * HT-Omega Claro (plus) - * HT-Omega Claro halo (XT) - * Kuroutoshikou CMI8787-HG2PCI - * Razer Barracuda AC-1 - * Sondigo Inferno - * TempoTec/MediaTek HiFier Fantasia - * TempoTec/MediaTek HiFier Serenade - - To compile this driver as a module, choose M here: the module - will be called snd-oxygen. - -config SND_CS4281 - tristate "Cirrus Logic (Sound Fusion) CS4281" - select SND_OPL3_LIB - select SND_RAWMIDI - select SND_AC97_CODEC - help - Say Y here to include support for Cirrus Logic CS4281 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-cs4281. - -config SND_CS46XX - tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x" - select SND_RAWMIDI - select SND_AC97_CODEC - help - Say Y here to include support for Cirrus Logic CS4610/CS4612/ - CS4614/CS4615/CS4622/CS4624/CS4630/CS4280 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-cs46xx. - -config SND_CS46XX_NEW_DSP - bool "Cirrus Logic (Sound Fusion) New DSP support" - depends on SND_CS46XX - default y - help - Say Y here to use a new DSP image for SPDIF and dual codecs. - - This works better than the old code, so say Y. - -config SND_CS5530 - tristate "CS5530 Audio" - depends on ISA_DMA_API - select SND_SB16_DSP - help - Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-cs5530. - -config SND_CS5535AUDIO - tristate "CS5535/CS5536 Audio" - select SND_PCM - select SND_AC97_CODEC - help - Say Y here to include support for audio on CS5535 chips. It is - referred to as NS CS5535 IO or AMD CS5535 IO companion in - various literature. This driver also supports the CS5536 audio - device. However, for both chips, on certain boards, you may - need to use ac97_quirk=hp_only if your board has physically - mapped headphone out to master output. If that works for you, - send lspci -vvv output to the mailing list so that your board - can be identified in the quirks list. - - To compile this driver as a module, choose M here: the module - will be called snd-cs5535audio. - -config SND_CTXFI - tristate "Creative Sound Blaster X-Fi" - select SND_PCM - help - If you want to use soundcards based on Creative Sound Blastr X-Fi - boards with 20k1 or 20k2 chips, say Y here. - - To compile this driver as a module, choose M here: the module - will be called snd-ctxfi. - -config SND_DARLA20 - tristate "(Echoaudio) Darla20" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Darla. - - To compile this driver as a module, choose M here: the module - will be called snd-darla20 - -config SND_GINA20 - tristate "(Echoaudio) Gina20" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Gina. - - To compile this driver as a module, choose M here: the module - will be called snd-gina20 - -config SND_LAYLA20 - tristate "(Echoaudio) Layla20" - select FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Layla. - - To compile this driver as a module, choose M here: the module - will be called snd-layla20 - -config SND_DARLA24 - tristate "(Echoaudio) Darla24" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Darla24. - - To compile this driver as a module, choose M here: the module - will be called snd-darla24 - -config SND_GINA24 - tristate "(Echoaudio) Gina24" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Gina24. - - To compile this driver as a module, choose M here: the module - will be called snd-gina24 - -config SND_LAYLA24 - tristate "(Echoaudio) Layla24" - select FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Layla24. - - To compile this driver as a module, choose M here: the module - will be called snd-layla24 - -config SND_MONA - tristate "(Echoaudio) Mona" - select FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Mona. - - To compile this driver as a module, choose M here: the module - will be called snd-mona - -config SND_MIA - tristate "(Echoaudio) Mia" - select FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Mia and Mia-midi. - - To compile this driver as a module, choose M here: the module - will be called snd-mia - -config SND_ECHO3G - tristate "(Echoaudio) 3G cards" - select FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Gina3G and Layla3G. - - To compile this driver as a module, choose M here: the module - will be called snd-echo3g - -config SND_INDIGO - tristate "(Echoaudio) Indigo" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Indigo. - - To compile this driver as a module, choose M here: the module - will be called snd-indigo - -config SND_INDIGOIO - tristate "(Echoaudio) Indigo IO" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Indigo IO. - - To compile this driver as a module, choose M here: the module - will be called snd-indigoio - -config SND_INDIGODJ - tristate "(Echoaudio) Indigo DJ" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Indigo DJ. - - To compile this driver as a module, choose M here: the module - will be called snd-indigodj - -config SND_INDIGOIOX - tristate "(Echoaudio) Indigo IOx" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Indigo IOx. - - To compile this driver as a module, choose M here: the module - will be called snd-indigoiox - -config SND_INDIGODJX - tristate "(Echoaudio) Indigo DJx" - select FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Indigo DJx. - - To compile this driver as a module, choose M here: the module - will be called snd-indigodjx - -config SND_EMU10K1 - tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)" - select FW_LOADER - select SND_HWDEP - select SND_RAWMIDI - select SND_AC97_CODEC - help - Say Y to include support for Sound Blaster PCI 512, Live!, - Audigy and E-mu APS (partially supported) soundcards. - - The confusing multitude of mixer controls is documented in - and - . - - To compile this driver as a module, choose M here: the module - will be called snd-emu10k1. - -config SND_EMU10K1X - tristate "Emu10k1X (Dell OEM Version)" - select SND_AC97_CODEC - select SND_RAWMIDI - help - Say Y here to include support for the Dell OEM version of the - Sound Blaster Live!. - - To compile this driver as a module, choose M here: the module - will be called snd-emu10k1x. - -config SND_ENS1370 - tristate "(Creative) Ensoniq AudioPCI 1370" - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for Ensoniq AudioPCI ES1370 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-ens1370. - -config SND_ENS1371 - tristate "(Creative) Ensoniq AudioPCI 1371/1373" - select SND_RAWMIDI - select SND_AC97_CODEC - help - Say Y here to include support for Ensoniq AudioPCI ES1371 chips and - Sound Blaster PCI 64 or 128 soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-ens1371. - -config SND_ES1938 - tristate "ESS ES1938/1946/1969 (Solo-1)" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for soundcards based on ESS Solo-1 - (ES1938, ES1946, ES1969) chips. - - To compile this driver as a module, choose M here: the module - will be called snd-es1938. - -config SND_ES1968 - tristate "ESS ES1968/1978 (Maestro-1/2/2E)" - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for soundcards based on ESS Maestro - 1/2/2E chips. - - To compile this driver as a module, choose M here: the module - will be called snd-es1968. - -config SND_ES1968_INPUT - bool "Enable input device for es1968 volume buttons" - depends on SND_ES1968 - depends on INPUT=y || INPUT=SND_ES1968 - help - If you say Y here, you will get an input device which reports - keypresses for the volume buttons connected to the es1968 chip. - If you say N the buttons will directly control the master volume. - It is recommended to say Y. - -config SND_ES1968_RADIO - bool "Enable TEA5757 radio tuner support for es1968" - depends on SND_ES1968 - depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 - help - Say Y here to include support for TEA5757 radio tuner integrated on - some MediaForte cards (e.g. SF64-PCE2). - -config SND_FM801 - tristate "ForteMedia FM801" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for soundcards based on the ForteMedia - FM801 chip. - - To compile this driver as a module, choose M here: the module - will be called snd-fm801. - -config SND_FM801_TEA575X_BOOL - bool "ForteMedia FM801 + TEA5757 tuner" - depends on SND_FM801 - depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 - help - Say Y here to include support for soundcards based on the ForteMedia - FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and - SF64-PCR) into the snd-fm801 driver. - -source "sound/pci/hda/Kconfig" - -config SND_HDSP - tristate "RME Hammerfall DSP Audio" - select SND_HWDEP - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for RME Hammerfall DSP Audio - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-hdsp. - -comment "Don't forget to add built-in firmwares for HDSP driver" - depends on SND_HDSP=y - -config SND_HDSPM - tristate "RME Hammerfall DSP MADI/RayDAT/AIO" - select SND_HWDEP - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for RME Hammerfall DSP MADI, - RayDAT and AIO soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-hdspm. - -config SND_ICE1712 - tristate "ICEnsemble ICE1712 (Envy24)" - select SND_MPU401_UART - select SND_AC97_CODEC - select BITREVERSE - help - Say Y here to include support for soundcards based on the - ICE1712 (Envy24) chip. - - Currently supported hardware is: M-Audio Delta 1010(LT), - DiO 2496, 66, 44, 410, Audiophile 24/96; Digigram VX442; - TerraTec EWX 24/96, EWS 88MT/D, DMX 6Fire, Phase 88; - Hoontech SoundTrack DSP 24/Value/Media7.1; Event EZ8; - Lionstracs Mediastation, Terrasoniq TS 88. - - To compile this driver as a module, choose M here: the module - will be called snd-ice1712. - -config SND_ICE1724 - tristate "ICE/VT1724/1720 (Envy24HT/PT)" - select SND_RAWMIDI - select SND_AC97_CODEC - select SND_VMASTER - help - Say Y here to include support for soundcards based on - ICE/VT1724/1720 (Envy24HT/PT) chips. - - Currently supported hardware is: AMP AUDIO2000; M-Audio - Revolution 5.1, 7.1, Audiophile 192; TerraTec Aureon 5.1 Sky, - 7.1 Space/Universe, Phase 22/28; Onkyo SE-90PCI, SE-200PCI; - AudioTrak Prodigy 192, 7.1 (HIFI/LT/XT), HD2; Hercules - Fortissimo IV; ESI Juli@; Pontis MS300; EGO-SYS WaveTerminal - 192M; Albatron K8X800 Pro II; Chaintech ZNF3-150/250, 9CJS, - AV-710; Shuttle SN25P. - - To compile this driver as a module, choose M here: the module - will be called snd-ice1724. - -config SND_INTEL8X0 - tristate "Intel/SiS/nVidia/AMD/ALi AC97 Controller" - select SND_AC97_CODEC - help - Say Y here to include support for the integrated AC97 sound - device on motherboards with Intel/SiS/nVidia/AMD chipsets, or - ALi chipsets using the M5455 Audio Controller. (There is a - separate driver for ALi M5451 Audio Controllers.) - - To compile this driver as a module, choose M here: the module - will be called snd-intel8x0. - -config SND_INTEL8X0M - tristate "Intel/SiS/nVidia/AMD MC97 Modem" - select SND_AC97_CODEC - help - Say Y here to include support for the integrated MC97 modem on - motherboards with Intel/SiS/nVidia/AMD chipsets. - - To compile this driver as a module, choose M here: the module - will be called snd-intel8x0m. - -config SND_KORG1212 - tristate "Korg 1212 IO" - select SND_PCM - help - Say Y here to include support for Korg 1212IO soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-korg1212. - -config SND_LOLA - tristate "Digigram Lola" - select SND_PCM - help - Say Y to include support for Digigram Lola boards. - - To compile this driver as a module, choose M here: the module - will be called snd-lola. - -config SND_LX6464ES - tristate "Digigram LX6464ES" - select SND_PCM - help - Say Y here to include support for Digigram LX6464ES boards. - - To compile this driver as a module, choose M here: the module - will be called snd-lx6464es. - - -config SND_MAESTRO3 - tristate "ESS Allegro/Maestro3" - select SND_AC97_CODEC - help - Say Y here to include support for soundcards based on ESS Maestro 3 - (Allegro) chips. - - To compile this driver as a module, choose M here: the module - will be called snd-maestro3. - -config SND_MAESTRO3_INPUT - bool "Enable input device for maestro3 volume buttons" - depends on SND_MAESTRO3 - depends on INPUT=y || INPUT=SND_MAESTRO3 - help - If you say Y here, you will get an input device which reports - keypresses for the volume buttons connected to the maestro3 chip. - If you say N the buttons will directly control the master volume. - It is recommended to say Y. - -config SND_MIXART - tristate "Digigram miXart" - select SND_HWDEP - select SND_PCM - help - If you want to use Digigram miXart soundcards, say Y here and - read . - - To compile this driver as a module, choose M here: the module - will be called snd-mixart. - -config SND_NM256 - tristate "NeoMagic NM256AV/ZX" - select SND_AC97_CODEC - help - Say Y here to include support for NeoMagic NM256AV/ZX chips. - - To compile this driver as a module, choose M here: the module - will be called snd-nm256. - -config SND_PCXHR - tristate "Digigram PCXHR" - select SND_PCM - select SND_HWDEP - help - Say Y here to include support for Digigram PCXHR boards. - - To compile this driver as a module, choose M here: the module - will be called snd-pcxhr. - -config SND_RIPTIDE - tristate "Conexant Riptide" - select FW_LOADER - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say 'Y' or 'M' to include support for Conexant Riptide chip. - - To compile this driver as a module, choose M here: the module - will be called snd-riptide - -config SND_RME32 - tristate "RME Digi32, 32/8, 32 PRO" - select SND_PCM - help - Say Y to include support for RME Digi32, Digi32 PRO and - Digi32/8 (Sek'd Prodif32, Prodif96 and Prodif Gold) audio - devices. - - To compile this driver as a module, choose M here: the module - will be called snd-rme32. - -config SND_RME96 - tristate "RME Digi96, 96/8, 96/8 PRO" - select SND_PCM - help - Say Y here to include support for RME Digi96, Digi96/8 and - Digi96/8 PRO/PAD/PST soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-rme96. - -config SND_RME9652 - tristate "RME Digi9652 (Hammerfall)" - select SND_PCM - help - Say Y here to include support for RME Hammerfall (RME - Digi9652/Digi9636) soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-rme9652. - -config SND_SIS7019 - tristate "SiS 7019 Audio Accelerator" - depends on X86 && !X86_64 - select SND_AC97_CODEC - help - Say Y here to include support for the SiS 7019 Audio Accelerator. - - To compile this driver as a module, choose M here: the module - will be called snd-sis7019. - -config SND_SONICVIBES - tristate "S3 SonicVibes" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for soundcards based on the S3 - SonicVibes chip. - - To compile this driver as a module, choose M here: the module - will be called snd-sonicvibes. - -config SND_TRIDENT - tristate "Trident 4D-Wave DX/NX; SiS 7018" - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for soundcards based on Trident - 4D-Wave DX/NX or SiS 7018 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-trident. - -config SND_VIA82XX - tristate "VIA 82C686A/B, 8233/8235 AC97 Controller" - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for the integrated AC97 sound - device on motherboards with VIA chipsets. - - To compile this driver as a module, choose M here: the module - will be called snd-via82xx. - -config SND_VIA82XX_MODEM - tristate "VIA 82C686A/B, 8233 based Modems" - select SND_AC97_CODEC - help - Say Y here to include support for the integrated MC97 modem on - motherboards with VIA chipsets. - - To compile this driver as a module, choose M here: the module - will be called snd-via82xx-modem. - -config SND_VIRTUOSO - tristate "Asus Virtuoso 66/100/200 (Xonar)" - select SND_OXYGEN_LIB - select SND_PCM - select SND_MPU401_UART - select SND_JACK if INPUT=y || INPUT=SND - help - Say Y here to include support for sound cards based on the - Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, - Essence ST (Deluxe), and Essence STX. - Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental; - for the Xense, missing. - - To compile this driver as a module, choose M here: the module - will be called snd-virtuoso. - -config SND_VX222 - tristate "Digigram VX222" - select SND_VX_LIB - help - Say Y here to include support for Digigram VX222 soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-vx222. - -config SND_YMFPCI - tristate "Yamaha YMF724/740/744/754" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_AC97_CODEC - help - Say Y here to include support for Yamaha PCI audio chips - - YMF724, YMF724F, YMF740, YMF740C, YMF744, YMF754. - - To compile this driver as a module, choose M here: the module - will be called snd-ymfpci. - -endif # SND_PCI diff --git a/ANDROID_3.4.5/sound/pci/Makefile b/ANDROID_3.4.5/sound/pci/Makefile deleted file mode 100644 index 54fe325e..00000000 --- a/ANDROID_3.4.5/sound/pci/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-ad1889-objs := ad1889.o -snd-als300-objs := als300.o -snd-als4000-objs := als4000.o -snd-atiixp-objs := atiixp.o -snd-atiixp-modem-objs := atiixp_modem.o -snd-azt3328-objs := azt3328.o -snd-bt87x-objs := bt87x.o -snd-cmipci-objs := cmipci.o -snd-cs4281-objs := cs4281.o -snd-cs5530-objs := cs5530.o -snd-ens1370-objs := ens1370.o ak4531_codec.o -snd-ens1371-objs := ens1371.o -snd-es1938-objs := es1938.o -snd-es1968-objs := es1968.o -snd-fm801-objs := fm801.o -snd-intel8x0-objs := intel8x0.o -snd-intel8x0m-objs := intel8x0m.o -snd-maestro3-objs := maestro3.o -snd-rme32-objs := rme32.o -snd-rme96-objs := rme96.o -snd-sis7019-objs := sis7019.o -snd-sonicvibes-objs := sonicvibes.o -snd-via82xx-objs := via82xx.o -snd-via82xx-modem-objs := via82xx_modem.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AD1889) += snd-ad1889.o -obj-$(CONFIG_SND_ALS300) += snd-als300.o -obj-$(CONFIG_SND_ALS4000) += snd-als4000.o -obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o -obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o -obj-$(CONFIG_SND_AZT3328) += snd-azt3328.o -obj-$(CONFIG_SND_BT87X) += snd-bt87x.o -obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o -obj-$(CONFIG_SND_CS4281) += snd-cs4281.o -obj-$(CONFIG_SND_CS5530) += snd-cs5530.o -obj-$(CONFIG_SND_ENS1370) += snd-ens1370.o -obj-$(CONFIG_SND_ENS1371) += snd-ens1371.o -obj-$(CONFIG_SND_ES1938) += snd-es1938.o -obj-$(CONFIG_SND_ES1968) += snd-es1968.o -obj-$(CONFIG_SND_FM801) += snd-fm801.o -obj-$(CONFIG_SND_INTEL8X0) += snd-intel8x0.o -obj-$(CONFIG_SND_INTEL8X0M) += snd-intel8x0m.o -obj-$(CONFIG_SND_MAESTRO3) += snd-maestro3.o -obj-$(CONFIG_SND_RME32) += snd-rme32.o -obj-$(CONFIG_SND_RME96) += snd-rme96.o -obj-$(CONFIG_SND_SIS7019) += snd-sis7019.o -obj-$(CONFIG_SND_SONICVIBES) += snd-sonicvibes.o -obj-$(CONFIG_SND_VIA82XX) += snd-via82xx.o -obj-$(CONFIG_SND_VIA82XX_MODEM) += snd-via82xx-modem.o - -obj-$(CONFIG_SND) += \ - ac97/ \ - ali5451/ \ - asihpi/ \ - au88x0/ \ - aw2/ \ - ctxfi/ \ - ca0106/ \ - cs46xx/ \ - cs5535audio/ \ - lola/ \ - lx6464es/ \ - echoaudio/ \ - emu10k1/ \ - hda/ \ - ice1712/ \ - korg1212/ \ - mixart/ \ - nm256/ \ - oxygen/ \ - pcxhr/ \ - riptide/ \ - rme9652/ \ - trident/ \ - ymfpci/ \ - vx222/ diff --git a/ANDROID_3.4.5/sound/pci/ac97/Makefile b/ANDROID_3.4.5/sound/pci/ac97/Makefile deleted file mode 100644 index 41fa322f..00000000 --- a/ANDROID_3.4.5/sound/pci/ac97/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-ac97-codec-y := ac97_codec.o ac97_pcm.o -snd-ac97-codec-$(CONFIG_PROC_FS) += ac97_proc.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o diff --git a/ANDROID_3.4.5/sound/pci/ac97/ac97_codec.c b/ANDROID_3.4.5/sound/pci/ac97/ac97_codec.c deleted file mode 100644 index 9473fca9..00000000 --- a/ANDROID_3.4.5/sound/pci/ac97/ac97_codec.c +++ /dev/null @@ -1,2937 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Universal interface for Audio Codec '97 - * - * For more details look to AC '97 component specification revision 2.2 - * by Intel Corporation (http://developer.intel.com). - * - * - * 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 -#include -#include -#include -#include "ac97_id.h" - -#include "ac97_patch.c" - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Universal interface for Audio Codec '97"); -MODULE_LICENSE("GPL"); - -static bool enable_loopback; - -module_param(enable_loopback, bool, 0444); -MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); - -#ifdef CONFIG_SND_AC97_POWER_SAVE -static int power_save = CONFIG_SND_AC97_POWER_SAVE_DEFAULT; -module_param(power_save, int, 0644); -MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " - "(in second, 0 = disable)."); -#endif -/* - - */ - -struct ac97_codec_id { - unsigned int id; - unsigned int mask; - const char *name; - int (*patch)(struct snd_ac97 *ac97); - int (*mpatch)(struct snd_ac97 *ac97); - unsigned int flags; -}; - -static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = { -{ 0x41445300, 0xffffff00, "Analog Devices", NULL, NULL }, -{ 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL }, -{ 0x414c4300, 0xffffff00, "Realtek", NULL, NULL }, -{ 0x414c4700, 0xffffff00, "Realtek", NULL, NULL }, -/* - * This is an _inofficial_ Aztech Labs entry - * (value might differ from unknown official Aztech ID), - * currently used by the AC97 emulation of the almost-AC97 PCI168 card. - */ -{ 0x415a5400, 0xffffff00, "Aztech Labs (emulated)", NULL, NULL }, -{ 0x434d4900, 0xffffff00, "C-Media Electronics", NULL, NULL }, -{ 0x43525900, 0xffffff00, "Cirrus Logic", NULL, NULL }, -{ 0x43585400, 0xffffff00, "Conexant", NULL, NULL }, -{ 0x44543000, 0xffffff00, "Diamond Technology", NULL, NULL }, -{ 0x454d4300, 0xffffff00, "eMicro", NULL, NULL }, -{ 0x45838300, 0xffffff00, "ESS Technology", NULL, NULL }, -{ 0x48525300, 0xffffff00, "Intersil", NULL, NULL }, -{ 0x49434500, 0xffffff00, "ICEnsemble", NULL, NULL }, -{ 0x49544500, 0xffffff00, "ITE Tech.Inc", NULL, NULL }, -{ 0x4e534300, 0xffffff00, "National Semiconductor", NULL, NULL }, -{ 0x50534300, 0xffffff00, "Philips", NULL, NULL }, -{ 0x53494c00, 0xffffff00, "Silicon Laboratory", NULL, NULL }, -{ 0x53544d00, 0xffffff00, "STMicroelectronics", NULL, NULL }, -{ 0x54524100, 0xffffff00, "TriTech", NULL, NULL }, -{ 0x54584e00, 0xffffff00, "Texas Instruments", NULL, NULL }, -{ 0x56494100, 0xffffff00, "VIA Technologies", NULL, NULL }, -{ 0x57454300, 0xffffff00, "Winbond", NULL, NULL }, -{ 0x574d4c00, 0xffffff00, "Wolfson", NULL, NULL }, -{ 0x594d4800, 0xffffff00, "Yamaha", NULL, NULL }, -{ 0x83847600, 0xffffff00, "SigmaTel", NULL, NULL }, -{ 0, 0, NULL, NULL, NULL } -}; - -static const struct ac97_codec_id snd_ac97_codec_ids[] = { -{ 0x41445303, 0xffffffff, "AD1819", patch_ad1819, NULL }, -{ 0x41445340, 0xffffffff, "AD1881", patch_ad1881, NULL }, -{ 0x41445348, 0xffffffff, "AD1881A", patch_ad1881, NULL }, -{ 0x41445360, 0xffffffff, "AD1885", patch_ad1885, NULL }, -{ 0x41445361, 0xffffffff, "AD1886", patch_ad1886, NULL }, -{ 0x41445362, 0xffffffff, "AD1887", patch_ad1881, NULL }, -{ 0x41445363, 0xffffffff, "AD1886A", patch_ad1881, NULL }, -{ 0x41445368, 0xffffffff, "AD1888", patch_ad1888, NULL }, -{ 0x41445370, 0xffffffff, "AD1980", patch_ad1980, NULL }, -{ 0x41445372, 0xffffffff, "AD1981A", patch_ad1981a, NULL }, -{ 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL }, -{ 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL }, -{ 0x41445378, 0xffffffff, "AD1986", patch_ad1986, NULL }, -{ 0x414b4d00, 0xffffffff, "AK4540", NULL, NULL }, -{ 0x414b4d01, 0xffffffff, "AK4542", NULL, NULL }, -{ 0x414b4d02, 0xffffffff, "AK4543", NULL, NULL }, -{ 0x414b4d06, 0xffffffff, "AK4544A", NULL, NULL }, -{ 0x414b4d07, 0xffffffff, "AK4545", NULL, NULL }, -{ 0x414c4300, 0xffffff00, "ALC100,100P", NULL, NULL }, -{ 0x414c4710, 0xfffffff0, "ALC200,200P", NULL, NULL }, -{ 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */ -{ 0x414c4722, 0xffffffff, "ALC650E", NULL, NULL }, /* already patched */ -{ 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */ -{ 0x414c4720, 0xfffffff0, "ALC650", patch_alc650, NULL }, -{ 0x414c4730, 0xffffffff, "ALC101", NULL, NULL }, -{ 0x414c4740, 0xfffffff0, "ALC202", NULL, NULL }, -{ 0x414c4750, 0xfffffff0, "ALC250", NULL, NULL }, -{ 0x414c4760, 0xfffffff0, "ALC655", patch_alc655, NULL }, -{ 0x414c4770, 0xfffffff0, "ALC203", patch_alc203, NULL }, -{ 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */ -{ 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL }, -{ 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL }, -{ 0x415a5401, 0xffffffff, "AZF3328", patch_aztech_azf3328, NULL }, -{ 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL }, -{ 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL }, -{ 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL }, -{ 0x434d4978, 0xffffffff, "CMI9761A", patch_cm9761, NULL }, -{ 0x434d4982, 0xffffffff, "CMI9761B", patch_cm9761, NULL }, -{ 0x434d4983, 0xffffffff, "CMI9761A+", patch_cm9761, NULL }, -{ 0x43525900, 0xfffffff8, "CS4297", NULL, NULL }, -{ 0x43525910, 0xfffffff8, "CS4297A", patch_cirrus_spdif, NULL }, -{ 0x43525920, 0xfffffff8, "CS4298", patch_cirrus_spdif, NULL }, -{ 0x43525928, 0xfffffff8, "CS4294", NULL, NULL }, -{ 0x43525930, 0xfffffff8, "CS4299", patch_cirrus_cs4299, NULL }, -{ 0x43525948, 0xfffffff8, "CS4201", NULL, NULL }, -{ 0x43525958, 0xfffffff8, "CS4205", patch_cirrus_spdif, NULL }, -{ 0x43525960, 0xfffffff8, "CS4291", NULL, NULL }, -{ 0x43525970, 0xfffffff8, "CS4202", NULL, NULL }, -{ 0x43585421, 0xffffffff, "HSD11246", NULL, NULL }, // SmartMC II -{ 0x43585428, 0xfffffff8, "Cx20468", patch_conexant, NULL }, // SmartAMC fixme: the mask might be different -{ 0x43585430, 0xffffffff, "Cx20468-31", patch_conexant, NULL }, -{ 0x43585431, 0xffffffff, "Cx20551", patch_cx20551, NULL }, -{ 0x44543031, 0xfffffff0, "DT0398", NULL, NULL }, -{ 0x454d4328, 0xffffffff, "EM28028", NULL, NULL }, // same as TR28028? -{ 0x45838308, 0xffffffff, "ESS1988", NULL, NULL }, -{ 0x48525300, 0xffffff00, "HMP9701", NULL, NULL }, -{ 0x49434501, 0xffffffff, "ICE1230", NULL, NULL }, -{ 0x49434511, 0xffffffff, "ICE1232", NULL, NULL }, // alias VIA VT1611A? -{ 0x49434514, 0xffffffff, "ICE1232A", NULL, NULL }, -{ 0x49434551, 0xffffffff, "VT1616", patch_vt1616, NULL }, -{ 0x49434552, 0xffffffff, "VT1616i", patch_vt1616, NULL }, // VT1616 compatible (chipset integrated) -{ 0x49544520, 0xffffffff, "IT2226E", NULL, NULL }, -{ 0x49544561, 0xffffffff, "IT2646E", patch_it2646, NULL }, -{ 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk -{ 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, -{ 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume wrap fix -{ 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL }, -{ 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, -{ 0x53544d02, 0xffffffff, "ST7597", NULL, NULL }, -{ 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, -{ 0x54524103, 0xffffffff, "TR28023", NULL, NULL }, -{ 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, -{ 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99] -{ 0x54524123, 0xffffffff, "TR28602", NULL, NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)] -{ 0x54584e20, 0xffffffff, "TLC320AD9xC", NULL, NULL }, -{ 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF -{ 0x56494170, 0xffffffff, "VIA1617A", patch_vt1617a, NULL }, // modified VT1616 with S/PDIF -{ 0x56494182, 0xffffffff, "VIA1618", patch_vt1618, NULL }, -{ 0x57454301, 0xffffffff, "W83971D", NULL, NULL }, -{ 0x574d4c00, 0xffffffff, "WM9701,WM9701A", NULL, NULL }, -{ 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL}, -{ 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL}, -{ 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL}, -{ 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, -{ 0x574d4C12, 0xffffffff, "WM9711,WM9712,WM9715", patch_wolfson11, NULL}, -{ 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, -{ 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL }, -{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, -{ 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL }, -{ 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL }, -{ 0x83847604, 0xffffffff, "STAC9701,3,4,5", NULL, NULL }, -{ 0x83847605, 0xffffffff, "STAC9704", NULL, NULL }, -{ 0x83847608, 0xffffffff, "STAC9708,11", patch_sigmatel_stac9708, NULL }, -{ 0x83847609, 0xffffffff, "STAC9721,23", patch_sigmatel_stac9721, NULL }, -{ 0x83847644, 0xffffffff, "STAC9744", patch_sigmatel_stac9744, NULL }, -{ 0x83847650, 0xffffffff, "STAC9750,51", NULL, NULL }, // patch? -{ 0x83847652, 0xffffffff, "STAC9752,53", NULL, NULL }, // patch? -{ 0x83847656, 0xffffffff, "STAC9756,57", patch_sigmatel_stac9756, NULL }, -{ 0x83847658, 0xffffffff, "STAC9758,59", patch_sigmatel_stac9758, NULL }, -{ 0x83847666, 0xffffffff, "STAC9766,67", NULL, NULL }, // patch? -{ 0, 0, NULL, NULL, NULL } -}; - - -static void update_power_regs(struct snd_ac97 *ac97); -#ifdef CONFIG_SND_AC97_POWER_SAVE -#define ac97_is_power_save_mode(ac97) \ - ((ac97->scaps & AC97_SCAP_POWER_SAVE) && power_save) -#else -#define ac97_is_power_save_mode(ac97) 0 -#endif - - -/* - * I/O routines - */ - -static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg) -{ - /* filter some registers for buggy codecs */ - switch (ac97->id) { - case AC97_ID_ST_AC97_ID4: - if (reg == 0x08) - return 0; - /* fall through */ - case AC97_ID_ST7597: - if (reg == 0x22 || reg == 0x7a) - return 1; - /* fall through */ - case AC97_ID_AK4540: - case AC97_ID_AK4542: - if (reg <= 0x1c || reg == 0x20 || reg == 0x26 || reg >= 0x7c) - return 1; - return 0; - case AC97_ID_AD1819: /* AD1819 */ - case AC97_ID_AD1881: /* AD1881 */ - case AC97_ID_AD1881A: /* AD1881A */ - if (reg >= 0x3a && reg <= 0x6e) /* 0x59 */ - return 0; - return 1; - case AC97_ID_AD1885: /* AD1885 */ - case AC97_ID_AD1886: /* AD1886 */ - case AC97_ID_AD1886A: /* AD1886A - !!verify!! --jk */ - case AC97_ID_AD1887: /* AD1887 - !!verify!! --jk */ - if (reg == 0x5a) - return 1; - if (reg >= 0x3c && reg <= 0x6e) /* 0x59 */ - return 0; - return 1; - case AC97_ID_STAC9700: - case AC97_ID_STAC9704: - case AC97_ID_STAC9705: - case AC97_ID_STAC9708: - case AC97_ID_STAC9721: - case AC97_ID_STAC9744: - case AC97_ID_STAC9756: - if (reg <= 0x3a || reg >= 0x5a) - return 1; - return 0; - } - return 1; -} - -/** - * snd_ac97_write - write a value on the given register - * @ac97: the ac97 instance - * @reg: the register to change - * @value: the value to set - * - * Writes a value on the given register. This will invoke the write - * callback directly after the register check. - * This function doesn't change the register cache unlike - * #snd_ca97_write_cache(), so use this only when you don't want to - * reflect the change to the suspend/resume state. - */ -void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short value) -{ - if (!snd_ac97_valid_reg(ac97, reg)) - return; - if ((ac97->id & 0xffffff00) == AC97_ID_ALC100) { - /* Fix H/W bug of ALC100/100P */ - if (reg == AC97_MASTER || reg == AC97_HEADPHONE) - ac97->bus->ops->write(ac97, AC97_RESET, 0); /* reset audio codec */ - } - ac97->bus->ops->write(ac97, reg, value); -} - -EXPORT_SYMBOL(snd_ac97_write); - -/** - * snd_ac97_read - read a value from the given register - * - * @ac97: the ac97 instance - * @reg: the register to read - * - * Reads a value from the given register. This will invoke the read - * callback directly after the register check. - * - * Returns the read value. - */ -unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - if (!snd_ac97_valid_reg(ac97, reg)) - return 0; - return ac97->bus->ops->read(ac97, reg); -} - -/* read a register - return the cached value if already read */ -static inline unsigned short snd_ac97_read_cache(struct snd_ac97 *ac97, unsigned short reg) -{ - if (! test_bit(reg, ac97->reg_accessed)) { - ac97->regs[reg] = ac97->bus->ops->read(ac97, reg); - // set_bit(reg, ac97->reg_accessed); - } - return ac97->regs[reg]; -} - -EXPORT_SYMBOL(snd_ac97_read); - -/** - * snd_ac97_write_cache - write a value on the given register and update the cache - * @ac97: the ac97 instance - * @reg: the register to change - * @value: the value to set - * - * Writes a value on the given register and updates the register - * cache. The cached values are used for the cached-read and the - * suspend/resume. - */ -void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned short value) -{ - if (!snd_ac97_valid_reg(ac97, reg)) - return; - mutex_lock(&ac97->reg_mutex); - ac97->regs[reg] = value; - ac97->bus->ops->write(ac97, reg, value); - set_bit(reg, ac97->reg_accessed); - mutex_unlock(&ac97->reg_mutex); -} - -EXPORT_SYMBOL(snd_ac97_write_cache); - -/** - * snd_ac97_update - update the value on the given register - * @ac97: the ac97 instance - * @reg: the register to change - * @value: the value to set - * - * Compares the value with the register cache and updates the value - * only when the value is changed. - * - * Returns 1 if the value is changed, 0 if no change, or a negative - * code on failure. - */ -int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value) -{ - int change; - - if (!snd_ac97_valid_reg(ac97, reg)) - return -EINVAL; - mutex_lock(&ac97->reg_mutex); - change = ac97->regs[reg] != value; - if (change) { - ac97->regs[reg] = value; - ac97->bus->ops->write(ac97, reg, value); - } - set_bit(reg, ac97->reg_accessed); - mutex_unlock(&ac97->reg_mutex); - return change; -} - -EXPORT_SYMBOL(snd_ac97_update); - -/** - * snd_ac97_update_bits - update the bits on the given register - * @ac97: the ac97 instance - * @reg: the register to change - * @mask: the bit-mask to change - * @value: the value to set - * - * Updates the masked-bits on the given register only when the value - * is changed. - * - * Returns 1 if the bits are changed, 0 if no change, or a negative - * code on failure. - */ -int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value) -{ - int change; - - if (!snd_ac97_valid_reg(ac97, reg)) - return -EINVAL; - mutex_lock(&ac97->reg_mutex); - change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); - mutex_unlock(&ac97->reg_mutex); - return change; -} - -EXPORT_SYMBOL(snd_ac97_update_bits); - -/* no lock version - see snd_ac97_update_bits() */ -int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, - unsigned short mask, unsigned short value) -{ - int change; - unsigned short old, new; - - old = snd_ac97_read_cache(ac97, reg); - new = (old & ~mask) | (value & mask); - change = old != new; - if (change) { - ac97->regs[reg] = new; - ac97->bus->ops->write(ac97, reg, new); - } - set_bit(reg, ac97->reg_accessed); - return change; -} - -static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, unsigned short mask, unsigned short value) -{ - int change; - unsigned short old, new, cfg; - - mutex_lock(&ac97->page_mutex); - old = ac97->spec.ad18xx.pcmreg[codec]; - new = (old & ~mask) | (value & mask); - change = old != new; - if (change) { - mutex_lock(&ac97->reg_mutex); - cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); - ac97->spec.ad18xx.pcmreg[codec] = new; - /* select single codec */ - ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, - (cfg & ~0x7000) | - ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); - /* update PCM bits */ - ac97->bus->ops->write(ac97, AC97_PCM, new); - /* select all codecs */ - ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG, - cfg | 0x7000); - mutex_unlock(&ac97->reg_mutex); - } - mutex_unlock(&ac97->page_mutex); - return change; -} - -/* - * Controls - */ - -static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = e->shift_l == e->shift_r ? 1 : 2; - uinfo->value.enumerated.items = e->mask; - - if (uinfo->value.enumerated.item > e->mask - 1) - uinfo->value.enumerated.item = e->mask - 1; - strcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; - unsigned short val, bitmask; - - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) - ; - val = snd_ac97_read_cache(ac97, e->reg); - ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); - if (e->shift_l != e->shift_r) - ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1); - - return 0; -} - -static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; - unsigned short val; - unsigned short mask, bitmask; - - for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) - ; - if (ucontrol->value.enumerated.item[0] > e->mask - 1) - return -EINVAL; - val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = (bitmask - 1) << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->mask - 1) - return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; - } - return snd_ac97_update_bits(ac97, e->reg, mask, val); -} - -/* save/restore ac97 v2.3 paging */ -static int snd_ac97_page_save(struct snd_ac97 *ac97, int reg, struct snd_kcontrol *kcontrol) -{ - int page_save = -1; - if ((kcontrol->private_value & (1<<25)) && - (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 && - (reg >= 0x60 && reg < 0x70)) { - unsigned short page = (kcontrol->private_value >> 26) & 0x0f; - mutex_lock(&ac97->page_mutex); /* lock paging */ - page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); - } - return page_save; -} - -static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save) -{ - if (page_save >= 0) { - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - mutex_unlock(&ac97->page_mutex); /* unlock paging */ - } -} - -/* volume and switch controls */ -static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = shift == rshift ? 1 : 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0x01; - int page_save; - - page_save = snd_ac97_page_save(ac97, reg, kcontrol); - ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask; - if (shift != rshift) - ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> rshift) & mask; - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - if (shift != rshift) - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - snd_ac97_page_restore(ac97, page_save); - return 0; -} - -static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0x01; - int err, page_save; - unsigned short val, val2, val_mask; - - page_save = snd_ac97_page_save(ac97, reg, kcontrol); - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val_mask = mask << shift; - val = val << shift; - if (shift != rshift) { - val2 = (ucontrol->value.integer.value[1] & mask); - if (invert) - val2 = mask - val2; - val_mask |= mask << rshift; - val |= val2 << rshift; - } - err = snd_ac97_update_bits(ac97, reg, val_mask, val); - snd_ac97_page_restore(ac97, page_save); -#ifdef CONFIG_SND_AC97_POWER_SAVE - /* check analog mixer power-down */ - if ((val_mask & AC97_PD_EAPD) && - (kcontrol->private_value & (1<<30))) { - if (val & AC97_PD_EAPD) - ac97->power_up &= ~(1 << (reg>>1)); - else - ac97->power_up |= 1 << (reg>>1); - update_power_regs(ac97); - } -#endif - return err; -} - -static const struct snd_kcontrol_new snd_ac97_controls_master_mono[2] = { -AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), -AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_tone[2] = { -AC97_SINGLE("Tone Control - Bass", AC97_MASTER_TONE, 8, 15, 1), -AC97_SINGLE("Tone Control - Treble", AC97_MASTER_TONE, 0, 15, 1) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_pc_beep[2] = { -AC97_SINGLE("Beep Playback Switch", AC97_PC_BEEP, 15, 1, 1), -AC97_SINGLE("Beep Playback Volume", AC97_PC_BEEP, 1, 15, 1) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = - AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0); - - -static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; -static const char* std_3d_path[] = {"pre 3D", "post 3D"}; -static const char* std_mix[] = {"Mix", "Mic"}; -static const char* std_mic[] = {"Mic1", "Mic2"}; - -static const struct ac97_enum std_enum[] = { -AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, std_rec_sel), -AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, std_3d_path), -AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, std_mix), -AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, std_mic), -}; - -static const struct snd_kcontrol_new snd_ac97_control_capture_src = -AC97_ENUM("Capture Source", std_enum[0]); - -static const struct snd_kcontrol_new snd_ac97_control_capture_vol = -AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0); - -static const struct snd_kcontrol_new snd_ac97_controls_mic_capture[2] = { -AC97_SINGLE("Mic Capture Switch", AC97_REC_GAIN_MIC, 15, 1, 1), -AC97_SINGLE("Mic Capture Volume", AC97_REC_GAIN_MIC, 0, 15, 0) -}; - -enum { - AC97_GENERAL_PCM_OUT = 0, - AC97_GENERAL_STEREO_ENHANCEMENT, - AC97_GENERAL_3D, - AC97_GENERAL_LOUDNESS, - AC97_GENERAL_MONO, - AC97_GENERAL_MIC, - AC97_GENERAL_LOOPBACK -}; - -static const struct snd_kcontrol_new snd_ac97_controls_general[7] = { -AC97_ENUM("PCM Out Path & Mute", std_enum[1]), -AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0), -AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), -AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0), -AC97_ENUM("Mono Output Select", std_enum[2]), -AC97_ENUM("Mic Select", std_enum[3]), -AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_3d[2] = { -AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0), -AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_center[2] = { -AC97_SINGLE("Center Playback Switch", AC97_CENTER_LFE_MASTER, 7, 1, 1), -AC97_SINGLE("Center Playback Volume", AC97_CENTER_LFE_MASTER, 0, 31, 1) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_lfe[2] = { -AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1), -AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1) -}; - -static const struct snd_kcontrol_new snd_ac97_control_eapd = -AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1); - -static const struct snd_kcontrol_new snd_ac97_controls_modem_switches[2] = { -AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0), -AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0) -}; - -/* change the existing EAPD control as inverted */ -static void set_inv_eapd(struct snd_ac97 *ac97, struct snd_kcontrol *kctl) -{ - kctl->private_value = AC97_SINGLE_VALUE(AC97_POWERDOWN, 15, 1, 0); - snd_ac97_update_bits(ac97, AC97_POWERDOWN, (1<<15), (1<<15)); /* EAPD up */ - ac97->scaps |= AC97_SCAP_INV_EAPD; -} - -static int snd_ac97_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ac97_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | - IEC958_AES0_NONAUDIO | - IEC958_AES0_CON_EMPHASIS_5015 | - IEC958_AES0_CON_NOT_COPYRIGHT; - ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY | - IEC958_AES1_CON_ORIGINAL; - ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS; - return 0; -} - -static int snd_ac97_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - /* FIXME: AC'97 spec doesn't say which bits are used for what */ - ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | - IEC958_AES0_NONAUDIO | - IEC958_AES0_PRO_FS | - IEC958_AES0_PRO_EMPHASIS_5015; - return 0; -} - -static int snd_ac97_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ac97->reg_mutex); - ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff; - ucontrol->value.iec958.status[1] = (ac97->spdif_status >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (ac97->spdif_status >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (ac97->spdif_status >> 24) & 0xff; - mutex_unlock(&ac97->reg_mutex); - return 0; -} - -static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned int new = 0; - unsigned short val = 0; - int change; - - new = val = ucontrol->value.iec958.status[0] & (IEC958_AES0_PROFESSIONAL|IEC958_AES0_NONAUDIO); - if (ucontrol->value.iec958.status[0] & IEC958_AES0_PROFESSIONAL) { - new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_PRO_FS|IEC958_AES0_PRO_EMPHASIS_5015); - switch (new & IEC958_AES0_PRO_FS) { - case IEC958_AES0_PRO_FS_44100: val |= 0<<12; break; - case IEC958_AES0_PRO_FS_48000: val |= 2<<12; break; - case IEC958_AES0_PRO_FS_32000: val |= 3<<12; break; - default: val |= 1<<12; break; - } - if ((new & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015) - val |= 1<<3; - } else { - new |= ucontrol->value.iec958.status[0] & (IEC958_AES0_CON_EMPHASIS_5015|IEC958_AES0_CON_NOT_COPYRIGHT); - new |= ((ucontrol->value.iec958.status[1] & (IEC958_AES1_CON_CATEGORY|IEC958_AES1_CON_ORIGINAL)) << 8); - new |= ((ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) << 24); - if ((new & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015) - val |= 1<<3; - if (!(new & IEC958_AES0_CON_NOT_COPYRIGHT)) - val |= 1<<2; - val |= ((new >> 8) & 0xff) << 4; // category + original - switch ((new >> 24) & 0xff) { - case IEC958_AES3_CON_FS_44100: val |= 0<<12; break; - case IEC958_AES3_CON_FS_48000: val |= 2<<12; break; - case IEC958_AES3_CON_FS_32000: val |= 3<<12; break; - default: val |= 1<<12; break; - } - } - - mutex_lock(&ac97->reg_mutex); - change = ac97->spdif_status != new; - ac97->spdif_status = new; - - if (ac97->flags & AC97_CS_SPDIF) { - int x = (val >> 12) & 0x03; - switch (x) { - case 0: x = 1; break; // 44.1 - case 2: x = 0; break; // 48.0 - default: x = 0; break; // illegal. - } - change |= snd_ac97_update_bits_nolock(ac97, AC97_CSR_SPDIF, 0x3fff, ((val & 0xcfff) | (x << 12))); - } else if (ac97->flags & AC97_CX_SPDIF) { - int v; - v = new & (IEC958_AES0_CON_EMPHASIS_5015|IEC958_AES0_CON_NOT_COPYRIGHT) ? 0 : AC97_CXR_COPYRGT; - v |= new & IEC958_AES0_NONAUDIO ? AC97_CXR_SPDIF_AC3 : AC97_CXR_SPDIF_PCM; - change |= snd_ac97_update_bits_nolock(ac97, AC97_CXR_AUDIO_MISC, - AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, - v); - } else if (ac97->id == AC97_ID_YMF743) { - change |= snd_ac97_update_bits_nolock(ac97, - AC97_YMF7X3_DIT_CTRL, - 0xff38, - ((val << 4) & 0xff00) | - ((val << 2) & 0x0038)); - } else { - unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); - snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ - - change |= snd_ac97_update_bits_nolock(ac97, AC97_SPDIF, 0x3fff, val); - if (extst & AC97_EA_SPDIF) { - snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ - } - } - mutex_unlock(&ac97->reg_mutex); - - return change; -} - -static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - // int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned short value, old, new; - int change; - - value = (ucontrol->value.integer.value[0] & mask); - - mutex_lock(&ac97->reg_mutex); - mask <<= shift; - value <<= shift; - old = snd_ac97_read_cache(ac97, reg); - new = (old & ~mask) | value; - change = old != new; - - if (change) { - unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); - snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ - change = snd_ac97_update_bits_nolock(ac97, reg, mask, value); - if (extst & AC97_EA_SPDIF) - snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ - } - mutex_unlock(&ac97->reg_mutex); - return change; -} - -static const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = { - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), - .info = snd_ac97_spdif_mask_info, - .get = snd_ac97_spdif_cmask_get, - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), - .info = snd_ac97_spdif_mask_info, - .get = snd_ac97_spdif_pmask_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_ac97_spdif_mask_info, - .get = snd_ac97_spdif_default_get, - .put = snd_ac97_spdif_default_put, - }, - - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),AC97_EXTENDED_STATUS, 2, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", - .info = snd_ac97_info_volsw, - .get = snd_ac97_get_volsw, - .put = snd_ac97_put_spsa, - .private_value = AC97_SINGLE_VALUE(AC97_EXTENDED_STATUS, 4, 3, 0) - }, -}; - -#define AD18XX_PCM_BITS(xname, codec, lshift, rshift, mask) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_bits, \ - .get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \ - .private_value = (codec) | ((lshift) << 8) | ((rshift) << 12) | ((mask) << 16) } - -static int snd_ac97_ad18xx_pcm_info_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int mask = (kcontrol->private_value >> 16) & 0x0f; - int lshift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES)) - uinfo->count = 2; - else - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ac97_ad18xx_pcm_get_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int codec = kcontrol->private_value & 3; - int lshift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - - ucontrol->value.integer.value[0] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> lshift) & mask); - if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES)) - ucontrol->value.integer.value[1] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> rshift) & mask); - return 0; -} - -static int snd_ac97_ad18xx_pcm_put_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int codec = kcontrol->private_value & 3; - int lshift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - unsigned short val, valmask; - - val = (mask - (ucontrol->value.integer.value[0] & mask)) << lshift; - valmask = mask << lshift; - if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES)) { - val |= (mask - (ucontrol->value.integer.value[1] & mask)) << rshift; - valmask |= mask << rshift; - } - return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, valmask, val); -} - -#define AD18XX_PCM_VOLUME(xname, codec) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_volume, \ - .get = snd_ac97_ad18xx_pcm_get_volume, .put = snd_ac97_ad18xx_pcm_put_volume, \ - .private_value = codec } - -static int snd_ac97_ad18xx_pcm_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 31; - return 0; -} - -static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int codec = kcontrol->private_value & 3; - - mutex_lock(&ac97->page_mutex); - ucontrol->value.integer.value[0] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 0) & 31); - ucontrol->value.integer.value[1] = 31 - ((ac97->spec.ad18xx.pcmreg[codec] >> 8) & 31); - mutex_unlock(&ac97->page_mutex); - return 0; -} - -static int snd_ac97_ad18xx_pcm_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int codec = kcontrol->private_value & 3; - unsigned short val1, val2; - - val1 = 31 - (ucontrol->value.integer.value[0] & 31); - val2 = 31 - (ucontrol->value.integer.value[1] & 31); - return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, 0x1f1f, (val1 << 8) | val2); -} - -static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_pcm[2] = { -AD18XX_PCM_BITS("PCM Playback Switch", 0, 15, 7, 1), -AD18XX_PCM_VOLUME("PCM Playback Volume", 0) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_surround[2] = { -AD18XX_PCM_BITS("Surround Playback Switch", 1, 15, 7, 1), -AD18XX_PCM_VOLUME("Surround Playback Volume", 1) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_center[2] = { -AD18XX_PCM_BITS("Center Playback Switch", 2, 15, 15, 1), -AD18XX_PCM_BITS("Center Playback Volume", 2, 8, 8, 31) -}; - -static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_lfe[2] = { -AD18XX_PCM_BITS("LFE Playback Switch", 2, 7, 7, 1), -AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 0, 31) -}; - -/* - * - */ - -static void snd_ac97_powerdown(struct snd_ac97 *ac97); - -static int snd_ac97_bus_free(struct snd_ac97_bus *bus) -{ - if (bus) { - snd_ac97_bus_proc_done(bus); - kfree(bus->pcms); - if (bus->private_free) - bus->private_free(bus); - kfree(bus); - } - return 0; -} - -static int snd_ac97_bus_dev_free(struct snd_device *device) -{ - struct snd_ac97_bus *bus = device->device_data; - return snd_ac97_bus_free(bus); -} - -static int snd_ac97_free(struct snd_ac97 *ac97) -{ - if (ac97) { -#ifdef CONFIG_SND_AC97_POWER_SAVE - cancel_delayed_work_sync(&ac97->power_work); -#endif - snd_ac97_proc_done(ac97); - if (ac97->bus) - ac97->bus->codec[ac97->num] = NULL; - if (ac97->private_free) - ac97->private_free(ac97); - kfree(ac97); - } - return 0; -} - -static int snd_ac97_dev_free(struct snd_device *device) -{ - struct snd_ac97 *ac97 = device->device_data; - snd_ac97_powerdown(ac97); /* for avoiding click noises during shut down */ - return snd_ac97_free(ac97); -} - -static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg) -{ - unsigned short val, mask = AC97_MUTE_MASK_MONO; - - if (! snd_ac97_valid_reg(ac97, reg)) - return 0; - - switch (reg) { - case AC97_MASTER_TONE: - return ac97->caps & AC97_BC_BASS_TREBLE ? 1 : 0; - case AC97_HEADPHONE: - return ac97->caps & AC97_BC_HEADPHONE ? 1 : 0; - case AC97_REC_GAIN_MIC: - return ac97->caps & AC97_BC_DEDICATED_MIC ? 1 : 0; - case AC97_3D_CONTROL: - if (ac97->caps & AC97_BC_3D_TECH_ID_MASK) { - val = snd_ac97_read(ac97, reg); - /* if nonzero - fixed and we can't set it */ - return val == 0; - } - return 0; - case AC97_CENTER_LFE_MASTER: /* center */ - if ((ac97->ext_id & AC97_EI_CDAC) == 0) - return 0; - break; - case AC97_CENTER_LFE_MASTER+1: /* lfe */ - if ((ac97->ext_id & AC97_EI_LDAC) == 0) - return 0; - reg = AC97_CENTER_LFE_MASTER; - mask = 0x0080; - break; - case AC97_SURROUND_MASTER: - if ((ac97->ext_id & AC97_EI_SDAC) == 0) - return 0; - break; - } - - val = snd_ac97_read(ac97, reg); - if (!(val & mask)) { - /* nothing seems to be here - mute flag is not set */ - /* try another test */ - snd_ac97_write_cache(ac97, reg, val | mask); - val = snd_ac97_read(ac97, reg); - val = snd_ac97_read(ac97, reg); - if (!(val & mask)) - return 0; /* nothing here */ - } - return 1; /* success, useable */ -} - -static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned char *lo_max, unsigned char *hi_max) -{ - unsigned short cbit[3] = { 0x20, 0x10, 0x01 }; - unsigned char max[3] = { 63, 31, 15 }; - int i; - - /* first look up the static resolution table */ - if (ac97->res_table) { - const struct snd_ac97_res_table *tbl; - for (tbl = ac97->res_table; tbl->reg; tbl++) { - if (tbl->reg == reg) { - *lo_max = tbl->bits & 0xff; - *hi_max = (tbl->bits >> 8) & 0xff; - return; - } - } - } - - *lo_max = *hi_max = 0; - for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { - unsigned short val; - snd_ac97_write( - ac97, reg, - AC97_MUTE_MASK_STEREO | cbit[i] | (cbit[i] << 8) - ); - /* Do the read twice due to buffers on some ac97 codecs. - * e.g. The STAC9704 returns exactly what you wrote to the register - * if you read it immediately. This causes the detect routine to fail. - */ - val = snd_ac97_read(ac97, reg); - val = snd_ac97_read(ac97, reg); - if (! *lo_max && (val & 0x7f) == cbit[i]) - *lo_max = max[i]; - if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i]) - *hi_max = max[i]; - if (*lo_max && *hi_max) - break; - } -} - -static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit) -{ - unsigned short mask, val, orig, res; - - mask = 1 << bit; - orig = snd_ac97_read(ac97, reg); - val = orig ^ mask; - snd_ac97_write(ac97, reg, val); - res = snd_ac97_read(ac97, reg); - snd_ac97_write_cache(ac97, reg, orig); - return res == val; -} - -/* check the volume resolution of center/lfe */ -static void snd_ac97_change_volume_params2(struct snd_ac97 * ac97, int reg, int shift, unsigned char *max) -{ - unsigned short val, val1; - - *max = 63; - val = AC97_MUTE_MASK_STEREO | (0x20 << shift); - snd_ac97_write(ac97, reg, val); - val1 = snd_ac97_read(ac97, reg); - if (val != val1) { - *max = 31; - } - /* reset volume to zero */ - snd_ac97_write_cache(ac97, reg, AC97_MUTE_MASK_STEREO); -} - -static inline int printable(unsigned int x) -{ - x &= 0xff; - if (x < ' ' || x >= 0x71) { - if (x <= 0x89) - return x - 0x71 + 'A'; - return '?'; - } - return x; -} - -static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, - struct snd_ac97 * ac97) -{ - struct snd_kcontrol_new template; - memcpy(&template, _template, sizeof(template)); - template.index = ac97->num; - return snd_ctl_new1(&template, ac97); -} - -/* - * create mute switch(es) for normal stereo controls - */ -static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, - int check_stereo, int check_amix, - struct snd_ac97 *ac97) -{ - struct snd_kcontrol *kctl; - int err; - unsigned short val, val1, mute_mask; - - if (! snd_ac97_valid_reg(ac97, reg)) - return 0; - - mute_mask = AC97_MUTE_MASK_MONO; - val = snd_ac97_read(ac97, reg); - if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) { - /* check whether both mute bits work */ - val1 = val | AC97_MUTE_MASK_STEREO; - snd_ac97_write(ac97, reg, val1); - if (val1 == snd_ac97_read(ac97, reg)) - mute_mask = AC97_MUTE_MASK_STEREO; - } - if (mute_mask == AC97_MUTE_MASK_STEREO) { - struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1); - if (check_amix) - tmp.private_value |= (1 << 30); - tmp.index = ac97->num; - kctl = snd_ctl_new1(&tmp, ac97); - } else { - struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 15, 1, 1); - if (check_amix) - tmp.private_value |= (1 << 30); - tmp.index = ac97->num; - kctl = snd_ctl_new1(&tmp, ac97); - } - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - /* mute as default */ - snd_ac97_write_cache(ac97, reg, val | mute_mask); - return 0; -} - -/* - * set dB information - */ -static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); - -static const unsigned int *find_db_scale(unsigned int maxval) -{ - switch (maxval) { - case 0x0f: return db_scale_4bit; - case 0x1f: return db_scale_5bit; - case 0x3f: return db_scale_6bit; - } - return NULL; -} - -static void set_tlv_db_scale(struct snd_kcontrol *kctl, const unsigned int *tlv) -{ - kctl->tlv.p = tlv; - if (tlv) - kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; -} - -/* - * create a volume for normal stereo/mono controls - */ -static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigned int lo_max, - unsigned int hi_max, struct snd_ac97 *ac97) -{ - int err; - struct snd_kcontrol *kctl; - - if (! snd_ac97_valid_reg(ac97, reg)) - return 0; - if (hi_max) { - /* invert */ - struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 8, 0, lo_max, 1); - tmp.index = ac97->num; - kctl = snd_ctl_new1(&tmp, ac97); - } else { - /* invert */ - struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 0, lo_max, 1); - tmp.index = ac97->num; - kctl = snd_ctl_new1(&tmp, ac97); - } - if (reg >= AC97_PHONE && reg <= AC97_PCM) - set_tlv_db_scale(kctl, db_scale_5bit_12db_max); - else - set_tlv_db_scale(kctl, find_db_scale(lo_max)); - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - snd_ac97_write_cache( - ac97, reg, - (snd_ac97_read(ac97, reg) & AC97_MUTE_MASK_STEREO) - | lo_max | (hi_max << 8) - ); - return 0; -} - -/* - * create a mute-switch and a volume for normal stereo/mono controls - */ -static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, - int reg, int check_stereo, int check_amix, - struct snd_ac97 *ac97) -{ - int err; - char name[44]; - unsigned char lo_max, hi_max; - - if (! snd_ac97_valid_reg(ac97, reg)) - return 0; - - if (snd_ac97_try_bit(ac97, reg, 15)) { - sprintf(name, "%s Switch", pfx); - if ((err = snd_ac97_cmute_new_stereo(card, name, reg, - check_stereo, check_amix, - ac97)) < 0) - return err; - } - check_volume_resolution(ac97, reg, &lo_max, &hi_max); - if (lo_max) { - sprintf(name, "%s Volume", pfx); - if ((err = snd_ac97_cvol_new(card, name, reg, lo_max, hi_max, ac97)) < 0) - return err; - } - return 0; -} - -#define snd_ac97_cmix_new(card, pfx, reg, acheck, ac97) \ - snd_ac97_cmix_new_stereo(card, pfx, reg, 0, acheck, ac97) -#define snd_ac97_cmute_new(card, name, reg, acheck, ac97) \ - snd_ac97_cmute_new_stereo(card, name, reg, 0, acheck, ac97) - -static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97); - -static int snd_ac97_mixer_build(struct snd_ac97 * ac97) -{ - struct snd_card *card = ac97->bus->card; - struct snd_kcontrol *kctl; - int err; - unsigned int idx; - unsigned char max; - - /* build master controls */ - /* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */ - if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) { - if (ac97->flags & AC97_HAS_NO_MASTER_VOL) - err = snd_ac97_cmute_new(card, "Master Playback Switch", - AC97_MASTER, 0, ac97); - else - err = snd_ac97_cmix_new(card, "Master Playback", - AC97_MASTER, 0, ac97); - if (err < 0) - return err; - } - - ac97->regs[AC97_CENTER_LFE_MASTER] = AC97_MUTE_MASK_STEREO; - - /* build center controls */ - if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) - && !(ac97->flags & AC97_AD_MULTI)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0) - return err; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0) - return err; - snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 0, &max); - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= (int)max << 16; - set_tlv_db_scale(kctl, find_db_scale(max)); - snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max); - } - - /* build LFE controls */ - if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1)) - && !(ac97->flags & AC97_AD_MULTI)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0) - return err; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0) - return err; - snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 8, &max); - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= (int)max << 16; - set_tlv_db_scale(kctl, find_db_scale(max)); - snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max << 8); - } - - /* build surround controls */ - if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) - && !(ac97->flags & AC97_AD_MULTI)) { - /* Surround Master (0x38) is with stereo mutes */ - if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", - AC97_SURROUND_MASTER, 1, 0, - ac97)) < 0) - return err; - } - - /* build headphone controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) { - if ((err = snd_ac97_cmix_new(card, "Headphone Playback", - AC97_HEADPHONE, 0, ac97)) < 0) - return err; - } - - /* build master mono controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) { - if ((err = snd_ac97_cmix_new(card, "Master Mono Playback", - AC97_MASTER_MONO, 0, ac97)) < 0) - return err; - } - - /* build master tone controls */ - if (!(ac97->flags & AC97_HAS_NO_TONE)) { - if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) { - for (idx = 0; idx < 2; idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) - return err; - if (ac97->id == AC97_ID_YMF743 || - ac97->id == AC97_ID_YMF753) { - kctl->private_value &= ~(0xff << 16); - kctl->private_value |= 7 << 16; - } - } - snd_ac97_write_cache(ac97, AC97_MASTER_TONE, 0x0f0f); - } - } - - /* build Beep controls */ - if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) && - ((ac97->flags & AC97_HAS_PC_BEEP) || - snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) - return err; - set_tlv_db_scale(kctl, db_scale_4bit); - snd_ac97_write_cache( - ac97, - AC97_PC_BEEP, - (snd_ac97_read(ac97, AC97_PC_BEEP) - | AC97_MUTE_MASK_MONO | 0x001e) - ); - } - - /* build Phone controls */ - if (!(ac97->flags & AC97_HAS_NO_PHONE)) { - if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) { - if ((err = snd_ac97_cmix_new(card, "Phone Playback", - AC97_PHONE, 1, ac97)) < 0) - return err; - } - } - - /* build MIC controls */ - if (!(ac97->flags & AC97_HAS_NO_MIC)) { - if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) { - if ((err = snd_ac97_cmix_new(card, "Mic Playback", - AC97_MIC, 1, ac97)) < 0) - return err; - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0) - return err; - } - } - - /* build Line controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_LINE)) { - if ((err = snd_ac97_cmix_new(card, "Line Playback", - AC97_LINE, 1, ac97)) < 0) - return err; - } - - /* build CD controls */ - if (!(ac97->flags & AC97_HAS_NO_CD)) { - if (snd_ac97_try_volume_mix(ac97, AC97_CD)) { - if ((err = snd_ac97_cmix_new(card, "CD Playback", - AC97_CD, 1, ac97)) < 0) - return err; - } - } - - /* build Video controls */ - if (!(ac97->flags & AC97_HAS_NO_VIDEO)) { - if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) { - if ((err = snd_ac97_cmix_new(card, "Video Playback", - AC97_VIDEO, 1, ac97)) < 0) - return err; - } - } - - /* build Aux controls */ - if (!(ac97->flags & AC97_HAS_NO_AUX)) { - if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { - if ((err = snd_ac97_cmix_new(card, "Aux Playback", - AC97_AUX, 1, ac97)) < 0) - return err; - } - } - - /* build PCM controls */ - if (ac97->flags & AC97_AD_MULTI) { - unsigned short init_val; - if (ac97->flags & AC97_STEREO_MUTES) - init_val = 0x9f9f; - else - init_val = 0x9f1f; - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0) - return err; - set_tlv_db_scale(kctl, db_scale_5bit); - ac97->spec.ad18xx.pcmreg[0] = init_val; - if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0) - return err; - set_tlv_db_scale(kctl, db_scale_5bit); - ac97->spec.ad18xx.pcmreg[1] = init_val; - } - if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0) - return err; - set_tlv_db_scale(kctl, db_scale_5bit); - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0) - return err; - set_tlv_db_scale(kctl, db_scale_5bit); - ac97->spec.ad18xx.pcmreg[2] = init_val; - } - snd_ac97_write_cache(ac97, AC97_PCM, init_val); - } else { - if (!(ac97->flags & AC97_HAS_NO_STD_PCM)) { - if (ac97->flags & AC97_HAS_NO_PCM_VOL) - err = snd_ac97_cmute_new(card, - "PCM Playback Switch", - AC97_PCM, 0, ac97); - else - err = snd_ac97_cmix_new(card, "PCM Playback", - AC97_PCM, 0, ac97); - if (err < 0) - return err; - } - } - - /* build Capture controls */ - if (!(ac97->flags & AC97_HAS_NO_REC_GAIN)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0) - return err; - if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) { - err = snd_ac97_cmute_new(card, "Capture Switch", - AC97_REC_GAIN, 0, ac97); - if (err < 0) - return err; - } - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0) - return err; - set_tlv_db_scale(kctl, db_scale_rec_gain); - snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); - snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); - } - /* build MIC Capture controls */ - if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) { - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97))) < 0) - return err; - set_tlv_db_scale(kctl, db_scale_rec_gain); - snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000); - } - - /* build PCM out path & mute control */ - if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 15)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_PCM_OUT], ac97))) < 0) - return err; - } - - /* build Simulated Stereo Enhancement control */ - if (ac97->caps & AC97_BC_SIM_STEREO) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0) - return err; - } - - /* build 3D Stereo Enhancement control */ - if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 13)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_3D], ac97))) < 0) - return err; - } - - /* build Loudness control */ - if (ac97->caps & AC97_BC_LOUDNESS) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0) - return err; - } - - /* build Mono output select control */ - if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 9)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MONO], ac97))) < 0) - return err; - } - - /* build Mic select control */ - if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 8)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MIC], ac97))) < 0) - return err; - } - - /* build ADC/DAC loopback control */ - if (enable_loopback && snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 7)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOOPBACK], ac97))) < 0) - return err; - } - - snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, ~AC97_GP_DRSS_MASK, 0x0000); - - /* build 3D controls */ - if (ac97->build_ops->build_3d) { - ac97->build_ops->build_3d(ac97); - } else { - if (snd_ac97_try_volume_mix(ac97, AC97_3D_CONTROL)) { - unsigned short val; - val = 0x0707; - snd_ac97_write(ac97, AC97_3D_CONTROL, val); - val = snd_ac97_read(ac97, AC97_3D_CONTROL); - val = val == 0x0606; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) - return err; - if (val) - kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16); - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[1], ac97))) < 0) - return err; - if (val) - kctl->private_value = AC97_3D_CONTROL | (1 << 8) | (7 << 16); - snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); - } - } - - /* build S/PDIF controls */ - - /* Hack for ASUS P5P800-VM, which does not indicate S/PDIF capability */ - if (ac97->subsystem_vendor == 0x1043 && - ac97->subsystem_device == 0x810f) - ac97->ext_id |= AC97_EI_SPDIF; - - if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) { - if (ac97->build_ops->build_spdif) { - if ((err = ac97->build_ops->build_spdif(ac97)) < 0) - return err; - } else { - for (idx = 0; idx < 5; idx++) - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0) - return err; - if (ac97->build_ops->build_post_spdif) { - if ((err = ac97->build_ops->build_post_spdif(ac97)) < 0) - return err; - } - /* set default PCM S/PDIF params */ - /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */ - snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20); - ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97); - } - ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF; - } - - /* build chip specific controls */ - if (ac97->build_ops->build_specific) - if ((err = ac97->build_ops->build_specific(ac97)) < 0) - return err; - - if (snd_ac97_try_bit(ac97, AC97_POWERDOWN, 15)) { - kctl = snd_ac97_cnew(&snd_ac97_control_eapd, ac97); - if (! kctl) - return -ENOMEM; - if (ac97->scaps & AC97_SCAP_INV_EAPD) - set_inv_eapd(ac97, kctl); - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - } - - return 0; -} - -static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97) -{ - int err, idx; - - /* - printk(KERN_DEBUG "AC97_GPIO_CFG = %x\n", - snd_ac97_read(ac97,AC97_GPIO_CFG)); - */ - snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); - snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH)); - snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff); - snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0); - snd_ac97_write(ac97, AC97_MISC_AFE, 0x0); - - /* build modem switches */ - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ac97_controls_modem_switches[idx], ac97))) < 0) - return err; - - /* build chip specific controls */ - if (ac97->build_ops->build_specific) - if ((err = ac97->build_ops->build_specific(ac97)) < 0) - return err; - - return 0; -} - -static int snd_ac97_test_rate(struct snd_ac97 *ac97, int reg, int shadow_reg, int rate) -{ - unsigned short val; - unsigned int tmp; - - tmp = ((unsigned int)rate * ac97->bus->clock) / 48000; - snd_ac97_write_cache(ac97, reg, tmp & 0xffff); - if (shadow_reg) - snd_ac97_write_cache(ac97, shadow_reg, tmp & 0xffff); - val = snd_ac97_read(ac97, reg); - return val == (tmp & 0xffff); -} - -static void snd_ac97_determine_rates(struct snd_ac97 *ac97, int reg, int shadow_reg, unsigned int *r_result) -{ - unsigned int result = 0; - unsigned short saved; - - if (ac97->bus->no_vra) { - *r_result = SNDRV_PCM_RATE_48000; - if ((ac97->flags & AC97_DOUBLE_RATE) && - reg == AC97_PCM_FRONT_DAC_RATE) - *r_result |= SNDRV_PCM_RATE_96000; - return; - } - - saved = snd_ac97_read(ac97, reg); - if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, - AC97_EA_DRA, 0); - /* test a non-standard rate */ - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 11000)) - result |= SNDRV_PCM_RATE_CONTINUOUS; - /* let's try to obtain standard rates */ - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 8000)) - result |= SNDRV_PCM_RATE_8000; - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 11025)) - result |= SNDRV_PCM_RATE_11025; - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 16000)) - result |= SNDRV_PCM_RATE_16000; - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 22050)) - result |= SNDRV_PCM_RATE_22050; - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 32000)) - result |= SNDRV_PCM_RATE_32000; - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 44100)) - result |= SNDRV_PCM_RATE_44100; - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 48000)) - result |= SNDRV_PCM_RATE_48000; - if ((ac97->flags & AC97_DOUBLE_RATE) && - reg == AC97_PCM_FRONT_DAC_RATE) { - /* test standard double rates */ - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, - AC97_EA_DRA, AC97_EA_DRA); - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 64000 / 2)) - result |= SNDRV_PCM_RATE_64000; - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 88200 / 2)) - result |= SNDRV_PCM_RATE_88200; - if (snd_ac97_test_rate(ac97, reg, shadow_reg, 96000 / 2)) - result |= SNDRV_PCM_RATE_96000; - /* some codecs don't support variable double rates */ - if (!snd_ac97_test_rate(ac97, reg, shadow_reg, 76100 / 2)) - result &= ~SNDRV_PCM_RATE_CONTINUOUS; - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, - AC97_EA_DRA, 0); - } - /* restore the default value */ - snd_ac97_write_cache(ac97, reg, saved); - if (shadow_reg) - snd_ac97_write_cache(ac97, shadow_reg, saved); - *r_result = result; -} - -/* check AC97_SPDIF register to accept which sample rates */ -static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97) -{ - unsigned int result = 0; - int i; - static unsigned short ctl_bits[] = { - AC97_SC_SPSR_44K, AC97_SC_SPSR_32K, AC97_SC_SPSR_48K - }; - static unsigned int rate_bits[] = { - SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_32000, SNDRV_PCM_RATE_48000 - }; - - for (i = 0; i < (int)ARRAY_SIZE(ctl_bits); i++) { - snd_ac97_update_bits(ac97, AC97_SPDIF, AC97_SC_SPSR_MASK, ctl_bits[i]); - if ((snd_ac97_read(ac97, AC97_SPDIF) & AC97_SC_SPSR_MASK) == ctl_bits[i]) - result |= rate_bits[i]; - } - return result; -} - -/* look for the codec id table matching with the given id */ -static const struct ac97_codec_id *look_for_codec_id(const struct ac97_codec_id *table, - unsigned int id) -{ - const struct ac97_codec_id *pid; - - for (pid = table; pid->id; pid++) - if (pid->id == (id & pid->mask)) - return pid; - return NULL; -} - -void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int modem) -{ - const struct ac97_codec_id *pid; - - sprintf(name, "0x%x %c%c%c", id, - printable(id >> 24), - printable(id >> 16), - printable(id >> 8)); - pid = look_for_codec_id(snd_ac97_codec_id_vendors, id); - if (! pid) - return; - - strcpy(name, pid->name); - if (ac97 && pid->patch) { - if ((modem && (pid->flags & AC97_MODEM_PATCH)) || - (! modem && ! (pid->flags & AC97_MODEM_PATCH))) - pid->patch(ac97); - } - - pid = look_for_codec_id(snd_ac97_codec_ids, id); - if (pid) { - strcat(name, " "); - strcat(name, pid->name); - if (pid->mask != 0xffffffff) - sprintf(name + strlen(name), " rev %d", id & ~pid->mask); - if (ac97 && pid->patch) { - if ((modem && (pid->flags & AC97_MODEM_PATCH)) || - (! modem && ! (pid->flags & AC97_MODEM_PATCH))) - pid->patch(ac97); - } - } else - sprintf(name + strlen(name), " id %x", id & 0xff); -} - -/** - * snd_ac97_get_short_name - retrieve codec name - * @ac97: the codec instance - * - * Returns the short identifying name of the codec. - */ -const char *snd_ac97_get_short_name(struct snd_ac97 *ac97) -{ - const struct ac97_codec_id *pid; - - for (pid = snd_ac97_codec_ids; pid->id; pid++) - if (pid->id == (ac97->id & pid->mask)) - return pid->name; - return "unknown codec"; -} - -EXPORT_SYMBOL(snd_ac97_get_short_name); - -/* wait for a while until registers are accessible after RESET - * return 0 if ok, negative not ready - */ -static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem) -{ - unsigned long end_time; - unsigned short val; - - end_time = jiffies + timeout; - do { - - /* use preliminary reads to settle the communication */ - snd_ac97_read(ac97, AC97_RESET); - snd_ac97_read(ac97, AC97_VENDOR_ID1); - snd_ac97_read(ac97, AC97_VENDOR_ID2); - /* modem? */ - if (with_modem) { - val = snd_ac97_read(ac97, AC97_EXTENDED_MID); - if (val != 0xffff && (val & 1) != 0) - return 0; - } - if (ac97->scaps & AC97_SCAP_DETECT_BY_VENDOR) { - /* probably only Xbox issue - all registers are read as zero */ - val = snd_ac97_read(ac97, AC97_VENDOR_ID1); - if (val != 0 && val != 0xffff) - return 0; - } else { - /* because the PCM or MASTER volume registers can be modified, - * the REC_GAIN register is used for tests - */ - /* test if we can write to the record gain volume register */ - snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05); - if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05) - return 0; - } - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - return -ENODEV; -} - -/** - * snd_ac97_bus - create an AC97 bus component - * @card: the card instance - * @num: the bus number - * @ops: the bus callbacks table - * @private_data: private data pointer for the new instance - * @rbus: the pointer to store the new AC97 bus instance. - * - * Creates an AC97 bus component. An struct snd_ac97_bus instance is newly - * allocated and initialized. - * - * The ops table must include valid callbacks (at least read and - * write). The other callbacks, wait and reset, are not mandatory. - * - * The clock is set to 48000. If another clock is needed, set - * (*rbus)->clock manually. - * - * The AC97 bus instance is registered as a low-level device, so you don't - * have to release it manually. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, - void *private_data, struct snd_ac97_bus **rbus) -{ - int err; - struct snd_ac97_bus *bus; - static struct snd_device_ops dev_ops = { - .dev_free = snd_ac97_bus_dev_free, - }; - - if (snd_BUG_ON(!card)) - return -EINVAL; - bus = kzalloc(sizeof(*bus), GFP_KERNEL); - if (bus == NULL) - return -ENOMEM; - bus->card = card; - bus->num = num; - bus->ops = ops; - bus->private_data = private_data; - bus->clock = 48000; - spin_lock_init(&bus->bus_lock); - snd_ac97_bus_proc_init(bus); - if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { - snd_ac97_bus_free(bus); - return err; - } - if (rbus) - *rbus = bus; - return 0; -} - -EXPORT_SYMBOL(snd_ac97_bus); - -/* stop no dev release warning */ -static void ac97_device_release(struct device * dev) -{ -} - -/* register ac97 codec to bus */ -static int snd_ac97_dev_register(struct snd_device *device) -{ - struct snd_ac97 *ac97 = device->device_data; - int err; - - ac97->dev.bus = &ac97_bus_type; - ac97->dev.parent = ac97->bus->card->dev; - ac97->dev.release = ac97_device_release; - dev_set_name(&ac97->dev, "%d-%d:%s", - ac97->bus->card->number, ac97->num, - snd_ac97_get_short_name(ac97)); - if ((err = device_register(&ac97->dev)) < 0) { - snd_printk(KERN_ERR "Can't register ac97 bus\n"); - ac97->dev.bus = NULL; - return err; - } - return 0; -} - -/* disconnect ac97 codec */ -static int snd_ac97_dev_disconnect(struct snd_device *device) -{ - struct snd_ac97 *ac97 = device->device_data; - if (ac97->dev.bus) - device_unregister(&ac97->dev); - return 0; -} - -/* build_ops to do nothing */ -static const struct snd_ac97_build_ops null_build_ops; - -#ifdef CONFIG_SND_AC97_POWER_SAVE -static void do_update_power(struct work_struct *work) -{ - update_power_regs( - container_of(work, struct snd_ac97, power_work.work)); -} -#endif - -/** - * snd_ac97_mixer - create an Codec97 component - * @bus: the AC97 bus which codec is attached to - * @template: the template of ac97, including index, callbacks and - * the private data. - * @rac97: the pointer to store the new ac97 instance. - * - * Creates an Codec97 component. An struct snd_ac97 instance is newly - * allocated and initialized from the template. The codec - * is then initialized by the standard procedure. - * - * The template must include the codec number (num) and address (addr), - * and the private data (private_data). - * - * The ac97 instance is registered as a low-level device, so you don't - * have to release it manually. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97) -{ - int err; - struct snd_ac97 *ac97; - struct snd_card *card; - char name[64]; - unsigned long end_time; - unsigned int reg; - const struct ac97_codec_id *pid; - static struct snd_device_ops ops = { - .dev_free = snd_ac97_dev_free, - .dev_register = snd_ac97_dev_register, - .dev_disconnect = snd_ac97_dev_disconnect, - }; - - if (rac97) - *rac97 = NULL; - if (snd_BUG_ON(!bus || !template)) - return -EINVAL; - if (snd_BUG_ON(template->num >= 4)) - return -EINVAL; - if (bus->codec[template->num]) - return -EBUSY; - - card = bus->card; - ac97 = kzalloc(sizeof(*ac97), GFP_KERNEL); - if (ac97 == NULL) - return -ENOMEM; - ac97->private_data = template->private_data; - ac97->private_free = template->private_free; - ac97->bus = bus; - ac97->pci = template->pci; - ac97->num = template->num; - ac97->addr = template->addr; - ac97->scaps = template->scaps; - ac97->res_table = template->res_table; - bus->codec[ac97->num] = ac97; - mutex_init(&ac97->reg_mutex); - mutex_init(&ac97->page_mutex); -#ifdef CONFIG_SND_AC97_POWER_SAVE - INIT_DELAYED_WORK(&ac97->power_work, do_update_power); -#endif - -#ifdef CONFIG_PCI - if (ac97->pci) { - pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor); - pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_ID, &ac97->subsystem_device); - } -#endif - if (bus->ops->reset) { - bus->ops->reset(ac97); - goto __access_ok; - } - - ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16; - ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2); - if (ac97->id && ac97->id != (unsigned int)-1) { - pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id); - if (pid && (pid->flags & AC97_DEFAULT_POWER_OFF)) - goto __access_ok; - } - - /* reset to defaults */ - if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO)) - snd_ac97_write(ac97, AC97_RESET, 0); - if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM)) - snd_ac97_write(ac97, AC97_EXTENDED_MID, 0); - if (bus->ops->wait) - bus->ops->wait(ac97); - else { - udelay(50); - if (ac97->scaps & AC97_SCAP_SKIP_AUDIO) - err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 1); - else { - err = ac97_reset_wait(ac97, msecs_to_jiffies(500), 0); - if (err < 0) - err = ac97_reset_wait(ac97, - msecs_to_jiffies(500), 1); - } - if (err < 0) { - snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num); - /* proceed anyway - it's often non-critical */ - } - } - __access_ok: - ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16; - ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2); - if (! (ac97->scaps & AC97_SCAP_DETECT_BY_VENDOR) && - (ac97->id == 0x00000000 || ac97->id == 0xffffffff)) { - snd_printk(KERN_ERR "AC'97 %d access is not valid [0x%x], removing mixer.\n", ac97->num, ac97->id); - snd_ac97_free(ac97); - return -EIO; - } - pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id); - if (pid) - ac97->flags |= pid->flags; - - /* test for AC'97 */ - if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) { - /* test if we can write to the record gain volume register */ - snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a06); - if (((err = snd_ac97_read(ac97, AC97_REC_GAIN)) & 0x7fff) == 0x0a06) - ac97->scaps |= AC97_SCAP_AUDIO; - } - if (ac97->scaps & AC97_SCAP_AUDIO) { - ac97->caps = snd_ac97_read(ac97, AC97_RESET); - ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID); - if (ac97->ext_id == 0xffff) /* invalid combination */ - ac97->ext_id = 0; - } - - /* test for MC'97 */ - if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM) && !(ac97->scaps & AC97_SCAP_MODEM)) { - ac97->ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID); - if (ac97->ext_mid == 0xffff) /* invalid combination */ - ac97->ext_mid = 0; - if (ac97->ext_mid & 1) - ac97->scaps |= AC97_SCAP_MODEM; - } - - if (!ac97_is_audio(ac97) && !ac97_is_modem(ac97)) { - if (!(ac97->scaps & (AC97_SCAP_SKIP_AUDIO|AC97_SCAP_SKIP_MODEM))) - snd_printk(KERN_ERR "AC'97 %d access error (not audio or modem codec)\n", ac97->num); - snd_ac97_free(ac97); - return -EACCES; - } - - if (bus->ops->reset) // FIXME: always skipping? - goto __ready_ok; - - /* FIXME: add powerdown control */ - if (ac97_is_audio(ac97)) { - /* nothing should be in powerdown mode */ - snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0); - if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { - snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to defaults */ - udelay(100); - snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0); - } - /* nothing should be in powerdown mode */ - snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); - end_time = jiffies + msecs_to_jiffies(5000); - do { - if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) - goto __ready_ok; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", ac97->num); - } - - /* FIXME: add powerdown control */ - if (ac97_is_modem(ac97)) { - unsigned char tmp; - - /* nothing should be in powerdown mode */ - /* note: it's important to set the rate at first */ - tmp = AC97_MEA_GPIO; - if (ac97->ext_mid & AC97_MEI_LINE1) { - snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000); - tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1; - } - if (ac97->ext_mid & AC97_MEI_LINE2) { - snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000); - tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2; - } - if (ac97->ext_mid & AC97_MEI_HANDSET) { - snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000); - tmp |= AC97_MEA_HADC | AC97_MEA_HDAC; - } - snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); - udelay(100); - /* nothing should be in powerdown mode */ - snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); - end_time = jiffies + msecs_to_jiffies(100); - do { - if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) - goto __ready_ok; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS)); - } - - __ready_ok: - if (ac97_is_audio(ac97)) - ac97->addr = (ac97->ext_id & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT; - else - ac97->addr = (ac97->ext_mid & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT; - if (ac97->ext_id & 0x01c9) { /* L/R, MIC, SDAC, LDAC VRA support */ - reg = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); - reg |= ac97->ext_id & 0x01c0; /* LDAC/SDAC/CDAC */ - if (! bus->no_vra) - reg |= ac97->ext_id & 0x0009; /* VRA/VRM */ - snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, reg); - } - if ((ac97->ext_id & AC97_EI_DRA) && bus->dra) { - /* Intel controllers require double rate data to be put in - * slots 7+8, so let's hope the codec supports it. */ - snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, AC97_GP_DRSS_MASK, AC97_GP_DRSS_78); - if ((snd_ac97_read(ac97, AC97_GENERAL_PURPOSE) & AC97_GP_DRSS_MASK) == AC97_GP_DRSS_78) - ac97->flags |= AC97_DOUBLE_RATE; - /* restore to slots 10/11 to avoid the confliction with surrounds */ - snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, AC97_GP_DRSS_MASK, 0); - } - if (ac97->ext_id & AC97_EI_VRA) { /* VRA support */ - snd_ac97_determine_rates(ac97, AC97_PCM_FRONT_DAC_RATE, 0, &ac97->rates[AC97_RATES_FRONT_DAC]); - snd_ac97_determine_rates(ac97, AC97_PCM_LR_ADC_RATE, 0, &ac97->rates[AC97_RATES_ADC]); - } else { - ac97->rates[AC97_RATES_FRONT_DAC] = SNDRV_PCM_RATE_48000; - if (ac97->flags & AC97_DOUBLE_RATE) - ac97->rates[AC97_RATES_FRONT_DAC] |= SNDRV_PCM_RATE_96000; - ac97->rates[AC97_RATES_ADC] = SNDRV_PCM_RATE_48000; - } - if (ac97->ext_id & AC97_EI_SPDIF) { - /* codec specific code (patch) should override these values */ - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_32000; - } - if (ac97->ext_id & AC97_EI_VRM) { /* MIC VRA support */ - snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, 0, &ac97->rates[AC97_RATES_MIC_ADC]); - } else { - ac97->rates[AC97_RATES_MIC_ADC] = SNDRV_PCM_RATE_48000; - } - if (ac97->ext_id & AC97_EI_SDAC) { /* SDAC support */ - snd_ac97_determine_rates(ac97, AC97_PCM_SURR_DAC_RATE, AC97_PCM_FRONT_DAC_RATE, &ac97->rates[AC97_RATES_SURR_DAC]); - ac97->scaps |= AC97_SCAP_SURROUND_DAC; - } - if (ac97->ext_id & AC97_EI_LDAC) { /* LDAC support */ - snd_ac97_determine_rates(ac97, AC97_PCM_LFE_DAC_RATE, AC97_PCM_FRONT_DAC_RATE, &ac97->rates[AC97_RATES_LFE_DAC]); - ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC; - } - /* additional initializations */ - if (bus->ops->init) - bus->ops->init(ac97); - snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97)); - snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97)); // ac97->id might be changed in the special setup code - if (! ac97->build_ops) - ac97->build_ops = &null_build_ops; - - if (ac97_is_audio(ac97)) { - char comp[16]; - if (card->mixername[0] == '\0') { - strcpy(card->mixername, name); - } else { - if (strlen(card->mixername) + 1 + strlen(name) + 1 <= sizeof(card->mixername)) { - strcat(card->mixername, ","); - strcat(card->mixername, name); - } - } - sprintf(comp, "AC97a:%08x", ac97->id); - if ((err = snd_component_add(card, comp)) < 0) { - snd_ac97_free(ac97); - return err; - } - if (snd_ac97_mixer_build(ac97) < 0) { - snd_ac97_free(ac97); - return -ENOMEM; - } - } - if (ac97_is_modem(ac97)) { - char comp[16]; - if (card->mixername[0] == '\0') { - strcpy(card->mixername, name); - } else { - if (strlen(card->mixername) + 1 + strlen(name) + 1 <= sizeof(card->mixername)) { - strcat(card->mixername, ","); - strcat(card->mixername, name); - } - } - sprintf(comp, "AC97m:%08x", ac97->id); - if ((err = snd_component_add(card, comp)) < 0) { - snd_ac97_free(ac97); - return err; - } - if (snd_ac97_modem_build(card, ac97) < 0) { - snd_ac97_free(ac97); - return -ENOMEM; - } - } - if (ac97_is_audio(ac97)) - update_power_regs(ac97); - snd_ac97_proc_init(ac97); - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ac97, &ops)) < 0) { - snd_ac97_free(ac97); - return err; - } - *rac97 = ac97; - return 0; -} - -EXPORT_SYMBOL(snd_ac97_mixer); - -/* - * Power down the chip. - * - * MASTER and HEADPHONE registers are muted but the register cache values - * are not changed, so that the values can be restored in snd_ac97_resume(). - */ -static void snd_ac97_powerdown(struct snd_ac97 *ac97) -{ - unsigned short power; - - if (ac97_is_audio(ac97)) { - /* some codecs have stereo mute bits */ - snd_ac97_write(ac97, AC97_MASTER, 0x9f9f); - snd_ac97_write(ac97, AC97_HEADPHONE, 0x9f9f); - } - - /* surround, CLFE, mic powerdown */ - power = ac97->regs[AC97_EXTENDED_STATUS]; - if (ac97->scaps & AC97_SCAP_SURROUND_DAC) - power |= AC97_EA_PRJ; - if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) - power |= AC97_EA_PRI | AC97_EA_PRK; - power |= AC97_EA_PRL; - snd_ac97_write(ac97, AC97_EXTENDED_STATUS, power); - - /* powerdown external amplifier */ - if (ac97->scaps & AC97_SCAP_INV_EAPD) - power = ac97->regs[AC97_POWERDOWN] & ~AC97_PD_EAPD; - else if (! (ac97->scaps & AC97_SCAP_EAPD_LED)) - power = ac97->regs[AC97_POWERDOWN] | AC97_PD_EAPD; - power |= AC97_PD_PR6; /* Headphone amplifier powerdown */ - power |= AC97_PD_PR0 | AC97_PD_PR1; /* ADC & DAC powerdown */ - snd_ac97_write(ac97, AC97_POWERDOWN, power); - udelay(100); - power |= AC97_PD_PR2; /* Analog Mixer powerdown (Vref on) */ - snd_ac97_write(ac97, AC97_POWERDOWN, power); - if (ac97_is_power_save_mode(ac97)) { - power |= AC97_PD_PR3; /* Analog Mixer powerdown */ - snd_ac97_write(ac97, AC97_POWERDOWN, power); - udelay(100); - /* AC-link powerdown, internal Clk disable */ - /* FIXME: this may cause click noises on some boards */ - power |= AC97_PD_PR4 | AC97_PD_PR5; - snd_ac97_write(ac97, AC97_POWERDOWN, power); - } -} - - -struct ac97_power_reg { - unsigned short reg; - unsigned short power_reg; - unsigned short mask; -}; - -enum { PWIDX_ADC, PWIDX_FRONT, PWIDX_CLFE, PWIDX_SURR, PWIDX_MIC, PWIDX_SIZE }; - -static struct ac97_power_reg power_regs[PWIDX_SIZE] = { - [PWIDX_ADC] = { AC97_PCM_LR_ADC_RATE, AC97_POWERDOWN, AC97_PD_PR0}, - [PWIDX_FRONT] = { AC97_PCM_FRONT_DAC_RATE, AC97_POWERDOWN, AC97_PD_PR1}, - [PWIDX_CLFE] = { AC97_PCM_LFE_DAC_RATE, AC97_EXTENDED_STATUS, - AC97_EA_PRI | AC97_EA_PRK}, - [PWIDX_SURR] = { AC97_PCM_SURR_DAC_RATE, AC97_EXTENDED_STATUS, - AC97_EA_PRJ}, - [PWIDX_MIC] = { AC97_PCM_MIC_ADC_RATE, AC97_EXTENDED_STATUS, - AC97_EA_PRL}, -}; - -#ifdef CONFIG_SND_AC97_POWER_SAVE -/** - * snd_ac97_update_power - update the powerdown register - * @ac97: the codec instance - * @reg: the rate register, e.g. AC97_PCM_FRONT_DAC_RATE - * @powerup: non-zero when power up the part - * - * Update the AC97 powerdown register bits of the given part. - */ -int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) -{ - int i; - - if (! ac97) - return 0; - - if (reg) { - /* SPDIF requires DAC power, too */ - if (reg == AC97_SPDIF) - reg = AC97_PCM_FRONT_DAC_RATE; - for (i = 0; i < PWIDX_SIZE; i++) { - if (power_regs[i].reg == reg) { - if (powerup) - ac97->power_up |= (1 << i); - else - ac97->power_up &= ~(1 << i); - break; - } - } - } - - if (ac97_is_power_save_mode(ac97) && !powerup) - /* adjust power-down bits after two seconds delay - * (for avoiding loud click noises for many (OSS) apps - * that open/close frequently) - */ - schedule_delayed_work(&ac97->power_work, - msecs_to_jiffies(power_save * 1000)); - else { - cancel_delayed_work(&ac97->power_work); - update_power_regs(ac97); - } - - return 0; -} - -EXPORT_SYMBOL(snd_ac97_update_power); -#endif /* CONFIG_SND_AC97_POWER_SAVE */ - -static void update_power_regs(struct snd_ac97 *ac97) -{ - unsigned int power_up, bits; - int i; - - power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC); - power_up |= (1 << PWIDX_MIC); - if (ac97->scaps & AC97_SCAP_SURROUND_DAC) - power_up |= (1 << PWIDX_SURR); - if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) - power_up |= (1 << PWIDX_CLFE); -#ifdef CONFIG_SND_AC97_POWER_SAVE - if (ac97_is_power_save_mode(ac97)) - power_up = ac97->power_up; -#endif - if (power_up) { - if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) { - /* needs power-up analog mix and vref */ - snd_ac97_update_bits(ac97, AC97_POWERDOWN, - AC97_PD_PR3, 0); - msleep(1); - snd_ac97_update_bits(ac97, AC97_POWERDOWN, - AC97_PD_PR2, 0); - } - } - for (i = 0; i < PWIDX_SIZE; i++) { - if (power_up & (1 << i)) - bits = 0; - else - bits = power_regs[i].mask; - snd_ac97_update_bits(ac97, power_regs[i].power_reg, - power_regs[i].mask, bits); - } - if (! power_up) { - if (! (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2)) { - /* power down analog mix and vref */ - snd_ac97_update_bits(ac97, AC97_POWERDOWN, - AC97_PD_PR2, AC97_PD_PR2); - snd_ac97_update_bits(ac97, AC97_POWERDOWN, - AC97_PD_PR3, AC97_PD_PR3); - } - } -} - - -#ifdef CONFIG_PM -/** - * snd_ac97_suspend - General suspend function for AC97 codec - * @ac97: the ac97 instance - * - * Suspends the codec, power down the chip. - */ -void snd_ac97_suspend(struct snd_ac97 *ac97) -{ - if (! ac97) - return; - if (ac97->build_ops->suspend) - ac97->build_ops->suspend(ac97); -#ifdef CONFIG_SND_AC97_POWER_SAVE - cancel_delayed_work_sync(&ac97->power_work); -#endif - snd_ac97_powerdown(ac97); -} - -EXPORT_SYMBOL(snd_ac97_suspend); - -/* - * restore ac97 status - */ -static void snd_ac97_restore_status(struct snd_ac97 *ac97) -{ - int i; - - for (i = 2; i < 0x7c ; i += 2) { - if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID) - continue; - /* restore only accessible registers - * some chip (e.g. nm256) may hang up when unsupported registers - * are accessed..! - */ - if (test_bit(i, ac97->reg_accessed)) { - snd_ac97_write(ac97, i, ac97->regs[i]); - snd_ac97_read(ac97, i); - } - } -} - -/* - * restore IEC958 status - */ -static void snd_ac97_restore_iec958(struct snd_ac97 *ac97) -{ - if (ac97->ext_id & AC97_EI_SPDIF) { - if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) { - /* reset spdif status */ - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); - snd_ac97_write(ac97, AC97_EXTENDED_STATUS, ac97->regs[AC97_EXTENDED_STATUS]); - if (ac97->flags & AC97_CS_SPDIF) - snd_ac97_write(ac97, AC97_CSR_SPDIF, ac97->regs[AC97_CSR_SPDIF]); - else - snd_ac97_write(ac97, AC97_SPDIF, ac97->regs[AC97_SPDIF]); - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); /* turn on again */ - } - } -} - -/** - * snd_ac97_resume - General resume function for AC97 codec - * @ac97: the ac97 instance - * - * Do the standard resume procedure, power up and restoring the - * old register values. - */ -void snd_ac97_resume(struct snd_ac97 *ac97) -{ - unsigned long end_time; - - if (! ac97) - return; - - if (ac97->bus->ops->reset) { - ac97->bus->ops->reset(ac97); - goto __reset_ready; - } - - snd_ac97_write(ac97, AC97_POWERDOWN, 0); - if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) { - if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO)) - snd_ac97_write(ac97, AC97_RESET, 0); - else if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM)) - snd_ac97_write(ac97, AC97_EXTENDED_MID, 0); - udelay(100); - snd_ac97_write(ac97, AC97_POWERDOWN, 0); - } - snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0); - - snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]); - if (ac97_is_audio(ac97)) { - ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101); - end_time = jiffies + msecs_to_jiffies(100); - do { - if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101) - break; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - /* FIXME: extra delay */ - ac97->bus->ops->write(ac97, AC97_MASTER, AC97_MUTE_MASK_MONO); - if (snd_ac97_read(ac97, AC97_MASTER) != AC97_MUTE_MASK_MONO) - msleep(250); - } else { - end_time = jiffies + msecs_to_jiffies(100); - do { - unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID); - if (val != 0xffff && (val & 1) != 0) - break; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - } -__reset_ready: - - if (ac97->bus->ops->init) - ac97->bus->ops->init(ac97); - - if (ac97->build_ops->resume) - ac97->build_ops->resume(ac97); - else { - snd_ac97_restore_status(ac97); - snd_ac97_restore_iec958(ac97); - } -} - -EXPORT_SYMBOL(snd_ac97_resume); -#endif - - -/* - * Hardware tuning - */ -static void set_ctl_name(char *dst, const char *src, const char *suffix) -{ - if (suffix) - sprintf(dst, "%s %s", src, suffix); - else - strcpy(dst, src); -} - -/* remove the control with the given name and optional suffix */ -static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, - const char *suffix) -{ - struct snd_ctl_elem_id id; - memset(&id, 0, sizeof(id)); - set_ctl_name(id.name, name, suffix); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_remove_id(ac97->bus->card, &id); -} - -static struct snd_kcontrol *ctl_find(struct snd_ac97 *ac97, const char *name, const char *suffix) -{ - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - set_ctl_name(sid.name, name, suffix); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_find_id(ac97->bus->card, &sid); -} - -/* rename the control with the given name and optional suffix */ -static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, - const char *dst, const char *suffix) -{ - struct snd_kcontrol *kctl = ctl_find(ac97, src, suffix); - if (kctl) { - set_ctl_name(kctl->id.name, dst, suffix); - return 0; - } - return -ENOENT; -} - -/* rename both Volume and Switch controls - don't check the return value */ -static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, - const char *dst) -{ - snd_ac97_rename_ctl(ac97, src, dst, "Switch"); - snd_ac97_rename_ctl(ac97, src, dst, "Volume"); -} - -/* swap controls */ -static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, - const char *s2, const char *suffix) -{ - struct snd_kcontrol *kctl1, *kctl2; - kctl1 = ctl_find(ac97, s1, suffix); - kctl2 = ctl_find(ac97, s2, suffix); - if (kctl1 && kctl2) { - set_ctl_name(kctl1->id.name, s2, suffix); - set_ctl_name(kctl2->id.name, s1, suffix); - return 0; - } - return -ENOENT; -} - -#if 1 -/* bind hp and master controls instead of using only hp control */ -static int bind_hp_volsw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - int err = snd_ac97_put_volsw(kcontrol, ucontrol); - if (err > 0) { - unsigned long priv_saved = kcontrol->private_value; - kcontrol->private_value = (kcontrol->private_value & ~0xff) | AC97_HEADPHONE; - snd_ac97_put_volsw(kcontrol, ucontrol); - kcontrol->private_value = priv_saved; - } - return err; -} - -/* ac97 tune: bind Master and Headphone controls */ -static int tune_hp_only(struct snd_ac97 *ac97) -{ - struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL); - struct snd_kcontrol *mvol = ctl_find(ac97, "Master Playback Volume", NULL); - if (! msw || ! mvol) - return -ENOENT; - msw->put = bind_hp_volsw_put; - mvol->put = bind_hp_volsw_put; - snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch"); - snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume"); - return 0; -} - -#else -/* ac97 tune: use Headphone control as master */ -static int tune_hp_only(struct snd_ac97 *ac97) -{ - if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL) - return -ENOENT; - snd_ac97_remove_ctl(ac97, "Master Playback", "Switch"); - snd_ac97_remove_ctl(ac97, "Master Playback", "Volume"); - snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); - return 0; -} -#endif - -/* ac97 tune: swap Headphone and Master controls */ -static int tune_swap_hp(struct snd_ac97 *ac97) -{ - if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL) - return -ENOENT; - snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback"); - snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); - return 0; -} - -/* ac97 tune: swap Surround and Master controls */ -static int tune_swap_surround(struct snd_ac97 *ac97) -{ - if (snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch") || - snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume")) - return -ENOENT; - return 0; -} - -/* ac97 tune: set up mic sharing for AD codecs */ -static int tune_ad_sharing(struct snd_ac97 *ac97) -{ - unsigned short scfg; - if ((ac97->id & 0xffffff00) != 0x41445300) { - snd_printk(KERN_ERR "ac97_quirk AD_SHARING is only for AD codecs\n"); - return -EINVAL; - } - /* Turn on OMS bit to route microphone to back panel */ - scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG); - snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x0200); - return 0; -} - -static const struct snd_kcontrol_new snd_ac97_alc_jack_detect = -AC97_SINGLE("Jack Detect", AC97_ALC650_CLOCK, 5, 1, 0); - -/* ac97 tune: set up ALC jack-select */ -static int tune_alc_jack(struct snd_ac97 *ac97) -{ - if ((ac97->id & 0xffffff00) != 0x414c4700) { - snd_printk(KERN_ERR "ac97_quirk ALC_JACK is only for Realtek codecs\n"); - return -EINVAL; - } - snd_ac97_update_bits(ac97, 0x7a, 0x20, 0x20); /* select jack detect function */ - snd_ac97_update_bits(ac97, 0x7a, 0x01, 0x01); /* Line-out auto mute */ - if (ac97->id == AC97_ID_ALC658D) - snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800); - return snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_alc_jack_detect, ac97)); -} - -/* ac97 tune: inversed EAPD bit */ -static int tune_inv_eapd(struct snd_ac97 *ac97) -{ - struct snd_kcontrol *kctl = ctl_find(ac97, "External Amplifier", NULL); - if (! kctl) - return -ENOENT; - set_inv_eapd(ac97, kctl); - return 0; -} - -static int master_mute_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - int err = snd_ac97_put_volsw(kcontrol, ucontrol); - if (err > 0) { - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - unsigned short mask; - if (shift != rshift) - mask = AC97_MUTE_MASK_STEREO; - else - mask = AC97_MUTE_MASK_MONO; - snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD, - (ac97->regs[AC97_MASTER] & mask) == mask ? - AC97_PD_EAPD : 0); - } - return err; -} - -/* ac97 tune: EAPD controls mute LED bound with the master mute */ -static int tune_mute_led(struct snd_ac97 *ac97) -{ - struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL); - if (! msw) - return -ENOENT; - msw->put = master_mute_sw_put; - snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); - snd_ac97_update_bits( - ac97, AC97_POWERDOWN, - AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */ - ); - ac97->scaps |= AC97_SCAP_EAPD_LED; - return 0; -} - -static int hp_master_mute_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int err = bind_hp_volsw_put(kcontrol, ucontrol); - if (err > 0) { - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int shift = (kcontrol->private_value >> 8) & 0x0f; - int rshift = (kcontrol->private_value >> 12) & 0x0f; - unsigned short mask; - if (shift != rshift) - mask = AC97_MUTE_MASK_STEREO; - else - mask = AC97_MUTE_MASK_MONO; - snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD, - (ac97->regs[AC97_MASTER] & mask) == mask ? - AC97_PD_EAPD : 0); - } - return err; -} - -static int tune_hp_mute_led(struct snd_ac97 *ac97) -{ - struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL); - struct snd_kcontrol *mvol = ctl_find(ac97, "Master Playback Volume", NULL); - if (! msw || ! mvol) - return -ENOENT; - msw->put = hp_master_mute_sw_put; - mvol->put = bind_hp_volsw_put; - snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); - snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch"); - snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume"); - snd_ac97_update_bits( - ac97, AC97_POWERDOWN, - AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */ - ); - return 0; -} - -struct quirk_table { - const char *name; - int (*func)(struct snd_ac97 *); -}; - -static struct quirk_table applicable_quirks[] = { - { "none", NULL }, - { "hp_only", tune_hp_only }, - { "swap_hp", tune_swap_hp }, - { "swap_surround", tune_swap_surround }, - { "ad_sharing", tune_ad_sharing }, - { "alc_jack", tune_alc_jack }, - { "inv_eapd", tune_inv_eapd }, - { "mute_led", tune_mute_led }, - { "hp_mute_led", tune_hp_mute_led }, -}; - -/* apply the quirk with the given type */ -static int apply_quirk(struct snd_ac97 *ac97, int type) -{ - if (type <= 0) - return 0; - else if (type >= ARRAY_SIZE(applicable_quirks)) - return -EINVAL; - if (applicable_quirks[type].func) - return applicable_quirks[type].func(ac97); - return 0; -} - -/* apply the quirk with the given name */ -static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr) -{ - int i; - struct quirk_table *q; - - for (i = 0; i < ARRAY_SIZE(applicable_quirks); i++) { - q = &applicable_quirks[i]; - if (q->name && ! strcmp(typestr, q->name)) - return apply_quirk(ac97, i); - } - /* for compatibility, accept the numbers, too */ - if (*typestr >= '0' && *typestr <= '9') - return apply_quirk(ac97, (int)simple_strtoul(typestr, NULL, 10)); - return -EINVAL; -} - -/** - * snd_ac97_tune_hardware - tune up the hardware - * @ac97: the ac97 instance - * @quirk: quirk list - * @override: explicit quirk value (overrides the list if non-NULL) - * - * Do some workaround for each pci device, such as renaming of the - * headphone (true line-out) control as "Master". - * The quirk-list must be terminated with a zero-filled entry. - * - * Returns zero if successful, or a negative error code on failure. - */ - -int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override) -{ - int result; - - /* quirk overriden? */ - if (override && strcmp(override, "-1") && strcmp(override, "default")) { - result = apply_quirk_str(ac97, override); - if (result < 0) - snd_printk(KERN_ERR "applying quirk type %s failed (%d)\n", override, result); - return result; - } - - if (! quirk) - return -EINVAL; - - for (; quirk->subvendor; quirk++) { - if (quirk->subvendor != ac97->subsystem_vendor) - continue; - if ((! quirk->mask && quirk->subdevice == ac97->subsystem_device) || - quirk->subdevice == (quirk->mask & ac97->subsystem_device)) { - if (quirk->codec_id && quirk->codec_id != ac97->id) - continue; - snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device); - result = apply_quirk(ac97, quirk->type); - if (result < 0) - snd_printk(KERN_ERR "applying quirk type %d for %s failed (%d)\n", quirk->type, quirk->name, result); - return result; - } - } - return 0; -} - -EXPORT_SYMBOL(snd_ac97_tune_hardware); - -/* - * INIT part - */ - -static int __init alsa_ac97_init(void) -{ - return 0; -} - -static void __exit alsa_ac97_exit(void) -{ -} - -module_init(alsa_ac97_init) -module_exit(alsa_ac97_exit) diff --git a/ANDROID_3.4.5/sound/pci/ac97/ac97_id.h b/ANDROID_3.4.5/sound/pci/ac97/ac97_id.h deleted file mode 100644 index d603147c..00000000 --- a/ANDROID_3.4.5/sound/pci/ac97/ac97_id.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Universal interface for Audio Codec '97 - * - * For more details look to AC '97 component specification revision 2.2 - * by Intel Corporation (http://developer.intel.com). - * - * - * 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 - * - */ - -#define AC97_ID_AK4540 0x414b4d00 -#define AC97_ID_AK4542 0x414b4d01 -#define AC97_ID_AD1819 0x41445303 -#define AC97_ID_AD1881 0x41445340 -#define AC97_ID_AD1881A 0x41445348 -#define AC97_ID_AD1885 0x41445360 -#define AC97_ID_AD1886 0x41445361 -#define AC97_ID_AD1887 0x41445362 -#define AC97_ID_AD1886A 0x41445363 -#define AC97_ID_AD1980 0x41445370 -#define AC97_ID_TR28028 0x54524108 -#define AC97_ID_STAC9700 0x83847600 -#define AC97_ID_STAC9704 0x83847604 -#define AC97_ID_STAC9705 0x83847605 -#define AC97_ID_STAC9708 0x83847608 -#define AC97_ID_STAC9721 0x83847609 -#define AC97_ID_STAC9744 0x83847644 -#define AC97_ID_STAC9756 0x83847656 -#define AC97_ID_CS4297A 0x43525910 -#define AC97_ID_CS4299 0x43525930 -#define AC97_ID_CS4201 0x43525948 -#define AC97_ID_CS4205 0x43525958 -#define AC97_ID_CS_MASK 0xfffffff8 /* bit 0-2: rev */ -#define AC97_ID_ALC100 0x414c4300 -#define AC97_ID_ALC650 0x414c4720 -#define AC97_ID_ALC650D 0x414c4721 -#define AC97_ID_ALC650E 0x414c4722 -#define AC97_ID_ALC650F 0x414c4723 -#define AC97_ID_ALC655 0x414c4760 -#define AC97_ID_ALC658 0x414c4780 -#define AC97_ID_ALC658D 0x414c4781 -#define AC97_ID_ALC850 0x414c4790 -#define AC97_ID_YMF743 0x594d4800 -#define AC97_ID_YMF753 0x594d4803 -#define AC97_ID_VT1616 0x49434551 -#define AC97_ID_CM9738 0x434d4941 -#define AC97_ID_CM9739 0x434d4961 -#define AC97_ID_CM9761_78 0x434d4978 -#define AC97_ID_CM9761_82 0x434d4982 -#define AC97_ID_CM9761_83 0x434d4983 -#define AC97_ID_ST7597 0x53544d02 -#define AC97_ID_ST_AC97_ID4 0x53544d04 diff --git a/ANDROID_3.4.5/sound/pci/ac97/ac97_local.h b/ANDROID_3.4.5/sound/pci/ac97/ac97_local.h deleted file mode 100644 index c276a5e3..00000000 --- a/ANDROID_3.4.5/sound/pci/ac97/ac97_local.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Universal interface for Audio Codec '97 - * - * For more details look to AC '97 component specification revision 2.2 - * by Intel Corporation (http://developer.intel.com). - * - * - * 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 - * - */ - -void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, - int modem); -int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, - unsigned short mask, unsigned short value); - -/* ac97_proc.c */ -#ifdef CONFIG_PROC_FS -void snd_ac97_bus_proc_init(struct snd_ac97_bus * ac97); -void snd_ac97_bus_proc_done(struct snd_ac97_bus * ac97); -void snd_ac97_proc_init(struct snd_ac97 * ac97); -void snd_ac97_proc_done(struct snd_ac97 * ac97); -#else -#define snd_ac97_bus_proc_init(ac97_bus_t) do { } while (0) -#define snd_ac97_bus_proc_done(ac97_bus_t) do { } while (0) -#define snd_ac97_proc_init(ac97_t) do { } while (0) -#define snd_ac97_proc_done(ac97_t) do { } while (0) -#endif diff --git a/ANDROID_3.4.5/sound/pci/ac97/ac97_patch.c b/ANDROID_3.4.5/sound/pci/ac97/ac97_patch.c deleted file mode 100644 index a872d0a8..00000000 --- a/ANDROID_3.4.5/sound/pci/ac97/ac97_patch.c +++ /dev/null @@ -1,3965 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Universal interface for Audio Codec '97 - * - * For more details look to AC '97 component specification revision 2.2 - * by Intel Corporation (http://developer.intel.com) and to datasheets - * for specific codecs. - * - * - * 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 "ac97_local.h" -#include "ac97_patch.h" - -/* - * Forward declarations - */ - -static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97, - const char *name); -static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, - const unsigned int *tlv, const char **slaves); - -/* - * Chip specific initialization - */ - -static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontrol_new *controls, int count) -{ - int idx, err; - - for (idx = 0; idx < count; idx++) - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&controls[idx], ac97))) < 0) - return err; - return 0; -} - -/* replace with a new TLV */ -static void reset_tlv(struct snd_ac97 *ac97, const char *name, - const unsigned int *tlv) -{ - struct snd_ctl_elem_id sid; - struct snd_kcontrol *kctl; - memset(&sid, 0, sizeof(sid)); - strcpy(sid.name, name); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kctl = snd_ctl_find_id(ac97->bus->card, &sid); - if (kctl && kctl->tlv.p) - kctl->tlv.p = tlv; -} - -/* set to the page, update bits and restore the page */ -static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page) -{ - unsigned short page_save; - int ret; - - mutex_lock(&ac97->page_mutex); - page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK; - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page); - ret = snd_ac97_update_bits(ac97, reg, mask, value); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save); - mutex_unlock(&ac97->page_mutex); /* unlock paging */ - return ret; -} - -/* - * shared line-in/mic controls - */ -static int ac97_enum_text_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo, - const char **texts, unsigned int nums) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = nums; - if (uinfo->value.enumerated.item > nums - 1) - uinfo->value.enumerated.item = nums - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int ac97_surround_jack_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[] = { "Shared", "Independent" }; - return ac97_enum_text_info(kcontrol, uinfo, texts, 2); -} - -static int ac97_surround_jack_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = ac97->indep_surround; - return 0; -} - -static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned char indep = !!ucontrol->value.enumerated.item[0]; - - if (indep != ac97->indep_surround) { - ac97->indep_surround = indep; - if (ac97->build_ops->update_jacks) - ac97->build_ops->update_jacks(ac97); - return 1; - } - return 0; -} - -static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[] = { "2ch", "4ch", "6ch", "8ch" }; - return ac97_enum_text_info(kcontrol, uinfo, texts, - kcontrol->private_value); -} - -static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = ac97->channel_mode; - return 0; -} - -static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned char mode = ucontrol->value.enumerated.item[0]; - - if (mode >= kcontrol->private_value) - return -EINVAL; - - if (mode != ac97->channel_mode) { - ac97->channel_mode = mode; - if (ac97->build_ops->update_jacks) - ac97->build_ops->update_jacks(ac97); - return 1; - } - return 0; -} - -#define AC97_SURROUND_JACK_MODE_CTL \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Surround Jack Mode", \ - .info = ac97_surround_jack_mode_info, \ - .get = ac97_surround_jack_mode_get, \ - .put = ac97_surround_jack_mode_put, \ - } -/* 6ch */ -#define AC97_CHANNEL_MODE_CTL \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Channel Mode", \ - .info = ac97_channel_mode_info, \ - .get = ac97_channel_mode_get, \ - .put = ac97_channel_mode_put, \ - .private_value = 3, \ - } -/* 4ch */ -#define AC97_CHANNEL_MODE_4CH_CTL \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Channel Mode", \ - .info = ac97_channel_mode_info, \ - .get = ac97_channel_mode_get, \ - .put = ac97_channel_mode_put, \ - .private_value = 2, \ - } -/* 8ch */ -#define AC97_CHANNEL_MODE_8CH_CTL \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Channel Mode", \ - .info = ac97_channel_mode_info, \ - .get = ac97_channel_mode_get, \ - .put = ac97_channel_mode_put, \ - .private_value = 4, \ - } - -static inline int is_surround_on(struct snd_ac97 *ac97) -{ - return ac97->channel_mode >= 1; -} - -static inline int is_clfe_on(struct snd_ac97 *ac97) -{ - return ac97->channel_mode >= 2; -} - -/* system has shared jacks with surround out enabled */ -static inline int is_shared_surrout(struct snd_ac97 *ac97) -{ - return !ac97->indep_surround && is_surround_on(ac97); -} - -/* system has shared jacks with center/lfe out enabled */ -static inline int is_shared_clfeout(struct snd_ac97 *ac97) -{ - return !ac97->indep_surround && is_clfe_on(ac97); -} - -/* system has shared jacks with line in enabled */ -static inline int is_shared_linein(struct snd_ac97 *ac97) -{ - return !ac97->indep_surround && !is_surround_on(ac97); -} - -/* system has shared jacks with mic in enabled */ -static inline int is_shared_micin(struct snd_ac97 *ac97) -{ - return !ac97->indep_surround && !is_clfe_on(ac97); -} - -static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97) -{ - return is_surround_on(ac97); -} - -/* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ -/* Modified for YMF743 by Keita Maehara */ - -/* It is possible to indicate to the Yamaha YMF7x3 the type of - speakers being used. */ - -static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { - "Standard", "Small", "Smaller" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL]; - val = (val >> 10) & 3; - if (val > 0) /* 0 = invalid */ - val--; - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - val = (ucontrol->value.enumerated.item[0] + 1) << 10; - return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val); -} - -static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "3D Control - Speaker", - .info = snd_ac97_ymf7x3_info_speaker, - .get = snd_ac97_ymf7x3_get_speaker, - .put = snd_ac97_ymf7x3_put_speaker, -}; - -/* It is possible to indicate to the Yamaha YMF7x3 the source to - direct to the S/PDIF output. */ -static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { "AC-Link", "A/D Converter" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_YMF7X3_DIT_CTRL]; - ucontrol->value.enumerated.item[0] = (val >> 1) & 1; - return 0; -} - -static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - if (ucontrol->value.enumerated.item[0] > 1) - return -EINVAL; - val = ucontrol->value.enumerated.item[0] << 1; - return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val); -} - -static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97) -{ - struct snd_kcontrol *kctl; - int err; - - kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97); - err = snd_ctl_add(ac97->bus->card, kctl); - if (err < 0) - return err; - strcpy(kctl->id.name, "3D Control - Wide"); - kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0); - snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); - err = snd_ctl_add(ac97->bus->card, - snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker, - ac97)); - if (err < 0) - return err; - snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00); - return 0; -} - -static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] = -{ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), - AC97_YMF7X3_DIT_CTRL, 0, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source", - .info = snd_ac97_ymf7x3_spdif_source_info, - .get = snd_ac97_ymf7x3_spdif_source_get, - .put = snd_ac97_ymf7x3_spdif_source_put, - }, - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute", - AC97_YMF7X3_DIT_CTRL, 2, 1, 1) -}; - -static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97) -{ - int err; - - err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3); - if (err < 0) - return err; - err = patch_build_controls(ac97, - snd_ac97_yamaha_ymf743_controls_spdif, 3); - if (err < 0) - return err; - /* set default PCM S/PDIF params */ - /* PCM audio,no copyright,no preemphasis,PCM coder,original */ - snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201); - return 0; -} - -static const struct snd_ac97_build_ops patch_yamaha_ymf743_ops = { - .build_spdif = patch_yamaha_ymf743_build_spdif, - .build_3d = patch_yamaha_ymf7x3_3d, -}; - -static int patch_yamaha_ymf743(struct snd_ac97 *ac97) -{ - ac97->build_ops = &patch_yamaha_ymf743_ops; - ac97->caps |= AC97_BC_BASS_TREBLE; - ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */ - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ - ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ - return 0; -} - -/* The AC'97 spec states that the S/PDIF signal is to be output at pin 48. - The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48. - By default, no output pin is selected, and the S/PDIF signal is not output. - There is also a bit to mute S/PDIF output in a vendor-specific register. */ -static int snd_ac97_ymf753_spdif_output_pin_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_YMF7X3_DIT_CTRL]; - ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0; - return 0; -} - -static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 : - (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0; - return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val); - /* The following can be used to direct S/PDIF output to pin 47 (EAPD). - snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */ -} - -static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = snd_ac97_ymf7x3_spdif_source_info, - .get = snd_ac97_ymf7x3_spdif_source_get, - .put = snd_ac97_ymf7x3_spdif_source_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin", - .info = snd_ac97_ymf753_spdif_output_pin_info, - .get = snd_ac97_ymf753_spdif_output_pin_get, - .put = snd_ac97_ymf753_spdif_output_pin_put, - }, - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute", - AC97_YMF7X3_DIT_CTRL, 2, 1, 1) -}; - -static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97) -{ - int err; - - if ((err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif))) < 0) - return err; - return 0; -} - -static const struct snd_ac97_build_ops patch_yamaha_ymf753_ops = { - .build_3d = patch_yamaha_ymf7x3_3d, - .build_post_spdif = patch_yamaha_ymf753_post_spdif -}; - -static int patch_yamaha_ymf753(struct snd_ac97 * ac97) -{ - /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com. - This chip has nonstandard and extended behaviour with regard to its S/PDIF output. - The AC'97 spec states that the S/PDIF signal is to be output at pin 48. - The YMF753 will ouput the S/PDIF signal to pin 43, 47 (EAPD), or 48. - By default, no output pin is selected, and the S/PDIF signal is not output. - There is also a bit to mute S/PDIF output in a vendor-specific register. - */ - ac97->build_ops = &patch_yamaha_ymf753_ops; - ac97->caps |= AC97_BC_BASS_TREBLE; - ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */ - return 0; -} - -/* - * May 2, 2003 Liam Girdwood - * removed broken wolfson00 patch. - * added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717. - */ - -static const struct snd_kcontrol_new wm97xx_snd_ac97_controls[] = { -AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1), -AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1), -}; - -static int patch_wolfson_wm9703_specific(struct snd_ac97 * ac97) -{ - /* This is known to work for the ViewSonic ViewPad 1000 - * Randolph Bentson - * WM9703/9707/9708/9717 - */ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0) - return err; - } - snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808); - return 0; -} - -static const struct snd_ac97_build_ops patch_wolfson_wm9703_ops = { - .build_specific = patch_wolfson_wm9703_specific, -}; - -static int patch_wolfson03(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_wolfson_wm9703_ops; - return 0; -} - -static const struct snd_kcontrol_new wm9704_snd_ac97_controls[] = { -AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1), -AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1), -AC97_DOUBLE("Rear Playback Volume", AC97_WM9704_RMIXER_VOL, 8, 0, 31, 1), -AC97_SINGLE("Rear Playback Switch", AC97_WM9704_RMIXER_VOL, 15, 1, 1), -AC97_DOUBLE("Rear DAC Volume", AC97_WM9704_RPCM_VOL, 8, 0, 31, 1), -AC97_DOUBLE("Surround Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), -}; - -static int patch_wolfson_wm9704_specific(struct snd_ac97 * ac97) -{ - int err, i; - for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97))) < 0) - return err; - } - /* patch for DVD noise */ - snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200); - return 0; -} - -static const struct snd_ac97_build_ops patch_wolfson_wm9704_ops = { - .build_specific = patch_wolfson_wm9704_specific, -}; - -static int patch_wolfson04(struct snd_ac97 * ac97) -{ - /* WM9704M/9704Q */ - ac97->build_ops = &patch_wolfson_wm9704_ops; - return 0; -} - -static int patch_wolfson05(struct snd_ac97 * ac97) -{ - /* WM9705, WM9710 */ - ac97->build_ops = &patch_wolfson_wm9703_ops; -#ifdef CONFIG_TOUCHSCREEN_WM9705 - /* WM9705 touchscreen uses AUX and VIDEO for touch */ - ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; -#endif - return 0; -} - -static const char* wm9711_alc_select[] = {"None", "Left", "Right", "Stereo"}; -static const char* wm9711_alc_mix[] = {"Stereo", "Right", "Left", "None"}; -static const char* wm9711_out3_src[] = {"Left", "VREF", "Left + Right", "Mono"}; -static const char* wm9711_out3_lrsrc[] = {"Master Mix", "Headphone Mix"}; -static const char* wm9711_rec_adc[] = {"Stereo", "Left", "Right", "Mute"}; -static const char* wm9711_base[] = {"Linear Control", "Adaptive Boost"}; -static const char* wm9711_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"}; -static const char* wm9711_mic[] = {"Mic 1", "Differential", "Mic 2", "Stereo"}; -static const char* wm9711_rec_sel[] = - {"Mic 1", "NC", "NC", "Master Mix", "Line", "Headphone Mix", "Phone Mix", "Phone"}; -static const char* wm9711_ng_type[] = {"Constant Gain", "Mute"}; - -static const struct ac97_enum wm9711_enum[] = { -AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9711_alc_select), -AC97_ENUM_SINGLE(AC97_VIDEO, 10, 4, wm9711_alc_mix), -AC97_ENUM_SINGLE(AC97_AUX, 9, 4, wm9711_out3_src), -AC97_ENUM_SINGLE(AC97_AUX, 8, 2, wm9711_out3_lrsrc), -AC97_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9711_rec_adc), -AC97_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9711_base), -AC97_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9711_rec_gain), -AC97_ENUM_SINGLE(AC97_MIC, 5, 4, wm9711_mic), -AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, wm9711_rec_sel), -AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9711_ng_type), -}; - -static const struct snd_kcontrol_new wm9711_snd_ac97_controls[] = { -AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0), -AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0), -AC97_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0), -AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0), -AC97_ENUM("ALC Function", wm9711_enum[0]), -AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 1), -AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1), -AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0), -AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0), -AC97_ENUM("ALC NG Type", wm9711_enum[9]), -AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1), - -AC97_SINGLE("Side Tone Switch", AC97_VIDEO, 15, 1, 1), -AC97_SINGLE("Side Tone Volume", AC97_VIDEO, 12, 7, 1), -AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]), -AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1), - -AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1), -AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0), -AC97_ENUM("Out3 Mux", wm9711_enum[2]), -AC97_ENUM("Out3 LR Mux", wm9711_enum[3]), -AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1), - -AC97_SINGLE("Beep to Headphone Switch", AC97_PC_BEEP, 15, 1, 1), -AC97_SINGLE("Beep to Headphone Volume", AC97_PC_BEEP, 12, 7, 1), -AC97_SINGLE("Beep to Side Tone Switch", AC97_PC_BEEP, 11, 1, 1), -AC97_SINGLE("Beep to Side Tone Volume", AC97_PC_BEEP, 8, 7, 1), -AC97_SINGLE("Beep to Phone Switch", AC97_PC_BEEP, 7, 1, 1), -AC97_SINGLE("Beep to Phone Volume", AC97_PC_BEEP, 4, 7, 1), - -AC97_SINGLE("Aux to Headphone Switch", AC97_CD, 15, 1, 1), -AC97_SINGLE("Aux to Headphone Volume", AC97_CD, 12, 7, 1), -AC97_SINGLE("Aux to Side Tone Switch", AC97_CD, 11, 1, 1), -AC97_SINGLE("Aux to Side Tone Volume", AC97_CD, 8, 7, 1), -AC97_SINGLE("Aux to Phone Switch", AC97_CD, 7, 1, 1), -AC97_SINGLE("Aux to Phone Volume", AC97_CD, 4, 7, 1), - -AC97_SINGLE("Phone to Headphone Switch", AC97_PHONE, 15, 1, 1), -AC97_SINGLE("Phone to Master Switch", AC97_PHONE, 14, 1, 1), - -AC97_SINGLE("Line to Headphone Switch", AC97_LINE, 15, 1, 1), -AC97_SINGLE("Line to Master Switch", AC97_LINE, 14, 1, 1), -AC97_SINGLE("Line to Phone Switch", AC97_LINE, 13, 1, 1), - -AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PCM, 15, 1, 1), -AC97_SINGLE("PCM Playback to Master Switch", AC97_PCM, 14, 1, 1), -AC97_SINGLE("PCM Playback to Phone Switch", AC97_PCM, 13, 1, 1), - -AC97_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0), -AC97_ENUM("Capture to Phone Mux", wm9711_enum[4]), -AC97_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1), -AC97_ENUM("Capture Select", wm9711_enum[8]), - -AC97_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), -AC97_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), - -AC97_ENUM("Bass Control", wm9711_enum[5]), -AC97_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1), -AC97_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1), -AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), - -AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1), -AC97_ENUM("Capture Volume Steps", wm9711_enum[6]), -AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), -AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), - -AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1), -AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1), -AC97_ENUM("Mic Select Source", wm9711_enum[7]), -AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1), -AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), -AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), - -AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0), -AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0), -AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0), -AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0), -}; - -static int patch_wolfson_wm9711_specific(struct snd_ac97 * ac97) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97))) < 0) - return err; - } - snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x0808); - snd_ac97_write_cache(ac97, AC97_PCI_SVID, 0x0808); - snd_ac97_write_cache(ac97, AC97_VIDEO, 0x0808); - snd_ac97_write_cache(ac97, AC97_AUX, 0x0808); - snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808); - snd_ac97_write_cache(ac97, AC97_CD, 0x0000); - return 0; -} - -static const struct snd_ac97_build_ops patch_wolfson_wm9711_ops = { - .build_specific = patch_wolfson_wm9711_specific, -}; - -static int patch_wolfson11(struct snd_ac97 * ac97) -{ - /* WM9711, WM9712 */ - ac97->build_ops = &patch_wolfson_wm9711_ops; - - ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_MIC | - AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD; - - return 0; -} - -static const char* wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; -static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; -static const char* wm9713_rec_src[] = - {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone Mix", "Master Mix", - "Mono Mix", "Zh"}; -static const char* wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"}; -static const char* wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"}; -static const char* wm9713_mono_pga[] = {"Vmid", "Zh", "Mono Mix", "Inv 1"}; -static const char* wm9713_spk_pga[] = - {"Vmid", "Zh", "Headphone Mix", "Master Mix", "Inv", "NC", "NC", "NC"}; -static const char* wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone Mix", "NC"}; -static const char* wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "NC"}; -static const char* wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "NC"}; -static const char* wm9713_dac_inv[] = - {"Off", "Mono Mix", "Master Mix", "Headphone Mix L", "Headphone Mix R", - "Headphone Mix Mono", "NC", "Vmid"}; -static const char* wm9713_base[] = {"Linear Control", "Adaptive Boost"}; -static const char* wm9713_ng_type[] = {"Constant Gain", "Mute"}; - -static const struct ac97_enum wm9713_enum[] = { -AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), -AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), -AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux), -AC97_ENUM_DOUBLE(AC97_VIDEO, 3, 0, 8, wm9713_rec_src), -AC97_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain), -AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), -AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), -AC97_ENUM_DOUBLE(AC97_REC_GAIN, 11, 8, 8, wm9713_spk_pga), -AC97_ENUM_DOUBLE(AC97_REC_GAIN, 6, 4, 4, wm9713_hp_pga), -AC97_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), -AC97_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), -AC97_ENUM_DOUBLE(AC97_REC_GAIN_MIC, 13, 10, 8, wm9713_dac_inv), -AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_base), -AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), -}; - -static const struct snd_kcontrol_new wm13_snd_ac97_controls[] = { -AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1), -AC97_SINGLE("Line In to Headphone Switch", AC97_PC_BEEP, 15, 1, 1), -AC97_SINGLE("Line In to Master Switch", AC97_PC_BEEP, 14, 1, 1), -AC97_SINGLE("Line In to Mono Switch", AC97_PC_BEEP, 13, 1, 1), - -AC97_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1), -AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PHONE, 15, 1, 1), -AC97_SINGLE("PCM Playback to Master Switch", AC97_PHONE, 14, 1, 1), -AC97_SINGLE("PCM Playback to Mono Switch", AC97_PHONE, 13, 1, 1), - -AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1), -AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1), -AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1), -AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1), -AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0), -AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]), -AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1), - -AC97_SINGLE("Capture Switch", AC97_CD, 15, 1, 1), -AC97_ENUM("Capture Volume Steps", wm9713_enum[4]), -AC97_DOUBLE("Capture Volume", AC97_CD, 8, 0, 15, 0), -AC97_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0), - -AC97_ENUM("Capture to Headphone Mux", wm9713_enum[1]), -AC97_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1), -AC97_ENUM("Capture to Mono Mux", wm9713_enum[2]), -AC97_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0), -AC97_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0), -AC97_ENUM("Capture Select", wm9713_enum[3]), - -AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0), -AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0), -AC97_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0), -AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0), -AC97_ENUM("ALC Function", wm9713_enum[5]), -AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0), -AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0), -AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0), -AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0), -AC97_ENUM("ALC NG Type", wm9713_enum[13]), -AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0), - -AC97_DOUBLE("Master ZC Switch", AC97_MASTER, 14, 6, 1, 0), -AC97_DOUBLE("Headphone ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0), -AC97_DOUBLE("Out3/4 ZC Switch", AC97_MASTER_MONO, 14, 6, 1, 0), -AC97_SINGLE("Master Right Switch", AC97_MASTER, 7, 1, 1), -AC97_SINGLE("Headphone Right Switch", AC97_HEADPHONE, 7, 1, 1), -AC97_SINGLE("Out3/4 Right Switch", AC97_MASTER_MONO, 7, 1, 1), - -AC97_SINGLE("Mono In to Headphone Switch", AC97_MASTER_TONE, 15, 1, 1), -AC97_SINGLE("Mono In to Master Switch", AC97_MASTER_TONE, 14, 1, 1), -AC97_SINGLE("Mono In Volume", AC97_MASTER_TONE, 8, 31, 1), -AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1), -AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0), -AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1), - -AC97_SINGLE("Beep to Headphone Switch", AC97_AUX, 15, 1, 1), -AC97_SINGLE("Beep to Headphone Volume", AC97_AUX, 12, 7, 1), -AC97_SINGLE("Beep to Master Switch", AC97_AUX, 11, 1, 1), -AC97_SINGLE("Beep to Master Volume", AC97_AUX, 8, 7, 1), -AC97_SINGLE("Beep to Mono Switch", AC97_AUX, 7, 1, 1), -AC97_SINGLE("Beep to Mono Volume", AC97_AUX, 4, 7, 1), - -AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1), -AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1), -AC97_SINGLE("Voice to Master Switch", AC97_PCM, 11, 1, 1), -AC97_SINGLE("Voice to Master Volume", AC97_PCM, 8, 7, 1), -AC97_SINGLE("Voice to Mono Switch", AC97_PCM, 7, 1, 1), -AC97_SINGLE("Voice to Mono Volume", AC97_PCM, 4, 7, 1), - -AC97_SINGLE("Aux to Headphone Switch", AC97_REC_SEL, 15, 1, 1), -AC97_SINGLE("Aux to Headphone Volume", AC97_REC_SEL, 12, 7, 1), -AC97_SINGLE("Aux to Master Switch", AC97_REC_SEL, 11, 1, 1), -AC97_SINGLE("Aux to Master Volume", AC97_REC_SEL, 8, 7, 1), -AC97_SINGLE("Aux to Mono Switch", AC97_REC_SEL, 7, 1, 1), -AC97_SINGLE("Aux to Mono Volume", AC97_REC_SEL, 4, 7, 1), - -AC97_ENUM("Mono Input Mux", wm9713_enum[6]), -AC97_ENUM("Master Input Mux", wm9713_enum[7]), -AC97_ENUM("Headphone Input Mux", wm9713_enum[8]), -AC97_ENUM("Out 3 Input Mux", wm9713_enum[9]), -AC97_ENUM("Out 4 Input Mux", wm9713_enum[10]), - -AC97_ENUM("Bass Control", wm9713_enum[12]), -AC97_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1), -AC97_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1), -AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0), -AC97_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1), -AC97_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1), -}; - -static const struct snd_kcontrol_new wm13_snd_ac97_controls_3d[] = { -AC97_ENUM("Inv Input Mux", wm9713_enum[11]), -AC97_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0), -AC97_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0), -AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), -}; - -static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97))) < 0) - return err; - } - return 0; -} - -static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97))) < 0) - return err; - } - snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808); - snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808); - snd_ac97_write_cache(ac97, AC97_MIC, 0x0808); - snd_ac97_write_cache(ac97, AC97_LINE, 0x00da); - snd_ac97_write_cache(ac97, AC97_CD, 0x0808); - snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612); - snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0); - return 0; -} - -#ifdef CONFIG_PM -static void patch_wolfson_wm9713_suspend (struct snd_ac97 * ac97) -{ - snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff); - snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff); -} - -static void patch_wolfson_wm9713_resume (struct snd_ac97 * ac97) -{ - snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00); - snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810); - snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0); -} -#endif - -static const struct snd_ac97_build_ops patch_wolfson_wm9713_ops = { - .build_specific = patch_wolfson_wm9713_specific, - .build_3d = patch_wolfson_wm9713_3d, -#ifdef CONFIG_PM - .suspend = patch_wolfson_wm9713_suspend, - .resume = patch_wolfson_wm9713_resume -#endif -}; - -static int patch_wolfson13(struct snd_ac97 * ac97) -{ - /* WM9713, WM9714 */ - ac97->build_ops = &patch_wolfson_wm9713_ops; - - ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE | - AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE | - AC97_HAS_NO_STD_PCM; - ac97->scaps &= ~AC97_SCAP_MODEM; - - snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00); - snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810); - snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0); - - return 0; -} - -/* - * Tritech codec - */ -static int patch_tritech_tr28028(struct snd_ac97 * ac97) -{ - snd_ac97_write_cache(ac97, 0x26, 0x0300); - snd_ac97_write_cache(ac97, 0x26, 0x0000); - snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000); - snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000); - return 0; -} - -/* - * Sigmatel STAC97xx codecs - */ -static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97) -{ - struct snd_kcontrol *kctl; - int err; - - if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) - return err; - strcpy(kctl->id.name, "3D Control Sigmatel - Depth"); - kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0); - snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); - return 0; -} - -static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97) -{ - struct snd_kcontrol *kctl; - int err; - - if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) - return err; - strcpy(kctl->id.name, "3D Control Sigmatel - Depth"); - kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0); - if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) - return err; - strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth"); - kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0); - snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); - return 0; -} - -static const struct snd_kcontrol_new snd_ac97_sigmatel_4speaker = -AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch", - AC97_SIGMATEL_DAC2INVERT, 2, 1, 0); - -/* "Sigmatel " removed due to excessive name length: */ -static const struct snd_kcontrol_new snd_ac97_sigmatel_phaseinvert = -AC97_SINGLE("Surround Phase Inversion Playback Switch", - AC97_SIGMATEL_DAC2INVERT, 3, 1, 0); - -static const struct snd_kcontrol_new snd_ac97_sigmatel_controls[] = { -AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0), -AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0) -}; - -static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97) -{ - int err; - - snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003); - if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1)) - if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1)) < 0) - return err; - if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0)) - if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1)) < 0) - return err; - if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2)) - if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1)) < 0) - return err; - if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3)) - if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1)) < 0) - return err; - return 0; -} - -static const struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = { - .build_3d = patch_sigmatel_stac9700_3d, - .build_specific = patch_sigmatel_stac97xx_specific -}; - -static int patch_sigmatel_stac9700(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_sigmatel_stac9700_ops; - return 0; -} - -static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int err; - - mutex_lock(&ac97->page_mutex); - snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba); - err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010, - (ucontrol->value.integer.value[0] & 1) << 4); - snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0); - mutex_unlock(&ac97->page_mutex); - return err; -} - -static const struct snd_kcontrol_new snd_ac97_stac9708_bias_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Sigmatel Output Bias Switch", - .info = snd_ac97_info_volsw, - .get = snd_ac97_get_volsw, - .put = snd_ac97_stac9708_put_bias, - .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0), -}; - -static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97) -{ - int err; - - /* the register bit is writable, but the function is not implemented: */ - snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL); - - snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback"); - if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0) - return err; - return patch_sigmatel_stac97xx_specific(ac97); -} - -static const struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = { - .build_3d = patch_sigmatel_stac9708_3d, - .build_specific = patch_sigmatel_stac9708_specific -}; - -static int patch_sigmatel_stac9708(struct snd_ac97 * ac97) -{ - unsigned int codec72, codec6c; - - ac97->build_ops = &patch_sigmatel_stac9708_ops; - ac97->caps |= 0x10; /* HP (sigmatel surround) support */ - - codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000; - codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG); - - if ((codec72==0) && (codec6c==0)) { - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007); - } else if ((codec72==0x8000) && (codec6c==0)) { - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008); - } else if ((codec72==0x8000) && (codec6c==0x0080)) { - /* nothing */ - } - snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); - return 0; -} - -static int patch_sigmatel_stac9721(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_sigmatel_stac9700_ops; - if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) { - // patch for SigmaTel - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); - } - snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); - return 0; -} - -static int patch_sigmatel_stac9744(struct snd_ac97 * ac97) -{ - // patch for SigmaTel - ac97->build_ops = &patch_sigmatel_stac9700_ops; - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */ - snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); - return 0; -} - -static int patch_sigmatel_stac9756(struct snd_ac97 * ac97) -{ - // patch for SigmaTel - ac97->build_ops = &patch_sigmatel_stac9700_ops; - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */ - snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); - snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); - return 0; -} - -static int snd_ac97_stac9758_output_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[5] = { "Input/Disabled", "Front Output", - "Rear Output", "Center/LFE Output", "Mixer Output" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_stac9758_output_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value; - unsigned short val; - - val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift; - if (!(val & 4)) - ucontrol->value.enumerated.item[0] = 0; - else - ucontrol->value.enumerated.item[0] = 1 + (val & 3); - return 0; -} - -static int snd_ac97_stac9758_output_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value; - unsigned short val; - - if (ucontrol->value.enumerated.item[0] > 4) - return -EINVAL; - if (ucontrol->value.enumerated.item[0] == 0) - val = 0; - else - val = 4 | (ucontrol->value.enumerated.item[0] - 1); - return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL, - 7 << shift, val << shift, 0); -} - -static int snd_ac97_stac9758_input_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[7] = { "Mic2 Jack", "Mic1 Jack", "Line In Jack", - "Front Jack", "Rear Jack", "Center/LFE Jack", "Mute" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 7; - if (uinfo->value.enumerated.item > 6) - uinfo->value.enumerated.item = 6; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_stac9758_input_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value; - unsigned short val; - - val = ac97->regs[AC97_SIGMATEL_INSEL]; - ucontrol->value.enumerated.item[0] = (val >> shift) & 7; - return 0; -} - -static int snd_ac97_stac9758_input_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value; - - return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift, - ucontrol->value.enumerated.item[0] << shift, 0); -} - -static int snd_ac97_stac9758_phonesel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { "None", "Front Jack", "Rear Jack" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_stac9758_phonesel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = ac97->regs[AC97_SIGMATEL_IOMISC] & 3; - return 0; -} - -static int snd_ac97_stac9758_phonesel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3, - ucontrol->value.enumerated.item[0], 0); -} - -#define STAC9758_OUTPUT_JACK(xname, shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_ac97_stac9758_output_jack_info, \ - .get = snd_ac97_stac9758_output_jack_get, \ - .put = snd_ac97_stac9758_output_jack_put, \ - .private_value = shift } -#define STAC9758_INPUT_JACK(xname, shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_ac97_stac9758_input_jack_info, \ - .get = snd_ac97_stac9758_input_jack_get, \ - .put = snd_ac97_stac9758_input_jack_put, \ - .private_value = shift } -static const struct snd_kcontrol_new snd_ac97_sigmatel_stac9758_controls[] = { - STAC9758_OUTPUT_JACK("Mic1 Jack", 1), - STAC9758_OUTPUT_JACK("LineIn Jack", 4), - STAC9758_OUTPUT_JACK("Front Jack", 7), - STAC9758_OUTPUT_JACK("Rear Jack", 10), - STAC9758_OUTPUT_JACK("Center/LFE Jack", 13), - STAC9758_INPUT_JACK("Mic Input Source", 0), - STAC9758_INPUT_JACK("Line Input Source", 8), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Amp", - .info = snd_ac97_stac9758_phonesel_info, - .get = snd_ac97_stac9758_phonesel_get, - .put = snd_ac97_stac9758_phonesel_put - }, - AC97_SINGLE("Exchange Center/LFE", AC97_SIGMATEL_IOMISC, 4, 1, 0), - AC97_SINGLE("Headphone +3dB Boost", AC97_SIGMATEL_IOMISC, 8, 1, 0) -}; - -static int patch_sigmatel_stac9758_specific(struct snd_ac97 *ac97) -{ - int err; - - err = patch_sigmatel_stac97xx_specific(ac97); - if (err < 0) - return err; - err = patch_build_controls(ac97, snd_ac97_sigmatel_stac9758_controls, - ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls)); - if (err < 0) - return err; - /* DAC-A direct */ - snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback"); - /* DAC-A to Mix = PCM */ - /* DAC-B direct = Surround */ - /* DAC-B to Mix */ - snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback"); - /* DAC-C direct = Center/LFE */ - - return 0; -} - -static const struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = { - .build_3d = patch_sigmatel_stac9700_3d, - .build_specific = patch_sigmatel_stac9758_specific -}; - -static int patch_sigmatel_stac9758(struct snd_ac97 * ac97) -{ - static unsigned short regs[4] = { - AC97_SIGMATEL_OUTSEL, - AC97_SIGMATEL_IOMISC, - AC97_SIGMATEL_INSEL, - AC97_SIGMATEL_VARIOUS - }; - static unsigned short def_regs[4] = { - /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */ - /* IOMISC */ 0x2001, - /* INSEL */ 0x0201, /* LI:LI, MI:M1 */ - /* VARIOUS */ 0x0040 - }; - static unsigned short m675_regs[4] = { - /* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */ - /* IOMISC */ 0x2102, /* HP amp on */ - /* INSEL */ 0x0203, /* LI:LI, MI:FR */ - /* VARIOUS */ 0x0041 /* stereo mic */ - }; - unsigned short *pregs = def_regs; - int i; - - /* Gateway M675 notebook */ - if (ac97->pci && - ac97->subsystem_vendor == 0x107b && - ac97->subsystem_device == 0x0601) - pregs = m675_regs; - - // patch for SigmaTel - ac97->build_ops = &patch_sigmatel_stac9758_ops; - /* FIXME: assume only page 0 for writing cache */ - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); - for (i = 0; i < 4; i++) - snd_ac97_write_cache(ac97, regs[i], pregs[i]); - - ac97->flags |= AC97_STEREO_MUTES; - return 0; -} - -/* - * Cirrus Logic CS42xx codecs - */ -static const struct snd_kcontrol_new snd_ac97_cirrus_controls_spdif[2] = { - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0), - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0) -}; - -static int patch_cirrus_build_spdif(struct snd_ac97 * ac97) -{ - int err; - - /* con mask, pro mask, default */ - if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0) - return err; - /* switch, spsa */ - if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0) - return err; - switch (ac97->id & AC97_ID_CS_MASK) { - case AC97_ID_CS4205: - if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1)) < 0) - return err; - break; - } - /* set default PCM S/PDIF params */ - /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */ - snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20); - return 0; -} - -static const struct snd_ac97_build_ops patch_cirrus_ops = { - .build_spdif = patch_cirrus_build_spdif -}; - -static int patch_cirrus_spdif(struct snd_ac97 * ac97) -{ - /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers. - WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC? *sigh* - - sp/dif EA ID is not set, but sp/dif is always present. - - enable/disable is spdif register bit 15. - - sp/dif control register is 0x68. differs from AC97: - - valid is bit 14 (vs 15) - - no DRS - - only 44.1/48k [00 = 48, 01=44,1] (AC97 is 00=44.1, 10=48) - - sp/dif ssource select is in 0x5e bits 0,1. - */ - - ac97->build_ops = &patch_cirrus_ops; - ac97->flags |= AC97_CS_SPDIF; - ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000; - ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ - snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080); - return 0; -} - -static int patch_cirrus_cs4299(struct snd_ac97 * ac97) -{ - /* force the detection of PC Beep */ - ac97->flags |= AC97_HAS_PC_BEEP; - - return patch_cirrus_spdif(ac97); -} - -/* - * Conexant codecs - */ -static const struct snd_kcontrol_new snd_ac97_conexant_controls_spdif[1] = { - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0), -}; - -static int patch_conexant_build_spdif(struct snd_ac97 * ac97) -{ - int err; - - /* con mask, pro mask, default */ - if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0) - return err; - /* switch */ - if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0) - return err; - /* set default PCM S/PDIF params */ - /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */ - snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC, - snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK)); - return 0; -} - -static const struct snd_ac97_build_ops patch_conexant_ops = { - .build_spdif = patch_conexant_build_spdif -}; - -static int patch_conexant(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_conexant_ops; - ac97->flags |= AC97_CX_SPDIF; - ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ - return 0; -} - -static int patch_cx20551(struct snd_ac97 *ac97) -{ - snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01); - return 0; -} - -/* - * Analog Device AD18xx, AD19xx codecs - */ -#ifdef CONFIG_PM -static void ad18xx_resume(struct snd_ac97 *ac97) -{ - static unsigned short setup_regs[] = { - AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF, - }; - int i, codec; - - for (i = 0; i < (int)ARRAY_SIZE(setup_regs); i++) { - unsigned short reg = setup_regs[i]; - if (test_bit(reg, ac97->reg_accessed)) { - snd_ac97_write(ac97, reg, ac97->regs[reg]); - snd_ac97_read(ac97, reg); - } - } - - if (! (ac97->flags & AC97_AD_MULTI)) - /* normal restore */ - snd_ac97_restore_status(ac97); - else { - /* restore the AD18xx codec configurations */ - for (codec = 0; codec < 3; codec++) { - if (! ac97->spec.ad18xx.id[codec]) - continue; - /* select single codec */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, - ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); - ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]); - } - /* select all codecs */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - - /* restore status */ - for (i = 2; i < 0x7c ; i += 2) { - if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID) - continue; - if (test_bit(i, ac97->reg_accessed)) { - /* handle multi codecs for AD18xx */ - if (i == AC97_PCM) { - for (codec = 0; codec < 3; codec++) { - if (! ac97->spec.ad18xx.id[codec]) - continue; - /* select single codec */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, - ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); - /* update PCM bits */ - ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]); - } - /* select all codecs */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - continue; - } else if (i == AC97_AD_TEST || - i == AC97_AD_CODEC_CFG || - i == AC97_AD_SERIAL_CFG) - continue; /* ignore */ - } - snd_ac97_write(ac97, i, ac97->regs[i]); - snd_ac97_read(ac97, i); - } - } - - snd_ac97_restore_iec958(ac97); -} - -static void ad1888_resume(struct snd_ac97 *ac97) -{ - ad18xx_resume(ac97); - snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080); -} - -#endif - -static const struct snd_ac97_res_table ad1819_restbl[] = { - { AC97_PHONE, 0x9f1f }, - { AC97_MIC, 0x9f1f }, - { AC97_LINE, 0x9f1f }, - { AC97_CD, 0x9f1f }, - { AC97_VIDEO, 0x9f1f }, - { AC97_AUX, 0x9f1f }, - { AC97_PCM, 0x9f1f }, - { } /* terminator */ -}; - -static int patch_ad1819(struct snd_ac97 * ac97) -{ - unsigned short scfg; - - // patch for Analog Devices - scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG); - snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */ - ac97->res_table = ad1819_restbl; - return 0; -} - -static unsigned short patch_ad1881_unchained(struct snd_ac97 * ac97, int idx, unsigned short mask) -{ - unsigned short val; - - // test for unchained codec - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, mask); - snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); /* ID0C, ID1C, SDIE = off */ - val = snd_ac97_read(ac97, AC97_VENDOR_ID2); - if ((val & 0xff40) != 0x5340) - return 0; - ac97->spec.ad18xx.unchained[idx] = mask; - ac97->spec.ad18xx.id[idx] = val; - ac97->spec.ad18xx.codec_cfg[idx] = 0x0000; - return mask; -} - -static int patch_ad1881_chained1(struct snd_ac97 * ac97, int idx, unsigned short codec_bits) -{ - static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 }; - unsigned short val; - - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]); - snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004); // SDIE - val = snd_ac97_read(ac97, AC97_VENDOR_ID2); - if ((val & 0xff40) != 0x5340) - return 0; - if (codec_bits) - snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, codec_bits); - ac97->spec.ad18xx.chained[idx] = cfg_bits[idx]; - ac97->spec.ad18xx.id[idx] = val; - ac97->spec.ad18xx.codec_cfg[idx] = codec_bits ? codec_bits : 0x0004; - return 1; -} - -static void patch_ad1881_chained(struct snd_ac97 * ac97, int unchained_idx, int cidx1, int cidx2) -{ - // already detected? - if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1]) - cidx1 = -1; - if (ac97->spec.ad18xx.unchained[cidx2] || ac97->spec.ad18xx.chained[cidx2]) - cidx2 = -1; - if (cidx1 < 0 && cidx2 < 0) - return; - // test for chained codecs - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, - ac97->spec.ad18xx.unchained[unchained_idx]); - snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C - ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002; - if (cidx1 >= 0) { - if (cidx2 < 0) - patch_ad1881_chained1(ac97, cidx1, 0); - else if (patch_ad1881_chained1(ac97, cidx1, 0x0006)) // SDIE | ID1C - patch_ad1881_chained1(ac97, cidx2, 0); - else if (patch_ad1881_chained1(ac97, cidx2, 0x0006)) // SDIE | ID1C - patch_ad1881_chained1(ac97, cidx1, 0); - } else if (cidx2 >= 0) { - patch_ad1881_chained1(ac97, cidx2, 0); - } -} - -static const struct snd_ac97_build_ops patch_ad1881_build_ops = { -#ifdef CONFIG_PM - .resume = ad18xx_resume -#endif -}; - -static int patch_ad1881(struct snd_ac97 * ac97) -{ - static const char cfg_idxs[3][2] = { - {2, 1}, - {0, 2}, - {0, 1} - }; - - // patch for Analog Devices - unsigned short codecs[3]; - unsigned short val; - int idx, num; - - val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG); - snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val); - codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12)); - codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14)); - codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13)); - - if (! (codecs[0] || codecs[1] || codecs[2])) - goto __end; - - for (idx = 0; idx < 3; idx++) - if (ac97->spec.ad18xx.unchained[idx]) - patch_ad1881_chained(ac97, idx, cfg_idxs[idx][0], cfg_idxs[idx][1]); - - if (ac97->spec.ad18xx.id[1]) { - ac97->flags |= AC97_AD_MULTI; - ac97->scaps |= AC97_SCAP_SURROUND_DAC; - } - if (ac97->spec.ad18xx.id[2]) { - ac97->flags |= AC97_AD_MULTI; - ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC; - } - - __end: - /* select all codecs */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - /* check if only one codec is present */ - for (idx = num = 0; idx < 3; idx++) - if (ac97->spec.ad18xx.id[idx]) - num++; - if (num == 1) { - /* ok, deselect all ID bits */ - snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); - ac97->spec.ad18xx.codec_cfg[0] = - ac97->spec.ad18xx.codec_cfg[1] = - ac97->spec.ad18xx.codec_cfg[2] = 0x0000; - } - /* required for AD1886/AD1885 combination */ - ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID); - if (ac97->spec.ad18xx.id[0]) { - ac97->id &= 0xffff0000; - ac97->id |= ac97->spec.ad18xx.id[0]; - } - ac97->build_ops = &patch_ad1881_build_ops; - return 0; -} - -static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = { - AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0), - /* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */ - AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0), - AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0), - AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1), /* inverted */ - AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */ -}; - -static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0); - -static int patch_ad1885_specific(struct snd_ac97 * ac97) -{ - int err; - - if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0) - return err; - reset_tlv(ac97, "Headphone Playback Volume", - db_scale_6bit_6db_max); - return 0; -} - -static const struct snd_ac97_build_ops patch_ad1885_build_ops = { - .build_specific = &patch_ad1885_specific, -#ifdef CONFIG_PM - .resume = ad18xx_resume -#endif -}; - -static int patch_ad1885(struct snd_ac97 * ac97) -{ - patch_ad1881(ac97); - /* This is required to deal with the Intel D815EEAL2 */ - /* i.e. Line out is actually headphone out from codec */ - - /* set default */ - snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404); - - ac97->build_ops = &patch_ad1885_build_ops; - return 0; -} - -static int patch_ad1886_specific(struct snd_ac97 * ac97) -{ - reset_tlv(ac97, "Headphone Playback Volume", - db_scale_6bit_6db_max); - return 0; -} - -static const struct snd_ac97_build_ops patch_ad1886_build_ops = { - .build_specific = &patch_ad1886_specific, -#ifdef CONFIG_PM - .resume = ad18xx_resume -#endif -}; - -static int patch_ad1886(struct snd_ac97 * ac97) -{ - patch_ad1881(ac97); - /* Presario700 workaround */ - /* for Jack Sense/SPDIF Register misetting causing */ - snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010); - ac97->build_ops = &patch_ad1886_build_ops; - return 0; -} - -/* MISC bits (AD1888/AD1980/AD1985 register 0x76) */ -#define AC97_AD198X_MBC 0x0003 /* mic boost */ -#define AC97_AD198X_MBC_20 0x0000 /* +20dB */ -#define AC97_AD198X_MBC_10 0x0001 /* +10dB */ -#define AC97_AD198X_MBC_30 0x0002 /* +30dB */ -#define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */ -#define AC97_AD198X_VREFH 0x0008 /* 0=2.25V, 1=3.7V */ -#define AC97_AD198X_VREF_0 0x000c /* 0V (AD1985 only) */ -#define AC97_AD198X_VREF_MASK (AC97_AD198X_VREFH | AC97_AD198X_VREFD) -#define AC97_AD198X_VREF_SHIFT 2 -#define AC97_AD198X_SRU 0x0010 /* sample rate unlock */ -#define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */ -#define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */ -#define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */ -#define AC97_AD198X_DMIX0 0x0100 /* downmix mode: */ - /* 0 = 6-to-4, 1 = 6-to-2 downmix */ -#define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */ -#define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */ -#define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */ -#define AC97_AD198X_LODIS 0x1000 /* LINE_OUT disable */ -#define AC97_AD198X_MSPLT 0x2000 /* mute split */ -#define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */ -#define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */ - -/* MISC 1 bits (AD1986 register 0x76) */ -#define AC97_AD1986_MBC 0x0003 /* mic boost */ -#define AC97_AD1986_MBC_20 0x0000 /* +20dB */ -#define AC97_AD1986_MBC_10 0x0001 /* +10dB */ -#define AC97_AD1986_MBC_30 0x0002 /* +30dB */ -#define AC97_AD1986_LISEL0 0x0004 /* LINE_IN select bit 0 */ -#define AC97_AD1986_LISEL1 0x0008 /* LINE_IN select bit 1 */ -#define AC97_AD1986_LISEL_MASK (AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0) -#define AC97_AD1986_LISEL_LI 0x0000 /* LINE_IN pins as LINE_IN source */ -#define AC97_AD1986_LISEL_SURR 0x0004 /* SURROUND pins as LINE_IN source */ -#define AC97_AD1986_LISEL_MIC 0x0008 /* MIC_1/2 pins as LINE_IN source */ -#define AC97_AD1986_SRU 0x0010 /* sample rate unlock */ -#define AC97_AD1986_SOSEL 0x0020 /* SURROUND_OUT amplifiers input sel */ -#define AC97_AD1986_2MIC 0x0040 /* 2-channel mic select */ -#define AC97_AD1986_SPRD 0x0080 /* SPREAD enable */ -#define AC97_AD1986_DMIX0 0x0100 /* downmix mode: */ - /* 0 = 6-to-4, 1 = 6-to-2 downmix */ -#define AC97_AD1986_DMIX1 0x0200 /* downmix mode: 1 = enabled */ -#define AC97_AD1986_CLDIS 0x0800 /* center/lfe disable */ -#define AC97_AD1986_SODIS 0x1000 /* SURROUND_OUT disable */ -#define AC97_AD1986_MSPLT 0x2000 /* mute split (read only 1) */ -#define AC97_AD1986_AC97NC 0x4000 /* AC97 no compatible mode (r/o 1) */ -#define AC97_AD1986_DACZ 0x8000 /* DAC zero-fill mode */ - -/* MISC 2 bits (AD1986 register 0x70) */ -#define AC97_AD_MISC2 0x70 /* Misc Control Bits 2 (AD1986) */ - -#define AC97_AD1986_CVREF0 0x0004 /* C/LFE VREF_OUT 2.25V */ -#define AC97_AD1986_CVREF1 0x0008 /* C/LFE VREF_OUT 0V */ -#define AC97_AD1986_CVREF2 0x0010 /* C/LFE VREF_OUT 3.7V */ -#define AC97_AD1986_CVREF_MASK \ - (AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0) -#define AC97_AD1986_JSMAP 0x0020 /* Jack Sense Mapping 1 = alternate */ -#define AC97_AD1986_MMDIS 0x0080 /* Mono Mute Disable */ -#define AC97_AD1986_MVREF0 0x0400 /* MIC VREF_OUT 2.25V */ -#define AC97_AD1986_MVREF1 0x0800 /* MIC VREF_OUT 0V */ -#define AC97_AD1986_MVREF2 0x1000 /* MIC VREF_OUT 3.7V */ -#define AC97_AD1986_MVREF_MASK \ - (AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0) - -/* MISC 3 bits (AD1986 register 0x7a) */ -#define AC97_AD_MISC3 0x7a /* Misc Control Bits 3 (AD1986) */ - -#define AC97_AD1986_MMIX 0x0004 /* Mic Mix, left/right */ -#define AC97_AD1986_GPO 0x0008 /* General Purpose Out */ -#define AC97_AD1986_LOHPEN 0x0010 /* LINE_OUT headphone drive */ -#define AC97_AD1986_LVREF0 0x0100 /* LINE_OUT VREF_OUT 2.25V */ -#define AC97_AD1986_LVREF1 0x0200 /* LINE_OUT VREF_OUT 0V */ -#define AC97_AD1986_LVREF2 0x0400 /* LINE_OUT VREF_OUT 3.7V */ -#define AC97_AD1986_LVREF_MASK \ - (AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0) -#define AC97_AD1986_JSINVA 0x0800 /* Jack Sense Invert SENSE_A */ -#define AC97_AD1986_LOSEL 0x1000 /* LINE_OUT amplifiers input select */ -#define AC97_AD1986_HPSEL0 0x2000 /* Headphone amplifiers */ - /* input select Surround DACs */ -#define AC97_AD1986_HPSEL1 0x4000 /* Headphone amplifiers input */ - /* select C/LFE DACs */ -#define AC97_AD1986_JSINVB 0x8000 /* Jack Sense Invert SENSE_B */ - -/* Serial Config bits (AD1986 register 0x74) (incomplete) */ -#define AC97_AD1986_OMS0 0x0100 /* Optional Mic Selector bit 0 */ -#define AC97_AD1986_OMS1 0x0200 /* Optional Mic Selector bit 1 */ -#define AC97_AD1986_OMS2 0x0400 /* Optional Mic Selector bit 2 */ -#define AC97_AD1986_OMS_MASK \ - (AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0) -#define AC97_AD1986_OMS_M 0x0000 /* MIC_1/2 pins are MIC sources */ -#define AC97_AD1986_OMS_L 0x0100 /* LINE_IN pins are MIC sources */ -#define AC97_AD1986_OMS_C 0x0200 /* Center/LFE pins are MCI sources */ -#define AC97_AD1986_OMS_MC 0x0400 /* Mix of MIC and C/LFE pins */ - /* are MIC sources */ -#define AC97_AD1986_OMS_ML 0x0500 /* MIX of MIC and LINE_IN pins */ - /* are MIC sources */ -#define AC97_AD1986_OMS_LC 0x0600 /* MIX of LINE_IN and C/LFE pins */ - /* are MIC sources */ -#define AC97_AD1986_OMS_MLC 0x0700 /* MIX of MIC, LINE_IN, C/LFE pins */ - /* are MIC sources */ - - -static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { "AC-Link", "A/D Converter" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_ad198x_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_AD_SERIAL_CFG]; - ucontrol->value.enumerated.item[0] = (val >> 2) & 1; - return 0; -} - -static int snd_ac97_ad198x_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - if (ucontrol->value.enumerated.item[0] > 1) - return -EINVAL; - val = ucontrol->value.enumerated.item[0] << 2; - return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val); -} - -static const struct snd_kcontrol_new snd_ac97_ad198x_spdif_source = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = snd_ac97_ad198x_spdif_source_info, - .get = snd_ac97_ad198x_spdif_source_get, - .put = snd_ac97_ad198x_spdif_source_put, -}; - -static int patch_ad198x_post_spdif(struct snd_ac97 * ac97) -{ - return patch_build_controls(ac97, &snd_ac97_ad198x_spdif_source, 1); -} - -static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = { - AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 11, 1, 0), - AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0), -}; - -/* black list to avoid HP/Line jack-sense controls - * (SS vendor << 16 | device) - */ -static unsigned int ad1981_jacks_blacklist[] = { - 0x10140523, /* Thinkpad R40 */ - 0x10140534, /* Thinkpad X31 */ - 0x10140537, /* Thinkpad T41p */ - 0x1014053e, /* Thinkpad R40e */ - 0x10140554, /* Thinkpad T42p/R50p */ - 0x10140567, /* Thinkpad T43p 2668-G7U */ - 0x10140581, /* Thinkpad X41-2527 */ - 0x10280160, /* Dell Dimension 2400 */ - 0x104380b0, /* Asus A7V8X-MX */ - 0x11790241, /* Toshiba Satellite A-15 S127 */ - 0x1179ff10, /* Toshiba P500 */ - 0x144dc01a, /* Samsung NP-X20C004/SEG */ - 0 /* end */ -}; - -static int check_list(struct snd_ac97 *ac97, const unsigned int *list) -{ - u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device; - for (; *list; list++) - if (*list == subid) - return 1; - return 0; -} - -static int patch_ad1981a_specific(struct snd_ac97 * ac97) -{ - if (check_list(ac97, ad1981_jacks_blacklist)) - return 0; - return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense, - ARRAY_SIZE(snd_ac97_ad1981x_jack_sense)); -} - -static const struct snd_ac97_build_ops patch_ad1981a_build_ops = { - .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1981a_specific, -#ifdef CONFIG_PM - .resume = ad18xx_resume -#endif -}; - -/* white list to enable HP jack-sense bits - * (SS vendor << 16 | device) - */ -static unsigned int ad1981_jacks_whitelist[] = { - 0x0e11005a, /* HP nc4000/4010 */ - 0x103c0890, /* HP nc6000 */ - 0x103c0938, /* HP nc4220 */ - 0x103c099c, /* HP nx6110 */ - 0x103c0944, /* HP nc6220 */ - 0x103c0934, /* HP nc8220 */ - 0x103c006d, /* HP nx9105 */ - 0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */ - 0x17340088, /* FSC Scenic-W */ - 0 /* end */ -}; - -static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97) -{ - if (check_list(ac97, ad1981_jacks_whitelist)) - /* enable headphone jack sense */ - snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11); -} - -static int patch_ad1981a(struct snd_ac97 *ac97) -{ - patch_ad1881(ac97); - ac97->build_ops = &patch_ad1981a_build_ops; - snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT); - ac97->flags |= AC97_STEREO_MUTES; - check_ad1981_hp_jack_sense(ac97); - return 0; -} - -static const struct snd_kcontrol_new snd_ac97_ad198x_2cmic = -AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0); - -static int patch_ad1981b_specific(struct snd_ac97 *ac97) -{ - int err; - - if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0) - return err; - if (check_list(ac97, ad1981_jacks_blacklist)) - return 0; - return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense, - ARRAY_SIZE(snd_ac97_ad1981x_jack_sense)); -} - -static const struct snd_ac97_build_ops patch_ad1981b_build_ops = { - .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1981b_specific, -#ifdef CONFIG_PM - .resume = ad18xx_resume -#endif -}; - -static int patch_ad1981b(struct snd_ac97 *ac97) -{ - patch_ad1881(ac97); - ac97->build_ops = &patch_ad1981b_build_ops; - snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT); - ac97->flags |= AC97_STEREO_MUTES; - check_ad1981_hp_jack_sense(ac97); - return 0; -} - -#define snd_ac97_ad1888_lohpsel_info snd_ctl_boolean_mono_info - -static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_AD_MISC]; - ucontrol->value.integer.value[0] = !(val & AC97_AD198X_LOSEL); - if (ac97->spec.ad18xx.lo_as_master) - ucontrol->value.integer.value[0] = - !ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_ac97_ad1888_lohpsel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = !ucontrol->value.integer.value[0]; - if (ac97->spec.ad18xx.lo_as_master) - val = !val; - val = val ? (AC97_AD198X_LOSEL | AC97_AD198X_HPSEL) : 0; - return snd_ac97_update_bits(ac97, AC97_AD_MISC, - AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val); -} - -static int snd_ac97_ad1888_downmix_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = {"Off", "6 -> 4", "6 -> 2"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_ad1888_downmix_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_AD_MISC]; - if (!(val & AC97_AD198X_DMIX1)) - ucontrol->value.enumerated.item[0] = 0; - else - ucontrol->value.enumerated.item[0] = 1 + ((val >> 8) & 1); - return 0; -} - -static int snd_ac97_ad1888_downmix_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - if (ucontrol->value.enumerated.item[0] == 0) - val = 0; - else - val = AC97_AD198X_DMIX1 | - ((ucontrol->value.enumerated.item[0] - 1) << 8); - return snd_ac97_update_bits(ac97, AC97_AD_MISC, - AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val); -} - -static void ad1888_update_jacks(struct snd_ac97 *ac97) -{ - unsigned short val = 0; - /* clear LODIS if shared jack is to be used for Surround out */ - if (!ac97->spec.ad18xx.lo_as_master && is_shared_linein(ac97)) - val |= (1 << 12); - /* clear CLDIS if shared jack is to be used for C/LFE out */ - if (is_shared_micin(ac97)) - val |= (1 << 11); - /* shared Line-In */ - snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val); -} - -static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Exchange Front/Surround", - .info = snd_ac97_ad1888_lohpsel_info, - .get = snd_ac97_ad1888_lohpsel_get, - .put = snd_ac97_ad1888_lohpsel_put - }, - AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, AC97_AD_VREFD_SHIFT, 1, 1), - AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, - AC97_AD_HPFD_SHIFT, 1, 1), - AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Downmix", - .info = snd_ac97_ad1888_downmix_info, - .get = snd_ac97_ad1888_downmix_get, - .put = snd_ac97_ad1888_downmix_put - }, - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, - - AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0), - AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0), -}; - -static int patch_ad1888_specific(struct snd_ac97 *ac97) -{ - if (!ac97->spec.ad18xx.lo_as_master) { - /* rename 0x04 as "Master" and 0x02 as "Master Surround" */ - snd_ac97_rename_vol_ctl(ac97, "Master Playback", - "Master Surround Playback"); - snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", - "Master Playback"); - } - return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls)); -} - -static const struct snd_ac97_build_ops patch_ad1888_build_ops = { - .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1888_specific, -#ifdef CONFIG_PM - .resume = ad1888_resume, -#endif - .update_jacks = ad1888_update_jacks, -}; - -static int patch_ad1888(struct snd_ac97 * ac97) -{ - unsigned short misc; - - patch_ad1881(ac97); - ac97->build_ops = &patch_ad1888_build_ops; - - /* - * LO can be used as a real line-out on some devices, - * and we need to revert the front/surround mixer switches - */ - if (ac97->subsystem_vendor == 0x1043 && - ac97->subsystem_device == 0x1193) /* ASUS A9T laptop */ - ac97->spec.ad18xx.lo_as_master = 1; - - misc = snd_ac97_read(ac97, AC97_AD_MISC); - /* AD-compatible mode */ - /* Stereo mutes enabled */ - misc |= AC97_AD198X_MSPLT | AC97_AD198X_AC97NC; - if (!ac97->spec.ad18xx.lo_as_master) - /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */ - /* it seems that most vendors connect line-out connector to - * headphone out of AC'97 - */ - misc |= AC97_AD198X_LOSEL | AC97_AD198X_HPSEL; - - snd_ac97_write_cache(ac97, AC97_AD_MISC, misc); - ac97->flags |= AC97_STEREO_MUTES; - return 0; -} - -static int patch_ad1980_specific(struct snd_ac97 *ac97) -{ - int err; - - if ((err = patch_ad1888_specific(ac97)) < 0) - return err; - return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1); -} - -static const struct snd_ac97_build_ops patch_ad1980_build_ops = { - .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1980_specific, -#ifdef CONFIG_PM - .resume = ad18xx_resume, -#endif - .update_jacks = ad1888_update_jacks, -}; - -static int patch_ad1980(struct snd_ac97 * ac97) -{ - patch_ad1888(ac97); - ac97->build_ops = &patch_ad1980_build_ops; - return 0; -} - -static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = {"High-Z", "3.7 V", "2.25 V", "0 V"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - static const int reg2ctrl[4] = {2, 0, 1, 3}; - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK) - >> AC97_AD198X_VREF_SHIFT; - ucontrol->value.enumerated.item[0] = reg2ctrl[val]; - return 0; -} - -static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - static const int ctrl2reg[4] = {1, 2, 0, 3}; - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - if (ucontrol->value.enumerated.item[0] > 3) - return -EINVAL; - val = ctrl2reg[ucontrol->value.enumerated.item[0]] - << AC97_AD198X_VREF_SHIFT; - return snd_ac97_update_bits(ac97, AC97_AD_MISC, - AC97_AD198X_VREF_MASK, val); -} - -static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = { - AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Exchange Front/Surround", - .info = snd_ac97_ad1888_lohpsel_info, - .get = snd_ac97_ad1888_lohpsel_get, - .put = snd_ac97_ad1888_lohpsel_put - }, - AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1), - AC97_SINGLE("Spread Front to Surround and Center/LFE", - AC97_AD_MISC, 7, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Downmix", - .info = snd_ac97_ad1888_downmix_info, - .get = snd_ac97_ad1888_downmix_get, - .put = snd_ac97_ad1888_downmix_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "V_REFOUT", - .info = snd_ac97_ad1985_vrefout_info, - .get = snd_ac97_ad1985_vrefout_get, - .put = snd_ac97_ad1985_vrefout_put - }, - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, - - AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0), - AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0), -}; - -static void ad1985_update_jacks(struct snd_ac97 *ac97) -{ - ad1888_update_jacks(ac97); - /* clear OMS if shared jack is to be used for C/LFE out */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9, - is_shared_micin(ac97) ? 1 << 9 : 0); -} - -static int patch_ad1985_specific(struct snd_ac97 *ac97) -{ - int err; - - /* rename 0x04 as "Master" and 0x02 as "Master Surround" */ - snd_ac97_rename_vol_ctl(ac97, "Master Playback", - "Master Surround Playback"); - snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); - - if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0) - return err; - - return patch_build_controls(ac97, snd_ac97_ad1985_controls, - ARRAY_SIZE(snd_ac97_ad1985_controls)); -} - -static const struct snd_ac97_build_ops patch_ad1985_build_ops = { - .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1985_specific, -#ifdef CONFIG_PM - .resume = ad18xx_resume, -#endif - .update_jacks = ad1985_update_jacks, -}; - -static int patch_ad1985(struct snd_ac97 * ac97) -{ - unsigned short misc; - - patch_ad1881(ac97); - ac97->build_ops = &patch_ad1985_build_ops; - misc = snd_ac97_read(ac97, AC97_AD_MISC); - /* switch front/surround line-out/hp-out */ - /* AD-compatible mode */ - /* Stereo mutes enabled */ - snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | - AC97_AD198X_LOSEL | - AC97_AD198X_HPSEL | - AC97_AD198X_MSPLT | - AC97_AD198X_AC97NC); - ac97->flags |= AC97_STEREO_MUTES; - - /* update current jack configuration */ - ad1985_update_jacks(ac97); - - /* on AD1985 rev. 3, AC'97 revision bits are zero */ - ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23; - return 0; -} - -#define snd_ac97_ad1986_bool_info snd_ctl_boolean_mono_info - -static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_AD_MISC3]; - ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0; - return 0; -} - -static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int ret0; - int ret1; - int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0; - - ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL, - ucontrol->value.integer.value[0] != 0 - ? AC97_AD1986_LOSEL : 0); - if (ret0 < 0) - return ret0; - - /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */ - ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL, - (ucontrol->value.integer.value[0] != 0 - || sprd) - ? AC97_AD1986_SOSEL : 0); - if (ret1 < 0) - return ret1; - - return (ret0 > 0 || ret1 > 0) ? 1 : 0; -} - -static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_AD_MISC]; - ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0; - return 0; -} - -static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - int ret0; - int ret1; - int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0; - - ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD, - ucontrol->value.integer.value[0] != 0 - ? AC97_AD1986_SPRD : 0); - if (ret0 < 0) - return ret0; - - /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */ - ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL, - (ucontrol->value.integer.value[0] != 0 - || sprd) - ? AC97_AD1986_SOSEL : 0); - if (ret1 < 0) - return ret1; - - return (ret0 > 0 || ret1 > 0) ? 1 : 0; -} - -static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein; - return 0; -} - -static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned char swap = ucontrol->value.integer.value[0] != 0; - - if (swap != ac97->spec.ad18xx.swap_mic_linein) { - ac97->spec.ad18xx.swap_mic_linein = swap; - if (ac97->build_ops->update_jacks) - ac97->build_ops->update_jacks(ac97); - return 1; - } - return 0; -} - -static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - /* Use MIC_1/2 V_REFOUT as the "get" value */ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - unsigned short reg = ac97->regs[AC97_AD_MISC2]; - if ((reg & AC97_AD1986_MVREF0) != 0) - val = 2; - else if ((reg & AC97_AD1986_MVREF1) != 0) - val = 3; - else if ((reg & AC97_AD1986_MVREF2) != 0) - val = 1; - else - val = 0; - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short cval; - unsigned short lval; - unsigned short mval; - int cret; - int lret; - int mret; - - switch (ucontrol->value.enumerated.item[0]) - { - case 0: /* High-Z */ - cval = 0; - lval = 0; - mval = 0; - break; - case 1: /* 3.7 V */ - cval = AC97_AD1986_CVREF2; - lval = AC97_AD1986_LVREF2; - mval = AC97_AD1986_MVREF2; - break; - case 2: /* 2.25 V */ - cval = AC97_AD1986_CVREF0; - lval = AC97_AD1986_LVREF0; - mval = AC97_AD1986_MVREF0; - break; - case 3: /* 0 V */ - cval = AC97_AD1986_CVREF1; - lval = AC97_AD1986_LVREF1; - mval = AC97_AD1986_MVREF1; - break; - default: - return -EINVAL; - } - - cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2, - AC97_AD1986_CVREF_MASK, cval); - if (cret < 0) - return cret; - lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3, - AC97_AD1986_LVREF_MASK, lval); - if (lret < 0) - return lret; - mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2, - AC97_AD1986_MVREF_MASK, mval); - if (mret < 0) - return mret; - - return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0; -} - -static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = { - AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Exchange Front/Surround", - .info = snd_ac97_ad1986_bool_info, - .get = snd_ac97_ad1986_lososel_get, - .put = snd_ac97_ad1986_lososel_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Exchange Mic/Line In", - .info = snd_ac97_ad1986_bool_info, - .get = snd_ac97_ad1986_miclisel_get, - .put = snd_ac97_ad1986_miclisel_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Spread Front to Surround and Center/LFE", - .info = snd_ac97_ad1986_bool_info, - .get = snd_ac97_ad1986_spread_get, - .put = snd_ac97_ad1986_spread_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Downmix", - .info = snd_ac97_ad1888_downmix_info, - .get = snd_ac97_ad1888_downmix_get, - .put = snd_ac97_ad1888_downmix_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "V_REFOUT", - .info = snd_ac97_ad1985_vrefout_info, - .get = snd_ac97_ad1986_vrefout_get, - .put = snd_ac97_ad1986_vrefout_put - }, - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, - - AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0), - AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0) -}; - -static void ad1986_update_jacks(struct snd_ac97 *ac97) -{ - unsigned short misc_val = 0; - unsigned short ser_val; - - /* disable SURROUND and CENTER/LFE if not surround mode */ - if (!is_surround_on(ac97)) - misc_val |= AC97_AD1986_SODIS; - if (!is_clfe_on(ac97)) - misc_val |= AC97_AD1986_CLDIS; - - /* select line input (default=LINE_IN, SURROUND or MIC_1/2) */ - if (is_shared_linein(ac97)) - misc_val |= AC97_AD1986_LISEL_SURR; - else if (ac97->spec.ad18xx.swap_mic_linein != 0) - misc_val |= AC97_AD1986_LISEL_MIC; - snd_ac97_update_bits(ac97, AC97_AD_MISC, - AC97_AD1986_SODIS | AC97_AD1986_CLDIS | - AC97_AD1986_LISEL_MASK, - misc_val); - - /* select microphone input (MIC_1/2, Center/LFE or LINE_IN) */ - if (is_shared_micin(ac97)) - ser_val = AC97_AD1986_OMS_C; - else if (ac97->spec.ad18xx.swap_mic_linein != 0) - ser_val = AC97_AD1986_OMS_L; - else - ser_val = AC97_AD1986_OMS_M; - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, - AC97_AD1986_OMS_MASK, - ser_val); -} - -static int patch_ad1986_specific(struct snd_ac97 *ac97) -{ - int err; - - if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0) - return err; - - return patch_build_controls(ac97, snd_ac97_ad1986_controls, - ARRAY_SIZE(snd_ac97_ad1985_controls)); -} - -static const struct snd_ac97_build_ops patch_ad1986_build_ops = { - .build_post_spdif = patch_ad198x_post_spdif, - .build_specific = patch_ad1986_specific, -#ifdef CONFIG_PM - .resume = ad18xx_resume, -#endif - .update_jacks = ad1986_update_jacks, -}; - -static int patch_ad1986(struct snd_ac97 * ac97) -{ - patch_ad1881(ac97); - ac97->build_ops = &patch_ad1986_build_ops; - ac97->flags |= AC97_STEREO_MUTES; - - /* update current jack configuration */ - ad1986_update_jacks(ac97); - - return 0; -} - -/* - * realtek ALC203: use mono-out for pin 37 - */ -static int patch_alc203(struct snd_ac97 *ac97) -{ - snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400); - return 0; -} - -/* - * realtek ALC65x/850 codecs - */ -static void alc650_update_jacks(struct snd_ac97 *ac97) -{ - int shared; - - /* shared Line-In / Surround Out */ - shared = is_shared_surrout(ac97); - snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9, - shared ? (1 << 9) : 0); - /* update shared Mic In / Center/LFE Out */ - shared = is_shared_clfeout(ac97); - /* disable/enable vref */ - snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, - shared ? (1 << 12) : 0); - /* turn on/off center-on-mic */ - snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10, - shared ? (1 << 10) : 0); - /* GPIO0 high for mic */ - snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100, - shared ? 0 : 0x100); -} - -static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = { - AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0), - AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0), - AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0), - AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0), - /* 4: Analog Input To Surround */ - /* 5: Analog Input To Center/LFE */ - /* 6: Independent Master Volume Right */ - /* 7: Independent Master Volume Left */ - /* 8: reserved */ - /* 9: Line-In/Surround share */ - /* 10: Mic/CLFE share */ - /* 11-13: in IEC958 controls */ - AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), -#if 0 /* always set in patch_alc650 */ - AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0), - AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0), - AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1), - AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1), - AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1), - AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1), -#endif - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, -}; - -static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = { - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0), - AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0), - /* disable this controls since it doesn't work as expected */ - /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */ -}; - -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0); - -static int patch_alc650_specific(struct snd_ac97 * ac97) -{ - int err; - - if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0) - return err; - if (ac97->ext_id & AC97_EI_SPDIF) { - if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0) - return err; - } - if (ac97->id != AC97_ID_ALC650F) - reset_tlv(ac97, "Master Playback Volume", - db_scale_5bit_3db_max); - return 0; -} - -static const struct snd_ac97_build_ops patch_alc650_ops = { - .build_specific = patch_alc650_specific, - .update_jacks = alc650_update_jacks -}; - -static int patch_alc650(struct snd_ac97 * ac97) -{ - unsigned short val; - - ac97->build_ops = &patch_alc650_ops; - - /* determine the revision */ - val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f; - if (val < 3) - ac97->id = 0x414c4720; /* Old version */ - else if (val < 0x10) - ac97->id = 0x414c4721; /* D version */ - else if (val < 0x20) - ac97->id = 0x414c4722; /* E version */ - else if (val < 0x30) - ac97->id = 0x414c4723; /* F version */ - - /* revision E or F */ - /* FIXME: what about revision D ? */ - ac97->spec.dev_flags = (ac97->id == 0x414c4722 || - ac97->id == 0x414c4723); - - /* enable AC97_ALC650_GPIO_SETUP, AC97_ALC650_CLOCK for R/W */ - snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS, - snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000); - - /* Enable SPDIF-IN only on Rev.E and above */ - val = snd_ac97_read(ac97, AC97_ALC650_CLOCK); - /* SPDIF IN with pin 47 */ - if (ac97->spec.dev_flags && - /* ASUS A6KM requires EAPD */ - ! (ac97->subsystem_vendor == 0x1043 && - ac97->subsystem_device == 0x1103)) - val |= 0x03; /* enable */ - else - val &= ~0x03; /* disable */ - snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val); - - /* set default: slot 3,4,7,8,6,9 - spdif-in monitor off, analog-spdif off, spdif-in off - center on mic off, surround on line-in off - downmix off, duplicate front off - */ - snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 0); - - /* set GPIO0 for mic bias */ - /* GPIO0 pin output, no interrupt, high */ - snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP, - snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01); - snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS, - (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & ~0x10); - - /* full DAC volume */ - snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808); - snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808); - return 0; -} - -static void alc655_update_jacks(struct snd_ac97 *ac97) -{ - int shared; - - /* shared Line-In / Surround Out */ - shared = is_shared_surrout(ac97); - ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9, - shared ? (1 << 9) : 0, 0); - /* update shared Mic In / Center/LFE Out */ - shared = is_shared_clfeout(ac97); - /* misc control; vrefout disable */ - snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, - shared ? (1 << 12) : 0); - ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10, - shared ? (1 << 10) : 0, 0); -} - -static const struct snd_kcontrol_new snd_ac97_controls_alc655[] = { - AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, -}; - -static int alc655_iec958_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts_655[3] = { "PCM", "Analog In", "IEC958 In" }; - static char *texts_658[4] = { "PCM", "Analog1 In", "Analog2 In", "IEC958 In" }; - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = ac97->spec.dev_flags ? 4 : 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - ac97->spec.dev_flags ? - texts_658[uinfo->value.enumerated.item] : - texts_655[uinfo->value.enumerated.item]); - return 0; -} - -static int alc655_iec958_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_ALC650_MULTICH]; - val = (val >> 12) & 3; - if (ac97->spec.dev_flags && val == 3) - val = 0; - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -static int alc655_iec958_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12, - (unsigned short)ucontrol->value.enumerated.item[0] << 12, - 0); -} - -static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc655[] = { - AC97_PAGE_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0, 0), - /* disable this controls since it doesn't work as expected */ - /* AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), */ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = alc655_iec958_route_info, - .get = alc655_iec958_route_get, - .put = alc655_iec958_route_put, - }, -}; - -static int patch_alc655_specific(struct snd_ac97 * ac97) -{ - int err; - - if ((err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655))) < 0) - return err; - if (ac97->ext_id & AC97_EI_SPDIF) { - if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0) - return err; - } - return 0; -} - -static const struct snd_ac97_build_ops patch_alc655_ops = { - .build_specific = patch_alc655_specific, - .update_jacks = alc655_update_jacks -}; - -static int patch_alc655(struct snd_ac97 * ac97) -{ - unsigned int val; - - if (ac97->id == AC97_ID_ALC658) { - ac97->spec.dev_flags = 1; /* ALC658 */ - if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) { - ac97->id = AC97_ID_ALC658D; - ac97->spec.dev_flags = 2; - } - } - - ac97->build_ops = &patch_alc655_ops; - - /* assume only page 0 for writing cache */ - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); - - /* adjust default values */ - val = snd_ac97_read(ac97, 0x7a); /* misc control */ - if (ac97->spec.dev_flags) /* ALC658 */ - val &= ~(1 << 1); /* Pin 47 is spdif input pin */ - else { /* ALC655 */ - if (ac97->subsystem_vendor == 0x1462 && - (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */ - ac97->subsystem_device == 0x0161 || /* LG K1 Express */ - ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */ - ac97->subsystem_device == 0x0471 || /* MSI L720 laptop */ - ac97->subsystem_device == 0x0061)) /* MSI S250 laptop */ - val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ - else - val |= (1 << 1); /* Pin 47 is spdif input pin */ - /* this seems missing on some hardwares */ - ac97->ext_id |= AC97_EI_SPDIF; - } - val &= ~(1 << 12); /* vref enable */ - snd_ac97_write_cache(ac97, 0x7a, val); - /* set default: spdif-in enabled, - spdif-in monitor off, spdif-in PCM off - center on mic off, surround on line-in off - duplicate front off - */ - snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15); - - /* full DAC volume */ - snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808); - snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808); - - /* update undocumented bit... */ - if (ac97->id == AC97_ID_ALC658D) - snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800); - - return 0; -} - - -#define AC97_ALC850_JACK_SELECT 0x76 -#define AC97_ALC850_MISC1 0x7a -#define AC97_ALC850_MULTICH 0x6a - -static void alc850_update_jacks(struct snd_ac97 *ac97) -{ - int shared; - int aux_is_back_surround; - - /* shared Line-In / Surround Out */ - shared = is_shared_surrout(ac97); - /* SURR 1kOhm (bit4), Amp (bit5) */ - snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), - shared ? (1<<5) : (1<<4)); - /* LINE-IN = 0, SURROUND = 2 */ - snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, - shared ? (2<<12) : (0<<12)); - /* update shared Mic In / Center/LFE Out */ - shared = is_shared_clfeout(ac97); - /* Vref disable (bit12), 1kOhm (bit13) */ - snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), - shared ? (1<<12) : (1<<13)); - /* MIC-IN = 1, CENTER-LFE = 5 */ - snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, - shared ? (5<<4) : (1<<4)); - - aux_is_back_surround = alc850_is_aux_back_surround(ac97); - /* Aux is Back Surround */ - snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10, - aux_is_back_surround ? (1<<10) : (0<<10)); -} - -static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = { - AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), - AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1), - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_8CH_CTL, -}; - -static int patch_alc850_specific(struct snd_ac97 *ac97) -{ - int err; - - if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0) - return err; - if (ac97->ext_id & AC97_EI_SPDIF) { - if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0) - return err; - } - return 0; -} - -static const struct snd_ac97_build_ops patch_alc850_ops = { - .build_specific = patch_alc850_specific, - .update_jacks = alc850_update_jacks -}; - -static int patch_alc850(struct snd_ac97 *ac97) -{ - ac97->build_ops = &patch_alc850_ops; - - ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */ - ac97->flags |= AC97_HAS_8CH; - - /* assume only page 0 for writing cache */ - snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); - - /* adjust default values */ - /* set default: spdif-in enabled, - spdif-in monitor off, spdif-in PCM off - center on mic off, surround on line-in off - duplicate front off - NB default bit 10=0 = Aux is Capture, not Back Surround - */ - snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15); - /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off - * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on - */ - snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)| - (1<<7)|(0<<12)|(1<<13)|(0<<14)); - /* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable, - * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute - */ - snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)| - (1<<11)|(0<<12)|(1<<15)); - - /* full DAC volume */ - snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808); - snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808); - return 0; -} - -static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97) -{ - struct snd_kcontrol *kctl_3d_center = - snd_ac97_find_mixer_ctl(ac97, "3D Control - Center"); - struct snd_kcontrol *kctl_3d_depth = - snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth"); - - /* - * 3D register is different from AC97 standard layout - * (also do some renaming, to resemble Windows driver naming) - */ - if (kctl_3d_center) { - kctl_3d_center->private_value = - AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0); - snd_ac97_rename_vol_ctl(ac97, - "3D Control - Center", "3D Control - Width" - ); - } - if (kctl_3d_depth) - kctl_3d_depth->private_value = - AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0); - - /* Aztech Windows driver calls the - equivalent control "Modem Playback", thus rename it: */ - snd_ac97_rename_vol_ctl(ac97, - "Master Mono Playback", "Modem Playback" - ); - snd_ac97_rename_vol_ctl(ac97, - "Headphone Playback", "FM Synth Playback" - ); - - return 0; -} - -static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = { - .build_specific = patch_aztech_azf3328_specific -}; - -static int patch_aztech_azf3328(struct snd_ac97 *ac97) -{ - ac97->build_ops = &patch_aztech_azf3328_ops; - return 0; -} - -/* - * C-Media CM97xx codecs - */ -static void cm9738_update_jacks(struct snd_ac97 *ac97) -{ - /* shared Line-In / Surround Out */ - snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10, - is_shared_surrout(ac97) ? (1 << 10) : 0); -} - -static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = { - AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0), - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_4CH_CTL, -}; - -static int patch_cm9738_specific(struct snd_ac97 * ac97) -{ - return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls)); -} - -static const struct snd_ac97_build_ops patch_cm9738_ops = { - .build_specific = patch_cm9738_specific, - .update_jacks = cm9738_update_jacks -}; - -static int patch_cm9738(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_cm9738_ops; - /* FIXME: can anyone confirm below? */ - /* CM9738 has no PCM volume although the register reacts */ - ac97->flags |= AC97_HAS_NO_PCM_VOL; - snd_ac97_write_cache(ac97, AC97_PCM, 0x8000); - - return 0; -} - -static int snd_ac97_cmedia_spdif_playback_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "Analog", "Digital" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ac97_cmedia_spdif_playback_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = ac97->regs[AC97_CM9739_SPDIF_CTRL]; - ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01; - return 0; -} - -static int snd_ac97_cmedia_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL, - 0x01 << 1, - (ucontrol->value.enumerated.item[0] & 0x01) << 1); -} - -static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = { - /* BIT 0: SPDI_EN - always true */ - { /* BIT 1: SPDIFS */ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = snd_ac97_cmedia_spdif_playback_source_info, - .get = snd_ac97_cmedia_spdif_playback_source_get, - .put = snd_ac97_cmedia_spdif_playback_source_put, - }, - /* BIT 2: IG_SPIV */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0), - /* BIT 3: SPI2F */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0), - /* BIT 4: SPI2SDI */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0), - /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */ -}; - -static void cm9739_update_jacks(struct snd_ac97 *ac97) -{ - /* shared Line-In / Surround Out */ - snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10, - is_shared_surrout(ac97) ? (1 << 10) : 0); - /* shared Mic In / Center/LFE Out **/ - snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, - is_shared_clfeout(ac97) ? 0x1000 : 0x2000); -} - -static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = { - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, -}; - -static int patch_cm9739_specific(struct snd_ac97 * ac97) -{ - return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls)); -} - -static int patch_cm9739_post_spdif(struct snd_ac97 * ac97) -{ - return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif)); -} - -static const struct snd_ac97_build_ops patch_cm9739_ops = { - .build_specific = patch_cm9739_specific, - .build_post_spdif = patch_cm9739_post_spdif, - .update_jacks = cm9739_update_jacks -}; - -static int patch_cm9739(struct snd_ac97 * ac97) -{ - unsigned short val; - - ac97->build_ops = &patch_cm9739_ops; - - /* CM9739/A has no Master and PCM volume although the register reacts */ - ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL; - snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000); - snd_ac97_write_cache(ac97, AC97_PCM, 0x8000); - - /* check spdif */ - val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); - if (val & AC97_EA_SPCV) { - /* enable spdif in */ - snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL, - snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01); - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ - } else { - ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */ - ac97->rates[AC97_RATES_SPDIF] = 0; - } - - /* set-up multi channel */ - /* bit 14: 0 = SPDIF, 1 = EAPD */ - /* bit 13: enable internal vref output for mic */ - /* bit 12: disable center/lfe (swithable) */ - /* bit 10: disable surround/line (switchable) */ - /* bit 9: mix 2 surround off */ - /* bit 4: undocumented; 0 mutes the CM9739A, which defaults to 1 */ - /* bit 3: undocumented; surround? */ - /* bit 0: dB */ - val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4); - val |= (1 << 3); - val |= (1 << 13); - if (! (ac97->ext_id & AC97_EI_SPDIF)) - val |= (1 << 14); - snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val); - - /* FIXME: set up GPIO */ - snd_ac97_write_cache(ac97, 0x70, 0x0100); - snd_ac97_write_cache(ac97, 0x72, 0x0020); - /* Special exception for ASUS W1000/CMI9739. It does not have an SPDIF in. */ - if (ac97->pci && - ac97->subsystem_vendor == 0x1043 && - ac97->subsystem_device == 0x1843) { - snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL, - snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01); - snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, - snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14)); - } - - return 0; -} - -#define AC97_CM9761_MULTI_CHAN 0x64 -#define AC97_CM9761_FUNC 0x66 -#define AC97_CM9761_SPDIF_CTRL 0x6c - -static void cm9761_update_jacks(struct snd_ac97 *ac97) -{ - /* FIXME: check the bits for each model - * model 83 is confirmed to work - */ - static unsigned short surr_on[3][2] = { - { 0x0008, 0x0000 }, /* 9761-78 & 82 */ - { 0x0000, 0x0008 }, /* 9761-82 rev.B */ - { 0x0000, 0x0008 }, /* 9761-83 */ - }; - static unsigned short clfe_on[3][2] = { - { 0x0000, 0x1000 }, /* 9761-78 & 82 */ - { 0x1000, 0x0000 }, /* 9761-82 rev.B */ - { 0x0000, 0x1000 }, /* 9761-83 */ - }; - static unsigned short surr_shared[3][2] = { - { 0x0000, 0x0400 }, /* 9761-78 & 82 */ - { 0x0000, 0x0400 }, /* 9761-82 rev.B */ - { 0x0000, 0x0400 }, /* 9761-83 */ - }; - static unsigned short clfe_shared[3][2] = { - { 0x2000, 0x0880 }, /* 9761-78 & 82 */ - { 0x0000, 0x2880 }, /* 9761-82 rev.B */ - { 0x2000, 0x0800 }, /* 9761-83 */ - }; - unsigned short val = 0; - - val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)]; - val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)]; - val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)]; - val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)]; - - snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val); -} - -static const struct snd_kcontrol_new snd_ac97_cm9761_controls[] = { - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, -}; - -static int cm9761_spdif_out_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int cm9761_spdif_out_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - if (ac97->regs[AC97_CM9761_FUNC] & 0x1) - ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */ - else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2) - ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */ - else - ucontrol->value.enumerated.item[0] = 0; /* AC-link */ - return 0; -} - -static int cm9761_spdif_out_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.enumerated.item[0] == 2) - return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1); - snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0); - return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2, - ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0); -} - -static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" }; -static const struct ac97_enum cm9761_dac_clock_enum = - AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock); - -static const struct snd_kcontrol_new snd_ac97_cm9761_controls_spdif[] = { - { /* BIT 1: SPDIFS */ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = cm9761_spdif_out_source_info, - .get = cm9761_spdif_out_source_get, - .put = cm9761_spdif_out_source_put, - }, - /* BIT 2: IG_SPIV */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0), - /* BIT 3: SPI2F */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0), - /* BIT 4: SPI2SDI */ - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0), - /* BIT 9-10: DAC_CTL */ - AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum), -}; - -static int patch_cm9761_post_spdif(struct snd_ac97 * ac97) -{ - return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif)); -} - -static int patch_cm9761_specific(struct snd_ac97 * ac97) -{ - return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls)); -} - -static const struct snd_ac97_build_ops patch_cm9761_ops = { - .build_specific = patch_cm9761_specific, - .build_post_spdif = patch_cm9761_post_spdif, - .update_jacks = cm9761_update_jacks -}; - -static int patch_cm9761(struct snd_ac97 *ac97) -{ - unsigned short val; - - /* CM9761 has no PCM volume although the register reacts */ - /* Master volume seems to have _some_ influence on the analog - * input sounds - */ - ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL; - snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808); - snd_ac97_write_cache(ac97, AC97_PCM, 0x8808); - - ac97->spec.dev_flags = 0; /* 1 = model 82 revision B, 2 = model 83 */ - if (ac97->id == AC97_ID_CM9761_82) { - unsigned short tmp; - /* check page 1, reg 0x60 */ - val = snd_ac97_read(ac97, AC97_INT_PAGING); - snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01); - tmp = snd_ac97_read(ac97, 0x60); - ac97->spec.dev_flags = tmp & 1; /* revision B? */ - snd_ac97_write_cache(ac97, AC97_INT_PAGING, val); - } else if (ac97->id == AC97_ID_CM9761_83) - ac97->spec.dev_flags = 2; - - ac97->build_ops = &patch_cm9761_ops; - - /* enable spdif */ - /* force the SPDIF bit in ext_id - codec doesn't set this bit! */ - ac97->ext_id |= AC97_EI_SPDIF; - /* to be sure: we overwrite the ext status bits */ - snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0); - /* Don't set 0x0200 here. This results in the silent analog output */ - snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */ - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ - - /* set-up multi channel */ - /* bit 15: pc master beep off - * bit 14: pin47 = EAPD/SPDIF - * bit 13: vref ctl [= cm9739] - * bit 12: CLFE control (reverted on rev B) - * bit 11: Mic/center share (reverted on rev B) - * bit 10: suddound/line share - * bit 9: Analog-in mix -> surround - * bit 8: Analog-in mix -> CLFE - * bit 7: Mic/LFE share (mic/center/lfe) - * bit 5: vref select (9761A) - * bit 4: front control - * bit 3: surround control (revereted with rev B) - * bit 2: front mic - * bit 1: stereo mic - * bit 0: mic boost level (0=20dB, 1=30dB) - */ - -#if 0 - if (ac97->spec.dev_flags) - val = 0x0214; - else - val = 0x321c; -#endif - val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN); - val |= (1 << 4); /* front on */ - snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val); - - /* FIXME: set up GPIO */ - snd_ac97_write_cache(ac97, 0x70, 0x0100); - snd_ac97_write_cache(ac97, 0x72, 0x0020); - - return 0; -} - -#define AC97_CM9780_SIDE 0x60 -#define AC97_CM9780_JACK 0x62 -#define AC97_CM9780_MIXER 0x64 -#define AC97_CM9780_MULTI_CHAN 0x66 -#define AC97_CM9780_SPDIF 0x6c - -static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" }; -static const struct ac97_enum cm9780_ch_select_enum = - AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select); -static const struct snd_kcontrol_new cm9780_controls[] = { - AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1), - AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0), - AC97_ENUM("Side Playback Route", cm9780_ch_select_enum), -}; - -static int patch_cm9780_specific(struct snd_ac97 *ac97) -{ - return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls)); -} - -static const struct snd_ac97_build_ops patch_cm9780_ops = { - .build_specific = patch_cm9780_specific, - .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */ -}; - -static int patch_cm9780(struct snd_ac97 *ac97) -{ - unsigned short val; - - ac97->build_ops = &patch_cm9780_ops; - - /* enable spdif */ - if (ac97->ext_id & AC97_EI_SPDIF) { - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ - val = snd_ac97_read(ac97, AC97_CM9780_SPDIF); - val |= 0x1; /* SPDI_EN */ - snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val); - } - - return 0; -} - -/* - * VIA VT1616 codec - */ -static const struct snd_kcontrol_new snd_ac97_controls_vt1616[] = { -AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0), -AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0), -AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0), -AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0), -}; - -static const char *slave_vols_vt1616[] = { - "Front Playback Volume", - "Surround Playback Volume", - "Center Playback Volume", - "LFE Playback Volume", - NULL -}; - -static const char *slave_sws_vt1616[] = { - "Front Playback Switch", - "Surround Playback Switch", - "Center Playback Switch", - "LFE Playback Switch", - NULL -}; - -/* find a mixer control element with the given name */ -static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97, - const char *name) -{ - struct snd_ctl_elem_id id; - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, name); - return snd_ctl_find_id(ac97->bus->card, &id); -} - -/* create a virtual master control and add slaves */ -static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, - const unsigned int *tlv, const char **slaves) -{ - struct snd_kcontrol *kctl; - const char **s; - int err; - - kctl = snd_ctl_make_virtual_master(name, tlv); - if (!kctl) - return -ENOMEM; - err = snd_ctl_add(ac97->bus->card, kctl); - if (err < 0) - return err; - - for (s = slaves; *s; s++) { - struct snd_kcontrol *sctl; - - sctl = snd_ac97_find_mixer_ctl(ac97, *s); - if (!sctl) { - snd_printdd("Cannot find slave %s, skipped\n", *s); - continue; - } - err = snd_ctl_add_slave(kctl, sctl); - if (err < 0) - return err; - } - return 0; -} - -static int patch_vt1616_specific(struct snd_ac97 * ac97) -{ - struct snd_kcontrol *kctl; - int err; - - if (snd_ac97_try_bit(ac97, 0x5a, 9)) - if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1)) < 0) - return err; - if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0) - return err; - - /* There is already a misnamed master switch. Rename it. */ - kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume"); - if (!kctl) - return -EINVAL; - - snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback"); - - err = snd_ac97_add_vmaster(ac97, "Master Playback Volume", - kctl->tlv.p, slave_vols_vt1616); - if (err < 0) - return err; - - err = snd_ac97_add_vmaster(ac97, "Master Playback Switch", - NULL, slave_sws_vt1616); - if (err < 0) - return err; - - return 0; -} - -static const struct snd_ac97_build_ops patch_vt1616_ops = { - .build_specific = patch_vt1616_specific -}; - -static int patch_vt1616(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_vt1616_ops; - return 0; -} - -/* - * VT1617A codec - */ - -/* - * unfortunately, the vt1617a stashes the twiddlers required for - * noodling the i/o jacks on 2 different regs. that means that we can't - * use the easy way provided by AC97_ENUM_DOUBLE() we have to write - * are own funcs. - * - * NB: this is absolutely and utterly different from the vt1618. dunno - * about the 1616. - */ - -/* copied from ac97_surround_jack_mode_info() */ -static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - /* ordering in this list reflects vt1617a docs for Reg 20 and - * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51 - * is SM51EN *AND* it's Bit14, not Bit15 so the table is very - * counter-intuitive */ - - static const char* texts[] = { "LineIn Mic1", "LineIn Mic1 Mic3", - "Surr LFE/C Mic3", "LineIn LFE/C Mic3", - "LineIn Mic2", "LineIn Mic2 Mic1", - "Surr LFE Mic1", "Surr LFE Mic1 Mic2"}; - return ac97_enum_text_info(kcontrol, uinfo, texts, 8); -} - -static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ushort usSM51, usMS; - - struct snd_ac97 *pac97; - - pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ - - /* grab our desired bits, then mash them together in a manner - * consistent with Table 6 on page 17 in the 1617a docs */ - - usSM51 = snd_ac97_read(pac97, 0x7a) >> 14; - usMS = snd_ac97_read(pac97, 0x20) >> 8; - - ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS; - - return 0; -} - -static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ushort usSM51, usMS, usReg; - - struct snd_ac97 *pac97; - - pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */ - - usSM51 = ucontrol->value.enumerated.item[0] >> 1; - usMS = ucontrol->value.enumerated.item[0] & 1; - - /* push our values into the register - consider that things will be left - * in a funky state if the write fails */ - - usReg = snd_ac97_read(pac97, 0x7a); - snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14)); - usReg = snd_ac97_read(pac97, 0x20); - snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS << 8)); - - return 0; -} - -static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = { - - AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0), - /* - * These are used to enable/disable surround sound on motherboards - * that have 3 bidirectional analog jacks - */ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Smart 5.1 Select", - .info = snd_ac97_vt1617a_smart51_info, - .get = snd_ac97_vt1617a_smart51_get, - .put = snd_ac97_vt1617a_smart51_put, - }, -}; - -static int patch_vt1617a(struct snd_ac97 * ac97) -{ - int err = 0; - int val; - - /* we choose to not fail out at this point, but we tell the - caller when we return */ - - err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0], - ARRAY_SIZE(snd_ac97_controls_vt1617a)); - - /* bring analog power consumption to normal by turning off the - * headphone amplifier, like WinXP driver for EPIA SP - */ - /* We need to check the bit before writing it. - * On some (many?) hardwares, setting bit actually clears it! - */ - val = snd_ac97_read(ac97, 0x5c); - if (!(val & 0x20)) - snd_ac97_write_cache(ac97, 0x5c, 0x20); - - ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; - ac97->build_ops = &patch_vt1616_ops; - - return err; -} - -/* VIA VT1618 8 CHANNEL AC97 CODEC - * - * VIA implements 'Smart 5.1' completely differently on the 1618 than - * it does on the 1617a. awesome! They seem to have sourced this - * particular revision of the technology from somebody else, it's - * called Universal Audio Jack and it shows up on some other folk's chips - * as well. - * - * ordering in this list reflects vt1618 docs for Reg 60h and - * the block diagram, DACs are as follows: - * - * OUT_O -> Front, - * OUT_1 -> Surround, - * OUT_2 -> C/LFE - * - * Unlike the 1617a, each OUT has a consistent set of mappings - * for all bitpatterns other than 00: - * - * 01 Unmixed Output - * 10 Line In - * 11 Mic In - * - * Special Case of 00: - * - * OUT_0 Mixed Output - * OUT_1 Reserved - * OUT_2 Reserved - * - * I have no idea what the hell Reserved does, but on an MSI - * CN700T, i have to set it to get 5.1 output - YMMV, bad - * shit may happen. - * - * If other chips use Universal Audio Jack, then this code might be applicable - * to them. - */ - -struct vt1618_uaj_item { - unsigned short mask; - unsigned short shift; - const char *items[4]; -}; - -/* This list reflects the vt1618 docs for Vendor Defined Register 0x60. */ - -static struct vt1618_uaj_item vt1618_uaj[3] = { - { - /* speaker jack */ - .mask = 0x03, - .shift = 0, - .items = { - "Speaker Out", "DAC Unmixed Out", "Line In", "Mic In" - } - }, - { - /* line jack */ - .mask = 0x0c, - .shift = 2, - .items = { - "Surround Out", "DAC Unmixed Out", "Line In", "Mic In" - } - }, - { - /* mic jack */ - .mask = 0x30, - .shift = 4, - .items = { - "Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In" - }, - }, -}; - -static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - return ac97_enum_text_info(kcontrol, uinfo, - vt1618_uaj[kcontrol->private_value].items, - 4); -} - -/* All of the vt1618 Universal Audio Jack twiddlers are on - * Vendor Defined Register 0x60, page 0. The bits, and thus - * the mask, are the only thing that changes - */ -static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned short datpag, uaj; - struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol); - - mutex_lock(&pac97->page_mutex); - - datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK; - snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0); - - uaj = snd_ac97_read(pac97, 0x60) & - vt1618_uaj[kcontrol->private_value].mask; - - snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag); - mutex_unlock(&pac97->page_mutex); - - ucontrol->value.enumerated.item[0] = uaj >> - vt1618_uaj[kcontrol->private_value].shift; - - return 0; -} - -static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60, - vt1618_uaj[kcontrol->private_value].mask, - ucontrol->value.enumerated.item[0]<< - vt1618_uaj[kcontrol->private_value].shift, - 0); -} - -/* config aux in jack - not found on 3 jack motherboards or soundcards */ - -static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char *txt_aux[] = {"Aux In", "Back Surr Out"}; - - return ac97_enum_text_info(kcontrol, uinfo, txt_aux, 2); -} - -static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.enumerated.item[0] = - (snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3; - return 0; -} - -static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - /* toggle surround rear dac power */ - - snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008, - ucontrol->value.enumerated.item[0] << 3); - - /* toggle aux in surround rear out jack */ - - return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008, - ucontrol->value.enumerated.item[0] << 3); -} - -static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = { - AC97_SINGLE("Exchange Center/LFE", 0x5a, 8, 1, 0), - AC97_SINGLE("DC Offset", 0x5a, 10, 1, 0), - AC97_SINGLE("Soft Mute", 0x5c, 0, 1, 1), - AC97_SINGLE("Headphone Amp", 0x5c, 5, 1, 1), - AC97_DOUBLE("Back Surr Volume", 0x5e, 8, 0, 31, 1), - AC97_SINGLE("Back Surr Switch", 0x5e, 15, 1, 1), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Speaker Jack Mode", - .info = snd_ac97_vt1618_UAJ_info, - .get = snd_ac97_vt1618_UAJ_get, - .put = snd_ac97_vt1618_UAJ_put, - .private_value = 0 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Jack Mode", - .info = snd_ac97_vt1618_UAJ_info, - .get = snd_ac97_vt1618_UAJ_get, - .put = snd_ac97_vt1618_UAJ_put, - .private_value = 1 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Jack Mode", - .info = snd_ac97_vt1618_UAJ_info, - .get = snd_ac97_vt1618_UAJ_get, - .put = snd_ac97_vt1618_UAJ_put, - .private_value = 2 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Aux Jack Mode", - .info = snd_ac97_vt1618_aux_info, - .get = snd_ac97_vt1618_aux_get, - .put = snd_ac97_vt1618_aux_put, - } -}; - -static int patch_vt1618(struct snd_ac97 *ac97) -{ - return patch_build_controls(ac97, snd_ac97_controls_vt1618, - ARRAY_SIZE(snd_ac97_controls_vt1618)); -} - -/* - */ -static void it2646_update_jacks(struct snd_ac97 *ac97) -{ - /* shared Line-In / Surround Out */ - snd_ac97_update_bits(ac97, 0x76, 1 << 9, - is_shared_surrout(ac97) ? (1<<9) : 0); - /* shared Mic / Center/LFE Out */ - snd_ac97_update_bits(ac97, 0x76, 1 << 10, - is_shared_clfeout(ac97) ? (1<<10) : 0); -} - -static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = { - AC97_SURROUND_JACK_MODE_CTL, - AC97_CHANNEL_MODE_CTL, -}; - -static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = { - AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0x76, 11, 1, 0), - AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0), - AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0), -}; - -static int patch_it2646_specific(struct snd_ac97 * ac97) -{ - int err; - if ((err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646))) < 0) - return err; - if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646))) < 0) - return err; - return 0; -} - -static const struct snd_ac97_build_ops patch_it2646_ops = { - .build_specific = patch_it2646_specific, - .update_jacks = it2646_update_jacks -}; - -static int patch_it2646(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_it2646_ops; - /* full DAC volume */ - snd_ac97_write_cache(ac97, 0x5E, 0x0808); - snd_ac97_write_cache(ac97, 0x7A, 0x0808); - return 0; -} - -/* - * Si3036 codec - */ - -#define AC97_SI3036_CHIP_ID 0x5a -#define AC97_SI3036_LINE_CFG 0x5c - -static const struct snd_kcontrol_new snd_ac97_controls_si3036[] = { -AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1) -}; - -static int patch_si3036_specific(struct snd_ac97 * ac97) -{ - int idx, err; - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++) - if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97))) < 0) - return err; - return 0; -} - -static const struct snd_ac97_build_ops patch_si3036_ops = { - .build_specific = patch_si3036_specific, -}; - -static int mpatch_si3036(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_si3036_ops; - snd_ac97_write_cache(ac97, 0x5c, 0xf210 ); - snd_ac97_write_cache(ac97, 0x68, 0); - return 0; -} - -/* - * LM 4550 Codec - * - * We use a static resolution table since LM4550 codec cannot be - * properly autoprobed to determine the resolution via - * check_volume_resolution(). - */ - -static struct snd_ac97_res_table lm4550_restbl[] = { - { AC97_MASTER, 0x1f1f }, - { AC97_HEADPHONE, 0x1f1f }, - { AC97_MASTER_MONO, 0x001f }, - { AC97_PC_BEEP, 0x001f }, /* LSB is ignored */ - { AC97_PHONE, 0x001f }, - { AC97_MIC, 0x001f }, - { AC97_LINE, 0x1f1f }, - { AC97_CD, 0x1f1f }, - { AC97_VIDEO, 0x1f1f }, - { AC97_AUX, 0x1f1f }, - { AC97_PCM, 0x1f1f }, - { AC97_REC_GAIN, 0x0f0f }, - { } /* terminator */ -}; - -static int patch_lm4550(struct snd_ac97 *ac97) -{ - ac97->res_table = lm4550_restbl; - return 0; -} - -/* - * UCB1400 codec (http://www.semiconductors.philips.com/acrobat_download/datasheets/UCB1400-02.pdf) - */ -static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = { -/* enable/disable headphone driver which allows direct connection to - stereo headphone without the use of external DC blocking - capacitors */ -AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0), -/* Filter used to compensate the DC offset is added in the ADC to remove idle - tones from the audio band. */ -AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0), -/* Control smart-low-power mode feature. Allows automatic power down - of unused blocks in the ADC analog front end and the PLL. */ -AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0), -}; - -static int patch_ucb1400_specific(struct snd_ac97 * ac97) -{ - int idx, err; - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) - if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0) - return err; - return 0; -} - -static const struct snd_ac97_build_ops patch_ucb1400_ops = { - .build_specific = patch_ucb1400_specific, -}; - -static int patch_ucb1400(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_ucb1400_ops; - /* enable headphone driver and smart low power mode by default */ - snd_ac97_write_cache(ac97, 0x6a, 0x0050); - snd_ac97_write_cache(ac97, 0x6c, 0x0030); - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/ac97/ac97_patch.h b/ANDROID_3.4.5/sound/pci/ac97/ac97_patch.h deleted file mode 100644 index 47bf8dfe..00000000 --- a/ANDROID_3.4.5/sound/pci/ac97/ac97_patch.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Universal interface for Audio Codec '97 - * - * For more details look to AC '97 component specification revision 2.2 - * by Intel Corporation (http://developer.intel.com). - * - * - * 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 - * - */ - -#define AC97_SINGLE_VALUE(reg,shift,mask,invert) \ - ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | \ - ((invert) << 24)) -#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) \ - (AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26)) -#define AC97_SINGLE(xname, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_ac97_info_volsw, \ - .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ - .private_value = AC97_SINGLE_VALUE(reg, shift, mask, invert) } -#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_ac97_info_volsw, \ - .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ - .private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) } -#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .info = snd_ac97_info_volsw, \ - .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \ - .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } - -/* enum control */ -struct ac97_enum { - unsigned char reg; - unsigned char shift_l; - unsigned char shift_r; - unsigned short mask; - const char **texts; -}; - -#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ -{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .mask = xmask, .texts = xtexts } -#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \ - AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts) -#define AC97_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_ac97_info_enum_double, \ - .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \ - .private_value = (unsigned long)&xenum } - -/* ac97_codec.c */ -static const struct snd_kcontrol_new snd_ac97_controls_3d[]; -static const struct snd_kcontrol_new snd_ac97_controls_spdif[]; -static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, - struct snd_ac97 * ac97); -static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit); -static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, - const char *suffix); -static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, - const char *dst, const char *suffix); -static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, - const char *s2, const char *suffix); -static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, - const char *dst); -#ifdef CONFIG_PM -static void snd_ac97_restore_status(struct snd_ac97 *ac97); -static void snd_ac97_restore_iec958(struct snd_ac97 *ac97); -#endif -static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); diff --git a/ANDROID_3.4.5/sound/pci/ac97/ac97_pcm.c b/ANDROID_3.4.5/sound/pci/ac97/ac97_pcm.c deleted file mode 100644 index f1488fc1..00000000 --- a/ANDROID_3.4.5/sound/pci/ac97/ac97_pcm.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Universal interface for Audio Codec '97 - * - * For more details look to AC '97 component specification revision 2.2 - * by Intel Corporation (http://developer.intel.com) and to datasheets - * for specific codecs. - * - * - * 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 -#include -#include "ac97_id.h" -#include "ac97_local.h" - -/* - * PCM support - */ - -static unsigned char rate_reg_tables[2][4][9] = { -{ - /* standard rates */ - { - /* 3&4 front, 7&8 rear, 6&9 center/lfe */ - AC97_PCM_FRONT_DAC_RATE, /* slot 3 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 4 */ - 0xff, /* slot 5 */ - AC97_PCM_LFE_DAC_RATE, /* slot 6 */ - AC97_PCM_SURR_DAC_RATE, /* slot 7 */ - AC97_PCM_SURR_DAC_RATE, /* slot 8 */ - AC97_PCM_LFE_DAC_RATE, /* slot 9 */ - 0xff, /* slot 10 */ - 0xff, /* slot 11 */ - }, - { - /* 7&8 front, 6&9 rear, 10&11 center/lfe */ - 0xff, /* slot 3 */ - 0xff, /* slot 4 */ - 0xff, /* slot 5 */ - AC97_PCM_SURR_DAC_RATE, /* slot 6 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 7 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 8 */ - AC97_PCM_SURR_DAC_RATE, /* slot 9 */ - AC97_PCM_LFE_DAC_RATE, /* slot 10 */ - AC97_PCM_LFE_DAC_RATE, /* slot 11 */ - }, - { - /* 6&9 front, 10&11 rear, 3&4 center/lfe */ - AC97_PCM_LFE_DAC_RATE, /* slot 3 */ - AC97_PCM_LFE_DAC_RATE, /* slot 4 */ - 0xff, /* slot 5 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 6 */ - 0xff, /* slot 7 */ - 0xff, /* slot 8 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 9 */ - AC97_PCM_SURR_DAC_RATE, /* slot 10 */ - AC97_PCM_SURR_DAC_RATE, /* slot 11 */ - }, - { - /* 10&11 front, 3&4 rear, 7&8 center/lfe */ - AC97_PCM_SURR_DAC_RATE, /* slot 3 */ - AC97_PCM_SURR_DAC_RATE, /* slot 4 */ - 0xff, /* slot 5 */ - 0xff, /* slot 6 */ - AC97_PCM_LFE_DAC_RATE, /* slot 7 */ - AC97_PCM_LFE_DAC_RATE, /* slot 8 */ - 0xff, /* slot 9 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 10 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 11 */ - }, -}, -{ - /* double rates */ - { - /* 3&4 front, 7&8 front (t+1) */ - AC97_PCM_FRONT_DAC_RATE, /* slot 3 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 4 */ - 0xff, /* slot 5 */ - 0xff, /* slot 6 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 7 */ - AC97_PCM_FRONT_DAC_RATE, /* slot 8 */ - 0xff, /* slot 9 */ - 0xff, /* slot 10 */ - 0xff, /* slot 11 */ - }, - { - /* not specified in the specification */ - 0xff, /* slot 3 */ - 0xff, /* slot 4 */ - 0xff, /* slot 5 */ - 0xff, /* slot 6 */ - 0xff, /* slot 7 */ - 0xff, /* slot 8 */ - 0xff, /* slot 9 */ - 0xff, /* slot 10 */ - 0xff, /* slot 11 */ - }, - { - 0xff, /* slot 3 */ - 0xff, /* slot 4 */ - 0xff, /* slot 5 */ - 0xff, /* slot 6 */ - 0xff, /* slot 7 */ - 0xff, /* slot 8 */ - 0xff, /* slot 9 */ - 0xff, /* slot 10 */ - 0xff, /* slot 11 */ - }, - { - 0xff, /* slot 3 */ - 0xff, /* slot 4 */ - 0xff, /* slot 5 */ - 0xff, /* slot 6 */ - 0xff, /* slot 7 */ - 0xff, /* slot 8 */ - 0xff, /* slot 9 */ - 0xff, /* slot 10 */ - 0xff, /* slot 11 */ - } -}}; - -/* FIXME: more various mappings for ADC? */ -static unsigned char rate_cregs[9] = { - AC97_PCM_LR_ADC_RATE, /* 3 */ - AC97_PCM_LR_ADC_RATE, /* 4 */ - 0xff, /* 5 */ - AC97_PCM_MIC_ADC_RATE, /* 6 */ - 0xff, /* 7 */ - 0xff, /* 8 */ - 0xff, /* 9 */ - 0xff, /* 10 */ - 0xff, /* 11 */ -}; - -static unsigned char get_slot_reg(struct ac97_pcm *pcm, unsigned short cidx, - unsigned short slot, int dbl) -{ - if (slot < 3) - return 0xff; - if (slot > 11) - return 0xff; - if (pcm->spdif) - return AC97_SPDIF; /* pseudo register */ - if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) - return rate_reg_tables[dbl][pcm->r[dbl].rate_table[cidx]][slot - 3]; - else - return rate_cregs[slot - 3]; -} - -static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) -{ - unsigned short old, bits, reg, mask; - unsigned int sbits; - - if (! (ac97->ext_id & AC97_EI_SPDIF)) - return -ENODEV; - - /* TODO: double rate support */ - if (ac97->flags & AC97_CS_SPDIF) { - switch (rate) { - case 48000: bits = 0; break; - case 44100: bits = 1 << AC97_SC_SPSR_SHIFT; break; - default: /* invalid - disable output */ - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); - return -EINVAL; - } - reg = AC97_CSR_SPDIF; - mask = 1 << AC97_SC_SPSR_SHIFT; - } else { - if (ac97->id == AC97_ID_CM9739 && rate != 48000) { - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); - return -EINVAL; - } - switch (rate) { - case 44100: bits = AC97_SC_SPSR_44K; break; - case 48000: bits = AC97_SC_SPSR_48K; break; - case 32000: bits = AC97_SC_SPSR_32K; break; - default: /* invalid - disable output */ - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); - return -EINVAL; - } - reg = AC97_SPDIF; - mask = AC97_SC_SPSR_MASK; - } - - mutex_lock(&ac97->reg_mutex); - old = snd_ac97_read(ac97, reg) & mask; - if (old != bits) { - snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); - snd_ac97_update_bits_nolock(ac97, reg, mask, bits); - /* update the internal spdif bits */ - sbits = ac97->spdif_status; - if (sbits & IEC958_AES0_PROFESSIONAL) { - sbits &= ~IEC958_AES0_PRO_FS; - switch (rate) { - case 44100: sbits |= IEC958_AES0_PRO_FS_44100; break; - case 48000: sbits |= IEC958_AES0_PRO_FS_48000; break; - case 32000: sbits |= IEC958_AES0_PRO_FS_32000; break; - } - } else { - sbits &= ~(IEC958_AES3_CON_FS << 24); - switch (rate) { - case 44100: sbits |= IEC958_AES3_CON_FS_44100<<24; break; - case 48000: sbits |= IEC958_AES3_CON_FS_48000<<24; break; - case 32000: sbits |= IEC958_AES3_CON_FS_32000<<24; break; - } - } - ac97->spdif_status = sbits; - } - snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); - mutex_unlock(&ac97->reg_mutex); - return 0; -} - -/** - * snd_ac97_set_rate - change the rate of the given input/output. - * @ac97: the ac97 instance - * @reg: the register to change - * @rate: the sample rate to set - * - * Changes the rate of the given input/output on the codec. - * If the codec doesn't support VAR, the rate must be 48000 (except - * for SPDIF). - * - * The valid registers are AC97_PMC_MIC_ADC_RATE, - * AC97_PCM_FRONT_DAC_RATE, AC97_PCM_LR_ADC_RATE. - * AC97_PCM_SURR_DAC_RATE and AC97_PCM_LFE_DAC_RATE are accepted - * if the codec supports them. - * AC97_SPDIF is accepted as a pseudo register to modify the SPDIF - * status bits. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate) -{ - int dbl; - unsigned int tmp; - - dbl = rate > 48000; - if (dbl) { - if (!(ac97->flags & AC97_DOUBLE_RATE)) - return -EINVAL; - if (reg != AC97_PCM_FRONT_DAC_RATE) - return -EINVAL; - } - - snd_ac97_update_power(ac97, reg, 1); - switch (reg) { - case AC97_PCM_MIC_ADC_RATE: - if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRM) == 0) /* MIC VRA */ - if (rate != 48000) - return -EINVAL; - break; - case AC97_PCM_FRONT_DAC_RATE: - case AC97_PCM_LR_ADC_RATE: - if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRA) == 0) /* VRA */ - if (rate != 48000 && rate != 96000) - return -EINVAL; - break; - case AC97_PCM_SURR_DAC_RATE: - if (! (ac97->scaps & AC97_SCAP_SURROUND_DAC)) - return -EINVAL; - break; - case AC97_PCM_LFE_DAC_RATE: - if (! (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)) - return -EINVAL; - break; - case AC97_SPDIF: - /* special case */ - return set_spdif_rate(ac97, rate); - default: - return -EINVAL; - } - if (dbl) - rate /= 2; - tmp = (rate * ac97->bus->clock) / 48000; - if (tmp > 65535) - return -EINVAL; - if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) - snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, - AC97_EA_DRA, dbl ? AC97_EA_DRA : 0); - snd_ac97_update(ac97, reg, tmp & 0xffff); - snd_ac97_read(ac97, reg); - if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) { - /* Intel controllers require double rate data to be put in - * slots 7+8 - */ - snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, - AC97_GP_DRSS_MASK, - dbl ? AC97_GP_DRSS_78 : 0); - snd_ac97_read(ac97, AC97_GENERAL_PURPOSE); - } - return 0; -} - -EXPORT_SYMBOL(snd_ac97_set_rate); - -static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots) -{ - if (!ac97_is_audio(ac97)) - return 0; - if (ac97_is_rev22(ac97) || ac97_can_amap(ac97)) { - unsigned short slots = 0; - if (ac97_is_rev22(ac97)) { - /* Note: it's simply emulation of AMAP behaviour */ - u16 es; - es = ac97->regs[AC97_EXTENDED_ID] &= ~AC97_EI_DACS_SLOT_MASK; - switch (ac97->addr) { - case 1: - case 2: es |= (1<addr) { - case 0: - slots |= (1<scaps & AC97_SCAP_SURROUND_DAC) - slots |= (1<scaps & AC97_SCAP_CENTER_LFE_DAC) - slots |= (1<ext_id & AC97_EI_SPDIF) { - if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC)) - *spdif_slots = (1<scaps & AC97_SCAP_CENTER_LFE_DAC)) - *spdif_slots = (1<scaps & AC97_SCAP_SURROUND_DAC) - slots |= (1<ext_id & AC97_EI_SPDIF) { - if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC)) - *spdif_slots = (1<ext_id & AC97_EI_SPDIF) - *spdif_slots = (1<scaps & AC97_SCAP_SURROUND_DAC) - slots |= (1<scaps & AC97_SCAP_CENTER_LFE_DAC) - slots |= (1<ext_id & AC97_EI_SPDIF) { - if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC)) - *spdif_slots = (1<scaps & AC97_SCAP_CENTER_LFE_DAC)) - *spdif_slots = (1<r[dbl].codec[cidx]->rates[idx]; - } - if (!dbl) - rates &= ~(SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000); - return rates; -} - -/** - * snd_ac97_pcm_assign - assign AC97 slots to given PCM streams - * @bus: the ac97 bus instance - * @pcms_count: count of PCMs to be assigned - * @pcms: PCMs to be assigned - * - * It assigns available AC97 slots for given PCMs. If none or only - * some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members - * are reduced and might be zero. - */ -int snd_ac97_pcm_assign(struct snd_ac97_bus *bus, - unsigned short pcms_count, - const struct ac97_pcm *pcms) -{ - int i, j, k; - const struct ac97_pcm *pcm; - struct ac97_pcm *rpcms, *rpcm; - unsigned short avail_slots[2][4]; - unsigned char rate_table[2][4]; - unsigned short tmp, slots; - unsigned short spdif_slots[4]; - unsigned int rates; - struct snd_ac97 *codec; - - rpcms = kcalloc(pcms_count, sizeof(struct ac97_pcm), GFP_KERNEL); - if (rpcms == NULL) - return -ENOMEM; - memset(avail_slots, 0, sizeof(avail_slots)); - memset(rate_table, 0, sizeof(rate_table)); - memset(spdif_slots, 0, sizeof(spdif_slots)); - for (i = 0; i < 4; i++) { - codec = bus->codec[i]; - if (!codec) - continue; - avail_slots[0][i] = get_pslots(codec, &rate_table[0][i], &spdif_slots[i]); - avail_slots[1][i] = get_cslots(codec); - if (!(codec->scaps & AC97_SCAP_INDEP_SDIN)) { - for (j = 0; j < i; j++) { - if (bus->codec[j]) - avail_slots[1][i] &= ~avail_slots[1][j]; - } - } - } - /* first step - exclusive devices */ - for (i = 0; i < pcms_count; i++) { - pcm = &pcms[i]; - rpcm = &rpcms[i]; - /* low-level driver thinks that it's more clever */ - if (pcm->copy_flag) { - *rpcm = *pcm; - continue; - } - rpcm->stream = pcm->stream; - rpcm->exclusive = pcm->exclusive; - rpcm->spdif = pcm->spdif; - rpcm->private_value = pcm->private_value; - rpcm->bus = bus; - rpcm->rates = ~0; - slots = pcm->r[0].slots; - for (j = 0; j < 4 && slots; j++) { - if (!bus->codec[j]) - continue; - rates = ~0; - if (pcm->spdif && pcm->stream == 0) - tmp = spdif_slots[j]; - else - tmp = avail_slots[pcm->stream][j]; - if (pcm->exclusive) { - /* exclusive access */ - tmp &= slots; - for (k = 0; k < i; k++) { - if (rpcm->stream == rpcms[k].stream) - tmp &= ~rpcms[k].r[0].rslots[j]; - } - } else { - /* non-exclusive access */ - tmp &= pcm->r[0].slots; - } - if (tmp) { - rpcm->r[0].rslots[j] = tmp; - rpcm->r[0].codec[j] = bus->codec[j]; - rpcm->r[0].rate_table[j] = rate_table[pcm->stream][j]; - if (bus->no_vra) - rates = SNDRV_PCM_RATE_48000; - else - rates = get_rates(rpcm, j, tmp, 0); - if (pcm->exclusive) - avail_slots[pcm->stream][j] &= ~tmp; - } - slots &= ~tmp; - rpcm->r[0].slots |= tmp; - rpcm->rates &= rates; - } - /* for double rate, we check the first codec only */ - if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK && - bus->codec[0] && (bus->codec[0]->flags & AC97_DOUBLE_RATE) && - rate_table[pcm->stream][0] == 0) { - tmp = (1<r[1].slots) == tmp) { - rpcm->r[1].slots = tmp; - rpcm->r[1].rslots[0] = tmp; - rpcm->r[1].rate_table[0] = 0; - rpcm->r[1].codec[0] = bus->codec[0]; - if (pcm->exclusive) - avail_slots[pcm->stream][0] &= ~tmp; - if (bus->no_vra) - rates = SNDRV_PCM_RATE_96000; - else - rates = get_rates(rpcm, 0, tmp, 1); - rpcm->rates |= rates; - } - } - if (rpcm->rates == ~0) - rpcm->rates = 0; /* not used */ - } - bus->pcms_count = pcms_count; - bus->pcms = rpcms; - return 0; -} - -EXPORT_SYMBOL(snd_ac97_pcm_assign); - -/** - * snd_ac97_pcm_open - opens the given AC97 pcm - * @pcm: the ac97 pcm instance - * @rate: rate in Hz, if codec does not support VRA, this value must be 48000Hz - * @cfg: output stream characteristics - * @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm - * - * It locks the specified slots and sets the given rate to AC97 registers. - */ -int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, - enum ac97_pcm_cfg cfg, unsigned short slots) -{ - struct snd_ac97_bus *bus; - int i, cidx, r, ok_flag; - unsigned int reg_ok[4] = {0,0,0,0}; - unsigned char reg; - int err = 0; - - r = rate > 48000; - bus = pcm->bus; - if (cfg == AC97_PCM_CFG_SPDIF) { - for (cidx = 0; cidx < 4; cidx++) - if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) { - err = set_spdif_rate(bus->codec[cidx], rate); - if (err < 0) - return err; - } - } - spin_lock_irq(&pcm->bus->bus_lock); - for (i = 3; i < 12; i++) { - if (!(slots & (1 << i))) - continue; - ok_flag = 0; - for (cidx = 0; cidx < 4; cidx++) { - if (bus->used_slots[pcm->stream][cidx] & (1 << i)) { - spin_unlock_irq(&pcm->bus->bus_lock); - err = -EBUSY; - goto error; - } - if (pcm->r[r].rslots[cidx] & (1 << i)) { - bus->used_slots[pcm->stream][cidx] |= (1 << i); - ok_flag++; - } - } - if (!ok_flag) { - spin_unlock_irq(&pcm->bus->bus_lock); - snd_printk(KERN_ERR "cannot find configuration for AC97 slot %i\n", i); - err = -EAGAIN; - goto error; - } - } - pcm->cur_dbl = r; - spin_unlock_irq(&pcm->bus->bus_lock); - for (i = 3; i < 12; i++) { - if (!(slots & (1 << i))) - continue; - for (cidx = 0; cidx < 4; cidx++) { - if (pcm->r[r].rslots[cidx] & (1 << i)) { - reg = get_slot_reg(pcm, cidx, i, r); - if (reg == 0xff) { - snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i); - continue; - } - if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE))) - continue; - //printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate); - err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate); - if (err < 0) - snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err); - else - reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE)); - } - } - } - pcm->aslots = slots; - return 0; - - error: - pcm->aslots = slots; - snd_ac97_pcm_close(pcm); - return err; -} - -EXPORT_SYMBOL(snd_ac97_pcm_open); - -/** - * snd_ac97_pcm_close - closes the given AC97 pcm - * @pcm: the ac97 pcm instance - * - * It frees the locked AC97 slots. - */ -int snd_ac97_pcm_close(struct ac97_pcm *pcm) -{ - struct snd_ac97_bus *bus; - unsigned short slots = pcm->aslots; - int i, cidx; - -#ifdef CONFIG_SND_AC97_POWER_SAVE - int r = pcm->cur_dbl; - for (i = 3; i < 12; i++) { - if (!(slots & (1 << i))) - continue; - for (cidx = 0; cidx < 4; cidx++) { - if (pcm->r[r].rslots[cidx] & (1 << i)) { - int reg = get_slot_reg(pcm, cidx, i, r); - snd_ac97_update_power(pcm->r[r].codec[cidx], - reg, 0); - } - } - } -#endif - - bus = pcm->bus; - spin_lock_irq(&pcm->bus->bus_lock); - for (i = 3; i < 12; i++) { - if (!(slots & (1 << i))) - continue; - for (cidx = 0; cidx < 4; cidx++) - bus->used_slots[pcm->stream][cidx] &= ~(1 << i); - } - pcm->aslots = 0; - pcm->cur_dbl = 0; - spin_unlock_irq(&pcm->bus->bus_lock); - return 0; -} - -EXPORT_SYMBOL(snd_ac97_pcm_close); - -static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - if (channels->min > 2) { - static const struct snd_interval single_rates = { - .min = 1, - .max = 48000, - }; - struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - return snd_interval_refine(rate, &single_rates); - } - return 0; -} - -static int double_rate_hw_constraint_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (rate->min > 48000) { - static const struct snd_interval double_rate_channels = { - .min = 2, - .max = 2, - }; - struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - return snd_interval_refine(channels, &double_rate_channels); - } - return 0; -} - -/** - * snd_ac97_pcm_double_rate_rules - set double rate constraints - * @runtime: the runtime of the ac97 front playback pcm - * - * Installs the hardware constraint rules to prevent using double rates and - * more than two channels at the same time. - */ -int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime) -{ - int err; - - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - double_rate_hw_constraint_rate, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - if (err < 0) - return err; - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - double_rate_hw_constraint_channels, NULL, - SNDRV_PCM_HW_PARAM_RATE, -1); - return err; -} - -EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules); diff --git a/ANDROID_3.4.5/sound/pci/ac97/ac97_proc.c b/ANDROID_3.4.5/sound/pci/ac97/ac97_proc.c deleted file mode 100644 index 6320bf08..00000000 --- a/ANDROID_3.4.5/sound/pci/ac97/ac97_proc.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Universal interface for Audio Codec '97 - * - * For more details look to AC '97 component specification revision 2.2 - * by Intel Corporation (http://developer.intel.com). - * - * - * 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 "ac97_local.h" -#include "ac97_id.h" - -/* - * proc interface - */ - -static void snd_ac97_proc_read_functions(struct snd_ac97 *ac97, struct snd_info_buffer *buffer) -{ - int header = 0, function; - unsigned short info, sense_info; - static const char *function_names[12] = { - "Master Out", "AUX Out", "Center/LFE Out", "SPDIF Out", - "Phone In", "Mic 1", "Mic 2", "Line In", "CD In", "Video In", - "Aux In", "Mono Out" - }; - static const char *locations[8] = { - "Rear I/O Panel", "Front Panel", "Motherboard", "Dock/External", - "reserved", "reserved", "reserved", "NC/unused" - }; - - for (function = 0; function < 12; ++function) { - snd_ac97_write(ac97, AC97_FUNC_SELECT, function << 1); - info = snd_ac97_read(ac97, AC97_FUNC_INFO); - if (!(info & 0x0001)) - continue; - if (!header) { - snd_iprintf(buffer, "\n Gain Inverted Buffer delay Location\n"); - header = 1; - } - sense_info = snd_ac97_read(ac97, AC97_SENSE_INFO); - snd_iprintf(buffer, "%-17s: %3d.%d dBV %c %2d/fs %s\n", - function_names[function], - (info & 0x8000 ? -1 : 1) * ((info & 0x7000) >> 12) * 3 / 2, - ((info & 0x0800) >> 11) * 5, - info & 0x0400 ? 'X' : '-', - (info & 0x03e0) >> 5, - locations[sense_info >> 13]); - } -} - -static const char *snd_ac97_stereo_enhancements[] = -{ - /* 0 */ "No 3D Stereo Enhancement", - /* 1 */ "Analog Devices Phat Stereo", - /* 2 */ "Creative Stereo Enhancement", - /* 3 */ "National Semi 3D Stereo Enhancement", - /* 4 */ "YAMAHA Ymersion", - /* 5 */ "BBE 3D Stereo Enhancement", - /* 6 */ "Crystal Semi 3D Stereo Enhancement", - /* 7 */ "Qsound QXpander", - /* 8 */ "Spatializer 3D Stereo Enhancement", - /* 9 */ "SRS 3D Stereo Enhancement", - /* 10 */ "Platform Tech 3D Stereo Enhancement", - /* 11 */ "AKM 3D Audio", - /* 12 */ "Aureal Stereo Enhancement", - /* 13 */ "Aztech 3D Enhancement", - /* 14 */ "Binaura 3D Audio Enhancement", - /* 15 */ "ESS Technology Stereo Enhancement", - /* 16 */ "Harman International VMAx", - /* 17 */ "Nvidea/IC Ensemble/KS Waves 3D Stereo Enhancement", - /* 18 */ "Philips Incredible Sound", - /* 19 */ "Texas Instruments 3D Stereo Enhancement", - /* 20 */ "VLSI Technology 3D Stereo Enhancement", - /* 21 */ "TriTech 3D Stereo Enhancement", - /* 22 */ "Realtek 3D Stereo Enhancement", - /* 23 */ "Samsung 3D Stereo Enhancement", - /* 24 */ "Wolfson Microelectronics 3D Enhancement", - /* 25 */ "Delta Integration 3D Enhancement", - /* 26 */ "SigmaTel 3D Enhancement", - /* 27 */ "IC Ensemble/KS Waves", - /* 28 */ "Rockwell 3D Stereo Enhancement", - /* 29 */ "Reserved 29", - /* 30 */ "Reserved 30", - /* 31 */ "Reserved 31" -}; - -static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffer *buffer, int subidx) -{ - char name[64]; - unsigned short val, tmp, ext, mext; - static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=10/11" }; - static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " Rate=48kHz", " Rate=32kHz" }; - static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" }; - static const char *double_rate_slots[4] = { "10/11", "7/8", "reserved", "reserved" }; - - snd_ac97_get_name(NULL, ac97->id, name, 0); - snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name); - - if ((ac97->scaps & AC97_SCAP_AUDIO) == 0) - goto __modem; - - snd_iprintf(buffer, "PCI Subsys Vendor: 0x%04x\n", - ac97->subsystem_vendor); - snd_iprintf(buffer, "PCI Subsys Device: 0x%04x\n\n", - ac97->subsystem_device); - - snd_iprintf(buffer, "Flags: %x\n", ac97->flags); - - if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) { - val = snd_ac97_read(ac97, AC97_INT_PAGING); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, - AC97_PAGE_MASK, AC97_PAGE_1); - tmp = snd_ac97_read(ac97, AC97_CODEC_CLASS_REV); - snd_iprintf(buffer, "Revision : 0x%02x\n", tmp & 0xff); - snd_iprintf(buffer, "Compat. Class : 0x%02x\n", (tmp >> 8) & 0x1f); - snd_iprintf(buffer, "Subsys. Vendor ID: 0x%04x\n", - snd_ac97_read(ac97, AC97_PCI_SVID)); - snd_iprintf(buffer, "Subsys. ID : 0x%04x\n\n", - snd_ac97_read(ac97, AC97_PCI_SID)); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, - AC97_PAGE_MASK, val & AC97_PAGE_MASK); - } - - // val = snd_ac97_read(ac97, AC97_RESET); - val = ac97->caps; - snd_iprintf(buffer, "Capabilities :%s%s%s%s%s%s\n", - val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" : "", - val & AC97_BC_RESERVED1 ? " -reserved1-" : "", - val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "", - val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "", - val & AC97_BC_HEADPHONE ? " -headphone out-" : "", - val & AC97_BC_LOUDNESS ? " -loudness-" : ""); - tmp = ac97->caps & AC97_BC_DAC_MASK; - snd_iprintf(buffer, "DAC resolution : %s%s%s%s\n", - tmp == AC97_BC_16BIT_DAC ? "16-bit" : "", - tmp == AC97_BC_18BIT_DAC ? "18-bit" : "", - tmp == AC97_BC_20BIT_DAC ? "20-bit" : "", - tmp == AC97_BC_DAC_MASK ? "???" : ""); - tmp = ac97->caps & AC97_BC_ADC_MASK; - snd_iprintf(buffer, "ADC resolution : %s%s%s%s\n", - tmp == AC97_BC_16BIT_ADC ? "16-bit" : "", - tmp == AC97_BC_18BIT_ADC ? "18-bit" : "", - tmp == AC97_BC_20BIT_ADC ? "20-bit" : "", - tmp == AC97_BC_ADC_MASK ? "???" : ""); - snd_iprintf(buffer, "3D enhancement : %s\n", - snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]); - snd_iprintf(buffer, "\nCurrent setup\n"); - val = snd_ac97_read(ac97, AC97_MIC); - snd_iprintf(buffer, "Mic gain : %s [%s]\n", val & 0x0040 ? "+20dB" : "+0dB", ac97->regs[AC97_MIC] & 0x0040 ? "+20dB" : "+0dB"); - val = snd_ac97_read(ac97, AC97_GENERAL_PURPOSE); - snd_iprintf(buffer, "POP path : %s 3D\n" - "Sim. stereo : %s\n" - "3D enhancement : %s\n" - "Loudness : %s\n" - "Mono output : %s\n" - "Mic select : %s\n" - "ADC/DAC loopback : %s\n", - val & 0x8000 ? "post" : "pre", - val & 0x4000 ? "on" : "off", - val & 0x2000 ? "on" : "off", - val & 0x1000 ? "on" : "off", - val & 0x0200 ? "Mic" : "MIX", - val & 0x0100 ? "Mic2" : "Mic1", - val & 0x0080 ? "on" : "off"); - if (ac97->ext_id & AC97_EI_DRA) - snd_iprintf(buffer, "Double rate slots: %s\n", - double_rate_slots[(val >> 10) & 3]); - - ext = snd_ac97_read(ac97, AC97_EXTENDED_ID); - if (ext == 0) - goto __modem; - - snd_iprintf(buffer, "Extended ID : codec=%i rev=%i%s%s%s%s DSA=%i%s%s%s%s\n", - (ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT, - (ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT, - ext & AC97_EI_AMAP ? " AMAP" : "", - ext & AC97_EI_LDAC ? " LDAC" : "", - ext & AC97_EI_SDAC ? " SDAC" : "", - ext & AC97_EI_CDAC ? " CDAC" : "", - (ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT, - ext & AC97_EI_VRM ? " VRM" : "", - ext & AC97_EI_SPDIF ? " SPDIF" : "", - ext & AC97_EI_DRA ? " DRA" : "", - ext & AC97_EI_VRA ? " VRA" : ""); - val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); - snd_iprintf(buffer, "Extended status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - val & AC97_EA_PRL ? " PRL" : "", - val & AC97_EA_PRK ? " PRK" : "", - val & AC97_EA_PRJ ? " PRJ" : "", - val & AC97_EA_PRI ? " PRI" : "", - val & AC97_EA_SPCV ? " SPCV" : "", - val & AC97_EA_MDAC ? " MADC" : "", - val & AC97_EA_LDAC ? " LDAC" : "", - val & AC97_EA_SDAC ? " SDAC" : "", - val & AC97_EA_CDAC ? " CDAC" : "", - ext & AC97_EI_SPDIF ? spdif_slots[(val & AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "", - val & AC97_EA_VRM ? " VRM" : "", - val & AC97_EA_SPDIF ? " SPDIF" : "", - val & AC97_EA_DRA ? " DRA" : "", - val & AC97_EA_VRA ? " VRA" : ""); - if (ext & AC97_EI_VRA) { /* VRA */ - val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE); - snd_iprintf(buffer, "PCM front DAC : %iHz\n", val); - if (ext & AC97_EI_SDAC) { - val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE); - snd_iprintf(buffer, "PCM Surr DAC : %iHz\n", val); - } - if (ext & AC97_EI_LDAC) { - val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE); - snd_iprintf(buffer, "PCM LFE DAC : %iHz\n", val); - } - val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE); - snd_iprintf(buffer, "PCM ADC : %iHz\n", val); - } - if (ext & AC97_EI_VRM) { - val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE); - snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val); - } - if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF) || - (ac97->id == AC97_ID_YMF743)) { - if (ac97->flags & AC97_CS_SPDIF) - val = snd_ac97_read(ac97, AC97_CSR_SPDIF); - else if (ac97->id == AC97_ID_YMF743) { - val = snd_ac97_read(ac97, AC97_YMF7X3_DIT_CTRL); - val = 0x2000 | (val & 0xff00) >> 4 | (val & 0x38) >> 2; - } else - val = snd_ac97_read(ac97, AC97_SPDIF); - - snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n", - val & AC97_SC_PRO ? " PRO" : " Consumer", - val & AC97_SC_NAUDIO ? " Non-audio" : " PCM", - val & AC97_SC_COPY ? "" : " Copyright", - val & AC97_SC_PRE ? " Preemph50/15" : "", - (val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT, - (val & AC97_SC_L) >> 11, - (ac97->flags & AC97_CS_SPDIF) ? - spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT] : - spdif_rates[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT], - (ac97->flags & AC97_CS_SPDIF) ? - (val & AC97_SC_DRS ? " Validity" : "") : - (val & AC97_SC_DRS ? " DRS" : ""), - (ac97->flags & AC97_CS_SPDIF) ? - (val & AC97_SC_V ? " Enabled" : "") : - (val & AC97_SC_V ? " Validity" : "")); - /* ALC650 specific*/ - if ((ac97->id & 0xfffffff0) == 0x414c4720 && - (snd_ac97_read(ac97, AC97_ALC650_CLOCK) & 0x01)) { - val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2); - if (val & AC97_ALC650_CLOCK_LOCK) { - val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS1); - snd_iprintf(buffer, "SPDIF In Status :%s%s%s%s Category=0x%x Generation=%i", - val & AC97_ALC650_PRO ? " PRO" : " Consumer", - val & AC97_ALC650_NAUDIO ? " Non-audio" : " PCM", - val & AC97_ALC650_COPY ? "" : " Copyright", - val & AC97_ALC650_PRE ? " Preemph50/15" : "", - (val & AC97_ALC650_CC_MASK) >> AC97_ALC650_CC_SHIFT, - (val & AC97_ALC650_L) >> 15); - val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2); - snd_iprintf(buffer, "%s Accuracy=%i%s%s\n", - spdif_rates[(val & AC97_ALC650_SPSR_MASK) >> AC97_ALC650_SPSR_SHIFT], - (val & AC97_ALC650_CLOCK_ACCURACY) >> AC97_ALC650_CLOCK_SHIFT, - (val & AC97_ALC650_CLOCK_LOCK ? " Locked" : " Unlocked"), - (val & AC97_ALC650_V ? " Validity?" : "")); - } else { - snd_iprintf(buffer, "SPDIF In Status : Not Locked\n"); - } - } - } - if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) { - val = snd_ac97_read(ac97, AC97_INT_PAGING); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, - AC97_PAGE_MASK, AC97_PAGE_1); - snd_ac97_proc_read_functions(ac97, buffer); - snd_ac97_update_bits(ac97, AC97_INT_PAGING, - AC97_PAGE_MASK, val & AC97_PAGE_MASK); - } - - - __modem: - mext = snd_ac97_read(ac97, AC97_EXTENDED_MID); - if (mext == 0) - return; - - snd_iprintf(buffer, "Extended modem ID: codec=%i%s%s%s%s%s\n", - (mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT, - mext & AC97_MEI_CID2 ? " CID2" : "", - mext & AC97_MEI_CID1 ? " CID1" : "", - mext & AC97_MEI_HANDSET ? " HSET" : "", - mext & AC97_MEI_LINE2 ? " LIN2" : "", - mext & AC97_MEI_LINE1 ? " LIN1" : ""); - val = snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS); - snd_iprintf(buffer, "Modem status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - val & AC97_MEA_GPIO ? " GPIO" : "", - val & AC97_MEA_MREF ? " MREF" : "", - val & AC97_MEA_ADC1 ? " ADC1" : "", - val & AC97_MEA_DAC1 ? " DAC1" : "", - val & AC97_MEA_ADC2 ? " ADC2" : "", - val & AC97_MEA_DAC2 ? " DAC2" : "", - val & AC97_MEA_HADC ? " HADC" : "", - val & AC97_MEA_HDAC ? " HDAC" : "", - val & AC97_MEA_PRA ? " PRA(GPIO)" : "", - val & AC97_MEA_PRB ? " PRB(res)" : "", - val & AC97_MEA_PRC ? " PRC(ADC1)" : "", - val & AC97_MEA_PRD ? " PRD(DAC1)" : "", - val & AC97_MEA_PRE ? " PRE(ADC2)" : "", - val & AC97_MEA_PRF ? " PRF(DAC2)" : "", - val & AC97_MEA_PRG ? " PRG(HADC)" : "", - val & AC97_MEA_PRH ? " PRH(HDAC)" : ""); - if (mext & AC97_MEI_LINE1) { - val = snd_ac97_read(ac97, AC97_LINE1_RATE); - snd_iprintf(buffer, "Line1 rate : %iHz\n", val); - } - if (mext & AC97_MEI_LINE2) { - val = snd_ac97_read(ac97, AC97_LINE2_RATE); - snd_iprintf(buffer, "Line2 rate : %iHz\n", val); - } - if (mext & AC97_MEI_HANDSET) { - val = snd_ac97_read(ac97, AC97_HANDSET_RATE); - snd_iprintf(buffer, "Headset rate : %iHz\n", val); - } -} - -static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_ac97 *ac97 = entry->private_data; - - mutex_lock(&ac97->page_mutex); - if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 - int idx; - for (idx = 0; idx < 3; idx++) - if (ac97->spec.ad18xx.id[idx]) { - /* select single codec */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, - ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]); - snd_ac97_proc_read_main(ac97, buffer, idx); - snd_iprintf(buffer, "\n\n"); - } - /* select all codecs */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - - snd_iprintf(buffer, "\nAD18XX configuration\n"); - snd_iprintf(buffer, "Unchained : 0x%04x,0x%04x,0x%04x\n", - ac97->spec.ad18xx.unchained[0], - ac97->spec.ad18xx.unchained[1], - ac97->spec.ad18xx.unchained[2]); - snd_iprintf(buffer, "Chained : 0x%04x,0x%04x,0x%04x\n", - ac97->spec.ad18xx.chained[0], - ac97->spec.ad18xx.chained[1], - ac97->spec.ad18xx.chained[2]); - } else { - snd_ac97_proc_read_main(ac97, buffer, 0); - } - mutex_unlock(&ac97->page_mutex); -} - -#ifdef CONFIG_SND_DEBUG -/* direct register write for debugging */ -static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_ac97 *ac97 = entry->private_data; - char line[64]; - unsigned int reg, val; - mutex_lock(&ac97->page_mutex); - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x", ®, &val) != 2) - continue; - /* register must be even */ - if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff) - snd_ac97_write_cache(ac97, reg, val); - } - mutex_unlock(&ac97->page_mutex); -} -#endif - -static void snd_ac97_proc_regs_read_main(struct snd_ac97 *ac97, struct snd_info_buffer *buffer, int subidx) -{ - int reg, val; - - for (reg = 0; reg < 0x80; reg += 2) { - val = snd_ac97_read(ac97, reg); - snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val); - } -} - -static void snd_ac97_proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ac97 *ac97 = entry->private_data; - - mutex_lock(&ac97->page_mutex); - if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 - - int idx; - for (idx = 0; idx < 3; idx++) - if (ac97->spec.ad18xx.id[idx]) { - /* select single codec */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, - ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]); - snd_ac97_proc_regs_read_main(ac97, buffer, idx); - } - /* select all codecs */ - snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000); - } else { - snd_ac97_proc_regs_read_main(ac97, buffer, 0); - } - mutex_unlock(&ac97->page_mutex); -} - -void snd_ac97_proc_init(struct snd_ac97 * ac97) -{ - struct snd_info_entry *entry; - char name[32]; - const char *prefix; - - if (ac97->bus->proc == NULL) - return; - prefix = ac97_is_audio(ac97) ? "ac97" : "mc97"; - sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num); - if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { - snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read); - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - ac97->proc = entry; - sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num); - if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { - snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read); -#ifdef CONFIG_SND_DEBUG - entry->mode |= S_IWUSR; - entry->c.text.write = snd_ac97_proc_regs_write; -#endif - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - ac97->proc_regs = entry; -} - -void snd_ac97_proc_done(struct snd_ac97 * ac97) -{ - snd_info_free_entry(ac97->proc_regs); - ac97->proc_regs = NULL; - snd_info_free_entry(ac97->proc); - ac97->proc = NULL; -} - -void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus) -{ - struct snd_info_entry *entry; - char name[32]; - - sprintf(name, "codec97#%d", bus->num); - if ((entry = snd_info_create_card_entry(bus->card, name, bus->card->proc_root)) != NULL) { - entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - bus->proc = entry; -} - -void snd_ac97_bus_proc_done(struct snd_ac97_bus * bus) -{ - snd_info_free_entry(bus->proc); - bus->proc = NULL; -} diff --git a/ANDROID_3.4.5/sound/pci/ad1889.c b/ANDROID_3.4.5/sound/pci/ad1889.c deleted file mode 100644 index 9d91d619..00000000 --- a/ANDROID_3.4.5/sound/pci/ad1889.c +++ /dev/null @@ -1,1078 +0,0 @@ -/* Analog Devices 1889 audio driver - * - * This is a driver for the AD1889 PCI audio chipset found - * on the HP PA-RISC [BCJ]-xxx0 workstations. - * - * Copyright (C) 2004-2005, Kyle McMartin - * Copyright (C) 2005, Thibaut Varene - * Based on the OSS AD1889 driver by Randolph Chung - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * TODO: - * Do we need to take care of CCS register? - * Maybe we could use finer grained locking (separate locks for pb/cap)? - * Wishlist: - * Control Interface (mixer) support - * Better AC97 support (VSR...)? - * PM support - * MIDI support - * Game Port support - * SG DMA support (this will need *a lot* of work) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "ad1889.h" -#include "ac97/ac97_id.h" - -#define AD1889_DRVVER "Version: 1.7" - -MODULE_AUTHOR("Kyle McMartin , Thibaut Varene "); -MODULE_DESCRIPTION("Analog Devices AD1889 ALSA sound driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1889}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the AD1889 soundcard."); - -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the AD1889 soundcard."); - -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable AD1889 soundcard."); - -static char *ac97_quirk[SNDRV_CARDS]; -module_param_array(ac97_quirk, charp, NULL, 0444); -MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); - -#define DEVNAME "ad1889" -#define PFX DEVNAME ": " - -/* let's use the global sound debug interfaces */ -#define ad1889_debug(fmt, arg...) snd_printd(KERN_DEBUG fmt, ## arg) - -/* keep track of some hw registers */ -struct ad1889_register_state { - u16 reg; /* reg setup */ - u32 addr; /* dma base address */ - unsigned long size; /* DMA buffer size */ -}; - -struct snd_ad1889 { - struct snd_card *card; - struct pci_dev *pci; - - int irq; - unsigned long bar; - void __iomem *iobase; - - struct snd_ac97 *ac97; - struct snd_ac97_bus *ac97_bus; - struct snd_pcm *pcm; - struct snd_info_entry *proc; - - struct snd_pcm_substream *psubs; - struct snd_pcm_substream *csubs; - - /* playback register state */ - struct ad1889_register_state wave; - struct ad1889_register_state ramc; - - spinlock_t lock; -}; - -static inline u16 -ad1889_readw(struct snd_ad1889 *chip, unsigned reg) -{ - return readw(chip->iobase + reg); -} - -static inline void -ad1889_writew(struct snd_ad1889 *chip, unsigned reg, u16 val) -{ - writew(val, chip->iobase + reg); -} - -static inline u32 -ad1889_readl(struct snd_ad1889 *chip, unsigned reg) -{ - return readl(chip->iobase + reg); -} - -static inline void -ad1889_writel(struct snd_ad1889 *chip, unsigned reg, u32 val) -{ - writel(val, chip->iobase + reg); -} - -static inline void -ad1889_unmute(struct snd_ad1889 *chip) -{ - u16 st; - st = ad1889_readw(chip, AD_DS_WADA) & - ~(AD_DS_WADA_RWAM | AD_DS_WADA_LWAM); - ad1889_writew(chip, AD_DS_WADA, st); - ad1889_readw(chip, AD_DS_WADA); -} - -static inline void -ad1889_mute(struct snd_ad1889 *chip) -{ - u16 st; - st = ad1889_readw(chip, AD_DS_WADA) | AD_DS_WADA_RWAM | AD_DS_WADA_LWAM; - ad1889_writew(chip, AD_DS_WADA, st); - ad1889_readw(chip, AD_DS_WADA); -} - -static inline void -ad1889_load_adc_buffer_address(struct snd_ad1889 *chip, u32 address) -{ - ad1889_writel(chip, AD_DMA_ADCBA, address); - ad1889_writel(chip, AD_DMA_ADCCA, address); -} - -static inline void -ad1889_load_adc_buffer_count(struct snd_ad1889 *chip, u32 count) -{ - ad1889_writel(chip, AD_DMA_ADCBC, count); - ad1889_writel(chip, AD_DMA_ADCCC, count); -} - -static inline void -ad1889_load_adc_interrupt_count(struct snd_ad1889 *chip, u32 count) -{ - ad1889_writel(chip, AD_DMA_ADCIB, count); - ad1889_writel(chip, AD_DMA_ADCIC, count); -} - -static inline void -ad1889_load_wave_buffer_address(struct snd_ad1889 *chip, u32 address) -{ - ad1889_writel(chip, AD_DMA_WAVBA, address); - ad1889_writel(chip, AD_DMA_WAVCA, address); -} - -static inline void -ad1889_load_wave_buffer_count(struct snd_ad1889 *chip, u32 count) -{ - ad1889_writel(chip, AD_DMA_WAVBC, count); - ad1889_writel(chip, AD_DMA_WAVCC, count); -} - -static inline void -ad1889_load_wave_interrupt_count(struct snd_ad1889 *chip, u32 count) -{ - ad1889_writel(chip, AD_DMA_WAVIB, count); - ad1889_writel(chip, AD_DMA_WAVIC, count); -} - -static void -ad1889_channel_reset(struct snd_ad1889 *chip, unsigned int channel) -{ - u16 reg; - - if (channel & AD_CHAN_WAV) { - /* Disable wave channel */ - reg = ad1889_readw(chip, AD_DS_WSMC) & ~AD_DS_WSMC_WAEN; - ad1889_writew(chip, AD_DS_WSMC, reg); - chip->wave.reg = reg; - - /* disable IRQs */ - reg = ad1889_readw(chip, AD_DMA_WAV); - reg &= AD_DMA_IM_DIS; - reg &= ~AD_DMA_LOOP; - ad1889_writew(chip, AD_DMA_WAV, reg); - - /* clear IRQ and address counters and pointers */ - ad1889_load_wave_buffer_address(chip, 0x0); - ad1889_load_wave_buffer_count(chip, 0x0); - ad1889_load_wave_interrupt_count(chip, 0x0); - - /* flush */ - ad1889_readw(chip, AD_DMA_WAV); - } - - if (channel & AD_CHAN_ADC) { - /* Disable ADC channel */ - reg = ad1889_readw(chip, AD_DS_RAMC) & ~AD_DS_RAMC_ADEN; - ad1889_writew(chip, AD_DS_RAMC, reg); - chip->ramc.reg = reg; - - reg = ad1889_readw(chip, AD_DMA_ADC); - reg &= AD_DMA_IM_DIS; - reg &= ~AD_DMA_LOOP; - ad1889_writew(chip, AD_DMA_ADC, reg); - - ad1889_load_adc_buffer_address(chip, 0x0); - ad1889_load_adc_buffer_count(chip, 0x0); - ad1889_load_adc_interrupt_count(chip, 0x0); - - /* flush */ - ad1889_readw(chip, AD_DMA_ADC); - } -} - -static u16 -snd_ad1889_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_ad1889 *chip = ac97->private_data; - return ad1889_readw(chip, AD_AC97_BASE + reg); -} - -static void -snd_ad1889_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) -{ - struct snd_ad1889 *chip = ac97->private_data; - ad1889_writew(chip, AD_AC97_BASE + reg, val); -} - -static int -snd_ad1889_ac97_ready(struct snd_ad1889 *chip) -{ - int retry = 400; /* average needs 352 msec */ - - while (!(ad1889_readw(chip, AD_AC97_ACIC) & AD_AC97_ACIC_ACRDY) - && --retry) - mdelay(1); - if (!retry) { - snd_printk(KERN_ERR PFX "[%s] Link is not ready.\n", - __func__); - return -EIO; - } - ad1889_debug("[%s] ready after %d ms\n", __func__, 400 - retry); - - return 0; -} - -static int -snd_ad1889_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int -snd_ad1889_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static struct snd_pcm_hardware snd_ad1889_playback_hw = { - .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, /* docs say 7000, but we're lazy */ - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = BUFFER_BYTES_MAX, - .period_bytes_min = PERIOD_BYTES_MIN, - .period_bytes_max = PERIOD_BYTES_MAX, - .periods_min = PERIODS_MIN, - .periods_max = PERIODS_MAX, - /*.fifo_size = 0,*/ -}; - -static struct snd_pcm_hardware snd_ad1889_capture_hw = { - .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, /* docs say we could to VSR, but we're lazy */ - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = BUFFER_BYTES_MAX, - .period_bytes_min = PERIOD_BYTES_MIN, - .period_bytes_max = PERIOD_BYTES_MAX, - .periods_min = PERIODS_MIN, - .periods_max = PERIODS_MAX, - /*.fifo_size = 0,*/ -}; - -static int -snd_ad1889_playback_open(struct snd_pcm_substream *ss) -{ - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - struct snd_pcm_runtime *rt = ss->runtime; - - chip->psubs = ss; - rt->hw = snd_ad1889_playback_hw; - - return 0; -} - -static int -snd_ad1889_capture_open(struct snd_pcm_substream *ss) -{ - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - struct snd_pcm_runtime *rt = ss->runtime; - - chip->csubs = ss; - rt->hw = snd_ad1889_capture_hw; - - return 0; -} - -static int -snd_ad1889_playback_close(struct snd_pcm_substream *ss) -{ - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - chip->psubs = NULL; - return 0; -} - -static int -snd_ad1889_capture_close(struct snd_pcm_substream *ss) -{ - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - chip->csubs = NULL; - return 0; -} - -static int -snd_ad1889_playback_prepare(struct snd_pcm_substream *ss) -{ - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - struct snd_pcm_runtime *rt = ss->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(ss); - unsigned int count = snd_pcm_lib_period_bytes(ss); - u16 reg; - - ad1889_channel_reset(chip, AD_CHAN_WAV); - - reg = ad1889_readw(chip, AD_DS_WSMC); - - /* Mask out 16-bit / Stereo */ - reg &= ~(AD_DS_WSMC_WA16 | AD_DS_WSMC_WAST); - - if (snd_pcm_format_width(rt->format) == 16) - reg |= AD_DS_WSMC_WA16; - - if (rt->channels > 1) - reg |= AD_DS_WSMC_WAST; - - /* let's make sure we don't clobber ourselves */ - spin_lock_irq(&chip->lock); - - chip->wave.size = size; - chip->wave.reg = reg; - chip->wave.addr = rt->dma_addr; - - ad1889_writew(chip, AD_DS_WSMC, chip->wave.reg); - - /* Set sample rates on the codec */ - ad1889_writew(chip, AD_DS_WAS, rt->rate); - - /* Set up DMA */ - ad1889_load_wave_buffer_address(chip, chip->wave.addr); - ad1889_load_wave_buffer_count(chip, size); - ad1889_load_wave_interrupt_count(chip, count); - - /* writes flush */ - ad1889_readw(chip, AD_DS_WSMC); - - spin_unlock_irq(&chip->lock); - - ad1889_debug("prepare playback: addr = 0x%x, count = %u, " - "size = %u, reg = 0x%x, rate = %u\n", chip->wave.addr, - count, size, reg, rt->rate); - return 0; -} - -static int -snd_ad1889_capture_prepare(struct snd_pcm_substream *ss) -{ - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - struct snd_pcm_runtime *rt = ss->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(ss); - unsigned int count = snd_pcm_lib_period_bytes(ss); - u16 reg; - - ad1889_channel_reset(chip, AD_CHAN_ADC); - - reg = ad1889_readw(chip, AD_DS_RAMC); - - /* Mask out 16-bit / Stereo */ - reg &= ~(AD_DS_RAMC_AD16 | AD_DS_RAMC_ADST); - - if (snd_pcm_format_width(rt->format) == 16) - reg |= AD_DS_RAMC_AD16; - - if (rt->channels > 1) - reg |= AD_DS_RAMC_ADST; - - /* let's make sure we don't clobber ourselves */ - spin_lock_irq(&chip->lock); - - chip->ramc.size = size; - chip->ramc.reg = reg; - chip->ramc.addr = rt->dma_addr; - - ad1889_writew(chip, AD_DS_RAMC, chip->ramc.reg); - - /* Set up DMA */ - ad1889_load_adc_buffer_address(chip, chip->ramc.addr); - ad1889_load_adc_buffer_count(chip, size); - ad1889_load_adc_interrupt_count(chip, count); - - /* writes flush */ - ad1889_readw(chip, AD_DS_RAMC); - - spin_unlock_irq(&chip->lock); - - ad1889_debug("prepare capture: addr = 0x%x, count = %u, " - "size = %u, reg = 0x%x, rate = %u\n", chip->ramc.addr, - count, size, reg, rt->rate); - return 0; -} - -/* this is called in atomic context with IRQ disabled. - Must be as fast as possible and not sleep. - DMA should be *triggered* by this call. - The WSMC "WAEN" bit triggers DMA Wave On/Off */ -static int -snd_ad1889_playback_trigger(struct snd_pcm_substream *ss, int cmd) -{ - u16 wsmc; - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - - wsmc = ad1889_readw(chip, AD_DS_WSMC); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* enable DMA loop & interrupts */ - ad1889_writew(chip, AD_DMA_WAV, AD_DMA_LOOP | AD_DMA_IM_CNT); - wsmc |= AD_DS_WSMC_WAEN; - /* 1 to clear CHSS bit */ - ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_WAVS); - ad1889_unmute(chip); - break; - case SNDRV_PCM_TRIGGER_STOP: - ad1889_mute(chip); - wsmc &= ~AD_DS_WSMC_WAEN; - break; - default: - snd_BUG(); - return -EINVAL; - } - - chip->wave.reg = wsmc; - ad1889_writew(chip, AD_DS_WSMC, wsmc); - ad1889_readw(chip, AD_DS_WSMC); /* flush */ - - /* reset the chip when STOP - will disable IRQs */ - if (cmd == SNDRV_PCM_TRIGGER_STOP) - ad1889_channel_reset(chip, AD_CHAN_WAV); - - return 0; -} - -/* this is called in atomic context with IRQ disabled. - Must be as fast as possible and not sleep. - DMA should be *triggered* by this call. - The RAMC "ADEN" bit triggers DMA ADC On/Off */ -static int -snd_ad1889_capture_trigger(struct snd_pcm_substream *ss, int cmd) -{ - u16 ramc; - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - - ramc = ad1889_readw(chip, AD_DS_RAMC); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* enable DMA loop & interrupts */ - ad1889_writew(chip, AD_DMA_ADC, AD_DMA_LOOP | AD_DMA_IM_CNT); - ramc |= AD_DS_RAMC_ADEN; - /* 1 to clear CHSS bit */ - ad1889_writel(chip, AD_DMA_CHSS, AD_DMA_CHSS_ADCS); - break; - case SNDRV_PCM_TRIGGER_STOP: - ramc &= ~AD_DS_RAMC_ADEN; - break; - default: - return -EINVAL; - } - - chip->ramc.reg = ramc; - ad1889_writew(chip, AD_DS_RAMC, ramc); - ad1889_readw(chip, AD_DS_RAMC); /* flush */ - - /* reset the chip when STOP - will disable IRQs */ - if (cmd == SNDRV_PCM_TRIGGER_STOP) - ad1889_channel_reset(chip, AD_CHAN_ADC); - - return 0; -} - -/* Called in atomic context with IRQ disabled */ -static snd_pcm_uframes_t -snd_ad1889_playback_pointer(struct snd_pcm_substream *ss) -{ - size_t ptr = 0; - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - - if (unlikely(!(chip->wave.reg & AD_DS_WSMC_WAEN))) - return 0; - - ptr = ad1889_readl(chip, AD_DMA_WAVCA); - ptr -= chip->wave.addr; - - if (snd_BUG_ON(ptr >= chip->wave.size)) - return 0; - - return bytes_to_frames(ss->runtime, ptr); -} - -/* Called in atomic context with IRQ disabled */ -static snd_pcm_uframes_t -snd_ad1889_capture_pointer(struct snd_pcm_substream *ss) -{ - size_t ptr = 0; - struct snd_ad1889 *chip = snd_pcm_substream_chip(ss); - - if (unlikely(!(chip->ramc.reg & AD_DS_RAMC_ADEN))) - return 0; - - ptr = ad1889_readl(chip, AD_DMA_ADCCA); - ptr -= chip->ramc.addr; - - if (snd_BUG_ON(ptr >= chip->ramc.size)) - return 0; - - return bytes_to_frames(ss->runtime, ptr); -} - -static struct snd_pcm_ops snd_ad1889_playback_ops = { - .open = snd_ad1889_playback_open, - .close = snd_ad1889_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ad1889_hw_params, - .hw_free = snd_ad1889_hw_free, - .prepare = snd_ad1889_playback_prepare, - .trigger = snd_ad1889_playback_trigger, - .pointer = snd_ad1889_playback_pointer, -}; - -static struct snd_pcm_ops snd_ad1889_capture_ops = { - .open = snd_ad1889_capture_open, - .close = snd_ad1889_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ad1889_hw_params, - .hw_free = snd_ad1889_hw_free, - .prepare = snd_ad1889_capture_prepare, - .trigger = snd_ad1889_capture_trigger, - .pointer = snd_ad1889_capture_pointer, -}; - -static irqreturn_t -snd_ad1889_interrupt(int irq, void *dev_id) -{ - unsigned long st; - struct snd_ad1889 *chip = dev_id; - - st = ad1889_readl(chip, AD_DMA_DISR); - - /* clear ISR */ - ad1889_writel(chip, AD_DMA_DISR, st); - - st &= AD_INTR_MASK; - - if (unlikely(!st)) - return IRQ_NONE; - - if (st & (AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI)) - ad1889_debug("Unexpected master or target abort interrupt!\n"); - - if ((st & AD_DMA_DISR_WAVI) && chip->psubs) - snd_pcm_period_elapsed(chip->psubs); - if ((st & AD_DMA_DISR_ADCI) && chip->csubs) - snd_pcm_period_elapsed(chip->csubs); - - return IRQ_HANDLED; -} - -static int __devinit -snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm) -{ - int err; - struct snd_pcm *pcm; - - if (rpcm) - *rpcm = NULL; - - err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_ad1889_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_ad1889_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->shortname); - - chip->pcm = pcm; - chip->psubs = NULL; - chip->csubs = NULL; - - err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - BUFFER_BYTES_MAX / 2, - BUFFER_BYTES_MAX); - - if (err < 0) { - snd_printk(KERN_ERR PFX "buffer allocation error: %d\n", err); - return err; - } - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -static void -snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_ad1889 *chip = entry->private_data; - u16 reg; - int tmp; - - reg = ad1889_readw(chip, AD_DS_WSMC); - snd_iprintf(buffer, "Wave output: %s\n", - (reg & AD_DS_WSMC_WAEN) ? "enabled" : "disabled"); - snd_iprintf(buffer, "Wave Channels: %s\n", - (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono"); - snd_iprintf(buffer, "Wave Quality: %d-bit linear\n", - (reg & AD_DS_WSMC_WA16) ? 16 : 8); - - /* WARQ is at offset 12 */ - tmp = (reg & AD_DS_WSMC_WARQ) ? - (((reg & AD_DS_WSMC_WARQ >> 12) & 0x01) ? 12 : 18) : 4; - tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1; - - snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp, - (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono"); - - - snd_iprintf(buffer, "Synthesis output: %s\n", - reg & AD_DS_WSMC_SYEN ? "enabled" : "disabled"); - - /* SYRQ is at offset 4 */ - tmp = (reg & AD_DS_WSMC_SYRQ) ? - (((reg & AD_DS_WSMC_SYRQ >> 4) & 0x01) ? 12 : 18) : 4; - tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1; - - snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp, - (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono"); - - reg = ad1889_readw(chip, AD_DS_RAMC); - snd_iprintf(buffer, "ADC input: %s\n", - (reg & AD_DS_RAMC_ADEN) ? "enabled" : "disabled"); - snd_iprintf(buffer, "ADC Channels: %s\n", - (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono"); - snd_iprintf(buffer, "ADC Quality: %d-bit linear\n", - (reg & AD_DS_RAMC_AD16) ? 16 : 8); - - /* ACRQ is at offset 4 */ - tmp = (reg & AD_DS_RAMC_ACRQ) ? - (((reg & AD_DS_RAMC_ACRQ >> 4) & 0x01) ? 12 : 18) : 4; - tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1; - - snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp, - (reg & AD_DS_RAMC_ADST) ? "stereo" : "mono"); - - snd_iprintf(buffer, "Resampler input: %s\n", - reg & AD_DS_RAMC_REEN ? "enabled" : "disabled"); - - /* RERQ is at offset 12 */ - tmp = (reg & AD_DS_RAMC_RERQ) ? - (((reg & AD_DS_RAMC_RERQ >> 12) & 0x01) ? 12 : 18) : 4; - tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1; - - snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp, - (reg & AD_DS_WSMC_WAST) ? "stereo" : "mono"); - - - /* doc says LSB represents -1.5dB, but the max value (-94.5dB) - suggests that LSB is -3dB, which is more coherent with the logarithmic - nature of the dB scale */ - reg = ad1889_readw(chip, AD_DS_WADA); - snd_iprintf(buffer, "Left: %s, -%d dB\n", - (reg & AD_DS_WADA_LWAM) ? "mute" : "unmute", - ((reg & AD_DS_WADA_LWAA) >> 8) * 3); - reg = ad1889_readw(chip, AD_DS_WADA); - snd_iprintf(buffer, "Right: %s, -%d dB\n", - (reg & AD_DS_WADA_RWAM) ? "mute" : "unmute", - ((reg & AD_DS_WADA_RWAA) >> 8) * 3); - - reg = ad1889_readw(chip, AD_DS_WAS); - snd_iprintf(buffer, "Wave samplerate: %u Hz\n", reg); - reg = ad1889_readw(chip, AD_DS_RES); - snd_iprintf(buffer, "Resampler samplerate: %u Hz\n", reg); -} - -static void __devinit -snd_ad1889_proc_init(struct snd_ad1889 *chip) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(chip->card, chip->card->driver, &entry)) - snd_info_set_text_ops(entry, chip, snd_ad1889_proc_read); -} - -static struct ac97_quirk ac97_quirks[] = { - { - .subvendor = 0x11d4, /* AD */ - .subdevice = 0x1889, /* AD1889 */ - .codec_id = AC97_ID_AD1819, - .name = "AD1889", - .type = AC97_TUNE_HP_ONLY - }, - { } /* terminator */ -}; - -static void __devinit -snd_ad1889_ac97_xinit(struct snd_ad1889 *chip) -{ - u16 reg; - - reg = ad1889_readw(chip, AD_AC97_ACIC); - reg |= AD_AC97_ACIC_ACRD; /* Reset Disable */ - ad1889_writew(chip, AD_AC97_ACIC, reg); - ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */ - udelay(10); - /* Interface Enable */ - reg |= AD_AC97_ACIC_ACIE; - ad1889_writew(chip, AD_AC97_ACIC, reg); - - snd_ad1889_ac97_ready(chip); - - /* Audio Stream Output | Variable Sample Rate Mode */ - reg = ad1889_readw(chip, AD_AC97_ACIC); - reg |= AD_AC97_ACIC_ASOE | AD_AC97_ACIC_VSRM; - ad1889_writew(chip, AD_AC97_ACIC, reg); - ad1889_readw(chip, AD_AC97_ACIC); /* flush posted write */ - -} - -static void -snd_ad1889_ac97_bus_free(struct snd_ac97_bus *bus) -{ - struct snd_ad1889 *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void -snd_ad1889_ac97_free(struct snd_ac97 *ac97) -{ - struct snd_ad1889 *chip = ac97->private_data; - chip->ac97 = NULL; -} - -static int __devinit -snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override) -{ - int err; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = snd_ad1889_ac97_write, - .read = snd_ad1889_ac97_read, - }; - - /* doing that here, it works. */ - snd_ad1889_ac97_xinit(chip); - - err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus); - if (err < 0) - return err; - - chip->ac97_bus->private_free = snd_ad1889_ac97_bus_free; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_ad1889_ac97_free; - ac97.pci = chip->pci; - - err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97); - if (err < 0) - return err; - - snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override); - - return 0; -} - -static int -snd_ad1889_free(struct snd_ad1889 *chip) -{ - if (chip->irq < 0) - goto skip_hw; - - spin_lock_irq(&chip->lock); - - ad1889_mute(chip); - - /* Turn off interrupt on count and zero DMA registers */ - ad1889_channel_reset(chip, AD_CHAN_WAV | AD_CHAN_ADC); - - /* clear DISR. If we don't, we'd better jump off the Eiffel Tower */ - ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PTAI | AD_DMA_DISR_PMAI); - ad1889_readl(chip, AD_DMA_DISR); /* flush, dammit! */ - - spin_unlock_irq(&chip->lock); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - -skip_hw: - if (chip->iobase) - iounmap(chip->iobase); - - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - - kfree(chip); - return 0; -} - -static int -snd_ad1889_dev_free(struct snd_device *device) -{ - struct snd_ad1889 *chip = device->device_data; - return snd_ad1889_free(chip); -} - -static int __devinit -snd_ad1889_init(struct snd_ad1889 *chip) -{ - ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */ - ad1889_readw(chip, AD_DS_CCS); /* flush posted write */ - - mdelay(10); - - /* enable Master and Target abort interrupts */ - ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE); - - return 0; -} - -static int __devinit -snd_ad1889_create(struct snd_card *card, - struct pci_dev *pci, - struct snd_ad1889 **rchip) -{ - int err; - - struct snd_ad1889 *chip; - static struct snd_device_ops ops = { - .dev_free = snd_ad1889_dev_free, - }; - - *rchip = NULL; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - /* check PCI availability (32bit DMA) */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - printk(KERN_ERR PFX "error setting 32-bit DMA mask.\n"); - pci_disable_device(pci); - return -ENXIO; - } - - /* allocate chip specific data with zero-filled memory */ - if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - card->private_data = chip; - chip->pci = pci; - chip->irq = -1; - - /* (1) PCI resource allocation */ - if ((err = pci_request_regions(pci, card->driver)) < 0) - goto free_and_ret; - - chip->bar = pci_resource_start(pci, 0); - chip->iobase = pci_ioremap_bar(pci, 0); - if (chip->iobase == NULL) { - printk(KERN_ERR PFX "unable to reserve region.\n"); - err = -EBUSY; - goto free_and_ret; - } - - pci_set_master(pci); - - spin_lock_init(&chip->lock); /* only now can we call ad1889_free */ - - if (request_irq(pci->irq, snd_ad1889_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq); - snd_ad1889_free(chip); - return -EBUSY; - } - - chip->irq = pci->irq; - synchronize_irq(chip->irq); - - /* (2) initialization of the chip hardware */ - if ((err = snd_ad1889_init(chip)) < 0) { - snd_ad1889_free(chip); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_ad1889_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - - return 0; - -free_and_ret: - kfree(chip); - pci_disable_device(pci); - - return err; -} - -static int __devinit -snd_ad1889_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - int err; - static int devno; - struct snd_card *card; - struct snd_ad1889 *chip; - - /* (1) */ - if (devno >= SNDRV_CARDS) - return -ENODEV; - if (!enable[devno]) { - devno++; - return -ENOENT; - } - - /* (2) */ - err = snd_card_create(index[devno], id[devno], THIS_MODULE, 0, &card); - /* XXX REVISIT: we can probably allocate chip in this call */ - if (err < 0) - return err; - - strcpy(card->driver, "AD1889"); - strcpy(card->shortname, "Analog Devices AD1889"); - - /* (3) */ - err = snd_ad1889_create(card, pci, &chip); - if (err < 0) - goto free_and_ret; - - /* (4) */ - sprintf(card->longname, "%s at 0x%lx irq %i", - card->shortname, chip->bar, chip->irq); - - /* (5) */ - /* register AC97 mixer */ - err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]); - if (err < 0) - goto free_and_ret; - - err = snd_ad1889_pcm_init(chip, 0, NULL); - if (err < 0) - goto free_and_ret; - - /* register proc interface */ - snd_ad1889_proc_init(chip); - - /* (6) */ - err = snd_card_register(card); - if (err < 0) - goto free_and_ret; - - /* (7) */ - pci_set_drvdata(pci, card); - - devno++; - return 0; - -free_and_ret: - snd_card_free(card); - return err; -} - -static void __devexit -snd_ad1889_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static DEFINE_PCI_DEVICE_TABLE(snd_ad1889_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) }, - { 0, }, -}; -MODULE_DEVICE_TABLE(pci, snd_ad1889_ids); - -static struct pci_driver ad1889_pci_driver = { - .name = KBUILD_MODNAME, - .id_table = snd_ad1889_ids, - .probe = snd_ad1889_probe, - .remove = __devexit_p(snd_ad1889_remove), -}; - -static int __init -alsa_ad1889_init(void) -{ - return pci_register_driver(&ad1889_pci_driver); -} - -static void __exit -alsa_ad1889_fini(void) -{ - pci_unregister_driver(&ad1889_pci_driver); -} - -module_init(alsa_ad1889_init); -module_exit(alsa_ad1889_fini); diff --git a/ANDROID_3.4.5/sound/pci/ad1889.h b/ANDROID_3.4.5/sound/pci/ad1889.h deleted file mode 100644 index 5e6dad53..00000000 --- a/ANDROID_3.4.5/sound/pci/ad1889.h +++ /dev/null @@ -1,189 +0,0 @@ -/* Analog Devices 1889 audio driver - * Copyright (C) 2004, Kyle McMartin - */ - -#ifndef __AD1889_H__ -#define __AD1889_H__ - -#define AD_DS_WSMC 0x00 /* wave/synthesis channel mixer control */ -#define AD_DS_WSMC_SYEN 0x0004 /* synthesis channel enable */ -#define AD_DS_WSMC_SYRQ 0x0030 /* synth. fifo request point */ -#define AD_DS_WSMC_WA16 0x0100 /* wave channel 16bit select */ -#define AD_DS_WSMC_WAST 0x0200 /* wave channel stereo select */ -#define AD_DS_WSMC_WAEN 0x0400 /* wave channel enable */ -#define AD_DS_WSMC_WARQ 0x3000 /* wave fifo request point */ - -#define AD_DS_RAMC 0x02 /* resampler/ADC channel mixer control */ -#define AD_DS_RAMC_AD16 0x0001 /* ADC channel 16bit select */ -#define AD_DS_RAMC_ADST 0x0002 /* ADC channel stereo select */ -#define AD_DS_RAMC_ADEN 0x0004 /* ADC channel enable */ -#define AD_DS_RAMC_ACRQ 0x0030 /* ADC fifo request point */ -#define AD_DS_RAMC_REEN 0x0400 /* resampler channel enable */ -#define AD_DS_RAMC_RERQ 0x3000 /* res. fifo request point */ - -#define AD_DS_WADA 0x04 /* wave channel mix attenuation */ -#define AD_DS_WADA_RWAM 0x0080 /* right wave mute */ -#define AD_DS_WADA_RWAA 0x001f /* right wave attenuation */ -#define AD_DS_WADA_LWAM 0x8000 /* left wave mute */ -#define AD_DS_WADA_LWAA 0x3e00 /* left wave attenuation */ - -#define AD_DS_SYDA 0x06 /* synthesis channel mix attenuation */ -#define AD_DS_SYDA_RSYM 0x0080 /* right synthesis mute */ -#define AD_DS_SYDA_RSYA 0x001f /* right synthesis attenuation */ -#define AD_DS_SYDA_LSYM 0x8000 /* left synthesis mute */ -#define AD_DS_SYDA_LSYA 0x3e00 /* left synthesis attenuation */ - -#define AD_DS_WAS 0x08 /* wave channel sample rate */ -#define AD_DS_WAS_WAS 0xffff /* sample rate mask */ - -#define AD_DS_RES 0x0a /* resampler channel sample rate */ -#define AD_DS_RES_RES 0xffff /* sample rate mask */ - -#define AD_DS_CCS 0x0c /* chip control/status */ -#define AD_DS_CCS_ADO 0x0001 /* ADC channel overflow */ -#define AD_DS_CCS_REO 0x0002 /* resampler channel overflow */ -#define AD_DS_CCS_SYU 0x0004 /* synthesis channel underflow */ -#define AD_DS_CCS_WAU 0x0008 /* wave channel underflow */ -/* bits 4 -> 7, 9, 11 -> 14 reserved */ -#define AD_DS_CCS_XTD 0x0100 /* xtd delay control (4096 clock cycles) */ -#define AD_DS_CCS_PDALL 0x0400 /* power */ -#define AD_DS_CCS_CLKEN 0x8000 /* clock */ - -#define AD_DMA_RESBA 0x40 /* RES base address */ -#define AD_DMA_RESCA 0x44 /* RES current address */ -#define AD_DMA_RESBC 0x48 /* RES base count */ -#define AD_DMA_RESCC 0x4c /* RES current count */ - -#define AD_DMA_ADCBA 0x50 /* ADC base address */ -#define AD_DMA_ADCCA 0x54 /* ADC current address */ -#define AD_DMA_ADCBC 0x58 /* ADC base count */ -#define AD_DMA_ADCCC 0x5c /* ADC current count */ - -#define AD_DMA_SYNBA 0x60 /* synth base address */ -#define AD_DMA_SYNCA 0x64 /* synth current address */ -#define AD_DMA_SYNBC 0x68 /* synth base count */ -#define AD_DMA_SYNCC 0x6c /* synth current count */ - -#define AD_DMA_WAVBA 0x70 /* wave base address */ -#define AD_DMA_WAVCA 0x74 /* wave current address */ -#define AD_DMA_WAVBC 0x78 /* wave base count */ -#define AD_DMA_WAVCC 0x7c /* wave current count */ - -#define AD_DMA_RESIC 0x80 /* RES dma interrupt current byte count */ -#define AD_DMA_RESIB 0x84 /* RES dma interrupt base byte count */ - -#define AD_DMA_ADCIC 0x88 /* ADC dma interrupt current byte count */ -#define AD_DMA_ADCIB 0x8c /* ADC dma interrupt base byte count */ - -#define AD_DMA_SYNIC 0x90 /* synth dma interrupt current byte count */ -#define AD_DMA_SYNIB 0x94 /* synth dma interrupt base byte count */ - -#define AD_DMA_WAVIC 0x98 /* wave dma interrupt current byte count */ -#define AD_DMA_WAVIB 0x9c /* wave dma interrupt base byte count */ - -#define AD_DMA_ICC 0xffffff /* current byte count mask */ -#define AD_DMA_IBC 0xffffff /* base byte count mask */ -/* bits 24 -> 31 reserved */ - -/* 4 bytes pad */ -#define AD_DMA_ADC 0xa8 /* ADC dma control and status */ -#define AD_DMA_SYNTH 0xb0 /* Synth dma control and status */ -#define AD_DMA_WAV 0xb8 /* wave dma control and status */ -#define AD_DMA_RES 0xa0 /* Resample dma control and status */ - -#define AD_DMA_SGDE 0x0001 /* SGD mode enable */ -#define AD_DMA_LOOP 0x0002 /* loop enable */ -#define AD_DMA_IM 0x000c /* interrupt mode mask */ -#define AD_DMA_IM_DIS (~AD_DMA_IM) /* disable */ -#define AD_DMA_IM_CNT 0x0004 /* interrupt on count */ -#define AD_DMA_IM_SGD 0x0008 /* interrupt on SGD flag */ -#define AD_DMA_IM_EOL 0x000c /* interrupt on End of Linked List */ -#define AD_DMA_SGDS 0x0030 /* SGD status */ -#define AD_DMA_SFLG 0x0040 /* SGD flag */ -#define AD_DMA_EOL 0x0080 /* SGD end of list */ -/* bits 8 -> 15 reserved */ - -#define AD_DMA_DISR 0xc0 /* dma interrupt status */ -#define AD_DMA_DISR_RESI 0x000001 /* resampler channel interrupt */ -#define AD_DMA_DISR_ADCI 0x000002 /* ADC channel interrupt */ -#define AD_DMA_DISR_SYNI 0x000004 /* synthesis channel interrupt */ -#define AD_DMA_DISR_WAVI 0x000008 /* wave channel interrupt */ -/* bits 4, 5 reserved */ -#define AD_DMA_DISR_SEPS 0x000040 /* serial eeprom status */ -/* bits 7 -> 13 reserved */ -#define AD_DMA_DISR_PMAI 0x004000 /* pci master abort interrupt */ -#define AD_DMA_DISR_PTAI 0x008000 /* pci target abort interrupt */ -#define AD_DMA_DISR_PTAE 0x010000 /* pci target abort interrupt enable */ -#define AD_DMA_DISR_PMAE 0x020000 /* pci master abort interrupt enable */ -/* bits 19 -> 31 reserved */ - -/* interrupt mask */ -#define AD_INTR_MASK (AD_DMA_DISR_RESI|AD_DMA_DISR_ADCI| \ - AD_DMA_DISR_WAVI|AD_DMA_DISR_SYNI| \ - AD_DMA_DISR_PMAI|AD_DMA_DISR_PTAI) - -#define AD_DMA_CHSS 0xc4 /* dma channel stop status */ -#define AD_DMA_CHSS_RESS 0x000001 /* resampler channel stopped */ -#define AD_DMA_CHSS_ADCS 0x000002 /* ADC channel stopped */ -#define AD_DMA_CHSS_SYNS 0x000004 /* synthesis channel stopped */ -#define AD_DMA_CHSS_WAVS 0x000008 /* wave channel stopped */ - -#define AD_GPIO_IPC 0xc8 /* gpio port control */ -#define AD_GPIO_OP 0xca /* gpio output port status */ -#define AD_GPIO_IP 0xcc /* gpio input port status */ - -#define AD_AC97_BASE 0x100 /* ac97 base register */ - -#define AD_AC97_RESET 0x100 /* reset */ - -#define AD_AC97_PWR_CTL 0x126 /* == AC97_POWERDOWN */ -#define AD_AC97_PWR_ADC 0x0001 /* ADC ready status */ -#define AD_AC97_PWR_DAC 0x0002 /* DAC ready status */ -#define AD_AC97_PWR_PR0 0x0100 /* PR0 (ADC) powerdown */ -#define AD_AC97_PWR_PR1 0x0200 /* PR1 (DAC) powerdown */ - -#define AD_MISC_CTL 0x176 /* misc control */ -#define AD_MISC_CTL_DACZ 0x8000 /* set for zero fill, unset for repeat */ -#define AD_MISC_CTL_ARSR 0x0001 /* set for SR1, unset for SR0 */ -#define AD_MISC_CTL_ALSR 0x0100 -#define AD_MISC_CTL_DLSR 0x0400 -#define AD_MISC_CTL_DRSR 0x0004 - -#define AD_AC97_SR0 0x178 /* sample rate 0, 0xbb80 == 48K */ -#define AD_AC97_SR0_48K 0xbb80 /* 48KHz */ -#define AD_AC97_SR1 0x17a /* sample rate 1 */ - -#define AD_AC97_ACIC 0x180 /* ac97 codec interface control */ -#define AD_AC97_ACIC_ACIE 0x0001 /* analog codec interface enable */ -#define AD_AC97_ACIC_ACRD 0x0002 /* analog codec reset disable */ -#define AD_AC97_ACIC_ASOE 0x0004 /* audio stream output enable */ -#define AD_AC97_ACIC_VSRM 0x0008 /* variable sample rate mode */ -#define AD_AC97_ACIC_FSDH 0x0100 /* force SDATA_OUT high */ -#define AD_AC97_ACIC_FSYH 0x0200 /* force sync high */ -#define AD_AC97_ACIC_ACRDY 0x8000 /* analog codec ready status */ -/* bits 10 -> 14 reserved */ - - -#define AD_DS_MEMSIZE 512 -#define AD_OPL_MEMSIZE 16 -#define AD_MIDI_MEMSIZE 16 - -#define AD_WAV_STATE 0 -#define AD_ADC_STATE 1 -#define AD_MAX_STATES 2 - -#define AD_CHAN_WAV 0x0001 -#define AD_CHAN_ADC 0x0002 -#define AD_CHAN_RES 0x0004 -#define AD_CHAN_SYN 0x0008 - - -/* The chip would support 4 GB buffers and 16 MB periods, - * but let's not overdo it ... */ -#define BUFFER_BYTES_MAX (256 * 1024) -#define PERIOD_BYTES_MIN 32 -#define PERIOD_BYTES_MAX (BUFFER_BYTES_MAX / 2) -#define PERIODS_MIN 2 -#define PERIODS_MAX (BUFFER_BYTES_MAX / PERIOD_BYTES_MIN) - -#endif /* __AD1889_H__ */ diff --git a/ANDROID_3.4.5/sound/pci/ak4531_codec.c b/ANDROID_3.4.5/sound/pci/ak4531_codec.c deleted file mode 100644 index cadf7b96..00000000 --- a/ANDROID_3.4.5/sound/pci/ak4531_codec.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Universal routines for AK4531 codec - * - * - * 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 - -/* -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Universal routines for AK4531 codec"); -MODULE_LICENSE("GPL"); -*/ - -#ifdef CONFIG_PROC_FS -static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531); -#else -#define snd_ak4531_proc_init(card,ak) -#endif - -/* - * - */ - -#if 0 - -static void snd_ak4531_dump(struct snd_ak4531 *ak4531) -{ - int idx; - - for (idx = 0; idx < 0x19; idx++) - printk(KERN_DEBUG "ak4531 0x%x: 0x%x\n", - idx, ak4531->regs[idx]); -} - -#endif - -/* - * - */ - -#define AK4531_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_ak4531_info_single, \ - .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \ - .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) } -#define AK4531_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_ak4531_info_single, \ - .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \ - .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 16) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int val; - - mutex_lock(&ak4531->reg_mutex); - val = (ak4531->regs[reg] >> shift) & mask; - mutex_unlock(&ak4531->reg_mutex); - if (invert) { - val = mask - val; - } - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 16) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - int val; - - val = ucontrol->value.integer.value[0] & mask; - if (invert) { - val = mask - val; - } - val <<= shift; - mutex_lock(&ak4531->reg_mutex); - val = (ak4531->regs[reg] & ~(mask << shift)) | val; - change = val != ak4531->regs[reg]; - ak4531->write(ak4531, reg, ak4531->regs[reg] = val); - mutex_unlock(&ak4531->reg_mutex); - return change; -} - -#define AK4531_DOUBLE(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_ak4531_info_double, \ - .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \ - .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) } -#define AK4531_DOUBLE_TLV(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_ak4531_info_double, \ - .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \ - .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x07; - int right_shift = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int left, right; - - mutex_lock(&ak4531->reg_mutex); - left = (ak4531->regs[left_reg] >> left_shift) & mask; - right = (ak4531->regs[right_reg] >> right_shift) & mask; - mutex_unlock(&ak4531->reg_mutex); - if (invert) { - left = mask - left; - right = mask - right; - } - ucontrol->value.integer.value[0] = left; - ucontrol->value.integer.value[1] = right; - return 0; -} - -static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x07; - int right_shift = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - int left, right; - - left = ucontrol->value.integer.value[0] & mask; - right = ucontrol->value.integer.value[1] & mask; - if (invert) { - left = mask - left; - right = mask - right; - } - left <<= left_shift; - right <<= right_shift; - mutex_lock(&ak4531->reg_mutex); - if (left_reg == right_reg) { - left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right; - change = left != ak4531->regs[left_reg]; - ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left); - } else { - left = (ak4531->regs[left_reg] & ~(mask << left_shift)) | left; - right = (ak4531->regs[right_reg] & ~(mask << right_shift)) | right; - change = left != ak4531->regs[left_reg] || right != ak4531->regs[right_reg]; - ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left); - ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right); - } - mutex_unlock(&ak4531->reg_mutex); - return change; -} - -#define AK4531_INPUT_SW(xname, xindex, reg1, reg2, left_shift, right_shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_ak4531_info_input_sw, \ - .get = snd_ak4531_get_input_sw, .put = snd_ak4531_put_input_sw, \ - .private_value = reg1 | (reg2 << 8) | (left_shift << 16) | (right_shift << 24) } - -static int snd_ak4531_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol); - int reg1 = kcontrol->private_value & 0xff; - int reg2 = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x0f; - int right_shift = (kcontrol->private_value >> 24) & 0x0f; - - mutex_lock(&ak4531->reg_mutex); - ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1; - ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1; - ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1; - ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1; - mutex_unlock(&ak4531->reg_mutex); - return 0; -} - -static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol); - int reg1 = kcontrol->private_value & 0xff; - int reg2 = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x0f; - int right_shift = (kcontrol->private_value >> 24) & 0x0f; - int change; - int val1, val2; - - mutex_lock(&ak4531->reg_mutex); - val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift)); - val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift)); - val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift; - val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift; - val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift; - val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift; - change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2]; - ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1); - ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2); - mutex_unlock(&ak4531->reg_mutex); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0); - -static struct snd_kcontrol_new snd_ak4531_controls[] __devinitdata = { - -AK4531_DOUBLE_TLV("Master Playback Switch", 0, - AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1, - db_scale_master), -AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1), - -AK4531_SINGLE_TLV("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1, - db_scale_mono), -AK4531_SINGLE("Master Mono Playback Volume", 0, AK4531_MONO_OUT, 0, 0x07, 1), - -AK4531_DOUBLE("PCM Switch", 0, AK4531_LVOICE, AK4531_RVOICE, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1, - db_scale_input), -AK4531_DOUBLE("PCM Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 3, 2, 1, 0), -AK4531_DOUBLE("PCM Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 2, 2, 1, 0), - -AK4531_DOUBLE("PCM Switch", 1, AK4531_LFM, AK4531_RFM, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1, - db_scale_input), -AK4531_DOUBLE("PCM Playback Switch", 1, AK4531_OUT_SW1, AK4531_OUT_SW1, 6, 5, 1, 0), -AK4531_INPUT_SW("PCM Capture Route", 1, AK4531_LIN_SW1, AK4531_RIN_SW1, 6, 5), - -AK4531_DOUBLE("CD Switch", 0, AK4531_LCD, AK4531_RCD, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1, - db_scale_input), -AK4531_DOUBLE("CD Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 2, 1, 1, 0), -AK4531_INPUT_SW("CD Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 2, 1), - -AK4531_DOUBLE("Line Switch", 0, AK4531_LLINE, AK4531_RLINE, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1, - db_scale_input), -AK4531_DOUBLE("Line Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 4, 3, 1, 0), -AK4531_INPUT_SW("Line Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 4, 3), - -AK4531_DOUBLE("Aux Switch", 0, AK4531_LAUXA, AK4531_RAUXA, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1, - db_scale_input), -AK4531_DOUBLE("Aux Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 5, 4, 1, 0), -AK4531_INPUT_SW("Aux Capture Route", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 4, 3), - -AK4531_SINGLE("Mono Switch", 0, AK4531_MONO1, 7, 1, 1), -AK4531_SINGLE_TLV("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1, db_scale_input), -AK4531_SINGLE("Mono Playback Switch", 0, AK4531_OUT_SW2, 0, 1, 0), -AK4531_DOUBLE("Mono Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 0, 0, 1, 0), - -AK4531_SINGLE("Mono Switch", 1, AK4531_MONO2, 7, 1, 1), -AK4531_SINGLE_TLV("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1, db_scale_input), -AK4531_SINGLE("Mono Playback Switch", 1, AK4531_OUT_SW2, 1, 1, 0), -AK4531_DOUBLE("Mono Capture Switch", 1, AK4531_LIN_SW2, AK4531_RIN_SW2, 1, 1, 1, 0), - -AK4531_SINGLE_TLV("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1, db_scale_input), -AK4531_SINGLE("Mic Switch", 0, AK4531_MIC, 7, 1, 1), -AK4531_SINGLE("Mic Playback Switch", 0, AK4531_OUT_SW1, 0, 1, 0), -AK4531_DOUBLE("Mic Capture Switch", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 0, 0, 1, 0), - -AK4531_DOUBLE("Mic Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 7, 7, 1, 0), -AK4531_DOUBLE("Mono1 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 6, 6, 1, 0), -AK4531_DOUBLE("Mono2 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 5, 5, 1, 0), - -AK4531_SINGLE("AD Input Select", 0, AK4531_AD_IN, 0, 1, 0), -AK4531_SINGLE("Mic Boost (+30dB)", 0, AK4531_MIC_GAIN, 0, 1, 0) -}; - -static int snd_ak4531_free(struct snd_ak4531 *ak4531) -{ - if (ak4531) { - if (ak4531->private_free) - ak4531->private_free(ak4531); - kfree(ak4531); - } - return 0; -} - -static int snd_ak4531_dev_free(struct snd_device *device) -{ - struct snd_ak4531 *ak4531 = device->device_data; - return snd_ak4531_free(ak4531); -} - -static u8 snd_ak4531_initial_map[0x19 + 1] = { - 0x9f, /* 00: Master Volume Lch */ - 0x9f, /* 01: Master Volume Rch */ - 0x9f, /* 02: Voice Volume Lch */ - 0x9f, /* 03: Voice Volume Rch */ - 0x9f, /* 04: FM Volume Lch */ - 0x9f, /* 05: FM Volume Rch */ - 0x9f, /* 06: CD Audio Volume Lch */ - 0x9f, /* 07: CD Audio Volume Rch */ - 0x9f, /* 08: Line Volume Lch */ - 0x9f, /* 09: Line Volume Rch */ - 0x9f, /* 0a: Aux Volume Lch */ - 0x9f, /* 0b: Aux Volume Rch */ - 0x9f, /* 0c: Mono1 Volume */ - 0x9f, /* 0d: Mono2 Volume */ - 0x9f, /* 0e: Mic Volume */ - 0x87, /* 0f: Mono-out Volume */ - 0x00, /* 10: Output Mixer SW1 */ - 0x00, /* 11: Output Mixer SW2 */ - 0x00, /* 12: Lch Input Mixer SW1 */ - 0x00, /* 13: Rch Input Mixer SW1 */ - 0x00, /* 14: Lch Input Mixer SW2 */ - 0x00, /* 15: Rch Input Mixer SW2 */ - 0x00, /* 16: Reset & Power Down */ - 0x00, /* 17: Clock Select */ - 0x00, /* 18: AD Input Select */ - 0x01 /* 19: Mic Amp Setup */ -}; - -int __devinit snd_ak4531_mixer(struct snd_card *card, - struct snd_ak4531 *_ak4531, - struct snd_ak4531 **rak4531) -{ - unsigned int idx; - int err; - struct snd_ak4531 *ak4531; - static struct snd_device_ops ops = { - .dev_free = snd_ak4531_dev_free, - }; - - if (snd_BUG_ON(!card || !_ak4531)) - return -EINVAL; - if (rak4531) - *rak4531 = NULL; - ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL); - if (ak4531 == NULL) - return -ENOMEM; - *ak4531 = *_ak4531; - mutex_init(&ak4531->reg_mutex); - if ((err = snd_component_add(card, "AK4531")) < 0) { - snd_ak4531_free(ak4531); - return err; - } - strcpy(card->mixername, "Asahi Kasei AK4531"); - ak4531->write(ak4531, AK4531_RESET, 0x03); /* no RST, PD */ - udelay(100); - ak4531->write(ak4531, AK4531_CLOCK, 0x00); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off LRCLK2 PLL */ - for (idx = 0; idx <= 0x19; idx++) { - if (idx == AK4531_RESET || idx == AK4531_CLOCK) - continue; - ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]); /* recording source is mixer */ - } - for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531))) < 0) { - snd_ak4531_free(ak4531); - return err; - } - } - snd_ak4531_proc_init(card, ak4531); - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ak4531, &ops)) < 0) { - snd_ak4531_free(ak4531); - return err; - } - -#if 0 - snd_ak4531_dump(ak4531); -#endif - if (rak4531) - *rak4531 = ak4531; - return 0; -} - -/* - * power management - */ -#ifdef CONFIG_PM -void snd_ak4531_suspend(struct snd_ak4531 *ak4531) -{ - /* mute */ - ak4531->write(ak4531, AK4531_LMASTER, 0x9f); - ak4531->write(ak4531, AK4531_RMASTER, 0x9f); - /* powerdown */ - ak4531->write(ak4531, AK4531_RESET, 0x01); -} - -void snd_ak4531_resume(struct snd_ak4531 *ak4531) -{ - int idx; - - /* initialize */ - ak4531->write(ak4531, AK4531_RESET, 0x03); - udelay(100); - ak4531->write(ak4531, AK4531_CLOCK, 0x00); - /* restore mixer registers */ - for (idx = 0; idx <= 0x19; idx++) { - if (idx == AK4531_RESET || idx == AK4531_CLOCK) - continue; - ak4531->write(ak4531, idx, ak4531->regs[idx]); - } -} -#endif - -#ifdef CONFIG_PROC_FS -/* - * /proc interface - */ - -static void snd_ak4531_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ak4531 *ak4531 = entry->private_data; - - snd_iprintf(buffer, "Asahi Kasei AK4531\n\n"); - snd_iprintf(buffer, "Recording source : %s\n" - "MIC gain : %s\n", - ak4531->regs[AK4531_AD_IN] & 1 ? "external" : "mixer", - ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB"); -} - -static void __devinit -snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(card, "ak4531", &entry)) - snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read); -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/ali5451/Makefile b/ANDROID_3.4.5/sound/pci/ali5451/Makefile deleted file mode 100644 index 713459c1..00000000 --- a/ANDROID_3.4.5/sound/pci/ali5451/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-ali5451-objs := ali5451.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_ALI5451) += snd-ali5451.o diff --git a/ANDROID_3.4.5/sound/pci/ali5451/ali5451.c b/ANDROID_3.4.5/sound/pci/ali5451/ali5451.c deleted file mode 100644 index bdd6164e..00000000 --- a/ANDROID_3.4.5/sound/pci/ali5451/ali5451.c +++ /dev/null @@ -1,2319 +0,0 @@ -/* - * Matt Wu - * Apr 26, 2001 - * Routines for control of ALi pci audio M5451 - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public Lcodecnse as published by - * the Free Software Foundation; either version 2 of the Lcodecnse, 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 Lcodecnse for more details. - * - * You should have received a copy of the GNU General Public Lcodecnse - * 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 -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Matt Wu "); -MODULE_DESCRIPTION("ALI M5451"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int pcm_channels = 32; -static bool spdif; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for ALI M5451 PCI Audio."); -module_param(pcm_channels, int, 0444); -MODULE_PARM_DESC(pcm_channels, "PCM Channels"); -module_param(spdif, bool, 0444); -MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); - -/* just for backward compatibility */ -static bool enable; -module_param(enable, bool, 0444); - - -/* - * Debug part definitions - */ - -/* #define ALI_DEBUG */ - -#ifdef ALI_DEBUG -#define snd_ali_printk(format, args...) printk(KERN_DEBUG format, ##args); -#else -#define snd_ali_printk(format, args...) -#endif - -/* - * Constants definition - */ - -#define DEVICE_ID_ALI5451 ((PCI_VENDOR_ID_AL<<16)|PCI_DEVICE_ID_AL_M5451) - - -#define ALI_CHANNELS 32 - -#define ALI_PCM_IN_CHANNEL 31 -#define ALI_SPDIF_IN_CHANNEL 19 -#define ALI_SPDIF_OUT_CHANNEL 15 -#define ALI_CENTER_CHANNEL 24 -#define ALI_LEF_CHANNEL 23 -#define ALI_SURR_LEFT_CHANNEL 26 -#define ALI_SURR_RIGHT_CHANNEL 25 -#define ALI_MODEM_IN_CHANNEL 21 -#define ALI_MODEM_OUT_CHANNEL 20 - -#define SNDRV_ALI_VOICE_TYPE_PCM 01 -#define SNDRV_ALI_VOICE_TYPE_OTH 02 - -#define ALI_5451_V02 0x02 - -/* - * Direct Registers - */ - -#define ALI_LEGACY_DMAR0 0x00 /* ADR0 */ -#define ALI_LEGACY_DMAR4 0x04 /* CNT0 */ -#define ALI_LEGACY_DMAR11 0x0b /* MOD */ -#define ALI_LEGACY_DMAR15 0x0f /* MMR */ -#define ALI_MPUR0 0x20 -#define ALI_MPUR1 0x21 -#define ALI_MPUR2 0x22 -#define ALI_MPUR3 0x23 - -#define ALI_AC97_WRITE 0x40 -#define ALI_AC97_READ 0x44 - -#define ALI_SCTRL 0x48 -#define ALI_SPDIF_OUT_ENABLE 0x20 -#define ALI_SCTRL_LINE_IN2 (1 << 9) -#define ALI_SCTRL_GPIO_IN2 (1 << 13) -#define ALI_SCTRL_LINE_OUT_EN (1 << 20) -#define ALI_SCTRL_GPIO_OUT_EN (1 << 23) -#define ALI_SCTRL_CODEC1_READY (1 << 24) -#define ALI_SCTRL_CODEC2_READY (1 << 25) -#define ALI_AC97_GPIO 0x4c -#define ALI_AC97_GPIO_ENABLE 0x8000 -#define ALI_AC97_GPIO_DATA_SHIFT 16 -#define ALI_SPDIF_CS 0x70 -#define ALI_SPDIF_CTRL 0x74 -#define ALI_SPDIF_IN_FUNC_ENABLE 0x02 -#define ALI_SPDIF_IN_CH_STATUS 0x40 -#define ALI_SPDIF_OUT_CH_STATUS 0xbf -#define ALI_START 0x80 -#define ALI_STOP 0x84 -#define ALI_CSPF 0x90 -#define ALI_AINT 0x98 -#define ALI_GC_CIR 0xa0 - #define ENDLP_IE 0x00001000 - #define MIDLP_IE 0x00002000 -#define ALI_AINTEN 0xa4 -#define ALI_VOLUME 0xa8 -#define ALI_SBDELTA_DELTA_R 0xac -#define ALI_MISCINT 0xb0 - #define ADDRESS_IRQ 0x00000020 - #define TARGET_REACHED 0x00008000 - #define MIXER_OVERFLOW 0x00000800 - #define MIXER_UNDERFLOW 0x00000400 - #define GPIO_IRQ 0x01000000 -#define ALI_SBBL_SBCL 0xc0 -#define ALI_SBCTRL_SBE2R_SBDD 0xc4 -#define ALI_STIMER 0xc8 -#define ALI_GLOBAL_CONTROL 0xd4 -#define ALI_SPDIF_OUT_SEL_PCM 0x00000400 /* bit 10 */ -#define ALI_SPDIF_IN_SUPPORT 0x00000800 /* bit 11 */ -#define ALI_SPDIF_OUT_CH_ENABLE 0x00008000 /* bit 15 */ -#define ALI_SPDIF_IN_CH_ENABLE 0x00080000 /* bit 19 */ -#define ALI_PCM_IN_ENABLE 0x80000000 /* bit 31 */ - -#define ALI_CSO_ALPHA_FMS 0xe0 -#define ALI_LBA 0xe4 -#define ALI_ESO_DELTA 0xe8 -#define ALI_GVSEL_PAN_VOC_CTRL_EC 0xf0 -#define ALI_EBUF1 0xf4 -#define ALI_EBUF2 0xf8 - -#define ALI_REG(codec, x) ((codec)->port + x) - -#define MAX_CODECS 2 - - -struct snd_ali; -struct snd_ali_voice; - -struct snd_ali_channel_control { - /* register data */ - struct REGDATA { - unsigned int start; - unsigned int stop; - unsigned int aint; - unsigned int ainten; - } data; - - /* register addresses */ - struct REGS { - unsigned int start; - unsigned int stop; - unsigned int aint; - unsigned int ainten; - unsigned int ac97read; - unsigned int ac97write; - } regs; - -}; - -struct snd_ali_voice { - unsigned int number; - unsigned int use :1, - pcm :1, - midi :1, - mode :1, - synth :1, - running :1; - - /* PCM data */ - struct snd_ali *codec; - struct snd_pcm_substream *substream; - struct snd_ali_voice *extra; - - int eso; /* final ESO value for channel */ - int count; /* runtime->period_size */ - - /* --- */ - - void *private_data; - void (*private_free)(void *private_data); -}; - - -struct snd_alidev { - - struct snd_ali_voice voices[ALI_CHANNELS]; - - unsigned int chcnt; /* num of opened channels */ - unsigned int chmap; /* bitmap for opened channels */ - unsigned int synthcount; - -}; - - -#define ALI_GLOBAL_REGS 56 -#define ALI_CHANNEL_REGS 8 -struct snd_ali_image { - u32 regs[ALI_GLOBAL_REGS]; - u32 channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS]; -}; - - -struct snd_ali { - int irq; - unsigned long port; - unsigned char revision; - - unsigned int hw_initialized :1; - unsigned int spdif_support :1; - - struct pci_dev *pci; - struct pci_dev *pci_m1533; - struct pci_dev *pci_m7101; - - struct snd_card *card; - struct snd_pcm *pcm[MAX_CODECS]; - struct snd_alidev synth; - struct snd_ali_channel_control chregs; - - /* S/PDIF Mask */ - unsigned int spdif_mask; - - unsigned int spurious_irq_count; - unsigned int spurious_irq_max_delta; - - unsigned int num_of_codecs; - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97[MAX_CODECS]; - unsigned short ac97_ext_id; - unsigned short ac97_ext_status; - - spinlock_t reg_lock; - spinlock_t voice_alloc; - -#ifdef CONFIG_PM - struct snd_ali_image *image; -#endif -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_ali_ids) = { - {PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0}, - {0, } -}; -MODULE_DEVICE_TABLE(pci, snd_ali_ids); - -static void snd_ali_clear_voices(struct snd_ali *, unsigned int, unsigned int); -static unsigned short snd_ali_codec_peek(struct snd_ali *, int, unsigned short); -static void snd_ali_codec_poke(struct snd_ali *, int, unsigned short, - unsigned short); - -/* - * AC97 ACCESS - */ - -static inline unsigned int snd_ali_5451_peek(struct snd_ali *codec, - unsigned int port) -{ - return (unsigned int)inl(ALI_REG(codec, port)); -} - -static inline void snd_ali_5451_poke(struct snd_ali *codec, - unsigned int port, - unsigned int val) -{ - outl((unsigned int)val, ALI_REG(codec, port)); -} - -static int snd_ali_codec_ready(struct snd_ali *codec, - unsigned int port) -{ - unsigned long end_time; - unsigned int res; - - end_time = jiffies + msecs_to_jiffies(250); - - for (;;) { - res = snd_ali_5451_peek(codec,port); - if (!(res & 0x8000)) - return 0; - if (!time_after_eq(end_time, jiffies)) - break; - schedule_timeout_uninterruptible(1); - } - - snd_ali_5451_poke(codec, port, res & ~0x8000); - snd_printdd("ali_codec_ready: codec is not ready.\n "); - return -EIO; -} - -static int snd_ali_stimer_ready(struct snd_ali *codec) -{ - unsigned long end_time; - unsigned long dwChk1,dwChk2; - - dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER); - end_time = jiffies + msecs_to_jiffies(250); - - for (;;) { - dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); - if (dwChk2 != dwChk1) - return 0; - if (!time_after_eq(end_time, jiffies)) - break; - schedule_timeout_uninterruptible(1); - } - - snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n"); - return -EIO; -} - -static void snd_ali_codec_poke(struct snd_ali *codec,int secondary, - unsigned short reg, - unsigned short val) -{ - unsigned int dwVal; - unsigned int port; - - if (reg >= 0x80) { - snd_printk(KERN_ERR "ali_codec_poke: reg(%xh) invalid.\n", reg); - return; - } - - port = codec->chregs.regs.ac97write; - - if (snd_ali_codec_ready(codec, port) < 0) - return; - if (snd_ali_stimer_ready(codec) < 0) - return; - - dwVal = (unsigned int) (reg & 0xff); - dwVal |= 0x8000 | (val << 16); - if (secondary) - dwVal |= 0x0080; - if (codec->revision == ALI_5451_V02) - dwVal |= 0x0100; - - snd_ali_5451_poke(codec, port, dwVal); - - return ; -} - -static unsigned short snd_ali_codec_peek(struct snd_ali *codec, - int secondary, - unsigned short reg) -{ - unsigned int dwVal; - unsigned int port; - - if (reg >= 0x80) { - snd_printk(KERN_ERR "ali_codec_peek: reg(%xh) invalid.\n", reg); - return ~0; - } - - port = codec->chregs.regs.ac97read; - - if (snd_ali_codec_ready(codec, port) < 0) - return ~0; - if (snd_ali_stimer_ready(codec) < 0) - return ~0; - - dwVal = (unsigned int) (reg & 0xff); - dwVal |= 0x8000; /* bit 15*/ - if (secondary) - dwVal |= 0x0080; - - snd_ali_5451_poke(codec, port, dwVal); - - if (snd_ali_stimer_ready(codec) < 0) - return ~0; - if (snd_ali_codec_ready(codec, port) < 0) - return ~0; - - return (snd_ali_5451_peek(codec, port) & 0xffff0000) >> 16; -} - -static void snd_ali_codec_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val ) -{ - struct snd_ali *codec = ac97->private_data; - - snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val); - if (reg == AC97_GPIO_STATUS) { - outl((val << ALI_AC97_GPIO_DATA_SHIFT) | ALI_AC97_GPIO_ENABLE, - ALI_REG(codec, ALI_AC97_GPIO)); - return; - } - snd_ali_codec_poke(codec, ac97->num, reg, val); - return ; -} - - -static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct snd_ali *codec = ac97->private_data; - - snd_ali_printk("codec_read reg=%xh.\n", reg); - return snd_ali_codec_peek(codec, ac97->num, reg); -} - -/* - * AC97 Reset - */ - -static int snd_ali_reset_5451(struct snd_ali *codec) -{ - struct pci_dev *pci_dev; - unsigned short wCount, wReg; - unsigned int dwVal; - - pci_dev = codec->pci_m1533; - if (pci_dev) { - pci_read_config_dword(pci_dev, 0x7c, &dwVal); - pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000); - udelay(5000); - pci_read_config_dword(pci_dev, 0x7c, &dwVal); - pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff); - udelay(5000); - } - - pci_dev = codec->pci; - pci_read_config_dword(pci_dev, 0x44, &dwVal); - pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000); - udelay(500); - pci_read_config_dword(pci_dev, 0x44, &dwVal); - pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff); - udelay(5000); - - wCount = 200; - while(wCount--) { - wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN); - if ((wReg & 0x000f) == 0x000f) - return 0; - udelay(5000); - } - - /* non-fatal if you have a non PM capable codec */ - /* snd_printk(KERN_WARNING "ali5451: reset time out\n"); */ - return 0; -} - -/* - * ALI 5451 Controller - */ - -static void snd_ali_enable_special_channel(struct snd_ali *codec, - unsigned int channel) -{ - unsigned long dwVal; - - dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)); - dwVal |= 1 << (channel & 0x0000001f); - outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); -} - -static void snd_ali_disable_special_channel(struct snd_ali *codec, - unsigned int channel) -{ - unsigned long dwVal; - - dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)); - dwVal &= ~(1 << (channel & 0x0000001f)); - outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); -} - -static void snd_ali_enable_address_interrupt(struct snd_ali *codec) -{ - unsigned int gc; - - gc = inl(ALI_REG(codec, ALI_GC_CIR)); - gc |= ENDLP_IE; - gc |= MIDLP_IE; - outl( gc, ALI_REG(codec, ALI_GC_CIR)); -} - -static void snd_ali_disable_address_interrupt(struct snd_ali *codec) -{ - unsigned int gc; - - gc = inl(ALI_REG(codec, ALI_GC_CIR)); - gc &= ~ENDLP_IE; - gc &= ~MIDLP_IE; - outl(gc, ALI_REG(codec, ALI_GC_CIR)); -} - -static void snd_ali_disable_voice_irq(struct snd_ali *codec, - unsigned int channel) -{ - unsigned int mask; - struct snd_ali_channel_control *pchregs = &(codec->chregs); - - snd_ali_printk("disable_voice_irq channel=%d\n",channel); - - mask = 1 << (channel & 0x1f); - pchregs->data.ainten = inl(ALI_REG(codec, pchregs->regs.ainten)); - pchregs->data.ainten &= ~mask; - outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten)); -} - -static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel) -{ - unsigned int idx = channel & 0x1f; - - if (codec->synth.chcnt >= ALI_CHANNELS){ - snd_printk(KERN_ERR - "ali_alloc_pcm_channel: no free channels.\n"); - return -1; - } - - if (!(codec->synth.chmap & (1 << idx))) { - codec->synth.chmap |= 1 << idx; - codec->synth.chcnt++; - snd_ali_printk("alloc_pcm_channel no. %d.\n",idx); - return idx; - } - return -1; -} - -static int snd_ali_find_free_channel(struct snd_ali * codec, int rec) -{ - int idx; - int result = -1; - - snd_ali_printk("find_free_channel: for %s\n",rec ? "rec" : "pcm"); - - /* recording */ - if (rec) { - if (codec->spdif_support && - (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & - ALI_SPDIF_IN_SUPPORT)) - idx = ALI_SPDIF_IN_CHANNEL; - else - idx = ALI_PCM_IN_CHANNEL; - - result = snd_ali_alloc_pcm_channel(codec, idx); - if (result >= 0) - return result; - else { - snd_printk(KERN_ERR "ali_find_free_channel: " - "record channel is busy now.\n"); - return -1; - } - } - - /* playback... */ - if (codec->spdif_support && - (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & - ALI_SPDIF_OUT_CH_ENABLE)) { - idx = ALI_SPDIF_OUT_CHANNEL; - result = snd_ali_alloc_pcm_channel(codec, idx); - if (result >= 0) - return result; - else - snd_printk(KERN_ERR "ali_find_free_channel: " - "S/PDIF out channel is in busy now.\n"); - } - - for (idx = 0; idx < ALI_CHANNELS; idx++) { - result = snd_ali_alloc_pcm_channel(codec, idx); - if (result >= 0) - return result; - } - snd_printk(KERN_ERR "ali_find_free_channel: no free channels.\n"); - return -1; -} - -static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel) -{ - unsigned int idx = channel & 0x0000001f; - - snd_ali_printk("free_channel_pcm channel=%d\n",channel); - - if (channel < 0 || channel >= ALI_CHANNELS) - return; - - if (!(codec->synth.chmap & (1 << idx))) { - snd_printk(KERN_ERR "ali_free_channel_pcm: " - "channel %d is not in use.\n", channel); - return; - } else { - codec->synth.chmap &= ~(1 << idx); - codec->synth.chcnt--; - } -} - -static void snd_ali_stop_voice(struct snd_ali *codec, unsigned int channel) -{ - unsigned int mask = 1 << (channel & 0x1f); - - snd_ali_printk("stop_voice: channel=%d\n",channel); - outl(mask, ALI_REG(codec, codec->chregs.regs.stop)); -} - -/* - * S/PDIF Part - */ - -static void snd_ali_delay(struct snd_ali *codec,int interval) -{ - unsigned long begintimer,currenttimer; - - begintimer = inl(ALI_REG(codec, ALI_STIMER)); - currenttimer = inl(ALI_REG(codec, ALI_STIMER)); - - while (currenttimer < begintimer + interval) { - if (snd_ali_stimer_ready(codec) < 0) - break; - currenttimer = inl(ALI_REG(codec, ALI_STIMER)); - cpu_relax(); - } -} - -static void snd_ali_detect_spdif_rate(struct snd_ali *codec) -{ - u16 wval; - u16 count = 0; - u8 bval, R1 = 0, R2; - - bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1)); - bval |= 0x1F; - outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL + 1)); - - while ((R1 < 0x0b || R1 > 0x0e) && R1 != 0x12 && count <= 50000) { - count ++; - snd_ali_delay(codec, 6); - bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1)); - R1 = bval & 0x1F; - } - - if (count > 50000) { - snd_printk(KERN_ERR "ali_detect_spdif_rate: timeout!\n"); - return; - } - - for (count = 0; count <= 50000; count++) { - snd_ali_delay(codec, 6); - bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1)); - R2 = bval & 0x1F; - if (R2 != R1) - R1 = R2; - else - break; - } - - if (count > 50000) { - snd_printk(KERN_ERR "ali_detect_spdif_rate: timeout!\n"); - return; - } - - if (R2 >= 0x0b && R2 <= 0x0e) { - wval = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2)); - wval &= 0xe0f0; - wval |= (0x09 << 8) | 0x05; - outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2)); - - bval = inb(ALI_REG(codec, ALI_SPDIF_CS + 3)) & 0xf0; - outb(bval | 0x02, ALI_REG(codec, ALI_SPDIF_CS + 3)); - } else if (R2 == 0x12) { - wval = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2)); - wval &= 0xe0f0; - wval |= (0x0e << 8) | 0x08; - outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2)); - - bval = inb(ALI_REG(codec,ALI_SPDIF_CS + 3)) & 0xf0; - outb(bval | 0x03, ALI_REG(codec, ALI_SPDIF_CS + 3)); - } -} - -static unsigned int snd_ali_get_spdif_in_rate(struct snd_ali *codec) -{ - u32 dwRate; - u8 bval; - - bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL)); - bval &= 0x7f; - bval |= 0x40; - outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL)); - - snd_ali_detect_spdif_rate(codec); - - bval = inb(ALI_REG(codec, ALI_SPDIF_CS + 3)); - bval &= 0x0f; - - switch (bval) { - case 0: dwRate = 44100; break; - case 1: dwRate = 48000; break; - case 2: dwRate = 32000; break; - default: dwRate = 0; break; - } - - return dwRate; -} - -static void snd_ali_enable_spdif_in(struct snd_ali *codec) -{ - unsigned int dwVal; - - dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)); - dwVal |= ALI_SPDIF_IN_SUPPORT; - outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); - - dwVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL)); - dwVal |= 0x02; - outb(dwVal, ALI_REG(codec, ALI_SPDIF_CTRL)); - - snd_ali_enable_special_channel(codec, ALI_SPDIF_IN_CHANNEL); -} - -static void snd_ali_disable_spdif_in(struct snd_ali *codec) -{ - unsigned int dwVal; - - dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)); - dwVal &= ~ALI_SPDIF_IN_SUPPORT; - outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); - - snd_ali_disable_special_channel(codec, ALI_SPDIF_IN_CHANNEL); -} - - -static void snd_ali_set_spdif_out_rate(struct snd_ali *codec, unsigned int rate) -{ - unsigned char bVal; - unsigned int dwRate; - - switch (rate) { - case 32000: dwRate = 0x300; break; - case 48000: dwRate = 0x200; break; - default: dwRate = 0; break; - } - - bVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL)); - bVal &= (unsigned char)(~(1<<6)); - - bVal |= 0x80; /* select right */ - outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL)); - outb(dwRate | 0x20, ALI_REG(codec, ALI_SPDIF_CS + 2)); - - bVal &= ~0x80; /* select left */ - outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL)); - outw(rate | 0x10, ALI_REG(codec, ALI_SPDIF_CS + 2)); -} - -static void snd_ali_enable_spdif_out(struct snd_ali *codec) -{ - unsigned short wVal; - unsigned char bVal; - struct pci_dev *pci_dev; - - pci_dev = codec->pci_m1533; - if (pci_dev == NULL) - return; - pci_read_config_byte(pci_dev, 0x61, &bVal); - bVal |= 0x40; - pci_write_config_byte(pci_dev, 0x61, bVal); - pci_read_config_byte(pci_dev, 0x7d, &bVal); - bVal |= 0x01; - pci_write_config_byte(pci_dev, 0x7d, bVal); - - pci_read_config_byte(pci_dev, 0x7e, &bVal); - bVal &= (~0x20); - bVal |= 0x10; - pci_write_config_byte(pci_dev, 0x7e, bVal); - - bVal = inb(ALI_REG(codec, ALI_SCTRL)); - outb(bVal | ALI_SPDIF_OUT_ENABLE, ALI_REG(codec, ALI_SCTRL)); - - bVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL)); - outb(bVal & ALI_SPDIF_OUT_CH_STATUS, ALI_REG(codec, ALI_SPDIF_CTRL)); - - wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL)); - wVal |= ALI_SPDIF_OUT_SEL_PCM; - outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); - snd_ali_disable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL); -} - -static void snd_ali_enable_spdif_chnout(struct snd_ali *codec) -{ - unsigned short wVal; - - wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL)); - wVal &= ~ALI_SPDIF_OUT_SEL_PCM; - outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); -/* - wVal = inw(ALI_REG(codec, ALI_SPDIF_CS)); - if (flag & ALI_SPDIF_OUT_NON_PCM) - wVal |= 0x0002; - else - wVal &= (~0x0002); - outw(wVal, ALI_REG(codec, ALI_SPDIF_CS)); -*/ - snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL); -} - -static void snd_ali_disable_spdif_chnout(struct snd_ali *codec) -{ - unsigned short wVal; - - wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL)); - wVal |= ALI_SPDIF_OUT_SEL_PCM; - outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL)); - - snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL); -} - -static void snd_ali_disable_spdif_out(struct snd_ali *codec) -{ - unsigned char bVal; - - bVal = inb(ALI_REG(codec, ALI_SCTRL)); - outb(bVal & ~ALI_SPDIF_OUT_ENABLE, ALI_REG(codec, ALI_SCTRL)); - - snd_ali_disable_spdif_chnout(codec); -} - -static void snd_ali_update_ptr(struct snd_ali *codec, int channel) -{ - struct snd_ali_voice *pvoice; - struct snd_pcm_runtime *runtime; - struct snd_ali_channel_control *pchregs; - unsigned int old, mask; -#ifdef ALI_DEBUG - unsigned int temp, cspf; -#endif - - pchregs = &(codec->chregs); - - /* check if interrupt occurred for channel */ - old = pchregs->data.aint; - mask = 1U << (channel & 0x1f); - - if (!(old & mask)) - return; - - pvoice = &codec->synth.voices[channel]; - runtime = pvoice->substream->runtime; - - udelay(100); - spin_lock(&codec->reg_lock); - - if (pvoice->pcm && pvoice->substream) { - /* pcm interrupt */ -#ifdef ALI_DEBUG - outb((u8)(pvoice->number), ALI_REG(codec, ALI_GC_CIR)); - temp = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); - cspf = (inl(ALI_REG(codec, ALI_CSPF)) & mask) == mask; -#endif - if (pvoice->running) { - snd_ali_printk("update_ptr: cso=%4.4x cspf=%d.\n", - (u16)temp, cspf); - spin_unlock(&codec->reg_lock); - snd_pcm_period_elapsed(pvoice->substream); - spin_lock(&codec->reg_lock); - } else { - snd_ali_stop_voice(codec, channel); - snd_ali_disable_voice_irq(codec, channel); - } - } else if (codec->synth.voices[channel].synth) { - /* synth interrupt */ - } else if (codec->synth.voices[channel].midi) { - /* midi interrupt */ - } else { - /* unknown interrupt */ - snd_ali_stop_voice(codec, channel); - snd_ali_disable_voice_irq(codec, channel); - } - spin_unlock(&codec->reg_lock); - outl(mask,ALI_REG(codec,pchregs->regs.aint)); - pchregs->data.aint = old & (~mask); -} - -static irqreturn_t snd_ali_card_interrupt(int irq, void *dev_id) -{ - struct snd_ali *codec = dev_id; - int channel; - unsigned int audio_int; - struct snd_ali_channel_control *pchregs; - - if (codec == NULL || !codec->hw_initialized) - return IRQ_NONE; - - audio_int = inl(ALI_REG(codec, ALI_MISCINT)); - if (!audio_int) - return IRQ_NONE; - - pchregs = &(codec->chregs); - if (audio_int & ADDRESS_IRQ) { - /* get interrupt status for all channels */ - pchregs->data.aint = inl(ALI_REG(codec, pchregs->regs.aint)); - for (channel = 0; channel < ALI_CHANNELS; channel++) - snd_ali_update_ptr(codec, channel); - } - outl((TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), - ALI_REG(codec, ALI_MISCINT)); - - return IRQ_HANDLED; -} - - -static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, - int type, int rec, int channel) -{ - struct snd_ali_voice *pvoice; - int idx; - - snd_ali_printk("alloc_voice: type=%d rec=%d\n", type, rec); - - spin_lock_irq(&codec->voice_alloc); - if (type == SNDRV_ALI_VOICE_TYPE_PCM) { - idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) : - snd_ali_find_free_channel(codec,rec); - if (idx < 0) { - snd_printk(KERN_ERR "ali_alloc_voice: err.\n"); - spin_unlock_irq(&codec->voice_alloc); - return NULL; - } - pvoice = &(codec->synth.voices[idx]); - pvoice->codec = codec; - pvoice->use = 1; - pvoice->pcm = 1; - pvoice->mode = rec; - spin_unlock_irq(&codec->voice_alloc); - return pvoice; - } - spin_unlock_irq(&codec->voice_alloc); - return NULL; -} - - -static void snd_ali_free_voice(struct snd_ali * codec, - struct snd_ali_voice *pvoice) -{ - void (*private_free)(void *); - void *private_data; - - snd_ali_printk("free_voice: channel=%d\n",pvoice->number); - if (!pvoice->use) - return; - snd_ali_clear_voices(codec, pvoice->number, pvoice->number); - spin_lock_irq(&codec->voice_alloc); - private_free = pvoice->private_free; - private_data = pvoice->private_data; - pvoice->private_free = NULL; - pvoice->private_data = NULL; - if (pvoice->pcm) - snd_ali_free_channel_pcm(codec, pvoice->number); - pvoice->use = pvoice->pcm = pvoice->synth = 0; - pvoice->substream = NULL; - spin_unlock_irq(&codec->voice_alloc); - if (private_free) - private_free(private_data); -} - - -static void snd_ali_clear_voices(struct snd_ali *codec, - unsigned int v_min, - unsigned int v_max) -{ - unsigned int i; - - for (i = v_min; i <= v_max; i++) { - snd_ali_stop_voice(codec, i); - snd_ali_disable_voice_irq(codec, i); - } -} - -static void snd_ali_write_voice_regs(struct snd_ali *codec, - unsigned int Channel, - unsigned int LBA, - unsigned int CSO, - unsigned int ESO, - unsigned int DELTA, - unsigned int ALPHA_FMS, - unsigned int GVSEL, - unsigned int PAN, - unsigned int VOL, - unsigned int CTRL, - unsigned int EC) -{ - unsigned int ctlcmds[4]; - - outb((unsigned char)(Channel & 0x001f), ALI_REG(codec, ALI_GC_CIR)); - - ctlcmds[0] = (CSO << 16) | (ALPHA_FMS & 0x0000ffff); - ctlcmds[1] = LBA; - ctlcmds[2] = (ESO << 16) | (DELTA & 0x0ffff); - ctlcmds[3] = (GVSEL << 31) | - ((PAN & 0x0000007f) << 24) | - ((VOL & 0x000000ff) << 16) | - ((CTRL & 0x0000000f) << 12) | - (EC & 0x00000fff); - - outb(Channel, ALI_REG(codec, ALI_GC_CIR)); - - outl(ctlcmds[0], ALI_REG(codec, ALI_CSO_ALPHA_FMS)); - outl(ctlcmds[1], ALI_REG(codec, ALI_LBA)); - outl(ctlcmds[2], ALI_REG(codec, ALI_ESO_DELTA)); - outl(ctlcmds[3], ALI_REG(codec, ALI_GVSEL_PAN_VOC_CTRL_EC)); - - outl(0x30000000, ALI_REG(codec, ALI_EBUF1)); /* Still Mode */ - outl(0x30000000, ALI_REG(codec, ALI_EBUF2)); /* Still Mode */ -} - -static unsigned int snd_ali_convert_rate(unsigned int rate, int rec) -{ - unsigned int delta; - - if (rate < 4000) - rate = 4000; - if (rate > 48000) - rate = 48000; - - if (rec) { - if (rate == 44100) - delta = 0x116a; - else if (rate == 8000) - delta = 0x6000; - else if (rate == 48000) - delta = 0x1000; - else - delta = ((48000 << 12) / rate) & 0x0000ffff; - } else { - if (rate == 44100) - delta = 0xeb3; - else if (rate == 8000) - delta = 0x2ab; - else if (rate == 48000) - delta = 0x1000; - else - delta = (((rate << 12) + rate) / 48000) & 0x0000ffff; - } - - return delta; -} - -static unsigned int snd_ali_control_mode(struct snd_pcm_substream *substream) -{ - unsigned int CTRL; - struct snd_pcm_runtime *runtime = substream->runtime; - - /* set ctrl mode - CTRL default: 8-bit (unsigned) mono, loop mode enabled - */ - CTRL = 0x00000001; - if (snd_pcm_format_width(runtime->format) == 16) - CTRL |= 0x00000008; /* 16-bit data */ - if (!snd_pcm_format_unsigned(runtime->format)) - CTRL |= 0x00000002; /* signed data */ - if (runtime->channels > 1) - CTRL |= 0x00000004; /* stereo data */ - return CTRL; -} - -/* - * PCM part - */ - -static int snd_ali_trigger(struct snd_pcm_substream *substream, - int cmd) - -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *s; - unsigned int what, whati, capture_flag; - struct snd_ali_voice *pvoice, *evoice; - unsigned int val; - int do_start; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - do_start = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - do_start = 0; - break; - default: - return -EINVAL; - } - - what = whati = capture_flag = 0; - snd_pcm_group_for_each_entry(s, substream) { - if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) { - pvoice = s->runtime->private_data; - evoice = pvoice->extra; - what |= 1 << (pvoice->number & 0x1f); - if (evoice == NULL) - whati |= 1 << (pvoice->number & 0x1f); - else { - whati |= 1 << (evoice->number & 0x1f); - what |= 1 << (evoice->number & 0x1f); - } - if (do_start) { - pvoice->running = 1; - if (evoice != NULL) - evoice->running = 1; - } else { - pvoice->running = 0; - if (evoice != NULL) - evoice->running = 0; - } - snd_pcm_trigger_done(s, substream); - if (pvoice->mode) - capture_flag = 1; - } - } - spin_lock(&codec->reg_lock); - if (!do_start) - outl(what, ALI_REG(codec, ALI_STOP)); - val = inl(ALI_REG(codec, ALI_AINTEN)); - if (do_start) - val |= whati; - else - val &= ~whati; - outl(val, ALI_REG(codec, ALI_AINTEN)); - if (do_start) - outl(what, ALI_REG(codec, ALI_START)); - snd_ali_printk("trigger: what=%xh whati=%xh\n", what, whati); - spin_unlock(&codec->reg_lock); - - return 0; -} - -static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ali_voice *pvoice = runtime->private_data; - struct snd_ali_voice *evoice = pvoice->extra; - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - /* voice management */ - - if (params_buffer_size(hw_params) / 2 != - params_period_size(hw_params)) { - if (!evoice) { - evoice = snd_ali_alloc_voice(codec, - SNDRV_ALI_VOICE_TYPE_PCM, - 0, -1); - if (!evoice) - return -ENOMEM; - pvoice->extra = evoice; - evoice->substream = substream; - } - } else { - if (evoice) { - snd_ali_free_voice(codec, evoice); - pvoice->extra = evoice = NULL; - } - } - - return 0; -} - -static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ali_voice *pvoice = runtime->private_data; - struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL; - - snd_pcm_lib_free_pages(substream); - if (evoice) { - snd_ali_free_voice(codec, evoice); - pvoice->extra = NULL; - } - return 0; -} - -static int snd_ali_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int snd_ali_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_ali_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ali_voice *pvoice = runtime->private_data; - struct snd_ali_voice *evoice = pvoice->extra; - - unsigned int LBA; - unsigned int Delta; - unsigned int ESO; - unsigned int CTRL; - unsigned int GVSEL; - unsigned int PAN; - unsigned int VOL; - unsigned int EC; - - snd_ali_printk("playback_prepare ...\n"); - - spin_lock_irq(&codec->reg_lock); - - /* set Delta (rate) value */ - Delta = snd_ali_convert_rate(runtime->rate, 0); - - if (pvoice->number == ALI_SPDIF_IN_CHANNEL || - pvoice->number == ALI_PCM_IN_CHANNEL) - snd_ali_disable_special_channel(codec, pvoice->number); - else if (codec->spdif_support && - (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & - ALI_SPDIF_OUT_CH_ENABLE) - && pvoice->number == ALI_SPDIF_OUT_CHANNEL) { - snd_ali_set_spdif_out_rate(codec, runtime->rate); - Delta = 0x1000; - } - - /* set Loop Back Address */ - LBA = runtime->dma_addr; - - /* set interrupt count size */ - pvoice->count = runtime->period_size; - - /* set target ESO for channel */ - pvoice->eso = runtime->buffer_size; - - snd_ali_printk("playback_prepare: eso=%xh count=%xh\n", - pvoice->eso, pvoice->count); - - /* set ESO to capture first MIDLP interrupt */ - ESO = pvoice->eso -1; - /* set ctrl mode */ - CTRL = snd_ali_control_mode(substream); - - GVSEL = 1; - PAN = 0; - VOL = 0; - EC = 0; - snd_ali_printk("playback_prepare:\n"); - snd_ali_printk("ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n", - pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL); - snd_ali_write_voice_regs(codec, - pvoice->number, - LBA, - 0, /* cso */ - ESO, - Delta, - 0, /* alpha */ - GVSEL, - PAN, - VOL, - CTRL, - EC); - if (evoice) { - evoice->count = pvoice->count; - evoice->eso = pvoice->count << 1; - ESO = evoice->eso - 1; - snd_ali_write_voice_regs(codec, - evoice->number, - LBA, - 0, /* cso */ - ESO, - Delta, - 0, /* alpha */ - GVSEL, - 0x7f, - 0x3ff, - CTRL, - EC); - } - spin_unlock_irq(&codec->reg_lock); - return 0; -} - - -static int snd_ali_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ali_voice *pvoice = runtime->private_data; - unsigned int LBA; - unsigned int Delta; - unsigned int ESO; - unsigned int CTRL; - unsigned int GVSEL; - unsigned int PAN; - unsigned int VOL; - unsigned int EC; - u8 bValue; - - spin_lock_irq(&codec->reg_lock); - - snd_ali_printk("ali_prepare...\n"); - - snd_ali_enable_special_channel(codec,pvoice->number); - - Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL || - pvoice->number == ALI_MODEM_OUT_CHANNEL) ? - 0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode); - - /* Prepare capture intr channel */ - if (pvoice->number == ALI_SPDIF_IN_CHANNEL) { - - unsigned int rate; - - spin_unlock_irq(&codec->reg_lock); - if (codec->revision != ALI_5451_V02) - return -1; - - rate = snd_ali_get_spdif_in_rate(codec); - if (rate == 0) { - snd_printk(KERN_WARNING "ali_capture_preapre: " - "spdif rate detect err!\n"); - rate = 48000; - } - spin_lock_irq(&codec->reg_lock); - bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL)); - if (bValue & 0x10) { - outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL)); - printk(KERN_WARNING "clear SPDIF parity error flag.\n"); - } - - if (rate != 48000) - Delta = ((rate << 12) / runtime->rate) & 0x00ffff; - } - - /* set target ESO for channel */ - pvoice->eso = runtime->buffer_size; - - /* set interrupt count size */ - pvoice->count = runtime->period_size; - - /* set Loop Back Address */ - LBA = runtime->dma_addr; - - /* set ESO to capture first MIDLP interrupt */ - ESO = pvoice->eso - 1; - CTRL = snd_ali_control_mode(substream); - GVSEL = 0; - PAN = 0x00; - VOL = 0x00; - EC = 0; - - snd_ali_write_voice_regs( codec, - pvoice->number, - LBA, - 0, /* cso */ - ESO, - Delta, - 0, /* alpha */ - GVSEL, - PAN, - VOL, - CTRL, - EC); - - spin_unlock_irq(&codec->reg_lock); - - return 0; -} - - -static snd_pcm_uframes_t -snd_ali_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ali_voice *pvoice = runtime->private_data; - unsigned int cso; - - spin_lock(&codec->reg_lock); - if (!pvoice->running) { - spin_unlock(&codec->reg_lock); - return 0; - } - outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR)); - cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); - spin_unlock(&codec->reg_lock); - snd_ali_printk("playback pointer returned cso=%xh.\n", cso); - - return cso; -} - - -static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ali_voice *pvoice = runtime->private_data; - unsigned int cso; - - spin_lock(&codec->reg_lock); - if (!pvoice->running) { - spin_unlock_irq(&codec->reg_lock); - return 0; - } - outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR)); - cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); - spin_unlock(&codec->reg_lock); - - return cso; -} - -static struct snd_pcm_hardware snd_ali_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (256*1024), - .period_bytes_min = 64, - .period_bytes_max = (256*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * Capture support device description - */ - -static struct snd_pcm_hardware snd_ali_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static void snd_ali_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - struct snd_ali_voice *pvoice = runtime->private_data; - struct snd_ali *codec; - - if (pvoice) { - codec = pvoice->codec; - snd_ali_free_voice(pvoice->codec, pvoice); - } -} - -static int snd_ali_open(struct snd_pcm_substream *substream, int rec, - int channel, struct snd_pcm_hardware *phw) -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ali_voice *pvoice; - - pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, - channel); - if (!pvoice) - return -EAGAIN; - - pvoice->substream = substream; - runtime->private_data = pvoice; - runtime->private_free = snd_ali_pcm_free_substream; - - runtime->hw = *phw; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - 0, 64*1024); - return 0; -} - -static int snd_ali_playback_open(struct snd_pcm_substream *substream) -{ - return snd_ali_open(substream, 0, -1, &snd_ali_playback); -} - -static int snd_ali_capture_open(struct snd_pcm_substream *substream) -{ - return snd_ali_open(substream, 1, -1, &snd_ali_capture); -} - -static int snd_ali_playback_close(struct snd_pcm_substream *substream) -{ - return 0; -} - -static int snd_ali_close(struct snd_pcm_substream *substream) -{ - struct snd_ali *codec = snd_pcm_substream_chip(substream); - struct snd_ali_voice *pvoice = substream->runtime->private_data; - - snd_ali_disable_special_channel(codec,pvoice->number); - - return 0; -} - -static struct snd_pcm_ops snd_ali_playback_ops = { - .open = snd_ali_playback_open, - .close = snd_ali_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ali_playback_hw_params, - .hw_free = snd_ali_playback_hw_free, - .prepare = snd_ali_playback_prepare, - .trigger = snd_ali_trigger, - .pointer = snd_ali_playback_pointer, -}; - -static struct snd_pcm_ops snd_ali_capture_ops = { - .open = snd_ali_capture_open, - .close = snd_ali_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ali_hw_params, - .hw_free = snd_ali_hw_free, - .prepare = snd_ali_prepare, - .trigger = snd_ali_trigger, - .pointer = snd_ali_pointer, -}; - -/* - * Modem PCM - */ - -static int snd_ali_modem_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_ali *chip = snd_pcm_substream_chip(substream); - unsigned int modem_num = chip->num_of_codecs - 1; - snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, - params_rate(hw_params)); - snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0); - return snd_ali_hw_params(substream, hw_params); -} - -static struct snd_pcm_hardware snd_ali_modem = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000), - .rate_min = 8000, - .rate_max = 16000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = (256*1024), - .period_bytes_min = 64, - .period_bytes_max = (256*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, - int channel) -{ - static unsigned int rates[] = {8000, 9600, 12000, 16000}; - static struct snd_pcm_hw_constraint_list hw_constraint_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - int err = snd_ali_open(substream, rec, channel, &snd_ali_modem); - - if (err) - return err; - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates); -} - -static int snd_ali_modem_playback_open(struct snd_pcm_substream *substream) -{ - return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL); -} - -static int snd_ali_modem_capture_open(struct snd_pcm_substream *substream) -{ - return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL); -} - -static struct snd_pcm_ops snd_ali_modem_playback_ops = { - .open = snd_ali_modem_playback_open, - .close = snd_ali_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ali_modem_hw_params, - .hw_free = snd_ali_hw_free, - .prepare = snd_ali_prepare, - .trigger = snd_ali_trigger, - .pointer = snd_ali_pointer, -}; - -static struct snd_pcm_ops snd_ali_modem_capture_ops = { - .open = snd_ali_modem_capture_open, - .close = snd_ali_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ali_modem_hw_params, - .hw_free = snd_ali_hw_free, - .prepare = snd_ali_prepare, - .trigger = snd_ali_trigger, - .pointer = snd_ali_pointer, -}; - - -struct ali_pcm_description { - char *name; - unsigned int playback_num; - unsigned int capture_num; - struct snd_pcm_ops *playback_ops; - struct snd_pcm_ops *capture_ops; - unsigned short class; -}; - - -static void snd_ali_pcm_free(struct snd_pcm *pcm) -{ - struct snd_ali *codec = pcm->private_data; - codec->pcm[pcm->device] = NULL; -} - - -static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, - struct ali_pcm_description *desc) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(codec->card, desc->name, device, - desc->playback_num, desc->capture_num, &pcm); - if (err < 0) { - snd_printk(KERN_ERR "snd_ali_pcm: err called snd_pcm_new.\n"); - return err; - } - pcm->private_data = codec; - pcm->private_free = snd_ali_pcm_free; - if (desc->playback_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - desc->playback_ops); - if (desc->capture_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - desc->capture_ops); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(codec->pci), - 64*1024, 128*1024); - - pcm->info_flags = 0; - pcm->dev_class = desc->class; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, desc->name); - codec->pcm[0] = pcm; - return 0; -} - -static struct ali_pcm_description ali_pcms[] = { - { .name = "ALI 5451", - .playback_num = ALI_CHANNELS, - .capture_num = 1, - .playback_ops = &snd_ali_playback_ops, - .capture_ops = &snd_ali_capture_ops - }, - { .name = "ALI 5451 modem", - .playback_num = 1, - .capture_num = 1, - .playback_ops = &snd_ali_modem_playback_ops, - .capture_ops = &snd_ali_modem_capture_ops, - .class = SNDRV_PCM_CLASS_MODEM - } -}; - -static int __devinit snd_ali_build_pcms(struct snd_ali *codec) -{ - int i, err; - for (i = 0; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms); i++) { - err = snd_ali_pcm(codec, i, &ali_pcms[i]); - if (err < 0) - return err; - } - return 0; -} - - -#define ALI5451_SPDIF(xname, xindex, value) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ -.info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ -.put = snd_ali5451_spdif_put, .private_value = value} - -#define snd_ali5451_spdif_info snd_ctl_boolean_mono_info - -static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ali *codec = kcontrol->private_data; - unsigned int spdif_enable; - - spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0; - - spin_lock_irq(&codec->reg_lock); - switch (kcontrol->private_value) { - case 0: - spdif_enable = (codec->spdif_mask & 0x02) ? 1 : 0; - break; - case 1: - spdif_enable = ((codec->spdif_mask & 0x02) && - (codec->spdif_mask & 0x04)) ? 1 : 0; - break; - case 2: - spdif_enable = (codec->spdif_mask & 0x01) ? 1 : 0; - break; - default: - break; - } - ucontrol->value.integer.value[0] = spdif_enable; - spin_unlock_irq(&codec->reg_lock); - return 0; -} - -static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ali *codec = kcontrol->private_data; - unsigned int change = 0, spdif_enable = 0; - - spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0; - - spin_lock_irq(&codec->reg_lock); - switch (kcontrol->private_value) { - case 0: - change = (codec->spdif_mask & 0x02) ? 1 : 0; - change = change ^ spdif_enable; - if (change) { - if (spdif_enable) { - codec->spdif_mask |= 0x02; - snd_ali_enable_spdif_out(codec); - } else { - codec->spdif_mask &= ~(0x02); - codec->spdif_mask &= ~(0x04); - snd_ali_disable_spdif_out(codec); - } - } - break; - case 1: - change = (codec->spdif_mask & 0x04) ? 1 : 0; - change = change ^ spdif_enable; - if (change && (codec->spdif_mask & 0x02)) { - if (spdif_enable) { - codec->spdif_mask |= 0x04; - snd_ali_enable_spdif_chnout(codec); - } else { - codec->spdif_mask &= ~(0x04); - snd_ali_disable_spdif_chnout(codec); - } - } - break; - case 2: - change = (codec->spdif_mask & 0x01) ? 1 : 0; - change = change ^ spdif_enable; - if (change) { - if (spdif_enable) { - codec->spdif_mask |= 0x01; - snd_ali_enable_spdif_in(codec); - } else { - codec->spdif_mask &= ~(0x01); - snd_ali_disable_spdif_in(codec); - } - } - break; - default: - break; - } - spin_unlock_irq(&codec->reg_lock); - - return change; -} - -static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = { - /* spdif aplayback switch */ - /* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */ - ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0), - /* spdif out to spdif channel */ - ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Channel Output ",NONE,SWITCH), 0, 1), - /* spdif in from spdif channel */ - ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2) -}; - -static int __devinit snd_ali_mixer(struct snd_ali * codec) -{ - struct snd_ac97_template ac97; - unsigned int idx; - int i, err; - static struct snd_ac97_bus_ops ops = { - .write = snd_ali_codec_write, - .read = snd_ali_codec_read, - }; - - err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus); - if (err < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = codec; - - for (i = 0; i < codec->num_of_codecs; i++) { - ac97.num = i; - err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i]); - if (err < 0) { - snd_printk(KERN_ERR - "ali mixer %d creating error.\n", i); - if (i == 0) - return err; - codec->num_of_codecs = 1; - break; - } - } - - if (codec->spdif_support) { - for (idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) { - err = snd_ctl_add(codec->card, - snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec)); - if (err < 0) - return err; - } - } - return 0; -} - -#ifdef CONFIG_PM -static int ali_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ali *chip = card->private_data; - struct snd_ali_image *im; - int i, j; - - im = chip->image; - if (!im) - return 0; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < chip->num_of_codecs; i++) { - snd_pcm_suspend_all(chip->pcm[i]); - snd_ac97_suspend(chip->ac97[i]); - } - - spin_lock_irq(&chip->reg_lock); - - im->regs[ALI_MISCINT >> 2] = inl(ALI_REG(chip, ALI_MISCINT)); - /* im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START)); */ - im->regs[ALI_STOP >> 2] = inl(ALI_REG(chip, ALI_STOP)); - - /* disable all IRQ bits */ - outl(0, ALI_REG(chip, ALI_MISCINT)); - - for (i = 0; i < ALI_GLOBAL_REGS; i++) { - if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP)) - continue; - im->regs[i] = inl(ALI_REG(chip, i*4)); - } - - for (i = 0; i < ALI_CHANNELS; i++) { - outb(i, ALI_REG(chip, ALI_GC_CIR)); - for (j = 0; j < ALI_CHANNEL_REGS; j++) - im->channel_regs[i][j] = inl(ALI_REG(chip, j*4 + 0xe0)); - } - - /* stop all HW channel */ - outl(0xffffffff, ALI_REG(chip, ALI_STOP)); - - spin_unlock_irq(&chip->reg_lock); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int ali_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ali *chip = card->private_data; - struct snd_ali_image *im; - int i, j; - - im = chip->image; - if (!im) - return 0; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "ali5451: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - spin_lock_irq(&chip->reg_lock); - - for (i = 0; i < ALI_CHANNELS; i++) { - outb(i, ALI_REG(chip, ALI_GC_CIR)); - for (j = 0; j < ALI_CHANNEL_REGS; j++) - outl(im->channel_regs[i][j], ALI_REG(chip, j*4 + 0xe0)); - } - - for (i = 0; i < ALI_GLOBAL_REGS; i++) { - if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) || - (i*4 == ALI_START)) - continue; - outl(im->regs[i], ALI_REG(chip, i*4)); - } - - /* start HW channel */ - outl(im->regs[ALI_START >> 2], ALI_REG(chip, ALI_START)); - /* restore IRQ enable bits */ - outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT)); - - spin_unlock_irq(&chip->reg_lock); - - for (i = 0 ; i < chip->num_of_codecs; i++) - snd_ac97_resume(chip->ac97[i]); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -static int snd_ali_free(struct snd_ali * codec) -{ - if (codec->hw_initialized) - snd_ali_disable_address_interrupt(codec); - if (codec->irq >= 0) - free_irq(codec->irq, codec); - if (codec->port) - pci_release_regions(codec->pci); - pci_disable_device(codec->pci); -#ifdef CONFIG_PM - kfree(codec->image); -#endif - pci_dev_put(codec->pci_m1533); - pci_dev_put(codec->pci_m7101); - kfree(codec); - return 0; -} - -static int snd_ali_chip_init(struct snd_ali *codec) -{ - unsigned int legacy; - unsigned char temp; - struct pci_dev *pci_dev; - - snd_ali_printk("chip initializing ... \n"); - - if (snd_ali_reset_5451(codec)) { - snd_printk(KERN_ERR "ali_chip_init: reset 5451 error.\n"); - return -1; - } - - if (codec->revision == ALI_5451_V02) { - pci_dev = codec->pci_m1533; - pci_read_config_byte(pci_dev, 0x59, &temp); - temp |= 0x80; - pci_write_config_byte(pci_dev, 0x59, temp); - - pci_dev = codec->pci_m7101; - pci_read_config_byte(pci_dev, 0xb8, &temp); - temp |= 0x20; - pci_write_config_byte(pci_dev, 0xB8, temp); - } - - pci_read_config_dword(codec->pci, 0x44, &legacy); - legacy &= 0xff00ff00; - legacy |= 0x000800aa; - pci_write_config_dword(codec->pci, 0x44, legacy); - - outl(0x80000001, ALI_REG(codec, ALI_GLOBAL_CONTROL)); - outl(0x00000000, ALI_REG(codec, ALI_AINTEN)); - outl(0xffffffff, ALI_REG(codec, ALI_AINT)); - outl(0x00000000, ALI_REG(codec, ALI_VOLUME)); - outb(0x10, ALI_REG(codec, ALI_MPUR2)); - - codec->ac97_ext_id = snd_ali_codec_peek(codec, 0, AC97_EXTENDED_ID); - codec->ac97_ext_status = snd_ali_codec_peek(codec, 0, - AC97_EXTENDED_STATUS); - if (codec->spdif_support) { - snd_ali_enable_spdif_out(codec); - codec->spdif_mask = 0x00000002; - } - - codec->num_of_codecs = 1; - - /* secondary codec - modem */ - if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) { - codec->num_of_codecs++; - outl(inl(ALI_REG(codec, ALI_SCTRL)) | - (ALI_SCTRL_LINE_IN2 | ALI_SCTRL_GPIO_IN2 | - ALI_SCTRL_LINE_OUT_EN), - ALI_REG(codec, ALI_SCTRL)); - } - - snd_ali_printk("chip initialize succeed.\n"); - return 0; - -} - -/* proc for register dump */ -static void snd_ali_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buf) -{ - struct snd_ali *codec = entry->private_data; - int i; - for (i = 0; i < 256 ; i+= 4) - snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i))); -} - -static void __devinit snd_ali_proc_init(struct snd_ali *codec) -{ - struct snd_info_entry *entry; - if (!snd_card_proc_new(codec->card, "ali5451", &entry)) - snd_info_set_text_ops(entry, codec, snd_ali_proc_read); -} - -static int __devinit snd_ali_resources(struct snd_ali *codec) -{ - int err; - - snd_ali_printk("resources allocation ...\n"); - err = pci_request_regions(codec->pci, "ALI 5451"); - if (err < 0) - return err; - codec->port = pci_resource_start(codec->pci, 0); - - if (request_irq(codec->pci->irq, snd_ali_card_interrupt, - IRQF_SHARED, KBUILD_MODNAME, codec)) { - snd_printk(KERN_ERR "Unable to request irq.\n"); - return -EBUSY; - } - codec->irq = codec->pci->irq; - snd_ali_printk("resources allocated.\n"); - return 0; -} -static int snd_ali_dev_free(struct snd_device *device) -{ - struct snd_ali *codec = device->device_data; - snd_ali_free(codec); - return 0; -} - -static int __devinit snd_ali_create(struct snd_card *card, - struct pci_dev *pci, - int pcm_streams, - int spdif_support, - struct snd_ali ** r_ali) -{ - struct snd_ali *codec; - int i, err; - unsigned short cmdw; - static struct snd_device_ops ops = { - .dev_free = snd_ali_dev_free, - }; - - *r_ali = NULL; - - snd_ali_printk("creating ...\n"); - - /* enable PCI device */ - err = pci_enable_device(pci); - if (err < 0) - return err; - /* check, if we can restrict PCI DMA transfers to 31 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(31)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(31)) < 0) { - snd_printk(KERN_ERR "architecture does not support " - "31bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - codec = kzalloc(sizeof(*codec), GFP_KERNEL); - if (!codec) { - pci_disable_device(pci); - return -ENOMEM; - } - - spin_lock_init(&codec->reg_lock); - spin_lock_init(&codec->voice_alloc); - - codec->card = card; - codec->pci = pci; - codec->irq = -1; - codec->revision = pci->revision; - codec->spdif_support = spdif_support; - - if (pcm_streams < 1) - pcm_streams = 1; - if (pcm_streams > 32) - pcm_streams = 32; - - pci_set_master(pci); - pci_read_config_word(pci, PCI_COMMAND, &cmdw); - if ((cmdw & PCI_COMMAND_IO) != PCI_COMMAND_IO) { - cmdw |= PCI_COMMAND_IO; - pci_write_config_word(pci, PCI_COMMAND, cmdw); - } - pci_set_master(pci); - - if (snd_ali_resources(codec)) { - snd_ali_free(codec); - return -EBUSY; - } - - synchronize_irq(pci->irq); - - codec->synth.chmap = 0; - codec->synth.chcnt = 0; - codec->spdif_mask = 0; - codec->synth.synthcount = 0; - - if (codec->revision == ALI_5451_V02) - codec->chregs.regs.ac97read = ALI_AC97_WRITE; - else - codec->chregs.regs.ac97read = ALI_AC97_READ; - codec->chregs.regs.ac97write = ALI_AC97_WRITE; - - codec->chregs.regs.start = ALI_START; - codec->chregs.regs.stop = ALI_STOP; - codec->chregs.regs.aint = ALI_AINT; - codec->chregs.regs.ainten = ALI_AINTEN; - - codec->chregs.data.start = 0x00; - codec->chregs.data.stop = 0x00; - codec->chregs.data.aint = 0x00; - codec->chregs.data.ainten = 0x00; - - /* M1533: southbridge */ - codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL); - if (!codec->pci_m1533) { - snd_printk(KERN_ERR "ali5451: cannot find ALi 1533 chip.\n"); - snd_ali_free(codec); - return -ENODEV; - } - /* M7101: power management */ - codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL); - if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) { - snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n"); - snd_ali_free(codec); - return -ENODEV; - } - - snd_ali_printk("snd_device_new is called.\n"); - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops); - if (err < 0) { - snd_ali_free(codec); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - /* initialise synth voices*/ - for (i = 0; i < ALI_CHANNELS; i++) - codec->synth.voices[i].number = i; - - err = snd_ali_chip_init(codec); - if (err < 0) { - snd_printk(KERN_ERR "ali create: chip init error.\n"); - return err; - } - -#ifdef CONFIG_PM - codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL); - if (!codec->image) - snd_printk(KERN_WARNING "can't allocate apm buffer\n"); -#endif - - snd_ali_enable_address_interrupt(codec); - codec->hw_initialized = 1; - - *r_ali = codec; - snd_ali_printk("created.\n"); - return 0; -} - -static int __devinit snd_ali_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct snd_ali *codec; - int err; - - snd_ali_printk("probe ...\n"); - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_ali_create(card, pci, pcm_channels, spdif, &codec); - if (err < 0) - goto error; - card->private_data = codec; - - snd_ali_printk("mixer building ...\n"); - err = snd_ali_mixer(codec); - if (err < 0) - goto error; - - snd_ali_printk("pcm building ...\n"); - err = snd_ali_build_pcms(codec); - if (err < 0) - goto error; - - snd_ali_proc_init(codec); - - strcpy(card->driver, "ALI5451"); - strcpy(card->shortname, "ALI 5451"); - - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, codec->port, codec->irq); - - snd_ali_printk("register card.\n"); - err = snd_card_register(card); - if (err < 0) - goto error; - - pci_set_drvdata(pci, card); - return 0; - - error: - snd_card_free(card); - return err; -} - -static void __devexit snd_ali_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_ali_ids, - .probe = snd_ali_probe, - .remove = __devexit_p(snd_ali_remove), -#ifdef CONFIG_PM - .suspend = ali_suspend, - .resume = ali_resume, -#endif -}; - -static int __init alsa_card_ali_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_ali_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_ali_init) -module_exit(alsa_card_ali_exit) diff --git a/ANDROID_3.4.5/sound/pci/als300.c b/ANDROID_3.4.5/sound/pci/als300.c deleted file mode 100644 index 8196e229..00000000 --- a/ANDROID_3.4.5/sound/pci/als300.c +++ /dev/null @@ -1,877 +0,0 @@ -/* - * als300.c - driver for Avance Logic ALS300/ALS300+ soundcards. - * Copyright (C) 2005 by Ash Willis - * - * 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 - * - * TODO - * 4 channel playback for ALS300+ - * gameport - * mpu401 - * opl3 - * - * NOTES - * The BLOCK_COUNTER registers for the ALS300(+) return a figure related to - * the position in the current period, NOT the whole buffer. It is important - * to know which period we are in so we can calculate the correct pointer. - * This is why we always use 2 periods. We can then use a flip-flop variable - * to keep track of what period we are in. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -/* snd_als300_set_irq_flag */ -#define IRQ_DISABLE 0 -#define IRQ_ENABLE 1 - -/* I/O port layout */ -#define AC97_ACCESS 0x00 -#define AC97_READ 0x04 -#define AC97_STATUS 0x06 -#define AC97_DATA_AVAIL (1<<6) -#define AC97_BUSY (1<<7) -#define ALS300_IRQ_STATUS 0x07 /* ALS300 Only */ -#define IRQ_PLAYBACK (1<<3) -#define IRQ_CAPTURE (1<<2) -#define GCR_DATA 0x08 -#define GCR_INDEX 0x0C -#define ALS300P_DRAM_IRQ_STATUS 0x0D /* ALS300+ Only */ -#define MPU_IRQ_STATUS 0x0E /* ALS300 Rev. E+, ALS300+ */ -#define ALS300P_IRQ_STATUS 0x0F /* ALS300+ Only */ - -/* General Control Registers */ -#define PLAYBACK_START 0x80 -#define PLAYBACK_END 0x81 -#define PLAYBACK_CONTROL 0x82 -#define TRANSFER_START (1<<16) -#define FIFO_PAUSE (1<<17) -#define RECORD_START 0x83 -#define RECORD_END 0x84 -#define RECORD_CONTROL 0x85 -#define DRAM_WRITE_CONTROL 0x8B -#define WRITE_TRANS_START (1<<16) -#define DRAM_MODE_2 (1<<17) -#define MISC_CONTROL 0x8C -#define IRQ_SET_BIT (1<<15) -#define VMUTE_NORMAL (1<<20) -#define MMUTE_NORMAL (1<<21) -#define MUS_VOC_VOL 0x8E -#define PLAYBACK_BLOCK_COUNTER 0x9A -#define RECORD_BLOCK_COUNTER 0x9B - -#define DEBUG_CALLS 0 -#define DEBUG_PLAY_REC 0 - -#if DEBUG_CALLS -#define snd_als300_dbgcalls(format, args...) printk(KERN_DEBUG format, ##args) -#define snd_als300_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__) -#define snd_als300_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__) -#else -#define snd_als300_dbgcalls(format, args...) -#define snd_als300_dbgcallenter() -#define snd_als300_dbgcallleave() -#endif - -#if DEBUG_PLAY_REC -#define snd_als300_dbgplay(format, args...) printk(KERN_ERR format, ##args) -#else -#define snd_als300_dbgplay(format, args...) -#endif - -enum {DEVICE_ALS300, DEVICE_ALS300_PLUS}; - -MODULE_AUTHOR("Ash Willis "); -MODULE_DESCRIPTION("Avance Logic ALS300"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS300},{Avance Logic,ALS300+}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ALS300 sound card."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ALS300 sound card."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ALS300 sound card."); - -struct snd_als300 { - unsigned long port; - spinlock_t reg_lock; - struct snd_card *card; - struct pci_dev *pci; - - struct snd_pcm *pcm; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - - struct snd_ac97 *ac97; - struct snd_opl3 *opl3; - - struct resource *res_port; - - int irq; - - int chip_type; /* ALS300 or ALS300+ */ - - char revision; -}; - -struct snd_als300_substream_data { - int period_flipflop; - int control_register; - int block_counter_register; -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_als300_ids) = { - { 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 }, - { 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_als300_ids); - -static inline u32 snd_als300_gcr_read(unsigned long port, unsigned short reg) -{ - outb(reg, port+GCR_INDEX); - return inl(port+GCR_DATA); -} - -static inline void snd_als300_gcr_write(unsigned long port, - unsigned short reg, u32 val) -{ - outb(reg, port+GCR_INDEX); - outl(val, port+GCR_DATA); -} - -/* Enable/Disable Interrupts */ -static void snd_als300_set_irq_flag(struct snd_als300 *chip, int cmd) -{ - u32 tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL); - snd_als300_dbgcallenter(); - - /* boolean XOR check, since old vs. new hardware have - directly reversed bit setting for ENABLE and DISABLE. - ALS300+ acts like newer versions of ALS300 */ - if (((chip->revision > 5 || chip->chip_type == DEVICE_ALS300_PLUS) ^ - (cmd == IRQ_ENABLE)) == 0) - tmp |= IRQ_SET_BIT; - else - tmp &= ~IRQ_SET_BIT; - snd_als300_gcr_write(chip->port, MISC_CONTROL, tmp); - snd_als300_dbgcallleave(); -} - -static int snd_als300_free(struct snd_als300 *chip) -{ - snd_als300_dbgcallenter(); - snd_als300_set_irq_flag(chip, IRQ_DISABLE); - if (chip->irq >= 0) - free_irq(chip->irq, chip); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - snd_als300_dbgcallleave(); - return 0; -} - -static int snd_als300_dev_free(struct snd_device *device) -{ - struct snd_als300 *chip = device->device_data; - return snd_als300_free(chip); -} - -static irqreturn_t snd_als300_interrupt(int irq, void *dev_id) -{ - u8 status; - struct snd_als300 *chip = dev_id; - struct snd_als300_substream_data *data; - - status = inb(chip->port+ALS300_IRQ_STATUS); - if (!status) /* shared IRQ, for different device?? Exit ASAP! */ - return IRQ_NONE; - - /* ACK everything ASAP */ - outb(status, chip->port+ALS300_IRQ_STATUS); - if (status & IRQ_PLAYBACK) { - if (chip->pcm && chip->playback_substream) { - data = chip->playback_substream->runtime->private_data; - data->period_flipflop ^= 1; - snd_pcm_period_elapsed(chip->playback_substream); - snd_als300_dbgplay("IRQ_PLAYBACK\n"); - } - } - if (status & IRQ_CAPTURE) { - if (chip->pcm && chip->capture_substream) { - data = chip->capture_substream->runtime->private_data; - data->period_flipflop ^= 1; - snd_pcm_period_elapsed(chip->capture_substream); - snd_als300_dbgplay("IRQ_CAPTURE\n"); - } - } - return IRQ_HANDLED; -} - -static irqreturn_t snd_als300plus_interrupt(int irq, void *dev_id) -{ - u8 general, mpu, dram; - struct snd_als300 *chip = dev_id; - struct snd_als300_substream_data *data; - - general = inb(chip->port+ALS300P_IRQ_STATUS); - mpu = inb(chip->port+MPU_IRQ_STATUS); - dram = inb(chip->port+ALS300P_DRAM_IRQ_STATUS); - - /* shared IRQ, for different device?? Exit ASAP! */ - if ((general == 0) && ((mpu & 0x80) == 0) && ((dram & 0x01) == 0)) - return IRQ_NONE; - - if (general & IRQ_PLAYBACK) { - if (chip->pcm && chip->playback_substream) { - outb(IRQ_PLAYBACK, chip->port+ALS300P_IRQ_STATUS); - data = chip->playback_substream->runtime->private_data; - data->period_flipflop ^= 1; - snd_pcm_period_elapsed(chip->playback_substream); - snd_als300_dbgplay("IRQ_PLAYBACK\n"); - } - } - if (general & IRQ_CAPTURE) { - if (chip->pcm && chip->capture_substream) { - outb(IRQ_CAPTURE, chip->port+ALS300P_IRQ_STATUS); - data = chip->capture_substream->runtime->private_data; - data->period_flipflop ^= 1; - snd_pcm_period_elapsed(chip->capture_substream); - snd_als300_dbgplay("IRQ_CAPTURE\n"); - } - } - /* FIXME: Ack other interrupt types. Not important right now as - * those other devices aren't enabled. */ - return IRQ_HANDLED; -} - -static void __devexit snd_als300_remove(struct pci_dev *pci) -{ - snd_als300_dbgcallenter(); - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); - snd_als300_dbgcallleave(); -} - -static unsigned short snd_als300_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - int i; - struct snd_als300 *chip = ac97->private_data; - - for (i = 0; i < 1000; i++) { - if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0) - break; - udelay(10); - } - outl((reg << 24) | (1 << 31), chip->port+AC97_ACCESS); - - for (i = 0; i < 1000; i++) { - if ((inb(chip->port+AC97_STATUS) & (AC97_DATA_AVAIL)) != 0) - break; - udelay(10); - } - return inw(chip->port+AC97_READ); -} - -static void snd_als300_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - int i; - struct snd_als300 *chip = ac97->private_data; - - for (i = 0; i < 1000; i++) { - if ((inb(chip->port+AC97_STATUS) & (AC97_BUSY)) == 0) - break; - udelay(10); - } - outl((reg << 24) | val, chip->port+AC97_ACCESS); -} - -static int snd_als300_ac97(struct snd_als300 *chip) -{ - struct snd_ac97_bus *bus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_als300_ac97_write, - .read = snd_als300_ac97_read, - }; - - snd_als300_dbgcallenter(); - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - - snd_als300_dbgcallleave(); - return snd_ac97_mixer(bus, &ac97, &chip->ac97); -} - -/* hardware definition - * - * In AC97 mode, we always use 48k/16bit/stereo. - * Any request to change data type is ignored by - * the card when it is running outside of legacy - * mode. - */ -static struct snd_pcm_hardware snd_als300_playback_hw = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 64 * 1024, - .period_bytes_min = 64, - .period_bytes_max = 32 * 1024, - .periods_min = 2, - .periods_max = 2, -}; - -static struct snd_pcm_hardware snd_als300_capture_hw = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 64 * 1024, - .period_bytes_min = 64, - .period_bytes_max = 32 * 1024, - .periods_min = 2, - .periods_max = 2, -}; - -static int snd_als300_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_als300 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_als300_substream_data *data = kzalloc(sizeof(*data), - GFP_KERNEL); - - snd_als300_dbgcallenter(); - chip->playback_substream = substream; - runtime->hw = snd_als300_playback_hw; - runtime->private_data = data; - data->control_register = PLAYBACK_CONTROL; - data->block_counter_register = PLAYBACK_BLOCK_COUNTER; - snd_als300_dbgcallleave(); - return 0; -} - -static int snd_als300_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_als300 *chip = snd_pcm_substream_chip(substream); - struct snd_als300_substream_data *data; - - data = substream->runtime->private_data; - snd_als300_dbgcallenter(); - kfree(data); - chip->playback_substream = NULL; - snd_pcm_lib_free_pages(substream); - snd_als300_dbgcallleave(); - return 0; -} - -static int snd_als300_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_als300 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_als300_substream_data *data = kzalloc(sizeof(*data), - GFP_KERNEL); - - snd_als300_dbgcallenter(); - chip->capture_substream = substream; - runtime->hw = snd_als300_capture_hw; - runtime->private_data = data; - data->control_register = RECORD_CONTROL; - data->block_counter_register = RECORD_BLOCK_COUNTER; - snd_als300_dbgcallleave(); - return 0; -} - -static int snd_als300_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_als300 *chip = snd_pcm_substream_chip(substream); - struct snd_als300_substream_data *data; - - data = substream->runtime->private_data; - snd_als300_dbgcallenter(); - kfree(data); - chip->capture_substream = NULL; - snd_pcm_lib_free_pages(substream); - snd_als300_dbgcallleave(); - return 0; -} - -static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int snd_als300_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_als300_playback_prepare(struct snd_pcm_substream *substream) -{ - u32 tmp; - struct snd_als300 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned short period_bytes = snd_pcm_lib_period_bytes(substream); - unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - - snd_als300_dbgcallenter(); - spin_lock_irq(&chip->reg_lock); - tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL); - tmp &= ~TRANSFER_START; - - snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n", - period_bytes, buffer_bytes); - - /* set block size */ - tmp &= 0xffff0000; - tmp |= period_bytes - 1; - snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, tmp); - - /* set dma area */ - snd_als300_gcr_write(chip->port, PLAYBACK_START, - runtime->dma_addr); - snd_als300_gcr_write(chip->port, PLAYBACK_END, - runtime->dma_addr + buffer_bytes - 1); - spin_unlock_irq(&chip->reg_lock); - snd_als300_dbgcallleave(); - return 0; -} - -static int snd_als300_capture_prepare(struct snd_pcm_substream *substream) -{ - u32 tmp; - struct snd_als300 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned short period_bytes = snd_pcm_lib_period_bytes(substream); - unsigned short buffer_bytes = snd_pcm_lib_buffer_bytes(substream); - - snd_als300_dbgcallenter(); - spin_lock_irq(&chip->reg_lock); - tmp = snd_als300_gcr_read(chip->port, RECORD_CONTROL); - tmp &= ~TRANSFER_START; - - snd_als300_dbgplay("Period bytes: %d Buffer bytes %d\n", period_bytes, - buffer_bytes); - - /* set block size */ - tmp &= 0xffff0000; - tmp |= period_bytes - 1; - - /* set dma area */ - snd_als300_gcr_write(chip->port, RECORD_CONTROL, tmp); - snd_als300_gcr_write(chip->port, RECORD_START, - runtime->dma_addr); - snd_als300_gcr_write(chip->port, RECORD_END, - runtime->dma_addr + buffer_bytes - 1); - spin_unlock_irq(&chip->reg_lock); - snd_als300_dbgcallleave(); - return 0; -} - -static int snd_als300_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_als300 *chip = snd_pcm_substream_chip(substream); - u32 tmp; - struct snd_als300_substream_data *data; - unsigned short reg; - int ret = 0; - - data = substream->runtime->private_data; - reg = data->control_register; - - snd_als300_dbgcallenter(); - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - tmp = snd_als300_gcr_read(chip->port, reg); - data->period_flipflop = 1; - snd_als300_gcr_write(chip->port, reg, tmp | TRANSFER_START); - snd_als300_dbgplay("TRIGGER START\n"); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - tmp = snd_als300_gcr_read(chip->port, reg); - snd_als300_gcr_write(chip->port, reg, tmp & ~TRANSFER_START); - snd_als300_dbgplay("TRIGGER STOP\n"); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - tmp = snd_als300_gcr_read(chip->port, reg); - snd_als300_gcr_write(chip->port, reg, tmp | FIFO_PAUSE); - snd_als300_dbgplay("TRIGGER PAUSE\n"); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - tmp = snd_als300_gcr_read(chip->port, reg); - snd_als300_gcr_write(chip->port, reg, tmp & ~FIFO_PAUSE); - snd_als300_dbgplay("TRIGGER RELEASE\n"); - break; - default: - snd_als300_dbgplay("TRIGGER INVALID\n"); - ret = -EINVAL; - } - spin_unlock(&chip->reg_lock); - snd_als300_dbgcallleave(); - return ret; -} - -static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream) -{ - u16 current_ptr; - struct snd_als300 *chip = snd_pcm_substream_chip(substream); - struct snd_als300_substream_data *data; - unsigned short period_bytes; - - data = substream->runtime->private_data; - period_bytes = snd_pcm_lib_period_bytes(substream); - - snd_als300_dbgcallenter(); - spin_lock(&chip->reg_lock); - current_ptr = (u16) snd_als300_gcr_read(chip->port, - data->block_counter_register) + 4; - spin_unlock(&chip->reg_lock); - if (current_ptr > period_bytes) - current_ptr = 0; - else - current_ptr = period_bytes - current_ptr; - - if (data->period_flipflop == 0) - current_ptr += period_bytes; - snd_als300_dbgplay("Pointer (bytes): %d\n", current_ptr); - snd_als300_dbgcallleave(); - return bytes_to_frames(substream->runtime, current_ptr); -} - -static struct snd_pcm_ops snd_als300_playback_ops = { - .open = snd_als300_playback_open, - .close = snd_als300_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_als300_pcm_hw_params, - .hw_free = snd_als300_pcm_hw_free, - .prepare = snd_als300_playback_prepare, - .trigger = snd_als300_trigger, - .pointer = snd_als300_pointer, -}; - -static struct snd_pcm_ops snd_als300_capture_ops = { - .open = snd_als300_capture_open, - .close = snd_als300_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_als300_pcm_hw_params, - .hw_free = snd_als300_pcm_hw_free, - .prepare = snd_als300_capture_prepare, - .trigger = snd_als300_trigger, - .pointer = snd_als300_pointer, -}; - -static int __devinit snd_als300_new_pcm(struct snd_als300 *chip) -{ - struct snd_pcm *pcm; - int err; - - snd_als300_dbgcallenter(); - err = snd_pcm_new(chip->card, "ALS300", 0, 1, 1, &pcm); - if (err < 0) - return err; - pcm->private_data = chip; - strcpy(pcm->name, "ALS300"); - chip->pcm = pcm; - - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_als300_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_als300_capture_ops); - - /* pre-allocation of buffers */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 64*1024); - snd_als300_dbgcallleave(); - return 0; -} - -static void snd_als300_init(struct snd_als300 *chip) -{ - unsigned long flags; - u32 tmp; - - snd_als300_dbgcallenter(); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->revision = (snd_als300_gcr_read(chip->port, MISC_CONTROL) >> 16) - & 0x0000000F; - /* Setup DRAM */ - tmp = snd_als300_gcr_read(chip->port, DRAM_WRITE_CONTROL); - snd_als300_gcr_write(chip->port, DRAM_WRITE_CONTROL, - (tmp | DRAM_MODE_2) - & ~WRITE_TRANS_START); - - /* Enable IRQ output */ - snd_als300_set_irq_flag(chip, IRQ_ENABLE); - - /* Unmute hardware devices so their outputs get routed to - * the onboard mixer */ - tmp = snd_als300_gcr_read(chip->port, MISC_CONTROL); - snd_als300_gcr_write(chip->port, MISC_CONTROL, - tmp | VMUTE_NORMAL | MMUTE_NORMAL); - - /* Reset volumes */ - snd_als300_gcr_write(chip->port, MUS_VOC_VOL, 0); - - /* Make sure playback transfer is stopped */ - tmp = snd_als300_gcr_read(chip->port, PLAYBACK_CONTROL); - snd_als300_gcr_write(chip->port, PLAYBACK_CONTROL, - tmp & ~TRANSFER_START); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_als300_dbgcallleave(); -} - -static int __devinit snd_als300_create(struct snd_card *card, - struct pci_dev *pci, int chip_type, - struct snd_als300 **rchip) -{ - struct snd_als300 *chip; - void *irq_handler; - int err; - - static struct snd_device_ops ops = { - .dev_free = snd_als300_dev_free, - }; - *rchip = NULL; - - snd_als300_dbgcallenter(); - if ((err = pci_enable_device(pci)) < 0) - return err; - - if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - printk(KERN_ERR "error setting 28bit DMA mask\n"); - pci_disable_device(pci); - return -ENXIO; - } - pci_set_master(pci); - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - chip->pci = pci; - chip->irq = -1; - chip->chip_type = chip_type; - spin_lock_init(&chip->reg_lock); - - if ((err = pci_request_regions(pci, "ALS300")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->port = pci_resource_start(pci, 0); - - if (chip->chip_type == DEVICE_ALS300_PLUS) - irq_handler = snd_als300plus_interrupt; - else - irq_handler = snd_als300_interrupt; - - if (request_irq(pci->irq, irq_handler, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_als300_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - - - snd_als300_init(chip); - - err = snd_als300_ac97(chip); - if (err < 0) { - snd_printk(KERN_WARNING "Could not create ac97\n"); - snd_als300_free(chip); - return err; - } - - if ((err = snd_als300_new_pcm(chip)) < 0) { - snd_printk(KERN_WARNING "Could not create PCM\n"); - snd_als300_free(chip); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - chip, &ops)) < 0) { - snd_als300_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - snd_als300_dbgcallleave(); - return 0; -} - -#ifdef CONFIG_PM -static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_als300 *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_ac97_suspend(chip->ac97); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_als300_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_als300 *chip = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "als300: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_als300_init(chip); - snd_ac97_resume(chip->ac97); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static int __devinit snd_als300_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_als300 *chip; - int err, chip_type; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - - if (err < 0) - return err; - - chip_type = pci_id->driver_data; - - if ((err = snd_als300_create(card, pci, chip_type, &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - strcpy(card->driver, "ALS300"); - if (chip->chip_type == DEVICE_ALS300_PLUS) - /* don't know much about ALS300+ yet - * print revision number for now */ - sprintf(card->shortname, "ALS300+ (Rev. %d)", chip->revision); - else - sprintf(card->shortname, "ALS300 (Rev. %c)", 'A' + - chip->revision - 1); - sprintf(card->longname, "%s at 0x%lx irq %i", - card->shortname, chip->port, chip->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_als300_ids, - .probe = snd_als300_probe, - .remove = __devexit_p(snd_als300_remove), -#ifdef CONFIG_PM - .suspend = snd_als300_suspend, - .resume = snd_als300_resume, -#endif -}; - -static int __init alsa_card_als300_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_als300_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_als300_init) -module_exit(alsa_card_als300_exit) diff --git a/ANDROID_3.4.5/sound/pci/als4000.c b/ANDROID_3.4.5/sound/pci/als4000.c deleted file mode 100644 index 3269b801..00000000 --- a/ANDROID_3.4.5/sound/pci/als4000.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * card-als4000.c - driver for Avance Logic ALS4000 based soundcards. - * Copyright (C) 2000 by Bart Hartgers , - * Jaroslav Kysela - * Copyright (C) 2002, 2008 by Andreas Mohr - * - * Framework borrowed from Massimo Piccioni's card-als100.c. - * - * - * 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 - * - * NOTES - * - * Since Avance does not provide any meaningful documentation, and I - * bought an ALS4000 based soundcard, I was forced to base this driver - * on reverse engineering. - * - * Note: this is no longer true (thank you!): - * pretty verbose chip docu (ALS4000a.PDF) can be found on the ALSA web site. - * Page numbers stated anywhere below with the "SPECS_PAGE:" tag - * refer to: ALS4000a.PDF specs Ver 1.0, May 28th, 1998. - * - * The ALS4000 seems to be the PCI-cousin of the ALS100. It contains an - * ALS100-like SB DSP/mixer, an OPL3 synth, a MPU401 and a gameport - * interface. These subsystems can be mapped into ISA io-port space, - * using the PCI-interface. In addition, the PCI-bit provides DMA and IRQ - * services to the subsystems. - * - * While ALS4000 is very similar to a SoundBlaster, the differences in - * DMA and capturing require more changes to the SoundBlaster than - * desirable, so I made this separate driver. - * - * The ALS4000 can do real full duplex playback/capture. - * - * FMDAC: - * - 0x4f -> port 0x14 - * - port 0x15 |= 1 - * - * Enable/disable 3D sound: - * - 0x50 -> port 0x14 - * - change bit 6 (0x40) of port 0x15 - * - * Set QSound: - * - 0xdb -> port 0x14 - * - set port 0x15: - * 0x3e (mode 3), 0x3c (mode 2), 0x3a (mode 1), 0x38 (mode 0) - * - * Set KSound: - * - value -> some port 0x0c0d - * - * ToDo: - * - by default, don't enable legacy game and use PCI game I/O - * - power management? (card can do voice wakeup according to datasheet!!) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Bart Hartgers , Andreas Mohr"); -MODULE_DESCRIPTION("Avance Logic ALS4000"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}"); - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -#ifdef SUPPORT_JOYSTICK -static int joystick_port[SNDRV_CARDS]; -#endif - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ALS4000 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ALS4000 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ALS4000 soundcard."); -#ifdef SUPPORT_JOYSTICK -module_param_array(joystick_port, int, NULL, 0444); -MODULE_PARM_DESC(joystick_port, "Joystick port address for ALS4000 soundcard. (0 = disabled)"); -#endif - -struct snd_card_als4000 { - /* most frequent access first */ - unsigned long iobase; - struct pci_dev *pci; - struct snd_sb *chip; -#ifdef SUPPORT_JOYSTICK - struct gameport *gameport; -#endif -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_als4000_ids) = { - { 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ALS4000 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_als4000_ids); - -enum als4k_iobase_t { - /* IOx: B == Byte, W = Word, D = DWord; SPECS_PAGE: 37 */ - ALS4K_IOD_00_AC97_ACCESS = 0x00, - ALS4K_IOW_04_AC97_READ = 0x04, - ALS4K_IOB_06_AC97_STATUS = 0x06, - ALS4K_IOB_07_IRQSTATUS = 0x07, - ALS4K_IOD_08_GCR_DATA = 0x08, - ALS4K_IOB_0C_GCR_INDEX = 0x0c, - ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU = 0x0e, - ALS4K_IOB_10_ADLIB_ADDR0 = 0x10, - ALS4K_IOB_11_ADLIB_ADDR1 = 0x11, - ALS4K_IOB_12_ADLIB_ADDR2 = 0x12, - ALS4K_IOB_13_ADLIB_ADDR3 = 0x13, - ALS4K_IOB_14_MIXER_INDEX = 0x14, - ALS4K_IOB_15_MIXER_DATA = 0x15, - ALS4K_IOB_16_ESP_RESET = 0x16, - ALS4K_IOB_16_ACK_FOR_CR1E = 0x16, /* 2nd function */ - ALS4K_IOB_18_OPL_ADDR0 = 0x18, - ALS4K_IOB_19_OPL_ADDR1 = 0x19, - ALS4K_IOB_1A_ESP_RD_DATA = 0x1a, - ALS4K_IOB_1C_ESP_CMD_DATA = 0x1c, - ALS4K_IOB_1C_ESP_WR_STATUS = 0x1c, /* 2nd function */ - ALS4K_IOB_1E_ESP_RD_STATUS8 = 0x1e, - ALS4K_IOB_1F_ESP_RD_STATUS16 = 0x1f, - ALS4K_IOB_20_ESP_GAMEPORT_200 = 0x20, - ALS4K_IOB_21_ESP_GAMEPORT_201 = 0x21, - ALS4K_IOB_30_MIDI_DATA = 0x30, - ALS4K_IOB_31_MIDI_STATUS = 0x31, - ALS4K_IOB_31_MIDI_COMMAND = 0x31, /* 2nd function */ -}; - -enum als4k_iobase_0e_t { - ALS4K_IOB_0E_MPU_IRQ = 0x10, - ALS4K_IOB_0E_CR1E_IRQ = 0x40, - ALS4K_IOB_0E_SB_DMA_IRQ = 0x80, -}; - -enum als4k_gcr_t { /* all registers 32bit wide; SPECS_PAGE: 38 to 42 */ - ALS4K_GCR8C_MISC_CTRL = 0x8c, - ALS4K_GCR90_TEST_MODE_REG = 0x90, - ALS4K_GCR91_DMA0_ADDR = 0x91, - ALS4K_GCR92_DMA0_MODE_COUNT = 0x92, - ALS4K_GCR93_DMA1_ADDR = 0x93, - ALS4K_GCR94_DMA1_MODE_COUNT = 0x94, - ALS4K_GCR95_DMA3_ADDR = 0x95, - ALS4K_GCR96_DMA3_MODE_COUNT = 0x96, - ALS4K_GCR99_DMA_EMULATION_CTRL = 0x99, - ALS4K_GCRA0_FIFO1_CURRENT_ADDR = 0xa0, - ALS4K_GCRA1_FIFO1_STATUS_BYTECOUNT = 0xa1, - ALS4K_GCRA2_FIFO2_PCIADDR = 0xa2, - ALS4K_GCRA3_FIFO2_COUNT = 0xa3, - ALS4K_GCRA4_FIFO2_CURRENT_ADDR = 0xa4, - ALS4K_GCRA5_FIFO1_STATUS_BYTECOUNT = 0xa5, - ALS4K_GCRA6_PM_CTRL = 0xa6, - ALS4K_GCRA7_PCI_ACCESS_STORAGE = 0xa7, - ALS4K_GCRA8_LEGACY_CFG1 = 0xa8, - ALS4K_GCRA9_LEGACY_CFG2 = 0xa9, - ALS4K_GCRFF_DUMMY_SCRATCH = 0xff, -}; - -enum als4k_gcr8c_t { - ALS4K_GCR8C_IRQ_MASK_CTRL_ENABLE = 0x8000, - ALS4K_GCR8C_CHIP_REV_MASK = 0xf0000 -}; - -static inline void snd_als4k_iobase_writeb(unsigned long iobase, - enum als4k_iobase_t reg, - u8 val) -{ - outb(val, iobase + reg); -} - -static inline void snd_als4k_iobase_writel(unsigned long iobase, - enum als4k_iobase_t reg, - u32 val) -{ - outl(val, iobase + reg); -} - -static inline u8 snd_als4k_iobase_readb(unsigned long iobase, - enum als4k_iobase_t reg) -{ - return inb(iobase + reg); -} - -static inline u32 snd_als4k_iobase_readl(unsigned long iobase, - enum als4k_iobase_t reg) -{ - return inl(iobase + reg); -} - -static inline void snd_als4k_gcr_write_addr(unsigned long iobase, - enum als4k_gcr_t reg, - u32 val) -{ - snd_als4k_iobase_writeb(iobase, ALS4K_IOB_0C_GCR_INDEX, reg); - snd_als4k_iobase_writel(iobase, ALS4K_IOD_08_GCR_DATA, val); -} - -static inline void snd_als4k_gcr_write(struct snd_sb *sb, - enum als4k_gcr_t reg, - u32 val) -{ - snd_als4k_gcr_write_addr(sb->alt_port, reg, val); -} - -static inline u32 snd_als4k_gcr_read_addr(unsigned long iobase, - enum als4k_gcr_t reg) -{ - /* SPECS_PAGE: 37/38 */ - snd_als4k_iobase_writeb(iobase, ALS4K_IOB_0C_GCR_INDEX, reg); - return snd_als4k_iobase_readl(iobase, ALS4K_IOD_08_GCR_DATA); -} - -static inline u32 snd_als4k_gcr_read(struct snd_sb *sb, enum als4k_gcr_t reg) -{ - return snd_als4k_gcr_read_addr(sb->alt_port, reg); -} - -enum als4k_cr_t { /* all registers 8bit wide; SPECS_PAGE: 20 to 23 */ - ALS4K_CR0_SB_CONFIG = 0x00, - ALS4K_CR2_MISC_CONTROL = 0x02, - ALS4K_CR3_CONFIGURATION = 0x03, - ALS4K_CR17_FIFO_STATUS = 0x17, - ALS4K_CR18_ESP_MAJOR_VERSION = 0x18, - ALS4K_CR19_ESP_MINOR_VERSION = 0x19, - ALS4K_CR1A_MPU401_UART_MODE_CONTROL = 0x1a, - ALS4K_CR1C_FIFO2_BLOCK_LENGTH_LO = 0x1c, - ALS4K_CR1D_FIFO2_BLOCK_LENGTH_HI = 0x1d, - ALS4K_CR1E_FIFO2_CONTROL = 0x1e, /* secondary PCM FIFO (recording) */ - ALS4K_CR3A_MISC_CONTROL = 0x3a, - ALS4K_CR3B_CRC32_BYTE0 = 0x3b, /* for testing, activate via CR3A */ - ALS4K_CR3C_CRC32_BYTE1 = 0x3c, - ALS4K_CR3D_CRC32_BYTE2 = 0x3d, - ALS4K_CR3E_CRC32_BYTE3 = 0x3e, -}; - -enum als4k_cr0_t { - ALS4K_CR0_DMA_CONTIN_MODE_CTRL = 0x02, /* IRQ/FIFO controlled for 0/1 */ - ALS4K_CR0_DMA_90H_MODE_CTRL = 0x04, /* IRQ/FIFO controlled for 0/1 */ - ALS4K_CR0_MX80_81_REG_WRITE_ENABLE = 0x80, -}; - -static inline void snd_als4_cr_write(struct snd_sb *chip, - enum als4k_cr_t reg, - u8 data) -{ - /* Control Register is reg | 0xc0 (bit 7, 6 set) on sbmixer_index - * NOTE: assumes chip->mixer_lock to be locked externally already! - * SPECS_PAGE: 6 */ - snd_sbmixer_write(chip, reg | 0xc0, data); -} - -static inline u8 snd_als4_cr_read(struct snd_sb *chip, - enum als4k_cr_t reg) -{ - /* NOTE: assumes chip->mixer_lock to be locked externally already! */ - return snd_sbmixer_read(chip, reg | 0xc0); -} - - - -static void snd_als4000_set_rate(struct snd_sb *chip, unsigned int rate) -{ - if (!(chip->mode & SB_RATE_LOCK)) { - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_OUT); - snd_sbdsp_command(chip, rate>>8); - snd_sbdsp_command(chip, rate); - } -} - -static inline void snd_als4000_set_capture_dma(struct snd_sb *chip, - dma_addr_t addr, unsigned size) -{ - /* SPECS_PAGE: 40 */ - snd_als4k_gcr_write(chip, ALS4K_GCRA2_FIFO2_PCIADDR, addr); - snd_als4k_gcr_write(chip, ALS4K_GCRA3_FIFO2_COUNT, (size-1)); -} - -static inline void snd_als4000_set_playback_dma(struct snd_sb *chip, - dma_addr_t addr, - unsigned size) -{ - /* SPECS_PAGE: 38 */ - snd_als4k_gcr_write(chip, ALS4K_GCR91_DMA0_ADDR, addr); - snd_als4k_gcr_write(chip, ALS4K_GCR92_DMA0_MODE_COUNT, - (size-1)|0x180000); -} - -#define ALS4000_FORMAT_SIGNED (1<<0) -#define ALS4000_FORMAT_16BIT (1<<1) -#define ALS4000_FORMAT_STEREO (1<<2) - -static int snd_als4000_get_format(struct snd_pcm_runtime *runtime) -{ - int result; - - result = 0; - if (snd_pcm_format_signed(runtime->format)) - result |= ALS4000_FORMAT_SIGNED; - if (snd_pcm_format_physical_width(runtime->format) == 16) - result |= ALS4000_FORMAT_16BIT; - if (runtime->channels > 1) - result |= ALS4000_FORMAT_STEREO; - return result; -} - -/* structure for setting up playback */ -static const struct { - unsigned char dsp_cmd, dma_on, dma_off, format; -} playback_cmd_vals[]={ -/* ALS4000_FORMAT_U8_MONO */ -{ SB_DSP4_OUT8_AI, SB_DSP_DMA8_ON, SB_DSP_DMA8_OFF, SB_DSP4_MODE_UNS_MONO }, -/* ALS4000_FORMAT_S8_MONO */ -{ SB_DSP4_OUT8_AI, SB_DSP_DMA8_ON, SB_DSP_DMA8_OFF, SB_DSP4_MODE_SIGN_MONO }, -/* ALS4000_FORMAT_U16L_MONO */ -{ SB_DSP4_OUT16_AI, SB_DSP_DMA16_ON, SB_DSP_DMA16_OFF, SB_DSP4_MODE_UNS_MONO }, -/* ALS4000_FORMAT_S16L_MONO */ -{ SB_DSP4_OUT16_AI, SB_DSP_DMA16_ON, SB_DSP_DMA16_OFF, SB_DSP4_MODE_SIGN_MONO }, -/* ALS4000_FORMAT_U8_STEREO */ -{ SB_DSP4_OUT8_AI, SB_DSP_DMA8_ON, SB_DSP_DMA8_OFF, SB_DSP4_MODE_UNS_STEREO }, -/* ALS4000_FORMAT_S8_STEREO */ -{ SB_DSP4_OUT8_AI, SB_DSP_DMA8_ON, SB_DSP_DMA8_OFF, SB_DSP4_MODE_SIGN_STEREO }, -/* ALS4000_FORMAT_U16L_STEREO */ -{ SB_DSP4_OUT16_AI, SB_DSP_DMA16_ON, SB_DSP_DMA16_OFF, SB_DSP4_MODE_UNS_STEREO }, -/* ALS4000_FORMAT_S16L_STEREO */ -{ SB_DSP4_OUT16_AI, SB_DSP_DMA16_ON, SB_DSP_DMA16_OFF, SB_DSP4_MODE_SIGN_STEREO }, -}; -#define playback_cmd(chip) (playback_cmd_vals[(chip)->playback_format]) - -/* structure for setting up capture */ -enum { CMD_WIDTH8=0x04, CMD_SIGNED=0x10, CMD_MONO=0x80, CMD_STEREO=0xA0 }; -static const unsigned char capture_cmd_vals[]= -{ -CMD_WIDTH8|CMD_MONO, /* ALS4000_FORMAT_U8_MONO */ -CMD_WIDTH8|CMD_SIGNED|CMD_MONO, /* ALS4000_FORMAT_S8_MONO */ -CMD_MONO, /* ALS4000_FORMAT_U16L_MONO */ -CMD_SIGNED|CMD_MONO, /* ALS4000_FORMAT_S16L_MONO */ -CMD_WIDTH8|CMD_STEREO, /* ALS4000_FORMAT_U8_STEREO */ -CMD_WIDTH8|CMD_SIGNED|CMD_STEREO, /* ALS4000_FORMAT_S8_STEREO */ -CMD_STEREO, /* ALS4000_FORMAT_U16L_STEREO */ -CMD_SIGNED|CMD_STEREO, /* ALS4000_FORMAT_S16L_STEREO */ -}; -#define capture_cmd(chip) (capture_cmd_vals[(chip)->capture_format]) - -static int snd_als4000_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_als4000_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_als4000_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long size; - unsigned count; - - chip->capture_format = snd_als4000_get_format(runtime); - - size = snd_pcm_lib_buffer_bytes(substream); - count = snd_pcm_lib_period_bytes(substream); - - if (chip->capture_format & ALS4000_FORMAT_16BIT) - count >>= 1; - count--; - - spin_lock_irq(&chip->reg_lock); - snd_als4000_set_rate(chip, runtime->rate); - snd_als4000_set_capture_dma(chip, runtime->dma_addr, size); - spin_unlock_irq(&chip->reg_lock); - spin_lock_irq(&chip->mixer_lock); - snd_als4_cr_write(chip, ALS4K_CR1C_FIFO2_BLOCK_LENGTH_LO, count & 0xff); - snd_als4_cr_write(chip, ALS4K_CR1D_FIFO2_BLOCK_LENGTH_HI, count >> 8); - spin_unlock_irq(&chip->mixer_lock); - return 0; -} - -static int snd_als4000_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long size; - unsigned count; - - chip->playback_format = snd_als4000_get_format(runtime); - - size = snd_pcm_lib_buffer_bytes(substream); - count = snd_pcm_lib_period_bytes(substream); - - if (chip->playback_format & ALS4000_FORMAT_16BIT) - count >>= 1; - count--; - - /* FIXME: from second playback on, there's a lot more clicks and pops - * involved here than on first playback. Fiddling with - * tons of different settings didn't help (DMA, speaker on/off, - * reordering, ...). Something seems to get enabled on playback - * that I haven't found out how to disable again, which then causes - * the switching pops to reach the speakers the next time here. */ - spin_lock_irq(&chip->reg_lock); - snd_als4000_set_rate(chip, runtime->rate); - snd_als4000_set_playback_dma(chip, runtime->dma_addr, size); - - /* SPEAKER_ON not needed, since dma_on seems to also enable speaker */ - /* snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); */ - snd_sbdsp_command(chip, playback_cmd(chip).dsp_cmd); - snd_sbdsp_command(chip, playback_cmd(chip).format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, playback_cmd(chip).dma_off); - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - -static int snd_als4000_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - int result = 0; - - /* FIXME race condition in here!!! - chip->mode non-atomic update gets consistently protected - by reg_lock always, _except_ for this place!! - Probably need to take reg_lock as outer (or inner??) lock, too. - (or serialize both lock operations? probably not, though... - racy?) - */ - spin_lock(&chip->mixer_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - chip->mode |= SB_RATE_LOCK_CAPTURE; - snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL, - capture_cmd(chip)); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - chip->mode &= ~SB_RATE_LOCK_CAPTURE; - snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL, - capture_cmd(chip)); - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&chip->mixer_lock); - return result; -} - -static int snd_als4000_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - int result = 0; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - chip->mode |= SB_RATE_LOCK_PLAYBACK; - snd_sbdsp_command(chip, playback_cmd(chip).dma_on); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_sbdsp_command(chip, playback_cmd(chip).dma_off); - chip->mode &= ~SB_RATE_LOCK_PLAYBACK; - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&chip->reg_lock); - return result; -} - -static snd_pcm_uframes_t snd_als4000_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int result; - - spin_lock(&chip->reg_lock); - result = snd_als4k_gcr_read(chip, ALS4K_GCRA4_FIFO2_CURRENT_ADDR); - spin_unlock(&chip->reg_lock); - result &= 0xffff; - return bytes_to_frames( substream->runtime, result ); -} - -static snd_pcm_uframes_t snd_als4000_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned result; - - spin_lock(&chip->reg_lock); - result = snd_als4k_gcr_read(chip, ALS4K_GCRA0_FIFO1_CURRENT_ADDR); - spin_unlock(&chip->reg_lock); - result &= 0xffff; - return bytes_to_frames( substream->runtime, result ); -} - -/* FIXME: this IRQ routine doesn't really support IRQ sharing (we always - * return IRQ_HANDLED no matter whether we actually had an IRQ flag or not). - * ALS4000a.PDF writes that while ACKing IRQ in PCI block will *not* ACK - * the IRQ in the SB core, ACKing IRQ in SB block *will* ACK the PCI IRQ - * register (alt_port + ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU). Probably something - * could be optimized here to query/write one register only... - * And even if both registers need to be queried, then there's still the - * question of whether it's actually correct to ACK PCI IRQ before reading - * SB IRQ like we do now, since ALS4000a.PDF mentions that PCI IRQ will *clear* - * SB IRQ status. - * (hmm, SPECS_PAGE: 38 mentions it the other way around!) - * And do we *really* need the lock here for *reading* SB_DSP4_IRQSTATUS?? - * */ -static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id) -{ - struct snd_sb *chip = dev_id; - unsigned pci_irqstatus; - unsigned sb_irqstatus; - - /* find out which bit of the ALS4000 PCI block produced the interrupt, - SPECS_PAGE: 38, 5 */ - pci_irqstatus = snd_als4k_iobase_readb(chip->alt_port, - ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU); - if ((pci_irqstatus & ALS4K_IOB_0E_SB_DMA_IRQ) - && (chip->playback_substream)) /* playback */ - snd_pcm_period_elapsed(chip->playback_substream); - if ((pci_irqstatus & ALS4K_IOB_0E_CR1E_IRQ) - && (chip->capture_substream)) /* capturing */ - snd_pcm_period_elapsed(chip->capture_substream); - if ((pci_irqstatus & ALS4K_IOB_0E_MPU_IRQ) - && (chip->rmidi)) /* MPU401 interrupt */ - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - /* ACK the PCI block IRQ */ - snd_als4k_iobase_writeb(chip->alt_port, - ALS4K_IOB_0E_IRQTYPE_SB_CR1E_MPU, pci_irqstatus); - - spin_lock(&chip->mixer_lock); - /* SPECS_PAGE: 20 */ - sb_irqstatus = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); - spin_unlock(&chip->mixer_lock); - - if (sb_irqstatus & SB_IRQTYPE_8BIT) - snd_sb_ack_8bit(chip); - if (sb_irqstatus & SB_IRQTYPE_16BIT) - snd_sb_ack_16bit(chip); - if (sb_irqstatus & SB_IRQTYPE_MPUIN) - inb(chip->mpu_port); - if (sb_irqstatus & ALS4K_IRQTYPE_CR1E_DMA) - snd_als4k_iobase_readb(chip->alt_port, - ALS4K_IOB_16_ACK_FOR_CR1E); - - /* printk(KERN_INFO "als4000: irq 0x%04x 0x%04x\n", - pci_irqstatus, sb_irqstatus); */ - - /* only ack the things we actually handled above */ - return IRQ_RETVAL( - (pci_irqstatus & (ALS4K_IOB_0E_SB_DMA_IRQ|ALS4K_IOB_0E_CR1E_IRQ| - ALS4K_IOB_0E_MPU_IRQ)) - || (sb_irqstatus & (SB_IRQTYPE_8BIT|SB_IRQTYPE_16BIT| - SB_IRQTYPE_MPUIN|ALS4K_IRQTYPE_CR1E_DMA)) - ); -} - -/*****************************************************************/ - -static struct snd_pcm_hardware snd_als4000_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE, /* formats */ - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0 -}; - -static struct snd_pcm_hardware snd_als4000_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE, /* formats */ - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0 -}; - -/*****************************************************************/ - -static int snd_als4000_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - chip->playback_substream = substream; - runtime->hw = snd_als4000_playback; - return 0; -} - -static int snd_als4000_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_als4000_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - chip->capture_substream = substream; - runtime->hw = snd_als4000_capture; - return 0; -} - -static int snd_als4000_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - snd_pcm_lib_free_pages(substream); - return 0; -} - -/******************************************************************/ - -static struct snd_pcm_ops snd_als4000_playback_ops = { - .open = snd_als4000_playback_open, - .close = snd_als4000_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_als4000_hw_params, - .hw_free = snd_als4000_hw_free, - .prepare = snd_als4000_playback_prepare, - .trigger = snd_als4000_playback_trigger, - .pointer = snd_als4000_playback_pointer -}; - -static struct snd_pcm_ops snd_als4000_capture_ops = { - .open = snd_als4000_capture_open, - .close = snd_als4000_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_als4000_hw_params, - .hw_free = snd_als4000_hw_free, - .prepare = snd_als4000_capture_prepare, - .trigger = snd_als4000_capture_trigger, - .pointer = snd_als4000_capture_pointer -}; - -static int __devinit snd_als4000_pcm(struct snd_sb *chip, int device) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(chip->card, "ALS4000 DSP", device, 1, 1, &pcm); - if (err < 0) - return err; - pcm->private_data = chip; - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_als4000_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_als4000_capture_ops); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - 64*1024, 64*1024); - - chip->pcm = pcm; - - return 0; -} - -/******************************************************************/ - -static void snd_als4000_set_addr(unsigned long iobase, - unsigned int sb_io, - unsigned int mpu_io, - unsigned int opl_io, - unsigned int game_io) -{ - u32 cfg1 = 0; - u32 cfg2 = 0; - - if (mpu_io > 0) - cfg2 |= (mpu_io | 1) << 16; - if (sb_io > 0) - cfg2 |= (sb_io | 1); - if (game_io > 0) - cfg1 |= (game_io | 1) << 16; - if (opl_io > 0) - cfg1 |= (opl_io | 1); - snd_als4k_gcr_write_addr(iobase, ALS4K_GCRA8_LEGACY_CFG1, cfg1); - snd_als4k_gcr_write_addr(iobase, ALS4K_GCRA9_LEGACY_CFG2, cfg2); -} - -static void snd_als4000_configure(struct snd_sb *chip) -{ - u8 tmp; - int i; - - /* do some more configuration */ - spin_lock_irq(&chip->mixer_lock); - tmp = snd_als4_cr_read(chip, ALS4K_CR0_SB_CONFIG); - snd_als4_cr_write(chip, ALS4K_CR0_SB_CONFIG, - tmp|ALS4K_CR0_MX80_81_REG_WRITE_ENABLE); - /* always select DMA channel 0, since we do not actually use DMA - * SPECS_PAGE: 19/20 */ - snd_sbmixer_write(chip, SB_DSP4_DMASETUP, SB_DMASETUP_DMA0); - snd_als4_cr_write(chip, ALS4K_CR0_SB_CONFIG, - tmp & ~ALS4K_CR0_MX80_81_REG_WRITE_ENABLE); - spin_unlock_irq(&chip->mixer_lock); - - spin_lock_irq(&chip->reg_lock); - /* enable interrupts */ - snd_als4k_gcr_write(chip, ALS4K_GCR8C_MISC_CTRL, - ALS4K_GCR8C_IRQ_MASK_CTRL_ENABLE); - - /* SPECS_PAGE: 39 */ - for (i = ALS4K_GCR91_DMA0_ADDR; i <= ALS4K_GCR96_DMA3_MODE_COUNT; ++i) - snd_als4k_gcr_write(chip, i, 0); - /* enable burst mode to prevent dropouts during high PCI bus usage */ - snd_als4k_gcr_write(chip, ALS4K_GCR99_DMA_EMULATION_CTRL, - (snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL) & ~0x07) | 0x04); - spin_unlock_irq(&chip->reg_lock); -} - -#ifdef SUPPORT_JOYSTICK -static int __devinit snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev) -{ - struct gameport *gp; - struct resource *r; - int io_port; - - if (joystick_port[dev] == 0) - return -ENODEV; - - if (joystick_port[dev] == 1) { /* auto-detect */ - for (io_port = 0x200; io_port <= 0x218; io_port += 8) { - r = request_region(io_port, 8, "ALS4000 gameport"); - if (r) - break; - } - } else { - io_port = joystick_port[dev]; - r = request_region(io_port, 8, "ALS4000 gameport"); - } - - if (!r) { - printk(KERN_WARNING "als4000: cannot reserve joystick ports\n"); - return -EBUSY; - } - - acard->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "als4000: cannot allocate memory for gameport\n"); - release_and_free_resource(r); - return -ENOMEM; - } - - gameport_set_name(gp, "ALS4000 Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci)); - gameport_set_dev_parent(gp, &acard->pci->dev); - gp->io = io_port; - gameport_set_port_data(gp, r); - - /* Enable legacy joystick port */ - snd_als4000_set_addr(acard->iobase, 0, 0, 0, 1); - - gameport_register_port(acard->gameport); - - return 0; -} - -static void snd_als4000_free_gameport(struct snd_card_als4000 *acard) -{ - if (acard->gameport) { - struct resource *r = gameport_get_port_data(acard->gameport); - - gameport_unregister_port(acard->gameport); - acard->gameport = NULL; - - /* disable joystick */ - snd_als4000_set_addr(acard->iobase, 0, 0, 0, 0); - - release_and_free_resource(r); - } -} -#else -static inline int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev) { return -ENOSYS; } -static inline void snd_als4000_free_gameport(struct snd_card_als4000 *acard) { } -#endif - -static void snd_card_als4000_free( struct snd_card *card ) -{ - struct snd_card_als4000 *acard = card->private_data; - - /* make sure that interrupts are disabled */ - snd_als4k_gcr_write_addr(acard->iobase, ALS4K_GCR8C_MISC_CTRL, 0); - /* free resources */ - snd_als4000_free_gameport(acard); - pci_release_regions(acard->pci); - pci_disable_device(acard->pci); -} - -static int __devinit snd_card_als4000_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_card_als4000 *acard; - unsigned long iobase; - struct snd_sb *chip; - struct snd_opl3 *opl3; - unsigned short word; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) { - return err; - } - /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { - snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - if ((err = pci_request_regions(pci, "ALS4000")) < 0) { - pci_disable_device(pci); - return err; - } - iobase = pci_resource_start(pci, 0); - - pci_read_config_word(pci, PCI_COMMAND, &word); - pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO); - pci_set_master(pci); - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(*acard) /* private_data: acard */, - &card); - if (err < 0) { - pci_release_regions(pci); - pci_disable_device(pci); - return err; - } - - acard = card->private_data; - acard->pci = pci; - acard->iobase = iobase; - card->private_free = snd_card_als4000_free; - - /* disable all legacy ISA stuff */ - snd_als4000_set_addr(acard->iobase, 0, 0, 0, 0); - - if ((err = snd_sbdsp_create(card, - iobase + ALS4K_IOB_10_ADLIB_ADDR0, - pci->irq, - /* internally registered as IRQF_SHARED in case of ALS4000 SB */ - snd_als4000_interrupt, - -1, - -1, - SB_HW_ALS4000, - &chip)) < 0) { - goto out_err; - } - acard->chip = chip; - - chip->pci = pci; - chip->alt_port = iobase; - snd_card_set_dev(card, &pci->dev); - - snd_als4000_configure(chip); - - strcpy(card->driver, "ALS4000"); - strcpy(card->shortname, "Avance Logic ALS4000"); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, chip->alt_port, chip->irq); - - if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, - iobase + ALS4K_IOB_30_MIDI_DATA, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi)) < 0) { - printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", - iobase + ALS4K_IOB_30_MIDI_DATA); - goto out_err; - } - /* FIXME: ALS4000 has interesting MPU401 configuration features - * at ALS4K_CR1A_MPU401_UART_MODE_CONTROL - * (pass-thru / UART switching, fast MIDI clock, etc.), - * however there doesn't seem to be an ALSA API for this... - * SPECS_PAGE: 21 */ - - if ((err = snd_als4000_pcm(chip, 0)) < 0) { - goto out_err; - } - if ((err = snd_sbmixer_new(chip)) < 0) { - goto out_err; - } - - if (snd_opl3_create(card, - iobase + ALS4K_IOB_10_ADLIB_ADDR0, - iobase + ALS4K_IOB_12_ADLIB_ADDR2, - OPL3_HW_AUTO, 1, &opl3) < 0) { - printk(KERN_ERR "als4000: no OPL device at 0x%lx-0x%lx?\n", - iobase + ALS4K_IOB_10_ADLIB_ADDR0, - iobase + ALS4K_IOB_12_ADLIB_ADDR2); - } else { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - goto out_err; - } - } - - snd_als4000_create_gameport(acard, dev); - - if ((err = snd_card_register(card)) < 0) { - goto out_err; - } - pci_set_drvdata(pci, card); - dev++; - err = 0; - goto out; - -out_err: - snd_card_free(card); - -out: - return err; -} - -static void __devexit snd_card_als4000_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -#ifdef CONFIG_PM -static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_card_als4000 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_als4000_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_card_als4000 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "als4000: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_als4000_configure(chip); - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - -#ifdef SUPPORT_JOYSTICK - if (acard->gameport) - snd_als4000_set_addr(acard->iobase, 0, 0, 0, 1); -#endif - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_als4000_ids, - .probe = snd_card_als4000_probe, - .remove = __devexit_p(snd_card_als4000_remove), -#ifdef CONFIG_PM - .suspend = snd_als4000_suspend, - .resume = snd_als4000_resume, -#endif -}; - -static int __init alsa_card_als4000_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_als4000_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_als4000_init) -module_exit(alsa_card_als4000_exit) diff --git a/ANDROID_3.4.5/sound/pci/asihpi/Makefile b/ANDROID_3.4.5/sound/pci/asihpi/Makefile deleted file mode 100644 index 391830a4..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -snd-asihpi-objs := asihpi.o hpioctl.o hpimsginit.o\ - hpicmn.o hpifunc.o hpidebug.o hpidspcd.o\ - hpios.o hpi6000.o hpi6205.o hpimsgx.o - -obj-$(CONFIG_SND_ASIHPI) += snd-asihpi.o diff --git a/ANDROID_3.4.5/sound/pci/asihpi/asihpi.c b/ANDROID_3.4.5/sound/pci/asihpi/asihpi.c deleted file mode 100644 index e8de831f..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/asihpi.c +++ /dev/null @@ -1,2992 +0,0 @@ -/* - * Asihpi soundcard - * Copyright (c) by AudioScience Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation; - * - * 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 - * - * - * The following is not a condition of use, merely a request: - * If you modify this program, particularly if you fix errors, AudioScience Inc - * would appreciate it if you grant us the right to use those modifications - * for any purpose including commercial applications. - */ - -#include "hpi_internal.h" -#include "hpi_version.h" -#include "hpimsginit.h" -#include "hpioctl.h" -#include "hpicmn.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("AudioScience inc. "); -MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx " - HPI_VER_STRING); - -#if defined CONFIG_SND_DEBUG_VERBOSE -/** - * snd_printddd - very verbose debug printk - * @format: format string - * - * Works like snd_printk() for debugging purposes. - * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set. - * Must set snd module debug parameter to 3 to enable at runtime. - */ -#define snd_printddd(format, args...) \ - __snd_printk(3, __FILE__, __LINE__, format, ##args) -#else -#define snd_printddd(format, args...) do { } while (0) -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static bool enable_hpi_hwdep = 1; - -module_param_array(index, int, NULL, S_IRUGO); -MODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard."); - -module_param_array(id, charp, NULL, S_IRUGO); -MODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard."); - -module_param_array(enable, bool, NULL, S_IRUGO); -MODULE_PARM_DESC(enable, "ALSA enable AudioScience soundcard."); - -module_param(enable_hpi_hwdep, bool, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(enable_hpi_hwdep, - "ALSA enable HPI hwdep for AudioScience soundcard "); - -/* identify driver */ -#ifdef KERNEL_ALSA_BUILD -static char *build_info = "Built using headers from kernel source"; -module_param(build_info, charp, S_IRUGO); -MODULE_PARM_DESC(build_info, "built using headers from kernel source"); -#else -static char *build_info = "Built within ALSA source"; -module_param(build_info, charp, S_IRUGO); -MODULE_PARM_DESC(build_info, "built within ALSA source"); -#endif - -/* set to 1 to dump every control from adapter to log */ -static const int mixer_dump; - -#define DEFAULT_SAMPLERATE 44100 -static int adapter_fs = DEFAULT_SAMPLERATE; - -/* defaults */ -#define PERIODS_MIN 2 -#define PERIOD_BYTES_MIN 2048 -#define BUFFER_BYTES_MAX (512 * 1024) - -#define MAX_CLOCKSOURCES (HPI_SAMPLECLOCK_SOURCE_LAST + 1 + 7) - -struct clk_source { - int source; - int index; - char *name; -}; - -struct clk_cache { - int count; - int has_local; - struct clk_source s[MAX_CLOCKSOURCES]; -}; - -/* Per card data */ -struct snd_card_asihpi { - struct snd_card *card; - struct pci_dev *pci; - struct hpi_adapter *hpi; - - u32 h_mixer; - struct clk_cache cc; - - u16 can_dma; - u16 support_grouping; - u16 support_mrx; - u16 update_interval_frames; - u16 in_max_chans; - u16 out_max_chans; - u16 in_min_chans; - u16 out_min_chans; -}; - -/* Per stream data */ -struct snd_card_asihpi_pcm { - struct timer_list timer; - unsigned int respawn_timer; - unsigned int hpi_buffer_attached; - unsigned int buffer_bytes; - unsigned int period_bytes; - unsigned int bytes_per_sec; - unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */ - unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */ - unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */ - unsigned int drained_count; - struct snd_pcm_substream *substream; - u32 h_stream; - struct hpi_format format; -}; - -/* universal stream verbs work with out or in stream handles */ - -/* Functions to allow driver to give a buffer to HPI for busmastering */ - -static u16 hpi_stream_host_buffer_attach( - u32 h_stream, /* handle to outstream. */ - u32 size_in_bytes, /* size in bytes of bus mastering buffer */ - u32 pci_address -) -{ - struct hpi_message hm; - struct hpi_response hr; - unsigned int obj = hpi_handle_object(h_stream); - - if (!h_stream) - return HPI_ERROR_INVALID_OBJ; - hpi_init_message_response(&hm, &hr, obj, - obj == HPI_OBJ_OSTREAM ? - HPI_OSTREAM_HOSTBUFFER_ALLOC : - HPI_ISTREAM_HOSTBUFFER_ALLOC); - - hpi_handle_to_indexes(h_stream, &hm.adapter_index, - &hm.obj_index); - - hm.u.d.u.buffer.buffer_size = size_in_bytes; - hm.u.d.u.buffer.pci_address = pci_address; - hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -static u16 hpi_stream_host_buffer_detach(u32 h_stream) -{ - struct hpi_message hm; - struct hpi_response hr; - unsigned int obj = hpi_handle_object(h_stream); - - if (!h_stream) - return HPI_ERROR_INVALID_OBJ; - - hpi_init_message_response(&hm, &hr, obj, - obj == HPI_OBJ_OSTREAM ? - HPI_OSTREAM_HOSTBUFFER_FREE : - HPI_ISTREAM_HOSTBUFFER_FREE); - - hpi_handle_to_indexes(h_stream, &hm.adapter_index, - &hm.obj_index); - hm.u.d.u.buffer.command = HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -static inline u16 hpi_stream_start(u32 h_stream) -{ - if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) - return hpi_outstream_start(h_stream); - else - return hpi_instream_start(h_stream); -} - -static inline u16 hpi_stream_stop(u32 h_stream) -{ - if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) - return hpi_outstream_stop(h_stream); - else - return hpi_instream_stop(h_stream); -} - -static inline u16 hpi_stream_get_info_ex( - u32 h_stream, - u16 *pw_state, - u32 *pbuffer_size, - u32 *pdata_in_buffer, - u32 *psample_count, - u32 *pauxiliary_data -) -{ - u16 e; - if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) - e = hpi_outstream_get_info_ex(h_stream, pw_state, - pbuffer_size, pdata_in_buffer, - psample_count, pauxiliary_data); - else - e = hpi_instream_get_info_ex(h_stream, pw_state, - pbuffer_size, pdata_in_buffer, - psample_count, pauxiliary_data); - return e; -} - -static inline u16 hpi_stream_group_add( - u32 h_master, - u32 h_stream) -{ - if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM) - return hpi_outstream_group_add(h_master, h_stream); - else - return hpi_instream_group_add(h_master, h_stream); -} - -static inline u16 hpi_stream_group_reset(u32 h_stream) -{ - if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) - return hpi_outstream_group_reset(h_stream); - else - return hpi_instream_group_reset(h_stream); -} - -static inline u16 hpi_stream_group_get_map( - u32 h_stream, u32 *mo, u32 *mi) -{ - if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) - return hpi_outstream_group_get_map(h_stream, mo, mi); - else - return hpi_instream_group_get_map(h_stream, mo, mi); -} - -static u16 handle_error(u16 err, int line, char *filename) -{ - if (err) - printk(KERN_WARNING - "in file %s, line %d: HPI error %d\n", - filename, line, err); - return err; -} - -#define hpi_handle_error(x) handle_error(x, __LINE__, __FILE__) - -/***************************** GENERAL PCM ****************/ - -static void print_hwparams(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *p) -{ - char name[16]; - snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printd("%s HWPARAMS\n", name); - snd_printd(" samplerate %d Hz\n", params_rate(p)); - snd_printd(" channels %d\n", params_channels(p)); - snd_printd(" format %d\n", params_format(p)); - snd_printd(" subformat %d\n", params_subformat(p)); - snd_printd(" buffer %d B\n", params_buffer_bytes(p)); - snd_printd(" period %d B\n", params_period_bytes(p)); - snd_printd(" access %d\n", params_access(p)); - snd_printd(" period_size %d\n", params_period_size(p)); - snd_printd(" periods %d\n", params_periods(p)); - snd_printd(" buffer_size %d\n", params_buffer_size(p)); - snd_printd(" %d B/s\n", params_rate(p) * - params_channels(p) * - snd_pcm_format_width(params_format(p)) / 8); - -} - -static snd_pcm_format_t hpi_to_alsa_formats[] = { - -1, /* INVALID */ - SNDRV_PCM_FORMAT_U8, /* HPI_FORMAT_PCM8_UNSIGNED 1 */ - SNDRV_PCM_FORMAT_S16, /* HPI_FORMAT_PCM16_SIGNED 2 */ - -1, /* HPI_FORMAT_MPEG_L1 3 */ - SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L2 4 */ - SNDRV_PCM_FORMAT_MPEG, /* HPI_FORMAT_MPEG_L3 5 */ - -1, /* HPI_FORMAT_DOLBY_AC2 6 */ - -1, /* HPI_FORMAT_DOLBY_AC3 7 */ - SNDRV_PCM_FORMAT_S16_BE,/* HPI_FORMAT_PCM16_BIGENDIAN 8 */ - -1, /* HPI_FORMAT_AA_TAGIT1_HITS 9 */ - -1, /* HPI_FORMAT_AA_TAGIT1_INSERTS 10 */ - SNDRV_PCM_FORMAT_S32, /* HPI_FORMAT_PCM32_SIGNED 11 */ - -1, /* HPI_FORMAT_RAW_BITSTREAM 12 */ - -1, /* HPI_FORMAT_AA_TAGIT1_HITS_EX1 13 */ - SNDRV_PCM_FORMAT_FLOAT, /* HPI_FORMAT_PCM32_FLOAT 14 */ -#if 1 - /* ALSA can't handle 3 byte sample size together with power-of-2 - * constraint on buffer_bytes, so disable this format - */ - -1 -#else - /* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */ -#endif -}; - - -static int snd_card_asihpi_format_alsa2hpi(snd_pcm_format_t alsa_format, - u16 *hpi_format) -{ - u16 format; - - for (format = HPI_FORMAT_PCM8_UNSIGNED; - format <= HPI_FORMAT_PCM24_SIGNED; format++) { - if (hpi_to_alsa_formats[format] == alsa_format) { - *hpi_format = format; - return 0; - } - } - - snd_printd(KERN_WARNING "failed match for alsa format %d\n", - alsa_format); - *hpi_format = 0; - return -EINVAL; -} - -static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi, - struct snd_pcm_hardware *pcmhw) -{ - u16 err; - u32 h_control; - u32 sample_rate; - int idx; - unsigned int rate_min = 200000; - unsigned int rate_max = 0; - unsigned int rates = 0; - - if (asihpi->support_mrx) { - rates |= SNDRV_PCM_RATE_CONTINUOUS; - rates |= SNDRV_PCM_RATE_8000_96000; - rate_min = 8000; - rate_max = 100000; - } else { - /* on cards without SRC, - valid rates are determined by sampleclock */ - err = hpi_mixer_get_control(asihpi->h_mixer, - HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, - HPI_CONTROL_SAMPLECLOCK, &h_control); - if (err) { - snd_printk(KERN_ERR - "No local sampleclock, err %d\n", err); - } - - for (idx = -1; idx < 100; idx++) { - if (idx == -1) { - if (hpi_sample_clock_get_sample_rate(h_control, - &sample_rate)) - continue; - } else if (hpi_sample_clock_query_local_rate(h_control, - idx, &sample_rate)) { - break; - } - - rate_min = min(rate_min, sample_rate); - rate_max = max(rate_max, sample_rate); - - switch (sample_rate) { - case 5512: - rates |= SNDRV_PCM_RATE_5512; - break; - case 8000: - rates |= SNDRV_PCM_RATE_8000; - break; - case 11025: - rates |= SNDRV_PCM_RATE_11025; - break; - case 16000: - rates |= SNDRV_PCM_RATE_16000; - break; - case 22050: - rates |= SNDRV_PCM_RATE_22050; - break; - case 32000: - rates |= SNDRV_PCM_RATE_32000; - break; - case 44100: - rates |= SNDRV_PCM_RATE_44100; - break; - case 48000: - rates |= SNDRV_PCM_RATE_48000; - break; - case 64000: - rates |= SNDRV_PCM_RATE_64000; - break; - case 88200: - rates |= SNDRV_PCM_RATE_88200; - break; - case 96000: - rates |= SNDRV_PCM_RATE_96000; - break; - case 176400: - rates |= SNDRV_PCM_RATE_176400; - break; - case 192000: - rates |= SNDRV_PCM_RATE_192000; - break; - default: /* some other rate */ - rates |= SNDRV_PCM_RATE_KNOT; - } - } - } - - pcmhw->rates = rates; - pcmhw->rate_min = rate_min; - pcmhw->rate_max = rate_max; -} - -static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); - int err; - u16 format; - int width; - unsigned int bytes_per_sec; - - print_hwparams(substream, params); - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (err < 0) - return err; - err = snd_card_asihpi_format_alsa2hpi(params_format(params), &format); - if (err) - return err; - - hpi_handle_error(hpi_format_create(&dpcm->format, - params_channels(params), - format, params_rate(params), 0, 0)); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - if (hpi_instream_reset(dpcm->h_stream) != 0) - return -EINVAL; - - if (hpi_instream_set_format( - dpcm->h_stream, &dpcm->format) != 0) - return -EINVAL; - } - - dpcm->hpi_buffer_attached = 0; - if (card->can_dma) { - err = hpi_stream_host_buffer_attach(dpcm->h_stream, - params_buffer_bytes(params), runtime->dma_addr); - if (err == 0) { - snd_printdd( - "stream_host_buffer_attach succeeded %u %lu\n", - params_buffer_bytes(params), - (unsigned long)runtime->dma_addr); - } else { - snd_printd("stream_host_buffer_attach error %d\n", - err); - return -ENOMEM; - } - - err = hpi_stream_get_info_ex(dpcm->h_stream, NULL, - &dpcm->hpi_buffer_attached, - NULL, NULL, NULL); - - snd_printdd("stream_host_buffer_attach status 0x%x\n", - dpcm->hpi_buffer_attached); - - } - bytes_per_sec = params_rate(params) * params_channels(params); - width = snd_pcm_format_width(params_format(params)); - bytes_per_sec *= width; - bytes_per_sec /= 8; - if (width < 0 || bytes_per_sec == 0) - return -EINVAL; - - dpcm->bytes_per_sec = bytes_per_sec; - dpcm->buffer_bytes = params_buffer_bytes(params); - dpcm->period_bytes = params_period_bytes(params); - - return 0; -} - -static int -snd_card_asihpi_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - if (dpcm->hpi_buffer_attached) - hpi_stream_host_buffer_detach(dpcm->h_stream); - - snd_pcm_lib_free_pages(substream); - return 0; -} - -static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime) -{ - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - kfree(dpcm); -} - -static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * - substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - int expiry; - - expiry = HZ / 200; - /*? (dpcm->period_bytes * HZ / dpcm->bytes_per_sec); */ - expiry = max(expiry, 1); /* don't let it be zero! */ - dpcm->timer.expires = jiffies + expiry; - dpcm->respawn_timer = 1; - add_timer(&dpcm->timer); -} - -static void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - - dpcm->respawn_timer = 0; - del_timer(&dpcm->timer); -} - -static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; - struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *s; - u16 e; - char name[16]; - - snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printdd("%s trigger\n", name); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_pcm_group_for_each_entry(s, substream) { - struct snd_pcm_runtime *runtime = s->runtime; - struct snd_card_asihpi_pcm *ds = runtime->private_data; - - if (snd_pcm_substream_chip(s) != card) - continue; - - /* don't link Cap and Play */ - if (substream->stream != s->stream) - continue; - - ds->drained_count = 0; - if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* How do I know how much valid data is present - * in buffer? Must be at least one period! - * Guessing 2 periods, but if - * buffer is bigger it may contain even more - * data?? - */ - unsigned int preload = ds->period_bytes * 1; - snd_printddd("%d preload x%x\n", s->number, preload); - hpi_handle_error(hpi_outstream_write_buf( - ds->h_stream, - &runtime->dma_area[0], - preload, - &ds->format)); - ds->pcm_buf_host_rw_ofs = preload; - } - - if (card->support_grouping) { - snd_printdd("%d group\n", s->number); - e = hpi_stream_group_add( - dpcm->h_stream, - ds->h_stream); - if (!e) { - snd_pcm_trigger_done(s, substream); - } else { - hpi_handle_error(e); - break; - } - } else - break; - } - snd_printdd("start\n"); - /* start the master stream */ - snd_card_asihpi_pcm_timer_start(substream); - if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) || - !card->can_dma) - hpi_handle_error(hpi_stream_start(dpcm->h_stream)); - break; - - case SNDRV_PCM_TRIGGER_STOP: - snd_card_asihpi_pcm_timer_stop(substream); - snd_pcm_group_for_each_entry(s, substream) { - if (snd_pcm_substream_chip(s) != card) - continue; - /* don't link Cap and Play */ - if (substream->stream != s->stream) - continue; - - /*? workaround linked streams don't - transition to SETUP 20070706*/ - s->runtime->status->state = SNDRV_PCM_STATE_SETUP; - - if (card->support_grouping) { - snd_printdd("%d group\n", s->number); - snd_pcm_trigger_done(s, substream); - } else - break; - } - snd_printdd("stop\n"); - - /* _prepare and _hwparams reset the stream */ - hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - hpi_handle_error( - hpi_outstream_reset(dpcm->h_stream)); - - if (card->support_grouping) - hpi_handle_error(hpi_stream_group_reset(dpcm->h_stream)); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_printdd("pause release\n"); - hpi_handle_error(hpi_stream_start(dpcm->h_stream)); - snd_card_asihpi_pcm_timer_start(substream); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_printdd("pause\n"); - snd_card_asihpi_pcm_timer_stop(substream); - hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); - break; - default: - snd_printd(KERN_ERR "\tINVALID\n"); - return -EINVAL; - } - - return 0; -} - -/*algorithm outline - Without linking degenerates to getting single stream pos etc - Without mmap 2nd loop degenerates to snd_pcm_period_elapsed -*/ -/* -pcm_buf_dma_ofs=get_buf_pos(s); -for_each_linked_stream(s) { - pcm_buf_dma_ofs=get_buf_pos(s); - min_buf_pos = modulo_min(min_buf_pos, pcm_buf_dma_ofs, buffer_bytes) - new_data = min(new_data, calc_new_data(pcm_buf_dma_ofs,irq_pos) -} -timer.expires = jiffies + predict_next_period_ready(min_buf_pos); -for_each_linked_stream(s) { - s->pcm_buf_dma_ofs = min_buf_pos; - if (new_data > period_bytes) { - if (mmap) { - irq_pos = (irq_pos + period_bytes) % buffer_bytes; - if (playback) { - write(period_bytes); - } else { - read(period_bytes); - } - } - snd_pcm_period_elapsed(s); - } -} -*/ - -/** Minimum of 2 modulo values. Works correctly when the difference between -* the values is less than half the modulus -*/ -static inline unsigned int modulo_min(unsigned int a, unsigned int b, - unsigned long int modulus) -{ - unsigned int result; - if (((a-b) % modulus) < (modulus/2)) - result = b; - else - result = a; - - return result; -} - -/** Timer function, equivalent to interrupt service routine for cards -*/ -static void snd_card_asihpi_timer_function(unsigned long data) -{ - struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data; - struct snd_pcm_substream *substream = dpcm->substream; - struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime; - struct snd_pcm_substream *s; - unsigned int newdata = 0; - unsigned int pcm_buf_dma_ofs, min_buf_pos = 0; - unsigned int remdata, xfercount, next_jiffies; - int first = 1; - int loops = 0; - u16 state; - u32 buffer_size, bytes_avail, samples_played, on_card_bytes; - char name[16]; - - snd_pcm_debug_name(substream, name, sizeof(name)); - - snd_printdd("%s snd_card_asihpi_timer_function\n", name); - - /* find minimum newdata and buffer pos in group */ - snd_pcm_group_for_each_entry(s, substream) { - struct snd_card_asihpi_pcm *ds = s->runtime->private_data; - runtime = s->runtime; - - if (snd_pcm_substream_chip(s) != card) - continue; - - /* don't link Cap and Play */ - if (substream->stream != s->stream) - continue; - - hpi_handle_error(hpi_stream_get_info_ex( - ds->h_stream, &state, - &buffer_size, &bytes_avail, - &samples_played, &on_card_bytes)); - - /* number of bytes in on-card buffer */ - runtime->delay = on_card_bytes; - - if (!card->can_dma) - on_card_bytes = bytes_avail; - - if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { - pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail; - if (state == HPI_STATE_STOPPED) { - if (bytes_avail == 0) { - hpi_handle_error(hpi_stream_start(ds->h_stream)); - snd_printdd("P%d start\n", s->number); - ds->drained_count = 0; - } - } else if (state == HPI_STATE_DRAINED) { - snd_printd(KERN_WARNING "P%d drained\n", - s->number); - ds->drained_count++; - if (ds->drained_count > 20) { - snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); - continue; - } - } else { - ds->drained_count = 0; - } - } else - pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs; - - if (first) { - /* can't statically init min when wrap is involved */ - min_buf_pos = pcm_buf_dma_ofs; - newdata = (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes; - first = 0; - } else { - min_buf_pos = - modulo_min(min_buf_pos, pcm_buf_dma_ofs, UINT_MAX+1L); - newdata = min( - (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes, - newdata); - } - - snd_printdd("hw_ptr 0x%04lX, appl_ptr 0x%04lX\n", - (unsigned long)frames_to_bytes(runtime, - runtime->status->hw_ptr), - (unsigned long)frames_to_bytes(runtime, - runtime->control->appl_ptr)); - - snd_printdd("%d S=%d, " - "rw=0x%04X, dma=0x%04X, left=0x%04X, " - "aux=0x%04X space=0x%04X\n", - s->number, state, - ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, - (int)bytes_avail, - (int)on_card_bytes, buffer_size-bytes_avail); - loops++; - } - pcm_buf_dma_ofs = min_buf_pos; - - remdata = newdata % dpcm->period_bytes; - xfercount = newdata - remdata; /* a multiple of period_bytes */ - /* come back when on_card_bytes has decreased enough to allow - write to happen, or when data has been consumed to make another - period - */ - if (xfercount && (on_card_bytes > dpcm->period_bytes)) - next_jiffies = ((on_card_bytes - dpcm->period_bytes) * HZ / dpcm->bytes_per_sec); - else - next_jiffies = ((dpcm->period_bytes - remdata) * HZ / dpcm->bytes_per_sec); - - next_jiffies = max(next_jiffies, 1U); - dpcm->timer.expires = jiffies + next_jiffies; - snd_printdd("jif %d buf pos 0x%04X newdata 0x%04X xfer 0x%04X\n", - next_jiffies, pcm_buf_dma_ofs, newdata, xfercount); - - snd_pcm_group_for_each_entry(s, substream) { - struct snd_card_asihpi_pcm *ds = s->runtime->private_data; - - /* don't link Cap and Play */ - if (substream->stream != s->stream) - continue; - - ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs; - - if (xfercount && - /* Limit use of on card fifo for playback */ - ((on_card_bytes <= ds->period_bytes) || - (s->stream == SNDRV_PCM_STREAM_CAPTURE))) - - { - - unsigned int buf_ofs = ds->pcm_buf_host_rw_ofs % ds->buffer_bytes; - unsigned int xfer1, xfer2; - char *pd = &s->runtime->dma_area[buf_ofs]; - - if (card->can_dma) { /* buffer wrap is handled at lower level */ - xfer1 = xfercount; - xfer2 = 0; - } else { - xfer1 = min(xfercount, ds->buffer_bytes - buf_ofs); - xfer2 = xfercount - xfer1; - } - - if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { - snd_printddd("P%d write1 0x%04X 0x%04X\n", - s->number, xfer1, buf_ofs); - hpi_handle_error( - hpi_outstream_write_buf( - ds->h_stream, pd, xfer1, - &ds->format)); - - if (xfer2) { - pd = s->runtime->dma_area; - - snd_printddd("P%d write2 0x%04X 0x%04X\n", - s->number, - xfercount - xfer1, buf_ofs); - hpi_handle_error( - hpi_outstream_write_buf( - ds->h_stream, pd, - xfercount - xfer1, - &ds->format)); - } - } else { - snd_printddd("C%d read1 0x%04x\n", - s->number, xfer1); - hpi_handle_error( - hpi_instream_read_buf( - ds->h_stream, - pd, xfer1)); - if (xfer2) { - pd = s->runtime->dma_area; - snd_printddd("C%d read2 0x%04x\n", - s->number, xfer2); - hpi_handle_error( - hpi_instream_read_buf( - ds->h_stream, - pd, xfer2)); - } - } - ds->pcm_buf_host_rw_ofs += xfercount; - ds->pcm_buf_elapsed_dma_ofs += xfercount; - snd_pcm_period_elapsed(s); - } - } - - if (dpcm->respawn_timer) - add_timer(&dpcm->timer); -} - -/***************************** PLAYBACK OPS ****************/ -static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - char name[16]; - snd_pcm_debug_name(substream, name, sizeof(name)); - snd_printddd(KERN_INFO "%s ioctl %d\n", name, cmd); - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream * - substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - - snd_printdd("P%d prepare\n", substream->number); - - hpi_handle_error(hpi_outstream_reset(dpcm->h_stream)); - dpcm->pcm_buf_host_rw_ofs = 0; - dpcm->pcm_buf_dma_ofs = 0; - dpcm->pcm_buf_elapsed_dma_ofs = 0; - return 0; -} - -static snd_pcm_uframes_t -snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - snd_pcm_uframes_t ptr; - char name[16]; - snd_pcm_debug_name(substream, name, sizeof(name)); - - ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); - snd_printddd("%s pointer = 0x%04lx\n", name, (unsigned long)ptr); - return ptr; -} - -static u64 snd_card_asihpi_playback_formats(struct snd_card_asihpi *asihpi, - u32 h_stream) -{ - struct hpi_format hpi_format; - u16 format; - u16 err; - u32 h_control; - u32 sample_rate = 48000; - u64 formats = 0; - - /* on cards without SRC, must query at valid rate, - * maybe set by external sync - */ - err = hpi_mixer_get_control(asihpi->h_mixer, - HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, - HPI_CONTROL_SAMPLECLOCK, &h_control); - - if (!err) - err = hpi_sample_clock_get_sample_rate(h_control, - &sample_rate); - - for (format = HPI_FORMAT_PCM8_UNSIGNED; - format <= HPI_FORMAT_PCM24_SIGNED; format++) { - err = hpi_format_create(&hpi_format, asihpi->out_max_chans, - format, sample_rate, 128000, 0); - if (!err) - err = hpi_outstream_query_format(h_stream, &hpi_format); - if (!err && (hpi_to_alsa_formats[format] != -1)) - formats |= (1ULL << hpi_to_alsa_formats[format]); - } - return formats; -} - -static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm; - struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); - struct snd_pcm_hardware snd_card_asihpi_playback; - int err; - - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (dpcm == NULL) - return -ENOMEM; - - err = hpi_outstream_open(card->hpi->adapter->index, - substream->number, &dpcm->h_stream); - hpi_handle_error(err); - if (err) - kfree(dpcm); - if (err == HPI_ERROR_OBJ_ALREADY_OPEN) - return -EBUSY; - if (err) - return -EIO; - - /*? also check ASI5000 samplerate source - If external, only support external rate. - If internal and other stream playing, can't switch - */ - - init_timer(&dpcm->timer); - dpcm->timer.data = (unsigned long) dpcm; - dpcm->timer.function = snd_card_asihpi_timer_function; - dpcm->substream = substream; - runtime->private_data = dpcm; - runtime->private_free = snd_card_asihpi_runtime_free; - - memset(&snd_card_asihpi_playback, 0, sizeof(snd_card_asihpi_playback)); - snd_card_asihpi_playback.buffer_bytes_max = BUFFER_BYTES_MAX; - snd_card_asihpi_playback.period_bytes_min = PERIOD_BYTES_MIN; - /*?snd_card_asihpi_playback.period_bytes_min = - card->out_max_chans * 4096; */ - snd_card_asihpi_playback.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN; - snd_card_asihpi_playback.periods_min = PERIODS_MIN; - snd_card_asihpi_playback.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN; - /* snd_card_asihpi_playback.fifo_size = 0; */ - snd_card_asihpi_playback.channels_max = card->out_max_chans; - snd_card_asihpi_playback.channels_min = card->out_min_chans; - snd_card_asihpi_playback.formats = - snd_card_asihpi_playback_formats(card, dpcm->h_stream); - - snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_playback); - - snd_card_asihpi_playback.info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_DOUBLE | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID; - - if (card->support_grouping) { - snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START; - snd_pcm_set_sync(substream); - } - - /* struct is copied, so can create initializer dynamically */ - runtime->hw = snd_card_asihpi_playback; - - if (card->can_dma) - err = snd_pcm_hw_constraint_pow2(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES); - if (err < 0) - return err; - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - card->update_interval_frames); - - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - card->update_interval_frames * 2, UINT_MAX); - - snd_printdd("playback open\n"); - - return 0; -} - -static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - - hpi_handle_error(hpi_outstream_close(dpcm->h_stream)); - snd_printdd("playback close\n"); - - return 0; -} - -static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { - .open = snd_card_asihpi_playback_open, - .close = snd_card_asihpi_playback_close, - .ioctl = snd_card_asihpi_playback_ioctl, - .hw_params = snd_card_asihpi_pcm_hw_params, - .hw_free = snd_card_asihpi_hw_free, - .prepare = snd_card_asihpi_playback_prepare, - .trigger = snd_card_asihpi_trigger, - .pointer = snd_card_asihpi_playback_pointer, -}; - -/***************************** CAPTURE OPS ****************/ -static snd_pcm_uframes_t -snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - - snd_printddd("capture pointer %d=%d\n", - substream->number, dpcm->pcm_buf_dma_ofs); - /* NOTE Unlike playback can't use actual samples_played - for the capture position, because those samples aren't yet in - the local buffer available for reading. - */ - return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); -} - -static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi_pcm *dpcm = runtime->private_data; - - hpi_handle_error(hpi_instream_reset(dpcm->h_stream)); - dpcm->pcm_buf_host_rw_ofs = 0; - dpcm->pcm_buf_dma_ofs = 0; - dpcm->pcm_buf_elapsed_dma_ofs = 0; - - snd_printdd("Capture Prepare %d\n", substream->number); - return 0; -} - - - -static u64 snd_card_asihpi_capture_formats(struct snd_card_asihpi *asihpi, - u32 h_stream) -{ - struct hpi_format hpi_format; - u16 format; - u16 err; - u32 h_control; - u32 sample_rate = 48000; - u64 formats = 0; - - /* on cards without SRC, must query at valid rate, - maybe set by external sync */ - err = hpi_mixer_get_control(asihpi->h_mixer, - HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, - HPI_CONTROL_SAMPLECLOCK, &h_control); - - if (!err) - err = hpi_sample_clock_get_sample_rate(h_control, - &sample_rate); - - for (format = HPI_FORMAT_PCM8_UNSIGNED; - format <= HPI_FORMAT_PCM24_SIGNED; format++) { - - err = hpi_format_create(&hpi_format, asihpi->in_max_chans, - format, sample_rate, 128000, 0); - if (!err) - err = hpi_instream_query_format(h_stream, &hpi_format); - if (!err) - formats |= (1ULL << hpi_to_alsa_formats[format]); - } - return formats; -} - -static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); - struct snd_card_asihpi_pcm *dpcm; - struct snd_pcm_hardware snd_card_asihpi_capture; - int err; - - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (dpcm == NULL) - return -ENOMEM; - - snd_printdd("capture open adapter %d stream %d\n", - card->hpi->adapter->index, substream->number); - - err = hpi_handle_error( - hpi_instream_open(card->hpi->adapter->index, - substream->number, &dpcm->h_stream)); - if (err) - kfree(dpcm); - if (err == HPI_ERROR_OBJ_ALREADY_OPEN) - return -EBUSY; - if (err) - return -EIO; - - init_timer(&dpcm->timer); - dpcm->timer.data = (unsigned long) dpcm; - dpcm->timer.function = snd_card_asihpi_timer_function; - dpcm->substream = substream; - runtime->private_data = dpcm; - runtime->private_free = snd_card_asihpi_runtime_free; - - memset(&snd_card_asihpi_capture, 0, sizeof(snd_card_asihpi_capture)); - snd_card_asihpi_capture.buffer_bytes_max = BUFFER_BYTES_MAX; - snd_card_asihpi_capture.period_bytes_min = PERIOD_BYTES_MIN; - snd_card_asihpi_capture.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN; - snd_card_asihpi_capture.periods_min = PERIODS_MIN; - snd_card_asihpi_capture.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN; - /* snd_card_asihpi_capture.fifo_size = 0; */ - snd_card_asihpi_capture.channels_max = card->in_max_chans; - snd_card_asihpi_capture.channels_min = card->in_min_chans; - snd_card_asihpi_capture.formats = - snd_card_asihpi_capture_formats(card, dpcm->h_stream); - snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture); - snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID; - - if (card->support_grouping) - snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START; - - runtime->hw = snd_card_asihpi_capture; - - if (card->can_dma) - err = snd_pcm_hw_constraint_pow2(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES); - if (err < 0) - return err; - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - card->update_interval_frames); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - card->update_interval_frames * 2, UINT_MAX); - - snd_pcm_set_sync(substream); - - return 0; -} - -static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; - - hpi_handle_error(hpi_instream_close(dpcm->h_stream)); - return 0; -} - -static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { - .open = snd_card_asihpi_capture_open, - .close = snd_card_asihpi_capture_close, - .ioctl = snd_card_asihpi_capture_ioctl, - .hw_params = snd_card_asihpi_pcm_hw_params, - .hw_free = snd_card_asihpi_hw_free, - .prepare = snd_card_asihpi_capture_prepare, - .trigger = snd_card_asihpi_trigger, - .pointer = snd_card_asihpi_capture_pointer, -}; - -static int __devinit snd_card_asihpi_pcm_new( - struct snd_card_asihpi *asihpi, int device) -{ - struct snd_pcm *pcm; - int err; - u16 num_instreams, num_outstreams, x16; - u32 x32; - - err = hpi_adapter_get_info(asihpi->hpi->adapter->index, - &num_outstreams, &num_instreams, - &x16, &x32, &x16); - - err = snd_pcm_new(asihpi->card, "Asihpi PCM", device, - num_outstreams, num_instreams, &pcm); - if (err < 0) - return err; - /* pointer to ops struct is stored, dont change ops afterwards! */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_card_asihpi_playback_mmap_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_card_asihpi_capture_mmap_ops); - - pcm->private_data = asihpi; - pcm->info_flags = 0; - strcpy(pcm->name, "Asihpi PCM"); - - /*? do we want to emulate MMAP for non-BBM cards? - Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(asihpi->pci), - 64*1024, BUFFER_BYTES_MAX); - - return 0; -} - -/***************************** MIXER CONTROLS ****************/ -struct hpi_control { - u32 h_control; - u16 control_type; - u16 src_node_type; - u16 src_node_index; - u16 dst_node_type; - u16 dst_node_index; - u16 band; - char name[44]; /* copied to snd_ctl_elem_id.name[44]; */ -}; - -static const char * const asihpi_tuner_band_names[] = { - "invalid", - "AM", - "FM mono", - "TV NTSC-M", - "FM stereo", - "AUX", - "TV PAL BG", - "TV PAL I", - "TV PAL DK", - "TV SECAM", -}; - -compile_time_assert( - (ARRAY_SIZE(asihpi_tuner_band_names) == - (HPI_TUNER_BAND_LAST+1)), - assert_tuner_band_names_size); - -static const char * const asihpi_src_names[] = { - "no source", - "PCM", - "Line", - "Digital", - "Tuner", - "RF", - "Clock", - "Bitstream", - "Mic", - "Net", - "Analog", - "Adapter", - "RTP", - "Internal" -}; - -compile_time_assert( - (ARRAY_SIZE(asihpi_src_names) == - (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)), - assert_src_names_size); - -static const char * const asihpi_dst_names[] = { - "no destination", - "PCM", - "Line", - "Digital", - "RF", - "Speaker", - "Net", - "Analog", - "RTP", -}; - -compile_time_assert( - (ARRAY_SIZE(asihpi_dst_names) == - (HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_NONE+1)), - assert_dst_names_size); - -static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl, - struct snd_card_asihpi *asihpi) -{ - int err; - - err = snd_ctl_add(card, snd_ctl_new1(ctl, asihpi)); - if (err < 0) - return err; - else if (mixer_dump) - snd_printk(KERN_INFO "added %s(%d)\n", ctl->name, ctl->index); - - return 0; -} - -/* Convert HPI control name and location into ALSA control name */ -static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control, - struct hpi_control *hpi_ctl, - char *name) -{ - char *dir; - memset(snd_control, 0, sizeof(*snd_control)); - snd_control->name = hpi_ctl->name; - snd_control->private_value = hpi_ctl->h_control; - snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; - snd_control->index = 0; - - if (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE == HPI_SOURCENODE_CLOCK_SOURCE) - dir = ""; /* clock is neither capture nor playback */ - else if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM) - dir = "Capture "; /* On or towards a PCM capture destination*/ - else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && - (!hpi_ctl->dst_node_type)) - dir = "Capture "; /* On a source node that is not PCM playback */ - else if (hpi_ctl->src_node_type && - (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && - (hpi_ctl->dst_node_type)) - dir = "Monitor Playback "; /* Between an input and an output */ - else - dir = "Playback "; /* PCM Playback source, or output node */ - - if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) - sprintf(hpi_ctl->name, "%s %d %s %d %s%s", - asihpi_src_names[hpi_ctl->src_node_type], - hpi_ctl->src_node_index, - asihpi_dst_names[hpi_ctl->dst_node_type], - hpi_ctl->dst_node_index, - dir, name); - else if (hpi_ctl->dst_node_type) { - sprintf(hpi_ctl->name, "%s %d %s%s", - asihpi_dst_names[hpi_ctl->dst_node_type], - hpi_ctl->dst_node_index, - dir, name); - } else { - sprintf(hpi_ctl->name, "%s %d %s%s", - asihpi_src_names[hpi_ctl->src_node_type], - hpi_ctl->src_node_index, - dir, name); - } - /* printk(KERN_INFO "Adding %s %d to %d ", hpi_ctl->name, - hpi_ctl->wSrcNodeType, hpi_ctl->wDstNodeType); */ -} - -/*------------------------------------------------------------ - Volume controls - ------------------------------------------------------------*/ -#define VOL_STEP_mB 1 -static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - u32 h_control = kcontrol->private_value; - u32 count; - u16 err; - /* native gains are in millibels */ - short min_gain_mB; - short max_gain_mB; - short step_gain_mB; - - err = hpi_volume_query_range(h_control, - &min_gain_mB, &max_gain_mB, &step_gain_mB); - if (err) { - max_gain_mB = 0; - min_gain_mB = -10000; - step_gain_mB = VOL_STEP_mB; - } - - err = hpi_meter_query_channels(h_control, &count); - if (err) - count = HPI_MAX_CHANNELS; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = count; - uinfo->value.integer.min = min_gain_mB / VOL_STEP_mB; - uinfo->value.integer.max = max_gain_mB / VOL_STEP_mB; - uinfo->value.integer.step = step_gain_mB / VOL_STEP_mB; - return 0; -} - -static int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - short an_gain_mB[HPI_MAX_CHANNELS]; - - hpi_handle_error(hpi_volume_get_gain(h_control, an_gain_mB)); - ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB; - ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB; - - return 0; -} - -static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int change; - u32 h_control = kcontrol->private_value; - short an_gain_mB[HPI_MAX_CHANNELS]; - - an_gain_mB[0] = - (ucontrol->value.integer.value[0]) * VOL_STEP_mB; - an_gain_mB[1] = - (ucontrol->value.integer.value[1]) * VOL_STEP_mB; - /* change = asihpi->mixer_volume[addr][0] != left || - asihpi->mixer_volume[addr][1] != right; - */ - change = 1; - hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB)); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_100, -10000, VOL_STEP_mB, 0); - -#define snd_asihpi_volume_mute_info snd_ctl_boolean_mono_info - -static int snd_asihpi_volume_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - u32 mute; - - hpi_handle_error(hpi_volume_get_mute(h_control, &mute)); - ucontrol->value.integer.value[0] = mute ? 0 : 1; - - return 0; -} - -static int snd_asihpi_volume_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - int change = 1; - /* HPI currently only supports all or none muting of multichannel volume - ALSA Switch element has opposite sense to HPI mute: on==unmuted, off=muted - */ - int mute = ucontrol->value.integer.value[0] ? 0 : HPI_BITMASK_ALL_CHANNELS; - hpi_handle_error(hpi_volume_set_mute(h_control, mute)); - return change; -} - -static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - int err; - u32 mute; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Volume"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - snd_control.info = snd_asihpi_volume_info; - snd_control.get = snd_asihpi_volume_get; - snd_control.put = snd_asihpi_volume_put; - snd_control.tlv.p = db_scale_100; - - err = ctl_add(card, &snd_control, asihpi); - if (err) - return err; - - if (hpi_volume_get_mute(hpi_ctl->h_control, &mute) == 0) { - asihpi_ctl_init(&snd_control, hpi_ctl, "Switch"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - snd_control.info = snd_asihpi_volume_mute_info; - snd_control.get = snd_asihpi_volume_mute_get; - snd_control.put = snd_asihpi_volume_mute_put; - err = ctl_add(card, &snd_control, asihpi); - } - return err; -} - -/*------------------------------------------------------------ - Level controls - ------------------------------------------------------------*/ -static int snd_asihpi_level_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - u32 h_control = kcontrol->private_value; - u16 err; - short min_gain_mB; - short max_gain_mB; - short step_gain_mB; - - err = - hpi_level_query_range(h_control, &min_gain_mB, - &max_gain_mB, &step_gain_mB); - if (err) { - max_gain_mB = 2400; - min_gain_mB = -1000; - step_gain_mB = 100; - } - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = min_gain_mB / HPI_UNITS_PER_dB; - uinfo->value.integer.max = max_gain_mB / HPI_UNITS_PER_dB; - uinfo->value.integer.step = step_gain_mB / HPI_UNITS_PER_dB; - return 0; -} - -static int snd_asihpi_level_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - short an_gain_mB[HPI_MAX_CHANNELS]; - - hpi_handle_error(hpi_level_get_gain(h_control, an_gain_mB)); - ucontrol->value.integer.value[0] = - an_gain_mB[0] / HPI_UNITS_PER_dB; - ucontrol->value.integer.value[1] = - an_gain_mB[1] / HPI_UNITS_PER_dB; - - return 0; -} - -static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int change; - u32 h_control = kcontrol->private_value; - short an_gain_mB[HPI_MAX_CHANNELS]; - - an_gain_mB[0] = - (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; - an_gain_mB[1] = - (ucontrol->value.integer.value[1]) * HPI_UNITS_PER_dB; - /* change = asihpi->mixer_level[addr][0] != left || - asihpi->mixer_level[addr][1] != right; - */ - change = 1; - hpi_handle_error(hpi_level_set_gain(h_control, an_gain_mB)); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_level, -1000, 100, 0); - -static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - - /* can't use 'volume' cos some nodes have volume as well */ - asihpi_ctl_init(&snd_control, hpi_ctl, "Level"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - snd_control.info = snd_asihpi_level_info; - snd_control.get = snd_asihpi_level_get; - snd_control.put = snd_asihpi_level_put; - snd_control.tlv.p = db_scale_level; - - return ctl_add(card, &snd_control, asihpi); -} - -/*------------------------------------------------------------ - AESEBU controls - ------------------------------------------------------------*/ - -/* AESEBU format */ -static const char * const asihpi_aesebu_format_names[] = { - "N/A", "S/PDIF", "AES/EBU" }; - -static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - asihpi_aesebu_format_names[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol, - u16 (*func)(u32, u16 *)) -{ - u32 h_control = kcontrol->private_value; - u16 source, err; - - err = func(h_control, &source); - - /* default to N/A */ - ucontrol->value.enumerated.item[0] = 0; - /* return success but set the control to N/A */ - if (err) - return 0; - if (source == HPI_AESEBU_FORMAT_SPDIF) - ucontrol->value.enumerated.item[0] = 1; - if (source == HPI_AESEBU_FORMAT_AESEBU) - ucontrol->value.enumerated.item[0] = 2; - - return 0; -} - -static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol, - u16 (*func)(u32, u16)) -{ - u32 h_control = kcontrol->private_value; - - /* default to S/PDIF */ - u16 source = HPI_AESEBU_FORMAT_SPDIF; - - if (ucontrol->value.enumerated.item[0] == 1) - source = HPI_AESEBU_FORMAT_SPDIF; - if (ucontrol->value.enumerated.item[0] == 2) - source = HPI_AESEBU_FORMAT_AESEBU; - - if (func(h_control, source) != 0) - return -EINVAL; - - return 1; -} - -static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) { - return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, - hpi_aesebu_receiver_get_format); -} - -static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) { - return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, - hpi_aesebu_receiver_set_format); -} - -static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0X1F; - uinfo->value.integer.step = 1; - - return 0; -} - -static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) { - - u32 h_control = kcontrol->private_value; - u16 status; - - hpi_handle_error(hpi_aesebu_receiver_get_error_status( - h_control, &status)); - ucontrol->value.integer.value[0] = status; - return 0; -} - -static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - snd_control.info = snd_asihpi_aesebu_format_info; - snd_control.get = snd_asihpi_aesebu_rx_format_get; - snd_control.put = snd_asihpi_aesebu_rx_format_put; - - - if (ctl_add(card, &snd_control, asihpi) < 0) - return -EINVAL; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Status"); - snd_control.access = - SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; - snd_control.info = snd_asihpi_aesebu_rxstatus_info; - snd_control.get = snd_asihpi_aesebu_rxstatus_get; - - return ctl_add(card, &snd_control, asihpi); -} - -static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) { - return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, - hpi_aesebu_transmitter_get_format); -} - -static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) { - return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, - hpi_aesebu_transmitter_set_format); -} - - -static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - snd_control.info = snd_asihpi_aesebu_format_info; - snd_control.get = snd_asihpi_aesebu_tx_format_get; - snd_control.put = snd_asihpi_aesebu_tx_format_put; - - return ctl_add(card, &snd_control, asihpi); -} - -/*------------------------------------------------------------ - Tuner controls - ------------------------------------------------------------*/ - -/* Gain */ - -static int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - u32 h_control = kcontrol->private_value; - u16 err; - short idx; - u16 gain_range[3]; - - for (idx = 0; idx < 3; idx++) { - err = hpi_tuner_query_gain(h_control, - idx, &gain_range[idx]); - if (err != 0) - return err; - } - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = ((int)gain_range[0]) / HPI_UNITS_PER_dB; - uinfo->value.integer.max = ((int)gain_range[1]) / HPI_UNITS_PER_dB; - uinfo->value.integer.step = ((int) gain_range[2]) / HPI_UNITS_PER_dB; - return 0; -} - -static int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - /* - struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); - */ - u32 h_control = kcontrol->private_value; - short gain; - - hpi_handle_error(hpi_tuner_get_gain(h_control, &gain)); - ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB; - - return 0; -} - -static int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - /* - struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); - */ - u32 h_control = kcontrol->private_value; - short gain; - - gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; - hpi_handle_error(hpi_tuner_set_gain(h_control, gain)); - - return 1; -} - -/* Band */ - -static int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol, - u16 *band_list, u32 len) { - u32 h_control = kcontrol->private_value; - u16 err = 0; - u32 i; - - for (i = 0; i < len; i++) { - err = hpi_tuner_query_band( - h_control, i, &band_list[i]); - if (err != 0) - break; - } - - if (err && (err != HPI_ERROR_INVALID_OBJ_INDEX)) - return -EIO; - - return i; -} - -static int snd_asihpi_tuner_band_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - u16 tuner_bands[HPI_TUNER_BAND_LAST]; - int num_bands = 0; - - num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, - HPI_TUNER_BAND_LAST); - - if (num_bands < 0) - return num_bands; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = num_bands; - - if (num_bands > 0) { - if (uinfo->value.enumerated.item >= - uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - asihpi_tuner_band_names[ - tuner_bands[uinfo->value.enumerated.item]]); - - } - return 0; -} - -static int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - /* - struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); - */ - u16 band, idx; - u16 tuner_bands[HPI_TUNER_BAND_LAST]; - u32 num_bands = 0; - - num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, - HPI_TUNER_BAND_LAST); - - hpi_handle_error(hpi_tuner_get_band(h_control, &band)); - - ucontrol->value.enumerated.item[0] = -1; - for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++) - if (tuner_bands[idx] == band) { - ucontrol->value.enumerated.item[0] = idx; - break; - } - - return 0; -} - -static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - /* - struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol); - */ - u32 h_control = kcontrol->private_value; - u16 band; - u16 tuner_bands[HPI_TUNER_BAND_LAST]; - u32 num_bands = 0; - - num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, - HPI_TUNER_BAND_LAST); - - band = tuner_bands[ucontrol->value.enumerated.item[0]]; - hpi_handle_error(hpi_tuner_set_band(h_control, band)); - - return 1; -} - -/* Freq */ - -static int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - u32 h_control = kcontrol->private_value; - u16 err; - u16 tuner_bands[HPI_TUNER_BAND_LAST]; - u16 num_bands = 0, band_iter, idx; - u32 freq_range[3], temp_freq_range[3]; - - num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, - HPI_TUNER_BAND_LAST); - - freq_range[0] = INT_MAX; - freq_range[1] = 0; - freq_range[2] = INT_MAX; - - for (band_iter = 0; band_iter < num_bands; band_iter++) { - for (idx = 0; idx < 3; idx++) { - err = hpi_tuner_query_frequency(h_control, - idx, tuner_bands[band_iter], - &temp_freq_range[idx]); - if (err != 0) - return err; - } - - /* skip band with bogus stepping */ - if (temp_freq_range[2] <= 0) - continue; - - if (temp_freq_range[0] < freq_range[0]) - freq_range[0] = temp_freq_range[0]; - if (temp_freq_range[1] > freq_range[1]) - freq_range[1] = temp_freq_range[1]; - if (temp_freq_range[2] < freq_range[2]) - freq_range[2] = temp_freq_range[2]; - } - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = ((int)freq_range[0]); - uinfo->value.integer.max = ((int)freq_range[1]); - uinfo->value.integer.step = ((int)freq_range[2]); - return 0; -} - -static int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - u32 freq; - - hpi_handle_error(hpi_tuner_get_frequency(h_control, &freq)); - ucontrol->value.integer.value[0] = freq; - - return 0; -} - -static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - u32 freq; - - freq = ucontrol->value.integer.value[0]; - hpi_handle_error(hpi_tuner_set_frequency(h_control, freq)); - - return 1; -} - -/* Tuner control group initializer */ -static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - - snd_control.private_value = hpi_ctl->h_control; - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - - if (!hpi_tuner_get_gain(hpi_ctl->h_control, NULL)) { - asihpi_ctl_init(&snd_control, hpi_ctl, "Gain"); - snd_control.info = snd_asihpi_tuner_gain_info; - snd_control.get = snd_asihpi_tuner_gain_get; - snd_control.put = snd_asihpi_tuner_gain_put; - - if (ctl_add(card, &snd_control, asihpi) < 0) - return -EINVAL; - } - - asihpi_ctl_init(&snd_control, hpi_ctl, "Band"); - snd_control.info = snd_asihpi_tuner_band_info; - snd_control.get = snd_asihpi_tuner_band_get; - snd_control.put = snd_asihpi_tuner_band_put; - - if (ctl_add(card, &snd_control, asihpi) < 0) - return -EINVAL; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Freq"); - snd_control.info = snd_asihpi_tuner_freq_info; - snd_control.get = snd_asihpi_tuner_freq_get; - snd_control.put = snd_asihpi_tuner_freq_put; - - return ctl_add(card, &snd_control, asihpi); -} - -/*------------------------------------------------------------ - Meter controls - ------------------------------------------------------------*/ -static int snd_asihpi_meter_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - u32 h_control = kcontrol->private_value; - u32 count; - u16 err; - err = hpi_meter_query_channels(h_control, &count); - if (err) - count = HPI_MAX_CHANNELS; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = count; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0x7FFFFFFF; - return 0; -} - -/* linear values for 10dB steps */ -static int log2lin[] = { - 0x7FFFFFFF, /* 0dB */ - 679093956, - 214748365, - 67909396, - 21474837, - 6790940, - 2147484, /* -60dB */ - 679094, - 214748, /* -80 */ - 67909, - 21475, /* -100 */ - 6791, - 2147, - 679, - 214, - 68, - 21, - 7, - 2 -}; - -static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - short an_gain_mB[HPI_MAX_CHANNELS], i; - u16 err; - - err = hpi_meter_get_peak(h_control, an_gain_mB); - - for (i = 0; i < HPI_MAX_CHANNELS; i++) { - if (err) { - ucontrol->value.integer.value[i] = 0; - } else if (an_gain_mB[i] >= 0) { - ucontrol->value.integer.value[i] = - an_gain_mB[i] << 16; - } else { - /* -ve is log value in millibels < -60dB, - * convert to (roughly!) linear, - */ - ucontrol->value.integer.value[i] = - log2lin[an_gain_mB[i] / -1000]; - } - } - return 0; -} - -static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl, int subidx) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Meter"); - snd_control.access = - SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; - snd_control.info = snd_asihpi_meter_info; - snd_control.get = snd_asihpi_meter_get; - - snd_control.index = subidx; - - return ctl_add(card, &snd_control, asihpi); -} - -/*------------------------------------------------------------ - Multiplexer controls - ------------------------------------------------------------*/ -static int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control) -{ - u32 h_control = snd_control->private_value; - struct hpi_control hpi_ctl; - int s, err; - for (s = 0; s < 32; s++) { - err = hpi_multiplexer_query_source(h_control, s, - &hpi_ctl. - src_node_type, - &hpi_ctl. - src_node_index); - if (err) - break; - } - return s; -} - -static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int err; - u16 src_node_type, src_node_index; - u32 h_control = kcontrol->private_value; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = - snd_card_asihpi_mux_count_sources(kcontrol); - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - err = - hpi_multiplexer_query_source(h_control, - uinfo->value.enumerated.item, - &src_node_type, &src_node_index); - - sprintf(uinfo->value.enumerated.name, "%s %d", - asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE], - src_node_index); - return 0; -} - -static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - u16 source_type, source_index; - u16 src_node_type, src_node_index; - int s; - - hpi_handle_error(hpi_multiplexer_get_source(h_control, - &source_type, &source_index)); - /* Should cache this search result! */ - for (s = 0; s < 256; s++) { - if (hpi_multiplexer_query_source(h_control, s, - &src_node_type, &src_node_index)) - break; - - if ((source_type == src_node_type) - && (source_index == src_node_index)) { - ucontrol->value.enumerated.item[0] = s; - return 0; - } - } - snd_printd(KERN_WARNING - "Control %x failed to match mux source %hu %hu\n", - h_control, source_type, source_index); - ucontrol->value.enumerated.item[0] = 0; - return 0; -} - -static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int change; - u32 h_control = kcontrol->private_value; - u16 source_type, source_index; - u16 e; - - change = 1; - - e = hpi_multiplexer_query_source(h_control, - ucontrol->value.enumerated.item[0], - &source_type, &source_index); - if (!e) - hpi_handle_error( - hpi_multiplexer_set_source(h_control, - source_type, source_index)); - return change; -} - - -static int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Route"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - snd_control.info = snd_asihpi_mux_info; - snd_control.get = snd_asihpi_mux_get; - snd_control.put = snd_asihpi_mux_put; - - return ctl_add(card, &snd_control, asihpi); - -} - -/*------------------------------------------------------------ - Channel mode controls - ------------------------------------------------------------*/ -static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const mode_names[HPI_CHANNEL_MODE_LAST + 1] = { - "invalid", - "Normal", "Swap", - "From Left", "From Right", - "To Left", "To Right" - }; - - u32 h_control = kcontrol->private_value; - u16 mode; - int i; - u16 mode_map[6]; - int valid_modes = 0; - - /* HPI channel mode values can be from 1 to 6 - Some adapters only support a contiguous subset - */ - for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++) - if (!hpi_channel_mode_query_mode( - h_control, i, &mode)) { - mode_map[valid_modes] = mode; - valid_modes++; - } - - if (!valid_modes) - return -EINVAL; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = valid_modes; - - if (uinfo->value.enumerated.item >= valid_modes) - uinfo->value.enumerated.item = valid_modes - 1; - - strcpy(uinfo->value.enumerated.name, - mode_names[mode_map[uinfo->value.enumerated.item]]); - - return 0; -} - -static int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - u16 mode; - - if (hpi_channel_mode_get(h_control, &mode)) - mode = 1; - - ucontrol->value.enumerated.item[0] = mode - 1; - - return 0; -} - -static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int change; - u32 h_control = kcontrol->private_value; - - change = 1; - - hpi_handle_error(hpi_channel_mode_set(h_control, - ucontrol->value.enumerated.item[0] + 1)); - return change; -} - - -static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Mode"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - snd_control.info = snd_asihpi_cmode_info; - snd_control.get = snd_asihpi_cmode_get; - snd_control.put = snd_asihpi_cmode_put; - - return ctl_add(card, &snd_control, asihpi); -} - -/*------------------------------------------------------------ - Sampleclock source controls - ------------------------------------------------------------*/ -static char *sampleclock_sources[MAX_CLOCKSOURCES] = { - "N/A", "Local PLL", "Digital Sync", "Word External", "Word Header", - "SMPTE", "Digital1", "Auto", "Network", "Invalid", - "Prev Module", - "Digital2", "Digital3", "Digital4", "Digital5", - "Digital6", "Digital7", "Digital8"}; - -static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_card_asihpi *asihpi = - (struct snd_card_asihpi *)(kcontrol->private_data); - struct clk_cache *clkcache = &asihpi->cc; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = clkcache->count; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - clkcache->s[uinfo->value.enumerated.item].name); - return 0; -} - -static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_card_asihpi *asihpi = - (struct snd_card_asihpi *)(kcontrol->private_data); - struct clk_cache *clkcache = &asihpi->cc; - u32 h_control = kcontrol->private_value; - u16 source, srcindex = 0; - int i; - - ucontrol->value.enumerated.item[0] = 0; - if (hpi_sample_clock_get_source(h_control, &source)) - source = 0; - - if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) - if (hpi_sample_clock_get_source_index(h_control, &srcindex)) - srcindex = 0; - - for (i = 0; i < clkcache->count; i++) - if ((clkcache->s[i].source == source) && - (clkcache->s[i].index == srcindex)) - break; - - ucontrol->value.enumerated.item[0] = i; - - return 0; -} - -static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_card_asihpi *asihpi = - (struct snd_card_asihpi *)(kcontrol->private_data); - struct clk_cache *clkcache = &asihpi->cc; - int change, item; - u32 h_control = kcontrol->private_value; - - change = 1; - item = ucontrol->value.enumerated.item[0]; - if (item >= clkcache->count) - item = clkcache->count-1; - - hpi_handle_error(hpi_sample_clock_set_source( - h_control, clkcache->s[item].source)); - - if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) - hpi_handle_error(hpi_sample_clock_set_source_index( - h_control, clkcache->s[item].index)); - return change; -} - -/*------------------------------------------------------------ - Clkrate controls - ------------------------------------------------------------*/ -/* Need to change this to enumerated control with list of rates */ -static int snd_asihpi_clklocal_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 8000; - uinfo->value.integer.max = 192000; - uinfo->value.integer.step = 100; - - return 0; -} - -static int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - u32 rate; - u16 e; - - e = hpi_sample_clock_get_local_rate(h_control, &rate); - if (!e) - ucontrol->value.integer.value[0] = rate; - else - ucontrol->value.integer.value[0] = 0; - return 0; -} - -static int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int change; - u32 h_control = kcontrol->private_value; - - /* change = asihpi->mixer_clkrate[addr][0] != left || - asihpi->mixer_clkrate[addr][1] != right; - */ - change = 1; - hpi_handle_error(hpi_sample_clock_set_local_rate(h_control, - ucontrol->value.integer.value[0])); - return change; -} - -static int snd_asihpi_clkrate_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 8000; - uinfo->value.integer.max = 192000; - uinfo->value.integer.step = 100; - - return 0; -} - -static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u32 h_control = kcontrol->private_value; - u32 rate; - u16 e; - - e = hpi_sample_clock_get_sample_rate(h_control, &rate); - if (!e) - ucontrol->value.integer.value[0] = rate; - else - ucontrol->value.integer.value[0] = 0; - return 0; -} - -static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, - struct hpi_control *hpi_ctl) -{ - struct snd_card *card = asihpi->card; - struct snd_kcontrol_new snd_control; - - struct clk_cache *clkcache = &asihpi->cc; - u32 hSC = hpi_ctl->h_control; - int has_aes_in = 0; - int i, j; - u16 source; - - snd_control.private_value = hpi_ctl->h_control; - - clkcache->has_local = 0; - - for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) { - if (hpi_sample_clock_query_source(hSC, - i, &source)) - break; - clkcache->s[i].source = source; - clkcache->s[i].index = 0; - clkcache->s[i].name = sampleclock_sources[source]; - if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) - has_aes_in = 1; - if (source == HPI_SAMPLECLOCK_SOURCE_LOCAL) - clkcache->has_local = 1; - } - if (has_aes_in) - /* already will have picked up index 0 above */ - for (j = 1; j < 8; j++) { - if (hpi_sample_clock_query_source_index(hSC, - j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT, - &source)) - break; - clkcache->s[i].source = - HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT; - clkcache->s[i].index = j; - clkcache->s[i].name = sampleclock_sources[ - j+HPI_SAMPLECLOCK_SOURCE_LAST]; - i++; - } - clkcache->count = i; - - asihpi_ctl_init(&snd_control, hpi_ctl, "Source"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; - snd_control.info = snd_asihpi_clksrc_info; - snd_control.get = snd_asihpi_clksrc_get; - snd_control.put = snd_asihpi_clksrc_put; - if (ctl_add(card, &snd_control, asihpi) < 0) - return -EINVAL; - - - if (clkcache->has_local) { - asihpi_ctl_init(&snd_control, hpi_ctl, "Localrate"); - snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; - snd_control.info = snd_asihpi_clklocal_info; - snd_control.get = snd_asihpi_clklocal_get; - snd_control.put = snd_asihpi_clklocal_put; - - - if (ctl_add(card, &snd_control, asihpi) < 0) - return -EINVAL; - } - - asihpi_ctl_init(&snd_control, hpi_ctl, "Rate"); - snd_control.access = - SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; - snd_control.info = snd_asihpi_clkrate_info; - snd_control.get = snd_asihpi_clkrate_get; - - return ctl_add(card, &snd_control, asihpi); -} -/*------------------------------------------------------------ - Mixer - ------------------------------------------------------------*/ - -static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) -{ - struct snd_card *card = asihpi->card; - unsigned int idx = 0; - unsigned int subindex = 0; - int err; - struct hpi_control hpi_ctl, prev_ctl; - - if (snd_BUG_ON(!asihpi)) - return -EINVAL; - strcpy(card->mixername, "Asihpi Mixer"); - - err = - hpi_mixer_open(asihpi->hpi->adapter->index, - &asihpi->h_mixer); - hpi_handle_error(err); - if (err) - return -err; - - memset(&prev_ctl, 0, sizeof(prev_ctl)); - prev_ctl.control_type = -1; - - for (idx = 0; idx < 2000; idx++) { - err = hpi_mixer_get_control_by_index( - asihpi->h_mixer, - idx, - &hpi_ctl.src_node_type, - &hpi_ctl.src_node_index, - &hpi_ctl.dst_node_type, - &hpi_ctl.dst_node_index, - &hpi_ctl.control_type, - &hpi_ctl.h_control); - if (err) { - if (err == HPI_ERROR_CONTROL_DISABLED) { - if (mixer_dump) - snd_printk(KERN_INFO - "Disabled HPI Control(%d)\n", - idx); - continue; - } else - break; - - } - - hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE; - hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE; - - /* ASI50xx in SSX mode has multiple meters on the same node. - Use subindex to create distinct ALSA controls - for any duplicated controls. - */ - if ((hpi_ctl.control_type == prev_ctl.control_type) && - (hpi_ctl.src_node_type == prev_ctl.src_node_type) && - (hpi_ctl.src_node_index == prev_ctl.src_node_index) && - (hpi_ctl.dst_node_type == prev_ctl.dst_node_type) && - (hpi_ctl.dst_node_index == prev_ctl.dst_node_index)) - subindex++; - else - subindex = 0; - - prev_ctl = hpi_ctl; - - switch (hpi_ctl.control_type) { - case HPI_CONTROL_VOLUME: - err = snd_asihpi_volume_add(asihpi, &hpi_ctl); - break; - case HPI_CONTROL_LEVEL: - err = snd_asihpi_level_add(asihpi, &hpi_ctl); - break; - case HPI_CONTROL_MULTIPLEXER: - err = snd_asihpi_mux_add(asihpi, &hpi_ctl); - break; - case HPI_CONTROL_CHANNEL_MODE: - err = snd_asihpi_cmode_add(asihpi, &hpi_ctl); - break; - case HPI_CONTROL_METER: - err = snd_asihpi_meter_add(asihpi, &hpi_ctl, subindex); - break; - case HPI_CONTROL_SAMPLECLOCK: - err = snd_asihpi_sampleclock_add( - asihpi, &hpi_ctl); - break; - case HPI_CONTROL_CONNECTION: /* ignore these */ - continue; - case HPI_CONTROL_TUNER: - err = snd_asihpi_tuner_add(asihpi, &hpi_ctl); - break; - case HPI_CONTROL_AESEBU_TRANSMITTER: - err = snd_asihpi_aesebu_tx_add(asihpi, &hpi_ctl); - break; - case HPI_CONTROL_AESEBU_RECEIVER: - err = snd_asihpi_aesebu_rx_add(asihpi, &hpi_ctl); - break; - case HPI_CONTROL_VOX: - case HPI_CONTROL_BITSTREAM: - case HPI_CONTROL_MICROPHONE: - case HPI_CONTROL_PARAMETRIC_EQ: - case HPI_CONTROL_COMPANDER: - default: - if (mixer_dump) - snd_printk(KERN_INFO - "Untranslated HPI Control" - "(%d) %d %d %d %d %d\n", - idx, - hpi_ctl.control_type, - hpi_ctl.src_node_type, - hpi_ctl.src_node_index, - hpi_ctl.dst_node_type, - hpi_ctl.dst_node_index); - continue; - }; - if (err < 0) - return err; - } - if (HPI_ERROR_INVALID_OBJ_INDEX != err) - hpi_handle_error(err); - - snd_printk(KERN_INFO "%d mixer controls found\n", idx); - - return 0; -} - -/*------------------------------------------------------------ - /proc interface - ------------------------------------------------------------*/ - -static void -snd_asihpi_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_card_asihpi *asihpi = entry->private_data; - u32 h_control; - u32 rate = 0; - u16 source = 0; - - u16 num_outstreams; - u16 num_instreams; - u16 version; - u32 serial_number; - u16 type; - - int err; - - snd_iprintf(buffer, "ASIHPI driver proc file\n"); - - hpi_handle_error(hpi_adapter_get_info(asihpi->hpi->adapter->index, - &num_outstreams, &num_instreams, - &version, &serial_number, &type)); - - snd_iprintf(buffer, - "Adapter type ASI%4X\nHardware Index %d\n" - "%d outstreams\n%d instreams\n", - type, asihpi->hpi->adapter->index, - num_outstreams, num_instreams); - - snd_iprintf(buffer, - "Serial#%d\nHardware version %c%d\nDSP code version %03d\n", - serial_number, ((version >> 3) & 0xf) + 'A', version & 0x7, - ((version >> 13) * 100) + ((version >> 7) & 0x3f)); - - err = hpi_mixer_get_control(asihpi->h_mixer, - HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, - HPI_CONTROL_SAMPLECLOCK, &h_control); - - if (!err) { - err = hpi_sample_clock_get_sample_rate(h_control, &rate); - err += hpi_sample_clock_get_source(h_control, &source); - - if (!err) - snd_iprintf(buffer, "Sample Clock %dHz, source %s\n", - rate, sampleclock_sources[source]); - } -} - -static void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(asihpi->card, "info", &entry)) - snd_info_set_text_ops(entry, asihpi, snd_asihpi_proc_read); -} - -/*------------------------------------------------------------ - HWDEP - ------------------------------------------------------------*/ - -static int snd_asihpi_hpi_open(struct snd_hwdep *hw, struct file *file) -{ - if (enable_hpi_hwdep) - return 0; - else - return -ENODEV; - -} - -static int snd_asihpi_hpi_release(struct snd_hwdep *hw, struct file *file) -{ - if (enable_hpi_hwdep) - return asihpi_hpi_release(file); - else - return -ENODEV; -} - -static int snd_asihpi_hpi_ioctl(struct snd_hwdep *hw, struct file *file, - unsigned int cmd, unsigned long arg) -{ - if (enable_hpi_hwdep) - return asihpi_hpi_ioctl(file, cmd, arg); - else - return -ENODEV; -} - - -/* results in /dev/snd/hwC#D0 file for each card with index # - also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card' -*/ -static int __devinit snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, - int device, struct snd_hwdep **rhwdep) -{ - struct snd_hwdep *hw; - int err; - - if (rhwdep) - *rhwdep = NULL; - err = snd_hwdep_new(asihpi->card, "HPI", device, &hw); - if (err < 0) - return err; - strcpy(hw->name, "asihpi (HPI)"); - hw->iface = SNDRV_HWDEP_IFACE_LAST; - hw->ops.open = snd_asihpi_hpi_open; - hw->ops.ioctl = snd_asihpi_hpi_ioctl; - hw->ops.release = snd_asihpi_hpi_release; - hw->private_data = asihpi; - if (rhwdep) - *rhwdep = hw; - return 0; -} - -/*------------------------------------------------------------ - CARD - ------------------------------------------------------------*/ -static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) -{ - int err; - struct hpi_adapter *hpi; - struct snd_card *card; - struct snd_card_asihpi *asihpi; - - u32 h_control; - u32 h_stream; - u32 adapter_index; - - static int dev; - if (dev >= SNDRV_CARDS) - return -ENODEV; - - /* Should this be enable[hpi->index] ? */ - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - /* Initialise low-level HPI driver */ - err = asihpi_adapter_probe(pci_dev, pci_id); - if (err < 0) - return err; - - hpi = pci_get_drvdata(pci_dev); - adapter_index = hpi->adapter->index; - /* first try to give the card the same index as its hardware index */ - err = snd_card_create(adapter_index, - id[adapter_index], THIS_MODULE, - sizeof(struct snd_card_asihpi), - &card); - if (err < 0) { - /* if that fails, try the default index==next available */ - err = - snd_card_create(index[dev], id[dev], - THIS_MODULE, - sizeof(struct snd_card_asihpi), - &card); - if (err < 0) - return err; - snd_printk(KERN_WARNING - "**** WARNING **** Adapter index %d->ALSA index %d\n", - adapter_index, card->number); - } - - snd_card_set_dev(card, &pci_dev->dev); - - asihpi = card->private_data; - asihpi->card = card; - asihpi->pci = pci_dev; - asihpi->hpi = hpi; - - snd_printk(KERN_INFO "adapter ID=%4X index=%d\n", - asihpi->hpi->adapter->type, adapter_index); - - err = hpi_adapter_get_property(adapter_index, - HPI_ADAPTER_PROPERTY_CAPS1, - NULL, &asihpi->support_grouping); - if (err) - asihpi->support_grouping = 0; - - err = hpi_adapter_get_property(adapter_index, - HPI_ADAPTER_PROPERTY_CAPS2, - &asihpi->support_mrx, NULL); - if (err) - asihpi->support_mrx = 0; - - err = hpi_adapter_get_property(adapter_index, - HPI_ADAPTER_PROPERTY_INTERVAL, - NULL, &asihpi->update_interval_frames); - if (err) - asihpi->update_interval_frames = 512; - - if (!asihpi->can_dma) - asihpi->update_interval_frames *= 2; - - hpi_handle_error(hpi_instream_open(adapter_index, - 0, &h_stream)); - - err = hpi_instream_host_buffer_free(h_stream); - asihpi->can_dma = (!err); - - hpi_handle_error(hpi_instream_close(h_stream)); - - err = hpi_adapter_get_property(adapter_index, - HPI_ADAPTER_PROPERTY_CURCHANNELS, - &asihpi->in_max_chans, &asihpi->out_max_chans); - if (err) { - asihpi->in_max_chans = 2; - asihpi->out_max_chans = 2; - } - - if (asihpi->out_max_chans > 2) { /* assume LL mode */ - asihpi->out_min_chans = asihpi->out_max_chans; - asihpi->in_min_chans = asihpi->in_max_chans; - asihpi->support_grouping = 0; - } else { - asihpi->out_min_chans = 1; - asihpi->in_min_chans = 1; - } - - snd_printk(KERN_INFO "Has dma:%d, grouping:%d, mrx:%d\n", - asihpi->can_dma, - asihpi->support_grouping, - asihpi->support_mrx - ); - - err = snd_card_asihpi_pcm_new(asihpi, 0); - if (err < 0) { - snd_printk(KERN_ERR "pcm_new failed\n"); - goto __nodev; - } - err = snd_card_asihpi_mixer_new(asihpi); - if (err < 0) { - snd_printk(KERN_ERR "mixer_new failed\n"); - goto __nodev; - } - - err = hpi_mixer_get_control(asihpi->h_mixer, - HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, - HPI_CONTROL_SAMPLECLOCK, &h_control); - - if (!err) - err = hpi_sample_clock_set_local_rate( - h_control, adapter_fs); - - snd_asihpi_proc_init(asihpi); - - /* always create, can be enabled or disabled dynamically - by enable_hwdep module param*/ - snd_asihpi_hpi_new(asihpi, 0, NULL); - - strcpy(card->driver, "ASIHPI"); - - sprintf(card->shortname, "AudioScience ASI%4X", - asihpi->hpi->adapter->type); - sprintf(card->longname, "%s %i", - card->shortname, adapter_index); - err = snd_card_register(card); - - if (!err) { - hpi->snd_card = card; - dev++; - return 0; - } -__nodev: - snd_card_free(card); - snd_printk(KERN_ERR "snd_asihpi_probe error %d\n", err); - return err; - -} - -static void __devexit snd_asihpi_remove(struct pci_dev *pci_dev) -{ - struct hpi_adapter *hpi = pci_get_drvdata(pci_dev); - snd_card_free(hpi->snd_card); - hpi->snd_card = NULL; - asihpi_adapter_remove(pci_dev); -} - -static DEFINE_PCI_DEVICE_TABLE(asihpi_pci_tbl) = { - {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, - HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, - (kernel_ulong_t)HPI_6205}, - {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040, - HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, - (kernel_ulong_t)HPI_6000}, - {0,} -}; -MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl); - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = asihpi_pci_tbl, - .probe = snd_asihpi_probe, - .remove = __devexit_p(snd_asihpi_remove), -#ifdef CONFIG_PM -/* .suspend = snd_asihpi_suspend, - .resume = snd_asihpi_resume, */ -#endif -}; - -static int __init snd_asihpi_init(void) -{ - asihpi_init(); - return pci_register_driver(&driver); -} - -static void __exit snd_asihpi_exit(void) -{ - - pci_unregister_driver(&driver); - asihpi_exit(); -} - -module_init(snd_asihpi_init) -module_exit(snd_asihpi_exit) - diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpi.h b/ANDROID_3.4.5/sound/pci/asihpi/hpi.h deleted file mode 100644 index 20887241..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpi.h +++ /dev/null @@ -1,1727 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -*/ -/** \file hpi.h - - AudioScience Hardware Programming Interface (HPI) - public API definition. - - The HPI is a low-level hardware abstraction layer to all - AudioScience digital audio adapters - -(C) Copyright AudioScience Inc. 1998-2010 -*/ - -#ifndef _HPI_H_ -#define _HPI_H_ - -#include -#define HPI_BUILD_KERNEL_MODE - -/******************************************************************************/ -/******** HPI API DEFINITIONS *****/ -/******************************************************************************/ - -/*******************************************/ -/** Audio format types -\ingroup stream -*/ -enum HPI_FORMATS { -/** Used internally on adapter. */ - HPI_FORMAT_MIXER_NATIVE = 0, -/** 8-bit unsigned PCM. Windows equivalent is WAVE_FORMAT_PCM. */ - HPI_FORMAT_PCM8_UNSIGNED = 1, -/** 16-bit signed PCM. Windows equivalent is WAVE_FORMAT_PCM. */ - HPI_FORMAT_PCM16_SIGNED = 2, -/** MPEG-1 Layer-1. */ - HPI_FORMAT_MPEG_L1 = 3, -/** MPEG-1 Layer-2. - -Windows equivalent is WAVE_FORMAT_MPEG. - -The following table shows what combinations of mode and bitrate are possible: - - - -

Bitrate (kbs)

-

Mono

-

Stereo,
Joint Stereo or
Dual Channel

- -
32X_ -
40__ -
48X_ -
56X_ -
64XX -
80X_ -
96XX -
112XX -
128XX -
160XX -
192XX -
224_X -
256-X -
320-X -
384_X -
-*/ - HPI_FORMAT_MPEG_L2 = 4, -/** MPEG-1 Layer-3. -Windows equivalent is WAVE_FORMAT_MPEG. - -The following table shows what combinations of mode and bitrate are possible: - - - -

Bitrate (kbs)

-

Mono
Stereo @ 8,
11.025 and
12kHz*

-

Mono
Stereo @ 16,
22.050 and
24kHz*

-

Mono
Stereo @ 32,
44.1 and
48kHz

- -
16XX_ -
24XX_ -
32XXX -
40XXX -
48XXX -
56XXX -
64XXX -
80_XX -
96_XX -
112_XX -
128_XX -
144_X_ -
160_XX -
192__X -
224__X -
256-_X -
320-_X -
-\b * Available on the ASI6000 series only -*/ - HPI_FORMAT_MPEG_L3 = 5, -/** Dolby AC-2. */ - HPI_FORMAT_DOLBY_AC2 = 6, -/** Dolbt AC-3. */ - HPI_FORMAT_DOLBY_AC3 = 7, -/** 16-bit PCM big-endian. */ - HPI_FORMAT_PCM16_BIGENDIAN = 8, -/** TAGIT-1 algorithm - hits. */ - HPI_FORMAT_AA_TAGIT1_HITS = 9, -/** TAGIT-1 algorithm - inserts. */ - HPI_FORMAT_AA_TAGIT1_INSERTS = 10, -/** 32-bit signed PCM. Windows equivalent is WAVE_FORMAT_PCM. -Each sample is a 32bit word. The most significant 24 bits contain a 24-bit -sample and the least significant 8 bits are set to 0. -*/ - HPI_FORMAT_PCM32_SIGNED = 11, -/** Raw bitstream - unknown format. */ - HPI_FORMAT_RAW_BITSTREAM = 12, -/** TAGIT-1 algorithm hits - extended. */ - HPI_FORMAT_AA_TAGIT1_HITS_EX1 = 13, -/** 32-bit PCM as an IEEE float. Windows equivalent is WAVE_FORMAT_IEEE_FLOAT. -Each sample is a 32bit word in IEEE754 floating point format. -The range is +1.0 to -1.0, which corresponds to digital fullscale. -*/ - HPI_FORMAT_PCM32_FLOAT = 14, -/** 24-bit PCM signed. Windows equivalent is WAVE_FORMAT_PCM. */ - HPI_FORMAT_PCM24_SIGNED = 15, -/** OEM format 1 - private. */ - HPI_FORMAT_OEM1 = 16, -/** OEM format 2 - private. */ - HPI_FORMAT_OEM2 = 17, -/** Undefined format. */ - HPI_FORMAT_UNDEFINED = 0xffff -}; - -/*******************************************/ -/** Stream States -\ingroup stream -*/ -enum HPI_STREAM_STATES { - /** State stopped - stream is stopped. */ - HPI_STATE_STOPPED = 1, - /** State playing - stream is playing audio. */ - HPI_STATE_PLAYING = 2, - /** State recording - stream is recording. */ - HPI_STATE_RECORDING = 3, - /** State drained - playing stream ran out of data to play. */ - HPI_STATE_DRAINED = 4, - /** State generate sine - to be implemented. */ - HPI_STATE_SINEGEN = 5, - /** State wait - used for inter-card sync to mean waiting for all - cards to be ready. */ - HPI_STATE_WAIT = 6 -}; -/*******************************************/ -/** Source node types -\ingroup mixer -*/ -enum HPI_SOURCENODES { - /** This define can be used instead of 0 to indicate - that there is no valid source node. A control that - exists on a destination node can be searched for using a source - node value of either 0, or HPI_SOURCENODE_NONE */ - HPI_SOURCENODE_NONE = 100, - /** Out Stream (Play) node. */ - HPI_SOURCENODE_OSTREAM = 101, - /** Line in node - could be analog, AES/EBU or network. */ - HPI_SOURCENODE_LINEIN = 102, - HPI_SOURCENODE_AESEBU_IN = 103, /**< AES/EBU input node. */ - HPI_SOURCENODE_TUNER = 104, /**< tuner node. */ - HPI_SOURCENODE_RF = 105, /**< RF input node. */ - HPI_SOURCENODE_CLOCK_SOURCE = 106, /**< clock source node. */ - HPI_SOURCENODE_RAW_BITSTREAM = 107, /**< raw bitstream node. */ - HPI_SOURCENODE_MICROPHONE = 108, /**< microphone node. */ - /** Cobranet input node - - Audio samples come from the Cobranet network and into the device. */ - HPI_SOURCENODE_COBRANET = 109, - HPI_SOURCENODE_ANALOG = 110, /**< analog input node. */ - HPI_SOURCENODE_ADAPTER = 111, /**< adapter node. */ - /** RTP stream input node - This node is a destination for - packets of RTP audio samples from other devices. */ - HPI_SOURCENODE_RTP_DESTINATION = 112, - HPI_SOURCENODE_INTERNAL = 113, /**< node internal to the device. */ - /* !!!Update this AND hpidebug.h if you add a new sourcenode type!!! */ - HPI_SOURCENODE_LAST_INDEX = 113 /**< largest ID */ - /* AX6 max sourcenode types = 15 */ -}; - -/*******************************************/ -/** Destination node types -\ingroup mixer -*/ -enum HPI_DESTNODES { - /** This define can be used instead of 0 to indicate - that there is no valid destination node. A control that - exists on a source node can be searched for using a destination - node value of either 0, or HPI_DESTNODE_NONE */ - HPI_DESTNODE_NONE = 200, - /** In Stream (Record) node. */ - HPI_DESTNODE_ISTREAM = 201, - HPI_DESTNODE_LINEOUT = 202, /**< line out node. */ - HPI_DESTNODE_AESEBU_OUT = 203, /**< AES/EBU output node. */ - HPI_DESTNODE_RF = 204, /**< RF output node. */ - HPI_DESTNODE_SPEAKER = 205, /**< speaker output node. */ - /** Cobranet output node - - Audio samples from the device are sent out on the Cobranet network.*/ - HPI_DESTNODE_COBRANET = 206, - HPI_DESTNODE_ANALOG = 207, /**< analog output node. */ - /** RTP stream output node - This node is a source for - packets of RTP audio samples that are sent to other devices. */ - HPI_DESTNODE_RTP_SOURCE = 208, - /* !!!Update this AND hpidebug.h if you add a new destnode type!!! */ - HPI_DESTNODE_LAST_INDEX = 208 /**< largest ID */ - /* AX6 max destnode types = 15 */ -}; - -/*******************************************/ -/** Mixer control types -\ingroup mixer -*/ -enum HPI_CONTROLS { - HPI_CONTROL_GENERIC = 0, /**< generic control. */ - HPI_CONTROL_CONNECTION = 1, /**< A connection between nodes. */ - HPI_CONTROL_VOLUME = 2, /**< volume control - works in dB_fs. */ - HPI_CONTROL_METER = 3, /**< peak meter control. */ - HPI_CONTROL_MUTE = 4, /*mute control - not used at present. */ - HPI_CONTROL_MULTIPLEXER = 5, /**< multiplexer control. */ - - HPI_CONTROL_AESEBU_TRANSMITTER = 6, /**< AES/EBU transmitter control */ - HPI_CONTROL_AESEBUTX = 6, /* HPI_CONTROL_AESEBU_TRANSMITTER */ - - HPI_CONTROL_AESEBU_RECEIVER = 7, /**< AES/EBU receiver control. */ - HPI_CONTROL_AESEBURX = 7, /* HPI_CONTROL_AESEBU_RECEIVER */ - - HPI_CONTROL_LEVEL = 8, /**< level/trim control - works in d_bu. */ - HPI_CONTROL_TUNER = 9, /**< tuner control. */ -/* HPI_CONTROL_ONOFFSWITCH = 10 */ - HPI_CONTROL_VOX = 11, /**< vox control. */ -/* HPI_CONTROL_AES18_TRANSMITTER = 12 */ -/* HPI_CONTROL_AES18_RECEIVER = 13 */ -/* HPI_CONTROL_AES18_BLOCKGENERATOR = 14 */ - HPI_CONTROL_CHANNEL_MODE = 15, /**< channel mode control. */ - - HPI_CONTROL_BITSTREAM = 16, /**< bitstream control. */ - HPI_CONTROL_SAMPLECLOCK = 17, /**< sample clock control. */ - HPI_CONTROL_MICROPHONE = 18, /**< microphone control. */ - HPI_CONTROL_PARAMETRIC_EQ = 19, /**< parametric EQ control. */ - HPI_CONTROL_EQUALIZER = 19, /*HPI_CONTROL_PARAMETRIC_EQ */ - - HPI_CONTROL_COMPANDER = 20, /**< compander control. */ - HPI_CONTROL_COBRANET = 21, /**< cobranet control. */ - HPI_CONTROL_TONEDETECTOR = 22, /**< tone detector control. */ - HPI_CONTROL_SILENCEDETECTOR = 23, /**< silence detector control. */ - HPI_CONTROL_PAD = 24, /**< tuner PAD control. */ - HPI_CONTROL_SRC = 25, /**< samplerate converter control. */ - HPI_CONTROL_UNIVERSAL = 26, /**< universal control. */ - -/* !!! Update this AND hpidebug.h if you add a new control type!!!*/ - HPI_CONTROL_LAST_INDEX = 26 /** 4 line outs = 1 to 8 channel streams), - 4 lineins -> 1 instream (1 to 8 channel streams) at 0-48kHz. - For more info see the SSX Specification. -*/ - HPI_ADAPTER_MODE_MULTICHANNEL = 9, - -/** 12 outstream mode. -- ASI6514, ASI6614: 2 instreams -- ASI6540,ASI6544: 8 instreams -- ASI6640,ASI6644: 8 instreams -*/ - HPI_ADAPTER_MODE_12OSTREAM = 10, - -/** 9 outstream mode. -- ASI6044: 8 instreams -*/ - HPI_ADAPTER_MODE_9OSTREAM = 11, - -/** mono mode. -- ASI6416: 16 outstreams/instreams -- ASI5402: 2 outstreams/instreams -*/ - HPI_ADAPTER_MODE_MONO = 12, - -/** Low latency mode. -- ASI6416/ASI6316: 1 16 channel outstream and instream -*/ - HPI_ADAPTER_MODE_LOW_LATENCY = 13 -}; - -/* Note, adapters can have more than one capability - -encoding as bitfield is recommended. */ -#define HPI_CAPABILITY_NONE (0) -#define HPI_CAPABILITY_MPEG_LAYER3 (1) - -/* Set this equal to maximum capability index, -Must not be greater than 32 - see axnvdef.h */ -#define HPI_CAPABILITY_MAX 1 -/* #define HPI_CAPABILITY_AAC 2 */ - -/******************************************* STREAM ATTRIBUTES ****/ - -/** MPEG Ancillary Data modes - -The mode for the ancillary data insertion or extraction to operate in. -\ingroup stream -*/ -enum HPI_MPEG_ANC_MODES { - /** the MPEG frames have energy information stored in them (5 bytes per stereo frame, 3 per mono) */ - HPI_MPEG_ANC_HASENERGY = 0, - /** the entire ancillary data field is taken up by data from the Anc data buffer - On encode, the encoder will insert the energy bytes before filling the remainder - of the ancillary data space with data from the ancillary data buffer. - */ - HPI_MPEG_ANC_RAW = 1 -}; - -/** Ancillary Data Alignment -\ingroup instream -*/ -enum HPI_ISTREAM_MPEG_ANC_ALIGNS { - /** data is packed against the end of data, then padded to the end of frame */ - HPI_MPEG_ANC_ALIGN_LEFT = 0, - /** data is packed against the end of the frame */ - HPI_MPEG_ANC_ALIGN_RIGHT = 1 -}; - -/** MPEG modes -MPEG modes - can be used optionally for HPI_FormatCreate() -parameter dwAttributes. - -Using any mode setting other than HPI_MPEG_MODE_DEFAULT -with single channel format will return an error. -\ingroup stream -*/ -enum HPI_MPEG_MODES { -/** Causes the MPEG-1 Layer II bitstream to be recorded -in single_channel mode when the number of channels is 1 and in stereo when the -number of channels is 2. */ - HPI_MPEG_MODE_DEFAULT = 0, - /** Standard stereo without joint-stereo compression */ - HPI_MPEG_MODE_STEREO = 1, - /** Joint stereo */ - HPI_MPEG_MODE_JOINTSTEREO = 2, - /** Left and Right channels are completely independent */ - HPI_MPEG_MODE_DUALCHANNEL = 3 -}; -/******************************************* MIXER ATTRIBUTES ****/ - -/* \defgroup mixer_flags Mixer flags for HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES -{ -*/ -#define HPI_MIXER_GET_CONTROL_MULTIPLE_CHANGED (0) -#define HPI_MIXER_GET_CONTROL_MULTIPLE_RESET (1) -/*}*/ - -/** Commands used by HPI_MixerStore() -\ingroup mixer -*/ -enum HPI_MIXER_STORE_COMMAND { -/** Save all mixer control settings. */ - HPI_MIXER_STORE_SAVE = 1, -/** Restore all controls from saved. */ - HPI_MIXER_STORE_RESTORE = 2, -/** Delete saved control settings. */ - HPI_MIXER_STORE_DELETE = 3, -/** Enable auto storage of some control settings. */ - HPI_MIXER_STORE_ENABLE = 4, -/** Disable auto storage of some control settings. */ - HPI_MIXER_STORE_DISABLE = 5, -/** Unimplemented - save the attributes of a single control. */ - HPI_MIXER_STORE_SAVE_SINGLE = 6 -}; - -/****************************/ -/* CONTROL ATTRIBUTE VALUES */ -/****************************/ - -/** Used by mixer plugin enable functions - -E.g. HPI_ParametricEq_SetState() -\ingroup mixer -*/ -enum HPI_SWITCH_STATES { - HPI_SWITCH_OFF = 0, /**< turn the mixer plugin on. */ - HPI_SWITCH_ON = 1 /**< turn the mixer plugin off. */ -}; - -/* Volume control special gain values */ - -/** volumes units are 100ths of a dB -\ingroup volume -*/ -#define HPI_UNITS_PER_dB 100 -/** turns volume control OFF or MUTE -\ingroup volume -*/ -#define HPI_GAIN_OFF (-100 * HPI_UNITS_PER_dB) - -/** channel mask specifying all channels -\ingroup volume -*/ -#define HPI_BITMASK_ALL_CHANNELS (0xFFFFFFFF) - -/** value returned for no signal -\ingroup meter -*/ -#define HPI_METER_MINIMUM (-150 * HPI_UNITS_PER_dB) - -/** autofade profiles -\ingroup volume -*/ -enum HPI_VOLUME_AUTOFADES { -/** log fade - dB attenuation changes linearly over time */ - HPI_VOLUME_AUTOFADE_LOG = 2, -/** linear fade - amplitude changes linearly */ - HPI_VOLUME_AUTOFADE_LINEAR = 3 -}; - -/** The physical encoding format of the AESEBU I/O. - -Used in HPI_Aesebu_Transmitter_SetFormat(), HPI_Aesebu_Receiver_SetFormat() -along with related Get and Query functions -\ingroup aestx -*/ -enum HPI_AESEBU_FORMATS { -/** AES/EBU physical format - AES/EBU balanced "professional" */ - HPI_AESEBU_FORMAT_AESEBU = 1, -/** AES/EBU physical format - S/PDIF unbalanced "consumer" */ - HPI_AESEBU_FORMAT_SPDIF = 2 -}; - -/** AES/EBU error status bits - -Returned by HPI_Aesebu_Receiver_GetErrorStatus() -\ingroup aesrx -*/ -enum HPI_AESEBU_ERRORS { -/** bit0: 1 when PLL is not locked */ - HPI_AESEBU_ERROR_NOT_LOCKED = 0x01, -/** bit1: 1 when signal quality is poor */ - HPI_AESEBU_ERROR_POOR_QUALITY = 0x02, -/** bit2: 1 when there is a parity error */ - HPI_AESEBU_ERROR_PARITY_ERROR = 0x04, -/** bit3: 1 when there is a bi-phase coding violation */ - HPI_AESEBU_ERROR_BIPHASE_VIOLATION = 0x08, -/** bit4: 1 when the validity bit is high */ - HPI_AESEBU_ERROR_VALIDITY = 0x10, -/** bit5: 1 when the CRC error bit is high */ - HPI_AESEBU_ERROR_CRC = 0x20 -}; - -/** \addtogroup pad -\{ -*/ -/** The text string containing the station/channel combination. */ -#define HPI_PAD_CHANNEL_NAME_LEN 16 -/** The text string containing the artist. */ -#define HPI_PAD_ARTIST_LEN 64 -/** The text string containing the title. */ -#define HPI_PAD_TITLE_LEN 64 -/** The text string containing the comment. */ -#define HPI_PAD_COMMENT_LEN 256 -/** The PTY when the tuner has not received any PTY. */ -#define HPI_PAD_PROGRAM_TYPE_INVALID 0xffff -/** \} */ - -/** Data types for PTY string translation. -\ingroup rds -*/ -enum eHPI_RDS_type { - HPI_RDS_DATATYPE_RDS = 0, /**< RDS bitstream.*/ - HPI_RDS_DATATYPE_RBDS = 1 /**< RBDS bitstream.*/ -}; - -/** Tuner bands - -Used for HPI_Tuner_SetBand(),HPI_Tuner_GetBand() -\ingroup tuner -*/ -enum HPI_TUNER_BAND { - HPI_TUNER_BAND_AM = 1, /**< AM band */ - HPI_TUNER_BAND_FM = 2, /**< FM band (mono) */ - HPI_TUNER_BAND_TV_NTSC_M = 3, /**< NTSC-M TV band*/ - HPI_TUNER_BAND_TV = 3, /* use TV_NTSC_M */ - HPI_TUNER_BAND_FM_STEREO = 4, /**< FM band (stereo) */ - HPI_TUNER_BAND_AUX = 5, /**< auxiliary input */ - HPI_TUNER_BAND_TV_PAL_BG = 6, /**< PAL-B/G TV band*/ - HPI_TUNER_BAND_TV_PAL_I = 7, /**< PAL-I TV band*/ - HPI_TUNER_BAND_TV_PAL_DK = 8, /**< PAL-D/K TV band*/ - HPI_TUNER_BAND_TV_SECAM_L = 9, /**< SECAM-L TV band*/ - HPI_TUNER_BAND_LAST = 9 /**< the index of the last tuner band. */ -}; - -/** Tuner mode attributes - -Used by HPI_Tuner_SetMode(), HPI_Tuner_GetMode() -\ingroup tuner - -*/ -enum HPI_TUNER_MODES { - HPI_TUNER_MODE_RSS = 1, /**< control RSS */ - HPI_TUNER_MODE_RDS = 2 /**< control RBDS/RDS */ -}; - -/** Tuner mode attribute values - -Used by HPI_Tuner_SetMode(), HPI_Tuner_GetMode() -\ingroup tuner -*/ -enum HPI_TUNER_MODE_VALUES { -/* RSS attribute values */ - HPI_TUNER_MODE_RSS_DISABLE = 0, /**< RSS disable */ - HPI_TUNER_MODE_RSS_ENABLE = 1, /**< RSS enable */ - -/* RDS mode attributes */ - HPI_TUNER_MODE_RDS_DISABLE = 0, /**< RDS - disabled */ - HPI_TUNER_MODE_RDS_RDS = 1, /**< RDS - RDS mode */ - HPI_TUNER_MODE_RDS_RBDS = 2 /**< RDS - RBDS mode */ -}; - -/** Tuner Status Bits - -These bitfield values are returned by a call to HPI_Tuner_GetStatus(). -Multiple fields are returned from a single call. -\ingroup tuner -*/ -enum HPI_TUNER_STATUS_BITS { - HPI_TUNER_VIDEO_COLOR_PRESENT = 0x0001, /**< video color is present. */ - HPI_TUNER_VIDEO_IS_60HZ = 0x0020, /**< 60 hz video detected. */ - HPI_TUNER_VIDEO_HORZ_SYNC_MISSING = 0x0040, /**< video HSYNC is missing. */ - HPI_TUNER_VIDEO_STATUS_VALID = 0x0100, /**< video status is valid. */ - HPI_TUNER_DIGITAL = 0x0200, /**< tuner reports digital programming. */ - HPI_TUNER_MULTIPROGRAM = 0x0400, /**< tuner reports multiple programs. */ - HPI_TUNER_PLL_LOCKED = 0x1000, /**< the tuner's PLL is locked. */ - HPI_TUNER_FM_STEREO = 0x2000 /**< tuner reports back FM stereo. */ -}; - -/** Channel Modes -Used for HPI_ChannelModeSet/Get() -\ingroup channelmode -*/ -enum HPI_CHANNEL_MODES { -/** Left channel out = left channel in, Right channel out = right channel in. */ - HPI_CHANNEL_MODE_NORMAL = 1, -/** Left channel out = right channel in, Right channel out = left channel in. */ - HPI_CHANNEL_MODE_SWAP = 2, -/** Left channel out = left channel in, Right channel out = left channel in. */ - HPI_CHANNEL_MODE_LEFT_TO_STEREO = 3, -/** Left channel out = right channel in, Right channel out = right channel in.*/ - HPI_CHANNEL_MODE_RIGHT_TO_STEREO = 4, -/** Left channel out = (left channel in + right channel in)/2, - Right channel out = mute. */ - HPI_CHANNEL_MODE_STEREO_TO_LEFT = 5, -/** Left channel out = mute, - Right channel out = (right channel in + left channel in)/2. */ - HPI_CHANNEL_MODE_STEREO_TO_RIGHT = 6, - HPI_CHANNEL_MODE_LAST = 6 -}; - -/** SampleClock source values -\ingroup sampleclock -*/ -enum HPI_SAMPLECLOCK_SOURCES { -/** The sampleclock output is derived from its local samplerate generator. - The local samplerate may be set using HPI_SampleClock_SetLocalRate(). */ - HPI_SAMPLECLOCK_SOURCE_LOCAL = 1, -/** The adapter is clocked from a dedicated AES/EBU SampleClock input.*/ - HPI_SAMPLECLOCK_SOURCE_AESEBU_SYNC = 2, -/** From external wordclock connector */ - HPI_SAMPLECLOCK_SOURCE_WORD = 3, -/** Board-to-board header */ - HPI_SAMPLECLOCK_SOURCE_WORD_HEADER = 4, -/** FUTURE - SMPTE clock. */ - HPI_SAMPLECLOCK_SOURCE_SMPTE = 5, -/** One of the aesebu inputs */ - HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT = 6, -/** From a network interface e.g. Cobranet or Livewire at either 48 or 96kHz */ - HPI_SAMPLECLOCK_SOURCE_NETWORK = 8, -/** From previous adjacent module (ASI2416 only)*/ - HPI_SAMPLECLOCK_SOURCE_PREV_MODULE = 10, -/*! Update this if you add a new clock source.*/ - HPI_SAMPLECLOCK_SOURCE_LAST = 10 -}; - -/** Equalizer filter types. Used by HPI_ParametricEq_SetBand() -\ingroup parmeq -*/ -enum HPI_FILTER_TYPE { - HPI_FILTER_TYPE_BYPASS = 0, /**< filter is turned off */ - - HPI_FILTER_TYPE_LOWSHELF = 1, /**< EQ low shelf */ - HPI_FILTER_TYPE_HIGHSHELF = 2, /**< EQ high shelf */ - HPI_FILTER_TYPE_EQ_BAND = 3, /**< EQ gain */ - - HPI_FILTER_TYPE_LOWPASS = 4, /**< standard low pass */ - HPI_FILTER_TYPE_HIGHPASS = 5, /**< standard high pass */ - HPI_FILTER_TYPE_BANDPASS = 6, /**< standard band pass */ - HPI_FILTER_TYPE_BANDSTOP = 7 /**< standard band stop/notch */ -}; - -/** Async Event sources -\ingroup async -*/ -enum ASYNC_EVENT_SOURCES { - HPI_ASYNC_EVENT_GPIO = 1, /**< GPIO event. */ - HPI_ASYNC_EVENT_SILENCE = 2, /**< silence event detected. */ - HPI_ASYNC_EVENT_TONE = 3 /**< tone event detected. */ -}; -/*******************************************/ -/** HPI Error codes - -Almost all HPI functions return an error code -A return value of zero means there was no error. -Otherwise one of these error codes is returned. -Error codes can be converted to a descriptive string using HPI_GetErrorText() - -\note When a new error code is added HPI_GetErrorText() MUST be updated. -\note Codes 1-100 are reserved for driver use -\ingroup utility -*/ -enum HPI_ERROR_CODES { - /** Message type does not exist. */ - HPI_ERROR_INVALID_TYPE = 100, - /** Object type does not exist. */ - HPI_ERROR_INVALID_OBJ = 101, - /** Function does not exist. */ - HPI_ERROR_INVALID_FUNC = 102, - /** The specified object does not exist. */ - HPI_ERROR_INVALID_OBJ_INDEX = 103, - /** Trying to access an object that has not been opened yet. */ - HPI_ERROR_OBJ_NOT_OPEN = 104, - /** Trying to open an already open object. */ - HPI_ERROR_OBJ_ALREADY_OPEN = 105, - /** PCI, ISA resource not valid. */ - HPI_ERROR_INVALID_RESOURCE = 106, - /* HPI_ERROR_SUBSYSFINDADAPTERS_GETINFO= 107 */ - /** Default response was never updated with actual error code. */ - HPI_ERROR_INVALID_RESPONSE = 108, - /** wSize field of response was not updated, - indicating that the message was not processed. */ - HPI_ERROR_PROCESSING_MESSAGE = 109, - /** The network did not respond in a timely manner. */ - HPI_ERROR_NETWORK_TIMEOUT = 110, - /* An HPI handle is invalid (uninitialised?). */ - HPI_ERROR_INVALID_HANDLE = 111, - /** A function or attribute has not been implemented yet. */ - HPI_ERROR_UNIMPLEMENTED = 112, - /** There are too many clients attempting - to access a network resource. */ - HPI_ERROR_NETWORK_TOO_MANY_CLIENTS = 113, - /** Response buffer passed to HPI_Message - was smaller than returned response. - wSpecificError field of hpi response contains the required size. - */ - HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL = 114, - /** The returned response did not match the sent message */ - HPI_ERROR_RESPONSE_MISMATCH = 115, - /** A control setting that should have been cached was not. */ - HPI_ERROR_CONTROL_CACHING = 116, - /** A message buffer in the path to the adapter was smaller - than the message size. - wSpecificError field of hpi response contains the actual size. - */ - HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL = 117, - - /* HPI_ERROR_TOO_MANY_ADAPTERS= 200 */ - /** Bad adpater. */ - HPI_ERROR_BAD_ADAPTER = 201, - /** Adapter number out of range or not set properly. */ - HPI_ERROR_BAD_ADAPTER_NUMBER = 202, - /** 2 adapters with the same adapter number. */ - HPI_ERROR_DUPLICATE_ADAPTER_NUMBER = 203, - /** DSP code failed to bootload. Usually a DSP memory test failure. */ - HPI_ERROR_DSP_BOOTLOAD = 204, - /** Couldn't find or open the DSP code file. */ - HPI_ERROR_DSP_FILE_NOT_FOUND = 206, - /** Internal DSP hardware error. */ - HPI_ERROR_DSP_HARDWARE = 207, - /** Could not allocate memory */ - HPI_ERROR_MEMORY_ALLOC = 208, - /** Failed to correctly load/config PLD. (unused) */ - HPI_ERROR_PLD_LOAD = 209, - /** Unexpected end of file, block length too big etc. */ - HPI_ERROR_DSP_FILE_FORMAT = 210, - - /** Found but could not open DSP code file. */ - HPI_ERROR_DSP_FILE_ACCESS_DENIED = 211, - /** First DSP code section header not found in DSP file. */ - HPI_ERROR_DSP_FILE_NO_HEADER = 212, - /* HPI_ERROR_DSP_FILE_READ_ERROR= 213, */ - /** DSP code for adapter family not found. */ - HPI_ERROR_DSP_SECTION_NOT_FOUND = 214, - /** Other OS specific error opening DSP file. */ - HPI_ERROR_DSP_FILE_OTHER_ERROR = 215, - /** Sharing violation opening DSP code file. */ - HPI_ERROR_DSP_FILE_SHARING_VIOLATION = 216, - /** DSP code section header had size == 0. */ - HPI_ERROR_DSP_FILE_NULL_HEADER = 217, - - /* HPI_ERROR_FLASH = 220, */ - - /** Flash has bad checksum */ - HPI_ERROR_BAD_CHECKSUM = 221, - HPI_ERROR_BAD_SEQUENCE = 222, - HPI_ERROR_FLASH_ERASE = 223, - HPI_ERROR_FLASH_PROGRAM = 224, - HPI_ERROR_FLASH_VERIFY = 225, - HPI_ERROR_FLASH_TYPE = 226, - HPI_ERROR_FLASH_START = 227, - HPI_ERROR_FLASH_READ = 228, - HPI_ERROR_FLASH_READ_NO_FILE = 229, - HPI_ERROR_FLASH_SIZE = 230, - - /** Reserved for OEMs. */ - HPI_ERROR_RESERVED_1 = 290, - - /* HPI_ERROR_INVALID_STREAM = 300 use HPI_ERROR_INVALID_OBJ_INDEX */ - /** Invalid compression format. */ - HPI_ERROR_INVALID_FORMAT = 301, - /** Invalid format samplerate */ - HPI_ERROR_INVALID_SAMPLERATE = 302, - /** Invalid format number of channels. */ - HPI_ERROR_INVALID_CHANNELS = 303, - /** Invalid format bitrate. */ - HPI_ERROR_INVALID_BITRATE = 304, - /** Invalid datasize used for stream read/write. */ - HPI_ERROR_INVALID_DATASIZE = 305, - /* HPI_ERROR_BUFFER_FULL = 306 use HPI_ERROR_INVALID_DATASIZE */ - /* HPI_ERROR_BUFFER_EMPTY = 307 use HPI_ERROR_INVALID_DATASIZE */ - /** Null data pointer used for stream read/write. */ - HPI_ERROR_INVALID_DATA_POINTER = 308, - /** Packet ordering error for stream read/write. */ - HPI_ERROR_INVALID_PACKET_ORDER = 309, - - /** Object can't do requested operation in its current - state, eg set format, change rec mux state while recording.*/ - HPI_ERROR_INVALID_OPERATION = 310, - - /** Where a SRG is shared amongst streams, an incompatible samplerate - is one that is different to any currently active stream. */ - HPI_ERROR_INCOMPATIBLE_SAMPLERATE = 311, - /** Adapter mode is illegal.*/ - HPI_ERROR_BAD_ADAPTER_MODE = 312, - - /** There have been too many attempts to set the adapter's - capabilities (using bad keys), the card should be returned - to ASI if further capabilities updates are required */ - HPI_ERROR_TOO_MANY_CAPABILITY_CHANGE_ATTEMPTS = 313, - /** Streams on different adapters cannot be grouped. */ - HPI_ERROR_NO_INTERADAPTER_GROUPS = 314, - /** Streams on different DSPs cannot be grouped. */ - HPI_ERROR_NO_INTERDSP_GROUPS = 315, - /** Stream wait cancelled before threshold reached. */ - HPI_ERROR_WAIT_CANCELLED = 316, - /** A character string is invalid. */ - HPI_ERROR_INVALID_STRING = 317, - - /** Invalid mixer node for this adapter. */ - HPI_ERROR_INVALID_NODE = 400, - /** Invalid control. */ - HPI_ERROR_INVALID_CONTROL = 401, - /** Invalid control value was passed. */ - HPI_ERROR_INVALID_CONTROL_VALUE = 402, - /** Control attribute not supported by this control. */ - HPI_ERROR_INVALID_CONTROL_ATTRIBUTE = 403, - /** Control is disabled. */ - HPI_ERROR_CONTROL_DISABLED = 404, - /** I2C transaction failed due to a missing ACK. */ - HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405, - HPI_ERROR_I2C_MISSING_ACK = 405, - /** Control is busy, or coming out of - reset and cannot be accessed at this time. */ - HPI_ERROR_CONTROL_NOT_READY = 407, - - /** Non volatile memory */ - HPI_ERROR_NVMEM_BUSY = 450, - HPI_ERROR_NVMEM_FULL = 451, - HPI_ERROR_NVMEM_FAIL = 452, - - /** I2C */ - HPI_ERROR_I2C_BAD_ADR = 460, - - /** Entity type did not match requested type */ - HPI_ERROR_ENTITY_TYPE_MISMATCH = 470, - /** Entity item count did not match requested count */ - HPI_ERROR_ENTITY_ITEM_COUNT = 471, - /** Entity type is not one of the valid types */ - HPI_ERROR_ENTITY_TYPE_INVALID = 472, - /** Entity role is not one of the valid roles */ - HPI_ERROR_ENTITY_ROLE_INVALID = 473, - /** Entity size doesn't match target size */ - HPI_ERROR_ENTITY_SIZE_MISMATCH = 474, - - /* AES18 specific errors were 500..507 */ - - /** custom error to use for debugging */ - HPI_ERROR_CUSTOM = 600, - - /** hpioct32.c can't obtain mutex */ - HPI_ERROR_MUTEX_TIMEOUT = 700, - - /** Backend errors used to be greater than this. - \deprecated Now, all backends return only errors defined here in hpi.h - */ - HPI_ERROR_BACKEND_BASE = 900, - - /** Communication with DSP failed */ - HPI_ERROR_DSP_COMMUNICATION = 900 - /* Note that the dsp communication error is set to this value so that - it remains compatible with any software that expects such errors - to be backend errors i.e. >= 900. - Do not define any new error codes with values > 900. - */ -}; - -/** \defgroup maximums HPI maximum values -\{ -*/ -/** Maximum number of PCI HPI adapters */ -#define HPI_MAX_ADAPTERS 20 -/** Maximum number of in or out streams per adapter */ -#define HPI_MAX_STREAMS 16 -#define HPI_MAX_CHANNELS 2 /* per stream */ -#define HPI_MAX_NODES 8 /* per mixer ? */ -#define HPI_MAX_CONTROLS 4 /* per node ? */ -/** maximum number of ancillary bytes per MPEG frame */ -#define HPI_MAX_ANC_BYTES_PER_FRAME (64) -#define HPI_STRING_LEN 16 - -/** Networked adapters have index >= 100 */ -#define HPI_MIN_NETWORK_ADAPTER_IDX 100 - -/** Velocity units */ -#define HPI_OSTREAM_VELOCITY_UNITS 4096 -/** OutStream timescale units */ -#define HPI_OSTREAM_TIMESCALE_UNITS 10000 -/** OutStream timescale passthrough - turns timescaling on in passthough mode */ -#define HPI_OSTREAM_TIMESCALE_PASSTHROUGH 99999 - -/**\}*/ - -/**************/ -/* STRUCTURES */ -#ifndef DISABLE_PRAGMA_PACK1 -#pragma pack(push, 1) -#endif - -/** Structure containing sample format information. - See also HPI_FormatCreate(). - */ -struct hpi_format { - u32 sample_rate; - /**< 11025, 32000, 44100 ... */ - u32 bit_rate; /**< for MPEG */ - u32 attributes; - /**< Stereo/JointStereo/Mono */ - u16 mode_legacy; - /**< Legacy ancillary mode or idle bit */ - u16 unused; /**< Unused */ - u16 channels; /**< 1,2..., (or ancillary mode or idle bit */ - u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */ -}; - -struct hpi_anc_frame { - u32 valid_bits_in_this_frame; - u8 b_data[HPI_MAX_ANC_BYTES_PER_FRAME]; -}; - -/** An object for containing a single async event. -*/ -struct hpi_async_event { - u16 event_type; /**< type of event. \sa async_event */ - u16 sequence; /**< Sequence number, allows lost event detection */ - u32 state; /**< New state */ - u32 h_object; /**< handle to the object returning the event. */ - union { - struct { - u16 index; /**< GPIO bit index. */ - } gpio; - struct { - u16 node_index; /**< what node is the control on ? */ - u16 node_type; /**< what type of node is the control on ? */ - } control; - } u; -}; - -#ifndef DISABLE_PRAGMA_PACK1 -#pragma pack(pop) -#endif - -/*****************/ -/* HPI FUNCTIONS */ -/*****************/ - -/* Stream */ -u16 hpi_stream_estimate_buffer_size(struct hpi_format *pF, - u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size); - -/*************/ -/* SubSystem */ -/*************/ - -u16 hpi_subsys_get_version_ex(u32 *pversion_ex); - -u16 hpi_subsys_get_num_adapters(int *pn_num_adapters); - -u16 hpi_subsys_get_adapter(int iterator, u32 *padapter_index, - u16 *pw_adapter_type); - -/***********/ -/* Adapter */ -/***********/ - -u16 hpi_adapter_open(u16 adapter_index); - -u16 hpi_adapter_close(u16 adapter_index); - -u16 hpi_adapter_get_info(u16 adapter_index, u16 *pw_num_outstreams, - u16 *pw_num_instreams, u16 *pw_version, u32 *pserial_number, - u16 *pw_adapter_type); - -u16 hpi_adapter_get_module_by_index(u16 adapter_index, u16 module_index, - u16 *pw_num_outputs, u16 *pw_num_inputs, u16 *pw_version, - u32 *pserial_number, u16 *pw_module_type, u32 *ph_module); - -u16 hpi_adapter_set_mode(u16 adapter_index, u32 adapter_mode); - -u16 hpi_adapter_set_mode_ex(u16 adapter_index, u32 adapter_mode, - u16 query_or_set); - -u16 hpi_adapter_get_mode(u16 adapter_index, u32 *padapter_mode); - -u16 hpi_adapter_get_assert2(u16 adapter_index, u16 *p_assert_count, - char *psz_assert, u32 *p_param1, u32 *p_param2, - u32 *p_dsp_string_addr, u16 *p_processor_id); - -u16 hpi_adapter_test_assert(u16 adapter_index, u16 assert_id); - -u16 hpi_adapter_enable_capability(u16 adapter_index, u16 capability, u32 key); - -u16 hpi_adapter_self_test(u16 adapter_index); - -u16 hpi_adapter_debug_read(u16 adapter_index, u32 dsp_address, char *p_bytes, - int *count_bytes); - -u16 hpi_adapter_set_property(u16 adapter_index, u16 property, u16 paramter1, - u16 paramter2); - -u16 hpi_adapter_get_property(u16 adapter_index, u16 property, - u16 *pw_paramter1, u16 *pw_paramter2); - -u16 hpi_adapter_enumerate_property(u16 adapter_index, u16 index, - u16 what_to_enumerate, u16 property_index, u32 *psetting); -/*************/ -/* OutStream */ -/*************/ -u16 hpi_outstream_open(u16 adapter_index, u16 outstream_index, - u32 *ph_outstream); - -u16 hpi_outstream_close(u32 h_outstream); - -u16 hpi_outstream_get_info_ex(u32 h_outstream, u16 *pw_state, - u32 *pbuffer_size, u32 *pdata_to_play, u32 *psamples_played, - u32 *pauxiliary_data_to_play); - -u16 hpi_outstream_write_buf(u32 h_outstream, const u8 *pb_write_buf, - u32 bytes_to_write, const struct hpi_format *p_format); - -u16 hpi_outstream_start(u32 h_outstream); - -u16 hpi_outstream_wait_start(u32 h_outstream); - -u16 hpi_outstream_stop(u32 h_outstream); - -u16 hpi_outstream_sinegen(u32 h_outstream); - -u16 hpi_outstream_reset(u32 h_outstream); - -u16 hpi_outstream_query_format(u32 h_outstream, struct hpi_format *p_format); - -u16 hpi_outstream_set_format(u32 h_outstream, struct hpi_format *p_format); - -u16 hpi_outstream_set_punch_in_out(u32 h_outstream, u32 punch_in_sample, - u32 punch_out_sample); - -u16 hpi_outstream_set_velocity(u32 h_outstream, short velocity); - -u16 hpi_outstream_ancillary_reset(u32 h_outstream, u16 mode); - -u16 hpi_outstream_ancillary_get_info(u32 h_outstream, u32 *pframes_available); - -u16 hpi_outstream_ancillary_read(u32 h_outstream, - struct hpi_anc_frame *p_anc_frame_buffer, - u32 anc_frame_buffer_size_in_bytes, - u32 number_of_ancillary_frames_to_read); - -u16 hpi_outstream_set_time_scale(u32 h_outstream, u32 time_scaleX10000); - -u16 hpi_outstream_host_buffer_allocate(u32 h_outstream, u32 size_in_bytes); - -u16 hpi_outstream_host_buffer_free(u32 h_outstream); - -u16 hpi_outstream_group_add(u32 h_outstream, u32 h_stream); - -u16 hpi_outstream_group_get_map(u32 h_outstream, u32 *poutstream_map, - u32 *pinstream_map); - -u16 hpi_outstream_group_reset(u32 h_outstream); - -/************/ -/* InStream */ -/************/ -u16 hpi_instream_open(u16 adapter_index, u16 instream_index, - u32 *ph_instream); - -u16 hpi_instream_close(u32 h_instream); - -u16 hpi_instream_query_format(u32 h_instream, - const struct hpi_format *p_format); - -u16 hpi_instream_set_format(u32 h_instream, - const struct hpi_format *p_format); - -u16 hpi_instream_read_buf(u32 h_instream, u8 *pb_read_buf, u32 bytes_to_read); - -u16 hpi_instream_start(u32 h_instream); - -u16 hpi_instream_wait_start(u32 h_instream); - -u16 hpi_instream_stop(u32 h_instream); - -u16 hpi_instream_reset(u32 h_instream); - -u16 hpi_instream_get_info_ex(u32 h_instream, u16 *pw_state, u32 *pbuffer_size, - u32 *pdata_recorded, u32 *psamples_recorded, - u32 *pauxiliary_data_recorded); - -u16 hpi_instream_ancillary_reset(u32 h_instream, u16 bytes_per_frame, - u16 mode, u16 alignment, u16 idle_bit); - -u16 hpi_instream_ancillary_get_info(u32 h_instream, u32 *pframe_space); - -u16 hpi_instream_ancillary_write(u32 h_instream, - const struct hpi_anc_frame *p_anc_frame_buffer, - u32 anc_frame_buffer_size_in_bytes, - u32 number_of_ancillary_frames_to_write); - -u16 hpi_instream_host_buffer_allocate(u32 h_instream, u32 size_in_bytes); - -u16 hpi_instream_host_buffer_free(u32 h_instream); - -u16 hpi_instream_group_add(u32 h_instream, u32 h_stream); - -u16 hpi_instream_group_get_map(u32 h_instream, u32 *poutstream_map, - u32 *pinstream_map); - -u16 hpi_instream_group_reset(u32 h_instream); - -/*********/ -/* Mixer */ -/*********/ -u16 hpi_mixer_open(u16 adapter_index, u32 *ph_mixer); - -u16 hpi_mixer_close(u32 h_mixer); - -u16 hpi_mixer_get_control(u32 h_mixer, u16 src_node_type, - u16 src_node_type_index, u16 dst_node_type, u16 dst_node_type_index, - u16 control_type, u32 *ph_control); - -u16 hpi_mixer_get_control_by_index(u32 h_mixer, u16 control_index, - u16 *pw_src_node_type, u16 *pw_src_node_index, u16 *pw_dst_node_type, - u16 *pw_dst_node_index, u16 *pw_control_type, u32 *ph_control); - -u16 hpi_mixer_store(u32 h_mixer, enum HPI_MIXER_STORE_COMMAND command, - u16 index); -/************/ -/* Controls */ -/************/ -/******************/ -/* Volume control */ -/******************/ -u16 hpi_volume_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS] - ); - -u16 hpi_volume_get_gain(u32 h_control, - short an_gain0_01dB_out[HPI_MAX_CHANNELS] - ); - -u16 hpi_volume_set_mute(u32 h_control, u32 mute); - -u16 hpi_volume_get_mute(u32 h_control, u32 *mute); - -#define hpi_volume_get_range hpi_volume_query_range -u16 hpi_volume_query_range(u32 h_control, short *min_gain_01dB, - short *max_gain_01dB, short *step_gain_01dB); - -u16 hpi_volume_query_channels(const u32 h_control, u32 *p_channels); - -u16 hpi_volume_auto_fade(u32 h_control, - short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms); - -u16 hpi_volume_auto_fade_profile(u32 h_control, - short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms, - u16 profile); - -u16 hpi_volume_query_auto_fade_profile(const u32 h_control, const u32 i, - u16 *profile); - -/*****************/ -/* Level control */ -/*****************/ -u16 hpi_level_query_range(u32 h_control, short *min_gain_01dB, - short *max_gain_01dB, short *step_gain_01dB); - -u16 hpi_level_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS] - ); - -u16 hpi_level_get_gain(u32 h_control, - short an_gain0_01dB_out[HPI_MAX_CHANNELS] - ); - -/*****************/ -/* Meter control */ -/*****************/ -u16 hpi_meter_query_channels(const u32 h_meter, u32 *p_channels); - -u16 hpi_meter_get_peak(u32 h_control, - short an_peak0_01dB_out[HPI_MAX_CHANNELS] - ); - -u16 hpi_meter_get_rms(u32 h_control, short an_peak0_01dB_out[HPI_MAX_CHANNELS] - ); - -u16 hpi_meter_set_peak_ballistics(u32 h_control, u16 attack, u16 decay); - -u16 hpi_meter_set_rms_ballistics(u32 h_control, u16 attack, u16 decay); - -u16 hpi_meter_get_peak_ballistics(u32 h_control, u16 *attack, u16 *decay); - -u16 hpi_meter_get_rms_ballistics(u32 h_control, u16 *attack, u16 *decay); - -/************************/ -/* ChannelMode control */ -/************************/ -u16 hpi_channel_mode_query_mode(const u32 h_mode, const u32 index, - u16 *pw_mode); - -u16 hpi_channel_mode_set(u32 h_control, u16 mode); - -u16 hpi_channel_mode_get(u32 h_control, u16 *mode); - -/*****************/ -/* Tuner control */ -/*****************/ -u16 hpi_tuner_query_band(const u32 h_tuner, const u32 index, u16 *pw_band); - -u16 hpi_tuner_set_band(u32 h_control, u16 band); - -u16 hpi_tuner_get_band(u32 h_control, u16 *pw_band); - -u16 hpi_tuner_query_frequency(const u32 h_tuner, const u32 index, - const u16 band, u32 *pfreq); - -u16 hpi_tuner_set_frequency(u32 h_control, u32 freq_ink_hz); - -u16 hpi_tuner_get_frequency(u32 h_control, u32 *pw_freq_ink_hz); - -u16 hpi_tuner_get_rf_level(u32 h_control, short *pw_level); - -u16 hpi_tuner_get_raw_rf_level(u32 h_control, short *pw_level); - -u16 hpi_tuner_query_gain(const u32 h_tuner, const u32 index, u16 *pw_gain); - -u16 hpi_tuner_set_gain(u32 h_control, short gain); - -u16 hpi_tuner_get_gain(u32 h_control, short *pn_gain); - -u16 hpi_tuner_get_status(u32 h_control, u16 *pw_status_mask, u16 *pw_status); - -u16 hpi_tuner_set_mode(u32 h_control, u32 mode, u32 value); - -u16 hpi_tuner_get_mode(u32 h_control, u32 mode, u32 *pn_value); - -u16 hpi_tuner_get_rds(u32 h_control, char *p_rds_data); - -u16 hpi_tuner_query_deemphasis(const u32 h_tuner, const u32 index, - const u16 band, u32 *pdeemphasis); - -u16 hpi_tuner_set_deemphasis(u32 h_control, u32 deemphasis); -u16 hpi_tuner_get_deemphasis(u32 h_control, u32 *pdeemphasis); - -u16 hpi_tuner_query_program(const u32 h_tuner, u32 *pbitmap_program); - -u16 hpi_tuner_set_program(u32 h_control, u32 program); - -u16 hpi_tuner_get_program(u32 h_control, u32 *pprogram); - -u16 hpi_tuner_get_hd_radio_dsp_version(u32 h_control, char *psz_dsp_version, - const u32 string_size); - -u16 hpi_tuner_get_hd_radio_sdk_version(u32 h_control, char *psz_sdk_version, - const u32 string_size); - -u16 hpi_tuner_get_hd_radio_signal_quality(u32 h_control, u32 *pquality); - -u16 hpi_tuner_get_hd_radio_signal_blend(u32 h_control, u32 *pblend); - -u16 hpi_tuner_set_hd_radio_signal_blend(u32 h_control, const u32 blend); - -/***************/ -/* PAD control */ -/***************/ - -u16 hpi_pad_get_channel_name(u32 h_control, char *psz_string, - const u32 string_length); - -u16 hpi_pad_get_artist(u32 h_control, char *psz_string, - const u32 string_length); - -u16 hpi_pad_get_title(u32 h_control, char *psz_string, - const u32 string_length); - -u16 hpi_pad_get_comment(u32 h_control, char *psz_string, - const u32 string_length); - -u16 hpi_pad_get_program_type(u32 h_control, u32 *ppTY); - -u16 hpi_pad_get_rdsPI(u32 h_control, u32 *ppI); - -u16 hpi_pad_get_program_type_string(u32 h_control, const u32 data_type, - const u32 pTY, char *psz_string, const u32 string_length); - -/****************************/ -/* AES/EBU Receiver control */ -/****************************/ -u16 hpi_aesebu_receiver_query_format(const u32 h_aes_rx, const u32 index, - u16 *pw_format); - -u16 hpi_aesebu_receiver_set_format(u32 h_control, u16 source); - -u16 hpi_aesebu_receiver_get_format(u32 h_control, u16 *pw_source); - -u16 hpi_aesebu_receiver_get_sample_rate(u32 h_control, u32 *psample_rate); - -u16 hpi_aesebu_receiver_get_user_data(u32 h_control, u16 index, u16 *pw_data); - -u16 hpi_aesebu_receiver_get_channel_status(u32 h_control, u16 index, - u16 *pw_data); - -u16 hpi_aesebu_receiver_get_error_status(u32 h_control, u16 *pw_error_data); - -/*******************************/ -/* AES/EBU Transmitter control */ -/*******************************/ -u16 hpi_aesebu_transmitter_set_sample_rate(u32 h_control, u32 sample_rate); - -u16 hpi_aesebu_transmitter_set_user_data(u32 h_control, u16 index, u16 data); - -u16 hpi_aesebu_transmitter_set_channel_status(u32 h_control, u16 index, - u16 data); - -u16 hpi_aesebu_transmitter_get_channel_status(u32 h_control, u16 index, - u16 *pw_data); - -u16 hpi_aesebu_transmitter_query_format(const u32 h_aes_tx, const u32 index, - u16 *pw_format); - -u16 hpi_aesebu_transmitter_set_format(u32 h_control, u16 output_format); - -u16 hpi_aesebu_transmitter_get_format(u32 h_control, u16 *pw_output_format); - -/***********************/ -/* Multiplexer control */ -/***********************/ -u16 hpi_multiplexer_set_source(u32 h_control, u16 source_node_type, - u16 source_node_index); - -u16 hpi_multiplexer_get_source(u32 h_control, u16 *source_node_type, - u16 *source_node_index); - -u16 hpi_multiplexer_query_source(u32 h_control, u16 index, - u16 *source_node_type, u16 *source_node_index); - -/***************/ -/* Vox control */ -/***************/ -u16 hpi_vox_set_threshold(u32 h_control, short an_gain0_01dB); - -u16 hpi_vox_get_threshold(u32 h_control, short *an_gain0_01dB); - -/*********************/ -/* Bitstream control */ -/*********************/ -u16 hpi_bitstream_set_clock_edge(u32 h_control, u16 edge_type); - -u16 hpi_bitstream_set_data_polarity(u32 h_control, u16 polarity); - -u16 hpi_bitstream_get_activity(u32 h_control, u16 *pw_clk_activity, - u16 *pw_data_activity); - -/***********************/ -/* SampleClock control */ -/***********************/ - -u16 hpi_sample_clock_query_source(const u32 h_clock, const u32 index, - u16 *pw_source); - -u16 hpi_sample_clock_set_source(u32 h_control, u16 source); - -u16 hpi_sample_clock_get_source(u32 h_control, u16 *pw_source); - -u16 hpi_sample_clock_query_source_index(const u32 h_clock, const u32 index, - const u32 source, u16 *pw_source_index); - -u16 hpi_sample_clock_set_source_index(u32 h_control, u16 source_index); - -u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index); - -u16 hpi_sample_clock_get_sample_rate(u32 h_control, u32 *psample_rate); - -u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index, - u32 *psource); - -u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate); - -u16 hpi_sample_clock_get_local_rate(u32 h_control, u32 *psample_rate); - -u16 hpi_sample_clock_set_auto(u32 h_control, u32 enable); - -u16 hpi_sample_clock_get_auto(u32 h_control, u32 *penable); - -u16 hpi_sample_clock_set_local_rate_lock(u32 h_control, u32 lock); - -u16 hpi_sample_clock_get_local_rate_lock(u32 h_control, u32 *plock); - -/***********************/ -/* Microphone control */ -/***********************/ -u16 hpi_microphone_set_phantom_power(u32 h_control, u16 on_off); - -u16 hpi_microphone_get_phantom_power(u32 h_control, u16 *pw_on_off); - -/********************************/ -/* Parametric Equalizer control */ -/********************************/ -u16 hpi_parametric_eq_get_info(u32 h_control, u16 *pw_number_of_bands, - u16 *pw_enabled); - -u16 hpi_parametric_eq_set_state(u32 h_control, u16 on_off); - -u16 hpi_parametric_eq_set_band(u32 h_control, u16 index, u16 type, - u32 frequency_hz, short q100, short gain0_01dB); - -u16 hpi_parametric_eq_get_band(u32 h_control, u16 index, u16 *pn_type, - u32 *pfrequency_hz, short *pnQ100, short *pn_gain0_01dB); - -u16 hpi_parametric_eq_get_coeffs(u32 h_control, u16 index, short coeffs[5] - ); - -/*******************************/ -/* Compressor Expander control */ -/*******************************/ - -u16 hpi_compander_set_enable(u32 h_control, u32 on); - -u16 hpi_compander_get_enable(u32 h_control, u32 *pon); - -u16 hpi_compander_set_makeup_gain(u32 h_control, short makeup_gain0_01dB); - -u16 hpi_compander_get_makeup_gain(u32 h_control, short *pn_makeup_gain0_01dB); - -u16 hpi_compander_set_attack_time_constant(u32 h_control, u32 index, - u32 attack); - -u16 hpi_compander_get_attack_time_constant(u32 h_control, u32 index, - u32 *pw_attack); - -u16 hpi_compander_set_decay_time_constant(u32 h_control, u32 index, - u32 decay); - -u16 hpi_compander_get_decay_time_constant(u32 h_control, u32 index, - u32 *pw_decay); - -u16 hpi_compander_set_threshold(u32 h_control, u32 index, - short threshold0_01dB); - -u16 hpi_compander_get_threshold(u32 h_control, u32 index, - short *pn_threshold0_01dB); - -u16 hpi_compander_set_ratio(u32 h_control, u32 index, u32 ratio100); - -u16 hpi_compander_get_ratio(u32 h_control, u32 index, u32 *pw_ratio100); - -/********************/ -/* Cobranet control */ -/********************/ -u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count, - u8 *pb_data); - -u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count, - u32 *pbyte_count, u8 *pb_data); - -u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus, - u32 *preadable_size, u32 *pwriteable_size); - -u16 hpi_cobranet_get_ip_address(u32 h_control, u32 *pdw_ip_address); - -u16 hpi_cobranet_set_ip_address(u32 h_control, u32 dw_ip_address); - -u16 hpi_cobranet_get_static_ip_address(u32 h_control, u32 *pdw_ip_address); - -u16 hpi_cobranet_set_static_ip_address(u32 h_control, u32 dw_ip_address); - -u16 hpi_cobranet_get_macaddress(u32 h_control, u32 *p_mac_msbs, - u32 *p_mac_lsbs); - -/*************************/ -/* Tone Detector control */ -/*************************/ -u16 hpi_tone_detector_get_state(u32 hC, u32 *state); - -u16 hpi_tone_detector_set_enable(u32 hC, u32 enable); - -u16 hpi_tone_detector_get_enable(u32 hC, u32 *enable); - -u16 hpi_tone_detector_set_event_enable(u32 hC, u32 event_enable); - -u16 hpi_tone_detector_get_event_enable(u32 hC, u32 *event_enable); - -u16 hpi_tone_detector_set_threshold(u32 hC, int threshold); - -u16 hpi_tone_detector_get_threshold(u32 hC, int *threshold); - -u16 hpi_tone_detector_get_frequency(u32 hC, u32 index, u32 *frequency); - -/****************************/ -/* Silence Detector control */ -/****************************/ -u16 hpi_silence_detector_get_state(u32 hC, u32 *state); - -u16 hpi_silence_detector_set_enable(u32 hC, u32 enable); - -u16 hpi_silence_detector_get_enable(u32 hC, u32 *enable); - -u16 hpi_silence_detector_set_event_enable(u32 hC, u32 event_enable); - -u16 hpi_silence_detector_get_event_enable(u32 hC, u32 *event_enable); - -u16 hpi_silence_detector_set_delay(u32 hC, u32 delay); - -u16 hpi_silence_detector_get_delay(u32 hC, u32 *delay); - -u16 hpi_silence_detector_set_threshold(u32 hC, int threshold); - -u16 hpi_silence_detector_get_threshold(u32 hC, int *threshold); -/*********************/ -/* Utility functions */ -/*********************/ - -u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, - u32 sample_rate, u32 bit_rate, u32 attributes); - -#endif /*_HPI_H_ */ diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpi6000.c b/ANDROID_3.4.5/sound/pci/asihpi/hpi6000.c deleted file mode 100644 index 2414d7a2..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpi6000.c +++ /dev/null @@ -1,1809 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - - Hardware Programming Interface (HPI) for AudioScience ASI6200 series adapters. - These PCI bus adapters are based on the TI C6711 DSP. - - Exported functions: - void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) - - #defines - HIDE_PCI_ASSERTS to show the PCI asserts - PROFILE_DSP2 get profile data from DSP2 if present (instead of DSP 1) - -(C) Copyright AudioScience Inc. 1998-2003 -*******************************************************************************/ -#define SOURCEFILE_NAME "hpi6000.c" - -#include "hpi_internal.h" -#include "hpimsginit.h" -#include "hpidebug.h" -#include "hpi6000.h" -#include "hpidspcd.h" -#include "hpicmn.h" - -#define HPI_HIF_BASE (0x00000200) /* start of C67xx internal RAM */ -#define HPI_HIF_ADDR(member) \ - (HPI_HIF_BASE + offsetof(struct hpi_hif_6000, member)) -#define HPI_HIF_ERROR_MASK 0x4000 - -/* HPI6000 specific error codes */ -#define HPI6000_ERROR_BASE 900 /* not actually used anywhere */ - -/* operational/messaging errors */ -#define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901 - -#define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903 -#define HPI6000_ERROR_MSG_GET_ADR 904 -#define HPI6000_ERROR_RESP_GET_ADR 905 -#define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32 906 -#define HPI6000_ERROR_MSG_RESP_BLOCKREAD32 907 - -#define HPI6000_ERROR_CONTROL_CACHE_PARAMS 909 - -#define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT 911 -#define HPI6000_ERROR_SEND_DATA_ACK 912 -#define HPI6000_ERROR_SEND_DATA_ADR 913 -#define HPI6000_ERROR_SEND_DATA_TIMEOUT 914 -#define HPI6000_ERROR_SEND_DATA_CMD 915 -#define HPI6000_ERROR_SEND_DATA_WRITE 916 -#define HPI6000_ERROR_SEND_DATA_IDLECMD 917 - -#define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT 921 -#define HPI6000_ERROR_GET_DATA_ACK 922 -#define HPI6000_ERROR_GET_DATA_CMD 923 -#define HPI6000_ERROR_GET_DATA_READ 924 -#define HPI6000_ERROR_GET_DATA_IDLECMD 925 - -#define HPI6000_ERROR_CONTROL_CACHE_ADDRLEN 951 -#define HPI6000_ERROR_CONTROL_CACHE_READ 952 -#define HPI6000_ERROR_CONTROL_CACHE_FLUSH 953 - -#define HPI6000_ERROR_MSG_RESP_GETRESPCMD 961 -#define HPI6000_ERROR_MSG_RESP_IDLECMD 962 - -/* Initialisation/bootload errors */ -#define HPI6000_ERROR_UNHANDLED_SUBSYS_ID 930 - -/* can't access PCI2040 */ -#define HPI6000_ERROR_INIT_PCI2040 931 -/* can't access DSP HPI i/f */ -#define HPI6000_ERROR_INIT_DSPHPI 932 -/* can't access internal DSP memory */ -#define HPI6000_ERROR_INIT_DSPINTMEM 933 -/* can't access SDRAM - test#1 */ -#define HPI6000_ERROR_INIT_SDRAM1 934 -/* can't access SDRAM - test#2 */ -#define HPI6000_ERROR_INIT_SDRAM2 935 - -#define HPI6000_ERROR_INIT_VERIFY 938 - -#define HPI6000_ERROR_INIT_NOACK 939 - -#define HPI6000_ERROR_INIT_PLDTEST1 941 -#define HPI6000_ERROR_INIT_PLDTEST2 942 - -/* local defines */ - -#define HIDE_PCI_ASSERTS -#define PROFILE_DSP2 - -/* for PCI2040 i/f chip */ -/* HPI CSR registers */ -/* word offsets from CSR base */ -/* use when io addresses defined as u32 * */ - -#define INTERRUPT_EVENT_SET 0 -#define INTERRUPT_EVENT_CLEAR 1 -#define INTERRUPT_MASK_SET 2 -#define INTERRUPT_MASK_CLEAR 3 -#define HPI_ERROR_REPORT 4 -#define HPI_RESET 5 -#define HPI_DATA_WIDTH 6 - -#define MAX_DSPS 2 -/* HPI registers, spaced 8K bytes = 2K words apart */ -#define DSP_SPACING 0x800 - -#define CONTROL 0x0000 -#define ADDRESS 0x0200 -#define DATA_AUTOINC 0x0400 -#define DATA 0x0600 - -#define TIMEOUT 500000 - -struct dsp_obj { - __iomem u32 *prHPI_control; - __iomem u32 *prHPI_address; - __iomem u32 *prHPI_data; - __iomem u32 *prHPI_data_auto_inc; - char c_dsp_rev; /*A, B */ - u32 control_cache_address_on_dsp; - u32 control_cache_length_on_dsp; - struct hpi_adapter_obj *pa_parent_adapter; -}; - -struct hpi_hw_obj { - __iomem u32 *dw2040_HPICSR; - __iomem u32 *dw2040_HPIDSP; - - u16 num_dsp; - struct dsp_obj ado[MAX_DSPS]; - - u32 message_buffer_address_on_dsp; - u32 response_buffer_address_on_dsp; - u32 pCI2040HPI_error_count; - - struct hpi_control_cache_single control_cache[HPI_NMIXER_CONTROLS]; - struct hpi_control_cache *p_cache; -}; - -static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao, - u16 dsp_index, u32 hpi_address, u32 *source, u32 count); -static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao, - u16 dsp_index, u32 hpi_address, u32 *dest, u32 count); - -static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, - u32 *pos_error_code); -static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao, - u16 read_or_write); -#define H6READ 1 -#define H6WRITE 0 - -static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao, - struct hpi_message *phm); -static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, - u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr); - -static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, - struct hpi_response *phr); - -static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index, - u32 ack_value); - -static short hpi6000_send_host_command(struct hpi_adapter_obj *pao, - u16 dsp_index, u32 host_cmd); - -static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo); - -static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index, - struct hpi_message *phm, struct hpi_response *phr); - -static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index, - struct hpi_message *phm, struct hpi_response *phr); - -static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data); - -static u32 hpi_read_word(struct dsp_obj *pdo, u32 address); - -static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata, - u32 length); - -static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata, - u32 length); - -static void subsys_create_adapter(struct hpi_message *phm, - struct hpi_response *phr); - -static void adapter_delete(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void adapter_get_asserts(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static short create_adapter_obj(struct hpi_adapter_obj *pao, - u32 *pos_error_code); - -static void delete_adapter_obj(struct hpi_adapter_obj *pao); - -/* local globals */ - -static u16 gw_pci_read_asserts; /* used to count PCI2040 errors */ -static u16 gw_pci_write_asserts; /* used to count PCI2040 errors */ - -static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) -{ - switch (phm->function) { - case HPI_SUBSYS_CREATE_ADAPTER: - subsys_create_adapter(phm, phr); - break; - default: - phr->error = HPI_ERROR_INVALID_FUNC; - break; - } -} - -static void control_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - - switch (phm->function) { - case HPI_CONTROL_GET_STATE: - if (pao->has_control_cache) { - u16 err; - err = hpi6000_update_control_cache(pao, phm); - - if (err) { - if (err >= HPI_ERROR_BACKEND_BASE) { - phr->error = - HPI_ERROR_CONTROL_CACHING; - phr->specific_error = err; - } else { - phr->error = err; - } - break; - } - - if (hpi_check_control_cache(phw->p_cache, phm, phr)) - break; - } - hw_message(pao, phm, phr); - break; - case HPI_CONTROL_SET_STATE: - hw_message(pao, phm, phr); - hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm, phr); - break; - - case HPI_CONTROL_GET_INFO: - default: - hw_message(pao, phm, phr); - break; - } -} - -static void adapter_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - switch (phm->function) { - case HPI_ADAPTER_GET_ASSERT: - adapter_get_asserts(pao, phm, phr); - break; - - case HPI_ADAPTER_DELETE: - adapter_delete(pao, phm, phr); - break; - - default: - hw_message(pao, phm, phr); - break; - } -} - -static void outstream_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - switch (phm->function) { - case HPI_OSTREAM_HOSTBUFFER_ALLOC: - case HPI_OSTREAM_HOSTBUFFER_FREE: - /* Don't let these messages go to the HW function because - * they're called without locking the spinlock. - * For the HPI6000 adapters the HW would return - * HPI_ERROR_INVALID_FUNC anyway. - */ - phr->error = HPI_ERROR_INVALID_FUNC; - break; - default: - hw_message(pao, phm, phr); - return; - } -} - -static void instream_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - - switch (phm->function) { - case HPI_ISTREAM_HOSTBUFFER_ALLOC: - case HPI_ISTREAM_HOSTBUFFER_FREE: - /* Don't let these messages go to the HW function because - * they're called without locking the spinlock. - * For the HPI6000 adapters the HW would return - * HPI_ERROR_INVALID_FUNC anyway. - */ - phr->error = HPI_ERROR_INVALID_FUNC; - break; - default: - hw_message(pao, phm, phr); - return; - } -} - -/************************************************************************/ -/** HPI_6000() - * Entry point from HPIMAN - * All calls to the HPI start here - */ -void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_adapter_obj *pao = NULL; - - if (phm->object != HPI_OBJ_SUBSYSTEM) { - pao = hpi_find_adapter(phm->adapter_index); - if (!pao) { - hpi_init_response(phr, phm->object, phm->function, - HPI_ERROR_BAD_ADAPTER_NUMBER); - HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n", - phm->adapter_index); - return; - } - - /* Don't even try to communicate with crashed DSP */ - if (pao->dsp_crashed >= 10) { - hpi_init_response(phr, phm->object, phm->function, - HPI_ERROR_DSP_HARDWARE); - HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n", - phm->adapter_index); - return; - } - } - /* Init default response including the size field */ - if (phm->function != HPI_SUBSYS_CREATE_ADAPTER) - hpi_init_response(phr, phm->object, phm->function, - HPI_ERROR_PROCESSING_MESSAGE); - - switch (phm->type) { - case HPI_TYPE_REQUEST: - switch (phm->object) { - case HPI_OBJ_SUBSYSTEM: - subsys_message(phm, phr); - break; - - case HPI_OBJ_ADAPTER: - phr->size = - sizeof(struct hpi_response_header) + - sizeof(struct hpi_adapter_res); - adapter_message(pao, phm, phr); - break; - - case HPI_OBJ_CONTROL: - control_message(pao, phm, phr); - break; - - case HPI_OBJ_OSTREAM: - outstream_message(pao, phm, phr); - break; - - case HPI_OBJ_ISTREAM: - instream_message(pao, phm, phr); - break; - - default: - hw_message(pao, phm, phr); - break; - } - break; - - default: - phr->error = HPI_ERROR_INVALID_TYPE; - break; - } -} - -/************************************************************************/ -/* SUBSYSTEM */ - -/* create an adapter object and initialise it based on resource information - * passed in in the message - * NOTE - you cannot use this function AND the FindAdapters function at the - * same time, the application must use only one of them to get the adapters - */ -static void subsys_create_adapter(struct hpi_message *phm, - struct hpi_response *phr) -{ - /* create temp adapter obj, because we don't know what index yet */ - struct hpi_adapter_obj ao; - struct hpi_adapter_obj *pao; - u32 os_error_code; - u16 err = 0; - u32 dsp_index = 0; - - HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n"); - - memset(&ao, 0, sizeof(ao)); - - ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); - if (!ao.priv) { - HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n"); - phr->error = HPI_ERROR_MEMORY_ALLOC; - return; - } - - /* create the adapter object based on the resource information */ - ao.pci = *phm->u.s.resource.r.pci; - - err = create_adapter_obj(&ao, &os_error_code); - if (err) { - delete_adapter_obj(&ao); - if (err >= HPI_ERROR_BACKEND_BASE) { - phr->error = HPI_ERROR_DSP_BOOTLOAD; - phr->specific_error = err; - } else { - phr->error = err; - } - - phr->u.s.data = os_error_code; - return; - } - /* need to update paParentAdapter */ - pao = hpi_find_adapter(ao.index); - if (!pao) { - /* We just added this adapter, why can't we find it!? */ - HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n"); - phr->error = HPI_ERROR_BAD_ADAPTER; - return; - } - - for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) { - struct hpi_hw_obj *phw = pao->priv; - phw->ado[dsp_index].pa_parent_adapter = pao; - } - - phr->u.s.adapter_type = ao.type; - phr->u.s.adapter_index = ao.index; - phr->error = 0; -} - -static void adapter_delete(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - delete_adapter_obj(pao); - hpi_delete_adapter(pao); - phr->error = 0; -} - -/* this routine is called from SubSysFindAdapter and SubSysCreateAdapter */ -static short create_adapter_obj(struct hpi_adapter_obj *pao, - u32 *pos_error_code) -{ - short boot_error = 0; - u32 dsp_index = 0; - u32 control_cache_size = 0; - u32 control_cache_count = 0; - struct hpi_hw_obj *phw = pao->priv; - - /* The PCI2040 has the following address map */ - /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */ - /* BAR1 - 32K = HPI registers on DSP */ - phw->dw2040_HPICSR = pao->pci.ap_mem_base[0]; - phw->dw2040_HPIDSP = pao->pci.ap_mem_base[1]; - HPI_DEBUG_LOG(VERBOSE, "csr %p, dsp %p\n", phw->dw2040_HPICSR, - phw->dw2040_HPIDSP); - - /* set addresses for the possible DSP HPI interfaces */ - for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) { - phw->ado[dsp_index].prHPI_control = - phw->dw2040_HPIDSP + (CONTROL + - DSP_SPACING * dsp_index); - - phw->ado[dsp_index].prHPI_address = - phw->dw2040_HPIDSP + (ADDRESS + - DSP_SPACING * dsp_index); - phw->ado[dsp_index].prHPI_data = - phw->dw2040_HPIDSP + (DATA + DSP_SPACING * dsp_index); - - phw->ado[dsp_index].prHPI_data_auto_inc = - phw->dw2040_HPIDSP + (DATA_AUTOINC + - DSP_SPACING * dsp_index); - - HPI_DEBUG_LOG(VERBOSE, "ctl %p, adr %p, dat %p, dat++ %p\n", - phw->ado[dsp_index].prHPI_control, - phw->ado[dsp_index].prHPI_address, - phw->ado[dsp_index].prHPI_data, - phw->ado[dsp_index].prHPI_data_auto_inc); - - phw->ado[dsp_index].pa_parent_adapter = pao; - } - - phw->pCI2040HPI_error_count = 0; - pao->has_control_cache = 0; - - /* Set the default number of DSPs on this card */ - /* This is (conditionally) adjusted after bootloading */ - /* of the first DSP in the bootload section. */ - phw->num_dsp = 1; - - boot_error = hpi6000_adapter_boot_load_dsp(pao, pos_error_code); - if (boot_error) - return boot_error; - - HPI_DEBUG_LOG(INFO, "bootload DSP OK\n"); - - phw->message_buffer_address_on_dsp = 0L; - phw->response_buffer_address_on_dsp = 0L; - - /* get info about the adapter by asking the adapter */ - /* send a HPI_ADAPTER_GET_INFO message */ - { - struct hpi_message hm; - struct hpi_response hr0; /* response from DSP 0 */ - struct hpi_response hr1; /* response from DSP 1 */ - u16 error = 0; - - HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n"); - memset(&hm, 0, sizeof(hm)); - hm.type = HPI_TYPE_REQUEST; - hm.size = sizeof(struct hpi_message); - hm.object = HPI_OBJ_ADAPTER; - hm.function = HPI_ADAPTER_GET_INFO; - hm.adapter_index = 0; - memset(&hr0, 0, sizeof(hr0)); - memset(&hr1, 0, sizeof(hr1)); - hr0.size = sizeof(hr0); - hr1.size = sizeof(hr1); - - error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0); - if (hr0.error) { - HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error); - return hr0.error; - } - if (phw->num_dsp == 2) { - error = hpi6000_message_response_sequence(pao, 1, &hm, - &hr1); - if (error) - return error; - } - pao->type = hr0.u.ax.info.adapter_type; - pao->index = hr0.u.ax.info.adapter_index; - } - - memset(&phw->control_cache[0], 0, - sizeof(struct hpi_control_cache_single) * - HPI_NMIXER_CONTROLS); - /* Read the control cache length to figure out if it is turned on */ - control_cache_size = - hpi_read_word(&phw->ado[0], - HPI_HIF_ADDR(control_cache_size_in_bytes)); - if (control_cache_size) { - control_cache_count = - hpi_read_word(&phw->ado[0], - HPI_HIF_ADDR(control_cache_count)); - - phw->p_cache = - hpi_alloc_control_cache(control_cache_count, - control_cache_size, (unsigned char *) - &phw->control_cache[0] - ); - if (phw->p_cache) - pao->has_control_cache = 1; - } - - HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", pao->type, - pao->index); - - if (phw->p_cache) - phw->p_cache->adap_idx = pao->index; - - return hpi_add_adapter(pao); -} - -static void delete_adapter_obj(struct hpi_adapter_obj *pao) -{ - struct hpi_hw_obj *phw = pao->priv; - - if (pao->has_control_cache) - hpi_free_control_cache(phw->p_cache); - - /* reset DSPs on adapter */ - iowrite32(0x0003000F, phw->dw2040_HPICSR + HPI_RESET); - - kfree(phw); -} - -/************************************************************************/ -/* ADAPTER */ - -static void adapter_get_asserts(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ -#ifndef HIDE_PCI_ASSERTS - /* if we have PCI2040 asserts then collect them */ - if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) { - phr->u.ax.assert.p1 = - gw_pci_read_asserts * 100 + gw_pci_write_asserts; - phr->u.ax.assert.p2 = 0; - phr->u.ax.assert.count = 1; /* assert count */ - phr->u.ax.assert.dsp_index = -1; /* "dsp index" */ - strcpy(phr->u.ax.assert.sz_message, "PCI2040 error"); - phr->u.ax.assert.dsp_msg_addr = 0; - gw_pci_read_asserts = 0; - gw_pci_write_asserts = 0; - phr->error = 0; - } else -#endif - hw_message(pao, phm, phr); /*get DSP asserts */ - - return; -} - -/************************************************************************/ -/* LOW-LEVEL */ - -static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, - u32 *pos_error_code) -{ - struct hpi_hw_obj *phw = pao->priv; - short error; - u32 timeout; - u32 read = 0; - u32 i = 0; - u32 data = 0; - u32 j = 0; - u32 test_addr = 0x80000000; - u32 test_data = 0x00000001; - u32 dw2040_reset = 0; - u32 dsp_index = 0; - u32 endian = 0; - u32 adapter_info = 0; - u32 delay = 0; - - struct dsp_code dsp_code; - u16 boot_load_family = 0; - - /* NOTE don't use wAdapterType in this routine. It is not setup yet */ - - switch (pao->pci.pci_dev->subsystem_device) { - case 0x5100: - case 0x5110: /* ASI5100 revB or higher with C6711D */ - case 0x5200: /* ASI5200 PCIe version of ASI5100 */ - case 0x6100: - case 0x6200: - boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200); - break; - default: - return HPI6000_ERROR_UNHANDLED_SUBSYS_ID; - } - - /* reset all DSPs, indicate two DSPs are present - * set RST3-=1 to disconnect HAD8 to set DSP in little endian mode - */ - endian = 0; - dw2040_reset = 0x0003000F; - iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); - - /* read back register to make sure PCI2040 chip is functioning - * note that bits 4..15 are read-only and so should always return zero, - * even though we wrote 1 to them - */ - hpios_delay_micro_seconds(1000); - delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); - - if (delay != dw2040_reset) { - HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset, - delay); - return HPI6000_ERROR_INIT_PCI2040; - } - - /* Indicate that DSP#0,1 is a C6X */ - iowrite32(0x00000003, phw->dw2040_HPICSR + HPI_DATA_WIDTH); - /* set Bit30 and 29 - which will prevent Target aborts from being - * issued upon HPI or GP error - */ - iowrite32(0x60000000, phw->dw2040_HPICSR + INTERRUPT_MASK_SET); - - /* isolate DSP HAD8 line from PCI2040 so that - * Little endian can be set by pullup - */ - dw2040_reset = dw2040_reset & (~(endian << 3)); - iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); - - phw->ado[0].c_dsp_rev = 'B'; /* revB */ - phw->ado[1].c_dsp_rev = 'B'; /* revB */ - - /*Take both DSPs out of reset, setting HAD8 to the correct Endian */ - dw2040_reset = dw2040_reset & (~0x00000001); /* start DSP 0 */ - iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); - dw2040_reset = dw2040_reset & (~0x00000002); /* start DSP 1 */ - iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); - - /* set HAD8 back to PCI2040, now that DSP set to little endian mode */ - dw2040_reset = dw2040_reset & (~0x00000008); - iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); - /*delay to allow DSP to get going */ - hpios_delay_micro_seconds(100); - - /* loop through all DSPs, downloading DSP code */ - for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) { - struct dsp_obj *pdo = &phw->ado[dsp_index]; - - /* configure DSP so that we download code into the SRAM */ - /* set control reg for little endian, HWOB=1 */ - iowrite32(0x00010001, pdo->prHPI_control); - - /* test access to the HPI address register (HPIA) */ - test_data = 0x00000001; - for (j = 0; j < 32; j++) { - iowrite32(test_data, pdo->prHPI_address); - data = ioread32(pdo->prHPI_address); - if (data != test_data) { - HPI_DEBUG_LOG(ERROR, "INIT_DSPHPI %x %x %x\n", - test_data, data, dsp_index); - return HPI6000_ERROR_INIT_DSPHPI; - } - test_data = test_data << 1; - } - -/* if C6713 the setup PLL to generate 225MHz from 25MHz. -* Since the PLLDIV1 read is sometimes wrong, even on a C6713, -* we're going to do this unconditionally -*/ -/* PLLDIV1 should have a value of 8000 after reset */ -/* - if (HpiReadWord(pdo,0x01B7C118) == 0x8000) -*/ - { - /* C6713 datasheet says we cannot program PLL from HPI, - * and indeed if we try to set the PLL multiply from the - * HPI, the PLL does not seem to lock, - * so we enable the PLL and use the default of x 7 - */ - /* bypass PLL */ - hpi_write_word(pdo, 0x01B7C100, 0x0000); - hpios_delay_micro_seconds(100); - - /* ** use default of PLL x7 ** */ - /* EMIF = 225/3=75MHz */ - hpi_write_word(pdo, 0x01B7C120, 0x8002); - hpios_delay_micro_seconds(100); - - /* peri = 225/2 */ - hpi_write_word(pdo, 0x01B7C11C, 0x8001); - hpios_delay_micro_seconds(100); - - /* cpu = 225/1 */ - hpi_write_word(pdo, 0x01B7C118, 0x8000); - - /* ~2ms delay */ - hpios_delay_micro_seconds(2000); - - /* PLL not bypassed */ - hpi_write_word(pdo, 0x01B7C100, 0x0001); - /* ~2ms delay */ - hpios_delay_micro_seconds(2000); - } - - /* test r/w to internal DSP memory - * C6711 has L2 cache mapped to 0x0 when reset - * - * revB - because of bug 3.0.1 last HPI read - * (before HPI address issued) must be non-autoinc - */ - /* test each bit in the 32bit word */ - for (i = 0; i < 100; i++) { - test_addr = 0x00000000; - test_data = 0x00000001; - for (j = 0; j < 32; j++) { - hpi_write_word(pdo, test_addr + i, test_data); - data = hpi_read_word(pdo, test_addr + i); - if (data != test_data) { - HPI_DEBUG_LOG(ERROR, - "DSP mem %x %x %x %x\n", - test_addr + i, test_data, - data, dsp_index); - - return HPI6000_ERROR_INIT_DSPINTMEM; - } - test_data = test_data << 1; - } - } - - /* memory map of ASI6200 - 00000000-0000FFFF 16Kx32 internal program - 01800000-019FFFFF Internal peripheral - 80000000-807FFFFF CE0 2Mx32 SDRAM running @ 100MHz - 90000000-9000FFFF CE1 Async peripherals: - - EMIF config - ------------ - Global EMIF control - 0 - - 1 - - 2 - - 3 CLK2EN = 1 CLKOUT2 enabled - 4 CLK1EN = 0 CLKOUT1 disabled - 5 EKEN = 1 <--!! C6713 specific, enables ECLKOUT - 6 - - 7 NOHOLD = 1 external HOLD disabled - 8 HOLDA = 0 HOLDA output is low - 9 HOLD = 0 HOLD input is low - 10 ARDY = 1 ARDY input is high - 11 BUSREQ = 0 BUSREQ output is low - 12,13 Reserved = 1 - */ - hpi_write_word(pdo, 0x01800000, 0x34A8); - - /* EMIF CE0 setup - 2Mx32 Sync DRAM - 31..28 Wr setup - 27..22 Wr strobe - 21..20 Wr hold - 19..16 Rd setup - 15..14 - - 13..8 Rd strobe - 7..4 MTYPE 0011 Sync DRAM 32bits - 3 Wr hold MSB - 2..0 Rd hold - */ - hpi_write_word(pdo, 0x01800008, 0x00000030); - - /* EMIF SDRAM Extension - 31-21 0 - 20 WR2RD = 0 - 19-18 WR2DEAC = 1 - 17 WR2WR = 0 - 16-15 R2WDQM = 2 - 14-12 RD2WR = 4 - 11-10 RD2DEAC = 1 - 9 RD2RD = 1 - 8-7 THZP = 10b - 6-5 TWR = 2-1 = 01b (tWR = 10ns) - 4 TRRD = 0b = 2 ECLK (tRRD = 14ns) - 3-1 TRAS = 5-1 = 100b (Tras=42ns = 5 ECLK) - 1 CAS latency = 3 ECLK - (for Micron 2M32-7 operating at 100Mhz) - */ - - /* need to use this else DSP code crashes */ - hpi_write_word(pdo, 0x01800020, 0x001BDF29); - - /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank) - 31 - - - 30 SDBSZ 1 4 bank - 29..28 SDRSZ 00 11 row address pins - 27..26 SDCSZ 01 8 column address pins - 25 RFEN 1 refersh enabled - 24 INIT 1 init SDRAM - 23..20 TRCD 0001 - 19..16 TRP 0001 - 15..12 TRC 0110 - 11..0 - - - */ - /* need to use this else DSP code crashes */ - hpi_write_word(pdo, 0x01800018, 0x47117000); - - /* EMIF SDRAM Refresh Timing */ - hpi_write_word(pdo, 0x0180001C, 0x00000410); - - /*MIF CE1 setup - Async peripherals - @100MHz bus speed, each cycle is 10ns, - 31..28 Wr setup = 1 - 27..22 Wr strobe = 3 30ns - 21..20 Wr hold = 1 - 19..16 Rd setup =1 - 15..14 Ta = 2 - 13..8 Rd strobe = 3 30ns - 7..4 MTYPE 0010 Async 32bits - 3 Wr hold MSB =0 - 2..0 Rd hold = 1 - */ - { - u32 cE1 = - (1L << 28) | (3L << 22) | (1L << 20) | (1L << - 16) | (2L << 14) | (3L << 8) | (2L << 4) | 1L; - hpi_write_word(pdo, 0x01800004, cE1); - } - - /* delay a little to allow SDRAM and DSP to "get going" */ - hpios_delay_micro_seconds(1000); - - /* test access to SDRAM */ - { - test_addr = 0x80000000; - test_data = 0x00000001; - /* test each bit in the 32bit word */ - for (j = 0; j < 32; j++) { - hpi_write_word(pdo, test_addr, test_data); - data = hpi_read_word(pdo, test_addr); - if (data != test_data) { - HPI_DEBUG_LOG(ERROR, - "DSP dram %x %x %x %x\n", - test_addr, test_data, data, - dsp_index); - - return HPI6000_ERROR_INIT_SDRAM1; - } - test_data = test_data << 1; - } - /* test every Nth address in the DRAM */ -#define DRAM_SIZE_WORDS 0x200000 /*2_mx32 */ -#define DRAM_INC 1024 - test_addr = 0x80000000; - test_data = 0x0; - for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) { - hpi_write_word(pdo, test_addr + i, test_data); - test_data++; - } - test_addr = 0x80000000; - test_data = 0x0; - for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) { - data = hpi_read_word(pdo, test_addr + i); - if (data != test_data) { - HPI_DEBUG_LOG(ERROR, - "DSP dram %x %x %x %x\n", - test_addr + i, test_data, - data, dsp_index); - return HPI6000_ERROR_INIT_SDRAM2; - } - test_data++; - } - - } - - /* write the DSP code down into the DSPs memory */ - error = hpi_dsp_code_open(boot_load_family, pao->pci.pci_dev, - &dsp_code, pos_error_code); - - if (error) - return error; - - while (1) { - u32 length; - u32 address; - u32 type; - u32 *pcode; - - error = hpi_dsp_code_read_word(&dsp_code, &length); - if (error) - break; - if (length == 0xFFFFFFFF) - break; /* end of code */ - - error = hpi_dsp_code_read_word(&dsp_code, &address); - if (error) - break; - error = hpi_dsp_code_read_word(&dsp_code, &type); - if (error) - break; - error = hpi_dsp_code_read_block(length, &dsp_code, - &pcode); - if (error) - break; - error = hpi6000_dsp_block_write32(pao, (u16)dsp_index, - address, pcode, length); - if (error) - break; - } - - if (error) { - hpi_dsp_code_close(&dsp_code); - return error; - } - /* verify that code was written correctly */ - /* this time through, assume no errors in DSP code file/array */ - hpi_dsp_code_rewind(&dsp_code); - while (1) { - u32 length; - u32 address; - u32 type; - u32 *pcode; - - hpi_dsp_code_read_word(&dsp_code, &length); - if (length == 0xFFFFFFFF) - break; /* end of code */ - - hpi_dsp_code_read_word(&dsp_code, &address); - hpi_dsp_code_read_word(&dsp_code, &type); - hpi_dsp_code_read_block(length, &dsp_code, &pcode); - - for (i = 0; i < length; i++) { - data = hpi_read_word(pdo, address); - if (data != *pcode) { - error = HPI6000_ERROR_INIT_VERIFY; - HPI_DEBUG_LOG(ERROR, - "DSP verify %x %x %x %x\n", - address, *pcode, data, - dsp_index); - break; - } - pcode++; - address += 4; - } - if (error) - break; - } - hpi_dsp_code_close(&dsp_code); - if (error) - return error; - - /* zero out the hostmailbox */ - { - u32 address = HPI_HIF_ADDR(host_cmd); - for (i = 0; i < 4; i++) { - hpi_write_word(pdo, address, 0); - address += 4; - } - } - /* write the DSP number into the hostmailbox */ - /* structure before starting the DSP */ - hpi_write_word(pdo, HPI_HIF_ADDR(dsp_number), dsp_index); - - /* write the DSP adapter Info into the */ - /* hostmailbox before starting the DSP */ - if (dsp_index > 0) - hpi_write_word(pdo, HPI_HIF_ADDR(adapter_info), - adapter_info); - - /* step 3. Start code by sending interrupt */ - iowrite32(0x00030003, pdo->prHPI_control); - hpios_delay_micro_seconds(10000); - - /* wait for a non-zero value in hostcmd - - * indicating initialization is complete - * - * Init could take a while if DSP checks SDRAM memory - * Was 200000. Increased to 2000000 for ASI8801 so we - * don't get 938 errors. - */ - timeout = 2000000; - while (timeout) { - do { - read = hpi_read_word(pdo, - HPI_HIF_ADDR(host_cmd)); - } while (--timeout - && hpi6000_check_PCI2040_error_flag(pao, - H6READ)); - - if (read) - break; - /* The following is a workaround for bug #94: - * Bluescreen on install and subsequent boots on a - * DELL PowerEdge 600SC PC with 1.8GHz P4 and - * ServerWorks chipset. Without this delay the system - * locks up with a bluescreen (NOT GPF or pagefault). - */ - else - hpios_delay_micro_seconds(10000); - } - if (timeout == 0) - return HPI6000_ERROR_INIT_NOACK; - - /* read the DSP adapter Info from the */ - /* hostmailbox structure after starting the DSP */ - if (dsp_index == 0) { - /*u32 dwTestData=0; */ - u32 mask = 0; - - adapter_info = - hpi_read_word(pdo, - HPI_HIF_ADDR(adapter_info)); - if (HPI_ADAPTER_FAMILY_ASI - (HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER - (adapter_info)) == - HPI_ADAPTER_FAMILY_ASI(0x6200)) - /* all 6200 cards have this many DSPs */ - phw->num_dsp = 2; - - /* test that the PLD is programmed */ - /* and we can read/write 24bits */ -#define PLD_BASE_ADDRESS 0x90000000L /*for ASI6100/6200/8800 */ - - switch (boot_load_family) { - case HPI_ADAPTER_FAMILY_ASI(0x6200): - /* ASI6100/6200 has 24bit path to FPGA */ - mask = 0xFFFFFF00L; - /* ASI5100 uses AX6 code, */ - /* but has no PLD r/w register to test */ - if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev-> - subsystem_device) == - HPI_ADAPTER_FAMILY_ASI(0x5100)) - mask = 0x00000000L; - /* ASI5200 uses AX6 code, */ - /* but has no PLD r/w register to test */ - if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev-> - subsystem_device) == - HPI_ADAPTER_FAMILY_ASI(0x5200)) - mask = 0x00000000L; - break; - case HPI_ADAPTER_FAMILY_ASI(0x8800): - /* ASI8800 has 16bit path to FPGA */ - mask = 0xFFFF0000L; - break; - } - test_data = 0xAAAAAA00L & mask; - /* write to 24 bit Debug register (D31-D8) */ - hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data); - read = hpi_read_word(pdo, - PLD_BASE_ADDRESS + 4L) & mask; - if (read != test_data) { - HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data, - read); - return HPI6000_ERROR_INIT_PLDTEST1; - } - test_data = 0x55555500L & mask; - hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data); - read = hpi_read_word(pdo, - PLD_BASE_ADDRESS + 4L) & mask; - if (read != test_data) { - HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data, - read); - return HPI6000_ERROR_INIT_PLDTEST2; - } - } - } /* for numDSP */ - return 0; -} - -#define PCI_TIMEOUT 100 - -static int hpi_set_address(struct dsp_obj *pdo, u32 address) -{ - u32 timeout = PCI_TIMEOUT; - - do { - iowrite32(address, pdo->prHPI_address); - } while (hpi6000_check_PCI2040_error_flag(pdo->pa_parent_adapter, - H6WRITE) - && --timeout); - - if (timeout) - return 0; - - return 1; -} - -/* write one word to the HPI port */ -static void hpi_write_word(struct dsp_obj *pdo, u32 address, u32 data) -{ - if (hpi_set_address(pdo, address)) - return; - iowrite32(data, pdo->prHPI_data); -} - -/* read one word from the HPI port */ -static u32 hpi_read_word(struct dsp_obj *pdo, u32 address) -{ - u32 data = 0; - - if (hpi_set_address(pdo, address)) - return 0; /*? No way to return error */ - - /* take care of errata in revB DSP (2.0.1) */ - data = ioread32(pdo->prHPI_data); - return data; -} - -/* write a block of 32bit words to the DSP HPI port using auto-inc mode */ -static void hpi_write_block(struct dsp_obj *pdo, u32 address, u32 *pdata, - u32 length) -{ - u16 length16 = length - 1; - - if (length == 0) - return; - - if (hpi_set_address(pdo, address)) - return; - - iowrite32_rep(pdo->prHPI_data_auto_inc, pdata, length16); - - /* take care of errata in revB DSP (2.0.1) */ - /* must end with non auto-inc */ - iowrite32(*(pdata + length - 1), pdo->prHPI_data); -} - -/** read a block of 32bit words from the DSP HPI port using auto-inc mode - */ -static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata, - u32 length) -{ - u16 length16 = length - 1; - - if (length == 0) - return; - - if (hpi_set_address(pdo, address)) - return; - - ioread32_rep(pdo->prHPI_data_auto_inc, pdata, length16); - - /* take care of errata in revB DSP (2.0.1) */ - /* must end with non auto-inc */ - *(pdata + length - 1) = ioread32(pdo->prHPI_data); -} - -static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao, - u16 dsp_index, u32 hpi_address, u32 *source, u32 count) -{ - struct hpi_hw_obj *phw = pao->priv; - struct dsp_obj *pdo = &phw->ado[dsp_index]; - u32 time_out = PCI_TIMEOUT; - int c6711_burst_size = 128; - u32 local_hpi_address = hpi_address; - int local_count = count; - int xfer_size; - u32 *pdata = source; - - while (local_count) { - if (local_count > c6711_burst_size) - xfer_size = c6711_burst_size; - else - xfer_size = local_count; - - time_out = PCI_TIMEOUT; - do { - hpi_write_block(pdo, local_hpi_address, pdata, - xfer_size); - } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) - && --time_out); - - if (!time_out) - break; - pdata += xfer_size; - local_hpi_address += sizeof(u32) * xfer_size; - local_count -= xfer_size; - } - - if (time_out) - return 0; - else - return 1; -} - -static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao, - u16 dsp_index, u32 hpi_address, u32 *dest, u32 count) -{ - struct hpi_hw_obj *phw = pao->priv; - struct dsp_obj *pdo = &phw->ado[dsp_index]; - u32 time_out = PCI_TIMEOUT; - int c6711_burst_size = 16; - u32 local_hpi_address = hpi_address; - int local_count = count; - int xfer_size; - u32 *pdata = dest; - u32 loop_count = 0; - - while (local_count) { - if (local_count > c6711_burst_size) - xfer_size = c6711_burst_size; - else - xfer_size = local_count; - - time_out = PCI_TIMEOUT; - do { - hpi_read_block(pdo, local_hpi_address, pdata, - xfer_size); - } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) - && --time_out); - if (!time_out) - break; - - pdata += xfer_size; - local_hpi_address += sizeof(u32) * xfer_size; - local_count -= xfer_size; - loop_count++; - } - - if (time_out) - return 0; - else - return 1; -} - -static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, - u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct dsp_obj *pdo = &phw->ado[dsp_index]; - u32 timeout; - u16 ack; - u32 address; - u32 length; - u32 *p_data; - u16 error = 0; - - ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); - if (ack & HPI_HIF_ERROR_MASK) { - pao->dsp_crashed++; - return HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT; - } - pao->dsp_crashed = 0; - - /* get the message address and size */ - if (phw->message_buffer_address_on_dsp == 0) { - timeout = TIMEOUT; - do { - address = - hpi_read_word(pdo, - HPI_HIF_ADDR(message_buffer_address)); - phw->message_buffer_address_on_dsp = address; - } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) - && --timeout); - if (!timeout) - return HPI6000_ERROR_MSG_GET_ADR; - } else - address = phw->message_buffer_address_on_dsp; - - length = phm->size; - - /* send the message */ - p_data = (u32 *)phm; - if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data, - (u16)length / 4)) - return HPI6000_ERROR_MSG_RESP_BLOCKWRITE32; - - if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_GET_RESP)) - return HPI6000_ERROR_MSG_RESP_GETRESPCMD; - hpi6000_send_dsp_interrupt(pdo); - - ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_RESP); - if (ack & HPI_HIF_ERROR_MASK) - return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK; - - /* get the response address */ - if (phw->response_buffer_address_on_dsp == 0) { - timeout = TIMEOUT; - do { - address = - hpi_read_word(pdo, - HPI_HIF_ADDR(response_buffer_address)); - } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) - && --timeout); - phw->response_buffer_address_on_dsp = address; - - if (!timeout) - return HPI6000_ERROR_RESP_GET_ADR; - } else - address = phw->response_buffer_address_on_dsp; - - /* read the length of the response back from the DSP */ - timeout = TIMEOUT; - do { - length = hpi_read_word(pdo, HPI_HIF_ADDR(length)); - } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout); - if (!timeout) - length = sizeof(struct hpi_response); - - /* get the response */ - p_data = (u32 *)phr; - if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data, - (u16)length / 4)) - return HPI6000_ERROR_MSG_RESP_BLOCKREAD32; - - /* set i/f back to idle */ - if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE)) - return HPI6000_ERROR_MSG_RESP_IDLECMD; - hpi6000_send_dsp_interrupt(pdo); - - error = hpi_validate_response(phm, phr); - return error; -} - -/* have to set up the below defines to match stuff in the MAP file */ - -#define MSG_ADDRESS (HPI_HIF_BASE+0x18) -#define MSG_LENGTH 11 -#define RESP_ADDRESS (HPI_HIF_BASE+0x44) -#define RESP_LENGTH 16 -#define QUEUE_START (HPI_HIF_BASE+0x88) -#define QUEUE_SIZE 0x8000 - -static short hpi6000_send_data_check_adr(u32 address, u32 length_in_dwords) -{ -/*#define CHECKING // comment this line in to enable checking */ -#ifdef CHECKING - if (address < (u32)MSG_ADDRESS) - return 0; - if (address > (u32)(QUEUE_START + QUEUE_SIZE)) - return 0; - if ((address + (length_in_dwords << 2)) > - (u32)(QUEUE_START + QUEUE_SIZE)) - return 0; -#else - (void)address; - (void)length_in_dwords; - return 1; -#endif -} - -static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct dsp_obj *pdo = &phw->ado[dsp_index]; - u32 data_sent = 0; - u16 ack; - u32 length, address; - u32 *p_data = (u32 *)phm->u.d.u.data.pb_data; - u16 time_out = 8; - - (void)phr; - - /* round dwDataSize down to nearest 4 bytes */ - while ((data_sent < (phm->u.d.u.data.data_size & ~3L)) - && --time_out) { - ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); - if (ack & HPI_HIF_ERROR_MASK) - return HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT; - - if (hpi6000_send_host_command(pao, dsp_index, - HPI_HIF_SEND_DATA)) - return HPI6000_ERROR_SEND_DATA_CMD; - - hpi6000_send_dsp_interrupt(pdo); - - ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_SEND_DATA); - - if (ack & HPI_HIF_ERROR_MASK) - return HPI6000_ERROR_SEND_DATA_ACK; - - do { - /* get the address and size */ - address = hpi_read_word(pdo, HPI_HIF_ADDR(address)); - /* DSP returns number of DWORDS */ - length = hpi_read_word(pdo, HPI_HIF_ADDR(length)); - } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)); - - if (!hpi6000_send_data_check_adr(address, length)) - return HPI6000_ERROR_SEND_DATA_ADR; - - /* send the data. break data into 512 DWORD blocks (2K bytes) - * and send using block write. 2Kbytes is the max as this is the - * memory window given to the HPI data register by the PCI2040 - */ - - { - u32 len = length; - u32 blk_len = 512; - while (len) { - if (len < blk_len) - blk_len = len; - if (hpi6000_dsp_block_write32(pao, dsp_index, - address, p_data, blk_len)) - return HPI6000_ERROR_SEND_DATA_WRITE; - address += blk_len * 4; - p_data += blk_len; - len -= blk_len; - } - } - - if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE)) - return HPI6000_ERROR_SEND_DATA_IDLECMD; - - hpi6000_send_dsp_interrupt(pdo); - - data_sent += length * 4; - } - if (!time_out) - return HPI6000_ERROR_SEND_DATA_TIMEOUT; - return 0; -} - -static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct dsp_obj *pdo = &phw->ado[dsp_index]; - u32 data_got = 0; - u16 ack; - u32 length, address; - u32 *p_data = (u32 *)phm->u.d.u.data.pb_data; - - (void)phr; /* this parameter not used! */ - - /* round dwDataSize down to nearest 4 bytes */ - while (data_got < (phm->u.d.u.data.data_size & ~3L)) { - ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); - if (ack & HPI_HIF_ERROR_MASK) - return HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT; - - if (hpi6000_send_host_command(pao, dsp_index, - HPI_HIF_GET_DATA)) - return HPI6000_ERROR_GET_DATA_CMD; - hpi6000_send_dsp_interrupt(pdo); - - ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_GET_DATA); - - if (ack & HPI_HIF_ERROR_MASK) - return HPI6000_ERROR_GET_DATA_ACK; - - /* get the address and size */ - do { - address = hpi_read_word(pdo, HPI_HIF_ADDR(address)); - length = hpi_read_word(pdo, HPI_HIF_ADDR(length)); - } while (hpi6000_check_PCI2040_error_flag(pao, H6READ)); - - /* read the data */ - { - u32 len = length; - u32 blk_len = 512; - while (len) { - if (len < blk_len) - blk_len = len; - if (hpi6000_dsp_block_read32(pao, dsp_index, - address, p_data, blk_len)) - return HPI6000_ERROR_GET_DATA_READ; - address += blk_len * 4; - p_data += blk_len; - len -= blk_len; - } - } - - if (hpi6000_send_host_command(pao, dsp_index, HPI_HIF_IDLE)) - return HPI6000_ERROR_GET_DATA_IDLECMD; - hpi6000_send_dsp_interrupt(pdo); - - data_got += length * 4; - } - return 0; -} - -static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo) -{ - iowrite32(0x00030003, pdo->prHPI_control); /* DSPINT */ -} - -static short hpi6000_send_host_command(struct hpi_adapter_obj *pao, - u16 dsp_index, u32 host_cmd) -{ - struct hpi_hw_obj *phw = pao->priv; - struct dsp_obj *pdo = &phw->ado[dsp_index]; - u32 timeout = TIMEOUT; - - /* set command */ - do { - hpi_write_word(pdo, HPI_HIF_ADDR(host_cmd), host_cmd); - /* flush the FIFO */ - hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd)); - } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) && --timeout); - - /* reset the interrupt bit */ - iowrite32(0x00040004, pdo->prHPI_control); - - if (timeout) - return 0; - else - return 1; -} - -/* if the PCI2040 has recorded an HPI timeout, reset the error and return 1 */ -static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao, - u16 read_or_write) -{ - u32 hPI_error; - - struct hpi_hw_obj *phw = pao->priv; - - /* read the error bits from the PCI2040 */ - hPI_error = ioread32(phw->dw2040_HPICSR + HPI_ERROR_REPORT); - if (hPI_error) { - /* reset the error flag */ - iowrite32(0L, phw->dw2040_HPICSR + HPI_ERROR_REPORT); - phw->pCI2040HPI_error_count++; - if (read_or_write == 1) - gw_pci_read_asserts++; /************* inc global */ - else - gw_pci_write_asserts++; - return 1; - } else - return 0; -} - -static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index, - u32 ack_value) -{ - struct hpi_hw_obj *phw = pao->priv; - struct dsp_obj *pdo = &phw->ado[dsp_index]; - u32 ack = 0L; - u32 timeout; - u32 hPIC = 0L; - - /* wait for host interrupt to signal ack is ready */ - timeout = TIMEOUT; - while (--timeout) { - hPIC = ioread32(pdo->prHPI_control); - if (hPIC & 0x04) /* 0x04 = HINT from DSP */ - break; - } - if (timeout == 0) - return HPI_HIF_ERROR_MASK; - - /* wait for dwAckValue */ - timeout = TIMEOUT; - while (--timeout) { - /* read the ack mailbox */ - ack = hpi_read_word(pdo, HPI_HIF_ADDR(dsp_ack)); - if (ack == ack_value) - break; - if ((ack & HPI_HIF_ERROR_MASK) - && !hpi6000_check_PCI2040_error_flag(pao, H6READ)) - break; - /*for (i=0;i<1000;i++) */ - /* dwPause=i+1; */ - } - if (ack & HPI_HIF_ERROR_MASK) - /* indicates bad read from DSP - - typically 0xffffff is read for some reason */ - ack = HPI_HIF_ERROR_MASK; - - if (timeout == 0) - ack = HPI_HIF_ERROR_MASK; - return (short)ack; -} - -static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao, - struct hpi_message *phm) -{ - const u16 dsp_index = 0; - struct hpi_hw_obj *phw = pao->priv; - struct dsp_obj *pdo = &phw->ado[dsp_index]; - u32 timeout; - u32 cache_dirty_flag; - u16 err; - - hpios_dsplock_lock(pao); - - timeout = TIMEOUT; - do { - cache_dirty_flag = - hpi_read_word((struct dsp_obj *)pdo, - HPI_HIF_ADDR(control_cache_is_dirty)); - } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout); - if (!timeout) { - err = HPI6000_ERROR_CONTROL_CACHE_PARAMS; - goto unlock; - } - - if (cache_dirty_flag) { - /* read the cached controls */ - u32 address; - u32 length; - - timeout = TIMEOUT; - if (pdo->control_cache_address_on_dsp == 0) { - do { - address = - hpi_read_word((struct dsp_obj *)pdo, - HPI_HIF_ADDR(control_cache_address)); - - length = hpi_read_word((struct dsp_obj *)pdo, - HPI_HIF_ADDR - (control_cache_size_in_bytes)); - } while (hpi6000_check_PCI2040_error_flag(pao, H6READ) - && --timeout); - if (!timeout) { - err = HPI6000_ERROR_CONTROL_CACHE_ADDRLEN; - goto unlock; - } - pdo->control_cache_address_on_dsp = address; - pdo->control_cache_length_on_dsp = length; - } else { - address = pdo->control_cache_address_on_dsp; - length = pdo->control_cache_length_on_dsp; - } - - if (hpi6000_dsp_block_read32(pao, dsp_index, address, - (u32 *)&phw->control_cache[0], - length / sizeof(u32))) { - err = HPI6000_ERROR_CONTROL_CACHE_READ; - goto unlock; - } - do { - hpi_write_word((struct dsp_obj *)pdo, - HPI_HIF_ADDR(control_cache_is_dirty), 0); - /* flush the FIFO */ - hpi_set_address(pdo, HPI_HIF_ADDR(host_cmd)); - } while (hpi6000_check_PCI2040_error_flag(pao, H6WRITE) - && --timeout); - if (!timeout) { - err = HPI6000_ERROR_CONTROL_CACHE_FLUSH; - goto unlock; - } - - } - err = 0; - -unlock: - hpios_dsplock_unlock(pao); - return err; -} - -/** Get dsp index for multi DSP adapters only */ -static u16 get_dsp_index(struct hpi_adapter_obj *pao, struct hpi_message *phm) -{ - u16 ret = 0; - switch (phm->object) { - case HPI_OBJ_ISTREAM: - if (phm->obj_index < 2) - ret = 1; - break; - case HPI_OBJ_PROFILE: - ret = phm->obj_index; - break; - default: - break; - } - return ret; -} - -/** Complete transaction with DSP - -Send message, get response, send or get stream data if any. -*/ -static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, - struct hpi_response *phr) -{ - u16 error = 0; - u16 dsp_index = 0; - struct hpi_hw_obj *phw = pao->priv; - u16 num_dsp = phw->num_dsp; - - if (num_dsp < 2) - dsp_index = 0; - else { - dsp_index = get_dsp_index(pao, phm); - - /* is this checked on the DSP anyway? */ - if ((phm->function == HPI_ISTREAM_GROUP_ADD) - || (phm->function == HPI_OSTREAM_GROUP_ADD)) { - struct hpi_message hm; - u16 add_index; - hm.obj_index = phm->u.d.u.stream.stream_index; - hm.object = phm->u.d.u.stream.object_type; - add_index = get_dsp_index(pao, &hm); - if (add_index != dsp_index) { - phr->error = HPI_ERROR_NO_INTERDSP_GROUPS; - return; - } - } - } - - hpios_dsplock_lock(pao); - error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr); - - if (error) /* something failed in the HPI/DSP interface */ - goto err; - - if (phr->error) /* something failed in the DSP */ - goto out; - - switch (phm->function) { - case HPI_OSTREAM_WRITE: - case HPI_ISTREAM_ANC_WRITE: - error = hpi6000_send_data(pao, dsp_index, phm, phr); - break; - case HPI_ISTREAM_READ: - case HPI_OSTREAM_ANC_READ: - error = hpi6000_get_data(pao, dsp_index, phm, phr); - break; - case HPI_ADAPTER_GET_ASSERT: - phr->u.ax.assert.dsp_index = 0; /* dsp 0 default */ - if (num_dsp == 2) { - if (!phr->u.ax.assert.count) { - /* no assert from dsp 0, check dsp 1 */ - error = hpi6000_message_response_sequence(pao, - 1, phm, phr); - phr->u.ax.assert.dsp_index = 1; - } - } - } - -err: - if (error) { - if (error >= HPI_ERROR_BACKEND_BASE) { - phr->error = HPI_ERROR_DSP_COMMUNICATION; - phr->specific_error = error; - } else { - phr->error = error; - } - - /* just the header of the response is valid */ - phr->size = sizeof(struct hpi_response_header); - } -out: - hpios_dsplock_unlock(pao); - return; -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpi6000.h b/ANDROID_3.4.5/sound/pci/asihpi/hpi6000.h deleted file mode 100644 index 7e0deeff..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpi6000.h +++ /dev/null @@ -1,70 +0,0 @@ -/***************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -Public declarations for DSP Proramming Interface to TI C6701 - -Shared between hpi6000.c and DSP code - -(C) Copyright AudioScience Inc. 1998-2003 -******************************************************************************/ - -#ifndef _HPI6000_H_ -#define _HPI6000_H_ - -#define HPI_NMIXER_CONTROLS 200 - -/* - * Control caching is always supported in the HPI code. - * The DSP should make sure that dwControlCacheSizeInBytes is initialized to 0 - * during boot to make it in-active. - */ -struct hpi_hif_6000 { - u32 host_cmd; - u32 dsp_ack; - u32 address; - u32 length; - u32 message_buffer_address; - u32 response_buffer_address; - u32 dsp_number; - u32 adapter_info; - u32 control_cache_is_dirty; - u32 control_cache_address; - u32 control_cache_size_in_bytes; - u32 control_cache_count; -}; - -#define HPI_HIF_PACK_ADAPTER_INFO(adapter, version_major, version_minor) \ - ((adapter << 16) | (version_major << 8) | version_minor) -#define HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER(adapterinfo) \ - ((adapterinfo >> 16) & 0xffff) -#define HPI_HIF_ADAPTER_INFO_EXTRACT_HWVERSION_MAJOR(adapterinfo) \ - ((adapterinfo >> 8) & 0xff) -#define HPI_HIF_ADAPTER_INFO_EXTRACT_HWVERSION_MINOR(adapterinfo) \ - (adapterinfo & 0xff) - -/* Command/status exchanged between host and DSP */ -#define HPI_HIF_IDLE 0 -#define HPI_HIF_SEND_MSG 1 -#define HPI_HIF_GET_RESP 2 -#define HPI_HIF_DATA_MASK 0x10 -#define HPI_HIF_SEND_DATA 0x13 -#define HPI_HIF_GET_DATA 0x14 -#define HPI_HIF_SEND_DONE 5 -#define HPI_HIF_RESET 9 - -#endif /* _HPI6000_H_ */ diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpi6205.c b/ANDROID_3.4.5/sound/pci/asihpi/hpi6205.c deleted file mode 100644 index 4f287388..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpi6205.c +++ /dev/null @@ -1,2208 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - - Hardware Programming Interface (HPI) for AudioScience - ASI50xx, AS51xx, ASI6xxx, ASI87xx ASI89xx series adapters. - These PCI and PCIe bus adapters are based on a - TMS320C6205 PCI bus mastering DSP, - and (except ASI50xx) TI TMS320C6xxx floating point DSP - - Exported function: - void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) - -(C) Copyright AudioScience Inc. 1998-2010 -*******************************************************************************/ -#define SOURCEFILE_NAME "hpi6205.c" - -#include "hpi_internal.h" -#include "hpimsginit.h" -#include "hpidebug.h" -#include "hpi6205.h" -#include "hpidspcd.h" -#include "hpicmn.h" - -/*****************************************************************************/ -/* HPI6205 specific error codes */ -#define HPI6205_ERROR_BASE 1000 /* not actually used anywhere */ - -/* operational/messaging errors */ -#define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT 1015 -#define HPI6205_ERROR_MSG_RESP_TIMEOUT 1016 - -/* initialization/bootload errors */ -#define HPI6205_ERROR_6205_NO_IRQ 1002 -#define HPI6205_ERROR_6205_INIT_FAILED 1003 -#define HPI6205_ERROR_6205_REG 1006 -#define HPI6205_ERROR_6205_DSPPAGE 1007 -#define HPI6205_ERROR_C6713_HPIC 1009 -#define HPI6205_ERROR_C6713_HPIA 1010 -#define HPI6205_ERROR_C6713_PLL 1011 -#define HPI6205_ERROR_DSP_INTMEM 1012 -#define HPI6205_ERROR_DSP_EXTMEM 1013 -#define HPI6205_ERROR_DSP_PLD 1014 -#define HPI6205_ERROR_6205_EEPROM 1017 -#define HPI6205_ERROR_DSP_EMIF1 1018 -#define HPI6205_ERROR_DSP_EMIF2 1019 -#define HPI6205_ERROR_DSP_EMIF3 1020 -#define HPI6205_ERROR_DSP_EMIF4 1021 - -/*****************************************************************************/ -/* for C6205 PCI i/f */ -/* Host Status Register (HSR) bitfields */ -#define C6205_HSR_INTSRC 0x01 -#define C6205_HSR_INTAVAL 0x02 -#define C6205_HSR_INTAM 0x04 -#define C6205_HSR_CFGERR 0x08 -#define C6205_HSR_EEREAD 0x10 -/* Host-to-DSP Control Register (HDCR) bitfields */ -#define C6205_HDCR_WARMRESET 0x01 -#define C6205_HDCR_DSPINT 0x02 -#define C6205_HDCR_PCIBOOT 0x04 -/* DSP Page Register (DSPP) bitfields, */ -/* defines 4 Mbyte page that BAR0 points to */ -#define C6205_DSPP_MAP1 0x400 - -/* BAR0 maps to prefetchable 4 Mbyte memory block set by DSPP. - * BAR1 maps to non-prefetchable 8 Mbyte memory block - * of DSP memory mapped registers (starting at 0x01800000). - * 0x01800000 is hardcoded in the PCI i/f, so that only the offset from this - * needs to be added to the BAR1 base address set in the PCI config reg - */ -#define C6205_BAR1_PCI_IO_OFFSET (0x027FFF0L) -#define C6205_BAR1_HSR (C6205_BAR1_PCI_IO_OFFSET) -#define C6205_BAR1_HDCR (C6205_BAR1_PCI_IO_OFFSET+4) -#define C6205_BAR1_DSPP (C6205_BAR1_PCI_IO_OFFSET+8) - -/* used to control LED (revA) and reset C6713 (revB) */ -#define C6205_BAR0_TIMER1_CTL (0x01980000L) - -/* For first 6713 in CE1 space, using DA17,16,2 */ -#define HPICL_ADDR 0x01400000L -#define HPICH_ADDR 0x01400004L -#define HPIAL_ADDR 0x01410000L -#define HPIAH_ADDR 0x01410004L -#define HPIDIL_ADDR 0x01420000L -#define HPIDIH_ADDR 0x01420004L -#define HPIDL_ADDR 0x01430000L -#define HPIDH_ADDR 0x01430004L - -#define C6713_EMIF_GCTL 0x01800000 -#define C6713_EMIF_CE1 0x01800004 -#define C6713_EMIF_CE0 0x01800008 -#define C6713_EMIF_CE2 0x01800010 -#define C6713_EMIF_CE3 0x01800014 -#define C6713_EMIF_SDRAMCTL 0x01800018 -#define C6713_EMIF_SDRAMTIMING 0x0180001C -#define C6713_EMIF_SDRAMEXT 0x01800020 - -struct hpi_hw_obj { - /* PCI registers */ - __iomem u32 *prHSR; - __iomem u32 *prHDCR; - __iomem u32 *prDSPP; - - u32 dsp_page; - - struct consistent_dma_area h_locked_mem; - struct bus_master_interface *p_interface_buffer; - - u16 flag_outstream_just_reset[HPI_MAX_STREAMS]; - /* a non-NULL handle means there is an HPI allocated buffer */ - struct consistent_dma_area instream_host_buffers[HPI_MAX_STREAMS]; - struct consistent_dma_area outstream_host_buffers[HPI_MAX_STREAMS]; - /* non-zero size means a buffer exists, may be external */ - u32 instream_host_buffer_size[HPI_MAX_STREAMS]; - u32 outstream_host_buffer_size[HPI_MAX_STREAMS]; - - struct consistent_dma_area h_control_cache; - struct hpi_control_cache *p_cache; -}; - -/*****************************************************************************/ -/* local prototypes */ - -#define check_before_bbm_copy(status, p_bbm_data, l_first_write, l_second_write) - -static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us); - -static void send_dsp_command(struct hpi_hw_obj *phw, int cmd); - -static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, - u32 *pos_error_code); - -static u16 message_response_sequence(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, - struct hpi_response *phr); - -#define HPI6205_TIMEOUT 1000000 - -static void subsys_create_adapter(struct hpi_message *phm, - struct hpi_response *phr); -static void adapter_delete(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static u16 create_adapter_obj(struct hpi_adapter_obj *pao, - u32 *pos_error_code); - -static void delete_adapter_obj(struct hpi_adapter_obj *pao); - -static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void outstream_host_buffer_free(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); -static void outstream_write(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void outstream_get_info(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void outstream_start(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void outstream_open(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void outstream_reset(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void instream_host_buffer_free(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void instream_read(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void instream_get_info(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static void instream_start(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr); - -static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index, - u32 address); - -static void boot_loader_write_mem32(struct hpi_adapter_obj *pao, - int dsp_index, u32 address, u32 data); - -static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, - int dsp_index); - -static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index, - u32 address, u32 length); - -static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao, - int dsp_index); - -static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao, - int dsp_index); - -static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index); - -/*****************************************************************************/ - -static void subsys_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - switch (phm->function) { - case HPI_SUBSYS_CREATE_ADAPTER: - subsys_create_adapter(phm, phr); - break; - default: - phr->error = HPI_ERROR_INVALID_FUNC; - break; - } -} - -static void control_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - - struct hpi_hw_obj *phw = pao->priv; - u16 pending_cache_error = 0; - - switch (phm->function) { - case HPI_CONTROL_GET_STATE: - if (pao->has_control_cache) { - rmb(); /* make sure we see updates DMAed from DSP */ - if (hpi_check_control_cache(phw->p_cache, phm, phr)) { - break; - } else if (phm->u.c.attribute == HPI_METER_PEAK) { - pending_cache_error = - HPI_ERROR_CONTROL_CACHING; - } - } - hw_message(pao, phm, phr); - if (pending_cache_error && !phr->error) - phr->error = pending_cache_error; - break; - case HPI_CONTROL_GET_INFO: - hw_message(pao, phm, phr); - break; - case HPI_CONTROL_SET_STATE: - hw_message(pao, phm, phr); - if (pao->has_control_cache) - hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm, - phr); - break; - default: - phr->error = HPI_ERROR_INVALID_FUNC; - break; - } -} - -static void adapter_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - switch (phm->function) { - case HPI_ADAPTER_DELETE: - adapter_delete(pao, phm, phr); - break; - - default: - hw_message(pao, phm, phr); - break; - } -} - -static void outstream_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - - if (phm->obj_index >= HPI_MAX_STREAMS) { - phr->error = HPI_ERROR_INVALID_OBJ_INDEX; - HPI_DEBUG_LOG(WARNING, - "Message referencing invalid stream %d " - "on adapter index %d\n", phm->obj_index, - phm->adapter_index); - return; - } - - switch (phm->function) { - case HPI_OSTREAM_WRITE: - outstream_write(pao, phm, phr); - break; - case HPI_OSTREAM_GET_INFO: - outstream_get_info(pao, phm, phr); - break; - case HPI_OSTREAM_HOSTBUFFER_ALLOC: - outstream_host_buffer_allocate(pao, phm, phr); - break; - case HPI_OSTREAM_HOSTBUFFER_GET_INFO: - outstream_host_buffer_get_info(pao, phm, phr); - break; - case HPI_OSTREAM_HOSTBUFFER_FREE: - outstream_host_buffer_free(pao, phm, phr); - break; - case HPI_OSTREAM_START: - outstream_start(pao, phm, phr); - break; - case HPI_OSTREAM_OPEN: - outstream_open(pao, phm, phr); - break; - case HPI_OSTREAM_RESET: - outstream_reset(pao, phm, phr); - break; - default: - hw_message(pao, phm, phr); - break; - } -} - -static void instream_message(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - - if (phm->obj_index >= HPI_MAX_STREAMS) { - phr->error = HPI_ERROR_INVALID_OBJ_INDEX; - HPI_DEBUG_LOG(WARNING, - "Message referencing invalid stream %d " - "on adapter index %d\n", phm->obj_index, - phm->adapter_index); - return; - } - - switch (phm->function) { - case HPI_ISTREAM_READ: - instream_read(pao, phm, phr); - break; - case HPI_ISTREAM_GET_INFO: - instream_get_info(pao, phm, phr); - break; - case HPI_ISTREAM_HOSTBUFFER_ALLOC: - instream_host_buffer_allocate(pao, phm, phr); - break; - case HPI_ISTREAM_HOSTBUFFER_GET_INFO: - instream_host_buffer_get_info(pao, phm, phr); - break; - case HPI_ISTREAM_HOSTBUFFER_FREE: - instream_host_buffer_free(pao, phm, phr); - break; - case HPI_ISTREAM_START: - instream_start(pao, phm, phr); - break; - default: - hw_message(pao, phm, phr); - break; - } -} - -/*****************************************************************************/ -/** Entry point to this HPI backend - * All calls to the HPI start here - */ -static -void _HPI_6205(struct hpi_adapter_obj *pao, struct hpi_message *phm, - struct hpi_response *phr) -{ - if (pao && (pao->dsp_crashed >= 10) - && (phm->function != HPI_ADAPTER_DEBUG_READ)) { - /* allow last resort debug read even after crash */ - hpi_init_response(phr, phm->object, phm->function, - HPI_ERROR_DSP_HARDWARE); - HPI_DEBUG_LOG(WARNING, " %d,%d dsp crashed.\n", phm->object, - phm->function); - return; - } - - /* Init default response */ - if (phm->function != HPI_SUBSYS_CREATE_ADAPTER) - phr->error = HPI_ERROR_PROCESSING_MESSAGE; - - HPI_DEBUG_LOG(VERBOSE, "start of switch\n"); - switch (phm->type) { - case HPI_TYPE_REQUEST: - switch (phm->object) { - case HPI_OBJ_SUBSYSTEM: - subsys_message(pao, phm, phr); - break; - - case HPI_OBJ_ADAPTER: - adapter_message(pao, phm, phr); - break; - - case HPI_OBJ_CONTROL: - control_message(pao, phm, phr); - break; - - case HPI_OBJ_OSTREAM: - outstream_message(pao, phm, phr); - break; - - case HPI_OBJ_ISTREAM: - instream_message(pao, phm, phr); - break; - - default: - hw_message(pao, phm, phr); - break; - } - break; - - default: - phr->error = HPI_ERROR_INVALID_TYPE; - break; - } -} - -void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_adapter_obj *pao = NULL; - - if (phm->object != HPI_OBJ_SUBSYSTEM) { - /* normal messages must have valid adapter index */ - pao = hpi_find_adapter(phm->adapter_index); - } else { - /* subsys messages don't address an adapter */ - _HPI_6205(NULL, phm, phr); - return; - } - - if (pao) - _HPI_6205(pao, phm, phr); - else - hpi_init_response(phr, phm->object, phm->function, - HPI_ERROR_BAD_ADAPTER_NUMBER); -} - -/*****************************************************************************/ -/* SUBSYSTEM */ - -/** Create an adapter object and initialise it based on resource information - * passed in in the message - * *** NOTE - you cannot use this function AND the FindAdapters function at the - * same time, the application must use only one of them to get the adapters *** - */ -static void subsys_create_adapter(struct hpi_message *phm, - struct hpi_response *phr) -{ - /* create temp adapter obj, because we don't know what index yet */ - struct hpi_adapter_obj ao; - u32 os_error_code; - u16 err; - - HPI_DEBUG_LOG(DEBUG, " subsys_create_adapter\n"); - - memset(&ao, 0, sizeof(ao)); - - ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); - if (!ao.priv) { - HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n"); - phr->error = HPI_ERROR_MEMORY_ALLOC; - return; - } - - ao.pci = *phm->u.s.resource.r.pci; - err = create_adapter_obj(&ao, &os_error_code); - if (err) { - delete_adapter_obj(&ao); - if (err >= HPI_ERROR_BACKEND_BASE) { - phr->error = HPI_ERROR_DSP_BOOTLOAD; - phr->specific_error = err; - } else { - phr->error = err; - } - phr->u.s.data = os_error_code; - return; - } - - phr->u.s.adapter_type = ao.type; - phr->u.s.adapter_index = ao.index; - phr->error = 0; -} - -/** delete an adapter - required by WDM driver */ -static void adapter_delete(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw; - - if (!pao) { - phr->error = HPI_ERROR_INVALID_OBJ_INDEX; - return; - } - phw = pao->priv; - /* reset adapter h/w */ - /* Reset C6713 #1 */ - boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0); - /* reset C6205 */ - iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR); - - delete_adapter_obj(pao); - hpi_delete_adapter(pao); - phr->error = 0; -} - -/** Create adapter object - allocate buffers, bootload DSPs, initialise control cache -*/ -static u16 create_adapter_obj(struct hpi_adapter_obj *pao, - u32 *pos_error_code) -{ - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface; - u32 phys_addr; - int i; - u16 err; - - /* init error reporting */ - pao->dsp_crashed = 0; - - for (i = 0; i < HPI_MAX_STREAMS; i++) - phw->flag_outstream_just_reset[i] = 1; - - /* The C6205 memory area 1 is 8Mbyte window into DSP registers */ - phw->prHSR = - pao->pci.ap_mem_base[1] + - C6205_BAR1_HSR / sizeof(*pao->pci.ap_mem_base[1]); - phw->prHDCR = - pao->pci.ap_mem_base[1] + - C6205_BAR1_HDCR / sizeof(*pao->pci.ap_mem_base[1]); - phw->prDSPP = - pao->pci.ap_mem_base[1] + - C6205_BAR1_DSPP / sizeof(*pao->pci.ap_mem_base[1]); - - pao->has_control_cache = 0; - - if (hpios_locked_mem_alloc(&phw->h_locked_mem, - sizeof(struct bus_master_interface), - pao->pci.pci_dev)) - phw->p_interface_buffer = NULL; - else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem, - (void *)&phw->p_interface_buffer)) - phw->p_interface_buffer = NULL; - - HPI_DEBUG_LOG(DEBUG, "interface buffer address %p\n", - phw->p_interface_buffer); - - if (phw->p_interface_buffer) { - memset((void *)phw->p_interface_buffer, 0, - sizeof(struct bus_master_interface)); - phw->p_interface_buffer->dsp_ack = H620_HIF_UNKNOWN; - } - - err = adapter_boot_load_dsp(pao, pos_error_code); - if (err) { - HPI_DEBUG_LOG(ERROR, "DSP code load failed\n"); - /* no need to clean up as SubSysCreateAdapter */ - /* calls DeleteAdapter on error. */ - return err; - } - HPI_DEBUG_LOG(INFO, "load DSP code OK\n"); - - /* allow boot load even if mem alloc wont work */ - if (!phw->p_interface_buffer) - return HPI_ERROR_MEMORY_ALLOC; - - interface = phw->p_interface_buffer; - - /* make sure the DSP has started ok */ - if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) { - HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n"); - return HPI6205_ERROR_6205_INIT_FAILED; - } - /* Note that *pao, *phw are zeroed after allocation, - * so pointers and flags are NULL by default. - * Allocate bus mastering control cache buffer and tell the DSP about it - */ - if (interface->control_cache.number_of_controls) { - u8 *p_control_cache_virtual; - - err = hpios_locked_mem_alloc(&phw->h_control_cache, - interface->control_cache.size_in_bytes, - pao->pci.pci_dev); - if (!err) - err = hpios_locked_mem_get_virt_addr(&phw-> - h_control_cache, - (void *)&p_control_cache_virtual); - if (!err) { - memset(p_control_cache_virtual, 0, - interface->control_cache.size_in_bytes); - - phw->p_cache = - hpi_alloc_control_cache(interface-> - control_cache.number_of_controls, - interface->control_cache.size_in_bytes, - p_control_cache_virtual); - - if (!phw->p_cache) - err = HPI_ERROR_MEMORY_ALLOC; - } - if (!err) { - err = hpios_locked_mem_get_phys_addr(&phw-> - h_control_cache, &phys_addr); - interface->control_cache.physical_address32 = - phys_addr; - } - - if (!err) - pao->has_control_cache = 1; - else { - if (hpios_locked_mem_valid(&phw->h_control_cache)) - hpios_locked_mem_free(&phw->h_control_cache); - pao->has_control_cache = 0; - } - } - send_dsp_command(phw, H620_HIF_IDLE); - - { - struct hpi_message hm; - struct hpi_response hr; - u32 max_streams; - - HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n"); - memset(&hm, 0, sizeof(hm)); - /* wAdapterIndex == version == 0 */ - hm.type = HPI_TYPE_REQUEST; - hm.size = sizeof(hm); - hm.object = HPI_OBJ_ADAPTER; - hm.function = HPI_ADAPTER_GET_INFO; - - memset(&hr, 0, sizeof(hr)); - hr.size = sizeof(hr); - - err = message_response_sequence(pao, &hm, &hr); - if (err) { - HPI_DEBUG_LOG(ERROR, "message transport error %d\n", - err); - return err; - } - if (hr.error) - return hr.error; - - pao->type = hr.u.ax.info.adapter_type; - pao->index = hr.u.ax.info.adapter_index; - - max_streams = - hr.u.ax.info.num_outstreams + - hr.u.ax.info.num_instreams; - - HPI_DEBUG_LOG(VERBOSE, - "got adapter info type %x index %d serial %d\n", - hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index, - hr.u.ax.info.serial_number); - } - - if (phw->p_cache) - phw->p_cache->adap_idx = pao->index; - - HPI_DEBUG_LOG(INFO, "bootload DSP OK\n"); - - return hpi_add_adapter(pao); -} - -/** Free memory areas allocated by adapter - * this routine is called from AdapterDelete, - * and SubSysCreateAdapter if duplicate index -*/ -static void delete_adapter_obj(struct hpi_adapter_obj *pao) -{ - struct hpi_hw_obj *phw = pao->priv; - int i; - - if (hpios_locked_mem_valid(&phw->h_control_cache)) { - hpios_locked_mem_free(&phw->h_control_cache); - hpi_free_control_cache(phw->p_cache); - } - - if (hpios_locked_mem_valid(&phw->h_locked_mem)) { - hpios_locked_mem_free(&phw->h_locked_mem); - phw->p_interface_buffer = NULL; - } - - for (i = 0; i < HPI_MAX_STREAMS; i++) - if (hpios_locked_mem_valid(&phw->instream_host_buffers[i])) { - hpios_locked_mem_free(&phw->instream_host_buffers[i]); - /*?phw->InStreamHostBuffers[i] = NULL; */ - phw->instream_host_buffer_size[i] = 0; - } - - for (i = 0; i < HPI_MAX_STREAMS; i++) - if (hpios_locked_mem_valid(&phw->outstream_host_buffers[i])) { - hpios_locked_mem_free(&phw->outstream_host_buffers - [i]); - phw->outstream_host_buffer_size[i] = 0; - } - kfree(phw); -} - -/*****************************************************************************/ -/* Adapter functions */ - -/*****************************************************************************/ -/* OutStream Host buffer functions */ - -/** Allocate or attach buffer for busmastering -*/ -static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - u16 err = 0; - u32 command = phm->u.d.u.buffer.command; - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - - hpi_init_response(phr, phm->object, phm->function, 0); - - if (command == HPI_BUFFER_CMD_EXTERNAL - || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) { - /* ALLOC phase, allocate a buffer with power of 2 size, - get its bus address for PCI bus mastering - */ - phm->u.d.u.buffer.buffer_size = - roundup_pow_of_two(phm->u.d.u.buffer.buffer_size); - /* return old size and allocated size, - so caller can detect change */ - phr->u.d.u.stream_info.data_available = - phw->outstream_host_buffer_size[phm->obj_index]; - phr->u.d.u.stream_info.buffer_size = - phm->u.d.u.buffer.buffer_size; - - if (phw->outstream_host_buffer_size[phm->obj_index] == - phm->u.d.u.buffer.buffer_size) { - /* Same size, no action required */ - return; - } - - if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm-> - obj_index])) - hpios_locked_mem_free(&phw->outstream_host_buffers - [phm->obj_index]); - - err = hpios_locked_mem_alloc(&phw->outstream_host_buffers - [phm->obj_index], phm->u.d.u.buffer.buffer_size, - pao->pci.pci_dev); - - if (err) { - phr->error = HPI_ERROR_INVALID_DATASIZE; - phw->outstream_host_buffer_size[phm->obj_index] = 0; - return; - } - - err = hpios_locked_mem_get_phys_addr - (&phw->outstream_host_buffers[phm->obj_index], - &phm->u.d.u.buffer.pci_address); - /* get the phys addr into msg for single call alloc caller - * needs to do this for split alloc (or use the same message) - * return the phy address for split alloc in the respose too - */ - phr->u.d.u.stream_info.auxiliary_data_available = - phm->u.d.u.buffer.pci_address; - - if (err) { - hpios_locked_mem_free(&phw->outstream_host_buffers - [phm->obj_index]); - phw->outstream_host_buffer_size[phm->obj_index] = 0; - phr->error = HPI_ERROR_MEMORY_ALLOC; - return; - } - } - - if (command == HPI_BUFFER_CMD_EXTERNAL - || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) { - /* GRANT phase. Set up the BBM status, tell the DSP about - the buffer so it can start using BBM. - */ - struct hpi_hostbuffer_status *status; - - if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer. - buffer_size - 1)) { - HPI_DEBUG_LOG(ERROR, - "Buffer size must be 2^N not %d\n", - phm->u.d.u.buffer.buffer_size); - phr->error = HPI_ERROR_INVALID_DATASIZE; - return; - } - phw->outstream_host_buffer_size[phm->obj_index] = - phm->u.d.u.buffer.buffer_size; - status = &interface->outstream_host_buffer_status[phm-> - obj_index]; - status->samples_processed = 0; - status->stream_state = HPI_STATE_STOPPED; - status->dsp_index = 0; - status->host_index = status->dsp_index; - status->size_in_bytes = phm->u.d.u.buffer.buffer_size; - status->auxiliary_data_available = 0; - - hw_message(pao, phm, phr); - - if (phr->error - && hpios_locked_mem_valid(&phw-> - outstream_host_buffers[phm->obj_index])) { - hpios_locked_mem_free(&phw->outstream_host_buffers - [phm->obj_index]); - phw->outstream_host_buffer_size[phm->obj_index] = 0; - } - } -} - -static void outstream_host_buffer_get_info(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - struct hpi_hostbuffer_status *status; - u8 *p_bbm_data; - - if (hpios_locked_mem_valid(&phw->outstream_host_buffers[phm-> - obj_index])) { - if (hpios_locked_mem_get_virt_addr(&phw-> - outstream_host_buffers[phm->obj_index], - (void *)&p_bbm_data)) { - phr->error = HPI_ERROR_INVALID_OPERATION; - return; - } - status = &interface->outstream_host_buffer_status[phm-> - obj_index]; - hpi_init_response(phr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_HOSTBUFFER_GET_INFO, 0); - phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data; - phr->u.d.u.hostbuffer_info.p_status = status; - } else { - hpi_init_response(phr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_HOSTBUFFER_GET_INFO, - HPI_ERROR_INVALID_OPERATION); - } -} - -static void outstream_host_buffer_free(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - u32 command = phm->u.d.u.buffer.command; - - if (phw->outstream_host_buffer_size[phm->obj_index]) { - if (command == HPI_BUFFER_CMD_EXTERNAL - || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) { - phw->outstream_host_buffer_size[phm->obj_index] = 0; - hw_message(pao, phm, phr); - /* Tell adapter to stop using the host buffer. */ - } - if (command == HPI_BUFFER_CMD_EXTERNAL - || command == HPI_BUFFER_CMD_INTERNAL_FREE) - hpios_locked_mem_free(&phw->outstream_host_buffers - [phm->obj_index]); - } - /* Should HPI_ERROR_INVALID_OPERATION be returned - if no host buffer is allocated? */ - else - hpi_init_response(phr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_HOSTBUFFER_FREE, 0); - -} - -static u32 outstream_get_space_available(struct hpi_hostbuffer_status *status) -{ - return status->size_in_bytes - (status->host_index - - status->dsp_index); -} - -static void outstream_write(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - struct hpi_hostbuffer_status *status; - u32 space_available; - - if (!phw->outstream_host_buffer_size[phm->obj_index]) { - /* there is no BBM buffer, write via message */ - hw_message(pao, phm, phr); - return; - } - - hpi_init_response(phr, phm->object, phm->function, 0); - status = &interface->outstream_host_buffer_status[phm->obj_index]; - - space_available = outstream_get_space_available(status); - if (space_available < phm->u.d.u.data.data_size) { - phr->error = HPI_ERROR_INVALID_DATASIZE; - return; - } - - /* HostBuffers is used to indicate host buffer is internally allocated. - otherwise, assumed external, data written externally */ - if (phm->u.d.u.data.pb_data - && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm-> - obj_index])) { - u8 *p_bbm_data; - u32 l_first_write; - u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data; - - if (hpios_locked_mem_get_virt_addr(&phw-> - outstream_host_buffers[phm->obj_index], - (void *)&p_bbm_data)) { - phr->error = HPI_ERROR_INVALID_OPERATION; - return; - } - - /* either all data, - or enough to fit from current to end of BBM buffer */ - l_first_write = - min(phm->u.d.u.data.data_size, - status->size_in_bytes - - (status->host_index & (status->size_in_bytes - 1))); - - memcpy(p_bbm_data + - (status->host_index & (status->size_in_bytes - 1)), - p_app_data, l_first_write); - /* remaining data if any */ - memcpy(p_bbm_data, p_app_data + l_first_write, - phm->u.d.u.data.data_size - l_first_write); - } - - /* - * This version relies on the DSP code triggering an OStream buffer - * update immediately following a SET_FORMAT call. The host has - * already written data into the BBM buffer, but the DSP won't know - * about it until dwHostIndex is adjusted. - */ - if (phw->flag_outstream_just_reset[phm->obj_index]) { - /* Format can only change after reset. Must tell DSP. */ - u16 function = phm->function; - phw->flag_outstream_just_reset[phm->obj_index] = 0; - phm->function = HPI_OSTREAM_SET_FORMAT; - hw_message(pao, phm, phr); /* send the format to the DSP */ - phm->function = function; - if (phr->error) - return; - } - - status->host_index += phm->u.d.u.data.data_size; -} - -static void outstream_get_info(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - struct hpi_hostbuffer_status *status; - - if (!phw->outstream_host_buffer_size[phm->obj_index]) { - hw_message(pao, phm, phr); - return; - } - - hpi_init_response(phr, phm->object, phm->function, 0); - - status = &interface->outstream_host_buffer_status[phm->obj_index]; - - phr->u.d.u.stream_info.state = (u16)status->stream_state; - phr->u.d.u.stream_info.samples_transferred = - status->samples_processed; - phr->u.d.u.stream_info.buffer_size = status->size_in_bytes; - phr->u.d.u.stream_info.data_available = - status->size_in_bytes - outstream_get_space_available(status); - phr->u.d.u.stream_info.auxiliary_data_available = - status->auxiliary_data_available; -} - -static void outstream_start(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - hw_message(pao, phm, phr); -} - -static void outstream_reset(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - phw->flag_outstream_just_reset[phm->obj_index] = 1; - hw_message(pao, phm, phr); -} - -static void outstream_open(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - outstream_reset(pao, phm, phr); -} - -/*****************************************************************************/ -/* InStream Host buffer functions */ - -static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - u16 err = 0; - u32 command = phm->u.d.u.buffer.command; - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - - hpi_init_response(phr, phm->object, phm->function, 0); - - if (command == HPI_BUFFER_CMD_EXTERNAL - || command == HPI_BUFFER_CMD_INTERNAL_ALLOC) { - - phm->u.d.u.buffer.buffer_size = - roundup_pow_of_two(phm->u.d.u.buffer.buffer_size); - phr->u.d.u.stream_info.data_available = - phw->instream_host_buffer_size[phm->obj_index]; - phr->u.d.u.stream_info.buffer_size = - phm->u.d.u.buffer.buffer_size; - - if (phw->instream_host_buffer_size[phm->obj_index] == - phm->u.d.u.buffer.buffer_size) { - /* Same size, no action required */ - return; - } - - if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm-> - obj_index])) - hpios_locked_mem_free(&phw->instream_host_buffers - [phm->obj_index]); - - err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm-> - obj_index], phm->u.d.u.buffer.buffer_size, - pao->pci.pci_dev); - - if (err) { - phr->error = HPI_ERROR_INVALID_DATASIZE; - phw->instream_host_buffer_size[phm->obj_index] = 0; - return; - } - - err = hpios_locked_mem_get_phys_addr - (&phw->instream_host_buffers[phm->obj_index], - &phm->u.d.u.buffer.pci_address); - /* get the phys addr into msg for single call alloc. Caller - needs to do this for split alloc so return the phy address */ - phr->u.d.u.stream_info.auxiliary_data_available = - phm->u.d.u.buffer.pci_address; - if (err) { - hpios_locked_mem_free(&phw->instream_host_buffers - [phm->obj_index]); - phw->instream_host_buffer_size[phm->obj_index] = 0; - phr->error = HPI_ERROR_MEMORY_ALLOC; - return; - } - } - - if (command == HPI_BUFFER_CMD_EXTERNAL - || command == HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER) { - struct hpi_hostbuffer_status *status; - - if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer. - buffer_size - 1)) { - HPI_DEBUG_LOG(ERROR, - "Buffer size must be 2^N not %d\n", - phm->u.d.u.buffer.buffer_size); - phr->error = HPI_ERROR_INVALID_DATASIZE; - return; - } - - phw->instream_host_buffer_size[phm->obj_index] = - phm->u.d.u.buffer.buffer_size; - status = &interface->instream_host_buffer_status[phm-> - obj_index]; - status->samples_processed = 0; - status->stream_state = HPI_STATE_STOPPED; - status->dsp_index = 0; - status->host_index = status->dsp_index; - status->size_in_bytes = phm->u.d.u.buffer.buffer_size; - status->auxiliary_data_available = 0; - - hw_message(pao, phm, phr); - - if (phr->error - && hpios_locked_mem_valid(&phw-> - instream_host_buffers[phm->obj_index])) { - hpios_locked_mem_free(&phw->instream_host_buffers - [phm->obj_index]); - phw->instream_host_buffer_size[phm->obj_index] = 0; - } - } -} - -static void instream_host_buffer_get_info(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - struct hpi_hostbuffer_status *status; - u8 *p_bbm_data; - - if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm-> - obj_index])) { - if (hpios_locked_mem_get_virt_addr(&phw-> - instream_host_buffers[phm->obj_index], - (void *)&p_bbm_data)) { - phr->error = HPI_ERROR_INVALID_OPERATION; - return; - } - status = &interface->instream_host_buffer_status[phm-> - obj_index]; - hpi_init_response(phr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_HOSTBUFFER_GET_INFO, 0); - phr->u.d.u.hostbuffer_info.p_buffer = p_bbm_data; - phr->u.d.u.hostbuffer_info.p_status = status; - } else { - hpi_init_response(phr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_HOSTBUFFER_GET_INFO, - HPI_ERROR_INVALID_OPERATION); - } -} - -static void instream_host_buffer_free(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - u32 command = phm->u.d.u.buffer.command; - - if (phw->instream_host_buffer_size[phm->obj_index]) { - if (command == HPI_BUFFER_CMD_EXTERNAL - || command == HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER) { - phw->instream_host_buffer_size[phm->obj_index] = 0; - hw_message(pao, phm, phr); - } - - if (command == HPI_BUFFER_CMD_EXTERNAL - || command == HPI_BUFFER_CMD_INTERNAL_FREE) - hpios_locked_mem_free(&phw->instream_host_buffers - [phm->obj_index]); - - } else { - /* Should HPI_ERROR_INVALID_OPERATION be returned - if no host buffer is allocated? */ - hpi_init_response(phr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_HOSTBUFFER_FREE, 0); - - } - -} - -static void instream_start(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - hw_message(pao, phm, phr); -} - -static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status) -{ - return status->dsp_index - status->host_index; -} - -static void instream_read(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - struct hpi_hostbuffer_status *status; - u32 data_available; - u8 *p_bbm_data; - u32 l_first_read; - u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data; - - if (!phw->instream_host_buffer_size[phm->obj_index]) { - hw_message(pao, phm, phr); - return; - } - hpi_init_response(phr, phm->object, phm->function, 0); - - status = &interface->instream_host_buffer_status[phm->obj_index]; - data_available = instream_get_bytes_available(status); - if (data_available < phm->u.d.u.data.data_size) { - phr->error = HPI_ERROR_INVALID_DATASIZE; - return; - } - - if (hpios_locked_mem_valid(&phw->instream_host_buffers[phm-> - obj_index])) { - if (hpios_locked_mem_get_virt_addr(&phw-> - instream_host_buffers[phm->obj_index], - (void *)&p_bbm_data)) { - phr->error = HPI_ERROR_INVALID_OPERATION; - return; - } - - /* either all data, - or enough to fit from current to end of BBM buffer */ - l_first_read = - min(phm->u.d.u.data.data_size, - status->size_in_bytes - - (status->host_index & (status->size_in_bytes - 1))); - - memcpy(p_app_data, - p_bbm_data + - (status->host_index & (status->size_in_bytes - 1)), - l_first_read); - /* remaining data if any */ - memcpy(p_app_data + l_first_read, p_bbm_data, - phm->u.d.u.data.data_size - l_first_read); - } - status->host_index += phm->u.d.u.data.data_size; -} - -static void instream_get_info(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - struct hpi_hostbuffer_status *status; - if (!phw->instream_host_buffer_size[phm->obj_index]) { - hw_message(pao, phm, phr); - return; - } - - status = &interface->instream_host_buffer_status[phm->obj_index]; - - hpi_init_response(phr, phm->object, phm->function, 0); - - phr->u.d.u.stream_info.state = (u16)status->stream_state; - phr->u.d.u.stream_info.samples_transferred = - status->samples_processed; - phr->u.d.u.stream_info.buffer_size = status->size_in_bytes; - phr->u.d.u.stream_info.data_available = - instream_get_bytes_available(status); - phr->u.d.u.stream_info.auxiliary_data_available = - status->auxiliary_data_available; -} - -/*****************************************************************************/ -/* LOW-LEVEL */ -#define HPI6205_MAX_FILES_TO_LOAD 2 - -static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, - u32 *pos_error_code) -{ - struct hpi_hw_obj *phw = pao->priv; - struct dsp_code dsp_code; - u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD]; - u32 temp; - int dsp = 0, i = 0; - u16 err = 0; - - boot_code_id[0] = HPI_ADAPTER_ASI(0x6205); - - boot_code_id[1] = pao->pci.pci_dev->subsystem_device; - boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(boot_code_id[1]); - - /* fix up cases where bootcode id[1] != subsys id */ - switch (boot_code_id[1]) { - case HPI_ADAPTER_FAMILY_ASI(0x5000): - boot_code_id[0] = boot_code_id[1]; - boot_code_id[1] = 0; - break; - case HPI_ADAPTER_FAMILY_ASI(0x5300): - case HPI_ADAPTER_FAMILY_ASI(0x5400): - case HPI_ADAPTER_FAMILY_ASI(0x6300): - boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400); - break; - case HPI_ADAPTER_FAMILY_ASI(0x5500): - case HPI_ADAPTER_FAMILY_ASI(0x5600): - case HPI_ADAPTER_FAMILY_ASI(0x6500): - boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600); - break; - case HPI_ADAPTER_FAMILY_ASI(0x8800): - boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x8900); - break; - default: - break; - } - - /* reset DSP by writing a 1 to the WARMRESET bit */ - temp = C6205_HDCR_WARMRESET; - iowrite32(temp, phw->prHDCR); - hpios_delay_micro_seconds(1000); - - /* check that PCI i/f was configured by EEPROM */ - temp = ioread32(phw->prHSR); - if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) != - C6205_HSR_EEREAD) - return HPI6205_ERROR_6205_EEPROM; - temp |= 0x04; - /* disable PINTA interrupt */ - iowrite32(temp, phw->prHSR); - - /* check control register reports PCI boot mode */ - temp = ioread32(phw->prHDCR); - if (!(temp & C6205_HDCR_PCIBOOT)) - return HPI6205_ERROR_6205_REG; - - /* try writing a few numbers to the DSP page register */ - /* and reading them back. */ - temp = 3; - iowrite32(temp, phw->prDSPP); - if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) - return HPI6205_ERROR_6205_DSPPAGE; - temp = 2; - iowrite32(temp, phw->prDSPP); - if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) - return HPI6205_ERROR_6205_DSPPAGE; - temp = 1; - iowrite32(temp, phw->prDSPP); - if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) - return HPI6205_ERROR_6205_DSPPAGE; - /* reset DSP page to the correct number */ - temp = 0; - iowrite32(temp, phw->prDSPP); - if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) - return HPI6205_ERROR_6205_DSPPAGE; - phw->dsp_page = 0; - - /* release 6713 from reset before 6205 is bootloaded. - This ensures that the EMIF is inactive, - and the 6713 HPI gets the correct bootmode etc - */ - if (boot_code_id[1] != 0) { - /* DSP 1 is a C6713 */ - /* CLKX0 <- '1' release the C6205 bootmode pulldowns */ - boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002202); - hpios_delay_micro_seconds(100); - /* Reset the 6713 #1 - revB */ - boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0); - - /* dummy read every 4 words for 6205 advisory 1.4.4 */ - boot_loader_read_mem32(pao, 0, 0); - - hpios_delay_micro_seconds(100); - /* Release C6713 from reset - revB */ - boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 4); - hpios_delay_micro_seconds(100); - } - - for (dsp = 0; dsp < HPI6205_MAX_FILES_TO_LOAD; dsp++) { - /* is there a DSP to load? */ - if (boot_code_id[dsp] == 0) - continue; - - err = boot_loader_config_emif(pao, dsp); - if (err) - return err; - - err = boot_loader_test_internal_memory(pao, dsp); - if (err) - return err; - - err = boot_loader_test_external_memory(pao, dsp); - if (err) - return err; - - err = boot_loader_test_pld(pao, dsp); - if (err) - return err; - - /* write the DSP code down into the DSPs memory */ - err = hpi_dsp_code_open(boot_code_id[dsp], pao->pci.pci_dev, - &dsp_code, pos_error_code); - if (err) - return err; - - while (1) { - u32 length; - u32 address; - u32 type; - u32 *pcode; - - err = hpi_dsp_code_read_word(&dsp_code, &length); - if (err) - break; - if (length == 0xFFFFFFFF) - break; /* end of code */ - - err = hpi_dsp_code_read_word(&dsp_code, &address); - if (err) - break; - err = hpi_dsp_code_read_word(&dsp_code, &type); - if (err) - break; - err = hpi_dsp_code_read_block(length, &dsp_code, - &pcode); - if (err) - break; - for (i = 0; i < (int)length; i++) { - boot_loader_write_mem32(pao, dsp, address, - *pcode); - /* dummy read every 4 words */ - /* for 6205 advisory 1.4.4 */ - if (i % 4 == 0) - boot_loader_read_mem32(pao, dsp, - address); - pcode++; - address += 4; - } - - } - if (err) { - hpi_dsp_code_close(&dsp_code); - return err; - } - - /* verify code */ - hpi_dsp_code_rewind(&dsp_code); - while (1) { - u32 length = 0; - u32 address = 0; - u32 type = 0; - u32 *pcode = NULL; - u32 data = 0; - - hpi_dsp_code_read_word(&dsp_code, &length); - if (length == 0xFFFFFFFF) - break; /* end of code */ - - hpi_dsp_code_read_word(&dsp_code, &address); - hpi_dsp_code_read_word(&dsp_code, &type); - hpi_dsp_code_read_block(length, &dsp_code, &pcode); - - for (i = 0; i < (int)length; i++) { - data = boot_loader_read_mem32(pao, dsp, - address); - if (data != *pcode) { - err = 0; - break; - } - pcode++; - address += 4; - } - if (err) - break; - } - hpi_dsp_code_close(&dsp_code); - if (err) - return err; - } - - /* After bootloading all DSPs, start DSP0 running - * The DSP0 code will handle starting and synchronizing with its slaves - */ - if (phw->p_interface_buffer) { - /* we need to tell the card the physical PCI address */ - u32 physicalPC_iaddress; - struct bus_master_interface *interface = - phw->p_interface_buffer; - u32 host_mailbox_address_on_dsp; - u32 physicalPC_iaddress_verify = 0; - int time_out = 10; - /* set ack so we know when DSP is ready to go */ - /* (dwDspAck will be changed to HIF_RESET) */ - interface->dsp_ack = H620_HIF_UNKNOWN; - wmb(); /* ensure ack is written before dsp writes back */ - - err = hpios_locked_mem_get_phys_addr(&phw->h_locked_mem, - &physicalPC_iaddress); - - /* locate the host mailbox on the DSP. */ - host_mailbox_address_on_dsp = 0x80000000; - while ((physicalPC_iaddress != physicalPC_iaddress_verify) - && time_out--) { - boot_loader_write_mem32(pao, 0, - host_mailbox_address_on_dsp, - physicalPC_iaddress); - physicalPC_iaddress_verify = - boot_loader_read_mem32(pao, 0, - host_mailbox_address_on_dsp); - } - } - HPI_DEBUG_LOG(DEBUG, "starting DS_ps running\n"); - /* enable interrupts */ - temp = ioread32(phw->prHSR); - temp &= ~(u32)C6205_HSR_INTAM; - iowrite32(temp, phw->prHSR); - - /* start code running... */ - temp = ioread32(phw->prHDCR); - temp |= (u32)C6205_HDCR_DSPINT; - iowrite32(temp, phw->prHDCR); - - /* give the DSP 10ms to start up */ - hpios_delay_micro_seconds(10000); - return err; - -} - -/*****************************************************************************/ -/* Bootloader utility functions */ - -static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index, - u32 address) -{ - struct hpi_hw_obj *phw = pao->priv; - u32 data = 0; - __iomem u32 *p_data; - - if (dsp_index == 0) { - /* DSP 0 is always C6205 */ - if ((address >= 0x01800000) & (address < 0x02000000)) { - /* BAR1 register access */ - p_data = pao->pci.ap_mem_base[1] + - (address & 0x007fffff) / - sizeof(*pao->pci.ap_mem_base[1]); - /* HPI_DEBUG_LOG(WARNING, - "BAR1 access %08x\n", dwAddress); */ - } else { - u32 dw4M_page = address >> 22L; - if (dw4M_page != phw->dsp_page) { - phw->dsp_page = dw4M_page; - /* *INDENT OFF* */ - iowrite32(phw->dsp_page, phw->prDSPP); - /* *INDENT-ON* */ - } - address &= 0x3fffff; /* address within 4M page */ - /* BAR0 memory access */ - p_data = pao->pci.ap_mem_base[0] + - address / sizeof(u32); - } - data = ioread32(p_data); - } else if (dsp_index == 1) { - /* DSP 1 is a C6713 */ - u32 lsb; - boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address); - boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16); - lsb = boot_loader_read_mem32(pao, 0, HPIDL_ADDR); - data = boot_loader_read_mem32(pao, 0, HPIDH_ADDR); - data = (data << 16) | (lsb & 0xFFFF); - } - return data; -} - -static void boot_loader_write_mem32(struct hpi_adapter_obj *pao, - int dsp_index, u32 address, u32 data) -{ - struct hpi_hw_obj *phw = pao->priv; - __iomem u32 *p_data; - /* u32 dwVerifyData=0; */ - - if (dsp_index == 0) { - /* DSP 0 is always C6205 */ - if ((address >= 0x01800000) & (address < 0x02000000)) { - /* BAR1 - DSP register access using */ - /* Non-prefetchable PCI access */ - p_data = pao->pci.ap_mem_base[1] + - (address & 0x007fffff) / - sizeof(*pao->pci.ap_mem_base[1]); - } else { - /* BAR0 access - all of DSP memory using */ - /* pre-fetchable PCI access */ - u32 dw4M_page = address >> 22L; - if (dw4M_page != phw->dsp_page) { - phw->dsp_page = dw4M_page; - /* *INDENT-OFF* */ - iowrite32(phw->dsp_page, phw->prDSPP); - /* *INDENT-ON* */ - } - address &= 0x3fffff; /* address within 4M page */ - p_data = pao->pci.ap_mem_base[0] + - address / sizeof(u32); - } - iowrite32(data, p_data); - } else if (dsp_index == 1) { - /* DSP 1 is a C6713 */ - boot_loader_write_mem32(pao, 0, HPIAL_ADDR, address); - boot_loader_write_mem32(pao, 0, HPIAH_ADDR, address >> 16); - - /* dummy read every 4 words for 6205 advisory 1.4.4 */ - boot_loader_read_mem32(pao, 0, 0); - - boot_loader_write_mem32(pao, 0, HPIDL_ADDR, data); - boot_loader_write_mem32(pao, 0, HPIDH_ADDR, data >> 16); - - /* dummy read every 4 words for 6205 advisory 1.4.4 */ - boot_loader_read_mem32(pao, 0, 0); - } -} - -static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) -{ - if (dsp_index == 0) { - u32 setting; - - /* DSP 0 is always C6205 */ - - /* Set the EMIF */ - /* memory map of C6205 */ - /* 00000000-0000FFFF 16Kx32 internal program */ - /* 00400000-00BFFFFF CE0 2Mx32 SDRAM running @ 100MHz */ - - /* EMIF config */ - /*------------ */ - /* Global EMIF control */ - boot_loader_write_mem32(pao, dsp_index, 0x01800000, 0x3779); -#define WS_OFS 28 -#define WST_OFS 22 -#define WH_OFS 20 -#define RS_OFS 16 -#define RST_OFS 8 -#define MTYPE_OFS 4 -#define RH_OFS 0 - - /* EMIF CE0 setup - 2Mx32 Sync DRAM on ASI5000 cards only */ - setting = 0x00000030; - boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting); - if (setting != boot_loader_read_mem32(pao, dsp_index, - 0x01800008)) - return HPI6205_ERROR_DSP_EMIF1; - - /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */ - /* which occupies D15..0. 6713 starts at 27MHz, so need */ - /* plenty of wait states. See dsn8701.rtf, and 6713 errata. */ - /* WST should be 71, but 63 is max possible */ - setting = - (1L << WS_OFS) | (63L << WST_OFS) | (1L << WH_OFS) | - (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) | - (2L << MTYPE_OFS); - boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting); - if (setting != boot_loader_read_mem32(pao, dsp_index, - 0x01800004)) - return HPI6205_ERROR_DSP_EMIF2; - - /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */ - /* which occupies D15..0. 6713 starts at 27MHz, so need */ - /* plenty of wait states */ - setting = - (1L << WS_OFS) | (28L << WST_OFS) | (1L << WH_OFS) | - (1L << RS_OFS) | (63L << RST_OFS) | (1L << RH_OFS) | - (2L << MTYPE_OFS); - boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting); - if (setting != boot_loader_read_mem32(pao, dsp_index, - 0x01800010)) - return HPI6205_ERROR_DSP_EMIF3; - - /* EMIF CE3 setup - 32 bit async. */ - /* This is the PLD on the ASI5000 cards only */ - setting = - (1L << WS_OFS) | (10L << WST_OFS) | (1L << WH_OFS) | - (1L << RS_OFS) | (10L << RST_OFS) | (1L << RH_OFS) | - (2L << MTYPE_OFS); - boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting); - if (setting != boot_loader_read_mem32(pao, dsp_index, - 0x01800014)) - return HPI6205_ERROR_DSP_EMIF4; - - /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */ - /* need to use this else DSP code crashes? */ - boot_loader_write_mem32(pao, dsp_index, 0x01800018, - 0x07117000); - - /* EMIF SDRAM Refresh Timing */ - /* EMIF SDRAM timing (orig = 0x410, emulator = 0x61a) */ - boot_loader_write_mem32(pao, dsp_index, 0x0180001C, - 0x00000410); - - } else if (dsp_index == 1) { - /* test access to the C6713s HPI registers */ - u32 write_data = 0, read_data = 0, i = 0; - - /* Set up HPIC for little endian, by setiing HPIC:HWOB=1 */ - write_data = 1; - boot_loader_write_mem32(pao, 0, HPICL_ADDR, write_data); - boot_loader_write_mem32(pao, 0, HPICH_ADDR, write_data); - /* C67 HPI is on lower 16bits of 32bit EMIF */ - read_data = - 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR); - if (write_data != read_data) { - HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data, - read_data); - return HPI6205_ERROR_C6713_HPIC; - } - /* HPIA - walking ones test */ - write_data = 1; - for (i = 0; i < 32; i++) { - boot_loader_write_mem32(pao, 0, HPIAL_ADDR, - write_data); - boot_loader_write_mem32(pao, 0, HPIAH_ADDR, - (write_data >> 16)); - read_data = - 0xFFFF & boot_loader_read_mem32(pao, 0, - HPIAL_ADDR); - read_data = - read_data | ((0xFFFF & - boot_loader_read_mem32(pao, 0, - HPIAH_ADDR)) - << 16); - if (read_data != write_data) { - HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n", - write_data, read_data); - return HPI6205_ERROR_C6713_HPIA; - } - write_data = write_data << 1; - } - - /* setup C67x PLL - * ** C6713 datasheet says we cannot program PLL from HPI, - * and indeed if we try to set the PLL multiply from the HPI, - * the PLL does not seem to lock, so we enable the PLL and - * use the default multiply of x 7, which for a 27MHz clock - * gives a DSP speed of 189MHz - */ - /* bypass PLL */ - boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0000); - hpios_delay_micro_seconds(1000); - /* EMIF = 189/3=63MHz */ - boot_loader_write_mem32(pao, dsp_index, 0x01B7C120, 0x8002); - /* peri = 189/2 */ - boot_loader_write_mem32(pao, dsp_index, 0x01B7C11C, 0x8001); - /* cpu = 189/1 */ - boot_loader_write_mem32(pao, dsp_index, 0x01B7C118, 0x8000); - hpios_delay_micro_seconds(1000); - /* ** SGT test to take GPO3 high when we start the PLL */ - /* and low when the delay is completed */ - /* FSX0 <- '1' (GPO3) */ - boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A0A); - /* PLL not bypassed */ - boot_loader_write_mem32(pao, dsp_index, 0x01B7C100, 0x0001); - hpios_delay_micro_seconds(1000); - /* FSX0 <- '0' (GPO3) */ - boot_loader_write_mem32(pao, 0, (0x018C0024L), 0x00002A02); - - /* 6205 EMIF CE1 resetup - 32 bit async. */ - /* Now 6713 #1 is running at 189MHz can reduce waitstates */ - boot_loader_write_mem32(pao, 0, 0x01800004, /* CE1 */ - (1L << WS_OFS) | (8L << WST_OFS) | (1L << WH_OFS) | - (1L << RS_OFS) | (12L << RST_OFS) | (1L << RH_OFS) | - (2L << MTYPE_OFS)); - - hpios_delay_micro_seconds(1000); - - /* check that we can read one of the PLL registers */ - /* PLL should not be bypassed! */ - if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF) - != 0x0001) { - return HPI6205_ERROR_C6713_PLL; - } - /* setup C67x EMIF (note this is the only use of - BAR1 via BootLoader_WriteMem32) */ - boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL, - 0x000034A8); - - /* EMIF CE0 setup - 2Mx32 Sync DRAM - 31..28 Wr setup - 27..22 Wr strobe - 21..20 Wr hold - 19..16 Rd setup - 15..14 - - 13..8 Rd strobe - 7..4 MTYPE 0011 Sync DRAM 32bits - 3 Wr hold MSB - 2..0 Rd hold - */ - boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0, - 0x00000030); - - /* EMIF SDRAM Extension - 0x00 - 31-21 0000b 0000b 000b - 20 WR2RD = 2cycles-1 = 1b - - 19-18 WR2DEAC = 3cycle-1 = 10b - 17 WR2WR = 2cycle-1 = 1b - 16-15 R2WDQM = 4cycle-1 = 11b - 14-12 RD2WR = 6cycles-1 = 101b - - 11-10 RD2DEAC = 4cycle-1 = 11b - 9 RD2RD = 2cycle-1 = 1b - 8-7 THZP = 3cycle-1 = 10b - 6-5 TWR = 2cycle-1 = 01b (tWR = 17ns) - 4 TRRD = 2cycle = 0b (tRRD = 14ns) - 3-1 TRAS = 5cycle-1 = 100b (Tras=42ns) - 1 CAS latency = 3cyc = 1b - (for Micron 2M32-7 operating at 100MHz) - */ - boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT, - 0x001BDF29); - - /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank) - 31 - 0b - - 30 SDBSZ 1b 4 bank - 29..28 SDRSZ 00b 11 row address pins - - 27..26 SDCSZ 01b 8 column address pins - 25 RFEN 1b refersh enabled - 24 INIT 1b init SDRAM! - - 23..20 TRCD 0001b (Trcd/Tcyc)-1 = (20/10)-1 = 1 - - 19..16 TRP 0001b (Trp/Tcyc)-1 = (20/10)-1 = 1 - - 15..12 TRC 0110b (Trc/Tcyc)-1 = (70/10)-1 = 6 - - 11..0 - 0000b 0000b 0000b - */ - boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL, - 0x47116000); - - /* SDRAM refresh timing - Need 4,096 refresh cycles every 64ms = 15.625us = 1562cycles of 100MHz = 0x61A - */ - boot_loader_write_mem32(pao, dsp_index, - C6713_EMIF_SDRAMTIMING, 0x00000410); - - hpios_delay_micro_seconds(1000); - } else if (dsp_index == 2) { - /* DSP 2 is a C6713 */ - } - - return 0; -} - -static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index, - u32 start_address, u32 length) -{ - u32 i = 0, j = 0; - u32 test_addr = 0; - u32 test_data = 0, data = 0; - - length = 1000; - - /* for 1st word, test each bit in the 32bit word, */ - /* dwLength specifies number of 32bit words to test */ - /*for(i=0; ipci.pci_dev->subsystem_device == 0x5000) { - /* DSP 0 is always C6205 */ - dRAM_start_address = 0x00400000; - dRAM_size = 0x200000; - /*dwDRAMinc=1024; */ - } else - return 0; - } else if (dsp_index == 1) { - /* DSP 1 is a C6713 */ - dRAM_start_address = 0x80000000; - dRAM_size = 0x200000; - /*dwDRAMinc=1024; */ - } - - if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address, - dRAM_size)) - return HPI6205_ERROR_DSP_EXTMEM; - return 0; -} - -static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index) -{ - u32 data = 0; - if (dsp_index == 0) { - /* only test for DSP0 PLD on ASI5000 card */ - if (pao->pci.pci_dev->subsystem_device == 0x5000) { - /* PLD is located at CE3=0x03000000 */ - data = boot_loader_read_mem32(pao, dsp_index, - 0x03000008); - if ((data & 0xF) != 0x5) - return HPI6205_ERROR_DSP_PLD; - data = boot_loader_read_mem32(pao, dsp_index, - 0x0300000C); - if ((data & 0xF) != 0xA) - return HPI6205_ERROR_DSP_PLD; - } - } else if (dsp_index == 1) { - /* DSP 1 is a C6713 */ - if (pao->pci.pci_dev->subsystem_device == 0x8700) { - /* PLD is located at CE1=0x90000000 */ - data = boot_loader_read_mem32(pao, dsp_index, - 0x90000010); - if ((data & 0xFF) != 0xAA) - return HPI6205_ERROR_DSP_PLD; - /* 8713 - LED on */ - boot_loader_write_mem32(pao, dsp_index, 0x90000000, - 0x02); - } - } - return 0; -} - -/** Transfer data to or from DSP - nOperation = H620_H620_HIF_SEND_DATA or H620_HIF_GET_DATA -*/ -static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data, - u32 data_size, int operation) -{ - struct hpi_hw_obj *phw = pao->priv; - u32 data_transferred = 0; - u16 err = 0; - u32 temp2; - struct bus_master_interface *interface = phw->p_interface_buffer; - - if (!p_data) - return HPI_ERROR_INVALID_DATA_POINTER; - - data_size &= ~3L; /* round data_size down to nearest 4 bytes */ - - /* make sure state is IDLE */ - if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) - return HPI_ERROR_DSP_HARDWARE; - - while (data_transferred < data_size) { - u32 this_copy = data_size - data_transferred; - - if (this_copy > HPI6205_SIZEOF_DATA) - this_copy = HPI6205_SIZEOF_DATA; - - if (operation == H620_HIF_SEND_DATA) - memcpy((void *)&interface->u.b_data[0], - &p_data[data_transferred], this_copy); - - interface->transfer_size_in_bytes = this_copy; - - /* DSP must change this back to nOperation */ - interface->dsp_ack = H620_HIF_IDLE; - send_dsp_command(phw, operation); - - temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT); - HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n", - HPI6205_TIMEOUT - temp2, this_copy); - - if (!temp2) { - /* timed out */ - HPI_DEBUG_LOG(ERROR, - "Timed out waiting for " "state %d got %d\n", - operation, interface->dsp_ack); - - break; - } - if (operation == H620_HIF_GET_DATA) - memcpy(&p_data[data_transferred], - (void *)&interface->u.b_data[0], this_copy); - - data_transferred += this_copy; - } - if (interface->dsp_ack != operation) - HPI_DEBUG_LOG(DEBUG, "interface->dsp_ack=%d, expected %d\n", - interface->dsp_ack, operation); - /* err=HPI_ERROR_DSP_HARDWARE; */ - - send_dsp_command(phw, H620_HIF_IDLE); - - return err; -} - -/* wait for up to timeout_us microseconds for the DSP - to signal state by DMA into dwDspAck -*/ -static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us) -{ - struct bus_master_interface *interface = phw->p_interface_buffer; - int t = timeout_us / 4; - - rmb(); /* ensure interface->dsp_ack is up to date */ - while ((interface->dsp_ack != state) && --t) { - hpios_delay_micro_seconds(4); - rmb(); /* DSP changes dsp_ack by DMA */ - } - - /*HPI_DEBUG_LOG(VERBOSE, "Spun %d for %d\n", timeout_us/4-t, state); */ - return t * 4; -} - -/* set the busmaster interface to cmd, then interrupt the DSP */ -static void send_dsp_command(struct hpi_hw_obj *phw, int cmd) -{ - struct bus_master_interface *interface = phw->p_interface_buffer; - u32 r; - - interface->host_cmd = cmd; - wmb(); /* DSP gets state by DMA, make sure it is written to memory */ - /* before we interrupt the DSP */ - r = ioread32(phw->prHDCR); - r |= (u32)C6205_HDCR_DSPINT; - iowrite32(r, phw->prHDCR); - r &= ~(u32)C6205_HDCR_DSPINT; - iowrite32(r, phw->prHDCR); -} - -static unsigned int message_count; - -static u16 message_response_sequence(struct hpi_adapter_obj *pao, - struct hpi_message *phm, struct hpi_response *phr) -{ - u32 time_out, time_out2; - struct hpi_hw_obj *phw = pao->priv; - struct bus_master_interface *interface = phw->p_interface_buffer; - u16 err = 0; - - message_count++; - if (phm->size > sizeof(interface->u.message_buffer)) { - phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL; - phr->specific_error = sizeof(interface->u.message_buffer); - phr->size = sizeof(struct hpi_response_header); - HPI_DEBUG_LOG(ERROR, - "message len %d too big for buffer %zd \n", phm->size, - sizeof(interface->u.message_buffer)); - return 0; - } - - /* Assume buffer of type struct bus_master_interface - is allocated "noncacheable" */ - - if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) { - HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n"); - return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT; - } - - memcpy(&interface->u.message_buffer, phm, phm->size); - /* signal we want a response */ - send_dsp_command(phw, H620_HIF_GET_RESP); - - time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT); - - if (!time_out2) { - HPI_DEBUG_LOG(ERROR, - "(%u) Timed out waiting for " "GET_RESP state [%x]\n", - message_count, interface->dsp_ack); - } else { - HPI_DEBUG_LOG(VERBOSE, - "(%u) transition to GET_RESP after %u\n", - message_count, HPI6205_TIMEOUT - time_out2); - } - /* spin waiting on HIF interrupt flag (end of msg process) */ - time_out = HPI6205_TIMEOUT; - - /* read the result */ - if (time_out) { - if (interface->u.response_buffer.response.size <= phr->size) - memcpy(phr, &interface->u.response_buffer, - interface->u.response_buffer.response.size); - else { - HPI_DEBUG_LOG(ERROR, - "response len %d too big for buffer %d\n", - interface->u.response_buffer.response.size, - phr->size); - memcpy(phr, &interface->u.response_buffer, - sizeof(struct hpi_response_header)); - phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; - phr->specific_error = - interface->u.response_buffer.response.size; - phr->size = sizeof(struct hpi_response_header); - } - } - /* set interface back to idle */ - send_dsp_command(phw, H620_HIF_IDLE); - - if (!time_out || !time_out2) { - HPI_DEBUG_LOG(DEBUG, "something timed out!\n"); - return HPI6205_ERROR_MSG_RESP_TIMEOUT; - } - /* special case for adapter close - */ - /* wait for the DSP to indicate it is idle */ - if (phm->function == HPI_ADAPTER_CLOSE) { - if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) { - HPI_DEBUG_LOG(DEBUG, - "Timeout waiting for idle " - "(on adapter_close)\n"); - return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT; - } - } - err = hpi_validate_response(phm, phr); - return err; -} - -static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, - struct hpi_response *phr) -{ - - u16 err = 0; - - hpios_dsplock_lock(pao); - - err = message_response_sequence(pao, phm, phr); - - /* maybe an error response */ - if (err) { - /* something failed in the HPI/DSP interface */ - if (err >= HPI_ERROR_BACKEND_BASE) { - phr->error = HPI_ERROR_DSP_COMMUNICATION; - phr->specific_error = err; - } else { - phr->error = err; - } - - pao->dsp_crashed++; - - /* just the header of the response is valid */ - phr->size = sizeof(struct hpi_response_header); - goto err; - } else - pao->dsp_crashed = 0; - - if (phr->error != 0) /* something failed in the DSP */ - goto err; - - switch (phm->function) { - case HPI_OSTREAM_WRITE: - case HPI_ISTREAM_ANC_WRITE: - err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data, - phm->u.d.u.data.data_size, H620_HIF_SEND_DATA); - break; - - case HPI_ISTREAM_READ: - case HPI_OSTREAM_ANC_READ: - err = hpi6205_transfer_data(pao, phm->u.d.u.data.pb_data, - phm->u.d.u.data.data_size, H620_HIF_GET_DATA); - break; - - } - phr->error = err; - -err: - hpios_dsplock_unlock(pao); - - return; -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpi6205.h b/ANDROID_3.4.5/sound/pci/asihpi/hpi6205.h deleted file mode 100644 index ec0827b6..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpi6205.h +++ /dev/null @@ -1,103 +0,0 @@ -/***************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -Host Interface module for an ASI6205 based -bus mastering PCI adapter. - -Copyright AudioScience, Inc., 2003 -******************************************************************************/ - -#ifndef _HPI6205_H_ -#define _HPI6205_H_ - -#include "hpi_internal.h" - -/*********************************************************** - Defines used for basic messaging -************************************************************/ -#define H620_HIF_RESET 0 -#define H620_HIF_IDLE 1 -#define H620_HIF_GET_RESP 2 -#define H620_HIF_DATA_DONE 3 -#define H620_HIF_DATA_MASK 0x10 -#define H620_HIF_SEND_DATA 0x14 -#define H620_HIF_GET_DATA 0x15 -#define H620_HIF_UNKNOWN 0x0000ffff - -/*********************************************************** - Types used for mixer control caching -************************************************************/ - -#define H620_MAX_ISTREAMS 32 -#define H620_MAX_OSTREAMS 32 -#define HPI_NMIXER_CONTROLS 2048 - -/********************************************************************* -This is used for dynamic control cache allocation -**********************************************************************/ -struct controlcache_6205 { - u32 number_of_controls; - u32 physical_address32; - u32 size_in_bytes; -}; - -/********************************************************************* -This is used for dynamic allocation of async event array -**********************************************************************/ -struct async_event_buffer_6205 { - u32 physical_address32; - u32 spare; - struct hpi_fifo_buffer b; -}; - -/*********************************************************** -The Host located memory buffer that the 6205 will bus master -in and out of. -************************************************************/ -#define HPI6205_SIZEOF_DATA (16*1024) - -struct message_buffer_6205 { - struct hpi_message message; - char data[256]; -}; - -struct response_buffer_6205 { - struct hpi_response response; - char data[256]; -}; - -union buffer_6205 { - struct message_buffer_6205 message_buffer; - struct response_buffer_6205 response_buffer; - u8 b_data[HPI6205_SIZEOF_DATA]; -}; - -struct bus_master_interface { - u32 host_cmd; - u32 dsp_ack; - u32 transfer_size_in_bytes; - union buffer_6205 u; - struct controlcache_6205 control_cache; - struct async_event_buffer_6205 async_buffer; - struct hpi_hostbuffer_status - instream_host_buffer_status[H620_MAX_ISTREAMS]; - struct hpi_hostbuffer_status - outstream_host_buffer_status[H620_MAX_OSTREAMS]; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpi_internal.h b/ANDROID_3.4.5/sound/pci/asihpi/hpi_internal.h deleted file mode 100644 index bc86cb72..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpi_internal.h +++ /dev/null @@ -1,1431 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2012 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -HPI internal definitions - -(C) Copyright AudioScience Inc. 1996-2009 -******************************************************************************/ - -#ifndef _HPI_INTERNAL_H_ -#define _HPI_INTERNAL_H_ - -#include "hpi.h" - -/** maximum number of memory regions mapped to an adapter */ -#define HPI_MAX_ADAPTER_MEM_SPACES (2) - -/* Each OS needs its own hpios.h */ -#include "hpios.h" - -/* physical memory allocation */ - -/** Allocate and map an area of locked memory for bus master DMA operations. - -On success, *pLockedMemeHandle is a valid handle, and 0 is returned -On error *pLockedMemHandle marked invalid, non-zero returned. - -If this function succeeds, then HpiOs_LockedMem_GetVirtAddr() and -HpiOs_LockedMem_GetPyhsAddr() will always succed on the returned handle. -*/ -u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle, - /**< memory handle */ - u32 size, /**< Size in bytes to allocate */ - struct pci_dev *p_os_reference - /**< OS specific data required for memory allocation */ - ); - -/** Free mapping and memory represented by LockedMemHandle - -Frees any resources, then invalidates the handle. -Returns 0 on success, 1 if handle is invalid. - -*/ -u16 hpios_locked_mem_free(struct consistent_dma_area *locked_mem_handle); - -/** Get the physical PCI address of memory represented by LockedMemHandle. - -If handle is invalid *pPhysicalAddr is set to zero and return 1 -*/ -u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area - *locked_mem_handle, u32 *p_physical_addr); - -/** Get the CPU address of of memory represented by LockedMemHandle. - -If handle is NULL *ppvVirtualAddr is set to NULL and return 1 -*/ -u16 hpios_locked_mem_get_virt_addr(struct consistent_dma_area - *locked_mem_handle, void **ppv_virtual_addr); - -/** Check that handle is valid -i.e it represents a valid memory area -*/ -u16 hpios_locked_mem_valid(struct consistent_dma_area *locked_mem_handle); - -/* timing/delay */ -void hpios_delay_micro_seconds(u32 num_micro_sec); - -struct hpi_message; -struct hpi_response; - -typedef void hpi_handler_func(struct hpi_message *, struct hpi_response *); - -/* If the assert fails, compiler complains - something like size of array `msg' is negative. - Unlike linux BUILD_BUG_ON, this works outside function scope. -*/ -#define compile_time_assert(cond, msg) \ - typedef char ASSERT_##msg[(cond) ? 1 : -1] - -/******************************************* bus types */ -enum HPI_BUSES { - HPI_BUS_ISAPNP = 1, - HPI_BUS_PCI = 2, - HPI_BUS_USB = 3, - HPI_BUS_NET = 4 -}; - -enum HPI_SUBSYS_OPTIONS { - /* 0, 256 are invalid, 1..255 reserved for global options */ - HPI_SUBSYS_OPT_NET_ENABLE = 257, - HPI_SUBSYS_OPT_NET_BROADCAST = 258, - HPI_SUBSYS_OPT_NET_UNICAST = 259, - HPI_SUBSYS_OPT_NET_ADDR = 260, - HPI_SUBSYS_OPT_NET_MASK = 261, - HPI_SUBSYS_OPT_NET_ADAPTER_ADDRESS_ADD = 262 -}; - -/** Volume flags -*/ -enum HPI_VOLUME_FLAGS { - /** Set if the volume control is muted */ - HPI_VOLUME_FLAG_MUTED = (1 << 0), - /** Set if the volume control has a mute function */ - HPI_VOLUME_FLAG_HAS_MUTE = (1 << 1), - /** Set if volume control can do autofading */ - HPI_VOLUME_FLAG_HAS_AUTOFADE = (1 << 2) - /* Note Flags >= (1<<8) are for DSP internal use only */ -}; - -/******************************************* CONTROL ATTRIBUTES ****/ -/* (in order of control type ID */ - -/* This allows for 255 control types, 256 unique attributes each */ -#define HPI_CTL_ATTR(ctl, ai) ((HPI_CONTROL_##ctl << 8) + ai) - -/* Get the sub-index of the attribute for a control type */ -#define HPI_CTL_ATTR_INDEX(i) (i & 0xff) - -/* Extract the control from the control attribute */ -#define HPI_CTL_ATTR_CONTROL(i) (i >> 8) - -/** Enable event generation for a control. -0=disable, 1=enable -\note generic to all controls that can generate events -*/ - -/** Unique identifiers for every control attribute -*/ -enum HPI_CONTROL_ATTRIBUTES { - HPI_GENERIC_ENABLE = HPI_CTL_ATTR(GENERIC, 1), - HPI_GENERIC_EVENT_ENABLE = HPI_CTL_ATTR(GENERIC, 2), - - HPI_VOLUME_GAIN = HPI_CTL_ATTR(VOLUME, 1), - HPI_VOLUME_AUTOFADE = HPI_CTL_ATTR(VOLUME, 2), - HPI_VOLUME_MUTE = HPI_CTL_ATTR(VOLUME, 3), - HPI_VOLUME_GAIN_AND_FLAGS = HPI_CTL_ATTR(VOLUME, 4), - HPI_VOLUME_NUM_CHANNELS = HPI_CTL_ATTR(VOLUME, 6), - HPI_VOLUME_RANGE = HPI_CTL_ATTR(VOLUME, 10), - - HPI_METER_RMS = HPI_CTL_ATTR(METER, 1), - HPI_METER_PEAK = HPI_CTL_ATTR(METER, 2), - HPI_METER_RMS_BALLISTICS = HPI_CTL_ATTR(METER, 3), - HPI_METER_PEAK_BALLISTICS = HPI_CTL_ATTR(METER, 4), - HPI_METER_NUM_CHANNELS = HPI_CTL_ATTR(METER, 5), - - HPI_MULTIPLEXER_SOURCE = HPI_CTL_ATTR(MULTIPLEXER, 1), - HPI_MULTIPLEXER_QUERYSOURCE = HPI_CTL_ATTR(MULTIPLEXER, 2), - - HPI_AESEBUTX_FORMAT = HPI_CTL_ATTR(AESEBUTX, 1), - HPI_AESEBUTX_SAMPLERATE = HPI_CTL_ATTR(AESEBUTX, 3), - HPI_AESEBUTX_CHANNELSTATUS = HPI_CTL_ATTR(AESEBUTX, 4), - HPI_AESEBUTX_USERDATA = HPI_CTL_ATTR(AESEBUTX, 5), - - HPI_AESEBURX_FORMAT = HPI_CTL_ATTR(AESEBURX, 1), - HPI_AESEBURX_ERRORSTATUS = HPI_CTL_ATTR(AESEBURX, 2), - HPI_AESEBURX_SAMPLERATE = HPI_CTL_ATTR(AESEBURX, 3), - HPI_AESEBURX_CHANNELSTATUS = HPI_CTL_ATTR(AESEBURX, 4), - HPI_AESEBURX_USERDATA = HPI_CTL_ATTR(AESEBURX, 5), - - HPI_LEVEL_GAIN = HPI_CTL_ATTR(LEVEL, 1), - HPI_LEVEL_RANGE = HPI_CTL_ATTR(LEVEL, 10), - - HPI_TUNER_BAND = HPI_CTL_ATTR(TUNER, 1), - HPI_TUNER_FREQ = HPI_CTL_ATTR(TUNER, 2), - HPI_TUNER_LEVEL_AVG = HPI_CTL_ATTR(TUNER, 3), - HPI_TUNER_LEVEL_RAW = HPI_CTL_ATTR(TUNER, 4), - HPI_TUNER_SNR = HPI_CTL_ATTR(TUNER, 5), - HPI_TUNER_GAIN = HPI_CTL_ATTR(TUNER, 6), - HPI_TUNER_STATUS = HPI_CTL_ATTR(TUNER, 7), - HPI_TUNER_MODE = HPI_CTL_ATTR(TUNER, 8), - HPI_TUNER_RDS = HPI_CTL_ATTR(TUNER, 9), - HPI_TUNER_DEEMPHASIS = HPI_CTL_ATTR(TUNER, 10), - HPI_TUNER_PROGRAM = HPI_CTL_ATTR(TUNER, 11), - HPI_TUNER_HDRADIO_SIGNAL_QUALITY = HPI_CTL_ATTR(TUNER, 12), - HPI_TUNER_HDRADIO_SDK_VERSION = HPI_CTL_ATTR(TUNER, 13), - HPI_TUNER_HDRADIO_DSP_VERSION = HPI_CTL_ATTR(TUNER, 14), - HPI_TUNER_HDRADIO_BLEND = HPI_CTL_ATTR(TUNER, 15), - - HPI_VOX_THRESHOLD = HPI_CTL_ATTR(VOX, 1), - - HPI_CHANNEL_MODE_MODE = HPI_CTL_ATTR(CHANNEL_MODE, 1), - - HPI_BITSTREAM_DATA_POLARITY = HPI_CTL_ATTR(BITSTREAM, 1), - HPI_BITSTREAM_CLOCK_EDGE = HPI_CTL_ATTR(BITSTREAM, 2), - HPI_BITSTREAM_CLOCK_SOURCE = HPI_CTL_ATTR(BITSTREAM, 3), - HPI_BITSTREAM_ACTIVITY = HPI_CTL_ATTR(BITSTREAM, 4), - - HPI_SAMPLECLOCK_SOURCE = HPI_CTL_ATTR(SAMPLECLOCK, 1), - HPI_SAMPLECLOCK_SAMPLERATE = HPI_CTL_ATTR(SAMPLECLOCK, 2), - HPI_SAMPLECLOCK_SOURCE_INDEX = HPI_CTL_ATTR(SAMPLECLOCK, 3), - HPI_SAMPLECLOCK_LOCAL_SAMPLERATE = HPI_CTL_ATTR(SAMPLECLOCK, 4), - HPI_SAMPLECLOCK_AUTO = HPI_CTL_ATTR(SAMPLECLOCK, 5), - HPI_SAMPLECLOCK_LOCAL_LOCK = HPI_CTL_ATTR(SAMPLECLOCK, 6), - - HPI_MICROPHONE_PHANTOM_POWER = HPI_CTL_ATTR(MICROPHONE, 1), - - HPI_EQUALIZER_NUM_FILTERS = HPI_CTL_ATTR(EQUALIZER, 1), - HPI_EQUALIZER_FILTER = HPI_CTL_ATTR(EQUALIZER, 2), - HPI_EQUALIZER_COEFFICIENTS = HPI_CTL_ATTR(EQUALIZER, 3), - - HPI_COMPANDER_PARAMS = HPI_CTL_ATTR(COMPANDER, 1), - HPI_COMPANDER_MAKEUPGAIN = HPI_CTL_ATTR(COMPANDER, 2), - HPI_COMPANDER_THRESHOLD = HPI_CTL_ATTR(COMPANDER, 3), - HPI_COMPANDER_RATIO = HPI_CTL_ATTR(COMPANDER, 4), - HPI_COMPANDER_ATTACK = HPI_CTL_ATTR(COMPANDER, 5), - HPI_COMPANDER_DECAY = HPI_CTL_ATTR(COMPANDER, 6), - - HPI_COBRANET_SET = HPI_CTL_ATTR(COBRANET, 1), - HPI_COBRANET_GET = HPI_CTL_ATTR(COBRANET, 2), - HPI_COBRANET_GET_STATUS = HPI_CTL_ATTR(COBRANET, 5), - HPI_COBRANET_SEND_PACKET = HPI_CTL_ATTR(COBRANET, 6), - HPI_COBRANET_GET_PACKET = HPI_CTL_ATTR(COBRANET, 7), - - HPI_TONEDETECTOR_THRESHOLD = HPI_CTL_ATTR(TONEDETECTOR, 1), - HPI_TONEDETECTOR_STATE = HPI_CTL_ATTR(TONEDETECTOR, 2), - HPI_TONEDETECTOR_FREQUENCY = HPI_CTL_ATTR(TONEDETECTOR, 3), - - HPI_SILENCEDETECTOR_THRESHOLD = HPI_CTL_ATTR(SILENCEDETECTOR, 1), - HPI_SILENCEDETECTOR_STATE = HPI_CTL_ATTR(SILENCEDETECTOR, 2), - HPI_SILENCEDETECTOR_DELAY = HPI_CTL_ATTR(SILENCEDETECTOR, 3), - - HPI_PAD_CHANNEL_NAME = HPI_CTL_ATTR(PAD, 1), - HPI_PAD_ARTIST = HPI_CTL_ATTR(PAD, 2), - HPI_PAD_TITLE = HPI_CTL_ATTR(PAD, 3), - HPI_PAD_COMMENT = HPI_CTL_ATTR(PAD, 4), - HPI_PAD_PROGRAM_TYPE = HPI_CTL_ATTR(PAD, 5), - HPI_PAD_PROGRAM_ID = HPI_CTL_ATTR(PAD, 6), - HPI_PAD_TA_SUPPORT = HPI_CTL_ATTR(PAD, 7), - HPI_PAD_TA_ACTIVE = HPI_CTL_ATTR(PAD, 8), - - HPI_UNIVERSAL_ENTITY = HPI_CTL_ATTR(UNIVERSAL, 1) -}; - -#define HPI_POLARITY_POSITIVE 0 -#define HPI_POLARITY_NEGATIVE 1 - -/*------------------------------------------------------------ - Cobranet Chip Bridge - copied from HMI.H -------------------------------------------------------------*/ -#define HPI_COBRANET_HMI_cobra_bridge 0x20000 -#define HPI_COBRANET_HMI_cobra_bridge_tx_pkt_buf \ - (HPI_COBRANET_HMI_cobra_bridge + 0x1000) -#define HPI_COBRANET_HMI_cobra_bridge_rx_pkt_buf \ - (HPI_COBRANET_HMI_cobra_bridge + 0x2000) -#define HPI_COBRANET_HMI_cobra_if_table1 0x110000 -#define HPI_COBRANET_HMI_cobra_if_phy_address \ - (HPI_COBRANET_HMI_cobra_if_table1 + 0xd) -#define HPI_COBRANET_HMI_cobra_protocolIP 0x72000 -#define HPI_COBRANET_HMI_cobra_ip_mon_currentIP \ - (HPI_COBRANET_HMI_cobra_protocolIP + 0x0) -#define HPI_COBRANET_HMI_cobra_ip_mon_staticIP \ - (HPI_COBRANET_HMI_cobra_protocolIP + 0x2) -#define HPI_COBRANET_HMI_cobra_sys 0x100000 -#define HPI_COBRANET_HMI_cobra_sys_desc \ - (HPI_COBRANET_HMI_cobra_sys + 0x0) -#define HPI_COBRANET_HMI_cobra_sys_objectID \ - (HPI_COBRANET_HMI_cobra_sys + 0x100) -#define HPI_COBRANET_HMI_cobra_sys_contact \ - (HPI_COBRANET_HMI_cobra_sys + 0x200) -#define HPI_COBRANET_HMI_cobra_sys_name \ - (HPI_COBRANET_HMI_cobra_sys + 0x300) -#define HPI_COBRANET_HMI_cobra_sys_location \ - (HPI_COBRANET_HMI_cobra_sys + 0x400) - -/*------------------------------------------------------------ - Cobranet Chip Status bits -------------------------------------------------------------*/ -#define HPI_COBRANET_HMI_STATUS_RXPACKET 2 -#define HPI_COBRANET_HMI_STATUS_TXPACKET 3 - -/*------------------------------------------------------------ - Ethernet header size -------------------------------------------------------------*/ -#define HPI_ETHERNET_HEADER_SIZE (16) - -/* These defines are used to fill in protocol information for an Ethernet packet - sent using HMI on CS18102 */ -/** ID supplied by Cirrus for ASI packets. */ -#define HPI_ETHERNET_PACKET_ID 0x85 -/** Simple packet - no special routing required */ -#define HPI_ETHERNET_PACKET_V1 0x01 -/** This packet must make its way to the host across the HPI interface */ -#define HPI_ETHERNET_PACKET_HOSTED_VIA_HMI 0x20 -/** This packet must make its way to the host across the HPI interface */ -#define HPI_ETHERNET_PACKET_HOSTED_VIA_HMI_V1 0x21 -/** This packet must make its way to the host across the HPI interface */ -#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI 0x40 -/** This packet must make its way to the host across the HPI interface */ -#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41 - -#define HPI_ETHERNET_UDP_PORT 44600 /**< HPI UDP service */ - -/** Default network timeout in milli-seconds. */ -#define HPI_ETHERNET_TIMEOUT_MS 500 - -/** Locked memory buffer alloc/free phases */ -enum HPI_BUFFER_CMDS { - /** use one message to allocate or free physical memory */ - HPI_BUFFER_CMD_EXTERNAL = 0, - /** alloc physical memory */ - HPI_BUFFER_CMD_INTERNAL_ALLOC = 1, - /** send physical memory address to adapter */ - HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER = 2, - /** notify adapter to stop using physical buffer */ - HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER = 3, - /** free physical buffer */ - HPI_BUFFER_CMD_INTERNAL_FREE = 4 -}; - -/*****************************************************************************/ -/*****************************************************************************/ -/******** HPI LOW LEVEL MESSAGES *******/ -/*****************************************************************************/ -/*****************************************************************************/ -/** Pnp ids */ -/** "ASI" - actual is "ASX" - need to change */ -#define HPI_ID_ISAPNP_AUDIOSCIENCE 0x0669 -/** PCI vendor ID that AudioScience uses */ -#define HPI_PCI_VENDOR_ID_AUDIOSCIENCE 0x175C -/** PCI vendor ID that the DSP56301 has */ -#define HPI_PCI_VENDOR_ID_MOTOROLA 0x1057 -/** PCI vendor ID that TI uses */ -#define HPI_PCI_VENDOR_ID_TI 0x104C - -#define HPI_PCI_DEV_ID_PCI2040 0xAC60 -/** TI's C6205 PCI interface has this ID */ -#define HPI_PCI_DEV_ID_DSP6205 0xA106 - -#define HPI_USB_VENDOR_ID_AUDIOSCIENCE 0x1257 -#define HPI_USB_W2K_TAG 0x57495341 /* "ASIW" */ -#define HPI_USB_LINUX_TAG 0x4C495341 /* "ASIL" */ - -/** Invalid Adapter index -Used in HPI messages that are not addressed to a specific adapter -Used in DLL to indicate device not present -*/ -#define HPI_ADAPTER_INDEX_INVALID 0xFFFF - -/** First 2 hex digits define the adapter family */ -#define HPI_ADAPTER_FAMILY_MASK 0xff00 -#define HPI_MODULE_FAMILY_MASK 0xfff0 - -#define HPI_ADAPTER_FAMILY_ASI(f) (f & HPI_ADAPTER_FAMILY_MASK) -#define HPI_MODULE_FAMILY_ASI(f) (f & HPI_MODULE_FAMILY_MASK) -#define HPI_ADAPTER_ASI(f) (f) - -enum HPI_MESSAGE_TYPES { - HPI_TYPE_REQUEST = 1, - HPI_TYPE_RESPONSE = 2, - HPI_TYPE_DATA = 3, - HPI_TYPE_SSX2BYPASS_MESSAGE = 4, - HPI_TYPE_COMMAND = 5, - HPI_TYPE_NOTIFICATION = 6 -}; - -enum HPI_OBJECT_TYPES { - HPI_OBJ_SUBSYSTEM = 1, - HPI_OBJ_ADAPTER = 2, - HPI_OBJ_OSTREAM = 3, - HPI_OBJ_ISTREAM = 4, - HPI_OBJ_MIXER = 5, - HPI_OBJ_NODE = 6, - HPI_OBJ_CONTROL = 7, - HPI_OBJ_NVMEMORY = 8, - HPI_OBJ_GPIO = 9, - HPI_OBJ_WATCHDOG = 10, - HPI_OBJ_CLOCK = 11, - HPI_OBJ_PROFILE = 12, - /* HPI_ OBJ_ CONTROLEX = 13, */ - HPI_OBJ_ASYNCEVENT = 14 -#define HPI_OBJ_MAXINDEX 14 -}; - -#define HPI_OBJ_FUNCTION_SPACING 0x100 -#define HPI_FUNC_ID(obj, i) (HPI_OBJ_##obj * HPI_OBJ_FUNCTION_SPACING + i) - -#define HPI_EXTRACT_INDEX(fn) (fn & 0xff) - -enum HPI_FUNCTION_IDS { - HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1), - HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2), - HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3), - HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5), - HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6), - HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8), - HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9), - HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12), - HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13), - HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14), - HPI_SUBSYS_OPTION_INFO = HPI_FUNC_ID(SUBSYSTEM, 15), - HPI_SUBSYS_OPTION_GET = HPI_FUNC_ID(SUBSYSTEM, 16), - HPI_SUBSYS_OPTION_SET = HPI_FUNC_ID(SUBSYSTEM, 17), -#define HPI_SUBSYS_FUNCTION_COUNT 17 - - HPI_ADAPTER_OPEN = HPI_FUNC_ID(ADAPTER, 1), - HPI_ADAPTER_CLOSE = HPI_FUNC_ID(ADAPTER, 2), - HPI_ADAPTER_GET_INFO = HPI_FUNC_ID(ADAPTER, 3), - HPI_ADAPTER_GET_ASSERT = HPI_FUNC_ID(ADAPTER, 4), - HPI_ADAPTER_TEST_ASSERT = HPI_FUNC_ID(ADAPTER, 5), - HPI_ADAPTER_SET_MODE = HPI_FUNC_ID(ADAPTER, 6), - HPI_ADAPTER_GET_MODE = HPI_FUNC_ID(ADAPTER, 7), - HPI_ADAPTER_ENABLE_CAPABILITY = HPI_FUNC_ID(ADAPTER, 8), - HPI_ADAPTER_SELFTEST = HPI_FUNC_ID(ADAPTER, 9), - HPI_ADAPTER_FIND_OBJECT = HPI_FUNC_ID(ADAPTER, 10), - HPI_ADAPTER_QUERY_FLASH = HPI_FUNC_ID(ADAPTER, 11), - HPI_ADAPTER_START_FLASH = HPI_FUNC_ID(ADAPTER, 12), - HPI_ADAPTER_PROGRAM_FLASH = HPI_FUNC_ID(ADAPTER, 13), - HPI_ADAPTER_SET_PROPERTY = HPI_FUNC_ID(ADAPTER, 14), - HPI_ADAPTER_GET_PROPERTY = HPI_FUNC_ID(ADAPTER, 15), - HPI_ADAPTER_ENUM_PROPERTY = HPI_FUNC_ID(ADAPTER, 16), - HPI_ADAPTER_MODULE_INFO = HPI_FUNC_ID(ADAPTER, 17), - HPI_ADAPTER_DEBUG_READ = HPI_FUNC_ID(ADAPTER, 18), - HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19), - HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20), - HPI_ADAPTER_DELETE = HPI_FUNC_ID(ADAPTER, 21), - HPI_ADAPTER_READ_FLASH = HPI_FUNC_ID(ADAPTER, 22), - HPI_ADAPTER_END_FLASH = HPI_FUNC_ID(ADAPTER, 23), - HPI_ADAPTER_FILESTORE_DELETE_ALL = HPI_FUNC_ID(ADAPTER, 24), -#define HPI_ADAPTER_FUNCTION_COUNT 24 - - HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1), - HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2), - HPI_OSTREAM_WRITE = HPI_FUNC_ID(OSTREAM, 3), - HPI_OSTREAM_START = HPI_FUNC_ID(OSTREAM, 4), - HPI_OSTREAM_STOP = HPI_FUNC_ID(OSTREAM, 5), - HPI_OSTREAM_RESET = HPI_FUNC_ID(OSTREAM, 6), - HPI_OSTREAM_GET_INFO = HPI_FUNC_ID(OSTREAM, 7), - HPI_OSTREAM_QUERY_FORMAT = HPI_FUNC_ID(OSTREAM, 8), - HPI_OSTREAM_DATA = HPI_FUNC_ID(OSTREAM, 9), - HPI_OSTREAM_SET_VELOCITY = HPI_FUNC_ID(OSTREAM, 10), - HPI_OSTREAM_SET_PUNCHINOUT = HPI_FUNC_ID(OSTREAM, 11), - HPI_OSTREAM_SINEGEN = HPI_FUNC_ID(OSTREAM, 12), - HPI_OSTREAM_ANC_RESET = HPI_FUNC_ID(OSTREAM, 13), - HPI_OSTREAM_ANC_GET_INFO = HPI_FUNC_ID(OSTREAM, 14), - HPI_OSTREAM_ANC_READ = HPI_FUNC_ID(OSTREAM, 15), - HPI_OSTREAM_SET_TIMESCALE = HPI_FUNC_ID(OSTREAM, 16), - HPI_OSTREAM_SET_FORMAT = HPI_FUNC_ID(OSTREAM, 17), - HPI_OSTREAM_HOSTBUFFER_ALLOC = HPI_FUNC_ID(OSTREAM, 18), - HPI_OSTREAM_HOSTBUFFER_FREE = HPI_FUNC_ID(OSTREAM, 19), - HPI_OSTREAM_GROUP_ADD = HPI_FUNC_ID(OSTREAM, 20), - HPI_OSTREAM_GROUP_GETMAP = HPI_FUNC_ID(OSTREAM, 21), - HPI_OSTREAM_GROUP_RESET = HPI_FUNC_ID(OSTREAM, 22), - HPI_OSTREAM_HOSTBUFFER_GET_INFO = HPI_FUNC_ID(OSTREAM, 23), - HPI_OSTREAM_WAIT_START = HPI_FUNC_ID(OSTREAM, 24), - HPI_OSTREAM_WAIT = HPI_FUNC_ID(OSTREAM, 25), -#define HPI_OSTREAM_FUNCTION_COUNT 25 - - HPI_ISTREAM_OPEN = HPI_FUNC_ID(ISTREAM, 1), - HPI_ISTREAM_CLOSE = HPI_FUNC_ID(ISTREAM, 2), - HPI_ISTREAM_SET_FORMAT = HPI_FUNC_ID(ISTREAM, 3), - HPI_ISTREAM_READ = HPI_FUNC_ID(ISTREAM, 4), - HPI_ISTREAM_START = HPI_FUNC_ID(ISTREAM, 5), - HPI_ISTREAM_STOP = HPI_FUNC_ID(ISTREAM, 6), - HPI_ISTREAM_RESET = HPI_FUNC_ID(ISTREAM, 7), - HPI_ISTREAM_GET_INFO = HPI_FUNC_ID(ISTREAM, 8), - HPI_ISTREAM_QUERY_FORMAT = HPI_FUNC_ID(ISTREAM, 9), - HPI_ISTREAM_ANC_RESET = HPI_FUNC_ID(ISTREAM, 10), - HPI_ISTREAM_ANC_GET_INFO = HPI_FUNC_ID(ISTREAM, 11), - HPI_ISTREAM_ANC_WRITE = HPI_FUNC_ID(ISTREAM, 12), - HPI_ISTREAM_HOSTBUFFER_ALLOC = HPI_FUNC_ID(ISTREAM, 13), - HPI_ISTREAM_HOSTBUFFER_FREE = HPI_FUNC_ID(ISTREAM, 14), - HPI_ISTREAM_GROUP_ADD = HPI_FUNC_ID(ISTREAM, 15), - HPI_ISTREAM_GROUP_GETMAP = HPI_FUNC_ID(ISTREAM, 16), - HPI_ISTREAM_GROUP_RESET = HPI_FUNC_ID(ISTREAM, 17), - HPI_ISTREAM_HOSTBUFFER_GET_INFO = HPI_FUNC_ID(ISTREAM, 18), - HPI_ISTREAM_WAIT_START = HPI_FUNC_ID(ISTREAM, 19), - HPI_ISTREAM_WAIT = HPI_FUNC_ID(ISTREAM, 20), -#define HPI_ISTREAM_FUNCTION_COUNT 20 - -/* NOTE: - GET_NODE_INFO, SET_CONNECTION, GET_CONNECTIONS are not currently used */ - HPI_MIXER_OPEN = HPI_FUNC_ID(MIXER, 1), - HPI_MIXER_CLOSE = HPI_FUNC_ID(MIXER, 2), - HPI_MIXER_GET_INFO = HPI_FUNC_ID(MIXER, 3), - HPI_MIXER_GET_NODE_INFO = HPI_FUNC_ID(MIXER, 4), - HPI_MIXER_GET_CONTROL = HPI_FUNC_ID(MIXER, 5), - HPI_MIXER_SET_CONNECTION = HPI_FUNC_ID(MIXER, 6), - HPI_MIXER_GET_CONNECTIONS = HPI_FUNC_ID(MIXER, 7), - HPI_MIXER_GET_CONTROL_BY_INDEX = HPI_FUNC_ID(MIXER, 8), - HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX = HPI_FUNC_ID(MIXER, 9), - HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES = HPI_FUNC_ID(MIXER, 10), - HPI_MIXER_STORE = HPI_FUNC_ID(MIXER, 11), - HPI_MIXER_GET_CACHE_INFO = HPI_FUNC_ID(MIXER, 12), - HPI_MIXER_GET_BLOCK_HANDLE = HPI_FUNC_ID(MIXER, 13), - HPI_MIXER_GET_PARAMETER_HANDLE = HPI_FUNC_ID(MIXER, 14), -#define HPI_MIXER_FUNCTION_COUNT 14 - - HPI_CONTROL_GET_INFO = HPI_FUNC_ID(CONTROL, 1), - HPI_CONTROL_GET_STATE = HPI_FUNC_ID(CONTROL, 2), - HPI_CONTROL_SET_STATE = HPI_FUNC_ID(CONTROL, 3), -#define HPI_CONTROL_FUNCTION_COUNT 3 - - HPI_NVMEMORY_OPEN = HPI_FUNC_ID(NVMEMORY, 1), - HPI_NVMEMORY_READ_BYTE = HPI_FUNC_ID(NVMEMORY, 2), - HPI_NVMEMORY_WRITE_BYTE = HPI_FUNC_ID(NVMEMORY, 3), -#define HPI_NVMEMORY_FUNCTION_COUNT 3 - - HPI_GPIO_OPEN = HPI_FUNC_ID(GPIO, 1), - HPI_GPIO_READ_BIT = HPI_FUNC_ID(GPIO, 2), - HPI_GPIO_WRITE_BIT = HPI_FUNC_ID(GPIO, 3), - HPI_GPIO_READ_ALL = HPI_FUNC_ID(GPIO, 4), - HPI_GPIO_WRITE_STATUS = HPI_FUNC_ID(GPIO, 5), -#define HPI_GPIO_FUNCTION_COUNT 5 - - HPI_ASYNCEVENT_OPEN = HPI_FUNC_ID(ASYNCEVENT, 1), - HPI_ASYNCEVENT_CLOSE = HPI_FUNC_ID(ASYNCEVENT, 2), - HPI_ASYNCEVENT_WAIT = HPI_FUNC_ID(ASYNCEVENT, 3), - HPI_ASYNCEVENT_GETCOUNT = HPI_FUNC_ID(ASYNCEVENT, 4), - HPI_ASYNCEVENT_GET = HPI_FUNC_ID(ASYNCEVENT, 5), - HPI_ASYNCEVENT_SENDEVENTS = HPI_FUNC_ID(ASYNCEVENT, 6), -#define HPI_ASYNCEVENT_FUNCTION_COUNT 6 - - HPI_WATCHDOG_OPEN = HPI_FUNC_ID(WATCHDOG, 1), - HPI_WATCHDOG_SET_TIME = HPI_FUNC_ID(WATCHDOG, 2), - HPI_WATCHDOG_PING = HPI_FUNC_ID(WATCHDOG, 3), - - HPI_CLOCK_OPEN = HPI_FUNC_ID(CLOCK, 1), - HPI_CLOCK_SET_TIME = HPI_FUNC_ID(CLOCK, 2), - HPI_CLOCK_GET_TIME = HPI_FUNC_ID(CLOCK, 3), - - HPI_PROFILE_OPEN_ALL = HPI_FUNC_ID(PROFILE, 1), - HPI_PROFILE_START_ALL = HPI_FUNC_ID(PROFILE, 2), - HPI_PROFILE_STOP_ALL = HPI_FUNC_ID(PROFILE, 3), - HPI_PROFILE_GET = HPI_FUNC_ID(PROFILE, 4), - HPI_PROFILE_GET_IDLECOUNT = HPI_FUNC_ID(PROFILE, 5), - HPI_PROFILE_GET_NAME = HPI_FUNC_ID(PROFILE, 6), - HPI_PROFILE_GET_UTILIZATION = HPI_FUNC_ID(PROFILE, 7) -#define HPI_PROFILE_FUNCTION_COUNT 7 -}; - -/* ////////////////////////////////////////////////////////////////////// */ -/* STRUCTURES */ -#ifndef DISABLE_PRAGMA_PACK1 -#pragma pack(push, 1) -#endif - -/** PCI bus resource */ -struct hpi_pci { - u32 __iomem *ap_mem_base[HPI_MAX_ADAPTER_MEM_SPACES]; - struct pci_dev *pci_dev; -}; - -struct hpi_resource { - union { - const struct hpi_pci *pci; - const char *net_if; - } r; -#ifndef HPI64BIT /* keep structure size constant */ - u32 pad_to64; -#endif - u16 bus_type; /* HPI_BUS_PNPISA, _PCI, _USB etc */ - u16 padding; - -}; - -/** Format info used inside struct hpi_message - Not the same as public API struct hpi_format */ -struct hpi_msg_format { - u32 sample_rate; /**< 11025, 32000, 44100 etc. */ - u32 bit_rate; /**< for MPEG */ - u32 attributes; /**< stereo/joint_stereo/mono */ - u16 channels; /**< 1,2..., (or ancillary mode or idle bit */ - u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see \ref HPI_FORMATS. */ -}; - -/** Buffer+format structure. - Must be kept 7 * 32 bits to match public struct hpi_datastruct */ -struct hpi_msg_data { - struct hpi_msg_format format; - u8 *pb_data; -#ifndef HPI64BIT - u32 padding; -#endif - u32 data_size; -}; - -/** struct hpi_datastructure used up to 3.04 driver */ -struct hpi_data_legacy32 { - struct hpi_format format; - u32 pb_data; - u32 data_size; -}; - -#ifdef HPI64BIT -/* Compatibility version of struct hpi_data*/ -struct hpi_data_compat32 { - struct hpi_msg_format format; - u32 pb_data; - u32 padding; - u32 data_size; -}; -#endif - -struct hpi_buffer { - /** placeholder for backward compatibility (see dwBufferSize) */ - struct hpi_msg_format reserved; - u32 command; /**< HPI_BUFFER_CMD_xxx*/ - u32 pci_address; /**< PCI physical address of buffer for DSP DMA */ - u32 buffer_size; /**< must line up with data_size of HPI_DATA*/ -}; - -/*/////////////////////////////////////////////////////////////////////////// */ -/* This is used for background buffer bus mastering stream buffers. */ -struct hpi_hostbuffer_status { - u32 samples_processed; - u32 auxiliary_data_available; - u32 stream_state; - /* DSP index in to the host bus master buffer. */ - u32 dsp_index; - /* Host index in to the host bus master buffer. */ - u32 host_index; - u32 size_in_bytes; -}; - -struct hpi_streamid { - u16 object_type; - /**< Type of object, HPI_OBJ_OSTREAM or HPI_OBJ_ISTREAM. */ - u16 stream_index; /**< outstream or instream index. */ -}; - -struct hpi_punchinout { - u32 punch_in_sample; - u32 punch_out_sample; -}; - -struct hpi_subsys_msg { - struct hpi_resource resource; -}; - -struct hpi_subsys_res { - u32 version; - u32 data; /* extended version */ - u16 num_adapters; - u16 adapter_index; - u16 adapter_type; - u16 pad16; -}; - -union hpi_adapterx_msg { - struct { - u32 dsp_address; - u32 count_bytes; - } debug_read; - struct { - u32 adapter_mode; - u16 query_or_set; - } mode; - struct { - u16 index; - } module_info; - struct { - u16 index; - u16 what; - u16 property_index; - } property_enum; - struct { - u16 property; - u16 parameter1; - u16 parameter2; - } property_set; - struct { - u32 pad32; - u16 key1; - u16 key2; - } restart; - struct { - u32 pad32; - u16 value; - } test_assert; - struct { - u32 yes; - } irq_query; - u32 pad[3]; -}; - -struct hpi_adapter_res { - u32 serial_number; - u16 adapter_type; - u16 adapter_index; - u16 num_instreams; - u16 num_outstreams; - u16 num_mixers; - u16 version; - u8 sz_adapter_assert[HPI_STRING_LEN]; -}; - -union hpi_adapterx_res { - struct hpi_adapter_res info; - struct { - u32 p1; - u16 count; - u16 dsp_index; - u32 p2; - u32 dsp_msg_addr; - char sz_message[HPI_STRING_LEN]; - } assert; - struct { - u32 adapter_mode; - } mode; - struct { - u16 parameter1; - u16 parameter2; - } property_get; - struct { - u32 yes; - } irq_query; -}; - -struct hpi_stream_msg { - union { - struct hpi_msg_data data; - struct hpi_data_legacy32 data32; - u16 velocity; - struct hpi_punchinout pio; - u32 time_scale; - struct hpi_buffer buffer; - struct hpi_streamid stream; - u32 threshold_bytes; - } u; -}; - -struct hpi_stream_res { - union { - struct { - /* size of hardware buffer */ - u32 buffer_size; - /* OutStream - data to play, - InStream - data recorded */ - u32 data_available; - /* OutStream - samples played, - InStream - samples recorded */ - u32 samples_transferred; - /* Adapter - OutStream - data to play, - InStream - data recorded */ - u32 auxiliary_data_available; - u16 state; /* HPI_STATE_PLAYING, _STATE_STOPPED */ - u16 padding; - } stream_info; - struct { - u32 buffer_size; - u32 data_available; - u32 samples_transfered; - u16 state; - u16 outstream_index; - u16 instream_index; - u16 padding; - u32 auxiliary_data_available; - } legacy_stream_info; - struct { - /* bitmap of grouped OutStreams */ - u32 outstream_group_map; - /* bitmap of grouped InStreams */ - u32 instream_group_map; - } group_info; - struct { - /* pointer to the buffer */ - u8 *p_buffer; - /* pointer to the hostbuffer status */ - struct hpi_hostbuffer_status *p_status; - } hostbuffer_info; - } u; -}; - -struct hpi_mixer_msg { - u16 control_index; - u16 control_type; /* = HPI_CONTROL_METER _VOLUME etc */ - u16 padding1; /* Maintain alignment of subsequent fields */ - u16 node_type1; /* = HPI_SOURCENODE_LINEIN etc */ - u16 node_index1; /* = 0..N */ - u16 node_type2; - u16 node_index2; - u16 padding2; /* round to 4 bytes */ -}; - -struct hpi_mixer_res { - u16 src_node_type; /* = HPI_SOURCENODE_LINEIN etc */ - u16 src_node_index; /* = 0..N */ - u16 dst_node_type; - u16 dst_node_index; - /* Also controlType for MixerGetControlByIndex */ - u16 control_index; - /* may indicate which DSP the control is located on */ - u16 dsp_index; -}; - -union hpi_mixerx_msg { - struct { - u16 starting_index; - u16 flags; - u32 length_in_bytes; /* length in bytes of p_data */ - u32 p_data; /* pointer to a data array */ - } gcabi; - struct { - u16 command; - u16 index; - } store; /* for HPI_MIXER_STORE message */ -}; - -union hpi_mixerx_res { - struct { - u32 bytes_returned; /* size of items returned */ - u32 p_data; /* pointer to data array */ - u16 more_to_do; /* indicates if there is more to do */ - } gcabi; - struct { - u32 total_controls; /* count of controls in the mixer */ - u32 cache_controls; /* count of controls in the cac */ - u32 cache_bytes; /* size of cache */ - } cache_info; -}; - -struct hpi_control_msg { - u16 attribute; /* control attribute or property */ - u16 saved_index; - u32 param1; /* generic parameter 1 */ - u32 param2; /* generic parameter 2 */ - short an_log_value[HPI_MAX_CHANNELS]; -}; - -struct hpi_control_union_msg { - u16 attribute; /* control attribute or property */ - u16 saved_index; /* only used in ctrl save/restore */ - union { - struct { - u32 param1; /* generic parameter 1 */ - u32 param2; /* generic parameter 2 */ - short an_log_value[HPI_MAX_CHANNELS]; - } old; - union { - u32 frequency; - u32 gain; - u32 band; - u32 deemphasis; - u32 program; - struct { - u32 mode; - u32 value; - } mode; - u32 blend; - } tuner; - } u; -}; - -struct hpi_control_res { - /* Could make union. dwParam, anLogValue never used in same response */ - u32 param1; - u32 param2; - short an_log_value[HPI_MAX_CHANNELS]; -}; - -union hpi_control_union_res { - struct { - u32 param1; - u32 param2; - short an_log_value[HPI_MAX_CHANNELS]; - } old; - union { - u32 band; - u32 frequency; - u32 gain; - u32 deemphasis; - struct { - u32 data[2]; - u32 bLER; - } rds; - short s_level; - struct { - u16 value; - u16 mask; - } status; - } tuner; - struct { - char sz_data[8]; - u32 remaining_chars; - } chars8; - char c_data12[12]; - union { - struct { - u32 status; - u32 readable_size; - u32 writeable_size; - } status; - } cobranet; -}; - -struct hpi_nvmemory_msg { - u16 address; - u16 data; -}; - -struct hpi_nvmemory_res { - u16 size_in_bytes; - u16 data; -}; - -struct hpi_gpio_msg { - u16 bit_index; - u16 bit_data; -}; - -struct hpi_gpio_res { - u16 number_input_bits; - u16 number_output_bits; - u16 bit_data[4]; -}; - -struct hpi_async_msg { - u32 events; - u16 maximum_events; - u16 padding; -}; - -struct hpi_async_res { - union { - struct { - u16 count; - } count; - struct { - u32 events; - u16 number_returned; - u16 padding; - } get; - struct hpi_async_event event; - } u; -}; - -struct hpi_watchdog_msg { - u32 time_ms; -}; - -struct hpi_watchdog_res { - u32 time_ms; -}; - -struct hpi_clock_msg { - u16 hours; - u16 minutes; - u16 seconds; - u16 milli_seconds; -}; - -struct hpi_clock_res { - u16 size_in_bytes; - u16 hours; - u16 minutes; - u16 seconds; - u16 milli_seconds; - u16 padding; -}; - -struct hpi_profile_msg { - u16 bin_index; - u16 padding; -}; - -struct hpi_profile_res_open { - u16 max_profiles; -}; - -struct hpi_profile_res_time { - u32 total_tick_count; - u32 call_count; - u32 max_tick_count; - u32 ticks_per_millisecond; - u16 profile_interval; -}; - -struct hpi_profile_res_name { - u8 sz_name[32]; -}; - -struct hpi_profile_res { - union { - struct hpi_profile_res_open o; - struct hpi_profile_res_time t; - struct hpi_profile_res_name n; - } u; -}; - -struct hpi_message_header { - u16 size; /* total size in bytes */ - u8 type; /* HPI_TYPE_MESSAGE */ - u8 version; /* message version */ - u16 object; /* HPI_OBJ_* */ - u16 function; /* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */ - u16 adapter_index; /* the adapter index */ - u16 obj_index; /* */ -}; - -struct hpi_message { - /* following fields must match HPI_MESSAGE_HEADER */ - u16 size; /* total size in bytes */ - u8 type; /* HPI_TYPE_MESSAGE */ - u8 version; /* message version */ - u16 object; /* HPI_OBJ_* */ - u16 function; /* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */ - u16 adapter_index; /* the adapter index */ - u16 obj_index; /* */ - union { - struct hpi_subsys_msg s; - union hpi_adapterx_msg ax; - struct hpi_stream_msg d; - struct hpi_mixer_msg m; - union hpi_mixerx_msg mx; /* extended mixer; */ - struct hpi_control_msg c; /* mixer control; */ - /* identical to struct hpi_control_msg, - but field naming is improved */ - struct hpi_control_union_msg cu; - struct hpi_nvmemory_msg n; - struct hpi_gpio_msg l; /* digital i/o */ - struct hpi_watchdog_msg w; - struct hpi_clock_msg t; /* dsp time */ - struct hpi_profile_msg p; - struct hpi_async_msg as; - char fixed_size[32]; - } u; -}; - -#define HPI_MESSAGE_SIZE_BY_OBJECT { \ - sizeof(struct hpi_message_header) , /* Default, no object type 0 */ \ - sizeof(struct hpi_message_header) + sizeof(struct hpi_subsys_msg),\ - sizeof(struct hpi_message_header) + sizeof(union hpi_adapterx_msg),\ - sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\ - sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\ - sizeof(struct hpi_message_header) + sizeof(struct hpi_mixer_msg),\ - sizeof(struct hpi_message_header) , /* no node message */ \ - sizeof(struct hpi_message_header) + sizeof(struct hpi_control_msg),\ - sizeof(struct hpi_message_header) + sizeof(struct hpi_nvmemory_msg),\ - sizeof(struct hpi_message_header) + sizeof(struct hpi_gpio_msg),\ - sizeof(struct hpi_message_header) + sizeof(struct hpi_watchdog_msg),\ - sizeof(struct hpi_message_header) + sizeof(struct hpi_clock_msg),\ - sizeof(struct hpi_message_header) + sizeof(struct hpi_profile_msg),\ - sizeof(struct hpi_message_header), /* controlx obj removed */ \ - sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \ -} - -/* -Note that the wSpecificError error field should be inspected and potentially -reported whenever HPI_ERROR_DSP_COMMUNICATION or HPI_ERROR_DSP_BOOTLOAD is -returned in wError. -*/ -struct hpi_response_header { - u16 size; - u8 type; /* HPI_TYPE_RESPONSE */ - u8 version; /* response version */ - u16 object; /* HPI_OBJ_* */ - u16 function; /* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */ - u16 error; /* HPI_ERROR_xxx */ - u16 specific_error; /* adapter specific error */ -}; - -struct hpi_response { -/* following fields must match HPI_RESPONSE_HEADER */ - u16 size; - u8 type; /* HPI_TYPE_RESPONSE */ - u8 version; /* response version */ - u16 object; /* HPI_OBJ_* */ - u16 function; /* HPI_SUBSYS_xxx, HPI_ADAPTER_xxx */ - u16 error; /* HPI_ERROR_xxx */ - u16 specific_error; /* adapter specific error */ - union { - struct hpi_subsys_res s; - union hpi_adapterx_res ax; - struct hpi_stream_res d; - struct hpi_mixer_res m; - union hpi_mixerx_res mx; /* extended mixer; */ - struct hpi_control_res c; /* mixer control; */ - /* identical to hpi_control_res, but field naming is improved */ - union hpi_control_union_res cu; - struct hpi_nvmemory_res n; - struct hpi_gpio_res l; /* digital i/o */ - struct hpi_watchdog_res w; - struct hpi_clock_res t; /* dsp time */ - struct hpi_profile_res p; - struct hpi_async_res as; - u8 bytes[52]; - } u; -}; - -#define HPI_RESPONSE_SIZE_BY_OBJECT { \ - sizeof(struct hpi_response_header) ,/* Default, no object type 0 */ \ - sizeof(struct hpi_response_header) + sizeof(struct hpi_subsys_res),\ - sizeof(struct hpi_response_header) + sizeof(union hpi_adapterx_res),\ - sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\ - sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\ - sizeof(struct hpi_response_header) + sizeof(struct hpi_mixer_res),\ - sizeof(struct hpi_response_header) , /* no node response */ \ - sizeof(struct hpi_response_header) + sizeof(struct hpi_control_res),\ - sizeof(struct hpi_response_header) + sizeof(struct hpi_nvmemory_res),\ - sizeof(struct hpi_response_header) + sizeof(struct hpi_gpio_res),\ - sizeof(struct hpi_response_header) + sizeof(struct hpi_watchdog_res),\ - sizeof(struct hpi_response_header) + sizeof(struct hpi_clock_res),\ - sizeof(struct hpi_response_header) + sizeof(struct hpi_profile_res),\ - sizeof(struct hpi_response_header), /* controlx obj removed */ \ - sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \ -} - -/*********************** version 1 message/response **************************/ -#define HPINET_ETHERNET_DATA_SIZE (1500) -#define HPINET_IP_HDR_SIZE (20) -#define HPINET_IP_DATA_SIZE (HPINET_ETHERNET_DATA_SIZE - HPINET_IP_HDR_SIZE) -#define HPINET_UDP_HDR_SIZE (8) -#define HPINET_UDP_DATA_SIZE (HPINET_IP_DATA_SIZE - HPINET_UDP_HDR_SIZE) -#define HPINET_ASI_HDR_SIZE (2) -#define HPINET_ASI_DATA_SIZE (HPINET_UDP_DATA_SIZE - HPINET_ASI_HDR_SIZE) - -#define HPI_MAX_PAYLOAD_SIZE (HPINET_ASI_DATA_SIZE - 2) - -/* New style message/response, but still V0 compatible */ -struct hpi_msg_adapter_get_info { - struct hpi_message_header h; -}; - -struct hpi_res_adapter_get_info { - struct hpi_response_header h; /*v0 */ - struct hpi_adapter_res p; -}; - -struct hpi_res_adapter_debug_read { - struct hpi_response_header h; - u8 bytes[1024]; -}; - -struct hpi_msg_cobranet_hmi { - u16 attribute; - u16 padding; - u32 hmi_address; - u32 byte_count; -}; - -struct hpi_msg_cobranet_hmiwrite { - struct hpi_message_header h; - struct hpi_msg_cobranet_hmi p; - u8 bytes[256]; -}; - -struct hpi_msg_cobranet_hmiread { - struct hpi_message_header h; - struct hpi_msg_cobranet_hmi p; -}; - -struct hpi_res_cobranet_hmiread { - struct hpi_response_header h; - u32 byte_count; - u8 bytes[256]; -}; - -#if 1 -#define hpi_message_header_v1 hpi_message_header -#define hpi_response_header_v1 hpi_response_header -#else -/* V1 headers in Addition to v0 headers */ -struct hpi_message_header_v1 { - struct hpi_message_header h0; -/* struct { -} h1; */ -}; - -struct hpi_response_header_v1 { - struct hpi_response_header h0; - struct { - u16 adapter_index; /* the adapter index */ - u16 obj_index; /* object index */ - } h1; -}; -#endif - -struct hpi_msg_payload_v0 { - struct hpi_message_header h; - union { - struct hpi_subsys_msg s; - union hpi_adapterx_msg ax; - struct hpi_stream_msg d; - struct hpi_mixer_msg m; - union hpi_mixerx_msg mx; - struct hpi_control_msg c; - struct hpi_control_union_msg cu; - struct hpi_nvmemory_msg n; - struct hpi_gpio_msg l; - struct hpi_watchdog_msg w; - struct hpi_clock_msg t; - struct hpi_profile_msg p; - struct hpi_async_msg as; - } u; -}; - -struct hpi_res_payload_v0 { - struct hpi_response_header h; - union { - struct hpi_subsys_res s; - union hpi_adapterx_res ax; - struct hpi_stream_res d; - struct hpi_mixer_res m; - union hpi_mixerx_res mx; - struct hpi_control_res c; - union hpi_control_union_res cu; - struct hpi_nvmemory_res n; - struct hpi_gpio_res l; - struct hpi_watchdog_res w; - struct hpi_clock_res t; - struct hpi_profile_res p; - struct hpi_async_res as; - } u; -}; - -union hpi_message_buffer_v1 { - struct hpi_message m0; /* version 0 */ - struct hpi_message_header_v1 h; - u8 buf[HPI_MAX_PAYLOAD_SIZE]; -}; - -union hpi_response_buffer_v1 { - struct hpi_response r0; /* version 0 */ - struct hpi_response_header_v1 h; - u8 buf[HPI_MAX_PAYLOAD_SIZE]; -}; - -compile_time_assert((sizeof(union hpi_message_buffer_v1) <= - HPI_MAX_PAYLOAD_SIZE), message_buffer_ok); -compile_time_assert((sizeof(union hpi_response_buffer_v1) <= - HPI_MAX_PAYLOAD_SIZE), response_buffer_ok); - -/*////////////////////////////////////////////////////////////////////////// */ -/* declarations for compact control calls */ -struct hpi_control_defn { - u8 type; - u8 channels; - u8 src_node_type; - u8 src_node_index; - u8 dest_node_type; - u8 dest_node_index; -}; - -/*////////////////////////////////////////////////////////////////////////// */ -/* declarations for control caching (internal to HPI<->DSP interaction) */ - -/** indicates a cached u16 value is invalid. */ -#define HPI_CACHE_INVALID_UINT16 0xFFFF -/** indicates a cached short value is invalid. */ -#define HPI_CACHE_INVALID_SHORT -32768 - -/** A compact representation of (part of) a controls state. -Used for efficient transfer of the control state -between DSP and host or across a network -*/ -struct hpi_control_cache_info { - /** one of HPI_CONTROL_* */ - u8 control_type; - /** The total size of cached information in 32-bit words. */ - u8 size_in32bit_words; - /** The original index of the control on the DSP */ - u16 control_index; -}; - -struct hpi_control_cache_vol { - struct hpi_control_cache_info i; - short an_log[2]; - unsigned short flags; - char padding[2]; -}; - -struct hpi_control_cache_meter { - struct hpi_control_cache_info i; - short an_log_peak[2]; - short an_logRMS[2]; -}; - -struct hpi_control_cache_channelmode { - struct hpi_control_cache_info i; - u16 mode; - char temp_padding[6]; -}; - -struct hpi_control_cache_mux { - struct hpi_control_cache_info i; - u16 source_node_type; - u16 source_node_index; - char temp_padding[4]; -}; - -struct hpi_control_cache_level { - struct hpi_control_cache_info i; - short an_log[2]; - char temp_padding[4]; -}; - -struct hpi_control_cache_tuner { - struct hpi_control_cache_info i; - u32 freq_ink_hz; - u16 band; - short s_level_avg; -}; - -struct hpi_control_cache_aes3rx { - struct hpi_control_cache_info i; - u32 error_status; - u32 format; -}; - -struct hpi_control_cache_aes3tx { - struct hpi_control_cache_info i; - u32 format; - char temp_padding[4]; -}; - -struct hpi_control_cache_tonedetector { - struct hpi_control_cache_info i; - u16 state; - char temp_padding[6]; -}; - -struct hpi_control_cache_silencedetector { - struct hpi_control_cache_info i; - u32 state; - char temp_padding[4]; -}; - -struct hpi_control_cache_sampleclock { - struct hpi_control_cache_info i; - u16 source; - u16 source_index; - u32 sample_rate; -}; - -struct hpi_control_cache_microphone { - struct hpi_control_cache_info i; - u16 phantom_state; - char temp_padding[6]; -}; - -struct hpi_control_cache_single { - union { - struct hpi_control_cache_info i; - struct hpi_control_cache_vol vol; - struct hpi_control_cache_meter meter; - struct hpi_control_cache_channelmode mode; - struct hpi_control_cache_mux mux; - struct hpi_control_cache_level level; - struct hpi_control_cache_tuner tuner; - struct hpi_control_cache_aes3rx aes3rx; - struct hpi_control_cache_aes3tx aes3tx; - struct hpi_control_cache_tonedetector tone; - struct hpi_control_cache_silencedetector silence; - struct hpi_control_cache_sampleclock clk; - struct hpi_control_cache_microphone microphone; - } u; -}; - -struct hpi_control_cache_pad { - struct hpi_control_cache_info i; - u32 field_valid_flags; - u8 c_channel[8]; - u8 c_artist[40]; - u8 c_title[40]; - u8 c_comment[200]; - u32 pTY; - u32 pI; - u32 traffic_supported; - u32 traffic_anouncement; -}; - -/* 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */ -struct hpi_fifo_buffer { - u32 size; - u32 dsp_index; - u32 host_index; -}; - -#ifndef DISABLE_PRAGMA_PACK1 -#pragma pack(pop) -#endif - -/* skip host side function declarations for DSP - compile and documentation extraction */ - -char hpi_handle_object(const u32 handle); - -void hpi_handle_to_indexes(const u32 handle, u16 *pw_adapter_index, - u16 *pw_object_index); - -u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index, - const u16 object_index); - -/*////////////////////////////////////////////////////////////////////////// */ - -/* main HPI entry point */ -void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr); - -/* used in PnP OS/driver */ -u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource, - u16 *pw_adapter_index); - -u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer, - struct hpi_hostbuffer_status **pp_status); - -u16 hpi_instream_host_buffer_get_info(u32 h_instream, u8 **pp_buffer, - struct hpi_hostbuffer_status **pp_status); - -u16 hpi_adapter_restart(u16 adapter_index); - -/* -The following 3 functions were last declared in header files for -driver 3.10. HPI_ControlQuery() used to be the recommended way -of getting a volume range. Declared here for binary asihpi32.dll -compatibility. -*/ - -void hpi_format_to_msg(struct hpi_msg_format *pMF, - const struct hpi_format *pF); -void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR); - -/*////////////////////////////////////////////////////////////////////////// */ -/* declarations for individual HPI entry points */ -hpi_handler_func HPI_6000; -hpi_handler_func HPI_6205; - -#endif /* _HPI_INTERNAL_H_ */ diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpi_version.h b/ANDROID_3.4.5/sound/pci/asihpi/hpi_version.h deleted file mode 100644 index e9146e53..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpi_version.h +++ /dev/null @@ -1,32 +0,0 @@ -/** HPI Version Definitions -Development releases have odd minor version. -Production releases have even minor version. - -\file hpi_version.h -*/ - -#ifndef _HPI_VERSION_H -#define _HPI_VERSION_H - -/* Use single digits for versions less that 10 to avoid octal. */ -/* *** HPI_VER is the only edit required to update version *** */ -/** HPI version */ -#define HPI_VER HPI_VERSION_CONSTRUCTOR(4, 10, 1) - -/** HPI version string in dotted decimal format */ -#define HPI_VER_STRING "4.10.01" - -/** Library version as documented in hpi-api-versions.txt */ -#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(10, 2, 0) - -/** Construct hpi version number from major, minor, release numbers */ -#define HPI_VERSION_CONSTRUCTOR(maj, min, r) ((maj << 16) + (min << 8) + r) - -/** Extract major version from hpi version number */ -#define HPI_VER_MAJOR(v) ((int)(v >> 16)) -/** Extract minor version from hpi version number */ -#define HPI_VER_MINOR(v) ((int)((v >> 8) & 0xFF)) -/** Extract release from hpi version number */ -#define HPI_VER_RELEASE(v) ((int)(v & 0xFF)) - -#endif diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpicmn.c b/ANDROID_3.4.5/sound/pci/asihpi/hpicmn.c deleted file mode 100644 index 7ed5c26c..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpicmn.c +++ /dev/null @@ -1,703 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -\file hpicmn.c - - Common functions used by hpixxxx.c modules - -(C) Copyright AudioScience Inc. 1998-2003 -*******************************************************************************/ -#define SOURCEFILE_NAME "hpicmn.c" - -#include "hpi_internal.h" -#include "hpidebug.h" -#include "hpimsginit.h" - -#include "hpicmn.h" - -struct hpi_adapters_list { - struct hpios_spinlock list_lock; - struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS]; - u16 gw_num_adapters; -}; - -static struct hpi_adapters_list adapters; - -/** -* Given an HPI Message that was sent out and a response that was received, -* validate that the response has the correct fields filled in, -* i.e ObjectType, Function etc -**/ -u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr) -{ - if (phr->type != HPI_TYPE_RESPONSE) { - HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type); - return HPI_ERROR_INVALID_RESPONSE; - } - - if (phr->object != phm->object) { - HPI_DEBUG_LOG(ERROR, "header object %d invalid\n", - phr->object); - return HPI_ERROR_INVALID_RESPONSE; - } - - if (phr->function != phm->function) { - HPI_DEBUG_LOG(ERROR, "header function %d invalid\n", - phr->function); - return HPI_ERROR_INVALID_RESPONSE; - } - - return 0; -} - -u16 hpi_add_adapter(struct hpi_adapter_obj *pao) -{ - u16 retval = 0; - /*HPI_ASSERT(pao->type); */ - - hpios_alistlock_lock(&adapters); - - if (pao->index >= HPI_MAX_ADAPTERS) { - retval = HPI_ERROR_BAD_ADAPTER_NUMBER; - goto unlock; - } - - if (adapters.adapter[pao->index].type) { - int a; - for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) { - if (!adapters.adapter[a].type) { - HPI_DEBUG_LOG(WARNING, - "ASI%X duplicate index %d moved to %d\n", - pao->type, pao->index, a); - pao->index = a; - break; - } - } - if (a < 0) { - retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER; - goto unlock; - } - } - adapters.adapter[pao->index] = *pao; - hpios_dsplock_init(&adapters.adapter[pao->index]); - adapters.gw_num_adapters++; - -unlock: - hpios_alistlock_unlock(&adapters); - return retval; -} - -void hpi_delete_adapter(struct hpi_adapter_obj *pao) -{ - if (!pao->type) { - HPI_DEBUG_LOG(ERROR, "removing null adapter?\n"); - return; - } - - hpios_alistlock_lock(&adapters); - if (adapters.adapter[pao->index].type) - adapters.gw_num_adapters--; - memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0])); - hpios_alistlock_unlock(&adapters); -} - -/** -* FindAdapter returns a pointer to the struct hpi_adapter_obj with -* index wAdapterIndex in an HPI_ADAPTERS_LIST structure. -* -*/ -struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index) -{ - struct hpi_adapter_obj *pao = NULL; - - if (adapter_index >= HPI_MAX_ADAPTERS) { - HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n", - adapter_index); - return NULL; - } - - pao = &adapters.adapter[adapter_index]; - if (pao->type != 0) { - /* - HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n", - wAdapterIndex); - */ - return pao; - } else { - /* - HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n", - wAdapterIndex); - */ - return NULL; - } -} - -/** -* -* wipe an HPI_ADAPTERS_LIST structure. -* -**/ -static void wipe_adapter_list(void) -{ - memset(&adapters, 0, sizeof(adapters)); -} - -static void subsys_get_adapter(struct hpi_message *phm, - struct hpi_response *phr) -{ - int count = phm->obj_index; - u16 index = 0; - - /* find the nCount'th nonzero adapter in array */ - for (index = 0; index < HPI_MAX_ADAPTERS; index++) { - if (adapters.adapter[index].type) { - if (!count) - break; - count--; - } - } - - if (index < HPI_MAX_ADAPTERS) { - phr->u.s.adapter_index = adapters.adapter[index].index; - phr->u.s.adapter_type = adapters.adapter[index].type; - } else { - phr->u.s.adapter_index = 0; - phr->u.s.adapter_type = 0; - phr->error = HPI_ERROR_INVALID_OBJ_INDEX; - } -} - -static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) -{ - unsigned int i; - int cached = 0; - if (!pC) - return 0; - - if (pC->init) - return pC->init; - - if (!pC->p_cache) - return 0; - - if (pC->control_count && pC->cache_size_in_bytes) { - char *p_master_cache; - unsigned int byte_count = 0; - - p_master_cache = (char *)pC->p_cache; - HPI_DEBUG_LOG(DEBUG, "check %d controls\n", - pC->control_count); - for (i = 0; i < pC->control_count; i++) { - struct hpi_control_cache_info *info = - (struct hpi_control_cache_info *) - &p_master_cache[byte_count]; - - if (!info->size_in32bit_words) { - if (!i) { - HPI_DEBUG_LOG(INFO, - "adap %d cache not ready?\n", - pC->adap_idx); - return 0; - } - /* The cache is invalid. - * Minimum valid entry size is - * sizeof(struct hpi_control_cache_info) - */ - HPI_DEBUG_LOG(ERROR, - "adap %d zero size cache entry %d\n", - pC->adap_idx, i); - break; - } - - if (info->control_type) { - pC->p_info[info->control_index] = info; - cached++; - } else { /* dummy cache entry */ - pC->p_info[info->control_index] = NULL; - } - - byte_count += info->size_in32bit_words * 4; - - HPI_DEBUG_LOG(VERBOSE, - "cached %d, pinfo %p index %d type %d size %d\n", - cached, pC->p_info[info->control_index], - info->control_index, info->control_type, - info->size_in32bit_words); - - /* quit loop early if whole cache has been scanned. - * dwControlCount is the maximum possible entries - * but some may be absent from the cache - */ - if (byte_count >= pC->cache_size_in_bytes) - break; - /* have seen last control index */ - if (info->control_index == pC->control_count - 1) - break; - } - - if (byte_count != pC->cache_size_in_bytes) - HPI_DEBUG_LOG(WARNING, - "adap %d bytecount %d != cache size %d\n", - pC->adap_idx, byte_count, - pC->cache_size_in_bytes); - else - HPI_DEBUG_LOG(DEBUG, - "adap %d cache good, bytecount == cache size = %d\n", - pC->adap_idx, byte_count); - - pC->init = (u16)cached; - } - return pC->init; -} - -/** Find a control. -*/ -static short find_control(u16 control_index, - struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI) -{ - if (!control_cache_alloc_check(p_cache)) { - HPI_DEBUG_LOG(VERBOSE, - "control_cache_alloc_check() failed %d\n", - control_index); - return 0; - } - - *pI = p_cache->p_info[control_index]; - if (!*pI) { - HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n", - control_index); - return 0; - } else { - HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n", - (*pI)->control_type); - } - return 1; -} - -/* allow unified treatment of several string fields within struct */ -#define HPICMN_PAD_OFS_AND_SIZE(m) {\ - offsetof(struct hpi_control_cache_pad, m), \ - sizeof(((struct hpi_control_cache_pad *)(NULL))->m) } - -struct pad_ofs_size { - unsigned int offset; - unsigned int field_size; -}; - -static const struct pad_ofs_size pad_desc[] = { - HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */ - HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */ - HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */ - HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */ -}; - -/** CheckControlCache checks the cache and fills the struct hpi_response - * accordingly. It returns one if a cache hit occurred, zero otherwise. - */ -short hpi_check_control_cache(struct hpi_control_cache *p_cache, - struct hpi_message *phm, struct hpi_response *phr) -{ - short found = 1; - struct hpi_control_cache_info *pI; - struct hpi_control_cache_single *pC; - size_t response_size; - if (!find_control(phm->obj_index, p_cache, &pI)) { - HPI_DEBUG_LOG(VERBOSE, - "HPICMN find_control() failed for adap %d\n", - phm->adapter_index); - return 0; - } - - phr->error = 0; - phr->specific_error = 0; - phr->version = 0; - - /* set the default response size */ - response_size = - sizeof(struct hpi_response_header) + - sizeof(struct hpi_control_res); - - /* pC is the default cached control strucure. May be cast to - something else in the following switch statement. - */ - pC = (struct hpi_control_cache_single *)pI; - - switch (pI->control_type) { - - case HPI_CONTROL_METER: - if (phm->u.c.attribute == HPI_METER_PEAK) { - phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0]; - phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1]; - } else if (phm->u.c.attribute == HPI_METER_RMS) { - if (pC->u.meter.an_logRMS[0] == - HPI_CACHE_INVALID_SHORT) { - phr->error = - HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; - phr->u.c.an_log_value[0] = HPI_METER_MINIMUM; - phr->u.c.an_log_value[1] = HPI_METER_MINIMUM; - } else { - phr->u.c.an_log_value[0] = - pC->u.meter.an_logRMS[0]; - phr->u.c.an_log_value[1] = - pC->u.meter.an_logRMS[1]; - } - } else - found = 0; - break; - case HPI_CONTROL_VOLUME: - if (phm->u.c.attribute == HPI_VOLUME_GAIN) { - phr->u.c.an_log_value[0] = pC->u.vol.an_log[0]; - phr->u.c.an_log_value[1] = pC->u.vol.an_log[1]; - } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) { - if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) { - if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED) - phr->u.c.param1 = - HPI_BITMASK_ALL_CHANNELS; - else - phr->u.c.param1 = 0; - } else { - phr->error = - HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; - phr->u.c.param1 = 0; - } - } else { - found = 0; - } - break; - case HPI_CONTROL_MULTIPLEXER: - if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { - phr->u.c.param1 = pC->u.mux.source_node_type; - phr->u.c.param2 = pC->u.mux.source_node_index; - } else { - found = 0; - } - break; - case HPI_CONTROL_CHANNEL_MODE: - if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) - phr->u.c.param1 = pC->u.mode.mode; - else - found = 0; - break; - case HPI_CONTROL_LEVEL: - if (phm->u.c.attribute == HPI_LEVEL_GAIN) { - phr->u.c.an_log_value[0] = pC->u.level.an_log[0]; - phr->u.c.an_log_value[1] = pC->u.level.an_log[1]; - } else - found = 0; - break; - case HPI_CONTROL_TUNER: - if (phm->u.c.attribute == HPI_TUNER_FREQ) - phr->u.c.param1 = pC->u.tuner.freq_ink_hz; - else if (phm->u.c.attribute == HPI_TUNER_BAND) - phr->u.c.param1 = pC->u.tuner.band; - else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG) - if (pC->u.tuner.s_level_avg == - HPI_CACHE_INVALID_SHORT) { - phr->u.cu.tuner.s_level = 0; - phr->error = - HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; - } else - phr->u.cu.tuner.s_level = - pC->u.tuner.s_level_avg; - else - found = 0; - break; - case HPI_CONTROL_AESEBU_RECEIVER: - if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS) - phr->u.c.param1 = pC->u.aes3rx.error_status; - else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) - phr->u.c.param1 = pC->u.aes3rx.format; - else - found = 0; - break; - case HPI_CONTROL_AESEBU_TRANSMITTER: - if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) - phr->u.c.param1 = pC->u.aes3tx.format; - else - found = 0; - break; - case HPI_CONTROL_TONEDETECTOR: - if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE) - phr->u.c.param1 = pC->u.tone.state; - else - found = 0; - break; - case HPI_CONTROL_SILENCEDETECTOR: - if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) { - phr->u.c.param1 = pC->u.silence.state; - } else - found = 0; - break; - case HPI_CONTROL_MICROPHONE: - if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) - phr->u.c.param1 = pC->u.microphone.phantom_state; - else - found = 0; - break; - case HPI_CONTROL_SAMPLECLOCK: - if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) - phr->u.c.param1 = pC->u.clk.source; - else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) { - if (pC->u.clk.source_index == - HPI_CACHE_INVALID_UINT16) { - phr->u.c.param1 = 0; - phr->error = - HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; - } else - phr->u.c.param1 = pC->u.clk.source_index; - } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE) - phr->u.c.param1 = pC->u.clk.sample_rate; - else - found = 0; - break; - case HPI_CONTROL_PAD:{ - struct hpi_control_cache_pad *p_pad; - p_pad = (struct hpi_control_cache_pad *)pI; - - if (!(p_pad->field_valid_flags & (1 << - HPI_CTL_ATTR_INDEX(phm->u.c. - attribute)))) { - phr->error = - HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; - break; - } - - if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID) - phr->u.c.param1 = p_pad->pI; - else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE) - phr->u.c.param1 = p_pad->pTY; - else { - unsigned int index = - HPI_CTL_ATTR_INDEX(phm->u.c. - attribute) - 1; - unsigned int offset = phm->u.c.param1; - unsigned int pad_string_len, field_size; - char *pad_string; - unsigned int tocopy; - - if (index > ARRAY_SIZE(pad_desc) - 1) { - phr->error = - HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; - break; - } - - pad_string = - ((char *)p_pad) + - pad_desc[index].offset; - field_size = pad_desc[index].field_size; - /* Ensure null terminator */ - pad_string[field_size - 1] = 0; - - pad_string_len = strlen(pad_string) + 1; - - if (offset > pad_string_len) { - phr->error = - HPI_ERROR_INVALID_CONTROL_VALUE; - break; - } - - tocopy = pad_string_len - offset; - if (tocopy > sizeof(phr->u.cu.chars8.sz_data)) - tocopy = sizeof(phr->u.cu.chars8. - sz_data); - - memcpy(phr->u.cu.chars8.sz_data, - &pad_string[offset], tocopy); - - phr->u.cu.chars8.remaining_chars = - pad_string_len - offset - tocopy; - } - } - break; - default: - found = 0; - break; - } - - HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n", - found ? "Cached" : "Uncached", phm->adapter_index, - pI->control_index, pI->control_type, phm->u.c.attribute); - - if (found) { - phr->size = (u16)response_size; - phr->type = HPI_TYPE_RESPONSE; - phr->object = phm->object; - phr->function = phm->function; - } - - return found; -} - -/** Updates the cache with Set values. - -Only update if no error. -Volume and Level return the limited values in the response, so use these -Multiplexer does so use sent values -*/ -void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache, - struct hpi_message *phm, struct hpi_response *phr) -{ - struct hpi_control_cache_single *pC; - struct hpi_control_cache_info *pI; - - if (phr->error) - return; - - if (!find_control(phm->obj_index, p_cache, &pI)) { - HPI_DEBUG_LOG(VERBOSE, - "HPICMN find_control() failed for adap %d\n", - phm->adapter_index); - return; - } - - /* pC is the default cached control strucure. - May be cast to something else in the following switch statement. - */ - pC = (struct hpi_control_cache_single *)pI; - - switch (pI->control_type) { - case HPI_CONTROL_VOLUME: - if (phm->u.c.attribute == HPI_VOLUME_GAIN) { - pC->u.vol.an_log[0] = phr->u.c.an_log_value[0]; - pC->u.vol.an_log[1] = phr->u.c.an_log_value[1]; - } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) { - if (phm->u.c.param1) - pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED; - else - pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED; - } - break; - case HPI_CONTROL_MULTIPLEXER: - /* mux does not return its setting on Set command. */ - if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { - pC->u.mux.source_node_type = (u16)phm->u.c.param1; - pC->u.mux.source_node_index = (u16)phm->u.c.param2; - } - break; - case HPI_CONTROL_CHANNEL_MODE: - /* mode does not return its setting on Set command. */ - if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) - pC->u.mode.mode = (u16)phm->u.c.param1; - break; - case HPI_CONTROL_LEVEL: - if (phm->u.c.attribute == HPI_LEVEL_GAIN) { - pC->u.vol.an_log[0] = phr->u.c.an_log_value[0]; - pC->u.vol.an_log[1] = phr->u.c.an_log_value[1]; - } - break; - case HPI_CONTROL_MICROPHONE: - if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) - pC->u.microphone.phantom_state = (u16)phm->u.c.param1; - break; - case HPI_CONTROL_AESEBU_TRANSMITTER: - if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) - pC->u.aes3tx.format = phm->u.c.param1; - break; - case HPI_CONTROL_AESEBU_RECEIVER: - if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) - pC->u.aes3rx.format = phm->u.c.param1; - break; - case HPI_CONTROL_SAMPLECLOCK: - if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) - pC->u.clk.source = (u16)phm->u.c.param1; - else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) - pC->u.clk.source_index = (u16)phm->u.c.param1; - else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE) - pC->u.clk.sample_rate = phm->u.c.param1; - break; - default: - break; - } -} - -/** Allocate control cache. - -\return Cache pointer, or NULL if allocation fails. -*/ -struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, - const u32 size_in_bytes, u8 *p_dsp_control_buffer) -{ - struct hpi_control_cache *p_cache = - kmalloc(sizeof(*p_cache), GFP_KERNEL); - if (!p_cache) - return NULL; - - p_cache->p_info = kcalloc(control_count, sizeof(*p_cache->p_info), - GFP_KERNEL); - if (!p_cache->p_info) { - kfree(p_cache); - return NULL; - } - p_cache->cache_size_in_bytes = size_in_bytes; - p_cache->control_count = control_count; - p_cache->p_cache = p_dsp_control_buffer; - p_cache->init = 0; - return p_cache; -} - -void hpi_free_control_cache(struct hpi_control_cache *p_cache) -{ - if (p_cache) { - kfree(p_cache->p_info); - kfree(p_cache); - } -} - -static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) -{ - hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0); - - switch (phm->function) { - case HPI_SUBSYS_OPEN: - case HPI_SUBSYS_CLOSE: - case HPI_SUBSYS_DRIVER_UNLOAD: - break; - case HPI_SUBSYS_DRIVER_LOAD: - wipe_adapter_list(); - hpios_alistlock_init(&adapters); - break; - case HPI_SUBSYS_GET_ADAPTER: - subsys_get_adapter(phm, phr); - break; - case HPI_SUBSYS_GET_NUM_ADAPTERS: - phr->u.s.num_adapters = adapters.gw_num_adapters; - break; - case HPI_SUBSYS_CREATE_ADAPTER: - break; - default: - phr->error = HPI_ERROR_INVALID_FUNC; - break; - } -} - -void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr) -{ - switch (phm->type) { - case HPI_TYPE_REQUEST: - switch (phm->object) { - case HPI_OBJ_SUBSYSTEM: - subsys_message(phm, phr); - break; - } - break; - - default: - phr->error = HPI_ERROR_INVALID_TYPE; - break; - } -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpicmn.h b/ANDROID_3.4.5/sound/pci/asihpi/hpicmn.h deleted file mode 100644 index e4412128..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpicmn.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -*/ - -struct hpi_adapter_obj; - -/* a function that takes an adapter obj and returns an int */ -typedef int adapter_int_func(struct hpi_adapter_obj *pao); - -struct hpi_adapter_obj { - struct hpi_pci pci; /* PCI info - bus#,dev#,address etc */ - u16 type; /* 0x6644 == ASI6644 etc */ - u16 index; - - struct hpios_spinlock dsp_lock; - - u16 dsp_crashed; - u16 has_control_cache; - void *priv; -}; - -struct hpi_control_cache { - /** indicates whether the structures are initialized */ - u16 init; - u16 adap_idx; - u32 control_count; - u32 cache_size_in_bytes; - /** pointer to allocated memory of lookup pointers. */ - struct hpi_control_cache_info **p_info; - /** pointer to DSP's control cache. */ - u8 *p_cache; -}; - -struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index); - -u16 hpi_add_adapter(struct hpi_adapter_obj *pao); - -void hpi_delete_adapter(struct hpi_adapter_obj *pao); - -short hpi_check_control_cache(struct hpi_control_cache *pC, - struct hpi_message *phm, struct hpi_response *phr); -struct hpi_control_cache *hpi_alloc_control_cache(const u32 - number_of_controls, const u32 size_in_bytes, u8 *pDSP_control_buffer); -void hpi_free_control_cache(struct hpi_control_cache *p_cache); - -void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC, - struct hpi_message *phm, struct hpi_response *phr); - -u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr); - -hpi_handler_func HPI_COMMON; diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpidebug.c b/ANDROID_3.4.5/sound/pci/asihpi/hpidebug.c deleted file mode 100644 index ac86a1f1..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpidebug.c +++ /dev/null @@ -1,78 +0,0 @@ -/************************************************************************ - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -Debug macro translation. - -************************************************************************/ - -#include "hpi_internal.h" -#include "hpidebug.h" - -/* Debug level; 0 quiet; 1 informative, 2 debug, 3 verbose debug. */ -int hpi_debug_level = HPI_DEBUG_LEVEL_DEFAULT; - -void hpi_debug_init(void) -{ - printk(KERN_INFO "debug start\n"); -} - -int hpi_debug_level_set(int level) -{ - int old_level; - - old_level = hpi_debug_level; - hpi_debug_level = level; - return old_level; -} - -int hpi_debug_level_get(void) -{ - return hpi_debug_level; -} - -void hpi_debug_message(struct hpi_message *phm, char *sz_fileline) -{ - if (phm) { - printk(KERN_DEBUG "HPI_MSG%d,%d,%d,%d,%d\n", phm->version, - phm->adapter_index, phm->obj_index, phm->function, - phm->u.c.attribute); - } - -} - -void hpi_debug_data(u16 *pdata, u32 len) -{ - u32 i; - int j; - int k; - int lines; - int cols = 8; - - lines = (len + cols - 1) / cols; - if (lines > 8) - lines = 8; - - for (i = 0, j = 0; j < lines; j++) { - printk(KERN_DEBUG "%p:", (pdata + i)); - - for (k = 0; k < cols && i < len; i++, k++) - printk("%s%04x", k == 0 ? "" : " ", pdata[i]); - - printk("\n"); - } -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpidebug.h b/ANDROID_3.4.5/sound/pci/asihpi/hpidebug.h deleted file mode 100644 index 2c9af232..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpidebug.h +++ /dev/null @@ -1,102 +0,0 @@ -/***************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -Debug macros. - -*****************************************************************************/ - -#ifndef _HPIDEBUG_H -#define _HPIDEBUG_H - -#include "hpi_internal.h" - -/* Define debugging levels. */ -enum { HPI_DEBUG_LEVEL_ERROR = 0, /* always log errors */ - HPI_DEBUG_LEVEL_WARNING = 1, - HPI_DEBUG_LEVEL_NOTICE = 2, - HPI_DEBUG_LEVEL_INFO = 3, - HPI_DEBUG_LEVEL_DEBUG = 4, - HPI_DEBUG_LEVEL_VERBOSE = 5 /* same printk level as DEBUG */ -}; - -#define HPI_DEBUG_LEVEL_DEFAULT HPI_DEBUG_LEVEL_NOTICE - -/* an OS can define an extra flag string that is appended to - the start of each message, eg see linux kernel hpios.h */ - -#ifdef SOURCEFILE_NAME -#define FILE_LINE SOURCEFILE_NAME ":" __stringify(__LINE__) " " -#else -#define FILE_LINE __FILE__ ":" __stringify(__LINE__) " " -#endif - -#define HPI_DEBUG_ASSERT(expression) \ - do { \ - if (!(expression)) { \ - printk(KERN_ERR FILE_LINE \ - "ASSERT " __stringify(expression)); \ - } \ - } while (0) - -#define HPI_DEBUG_LOG(level, ...) \ - do { \ - if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) { \ - printk(HPI_DEBUG_FLAG_##level \ - FILE_LINE __VA_ARGS__); \ - } \ - } while (0) - -void hpi_debug_init(void); -int hpi_debug_level_set(int level); -int hpi_debug_level_get(void); -/* needed by Linux driver for dynamic debug level changes */ -extern int hpi_debug_level; - -void hpi_debug_message(struct hpi_message *phm, char *sz_fileline); - -void hpi_debug_data(u16 *pdata, u32 len); - -#define HPI_DEBUG_DATA(pdata, len) \ - do { \ - if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \ - hpi_debug_data(pdata, len); \ - } while (0) - -#define HPI_DEBUG_MESSAGE(level, phm) \ - do { \ - if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) { \ - hpi_debug_message(phm, HPI_DEBUG_FLAG_##level \ - FILE_LINE __stringify(level)); \ - } \ - } while (0) - -#define HPI_DEBUG_RESPONSE(phr) \ - do { \ - if (((hpi_debug_level >= HPI_DEBUG_LEVEL_DEBUG) && \ - (phr->error)) ||\ - (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE)) \ - printk(KERN_DEBUG "HPI_RES%d,%d,%d\n", \ - phr->version, phr->error, phr->specific_error); \ - } while (0) - -#ifndef compile_time_assert -#define compile_time_assert(cond, msg) \ - typedef char msg[(cond) ? 1 : -1] -#endif - -#endif /* _HPIDEBUG_H_ */ diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.c b/ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.c deleted file mode 100644 index 456a758f..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.c +++ /dev/null @@ -1,148 +0,0 @@ -/***********************************************************************/ -/** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -\file -Functions for reading DSP code using -hotplug firmware loader from individual dsp code files -*/ -/***********************************************************************/ -#define SOURCEFILE_NAME "hpidspcd.c" -#include "hpidspcd.h" -#include "hpidebug.h" -#include "hpi_version.h" - -struct dsp_code_private { - /** Firmware descriptor */ - const struct firmware *firmware; - struct pci_dev *dev; -}; - -/*-------------------------------------------------------------------*/ -short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code, - u32 *os_error_code) -{ - const struct firmware *firmware; - struct pci_dev *dev = os_data; - struct code_header header; - char fw_name[20]; - short err_ret = HPI_ERROR_DSP_FILE_NOT_FOUND; - int err; - - sprintf(fw_name, "asihpi/dsp%04x.bin", adapter); - - err = request_firmware(&firmware, fw_name, &dev->dev); - - if (err || !firmware) { - dev_printk(KERN_ERR, &dev->dev, - "%d, request_firmware failed for %s\n", err, - fw_name); - goto error1; - } - if (firmware->size < sizeof(header)) { - dev_printk(KERN_ERR, &dev->dev, "Header size too small %s\n", - fw_name); - goto error2; - } - memcpy(&header, firmware->data, sizeof(header)); - - if ((header.type != 0x45444F43) || /* "CODE" */ - (header.adapter != adapter) - || (header.size != firmware->size)) { - dev_printk(KERN_ERR, &dev->dev, - "Invalid firmware header size %d != file %zd\n", - header.size, firmware->size); - goto error2; - } - - if ((header.version >> 9) != (HPI_VER >> 9)) { - /* Consider even and subsequent odd minor versions to be compatible */ - dev_printk(KERN_ERR, &dev->dev, - "Incompatible firmware version " - "DSP image %X != Driver %X\n", header.version, - HPI_VER); - goto error2; - } - - if (header.version != HPI_VER) { - dev_printk(KERN_INFO, &dev->dev, - "Firmware: release version mismatch DSP image %X != Driver %X\n", - header.version, HPI_VER); - } - - HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name); - dsp_code->pvt = kmalloc(sizeof(*dsp_code->pvt), GFP_KERNEL); - if (!dsp_code->pvt) { - err_ret = HPI_ERROR_MEMORY_ALLOC; - goto error2; - } - - dsp_code->pvt->dev = dev; - dsp_code->pvt->firmware = firmware; - dsp_code->header = header; - dsp_code->block_length = header.size / sizeof(u32); - dsp_code->word_count = sizeof(header) / sizeof(u32); - return 0; - -error2: - release_firmware(firmware); -error1: - dsp_code->block_length = 0; - return err_ret; -} - -/*-------------------------------------------------------------------*/ -void hpi_dsp_code_close(struct dsp_code *dsp_code) -{ - HPI_DEBUG_LOG(DEBUG, "dsp code closed\n"); - release_firmware(dsp_code->pvt->firmware); - kfree(dsp_code->pvt); -} - -/*-------------------------------------------------------------------*/ -void hpi_dsp_code_rewind(struct dsp_code *dsp_code) -{ - /* Go back to start of data, after header */ - dsp_code->word_count = sizeof(struct code_header) / sizeof(u32); -} - -/*-------------------------------------------------------------------*/ -short hpi_dsp_code_read_word(struct dsp_code *dsp_code, u32 *pword) -{ - if (dsp_code->word_count + 1 > dsp_code->block_length) - return HPI_ERROR_DSP_FILE_FORMAT; - - *pword = ((u32 *)(dsp_code->pvt->firmware->data))[dsp_code-> - word_count]; - dsp_code->word_count++; - return 0; -} - -/*-------------------------------------------------------------------*/ -short hpi_dsp_code_read_block(size_t words_requested, - struct dsp_code *dsp_code, u32 **ppblock) -{ - if (dsp_code->word_count + words_requested > dsp_code->block_length) - return HPI_ERROR_DSP_FILE_FORMAT; - - *ppblock = - ((u32 *)(dsp_code->pvt->firmware->data)) + - dsp_code->word_count; - dsp_code->word_count += words_requested; - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.h b/ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.h deleted file mode 100644 index 659d19ca..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpidspcd.h +++ /dev/null @@ -1,106 +0,0 @@ -/***********************************************************************/ -/** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -\file -Functions for reading DSP code to load into DSP - -*/ -/***********************************************************************/ -#ifndef _HPIDSPCD_H_ -#define _HPIDSPCD_H_ - -#include "hpi_internal.h" - -/** Header structure for dsp firmware file - This structure must match that used in s2bin.c for generation of asidsp.bin - */ -/*#ifndef DISABLE_PRAGMA_PACK1 */ -/*#pragma pack(push, 1) */ -/*#endif */ -struct code_header { - /** Size in bytes including header */ - u32 size; - /** File type tag "CODE" == 0x45444F43 */ - u32 type; - /** Adapter model number */ - u32 adapter; - /** Firmware version*/ - u32 version; - /** Data checksum */ - u32 checksum; -}; -/*#ifndef DISABLE_PRAGMA_PACK1 */ -/*#pragma pack(pop) */ -/*#endif */ - -/*? Don't need the pragmas? */ -compile_time_assert((sizeof(struct code_header) == 20), code_header_size); - -/** Descriptor for dspcode from firmware loader */ -struct dsp_code { - /** copy of file header */ - struct code_header header; - /** Expected number of words in the whole dsp code,INCL header */ - u32 block_length; - /** Number of words read so far */ - u32 word_count; - - /** internal state of DSP code reader */ - struct dsp_code_private *pvt; -}; - -/** Prepare *psDspCode to refer to the requested adapter's firmware. -Code file name is obtained from HpiOs_GetDspCodePath - -\return 0 for success, or error code if requested code is not available -*/ -short hpi_dsp_code_open( - /** Code identifier, usually adapter family */ - u32 adapter, void *pci_dev, - /** Pointer to DSP code control structure */ - struct dsp_code *ps_dsp_code, - /** Pointer to dword to receive OS specific error code */ - u32 *pos_error_code); - -/** Close the DSP code file */ -void hpi_dsp_code_close(struct dsp_code *ps_dsp_code); - -/** Rewind to the beginning of the DSP code file (for verify) */ -void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code); - -/** Read one word from the dsp code file - \return 0 for success, or error code if eof, or block length exceeded -*/ -short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, - /**< DSP code descriptor */ - u32 *pword /**< Where to store the read word */ - ); - -/** Get a block of dsp code into an internal buffer, and provide a pointer to -that buffer. (If dsp code is already an array in memory, it is referenced, -not copied.) - -\return Error if requested number of words are not available -*/ -short hpi_dsp_code_read_block(size_t words_requested, - struct dsp_code *ps_dsp_code, - /* Pointer to store (Pointer to code buffer) */ - u32 **ppblock); - -#endif diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpifunc.c b/ANDROID_3.4.5/sound/pci/asihpi/hpifunc.c deleted file mode 100644 index 510e56cf..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpifunc.c +++ /dev/null @@ -1,2871 +0,0 @@ - -#include "hpi_internal.h" -#include "hpimsginit.h" - -#include "hpidebug.h" - -struct hpi_handle { - unsigned int obj_index:12; - unsigned int obj_type:4; - unsigned int adapter_index:14; - unsigned int spare:1; - unsigned int read_only:1; -}; - -union handle_word { - struct hpi_handle h; - u32 w; -}; - -u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index, - const u16 object_index) -{ - union handle_word handle; - - handle.h.adapter_index = adapter_index; - handle.h.spare = 0; - handle.h.read_only = 0; - handle.h.obj_type = c_object; - handle.h.obj_index = object_index; - return handle.w; -} - -static u16 hpi_handle_indexes(const u32 h, u16 *p1, u16 *p2) -{ - union handle_word uhandle; - if (!h) - return HPI_ERROR_INVALID_HANDLE; - - uhandle.w = h; - - *p1 = (u16)uhandle.h.adapter_index; - if (p2) - *p2 = (u16)uhandle.h.obj_index; - - return 0; -} - -void hpi_handle_to_indexes(const u32 handle, u16 *pw_adapter_index, - u16 *pw_object_index) -{ - hpi_handle_indexes(handle, pw_adapter_index, pw_object_index); -} - -char hpi_handle_object(const u32 handle) -{ - union handle_word uhandle; - uhandle.w = handle; - return (char)uhandle.h.obj_type; -} - -void hpi_format_to_msg(struct hpi_msg_format *pMF, - const struct hpi_format *pF) -{ - pMF->sample_rate = pF->sample_rate; - pMF->bit_rate = pF->bit_rate; - pMF->attributes = pF->attributes; - pMF->channels = pF->channels; - pMF->format = pF->format; -} - -static void hpi_msg_to_format(struct hpi_format *pF, - struct hpi_msg_format *pMF) -{ - pF->sample_rate = pMF->sample_rate; - pF->bit_rate = pMF->bit_rate; - pF->attributes = pMF->attributes; - pF->channels = pMF->channels; - pF->format = pMF->format; - pF->mode_legacy = 0; - pF->unused = 0; -} - -void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR) -{ - pSR->u.legacy_stream_info.auxiliary_data_available = - pSR->u.stream_info.auxiliary_data_available; - pSR->u.legacy_stream_info.state = pSR->u.stream_info.state; -} - -static inline void hpi_send_recvV1(struct hpi_message_header *m, - struct hpi_response_header *r) -{ - hpi_send_recv((struct hpi_message *)m, (struct hpi_response *)r); -} - -u16 hpi_subsys_get_version_ex(u32 *pversion_ex) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_GET_VERSION); - hpi_send_recv(&hm, &hr); - *pversion_ex = hr.u.s.data; - return hr.error; -} - -u16 hpi_subsys_get_num_adapters(int *pn_num_adapters) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_GET_NUM_ADAPTERS); - hpi_send_recv(&hm, &hr); - *pn_num_adapters = (int)hr.u.s.num_adapters; - return hr.error; -} - -u16 hpi_subsys_get_adapter(int iterator, u32 *padapter_index, - u16 *pw_adapter_type) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_GET_ADAPTER); - hm.obj_index = (u16)iterator; - hpi_send_recv(&hm, &hr); - *padapter_index = (int)hr.u.s.adapter_index; - *pw_adapter_type = hr.u.s.adapter_type; - - return hr.error; -} - -u16 hpi_adapter_open(u16 adapter_index) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_OPEN); - hm.adapter_index = adapter_index; - - hpi_send_recv(&hm, &hr); - - return hr.error; - -} - -u16 hpi_adapter_close(u16 adapter_index) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_CLOSE); - hm.adapter_index = adapter_index; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_adapter_set_mode(u16 adapter_index, u32 adapter_mode) -{ - return hpi_adapter_set_mode_ex(adapter_index, adapter_mode, - HPI_ADAPTER_MODE_SET); -} - -u16 hpi_adapter_set_mode_ex(u16 adapter_index, u32 adapter_mode, - u16 query_or_set) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_SET_MODE); - hm.adapter_index = adapter_index; - hm.u.ax.mode.adapter_mode = adapter_mode; - hm.u.ax.mode.query_or_set = query_or_set; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_adapter_get_mode(u16 adapter_index, u32 *padapter_mode) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_GET_MODE); - hm.adapter_index = adapter_index; - hpi_send_recv(&hm, &hr); - if (padapter_mode) - *padapter_mode = hr.u.ax.mode.adapter_mode; - return hr.error; -} - -u16 hpi_adapter_get_info(u16 adapter_index, u16 *pw_num_outstreams, - u16 *pw_num_instreams, u16 *pw_version, u32 *pserial_number, - u16 *pw_adapter_type) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_GET_INFO); - hm.adapter_index = adapter_index; - - hpi_send_recv(&hm, &hr); - - *pw_adapter_type = hr.u.ax.info.adapter_type; - *pw_num_outstreams = hr.u.ax.info.num_outstreams; - *pw_num_instreams = hr.u.ax.info.num_instreams; - *pw_version = hr.u.ax.info.version; - *pserial_number = hr.u.ax.info.serial_number; - return hr.error; -} - -u16 hpi_adapter_get_module_by_index(u16 adapter_index, u16 module_index, - u16 *pw_num_outputs, u16 *pw_num_inputs, u16 *pw_version, - u32 *pserial_number, u16 *pw_module_type, u32 *ph_module) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_MODULE_INFO); - hm.adapter_index = adapter_index; - hm.u.ax.module_info.index = module_index; - - hpi_send_recv(&hm, &hr); - - *pw_module_type = hr.u.ax.info.adapter_type; - *pw_num_outputs = hr.u.ax.info.num_outstreams; - *pw_num_inputs = hr.u.ax.info.num_instreams; - *pw_version = hr.u.ax.info.version; - *pserial_number = hr.u.ax.info.serial_number; - *ph_module = 0; - - return hr.error; -} - -u16 hpi_adapter_set_property(u16 adapter_index, u16 property, u16 parameter1, - u16 parameter2) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_SET_PROPERTY); - hm.adapter_index = adapter_index; - hm.u.ax.property_set.property = property; - hm.u.ax.property_set.parameter1 = parameter1; - hm.u.ax.property_set.parameter2 = parameter2; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_adapter_get_property(u16 adapter_index, u16 property, - u16 *pw_parameter1, u16 *pw_parameter2) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_GET_PROPERTY); - hm.adapter_index = adapter_index; - hm.u.ax.property_set.property = property; - - hpi_send_recv(&hm, &hr); - if (!hr.error) { - if (pw_parameter1) - *pw_parameter1 = hr.u.ax.property_get.parameter1; - if (pw_parameter2) - *pw_parameter2 = hr.u.ax.property_get.parameter2; - } - - return hr.error; -} - -u16 hpi_adapter_enumerate_property(u16 adapter_index, u16 index, - u16 what_to_enumerate, u16 property_index, u32 *psetting) -{ - return 0; -} - -u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, - u32 sample_rate, u32 bit_rate, u32 attributes) -{ - u16 err = 0; - struct hpi_msg_format fmt; - - switch (channels) { - case 1: - case 2: - case 4: - case 6: - case 8: - case 16: - break; - default: - err = HPI_ERROR_INVALID_CHANNELS; - return err; - } - fmt.channels = channels; - - switch (format) { - case HPI_FORMAT_PCM16_SIGNED: - case HPI_FORMAT_PCM24_SIGNED: - case HPI_FORMAT_PCM32_SIGNED: - case HPI_FORMAT_PCM32_FLOAT: - case HPI_FORMAT_PCM16_BIGENDIAN: - case HPI_FORMAT_PCM8_UNSIGNED: - case HPI_FORMAT_MPEG_L1: - case HPI_FORMAT_MPEG_L2: - case HPI_FORMAT_MPEG_L3: - case HPI_FORMAT_DOLBY_AC2: - case HPI_FORMAT_AA_TAGIT1_HITS: - case HPI_FORMAT_AA_TAGIT1_INSERTS: - case HPI_FORMAT_RAW_BITSTREAM: - case HPI_FORMAT_AA_TAGIT1_HITS_EX1: - case HPI_FORMAT_OEM1: - case HPI_FORMAT_OEM2: - break; - default: - err = HPI_ERROR_INVALID_FORMAT; - return err; - } - fmt.format = format; - - if (sample_rate < 8000L) { - err = HPI_ERROR_INCOMPATIBLE_SAMPLERATE; - sample_rate = 8000L; - } - if (sample_rate > 200000L) { - err = HPI_ERROR_INCOMPATIBLE_SAMPLERATE; - sample_rate = 200000L; - } - fmt.sample_rate = sample_rate; - - switch (format) { - case HPI_FORMAT_MPEG_L1: - case HPI_FORMAT_MPEG_L2: - case HPI_FORMAT_MPEG_L3: - fmt.bit_rate = bit_rate; - break; - case HPI_FORMAT_PCM16_SIGNED: - case HPI_FORMAT_PCM16_BIGENDIAN: - fmt.bit_rate = channels * sample_rate * 2; - break; - case HPI_FORMAT_PCM32_SIGNED: - case HPI_FORMAT_PCM32_FLOAT: - fmt.bit_rate = channels * sample_rate * 4; - break; - case HPI_FORMAT_PCM8_UNSIGNED: - fmt.bit_rate = channels * sample_rate; - break; - default: - fmt.bit_rate = 0; - } - - switch (format) { - case HPI_FORMAT_MPEG_L2: - if ((channels == 1) - && (attributes != HPI_MPEG_MODE_DEFAULT)) { - attributes = HPI_MPEG_MODE_DEFAULT; - err = HPI_ERROR_INVALID_FORMAT; - } else if (attributes > HPI_MPEG_MODE_DUALCHANNEL) { - attributes = HPI_MPEG_MODE_DEFAULT; - err = HPI_ERROR_INVALID_FORMAT; - } - fmt.attributes = attributes; - break; - default: - fmt.attributes = attributes; - } - - hpi_msg_to_format(p_format, &fmt); - return err; -} - -u16 hpi_stream_estimate_buffer_size(struct hpi_format *p_format, - u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size) -{ - - u32 bytes_per_second; - u32 size; - u16 channels; - struct hpi_format *pF = p_format; - - channels = pF->channels; - - switch (pF->format) { - case HPI_FORMAT_PCM16_BIGENDIAN: - case HPI_FORMAT_PCM16_SIGNED: - bytes_per_second = pF->sample_rate * 2L * channels; - break; - case HPI_FORMAT_PCM24_SIGNED: - bytes_per_second = pF->sample_rate * 3L * channels; - break; - case HPI_FORMAT_PCM32_SIGNED: - case HPI_FORMAT_PCM32_FLOAT: - bytes_per_second = pF->sample_rate * 4L * channels; - break; - case HPI_FORMAT_PCM8_UNSIGNED: - bytes_per_second = pF->sample_rate * 1L * channels; - break; - case HPI_FORMAT_MPEG_L1: - case HPI_FORMAT_MPEG_L2: - case HPI_FORMAT_MPEG_L3: - bytes_per_second = pF->bit_rate / 8L; - break; - case HPI_FORMAT_DOLBY_AC2: - - bytes_per_second = 256000L / 8L; - break; - default: - return HPI_ERROR_INVALID_FORMAT; - } - size = (bytes_per_second * host_polling_rate_in_milli_seconds * 2) / - 1000L; - - *recommended_buffer_size = - roundup_pow_of_two(((size + 4095L) & ~4095L)); - return 0; -} - -u16 hpi_outstream_open(u16 adapter_index, u16 outstream_index, - u32 *ph_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_OPEN); - hm.adapter_index = adapter_index; - hm.obj_index = outstream_index; - - hpi_send_recv(&hm, &hr); - - if (hr.error == 0) - *ph_outstream = - hpi_indexes_to_handle(HPI_OBJ_OSTREAM, adapter_index, - outstream_index); - else - *ph_outstream = 0; - return hr.error; -} - -u16 hpi_outstream_close(u32 h_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_HOSTBUFFER_FREE); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_GROUP_RESET); - hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index); - hpi_send_recv(&hm, &hr); - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_CLOSE); - hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index); - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_get_info_ex(u32 h_outstream, u16 *pw_state, - u32 *pbuffer_size, u32 *pdata_to_play, u32 *psamples_played, - u32 *pauxiliary_data_to_play) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_GET_INFO); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - if (pw_state) - *pw_state = hr.u.d.u.stream_info.state; - if (pbuffer_size) - *pbuffer_size = hr.u.d.u.stream_info.buffer_size; - if (pdata_to_play) - *pdata_to_play = hr.u.d.u.stream_info.data_available; - if (psamples_played) - *psamples_played = hr.u.d.u.stream_info.samples_transferred; - if (pauxiliary_data_to_play) - *pauxiliary_data_to_play = - hr.u.d.u.stream_info.auxiliary_data_available; - return hr.error; -} - -u16 hpi_outstream_write_buf(u32 h_outstream, const u8 *pb_data, - u32 bytes_to_write, const struct hpi_format *p_format) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_WRITE); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.data.pb_data = (u8 *)pb_data; - hm.u.d.u.data.data_size = bytes_to_write; - - hpi_format_to_msg(&hm.u.d.u.data.format, p_format); - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_start(u32 h_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_START); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_wait_start(u32 h_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_WAIT_START); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_stop(u32 h_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_STOP); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_sinegen(u32 h_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_SINEGEN); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_reset(u32 h_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_RESET); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_query_format(u32 h_outstream, struct hpi_format *p_format) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_QUERY_FORMAT); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_format_to_msg(&hm.u.d.u.data.format, p_format); - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_set_format(u32 h_outstream, struct hpi_format *p_format) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_SET_FORMAT); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_format_to_msg(&hm.u.d.u.data.format, p_format); - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_set_velocity(u32 h_outstream, short velocity) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_SET_VELOCITY); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.velocity = velocity; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_set_punch_in_out(u32 h_outstream, u32 punch_in_sample, - u32 punch_out_sample) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_SET_PUNCHINOUT); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hm.u.d.u.pio.punch_in_sample = punch_in_sample; - hm.u.d.u.pio.punch_out_sample = punch_out_sample; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_ancillary_reset(u32 h_outstream, u16 mode) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_ANC_RESET); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.data.format.channels = mode; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_outstream_ancillary_get_info(u32 h_outstream, u32 *pframes_available) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_ANC_GET_INFO); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - if (hr.error == 0) { - if (pframes_available) - *pframes_available = - hr.u.d.u.stream_info.data_available / - sizeof(struct hpi_anc_frame); - } - return hr.error; -} - -u16 hpi_outstream_ancillary_read(u32 h_outstream, - struct hpi_anc_frame *p_anc_frame_buffer, - u32 anc_frame_buffer_size_in_bytes, - u32 number_of_ancillary_frames_to_read) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_ANC_READ); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer; - hm.u.d.u.data.data_size = - number_of_ancillary_frames_to_read * - sizeof(struct hpi_anc_frame); - if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes) - hpi_send_recv(&hm, &hr); - else - hr.error = HPI_ERROR_INVALID_DATASIZE; - return hr.error; -} - -u16 hpi_outstream_set_time_scale(u32 h_outstream, u32 time_scale) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_SET_TIMESCALE); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hm.u.d.u.time_scale = time_scale; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_outstream_host_buffer_allocate(u32 h_outstream, u32 size_in_bytes) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_HOSTBUFFER_ALLOC); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.data.data_size = size_in_bytes; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer, - struct hpi_hostbuffer_status **pp_status) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_HOSTBUFFER_GET_INFO); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - - if (hr.error == 0) { - if (pp_buffer) - *pp_buffer = hr.u.d.u.hostbuffer_info.p_buffer; - if (pp_status) - *pp_status = hr.u.d.u.hostbuffer_info.p_status; - } - return hr.error; -} - -u16 hpi_outstream_host_buffer_free(u32 h_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_HOSTBUFFER_FREE); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_outstream_group_add(u32 h_outstream, u32 h_stream) -{ - struct hpi_message hm; - struct hpi_response hr; - u16 adapter; - char c_obj_type; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_GROUP_ADD); - - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - if (hpi_handle_indexes(h_stream, &adapter, - &hm.u.d.u.stream.stream_index)) - return HPI_ERROR_INVALID_HANDLE; - - c_obj_type = hpi_handle_object(h_stream); - switch (c_obj_type) { - case HPI_OBJ_OSTREAM: - case HPI_OBJ_ISTREAM: - hm.u.d.u.stream.object_type = c_obj_type; - break; - default: - return HPI_ERROR_INVALID_OBJ; - } - if (adapter != hm.adapter_index) - return HPI_ERROR_NO_INTERADAPTER_GROUPS; - - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_outstream_group_get_map(u32 h_outstream, u32 *poutstream_map, - u32 *pinstream_map) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_GROUP_GETMAP); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - - if (poutstream_map) - *poutstream_map = hr.u.d.u.group_info.outstream_group_map; - if (pinstream_map) - *pinstream_map = hr.u.d.u.group_info.instream_group_map; - - return hr.error; -} - -u16 hpi_outstream_group_reset(u32 h_outstream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_GROUP_RESET); - if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_instream_open(u16 adapter_index, u16 instream_index, u32 *ph_instream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_OPEN); - hm.adapter_index = adapter_index; - hm.obj_index = instream_index; - - hpi_send_recv(&hm, &hr); - - if (hr.error == 0) - *ph_instream = - hpi_indexes_to_handle(HPI_OBJ_ISTREAM, adapter_index, - instream_index); - else - *ph_instream = 0; - - return hr.error; -} - -u16 hpi_instream_close(u32 h_instream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_HOSTBUFFER_FREE); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_GROUP_RESET); - hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index); - hpi_send_recv(&hm, &hr); - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_CLOSE); - hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index); - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_instream_query_format(u32 h_instream, - const struct hpi_format *p_format) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_QUERY_FORMAT); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_format_to_msg(&hm.u.d.u.data.format, p_format); - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_instream_set_format(u32 h_instream, const struct hpi_format *p_format) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_SET_FORMAT); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_format_to_msg(&hm.u.d.u.data.format, p_format); - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_instream_read_buf(u32 h_instream, u8 *pb_data, u32 bytes_to_read) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_READ); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.data.data_size = bytes_to_read; - hm.u.d.u.data.pb_data = pb_data; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_instream_start(u32 h_instream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_START); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_instream_wait_start(u32 h_instream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_WAIT_START); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_instream_stop(u32 h_instream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_STOP); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_instream_reset(u32 h_instream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_RESET); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_instream_get_info_ex(u32 h_instream, u16 *pw_state, u32 *pbuffer_size, - u32 *pdata_recorded, u32 *psamples_recorded, - u32 *pauxiliary_data_recorded) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_GET_INFO); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - - if (pw_state) - *pw_state = hr.u.d.u.stream_info.state; - if (pbuffer_size) - *pbuffer_size = hr.u.d.u.stream_info.buffer_size; - if (pdata_recorded) - *pdata_recorded = hr.u.d.u.stream_info.data_available; - if (psamples_recorded) - *psamples_recorded = hr.u.d.u.stream_info.samples_transferred; - if (pauxiliary_data_recorded) - *pauxiliary_data_recorded = - hr.u.d.u.stream_info.auxiliary_data_available; - return hr.error; -} - -u16 hpi_instream_ancillary_reset(u32 h_instream, u16 bytes_per_frame, - u16 mode, u16 alignment, u16 idle_bit) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_ANC_RESET); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.data.format.attributes = bytes_per_frame; - hm.u.d.u.data.format.format = (mode << 8) | (alignment & 0xff); - hm.u.d.u.data.format.channels = idle_bit; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_instream_ancillary_get_info(u32 h_instream, u32 *pframe_space) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_ANC_GET_INFO); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - if (pframe_space) - *pframe_space = - (hr.u.d.u.stream_info.buffer_size - - hr.u.d.u.stream_info.data_available) / - sizeof(struct hpi_anc_frame); - return hr.error; -} - -u16 hpi_instream_ancillary_write(u32 h_instream, - const struct hpi_anc_frame *p_anc_frame_buffer, - u32 anc_frame_buffer_size_in_bytes, - u32 number_of_ancillary_frames_to_write) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_ANC_WRITE); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer; - hm.u.d.u.data.data_size = - number_of_ancillary_frames_to_write * - sizeof(struct hpi_anc_frame); - if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes) - hpi_send_recv(&hm, &hr); - else - hr.error = HPI_ERROR_INVALID_DATASIZE; - return hr.error; -} - -u16 hpi_instream_host_buffer_allocate(u32 h_instream, u32 size_in_bytes) -{ - - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_HOSTBUFFER_ALLOC); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.d.u.data.data_size = size_in_bytes; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_instream_host_buffer_get_info(u32 h_instream, u8 **pp_buffer, - struct hpi_hostbuffer_status **pp_status) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_HOSTBUFFER_GET_INFO); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - - if (hr.error == 0) { - if (pp_buffer) - *pp_buffer = hr.u.d.u.hostbuffer_info.p_buffer; - if (pp_status) - *pp_status = hr.u.d.u.hostbuffer_info.p_status; - } - return hr.error; -} - -u16 hpi_instream_host_buffer_free(u32 h_instream) -{ - - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_HOSTBUFFER_FREE); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_instream_group_add(u32 h_instream, u32 h_stream) -{ - struct hpi_message hm; - struct hpi_response hr; - u16 adapter; - char c_obj_type; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_GROUP_ADD); - hr.error = 0; - - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - if (hpi_handle_indexes(h_stream, &adapter, - &hm.u.d.u.stream.stream_index)) - return HPI_ERROR_INVALID_HANDLE; - - c_obj_type = hpi_handle_object(h_stream); - - switch (c_obj_type) { - case HPI_OBJ_OSTREAM: - case HPI_OBJ_ISTREAM: - hm.u.d.u.stream.object_type = c_obj_type; - break; - default: - return HPI_ERROR_INVALID_OBJ; - } - - if (adapter != hm.adapter_index) - return HPI_ERROR_NO_INTERADAPTER_GROUPS; - - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_instream_group_get_map(u32 h_instream, u32 *poutstream_map, - u32 *pinstream_map) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_HOSTBUFFER_FREE); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - - if (poutstream_map) - *poutstream_map = hr.u.d.u.group_info.outstream_group_map; - if (pinstream_map) - *pinstream_map = hr.u.d.u.group_info.instream_group_map; - - return hr.error; -} - -u16 hpi_instream_group_reset(u32 h_instream) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_GROUP_RESET); - if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_mixer_open(u16 adapter_index, u32 *ph_mixer) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN); - hm.adapter_index = adapter_index; - - hpi_send_recv(&hm, &hr); - - if (hr.error == 0) - *ph_mixer = - hpi_indexes_to_handle(HPI_OBJ_MIXER, adapter_index, - 0); - else - *ph_mixer = 0; - return hr.error; -} - -u16 hpi_mixer_close(u32 h_mixer) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE); - if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL)) - return HPI_ERROR_INVALID_HANDLE; - - hpi_send_recv(&hm, &hr); - return hr.error; -} - -u16 hpi_mixer_get_control(u32 h_mixer, u16 src_node_type, - u16 src_node_type_index, u16 dst_node_type, u16 dst_node_type_index, - u16 control_type, u32 *ph_control) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, - HPI_MIXER_GET_CONTROL); - if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.m.node_type1 = src_node_type; - hm.u.m.node_index1 = src_node_type_index; - hm.u.m.node_type2 = dst_node_type; - hm.u.m.node_index2 = dst_node_type_index; - hm.u.m.control_type = control_type; - - hpi_send_recv(&hm, &hr); - - if (hr.error == 0) - *ph_control = - hpi_indexes_to_handle(HPI_OBJ_CONTROL, - hm.adapter_index, hr.u.m.control_index); - else - *ph_control = 0; - return hr.error; -} - -u16 hpi_mixer_get_control_by_index(u32 h_mixer, u16 control_index, - u16 *pw_src_node_type, u16 *pw_src_node_index, u16 *pw_dst_node_type, - u16 *pw_dst_node_index, u16 *pw_control_type, u32 *ph_control) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, - HPI_MIXER_GET_CONTROL_BY_INDEX); - if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.m.control_index = control_index; - hpi_send_recv(&hm, &hr); - - if (pw_src_node_type) { - *pw_src_node_type = - hr.u.m.src_node_type + HPI_SOURCENODE_NONE; - *pw_src_node_index = hr.u.m.src_node_index; - *pw_dst_node_type = hr.u.m.dst_node_type + HPI_DESTNODE_NONE; - *pw_dst_node_index = hr.u.m.dst_node_index; - } - if (pw_control_type) - *pw_control_type = hr.u.m.control_index; - - if (ph_control) { - if (hr.error == 0) - *ph_control = - hpi_indexes_to_handle(HPI_OBJ_CONTROL, - hm.adapter_index, control_index); - else - *ph_control = 0; - } - return hr.error; -} - -u16 hpi_mixer_store(u32 h_mixer, enum HPI_MIXER_STORE_COMMAND command, - u16 index) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_STORE); - if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.mx.store.command = command; - hm.u.mx.store.index = index; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -static -u16 hpi_control_param_set(const u32 h_control, const u16 attrib, - const u32 param1, const u32 param2) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_SET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = attrib; - hm.u.c.param1 = param1; - hm.u.c.param2 = param2; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -static u16 hpi_control_log_set2(u32 h_control, u16 attrib, short sv0, - short sv1) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_SET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = attrib; - hm.u.c.an_log_value[0] = sv0; - hm.u.c.an_log_value[1] = sv1; - hpi_send_recv(&hm, &hr); - return hr.error; -} - -static -u16 hpi_control_param_get(const u32 h_control, const u16 attrib, u32 param1, - u32 param2, u32 *pparam1, u32 *pparam2) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = attrib; - hm.u.c.param1 = param1; - hm.u.c.param2 = param2; - hpi_send_recv(&hm, &hr); - - *pparam1 = hr.u.c.param1; - if (pparam2) - *pparam2 = hr.u.c.param2; - - return hr.error; -} - -#define hpi_control_param1_get(h, a, p1) \ - hpi_control_param_get(h, a, 0, 0, p1, NULL) -#define hpi_control_param2_get(h, a, p1, p2) \ - hpi_control_param_get(h, a, 0, 0, p1, p2) - -static u16 hpi_control_log_get2(u32 h_control, u16 attrib, short *sv0, - short *sv1) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = attrib; - - hpi_send_recv(&hm, &hr); - *sv0 = hr.u.c.an_log_value[0]; - if (sv1) - *sv1 = hr.u.c.an_log_value[1]; - return hr.error; -} - -static -u16 hpi_control_query(const u32 h_control, const u16 attrib, const u32 index, - const u32 param, u32 *psetting) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_INFO); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hm.u.c.attribute = attrib; - hm.u.c.param1 = index; - hm.u.c.param2 = param; - - hpi_send_recv(&hm, &hr); - *psetting = hr.u.c.param1; - - return hr.error; -} - -static u16 hpi_control_get_string(const u32 h_control, const u16 attribute, - char *psz_string, const u32 string_length) -{ - unsigned int sub_string_index = 0, j = 0; - char c = 0; - unsigned int n = 0; - u16 err = 0; - - if ((string_length < 1) || (string_length > 256)) - return HPI_ERROR_INVALID_CONTROL_VALUE; - for (sub_string_index = 0; sub_string_index < string_length; - sub_string_index += 8) { - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, - &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = attribute; - hm.u.c.param1 = sub_string_index; - hm.u.c.param2 = 0; - hpi_send_recv(&hm, &hr); - - if (sub_string_index == 0 - && (hr.u.cu.chars8.remaining_chars + 8) > - string_length) - return HPI_ERROR_INVALID_CONTROL_VALUE; - - if (hr.error) { - err = hr.error; - break; - } - for (j = 0; j < 8; j++) { - c = hr.u.cu.chars8.sz_data[j]; - psz_string[sub_string_index + j] = c; - n++; - if (n >= string_length) { - psz_string[string_length - 1] = 0; - err = HPI_ERROR_INVALID_CONTROL_VALUE; - break; - } - if (c == 0) - break; - } - - if ((hr.u.cu.chars8.remaining_chars == 0) - && ((sub_string_index + j) < string_length) - && (c != 0)) { - c = 0; - psz_string[sub_string_index + j] = c; - } - if (c == 0) - break; - } - return err; -} - -u16 hpi_aesebu_receiver_query_format(const u32 h_aes_rx, const u32 index, - u16 *pw_format) -{ - u32 qr; - u16 err; - - err = hpi_control_query(h_aes_rx, HPI_AESEBURX_FORMAT, index, 0, &qr); - *pw_format = (u16)qr; - return err; -} - -u16 hpi_aesebu_receiver_set_format(u32 h_control, u16 format) -{ - return hpi_control_param_set(h_control, HPI_AESEBURX_FORMAT, format, - 0); -} - -u16 hpi_aesebu_receiver_get_format(u32 h_control, u16 *pw_format) -{ - u16 err; - u32 param; - - err = hpi_control_param1_get(h_control, HPI_AESEBURX_FORMAT, ¶m); - if (!err && pw_format) - *pw_format = (u16)param; - - return err; -} - -u16 hpi_aesebu_receiver_get_sample_rate(u32 h_control, u32 *psample_rate) -{ - return hpi_control_param1_get(h_control, HPI_AESEBURX_SAMPLERATE, - psample_rate); -} - -u16 hpi_aesebu_receiver_get_user_data(u32 h_control, u16 index, u16 *pw_data) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_AESEBURX_USERDATA; - hm.u.c.param1 = index; - - hpi_send_recv(&hm, &hr); - - if (pw_data) - *pw_data = (u16)hr.u.c.param2; - return hr.error; -} - -u16 hpi_aesebu_receiver_get_channel_status(u32 h_control, u16 index, - u16 *pw_data) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_AESEBURX_CHANNELSTATUS; - hm.u.c.param1 = index; - - hpi_send_recv(&hm, &hr); - - if (pw_data) - *pw_data = (u16)hr.u.c.param2; - return hr.error; -} - -u16 hpi_aesebu_receiver_get_error_status(u32 h_control, u16 *pw_error_data) -{ - u32 error_data = 0; - u16 err = 0; - - err = hpi_control_param1_get(h_control, HPI_AESEBURX_ERRORSTATUS, - &error_data); - if (pw_error_data) - *pw_error_data = (u16)error_data; - return err; -} - -u16 hpi_aesebu_transmitter_set_sample_rate(u32 h_control, u32 sample_rate) -{ - return hpi_control_param_set(h_control, HPI_AESEBUTX_SAMPLERATE, - sample_rate, 0); -} - -u16 hpi_aesebu_transmitter_set_user_data(u32 h_control, u16 index, u16 data) -{ - return hpi_control_param_set(h_control, HPI_AESEBUTX_USERDATA, index, - data); -} - -u16 hpi_aesebu_transmitter_set_channel_status(u32 h_control, u16 index, - u16 data) -{ - return hpi_control_param_set(h_control, HPI_AESEBUTX_CHANNELSTATUS, - index, data); -} - -u16 hpi_aesebu_transmitter_get_channel_status(u32 h_control, u16 index, - u16 *pw_data) -{ - return HPI_ERROR_INVALID_OPERATION; -} - -u16 hpi_aesebu_transmitter_query_format(const u32 h_aes_tx, const u32 index, - u16 *pw_format) -{ - u32 qr; - u16 err; - - err = hpi_control_query(h_aes_tx, HPI_AESEBUTX_FORMAT, index, 0, &qr); - *pw_format = (u16)qr; - return err; -} - -u16 hpi_aesebu_transmitter_set_format(u32 h_control, u16 output_format) -{ - return hpi_control_param_set(h_control, HPI_AESEBUTX_FORMAT, - output_format, 0); -} - -u16 hpi_aesebu_transmitter_get_format(u32 h_control, u16 *pw_output_format) -{ - u16 err; - u32 param; - - err = hpi_control_param1_get(h_control, HPI_AESEBUTX_FORMAT, ¶m); - if (!err && pw_output_format) - *pw_output_format = (u16)param; - - return err; -} - -u16 hpi_bitstream_set_clock_edge(u32 h_control, u16 edge_type) -{ - return hpi_control_param_set(h_control, HPI_BITSTREAM_CLOCK_EDGE, - edge_type, 0); -} - -u16 hpi_bitstream_set_data_polarity(u32 h_control, u16 polarity) -{ - return hpi_control_param_set(h_control, HPI_BITSTREAM_DATA_POLARITY, - polarity, 0); -} - -u16 hpi_bitstream_get_activity(u32 h_control, u16 *pw_clk_activity, - u16 *pw_data_activity) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_BITSTREAM_ACTIVITY; - hpi_send_recv(&hm, &hr); - if (pw_clk_activity) - *pw_clk_activity = (u16)hr.u.c.param1; - if (pw_data_activity) - *pw_data_activity = (u16)hr.u.c.param2; - return hr.error; -} - -u16 hpi_channel_mode_query_mode(const u32 h_mode, const u32 index, - u16 *pw_mode) -{ - u32 qr; - u16 err; - - err = hpi_control_query(h_mode, HPI_CHANNEL_MODE_MODE, index, 0, &qr); - *pw_mode = (u16)qr; - return err; -} - -u16 hpi_channel_mode_set(u32 h_control, u16 mode) -{ - return hpi_control_param_set(h_control, HPI_CHANNEL_MODE_MODE, mode, - 0); -} - -u16 hpi_channel_mode_get(u32 h_control, u16 *mode) -{ - u32 mode32 = 0; - u16 err = hpi_control_param1_get(h_control, - HPI_CHANNEL_MODE_MODE, &mode32); - if (mode) - *mode = (u16)mode32; - return err; -} - -u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count, - u8 *pb_data) -{ - struct hpi_msg_cobranet_hmiwrite hm; - struct hpi_response_header hr; - - hpi_init_message_responseV1(&hm.h, sizeof(hm), &hr, sizeof(hr), - HPI_OBJ_CONTROL, HPI_CONTROL_SET_STATE); - - if (hpi_handle_indexes(h_control, &hm.h.adapter_index, - &hm.h.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - if (byte_count > sizeof(hm.bytes)) - return HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL; - - hm.p.attribute = HPI_COBRANET_SET; - hm.p.byte_count = byte_count; - hm.p.hmi_address = hmi_address; - memcpy(hm.bytes, pb_data, byte_count); - hm.h.size = (u16)(sizeof(hm.h) + sizeof(hm.p) + byte_count); - - hpi_send_recvV1(&hm.h, &hr); - return hr.error; -} - -u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count, - u32 *pbyte_count, u8 *pb_data) -{ - struct hpi_msg_cobranet_hmiread hm; - struct hpi_res_cobranet_hmiread hr; - - hpi_init_message_responseV1(&hm.h, sizeof(hm), &hr.h, sizeof(hr), - HPI_OBJ_CONTROL, HPI_CONTROL_GET_STATE); - - if (hpi_handle_indexes(h_control, &hm.h.adapter_index, - &hm.h.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - if (max_byte_count > sizeof(hr.bytes)) - return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; - - hm.p.attribute = HPI_COBRANET_GET; - hm.p.byte_count = max_byte_count; - hm.p.hmi_address = hmi_address; - - hpi_send_recvV1(&hm.h, &hr.h); - - if (!hr.h.error && pb_data) { - if (hr.byte_count > sizeof(hr.bytes)) - - return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; - - *pbyte_count = hr.byte_count; - - if (hr.byte_count < max_byte_count) - max_byte_count = *pbyte_count; - - memcpy(pb_data, hr.bytes, max_byte_count); - } - return hr.h.error; -} - -u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus, - u32 *preadable_size, u32 *pwriteable_size) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hm.u.c.attribute = HPI_COBRANET_GET_STATUS; - - hpi_send_recv(&hm, &hr); - if (!hr.error) { - if (pstatus) - *pstatus = hr.u.cu.cobranet.status.status; - if (preadable_size) - *preadable_size = - hr.u.cu.cobranet.status.readable_size; - if (pwriteable_size) - *pwriteable_size = - hr.u.cu.cobranet.status.writeable_size; - } - return hr.error; -} - -u16 hpi_cobranet_get_ip_address(u32 h_control, u32 *pdw_ip_address) -{ - u32 byte_count; - u32 iP; - u16 err; - - err = hpi_cobranet_hmi_read(h_control, - HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count, - (u8 *)&iP); - - *pdw_ip_address = - ((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP & - 0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8); - - if (err) - *pdw_ip_address = 0; - - return err; - -} - -u16 hpi_cobranet_set_ip_address(u32 h_control, u32 dw_ip_address) -{ - u32 iP; - u16 err; - - iP = ((dw_ip_address & 0xff000000) >> 8) | ((dw_ip_address & - 0x00ff0000) << 8) | ((dw_ip_address & 0x0000ff00) >> - 8) | ((dw_ip_address & 0x000000ff) << 8); - - err = hpi_cobranet_hmi_write(h_control, - HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, (u8 *)&iP); - - return err; - -} - -u16 hpi_cobranet_get_static_ip_address(u32 h_control, u32 *pdw_ip_address) -{ - u32 byte_count; - u32 iP; - u16 err; - err = hpi_cobranet_hmi_read(h_control, - HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, &byte_count, - (u8 *)&iP); - - *pdw_ip_address = - ((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP & - 0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8); - - if (err) - *pdw_ip_address = 0; - - return err; - -} - -u16 hpi_cobranet_set_static_ip_address(u32 h_control, u32 dw_ip_address) -{ - u32 iP; - u16 err; - - iP = ((dw_ip_address & 0xff000000) >> 8) | ((dw_ip_address & - 0x00ff0000) << 8) | ((dw_ip_address & 0x0000ff00) >> - 8) | ((dw_ip_address & 0x000000ff) << 8); - - err = hpi_cobranet_hmi_write(h_control, - HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, (u8 *)&iP); - - return err; - -} - -u16 hpi_cobranet_get_macaddress(u32 h_control, u32 *p_mac_msbs, - u32 *p_mac_lsbs) -{ - u32 byte_count; - u16 err; - u32 mac; - - err = hpi_cobranet_hmi_read(h_control, - HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count, - (u8 *)&mac); - - if (!err) { - *p_mac_msbs = - ((mac & 0xff000000) >> 8) | ((mac & 0x00ff0000) << 8) - | ((mac & 0x0000ff00) >> 8) | ((mac & 0x000000ff) << - 8); - - err = hpi_cobranet_hmi_read(h_control, - HPI_COBRANET_HMI_cobra_if_phy_address + 1, 4, - &byte_count, (u8 *)&mac); - } - - if (!err) { - *p_mac_lsbs = - ((mac & 0xff000000) >> 8) | ((mac & 0x00ff0000) << 8) - | ((mac & 0x0000ff00) >> 8) | ((mac & 0x000000ff) << - 8); - } else { - *p_mac_msbs = 0; - *p_mac_lsbs = 0; - } - - return err; -} - -u16 hpi_compander_set_enable(u32 h_control, u32 enable) -{ - return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable, - 0); -} - -u16 hpi_compander_get_enable(u32 h_control, u32 *enable) -{ - return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable); -} - -u16 hpi_compander_set_makeup_gain(u32 h_control, short makeup_gain0_01dB) -{ - return hpi_control_log_set2(h_control, HPI_COMPANDER_MAKEUPGAIN, - makeup_gain0_01dB, 0); -} - -u16 hpi_compander_get_makeup_gain(u32 h_control, short *makeup_gain0_01dB) -{ - return hpi_control_log_get2(h_control, HPI_COMPANDER_MAKEUPGAIN, - makeup_gain0_01dB, NULL); -} - -u16 hpi_compander_set_attack_time_constant(u32 h_control, unsigned int index, - u32 attack) -{ - return hpi_control_param_set(h_control, HPI_COMPANDER_ATTACK, attack, - index); -} - -u16 hpi_compander_get_attack_time_constant(u32 h_control, unsigned int index, - u32 *attack) -{ - return hpi_control_param_get(h_control, HPI_COMPANDER_ATTACK, 0, - index, attack, NULL); -} - -u16 hpi_compander_set_decay_time_constant(u32 h_control, unsigned int index, - u32 decay) -{ - return hpi_control_param_set(h_control, HPI_COMPANDER_DECAY, decay, - index); -} - -u16 hpi_compander_get_decay_time_constant(u32 h_control, unsigned int index, - u32 *decay) -{ - return hpi_control_param_get(h_control, HPI_COMPANDER_DECAY, 0, index, - decay, NULL); - -} - -u16 hpi_compander_set_threshold(u32 h_control, unsigned int index, - short threshold0_01dB) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_SET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_COMPANDER_THRESHOLD; - hm.u.c.param2 = index; - hm.u.c.an_log_value[0] = threshold0_01dB; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_compander_get_threshold(u32 h_control, unsigned int index, - short *threshold0_01dB) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_COMPANDER_THRESHOLD; - hm.u.c.param2 = index; - - hpi_send_recv(&hm, &hr); - *threshold0_01dB = hr.u.c.an_log_value[0]; - - return hr.error; -} - -u16 hpi_compander_set_ratio(u32 h_control, u32 index, u32 ratio100) -{ - return hpi_control_param_set(h_control, HPI_COMPANDER_RATIO, ratio100, - index); -} - -u16 hpi_compander_get_ratio(u32 h_control, u32 index, u32 *ratio100) -{ - return hpi_control_param_get(h_control, HPI_COMPANDER_RATIO, 0, index, - ratio100, NULL); -} - -u16 hpi_level_query_range(u32 h_control, short *min_gain_01dB, - short *max_gain_01dB, short *step_gain_01dB) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_LEVEL_RANGE; - - hpi_send_recv(&hm, &hr); - if (hr.error) { - hr.u.c.an_log_value[0] = 0; - hr.u.c.an_log_value[1] = 0; - hr.u.c.param1 = 0; - } - if (min_gain_01dB) - *min_gain_01dB = hr.u.c.an_log_value[0]; - if (max_gain_01dB) - *max_gain_01dB = hr.u.c.an_log_value[1]; - if (step_gain_01dB) - *step_gain_01dB = (short)hr.u.c.param1; - return hr.error; -} - -u16 hpi_level_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS] - ) -{ - return hpi_control_log_set2(h_control, HPI_LEVEL_GAIN, - an_gain0_01dB[0], an_gain0_01dB[1]); -} - -u16 hpi_level_get_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS] - ) -{ - return hpi_control_log_get2(h_control, HPI_LEVEL_GAIN, - &an_gain0_01dB[0], &an_gain0_01dB[1]); -} - -u16 hpi_meter_query_channels(const u32 h_meter, u32 *p_channels) -{ - return hpi_control_query(h_meter, HPI_METER_NUM_CHANNELS, 0, 0, - p_channels); -} - -u16 hpi_meter_get_peak(u32 h_control, short an_peakdB[HPI_MAX_CHANNELS] - ) -{ - short i = 0; - - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.obj_index = hm.obj_index; - hm.u.c.attribute = HPI_METER_PEAK; - - hpi_send_recv(&hm, &hr); - - if (!hr.error) - memcpy(an_peakdB, hr.u.c.an_log_value, - sizeof(short) * HPI_MAX_CHANNELS); - else - for (i = 0; i < HPI_MAX_CHANNELS; i++) - an_peakdB[i] = HPI_METER_MINIMUM; - return hr.error; -} - -u16 hpi_meter_get_rms(u32 h_control, short an_rmsdB[HPI_MAX_CHANNELS] - ) -{ - short i = 0; - - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_METER_RMS; - - hpi_send_recv(&hm, &hr); - - if (!hr.error) - memcpy(an_rmsdB, hr.u.c.an_log_value, - sizeof(short) * HPI_MAX_CHANNELS); - else - for (i = 0; i < HPI_MAX_CHANNELS; i++) - an_rmsdB[i] = HPI_METER_MINIMUM; - - return hr.error; -} - -u16 hpi_meter_set_rms_ballistics(u32 h_control, u16 attack, u16 decay) -{ - return hpi_control_param_set(h_control, HPI_METER_RMS_BALLISTICS, - attack, decay); -} - -u16 hpi_meter_get_rms_ballistics(u32 h_control, u16 *pn_attack, u16 *pn_decay) -{ - u32 attack; - u32 decay; - u16 error; - - error = hpi_control_param2_get(h_control, HPI_METER_RMS_BALLISTICS, - &attack, &decay); - - if (pn_attack) - *pn_attack = (unsigned short)attack; - if (pn_decay) - *pn_decay = (unsigned short)decay; - - return error; -} - -u16 hpi_meter_set_peak_ballistics(u32 h_control, u16 attack, u16 decay) -{ - return hpi_control_param_set(h_control, HPI_METER_PEAK_BALLISTICS, - attack, decay); -} - -u16 hpi_meter_get_peak_ballistics(u32 h_control, u16 *pn_attack, - u16 *pn_decay) -{ - u32 attack; - u32 decay; - u16 error; - - error = hpi_control_param2_get(h_control, HPI_METER_PEAK_BALLISTICS, - &attack, &decay); - - if (pn_attack) - *pn_attack = (short)attack; - if (pn_decay) - *pn_decay = (short)decay; - - return error; -} - -u16 hpi_microphone_set_phantom_power(u32 h_control, u16 on_off) -{ - return hpi_control_param_set(h_control, HPI_MICROPHONE_PHANTOM_POWER, - (u32)on_off, 0); -} - -u16 hpi_microphone_get_phantom_power(u32 h_control, u16 *pw_on_off) -{ - u16 error = 0; - u32 on_off = 0; - error = hpi_control_param1_get(h_control, - HPI_MICROPHONE_PHANTOM_POWER, &on_off); - if (pw_on_off) - *pw_on_off = (u16)on_off; - return error; -} - -u16 hpi_multiplexer_set_source(u32 h_control, u16 source_node_type, - u16 source_node_index) -{ - return hpi_control_param_set(h_control, HPI_MULTIPLEXER_SOURCE, - source_node_type, source_node_index); -} - -u16 hpi_multiplexer_get_source(u32 h_control, u16 *source_node_type, - u16 *source_node_index) -{ - u32 node, index; - u16 err = hpi_control_param2_get(h_control, - HPI_MULTIPLEXER_SOURCE, &node, - &index); - if (source_node_type) - *source_node_type = (u16)node; - if (source_node_index) - *source_node_index = (u16)index; - return err; -} - -u16 hpi_multiplexer_query_source(u32 h_control, u16 index, - u16 *source_node_type, u16 *source_node_index) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_MULTIPLEXER_QUERYSOURCE; - hm.u.c.param1 = index; - - hpi_send_recv(&hm, &hr); - - if (source_node_type) - *source_node_type = (u16)hr.u.c.param1; - if (source_node_index) - *source_node_index = (u16)hr.u.c.param2; - return hr.error; -} - -u16 hpi_parametric_eq_get_info(u32 h_control, u16 *pw_number_of_bands, - u16 *pw_on_off) -{ - u32 oB = 0; - u32 oO = 0; - u16 error = 0; - - error = hpi_control_param2_get(h_control, HPI_EQUALIZER_NUM_FILTERS, - &oO, &oB); - if (pw_number_of_bands) - *pw_number_of_bands = (u16)oB; - if (pw_on_off) - *pw_on_off = (u16)oO; - return error; -} - -u16 hpi_parametric_eq_set_state(u32 h_control, u16 on_off) -{ - return hpi_control_param_set(h_control, HPI_EQUALIZER_NUM_FILTERS, - on_off, 0); -} - -u16 hpi_parametric_eq_get_band(u32 h_control, u16 index, u16 *pn_type, - u32 *pfrequency_hz, short *pnQ100, short *pn_gain0_01dB) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_EQUALIZER_FILTER; - hm.u.c.param2 = index; - - hpi_send_recv(&hm, &hr); - - if (pfrequency_hz) - *pfrequency_hz = hr.u.c.param1; - if (pn_type) - *pn_type = (u16)(hr.u.c.param2 >> 16); - if (pnQ100) - *pnQ100 = hr.u.c.an_log_value[1]; - if (pn_gain0_01dB) - *pn_gain0_01dB = hr.u.c.an_log_value[0]; - - return hr.error; -} - -u16 hpi_parametric_eq_set_band(u32 h_control, u16 index, u16 type, - u32 frequency_hz, short q100, short gain0_01dB) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_SET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - hm.u.c.param1 = frequency_hz; - hm.u.c.param2 = (index & 0xFFFFL) + ((u32)type << 16); - hm.u.c.an_log_value[0] = gain0_01dB; - hm.u.c.an_log_value[1] = q100; - hm.u.c.attribute = HPI_EQUALIZER_FILTER; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_parametric_eq_get_coeffs(u32 h_control, u16 index, short coeffs[5] - ) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_EQUALIZER_COEFFICIENTS; - hm.u.c.param2 = index; - - hpi_send_recv(&hm, &hr); - - coeffs[0] = (short)hr.u.c.an_log_value[0]; - coeffs[1] = (short)hr.u.c.an_log_value[1]; - coeffs[2] = (short)hr.u.c.param1; - coeffs[3] = (short)(hr.u.c.param1 >> 16); - coeffs[4] = (short)hr.u.c.param2; - - return hr.error; -} - -u16 hpi_sample_clock_query_source(const u32 h_clock, const u32 index, - u16 *pw_source) -{ - u32 qr; - u16 err; - - err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_SOURCE, index, 0, - &qr); - *pw_source = (u16)qr; - return err; -} - -u16 hpi_sample_clock_set_source(u32 h_control, u16 source) -{ - return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_SOURCE, - source, 0); -} - -u16 hpi_sample_clock_get_source(u32 h_control, u16 *pw_source) -{ - u16 err = 0; - u32 source = 0; - err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SOURCE, - &source); - if (!err) - if (pw_source) - *pw_source = (u16)source; - return err; -} - -u16 hpi_sample_clock_query_source_index(const u32 h_clock, const u32 index, - const u32 source, u16 *pw_source_index) -{ - u32 qr; - u16 err; - - err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_SOURCE_INDEX, index, - source, &qr); - *pw_source_index = (u16)qr; - return err; -} - -u16 hpi_sample_clock_set_source_index(u32 h_control, u16 source_index) -{ - return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_SOURCE_INDEX, - source_index, 0); -} - -u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index) -{ - u16 err = 0; - u32 source_index = 0; - err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SOURCE_INDEX, - &source_index); - if (!err) - if (pw_source_index) - *pw_source_index = (u16)source_index; - return err; -} - -u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index, - u32 *prate) -{ - u16 err; - err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, - index, 0, prate); - - return err; -} - -u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate) -{ - return hpi_control_param_set(h_control, - HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, sample_rate, 0); -} - -u16 hpi_sample_clock_get_local_rate(u32 h_control, u32 *psample_rate) -{ - u16 err = 0; - u32 sample_rate = 0; - err = hpi_control_param1_get(h_control, - HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, &sample_rate); - if (!err) - if (psample_rate) - *psample_rate = sample_rate; - return err; -} - -u16 hpi_sample_clock_get_sample_rate(u32 h_control, u32 *psample_rate) -{ - u16 err = 0; - u32 sample_rate = 0; - err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SAMPLERATE, - &sample_rate); - if (!err) - if (psample_rate) - *psample_rate = sample_rate; - return err; -} - -u16 hpi_sample_clock_set_auto(u32 h_control, u32 enable) -{ - return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_AUTO, enable, - 0); -} - -u16 hpi_sample_clock_get_auto(u32 h_control, u32 *penable) -{ - return hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_AUTO, - penable); -} - -u16 hpi_sample_clock_set_local_rate_lock(u32 h_control, u32 lock) -{ - return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_LOCAL_LOCK, - lock, 0); -} - -u16 hpi_sample_clock_get_local_rate_lock(u32 h_control, u32 *plock) -{ - return hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_LOCAL_LOCK, - plock); -} - -u16 hpi_tone_detector_get_frequency(u32 h_control, u32 index, u32 *frequency) -{ - return hpi_control_param_get(h_control, HPI_TONEDETECTOR_FREQUENCY, - index, 0, frequency, NULL); -} - -u16 hpi_tone_detector_get_state(u32 h_control, u32 *state) -{ - return hpi_control_param1_get(h_control, HPI_TONEDETECTOR_STATE, - state); -} - -u16 hpi_tone_detector_set_enable(u32 h_control, u32 enable) -{ - return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable, - 0); -} - -u16 hpi_tone_detector_get_enable(u32 h_control, u32 *enable) -{ - return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable); -} - -u16 hpi_tone_detector_set_event_enable(u32 h_control, u32 event_enable) -{ - return hpi_control_param_set(h_control, HPI_GENERIC_EVENT_ENABLE, - (u32)event_enable, 0); -} - -u16 hpi_tone_detector_get_event_enable(u32 h_control, u32 *event_enable) -{ - return hpi_control_param1_get(h_control, HPI_GENERIC_EVENT_ENABLE, - event_enable); -} - -u16 hpi_tone_detector_set_threshold(u32 h_control, int threshold) -{ - return hpi_control_param_set(h_control, HPI_TONEDETECTOR_THRESHOLD, - (u32)threshold, 0); -} - -u16 hpi_tone_detector_get_threshold(u32 h_control, int *threshold) -{ - return hpi_control_param1_get(h_control, HPI_TONEDETECTOR_THRESHOLD, - (u32 *)threshold); -} - -u16 hpi_silence_detector_get_state(u32 h_control, u32 *state) -{ - return hpi_control_param1_get(h_control, HPI_SILENCEDETECTOR_STATE, - state); -} - -u16 hpi_silence_detector_set_enable(u32 h_control, u32 enable) -{ - return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable, - 0); -} - -u16 hpi_silence_detector_get_enable(u32 h_control, u32 *enable) -{ - return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable); -} - -u16 hpi_silence_detector_set_event_enable(u32 h_control, u32 event_enable) -{ - return hpi_control_param_set(h_control, HPI_GENERIC_EVENT_ENABLE, - event_enable, 0); -} - -u16 hpi_silence_detector_get_event_enable(u32 h_control, u32 *event_enable) -{ - return hpi_control_param1_get(h_control, HPI_GENERIC_EVENT_ENABLE, - event_enable); -} - -u16 hpi_silence_detector_set_delay(u32 h_control, u32 delay) -{ - return hpi_control_param_set(h_control, HPI_SILENCEDETECTOR_DELAY, - delay, 0); -} - -u16 hpi_silence_detector_get_delay(u32 h_control, u32 *delay) -{ - return hpi_control_param1_get(h_control, HPI_SILENCEDETECTOR_DELAY, - delay); -} - -u16 hpi_silence_detector_set_threshold(u32 h_control, int threshold) -{ - return hpi_control_param_set(h_control, HPI_SILENCEDETECTOR_THRESHOLD, - threshold, 0); -} - -u16 hpi_silence_detector_get_threshold(u32 h_control, int *threshold) -{ - return hpi_control_param1_get(h_control, - HPI_SILENCEDETECTOR_THRESHOLD, (u32 *)threshold); -} - -u16 hpi_tuner_query_band(const u32 h_tuner, const u32 index, u16 *pw_band) -{ - u32 qr; - u16 err; - - err = hpi_control_query(h_tuner, HPI_TUNER_BAND, index, 0, &qr); - *pw_band = (u16)qr; - return err; -} - -u16 hpi_tuner_set_band(u32 h_control, u16 band) -{ - return hpi_control_param_set(h_control, HPI_TUNER_BAND, band, 0); -} - -u16 hpi_tuner_get_band(u32 h_control, u16 *pw_band) -{ - u32 band = 0; - u16 error = 0; - - error = hpi_control_param1_get(h_control, HPI_TUNER_BAND, &band); - if (pw_band) - *pw_band = (u16)band; - return error; -} - -u16 hpi_tuner_query_frequency(const u32 h_tuner, const u32 index, - const u16 band, u32 *pfreq) -{ - return hpi_control_query(h_tuner, HPI_TUNER_FREQ, index, band, pfreq); -} - -u16 hpi_tuner_set_frequency(u32 h_control, u32 freq_ink_hz) -{ - return hpi_control_param_set(h_control, HPI_TUNER_FREQ, freq_ink_hz, - 0); -} - -u16 hpi_tuner_get_frequency(u32 h_control, u32 *pw_freq_ink_hz) -{ - return hpi_control_param1_get(h_control, HPI_TUNER_FREQ, - pw_freq_ink_hz); -} - -u16 hpi_tuner_query_gain(const u32 h_tuner, const u32 index, u16 *pw_gain) -{ - u32 qr; - u16 err; - - err = hpi_control_query(h_tuner, HPI_TUNER_BAND, index, 0, &qr); - *pw_gain = (u16)qr; - return err; -} - -u16 hpi_tuner_set_gain(u32 h_control, short gain) -{ - return hpi_control_param_set(h_control, HPI_TUNER_GAIN, gain, 0); -} - -u16 hpi_tuner_get_gain(u32 h_control, short *pn_gain) -{ - u32 gain = 0; - u16 error = 0; - - error = hpi_control_param1_get(h_control, HPI_TUNER_GAIN, &gain); - if (pn_gain) - *pn_gain = (u16)gain; - return error; -} - -u16 hpi_tuner_get_rf_level(u32 h_control, short *pw_level) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.cu.attribute = HPI_TUNER_LEVEL_AVG; - hpi_send_recv(&hm, &hr); - if (pw_level) - *pw_level = hr.u.cu.tuner.s_level; - return hr.error; -} - -u16 hpi_tuner_get_raw_rf_level(u32 h_control, short *pw_level) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.cu.attribute = HPI_TUNER_LEVEL_RAW; - hpi_send_recv(&hm, &hr); - if (pw_level) - *pw_level = hr.u.cu.tuner.s_level; - return hr.error; -} - -u16 hpi_tuner_query_deemphasis(const u32 h_tuner, const u32 index, - const u16 band, u32 *pdeemphasis) -{ - return hpi_control_query(h_tuner, HPI_TUNER_DEEMPHASIS, index, band, - pdeemphasis); -} - -u16 hpi_tuner_set_deemphasis(u32 h_control, u32 deemphasis) -{ - return hpi_control_param_set(h_control, HPI_TUNER_DEEMPHASIS, - deemphasis, 0); -} - -u16 hpi_tuner_get_deemphasis(u32 h_control, u32 *pdeemphasis) -{ - return hpi_control_param1_get(h_control, HPI_TUNER_DEEMPHASIS, - pdeemphasis); -} - -u16 hpi_tuner_query_program(const u32 h_tuner, u32 *pbitmap_program) -{ - return hpi_control_query(h_tuner, HPI_TUNER_PROGRAM, 0, 0, - pbitmap_program); -} - -u16 hpi_tuner_set_program(u32 h_control, u32 program) -{ - return hpi_control_param_set(h_control, HPI_TUNER_PROGRAM, program, - 0); -} - -u16 hpi_tuner_get_program(u32 h_control, u32 *pprogram) -{ - return hpi_control_param1_get(h_control, HPI_TUNER_PROGRAM, pprogram); -} - -u16 hpi_tuner_get_hd_radio_dsp_version(u32 h_control, char *psz_dsp_version, - const u32 string_size) -{ - return hpi_control_get_string(h_control, - HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size); -} - -u16 hpi_tuner_get_hd_radio_sdk_version(u32 h_control, char *psz_sdk_version, - const u32 string_size) -{ - return hpi_control_get_string(h_control, - HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size); -} - -u16 hpi_tuner_get_status(u32 h_control, u16 *pw_status_mask, u16 *pw_status) -{ - u32 status = 0; - u16 error = 0; - - error = hpi_control_param1_get(h_control, HPI_TUNER_STATUS, &status); - if (pw_status) { - if (!error) { - *pw_status_mask = (u16)(status >> 16); - *pw_status = (u16)(status & 0xFFFF); - } else { - *pw_status_mask = 0; - *pw_status = 0; - } - } - return error; -} - -u16 hpi_tuner_set_mode(u32 h_control, u32 mode, u32 value) -{ - return hpi_control_param_set(h_control, HPI_TUNER_MODE, mode, value); -} - -u16 hpi_tuner_get_mode(u32 h_control, u32 mode, u32 *pn_value) -{ - return hpi_control_param_get(h_control, HPI_TUNER_MODE, mode, 0, - pn_value, NULL); -} - -u16 hpi_tuner_get_hd_radio_signal_quality(u32 h_control, u32 *pquality) -{ - return hpi_control_param1_get(h_control, - HPI_TUNER_HDRADIO_SIGNAL_QUALITY, pquality); -} - -u16 hpi_tuner_get_hd_radio_signal_blend(u32 h_control, u32 *pblend) -{ - return hpi_control_param1_get(h_control, HPI_TUNER_HDRADIO_BLEND, - pblend); -} - -u16 hpi_tuner_set_hd_radio_signal_blend(u32 h_control, const u32 blend) -{ - return hpi_control_param_set(h_control, HPI_TUNER_HDRADIO_BLEND, - blend, 0); -} - -u16 hpi_tuner_get_rds(u32 h_control, char *p_data) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_TUNER_RDS; - hpi_send_recv(&hm, &hr); - if (p_data) { - *(u32 *)&p_data[0] = hr.u.cu.tuner.rds.data[0]; - *(u32 *)&p_data[4] = hr.u.cu.tuner.rds.data[1]; - *(u32 *)&p_data[8] = hr.u.cu.tuner.rds.bLER; - } - return hr.error; -} - -u16 hpi_pad_get_channel_name(u32 h_control, char *psz_string, - const u32 data_length) -{ - return hpi_control_get_string(h_control, HPI_PAD_CHANNEL_NAME, - psz_string, data_length); -} - -u16 hpi_pad_get_artist(u32 h_control, char *psz_string, const u32 data_length) -{ - return hpi_control_get_string(h_control, HPI_PAD_ARTIST, psz_string, - data_length); -} - -u16 hpi_pad_get_title(u32 h_control, char *psz_string, const u32 data_length) -{ - return hpi_control_get_string(h_control, HPI_PAD_TITLE, psz_string, - data_length); -} - -u16 hpi_pad_get_comment(u32 h_control, char *psz_string, - const u32 data_length) -{ - return hpi_control_get_string(h_control, HPI_PAD_COMMENT, psz_string, - data_length); -} - -u16 hpi_pad_get_program_type(u32 h_control, u32 *ppTY) -{ - return hpi_control_param1_get(h_control, HPI_PAD_PROGRAM_TYPE, ppTY); -} - -u16 hpi_pad_get_rdsPI(u32 h_control, u32 *ppI) -{ - return hpi_control_param1_get(h_control, HPI_PAD_PROGRAM_ID, ppI); -} - -u16 hpi_volume_query_channels(const u32 h_volume, u32 *p_channels) -{ - return hpi_control_query(h_volume, HPI_VOLUME_NUM_CHANNELS, 0, 0, - p_channels); -} - -u16 hpi_volume_set_gain(u32 h_control, short an_log_gain[HPI_MAX_CHANNELS] - ) -{ - return hpi_control_log_set2(h_control, HPI_VOLUME_GAIN, - an_log_gain[0], an_log_gain[1]); -} - -u16 hpi_volume_get_gain(u32 h_control, short an_log_gain[HPI_MAX_CHANNELS] - ) -{ - return hpi_control_log_get2(h_control, HPI_VOLUME_GAIN, - &an_log_gain[0], &an_log_gain[1]); -} - -u16 hpi_volume_set_mute(u32 h_control, u32 mute) -{ - return hpi_control_param_set(h_control, HPI_VOLUME_MUTE, mute, 0); -} - -u16 hpi_volume_get_mute(u32 h_control, u32 *mute) -{ - return hpi_control_param1_get(h_control, HPI_VOLUME_MUTE, mute); -} - -u16 hpi_volume_query_range(u32 h_control, short *min_gain_01dB, - short *max_gain_01dB, short *step_gain_01dB) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_VOLUME_RANGE; - - hpi_send_recv(&hm, &hr); - if (hr.error) { - hr.u.c.an_log_value[0] = 0; - hr.u.c.an_log_value[1] = 0; - hr.u.c.param1 = 0; - } - if (min_gain_01dB) - *min_gain_01dB = hr.u.c.an_log_value[0]; - if (max_gain_01dB) - *max_gain_01dB = hr.u.c.an_log_value[1]; - if (step_gain_01dB) - *step_gain_01dB = (short)hr.u.c.param1; - return hr.error; -} - -u16 hpi_volume_auto_fade_profile(u32 h_control, - short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms, - u16 profile) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_SET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - - memcpy(hm.u.c.an_log_value, an_stop_gain0_01dB, - sizeof(short) * HPI_MAX_CHANNELS); - - hm.u.c.attribute = HPI_VOLUME_AUTOFADE; - hm.u.c.param1 = duration_ms; - hm.u.c.param2 = profile; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_volume_auto_fade(u32 h_control, - short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms) -{ - return hpi_volume_auto_fade_profile(h_control, an_stop_gain0_01dB, - duration_ms, HPI_VOLUME_AUTOFADE_LOG); -} - -u16 hpi_volume_query_auto_fade_profile(const u32 h_volume, const u32 i, - u16 *profile) -{ - u16 e; - u32 u; - e = hpi_control_query(h_volume, HPI_VOLUME_AUTOFADE, i, 0, &u); - *profile = (u16)u; - return e; -} - -u16 hpi_vox_set_threshold(u32 h_control, short an_gain0_01dB) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_SET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_VOX_THRESHOLD; - - hm.u.c.an_log_value[0] = an_gain0_01dB; - - hpi_send_recv(&hm, &hr); - - return hr.error; -} - -u16 hpi_vox_get_threshold(u32 h_control, short *an_gain0_01dB) -{ - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, - HPI_CONTROL_GET_STATE); - if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) - return HPI_ERROR_INVALID_HANDLE; - hm.u.c.attribute = HPI_VOX_THRESHOLD; - - hpi_send_recv(&hm, &hr); - - *an_gain0_01dB = hr.u.c.an_log_value[0]; - - return hr.error; -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.c b/ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.c deleted file mode 100644 index 032d563e..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.c +++ /dev/null @@ -1,116 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - - Hardware Programming Interface (HPI) Utility functions. - - (C) Copyright AudioScience Inc. 2007 -*******************************************************************************/ - -#include "hpi_internal.h" -#include "hpimsginit.h" - -/* The actual message size for each object type */ -static u16 msg_size[HPI_OBJ_MAXINDEX + 1] = HPI_MESSAGE_SIZE_BY_OBJECT; -/* The actual response size for each object type */ -static u16 res_size[HPI_OBJ_MAXINDEX + 1] = HPI_RESPONSE_SIZE_BY_OBJECT; -/* Flag to enable alternate message type for SSX2 bypass. */ -static u16 gwSSX2_bypass; - -/** \internal - * initialize the HPI message structure - */ -static void hpi_init_message(struct hpi_message *phm, u16 object, - u16 function) -{ - memset(phm, 0, sizeof(*phm)); - if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) - phm->size = msg_size[object]; - else - phm->size = sizeof(*phm); - - if (gwSSX2_bypass) - phm->type = HPI_TYPE_SSX2BYPASS_MESSAGE; - else - phm->type = HPI_TYPE_REQUEST; - phm->object = object; - phm->function = function; - phm->version = 0; - phm->adapter_index = HPI_ADAPTER_INDEX_INVALID; - /* Expect actual adapter index to be set by caller */ -} - -/** \internal - * initialize the HPI response structure - */ -void hpi_init_response(struct hpi_response *phr, u16 object, u16 function, - u16 error) -{ - memset(phr, 0, sizeof(*phr)); - phr->type = HPI_TYPE_RESPONSE; - if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) - phr->size = res_size[object]; - else - phr->size = sizeof(*phr); - phr->object = object; - phr->function = function; - phr->error = error; - phr->specific_error = 0; - phr->version = 0; -} - -void hpi_init_message_response(struct hpi_message *phm, - struct hpi_response *phr, u16 object, u16 function) -{ - hpi_init_message(phm, object, function); - /* default error return if the response is - not filled in by the callee */ - hpi_init_response(phr, object, function, - HPI_ERROR_PROCESSING_MESSAGE); -} - -static void hpi_init_messageV1(struct hpi_message_header *phm, u16 size, - u16 object, u16 function) -{ - memset(phm, 0, sizeof(*phm)); - if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { - phm->size = size; - phm->type = HPI_TYPE_REQUEST; - phm->object = object; - phm->function = function; - phm->version = 1; - /* Expect adapter index to be set by caller */ - } -} - -void hpi_init_responseV1(struct hpi_response_header *phr, u16 size, - u16 object, u16 function) -{ - memset(phr, 0, sizeof(*phr)); - phr->size = size; - phr->version = 1; - phr->type = HPI_TYPE_RESPONSE; - phr->error = HPI_ERROR_PROCESSING_MESSAGE; -} - -void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size, - struct hpi_response_header *phr, u16 res_size, u16 object, - u16 function) -{ - hpi_init_messageV1(phm, msg_size, object, function); - hpi_init_responseV1(phr, res_size, object, function); -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.h b/ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.h deleted file mode 100644 index 5b48708c..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpimsginit.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - - Hardware Programming Interface (HPI) Utility functions - - (C) Copyright AudioScience Inc. 2007 -*******************************************************************************/ -/* Initialise response headers, or msg/response pairs. -Note that it is valid to just init a response e.g. when a lower level is -preparing a response to a message. -However, when sending a message, a matching response buffer must always be -prepared. -*/ - -#ifndef _HPIMSGINIT_H_ -#define _HPIMSGINIT_H_ - -void hpi_init_response(struct hpi_response *phr, u16 object, u16 function, - u16 error); - -void hpi_init_message_response(struct hpi_message *phm, - struct hpi_response *phr, u16 object, u16 function); - -void hpi_init_responseV1(struct hpi_response_header *phr, u16 size, - u16 object, u16 function); - -void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size, - struct hpi_response_header *phr, u16 res_size, u16 object, - u16 function); - -#endif /* _HPIMSGINIT_H_ */ diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.c b/ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.c deleted file mode 100644 index d4790ddc..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.c +++ /dev/null @@ -1,800 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -Extended Message Function With Response Caching - -(C) Copyright AudioScience Inc. 2002 -*****************************************************************************/ -#define SOURCEFILE_NAME "hpimsgx.c" -#include "hpi_internal.h" -#include "hpi_version.h" -#include "hpimsginit.h" -#include "hpicmn.h" -#include "hpimsgx.h" -#include "hpidebug.h" - -static struct pci_device_id asihpi_pci_tbl[] = { -#include "hpipcida.h" -}; - -static struct hpios_spinlock msgx_lock; - -static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS]; - -static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci - *pci_info) -{ - - int i; - - for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) { - if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID - && asihpi_pci_tbl[i].vendor != - pci_info->pci_dev->vendor) - continue; - if (asihpi_pci_tbl[i].device != PCI_ANY_ID - && asihpi_pci_tbl[i].device != - pci_info->pci_dev->device) - continue; - if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID - && asihpi_pci_tbl[i].subvendor != - pci_info->pci_dev->subsystem_vendor) - continue; - if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID - && asihpi_pci_tbl[i].subdevice != - pci_info->pci_dev->subsystem_device) - continue; - - /* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i, - asihpi_pci_tbl[i].driver_data); */ - return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data; - } - - return NULL; -} - -static inline void hw_entry_point(struct hpi_message *phm, - struct hpi_response *phr) -{ - if ((phm->adapter_index < HPI_MAX_ADAPTERS) - && hpi_entry_points[phm->adapter_index]) - hpi_entry_points[phm->adapter_index] (phm, phr); - else - hpi_init_response(phr, phm->object, phm->function, - HPI_ERROR_PROCESSING_MESSAGE); -} - -static void adapter_open(struct hpi_message *phm, struct hpi_response *phr); -static void adapter_close(struct hpi_message *phm, struct hpi_response *phr); - -static void mixer_open(struct hpi_message *phm, struct hpi_response *phr); -static void mixer_close(struct hpi_message *phm, struct hpi_response *phr); - -static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner); -static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner); -static void instream_open(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner); -static void instream_close(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner); - -static void HPIMSGX__reset(u16 adapter_index); - -static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr); -static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner); - -#ifndef DISABLE_PRAGMA_PACK1 -#pragma pack(push, 1) -#endif - -struct hpi_subsys_response { - struct hpi_response_header h; - struct hpi_subsys_res s; -}; - -struct hpi_adapter_response { - struct hpi_response_header h; - struct hpi_adapter_res a; -}; - -struct hpi_mixer_response { - struct hpi_response_header h; - struct hpi_mixer_res m; -}; - -struct hpi_stream_response { - struct hpi_response_header h; - struct hpi_stream_res d; -}; - -struct adapter_info { - u16 type; - u16 num_instreams; - u16 num_outstreams; -}; - -struct asi_open_state { - int open_flag; - void *h_owner; -}; - -#ifndef DISABLE_PRAGMA_PACK1 -#pragma pack(pop) -#endif - -/* Globals */ -static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS]; - -static struct hpi_stream_response - rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; - -static struct hpi_stream_response - rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; - -static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS]; - -static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS]; - -/* use these to keep track of opens from user mode apps/DLLs */ -static struct asi_open_state - outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; - -static struct asi_open_state - instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS]; - -static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner) -{ - if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID) - HPI_DEBUG_LOG(WARNING, - "suspicious adapter index %d in subsys message 0x%x.\n", - phm->adapter_index, phm->function); - - switch (phm->function) { - case HPI_SUBSYS_GET_VERSION: - hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_GET_VERSION, 0); - phr->u.s.version = HPI_VER >> 8; /* return major.minor */ - phr->u.s.data = HPI_VER; /* return major.minor.release */ - break; - case HPI_SUBSYS_OPEN: - /*do not propagate the message down the chain */ - hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0); - break; - case HPI_SUBSYS_CLOSE: - /*do not propagate the message down the chain */ - hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE, - 0); - HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner); - break; - case HPI_SUBSYS_DRIVER_LOAD: - /* Initialize this module's internal state */ - hpios_msgxlock_init(&msgx_lock); - memset(&hpi_entry_points, 0, sizeof(hpi_entry_points)); - /* Init subsys_findadapters response to no-adapters */ - HPIMSGX__reset(HPIMSGX_ALLADAPTERS); - hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_DRIVER_LOAD, 0); - /* individual HPIs dont implement driver load */ - HPI_COMMON(phm, phr); - break; - case HPI_SUBSYS_DRIVER_UNLOAD: - HPI_COMMON(phm, phr); - HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner); - hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_DRIVER_UNLOAD, 0); - return; - - case HPI_SUBSYS_GET_NUM_ADAPTERS: - case HPI_SUBSYS_GET_ADAPTER: - HPI_COMMON(phm, phr); - break; - - case HPI_SUBSYS_CREATE_ADAPTER: - HPIMSGX__init(phm, phr); - break; - - default: - /* Must explicitly handle every subsys message in this switch */ - hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, - HPI_ERROR_INVALID_FUNC); - break; - } -} - -static void adapter_message(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner) -{ - switch (phm->function) { - case HPI_ADAPTER_OPEN: - adapter_open(phm, phr); - break; - case HPI_ADAPTER_CLOSE: - adapter_close(phm, phr); - break; - case HPI_ADAPTER_DELETE: - HPIMSGX__cleanup(phm->adapter_index, h_owner); - { - struct hpi_message hm; - struct hpi_response hr; - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_CLOSE); - hm.adapter_index = phm->adapter_index; - hw_entry_point(&hm, &hr); - } - hw_entry_point(phm, phr); - break; - - default: - hw_entry_point(phm, phr); - break; - } -} - -static void mixer_message(struct hpi_message *phm, struct hpi_response *phr) -{ - switch (phm->function) { - case HPI_MIXER_OPEN: - mixer_open(phm, phr); - break; - case HPI_MIXER_CLOSE: - mixer_close(phm, phr); - break; - default: - hw_entry_point(phm, phr); - break; - } -} - -static void outstream_message(struct hpi_message *phm, - struct hpi_response *phr, void *h_owner) -{ - if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) { - hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function, - HPI_ERROR_INVALID_OBJ_INDEX); - return; - } - - switch (phm->function) { - case HPI_OSTREAM_OPEN: - outstream_open(phm, phr, h_owner); - break; - case HPI_OSTREAM_CLOSE: - outstream_close(phm, phr, h_owner); - break; - default: - hw_entry_point(phm, phr); - break; - } -} - -static void instream_message(struct hpi_message *phm, - struct hpi_response *phr, void *h_owner) -{ - if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) { - hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function, - HPI_ERROR_INVALID_OBJ_INDEX); - return; - } - - switch (phm->function) { - case HPI_ISTREAM_OPEN: - instream_open(phm, phr, h_owner); - break; - case HPI_ISTREAM_CLOSE: - instream_close(phm, phr, h_owner); - break; - default: - hw_entry_point(phm, phr); - break; - } -} - -/* NOTE: HPI_Message() must be defined in the driver as a wrapper for - * HPI_MessageEx so that functions in hpifunc.c compile. - */ -void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner) -{ - HPI_DEBUG_MESSAGE(DEBUG, phm); - - if (phm->type != HPI_TYPE_REQUEST) { - hpi_init_response(phr, phm->object, phm->function, - HPI_ERROR_INVALID_TYPE); - return; - } - - if (phm->adapter_index >= HPI_MAX_ADAPTERS - && phm->adapter_index != HPIMSGX_ALLADAPTERS) { - hpi_init_response(phr, phm->object, phm->function, - HPI_ERROR_BAD_ADAPTER_NUMBER); - return; - } - - switch (phm->object) { - case HPI_OBJ_SUBSYSTEM: - subsys_message(phm, phr, h_owner); - break; - - case HPI_OBJ_ADAPTER: - adapter_message(phm, phr, h_owner); - break; - - case HPI_OBJ_MIXER: - mixer_message(phm, phr); - break; - - case HPI_OBJ_OSTREAM: - outstream_message(phm, phr, h_owner); - break; - - case HPI_OBJ_ISTREAM: - instream_message(phm, phr, h_owner); - break; - - default: - hw_entry_point(phm, phr); - break; - } - HPI_DEBUG_RESPONSE(phr); - -} - -static void adapter_open(struct hpi_message *phm, struct hpi_response *phr) -{ - HPI_DEBUG_LOG(VERBOSE, "adapter_open\n"); - memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index], - sizeof(rESP_HPI_ADAPTER_OPEN[0])); -} - -static void adapter_close(struct hpi_message *phm, struct hpi_response *phr) -{ - HPI_DEBUG_LOG(VERBOSE, "adapter_close\n"); - hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0); -} - -static void mixer_open(struct hpi_message *phm, struct hpi_response *phr) -{ - memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index], - sizeof(rESP_HPI_MIXER_OPEN[0])); -} - -static void mixer_close(struct hpi_message *phm, struct hpi_response *phr) -{ - hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0); -} - -static void instream_open(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner) -{ - - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0); - - hpios_msgxlock_lock(&msgx_lock); - - if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag) - phr->error = HPI_ERROR_OBJ_ALREADY_OPEN; - else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index] - [phm->obj_index].h.error) - memcpy(phr, - &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm-> - obj_index], - sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); - else { - instream_user_open[phm->adapter_index][phm-> - obj_index].open_flag = 1; - hpios_msgxlock_unlock(&msgx_lock); - - /* issue a reset */ - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_RESET); - hm.adapter_index = phm->adapter_index; - hm.obj_index = phm->obj_index; - hw_entry_point(&hm, &hr); - - hpios_msgxlock_lock(&msgx_lock); - if (hr.error) { - instream_user_open[phm->adapter_index][phm-> - obj_index].open_flag = 0; - phr->error = hr.error; - } else { - instream_user_open[phm->adapter_index][phm-> - obj_index].open_flag = 1; - instream_user_open[phm->adapter_index][phm-> - obj_index].h_owner = h_owner; - memcpy(phr, - &rESP_HPI_ISTREAM_OPEN[phm->adapter_index] - [phm->obj_index], - sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); - } - } - hpios_msgxlock_unlock(&msgx_lock); -} - -static void instream_close(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner) -{ - - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0); - - hpios_msgxlock_lock(&msgx_lock); - if (h_owner == - instream_user_open[phm->adapter_index][phm-> - obj_index].h_owner) { - /* HPI_DEBUG_LOG(INFO,"closing adapter %d " - "instream %d owned by %p\n", - phm->wAdapterIndex, phm->wObjIndex, hOwner); */ - instream_user_open[phm->adapter_index][phm-> - obj_index].h_owner = NULL; - hpios_msgxlock_unlock(&msgx_lock); - /* issue a reset */ - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_RESET); - hm.adapter_index = phm->adapter_index; - hm.obj_index = phm->obj_index; - hw_entry_point(&hm, &hr); - hpios_msgxlock_lock(&msgx_lock); - if (hr.error) { - instream_user_open[phm->adapter_index][phm-> - obj_index].h_owner = h_owner; - phr->error = hr.error; - } else { - instream_user_open[phm->adapter_index][phm-> - obj_index].open_flag = 0; - instream_user_open[phm->adapter_index][phm-> - obj_index].h_owner = NULL; - } - } else { - HPI_DEBUG_LOG(WARNING, - "%p trying to close %d instream %d owned by %p\n", - h_owner, phm->adapter_index, phm->obj_index, - instream_user_open[phm->adapter_index][phm-> - obj_index].h_owner); - phr->error = HPI_ERROR_OBJ_NOT_OPEN; - } - hpios_msgxlock_unlock(&msgx_lock); -} - -static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner) -{ - - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0); - - hpios_msgxlock_lock(&msgx_lock); - - if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag) - phr->error = HPI_ERROR_OBJ_ALREADY_OPEN; - else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index] - [phm->obj_index].h.error) - memcpy(phr, - &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm-> - obj_index], - sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); - else { - outstream_user_open[phm->adapter_index][phm-> - obj_index].open_flag = 1; - hpios_msgxlock_unlock(&msgx_lock); - - /* issue a reset */ - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_RESET); - hm.adapter_index = phm->adapter_index; - hm.obj_index = phm->obj_index; - hw_entry_point(&hm, &hr); - - hpios_msgxlock_lock(&msgx_lock); - if (hr.error) { - outstream_user_open[phm->adapter_index][phm-> - obj_index].open_flag = 0; - phr->error = hr.error; - } else { - outstream_user_open[phm->adapter_index][phm-> - obj_index].open_flag = 1; - outstream_user_open[phm->adapter_index][phm-> - obj_index].h_owner = h_owner; - memcpy(phr, - &rESP_HPI_OSTREAM_OPEN[phm->adapter_index] - [phm->obj_index], - sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); - } - } - hpios_msgxlock_unlock(&msgx_lock); -} - -static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner) -{ - - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0); - - hpios_msgxlock_lock(&msgx_lock); - - if (h_owner == - outstream_user_open[phm->adapter_index][phm-> - obj_index].h_owner) { - /* HPI_DEBUG_LOG(INFO,"closing adapter %d " - "outstream %d owned by %p\n", - phm->wAdapterIndex, phm->wObjIndex, hOwner); */ - outstream_user_open[phm->adapter_index][phm-> - obj_index].h_owner = NULL; - hpios_msgxlock_unlock(&msgx_lock); - /* issue a reset */ - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_RESET); - hm.adapter_index = phm->adapter_index; - hm.obj_index = phm->obj_index; - hw_entry_point(&hm, &hr); - hpios_msgxlock_lock(&msgx_lock); - if (hr.error) { - outstream_user_open[phm->adapter_index][phm-> - obj_index].h_owner = h_owner; - phr->error = hr.error; - } else { - outstream_user_open[phm->adapter_index][phm-> - obj_index].open_flag = 0; - outstream_user_open[phm->adapter_index][phm-> - obj_index].h_owner = NULL; - } - } else { - HPI_DEBUG_LOG(WARNING, - "%p trying to close %d outstream %d owned by %p\n", - h_owner, phm->adapter_index, phm->obj_index, - outstream_user_open[phm->adapter_index][phm-> - obj_index].h_owner); - phr->error = HPI_ERROR_OBJ_NOT_OPEN; - } - hpios_msgxlock_unlock(&msgx_lock); -} - -static u16 adapter_prepare(u16 adapter) -{ - struct hpi_message hm; - struct hpi_response hr; - - /* Open the adapter and streams */ - u16 i; - - /* call to HPI_ADAPTER_OPEN */ - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_OPEN); - hm.adapter_index = adapter; - hw_entry_point(&hm, &hr); - memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr, - sizeof(rESP_HPI_ADAPTER_OPEN[0])); - if (hr.error) - return hr.error; - - /* call to HPI_ADAPTER_GET_INFO */ - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_GET_INFO); - hm.adapter_index = adapter; - hw_entry_point(&hm, &hr); - if (hr.error) - return hr.error; - - aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams; - aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams; - aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type; - - /* call to HPI_OSTREAM_OPEN */ - for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) { - hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_OPEN); - hm.adapter_index = adapter; - hm.obj_index = i; - hw_entry_point(&hm, &hr); - memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr, - sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); - outstream_user_open[adapter][i].open_flag = 0; - outstream_user_open[adapter][i].h_owner = NULL; - } - - /* call to HPI_ISTREAM_OPEN */ - for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) { - hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_OPEN); - hm.adapter_index = adapter; - hm.obj_index = i; - hw_entry_point(&hm, &hr); - memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr, - sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); - instream_user_open[adapter][i].open_flag = 0; - instream_user_open[adapter][i].h_owner = NULL; - } - - /* call to HPI_MIXER_OPEN */ - hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN); - hm.adapter_index = adapter; - hw_entry_point(&hm, &hr); - memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, - sizeof(rESP_HPI_MIXER_OPEN[0])); - - return 0; -} - -static void HPIMSGX__reset(u16 adapter_index) -{ - int i; - u16 adapter; - struct hpi_response hr; - - if (adapter_index == HPIMSGX_ALLADAPTERS) { - for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) { - - hpi_init_response(&hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER); - memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr, - sizeof(rESP_HPI_ADAPTER_OPEN[adapter])); - - hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN, - HPI_ERROR_INVALID_OBJ); - memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, - sizeof(rESP_HPI_MIXER_OPEN[adapter])); - - for (i = 0; i < HPI_MAX_STREAMS; i++) { - hpi_init_response(&hr, HPI_OBJ_OSTREAM, - HPI_OSTREAM_OPEN, - HPI_ERROR_INVALID_OBJ); - memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], - &hr, - sizeof(rESP_HPI_OSTREAM_OPEN[adapter] - [i])); - hpi_init_response(&hr, HPI_OBJ_ISTREAM, - HPI_ISTREAM_OPEN, - HPI_ERROR_INVALID_OBJ); - memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], - &hr, - sizeof(rESP_HPI_ISTREAM_OPEN[adapter] - [i])); - } - } - } else if (adapter_index < HPI_MAX_ADAPTERS) { - rESP_HPI_ADAPTER_OPEN[adapter_index].h.error = - HPI_ERROR_BAD_ADAPTER; - rESP_HPI_MIXER_OPEN[adapter_index].h.error = - HPI_ERROR_INVALID_OBJ; - for (i = 0; i < HPI_MAX_STREAMS; i++) { - rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error = - HPI_ERROR_INVALID_OBJ; - rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error = - HPI_ERROR_INVALID_OBJ; - } - } -} - -static u16 HPIMSGX__init(struct hpi_message *phm, - /* HPI_SUBSYS_CREATE_ADAPTER structure with */ - /* resource list or NULL=find all */ - struct hpi_response *phr - /* response from HPI_ADAPTER_GET_INFO */ - ) -{ - hpi_handler_func *entry_point_func; - struct hpi_response hr; - - /* Init response here so we can pass in previous adapter list */ - hpi_init_response(&hr, phm->object, phm->function, - HPI_ERROR_INVALID_OBJ); - - entry_point_func = - hpi_lookup_entry_point_function(phm->u.s.resource.r.pci); - - if (entry_point_func) { - HPI_DEBUG_MESSAGE(DEBUG, phm); - entry_point_func(phm, &hr); - } else { - phr->error = HPI_ERROR_PROCESSING_MESSAGE; - return phr->error; - } - if (hr.error == 0) { - /* the adapter was created successfully - save the mapping for future use */ - hpi_entry_points[hr.u.s.adapter_index] = entry_point_func; - /* prepare adapter (pre-open streams etc.) */ - HPI_DEBUG_LOG(DEBUG, - "HPI_SUBSYS_CREATE_ADAPTER successful," - " preparing adapter\n"); - adapter_prepare(hr.u.s.adapter_index); - } - memcpy(phr, &hr, hr.size); - return phr->error; -} - -static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner) -{ - int i, adapter, adapter_limit; - - if (!h_owner) - return; - - if (adapter_index == HPIMSGX_ALLADAPTERS) { - adapter = 0; - adapter_limit = HPI_MAX_ADAPTERS; - } else { - adapter = adapter_index; - adapter_limit = adapter + 1; - } - - for (; adapter < adapter_limit; adapter++) { - /* printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */ - for (i = 0; i < HPI_MAX_STREAMS; i++) { - if (h_owner == - outstream_user_open[adapter][i].h_owner) { - struct hpi_message hm; - struct hpi_response hr; - - HPI_DEBUG_LOG(DEBUG, - "Close adapter %d ostream %d\n", - adapter, i); - - hpi_init_message_response(&hm, &hr, - HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET); - hm.adapter_index = (u16)adapter; - hm.obj_index = (u16)i; - hw_entry_point(&hm, &hr); - - hm.function = HPI_OSTREAM_HOSTBUFFER_FREE; - hw_entry_point(&hm, &hr); - - hm.function = HPI_OSTREAM_GROUP_RESET; - hw_entry_point(&hm, &hr); - - outstream_user_open[adapter][i].open_flag = 0; - outstream_user_open[adapter][i].h_owner = - NULL; - } - if (h_owner == instream_user_open[adapter][i].h_owner) { - struct hpi_message hm; - struct hpi_response hr; - - HPI_DEBUG_LOG(DEBUG, - "Close adapter %d istream %d\n", - adapter, i); - - hpi_init_message_response(&hm, &hr, - HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET); - hm.adapter_index = (u16)adapter; - hm.obj_index = (u16)i; - hw_entry_point(&hm, &hr); - - hm.function = HPI_ISTREAM_HOSTBUFFER_FREE; - hw_entry_point(&hm, &hr); - - hm.function = HPI_ISTREAM_GROUP_RESET; - hw_entry_point(&hm, &hr); - - instream_user_open[adapter][i].open_flag = 0; - instream_user_open[adapter][i].h_owner = NULL; - } - } - } -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.h b/ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.h deleted file mode 100644 index 37f3efd9..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpimsgx.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - - HPI Extended Message Handler Functions - -(C) Copyright AudioScience Inc. 1997-2003 -******************************************************************************/ - -#ifndef _HPIMSGX_H_ -#define _HPIMSGX_H_ - -#include "hpi_internal.h" - -#define HPIMSGX_ALLADAPTERS (0xFFFF) - -void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr, - void *h_owner); - -#define HPI_MESSAGE_LOWER_LAYER hpi_send_recv_ex - -#endif /* _HPIMSGX_H_ */ diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpioctl.c b/ANDROID_3.4.5/sound/pci/asihpi/hpioctl.c deleted file mode 100644 index 60915620..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpioctl.c +++ /dev/null @@ -1,482 +0,0 @@ -/******************************************************************************* - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -Common Linux HPI ioctl and module probe/remove functions -*******************************************************************************/ -#define SOURCEFILE_NAME "hpioctl.c" - -#include "hpi_internal.h" -#include "hpi_version.h" -#include "hpimsginit.h" -#include "hpidebug.h" -#include "hpimsgx.h" -#include "hpioctl.h" -#include "hpicmn.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef MODULE_FIRMWARE -MODULE_FIRMWARE("asihpi/dsp5000.bin"); -MODULE_FIRMWARE("asihpi/dsp6200.bin"); -MODULE_FIRMWARE("asihpi/dsp6205.bin"); -MODULE_FIRMWARE("asihpi/dsp6400.bin"); -MODULE_FIRMWARE("asihpi/dsp6600.bin"); -MODULE_FIRMWARE("asihpi/dsp8700.bin"); -MODULE_FIRMWARE("asihpi/dsp8900.bin"); -#endif - -static int prealloc_stream_buf; -module_param(prealloc_stream_buf, int, S_IRUGO); -MODULE_PARM_DESC(prealloc_stream_buf, - "Preallocate size for per-adapter stream buffer"); - -/* Allow the debug level to be changed after module load. - E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel -*/ -module_param(hpi_debug_level, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(hpi_debug_level, "debug verbosity 0..5"); - -/* List of adapters found */ -static struct hpi_adapter adapters[HPI_MAX_ADAPTERS]; - -/* Wrapper function to HPI_Message to enable dumping of the - message and response types. -*/ -static void hpi_send_recv_f(struct hpi_message *phm, struct hpi_response *phr, - struct file *file) -{ - if ((phm->adapter_index >= HPI_MAX_ADAPTERS) - && (phm->object != HPI_OBJ_SUBSYSTEM)) - phr->error = HPI_ERROR_INVALID_OBJ_INDEX; - else - hpi_send_recv_ex(phm, phr, file); -} - -/* This is called from hpifunc.c functions, called by ALSA - * (or other kernel process) In this case there is no file descriptor - * available for the message cache code - */ -void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr) -{ - hpi_send_recv_f(phm, phr, HOWNER_KERNEL); -} - -EXPORT_SYMBOL(hpi_send_recv); -/* for radio-asihpi */ - -int asihpi_hpi_release(struct file *file) -{ - struct hpi_message hm; - struct hpi_response hr; - -/* HPI_DEBUG_LOG(INFO,"hpi_release file %p, pid %d\n", file, current->pid); */ - /* close the subsystem just in case the application forgot to. */ - hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_CLOSE); - hpi_send_recv_ex(&hm, &hr, file); - return 0; -} - -long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct hpi_ioctl_linux __user *phpi_ioctl_data; - void __user *puhm; - void __user *puhr; - union hpi_message_buffer_v1 *hm; - union hpi_response_buffer_v1 *hr; - u16 res_max_size; - u32 uncopied_bytes; - int err = 0; - - if (cmd != HPI_IOCTL_LINUX) - return -EINVAL; - - hm = kmalloc(sizeof(*hm), GFP_KERNEL); - hr = kmalloc(sizeof(*hr), GFP_KERNEL); - if (!hm || !hr) { - err = -ENOMEM; - goto out; - } - - phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg; - - /* Read the message and response pointers from user space. */ - if (get_user(puhm, &phpi_ioctl_data->phm) - || get_user(puhr, &phpi_ioctl_data->phr)) { - err = -EFAULT; - goto out; - } - - /* Now read the message size and data from user space. */ - if (get_user(hm->h.size, (u16 __user *)puhm)) { - err = -EFAULT; - goto out; - } - if (hm->h.size > sizeof(*hm)) - hm->h.size = sizeof(*hm); - - /* printk(KERN_INFO "message size %d\n", hm->h.wSize); */ - - uncopied_bytes = copy_from_user(hm, puhm, hm->h.size); - if (uncopied_bytes) { - HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes); - err = -EFAULT; - goto out; - } - - if (get_user(res_max_size, (u16 __user *)puhr)) { - err = -EFAULT; - goto out; - } - /* printk(KERN_INFO "user response size %d\n", res_max_size); */ - if (res_max_size < sizeof(struct hpi_response_header)) { - HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size); - err = -EFAULT; - goto out; - } - - switch (hm->h.function) { - case HPI_SUBSYS_CREATE_ADAPTER: - case HPI_ADAPTER_DELETE: - /* Application must not use these functions! */ - hr->h.size = sizeof(hr->h); - hr->h.error = HPI_ERROR_INVALID_OPERATION; - hr->h.function = hm->h.function; - uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); - if (uncopied_bytes) - err = -EFAULT; - else - err = 0; - goto out; - } - - hr->h.size = res_max_size; - if (hm->h.object == HPI_OBJ_SUBSYSTEM) { - hpi_send_recv_f(&hm->m0, &hr->r0, file); - } else { - u16 __user *ptr = NULL; - u32 size = 0; - /* -1=no data 0=read from user mem, 1=write to user mem */ - int wrflag = -1; - struct hpi_adapter *pa = NULL; - - if (hm->h.adapter_index < ARRAY_SIZE(adapters)) - pa = &adapters[hm->h.adapter_index]; - - if (!pa || !pa->adapter || !pa->adapter->type) { - hpi_init_response(&hr->r0, hm->h.object, - hm->h.function, HPI_ERROR_BAD_ADAPTER_NUMBER); - - uncopied_bytes = - copy_to_user(puhr, hr, sizeof(hr->h)); - if (uncopied_bytes) - err = -EFAULT; - else - err = 0; - goto out; - } - - if (mutex_lock_interruptible(&pa->mutex)) { - err = -EINTR; - goto out; - } - - /* Dig out any pointers embedded in the message. */ - switch (hm->h.function) { - case HPI_OSTREAM_WRITE: - case HPI_ISTREAM_READ:{ - /* Yes, sparse, this is correct. */ - ptr = (u16 __user *)hm->m0.u.d.u.data.pb_data; - size = hm->m0.u.d.u.data.data_size; - - /* Allocate buffer according to application request. - ?Is it better to alloc/free for the duration - of the transaction? - */ - if (pa->buffer_size < size) { - HPI_DEBUG_LOG(DEBUG, - "Realloc adapter %d stream " - "buffer from %zd to %d\n", - hm->h.adapter_index, - pa->buffer_size, size); - if (pa->p_buffer) { - pa->buffer_size = 0; - vfree(pa->p_buffer); - } - pa->p_buffer = vmalloc(size); - if (pa->p_buffer) - pa->buffer_size = size; - else { - HPI_DEBUG_LOG(ERROR, - "HPI could not allocate " - "stream buffer size %d\n", - size); - - mutex_unlock(&pa->mutex); - err = -EINVAL; - goto out; - } - } - - hm->m0.u.d.u.data.pb_data = pa->p_buffer; - if (hm->h.function == HPI_ISTREAM_READ) - /* from card, WRITE to user mem */ - wrflag = 1; - else - wrflag = 0; - break; - } - - default: - size = 0; - break; - } - - if (size && (wrflag == 0)) { - uncopied_bytes = - copy_from_user(pa->p_buffer, ptr, size); - if (uncopied_bytes) - HPI_DEBUG_LOG(WARNING, - "Missed %d of %d " - "bytes from user\n", uncopied_bytes, - size); - } - - hpi_send_recv_f(&hm->m0, &hr->r0, file); - - if (size && (wrflag == 1)) { - uncopied_bytes = - copy_to_user(ptr, pa->p_buffer, size); - if (uncopied_bytes) - HPI_DEBUG_LOG(WARNING, - "Missed %d of %d " "bytes to user\n", - uncopied_bytes, size); - } - - mutex_unlock(&pa->mutex); - } - - /* on return response size must be set */ - /*printk(KERN_INFO "response size %d\n", hr->h.wSize); */ - - if (!hr->h.size) { - HPI_DEBUG_LOG(ERROR, "response zero size\n"); - err = -EFAULT; - goto out; - } - - if (hr->h.size > res_max_size) { - HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size, - res_max_size); - hr->h.error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; - hr->h.specific_error = hr->h.size; - hr->h.size = sizeof(hr->h); - } - - uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); - if (uncopied_bytes) { - HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes); - err = -EFAULT; - goto out; - } - -out: - kfree(hm); - kfree(hr); - return err; -} - -int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) -{ - int idx, nm; - int adapter_index; - unsigned int memlen; - struct hpi_message hm; - struct hpi_response hr; - struct hpi_adapter adapter; - struct hpi_pci pci; - - memset(&adapter, 0, sizeof(adapter)); - - dev_printk(KERN_DEBUG, &pci_dev->dev, - "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor, - pci_dev->device, pci_dev->subsystem_vendor, - pci_dev->subsystem_device, pci_dev->devfn); - - if (pci_enable_device(pci_dev) < 0) { - dev_printk(KERN_ERR, &pci_dev->dev, - "pci_enable_device failed, disabling device\n"); - return -EIO; - } - - pci_set_master(pci_dev); /* also sets latency timer if < 16 */ - - hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_CREATE_ADAPTER); - hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, - HPI_ERROR_PROCESSING_MESSAGE); - - hm.adapter_index = HPI_ADAPTER_INDEX_INVALID; - - nm = HPI_MAX_ADAPTER_MEM_SPACES; - - for (idx = 0; idx < nm; idx++) { - HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx, - &pci_dev->resource[idx]); - - if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) { - memlen = pci_resource_len(pci_dev, idx); - pci.ap_mem_base[idx] = - ioremap(pci_resource_start(pci_dev, idx), - memlen); - if (!pci.ap_mem_base[idx]) { - HPI_DEBUG_LOG(ERROR, - "ioremap failed, aborting\n"); - /* unmap previously mapped pci mem space */ - goto err; - } - } - } - - pci.pci_dev = pci_dev; - hm.u.s.resource.bus_type = HPI_BUS_PCI; - hm.u.s.resource.r.pci = &pci; - - /* call CreateAdapterObject on the relevant hpi module */ - hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); - if (hr.error) - goto err; - - adapter_index = hr.u.s.adapter_index; - adapter.adapter = hpi_find_adapter(adapter_index); - - if (prealloc_stream_buf) { - adapter.p_buffer = vmalloc(prealloc_stream_buf); - if (!adapter.p_buffer) { - HPI_DEBUG_LOG(ERROR, - "HPI could not allocate " - "kernel buffer size %d\n", - prealloc_stream_buf); - goto err; - } - } - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_OPEN); - hm.adapter_index = adapter.adapter->index; - hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); - - if (hr.error) - goto err; - - /* WARNING can't init mutex in 'adapter' - * and then copy it to adapters[] ?!?! - */ - adapters[adapter_index] = adapter; - mutex_init(&adapters[adapter_index].mutex); - pci_set_drvdata(pci_dev, &adapters[adapter_index]); - - dev_printk(KERN_INFO, &pci_dev->dev, - "probe succeeded for ASI%04X HPI index %d\n", - adapter.adapter->type, adapter_index); - - return 0; - -err: - for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) { - if (pci.ap_mem_base[idx]) { - iounmap(pci.ap_mem_base[idx]); - pci.ap_mem_base[idx] = NULL; - } - } - - if (adapter.p_buffer) { - adapter.buffer_size = 0; - vfree(adapter.p_buffer); - } - - HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n"); - return -ENODEV; -} - -void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) -{ - int idx; - struct hpi_message hm; - struct hpi_response hr; - struct hpi_adapter *pa; - struct hpi_pci pci; - - pa = pci_get_drvdata(pci_dev); - pci = pa->adapter->pci; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, - HPI_ADAPTER_DELETE); - hm.adapter_index = pa->adapter->index; - hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); - - /* unmap PCI memory space, mapped during device init. */ - for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) { - if (pci.ap_mem_base[idx]) - iounmap(pci.ap_mem_base[idx]); - } - - if (pa->p_buffer) - vfree(pa->p_buffer); - - pci_set_drvdata(pci_dev, NULL); - if (1) - dev_printk(KERN_INFO, &pci_dev->dev, - "remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n", - pci_dev->vendor, pci_dev->device, - pci_dev->subsystem_vendor, pci_dev->subsystem_device, - pci_dev->devfn, pa->adapter->index); - - memset(pa, 0, sizeof(*pa)); -} - -void __init asihpi_init(void) -{ - struct hpi_message hm; - struct hpi_response hr; - - memset(adapters, 0, sizeof(adapters)); - - printk(KERN_INFO "ASIHPI driver " HPI_VER_STRING "\n"); - - hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_DRIVER_LOAD); - hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); -} - -void asihpi_exit(void) -{ - struct hpi_message hm; - struct hpi_response hr; - - hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, - HPI_SUBSYS_DRIVER_UNLOAD); - hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpioctl.h b/ANDROID_3.4.5/sound/pci/asihpi/hpioctl.h deleted file mode 100644 index 2614aff6..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpioctl.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -Linux HPI ioctl, and shared module init functions -*******************************************************************************/ - -int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id); -void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev); -void __init asihpi_init(void); -void __exit asihpi_exit(void); - -int asihpi_hpi_release(struct file *file); - -long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg); - -/* This is called from hpifunc.c functions, called by ALSA - * (or other kernel process) In this case there is no file descriptor - * available for the message cache code - */ -void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr); - -#define HOWNER_KERNEL ((void *)-1) diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpios.c b/ANDROID_3.4.5/sound/pci/asihpi/hpios.c deleted file mode 100644 index 5ef4fe96..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpios.c +++ /dev/null @@ -1,83 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2012 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -HPI Operating System function implementation for Linux - -(C) Copyright AudioScience Inc. 1997-2003 -******************************************************************************/ -#define SOURCEFILE_NAME "hpios.c" -#include "hpi_internal.h" -#include "hpidebug.h" -#include -#include - -void hpios_delay_micro_seconds(u32 num_micro_sec) -{ - if ((usecs_to_jiffies(num_micro_sec) > 1) && !in_interrupt()) { - /* MUST NOT SCHEDULE IN INTERRUPT CONTEXT! */ - schedule_timeout_uninterruptible(usecs_to_jiffies - (num_micro_sec)); - } else if (num_micro_sec <= 2000) - udelay(num_micro_sec); - else - mdelay(num_micro_sec / 1000); - -} - -/** Allocate an area of locked memory for bus master DMA operations. - -If allocation fails, return 1, and *pMemArea.size = 0 -*/ -u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size, - struct pci_dev *pdev) -{ - /*?? any benefit in using managed dmam_alloc_coherent? */ - p_mem_area->vaddr = - dma_alloc_coherent(&pdev->dev, size, &p_mem_area->dma_handle, - GFP_DMA32 | GFP_KERNEL); - - if (p_mem_area->vaddr) { - HPI_DEBUG_LOG(DEBUG, "allocated %d bytes, dma 0x%x vma %p\n", - size, (unsigned int)p_mem_area->dma_handle, - p_mem_area->vaddr); - p_mem_area->pdev = &pdev->dev; - p_mem_area->size = size; - return 0; - } else { - HPI_DEBUG_LOG(WARNING, - "failed to allocate %d bytes locked memory\n", size); - p_mem_area->size = 0; - return 1; - } -} - -u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area) -{ - if (p_mem_area->size) { - dma_free_coherent(p_mem_area->pdev, p_mem_area->size, - p_mem_area->vaddr, p_mem_area->dma_handle); - HPI_DEBUG_LOG(DEBUG, "freed %lu bytes, dma 0x%x vma %p\n", - (unsigned long)p_mem_area->size, - (unsigned int)p_mem_area->dma_handle, - p_mem_area->vaddr); - p_mem_area->size = 0; - return 0; - } else { - return 1; - } -} diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpios.h b/ANDROID_3.4.5/sound/pci/asihpi/hpios.h deleted file mode 100644 index d3fbd0d7..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpios.h +++ /dev/null @@ -1,165 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - -HPI Operating System Specific macros for Linux Kernel driver - -(C) Copyright AudioScience Inc. 1997-2003 -******************************************************************************/ -#ifndef _HPIOS_H_ -#define _HPIOS_H_ - -#undef HPI_OS_LINUX_KERNEL -#define HPI_OS_LINUX_KERNEL - -#define HPI_OS_DEFINED -#define HPI_BUILD_KERNEL_MODE - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define HPI_NO_OS_FILE_OPS - -#ifdef CONFIG_64BIT -#define HPI64BIT -#endif - -/** Details of a memory area allocated with pci_alloc_consistent -Need all info for parameters to pci_free_consistent -*/ -struct consistent_dma_area { - struct device *pdev; - /* looks like dma-mapping dma_devres ?! */ - size_t size; - void *vaddr; - dma_addr_t dma_handle; -}; - -static inline u16 hpios_locked_mem_get_phys_addr(struct consistent_dma_area - *locked_mem_handle, u32 *p_physical_addr) -{ - *p_physical_addr = locked_mem_handle->dma_handle; - return 0; -} - -static inline u16 hpios_locked_mem_get_virt_addr(struct consistent_dma_area - *locked_mem_handle, void **pp_virtual_addr) -{ - *pp_virtual_addr = locked_mem_handle->vaddr; - return 0; -} - -static inline u16 hpios_locked_mem_valid(struct consistent_dma_area - *locked_mem_handle) -{ - return locked_mem_handle->size != 0; -} - -struct hpi_ioctl_linux { - void __user *phm; - void __user *phr; -}; - -/* Conflict?: H is already used by a number of drivers hid, bluetooth hci, - and some sound drivers sb16, hdsp, emu10k. AFAIK 0xFC is ununsed command -*/ -#define HPI_IOCTL_LINUX _IOWR('H', 0xFC, struct hpi_ioctl_linux) - -#define HPI_DEBUG_FLAG_ERROR KERN_ERR -#define HPI_DEBUG_FLAG_WARNING KERN_WARNING -#define HPI_DEBUG_FLAG_NOTICE KERN_NOTICE -#define HPI_DEBUG_FLAG_INFO KERN_INFO -#define HPI_DEBUG_FLAG_DEBUG KERN_DEBUG -#define HPI_DEBUG_FLAG_VERBOSE KERN_DEBUG /* kernel has no verbose */ - -#include - -#define HPI_LOCKING - -struct hpios_spinlock { - spinlock_t lock; /* SEE hpios_spinlock */ - int lock_context; -}; - -/* The reason for all this evilness is that ALSA calls some of a drivers - * operators in atomic context, and some not. But all our functions channel - * through the HPI_Message conduit, so we can't handle the different context - * per function - */ -#define IN_LOCK_BH 1 -#define IN_LOCK_IRQ 0 -static inline void cond_lock(struct hpios_spinlock *l) -{ - if (irqs_disabled()) { - /* NO bh or isr can execute on this processor, - so ordinary lock will do - */ - spin_lock(&((l)->lock)); - l->lock_context = IN_LOCK_IRQ; - } else { - spin_lock_bh(&((l)->lock)); - l->lock_context = IN_LOCK_BH; - } -} - -static inline void cond_unlock(struct hpios_spinlock *l) -{ - if (l->lock_context == IN_LOCK_BH) - spin_unlock_bh(&((l)->lock)); - else - spin_unlock(&((l)->lock)); -} - -#define hpios_msgxlock_init(obj) spin_lock_init(&(obj)->lock) -#define hpios_msgxlock_lock(obj) cond_lock(obj) -#define hpios_msgxlock_unlock(obj) cond_unlock(obj) - -#define hpios_dsplock_init(obj) spin_lock_init(&(obj)->dsp_lock.lock) -#define hpios_dsplock_lock(obj) cond_lock(&(obj)->dsp_lock) -#define hpios_dsplock_unlock(obj) cond_unlock(&(obj)->dsp_lock) - -#ifdef CONFIG_SND_DEBUG -#define HPI_BUILD_DEBUG -#endif - -#define HPI_ALIST_LOCKING -#define hpios_alistlock_init(obj) spin_lock_init(&((obj)->list_lock.lock)) -#define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock)) -#define hpios_alistlock_unlock(obj) spin_unlock(&((obj)->list_lock.lock)) - -struct snd_card; - -/** pci drvdata points to an instance of this struct */ -struct hpi_adapter { - struct hpi_adapter_obj *adapter; - struct snd_card *snd_card; - - /* mutex prevents contention for one card - between multiple user programs (via ioctl) */ - struct mutex mutex; - char *p_buffer; - size_t buffer_size; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/pci/asihpi/hpipcida.h b/ANDROID_3.4.5/sound/pci/asihpi/hpipcida.h deleted file mode 100644 index db570ddf..00000000 --- a/ANDROID_3.4.5/sound/pci/asihpi/hpipcida.h +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - - AudioScience HPI driver - Copyright (C) 1997-2011 AudioScience Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation; - - 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 - - Array initializer for PCI card IDs - -(C) Copyright AudioScience Inc. 1998-2003 -*******************************************************************************/ - -/*NOTE: when adding new lines to this header file - they MUST be grouped by HPI entry point. -*/ - -{ -HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, - HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, - (kernel_ulong_t) HPI_6205} -, { -HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040, - HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, - (kernel_ulong_t) HPI_6000} -, { -0} diff --git a/ANDROID_3.4.5/sound/pci/atiixp.c b/ANDROID_3.4.5/sound/pci/atiixp.c deleted file mode 100644 index 590682f1..00000000 --- a/ANDROID_3.4.5/sound/pci/atiixp.c +++ /dev/null @@ -1,1726 +0,0 @@ -/* - * ALSA driver for ATI IXP 150/200/250/300 AC97 controllers - * - * Copyright (c) 2004 Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("ATI IXP AC97 controller"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250/300/400/600}}"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int ac97_clock = 48000; -static char *ac97_quirk; -static bool spdif_aclink = 1; -static int ac97_codec = -1; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for ATI IXP controller."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for ATI IXP controller."); -module_param(ac97_clock, int, 0444); -MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); -module_param(ac97_quirk, charp, 0444); -MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); -module_param(ac97_codec, int, 0444); -MODULE_PARM_DESC(ac97_codec, "Specify codec instead of probing."); -module_param(spdif_aclink, bool, 0444); -MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); - -/* just for backward compatibility */ -static bool enable; -module_param(enable, bool, 0444); - - -/* - */ - -#define ATI_REG_ISR 0x00 /* interrupt source */ -#define ATI_REG_ISR_IN_XRUN (1U<<0) -#define ATI_REG_ISR_IN_STATUS (1U<<1) -#define ATI_REG_ISR_OUT_XRUN (1U<<2) -#define ATI_REG_ISR_OUT_STATUS (1U<<3) -#define ATI_REG_ISR_SPDF_XRUN (1U<<4) -#define ATI_REG_ISR_SPDF_STATUS (1U<<5) -#define ATI_REG_ISR_PHYS_INTR (1U<<8) -#define ATI_REG_ISR_PHYS_MISMATCH (1U<<9) -#define ATI_REG_ISR_CODEC0_NOT_READY (1U<<10) -#define ATI_REG_ISR_CODEC1_NOT_READY (1U<<11) -#define ATI_REG_ISR_CODEC2_NOT_READY (1U<<12) -#define ATI_REG_ISR_NEW_FRAME (1U<<13) - -#define ATI_REG_IER 0x04 /* interrupt enable */ -#define ATI_REG_IER_IN_XRUN_EN (1U<<0) -#define ATI_REG_IER_IO_STATUS_EN (1U<<1) -#define ATI_REG_IER_OUT_XRUN_EN (1U<<2) -#define ATI_REG_IER_OUT_XRUN_COND (1U<<3) -#define ATI_REG_IER_SPDF_XRUN_EN (1U<<4) -#define ATI_REG_IER_SPDF_STATUS_EN (1U<<5) -#define ATI_REG_IER_PHYS_INTR_EN (1U<<8) -#define ATI_REG_IER_PHYS_MISMATCH_EN (1U<<9) -#define ATI_REG_IER_CODEC0_INTR_EN (1U<<10) -#define ATI_REG_IER_CODEC1_INTR_EN (1U<<11) -#define ATI_REG_IER_CODEC2_INTR_EN (1U<<12) -#define ATI_REG_IER_NEW_FRAME_EN (1U<<13) /* (RO */ -#define ATI_REG_IER_SET_BUS_BUSY (1U<<14) /* (WO) audio is running */ - -#define ATI_REG_CMD 0x08 /* command */ -#define ATI_REG_CMD_POWERDOWN (1U<<0) -#define ATI_REG_CMD_RECEIVE_EN (1U<<1) -#define ATI_REG_CMD_SEND_EN (1U<<2) -#define ATI_REG_CMD_STATUS_MEM (1U<<3) -#define ATI_REG_CMD_SPDF_OUT_EN (1U<<4) -#define ATI_REG_CMD_SPDF_STATUS_MEM (1U<<5) -#define ATI_REG_CMD_SPDF_THRESHOLD (3U<<6) -#define ATI_REG_CMD_SPDF_THRESHOLD_SHIFT 6 -#define ATI_REG_CMD_IN_DMA_EN (1U<<8) -#define ATI_REG_CMD_OUT_DMA_EN (1U<<9) -#define ATI_REG_CMD_SPDF_DMA_EN (1U<<10) -#define ATI_REG_CMD_SPDF_OUT_STOPPED (1U<<11) -#define ATI_REG_CMD_SPDF_CONFIG_MASK (7U<<12) -#define ATI_REG_CMD_SPDF_CONFIG_34 (1U<<12) -#define ATI_REG_CMD_SPDF_CONFIG_78 (2U<<12) -#define ATI_REG_CMD_SPDF_CONFIG_69 (3U<<12) -#define ATI_REG_CMD_SPDF_CONFIG_01 (4U<<12) -#define ATI_REG_CMD_INTERLEAVE_SPDF (1U<<16) -#define ATI_REG_CMD_AUDIO_PRESENT (1U<<20) -#define ATI_REG_CMD_INTERLEAVE_IN (1U<<21) -#define ATI_REG_CMD_INTERLEAVE_OUT (1U<<22) -#define ATI_REG_CMD_LOOPBACK_EN (1U<<23) -#define ATI_REG_CMD_PACKED_DIS (1U<<24) -#define ATI_REG_CMD_BURST_EN (1U<<25) -#define ATI_REG_CMD_PANIC_EN (1U<<26) -#define ATI_REG_CMD_MODEM_PRESENT (1U<<27) -#define ATI_REG_CMD_ACLINK_ACTIVE (1U<<28) -#define ATI_REG_CMD_AC_SOFT_RESET (1U<<29) -#define ATI_REG_CMD_AC_SYNC (1U<<30) -#define ATI_REG_CMD_AC_RESET (1U<<31) - -#define ATI_REG_PHYS_OUT_ADDR 0x0c -#define ATI_REG_PHYS_OUT_CODEC_MASK (3U<<0) -#define ATI_REG_PHYS_OUT_RW (1U<<2) -#define ATI_REG_PHYS_OUT_ADDR_EN (1U<<8) -#define ATI_REG_PHYS_OUT_ADDR_SHIFT 9 -#define ATI_REG_PHYS_OUT_DATA_SHIFT 16 - -#define ATI_REG_PHYS_IN_ADDR 0x10 -#define ATI_REG_PHYS_IN_READ_FLAG (1U<<8) -#define ATI_REG_PHYS_IN_ADDR_SHIFT 9 -#define ATI_REG_PHYS_IN_DATA_SHIFT 16 - -#define ATI_REG_SLOTREQ 0x14 - -#define ATI_REG_COUNTER 0x18 -#define ATI_REG_COUNTER_SLOT (3U<<0) /* slot # */ -#define ATI_REG_COUNTER_BITCLOCK (31U<<8) - -#define ATI_REG_IN_FIFO_THRESHOLD 0x1c - -#define ATI_REG_IN_DMA_LINKPTR 0x20 -#define ATI_REG_IN_DMA_DT_START 0x24 /* RO */ -#define ATI_REG_IN_DMA_DT_NEXT 0x28 /* RO */ -#define ATI_REG_IN_DMA_DT_CUR 0x2c /* RO */ -#define ATI_REG_IN_DMA_DT_SIZE 0x30 - -#define ATI_REG_OUT_DMA_SLOT 0x34 -#define ATI_REG_OUT_DMA_SLOT_BIT(x) (1U << ((x) - 3)) -#define ATI_REG_OUT_DMA_SLOT_MASK 0x1ff -#define ATI_REG_OUT_DMA_THRESHOLD_MASK 0xf800 -#define ATI_REG_OUT_DMA_THRESHOLD_SHIFT 11 - -#define ATI_REG_OUT_DMA_LINKPTR 0x38 -#define ATI_REG_OUT_DMA_DT_START 0x3c /* RO */ -#define ATI_REG_OUT_DMA_DT_NEXT 0x40 /* RO */ -#define ATI_REG_OUT_DMA_DT_CUR 0x44 /* RO */ -#define ATI_REG_OUT_DMA_DT_SIZE 0x48 - -#define ATI_REG_SPDF_CMD 0x4c -#define ATI_REG_SPDF_CMD_LFSR (1U<<4) -#define ATI_REG_SPDF_CMD_SINGLE_CH (1U<<5) -#define ATI_REG_SPDF_CMD_LFSR_ACC (0xff<<8) /* RO */ - -#define ATI_REG_SPDF_DMA_LINKPTR 0x50 -#define ATI_REG_SPDF_DMA_DT_START 0x54 /* RO */ -#define ATI_REG_SPDF_DMA_DT_NEXT 0x58 /* RO */ -#define ATI_REG_SPDF_DMA_DT_CUR 0x5c /* RO */ -#define ATI_REG_SPDF_DMA_DT_SIZE 0x60 - -#define ATI_REG_MODEM_MIRROR 0x7c -#define ATI_REG_AUDIO_MIRROR 0x80 - -#define ATI_REG_6CH_REORDER 0x84 /* reorder slots for 6ch */ -#define ATI_REG_6CH_REORDER_EN (1U<<0) /* 3,4,7,8,6,9 -> 3,4,6,9,7,8 */ - -#define ATI_REG_FIFO_FLUSH 0x88 -#define ATI_REG_FIFO_OUT_FLUSH (1U<<0) -#define ATI_REG_FIFO_IN_FLUSH (1U<<1) - -/* LINKPTR */ -#define ATI_REG_LINKPTR_EN (1U<<0) - -/* [INT|OUT|SPDIF]_DMA_DT_SIZE */ -#define ATI_REG_DMA_DT_SIZE (0xffffU<<0) -#define ATI_REG_DMA_FIFO_USED (0x1fU<<16) -#define ATI_REG_DMA_FIFO_FREE (0x1fU<<21) -#define ATI_REG_DMA_STATE (7U<<26) - - -#define ATI_MAX_DESCRIPTORS 256 /* max number of descriptor packets */ - - -struct atiixp; - -/* - * DMA packate descriptor - */ - -struct atiixp_dma_desc { - u32 addr; /* DMA buffer address */ - u16 status; /* status bits */ - u16 size; /* size of the packet in dwords */ - u32 next; /* address of the next packet descriptor */ -}; - -/* - * stream enum - */ -enum { ATI_DMA_PLAYBACK, ATI_DMA_CAPTURE, ATI_DMA_SPDIF, NUM_ATI_DMAS }; /* DMAs */ -enum { ATI_PCM_OUT, ATI_PCM_IN, ATI_PCM_SPDIF, NUM_ATI_PCMS }; /* AC97 pcm slots */ -enum { ATI_PCMDEV_ANALOG, ATI_PCMDEV_DIGITAL, NUM_ATI_PCMDEVS }; /* pcm devices */ - -#define NUM_ATI_CODECS 3 - - -/* - * constants and callbacks for each DMA type - */ -struct atiixp_dma_ops { - int type; /* ATI_DMA_XXX */ - unsigned int llp_offset; /* LINKPTR offset */ - unsigned int dt_cur; /* DT_CUR offset */ - /* called from open callback */ - void (*enable_dma)(struct atiixp *chip, int on); - /* called from trigger (START/STOP) */ - void (*enable_transfer)(struct atiixp *chip, int on); - /* called from trigger (STOP only) */ - void (*flush_dma)(struct atiixp *chip); -}; - -/* - * DMA stream - */ -struct atiixp_dma { - const struct atiixp_dma_ops *ops; - struct snd_dma_buffer desc_buf; - struct snd_pcm_substream *substream; /* assigned PCM substream */ - unsigned int buf_addr, buf_bytes; /* DMA buffer address, bytes */ - unsigned int period_bytes, periods; - int opened; - int running; - int suspended; - int pcm_open_flag; - int ac97_pcm_type; /* index # of ac97_pcm to access, -1 = not used */ - unsigned int saved_curptr; -}; - -/* - * ATI IXP chip - */ -struct atiixp { - struct snd_card *card; - struct pci_dev *pci; - - unsigned long addr; - void __iomem *remap_addr; - int irq; - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97[NUM_ATI_CODECS]; - - spinlock_t reg_lock; - - struct atiixp_dma dmas[NUM_ATI_DMAS]; - struct ac97_pcm *pcms[NUM_ATI_PCMS]; - struct snd_pcm *pcmdevs[NUM_ATI_PCMDEVS]; - - int max_channels; /* max. channels for PCM out */ - - unsigned int codec_not_ready_bits; /* for codec detection */ - - int spdif_over_aclink; /* passed from the module option */ - struct mutex open_mutex; /* playback open mutex */ -}; - - -/* - */ -static DEFINE_PCI_DEVICE_TABLE(snd_atiixp_ids) = { - { PCI_VDEVICE(ATI, 0x4341), 0 }, /* SB200 */ - { PCI_VDEVICE(ATI, 0x4361), 0 }, /* SB300 */ - { PCI_VDEVICE(ATI, 0x4370), 0 }, /* SB400 */ - { PCI_VDEVICE(ATI, 0x4382), 0 }, /* SB600 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_atiixp_ids); - -static struct snd_pci_quirk atiixp_quirks[] __devinitdata = { - SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0), - SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0), - { } /* terminator */ -}; - -/* - * lowlevel functions - */ - -/* - * update the bits of the given register. - * return 1 if the bits changed. - */ -static int snd_atiixp_update_bits(struct atiixp *chip, unsigned int reg, - unsigned int mask, unsigned int value) -{ - void __iomem *addr = chip->remap_addr + reg; - unsigned int data, old_data; - old_data = data = readl(addr); - data &= ~mask; - data |= value; - if (old_data == data) - return 0; - writel(data, addr); - return 1; -} - -/* - * macros for easy use - */ -#define atiixp_write(chip,reg,value) \ - writel(value, chip->remap_addr + ATI_REG_##reg) -#define atiixp_read(chip,reg) \ - readl(chip->remap_addr + ATI_REG_##reg) -#define atiixp_update(chip,reg,mask,val) \ - snd_atiixp_update_bits(chip, ATI_REG_##reg, mask, val) - -/* - * handling DMA packets - * - * we allocate a linear buffer for the DMA, and split it to each packet. - * in a future version, a scatter-gather buffer should be implemented. - */ - -#define ATI_DESC_LIST_SIZE \ - PAGE_ALIGN(ATI_MAX_DESCRIPTORS * sizeof(struct atiixp_dma_desc)) - -/* - * build packets ring for the given buffer size. - * - * IXP handles the buffer descriptors, which are connected as a linked - * list. although we can change the list dynamically, in this version, - * a static RING of buffer descriptors is used. - * - * the ring is built in this function, and is set up to the hardware. - */ -static int atiixp_build_dma_packets(struct atiixp *chip, struct atiixp_dma *dma, - struct snd_pcm_substream *substream, - unsigned int periods, - unsigned int period_bytes) -{ - unsigned int i; - u32 addr, desc_addr; - unsigned long flags; - - if (periods > ATI_MAX_DESCRIPTORS) - return -ENOMEM; - - if (dma->desc_buf.area == NULL) { - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - ATI_DESC_LIST_SIZE, - &dma->desc_buf) < 0) - return -ENOMEM; - dma->period_bytes = dma->periods = 0; /* clear */ - } - - if (dma->periods == periods && dma->period_bytes == period_bytes) - return 0; - - /* reset DMA before changing the descriptor table */ - spin_lock_irqsave(&chip->reg_lock, flags); - writel(0, chip->remap_addr + dma->ops->llp_offset); - dma->ops->enable_dma(chip, 0); - dma->ops->enable_dma(chip, 1); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - /* fill the entries */ - addr = (u32)substream->runtime->dma_addr; - desc_addr = (u32)dma->desc_buf.addr; - for (i = 0; i < periods; i++) { - struct atiixp_dma_desc *desc; - desc = &((struct atiixp_dma_desc *)dma->desc_buf.area)[i]; - desc->addr = cpu_to_le32(addr); - desc->status = 0; - desc->size = period_bytes >> 2; /* in dwords */ - desc_addr += sizeof(struct atiixp_dma_desc); - if (i == periods - 1) - desc->next = cpu_to_le32((u32)dma->desc_buf.addr); - else - desc->next = cpu_to_le32(desc_addr); - addr += period_bytes; - } - - writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN, - chip->remap_addr + dma->ops->llp_offset); - - dma->period_bytes = period_bytes; - dma->periods = periods; - - return 0; -} - -/* - * remove the ring buffer and release it if assigned - */ -static void atiixp_clear_dma_packets(struct atiixp *chip, struct atiixp_dma *dma, - struct snd_pcm_substream *substream) -{ - if (dma->desc_buf.area) { - writel(0, chip->remap_addr + dma->ops->llp_offset); - snd_dma_free_pages(&dma->desc_buf); - dma->desc_buf.area = NULL; - } -} - -/* - * AC97 interface - */ -static int snd_atiixp_acquire_codec(struct atiixp *chip) -{ - int timeout = 1000; - - while (atiixp_read(chip, PHYS_OUT_ADDR) & ATI_REG_PHYS_OUT_ADDR_EN) { - if (! timeout--) { - snd_printk(KERN_WARNING "atiixp: codec acquire timeout\n"); - return -EBUSY; - } - udelay(1); - } - return 0; -} - -static unsigned short snd_atiixp_codec_read(struct atiixp *chip, unsigned short codec, unsigned short reg) -{ - unsigned int data; - int timeout; - - if (snd_atiixp_acquire_codec(chip) < 0) - return 0xffff; - data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) | - ATI_REG_PHYS_OUT_ADDR_EN | - ATI_REG_PHYS_OUT_RW | - codec; - atiixp_write(chip, PHYS_OUT_ADDR, data); - if (snd_atiixp_acquire_codec(chip) < 0) - return 0xffff; - timeout = 1000; - do { - data = atiixp_read(chip, PHYS_IN_ADDR); - if (data & ATI_REG_PHYS_IN_READ_FLAG) - return data >> ATI_REG_PHYS_IN_DATA_SHIFT; - udelay(1); - } while (--timeout); - /* time out may happen during reset */ - if (reg < 0x7c) - snd_printk(KERN_WARNING "atiixp: codec read timeout (reg %x)\n", reg); - return 0xffff; -} - - -static void snd_atiixp_codec_write(struct atiixp *chip, unsigned short codec, - unsigned short reg, unsigned short val) -{ - unsigned int data; - - if (snd_atiixp_acquire_codec(chip) < 0) - return; - data = ((unsigned int)val << ATI_REG_PHYS_OUT_DATA_SHIFT) | - ((unsigned int)reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) | - ATI_REG_PHYS_OUT_ADDR_EN | codec; - atiixp_write(chip, PHYS_OUT_ADDR, data); -} - - -static unsigned short snd_atiixp_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct atiixp *chip = ac97->private_data; - return snd_atiixp_codec_read(chip, ac97->num, reg); - -} - -static void snd_atiixp_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct atiixp *chip = ac97->private_data; - snd_atiixp_codec_write(chip, ac97->num, reg, val); -} - -/* - * reset AC link - */ -static int snd_atiixp_aclink_reset(struct atiixp *chip) -{ - int timeout; - - /* reset powerdoewn */ - if (atiixp_update(chip, CMD, ATI_REG_CMD_POWERDOWN, 0)) - udelay(10); - - /* perform a software reset */ - atiixp_update(chip, CMD, ATI_REG_CMD_AC_SOFT_RESET, ATI_REG_CMD_AC_SOFT_RESET); - atiixp_read(chip, CMD); - udelay(10); - atiixp_update(chip, CMD, ATI_REG_CMD_AC_SOFT_RESET, 0); - - timeout = 10; - while (! (atiixp_read(chip, CMD) & ATI_REG_CMD_ACLINK_ACTIVE)) { - /* do a hard reset */ - atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET, - ATI_REG_CMD_AC_SYNC); - atiixp_read(chip, CMD); - mdelay(1); - atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); - if (!--timeout) { - snd_printk(KERN_ERR "atiixp: codec reset timeout\n"); - break; - } - } - - /* deassert RESET and assert SYNC to make sure */ - atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET, - ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET); - - return 0; -} - -#ifdef CONFIG_PM -static int snd_atiixp_aclink_down(struct atiixp *chip) -{ - // if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */ - // return -EBUSY; - atiixp_update(chip, CMD, - ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET, - ATI_REG_CMD_POWERDOWN); - return 0; -} -#endif - -/* - * auto-detection of codecs - * - * the IXP chip can generate interrupts for the non-existing codecs. - * NEW_FRAME interrupt is used to make sure that the interrupt is generated - * even if all three codecs are connected. - */ - -#define ALL_CODEC_NOT_READY \ - (ATI_REG_ISR_CODEC0_NOT_READY |\ - ATI_REG_ISR_CODEC1_NOT_READY |\ - ATI_REG_ISR_CODEC2_NOT_READY) -#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME) - -static int __devinit ac97_probing_bugs(struct pci_dev *pci) -{ - const struct snd_pci_quirk *q; - - q = snd_pci_quirk_lookup(pci, atiixp_quirks); - if (q) { - snd_printdd(KERN_INFO "Atiixp quirk for %s. " - "Forcing codec %d\n", q->name, q->value); - return q->value; - } - /* this hardware doesn't need workarounds. Probe for codec */ - return -1; -} - -static int __devinit snd_atiixp_codec_detect(struct atiixp *chip) -{ - int timeout; - - chip->codec_not_ready_bits = 0; - if (ac97_codec == -1) - ac97_codec = ac97_probing_bugs(chip->pci); - if (ac97_codec >= 0) { - chip->codec_not_ready_bits |= - CODEC_CHECK_BITS ^ (1 << (ac97_codec + 10)); - return 0; - } - - atiixp_write(chip, IER, CODEC_CHECK_BITS); - /* wait for the interrupts */ - timeout = 50; - while (timeout-- > 0) { - mdelay(1); - if (chip->codec_not_ready_bits) - break; - } - atiixp_write(chip, IER, 0); /* disable irqs */ - - if ((chip->codec_not_ready_bits & ALL_CODEC_NOT_READY) == ALL_CODEC_NOT_READY) { - snd_printk(KERN_ERR "atiixp: no codec detected!\n"); - return -ENXIO; - } - return 0; -} - - -/* - * enable DMA and irqs - */ -static int snd_atiixp_chip_start(struct atiixp *chip) -{ - unsigned int reg; - - /* set up spdif, enable burst mode */ - reg = atiixp_read(chip, CMD); - reg |= 0x02 << ATI_REG_CMD_SPDF_THRESHOLD_SHIFT; - reg |= ATI_REG_CMD_BURST_EN; - atiixp_write(chip, CMD, reg); - - reg = atiixp_read(chip, SPDF_CMD); - reg &= ~(ATI_REG_SPDF_CMD_LFSR|ATI_REG_SPDF_CMD_SINGLE_CH); - atiixp_write(chip, SPDF_CMD, reg); - - /* clear all interrupt source */ - atiixp_write(chip, ISR, 0xffffffff); - /* enable irqs */ - atiixp_write(chip, IER, - ATI_REG_IER_IO_STATUS_EN | - ATI_REG_IER_IN_XRUN_EN | - ATI_REG_IER_OUT_XRUN_EN | - ATI_REG_IER_SPDF_XRUN_EN | - ATI_REG_IER_SPDF_STATUS_EN); - return 0; -} - - -/* - * disable DMA and IRQs - */ -static int snd_atiixp_chip_stop(struct atiixp *chip) -{ - /* clear interrupt source */ - atiixp_write(chip, ISR, atiixp_read(chip, ISR)); - /* disable irqs */ - atiixp_write(chip, IER, 0); - return 0; -} - - -/* - * PCM section - */ - -/* - * pointer callback simplly reads XXX_DMA_DT_CUR register as the current - * position. when SG-buffer is implemented, the offset must be calculated - * correctly... - */ -static snd_pcm_uframes_t snd_atiixp_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct atiixp_dma *dma = runtime->private_data; - unsigned int curptr; - int timeout = 1000; - - while (timeout--) { - curptr = readl(chip->remap_addr + dma->ops->dt_cur); - if (curptr < dma->buf_addr) - continue; - curptr -= dma->buf_addr; - if (curptr >= dma->buf_bytes) - continue; - return bytes_to_frames(runtime, curptr); - } - snd_printd("atiixp: invalid DMA pointer read 0x%x (buf=%x)\n", - readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr); - return 0; -} - -/* - * XRUN detected, and stop the PCM substream - */ -static void snd_atiixp_xrun_dma(struct atiixp *chip, struct atiixp_dma *dma) -{ - if (! dma->substream || ! dma->running) - return; - snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type); - snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN); -} - -/* - * the period ack. update the substream. - */ -static void snd_atiixp_update_dma(struct atiixp *chip, struct atiixp_dma *dma) -{ - if (! dma->substream || ! dma->running) - return; - snd_pcm_period_elapsed(dma->substream); -} - -/* set BUS_BUSY interrupt bit if any DMA is running */ -/* call with spinlock held */ -static void snd_atiixp_check_bus_busy(struct atiixp *chip) -{ - unsigned int bus_busy; - if (atiixp_read(chip, CMD) & (ATI_REG_CMD_SEND_EN | - ATI_REG_CMD_RECEIVE_EN | - ATI_REG_CMD_SPDF_OUT_EN)) - bus_busy = ATI_REG_IER_SET_BUS_BUSY; - else - bus_busy = 0; - atiixp_update(chip, IER, ATI_REG_IER_SET_BUS_BUSY, bus_busy); -} - -/* common trigger callback - * calling the lowlevel callbacks in it - */ -static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - struct atiixp_dma *dma = substream->runtime->private_data; - int err = 0; - - if (snd_BUG_ON(!dma->ops->enable_transfer || - !dma->ops->flush_dma)) - return -EINVAL; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - dma->ops->enable_transfer(chip, 1); - dma->running = 1; - dma->suspended = 0; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - dma->ops->enable_transfer(chip, 0); - dma->running = 0; - dma->suspended = cmd == SNDRV_PCM_TRIGGER_SUSPEND; - break; - default: - err = -EINVAL; - break; - } - if (! err) { - snd_atiixp_check_bus_busy(chip); - if (cmd == SNDRV_PCM_TRIGGER_STOP) { - dma->ops->flush_dma(chip); - snd_atiixp_check_bus_busy(chip); - } - } - spin_unlock(&chip->reg_lock); - return err; -} - - -/* - * lowlevel callbacks for each DMA type - * - * every callback is supposed to be called in chip->reg_lock spinlock - */ - -/* flush FIFO of analog OUT DMA */ -static void atiixp_out_flush_dma(struct atiixp *chip) -{ - atiixp_write(chip, FIFO_FLUSH, ATI_REG_FIFO_OUT_FLUSH); -} - -/* enable/disable analog OUT DMA */ -static void atiixp_out_enable_dma(struct atiixp *chip, int on) -{ - unsigned int data; - data = atiixp_read(chip, CMD); - if (on) { - if (data & ATI_REG_CMD_OUT_DMA_EN) - return; - atiixp_out_flush_dma(chip); - data |= ATI_REG_CMD_OUT_DMA_EN; - } else - data &= ~ATI_REG_CMD_OUT_DMA_EN; - atiixp_write(chip, CMD, data); -} - -/* start/stop transfer over OUT DMA */ -static void atiixp_out_enable_transfer(struct atiixp *chip, int on) -{ - atiixp_update(chip, CMD, ATI_REG_CMD_SEND_EN, - on ? ATI_REG_CMD_SEND_EN : 0); -} - -/* enable/disable analog IN DMA */ -static void atiixp_in_enable_dma(struct atiixp *chip, int on) -{ - atiixp_update(chip, CMD, ATI_REG_CMD_IN_DMA_EN, - on ? ATI_REG_CMD_IN_DMA_EN : 0); -} - -/* start/stop analog IN DMA */ -static void atiixp_in_enable_transfer(struct atiixp *chip, int on) -{ - if (on) { - unsigned int data = atiixp_read(chip, CMD); - if (! (data & ATI_REG_CMD_RECEIVE_EN)) { - data |= ATI_REG_CMD_RECEIVE_EN; -#if 0 /* FIXME: this causes the endless loop */ - /* wait until slot 3/4 are finished */ - while ((atiixp_read(chip, COUNTER) & - ATI_REG_COUNTER_SLOT) != 5) - ; -#endif - atiixp_write(chip, CMD, data); - } - } else - atiixp_update(chip, CMD, ATI_REG_CMD_RECEIVE_EN, 0); -} - -/* flush FIFO of analog IN DMA */ -static void atiixp_in_flush_dma(struct atiixp *chip) -{ - atiixp_write(chip, FIFO_FLUSH, ATI_REG_FIFO_IN_FLUSH); -} - -/* enable/disable SPDIF OUT DMA */ -static void atiixp_spdif_enable_dma(struct atiixp *chip, int on) -{ - atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_DMA_EN, - on ? ATI_REG_CMD_SPDF_DMA_EN : 0); -} - -/* start/stop SPDIF OUT DMA */ -static void atiixp_spdif_enable_transfer(struct atiixp *chip, int on) -{ - unsigned int data; - data = atiixp_read(chip, CMD); - if (on) - data |= ATI_REG_CMD_SPDF_OUT_EN; - else - data &= ~ATI_REG_CMD_SPDF_OUT_EN; - atiixp_write(chip, CMD, data); -} - -/* flush FIFO of SPDIF OUT DMA */ -static void atiixp_spdif_flush_dma(struct atiixp *chip) -{ - int timeout; - - /* DMA off, transfer on */ - atiixp_spdif_enable_dma(chip, 0); - atiixp_spdif_enable_transfer(chip, 1); - - timeout = 100; - do { - if (! (atiixp_read(chip, SPDF_DMA_DT_SIZE) & ATI_REG_DMA_FIFO_USED)) - break; - udelay(1); - } while (timeout-- > 0); - - atiixp_spdif_enable_transfer(chip, 0); -} - -/* set up slots and formats for SPDIF OUT */ -static int snd_atiixp_spdif_prepare(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - if (chip->spdif_over_aclink) { - unsigned int data; - /* enable slots 10/11 */ - atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_CONFIG_MASK, - ATI_REG_CMD_SPDF_CONFIG_01); - data = atiixp_read(chip, OUT_DMA_SLOT) & ~ATI_REG_OUT_DMA_SLOT_MASK; - data |= ATI_REG_OUT_DMA_SLOT_BIT(10) | - ATI_REG_OUT_DMA_SLOT_BIT(11); - data |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT; - atiixp_write(chip, OUT_DMA_SLOT, data); - atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_OUT, - substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ? - ATI_REG_CMD_INTERLEAVE_OUT : 0); - } else { - atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_CONFIG_MASK, 0); - atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_SPDF, 0); - } - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -/* set up slots and formats for analog OUT */ -static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - unsigned int data; - - spin_lock_irq(&chip->reg_lock); - data = atiixp_read(chip, OUT_DMA_SLOT) & ~ATI_REG_OUT_DMA_SLOT_MASK; - switch (substream->runtime->channels) { - case 8: - data |= ATI_REG_OUT_DMA_SLOT_BIT(10) | - ATI_REG_OUT_DMA_SLOT_BIT(11); - /* fallthru */ - case 6: - data |= ATI_REG_OUT_DMA_SLOT_BIT(7) | - ATI_REG_OUT_DMA_SLOT_BIT(8); - /* fallthru */ - case 4: - data |= ATI_REG_OUT_DMA_SLOT_BIT(6) | - ATI_REG_OUT_DMA_SLOT_BIT(9); - /* fallthru */ - default: - data |= ATI_REG_OUT_DMA_SLOT_BIT(3) | - ATI_REG_OUT_DMA_SLOT_BIT(4); - break; - } - - /* set output threshold */ - data |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT; - atiixp_write(chip, OUT_DMA_SLOT, data); - - atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_OUT, - substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ? - ATI_REG_CMD_INTERLEAVE_OUT : 0); - - /* - * enable 6 channel re-ordering bit if needed - */ - atiixp_update(chip, 6CH_REORDER, ATI_REG_6CH_REORDER_EN, - substream->runtime->channels >= 6 ? ATI_REG_6CH_REORDER_EN: 0); - - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -/* set up slots and formats for analog IN */ -static int snd_atiixp_capture_prepare(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_IN, - substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ? - ATI_REG_CMD_INTERLEAVE_IN : 0); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -/* - * hw_params - allocate the buffer and set up buffer descriptors - */ -static int snd_atiixp_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - struct atiixp_dma *dma = substream->runtime->private_data; - int err; - - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) - return err; - dma->buf_addr = substream->runtime->dma_addr; - dma->buf_bytes = params_buffer_bytes(hw_params); - - err = atiixp_build_dma_packets(chip, dma, substream, - params_periods(hw_params), - params_period_bytes(hw_params)); - if (err < 0) - return err; - - if (dma->ac97_pcm_type >= 0) { - struct ac97_pcm *pcm = chip->pcms[dma->ac97_pcm_type]; - /* PCM is bound to AC97 codec(s) - * set up the AC97 codecs - */ - if (dma->pcm_open_flag) { - snd_ac97_pcm_close(pcm); - dma->pcm_open_flag = 0; - } - err = snd_ac97_pcm_open(pcm, params_rate(hw_params), - params_channels(hw_params), - pcm->r[0].slots); - if (err >= 0) - dma->pcm_open_flag = 1; - } - - return err; -} - -static int snd_atiixp_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - struct atiixp_dma *dma = substream->runtime->private_data; - - if (dma->pcm_open_flag) { - struct ac97_pcm *pcm = chip->pcms[dma->ac97_pcm_type]; - snd_ac97_pcm_close(pcm); - dma->pcm_open_flag = 0; - } - atiixp_clear_dma_packets(chip, dma, substream); - snd_pcm_lib_free_pages(substream); - return 0; -} - - -/* - * pcm hardware definition, identical for all DMA types - */ -static struct snd_pcm_hardware snd_atiixp_pcm_hw = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 256 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 128 * 1024, - .periods_min = 2, - .periods_max = ATI_MAX_DESCRIPTORS, -}; - -static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, - struct atiixp_dma *dma, int pcm_type) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) - return -EINVAL; - - if (dma->opened) - return -EBUSY; - dma->substream = substream; - runtime->hw = snd_atiixp_pcm_hw; - dma->ac97_pcm_type = pcm_type; - if (pcm_type >= 0) { - runtime->hw.rates = chip->pcms[pcm_type]->rates; - snd_pcm_limit_hw_rates(runtime); - } else { - /* direct SPDIF */ - runtime->hw.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; - } - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - runtime->private_data = dma; - - /* enable DMA bits */ - spin_lock_irq(&chip->reg_lock); - dma->ops->enable_dma(chip, 1); - spin_unlock_irq(&chip->reg_lock); - dma->opened = 1; - - return 0; -} - -static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream, - struct atiixp_dma *dma) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - /* disable DMA bits */ - if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) - return -EINVAL; - spin_lock_irq(&chip->reg_lock); - dma->ops->enable_dma(chip, 0); - spin_unlock_irq(&chip->reg_lock); - dma->substream = NULL; - dma->opened = 0; - return 0; -} - -/* - */ -static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - int err; - - mutex_lock(&chip->open_mutex); - err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); - mutex_unlock(&chip->open_mutex); - if (err < 0) - return err; - substream->runtime->hw.channels_max = chip->max_channels; - if (chip->max_channels > 2) - /* channels must be even */ - snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, 2); - return 0; -} - -static int snd_atiixp_playback_close(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); - err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); - mutex_unlock(&chip->open_mutex); - return err; -} - -static int snd_atiixp_capture_open(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE], 1); -} - -static int snd_atiixp_capture_close(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_CAPTURE]); -} - -static int snd_atiixp_spdif_open(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); - if (chip->spdif_over_aclink) /* share DMA_PLAYBACK */ - err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 2); - else - err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_SPDIF], -1); - mutex_unlock(&chip->open_mutex); - return err; -} - -static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream) -{ - struct atiixp *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); - if (chip->spdif_over_aclink) - err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); - else - err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_SPDIF]); - mutex_unlock(&chip->open_mutex); - return err; -} - -/* AC97 playback */ -static struct snd_pcm_ops snd_atiixp_playback_ops = { - .open = snd_atiixp_playback_open, - .close = snd_atiixp_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_atiixp_pcm_hw_params, - .hw_free = snd_atiixp_pcm_hw_free, - .prepare = snd_atiixp_playback_prepare, - .trigger = snd_atiixp_pcm_trigger, - .pointer = snd_atiixp_pcm_pointer, -}; - -/* AC97 capture */ -static struct snd_pcm_ops snd_atiixp_capture_ops = { - .open = snd_atiixp_capture_open, - .close = snd_atiixp_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_atiixp_pcm_hw_params, - .hw_free = snd_atiixp_pcm_hw_free, - .prepare = snd_atiixp_capture_prepare, - .trigger = snd_atiixp_pcm_trigger, - .pointer = snd_atiixp_pcm_pointer, -}; - -/* SPDIF playback */ -static struct snd_pcm_ops snd_atiixp_spdif_ops = { - .open = snd_atiixp_spdif_open, - .close = snd_atiixp_spdif_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_atiixp_pcm_hw_params, - .hw_free = snd_atiixp_pcm_hw_free, - .prepare = snd_atiixp_spdif_prepare, - .trigger = snd_atiixp_pcm_trigger, - .pointer = snd_atiixp_pcm_pointer, -}; - -static struct ac97_pcm atiixp_pcm_defs[] __devinitdata = { - /* front PCM */ - { - .exclusive = 1, - .r = { { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) | - (1 << AC97_SLOT_PCM_CENTER) | - (1 << AC97_SLOT_PCM_SLEFT) | - (1 << AC97_SLOT_PCM_SRIGHT) | - (1 << AC97_SLOT_LFE) - } - } - }, - /* PCM IN #1 */ - { - .stream = 1, - .exclusive = 1, - .r = { { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) - } - } - }, - /* S/PDIF OUT (optional) */ - { - .exclusive = 1, - .spdif = 1, - .r = { { - .slots = (1 << AC97_SLOT_SPDIF_LEFT2) | - (1 << AC97_SLOT_SPDIF_RIGHT2) - } - } - }, -}; - -static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = { - .type = ATI_DMA_PLAYBACK, - .llp_offset = ATI_REG_OUT_DMA_LINKPTR, - .dt_cur = ATI_REG_OUT_DMA_DT_CUR, - .enable_dma = atiixp_out_enable_dma, - .enable_transfer = atiixp_out_enable_transfer, - .flush_dma = atiixp_out_flush_dma, -}; - -static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = { - .type = ATI_DMA_CAPTURE, - .llp_offset = ATI_REG_IN_DMA_LINKPTR, - .dt_cur = ATI_REG_IN_DMA_DT_CUR, - .enable_dma = atiixp_in_enable_dma, - .enable_transfer = atiixp_in_enable_transfer, - .flush_dma = atiixp_in_flush_dma, -}; - -static struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = { - .type = ATI_DMA_SPDIF, - .llp_offset = ATI_REG_SPDF_DMA_LINKPTR, - .dt_cur = ATI_REG_SPDF_DMA_DT_CUR, - .enable_dma = atiixp_spdif_enable_dma, - .enable_transfer = atiixp_spdif_enable_transfer, - .flush_dma = atiixp_spdif_flush_dma, -}; - - -static int __devinit snd_atiixp_pcm_new(struct atiixp *chip) -{ - struct snd_pcm *pcm; - struct snd_ac97_bus *pbus = chip->ac97_bus; - int err, i, num_pcms; - - /* initialize constants */ - chip->dmas[ATI_DMA_PLAYBACK].ops = &snd_atiixp_playback_dma_ops; - chip->dmas[ATI_DMA_CAPTURE].ops = &snd_atiixp_capture_dma_ops; - if (! chip->spdif_over_aclink) - chip->dmas[ATI_DMA_SPDIF].ops = &snd_atiixp_spdif_dma_ops; - - /* assign AC97 pcm */ - if (chip->spdif_over_aclink) - num_pcms = 3; - else - num_pcms = 2; - err = snd_ac97_pcm_assign(pbus, num_pcms, atiixp_pcm_defs); - if (err < 0) - return err; - for (i = 0; i < num_pcms; i++) - chip->pcms[i] = &pbus->pcms[i]; - - chip->max_channels = 2; - if (pbus->pcms[ATI_PCM_OUT].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) { - if (pbus->pcms[ATI_PCM_OUT].r[0].slots & (1 << AC97_SLOT_LFE)) - chip->max_channels = 6; - else - chip->max_channels = 4; - } - - /* PCM #0: analog I/O */ - err = snd_pcm_new(chip->card, "ATI IXP AC97", - ATI_PCMDEV_ANALOG, 1, 1, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_atiixp_capture_ops); - pcm->private_data = chip; - strcpy(pcm->name, "ATI IXP AC97"); - chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - 64*1024, 128*1024); - - /* no SPDIF support on codec? */ - if (chip->pcms[ATI_PCM_SPDIF] && ! chip->pcms[ATI_PCM_SPDIF]->rates) - return 0; - - /* FIXME: non-48k sample rate doesn't work on my test machine with AD1888 */ - if (chip->pcms[ATI_PCM_SPDIF]) - chip->pcms[ATI_PCM_SPDIF]->rates = SNDRV_PCM_RATE_48000; - - /* PCM #1: spdif playback */ - err = snd_pcm_new(chip->card, "ATI IXP IEC958", - ATI_PCMDEV_DIGITAL, 1, 0, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_spdif_ops); - pcm->private_data = chip; - if (chip->spdif_over_aclink) - strcpy(pcm->name, "ATI IXP IEC958 (AC97)"); - else - strcpy(pcm->name, "ATI IXP IEC958 (Direct)"); - chip->pcmdevs[ATI_PCMDEV_DIGITAL] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - 64*1024, 128*1024); - - /* pre-select AC97 SPDIF slots 10/11 */ - for (i = 0; i < NUM_ATI_CODECS; i++) { - if (chip->ac97[i]) - snd_ac97_update_bits(chip->ac97[i], - AC97_EXTENDED_STATUS, - 0x03 << 4, 0x03 << 4); - } - - return 0; -} - - - -/* - * interrupt handler - */ -static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id) -{ - struct atiixp *chip = dev_id; - unsigned int status; - - status = atiixp_read(chip, ISR); - - if (! status) - return IRQ_NONE; - - /* process audio DMA */ - if (status & ATI_REG_ISR_OUT_XRUN) - snd_atiixp_xrun_dma(chip, &chip->dmas[ATI_DMA_PLAYBACK]); - else if (status & ATI_REG_ISR_OUT_STATUS) - snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_PLAYBACK]); - if (status & ATI_REG_ISR_IN_XRUN) - snd_atiixp_xrun_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]); - else if (status & ATI_REG_ISR_IN_STATUS) - snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]); - if (! chip->spdif_over_aclink) { - if (status & ATI_REG_ISR_SPDF_XRUN) - snd_atiixp_xrun_dma(chip, &chip->dmas[ATI_DMA_SPDIF]); - else if (status & ATI_REG_ISR_SPDF_STATUS) - snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_SPDIF]); - } - - /* for codec detection */ - if (status & CODEC_CHECK_BITS) { - unsigned int detected; - detected = status & CODEC_CHECK_BITS; - spin_lock(&chip->reg_lock); - chip->codec_not_ready_bits |= detected; - atiixp_update(chip, IER, detected, 0); /* disable the detected irqs */ - spin_unlock(&chip->reg_lock); - } - - /* ack */ - atiixp_write(chip, ISR, status); - - return IRQ_HANDLED; -} - - -/* - * ac97 mixer section - */ - -static struct ac97_quirk ac97_quirks[] __devinitdata = { - { - .subvendor = 0x103c, - .subdevice = 0x006b, - .name = "HP Pavilion ZV5030US", - .type = AC97_TUNE_MUTE_LED - }, - { - .subvendor = 0x103c, - .subdevice = 0x308b, - .name = "HP nx6125", - .type = AC97_TUNE_MUTE_LED - }, - { - .subvendor = 0x103c, - .subdevice = 0x3091, - .name = "unknown HP", - .type = AC97_TUNE_MUTE_LED - }, - { } /* terminator */ -}; - -static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock, - const char *quirk_override) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int i, err; - int codec_count; - static struct snd_ac97_bus_ops ops = { - .write = snd_atiixp_ac97_write, - .read = snd_atiixp_ac97_read, - }; - static unsigned int codec_skip[NUM_ATI_CODECS] = { - ATI_REG_ISR_CODEC0_NOT_READY, - ATI_REG_ISR_CODEC1_NOT_READY, - ATI_REG_ISR_CODEC2_NOT_READY, - }; - - if (snd_atiixp_codec_detect(chip) < 0) - return -ENXIO; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) - return err; - pbus->clock = clock; - chip->ac97_bus = pbus; - - codec_count = 0; - for (i = 0; i < NUM_ATI_CODECS; i++) { - if (chip->codec_not_ready_bits & codec_skip[i]) - continue; - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.pci = chip->pci; - ac97.num = i; - ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE; - if (! chip->spdif_over_aclink) - ac97.scaps |= AC97_SCAP_NO_SPDIF; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { - chip->ac97[i] = NULL; /* to be sure */ - snd_printdd("atiixp: codec %d not available for audio\n", i); - continue; - } - codec_count++; - } - - if (! codec_count) { - snd_printk(KERN_ERR "atiixp: no codec available\n"); - return -ENODEV; - } - - snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override); - - return 0; -} - - -#ifdef CONFIG_PM -/* - * power management - */ -static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct atiixp *chip = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < NUM_ATI_PCMDEVS; i++) - if (chip->pcmdevs[i]) { - struct atiixp_dma *dma = &chip->dmas[i]; - if (dma->substream && dma->running) - dma->saved_curptr = readl(chip->remap_addr + - dma->ops->dt_cur); - snd_pcm_suspend_all(chip->pcmdevs[i]); - } - for (i = 0; i < NUM_ATI_CODECS; i++) - snd_ac97_suspend(chip->ac97[i]); - snd_atiixp_aclink_down(chip); - snd_atiixp_chip_stop(chip); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_atiixp_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct atiixp *chip = card->private_data; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "atiixp: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_atiixp_aclink_reset(chip); - snd_atiixp_chip_start(chip); - - for (i = 0; i < NUM_ATI_CODECS; i++) - snd_ac97_resume(chip->ac97[i]); - - for (i = 0; i < NUM_ATI_PCMDEVS; i++) - if (chip->pcmdevs[i]) { - struct atiixp_dma *dma = &chip->dmas[i]; - if (dma->substream && dma->suspended) { - dma->ops->enable_dma(chip, 1); - dma->substream->ops->prepare(dma->substream); - writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN, - chip->remap_addr + dma->ops->llp_offset); - writel(dma->saved_curptr, chip->remap_addr + - dma->ops->dt_cur); - } - } - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - - -#ifdef CONFIG_PROC_FS -/* - * proc interface for register dump - */ - -static void snd_atiixp_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct atiixp *chip = entry->private_data; - int i; - - for (i = 0; i < 256; i += 4) - snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i)); -} - -static void __devinit snd_atiixp_proc_init(struct atiixp *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "atiixp", &entry)) - snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); -} -#else /* !CONFIG_PROC_FS */ -#define snd_atiixp_proc_init(chip) -#endif - - -/* - * destructor - */ - -static int snd_atiixp_free(struct atiixp *chip) -{ - if (chip->irq < 0) - goto __hw_end; - snd_atiixp_chip_stop(chip); - - __hw_end: - if (chip->irq >= 0) - free_irq(chip->irq, chip); - if (chip->remap_addr) - iounmap(chip->remap_addr); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_atiixp_dev_free(struct snd_device *device) -{ - struct atiixp *chip = device->device_data; - return snd_atiixp_free(chip); -} - -/* - * constructor for chip instance - */ -static int __devinit snd_atiixp_create(struct snd_card *card, - struct pci_dev *pci, - struct atiixp **r_chip) -{ - static struct snd_device_ops ops = { - .dev_free = snd_atiixp_dev_free, - }; - struct atiixp *chip; - int err; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->open_mutex); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - if ((err = pci_request_regions(pci, "ATI IXP AC97")) < 0) { - pci_disable_device(pci); - kfree(chip); - return err; - } - chip->addr = pci_resource_start(pci, 0); - chip->remap_addr = pci_ioremap_bar(pci, 0); - if (chip->remap_addr == NULL) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); - snd_atiixp_free(chip); - return -EIO; - } - - if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_atiixp_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - pci_set_master(pci); - synchronize_irq(chip->irq); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_atiixp_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *r_chip = chip; - return 0; -} - - -static int __devinit snd_atiixp_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct atiixp *chip; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA"); - strcpy(card->shortname, "ATI IXP"); - if ((err = snd_atiixp_create(card, pci, &chip)) < 0) - goto __error; - card->private_data = chip; - - if ((err = snd_atiixp_aclink_reset(chip)) < 0) - goto __error; - - chip->spdif_over_aclink = spdif_aclink; - - if ((err = snd_atiixp_mixer_new(chip, ac97_clock, ac97_quirk)) < 0) - goto __error; - - if ((err = snd_atiixp_pcm_new(chip)) < 0) - goto __error; - - snd_atiixp_proc_init(chip); - - snd_atiixp_chip_start(chip); - - snprintf(card->longname, sizeof(card->longname), - "%s rev %x with %s at %#lx, irq %i", card->shortname, - pci->revision, - chip->ac97[0] ? snd_ac97_get_short_name(chip->ac97[0]) : "?", - chip->addr, chip->irq); - - if ((err = snd_card_register(card)) < 0) - goto __error; - - pci_set_drvdata(pci, card); - return 0; - - __error: - snd_card_free(card); - return err; -} - -static void __devexit snd_atiixp_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_atiixp_ids, - .probe = snd_atiixp_probe, - .remove = __devexit_p(snd_atiixp_remove), -#ifdef CONFIG_PM - .suspend = snd_atiixp_suspend, - .resume = snd_atiixp_resume, -#endif -}; - - -static int __init alsa_card_atiixp_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_atiixp_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_atiixp_init) -module_exit(alsa_card_atiixp_exit) diff --git a/ANDROID_3.4.5/sound/pci/atiixp_modem.c b/ANDROID_3.4.5/sound/pci/atiixp_modem.c deleted file mode 100644 index 524d35f3..00000000 --- a/ANDROID_3.4.5/sound/pci/atiixp_modem.c +++ /dev/null @@ -1,1357 +0,0 @@ -/* - * ALSA driver for ATI IXP 150/200/250 AC97 modem controllers - * - * Copyright (c) 2004 Takashi Iwai - * - * 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 -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("ATI IXP MC97 controller"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250}}"); - -static int index = -2; /* Exclude the first card */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int ac97_clock = 48000; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for ATI IXP controller."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for ATI IXP controller."); -module_param(ac97_clock, int, 0444); -MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); - -/* just for backward compatibility */ -static bool enable; -module_param(enable, bool, 0444); - - -/* - */ - -#define ATI_REG_ISR 0x00 /* interrupt source */ -#define ATI_REG_ISR_MODEM_IN_XRUN (1U<<0) -#define ATI_REG_ISR_MODEM_IN_STATUS (1U<<1) -#define ATI_REG_ISR_MODEM_OUT1_XRUN (1U<<2) -#define ATI_REG_ISR_MODEM_OUT1_STATUS (1U<<3) -#define ATI_REG_ISR_MODEM_OUT2_XRUN (1U<<4) -#define ATI_REG_ISR_MODEM_OUT2_STATUS (1U<<5) -#define ATI_REG_ISR_MODEM_OUT3_XRUN (1U<<6) -#define ATI_REG_ISR_MODEM_OUT3_STATUS (1U<<7) -#define ATI_REG_ISR_PHYS_INTR (1U<<8) -#define ATI_REG_ISR_PHYS_MISMATCH (1U<<9) -#define ATI_REG_ISR_CODEC0_NOT_READY (1U<<10) -#define ATI_REG_ISR_CODEC1_NOT_READY (1U<<11) -#define ATI_REG_ISR_CODEC2_NOT_READY (1U<<12) -#define ATI_REG_ISR_NEW_FRAME (1U<<13) -#define ATI_REG_ISR_MODEM_GPIO_DATA (1U<<14) - -#define ATI_REG_IER 0x04 /* interrupt enable */ -#define ATI_REG_IER_MODEM_IN_XRUN_EN (1U<<0) -#define ATI_REG_IER_MODEM_STATUS_EN (1U<<1) -#define ATI_REG_IER_MODEM_OUT1_XRUN_EN (1U<<2) -#define ATI_REG_IER_MODEM_OUT2_XRUN_EN (1U<<4) -#define ATI_REG_IER_MODEM_OUT3_XRUN_EN (1U<<6) -#define ATI_REG_IER_PHYS_INTR_EN (1U<<8) -#define ATI_REG_IER_PHYS_MISMATCH_EN (1U<<9) -#define ATI_REG_IER_CODEC0_INTR_EN (1U<<10) -#define ATI_REG_IER_CODEC1_INTR_EN (1U<<11) -#define ATI_REG_IER_CODEC2_INTR_EN (1U<<12) -#define ATI_REG_IER_NEW_FRAME_EN (1U<<13) /* (RO */ -#define ATI_REG_IER_MODEM_GPIO_DATA_EN (1U<<14) /* (WO) modem is running */ -#define ATI_REG_IER_MODEM_SET_BUS_BUSY (1U<<15) - -#define ATI_REG_CMD 0x08 /* command */ -#define ATI_REG_CMD_POWERDOWN (1U<<0) -#define ATI_REG_CMD_MODEM_RECEIVE_EN (1U<<1) /* modem only */ -#define ATI_REG_CMD_MODEM_SEND1_EN (1U<<2) /* modem only */ -#define ATI_REG_CMD_MODEM_SEND2_EN (1U<<3) /* modem only */ -#define ATI_REG_CMD_MODEM_SEND3_EN (1U<<4) /* modem only */ -#define ATI_REG_CMD_MODEM_STATUS_MEM (1U<<5) /* modem only */ -#define ATI_REG_CMD_MODEM_IN_DMA_EN (1U<<8) /* modem only */ -#define ATI_REG_CMD_MODEM_OUT_DMA1_EN (1U<<9) /* modem only */ -#define ATI_REG_CMD_MODEM_OUT_DMA2_EN (1U<<10) /* modem only */ -#define ATI_REG_CMD_MODEM_OUT_DMA3_EN (1U<<11) /* modem only */ -#define ATI_REG_CMD_AUDIO_PRESENT (1U<<20) -#define ATI_REG_CMD_MODEM_GPIO_THRU_DMA (1U<<22) /* modem only */ -#define ATI_REG_CMD_LOOPBACK_EN (1U<<23) -#define ATI_REG_CMD_PACKED_DIS (1U<<24) -#define ATI_REG_CMD_BURST_EN (1U<<25) -#define ATI_REG_CMD_PANIC_EN (1U<<26) -#define ATI_REG_CMD_MODEM_PRESENT (1U<<27) -#define ATI_REG_CMD_ACLINK_ACTIVE (1U<<28) -#define ATI_REG_CMD_AC_SOFT_RESET (1U<<29) -#define ATI_REG_CMD_AC_SYNC (1U<<30) -#define ATI_REG_CMD_AC_RESET (1U<<31) - -#define ATI_REG_PHYS_OUT_ADDR 0x0c -#define ATI_REG_PHYS_OUT_CODEC_MASK (3U<<0) -#define ATI_REG_PHYS_OUT_RW (1U<<2) -#define ATI_REG_PHYS_OUT_ADDR_EN (1U<<8) -#define ATI_REG_PHYS_OUT_ADDR_SHIFT 9 -#define ATI_REG_PHYS_OUT_DATA_SHIFT 16 - -#define ATI_REG_PHYS_IN_ADDR 0x10 -#define ATI_REG_PHYS_IN_READ_FLAG (1U<<8) -#define ATI_REG_PHYS_IN_ADDR_SHIFT 9 -#define ATI_REG_PHYS_IN_DATA_SHIFT 16 - -#define ATI_REG_SLOTREQ 0x14 - -#define ATI_REG_COUNTER 0x18 -#define ATI_REG_COUNTER_SLOT (3U<<0) /* slot # */ -#define ATI_REG_COUNTER_BITCLOCK (31U<<8) - -#define ATI_REG_IN_FIFO_THRESHOLD 0x1c - -#define ATI_REG_MODEM_IN_DMA_LINKPTR 0x20 -#define ATI_REG_MODEM_IN_DMA_DT_START 0x24 /* RO */ -#define ATI_REG_MODEM_IN_DMA_DT_NEXT 0x28 /* RO */ -#define ATI_REG_MODEM_IN_DMA_DT_CUR 0x2c /* RO */ -#define ATI_REG_MODEM_IN_DMA_DT_SIZE 0x30 -#define ATI_REG_MODEM_OUT_FIFO 0x34 /* output threshold */ -#define ATI_REG_MODEM_OUT1_DMA_THRESHOLD_MASK (0xf<<16) -#define ATI_REG_MODEM_OUT1_DMA_THRESHOLD_SHIFT 16 -#define ATI_REG_MODEM_OUT_DMA1_LINKPTR 0x38 -#define ATI_REG_MODEM_OUT_DMA2_LINKPTR 0x3c -#define ATI_REG_MODEM_OUT_DMA3_LINKPTR 0x40 -#define ATI_REG_MODEM_OUT_DMA1_DT_START 0x44 -#define ATI_REG_MODEM_OUT_DMA1_DT_NEXT 0x48 -#define ATI_REG_MODEM_OUT_DMA1_DT_CUR 0x4c -#define ATI_REG_MODEM_OUT_DMA2_DT_START 0x50 -#define ATI_REG_MODEM_OUT_DMA2_DT_NEXT 0x54 -#define ATI_REG_MODEM_OUT_DMA2_DT_CUR 0x58 -#define ATI_REG_MODEM_OUT_DMA3_DT_START 0x5c -#define ATI_REG_MODEM_OUT_DMA3_DT_NEXT 0x60 -#define ATI_REG_MODEM_OUT_DMA3_DT_CUR 0x64 -#define ATI_REG_MODEM_OUT_DMA12_DT_SIZE 0x68 -#define ATI_REG_MODEM_OUT_DMA3_DT_SIZE 0x6c -#define ATI_REG_MODEM_OUT_FIFO_USED 0x70 -#define ATI_REG_MODEM_OUT_GPIO 0x74 -#define ATI_REG_MODEM_OUT_GPIO_EN 1 -#define ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT 5 -#define ATI_REG_MODEM_IN_GPIO 0x78 - -#define ATI_REG_MODEM_MIRROR 0x7c -#define ATI_REG_AUDIO_MIRROR 0x80 - -#define ATI_REG_MODEM_FIFO_FLUSH 0x88 -#define ATI_REG_MODEM_FIFO_OUT1_FLUSH (1U<<0) -#define ATI_REG_MODEM_FIFO_OUT2_FLUSH (1U<<1) -#define ATI_REG_MODEM_FIFO_OUT3_FLUSH (1U<<2) -#define ATI_REG_MODEM_FIFO_IN_FLUSH (1U<<3) - -/* LINKPTR */ -#define ATI_REG_LINKPTR_EN (1U<<0) - -#define ATI_MAX_DESCRIPTORS 256 /* max number of descriptor packets */ - - -struct atiixp_modem; - -/* - * DMA packate descriptor - */ - -struct atiixp_dma_desc { - u32 addr; /* DMA buffer address */ - u16 status; /* status bits */ - u16 size; /* size of the packet in dwords */ - u32 next; /* address of the next packet descriptor */ -}; - -/* - * stream enum - */ -enum { ATI_DMA_PLAYBACK, ATI_DMA_CAPTURE, NUM_ATI_DMAS }; /* DMAs */ -enum { ATI_PCM_OUT, ATI_PCM_IN, NUM_ATI_PCMS }; /* AC97 pcm slots */ -enum { ATI_PCMDEV_ANALOG, NUM_ATI_PCMDEVS }; /* pcm devices */ - -#define NUM_ATI_CODECS 3 - - -/* - * constants and callbacks for each DMA type - */ -struct atiixp_dma_ops { - int type; /* ATI_DMA_XXX */ - unsigned int llp_offset; /* LINKPTR offset */ - unsigned int dt_cur; /* DT_CUR offset */ - /* called from open callback */ - void (*enable_dma)(struct atiixp_modem *chip, int on); - /* called from trigger (START/STOP) */ - void (*enable_transfer)(struct atiixp_modem *chip, int on); - /* called from trigger (STOP only) */ - void (*flush_dma)(struct atiixp_modem *chip); -}; - -/* - * DMA stream - */ -struct atiixp_dma { - const struct atiixp_dma_ops *ops; - struct snd_dma_buffer desc_buf; - struct snd_pcm_substream *substream; /* assigned PCM substream */ - unsigned int buf_addr, buf_bytes; /* DMA buffer address, bytes */ - unsigned int period_bytes, periods; - int opened; - int running; - int pcm_open_flag; - int ac97_pcm_type; /* index # of ac97_pcm to access, -1 = not used */ -}; - -/* - * ATI IXP chip - */ -struct atiixp_modem { - struct snd_card *card; - struct pci_dev *pci; - - struct resource *res; /* memory i/o */ - unsigned long addr; - void __iomem *remap_addr; - int irq; - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97[NUM_ATI_CODECS]; - - spinlock_t reg_lock; - - struct atiixp_dma dmas[NUM_ATI_DMAS]; - struct ac97_pcm *pcms[NUM_ATI_PCMS]; - struct snd_pcm *pcmdevs[NUM_ATI_PCMDEVS]; - - int max_channels; /* max. channels for PCM out */ - - unsigned int codec_not_ready_bits; /* for codec detection */ - - int spdif_over_aclink; /* passed from the module option */ - struct mutex open_mutex; /* playback open mutex */ -}; - - -/* - */ -static DEFINE_PCI_DEVICE_TABLE(snd_atiixp_ids) = { - { PCI_VDEVICE(ATI, 0x434d), 0 }, /* SB200 */ - { PCI_VDEVICE(ATI, 0x4378), 0 }, /* SB400 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_atiixp_ids); - - -/* - * lowlevel functions - */ - -/* - * update the bits of the given register. - * return 1 if the bits changed. - */ -static int snd_atiixp_update_bits(struct atiixp_modem *chip, unsigned int reg, - unsigned int mask, unsigned int value) -{ - void __iomem *addr = chip->remap_addr + reg; - unsigned int data, old_data; - old_data = data = readl(addr); - data &= ~mask; - data |= value; - if (old_data == data) - return 0; - writel(data, addr); - return 1; -} - -/* - * macros for easy use - */ -#define atiixp_write(chip,reg,value) \ - writel(value, chip->remap_addr + ATI_REG_##reg) -#define atiixp_read(chip,reg) \ - readl(chip->remap_addr + ATI_REG_##reg) -#define atiixp_update(chip,reg,mask,val) \ - snd_atiixp_update_bits(chip, ATI_REG_##reg, mask, val) - -/* - * handling DMA packets - * - * we allocate a linear buffer for the DMA, and split it to each packet. - * in a future version, a scatter-gather buffer should be implemented. - */ - -#define ATI_DESC_LIST_SIZE \ - PAGE_ALIGN(ATI_MAX_DESCRIPTORS * sizeof(struct atiixp_dma_desc)) - -/* - * build packets ring for the given buffer size. - * - * IXP handles the buffer descriptors, which are connected as a linked - * list. although we can change the list dynamically, in this version, - * a static RING of buffer descriptors is used. - * - * the ring is built in this function, and is set up to the hardware. - */ -static int atiixp_build_dma_packets(struct atiixp_modem *chip, - struct atiixp_dma *dma, - struct snd_pcm_substream *substream, - unsigned int periods, - unsigned int period_bytes) -{ - unsigned int i; - u32 addr, desc_addr; - unsigned long flags; - - if (periods > ATI_MAX_DESCRIPTORS) - return -ENOMEM; - - if (dma->desc_buf.area == NULL) { - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - ATI_DESC_LIST_SIZE, &dma->desc_buf) < 0) - return -ENOMEM; - dma->period_bytes = dma->periods = 0; /* clear */ - } - - if (dma->periods == periods && dma->period_bytes == period_bytes) - return 0; - - /* reset DMA before changing the descriptor table */ - spin_lock_irqsave(&chip->reg_lock, flags); - writel(0, chip->remap_addr + dma->ops->llp_offset); - dma->ops->enable_dma(chip, 0); - dma->ops->enable_dma(chip, 1); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - /* fill the entries */ - addr = (u32)substream->runtime->dma_addr; - desc_addr = (u32)dma->desc_buf.addr; - for (i = 0; i < periods; i++) { - struct atiixp_dma_desc *desc; - desc = &((struct atiixp_dma_desc *)dma->desc_buf.area)[i]; - desc->addr = cpu_to_le32(addr); - desc->status = 0; - desc->size = period_bytes >> 2; /* in dwords */ - desc_addr += sizeof(struct atiixp_dma_desc); - if (i == periods - 1) - desc->next = cpu_to_le32((u32)dma->desc_buf.addr); - else - desc->next = cpu_to_le32(desc_addr); - addr += period_bytes; - } - - writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN, - chip->remap_addr + dma->ops->llp_offset); - - dma->period_bytes = period_bytes; - dma->periods = periods; - - return 0; -} - -/* - * remove the ring buffer and release it if assigned - */ -static void atiixp_clear_dma_packets(struct atiixp_modem *chip, - struct atiixp_dma *dma, - struct snd_pcm_substream *substream) -{ - if (dma->desc_buf.area) { - writel(0, chip->remap_addr + dma->ops->llp_offset); - snd_dma_free_pages(&dma->desc_buf); - dma->desc_buf.area = NULL; - } -} - -/* - * AC97 interface - */ -static int snd_atiixp_acquire_codec(struct atiixp_modem *chip) -{ - int timeout = 1000; - - while (atiixp_read(chip, PHYS_OUT_ADDR) & ATI_REG_PHYS_OUT_ADDR_EN) { - if (! timeout--) { - snd_printk(KERN_WARNING "atiixp-modem: codec acquire timeout\n"); - return -EBUSY; - } - udelay(1); - } - return 0; -} - -static unsigned short snd_atiixp_codec_read(struct atiixp_modem *chip, - unsigned short codec, - unsigned short reg) -{ - unsigned int data; - int timeout; - - if (snd_atiixp_acquire_codec(chip) < 0) - return 0xffff; - data = (reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) | - ATI_REG_PHYS_OUT_ADDR_EN | - ATI_REG_PHYS_OUT_RW | - codec; - atiixp_write(chip, PHYS_OUT_ADDR, data); - if (snd_atiixp_acquire_codec(chip) < 0) - return 0xffff; - timeout = 1000; - do { - data = atiixp_read(chip, PHYS_IN_ADDR); - if (data & ATI_REG_PHYS_IN_READ_FLAG) - return data >> ATI_REG_PHYS_IN_DATA_SHIFT; - udelay(1); - } while (--timeout); - /* time out may happen during reset */ - if (reg < 0x7c) - snd_printk(KERN_WARNING "atiixp-modem: codec read timeout (reg %x)\n", reg); - return 0xffff; -} - - -static void snd_atiixp_codec_write(struct atiixp_modem *chip, - unsigned short codec, - unsigned short reg, unsigned short val) -{ - unsigned int data; - - if (snd_atiixp_acquire_codec(chip) < 0) - return; - data = ((unsigned int)val << ATI_REG_PHYS_OUT_DATA_SHIFT) | - ((unsigned int)reg << ATI_REG_PHYS_OUT_ADDR_SHIFT) | - ATI_REG_PHYS_OUT_ADDR_EN | codec; - atiixp_write(chip, PHYS_OUT_ADDR, data); -} - - -static unsigned short snd_atiixp_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct atiixp_modem *chip = ac97->private_data; - return snd_atiixp_codec_read(chip, ac97->num, reg); - -} - -static void snd_atiixp_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct atiixp_modem *chip = ac97->private_data; - if (reg == AC97_GPIO_STATUS) { - atiixp_write(chip, MODEM_OUT_GPIO, - (val << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN); - return; - } - snd_atiixp_codec_write(chip, ac97->num, reg, val); -} - -/* - * reset AC link - */ -static int snd_atiixp_aclink_reset(struct atiixp_modem *chip) -{ - int timeout; - - /* reset powerdoewn */ - if (atiixp_update(chip, CMD, ATI_REG_CMD_POWERDOWN, 0)) - udelay(10); - - /* perform a software reset */ - atiixp_update(chip, CMD, ATI_REG_CMD_AC_SOFT_RESET, ATI_REG_CMD_AC_SOFT_RESET); - atiixp_read(chip, CMD); - udelay(10); - atiixp_update(chip, CMD, ATI_REG_CMD_AC_SOFT_RESET, 0); - - timeout = 10; - while (! (atiixp_read(chip, CMD) & ATI_REG_CMD_ACLINK_ACTIVE)) { - /* do a hard reset */ - atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET, - ATI_REG_CMD_AC_SYNC); - atiixp_read(chip, CMD); - msleep(1); - atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); - if (!--timeout) { - snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n"); - break; - } - } - - /* deassert RESET and assert SYNC to make sure */ - atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET, - ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET); - - return 0; -} - -#ifdef CONFIG_PM -static int snd_atiixp_aclink_down(struct atiixp_modem *chip) -{ - // if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */ - // return -EBUSY; - atiixp_update(chip, CMD, - ATI_REG_CMD_POWERDOWN | ATI_REG_CMD_AC_RESET, - ATI_REG_CMD_POWERDOWN); - return 0; -} -#endif - -/* - * auto-detection of codecs - * - * the IXP chip can generate interrupts for the non-existing codecs. - * NEW_FRAME interrupt is used to make sure that the interrupt is generated - * even if all three codecs are connected. - */ - -#define ALL_CODEC_NOT_READY \ - (ATI_REG_ISR_CODEC0_NOT_READY |\ - ATI_REG_ISR_CODEC1_NOT_READY |\ - ATI_REG_ISR_CODEC2_NOT_READY) -#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME) - -static int snd_atiixp_codec_detect(struct atiixp_modem *chip) -{ - int timeout; - - chip->codec_not_ready_bits = 0; - atiixp_write(chip, IER, CODEC_CHECK_BITS); - /* wait for the interrupts */ - timeout = 50; - while (timeout-- > 0) { - msleep(1); - if (chip->codec_not_ready_bits) - break; - } - atiixp_write(chip, IER, 0); /* disable irqs */ - - if ((chip->codec_not_ready_bits & ALL_CODEC_NOT_READY) == ALL_CODEC_NOT_READY) { - snd_printk(KERN_ERR "atiixp-modem: no codec detected!\n"); - return -ENXIO; - } - return 0; -} - - -/* - * enable DMA and irqs - */ -static int snd_atiixp_chip_start(struct atiixp_modem *chip) -{ - unsigned int reg; - - /* set up spdif, enable burst mode */ - reg = atiixp_read(chip, CMD); - reg |= ATI_REG_CMD_BURST_EN; - if(!(reg & ATI_REG_CMD_MODEM_PRESENT)) - reg |= ATI_REG_CMD_MODEM_PRESENT; - atiixp_write(chip, CMD, reg); - - /* clear all interrupt source */ - atiixp_write(chip, ISR, 0xffffffff); - /* enable irqs */ - atiixp_write(chip, IER, - ATI_REG_IER_MODEM_STATUS_EN | - ATI_REG_IER_MODEM_IN_XRUN_EN | - ATI_REG_IER_MODEM_OUT1_XRUN_EN); - return 0; -} - - -/* - * disable DMA and IRQs - */ -static int snd_atiixp_chip_stop(struct atiixp_modem *chip) -{ - /* clear interrupt source */ - atiixp_write(chip, ISR, atiixp_read(chip, ISR)); - /* disable irqs */ - atiixp_write(chip, IER, 0); - return 0; -} - - -/* - * PCM section - */ - -/* - * pointer callback simplly reads XXX_DMA_DT_CUR register as the current - * position. when SG-buffer is implemented, the offset must be calculated - * correctly... - */ -static snd_pcm_uframes_t snd_atiixp_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct atiixp_dma *dma = runtime->private_data; - unsigned int curptr; - int timeout = 1000; - - while (timeout--) { - curptr = readl(chip->remap_addr + dma->ops->dt_cur); - if (curptr < dma->buf_addr) - continue; - curptr -= dma->buf_addr; - if (curptr >= dma->buf_bytes) - continue; - return bytes_to_frames(runtime, curptr); - } - snd_printd("atiixp-modem: invalid DMA pointer read 0x%x (buf=%x)\n", - readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr); - return 0; -} - -/* - * XRUN detected, and stop the PCM substream - */ -static void snd_atiixp_xrun_dma(struct atiixp_modem *chip, - struct atiixp_dma *dma) -{ - if (! dma->substream || ! dma->running) - return; - snd_printdd("atiixp-modem: XRUN detected (DMA %d)\n", dma->ops->type); - snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN); -} - -/* - * the period ack. update the substream. - */ -static void snd_atiixp_update_dma(struct atiixp_modem *chip, - struct atiixp_dma *dma) -{ - if (! dma->substream || ! dma->running) - return; - snd_pcm_period_elapsed(dma->substream); -} - -/* set BUS_BUSY interrupt bit if any DMA is running */ -/* call with spinlock held */ -static void snd_atiixp_check_bus_busy(struct atiixp_modem *chip) -{ - unsigned int bus_busy; - if (atiixp_read(chip, CMD) & (ATI_REG_CMD_MODEM_SEND1_EN | - ATI_REG_CMD_MODEM_RECEIVE_EN)) - bus_busy = ATI_REG_IER_MODEM_SET_BUS_BUSY; - else - bus_busy = 0; - atiixp_update(chip, IER, ATI_REG_IER_MODEM_SET_BUS_BUSY, bus_busy); -} - -/* common trigger callback - * calling the lowlevel callbacks in it - */ -static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - struct atiixp_dma *dma = substream->runtime->private_data; - int err = 0; - - if (snd_BUG_ON(!dma->ops->enable_transfer || - !dma->ops->flush_dma)) - return -EINVAL; - - spin_lock(&chip->reg_lock); - switch(cmd) { - case SNDRV_PCM_TRIGGER_START: - dma->ops->enable_transfer(chip, 1); - dma->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - dma->ops->enable_transfer(chip, 0); - dma->running = 0; - break; - default: - err = -EINVAL; - break; - } - if (! err) { - snd_atiixp_check_bus_busy(chip); - if (cmd == SNDRV_PCM_TRIGGER_STOP) { - dma->ops->flush_dma(chip); - snd_atiixp_check_bus_busy(chip); - } - } - spin_unlock(&chip->reg_lock); - return err; -} - - -/* - * lowlevel callbacks for each DMA type - * - * every callback is supposed to be called in chip->reg_lock spinlock - */ - -/* flush FIFO of analog OUT DMA */ -static void atiixp_out_flush_dma(struct atiixp_modem *chip) -{ - atiixp_write(chip, MODEM_FIFO_FLUSH, ATI_REG_MODEM_FIFO_OUT1_FLUSH); -} - -/* enable/disable analog OUT DMA */ -static void atiixp_out_enable_dma(struct atiixp_modem *chip, int on) -{ - unsigned int data; - data = atiixp_read(chip, CMD); - if (on) { - if (data & ATI_REG_CMD_MODEM_OUT_DMA1_EN) - return; - atiixp_out_flush_dma(chip); - data |= ATI_REG_CMD_MODEM_OUT_DMA1_EN; - } else - data &= ~ATI_REG_CMD_MODEM_OUT_DMA1_EN; - atiixp_write(chip, CMD, data); -} - -/* start/stop transfer over OUT DMA */ -static void atiixp_out_enable_transfer(struct atiixp_modem *chip, int on) -{ - atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_SEND1_EN, - on ? ATI_REG_CMD_MODEM_SEND1_EN : 0); -} - -/* enable/disable analog IN DMA */ -static void atiixp_in_enable_dma(struct atiixp_modem *chip, int on) -{ - atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_IN_DMA_EN, - on ? ATI_REG_CMD_MODEM_IN_DMA_EN : 0); -} - -/* start/stop analog IN DMA */ -static void atiixp_in_enable_transfer(struct atiixp_modem *chip, int on) -{ - if (on) { - unsigned int data = atiixp_read(chip, CMD); - if (! (data & ATI_REG_CMD_MODEM_RECEIVE_EN)) { - data |= ATI_REG_CMD_MODEM_RECEIVE_EN; - atiixp_write(chip, CMD, data); - } - } else - atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_RECEIVE_EN, 0); -} - -/* flush FIFO of analog IN DMA */ -static void atiixp_in_flush_dma(struct atiixp_modem *chip) -{ - atiixp_write(chip, MODEM_FIFO_FLUSH, ATI_REG_MODEM_FIFO_IN_FLUSH); -} - -/* set up slots and formats for analog OUT */ -static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - unsigned int data; - - spin_lock_irq(&chip->reg_lock); - /* set output threshold */ - data = atiixp_read(chip, MODEM_OUT_FIFO); - data &= ~ATI_REG_MODEM_OUT1_DMA_THRESHOLD_MASK; - data |= 0x04 << ATI_REG_MODEM_OUT1_DMA_THRESHOLD_SHIFT; - atiixp_write(chip, MODEM_OUT_FIFO, data); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -/* set up slots and formats for analog IN */ -static int snd_atiixp_capture_prepare(struct snd_pcm_substream *substream) -{ - return 0; -} - -/* - * hw_params - allocate the buffer and set up buffer descriptors - */ -static int snd_atiixp_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - struct atiixp_dma *dma = substream->runtime->private_data; - int err; - int i; - - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) - return err; - dma->buf_addr = substream->runtime->dma_addr; - dma->buf_bytes = params_buffer_bytes(hw_params); - - err = atiixp_build_dma_packets(chip, dma, substream, - params_periods(hw_params), - params_period_bytes(hw_params)); - if (err < 0) - return err; - - /* set up modem rate */ - for (i = 0; i < NUM_ATI_CODECS; i++) { - if (! chip->ac97[i]) - continue; - snd_ac97_write(chip->ac97[i], AC97_LINE1_RATE, params_rate(hw_params)); - snd_ac97_write(chip->ac97[i], AC97_LINE1_LEVEL, 0); - } - - return err; -} - -static int snd_atiixp_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - struct atiixp_dma *dma = substream->runtime->private_data; - - atiixp_clear_dma_packets(chip, dma, substream); - snd_pcm_lib_free_pages(substream); - return 0; -} - - -/* - * pcm hardware definition, identical for all DMA types - */ -static struct snd_pcm_hardware snd_atiixp_pcm_hw = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_KNOT), - .rate_min = 8000, - .rate_max = 16000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 256 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 128 * 1024, - .periods_min = 2, - .periods_max = ATI_MAX_DESCRIPTORS, -}; - -static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, - struct atiixp_dma *dma, int pcm_type) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - - if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) - return -EINVAL; - - if (dma->opened) - return -EBUSY; - dma->substream = substream; - runtime->hw = snd_atiixp_pcm_hw; - dma->ac97_pcm_type = pcm_type; - if ((err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates)) < 0) - return err; - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - runtime->private_data = dma; - - /* enable DMA bits */ - spin_lock_irq(&chip->reg_lock); - dma->ops->enable_dma(chip, 1); - spin_unlock_irq(&chip->reg_lock); - dma->opened = 1; - - return 0; -} - -static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream, - struct atiixp_dma *dma) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - /* disable DMA bits */ - if (snd_BUG_ON(!dma->ops || !dma->ops->enable_dma)) - return -EINVAL; - spin_lock_irq(&chip->reg_lock); - dma->ops->enable_dma(chip, 0); - spin_unlock_irq(&chip->reg_lock); - dma->substream = NULL; - dma->opened = 0; - return 0; -} - -/* - */ -static int snd_atiixp_playback_open(struct snd_pcm_substream *substream) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - int err; - - mutex_lock(&chip->open_mutex); - err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); - mutex_unlock(&chip->open_mutex); - if (err < 0) - return err; - return 0; -} - -static int snd_atiixp_playback_close(struct snd_pcm_substream *substream) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - int err; - mutex_lock(&chip->open_mutex); - err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); - mutex_unlock(&chip->open_mutex); - return err; -} - -static int snd_atiixp_capture_open(struct snd_pcm_substream *substream) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE], 1); -} - -static int snd_atiixp_capture_close(struct snd_pcm_substream *substream) -{ - struct atiixp_modem *chip = snd_pcm_substream_chip(substream); - return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_CAPTURE]); -} - - -/* AC97 playback */ -static struct snd_pcm_ops snd_atiixp_playback_ops = { - .open = snd_atiixp_playback_open, - .close = snd_atiixp_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_atiixp_pcm_hw_params, - .hw_free = snd_atiixp_pcm_hw_free, - .prepare = snd_atiixp_playback_prepare, - .trigger = snd_atiixp_pcm_trigger, - .pointer = snd_atiixp_pcm_pointer, -}; - -/* AC97 capture */ -static struct snd_pcm_ops snd_atiixp_capture_ops = { - .open = snd_atiixp_capture_open, - .close = snd_atiixp_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_atiixp_pcm_hw_params, - .hw_free = snd_atiixp_pcm_hw_free, - .prepare = snd_atiixp_capture_prepare, - .trigger = snd_atiixp_pcm_trigger, - .pointer = snd_atiixp_pcm_pointer, -}; - -static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = { - .type = ATI_DMA_PLAYBACK, - .llp_offset = ATI_REG_MODEM_OUT_DMA1_LINKPTR, - .dt_cur = ATI_REG_MODEM_OUT_DMA1_DT_CUR, - .enable_dma = atiixp_out_enable_dma, - .enable_transfer = atiixp_out_enable_transfer, - .flush_dma = atiixp_out_flush_dma, -}; - -static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = { - .type = ATI_DMA_CAPTURE, - .llp_offset = ATI_REG_MODEM_IN_DMA_LINKPTR, - .dt_cur = ATI_REG_MODEM_IN_DMA_DT_CUR, - .enable_dma = atiixp_in_enable_dma, - .enable_transfer = atiixp_in_enable_transfer, - .flush_dma = atiixp_in_flush_dma, -}; - -static int __devinit snd_atiixp_pcm_new(struct atiixp_modem *chip) -{ - struct snd_pcm *pcm; - int err; - - /* initialize constants */ - chip->dmas[ATI_DMA_PLAYBACK].ops = &snd_atiixp_playback_dma_ops; - chip->dmas[ATI_DMA_CAPTURE].ops = &snd_atiixp_capture_dma_ops; - - /* PCM #0: analog I/O */ - err = snd_pcm_new(chip->card, "ATI IXP MC97", ATI_PCMDEV_ANALOG, 1, 1, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_atiixp_capture_ops); - pcm->dev_class = SNDRV_PCM_CLASS_MODEM; - pcm->private_data = chip; - strcpy(pcm->name, "ATI IXP MC97"); - chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - 64*1024, 128*1024); - - return 0; -} - - - -/* - * interrupt handler - */ -static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id) -{ - struct atiixp_modem *chip = dev_id; - unsigned int status; - - status = atiixp_read(chip, ISR); - - if (! status) - return IRQ_NONE; - - /* process audio DMA */ - if (status & ATI_REG_ISR_MODEM_OUT1_XRUN) - snd_atiixp_xrun_dma(chip, &chip->dmas[ATI_DMA_PLAYBACK]); - else if (status & ATI_REG_ISR_MODEM_OUT1_STATUS) - snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_PLAYBACK]); - if (status & ATI_REG_ISR_MODEM_IN_XRUN) - snd_atiixp_xrun_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]); - else if (status & ATI_REG_ISR_MODEM_IN_STATUS) - snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]); - - /* for codec detection */ - if (status & CODEC_CHECK_BITS) { - unsigned int detected; - detected = status & CODEC_CHECK_BITS; - spin_lock(&chip->reg_lock); - chip->codec_not_ready_bits |= detected; - atiixp_update(chip, IER, detected, 0); /* disable the detected irqs */ - spin_unlock(&chip->reg_lock); - } - - /* ack */ - atiixp_write(chip, ISR, status); - - return IRQ_HANDLED; -} - - -/* - * ac97 mixer section - */ - -static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int i, err; - int codec_count; - static struct snd_ac97_bus_ops ops = { - .write = snd_atiixp_ac97_write, - .read = snd_atiixp_ac97_read, - }; - static unsigned int codec_skip[NUM_ATI_CODECS] = { - ATI_REG_ISR_CODEC0_NOT_READY, - ATI_REG_ISR_CODEC1_NOT_READY, - ATI_REG_ISR_CODEC2_NOT_READY, - }; - - if (snd_atiixp_codec_detect(chip) < 0) - return -ENXIO; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) - return err; - pbus->clock = clock; - chip->ac97_bus = pbus; - - codec_count = 0; - for (i = 0; i < NUM_ATI_CODECS; i++) { - if (chip->codec_not_ready_bits & codec_skip[i]) - continue; - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.pci = chip->pci; - ac97.num = i; - ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { - chip->ac97[i] = NULL; /* to be sure */ - snd_printdd("atiixp-modem: codec %d not available for modem\n", i); - continue; - } - codec_count++; - } - - if (! codec_count) { - snd_printk(KERN_ERR "atiixp-modem: no codec available\n"); - return -ENODEV; - } - - /* snd_ac97_tune_hardware(chip->ac97, ac97_quirks); */ - - return 0; -} - - -#ifdef CONFIG_PM -/* - * power management - */ -static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct atiixp_modem *chip = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < NUM_ATI_PCMDEVS; i++) - snd_pcm_suspend_all(chip->pcmdevs[i]); - for (i = 0; i < NUM_ATI_CODECS; i++) - snd_ac97_suspend(chip->ac97[i]); - snd_atiixp_aclink_down(chip); - snd_atiixp_chip_stop(chip); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_atiixp_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct atiixp_modem *chip = card->private_data; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "atiixp-modem: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_atiixp_aclink_reset(chip); - snd_atiixp_chip_start(chip); - - for (i = 0; i < NUM_ATI_CODECS; i++) - snd_ac97_resume(chip->ac97[i]); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - - -#ifdef CONFIG_PROC_FS -/* - * proc interface for register dump - */ - -static void snd_atiixp_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct atiixp_modem *chip = entry->private_data; - int i; - - for (i = 0; i < 256; i += 4) - snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i)); -} - -static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry)) - snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); -} -#else -#define snd_atiixp_proc_init(chip) -#endif - - -/* - * destructor - */ - -static int snd_atiixp_free(struct atiixp_modem *chip) -{ - if (chip->irq < 0) - goto __hw_end; - snd_atiixp_chip_stop(chip); - - __hw_end: - if (chip->irq >= 0) - free_irq(chip->irq, chip); - if (chip->remap_addr) - iounmap(chip->remap_addr); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_atiixp_dev_free(struct snd_device *device) -{ - struct atiixp_modem *chip = device->device_data; - return snd_atiixp_free(chip); -} - -/* - * constructor for chip instance - */ -static int __devinit snd_atiixp_create(struct snd_card *card, - struct pci_dev *pci, - struct atiixp_modem **r_chip) -{ - static struct snd_device_ops ops = { - .dev_free = snd_atiixp_dev_free, - }; - struct atiixp_modem *chip; - int err; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->open_mutex); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - if ((err = pci_request_regions(pci, "ATI IXP MC97")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->addr = pci_resource_start(pci, 0); - chip->remap_addr = pci_ioremap_bar(pci, 0); - if (chip->remap_addr == NULL) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); - snd_atiixp_free(chip); - return -EIO; - } - - if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_atiixp_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - pci_set_master(pci); - synchronize_irq(chip->irq); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_atiixp_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *r_chip = chip; - return 0; -} - - -static int __devinit snd_atiixp_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct atiixp_modem *chip; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - strcpy(card->driver, "ATIIXP-MODEM"); - strcpy(card->shortname, "ATI IXP Modem"); - if ((err = snd_atiixp_create(card, pci, &chip)) < 0) - goto __error; - card->private_data = chip; - - if ((err = snd_atiixp_aclink_reset(chip)) < 0) - goto __error; - - if ((err = snd_atiixp_mixer_new(chip, ac97_clock)) < 0) - goto __error; - - if ((err = snd_atiixp_pcm_new(chip)) < 0) - goto __error; - - snd_atiixp_proc_init(chip); - - snd_atiixp_chip_start(chip); - - sprintf(card->longname, "%s rev %x at 0x%lx, irq %i", - card->shortname, pci->revision, chip->addr, chip->irq); - - if ((err = snd_card_register(card)) < 0) - goto __error; - - pci_set_drvdata(pci, card); - return 0; - - __error: - snd_card_free(card); - return err; -} - -static void __devexit snd_atiixp_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_atiixp_ids, - .probe = snd_atiixp_probe, - .remove = __devexit_p(snd_atiixp_remove), -#ifdef CONFIG_PM - .suspend = snd_atiixp_suspend, - .resume = snd_atiixp_resume, -#endif -}; - - -static int __init alsa_card_atiixp_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_atiixp_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_atiixp_init) -module_exit(alsa_card_atiixp_exit) diff --git a/ANDROID_3.4.5/sound/pci/au88x0/Makefile b/ANDROID_3.4.5/sound/pci/au88x0/Makefile deleted file mode 100644 index d0a66bc5..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -snd-au8810-objs := au8810.o -snd-au8820-objs := au8820.o -snd-au8830-objs := au8830.o - -obj-$(CONFIG_SND_AU8810) += snd-au8810.o -obj-$(CONFIG_SND_AU8820) += snd-au8820.o -obj-$(CONFIG_SND_AU8830) += snd-au8830.o diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au8810.c b/ANDROID_3.4.5/sound/pci/au88x0/au8810.c deleted file mode 100644 index aa51cc77..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au8810.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "au8810.h" -#include "au88x0.h" -static DEFINE_PCI_DEVICE_TABLE(snd_vortex_ids) = { - {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE), 1,}, - {0,} -}; - -#include "au88x0_core.c" -#include "au88x0_pcm.c" -#include "au88x0_mixer.c" -#include "au88x0_mpu401.c" -#include "au88x0_game.c" -#include "au88x0_eq.c" -#include "au88x0_a3d.c" -#include "au88x0_xtalk.c" -#include "au88x0.c" diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au8810.h b/ANDROID_3.4.5/sound/pci/au88x0/au8810.h deleted file mode 100644 index 79fbee38..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au8810.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - Aureal Advantage Soundcard driver. - */ - -#define CHIP_AU8810 - -#define CARD_NAME "Aureal Advantage" -#define CARD_NAME_SHORT "au8810" - -#define NR_ADB 0x10 -#define NR_WT 0x00 -#define NR_SRC 0x10 -#define NR_A3D 0x10 -#define NR_MIXIN 0x20 -#define NR_MIXOUT 0x10 - - -/* ADBDMA */ -#define VORTEX_ADBDMA_STAT 0x27e00 /* read only, subbuffer, DMA pos */ -#define POS_MASK 0x00000fff -#define POS_SHIFT 0x0 -#define ADB_SUBBUF_MASK 0x00003000 /* ADB only. */ -#define ADB_SUBBUF_SHIFT 0xc /* ADB only. */ -#define VORTEX_ADBDMA_CTRL 0x27180 /* write only; format, flags, DMA pos */ -#define OFFSET_MASK 0x00000fff -#define OFFSET_SHIFT 0x0 -#define IE_MASK 0x00001000 /* interrupt enable. */ -#define IE_SHIFT 0xc -#define DIR_MASK 0x00002000 /* Direction */ -#define DIR_SHIFT 0xd -#define FMT_MASK 0x0003c000 -#define FMT_SHIFT 0xe -// The ADB masks and shift also are valid for the wtdma, except if specified otherwise. -#define VORTEX_ADBDMA_BUFCFG0 0x27100 -#define VORTEX_ADBDMA_BUFCFG1 0x27104 -#define VORTEX_ADBDMA_BUFBASE 0x27000 -#define VORTEX_ADBDMA_START 0x27c00 /* Which subbuffer starts */ - -#define VORTEX_ADBDMA_STATUS 0x27A90 /* stored at AdbDma->this_10 / 2 DWORD in size. */ - -/* WTDMA */ -#define VORTEX_WTDMA_CTRL 0x27fd8 /* format, DMA pos */ -#define VORTEX_WTDMA_STAT 0x27fe8 /* DMA subbuf, DMA pos */ -#define WT_SUBBUF_MASK 0x3 -#define WT_SUBBUF_SHIFT 0xc -#define VORTEX_WTDMA_BUFBASE 0x27fc0 -#define VORTEX_WTDMA_BUFCFG0 0x27fd0 -#define VORTEX_WTDMA_BUFCFG1 0x27fd4 -#define VORTEX_WTDMA_START 0x27fe4 /* which subbuffer is first */ - -/* ADB */ -#define VORTEX_ADB_SR 0x28400 /* Samplerates enable/disable */ -#define VORTEX_ADB_RTBASE 0x28000 -#define VORTEX_ADB_RTBASE_COUNT 173 -#define VORTEX_ADB_CHNBASE 0x282b4 -#define VORTEX_ADB_CHNBASE_COUNT 24 -#define ROUTE_MASK 0xffff -#define SOURCE_MASK 0xff00 -#define ADB_MASK 0xff -#define ADB_SHIFT 0x8 - -/* ADB address */ -#define OFFSET_ADBDMA 0x00 -#define OFFSET_SRCIN 0x40 -#define OFFSET_SRCOUT 0x20 -#define OFFSET_MIXIN 0x50 -#define OFFSET_MIXOUT 0x30 -#define OFFSET_CODECIN 0x70 -#define OFFSET_CODECOUT 0x88 -#define OFFSET_SPORTIN 0x78 /* ch 0x13 */ -#define OFFSET_SPORTOUT 0x90 -#define OFFSET_SPDIFOUT 0x92 /* ch 0x14 check this! */ -#define OFFSET_EQIN 0xa0 -#define OFFSET_EQOUT 0x7e /* 2 routes on ch 0x11 */ -#define OFFSET_XTALKOUT 0x66 /* crosstalk canceller (source) */ -#define OFFSET_XTALKIN 0x96 /* crosstalk canceller (sink) */ -#define OFFSET_A3DIN 0x70 /* ADB sink. */ -#define OFFSET_A3DOUT 0xA6 /* ADB source. 2 routes per slice = 8 */ -#define OFFSET_EFXIN 0x80 /* ADB sink. */ -#define OFFSET_EFXOUT 0x68 /* ADB source. */ - -/* ADB route translate helper */ -#define ADB_DMA(x) (x) -#define ADB_SRCOUT(x) (x + OFFSET_SRCOUT) -#define ADB_SRCIN(x) (x + OFFSET_SRCIN) -#define ADB_MIXOUT(x) (x + OFFSET_MIXOUT) -#define ADB_MIXIN(x) (x + OFFSET_MIXIN) -#define ADB_CODECIN(x) (x + OFFSET_CODECIN) -#define ADB_CODECOUT(x) (x + OFFSET_CODECOUT) -#define ADB_SPORTIN(x) (x + OFFSET_SPORTIN) -#define ADB_SPORTOUT(x) (x + OFFSET_SPORTOUT) -#define ADB_SPDIFOUT(x) (x + OFFSET_SPDIFOUT) -#define ADB_EQIN(x) (x + OFFSET_EQIN) -#define ADB_EQOUT(x) (x + OFFSET_EQOUT) -#define ADB_A3DOUT(x) (x + OFFSET_A3DOUT) /* 0x10 A3D blocks */ -#define ADB_A3DIN(x) (x + OFFSET_A3DIN) -#define ADB_XTALKIN(x) (x + OFFSET_XTALKIN) -#define ADB_XTALKOUT(x) (x + OFFSET_XTALKOUT) - -#define MIX_OUTL 0xe -#define MIX_OUTR 0xf -#define MIX_INL 0x1e -#define MIX_INR 0x1f -#define MIX_DEFIGAIN 0x08 /* 0x8 => 6dB */ -#define MIX_DEFOGAIN 0x08 - -/* MIXER */ -#define VORTEX_MIXER_SR 0x21f00 -#define VORTEX_MIXER_CLIP 0x21f80 -#define VORTEX_MIXER_CHNBASE 0x21e40 -#define VORTEX_MIXER_RTBASE 0x21e00 -#define MIXER_RTBASE_SIZE 0x38 -#define VORTEX_MIX_ENIN 0x21a00 /* Input enable bits. 4 bits wide. */ -#define VORTEX_MIX_SMP 0x21c00 /* AU8820: 0x9c00 */ - -/* MIX */ -#define VORTEX_MIX_INVOL_A 0x21000 /* in? */ -#define VORTEX_MIX_INVOL_B 0x20000 /* out? */ -#define VORTEX_MIX_VOL_A 0x21800 -#define VORTEX_MIX_VOL_B 0x20800 - -#define VOL_MIN 0x80 /* Input volume when muted. */ -#define VOL_MAX 0x7f /* FIXME: Not confirmed! Just guessed. */ - -/* SRC */ -#define VORTEX_SRC_CHNBASE 0x26c40 -#define VORTEX_SRC_RTBASE 0x26c00 -#define VORTEX_SRCBLOCK_SR 0x26cc0 -#define VORTEX_SRC_SOURCE 0x26cc4 -#define VORTEX_SRC_SOURCESIZE 0x26cc8 -/* Params - 0x26e00 : 1 U0 - 0x26e40 : 2 CR - 0x26e80 : 3 U3 - 0x26ec0 : 4 DRIFT1 - 0x26f00 : 5 U1 - 0x26f40 : 6 DRIFT2 - 0x26f80 : 7 U2 : Target rate, direction -*/ - -#define VORTEX_SRC_CONVRATIO 0x26e40 -#define VORTEX_SRC_DRIFT0 0x26e80 -#define VORTEX_SRC_DRIFT1 0x26ec0 -#define VORTEX_SRC_DRIFT2 0x26f40 -#define VORTEX_SRC_U0 0x26e00 -#define U0_SLOWLOCK 0x200 -#define VORTEX_SRC_U1 0x26f00 -#define VORTEX_SRC_U2 0x26f80 -#define VORTEX_SRC_DATA 0x26800 /* 0xc800 */ -#define VORTEX_SRC_DATA0 0x26000 - -/* FIFO */ -#define VORTEX_FIFO_ADBCTRL 0x16100 /* Control bits. */ -#define VORTEX_FIFO_WTCTRL 0x16000 -#define FIFO_RDONLY 0x00000001 -#define FIFO_CTRL 0x00000002 /* Allow ctrl. ? */ -#define FIFO_VALID 0x00000010 -#define FIFO_EMPTY 0x00000020 -#define FIFO_U0 0x00001000 /* Unknown. */ -#define FIFO_U1 0x00010000 -#define FIFO_SIZE_BITS 5 -#define FIFO_SIZE (1<this_10 / 2 DWORD in size. */ - -/* ADB */ -#define VORTEX_ADB_SR 0x10a00 /* Samplerates enable/disable */ -#define VORTEX_ADB_RTBASE 0x10800 -#define VORTEX_ADB_RTBASE_COUNT 103 -#define VORTEX_ADB_CHNBASE 0x1099c -#define VORTEX_ADB_CHNBASE_COUNT 22 -#define ROUTE_MASK 0x3fff -#define ADB_MASK 0x7f -#define ADB_SHIFT 0x7 -//#define ADB_MIX_MASK 0xf -/* ADB address */ -#define OFFSET_ADBDMA 0x00 -#define OFFSET_SRCOUT 0x10 /* on channel 0x11 */ -#define OFFSET_SRCIN 0x10 /* on channel < 0x11 */ -#define OFFSET_MIXOUT 0x20 /* source */ -#define OFFSET_MIXIN 0x30 /* sink */ -#define OFFSET_CODECIN 0x48 /* ADB source */ -#define OFFSET_CODECOUT 0x58 /* ADB sink/target */ -#define OFFSET_SPORTOUT 0x60 /* sink */ -#define OFFSET_SPORTIN 0x50 /* source */ -#define OFFSET_EFXOUT 0x50 /* sink */ -#define OFFSET_EFXIN 0x40 /* source */ -#define OFFSET_A3DOUT 0x00 /* This card has no HRTF :( */ -#define OFFSET_A3DIN 0x00 -#define OFFSET_WTOUT 0x58 /* */ - -/* ADB route translate helper */ -#define ADB_DMA(x) (x + OFFSET_ADBDMA) -#define ADB_SRCOUT(x) (x + OFFSET_SRCOUT) -#define ADB_SRCIN(x) (x + OFFSET_SRCIN) -#define ADB_MIXOUT(x) (x + OFFSET_MIXOUT) -#define ADB_MIXIN(x) (x + OFFSET_MIXIN) -#define ADB_CODECIN(x) (x + OFFSET_CODECIN) -#define ADB_CODECOUT(x) (x + OFFSET_CODECOUT) -#define ADB_SPORTOUT(x) (x + OFFSET_SPORTOUT) -#define ADB_SPORTIN(x) (x + OFFSET_SPORTIN) /* */ -#define ADB_A3DOUT(x) (x + OFFSET_A3DOUT) /* 8 A3D blocks */ -#define ADB_A3DIN(x) (x + OFFSET_A3DIN) -#define ADB_WTOUT(x,y) (y + OFFSET_WTOUT) - -/* WTDMA */ -#define VORTEX_WTDMA_CTRL 0x10500 /* format, DMA pos */ -#define VORTEX_WTDMA_STAT 0x10500 /* DMA subbuf, DMA pos */ -#define WT_SUBBUF_MASK (0x3 << WT_SUBBUF_SHIFT) -#define WT_SUBBUF_SHIFT 0x15 -#define VORTEX_WTDMA_BUFBASE 0x10000 -#define VORTEX_WTDMA_BUFCFG0 0x10300 -#define VORTEX_WTDMA_BUFCFG1 0x10304 -#define VORTEX_WTDMA_START 0x10640 /* which subbuffer is first */ - -#define VORTEX_WT_BASE 0x9000 - -/* MIXER */ -#define VORTEX_MIXER_SR 0x9f00 -#define VORTEX_MIXER_CLIP 0x9f80 -#define VORTEX_MIXER_CHNBASE 0x9e40 -#define VORTEX_MIXER_RTBASE 0x9e00 -#define MIXER_RTBASE_SIZE 0x26 -#define VORTEX_MIX_ENIN 0x9a00 /* Input enable bits. 4 bits wide. */ -#define VORTEX_MIX_SMP 0x9c00 - -/* MIX */ -#define VORTEX_MIX_INVOL_A 0x9000 /* in? */ -#define VORTEX_MIX_INVOL_B 0x8000 /* out? */ -#define VORTEX_MIX_VOL_A 0x9800 -#define VORTEX_MIX_VOL_B 0x8800 - -#define VOL_MIN 0x80 /* Input volume when muted. */ -#define VOL_MAX 0x7f /* FIXME: Not confirmed! Just guessed. */ - -//#define MIX_OUTL 0xe -//#define MIX_OUTR 0xf -//#define MIX_INL 0xe -//#define MIX_INR 0xf -#define MIX_DEFIGAIN 0x08 /* 0x8 => 6dB */ -#define MIX_DEFOGAIN 0x08 - -/* SRC */ -#define VORTEX_SRCBLOCK_SR 0xccc0 -#define VORTEX_SRC_CHNBASE 0xcc40 -#define VORTEX_SRC_RTBASE 0xcc00 -#define VORTEX_SRC_SOURCE 0xccc4 -#define VORTEX_SRC_SOURCESIZE 0xccc8 -#define VORTEX_SRC_U0 0xce00 -#define VORTEX_SRC_DRIFT0 0xce80 -#define VORTEX_SRC_DRIFT1 0xcec0 -#define VORTEX_SRC_U1 0xcf00 -#define VORTEX_SRC_DRIFT2 0xcf40 -#define VORTEX_SRC_U2 0xcf80 -#define VORTEX_SRC_DATA 0xc800 -#define VORTEX_SRC_DATA0 0xc000 -#define VORTEX_SRC_CONVRATIO 0xce40 -//#define SRC_RATIO(x) ((((x<<15)/48000) + 1)/2) /* Playback */ -//#define SRC_RATIO2(x) ((((48000<<15)/x) + 1)/2) /* Recording */ - -/* FIFO */ -#define VORTEX_FIFO_ADBCTRL 0xf800 /* Control bits. */ -#define VORTEX_FIFO_WTCTRL 0xf840 -#define FIFO_RDONLY 0x00000001 -#define FIFO_CTRL 0x00000002 /* Allow ctrl. ? */ -#define FIFO_VALID 0x00000010 -#define FIFO_EMPTY 0x00000020 -#define FIFO_U0 0x00001000 /* Unknown. */ -#define FIFO_U1 0x00010000 -#define FIFO_SIZE_BITS 5 -#define FIFO_SIZE (1<this_10 / 2 DWORD in size. */ -/* Starting at the MSB, each pair of bits seem to be the current DMA page. */ -/* This current page bits are consistent (same value) with VORTEX_ADBDMA_STAT) */ - -/* DMA */ -#define VORTEX_ENGINE_CTRL 0x27ae8 -#define ENGINE_INIT 0x1380000 - -/* WTDMA */ -#define VORTEX_WTDMA_CTRL 0x27900 /* format, DMA pos */ -#define VORTEX_WTDMA_STAT 0x27d00 /* DMA subbuf, DMA pos */ -#define WT_SUBBUF_MASK 0x3 -#define WT_SUBBUF_SHIFT 0xc -#define VORTEX_WTDMA_BUFBASE 0x27000 -#define VORTEX_WTDMA_BUFCFG0 0x27600 -#define VORTEX_WTDMA_BUFCFG1 0x27604 -#define VORTEX_WTDMA_START 0x27b00 /* which subbuffer is first */ - -/* ADB */ -#define VORTEX_ADB_SR 0x28400 /* Samplerates enable/disable */ -#define VORTEX_ADB_RTBASE 0x28000 -#define VORTEX_ADB_RTBASE_COUNT 173 -#define VORTEX_ADB_CHNBASE 0x282b4 -#define VORTEX_ADB_CHNBASE_COUNT 24 -#define ROUTE_MASK 0xffff -#define SOURCE_MASK 0xff00 -#define ADB_MASK 0xff -#define ADB_SHIFT 0x8 -/* ADB address */ -#define OFFSET_ADBDMA 0x00 -#define OFFSET_ADBDMAB 0x20 -#define OFFSET_SRCIN 0x40 -#define OFFSET_SRCOUT 0x20 /* ch 0x11 */ -#define OFFSET_MIXIN 0x50 /* ch 0x11 */ -#define OFFSET_MIXOUT 0x30 /* ch 0x11 */ -#define OFFSET_CODECIN 0x70 /* ch 0x11 */ /* adb source */ -#define OFFSET_CODECOUT 0x88 /* ch 0x11 */ /* adb target */ -#define OFFSET_SPORTIN 0x78 /* ch 0x13 ADB source. 2 routes. */ -#define OFFSET_SPORTOUT 0x90 /* ch 0x13 ADB sink. 2 routes. */ -#define OFFSET_SPDIFIN 0x7A /* ch 0x14 ADB source. */ -#define OFFSET_SPDIFOUT 0x92 /* ch 0x14 ADB sink. */ -#define OFFSET_AC98IN 0x7c /* ch 0x14 ADB source. */ -#define OFFSET_AC98OUT 0x94 /* ch 0x14 ADB sink. */ -#define OFFSET_EQIN 0xa0 /* ch 0x11 */ -#define OFFSET_EQOUT 0x7e /* ch 0x11 */ /* 2 routes on ch 0x11 */ -#define OFFSET_A3DIN 0x70 /* ADB sink. */ -#define OFFSET_A3DOUT 0xA6 /* ADB source. 2 routes per slice = 8 */ -#define OFFSET_WT0 0x40 /* WT bank 0 output. 0x40 - 0x65 */ -#define OFFSET_WT1 0x80 /* WT bank 1 output. 0x80 - 0xA5 */ -/* WT sources offset : 0x00-0x1f Direct stream. */ -/* WT sources offset : 0x20-0x25 Mixed Output. */ -#define OFFSET_XTALKOUT 0x66 /* crosstalk canceller (source) 2 routes */ -#define OFFSET_XTALKIN 0x96 /* crosstalk canceller (sink). 10 routes */ -#define OFFSET_EFXOUT 0x68 /* ADB source. 8 routes. */ -#define OFFSET_EFXIN 0x80 /* ADB sink. 8 routes. */ - -/* ADB route translate helper */ -#define ADB_DMA(x) (x) -#define ADB_SRCOUT(x) (x + OFFSET_SRCOUT) -#define ADB_SRCIN(x) (x + OFFSET_SRCIN) -#define ADB_MIXOUT(x) (x + OFFSET_MIXOUT) -#define ADB_MIXIN(x) (x + OFFSET_MIXIN) -#define ADB_CODECIN(x) (x + OFFSET_CODECIN) -#define ADB_CODECOUT(x) (x + OFFSET_CODECOUT) -#define ADB_SPORTIN(x) (x + OFFSET_SPORTIN) -#define ADB_SPORTOUT(x) (x + OFFSET_SPORTOUT) -#define ADB_SPDIFIN(x) (x + OFFSET_SPDIFIN) -#define ADB_SPDIFOUT(x) (x + OFFSET_SPDIFOUT) -#define ADB_EQIN(x) (x + OFFSET_EQIN) -#define ADB_EQOUT(x) (x + OFFSET_EQOUT) -#define ADB_A3DOUT(x) (x + OFFSET_A3DOUT) /* 0x10 A3D blocks */ -#define ADB_A3DIN(x) (x + OFFSET_A3DIN) -//#define ADB_WTOUT(x) ((x6dB (6dB = x4) 16 to 18 bit conversion? */ - -/* MIXER */ -#define VORTEX_MIXER_SR 0x21f00 -#define VORTEX_MIXER_CLIP 0x21f80 -#define VORTEX_MIXER_CHNBASE 0x21e40 -#define VORTEX_MIXER_RTBASE 0x21e00 -#define MIXER_RTBASE_SIZE 0x38 -#define VORTEX_MIX_ENIN 0x21a00 /* Input enable bits. 4 bits wide. */ -#define VORTEX_MIX_SMP 0x21c00 /* wave data buffers. AU8820: 0x9c00 */ - -/* MIX */ -#define VORTEX_MIX_INVOL_B 0x20000 /* Input volume current */ -#define VORTEX_MIX_VOL_B 0x20800 /* Output Volume current */ -#define VORTEX_MIX_INVOL_A 0x21000 /* Input Volume target */ -#define VORTEX_MIX_VOL_A 0x21800 /* Output Volume target */ - -#define VOL_MIN 0x80 /* Input volume when muted. */ -#define VOL_MAX 0x7f /* FIXME: Not confirmed! Just guessed. */ - -/* SRC */ -#define VORTEX_SRC_CHNBASE 0x26c40 -#define VORTEX_SRC_RTBASE 0x26c00 -#define VORTEX_SRCBLOCK_SR 0x26cc0 -#define VORTEX_SRC_SOURCE 0x26cc4 -#define VORTEX_SRC_SOURCESIZE 0x26cc8 -/* Params - 0x26e00 : 1 U0 - 0x26e40 : 2 CR - 0x26e80 : 3 U3 - 0x26ec0 : 4 DRIFT1 - 0x26f00 : 5 U1 - 0x26f40 : 6 DRIFT2 - 0x26f80 : 7 U2 : Target rate, direction -*/ - -#define VORTEX_SRC_CONVRATIO 0x26e40 -#define VORTEX_SRC_DRIFT0 0x26e80 -#define VORTEX_SRC_DRIFT1 0x26ec0 -#define VORTEX_SRC_DRIFT2 0x26f40 -#define VORTEX_SRC_U0 0x26e00 -#define U0_SLOWLOCK 0x200 -#define VORTEX_SRC_U1 0x26f00 -#define VORTEX_SRC_U2 0x26f80 -#define VORTEX_SRC_DATA 0x26800 /* 0xc800 */ -#define VORTEX_SRC_DATA0 0x26000 - -/* FIFO */ -#define VORTEX_FIFO_ADBCTRL 0x16100 /* Control bits. */ -#define VORTEX_FIFO_WTCTRL 0x16000 -#define FIFO_RDONLY 0x00000001 -#define FIFO_CTRL 0x00000002 /* Allow ctrl. ? */ -#define FIFO_VALID 0x00000010 -#define FIFO_EMPTY 0x00000020 -#define FIFO_U0 0x00002000 /* Unknown. */ -#define FIFO_U1 0x00040000 -#define FIFO_SIZE_BITS 6 -#define FIFO_SIZE (1<<(FIFO_SIZE_BITS)) // 0x40 -#define FIFO_MASK (FIFO_SIZE-1) //0x3f /* at shift left 0xc */ -#define FIFO_BITS 0x1c400000 -#define VORTEX_FIFO_ADBDATA 0x14000 -#define VORTEX_FIFO_WTDATA 0x10000 - -#define VORTEX_FIFO_GIRT 0x17000 /* wt0, wt1, adb */ -#define GIRT_COUNT 3 - -/* CODEC */ - -#define VORTEX_CODEC_CHN 0x29080 /* The name "CHN" is wrong. */ - -#define VORTEX_CODEC_CTRL 0x29184 -#define VORTEX_CODEC_IO 0x29188 - -#define VORTEX_CODEC_SPORTCTRL 0x2918c - -#define VORTEX_CODEC_EN 0x29190 -#define EN_AUDIO0 0x00000300 -#define EN_MODEM 0x00000c00 -#define EN_AUDIO1 0x00003000 -#define EN_SPORT 0x00030000 -#define EN_SPDIF 0x000c0000 -#define EN_CODEC (EN_AUDIO1 | EN_AUDIO0) - -#define VORTEX_SPDIF_SMPRATE 0x29194 - -#define VORTEX_SPDIF_FLAGS 0x2205c -#define VORTEX_SPDIF_CFG0 0x291D0 /* status data */ -#define VORTEX_SPDIF_CFG1 0x291D4 - -#define VORTEX_SMP_TIME 0x29198 /* Sample counter/timer */ -#define VORTEX_SMP_TIMER 0x2919c -#define VORTEX_CODEC2_CTRL 0x291a0 - -#define VORTEX_MODEM_CTRL 0x291ac - -/* IRQ */ -#define VORTEX_IRQ_SOURCE 0x2a000 /* Interrupt source flags. */ -#define VORTEX_IRQ_CTRL 0x2a004 /* Interrupt source mask. */ - -//#define VORTEX_IRQ_U0 0x2a008 /* ?? */ -#define VORTEX_STAT 0x2a008 /* Some sort of status */ -#define STAT_IRQ 0x00000001 /* This bitis set if the IRQ is valid. */ - -#define VORTEX_CTRL 0x2a00c -#define CTRL_MIDI_EN 0x00000001 -#define CTRL_MIDI_PORT 0x00000060 -#define CTRL_GAME_EN 0x00000008 -#define CTRL_GAME_PORT 0x00000e00 -#define CTRL_IRQ_ENABLE 0x00004000 -#define CTRL_SPDIF 0x00000000 /* unknown. Please find this value */ -#define CTRL_SPORT 0x00200000 -#define CTRL_RST 0x00800000 -#define CTRL_UNKNOWN 0x01000000 - -/* write: Timer period config / read: TIMER IRQ ack. */ -#define VORTEX_IRQ_STAT 0x2919c - - /* MIDI *//* GAME. */ -#define VORTEX_MIDI_DATA 0x28800 -#define VORTEX_MIDI_CMD 0x28804 /* Write command / Read status */ - -#define VORTEX_GAME_LEGACY 0x28808 -#define VORTEX_CTRL2 0x2880c -#define CTRL2_GAME_ADCMODE 0x40 -#define VORTEX_GAME_AXIS 0x28810 /* Axis base register. 4 axis's */ -#define AXIS_SIZE 4 -#define AXIS_RANGE 0x1fff diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0.c deleted file mode 100644 index f13ad536..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * ALSA driver for the Aureal Vortex family of soundprocessors. - * Author: Manuel Jander (mjander@embedded.cl) - * - * This driver is the result of the OpenVortex Project from Savannah - * (savannah.nongnu.org/projects/openvortex). I would like to thank - * the developers of OpenVortex, Jeff Muizelaar and Kester Maddock, from - * whom i got plenty of help, and their codebase was invaluable. - * Thanks to the ALSA developers, they helped a lot working out - * the ALSA part. - * Thanks also to Sourceforge for maintaining the old binary drivers, - * and the forum, where developers could comunicate. - * - * Now at least i can play Legacy DOOM with MIDI music :-) - */ - -#include "au88x0.h" -#include -#include -#include -#include -#include -#include -#include - -// module parameters (see "Module Parameters") -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static int pcifix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 255 }; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); -module_param_array(pcifix, int, NULL, 0444); -MODULE_PARM_DESC(pcifix, "Enable VIA-workaround for " CARD_NAME " soundcard."); - -MODULE_DESCRIPTION("Aureal vortex"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}"); - -MODULE_DEVICE_TABLE(pci, snd_vortex_ids); - -static void vortex_fix_latency(struct pci_dev *vortex) -{ - int rc; - if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) { - printk(KERN_INFO CARD_NAME - ": vortex latency is 0xff\n"); - } else { - printk(KERN_WARNING CARD_NAME - ": could not set vortex latency: pci error 0x%x\n", rc); - } -} - -static void vortex_fix_agp_bridge(struct pci_dev *via) -{ - int rc; - u8 value; - - /* - * only set the bit (Extend PCI#2 Internal Master for - * Efficient Handling of Dummy Requests) if the can - * read the config and it is not already set - */ - - if (!(rc = pci_read_config_byte(via, 0x42, &value)) - && ((value & 0x10) - || !(rc = pci_write_config_byte(via, 0x42, value | 0x10)))) { - printk(KERN_INFO CARD_NAME - ": bridge config is 0x%x\n", value | 0x10); - } else { - printk(KERN_WARNING CARD_NAME - ": could not set vortex latency: pci error 0x%x\n", rc); - } -} - -static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix) -{ - struct pci_dev *via = NULL; - - /* autodetect if workarounds are required */ - if (fix == 255) { - /* VIA KT133 */ - via = pci_get_device(PCI_VENDOR_ID_VIA, - PCI_DEVICE_ID_VIA_8365_1, NULL); - /* VIA Apollo */ - if (via == NULL) { - via = pci_get_device(PCI_VENDOR_ID_VIA, - PCI_DEVICE_ID_VIA_82C598_1, NULL); - /* AMD Irongate */ - if (via == NULL) - via = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL); - } - if (via) { - printk(KERN_INFO CARD_NAME ": Activating latency workaround...\n"); - vortex_fix_latency(vortex); - vortex_fix_agp_bridge(via); - } - } else { - if (fix & 0x1) - vortex_fix_latency(vortex); - if ((fix & 0x2) && (via = pci_get_device(PCI_VENDOR_ID_VIA, - PCI_DEVICE_ID_VIA_8365_1, NULL))) - vortex_fix_agp_bridge(via); - if ((fix & 0x4) && (via = pci_get_device(PCI_VENDOR_ID_VIA, - PCI_DEVICE_ID_VIA_82C598_1, NULL))) - vortex_fix_agp_bridge(via); - if ((fix & 0x8) && (via = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL))) - vortex_fix_agp_bridge(via); - } - pci_dev_put(via); -} - -// component-destructor -// (see "Management of Cards and Components") -static int snd_vortex_dev_free(struct snd_device *device) -{ - vortex_t *vortex = device->device_data; - - vortex_gameport_unregister(vortex); - vortex_core_shutdown(vortex); - // Take down PCI interface. - free_irq(vortex->irq, vortex); - iounmap(vortex->mmio); - pci_release_regions(vortex->pci_dev); - pci_disable_device(vortex->pci_dev); - kfree(vortex); - - return 0; -} - -// chip-specific constructor -// (see "Management of Cards and Components") -static int __devinit -snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) -{ - vortex_t *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_vortex_dev_free, - }; - - *rchip = NULL; - - // check PCI availability (DMA). - if ((err = pci_enable_device(pci)) < 0) - return err; - if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - printk(KERN_ERR "error to set DMA mask\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - - // initialize the stuff - chip->pci_dev = pci; - chip->io = pci_resource_start(pci, 0); - chip->vendor = pci->vendor; - chip->device = pci->device; - chip->card = card; - chip->irq = -1; - - // (1) PCI resource allocation - // Get MMIO area - // - if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0) - goto regions_out; - - chip->mmio = pci_ioremap_bar(pci, 0); - if (!chip->mmio) { - printk(KERN_ERR "MMIO area remap failed.\n"); - err = -ENOMEM; - goto ioremap_out; - } - - /* Init audio core. - * This must be done before we do request_irq otherwise we can get spurious - * interrupts that we do not handle properly and make a mess of things */ - if ((err = vortex_core_init(chip)) != 0) { - printk(KERN_ERR "hw core init failed\n"); - goto core_out; - } - - if ((err = request_irq(pci->irq, vortex_interrupt, - IRQF_SHARED, KBUILD_MODNAME, - chip)) != 0) { - printk(KERN_ERR "cannot grab irq\n"); - goto irq_out; - } - chip->irq = pci->irq; - - pci_set_master(pci); - // End of PCI setup. - - // Register alsa root device. - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - goto alloc_out; - } - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - - return 0; - - alloc_out: - free_irq(chip->irq, chip); - irq_out: - vortex_core_shutdown(chip); - core_out: - iounmap(chip->mmio); - ioremap_out: - pci_release_regions(chip->pci_dev); - regions_out: - pci_disable_device(chip->pci_dev); - //FIXME: this not the right place to unregister the gameport - vortex_gameport_unregister(chip); - kfree(chip); - return err; -} - -// constructor -- see "Constructor" sub-section -static int __devinit -snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - vortex_t *chip; - int err; - - // (1) - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - // (2) - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - // (3) - if ((err = snd_vortex_create(card, pci, &chip)) < 0) { - snd_card_free(card); - return err; - } - snd_vortex_workaround(pci, pcifix[dev]); - - // Card details needed in snd_vortex_midi - strcpy(card->driver, CARD_NAME_SHORT); - sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT); - sprintf(card->longname, "%s at 0x%lx irq %i", - card->shortname, chip->io, chip->irq); - - // (4) Alloc components. - err = snd_vortex_mixer(chip); - if (err < 0) { - snd_card_free(card); - return err; - } - // ADB pcm. - err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM); - if (err < 0) { - snd_card_free(card); - return err; - } -#ifndef CHIP_AU8820 - // ADB SPDIF - if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1)) < 0) { - snd_card_free(card); - return err; - } - // A3D - if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D)) < 0) { - snd_card_free(card); - return err; - } -#endif - /* - // ADB I2S - if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) { - snd_card_free(card); - return err; - } - */ -#ifndef CHIP_AU8810 - // WT pcm. - if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT)) < 0) { - snd_card_free(card); - return err; - } -#endif - if ((err = snd_vortex_midi(chip)) < 0) { - snd_card_free(card); - return err; - } - - vortex_gameport_register(chip); - -#if 0 - if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH, - sizeof(snd_vortex_synth_arg_t), &wave) < 0 - || wave == NULL) { - snd_printk(KERN_ERR "Can't initialize Aureal wavetable synth\n"); - } else { - snd_vortex_synth_arg_t *arg; - - arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); - strcpy(wave->name, "Aureal Synth"); - arg->hwptr = vortex; - arg->index = 1; - arg->seq_ports = seq_ports[dev]; - arg->max_voices = max_synth_voices[dev]; - } -#endif - - // (5) - if ((err = pci_read_config_word(pci, PCI_DEVICE_ID, - &(chip->device))) < 0) { - snd_card_free(card); - return err; - } - if ((err = pci_read_config_word(pci, PCI_VENDOR_ID, - &(chip->vendor))) < 0) { - snd_card_free(card); - return err; - } - chip->rev = pci->revision; -#ifdef CHIP_AU8830 - if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) { - printk(KERN_ALERT - "vortex: The revision (%x) of your card has not been seen before.\n", - chip->rev); - printk(KERN_ALERT - "vortex: Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n"); - snd_card_free(card); - err = -ENODEV; - return err; - } -#endif - - // (6) - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - // (7) - pci_set_drvdata(pci, card); - dev++; - vortex_connect_default(chip, 1); - vortex_enable_int(chip); - return 0; -} - -// destructor -- see "Destructor" sub-section -static void __devexit snd_vortex_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -// pci_driver definition -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_vortex_ids, - .probe = snd_vortex_probe, - .remove = __devexit_p(snd_vortex_remove), -}; - -// initialization of the module -static int __init alsa_card_vortex_init(void) -{ - return pci_register_driver(&driver); -} - -// clean up the module -static void __exit alsa_card_vortex_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_vortex_init) -module_exit(alsa_card_vortex_exit) diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0.h b/ANDROID_3.4.5/sound/pci/au88x0/au88x0.h deleted file mode 100644 index 466a5c8e..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * 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 Library 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. - */ - -#ifndef __SOUND_AU88X0_H -#define __SOUND_AU88X0_H - -#ifdef __KERNEL__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#ifndef CHIP_AU8820 -#include "au88x0_eq.h" -#include "au88x0_a3d.h" -#endif -#ifndef CHIP_AU8810 -#include "au88x0_wt.h" -#endif - -#define hwread(x,y) readl((x)+(y)) -#define hwwrite(x,y,z) writel((z),(x)+(y)) - -/* Vortex MPU401 defines. */ -#define MIDI_CLOCK_DIV 0x61 -/* Standart MPU401 defines. */ -#define MPU401_RESET 0xff -#define MPU401_ENTER_UART 0x3f -#define MPU401_ACK 0xfe - -// Get src register value to convert from x to y. -#define SRC_RATIO(x,y) ((((x<<15)/y) + 1)/2) - -/* FIFO software state constants. */ -#define FIFO_STOP 0 -#define FIFO_START 1 -#define FIFO_PAUSE 2 - -/* IRQ flags */ -#define IRQ_ERR_MASK 0x00ff -#define IRQ_FATAL 0x0001 -#define IRQ_PARITY 0x0002 -#define IRQ_REG 0x0004 -#define IRQ_FIFO 0x0008 -#define IRQ_DMA 0x0010 -#define IRQ_PCMOUT 0x0020 /* PCM OUT page crossing */ -#define IRQ_TIMER 0x1000 -#define IRQ_MIDI 0x2000 -#define IRQ_MODEM 0x4000 - -/* ADB Resource */ -#define VORTEX_RESOURCE_DMA 0x00000000 -#define VORTEX_RESOURCE_SRC 0x00000001 -#define VORTEX_RESOURCE_MIXIN 0x00000002 -#define VORTEX_RESOURCE_MIXOUT 0x00000003 -#define VORTEX_RESOURCE_A3D 0x00000004 -#define VORTEX_RESOURCE_LAST 0x00000005 - -/* codec io: VORTEX_CODEC_IO bits */ -#define VORTEX_CODEC_ID_SHIFT 24 -#define VORTEX_CODEC_WRITE 0x00800000 -#define VORTEX_CODEC_ADDSHIFT 16 -#define VORTEX_CODEC_ADDMASK 0x7f0000 -#define VORTEX_CODEC_DATSHIFT 0 -#define VORTEX_CODEC_DATMASK 0xffff - -/* Check for SDAC bit in "Extended audio ID" AC97 register */ -//#define VORTEX_IS_QUAD(x) (((x)->codec == NULL) ? 0 : ((x)->codec->ext_id&0x80)) -#define VORTEX_IS_QUAD(x) ((x)->isquad) -/* Check if chip has bug. */ -#define IS_BAD_CHIP(x) (\ - (x->rev == 0xfe && x->device == PCI_DEVICE_ID_AUREAL_VORTEX_2) || \ - (x->rev == 0xfe && x->device == PCI_DEVICE_ID_AUREAL_ADVANTAGE)) - - -/* PCM devices */ -#define VORTEX_PCM_ADB 0 -#define VORTEX_PCM_SPDIF 1 -#define VORTEX_PCM_A3D 2 -#define VORTEX_PCM_WT 3 -#define VORTEX_PCM_I2S 4 -#define VORTEX_PCM_LAST 5 - -#define MIX_CAPT(x) (vortex->mixcapt[x]) -#define MIX_PLAYB(x) (vortex->mixplayb[x]) -#define MIX_SPDIF(x) (vortex->mixspdif[x]) - -#define NR_WTPB 0x20 /* WT channels per each bank. */ -#define NR_PCM 0x10 - -struct pcm_vol { - struct snd_kcontrol *kctl; - int active; - int dma; - int mixin[4]; - int vol[4]; -}; - -/* Structs */ -typedef struct { - //int this_08; /* Still unknown */ - int fifo_enabled; /* this_24 */ - int fifo_status; /* this_1c */ - u32 dma_ctrl; /* this_78 (ADB), this_7c (WT) */ - int dma_unknown; /* this_74 (ADB), this_78 (WT). WDM: +8 */ - int cfg0; - int cfg1; - - int nr_ch; /* Nr of PCM channels in use */ - int type; /* Output type (ac97, a3d, spdif, i2s, dsp) */ - int dma; /* Hardware DMA index. */ - int dir; /* Stream Direction. */ - u32 resources[5]; - - /* Virtual page extender stuff */ - int nr_periods; - int period_bytes; - int period_real; - int period_virt; - - struct snd_pcm_substream *substream; -} stream_t; - -typedef struct snd_vortex vortex_t; -struct snd_vortex { - /* ALSA structs. */ - struct snd_card *card; - struct snd_pcm *pcm[VORTEX_PCM_LAST]; - - struct snd_rawmidi *rmidi; /* Legacy Midi interface. */ - struct snd_ac97 *codec; - - /* Stream structs. */ - stream_t dma_adb[NR_ADB]; - int spdif_sr; -#ifndef CHIP_AU8810 - stream_t dma_wt[NR_WT]; - wt_voice_t wt_voice[NR_WT]; /* WT register cache. */ - char mixwt[(NR_WT / NR_WTPB) * 6]; /* WT mixin objects */ -#endif - - /* Global resources */ - s8 mixcapt[2]; - s8 mixplayb[4]; -#ifndef CHIP_AU8820 - s8 mixspdif[2]; - s8 mixa3d[2]; /* mixers which collect all a3d streams. */ - s8 mixxtlk[2]; /* crosstalk canceler mixer inputs. */ -#endif - u32 fixed_res[5]; - -#ifndef CHIP_AU8820 - /* Hardware equalizer structs */ - eqlzr_t eq; - /* A3D structs */ - a3dsrc_t a3d[NR_A3D]; - /* Xtalk canceler */ - int xt_mode; /* 1: speakers, 0:headphones. */ -#endif - struct pcm_vol pcm_vol[NR_PCM]; - - int isquad; /* cache of extended ID codec flag. */ - - /* Gameport stuff. */ - struct gameport *gameport; - - /* PCI hardware resources */ - unsigned long io; - void __iomem *mmio; - unsigned int irq; - spinlock_t lock; - - /* PCI device */ - struct pci_dev *pci_dev; - u16 vendor; - u16 device; - u8 rev; -}; - -/* Functions. */ - -/* SRC */ -static void vortex_adb_setsrc(vortex_t * vortex, int adbdma, - unsigned int cvrt, int dir); - -/* DMA Engines. */ -static void vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, - int size, int count); -static void vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, - int dir, int fmt, int d, - u32 offset); -static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb); -#ifndef CHIP_AU8810 -static void vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, - int size, int count); -static void vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, /*int e, */ - u32 offset); -static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb); -#endif - -static void vortex_adbdma_startfifo(vortex_t * vortex, int adbdma); -//static void vortex_adbdma_stopfifo(vortex_t *vortex, int adbdma); -static void vortex_adbdma_pausefifo(vortex_t * vortex, int adbdma); -static void vortex_adbdma_resumefifo(vortex_t * vortex, int adbdma); -static inline int vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma); -static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma); - -#ifndef CHIP_AU8810 -static void vortex_wtdma_startfifo(vortex_t * vortex, int wtdma); -static void vortex_wtdma_stopfifo(vortex_t * vortex, int wtdma); -static void vortex_wtdma_pausefifo(vortex_t * vortex, int wtdma); -static void vortex_wtdma_resumefifo(vortex_t * vortex, int wtdma); -static inline int vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma); -#endif - -/* global stuff. */ -static void vortex_codec_init(vortex_t * vortex); -static void vortex_codec_write(struct snd_ac97 * codec, unsigned short addr, - unsigned short data); -static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short addr); -static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode); - -static int vortex_core_init(vortex_t * card); -static int vortex_core_shutdown(vortex_t * card); -static void vortex_enable_int(vortex_t * card); -static irqreturn_t vortex_interrupt(int irq, void *dev_id); -static int vortex_alsafmt_aspfmt(int alsafmt); - -/* Connection stuff. */ -static void vortex_connect_default(vortex_t * vortex, int en); -static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, - int dir, int type, int subdev); -static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, - int restype); -#ifndef CHIP_AU8810 -static int vortex_wt_allocroute(vortex_t * vortex, int dma, int nr_ch); -static void vortex_wt_connect(vortex_t * vortex, int en); -static void vortex_wt_init(vortex_t * vortex); -#endif - -static void vortex_route(vortex_t * vortex, int en, unsigned char channel, - unsigned char source, unsigned char dest); -#if 0 -static void vortex_routes(vortex_t * vortex, int en, unsigned char channel, - unsigned char source, unsigned char dest0, - unsigned char dest1); -#endif -static void vortex_connection_mixin_mix(vortex_t * vortex, int en, - unsigned char mixin, - unsigned char mix, int a); -static void vortex_mix_setinputvolumebyte(vortex_t * vortex, - unsigned char mix, int mixin, - unsigned char vol); -static void vortex_mix_setvolumebyte(vortex_t * vortex, unsigned char mix, - unsigned char vol); - -/* A3D functions. */ -#ifndef CHIP_AU8820 -static void vortex_Vort3D_enable(vortex_t * v); -static void vortex_Vort3D_disable(vortex_t * v); -static void vortex_Vort3D_connect(vortex_t * vortex, int en); -static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en); -#endif - -/* Driver stuff. */ -static int vortex_gameport_register(vortex_t * card); -static void vortex_gameport_unregister(vortex_t * card); -#ifndef CHIP_AU8820 -static int vortex_eq_init(vortex_t * vortex); -static int vortex_eq_free(vortex_t * vortex); -#endif -/* ALSA stuff. */ -static int snd_vortex_new_pcm(vortex_t * vortex, int idx, int nr); -static int snd_vortex_mixer(vortex_t * vortex); -static int snd_vortex_midi(vortex_t * vortex); -#endif diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.c deleted file mode 100644 index 9ae8b3b1..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.c +++ /dev/null @@ -1,914 +0,0 @@ -/*************************************************************************** - * au88x0_a3d.c - * - * Fri Jul 18 14:16:22 2003 - * Copyright 2003 mjander - * mjander@users.sourceforge.net - * - * A3D. You may think i'm crazy, but this may work someday. Who knows... - ****************************************************************************/ - -/* - * 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 Library 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 "au88x0_a3d.h" -#include "au88x0_a3ddata.c" -#include "au88x0_xtalk.h" -#include "au88x0.h" - -static void -a3dsrc_SetTimeConsts(a3dsrc_t * a, short HrtfTrack, short ItdTrack, - short GTrack, short CTrack) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_HrtfTrackTC), HrtfTrack); - hwwrite(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_ITDTrackTC), ItdTrack); - hwwrite(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_GainTrackTC), GTrack); - hwwrite(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_CoeffTrackTC), CTrack); -} - -#if 0 -static void -a3dsrc_GetTimeConsts(a3dsrc_t * a, short *HrtfTrack, short *ItdTrack, - short *GTrack, short *CTrack) -{ - // stub! -} - -#endif -/* Atmospheric absorption. */ - -static void -a3dsrc_SetAtmosTarget(a3dsrc_t * a, short aa, short b, short c, short d, - short e) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_A21Target), - (e << 0x10) | d); - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_B10Target), - (b << 0x10) | aa); - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_B2Target), c); -} - -static void -a3dsrc_SetAtmosCurrent(a3dsrc_t * a, short aa, short b, short c, short d, - short e) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_A12Current), - (e << 0x10) | d); - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_B01Current), - (b << 0x10) | aa); - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_B2Current), c); -} - -static void -a3dsrc_SetAtmosState(a3dsrc_t * a, short x1, short x2, short y1, short y2) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_x1), x1); - hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_x2), x2); - hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_y1), y1); - hwwrite(vortex->mmio, a3d_addrA(a->slice, a->source, A3D_A_y2), y2); -} - -#if 0 -static void -a3dsrc_GetAtmosTarget(a3dsrc_t * a, short *aa, short *b, short *c, - short *d, short *e) -{ -} -static void -a3dsrc_GetAtmosCurrent(a3dsrc_t * a, short *bb01, short *ab01, short *b2, - short *aa12, short *ba12) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - *aa12 = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_A12Current)); - *ba12 = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_A12Current)); - *ab01 = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_B01Current)); - *bb01 = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_B01Current)); - *b2 = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_B2Current)); -} - -static void -a3dsrc_GetAtmosState(a3dsrc_t * a, short *x1, short *x2, short *y1, short *y2) -{ - -} - -#endif -/* HRTF */ - -static void -a3dsrc_SetHrtfTarget(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - - for (i = 0; i < HRTF_SZ; i++) - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, - A3D_B_HrtfTarget) + (i << 2), - (b[i] << 0x10) | aa[i]); -} - -static void -a3dsrc_SetHrtfCurrent(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - - for (i = 0; i < HRTF_SZ; i++) - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, - A3D_B_HrtfCurrent) + (i << 2), - (b[i] << 0x10) | aa[i]); -} - -static void -a3dsrc_SetHrtfState(a3dsrc_t * a, a3d_Hrtf_t const aa, a3d_Hrtf_t const b) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - - for (i = 0; i < HRTF_SZ; i++) - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, - A3D_B_HrtfDelayLine) + (i << 2), - (b[i] << 0x10) | aa[i]); -} - -static void a3dsrc_SetHrtfOutput(a3dsrc_t * a, short left, short right) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_HrtfOutL), left); - hwwrite(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_HrtfOutR), right); -} - -#if 0 -static void a3dsrc_GetHrtfTarget(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - - for (i = 0; i < HRTF_SZ; i++) - aa[i] = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, - A3D_A_HrtfTarget + (i << 2))); - for (i = 0; i < HRTF_SZ; i++) - b[i] = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, - A3D_B_HrtfTarget + (i << 2))); -} - -static void a3dsrc_GetHrtfCurrent(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - - for (i = 0; i < HRTF_SZ; i++) - aa[i] = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, - A3D_A_HrtfCurrent + (i << 2))); - for (i = 0; i < HRTF_SZ; i++) - b[i] = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, - A3D_B_HrtfCurrent + (i << 2))); -} - -static void a3dsrc_GetHrtfState(a3dsrc_t * a, a3d_Hrtf_t aa, a3d_Hrtf_t b) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - // FIXME: verify this! - for (i = 0; i < HRTF_SZ; i++) - aa[i] = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, - A3D_A_HrtfDelayLine + (i << 2))); - for (i = 0; i < HRTF_SZ; i++) - b[i] = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, - A3D_B_HrtfDelayLine + (i << 2))); -} - -static void a3dsrc_GetHrtfOutput(a3dsrc_t * a, short *left, short *right) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - *left = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_HrtfOutL)); - *right = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_HrtfOutR)); -} - -#endif - -/* Interaural Time Difference. - * "The other main clue that humans use to locate sounds, is called - * Interaural Time Difference (ITD). The differences in distance from - * the sound source to a listeners ears means that the sound will - * reach one ear slightly before the other....", found somewhere with google.*/ -static void a3dsrc_SetItdTarget(a3dsrc_t * a, short litd, short ritd) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - - if (litd < 0) - litd = 0; - if (litd > 0x57FF) - litd = 0x57FF; - if (ritd < 0) - ritd = 0; - if (ritd > 0x57FF) - ritd = 0x57FF; - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_ITDTarget), - (ritd << 0x10) | litd); - //hwwrite(vortex->mmio, addr(0x191DF+5, this04, this08), (ritd<<0x10)|litd); -} - -static void a3dsrc_SetItdCurrent(a3dsrc_t * a, short litd, short ritd) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - - if (litd < 0) - litd = 0; - if (litd > 0x57FF) - litd = 0x57FF; - if (ritd < 0) - ritd = 0; - if (ritd > 0x57FF) - ritd = 0x57FF; - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_ITDCurrent), - (ritd << 0x10) | litd); - //hwwrite(vortex->mmio, addr(0x191DF+1, this04, this08), (ritd<<0x10)|litd); -} - -static void a3dsrc_SetItdDline(a3dsrc_t * a, a3d_ItdDline_t const dline) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - /* 45 != 40 -> Check this ! */ - for (i = 0; i < DLINE_SZ; i++) - hwwrite(vortex->mmio, - a3d_addrA(a->slice, a->source, - A3D_A_ITDDelayLine) + (i << 2), dline[i]); -} - -#if 0 -static void a3dsrc_GetItdTarget(a3dsrc_t * a, short *litd, short *ritd) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - *ritd = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_ITDTarget)); - *litd = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_ITDTarget)); -} - -static void a3dsrc_GetItdCurrent(a3dsrc_t * a, short *litd, short *ritd) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - - *ritd = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_ITDCurrent)); - *litd = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_ITDCurrent)); -} - -static void a3dsrc_GetItdDline(a3dsrc_t * a, a3d_ItdDline_t dline) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - - for (i = 0; i < DLINE_SZ; i++) - dline[i] = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, - A3D_A_ITDDelayLine + (i << 2))); -} - -#endif -/* This is may be used for ILD Interaural Level Difference. */ - -static void a3dsrc_SetGainTarget(a3dsrc_t * a, short left, short right) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_GainTarget), - (right << 0x10) | left); -} - -static void a3dsrc_SetGainCurrent(a3dsrc_t * a, short left, short right) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_GainCurrent), - (right << 0x10) | left); -} - -#if 0 -static void a3dsrc_GetGainTarget(a3dsrc_t * a, short *left, short *right) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - *right = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_GainTarget)); - *left = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_GainTarget)); -} - -static void a3dsrc_GetGainCurrent(a3dsrc_t * a, short *left, short *right) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - *right = - hwread(vortex->mmio, - a3d_addrA(a->slice, a->source, A3D_A_GainCurrent)); - *left = - hwread(vortex->mmio, - a3d_addrB(a->slice, a->source, A3D_B_GainCurrent)); -} - -/* CA3dIO this func seems to be inlined all over this place. */ -static void CA3dIO_WriteReg(a3dsrc_t * a, unsigned long addr, short aa, short b) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, addr, (aa << 0x10) | b); -} - -#endif -/* Generic A3D stuff */ - -static void a3dsrc_SetA3DSampleRate(a3dsrc_t * a, int sr) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int esp0 = 0; - - esp0 = (((esp0 & 0x7fffffff) | 0xB8000000) & 0x7) | ((sr & 0x1f) << 3); - hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), esp0); - //hwwrite(vortex->mmio, 0x19C38 + (this08<<0xd), esp0); -} - -static void a3dsrc_EnableA3D(a3dsrc_t * a) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), - 0xF0000001); - //hwwrite(vortex->mmio, 0x19C38 + (this08<<0xd), 0xF0000001); -} - -static void a3dsrc_DisableA3D(a3dsrc_t * a) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), - 0xF0000000); -} - -static void a3dsrc_SetA3DControlReg(a3dsrc_t * a, unsigned long ctrl) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd), ctrl); -} - -static void a3dsrc_SetA3DPointerReg(a3dsrc_t * a, unsigned long ptr) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - hwwrite(vortex->mmio, A3D_SLICE_Pointers + ((a->slice) << 0xd), ptr); -} - -#if 0 -static void a3dsrc_GetA3DSampleRate(a3dsrc_t * a, int *sr) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - *sr = ((hwread(vortex->mmio, A3D_SLICE_Control + (a->slice << 0xd)) - >> 3) & 0x1f); - //*sr = ((hwread(vortex->mmio, 0x19C38 + (this08<<0xd))>>3)&0x1f); -} - -static void a3dsrc_GetA3DControlReg(a3dsrc_t * a, unsigned long *ctrl) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - *ctrl = hwread(vortex->mmio, A3D_SLICE_Control + ((a->slice) << 0xd)); -} - -static void a3dsrc_GetA3DPointerReg(a3dsrc_t * a, unsigned long *ptr) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - *ptr = hwread(vortex->mmio, A3D_SLICE_Pointers + ((a->slice) << 0xd)); -} - -#endif -static void a3dsrc_ZeroSliceIO(a3dsrc_t * a) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - int i; - - for (i = 0; i < 8; i++) - hwwrite(vortex->mmio, - A3D_SLICE_VDBDest + - ((((a->slice) << 0xb) + i) << 2), 0); - for (i = 0; i < 4; i++) - hwwrite(vortex->mmio, - A3D_SLICE_VDBSource + - ((((a->slice) << 0xb) + i) << 2), 0); -} - -/* Reset Single A3D source. */ -static void a3dsrc_ZeroState(a3dsrc_t * a) -{ - /* - printk(KERN_DEBUG "vortex: ZeroState slice: %d, source %d\n", - a->slice, a->source); - */ - a3dsrc_SetAtmosState(a, 0, 0, 0, 0); - a3dsrc_SetHrtfState(a, A3dHrirZeros, A3dHrirZeros); - a3dsrc_SetItdDline(a, A3dItdDlineZeros); - a3dsrc_SetHrtfOutput(a, 0, 0); - a3dsrc_SetTimeConsts(a, 0, 0, 0, 0); - - a3dsrc_SetAtmosCurrent(a, 0, 0, 0, 0, 0); - a3dsrc_SetAtmosTarget(a, 0, 0, 0, 0, 0); - a3dsrc_SetItdCurrent(a, 0, 0); - a3dsrc_SetItdTarget(a, 0, 0); - a3dsrc_SetGainCurrent(a, 0, 0); - a3dsrc_SetGainTarget(a, 0, 0); - - a3dsrc_SetHrtfCurrent(a, A3dHrirZeros, A3dHrirZeros); - a3dsrc_SetHrtfTarget(a, A3dHrirZeros, A3dHrirZeros); -} - -/* Reset entire A3D engine */ -static void a3dsrc_ZeroStateA3D(a3dsrc_t * a) -{ - int i, var, var2; - - if ((a->vortex) == NULL) { - printk(KERN_ERR "vortex: ZeroStateA3D: ERROR: a->vortex is NULL\n"); - return; - } - - a3dsrc_SetA3DControlReg(a, 0); - a3dsrc_SetA3DPointerReg(a, 0); - - var = a->slice; - var2 = a->source; - for (i = 0; i < 4; i++) { - a->slice = i; - a3dsrc_ZeroSliceIO(a); - //a3dsrc_ZeroState(a); - } - a->source = var2; - a->slice = var; -} - -/* Program A3D block as pass through */ -static void a3dsrc_ProgramPipe(a3dsrc_t * a) -{ - a3dsrc_SetTimeConsts(a, 0, 0, 0, 0); - a3dsrc_SetAtmosCurrent(a, 0, 0x4000, 0, 0, 0); - a3dsrc_SetAtmosTarget(a, 0x4000, 0, 0, 0, 0); - a3dsrc_SetItdCurrent(a, 0, 0); - a3dsrc_SetItdTarget(a, 0, 0); - a3dsrc_SetGainCurrent(a, 0x7fff, 0x7fff); - a3dsrc_SetGainTarget(a, 0x7fff, 0x7fff); - - /* SET HRTF HERE */ - - /* Single spike leads to identity transfer function. */ - a3dsrc_SetHrtfCurrent(a, A3dHrirImpulse, A3dHrirImpulse); - a3dsrc_SetHrtfTarget(a, A3dHrirImpulse, A3dHrirImpulse); - - /* Test: Sounds saturated. */ - //a3dsrc_SetHrtfCurrent(a, A3dHrirSatTest, A3dHrirSatTest); - //a3dsrc_SetHrtfTarget(a, A3dHrirSatTest, A3dHrirSatTest); -} - -/* VDB = Vortex audio Dataflow Bus */ -#if 0 -static void a3dsrc_ClearVDBData(a3dsrc_t * a, unsigned long aa) -{ - vortex_t *vortex = (vortex_t *) (a->vortex); - - // ((aa >> 2) << 8) - (aa >> 2) - hwwrite(vortex->mmio, - a3d_addrS(a->slice, A3D_SLICE_VDBDest) + (a->source << 2), 0); - hwwrite(vortex->mmio, - a3d_addrS(a->slice, - A3D_SLICE_VDBDest + 4) + (a->source << 2), 0); - /* - hwwrite(vortex->mmio, 0x19c00 + (((aa>>2)*255*4)+aa)*8, 0); - hwwrite(vortex->mmio, 0x19c04 + (((aa>>2)*255*4)+aa)*8, 0); - */ -} -#endif - -/* A3D HwSource stuff. */ - -static void vortex_A3dSourceHw_Initialize(vortex_t * v, int source, int slice) -{ - a3dsrc_t *a3dsrc = &(v->a3d[source + (slice * 4)]); - //a3dsrc_t *a3dsrc = &(v->a3d[source + (slice*4)]); - - a3dsrc->vortex = (void *)v; - a3dsrc->source = source; /* source */ - a3dsrc->slice = slice; /* slice */ - a3dsrc_ZeroState(a3dsrc); - /* Added by me. */ - a3dsrc_SetA3DSampleRate(a3dsrc, 0x11); -} - -static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode) -{ - v->xt_mode = mode; /* this_14 */ - - vortex_XtalkHw_init(v); - vortex_XtalkHw_SetGainsAllChan(v); - switch (v->xt_mode) { - case XT_SPEAKER0: - vortex_XtalkHw_ProgramXtalkNarrow(v); - break; - case XT_SPEAKER1: - vortex_XtalkHw_ProgramXtalkWide(v); - break; - default: - case XT_HEADPHONE: - vortex_XtalkHw_ProgramPipe(v); - break; - case XT_DIAMOND: - vortex_XtalkHw_ProgramDiamondXtalk(v); - break; - } - vortex_XtalkHw_SetSampleRate(v, 0x11); - vortex_XtalkHw_Enable(v); - return 0; -} - -/* 3D Sound entry points. */ - -static int vortex_a3d_register_controls(vortex_t * vortex); -static void vortex_a3d_unregister_controls(vortex_t * vortex); -/* A3D base support init/shudown */ -static void __devinit vortex_Vort3D_enable(vortex_t * v) -{ - int i; - - Vort3DRend_Initialize(v, XT_HEADPHONE); - for (i = 0; i < NR_A3D; i++) { - vortex_A3dSourceHw_Initialize(v, i % 4, i >> 2); - a3dsrc_ZeroStateA3D(&(v->a3d[0])); - } - /* Register ALSA controls */ - vortex_a3d_register_controls(v); -} - -static void vortex_Vort3D_disable(vortex_t * v) -{ - vortex_XtalkHw_Disable(v); - vortex_a3d_unregister_controls(v); -} - -/* Make A3D subsystem connections. */ -static void vortex_Vort3D_connect(vortex_t * v, int en) -{ - int i; - -// Disable AU8810 routes, since they seem to be wrong (in au8810.h). -#ifdef CHIP_AU8810 - return; -#endif - -#if 1 - /* Alloc Xtalk mixin resources */ - v->mixxtlk[0] = - vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); - if (v->mixxtlk[0] < 0) { - printk - ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); - return; - } - v->mixxtlk[1] = - vortex_adb_checkinout(v, v->fixed_res, en, VORTEX_RESOURCE_MIXIN); - if (v->mixxtlk[1] < 0) { - printk - ("vortex: vortex_Vort3D: ERROR: not enough free mixer resources.\n"); - return; - } -#endif - - /* Connect A3D -> XTALK */ - for (i = 0; i < 4; i++) { - // 2 outputs per each A3D slice. - vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2), ADB_XTALKIN(i)); - vortex_route(v, en, 0x11, ADB_A3DOUT(i * 2) + 1, ADB_XTALKIN(5 + i)); - } -#if 0 - vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_EQIN(2)); - vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_EQIN(3)); -#else - /* Connect XTalk -> mixer */ - vortex_route(v, en, 0x11, ADB_XTALKOUT(0), ADB_MIXIN(v->mixxtlk[0])); - vortex_route(v, en, 0x11, ADB_XTALKOUT(1), ADB_MIXIN(v->mixxtlk[1])); - vortex_connection_mixin_mix(v, en, v->mixxtlk[0], v->mixplayb[0], 0); - vortex_connection_mixin_mix(v, en, v->mixxtlk[1], v->mixplayb[1], 0); - vortex_mix_setinputvolumebyte(v, v->mixplayb[0], v->mixxtlk[0], - en ? MIX_DEFIGAIN : VOL_MIN); - vortex_mix_setinputvolumebyte(v, v->mixplayb[1], v->mixxtlk[1], - en ? MIX_DEFIGAIN : VOL_MIN); - if (VORTEX_IS_QUAD(v)) { - vortex_connection_mixin_mix(v, en, v->mixxtlk[0], - v->mixplayb[2], 0); - vortex_connection_mixin_mix(v, en, v->mixxtlk[1], - v->mixplayb[3], 0); - vortex_mix_setinputvolumebyte(v, v->mixplayb[2], - v->mixxtlk[0], - en ? MIX_DEFIGAIN : VOL_MIN); - vortex_mix_setinputvolumebyte(v, v->mixplayb[3], - v->mixxtlk[1], - en ? MIX_DEFIGAIN : VOL_MIN); - } -#endif -} - -/* Initialize one single A3D source. */ -static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en) -{ - if (a->vortex == NULL) { - printk - ("vortex: Vort3D_InitializeSource: A3D source not initialized\n"); - return; - } - if (en) { - a3dsrc_ProgramPipe(a); - a3dsrc_SetA3DSampleRate(a, 0x11); - a3dsrc_SetTimeConsts(a, HrtfTCDefault, - ItdTCDefault, GainTCDefault, - CoefTCDefault); - /* Remark: zero gain is muted. */ - //a3dsrc_SetGainTarget(a,0,0); - //a3dsrc_SetGainCurrent(a,0,0); - a3dsrc_EnableA3D(a); - } else { - a3dsrc_DisableA3D(a); - a3dsrc_ZeroState(a); - } -} - -/* Conversion of coordinates into 3D parameters. */ - -static void vortex_a3d_coord2hrtf(a3d_Hrtf_t hrtf, int *coord) -{ - /* FIXME: implement this. */ - -} -static void vortex_a3d_coord2itd(a3d_Itd_t itd, int *coord) -{ - /* FIXME: implement this. */ - -} -static void vortex_a3d_coord2ild(a3d_LRGains_t ild, int left, int right) -{ - /* FIXME: implement this. */ - -} -static void vortex_a3d_translate_filter(a3d_atmos_t filter, int *params) -{ - /* FIXME: implement this. */ - -} - -/* ALSA control interface. */ - -static int -snd_vortex_a3d_hrtf_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 6; - uinfo->value.integer.min = 0x00000000; - uinfo->value.integer.max = 0xffffffff; - return 0; -} -static int -snd_vortex_a3d_itd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0x00000000; - uinfo->value.integer.max = 0xffffffff; - return 0; -} -static int -snd_vortex_a3d_ild_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0x00000000; - uinfo->value.integer.max = 0xffffffff; - return 0; -} -static int -snd_vortex_a3d_filter_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 4; - uinfo->value.integer.min = 0x00000000; - uinfo->value.integer.max = 0xffffffff; - return 0; -} - -static int -snd_vortex_a3d_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - //a3dsrc_t *a = kcontrol->private_data; - /* No read yet. Would this be really useable/needed ? */ - - return 0; -} - -static int -snd_vortex_a3d_hrtf_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - a3dsrc_t *a = kcontrol->private_data; - int changed = 1, i; - int coord[6]; - for (i = 0; i < 6; i++) - coord[i] = ucontrol->value.integer.value[i]; - /* Translate orientation coordinates to a3d params. */ - vortex_a3d_coord2hrtf(a->hrtf[0], coord); - vortex_a3d_coord2hrtf(a->hrtf[1], coord); - a3dsrc_SetHrtfTarget(a, a->hrtf[0], a->hrtf[1]); - a3dsrc_SetHrtfCurrent(a, a->hrtf[0], a->hrtf[1]); - return changed; -} - -static int -snd_vortex_a3d_itd_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - a3dsrc_t *a = kcontrol->private_data; - int coord[6]; - int i, changed = 1; - for (i = 0; i < 6; i++) - coord[i] = ucontrol->value.integer.value[i]; - /* Translate orientation coordinates to a3d params. */ - vortex_a3d_coord2itd(a->hrtf[0], coord); - vortex_a3d_coord2itd(a->hrtf[1], coord); - /* Inter aural time difference. */ - a3dsrc_SetItdTarget(a, a->itd[0], a->itd[1]); - a3dsrc_SetItdCurrent(a, a->itd[0], a->itd[1]); - a3dsrc_SetItdDline(a, a->dline); - return changed; -} - -static int -snd_vortex_a3d_ild_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - a3dsrc_t *a = kcontrol->private_data; - int changed = 1; - int l, r; - /* There may be some scale tranlation needed here. */ - l = ucontrol->value.integer.value[0]; - r = ucontrol->value.integer.value[1]; - vortex_a3d_coord2ild(a->ild, l, r); - /* Left Right panning. */ - a3dsrc_SetGainTarget(a, l, r); - a3dsrc_SetGainCurrent(a, l, r); - return changed; -} - -static int -snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - a3dsrc_t *a = kcontrol->private_data; - int i, changed = 1; - int params[6]; - for (i = 0; i < 6; i++) - params[i] = ucontrol->value.integer.value[i]; - /* Translate generic filter params to a3d filter params. */ - vortex_a3d_translate_filter(a->filter, params); - /* Atmospheric absorption and filtering. */ - a3dsrc_SetAtmosTarget(a, a->filter[0], - a->filter[1], a->filter[2], - a->filter[3], a->filter[4]); - a3dsrc_SetAtmosCurrent(a, a->filter[0], - a->filter[1], a->filter[2], - a->filter[3], a->filter[4]); - return changed; -} - -static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Playback PCM advanced processing", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = snd_vortex_a3d_hrtf_info, - .get = snd_vortex_a3d_get, - .put = snd_vortex_a3d_hrtf_put, -}; - -/* Control (un)registration. */ -static int __devinit vortex_a3d_register_controls(vortex_t * vortex) -{ - struct snd_kcontrol *kcontrol; - int err, i; - /* HRTF controls. */ - for (i = 0; i < NR_A3D; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) - return -ENOMEM; - kcontrol->id.numid = CTRLID_HRTF; - kcontrol->info = snd_vortex_a3d_hrtf_info; - kcontrol->put = snd_vortex_a3d_hrtf_put; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) - return err; - } - /* ITD controls. */ - for (i = 0; i < NR_A3D; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) - return -ENOMEM; - kcontrol->id.numid = CTRLID_ITD; - kcontrol->info = snd_vortex_a3d_itd_info; - kcontrol->put = snd_vortex_a3d_itd_put; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) - return err; - } - /* ILD (gains) controls. */ - for (i = 0; i < NR_A3D; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) - return -ENOMEM; - kcontrol->id.numid = CTRLID_GAINS; - kcontrol->info = snd_vortex_a3d_ild_info; - kcontrol->put = snd_vortex_a3d_ild_put; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) - return err; - } - /* Filter controls. */ - for (i = 0; i < NR_A3D; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) - return -ENOMEM; - kcontrol->id.numid = CTRLID_FILTER; - kcontrol->info = snd_vortex_a3d_filter_info; - kcontrol->put = snd_vortex_a3d_filter_put; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) - return err; - } - return 0; -} - -static void vortex_a3d_unregister_controls(vortex_t * vortex) -{ - -} - -/* End of File*/ diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.h b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.h deleted file mode 100644 index 0584c65b..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3d.h +++ /dev/null @@ -1,123 +0,0 @@ -/*************************************************************************** - * au88x0_a3d.h - * - * Fri Jul 18 14:16:03 2003 - * Copyright 2003 mjander - * mjander@users.sourceforge.net - ****************************************************************************/ - -/* - * 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 Library 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. - */ - -#ifndef _AU88X0_A3D_H -#define _AU88X0_A3D_H - -//#include - -#define HRTF_SZ 0x38 -#define DLINE_SZ 0x28 - -#define CTRLID_HRTF 1 -#define CTRLID_ITD 2 -#define CTRLID_ILD 4 -#define CTRLID_FILTER 8 -#define CTRLID_GAINS 16 - -/* 3D parameter structs */ -typedef unsigned short int a3d_Hrtf_t[HRTF_SZ]; -typedef unsigned short int a3d_ItdDline_t[DLINE_SZ]; -typedef unsigned short int a3d_atmos_t[5]; -typedef unsigned short int a3d_LRGains_t[2]; -typedef unsigned short int a3d_Itd_t[2]; -typedef unsigned short int a3d_Ild_t[2]; - -typedef struct { - void *vortex; // Formerly CAsp4HwIO*, now vortex_t*. - unsigned int source; /* this_04 */ - unsigned int slice; /* this_08 */ - a3d_Hrtf_t hrtf[2]; - a3d_Itd_t itd; - a3d_Ild_t ild; - a3d_ItdDline_t dline; - a3d_atmos_t filter; -} a3dsrc_t; - -/* First Register bank */ - -#define A3D_A_HrtfCurrent 0x18000 /* 56 ULONG */ -#define A3D_A_GainCurrent 0x180E0 -#define A3D_A_GainTarget 0x180E4 -#define A3D_A_A12Current 0x180E8 /* Atmospheric current. */ -#define A3D_A_A21Target 0x180EC /* Atmospheric target */ -#define A3D_A_B01Current 0x180F0 /* Atmospheric current */ -#define A3D_A_B10Target 0x180F4 /* Atmospheric target */ -#define A3D_A_B2Current 0x180F8 /* Atmospheric current */ -#define A3D_A_B2Target 0x180FC /* Atmospheric target */ -#define A3D_A_HrtfTarget 0x18100 /* 56 ULONG */ -#define A3D_A_ITDCurrent 0x181E0 -#define A3D_A_ITDTarget 0x181E4 -#define A3D_A_HrtfDelayLine 0x181E8 /* 56 ULONG */ -#define A3D_A_ITDDelayLine 0x182C8 /* 40/45 ULONG */ -#define A3D_A_HrtfTrackTC 0x1837C /* Time Constants */ -#define A3D_A_GainTrackTC 0x18380 -#define A3D_A_CoeffTrackTC 0x18384 -#define A3D_A_ITDTrackTC 0x18388 -#define A3D_A_x1 0x1838C -#define A3D_A_x2 0x18390 -#define A3D_A_y1 0x18394 -#define A3D_A_y2 0x18398 -#define A3D_A_HrtfOutL 0x1839C -#define A3D_A_HrtfOutR 0x183A0 -#define A3D_A_TAIL 0x183A4 - -/* Second register bank */ -#define A3D_B_HrtfCurrent 0x19000 /* 56 ULONG */ -#define A3D_B_GainCurrent 0x190E0 -#define A3D_B_GainTarget 0x190E4 -#define A3D_B_A12Current 0x190E8 -#define A3D_B_A21Target 0x190EC -#define A3D_B_B01Current 0x190F0 -#define A3D_B_B10Target 0x190F4 -#define A3D_B_B2Current 0x190F8 -#define A3D_B_B2Target 0x190FC -#define A3D_B_HrtfTarget 0x19100 /* 56 ULONG */ -#define A3D_B_ITDCurrent 0x191E0 -#define A3D_B_ITDTarget 0x191E4 -#define A3D_B_HrtfDelayLine 0x191E8 /* 56 ULONG */ -#define A3D_B_TAIL 0x192C8 - -/* There are 4 slices, 4 a3d each = 16 a3d sources. */ -#define A3D_SLICE_BANK_A 0x18000 /* 4 sources */ -#define A3D_SLICE_BANK_B 0x19000 /* 4 sources */ -#define A3D_SLICE_VDBDest 0x19C00 /* 8 ULONG */ -#define A3D_SLICE_VDBSource 0x19C20 /* 4 ULONG */ -#define A3D_SLICE_ABReg 0x19C30 -#define A3D_SLICE_CReg 0x19C34 -#define A3D_SLICE_Control 0x19C38 -#define A3D_SLICE_DebugReserved 0x19C3c /* Dangerous! */ -#define A3D_SLICE_Pointers 0x19C40 -#define A3D_SLICE_TAIL 0x1A000 - -// Slice size: 0x2000 -// Source size: 0x3A4, 0x2C8 - -/* Address generator macro. */ -#define a3d_addrA(slice,source,reg) (((slice)<<0xd)+((source)*0x3A4)+(reg)) -#define a3d_addrB(slice,source,reg) (((slice)<<0xd)+((source)*0x2C8)+(reg)) -#define a3d_addrS(slice,reg) (((slice)<<0xd)+(reg)) -//#define a3d_addr(slice,source,reg) (((reg)>=0x19000) ? a3d_addr2((slice),(source),(reg)) : a3d_addr1((slice),(source),(reg))) - -#endif /* _AU88X0_A3D_H */ diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3ddata.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3ddata.c deleted file mode 100644 index 6fab4bba..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_a3ddata.c +++ /dev/null @@ -1,91 +0,0 @@ -/*************************************************************************** - * au88x0_a3ddata.c - * - * Wed Nov 19 21:11:32 2003 - * Copyright 2003 mjander - * mjander@users.sourceforge.org - ****************************************************************************/ - -/* - * 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 Library 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. - */ - -/* Constant initializer values. */ - -static const a3d_Hrtf_t A3dHrirZeros = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0 -}; - -static const a3d_Hrtf_t A3dHrirImpulse = { - 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0 -}; - -static const a3d_Hrtf_t A3dHrirOnes = { - 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, - 0x7fff, - 0x7fff, - 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, - 0x7fff, - 0x7fff, - 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, - 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, - 0x7fff, - 0x7fff, - 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, - 0x7fff, - 0x7fff, - 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff -}; - -static const a3d_Hrtf_t A3dHrirSatTest = { - 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, - 0x7fff, - 0x7fff, - 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, - 0x8001, - 0x8001, - 0x7fff, 0x0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const a3d_Hrtf_t A3dHrirDImpulse = { - 0, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0 -}; - -static const a3d_ItdDline_t A3dItdDlineZeros = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static short const GainTCDefault = 0x300; -static short const ItdTCDefault = 0x0C8; -static short const HrtfTCDefault = 0x147; -static short const CoefTCDefault = 0x300; diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_core.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_core.c deleted file mode 100644 index 525f881f..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_core.c +++ /dev/null @@ -1,2856 +0,0 @@ -/* - * 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 Library 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. - */ - -/* - Vortex core low level functions. - - Author: Manuel Jander (mjander@users.sourceforge.cl) - These functions are mainly the result of translations made - from the original disassembly of the au88x0 binary drivers, - written by Aureal before they went down. - Many thanks to the Jeff Muizelaar, Kester Maddock, and whoever - contributed to the OpenVortex project. - The author of this file, put the few available pieces together - and translated the rest of the riddle (Mix, Src and connection stuff). - Some things are still to be discovered, and their meanings are unclear. - - Some of these functions aren't intended to be really used, rather - to help to understand how does the AU88X0 chips work. Keep them in, because - they could be used somewhere in the future. - - This code hasn't been tested or proof read thoroughly. If you wanna help, - take a look at the AU88X0 assembly and check if this matches. - Functions tested ok so far are (they show the desired effect - at least): - vortex_routes(); (1 bug fixed). - vortex_adb_addroute(); - vortex_adb_addroutes(); - vortex_connect_codecplay(); - vortex_src_flushbuffers(); - vortex_adbdma_setmode(); note: still some unknown arguments! - vortex_adbdma_startfifo(); - vortex_adbdma_stopfifo(); - vortex_fifo_setadbctrl(); note: still some unknown arguments! - vortex_mix_setinputvolumebyte(); - vortex_mix_enableinput(); - vortex_mixer_addWTD(); (fixed) - vortex_connection_adbdma_src_src(); - vortex_connection_adbdma_src(); - vortex_src_change_convratio(); - vortex_src_addWTD(); (fixed) - - History: - - 01-03-2003 First revision. - 01-21-2003 Some bug fixes. - 17-02-2003 many bugfixes after a big versioning mess. - 18-02-2003 JAAAAAHHHUUUUUU!!!! The mixer works !! I'm just so happy ! - (2 hours later...) I cant believe it! Im really lucky today. - Now the SRC is working too! Yeah! XMMS works ! - 20-02-2003 First steps into the ALSA world. - 28-02-2003 As my birthday present, i discovered how the DMA buffer pages really - work :-). It was all wrong. - 12-03-2003 ALSA driver starts working (2 channels). - 16-03-2003 More srcblock_setupchannel discoveries. - 12-04-2003 AU8830 playback support. Recording in the works. - 17-04-2003 vortex_route() and vortex_routes() bug fixes. AU8830 recording - works now, but chipn' dale effect is still there. - 16-05-2003 SrcSetupChannel cleanup. Moved the Src setup stuff entirely - into au88x0_pcm.c . - 06-06-2003 Buffer shifter bugfix. Mixer volume fix. - 07-12-2003 A3D routing finally fixed. Believed to be OK. - 25-03-2004 Many thanks to Claudia, for such valuable bug reports. - -*/ - -#include "au88x0.h" -#include "au88x0_a3d.h" -#include - -/* MIXER (CAsp4Mix.s and CAsp4Mixer.s) */ - -// FIXME: get rid of this. -static int mchannels[NR_MIXIN]; -static int rampchs[NR_MIXIN]; - -static void vortex_mixer_en_sr(vortex_t * vortex, int channel) -{ - hwwrite(vortex->mmio, VORTEX_MIXER_SR, - hwread(vortex->mmio, VORTEX_MIXER_SR) | (0x1 << channel)); -} -static void vortex_mixer_dis_sr(vortex_t * vortex, int channel) -{ - hwwrite(vortex->mmio, VORTEX_MIXER_SR, - hwread(vortex->mmio, VORTEX_MIXER_SR) & ~(0x1 << channel)); -} - -#if 0 -static void -vortex_mix_muteinputgain(vortex_t * vortex, unsigned char mix, - unsigned char channel) -{ - hwwrite(vortex->mmio, VORTEX_MIX_INVOL_A + ((mix << 5) + channel), - 0x80); - hwwrite(vortex->mmio, VORTEX_MIX_INVOL_B + ((mix << 5) + channel), - 0x80); -} - -static int vortex_mix_getvolume(vortex_t * vortex, unsigned char mix) -{ - int a; - a = hwread(vortex->mmio, VORTEX_MIX_VOL_A + (mix << 2)) & 0xff; - //FP2LinearFrac(a); - return (a); -} - -static int -vortex_mix_getinputvolume(vortex_t * vortex, unsigned char mix, - int channel, int *vol) -{ - int a; - if (!(mchannels[mix] & (1 << channel))) - return 0; - a = hwread(vortex->mmio, - VORTEX_MIX_INVOL_A + (((mix << 5) + channel) << 2)); - /* - if (rampchs[mix] == 0) - a = FP2LinearFrac(a); - else - a = FP2LinearFracWT(a); - */ - *vol = a; - return (0); -} - -static unsigned int vortex_mix_boost6db(unsigned char vol) -{ - return (vol + 8); /* WOW! what a complex function! */ -} - -static void vortex_mix_rampvolume(vortex_t * vortex, int mix) -{ - int ch; - char a; - // This function is intended for ramping down only (see vortex_disableinput()). - for (ch = 0; ch < 0x20; ch++) { - if (((1 << ch) & rampchs[mix]) == 0) - continue; - a = hwread(vortex->mmio, - VORTEX_MIX_INVOL_B + (((mix << 5) + ch) << 2)); - if (a > -126) { - a -= 2; - hwwrite(vortex->mmio, - VORTEX_MIX_INVOL_A + - (((mix << 5) + ch) << 2), a); - hwwrite(vortex->mmio, - VORTEX_MIX_INVOL_B + - (((mix << 5) + ch) << 2), a); - } else - vortex_mix_killinput(vortex, mix, ch); - } -} - -static int -vortex_mix_getenablebit(vortex_t * vortex, unsigned char mix, int mixin) -{ - int addr, temp; - if (mixin >= 0) - addr = mixin; - else - addr = mixin + 3; - addr = ((mix << 3) + (addr >> 2)) << 2; - temp = hwread(vortex->mmio, VORTEX_MIX_ENIN + addr); - return ((temp >> (mixin & 3)) & 1); -} -#endif -static void -vortex_mix_setvolumebyte(vortex_t * vortex, unsigned char mix, - unsigned char vol) -{ - int temp; - hwwrite(vortex->mmio, VORTEX_MIX_VOL_A + (mix << 2), vol); - if (1) { /*if (this_10) */ - temp = hwread(vortex->mmio, VORTEX_MIX_VOL_B + (mix << 2)); - if ((temp != 0x80) || (vol == 0x80)) - return; - } - hwwrite(vortex->mmio, VORTEX_MIX_VOL_B + (mix << 2), vol); -} - -static void -vortex_mix_setinputvolumebyte(vortex_t * vortex, unsigned char mix, - int mixin, unsigned char vol) -{ - int temp; - - hwwrite(vortex->mmio, - VORTEX_MIX_INVOL_A + (((mix << 5) + mixin) << 2), vol); - if (1) { /* this_10, initialized to 1. */ - temp = - hwread(vortex->mmio, - VORTEX_MIX_INVOL_B + (((mix << 5) + mixin) << 2)); - if ((temp != 0x80) || (vol == 0x80)) - return; - } - hwwrite(vortex->mmio, - VORTEX_MIX_INVOL_B + (((mix << 5) + mixin) << 2), vol); -} - -static void -vortex_mix_setenablebit(vortex_t * vortex, unsigned char mix, int mixin, int en) -{ - int temp, addr; - - if (mixin < 0) - addr = (mixin + 3); - else - addr = mixin; - addr = ((mix << 3) + (addr >> 2)) << 2; - temp = hwread(vortex->mmio, VORTEX_MIX_ENIN + addr); - if (en) - temp |= (1 << (mixin & 3)); - else - temp &= ~(1 << (mixin & 3)); - /* Mute input. Astatic void crackling? */ - hwwrite(vortex->mmio, - VORTEX_MIX_INVOL_B + (((mix << 5) + mixin) << 2), 0x80); - /* Looks like clear buffer. */ - hwwrite(vortex->mmio, VORTEX_MIX_SMP + (mixin << 2), 0x0); - hwwrite(vortex->mmio, VORTEX_MIX_SMP + 4 + (mixin << 2), 0x0); - /* Write enable bit. */ - hwwrite(vortex->mmio, VORTEX_MIX_ENIN + addr, temp); -} - -static void -vortex_mix_killinput(vortex_t * vortex, unsigned char mix, int mixin) -{ - rampchs[mix] &= ~(1 << mixin); - vortex_mix_setinputvolumebyte(vortex, mix, mixin, 0x80); - mchannels[mix] &= ~(1 << mixin); - vortex_mix_setenablebit(vortex, mix, mixin, 0); -} - -static void -vortex_mix_enableinput(vortex_t * vortex, unsigned char mix, int mixin) -{ - vortex_mix_killinput(vortex, mix, mixin); - if ((mchannels[mix] & (1 << mixin)) == 0) { - vortex_mix_setinputvolumebyte(vortex, mix, mixin, 0x80); /*0x80 : mute */ - mchannels[mix] |= (1 << mixin); - } - vortex_mix_setenablebit(vortex, mix, mixin, 1); -} - -static void -vortex_mix_disableinput(vortex_t * vortex, unsigned char mix, int channel, - int ramp) -{ - if (ramp) { - rampchs[mix] |= (1 << channel); - // Register callback. - //vortex_mix_startrampvolume(vortex); - vortex_mix_killinput(vortex, mix, channel); - } else - vortex_mix_killinput(vortex, mix, channel); -} - -static int -vortex_mixer_addWTD(vortex_t * vortex, unsigned char mix, unsigned char ch) -{ - int temp, lifeboat = 0, prev; - - temp = hwread(vortex->mmio, VORTEX_MIXER_SR); - if ((temp & (1 << ch)) == 0) { - hwwrite(vortex->mmio, VORTEX_MIXER_CHNBASE + (ch << 2), mix); - vortex_mixer_en_sr(vortex, ch); - return 1; - } - prev = VORTEX_MIXER_CHNBASE + (ch << 2); - temp = hwread(vortex->mmio, prev); - while (temp & 0x10) { - prev = VORTEX_MIXER_RTBASE + ((temp & 0xf) << 2); - temp = hwread(vortex->mmio, prev); - //printk(KERN_INFO "vortex: mixAddWTD: while addr=%x, val=%x\n", prev, temp); - if ((++lifeboat) > 0xf) { - printk(KERN_ERR - "vortex_mixer_addWTD: lifeboat overflow\n"); - return 0; - } - } - hwwrite(vortex->mmio, VORTEX_MIXER_RTBASE + ((temp & 0xf) << 2), mix); - hwwrite(vortex->mmio, prev, (temp & 0xf) | 0x10); - return 1; -} - -static int -vortex_mixer_delWTD(vortex_t * vortex, unsigned char mix, unsigned char ch) -{ - int esp14 = -1, esp18, eax, ebx, edx, ebp, esi = 0; - //int esp1f=edi(while)=src, esp10=ch; - - eax = hwread(vortex->mmio, VORTEX_MIXER_SR); - if (((1 << ch) & eax) == 0) { - printk(KERN_ERR "mix ALARM %x\n", eax); - return 0; - } - ebp = VORTEX_MIXER_CHNBASE + (ch << 2); - esp18 = hwread(vortex->mmio, ebp); - if (esp18 & 0x10) { - ebx = (esp18 & 0xf); - if (mix == ebx) { - ebx = VORTEX_MIXER_RTBASE + (mix << 2); - edx = hwread(vortex->mmio, ebx); - //7b60 - hwwrite(vortex->mmio, ebp, edx); - hwwrite(vortex->mmio, ebx, 0); - } else { - //7ad3 - edx = - hwread(vortex->mmio, - VORTEX_MIXER_RTBASE + (ebx << 2)); - //printk(KERN_INFO "vortex: mixdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src); - while ((edx & 0xf) != mix) { - if ((esi) > 0xf) { - printk(KERN_ERR - "vortex: mixdelWTD: error lifeboat overflow\n"); - return 0; - } - esp14 = ebx; - ebx = edx & 0xf; - ebp = ebx << 2; - edx = - hwread(vortex->mmio, - VORTEX_MIXER_RTBASE + ebp); - //printk(KERN_INFO "vortex: mixdelWTD: while addr=%x, val=%x\n", ebp, edx); - esi++; - } - //7b30 - ebp = ebx << 2; - if (edx & 0x10) { /* Delete entry in between others */ - ebx = VORTEX_MIXER_RTBASE + ((edx & 0xf) << 2); - edx = hwread(vortex->mmio, ebx); - //7b60 - hwwrite(vortex->mmio, - VORTEX_MIXER_RTBASE + ebp, edx); - hwwrite(vortex->mmio, ebx, 0); - //printk(KERN_INFO "vortex mixdelWTD between addr= 0x%x, val= 0x%x\n", ebp, edx); - } else { /* Delete last entry */ - //7b83 - if (esp14 == -1) - hwwrite(vortex->mmio, - VORTEX_MIXER_CHNBASE + - (ch << 2), esp18 & 0xef); - else { - ebx = (0xffffffe0 & edx) | (0xf & ebx); - hwwrite(vortex->mmio, - VORTEX_MIXER_RTBASE + - (esp14 << 2), ebx); - //printk(KERN_INFO "vortex mixdelWTD last addr= 0x%x, val= 0x%x\n", esp14, ebx); - } - hwwrite(vortex->mmio, - VORTEX_MIXER_RTBASE + ebp, 0); - return 1; - } - } - } else { - //printk(KERN_INFO "removed last mix\n"); - //7be0 - vortex_mixer_dis_sr(vortex, ch); - hwwrite(vortex->mmio, ebp, 0); - } - return 1; -} - -static void vortex_mixer_init(vortex_t * vortex) -{ - u32 addr; - int x; - - // FIXME: get rid of this crap. - memset(mchannels, 0, NR_MIXOUT * sizeof(int)); - memset(rampchs, 0, NR_MIXOUT * sizeof(int)); - - addr = VORTEX_MIX_SMP + 0x17c; - for (x = 0x5f; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0); - addr -= 4; - } - addr = VORTEX_MIX_ENIN + 0x1fc; - for (x = 0x7f; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0); - addr -= 4; - } - addr = VORTEX_MIX_SMP + 0x17c; - for (x = 0x5f; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0); - addr -= 4; - } - addr = VORTEX_MIX_INVOL_A + 0x7fc; - for (x = 0x1ff; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0x80); - addr -= 4; - } - addr = VORTEX_MIX_VOL_A + 0x3c; - for (x = 0xf; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0x80); - addr -= 4; - } - addr = VORTEX_MIX_INVOL_B + 0x7fc; - for (x = 0x1ff; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0x80); - addr -= 4; - } - addr = VORTEX_MIX_VOL_B + 0x3c; - for (x = 0xf; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0x80); - addr -= 4; - } - addr = VORTEX_MIXER_RTBASE + (MIXER_RTBASE_SIZE - 1) * 4; - for (x = (MIXER_RTBASE_SIZE - 1); x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0x0); - addr -= 4; - } - hwwrite(vortex->mmio, VORTEX_MIXER_SR, 0); - - /* Set clipping ceiling (this may be all wrong). */ - /* - for (x = 0; x < 0x80; x++) { - hwwrite(vortex->mmio, VORTEX_MIXER_CLIP + (x << 2), 0x3ffff); - } - */ - /* - call CAsp4Mix__Initialize_CAsp4HwIO____CAsp4Mixer____ - Register ISR callback for volume smooth fade out. - Maybe this avoids clicks when press "stop" ? - */ -} - -/* SRC (CAsp4Src.s and CAsp4SrcBlock) */ - -static void vortex_src_en_sr(vortex_t * vortex, int channel) -{ - hwwrite(vortex->mmio, VORTEX_SRCBLOCK_SR, - hwread(vortex->mmio, VORTEX_SRCBLOCK_SR) | (0x1 << channel)); -} - -static void vortex_src_dis_sr(vortex_t * vortex, int channel) -{ - hwwrite(vortex->mmio, VORTEX_SRCBLOCK_SR, - hwread(vortex->mmio, VORTEX_SRCBLOCK_SR) & ~(0x1 << channel)); -} - -static void vortex_src_flushbuffers(vortex_t * vortex, unsigned char src) -{ - int i; - - for (i = 0x1f; i >= 0; i--) - hwwrite(vortex->mmio, - VORTEX_SRC_DATA0 + (src << 7) + (i << 2), 0); - hwwrite(vortex->mmio, VORTEX_SRC_DATA + (src << 3), 0); - hwwrite(vortex->mmio, VORTEX_SRC_DATA + (src << 3) + 4, 0); -} - -static void vortex_src_cleardrift(vortex_t * vortex, unsigned char src) -{ - hwwrite(vortex->mmio, VORTEX_SRC_DRIFT0 + (src << 2), 0); - hwwrite(vortex->mmio, VORTEX_SRC_DRIFT1 + (src << 2), 0); - hwwrite(vortex->mmio, VORTEX_SRC_DRIFT2 + (src << 2), 1); -} - -static void -vortex_src_set_throttlesource(vortex_t * vortex, unsigned char src, int en) -{ - int temp; - - temp = hwread(vortex->mmio, VORTEX_SRC_SOURCE); - if (en) - temp |= 1 << src; - else - temp &= ~(1 << src); - hwwrite(vortex->mmio, VORTEX_SRC_SOURCE, temp); -} - -static int -vortex_src_persist_convratio(vortex_t * vortex, unsigned char src, int ratio) -{ - int temp, lifeboat = 0; - - do { - hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), ratio); - temp = hwread(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2)); - if ((++lifeboat) > 0x9) { - printk(KERN_ERR "Vortex: Src cvr fail\n"); - break; - } - } - while (temp != ratio); - return temp; -} - -#if 0 -static void vortex_src_slowlock(vortex_t * vortex, unsigned char src) -{ - int temp; - - hwwrite(vortex->mmio, VORTEX_SRC_DRIFT2 + (src << 2), 1); - hwwrite(vortex->mmio, VORTEX_SRC_DRIFT0 + (src << 2), 0); - temp = hwread(vortex->mmio, VORTEX_SRC_U0 + (src << 2)); - if (temp & 0x200) - hwwrite(vortex->mmio, VORTEX_SRC_U0 + (src << 2), - temp & ~0x200L); -} - -static void -vortex_src_change_convratio(vortex_t * vortex, unsigned char src, int ratio) -{ - int temp, a; - - if ((ratio & 0x10000) && (ratio != 0x10000)) { - if (ratio & 0x3fff) - a = (0x11 - ((ratio >> 0xe) & 0x3)) - 1; - else - a = (0x11 - ((ratio >> 0xe) & 0x3)) - 2; - } else - a = 0xc; - temp = hwread(vortex->mmio, VORTEX_SRC_U0 + (src << 2)); - if (((temp >> 4) & 0xf) != a) - hwwrite(vortex->mmio, VORTEX_SRC_U0 + (src << 2), - (temp & 0xf) | ((a & 0xf) << 4)); - - vortex_src_persist_convratio(vortex, src, ratio); -} - -static int -vortex_src_checkratio(vortex_t * vortex, unsigned char src, - unsigned int desired_ratio) -{ - int hw_ratio, lifeboat = 0; - - hw_ratio = hwread(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2)); - - while (hw_ratio != desired_ratio) { - hwwrite(vortex->mmio, VORTEX_SRC_CONVRATIO + (src << 2), desired_ratio); - - if ((lifeboat++) > 15) { - printk(KERN_ERR "Vortex: could not set src-%d from %d to %d\n", - src, hw_ratio, desired_ratio); - break; - } - } - - return hw_ratio; -} - -#endif -/* - Objective: Set samplerate for given SRC module. - Arguments: - card: pointer to vortex_t strcut. - src: Integer index of the SRC module. - cr: Current sample rate conversion factor. - b: unknown 16 bit value. - sweep: Enable Samplerate fade from cr toward tr flag. - dirplay: 1: playback, 0: recording. - sl: Slow Lock flag. - tr: Target samplerate conversion. - thsource: Throttle source flag (no idea what that means). -*/ -static void vortex_src_setupchannel(vortex_t * card, unsigned char src, - unsigned int cr, unsigned int b, int sweep, int d, - int dirplay, int sl, unsigned int tr, int thsource) -{ - // noplayback: d=2,4,7,0xa,0xb when using first 2 src's. - // c: enables pitch sweep. - // looks like g is c related. Maybe g is a sweep parameter ? - // g = cvr - // dirplay: 0 = recording, 1 = playback - // d = src hw index. - - int esi, ebp = 0, esp10; - - vortex_src_flushbuffers(card, src); - - if (sweep) { - if ((tr & 0x10000) && (tr != 0x10000)) { - tr = 0; - esi = 0x7; - } else { - if ((((short)tr) < 0) && (tr != 0x8000)) { - tr = 0; - esi = 0x8; - } else { - tr = 1; - esi = 0xc; - } - } - } else { - if ((cr & 0x10000) && (cr != 0x10000)) { - tr = 0; /*ebx = 0 */ - esi = 0x11 - ((cr >> 0xe) & 7); - if (cr & 0x3fff) - esi -= 1; - else - esi -= 2; - } else { - tr = 1; - esi = 0xc; - } - } - vortex_src_cleardrift(card, src); - vortex_src_set_throttlesource(card, src, thsource); - - if ((dirplay == 0) && (sweep == 0)) { - if (tr) - esp10 = 0xf; - else - esp10 = 0xc; - ebp = 0; - } else { - if (tr) - ebp = 0xf; - else - ebp = 0xc; - esp10 = 0; - } - hwwrite(card->mmio, VORTEX_SRC_U0 + (src << 2), - (sl << 0x9) | (sweep << 0x8) | ((esi & 0xf) << 4) | d); - /* 0xc0 esi=0xc c=f=0 d=0 */ - vortex_src_persist_convratio(card, src, cr); - hwwrite(card->mmio, VORTEX_SRC_U1 + (src << 2), b & 0xffff); - /* 0 b=0 */ - hwwrite(card->mmio, VORTEX_SRC_U2 + (src << 2), - (tr << 0x11) | (dirplay << 0x10) | (ebp << 0x8) | esp10); - /* 0x30f00 e=g=1 esp10=0 ebp=f */ - //printk(KERN_INFO "vortex: SRC %d, d=0x%x, esi=0x%x, esp10=0x%x, ebp=0x%x\n", src, d, esi, esp10, ebp); -} - -static void vortex_srcblock_init(vortex_t * vortex) -{ - u32 addr; - int x; - hwwrite(vortex->mmio, VORTEX_SRC_SOURCESIZE, 0x1ff); - /* - for (x=0; x<0x10; x++) { - vortex_src_init(&vortex_src[x], x); - } - */ - //addr = 0xcc3c; - //addr = 0x26c3c; - addr = VORTEX_SRC_RTBASE + 0x3c; - for (x = 0xf; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0); - addr -= 4; - } - //addr = 0xcc94; - //addr = 0x26c94; - addr = VORTEX_SRC_CHNBASE + 0x54; - for (x = 0x15; x >= 0; x--) { - hwwrite(vortex->mmio, addr, 0); - addr -= 4; - } -} - -static int -vortex_src_addWTD(vortex_t * vortex, unsigned char src, unsigned char ch) -{ - int temp, lifeboat = 0, prev; - // esp13 = src - - temp = hwread(vortex->mmio, VORTEX_SRCBLOCK_SR); - if ((temp & (1 << ch)) == 0) { - hwwrite(vortex->mmio, VORTEX_SRC_CHNBASE + (ch << 2), src); - vortex_src_en_sr(vortex, ch); - return 1; - } - prev = VORTEX_SRC_CHNBASE + (ch << 2); /*ebp */ - temp = hwread(vortex->mmio, prev); - //while (temp & NR_SRC) { - while (temp & 0x10) { - prev = VORTEX_SRC_RTBASE + ((temp & 0xf) << 2); /*esp12 */ - //prev = VORTEX_SRC_RTBASE + ((temp & (NR_SRC-1)) << 2); /*esp12*/ - temp = hwread(vortex->mmio, prev); - //printk(KERN_INFO "vortex: srcAddWTD: while addr=%x, val=%x\n", prev, temp); - if ((++lifeboat) > 0xf) { - printk(KERN_ERR - "vortex_src_addWTD: lifeboat overflow\n"); - return 0; - } - } - hwwrite(vortex->mmio, VORTEX_SRC_RTBASE + ((temp & 0xf) << 2), src); - //hwwrite(vortex->mmio, prev, (temp & (NR_SRC-1)) | NR_SRC); - hwwrite(vortex->mmio, prev, (temp & 0xf) | 0x10); - return 1; -} - -static int -vortex_src_delWTD(vortex_t * vortex, unsigned char src, unsigned char ch) -{ - int esp14 = -1, esp18, eax, ebx, edx, ebp, esi = 0; - //int esp1f=edi(while)=src, esp10=ch; - - eax = hwread(vortex->mmio, VORTEX_SRCBLOCK_SR); - if (((1 << ch) & eax) == 0) { - printk(KERN_ERR "src alarm\n"); - return 0; - } - ebp = VORTEX_SRC_CHNBASE + (ch << 2); - esp18 = hwread(vortex->mmio, ebp); - if (esp18 & 0x10) { - ebx = (esp18 & 0xf); - if (src == ebx) { - ebx = VORTEX_SRC_RTBASE + (src << 2); - edx = hwread(vortex->mmio, ebx); - //7b60 - hwwrite(vortex->mmio, ebp, edx); - hwwrite(vortex->mmio, ebx, 0); - } else { - //7ad3 - edx = - hwread(vortex->mmio, - VORTEX_SRC_RTBASE + (ebx << 2)); - //printk(KERN_INFO "vortex: srcdelWTD: 1 addr=%x, val=%x, src=%x\n", ebx, edx, src); - while ((edx & 0xf) != src) { - if ((esi) > 0xf) { - printk - ("vortex: srcdelWTD: error, lifeboat overflow\n"); - return 0; - } - esp14 = ebx; - ebx = edx & 0xf; - ebp = ebx << 2; - edx = - hwread(vortex->mmio, - VORTEX_SRC_RTBASE + ebp); - //printk(KERN_INFO "vortex: srcdelWTD: while addr=%x, val=%x\n", ebp, edx); - esi++; - } - //7b30 - ebp = ebx << 2; - if (edx & 0x10) { /* Delete entry in between others */ - ebx = VORTEX_SRC_RTBASE + ((edx & 0xf) << 2); - edx = hwread(vortex->mmio, ebx); - //7b60 - hwwrite(vortex->mmio, - VORTEX_SRC_RTBASE + ebp, edx); - hwwrite(vortex->mmio, ebx, 0); - //printk(KERN_INFO "vortex srcdelWTD between addr= 0x%x, val= 0x%x\n", ebp, edx); - } else { /* Delete last entry */ - //7b83 - if (esp14 == -1) - hwwrite(vortex->mmio, - VORTEX_SRC_CHNBASE + - (ch << 2), esp18 & 0xef); - else { - ebx = (0xffffffe0 & edx) | (0xf & ebx); - hwwrite(vortex->mmio, - VORTEX_SRC_RTBASE + - (esp14 << 2), ebx); - //printk(KERN_INFO"vortex srcdelWTD last addr= 0x%x, val= 0x%x\n", esp14, ebx); - } - hwwrite(vortex->mmio, - VORTEX_SRC_RTBASE + ebp, 0); - return 1; - } - } - } else { - //7be0 - vortex_src_dis_sr(vortex, ch); - hwwrite(vortex->mmio, ebp, 0); - } - return 1; -} - - /*FIFO*/ - -static void -vortex_fifo_clearadbdata(vortex_t * vortex, int fifo, int x) -{ - for (x--; x >= 0; x--) - hwwrite(vortex->mmio, - VORTEX_FIFO_ADBDATA + - (((fifo << FIFO_SIZE_BITS) + x) << 2), 0); -} - -#if 0 -static void vortex_fifo_adbinitialize(vortex_t * vortex, int fifo, int j) -{ - vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); -#ifdef CHIP_AU8820 - hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), - (FIFO_U1 | ((j & FIFO_MASK) << 0xb))); -#else - hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), - (FIFO_U1 | ((j & FIFO_MASK) << 0xc))); -#endif -} -#endif -static void vortex_fifo_setadbvalid(vortex_t * vortex, int fifo, int en) -{ - hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), - (hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)) & - 0xffffffef) | ((1 & en) << 4) | FIFO_U1); -} - -static void -vortex_fifo_setadbctrl(vortex_t * vortex, int fifo, int stereo, int priority, - int empty, int valid, int f) -{ - int temp, lifeboat = 0; - //int this_8[NR_ADB] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* position */ - int this_4 = 0x2; - /* f seems priority related. - * CAsp4AdbDma::SetPriority is the only place that calls SetAdbCtrl with f set to 1 - * every where else it is set to 0. It seems, however, that CAsp4AdbDma::SetPriority - * is never called, thus the f related bits remain a mystery for now. - */ - do { - temp = hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)); - if (lifeboat++ > 0xbb8) { - printk(KERN_ERR - "Vortex: vortex_fifo_setadbctrl fail\n"); - break; - } - } - while (temp & FIFO_RDONLY); - - // AU8830 semes to take some special care about fifo content (data). - // But i'm just to lazy to translate that :) - if (valid) { - if ((temp & FIFO_VALID) == 0) { - //this_8[fifo] = 0; - vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); // this_4 -#ifdef CHIP_AU8820 - temp = (this_4 & 0x1f) << 0xb; -#else - temp = (this_4 & 0x3f) << 0xc; -#endif - temp = (temp & 0xfffffffd) | ((stereo & 1) << 1); - temp = (temp & 0xfffffff3) | ((priority & 3) << 2); - temp = (temp & 0xffffffef) | ((valid & 1) << 4); - temp |= FIFO_U1; - temp = (temp & 0xffffffdf) | ((empty & 1) << 5); -#ifdef CHIP_AU8820 - temp = (temp & 0xfffbffff) | ((f & 1) << 0x12); -#endif -#ifdef CHIP_AU8830 - temp = (temp & 0xf7ffffff) | ((f & 1) << 0x1b); - temp = (temp & 0xefffffff) | ((f & 1) << 0x1c); -#endif -#ifdef CHIP_AU8810 - temp = (temp & 0xfeffffff) | ((f & 1) << 0x18); - temp = (temp & 0xfdffffff) | ((f & 1) << 0x19); -#endif - } - } else { - if (temp & FIFO_VALID) { -#ifdef CHIP_AU8820 - temp = ((f & 1) << 0x12) | (temp & 0xfffbffef); -#endif -#ifdef CHIP_AU8830 - temp = - ((f & 1) << 0x1b) | (temp & 0xe7ffffef) | FIFO_BITS; -#endif -#ifdef CHIP_AU8810 - temp = - ((f & 1) << 0x18) | (temp & 0xfcffffef) | FIFO_BITS; -#endif - } else - /*if (this_8[fifo]) */ - vortex_fifo_clearadbdata(vortex, fifo, FIFO_SIZE); - } - hwwrite(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2), temp); - hwread(vortex->mmio, VORTEX_FIFO_ADBCTRL + (fifo << 2)); -} - -#ifndef CHIP_AU8810 -static void vortex_fifo_clearwtdata(vortex_t * vortex, int fifo, int x) -{ - if (x < 1) - return; - for (x--; x >= 0; x--) - hwwrite(vortex->mmio, - VORTEX_FIFO_WTDATA + - (((fifo << FIFO_SIZE_BITS) + x) << 2), 0); -} - -static void vortex_fifo_wtinitialize(vortex_t * vortex, int fifo, int j) -{ - vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); -#ifdef CHIP_AU8820 - hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), - (FIFO_U1 | ((j & FIFO_MASK) << 0xb))); -#else - hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), - (FIFO_U1 | ((j & FIFO_MASK) << 0xc))); -#endif -} - -static void vortex_fifo_setwtvalid(vortex_t * vortex, int fifo, int en) -{ - hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), - (hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)) & - 0xffffffef) | ((en & 1) << 4) | FIFO_U1); -} - -static void -vortex_fifo_setwtctrl(vortex_t * vortex, int fifo, int ctrl, int priority, - int empty, int valid, int f) -{ - int temp = 0, lifeboat = 0; - int this_4 = 2; - - do { - temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); - if (lifeboat++ > 0xbb8) { - printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail\n"); - break; - } - } - while (temp & FIFO_RDONLY); - - if (valid) { - if ((temp & FIFO_VALID) == 0) { - vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); // this_4 -#ifdef CHIP_AU8820 - temp = (this_4 & 0x1f) << 0xb; -#else - temp = (this_4 & 0x3f) << 0xc; -#endif - temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); - temp = (temp & 0xfffffff3) | ((priority & 3) << 2); - temp = (temp & 0xffffffef) | ((valid & 1) << 4); - temp |= FIFO_U1; - temp = (temp & 0xffffffdf) | ((empty & 1) << 5); -#ifdef CHIP_AU8820 - temp = (temp & 0xfffbffff) | ((f & 1) << 0x12); -#endif -#ifdef CHIP_AU8830 - temp = (temp & 0xf7ffffff) | ((f & 1) << 0x1b); - temp = (temp & 0xefffffff) | ((f & 1) << 0x1c); -#endif -#ifdef CHIP_AU8810 - temp = (temp & 0xfeffffff) | ((f & 1) << 0x18); - temp = (temp & 0xfdffffff) | ((f & 1) << 0x19); -#endif - } - } else { - if (temp & FIFO_VALID) { -#ifdef CHIP_AU8820 - temp = ((f & 1) << 0x12) | (temp & 0xfffbffef); -#endif -#ifdef CHIP_AU8830 - temp = - ((f & 1) << 0x1b) | (temp & 0xe7ffffef) | FIFO_BITS; -#endif -#ifdef CHIP_AU8810 - temp = - ((f & 1) << 0x18) | (temp & 0xfcffffef) | FIFO_BITS; -#endif - } else - /*if (this_8[fifo]) */ - vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); - } - hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); - hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); - -/* - do { - temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); - if (lifeboat++ > 0xbb8) { - printk(KERN_ERR "Vortex: vortex_fifo_setwtctrl fail (hanging)\n"); - break; - } - } while ((temp & FIFO_RDONLY)&&(temp & FIFO_VALID)&&(temp != 0xFFFFFFFF)); - - - if (valid) { - if (temp & FIFO_VALID) { - temp = 0x40000; - //temp |= 0x08000000; - //temp |= 0x10000000; - //temp |= 0x04000000; - //temp |= 0x00400000; - temp |= 0x1c400000; - temp &= 0xFFFFFFF3; - temp &= 0xFFFFFFEF; - temp |= (valid & 1) << 4; - hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); - return; - } else { - vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); - return; - } - } else { - temp &= 0xffffffef; - temp |= 0x08000000; - temp |= 0x10000000; - temp |= 0x04000000; - temp |= 0x00400000; - hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); - temp = hwread(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2)); - //((temp >> 6) & 0x3f) - - priority = 0; - if (((temp & 0x0fc0) ^ ((temp >> 6) & 0x0fc0)) & 0FFFFFFC0) - vortex_fifo_clearwtdata(vortex, fifo, FIFO_SIZE); - valid = 0xfb; - temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); - temp = (temp & 0xfffdffff) | ((f & 1) << 0x11); - temp = (temp & 0xfffffff3) | ((priority & 3) << 2); - temp = (temp & 0xffffffef) | ((valid & 1) << 4); - temp = (temp & 0xffffffdf) | ((empty & 1) << 5); - hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); - } - - */ - - /* - temp = (temp & 0xfffffffd) | ((ctrl & 1) << 1); - temp = (temp & 0xfffdffff) | ((f & 1) << 0x11); - temp = (temp & 0xfffffff3) | ((priority & 3) << 2); - temp = (temp & 0xffffffef) | ((valid & 1) << 4); - temp = (temp & 0xffffffdf) | ((empty & 1) << 5); - #ifdef FIFO_BITS - temp = temp | FIFO_BITS | 40000; - #endif - // 0x1c440010, 0x1c400000 - hwwrite(vortex->mmio, VORTEX_FIFO_WTCTRL + (fifo << 2), temp); - */ -} - -#endif -static void vortex_fifo_init(vortex_t * vortex) -{ - int x; - u32 addr; - - /* ADB DMA channels fifos. */ - addr = VORTEX_FIFO_ADBCTRL + ((NR_ADB - 1) * 4); - for (x = NR_ADB - 1; x >= 0; x--) { - hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1)); - if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1)) - printk(KERN_ERR "bad adb fifo reset!"); - vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE); - addr -= 4; - } - -#ifndef CHIP_AU8810 - /* WT DMA channels fifos. */ - addr = VORTEX_FIFO_WTCTRL + ((NR_WT - 1) * 4); - for (x = NR_WT - 1; x >= 0; x--) { - hwwrite(vortex->mmio, addr, FIFO_U0); - if (hwread(vortex->mmio, addr) != FIFO_U0) - printk(KERN_ERR - "bad wt fifo reset (0x%08x, 0x%08x)!\n", - addr, hwread(vortex->mmio, addr)); - vortex_fifo_clearwtdata(vortex, x, FIFO_SIZE); - addr -= 4; - } -#endif - /* trigger... */ -#ifdef CHIP_AU8820 - hwwrite(vortex->mmio, 0xf8c0, 0xd03); //0x0843 0xd6b -#else -#ifdef CHIP_AU8830 - hwwrite(vortex->mmio, 0x17000, 0x61); /* wt a */ - hwwrite(vortex->mmio, 0x17004, 0x61); /* wt b */ -#endif - hwwrite(vortex->mmio, 0x17008, 0x61); /* adb */ -#endif -} - -/* ADBDMA */ - -static void vortex_adbdma_init(vortex_t * vortex) -{ -} - -static void vortex_adbdma_setfirstbuffer(vortex_t * vortex, int adbdma) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - - hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), - dma->dma_ctrl); -} - -static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - //hwwrite(vortex->mmio, VORTEX_ADBDMA_START + (adbdma << 2), sb << (((NR_ADB-1)-((adbdma&0xf)*2)))); - hwwrite(vortex->mmio, VORTEX_ADBDMA_START + (adbdma << 2), - sb << ((0xf - (adbdma & 0xf)) * 2)); - dma->period_real = dma->period_virt = sb; -} - -static void -vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma, - int psize, int count) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - - dma->period_bytes = psize; - dma->nr_periods = count; - - dma->cfg0 = 0; - dma->cfg1 = 0; - switch (count) { - /* Four or more pages */ - default: - case 4: - dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize - 1); - hwwrite(vortex->mmio, - VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0xc, - snd_pcm_sgbuf_get_addr(dma->substream, psize * 3)); - /* 3 pages */ - case 3: - dma->cfg0 |= 0x12000000; - dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); - hwwrite(vortex->mmio, - VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x8, - snd_pcm_sgbuf_get_addr(dma->substream, psize * 2)); - /* 2 pages */ - case 2: - dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize - 1); - hwwrite(vortex->mmio, - VORTEX_ADBDMA_BUFBASE + (adbdma << 4) + 0x4, - snd_pcm_sgbuf_get_addr(dma->substream, psize)); - /* 1 page */ - case 1: - dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize - 1) << 0xc); - hwwrite(vortex->mmio, - VORTEX_ADBDMA_BUFBASE + (adbdma << 4), - snd_pcm_sgbuf_get_addr(dma->substream, 0)); - break; - } - /* - printk(KERN_DEBUG "vortex: cfg0 = 0x%x\nvortex: cfg1=0x%x\n", - dma->cfg0, dma->cfg1); - */ - hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG0 + (adbdma << 3), dma->cfg0); - hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFCFG1 + (adbdma << 3), dma->cfg1); - - vortex_adbdma_setfirstbuffer(vortex, adbdma); - vortex_adbdma_setstartbuffer(vortex, adbdma, 0); -} - -static void -vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, int dir, - int fmt, int stereo, u32 offset) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - - dma->dma_unknown = stereo; - dma->dma_ctrl = - ((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK)); - /* Enable PCMOUT interrupts. */ - dma->dma_ctrl = - (dma->dma_ctrl & ~IE_MASK) | ((ie << IE_SHIFT) & IE_MASK); - - dma->dma_ctrl = - (dma->dma_ctrl & ~DIR_MASK) | ((dir << DIR_SHIFT) & DIR_MASK); - dma->dma_ctrl = - (dma->dma_ctrl & ~FMT_MASK) | ((fmt << FMT_SHIFT) & FMT_MASK); - - hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), - dma->dma_ctrl); - hwread(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2)); -} - -static int vortex_adbdma_bufshift(vortex_t * vortex, int adbdma) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - int page, p, pp, delta, i; - - page = - (hwread(vortex->mmio, VORTEX_ADBDMA_STAT + (adbdma << 2)) & - ADB_SUBBUF_MASK) >> ADB_SUBBUF_SHIFT; - if (dma->nr_periods >= 4) - delta = (page - dma->period_real) & 3; - else { - delta = (page - dma->period_real); - if (delta < 0) - delta += dma->nr_periods; - } - if (delta == 0) - return 0; - - /* refresh hw page table */ - if (dma->nr_periods > 4) { - for (i = 0; i < delta; i++) { - /* p: audio buffer page index */ - p = dma->period_virt + i + 4; - if (p >= dma->nr_periods) - p -= dma->nr_periods; - /* pp: hardware DMA page index. */ - pp = dma->period_real + i; - if (pp >= 4) - pp -= 4; - //hwwrite(vortex->mmio, VORTEX_ADBDMA_BUFBASE+(((adbdma << 2)+pp) << 2), dma->table[p].addr); - hwwrite(vortex->mmio, - VORTEX_ADBDMA_BUFBASE + (((adbdma << 2) + pp) << 2), - snd_pcm_sgbuf_get_addr(dma->substream, - dma->period_bytes * p)); - /* Force write thru cache. */ - hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + - (((adbdma << 2) + pp) << 2)); - } - } - dma->period_virt += delta; - dma->period_real = page; - if (dma->period_virt >= dma->nr_periods) - dma->period_virt -= dma->nr_periods; - if (delta != 1) - printk(KERN_INFO "vortex: %d virt=%d, real=%d, delta=%d\n", - adbdma, dma->period_virt, dma->period_real, delta); - - return delta; -} - - -static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma) { - stream_t *dma = &vortex->dma_adb[adbdma]; - int p, pp, i; - - /* refresh hw page table */ - for (i=0 ; i < 4 && i < dma->nr_periods; i++) { - /* p: audio buffer page index */ - p = dma->period_virt + i; - if (p >= dma->nr_periods) - p -= dma->nr_periods; - /* pp: hardware DMA page index. */ - pp = dma->period_real + i; - if (dma->nr_periods < 4) { - if (pp >= dma->nr_periods) - pp -= dma->nr_periods; - } - else { - if (pp >= 4) - pp -= 4; - } - hwwrite(vortex->mmio, - VORTEX_ADBDMA_BUFBASE + (((adbdma << 2) + pp) << 2), - snd_pcm_sgbuf_get_addr(dma->substream, - dma->period_bytes * p)); - /* Force write thru cache. */ - hwread(vortex->mmio, VORTEX_ADBDMA_BUFBASE + (((adbdma << 2)+pp) << 2)); - } -} - -static inline int vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - int temp, page, delta; - - temp = hwread(vortex->mmio, VORTEX_ADBDMA_STAT + (adbdma << 2)); - page = (temp & ADB_SUBBUF_MASK) >> ADB_SUBBUF_SHIFT; - if (dma->nr_periods >= 4) - delta = (page - dma->period_real) & 3; - else { - delta = (page - dma->period_real); - if (delta < 0) - delta += dma->nr_periods; - } - return (dma->period_virt + delta) * dma->period_bytes - + (temp & (dma->period_bytes - 1)); -} - -static void vortex_adbdma_startfifo(vortex_t * vortex, int adbdma) -{ - int this_8 = 0 /*empty */ , this_4 = 0 /*priority */ ; - stream_t *dma = &vortex->dma_adb[adbdma]; - - switch (dma->fifo_status) { - case FIFO_START: - vortex_fifo_setadbvalid(vortex, adbdma, - dma->fifo_enabled ? 1 : 0); - break; - case FIFO_STOP: - this_8 = 1; - hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), - dma->dma_ctrl); - vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, - this_4, this_8, - dma->fifo_enabled ? 1 : 0, 0); - break; - case FIFO_PAUSE: - vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, - this_4, this_8, - dma->fifo_enabled ? 1 : 0, 0); - break; - } - dma->fifo_status = FIFO_START; -} - -static void vortex_adbdma_resumefifo(vortex_t * vortex, int adbdma) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - - int this_8 = 1, this_4 = 0; - switch (dma->fifo_status) { - case FIFO_STOP: - hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), - dma->dma_ctrl); - vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, - this_4, this_8, - dma->fifo_enabled ? 1 : 0, 0); - break; - case FIFO_PAUSE: - vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, - this_4, this_8, - dma->fifo_enabled ? 1 : 0, 0); - break; - } - dma->fifo_status = FIFO_START; -} - -static void vortex_adbdma_pausefifo(vortex_t * vortex, int adbdma) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - - int this_8 = 0, this_4 = 0; - switch (dma->fifo_status) { - case FIFO_START: - vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, - this_4, this_8, 0, 0); - break; - case FIFO_STOP: - hwwrite(vortex->mmio, VORTEX_ADBDMA_CTRL + (adbdma << 2), - dma->dma_ctrl); - vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, - this_4, this_8, 0, 0); - break; - } - dma->fifo_status = FIFO_PAUSE; -} - -static void vortex_adbdma_stopfifo(vortex_t * vortex, int adbdma) -{ - stream_t *dma = &vortex->dma_adb[adbdma]; - - int this_4 = 0, this_8 = 0; - if (dma->fifo_status == FIFO_START) - vortex_fifo_setadbctrl(vortex, adbdma, dma->dma_unknown, - this_4, this_8, 0, 0); - else if (dma->fifo_status == FIFO_STOP) - return; - dma->fifo_status = FIFO_STOP; - dma->fifo_enabled = 0; -} - -/* WTDMA */ - -#ifndef CHIP_AU8810 -static void vortex_wtdma_setfirstbuffer(vortex_t * vortex, int wtdma) -{ - //int this_7c=dma_ctrl; - stream_t *dma = &vortex->dma_wt[wtdma]; - - hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl); -} - -static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - //hwwrite(vortex->mmio, VORTEX_WTDMA_START + (wtdma << 2), sb << ((0x1f-(wtdma&0xf)*2))); - hwwrite(vortex->mmio, VORTEX_WTDMA_START + (wtdma << 2), - sb << ((0xf - (wtdma & 0xf)) * 2)); - dma->period_real = dma->period_virt = sb; -} - -static void -vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma, - int psize, int count) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - - dma->period_bytes = psize; - dma->nr_periods = count; - - dma->cfg0 = 0; - dma->cfg1 = 0; - switch (count) { - /* Four or more pages */ - default: - case 4: - dma->cfg1 |= 0x88000000 | 0x44000000 | 0x30000000 | (psize-1); - hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0xc, - snd_pcm_sgbuf_get_addr(dma->substream, psize * 3)); - /* 3 pages */ - case 3: - dma->cfg0 |= 0x12000000; - dma->cfg1 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); - hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x8, - snd_pcm_sgbuf_get_addr(dma->substream, psize * 2)); - /* 2 pages */ - case 2: - dma->cfg0 |= 0x88000000 | 0x44000000 | 0x10000000 | (psize-1); - hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4) + 0x4, - snd_pcm_sgbuf_get_addr(dma->substream, psize)); - /* 1 page */ - case 1: - dma->cfg0 |= 0x80000000 | 0x40000000 | ((psize-1) << 0xc); - hwwrite(vortex->mmio, VORTEX_WTDMA_BUFBASE + (wtdma << 4), - snd_pcm_sgbuf_get_addr(dma->substream, 0)); - break; - } - hwwrite(vortex->mmio, VORTEX_WTDMA_BUFCFG0 + (wtdma << 3), dma->cfg0); - hwwrite(vortex->mmio, VORTEX_WTDMA_BUFCFG1 + (wtdma << 3), dma->cfg1); - - vortex_wtdma_setfirstbuffer(vortex, wtdma); - vortex_wtdma_setstartbuffer(vortex, wtdma, 0); -} - -static void -vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, - /*int e, */ u32 offset) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - - //dma->this_08 = e; - dma->dma_unknown = d; - dma->dma_ctrl = 0; - dma->dma_ctrl = - ((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK)); - /* PCMOUT interrupt */ - dma->dma_ctrl = - (dma->dma_ctrl & ~IE_MASK) | ((ie << IE_SHIFT) & IE_MASK); - /* Always playback. */ - dma->dma_ctrl |= (1 << DIR_SHIFT); - /* Audio Format */ - dma->dma_ctrl = - (dma->dma_ctrl & FMT_MASK) | ((fmt << FMT_SHIFT) & FMT_MASK); - /* Write into hardware */ - hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), dma->dma_ctrl); -} - -static int vortex_wtdma_bufshift(vortex_t * vortex, int wtdma) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - int page, p, pp, delta, i; - - page = - (hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) & - WT_SUBBUF_MASK) - >> WT_SUBBUF_SHIFT; - if (dma->nr_periods >= 4) - delta = (page - dma->period_real) & 3; - else { - delta = (page - dma->period_real); - if (delta < 0) - delta += dma->nr_periods; - } - if (delta == 0) - return 0; - - /* refresh hw page table */ - if (dma->nr_periods > 4) { - for (i = 0; i < delta; i++) { - /* p: audio buffer page index */ - p = dma->period_virt + i + 4; - if (p >= dma->nr_periods) - p -= dma->nr_periods; - /* pp: hardware DMA page index. */ - pp = dma->period_real + i; - if (pp >= 4) - pp -= 4; - hwwrite(vortex->mmio, - VORTEX_WTDMA_BUFBASE + - (((wtdma << 2) + pp) << 2), - snd_pcm_sgbuf_get_addr(dma->substream, - dma->period_bytes * p)); - /* Force write thru cache. */ - hwread(vortex->mmio, VORTEX_WTDMA_BUFBASE + - (((wtdma << 2) + pp) << 2)); - } - } - dma->period_virt += delta; - if (dma->period_virt >= dma->nr_periods) - dma->period_virt -= dma->nr_periods; - dma->period_real = page; - - if (delta != 1) - printk(KERN_WARNING "vortex: wt virt = %d, delta = %d\n", - dma->period_virt, delta); - - return delta; -} - -#if 0 -static void -vortex_wtdma_getposition(vortex_t * vortex, int wtdma, int *subbuf, int *pos) -{ - int temp; - temp = hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)); - *subbuf = (temp >> WT_SUBBUF_SHIFT) & WT_SUBBUF_MASK; - *pos = temp & POS_MASK; -} - -static int vortex_wtdma_getcursubuffer(vortex_t * vortex, int wtdma) -{ - return ((hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) >> - POS_SHIFT) & POS_MASK); -} -#endif -static inline int vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - int temp; - - temp = hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)); - temp = (dma->period_virt * dma->period_bytes) + (temp & (dma->period_bytes - 1)); - return temp; -} - -static void vortex_wtdma_startfifo(vortex_t * vortex, int wtdma) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - int this_8 = 0, this_4 = 0; - - switch (dma->fifo_status) { - case FIFO_START: - vortex_fifo_setwtvalid(vortex, wtdma, - dma->fifo_enabled ? 1 : 0); - break; - case FIFO_STOP: - this_8 = 1; - hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), - dma->dma_ctrl); - vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, - this_4, this_8, - dma->fifo_enabled ? 1 : 0, 0); - break; - case FIFO_PAUSE: - vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, - this_4, this_8, - dma->fifo_enabled ? 1 : 0, 0); - break; - } - dma->fifo_status = FIFO_START; -} - -static void vortex_wtdma_resumefifo(vortex_t * vortex, int wtdma) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - - int this_8 = 0, this_4 = 0; - switch (dma->fifo_status) { - case FIFO_STOP: - hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), - dma->dma_ctrl); - vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, - this_4, this_8, - dma->fifo_enabled ? 1 : 0, 0); - break; - case FIFO_PAUSE: - vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, - this_4, this_8, - dma->fifo_enabled ? 1 : 0, 0); - break; - } - dma->fifo_status = FIFO_START; -} - -static void vortex_wtdma_pausefifo(vortex_t * vortex, int wtdma) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - - int this_8 = 0, this_4 = 0; - switch (dma->fifo_status) { - case FIFO_START: - vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, - this_4, this_8, 0, 0); - break; - case FIFO_STOP: - hwwrite(vortex->mmio, VORTEX_WTDMA_CTRL + (wtdma << 2), - dma->dma_ctrl); - vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, - this_4, this_8, 0, 0); - break; - } - dma->fifo_status = FIFO_PAUSE; -} - -static void vortex_wtdma_stopfifo(vortex_t * vortex, int wtdma) -{ - stream_t *dma = &vortex->dma_wt[wtdma]; - - int this_4 = 0, this_8 = 0; - if (dma->fifo_status == FIFO_START) - vortex_fifo_setwtctrl(vortex, wtdma, dma->dma_unknown, - this_4, this_8, 0, 0); - else if (dma->fifo_status == FIFO_STOP) - return; - dma->fifo_status = FIFO_STOP; - dma->fifo_enabled = 0; -} - -#endif -/* ADB Routes */ - -typedef int ADBRamLink; -static void vortex_adb_init(vortex_t * vortex) -{ - int i; - /* it looks like we are writing more than we need to... - * if we write what we are supposed to it breaks things... */ - hwwrite(vortex->mmio, VORTEX_ADB_SR, 0); - for (i = 0; i < VORTEX_ADB_RTBASE_COUNT; i++) - hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (i << 2), - hwread(vortex->mmio, - VORTEX_ADB_RTBASE + (i << 2)) | ROUTE_MASK); - for (i = 0; i < VORTEX_ADB_CHNBASE_COUNT; i++) { - hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (i << 2), - hwread(vortex->mmio, - VORTEX_ADB_CHNBASE + (i << 2)) | ROUTE_MASK); - } -} - -static void vortex_adb_en_sr(vortex_t * vortex, int channel) -{ - hwwrite(vortex->mmio, VORTEX_ADB_SR, - hwread(vortex->mmio, VORTEX_ADB_SR) | (0x1 << channel)); -} - -static void vortex_adb_dis_sr(vortex_t * vortex, int channel) -{ - hwwrite(vortex->mmio, VORTEX_ADB_SR, - hwread(vortex->mmio, VORTEX_ADB_SR) & ~(0x1 << channel)); -} - -static void -vortex_adb_addroutes(vortex_t * vortex, unsigned char channel, - ADBRamLink * route, int rnum) -{ - int temp, prev, lifeboat = 0; - - if ((rnum <= 0) || (route == NULL)) - return; - /* Write last routes. */ - rnum--; - hwwrite(vortex->mmio, - VORTEX_ADB_RTBASE + ((route[rnum] & ADB_MASK) << 2), - ROUTE_MASK); - while (rnum > 0) { - hwwrite(vortex->mmio, - VORTEX_ADB_RTBASE + - ((route[rnum - 1] & ADB_MASK) << 2), route[rnum]); - rnum--; - } - /* Write first route. */ - temp = - hwread(vortex->mmio, - VORTEX_ADB_CHNBASE + (channel << 2)) & ADB_MASK; - if (temp == ADB_MASK) { - /* First entry on this channel. */ - hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (channel << 2), - route[0]); - vortex_adb_en_sr(vortex, channel); - return; - } - /* Not first entry on this channel. Need to link. */ - do { - prev = temp; - temp = - hwread(vortex->mmio, - VORTEX_ADB_RTBASE + (temp << 2)) & ADB_MASK; - if ((lifeboat++) > ADB_MASK) { - printk(KERN_ERR - "vortex_adb_addroutes: unending route! 0x%x\n", - *route); - return; - } - } - while (temp != ADB_MASK); - hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (prev << 2), route[0]); -} - -static void -vortex_adb_delroutes(vortex_t * vortex, unsigned char channel, - ADBRamLink route0, ADBRamLink route1) -{ - int temp, lifeboat = 0, prev; - - /* Find route. */ - temp = - hwread(vortex->mmio, - VORTEX_ADB_CHNBASE + (channel << 2)) & ADB_MASK; - if (temp == (route0 & ADB_MASK)) { - temp = - hwread(vortex->mmio, - VORTEX_ADB_RTBASE + ((route1 & ADB_MASK) << 2)); - if ((temp & ADB_MASK) == ADB_MASK) - vortex_adb_dis_sr(vortex, channel); - hwwrite(vortex->mmio, VORTEX_ADB_CHNBASE + (channel << 2), - temp); - return; - } - do { - prev = temp; - temp = - hwread(vortex->mmio, - VORTEX_ADB_RTBASE + (prev << 2)) & ADB_MASK; - if (((lifeboat++) > ADB_MASK) || (temp == ADB_MASK)) { - printk(KERN_ERR - "vortex_adb_delroutes: route not found! 0x%x\n", - route0); - return; - } - } - while (temp != (route0 & ADB_MASK)); - temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + (temp << 2)); - if ((temp & ADB_MASK) == route1) - temp = hwread(vortex->mmio, VORTEX_ADB_RTBASE + (temp << 2)); - /* Make bridge over deleted route. */ - hwwrite(vortex->mmio, VORTEX_ADB_RTBASE + (prev << 2), temp); -} - -static void -vortex_route(vortex_t * vortex, int en, unsigned char channel, - unsigned char source, unsigned char dest) -{ - ADBRamLink route; - - route = ((source & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); - if (en) { - vortex_adb_addroutes(vortex, channel, &route, 1); - if ((source < (OFFSET_SRCOUT + NR_SRC)) - && (source >= OFFSET_SRCOUT)) - vortex_src_addWTD(vortex, (source - OFFSET_SRCOUT), - channel); - else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) - && (source >= OFFSET_MIXOUT)) - vortex_mixer_addWTD(vortex, - (source - OFFSET_MIXOUT), channel); - } else { - vortex_adb_delroutes(vortex, channel, route, route); - if ((source < (OFFSET_SRCOUT + NR_SRC)) - && (source >= OFFSET_SRCOUT)) - vortex_src_delWTD(vortex, (source - OFFSET_SRCOUT), - channel); - else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) - && (source >= OFFSET_MIXOUT)) - vortex_mixer_delWTD(vortex, - (source - OFFSET_MIXOUT), channel); - } -} - -#if 0 -static void -vortex_routes(vortex_t * vortex, int en, unsigned char channel, - unsigned char source, unsigned char dest0, unsigned char dest1) -{ - ADBRamLink route[2]; - - route[0] = ((source & ADB_MASK) << ADB_SHIFT) | (dest0 & ADB_MASK); - route[1] = ((source & ADB_MASK) << ADB_SHIFT) | (dest1 & ADB_MASK); - - if (en) { - vortex_adb_addroutes(vortex, channel, route, 2); - if ((source < (OFFSET_SRCOUT + NR_SRC)) - && (source >= (OFFSET_SRCOUT))) - vortex_src_addWTD(vortex, (source - OFFSET_SRCOUT), - channel); - else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) - && (source >= (OFFSET_MIXOUT))) - vortex_mixer_addWTD(vortex, - (source - OFFSET_MIXOUT), channel); - } else { - vortex_adb_delroutes(vortex, channel, route[0], route[1]); - if ((source < (OFFSET_SRCOUT + NR_SRC)) - && (source >= (OFFSET_SRCOUT))) - vortex_src_delWTD(vortex, (source - OFFSET_SRCOUT), - channel); - else if ((source < (OFFSET_MIXOUT + NR_MIXOUT)) - && (source >= (OFFSET_MIXOUT))) - vortex_mixer_delWTD(vortex, - (source - OFFSET_MIXOUT), channel); - } -} - -#endif -/* Route two sources to same target. Sources must be of same class !!! */ -static void -vortex_routeLRT(vortex_t * vortex, int en, unsigned char ch, - unsigned char source0, unsigned char source1, - unsigned char dest) -{ - ADBRamLink route[2]; - - route[0] = ((source0 & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); - route[1] = ((source1 & ADB_MASK) << ADB_SHIFT) | (dest & ADB_MASK); - - if (dest < 0x10) - route[1] = (route[1] & ~ADB_MASK) | (dest + 0x20); /* fifo A */ - - if (en) { - vortex_adb_addroutes(vortex, ch, route, 2); - if ((source0 < (OFFSET_SRCOUT + NR_SRC)) - && (source0 >= OFFSET_SRCOUT)) { - vortex_src_addWTD(vortex, - (source0 - OFFSET_SRCOUT), ch); - vortex_src_addWTD(vortex, - (source1 - OFFSET_SRCOUT), ch); - } else if ((source0 < (OFFSET_MIXOUT + NR_MIXOUT)) - && (source0 >= OFFSET_MIXOUT)) { - vortex_mixer_addWTD(vortex, - (source0 - OFFSET_MIXOUT), ch); - vortex_mixer_addWTD(vortex, - (source1 - OFFSET_MIXOUT), ch); - } - } else { - vortex_adb_delroutes(vortex, ch, route[0], route[1]); - if ((source0 < (OFFSET_SRCOUT + NR_SRC)) - && (source0 >= OFFSET_SRCOUT)) { - vortex_src_delWTD(vortex, - (source0 - OFFSET_SRCOUT), ch); - vortex_src_delWTD(vortex, - (source1 - OFFSET_SRCOUT), ch); - } else if ((source0 < (OFFSET_MIXOUT + NR_MIXOUT)) - && (source0 >= OFFSET_MIXOUT)) { - vortex_mixer_delWTD(vortex, - (source0 - OFFSET_MIXOUT), ch); - vortex_mixer_delWTD(vortex, - (source1 - OFFSET_MIXOUT), ch); - } - } -} - -/* Connection stuff */ - -// Connect adbdma to src('s). -static void -vortex_connection_adbdma_src(vortex_t * vortex, int en, unsigned char ch, - unsigned char adbdma, unsigned char src) -{ - vortex_route(vortex, en, ch, ADB_DMA(adbdma), ADB_SRCIN(src)); -} - -// Connect SRC to mixin. -static void -vortex_connection_src_mixin(vortex_t * vortex, int en, - unsigned char channel, unsigned char src, - unsigned char mixin) -{ - vortex_route(vortex, en, channel, ADB_SRCOUT(src), ADB_MIXIN(mixin)); -} - -// Connect mixin with mix output. -static void -vortex_connection_mixin_mix(vortex_t * vortex, int en, unsigned char mixin, - unsigned char mix, int a) -{ - if (en) { - vortex_mix_enableinput(vortex, mix, mixin); - vortex_mix_setinputvolumebyte(vortex, mix, mixin, MIX_DEFIGAIN); // added to original code. - } else - vortex_mix_disableinput(vortex, mix, mixin, a); -} - -// Connect absolut address to mixin. -static void -vortex_connection_adb_mixin(vortex_t * vortex, int en, - unsigned char channel, unsigned char source, - unsigned char mixin) -{ - vortex_route(vortex, en, channel, source, ADB_MIXIN(mixin)); -} - -static void -vortex_connection_src_adbdma(vortex_t * vortex, int en, unsigned char ch, - unsigned char src, unsigned char adbdma) -{ - vortex_route(vortex, en, ch, ADB_SRCOUT(src), ADB_DMA(adbdma)); -} - -static void -vortex_connection_src_src_adbdma(vortex_t * vortex, int en, - unsigned char ch, unsigned char src0, - unsigned char src1, unsigned char adbdma) -{ - - vortex_routeLRT(vortex, en, ch, ADB_SRCOUT(src0), ADB_SRCOUT(src1), - ADB_DMA(adbdma)); -} - -// mix to absolut address. -static void -vortex_connection_mix_adb(vortex_t * vortex, int en, unsigned char ch, - unsigned char mix, unsigned char dest) -{ - vortex_route(vortex, en, ch, ADB_MIXOUT(mix), dest); - vortex_mix_setvolumebyte(vortex, mix, MIX_DEFOGAIN); // added to original code. -} - -// mixer to src. -static void -vortex_connection_mix_src(vortex_t * vortex, int en, unsigned char ch, - unsigned char mix, unsigned char src) -{ - vortex_route(vortex, en, ch, ADB_MIXOUT(mix), ADB_SRCIN(src)); - vortex_mix_setvolumebyte(vortex, mix, MIX_DEFOGAIN); // added to original code. -} - -#if 0 -static void -vortex_connection_adbdma_src_src(vortex_t * vortex, int en, - unsigned char channel, - unsigned char adbdma, unsigned char src0, - unsigned char src1) -{ - vortex_routes(vortex, en, channel, ADB_DMA(adbdma), - ADB_SRCIN(src0), ADB_SRCIN(src1)); -} - -// Connect two mix to AdbDma. -static void -vortex_connection_mix_mix_adbdma(vortex_t * vortex, int en, - unsigned char ch, unsigned char mix0, - unsigned char mix1, unsigned char adbdma) -{ - - ADBRamLink routes[2]; - routes[0] = - (((mix0 + - OFFSET_MIXOUT) & ADB_MASK) << ADB_SHIFT) | (adbdma & ADB_MASK); - routes[1] = - (((mix1 + OFFSET_MIXOUT) & ADB_MASK) << ADB_SHIFT) | ((adbdma + - 0x20) & - ADB_MASK); - if (en) { - vortex_adb_addroutes(vortex, ch, routes, 0x2); - vortex_mixer_addWTD(vortex, mix0, ch); - vortex_mixer_addWTD(vortex, mix1, ch); - } else { - vortex_adb_delroutes(vortex, ch, routes[0], routes[1]); - vortex_mixer_delWTD(vortex, mix0, ch); - vortex_mixer_delWTD(vortex, mix1, ch); - } -} -#endif - -/* CODEC connect. */ - -static void -vortex_connect_codecplay(vortex_t * vortex, int en, unsigned char mixers[]) -{ -#ifdef CHIP_AU8820 - vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_CODECOUT(0)); - vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_CODECOUT(1)); -#else -#if 1 - // Connect front channels through EQ. - vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_EQIN(0)); - vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_EQIN(1)); - /* Lower volume, since EQ has some gain. */ - vortex_mix_setvolumebyte(vortex, mixers[0], 0); - vortex_mix_setvolumebyte(vortex, mixers[1], 0); - vortex_route(vortex, en, 0x11, ADB_EQOUT(0), ADB_CODECOUT(0)); - vortex_route(vortex, en, 0x11, ADB_EQOUT(1), ADB_CODECOUT(1)); - - /* Check if reg 0x28 has SDAC bit set. */ - if (VORTEX_IS_QUAD(vortex)) { - /* Rear channel. Note: ADB_CODECOUT(0+2) and (1+2) is for AC97 modem */ - vortex_connection_mix_adb(vortex, en, 0x11, mixers[2], - ADB_CODECOUT(0 + 4)); - vortex_connection_mix_adb(vortex, en, 0x11, mixers[3], - ADB_CODECOUT(1 + 4)); - /* printk(KERN_DEBUG "SDAC detected "); */ - } -#else - // Use plain direct output to codec. - vortex_connection_mix_adb(vortex, en, 0x11, mixers[0], ADB_CODECOUT(0)); - vortex_connection_mix_adb(vortex, en, 0x11, mixers[1], ADB_CODECOUT(1)); -#endif -#endif -} - -static void -vortex_connect_codecrec(vortex_t * vortex, int en, unsigned char mixin0, - unsigned char mixin1) -{ - /* - Enable: 0x1, 0x1 - Channel: 0x11, 0x11 - ADB Source address: 0x48, 0x49 - Destination Asp4Topology_0x9c,0x98 - */ - vortex_connection_adb_mixin(vortex, en, 0x11, ADB_CODECIN(0), mixin0); - vortex_connection_adb_mixin(vortex, en, 0x11, ADB_CODECIN(1), mixin1); -} - -// Higher level ADB audio path (de)allocator. - -/* Resource manager */ -static int resnum[VORTEX_RESOURCE_LAST] = - { NR_ADB, NR_SRC, NR_MIXIN, NR_MIXOUT, NR_A3D }; -/* - Checkout/Checkin resource of given type. - resmap: resource map to be used. If NULL means that we want to allocate - a DMA resource (root of all other resources of a dma channel). - out: Mean checkout if != 0. Else mean Checkin resource. - restype: Indicates type of resource to be checked in or out. -*/ -static char -vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype) -{ - int i, qty = resnum[restype], resinuse = 0; - - if (out) { - /* Gather used resources by all streams. */ - for (i = 0; i < NR_ADB; i++) { - resinuse |= vortex->dma_adb[i].resources[restype]; - } - resinuse |= vortex->fixed_res[restype]; - /* Find and take free resource. */ - for (i = 0; i < qty; i++) { - if ((resinuse & (1 << i)) == 0) { - if (resmap != NULL) - resmap[restype] |= (1 << i); - else - vortex->dma_adb[i].resources[restype] |= (1 << i); - /* - printk(KERN_DEBUG - "vortex: ResManager: type %d out %d\n", - restype, i); - */ - return i; - } - } - } else { - if (resmap == NULL) - return -EINVAL; - /* Checkin first resource of type restype. */ - for (i = 0; i < qty; i++) { - if (resmap[restype] & (1 << i)) { - resmap[restype] &= ~(1 << i); - /* - printk(KERN_DEBUG - "vortex: ResManager: type %d in %d\n", - restype, i); - */ - return i; - } - } - } - printk(KERN_ERR "vortex: FATAL: ResManager: resource type %d exhausted.\n", restype); - return -ENOMEM; -} - -/* Default Connections */ - -static void vortex_connect_default(vortex_t * vortex, int en) -{ - // Connect AC97 codec. - vortex->mixplayb[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, - VORTEX_RESOURCE_MIXOUT); - vortex->mixplayb[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, - VORTEX_RESOURCE_MIXOUT); - if (VORTEX_IS_QUAD(vortex)) { - vortex->mixplayb[2] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, - VORTEX_RESOURCE_MIXOUT); - vortex->mixplayb[3] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, - VORTEX_RESOURCE_MIXOUT); - } - vortex_connect_codecplay(vortex, en, vortex->mixplayb); - - vortex->mixcapt[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, - VORTEX_RESOURCE_MIXIN); - vortex->mixcapt[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, - VORTEX_RESOURCE_MIXIN); - vortex_connect_codecrec(vortex, en, MIX_CAPT(0), MIX_CAPT(1)); - - // Connect SPDIF -#ifndef CHIP_AU8820 - vortex->mixspdif[0] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, - VORTEX_RESOURCE_MIXOUT); - vortex->mixspdif[1] = vortex_adb_checkinout(vortex, vortex->fixed_res, en, - VORTEX_RESOURCE_MIXOUT); - vortex_connection_mix_adb(vortex, en, 0x14, vortex->mixspdif[0], - ADB_SPDIFOUT(0)); - vortex_connection_mix_adb(vortex, en, 0x14, vortex->mixspdif[1], - ADB_SPDIFOUT(1)); -#endif - // Connect WT -#ifndef CHIP_AU8810 - vortex_wt_connect(vortex, en); -#endif - // A3D (crosstalk canceler and A3D slices). AU8810 disabled for now. -#ifndef CHIP_AU8820 - vortex_Vort3D_connect(vortex, en); -#endif - // Connect I2S - - // Connect DSP interface for SQ3500 turbo (not here i think...) - - // Connect AC98 modem codec - -} - -/* - Allocate nr_ch pcm audio routes if dma < 0. If dma >= 0, existing routes - are deallocated. - dma: DMA engine routes to be deallocated when dma >= 0. - nr_ch: Number of channels to be de/allocated. - dir: direction of stream. Uses same values as substream->stream. - type: Type of audio output/source (codec, spdif, i2s, dsp, etc) - Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0. -*/ -static int -vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, - int type, int subdev) -{ - stream_t *stream; - int i, en; - struct pcm_vol *p; - - if (dma >= 0) { - en = 0; - vortex_adb_checkinout(vortex, - vortex->dma_adb[dma].resources, en, - VORTEX_RESOURCE_DMA); - } else { - en = 1; - if ((dma = - vortex_adb_checkinout(vortex, NULL, en, - VORTEX_RESOURCE_DMA)) < 0) - return -EBUSY; - } - - stream = &vortex->dma_adb[dma]; - stream->dma = dma; - stream->dir = dir; - stream->type = type; - - /* PLAYBACK ROUTES. */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - int src[4], mix[4], ch_top; -#ifndef CHIP_AU8820 - int a3d = 0; -#endif - /* Get SRC and MIXER hardware resources. */ - if (stream->type != VORTEX_PCM_SPDIF) { - for (i = 0; i < nr_ch; i++) { - if ((src[i] = vortex_adb_checkinout(vortex, - stream->resources, en, - VORTEX_RESOURCE_SRC)) < 0) { - memset(stream->resources, 0, - sizeof(unsigned char) * - VORTEX_RESOURCE_LAST); - return -EBUSY; - } - if (stream->type != VORTEX_PCM_A3D) { - if ((mix[i] = vortex_adb_checkinout(vortex, - stream->resources, - en, - VORTEX_RESOURCE_MIXIN)) < 0) { - memset(stream->resources, - 0, - sizeof(unsigned char) * VORTEX_RESOURCE_LAST); - return -EBUSY; - } - } - } - } -#ifndef CHIP_AU8820 - if (stream->type == VORTEX_PCM_A3D) { - if ((a3d = - vortex_adb_checkinout(vortex, - stream->resources, en, - VORTEX_RESOURCE_A3D)) < 0) { - memset(stream->resources, 0, - sizeof(unsigned char) * - VORTEX_RESOURCE_LAST); - printk(KERN_ERR "vortex: out of A3D sources. Sorry\n"); - return -EBUSY; - } - /* (De)Initialize A3D hardware source. */ - vortex_Vort3D_InitializeSource(&(vortex->a3d[a3d]), en); - } - /* Make SPDIF out exclusive to "spdif" device when in use. */ - if ((stream->type == VORTEX_PCM_SPDIF) && (en)) { - vortex_route(vortex, 0, 0x14, - ADB_MIXOUT(vortex->mixspdif[0]), - ADB_SPDIFOUT(0)); - vortex_route(vortex, 0, 0x14, - ADB_MIXOUT(vortex->mixspdif[1]), - ADB_SPDIFOUT(1)); - } -#endif - /* Make playback routes. */ - for (i = 0; i < nr_ch; i++) { - if (stream->type == VORTEX_PCM_ADB) { - vortex_connection_adbdma_src(vortex, en, - src[nr_ch - 1], - dma, - src[i]); - vortex_connection_src_mixin(vortex, en, - 0x11, src[i], - mix[i]); - vortex_connection_mixin_mix(vortex, en, - mix[i], - MIX_PLAYB(i), 0); -#ifndef CHIP_AU8820 - vortex_connection_mixin_mix(vortex, en, - mix[i], - MIX_SPDIF(i % 2), 0); - vortex_mix_setinputvolumebyte(vortex, - MIX_SPDIF(i % 2), - mix[i], - MIX_DEFIGAIN); -#endif - } -#ifndef CHIP_AU8820 - if (stream->type == VORTEX_PCM_A3D) { - vortex_connection_adbdma_src(vortex, en, - src[nr_ch - 1], - dma, - src[i]); - vortex_route(vortex, en, 0x11, ADB_SRCOUT(src[i]), ADB_A3DIN(a3d)); - /* XTalk test. */ - //vortex_route(vortex, en, 0x11, dma, ADB_XTALKIN(i?9:4)); - //vortex_route(vortex, en, 0x11, ADB_SRCOUT(src[i]), ADB_XTALKIN(i?4:9)); - } - if (stream->type == VORTEX_PCM_SPDIF) - vortex_route(vortex, en, 0x14, - ADB_DMA(stream->dma), - ADB_SPDIFOUT(i)); -#endif - } - if (stream->type != VORTEX_PCM_SPDIF && stream->type != VORTEX_PCM_A3D) { - ch_top = (VORTEX_IS_QUAD(vortex) ? 4 : 2); - for (i = nr_ch; i < ch_top; i++) { - vortex_connection_mixin_mix(vortex, en, - mix[i % nr_ch], - MIX_PLAYB(i), 0); -#ifndef CHIP_AU8820 - vortex_connection_mixin_mix(vortex, en, - mix[i % nr_ch], - MIX_SPDIF(i % 2), - 0); - vortex_mix_setinputvolumebyte(vortex, - MIX_SPDIF(i % 2), - mix[i % nr_ch], - MIX_DEFIGAIN); -#endif - } - if (stream->type == VORTEX_PCM_ADB && en) { - p = &vortex->pcm_vol[subdev]; - p->dma = dma; - for (i = 0; i < nr_ch; i++) - p->mixin[i] = mix[i]; - for (i = 0; i < ch_top; i++) - p->vol[i] = 0; - } - } -#ifndef CHIP_AU8820 - else { - if (nr_ch == 1 && stream->type == VORTEX_PCM_SPDIF) - vortex_route(vortex, en, 0x14, - ADB_DMA(stream->dma), - ADB_SPDIFOUT(1)); - } - /* Reconnect SPDIF out when "spdif" device is down. */ - if ((stream->type == VORTEX_PCM_SPDIF) && (!en)) { - vortex_route(vortex, 1, 0x14, - ADB_MIXOUT(vortex->mixspdif[0]), - ADB_SPDIFOUT(0)); - vortex_route(vortex, 1, 0x14, - ADB_MIXOUT(vortex->mixspdif[1]), - ADB_SPDIFOUT(1)); - } -#endif - /* CAPTURE ROUTES. */ - } else { - int src[2], mix[2]; - - /* Get SRC and MIXER hardware resources. */ - for (i = 0; i < nr_ch; i++) { - if ((mix[i] = - vortex_adb_checkinout(vortex, - stream->resources, en, - VORTEX_RESOURCE_MIXOUT)) - < 0) { - memset(stream->resources, 0, - sizeof(unsigned char) * - VORTEX_RESOURCE_LAST); - return -EBUSY; - } - if ((src[i] = - vortex_adb_checkinout(vortex, - stream->resources, en, - VORTEX_RESOURCE_SRC)) < 0) { - memset(stream->resources, 0, - sizeof(unsigned char) * - VORTEX_RESOURCE_LAST); - return -EBUSY; - } - } - - /* Make capture routes. */ - vortex_connection_mixin_mix(vortex, en, MIX_CAPT(0), mix[0], 0); - vortex_connection_mix_src(vortex, en, 0x11, mix[0], src[0]); - if (nr_ch == 1) { - vortex_connection_mixin_mix(vortex, en, - MIX_CAPT(1), mix[0], 0); - vortex_connection_src_adbdma(vortex, en, - src[0], - src[0], dma); - } else { - vortex_connection_mixin_mix(vortex, en, - MIX_CAPT(1), mix[1], 0); - vortex_connection_mix_src(vortex, en, 0x11, mix[1], - src[1]); - vortex_connection_src_src_adbdma(vortex, en, - src[1], src[0], - src[1], dma); - } - } - vortex->dma_adb[dma].nr_ch = nr_ch; - -#if 0 - /* AC97 Codec channel setup. FIXME: this has no effect on some cards !! */ - if (nr_ch < 4) { - /* Copy stereo to rear channel (surround) */ - snd_ac97_write_cache(vortex->codec, - AC97_SIGMATEL_DAC2INVERT, - snd_ac97_read(vortex->codec, - AC97_SIGMATEL_DAC2INVERT) - | 4); - } else { - /* Allow separate front and rear channels. */ - snd_ac97_write_cache(vortex->codec, - AC97_SIGMATEL_DAC2INVERT, - snd_ac97_read(vortex->codec, - AC97_SIGMATEL_DAC2INVERT) - & ~((u32) - 4)); - } -#endif - return dma; -} - -/* - Set the SampleRate of the SRC's attached to the given DMA engine. - */ -static void -vortex_adb_setsrc(vortex_t * vortex, int adbdma, unsigned int rate, int dir) -{ - stream_t *stream = &(vortex->dma_adb[adbdma]); - int i, cvrt; - - /* dir=1:play ; dir=0:rec */ - if (dir) - cvrt = SRC_RATIO(rate, 48000); - else - cvrt = SRC_RATIO(48000, rate); - - /* Setup SRC's */ - for (i = 0; i < NR_SRC; i++) { - if (stream->resources[VORTEX_RESOURCE_SRC] & (1 << i)) - vortex_src_setupchannel(vortex, i, cvrt, 0, 0, i, dir, 1, cvrt, dir); - } -} - -// Timer and ISR functions. - -static void vortex_settimer(vortex_t * vortex, int period) -{ - //set the timer period to 48000ths of a second. - hwwrite(vortex->mmio, VORTEX_IRQ_STAT, period); -} - -#if 0 -static void vortex_enable_timer_int(vortex_t * card) -{ - hwwrite(card->mmio, VORTEX_IRQ_CTRL, - hwread(card->mmio, VORTEX_IRQ_CTRL) | IRQ_TIMER | 0x60); -} - -static void vortex_disable_timer_int(vortex_t * card) -{ - hwwrite(card->mmio, VORTEX_IRQ_CTRL, - hwread(card->mmio, VORTEX_IRQ_CTRL) & ~IRQ_TIMER); -} - -#endif -static void vortex_enable_int(vortex_t * card) -{ - // CAsp4ISR__EnableVortexInt_void_ - hwwrite(card->mmio, VORTEX_CTRL, - hwread(card->mmio, VORTEX_CTRL) | CTRL_IRQ_ENABLE); - hwwrite(card->mmio, VORTEX_IRQ_CTRL, - (hwread(card->mmio, VORTEX_IRQ_CTRL) & 0xffffefc0) | 0x24); -} - -static void vortex_disable_int(vortex_t * card) -{ - hwwrite(card->mmio, VORTEX_CTRL, - hwread(card->mmio, VORTEX_CTRL) & ~CTRL_IRQ_ENABLE); -} - -static irqreturn_t vortex_interrupt(int irq, void *dev_id) -{ - vortex_t *vortex = dev_id; - int i, handled; - u32 source; - - //check if the interrupt is ours. - if (!(hwread(vortex->mmio, VORTEX_STAT) & 0x1)) - return IRQ_NONE; - - // This is the Interrupt Enable flag we set before (consistency check). - if (!(hwread(vortex->mmio, VORTEX_CTRL) & CTRL_IRQ_ENABLE)) - return IRQ_NONE; - - source = hwread(vortex->mmio, VORTEX_IRQ_SOURCE); - // Reset IRQ flags. - hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, source); - hwread(vortex->mmio, VORTEX_IRQ_SOURCE); - // Is at least one IRQ flag set? - if (source == 0) { - printk(KERN_ERR "vortex: missing irq source\n"); - return IRQ_NONE; - } - - handled = 0; - // Attend every interrupt source. - if (unlikely(source & IRQ_ERR_MASK)) { - if (source & IRQ_FATAL) { - printk(KERN_ERR "vortex: IRQ fatal error\n"); - } - if (source & IRQ_PARITY) { - printk(KERN_ERR "vortex: IRQ parity error\n"); - } - if (source & IRQ_REG) { - printk(KERN_ERR "vortex: IRQ reg error\n"); - } - if (source & IRQ_FIFO) { - printk(KERN_ERR "vortex: IRQ fifo error\n"); - } - if (source & IRQ_DMA) { - printk(KERN_ERR "vortex: IRQ dma error\n"); - } - handled = 1; - } - if (source & IRQ_PCMOUT) { - /* ALSA period acknowledge. */ - spin_lock(&vortex->lock); - for (i = 0; i < NR_ADB; i++) { - if (vortex->dma_adb[i].fifo_status == FIFO_START) { - if (!vortex_adbdma_bufshift(vortex, i)) - continue; - spin_unlock(&vortex->lock); - snd_pcm_period_elapsed(vortex->dma_adb[i]. - substream); - spin_lock(&vortex->lock); - } - } -#ifndef CHIP_AU8810 - for (i = 0; i < NR_WT; i++) { - if (vortex->dma_wt[i].fifo_status == FIFO_START) { - if (vortex_wtdma_bufshift(vortex, i)) ; - spin_unlock(&vortex->lock); - snd_pcm_period_elapsed(vortex->dma_wt[i]. - substream); - spin_lock(&vortex->lock); - } - } -#endif - spin_unlock(&vortex->lock); - handled = 1; - } - //Acknowledge the Timer interrupt - if (source & IRQ_TIMER) { - hwread(vortex->mmio, VORTEX_IRQ_STAT); - handled = 1; - } - if ((source & IRQ_MIDI) && vortex->rmidi) { - snd_mpu401_uart_interrupt(vortex->irq, - vortex->rmidi->private_data); - handled = 1; - } - - if (!handled) { - printk(KERN_ERR "vortex: unknown irq source %x\n", source); - } - return IRQ_RETVAL(handled); -} - -/* Codec */ - -#define POLL_COUNT 1000 -static void vortex_codec_init(vortex_t * vortex) -{ - int i; - - for (i = 0; i < 32; i++) { - /* the windows driver writes -i, so we write -i */ - hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i); - msleep(2); - } - if (0) { - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x8068); - msleep(1); - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8); - msleep(1); - } else { - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00a8); - msleep(2); - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80a8); - msleep(2); - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80e8); - msleep(2); - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x80a8); - msleep(2); - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00a8); - msleep(2); - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8); - } - for (i = 0; i < 32; i++) { - hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i); - msleep(5); - } - hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0xe8); - msleep(1); - /* Enable codec channels 0 and 1. */ - hwwrite(vortex->mmio, VORTEX_CODEC_EN, - hwread(vortex->mmio, VORTEX_CODEC_EN) | EN_CODEC); -} - -static void -vortex_codec_write(struct snd_ac97 * codec, unsigned short addr, unsigned short data) -{ - - vortex_t *card = (vortex_t *) codec->private_data; - unsigned int lifeboat = 0; - - /* wait for transactions to clear */ - while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { - udelay(100); - if (lifeboat++ > POLL_COUNT) { - printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); - return; - } - } - /* write register */ - hwwrite(card->mmio, VORTEX_CODEC_IO, - ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK) | - ((data << VORTEX_CODEC_DATSHIFT) & VORTEX_CODEC_DATMASK) | - VORTEX_CODEC_WRITE | - (codec->num << VORTEX_CODEC_ID_SHIFT) ); - - /* Flush Caches. */ - hwread(card->mmio, VORTEX_CODEC_IO); -} - -static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short addr) -{ - - vortex_t *card = (vortex_t *) codec->private_data; - u32 read_addr, data; - unsigned lifeboat = 0; - - /* wait for transactions to clear */ - while (!(hwread(card->mmio, VORTEX_CODEC_CTRL) & 0x100)) { - udelay(100); - if (lifeboat++ > POLL_COUNT) { - printk(KERN_ERR "vortex: ac97 codec stuck busy\n"); - return 0xffff; - } - } - /* set up read address */ - read_addr = ((addr << VORTEX_CODEC_ADDSHIFT) & VORTEX_CODEC_ADDMASK) | - (codec->num << VORTEX_CODEC_ID_SHIFT) ; - hwwrite(card->mmio, VORTEX_CODEC_IO, read_addr); - - /* wait for address */ - do { - udelay(100); - data = hwread(card->mmio, VORTEX_CODEC_IO); - if (lifeboat++ > POLL_COUNT) { - printk(KERN_ERR "vortex: ac97 address never arrived\n"); - return 0xffff; - } - } while ((data & VORTEX_CODEC_ADDMASK) != - (addr << VORTEX_CODEC_ADDSHIFT)); - - /* return data. */ - return (u16) (data & VORTEX_CODEC_DATMASK); -} - -/* SPDIF support */ - -static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode) -{ - int i, this_38 = 0, this_04 = 0, this_08 = 0, this_0c = 0; - - /* CAsp4Spdif::InitializeSpdifHardware(void) */ - hwwrite(vortex->mmio, VORTEX_SPDIF_FLAGS, - hwread(vortex->mmio, VORTEX_SPDIF_FLAGS) & 0xfff3fffd); - //for (i=0x291D4; i<0x29200; i+=4) - for (i = 0; i < 11; i++) - hwwrite(vortex->mmio, VORTEX_SPDIF_CFG1 + (i << 2), 0); - //hwwrite(vortex->mmio, 0x29190, hwread(vortex->mmio, 0x29190) | 0xc0000); - hwwrite(vortex->mmio, VORTEX_CODEC_EN, - hwread(vortex->mmio, VORTEX_CODEC_EN) | EN_SPDIF); - - /* CAsp4Spdif::ProgramSRCInHardware(enum SPDIF_SR,enum SPDIFMODE) */ - if (this_04 && this_08) { - int edi; - - i = (((0x5DC00000 / spdif_sr) + 1) >> 1); - if (i > 0x800) { - if (i < 0x1ffff) - edi = (i >> 1); - else - edi = 0x1ffff; - } else { - i = edi = 0x800; - } - /* this_04 and this_08 are the CASp4Src's (samplerate converters) */ - vortex_src_setupchannel(vortex, this_04, edi, 0, 1, - this_0c, 1, 0, edi, 1); - vortex_src_setupchannel(vortex, this_08, edi, 0, 1, - this_0c, 1, 0, edi, 1); - } - - i = spdif_sr; - spdif_sr |= 0x8c; - switch (i) { - case 32000: - this_38 &= 0xFFFFFFFE; - this_38 &= 0xFFFFFFFD; - this_38 &= 0xF3FFFFFF; - this_38 |= 0x03000000; /* set 32khz samplerate */ - this_38 &= 0xFFFFFF3F; - spdif_sr &= 0xFFFFFFFD; - spdif_sr |= 1; - break; - case 44100: - this_38 &= 0xFFFFFFFE; - this_38 &= 0xFFFFFFFD; - this_38 &= 0xF0FFFFFF; - this_38 |= 0x03000000; - this_38 &= 0xFFFFFF3F; - spdif_sr &= 0xFFFFFFFC; - break; - case 48000: - if (spdif_mode == 1) { - this_38 &= 0xFFFFFFFE; - this_38 &= 0xFFFFFFFD; - this_38 &= 0xF2FFFFFF; - this_38 |= 0x02000000; /* set 48khz samplerate */ - this_38 &= 0xFFFFFF3F; - } else { - /* J. Gordon Wolfe: I think this stuff is for AC3 */ - this_38 |= 0x00000003; - this_38 &= 0xFFFFFFBF; - this_38 |= 0x80; - } - spdif_sr |= 2; - spdif_sr &= 0xFFFFFFFE; - break; - - } - /* looks like the next 2 lines transfer a 16-bit value into 2 8-bit - registers. seems to be for the standard IEC/SPDIF initialization - stuff */ - hwwrite(vortex->mmio, VORTEX_SPDIF_CFG0, this_38 & 0xffff); - hwwrite(vortex->mmio, VORTEX_SPDIF_CFG1, this_38 >> 0x10); - hwwrite(vortex->mmio, VORTEX_SPDIF_SMPRATE, spdif_sr); -} - -/* Initialization */ - -static int __devinit vortex_core_init(vortex_t * vortex) -{ - - printk(KERN_INFO "Vortex: init.... "); - /* Hardware Init. */ - hwwrite(vortex->mmio, VORTEX_CTRL, 0xffffffff); - msleep(5); - hwwrite(vortex->mmio, VORTEX_CTRL, - hwread(vortex->mmio, VORTEX_CTRL) & 0xffdfffff); - msleep(5); - /* Reset IRQ flags */ - hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffffffff); - hwread(vortex->mmio, VORTEX_IRQ_STAT); - - vortex_codec_init(vortex); - -#ifdef CHIP_AU8830 - hwwrite(vortex->mmio, VORTEX_CTRL, - hwread(vortex->mmio, VORTEX_CTRL) | 0x1000000); -#endif - - /* Init audio engine. */ - vortex_adbdma_init(vortex); - hwwrite(vortex->mmio, VORTEX_ENGINE_CTRL, 0x0); //, 0xc83c7e58, 0xc5f93e58 - vortex_adb_init(vortex); - /* Init processing blocks. */ - vortex_fifo_init(vortex); - vortex_mixer_init(vortex); - vortex_srcblock_init(vortex); -#ifndef CHIP_AU8820 - vortex_eq_init(vortex); - vortex_spdif_init(vortex, 48000, 1); - vortex_Vort3D_enable(vortex); -#endif -#ifndef CHIP_AU8810 - vortex_wt_init(vortex); -#endif - // Moved to au88x0.c - //vortex_connect_default(vortex, 1); - - vortex_settimer(vortex, 0x90); - // Enable Interrupts. - // vortex_enable_int() must be first !! - // hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, 0); - // vortex_enable_int(vortex); - //vortex_enable_timer_int(vortex); - //vortex_disable_timer_int(vortex); - - printk(KERN_INFO "done.\n"); - spin_lock_init(&vortex->lock); - - return 0; -} - -static int vortex_core_shutdown(vortex_t * vortex) -{ - - printk(KERN_INFO "Vortex: shutdown..."); -#ifndef CHIP_AU8820 - vortex_eq_free(vortex); - vortex_Vort3D_disable(vortex); -#endif - //vortex_disable_timer_int(vortex); - vortex_disable_int(vortex); - vortex_connect_default(vortex, 0); - /* Reset all DMA fifos. */ - vortex_fifo_init(vortex); - /* Erase all audio routes. */ - vortex_adb_init(vortex); - - /* Disable MPU401 */ - //hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, hwread(vortex->mmio, VORTEX_IRQ_CTRL) & ~IRQ_MIDI); - //hwwrite(vortex->mmio, VORTEX_CTRL, hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_EN); - - hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, 0); - hwwrite(vortex->mmio, VORTEX_CTRL, 0); - msleep(5); - hwwrite(vortex->mmio, VORTEX_IRQ_SOURCE, 0xffff); - - printk(KERN_INFO "done.\n"); - return 0; -} - -/* Alsa support. */ - -static int vortex_alsafmt_aspfmt(int alsafmt) -{ - int fmt; - - switch (alsafmt) { - case SNDRV_PCM_FORMAT_U8: - fmt = 0x1; - break; - case SNDRV_PCM_FORMAT_MU_LAW: - fmt = 0x2; - break; - case SNDRV_PCM_FORMAT_A_LAW: - fmt = 0x3; - break; - case SNDRV_PCM_FORMAT_SPECIAL: - fmt = 0x4; /* guess. */ - break; - case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: - fmt = 0x5; /* guess. */ - break; - case SNDRV_PCM_FORMAT_S16_LE: - fmt = 0x8; - break; - case SNDRV_PCM_FORMAT_S16_BE: - fmt = 0x9; /* check this... */ - break; - default: - fmt = 0x8; - printk(KERN_ERR "vortex: format unsupported %d\n", alsafmt); - break; - } - return fmt; -} - -/* Some not yet useful translations. */ -#if 0 -typedef enum { - ASPFMTLINEAR16 = 0, /* 0x8 */ - ASPFMTLINEAR8, /* 0x1 */ - ASPFMTULAW, /* 0x2 */ - ASPFMTALAW, /* 0x3 */ - ASPFMTSPORT, /* ? */ - ASPFMTSPDIF, /* ? */ -} ASPENCODING; - -static int -vortex_translateformat(vortex_t * vortex, char bits, char nch, int encod) -{ - int a, this_194; - - if ((bits != 8) && (bits != 16)) - return -1; - - switch (encod) { - case 0: - if (bits == 0x10) - a = 8; // 16 bit - break; - case 1: - if (bits == 8) - a = 1; // 8 bit - break; - case 2: - a = 2; // U_LAW - break; - case 3: - a = 3; // A_LAW - break; - } - switch (nch) { - case 1: - this_194 = 0; - break; - case 2: - this_194 = 1; - break; - case 4: - this_194 = 1; - break; - case 6: - this_194 = 1; - break; - } - return (a); -} - -static void vortex_cdmacore_setformat(vortex_t * vortex, int bits, int nch) -{ - short int d, this_148; - - d = ((bits >> 3) * nch); - this_148 = 0xbb80 / d; -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.c deleted file mode 100644 index 278ed818..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.c +++ /dev/null @@ -1,929 +0,0 @@ -/*************************************************************************** - * au88x0_eq.c - * Aureal Vortex Hardware EQ control/access. - * - * Sun Jun 8 18:19:19 2003 - * 2003 Manuel Jander (mjander@users.sourceforge.net) - * - * 02 July 2003: First time something works :) - * November 2003: A3D Bypass code completed but untested. - * - * TODO: - * - Debug (testing) - * - Test peak visualization support. - * - ****************************************************************************/ - -/* - * 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 Library 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. - */ - -/* - The Aureal Hardware EQ is found on AU8810 and AU8830 chips only. - it has 4 inputs (2 for general mix, 2 for A3D) and 2 outputs (supposed - to be routed to the codec). -*/ - -#include "au88x0.h" -#include "au88x0_eq.h" -#include "au88x0_eqdata.c" - -#define VORTEX_EQ_BASE 0x2b000 -#define VORTEX_EQ_DEST (VORTEX_EQ_BASE + 0x410) -#define VORTEX_EQ_SOURCE (VORTEX_EQ_BASE + 0x430) -#define VORTEX_EQ_CTRL (VORTEX_EQ_BASE + 0x440) - -#define VORTEX_BAND_COEFF_SIZE 0x30 - -/* CEqHw.s */ -static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level) -{ - hwwrite(vortex->mmio, 0x2b3c4, gain); - hwwrite(vortex->mmio, 0x2b3c8, level); -} - -static inline u16 sign_invert(u16 a) -{ - /* -(-32768) -> -32768 so we do -(-32768) -> 32767 to make the result positive */ - if (a == (u16)-32768) - return 32767; - else - return -a; -} - -static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int i = 0, n /*esp2c */; - - for (n = 0; n < eqhw->this04; n++) { - hwwrite(vortex->mmio, 0x2b000 + n * 0x30, coefs[i + 0]); - hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]); - - if (eqhw->this08 == 0) { - hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2]); - hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3]); - hwwrite(vortex->mmio, 0x2b010 + n * 0x30, coefs[i + 4]); - } else { - hwwrite(vortex->mmio, 0x2b008 + n * 0x30, sign_invert(coefs[2 + i])); - hwwrite(vortex->mmio, 0x2b00c + n * 0x30, sign_invert(coefs[3 + i])); - hwwrite(vortex->mmio, 0x2b010 + n * 0x30, sign_invert(coefs[4 + i])); - } - i += 5; - } -} - -static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int i = 0, n /*esp2c */; - - for (n = 0; n < eqhw->this04; n++) { - hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, coefs[0 + i]); - hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]); - - if (eqhw->this08 == 0) { - hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i]); - hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i]); - hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, coefs[4 + i]); - } else { - hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, sign_invert(coefs[2 + i])); - hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, sign_invert(coefs[3 + i])); - hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, sign_invert(coefs[4 + i])); - } - i += 5; - } - -} - -static void vortex_EqHw_SetLeftStates(vortex_t * vortex, u16 a[], u16 b[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int i = 0, ebx; - - hwwrite(vortex->mmio, 0x2b3fc, a[0]); - hwwrite(vortex->mmio, 0x2b400, a[1]); - - for (ebx = 0; ebx < eqhw->this04; ebx++) { - hwwrite(vortex->mmio, 0x2b014 + (i * 0xc), b[i]); - hwwrite(vortex->mmio, 0x2b018 + (i * 0xc), b[1 + i]); - hwwrite(vortex->mmio, 0x2b01c + (i * 0xc), b[2 + i]); - hwwrite(vortex->mmio, 0x2b020 + (i * 0xc), b[3 + i]); - i += 4; - } -} - -static void vortex_EqHw_SetRightStates(vortex_t * vortex, u16 a[], u16 b[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int i = 0, ebx; - - hwwrite(vortex->mmio, 0x2b404, a[0]); - hwwrite(vortex->mmio, 0x2b408, a[1]); - - for (ebx = 0; ebx < eqhw->this04; ebx++) { - hwwrite(vortex->mmio, 0x2b1f4 + (i * 0xc), b[i]); - hwwrite(vortex->mmio, 0x2b1f8 + (i * 0xc), b[1 + i]); - hwwrite(vortex->mmio, 0x2b1fc + (i * 0xc), b[2 + i]); - hwwrite(vortex->mmio, 0x2b200 + (i * 0xc), b[3 + i]); - i += 4; - } -} - -#if 0 -static void vortex_EqHw_GetTimeConsts(vortex_t * vortex, u16 * a, u16 * b) -{ - *a = hwread(vortex->mmio, 0x2b3c4); - *b = hwread(vortex->mmio, 0x2b3c8); -} - -static void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[]) -{ - -} - -static void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[]) -{ - -} - -static void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[]) -{ - -} - -static void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[]) -{ - -} - -#endif -/* Mix Gains */ -static void vortex_EqHw_SetBypassGain(vortex_t * vortex, u16 a, u16 b) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - if (eqhw->this08 == 0) { - hwwrite(vortex->mmio, 0x2b3d4, a); - hwwrite(vortex->mmio, 0x2b3ec, b); - } else { - hwwrite(vortex->mmio, 0x2b3d4, sign_invert(a)); - hwwrite(vortex->mmio, 0x2b3ec, sign_invert(b)); - } -} - -static void vortex_EqHw_SetA3DBypassGain(vortex_t * vortex, u16 a, u16 b) -{ - - hwwrite(vortex->mmio, 0x2b3e0, a); - hwwrite(vortex->mmio, 0x2b3f8, b); -} - -#if 0 -static void vortex_EqHw_SetCurrBypassGain(vortex_t * vortex, u16 a, u16 b) -{ - - hwwrite(vortex->mmio, 0x2b3d0, a); - hwwrite(vortex->mmio, 0x2b3e8, b); -} - -static void vortex_EqHw_SetCurrA3DBypassGain(vortex_t * vortex, u16 a, u16 b) -{ - - hwwrite(vortex->mmio, 0x2b3dc, a); - hwwrite(vortex->mmio, 0x2b3f4, b); -} - -#endif -static void -vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b) -{ - hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b); -} - -static void -vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b) -{ - hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b); -} - -static void vortex_EqHw_SetLeftGainsTarget(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx; - - for (ebx = 0; ebx < eqhw->this04; ebx++) { - hwwrite(vortex->mmio, 0x2b02c + ebx * 0x30, a[ebx]); - } -} - -static void vortex_EqHw_SetRightGainsTarget(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx; - - for (ebx = 0; ebx < eqhw->this04; ebx++) { - hwwrite(vortex->mmio, 0x2b20c + ebx * 0x30, a[ebx]); - } -} - -static void vortex_EqHw_SetLeftGainsCurrent(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx; - - for (ebx = 0; ebx < eqhw->this04; ebx++) { - hwwrite(vortex->mmio, 0x2b028 + ebx * 0x30, a[ebx]); - } -} - -static void vortex_EqHw_SetRightGainsCurrent(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx; - - for (ebx = 0; ebx < eqhw->this04; ebx++) { - hwwrite(vortex->mmio, 0x2b208 + ebx * 0x30, a[ebx]); - } -} - -#if 0 -static void vortex_EqHw_GetLeftGainsTarget(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx = 0; - - if (eqhw->this04 < 0) - return; - - do { - a[ebx] = hwread(vortex->mmio, 0x2b02c + ebx * 0x30); - ebx++; - } - while (ebx < eqhw->this04); -} - -static void vortex_EqHw_GetRightGainsTarget(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx = 0; - - if (eqhw->this04 < 0) - return; - - do { - a[ebx] = hwread(vortex->mmio, 0x2b20c + ebx * 0x30); - ebx++; - } - while (ebx < eqhw->this04); -} - -static void vortex_EqHw_GetLeftGainsCurrent(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx = 0; - - if (eqhw->this04 < 0) - return; - - do { - a[ebx] = hwread(vortex->mmio, 0x2b028 + ebx * 0x30); - ebx++; - } - while (ebx < eqhw->this04); -} - -static void vortex_EqHw_GetRightGainsCurrent(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx = 0; - - if (eqhw->this04 < 0) - return; - - do { - a[ebx] = hwread(vortex->mmio, 0x2b208 + ebx * 0x30); - ebx++; - } - while (ebx < eqhw->this04); -} - -#endif -/* EQ band levels settings */ -static void vortex_EqHw_SetLevels(vortex_t * vortex, u16 peaks[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int i; - - /* set left peaks */ - for (i = 0; i < eqhw->this04; i++) { - hwwrite(vortex->mmio, 0x2b024 + i * VORTEX_BAND_COEFF_SIZE, peaks[i]); - } - - hwwrite(vortex->mmio, 0x2b3cc, peaks[eqhw->this04]); - hwwrite(vortex->mmio, 0x2b3d8, peaks[eqhw->this04 + 1]); - - /* set right peaks */ - for (i = 0; i < eqhw->this04; i++) { - hwwrite(vortex->mmio, 0x2b204 + i * VORTEX_BAND_COEFF_SIZE, - peaks[i + (eqhw->this04 + 2)]); - } - - hwwrite(vortex->mmio, 0x2b3e4, peaks[2 + (eqhw->this04 * 2)]); - hwwrite(vortex->mmio, 0x2b3f0, peaks[3 + (eqhw->this04 * 2)]); -} - -#if 0 -static void vortex_EqHw_GetLevels(vortex_t * vortex, u16 a[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int ebx; - - if (eqhw->this04 < 0) - return; - - ebx = 0; - do { - a[ebx] = hwread(vortex->mmio, 0x2b024 + ebx * 0x30); - ebx++; - } - while (ebx < eqhw->this04); - - a[eqhw->this04] = hwread(vortex->mmio, 0x2b3cc); - a[eqhw->this04 + 1] = hwread(vortex->mmio, 0x2b3d8); - - ebx = 0; - do { - a[ebx + (eqhw->this04 + 2)] = - hwread(vortex->mmio, 0x2b204 + ebx * 0x30); - ebx++; - } - while (ebx < eqhw->this04); - - a[2 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3e4); - a[3 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3f0); -} - -#endif -/* Global Control */ -static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg) -{ - hwwrite(vortex->mmio, 0x2b440, reg); -} - -static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr) -{ - hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800); -} - -#if 0 -static void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg) -{ - *reg = hwread(vortex->mmio, 0x2b440); -} - -static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr) -{ - *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f; -} - -#endif -static void vortex_EqHw_Enable(vortex_t * vortex) -{ - hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001); -} - -static void vortex_EqHw_Disable(vortex_t * vortex) -{ - hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000); -} - -/* Reset (zero) buffers */ -static void vortex_EqHw_ZeroIO(vortex_t * vortex) -{ - int i; - for (i = 0; i < 0x8; i++) - hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0); - for (i = 0; i < 0x4; i++) - hwwrite(vortex->mmio, VORTEX_EQ_SOURCE + (i << 2), 0x0); -} - -static void vortex_EqHw_ZeroA3DIO(vortex_t * vortex) -{ - int i; - for (i = 0; i < 0x4; i++) - hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0); -} - -static void vortex_EqHw_ZeroState(vortex_t * vortex) -{ - - vortex_EqHw_SetControlReg(vortex, 0); - vortex_EqHw_ZeroIO(vortex); - hwwrite(vortex->mmio, 0x2b3c0, 0); - - vortex_EqHw_SetTimeConsts(vortex, 0, 0); - - vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsZeros); - vortex_EqHw_SetRightCoefs(vortex, asEqCoefsZeros); - - vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_zero); - vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_zero); - vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_zero); - vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_zero); - - vortex_EqHw_SetBypassGain(vortex, 0, 0); - //vortex_EqHw_SetCurrBypassGain(vortex, 0, 0); - vortex_EqHw_SetA3DBypassGain(vortex, 0, 0); - //vortex_EqHw_SetCurrA3DBypassGain(vortex, 0, 0); - vortex_EqHw_SetLeftStates(vortex, eq_states_zero, asEqOutStateZeros); - vortex_EqHw_SetRightStates(vortex, eq_states_zero, asEqOutStateZeros); - vortex_EqHw_SetLevels(vortex, (u16 *) eq_levels); -} - -/* Program coeficients as pass through */ -static void vortex_EqHw_ProgramPipe(vortex_t * vortex) -{ - vortex_EqHw_SetTimeConsts(vortex, 0, 0); - - vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsPipes); - vortex_EqHw_SetRightCoefs(vortex, asEqCoefsPipes); - - vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_current); - vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_current); - vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_current); - vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_current); -} - -/* Program EQ block as 10 band Equalizer */ -static void -vortex_EqHw_Program10Band(vortex_t * vortex, auxxEqCoeffSet_t * coefset) -{ - - vortex_EqHw_SetTimeConsts(vortex, 0xc, 0x7fe0); - - vortex_EqHw_SetLeftCoefs(vortex, coefset->LeftCoefs); - vortex_EqHw_SetRightCoefs(vortex, coefset->RightCoefs); - - vortex_EqHw_SetLeftGainsCurrent(vortex, coefset->LeftGains); - - vortex_EqHw_SetRightGainsTarget(vortex, coefset->RightGains); - vortex_EqHw_SetLeftGainsTarget(vortex, coefset->LeftGains); - - vortex_EqHw_SetRightGainsCurrent(vortex, coefset->RightGains); -} - -/* Read all EQ peaks. (think VU meter) */ -static void vortex_EqHw_GetTenBandLevels(vortex_t * vortex, u16 peaks[]) -{ - eqhw_t *eqhw = &(vortex->eq.this04); - int i; - - if (eqhw->this04 <= 0) - return; - - for (i = 0; i < eqhw->this04; i++) - peaks[i] = hwread(vortex->mmio, 0x2B024 + i * 0x30); - for (i = 0; i < eqhw->this04; i++) - peaks[i + eqhw->this04] = - hwread(vortex->mmio, 0x2B204 + i * 0x30); -} - -/* CEqlzr.s */ - -static int vortex_Eqlzr_GetLeftGain(vortex_t * vortex, u16 index, u16 * gain) -{ - eqlzr_t *eq = &(vortex->eq); - - if (eq->this28) { - *gain = eq->this130[index]; - return 0; - } - return 1; -} - -static void vortex_Eqlzr_SetLeftGain(vortex_t * vortex, u16 index, u16 gain) -{ - eqlzr_t *eq = &(vortex->eq); - - if (eq->this28 == 0) - return; - - eq->this130[index] = gain; - if (eq->this54) - return; - - vortex_EqHw_SetLeftGainsSingleTarget(vortex, index, gain); -} - -static int vortex_Eqlzr_GetRightGain(vortex_t * vortex, u16 index, u16 * gain) -{ - eqlzr_t *eq = &(vortex->eq); - - if (eq->this28) { - *gain = eq->this130[index + eq->this10]; - return 0; - } - return 1; -} - -static void vortex_Eqlzr_SetRightGain(vortex_t * vortex, u16 index, u16 gain) -{ - eqlzr_t *eq = &(vortex->eq); - - if (eq->this28 == 0) - return; - - eq->this130[index + eq->this10] = gain; - if (eq->this54) - return; - - vortex_EqHw_SetRightGainsSingleTarget(vortex, index, gain); -} - -#if 0 -static int -vortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, s32 *cnt) -{ - eqlzr_t *eq = &(vortex->eq); - int si = 0; - - if (eq->this10 == 0) - return 1; - - { - if (vortex_Eqlzr_GetLeftGain(vortex, si, &gains[si])) - return 1; - if (vortex_Eqlzr_GetRightGain - (vortex, si, &gains[si + eq->this10])) - return 1; - si++; - } - while (eq->this10 > si) ; - *cnt = si * 2; - return 0; -} -#endif -static int vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex) -{ - eqlzr_t *eq = &(vortex->eq); - - vortex_EqHw_SetLeftGainsTarget(vortex, eq->this130); - vortex_EqHw_SetRightGainsTarget(vortex, &(eq->this130[eq->this10])); - - return 0; -} - -static int -vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], s32 count) -{ - eqlzr_t *eq = &(vortex->eq); - int i; - - if (((eq->this10) * 2 != count) || (eq->this28 == 0)) - return 1; - - for (i = 0; i < count; i++) { - eq->this130[i] = gains[i]; - } - - if (eq->this54) - return 0; - return vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex); -} - -static void -vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, u32 a, u32 b) -{ - eqlzr_t *eq = &(vortex->eq); - u32 eax, ebx; - - eq->this58 = a; - eq->this5c = b; - if (eq->this54) - eax = eq->this0e; - else - eax = eq->this0a; - ebx = (eax * eq->this58) >> 0x10; - eax = (eax * eq->this5c) >> 0x10; - vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax); -} - -static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex) -{ - eqlzr_t *eq = &(vortex->eq); - u32 eax, ebx; - - if (eq->this54) - eax = eq->this0e; - else - eax = eq->this0a; - ebx = (eax * eq->this58) >> 0x10; - eax = (eax * eq->this5c) >> 0x10; - vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax); -} - -static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex) -{ - if (vortex != NULL) - vortex_EqHw_ZeroA3DIO(vortex); -} - -static void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp) -{ - eqlzr_t *eq = &(vortex->eq); - - if ((eq->this28) && (bp == 0)) { - /* EQ enabled */ - vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex); - vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08); - } else { - /* EQ disabled. */ - vortex_EqHw_SetLeftGainsTarget(vortex, eq->this14_array); - vortex_EqHw_SetRightGainsTarget(vortex, eq->this14_array); - vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c); - } - vortex_Eqlzr_ProgramA3dBypassGain(vortex); -} - -static void vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex) -{ - eqlzr_t *eq = &(vortex->eq); - - /* Set EQ BiQuad filter coeficients */ - memcpy(&(eq->coefset), &asEqCoefsNormal, sizeof(auxxEqCoeffSet_t)); - /* Set EQ Band gain levels and dump into hardware registers. */ - vortex_Eqlzr_SetAllBands(vortex, eq_gains_normal, eq->this10 * 2); -} - -static int vortex_Eqlzr_GetAllPeaks(vortex_t * vortex, u16 * peaks, int *count) -{ - eqlzr_t *eq = &(vortex->eq); - - if (eq->this10 == 0) - return 1; - *count = eq->this10 * 2; - vortex_EqHw_GetTenBandLevels(vortex, peaks); - return 0; -} - -#if 0 -static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex) -{ - eqlzr_t *eq = &(vortex->eq); - - return (&(eq->coefset)); -} -#endif -static void vortex_Eqlzr_init(vortex_t * vortex) -{ - eqlzr_t *eq = &(vortex->eq); - - /* Object constructor */ - //eq->this04 = 0; - eq->this08 = 0; /* Bypass gain with EQ in use. */ - eq->this0a = 0x5999; - eq->this0c = 0x5999; /* Bypass gain with EQ disabled. */ - eq->this0e = 0x5999; - - eq->this10 = 0xa; /* 10 eq frequency bands. */ - eq->this04.this04 = eq->this10; - eq->this28 = 0x1; /* if 1 => Allow read access to this130 (gains) */ - eq->this54 = 0x0; /* if 1 => Dont Allow access to hardware (gains) */ - eq->this58 = 0xffff; - eq->this5c = 0xffff; - - /* Set gains. */ - memset(eq->this14_array, 0, sizeof(eq->this14_array)); - - /* Actual init. */ - vortex_EqHw_ZeroState(vortex); - vortex_EqHw_SetSampleRate(vortex, 0x11); - vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex); - - vortex_EqHw_Program10Band(vortex, &(eq->coefset)); - vortex_Eqlzr_SetBypass(vortex, eq->this54); - vortex_Eqlzr_SetA3dBypassGain(vortex, 0, 0); - vortex_EqHw_Enable(vortex); -} - -static void vortex_Eqlzr_shutdown(vortex_t * vortex) -{ - vortex_Eqlzr_ShutDownA3d(vortex); - vortex_EqHw_ProgramPipe(vortex); - vortex_EqHw_Disable(vortex); -} - -/* ALSA interface */ - -/* Control interface */ -#define snd_vortex_eqtoggle_info snd_ctl_boolean_mono_info - -static int -snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - eqlzr_t *eq = &(vortex->eq); - //int i = kcontrol->private_value; - - ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1; - - return 0; -} - -static int -snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - eqlzr_t *eq = &(vortex->eq); - //int i = kcontrol->private_value; - - eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1; - vortex_Eqlzr_SetBypass(vortex, eq->this54); - - return 1; /* Allways changes */ -} - -static struct snd_kcontrol_new vortex_eqtoggle_kcontrol __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "EQ Enable", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_vortex_eqtoggle_info, - .get = snd_vortex_eqtoggle_get, - .put = snd_vortex_eqtoggle_put -}; - -static int -snd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0x0000; - uinfo->value.integer.max = 0x7fff; - return 0; -} - -static int -snd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - int i = kcontrol->private_value; - u16 gainL = 0, gainR = 0; - - vortex_Eqlzr_GetLeftGain(vortex, i, &gainL); - vortex_Eqlzr_GetRightGain(vortex, i, &gainR); - ucontrol->value.integer.value[0] = gainL; - ucontrol->value.integer.value[1] = gainR; - return 0; -} - -static int -snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - int changed = 0, i = kcontrol->private_value; - u16 gainL = 0, gainR = 0; - - vortex_Eqlzr_GetLeftGain(vortex, i, &gainL); - vortex_Eqlzr_GetRightGain(vortex, i, &gainR); - - if (gainL != ucontrol->value.integer.value[0]) { - vortex_Eqlzr_SetLeftGain(vortex, i, - ucontrol->value.integer.value[0]); - changed = 1; - } - if (gainR != ucontrol->value.integer.value[1]) { - vortex_Eqlzr_SetRightGain(vortex, i, - ucontrol->value.integer.value[1]); - changed = 1; - } - return changed; -} - -static struct snd_kcontrol_new vortex_eq_kcontrol __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = " .", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_vortex_eq_info, - .get = snd_vortex_eq_get, - .put = snd_vortex_eq_put -}; - -static int -snd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 20; - uinfo->value.integer.min = 0x0000; - uinfo->value.integer.max = 0x7fff; - return 0; -} - -static int -snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - int i, count = 0; - u16 peaks[20]; - - vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count); - if (count != 20) { - printk(KERN_ERR "vortex: peak count error 20 != %d \n", count); - return -1; - } - for (i = 0; i < 20; i++) - ucontrol->value.integer.value[i] = peaks[i]; - - return 0; -} - -static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "EQ Peaks", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_vortex_peaks_info, - .get = snd_vortex_peaks_get, -}; - -/* EQ band gain labels. */ -static char *EqBandLabels[10] __devinitdata = { - "EQ0 31Hz\0", - "EQ1 63Hz\0", - "EQ2 125Hz\0", - "EQ3 250Hz\0", - "EQ4 500Hz\0", - "EQ5 1KHz\0", - "EQ6 2KHz\0", - "EQ7 4KHz\0", - "EQ8 8KHz\0", - "EQ9 16KHz\0", -}; - -/* ALSA driver entry points. Init and exit. */ -static int __devinit vortex_eq_init(vortex_t * vortex) -{ - struct snd_kcontrol *kcontrol; - int err, i; - - vortex_Eqlzr_init(vortex); - - if ((kcontrol = - snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL) - return -ENOMEM; - kcontrol->private_value = 0; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) - return err; - - /* EQ gain controls */ - for (i = 0; i < 10; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL) - return -ENOMEM; - snprintf(kcontrol->id.name, sizeof(kcontrol->id.name), - "%s Playback Volume", EqBandLabels[i]); - kcontrol->private_value = i; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) - return err; - //vortex->eqctrl[i] = kcontrol; - } - /* EQ band levels */ - if ((kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) - return err; - - return 0; -} - -static int vortex_eq_free(vortex_t * vortex) -{ - /* - //FIXME: segfault because vortex->eqctrl[i] == 4 - int i; - for (i=0; i<10; i++) { - if (vortex->eqctrl[i]) - snd_ctl_remove(vortex->card, vortex->eqctrl[i]); - } - */ - vortex_Eqlzr_shutdown(vortex); - return 0; -} - -/* End */ diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.h b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.h deleted file mode 100644 index 474cd004..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eq.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef AU88X0_EQ_H -#define AU88X0_EQ_H - -/*************************************************************************** - * au88x0_eq.h - * - * Definitions and constant data for the Aureal Hardware EQ. - * - * Sun Jun 8 18:23:38 2003 - * Author: Manuel Jander (mjander@users.sourceforge.net) - ****************************************************************************/ - -typedef struct { - u16 LeftCoefs[50]; //0x4 - u16 RightCoefs[50]; // 0x68 - u16 LeftGains[10]; //0xd0 - u16 RightGains[10]; //0xe4 -} auxxEqCoeffSet_t; - -typedef struct { - s32 this04; /* How many filters for each side (default = 10) */ - s32 this08; /* inited to cero. Stereo flag? */ -} eqhw_t; - -typedef struct { - eqhw_t this04; /* CHwEq */ - u16 this08; /* Bad codec flag ? SetBypassGain: bypass gain */ - u16 this0a; - u16 this0c; /* SetBypassGain: bypass gain when this28 is not set. */ - u16 this0e; - - s32 this10; /* How many gains are used for each side (right or left). */ - u16 this14_array[10]; /* SetLeftGainsTarget: Left (and right?) EQ gains */ - s32 this28; /* flag related to EQ enabled or not. Gang flag ? */ - s32 this54; /* SetBypass */ - s32 this58; - s32 this5c; - /*0x60 */ auxxEqCoeffSet_t coefset; - /* 50 u16 word each channel. */ - u16 this130[20]; /* Left and Right gains */ -} eqlzr_t; - -#endif diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eqdata.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eqdata.c deleted file mode 100644 index ce8dca8c..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_eqdata.c +++ /dev/null @@ -1,116 +0,0 @@ -/* Data structs */ - -static u16 asEqCoefsZeros[50] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -}; - -static u16 asEqCoefsPipes[64] = { - 0x0000, 0x0000, - 0x0000, 0x0666, 0x0000, 0x0000, 0x0666, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0666, 0x0000, 0x0000, 0x0666, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0666, 0x0000, 0x0000, 0x0666, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0666, 0x0000, 0x0000, 0x0666, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0666, 0x0000, 0x0000, 0x066a, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000 -}; - -/* More coef sets can be found in the win2k "inf" file. */ -static auxxEqCoeffSet_t asEqCoefsNormal = { - .LeftCoefs = { - 0x7e60, 0xc19e, 0x0001, 0x0002, 0x0001, - 0x7fa0, 0xc05f, 0x004f, 0x0000, 0xffb1, - 0x7f3f, 0xc0bc, 0x00c2, 0x0000, 0xff3e, - 0x7e78, 0xc177, 0x011f, 0x0000, 0xfee1, - 0x7cd6, 0xc2e5, 0x025c, 0x0000, 0xfda4, - 0x7949, 0xc5aa, 0x0467, 0x0000, 0xfb99, - 0x7120, 0xcadf, 0x0864, 0x0000, 0xf79c, - 0x5d33, 0xd430, 0x0f7e, 0x0000, 0xf082, - 0x2beb, 0xe3ca, 0x1bd3, 0x0000, 0xe42d, - 0xd740, 0xf01d, 0x2ac5, 0x0000, 0xd53b}, - - .RightCoefs = { - 0x7e60, 0xc19e, 0x0001, 0x0002, 0x0001, - 0x7fa0, 0xc05f, 0x004f, 0x0000, 0xffb1, - 0x7f3f, 0xc0bc, 0x00c2, 0x0000, 0xff3e, - 0x7e78, 0xc177, 0x011f, 0x0000, 0xfee1, - 0x7cd6, 0xc2e5, 0x025c, 0x0000, 0xfda4, - 0x7949, 0xc5aa, 0x0467, 0x0000, 0xfb99, - 0x7120, 0xcadf, 0x0864, 0x0000, 0xf79c, - 0x5d33, 0xd430, 0x0f7e, 0x0000, 0xf082, - 0x2beb, 0xe3ca, 0x1bd3, 0x0000, 0xe42d, - 0xd740, 0xf01d, 0x2ac5, 0x0000, 0xd53b}, - - .LeftGains = { - 0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96, - 0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96}, - .RightGains = { - 0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96, - 0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96} -}; - -static u16 eq_gains_normal[20] = { - 0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96, - 0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96, - 0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96, - 0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96 -}; - -/* _rodatab60 */ -static u16 eq_gains_zero[10] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 -}; - -/* _rodatab7c: ProgramPipe */ -static u16 eq_gains_current[12] = { - 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, - 0x7fff, - 0x7fff, 0x7fff, 0x7fff -}; - -/* _rodatab78 */ -static u16 eq_states_zero[2] = { 0x0000, 0x0000 }; - -static u16 asEqOutStateZeros[48] = { - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000 -}; - -/*_rodataba0:*/ -static u16 eq_levels[64] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 -}; diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_game.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_game.c deleted file mode 100644 index c07c792b..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_game.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Manuel Jander. - * - * Based on the work of: - * Vojtech Pavlik - * Raymond Ingles - * - * 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 - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to , or by paper mail: - * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic - * - * Based 90% on Vojtech Pavlik pcigame driver. - * Merged and modified by Manuel Jander, for the OpenVortex - * driver. (email: mjander@embedded.cl). - */ - -#include -#include -#include -#include -#include "au88x0.h" -#include -#include - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - -#define VORTEX_GAME_DWAIT 20 /* 20 ms */ - -static unsigned char vortex_game_read(struct gameport *gameport) -{ - vortex_t *vortex = gameport_get_port_data(gameport); - return hwread(vortex->mmio, VORTEX_GAME_LEGACY); -} - -static void vortex_game_trigger(struct gameport *gameport) -{ - vortex_t *vortex = gameport_get_port_data(gameport); - hwwrite(vortex->mmio, VORTEX_GAME_LEGACY, 0xff); -} - -static int -vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) -{ - vortex_t *vortex = gameport_get_port_data(gameport); - int i; - - *buttons = (~hwread(vortex->mmio, VORTEX_GAME_LEGACY) >> 4) & 0xf; - - for (i = 0; i < 4; i++) { - axes[i] = - hwread(vortex->mmio, VORTEX_GAME_AXIS + (i * AXIS_SIZE)); - if (axes[i] == AXIS_RANGE) - axes[i] = -1; - } - return 0; -} - -static int vortex_game_open(struct gameport *gameport, int mode) -{ - vortex_t *vortex = gameport_get_port_data(gameport); - - switch (mode) { - case GAMEPORT_MODE_COOKED: - hwwrite(vortex->mmio, VORTEX_CTRL2, - hwread(vortex->mmio, - VORTEX_CTRL2) | CTRL2_GAME_ADCMODE); - msleep(VORTEX_GAME_DWAIT); - return 0; - case GAMEPORT_MODE_RAW: - hwwrite(vortex->mmio, VORTEX_CTRL2, - hwread(vortex->mmio, - VORTEX_CTRL2) & ~CTRL2_GAME_ADCMODE); - return 0; - default: - return -1; - } - - return 0; -} - -static int __devinit vortex_gameport_register(vortex_t * vortex) -{ - struct gameport *gp; - - vortex->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "vortex: cannot allocate memory for gameport\n"); - return -ENOMEM; - }; - - gameport_set_name(gp, "AU88x0 Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev)); - gameport_set_dev_parent(gp, &vortex->pci_dev->dev); - - gp->read = vortex_game_read; - gp->trigger = vortex_game_trigger; - gp->cooked_read = vortex_game_cooked_read; - gp->open = vortex_game_open; - - gameport_set_port_data(gp, vortex); - gp->fuzz = 64; - - gameport_register_port(gp); - - return 0; -} - -static void vortex_gameport_unregister(vortex_t * vortex) -{ - if (vortex->gameport) { - gameport_unregister_port(vortex->gameport); - vortex->gameport = NULL; - } -} - -#else -static inline int vortex_gameport_register(vortex_t * vortex) { return -ENOSYS; } -static inline void vortex_gameport_unregister(vortex_t * vortex) { } -#endif diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_mixer.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_mixer.c deleted file mode 100644 index 557c782a..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_mixer.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Vortex Mixer support. - * - * There is much more than just the AC97 mixer... - * - */ - -#include -#include -#include -#include "au88x0.h" - -static int __devinit snd_vortex_mixer(vortex_t * vortex) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = vortex_codec_write, - .read = vortex_codec_read, - }; - - if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0) - return err; - memset(&ac97, 0, sizeof(ac97)); - // Initialize AC97 codec stuff. - ac97.private_data = vortex; - ac97.scaps = AC97_SCAP_NO_SPDIF; - err = snd_ac97_mixer(pbus, &ac97, &vortex->codec); - vortex->isquad = ((vortex->codec == NULL) ? 0 : (vortex->codec->ext_id&0x80)); - return err; -} diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_mpu401.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_mpu401.c deleted file mode 100644 index e6c6a0fe..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_mpu401.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of MPU-401 in UART mode - * - * Modified for the Aureal Vortex based Soundcards - * by Manuel Jander (mjande@embedded.cl). - * - * 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 "au88x0.h" - -/* Check for mpu401 mmio support. */ -/* MPU401 legacy support is only provided as a emergency fallback * - * for older versions of ALSA. Its usage is strongly discouraged. */ -#ifndef MPU401_HW_AUREAL -#define VORTEX_MPU401_LEGACY -#endif - -/* Vortex MPU401 defines. */ -#define MIDI_CLOCK_DIV 0x61 -/* Standart MPU401 defines. */ -#define MPU401_RESET 0xff -#define MPU401_ENTER_UART 0x3f -#define MPU401_ACK 0xfe - -static int __devinit snd_vortex_midi(vortex_t * vortex) -{ - struct snd_rawmidi *rmidi; - int temp, mode; - struct snd_mpu401 *mpu; - unsigned long port; - -#ifdef VORTEX_MPU401_LEGACY - /* EnableHardCodedMPU401Port() */ - /* Enable Legacy MIDI Interface port. */ - port = (0x03 << 5); /* FIXME: static address. 0x330 */ - temp = - (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) | - CTRL_MIDI_EN | port; - hwwrite(vortex->mmio, VORTEX_CTRL, temp); -#else - /* Disable Legacy MIDI Interface port. */ - temp = - (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) & - ~CTRL_MIDI_EN; - hwwrite(vortex->mmio, VORTEX_CTRL, temp); -#endif - /* Mpu401UartInit() */ - mode = 1; - temp = hwread(vortex->mmio, VORTEX_CTRL2) & 0xffff00cf; - temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4; - hwwrite(vortex->mmio, VORTEX_CTRL2, temp); - hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET); - - /* Check if anything is OK. */ - temp = hwread(vortex->mmio, VORTEX_MIDI_DATA); - if (temp != MPU401_ACK /*0xfe */ ) { - printk(KERN_ERR "midi port doesn't acknowledge!\n"); - return -ENODEV; - } - /* Enable MPU401 interrupts. */ - hwwrite(vortex->mmio, VORTEX_IRQ_CTRL, - hwread(vortex->mmio, VORTEX_IRQ_CTRL) | IRQ_MIDI); - - /* Create MPU401 instance. */ -#ifdef VORTEX_MPU401_LEGACY - if ((temp = - snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330, - MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) { - hwwrite(vortex->mmio, VORTEX_CTRL, - (hwread(vortex->mmio, VORTEX_CTRL) & - ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); - return temp; - } -#else - port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); - if ((temp = - snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, - MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO | - MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) { - hwwrite(vortex->mmio, VORTEX_CTRL, - (hwread(vortex->mmio, VORTEX_CTRL) & - ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); - return temp; - } - mpu = rmidi->private_data; - mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD); -#endif - /* Overwrite MIDI name */ - snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number); - - vortex->rmidi = rmidi; - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_pcm.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_pcm.c deleted file mode 100644 index e59f1207..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_pcm.c +++ /dev/null @@ -1,678 +0,0 @@ -/* - * 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 Library 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. - */ - -/* - * Vortex PCM ALSA driver. - * - * Supports ADB and WT DMA. Unfortunately, WT channels do not run yet. - * It remains stuck,and DMA transfers do not happen. - */ -#include -#include -#include -#include -#include -#include "au88x0.h" - -#define VORTEX_PCM_TYPE(x) (x->name[40]) - -/* hardware definition */ -static struct snd_pcm_hardware snd_vortex_playback_hw_adb = { - .info = - (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */ - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 5000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 0x10000, - .period_bytes_min = 0x20, - .period_bytes_max = 0x1000, - .periods_min = 2, - .periods_max = 1024, -}; - -#ifndef CHIP_AU8820 -static struct snd_pcm_hardware snd_vortex_playback_hw_a3d = { - .info = - (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */ - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 5000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = 0x10000, - .period_bytes_min = 0x100, - .period_bytes_max = 0x1000, - .periods_min = 2, - .periods_max = 64, -}; -#endif -static struct snd_pcm_hardware snd_vortex_playback_hw_spdif = { - .info = - (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */ - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | SNDRV_PCM_FMTBIT_MU_LAW | - SNDRV_PCM_FMTBIT_A_LAW, - .rates = - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 32000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 0x10000, - .period_bytes_min = 0x100, - .period_bytes_max = 0x1000, - .periods_min = 2, - .periods_max = 64, -}; - -#ifndef CHIP_AU8810 -static struct snd_pcm_hardware snd_vortex_playback_hw_wt = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS, // SNDRV_PCM_RATE_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 0x10000, - .period_bytes_min = 0x0400, - .period_bytes_max = 0x1000, - .periods_min = 2, - .periods_max = 64, -}; -#endif -#ifdef CHIP_AU8830 -static unsigned int au8830_channels[3] = { - 1, 2, 4, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = { - .count = ARRAY_SIZE(au8830_channels), - .list = au8830_channels, - .mask = 0, -}; -#endif - -static void vortex_notify_pcm_vol_change(struct snd_card *card, - struct snd_kcontrol *kctl, int activate) -{ - if (activate) - kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - else - kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id)); -} - -/* open callback */ -static int snd_vortex_pcm_open(struct snd_pcm_substream *substream) -{ - vortex_t *vortex = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - /* Force equal size periods */ - if ((err = - snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - /* Avoid PAGE_SIZE boundary to fall inside of a period. */ - if ((err = - snd_pcm_hw_constraint_pow2(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0) - return err; - - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 64); - - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { -#ifndef CHIP_AU8820 - if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_A3D) { - runtime->hw = snd_vortex_playback_hw_a3d; - } -#endif - if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_SPDIF) { - runtime->hw = snd_vortex_playback_hw_spdif; - switch (vortex->spdif_sr) { - case 32000: - runtime->hw.rates = SNDRV_PCM_RATE_32000; - break; - case 44100: - runtime->hw.rates = SNDRV_PCM_RATE_44100; - break; - case 48000: - runtime->hw.rates = SNDRV_PCM_RATE_48000; - break; - } - } - if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB - || VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_I2S) - runtime->hw = snd_vortex_playback_hw_adb; -#ifdef CHIP_AU8830 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - VORTEX_IS_QUAD(vortex) && - VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) { - runtime->hw.channels_max = 4; - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &hw_constraints_au8830_channels); - } -#endif - substream->runtime->private_data = NULL; - } -#ifndef CHIP_AU8810 - else { - runtime->hw = snd_vortex_playback_hw_wt; - substream->runtime->private_data = NULL; - } -#endif - return 0; -} - -/* close callback */ -static int snd_vortex_pcm_close(struct snd_pcm_substream *substream) -{ - //vortex_t *chip = snd_pcm_substream_chip(substream); - stream_t *stream = (stream_t *) substream->runtime->private_data; - - // the hardware-specific codes will be here - if (stream != NULL) { - stream->substream = NULL; - stream->nr_ch = 0; - } - substream->runtime->private_data = NULL; - return 0; -} - -/* hw_params callback */ -static int -snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - vortex_t *chip = snd_pcm_substream_chip(substream); - stream_t *stream = (stream_t *) (substream->runtime->private_data); - int err; - - // Alloc buffer memory. - err = - snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) { - printk(KERN_ERR "Vortex: pcm page alloc failed!\n"); - return err; - } - /* - printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params), - params_period_bytes(hw_params), params_channels(hw_params)); - */ - spin_lock_irq(&chip->lock); - // Make audio routes and config buffer DMA. - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { - int dma, type = VORTEX_PCM_TYPE(substream->pcm); - /* Dealloc any routes. */ - if (stream != NULL) - vortex_adb_allocroute(chip, stream->dma, - stream->nr_ch, stream->dir, - stream->type, - substream->number); - /* Alloc routes. */ - dma = - vortex_adb_allocroute(chip, -1, - params_channels(hw_params), - substream->stream, type, - substream->number); - if (dma < 0) { - spin_unlock_irq(&chip->lock); - return dma; - } - stream = substream->runtime->private_data = &chip->dma_adb[dma]; - stream->substream = substream; - /* Setup Buffers. */ - vortex_adbdma_setbuffers(chip, dma, - params_period_bytes(hw_params), - params_periods(hw_params)); - if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) { - chip->pcm_vol[substream->number].active = 1; - vortex_notify_pcm_vol_change(chip->card, - chip->pcm_vol[substream->number].kctl, 1); - } - } -#ifndef CHIP_AU8810 - else { - /* if (stream != NULL) - vortex_wt_allocroute(chip, substream->number, 0); */ - vortex_wt_allocroute(chip, substream->number, - params_channels(hw_params)); - stream = substream->runtime->private_data = - &chip->dma_wt[substream->number]; - stream->dma = substream->number; - stream->substream = substream; - vortex_wtdma_setbuffers(chip, substream->number, - params_period_bytes(hw_params), - params_periods(hw_params)); - } -#endif - spin_unlock_irq(&chip->lock); - return 0; -} - -/* hw_free callback */ -static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream) -{ - vortex_t *chip = snd_pcm_substream_chip(substream); - stream_t *stream = (stream_t *) (substream->runtime->private_data); - - spin_lock_irq(&chip->lock); - // Delete audio routes. - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { - if (stream != NULL) { - if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) { - chip->pcm_vol[substream->number].active = 0; - vortex_notify_pcm_vol_change(chip->card, - chip->pcm_vol[substream->number].kctl, - 0); - } - vortex_adb_allocroute(chip, stream->dma, - stream->nr_ch, stream->dir, - stream->type, - substream->number); - } - } -#ifndef CHIP_AU8810 - else { - if (stream != NULL) - vortex_wt_allocroute(chip, stream->dma, 0); - } -#endif - substream->runtime->private_data = NULL; - spin_unlock_irq(&chip->lock); - - return snd_pcm_lib_free_pages(substream); -} - -/* prepare callback */ -static int snd_vortex_pcm_prepare(struct snd_pcm_substream *substream) -{ - vortex_t *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - stream_t *stream = (stream_t *) substream->runtime->private_data; - int dma = stream->dma, fmt, dir; - - // set up the hardware with the current configuration. - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dir = 1; - else - dir = 0; - fmt = vortex_alsafmt_aspfmt(runtime->format); - spin_lock_irq(&chip->lock); - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { - vortex_adbdma_setmode(chip, dma, 1, dir, fmt, - runtime->channels == 1 ? 0 : 1, 0); - vortex_adbdma_setstartbuffer(chip, dma, 0); - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_SPDIF) - vortex_adb_setsrc(chip, dma, runtime->rate, dir); - } -#ifndef CHIP_AU8810 - else { - vortex_wtdma_setmode(chip, dma, 1, fmt, 0, 0); - // FIXME: Set rate (i guess using vortex_wt_writereg() somehow). - vortex_wtdma_setstartbuffer(chip, dma, 0); - } -#endif - spin_unlock_irq(&chip->lock); - return 0; -} - -/* trigger callback */ -static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - vortex_t *chip = snd_pcm_substream_chip(substream); - stream_t *stream = (stream_t *) substream->runtime->private_data; - int dma = stream->dma; - - spin_lock(&chip->lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - // do something to start the PCM engine - //printk(KERN_INFO "vortex: start %d\n", dma); - stream->fifo_enabled = 1; - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) { - vortex_adbdma_resetup(chip, dma); - vortex_adbdma_startfifo(chip, dma); - } -#ifndef CHIP_AU8810 - else { - printk(KERN_INFO "vortex: wt start %d\n", dma); - vortex_wtdma_startfifo(chip, dma); - } -#endif - break; - case SNDRV_PCM_TRIGGER_STOP: - // do something to stop the PCM engine - //printk(KERN_INFO "vortex: stop %d\n", dma); - stream->fifo_enabled = 0; - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) - vortex_adbdma_stopfifo(chip, dma); -#ifndef CHIP_AU8810 - else { - printk(KERN_INFO "vortex: wt stop %d\n", dma); - vortex_wtdma_stopfifo(chip, dma); - } -#endif - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - //printk(KERN_INFO "vortex: pause %d\n", dma); - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) - vortex_adbdma_pausefifo(chip, dma); -#ifndef CHIP_AU8810 - else - vortex_wtdma_pausefifo(chip, dma); -#endif - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - //printk(KERN_INFO "vortex: resume %d\n", dma); - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) - vortex_adbdma_resumefifo(chip, dma); -#ifndef CHIP_AU8810 - else - vortex_wtdma_resumefifo(chip, dma); -#endif - break; - default: - spin_unlock(&chip->lock); - return -EINVAL; - } - spin_unlock(&chip->lock); - return 0; -} - -/* pointer callback */ -static snd_pcm_uframes_t snd_vortex_pcm_pointer(struct snd_pcm_substream *substream) -{ - vortex_t *chip = snd_pcm_substream_chip(substream); - stream_t *stream = (stream_t *) substream->runtime->private_data; - int dma = stream->dma; - snd_pcm_uframes_t current_ptr = 0; - - spin_lock(&chip->lock); - if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) - current_ptr = vortex_adbdma_getlinearpos(chip, dma); -#ifndef CHIP_AU8810 - else - current_ptr = vortex_wtdma_getlinearpos(chip, dma); -#endif - //printk(KERN_INFO "vortex: pointer = 0x%x\n", current_ptr); - spin_unlock(&chip->lock); - return (bytes_to_frames(substream->runtime, current_ptr)); -} - -/* operators */ -static struct snd_pcm_ops snd_vortex_playback_ops = { - .open = snd_vortex_pcm_open, - .close = snd_vortex_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_vortex_pcm_hw_params, - .hw_free = snd_vortex_pcm_hw_free, - .prepare = snd_vortex_pcm_prepare, - .trigger = snd_vortex_pcm_trigger, - .pointer = snd_vortex_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -/* -* definitions of capture are omitted here... -*/ - -static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = { - CARD_NAME " ADB", - CARD_NAME " SPDIF", - CARD_NAME " A3D", - CARD_NAME " WT", - CARD_NAME " I2S", -}; -static char *vortex_pcm_name[VORTEX_PCM_LAST] = { - "adb", - "spdif", - "a3d", - "wt", - "i2s", -}; - -/* SPDIF kcontrol */ - -static int snd_vortex_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_vortex_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS; - return 0; -} - -static int snd_vortex_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - ucontrol->value.iec958.status[0] = 0x00; - ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL|IEC958_AES1_CON_DIGDIGCONV_ID; - ucontrol->value.iec958.status[2] = 0x00; - switch (vortex->spdif_sr) { - case 32000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_32000; break; - case 44100: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_44100; break; - case 48000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; break; - } - return 0; -} - -static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - int spdif_sr = 48000; - switch (ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) { - case IEC958_AES3_CON_FS_32000: spdif_sr = 32000; break; - case IEC958_AES3_CON_FS_44100: spdif_sr = 44100; break; - case IEC958_AES3_CON_FS_48000: spdif_sr = 48000; break; - } - if (spdif_sr == vortex->spdif_sr) - return 0; - vortex->spdif_sr = spdif_sr; - vortex_spdif_init(vortex, vortex->spdif_sr, 1); - return 1; -} - -/* spdif controls */ -static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_vortex_spdif_info, - .get = snd_vortex_spdif_get, - .put = snd_vortex_spdif_put, - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), - .info = snd_vortex_spdif_info, - .get = snd_vortex_spdif_mask_get - }, -}; - -/* subdevice PCM Volume control */ - -static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2); - uinfo->value.integer.min = -128; - uinfo->value.integer.max = 32; - return 0; -} - -static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int i; - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - int subdev = kcontrol->id.subdevice; - struct pcm_vol *p = &vortex->pcm_vol[subdev]; - int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2); - for (i = 0; i < max_chn; i++) - ucontrol->value.integer.value[i] = p->vol[i]; - return 0; -} - -static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int i; - int changed = 0; - int mixin; - unsigned char vol; - vortex_t *vortex = snd_kcontrol_chip(kcontrol); - int subdev = kcontrol->id.subdevice; - struct pcm_vol *p = &vortex->pcm_vol[subdev]; - int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2); - for (i = 0; i < max_chn; i++) { - if (p->vol[i] != ucontrol->value.integer.value[i]) { - p->vol[i] = ucontrol->value.integer.value[i]; - if (p->active) { - switch (vortex->dma_adb[p->dma].nr_ch) { - case 1: - mixin = p->mixin[0]; - break; - case 2: - default: - mixin = p->mixin[(i < 2) ? i : (i - 2)]; - break; - case 4: - mixin = p->mixin[i]; - break; - }; - vol = p->vol[i]; - vortex_mix_setinputvolumebyte(vortex, - vortex->mixplayb[i], mixin, vol); - } - changed = 1; - } - } - return changed; -} - -static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400); - -static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .info = snd_vortex_pcm_vol_info, - .get = snd_vortex_pcm_vol_get, - .put = snd_vortex_pcm_vol_put, - .tlv = { .p = vortex_pcm_vol_db_scale }, -}; - -/* create a pcm device */ -static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) -{ - struct snd_pcm *pcm; - struct snd_kcontrol *kctl; - int i; - int err, nr_capt; - - if (!chip || idx < 0 || idx >= VORTEX_PCM_LAST) - return -ENODEV; - - /* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the - * same dma engine. WT uses it own separate dma engine which can't capture. */ - if (idx == VORTEX_PCM_ADB) - nr_capt = nr; - else - nr_capt = 0; - err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr, - nr_capt, &pcm); - if (err < 0) - return err; - snprintf(pcm->name, sizeof(pcm->name), - "%s %s", CARD_NAME_SHORT, vortex_pcm_name[idx]); - chip->pcm[idx] = pcm; - // This is an evil hack, but it saves a lot of duplicated code. - VORTEX_PCM_TYPE(pcm) = idx; - pcm->private_data = chip; - /* set operators */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_vortex_playback_ops); - if (idx == VORTEX_PCM_ADB) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_vortex_playback_ops); - - /* pre-allocation of Scatter-Gather buffers */ - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci_dev), - 0x10000, 0x10000); - - if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) { - for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) { - kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip); - if (!kctl) - return -ENOMEM; - if ((err = snd_ctl_add(chip->card, kctl)) < 0) - return err; - } - } - if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) { - for (i = 0; i < NR_PCM; i++) { - chip->pcm_vol[i].active = 0; - chip->pcm_vol[i].dma = -1; - kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip); - if (!kctl) - return -ENOMEM; - chip->pcm_vol[i].kctl = kctl; - kctl->id.device = 0; - kctl->id.subdevice = i; - err = snd_ctl_add(chip->card, kctl); - if (err < 0) - return err; - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_synth.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_synth.c deleted file mode 100644 index 2805e34b..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_synth.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * 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 Library 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. - */ - -/* - * Someday its supposed to make use of the WT DMA engine - * for a Wavetable synthesizer. - */ - -#include "au88x0.h" -#include "au88x0_wt.h" - -static void vortex_fifo_setwtvalid(vortex_t * vortex, int fifo, int en); -static void vortex_connection_adb_mixin(vortex_t * vortex, int en, - unsigned char channel, - unsigned char source, - unsigned char mixin); -static void vortex_connection_mixin_mix(vortex_t * vortex, int en, - unsigned char mixin, - unsigned char mix, int a); -static void vortex_fifo_wtinitialize(vortex_t * vortex, int fifo, int j); -static int vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, - u32 val); - -/* WT */ - -/* Put 2 WT channels together for one stereo interlaced channel. */ -static void vortex_wt_setstereo(vortex_t * vortex, u32 wt, u32 stereo) -{ - int temp; - - //temp = hwread(vortex->mmio, 0x80 + ((wt >> 0x5)<< 0xf) + (((wt & 0x1f) >> 1) << 2)); - temp = hwread(vortex->mmio, WT_STEREO(wt)); - temp = (temp & 0xfe) | (stereo & 1); - //hwwrite(vortex->mmio, 0x80 + ((wt >> 0x5)<< 0xf) + (((wt & 0x1f) >> 1) << 2), temp); - hwwrite(vortex->mmio, WT_STEREO(wt), temp); -} - -/* Join to mixdown route. */ -static void vortex_wt_setdsout(vortex_t * vortex, u32 wt, int en) -{ - int temp; - - /* There is one DSREG register for each bank (32 voices each). */ - temp = hwread(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0)); - if (en) - temp |= (1 << (wt & 0x1f)); - else - temp &= (1 << ~(wt & 0x1f)); - hwwrite(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0), temp); -} - -/* Setup WT route. */ -static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch) -{ - wt_voice_t *voice = &(vortex->wt_voice[wt]); - int temp; - - //FIXME: WT audio routing. - if (nr_ch) { - vortex_fifo_wtinitialize(vortex, wt, 1); - vortex_fifo_setwtvalid(vortex, wt, 1); - vortex_wt_setstereo(vortex, wt, nr_ch - 1); - } else - vortex_fifo_setwtvalid(vortex, wt, 0); - - /* Set mixdown mode. */ - vortex_wt_setdsout(vortex, wt, 1); - /* Set other parameter registers. */ - hwwrite(vortex->mmio, WT_SRAMP(0), 0x880000); - //hwwrite(vortex->mmio, WT_GMODE(0), 0xffffffff); -#ifdef CHIP_AU8830 - hwwrite(vortex->mmio, WT_SRAMP(1), 0x880000); - //hwwrite(vortex->mmio, WT_GMODE(1), 0xffffffff); -#endif - hwwrite(vortex->mmio, WT_PARM(wt, 0), 0); - hwwrite(vortex->mmio, WT_PARM(wt, 1), 0); - hwwrite(vortex->mmio, WT_PARM(wt, 2), 0); - - temp = hwread(vortex->mmio, WT_PARM(wt, 3)); - printk(KERN_DEBUG "vortex: WT PARM3: %x\n", temp); - //hwwrite(vortex->mmio, WT_PARM(wt, 3), temp); - - hwwrite(vortex->mmio, WT_DELAY(wt, 0), 0); - hwwrite(vortex->mmio, WT_DELAY(wt, 1), 0); - hwwrite(vortex->mmio, WT_DELAY(wt, 2), 0); - hwwrite(vortex->mmio, WT_DELAY(wt, 3), 0); - - printk(KERN_DEBUG "vortex: WT GMODE: %x\n", hwread(vortex->mmio, WT_GMODE(wt))); - - hwwrite(vortex->mmio, WT_PARM(wt, 2), 0xffffffff); - hwwrite(vortex->mmio, WT_PARM(wt, 3), 0xcff1c810); - - voice->parm0 = voice->parm1 = 0xcfb23e2f; - hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0); - hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1); - printk(KERN_DEBUG "vortex: WT GMODE 2 : %x\n", hwread(vortex->mmio, WT_GMODE(wt))); - return 0; -} - - -static void vortex_wt_connect(vortex_t * vortex, int en) -{ - int i, ii, mix; - -#define NR_WTROUTES 6 -#ifdef CHIP_AU8830 -#define NR_WTBLOCKS 2 -#else -#define NR_WTBLOCKS 1 -#endif - - for (i = 0; i < NR_WTBLOCKS; i++) { - for (ii = 0; ii < NR_WTROUTES; ii++) { - mix = - vortex_adb_checkinout(vortex, - vortex->fixed_res, en, - VORTEX_RESOURCE_MIXIN); - vortex->mixwt[(i * NR_WTROUTES) + ii] = mix; - - vortex_route(vortex, en, 0x11, - ADB_WTOUT(i, ii + 0x20), ADB_MIXIN(mix)); - - vortex_connection_mixin_mix(vortex, en, mix, - vortex->mixplayb[ii % 2], 0); - if (VORTEX_IS_QUAD(vortex)) - vortex_connection_mixin_mix(vortex, en, - mix, - vortex->mixplayb[2 + - (ii % 2)], 0); - } - } - for (i = 0; i < NR_WT; i++) { - hwwrite(vortex->mmio, WT_RUN(i), 1); - } -} - -/* Read WT Register */ -#if 0 -static int vortex_wt_GetReg(vortex_t * vortex, char reg, int wt) -{ - //int eax, esi; - - if (reg == 4) { - return hwread(vortex->mmio, WT_PARM(wt, 3)); - } - if (reg == 7) { - return hwread(vortex->mmio, WT_GMODE(wt)); - } - - return 0; -} - -/* WT hardware abstraction layer generic register interface. */ -static int -vortex_wt_SetReg2(vortex_t * vortex, unsigned char reg, int wt, - u16 val) -{ - /* - int eax, edx; - - if (wt >= NR_WT) // 0x40 -> NR_WT - return 0; - - if ((reg - 0x20) > 0) { - if ((reg - 0x21) != 0) - return 0; - eax = ((((b & 0xff) << 0xb) + (edx & 0xff)) << 4) + 0x208; // param 2 - } else { - eax = ((((b & 0xff) << 0xb) + (edx & 0xff)) << 4) + 0x20a; // param 3 - } - hwwrite(vortex->mmio, eax, c); - */ - return 1; -} - -/*public: static void __thiscall CWTHal::SetReg(unsigned char,int,unsigned long) */ -#endif -static int -vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt, - u32 val) -{ - int ecx; - - if ((reg == 5) || ((reg >= 7) && (reg <= 10)) || (reg == 0xc)) { - if (wt >= (NR_WT / NR_WT_PB)) { - printk - ("vortex: WT SetReg: bank out of range. reg=0x%x, wt=%d\n", - reg, wt); - return 0; - } - } else { - if (wt >= NR_WT) { - printk(KERN_ERR "vortex: WT SetReg: voice out of range\n"); - return 0; - } - } - if (reg > 0xc) - return 0; - - switch (reg) { - /* Voice specific parameters */ - case 0: /* running */ - /* - printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", - WT_RUN(wt), (int)val); - */ - hwwrite(vortex->mmio, WT_RUN(wt), val); - return 0xc; - break; - case 1: /* param 0 */ - /* - printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", - WT_PARM(wt,0), (int)val); - */ - hwwrite(vortex->mmio, WT_PARM(wt, 0), val); - return 0xc; - break; - case 2: /* param 1 */ - /* - printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", - WT_PARM(wt,1), (int)val); - */ - hwwrite(vortex->mmio, WT_PARM(wt, 1), val); - return 0xc; - break; - case 3: /* param 2 */ - /* - printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", - WT_PARM(wt,2), (int)val); - */ - hwwrite(vortex->mmio, WT_PARM(wt, 2), val); - return 0xc; - break; - case 4: /* param 3 */ - /* - printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", - WT_PARM(wt,3), (int)val); - */ - hwwrite(vortex->mmio, WT_PARM(wt, 3), val); - return 0xc; - break; - case 6: /* mute */ - /* - printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", - WT_MUTE(wt), (int)val); - */ - hwwrite(vortex->mmio, WT_MUTE(wt), val); - return 0xc; - break; - case 0xb: - { /* delay */ - /* - printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", - WT_DELAY(wt,0), (int)val); - */ - hwwrite(vortex->mmio, WT_DELAY(wt, 3), val); - hwwrite(vortex->mmio, WT_DELAY(wt, 2), val); - hwwrite(vortex->mmio, WT_DELAY(wt, 1), val); - hwwrite(vortex->mmio, WT_DELAY(wt, 0), val); - return 0xc; - } - break; - /* Global WT block parameters */ - case 5: /* sramp */ - ecx = WT_SRAMP(wt); - break; - case 8: /* aramp */ - ecx = WT_ARAMP(wt); - break; - case 9: /* mramp */ - ecx = WT_MRAMP(wt); - break; - case 0xa: /* ctrl */ - ecx = WT_CTRL(wt); - break; - case 0xc: /* ds_reg */ - ecx = WT_DSREG(wt); - break; - default: - return 0; - break; - } - /* - printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val); - */ - hwwrite(vortex->mmio, ecx, val); - return 1; -} - -static void vortex_wt_init(vortex_t * vortex) -{ - u32 var4, var8, varc, var10 = 0, edi; - - var10 &= 0xFFFFFFE3; - var10 |= 0x22; - var10 &= 0xFFFFFEBF; - var10 |= 0x80; - var10 |= 0x200; - var10 &= 0xfffffffe; - var10 &= 0xfffffbff; - var10 |= 0x1800; - // var10 = 0x1AA2 - var4 = 0x10000000; - varc = 0x00830000; - var8 = 0x00830000; - - /* Init Bank registers. */ - for (edi = 0; edi < (NR_WT / NR_WT_PB); edi++) { - vortex_wt_SetReg(vortex, 0xc, edi, 0); /* ds_reg */ - vortex_wt_SetReg(vortex, 0xa, edi, var10); /* ctrl */ - vortex_wt_SetReg(vortex, 0x9, edi, var4); /* mramp */ - vortex_wt_SetReg(vortex, 0x8, edi, varc); /* aramp */ - vortex_wt_SetReg(vortex, 0x5, edi, var8); /* sramp */ - } - /* Init Voice registers. */ - for (edi = 0; edi < NR_WT; edi++) { - vortex_wt_SetReg(vortex, 0x4, edi, 0); /* param 3 0x20c */ - vortex_wt_SetReg(vortex, 0x3, edi, 0); /* param 2 0x208 */ - vortex_wt_SetReg(vortex, 0x2, edi, 0); /* param 1 0x204 */ - vortex_wt_SetReg(vortex, 0x1, edi, 0); /* param 0 0x200 */ - vortex_wt_SetReg(vortex, 0xb, edi, 0); /* delay 0x400 - 0x40c */ - } - var10 |= 1; - for (edi = 0; edi < (NR_WT / NR_WT_PB); edi++) - vortex_wt_SetReg(vortex, 0xa, edi, var10); /* ctrl */ -} - -/* Extract of CAdbTopology::SetVolume(struct _ASPVOLUME *) */ -#if 0 -static void vortex_wt_SetVolume(vortex_t * vortex, int wt, int vol[]) -{ - wt_voice_t *voice = &(vortex->wt_voice[wt]); - int ecx = vol[1], eax = vol[0]; - - /* This is pure guess */ - voice->parm0 &= 0xff00ffff; - voice->parm0 |= (vol[0] & 0xff) << 0x10; - voice->parm1 &= 0xff00ffff; - voice->parm1 |= (vol[1] & 0xff) << 0x10; - - /* This is real */ - hwwrite(vortex, WT_PARM(wt, 0), voice->parm0); - hwwrite(vortex, WT_PARM(wt, 1), voice->parm0); - - if (voice->this_1D0 & 4) { - eax >>= 8; - ecx = eax; - if (ecx < 0x80) - ecx = 0x7f; - voice->parm3 &= 0xFFFFC07F; - voice->parm3 |= (ecx & 0x7f) << 7; - voice->parm3 &= 0xFFFFFF80; - voice->parm3 |= (eax & 0x7f); - } else { - voice->parm3 &= 0xFFE03FFF; - voice->parm3 |= (eax & 0xFE00) << 5; - } - - hwwrite(vortex, WT_PARM(wt, 3), voice->parm3); -} - -/* Extract of CAdbTopology::SetFrequency(unsigned long arg_0) */ -static void vortex_wt_SetFrequency(vortex_t * vortex, int wt, unsigned int sr) -{ - wt_voice_t *voice = &(vortex->wt_voice[wt]); - u32 eax, edx; - - //FIXME: 64 bit operation. - eax = ((sr << 0xf) * 0x57619F1) & 0xffffffff; - edx = (((sr << 0xf) * 0x57619F1)) >> 0x20; - - edx >>= 0xa; - edx <<= 1; - if (edx) { - if (edx & 0x0FFF80000) - eax = 0x7fff; - else { - edx <<= 0xd; - eax = 7; - while ((edx & 0x80000000) == 0) { - edx <<= 1; - eax--; - if (eax == 0) - break; - } - if (eax) - edx <<= 1; - eax <<= 0xc; - edx >>= 0x14; - eax |= edx; - } - } else - eax = 0; - voice->parm0 &= 0xffff0001; - voice->parm0 |= (eax & 0x7fff) << 1; - voice->parm1 = voice->parm0 | 1; - // Wt: this_1D4 - //AuWt::WriteReg((ulong)(this_1DC<<4)+0x200, (ulong)this_1E4); - //AuWt::WriteReg((ulong)(this_1DC<<4)+0x204, (ulong)this_1E8); - hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0); - hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1); -} -#endif - -/* End of File */ diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_wt.h b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_wt.h deleted file mode 100644 index 38d98f88..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_wt.h +++ /dev/null @@ -1,65 +0,0 @@ -/*************************************************************************** - * WT register offsets. - * - * Wed Oct 22 13:50:20 2003 - * Copyright 2003 mjander - * mjander@users.sourceforge.org - ****************************************************************************/ -#ifndef _AU88X0_WT_H -#define _AU88X0_WT_H - -/* WT channels are grouped in banks. Each bank has 0x20 channels. */ -/* Bank register address boundary is 0x8000 */ - -#define NR_WT_PB 0x20 - -/* WT bank base register (as dword address). */ -#define WT_BAR(x) (((x)&0xffe0)<<0x8) -#define WT_BANK(x) (x>>5) -/* WT Bank registers */ -#define WT_CTRL(bank) (((((bank)&1)<<0xd) + 0x00)<<2) /* 0x0000 */ -#define WT_SRAMP(bank) (((((bank)&1)<<0xd) + 0x01)<<2) /* 0x0004 */ -#define WT_DSREG(bank) (((((bank)&1)<<0xd) + 0x02)<<2) /* 0x0008 */ -#define WT_MRAMP(bank) (((((bank)&1)<<0xd) + 0x03)<<2) /* 0x000c */ -#define WT_GMODE(bank) (((((bank)&1)<<0xd) + 0x04)<<2) /* 0x0010 */ -#define WT_ARAMP(bank) (((((bank)&1)<<0xd) + 0x05)<<2) /* 0x0014 */ -/* WT Voice registers */ -#define WT_STEREO(voice) ((WT_BAR(voice)+ 0x20 +(((voice)&0x1f)>>1))<<2) /* 0x0080 */ -#define WT_MUTE(voice) ((WT_BAR(voice)+ 0x40 +((voice)&0x1f))<<2) /* 0x0100 */ -#define WT_RUN(voice) ((WT_BAR(voice)+ 0x60 +((voice)&0x1f))<<2) /* 0x0180 */ -/* Some kind of parameters. */ -/* PARM0, PARM1 : Filter (0xFF000000), SampleRate (0x0000FFFF) */ -/* PARM2, PARM3 : Still unknown */ -#define WT_PARM(x,y) (((WT_BAR(x))+ 0x80 +(((x)&0x1f)<<2)+(y))<<2) /* 0x0200 */ -#define WT_DELAY(x,y) (((WT_BAR(x))+ 0x100 +(((x)&0x1f)<<2)+(y))<<2) /* 0x0400 */ - -/* Numeric indexes used by SetReg() and GetReg() */ -#if 0 -enum { - run = 0, /* 0 W 1:run 0:stop */ - parm0, /* 1 W filter, samplerate */ - parm1, /* 2 W filter, samplerate */ - parm2, /* 3 W */ - parm3, /* 4 RW volume. This value is calculated using floating point ops. */ - sramp, /* 5 W */ - mute, /* 6 W 1:mute, 0:unmute */ - gmode, /* 7 RO Looks like only bit0 is used. */ - aramp, /* 8 W */ - mramp, /* 9 W */ - ctrl, /* a W */ - delay, /* b W All 4 values are written at once with same value. */ - dsreg, /* c (R)W */ -} wt_reg; -#endif - -typedef struct { - u32 parm0; /* this_1E4 */ - u32 parm1; /* this_1E8 */ - u32 parm2; /* this_1EC */ - u32 parm3; /* this_1F0 */ - u32 this_1D0; -} wt_voice_t; - -#endif /* _AU88X0_WT_H */ - -/* End of file */ diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.c b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.c deleted file mode 100644 index b278e285..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.c +++ /dev/null @@ -1,795 +0,0 @@ -/*************************************************************************** - * au88x0_cxtalk.c - * - * Wed Nov 19 16:29:47 2003 - * Copyright 2003 mjander - * mjander@users.sourceforge.org - ****************************************************************************/ - -/* - * 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 Library 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 "au88x0_xtalk.h" - -/* Data (a whole lot of data.... ) */ - -static short const sXtalkWideKLeftEq = 0x269C; -static short const sXtalkWideKRightEq = 0x269C; -static short const sXtalkWideKLeftXt = 0xF25E; -static short const sXtalkWideKRightXt = 0xF25E; -static short const sXtalkWideShiftLeftEq = 1; -static short const sXtalkWideShiftRightEq = 1; -static short const sXtalkWideShiftLeftXt = 0; -static short const sXtalkWideShiftRightXt = 0; -static unsigned short const wXtalkWideLeftDelay = 0xd; -static unsigned short const wXtalkWideRightDelay = 0xd; -static short const sXtalkNarrowKLeftEq = 0x468D; -static short const sXtalkNarrowKRightEq = 0x468D; -static short const sXtalkNarrowKLeftXt = 0xF82E; -static short const sXtalkNarrowKRightXt = 0xF82E; -static short const sXtalkNarrowShiftLeftEq = 0x3; -static short const sXtalkNarrowShiftRightEq = 0x3; -static short const sXtalkNarrowShiftLeftXt = 0; -static short const sXtalkNarrowShiftRightXt = 0; -static unsigned short const wXtalkNarrowLeftDelay = 0x7; -static unsigned short const wXtalkNarrowRightDelay = 0x7; - -static xtalk_gains_t const asXtalkGainsDefault = { - 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, - 0x4000, 0x4000, 0x4000, 0x4000, 0x4000 -}; - -static xtalk_gains_t const asXtalkGainsTest = { - 0x7fff, 0x8000, 0x0000, 0x0000, 0x0001, - 0xffff, 0x4000, 0xc000, 0x0002, 0xfffe -}; - -static xtalk_gains_t const asXtalkGains1Chan = { - 0x7FFF, 0, 0, 0, 0, - 0x7FFF, 0, 0, 0, 0, -}; - -// Input gain for 4 A3D slices. One possible input pair is left zero. -static xtalk_gains_t const asXtalkGainsAllChan = { - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0, - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0 -}; - -static xtalk_gains_t const asXtalkGainsZeros = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static xtalk_dline_t const alXtalkDlineZeros = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; -static xtalk_dline_t const alXtalkDlineTest = { - 0x0000fc18, 0xfff03e8, 0x000186a0, 0xfffe7960, 1, 0xffffffff, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static xtalk_instate_t const asXtalkInStateZeros = { - 0, 0, 0, 0 -}; - -static xtalk_instate_t const asXtalkInStateTest = { - 0x0080, 0xff80, 0x0001, 0xffff -}; - -static xtalk_state_t const asXtalkOutStateZeros = { - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; - -static short const sDiamondKLeftEq = 0x401d; -static short const sDiamondKRightEq = 0x401d; -static short const sDiamondKLeftXt = 0xF90E; -static short const sDiamondKRightXt = 0xF90E; -static short const sDiamondShiftLeftEq = 1; -static short const sDiamondShiftRightEq = 1; -static short const sDiamondShiftLeftXt = 0; -static short const sDiamondShiftRightXt = 0; -static unsigned short const wDiamondLeftDelay = 0xb; -static unsigned short const wDiamondRightDelay = 0xb; - -static xtalk_coefs_t const asXtalkWideCoefsLeftEq = { - {0xEC4C, 0xDCE9, 0xFDC2, 0xFEEC, 0}, - {0x5F60, 0xCBCB, 0xFC26, 0x0305, 0}, - {0x340B, 0xe8f5, 0x236c, 0xe40d, 0}, - {0x76d5, 0xc78d, 0x05ac, 0xfa5b, 0}, - {0x7F04, 0xC0FA, 0x0263, 0xFDA2, 0} -}; -static xtalk_coefs_t const asXtalkWideCoefsRightEq = { - {0xEC4C, 0xDCE9, 0xFDC2, 0xFEEC, 0}, - {0x5F60, 0xCBCB, 0xFC26, 0x0305, 0}, - {0x340B, 0xe8f5, 0x236c, 0xe40d, 0}, - {0x76d5, 0xc78d, 0x05ac, 0xfa5b, 0}, - {0x7F04, 0xC0FA, 0x0263, 0xFDA2, 0} -}; -static xtalk_coefs_t const asXtalkWideCoefsLeftXt = { - {0x55c6, 0xc97b, 0x005b, 0x0047, 0}, - {0x6a60, 0xca20, 0xffc6, 0x0040, 0}, - {0x6411, 0xd711, 0xfca1, 0x0190, 0}, - {0x77dc, 0xc79e, 0xffb8, 0x000a, 0}, - {0, 0, 0, 0, 0} -}; -static xtalk_coefs_t const asXtalkWideCoefsRightXt = { - {0x55c6, 0xc97b, 0x005b, 0x0047, 0}, - {0x6a60, 0xca20, 0xffc6, 0x0040, 0}, - {0x6411, 0xd711, 0xfca1, 0x0190, 0}, - {0x77dc, 0xc79e, 0xffb8, 0x000a, 0}, - {0, 0, 0, 0, 0} -}; -static xtalk_coefs_t const asXtalkNarrowCoefsLeftEq = { - {0x50B5, 0xD07C, 0x026D, 0xFD21, 0}, - {0x460F, 0xE44F, 0xF75E, 0xEFA6, 0}, - {0x556D, 0xDCAB, 0x2098, 0xF0F2, 0}, - {0x7E03, 0xC1F0, 0x007D, 0xFF89, 0}, - {0x383E, 0xFD9D, 0xB278, 0x4547, 0} -}; - -static xtalk_coefs_t const asXtalkNarrowCoefsRightEq = { - {0x50B5, 0xD07C, 0x026D, 0xFD21, 0}, - {0x460F, 0xE44F, 0xF75E, 0xEFA6, 0}, - {0x556D, 0xDCAB, 0x2098, 0xF0F2, 0}, - {0x7E03, 0xC1F0, 0x007D, 0xFF89, 0}, - {0x383E, 0xFD9D, 0xB278, 0x4547, 0} -}; - -static xtalk_coefs_t const asXtalkNarrowCoefsLeftXt = { - {0x3CB2, 0xDF49, 0xF6EA, 0x095B, 0}, - {0x6777, 0xC915, 0xFEAF, 0x00B1, 0}, - {0x7762, 0xC7D9, 0x025B, 0xFDA6, 0}, - {0x6B7A, 0xD2AA, 0xF2FB, 0x0B64, 0}, - {0, 0, 0, 0, 0} -}; - -static xtalk_coefs_t const asXtalkNarrowCoefsRightXt = { - {0x3CB2, 0xDF49, 0xF6EA, 0x095B, 0}, - {0x6777, 0xC915, 0xFEAF, 0x00B1, 0}, - {0x7762, 0xC7D9, 0x025B, 0xFDA6, 0}, - {0x6B7A, 0xD2AA, 0xF2FB, 0x0B64, 0}, - {0, 0, 0, 0, 0} -}; - -static xtalk_coefs_t const asXtalkCoefsZeros = { - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; - -static xtalk_coefs_t const asXtalkCoefsPipe = { - {0, 0, 0x0FA0, 0, 0}, - {0, 0, 0x0FA0, 0, 0}, - {0, 0, 0x0FA0, 0, 0}, - {0, 0, 0x0FA0, 0, 0}, - {0, 0, 0x1180, 0, 0}, -}; -static xtalk_coefs_t const asXtalkCoefsNegPipe = { - {0, 0, 0xF380, 0, 0}, - {0, 0, 0xF380, 0, 0}, - {0, 0, 0xF380, 0, 0}, - {0, 0, 0xF380, 0, 0}, - {0, 0, 0xF200, 0, 0} -}; - -static xtalk_coefs_t const asXtalkCoefsNumTest = { - {0, 0, 0xF380, 0x8000, 0x6D60}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; - -static xtalk_coefs_t const asXtalkCoefsDenTest = { - {0xC000, 0x2000, 0x4000, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; - -static xtalk_state_t const asXtalkOutStateTest = { - {0x7FFF, 0x0004, 0xFFFC, 0}, - {0xFE00, 0x0008, 0xFFF8, 0x4000}, - {0x0200, 0x0010, 0xFFF0, 0xC000}, - {0x8000, 0x0020, 0xFFE0, 0}, - {0, 0, 0, 0} -}; - -static xtalk_coefs_t const asDiamondCoefsLeftEq = { - {0x0F1E, 0x2D05, 0xF8E3, 0x07C8, 0}, - {0x45E2, 0xCA51, 0x0448, 0xFCE7, 0}, - {0xA93E, 0xDBD5, 0x022C, 0x028A, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; - -static xtalk_coefs_t const asDiamondCoefsRightEq = { - {0x0F1E, 0x2D05, 0xF8E3, 0x07C8, 0}, - {0x45E2, 0xCA51, 0x0448, 0xFCE7, 0}, - {0xA93E, 0xDBD5, 0x022C, 0x028A, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; - -static xtalk_coefs_t const asDiamondCoefsLeftXt = { - {0x3B50, 0xFE08, 0xF959, 0x0060, 0}, - {0x9FCB, 0xD8F1, 0x00A2, 0x003A, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; - -static xtalk_coefs_t const asDiamondCoefsRightXt = { - {0x3B50, 0xFE08, 0xF959, 0x0060, 0}, - {0x9FCB, 0xD8F1, 0x00A2, 0x003A, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0} -}; - - /**/ -/* XTalk EQ and XT */ -static void -vortex_XtalkHw_SetLeftEQ(vortex_t * vortex, short arg_0, short arg_4, - xtalk_coefs_t const coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - hwwrite(vortex->mmio, 0x24200 + i * 0x24, coefs[i][0]); - hwwrite(vortex->mmio, 0x24204 + i * 0x24, coefs[i][1]); - hwwrite(vortex->mmio, 0x24208 + i * 0x24, coefs[i][2]); - hwwrite(vortex->mmio, 0x2420c + i * 0x24, coefs[i][3]); - hwwrite(vortex->mmio, 0x24210 + i * 0x24, coefs[i][4]); - } - hwwrite(vortex->mmio, 0x24538, arg_0 & 0xffff); - hwwrite(vortex->mmio, 0x2453C, arg_4 & 0xffff); -} - -static void -vortex_XtalkHw_SetRightEQ(vortex_t * vortex, short arg_0, short arg_4, - xtalk_coefs_t const coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - hwwrite(vortex->mmio, 0x242b4 + i * 0x24, coefs[i][0]); - hwwrite(vortex->mmio, 0x242b8 + i * 0x24, coefs[i][1]); - hwwrite(vortex->mmio, 0x242bc + i * 0x24, coefs[i][2]); - hwwrite(vortex->mmio, 0x242c0 + i * 0x24, coefs[i][3]); - hwwrite(vortex->mmio, 0x242c4 + i * 0x24, coefs[i][4]); - } - hwwrite(vortex->mmio, 0x24540, arg_0 & 0xffff); - hwwrite(vortex->mmio, 0x24544, arg_4 & 0xffff); -} - -static void -vortex_XtalkHw_SetLeftXT(vortex_t * vortex, short arg_0, short arg_4, - xtalk_coefs_t const coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - hwwrite(vortex->mmio, 0x24368 + i * 0x24, coefs[i][0]); - hwwrite(vortex->mmio, 0x2436c + i * 0x24, coefs[i][1]); - hwwrite(vortex->mmio, 0x24370 + i * 0x24, coefs[i][2]); - hwwrite(vortex->mmio, 0x24374 + i * 0x24, coefs[i][3]); - hwwrite(vortex->mmio, 0x24378 + i * 0x24, coefs[i][4]); - } - hwwrite(vortex->mmio, 0x24548, arg_0 & 0xffff); - hwwrite(vortex->mmio, 0x2454C, arg_4 & 0xffff); -} - -static void -vortex_XtalkHw_SetRightXT(vortex_t * vortex, short arg_0, short arg_4, - xtalk_coefs_t const coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - hwwrite(vortex->mmio, 0x2441C + i * 0x24, coefs[i][0]); - hwwrite(vortex->mmio, 0x24420 + i * 0x24, coefs[i][1]); - hwwrite(vortex->mmio, 0x24424 + i * 0x24, coefs[i][2]); - hwwrite(vortex->mmio, 0x24428 + i * 0x24, coefs[i][3]); - hwwrite(vortex->mmio, 0x2442C + i * 0x24, coefs[i][4]); - } - hwwrite(vortex->mmio, 0x24550, arg_0 & 0xffff); - hwwrite(vortex->mmio, 0x24554, arg_4 & 0xffff); -} - -static void -vortex_XtalkHw_SetLeftEQStates(vortex_t * vortex, - xtalk_instate_t const arg_0, - xtalk_state_t const coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - hwwrite(vortex->mmio, 0x24214 + i * 0x24, coefs[i][0]); - hwwrite(vortex->mmio, 0x24218 + i * 0x24, coefs[i][1]); - hwwrite(vortex->mmio, 0x2421C + i * 0x24, coefs[i][2]); - hwwrite(vortex->mmio, 0x24220 + i * 0x24, coefs[i][3]); - } - hwwrite(vortex->mmio, 0x244F8, arg_0[0]); - hwwrite(vortex->mmio, 0x244FC, arg_0[1]); - hwwrite(vortex->mmio, 0x24500, arg_0[2]); - hwwrite(vortex->mmio, 0x24504, arg_0[3]); -} - -static void -vortex_XtalkHw_SetRightEQStates(vortex_t * vortex, - xtalk_instate_t const arg_0, - xtalk_state_t const coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - hwwrite(vortex->mmio, 0x242C8 + i * 0x24, coefs[i][0]); - hwwrite(vortex->mmio, 0x242CC + i * 0x24, coefs[i][1]); - hwwrite(vortex->mmio, 0x242D0 + i * 0x24, coefs[i][2]); - hwwrite(vortex->mmio, 0x244D4 + i * 0x24, coefs[i][3]); - } - hwwrite(vortex->mmio, 0x24508, arg_0[0]); - hwwrite(vortex->mmio, 0x2450C, arg_0[1]); - hwwrite(vortex->mmio, 0x24510, arg_0[2]); - hwwrite(vortex->mmio, 0x24514, arg_0[3]); -} - -static void -vortex_XtalkHw_SetLeftXTStates(vortex_t * vortex, - xtalk_instate_t const arg_0, - xtalk_state_t const coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - hwwrite(vortex->mmio, 0x2437C + i * 0x24, coefs[i][0]); - hwwrite(vortex->mmio, 0x24380 + i * 0x24, coefs[i][1]); - hwwrite(vortex->mmio, 0x24384 + i * 0x24, coefs[i][2]); - hwwrite(vortex->mmio, 0x24388 + i * 0x24, coefs[i][3]); - } - hwwrite(vortex->mmio, 0x24518, arg_0[0]); - hwwrite(vortex->mmio, 0x2451C, arg_0[1]); - hwwrite(vortex->mmio, 0x24520, arg_0[2]); - hwwrite(vortex->mmio, 0x24524, arg_0[3]); -} - -static void -vortex_XtalkHw_SetRightXTStates(vortex_t * vortex, - xtalk_instate_t const arg_0, - xtalk_state_t const coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - hwwrite(vortex->mmio, 0x24430 + i * 0x24, coefs[i][0]); - hwwrite(vortex->mmio, 0x24434 + i * 0x24, coefs[i][1]); - hwwrite(vortex->mmio, 0x24438 + i * 0x24, coefs[i][2]); - hwwrite(vortex->mmio, 0x2443C + i * 0x24, coefs[i][3]); - } - hwwrite(vortex->mmio, 0x24528, arg_0[0]); - hwwrite(vortex->mmio, 0x2452C, arg_0[1]); - hwwrite(vortex->mmio, 0x24530, arg_0[2]); - hwwrite(vortex->mmio, 0x24534, arg_0[3]); -} - -#if 0 -static void -vortex_XtalkHw_GetLeftEQ(vortex_t * vortex, short *arg_0, short *arg_4, - xtalk_coefs_t coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - coefs[i][0] = hwread(vortex->mmio, 0x24200 + i * 0x24); - coefs[i][1] = hwread(vortex->mmio, 0x24204 + i * 0x24); - coefs[i][2] = hwread(vortex->mmio, 0x24208 + i * 0x24); - coefs[i][3] = hwread(vortex->mmio, 0x2420c + i * 0x24); - coefs[i][4] = hwread(vortex->mmio, 0x24210 + i * 0x24); - } - *arg_0 = hwread(vortex->mmio, 0x24538) & 0xffff; - *arg_4 = hwread(vortex->mmio, 0x2453c) & 0xffff; -} - -static void -vortex_XtalkHw_GetRightEQ(vortex_t * vortex, short *arg_0, short *arg_4, - xtalk_coefs_t coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - coefs[i][0] = hwread(vortex->mmio, 0x242b4 + i * 0x24); - coefs[i][1] = hwread(vortex->mmio, 0x242b8 + i * 0x24); - coefs[i][2] = hwread(vortex->mmio, 0x242bc + i * 0x24); - coefs[i][3] = hwread(vortex->mmio, 0x242c0 + i * 0x24); - coefs[i][4] = hwread(vortex->mmio, 0x242c4 + i * 0x24); - } - *arg_0 = hwread(vortex->mmio, 0x24540) & 0xffff; - *arg_4 = hwread(vortex->mmio, 0x24544) & 0xffff; -} - -static void -vortex_XtalkHw_GetLeftXT(vortex_t * vortex, short *arg_0, short *arg_4, - xtalk_coefs_t coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - coefs[i][0] = hwread(vortex->mmio, 0x24368 + i * 0x24); - coefs[i][1] = hwread(vortex->mmio, 0x2436C + i * 0x24); - coefs[i][2] = hwread(vortex->mmio, 0x24370 + i * 0x24); - coefs[i][3] = hwread(vortex->mmio, 0x24374 + i * 0x24); - coefs[i][4] = hwread(vortex->mmio, 0x24378 + i * 0x24); - } - *arg_0 = hwread(vortex->mmio, 0x24548) & 0xffff; - *arg_4 = hwread(vortex->mmio, 0x2454C) & 0xffff; -} - -static void -vortex_XtalkHw_GetRightXT(vortex_t * vortex, short *arg_0, short *arg_4, - xtalk_coefs_t coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - coefs[i][0] = hwread(vortex->mmio, 0x2441C + i * 0x24); - coefs[i][1] = hwread(vortex->mmio, 0x24420 + i * 0x24); - coefs[i][2] = hwread(vortex->mmio, 0x24424 + i * 0x24); - coefs[i][3] = hwread(vortex->mmio, 0x24428 + i * 0x24); - coefs[i][4] = hwread(vortex->mmio, 0x2442C + i * 0x24); - } - *arg_0 = hwread(vortex->mmio, 0x24550) & 0xffff; - *arg_4 = hwread(vortex->mmio, 0x24554) & 0xffff; -} - -static void -vortex_XtalkHw_GetLeftEQStates(vortex_t * vortex, xtalk_instate_t arg_0, - xtalk_state_t coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - coefs[i][0] = hwread(vortex->mmio, 0x24214 + i * 0x24); - coefs[i][1] = hwread(vortex->mmio, 0x24218 + i * 0x24); - coefs[i][2] = hwread(vortex->mmio, 0x2421C + i * 0x24); - coefs[i][3] = hwread(vortex->mmio, 0x24220 + i * 0x24); - } - arg_0[0] = hwread(vortex->mmio, 0x244F8); - arg_0[1] = hwread(vortex->mmio, 0x244FC); - arg_0[2] = hwread(vortex->mmio, 0x24500); - arg_0[3] = hwread(vortex->mmio, 0x24504); -} - -static void -vortex_XtalkHw_GetRightEQStates(vortex_t * vortex, xtalk_instate_t arg_0, - xtalk_state_t coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - coefs[i][0] = hwread(vortex->mmio, 0x242C8 + i * 0x24); - coefs[i][1] = hwread(vortex->mmio, 0x242CC + i * 0x24); - coefs[i][2] = hwread(vortex->mmio, 0x242D0 + i * 0x24); - coefs[i][3] = hwread(vortex->mmio, 0x242D4 + i * 0x24); - } - arg_0[0] = hwread(vortex->mmio, 0x24508); - arg_0[1] = hwread(vortex->mmio, 0x2450C); - arg_0[2] = hwread(vortex->mmio, 0x24510); - arg_0[3] = hwread(vortex->mmio, 0x24514); -} - -static void -vortex_XtalkHw_GetLeftXTStates(vortex_t * vortex, xtalk_instate_t arg_0, - xtalk_state_t coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - coefs[i][0] = hwread(vortex->mmio, 0x2437C + i * 0x24); - coefs[i][1] = hwread(vortex->mmio, 0x24380 + i * 0x24); - coefs[i][2] = hwread(vortex->mmio, 0x24384 + i * 0x24); - coefs[i][3] = hwread(vortex->mmio, 0x24388 + i * 0x24); - } - arg_0[0] = hwread(vortex->mmio, 0x24518); - arg_0[1] = hwread(vortex->mmio, 0x2451C); - arg_0[2] = hwread(vortex->mmio, 0x24520); - arg_0[3] = hwread(vortex->mmio, 0x24524); -} - -static void -vortex_XtalkHw_GetRightXTStates(vortex_t * vortex, xtalk_instate_t arg_0, - xtalk_state_t coefs) -{ - int i; - - for (i = 0; i < 5; i++) { - coefs[i][0] = hwread(vortex->mmio, 0x24430 + i * 0x24); - coefs[i][1] = hwread(vortex->mmio, 0x24434 + i * 0x24); - coefs[i][2] = hwread(vortex->mmio, 0x24438 + i * 0x24); - coefs[i][3] = hwread(vortex->mmio, 0x2443C + i * 0x24); - } - arg_0[0] = hwread(vortex->mmio, 0x24528); - arg_0[1] = hwread(vortex->mmio, 0x2452C); - arg_0[2] = hwread(vortex->mmio, 0x24530); - arg_0[3] = hwread(vortex->mmio, 0x24534); -} - -#endif -/* Gains */ - -static void -vortex_XtalkHw_SetGains(vortex_t * vortex, xtalk_gains_t const gains) -{ - int i; - - for (i = 0; i < XTGAINS_SZ; i++) { - hwwrite(vortex->mmio, 0x244D0 + (i * 4), gains[i]); - } -} - -static void -vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex) -{ - vortex_XtalkHw_SetGains(vortex, asXtalkGainsAllChan); -} - -#if 0 -static void vortex_XtalkHw_GetGains(vortex_t * vortex, xtalk_gains_t gains) -{ - int i; - - for (i = 0; i < XTGAINS_SZ; i++) - gains[i] = hwread(vortex->mmio, 0x244D0 + i * 4); -} - -#endif -/* Delay parameters */ - -static void -vortex_XtalkHw_SetDelay(vortex_t * vortex, unsigned short right, - unsigned short left) -{ - u32 esp0 = 0; - - esp0 &= 0x1FFFFFFF; - esp0 |= 0xA0000000; - esp0 = (esp0 & 0xffffE0ff) | ((right & 0x1F) << 8); - esp0 = (esp0 & 0xfffc1fff) | ((left & 0x1F) << 0xd); - - hwwrite(vortex->mmio, 0x24660, esp0); -} - -static void -vortex_XtalkHw_SetLeftDline(vortex_t * vortex, xtalk_dline_t const dline) -{ - int i; - - for (i = 0; i < 0x20; i++) { - hwwrite(vortex->mmio, 0x24000 + (i << 2), dline[i] & 0xffff); - hwwrite(vortex->mmio, 0x24080 + (i << 2), dline[i] >> 0x10); - } -} - -static void -vortex_XtalkHw_SetRightDline(vortex_t * vortex, xtalk_dline_t const dline) -{ - int i; - - for (i = 0; i < 0x20; i++) { - hwwrite(vortex->mmio, 0x24100 + (i << 2), dline[i] & 0xffff); - hwwrite(vortex->mmio, 0x24180 + (i << 2), dline[i] >> 0x10); - } -} - -#if 0 -static void -vortex_XtalkHw_GetDelay(vortex_t * vortex, unsigned short *right, - unsigned short *left) -{ - int esp0; - - esp0 = hwread(vortex->mmio, 0x24660); - *right = (esp0 >> 8) & 0x1f; - *left = (esp0 >> 0xd) & 0x1f; -} - -static void vortex_XtalkHw_GetLeftDline(vortex_t * vortex, xtalk_dline_t dline) -{ - int i; - - for (i = 0; i < 0x20; i++) { - dline[i] = - (hwread(vortex->mmio, 0x24000 + (i << 2)) & 0xffff) | - (hwread(vortex->mmio, 0x24080 + (i << 2)) << 0x10); - } -} - -static void vortex_XtalkHw_GetRightDline(vortex_t * vortex, xtalk_dline_t dline) -{ - int i; - - for (i = 0; i < 0x20; i++) { - dline[i] = - (hwread(vortex->mmio, 0x24100 + (i << 2)) & 0xffff) | - (hwread(vortex->mmio, 0x24180 + (i << 2)) << 0x10); - } -} - -#endif -/* Control/Global stuff */ - -#if 0 -static void vortex_XtalkHw_SetControlReg(vortex_t * vortex, u32 ctrl) -{ - hwwrite(vortex->mmio, 0x24660, ctrl); -} -static void vortex_XtalkHw_GetControlReg(vortex_t * vortex, u32 *ctrl) -{ - *ctrl = hwread(vortex->mmio, 0x24660); -} -#endif -static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, u32 sr) -{ - u32 temp; - - temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; - temp = (temp & 0xffffff07) | ((sr & 0x1f) << 3); - hwwrite(vortex->mmio, 0x24660, temp); -} - -#if 0 -static void vortex_XtalkHw_GetSampleRate(vortex_t * vortex, u32 *sr) -{ - *sr = (hwread(vortex->mmio, 0x24660) >> 3) & 0x1f; -} - -#endif -static void vortex_XtalkHw_Enable(vortex_t * vortex) -{ - u32 temp; - - temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; - temp |= 1; - hwwrite(vortex->mmio, 0x24660, temp); - -} - -static void vortex_XtalkHw_Disable(vortex_t * vortex) -{ - u32 temp; - - temp = (hwread(vortex->mmio, 0x24660) & 0x1FFFFFFF) | 0xC0000000; - temp &= 0xfffffffe; - hwwrite(vortex->mmio, 0x24660, temp); - -} - -static void vortex_XtalkHw_ZeroIO(vortex_t * vortex) -{ - int i; - - for (i = 0; i < 20; i++) - hwwrite(vortex->mmio, 0x24600 + (i << 2), 0); - for (i = 0; i < 4; i++) - hwwrite(vortex->mmio, 0x24650 + (i << 2), 0); -} - -static void vortex_XtalkHw_ZeroState(vortex_t * vortex) -{ - vortex_XtalkHw_ZeroIO(vortex); // inlined - - vortex_XtalkHw_SetLeftEQ(vortex, 0, 0, asXtalkCoefsZeros); - vortex_XtalkHw_SetRightEQ(vortex, 0, 0, asXtalkCoefsZeros); - - vortex_XtalkHw_SetLeftXT(vortex, 0, 0, asXtalkCoefsZeros); - vortex_XtalkHw_SetRightXT(vortex, 0, 0, asXtalkCoefsZeros); - - vortex_XtalkHw_SetGains(vortex, asXtalkGainsZeros); // inlined - - vortex_XtalkHw_SetDelay(vortex, 0, 0); // inlined - - vortex_XtalkHw_SetLeftDline(vortex, alXtalkDlineZeros); // inlined - vortex_XtalkHw_SetRightDline(vortex, alXtalkDlineZeros); // inlined - vortex_XtalkHw_SetLeftDline(vortex, alXtalkDlineZeros); // inlined - vortex_XtalkHw_SetRightDline(vortex, alXtalkDlineZeros); // inlined - - vortex_XtalkHw_SetLeftEQStates(vortex, asXtalkInStateZeros, - asXtalkOutStateZeros); - vortex_XtalkHw_SetRightEQStates(vortex, asXtalkInStateZeros, - asXtalkOutStateZeros); - vortex_XtalkHw_SetLeftXTStates(vortex, asXtalkInStateZeros, - asXtalkOutStateZeros); - vortex_XtalkHw_SetRightXTStates(vortex, asXtalkInStateZeros, - asXtalkOutStateZeros); -} - -static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex) -{ - - vortex_XtalkHw_SetLeftEQ(vortex, 0, 1, asXtalkCoefsPipe); - vortex_XtalkHw_SetRightEQ(vortex, 0, 1, asXtalkCoefsPipe); - vortex_XtalkHw_SetLeftXT(vortex, 0, 0, asXtalkCoefsZeros); - vortex_XtalkHw_SetRightXT(vortex, 0, 0, asXtalkCoefsZeros); - - vortex_XtalkHw_SetDelay(vortex, 0, 0); // inlined -} - -static void vortex_XtalkHw_ProgramXtalkWide(vortex_t * vortex) -{ - - vortex_XtalkHw_SetLeftEQ(vortex, sXtalkWideKLeftEq, - sXtalkWideShiftLeftEq, asXtalkWideCoefsLeftEq); - vortex_XtalkHw_SetRightEQ(vortex, sXtalkWideKRightEq, - sXtalkWideShiftRightEq, - asXtalkWideCoefsRightEq); - vortex_XtalkHw_SetLeftXT(vortex, sXtalkWideKLeftXt, - sXtalkWideShiftLeftXt, asXtalkWideCoefsLeftXt); - vortex_XtalkHw_SetRightXT(vortex, sXtalkWideKLeftXt, - sXtalkWideShiftLeftXt, - asXtalkWideCoefsLeftXt); - - vortex_XtalkHw_SetDelay(vortex, wXtalkWideRightDelay, wXtalkWideLeftDelay); // inlined -} - -static void vortex_XtalkHw_ProgramXtalkNarrow(vortex_t * vortex) -{ - - vortex_XtalkHw_SetLeftEQ(vortex, sXtalkNarrowKLeftEq, - sXtalkNarrowShiftLeftEq, - asXtalkNarrowCoefsLeftEq); - vortex_XtalkHw_SetRightEQ(vortex, sXtalkNarrowKRightEq, - sXtalkNarrowShiftRightEq, - asXtalkNarrowCoefsRightEq); - vortex_XtalkHw_SetLeftXT(vortex, sXtalkNarrowKLeftXt, - sXtalkNarrowShiftLeftXt, - asXtalkNarrowCoefsLeftXt); - vortex_XtalkHw_SetRightXT(vortex, sXtalkNarrowKLeftXt, - sXtalkNarrowShiftLeftXt, - asXtalkNarrowCoefsLeftXt); - - vortex_XtalkHw_SetDelay(vortex, wXtalkNarrowRightDelay, wXtalkNarrowLeftDelay); // inlined -} - -static void vortex_XtalkHw_ProgramDiamondXtalk(vortex_t * vortex) -{ - - //sDiamondKLeftEq,sDiamondKRightXt,asDiamondCoefsLeftEq - vortex_XtalkHw_SetLeftEQ(vortex, sDiamondKLeftEq, - sDiamondShiftLeftEq, asDiamondCoefsLeftEq); - vortex_XtalkHw_SetRightEQ(vortex, sDiamondKRightEq, - sDiamondShiftRightEq, asDiamondCoefsRightEq); - vortex_XtalkHw_SetLeftXT(vortex, sDiamondKLeftXt, - sDiamondShiftLeftXt, asDiamondCoefsLeftXt); - vortex_XtalkHw_SetRightXT(vortex, sDiamondKLeftXt, - sDiamondShiftLeftXt, asDiamondCoefsLeftXt); - - vortex_XtalkHw_SetDelay(vortex, wDiamondRightDelay, wDiamondLeftDelay); // inlined -} - -static void vortex_XtalkHw_init(vortex_t * vortex) -{ - vortex_XtalkHw_ZeroState(vortex); -} - -/* End of file */ diff --git a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.h b/ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.h deleted file mode 100644 index 7f4534b9..00000000 --- a/ANDROID_3.4.5/sound/pci/au88x0/au88x0_xtalk.h +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************** - * au88x0_cxtalk.h - * - * Wed Nov 19 19:07:17 2003 - * Copyright 2003 mjander - * mjander@users.sourceforge.org - ****************************************************************************/ - -/* - * 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 Library 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. - */ - -/* The crosstalk canceler supports 5 stereo input channels. The result is - available at one single output route pair (stereo). */ - -#ifndef _AU88X0_CXTALK_H -#define _AU88X0_CXTALK_H - -#include "au88x0.h" - -#define XTDLINE_SZ 32 -#define XTGAINS_SZ 10 -#define XTINST_SZ 4 - -#define XT_HEADPHONE 1 -#define XT_SPEAKER0 2 -#define XT_SPEAKER1 3 -#define XT_DIAMOND 4 - -typedef u32 xtalk_dline_t[XTDLINE_SZ]; -typedef u16 xtalk_gains_t[XTGAINS_SZ]; -typedef u16 xtalk_instate_t[XTINST_SZ]; -typedef u16 xtalk_coefs_t[5][5]; -typedef u16 xtalk_state_t[5][4]; - -static void vortex_XtalkHw_SetGains(vortex_t * vortex, - xtalk_gains_t const gains); -static void vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex); -static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, u32 sr); -static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex); -static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex); -static void vortex_XtalkHw_ProgramXtalkWide(vortex_t * vortex); -static void vortex_XtalkHw_ProgramXtalkNarrow(vortex_t * vortex); -static void vortex_XtalkHw_ProgramDiamondXtalk(vortex_t * vortex); -static void vortex_XtalkHw_Enable(vortex_t * vortex); -static void vortex_XtalkHw_Disable(vortex_t * vortex); -static void vortex_XtalkHw_init(vortex_t * vortex); - -#endif /* _AU88X0_CXTALK_H */ diff --git a/ANDROID_3.4.5/sound/pci/aw2/Makefile b/ANDROID_3.4.5/sound/pci/aw2/Makefile deleted file mode 100644 index 842335d3..00000000 --- a/ANDROID_3.4.5/sound/pci/aw2/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -snd-aw2-objs := aw2-alsa.o aw2-saa7146.o - -obj-$(CONFIG_SND_AW2) += snd-aw2.o diff --git a/ANDROID_3.4.5/sound/pci/aw2/aw2-alsa.c b/ANDROID_3.4.5/sound/pci/aw2/aw2-alsa.c deleted file mode 100644 index 1c523193..00000000 --- a/ANDROID_3.4.5/sound/pci/aw2/aw2-alsa.c +++ /dev/null @@ -1,792 +0,0 @@ -/***************************************************************************** - * - * Copyright (C) 2008 Cedric Bregardis and - * Jean-Christian Hassler - * - * This file is part of the Audiowerk2 ALSA driver - * - * The Audiowerk2 ALSA driver 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; version 2. - * - * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - *****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "saa7146.h" -#include "aw2-saa7146.h" - -MODULE_AUTHOR("Cedric Bregardis , " - "Jean-Christian Hassler "); -MODULE_DESCRIPTION("Emagic Audiowerk 2 sound driver"); -MODULE_LICENSE("GPL"); - -/********************************* - * DEFINES - ********************************/ -#define CTL_ROUTE_ANALOG 0 -#define CTL_ROUTE_DIGITAL 1 - -/********************************* - * TYPEDEFS - ********************************/ - /* hardware definition */ -static struct snd_pcm_hardware snd_aw2_playback_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_44100, - .rate_min = 44100, - .rate_max = 44100, - .channels_min = 2, - .channels_max = 4, - .buffer_bytes_max = 32768, - .period_bytes_min = 4096, - .period_bytes_max = 32768, - .periods_min = 1, - .periods_max = 1024, -}; - -static struct snd_pcm_hardware snd_aw2_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_44100, - .rate_min = 44100, - .rate_max = 44100, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 32768, - .period_bytes_min = 4096, - .period_bytes_max = 32768, - .periods_min = 1, - .periods_max = 1024, -}; - -struct aw2_pcm_device { - struct snd_pcm *pcm; - unsigned int stream_number; - struct aw2 *chip; -}; - -struct aw2 { - struct snd_aw2_saa7146 saa7146; - - struct pci_dev *pci; - int irq; - spinlock_t reg_lock; - struct mutex mtx; - - unsigned long iobase_phys; - void __iomem *iobase_virt; - - struct snd_card *card; - - struct aw2_pcm_device device_playback[NB_STREAM_PLAYBACK]; - struct aw2_pcm_device device_capture[NB_STREAM_CAPTURE]; -}; - -/********************************* - * FUNCTION DECLARATIONS - ********************************/ -static int __init alsa_card_aw2_init(void); -static void __exit alsa_card_aw2_exit(void); -static int snd_aw2_dev_free(struct snd_device *device); -static int __devinit snd_aw2_create(struct snd_card *card, - struct pci_dev *pci, struct aw2 **rchip); -static int __devinit snd_aw2_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id); -static void __devexit snd_aw2_remove(struct pci_dev *pci); -static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream); -static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream); -static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream); -static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream); -static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params); -static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream); -static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream); -static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream); -static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream, - int cmd); -static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream, - int cmd); -static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream - *substream); -static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream - *substream); -static int __devinit snd_aw2_new_pcm(struct aw2 *chip); - -static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value - *ucontrol); -static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value - *ucontrol); - -/********************************* - * VARIABLES - ********************************/ -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Audiowerk2 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the Audiowerk2 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard."); - -static DEFINE_PCI_DEVICE_TABLE(snd_aw2_ids) = { - {PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0, 0, - 0, 0, 0}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, snd_aw2_ids); - -/* pci_driver definition */ -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_aw2_ids, - .probe = snd_aw2_probe, - .remove = __devexit_p(snd_aw2_remove), -}; - -/* operators for playback PCM alsa interface */ -static struct snd_pcm_ops snd_aw2_playback_ops = { - .open = snd_aw2_pcm_playback_open, - .close = snd_aw2_pcm_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_aw2_pcm_hw_params, - .hw_free = snd_aw2_pcm_hw_free, - .prepare = snd_aw2_pcm_prepare_playback, - .trigger = snd_aw2_pcm_trigger_playback, - .pointer = snd_aw2_pcm_pointer_playback, -}; - -/* operators for capture PCM alsa interface */ -static struct snd_pcm_ops snd_aw2_capture_ops = { - .open = snd_aw2_pcm_capture_open, - .close = snd_aw2_pcm_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_aw2_pcm_hw_params, - .hw_free = snd_aw2_pcm_hw_free, - .prepare = snd_aw2_pcm_prepare_capture, - .trigger = snd_aw2_pcm_trigger_capture, - .pointer = snd_aw2_pcm_pointer_capture, -}; - -static struct snd_kcontrol_new aw2_control __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Capture Route", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0xffff, - .info = snd_aw2_control_switch_capture_info, - .get = snd_aw2_control_switch_capture_get, - .put = snd_aw2_control_switch_capture_put -}; - -/********************************* - * FUNCTION IMPLEMENTATIONS - ********************************/ - -/* initialization of the module */ -static int __init alsa_card_aw2_init(void) -{ - snd_printdd(KERN_DEBUG "aw2: Load aw2 module\n"); - return pci_register_driver(&driver); -} - -/* clean up the module */ -static void __exit alsa_card_aw2_exit(void) -{ - snd_printdd(KERN_DEBUG "aw2: Unload aw2 module\n"); - pci_unregister_driver(&driver); -} - -module_init(alsa_card_aw2_init); -module_exit(alsa_card_aw2_exit); - -/* component-destructor */ -static int snd_aw2_dev_free(struct snd_device *device) -{ - struct aw2 *chip = device->device_data; - - /* Free hardware */ - snd_aw2_saa7146_free(&chip->saa7146); - - /* release the irq */ - if (chip->irq >= 0) - free_irq(chip->irq, (void *)chip); - /* release the i/o ports & memory */ - if (chip->iobase_virt) - iounmap(chip->iobase_virt); - - pci_release_regions(chip->pci); - /* disable the PCI entry */ - pci_disable_device(chip->pci); - /* release the data */ - kfree(chip); - - return 0; -} - -/* chip-specific constructor */ -static int __devinit snd_aw2_create(struct snd_card *card, - struct pci_dev *pci, struct aw2 **rchip) -{ - struct aw2 *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_aw2_dev_free, - }; - - *rchip = NULL; - - /* initialize the PCI entry */ - err = pci_enable_device(pci); - if (err < 0) - return err; - pci_set_master(pci); - - /* check PCI availability (32bit DMA) */ - if ((pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) || - (pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0)) { - printk(KERN_ERR "aw2: Impossible to set 32bit mask DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - /* initialize the stuff */ - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - /* (1) PCI resource allocation */ - err = pci_request_regions(pci, "Audiowerk2"); - if (err < 0) { - pci_disable_device(pci); - kfree(chip); - return err; - } - chip->iobase_phys = pci_resource_start(pci, 0); - chip->iobase_virt = - ioremap_nocache(chip->iobase_phys, - pci_resource_len(pci, 0)); - - if (chip->iobase_virt == NULL) { - printk(KERN_ERR "aw2: unable to remap memory region"); - pci_release_regions(pci); - pci_disable_device(pci); - kfree(chip); - return -ENOMEM; - } - - /* (2) initialization of the chip hardware */ - snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt); - - if (request_irq(pci->irq, snd_aw2_saa7146_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq); - - iounmap(chip->iobase_virt); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return -EBUSY; - } - chip->irq = pci->irq; - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - free_irq(chip->irq, (void *)chip); - iounmap(chip->iobase_virt); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - *rchip = chip; - - printk(KERN_INFO - "Audiowerk 2 sound card (saa7146 chipset) detected and " - "managed\n"); - return 0; -} - -/* constructor */ -static int __devinit snd_aw2_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct aw2 *chip; - int err; - - /* (1) Continue if device is not enabled, else inc dev */ - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - /* (2) Create card instance */ - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - /* (3) Create main component */ - err = snd_aw2_create(card, pci, &chip); - if (err < 0) { - snd_card_free(card); - return err; - } - - /* initialize mutex */ - mutex_init(&chip->mtx); - /* init spinlock */ - spin_lock_init(&chip->reg_lock); - /* (4) Define driver ID and name string */ - strcpy(card->driver, "aw2"); - strcpy(card->shortname, "Audiowerk2"); - - sprintf(card->longname, "%s with SAA7146 irq %i", - card->shortname, chip->irq); - - /* (5) Create other components */ - snd_aw2_new_pcm(chip); - - /* (6) Register card instance */ - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - - /* (7) Set PCI driver data */ - pci_set_drvdata(pci, card); - - dev++; - return 0; -} - -/* destructor */ -static void __devexit snd_aw2_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -/* open callback */ -static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_printdd(KERN_DEBUG "aw2: Playback_open\n"); - runtime->hw = snd_aw2_playback_hw; - return 0; -} - -/* close callback */ -static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream) -{ - return 0; - -} - -static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_printdd(KERN_DEBUG "aw2: Capture_open\n"); - runtime->hw = snd_aw2_capture_hw; - return 0; -} - -/* close callback */ -static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream) -{ - /* TODO: something to do ? */ - return 0; -} - - /* hw_params callback */ -static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -/* prepare callback for playback */ -static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream) -{ - struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream); - struct aw2 *chip = pcm_device->chip; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long period_size, buffer_size; - - mutex_lock(&chip->mtx); - - period_size = snd_pcm_lib_period_bytes(substream); - buffer_size = snd_pcm_lib_buffer_bytes(substream); - - snd_aw2_saa7146_pcm_init_playback(&chip->saa7146, - pcm_device->stream_number, - runtime->dma_addr, period_size, - buffer_size); - - /* Define Interrupt callback */ - snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number, - (snd_aw2_saa7146_it_cb) - snd_pcm_period_elapsed, - (void *)substream); - - mutex_unlock(&chip->mtx); - - return 0; -} - -/* prepare callback for capture */ -static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream) -{ - struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream); - struct aw2 *chip = pcm_device->chip; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long period_size, buffer_size; - - mutex_lock(&chip->mtx); - - period_size = snd_pcm_lib_period_bytes(substream); - buffer_size = snd_pcm_lib_buffer_bytes(substream); - - snd_aw2_saa7146_pcm_init_capture(&chip->saa7146, - pcm_device->stream_number, - runtime->dma_addr, period_size, - buffer_size); - - /* Define Interrupt callback */ - snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number, - (snd_aw2_saa7146_it_cb) - snd_pcm_period_elapsed, - (void *)substream); - - mutex_unlock(&chip->mtx); - - return 0; -} - -/* playback trigger callback */ -static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream, - int cmd) -{ - int status = 0; - struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream); - struct aw2 *chip = pcm_device->chip; - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_aw2_saa7146_pcm_trigger_start_playback(&chip->saa7146, - pcm_device-> - stream_number); - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_aw2_saa7146_pcm_trigger_stop_playback(&chip->saa7146, - pcm_device-> - stream_number); - break; - default: - status = -EINVAL; - } - spin_unlock(&chip->reg_lock); - return status; -} - -/* capture trigger callback */ -static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream, - int cmd) -{ - int status = 0; - struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream); - struct aw2 *chip = pcm_device->chip; - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_aw2_saa7146_pcm_trigger_start_capture(&chip->saa7146, - pcm_device-> - stream_number); - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_aw2_saa7146_pcm_trigger_stop_capture(&chip->saa7146, - pcm_device-> - stream_number); - break; - default: - status = -EINVAL; - } - spin_unlock(&chip->reg_lock); - return status; -} - -/* playback pointer callback */ -static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream - *substream) -{ - struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream); - struct aw2 *chip = pcm_device->chip; - unsigned int current_ptr; - - /* get the current hardware pointer */ - struct snd_pcm_runtime *runtime = substream->runtime; - current_ptr = - snd_aw2_saa7146_get_hw_ptr_playback(&chip->saa7146, - pcm_device->stream_number, - runtime->dma_area, - runtime->buffer_size); - - return bytes_to_frames(substream->runtime, current_ptr); -} - -/* capture pointer callback */ -static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream - *substream) -{ - struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream); - struct aw2 *chip = pcm_device->chip; - unsigned int current_ptr; - - /* get the current hardware pointer */ - struct snd_pcm_runtime *runtime = substream->runtime; - current_ptr = - snd_aw2_saa7146_get_hw_ptr_capture(&chip->saa7146, - pcm_device->stream_number, - runtime->dma_area, - runtime->buffer_size); - - return bytes_to_frames(substream->runtime, current_ptr); -} - -/* create a pcm device */ -static int __devinit snd_aw2_new_pcm(struct aw2 *chip) -{ - struct snd_pcm *pcm_playback_ana; - struct snd_pcm *pcm_playback_num; - struct snd_pcm *pcm_capture; - struct aw2_pcm_device *pcm_device; - int err = 0; - - /* Create new Alsa PCM device */ - - err = snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0, - &pcm_playback_ana); - if (err < 0) { - printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err); - return err; - } - - /* Creation ok */ - pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_ANA]; - - /* Set PCM device name */ - strcpy(pcm_playback_ana->name, "Analog playback"); - /* Associate private data to PCM device */ - pcm_playback_ana->private_data = pcm_device; - /* set operators of PCM device */ - snd_pcm_set_ops(pcm_playback_ana, SNDRV_PCM_STREAM_PLAYBACK, - &snd_aw2_playback_ops); - /* store PCM device */ - pcm_device->pcm = pcm_playback_ana; - /* give base chip pointer to our internal pcm device - structure */ - pcm_device->chip = chip; - /* Give stream number to PCM device */ - pcm_device->stream_number = NUM_STREAM_PLAYBACK_ANA; - - /* pre-allocation of buffers */ - /* Preallocate continuous pages. */ - err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data - (chip->pci), - 64 * 1024, 64 * 1024); - if (err) - printk(KERN_ERR "aw2: snd_pcm_lib_preallocate_pages_for_all " - "error (0x%X)\n", err); - - err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0, - &pcm_playback_num); - - if (err < 0) { - printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err); - return err; - } - /* Creation ok */ - pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_DIG]; - - /* Set PCM device name */ - strcpy(pcm_playback_num->name, "Digital playback"); - /* Associate private data to PCM device */ - pcm_playback_num->private_data = pcm_device; - /* set operators of PCM device */ - snd_pcm_set_ops(pcm_playback_num, SNDRV_PCM_STREAM_PLAYBACK, - &snd_aw2_playback_ops); - /* store PCM device */ - pcm_device->pcm = pcm_playback_num; - /* give base chip pointer to our internal pcm device - structure */ - pcm_device->chip = chip; - /* Give stream number to PCM device */ - pcm_device->stream_number = NUM_STREAM_PLAYBACK_DIG; - - /* pre-allocation of buffers */ - /* Preallocate continuous pages. */ - err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data - (chip->pci), - 64 * 1024, 64 * 1024); - if (err) - printk(KERN_ERR - "aw2: snd_pcm_lib_preallocate_pages_for_all error " - "(0x%X)\n", err); - - - - err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1, - &pcm_capture); - - if (err < 0) { - printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err); - return err; - } - - /* Creation ok */ - pcm_device = &chip->device_capture[NUM_STREAM_CAPTURE_ANA]; - - /* Set PCM device name */ - strcpy(pcm_capture->name, "Capture"); - /* Associate private data to PCM device */ - pcm_capture->private_data = pcm_device; - /* set operators of PCM device */ - snd_pcm_set_ops(pcm_capture, SNDRV_PCM_STREAM_CAPTURE, - &snd_aw2_capture_ops); - /* store PCM device */ - pcm_device->pcm = pcm_capture; - /* give base chip pointer to our internal pcm device - structure */ - pcm_device->chip = chip; - /* Give stream number to PCM device */ - pcm_device->stream_number = NUM_STREAM_CAPTURE_ANA; - - /* pre-allocation of buffers */ - /* Preallocate continuous pages. */ - err = snd_pcm_lib_preallocate_pages_for_all(pcm_capture, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data - (chip->pci), - 64 * 1024, 64 * 1024); - if (err) - printk(KERN_ERR - "aw2: snd_pcm_lib_preallocate_pages_for_all error " - "(0x%X)\n", err); - - - /* Create control */ - err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip)); - if (err < 0) { - printk(KERN_ERR "aw2: snd_ctl_add error (0x%X)\n", err); - return err; - } - - return 0; -} - -static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { - "Analog", "Digital" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) { - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - } - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value - *ucontrol) -{ - struct aw2 *chip = snd_kcontrol_chip(kcontrol); - if (snd_aw2_saa7146_is_using_digital_input(&chip->saa7146)) - ucontrol->value.enumerated.item[0] = CTL_ROUTE_DIGITAL; - else - ucontrol->value.enumerated.item[0] = CTL_ROUTE_ANALOG; - return 0; -} - -static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value - *ucontrol) -{ - struct aw2 *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int is_disgital = - snd_aw2_saa7146_is_using_digital_input(&chip->saa7146); - - if (((ucontrol->value.integer.value[0] == CTL_ROUTE_DIGITAL) - && !is_disgital) - || ((ucontrol->value.integer.value[0] == CTL_ROUTE_ANALOG) - && is_disgital)) { - snd_aw2_saa7146_use_digital_input(&chip->saa7146, !is_disgital); - changed = 1; - } - return changed; -} diff --git a/ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.c b/ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.c deleted file mode 100644 index 44396369..00000000 --- a/ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.c +++ /dev/null @@ -1,463 +0,0 @@ -/***************************************************************************** - * - * Copyright (C) 2008 Cedric Bregardis and - * Jean-Christian Hassler - * - * This file is part of the Audiowerk2 ALSA driver - * - * The Audiowerk2 ALSA driver 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; version 2. - * - * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - *****************************************************************************/ - -#define AW2_SAA7146_M - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "saa7146.h" -#include "aw2-saa7146.h" - -#include "aw2-tsl.c" - -#define WRITEREG(value, addr) writel((value), chip->base_addr + (addr)) -#define READREG(addr) readl(chip->base_addr + (addr)) - -static struct snd_aw2_saa7146_cb_param - arr_substream_it_playback_cb[NB_STREAM_PLAYBACK]; -static struct snd_aw2_saa7146_cb_param - arr_substream_it_capture_cb[NB_STREAM_CAPTURE]; - -static int snd_aw2_saa7146_get_limit(int size); - -/* chip-specific destructor */ -int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip) -{ - /* disable all irqs */ - WRITEREG(0, IER); - - /* reset saa7146 */ - WRITEREG((MRST_N << 16), MC1); - - /* Unset base addr */ - chip->base_addr = NULL; - - return 0; -} - -void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip, - void __iomem *pci_base_addr) -{ - /* set PCI burst/threshold - - Burst length definition - VALUE BURST LENGTH - 000 1 Dword - 001 2 Dwords - 010 4 Dwords - 011 8 Dwords - 100 16 Dwords - 101 32 Dwords - 110 64 Dwords - 111 128 Dwords - - Threshold definition - VALUE WRITE MODE READ MODE - 00 1 Dword of valid data 1 empty Dword - 01 4 Dwords of valid data 4 empty Dwords - 10 8 Dwords of valid data 8 empty Dwords - 11 16 Dwords of valid data 16 empty Dwords */ - - unsigned int acon2; - unsigned int acon1 = 0; - int i; - - /* Set base addr */ - chip->base_addr = pci_base_addr; - - /* disable all irqs */ - WRITEREG(0, IER); - - /* reset saa7146 */ - WRITEREG((MRST_N << 16), MC1); - - /* enable audio interface */ -#ifdef __BIG_ENDIAN - acon1 |= A1_SWAP; - acon1 |= A2_SWAP; -#endif - /* WS0_CTRL, WS0_SYNC: input TSL1, I2S */ - - /* At initialization WS1 and WS2 are disabled (configured as input) */ - acon1 |= 0 * WS1_CTRL; - acon1 |= 0 * WS2_CTRL; - - /* WS4 is not used. So it must not restart A2. - This is why it is configured as output (force to low) */ - acon1 |= 3 * WS4_CTRL; - - /* WS3_CTRL, WS3_SYNC: output TSL2, I2S */ - acon1 |= 2 * WS3_CTRL; - - /* A1 and A2 are active and asynchronous */ - acon1 |= 3 * AUDIO_MODE; - WRITEREG(acon1, ACON1); - - /* The following comes from original windows driver. - It is needed to have a correct behavior of input and output - simultenously, but I don't know why ! */ - WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) + - 3 * (BurstA1_out) + 3 * (ThreshA1_out) + - 3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A); - - /* enable audio port pins */ - WRITEREG((EAP << 16) | EAP, MC1); - - /* enable I2C */ - WRITEREG((EI2C << 16) | EI2C, MC1); - /* enable interrupts */ - WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER); - - /* audio configuration */ - acon2 = A2_CLKSRC | BCLK1_OEN; - WRITEREG(acon2, ACON2); - - /* By default use analog input */ - snd_aw2_saa7146_use_digital_input(chip, 0); - - /* TSL setup */ - for (i = 0; i < 8; ++i) { - WRITEREG(tsl1[i], TSL1 + (i * 4)); - WRITEREG(tsl2[i], TSL2 + (i * 4)); - } - -} - -void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip, - int stream_number, - unsigned long dma_addr, - unsigned long period_size, - unsigned long buffer_size) -{ - unsigned long dw_page, dw_limit; - - /* Configure DMA for substream - Configuration informations: ALSA has allocated continuous memory - pages. So we don't need to use MMU of saa7146. - */ - - /* No MMU -> nothing to do with PageA1, we only configure the limit of - PageAx_out register */ - /* Disable MMU */ - dw_page = (0L << 11); - - /* Configure Limit for DMA access. - The limit register defines an address limit, which generates - an interrupt if passed by the actual PCI address pointer. - '0001' means an interrupt will be generated if the lower - 6 bits (64 bytes) of the PCI address are zero. '0010' - defines a limit of 128 bytes, '0011' one of 256 bytes, and - so on up to 1 Mbyte defined by '1111'. This interrupt range - can be calculated as follows: - Range = 2^(5 + Limit) bytes. - */ - dw_limit = snd_aw2_saa7146_get_limit(period_size); - dw_page |= (dw_limit << 4); - - if (stream_number == 0) { - WRITEREG(dw_page, PageA2_out); - - /* Base address for DMA transfert. */ - /* This address has been reserved by ALSA. */ - /* This is a physical address */ - WRITEREG(dma_addr, BaseA2_out); - - /* Define upper limit for DMA access */ - WRITEREG(dma_addr + buffer_size, ProtA2_out); - - } else if (stream_number == 1) { - WRITEREG(dw_page, PageA1_out); - - /* Base address for DMA transfert. */ - /* This address has been reserved by ALSA. */ - /* This is a physical address */ - WRITEREG(dma_addr, BaseA1_out); - - /* Define upper limit for DMA access */ - WRITEREG(dma_addr + buffer_size, ProtA1_out); - } else { - printk(KERN_ERR - "aw2: snd_aw2_saa7146_pcm_init_playback: " - "Substream number is not 0 or 1 -> not managed\n"); - } -} - -void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip, - int stream_number, unsigned long dma_addr, - unsigned long period_size, - unsigned long buffer_size) -{ - unsigned long dw_page, dw_limit; - - /* Configure DMA for substream - Configuration informations: ALSA has allocated continuous memory - pages. So we don't need to use MMU of saa7146. - */ - - /* No MMU -> nothing to do with PageA1, we only configure the limit of - PageAx_out register */ - /* Disable MMU */ - dw_page = (0L << 11); - - /* Configure Limit for DMA access. - The limit register defines an address limit, which generates - an interrupt if passed by the actual PCI address pointer. - '0001' means an interrupt will be generated if the lower - 6 bits (64 bytes) of the PCI address are zero. '0010' - defines a limit of 128 bytes, '0011' one of 256 bytes, and - so on up to 1 Mbyte defined by '1111'. This interrupt range - can be calculated as follows: - Range = 2^(5 + Limit) bytes. - */ - dw_limit = snd_aw2_saa7146_get_limit(period_size); - dw_page |= (dw_limit << 4); - - if (stream_number == 0) { - WRITEREG(dw_page, PageA1_in); - - /* Base address for DMA transfert. */ - /* This address has been reserved by ALSA. */ - /* This is a physical address */ - WRITEREG(dma_addr, BaseA1_in); - - /* Define upper limit for DMA access */ - WRITEREG(dma_addr + buffer_size, ProtA1_in); - } else { - printk(KERN_ERR - "aw2: snd_aw2_saa7146_pcm_init_capture: " - "Substream number is not 0 -> not managed\n"); - } -} - -void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number, - snd_aw2_saa7146_it_cb - p_it_callback, - void *p_callback_param) -{ - if (stream_number < NB_STREAM_PLAYBACK) { - arr_substream_it_playback_cb[stream_number].p_it_callback = - (snd_aw2_saa7146_it_cb) p_it_callback; - arr_substream_it_playback_cb[stream_number].p_callback_param = - (void *)p_callback_param; - } -} - -void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number, - snd_aw2_saa7146_it_cb - p_it_callback, - void *p_callback_param) -{ - if (stream_number < NB_STREAM_CAPTURE) { - arr_substream_it_capture_cb[stream_number].p_it_callback = - (snd_aw2_saa7146_it_cb) p_it_callback; - arr_substream_it_capture_cb[stream_number].p_callback_param = - (void *)p_callback_param; - } -} - -void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip, - int stream_number) -{ - unsigned int acon1 = 0; - /* In aw8 driver, dma transfert is always active. It is - started and stopped in a larger "space" */ - acon1 = READREG(ACON1); - if (stream_number == 0) { - WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1); - - /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */ - acon1 |= 2 * WS2_CTRL; - WRITEREG(acon1, ACON1); - - } else if (stream_number == 1) { - WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1); - - /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */ - acon1 |= 1 * WS1_CTRL; - WRITEREG(acon1, ACON1); - } -} - -void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip, - int stream_number) -{ - unsigned int acon1 = 0; - acon1 = READREG(ACON1); - if (stream_number == 0) { - /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */ - acon1 &= ~(3 * WS2_CTRL); - WRITEREG(acon1, ACON1); - - WRITEREG((TR_E_A2_OUT << 16), MC1); - } else if (stream_number == 1) { - /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */ - acon1 &= ~(3 * WS1_CTRL); - WRITEREG(acon1, ACON1); - - WRITEREG((TR_E_A1_OUT << 16), MC1); - } -} - -void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip, - int stream_number) -{ - /* In aw8 driver, dma transfert is always active. It is - started and stopped in a larger "space" */ - if (stream_number == 0) - WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1); -} - -void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip, - int stream_number) -{ - if (stream_number == 0) - WRITEREG((TR_E_A1_IN << 16), MC1); -} - -irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id) -{ - unsigned int isr; - unsigned int iicsta; - struct snd_aw2_saa7146 *chip = dev_id; - - isr = READREG(ISR); - if (!isr) - return IRQ_NONE; - - WRITEREG(isr, ISR); - - if (isr & (IIC_S | IIC_E)) { - iicsta = READREG(IICSTA); - WRITEREG(0x100, IICSTA); - } - - if (isr & A1_out) { - if (arr_substream_it_playback_cb[1].p_it_callback != NULL) { - arr_substream_it_playback_cb[1]. - p_it_callback(arr_substream_it_playback_cb[1]. - p_callback_param); - } - } - if (isr & A2_out) { - if (arr_substream_it_playback_cb[0].p_it_callback != NULL) { - arr_substream_it_playback_cb[0]. - p_it_callback(arr_substream_it_playback_cb[0]. - p_callback_param); - } - - } - if (isr & A1_in) { - if (arr_substream_it_capture_cb[0].p_it_callback != NULL) { - arr_substream_it_capture_cb[0]. - p_it_callback(arr_substream_it_capture_cb[0]. - p_callback_param); - } - } - return IRQ_HANDLED; -} - -unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip, - int stream_number, - unsigned char *start_addr, - unsigned int buffer_size) -{ - long pci_adp = 0; - size_t ptr = 0; - - if (stream_number == 0) { - pci_adp = READREG(PCI_ADP3); - ptr = pci_adp - (long)start_addr; - - if (ptr == buffer_size) - ptr = 0; - } - if (stream_number == 1) { - pci_adp = READREG(PCI_ADP1); - ptr = pci_adp - (size_t) start_addr; - - if (ptr == buffer_size) - ptr = 0; - } - return ptr; -} - -unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip, - int stream_number, - unsigned char *start_addr, - unsigned int buffer_size) -{ - size_t pci_adp = 0; - size_t ptr = 0; - if (stream_number == 0) { - pci_adp = READREG(PCI_ADP2); - ptr = pci_adp - (size_t) start_addr; - - if (ptr == buffer_size) - ptr = 0; - } - return ptr; -} - -void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip, - int use_digital) -{ - /* FIXME: switch between analog and digital input does not always work. - It can produce a kind of white noise. It seams that received data - are inverted sometime (endian inversion). Why ? I don't know, maybe - a problem of synchronization... However for the time being I have - not found the problem. Workaround: switch again (and again) between - digital and analog input until it works. */ - if (use_digital) - WRITEREG(0x40, GPIO_CTRL); - else - WRITEREG(0x50, GPIO_CTRL); -} - -int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip) -{ - unsigned int reg_val = READREG(GPIO_CTRL); - if ((reg_val & 0xFF) == 0x40) - return 1; - else - return 0; -} - - -static int snd_aw2_saa7146_get_limit(int size) -{ - int limitsize = 32; - int limit = 0; - while (limitsize < size) { - limitsize *= 2; - limit++; - } - return limit; -} diff --git a/ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.h b/ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.h deleted file mode 100644 index 5b35e358..00000000 --- a/ANDROID_3.4.5/sound/pci/aw2/aw2-saa7146.h +++ /dev/null @@ -1,105 +0,0 @@ -/***************************************************************************** - * - * Copyright (C) 2008 Cedric Bregardis and - * Jean-Christian Hassler - * - * This file is part of the Audiowerk2 ALSA driver - * - * The Audiowerk2 ALSA driver 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; version 2. - * - * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - *****************************************************************************/ - -#ifndef AW2_SAA7146_H -#define AW2_SAA7146_H - -#define NB_STREAM_PLAYBACK 2 -#define NB_STREAM_CAPTURE 1 - -#define NUM_STREAM_PLAYBACK_ANA 0 -#define NUM_STREAM_PLAYBACK_DIG 1 - -#define NUM_STREAM_CAPTURE_ANA 0 - -typedef void (*snd_aw2_saa7146_it_cb) (void *); - -struct snd_aw2_saa7146_cb_param { - snd_aw2_saa7146_it_cb p_it_callback; - void *p_callback_param; -}; - -/* definition of the chip-specific record */ - -struct snd_aw2_saa7146 { - void __iomem *base_addr; -}; - -extern void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip, - void __iomem *pci_base_addr); -extern int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip); - -extern void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip, - int stream_number, - unsigned long dma_addr, - unsigned long period_size, - unsigned long buffer_size); -extern void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip, - int stream_number, - unsigned long dma_addr, - unsigned long period_size, - unsigned long buffer_size); -extern void snd_aw2_saa7146_define_it_playback_callback(unsigned int - stream_number, - snd_aw2_saa7146_it_cb - p_it_callback, - void *p_callback_param); -extern void snd_aw2_saa7146_define_it_capture_callback(unsigned int - stream_number, - snd_aw2_saa7146_it_cb - p_it_callback, - void *p_callback_param); -extern void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 - *chip, int stream_number); -extern void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 - *chip, int stream_number); - -extern void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 - *chip, - int stream_number); -extern void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 - *chip, int stream_number); - -extern irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id); -extern unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 - *chip, - int stream_number, - unsigned char - *start_addr, - unsigned int - buffer_size); -extern unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 - *chip, - int stream_number, - unsigned char - *start_addr, - unsigned int - buffer_size); - -extern void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip, - int use_digital); - -extern int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 - *chip); - -#endif diff --git a/ANDROID_3.4.5/sound/pci/aw2/aw2-tsl.c b/ANDROID_3.4.5/sound/pci/aw2/aw2-tsl.c deleted file mode 100644 index 459b0311..00000000 --- a/ANDROID_3.4.5/sound/pci/aw2/aw2-tsl.c +++ /dev/null @@ -1,110 +0,0 @@ -/***************************************************************************** - * - * Copyright (C) 2008 Cedric Bregardis and - * Jean-Christian Hassler - * Copyright 1998 Emagic Soft- und Hardware GmbH - * Copyright 2002 Martijn Sipkema - * - * This file is part of the Audiowerk2 ALSA driver - * - * The Audiowerk2 ALSA driver 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; version 2. - * - * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - *****************************************************************************/ - -#define TSL_WS0 (1UL << 31) -#define TSL_WS1 (1UL << 30) -#define TSL_WS2 (1UL << 29) -#define TSL_WS3 (1UL << 28) -#define TSL_WS4 (1UL << 27) -#define TSL_DIS_A1 (1UL << 24) -#define TSL_SDW_A1 (1UL << 23) -#define TSL_SIB_A1 (1UL << 22) -#define TSL_SF_A1 (1UL << 21) -#define TSL_LF_A1 (1UL << 20) -#define TSL_BSEL_A1 (1UL << 17) -#define TSL_DOD_A1 (1UL << 15) -#define TSL_LOW_A1 (1UL << 14) -#define TSL_DIS_A2 (1UL << 11) -#define TSL_SDW_A2 (1UL << 10) -#define TSL_SIB_A2 (1UL << 9) -#define TSL_SF_A2 (1UL << 8) -#define TSL_LF_A2 (1UL << 7) -#define TSL_BSEL_A2 (1UL << 4) -#define TSL_DOD_A2 (1UL << 2) -#define TSL_LOW_A2 (1UL << 1) -#define TSL_EOS (1UL << 0) - - /* Audiowerk8 hardware setup: */ - /* WS0, SD4, TSL1 - Analog/ digital in */ - /* WS1, SD0, TSL1 - Analog out #1, digital out */ - /* WS2, SD2, TSL1 - Analog out #2 */ - /* WS3, SD1, TSL2 - Analog out #3 */ - /* WS4, SD3, TSL2 - Analog out #4 */ - - /* Audiowerk8 timing: */ - /* Timeslot: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... */ - - /* A1_INPUT: */ - /* SD4: <_ADC-L_>-------<_ADC-R_>-------< */ - /* WS0: _______________/---------------\_ */ - - /* A1_OUTPUT: */ - /* SD0: <_1-L___>-------<_1-R___>-------< */ - /* WS1: _______________/---------------\_ */ - /* SD2: >-------<_2-L___>-------<_2-R___> */ - /* WS2: -------\_______________/--------- */ - - /* A2_OUTPUT: */ - /* SD1: <_3-L___>-------<_3-R___>-------< */ - /* WS3: _______________/---------------\_ */ - /* SD3: >-------<_4-L___>-------<_4-R___> */ - /* WS4: -------\_______________/--------- */ - -static int tsl1[8] = { - 1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 | - 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1, - - 1 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 | - 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1, - - 0 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 | - 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1, - - 0 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 | - 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1, - - 1 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 | - 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0, - - 1 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | - 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0, - - 0 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 | - 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0, - - 0 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | 0 * TSL_DIS_A1 | - 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS, -}; - -static int tsl2[8] = { - 0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2, - 0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2, - 0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2, - 0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2, - 0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2, - 0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2, - 0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2, - 0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS -}; diff --git a/ANDROID_3.4.5/sound/pci/aw2/saa7146.h b/ANDROID_3.4.5/sound/pci/aw2/saa7146.h deleted file mode 100644 index ce0ab5f9..00000000 --- a/ANDROID_3.4.5/sound/pci/aw2/saa7146.h +++ /dev/null @@ -1,168 +0,0 @@ -/***************************************************************************** - * - * Copyright (C) 2008 Cedric Bregardis and - * Jean-Christian Hassler - * - * This file is part of the Audiowerk2 ALSA driver - * - * The Audiowerk2 ALSA driver 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; version 2. - * - * The Audiowerk2 ALSA driver 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 the Audiowerk2 ALSA driver; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - *****************************************************************************/ - -/* SAA7146 registers */ -#define PCI_BT_A 0x4C -#define IICTFR 0x8C -#define IICSTA 0x90 -#define BaseA1_in 0x94 -#define ProtA1_in 0x98 -#define PageA1_in 0x9C -#define BaseA1_out 0xA0 -#define ProtA1_out 0xA4 -#define PageA1_out 0xA8 -#define BaseA2_in 0xAC -#define ProtA2_in 0xB0 -#define PageA2_in 0xB4 -#define BaseA2_out 0xB8 -#define ProtA2_out 0xBC -#define PageA2_out 0xC0 -#define IER 0xDC -#define GPIO_CTRL 0xE0 -#define ACON1 0xF4 -#define ACON2 0xF8 -#define MC1 0xFC -#define MC2 0x100 -#define ISR 0x10C -#define PSR 0x110 -#define SSR 0x114 -#define PCI_ADP1 0x12C -#define PCI_ADP2 0x130 -#define PCI_ADP3 0x134 -#define PCI_ADP4 0x138 -#define LEVEL_REP 0x140 -#define FB_BUFFER1 0x144 -#define FB_BUFFER2 0x148 -#define TSL1 0x180 -#define TSL2 0x1C0 - -#define ME (1UL << 11) -#define LIMIT (1UL << 4) -#define PV (1UL << 3) - -/* PSR/ISR/IER */ -#define PPEF (1UL << 31) -#define PABO (1UL << 30) -#define IIC_S (1UL << 17) -#define IIC_E (1UL << 16) -#define A2_in (1UL << 15) -#define A2_out (1UL << 14) -#define A1_in (1UL << 13) -#define A1_out (1UL << 12) -#define AFOU (1UL << 11) -#define PIN3 (1UL << 6) -#define PIN2 (1UL << 5) -#define PIN1 (1UL << 4) -#define PIN0 (1UL << 3) -#define ECS (1UL << 2) -#define EC3S (1UL << 1) -#define EC0S (1UL << 0) - -/* SSR */ -#define PRQ (1UL << 31) -#define PMA (1UL << 30) -#define IIC_EA (1UL << 21) -#define IIC_EW (1UL << 20) -#define IIC_ER (1UL << 19) -#define IIC_EL (1UL << 18) -#define IIC_EF (1UL << 17) -#define AF2_in (1UL << 10) -#define AF2_out (1UL << 9) -#define AF1_in (1UL << 8) -#define AF1_out (1UL << 7) -#define EC5S (1UL << 3) -#define EC4S (1UL << 2) -#define EC2S (1UL << 1) -#define EC1S (1UL << 0) - -/* PCI_BT_A */ -#define BurstA1_in (1UL << 26) -#define ThreshA1_in (1UL << 24) -#define BurstA1_out (1UL << 18) -#define ThreshA1_out (1UL << 16) -#define BurstA2_in (1UL << 10) -#define ThreshA2_in (1UL << 8) -#define BurstA2_out (1UL << 2) -#define ThreshA2_out (1UL << 0) - -/* MC1 */ -#define MRST_N (1UL << 15) -#define EAP (1UL << 9) -#define EI2C (1UL << 8) -#define TR_E_A2_OUT (1UL << 3) -#define TR_E_A2_IN (1UL << 2) -#define TR_E_A1_OUT (1UL << 1) -#define TR_E_A1_IN (1UL << 0) - -/* MC2 */ -#define UPLD_IIC (1UL << 0) - -/* ACON1 */ -#define AUDIO_MODE (1UL << 29) -#define MAXLEVEL (1UL << 22) -#define A1_SWAP (1UL << 21) -#define A2_SWAP (1UL << 20) -#define WS0_CTRL (1UL << 18) -#define WS0_SYNC (1UL << 16) -#define WS1_CTRL (1UL << 14) -#define WS1_SYNC (1UL << 12) -#define WS2_CTRL (1UL << 10) -#define WS2_SYNC (1UL << 8) -#define WS3_CTRL (1UL << 6) -#define WS3_SYNC (1UL << 4) -#define WS4_CTRL (1UL << 2) -#define WS4_SYNC (1UL << 0) - -/* ACON2 */ -#define A1_CLKSRC (1UL << 27) -#define A2_CLKSRC (1UL << 22) -#define INVERT_BCLK1 (1UL << 21) -#define INVERT_BCLK2 (1UL << 20) -#define BCLK1_OEN (1UL << 19) -#define BCLK2_OEN (1UL << 18) - -/* IICSTA */ -#define IICCC (1UL << 8) -#define ABORT (1UL << 7) -#define SPERR (1UL << 6) -#define APERR (1UL << 5) -#define DTERR (1UL << 4) -#define DRERR (1UL << 3) -#define AL (1UL << 2) -#define ERR (1UL << 1) -#define BUSY (1UL << 0) - -/* IICTFR */ -#define BYTE2 (1UL << 24) -#define BYTE1 (1UL << 16) -#define BYTE0 (1UL << 8) -#define ATRR2 (1UL << 6) -#define ATRR1 (1UL << 4) -#define ATRR0 (1UL << 2) -#define ERR (1UL << 1) -#define BUSY (1UL << 0) - -#define START 3 -#define CONT 2 -#define STOP 1 -#define NOP 0 diff --git a/ANDROID_3.4.5/sound/pci/azt3328.c b/ANDROID_3.4.5/sound/pci/azt3328.c deleted file mode 100644 index 496f14c1..00000000 --- a/ANDROID_3.4.5/sound/pci/azt3328.c +++ /dev/null @@ -1,2895 +0,0 @@ -/* azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). - * Copyright (C) 2002, 2005 - 2011 by Andreas Mohr - * - * Framework borrowed from Bart Hartgers's als4000.c. - * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), - * found in a Fujitsu-Siemens PC ("Cordant", aluminum case). - * Other versions are: - * PCI168 A(W), sub ID 1800 - * PCI168 A/AP, sub ID 8000 - * Please give me feedback in case you try my driver with one of these!! - * - * Keywords: Windows XP Vista 168nt4-125.zip 168win95-125.zip PCI 168 download - * (XP/Vista do not support this card at all but every Linux distribution - * has very good support out of the box; - * just to make sure that the right people hit this and get to know that, - * despite the high level of Internet ignorance - as usual :-P - - * about very good support for this card - on Linux!) - * - * GPL LICENSE - * 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 - * - * NOTES - * Since Aztech does not provide any chipset documentation, - * even on repeated request to various addresses, - * and the answer that was finally given was negative - * (and I was stupid enough to manage to get hold of a PCI168 soundcard - * in the first place >:-P}), - * I was forced to base this driver on reverse engineering - * (3 weeks' worth of evenings filled with driver work). - * (and no, I did NOT go the easy way: to pick up a SB PCI128 for 9 Euros) - * - * It is quite likely that the AZF3328 chip is the PCI cousin of the - * AZF3318 ("azt1020 pnp", "MM Pro 16") ISA chip, given very similar specs. - * - * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name - * for compatibility reasons) from Azfin (joint-venture of Aztech and Fincitec, - * Fincitec acquired by National Semiconductor in 2002, together with the - * Fincitec-related company ARSmikro) has the following features: - * - * - compatibility & compliance: - * - Microsoft PC 97 ("PC 97 Hardware Design Guide", - * http://www.microsoft.com/whdc/archive/pcguides.mspx) - * - Microsoft PC 98 Baseline Audio - * - MPU401 UART - * - Sound Blaster Emulation (DOS Box) - * - builtin AC97 conformant codec (SNR over 80dB) - * Note that "conformant" != "compliant"!! this chip's mixer register layout - * *differs* from the standard AC97 layout: - * they chose to not implement the headphone register (which is not a - * problem since it's merely optional), yet when doing this, they committed - * the grave sin of letting other registers follow immediately instead of - * keeping a headphone dummy register, thereby shifting the mixer register - * addresses illegally. So far unfortunately it looks like the very flexible - * ALSA AC97 support is still not enough to easily compensate for such a - * grave layout violation despite all tweaks and quirks mechanisms it offers. - * Well, not quite: now ac97 layer is much improved (bus-specific ops!), - * thus I was able to implement support - it's actually working quite well. - * An interesting item might be Aztech AMR 2800-W, since it's an AC97 - * modem card which might reveal the Aztech-specific codec ID which - * we might want to pretend, too. Dito PCI168's brother, PCI368, - * where the advertising datasheet says it's AC97-based and has a - * Digital Enhanced Game Port. - * - builtin genuine OPL3 - verified to work fine, 20080506 - * - full duplex 16bit playback/record at independent sampling rate - * - MPU401 (+ legacy address support, claimed by one official spec sheet) - * FIXME: how to enable legacy addr?? - * - game port (legacy address support) - * - builtin DirectInput support, helps reduce CPU overhead (interrupt-driven - * features supported). - See common term "Digital Enhanced Game Port"... - * (probably DirectInput 3.0 spec - confirm) - * - builtin 3D enhancement (said to be YAMAHA Ymersion) - * - built-in General DirectX timer having a 20 bits counter - * with 1us resolution (see below!) - * - I2S serial output port for external DAC - * [FIXME: 3.3V or 5V level? maximum rate is 66.2kHz right?] - * - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI - * - supports hardware volume control - * - single chip low cost solution (128 pin QFP) - * - supports programmable Sub-vendor and Sub-system ID [24C02 SEEPROM chip] - * required for Microsoft's logo compliance (FIXME: where?) - * At least the Trident 4D Wave DX has one bit somewhere - * to enable writes to PCI subsystem VID registers, that should be it. - * This might easily be in extended PCI reg space, since PCI168 also has - * some custom data starting at 0x80. What kind of config settings - * are located in our extended PCI space anyway?? - * - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms - * [TDA1517P chip] - * - * Note that this driver now is actually *better* than the Windows driver, - * since it additionally supports the card's 1MHz DirectX timer - just try - * the following snd-seq module parameters etc.: - * - options snd-seq seq_default_timer_class=2 seq_default_timer_sclass=0 - * seq_default_timer_card=0 seq_client_load=1 seq_default_timer_device=0 - * seq_default_timer_subdevice=0 seq_default_timer_resolution=1000000 - * - "timidity -iAv -B2,8 -Os -EFreverb=0" - * - "pmidi -p 128:0 jazz.mid" - * - * OPL3 hardware playback testing, try something like: - * cat /proc/asound/hwdep - * and - * aconnect -o - * Then use - * sbiload -Dhw:x,y --opl3 /usr/share/sounds/opl3/std.o3 ......./drums.o3 - * where x,y is the xx-yy number as given in hwdep. - * Then try - * pmidi -p a:b jazz.mid - * where a:b is the client number plus 0 usually, as given by aconnect above. - * Oh, and make sure to unmute the FM mixer control (doh!) - * NOTE: power use during OPL3 playback is _VERY_ high (70W --> 90W!) - * despite no CPU activity, possibly due to hindering ACPI idling somehow. - * Shouldn't be a problem of the AZF3328 chip itself, I'd hope. - * Higher PCM / FM mixer levels seem to conflict (causes crackling), - * at least sometimes. Maybe even use with hardware sequencer timer above :) - * adplay/adplug-utils might soon offer hardware-based OPL3 playback, too. - * - * Certain PCI versions of this card are susceptible to DMA traffic underruns - * in some systems (resulting in sound crackling/clicking/popping), - * probably because they don't have a DMA FIFO buffer or so. - * Overview (PCI ID/PCI subID/PCI rev.): - * - no DMA crackling on SiS735: 0x50DC/0x1801/16 - * - unknown performance: 0x50DC/0x1801/10 - * (well, it's not bad on an Athlon 1800 with now very optimized IRQ handler) - * - * Crackling happens with VIA chipsets or, in my case, an SiS735, which is - * supposed to be very fast and supposed to get rid of crackling much - * better than a VIA, yet ironically I still get crackling, like many other - * people with the same chipset. - * Possible remedies: - * - use speaker (amplifier) output instead of headphone output - * (in case crackling is due to overloaded output clipping) - * - plug card into a different PCI slot, preferably one that isn't shared - * too much (this helps a lot, but not completely!) - * - get rid of PCI VGA card, use AGP instead - * - upgrade or downgrade BIOS - * - fiddle with PCI latency settings (setpci -v -s BUSID latency_timer=XX) - * Not too helpful. - * - Disable ACPI/power management/"Auto Detect RAM/PCI Clk" in BIOS - * - * BUGS - * - full-duplex might *still* be problematic, however a recent test was fine - * - (non-bug) "Bass/Treble or 3D settings don't work" - they do get evaluated - * if you set PCM output switch to "pre 3D" instead of "post 3D". - * If this can't be set, then get a mixer application that Isn't Stupid (tm) - * (e.g. kmix, gamix) - unfortunately several are!! - * - locking is not entirely clean, especially the audio stream activity - * ints --> may be racy - * - an _unconnected_ secondary joystick at the gameport will be reported - * to be "active" (floating values, not precisely -1) due to the way we need - * to read the Digital Enhanced Game Port. Not sure whether it is fixable. - * - * TODO - * - use PCI_VDEVICE - * - verify driver status on x86_64 - * - test multi-card driver operation - * - (ab)use 1MHz DirectX timer as kernel clocksource - * - test MPU401 MIDI playback etc. - * - add more power micro-management (disable various units of the card - * as long as they're unused, to improve audio quality and save power). - * However this requires more I/O ports which I haven't figured out yet - * and which thus might not even exist... - * The standard suspend/resume functionality could probably make use of - * some improvement, too... - * - figure out what all unknown port bits are responsible for - * - figure out some cleverly evil scheme to possibly make ALSA AC97 code - * fully accept our quite incompatible ""AC97"" mixer and thus save some - * code (but I'm not too optimistic that doing this is possible at all) - * - use MMIO (memory-mapped I/O)? Slightly faster access, e.g. for gameport. - */ - -#include -#include -#include /* WARN_ONCE */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* - * Config switch, to use ALSA's AC97 layer instead of old custom mixer crap. - * If the AC97 compatibility parts we needed to implement locally turn out - * to work nicely, then remove the old implementation eventually. - */ -#define AZF_USE_AC97_LAYER 1 - -#ifdef AZF_USE_AC97_LAYER -#include -#endif -#include "azt3328.h" - -MODULE_AUTHOR("Andreas Mohr "); -MODULE_DESCRIPTION("Aztech AZF3328 (PCI168)"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_GAMEPORT 1 -#endif - -/* === Debug settings === - Further diagnostic functionality than the settings below - does not need to be provided, since one can easily write a POSIX shell script - to dump the card's I/O ports (those listed in lspci -v -v): - dump() - { - local descr=$1; local addr=$2; local count=$3 - - echo "${descr}: ${count} @ ${addr}:" - dd if=/dev/port skip=`printf %d ${addr}` count=${count} bs=1 \ - 2>/dev/null| hexdump -C - } - and then use something like - "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8", - "dump codec00 0xa800 32", "dump mixer 0xb800 64", "dump synth 0xbc00 8", - possibly within a "while true; do ... sleep 1; done" loop. - Tweaking ports could be done using - VALSTRING="`printf "%02x" $value`" - printf "\x""$VALSTRING"|dd of=/dev/port seek=`printf %d ${addr}` bs=1 \ - 2>/dev/null -*/ - -#define DEBUG_MISC 0 -#define DEBUG_CALLS 0 -#define DEBUG_MIXER 0 -#define DEBUG_CODEC 0 -#define DEBUG_TIMER 0 -#define DEBUG_GAME 0 -#define DEBUG_PM 0 -#define MIXER_TESTING 0 - -#if DEBUG_MISC -#define snd_azf3328_dbgmisc(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgmisc(format, args...) -#endif - -#if DEBUG_CALLS -#define snd_azf3328_dbgcalls(format, args...) printk(format, ##args) -#define snd_azf3328_dbgcallenter() printk(KERN_DEBUG "--> %s\n", __func__) -#define snd_azf3328_dbgcallleave() printk(KERN_DEBUG "<-- %s\n", __func__) -#else -#define snd_azf3328_dbgcalls(format, args...) -#define snd_azf3328_dbgcallenter() -#define snd_azf3328_dbgcallleave() -#endif - -#if DEBUG_MIXER -#define snd_azf3328_dbgmixer(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgmixer(format, args...) -#endif - -#if DEBUG_CODEC -#define snd_azf3328_dbgcodec(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgcodec(format, args...) -#endif - -#if DEBUG_MISC -#define snd_azf3328_dbgtimer(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgtimer(format, args...) -#endif - -#if DEBUG_GAME -#define snd_azf3328_dbggame(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbggame(format, args...) -#endif - -#if DEBUG_PM -#define snd_azf3328_dbgpm(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgpm(format, args...) -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard."); - -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard."); - -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard."); - -static int seqtimer_scaling = 128; -module_param(seqtimer_scaling, int, 0444); -MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); - -enum snd_azf3328_codec_type { - /* warning: fixed indices (also used for bitmask checks!) */ - AZF_CODEC_PLAYBACK = 0, - AZF_CODEC_CAPTURE = 1, - AZF_CODEC_I2S_OUT = 2, -}; - -struct snd_azf3328_codec_data { - unsigned long io_base; /* keep first! (avoid offset calc) */ - unsigned int dma_base; /* helper to avoid an indirection in hotpath */ - spinlock_t *lock; /* TODO: convert to our own per-codec lock member */ - struct snd_pcm_substream *substream; - bool running; - enum snd_azf3328_codec_type type; - const char *name; -}; - -struct snd_azf3328 { - /* often-used fields towards beginning, then grouped */ - - unsigned long ctrl_io; /* usually 0xb000, size 128 */ - unsigned long game_io; /* usually 0xb400, size 8 */ - unsigned long mpu_io; /* usually 0xb800, size 4 */ - unsigned long opl3_io; /* usually 0xbc00, size 8 */ - unsigned long mixer_io; /* usually 0xc000, size 64 */ - - spinlock_t reg_lock; - - struct snd_timer *timer; - - struct snd_pcm *pcm[3]; - - /* playback, recording and I2S out codecs */ - struct snd_azf3328_codec_data codecs[3]; - -#ifdef AZF_USE_AC97_LAYER - struct snd_ac97 *ac97; -#endif - - struct snd_card *card; - struct snd_rawmidi *rmidi; - -#ifdef SUPPORT_GAMEPORT - struct gameport *gameport; - u16 axes[4]; -#endif - - struct pci_dev *pci; - int irq; - - /* register 0x6a is write-only, thus need to remember setting. - * If we need to add more registers here, then we might try to fold this - * into some transparent combined shadow register handling with - * CONFIG_PM register storage below, but that's slightly difficult. */ - u16 shadow_reg_ctrl_6AH; - -#ifdef CONFIG_PM - /* register value containers for power management - * Note: not always full I/O range preserved (similar to Win driver!) */ - u32 saved_regs_ctrl[AZF_ALIGN(AZF_IO_SIZE_CTRL_PM) / 4]; - u32 saved_regs_game[AZF_ALIGN(AZF_IO_SIZE_GAME_PM) / 4]; - u32 saved_regs_mpu[AZF_ALIGN(AZF_IO_SIZE_MPU_PM) / 4]; - u32 saved_regs_opl3[AZF_ALIGN(AZF_IO_SIZE_OPL3_PM) / 4]; - u32 saved_regs_mixer[AZF_ALIGN(AZF_IO_SIZE_MIXER_PM) / 4]; -#endif -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_azf3328_ids) = { - { 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */ - { 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_azf3328_ids); - - -static int -snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set) -{ - /* Well, strictly spoken, the inb/outb sequence isn't atomic - and would need locking. However we currently don't care - since it potentially complicates matters. */ - u8 prev = inb(reg), new; - - new = (do_set) ? (prev|mask) : (prev & ~mask); - /* we need to always write the new value no matter whether it differs - * or not, since some register bits don't indicate their setting */ - outb(new, reg); - if (new != prev) - return 1; - - return 0; -} - -static inline void -snd_azf3328_codec_outb(const struct snd_azf3328_codec_data *codec, - unsigned reg, - u8 value -) -{ - outb(value, codec->io_base + reg); -} - -static inline u8 -snd_azf3328_codec_inb(const struct snd_azf3328_codec_data *codec, unsigned reg) -{ - return inb(codec->io_base + reg); -} - -static inline void -snd_azf3328_codec_outw(const struct snd_azf3328_codec_data *codec, - unsigned reg, - u16 value -) -{ - outw(value, codec->io_base + reg); -} - -static inline u16 -snd_azf3328_codec_inw(const struct snd_azf3328_codec_data *codec, unsigned reg) -{ - return inw(codec->io_base + reg); -} - -static inline void -snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec, - unsigned reg, - u32 value -) -{ - outl(value, codec->io_base + reg); -} - -static inline void -snd_azf3328_codec_outl_multi(const struct snd_azf3328_codec_data *codec, - unsigned reg, const void *buffer, int count -) -{ - unsigned long addr = codec->io_base + reg; - if (count) { - const u32 *buf = buffer; - do { - outl(*buf++, addr); - addr += 4; - } while (--count); - } -} - -static inline u32 -snd_azf3328_codec_inl(const struct snd_azf3328_codec_data *codec, unsigned reg) -{ - return inl(codec->io_base + reg); -} - -static inline void -snd_azf3328_ctrl_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value) -{ - outb(value, chip->ctrl_io + reg); -} - -static inline u8 -snd_azf3328_ctrl_inb(const struct snd_azf3328 *chip, unsigned reg) -{ - return inb(chip->ctrl_io + reg); -} - -static inline void -snd_azf3328_ctrl_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) -{ - outw(value, chip->ctrl_io + reg); -} - -static inline void -snd_azf3328_ctrl_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value) -{ - outl(value, chip->ctrl_io + reg); -} - -static inline void -snd_azf3328_game_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value) -{ - outb(value, chip->game_io + reg); -} - -static inline void -snd_azf3328_game_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) -{ - outw(value, chip->game_io + reg); -} - -static inline u8 -snd_azf3328_game_inb(const struct snd_azf3328 *chip, unsigned reg) -{ - return inb(chip->game_io + reg); -} - -static inline u16 -snd_azf3328_game_inw(const struct snd_azf3328 *chip, unsigned reg) -{ - return inw(chip->game_io + reg); -} - -static inline void -snd_azf3328_mixer_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) -{ - outw(value, chip->mixer_io + reg); -} - -static inline u16 -snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg) -{ - return inw(chip->mixer_io + reg); -} - -#define AZF_MUTE_BIT 0x80 - -static bool -snd_azf3328_mixer_mute_control(const struct snd_azf3328 *chip, - unsigned reg, bool do_mute -) -{ - unsigned long portbase = chip->mixer_io + reg + 1; - bool updated; - - /* the mute bit is on the *second* (i.e. right) register of a - * left/right channel setting */ - updated = snd_azf3328_io_reg_setb(portbase, AZF_MUTE_BIT, do_mute); - - /* indicate whether it was muted before */ - return (do_mute) ? !updated : updated; -} - -static inline bool -snd_azf3328_mixer_mute_control_master(const struct snd_azf3328 *chip, - bool do_mute -) -{ - return snd_azf3328_mixer_mute_control( - chip, - IDX_MIXER_PLAY_MASTER, - do_mute - ); -} - -static inline bool -snd_azf3328_mixer_mute_control_pcm(const struct snd_azf3328 *chip, - bool do_mute -) -{ - return snd_azf3328_mixer_mute_control( - chip, - IDX_MIXER_WAVEOUT, - do_mute - ); -} - -static inline void -snd_azf3328_mixer_reset(const struct snd_azf3328 *chip) -{ - /* reset (close) mixer: - * first mute master volume, then reset - */ - snd_azf3328_mixer_mute_control_master(chip, 1); - snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000); -} - -#ifdef AZF_USE_AC97_LAYER - -static inline void -snd_azf3328_mixer_ac97_map_unsupported(unsigned short reg, const char *mode) -{ - /* need to add some more or less clever emulation? */ - printk(KERN_WARNING - "azt3328: missing %s emulation for AC97 register 0x%02x!\n", - mode, reg); -} - -/* - * Need to have _special_ AC97 mixer hardware register index mapper, - * to compensate for the issue of a rather AC97-incompatible hardware layout. - */ -#define AZF_REG_MASK 0x3f -#define AZF_AC97_REG_UNSUPPORTED 0x8000 -#define AZF_AC97_REG_REAL_IO_READ 0x4000 -#define AZF_AC97_REG_REAL_IO_WRITE 0x2000 -#define AZF_AC97_REG_REAL_IO_RW \ - (AZF_AC97_REG_REAL_IO_READ | AZF_AC97_REG_REAL_IO_WRITE) -#define AZF_AC97_REG_EMU_IO_READ 0x0400 -#define AZF_AC97_REG_EMU_IO_WRITE 0x0200 -#define AZF_AC97_REG_EMU_IO_RW \ - (AZF_AC97_REG_EMU_IO_READ | AZF_AC97_REG_EMU_IO_WRITE) -static unsigned short -snd_azf3328_mixer_ac97_map_reg_idx(unsigned short reg) -{ - static const struct { - unsigned short azf_reg; - } azf_reg_mapper[] = { - /* Especially when taking into consideration - * mono/stereo-based sequence of azf vs. AC97 control series, - * it's quite obvious that azf simply got rid - * of the AC97_HEADPHONE control at its intended offset, - * thus shifted _all_ controls by one, - * and _then_ simply added it as an FMSYNTH control at the end, - * to make up for the offset. - * This means we'll have to translate indices here as - * needed and then do some tiny AC97 patch action - * (snd_ac97_rename_vol_ctl() etc.) - that's it. - */ - { /* AC97_RESET */ IDX_MIXER_RESET - | AZF_AC97_REG_REAL_IO_WRITE - | AZF_AC97_REG_EMU_IO_READ }, - { /* AC97_MASTER */ IDX_MIXER_PLAY_MASTER }, - /* note large shift: AC97_HEADPHONE to IDX_MIXER_FMSYNTH! */ - { /* AC97_HEADPHONE */ IDX_MIXER_FMSYNTH }, - { /* AC97_MASTER_MONO */ IDX_MIXER_MODEMOUT }, - { /* AC97_MASTER_TONE */ IDX_MIXER_BASSTREBLE }, - { /* AC97_PC_BEEP */ IDX_MIXER_PCBEEP }, - { /* AC97_PHONE */ IDX_MIXER_MODEMIN }, - { /* AC97_MIC */ IDX_MIXER_MIC }, - { /* AC97_LINE */ IDX_MIXER_LINEIN }, - { /* AC97_CD */ IDX_MIXER_CDAUDIO }, - { /* AC97_VIDEO */ IDX_MIXER_VIDEO }, - { /* AC97_AUX */ IDX_MIXER_AUX }, - { /* AC97_PCM */ IDX_MIXER_WAVEOUT }, - { /* AC97_REC_SEL */ IDX_MIXER_REC_SELECT }, - { /* AC97_REC_GAIN */ IDX_MIXER_REC_VOLUME }, - { /* AC97_REC_GAIN_MIC */ AZF_AC97_REG_EMU_IO_RW }, - { /* AC97_GENERAL_PURPOSE */ IDX_MIXER_ADVCTL2 }, - { /* AC97_3D_CONTROL */ IDX_MIXER_ADVCTL1 }, - }; - - unsigned short reg_azf = AZF_AC97_REG_UNSUPPORTED; - - /* azf3328 supports the low-numbered and low-spec:ed range - of AC97 regs only */ - if (reg <= AC97_3D_CONTROL) { - unsigned short reg_idx = reg / 2; - reg_azf = azf_reg_mapper[reg_idx].azf_reg; - /* a translation-only entry means it's real read/write: */ - if (!(reg_azf & ~AZF_REG_MASK)) - reg_azf |= AZF_AC97_REG_REAL_IO_RW; - } else { - switch (reg) { - case AC97_POWERDOWN: - reg_azf = AZF_AC97_REG_EMU_IO_RW; - break; - case AC97_EXTENDED_ID: - reg_azf = AZF_AC97_REG_EMU_IO_READ; - break; - case AC97_EXTENDED_STATUS: - /* I don't know what the h*ll AC97 layer - * would consult this _extended_ register for - * given a base-AC97-advertised card, - * but let's just emulate it anyway :-P - */ - reg_azf = AZF_AC97_REG_EMU_IO_RW; - break; - case AC97_VENDOR_ID1: - case AC97_VENDOR_ID2: - reg_azf = AZF_AC97_REG_EMU_IO_READ; - break; - } - } - return reg_azf; -} - -static const unsigned short -azf_emulated_ac97_caps = - AC97_BC_DEDICATED_MIC | - AC97_BC_BASS_TREBLE | - /* Headphone is an FM Synth control here */ - AC97_BC_HEADPHONE | - /* no AC97_BC_LOUDNESS! */ - /* mask 0x7c00 is - vendor-specific 3D enhancement - vendor indicator. - Since there actually _is_ an - entry for Aztech Labs - (13), make damn sure - to indicate it. */ - (13 << 10); - -static const unsigned short -azf_emulated_ac97_powerdown = - /* pretend everything to be active */ - AC97_PD_ADC_STATUS | - AC97_PD_DAC_STATUS | - AC97_PD_MIXER_STATUS | - AC97_PD_VREF_STATUS; - -/* - * Emulated, _inofficial_ vendor ID - * (there might be some devices such as the MR 2800-W - * which could reveal the real Aztech AC97 ID). - * We choose to use "AZT" prefix, and then use 1 to indicate PCI168 - * (better don't use 0x68 since there's a PCI368 as well). - */ -static const unsigned int -azf_emulated_ac97_vendor_id = 0x415a5401; - -static unsigned short -snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97) -{ - const struct snd_azf3328 *chip = ac97->private_data; - unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97); - unsigned short reg_val = 0; - bool unsupported = 0; - - snd_azf3328_dbgmixer( - "snd_azf3328_mixer_ac97_read reg_ac97 %u\n", - reg_ac97 - ); - if (reg_azf & AZF_AC97_REG_UNSUPPORTED) - unsupported = 1; - else { - if (reg_azf & AZF_AC97_REG_REAL_IO_READ) - reg_val = snd_azf3328_mixer_inw(chip, - reg_azf & AZF_REG_MASK); - else { - /* - * Proceed with dummy I/O read, - * to ensure compatible timing where this may matter. - * (ALSA AC97 layer usually doesn't call I/O functions - * due to intelligent I/O caching anyway) - * Choose a mixer register that's thoroughly unrelated - * to common audio (try to minimize distortion). - */ - snd_azf3328_mixer_inw(chip, IDX_MIXER_SOMETHING30H); - } - - if (reg_azf & AZF_AC97_REG_EMU_IO_READ) { - switch (reg_ac97) { - case AC97_RESET: - reg_val |= azf_emulated_ac97_caps; - break; - case AC97_POWERDOWN: - reg_val |= azf_emulated_ac97_powerdown; - break; - case AC97_EXTENDED_ID: - case AC97_EXTENDED_STATUS: - /* AFAICS we simply can't support anything: */ - reg_val |= 0; - break; - case AC97_VENDOR_ID1: - reg_val = azf_emulated_ac97_vendor_id >> 16; - break; - case AC97_VENDOR_ID2: - reg_val = azf_emulated_ac97_vendor_id & 0xffff; - break; - default: - unsupported = 1; - break; - } - } - } - if (unsupported) - snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "read"); - - return reg_val; -} - -static void -snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97, - unsigned short reg_ac97, unsigned short val) -{ - const struct snd_azf3328 *chip = ac97->private_data; - unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97); - bool unsupported = 0; - - snd_azf3328_dbgmixer( - "snd_azf3328_mixer_ac97_write reg_ac97 %u val %u\n", - reg_ac97, val - ); - if (reg_azf & AZF_AC97_REG_UNSUPPORTED) - unsupported = 1; - else { - if (reg_azf & AZF_AC97_REG_REAL_IO_WRITE) - snd_azf3328_mixer_outw( - chip, - reg_azf & AZF_REG_MASK, - val - ); - else - if (reg_azf & AZF_AC97_REG_EMU_IO_WRITE) { - switch (reg_ac97) { - case AC97_REC_GAIN_MIC: - case AC97_POWERDOWN: - case AC97_EXTENDED_STATUS: - /* - * Silently swallow these writes. - * Since for most registers our card doesn't - * actually support a comparable feature, - * this is exactly what we should do here. - * The AC97 layer's I/O caching probably - * automatically takes care of all the rest... - * (remembers written values etc.) - */ - break; - default: - unsupported = 1; - break; - } - } - } - if (unsupported) - snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "write"); -} - -static int __devinit -snd_azf3328_mixer_new(struct snd_azf3328 *chip) -{ - struct snd_ac97_bus *bus; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = snd_azf3328_mixer_ac97_write, - .read = snd_azf3328_mixer_ac97_read, - }; - int rc; - - memset(&ac97, 0, sizeof(ac97)); - ac97.scaps = AC97_SCAP_SKIP_MODEM - | AC97_SCAP_AUDIO /* we support audio! */ - | AC97_SCAP_NO_SPDIF; - ac97.private_data = chip; - ac97.pci = chip->pci; - - /* - * ALSA's AC97 layer has terrible init crackling issues, - * unfortunately, and since it makes use of AC97_RESET, - * there's no use trying to mute Master Playback proactively. - */ - - rc = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus); - if (!rc) - rc = snd_ac97_mixer(bus, &ac97, &chip->ac97); - /* - * Make sure to complain loudly in case of AC97 init failure, - * since failure may happen quite often, - * due to this card being a very quirky AC97 "lookalike". - */ - if (rc) - printk(KERN_ERR "azt3328: AC97 init failed, err %d!\n", rc); - - /* If we return an error here, then snd_card_free() should - * free up any ac97 codecs that got created, as well as the bus. - */ - return rc; -} -#else /* AZF_USE_AC97_LAYER */ -static void -snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, - unsigned reg, - unsigned char dst_vol_left, - unsigned char dst_vol_right, - int chan_sel, int delay -) -{ - unsigned long portbase = chip->mixer_io + reg; - unsigned char curr_vol_left = 0, curr_vol_right = 0; - int left_change = 0, right_change = 0; - - snd_azf3328_dbgcallenter(); - - if (chan_sel & SET_CHAN_LEFT) { - curr_vol_left = inb(portbase + 1); - - /* take care of muting flag contained in left channel */ - if (curr_vol_left & AZF_MUTE_BIT) - dst_vol_left |= AZF_MUTE_BIT; - else - dst_vol_left &= ~AZF_MUTE_BIT; - - left_change = (curr_vol_left > dst_vol_left) ? -1 : 1; - } - - if (chan_sel & SET_CHAN_RIGHT) { - curr_vol_right = inb(portbase + 0); - - right_change = (curr_vol_right > dst_vol_right) ? -1 : 1; - } - - do { - if (left_change) { - if (curr_vol_left != dst_vol_left) { - curr_vol_left += left_change; - outb(curr_vol_left, portbase + 1); - } else - left_change = 0; - } - if (right_change) { - if (curr_vol_right != dst_vol_right) { - curr_vol_right += right_change; - - /* during volume change, the right channel is crackling - * somewhat more than the left channel, unfortunately. - * This seems to be a hardware issue. */ - outb(curr_vol_right, portbase + 0); - } else - right_change = 0; - } - if (delay) - mdelay(delay); - } while ((left_change) || (right_change)); - snd_azf3328_dbgcallleave(); -} - -/* - * general mixer element - */ -struct azf3328_mixer_reg { - unsigned reg; - unsigned int lchan_shift, rchan_shift; - unsigned int mask; - unsigned int invert: 1; - unsigned int stereo: 1; - unsigned int enum_c: 4; -}; - -#define COMPOSE_MIXER_REG(reg,lchan_shift,rchan_shift,mask,invert,stereo,enum_c) \ - ((reg) | (lchan_shift << 8) | (rchan_shift << 12) | \ - (mask << 16) | \ - (invert << 24) | \ - (stereo << 25) | \ - (enum_c << 26)) - -static void snd_azf3328_mixer_reg_decode(struct azf3328_mixer_reg *r, unsigned long val) -{ - r->reg = val & 0xff; - r->lchan_shift = (val >> 8) & 0x0f; - r->rchan_shift = (val >> 12) & 0x0f; - r->mask = (val >> 16) & 0xff; - r->invert = (val >> 24) & 1; - r->stereo = (val >> 25) & 1; - r->enum_c = (val >> 26) & 0x0f; -} - -/* - * mixer switches/volumes - */ - -#define AZF3328_MIXER_SWITCH(xname, reg, shift, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_azf3328_info_mixer, \ - .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \ - .private_value = COMPOSE_MIXER_REG(reg, shift, 0, 0x1, invert, 0, 0), \ -} - -#define AZF3328_MIXER_VOL_STEREO(xname, reg, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_azf3328_info_mixer, \ - .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \ - .private_value = COMPOSE_MIXER_REG(reg, 8, 0, mask, invert, 1, 0), \ -} - -#define AZF3328_MIXER_VOL_MONO(xname, reg, mask, is_right_chan) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_azf3328_info_mixer, \ - .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \ - .private_value = COMPOSE_MIXER_REG(reg, is_right_chan ? 0 : 8, 0, mask, 1, 0, 0), \ -} - -#define AZF3328_MIXER_VOL_SPECIAL(xname, reg, mask, shift, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_azf3328_info_mixer, \ - .get = snd_azf3328_get_mixer, .put = snd_azf3328_put_mixer, \ - .private_value = COMPOSE_MIXER_REG(reg, shift, 0, mask, invert, 0, 0), \ -} - -#define AZF3328_MIXER_ENUM(xname, reg, enum_c, shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_azf3328_info_mixer_enum, \ - .get = snd_azf3328_get_mixer_enum, .put = snd_azf3328_put_mixer_enum, \ - .private_value = COMPOSE_MIXER_REG(reg, shift, 0, 0, 0, 0, enum_c), \ -} - -static int -snd_azf3328_info_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct azf3328_mixer_reg reg; - - snd_azf3328_dbgcallenter(); - snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - uinfo->type = reg.mask == 1 ? - SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = reg.stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = reg.mask; - snd_azf3328_dbgcallleave(); - return 0; -} - -static int -snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); - struct azf3328_mixer_reg reg; - u16 oreg, val; - - snd_azf3328_dbgcallenter(); - snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - - oreg = snd_azf3328_mixer_inw(chip, reg.reg); - val = (oreg >> reg.lchan_shift) & reg.mask; - if (reg.invert) - val = reg.mask - val; - ucontrol->value.integer.value[0] = val; - if (reg.stereo) { - val = (oreg >> reg.rchan_shift) & reg.mask; - if (reg.invert) - val = reg.mask - val; - ucontrol->value.integer.value[1] = val; - } - snd_azf3328_dbgmixer("get: %02x is %04x -> vol %02lx|%02lx " - "(shift %02d|%02d, mask %02x, inv. %d, stereo %d)\n", - reg.reg, oreg, - ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], - reg.lchan_shift, reg.rchan_shift, reg.mask, reg.invert, reg.stereo); - snd_azf3328_dbgcallleave(); - return 0; -} - -static int -snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); - struct azf3328_mixer_reg reg; - u16 oreg, nreg, val; - - snd_azf3328_dbgcallenter(); - snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - oreg = snd_azf3328_mixer_inw(chip, reg.reg); - val = ucontrol->value.integer.value[0] & reg.mask; - if (reg.invert) - val = reg.mask - val; - nreg = oreg & ~(reg.mask << reg.lchan_shift); - nreg |= (val << reg.lchan_shift); - if (reg.stereo) { - val = ucontrol->value.integer.value[1] & reg.mask; - if (reg.invert) - val = reg.mask - val; - nreg &= ~(reg.mask << reg.rchan_shift); - nreg |= (val << reg.rchan_shift); - } - if (reg.mask >= 0x07) /* it's a volume control, so better take care */ - snd_azf3328_mixer_write_volume_gradually( - chip, reg.reg, nreg >> 8, nreg & 0xff, - /* just set both channels, doesn't matter */ - SET_CHAN_LEFT|SET_CHAN_RIGHT, - 0); - else - snd_azf3328_mixer_outw(chip, reg.reg, nreg); - - snd_azf3328_dbgmixer("put: %02x to %02lx|%02lx, " - "oreg %04x; shift %02d|%02d -> nreg %04x; after: %04x\n", - reg.reg, ucontrol->value.integer.value[0], ucontrol->value.integer.value[1], - oreg, reg.lchan_shift, reg.rchan_shift, - nreg, snd_azf3328_mixer_inw(chip, reg.reg)); - snd_azf3328_dbgcallleave(); - return (nreg != oreg); -} - -static int -snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts1[] = { - "Mic1", "Mic2" - }; - static const char * const texts2[] = { - "Mix", "Mic" - }; - static const char * const texts3[] = { - "Mic", "CD", "Video", "Aux", - "Line", "Mix", "Mix Mono", "Phone" - }; - static const char * const texts4[] = { - "pre 3D", "post 3D" - }; - struct azf3328_mixer_reg reg; - const char * const *p = NULL; - - snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = (reg.reg == IDX_MIXER_REC_SELECT) ? 2 : 1; - uinfo->value.enumerated.items = reg.enum_c; - if (uinfo->value.enumerated.item > reg.enum_c - 1U) - uinfo->value.enumerated.item = reg.enum_c - 1U; - if (reg.reg == IDX_MIXER_ADVCTL2) { - switch(reg.lchan_shift) { - case 8: /* modem out sel */ - p = texts1; - break; - case 9: /* mono sel source */ - p = texts2; - break; - case 15: /* PCM Out Path */ - p = texts4; - break; - } - } else - if (reg.reg == IDX_MIXER_REC_SELECT) - p = texts3; - - strcpy(uinfo->value.enumerated.name, p[uinfo->value.enumerated.item]); - return 0; -} - -static int -snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); - struct azf3328_mixer_reg reg; - unsigned short val; - - snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - val = snd_azf3328_mixer_inw(chip, reg.reg); - if (reg.reg == IDX_MIXER_REC_SELECT) { - ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); - ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1); - } else - ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); - - snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", - reg.reg, val, ucontrol->value.enumerated.item[0], ucontrol->value.enumerated.item[1], - reg.lchan_shift, reg.enum_c); - return 0; -} - -static int -snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); - struct azf3328_mixer_reg reg; - u16 oreg, nreg, val; - - snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); - oreg = snd_azf3328_mixer_inw(chip, reg.reg); - val = oreg; - if (reg.reg == IDX_MIXER_REC_SELECT) { - if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U || - ucontrol->value.enumerated.item[1] > reg.enum_c - 1U) - return -EINVAL; - val = (ucontrol->value.enumerated.item[0] << 8) | - (ucontrol->value.enumerated.item[1] << 0); - } else { - if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U) - return -EINVAL; - val &= ~((reg.enum_c - 1) << reg.lchan_shift); - val |= (ucontrol->value.enumerated.item[0] << reg.lchan_shift); - } - snd_azf3328_mixer_outw(chip, reg.reg, val); - nreg = val; - - snd_azf3328_dbgmixer("put_enum: %02x to %04x, oreg %04x\n", reg.reg, val, oreg); - return (nreg != oreg); -} - -static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = { - AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1), - AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1), - AZF3328_MIXER_SWITCH("PCM Playback Switch", IDX_MIXER_WAVEOUT, 15, 1), - AZF3328_MIXER_VOL_STEREO("PCM Playback Volume", - IDX_MIXER_WAVEOUT, 0x1f, 1), - AZF3328_MIXER_SWITCH("PCM 3D Bypass Playback Switch", - IDX_MIXER_ADVCTL2, 7, 1), - AZF3328_MIXER_SWITCH("FM Playback Switch", IDX_MIXER_FMSYNTH, 15, 1), - AZF3328_MIXER_VOL_STEREO("FM Playback Volume", IDX_MIXER_FMSYNTH, 0x1f, 1), - AZF3328_MIXER_SWITCH("CD Playback Switch", IDX_MIXER_CDAUDIO, 15, 1), - AZF3328_MIXER_VOL_STEREO("CD Playback Volume", IDX_MIXER_CDAUDIO, 0x1f, 1), - AZF3328_MIXER_SWITCH("Capture Switch", IDX_MIXER_REC_VOLUME, 15, 1), - AZF3328_MIXER_VOL_STEREO("Capture Volume", IDX_MIXER_REC_VOLUME, 0x0f, 0), - AZF3328_MIXER_ENUM("Capture Source", IDX_MIXER_REC_SELECT, 8, 0), - AZF3328_MIXER_SWITCH("Mic Playback Switch", IDX_MIXER_MIC, 15, 1), - AZF3328_MIXER_VOL_MONO("Mic Playback Volume", IDX_MIXER_MIC, 0x1f, 1), - AZF3328_MIXER_SWITCH("Mic Boost (+20dB)", IDX_MIXER_MIC, 6, 0), - AZF3328_MIXER_SWITCH("Line Playback Switch", IDX_MIXER_LINEIN, 15, 1), - AZF3328_MIXER_VOL_STEREO("Line Playback Volume", IDX_MIXER_LINEIN, 0x1f, 1), - AZF3328_MIXER_SWITCH("Beep Playback Switch", IDX_MIXER_PCBEEP, 15, 1), - AZF3328_MIXER_VOL_SPECIAL("Beep Playback Volume", IDX_MIXER_PCBEEP, 0x0f, 1, 1), - AZF3328_MIXER_SWITCH("Video Playback Switch", IDX_MIXER_VIDEO, 15, 1), - AZF3328_MIXER_VOL_STEREO("Video Playback Volume", IDX_MIXER_VIDEO, 0x1f, 1), - AZF3328_MIXER_SWITCH("Aux Playback Switch", IDX_MIXER_AUX, 15, 1), - AZF3328_MIXER_VOL_STEREO("Aux Playback Volume", IDX_MIXER_AUX, 0x1f, 1), - AZF3328_MIXER_SWITCH("Modem Playback Switch", IDX_MIXER_MODEMOUT, 15, 1), - AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1), - AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1), - AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1), - AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8), - AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9), - AZF3328_MIXER_ENUM("PCM Output Route", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */ - AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0), - AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0), - AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0), - AZF3328_MIXER_VOL_SPECIAL("3D Control - Width", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ - AZF3328_MIXER_VOL_SPECIAL("3D Control - Depth", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */ -#if MIXER_TESTING - AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0), - AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0), - AZF3328_MIXER_SWITCH("2", IDX_MIXER_ADVCTL2, 2, 0), - AZF3328_MIXER_SWITCH("3", IDX_MIXER_ADVCTL2, 3, 0), - AZF3328_MIXER_SWITCH("4", IDX_MIXER_ADVCTL2, 4, 0), - AZF3328_MIXER_SWITCH("5", IDX_MIXER_ADVCTL2, 5, 0), - AZF3328_MIXER_SWITCH("6", IDX_MIXER_ADVCTL2, 6, 0), - AZF3328_MIXER_SWITCH("7", IDX_MIXER_ADVCTL2, 7, 0), - AZF3328_MIXER_SWITCH("8", IDX_MIXER_ADVCTL2, 8, 0), - AZF3328_MIXER_SWITCH("9", IDX_MIXER_ADVCTL2, 9, 0), - AZF3328_MIXER_SWITCH("10", IDX_MIXER_ADVCTL2, 10, 0), - AZF3328_MIXER_SWITCH("11", IDX_MIXER_ADVCTL2, 11, 0), - AZF3328_MIXER_SWITCH("12", IDX_MIXER_ADVCTL2, 12, 0), - AZF3328_MIXER_SWITCH("13", IDX_MIXER_ADVCTL2, 13, 0), - AZF3328_MIXER_SWITCH("14", IDX_MIXER_ADVCTL2, 14, 0), - AZF3328_MIXER_SWITCH("15", IDX_MIXER_ADVCTL2, 15, 0), -#endif -}; - -static u16 __devinitdata snd_azf3328_init_values[][2] = { - { IDX_MIXER_PLAY_MASTER, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_MODEMOUT, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_BASSTREBLE, 0x0000 }, - { IDX_MIXER_PCBEEP, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_MODEMIN, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_MIC, MIXER_MUTE_MASK|0x001f }, - { IDX_MIXER_LINEIN, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_CDAUDIO, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_VIDEO, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_AUX, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_WAVEOUT, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_FMSYNTH, MIXER_MUTE_MASK|0x1f1f }, - { IDX_MIXER_REC_VOLUME, MIXER_MUTE_MASK|0x0707 }, -}; - -static int __devinit -snd_azf3328_mixer_new(struct snd_azf3328 *chip) -{ - struct snd_card *card; - const struct snd_kcontrol_new *sw; - unsigned int idx; - int err; - - snd_azf3328_dbgcallenter(); - if (snd_BUG_ON(!chip || !chip->card)) - return -EINVAL; - - card = chip->card; - - /* mixer reset */ - snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000); - - /* mute and zero volume channels */ - for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_init_values); ++idx) { - snd_azf3328_mixer_outw(chip, - snd_azf3328_init_values[idx][0], - snd_azf3328_init_values[idx][1]); - } - - /* add mixer controls */ - sw = snd_azf3328_mixer_controls; - for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls); - ++idx, ++sw) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip))) < 0) - return err; - } - snd_component_add(card, "AZF3328 mixer"); - strcpy(card->mixername, "AZF3328 mixer"); - - snd_azf3328_dbgcallleave(); - return 0; -} -#endif /* AZF_USE_AC97_LAYER */ - -static int -snd_azf3328_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int res; - snd_azf3328_dbgcallenter(); - res = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - snd_azf3328_dbgcallleave(); - return res; -} - -static int -snd_azf3328_hw_free(struct snd_pcm_substream *substream) -{ - snd_azf3328_dbgcallenter(); - snd_pcm_lib_free_pages(substream); - snd_azf3328_dbgcallleave(); - return 0; -} - -static void -snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, - enum azf_freq_t bitrate, - unsigned int format_width, - unsigned int channels -) -{ - unsigned long flags; - u16 val = 0xff00; - u8 freq = 0; - - snd_azf3328_dbgcallenter(); - switch (bitrate) { - case AZF_FREQ_4000: freq = SOUNDFORMAT_FREQ_SUSPECTED_4000; break; - case AZF_FREQ_4800: freq = SOUNDFORMAT_FREQ_SUSPECTED_4800; break; - case AZF_FREQ_5512: - /* the AZF3328 names it "5510" for some strange reason */ - freq = SOUNDFORMAT_FREQ_5510; break; - case AZF_FREQ_6620: freq = SOUNDFORMAT_FREQ_6620; break; - case AZF_FREQ_8000: freq = SOUNDFORMAT_FREQ_8000; break; - case AZF_FREQ_9600: freq = SOUNDFORMAT_FREQ_9600; break; - case AZF_FREQ_11025: freq = SOUNDFORMAT_FREQ_11025; break; - case AZF_FREQ_13240: freq = SOUNDFORMAT_FREQ_SUSPECTED_13240; break; - case AZF_FREQ_16000: freq = SOUNDFORMAT_FREQ_16000; break; - case AZF_FREQ_22050: freq = SOUNDFORMAT_FREQ_22050; break; - case AZF_FREQ_32000: freq = SOUNDFORMAT_FREQ_32000; break; - default: - snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); - /* fall-through */ - case AZF_FREQ_44100: freq = SOUNDFORMAT_FREQ_44100; break; - case AZF_FREQ_48000: freq = SOUNDFORMAT_FREQ_48000; break; - case AZF_FREQ_66200: freq = SOUNDFORMAT_FREQ_SUSPECTED_66200; break; - } - /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */ - /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */ - /* val = 0xff0a; 47m30.599s (4764,891Hz; -> 4800Hz???) yup, 4803Hz */ - /* val = 0xff0c; 57m0.510s (4010,263Hz; -> 4000Hz???) yup, 4003Hz */ - /* val = 0xff05; 5m11.556s (... -> 44100Hz) */ - /* val = 0xff03; 10m21.529s (21872,463Hz; -> 22050Hz???) */ - /* val = 0xff0f; 20m41.883s (10937,993Hz; -> 11025Hz???) */ - /* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */ - /* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */ - - val |= freq; - - if (channels == 2) - val |= SOUNDFORMAT_FLAG_2CHANNELS; - - if (format_width == 16) - val |= SOUNDFORMAT_FLAG_16BIT; - - spin_lock_irqsave(codec->lock, flags); - - /* set bitrate/format */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val); - - /* changing the bitrate/format settings switches off the - * audio output with an annoying click in case of 8/16bit format change - * (maybe shutting down DAC/ADC?), thus immediately - * do some tweaking to reenable it and get rid of the clicking - * (FIXME: yes, it works, but what exactly am I doing here?? :) - * FIXME: does this have some side effects for full-duplex - * or other dramatic side effects? */ - /* do it for non-capture codecs only */ - if (codec->type != AZF_CODEC_CAPTURE) - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) | - DMA_RUN_SOMETHING1 | - DMA_RUN_SOMETHING2 | - SOMETHING_ALMOST_ALWAYS_SET | - DMA_EPILOGUE_SOMETHING | - DMA_SOMETHING_ELSE - ); - - spin_unlock_irqrestore(codec->lock, flags); - snd_azf3328_dbgcallleave(); -} - -static inline void -snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328_codec_data *codec -) -{ - /* choose lowest frequency for low power consumption. - * While this will cause louder noise due to rather coarse frequency, - * it should never matter since output should always - * get disabled properly when idle anyway. */ - snd_azf3328_codec_setfmt(codec, AZF_FREQ_4000, 8, 1); -} - -static void -snd_azf3328_ctrl_reg_6AH_update(struct snd_azf3328 *chip, - unsigned bitmask, - bool enable -) -{ - bool do_mask = !enable; - if (do_mask) - chip->shadow_reg_ctrl_6AH |= bitmask; - else - chip->shadow_reg_ctrl_6AH &= ~bitmask; - snd_azf3328_dbgcodec("6AH_update mask 0x%04x do_mask %d: val 0x%04x\n", - bitmask, do_mask, chip->shadow_reg_ctrl_6AH); - snd_azf3328_ctrl_outw(chip, IDX_IO_6AH, chip->shadow_reg_ctrl_6AH); -} - -static inline void -snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable) -{ - snd_azf3328_dbgcodec("codec_enable %d\n", enable); - /* no idea what exactly is being done here, but I strongly assume it's - * PM related */ - snd_azf3328_ctrl_reg_6AH_update( - chip, IO_6A_PAUSE_PLAYBACK_BIT8, enable - ); -} - -static void -snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip, - enum snd_azf3328_codec_type codec_type, - bool enable -) -{ - struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; - bool need_change = (codec->running != enable); - - snd_azf3328_dbgcodec( - "codec_activity: %s codec, enable %d, need_change %d\n", - codec->name, enable, need_change - ); - if (need_change) { - static const struct { - enum snd_azf3328_codec_type other1; - enum snd_azf3328_codec_type other2; - } peer_codecs[3] = - { { AZF_CODEC_CAPTURE, AZF_CODEC_I2S_OUT }, - { AZF_CODEC_PLAYBACK, AZF_CODEC_I2S_OUT }, - { AZF_CODEC_PLAYBACK, AZF_CODEC_CAPTURE } }; - bool call_function; - - if (enable) - /* if enable codec, call enable_codecs func - to enable codec supply... */ - call_function = 1; - else { - /* ...otherwise call enable_codecs func - (which globally shuts down operation of codecs) - only in case the other codecs are currently - not active either! */ - call_function = - ((!chip->codecs[peer_codecs[codec_type].other1] - .running) - && (!chip->codecs[peer_codecs[codec_type].other2] - .running)); - } - if (call_function) - snd_azf3328_ctrl_enable_codecs(chip, enable); - - /* ...and adjust clock, too - * (reduce noise and power consumption) */ - if (!enable) - snd_azf3328_codec_setfmt_lowpower(codec); - codec->running = enable; - } -} - -static void -snd_azf3328_codec_setdmaa(struct snd_azf3328_codec_data *codec, - unsigned long addr, - unsigned int period_bytes, - unsigned int buffer_bytes -) -{ - snd_azf3328_dbgcallenter(); - WARN_ONCE(period_bytes & 1, "odd period length!?\n"); - WARN_ONCE(buffer_bytes != 2 * period_bytes, - "missed our input expectations! %u vs. %u\n", - buffer_bytes, period_bytes); - if (!codec->running) { - /* AZF3328 uses a two buffer pointer DMA transfer approach */ - - unsigned long flags; - - /* width 32bit (prevent overflow): */ - u32 area_length; - struct codec_setup_io { - u32 dma_start_1; - u32 dma_start_2; - u32 dma_lengths; - } __attribute__((packed)) setup_io; - - area_length = buffer_bytes/2; - - setup_io.dma_start_1 = addr; - setup_io.dma_start_2 = addr+area_length; - - snd_azf3328_dbgcodec( - "setdma: buffers %08x[%u] / %08x[%u], %u, %u\n", - setup_io.dma_start_1, area_length, - setup_io.dma_start_2, area_length, - period_bytes, buffer_bytes); - - /* Hmm, are we really supposed to decrement this by 1?? - Most definitely certainly not: configuring full length does - work properly (i.e. likely better), and BTW we - violated possibly differing frame sizes with this... - - area_length--; |* max. index *| - */ - - /* build combined I/O buffer length word */ - setup_io.dma_lengths = (area_length << 16) | (area_length); - - spin_lock_irqsave(codec->lock, flags); - snd_azf3328_codec_outl_multi( - codec, IDX_IO_CODEC_DMA_START_1, &setup_io, 3 - ); - spin_unlock_irqrestore(codec->lock, flags); - } - snd_azf3328_dbgcallleave(); -} - -static int -snd_azf3328_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_azf3328_codec_data *codec = runtime->private_data; -#if 0 - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); -#endif - - snd_azf3328_dbgcallenter(); - - codec->dma_base = runtime->dma_addr; - -#if 0 - snd_azf3328_codec_setfmt(codec, - runtime->rate, - snd_pcm_format_width(runtime->format), - runtime->channels); - snd_azf3328_codec_setdmaa(codec, - runtime->dma_addr, count, size); -#endif - snd_azf3328_dbgcallleave(); - return 0; -} - -static int -snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_azf3328_codec_data *codec = runtime->private_data; - int result = 0; - u16 flags1; - bool previously_muted = 0; - bool is_main_mixer_playback_codec = (AZF_CODEC_PLAYBACK == codec->type); - - snd_azf3328_dbgcalls("snd_azf3328_pcm_trigger cmd %d\n", cmd); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_azf3328_dbgcodec("START %s\n", codec->name); - - if (is_main_mixer_playback_codec) { - /* mute WaveOut (avoid clicking during setup) */ - previously_muted = - snd_azf3328_mixer_mute_control_pcm( - chip, 1 - ); - } - - snd_azf3328_codec_setfmt(codec, - runtime->rate, - snd_pcm_format_width(runtime->format), - runtime->channels); - - spin_lock(codec->lock); - /* first, remember current value: */ - flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); - - /* stop transfer */ - flags1 &= ~DMA_RESUME; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - - /* FIXME: clear interrupts or what??? */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); - spin_unlock(codec->lock); - - snd_azf3328_codec_setdmaa(codec, runtime->dma_addr, - snd_pcm_lib_period_bytes(substream), - snd_pcm_lib_buffer_bytes(substream) - ); - - spin_lock(codec->lock); -#ifdef WIN9X - /* FIXME: enable playback/recording??? */ - flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - - /* start transfer again */ - /* FIXME: what is this value (0x0010)??? */ - flags1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); -#else /* NT4 */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - 0x0000); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - DMA_RUN_SOMETHING1); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - DMA_RUN_SOMETHING1 | - DMA_RUN_SOMETHING2); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - DMA_RESUME | - SOMETHING_ALMOST_ALWAYS_SET | - DMA_EPILOGUE_SOMETHING | - DMA_SOMETHING_ELSE); -#endif - spin_unlock(codec->lock); - snd_azf3328_ctrl_codec_activity(chip, codec->type, 1); - - if (is_main_mixer_playback_codec) { - /* now unmute WaveOut */ - if (!previously_muted) - snd_azf3328_mixer_mute_control_pcm( - chip, 0 - ); - } - - snd_azf3328_dbgcodec("STARTED %s\n", codec->name); - break; - case SNDRV_PCM_TRIGGER_RESUME: - snd_azf3328_dbgcodec("RESUME %s\n", codec->name); - /* resume codec if we were active */ - spin_lock(codec->lock); - if (codec->running) - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - snd_azf3328_codec_inw( - codec, IDX_IO_CODEC_DMA_FLAGS - ) | DMA_RESUME - ); - spin_unlock(codec->lock); - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_azf3328_dbgcodec("STOP %s\n", codec->name); - - if (is_main_mixer_playback_codec) { - /* mute WaveOut (avoid clicking during setup) */ - previously_muted = - snd_azf3328_mixer_mute_control_pcm( - chip, 1 - ); - } - - spin_lock(codec->lock); - /* first, remember current value: */ - flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); - - /* stop transfer */ - flags1 &= ~DMA_RESUME; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - - /* hmm, is this really required? we're resetting the same bit - * immediately thereafter... */ - flags1 |= DMA_RUN_SOMETHING1; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - - flags1 &= ~DMA_RUN_SOMETHING1; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); - spin_unlock(codec->lock); - snd_azf3328_ctrl_codec_activity(chip, codec->type, 0); - - if (is_main_mixer_playback_codec) { - /* now unmute WaveOut */ - if (!previously_muted) - snd_azf3328_mixer_mute_control_pcm( - chip, 0 - ); - } - - snd_azf3328_dbgcodec("STOPPED %s\n", codec->name); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_azf3328_dbgcodec("SUSPEND %s\n", codec->name); - /* make sure codec is stopped */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - snd_azf3328_codec_inw( - codec, IDX_IO_CODEC_DMA_FLAGS - ) & ~DMA_RESUME - ); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); - break; - default: - snd_printk(KERN_ERR "FIXME: unknown trigger mode!\n"); - return -EINVAL; - } - - snd_azf3328_dbgcallleave(); - return result; -} - -static snd_pcm_uframes_t -snd_azf3328_pcm_pointer(struct snd_pcm_substream *substream -) -{ - const struct snd_azf3328_codec_data *codec = - substream->runtime->private_data; - unsigned long result; - snd_pcm_uframes_t frmres; - - result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS); - - /* calculate offset */ -#ifdef QUERY_HARDWARE - result -= snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1); -#else - result -= codec->dma_base; -#endif - frmres = bytes_to_frames( substream->runtime, result); - snd_azf3328_dbgcodec("%08li %s @ 0x%8lx, frames %8ld\n", - jiffies, codec->name, result, frmres); - return frmres; -} - -/******************************************************************/ - -#ifdef SUPPORT_GAMEPORT -static inline void -snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, - bool enable -) -{ - snd_azf3328_io_reg_setb( - chip->game_io+IDX_GAME_HWCONFIG, - GAME_HWCFG_IRQ_ENABLE, - enable - ); -} - -static inline void -snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, - bool enable -) -{ - snd_azf3328_io_reg_setb( - chip->game_io+IDX_GAME_HWCONFIG, - GAME_HWCFG_LEGACY_ADDRESS_ENABLE, - enable - ); -} - -static void -snd_azf3328_gameport_set_counter_frequency(struct snd_azf3328 *chip, - unsigned int freq_cfg -) -{ - snd_azf3328_io_reg_setb( - chip->game_io+IDX_GAME_HWCONFIG, - 0x02, - (freq_cfg & 1) != 0 - ); - snd_azf3328_io_reg_setb( - chip->game_io+IDX_GAME_HWCONFIG, - 0x04, - (freq_cfg & 2) != 0 - ); -} - -static inline void -snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, bool enable) -{ - snd_azf3328_ctrl_reg_6AH_update( - chip, IO_6A_SOMETHING2_GAMEPORT, enable - ); -} - -static inline void -snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip) -{ - /* - * skeleton handler only - * (we do not want axis reading in interrupt handler - too much load!) - */ - snd_azf3328_dbggame("gameport irq\n"); - - /* this should ACK the gameport IRQ properly, hopefully. */ - snd_azf3328_game_inw(chip, IDX_GAME_AXIS_VALUE); -} - -static int -snd_azf3328_gameport_open(struct gameport *gameport, int mode) -{ - struct snd_azf3328 *chip = gameport_get_port_data(gameport); - int res; - - snd_azf3328_dbggame("gameport_open, mode %d\n", mode); - switch (mode) { - case GAMEPORT_MODE_COOKED: - case GAMEPORT_MODE_RAW: - res = 0; - break; - default: - res = -1; - break; - } - - snd_azf3328_gameport_set_counter_frequency(chip, - GAME_HWCFG_ADC_COUNTER_FREQ_STD); - snd_azf3328_gameport_axis_circuit_enable(chip, (res == 0)); - - return res; -} - -static void -snd_azf3328_gameport_close(struct gameport *gameport) -{ - struct snd_azf3328 *chip = gameport_get_port_data(gameport); - - snd_azf3328_dbggame("gameport_close\n"); - snd_azf3328_gameport_set_counter_frequency(chip, - GAME_HWCFG_ADC_COUNTER_FREQ_1_200); - snd_azf3328_gameport_axis_circuit_enable(chip, 0); -} - -static int -snd_azf3328_gameport_cooked_read(struct gameport *gameport, - int *axes, - int *buttons -) -{ - struct snd_azf3328 *chip = gameport_get_port_data(gameport); - int i; - u8 val; - unsigned long flags; - - if (snd_BUG_ON(!chip)) - return 0; - - spin_lock_irqsave(&chip->reg_lock, flags); - val = snd_azf3328_game_inb(chip, IDX_GAME_LEGACY_COMPATIBLE); - *buttons = (~(val) >> 4) & 0xf; - - /* ok, this one is a bit dirty: cooked_read is being polled by a timer, - * thus we're atomic and cannot actively wait in here - * (which would be useful for us since it probably would be better - * to trigger a measurement in here, then wait a short amount of - * time until it's finished, then read values of _this_ measurement). - * - * Thus we simply resort to reading values if they're available already - * and trigger the next measurement. - */ - - val = snd_azf3328_game_inb(chip, IDX_GAME_AXES_CONFIG); - if (val & GAME_AXES_SAMPLING_READY) { - for (i = 0; i < ARRAY_SIZE(chip->axes); ++i) { - /* configure the axis to read */ - val = (i << 4) | 0x0f; - snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val); - - chip->axes[i] = snd_azf3328_game_inw( - chip, IDX_GAME_AXIS_VALUE - ); - } - } - - /* trigger next sampling of axes, to be evaluated the next time we - * enter this function */ - - /* for some very, very strange reason we cannot enable - * Measurement Ready monitoring for all axes here, - * at least not when only one joystick connected */ - val = 0x03; /* we're able to monitor axes 1 and 2 only */ - snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val); - - snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - for (i = 0; i < ARRAY_SIZE(chip->axes); i++) { - axes[i] = chip->axes[i]; - if (axes[i] == 0xffff) - axes[i] = -1; - } - - snd_azf3328_dbggame("cooked_read: axes %d %d %d %d buttons %d\n", - axes[0], axes[1], axes[2], axes[3], *buttons - ); - - return 0; -} - -static int __devinit -snd_azf3328_gameport(struct snd_azf3328 *chip, int dev) -{ - struct gameport *gp; - - chip->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "azt3328: cannot alloc memory for gameport\n"); - return -ENOMEM; - } - - gameport_set_name(gp, "AZF3328 Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); - gameport_set_dev_parent(gp, &chip->pci->dev); - gp->io = chip->game_io; - gameport_set_port_data(gp, chip); - - gp->open = snd_azf3328_gameport_open; - gp->close = snd_azf3328_gameport_close; - gp->fuzz = 16; /* seems ok */ - gp->cooked_read = snd_azf3328_gameport_cooked_read; - - /* DISABLE legacy address: we don't need it! */ - snd_azf3328_gameport_legacy_address_enable(chip, 0); - - snd_azf3328_gameport_set_counter_frequency(chip, - GAME_HWCFG_ADC_COUNTER_FREQ_1_200); - snd_azf3328_gameport_axis_circuit_enable(chip, 0); - - gameport_register_port(chip->gameport); - - return 0; -} - -static void -snd_azf3328_gameport_free(struct snd_azf3328 *chip) -{ - if (chip->gameport) { - gameport_unregister_port(chip->gameport); - chip->gameport = NULL; - } - snd_azf3328_gameport_irq_enable(chip, 0); -} -#else -static inline int -snd_azf3328_gameport(struct snd_azf3328 *chip, int dev) { return -ENOSYS; } -static inline void -snd_azf3328_gameport_free(struct snd_azf3328 *chip) { } -static inline void -snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip) -{ - printk(KERN_WARNING "huh, game port IRQ occurred!?\n"); -} -#endif /* SUPPORT_GAMEPORT */ - -/******************************************************************/ - -static inline void -snd_azf3328_irq_log_unknown_type(u8 which) -{ - snd_azf3328_dbgcodec( - "azt3328: unknown IRQ type (%x) occurred, please report!\n", - which - ); -} - -static inline void -snd_azf3328_pcm_interrupt(const struct snd_azf3328_codec_data *first_codec, - u8 status -) -{ - u8 which; - enum snd_azf3328_codec_type codec_type; - const struct snd_azf3328_codec_data *codec = first_codec; - - for (codec_type = AZF_CODEC_PLAYBACK; - codec_type <= AZF_CODEC_I2S_OUT; - ++codec_type, ++codec) { - - /* skip codec if there's no interrupt for it */ - if (!(status & (1 << codec_type))) - continue; - - spin_lock(codec->lock); - which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); - /* ack all IRQ types immediately */ - snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); - spin_unlock(codec->lock); - - if (codec->substream) { - snd_pcm_period_elapsed(codec->substream); - snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n", - codec->name, - which, - snd_azf3328_codec_inl( - codec, IDX_IO_CODEC_DMA_CURRPOS - ) - ); - } else - printk(KERN_WARNING "azt3328: irq handler problem!\n"); - if (which & IRQ_SOMETHING) - snd_azf3328_irq_log_unknown_type(which); - } -} - -static irqreturn_t -snd_azf3328_interrupt(int irq, void *dev_id) -{ - struct snd_azf3328 *chip = dev_id; - u8 status; -#if DEBUG_CODEC - static unsigned long irq_count; -#endif - - status = snd_azf3328_ctrl_inb(chip, IDX_IO_IRQSTATUS); - - /* fast path out, to ease interrupt sharing */ - if (!(status & - (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT - |IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER) - )) - return IRQ_NONE; /* must be interrupt for another device */ - - snd_azf3328_dbgcodec( - "irq_count %ld! IDX_IO_IRQSTATUS %04x\n", - irq_count++ /* debug-only */, - status - ); - - if (status & IRQ_TIMER) { - /* snd_azf3328_dbgcodec("timer %ld\n", - snd_azf3328_codec_inl(chip, IDX_IO_TIMER_VALUE) - & TIMER_VALUE_MASK - ); */ - if (chip->timer) - snd_timer_interrupt(chip->timer, chip->timer->sticks); - /* ACK timer */ - spin_lock(&chip->reg_lock); - snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); - spin_unlock(&chip->reg_lock); - snd_azf3328_dbgcodec("azt3328: timer IRQ\n"); - } - - if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) - snd_azf3328_pcm_interrupt(chip->codecs, status); - - if (status & IRQ_GAMEPORT) - snd_azf3328_gameport_interrupt(chip); - - /* MPU401 has less critical IRQ requirements - * than timer and playback/recording, right? */ - if (status & IRQ_MPU401) { - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - - /* hmm, do we have to ack the IRQ here somehow? - * If so, then I don't know how yet... */ - snd_azf3328_dbgcodec("azt3328: MPU401 IRQ\n"); - } - return IRQ_HANDLED; -} - -/*****************************************************************/ - -/* as long as we think we have identical snd_pcm_hardware parameters - for playback, capture and i2s out, we can use the same physical struct - since the struct is simply being copied into a member. -*/ -static const struct snd_pcm_hardware snd_azf3328_hardware = -{ - /* FIXME!! Correct? */ - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_U16_LE, - .rates = SNDRV_PCM_RATE_5512 | - SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_KNOT, - .rate_min = AZF_FREQ_4000, - .rate_max = AZF_FREQ_66200, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 1024, - .period_bytes_max = (32*1024), - /* We simply have two DMA areas (instead of a list of descriptors - such as other cards); I believe that this is a fixed hardware - attribute and there isn't much driver magic to be done to expand it. - Thus indicate that we have at least and at most 2 periods. */ - .periods_min = 2, - .periods_max = 2, - /* FIXME: maybe that card actually has a FIFO? - * Hmm, it seems newer revisions do have one, but we still don't know - * its size... */ - .fifo_size = 0, -}; - - -static unsigned int snd_azf3328_fixed_rates[] = { - AZF_FREQ_4000, - AZF_FREQ_4800, - AZF_FREQ_5512, - AZF_FREQ_6620, - AZF_FREQ_8000, - AZF_FREQ_9600, - AZF_FREQ_11025, - AZF_FREQ_13240, - AZF_FREQ_16000, - AZF_FREQ_22050, - AZF_FREQ_32000, - AZF_FREQ_44100, - AZF_FREQ_48000, - AZF_FREQ_66200 -}; - -static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = { - .count = ARRAY_SIZE(snd_azf3328_fixed_rates), - .list = snd_azf3328_fixed_rates, - .mask = 0, -}; - -/*****************************************************************/ - -static int -snd_azf3328_pcm_open(struct snd_pcm_substream *substream, - enum snd_azf3328_codec_type codec_type -) -{ - struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; - - snd_azf3328_dbgcallenter(); - codec->substream = substream; - - /* same parameters for all our codecs - at least we think so... */ - runtime->hw = snd_azf3328_hardware; - - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &snd_azf3328_hw_constraints_rates); - runtime->private_data = codec; - snd_azf3328_dbgcallleave(); - return 0; -} - -static int -snd_azf3328_pcm_playback_open(struct snd_pcm_substream *substream) -{ - return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK); -} - -static int -snd_azf3328_pcm_capture_open(struct snd_pcm_substream *substream) -{ - return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE); -} - -static int -snd_azf3328_pcm_i2s_out_open(struct snd_pcm_substream *substream) -{ - return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT); -} - -static int -snd_azf3328_pcm_close(struct snd_pcm_substream *substream -) -{ - struct snd_azf3328_codec_data *codec = - substream->runtime->private_data; - - snd_azf3328_dbgcallenter(); - codec->substream = NULL; - snd_azf3328_dbgcallleave(); - return 0; -} - -/******************************************************************/ - -static struct snd_pcm_ops snd_azf3328_playback_ops = { - .open = snd_azf3328_pcm_playback_open, - .close = snd_azf3328_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_azf3328_hw_params, - .hw_free = snd_azf3328_hw_free, - .prepare = snd_azf3328_pcm_prepare, - .trigger = snd_azf3328_pcm_trigger, - .pointer = snd_azf3328_pcm_pointer -}; - -static struct snd_pcm_ops snd_azf3328_capture_ops = { - .open = snd_azf3328_pcm_capture_open, - .close = snd_azf3328_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_azf3328_hw_params, - .hw_free = snd_azf3328_hw_free, - .prepare = snd_azf3328_pcm_prepare, - .trigger = snd_azf3328_pcm_trigger, - .pointer = snd_azf3328_pcm_pointer -}; - -static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { - .open = snd_azf3328_pcm_i2s_out_open, - .close = snd_azf3328_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_azf3328_hw_params, - .hw_free = snd_azf3328_hw_free, - .prepare = snd_azf3328_pcm_prepare, - .trigger = snd_azf3328_pcm_trigger, - .pointer = snd_azf3328_pcm_pointer -}; - -static int __devinit -snd_azf3328_pcm(struct snd_azf3328 *chip) -{ -enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */ - - struct snd_pcm *pcm; - int err; - - snd_azf3328_dbgcallenter(); - - err = snd_pcm_new(chip->card, "AZF3328 DSP", AZF_PCMDEV_STD, - 1, 1, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_azf3328_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_azf3328_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->shortname); - /* same pcm object for playback/capture (see snd_pcm_new() above) */ - chip->pcm[AZF_CODEC_PLAYBACK] = pcm; - chip->pcm[AZF_CODEC_CAPTURE] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - 64*1024, 64*1024); - - err = snd_pcm_new(chip->card, "AZF3328 I2S OUT", AZF_PCMDEV_I2S_OUT, - 1, 0, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_azf3328_i2s_out_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->shortname); - chip->pcm[AZF_CODEC_I2S_OUT] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - 64*1024, 64*1024); - - snd_azf3328_dbgcallleave(); - return 0; -} - -/******************************************************************/ - -/*** NOTE: the physical timer resolution actually is 1024000 ticks per second - *** (probably derived from main crystal via a divider of 24), - *** but announcing those attributes to user-space would make programs - *** configure the timer to a 1 tick value, resulting in an absolutely fatal - *** timer IRQ storm. - *** Thus I chose to announce a down-scaled virtual timer to the outside and - *** calculate real timer countdown values internally. - *** (the scale factor can be set via module parameter "seqtimer_scaling"). - ***/ - -static int -snd_azf3328_timer_start(struct snd_timer *timer) -{ - struct snd_azf3328 *chip; - unsigned long flags; - unsigned int delay; - - snd_azf3328_dbgcallenter(); - chip = snd_timer_chip(timer); - delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; - if (delay < 49) { - /* uhoh, that's not good, since user-space won't know about - * this timing tweak - * (we need to do it to avoid a lockup, though) */ - - snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay); - delay = 49; /* minimum time is 49 ticks */ - } - snd_azf3328_dbgtimer("setting timer countdown value %d\n", delay); - delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_azf3328_dbgcallleave(); - return 0; -} - -static int -snd_azf3328_timer_stop(struct snd_timer *timer) -{ - struct snd_azf3328 *chip; - unsigned long flags; - - snd_azf3328_dbgcallenter(); - chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); - /* disable timer countdown and interrupt */ - /* Hmm, should we write TIMER_IRQ_ACK here? - YES indeed, otherwise a rogue timer operation - which prompts - ALSA(?) to call repeated stop() in vain, but NOT start() - - will never end (value 0x03 is kept shown in control byte). - Simply manually poking 0x04 _once_ immediately successfully stops - the hardware/ALSA interrupt activity. */ - snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x04); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_azf3328_dbgcallleave(); - return 0; -} - - -static int -snd_azf3328_timer_precise_resolution(struct snd_timer *timer, - unsigned long *num, unsigned long *den) -{ - snd_azf3328_dbgcallenter(); - *num = 1; - *den = 1024000 / seqtimer_scaling; - snd_azf3328_dbgcallleave(); - return 0; -} - -static struct snd_timer_hardware snd_azf3328_timer_hw = { - .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 977, /* 1000000/1024000 = 0.9765625us */ - .ticks = 1024000, /* max tick count, defined by the value register; actually it's not 1024000, but 1048576, but we don't care */ - .start = snd_azf3328_timer_start, - .stop = snd_azf3328_timer_stop, - .precise_resolution = snd_azf3328_timer_precise_resolution, -}; - -static int __devinit -snd_azf3328_timer(struct snd_azf3328 *chip, int device) -{ - struct snd_timer *timer = NULL; - struct snd_timer_id tid; - int err; - - snd_azf3328_dbgcallenter(); - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = chip->card->number; - tid.device = device; - tid.subdevice = 0; - - snd_azf3328_timer_hw.resolution *= seqtimer_scaling; - snd_azf3328_timer_hw.ticks /= seqtimer_scaling; - - err = snd_timer_new(chip->card, "AZF3328", &tid, &timer); - if (err < 0) - goto out; - - strcpy(timer->name, "AZF3328 timer"); - timer->private_data = chip; - timer->hw = snd_azf3328_timer_hw; - - chip->timer = timer; - - snd_azf3328_timer_stop(timer); - - err = 0; - -out: - snd_azf3328_dbgcallleave(); - return err; -} - -/******************************************************************/ - -static int -snd_azf3328_free(struct snd_azf3328 *chip) -{ - if (chip->irq < 0) - goto __end_hw; - - snd_azf3328_mixer_reset(chip); - - snd_azf3328_timer_stop(chip->timer); - snd_azf3328_gameport_free(chip); - - if (chip->irq >= 0) - synchronize_irq(chip->irq); -__end_hw: - if (chip->irq >= 0) - free_irq(chip->irq, chip); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - - kfree(chip); - return 0; -} - -static int -snd_azf3328_dev_free(struct snd_device *device) -{ - struct snd_azf3328 *chip = device->device_data; - return snd_azf3328_free(chip); -} - -#if 0 -/* check whether a bit can be modified */ -static void -snd_azf3328_test_bit(unsigned unsigned reg, int bit) -{ - unsigned char val, valoff, valon; - - val = inb(reg); - - outb(val & ~(1 << bit), reg); - valoff = inb(reg); - - outb(val|(1 << bit), reg); - valon = inb(reg); - - outb(val, reg); - - printk(KERN_DEBUG "reg %04x bit %d: %02x %02x %02x\n", - reg, bit, val, valoff, valon - ); -} -#endif - -static inline void -snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) -{ -#if DEBUG_MISC - u16 tmp; - - snd_azf3328_dbgmisc( - "ctrl_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, " - "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n", - chip->ctrl_io, chip->game_io, chip->mpu_io, - chip->opl3_io, chip->mixer_io, chip->irq - ); - - snd_azf3328_dbgmisc("game %02x %02x %02x %02x %02x %02x\n", - snd_azf3328_game_inb(chip, 0), - snd_azf3328_game_inb(chip, 1), - snd_azf3328_game_inb(chip, 2), - snd_azf3328_game_inb(chip, 3), - snd_azf3328_game_inb(chip, 4), - snd_azf3328_game_inb(chip, 5) - ); - - for (tmp = 0; tmp < 0x07; tmp += 1) - snd_azf3328_dbgmisc("mpu_io 0x%04x\n", inb(chip->mpu_io + tmp)); - - for (tmp = 0; tmp <= 0x07; tmp += 1) - snd_azf3328_dbgmisc("0x%02x: game200 0x%04x, game208 0x%04x\n", - tmp, inb(0x200 + tmp), inb(0x208 + tmp)); - - for (tmp = 0; tmp <= 0x01; tmp += 1) - snd_azf3328_dbgmisc( - "0x%02x: mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, " - "mpu330 0x%04x opl388 0x%04x opl38c 0x%04x\n", - tmp, - inb(0x300 + tmp), - inb(0x310 + tmp), - inb(0x320 + tmp), - inb(0x330 + tmp), - inb(0x388 + tmp), - inb(0x38c + tmp) - ); - - for (tmp = 0; tmp < AZF_IO_SIZE_CTRL; tmp += 2) - snd_azf3328_dbgmisc("ctrl 0x%02x: 0x%04x\n", - tmp, snd_azf3328_ctrl_inw(chip, tmp) - ); - - for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2) - snd_azf3328_dbgmisc("mixer 0x%02x: 0x%04x\n", - tmp, snd_azf3328_mixer_inw(chip, tmp) - ); -#endif /* DEBUG_MISC */ -} - -static int __devinit -snd_azf3328_create(struct snd_card *card, - struct pci_dev *pci, - unsigned long device_type, - struct snd_azf3328 **rchip) -{ - struct snd_azf3328 *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_azf3328_dev_free, - }; - u8 dma_init; - enum snd_azf3328_codec_type codec_type; - struct snd_azf3328_codec_data *codec_setup; - - *rchip = NULL; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - err = -ENOMEM; - goto out_err; - } - spin_lock_init(&chip->reg_lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - /* check if we can restrict PCI DMA transfers to 24 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { - snd_printk(KERN_ERR "architecture does not support " - "24bit PCI busmaster DMA\n" - ); - err = -ENXIO; - goto out_err; - } - - err = pci_request_regions(pci, "Aztech AZF3328"); - if (err < 0) - goto out_err; - - chip->ctrl_io = pci_resource_start(pci, 0); - chip->game_io = pci_resource_start(pci, 1); - chip->mpu_io = pci_resource_start(pci, 2); - chip->opl3_io = pci_resource_start(pci, 3); - chip->mixer_io = pci_resource_start(pci, 4); - - codec_setup = &chip->codecs[AZF_CODEC_PLAYBACK]; - codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK; - codec_setup->lock = &chip->reg_lock; - codec_setup->type = AZF_CODEC_PLAYBACK; - codec_setup->name = "PLAYBACK"; - - codec_setup = &chip->codecs[AZF_CODEC_CAPTURE]; - codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE; - codec_setup->lock = &chip->reg_lock; - codec_setup->type = AZF_CODEC_CAPTURE; - codec_setup->name = "CAPTURE"; - - codec_setup = &chip->codecs[AZF_CODEC_I2S_OUT]; - codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT; - codec_setup->lock = &chip->reg_lock; - codec_setup->type = AZF_CODEC_I2S_OUT; - codec_setup->name = "I2S_OUT"; - - if (request_irq(pci->irq, snd_azf3328_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - err = -EBUSY; - goto out_err; - } - chip->irq = pci->irq; - pci_set_master(pci); - synchronize_irq(chip->irq); - - snd_azf3328_debug_show_ports(chip); - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) - goto out_err; - - /* create mixer interface & switches */ - err = snd_azf3328_mixer_new(chip); - if (err < 0) - goto out_err; - - /* standard codec init stuff */ - /* default DMA init value */ - dma_init = DMA_RUN_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE; - - for (codec_type = AZF_CODEC_PLAYBACK; - codec_type <= AZF_CODEC_I2S_OUT; ++codec_type) { - struct snd_azf3328_codec_data *codec = - &chip->codecs[codec_type]; - - /* shutdown codecs to reduce power / noise */ - /* have ...ctrl_codec_activity() act properly */ - codec->running = 1; - snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); - - spin_lock_irq(codec->lock); - snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS, - dma_init); - spin_unlock_irq(codec->lock); - } - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - - err = 0; - goto out; - -out_err: - if (chip) - snd_azf3328_free(chip); - pci_disable_device(pci); - -out: - return err; -} - -static int __devinit -snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_azf3328 *chip; - struct snd_opl3 *opl3; - int err; - - snd_azf3328_dbgcallenter(); - if (dev >= SNDRV_CARDS) { - err = -ENODEV; - goto out; - } - if (!enable[dev]) { - dev++; - err = -ENOENT; - goto out; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - goto out; - - strcpy(card->driver, "AZF3328"); - strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); - - err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip); - if (err < 0) - goto out_err; - - card->private_data = chip; - - /* chose to use MPU401_HW_AZT2320 ID instead of MPU401_HW_MPU401, - since our hardware ought to be similar, thus use same ID. */ - err = snd_mpu401_uart_new( - card, 0, - MPU401_HW_AZT2320, chip->mpu_io, - MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi - ); - if (err < 0) { - snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", - chip->mpu_io - ); - goto out_err; - } - - err = snd_azf3328_timer(chip, 0); - if (err < 0) - goto out_err; - - err = snd_azf3328_pcm(chip); - if (err < 0) - goto out_err; - - if (snd_opl3_create(card, chip->opl3_io, chip->opl3_io+2, - OPL3_HW_AUTO, 1, &opl3) < 0) { - snd_printk(KERN_ERR "azf3328: no OPL3 device at 0x%lx-0x%lx?\n", - chip->opl3_io, chip->opl3_io+2 - ); - } else { - /* need to use IDs 1, 2 since ID 0 is snd_azf3328_timer above */ - err = snd_opl3_timer_new(opl3, 1, 2); - if (err < 0) - goto out_err; - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - goto out_err; - opl3->private_data = chip; - } - - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, chip->ctrl_io, chip->irq); - - err = snd_card_register(card); - if (err < 0) - goto out_err; - -#ifdef MODULE - printk(KERN_INFO -"azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n" -"azt3328: Hardware was completely undocumented, unfortunately.\n" -"azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n" -"azt3328: User-scalable sequencer timer set to %dHz (1024000Hz / %d).\n", - 1024000 / seqtimer_scaling, seqtimer_scaling); -#endif - - snd_azf3328_gameport(chip, dev); - - pci_set_drvdata(pci, card); - dev++; - - err = 0; - goto out; - -out_err: - snd_printk(KERN_ERR "azf3328: something failed, exiting\n"); - snd_card_free(card); - -out: - snd_azf3328_dbgcallleave(); - return err; -} - -static void __devexit -snd_azf3328_remove(struct pci_dev *pci) -{ - snd_azf3328_dbgcallenter(); - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); - snd_azf3328_dbgcallleave(); -} - -#ifdef CONFIG_PM -static inline void -snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs) -{ - unsigned reg; - - for (reg = 0; reg < count; ++reg) { - *saved_regs = inl(io_addr); - snd_azf3328_dbgpm("suspend: io 0x%04lx: 0x%08x\n", - io_addr, *saved_regs); - ++saved_regs; - io_addr += sizeof(*saved_regs); - } -} - -static inline void -snd_azf3328_resume_regs(const u32 *saved_regs, - unsigned long io_addr, - unsigned count -) -{ - unsigned reg; - - for (reg = 0; reg < count; ++reg) { - outl(*saved_regs, io_addr); - snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n", - io_addr, *saved_regs, inl(io_addr)); - ++saved_regs; - io_addr += sizeof(*saved_regs); - } -} - -static inline void -snd_azf3328_suspend_ac97(struct snd_azf3328 *chip) -{ -#ifdef AZF_USE_AC97_LAYER - snd_ac97_suspend(chip->ac97); -#else - snd_azf3328_suspend_regs(chip->mixer_io, - ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer); - - /* make sure to disable master volume etc. to prevent looping sound */ - snd_azf3328_mixer_mute_control_master(chip, 1); - snd_azf3328_mixer_mute_control_pcm(chip, 1); -#endif /* AZF_USE_AC97_LAYER */ -} - -static inline void -snd_azf3328_resume_ac97(const struct snd_azf3328 *chip) -{ -#ifdef AZF_USE_AC97_LAYER - snd_ac97_resume(chip->ac97); -#else - snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io, - ARRAY_SIZE(chip->saved_regs_mixer)); - - /* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02) - and IDX_MIXER_RESET (offset 0x00) get touched at the same time, - resulting in a mixer reset condition persisting until _after_ - master vol was restored. Thus master vol needs an extra restore. */ - outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2); -#endif /* AZF_USE_AC97_LAYER */ -} - -static int -snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_azf3328 *chip = card->private_data; - u16 *saved_regs_ctrl_u16; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - /* same pcm object for playback/capture */ - snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]); - snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]); - - snd_azf3328_suspend_ac97(chip); - - snd_azf3328_suspend_regs(chip->ctrl_io, - ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl); - - /* manually store the one currently relevant write-only reg, too */ - saved_regs_ctrl_u16 = (u16 *)chip->saved_regs_ctrl; - saved_regs_ctrl_u16[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH; - - snd_azf3328_suspend_regs(chip->game_io, - ARRAY_SIZE(chip->saved_regs_game), chip->saved_regs_game); - snd_azf3328_suspend_regs(chip->mpu_io, - ARRAY_SIZE(chip->saved_regs_mpu), chip->saved_regs_mpu); - snd_azf3328_suspend_regs(chip->opl3_io, - ARRAY_SIZE(chip->saved_regs_opl3), chip->saved_regs_opl3); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int -snd_azf3328_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - const struct snd_azf3328 *chip = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "azt3328: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_azf3328_resume_regs(chip->saved_regs_game, chip->game_io, - ARRAY_SIZE(chip->saved_regs_game)); - snd_azf3328_resume_regs(chip->saved_regs_mpu, chip->mpu_io, - ARRAY_SIZE(chip->saved_regs_mpu)); - snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io, - ARRAY_SIZE(chip->saved_regs_opl3)); - - snd_azf3328_resume_ac97(chip); - - snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io, - ARRAY_SIZE(chip->saved_regs_ctrl)); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_azf3328_ids, - .probe = snd_azf3328_probe, - .remove = __devexit_p(snd_azf3328_remove), -#ifdef CONFIG_PM - .suspend = snd_azf3328_suspend, - .resume = snd_azf3328_resume, -#endif -}; - -static int __init -alsa_card_azf3328_init(void) -{ - int err; - snd_azf3328_dbgcallenter(); - err = pci_register_driver(&driver); - snd_azf3328_dbgcallleave(); - return err; -} - -static void __exit -alsa_card_azf3328_exit(void) -{ - snd_azf3328_dbgcallenter(); - pci_unregister_driver(&driver); - snd_azf3328_dbgcallleave(); -} - -module_init(alsa_card_azf3328_init) -module_exit(alsa_card_azf3328_exit) diff --git a/ANDROID_3.4.5/sound/pci/azt3328.h b/ANDROID_3.4.5/sound/pci/azt3328.h deleted file mode 100644 index 6f46b976..00000000 --- a/ANDROID_3.4.5/sound/pci/azt3328.h +++ /dev/null @@ -1,342 +0,0 @@ -#ifndef __SOUND_AZT3328_H -#define __SOUND_AZT3328_H - -/* "PU" == "power-up value", as tested on PCI168 PCI rev. 10 - * "WRITE_ONLY" == register does not indicate actual bit values */ - -/*** main I/O area port indices ***/ -/* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ -#define AZF_IO_SIZE_CTRL 0x80 -#define AZF_IO_SIZE_CTRL_PM 0x70 - -/* the driver initialisation suggests a layout of 4 areas - * within the main card control I/O: - * from 0x00 (playback codec), from 0x20 (recording codec) - * and from 0x40 (most certainly I2S out codec). - * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, - * power management etc.???). */ - -#define AZF_IO_OFFS_CODEC_PLAYBACK 0x00 -#define AZF_IO_OFFS_CODEC_CAPTURE 0x20 -#define AZF_IO_OFFS_CODEC_I2S_OUT 0x40 - -#define IDX_IO_CODEC_DMA_FLAGS 0x00 /* PU:0x0000 */ - /* able to reactivate output after output muting due to 8/16bit - * output change, just like 0x0002. - * 0x0001 is the only bit that's able to start the DMA counter */ - #define DMA_RESUME 0x0001 /* paused if cleared? */ - /* 0x0002 *temporarily* set during DMA stopping. hmm - * both 0x0002 and 0x0004 set in playback setup. */ - /* able to reactivate output after output muting due to 8/16bit - * output change, just like 0x0001. */ - #define DMA_RUN_SOMETHING1 0x0002 /* \ alternated (toggled) */ - /* 0x0004: NOT able to reactivate output */ - #define DMA_RUN_SOMETHING2 0x0004 /* / bits */ - #define SOMETHING_ALMOST_ALWAYS_SET 0x0008 /* ???; can be modified */ - #define DMA_EPILOGUE_SOMETHING 0x0010 - #define DMA_SOMETHING_ELSE 0x0020 /* ??? */ - #define SOMETHING_UNMODIFIABLE 0xffc0 /* unused? not modifiable */ -#define IDX_IO_CODEC_IRQTYPE 0x02 /* PU:0x0001 */ - /* write back to flags in case flags are set, in order to ACK IRQ in handler - * (bit 1 of port 0x64 indicates interrupt for one of these three types) - * sometimes in this case it just writes 0xffff to globally ACK all IRQs - * settings written are not reflected when reading back, though. - * seems to be IRQ, too (frequently used: port |= 0x07 !), but who knows? */ - #define IRQ_SOMETHING 0x0001 /* something & ACK */ - #define IRQ_FINISHED_DMABUF_1 0x0002 /* 1st dmabuf finished & ACK */ - #define IRQ_FINISHED_DMABUF_2 0x0004 /* 2nd dmabuf finished & ACK */ - #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ - #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ - #define IRQMASK_UNMODIFIABLE 0xffe0 /* unused? not modifiable */ - /* start address of 1st DMA transfer area, PU:0x00000000 */ -#define IDX_IO_CODEC_DMA_START_1 0x04 - /* start address of 2nd DMA transfer area, PU:0x00000000 */ -#define IDX_IO_CODEC_DMA_START_2 0x08 - /* both lengths of DMA transfer areas, PU:0x00000000 - length1: offset 0x0c, length2: offset 0x0e */ -#define IDX_IO_CODEC_DMA_LENGTHS 0x0c -#define IDX_IO_CODEC_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */ - /* offset within current DMA transfer area, PU:0x0000 */ -#define IDX_IO_CODEC_DMA_CURROFS 0x14 -#define IDX_IO_CODEC_SOUNDFORMAT 0x16 /* PU:0x0010 */ - /* all unspecified bits can't be modified */ - #define SOUNDFORMAT_FREQUENCY_MASK 0x000f - #define SOUNDFORMAT_XTAL1 0x00 - #define SOUNDFORMAT_XTAL2 0x01 - /* all _SUSPECTED_ values are not used by Windows drivers, so we don't - * have any hard facts, only rough measurements. - * All we know is that the crystal used on the board has 24.576MHz, - * like many soundcards (which results in the frequencies below when - * using certain divider values selected by the values below) */ - #define SOUNDFORMAT_FREQ_SUSPECTED_4000 0x0c | SOUNDFORMAT_XTAL1 - #define SOUNDFORMAT_FREQ_SUSPECTED_4800 0x0a | SOUNDFORMAT_XTAL1 - #define SOUNDFORMAT_FREQ_5510 0x0c | SOUNDFORMAT_XTAL2 - #define SOUNDFORMAT_FREQ_6620 0x0a | SOUNDFORMAT_XTAL2 - #define SOUNDFORMAT_FREQ_8000 0x00 | SOUNDFORMAT_XTAL1 /* also 0x0e | SOUNDFORMAT_XTAL1? */ - #define SOUNDFORMAT_FREQ_9600 0x08 | SOUNDFORMAT_XTAL1 - #define SOUNDFORMAT_FREQ_11025 0x00 | SOUNDFORMAT_XTAL2 /* also 0x0e | SOUNDFORMAT_XTAL2? */ - #define SOUNDFORMAT_FREQ_SUSPECTED_13240 0x08 | SOUNDFORMAT_XTAL2 /* seems to be 6620 *2 */ - #define SOUNDFORMAT_FREQ_16000 0x02 | SOUNDFORMAT_XTAL1 - #define SOUNDFORMAT_FREQ_22050 0x02 | SOUNDFORMAT_XTAL2 - #define SOUNDFORMAT_FREQ_32000 0x04 | SOUNDFORMAT_XTAL1 - #define SOUNDFORMAT_FREQ_44100 0x04 | SOUNDFORMAT_XTAL2 - #define SOUNDFORMAT_FREQ_48000 0x06 | SOUNDFORMAT_XTAL1 - #define SOUNDFORMAT_FREQ_SUSPECTED_66200 0x06 | SOUNDFORMAT_XTAL2 /* 66200 (13240 * 5); 64000 may have been nicer :-\ */ - #define SOUNDFORMAT_FLAG_16BIT 0x0010 - #define SOUNDFORMAT_FLAG_2CHANNELS 0x0020 - - -/* define frequency helpers, for maximum value safety */ -enum azf_freq_t { -#define AZF_FREQ(rate) AZF_FREQ_##rate = rate - AZF_FREQ(4000), - AZF_FREQ(4800), - AZF_FREQ(5512), - AZF_FREQ(6620), - AZF_FREQ(8000), - AZF_FREQ(9600), - AZF_FREQ(11025), - AZF_FREQ(13240), - AZF_FREQ(16000), - AZF_FREQ(22050), - AZF_FREQ(32000), - AZF_FREQ(44100), - AZF_FREQ(48000), - AZF_FREQ(66200), -#undef AZF_FREQ -}; - -/** DirectX timer, main interrupt area (FIXME: and something else?) **/ -#define IDX_IO_TIMER_VALUE 0x60 /* found this timer area by pure luck :-) */ - /* timer countdown value; triggers IRQ when timer is finished */ - #define TIMER_VALUE_MASK 0x000fffffUL - /* activate timer countdown */ - #define TIMER_COUNTDOWN_ENABLE 0x01000000UL - /* trigger timer IRQ on zero transition */ - #define TIMER_IRQ_ENABLE 0x02000000UL - /* being set in IRQ handler in case port 0x00 (hmm, not port 0x64!?!?) - * had 0x0020 set upon IRQ handler */ - #define TIMER_IRQ_ACK 0x04000000UL -#define IDX_IO_IRQSTATUS 0x64 - /* some IRQ bit in here might also be used to signal a power-management timer - * timeout, to request shutdown of the chip (e.g. AD1815JS has such a thing). - * OPL3 hardware contains several timers which confusingly in most cases - * are NOT routed to an IRQ, but some designs (e.g. LM4560) DO support that, - * so I wouldn't be surprised at all to discover that AZF3328 - * supports that thing as well... */ - - #define IRQ_PLAYBACK 0x0001 - #define IRQ_RECORDING 0x0002 - #define IRQ_I2S_OUT 0x0004 /* this IS I2S, right!? (untested) */ - #define IRQ_GAMEPORT 0x0008 /* Interrupt of Digital(ly) Enhanced Game Port */ - #define IRQ_MPU401 0x0010 - #define IRQ_TIMER 0x0020 /* DirectX timer */ - #define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly OPL3 timer? */ - #define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly OPL3 timer? */ -#define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ - /* this is set to e.g. 0x3ff or 0x300, and writable; - * maybe some buffer limit, but I couldn't find out more, PU:0x00ff: */ -#define IDX_IO_SOME_VALUE 0x68 - #define IO_68_RANDOM_TOGGLE1 0x0100 /* toggles randomly */ - #define IO_68_RANDOM_TOGGLE2 0x0200 /* toggles randomly */ - /* umm, nope, behaviour of these bits changes depending on what we wrote - * to 0x6b!! - * And they change upon playback/stop, too: - * Writing a value to 0x68 will display this exact value during playback, - * too but when stopped it can fall back to a rather different - * seemingly random value). Hmm, possibly this is a register which - * has a remote shadow which needs proper device supply which only exists - * in case playback is active? Or is this driver-induced? - */ - -/* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); - * actually inhibits PCM playback!!! maybe power management??: */ -#define IDX_IO_6AH 0x6A /* WRITE_ONLY! */ - /* bit 5: enabling this will activate permanent counting of bytes 2/3 - * at gameport I/O (0xb402/3) (equal values each) and cause - * gameport legacy I/O at 0x0200 to be _DISABLED_! - * Is this Digital Enhanced Game Port Enable??? Or maybe it's Testmode - * for Enhanced Digital Gameport (see 4D Wave DX card): */ - #define IO_6A_SOMETHING1_GAMEPORT 0x0020 - /* bit 8; sure, this _pauses_ playback (later resumes at same spot!), - * but what the heck is this really about??: */ - #define IO_6A_PAUSE_PLAYBACK_BIT8 0x0100 - /* bit 9; sure, this _pauses_ playback (later resumes at same spot!), - * but what the heck is this really about??: */ - #define IO_6A_PAUSE_PLAYBACK_BIT9 0x0200 - /* BIT8 and BIT9 are _NOT_ able to affect OPL3 MIDI playback, - * thus it suggests influence on PCM only!! - * However OTOH there seems to be no bit anywhere around here - * which is able to disable OPL3... */ - /* bit 10: enabling this actually changes values at legacy gameport - * I/O address (0x200); is this enabling of the Digital Enhanced Game Port??? - * Or maybe this simply switches off the NE558 circuit, since enabling this - * still lets us evaluate button states, but not axis states */ - #define IO_6A_SOMETHING2_GAMEPORT 0x0400 - /* writing 0x0300: causes quite some crackling during - * PC activity such as switching windows (PCI traffic?? - * --> FIFO/timing settings???) */ - /* writing 0x0100 plus/or 0x0200 inhibits playback */ - /* since the Windows .INF file has Flag_Enable_JoyStick and - * Flag_Enable_SB_DOS_Emulation directly together, it stands to reason - * that some other bit in this same register might be responsible - * for SB DOS Emulation activation (note that the file did NOT define - * a switch for OPL3!) */ -#define IDX_IO_6CH 0x6C /* unknown; fully read-writable */ -#define IDX_IO_6EH 0x6E - /* writing 0xffff returns 0x83fe (or 0x03fe only). - * writing 0x83 (and only 0x83!!) to 0x6f will cause 0x6c to switch - * from 0000 to ffff. */ - -/* further I/O indices not saved/restored and not readable after writing, - * so probably not used */ - - -/*** Gameport area port indices ***/ -/* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ -#define AZF_IO_SIZE_GAME 0x08 -#define AZF_IO_SIZE_GAME_PM 0x06 - -enum { - AZF_GAME_LEGACY_IO_PORT = 0x200 -}; - -#define IDX_GAME_LEGACY_COMPATIBLE 0x00 - /* in some operation mode, writing anything to this port - * triggers an interrupt: - * yup, that's in case IDX_GAME_01H has one of the - * axis measurement bits enabled - * (and of course one needs to have GAME_HWCFG_IRQ_ENABLE, too) */ - -#define IDX_GAME_AXES_CONFIG 0x01 - /* NOTE: layout of this register awfully similar (read: "identical??") - * to AD1815JS.pdf (p.29) */ - - /* enables axis 1 (X axis) measurement: */ - #define GAME_AXES_ENABLE_1 0x01 - /* enables axis 2 (Y axis) measurement: */ - #define GAME_AXES_ENABLE_2 0x02 - /* enables axis 3 (X axis) measurement: */ - #define GAME_AXES_ENABLE_3 0x04 - /* enables axis 4 (Y axis) measurement: */ - #define GAME_AXES_ENABLE_4 0x08 - /* selects the current axis to read the measured value of - * (at IDX_GAME_AXIS_VALUE): - * 00 = axis 1, 01 = axis 2, 10 = axis 3, 11 = axis 4: */ - #define GAME_AXES_READ_MASK 0x30 - /* enable to have the latch continuously accept ADC values - * (and continuously cause interrupts in case interrupts are enabled); - * AD1815JS.pdf says it's ~16ms interval there: */ - #define GAME_AXES_LATCH_ENABLE 0x40 - /* joystick data (measured axes) ready for reading: */ - #define GAME_AXES_SAMPLING_READY 0x80 - - /* NOTE: other card specs (SiS960 and others!) state that the - * game position latches should be frozen when reading and be freed - * (== reset?) after reading!!! - * Freezing most likely means disabling 0x40 (GAME_AXES_LATCH_ENABLE), - * but how to free the value? */ - /* An internet search for "gameport latch ADC" should provide some insight - * into how to program such a gameport system. */ - - /* writing 0xf0 to 01H once reset both counters to 0, in some special mode!? - * yup, in case 6AH 0x20 is not enabled - * (and 0x40 is sufficient, 0xf0 is not needed) */ - -#define IDX_GAME_AXIS_VALUE 0x02 - /* R: value of currently configured axis (word value!); - * W: trigger axis measurement */ - -#define IDX_GAME_HWCONFIG 0x04 - /* note: bits 4 to 7 are never set (== 0) when reading! - * --> reserved bits? */ - /* enables IRQ notification upon axes measurement ready: */ - #define GAME_HWCFG_IRQ_ENABLE 0x01 - /* these bits choose a different frequency for the - * internal ADC counter increment. - * hmm, seems to be a combo of bits: - * 00 --> standard frequency - * 10 --> 1/2 - * 01 --> 1/20 - * 11 --> 1/200: */ - #define GAME_HWCFG_ADC_COUNTER_FREQ_MASK 0x06 - - /* FIXME: these values might be reversed... */ - #define GAME_HWCFG_ADC_COUNTER_FREQ_STD 0 - #define GAME_HWCFG_ADC_COUNTER_FREQ_1_2 1 - #define GAME_HWCFG_ADC_COUNTER_FREQ_1_20 2 - #define GAME_HWCFG_ADC_COUNTER_FREQ_1_200 3 - - /* enable gameport legacy I/O address (0x200) - * I was unable to locate any configurability for a different address: */ - #define GAME_HWCFG_LEGACY_ADDRESS_ENABLE 0x08 - -/*** MPU401 ***/ -#define AZF_IO_SIZE_MPU 0x04 -#define AZF_IO_SIZE_MPU_PM 0x04 - -/*** OPL3 synth ***/ -/* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ -#define AZF_IO_SIZE_OPL3 0x08 -#define AZF_IO_SIZE_OPL3_PM 0x06 -/* hmm, given that a standard OPL3 has 4 registers only, - * there might be some enhanced functionality lurking at the end - * (especially since register 0x04 has a "non-empty" value 0xfe) */ - -/*** mixer I/O area port indices ***/ -/* (only 0x22 of 0x40 bytes saved/restored by Windows driver) - * UNFORTUNATELY azf3328 is NOT truly AC97 compliant: see main file intro */ -#define AZF_IO_SIZE_MIXER 0x40 -#define AZF_IO_SIZE_MIXER_PM 0x22 - - #define MIXER_VOLUME_RIGHT_MASK 0x001f - #define MIXER_VOLUME_LEFT_MASK 0x1f00 - #define MIXER_MUTE_MASK 0x8000 -#define IDX_MIXER_RESET 0x00 /* does NOT seem to have AC97 ID bits */ -#define IDX_MIXER_PLAY_MASTER 0x02 -#define IDX_MIXER_MODEMOUT 0x04 -#define IDX_MIXER_BASSTREBLE 0x06 - #define MIXER_BASSTREBLE_TREBLE_VOLUME_MASK 0x000e - #define MIXER_BASSTREBLE_BASS_VOLUME_MASK 0x0e00 -#define IDX_MIXER_PCBEEP 0x08 -#define IDX_MIXER_MODEMIN 0x0a -#define IDX_MIXER_MIC 0x0c - #define MIXER_MIC_MICGAIN_20DB_ENHANCEMENT_MASK 0x0040 -#define IDX_MIXER_LINEIN 0x0e -#define IDX_MIXER_CDAUDIO 0x10 -#define IDX_MIXER_VIDEO 0x12 -#define IDX_MIXER_AUX 0x14 -#define IDX_MIXER_WAVEOUT 0x16 -#define IDX_MIXER_FMSYNTH 0x18 -#define IDX_MIXER_REC_SELECT 0x1a - #define MIXER_REC_SELECT_MIC 0x00 - #define MIXER_REC_SELECT_CD 0x01 - #define MIXER_REC_SELECT_VIDEO 0x02 - #define MIXER_REC_SELECT_AUX 0x03 - #define MIXER_REC_SELECT_LINEIN 0x04 - #define MIXER_REC_SELECT_MIXSTEREO 0x05 - #define MIXER_REC_SELECT_MIXMONO 0x06 - #define MIXER_REC_SELECT_MONOIN 0x07 -#define IDX_MIXER_REC_VOLUME 0x1c -#define IDX_MIXER_ADVCTL1 0x1e - /* unlisted bits are unmodifiable */ - #define MIXER_ADVCTL1_3DWIDTH_MASK 0x000e - #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 /* yup, this is missing the high bit that official AC97 contains, plus it doesn't have linear bit value range behaviour but instead acts weirdly (possibly we're dealing with two *different* 3D settings here??) */ -#define IDX_MIXER_ADVCTL2 0x20 /* subset of AC97_GENERAL_PURPOSE reg! */ - /* unlisted bits are unmodifiable */ - #define MIXER_ADVCTL2_LPBK 0x0080 /* Loopback mode -- Win driver: "WaveOut3DBypass"? mutes WaveOut at LineOut */ - #define MIXER_ADVCTL2_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 -- Win driver: "ModemOutSelect"?? */ - #define MIXER_ADVCTL2_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic; Win driver: "MonoSelectSource"?? */ - #define MIXER_ADVCTL2_3D 0x2000 /* 3D Enhancement 1=on */ - #define MIXER_ADVCTL2_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */ - -#define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown??? */ - -/* driver internal flags */ -#define SET_CHAN_LEFT 1 -#define SET_CHAN_RIGHT 2 - -/* helper macro to align I/O port ranges to 32bit I/O width */ -#define AZF_ALIGN(x) (((x) + 3) & (~3)) - -#endif /* __SOUND_AZT3328_H */ diff --git a/ANDROID_3.4.5/sound/pci/bt87x.c b/ANDROID_3.4.5/sound/pci/bt87x.c deleted file mode 100644 index 62d6163f..00000000 --- a/ANDROID_3.4.5/sound/pci/bt87x.c +++ /dev/null @@ -1,987 +0,0 @@ -/* - * bt87x.c - Brooktree Bt878/Bt879 driver for ALSA - * - * Copyright (c) Clemens Ladisch - * - * based on btaudio.c by Gerd Knorr - * - * - * This driver 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 driver 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 -#include -#include -#include - -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_DESCRIPTION("Brooktree Bt87x audio driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878}," - "{Brooktree,Bt879}}"); - -static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int digital_rate[SNDRV_CARDS]; /* digital input rate */ -static bool load_all; /* allow to load the non-whitelisted cards */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Bt87x soundcard"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Bt87x soundcard"); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Bt87x soundcard"); -module_param_array(digital_rate, int, NULL, 0444); -MODULE_PARM_DESC(digital_rate, "Digital input rate for Bt87x soundcard"); -module_param(load_all, bool, 0444); -MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards"); - - -/* register offsets */ -#define REG_INT_STAT 0x100 /* interrupt status */ -#define REG_INT_MASK 0x104 /* interrupt mask */ -#define REG_GPIO_DMA_CTL 0x10c /* audio control */ -#define REG_PACKET_LEN 0x110 /* audio packet lengths */ -#define REG_RISC_STRT_ADD 0x114 /* RISC program start address */ -#define REG_RISC_COUNT 0x120 /* RISC program counter */ - -/* interrupt bits */ -#define INT_OFLOW (1 << 3) /* audio A/D overflow */ -#define INT_RISCI (1 << 11) /* RISC instruction IRQ bit set */ -#define INT_FBUS (1 << 12) /* FIFO overrun due to bus access latency */ -#define INT_FTRGT (1 << 13) /* FIFO overrun due to target latency */ -#define INT_FDSR (1 << 14) /* FIFO data stream resynchronization */ -#define INT_PPERR (1 << 15) /* PCI parity error */ -#define INT_RIPERR (1 << 16) /* RISC instruction parity error */ -#define INT_PABORT (1 << 17) /* PCI master or target abort */ -#define INT_OCERR (1 << 18) /* invalid opcode */ -#define INT_SCERR (1 << 19) /* sync counter overflow */ -#define INT_RISC_EN (1 << 27) /* DMA controller running */ -#define INT_RISCS_SHIFT 28 /* RISC status bits */ - -/* audio control bits */ -#define CTL_FIFO_ENABLE (1 << 0) /* enable audio data FIFO */ -#define CTL_RISC_ENABLE (1 << 1) /* enable audio DMA controller */ -#define CTL_PKTP_4 (0 << 2) /* packet mode FIFO trigger point - 4 DWORDs */ -#define CTL_PKTP_8 (1 << 2) /* 8 DWORDs */ -#define CTL_PKTP_16 (2 << 2) /* 16 DWORDs */ -#define CTL_ACAP_EN (1 << 4) /* enable audio capture */ -#define CTL_DA_APP (1 << 5) /* GPIO input */ -#define CTL_DA_IOM_AFE (0 << 6) /* audio A/D input */ -#define CTL_DA_IOM_DA (1 << 6) /* digital audio input */ -#define CTL_DA_SDR_SHIFT 8 /* DDF first stage decimation rate */ -#define CTL_DA_SDR_MASK (0xf<< 8) -#define CTL_DA_LMT (1 << 12) /* limit audio data values */ -#define CTL_DA_ES2 (1 << 13) /* enable DDF stage 2 */ -#define CTL_DA_SBR (1 << 14) /* samples rounded to 8 bits */ -#define CTL_DA_DPM (1 << 15) /* data packet mode */ -#define CTL_DA_LRD_SHIFT 16 /* ALRCK delay */ -#define CTL_DA_MLB (1 << 21) /* MSB/LSB format */ -#define CTL_DA_LRI (1 << 22) /* left/right indication */ -#define CTL_DA_SCE (1 << 23) /* sample clock edge */ -#define CTL_A_SEL_STV (0 << 24) /* TV tuner audio input */ -#define CTL_A_SEL_SFM (1 << 24) /* FM audio input */ -#define CTL_A_SEL_SML (2 << 24) /* mic/line audio input */ -#define CTL_A_SEL_SMXC (3 << 24) /* MUX bypass */ -#define CTL_A_SEL_SHIFT 24 -#define CTL_A_SEL_MASK (3 << 24) -#define CTL_A_PWRDN (1 << 26) /* analog audio power-down */ -#define CTL_A_G2X (1 << 27) /* audio gain boost */ -#define CTL_A_GAIN_SHIFT 28 /* audio input gain */ -#define CTL_A_GAIN_MASK (0xf<<28) - -/* RISC instruction opcodes */ -#define RISC_WRITE (0x1 << 28) /* write FIFO data to memory at address */ -#define RISC_WRITEC (0x5 << 28) /* write FIFO data to memory at current address */ -#define RISC_SKIP (0x2 << 28) /* skip FIFO data */ -#define RISC_JUMP (0x7 << 28) /* jump to address */ -#define RISC_SYNC (0x8 << 28) /* synchronize with FIFO */ - -/* RISC instruction bits */ -#define RISC_BYTES_ENABLE (0xf << 12) /* byte enable bits */ -#define RISC_RESYNC ( 1 << 15) /* disable FDSR errors */ -#define RISC_SET_STATUS_SHIFT 16 /* set status bits */ -#define RISC_RESET_STATUS_SHIFT 20 /* clear status bits */ -#define RISC_IRQ ( 1 << 24) /* interrupt */ -#define RISC_EOL ( 1 << 26) /* end of line */ -#define RISC_SOL ( 1 << 27) /* start of line */ - -/* SYNC status bits values */ -#define RISC_SYNC_FM1 0x6 -#define RISC_SYNC_VRO 0xc - -#define ANALOG_CLOCK 1792000 -#ifdef CONFIG_SND_BT87X_OVERCLOCK -#define CLOCK_DIV_MIN 1 -#else -#define CLOCK_DIV_MIN 4 -#endif -#define CLOCK_DIV_MAX 15 - -#define ERROR_INTERRUPTS (INT_FBUS | INT_FTRGT | INT_PPERR | \ - INT_RIPERR | INT_PABORT | INT_OCERR) -#define MY_INTERRUPTS (INT_RISCI | ERROR_INTERRUPTS) - -/* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */ -#define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8) - -/* Cards with configuration information */ -enum snd_bt87x_boardid { - SND_BT87X_BOARD_UNKNOWN, - SND_BT87X_BOARD_GENERIC, /* both an & dig interfaces, 32kHz */ - SND_BT87X_BOARD_ANALOG, /* board with no external A/D */ - SND_BT87X_BOARD_OSPREY2x0, - SND_BT87X_BOARD_OSPREY440, - SND_BT87X_BOARD_AVPHONE98, -}; - -/* Card configuration */ -struct snd_bt87x_board { - int dig_rate; /* Digital input sampling rate */ - u32 digital_fmt; /* Register settings for digital input */ - unsigned no_analog:1; /* No analog input */ - unsigned no_digital:1; /* No digital input */ -}; - -static __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = { - [SND_BT87X_BOARD_UNKNOWN] = { - .dig_rate = 32000, /* just a guess */ - }, - [SND_BT87X_BOARD_GENERIC] = { - .dig_rate = 32000, - }, - [SND_BT87X_BOARD_ANALOG] = { - .no_digital = 1, - }, - [SND_BT87X_BOARD_OSPREY2x0] = { - .dig_rate = 44100, - .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), - }, - [SND_BT87X_BOARD_OSPREY440] = { - .dig_rate = 32000, - .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), - .no_analog = 1, - }, - [SND_BT87X_BOARD_AVPHONE98] = { - .dig_rate = 48000, - }, -}; - -struct snd_bt87x { - struct snd_card *card; - struct pci_dev *pci; - struct snd_bt87x_board board; - - void __iomem *mmio; - int irq; - - spinlock_t reg_lock; - unsigned long opened; - struct snd_pcm_substream *substream; - - struct snd_dma_buffer dma_risc; - unsigned int line_bytes; - unsigned int lines; - - u32 reg_control; - u32 interrupt_mask; - - int current_line; - - int pci_parity_errors; -}; - -enum { DEVICE_DIGITAL, DEVICE_ANALOG }; - -static inline u32 snd_bt87x_readl(struct snd_bt87x *chip, u32 reg) -{ - return readl(chip->mmio + reg); -} - -static inline void snd_bt87x_writel(struct snd_bt87x *chip, u32 reg, u32 value) -{ - writel(value, chip->mmio + reg); -} - -static int snd_bt87x_create_risc(struct snd_bt87x *chip, struct snd_pcm_substream *substream, - unsigned int periods, unsigned int period_bytes) -{ - unsigned int i, offset; - u32 *risc; - - if (chip->dma_risc.area == NULL) { - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - PAGE_ALIGN(MAX_RISC_SIZE), &chip->dma_risc) < 0) - return -ENOMEM; - } - risc = (u32 *)chip->dma_risc.area; - offset = 0; - *risc++ = cpu_to_le32(RISC_SYNC | RISC_SYNC_FM1); - *risc++ = cpu_to_le32(0); - for (i = 0; i < periods; ++i) { - u32 rest; - - rest = period_bytes; - do { - u32 cmd, len; - unsigned int addr; - - len = PAGE_SIZE - (offset % PAGE_SIZE); - if (len > rest) - len = rest; - cmd = RISC_WRITE | len; - if (rest == period_bytes) { - u32 block = i * 16 / periods; - cmd |= RISC_SOL; - cmd |= block << RISC_SET_STATUS_SHIFT; - cmd |= (~block & 0xf) << RISC_RESET_STATUS_SHIFT; - } - if (len == rest) - cmd |= RISC_EOL | RISC_IRQ; - *risc++ = cpu_to_le32(cmd); - addr = snd_pcm_sgbuf_get_addr(substream, offset); - *risc++ = cpu_to_le32(addr); - offset += len; - rest -= len; - } while (rest > 0); - } - *risc++ = cpu_to_le32(RISC_SYNC | RISC_SYNC_VRO); - *risc++ = cpu_to_le32(0); - *risc++ = cpu_to_le32(RISC_JUMP); - *risc++ = cpu_to_le32(chip->dma_risc.addr); - chip->line_bytes = period_bytes; - chip->lines = periods; - return 0; -} - -static void snd_bt87x_free_risc(struct snd_bt87x *chip) -{ - if (chip->dma_risc.area) { - snd_dma_free_pages(&chip->dma_risc); - chip->dma_risc.area = NULL; - } -} - -static void snd_bt87x_pci_error(struct snd_bt87x *chip, unsigned int status) -{ - u16 pci_status; - - pci_read_config_word(chip->pci, PCI_STATUS, &pci_status); - pci_status &= PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY; - pci_write_config_word(chip->pci, PCI_STATUS, pci_status); - if (pci_status != PCI_STATUS_DETECTED_PARITY) - snd_printk(KERN_ERR "Aieee - PCI error! status %#08x, PCI status %#04x\n", - status & ERROR_INTERRUPTS, pci_status); - else { - snd_printk(KERN_ERR "Aieee - PCI parity error detected!\n"); - /* error 'handling' similar to aic7xxx_pci.c: */ - chip->pci_parity_errors++; - if (chip->pci_parity_errors > 20) { - snd_printk(KERN_ERR "Too many PCI parity errors observed.\n"); - snd_printk(KERN_ERR "Some device on this bus is generating bad parity.\n"); - snd_printk(KERN_ERR "This is an error *observed by*, not *generated by*, this card.\n"); - snd_printk(KERN_ERR "PCI parity error checking has been disabled.\n"); - chip->interrupt_mask &= ~(INT_PPERR | INT_RIPERR); - snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); - } - } -} - -static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id) -{ - struct snd_bt87x *chip = dev_id; - unsigned int status, irq_status; - - status = snd_bt87x_readl(chip, REG_INT_STAT); - irq_status = status & chip->interrupt_mask; - if (!irq_status) - return IRQ_NONE; - snd_bt87x_writel(chip, REG_INT_STAT, irq_status); - - if (irq_status & ERROR_INTERRUPTS) { - if (irq_status & (INT_FBUS | INT_FTRGT)) - snd_printk(KERN_WARNING "FIFO overrun, status %#08x\n", status); - if (irq_status & INT_OCERR) - snd_printk(KERN_ERR "internal RISC error, status %#08x\n", status); - if (irq_status & (INT_PPERR | INT_RIPERR | INT_PABORT)) - snd_bt87x_pci_error(chip, irq_status); - } - if ((irq_status & INT_RISCI) && (chip->reg_control & CTL_ACAP_EN)) { - int current_block, irq_block; - - /* assume that exactly one line has been recorded */ - chip->current_line = (chip->current_line + 1) % chip->lines; - /* but check if some interrupts have been skipped */ - current_block = chip->current_line * 16 / chip->lines; - irq_block = status >> INT_RISCS_SHIFT; - if (current_block != irq_block) - chip->current_line = (irq_block * chip->lines + 15) / 16; - - snd_pcm_period_elapsed(chip->substream); - } - return IRQ_HANDLED; -} - -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_BATCH, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = 0, /* set at runtime */ - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 255 * 4092, - .period_bytes_min = 32, - .period_bytes_max = 4092, - .periods_min = 2, - .periods_max = 255, -}; - -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_BATCH, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, - .rates = SNDRV_PCM_RATE_KNOT, - .rate_min = ANALOG_CLOCK / CLOCK_DIV_MAX, - .rate_max = ANALOG_CLOCK / CLOCK_DIV_MIN, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = 255 * 4092, - .period_bytes_min = 32, - .period_bytes_max = 4092, - .periods_min = 2, - .periods_max = 255, -}; - -static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) -{ - chip->reg_control |= CTL_DA_IOM_DA | CTL_A_PWRDN; - runtime->hw = snd_bt87x_digital_hw; - runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->board.dig_rate); - runtime->hw.rate_min = chip->board.dig_rate; - runtime->hw.rate_max = chip->board.dig_rate; - return 0; -} - -static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) -{ - static struct snd_ratnum analog_clock = { - .num = ANALOG_CLOCK, - .den_min = CLOCK_DIV_MIN, - .den_max = CLOCK_DIV_MAX, - .den_step = 1 - }; - static struct snd_pcm_hw_constraint_ratnums constraint_rates = { - .nrats = 1, - .rats = &analog_clock - }; - - chip->reg_control &= ~(CTL_DA_IOM_DA | CTL_A_PWRDN); - runtime->hw = snd_bt87x_analog_hw; - return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &constraint_rates); -} - -static int snd_bt87x_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_bt87x *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if (test_and_set_bit(0, &chip->opened)) - return -EBUSY; - - if (substream->pcm->device == DEVICE_DIGITAL) - err = snd_bt87x_set_digital_hw(chip, runtime); - else - err = snd_bt87x_set_analog_hw(chip, runtime); - if (err < 0) - goto _error; - - err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) - goto _error; - - chip->substream = substream; - return 0; - -_error: - clear_bit(0, &chip->opened); - smp_mb__after_clear_bit(); - return err; -} - -static int snd_bt87x_close(struct snd_pcm_substream *substream) -{ - struct snd_bt87x *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - chip->reg_control |= CTL_A_PWRDN; - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - spin_unlock_irq(&chip->reg_lock); - - chip->substream = NULL; - clear_bit(0, &chip->opened); - smp_mb__after_clear_bit(); - return 0; -} - -static int snd_bt87x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_bt87x *chip = snd_pcm_substream_chip(substream); - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - return snd_bt87x_create_risc(chip, substream, - params_periods(hw_params), - params_period_bytes(hw_params)); -} - -static int snd_bt87x_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_bt87x *chip = snd_pcm_substream_chip(substream); - - snd_bt87x_free_risc(chip); - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_bt87x_prepare(struct snd_pcm_substream *substream) -{ - struct snd_bt87x *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int decimation; - - spin_lock_irq(&chip->reg_lock); - chip->reg_control &= ~(CTL_DA_SDR_MASK | CTL_DA_SBR); - decimation = (ANALOG_CLOCK + runtime->rate / 4) / runtime->rate; - chip->reg_control |= decimation << CTL_DA_SDR_SHIFT; - if (runtime->format == SNDRV_PCM_FORMAT_S8) - chip->reg_control |= CTL_DA_SBR; - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_bt87x_start(struct snd_bt87x *chip) -{ - spin_lock(&chip->reg_lock); - chip->current_line = 0; - chip->reg_control |= CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN; - snd_bt87x_writel(chip, REG_RISC_STRT_ADD, chip->dma_risc.addr); - snd_bt87x_writel(chip, REG_PACKET_LEN, - chip->line_bytes | (chip->lines << 16)); - snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - spin_unlock(&chip->reg_lock); - return 0; -} - -static int snd_bt87x_stop(struct snd_bt87x *chip) -{ - spin_lock(&chip->reg_lock); - chip->reg_control &= ~(CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN); - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - snd_bt87x_writel(chip, REG_INT_MASK, 0); - snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); - spin_unlock(&chip->reg_lock); - return 0; -} - -static int snd_bt87x_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_bt87x *chip = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - return snd_bt87x_start(chip); - case SNDRV_PCM_TRIGGER_STOP: - return snd_bt87x_stop(chip); - default: - return -EINVAL; - } -} - -static snd_pcm_uframes_t snd_bt87x_pointer(struct snd_pcm_substream *substream) -{ - struct snd_bt87x *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes); -} - -static struct snd_pcm_ops snd_bt87x_pcm_ops = { - .open = snd_bt87x_pcm_open, - .close = snd_bt87x_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_bt87x_hw_params, - .hw_free = snd_bt87x_hw_free, - .prepare = snd_bt87x_prepare, - .trigger = snd_bt87x_trigger, - .pointer = snd_bt87x_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -static int snd_bt87x_capture_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; - info->value.integer.min = 0; - info->value.integer.max = 15; - return 0; -} - -static int snd_bt87x_capture_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); - - value->value.integer.value[0] = (chip->reg_control & CTL_A_GAIN_MASK) >> CTL_A_GAIN_SHIFT; - return 0; -} - -static int snd_bt87x_capture_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); - u32 old_control; - int changed; - - spin_lock_irq(&chip->reg_lock); - old_control = chip->reg_control; - chip->reg_control = (chip->reg_control & ~CTL_A_GAIN_MASK) - | (value->value.integer.value[0] << CTL_A_GAIN_SHIFT); - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - changed = old_control != chip->reg_control; - spin_unlock_irq(&chip->reg_lock); - return changed; -} - -static struct snd_kcontrol_new snd_bt87x_capture_volume = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Volume", - .info = snd_bt87x_capture_volume_info, - .get = snd_bt87x_capture_volume_get, - .put = snd_bt87x_capture_volume_put, -}; - -#define snd_bt87x_capture_boost_info snd_ctl_boolean_mono_info - -static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); - - value->value.integer.value[0] = !! (chip->reg_control & CTL_A_G2X); - return 0; -} - -static int snd_bt87x_capture_boost_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); - u32 old_control; - int changed; - - spin_lock_irq(&chip->reg_lock); - old_control = chip->reg_control; - chip->reg_control = (chip->reg_control & ~CTL_A_G2X) - | (value->value.integer.value[0] ? CTL_A_G2X : 0); - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - changed = chip->reg_control != old_control; - spin_unlock_irq(&chip->reg_lock); - return changed; -} - -static struct snd_kcontrol_new snd_bt87x_capture_boost = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Boost", - .info = snd_bt87x_capture_boost_info, - .get = snd_bt87x_capture_boost_get, - .put = snd_bt87x_capture_boost_put, -}; - -static int snd_bt87x_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - static const char *const texts[3] = {"TV Tuner", "FM", "Mic/Line"}; - - return snd_ctl_enum_info(info, 1, 3, texts); -} - -static int snd_bt87x_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); - - value->value.enumerated.item[0] = (chip->reg_control & CTL_A_SEL_MASK) >> CTL_A_SEL_SHIFT; - return 0; -} - -static int snd_bt87x_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); - u32 old_control; - int changed; - - spin_lock_irq(&chip->reg_lock); - old_control = chip->reg_control; - chip->reg_control = (chip->reg_control & ~CTL_A_SEL_MASK) - | (value->value.enumerated.item[0] << CTL_A_SEL_SHIFT); - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - changed = chip->reg_control != old_control; - spin_unlock_irq(&chip->reg_lock); - return changed; -} - -static struct snd_kcontrol_new snd_bt87x_capture_source = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_bt87x_capture_source_info, - .get = snd_bt87x_capture_source_get, - .put = snd_bt87x_capture_source_put, -}; - -static int snd_bt87x_free(struct snd_bt87x *chip) -{ - if (chip->mmio) - snd_bt87x_stop(chip); - if (chip->irq >= 0) - free_irq(chip->irq, chip); - if (chip->mmio) - iounmap(chip->mmio); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_bt87x_dev_free(struct snd_device *device) -{ - struct snd_bt87x *chip = device->device_data; - return snd_bt87x_free(chip); -} - -static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name) -{ - int err; - struct snd_pcm *pcm; - - err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); - if (err < 0) - return err; - pcm->private_data = chip; - strcpy(pcm->name, name); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_bt87x_pcm_ops); - return snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 128 * 1024, - ALIGN(255 * 4092, 1024)); -} - -static int __devinit snd_bt87x_create(struct snd_card *card, - struct pci_dev *pci, - struct snd_bt87x **rchip) -{ - struct snd_bt87x *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_bt87x_dev_free - }; - - *rchip = NULL; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) { - pci_disable_device(pci); - return -ENOMEM; - } - chip->card = card; - chip->pci = pci; - chip->irq = -1; - spin_lock_init(&chip->reg_lock); - - if ((err = pci_request_regions(pci, "Bt87x audio")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->mmio = pci_ioremap_bar(pci, 0); - if (!chip->mmio) { - snd_printk(KERN_ERR "cannot remap io memory\n"); - err = -ENOMEM; - goto fail; - } - - chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 | - CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); - chip->interrupt_mask = MY_INTERRUPTS; - snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - snd_bt87x_writel(chip, REG_INT_MASK, 0); - snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); - - err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip); - if (err < 0) { - snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq); - goto fail; - } - chip->irq = pci->irq; - pci_set_master(pci); - synchronize_irq(chip->irq); - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) - goto fail; - - snd_card_set_dev(card, &pci->dev); - *rchip = chip; - return 0; - -fail: - snd_bt87x_free(chip); - return err; -} - -#define BT_DEVICE(chip, subvend, subdev, id) \ - { .vendor = PCI_VENDOR_ID_BROOKTREE, \ - .device = chip, \ - .subvendor = subvend, .subdevice = subdev, \ - .driver_data = SND_BT87X_BOARD_ ## id } -/* driver_data is the card id for that device */ - -static DEFINE_PCI_DEVICE_TABLE(snd_bt87x_ids) = { - /* Hauppauge WinTV series */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, GENERIC), - /* Hauppauge WinTV series */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, GENERIC), - /* Viewcast Osprey 200 */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, OSPREY2x0), - /* Viewcast Osprey 440 (rate is configurable via gpio) */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, OSPREY440), - /* ATI TV-Wonder */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, GENERIC), - /* Leadtek Winfast tv 2000xp delux */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, GENERIC), - /* Pinnacle PCTV */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x11bd, 0x0012, GENERIC), - /* Voodoo TV 200 */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, GENERIC), - /* Askey Computer Corp. MagicTView'99 */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x144f, 0x3000, GENERIC), - /* AVerMedia Studio No. 103, 203, ...? */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, AVPHONE98), - /* Prolink PixelView PV-M4900 */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1554, 0x4011, GENERIC), - /* Pinnacle Studio PCTV rave */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0xbd11, 0x1200, GENERIC), - { } -}; -MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); - -/* cards known not to have audio - * (DVB cards use the audio function to transfer MPEG data) */ -static struct { - unsigned short subvendor, subdevice; -} blacklist[] __devinitdata = { - {0x0071, 0x0101}, /* Nebula Electronics DigiTV */ - {0x11bd, 0x001c}, /* Pinnacle PCTV Sat */ - {0x11bd, 0x0026}, /* Pinnacle PCTV SAT CI */ - {0x1461, 0x0761}, /* AVermedia AverTV DVB-T */ - {0x1461, 0x0771}, /* AVermedia DVB-T 771 */ - {0x1822, 0x0001}, /* Twinhan VisionPlus DVB-T */ - {0x18ac, 0xd500}, /* DVICO FusionHDTV 5 Lite */ - {0x18ac, 0xdb10}, /* DVICO FusionHDTV DVB-T Lite */ - {0x18ac, 0xdb11}, /* Ultraview DVB-T Lite */ - {0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */ - {0x7063, 0x2000}, /* pcHDTV HD-2000 TV */ -}; - -static struct pci_driver driver; - -/* return the id of the card, or a negative value if it's blacklisted */ -static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) -{ - int i; - const struct pci_device_id *supported; - - supported = pci_match_id(snd_bt87x_ids, pci); - if (supported && supported->driver_data > 0) - return supported->driver_data; - - for (i = 0; i < ARRAY_SIZE(blacklist); ++i) - if (blacklist[i].subvendor == pci->subsystem_vendor && - blacklist[i].subdevice == pci->subsystem_device) { - snd_printdd(KERN_INFO "card %#04x-%#04x:%#04x has no audio\n", - pci->device, pci->subsystem_vendor, pci->subsystem_device); - return -EBUSY; - } - - snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x\n", - pci->device, pci->subsystem_vendor, pci->subsystem_device); - snd_printk(KERN_DEBUG "please mail id, board name, and, " - "if it works, the correct digital_rate option to " - "\n"); - return SND_BT87X_BOARD_UNKNOWN; -} - -static int __devinit snd_bt87x_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_bt87x *chip; - int err; - enum snd_bt87x_boardid boardid; - - if (!pci_id->driver_data) { - err = snd_bt87x_detect_card(pci); - if (err < 0) - return -ENODEV; - boardid = err; - } else - boardid = pci_id->driver_data; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - ++dev; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_bt87x_create(card, pci, &chip); - if (err < 0) - goto _error; - - memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board)); - - if (!chip->board.no_digital) { - if (digital_rate[dev] > 0) - chip->board.dig_rate = digital_rate[dev]; - - chip->reg_control |= chip->board.digital_fmt; - - err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); - if (err < 0) - goto _error; - } - if (!chip->board.no_analog) { - err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); - if (err < 0) - goto _error; - err = snd_ctl_add(card, snd_ctl_new1( - &snd_bt87x_capture_volume, chip)); - if (err < 0) - goto _error; - err = snd_ctl_add(card, snd_ctl_new1( - &snd_bt87x_capture_boost, chip)); - if (err < 0) - goto _error; - err = snd_ctl_add(card, snd_ctl_new1( - &snd_bt87x_capture_source, chip)); - if (err < 0) - goto _error; - } - snd_printk(KERN_INFO "bt87x%d: Using board %d, %sanalog, %sdigital " - "(rate %d Hz)\n", dev, boardid, - chip->board.no_analog ? "no " : "", - chip->board.no_digital ? "no " : "", chip->board.dig_rate); - - strcpy(card->driver, "Bt87x"); - sprintf(card->shortname, "Brooktree Bt%x", pci->device); - sprintf(card->longname, "%s at %#llx, irq %i", - card->shortname, (unsigned long long)pci_resource_start(pci, 0), - chip->irq); - strcpy(card->mixername, "Bt87x"); - - err = snd_card_register(card); - if (err < 0) - goto _error; - - pci_set_drvdata(pci, card); - ++dev; - return 0; - -_error: - snd_card_free(card); - return err; -} - -static void __devexit snd_bt87x_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -/* default entries for all Bt87x cards - it's not exported */ -/* driver_data is set to 0 to call detection */ -static DEFINE_PCI_DEVICE_TABLE(snd_bt87x_default_ids) = { - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), - { } -}; - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_bt87x_ids, - .probe = snd_bt87x_probe, - .remove = __devexit_p(snd_bt87x_remove), -}; - -static int __init alsa_card_bt87x_init(void) -{ - if (load_all) - driver.id_table = snd_bt87x_default_ids; - return pci_register_driver(&driver); -} - -static void __exit alsa_card_bt87x_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_bt87x_init) -module_exit(alsa_card_bt87x_exit) diff --git a/ANDROID_3.4.5/sound/pci/ca0106/Makefile b/ANDROID_3.4.5/sound/pci/ca0106/Makefile deleted file mode 100644 index dcbae7b3..00000000 --- a/ANDROID_3.4.5/sound/pci/ca0106/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -snd-ca0106-objs := ca0106_main.o ca0106_proc.o ca0106_mixer.o ca_midi.o - -obj-$(CONFIG_SND_CA0106) += snd-ca0106.o diff --git a/ANDROID_3.4.5/sound/pci/ca0106/ca0106.h b/ANDROID_3.4.5/sound/pci/ca0106/ca0106.h deleted file mode 100644 index e8e8ccc9..00000000 --- a/ANDROID_3.4.5/sound/pci/ca0106/ca0106.h +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Copyright (c) 2004 James Courtier-Dutton - * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit - * Version: 0.0.22 - * - * FEATURES currently supported: - * See ca0106_main.c for features. - * - * Changelog: - * Support interrupts per period. - * Removed noise from Center/LFE channel when in Analog mode. - * Rename and remove mixer controls. - * 0.0.6 - * Use separate card based DMA buffer for periods table list. - * 0.0.7 - * Change remove and rename ctrls into lists. - * 0.0.8 - * Try to fix capture sources. - * 0.0.9 - * Fix AC3 output. - * Enable S32_LE format support. - * 0.0.10 - * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".) - * 0.0.11 - * Add Model name recognition. - * 0.0.12 - * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period. - * Remove redundent "voice" handling. - * 0.0.13 - * Single trigger call for multi channels. - * 0.0.14 - * Set limits based on what the sound card hardware can do. - * playback periods_min=2, periods_max=8 - * capture hw constraints require period_size = n * 64 bytes. - * playback hw constraints require period_size = n * 64 bytes. - * 0.0.15 - * Separated ca0106.c into separate functional .c files. - * 0.0.16 - * Implement 192000 sample rate. - * 0.0.17 - * Add support for SB0410 and SB0413. - * 0.0.18 - * Modified Copyright message. - * 0.0.19 - * Added I2C and SPI registers. Filled in interrupt enable. - * 0.0.20 - * Added GPIO info for SB Live 24bit. - * 0.0.21 - * Implement support for Line-in capture on SB Live 24bit. - * 0.0.22 - * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) - * - * - * This code was initially based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes - * - * 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 - * - */ - -/************************************************************************************************/ -/* PCI function 0 registers, address = + PCIBASE0 */ -/************************************************************************************************/ - -#define PTR 0x00 /* Indexed register set pointer register */ - /* NOTE: The CHANNELNUM and ADDRESS words can */ - /* be modified independently of each other. */ - /* CNL[1:0], ADDR[27:16] */ - -#define DATA 0x04 /* Indexed register set data register */ - /* DATA[31:0] */ - -#define IPR 0x08 /* Global interrupt pending register */ - /* Clear pending interrupts by writing a 1 to */ - /* the relevant bits and zero to the other bits */ -#define IPR_MIDI_RX_B 0x00020000 /* MIDI UART-B Receive buffer non-empty */ -#define IPR_MIDI_TX_B 0x00010000 /* MIDI UART-B Transmit buffer empty */ -#define IPR_SPDIF_IN_USER 0x00004000 /* SPDIF input user data has 16 more bits */ -#define IPR_SPDIF_OUT_USER 0x00002000 /* SPDIF output user data needs 16 more bits */ -#define IPR_SPDIF_OUT_FRAME 0x00001000 /* SPDIF frame about to start */ -#define IPR_SPI 0x00000800 /* SPI transaction completed */ -#define IPR_I2C_EEPROM 0x00000400 /* I2C EEPROM transaction completed */ -#define IPR_I2C_DAC 0x00000200 /* I2C DAC transaction completed */ -#define IPR_AI 0x00000100 /* Audio pending register changed. See PTR reg 0x76 */ -#define IPR_GPI 0x00000080 /* General Purpose input changed */ -#define IPR_SRC_LOCKED 0x00000040 /* SRC lock status changed */ -#define IPR_SPDIF_STATUS 0x00000020 /* SPDIF status changed */ -#define IPR_TIMER2 0x00000010 /* 192000Hz Timer */ -#define IPR_TIMER1 0x00000008 /* 44100Hz Timer */ -#define IPR_MIDI_RX_A 0x00000004 /* MIDI UART-A Receive buffer non-empty */ -#define IPR_MIDI_TX_A 0x00000002 /* MIDI UART-A Transmit buffer empty */ -#define IPR_PCI 0x00000001 /* PCI Bus error */ - -#define INTE 0x0c /* Interrupt enable register */ - -#define INTE_MIDI_RX_B 0x00020000 /* MIDI UART-B Receive buffer non-empty */ -#define INTE_MIDI_TX_B 0x00010000 /* MIDI UART-B Transmit buffer empty */ -#define INTE_SPDIF_IN_USER 0x00004000 /* SPDIF input user data has 16 more bits */ -#define INTE_SPDIF_OUT_USER 0x00002000 /* SPDIF output user data needs 16 more bits */ -#define INTE_SPDIF_OUT_FRAME 0x00001000 /* SPDIF frame about to start */ -#define INTE_SPI 0x00000800 /* SPI transaction completed */ -#define INTE_I2C_EEPROM 0x00000400 /* I2C EEPROM transaction completed */ -#define INTE_I2C_DAC 0x00000200 /* I2C DAC transaction completed */ -#define INTE_AI 0x00000100 /* Audio pending register changed. See PTR reg 0x75 */ -#define INTE_GPI 0x00000080 /* General Purpose input changed */ -#define INTE_SRC_LOCKED 0x00000040 /* SRC lock status changed */ -#define INTE_SPDIF_STATUS 0x00000020 /* SPDIF status changed */ -#define INTE_TIMER2 0x00000010 /* 192000Hz Timer */ -#define INTE_TIMER1 0x00000008 /* 44100Hz Timer */ -#define INTE_MIDI_RX_A 0x00000004 /* MIDI UART-A Receive buffer non-empty */ -#define INTE_MIDI_TX_A 0x00000002 /* MIDI UART-A Transmit buffer empty */ -#define INTE_PCI 0x00000001 /* PCI Bus error */ - -#define UNKNOWN10 0x10 /* Unknown ??. Defaults to 0 */ -#define HCFG 0x14 /* Hardware config register */ - /* 0x1000 causes AC3 to fails. It adds a dither bit. */ - -#define HCFG_STAC 0x10000000 /* Special mode for STAC9460 Codec. */ -#define HCFG_CAPTURE_I2S_BYPASS 0x08000000 /* 1 = bypass I2S input async SRC. */ -#define HCFG_CAPTURE_SPDIF_BYPASS 0x04000000 /* 1 = bypass SPDIF input async SRC. */ -#define HCFG_PLAYBACK_I2S_BYPASS 0x02000000 /* 0 = I2S IN mixer output, 1 = I2S IN1. */ -#define HCFG_FORCE_LOCK 0x01000000 /* For test only. Force input SRC tracker to lock. */ -#define HCFG_PLAYBACK_ATTENUATION 0x00006000 /* Playback attenuation mask. 0 = 0dB, 1 = 6dB, 2 = 12dB, 3 = Mute. */ -#define HCFG_PLAYBACK_DITHER 0x00001000 /* 1 = Add dither bit to all playback channels. */ -#define HCFG_PLAYBACK_S32_LE 0x00000800 /* 1 = S32_LE, 0 = S16_LE */ -#define HCFG_CAPTURE_S32_LE 0x00000400 /* 1 = S32_LE, 0 = S16_LE (S32_LE current not working) */ -#define HCFG_8_CHANNEL_PLAY 0x00000200 /* 1 = 8 channels, 0 = 2 channels per substream.*/ -#define HCFG_8_CHANNEL_CAPTURE 0x00000100 /* 1 = 8 channels, 0 = 2 channels per substream.*/ -#define HCFG_MONO 0x00000080 /* 1 = I2S Input mono */ -#define HCFG_I2S_OUTPUT 0x00000010 /* 1 = I2S Output disabled */ -#define HCFG_AC97 0x00000008 /* 0 = AC97 1.0, 1 = AC97 2.0 */ -#define HCFG_LOCK_PLAYBACK_CACHE 0x00000004 /* 1 = Cancel bustmaster accesses to soundcache */ - /* NOTE: This should generally never be used. */ -#define HCFG_LOCK_CAPTURE_CACHE 0x00000002 /* 1 = Cancel bustmaster accesses to soundcache */ - /* NOTE: This should generally never be used. */ -#define HCFG_AUDIOENABLE 0x00000001 /* 0 = CODECs transmit zero-valued samples */ - /* Should be set to 1 when the EMU10K1 is */ - /* completely initialized. */ -#define GPIO 0x18 /* Defaults: 005f03a3-Analog, 005f02a2-SPDIF. */ - /* Here pins 0,1,2,3,4,,6 are output. 5,7 are input */ - /* For the Audigy LS, pin 0 (or bit 8) controls the SPDIF/Analog jack. */ - /* SB Live 24bit: - * bit 8 0 = SPDIF in and out / 1 = Analog (Mic or Line)-in. - * bit 9 0 = Mute / 1 = Analog out. - * bit 10 0 = Line-in / 1 = Mic-in. - * bit 11 0 = ? / 1 = ? - * bit 12 0 = 48 Khz / 1 = 96 Khz Analog out on SB Live 24bit. - * bit 13 0 = ? / 1 = ? - * bit 14 0 = Mute / 1 = Analog out - * bit 15 0 = ? / 1 = ? - * Both bit 9 and bit 14 have to be set for analog sound to work on the SB Live 24bit. - */ - /* 8 general purpose programmable In/Out pins. - * GPI [8:0] Read only. Default 0. - * GPO [15:8] Default 0x9. (Default to SPDIF jack enabled for SPDIF) - * GPO Enable [23:16] Default 0x0f. Setting a bit to 1, causes the pin to be an output pin. - */ -#define AC97DATA 0x1c /* AC97 register set data register (16 bit) */ - -#define AC97ADDRESS 0x1e /* AC97 register set address register (8 bit) */ - -/********************************************************************************************************/ -/* CA0106 pointer-offset register set, accessed through the PTR and DATA registers */ -/********************************************************************************************************/ - -/* Initially all registers from 0x00 to 0x3f have zero contents. */ -#define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */ - /* One list entry: 4 bytes for DMA address, - * 4 bytes for period_size << 16. - * One list entry is 8 bytes long. - * One list entry for each period in the buffer. - */ - /* ADDR[31:0], Default: 0x0 */ -#define PLAYBACK_LIST_SIZE 0x01 /* Size of list in bytes << 16. E.g. 8 periods -> 0x00380000 */ - /* SIZE[21:16], Default: 0x8 */ -#define PLAYBACK_LIST_PTR 0x02 /* Pointer to the current period being played */ - /* PTR[5:0], Default: 0x0 */ -#define PLAYBACK_UNKNOWN3 0x03 /* Not used ?? */ -#define PLAYBACK_DMA_ADDR 0x04 /* Playback DMA address */ - /* DMA[31:0], Default: 0x0 */ -#define PLAYBACK_PERIOD_SIZE 0x05 /* Playback period size. win2000 uses 0x04000000 */ - /* SIZE[31:16], Default: 0x0 */ -#define PLAYBACK_POINTER 0x06 /* Playback period pointer. Used with PLAYBACK_LIST_PTR to determine buffer position currently in DAC */ - /* POINTER[15:0], Default: 0x0 */ -#define PLAYBACK_PERIOD_END_ADDR 0x07 /* Playback fifo end address */ - /* END_ADDR[15:0], FLAG[16] 0 = don't stop, 1 = stop */ -#define PLAYBACK_FIFO_OFFSET_ADDRESS 0x08 /* Current fifo offset address [21:16] */ - /* Cache size valid [5:0] */ -#define PLAYBACK_UNKNOWN9 0x09 /* 0x9 to 0xf Unused */ -#define CAPTURE_DMA_ADDR 0x10 /* Capture DMA address */ - /* DMA[31:0], Default: 0x0 */ -#define CAPTURE_BUFFER_SIZE 0x11 /* Capture buffer size */ - /* SIZE[31:16], Default: 0x0 */ -#define CAPTURE_POINTER 0x12 /* Capture buffer pointer. Sample currently in ADC */ - /* POINTER[15:0], Default: 0x0 */ -#define CAPTURE_FIFO_OFFSET_ADDRESS 0x13 /* Current fifo offset address [21:16] */ - /* Cache size valid [5:0] */ -#define PLAYBACK_LAST_SAMPLE 0x20 /* The sample currently being played */ -/* 0x21 - 0x3f unused */ -#define BASIC_INTERRUPT 0x40 /* Used by both playback and capture interrupt handler */ - /* Playback (0x1< Center Speaker, 2 -> Sub Woofer, 3 -> Ground, 4 -> Ground - * For Digital: 1 -> Front SPDIF, 2 -> Rear SPDIF, 3 -> Center/Subwoofer SPDIF, 4 -> Ground. - * Standard 4 pole Video A/V cable with RCA outputs: 1 -> White, 2 -> Yellow, 3 -> Shield on all three, 4 -> Red. - * So, from this you can see that you cannot use a Standard 4 pole Video A/V cable with the SB Audigy LS card. - */ -/* The Front SPDIF PCM gets mixed with samples from the AC97 codec, so can only work for Stereo PCM and not AC3/DTS - * The Rear SPDIF can be used for Stereo PCM and also AC3/DTS - * The Center/LFE SPDIF cannot be used for AC3/DTS, but can be used for Stereo PCM. - * Summary: For ALSA we use the Rear channel for SPDIF Digital AC3/DTS output - */ -/* A standard 2 pole mono mini-jack to RCA plug can be used for SPDIF Stereo PCM output from the Front channel. - * A standard 3 pole stereo mini-jack to 2 RCA plugs can be used for SPDIF AC3/DTS and Stereo PCM output utilising the Rear channel and just one of the RCA plugs. - */ -#define SPCS0 0x41 /* SPDIF output Channel Status 0 register. For Rear. default=0x02108004, non-audio=0x02108006 */ -#define SPCS1 0x42 /* SPDIF output Channel Status 1 register. For Front */ -#define SPCS2 0x43 /* SPDIF output Channel Status 2 register. For Center/LFE */ -#define SPCS3 0x44 /* SPDIF output Channel Status 3 register. Unknown */ - /* When Channel set to 0: */ -#define SPCS_CLKACCYMASK 0x30000000 /* Clock accuracy */ -#define SPCS_CLKACCY_1000PPM 0x00000000 /* 1000 parts per million */ -#define SPCS_CLKACCY_50PPM 0x10000000 /* 50 parts per million */ -#define SPCS_CLKACCY_VARIABLE 0x20000000 /* Variable accuracy */ -#define SPCS_SAMPLERATEMASK 0x0f000000 /* Sample rate */ -#define SPCS_SAMPLERATE_44 0x00000000 /* 44.1kHz sample rate */ -#define SPCS_SAMPLERATE_48 0x02000000 /* 48kHz sample rate */ -#define SPCS_SAMPLERATE_32 0x03000000 /* 32kHz sample rate */ -#define SPCS_CHANNELNUMMASK 0x00f00000 /* Channel number */ -#define SPCS_CHANNELNUM_UNSPEC 0x00000000 /* Unspecified channel number */ -#define SPCS_CHANNELNUM_LEFT 0x00100000 /* Left channel */ -#define SPCS_CHANNELNUM_RIGHT 0x00200000 /* Right channel */ -#define SPCS_SOURCENUMMASK 0x000f0000 /* Source number */ -#define SPCS_SOURCENUM_UNSPEC 0x00000000 /* Unspecified source number */ -#define SPCS_GENERATIONSTATUS 0x00008000 /* Originality flag (see IEC-958 spec) */ -#define SPCS_CATEGORYCODEMASK 0x00007f00 /* Category code (see IEC-958 spec) */ -#define SPCS_MODEMASK 0x000000c0 /* Mode (see IEC-958 spec) */ -#define SPCS_EMPHASISMASK 0x00000038 /* Emphasis */ -#define SPCS_EMPHASIS_NONE 0x00000000 /* No emphasis */ -#define SPCS_EMPHASIS_50_15 0x00000008 /* 50/15 usec 2 channel */ -#define SPCS_COPYRIGHT 0x00000004 /* Copyright asserted flag -- do not modify */ -#define SPCS_NOTAUDIODATA 0x00000002 /* 0 = Digital audio, 1 = not audio */ -#define SPCS_PROFESSIONAL 0x00000001 /* 0 = Consumer (IEC-958), 1 = pro (AES3-1992) */ - - /* When Channel set to 1: */ -#define SPCS_WORD_LENGTH_MASK 0x0000000f /* Word Length Mask */ -#define SPCS_WORD_LENGTH_16 0x00000008 /* Word Length 16 bit */ -#define SPCS_WORD_LENGTH_17 0x00000006 /* Word Length 17 bit */ -#define SPCS_WORD_LENGTH_18 0x00000004 /* Word Length 18 bit */ -#define SPCS_WORD_LENGTH_19 0x00000002 /* Word Length 19 bit */ -#define SPCS_WORD_LENGTH_20A 0x0000000a /* Word Length 20 bit */ -#define SPCS_WORD_LENGTH_20 0x00000009 /* Word Length 20 bit (both 0xa and 0x9 are 20 bit) */ -#define SPCS_WORD_LENGTH_21 0x00000007 /* Word Length 21 bit */ -#define SPCS_WORD_LENGTH_22 0x00000005 /* Word Length 22 bit */ -#define SPCS_WORD_LENGTH_23 0x00000003 /* Word Length 23 bit */ -#define SPCS_WORD_LENGTH_24 0x0000000b /* Word Length 24 bit */ -#define SPCS_ORIGINAL_SAMPLE_RATE_MASK 0x000000f0 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_NONE 0x00000000 /* Original Sample rate not indicated */ -#define SPCS_ORIGINAL_SAMPLE_RATE_16000 0x00000010 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_RES1 0x00000020 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_32000 0x00000030 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_12000 0x00000040 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_11025 0x00000050 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_8000 0x00000060 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_RES2 0x00000070 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_192000 0x00000080 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_24000 0x00000090 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_96000 0x000000a0 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_48000 0x000000b0 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_176400 0x000000c0 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_22050 0x000000d0 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_88200 0x000000e0 /* Original Sample rate */ -#define SPCS_ORIGINAL_SAMPLE_RATE_44100 0x000000f0 /* Original Sample rate */ - -#define SPDIF_SELECT1 0x45 /* Enables SPDIF or Analogue outputs 0-SPDIF, 0xf00-Analogue */ - /* 0x100 - Front, 0x800 - Rear, 0x200 - Center/LFE. - * But as the jack is shared, use 0xf00. - * The Windows2000 driver uses 0x0000000f for both digital and analog. - * 0xf00 introduces interesting noises onto the Center/LFE. - * If you turn the volume up, you hear computer noise, - * e.g. mouse moving, changing between app windows etc. - * So, I am going to set this to 0x0000000f all the time now, - * same as the windows driver does. - * Use register SPDIF_SELECT2(0x72) to switch between SPDIF and Analog. - */ - /* When Channel = 0: - * Wide SPDIF format [3:0] (one bit for each channel) (0=20bit, 1=24bit) - * Tristate SPDIF Output [11:8] (one bit for each channel) (0=Not tristate, 1=Tristate) - * SPDIF Bypass enable [19:16] (one bit for each channel) (0=Not bypass, 1=Bypass) - */ - /* When Channel = 1: - * SPDIF 0 User data [7:0] - * SPDIF 1 User data [15:8] - * SPDIF 0 User data [23:16] - * SPDIF 0 User data [31:24] - * User data can be sent by using the SPDIF output frame pending and SPDIF output user bit interrupts. - */ -#define WATERMARK 0x46 /* Test bit to indicate cache usage level */ -#define SPDIF_INPUT_STATUS 0x49 /* SPDIF Input status register. Bits the same as SPCS. - * When Channel = 0: Bits the same as SPCS channel 0. - * When Channel = 1: Bits the same as SPCS channel 1. - * When Channel = 2: - * SPDIF Input User data [16:0] - * SPDIF Input Frame count [21:16] - */ -#define CAPTURE_CACHE_DATA 0x50 /* 0x50-0x5f Recorded samples. */ -#define CAPTURE_SOURCE 0x60 /* Capture Source 0 = MIC */ -#define CAPTURE_SOURCE_CHANNEL0 0xf0000000 /* Mask for selecting the Capture sources */ -#define CAPTURE_SOURCE_CHANNEL1 0x0f000000 /* 0 - SPDIF mixer output. */ -#define CAPTURE_SOURCE_CHANNEL2 0x00f00000 /* 1 - What you hear or . 2 - ?? */ -#define CAPTURE_SOURCE_CHANNEL3 0x000f0000 /* 3 - Mic in, Line in, TAD in, Aux in. */ -#define CAPTURE_SOURCE_RECORD_MAP 0x0000ffff /* Default 0x00e4 */ - /* Record Map [7:0] (2 bits per channel) 0=mapped to channel 0, 1=mapped to channel 1, 2=mapped to channel2, 3=mapped to channel3 - * Record source select for channel 0 [18:16] - * Record source select for channel 1 [22:20] - * Record source select for channel 2 [26:24] - * Record source select for channel 3 [30:28] - * 0 - SPDIF mixer output. - * 1 - i2s mixer output. - * 2 - SPDIF input. - * 3 - i2s input. - * 4 - AC97 capture. - * 5 - SRC output. - */ -#define CAPTURE_VOLUME1 0x61 /* Capture volume per channel 0-3 */ -#define CAPTURE_VOLUME2 0x62 /* Capture volume per channel 4-7 */ - -#define PLAYBACK_ROUTING1 0x63 /* Playback routing of channels 0-7. Effects AC3 output. Default 0x32765410 */ -#define ROUTING1_REAR 0x77000000 /* Channel_id 0 sends to 10, Channel_id 1 sends to 32 */ -#define ROUTING1_NULL 0x00770000 /* Channel_id 2 sends to 54, Channel_id 3 sends to 76 */ -#define ROUTING1_CENTER_LFE 0x00007700 /* 0x32765410 means, send Channel_id 0 to FRONT, Channel_id 1 to REAR */ -#define ROUTING1_FRONT 0x00000077 /* Channel_id 2 to CENTER_LFE, Channel_id 3 to NULL. */ - /* Channel_id's handle stereo channels. Channel X is a single mono channel */ - /* Host is input from the PCI bus. */ - /* Host channel 0 [2:0] -> SPDIF Mixer/Router channel 0-7. - * Host channel 1 [6:4] -> SPDIF Mixer/Router channel 0-7. - * Host channel 2 [10:8] -> SPDIF Mixer/Router channel 0-7. - * Host channel 3 [14:12] -> SPDIF Mixer/Router channel 0-7. - * Host channel 4 [18:16] -> SPDIF Mixer/Router channel 0-7. - * Host channel 5 [22:20] -> SPDIF Mixer/Router channel 0-7. - * Host channel 6 [26:24] -> SPDIF Mixer/Router channel 0-7. - * Host channel 7 [30:28] -> SPDIF Mixer/Router channel 0-7. - */ - -#define PLAYBACK_ROUTING2 0x64 /* Playback Routing . Feeding Capture channels back into Playback. Effects AC3 output. Default 0x76767676 */ - /* SRC is input from the capture inputs. */ - /* SRC channel 0 [2:0] -> SPDIF Mixer/Router channel 0-7. - * SRC channel 1 [6:4] -> SPDIF Mixer/Router channel 0-7. - * SRC channel 2 [10:8] -> SPDIF Mixer/Router channel 0-7. - * SRC channel 3 [14:12] -> SPDIF Mixer/Router channel 0-7. - * SRC channel 4 [18:16] -> SPDIF Mixer/Router channel 0-7. - * SRC channel 5 [22:20] -> SPDIF Mixer/Router channel 0-7. - * SRC channel 6 [26:24] -> SPDIF Mixer/Router channel 0-7. - * SRC channel 7 [30:28] -> SPDIF Mixer/Router channel 0-7. - */ - -#define PLAYBACK_MUTE 0x65 /* Unknown. While playing 0x0, while silent 0x00fc0000 */ - /* SPDIF Mixer input control: - * Invert SRC to SPDIF Mixer [7-0] (One bit per channel) - * Invert Host to SPDIF Mixer [15:8] (One bit per channel) - * SRC to SPDIF Mixer disable [23:16] (One bit per channel) - * Host to SPDIF Mixer disable [31:24] (One bit per channel) - */ -#define PLAYBACK_VOLUME1 0x66 /* Playback SPDIF volume per channel. Set to the same PLAYBACK_VOLUME(0x6a) */ - /* PLAYBACK_VOLUME1 must be set to 30303030 for SPDIF AC3 Playback */ - /* SPDIF mixer input volume. 0=12dB, 0x30=0dB, 0xFE=-51.5dB, 0xff=Mute */ - /* One register for each of the 4 stereo streams. */ - /* SRC Right volume [7:0] - * SRC Left volume [15:8] - * Host Right volume [23:16] - * Host Left volume [31:24] - */ -#define CAPTURE_ROUTING1 0x67 /* Capture Routing. Default 0x32765410 */ - /* Similar to register 0x63, except that the destination is the I2S mixer instead of the SPDIF mixer. I.E. Outputs to the Analog outputs instead of SPDIF. */ -#define CAPTURE_ROUTING2 0x68 /* Unknown Routing. Default 0x76767676 */ - /* Similar to register 0x64, except that the destination is the I2S mixer instead of the SPDIF mixer. I.E. Outputs to the Analog outputs instead of SPDIF. */ -#define CAPTURE_MUTE 0x69 /* Unknown. While capturing 0x0, while silent 0x00fc0000 */ - /* Similar to register 0x65, except that the destination is the I2S mixer instead of the SPDIF mixer. I.E. Outputs to the Analog outputs instead of SPDIF. */ -#define PLAYBACK_VOLUME2 0x6a /* Playback Analog volume per channel. Does not effect AC3 output */ - /* Similar to register 0x66, except that the destination is the I2S mixer instead of the SPDIF mixer. I.E. Outputs to the Analog outputs instead of SPDIF. */ -#define UNKNOWN6b 0x6b /* Unknown. Readonly. Default 00400000 00400000 00400000 00400000 */ -#define MIDI_UART_A_DATA 0x6c /* Midi Uart A Data */ -#define MIDI_UART_A_CMD 0x6d /* Midi Uart A Command/Status */ -#define MIDI_UART_B_DATA 0x6e /* Midi Uart B Data (currently unused) */ -#define MIDI_UART_B_CMD 0x6f /* Midi Uart B Command/Status (currently unused) */ - -/* unique channel identifier for midi->channel */ - -#define CA0106_MIDI_CHAN_A 0x1 -#define CA0106_MIDI_CHAN_B 0x2 - -/* from mpu401 */ - -#define CA0106_MIDI_INPUT_AVAIL 0x80 -#define CA0106_MIDI_OUTPUT_READY 0x40 -#define CA0106_MPU401_RESET 0xff -#define CA0106_MPU401_ENTER_UART 0x3f -#define CA0106_MPU401_ACK 0xfe - -#define SAMPLE_RATE_TRACKER_STATUS 0x70 /* Readonly. Default 00108000 00108000 00500000 00500000 */ - /* Estimated sample rate [19:0] Relative to 48kHz. 0x8000 = 1.0 - * Rate Locked [20] - * SPDIF Locked [21] For SPDIF channel only. - * Valid Audio [22] For SPDIF channel only. - */ -#define CAPTURE_CONTROL 0x71 /* Some sort of routing. default = 40c81000 30303030 30300000 00700000 */ - /* Channel_id 0: 0x40c81000 must be changed to 0x40c80000 for SPDIF AC3 input or output. */ - /* Channel_id 1: 0xffffffff(mute) 0x30303030(max) controls CAPTURE feedback into PLAYBACK. */ - /* Sample rate output control register Channel=0 - * Sample output rate [1:0] (0=48kHz, 1=44.1kHz, 2=96kHz, 3=192Khz) - * Sample input rate [3:2] (0=48kHz, 1=Not available, 2=96kHz, 3=192Khz) - * SRC input source select [4] 0=Audio from digital mixer, 1=Audio from analog source. - * Record rate [9:8] (0=48kHz, 1=Not available, 2=96kHz, 3=192Khz) - * Record mixer output enable [12:10] - * I2S input rate master mode [15:14] (0=48kHz, 1=44.1kHz, 2=96kHz, 3=192Khz) - * I2S output rate [17:16] (0=48kHz, 1=44.1kHz, 2=96kHz, 3=192Khz) - * I2S output source select [18] (0=Audio from host, 1=Audio from SRC) - * Record mixer I2S enable [20:19] (enable/disable i2sin1 and i2sin0) - * I2S output master clock select [21] (0=256*I2S output rate, 1=512*I2S output rate.) - * I2S input master clock select [22] (0=256*I2S input rate, 1=512*I2S input rate.) - * I2S input mode [23] (0=Slave, 1=Master) - * SPDIF output rate [25:24] (0=48kHz, 1=44.1kHz, 2=96kHz, 3=192Khz) - * SPDIF output source select [26] (0=host, 1=SRC) - * Not used [27] - * Record Source 0 input [29:28] (0=SPDIF in, 1=I2S in, 2=AC97 Mic, 3=AC97 PCM) - * Record Source 1 input [31:30] (0=SPDIF in, 1=I2S in, 2=AC97 Mic, 3=AC97 PCM) - */ - /* Sample rate output control register Channel=1 - * I2S Input 0 volume Right [7:0] - * I2S Input 0 volume Left [15:8] - * I2S Input 1 volume Right [23:16] - * I2S Input 1 volume Left [31:24] - */ - /* Sample rate output control register Channel=2 - * SPDIF Input volume Right [23:16] - * SPDIF Input volume Left [31:24] - */ - /* Sample rate output control register Channel=3 - * No used - */ -#define SPDIF_SELECT2 0x72 /* Some sort of routing. Channel_id 0 only. default = 0x0f0f003f. Analog 0x000b0000, Digital 0x0b000000 */ -#define ROUTING2_FRONT_MASK 0x00010000 /* Enable for Front speakers. */ -#define ROUTING2_CENTER_LFE_MASK 0x00020000 /* Enable for Center/LFE speakers. */ -#define ROUTING2_REAR_MASK 0x00080000 /* Enable for Rear speakers. */ - /* Audio output control - * AC97 output enable [5:0] - * I2S output enable [19:16] - * SPDIF output enable [27:24] - */ -#define UNKNOWN73 0x73 /* Unknown. Readonly. Default 0x0 */ -#define CHIP_VERSION 0x74 /* P17 Chip version. Channel_id 0 only. Default 00000071 */ -#define EXTENDED_INT_MASK 0x75 /* Used by both playback and capture interrupt handler */ - /* Sets which Interrupts are enabled. */ - /* 0x00000001 = Half period. Playback. - * 0x00000010 = Full period. Playback. - * 0x00000100 = Half buffer. Playback. - * 0x00001000 = Full buffer. Playback. - * 0x00010000 = Half buffer. Capture. - * 0x00100000 = Full buffer. Capture. - * Capture can only do 2 periods. - * 0x01000000 = End audio. Playback. - * 0x40000000 = Half buffer Playback,Caputre xrun. - * 0x80000000 = Full buffer Playback,Caputre xrun. - */ -#define EXTENDED_INT 0x76 /* Used by both playback and capture interrupt handler */ - /* Shows which interrupts are active at the moment. */ - /* Same bit layout as EXTENDED_INT_MASK */ -#define COUNTER77 0x77 /* Counter range 0 to 0x3fffff, 192000 counts per second. */ -#define COUNTER78 0x78 /* Counter range 0 to 0x3fffff, 44100 counts per second. */ -#define EXTENDED_INT_TIMER 0x79 /* Channel_id 0 only. Used by both playback and capture interrupt handler */ - /* Causes interrupts based on timer intervals. */ -#define SPI 0x7a /* SPI: Serial Interface Register */ -#define I2C_A 0x7b /* I2C Address. 32 bit */ -#define I2C_D0 0x7c /* I2C Data Port 0. 32 bit */ -#define I2C_D1 0x7d /* I2C Data Port 1. 32 bit */ -//I2C values -#define I2C_A_ADC_ADD_MASK 0x000000fe //The address is a 7 bit address -#define I2C_A_ADC_RW_MASK 0x00000001 //bit mask for R/W -#define I2C_A_ADC_TRANS_MASK 0x00000010 //Bit mask for I2c address DAC value -#define I2C_A_ADC_ABORT_MASK 0x00000020 //Bit mask for I2C transaction abort flag -#define I2C_A_ADC_LAST_MASK 0x00000040 //Bit mask for Last word transaction -#define I2C_A_ADC_BYTE_MASK 0x00000080 //Bit mask for Byte Mode - -#define I2C_A_ADC_ADD 0x00000034 //This is the Device address for ADC -#define I2C_A_ADC_READ 0x00000001 //To perform a read operation -#define I2C_A_ADC_START 0x00000100 //Start I2C transaction -#define I2C_A_ADC_ABORT 0x00000200 //I2C transaction abort -#define I2C_A_ADC_LAST 0x00000400 //I2C last transaction -#define I2C_A_ADC_BYTE 0x00000800 //I2C one byte mode - -#define I2C_D_ADC_REG_MASK 0xfe000000 //ADC address register -#define I2C_D_ADC_DAT_MASK 0x01ff0000 //ADC data register - -#define ADC_TIMEOUT 0x00000007 //ADC Timeout Clock Disable -#define ADC_IFC_CTRL 0x0000000b //ADC Interface Control -#define ADC_MASTER 0x0000000c //ADC Master Mode Control -#define ADC_POWER 0x0000000d //ADC PowerDown Control -#define ADC_ATTEN_ADCL 0x0000000e //ADC Attenuation ADCL -#define ADC_ATTEN_ADCR 0x0000000f //ADC Attenuation ADCR -#define ADC_ALC_CTRL1 0x00000010 //ADC ALC Control 1 -#define ADC_ALC_CTRL2 0x00000011 //ADC ALC Control 2 -#define ADC_ALC_CTRL3 0x00000012 //ADC ALC Control 3 -#define ADC_NOISE_CTRL 0x00000013 //ADC Noise Gate Control -#define ADC_LIMIT_CTRL 0x00000014 //ADC Limiter Control -#define ADC_MUX 0x00000015 //ADC Mux offset - -#if 0 -/* FIXME: Not tested yet. */ -#define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain -#define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB -#define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute -#define ADC_MUTE 0x000000c0 //Value to mute ADC -#define ADC_OSR 0x00000008 //Mask for ADC oversample rate select -#define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock -#define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter -#define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window -#endif - -#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux -#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) -#define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux -#define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux -#define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux - -#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ -#define PCM_FRONT_CHANNEL 0 -#define PCM_REAR_CHANNEL 1 -#define PCM_CENTER_LFE_CHANNEL 2 -#define PCM_UNKNOWN_CHANNEL 3 -#define CONTROL_FRONT_CHANNEL 0 -#define CONTROL_REAR_CHANNEL 3 -#define CONTROL_CENTER_LFE_CHANNEL 1 -#define CONTROL_UNKNOWN_CHANNEL 2 - - -/* Based on WM8768 Datasheet Rev 4.2 page 32 */ -#define SPI_REG_MASK 0x1ff /* 16-bit SPI writes have a 7-bit address */ -#define SPI_REG_SHIFT 9 /* followed by 9 bits of data */ - -#define SPI_LDA1_REG 0 /* digital attenuation */ -#define SPI_RDA1_REG 1 -#define SPI_LDA2_REG 4 -#define SPI_RDA2_REG 5 -#define SPI_LDA3_REG 6 -#define SPI_RDA3_REG 7 -#define SPI_LDA4_REG 13 -#define SPI_RDA4_REG 14 -#define SPI_MASTDA_REG 8 - -#define SPI_DA_BIT_UPDATE (1<<8) /* update attenuation values */ -#define SPI_DA_BIT_0dB 0xff /* 0 dB */ -#define SPI_DA_BIT_infdB 0x00 /* inf dB attenuation (mute) */ - -#define SPI_PL_REG 2 -#define SPI_PL_BIT_L_M (0<<5) /* left channel = mute */ -#define SPI_PL_BIT_L_L (1<<5) /* left channel = left */ -#define SPI_PL_BIT_L_R (2<<5) /* left channel = right */ -#define SPI_PL_BIT_L_C (3<<5) /* left channel = (L+R)/2 */ -#define SPI_PL_BIT_R_M (0<<7) /* right channel = mute */ -#define SPI_PL_BIT_R_L (1<<7) /* right channel = left */ -#define SPI_PL_BIT_R_R (2<<7) /* right channel = right */ -#define SPI_PL_BIT_R_C (3<<7) /* right channel = (L+R)/2 */ -#define SPI_IZD_REG 2 -#define SPI_IZD_BIT (1<<4) /* infinite zero detect */ - -#define SPI_FMT_REG 3 -#define SPI_FMT_BIT_RJ (0<<0) /* right justified mode */ -#define SPI_FMT_BIT_LJ (1<<0) /* left justified mode */ -#define SPI_FMT_BIT_I2S (2<<0) /* I2S mode */ -#define SPI_FMT_BIT_DSP (3<<0) /* DSP Modes A or B */ -#define SPI_LRP_REG 3 -#define SPI_LRP_BIT (1<<2) /* invert LRCLK polarity */ -#define SPI_BCP_REG 3 -#define SPI_BCP_BIT (1<<3) /* invert BCLK polarity */ -#define SPI_IWL_REG 3 -#define SPI_IWL_BIT_16 (0<<4) /* 16-bit world length */ -#define SPI_IWL_BIT_20 (1<<4) /* 20-bit world length */ -#define SPI_IWL_BIT_24 (2<<4) /* 24-bit world length */ -#define SPI_IWL_BIT_32 (3<<4) /* 32-bit world length */ - -#define SPI_MS_REG 10 -#define SPI_MS_BIT (1<<5) /* master mode */ -#define SPI_RATE_REG 10 /* only applies in master mode */ -#define SPI_RATE_BIT_128 (0<<6) /* MCLK = LRCLK * 128 */ -#define SPI_RATE_BIT_192 (1<<6) -#define SPI_RATE_BIT_256 (2<<6) -#define SPI_RATE_BIT_384 (3<<6) -#define SPI_RATE_BIT_512 (4<<6) -#define SPI_RATE_BIT_768 (5<<6) - -/* They really do label the bit for the 4th channel "4" and not "3" */ -#define SPI_DMUTE0_REG 9 -#define SPI_DMUTE1_REG 9 -#define SPI_DMUTE2_REG 9 -#define SPI_DMUTE4_REG 15 -#define SPI_DMUTE0_BIT (1<<3) -#define SPI_DMUTE1_BIT (1<<4) -#define SPI_DMUTE2_BIT (1<<5) -#define SPI_DMUTE4_BIT (1<<2) - -#define SPI_PHASE0_REG 3 -#define SPI_PHASE1_REG 3 -#define SPI_PHASE2_REG 3 -#define SPI_PHASE4_REG 15 -#define SPI_PHASE0_BIT (1<<6) -#define SPI_PHASE1_BIT (1<<7) -#define SPI_PHASE2_BIT (1<<8) -#define SPI_PHASE4_BIT (1<<3) - -#define SPI_PDWN_REG 2 /* power down all DACs */ -#define SPI_PDWN_BIT (1<<2) -#define SPI_DACD0_REG 10 /* power down individual DACs */ -#define SPI_DACD1_REG 10 -#define SPI_DACD2_REG 10 -#define SPI_DACD4_REG 15 -#define SPI_DACD0_BIT (1<<1) -#define SPI_DACD1_BIT (1<<2) -#define SPI_DACD2_BIT (1<<3) -#define SPI_DACD4_BIT (1<<0) /* datasheet error says it's 1 */ - -#define SPI_PWRDNALL_REG 10 /* power down everything */ -#define SPI_PWRDNALL_BIT (1<<4) - -#include "ca_midi.h" - -struct snd_ca0106; - -struct snd_ca0106_channel { - struct snd_ca0106 *emu; - int number; - int use; - void (*interrupt)(struct snd_ca0106 *emu, struct snd_ca0106_channel *channel); - struct snd_ca0106_pcm *epcm; -}; - -struct snd_ca0106_pcm { - struct snd_ca0106 *emu; - struct snd_pcm_substream *substream; - int channel_id; - unsigned short running; -}; - -struct snd_ca0106_details { - u32 serial; - char * name; - int ac97; /* ac97 = 0 -> Select MIC, Line in, TAD in, AUX in. - ac97 = 1 -> Default to AC97 in. */ - int gpio_type; /* gpio_type = 1 -> shared mic-in/line-in - gpio_type = 2 -> shared side-out/line-in. */ - int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume - controls, phone, mic, line-in and aux. */ - u16 spi_dac; /* spi_dac = 0 -> no spi interface for DACs - spi_dac = 0x - -> specifies DAC id for each channel pair. */ -}; - -// definition of the chip-specific record -struct snd_ca0106 { - struct snd_card *card; - struct snd_ca0106_details *details; - struct pci_dev *pci; - - unsigned long port; - struct resource *res_port; - int irq; - - unsigned int serial; /* serial number */ - unsigned short model; /* subsystem id */ - - spinlock_t emu_lock; - - struct snd_ac97 *ac97; - struct snd_pcm *pcm[4]; - - struct snd_ca0106_channel playback_channels[4]; - struct snd_ca0106_channel capture_channels[4]; - u32 spdif_bits[4]; /* s/pdif out default setup */ - u32 spdif_str_bits[4]; /* s/pdif out per-stream setup */ - int spdif_enable; - int capture_source; - int i2c_capture_source; - u8 i2c_capture_volume[4][2]; - int capture_mic_line_in; - - struct snd_dma_buffer buffer; - - struct snd_ca_midi midi; - struct snd_ca_midi midi2; - - u16 spi_dac_reg[16]; - -#ifdef CONFIG_PM -#define NUM_SAVED_VOLUMES 9 - unsigned int saved_vol[NUM_SAVED_VOLUMES]; -#endif -}; - -int snd_ca0106_mixer(struct snd_ca0106 *emu); -int snd_ca0106_proc_init(struct snd_ca0106 * emu); - -unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu, - unsigned int reg, - unsigned int chn); - -void snd_ca0106_ptr_write(struct snd_ca0106 *emu, - unsigned int reg, - unsigned int chn, - unsigned int data); - -int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); - -int snd_ca0106_spi_write(struct snd_ca0106 * emu, - unsigned int data); - -#ifdef CONFIG_PM -void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip); -void snd_ca0106_mixer_resume(struct snd_ca0106 *chip); -#else -#define snd_ca0106_mixer_suspend(chip) do { } while (0) -#define snd_ca0106_mixer_resume(chip) do { } while (0) -#endif diff --git a/ANDROID_3.4.5/sound/pci/ca0106/ca0106_main.c b/ANDROID_3.4.5/sound/pci/ca0106/ca0106_main.c deleted file mode 100644 index 08d6ebfe..00000000 --- a/ANDROID_3.4.5/sound/pci/ca0106/ca0106_main.c +++ /dev/null @@ -1,1959 +0,0 @@ -/* - * Copyright (c) 2004 James Courtier-Dutton - * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit - * Version: 0.0.25 - * - * FEATURES currently supported: - * Front, Rear and Center/LFE. - * Surround40 and Surround51. - * Capture from MIC an LINE IN input. - * SPDIF digital playback of PCM stereo and AC3/DTS works. - * (One can use a standard mono mini-jack to one RCA plugs cable. - * or one can use a standard stereo mini-jack to two RCA plugs cable. - * Plug one of the RCA plugs into the Coax input of the external decoder/receiver.) - * ( In theory one could output 3 different AC3 streams at once, to 3 different SPDIF outputs. ) - * Notes on how to capture sound: - * The AC97 is used in the PLAYBACK direction. - * The output from the AC97 chip, instead of reaching the speakers, is fed into the Philips 1361T ADC. - * So, to record from the MIC, set the MIC Playback volume to max, - * unmute the MIC and turn up the MASTER Playback volume. - * So, to prevent feedback when capturing, minimise the "Capture feedback into Playback" volume. - * - * The only playback controls that currently do anything are: - - * Analog Front - * Analog Rear - * Analog Center/LFE - * SPDIF Front - * SPDIF Rear - * SPDIF Center/LFE - * - * For capture from Mic in or Line in. - * Digital/Analog ( switch must be in Analog mode for CAPTURE. ) - * - * CAPTURE feedback into PLAYBACK - * - * Changelog: - * Support interrupts per period. - * Removed noise from Center/LFE channel when in Analog mode. - * Rename and remove mixer controls. - * 0.0.6 - * Use separate card based DMA buffer for periods table list. - * 0.0.7 - * Change remove and rename ctrls into lists. - * 0.0.8 - * Try to fix capture sources. - * 0.0.9 - * Fix AC3 output. - * Enable S32_LE format support. - * 0.0.10 - * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".) - * 0.0.11 - * Add Model name recognition. - * 0.0.12 - * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period. - * Remove redundent "voice" handling. - * 0.0.13 - * Single trigger call for multi channels. - * 0.0.14 - * Set limits based on what the sound card hardware can do. - * playback periods_min=2, periods_max=8 - * capture hw constraints require period_size = n * 64 bytes. - * playback hw constraints require period_size = n * 64 bytes. - * 0.0.15 - * Minor updates. - * 0.0.16 - * Implement 192000 sample rate. - * 0.0.17 - * Add support for SB0410 and SB0413. - * 0.0.18 - * Modified Copyright message. - * 0.0.19 - * Finally fix support for SB Live 24 bit. SB0410 and SB0413. - * The output codec needs resetting, otherwise all output is muted. - * 0.0.20 - * Merge "pci_disable_device(pci);" fixes. - * 0.0.21 - * Add 4 capture channels. (SPDIF only comes in on channel 0. ) - * Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.) - * 0.0.22 - * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 - * 0.0.23 - * Implement support for Line-in capture on SB Live 24bit. - * 0.0.24 - * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) - * 0.0.25 - * Powerdown SPI DAC channels when not in use - * - * BUGS: - * Some stability problems when unloading the snd-ca0106 kernel module. - * -- - * - * TODO: - * 4 Capture channels, only one implemented so far. - * Other capture rates apart from 48khz not implemented. - * MIDI - * -- - * GENERAL INFO: - * Model: SB0310 - * P17 Chip: CA0106-DAT - * AC97 Codec: STAC 9721 - * ADC: Philips 1361T (Stereo 24bit) - * DAC: WM8746EDS (6-channel, 24bit, 192Khz) - * - * GENERAL INFO: - * Model: SB0410 - * P17 Chip: CA0106-DAT - * AC97 Codec: None - * ADC: WM8775EDS (4 Channel) - * DAC: CS4382 (114 dB, 24-Bit, 192 kHz, 8-Channel D/A Converter with DSD Support) - * SPDIF Out control switches between Mic in and SPDIF out. - * No sound out or mic input working yet. - * - * GENERAL INFO: - * Model: SB0413 - * P17 Chip: CA0106-DAT - * AC97 Codec: None. - * ADC: Unknown - * DAC: Unknown - * Trying to handle it like the SB0410. - * - * This code was initially based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes - * - * 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 -#include -#include -#include - -MODULE_AUTHOR("James Courtier-Dutton "); -MODULE_DESCRIPTION("CA0106"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Creative,SB CA0106 chip}}"); - -// module parameters (see "Module Parameters") -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the CA0106 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the CA0106 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard."); -module_param_array(subsystem, uint, NULL, 0444); -MODULE_PARM_DESC(subsystem, "Force card subsystem model."); - -#include "ca0106.h" - -static struct snd_ca0106_details ca0106_chip_details[] = { - /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ - /* It is really just a normal SB Live 24bit. */ - /* Tested: - * See ALSA bug#3251 - */ - { .serial = 0x10131102, - .name = "X-Fi Extreme Audio [SBxxxx]", - .gpio_type = 1, - .i2c_adc = 1 } , - /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ - /* It is really just a normal SB Live 24bit. */ - /* - * CTRL:CA0111-WTLF - * ADC: WM8775SEDS - * DAC: CS4382-KQZ - */ - /* Tested: - * Playback on front, rear, center/lfe speakers - * Capture from Mic in. - * Not-Tested: - * Capture from Line in. - * Playback to digital out. - */ - { .serial = 0x10121102, - .name = "X-Fi Extreme Audio [SB0790]", - .gpio_type = 1, - .i2c_adc = 1 } , - /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ - /* AudigyLS[SB0310] */ - { .serial = 0x10021102, - .name = "AudigyLS [SB0310]", - .ac97 = 1 } , - /* Unknown AudigyLS that also says SB0310 on it */ - { .serial = 0x10051102, - .name = "AudigyLS [SB0310b]", - .ac97 = 1 } , - /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */ - { .serial = 0x10061102, - .name = "Live! 7.1 24bit [SB0410]", - .gpio_type = 1, - .i2c_adc = 1 } , - /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ - { .serial = 0x10071102, - .name = "Live! 7.1 24bit [SB0413]", - .gpio_type = 1, - .i2c_adc = 1 } , - /* New Audigy SE. Has a different DAC. */ - /* SB0570: - * CTRL:CA0106-DAT - * ADC: WM8775EDS - * DAC: WM8768GEDS - */ - { .serial = 0x100a1102, - .name = "Audigy SE [SB0570]", - .gpio_type = 1, - .i2c_adc = 1, - .spi_dac = 0x4021 } , - /* New Audigy LS. Has a different DAC. */ - /* SB0570: - * CTRL:CA0106-DAT - * ADC: WM8775EDS - * DAC: WM8768GEDS - */ - { .serial = 0x10111102, - .name = "Audigy SE OEM [SB0570a]", - .gpio_type = 1, - .i2c_adc = 1, - .spi_dac = 0x4021 } , - /* Sound Blaster 5.1vx - * Tested: Playback on front, rear, center/lfe speakers - * Not-Tested: Capture - */ - { .serial = 0x10041102, - .name = "Sound Blaster 5.1vx [SB1070]", - .gpio_type = 1, - .i2c_adc = 0, - .spi_dac = 0x0124 - } , - /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ - /* SB0438 - * CTRL:CA0106-DAT - * ADC: WM8775SEDS - * DAC: CS4382-KQZ - */ - { .serial = 0x10091462, - .name = "MSI K8N Diamond MB [SB0438]", - .gpio_type = 2, - .i2c_adc = 1 } , - /* MSI K8N Diamond PLUS MB */ - { .serial = 0x10091102, - .name = "MSI K8N Diamond MB", - .gpio_type = 2, - .i2c_adc = 1, - .spi_dac = 0x4021 } , - /* Giga-byte GA-G1975X mobo - * Novell bnc#395807 - */ - /* FIXME: the GPIO and I2C setting aren't tested well */ - { .serial = 0x1458a006, - .name = "Giga-byte GA-G1975X", - .gpio_type = 1, - .i2c_adc = 1 }, - /* Shuttle XPC SD31P which has an onboard Creative Labs - * Sound Blaster Live! 24-bit EAX - * high-definition 7.1 audio processor". - * Added using info from andrewvegan in alsa bug #1298 - */ - { .serial = 0x30381297, - .name = "Shuttle XPC SD31P [SD31P]", - .gpio_type = 1, - .i2c_adc = 1 } , - /* Shuttle XPC SD11G5 which has an onboard Creative Labs - * Sound Blaster Live! 24-bit EAX - * high-definition 7.1 audio processor". - * Fixes ALSA bug#1600 - */ - { .serial = 0x30411297, - .name = "Shuttle XPC SD11G5 [SD11G5]", - .gpio_type = 1, - .i2c_adc = 1 } , - { .serial = 0, - .name = "AudigyLS [Unknown]" } -}; - -/* hardware definition */ -static struct snd_pcm_hardware snd_ca0106_playback_hw = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000), - .rate_min = 48000, - .rate_max = 192000, - .channels_min = 2, //1, - .channels_max = 2, //6, - .buffer_bytes_max = ((65536 - 64) * 8), - .period_bytes_min = 64, - .period_bytes_max = (65536 - 64), - .periods_min = 2, - .periods_max = 8, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_ca0106_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, -#if 0 /* FIXME: looks like 44.1kHz capture causes noisy output on 48kHz */ - .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), - .rate_min = 44100, -#else - .rates = (SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), - .rate_min = 48000, -#endif /* FIXME */ - .rate_max = 192000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 65536 - 128, - .period_bytes_min = 64, - .period_bytes_max = 32768 - 64, - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu, - unsigned int reg, - unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -void snd_ca0106_ptr_write(struct snd_ca0106 *emu, - unsigned int reg, - unsigned int chn, - unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -int snd_ca0106_spi_write(struct snd_ca0106 * emu, - unsigned int data) -{ - unsigned int reset, set; - unsigned int reg, tmp; - int n, result; - reg = SPI; - if (data > 0xffff) /* Only 16bit values allowed */ - return 1; - tmp = snd_ca0106_ptr_read(emu, reg, 0); - reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */ - set = reset | 0x10000; /* Set xxx1xxxx */ - snd_ca0106_ptr_write(emu, reg, 0, reset | data); - tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */ - snd_ca0106_ptr_write(emu, reg, 0, set | data); - result = 1; - /* Wait for status bit to return to 0 */ - for (n = 0; n < 100; n++) { - udelay(10); - tmp = snd_ca0106_ptr_read(emu, reg, 0); - if (!(tmp & 0x10000)) { - result = 0; - break; - } - } - if (result) /* Timed out */ - return 1; - snd_ca0106_ptr_write(emu, reg, 0, reset | data); - tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */ - return 0; -} - -/* The ADC does not support i2c read, so only write is implemented */ -int snd_ca0106_i2c_write(struct snd_ca0106 *emu, - u32 reg, - u32 value) -{ - u32 tmp; - int timeout = 0; - int status; - int retry; - if ((reg > 0x7f) || (value > 0x1ff)) { - snd_printk(KERN_ERR "i2c_write: invalid values.\n"); - return -EINVAL; - } - - tmp = reg << 25 | value << 16; - /* - snd_printk(KERN_DEBUG "I2C-write:reg=0x%x, value=0x%x\n", reg, value); - */ - /* Not sure what this I2C channel controls. */ - /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ - - /* This controls the I2C connected to the WM8775 ADC Codec */ - snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp); - - for (retry = 0; retry < 10; retry++) { - /* Send the data to i2c */ - //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); - //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); - tmp = 0; - tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); - snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); - - /* Wait till the transaction ends */ - while (1) { - status = snd_ca0106_ptr_read(emu, I2C_A, 0); - /*snd_printk(KERN_DEBUG "I2C:status=0x%x\n", status);*/ - timeout++; - if ((status & I2C_A_ADC_START) == 0) - break; - - if (timeout > 1000) - break; - } - //Read back and see if the transaction is successful - if ((status & I2C_A_ADC_ABORT) == 0) - break; - } - - if (retry == 10) { - snd_printk(KERN_ERR "Writing to ADC failed!\n"); - return -EINVAL; - } - - return 0; -} - - -static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int intr_enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - intr_enable = inl(emu->port + INTE) | intrenb; - outl(intr_enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int intr_enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - intr_enable = inl(emu->port + INTE) & ~intrenb; - outl(intr_enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - - -static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static const int spi_dacd_reg[] = { - SPI_DACD0_REG, - SPI_DACD1_REG, - SPI_DACD2_REG, - 0, - SPI_DACD4_REG, -}; -static const int spi_dacd_bit[] = { - SPI_DACD0_BIT, - SPI_DACD1_BIT, - SPI_DACD2_BIT, - 0, - SPI_DACD4_BIT, -}; - -static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) -{ - if (chip->spdif_str_bits[idx] != chip->spdif_bits[idx]) { - chip->spdif_str_bits[idx] = chip->spdif_bits[idx]; - snd_ca0106_ptr_write(chip, SPCS0 + idx, 0, - chip->spdif_str_bits[idx]); - } -} - -static int snd_ca0106_channel_dac(struct snd_ca0106_details *details, - int channel_id) -{ - switch (channel_id) { - case PCM_FRONT_CHANNEL: - return (details->spi_dac & 0xf000) >> (4 * 3); - case PCM_REAR_CHANNEL: - return (details->spi_dac & 0x0f00) >> (4 * 2); - case PCM_CENTER_LFE_CHANNEL: - return (details->spi_dac & 0x00f0) >> (4 * 1); - case PCM_UNKNOWN_CHANNEL: - return (details->spi_dac & 0x000f) >> (4 * 0); - default: - snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n", - channel_id); - } - return 0; -} - -static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id, - int power) -{ - if (chip->details->spi_dac) { - const int dac = snd_ca0106_channel_dac(chip->details, - channel_id); - const int reg = spi_dacd_reg[dac]; - const int bit = spi_dacd_bit[dac]; - - if (power) - /* Power up */ - chip->spi_dac_reg[reg] &= ~bit; - else - /* Power down */ - chip->spi_dac_reg[reg] |= bit; - return snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); - } - return 0; -} - -/* open_playback callback */ -static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, - int channel_id) -{ - struct snd_ca0106 *chip = snd_pcm_substream_chip(substream); - struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]); - struct snd_ca0106_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - - if (epcm == NULL) - return -ENOMEM; - epcm->emu = chip; - epcm->substream = substream; - epcm->channel_id=channel_id; - - runtime->private_data = epcm; - runtime->private_free = snd_ca0106_pcm_free_substream; - - runtime->hw = snd_ca0106_playback_hw; - - channel->emu = chip; - channel->number = channel_id; - - channel->use = 1; - /* - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", - channel_id, chip, channel); - */ - //channel->interrupt = snd_ca0106_pcm_channel_interrupt; - channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) - return err; - snd_pcm_set_sync(substream); - - /* Front channel dac should already be on */ - if (channel_id != PCM_FRONT_CHANNEL) { - err = snd_ca0106_pcm_power_dac(chip, channel_id, 1); - if (err < 0) - return err; - } - - restore_spdif_bits(chip, channel_id); - - return 0; -} - -/* close callback */ -static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) -{ - struct snd_ca0106 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ca0106_pcm *epcm = runtime->private_data; - chip->playback_channels[epcm->channel_id].use = 0; - - restore_spdif_bits(chip, epcm->channel_id); - - /* Front channel dac should stay on */ - if (epcm->channel_id != PCM_FRONT_CHANNEL) { - int err; - err = snd_ca0106_pcm_power_dac(chip, epcm->channel_id, 0); - if (err < 0) - return err; - } - - /* FIXME: maybe zero others */ - return 0; -} - -static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream) -{ - return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL); -} - -static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream) -{ - return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL); -} - -static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream) -{ - return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL); -} - -static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream) -{ - return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL); -} - -/* open_capture callback */ -static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream, - int channel_id) -{ - struct snd_ca0106 *chip = snd_pcm_substream_chip(substream); - struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]); - struct snd_ca0106_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) { - snd_printk(KERN_ERR "open_capture_channel: failed epcm alloc\n"); - return -ENOMEM; - } - epcm->emu = chip; - epcm->substream = substream; - epcm->channel_id=channel_id; - - runtime->private_data = epcm; - runtime->private_free = snd_ca0106_pcm_free_substream; - - runtime->hw = snd_ca0106_capture_hw; - - channel->emu = chip; - channel->number = channel_id; - - channel->use = 1; - /* - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", - channel_id, chip, channel); - */ - //channel->interrupt = snd_ca0106_pcm_channel_interrupt; - channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes); - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) - return err; - return 0; -} - -/* close callback */ -static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream) -{ - struct snd_ca0106 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ca0106_pcm *epcm = runtime->private_data; - chip->capture_channels[epcm->channel_id].use = 0; - /* FIXME: maybe zero others */ - return 0; -} - -static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream) -{ - return snd_ca0106_pcm_open_capture_channel(substream, 0); -} - -static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream) -{ - return snd_ca0106_pcm_open_capture_channel(substream, 1); -} - -static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream) -{ - return snd_ca0106_pcm_open_capture_channel(substream, 2); -} - -static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream) -{ - return snd_ca0106_pcm_open_capture_channel(substream, 3); -} - -/* hw_params callback */ -static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -/* hw_params callback */ -static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -/* prepare playback callback */ -static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream) -{ - struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ca0106_pcm *epcm = runtime->private_data; - int channel = epcm->channel_id; - u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel)); - u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); - u32 hcfg_mask = HCFG_PLAYBACK_S32_LE; - u32 hcfg_set = 0x00000000; - u32 hcfg; - u32 reg40_mask = 0x30000 << (channel<<1); - u32 reg40_set = 0; - u32 reg40; - /* FIXME: Depending on mixer selection of SPDIF out or not, select the spdif rate or the DAC rate. */ - u32 reg71_mask = 0x03030000 ; /* Global. Set SPDIF rate. We only support 44100 to spdif, not to DAC. */ - u32 reg71_set = 0; - u32 reg71; - int i; - -#if 0 /* debug */ - snd_printk(KERN_DEBUG - "prepare:channel_number=%d, rate=%d, format=0x%x, " - "channels=%d, buffer_size=%ld, period_size=%ld, " - "periods=%u, frames_to_bytes=%d\n", - channel, runtime->rate, runtime->format, - runtime->channels, runtime->buffer_size, - runtime->period_size, runtime->periods, - frames_to_bytes(runtime, 1)); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", - runtime->dma_addr, runtime->dma_area, table_base); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", - emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); -#endif /* debug */ - /* Rate can be set per channel. */ - /* reg40 control host to fifo */ - /* reg71 controls DAC rate. */ - switch (runtime->rate) { - case 44100: - reg40_set = 0x10000 << (channel<<1); - reg71_set = 0x01010000; - break; - case 48000: - reg40_set = 0; - reg71_set = 0; - break; - case 96000: - reg40_set = 0x20000 << (channel<<1); - reg71_set = 0x02020000; - break; - case 192000: - reg40_set = 0x30000 << (channel<<1); - reg71_set = 0x03030000; - break; - default: - reg40_set = 0; - reg71_set = 0; - break; - } - /* Format is a global setting */ - /* FIXME: Only let the first channel accessed set this. */ - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - hcfg_set = 0; - break; - case SNDRV_PCM_FORMAT_S32_LE: - hcfg_set = HCFG_PLAYBACK_S32_LE; - break; - default: - hcfg_set = 0; - break; - } - hcfg = inl(emu->port + HCFG) ; - hcfg = (hcfg & ~hcfg_mask) | hcfg_set; - outl(hcfg, emu->port + HCFG); - reg40 = snd_ca0106_ptr_read(emu, 0x40, 0); - reg40 = (reg40 & ~reg40_mask) | reg40_set; - snd_ca0106_ptr_write(emu, 0x40, 0, reg40); - reg71 = snd_ca0106_ptr_read(emu, 0x71, 0); - reg71 = (reg71 & ~reg71_mask) | reg71_set; - snd_ca0106_ptr_write(emu, 0x71, 0, reg71); - - /* FIXME: Check emu->buffer.size before actually writing to it. */ - for(i=0; i < runtime->periods; i++) { - table_base[i*2] = runtime->dma_addr + (i * period_size_bytes); - table_base[i*2+1] = period_size_bytes << 16; - } - - snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel)); - snd_ca0106_ptr_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); - snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0); - snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); - snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes - /* FIXME test what 0 bytes does. */ - snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes - snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0); - snd_ca0106_ptr_write(emu, 0x07, channel, 0x0); - snd_ca0106_ptr_write(emu, 0x08, channel, 0); - snd_ca0106_ptr_write(emu, PLAYBACK_MUTE, 0x0, 0x0); /* Unmute output */ -#if 0 - snd_ca0106_ptr_write(emu, SPCS0, 0, - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT ); -#endif - - return 0; -} - -/* prepare capture callback */ -static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream) -{ - struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ca0106_pcm *epcm = runtime->private_data; - int channel = epcm->channel_id; - u32 hcfg_mask = HCFG_CAPTURE_S32_LE; - u32 hcfg_set = 0x00000000; - u32 hcfg; - u32 over_sampling=0x2; - u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */ - u32 reg71_set = 0; - u32 reg71; - -#if 0 /* debug */ - snd_printk(KERN_DEBUG - "prepare:channel_number=%d, rate=%d, format=0x%x, " - "channels=%d, buffer_size=%ld, period_size=%ld, " - "periods=%u, frames_to_bytes=%d\n", - channel, runtime->rate, runtime->format, - runtime->channels, runtime->buffer_size, - runtime->period_size, runtime->periods, - frames_to_bytes(runtime, 1)); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", - runtime->dma_addr, runtime->dma_area, table_base); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", - emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); -#endif /* debug */ - /* reg71 controls ADC rate. */ - switch (runtime->rate) { - case 44100: - reg71_set = 0x00004000; - break; - case 48000: - reg71_set = 0; - break; - case 96000: - reg71_set = 0x00008000; - over_sampling=0xa; - break; - case 192000: - reg71_set = 0x0000c000; - over_sampling=0xa; - break; - default: - reg71_set = 0; - break; - } - /* Format is a global setting */ - /* FIXME: Only let the first channel accessed set this. */ - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - hcfg_set = 0; - break; - case SNDRV_PCM_FORMAT_S32_LE: - hcfg_set = HCFG_CAPTURE_S32_LE; - break; - default: - hcfg_set = 0; - break; - } - hcfg = inl(emu->port + HCFG) ; - hcfg = (hcfg & ~hcfg_mask) | hcfg_set; - outl(hcfg, emu->port + HCFG); - reg71 = snd_ca0106_ptr_read(emu, 0x71, 0); - reg71 = (reg71 & ~reg71_mask) | reg71_set; - snd_ca0106_ptr_write(emu, 0x71, 0, reg71); - if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ - snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */ - } - - - /* - printk(KERN_DEBUG - "prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, " - "buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n", - channel, runtime->rate, runtime->format, runtime->channels, - runtime->buffer_size, runtime->period_size, - frames_to_bytes(runtime, 1)); - */ - snd_ca0106_ptr_write(emu, 0x13, channel, 0); - snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); - snd_ca0106_ptr_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes - snd_ca0106_ptr_write(emu, CAPTURE_POINTER, channel, 0); - - return 0; -} - -/* trigger_playback callback */ -static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime; - struct snd_ca0106_pcm *epcm; - int channel; - int result = 0; - struct snd_pcm_substream *s; - u32 basic = 0; - u32 extended = 0; - u32 bits; - int running = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - default: - running = 0; - break; - } - snd_pcm_group_for_each_entry(s, substream) { - if (snd_pcm_substream_chip(s) != emu || - s->stream != SNDRV_PCM_STREAM_PLAYBACK) - continue; - runtime = s->runtime; - epcm = runtime->private_data; - channel = epcm->channel_id; - /* snd_printk(KERN_DEBUG "channel=%d\n", channel); */ - epcm->running = running; - basic |= (0x1 << channel); - extended |= (0x10 << channel); - snd_pcm_trigger_done(s, substream); - } - /* snd_printk(KERN_DEBUG "basic=0x%x, extended=0x%x\n",basic, extended); */ - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0); - bits |= extended; - snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits); - bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0); - bits |= basic; - snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0); - bits &= ~basic; - snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits); - bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0); - bits &= ~extended; - snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits); - break; - default: - result = -EINVAL; - break; - } - return result; -} - -/* trigger_capture callback */ -static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ca0106_pcm *epcm = runtime->private_data; - int channel = epcm->channel_id; - int result = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<running = 0; - break; - default: - result = -EINVAL; - break; - } - return result; -} - -/* pointer_playback callback */ -static snd_pcm_uframes_t -snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream) -{ - struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ca0106_pcm *epcm = runtime->private_data; - unsigned int ptr, prev_ptr; - int channel = epcm->channel_id; - int timeout = 10; - - if (!epcm->running) - return 0; - - prev_ptr = -1; - do { - ptr = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel); - ptr = (ptr >> 3) * runtime->period_size; - ptr += bytes_to_frames(runtime, - snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel)); - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - if (prev_ptr == ptr) - return ptr; - prev_ptr = ptr; - } while (--timeout); - snd_printk(KERN_WARNING "ca0106: unstable DMA pointer!\n"); - return 0; -} - -/* pointer_capture callback */ -static snd_pcm_uframes_t -snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream) -{ - struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ca0106_pcm *epcm = runtime->private_data; - snd_pcm_uframes_t ptr, ptr1, ptr2 = 0; - int channel = epcm->channel_id; - - if (!epcm->running) - return 0; - - ptr1 = snd_ca0106_ptr_read(emu, CAPTURE_POINTER, channel); - ptr2 = bytes_to_frames(runtime, ptr1); - ptr=ptr2; - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - /* - printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " - "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", - ptr1, ptr2, ptr, (int)runtime->buffer_size, - (int)runtime->period_size, (int)runtime->frame_bits, - (int)runtime->rate); - */ - return ptr; -} - -/* operators */ -static struct snd_pcm_ops snd_ca0106_playback_front_ops = { - .open = snd_ca0106_pcm_open_playback_front, - .close = snd_ca0106_pcm_close_playback, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ca0106_pcm_hw_params_playback, - .hw_free = snd_ca0106_pcm_hw_free_playback, - .prepare = snd_ca0106_pcm_prepare_playback, - .trigger = snd_ca0106_pcm_trigger_playback, - .pointer = snd_ca0106_pcm_pointer_playback, -}; - -static struct snd_pcm_ops snd_ca0106_capture_0_ops = { - .open = snd_ca0106_pcm_open_0_capture, - .close = snd_ca0106_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ca0106_pcm_hw_params_capture, - .hw_free = snd_ca0106_pcm_hw_free_capture, - .prepare = snd_ca0106_pcm_prepare_capture, - .trigger = snd_ca0106_pcm_trigger_capture, - .pointer = snd_ca0106_pcm_pointer_capture, -}; - -static struct snd_pcm_ops snd_ca0106_capture_1_ops = { - .open = snd_ca0106_pcm_open_1_capture, - .close = snd_ca0106_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ca0106_pcm_hw_params_capture, - .hw_free = snd_ca0106_pcm_hw_free_capture, - .prepare = snd_ca0106_pcm_prepare_capture, - .trigger = snd_ca0106_pcm_trigger_capture, - .pointer = snd_ca0106_pcm_pointer_capture, -}; - -static struct snd_pcm_ops snd_ca0106_capture_2_ops = { - .open = snd_ca0106_pcm_open_2_capture, - .close = snd_ca0106_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ca0106_pcm_hw_params_capture, - .hw_free = snd_ca0106_pcm_hw_free_capture, - .prepare = snd_ca0106_pcm_prepare_capture, - .trigger = snd_ca0106_pcm_trigger_capture, - .pointer = snd_ca0106_pcm_pointer_capture, -}; - -static struct snd_pcm_ops snd_ca0106_capture_3_ops = { - .open = snd_ca0106_pcm_open_3_capture, - .close = snd_ca0106_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ca0106_pcm_hw_params_capture, - .hw_free = snd_ca0106_pcm_hw_free_capture, - .prepare = snd_ca0106_pcm_prepare_capture, - .trigger = snd_ca0106_pcm_trigger_capture, - .pointer = snd_ca0106_pcm_pointer_capture, -}; - -static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = { - .open = snd_ca0106_pcm_open_playback_center_lfe, - .close = snd_ca0106_pcm_close_playback, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ca0106_pcm_hw_params_playback, - .hw_free = snd_ca0106_pcm_hw_free_playback, - .prepare = snd_ca0106_pcm_prepare_playback, - .trigger = snd_ca0106_pcm_trigger_playback, - .pointer = snd_ca0106_pcm_pointer_playback, -}; - -static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = { - .open = snd_ca0106_pcm_open_playback_unknown, - .close = snd_ca0106_pcm_close_playback, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ca0106_pcm_hw_params_playback, - .hw_free = snd_ca0106_pcm_hw_free_playback, - .prepare = snd_ca0106_pcm_prepare_playback, - .trigger = snd_ca0106_pcm_trigger_playback, - .pointer = snd_ca0106_pcm_pointer_playback, -}; - -static struct snd_pcm_ops snd_ca0106_playback_rear_ops = { - .open = snd_ca0106_pcm_open_playback_rear, - .close = snd_ca0106_pcm_close_playback, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ca0106_pcm_hw_params_playback, - .hw_free = snd_ca0106_pcm_hw_free_playback, - .prepare = snd_ca0106_pcm_prepare_playback, - .trigger = snd_ca0106_pcm_trigger_playback, - .pointer = snd_ca0106_pcm_pointer_playback, -}; - - -static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct snd_ca0106 *emu = ac97->private_data; - unsigned long flags; - unsigned short val; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - val = inw(emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -static void snd_ca0106_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - struct snd_ca0106 *emu = ac97->private_data; - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - outw(val, emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static int snd_ca0106_ac97(struct snd_ca0106 *chip) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_ca0106_ac97_write, - .read = snd_ca0106_ac97_read, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) - return err; - pbus->no_vra = 1; /* we don't need VRA */ - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.scaps = AC97_SCAP_NO_SPDIF; - return snd_ac97_mixer(pbus, &ac97, &chip->ac97); -} - -static void ca0106_stop_chip(struct snd_ca0106 *chip); - -static int snd_ca0106_free(struct snd_ca0106 *chip) -{ - if (chip->res_port != NULL) { - /* avoid access to already used hardware */ - ca0106_stop_chip(chip); - } - if (chip->irq >= 0) - free_irq(chip->irq, chip); - // release the data -#if 1 - if (chip->buffer.area) - snd_dma_free_pages(&chip->buffer); -#endif - - // release the i/o port - release_and_free_resource(chip->res_port); - - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_ca0106_dev_free(struct snd_device *device) -{ - struct snd_ca0106 *chip = device->device_data; - return snd_ca0106_free(chip); -} - -static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) -{ - unsigned int status; - - struct snd_ca0106 *chip = dev_id; - int i; - int mask; - unsigned int stat76; - struct snd_ca0106_channel *pchannel; - - status = inl(chip->port + IPR); - if (! status) - return IRQ_NONE; - - stat76 = snd_ca0106_ptr_read(chip, EXTENDED_INT, 0); - /* - snd_printk(KERN_DEBUG "interrupt status = 0x%08x, stat76=0x%08x\n", - status, stat76); - snd_printk(KERN_DEBUG "ptr=0x%08x\n", - snd_ca0106_ptr_read(chip, PLAYBACK_POINTER, 0)); - */ - mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */ - for(i = 0; i < 4; i++) { - pchannel = &(chip->playback_channels[i]); - if (stat76 & mask) { -/* FIXME: Select the correct substream for period elapsed */ - if(pchannel->use) { - snd_pcm_period_elapsed(pchannel->epcm->substream); - //printk(KERN_INFO "interrupt [%d] used\n", i); - } - } - //printk(KERN_INFO "channel=%p\n",pchannel); - //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number); - mask <<= 1; - } - mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */ - for(i = 0; i < 4; i++) { - pchannel = &(chip->capture_channels[i]); - if (stat76 & mask) { -/* FIXME: Select the correct substream for period elapsed */ - if(pchannel->use) { - snd_pcm_period_elapsed(pchannel->epcm->substream); - //printk(KERN_INFO "interrupt [%d] used\n", i); - } - } - //printk(KERN_INFO "channel=%p\n",pchannel); - //printk(KERN_INFO "interrupt stat76[%d] = %08x, use=%d, channel=%d\n", i, stat76, pchannel->use, pchannel->number); - mask <<= 1; - } - - snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76); - - if (chip->midi.dev_id && - (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) { - if (chip->midi.interrupt) - chip->midi.interrupt(&chip->midi, status); - else - chip->midi.interrupt_disable(&chip->midi, chip->midi.tx_enable | chip->midi.rx_enable); - } - - // acknowledge the interrupt if necessary - outl(status, chip->port+IPR); - - return IRQ_HANDLED; -} - -static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int err; - - err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm); - if (err < 0) - return err; - - pcm->private_data = emu; - - switch (device) { - case 0: - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops); - break; - case 1: - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops); - break; - case 2: - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops); - break; - case 3: - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops); - break; - } - - pcm->info_flags = 0; - strcpy(pcm->name, "CA0106"); - - for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - substream; - substream = substream->next) { - if ((err = snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */ - return err; - } - - for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - substream; - substream = substream->next) { - if ((err = snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - 64*1024, 64*1024)) < 0) - return err; - } - - emu->pcm[device] = pcm; - - return 0; -} - -#define SPI_REG(reg, value) (((reg) << SPI_REG_SHIFT) | (value)) -static unsigned int spi_dac_init[] = { - SPI_REG(SPI_LDA1_REG, SPI_DA_BIT_0dB), /* 0dB dig. attenuation */ - SPI_REG(SPI_RDA1_REG, SPI_DA_BIT_0dB), - SPI_REG(SPI_PL_REG, SPI_PL_BIT_L_L | SPI_PL_BIT_R_R | SPI_IZD_BIT), - SPI_REG(SPI_FMT_REG, SPI_FMT_BIT_I2S | SPI_IWL_BIT_24), - SPI_REG(SPI_LDA2_REG, SPI_DA_BIT_0dB), - SPI_REG(SPI_RDA2_REG, SPI_DA_BIT_0dB), - SPI_REG(SPI_LDA3_REG, SPI_DA_BIT_0dB), - SPI_REG(SPI_RDA3_REG, SPI_DA_BIT_0dB), - SPI_REG(SPI_MASTDA_REG, SPI_DA_BIT_0dB), - SPI_REG(9, 0x00), - SPI_REG(SPI_MS_REG, SPI_DACD0_BIT | SPI_DACD1_BIT | SPI_DACD2_BIT), - SPI_REG(12, 0x00), - SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB), - SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE), - SPI_REG(SPI_DACD4_REG, SPI_DACD4_BIT), -}; - -static unsigned int i2c_adc_init[][2] = { - { 0x17, 0x00 }, /* Reset */ - { 0x07, 0x00 }, /* Timeout */ - { 0x0b, 0x22 }, /* Interface control */ - { 0x0c, 0x22 }, /* Master mode control */ - { 0x0d, 0x08 }, /* Powerdown control */ - { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */ - { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */ - { 0x10, 0x7b }, /* ALC Control 1 */ - { 0x11, 0x00 }, /* ALC Control 2 */ - { 0x12, 0x32 }, /* ALC Control 3 */ - { 0x13, 0x00 }, /* Noise gate control */ - { 0x14, 0xa6 }, /* Limiter control */ - { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */ -}; - -static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) -{ - int ch; - unsigned int def_bits; - - outl(0, chip->port + INTE); - - /* - * Init to 0x02109204 : - * Clock accuracy = 0 (1000ppm) - * Sample Rate = 2 (48kHz) - * Audio Channel = 1 (Left of 2) - * Source Number = 0 (Unspecified) - * Generation Status = 1 (Original for Cat Code 12) - * Cat Code = 12 (Digital Signal Mixer) - * Mode = 0 (Mode 0) - * Emphasis = 0 (None) - * CP = 1 (Copyright unasserted) - * AN = 0 (Audio data) - * P = 0 (Consumer) - */ - def_bits = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; - if (!resume) { - chip->spdif_str_bits[0] = chip->spdif_bits[0] = def_bits; - chip->spdif_str_bits[1] = chip->spdif_bits[1] = def_bits; - chip->spdif_str_bits[2] = chip->spdif_bits[2] = def_bits; - chip->spdif_str_bits[3] = chip->spdif_bits[3] = def_bits; - } - /* Only SPCS1 has been tested */ - snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_str_bits[1]); - snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_str_bits[0]); - snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_str_bits[2]); - snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_str_bits[3]); - - snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000); - snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000); - - /* Write 0x8000 to AC97_REC_GAIN to mute it. */ - outb(AC97_REC_GAIN, chip->port + AC97ADDRESS); - outw(0x8000, chip->port + AC97DATA); -#if 0 /* FIXME: what are these? */ - snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006); - snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006); - snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006); - snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006); -#endif - - /* OSS drivers set this. */ - /* snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); */ - - /* Analog or Digital output */ - snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); - /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. - * Use 0x000f0000 for surround71 - */ - snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); - - chip->spdif_enable = 0; /* Set digital SPDIF output off */ - /*snd_ca0106_ptr_write(chip, 0x45, 0, 0);*/ /* Analogue out */ - /*snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00);*/ /* Digital out */ - - /* goes to 0x40c80000 when doing SPDIF IN/OUT */ - snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); - /* (Mute) CAPTURE feedback into PLAYBACK volume. - * Only lower 16 bits matter. - */ - snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); - /* SPDIF IN Volume */ - snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); - /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */ - snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); - - snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410); - snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676); - snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410); - snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676); - - for (ch = 0; ch < 4; ch++) { - /* Only high 16 bits matter */ - snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); - snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030); -#if 0 /* Mute */ - snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); - snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); - snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); - snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); -#endif - } - if (chip->details->i2c_adc == 1) { - /* Select MIC, Line in, TAD in, AUX in */ - snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); - /* Default to CAPTURE_SOURCE to i2s in */ - if (!resume) - chip->capture_source = 3; - } else if (chip->details->ac97 == 1) { - /* Default to AC97 in */ - snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4); - /* Default to CAPTURE_SOURCE to AC97 in */ - if (!resume) - chip->capture_source = 4; - } else { - /* Select MIC, Line in, TAD in, AUX in */ - snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); - /* Default to Set CAPTURE_SOURCE to i2s in */ - if (!resume) - chip->capture_source = 3; - } - - if (chip->details->gpio_type == 2) { - /* The SB0438 use GPIO differently. */ - /* FIXME: Still need to find out what the other GPIO bits do. - * E.g. For digital spdif out. - */ - outl(0x0, chip->port+GPIO); - /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */ - outl(0x005f5301, chip->port+GPIO); /* Analog */ - } else if (chip->details->gpio_type == 1) { - /* The SB0410 and SB0413 use GPIO differently. */ - /* FIXME: Still need to find out what the other GPIO bits do. - * E.g. For digital spdif out. - */ - outl(0x0, chip->port+GPIO); - /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */ - outl(0x005f5301, chip->port+GPIO); /* Analog */ - } else { - outl(0x0, chip->port+GPIO); - outl(0x005f03a3, chip->port+GPIO); /* Analog */ - /* outl(0x005f02a2, chip->port+GPIO); */ /* SPDIF */ - } - snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */ - - /* outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); */ - /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */ - /* outl(0x00001409, chip->port+HCFG); */ - /* outl(0x00000009, chip->port+HCFG); */ - /* AC97 2.0, Enable outputs. */ - outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); - - if (chip->details->i2c_adc == 1) { - /* The SB0410 and SB0413 use I2C to control ADC. */ - int size, n; - - size = ARRAY_SIZE(i2c_adc_init); - /* snd_printk(KERN_DEBUG "I2C:array size=0x%x\n", size); */ - for (n = 0; n < size; n++) - snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], - i2c_adc_init[n][1]); - for (n = 0; n < 4; n++) { - chip->i2c_capture_volume[n][0] = 0xcf; - chip->i2c_capture_volume[n][1] = 0xcf; - } - chip->i2c_capture_source = 2; /* Line in */ - /* Enable Line-in capture. MIC in currently untested. */ - /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */ - } - - if (chip->details->spi_dac) { - /* The SB0570 use SPI to control DAC. */ - int size, n; - - size = ARRAY_SIZE(spi_dac_init); - for (n = 0; n < size; n++) { - int reg = spi_dac_init[n] >> SPI_REG_SHIFT; - - snd_ca0106_spi_write(chip, spi_dac_init[n]); - if (reg < ARRAY_SIZE(chip->spi_dac_reg)) - chip->spi_dac_reg[reg] = spi_dac_init[n]; - } - - /* Enable front dac only */ - snd_ca0106_pcm_power_dac(chip, PCM_FRONT_CHANNEL, 1); - } -} - -static void ca0106_stop_chip(struct snd_ca0106 *chip) -{ - /* disable interrupts */ - snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0); - outl(0, chip->port + INTE); - snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0); - udelay(1000); - /* disable audio */ - /* outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); */ - outl(0, chip->port + HCFG); - /* FIXME: We need to stop and DMA transfers here. - * But as I am not sure how yet, we cannot from the dma pages. - * So we can fix: snd-malloc: Memory leak? pages not freed = 8 - */ -} - -static int __devinit snd_ca0106_create(int dev, struct snd_card *card, - struct pci_dev *pci, - struct snd_ca0106 **rchip) -{ - struct snd_ca0106 *chip; - struct snd_ca0106_details *c; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_ca0106_dev_free, - }; - - *rchip = NULL; - - err = pci_enable_device(pci); - if (err < 0) - return err; - if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - printk(KERN_ERR "error to set 32bit mask DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - spin_lock_init(&chip->emu_lock); - - chip->port = pci_resource_start(pci, 0); - chip->res_port = request_region(chip->port, 0x20, "snd_ca0106"); - if (!chip->res_port) { - snd_ca0106_free(chip); - printk(KERN_ERR "cannot allocate the port\n"); - return -EBUSY; - } - - if (request_irq(pci->irq, snd_ca0106_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_ca0106_free(chip); - printk(KERN_ERR "cannot grab irq\n"); - return -EBUSY; - } - chip->irq = pci->irq; - - /* This stores the periods table. */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - 1024, &chip->buffer) < 0) { - snd_ca0106_free(chip); - return -ENOMEM; - } - - pci_set_master(pci); - /* read serial */ - pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); - printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", - chip->model, pci->revision, chip->serial); - strcpy(card->driver, "CA0106"); - strcpy(card->shortname, "CA0106"); - - for (c = ca0106_chip_details; c->serial; c++) { - if (subsystem[dev]) { - if (c->serial == subsystem[dev]) - break; - } else if (c->serial == chip->serial) - break; - } - chip->details = c; - if (subsystem[dev]) { - printk(KERN_INFO "snd-ca0106: Sound card name=%s, " - "subsystem=0x%x. Forced to subsystem=0x%x\n", - c->name, chip->serial, subsystem[dev]); - } - - sprintf(card->longname, "%s at 0x%lx irq %i", - c->name, chip->port, chip->irq); - - ca0106_init_chip(chip, 0); - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_ca0106_free(chip); - return err; - } - *rchip = chip; - return 0; -} - - -static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr) -{ - snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr); -} - -static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr) -{ - snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr); -} - -static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx) -{ - return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id), - midi->port + idx, 0); -} - -static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx) -{ - snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data); -} - -static struct snd_card *ca0106_dev_id_card(void *dev_id) -{ - return ((struct snd_ca0106 *)dev_id)->card; -} - -static int ca0106_dev_id_port(void *dev_id) -{ - return ((struct snd_ca0106 *)dev_id)->port; -} - -static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel) -{ - struct snd_ca_midi *midi; - char *name; - int err; - - if (channel == CA0106_MIDI_CHAN_B) { - name = "CA0106 MPU-401 (UART) B"; - midi = &chip->midi2; - midi->tx_enable = INTE_MIDI_TX_B; - midi->rx_enable = INTE_MIDI_RX_B; - midi->ipr_tx = IPR_MIDI_TX_B; - midi->ipr_rx = IPR_MIDI_RX_B; - midi->port = MIDI_UART_B_DATA; - } else { - name = "CA0106 MPU-401 (UART)"; - midi = &chip->midi; - midi->tx_enable = INTE_MIDI_TX_A; - midi->rx_enable = INTE_MIDI_TX_B; - midi->ipr_tx = IPR_MIDI_TX_A; - midi->ipr_rx = IPR_MIDI_RX_A; - midi->port = MIDI_UART_A_DATA; - } - - midi->reset = CA0106_MPU401_RESET; - midi->enter_uart = CA0106_MPU401_ENTER_UART; - midi->ack = CA0106_MPU401_ACK; - - midi->input_avail = CA0106_MIDI_INPUT_AVAIL; - midi->output_ready = CA0106_MIDI_OUTPUT_READY; - - midi->channel = channel; - - midi->interrupt_enable = ca0106_midi_interrupt_enable; - midi->interrupt_disable = ca0106_midi_interrupt_disable; - - midi->read = ca0106_midi_read; - midi->write = ca0106_midi_write; - - midi->get_dev_id_card = ca0106_dev_id_card; - midi->get_dev_id_port = ca0106_dev_id_port; - - midi->dev_id = chip; - - if ((err = ca_midi_init(chip, midi, 0, name)) < 0) - return err; - - return 0; -} - - -static int __devinit snd_ca0106_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_ca0106 *chip; - int i, err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_ca0106_create(dev, card, pci, &chip); - if (err < 0) - goto error; - card->private_data = chip; - - for (i = 0; i < 4; i++) { - err = snd_ca0106_pcm(chip, i); - if (err < 0) - goto error; - } - - if (chip->details->ac97 == 1) { - /* The SB0410 and SB0413 do not have an AC97 chip. */ - err = snd_ca0106_ac97(chip); - if (err < 0) - goto error; - } - err = snd_ca0106_mixer(chip); - if (err < 0) - goto error; - - snd_printdd("ca0106: probe for MIDI channel A ..."); - err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A); - if (err < 0) - goto error; - snd_printdd(" done.\n"); - -#ifdef CONFIG_PROC_FS - snd_ca0106_proc_init(chip); -#endif - - snd_card_set_dev(card, &pci->dev); - - err = snd_card_register(card); - if (err < 0) - goto error; - - pci_set_drvdata(pci, card); - dev++; - return 0; - - error: - snd_card_free(card); - return err; -} - -static void __devexit snd_ca0106_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -#ifdef CONFIG_PM -static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ca0106 *chip = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < 4; i++) - snd_pcm_suspend_all(chip->pcm[i]); - if (chip->details->ac97) - snd_ac97_suspend(chip->ac97); - snd_ca0106_mixer_suspend(chip); - - ca0106_stop_chip(chip); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_ca0106_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ca0106 *chip = card->private_data; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - - if (pci_enable_device(pci) < 0) { - snd_card_disconnect(card); - return -EIO; - } - - pci_set_master(pci); - - ca0106_init_chip(chip, 1); - - if (chip->details->ac97) - snd_ac97_resume(chip->ac97); - snd_ca0106_mixer_resume(chip); - if (chip->details->spi_dac) { - for (i = 0; i < ARRAY_SIZE(chip->spi_dac_reg); i++) - snd_ca0106_spi_write(chip, chip->spi_dac_reg[i]); - } - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -// PCI IDs -static DEFINE_PCI_DEVICE_TABLE(snd_ca0106_ids) = { - { PCI_VDEVICE(CREATIVE, 0x0007), 0 }, /* Audigy LS or Live 24bit */ - { 0, } -}; -MODULE_DEVICE_TABLE(pci, snd_ca0106_ids); - -// pci_driver definition -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_ca0106_ids, - .probe = snd_ca0106_probe, - .remove = __devexit_p(snd_ca0106_remove), -#ifdef CONFIG_PM - .suspend = snd_ca0106_suspend, - .resume = snd_ca0106_resume, -#endif -}; - -// initialization of the module -static int __init alsa_card_ca0106_init(void) -{ - return pci_register_driver(&driver); -} - -// clean up the module -static void __exit alsa_card_ca0106_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_ca0106_init) -module_exit(alsa_card_ca0106_exit) diff --git a/ANDROID_3.4.5/sound/pci/ca0106/ca0106_mixer.c b/ANDROID_3.4.5/sound/pci/ca0106/ca0106_mixer.c deleted file mode 100644 index 84f3f924..00000000 --- a/ANDROID_3.4.5/sound/pci/ca0106/ca0106_mixer.c +++ /dev/null @@ -1,956 +0,0 @@ -/* - * Copyright (c) 2004 James Courtier-Dutton - * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit - * Version: 0.0.18 - * - * FEATURES currently supported: - * See ca0106_main.c for features. - * - * Changelog: - * Support interrupts per period. - * Removed noise from Center/LFE channel when in Analog mode. - * Rename and remove mixer controls. - * 0.0.6 - * Use separate card based DMA buffer for periods table list. - * 0.0.7 - * Change remove and rename ctrls into lists. - * 0.0.8 - * Try to fix capture sources. - * 0.0.9 - * Fix AC3 output. - * Enable S32_LE format support. - * 0.0.10 - * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".) - * 0.0.11 - * Add Model name recognition. - * 0.0.12 - * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period. - * Remove redundent "voice" handling. - * 0.0.13 - * Single trigger call for multi channels. - * 0.0.14 - * Set limits based on what the sound card hardware can do. - * playback periods_min=2, periods_max=8 - * capture hw constraints require period_size = n * 64 bytes. - * playback hw constraints require period_size = n * 64 bytes. - * 0.0.15 - * Separated ca0106.c into separate functional .c files. - * 0.0.16 - * Modified Copyright message. - * 0.0.17 - * Implement Mic and Line in Capture. - * 0.0.18 - * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) - * - * This code was initially based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes - * - * 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 -#include -#include - -#include "ca0106.h" - -static void ca0106_spdif_enable(struct snd_ca0106 *emu) -{ - unsigned int val; - - if (emu->spdif_enable) { - /* Digital */ - snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); - snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); - val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000; - snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val); - val = inl(emu->port + GPIO) & ~0x101; - outl(val, emu->port + GPIO); - - } else { - /* Analog */ - snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); - snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); - val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000; - snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val); - val = inl(emu->port + GPIO) | 0x101; - outl(val, emu->port + GPIO); - } -} - -static void ca0106_set_capture_source(struct snd_ca0106 *emu) -{ - unsigned int val = emu->capture_source; - unsigned int source, mask; - source = (val << 28) | (val << 24) | (val << 20) | (val << 16); - mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff; - snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask); -} - -static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu, - unsigned int val, int force) -{ - unsigned int ngain, ogain; - u32 source; - - snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ - ngain = emu->i2c_capture_volume[val][0]; /* Left */ - ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ - if (force || ngain != ogain) - snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff); - ngain = emu->i2c_capture_volume[val][1]; /* Right */ - ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */ - if (force || ngain != ogain) - snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff); - source = 1 << val; - snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ - emu->i2c_capture_source = val; -} - -static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu) -{ - u32 tmp; - - if (emu->capture_mic_line_in) { - /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */ - tmp = inl(emu->port+GPIO) & ~0x400; - tmp = tmp | 0x400; - outl(tmp, emu->port+GPIO); - /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */ - } else { - /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */ - tmp = inl(emu->port+GPIO) & ~0x400; - outl(tmp, emu->port+GPIO); - /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */ - } -} - -static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) -{ - snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]); -} - -/* - */ -static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); -static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); - -#define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info - -static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = emu->spdif_enable; - return 0; -} - -static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = !!ucontrol->value.integer.value[0]; - change = (emu->spdif_enable != val); - if (change) { - emu->spdif_enable = val; - ca0106_spdif_enable(emu); - } - return change; -} - -static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[6] = { - "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 6; - if (uinfo->value.enumerated.item > 5) - uinfo->value.enumerated.item = 5; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->capture_source; - return 0; -} - -static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.enumerated.item[0] ; - if (val >= 6) - return -EINVAL; - change = (emu->capture_source != val); - if (change) { - emu->capture_source = val; - ca0106_set_capture_source(emu); - } - return change; -} - -static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[6] = { - "Phone", "Mic", "Line in", "Aux" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; - return 0; -} - -static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int source_id; - int change = 0; - /* If the capture source has changed, - * update the capture volume from the cached value - * for the particular source. - */ - source_id = ucontrol->value.enumerated.item[0] ; - if (source_id >= 4) - return -EINVAL; - change = (emu->i2c_capture_source != source_id); - if (change) { - ca0106_set_i2c_capture_source(emu, source_id, 0); - } - return change; -} - -static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { "Side out", "Line in" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { "Line in", "Mic in" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in; - return 0; -} - -static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.enumerated.item[0] ; - if (val > 1) - return -EINVAL; - change = (emu->capture_mic_line_in != val); - if (change) { - emu->capture_mic_line_in = val; - ca0106_set_capture_mic_line_in(emu); - } - return change; -} - -static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Shared Mic/Line in Capture Switch", - .info = snd_ca0106_capture_mic_line_in_info, - .get = snd_ca0106_capture_mic_line_in_get, - .put = snd_ca0106_capture_mic_line_in_put -}; - -static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Shared Line in/Side out Capture Switch", - .info = snd_ca0106_capture_line_in_side_out_info, - .get = snd_ca0106_capture_mic_line_in_get, - .put = snd_ca0106_capture_mic_line_in_put -}; - - -static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static void decode_spdif_bits(unsigned char *status, unsigned int bits) -{ - status[0] = (bits >> 0) & 0xff; - status[1] = (bits >> 8) & 0xff; - status[2] = (bits >> 16) & 0xff; - status[3] = (bits >> 24) & 0xff; -} - -static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - decode_spdif_bits(ucontrol->value.iec958.status, - emu->spdif_bits[idx]); - return 0; -} - -static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - decode_spdif_bits(ucontrol->value.iec958.status, - emu->spdif_str_bits[idx]); - return 0; -} - -static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static unsigned int encode_spdif_bits(unsigned char *status) -{ - return ((unsigned int)status[0] << 0) | - ((unsigned int)status[1] << 8) | - ((unsigned int)status[2] << 16) | - ((unsigned int)status[3] << 24); -} - -static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned int val; - - val = encode_spdif_bits(ucontrol->value.iec958.status); - if (val != emu->spdif_bits[idx]) { - emu->spdif_bits[idx] = val; - /* FIXME: this isn't safe, but needed to keep the compatibility - * with older alsa-lib config - */ - emu->spdif_str_bits[idx] = val; - ca0106_set_spdif_bits(emu, idx); - return 1; - } - return 0; -} - -static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned int val; - - val = encode_spdif_bits(ucontrol->value.iec958.status); - if (val != emu->spdif_str_bits[idx]) { - emu->spdif_str_bits[idx] = val; - ca0106_set_spdif_bits(emu, idx); - return 1; - } - return 0; -} - -static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int value; - int channel_id, reg; - - channel_id = (kcontrol->private_value >> 8) & 0xff; - reg = kcontrol->private_value & 0xff; - - value = snd_ca0106_ptr_read(emu, reg, channel_id); - ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */ - ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */ - return 0; -} - -static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int oval, nval; - int channel_id, reg; - - channel_id = (kcontrol->private_value >> 8) & 0xff; - reg = kcontrol->private_value & 0xff; - - oval = snd_ca0106_ptr_read(emu, reg, channel_id); - nval = ((0xff - ucontrol->value.integer.value[0]) << 24) | - ((0xff - ucontrol->value.integer.value[1]) << 16); - nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) | - ((0xff - ucontrol->value.integer.value[1]) ); - if (oval == nval) - return 0; - snd_ca0106_ptr_write(emu, reg, channel_id, nval); - return 1; -} - -static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - int source_id; - - source_id = kcontrol->private_value; - - ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; - ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; - return 0; -} - -static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int ogain; - unsigned int ngain; - int source_id; - int change = 0; - - source_id = kcontrol->private_value; - ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ - ngain = ucontrol->value.integer.value[0]; - if (ngain > 0xff) - return -EINVAL; - if (ogain != ngain) { - if (emu->i2c_capture_source == source_id) - snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); - emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0]; - change = 1; - } - ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ - ngain = ucontrol->value.integer.value[1]; - if (ngain > 0xff) - return -EINVAL; - if (ogain != ngain) { - if (emu->i2c_capture_source == source_id) - snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1]; - change = 1; - } - - return change; -} - -#define spi_mute_info snd_ctl_boolean_mono_info - -static int spi_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; - unsigned int bit = kcontrol->private_value & SPI_REG_MASK; - - ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit); - return 0; -} - -static int spi_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; - unsigned int bit = kcontrol->private_value & SPI_REG_MASK; - int ret; - - ret = emu->spi_dac_reg[reg] & bit; - if (ucontrol->value.integer.value[0]) { - if (!ret) /* bit already cleared, do nothing */ - return 0; - emu->spi_dac_reg[reg] &= ~bit; - } else { - if (ret) /* bit already set, do nothing */ - return 0; - emu->spi_dac_reg[reg] |= bit; - } - - ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); - return ret ? -EINVAL : 1; -} - -#define CA_VOLUME(xname,chid,reg) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_ca0106_volume_info, \ - .get = snd_ca0106_volume_get, \ - .put = snd_ca0106_volume_put, \ - .tlv = { .p = snd_ca0106_db_scale1 }, \ - .private_value = ((chid) << 8) | (reg) \ -} - -static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { - CA_VOLUME("Analog Front Playback Volume", - CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2), - CA_VOLUME("Analog Rear Playback Volume", - CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2), - CA_VOLUME("Analog Center/LFE Playback Volume", - CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2), - CA_VOLUME("Analog Side Playback Volume", - CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2), - - CA_VOLUME("IEC958 Front Playback Volume", - CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1), - CA_VOLUME("IEC958 Rear Playback Volume", - CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1), - CA_VOLUME("IEC958 Center/LFE Playback Volume", - CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1), - CA_VOLUME("IEC958 Unknown Playback Volume", - CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1), - - CA_VOLUME("CAPTURE feedback Playback Volume", - 1, CAPTURE_CONTROL), - - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .count = 4, - .info = snd_ca0106_spdif_info, - .get = snd_ca0106_spdif_get_mask - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Playback Switch", - .info = snd_ca0106_shared_spdif_info, - .get = snd_ca0106_shared_spdif_get, - .put = snd_ca0106_shared_spdif_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Source Capture Enum", - .info = snd_ca0106_capture_source_info, - .get = snd_ca0106_capture_source_get, - .put = snd_ca0106_capture_source_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Source Capture Enum", - .info = snd_ca0106_i2c_capture_source_info, - .get = snd_ca0106_i2c_capture_source_get, - .put = snd_ca0106_i2c_capture_source_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .count = 4, - .info = snd_ca0106_spdif_info, - .get = snd_ca0106_spdif_get_default, - .put = snd_ca0106_spdif_put_default - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .count = 4, - .info = snd_ca0106_spdif_info, - .get = snd_ca0106_spdif_get_stream, - .put = snd_ca0106_spdif_put_stream - }, -}; - -#define I2C_VOLUME(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_ca0106_i2c_volume_info, \ - .get = snd_ca0106_i2c_volume_get, \ - .put = snd_ca0106_i2c_volume_put, \ - .tlv = { .p = snd_ca0106_db_scale2 }, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = { - I2C_VOLUME("Phone Capture Volume", 0), - I2C_VOLUME("Mic Capture Volume", 1), - I2C_VOLUME("Line in Capture Volume", 2), - I2C_VOLUME("Aux Capture Volume", 3), -}; - -static const int spi_dmute_reg[] = { - SPI_DMUTE0_REG, - SPI_DMUTE1_REG, - SPI_DMUTE2_REG, - 0, - SPI_DMUTE4_REG, -}; -static const int spi_dmute_bit[] = { - SPI_DMUTE0_BIT, - SPI_DMUTE1_BIT, - SPI_DMUTE2_BIT, - 0, - SPI_DMUTE4_BIT, -}; - -static struct snd_kcontrol_new __devinit -snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details, - int channel_id) -{ - struct snd_kcontrol_new spi_switch = {0}; - int reg, bit; - int dac_id; - - spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - spi_switch.info = spi_mute_info; - spi_switch.get = spi_mute_get; - spi_switch.put = spi_mute_put; - - switch (channel_id) { - case PCM_FRONT_CHANNEL: - spi_switch.name = "Analog Front Playback Switch"; - dac_id = (details->spi_dac & 0xf000) >> (4 * 3); - break; - case PCM_REAR_CHANNEL: - spi_switch.name = "Analog Rear Playback Switch"; - dac_id = (details->spi_dac & 0x0f00) >> (4 * 2); - break; - case PCM_CENTER_LFE_CHANNEL: - spi_switch.name = "Analog Center/LFE Playback Switch"; - dac_id = (details->spi_dac & 0x00f0) >> (4 * 1); - break; - case PCM_UNKNOWN_CHANNEL: - spi_switch.name = "Analog Side Playback Switch"; - dac_id = (details->spi_dac & 0x000f) >> (4 * 0); - break; - default: - /* Unused channel */ - spi_switch.name = NULL; - dac_id = 0; - } - reg = spi_dmute_reg[dac_id]; - bit = spi_dmute_bit[dac_id]; - - spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit; - - return spi_switch; -} - -static int __devinit remove_ctl(struct snd_card *card, const char *name) -{ - struct snd_ctl_elem_id id; - memset(&id, 0, sizeof(id)); - strcpy(id.name, name); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_remove_id(card, &id); -} - -static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name) -{ - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - /* FIXME: strcpy is bad. */ - strcpy(sid.name, name); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_find_id(card, &sid); -} - -static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst) -{ - struct snd_kcontrol *kctl = ctl_find(card, src); - if (kctl) { - strcpy(kctl->id.name, dst); - return 0; - } - return -ENOENT; -} - -#define ADD_CTLS(emu, ctls) \ - do { \ - int i, _err; \ - for (i = 0; i < ARRAY_SIZE(ctls); i++) { \ - _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \ - if (_err < 0) \ - return _err; \ - } \ - } while (0) - -static __devinitdata -DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1); - -static char *slave_vols[] __devinitdata = { - "Analog Front Playback Volume", - "Analog Rear Playback Volume", - "Analog Center/LFE Playback Volume", - "Analog Side Playback Volume", - "IEC958 Front Playback Volume", - "IEC958 Rear Playback Volume", - "IEC958 Center/LFE Playback Volume", - "IEC958 Unknown Playback Volume", - "CAPTURE feedback Playback Volume", - NULL -}; - -static char *slave_sws[] __devinitdata = { - "Analog Front Playback Switch", - "Analog Rear Playback Switch", - "Analog Center/LFE Playback Switch", - "Analog Side Playback Switch", - "IEC958 Playback Switch", - NULL -}; - -static void __devinit add_slaves(struct snd_card *card, - struct snd_kcontrol *master, char **list) -{ - for (; *list; list++) { - struct snd_kcontrol *slave = ctl_find(card, *list); - if (slave) - snd_ctl_add_slave(master, slave); - } -} - -int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) -{ - int err; - struct snd_card *card = emu->card; - char **c; - struct snd_kcontrol *vmaster; - static char *ca0106_remove_ctls[] = { - "Master Mono Playback Switch", - "Master Mono Playback Volume", - "3D Control - Switch", - "3D Control Sigmatel - Depth", - "PCM Playback Switch", - "PCM Playback Volume", - "CD Playback Switch", - "CD Playback Volume", - "Phone Playback Switch", - "Phone Playback Volume", - "Video Playback Switch", - "Video Playback Volume", - "Beep Playback Switch", - "Beep Playback Volume", - "Mono Output Select", - "Capture Source", - "Capture Switch", - "Capture Volume", - "External Amplifier", - "Sigmatel 4-Speaker Stereo Playback Switch", - "Surround Phase Inversion Playback Switch", - NULL - }; - static char *ca0106_rename_ctls[] = { - "Master Playback Switch", "Capture Switch", - "Master Playback Volume", "Capture Volume", - "Line Playback Switch", "AC97 Line Capture Switch", - "Line Playback Volume", "AC97 Line Capture Volume", - "Aux Playback Switch", "AC97 Aux Capture Switch", - "Aux Playback Volume", "AC97 Aux Capture Volume", - "Mic Playback Switch", "AC97 Mic Capture Switch", - "Mic Playback Volume", "AC97 Mic Capture Volume", - "Mic Select", "AC97 Mic Select", - "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)", - NULL - }; -#if 1 - for (c = ca0106_remove_ctls; *c; c++) - remove_ctl(card, *c); - for (c = ca0106_rename_ctls; *c; c += 2) - rename_ctl(card, c[0], c[1]); -#endif - - ADD_CTLS(emu, snd_ca0106_volume_ctls); - if (emu->details->i2c_adc == 1) { - ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls); - if (emu->details->gpio_type == 1) - err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); - else /* gpio_type == 2 */ - err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu)); - if (err < 0) - return err; - } - if (emu->details->spi_dac) { - int i; - for (i = 0;; i++) { - struct snd_kcontrol_new ctl; - ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i); - if (!ctl.name) - break; - err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu)); - if (err < 0) - return err; - } - } - - /* Create virtual master controls */ - vmaster = snd_ctl_make_virtual_master("Master Playback Volume", - snd_ca0106_master_db_scale); - if (!vmaster) - return -ENOMEM; - err = snd_ctl_add(card, vmaster); - if (err < 0) - return err; - add_slaves(card, vmaster, slave_vols); - - if (emu->details->spi_dac) { - vmaster = snd_ctl_make_virtual_master("Master Playback Switch", - NULL); - if (!vmaster) - return -ENOMEM; - err = snd_ctl_add(card, vmaster); - if (err < 0) - return err; - add_slaves(card, vmaster, slave_sws); - } - - strcpy(card->mixername, "CA0106"); - return 0; -} - -#ifdef CONFIG_PM -struct ca0106_vol_tbl { - unsigned int channel_id; - unsigned int reg; -}; - -static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = { - { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 }, - { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 }, - { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 }, - { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 }, - { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 }, - { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 }, - { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 }, - { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 }, - { 1, CAPTURE_CONTROL }, -}; - -void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip) -{ - int i; - - /* save volumes */ - for (i = 0; i < NUM_SAVED_VOLUMES; i++) - chip->saved_vol[i] = - snd_ca0106_ptr_read(chip, saved_volumes[i].reg, - saved_volumes[i].channel_id); -} - -void snd_ca0106_mixer_resume(struct snd_ca0106 *chip) -{ - int i; - - for (i = 0; i < NUM_SAVED_VOLUMES; i++) - snd_ca0106_ptr_write(chip, saved_volumes[i].reg, - saved_volumes[i].channel_id, - chip->saved_vol[i]); - - ca0106_spdif_enable(chip); - ca0106_set_capture_source(chip); - ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1); - for (i = 0; i < 4; i++) - ca0106_set_spdif_bits(chip, i); - if (chip->details->i2c_adc) - ca0106_set_capture_mic_line_in(chip); -} -#endif /* CONFIG_PM */ diff --git a/ANDROID_3.4.5/sound/pci/ca0106/ca0106_proc.c b/ANDROID_3.4.5/sound/pci/ca0106/ca0106_proc.c deleted file mode 100644 index c694464b..00000000 --- a/ANDROID_3.4.5/sound/pci/ca0106/ca0106_proc.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright (c) 2004 James Courtier-Dutton - * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit - * Version: 0.0.18 - * - * FEATURES currently supported: - * See ca0106_main.c for features. - * - * Changelog: - * Support interrupts per period. - * Removed noise from Center/LFE channel when in Analog mode. - * Rename and remove mixer controls. - * 0.0.6 - * Use separate card based DMA buffer for periods table list. - * 0.0.7 - * Change remove and rename ctrls into lists. - * 0.0.8 - * Try to fix capture sources. - * 0.0.9 - * Fix AC3 output. - * Enable S32_LE format support. - * 0.0.10 - * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".) - * 0.0.11 - * Add Model name recognition. - * 0.0.12 - * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period. - * Remove redundent "voice" handling. - * 0.0.13 - * Single trigger call for multi channels. - * 0.0.14 - * Set limits based on what the sound card hardware can do. - * playback periods_min=2, periods_max=8 - * capture hw constraints require period_size = n * 64 bytes. - * playback hw constraints require period_size = n * 64 bytes. - * 0.0.15 - * Separate ca0106.c into separate functional .c files. - * 0.0.16 - * Modified Copyright message. - * 0.0.17 - * Add iec958 file in proc file system to show status of SPDIF in. - * 0.0.18 - * Implement support for Line-in capture on SB Live 24bit. - * - * This code was initially based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes - * - * 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 -#include -#include - -#include "ca0106.h" - - -#ifdef CONFIG_PROC_FS - -struct snd_ca0106_category_str { - int val; - const char *name; -}; - -static struct snd_ca0106_category_str snd_ca0106_con_category[] = { - { IEC958_AES1_CON_DAT, "DAT" }, - { IEC958_AES1_CON_VCR, "VCR" }, - { IEC958_AES1_CON_MICROPHONE, "microphone" }, - { IEC958_AES1_CON_SYNTHESIZER, "synthesizer" }, - { IEC958_AES1_CON_RATE_CONVERTER, "rate converter" }, - { IEC958_AES1_CON_MIXER, "mixer" }, - { IEC958_AES1_CON_SAMPLER, "sampler" }, - { IEC958_AES1_CON_PCM_CODER, "PCM coder" }, - { IEC958_AES1_CON_IEC908_CD, "CD" }, - { IEC958_AES1_CON_NON_IEC908_CD, "non-IEC908 CD" }, - { IEC958_AES1_CON_GENERAL, "general" }, -}; - - -static void snd_ca0106_proc_dump_iec958( struct snd_info_buffer *buffer, u32 value) -{ - int i; - u32 status[4]; - status[0] = value & 0xff; - status[1] = (value >> 8) & 0xff; - status[2] = (value >> 16) & 0xff; - status[3] = (value >> 24) & 0xff; - - if (! (status[0] & IEC958_AES0_PROFESSIONAL)) { - /* consumer */ - snd_iprintf(buffer, "Mode: consumer\n"); - snd_iprintf(buffer, "Data: "); - if (!(status[0] & IEC958_AES0_NONAUDIO)) { - snd_iprintf(buffer, "audio\n"); - } else { - snd_iprintf(buffer, "non-audio\n"); - } - snd_iprintf(buffer, "Rate: "); - switch (status[3] & IEC958_AES3_CON_FS) { - case IEC958_AES3_CON_FS_44100: - snd_iprintf(buffer, "44100 Hz\n"); - break; - case IEC958_AES3_CON_FS_48000: - snd_iprintf(buffer, "48000 Hz\n"); - break; - case IEC958_AES3_CON_FS_32000: - snd_iprintf(buffer, "32000 Hz\n"); - break; - default: - snd_iprintf(buffer, "unknown\n"); - break; - } - snd_iprintf(buffer, "Copyright: "); - if (status[0] & IEC958_AES0_CON_NOT_COPYRIGHT) { - snd_iprintf(buffer, "permitted\n"); - } else { - snd_iprintf(buffer, "protected\n"); - } - snd_iprintf(buffer, "Emphasis: "); - if ((status[0] & IEC958_AES0_CON_EMPHASIS) != IEC958_AES0_CON_EMPHASIS_5015) { - snd_iprintf(buffer, "none\n"); - } else { - snd_iprintf(buffer, "50/15us\n"); - } - snd_iprintf(buffer, "Category: "); - for (i = 0; i < ARRAY_SIZE(snd_ca0106_con_category); i++) { - if ((status[1] & IEC958_AES1_CON_CATEGORY) == snd_ca0106_con_category[i].val) { - snd_iprintf(buffer, "%s\n", snd_ca0106_con_category[i].name); - break; - } - } - if (i >= ARRAY_SIZE(snd_ca0106_con_category)) { - snd_iprintf(buffer, "unknown 0x%x\n", status[1] & IEC958_AES1_CON_CATEGORY); - } - snd_iprintf(buffer, "Original: "); - if (status[1] & IEC958_AES1_CON_ORIGINAL) { - snd_iprintf(buffer, "original\n"); - } else { - snd_iprintf(buffer, "1st generation\n"); - } - snd_iprintf(buffer, "Clock: "); - switch (status[3] & IEC958_AES3_CON_CLOCK) { - case IEC958_AES3_CON_CLOCK_1000PPM: - snd_iprintf(buffer, "1000 ppm\n"); - break; - case IEC958_AES3_CON_CLOCK_50PPM: - snd_iprintf(buffer, "50 ppm\n"); - break; - case IEC958_AES3_CON_CLOCK_VARIABLE: - snd_iprintf(buffer, "variable pitch\n"); - break; - default: - snd_iprintf(buffer, "unknown\n"); - break; - } - } else { - snd_iprintf(buffer, "Mode: professional\n"); - snd_iprintf(buffer, "Data: "); - if (!(status[0] & IEC958_AES0_NONAUDIO)) { - snd_iprintf(buffer, "audio\n"); - } else { - snd_iprintf(buffer, "non-audio\n"); - } - snd_iprintf(buffer, "Rate: "); - switch (status[0] & IEC958_AES0_PRO_FS) { - case IEC958_AES0_PRO_FS_44100: - snd_iprintf(buffer, "44100 Hz\n"); - break; - case IEC958_AES0_PRO_FS_48000: - snd_iprintf(buffer, "48000 Hz\n"); - break; - case IEC958_AES0_PRO_FS_32000: - snd_iprintf(buffer, "32000 Hz\n"); - break; - default: - snd_iprintf(buffer, "unknown\n"); - break; - } - snd_iprintf(buffer, "Rate Locked: "); - if (status[0] & IEC958_AES0_PRO_FREQ_UNLOCKED) - snd_iprintf(buffer, "no\n"); - else - snd_iprintf(buffer, "yes\n"); - snd_iprintf(buffer, "Emphasis: "); - switch (status[0] & IEC958_AES0_PRO_EMPHASIS) { - case IEC958_AES0_PRO_EMPHASIS_CCITT: - snd_iprintf(buffer, "CCITT J.17\n"); - break; - case IEC958_AES0_PRO_EMPHASIS_NONE: - snd_iprintf(buffer, "none\n"); - break; - case IEC958_AES0_PRO_EMPHASIS_5015: - snd_iprintf(buffer, "50/15us\n"); - break; - case IEC958_AES0_PRO_EMPHASIS_NOTID: - default: - snd_iprintf(buffer, "unknown\n"); - break; - } - snd_iprintf(buffer, "Stereophonic: "); - if ((status[1] & IEC958_AES1_PRO_MODE) == IEC958_AES1_PRO_MODE_STEREOPHONIC) { - snd_iprintf(buffer, "stereo\n"); - } else { - snd_iprintf(buffer, "not indicated\n"); - } - snd_iprintf(buffer, "Userbits: "); - switch (status[1] & IEC958_AES1_PRO_USERBITS) { - case IEC958_AES1_PRO_USERBITS_192: - snd_iprintf(buffer, "192bit\n"); - break; - case IEC958_AES1_PRO_USERBITS_UDEF: - snd_iprintf(buffer, "user-defined\n"); - break; - default: - snd_iprintf(buffer, "unknown\n"); - break; - } - snd_iprintf(buffer, "Sample Bits: "); - switch (status[2] & IEC958_AES2_PRO_SBITS) { - case IEC958_AES2_PRO_SBITS_20: - snd_iprintf(buffer, "20 bit\n"); - break; - case IEC958_AES2_PRO_SBITS_24: - snd_iprintf(buffer, "24 bit\n"); - break; - case IEC958_AES2_PRO_SBITS_UDEF: - snd_iprintf(buffer, "user defined\n"); - break; - default: - snd_iprintf(buffer, "unknown\n"); - break; - } - snd_iprintf(buffer, "Word Length: "); - switch (status[2] & IEC958_AES2_PRO_WORDLEN) { - case IEC958_AES2_PRO_WORDLEN_22_18: - snd_iprintf(buffer, "22 bit or 18 bit\n"); - break; - case IEC958_AES2_PRO_WORDLEN_23_19: - snd_iprintf(buffer, "23 bit or 19 bit\n"); - break; - case IEC958_AES2_PRO_WORDLEN_24_20: - snd_iprintf(buffer, "24 bit or 20 bit\n"); - break; - case IEC958_AES2_PRO_WORDLEN_20_16: - snd_iprintf(buffer, "20 bit or 16 bit\n"); - break; - default: - snd_iprintf(buffer, "unknown\n"); - break; - } - } -} - -static void snd_ca0106_proc_iec958(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - u32 value; - - value = snd_ca0106_ptr_read(emu, SAMPLE_RATE_TRACKER_STATUS, 0); - snd_iprintf(buffer, "Status: %s, %s, %s\n", - (value & 0x100000) ? "Rate Locked" : "Not Rate Locked", - (value & 0x200000) ? "SPDIF Locked" : "No SPDIF Lock", - (value & 0x400000) ? "Audio Valid" : "No valid audio" ); - snd_iprintf(buffer, "Estimated sample rate: %u\n", - ((value & 0xfffff) * 48000) / 0x8000 ); - if (value & 0x200000) { - snd_iprintf(buffer, "IEC958/SPDIF input status:\n"); - value = snd_ca0106_ptr_read(emu, SPDIF_INPUT_STATUS, 0); - snd_ca0106_proc_dump_iec958(buffer, value); - } - - snd_iprintf(buffer, "\n"); -} - -static void snd_ca0106_proc_reg_write32(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - unsigned long flags; - char line[64]; - u32 reg, val; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x", ®, &val) != 2) - continue; - if (reg < 0x40 && val <= 0xffffffff) { - spin_lock_irqsave(&emu->emu_lock, flags); - outl(val, emu->port + (reg & 0xfffffffc)); - spin_unlock_irqrestore(&emu->emu_lock, flags); - } - } -} - -static void snd_ca0106_proc_reg_read32(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - unsigned long value; - unsigned long flags; - int i; - snd_iprintf(buffer, "Registers:\n\n"); - for(i = 0; i < 0x20; i+=4) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inl(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "Register %02X: %08lX\n", i, value); - } -} - -static void snd_ca0106_proc_reg_read16(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - unsigned int value; - unsigned long flags; - int i; - snd_iprintf(buffer, "Registers:\n\n"); - for(i = 0; i < 0x20; i+=2) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inw(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "Register %02X: %04X\n", i, value); - } -} - -static void snd_ca0106_proc_reg_read8(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - unsigned int value; - unsigned long flags; - int i; - snd_iprintf(buffer, "Registers:\n\n"); - for(i = 0; i < 0x20; i+=1) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inb(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "Register %02X: %02X\n", i, value); - } -} - -static void snd_ca0106_proc_reg_read1(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - unsigned long value; - int i,j; - - snd_iprintf(buffer, "Registers\n"); - for(i = 0; i < 0x40; i++) { - snd_iprintf(buffer, "%02X: ",i); - for (j = 0; j < 4; j++) { - value = snd_ca0106_ptr_read(emu, i, j); - snd_iprintf(buffer, "%08lX ", value); - } - snd_iprintf(buffer, "\n"); - } -} - -static void snd_ca0106_proc_reg_read2(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - unsigned long value; - int i,j; - - snd_iprintf(buffer, "Registers\n"); - for(i = 0x40; i < 0x80; i++) { - snd_iprintf(buffer, "%02X: ",i); - for (j = 0; j < 4; j++) { - value = snd_ca0106_ptr_read(emu, i, j); - snd_iprintf(buffer, "%08lX ", value); - } - snd_iprintf(buffer, "\n"); - } -} - -static void snd_ca0106_proc_reg_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - char line[64]; - unsigned int reg, channel_id , val; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x %x", ®, &channel_id, &val) != 3) - continue; - if (reg < 0x80 && val <= 0xffffffff && channel_id <= 3) - snd_ca0106_ptr_write(emu, reg, channel_id, val); - } -} - -static void snd_ca0106_proc_i2c_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ca0106 *emu = entry->private_data; - char line[64]; - unsigned int reg, val; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x", ®, &val) != 2) - continue; - if ((reg <= 0x7f) || (val <= 0x1ff)) { - snd_ca0106_i2c_write(emu, reg, val); - } - } -} - -int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu) -{ - struct snd_info_entry *entry; - - if(! snd_card_proc_new(emu->card, "iec958", &entry)) - snd_info_set_text_ops(entry, emu, snd_ca0106_proc_iec958); - if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) { - snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read32); - entry->c.text.write = snd_ca0106_proc_reg_write32; - entry->mode |= S_IWUSR; - } - if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) - snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read16); - if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry)) - snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read8); - if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) { - snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1); - entry->c.text.write = snd_ca0106_proc_reg_write; - entry->mode |= S_IWUSR; - } - if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { - entry->c.text.write = snd_ca0106_proc_i2c_write; - entry->private_data = emu; - entry->mode |= S_IWUSR; - } - if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) - snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2); - return 0; -} - -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/pci/ca0106/ca_midi.c b/ANDROID_3.4.5/sound/pci/ca0106/ca_midi.c deleted file mode 100644 index c7885117..00000000 --- a/ANDROID_3.4.5/sound/pci/ca0106/ca_midi.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright 10/16/2005 Tilman Kranz - * Creative Audio MIDI, for the CA0106 Driver - * Version: 0.0.1 - * - * Changelog: - * Implementation is based on mpu401 and emu10k1x and - * tested with ca0106. - * mpu401: Copyright (c) by Jaroslav Kysela - * emu10k1x: Copyright (c) by Francisco Moraes - * - * 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 "ca_midi.h" - -#define ca_midi_write_data(midi, data) midi->write(midi, data, 0) -#define ca_midi_write_cmd(midi, data) midi->write(midi, data, 1) -#define ca_midi_read_data(midi) midi->read(midi, 0) -#define ca_midi_read_stat(midi) midi->read(midi, 1) -#define ca_midi_input_avail(midi) (!(ca_midi_read_stat(midi) & midi->input_avail)) -#define ca_midi_output_ready(midi) (!(ca_midi_read_stat(midi) & midi->output_ready)) - -static void ca_midi_clear_rx(struct snd_ca_midi *midi) -{ - int timeout = 100000; - for (; timeout > 0 && ca_midi_input_avail(midi); timeout--) - ca_midi_read_data(midi); -#ifdef CONFIG_SND_DEBUG - if (timeout <= 0) - snd_printk(KERN_ERR "ca_midi_clear_rx: timeout (status = 0x%x)\n", - ca_midi_read_stat(midi)); -#endif -} - -static void ca_midi_interrupt(struct snd_ca_midi *midi, unsigned int status) -{ - unsigned char byte; - - if (midi->rmidi == NULL) { - midi->interrupt_disable(midi,midi->tx_enable | midi->rx_enable); - return; - } - - spin_lock(&midi->input_lock); - if ((status & midi->ipr_rx) && ca_midi_input_avail(midi)) { - if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { - ca_midi_clear_rx(midi); - } else { - byte = ca_midi_read_data(midi); - if(midi->substream_input) - snd_rawmidi_receive(midi->substream_input, &byte, 1); - - - } - } - spin_unlock(&midi->input_lock); - - spin_lock(&midi->output_lock); - if ((status & midi->ipr_tx) && ca_midi_output_ready(midi)) { - if (midi->substream_output && - snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { - ca_midi_write_data(midi, byte); - } else { - midi->interrupt_disable(midi,midi->tx_enable); - } - } - spin_unlock(&midi->output_lock); - -} - -static void ca_midi_cmd(struct snd_ca_midi *midi, unsigned char cmd, int ack) -{ - unsigned long flags; - int timeout, ok; - - spin_lock_irqsave(&midi->input_lock, flags); - ca_midi_write_data(midi, 0x00); - /* ca_midi_clear_rx(midi); */ - - ca_midi_write_cmd(midi, cmd); - if (ack) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (ca_midi_input_avail(midi)) { - if (ca_midi_read_data(midi) == midi->ack) - ok = 1; - } - } - if (!ok && ca_midi_read_data(midi) == midi->ack) - ok = 1; - } else { - ok = 1; - } - spin_unlock_irqrestore(&midi->input_lock, flags); - if (!ok) - snd_printk(KERN_ERR "ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n", - cmd, - midi->get_dev_id_port(midi->dev_id), - ca_midi_read_stat(midi), - ca_midi_read_data(midi)); -} - -static int ca_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - if (snd_BUG_ON(!midi->dev_id)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= CA_MIDI_MODE_INPUT; - midi->substream_input = substream; - if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - ca_midi_cmd(midi, midi->reset, 1); - ca_midi_cmd(midi, midi->enter_uart, 1); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; -} - -static int ca_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - if (snd_BUG_ON(!midi->dev_id)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= CA_MIDI_MODE_OUTPUT; - midi->substream_output = substream; - if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - ca_midi_cmd(midi, midi->reset, 1); - ca_midi_cmd(midi, midi->enter_uart, 1); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; -} - -static int ca_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - if (snd_BUG_ON(!midi->dev_id)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->interrupt_disable(midi,midi->rx_enable); - midi->midi_mode &= ~CA_MIDI_MODE_INPUT; - midi->substream_input = NULL; - if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - ca_midi_cmd(midi, midi->reset, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; -} - -static int ca_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - if (snd_BUG_ON(!midi->dev_id)) - return -ENXIO; - - spin_lock_irqsave(&midi->open_lock, flags); - - midi->interrupt_disable(midi,midi->tx_enable); - midi->midi_mode &= ~CA_MIDI_MODE_OUTPUT; - midi->substream_output = NULL; - - if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - ca_midi_cmd(midi, midi->reset, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; -} - -static void ca_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_ca_midi *midi = substream->rmidi->private_data; - - if (snd_BUG_ON(!midi->dev_id)) - return; - - if (up) { - midi->interrupt_enable(midi,midi->rx_enable); - } else { - midi->interrupt_disable(midi, midi->rx_enable); - } -} - -static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_ca_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - if (snd_BUG_ON(!midi->dev_id)) - return; - - if (up) { - int max = 4; - unsigned char byte; - - spin_lock_irqsave(&midi->output_lock, flags); - - /* try to send some amount of bytes here before interrupts */ - while (max > 0) { - if (ca_midi_output_ready(midi)) { - if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT) || - snd_rawmidi_transmit(substream, &byte, 1) != 1) { - /* no more data */ - spin_unlock_irqrestore(&midi->output_lock, flags); - return; - } - ca_midi_write_data(midi, byte); - max--; - } else { - break; - } - } - - spin_unlock_irqrestore(&midi->output_lock, flags); - midi->interrupt_enable(midi,midi->tx_enable); - - } else { - midi->interrupt_disable(midi,midi->tx_enable); - } -} - -static struct snd_rawmidi_ops ca_midi_output = -{ - .open = ca_midi_output_open, - .close = ca_midi_output_close, - .trigger = ca_midi_output_trigger, -}; - -static struct snd_rawmidi_ops ca_midi_input = -{ - .open = ca_midi_input_open, - .close = ca_midi_input_close, - .trigger = ca_midi_input_trigger, -}; - -static void ca_midi_free(struct snd_ca_midi *midi) -{ - midi->interrupt = NULL; - midi->interrupt_enable = NULL; - midi->interrupt_disable = NULL; - midi->read = NULL; - midi->write = NULL; - midi->get_dev_id_card = NULL; - midi->get_dev_id_port = NULL; - midi->rmidi = NULL; -} - -static void ca_rmidi_free(struct snd_rawmidi *rmidi) -{ - ca_midi_free(rmidi->private_data); -} - -int __devinit ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name) -{ - struct snd_rawmidi *rmidi; - int err; - - if ((err = snd_rawmidi_new(midi->get_dev_id_card(midi->dev_id), name, device, 1, 1, &rmidi)) < 0) - return err; - - midi->dev_id = dev_id; - midi->interrupt = ca_midi_interrupt; - - spin_lock_init(&midi->open_lock); - spin_lock_init(&midi->input_lock); - spin_lock_init(&midi->output_lock); - - strcpy(rmidi->name, name); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &ca_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &ca_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = midi; - rmidi->private_free = ca_rmidi_free; - - midi->rmidi = rmidi; - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pci/ca0106/ca_midi.h b/ANDROID_3.4.5/sound/pci/ca0106/ca_midi.h deleted file mode 100644 index 922ed3e3..00000000 --- a/ANDROID_3.4.5/sound/pci/ca0106/ca_midi.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 10/16/2005 Tilman Kranz - * Creative Audio MIDI, for the CA0106 Driver - * Version: 0.0.1 - * - * Changelog: - * See ca_midi.c - * - * 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 - -#define CA_MIDI_MODE_INPUT MPU401_MODE_INPUT -#define CA_MIDI_MODE_OUTPUT MPU401_MODE_OUTPUT - -struct snd_ca_midi { - - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream_input; - struct snd_rawmidi_substream *substream_output; - - void *dev_id; - - spinlock_t input_lock; - spinlock_t output_lock; - spinlock_t open_lock; - - unsigned int channel; - - unsigned int midi_mode; - int port; - int tx_enable, rx_enable; - int ipr_tx, ipr_rx; - - int input_avail, output_ready; - int ack, reset, enter_uart; - - void (*interrupt)(struct snd_ca_midi *midi, unsigned int status); - void (*interrupt_enable)(struct snd_ca_midi *midi, int intr); - void (*interrupt_disable)(struct snd_ca_midi *midi, int intr); - - unsigned char (*read)(struct snd_ca_midi *midi, int idx); - void (*write)(struct snd_ca_midi *midi, int data, int idx); - - /* get info from dev_id */ - struct snd_card *(*get_dev_id_card)(void *dev_id); - int (*get_dev_id_port)(void *dev_id); -}; - -int ca_midi_init(void *card, struct snd_ca_midi *midi, int device, char *name); diff --git a/ANDROID_3.4.5/sound/pci/cmipci.c b/ANDROID_3.4.5/sound/pci/cmipci.c deleted file mode 100644 index 19b06269..00000000 --- a/ANDROID_3.4.5/sound/pci/cmipci.c +++ /dev/null @@ -1,3423 +0,0 @@ -/* - * Driver for C-Media CMI8338 and 8738 PCI soundcards. - * Copyright (c) 2000 by Takashi Iwai - * - * 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 - */ - -/* Does not work. Warning may block system in capture mode */ -/* #define USE_VAR48KRATE */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("C-Media CMI8x38 PCI"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8738}," - "{C-Media,CMI8738B}," - "{C-Media,CMI8338A}," - "{C-Media,CMI8338B}}"); - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ -static long mpu_port[SNDRV_CARDS]; -static long fm_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1}; -static bool soft_ac3[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1}; -#ifdef SUPPORT_JOYSTICK -static int joystick_port[SNDRV_CARDS]; -#endif - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for C-Media PCI soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for C-Media PCI soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable C-Media PCI soundcard."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port."); -module_param_array(soft_ac3, bool, NULL, 0444); -MODULE_PARM_DESC(soft_ac3, "Software-conversion of raw SPDIF packets (model 033 only)."); -#ifdef SUPPORT_JOYSTICK -module_param_array(joystick_port, int, NULL, 0444); -MODULE_PARM_DESC(joystick_port, "Joystick port address."); -#endif - -/* - * CM8x38 registers definition - */ - -#define CM_REG_FUNCTRL0 0x00 -#define CM_RST_CH1 0x00080000 -#define CM_RST_CH0 0x00040000 -#define CM_CHEN1 0x00020000 /* ch1: enable */ -#define CM_CHEN0 0x00010000 /* ch0: enable */ -#define CM_PAUSE1 0x00000008 /* ch1: pause */ -#define CM_PAUSE0 0x00000004 /* ch0: pause */ -#define CM_CHADC1 0x00000002 /* ch1, 0:playback, 1:record */ -#define CM_CHADC0 0x00000001 /* ch0, 0:playback, 1:record */ - -#define CM_REG_FUNCTRL1 0x04 -#define CM_DSFC_MASK 0x0000E000 /* channel 1 (DAC?) sampling frequency */ -#define CM_DSFC_SHIFT 13 -#define CM_ASFC_MASK 0x00001C00 /* channel 0 (ADC?) sampling frequency */ -#define CM_ASFC_SHIFT 10 -#define CM_SPDF_1 0x00000200 /* SPDIF IN/OUT at channel B */ -#define CM_SPDF_0 0x00000100 /* SPDIF OUT only channel A */ -#define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/IN -> OUT loopback */ -#define CM_SPDO2DAC 0x00000040 /* SPDIF/OUT can be heard from internal DAC */ -#define CM_INTRM 0x00000020 /* master control block (MCB) interrupt enabled */ -#define CM_BREQ 0x00000010 /* bus master enabled */ -#define CM_VOICE_EN 0x00000008 /* legacy voice (SB16,FM) */ -#define CM_UART_EN 0x00000004 /* legacy UART */ -#define CM_JYSTK_EN 0x00000002 /* legacy joystick */ -#define CM_ZVPORT 0x00000001 /* ZVPORT */ - -#define CM_REG_CHFORMAT 0x08 - -#define CM_CHB3D5C 0x80000000 /* 5,6 channels */ -#define CM_FMOFFSET2 0x40000000 /* initial FM PCM offset 2 when Fmute=1 */ -#define CM_CHB3D 0x20000000 /* 4 channels */ - -#define CM_CHIP_MASK1 0x1f000000 -#define CM_CHIP_037 0x01000000 -#define CM_SETLAT48 0x00800000 /* set latency timer 48h */ -#define CM_EDGEIRQ 0x00400000 /* emulated edge trigger legacy IRQ */ -#define CM_SPD24SEL39 0x00200000 /* 24-bit spdif: model 039 */ -#define CM_AC3EN1 0x00100000 /* enable AC3: model 037 */ -#define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */ -#define CM_SPD24SEL 0x00020000 /* 24bit spdif: model 037 */ -/* #define CM_SPDIF_INVERSE 0x00010000 */ /* ??? */ - -#define CM_ADCBITLEN_MASK 0x0000C000 -#define CM_ADCBITLEN_16 0x00000000 -#define CM_ADCBITLEN_15 0x00004000 -#define CM_ADCBITLEN_14 0x00008000 -#define CM_ADCBITLEN_13 0x0000C000 - -#define CM_ADCDACLEN_MASK 0x00003000 /* model 037 */ -#define CM_ADCDACLEN_060 0x00000000 -#define CM_ADCDACLEN_066 0x00001000 -#define CM_ADCDACLEN_130 0x00002000 -#define CM_ADCDACLEN_280 0x00003000 - -#define CM_ADCDLEN_MASK 0x00003000 /* model 039 */ -#define CM_ADCDLEN_ORIGINAL 0x00000000 -#define CM_ADCDLEN_EXTRA 0x00001000 -#define CM_ADCDLEN_24K 0x00002000 -#define CM_ADCDLEN_WEIGHT 0x00003000 - -#define CM_CH1_SRATE_176K 0x00000800 -#define CM_CH1_SRATE_96K 0x00000800 /* model 055? */ -#define CM_CH1_SRATE_88K 0x00000400 -#define CM_CH0_SRATE_176K 0x00000200 -#define CM_CH0_SRATE_96K 0x00000200 /* model 055? */ -#define CM_CH0_SRATE_88K 0x00000100 -#define CM_CH0_SRATE_128K 0x00000300 -#define CM_CH0_SRATE_MASK 0x00000300 - -#define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */ -#define CM_DBLSPDS 0x00000040 /* double SPDIF sample rate 88.2/96 */ -#define CM_POLVALID 0x00000020 /* inverse SPDIF/IN valid bit */ -#define CM_SPDLOCKED 0x00000010 - -#define CM_CH1FMT_MASK 0x0000000C /* bit 3: 16 bits, bit 2: stereo */ -#define CM_CH1FMT_SHIFT 2 -#define CM_CH0FMT_MASK 0x00000003 /* bit 1: 16 bits, bit 0: stereo */ -#define CM_CH0FMT_SHIFT 0 - -#define CM_REG_INT_HLDCLR 0x0C -#define CM_CHIP_MASK2 0xff000000 -#define CM_CHIP_8768 0x20000000 -#define CM_CHIP_055 0x08000000 -#define CM_CHIP_039 0x04000000 -#define CM_CHIP_039_6CH 0x01000000 -#define CM_UNKNOWN_INT_EN 0x00080000 /* ? */ -#define CM_TDMA_INT_EN 0x00040000 -#define CM_CH1_INT_EN 0x00020000 -#define CM_CH0_INT_EN 0x00010000 - -#define CM_REG_INT_STATUS 0x10 -#define CM_INTR 0x80000000 -#define CM_VCO 0x08000000 /* Voice Control? CMI8738 */ -#define CM_MCBINT 0x04000000 /* Master Control Block abort cond.? */ -#define CM_UARTINT 0x00010000 -#define CM_LTDMAINT 0x00008000 -#define CM_HTDMAINT 0x00004000 -#define CM_XDO46 0x00000080 /* Modell 033? Direct programming EEPROM (read data register) */ -#define CM_LHBTOG 0x00000040 /* High/Low status from DMA ctrl register */ -#define CM_LEG_HDMA 0x00000020 /* Legacy is in High DMA channel */ -#define CM_LEG_STEREO 0x00000010 /* Legacy is in Stereo mode */ -#define CM_CH1BUSY 0x00000008 -#define CM_CH0BUSY 0x00000004 -#define CM_CHINT1 0x00000002 -#define CM_CHINT0 0x00000001 - -#define CM_REG_LEGACY_CTRL 0x14 -#define CM_NXCHG 0x80000000 /* don't map base reg dword->sample */ -#define CM_VMPU_MASK 0x60000000 /* MPU401 i/o port address */ -#define CM_VMPU_330 0x00000000 -#define CM_VMPU_320 0x20000000 -#define CM_VMPU_310 0x40000000 -#define CM_VMPU_300 0x60000000 -#define CM_ENWR8237 0x10000000 /* enable bus master to write 8237 base reg */ -#define CM_VSBSEL_MASK 0x0C000000 /* SB16 base address */ -#define CM_VSBSEL_220 0x00000000 -#define CM_VSBSEL_240 0x04000000 -#define CM_VSBSEL_260 0x08000000 -#define CM_VSBSEL_280 0x0C000000 -#define CM_FMSEL_MASK 0x03000000 /* FM OPL3 base address */ -#define CM_FMSEL_388 0x00000000 -#define CM_FMSEL_3C8 0x01000000 -#define CM_FMSEL_3E0 0x02000000 -#define CM_FMSEL_3E8 0x03000000 -#define CM_ENSPDOUT 0x00800000 /* enable XSPDIF/OUT to I/O interface */ -#define CM_SPDCOPYRHT 0x00400000 /* spdif in/out copyright bit */ -#define CM_DAC2SPDO 0x00200000 /* enable wave+fm_midi -> SPDIF/OUT */ -#define CM_INVIDWEN 0x00100000 /* internal vendor ID write enable, model 039? */ -#define CM_SETRETRY 0x00100000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */ -#define CM_C_EEACCESS 0x00080000 /* direct programming eeprom regs */ -#define CM_C_EECS 0x00040000 -#define CM_C_EEDI46 0x00020000 -#define CM_C_EECK46 0x00010000 -#define CM_CHB3D6C 0x00008000 /* 5.1 channels support */ -#define CM_CENTR2LIN 0x00004000 /* line-in as center out */ -#define CM_BASE2LIN 0x00002000 /* line-in as bass out */ -#define CM_EXBASEN 0x00001000 /* external bass input enable */ - -#define CM_REG_MISC_CTRL 0x18 -#define CM_PWD 0x80000000 /* power down */ -#define CM_RESET 0x40000000 -#define CM_SFIL_MASK 0x30000000 /* filter control at front end DAC, model 037? */ -#define CM_VMGAIN 0x10000000 /* analog master amp +6dB, model 039? */ -#define CM_TXVX 0x08000000 /* model 037? */ -#define CM_N4SPK3D 0x04000000 /* copy front to rear */ -#define CM_SPDO5V 0x02000000 /* 5V spdif output (1 = 0.5v (coax)) */ -#define CM_SPDIF48K 0x01000000 /* write */ -#define CM_SPATUS48K 0x01000000 /* read */ -#define CM_ENDBDAC 0x00800000 /* enable double dac */ -#define CM_XCHGDAC 0x00400000 /* 0: front=ch0, 1: front=ch1 */ -#define CM_SPD32SEL 0x00200000 /* 0: 16bit SPDIF, 1: 32bit */ -#define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-OUT -> int. IN */ -#define CM_FM_EN 0x00080000 /* enable legacy FM */ -#define CM_AC3EN2 0x00040000 /* enable AC3: model 039 */ -#define CM_ENWRASID 0x00010000 /* choose writable internal SUBID (audio) */ -#define CM_VIDWPDSB 0x00010000 /* model 037? */ -#define CM_SPDF_AC97 0x00008000 /* 0: SPDIF/OUT 44.1K, 1: 48K */ -#define CM_MASK_EN 0x00004000 /* activate channel mask on legacy DMA */ -#define CM_ENWRMSID 0x00002000 /* choose writable internal SUBID (modem) */ -#define CM_VIDWPPRT 0x00002000 /* model 037? */ -#define CM_SFILENB 0x00001000 /* filter stepping at front end DAC, model 037? */ -#define CM_MMODE_MASK 0x00000E00 /* model DAA interface mode */ -#define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */ -#define CM_ENCENTER 0x00000080 -#define CM_FLINKON 0x00000040 /* force modem link detection on, model 037 */ -#define CM_MUTECH1 0x00000040 /* mute PCI ch1 to DAC */ -#define CM_FLINKOFF 0x00000020 /* force modem link detection off, model 037 */ -#define CM_MIDSMP 0x00000010 /* 1/2 interpolation at front end DAC */ -#define CM_UPDDMA_MASK 0x0000000C /* TDMA position update notification */ -#define CM_UPDDMA_2048 0x00000000 -#define CM_UPDDMA_1024 0x00000004 -#define CM_UPDDMA_512 0x00000008 -#define CM_UPDDMA_256 0x0000000C -#define CM_TWAIT_MASK 0x00000003 /* model 037 */ -#define CM_TWAIT1 0x00000002 /* FM i/o cycle, 0: 48, 1: 64 PCICLKs */ -#define CM_TWAIT0 0x00000001 /* i/o cycle, 0: 4, 1: 6 PCICLKs */ - -#define CM_REG_TDMA_POSITION 0x1C -#define CM_TDMA_CNT_MASK 0xFFFF0000 /* current byte/word count */ -#define CM_TDMA_ADR_MASK 0x0000FFFF /* current address */ - - /* byte */ -#define CM_REG_MIXER0 0x20 -#define CM_REG_SBVR 0x20 /* write: sb16 version */ -#define CM_REG_DEV 0x20 /* read: hardware device version */ - -#define CM_REG_MIXER21 0x21 -#define CM_UNKNOWN_21_MASK 0x78 /* ? */ -#define CM_X_ADPCM 0x04 /* SB16 ADPCM enable */ -#define CM_PROINV 0x02 /* SBPro left/right channel switching */ -#define CM_X_SB16 0x01 /* SB16 compatible */ - -#define CM_REG_SB16_DATA 0x22 -#define CM_REG_SB16_ADDR 0x23 - -#define CM_REFFREQ_XIN (315*1000*1000)/22 /* 14.31818 Mhz reference clock frequency pin XIN */ -#define CM_ADCMULT_XIN 512 /* Guessed (487 best for 44.1kHz, not for 88/176kHz) */ -#define CM_TOLERANCE_RATE 0.001 /* Tolerance sample rate pitch (1000ppm) */ -#define CM_MAXIMUM_RATE 80000000 /* Note more than 80MHz */ - -#define CM_REG_MIXER1 0x24 -#define CM_FMMUTE 0x80 /* mute FM */ -#define CM_FMMUTE_SHIFT 7 -#define CM_WSMUTE 0x40 /* mute PCM */ -#define CM_WSMUTE_SHIFT 6 -#define CM_REAR2LIN 0x20 /* lin-in -> rear line out */ -#define CM_REAR2LIN_SHIFT 5 -#define CM_REAR2FRONT 0x10 /* exchange rear/front */ -#define CM_REAR2FRONT_SHIFT 4 -#define CM_WAVEINL 0x08 /* digital wave rec. left chan */ -#define CM_WAVEINL_SHIFT 3 -#define CM_WAVEINR 0x04 /* digical wave rec. right */ -#define CM_WAVEINR_SHIFT 2 -#define CM_X3DEN 0x02 /* 3D surround enable */ -#define CM_X3DEN_SHIFT 1 -#define CM_CDPLAY 0x01 /* enable SPDIF/IN PCM -> DAC */ -#define CM_CDPLAY_SHIFT 0 - -#define CM_REG_MIXER2 0x25 -#define CM_RAUXREN 0x80 /* AUX right capture */ -#define CM_RAUXREN_SHIFT 7 -#define CM_RAUXLEN 0x40 /* AUX left capture */ -#define CM_RAUXLEN_SHIFT 6 -#define CM_VAUXRM 0x20 /* AUX right mute */ -#define CM_VAUXRM_SHIFT 5 -#define CM_VAUXLM 0x10 /* AUX left mute */ -#define CM_VAUXLM_SHIFT 4 -#define CM_VADMIC_MASK 0x0e /* mic gain level (0-3) << 1 */ -#define CM_VADMIC_SHIFT 1 -#define CM_MICGAINZ 0x01 /* mic boost */ -#define CM_MICGAINZ_SHIFT 0 - -#define CM_REG_MIXER3 0x24 -#define CM_REG_AUX_VOL 0x26 -#define CM_VAUXL_MASK 0xf0 -#define CM_VAUXR_MASK 0x0f - -#define CM_REG_MISC 0x27 -#define CM_UNKNOWN_27_MASK 0xd8 /* ? */ -#define CM_XGPO1 0x20 -// #define CM_XGPBIO 0x04 -#define CM_MIC_CENTER_LFE 0x04 /* mic as center/lfe out? (model 039 or later?) */ -#define CM_SPDIF_INVERSE 0x04 /* spdif input phase inverse (model 037) */ -#define CM_SPDVALID 0x02 /* spdif input valid check */ -#define CM_DMAUTO 0x01 /* SB16 DMA auto detect */ - -#define CM_REG_AC97 0x28 /* hmmm.. do we have ac97 link? */ -/* - * For CMI-8338 (0x28 - 0x2b) .. is this valid for CMI-8738 - * or identical with AC97 codec? - */ -#define CM_REG_EXTERN_CODEC CM_REG_AC97 - -/* - * MPU401 pci port index address 0x40 - 0x4f (CMI-8738 spec ver. 0.6) - */ -#define CM_REG_MPU_PCI 0x40 - -/* - * FM pci port index address 0x50 - 0x5f (CMI-8738 spec ver. 0.6) - */ -#define CM_REG_FM_PCI 0x50 - -/* - * access from SB-mixer port - */ -#define CM_REG_EXTENT_IND 0xf0 -#define CM_VPHONE_MASK 0xe0 /* Phone volume control (0-3) << 5 */ -#define CM_VPHONE_SHIFT 5 -#define CM_VPHOM 0x10 /* Phone mute control */ -#define CM_VSPKM 0x08 /* Speaker mute control, default high */ -#define CM_RLOOPREN 0x04 /* Rec. R-channel enable */ -#define CM_RLOOPLEN 0x02 /* Rec. L-channel enable */ -#define CM_VADMIC3 0x01 /* Mic record boost */ - -/* - * CMI-8338 spec ver 0.5 (this is not valid for CMI-8738): - * the 8 registers 0xf8 - 0xff are used for programming m/n counter by the PLL - * unit (readonly?). - */ -#define CM_REG_PLL 0xf8 - -/* - * extended registers - */ -#define CM_REG_CH0_FRAME1 0x80 /* write: base address */ -#define CM_REG_CH0_FRAME2 0x84 /* read: current address */ -#define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */ -#define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */ - -#define CM_REG_EXT_MISC 0x90 -#define CM_ADC48K44K 0x10000000 /* ADC parameters group, 0: 44k, 1: 48k */ -#define CM_CHB3D8C 0x00200000 /* 7.1 channels support */ -#define CM_SPD32FMT 0x00100000 /* SPDIF/IN 32k sample rate */ -#define CM_ADC2SPDIF 0x00080000 /* ADC output to SPDIF/OUT */ -#define CM_SHAREADC 0x00040000 /* DAC in ADC as Center/LFE */ -#define CM_REALTCMP 0x00020000 /* monitor the CMPL/CMPR of ADC */ -#define CM_INVLRCK 0x00010000 /* invert ZVPORT's LRCK */ -#define CM_UNKNOWN_90_MASK 0x0000FFFF /* ? */ - -/* - * size of i/o region - */ -#define CM_EXTENT_CODEC 0x100 -#define CM_EXTENT_MIDI 0x2 -#define CM_EXTENT_SYNTH 0x4 - - -/* - * channels for playback / capture - */ -#define CM_CH_PLAY 0 -#define CM_CH_CAPT 1 - -/* - * flags to check device open/close - */ -#define CM_OPEN_NONE 0 -#define CM_OPEN_CH_MASK 0x01 -#define CM_OPEN_DAC 0x10 -#define CM_OPEN_ADC 0x20 -#define CM_OPEN_SPDIF 0x40 -#define CM_OPEN_MCHAN 0x80 -#define CM_OPEN_PLAYBACK (CM_CH_PLAY | CM_OPEN_DAC) -#define CM_OPEN_PLAYBACK2 (CM_CH_CAPT | CM_OPEN_DAC) -#define CM_OPEN_PLAYBACK_MULTI (CM_CH_PLAY | CM_OPEN_DAC | CM_OPEN_MCHAN) -#define CM_OPEN_CAPTURE (CM_CH_CAPT | CM_OPEN_ADC) -#define CM_OPEN_SPDIF_PLAYBACK (CM_CH_PLAY | CM_OPEN_DAC | CM_OPEN_SPDIF) -#define CM_OPEN_SPDIF_CAPTURE (CM_CH_CAPT | CM_OPEN_ADC | CM_OPEN_SPDIF) - - -#if CM_CH_PLAY == 1 -#define CM_PLAYBACK_SRATE_176K CM_CH1_SRATE_176K -#define CM_PLAYBACK_SPDF CM_SPDF_1 -#define CM_CAPTURE_SPDF CM_SPDF_0 -#else -#define CM_PLAYBACK_SRATE_176K CM_CH0_SRATE_176K -#define CM_PLAYBACK_SPDF CM_SPDF_0 -#define CM_CAPTURE_SPDF CM_SPDF_1 -#endif - - -/* - * driver data - */ - -struct cmipci_pcm { - struct snd_pcm_substream *substream; - u8 running; /* dac/adc running? */ - u8 fmt; /* format bits */ - u8 is_dac; - u8 needs_silencing; - unsigned int dma_size; /* in frames */ - unsigned int shift; - unsigned int ch; /* channel (0/1) */ - unsigned int offset; /* physical address of the buffer */ -}; - -/* mixer elements toggled/resumed during ac3 playback */ -struct cmipci_mixer_auto_switches { - const char *name; /* switch to toggle */ - int toggle_on; /* value to change when ac3 mode */ -}; -static const struct cmipci_mixer_auto_switches cm_saved_mixer[] = { - {"PCM Playback Switch", 0}, - {"IEC958 Output Switch", 1}, - {"IEC958 Mix Analog", 0}, - // {"IEC958 Out To DAC", 1}, // no longer used - {"IEC958 Loop", 0}, -}; -#define CM_SAVED_MIXERS ARRAY_SIZE(cm_saved_mixer) - -struct cmipci { - struct snd_card *card; - - struct pci_dev *pci; - unsigned int device; /* device ID */ - int irq; - - unsigned long iobase; - unsigned int ctrl; /* FUNCTRL0 current value */ - - struct snd_pcm *pcm; /* DAC/ADC PCM */ - struct snd_pcm *pcm2; /* 2nd DAC */ - struct snd_pcm *pcm_spdif; /* SPDIF */ - - int chip_version; - int max_channels; - unsigned int can_ac3_sw: 1; - unsigned int can_ac3_hw: 1; - unsigned int can_multi_ch: 1; - unsigned int can_96k: 1; /* samplerate above 48k */ - unsigned int do_soft_ac3: 1; - - unsigned int spdif_playback_avail: 1; /* spdif ready? */ - unsigned int spdif_playback_enabled: 1; /* spdif switch enabled? */ - int spdif_counter; /* for software AC3 */ - - unsigned int dig_status; - unsigned int dig_pcm_status; - - struct snd_pcm_hardware *hw_info[3]; /* for playbacks */ - - int opened[2]; /* open mode */ - struct mutex open_mutex; - - unsigned int mixer_insensitive: 1; - struct snd_kcontrol *mixer_res_ctl[CM_SAVED_MIXERS]; - int mixer_res_status[CM_SAVED_MIXERS]; - - struct cmipci_pcm channel[2]; /* ch0 - DAC, ch1 - ADC or 2nd DAC */ - - /* external MIDI */ - struct snd_rawmidi *rmidi; - -#ifdef SUPPORT_JOYSTICK - struct gameport *gameport; -#endif - - spinlock_t reg_lock; - -#ifdef CONFIG_PM - unsigned int saved_regs[0x20]; - unsigned char saved_mixers[0x20]; -#endif -}; - - -/* read/write operations for dword register */ -static inline void snd_cmipci_write(struct cmipci *cm, unsigned int cmd, unsigned int data) -{ - outl(data, cm->iobase + cmd); -} - -static inline unsigned int snd_cmipci_read(struct cmipci *cm, unsigned int cmd) -{ - return inl(cm->iobase + cmd); -} - -/* read/write operations for word register */ -static inline void snd_cmipci_write_w(struct cmipci *cm, unsigned int cmd, unsigned short data) -{ - outw(data, cm->iobase + cmd); -} - -static inline unsigned short snd_cmipci_read_w(struct cmipci *cm, unsigned int cmd) -{ - return inw(cm->iobase + cmd); -} - -/* read/write operations for byte register */ -static inline void snd_cmipci_write_b(struct cmipci *cm, unsigned int cmd, unsigned char data) -{ - outb(data, cm->iobase + cmd); -} - -static inline unsigned char snd_cmipci_read_b(struct cmipci *cm, unsigned int cmd) -{ - return inb(cm->iobase + cmd); -} - -/* bit operations for dword register */ -static int snd_cmipci_set_bit(struct cmipci *cm, unsigned int cmd, unsigned int flag) -{ - unsigned int val, oval; - val = oval = inl(cm->iobase + cmd); - val |= flag; - if (val == oval) - return 0; - outl(val, cm->iobase + cmd); - return 1; -} - -static int snd_cmipci_clear_bit(struct cmipci *cm, unsigned int cmd, unsigned int flag) -{ - unsigned int val, oval; - val = oval = inl(cm->iobase + cmd); - val &= ~flag; - if (val == oval) - return 0; - outl(val, cm->iobase + cmd); - return 1; -} - -/* bit operations for byte register */ -static int snd_cmipci_set_bit_b(struct cmipci *cm, unsigned int cmd, unsigned char flag) -{ - unsigned char val, oval; - val = oval = inb(cm->iobase + cmd); - val |= flag; - if (val == oval) - return 0; - outb(val, cm->iobase + cmd); - return 1; -} - -static int snd_cmipci_clear_bit_b(struct cmipci *cm, unsigned int cmd, unsigned char flag) -{ - unsigned char val, oval; - val = oval = inb(cm->iobase + cmd); - val &= ~flag; - if (val == oval) - return 0; - outb(val, cm->iobase + cmd); - return 1; -} - - -/* - * PCM interface - */ - -/* - * calculate frequency - */ - -static unsigned int rates[] = { 5512, 11025, 22050, 44100, 8000, 16000, 32000, 48000 }; - -static unsigned int snd_cmipci_rate_freq(unsigned int rate) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(rates); i++) { - if (rates[i] == rate) - return i; - } - snd_BUG(); - return 0; -} - -#ifdef USE_VAR48KRATE -/* - * Determine PLL values for frequency setup, maybe the CMI8338 (CMI8738???) - * does it this way .. maybe not. Never get any information from C-Media about - * that . - */ -static int snd_cmipci_pll_rmn(unsigned int rate, unsigned int adcmult, int *r, int *m, int *n) -{ - unsigned int delta, tolerance; - int xm, xn, xr; - - for (*r = 0; rate < CM_MAXIMUM_RATE/adcmult; *r += (1<<5)) - rate <<= 1; - *n = -1; - if (*r > 0xff) - goto out; - tolerance = rate*CM_TOLERANCE_RATE; - - for (xn = (1+2); xn < (0x1f+2); xn++) { - for (xm = (1+2); xm < (0xff+2); xm++) { - xr = ((CM_REFFREQ_XIN/adcmult) * xm) / xn; - - if (xr < rate) - delta = rate - xr; - else - delta = xr - rate; - - /* - * If we found one, remember this, - * and try to find a closer one - */ - if (delta < tolerance) { - tolerance = delta; - *m = xm - 2; - *n = xn - 2; - } - } - } -out: - return (*n > -1); -} - -/* - * Program pll register bits, I assume that the 8 registers 0xf8 up to 0xff - * are mapped onto the 8 ADC/DAC sampling frequency which can be chosen - * at the register CM_REG_FUNCTRL1 (0x04). - * Problem: other ways are also possible (any information about that?) - */ -static void snd_cmipci_set_pll(struct cmipci *cm, unsigned int rate, unsigned int slot) -{ - unsigned int reg = CM_REG_PLL + slot; - /* - * Guess that this programs at reg. 0x04 the pos 15:13/12:10 - * for DSFC/ASFC (000 up to 111). - */ - - /* FIXME: Init (Do we've to set an other register first before programming?) */ - - /* FIXME: Is this correct? Or shouldn't the m/n/r values be used for that? */ - snd_cmipci_write_b(cm, reg, rate>>8); - snd_cmipci_write_b(cm, reg, rate&0xff); - - /* FIXME: Setup (Do we've to set an other register first to enable this?) */ -} -#endif /* USE_VAR48KRATE */ - -static int snd_cmipci_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - if (params_channels(hw_params) > 2) { - mutex_lock(&cm->open_mutex); - if (cm->opened[CM_CH_PLAY]) { - mutex_unlock(&cm->open_mutex); - return -EBUSY; - } - /* reserve the channel A */ - cm->opened[CM_CH_PLAY] = CM_OPEN_PLAYBACK_MULTI; - mutex_unlock(&cm->open_mutex); - } - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static void snd_cmipci_ch_reset(struct cmipci *cm, int ch) -{ - int reset = CM_RST_CH0 << (cm->channel[ch].ch); - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset); - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset); - udelay(10); -} - -static int snd_cmipci_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - - -/* - */ - -static unsigned int hw_channels[] = {1, 2, 4, 6, 8}; -static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { - .count = 3, - .list = hw_channels, - .mask = 0, -}; -static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { - .count = 4, - .list = hw_channels, - .mask = 0, -}; -static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { - .count = 5, - .list = hw_channels, - .mask = 0, -}; - -static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels) -{ - if (channels > 2) { - if (!cm->can_multi_ch || !rec->ch) - return -EINVAL; - if (rec->fmt != 0x03) /* stereo 16bit only */ - return -EINVAL; - } - - if (cm->can_multi_ch) { - spin_lock_irq(&cm->reg_lock); - if (channels > 2) { - snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); - } else { - snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); - } - if (channels == 8) - snd_cmipci_set_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C); - else - snd_cmipci_clear_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C); - if (channels == 6) { - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); - snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); - } else { - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); - snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); - } - if (channels == 4) - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); - else - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); - spin_unlock_irq(&cm->reg_lock); - } - return 0; -} - - -/* - * prepare playback/capture channel - * channel to be used must have been set in rec->ch. - */ -static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, - struct snd_pcm_substream *substream) -{ - unsigned int reg, freq, freq_ext, val; - unsigned int period_size; - struct snd_pcm_runtime *runtime = substream->runtime; - - rec->fmt = 0; - rec->shift = 0; - if (snd_pcm_format_width(runtime->format) >= 16) { - rec->fmt |= 0x02; - if (snd_pcm_format_width(runtime->format) > 16) - rec->shift++; /* 24/32bit */ - } - if (runtime->channels > 1) - rec->fmt |= 0x01; - if (rec->is_dac && set_dac_channels(cm, rec, runtime->channels) < 0) { - snd_printd("cannot set dac channels\n"); - return -EINVAL; - } - - rec->offset = runtime->dma_addr; - /* buffer and period sizes in frame */ - rec->dma_size = runtime->buffer_size << rec->shift; - period_size = runtime->period_size << rec->shift; - if (runtime->channels > 2) { - /* multi-channels */ - rec->dma_size = (rec->dma_size * runtime->channels) / 2; - period_size = (period_size * runtime->channels) / 2; - } - - spin_lock_irq(&cm->reg_lock); - - /* set buffer address */ - reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1; - snd_cmipci_write(cm, reg, rec->offset); - /* program sample counts */ - reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; - snd_cmipci_write_w(cm, reg, rec->dma_size - 1); - snd_cmipci_write_w(cm, reg + 2, period_size - 1); - - /* set adc/dac flag */ - val = rec->ch ? CM_CHADC1 : CM_CHADC0; - if (rec->is_dac) - cm->ctrl &= ~val; - else - cm->ctrl |= val; - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); - //snd_printd("cmipci: functrl0 = %08x\n", cm->ctrl); - - /* set sample rate */ - freq = 0; - freq_ext = 0; - if (runtime->rate > 48000) - switch (runtime->rate) { - case 88200: freq_ext = CM_CH0_SRATE_88K; break; - case 96000: freq_ext = CM_CH0_SRATE_96K; break; - case 128000: freq_ext = CM_CH0_SRATE_128K; break; - default: snd_BUG(); break; - } - else - freq = snd_cmipci_rate_freq(runtime->rate); - val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); - if (rec->ch) { - val &= ~CM_DSFC_MASK; - val |= (freq << CM_DSFC_SHIFT) & CM_DSFC_MASK; - } else { - val &= ~CM_ASFC_MASK; - val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK; - } - snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); - //snd_printd("cmipci: functrl1 = %08x\n", val); - - /* set format */ - val = snd_cmipci_read(cm, CM_REG_CHFORMAT); - if (rec->ch) { - val &= ~CM_CH1FMT_MASK; - val |= rec->fmt << CM_CH1FMT_SHIFT; - } else { - val &= ~CM_CH0FMT_MASK; - val |= rec->fmt << CM_CH0FMT_SHIFT; - } - if (cm->can_96k) { - val &= ~(CM_CH0_SRATE_MASK << (rec->ch * 2)); - val |= freq_ext << (rec->ch * 2); - } - snd_cmipci_write(cm, CM_REG_CHFORMAT, val); - //snd_printd("cmipci: chformat = %08x\n", val); - - if (!rec->is_dac && cm->chip_version) { - if (runtime->rate > 44100) - snd_cmipci_set_bit(cm, CM_REG_EXT_MISC, CM_ADC48K44K); - else - snd_cmipci_clear_bit(cm, CM_REG_EXT_MISC, CM_ADC48K44K); - } - - rec->running = 0; - spin_unlock_irq(&cm->reg_lock); - - return 0; -} - -/* - * PCM trigger/stop - */ -static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, - int cmd) -{ - unsigned int inthld, chen, reset, pause; - int result = 0; - - inthld = CM_CH0_INT_EN << rec->ch; - chen = CM_CHEN0 << rec->ch; - reset = CM_RST_CH0 << rec->ch; - pause = CM_PAUSE0 << rec->ch; - - spin_lock(&cm->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - rec->running = 1; - /* set interrupt */ - snd_cmipci_set_bit(cm, CM_REG_INT_HLDCLR, inthld); - cm->ctrl |= chen; - /* enable channel */ - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); - //snd_printd("cmipci: functrl0 = %08x\n", cm->ctrl); - break; - case SNDRV_PCM_TRIGGER_STOP: - rec->running = 0; - /* disable interrupt */ - snd_cmipci_clear_bit(cm, CM_REG_INT_HLDCLR, inthld); - /* reset */ - cm->ctrl &= ~chen; - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset); - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset); - rec->needs_silencing = rec->is_dac; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - cm->ctrl |= pause; - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - cm->ctrl &= ~pause; - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&cm->reg_lock); - return result; -} - -/* - * return the current pointer - */ -static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci_pcm *rec, - struct snd_pcm_substream *substream) -{ - size_t ptr; - unsigned int reg, rem, tries; - - if (!rec->running) - return 0; -#if 1 // this seems better.. - reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; - for (tries = 0; tries < 3; tries++) { - rem = snd_cmipci_read_w(cm, reg); - if (rem < rec->dma_size) - goto ok; - } - printk(KERN_ERR "cmipci: invalid PCM pointer: %#x\n", rem); - return SNDRV_PCM_POS_XRUN; -ok: - ptr = (rec->dma_size - (rem + 1)) >> rec->shift; -#else - reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1; - ptr = snd_cmipci_read(cm, reg) - rec->offset; - ptr = bytes_to_frames(substream->runtime, ptr); -#endif - if (substream->runtime->channels > 2) - ptr = (ptr * 2) / substream->runtime->channels; - return ptr; -} - -/* - * playback - */ - -static int snd_cmipci_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], cmd); -} - -static snd_pcm_uframes_t snd_cmipci_playback_pointer(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - return snd_cmipci_pcm_pointer(cm, &cm->channel[CM_CH_PLAY], substream); -} - - - -/* - * capture - */ - -static int snd_cmipci_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], cmd); -} - -static snd_pcm_uframes_t snd_cmipci_capture_pointer(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - return snd_cmipci_pcm_pointer(cm, &cm->channel[CM_CH_CAPT], substream); -} - - -/* - * hw preparation for spdif - */ - -static int snd_cmipci_spdif_default_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_cmipci_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *chip = snd_kcontrol_chip(kcontrol); - int i; - - spin_lock_irq(&chip->reg_lock); - for (i = 0; i < 4; i++) - ucontrol->value.iec958.status[i] = (chip->dig_status >> (i * 8)) & 0xff; - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_cmipci_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *chip = snd_kcontrol_chip(kcontrol); - int i, change; - unsigned int val; - - val = 0; - spin_lock_irq(&chip->reg_lock); - for (i = 0; i < 4; i++) - val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8); - change = val != chip->dig_status; - chip->dig_status = val; - spin_unlock_irq(&chip->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_cmipci_spdif_default __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_cmipci_spdif_default_info, - .get = snd_cmipci_spdif_default_get, - .put = snd_cmipci_spdif_default_put -}; - -static int snd_cmipci_spdif_mask_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_cmipci_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static struct snd_kcontrol_new snd_cmipci_spdif_mask __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), - .info = snd_cmipci_spdif_mask_info, - .get = snd_cmipci_spdif_mask_get, -}; - -static int snd_cmipci_spdif_stream_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_cmipci_spdif_stream_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *chip = snd_kcontrol_chip(kcontrol); - int i; - - spin_lock_irq(&chip->reg_lock); - for (i = 0; i < 4; i++) - ucontrol->value.iec958.status[i] = (chip->dig_pcm_status >> (i * 8)) & 0xff; - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_cmipci_spdif_stream_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *chip = snd_kcontrol_chip(kcontrol); - int i, change; - unsigned int val; - - val = 0; - spin_lock_irq(&chip->reg_lock); - for (i = 0; i < 4; i++) - val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8); - change = val != chip->dig_pcm_status; - chip->dig_pcm_status = val; - spin_unlock_irq(&chip->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_cmipci_spdif_stream __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_cmipci_spdif_stream_info, - .get = snd_cmipci_spdif_stream_get, - .put = snd_cmipci_spdif_stream_put -}; - -/* - */ - -/* save mixer setting and mute for AC3 playback */ -static int save_mixer_state(struct cmipci *cm) -{ - if (! cm->mixer_insensitive) { - struct snd_ctl_elem_value *val; - unsigned int i; - - val = kmalloc(sizeof(*val), GFP_ATOMIC); - if (!val) - return -ENOMEM; - for (i = 0; i < CM_SAVED_MIXERS; i++) { - struct snd_kcontrol *ctl = cm->mixer_res_ctl[i]; - if (ctl) { - int event; - memset(val, 0, sizeof(*val)); - ctl->get(ctl, val); - cm->mixer_res_status[i] = val->value.integer.value[0]; - val->value.integer.value[0] = cm_saved_mixer[i].toggle_on; - event = SNDRV_CTL_EVENT_MASK_INFO; - if (cm->mixer_res_status[i] != val->value.integer.value[0]) { - ctl->put(ctl, val); /* toggle */ - event |= SNDRV_CTL_EVENT_MASK_VALUE; - } - ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(cm->card, event, &ctl->id); - } - } - kfree(val); - cm->mixer_insensitive = 1; - } - return 0; -} - - -/* restore the previously saved mixer status */ -static void restore_mixer_state(struct cmipci *cm) -{ - if (cm->mixer_insensitive) { - struct snd_ctl_elem_value *val; - unsigned int i; - - val = kmalloc(sizeof(*val), GFP_KERNEL); - if (!val) - return; - cm->mixer_insensitive = 0; /* at first clear this; - otherwise the changes will be ignored */ - for (i = 0; i < CM_SAVED_MIXERS; i++) { - struct snd_kcontrol *ctl = cm->mixer_res_ctl[i]; - if (ctl) { - int event; - - memset(val, 0, sizeof(*val)); - ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - ctl->get(ctl, val); - event = SNDRV_CTL_EVENT_MASK_INFO; - if (val->value.integer.value[0] != cm->mixer_res_status[i]) { - val->value.integer.value[0] = cm->mixer_res_status[i]; - ctl->put(ctl, val); - event |= SNDRV_CTL_EVENT_MASK_VALUE; - } - snd_ctl_notify(cm->card, event, &ctl->id); - } - } - kfree(val); - } -} - -/* spinlock held! */ -static void setup_ac3(struct cmipci *cm, struct snd_pcm_substream *subs, int do_ac3, int rate) -{ - if (do_ac3) { - /* AC3EN for 037 */ - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_AC3EN1); - /* AC3EN for 039 */ - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_AC3EN2); - - if (cm->can_ac3_hw) { - /* SPD24SEL for 037, 0x02 */ - /* SPD24SEL for 039, 0x20, but cannot be set */ - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - } else { /* can_ac3_sw */ - /* SPD32SEL for 037 & 039, 0x20 */ - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - /* set 176K sample rate to fix 033 HW bug */ - if (cm->chip_version == 33) { - if (rate >= 48000) { - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_PLAYBACK_SRATE_176K); - } else { - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_PLAYBACK_SRATE_176K); - } - } - } - - } else { - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_AC3EN1); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_AC3EN2); - - if (cm->can_ac3_hw) { - /* chip model >= 37 */ - if (snd_pcm_format_width(subs->runtime->format) > 16) { - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL); - } else { - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL); - } - } else { - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_SPD24SEL); - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_PLAYBACK_SRATE_176K); - } - } -} - -static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *subs, int up, int do_ac3) -{ - int rate, err; - - rate = subs->runtime->rate; - - if (up && do_ac3) - if ((err = save_mixer_state(cm)) < 0) - return err; - - spin_lock_irq(&cm->reg_lock); - cm->spdif_playback_avail = up; - if (up) { - /* they are controlled via "IEC958 Output Switch" */ - /* snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */ - /* snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */ - if (cm->spdif_playback_enabled) - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); - setup_ac3(cm, subs, do_ac3, rate); - - if (rate == 48000 || rate == 96000) - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); - else - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); - if (rate > 48000) - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); - else - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); - } else { - /* they are controlled via "IEC958 Output Switch" */ - /* snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */ - /* snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */ - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); - snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); - setup_ac3(cm, subs, 0, 0); - } - spin_unlock_irq(&cm->reg_lock); - return 0; -} - - -/* - * preparation - */ - -/* playback - enable spdif only on the certain condition */ -static int snd_cmipci_playback_prepare(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - int rate = substream->runtime->rate; - int err, do_spdif, do_ac3 = 0; - - do_spdif = (rate >= 44100 && rate <= 96000 && - substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE && - substream->runtime->channels == 2); - if (do_spdif && cm->can_ac3_hw) - do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO; - if ((err = setup_spdif_playback(cm, substream, do_spdif, do_ac3)) < 0) - return err; - return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); -} - -/* playback (via device #2) - enable spdif always */ -static int snd_cmipci_playback_spdif_prepare(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - int err, do_ac3; - - if (cm->can_ac3_hw) - do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO; - else - do_ac3 = 1; /* doesn't matter */ - if ((err = setup_spdif_playback(cm, substream, 1, do_ac3)) < 0) - return err; - return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); -} - -/* - * Apparently, the samples last played on channel A stay in some buffer, even - * after the channel is reset, and get added to the data for the rear DACs when - * playing a multichannel stream on channel B. This is likely to generate - * wraparounds and thus distortions. - * To avoid this, we play at least one zero sample after the actual stream has - * stopped. - */ -static void snd_cmipci_silence_hack(struct cmipci *cm, struct cmipci_pcm *rec) -{ - struct snd_pcm_runtime *runtime = rec->substream->runtime; - unsigned int reg, val; - - if (rec->needs_silencing && runtime && runtime->dma_area) { - /* set up a small silence buffer */ - memset(runtime->dma_area, 0, PAGE_SIZE); - reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; - val = ((PAGE_SIZE / 4) - 1) | (((PAGE_SIZE / 4) / 2 - 1) << 16); - snd_cmipci_write(cm, reg, val); - - /* configure for 16 bits, 2 channels, 8 kHz */ - if (runtime->channels > 2) - set_dac_channels(cm, rec, 2); - spin_lock_irq(&cm->reg_lock); - val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); - val &= ~(CM_ASFC_MASK << (rec->ch * 3)); - val |= (4 << CM_ASFC_SHIFT) << (rec->ch * 3); - snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); - val = snd_cmipci_read(cm, CM_REG_CHFORMAT); - val &= ~(CM_CH0FMT_MASK << (rec->ch * 2)); - val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2); - if (cm->can_96k) - val &= ~(CM_CH0_SRATE_MASK << (rec->ch * 2)); - snd_cmipci_write(cm, CM_REG_CHFORMAT, val); - - /* start stream (we don't need interrupts) */ - cm->ctrl |= CM_CHEN0 << rec->ch; - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); - spin_unlock_irq(&cm->reg_lock); - - msleep(1); - - /* stop and reset stream */ - spin_lock_irq(&cm->reg_lock); - cm->ctrl &= ~(CM_CHEN0 << rec->ch); - val = CM_RST_CH0 << rec->ch; - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | val); - snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~val); - spin_unlock_irq(&cm->reg_lock); - - rec->needs_silencing = 0; - } -} - -static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - setup_spdif_playback(cm, substream, 0, 0); - restore_mixer_state(cm); - snd_cmipci_silence_hack(cm, &cm->channel[0]); - return snd_cmipci_hw_free(substream); -} - -static int snd_cmipci_playback2_hw_free(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - snd_cmipci_silence_hack(cm, &cm->channel[1]); - return snd_cmipci_hw_free(substream); -} - -/* capture */ -static int snd_cmipci_capture_prepare(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream); -} - -/* capture with spdif (via device #2) */ -static int snd_cmipci_capture_spdif_prepare(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - - spin_lock_irq(&cm->reg_lock); - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); - if (cm->can_96k) { - if (substream->runtime->rate > 48000) - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); - else - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); - } - if (snd_pcm_format_width(substream->runtime->format) > 16) - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - else - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - - spin_unlock_irq(&cm->reg_lock); - - return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream); -} - -static int snd_cmipci_capture_spdif_hw_free(struct snd_pcm_substream *subs) -{ - struct cmipci *cm = snd_pcm_substream_chip(subs); - - spin_lock_irq(&cm->reg_lock); - snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); - spin_unlock_irq(&cm->reg_lock); - - return snd_cmipci_hw_free(subs); -} - - -/* - * interrupt handler - */ -static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id) -{ - struct cmipci *cm = dev_id; - unsigned int status, mask = 0; - - /* fastpath out, to ease interrupt sharing */ - status = snd_cmipci_read(cm, CM_REG_INT_STATUS); - if (!(status & CM_INTR)) - return IRQ_NONE; - - /* acknowledge interrupt */ - spin_lock(&cm->reg_lock); - if (status & CM_CHINT0) - mask |= CM_CH0_INT_EN; - if (status & CM_CHINT1) - mask |= CM_CH1_INT_EN; - snd_cmipci_clear_bit(cm, CM_REG_INT_HLDCLR, mask); - snd_cmipci_set_bit(cm, CM_REG_INT_HLDCLR, mask); - spin_unlock(&cm->reg_lock); - - if (cm->rmidi && (status & CM_UARTINT)) - snd_mpu401_uart_interrupt(irq, cm->rmidi->private_data); - - if (cm->pcm) { - if ((status & CM_CHINT0) && cm->channel[0].running) - snd_pcm_period_elapsed(cm->channel[0].substream); - if ((status & CM_CHINT1) && cm->channel[1].running) - snd_pcm_period_elapsed(cm->channel[1].substream); - } - return IRQ_HANDLED; -} - -/* - * h/w infos - */ - -/* playback on channel A */ -static struct snd_pcm_hardware snd_cmipci_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5512, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* capture on channel B */ -static struct snd_pcm_hardware snd_cmipci_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5512, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* playback on channel B - stereo 16bit only? */ -static struct snd_pcm_hardware snd_cmipci_playback2 = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5512, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* spdif playback on channel A */ -static struct snd_pcm_hardware snd_cmipci_playback_spdif = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* spdif playback on channel A (32bit, IEC958 subframes) */ -static struct snd_pcm_hardware snd_cmipci_playback_iec958_subframe = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* spdif capture on channel B */ -static struct snd_pcm_hardware snd_cmipci_capture_spdif = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -static unsigned int rate_constraints[] = { 5512, 8000, 11025, 16000, 22050, - 32000, 44100, 48000, 88200, 96000, 128000 }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rate_constraints), - .list = rate_constraints, - .mask = 0, -}; - -/* - * check device open/close - */ -static int open_device_check(struct cmipci *cm, int mode, struct snd_pcm_substream *subs) -{ - int ch = mode & CM_OPEN_CH_MASK; - - /* FIXME: a file should wait until the device becomes free - * when it's opened on blocking mode. however, since the current - * pcm framework doesn't pass file pointer before actually opened, - * we can't know whether blocking mode or not in open callback.. - */ - mutex_lock(&cm->open_mutex); - if (cm->opened[ch]) { - mutex_unlock(&cm->open_mutex); - return -EBUSY; - } - cm->opened[ch] = mode; - cm->channel[ch].substream = subs; - if (! (mode & CM_OPEN_DAC)) { - /* disable dual DAC mode */ - cm->channel[ch].is_dac = 0; - spin_lock_irq(&cm->reg_lock); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC); - spin_unlock_irq(&cm->reg_lock); - } - mutex_unlock(&cm->open_mutex); - return 0; -} - -static void close_device_check(struct cmipci *cm, int mode) -{ - int ch = mode & CM_OPEN_CH_MASK; - - mutex_lock(&cm->open_mutex); - if (cm->opened[ch] == mode) { - if (cm->channel[ch].substream) { - snd_cmipci_ch_reset(cm, ch); - cm->channel[ch].running = 0; - cm->channel[ch].substream = NULL; - } - cm->opened[ch] = 0; - if (! cm->channel[ch].is_dac) { - /* enable dual DAC mode again */ - cm->channel[ch].is_dac = 1; - spin_lock_irq(&cm->reg_lock); - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC); - spin_unlock_irq(&cm->reg_lock); - } - } - mutex_unlock(&cm->open_mutex); -} - -/* - */ - -static int snd_cmipci_playback_open(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) - return err; - runtime->hw = snd_cmipci_playback; - if (cm->chip_version == 68) { - runtime->hw.rates |= SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000; - runtime->hw.rate_max = 96000; - } else if (cm->chip_version == 55) { - err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - if (err < 0) - return err; - runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; - runtime->hw.rate_max = 128000; - } - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); - cm->dig_pcm_status = cm->dig_status; - return 0; -} - -static int snd_cmipci_capture_open(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = open_device_check(cm, CM_OPEN_CAPTURE, substream)) < 0) - return err; - runtime->hw = snd_cmipci_capture; - if (cm->chip_version == 68) { // 8768 only supports 44k/48k recording - runtime->hw.rate_min = 41000; - runtime->hw.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; - } else if (cm->chip_version == 55) { - err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - if (err < 0) - return err; - runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; - runtime->hw.rate_max = 128000; - } - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); - return 0; -} - -static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = open_device_check(cm, CM_OPEN_PLAYBACK2, substream)) < 0) /* use channel B */ - return err; - runtime->hw = snd_cmipci_playback2; - mutex_lock(&cm->open_mutex); - if (! cm->opened[CM_CH_PLAY]) { - if (cm->can_multi_ch) { - runtime->hw.channels_max = cm->max_channels; - if (cm->max_channels == 4) - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_4); - else if (cm->max_channels == 6) - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_6); - else if (cm->max_channels == 8) - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); - } - } - mutex_unlock(&cm->open_mutex); - if (cm->chip_version == 68) { - runtime->hw.rates |= SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000; - runtime->hw.rate_max = 96000; - } else if (cm->chip_version == 55) { - err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - if (err < 0) - return err; - runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; - runtime->hw.rate_max = 128000; - } - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); - return 0; -} - -static int snd_cmipci_playback_spdif_open(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = open_device_check(cm, CM_OPEN_SPDIF_PLAYBACK, substream)) < 0) /* use channel A */ - return err; - if (cm->can_ac3_hw) { - runtime->hw = snd_cmipci_playback_spdif; - if (cm->chip_version >= 37) { - runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - } - if (cm->can_96k) { - runtime->hw.rates |= SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000; - runtime->hw.rate_max = 96000; - } - } else { - runtime->hw = snd_cmipci_playback_iec958_subframe; - } - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x40000); - cm->dig_pcm_status = cm->dig_status; - return 0; -} - -static int snd_cmipci_capture_spdif_open(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = open_device_check(cm, CM_OPEN_SPDIF_CAPTURE, substream)) < 0) /* use channel B */ - return err; - runtime->hw = snd_cmipci_capture_spdif; - if (cm->can_96k && !(cm->chip_version == 68)) { - runtime->hw.rates |= SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000; - runtime->hw.rate_max = 96000; - } - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x40000); - return 0; -} - - -/* - */ - -static int snd_cmipci_playback_close(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - close_device_check(cm, CM_OPEN_PLAYBACK); - return 0; -} - -static int snd_cmipci_capture_close(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - close_device_check(cm, CM_OPEN_CAPTURE); - return 0; -} - -static int snd_cmipci_playback2_close(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - close_device_check(cm, CM_OPEN_PLAYBACK2); - close_device_check(cm, CM_OPEN_PLAYBACK_MULTI); - return 0; -} - -static int snd_cmipci_playback_spdif_close(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - close_device_check(cm, CM_OPEN_SPDIF_PLAYBACK); - return 0; -} - -static int snd_cmipci_capture_spdif_close(struct snd_pcm_substream *substream) -{ - struct cmipci *cm = snd_pcm_substream_chip(substream); - close_device_check(cm, CM_OPEN_SPDIF_CAPTURE); - return 0; -} - - -/* - */ - -static struct snd_pcm_ops snd_cmipci_playback_ops = { - .open = snd_cmipci_playback_open, - .close = snd_cmipci_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cmipci_hw_params, - .hw_free = snd_cmipci_playback_hw_free, - .prepare = snd_cmipci_playback_prepare, - .trigger = snd_cmipci_playback_trigger, - .pointer = snd_cmipci_playback_pointer, -}; - -static struct snd_pcm_ops snd_cmipci_capture_ops = { - .open = snd_cmipci_capture_open, - .close = snd_cmipci_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cmipci_hw_params, - .hw_free = snd_cmipci_hw_free, - .prepare = snd_cmipci_capture_prepare, - .trigger = snd_cmipci_capture_trigger, - .pointer = snd_cmipci_capture_pointer, -}; - -static struct snd_pcm_ops snd_cmipci_playback2_ops = { - .open = snd_cmipci_playback2_open, - .close = snd_cmipci_playback2_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cmipci_playback2_hw_params, - .hw_free = snd_cmipci_playback2_hw_free, - .prepare = snd_cmipci_capture_prepare, /* channel B */ - .trigger = snd_cmipci_capture_trigger, /* channel B */ - .pointer = snd_cmipci_capture_pointer, /* channel B */ -}; - -static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = { - .open = snd_cmipci_playback_spdif_open, - .close = snd_cmipci_playback_spdif_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cmipci_hw_params, - .hw_free = snd_cmipci_playback_hw_free, - .prepare = snd_cmipci_playback_spdif_prepare, /* set up rate */ - .trigger = snd_cmipci_playback_trigger, - .pointer = snd_cmipci_playback_pointer, -}; - -static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = { - .open = snd_cmipci_capture_spdif_open, - .close = snd_cmipci_capture_spdif_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cmipci_hw_params, - .hw_free = snd_cmipci_capture_spdif_hw_free, - .prepare = snd_cmipci_capture_spdif_prepare, - .trigger = snd_cmipci_capture_trigger, - .pointer = snd_cmipci_capture_pointer, -}; - - -/* - */ - -static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cmipci_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cmipci_capture_ops); - - pcm->private_data = cm; - pcm->info_flags = 0; - strcpy(pcm->name, "C-Media PCI DAC/ADC"); - cm->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(cm->pci), 64*1024, 128*1024); - - return 0; -} - -static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 0, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cmipci_playback2_ops); - - pcm->private_data = cm; - pcm->info_flags = 0; - strcpy(pcm->name, "C-Media PCI 2nd DAC"); - cm->pcm2 = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(cm->pci), 64*1024, 128*1024); - - return 0; -} - -static int __devinit snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cmipci_playback_spdif_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cmipci_capture_spdif_ops); - - pcm->private_data = cm; - pcm->info_flags = 0; - strcpy(pcm->name, "C-Media PCI IEC958"); - cm->pcm_spdif = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(cm->pci), 64*1024, 128*1024); - - return 0; -} - -/* - * mixer interface: - * - CM8338/8738 has a compatible mixer interface with SB16, but - * lack of some elements like tone control, i/o gain and AGC. - * - Access to native registers: - * - A 3D switch - * - Output mute switches - */ - -static void snd_cmipci_mixer_write(struct cmipci *s, unsigned char idx, unsigned char data) -{ - outb(idx, s->iobase + CM_REG_SB16_ADDR); - outb(data, s->iobase + CM_REG_SB16_DATA); -} - -static unsigned char snd_cmipci_mixer_read(struct cmipci *s, unsigned char idx) -{ - unsigned char v; - - outb(idx, s->iobase + CM_REG_SB16_ADDR); - v = inb(s->iobase + CM_REG_SB16_DATA); - return v; -} - -/* - * general mixer element - */ -struct cmipci_sb_reg { - unsigned int left_reg, right_reg; - unsigned int left_shift, right_shift; - unsigned int mask; - unsigned int invert: 1; - unsigned int stereo: 1; -}; - -#define COMPOSE_SB_REG(lreg,rreg,lshift,rshift,mask,invert,stereo) \ - ((lreg) | ((rreg) << 8) | (lshift << 16) | (rshift << 19) | (mask << 24) | (invert << 22) | (stereo << 23)) - -#define CMIPCI_DOUBLE(xname, left_reg, right_reg, left_shift, right_shift, mask, invert, stereo) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_cmipci_info_volume, \ - .get = snd_cmipci_get_volume, .put = snd_cmipci_put_volume, \ - .private_value = COMPOSE_SB_REG(left_reg, right_reg, left_shift, right_shift, mask, invert, stereo), \ -} - -#define CMIPCI_SB_VOL_STEREO(xname,reg,shift,mask) CMIPCI_DOUBLE(xname, reg, reg+1, shift, shift, mask, 0, 1) -#define CMIPCI_SB_VOL_MONO(xname,reg,shift,mask) CMIPCI_DOUBLE(xname, reg, reg, shift, shift, mask, 0, 0) -#define CMIPCI_SB_SW_STEREO(xname,lshift,rshift) CMIPCI_DOUBLE(xname, SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, lshift, rshift, 1, 0, 1) -#define CMIPCI_SB_SW_MONO(xname,shift) CMIPCI_DOUBLE(xname, SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, shift, shift, 1, 0, 0) - -static void cmipci_sb_reg_decode(struct cmipci_sb_reg *r, unsigned long val) -{ - r->left_reg = val & 0xff; - r->right_reg = (val >> 8) & 0xff; - r->left_shift = (val >> 16) & 0x07; - r->right_shift = (val >> 19) & 0x07; - r->invert = (val >> 22) & 1; - r->stereo = (val >> 23) & 1; - r->mask = (val >> 24) & 0xff; -} - -static int snd_cmipci_info_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct cmipci_sb_reg reg; - - cmipci_sb_reg_decode(®, kcontrol->private_value); - uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = reg.stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = reg.mask; - return 0; -} - -static int snd_cmipci_get_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - struct cmipci_sb_reg reg; - int val; - - cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); - val = (snd_cmipci_mixer_read(cm, reg.left_reg) >> reg.left_shift) & reg.mask; - if (reg.invert) - val = reg.mask - val; - ucontrol->value.integer.value[0] = val; - if (reg.stereo) { - val = (snd_cmipci_mixer_read(cm, reg.right_reg) >> reg.right_shift) & reg.mask; - if (reg.invert) - val = reg.mask - val; - ucontrol->value.integer.value[1] = val; - } - spin_unlock_irq(&cm->reg_lock); - return 0; -} - -static int snd_cmipci_put_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - struct cmipci_sb_reg reg; - int change; - int left, right, oleft, oright; - - cmipci_sb_reg_decode(®, kcontrol->private_value); - left = ucontrol->value.integer.value[0] & reg.mask; - if (reg.invert) - left = reg.mask - left; - left <<= reg.left_shift; - if (reg.stereo) { - right = ucontrol->value.integer.value[1] & reg.mask; - if (reg.invert) - right = reg.mask - right; - right <<= reg.right_shift; - } else - right = 0; - spin_lock_irq(&cm->reg_lock); - oleft = snd_cmipci_mixer_read(cm, reg.left_reg); - left |= oleft & ~(reg.mask << reg.left_shift); - change = left != oleft; - if (reg.stereo) { - if (reg.left_reg != reg.right_reg) { - snd_cmipci_mixer_write(cm, reg.left_reg, left); - oright = snd_cmipci_mixer_read(cm, reg.right_reg); - } else - oright = left; - right |= oright & ~(reg.mask << reg.right_shift); - change |= right != oright; - snd_cmipci_mixer_write(cm, reg.right_reg, right); - } else - snd_cmipci_mixer_write(cm, reg.left_reg, left); - spin_unlock_irq(&cm->reg_lock); - return change; -} - -/* - * input route (left,right) -> (left,right) - */ -#define CMIPCI_SB_INPUT_SW(xname, left_shift, right_shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_cmipci_info_input_sw, \ - .get = snd_cmipci_get_input_sw, .put = snd_cmipci_put_input_sw, \ - .private_value = COMPOSE_SB_REG(SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, left_shift, right_shift, 1, 0, 1), \ -} - -static int snd_cmipci_info_input_sw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_cmipci_get_input_sw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - struct cmipci_sb_reg reg; - int val1, val2; - - cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); - val1 = snd_cmipci_mixer_read(cm, reg.left_reg); - val2 = snd_cmipci_mixer_read(cm, reg.right_reg); - spin_unlock_irq(&cm->reg_lock); - ucontrol->value.integer.value[0] = (val1 >> reg.left_shift) & 1; - ucontrol->value.integer.value[1] = (val2 >> reg.left_shift) & 1; - ucontrol->value.integer.value[2] = (val1 >> reg.right_shift) & 1; - ucontrol->value.integer.value[3] = (val2 >> reg.right_shift) & 1; - return 0; -} - -static int snd_cmipci_put_input_sw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - struct cmipci_sb_reg reg; - int change; - int val1, val2, oval1, oval2; - - cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); - oval1 = snd_cmipci_mixer_read(cm, reg.left_reg); - oval2 = snd_cmipci_mixer_read(cm, reg.right_reg); - val1 = oval1 & ~((1 << reg.left_shift) | (1 << reg.right_shift)); - val2 = oval2 & ~((1 << reg.left_shift) | (1 << reg.right_shift)); - val1 |= (ucontrol->value.integer.value[0] & 1) << reg.left_shift; - val2 |= (ucontrol->value.integer.value[1] & 1) << reg.left_shift; - val1 |= (ucontrol->value.integer.value[2] & 1) << reg.right_shift; - val2 |= (ucontrol->value.integer.value[3] & 1) << reg.right_shift; - change = val1 != oval1 || val2 != oval2; - snd_cmipci_mixer_write(cm, reg.left_reg, val1); - snd_cmipci_mixer_write(cm, reg.right_reg, val2); - spin_unlock_irq(&cm->reg_lock); - return change; -} - -/* - * native mixer switches/volumes - */ - -#define CMIPCI_MIXER_SW_STEREO(xname, reg, lshift, rshift, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_cmipci_info_native_mixer, \ - .get = snd_cmipci_get_native_mixer, .put = snd_cmipci_put_native_mixer, \ - .private_value = COMPOSE_SB_REG(reg, reg, lshift, rshift, 1, invert, 1), \ -} - -#define CMIPCI_MIXER_SW_MONO(xname, reg, shift, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_cmipci_info_native_mixer, \ - .get = snd_cmipci_get_native_mixer, .put = snd_cmipci_put_native_mixer, \ - .private_value = COMPOSE_SB_REG(reg, reg, shift, shift, 1, invert, 0), \ -} - -#define CMIPCI_MIXER_VOL_STEREO(xname, reg, lshift, rshift, mask) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_cmipci_info_native_mixer, \ - .get = snd_cmipci_get_native_mixer, .put = snd_cmipci_put_native_mixer, \ - .private_value = COMPOSE_SB_REG(reg, reg, lshift, rshift, mask, 0, 1), \ -} - -#define CMIPCI_MIXER_VOL_MONO(xname, reg, shift, mask) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_cmipci_info_native_mixer, \ - .get = snd_cmipci_get_native_mixer, .put = snd_cmipci_put_native_mixer, \ - .private_value = COMPOSE_SB_REG(reg, reg, shift, shift, mask, 0, 0), \ -} - -static int snd_cmipci_info_native_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct cmipci_sb_reg reg; - - cmipci_sb_reg_decode(®, kcontrol->private_value); - uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = reg.stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = reg.mask; - return 0; - -} - -static int snd_cmipci_get_native_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - struct cmipci_sb_reg reg; - unsigned char oreg, val; - - cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); - oreg = inb(cm->iobase + reg.left_reg); - val = (oreg >> reg.left_shift) & reg.mask; - if (reg.invert) - val = reg.mask - val; - ucontrol->value.integer.value[0] = val; - if (reg.stereo) { - val = (oreg >> reg.right_shift) & reg.mask; - if (reg.invert) - val = reg.mask - val; - ucontrol->value.integer.value[1] = val; - } - spin_unlock_irq(&cm->reg_lock); - return 0; -} - -static int snd_cmipci_put_native_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - struct cmipci_sb_reg reg; - unsigned char oreg, nreg, val; - - cmipci_sb_reg_decode(®, kcontrol->private_value); - spin_lock_irq(&cm->reg_lock); - oreg = inb(cm->iobase + reg.left_reg); - val = ucontrol->value.integer.value[0] & reg.mask; - if (reg.invert) - val = reg.mask - val; - nreg = oreg & ~(reg.mask << reg.left_shift); - nreg |= (val << reg.left_shift); - if (reg.stereo) { - val = ucontrol->value.integer.value[1] & reg.mask; - if (reg.invert) - val = reg.mask - val; - nreg &= ~(reg.mask << reg.right_shift); - nreg |= (val << reg.right_shift); - } - outb(nreg, cm->iobase + reg.left_reg); - spin_unlock_irq(&cm->reg_lock); - return (nreg != oreg); -} - -/* - * special case - check mixer sensitivity - */ -static int snd_cmipci_get_native_mixer_sensitive(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - //struct cmipci *cm = snd_kcontrol_chip(kcontrol); - return snd_cmipci_get_native_mixer(kcontrol, ucontrol); -} - -static int snd_cmipci_put_native_mixer_sensitive(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - if (cm->mixer_insensitive) { - /* ignored */ - return 0; - } - return snd_cmipci_put_native_mixer(kcontrol, ucontrol); -} - - -static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = { - CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31), - CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0), - CMIPCI_SB_VOL_STEREO("PCM Playback Volume", SB_DSP4_PCM_DEV, 3, 31), - //CMIPCI_MIXER_SW_MONO("PCM Playback Switch", CM_REG_MIXER1, CM_WSMUTE_SHIFT, 1), - { /* switch with sensitivity */ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .info = snd_cmipci_info_native_mixer, - .get = snd_cmipci_get_native_mixer_sensitive, - .put = snd_cmipci_put_native_mixer_sensitive, - .private_value = COMPOSE_SB_REG(CM_REG_MIXER1, CM_REG_MIXER1, CM_WSMUTE_SHIFT, CM_WSMUTE_SHIFT, 1, 1, 0), - }, - CMIPCI_MIXER_SW_STEREO("PCM Capture Switch", CM_REG_MIXER1, CM_WAVEINL_SHIFT, CM_WAVEINR_SHIFT, 0), - CMIPCI_SB_VOL_STEREO("Synth Playback Volume", SB_DSP4_SYNTH_DEV, 3, 31), - CMIPCI_MIXER_SW_MONO("Synth Playback Switch", CM_REG_MIXER1, CM_FMMUTE_SHIFT, 1), - CMIPCI_SB_INPUT_SW("Synth Capture Route", 6, 5), - CMIPCI_SB_VOL_STEREO("CD Playback Volume", SB_DSP4_CD_DEV, 3, 31), - CMIPCI_SB_SW_STEREO("CD Playback Switch", 2, 1), - CMIPCI_SB_INPUT_SW("CD Capture Route", 2, 1), - CMIPCI_SB_VOL_STEREO("Line Playback Volume", SB_DSP4_LINE_DEV, 3, 31), - CMIPCI_SB_SW_STEREO("Line Playback Switch", 4, 3), - CMIPCI_SB_INPUT_SW("Line Capture Route", 4, 3), - CMIPCI_SB_VOL_MONO("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), - CMIPCI_SB_SW_MONO("Mic Playback Switch", 0), - CMIPCI_DOUBLE("Mic Capture Switch", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0, 1, 0, 0), - CMIPCI_SB_VOL_MONO("Beep Playback Volume", SB_DSP4_SPEAKER_DEV, 6, 3), - CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15), - CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0), - CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0), - CMIPCI_MIXER_SW_MONO("Mic Boost Playback Switch", CM_REG_MIXER2, CM_MICGAINZ_SHIFT, 1), - CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), - CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), - CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), - CMIPCI_DOUBLE("Beep Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), - CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), -}; - -/* - * other switches - */ - -struct cmipci_switch_args { - int reg; /* register index */ - unsigned int mask; /* mask bits */ - unsigned int mask_on; /* mask bits to turn on */ - unsigned int is_byte: 1; /* byte access? */ - unsigned int ac3_sensitive: 1; /* access forbidden during - * non-audio operation? - */ -}; - -#define snd_cmipci_uswitch_info snd_ctl_boolean_mono_info - -static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol, - struct cmipci_switch_args *args) -{ - unsigned int val; - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&cm->reg_lock); - if (args->ac3_sensitive && cm->mixer_insensitive) { - ucontrol->value.integer.value[0] = 0; - spin_unlock_irq(&cm->reg_lock); - return 0; - } - if (args->is_byte) - val = inb(cm->iobase + args->reg); - else - val = snd_cmipci_read(cm, args->reg); - ucontrol->value.integer.value[0] = ((val & args->mask) == args->mask_on) ? 1 : 0; - spin_unlock_irq(&cm->reg_lock); - return 0; -} - -static int snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci_switch_args *args; - args = (struct cmipci_switch_args *)kcontrol->private_value; - if (snd_BUG_ON(!args)) - return -EINVAL; - return _snd_cmipci_uswitch_get(kcontrol, ucontrol, args); -} - -static int _snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol, - struct cmipci_switch_args *args) -{ - unsigned int val; - int change; - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&cm->reg_lock); - if (args->ac3_sensitive && cm->mixer_insensitive) { - /* ignored */ - spin_unlock_irq(&cm->reg_lock); - return 0; - } - if (args->is_byte) - val = inb(cm->iobase + args->reg); - else - val = snd_cmipci_read(cm, args->reg); - change = (val & args->mask) != (ucontrol->value.integer.value[0] ? - args->mask_on : (args->mask & ~args->mask_on)); - if (change) { - val &= ~args->mask; - if (ucontrol->value.integer.value[0]) - val |= args->mask_on; - else - val |= (args->mask & ~args->mask_on); - if (args->is_byte) - outb((unsigned char)val, cm->iobase + args->reg); - else - snd_cmipci_write(cm, args->reg, val); - } - spin_unlock_irq(&cm->reg_lock); - return change; -} - -static int snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci_switch_args *args; - args = (struct cmipci_switch_args *)kcontrol->private_value; - if (snd_BUG_ON(!args)) - return -EINVAL; - return _snd_cmipci_uswitch_put(kcontrol, ucontrol, args); -} - -#define DEFINE_SWITCH_ARG(sname, xreg, xmask, xmask_on, xis_byte, xac3) \ -static struct cmipci_switch_args cmipci_switch_arg_##sname = { \ - .reg = xreg, \ - .mask = xmask, \ - .mask_on = xmask_on, \ - .is_byte = xis_byte, \ - .ac3_sensitive = xac3, \ -} - -#define DEFINE_BIT_SWITCH_ARG(sname, xreg, xmask, xis_byte, xac3) \ - DEFINE_SWITCH_ARG(sname, xreg, xmask, xmask, xis_byte, xac3) - -#if 0 /* these will be controlled in pcm device */ -DEFINE_BIT_SWITCH_ARG(spdif_in, CM_REG_FUNCTRL1, CM_SPDF_1, 0, 0); -DEFINE_BIT_SWITCH_ARG(spdif_out, CM_REG_FUNCTRL1, CM_SPDF_0, 0, 0); -#endif -DEFINE_BIT_SWITCH_ARG(spdif_in_sel1, CM_REG_CHFORMAT, CM_SPDIF_SELECT1, 0, 0); -DEFINE_BIT_SWITCH_ARG(spdif_in_sel2, CM_REG_MISC_CTRL, CM_SPDIF_SELECT2, 0, 0); -DEFINE_BIT_SWITCH_ARG(spdif_enable, CM_REG_LEGACY_CTRL, CM_ENSPDOUT, 0, 0); -DEFINE_BIT_SWITCH_ARG(spdo2dac, CM_REG_FUNCTRL1, CM_SPDO2DAC, 0, 1); -DEFINE_BIT_SWITCH_ARG(spdi_valid, CM_REG_MISC, CM_SPDVALID, 1, 0); -DEFINE_BIT_SWITCH_ARG(spdif_copyright, CM_REG_LEGACY_CTRL, CM_SPDCOPYRHT, 0, 0); -DEFINE_BIT_SWITCH_ARG(spdif_dac_out, CM_REG_LEGACY_CTRL, CM_DAC2SPDO, 0, 1); -DEFINE_SWITCH_ARG(spdo_5v, CM_REG_MISC_CTRL, CM_SPDO5V, 0, 0, 0); /* inverse: 0 = 5V */ -// DEFINE_BIT_SWITCH_ARG(spdo_48k, CM_REG_MISC_CTRL, CM_SPDF_AC97|CM_SPDIF48K, 0, 1); -DEFINE_BIT_SWITCH_ARG(spdif_loop, CM_REG_FUNCTRL1, CM_SPDFLOOP, 0, 1); -DEFINE_BIT_SWITCH_ARG(spdi_monitor, CM_REG_MIXER1, CM_CDPLAY, 1, 0); -/* DEFINE_BIT_SWITCH_ARG(spdi_phase, CM_REG_CHFORMAT, CM_SPDIF_INVERSE, 0, 0); */ -DEFINE_BIT_SWITCH_ARG(spdi_phase, CM_REG_MISC, CM_SPDIF_INVERSE, 1, 0); -DEFINE_BIT_SWITCH_ARG(spdi_phase2, CM_REG_CHFORMAT, CM_SPDIF_INVERSE2, 0, 0); -#if CM_CH_PLAY == 1 -DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* reversed */ -#else -DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); -#endif -DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); -// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_REAR2LIN, 1, 0); -// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_CENTR2LIN|CM_BASE2LIN, 0, 0); -// DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ -DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); - -#define DEFINE_SWITCH(sname, stype, sarg) \ -{ .name = sname, \ - .iface = stype, \ - .info = snd_cmipci_uswitch_info, \ - .get = snd_cmipci_uswitch_get, \ - .put = snd_cmipci_uswitch_put, \ - .private_value = (unsigned long)&cmipci_switch_arg_##sarg,\ -} - -#define DEFINE_CARD_SWITCH(sname, sarg) DEFINE_SWITCH(sname, SNDRV_CTL_ELEM_IFACE_CARD, sarg) -#define DEFINE_MIXER_SWITCH(sname, sarg) DEFINE_SWITCH(sname, SNDRV_CTL_ELEM_IFACE_MIXER, sarg) - - -/* - * callbacks for spdif output switch - * needs toggle two registers.. - */ -static int snd_cmipci_spdout_enable_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int changed; - changed = _snd_cmipci_uswitch_get(kcontrol, ucontrol, &cmipci_switch_arg_spdif_enable); - changed |= _snd_cmipci_uswitch_get(kcontrol, ucontrol, &cmipci_switch_arg_spdo2dac); - return changed; -} - -static int snd_cmipci_spdout_enable_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *chip = snd_kcontrol_chip(kcontrol); - int changed; - changed = _snd_cmipci_uswitch_put(kcontrol, ucontrol, &cmipci_switch_arg_spdif_enable); - changed |= _snd_cmipci_uswitch_put(kcontrol, ucontrol, &cmipci_switch_arg_spdo2dac); - if (changed) { - if (ucontrol->value.integer.value[0]) { - if (chip->spdif_playback_avail) - snd_cmipci_set_bit(chip, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); - } else { - if (chip->spdif_playback_avail) - snd_cmipci_clear_bit(chip, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); - } - } - chip->spdif_playback_enabled = ucontrol->value.integer.value[0]; - return changed; -} - - -static int snd_cmipci_line_in_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - static const char *const texts[3] = { - "Line-In", "Rear Output", "Bass Output" - }; - - return snd_ctl_enum_info(uinfo, 1, - cm->chip_version >= 39 ? 3 : 2, texts); -} - -static inline unsigned int get_line_in_mode(struct cmipci *cm) -{ - unsigned int val; - if (cm->chip_version >= 39) { - val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); - if (val & (CM_CENTR2LIN | CM_BASE2LIN)) - return 2; - } - val = snd_cmipci_read_b(cm, CM_REG_MIXER1); - if (val & CM_REAR2LIN) - return 1; - return 0; -} - -static int snd_cmipci_line_in_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&cm->reg_lock); - ucontrol->value.enumerated.item[0] = get_line_in_mode(cm); - spin_unlock_irq(&cm->reg_lock); - return 0; -} - -static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - int change; - - spin_lock_irq(&cm->reg_lock); - if (ucontrol->value.enumerated.item[0] == 2) - change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); - else - change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); - if (ucontrol->value.enumerated.item[0] == 1) - change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); - else - change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); - spin_unlock_irq(&cm->reg_lock); - return change; -} - -static int snd_cmipci_mic_in_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char *const texts[2] = { "Mic-In", "Center/LFE Output" }; - - return snd_ctl_enum_info(uinfo, 1, 2, texts); -} - -static int snd_cmipci_mic_in_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - /* same bit as spdi_phase */ - spin_lock_irq(&cm->reg_lock); - ucontrol->value.enumerated.item[0] = - (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0; - spin_unlock_irq(&cm->reg_lock); - return 0; -} - -static int snd_cmipci_mic_in_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cmipci *cm = snd_kcontrol_chip(kcontrol); - int change; - - spin_lock_irq(&cm->reg_lock); - if (ucontrol->value.enumerated.item[0]) - change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); - else - change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); - spin_unlock_irq(&cm->reg_lock); - return change; -} - -/* both for CM8338/8738 */ -static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = { - DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), - { - .name = "Line-In Mode", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_cmipci_line_in_mode_info, - .get = snd_cmipci_line_in_mode_get, - .put = snd_cmipci_line_in_mode_put, - }, -}; - -/* for non-multichannel chips */ -static struct snd_kcontrol_new snd_cmipci_nomulti_switch __devinitdata = -DEFINE_MIXER_SWITCH("Exchange DAC", exchange_dac); - -/* only for CM8738 */ -static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata = { -#if 0 /* controlled in pcm device */ - DEFINE_MIXER_SWITCH("IEC958 In Record", spdif_in), - DEFINE_MIXER_SWITCH("IEC958 Out", spdif_out), - DEFINE_MIXER_SWITCH("IEC958 Out To DAC", spdo2dac), -#endif - // DEFINE_MIXER_SWITCH("IEC958 Output Switch", spdif_enable), - { .name = "IEC958 Output Switch", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_cmipci_uswitch_info, - .get = snd_cmipci_spdout_enable_get, - .put = snd_cmipci_spdout_enable_put, - }, - DEFINE_MIXER_SWITCH("IEC958 In Valid", spdi_valid), - DEFINE_MIXER_SWITCH("IEC958 Copyright", spdif_copyright), - DEFINE_MIXER_SWITCH("IEC958 5V", spdo_5v), -// DEFINE_MIXER_SWITCH("IEC958 In/Out 48KHz", spdo_48k), - DEFINE_MIXER_SWITCH("IEC958 Loop", spdif_loop), - DEFINE_MIXER_SWITCH("IEC958 In Monitor", spdi_monitor), -}; - -/* only for model 033/037 */ -static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] __devinitdata = { - DEFINE_MIXER_SWITCH("IEC958 Mix Analog", spdif_dac_out), - DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase), - DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel1), -}; - -/* only for model 039 or later */ -static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata = { - DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2), - DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), - { - .name = "Mic-In Mode", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_cmipci_mic_in_mode_info, - .get = snd_cmipci_mic_in_mode_get, - .put = snd_cmipci_mic_in_mode_put, - } -}; - -/* card control switches */ -static struct snd_kcontrol_new snd_cmipci_modem_switch __devinitdata = -DEFINE_CARD_SWITCH("Modem", modem); - - -static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device) -{ - struct snd_card *card; - struct snd_kcontrol_new *sw; - struct snd_kcontrol *kctl; - unsigned int idx; - int err; - - if (snd_BUG_ON(!cm || !cm->card)) - return -EINVAL; - - card = cm->card; - - strcpy(card->mixername, "CMedia PCI"); - - spin_lock_irq(&cm->reg_lock); - snd_cmipci_mixer_write(cm, 0x00, 0x00); /* mixer reset */ - spin_unlock_irq(&cm->reg_lock); - - for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixers); idx++) { - if (cm->chip_version == 68) { // 8768 has no PCM volume - if (!strcmp(snd_cmipci_mixers[idx].name, - "PCM Playback Volume")) - continue; - } - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm))) < 0) - return err; - } - - /* mixer switches */ - sw = snd_cmipci_mixer_switches; - for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixer_switches); idx++, sw++) { - err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm)); - if (err < 0) - return err; - } - if (! cm->can_multi_ch) { - err = snd_ctl_add(cm->card, snd_ctl_new1(&snd_cmipci_nomulti_switch, cm)); - if (err < 0) - return err; - } - if (cm->device == PCI_DEVICE_ID_CMEDIA_CM8738 || - cm->device == PCI_DEVICE_ID_CMEDIA_CM8738B) { - sw = snd_cmipci_8738_mixer_switches; - for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_8738_mixer_switches); idx++, sw++) { - err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm)); - if (err < 0) - return err; - } - if (cm->can_ac3_hw) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_cmipci_spdif_default, cm))) < 0) - return err; - kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_cmipci_spdif_mask, cm))) < 0) - return err; - kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_cmipci_spdif_stream, cm))) < 0) - return err; - kctl->id.device = pcm_spdif_device; - } - if (cm->chip_version <= 37) { - sw = snd_cmipci_old_mixer_switches; - for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_old_mixer_switches); idx++, sw++) { - err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm)); - if (err < 0) - return err; - } - } - } - if (cm->chip_version >= 39) { - sw = snd_cmipci_extra_mixer_switches; - for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_extra_mixer_switches); idx++, sw++) { - err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm)); - if (err < 0) - return err; - } - } - - /* card switches */ - /* - * newer chips don't have the register bits to force modem link - * detection; the bit that was FLINKON now mutes CH1 - */ - if (cm->chip_version < 39) { - err = snd_ctl_add(cm->card, - snd_ctl_new1(&snd_cmipci_modem_switch, cm)); - if (err < 0) - return err; - } - - for (idx = 0; idx < CM_SAVED_MIXERS; idx++) { - struct snd_ctl_elem_id elem_id; - struct snd_kcontrol *ctl; - memset(&elem_id, 0, sizeof(elem_id)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(elem_id.name, cm_saved_mixer[idx].name); - ctl = snd_ctl_find_id(cm->card, &elem_id); - if (ctl) - cm->mixer_res_ctl[idx] = ctl; - } - - return 0; -} - - -/* - * proc interface - */ - -#ifdef CONFIG_PROC_FS -static void snd_cmipci_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct cmipci *cm = entry->private_data; - int i, v; - - snd_iprintf(buffer, "%s\n", cm->card->longname); - for (i = 0; i < 0x94; i++) { - if (i == 0x28) - i = 0x90; - v = inb(cm->iobase + i); - if (i % 4 == 0) - snd_iprintf(buffer, "\n%02x:", i); - snd_iprintf(buffer, " %02x", v); - } - snd_iprintf(buffer, "\n"); -} - -static void __devinit snd_cmipci_proc_init(struct cmipci *cm) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(cm->card, "cmipci", &entry)) - snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read); -} -#else /* !CONFIG_PROC_FS */ -static inline void snd_cmipci_proc_init(struct cmipci *cm) {} -#endif - - -static DEFINE_PCI_DEVICE_TABLE(snd_cmipci_ids) = { - {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0}, - {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B), 0}, - {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, - {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B), 0}, - {PCI_VDEVICE(AL, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, - {0,}, -}; - - -/* - * check chip version and capabilities - * driver name is modified according to the chip model - */ -static void __devinit query_chip(struct cmipci *cm) -{ - unsigned int detect; - - /* check reg 0Ch, bit 24-31 */ - detect = snd_cmipci_read(cm, CM_REG_INT_HLDCLR) & CM_CHIP_MASK2; - if (! detect) { - /* check reg 08h, bit 24-28 */ - detect = snd_cmipci_read(cm, CM_REG_CHFORMAT) & CM_CHIP_MASK1; - switch (detect) { - case 0: - cm->chip_version = 33; - if (cm->do_soft_ac3) - cm->can_ac3_sw = 1; - else - cm->can_ac3_hw = 1; - break; - case CM_CHIP_037: - cm->chip_version = 37; - cm->can_ac3_hw = 1; - break; - default: - cm->chip_version = 39; - cm->can_ac3_hw = 1; - break; - } - cm->max_channels = 2; - } else { - if (detect & CM_CHIP_039) { - cm->chip_version = 39; - if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */ - cm->max_channels = 6; - else - cm->max_channels = 4; - } else if (detect & CM_CHIP_8768) { - cm->chip_version = 68; - cm->max_channels = 8; - cm->can_96k = 1; - } else { - cm->chip_version = 55; - cm->max_channels = 6; - cm->can_96k = 1; - } - cm->can_ac3_hw = 1; - cm->can_multi_ch = 1; - } -} - -#ifdef SUPPORT_JOYSTICK -static int __devinit snd_cmipci_create_gameport(struct cmipci *cm, int dev) -{ - static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */ - struct gameport *gp; - struct resource *r = NULL; - int i, io_port = 0; - - if (joystick_port[dev] == 0) - return -ENODEV; - - if (joystick_port[dev] == 1) { /* auto-detect */ - for (i = 0; ports[i]; i++) { - io_port = ports[i]; - r = request_region(io_port, 1, "CMIPCI gameport"); - if (r) - break; - } - } else { - io_port = joystick_port[dev]; - r = request_region(io_port, 1, "CMIPCI gameport"); - } - - if (!r) { - printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n"); - return -EBUSY; - } - - cm->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n"); - release_and_free_resource(r); - return -ENOMEM; - } - gameport_set_name(gp, "C-Media Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci)); - gameport_set_dev_parent(gp, &cm->pci->dev); - gp->io = io_port; - gameport_set_port_data(gp, r); - - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - - gameport_register_port(cm->gameport); - - return 0; -} - -static void snd_cmipci_free_gameport(struct cmipci *cm) -{ - if (cm->gameport) { - struct resource *r = gameport_get_port_data(cm->gameport); - - gameport_unregister_port(cm->gameport); - cm->gameport = NULL; - - snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - release_and_free_resource(r); - } -} -#else -static inline int snd_cmipci_create_gameport(struct cmipci *cm, int dev) { return -ENOSYS; } -static inline void snd_cmipci_free_gameport(struct cmipci *cm) { } -#endif - -static int snd_cmipci_free(struct cmipci *cm) -{ - if (cm->irq >= 0) { - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); - snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); - snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */ - snd_cmipci_ch_reset(cm, CM_CH_PLAY); - snd_cmipci_ch_reset(cm, CM_CH_CAPT); - snd_cmipci_write(cm, CM_REG_FUNCTRL0, 0); /* disable channels */ - snd_cmipci_write(cm, CM_REG_FUNCTRL1, 0); - - /* reset mixer */ - snd_cmipci_mixer_write(cm, 0, 0); - - free_irq(cm->irq, cm); - } - - snd_cmipci_free_gameport(cm); - pci_release_regions(cm->pci); - pci_disable_device(cm->pci); - kfree(cm); - return 0; -} - -static int snd_cmipci_dev_free(struct snd_device *device) -{ - struct cmipci *cm = device->device_data; - return snd_cmipci_free(cm); -} - -static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port) -{ - long iosynth; - unsigned int val; - struct snd_opl3 *opl3; - int err; - - if (!fm_port) - goto disable_fm; - - if (cm->chip_version >= 39) { - /* first try FM regs in PCI port range */ - iosynth = cm->iobase + CM_REG_FM_PCI; - err = snd_opl3_create(cm->card, iosynth, iosynth + 2, - OPL3_HW_OPL3, 1, &opl3); - } else { - err = -EIO; - } - if (err < 0) { - /* then try legacy ports */ - val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; - iosynth = fm_port; - switch (iosynth) { - case 0x3E8: val |= CM_FMSEL_3E8; break; - case 0x3E0: val |= CM_FMSEL_3E0; break; - case 0x3C8: val |= CM_FMSEL_3C8; break; - case 0x388: val |= CM_FMSEL_388; break; - default: - goto disable_fm; - } - snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); - /* enable FM */ - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); - - if (snd_opl3_create(cm->card, iosynth, iosynth + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) { - printk(KERN_ERR "cmipci: no OPL device at %#lx, " - "skipping...\n", iosynth); - goto disable_fm; - } - } - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - printk(KERN_ERR "cmipci: cannot create OPL3 hwdep\n"); - return err; - } - return 0; - - disable_fm: - snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_FMSEL_MASK); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); - return 0; -} - -static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, - int dev, struct cmipci **rcmipci) -{ - struct cmipci *cm; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_cmipci_dev_free, - }; - unsigned int val; - long iomidi = 0; - int integrated_midi = 0; - char modelstr[16]; - int pcm_index, pcm_spdif_index; - static DEFINE_PCI_DEVICE_TABLE(intel_82437vx) = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) }, - { }, - }; - - *rcmipci = NULL; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - cm = kzalloc(sizeof(*cm), GFP_KERNEL); - if (cm == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - spin_lock_init(&cm->reg_lock); - mutex_init(&cm->open_mutex); - cm->device = pci->device; - cm->card = card; - cm->pci = pci; - cm->irq = -1; - cm->channel[0].ch = 0; - cm->channel[1].ch = 1; - cm->channel[0].is_dac = cm->channel[1].is_dac = 1; /* dual DAC mode */ - - if ((err = pci_request_regions(pci, card->driver)) < 0) { - kfree(cm); - pci_disable_device(pci); - return err; - } - cm->iobase = pci_resource_start(pci, 0); - - if (request_irq(pci->irq, snd_cmipci_interrupt, - IRQF_SHARED, KBUILD_MODNAME, cm)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_cmipci_free(cm); - return -EBUSY; - } - cm->irq = pci->irq; - - pci_set_master(cm->pci); - - /* - * check chip version, max channels and capabilities - */ - - cm->chip_version = 0; - cm->max_channels = 2; - cm->do_soft_ac3 = soft_ac3[dev]; - - if (pci->device != PCI_DEVICE_ID_CMEDIA_CM8338A && - pci->device != PCI_DEVICE_ID_CMEDIA_CM8338B) - query_chip(cm); - /* added -MCx suffix for chip supporting multi-channels */ - if (cm->can_multi_ch) - sprintf(cm->card->driver + strlen(cm->card->driver), - "-MC%d", cm->max_channels); - else if (cm->can_ac3_sw) - strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC"); - - cm->dig_status = SNDRV_PCM_DEFAULT_CON_SPDIF; - cm->dig_pcm_status = SNDRV_PCM_DEFAULT_CON_SPDIF; - -#if CM_CH_PLAY == 1 - cm->ctrl = CM_CHADC0; /* default FUNCNTRL0 */ -#else - cm->ctrl = CM_CHADC1; /* default FUNCNTRL0 */ -#endif - - /* initialize codec registers */ - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_RESET); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_RESET); - snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */ - snd_cmipci_ch_reset(cm, CM_CH_PLAY); - snd_cmipci_ch_reset(cm, CM_CH_CAPT); - snd_cmipci_write(cm, CM_REG_FUNCTRL0, 0); /* disable channels */ - snd_cmipci_write(cm, CM_REG_FUNCTRL1, 0); - - snd_cmipci_write(cm, CM_REG_CHFORMAT, 0); - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC|CM_N4SPK3D); -#if CM_CH_PLAY == 1 - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); -#else - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); -#endif - if (cm->chip_version) { - snd_cmipci_write_b(cm, CM_REG_EXT_MISC, 0x20); /* magic */ - snd_cmipci_write_b(cm, CM_REG_EXT_MISC + 1, 0x09); /* more magic */ - } - /* Set Bus Master Request */ - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_BREQ); - - /* Assume TX and compatible chip set (Autodetection required for VX chip sets) */ - switch (pci->device) { - case PCI_DEVICE_ID_CMEDIA_CM8738: - case PCI_DEVICE_ID_CMEDIA_CM8738B: - if (!pci_dev_present(intel_82437vx)) - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_TXVX); - break; - default: - break; - } - - if (cm->chip_version < 68) { - val = pci->device < 0x110 ? 8338 : 8738; - } else { - switch (snd_cmipci_read_b(cm, CM_REG_INT_HLDCLR + 3) & 0x03) { - case 0: - val = 8769; - break; - case 2: - val = 8762; - break; - default: - switch ((pci->subsystem_vendor << 16) | - pci->subsystem_device) { - case 0x13f69761: - case 0x584d3741: - case 0x584d3751: - case 0x584d3761: - case 0x584d3771: - case 0x72848384: - val = 8770; - break; - default: - val = 8768; - break; - } - } - } - sprintf(card->shortname, "C-Media CMI%d", val); - if (cm->chip_version < 68) - sprintf(modelstr, " (model %d)", cm->chip_version); - else - modelstr[0] = '\0'; - sprintf(card->longname, "%s%s at %#lx, irq %i", - card->shortname, modelstr, cm->iobase, cm->irq); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops)) < 0) { - snd_cmipci_free(cm); - return err; - } - - if (cm->chip_version >= 39) { - val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1); - if (val != 0x00 && val != 0xff) { - iomidi = cm->iobase + CM_REG_MPU_PCI; - integrated_midi = 1; - } - } - if (!integrated_midi) { - val = 0; - iomidi = mpu_port[dev]; - switch (iomidi) { - case 0x320: val = CM_VMPU_320; break; - case 0x310: val = CM_VMPU_310; break; - case 0x300: val = CM_VMPU_300; break; - case 0x330: val = CM_VMPU_330; break; - default: - iomidi = 0; break; - } - if (iomidi > 0) { - snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); - /* enable UART */ - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); - if (inb(iomidi + 1) == 0xff) { - snd_printk(KERN_ERR "cannot enable MPU-401 port" - " at %#lx\n", iomidi); - snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, - CM_UART_EN); - iomidi = 0; - } - } - } - - if (cm->chip_version < 68) { - err = snd_cmipci_create_fm(cm, fm_port[dev]); - if (err < 0) - return err; - } - - /* reset mixer */ - snd_cmipci_mixer_write(cm, 0, 0); - - snd_cmipci_proc_init(cm); - - /* create pcm devices */ - pcm_index = pcm_spdif_index = 0; - if ((err = snd_cmipci_pcm_new(cm, pcm_index)) < 0) - return err; - pcm_index++; - if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0) - return err; - pcm_index++; - if (cm->can_ac3_hw || cm->can_ac3_sw) { - pcm_spdif_index = pcm_index; - if ((err = snd_cmipci_pcm_spdif_new(cm, pcm_index)) < 0) - return err; - } - - /* create mixer interface & switches */ - if ((err = snd_cmipci_mixer_new(cm, pcm_spdif_index)) < 0) - return err; - - if (iomidi > 0) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, - iomidi, - (integrated_midi ? - MPU401_INFO_INTEGRATED : 0) | - MPU401_INFO_IRQ_HOOK, - -1, &cm->rmidi)) < 0) { - printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); - } - } - -#ifdef USE_VAR48KRATE - for (val = 0; val < ARRAY_SIZE(rates); val++) - snd_cmipci_set_pll(cm, rates[val], val); - - /* - * (Re-)Enable external switch spdo_48k - */ - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K|CM_SPDF_AC97); -#endif /* USE_VAR48KRATE */ - - if (snd_cmipci_create_gameport(cm, dev) < 0) - snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - - snd_card_set_dev(card, &pci->dev); - - *rcmipci = cm; - return 0; -} - -/* - */ - -MODULE_DEVICE_TABLE(pci, snd_cmipci_ids); - -static int __devinit snd_cmipci_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct cmipci *cm; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (! enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - switch (pci->device) { - case PCI_DEVICE_ID_CMEDIA_CM8738: - case PCI_DEVICE_ID_CMEDIA_CM8738B: - strcpy(card->driver, "CMI8738"); - break; - case PCI_DEVICE_ID_CMEDIA_CM8338A: - case PCI_DEVICE_ID_CMEDIA_CM8338B: - strcpy(card->driver, "CMI8338"); - break; - default: - strcpy(card->driver, "CMIPCI"); - break; - } - - if ((err = snd_cmipci_create(card, pci, dev, &cm)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = cm; - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; - -} - -static void __devexit snd_cmipci_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - - -#ifdef CONFIG_PM -/* - * power management - */ -static unsigned char saved_regs[] = { - CM_REG_FUNCTRL1, CM_REG_CHFORMAT, CM_REG_LEGACY_CTRL, CM_REG_MISC_CTRL, - CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_MIXER3, CM_REG_PLL, - CM_REG_CH0_FRAME1, CM_REG_CH0_FRAME2, - CM_REG_CH1_FRAME1, CM_REG_CH1_FRAME2, CM_REG_EXT_MISC, - CM_REG_INT_STATUS, CM_REG_INT_HLDCLR, CM_REG_FUNCTRL0, -}; - -static unsigned char saved_mixers[] = { - SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, - SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, - SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, - SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, - SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1, - SB_DSP4_MIC_DEV, SB_DSP4_SPEAKER_DEV, - CM_REG_EXTENT_IND, SB_DSP4_OUTPUT_SW, - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, -}; - -static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct cmipci *cm = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(cm->pcm); - snd_pcm_suspend_all(cm->pcm2); - snd_pcm_suspend_all(cm->pcm_spdif); - - /* save registers */ - for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - cm->saved_regs[i] = snd_cmipci_read(cm, saved_regs[i]); - for (i = 0; i < ARRAY_SIZE(saved_mixers); i++) - cm->saved_mixers[i] = snd_cmipci_mixer_read(cm, saved_mixers[i]); - - /* disable ints */ - snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_cmipci_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct cmipci *cm = card->private_data; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cmipci: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - /* reset / initialize to a sane state */ - snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); - snd_cmipci_ch_reset(cm, CM_CH_PLAY); - snd_cmipci_ch_reset(cm, CM_CH_CAPT); - snd_cmipci_mixer_write(cm, 0, 0); - - /* restore registers */ - for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - snd_cmipci_write(cm, saved_regs[i], cm->saved_regs[i]); - for (i = 0; i < ARRAY_SIZE(saved_mixers); i++) - snd_cmipci_mixer_write(cm, saved_mixers[i], cm->saved_mixers[i]); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_cmipci_ids, - .probe = snd_cmipci_probe, - .remove = __devexit_p(snd_cmipci_remove), -#ifdef CONFIG_PM - .suspend = snd_cmipci_suspend, - .resume = snd_cmipci_resume, -#endif -}; - -static int __init alsa_card_cmipci_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_cmipci_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_cmipci_init) -module_exit(alsa_card_cmipci_exit) diff --git a/ANDROID_3.4.5/sound/pci/cs4281.c b/ANDROID_3.4.5/sound/pci/cs4281.c deleted file mode 100644 index a9f368f6..00000000 --- a/ANDROID_3.4.5/sound/pci/cs4281.c +++ /dev/null @@ -1,2109 +0,0 @@ -/* - * Driver for Cirrus Logic CS4281 based PCI soundcard - * Copyright (c) by Jaroslav Kysela , - * - * - * 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 -#include -#include -#include -#include -#include -#include -#include - - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Cirrus Logic CS4281"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ -static bool dual_codec[SNDRV_CARDS]; /* dual codec */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for CS4281 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for CS4281 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable CS4281 soundcard."); -module_param_array(dual_codec, bool, NULL, 0444); -MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled)."); - -/* - * Direct registers - */ - -#define CS4281_BA0_SIZE 0x1000 -#define CS4281_BA1_SIZE 0x10000 - -/* - * BA0 registers - */ -#define BA0_HISR 0x0000 /* Host Interrupt Status Register */ -#define BA0_HISR_INTENA (1<<31) /* Internal Interrupt Enable Bit */ -#define BA0_HISR_MIDI (1<<22) /* MIDI port interrupt */ -#define BA0_HISR_FIFOI (1<<20) /* FIFO polled interrupt */ -#define BA0_HISR_DMAI (1<<18) /* DMA interrupt (half or end) */ -#define BA0_HISR_FIFO(c) (1<<(12+(c))) /* FIFO channel interrupt */ -#define BA0_HISR_DMA(c) (1<<(8+(c))) /* DMA channel interrupt */ -#define BA0_HISR_GPPI (1<<5) /* General Purpose Input (Primary chip) */ -#define BA0_HISR_GPSI (1<<4) /* General Purpose Input (Secondary chip) */ -#define BA0_HISR_GP3I (1<<3) /* GPIO3 pin Interrupt */ -#define BA0_HISR_GP1I (1<<2) /* GPIO1 pin Interrupt */ -#define BA0_HISR_VUPI (1<<1) /* VOLUP pin Interrupt */ -#define BA0_HISR_VDNI (1<<0) /* VOLDN pin Interrupt */ - -#define BA0_HICR 0x0008 /* Host Interrupt Control Register */ -#define BA0_HICR_CHGM (1<<1) /* INTENA Change Mask */ -#define BA0_HICR_IEV (1<<0) /* INTENA Value */ -#define BA0_HICR_EOI (3<<0) /* End of Interrupt command */ - -#define BA0_HIMR 0x000c /* Host Interrupt Mask Register */ - /* Use same contants as for BA0_HISR */ - -#define BA0_IIER 0x0010 /* ISA Interrupt Enable Register */ - -#define BA0_HDSR0 0x00f0 /* Host DMA Engine 0 Status Register */ -#define BA0_HDSR1 0x00f4 /* Host DMA Engine 1 Status Register */ -#define BA0_HDSR2 0x00f8 /* Host DMA Engine 2 Status Register */ -#define BA0_HDSR3 0x00fc /* Host DMA Engine 3 Status Register */ - -#define BA0_HDSR_CH1P (1<<25) /* Channel 1 Pending */ -#define BA0_HDSR_CH2P (1<<24) /* Channel 2 Pending */ -#define BA0_HDSR_DHTC (1<<17) /* DMA Half Terminal Count */ -#define BA0_HDSR_DTC (1<<16) /* DMA Terminal Count */ -#define BA0_HDSR_DRUN (1<<15) /* DMA Running */ -#define BA0_HDSR_RQ (1<<7) /* Pending Request */ - -#define BA0_DCA0 0x0110 /* Host DMA Engine 0 Current Address */ -#define BA0_DCC0 0x0114 /* Host DMA Engine 0 Current Count */ -#define BA0_DBA0 0x0118 /* Host DMA Engine 0 Base Address */ -#define BA0_DBC0 0x011c /* Host DMA Engine 0 Base Count */ -#define BA0_DCA1 0x0120 /* Host DMA Engine 1 Current Address */ -#define BA0_DCC1 0x0124 /* Host DMA Engine 1 Current Count */ -#define BA0_DBA1 0x0128 /* Host DMA Engine 1 Base Address */ -#define BA0_DBC1 0x012c /* Host DMA Engine 1 Base Count */ -#define BA0_DCA2 0x0130 /* Host DMA Engine 2 Current Address */ -#define BA0_DCC2 0x0134 /* Host DMA Engine 2 Current Count */ -#define BA0_DBA2 0x0138 /* Host DMA Engine 2 Base Address */ -#define BA0_DBC2 0x013c /* Host DMA Engine 2 Base Count */ -#define BA0_DCA3 0x0140 /* Host DMA Engine 3 Current Address */ -#define BA0_DCC3 0x0144 /* Host DMA Engine 3 Current Count */ -#define BA0_DBA3 0x0148 /* Host DMA Engine 3 Base Address */ -#define BA0_DBC3 0x014c /* Host DMA Engine 3 Base Count */ -#define BA0_DMR0 0x0150 /* Host DMA Engine 0 Mode */ -#define BA0_DCR0 0x0154 /* Host DMA Engine 0 Command */ -#define BA0_DMR1 0x0158 /* Host DMA Engine 1 Mode */ -#define BA0_DCR1 0x015c /* Host DMA Engine 1 Command */ -#define BA0_DMR2 0x0160 /* Host DMA Engine 2 Mode */ -#define BA0_DCR2 0x0164 /* Host DMA Engine 2 Command */ -#define BA0_DMR3 0x0168 /* Host DMA Engine 3 Mode */ -#define BA0_DCR3 0x016c /* Host DMA Engine 3 Command */ - -#define BA0_DMR_DMA (1<<29) /* Enable DMA mode */ -#define BA0_DMR_POLL (1<<28) /* Enable poll mode */ -#define BA0_DMR_TBC (1<<25) /* Transfer By Channel */ -#define BA0_DMR_CBC (1<<24) /* Count By Channel (0 = frame resolution) */ -#define BA0_DMR_SWAPC (1<<22) /* Swap Left/Right Channels */ -#define BA0_DMR_SIZE20 (1<<20) /* Sample is 20-bit */ -#define BA0_DMR_USIGN (1<<19) /* Unsigned */ -#define BA0_DMR_BEND (1<<18) /* Big Endian */ -#define BA0_DMR_MONO (1<<17) /* Mono */ -#define BA0_DMR_SIZE8 (1<<16) /* Sample is 8-bit */ -#define BA0_DMR_TYPE_DEMAND (0<<6) -#define BA0_DMR_TYPE_SINGLE (1<<6) -#define BA0_DMR_TYPE_BLOCK (2<<6) -#define BA0_DMR_TYPE_CASCADE (3<<6) /* Not supported */ -#define BA0_DMR_DEC (1<<5) /* Access Increment (0) or Decrement (1) */ -#define BA0_DMR_AUTO (1<<4) /* Auto-Initialize */ -#define BA0_DMR_TR_VERIFY (0<<2) /* Verify Transfer */ -#define BA0_DMR_TR_WRITE (1<<2) /* Write Transfer */ -#define BA0_DMR_TR_READ (2<<2) /* Read Transfer */ - -#define BA0_DCR_HTCIE (1<<17) /* Half Terminal Count Interrupt */ -#define BA0_DCR_TCIE (1<<16) /* Terminal Count Interrupt */ -#define BA0_DCR_MSK (1<<0) /* DMA Mask bit */ - -#define BA0_FCR0 0x0180 /* FIFO Control 0 */ -#define BA0_FCR1 0x0184 /* FIFO Control 1 */ -#define BA0_FCR2 0x0188 /* FIFO Control 2 */ -#define BA0_FCR3 0x018c /* FIFO Control 3 */ - -#define BA0_FCR_FEN (1<<31) /* FIFO Enable bit */ -#define BA0_FCR_DACZ (1<<30) /* DAC Zero */ -#define BA0_FCR_PSH (1<<29) /* Previous Sample Hold */ -#define BA0_FCR_RS(x) (((x)&0x1f)<<24) /* Right Slot Mapping */ -#define BA0_FCR_LS(x) (((x)&0x1f)<<16) /* Left Slot Mapping */ -#define BA0_FCR_SZ(x) (((x)&0x7f)<<8) /* FIFO buffer size (in samples) */ -#define BA0_FCR_OF(x) (((x)&0x7f)<<0) /* FIFO starting offset (in samples) */ - -#define BA0_FPDR0 0x0190 /* FIFO Polled Data 0 */ -#define BA0_FPDR1 0x0194 /* FIFO Polled Data 1 */ -#define BA0_FPDR2 0x0198 /* FIFO Polled Data 2 */ -#define BA0_FPDR3 0x019c /* FIFO Polled Data 3 */ - -#define BA0_FCHS 0x020c /* FIFO Channel Status */ -#define BA0_FCHS_RCO(x) (1<<(7+(((x)&3)<<3))) /* Right Channel Out */ -#define BA0_FCHS_LCO(x) (1<<(6+(((x)&3)<<3))) /* Left Channel Out */ -#define BA0_FCHS_MRP(x) (1<<(5+(((x)&3)<<3))) /* Move Read Pointer */ -#define BA0_FCHS_FE(x) (1<<(4+(((x)&3)<<3))) /* FIFO Empty */ -#define BA0_FCHS_FF(x) (1<<(3+(((x)&3)<<3))) /* FIFO Full */ -#define BA0_FCHS_IOR(x) (1<<(2+(((x)&3)<<3))) /* Internal Overrun Flag */ -#define BA0_FCHS_RCI(x) (1<<(1+(((x)&3)<<3))) /* Right Channel In */ -#define BA0_FCHS_LCI(x) (1<<(0+(((x)&3)<<3))) /* Left Channel In */ - -#define BA0_FSIC0 0x0210 /* FIFO Status and Interrupt Control 0 */ -#define BA0_FSIC1 0x0214 /* FIFO Status and Interrupt Control 1 */ -#define BA0_FSIC2 0x0218 /* FIFO Status and Interrupt Control 2 */ -#define BA0_FSIC3 0x021c /* FIFO Status and Interrupt Control 3 */ - -#define BA0_FSIC_FIC(x) (((x)&0x7f)<<24) /* FIFO Interrupt Count */ -#define BA0_FSIC_FORIE (1<<23) /* FIFO OverRun Interrupt Enable */ -#define BA0_FSIC_FURIE (1<<22) /* FIFO UnderRun Interrupt Enable */ -#define BA0_FSIC_FSCIE (1<<16) /* FIFO Sample Count Interrupt Enable */ -#define BA0_FSIC_FSC(x) (((x)&0x7f)<<8) /* FIFO Sample Count */ -#define BA0_FSIC_FOR (1<<7) /* FIFO OverRun */ -#define BA0_FSIC_FUR (1<<6) /* FIFO UnderRun */ -#define BA0_FSIC_FSCR (1<<0) /* FIFO Sample Count Reached */ - -#define BA0_PMCS 0x0344 /* Power Management Control/Status */ -#define BA0_CWPR 0x03e0 /* Configuration Write Protect */ - -#define BA0_EPPMC 0x03e4 /* Extended PCI Power Management Control */ -#define BA0_EPPMC_FPDN (1<<14) /* Full Power DowN */ - -#define BA0_GPIOR 0x03e8 /* GPIO Pin Interface Register */ - -#define BA0_SPMC 0x03ec /* Serial Port Power Management Control (& ASDIN2 enable) */ -#define BA0_SPMC_GIPPEN (1<<15) /* GP INT Primary PME# Enable */ -#define BA0_SPMC_GISPEN (1<<14) /* GP INT Secondary PME# Enable */ -#define BA0_SPMC_EESPD (1<<9) /* EEPROM Serial Port Disable */ -#define BA0_SPMC_ASDI2E (1<<8) /* ASDIN2 Enable */ -#define BA0_SPMC_ASDO (1<<7) /* Asynchronous ASDOUT Assertion */ -#define BA0_SPMC_WUP2 (1<<3) /* Wakeup for Secondary Input */ -#define BA0_SPMC_WUP1 (1<<2) /* Wakeup for Primary Input */ -#define BA0_SPMC_ASYNC (1<<1) /* Asynchronous ASYNC Assertion */ -#define BA0_SPMC_RSTN (1<<0) /* Reset Not! */ - -#define BA0_CFLR 0x03f0 /* Configuration Load Register (EEPROM or BIOS) */ -#define BA0_CFLR_DEFAULT 0x00000001 /* CFLR must be in AC97 link mode */ -#define BA0_IISR 0x03f4 /* ISA Interrupt Select */ -#define BA0_TMS 0x03f8 /* Test Register */ -#define BA0_SSVID 0x03fc /* Subsystem ID register */ - -#define BA0_CLKCR1 0x0400 /* Clock Control Register 1 */ -#define BA0_CLKCR1_CLKON (1<<25) /* Read Only */ -#define BA0_CLKCR1_DLLRDY (1<<24) /* DLL Ready */ -#define BA0_CLKCR1_DLLOS (1<<6) /* DLL Output Select */ -#define BA0_CLKCR1_SWCE (1<<5) /* Clock Enable */ -#define BA0_CLKCR1_DLLP (1<<4) /* DLL PowerUp */ -#define BA0_CLKCR1_DLLSS (((x)&3)<<3) /* DLL Source Select */ - -#define BA0_FRR 0x0410 /* Feature Reporting Register */ -#define BA0_SLT12O 0x041c /* Slot 12 GPIO Output Register for AC-Link */ - -#define BA0_SERMC 0x0420 /* Serial Port Master Control */ -#define BA0_SERMC_FCRN (1<<27) /* Force Codec Ready Not */ -#define BA0_SERMC_ODSEN2 (1<<25) /* On-Demand Support Enable ASDIN2 */ -#define BA0_SERMC_ODSEN1 (1<<24) /* On-Demand Support Enable ASDIN1 */ -#define BA0_SERMC_SXLB (1<<21) /* ASDIN2 to ASDOUT Loopback */ -#define BA0_SERMC_SLB (1<<20) /* ASDOUT to ASDIN2 Loopback */ -#define BA0_SERMC_LOVF (1<<19) /* Loopback Output Valid Frame bit */ -#define BA0_SERMC_TCID(x) (((x)&3)<<16) /* Target Secondary Codec ID */ -#define BA0_SERMC_PXLB (5<<1) /* Primary Port External Loopback */ -#define BA0_SERMC_PLB (4<<1) /* Primary Port Internal Loopback */ -#define BA0_SERMC_PTC (7<<1) /* Port Timing Configuration */ -#define BA0_SERMC_PTC_AC97 (1<<1) /* AC97 mode */ -#define BA0_SERMC_MSPE (1<<0) /* Master Serial Port Enable */ - -#define BA0_SERC1 0x0428 /* Serial Port Configuration 1 */ -#define BA0_SERC1_SO1F(x) (((x)&7)>>1) /* Primary Output Port Format */ -#define BA0_SERC1_AC97 (1<<1) -#define BA0_SERC1_SO1EN (1<<0) /* Primary Output Port Enable */ - -#define BA0_SERC2 0x042c /* Serial Port Configuration 2 */ -#define BA0_SERC2_SI1F(x) (((x)&7)>>1) /* Primary Input Port Format */ -#define BA0_SERC2_AC97 (1<<1) -#define BA0_SERC2_SI1EN (1<<0) /* Primary Input Port Enable */ - -#define BA0_SLT12M 0x045c /* Slot 12 Monitor Register for Primary AC-Link */ - -#define BA0_ACCTL 0x0460 /* AC'97 Control */ -#define BA0_ACCTL_TC (1<<6) /* Target Codec */ -#define BA0_ACCTL_CRW (1<<4) /* 0=Write, 1=Read Command */ -#define BA0_ACCTL_DCV (1<<3) /* Dynamic Command Valid */ -#define BA0_ACCTL_VFRM (1<<2) /* Valid Frame */ -#define BA0_ACCTL_ESYN (1<<1) /* Enable Sync */ - -#define BA0_ACSTS 0x0464 /* AC'97 Status */ -#define BA0_ACSTS_VSTS (1<<1) /* Valid Status */ -#define BA0_ACSTS_CRDY (1<<0) /* Codec Ready */ - -#define BA0_ACOSV 0x0468 /* AC'97 Output Slot Valid */ -#define BA0_ACOSV_SLV(x) (1<<((x)-3)) - -#define BA0_ACCAD 0x046c /* AC'97 Command Address */ -#define BA0_ACCDA 0x0470 /* AC'97 Command Data */ - -#define BA0_ACISV 0x0474 /* AC'97 Input Slot Valid */ -#define BA0_ACISV_SLV(x) (1<<((x)-3)) - -#define BA0_ACSAD 0x0478 /* AC'97 Status Address */ -#define BA0_ACSDA 0x047c /* AC'97 Status Data */ -#define BA0_JSPT 0x0480 /* Joystick poll/trigger */ -#define BA0_JSCTL 0x0484 /* Joystick control */ -#define BA0_JSC1 0x0488 /* Joystick control */ -#define BA0_JSC2 0x048c /* Joystick control */ -#define BA0_JSIO 0x04a0 - -#define BA0_MIDCR 0x0490 /* MIDI Control */ -#define BA0_MIDCR_MRST (1<<5) /* Reset MIDI Interface */ -#define BA0_MIDCR_MLB (1<<4) /* MIDI Loop Back Enable */ -#define BA0_MIDCR_TIE (1<<3) /* MIDI Transmuit Interrupt Enable */ -#define BA0_MIDCR_RIE (1<<2) /* MIDI Receive Interrupt Enable */ -#define BA0_MIDCR_RXE (1<<1) /* MIDI Receive Enable */ -#define BA0_MIDCR_TXE (1<<0) /* MIDI Transmit Enable */ - -#define BA0_MIDCMD 0x0494 /* MIDI Command (wo) */ - -#define BA0_MIDSR 0x0494 /* MIDI Status (ro) */ -#define BA0_MIDSR_RDA (1<<15) /* Sticky bit (RBE 1->0) */ -#define BA0_MIDSR_TBE (1<<14) /* Sticky bit (TBF 0->1) */ -#define BA0_MIDSR_RBE (1<<7) /* Receive Buffer Empty */ -#define BA0_MIDSR_TBF (1<<6) /* Transmit Buffer Full */ - -#define BA0_MIDWP 0x0498 /* MIDI Write */ -#define BA0_MIDRP 0x049c /* MIDI Read (ro) */ - -#define BA0_AODSD1 0x04a8 /* AC'97 On-Demand Slot Disable for primary link (ro) */ -#define BA0_AODSD1_NDS(x) (1<<((x)-3)) - -#define BA0_AODSD2 0x04ac /* AC'97 On-Demand Slot Disable for secondary link (ro) */ -#define BA0_AODSD2_NDS(x) (1<<((x)-3)) - -#define BA0_CFGI 0x04b0 /* Configure Interface (EEPROM interface) */ -#define BA0_SLT12M2 0x04dc /* Slot 12 Monitor Register 2 for secondary AC-link */ -#define BA0_ACSTS2 0x04e4 /* AC'97 Status Register 2 */ -#define BA0_ACISV2 0x04f4 /* AC'97 Input Slot Valid Register 2 */ -#define BA0_ACSAD2 0x04f8 /* AC'97 Status Address Register 2 */ -#define BA0_ACSDA2 0x04fc /* AC'97 Status Data Register 2 */ -#define BA0_FMSR 0x0730 /* FM Synthesis Status (ro) */ -#define BA0_B0AP 0x0730 /* FM Bank 0 Address Port (wo) */ -#define BA0_FMDP 0x0734 /* FM Data Port */ -#define BA0_B1AP 0x0738 /* FM Bank 1 Address Port */ -#define BA0_B1DP 0x073c /* FM Bank 1 Data Port */ - -#define BA0_SSPM 0x0740 /* Sound System Power Management */ -#define BA0_SSPM_MIXEN (1<<6) /* Playback SRC + FM/Wavetable MIX */ -#define BA0_SSPM_CSRCEN (1<<5) /* Capture Sample Rate Converter Enable */ -#define BA0_SSPM_PSRCEN (1<<4) /* Playback Sample Rate Converter Enable */ -#define BA0_SSPM_JSEN (1<<3) /* Joystick Enable */ -#define BA0_SSPM_ACLEN (1<<2) /* Serial Port Engine and AC-Link Enable */ -#define BA0_SSPM_FMEN (1<<1) /* FM Synthesis Block Enable */ - -#define BA0_DACSR 0x0744 /* DAC Sample Rate - Playback SRC */ -#define BA0_ADCSR 0x0748 /* ADC Sample Rate - Capture SRC */ - -#define BA0_SSCR 0x074c /* Sound System Control Register */ -#define BA0_SSCR_HVS1 (1<<23) /* Hardwave Volume Step (0=1,1=2) */ -#define BA0_SSCR_MVCS (1<<19) /* Master Volume Codec Select */ -#define BA0_SSCR_MVLD (1<<18) /* Master Volume Line Out Disable */ -#define BA0_SSCR_MVAD (1<<17) /* Master Volume Alternate Out Disable */ -#define BA0_SSCR_MVMD (1<<16) /* Master Volume Mono Out Disable */ -#define BA0_SSCR_XLPSRC (1<<8) /* External SRC Loopback Mode */ -#define BA0_SSCR_LPSRC (1<<7) /* SRC Loopback Mode */ -#define BA0_SSCR_CDTX (1<<5) /* CD Transfer Data */ -#define BA0_SSCR_HVC (1<<3) /* Harware Volume Control Enable */ - -#define BA0_FMLVC 0x0754 /* FM Synthesis Left Volume Control */ -#define BA0_FMRVC 0x0758 /* FM Synthesis Right Volume Control */ -#define BA0_SRCSA 0x075c /* SRC Slot Assignments */ -#define BA0_PPLVC 0x0760 /* PCM Playback Left Volume Control */ -#define BA0_PPRVC 0x0764 /* PCM Playback Right Volume Control */ -#define BA0_PASR 0x0768 /* playback sample rate */ -#define BA0_CASR 0x076C /* capture sample rate */ - -/* Source Slot Numbers - Playback */ -#define SRCSLOT_LEFT_PCM_PLAYBACK 0 -#define SRCSLOT_RIGHT_PCM_PLAYBACK 1 -#define SRCSLOT_PHONE_LINE_1_DAC 2 -#define SRCSLOT_CENTER_PCM_PLAYBACK 3 -#define SRCSLOT_LEFT_SURROUND_PCM_PLAYBACK 4 -#define SRCSLOT_RIGHT_SURROUND_PCM_PLAYBACK 5 -#define SRCSLOT_LFE_PCM_PLAYBACK 6 -#define SRCSLOT_PHONE_LINE_2_DAC 7 -#define SRCSLOT_HEADSET_DAC 8 -#define SRCSLOT_LEFT_WT 29 /* invalid for BA0_SRCSA */ -#define SRCSLOT_RIGHT_WT 30 /* invalid for BA0_SRCSA */ - -/* Source Slot Numbers - Capture */ -#define SRCSLOT_LEFT_PCM_RECORD 10 -#define SRCSLOT_RIGHT_PCM_RECORD 11 -#define SRCSLOT_PHONE_LINE_1_ADC 12 -#define SRCSLOT_MIC_ADC 13 -#define SRCSLOT_PHONE_LINE_2_ADC 17 -#define SRCSLOT_HEADSET_ADC 18 -#define SRCSLOT_SECONDARY_LEFT_PCM_RECORD 20 -#define SRCSLOT_SECONDARY_RIGHT_PCM_RECORD 21 -#define SRCSLOT_SECONDARY_PHONE_LINE_1_ADC 22 -#define SRCSLOT_SECONDARY_MIC_ADC 23 -#define SRCSLOT_SECONDARY_PHONE_LINE_2_ADC 27 -#define SRCSLOT_SECONDARY_HEADSET_ADC 28 - -/* Source Slot Numbers - Others */ -#define SRCSLOT_POWER_DOWN 31 - -/* MIDI modes */ -#define CS4281_MODE_OUTPUT (1<<0) -#define CS4281_MODE_INPUT (1<<1) - -/* joystick bits */ -/* Bits for JSPT */ -#define JSPT_CAX 0x00000001 -#define JSPT_CAY 0x00000002 -#define JSPT_CBX 0x00000004 -#define JSPT_CBY 0x00000008 -#define JSPT_BA1 0x00000010 -#define JSPT_BA2 0x00000020 -#define JSPT_BB1 0x00000040 -#define JSPT_BB2 0x00000080 - -/* Bits for JSCTL */ -#define JSCTL_SP_MASK 0x00000003 -#define JSCTL_SP_SLOW 0x00000000 -#define JSCTL_SP_MEDIUM_SLOW 0x00000001 -#define JSCTL_SP_MEDIUM_FAST 0x00000002 -#define JSCTL_SP_FAST 0x00000003 -#define JSCTL_ARE 0x00000004 - -/* Data register pairs masks */ -#define JSC1_Y1V_MASK 0x0000FFFF -#define JSC1_X1V_MASK 0xFFFF0000 -#define JSC1_Y1V_SHIFT 0 -#define JSC1_X1V_SHIFT 16 -#define JSC2_Y2V_MASK 0x0000FFFF -#define JSC2_X2V_MASK 0xFFFF0000 -#define JSC2_Y2V_SHIFT 0 -#define JSC2_X2V_SHIFT 16 - -/* JS GPIO */ -#define JSIO_DAX 0x00000001 -#define JSIO_DAY 0x00000002 -#define JSIO_DBX 0x00000004 -#define JSIO_DBY 0x00000008 -#define JSIO_AXOE 0x00000010 -#define JSIO_AYOE 0x00000020 -#define JSIO_BXOE 0x00000040 -#define JSIO_BYOE 0x00000080 - -/* - * - */ - -struct cs4281_dma { - struct snd_pcm_substream *substream; - unsigned int regDBA; /* offset to DBA register */ - unsigned int regDCA; /* offset to DCA register */ - unsigned int regDBC; /* offset to DBC register */ - unsigned int regDCC; /* offset to DCC register */ - unsigned int regDMR; /* offset to DMR register */ - unsigned int regDCR; /* offset to DCR register */ - unsigned int regHDSR; /* offset to HDSR register */ - unsigned int regFCR; /* offset to FCR register */ - unsigned int regFSIC; /* offset to FSIC register */ - unsigned int valDMR; /* DMA mode */ - unsigned int valDCR; /* DMA command */ - unsigned int valFCR; /* FIFO control */ - unsigned int fifo_offset; /* FIFO offset within BA1 */ - unsigned char left_slot; /* FIFO left slot */ - unsigned char right_slot; /* FIFO right slot */ - int frag; /* period number */ -}; - -#define SUSPEND_REGISTERS 20 - -struct cs4281 { - int irq; - - void __iomem *ba0; /* virtual (accessible) address */ - void __iomem *ba1; /* virtual (accessible) address */ - unsigned long ba0_addr; - unsigned long ba1_addr; - - int dual_codec; - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97; - struct snd_ac97 *ac97_secondary; - - struct pci_dev *pci; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *midi_input; - struct snd_rawmidi_substream *midi_output; - - struct cs4281_dma dma[4]; - - unsigned char src_left_play_slot; - unsigned char src_right_play_slot; - unsigned char src_left_rec_slot; - unsigned char src_right_rec_slot; - - unsigned int spurious_dhtc_irq; - unsigned int spurious_dtc_irq; - - spinlock_t reg_lock; - unsigned int midcr; - unsigned int uartm; - - struct gameport *gameport; - -#ifdef CONFIG_PM - u32 suspend_regs[SUSPEND_REGISTERS]; -#endif - -}; - -static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id); - -static DEFINE_PCI_DEVICE_TABLE(snd_cs4281_ids) = { - { PCI_VDEVICE(CIRRUS, 0x6005), 0, }, /* CS4281 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_cs4281_ids); - -/* - * constants - */ - -#define CS4281_FIFO_SIZE 32 - -/* - * common I/O routines - */ - -static inline void snd_cs4281_pokeBA0(struct cs4281 *chip, unsigned long offset, - unsigned int val) -{ - writel(val, chip->ba0 + offset); -} - -static inline unsigned int snd_cs4281_peekBA0(struct cs4281 *chip, unsigned long offset) -{ - return readl(chip->ba0 + offset); -} - -static void snd_cs4281_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - /* - * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address - * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 - * 3. Write ACCTL = Control Register = 460h for initiating the write - * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h - * 5. if DCV not cleared, break and return error - */ - struct cs4281 *chip = ac97->private_data; - int count; - - /* - * Setup the AC97 control registers on the CS461x to send the - * appropriate command to the AC97 to perform the read. - * ACCAD = Command Address Register = 46Ch - * ACCDA = Command Data Register = 470h - * ACCTL = Control Register = 460h - * set DCV - will clear when process completed - * reset CRW - Write command - * set VFRM - valid frame enabled - * set ESYN - ASYNC generation enabled - * set RSTN - ARST# inactive, AC97 codec not reset - */ - snd_cs4281_pokeBA0(chip, BA0_ACCAD, reg); - snd_cs4281_pokeBA0(chip, BA0_ACCDA, val); - snd_cs4281_pokeBA0(chip, BA0_ACCTL, BA0_ACCTL_DCV | BA0_ACCTL_VFRM | - BA0_ACCTL_ESYN | (ac97->num ? BA0_ACCTL_TC : 0)); - for (count = 0; count < 2000; count++) { - /* - * First, we want to wait for a short time. - */ - udelay(10); - /* - * Now, check to see if the write has completed. - * ACCTL = 460h, DCV should be reset by now and 460h = 07h - */ - if (!(snd_cs4281_peekBA0(chip, BA0_ACCTL) & BA0_ACCTL_DCV)) { - return; - } - } - snd_printk(KERN_ERR "AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val); -} - -static unsigned short snd_cs4281_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct cs4281 *chip = ac97->private_data; - int count; - unsigned short result; - // FIXME: volatile is necessary in the following due to a bug of - // some gcc versions - volatile int ac97_num = ((volatile struct snd_ac97 *)ac97)->num; - - /* - * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address - * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 - * 3. Write ACCTL = Control Register = 460h for initiating the write - * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h - * 5. if DCV not cleared, break and return error - * 6. Read ACSTS = Status Register = 464h, check VSTS bit - */ - - snd_cs4281_peekBA0(chip, ac97_num ? BA0_ACSDA2 : BA0_ACSDA); - - /* - * Setup the AC97 control registers on the CS461x to send the - * appropriate command to the AC97 to perform the read. - * ACCAD = Command Address Register = 46Ch - * ACCDA = Command Data Register = 470h - * ACCTL = Control Register = 460h - * set DCV - will clear when process completed - * set CRW - Read command - * set VFRM - valid frame enabled - * set ESYN - ASYNC generation enabled - * set RSTN - ARST# inactive, AC97 codec not reset - */ - - snd_cs4281_pokeBA0(chip, BA0_ACCAD, reg); - snd_cs4281_pokeBA0(chip, BA0_ACCDA, 0); - snd_cs4281_pokeBA0(chip, BA0_ACCTL, BA0_ACCTL_DCV | BA0_ACCTL_CRW | - BA0_ACCTL_VFRM | BA0_ACCTL_ESYN | - (ac97_num ? BA0_ACCTL_TC : 0)); - - - /* - * Wait for the read to occur. - */ - for (count = 0; count < 500; count++) { - /* - * First, we want to wait for a short time. - */ - udelay(10); - /* - * Now, check to see if the read has completed. - * ACCTL = 460h, DCV should be reset by now and 460h = 17h - */ - if (!(snd_cs4281_peekBA0(chip, BA0_ACCTL) & BA0_ACCTL_DCV)) - goto __ok1; - } - - snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); - result = 0xffff; - goto __end; - - __ok1: - /* - * Wait for the valid status bit to go active. - */ - for (count = 0; count < 100; count++) { - /* - * Read the AC97 status register. - * ACSTS = Status Register = 464h - * VSTS - Valid Status - */ - if (snd_cs4281_peekBA0(chip, ac97_num ? BA0_ACSTS2 : BA0_ACSTS) & BA0_ACSTS_VSTS) - goto __ok2; - udelay(10); - } - - snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), reg = 0x%x\n", reg); - result = 0xffff; - goto __end; - - __ok2: - /* - * Read the data returned from the AC97 register. - * ACSDA = Status Data Register = 474h - */ - result = snd_cs4281_peekBA0(chip, ac97_num ? BA0_ACSDA2 : BA0_ACSDA); - - __end: - return result; -} - -/* - * PCM part - */ - -static int snd_cs4281_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct cs4281_dma *dma = substream->runtime->private_data; - struct cs4281 *chip = snd_pcm_substream_chip(substream); - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - dma->valDCR |= BA0_DCR_MSK; - dma->valFCR |= BA0_FCR_FEN; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - dma->valDCR &= ~BA0_DCR_MSK; - dma->valFCR &= ~BA0_FCR_FEN; - break; - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR & ~BA0_DMR_DMA); - dma->valDMR |= BA0_DMR_DMA; - dma->valDCR &= ~BA0_DCR_MSK; - dma->valFCR |= BA0_FCR_FEN; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - dma->valDMR &= ~(BA0_DMR_DMA|BA0_DMR_POLL); - dma->valDCR |= BA0_DCR_MSK; - dma->valFCR &= ~BA0_FCR_FEN; - /* Leave wave playback FIFO enabled for FM */ - if (dma->regFCR != BA0_FCR0) - dma->valFCR &= ~BA0_FCR_FEN; - break; - default: - spin_unlock(&chip->reg_lock); - return -EINVAL; - } - snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR); - snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR); - snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR); - spin_unlock(&chip->reg_lock); - return 0; -} - -static unsigned int snd_cs4281_rate(unsigned int rate, unsigned int *real_rate) -{ - unsigned int val = ~0; - - if (real_rate) - *real_rate = rate; - /* special "hardcoded" rates */ - switch (rate) { - case 8000: return 5; - case 11025: return 4; - case 16000: return 3; - case 22050: return 2; - case 44100: return 1; - case 48000: return 0; - default: - goto __variable; - } - __variable: - val = 1536000 / rate; - if (real_rate) - *real_rate = 1536000 / val; - return val; -} - -static void snd_cs4281_mode(struct cs4281 *chip, struct cs4281_dma *dma, - struct snd_pcm_runtime *runtime, - int capture, int src) -{ - int rec_mono; - - dma->valDMR = BA0_DMR_TYPE_SINGLE | BA0_DMR_AUTO | - (capture ? BA0_DMR_TR_WRITE : BA0_DMR_TR_READ); - if (runtime->channels == 1) - dma->valDMR |= BA0_DMR_MONO; - if (snd_pcm_format_unsigned(runtime->format) > 0) - dma->valDMR |= BA0_DMR_USIGN; - if (snd_pcm_format_big_endian(runtime->format) > 0) - dma->valDMR |= BA0_DMR_BEND; - switch (snd_pcm_format_width(runtime->format)) { - case 8: dma->valDMR |= BA0_DMR_SIZE8; - if (runtime->channels == 1) - dma->valDMR |= BA0_DMR_SWAPC; - break; - case 32: dma->valDMR |= BA0_DMR_SIZE20; break; - } - dma->frag = 0; /* for workaround */ - dma->valDCR = BA0_DCR_TCIE | BA0_DCR_MSK; - if (runtime->buffer_size != runtime->period_size) - dma->valDCR |= BA0_DCR_HTCIE; - /* Initialize DMA */ - snd_cs4281_pokeBA0(chip, dma->regDBA, runtime->dma_addr); - snd_cs4281_pokeBA0(chip, dma->regDBC, runtime->buffer_size - 1); - rec_mono = (chip->dma[1].valDMR & BA0_DMR_MONO) == BA0_DMR_MONO; - snd_cs4281_pokeBA0(chip, BA0_SRCSA, (chip->src_left_play_slot << 0) | - (chip->src_right_play_slot << 8) | - (chip->src_left_rec_slot << 16) | - ((rec_mono ? 31 : chip->src_right_rec_slot) << 24)); - if (!src) - goto __skip_src; - if (!capture) { - if (dma->left_slot == chip->src_left_play_slot) { - unsigned int val = snd_cs4281_rate(runtime->rate, NULL); - snd_BUG_ON(dma->right_slot != chip->src_right_play_slot); - snd_cs4281_pokeBA0(chip, BA0_DACSR, val); - } - } else { - if (dma->left_slot == chip->src_left_rec_slot) { - unsigned int val = snd_cs4281_rate(runtime->rate, NULL); - snd_BUG_ON(dma->right_slot != chip->src_right_rec_slot); - snd_cs4281_pokeBA0(chip, BA0_ADCSR, val); - } - } - __skip_src: - /* Deactivate wave playback FIFO before changing slot assignments */ - if (dma->regFCR == BA0_FCR0) - snd_cs4281_pokeBA0(chip, dma->regFCR, snd_cs4281_peekBA0(chip, dma->regFCR) & ~BA0_FCR_FEN); - /* Initialize FIFO */ - dma->valFCR = BA0_FCR_LS(dma->left_slot) | - BA0_FCR_RS(capture && (dma->valDMR & BA0_DMR_MONO) ? 31 : dma->right_slot) | - BA0_FCR_SZ(CS4281_FIFO_SIZE) | - BA0_FCR_OF(dma->fifo_offset); - snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR | (capture ? BA0_FCR_PSH : 0)); - /* Activate FIFO again for FM playback */ - if (dma->regFCR == BA0_FCR0) - snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR | BA0_FCR_FEN); - /* Clear FIFO Status and Interrupt Control Register */ - snd_cs4281_pokeBA0(chip, dma->regFSIC, 0); -} - -static int snd_cs4281_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_cs4281_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_cs4281_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct cs4281_dma *dma = runtime->private_data; - struct cs4281 *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - snd_cs4281_mode(chip, dma, runtime, 0, 1); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_cs4281_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct cs4281_dma *dma = runtime->private_data; - struct cs4281 *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - snd_cs4281_mode(chip, dma, runtime, 1, 1); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct cs4281_dma *dma = runtime->private_data; - struct cs4281 *chip = snd_pcm_substream_chip(substream); - - /* - printk(KERN_DEBUG "DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", - snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, - jiffies); - */ - return runtime->buffer_size - - snd_cs4281_peekBA0(chip, dma->regDCC) - 1; -} - -static struct snd_pcm_hardware snd_cs4281_playback = -{ - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (512*1024), - .period_bytes_min = 64, - .period_bytes_max = (512*1024), - .periods_min = 1, - .periods_max = 2, - .fifo_size = CS4281_FIFO_SIZE, -}; - -static struct snd_pcm_hardware snd_cs4281_capture = -{ - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (512*1024), - .period_bytes_min = 64, - .period_bytes_max = (512*1024), - .periods_min = 1, - .periods_max = 2, - .fifo_size = CS4281_FIFO_SIZE, -}; - -static int snd_cs4281_playback_open(struct snd_pcm_substream *substream) -{ - struct cs4281 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct cs4281_dma *dma; - - dma = &chip->dma[0]; - dma->substream = substream; - dma->left_slot = 0; - dma->right_slot = 1; - runtime->private_data = dma; - runtime->hw = snd_cs4281_playback; - /* should be detected from the AC'97 layer, but it seems - that although CS4297A rev B reports 18-bit ADC resolution, - samples are 20-bit */ - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20); - return 0; -} - -static int snd_cs4281_capture_open(struct snd_pcm_substream *substream) -{ - struct cs4281 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct cs4281_dma *dma; - - dma = &chip->dma[1]; - dma->substream = substream; - dma->left_slot = 10; - dma->right_slot = 11; - runtime->private_data = dma; - runtime->hw = snd_cs4281_capture; - /* should be detected from the AC'97 layer, but it seems - that although CS4297A rev B reports 18-bit ADC resolution, - samples are 20-bit */ - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20); - return 0; -} - -static int snd_cs4281_playback_close(struct snd_pcm_substream *substream) -{ - struct cs4281_dma *dma = substream->runtime->private_data; - - dma->substream = NULL; - return 0; -} - -static int snd_cs4281_capture_close(struct snd_pcm_substream *substream) -{ - struct cs4281_dma *dma = substream->runtime->private_data; - - dma->substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_cs4281_playback_ops = { - .open = snd_cs4281_playback_open, - .close = snd_cs4281_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs4281_hw_params, - .hw_free = snd_cs4281_hw_free, - .prepare = snd_cs4281_playback_prepare, - .trigger = snd_cs4281_trigger, - .pointer = snd_cs4281_pointer, -}; - -static struct snd_pcm_ops snd_cs4281_capture_ops = { - .open = snd_cs4281_capture_open, - .close = snd_cs4281_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs4281_hw_params, - .hw_free = snd_cs4281_hw_free, - .prepare = snd_cs4281_capture_prepare, - .trigger = snd_cs4281_trigger, - .pointer = snd_cs4281_pointer, -}; - -static int __devinit snd_cs4281_pcm(struct cs4281 * chip, int device, - struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - err = snd_pcm_new(chip->card, "CS4281", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4281_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4281_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, "CS4281"); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 512*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* - * Mixer section - */ - -#define CS_VOL_MASK 0x1f - -static int snd_cs4281_info_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = CS_VOL_MASK; - return 0; -} - -static int snd_cs4281_get_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cs4281 *chip = snd_kcontrol_chip(kcontrol); - int regL = (kcontrol->private_value >> 16) & 0xffff; - int regR = kcontrol->private_value & 0xffff; - int volL, volR; - - volL = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regL) & CS_VOL_MASK); - volR = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regR) & CS_VOL_MASK); - - ucontrol->value.integer.value[0] = volL; - ucontrol->value.integer.value[1] = volR; - return 0; -} - -static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct cs4281 *chip = snd_kcontrol_chip(kcontrol); - int change = 0; - int regL = (kcontrol->private_value >> 16) & 0xffff; - int regR = kcontrol->private_value & 0xffff; - int volL, volR; - - volL = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regL) & CS_VOL_MASK); - volR = CS_VOL_MASK - (snd_cs4281_peekBA0(chip, regR) & CS_VOL_MASK); - - if (ucontrol->value.integer.value[0] != volL) { - volL = CS_VOL_MASK - (ucontrol->value.integer.value[0] & CS_VOL_MASK); - snd_cs4281_pokeBA0(chip, regL, volL); - change = 1; - } - if (ucontrol->value.integer.value[1] != volR) { - volR = CS_VOL_MASK - (ucontrol->value.integer.value[1] & CS_VOL_MASK); - snd_cs4281_pokeBA0(chip, regR, volR); - change = 1; - } - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0); - -static struct snd_kcontrol_new snd_cs4281_fm_vol = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Synth Playback Volume", - .info = snd_cs4281_info_volume, - .get = snd_cs4281_get_volume, - .put = snd_cs4281_put_volume, - .private_value = ((BA0_FMLVC << 16) | BA0_FMRVC), - .tlv = { .p = db_scale_dsp }, -}; - -static struct snd_kcontrol_new snd_cs4281_pcm_vol = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Stream Playback Volume", - .info = snd_cs4281_info_volume, - .get = snd_cs4281_get_volume, - .put = snd_cs4281_put_volume, - .private_value = ((BA0_PPLVC << 16) | BA0_PPRVC), - .tlv = { .p = db_scale_dsp }, -}; - -static void snd_cs4281_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct cs4281 *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void snd_cs4281_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct cs4281 *chip = ac97->private_data; - if (ac97->num) - chip->ac97_secondary = NULL; - else - chip->ac97 = NULL; -} - -static int __devinit snd_cs4281_mixer(struct cs4281 * chip) -{ - struct snd_card *card = chip->card; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_cs4281_ac97_write, - .read = snd_cs4281_ac97_read, - }; - - if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) - return err; - chip->ac97_bus->private_free = snd_cs4281_mixer_free_ac97_bus; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_cs4281_mixer_free_ac97; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) - return err; - if (chip->dual_codec) { - ac97.num = 1; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_secondary)) < 0) - return err; - } - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_fm_vol, chip))) < 0) - return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_pcm_vol, chip))) < 0) - return err; - return 0; -} - - -/* - * proc interface - */ - -static void snd_cs4281_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct cs4281 *chip = entry->private_data; - - snd_iprintf(buffer, "Cirrus Logic CS4281\n\n"); - snd_iprintf(buffer, "Spurious half IRQs : %u\n", chip->spurious_dhtc_irq); - snd_iprintf(buffer, "Spurious end IRQs : %u\n", chip->spurious_dtc_irq); -} - -static ssize_t snd_cs4281_BA0_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct cs4281 *chip = entry->private_data; - - if (copy_to_user_fromio(buf, chip->ba0 + pos, count)) - return -EFAULT; - return count; -} - -static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct cs4281 *chip = entry->private_data; - - if (copy_to_user_fromio(buf, chip->ba1 + pos, count)) - return -EFAULT; - return count; -} - -static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { - .read = snd_cs4281_BA0_read, -}; - -static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = { - .read = snd_cs4281_BA1_read, -}; - -static void __devinit snd_cs4281_proc_init(struct cs4281 * chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "cs4281", &entry)) - snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read); - if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = chip; - entry->c.ops = &snd_cs4281_proc_ops_BA0; - entry->size = CS4281_BA0_SIZE; - } - if (! snd_card_proc_new(chip->card, "cs4281_BA1", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = chip; - entry->c.ops = &snd_cs4281_proc_ops_BA1; - entry->size = CS4281_BA1_SIZE; - } -} - -/* - * joystick support - */ - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - -static void snd_cs4281_gameport_trigger(struct gameport *gameport) -{ - struct cs4281 *chip = gameport_get_port_data(gameport); - - if (snd_BUG_ON(!chip)) - return; - snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff); -} - -static unsigned char snd_cs4281_gameport_read(struct gameport *gameport) -{ - struct cs4281 *chip = gameport_get_port_data(gameport); - - if (snd_BUG_ON(!chip)) - return 0; - return snd_cs4281_peekBA0(chip, BA0_JSPT); -} - -#ifdef COOKED_MODE -static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, - int *axes, int *buttons) -{ - struct cs4281 *chip = gameport_get_port_data(gameport); - unsigned js1, js2, jst; - - if (snd_BUG_ON(!chip)) - return 0; - - js1 = snd_cs4281_peekBA0(chip, BA0_JSC1); - js2 = snd_cs4281_peekBA0(chip, BA0_JSC2); - jst = snd_cs4281_peekBA0(chip, BA0_JSPT); - - *buttons = (~jst >> 4) & 0x0F; - - axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; - axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; - axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; - axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; - - for (jst = 0; jst < 4; ++jst) - if (axes[jst] == 0xFFFF) axes[jst] = -1; - return 0; -} -#else -#define snd_cs4281_gameport_cooked_read NULL -#endif - -static int snd_cs4281_gameport_open(struct gameport *gameport, int mode) -{ - switch (mode) { -#ifdef COOKED_MODE - case GAMEPORT_MODE_COOKED: - return 0; -#endif - case GAMEPORT_MODE_RAW: - return 0; - default: - return -1; - } - return 0; -} - -static int __devinit snd_cs4281_create_gameport(struct cs4281 *chip) -{ - struct gameport *gp; - - chip->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "cs4281: cannot allocate memory for gameport\n"); - return -ENOMEM; - } - - gameport_set_name(gp, "CS4281 Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); - gameport_set_dev_parent(gp, &chip->pci->dev); - gp->open = snd_cs4281_gameport_open; - gp->read = snd_cs4281_gameport_read; - gp->trigger = snd_cs4281_gameport_trigger; - gp->cooked_read = snd_cs4281_gameport_cooked_read; - gameport_set_port_data(gp, chip); - - snd_cs4281_pokeBA0(chip, BA0_JSIO, 0xFF); // ? - snd_cs4281_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); - - gameport_register_port(gp); - - return 0; -} - -static void snd_cs4281_free_gameport(struct cs4281 *chip) -{ - if (chip->gameport) { - gameport_unregister_port(chip->gameport); - chip->gameport = NULL; - } -} -#else -static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOSYS; } -static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { } -#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ - -static int snd_cs4281_free(struct cs4281 *chip) -{ - snd_cs4281_free_gameport(chip); - - if (chip->irq >= 0) - synchronize_irq(chip->irq); - - /* Mask interrupts */ - snd_cs4281_pokeBA0(chip, BA0_HIMR, 0x7fffffff); - /* Stop the DLL Clock logic. */ - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0); - /* Sound System Power Management - Turn Everything OFF */ - snd_cs4281_pokeBA0(chip, BA0_SSPM, 0); - /* PCI interface - D3 state */ - pci_set_power_state(chip->pci, 3); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - if (chip->ba0) - iounmap(chip->ba0); - if (chip->ba1) - iounmap(chip->ba1); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - - kfree(chip); - return 0; -} - -static int snd_cs4281_dev_free(struct snd_device *device) -{ - struct cs4281 *chip = device->device_data; - return snd_cs4281_free(chip); -} - -static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */ - -static int __devinit snd_cs4281_create(struct snd_card *card, - struct pci_dev *pci, - struct cs4281 ** rchip, - int dual_codec) -{ - struct cs4281 *chip; - unsigned int tmp; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_cs4281_dev_free, - }; - - *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) - return err; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&chip->reg_lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - pci_set_master(pci); - if (dual_codec < 0 || dual_codec > 3) { - snd_printk(KERN_ERR "invalid dual_codec option %d\n", dual_codec); - dual_codec = 0; - } - chip->dual_codec = dual_codec; - - if ((err = pci_request_regions(pci, "CS4281")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->ba0_addr = pci_resource_start(pci, 0); - chip->ba1_addr = pci_resource_start(pci, 1); - - chip->ba0 = pci_ioremap_bar(pci, 0); - chip->ba1 = pci_ioremap_bar(pci, 1); - if (!chip->ba0 || !chip->ba1) { - snd_cs4281_free(chip); - return -ENOMEM; - } - - if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_cs4281_free(chip); - return -ENOMEM; - } - chip->irq = pci->irq; - - tmp = snd_cs4281_chip_init(chip); - if (tmp) { - snd_cs4281_free(chip); - return tmp; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_cs4281_free(chip); - return err; - } - - snd_cs4281_proc_init(chip); - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - return 0; -} - -static int snd_cs4281_chip_init(struct cs4281 *chip) -{ - unsigned int tmp; - unsigned long end_time; - int retry_count = 2; - - /* Having EPPMC.FPDN=1 prevent proper chip initialisation */ - tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC); - if (tmp & BA0_EPPMC_FPDN) - snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN); - - __retry: - tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); - if (tmp != BA0_CFLR_DEFAULT) { - snd_cs4281_pokeBA0(chip, BA0_CFLR, BA0_CFLR_DEFAULT); - tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); - if (tmp != BA0_CFLR_DEFAULT) { - snd_printk(KERN_ERR "CFLR setup failed (0x%x)\n", tmp); - return -EIO; - } - } - - /* Set the 'Configuration Write Protect' register - * to 4281h. Allows vendor-defined configuration - * space between 0e4h and 0ffh to be written. */ - snd_cs4281_pokeBA0(chip, BA0_CWPR, 0x4281); - - if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC1)) != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) { - snd_printk(KERN_ERR "SERC1 AC'97 check failed (0x%x)\n", tmp); - return -EIO; - } - if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC2)) != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) { - snd_printk(KERN_ERR "SERC2 AC'97 check failed (0x%x)\n", tmp); - return -EIO; - } - - /* Sound System Power Management */ - snd_cs4281_pokeBA0(chip, BA0_SSPM, BA0_SSPM_MIXEN | BA0_SSPM_CSRCEN | - BA0_SSPM_PSRCEN | BA0_SSPM_JSEN | - BA0_SSPM_ACLEN | BA0_SSPM_FMEN); - - /* Serial Port Power Management */ - /* Blast the clock control register to zero so that the - * PLL starts out in a known state, and blast the master serial - * port control register to zero so that the serial ports also - * start out in a known state. */ - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0); - snd_cs4281_pokeBA0(chip, BA0_SERMC, 0); - - /* Make ESYN go to zero to turn off - * the Sync pulse on the AC97 link. */ - snd_cs4281_pokeBA0(chip, BA0_ACCTL, 0); - udelay(50); - - /* Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97 - * spec) and then drive it high. This is done for non AC97 modes since - * there might be logic external to the CS4281 that uses the ARST# line - * for a reset. */ - snd_cs4281_pokeBA0(chip, BA0_SPMC, 0); - udelay(50); - snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN); - msleep(50); - - if (chip->dual_codec) - snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN | BA0_SPMC_ASDI2E); - - /* - * Set the serial port timing configuration. - */ - snd_cs4281_pokeBA0(chip, BA0_SERMC, - (chip->dual_codec ? BA0_SERMC_TCID(chip->dual_codec) : BA0_SERMC_TCID(1)) | - BA0_SERMC_PTC_AC97 | BA0_SERMC_MSPE); - - /* - * Start the DLL Clock logic. - */ - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_DLLP); - msleep(50); - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_SWCE | BA0_CLKCR1_DLLP); - - /* - * Wait for the DLL ready signal from the clock logic. - */ - end_time = jiffies + HZ; - do { - /* - * Read the AC97 status register to see if we've seen a CODEC - * signal from the AC97 codec. - */ - if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY) - goto __ok0; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - - snd_printk(KERN_ERR "DLLRDY not seen\n"); - return -EIO; - - __ok0: - - /* - * The first thing we do here is to enable sync generation. As soon - * as we start receiving bit clock, we'll start producing the SYNC - * signal. - */ - snd_cs4281_pokeBA0(chip, BA0_ACCTL, BA0_ACCTL_ESYN); - - /* - * Wait for the codec ready signal from the AC97 codec. - */ - end_time = jiffies + HZ; - do { - /* - * Read the AC97 status register to see if we've seen a CODEC - * signal from the AC97 codec. - */ - if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY) - goto __ok1; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - - snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS)); - return -EIO; - - __ok1: - if (chip->dual_codec) { - end_time = jiffies + HZ; - do { - if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY) - goto __codec2_ok; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n"); - chip->dual_codec = 0; - __codec2_ok: ; - } - - /* - * Assert the valid frame signal so that we can start sending commands - * to the AC97 codec. - */ - - snd_cs4281_pokeBA0(chip, BA0_ACCTL, BA0_ACCTL_VFRM | BA0_ACCTL_ESYN); - - /* - * Wait until we've sampled input slots 3 and 4 as valid, meaning that - * the codec is pumping ADC data across the AC-link. - */ - - end_time = jiffies + HZ; - do { - /* - * Read the input slot valid register and see if input slots 3 - * 4 are valid yet. - */ - if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) - goto __ok2; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - - if (--retry_count > 0) - goto __retry; - snd_printk(KERN_ERR "never read ISV3 and ISV4 from AC'97\n"); - return -EIO; - - __ok2: - - /* - * Now, assert valid frame and the slot 3 and 4 valid bits. This will - * commense the transfer of digital audio data to the AC97 codec. - */ - snd_cs4281_pokeBA0(chip, BA0_ACOSV, BA0_ACOSV_SLV(3) | BA0_ACOSV_SLV(4)); - - /* - * Initialize DMA structures - */ - for (tmp = 0; tmp < 4; tmp++) { - struct cs4281_dma *dma = &chip->dma[tmp]; - dma->regDBA = BA0_DBA0 + (tmp * 0x10); - dma->regDCA = BA0_DCA0 + (tmp * 0x10); - dma->regDBC = BA0_DBC0 + (tmp * 0x10); - dma->regDCC = BA0_DCC0 + (tmp * 0x10); - dma->regDMR = BA0_DMR0 + (tmp * 8); - dma->regDCR = BA0_DCR0 + (tmp * 8); - dma->regHDSR = BA0_HDSR0 + (tmp * 4); - dma->regFCR = BA0_FCR0 + (tmp * 4); - dma->regFSIC = BA0_FSIC0 + (tmp * 4); - dma->fifo_offset = tmp * CS4281_FIFO_SIZE; - snd_cs4281_pokeBA0(chip, dma->regFCR, - BA0_FCR_LS(31) | - BA0_FCR_RS(31) | - BA0_FCR_SZ(CS4281_FIFO_SIZE) | - BA0_FCR_OF(dma->fifo_offset)); - } - - chip->src_left_play_slot = 0; /* AC'97 left PCM playback (3) */ - chip->src_right_play_slot = 1; /* AC'97 right PCM playback (4) */ - chip->src_left_rec_slot = 10; /* AC'97 left PCM record (3) */ - chip->src_right_rec_slot = 11; /* AC'97 right PCM record (4) */ - - /* Activate wave playback FIFO for FM playback */ - chip->dma[0].valFCR = BA0_FCR_FEN | BA0_FCR_LS(0) | - BA0_FCR_RS(1) | - BA0_FCR_SZ(CS4281_FIFO_SIZE) | - BA0_FCR_OF(chip->dma[0].fifo_offset); - snd_cs4281_pokeBA0(chip, chip->dma[0].regFCR, chip->dma[0].valFCR); - snd_cs4281_pokeBA0(chip, BA0_SRCSA, (chip->src_left_play_slot << 0) | - (chip->src_right_play_slot << 8) | - (chip->src_left_rec_slot << 16) | - (chip->src_right_rec_slot << 24)); - - /* Initialize digital volume */ - snd_cs4281_pokeBA0(chip, BA0_PPLVC, 0); - snd_cs4281_pokeBA0(chip, BA0_PPRVC, 0); - - /* Enable IRQs */ - snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_EOI); - /* Unmask interrupts */ - snd_cs4281_pokeBA0(chip, BA0_HIMR, 0x7fffffff & ~( - BA0_HISR_MIDI | - BA0_HISR_DMAI | - BA0_HISR_DMA(0) | - BA0_HISR_DMA(1) | - BA0_HISR_DMA(2) | - BA0_HISR_DMA(3))); - synchronize_irq(chip->irq); - - return 0; -} - -/* - * MIDI section - */ - -static void snd_cs4281_midi_reset(struct cs4281 *chip) -{ - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr | BA0_MIDCR_MRST); - udelay(100); - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); -} - -static int snd_cs4281_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct cs4281 *chip = substream->rmidi->private_data; - - spin_lock_irq(&chip->reg_lock); - chip->midcr |= BA0_MIDCR_RXE; - chip->midi_input = substream; - if (!(chip->uartm & CS4281_MODE_OUTPUT)) { - snd_cs4281_midi_reset(chip); - } else { - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_cs4281_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct cs4281 *chip = substream->rmidi->private_data; - - spin_lock_irq(&chip->reg_lock); - chip->midcr &= ~(BA0_MIDCR_RXE | BA0_MIDCR_RIE); - chip->midi_input = NULL; - if (!(chip->uartm & CS4281_MODE_OUTPUT)) { - snd_cs4281_midi_reset(chip); - } else { - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - chip->uartm &= ~CS4281_MODE_INPUT; - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_cs4281_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct cs4281 *chip = substream->rmidi->private_data; - - spin_lock_irq(&chip->reg_lock); - chip->uartm |= CS4281_MODE_OUTPUT; - chip->midcr |= BA0_MIDCR_TXE; - chip->midi_output = substream; - if (!(chip->uartm & CS4281_MODE_INPUT)) { - snd_cs4281_midi_reset(chip); - } else { - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_cs4281_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct cs4281 *chip = substream->rmidi->private_data; - - spin_lock_irq(&chip->reg_lock); - chip->midcr &= ~(BA0_MIDCR_TXE | BA0_MIDCR_TIE); - chip->midi_output = NULL; - if (!(chip->uartm & CS4281_MODE_INPUT)) { - snd_cs4281_midi_reset(chip); - } else { - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - chip->uartm &= ~CS4281_MODE_OUTPUT; - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static void snd_cs4281_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct cs4281 *chip = substream->rmidi->private_data; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (up) { - if ((chip->midcr & BA0_MIDCR_RIE) == 0) { - chip->midcr |= BA0_MIDCR_RIE; - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - } else { - if (chip->midcr & BA0_MIDCR_RIE) { - chip->midcr &= ~BA0_MIDCR_RIE; - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct cs4281 *chip = substream->rmidi->private_data; - unsigned char byte; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (up) { - if ((chip->midcr & BA0_MIDCR_TIE) == 0) { - chip->midcr |= BA0_MIDCR_TIE; - /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */ - while ((chip->midcr & BA0_MIDCR_TIE) && - (snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) { - if (snd_rawmidi_transmit(substream, &byte, 1) != 1) { - chip->midcr &= ~BA0_MIDCR_TIE; - } else { - snd_cs4281_pokeBA0(chip, BA0_MIDWP, byte); - } - } - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - } else { - if (chip->midcr & BA0_MIDCR_TIE) { - chip->midcr &= ~BA0_MIDCR_TIE; - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static struct snd_rawmidi_ops snd_cs4281_midi_output = -{ - .open = snd_cs4281_midi_output_open, - .close = snd_cs4281_midi_output_close, - .trigger = snd_cs4281_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_cs4281_midi_input = -{ - .open = snd_cs4281_midi_input_open, - .close = snd_cs4281_midi_input_close, - .trigger = snd_cs4281_midi_input_trigger, -}; - -static int __devinit snd_cs4281_midi(struct cs4281 * chip, int device, - struct snd_rawmidi **rrawmidi) -{ - struct snd_rawmidi *rmidi; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if ((err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi)) < 0) - return err; - strcpy(rmidi->name, "CS4281"); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs4281_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs4281_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = chip; - chip->rmidi = rmidi; - if (rrawmidi) - *rrawmidi = rmidi; - return 0; -} - -/* - * Interrupt handler - */ - -static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id) -{ - struct cs4281 *chip = dev_id; - unsigned int status, dma, val; - struct cs4281_dma *cdma; - - if (chip == NULL) - return IRQ_NONE; - status = snd_cs4281_peekBA0(chip, BA0_HISR); - if ((status & 0x7fffffff) == 0) { - snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_EOI); - return IRQ_NONE; - } - - if (status & (BA0_HISR_DMA(0)|BA0_HISR_DMA(1)|BA0_HISR_DMA(2)|BA0_HISR_DMA(3))) { - for (dma = 0; dma < 4; dma++) - if (status & BA0_HISR_DMA(dma)) { - cdma = &chip->dma[dma]; - spin_lock(&chip->reg_lock); - /* ack DMA IRQ */ - val = snd_cs4281_peekBA0(chip, cdma->regHDSR); - /* workaround, sometimes CS4281 acknowledges */ - /* end or middle transfer position twice */ - cdma->frag++; - if ((val & BA0_HDSR_DHTC) && !(cdma->frag & 1)) { - cdma->frag--; - chip->spurious_dhtc_irq++; - spin_unlock(&chip->reg_lock); - continue; - } - if ((val & BA0_HDSR_DTC) && (cdma->frag & 1)) { - cdma->frag--; - chip->spurious_dtc_irq++; - spin_unlock(&chip->reg_lock); - continue; - } - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(cdma->substream); - } - } - - if ((status & BA0_HISR_MIDI) && chip->rmidi) { - unsigned char c; - - spin_lock(&chip->reg_lock); - while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_RBE) == 0) { - c = snd_cs4281_peekBA0(chip, BA0_MIDRP); - if ((chip->midcr & BA0_MIDCR_RIE) == 0) - continue; - snd_rawmidi_receive(chip->midi_input, &c, 1); - } - while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) { - if ((chip->midcr & BA0_MIDCR_TIE) == 0) - break; - if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) { - chip->midcr &= ~BA0_MIDCR_TIE; - snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr); - break; - } - snd_cs4281_pokeBA0(chip, BA0_MIDWP, c); - } - spin_unlock(&chip->reg_lock); - } - - /* EOI to the PCI part... reenables interrupts */ - snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_EOI); - - return IRQ_HANDLED; -} - - -/* - * OPL3 command - */ -static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd, - unsigned char val) -{ - unsigned long flags; - struct cs4281 *chip = opl3->private_data; - void __iomem *port; - - if (cmd & OPL3_RIGHT) - port = chip->ba0 + BA0_B1AP; /* right port */ - else - port = chip->ba0 + BA0_B0AP; /* left port */ - - spin_lock_irqsave(&opl3->reg_lock, flags); - - writel((unsigned int)cmd, port); - udelay(10); - - writel((unsigned int)val, port + 4); - udelay(30); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); -} - -static int __devinit snd_cs4281_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct cs4281 *chip; - struct snd_opl3 *opl3; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_cs4281_create(card, pci, &chip, dual_codec[dev])) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - if ((err = snd_cs4281_mixer(chip)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_cs4281_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_cs4281_midi(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3)) < 0) { - snd_card_free(card); - return err; - } - opl3->private_data = chip; - opl3->command = snd_cs4281_opl3_command; - snd_opl3_init(opl3); - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - snd_cs4281_create_gameport(chip); - strcpy(card->driver, "CS4281"); - strcpy(card->shortname, "Cirrus Logic CS4281"); - sprintf(card->longname, "%s at 0x%lx, irq %d", - card->shortname, - chip->ba0_addr, - chip->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_cs4281_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -/* - * Power Management - */ -#ifdef CONFIG_PM - -static int saved_regs[SUSPEND_REGISTERS] = { - BA0_JSCTL, - BA0_GPIOR, - BA0_SSCR, - BA0_MIDCR, - BA0_SRCSA, - BA0_PASR, - BA0_CASR, - BA0_DACSR, - BA0_ADCSR, - BA0_FMLVC, - BA0_FMRVC, - BA0_PPLVC, - BA0_PPRVC, -}; - -#define CLKCR1_CKRA 0x00010000L - -static int cs4281_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct cs4281 *chip = card->private_data; - u32 ulCLK; - unsigned int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - - snd_ac97_suspend(chip->ac97); - snd_ac97_suspend(chip->ac97_secondary); - - ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); - ulCLK |= CLKCR1_CKRA; - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); - - /* Disable interrupts. */ - snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_CHGM); - - /* remember the status registers */ - for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - if (saved_regs[i]) - chip->suspend_regs[i] = snd_cs4281_peekBA0(chip, saved_regs[i]); - - /* Turn off the serial ports. */ - snd_cs4281_pokeBA0(chip, BA0_SERMC, 0); - - /* Power off FM, Joystick, AC link, */ - snd_cs4281_pokeBA0(chip, BA0_SSPM, 0); - - /* DLL off. */ - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, 0); - - /* AC link off. */ - snd_cs4281_pokeBA0(chip, BA0_SPMC, 0); - - ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); - ulCLK &= ~CLKCR1_CKRA; - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int cs4281_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct cs4281 *chip = card->private_data; - unsigned int i; - u32 ulCLK; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cs4281: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); - ulCLK |= CLKCR1_CKRA; - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); - - snd_cs4281_chip_init(chip); - - /* restore the status registers */ - for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - if (saved_regs[i]) - snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]); - - snd_ac97_resume(chip->ac97); - snd_ac97_resume(chip->ac97_secondary); - - ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); - ulCLK &= ~CLKCR1_CKRA; - snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_cs4281_ids, - .probe = snd_cs4281_probe, - .remove = __devexit_p(snd_cs4281_remove), -#ifdef CONFIG_PM - .suspend = cs4281_suspend, - .resume = cs4281_resume, -#endif -}; - -static int __init alsa_card_cs4281_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_cs4281_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_cs4281_init) -module_exit(alsa_card_cs4281_exit) diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/Makefile b/ANDROID_3.4.5/sound/pci/cs46xx/Makefile deleted file mode 100644 index 67e811ec..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-cs46xx-y := cs46xx.o cs46xx_lib.o -snd-cs46xx-$(CONFIG_SND_CS46XX_NEW_DSP) += dsp_spos.o dsp_spos_scb_lib.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_CS46XX) += snd-cs46xx.o diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx.c b/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx.c deleted file mode 100644 index 819d79d0..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -/* - NOTES: - - sometimes the sound is metallic and sibilant, unloading and - reloading the module may solve this. -*/ - -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)}," - "{Cirrus Logic,Sound Fusion (CS4610)}," - "{Cirrus Logic,Sound Fusion (CS4612)}," - "{Cirrus Logic,Sound Fusion (CS4615)}," - "{Cirrus Logic,Sound Fusion (CS4622)}," - "{Cirrus Logic,Sound Fusion (CS4624)}," - "{Cirrus Logic,Sound Fusion (CS4630)}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static bool external_amp[SNDRV_CARDS]; -static bool thinkpad[SNDRV_CARDS]; -static bool mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the CS46xx soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the CS46xx soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable CS46xx soundcard."); -module_param_array(external_amp, bool, NULL, 0444); -MODULE_PARM_DESC(external_amp, "Force to enable external amplifer."); -module_param_array(thinkpad, bool, NULL, 0444); -MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control."); -module_param_array(mmap_valid, bool, NULL, 0444); -MODULE_PARM_DESC(mmap_valid, "Support OSS mmap."); - -static DEFINE_PCI_DEVICE_TABLE(snd_cs46xx_ids) = { - { PCI_VDEVICE(CIRRUS, 0x6001), 0, }, /* CS4280 */ - { PCI_VDEVICE(CIRRUS, 0x6003), 0, }, /* CS4612 */ - { PCI_VDEVICE(CIRRUS, 0x6004), 0, }, /* CS4615 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_cs46xx_ids); - -static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_cs46xx *chip; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - if ((err = snd_cs46xx_create(card, pci, - external_amp[dev], thinkpad[dev], - &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - chip->accept_valid = mmap_valid[dev]; - if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_cs46xx_pcm_iec958(chip,2,NULL)) < 0) { - snd_card_free(card); - return err; - } -#endif - if ((err = snd_cs46xx_mixer(chip, 2)) < 0) { - snd_card_free(card); - return err; - } -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (chip->nr_ac97_codecs ==2) { - if ((err = snd_cs46xx_pcm_center_lfe(chip,3,NULL)) < 0) { - snd_card_free(card); - return err; - } - } -#endif - if ((err = snd_cs46xx_midi(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_cs46xx_start_dsp(chip)) < 0) { - snd_card_free(card); - return err; - } - - - snd_cs46xx_gameport(chip); - - strcpy(card->driver, "CS46xx"); - strcpy(card->shortname, "Sound Fusion CS46xx"); - sprintf(card->longname, "%s at 0x%lx/0x%lx, irq %i", - card->shortname, - chip->ba0_addr, - chip->ba1_addr, - chip->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_card_cs46xx_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_cs46xx_ids, - .probe = snd_card_cs46xx_probe, - .remove = __devexit_p(snd_card_cs46xx_remove), -#ifdef CONFIG_PM - .suspend = snd_cs46xx_suspend, - .resume = snd_cs46xx_resume, -#endif -}; - -static int __init alsa_card_cs46xx_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_cs46xx_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_cs46xx_init) -module_exit(alsa_card_cs46xx_exit) diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_image.h b/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_image.h deleted file mode 100644 index dc93f62d..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_image.h +++ /dev/null @@ -1,3468 +0,0 @@ -struct BA1struct { - struct { - unsigned long offset; - unsigned long size; - } memory[BA1_MEMORY_COUNT]; - u32 map[BA1_DWORD_SIZE]; -}; - - -static struct BA1struct BA1Struct = { -{{ 0x00000000, 0x00003000 },{ 0x00010000, 0x00003800 },{ 0x00020000, 0x00007000 }}, -{0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000163,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00200040,0x00008010,0x00000000, -0x00000000,0x80000001,0x00000001,0x00060000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00900080,0x00000173,0x00000000, -0x00000000,0x00000010,0x00800000,0x00900000, -0xf2c0000f,0x00000200,0x00000000,0x00010600, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000163,0x330300c2, -0x06000000,0x00000000,0x80008000,0x80008000, -0x3fc0000f,0x00000301,0x00010400,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00b00000,0x00d0806d,0x330480c3, -0x04800000,0x00000001,0x00800001,0x0000ffff, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x066a0600,0x06350070,0x0000929d,0x929d929d, -0x00000000,0x0000735a,0x00000600,0x00000000, -0x929d735a,0x8734abfe,0x00010000,0x735a735a, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0000804f,0x000000c3, -0x05000000,0x00a00010,0x00000000,0x80008000, -0x00000000,0x00000000,0x00000700,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000080,0x00a00000,0x0000809a,0x000000c2, -0x07400000,0x00000000,0x80008000,0xffffffff, -0x00c80028,0x00005555,0x00000000,0x000107a0, -0x00c80028,0x000000c2,0x06800000,0x00000000, -0x06e00080,0x00300000,0x000080bb,0x000000c9, -0x07a00000,0x04000000,0x80008000,0xffffffff, -0x00c80028,0x00005555,0x00000000,0x00000780, -0x00c80028,0x000000c5,0xff800000,0x00000000, -0x00640080,0x00c00000,0x00008197,0x000000c9, -0x07800000,0x04000000,0x80008000,0xffffffff, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0000805e,0x000000c1, -0x00000000,0x00800000,0x80008000,0x80008000, -0x00020000,0x0000ffff,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x929d0600,0x929d929d,0x929d929d,0x929d0000, -0x929d929d,0x929d929d,0x929d929d,0x929d929d, -0x929d929d,0x00100635,0x060b013f,0x00000004, -0x00000001,0x007a0002,0x00000000,0x066e0610, -0x0105929d,0x929d929d,0x929d929d,0x929d929d, -0x929d929d,0xa431ac75,0x0001735a,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051, -0x00000000,0x929d929d,0x929d929d,0x929d929d, -0x929d929d,0x929d929d,0x929d929d,0x929d929d, -0x929d929d,0x929d929d,0x00000000,0x06400136, -0x0000270f,0x00010000,0x007a0000,0x00000000, -0x068e0645,0x0105929d,0x929d929d,0x929d929d, -0x929d929d,0x929d929d,0xa431ac75,0x0001735a, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0x735a0100,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00010004, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00001705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00009705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00011705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00019705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00021705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00029705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00031705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00039705,0x00001400,0x000a411e,0x00001003, -0x000fe19e,0x00001003,0x0009c730,0x00001003, -0x0008e19c,0x00001003,0x000083c1,0x00093040, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00009705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00011705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00019705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00021705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00029705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00031705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00039705,0x00001400,0x000a211e,0x00001003, -0x0000a730,0x00001008,0x000e2730,0x00001002, -0x0000a731,0x00001002,0x0000a731,0x00001002, -0x0000a731,0x00001002,0x0000a731,0x00001002, -0x0000a731,0x00001002,0x0000a731,0x00001002, -0x00000000,0x00000000,0x000f619c,0x00001003, -0x0007f801,0x000c0000,0x00000037,0x00001000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x000c0000,0x00000000,0x00000000, -0x0000373c,0x00001000,0x00000000,0x00000000, -0x000ee19c,0x00001003,0x0007f801,0x000c0000, -0x00000037,0x00001000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0000273c,0x00001000, -0x00000033,0x00001000,0x000e679e,0x00001003, -0x00007705,0x00001400,0x000ac71e,0x00001003, -0x00087fc1,0x000c3be0,0x0007f801,0x000c0000, -0x00000037,0x00001000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0000a730,0x00001003, -0x00000033,0x00001000,0x0007f801,0x000c0000, -0x00000037,0x00001000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x000c0000, -0x00000032,0x00001000,0x0000273d,0x00001000, -0x0004a730,0x00001003,0x00000f41,0x00097140, -0x0000a841,0x0009b240,0x0000a0c1,0x0009f040, -0x0001c641,0x00093540,0x0001cec1,0x0009b5c0, -0x00000000,0x00000000,0x0001bf05,0x0003fc40, -0x00002725,0x000aa400,0x00013705,0x00093a00, -0x0000002e,0x0009d6c0,0x00038630,0x00001004, -0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000, -0x00000000,0x000c70e0,0x0007d182,0x0002c640, -0x00000630,0x00001004,0x000799b8,0x0002c6c0, -0x00031705,0x00092240,0x00039f05,0x000932c0, -0x0003520a,0x00000000,0x00040731,0x0000100b, -0x00010705,0x000b20c0,0x00000000,0x000eba44, -0x00032108,0x000c60c4,0x00065208,0x000c2917, -0x000406b0,0x00001007,0x00012f05,0x00036880, -0x0002818e,0x000c0000,0x0004410a,0x00000000, -0x00040630,0x00001007,0x00029705,0x000c0000, -0x00000000,0x00000000,0x00003fc1,0x0003fc40, -0x000037c1,0x00091b40,0x00003fc1,0x000911c0, -0x000037c1,0x000957c0,0x00003fc1,0x000951c0, -0x000037c1,0x00000000,0x00003fc1,0x000991c0, -0x000037c1,0x00000000,0x00003fc1,0x0009d1c0, -0x000037c1,0x00000000,0x0001ccc1,0x000915c0, -0x0001c441,0x0009d800,0x0009cdc1,0x00091240, -0x0001c541,0x00091d00,0x0009cfc1,0x00095240, -0x0001c741,0x00095c80,0x000e8ca9,0x00099240, -0x000e85ad,0x00095640,0x00069ca9,0x00099d80, -0x000e952d,0x00099640,0x000eaca9,0x0009d6c0, -0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80, -0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0, -0x000ec5ad,0x0009da40,0x000edca9,0x0009d300, -0x000a6e0a,0x00001000,0x000ed52d,0x00091e40, -0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40, -0x0006fca9,0x00002500,0x000fb208,0x000c59a0, -0x000ef52d,0x0009de40,0x00068ca9,0x000912c1, -0x000683ad,0x00095241,0x00020f05,0x000991c1, -0x00000000,0x00000000,0x00086f88,0x00001000, -0x0009cf81,0x000b5340,0x0009c701,0x000b92c0, -0x0009de81,0x000bd300,0x0009d601,0x000b1700, -0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0, -0x000a0f81,0x000bd740,0x00020701,0x000b5c80, -0x000a1681,0x000b97c0,0x00021601,0x00002500, -0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0, -0x00021681,0x00002d00,0x00020f81,0x000bd800, -0x000a0701,0x000b5bc0,0x00021601,0x00003500, -0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0, -0x00021681,0x00003d00,0x00020f81,0x000b1d00, -0x000a0701,0x000b1fc0,0x00021601,0x00020500, -0x00020f81,0x000b1341,0x000a0701,0x000b9fc0, -0x00021681,0x00020d00,0x00020f81,0x000bde80, -0x000a0701,0x000bdfc0,0x00021601,0x00021500, -0x00020f81,0x000b9341,0x00020701,0x000b53c1, -0x00021681,0x00021d00,0x000a0f81,0x000d0380, -0x0000b601,0x000b15c0,0x00007b01,0x00000000, -0x00007b81,0x000bd1c0,0x00007b01,0x00000000, -0x00007b81,0x000b91c0,0x00007b01,0x000b57c0, -0x00007b81,0x000b51c0,0x00007b01,0x000b1b40, -0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0, -0x0007e488,0x000d7e45,0x00000000,0x000d7a44, -0x0007e48a,0x00000000,0x00011f05,0x00084080, -0x00000000,0x00000000,0x00001705,0x000b3540, -0x00008a01,0x000bf040,0x00007081,0x000bb5c0, -0x00055488,0x00000000,0x0000d482,0x0003fc40, -0x0003fc88,0x00000000,0x0001e401,0x000b3a00, -0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784, -0x000c86b0,0x00001007,0x00008281,0x000bb240, -0x0000b801,0x000b7140,0x00007888,0x00000000, -0x0000073c,0x00001000,0x0007f188,0x000c0000, -0x00000000,0x00000000,0x00055288,0x000c555c, -0x0005528a,0x000c0000,0x0009fa88,0x000c5d00, -0x0000fa88,0x00000000,0x00000032,0x00001000, -0x0000073d,0x00001000,0x0007f188,0x000c0000, -0x00000000,0x00000000,0x0008c01c,0x00001003, -0x00002705,0x00001008,0x0008b201,0x000c1392, -0x0000ba01,0x00000000,0x00008731,0x00001400, -0x0004c108,0x000fe0c4,0x00057488,0x00000000, -0x000a6388,0x00001001,0x0008b334,0x000bc141, -0x0003020e,0x00000000,0x000886b0,0x00001008, -0x00003625,0x000c5dfa,0x000a638a,0x00001001, -0x0008020e,0x00001002,0x0008a6b0,0x00001008, -0x0007f301,0x00000000,0x00000000,0x00000000, -0x00002725,0x000a8c40,0x000000ae,0x00000000, -0x000d8630,0x00001008,0x00000000,0x000c74e0, -0x0007d182,0x0002d640,0x000a8630,0x00001008, -0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5, -0x0007420a,0x000c0000,0x00062208,0x000c4117, -0x00070630,0x00001009,0x00000000,0x000c0000, -0x0001022e,0x00000000,0x0003a630,0x00001009, -0x00000000,0x000c0000,0x00000036,0x00001000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x0002a730,0x00001008,0x0007f801,0x000c0000, -0x00000037,0x00001000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0002a730,0x00001008, -0x00000033,0x00001000,0x0002a705,0x00001008, -0x00007a01,0x000c0000,0x000e6288,0x000d550a, -0x0006428a,0x00000000,0x00060730,0x0000100a, -0x00000000,0x000c0000,0x00000000,0x00000000, -0x0007aab0,0x00034880,0x00078fb0,0x0000100b, -0x00057488,0x00000000,0x00033b94,0x00081140, -0x000183ae,0x00000000,0x000786b0,0x0000100b, -0x00022f05,0x000c3545,0x0000eb8a,0x00000000, -0x00042731,0x00001003,0x0007aab0,0x00034880, -0x00048fb0,0x0000100a,0x00057488,0x00000000, -0x00033b94,0x00081140,0x000183ae,0x00000000, -0x000806b0,0x0000100b,0x00022f05,0x00000000, -0x00007401,0x00091140,0x00048f05,0x000951c0, -0x00042731,0x00001003,0x0000473d,0x00001000, -0x000f19b0,0x000bbc47,0x00080000,0x000bffc7, -0x000fe19e,0x00001003,0x00000000,0x00000000, -0x0008e19c,0x00001003,0x000083c1,0x00093040, -0x00000f41,0x00097140,0x0000a841,0x0009b240, -0x0000a0c1,0x0009f040,0x0001c641,0x00093540, -0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44, -0x00055208,0x00000000,0x00010705,0x000a2880, -0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5, -0x0004ef0a,0x000c0000,0x00012f05,0x00036880, -0x00065308,0x000c2997,0x000d86b0,0x0000100a, -0x0004410a,0x000d40c7,0x00000000,0x00000000, -0x00080730,0x00001004,0x00056f0a,0x000ea105, -0x00000000,0x00000000,0x0000473d,0x00001000, -0x000f19b0,0x000bbc47,0x00080000,0x000bffc7, -0x0000273d,0x00001000,0x00000000,0x000eba44, -0x00048f05,0x0000f440,0x00007401,0x0000f7c0, -0x00000734,0x00001000,0x00010705,0x000a6880, -0x00006a88,0x000c75c4,0x00000000,0x000e5084, -0x00000000,0x000eba44,0x00087401,0x000e4782, -0x00000734,0x00001000,0x00010705,0x000a6880, -0x00006a88,0x000c75c4,0x0007c108,0x000c0000, -0x0007e721,0x000bed40,0x00005f25,0x000badc0, -0x0003ba97,0x000beb80,0x00065590,0x000b2e00, -0x00033217,0x00003ec0,0x00065590,0x000b8e40, -0x0003ed80,0x000491c0,0x00073fb0,0x00074c80, -0x000283a0,0x0000100c,0x000ee388,0x00042970, -0x00008301,0x00021ef2,0x000b8f14,0x0000000f, -0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6, -0x000032ac,0x000c3916,0x0004edc2,0x00074c80, -0x00078898,0x00001000,0x00038894,0x00000032, -0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6, -0x0004edc2,0x000c1956,0x0000722c,0x00034a00, -0x00041705,0x0009ed40,0x00058730,0x00001400, -0x000d7488,0x000c3a00,0x00048f05,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000} - }; diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.c b/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.c deleted file mode 100644 index 4fa53161..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.c +++ /dev/null @@ -1,3882 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Abramo Bagnara - * Cirrus Logic, Inc. - * Routines for control of Cirrus Logic CS461x chips - * - * KNOWN BUGS: - * - Sometimes the SPDIF input DSP tasks get's unsynchronized - * and the SPDIF get somewhat "distorcionated", or/and left right channel - * are swapped. To get around this problem when it happens, mute and unmute - * the SPDIF input mixer control. - * - On the Hercules Game Theater XP the amplifier are sometimes turned - * off on inadecuate moments which causes distorcions on sound. - * - * TODO: - * - Secondary CODEC on some soundcards - * - SPDIF input support for other sample rates then 48khz - * - Posibility to mix the SPDIF output with analog sources. - * - PCM channels for Center and LFE on secondary codec - * - * NOTE: with CONFIG_SND_CS46XX_NEW_DSP unset uses old DSP image (which - * is default configuration), no SPDIF, no secondary codec, no - * multi channel PCM. But known to work. - * - * FINALLY: A credit to the developers Tom and Jordan - * at Cirrus for have helping me out with the DSP, however we - * still don't have sufficient documentation and technical - * references to be able to implement all fancy feutures - * supported by the cs46xx DSP's. - * Benny - * - * 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 - - -#include -#include -#include -#include -#include -#include - -#include - -#include "cs46xx_lib.h" -#include "dsp_spos.h" - -static void amp_voyetra(struct snd_cs46xx *chip, int change); - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -static struct snd_pcm_ops snd_cs46xx_playback_rear_ops; -static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops; -static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops; -static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops; -static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops; -static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops; -#endif - -static struct snd_pcm_ops snd_cs46xx_playback_ops; -static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops; -static struct snd_pcm_ops snd_cs46xx_capture_ops; -static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops; - -static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip, - unsigned short reg, - int codec_index) -{ - int count; - unsigned short result,tmp; - u32 offset = 0; - - if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && - codec_index != CS46XX_SECONDARY_CODEC_INDEX)) - return -EINVAL; - - chip->active_ctrl(chip, 1); - - if (codec_index == CS46XX_SECONDARY_CODEC_INDEX) - offset = CS46XX_SECONDARY_CODEC_OFFSET; - - /* - * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address - * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 - * 3. Write ACCTL = Control Register = 460h for initiating the write7---55 - * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h - * 5. if DCV not cleared, break and return error - * 6. Read ACSTS = Status Register = 464h, check VSTS bit - */ - - snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset); - - tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL); - if ((tmp & ACCTL_VFRM) == 0) { - snd_printk(KERN_WARNING "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp); - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM ); - msleep(50); - tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset); - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM ); - - } - - /* - * Setup the AC97 control registers on the CS461x to send the - * appropriate command to the AC97 to perform the read. - * ACCAD = Command Address Register = 46Ch - * ACCDA = Command Data Register = 470h - * ACCTL = Control Register = 460h - * set DCV - will clear when process completed - * set CRW - Read command - * set VFRM - valid frame enabled - * set ESYN - ASYNC generation enabled - * set RSTN - ARST# inactive, AC97 codec not reset - */ - - snd_cs46xx_pokeBA0(chip, BA0_ACCAD, reg); - snd_cs46xx_pokeBA0(chip, BA0_ACCDA, 0); - if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) { - snd_cs46xx_pokeBA0(chip, BA0_ACCTL,/* clear ACCTL_DCV */ ACCTL_CRW | - ACCTL_VFRM | ACCTL_ESYN | - ACCTL_RSTN); - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW | - ACCTL_VFRM | ACCTL_ESYN | - ACCTL_RSTN); - } else { - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC | - ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN | - ACCTL_RSTN); - } - - /* - * Wait for the read to occur. - */ - for (count = 0; count < 1000; count++) { - /* - * First, we want to wait for a short time. - */ - udelay(10); - /* - * Now, check to see if the read has completed. - * ACCTL = 460h, DCV should be reset by now and 460h = 17h - */ - if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) - goto ok1; - } - - snd_printk(KERN_ERR "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg); - result = 0xffff; - goto end; - - ok1: - /* - * Wait for the valid status bit to go active. - */ - for (count = 0; count < 100; count++) { - /* - * Read the AC97 status register. - * ACSTS = Status Register = 464h - * VSTS - Valid Status - */ - if (snd_cs46xx_peekBA0(chip, BA0_ACSTS + offset) & ACSTS_VSTS) - goto ok2; - udelay(10); - } - - snd_printk(KERN_ERR "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg); - result = 0xffff; - goto end; - - ok2: - /* - * Read the data returned from the AC97 register. - * ACSDA = Status Data Register = 474h - */ -#if 0 - printk(KERN_DEBUG "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg, - snd_cs46xx_peekBA0(chip, BA0_ACSDA), - snd_cs46xx_peekBA0(chip, BA0_ACCAD)); -#endif - - //snd_cs46xx_peekBA0(chip, BA0_ACCAD); - result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset); - end: - chip->active_ctrl(chip, -1); - return result; -} - -static unsigned short snd_cs46xx_ac97_read(struct snd_ac97 * ac97, - unsigned short reg) -{ - struct snd_cs46xx *chip = ac97->private_data; - unsigned short val; - int codec_index = ac97->num; - - if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && - codec_index != CS46XX_SECONDARY_CODEC_INDEX)) - return 0xffff; - - val = snd_cs46xx_codec_read(chip, reg, codec_index); - - return val; -} - - -static void snd_cs46xx_codec_write(struct snd_cs46xx *chip, - unsigned short reg, - unsigned short val, - int codec_index) -{ - int count; - - if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && - codec_index != CS46XX_SECONDARY_CODEC_INDEX)) - return; - - chip->active_ctrl(chip, 1); - - /* - * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address - * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 - * 3. Write ACCTL = Control Register = 460h for initiating the write - * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h - * 5. if DCV not cleared, break and return error - */ - - /* - * Setup the AC97 control registers on the CS461x to send the - * appropriate command to the AC97 to perform the read. - * ACCAD = Command Address Register = 46Ch - * ACCDA = Command Data Register = 470h - * ACCTL = Control Register = 460h - * set DCV - will clear when process completed - * reset CRW - Write command - * set VFRM - valid frame enabled - * set ESYN - ASYNC generation enabled - * set RSTN - ARST# inactive, AC97 codec not reset - */ - snd_cs46xx_pokeBA0(chip, BA0_ACCAD , reg); - snd_cs46xx_pokeBA0(chip, BA0_ACCDA , val); - snd_cs46xx_peekBA0(chip, BA0_ACCTL); - - if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) { - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, /* clear ACCTL_DCV */ ACCTL_VFRM | - ACCTL_ESYN | ACCTL_RSTN); - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM | - ACCTL_ESYN | ACCTL_RSTN); - } else { - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC | - ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); - } - - for (count = 0; count < 4000; count++) { - /* - * First, we want to wait for a short time. - */ - udelay(10); - /* - * Now, check to see if the write has completed. - * ACCTL = 460h, DCV should be reset by now and 460h = 07h - */ - if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) { - goto end; - } - } - snd_printk(KERN_ERR "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val); - end: - chip->active_ctrl(chip, -1); -} - -static void snd_cs46xx_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct snd_cs46xx *chip = ac97->private_data; - int codec_index = ac97->num; - - if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX && - codec_index != CS46XX_SECONDARY_CODEC_INDEX)) - return; - - snd_cs46xx_codec_write(chip, reg, val, codec_index); -} - - -/* - * Chip initialization - */ - -int snd_cs46xx_download(struct snd_cs46xx *chip, - u32 *src, - unsigned long offset, - unsigned long len) -{ - void __iomem *dst; - unsigned int bank = offset >> 16; - offset = offset & 0xffff; - - if (snd_BUG_ON((offset & 3) || (len & 3))) - return -EINVAL; - dst = chip->region.idx[bank+1].remap_addr + offset; - len /= sizeof(u32); - - /* writel already converts 32-bit value to right endianess */ - while (len-- > 0) { - writel(*src++, dst); - dst += sizeof(u32); - } - return 0; -} - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - -#include "imgs/cwc4630.h" -#include "imgs/cwcasync.h" -#include "imgs/cwcsnoop.h" -#include "imgs/cwcbinhack.h" -#include "imgs/cwcdma.h" - -int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip, - unsigned long offset, - unsigned long len) -{ - void __iomem *dst; - unsigned int bank = offset >> 16; - offset = offset & 0xffff; - - if (snd_BUG_ON((offset & 3) || (len & 3))) - return -EINVAL; - dst = chip->region.idx[bank+1].remap_addr + offset; - len /= sizeof(u32); - - /* writel already converts 32-bit value to right endianess */ - while (len-- > 0) { - writel(0, dst); - dst += sizeof(u32); - } - return 0; -} - -#else /* old DSP image */ - -#include "cs46xx_image.h" - -int snd_cs46xx_download_image(struct snd_cs46xx *chip) -{ - int idx, err; - unsigned long offset = 0; - - for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) { - if ((err = snd_cs46xx_download(chip, - &BA1Struct.map[offset], - BA1Struct.memory[idx].offset, - BA1Struct.memory[idx].size)) < 0) - return err; - offset += BA1Struct.memory[idx].size >> 2; - } - return 0; -} -#endif /* CONFIG_SND_CS46XX_NEW_DSP */ - -/* - * Chip reset - */ - -static void snd_cs46xx_reset(struct snd_cs46xx *chip) -{ - int idx; - - /* - * Write the reset bit of the SP control register. - */ - snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP); - - /* - * Write the control register. - */ - snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN); - - /* - * Clear the trap registers. - */ - for (idx = 0; idx < 8; idx++) { - snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx); - snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF); - } - snd_cs46xx_poke(chip, BA1_DREG, 0); - - /* - * Set the frame timer to reflect the number of cycles per frame. - */ - snd_cs46xx_poke(chip, BA1_FRMT, 0xadf); -} - -static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout) -{ - u32 i, status = 0; - /* - * Make sure the previous FIFO write operation has completed. - */ - for(i = 0; i < 50; i++){ - status = snd_cs46xx_peekBA0(chip, BA0_SERBST); - - if( !(status & SERBST_WBSY) ) - break; - - mdelay(retry_timeout); - } - - if(status & SERBST_WBSY) { - snd_printk(KERN_ERR "cs46xx: failure waiting for " - "FIFO command to complete\n"); - return -EINVAL; - } - - return 0; -} - -static void snd_cs46xx_clear_serial_FIFOs(struct snd_cs46xx *chip) -{ - int idx, powerdown = 0; - unsigned int tmp; - - /* - * See if the devices are powered down. If so, we must power them up first - * or they will not respond. - */ - tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1); - if (!(tmp & CLKCR1_SWCE)) { - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE); - powerdown = 1; - } - - /* - * We want to clear out the serial port FIFOs so we don't end up playing - * whatever random garbage happens to be in them. We fill the sample FIFOS - * with zero (silence). - */ - snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0); - - /* - * Fill all 256 sample FIFO locations. - */ - for (idx = 0; idx < 0xFF; idx++) { - /* - * Make sure the previous FIFO write operation has completed. - */ - if (cs46xx_wait_for_fifo(chip,1)) { - snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx); - - if (powerdown) - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); - - break; - } - /* - * Write the serial port FIFO index. - */ - snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx); - /* - * Tell the serial port to load the new value into the FIFO location. - */ - snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC); - } - /* - * Now, if we powered up the devices, then power them back down again. - * This is kinda ugly, but should never happen. - */ - if (powerdown) - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); -} - -static void snd_cs46xx_proc_start(struct snd_cs46xx *chip) -{ - int cnt; - - /* - * Set the frame timer to reflect the number of cycles per frame. - */ - snd_cs46xx_poke(chip, BA1_FRMT, 0xadf); - /* - * Turn on the run, run at frame, and DMA enable bits in the local copy of - * the SP control register. - */ - snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN); - /* - * Wait until the run at frame bit resets itself in the SP control - * register. - */ - for (cnt = 0; cnt < 25; cnt++) { - udelay(50); - if (!(snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR)) - break; - } - - if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR) - snd_printk(KERN_ERR "SPCR_RUNFR never reset\n"); -} - -static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip) -{ - /* - * Turn off the run, run at frame, and DMA enable bits in the local copy of - * the SP control register. - */ - snd_cs46xx_poke(chip, BA1_SPCR, 0); -} - -/* - * Sample rate routines - */ - -#define GOF_PER_SEC 200 - -static void snd_cs46xx_set_play_sample_rate(struct snd_cs46xx *chip, unsigned int rate) -{ - unsigned long flags; - unsigned int tmp1, tmp2; - unsigned int phiIncr; - unsigned int correctionPerGOF, correctionPerSec; - - /* - * Compute the values used to drive the actual sample rate conversion. - * The following formulas are being computed, using inline assembly - * since we need to use 64 bit arithmetic to compute the values: - * - * phiIncr = floor((Fs,in * 2^26) / Fs,out) - * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / - * GOF_PER_SEC) - * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M - * GOF_PER_SEC * correctionPerGOF - * - * i.e. - * - * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out) - * correctionPerGOF:correctionPerSec = - * dividend:remainder(ulOther / GOF_PER_SEC) - */ - tmp1 = rate << 16; - phiIncr = tmp1 / 48000; - tmp1 -= phiIncr * 48000; - tmp1 <<= 10; - phiIncr <<= 10; - tmp2 = tmp1 / 48000; - phiIncr += tmp2; - tmp1 -= tmp2 * 48000; - correctionPerGOF = tmp1 / GOF_PER_SEC; - tmp1 -= correctionPerGOF * GOF_PER_SEC; - correctionPerSec = tmp1; - - /* - * Fill in the SampleRateConverter control block. - */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs46xx_poke(chip, BA1_PSRC, - ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); - snd_cs46xx_poke(chip, BA1_PPI, phiIncr); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned int rate) -{ - unsigned long flags; - unsigned int phiIncr, coeffIncr, tmp1, tmp2; - unsigned int correctionPerGOF, correctionPerSec, initialDelay; - unsigned int frameGroupLength, cnt; - - /* - * We can only decimate by up to a factor of 1/9th the hardware rate. - * Correct the value if an attempt is made to stray outside that limit. - */ - if ((rate * 9) < 48000) - rate = 48000 / 9; - - /* - * We can not capture at at rate greater than the Input Rate (48000). - * Return an error if an attempt is made to stray outside that limit. - */ - if (rate > 48000) - rate = 48000; - - /* - * Compute the values used to drive the actual sample rate conversion. - * The following formulas are being computed, using inline assembly - * since we need to use 64 bit arithmetic to compute the values: - * - * coeffIncr = -floor((Fs,out * 2^23) / Fs,in) - * phiIncr = floor((Fs,in * 2^26) / Fs,out) - * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / - * GOF_PER_SEC) - * correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr - - * GOF_PER_SEC * correctionPerGOF - * initialDelay = ceil((24 * Fs,in) / Fs,out) - * - * i.e. - * - * coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in)) - * phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out) - * correctionPerGOF:correctionPerSec = - * dividend:remainder(ulOther / GOF_PER_SEC) - * initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out) - */ - - tmp1 = rate << 16; - coeffIncr = tmp1 / 48000; - tmp1 -= coeffIncr * 48000; - tmp1 <<= 7; - coeffIncr <<= 7; - coeffIncr += tmp1 / 48000; - coeffIncr ^= 0xFFFFFFFF; - coeffIncr++; - tmp1 = 48000 << 16; - phiIncr = tmp1 / rate; - tmp1 -= phiIncr * rate; - tmp1 <<= 10; - phiIncr <<= 10; - tmp2 = tmp1 / rate; - phiIncr += tmp2; - tmp1 -= tmp2 * rate; - correctionPerGOF = tmp1 / GOF_PER_SEC; - tmp1 -= correctionPerGOF * GOF_PER_SEC; - correctionPerSec = tmp1; - initialDelay = ((48000 * 24) + rate - 1) / rate; - - /* - * Fill in the VariDecimate control block. - */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs46xx_poke(chip, BA1_CSRC, - ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF)); - snd_cs46xx_poke(chip, BA1_CCI, coeffIncr); - snd_cs46xx_poke(chip, BA1_CD, - (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80); - snd_cs46xx_poke(chip, BA1_CPI, phiIncr); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - /* - * Figure out the frame group length for the write back task. Basically, - * this is just the factors of 24000 (2^6*3*5^3) that are not present in - * the output sample rate. - */ - frameGroupLength = 1; - for (cnt = 2; cnt <= 64; cnt *= 2) { - if (((rate / cnt) * cnt) != rate) - frameGroupLength *= 2; - } - if (((rate / 3) * 3) != rate) { - frameGroupLength *= 3; - } - for (cnt = 5; cnt <= 125; cnt *= 5) { - if (((rate / cnt) * cnt) != rate) - frameGroupLength *= 5; - } - - /* - * Fill in the WriteBack control block. - */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength); - snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength)); - snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF); - snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000)); - snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -/* - * PCM part - */ - -static void snd_cs46xx_pb_trans_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_cs46xx_pcm * cpcm = runtime->private_data; - memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes); -} - -static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_cs46xx_pcm * cpcm = runtime->private_data; - snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy); - return 0; -} - -static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - memcpy(runtime->dma_area + rec->sw_data, - chip->capt.hw_buf.area + rec->hw_data, bytes); -} - -static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy); - return 0; -} - -static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - size_t ptr; - struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data; - - if (snd_BUG_ON(!cpcm->pcm_channel)) - return -ENXIO; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2); -#else - ptr = snd_cs46xx_peek(chip, BA1_PBA); -#endif - ptr -= cpcm->hw_buf.addr; - return ptr >> cpcm->shift; -} - -static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - size_t ptr; - struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (snd_BUG_ON(!cpcm->pcm_channel)) - return -ENXIO; - ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2); -#else - ptr = snd_cs46xx_peek(chip, BA1_PBA); -#endif - ptr -= cpcm->hw_buf.addr; - return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr); -} - -static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr; - return ptr >> chip->capt.shift; -} - -static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr; - return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr); -} - -static int snd_cs46xx_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - /*struct snd_pcm_runtime *runtime = substream->runtime;*/ - int result = 0; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data; - if (! cpcm->pcm_channel) { - return -ENXIO; - } -#endif - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: -#ifdef CONFIG_SND_CS46XX_NEW_DSP - /* magic value to unmute PCM stream playback volume */ - snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + - SCBVolumeCtrl) << 2, 0x80008000); - - if (cpcm->pcm_channel->unlinked) - cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel); - - if (substream->runtime->periods != CS46XX_FRAGS) - snd_cs46xx_playback_transfer(substream); -#else - spin_lock(&chip->reg_lock); - if (substream->runtime->periods != CS46XX_FRAGS) - snd_cs46xx_playback_transfer(substream); - { unsigned int tmp; - tmp = snd_cs46xx_peek(chip, BA1_PCTL); - tmp &= 0x0000ffff; - snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp); - } - spin_unlock(&chip->reg_lock); -#endif - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: -#ifdef CONFIG_SND_CS46XX_NEW_DSP - /* magic mute channel */ - snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + - SCBVolumeCtrl) << 2, 0xffffffff); - - if (!cpcm->pcm_channel->unlinked) - cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel); -#else - spin_lock(&chip->reg_lock); - { unsigned int tmp; - tmp = snd_cs46xx_peek(chip, BA1_PCTL); - tmp &= 0x0000ffff; - snd_cs46xx_poke(chip, BA1_PCTL, tmp); - } - spin_unlock(&chip->reg_lock); -#endif - break; - default: - result = -EINVAL; - break; - } - - return result; -} - -static int snd_cs46xx_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - unsigned int tmp; - int result = 0; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - tmp = snd_cs46xx_peek(chip, BA1_CCTL); - tmp &= 0xffff0000; - snd_cs46xx_poke(chip, BA1_CCTL, chip->capt.ctl | tmp); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - tmp = snd_cs46xx_peek(chip, BA1_CCTL); - tmp &= 0xffff0000; - snd_cs46xx_poke(chip, BA1_CCTL, tmp); - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&chip->reg_lock); - - return result; -} - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46xx_pcm *cpcm, - int sample_rate) -{ - - /* If PCMReaderSCB and SrcTaskSCB not created yet ... */ - if ( cpcm->pcm_channel == NULL) { - cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, - cpcm, cpcm->hw_buf.addr,cpcm->pcm_channel_id); - if (cpcm->pcm_channel == NULL) { - snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n"); - return -ENOMEM; - } - cpcm->pcm_channel->sample_rate = sample_rate; - } else - /* if sample rate is changed */ - if ((int)cpcm->pcm_channel->sample_rate != sample_rate) { - int unlinked = cpcm->pcm_channel->unlinked; - cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel); - - if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, - cpcm->hw_buf.addr, - cpcm->pcm_channel_id)) == NULL) { - snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n"); - return -ENOMEM; - } - - if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel); - cpcm->pcm_channel->sample_rate = sample_rate; - } - - return 0; -} -#endif - - -static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_cs46xx_pcm *cpcm; - int err; -#ifdef CONFIG_SND_CS46XX_NEW_DSP - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - int sample_rate = params_rate(hw_params); - int period_size = params_period_bytes(hw_params); -#endif - cpcm = runtime->private_data; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (snd_BUG_ON(!sample_rate)) - return -ENXIO; - - mutex_lock(&chip->spos_mutex); - - if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) { - mutex_unlock(&chip->spos_mutex); - return -ENXIO; - } - - snd_BUG_ON(!cpcm->pcm_channel); - if (!cpcm->pcm_channel) { - mutex_unlock(&chip->spos_mutex); - return -ENXIO; - } - - - if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) { - mutex_unlock(&chip->spos_mutex); - return -EINVAL; - } - - snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n", - period_size, params_periods(hw_params), - params_buffer_bytes(hw_params)); -#endif - - if (params_periods(hw_params) == CS46XX_FRAGS) { - if (runtime->dma_area != cpcm->hw_buf.area) - snd_pcm_lib_free_pages(substream); - runtime->dma_area = cpcm->hw_buf.area; - runtime->dma_addr = cpcm->hw_buf.addr; - runtime->dma_bytes = cpcm->hw_buf.bytes; - - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { - substream->ops = &snd_cs46xx_playback_ops; - } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) { - substream->ops = &snd_cs46xx_playback_rear_ops; - } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) { - substream->ops = &snd_cs46xx_playback_clfe_ops; - } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) { - substream->ops = &snd_cs46xx_playback_iec958_ops; - } else { - snd_BUG(); - } -#else - substream->ops = &snd_cs46xx_playback_ops; -#endif - - } else { - if (runtime->dma_area == cpcm->hw_buf.area) { - runtime->dma_area = NULL; - runtime->dma_addr = 0; - runtime->dma_bytes = 0; - } - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) { -#ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_unlock(&chip->spos_mutex); -#endif - return err; - } - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) { - substream->ops = &snd_cs46xx_playback_indirect_ops; - } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) { - substream->ops = &snd_cs46xx_playback_indirect_rear_ops; - } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) { - substream->ops = &snd_cs46xx_playback_indirect_clfe_ops; - } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) { - substream->ops = &snd_cs46xx_playback_indirect_iec958_ops; - } else { - snd_BUG(); - } -#else - substream->ops = &snd_cs46xx_playback_indirect_ops; -#endif - - } - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_unlock(&chip->spos_mutex); -#endif - - return 0; -} - -static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream) -{ - /*struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);*/ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_cs46xx_pcm *cpcm; - - cpcm = runtime->private_data; - - /* if play_back open fails, then this function - is called and cpcm can actually be NULL here */ - if (!cpcm) return -ENXIO; - - if (runtime->dma_area != cpcm->hw_buf.area) - snd_pcm_lib_free_pages(substream); - - runtime->dma_area = NULL; - runtime->dma_addr = 0; - runtime->dma_bytes = 0; - - return 0; -} - -static int snd_cs46xx_playback_prepare(struct snd_pcm_substream *substream) -{ - unsigned int tmp; - unsigned int pfie; - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_cs46xx_pcm *cpcm; - - cpcm = runtime->private_data; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (snd_BUG_ON(!cpcm->pcm_channel)) - return -ENXIO; - - pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 ); - pfie &= ~0x0000f03f; -#else - /* old dsp */ - pfie = snd_cs46xx_peek(chip, BA1_PFIE); - pfie &= ~0x0000f03f; -#endif - - cpcm->shift = 2; - /* if to convert from stereo to mono */ - if (runtime->channels == 1) { - cpcm->shift--; - pfie |= 0x00002000; - } - /* if to convert from 8 bit to 16 bit */ - if (snd_pcm_format_width(runtime->format) == 8) { - cpcm->shift--; - pfie |= 0x00001000; - } - /* if to convert to unsigned */ - if (snd_pcm_format_unsigned(runtime->format)) - pfie |= 0x00008000; - - /* Never convert byte order when sample stream is 8 bit */ - if (snd_pcm_format_width(runtime->format) != 8) { - /* convert from big endian to little endian */ - if (snd_pcm_format_big_endian(runtime->format)) - pfie |= 0x00004000; - } - - memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec)); - cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - - tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2); - tmp &= ~0x000003ff; - tmp |= (4 << cpcm->shift) - 1; - /* playback transaction count register */ - snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2, tmp); - - /* playback format && interrupt enable */ - snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2, pfie | cpcm->pcm_channel->pcm_slot); -#else - snd_cs46xx_poke(chip, BA1_PBA, cpcm->hw_buf.addr); - tmp = snd_cs46xx_peek(chip, BA1_PDTC); - tmp &= ~0x000003ff; - tmp |= (4 << cpcm->shift) - 1; - snd_cs46xx_poke(chip, BA1_PDTC, tmp); - snd_cs46xx_poke(chip, BA1_PFIE, pfie); - snd_cs46xx_set_play_sample_rate(chip, runtime->rate); -#endif - - return 0; -} - -static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - cs46xx_dsp_pcm_ostream_set_period (chip, params_period_bytes(hw_params)); -#endif - if (runtime->periods == CS46XX_FRAGS) { - if (runtime->dma_area != chip->capt.hw_buf.area) - snd_pcm_lib_free_pages(substream); - runtime->dma_area = chip->capt.hw_buf.area; - runtime->dma_addr = chip->capt.hw_buf.addr; - runtime->dma_bytes = chip->capt.hw_buf.bytes; - substream->ops = &snd_cs46xx_capture_ops; - } else { - if (runtime->dma_area == chip->capt.hw_buf.area) { - runtime->dma_area = NULL; - runtime->dma_addr = 0; - runtime->dma_bytes = 0; - } - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - substream->ops = &snd_cs46xx_capture_indirect_ops; - } - - return 0; -} - -static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (runtime->dma_area != chip->capt.hw_buf.area) - snd_pcm_lib_free_pages(substream); - runtime->dma_area = NULL; - runtime->dma_addr = 0; - runtime->dma_bytes = 0; - - return 0; -} - -static int snd_cs46xx_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr); - chip->capt.shift = 2; - memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec)); - chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2; - snd_cs46xx_set_capture_sample_rate(chip, runtime->rate); - - return 0; -} - -static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id) -{ - struct snd_cs46xx *chip = dev_id; - u32 status1; -#ifdef CONFIG_SND_CS46XX_NEW_DSP - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - u32 status2; - int i; - struct snd_cs46xx_pcm *cpcm = NULL; -#endif - - /* - * Read the Interrupt Status Register to clear the interrupt - */ - status1 = snd_cs46xx_peekBA0(chip, BA0_HISR); - if ((status1 & 0x7fffffff) == 0) { - snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV); - return IRQ_NONE; - } - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - status2 = snd_cs46xx_peekBA0(chip, BA0_HSR0); - - for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) { - if (i <= 15) { - if ( status1 & (1 << i) ) { - if (i == CS46XX_DSP_CAPTURE_CHANNEL) { - if (chip->capt.substream) - snd_pcm_period_elapsed(chip->capt.substream); - } else { - if (ins->pcm_channels[i].active && - ins->pcm_channels[i].private_data && - !ins->pcm_channels[i].unlinked) { - cpcm = ins->pcm_channels[i].private_data; - snd_pcm_period_elapsed(cpcm->substream); - } - } - } - } else { - if ( status2 & (1 << (i - 16))) { - if (ins->pcm_channels[i].active && - ins->pcm_channels[i].private_data && - !ins->pcm_channels[i].unlinked) { - cpcm = ins->pcm_channels[i].private_data; - snd_pcm_period_elapsed(cpcm->substream); - } - } - } - } - -#else - /* old dsp */ - if ((status1 & HISR_VC0) && chip->playback_pcm) { - if (chip->playback_pcm->substream) - snd_pcm_period_elapsed(chip->playback_pcm->substream); - } - if ((status1 & HISR_VC1) && chip->pcm) { - if (chip->capt.substream) - snd_pcm_period_elapsed(chip->capt.substream); - } -#endif - - if ((status1 & HISR_MIDI) && chip->rmidi) { - unsigned char c; - - spin_lock(&chip->reg_lock); - while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) { - c = snd_cs46xx_peekBA0(chip, BA0_MIDRP); - if ((chip->midcr & MIDCR_RIE) == 0) - continue; - snd_rawmidi_receive(chip->midi_input, &c, 1); - } - while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) { - if ((chip->midcr & MIDCR_TIE) == 0) - break; - if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) { - chip->midcr &= ~MIDCR_TIE; - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - break; - } - snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c); - } - spin_unlock(&chip->reg_lock); - } - /* - * EOI to the PCI part....reenables interrupts - */ - snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV); - - return IRQ_HANDLED; -} - -static struct snd_pcm_hardware snd_cs46xx_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ - /*SNDRV_PCM_INFO_RESUME*/), - .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5500, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (256 * 1024), - .period_bytes_min = CS46XX_MIN_PERIOD_SIZE, - .period_bytes_max = CS46XX_MAX_PERIOD_SIZE, - .periods_min = CS46XX_FRAGS, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_cs46xx_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/ - /*SNDRV_PCM_INFO_RESUME*/), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5500, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (256 * 1024), - .period_bytes_min = CS46XX_MIN_PERIOD_SIZE, - .period_bytes_max = CS46XX_MAX_PERIOD_SIZE, - .periods_min = CS46XX_FRAGS, - .periods_max = 1024, - .fifo_size = 0, -}; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - -static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 }; - -static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { - .count = ARRAY_SIZE(period_sizes), - .list = period_sizes, - .mask = 0 -}; - -#endif - -static void snd_cs46xx_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,int pcm_channel_id) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - struct snd_cs46xx_pcm * cpcm; - struct snd_pcm_runtime *runtime = substream->runtime; - - cpcm = kzalloc(sizeof(*cpcm), GFP_KERNEL); - if (cpcm == NULL) - return -ENOMEM; - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - PAGE_SIZE, &cpcm->hw_buf) < 0) { - kfree(cpcm); - return -ENOMEM; - } - - runtime->hw = snd_cs46xx_playback; - runtime->private_data = cpcm; - runtime->private_free = snd_cs46xx_pcm_free_substream; - - cpcm->substream = substream; -#ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_lock(&chip->spos_mutex); - cpcm->pcm_channel = NULL; - cpcm->pcm_channel_id = pcm_channel_id; - - - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - &hw_constraints_period_sizes); - - mutex_unlock(&chip->spos_mutex); -#else - chip->playback_pcm = cpcm; /* HACK */ -#endif - - if (chip->accept_valid) - substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID; - chip->active_ctrl(chip, 1); - - return 0; -} - -static int snd_cs46xx_playback_open(struct snd_pcm_substream *substream) -{ - snd_printdd("open front channel\n"); - return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL); -} - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -static int snd_cs46xx_playback_open_rear(struct snd_pcm_substream *substream) -{ - snd_printdd("open rear channel\n"); - - return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL); -} - -static int snd_cs46xx_playback_open_clfe(struct snd_pcm_substream *substream) -{ - snd_printdd("open center - LFE channel\n"); - - return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL); -} - -static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - - snd_printdd("open raw iec958 channel\n"); - - mutex_lock(&chip->spos_mutex); - cs46xx_iec958_pre_open (chip); - mutex_unlock(&chip->spos_mutex); - - return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL); -} - -static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream); - -static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream) -{ - int err; - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - - snd_printdd("close raw iec958 channel\n"); - - err = snd_cs46xx_playback_close(substream); - - mutex_lock(&chip->spos_mutex); - cs46xx_iec958_post_close (chip); - mutex_unlock(&chip->spos_mutex); - - return err; -} -#endif - -static int snd_cs46xx_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - PAGE_SIZE, &chip->capt.hw_buf) < 0) - return -ENOMEM; - chip->capt.substream = substream; - substream->runtime->hw = snd_cs46xx_capture; - - if (chip->accept_valid) - substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID; - - chip->active_ctrl(chip, 1); - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - &hw_constraints_period_sizes); -#endif - return 0; -} - -static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_cs46xx_pcm * cpcm; - - cpcm = runtime->private_data; - - /* when playback_open fails, then cpcm can be NULL */ - if (!cpcm) return -ENXIO; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_lock(&chip->spos_mutex); - if (cpcm->pcm_channel) { - cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel); - cpcm->pcm_channel = NULL; - } - mutex_unlock(&chip->spos_mutex); -#else - chip->playback_pcm = NULL; -#endif - - cpcm->substream = NULL; - snd_dma_free_pages(&cpcm->hw_buf); - chip->active_ctrl(chip, -1); - - return 0; -} - -static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - - chip->capt.substream = NULL; - snd_dma_free_pages(&chip->capt.hw_buf); - chip->active_ctrl(chip, -1); - - return 0; -} - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = { - .open = snd_cs46xx_playback_open_rear, - .close = snd_cs46xx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_playback_hw_params, - .hw_free = snd_cs46xx_playback_hw_free, - .prepare = snd_cs46xx_playback_prepare, - .trigger = snd_cs46xx_playback_trigger, - .pointer = snd_cs46xx_playback_direct_pointer, -}; - -static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = { - .open = snd_cs46xx_playback_open_rear, - .close = snd_cs46xx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_playback_hw_params, - .hw_free = snd_cs46xx_playback_hw_free, - .prepare = snd_cs46xx_playback_prepare, - .trigger = snd_cs46xx_playback_trigger, - .pointer = snd_cs46xx_playback_indirect_pointer, - .ack = snd_cs46xx_playback_transfer, -}; - -static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = { - .open = snd_cs46xx_playback_open_clfe, - .close = snd_cs46xx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_playback_hw_params, - .hw_free = snd_cs46xx_playback_hw_free, - .prepare = snd_cs46xx_playback_prepare, - .trigger = snd_cs46xx_playback_trigger, - .pointer = snd_cs46xx_playback_direct_pointer, -}; - -static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = { - .open = snd_cs46xx_playback_open_clfe, - .close = snd_cs46xx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_playback_hw_params, - .hw_free = snd_cs46xx_playback_hw_free, - .prepare = snd_cs46xx_playback_prepare, - .trigger = snd_cs46xx_playback_trigger, - .pointer = snd_cs46xx_playback_indirect_pointer, - .ack = snd_cs46xx_playback_transfer, -}; - -static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = { - .open = snd_cs46xx_playback_open_iec958, - .close = snd_cs46xx_playback_close_iec958, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_playback_hw_params, - .hw_free = snd_cs46xx_playback_hw_free, - .prepare = snd_cs46xx_playback_prepare, - .trigger = snd_cs46xx_playback_trigger, - .pointer = snd_cs46xx_playback_direct_pointer, -}; - -static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = { - .open = snd_cs46xx_playback_open_iec958, - .close = snd_cs46xx_playback_close_iec958, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_playback_hw_params, - .hw_free = snd_cs46xx_playback_hw_free, - .prepare = snd_cs46xx_playback_prepare, - .trigger = snd_cs46xx_playback_trigger, - .pointer = snd_cs46xx_playback_indirect_pointer, - .ack = snd_cs46xx_playback_transfer, -}; - -#endif - -static struct snd_pcm_ops snd_cs46xx_playback_ops = { - .open = snd_cs46xx_playback_open, - .close = snd_cs46xx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_playback_hw_params, - .hw_free = snd_cs46xx_playback_hw_free, - .prepare = snd_cs46xx_playback_prepare, - .trigger = snd_cs46xx_playback_trigger, - .pointer = snd_cs46xx_playback_direct_pointer, -}; - -static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = { - .open = snd_cs46xx_playback_open, - .close = snd_cs46xx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_playback_hw_params, - .hw_free = snd_cs46xx_playback_hw_free, - .prepare = snd_cs46xx_playback_prepare, - .trigger = snd_cs46xx_playback_trigger, - .pointer = snd_cs46xx_playback_indirect_pointer, - .ack = snd_cs46xx_playback_transfer, -}; - -static struct snd_pcm_ops snd_cs46xx_capture_ops = { - .open = snd_cs46xx_capture_open, - .close = snd_cs46xx_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_capture_hw_params, - .hw_free = snd_cs46xx_capture_hw_free, - .prepare = snd_cs46xx_capture_prepare, - .trigger = snd_cs46xx_capture_trigger, - .pointer = snd_cs46xx_capture_direct_pointer, -}; - -static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = { - .open = snd_cs46xx_capture_open, - .close = snd_cs46xx_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs46xx_capture_hw_params, - .hw_free = snd_cs46xx_capture_hw_free, - .prepare = snd_cs46xx_capture_prepare, - .trigger = snd_cs46xx_capture_trigger, - .pointer = snd_cs46xx_capture_indirect_pointer, - .ack = snd_cs46xx_capture_transfer, -}; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -#define MAX_PLAYBACK_CHANNELS (DSP_MAX_PCM_CHANNELS - 1) -#else -#define MAX_PLAYBACK_CHANNELS 1 -#endif - -int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0) - return err; - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs46xx_capture_ops); - - /* global setup */ - pcm->info_flags = 0; - strcpy(pcm->name, "CS46xx"); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 256*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} - - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) - return err; - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops); - - /* global setup */ - pcm->info_flags = 0; - strcpy(pcm->name, "CS46xx - Rear"); - chip->pcm_rear = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 256*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) - return err; - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_clfe_ops); - - /* global setup */ - pcm->info_flags = 0; - strcpy(pcm->name, "CS46xx - Center LFE"); - chip->pcm_center_lfe = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 256*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0) - return err; - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops); - - /* global setup */ - pcm->info_flags = 0; - strcpy(pcm->name, "CS46xx - IEC958"); - chip->pcm_rear = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 256*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} -#endif - -/* - * Mixer routines - */ -static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct snd_cs46xx *chip = bus->private_data; - - chip->ac97_bus = NULL; -} - -static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct snd_cs46xx *chip = ac97->private_data; - - if (snd_BUG_ON(ac97 != chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] && - ac97 != chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])) - return; - - if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) { - chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL; - chip->eapd_switch = NULL; - } - else - chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL; -} - -static int snd_cs46xx_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0x7fff; - return 0; -} - -static int snd_cs46xx_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value; - unsigned int val = snd_cs46xx_peek(chip, reg); - ucontrol->value.integer.value[0] = 0xffff - (val >> 16); - ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff); - return 0; -} - -static int snd_cs46xx_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value; - unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 | - (0xffff - ucontrol->value.integer.value[1])); - unsigned int old = snd_cs46xx_peek(chip, reg); - int change = (old != val); - - if (change) { - snd_cs46xx_poke(chip, reg, val); - } - - return change; -} - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - -static int snd_cs46xx_vol_dac_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left; - ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right; - - return 0; -} - -static int snd_cs46xx_vol_dac_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - int change = 0; - - if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] || - chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) { - cs46xx_dsp_set_dac_volume(chip, - ucontrol->value.integer.value[0], - ucontrol->value.integer.value[1]); - change = 1; - } - - return change; -} - -#if 0 -static int snd_cs46xx_vol_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left; - ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right; - return 0; -} - -static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - int change = 0; - - if (chip->dsp_spos_instance->spdif_input_volume_left != ucontrol->value.integer.value[0] || - chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) { - cs46xx_dsp_set_iec958_volume (chip, - ucontrol->value.integer.value[0], - ucontrol->value.integer.value[1]); - change = 1; - } - - return change; -} -#endif - -#define snd_mixer_boolean_info snd_ctl_boolean_mono_info - -static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value; - - if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT) - ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); - else - ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in; - - return 0; -} - -static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - int change, res; - - switch (kcontrol->private_value) { - case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT: - mutex_lock(&chip->spos_mutex); - change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED); - if (ucontrol->value.integer.value[0] && !change) - cs46xx_dsp_enable_spdif_out(chip); - else if (change && !ucontrol->value.integer.value[0]) - cs46xx_dsp_disable_spdif_out(chip); - - res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED)); - mutex_unlock(&chip->spos_mutex); - break; - case CS46XX_MIXER_SPDIF_INPUT_ELEMENT: - change = chip->dsp_spos_instance->spdif_status_in; - if (ucontrol->value.integer.value[0] && !change) { - cs46xx_dsp_enable_spdif_in(chip); - /* restore volume */ - } - else if (change && !ucontrol->value.integer.value[0]) - cs46xx_dsp_disable_spdif_in(chip); - - res = (change != chip->dsp_spos_instance->spdif_status_in); - break; - default: - res = -EINVAL; - snd_BUG(); /* should never happen ... */ - } - - return res; -} - -static int snd_cs46xx_adc_capture_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (ins->adc_input != NULL) - ucontrol->value.integer.value[0] = 1; - else - ucontrol->value.integer.value[0] = 0; - - return 0; -} - -static int snd_cs46xx_adc_capture_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int change = 0; - - if (ucontrol->value.integer.value[0] && !ins->adc_input) { - cs46xx_dsp_enable_adc_capture(chip); - change = 1; - } else if (!ucontrol->value.integer.value[0] && ins->adc_input) { - cs46xx_dsp_disable_adc_capture(chip); - change = 1; - } - return change; -} - -static int snd_cs46xx_pcm_capture_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (ins->pcm_input != NULL) - ucontrol->value.integer.value[0] = 1; - else - ucontrol->value.integer.value[0] = 0; - - return 0; -} - - -static int snd_cs46xx_pcm_capture_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int change = 0; - - if (ucontrol->value.integer.value[0] && !ins->pcm_input) { - cs46xx_dsp_enable_pcm_capture(chip); - change = 1; - } else if (!ucontrol->value.integer.value[0] && ins->pcm_input) { - cs46xx_dsp_disable_pcm_capture(chip); - change = 1; - } - - return change; -} - -static int snd_herc_spdif_select_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - - int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR); - - if (val1 & EGPIODR_GPOE0) - ucontrol->value.integer.value[0] = 1; - else - ucontrol->value.integer.value[0] = 0; - - return 0; -} - -/* - * Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial. - */ -static int snd_herc_spdif_select_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR); - int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR); - - if (ucontrol->value.integer.value[0]) { - /* optical is default */ - snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, - EGPIODR_GPOE0 | val1); /* enable EGPIO0 output */ - snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, - EGPIOPTR_GPPT0 | val2); /* open-drain on output */ - } else { - /* coaxial */ - snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE0); /* disable */ - snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */ - } - - /* checking diff from the EGPIO direction register - should be enough */ - return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR)); -} - - -static int snd_cs46xx_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - mutex_lock(&chip->spos_mutex); - ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff); - ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff); - ucontrol->value.iec958.status[2] = 0; - ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff); - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol); - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - unsigned int val; - int change; - - mutex_lock(&chip->spos_mutex); - val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | - ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) | - ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | - /* left and right validity bit */ - (1 << 13) | (1 << 12); - - - change = (unsigned int)ins->spdif_csuv_default != val; - ins->spdif_csuv_default = val; - - if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) ) - cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); - - mutex_unlock(&chip->spos_mutex); - - return change; -} - -static int snd_cs46xx_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0x00; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - mutex_lock(&chip->spos_mutex); - ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff); - ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff); - ucontrol->value.iec958.status[2] = 0; - ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff); - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol); - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - unsigned int val; - int change; - - mutex_lock(&chip->spos_mutex); - val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) | - ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) | - ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) | - /* left and right validity bit */ - (1 << 13) | (1 << 12); - - - change = ins->spdif_csuv_stream != val; - ins->spdif_csuv_stream = val; - - if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN ) - cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val); - - mutex_unlock(&chip->spos_mutex); - - return change; -} - -#endif /* CONFIG_SND_CS46XX_NEW_DSP */ - - -static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Volume", - .info = snd_cs46xx_vol_info, -#ifndef CONFIG_SND_CS46XX_NEW_DSP - .get = snd_cs46xx_vol_get, - .put = snd_cs46xx_vol_put, - .private_value = BA1_PVOL, -#else - .get = snd_cs46xx_vol_dac_get, - .put = snd_cs46xx_vol_dac_put, -#endif -}, - -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Volume", - .info = snd_cs46xx_vol_info, - .get = snd_cs46xx_vol_get, - .put = snd_cs46xx_vol_put, -#ifndef CONFIG_SND_CS46XX_NEW_DSP - .private_value = BA1_CVOL, -#else - .private_value = (VARIDECIMATE_SCB_ADDR + 0xE) << 2, -#endif -}, -#ifdef CONFIG_SND_CS46XX_NEW_DSP -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Capture Switch", - .info = snd_mixer_boolean_info, - .get = snd_cs46xx_adc_capture_get, - .put = snd_cs46xx_adc_capture_put -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Capture Switch", - .info = snd_mixer_boolean_info, - .get = snd_cs46xx_pcm_capture_get, - .put = snd_cs46xx_pcm_capture_put -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), - .info = snd_mixer_boolean_info, - .get = snd_cs46xx_iec958_get, - .put = snd_cs46xx_iec958_put, - .private_value = CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,SWITCH), - .info = snd_mixer_boolean_info, - .get = snd_cs46xx_iec958_get, - .put = snd_cs46xx_iec958_put, - .private_value = CS46XX_MIXER_SPDIF_INPUT_ELEMENT, -}, -#if 0 -/* Input IEC958 volume does not work for the moment. (Benny) */ -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,VOLUME), - .info = snd_cs46xx_vol_info, - .get = snd_cs46xx_vol_iec958_get, - .put = snd_cs46xx_vol_iec958_put, - .private_value = (ASYNCRX_SCB_ADDR + 0xE) << 2, -}, -#endif -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_cs46xx_spdif_info, - .get = snd_cs46xx_spdif_default_get, - .put = snd_cs46xx_spdif_default_put, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .info = snd_cs46xx_spdif_info, - .get = snd_cs46xx_spdif_mask_get, - .access = SNDRV_CTL_ELEM_ACCESS_READ -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_cs46xx_spdif_info, - .get = snd_cs46xx_spdif_stream_get, - .put = snd_cs46xx_spdif_stream_put -}, - -#endif -}; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -/* set primary cs4294 codec into Extended Audio Mode */ -static int snd_cs46xx_front_dup_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - unsigned short val; - val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE); - ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1; - return 0; -} - -static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol); - return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], - AC97_CSR_ACMODE, 0x200, - ucontrol->value.integer.value[0] ? 0 : 0x200); -} - -static struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Duplicate Front", - .info = snd_mixer_boolean_info, - .get = snd_cs46xx_front_dup_get, - .put = snd_cs46xx_front_dup_put, -}; -#endif - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -/* Only available on the Hercules Game Theater XP soundcard */ -static struct snd_kcontrol_new snd_hercules_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Optical/Coaxial SPDIF Input Switch", - .info = snd_mixer_boolean_info, - .get = snd_herc_spdif_select_get, - .put = snd_herc_spdif_select_put, -}, -}; - - -static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97) -{ - unsigned long end_time; - int err; - - /* reset to defaults */ - snd_ac97_write(ac97, AC97_RESET, 0); - - /* set the desired CODEC mode */ - if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) { - snd_printdd("cs46xx: CODEC1 mode %04x\n", 0x0); - snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x0); - } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) { - snd_printdd("cs46xx: CODEC2 mode %04x\n", 0x3); - snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x3); - } else { - snd_BUG(); /* should never happen ... */ - } - - udelay(50); - - /* it's necessary to wait awhile until registers are accessible after RESET */ - /* because the PCM or MASTER volume registers can be modified, */ - /* the REC_GAIN register is used for tests */ - end_time = jiffies + HZ; - do { - unsigned short ext_mid; - - /* use preliminary reads to settle the communication */ - snd_ac97_read(ac97, AC97_RESET); - snd_ac97_read(ac97, AC97_VENDOR_ID1); - snd_ac97_read(ac97, AC97_VENDOR_ID2); - /* modem? */ - ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID); - if (ext_mid != 0xffff && (ext_mid & 1) != 0) - return; - - /* test if we can write to the record gain volume register */ - snd_ac97_write(ac97, AC97_REC_GAIN, 0x8a05); - if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) - return; - - msleep(10); - } while (time_after_eq(end_time, jiffies)); - - snd_printk(KERN_ERR "CS46xx secondary codec doesn't respond!\n"); -} -#endif - -static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) -{ - int idx, err; - struct snd_ac97_template ac97; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_cs46xx_mixer_free_ac97; - ac97.num = codec; - if (chip->amplifier_ctrl == amp_voyetra) - ac97.scaps = AC97_SCAP_INV_EAPD; - - if (codec == CS46XX_SECONDARY_CODEC_INDEX) { - snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec); - udelay(10); - if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) { - snd_printdd("snd_cs46xx: seconadry codec not present\n"); - return -ENXIO; - } - } - - snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec); - for (idx = 0; idx < 100; ++idx) { - if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) { - err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]); - return err; - } - msleep(10); - } - snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); - return -ENXIO; -} - -int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) -{ - struct snd_card *card = chip->card; - struct snd_ctl_elem_id id; - int err; - unsigned int idx; - static struct snd_ac97_bus_ops ops = { -#ifdef CONFIG_SND_CS46XX_NEW_DSP - .reset = snd_cs46xx_codec_reset, -#endif - .write = snd_cs46xx_ac97_write, - .read = snd_cs46xx_ac97_read, - }; - - /* detect primary codec */ - chip->nr_ac97_codecs = 0; - snd_printdd("snd_cs46xx: detecting primary codec\n"); - if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) - return err; - chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus; - - if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0) - return -ENXIO; - chip->nr_ac97_codecs = 1; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_printdd("snd_cs46xx: detecting seconadry codec\n"); - /* try detect a secondary codec */ - if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX)) - chip->nr_ac97_codecs = 2; -#endif /* CONFIG_SND_CS46XX_NEW_DSP */ - - /* add cs4630 mixer controls */ - for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip); - if (kctl && kctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM) - kctl->id.device = spdif_device; - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - } - - /* get EAPD mixer switch (for voyetra hack) */ - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, "External Amplifier"); - chip->eapd_switch = snd_ctl_find_id(chip->card, &id); - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (chip->nr_ac97_codecs == 1) { - unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff; - if (id2 == 0x592b || id2 == 0x592d) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_cs46xx_front_dup_ctl, chip)); - if (err < 0) - return err; - snd_ac97_write_cache(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], - AC97_CSR_ACMODE, 0x200); - } - } - /* do soundcard specific mixer setup */ - if (chip->mixer_init) { - snd_printdd ("calling chip->mixer_init(chip);\n"); - chip->mixer_init(chip); - } -#endif - - /* turn on amplifier */ - chip->amplifier_ctrl(chip, 1); - - return 0; -} - -/* - * RawMIDI interface - */ - -static void snd_cs46xx_midi_reset(struct snd_cs46xx *chip) -{ - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST); - udelay(100); - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); -} - -static int snd_cs46xx_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_cs46xx *chip = substream->rmidi->private_data; - - chip->active_ctrl(chip, 1); - spin_lock_irq(&chip->reg_lock); - chip->uartm |= CS46XX_MODE_INPUT; - chip->midcr |= MIDCR_RXE; - chip->midi_input = substream; - if (!(chip->uartm & CS46XX_MODE_OUTPUT)) { - snd_cs46xx_midi_reset(chip); - } else { - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_cs46xx_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_cs46xx *chip = substream->rmidi->private_data; - - spin_lock_irq(&chip->reg_lock); - chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE); - chip->midi_input = NULL; - if (!(chip->uartm & CS46XX_MODE_OUTPUT)) { - snd_cs46xx_midi_reset(chip); - } else { - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - chip->uartm &= ~CS46XX_MODE_INPUT; - spin_unlock_irq(&chip->reg_lock); - chip->active_ctrl(chip, -1); - return 0; -} - -static int snd_cs46xx_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct snd_cs46xx *chip = substream->rmidi->private_data; - - chip->active_ctrl(chip, 1); - - spin_lock_irq(&chip->reg_lock); - chip->uartm |= CS46XX_MODE_OUTPUT; - chip->midcr |= MIDCR_TXE; - chip->midi_output = substream; - if (!(chip->uartm & CS46XX_MODE_INPUT)) { - snd_cs46xx_midi_reset(chip); - } else { - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_cs46xx_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_cs46xx *chip = substream->rmidi->private_data; - - spin_lock_irq(&chip->reg_lock); - chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE); - chip->midi_output = NULL; - if (!(chip->uartm & CS46XX_MODE_INPUT)) { - snd_cs46xx_midi_reset(chip); - } else { - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - chip->uartm &= ~CS46XX_MODE_OUTPUT; - spin_unlock_irq(&chip->reg_lock); - chip->active_ctrl(chip, -1); - return 0; -} - -static void snd_cs46xx_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_cs46xx *chip = substream->rmidi->private_data; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (up) { - if ((chip->midcr & MIDCR_RIE) == 0) { - chip->midcr |= MIDCR_RIE; - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - } else { - if (chip->midcr & MIDCR_RIE) { - chip->midcr &= ~MIDCR_RIE; - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_cs46xx *chip = substream->rmidi->private_data; - unsigned char byte; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (up) { - if ((chip->midcr & MIDCR_TIE) == 0) { - chip->midcr |= MIDCR_TIE; - /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */ - while ((chip->midcr & MIDCR_TIE) && - (snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) { - if (snd_rawmidi_transmit(substream, &byte, 1) != 1) { - chip->midcr &= ~MIDCR_TIE; - } else { - snd_cs46xx_pokeBA0(chip, BA0_MIDWP, byte); - } - } - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - } else { - if (chip->midcr & MIDCR_TIE) { - chip->midcr &= ~MIDCR_TIE; - snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr); - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static struct snd_rawmidi_ops snd_cs46xx_midi_output = -{ - .open = snd_cs46xx_midi_output_open, - .close = snd_cs46xx_midi_output_close, - .trigger = snd_cs46xx_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_cs46xx_midi_input = -{ - .open = snd_cs46xx_midi_input_open, - .close = snd_cs46xx_midi_input_close, - .trigger = snd_cs46xx_midi_input_trigger, -}; - -int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi) -{ - struct snd_rawmidi *rmidi; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0) - return err; - strcpy(rmidi->name, "CS46XX"); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = chip; - chip->rmidi = rmidi; - if (rrawmidi) - *rrawmidi = NULL; - return 0; -} - - -/* - * gameport interface - */ - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - -static void snd_cs46xx_gameport_trigger(struct gameport *gameport) -{ - struct snd_cs46xx *chip = gameport_get_port_data(gameport); - - if (snd_BUG_ON(!chip)) - return; - snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); -} - -static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport) -{ - struct snd_cs46xx *chip = gameport_get_port_data(gameport); - - if (snd_BUG_ON(!chip)) - return 0; - return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io); -} - -static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) -{ - struct snd_cs46xx *chip = gameport_get_port_data(gameport); - unsigned js1, js2, jst; - - if (snd_BUG_ON(!chip)) - return 0; - - js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1); - js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2); - jst = snd_cs46xx_peekBA0(chip, BA0_JSPT); - - *buttons = (~jst >> 4) & 0x0F; - - axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; - axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; - axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; - axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; - - for(jst=0;jst<4;++jst) - if(axes[jst]==0xFFFF) axes[jst] = -1; - return 0; -} - -static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode) -{ - switch (mode) { - case GAMEPORT_MODE_COOKED: - return 0; - case GAMEPORT_MODE_RAW: - return 0; - default: - return -1; - } - return 0; -} - -int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) -{ - struct gameport *gp; - - chip->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n"); - return -ENOMEM; - } - - gameport_set_name(gp, "CS46xx Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); - gameport_set_dev_parent(gp, &chip->pci->dev); - gameport_set_port_data(gp, chip); - - gp->open = snd_cs46xx_gameport_open; - gp->read = snd_cs46xx_gameport_read; - gp->trigger = snd_cs46xx_gameport_trigger; - gp->cooked_read = snd_cs46xx_gameport_cooked_read; - - snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ? - snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); - - gameport_register_port(gp); - - return 0; -} - -static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) -{ - if (chip->gameport) { - gameport_unregister_port(chip->gameport); - chip->gameport = NULL; - } -} -#else -int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; } -static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { } -#endif /* CONFIG_GAMEPORT */ - -#ifdef CONFIG_PROC_FS -/* - * proc interface - */ - -static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct snd_cs46xx_region *region = entry->private_data; - - if (copy_to_user_fromio(buf, region->remap_addr + pos, count)) - return -EFAULT; - return count; -} - -static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { - .read = snd_cs46xx_io_read, -}; - -static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip) -{ - struct snd_info_entry *entry; - int idx; - - for (idx = 0; idx < 5; idx++) { - struct snd_cs46xx_region *region = &chip->region.idx[idx]; - if (! snd_card_proc_new(card, region->name, &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = chip; - entry->c.ops = &snd_cs46xx_proc_io_ops; - entry->size = region->size; - entry->mode = S_IFREG | S_IRUSR; - } - } -#ifdef CONFIG_SND_CS46XX_NEW_DSP - cs46xx_dsp_proc_init(card, chip); -#endif - return 0; -} - -static int snd_cs46xx_proc_done(struct snd_cs46xx *chip) -{ -#ifdef CONFIG_SND_CS46XX_NEW_DSP - cs46xx_dsp_proc_done(chip); -#endif - return 0; -} -#else /* !CONFIG_PROC_FS */ -#define snd_cs46xx_proc_init(card, chip) -#define snd_cs46xx_proc_done(chip) -#endif - -/* - * stop the h/w - */ -static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip) -{ - unsigned int tmp; - - tmp = snd_cs46xx_peek(chip, BA1_PFIE); - tmp &= ~0x0000f03f; - tmp |= 0x00000010; - snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt disable */ - - tmp = snd_cs46xx_peek(chip, BA1_CIE); - tmp &= ~0x0000003f; - tmp |= 0x00000011; - snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt disable */ - - /* - * Stop playback DMA. - */ - tmp = snd_cs46xx_peek(chip, BA1_PCTL); - snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff); - - /* - * Stop capture DMA. - */ - tmp = snd_cs46xx_peek(chip, BA1_CCTL); - snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000); - - /* - * Reset the processor. - */ - snd_cs46xx_reset(chip); - - snd_cs46xx_proc_stop(chip); - - /* - * Power down the PLL. - */ - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0); - - /* - * Turn off the Processor by turning off the software clock enable flag in - * the clock control register. - */ - tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); -} - - -static int snd_cs46xx_free(struct snd_cs46xx *chip) -{ - int idx; - - if (snd_BUG_ON(!chip)) - return -EINVAL; - - if (chip->active_ctrl) - chip->active_ctrl(chip, 1); - - snd_cs46xx_remove_gameport(chip); - - if (chip->amplifier_ctrl) - chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */ - - snd_cs46xx_proc_done(chip); - - if (chip->region.idx[0].resource) - snd_cs46xx_hw_stop(chip); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - if (chip->active_ctrl) - chip->active_ctrl(chip, -chip->amplifier); - - for (idx = 0; idx < 5; idx++) { - struct snd_cs46xx_region *region = &chip->region.idx[idx]; - if (region->remap_addr) - iounmap(region->remap_addr); - release_and_free_resource(region->resource); - } - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (chip->dsp_spos_instance) { - cs46xx_dsp_spos_destroy(chip); - chip->dsp_spos_instance = NULL; - } -#endif - -#ifdef CONFIG_PM - kfree(chip->saved_regs); -#endif - - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_cs46xx_dev_free(struct snd_device *device) -{ - struct snd_cs46xx *chip = device->device_data; - return snd_cs46xx_free(chip); -} - -/* - * initialize chip - */ -static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) -{ - int timeout; - - /* - * First, blast the clock control register to zero so that the PLL starts - * out in a known state, and blast the master serial port control register - * to zero so that the serial ports also start out in a known state. - */ - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0); - snd_cs46xx_pokeBA0(chip, BA0_SERMC1, 0); - - /* - * If we are in AC97 mode, then we must set the part to a host controlled - * AC-link. Otherwise, we won't be able to bring up the link. - */ -#ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0 | - SERACC_TWO_CODECS); /* 2.00 dual codecs */ - /* snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0); */ /* 2.00 codec */ -#else - snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_1_03); /* 1.03 codec */ -#endif - - /* - * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97 - * spec) and then drive it high. This is done for non AC97 modes since - * there might be logic external to the CS461x that uses the ARST# line - * for a reset. - */ - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, 0); -#ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, 0); -#endif - udelay(50); - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_RSTN); -#ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_RSTN); -#endif - - /* - * The first thing we do here is to enable sync generation. As soon - * as we start receiving bit clock, we'll start producing the SYNC - * signal. - */ - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN); -#ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_ESYN | ACCTL_RSTN); -#endif - - /* - * Now wait for a short while to allow the AC97 part to start - * generating bit clock (so we don't try to start the PLL without an - * input clock). - */ - mdelay(10); - - /* - * Set the serial port timing configuration, so that - * the clock control circuit gets its clock from the correct place. - */ - snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97); - - /* - * Write the selected clock control setup to the hardware. Do not turn on - * SWCE yet (if requested), so that the devices clocked by the output of - * PLL are not clocked until the PLL is stable. - */ - snd_cs46xx_pokeBA0(chip, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ); - snd_cs46xx_pokeBA0(chip, BA0_PLLM, 0x3a); - snd_cs46xx_pokeBA0(chip, BA0_CLKCR2, CLKCR2_PDIVS_8); - - /* - * Power up the PLL. - */ - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP); - - /* - * Wait until the PLL has stabilized. - */ - msleep(100); - - /* - * Turn on clocking of the core so that we can setup the serial ports. - */ - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE); - - /* - * Enable FIFO Host Bypass - */ - snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP); - - /* - * Fill the serial port FIFOs with silence. - */ - snd_cs46xx_clear_serial_FIFOs(chip); - - /* - * Set the serial port FIFO pointer to the first sample in the FIFO. - */ - /* snd_cs46xx_pokeBA0(chip, BA0_SERBSP, 0); */ - - /* - * Write the serial port configuration to the part. The master - * enable bit is not set until all other values have been written. - */ - snd_cs46xx_pokeBA0(chip, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN); - snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN); - snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE); - - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN); - snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0); - snd_cs46xx_pokeBA0(chip, BA0_SERC4, 0); - snd_cs46xx_pokeBA0(chip, BA0_SERC5, 0); - snd_cs46xx_pokeBA0(chip, BA0_SERC6, 1); -#endif - - mdelay(5); - - - /* - * Wait for the codec ready signal from the AC97 codec. - */ - timeout = 150; - while (timeout-- > 0) { - /* - * Read the AC97 status register to see if we've seen a CODEC READY - * signal from the AC97 codec. - */ - if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY) - goto ok1; - msleep(10); - } - - - snd_printk(KERN_ERR "create - never read codec ready from AC'97\n"); - snd_printk(KERN_ERR "it is not probably bug, try to use CS4236 driver\n"); - return -EIO; - ok1: -#ifdef CONFIG_SND_CS46XX_NEW_DSP - { - int count; - for (count = 0; count < 150; count++) { - /* First, we want to wait for a short time. */ - udelay(25); - - if (snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY) - break; - } - - /* - * Make sure CODEC is READY. - */ - if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)) - snd_printdd("cs46xx: never read card ready from secondary AC'97\n"); - } -#endif - - /* - * Assert the vaid frame signal so that we can start sending commands - * to the AC97 codec. - */ - snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); -#ifdef CONFIG_SND_CS46XX_NEW_DSP - snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN); -#endif - - - /* - * Wait until we've sampled input slots 3 and 4 as valid, meaning that - * the codec is pumping ADC data across the AC-link. - */ - timeout = 150; - while (timeout-- > 0) { - /* - * Read the input slot valid register and see if input slots 3 and - * 4 are valid yet. - */ - if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) - goto ok2; - msleep(10); - } - -#ifndef CONFIG_SND_CS46XX_NEW_DSP - snd_printk(KERN_ERR "create - never read ISV3 & ISV4 from AC'97\n"); - return -EIO; -#else - /* This may happen on a cold boot with a Terratec SiXPack 5.1. - Reloading the driver may help, if there's other soundcards - with the same problem I would like to know. (Benny) */ - - snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n"); - snd_printk(KERN_ERR " Try reloading the ALSA driver, if you find something\n"); - snd_printk(KERN_ERR " broken or not working on your soundcard upon\n"); - snd_printk(KERN_ERR " this message please report to alsa-devel@alsa-project.org\n"); - - return -EIO; -#endif - ok2: - - /* - * Now, assert valid frame and the slot 3 and 4 valid bits. This will - * commense the transfer of digital audio data to the AC97 codec. - */ - - snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4); - - - /* - * Power down the DAC and ADC. We will power them up (if) when we need - * them. - */ - /* snd_cs46xx_pokeBA0(chip, BA0_AC97_POWERDOWN, 0x300); */ - - /* - * Turn off the Processor by turning off the software clock enable flag in - * the clock control register. - */ - /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */ - /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */ - - return 0; -} - -/* - * start and load DSP - */ - -static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip) -{ - unsigned int tmp; - - snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM); - - tmp = snd_cs46xx_peek(chip, BA1_PFIE); - tmp &= ~0x0000f03f; - snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */ - - tmp = snd_cs46xx_peek(chip, BA1_CIE); - tmp &= ~0x0000003f; - tmp |= 0x00000001; - snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */ -} - -int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) -{ - unsigned int tmp; - /* - * Reset the processor. - */ - snd_cs46xx_reset(chip); - /* - * Download the image to the processor. - */ -#ifdef CONFIG_SND_CS46XX_NEW_DSP -#if 0 - if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) { - snd_printk(KERN_ERR "image download error\n"); - return -EIO; - } -#endif - - if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) { - snd_printk(KERN_ERR "image download error [cwc4630]\n"); - return -EIO; - } - - if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) { - snd_printk(KERN_ERR "image download error [cwcasync]\n"); - return -EIO; - } - - if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) { - snd_printk(KERN_ERR "image download error [cwcsnoop]\n"); - return -EIO; - } - - if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) { - snd_printk(KERN_ERR "image download error [cwcbinhack]\n"); - return -EIO; - } - - if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) { - snd_printk(KERN_ERR "image download error [cwcdma]\n"); - return -EIO; - } - - if (cs46xx_dsp_scb_and_task_init(chip) < 0) - return -EIO; -#else - /* old image */ - if (snd_cs46xx_download_image(chip) < 0) { - snd_printk(KERN_ERR "image download error\n"); - return -EIO; - } - - /* - * Stop playback DMA. - */ - tmp = snd_cs46xx_peek(chip, BA1_PCTL); - chip->play_ctl = tmp & 0xffff0000; - snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff); -#endif - - /* - * Stop capture DMA. - */ - tmp = snd_cs46xx_peek(chip, BA1_CCTL); - chip->capt.ctl = tmp & 0x0000ffff; - snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000); - - mdelay(5); - - snd_cs46xx_set_play_sample_rate(chip, 8000); - snd_cs46xx_set_capture_sample_rate(chip, 8000); - - snd_cs46xx_proc_start(chip); - - cs46xx_enable_stream_irqs(chip); - -#ifndef CONFIG_SND_CS46XX_NEW_DSP - /* set the attenuation to 0dB */ - snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000); - snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000); -#endif - - return 0; -} - - -/* - * AMP control - null AMP - */ - -static void amp_none(struct snd_cs46xx *chip, int change) -{ -} - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip) -{ - - u32 idx, valid_slots,tmp,powerdown = 0; - u16 modem_power,pin_config,logic_type; - - snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n"); - - /* - * See if the devices are powered down. If so, we must power them up first - * or they will not respond. - */ - tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1); - - if (!(tmp & CLKCR1_SWCE)) { - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE); - powerdown = 1; - } - - /* - * Clear PRA. The Bonzo chip will be used for GPIO not for modem - * stuff. - */ - if(chip->nr_ac97_codecs != 2) { - snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n"); - return -EINVAL; - } - - modem_power = snd_cs46xx_codec_read (chip, - AC97_EXTENDED_MSTATUS, - CS46XX_SECONDARY_CODEC_INDEX); - modem_power &=0xFEFF; - - snd_cs46xx_codec_write(chip, - AC97_EXTENDED_MSTATUS, modem_power, - CS46XX_SECONDARY_CODEC_INDEX); - - /* - * Set GPIO pin's 7 and 8 so that they are configured for output. - */ - pin_config = snd_cs46xx_codec_read (chip, - AC97_GPIO_CFG, - CS46XX_SECONDARY_CODEC_INDEX); - pin_config &=0x27F; - - snd_cs46xx_codec_write(chip, - AC97_GPIO_CFG, pin_config, - CS46XX_SECONDARY_CODEC_INDEX); - - /* - * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic. - */ - - logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY, - CS46XX_SECONDARY_CODEC_INDEX); - logic_type &=0x27F; - - snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type, - CS46XX_SECONDARY_CODEC_INDEX); - - valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV); - valid_slots |= 0x200; - snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots); - - if ( cs46xx_wait_for_fifo(chip,1) ) { - snd_printdd("FIFO is busy\n"); - - return -EINVAL; - } - - /* - * Fill slots 12 with the correct value for the GPIO pins. - */ - for(idx = 0x90; idx <= 0x9F; idx++) { - /* - * Initialize the fifo so that bits 7 and 8 are on. - * - * Remember that the GPIO pins in bonzo are shifted by 4 bits to - * the left. 0x1800 corresponds to bits 7 and 8. - */ - snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800); - - /* - * Wait for command to complete - */ - if ( cs46xx_wait_for_fifo(chip,200) ) { - snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx); - - return -EINVAL; - } - - /* - * Write the serial port FIFO index. - */ - snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx); - - /* - * Tell the serial port to load the new value into the FIFO location. - */ - snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC); - } - - /* wait for last command to complete */ - cs46xx_wait_for_fifo(chip,200); - - /* - * Now, if we powered up the devices, then power them back down again. - * This is kinda ugly, but should never happen. - */ - if (powerdown) - snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); - - return 0; -} -#endif - -/* - * Crystal EAPD mode - */ - -static void amp_voyetra(struct snd_cs46xx *chip, int change) -{ - /* Manage the EAPD bit on the Crystal 4297 - and the Analog AD1885 */ - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - int old = chip->amplifier; -#endif - int oval, val; - - chip->amplifier += change; - oval = snd_cs46xx_codec_read(chip, AC97_POWERDOWN, - CS46XX_PRIMARY_CODEC_INDEX); - val = oval; - if (chip->amplifier) { - /* Turn the EAPD amp on */ - val |= 0x8000; - } else { - /* Turn the EAPD amp off */ - val &= ~0x8000; - } - if (val != oval) { - snd_cs46xx_codec_write(chip, AC97_POWERDOWN, val, - CS46XX_PRIMARY_CODEC_INDEX); - if (chip->eapd_switch) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->eapd_switch->id); - } - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (chip->amplifier && !old) { - voyetra_setup_eapd_slot(chip); - } -#endif -} - -static void hercules_init(struct snd_cs46xx *chip) -{ - /* default: AMP off, and SPDIF input optical */ - snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0); - snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0); -} - - -/* - * Game Theatre XP card - EGPIO[2] is used to enable the external amp. - */ -static void amp_hercules(struct snd_cs46xx *chip, int change) -{ - int old = chip->amplifier; - int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR); - int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR); - - chip->amplifier += change; - if (chip->amplifier && !old) { - snd_printdd ("Hercules amplifier ON\n"); - - snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, - EGPIODR_GPOE2 | val1); /* enable EGPIO2 output */ - snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, - EGPIOPTR_GPPT2 | val2); /* open-drain on output */ - } else if (old && !chip->amplifier) { - snd_printdd ("Hercules amplifier OFF\n"); - snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE2); /* disable */ - snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */ - } -} - -static void voyetra_mixer_init (struct snd_cs46xx *chip) -{ - snd_printdd ("initializing Voyetra mixer\n"); - - /* Enable SPDIF out */ - snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0); - snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0); -} - -static void hercules_mixer_init (struct snd_cs46xx *chip) -{ -#ifdef CONFIG_SND_CS46XX_NEW_DSP - unsigned int idx; - int err; - struct snd_card *card = chip->card; -#endif - - /* set EGPIO to default */ - hercules_init(chip); - - snd_printdd ("initializing Hercules mixer\n"); - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - if (chip->in_suspend) - return; - - for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) { - struct snd_kcontrol *kctl; - - kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip); - if ((err = snd_ctl_add(card, kctl)) < 0) { - printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err); - break; - } - } -#endif -} - - -#if 0 -/* - * Untested - */ - -static void amp_voyetra_4294(struct snd_cs46xx *chip, int change) -{ - chip->amplifier += change; - - if (chip->amplifier) { - /* Switch the GPIO pins 7 and 8 to open drain */ - snd_cs46xx_codec_write(chip, 0x4C, - snd_cs46xx_codec_read(chip, 0x4C) & 0xFE7F); - snd_cs46xx_codec_write(chip, 0x4E, - snd_cs46xx_codec_read(chip, 0x4E) | 0x0180); - /* Now wake the AMP (this might be backwards) */ - snd_cs46xx_codec_write(chip, 0x54, - snd_cs46xx_codec_read(chip, 0x54) & ~0x0180); - } else { - snd_cs46xx_codec_write(chip, 0x54, - snd_cs46xx_codec_read(chip, 0x54) | 0x0180); - } -} -#endif - - -/* - * Handle the CLKRUN on a thinkpad. We must disable CLKRUN support - * whenever we need to beat on the chip. - * - * The original idea and code for this hack comes from David Kaiser at - * Linuxcare. Perhaps one day Crystal will document their chips well - * enough to make them useful. - */ - -static void clkrun_hack(struct snd_cs46xx *chip, int change) -{ - u16 control, nval; - - if (!chip->acpi_port) - return; - - chip->amplifier += change; - - /* Read ACPI port */ - nval = control = inw(chip->acpi_port + 0x10); - - /* Flip CLKRUN off while running */ - if (! chip->amplifier) - nval |= 0x2000; - else - nval &= ~0x2000; - if (nval != control) - outw(nval, chip->acpi_port + 0x10); -} - - -/* - * detect intel piix4 - */ -static void clkrun_init(struct snd_cs46xx *chip) -{ - struct pci_dev *pdev; - u8 pp; - - chip->acpi_port = 0; - - pdev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, NULL); - if (pdev == NULL) - return; /* Not a thinkpad thats for sure */ - - /* Find the control port */ - pci_read_config_byte(pdev, 0x41, &pp); - chip->acpi_port = pp << 8; - pci_dev_put(pdev); -} - - -/* - * Card subid table - */ - -struct cs_card_type -{ - u16 vendor; - u16 id; - char *name; - void (*init)(struct snd_cs46xx *); - void (*amp)(struct snd_cs46xx *, int); - void (*active)(struct snd_cs46xx *, int); - void (*mixer_init)(struct snd_cs46xx *); -}; - -static struct cs_card_type __devinitdata cards[] = { - { - .vendor = 0x1489, - .id = 0x7001, - .name = "Genius Soundmaker 128 value", - /* nothing special */ - }, - { - .vendor = 0x5053, - .id = 0x3357, - .name = "Voyetra", - .amp = amp_voyetra, - .mixer_init = voyetra_mixer_init, - }, - { - .vendor = 0x1071, - .id = 0x6003, - .name = "Mitac MI6020/21", - .amp = amp_voyetra, - }, - /* Hercules Game Theatre XP */ - { - .vendor = 0x14af, /* Guillemot Corporation */ - .id = 0x0050, - .name = "Hercules Game Theatre XP", - .amp = amp_hercules, - .mixer_init = hercules_mixer_init, - }, - { - .vendor = 0x1681, - .id = 0x0050, - .name = "Hercules Game Theatre XP", - .amp = amp_hercules, - .mixer_init = hercules_mixer_init, - }, - { - .vendor = 0x1681, - .id = 0x0051, - .name = "Hercules Game Theatre XP", - .amp = amp_hercules, - .mixer_init = hercules_mixer_init, - - }, - { - .vendor = 0x1681, - .id = 0x0052, - .name = "Hercules Game Theatre XP", - .amp = amp_hercules, - .mixer_init = hercules_mixer_init, - }, - { - .vendor = 0x1681, - .id = 0x0053, - .name = "Hercules Game Theatre XP", - .amp = amp_hercules, - .mixer_init = hercules_mixer_init, - }, - { - .vendor = 0x1681, - .id = 0x0054, - .name = "Hercules Game Theatre XP", - .amp = amp_hercules, - .mixer_init = hercules_mixer_init, - }, - /* Herculess Fortissimo */ - { - .vendor = 0x1681, - .id = 0xa010, - .name = "Hercules Gamesurround Fortissimo II", - }, - { - .vendor = 0x1681, - .id = 0xa011, - .name = "Hercules Gamesurround Fortissimo III 7.1", - }, - /* Teratec */ - { - .vendor = 0x153b, - .id = 0x112e, - .name = "Terratec DMX XFire 1024", - }, - { - .vendor = 0x153b, - .id = 0x1136, - .name = "Terratec SiXPack 5.1", - }, - /* Not sure if the 570 needs the clkrun hack */ - { - .vendor = PCI_VENDOR_ID_IBM, - .id = 0x0132, - .name = "Thinkpad 570", - .init = clkrun_init, - .active = clkrun_hack, - }, - { - .vendor = PCI_VENDOR_ID_IBM, - .id = 0x0153, - .name = "Thinkpad 600X/A20/T20", - .init = clkrun_init, - .active = clkrun_hack, - }, - { - .vendor = PCI_VENDOR_ID_IBM, - .id = 0x1010, - .name = "Thinkpad 600E (unsupported)", - }, - {} /* terminator */ -}; - - -/* - * APM support - */ -#ifdef CONFIG_PM -static unsigned int saved_regs[] = { - BA0_ACOSV, - /*BA0_ASER_FADDR,*/ - BA0_ASER_MASTER, - BA1_PVOL, - BA1_CVOL, -}; - -int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_cs46xx *chip = card->private_data; - int i, amp_saved; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->in_suspend = 1; - snd_pcm_suspend_all(chip->pcm); - // chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL); - // chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE); - - snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); - snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); - - /* save some registers */ - for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - chip->saved_regs[i] = snd_cs46xx_peekBA0(chip, saved_regs[i]); - - amp_saved = chip->amplifier; - /* turn off amp */ - chip->amplifier_ctrl(chip, -chip->amplifier); - snd_cs46xx_hw_stop(chip); - /* disable CLKRUN */ - chip->active_ctrl(chip, -chip->amplifier); - chip->amplifier = amp_saved; /* restore the status */ - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -int snd_cs46xx_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_cs46xx *chip = card->private_data; - int amp_saved; -#ifdef CONFIG_SND_CS46XX_NEW_DSP - int i; -#endif - unsigned int tmp; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cs46xx: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - amp_saved = chip->amplifier; - chip->amplifier = 0; - chip->active_ctrl(chip, 1); /* force to on */ - - snd_cs46xx_chip_init(chip); - - snd_cs46xx_reset(chip); -#ifdef CONFIG_SND_CS46XX_NEW_DSP - cs46xx_dsp_resume(chip); - /* restore some registers */ - for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - snd_cs46xx_pokeBA0(chip, saved_regs[i], chip->saved_regs[i]); -#else - snd_cs46xx_download_image(chip); -#endif - -#if 0 - snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, - chip->ac97_general_purpose); - snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL, - chip->ac97_powerdown); - mdelay(10); - snd_cs46xx_codec_write(chip, BA0_AC97_POWERDOWN, - chip->ac97_powerdown); - mdelay(5); -#endif - - snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); - snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); - - /* - * Stop capture DMA. - */ - tmp = snd_cs46xx_peek(chip, BA1_CCTL); - chip->capt.ctl = tmp & 0x0000ffff; - snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000); - - mdelay(5); - - /* reset playback/capture */ - snd_cs46xx_set_play_sample_rate(chip, 8000); - snd_cs46xx_set_capture_sample_rate(chip, 8000); - snd_cs46xx_proc_start(chip); - - cs46xx_enable_stream_irqs(chip); - - if (amp_saved) - chip->amplifier_ctrl(chip, 1); /* turn amp on */ - else - chip->active_ctrl(chip, -1); /* disable CLKRUN */ - chip->amplifier = amp_saved; - chip->in_suspend = 0; - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - - -/* - */ - -int __devinit snd_cs46xx_create(struct snd_card *card, - struct pci_dev * pci, - int external_amp, int thinkpad, - struct snd_cs46xx ** rchip) -{ - struct snd_cs46xx *chip; - int err, idx; - struct snd_cs46xx_region *region; - struct cs_card_type *cp; - u16 ss_card, ss_vendor; - static struct snd_device_ops ops = { - .dev_free = snd_cs46xx_dev_free, - }; - - *rchip = NULL; - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&chip->reg_lock); -#ifdef CONFIG_SND_CS46XX_NEW_DSP - mutex_init(&chip->spos_mutex); -#endif - chip->card = card; - chip->pci = pci; - chip->irq = -1; - chip->ba0_addr = pci_resource_start(pci, 0); - chip->ba1_addr = pci_resource_start(pci, 1); - if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 || - chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) { - snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", - chip->ba0_addr, chip->ba1_addr); - snd_cs46xx_free(chip); - return -ENOMEM; - } - - region = &chip->region.name.ba0; - strcpy(region->name, "CS46xx_BA0"); - region->base = chip->ba0_addr; - region->size = CS46XX_BA0_SIZE; - - region = &chip->region.name.data0; - strcpy(region->name, "CS46xx_BA1_data0"); - region->base = chip->ba1_addr + BA1_SP_DMEM0; - region->size = CS46XX_BA1_DATA0_SIZE; - - region = &chip->region.name.data1; - strcpy(region->name, "CS46xx_BA1_data1"); - region->base = chip->ba1_addr + BA1_SP_DMEM1; - region->size = CS46XX_BA1_DATA1_SIZE; - - region = &chip->region.name.pmem; - strcpy(region->name, "CS46xx_BA1_pmem"); - region->base = chip->ba1_addr + BA1_SP_PMEM; - region->size = CS46XX_BA1_PRG_SIZE; - - region = &chip->region.name.reg; - strcpy(region->name, "CS46xx_BA1_reg"); - region->base = chip->ba1_addr + BA1_SP_REG; - region->size = CS46XX_BA1_REG_SIZE; - - /* set up amp and clkrun hack */ - pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor); - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card); - - for (cp = &cards[0]; cp->name; cp++) { - if (cp->vendor == ss_vendor && cp->id == ss_card) { - snd_printdd ("hack for %s enabled\n", cp->name); - - chip->amplifier_ctrl = cp->amp; - chip->active_ctrl = cp->active; - chip->mixer_init = cp->mixer_init; - - if (cp->init) - cp->init(chip); - break; - } - } - - if (external_amp) { - snd_printk(KERN_INFO "Crystal EAPD support forced on.\n"); - chip->amplifier_ctrl = amp_voyetra; - } - - if (thinkpad) { - snd_printk(KERN_INFO "Activating CLKRUN hack for Thinkpad.\n"); - chip->active_ctrl = clkrun_hack; - clkrun_init(chip); - } - - if (chip->amplifier_ctrl == NULL) - chip->amplifier_ctrl = amp_none; - if (chip->active_ctrl == NULL) - chip->active_ctrl = amp_none; - - chip->active_ctrl(chip, 1); /* enable CLKRUN */ - - pci_set_master(pci); - - for (idx = 0; idx < 5; idx++) { - region = &chip->region.idx[idx]; - if ((region->resource = request_mem_region(region->base, region->size, - region->name)) == NULL) { - snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n", - region->base, region->base + region->size - 1); - snd_cs46xx_free(chip); - return -EBUSY; - } - region->remap_addr = ioremap_nocache(region->base, region->size); - if (region->remap_addr == NULL) { - snd_printk(KERN_ERR "%s ioremap problem\n", region->name); - snd_cs46xx_free(chip); - return -ENOMEM; - } - } - - if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_cs46xx_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - -#ifdef CONFIG_SND_CS46XX_NEW_DSP - chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip); - if (chip->dsp_spos_instance == NULL) { - snd_cs46xx_free(chip); - return -ENOMEM; - } -#endif - - err = snd_cs46xx_chip_init(chip); - if (err < 0) { - snd_cs46xx_free(chip); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_cs46xx_free(chip); - return err; - } - - snd_cs46xx_proc_init(card, chip); - -#ifdef CONFIG_PM - chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) * - ARRAY_SIZE(saved_regs), GFP_KERNEL); - if (!chip->saved_regs) { - snd_cs46xx_free(chip); - return -ENOMEM; - } -#endif - - chip->active_ctrl(chip, -1); /* disable CLKRUN */ - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.h b/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.h deleted file mode 100644 index b5189495..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/cs46xx_lib.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -#ifndef __CS46XX_LIB_H__ -#define __CS46XX_LIB_H__ - -/* - * constants - */ - -#define CS46XX_BA0_SIZE 0x1000 -#define CS46XX_BA1_DATA0_SIZE 0x3000 -#define CS46XX_BA1_DATA1_SIZE 0x3800 -#define CS46XX_BA1_PRG_SIZE 0x7000 -#define CS46XX_BA1_REG_SIZE 0x0100 - - - -#ifdef CONFIG_SND_CS46XX_NEW_DSP -#define CS46XX_MIN_PERIOD_SIZE 64 -#define CS46XX_MAX_PERIOD_SIZE 1024*1024 -#else -#define CS46XX_MIN_PERIOD_SIZE 2048 -#define CS46XX_MAX_PERIOD_SIZE 2048 -#endif - -#define CS46XX_FRAGS 2 -/* #define CS46XX_BUFFER_SIZE CS46XX_MAX_PERIOD_SIZE * CS46XX_FRAGS */ - -#define SCB_NO_PARENT 0 -#define SCB_ON_PARENT_NEXT_SCB 1 -#define SCB_ON_PARENT_SUBLIST_SCB 2 - -/* 3*1024 parameter, 3.5*1024 sample, 2*3.5*1024 code */ -#define BA1_DWORD_SIZE (13 * 1024 + 512) -#define BA1_MEMORY_COUNT 3 - -/* - * common I/O routines - */ - -static inline void snd_cs46xx_poke(struct snd_cs46xx *chip, unsigned long reg, unsigned int val) -{ - unsigned int bank = reg >> 16; - unsigned int offset = reg & 0xffff; - - /* - if (bank == 0) - printk(KERN_DEBUG "snd_cs46xx_poke: %04X - %08X\n", - reg >> 2,val); - */ - writel(val, chip->region.idx[bank+1].remap_addr + offset); -} - -static inline unsigned int snd_cs46xx_peek(struct snd_cs46xx *chip, unsigned long reg) -{ - unsigned int bank = reg >> 16; - unsigned int offset = reg & 0xffff; - return readl(chip->region.idx[bank+1].remap_addr + offset); -} - -static inline void snd_cs46xx_pokeBA0(struct snd_cs46xx *chip, unsigned long offset, unsigned int val) -{ - writel(val, chip->region.name.ba0.remap_addr + offset); -} - -static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned long offset) -{ - return readl(chip->region.name.ba0.remap_addr + offset); -} - -struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip); -void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip); -int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module); -#ifdef CONFIG_PM -int cs46xx_dsp_resume(struct snd_cs46xx * chip); -#endif -struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, - int symbol_type); -#ifdef CONFIG_PROC_FS -int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip); -int cs46xx_dsp_proc_done (struct snd_cs46xx *chip); -#else -#define cs46xx_dsp_proc_init(card, chip) -#define cs46xx_dsp_proc_done(chip) -#endif -int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip); -int snd_cs46xx_download (struct snd_cs46xx *chip, u32 *src, unsigned long offset, - unsigned long len); -int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip, unsigned long offset, unsigned long len); -int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip); -int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip); -int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip); -int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip); -int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip); -int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip); -int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip); -int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip); -int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip); -int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data); -struct dsp_scb_descriptor * cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, - u32 * scb_data, u32 dest); -#ifdef CONFIG_PROC_FS -void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb); -void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip, - struct dsp_scb_descriptor * scb); -#else -#define cs46xx_dsp_proc_free_scb_desc(scb) -#define cs46xx_dsp_proc_register_scb_desc(chip, scb) -#endif -struct dsp_scb_descriptor * cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip); -struct dsp_scb_descriptor * -cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip, - char * codec_name, u16 channel_disp, u16 fifo_addr, - u16 child_scb_addr, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); -struct dsp_scb_descriptor * -cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name, - u16 channel_disp, u16 fifo_addr, - u16 sample_buffer_addr, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); -void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, - struct dsp_scb_descriptor * scb); -struct dsp_scb_descriptor * -cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name, - u16 channel_disp, u16 fifo_addr, - u16 sample_buffer_addr, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); -struct dsp_scb_descriptor * -cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name, - int sample_rate, u16 src_buffer_addr, - u16 src_delay_buffer_addr, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type, int pass_through); -struct dsp_scb_descriptor * -cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name, - u16 mix_buffer_addr, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); - -struct dsp_scb_descriptor * -cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip, char * scb_name, - u16 vari_buffer_addr0, u16 vari_buffer_addr1, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); -struct dsp_scb_descriptor * -cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name, - u32 dest, u16 hfg_scb_address, u16 asynch_buffer_address, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); -struct dsp_scb_descriptor * -cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); -struct dsp_scb_descriptor * -cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name, - u16 mix_buffer_addr, u16 writeback_spb, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); -struct dsp_scb_descriptor * -cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name, - u32 dest, u16 snoop_buffer_address, - struct dsp_scb_descriptor * snoop_scb, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type); -struct dsp_pcm_channel_descriptor * -cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, u32 sample_rate, - void * private_data, u32 hw_dma_addr, - int pcm_channel_id); -void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, - struct dsp_pcm_channel_descriptor * pcm_channel); -int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip, - struct dsp_pcm_channel_descriptor * pcm_channel); -int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip, - struct dsp_pcm_channel_descriptor * pcm_channel); -struct dsp_scb_descriptor * -cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source, - u16 addr, char * scb_name); -int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src); -int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src); -int cs46xx_iec958_pre_open (struct snd_cs46xx *chip); -int cs46xx_iec958_post_close (struct snd_cs46xx *chip); -int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip, - struct dsp_pcm_channel_descriptor * pcm_channel, - int period_size); -int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip, int period_size); -int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right); -int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right); -#endif /* __CS46XX_LIB_H__ */ diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.c b/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.c deleted file mode 100644 index e3772871..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.c +++ /dev/null @@ -1,2017 +0,0 @@ -/* - * 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 - * - */ - -/* - * 2002-07 Benny Sjostrand benny@hostmobility.com - */ - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "cs46xx_lib.h" -#include "dsp_spos.h" - -static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, - struct dsp_scb_descriptor * fg_entry); - -static enum wide_opcode wide_opcodes[] = { - WIDE_FOR_BEGIN_LOOP, - WIDE_FOR_BEGIN_LOOP2, - WIDE_COND_GOTO_ADDR, - WIDE_COND_GOTO_CALL, - WIDE_TBEQ_COND_GOTO_ADDR, - WIDE_TBEQ_COND_CALL_ADDR, - WIDE_TBEQ_NCOND_GOTO_ADDR, - WIDE_TBEQ_NCOND_CALL_ADDR, - WIDE_TBEQ_COND_GOTO1_ADDR, - WIDE_TBEQ_COND_CALL1_ADDR, - WIDE_TBEQ_NCOND_GOTOI_ADDR, - WIDE_TBEQ_NCOND_CALL1_ADDR -}; - -static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 size, - u32 overlay_begin_address) -{ - unsigned int i = 0, j, nreallocated = 0; - u32 hival,loval,address; - u32 mop_operands,mop_type,wide_op; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (snd_BUG_ON(size %2)) - return -EINVAL; - - while (i < size) { - loval = data[i++]; - hival = data[i++]; - - if (ins->code.offset > 0) { - mop_operands = (hival >> 6) & 0x03fff; - mop_type = mop_operands >> 10; - - /* check for wide type instruction */ - if (mop_type == 0 && - (mop_operands & WIDE_LADD_INSTR_MASK) == 0 && - (mop_operands & WIDE_INSTR_MASK) != 0) { - wide_op = loval & 0x7f; - for (j = 0;j < ARRAY_SIZE(wide_opcodes); ++j) { - if (wide_opcodes[j] == wide_op) { - /* need to reallocate instruction */ - address = (hival & 0x00FFF) << 5; - address |= loval >> 15; - - snd_printdd("handle_wideop[1]: %05x:%05x addr %04x\n",hival,loval,address); - - if ( !(address & 0x8000) ) { - address += (ins->code.offset / 2) - overlay_begin_address; - } else { - snd_printdd("handle_wideop[1]: ROM symbol not reallocated\n"); - } - - hival &= 0xFF000; - loval &= 0x07FFF; - - hival |= ( (address >> 5) & 0x00FFF); - loval |= ( (address << 15) & 0xF8000); - - address = (hival & 0x00FFF) << 5; - address |= loval >> 15; - - snd_printdd("handle_wideop:[2] %05x:%05x addr %04x\n",hival,loval,address); - nreallocated ++; - } /* wide_opcodes[j] == wide_op */ - } /* for */ - } /* mod_type == 0 ... */ - } /* ins->code.offset > 0 */ - - ins->code.data[ins->code.size++] = loval; - ins->code.data[ins->code.size++] = hival; - } - - snd_printdd("dsp_spos: %d instructions reallocated\n",nreallocated); - return nreallocated; -} - -static struct dsp_segment_desc * get_segment_desc (struct dsp_module_desc * module, int seg_type) -{ - int i; - for (i = 0;i < module->nsegments; ++i) { - if (module->segments[i].segment_type == seg_type) { - return (module->segments + i); - } - } - - return NULL; -}; - -static int find_free_symbol_index (struct dsp_spos_instance * ins) -{ - int index = ins->symbol_table.nsymbols,i; - - for (i = ins->symbol_table.highest_frag_index; i < ins->symbol_table.nsymbols; ++i) { - if (ins->symbol_table.symbols[i].deleted) { - index = i; - break; - } - } - - return index; -} - -static int add_symbols (struct snd_cs46xx * chip, struct dsp_module_desc * module) -{ - int i; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (module->symbol_table.nsymbols > 0) { - if (!strcmp(module->symbol_table.symbols[0].symbol_name, "OVERLAYBEGINADDRESS") && - module->symbol_table.symbols[0].symbol_type == SYMBOL_CONSTANT ) { - module->overlay_begin_address = module->symbol_table.symbols[0].address; - } - } - - for (i = 0;i < module->symbol_table.nsymbols; ++i) { - if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) { - snd_printk(KERN_ERR "dsp_spos: symbol table is full\n"); - return -ENOMEM; - } - - - if (cs46xx_dsp_lookup_symbol(chip, - module->symbol_table.symbols[i].symbol_name, - module->symbol_table.symbols[i].symbol_type) == NULL) { - - ins->symbol_table.symbols[ins->symbol_table.nsymbols] = module->symbol_table.symbols[i]; - ins->symbol_table.symbols[ins->symbol_table.nsymbols].address += ((ins->code.offset / 2) - module->overlay_begin_address); - ins->symbol_table.symbols[ins->symbol_table.nsymbols].module = module; - ins->symbol_table.symbols[ins->symbol_table.nsymbols].deleted = 0; - - if (ins->symbol_table.nsymbols > ins->symbol_table.highest_frag_index) - ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols; - - ins->symbol_table.nsymbols++; - } else { - /* if (0) printk ("dsp_spos: symbol <%s> duplicated, probably nothing wrong with that (Cirrus?)\n", - module->symbol_table.symbols[i].symbol_name); */ - } - } - - return 0; -} - -static struct dsp_symbol_entry * -add_symbol (struct snd_cs46xx * chip, char * symbol_name, u32 address, int type) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_symbol_entry * symbol = NULL; - int index; - - if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) { - snd_printk(KERN_ERR "dsp_spos: symbol table is full\n"); - return NULL; - } - - if (cs46xx_dsp_lookup_symbol(chip, - symbol_name, - type) != NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol <%s> duplicated\n", symbol_name); - return NULL; - } - - index = find_free_symbol_index (ins); - - strcpy (ins->symbol_table.symbols[index].symbol_name, symbol_name); - ins->symbol_table.symbols[index].address = address; - ins->symbol_table.symbols[index].symbol_type = type; - ins->symbol_table.symbols[index].module = NULL; - ins->symbol_table.symbols[index].deleted = 0; - symbol = (ins->symbol_table.symbols + index); - - if (index > ins->symbol_table.highest_frag_index) - ins->symbol_table.highest_frag_index = index; - - if (index == ins->symbol_table.nsymbols) - ins->symbol_table.nsymbols++; /* no frag. in list */ - - return symbol; -} - -struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip) -{ - struct dsp_spos_instance * ins = kzalloc(sizeof(struct dsp_spos_instance), GFP_KERNEL); - - if (ins == NULL) - return NULL; - - /* better to use vmalloc for this big table */ - ins->symbol_table.symbols = vmalloc(sizeof(struct dsp_symbol_entry) * - DSP_MAX_SYMBOLS); - ins->code.data = kmalloc(DSP_CODE_BYTE_SIZE, GFP_KERNEL); - ins->modules = kmalloc(sizeof(struct dsp_module_desc) * DSP_MAX_MODULES, GFP_KERNEL); - if (!ins->symbol_table.symbols || !ins->code.data || !ins->modules) { - cs46xx_dsp_spos_destroy(chip); - goto error; - } - ins->symbol_table.nsymbols = 0; - ins->symbol_table.highest_frag_index = 0; - ins->code.offset = 0; - ins->code.size = 0; - ins->nscb = 0; - ins->ntask = 0; - ins->nmodules = 0; - - /* default SPDIF input sample rate - to 48000 khz */ - ins->spdif_in_sample_rate = 48000; - - /* maximize volume */ - ins->dac_volume_right = 0x8000; - ins->dac_volume_left = 0x8000; - ins->spdif_input_volume_right = 0x8000; - ins->spdif_input_volume_left = 0x8000; - - /* set left and right validity bits and - default channel status */ - ins->spdif_csuv_default = - ins->spdif_csuv_stream = - /* byte 0 */ ((unsigned int)_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF & 0xff)) << 24) | - /* byte 1 */ ((unsigned int)_wrap_all_bits( ((SNDRV_PCM_DEFAULT_CON_SPDIF >> 8) & 0xff)) << 16) | - /* byte 3 */ (unsigned int)_wrap_all_bits( (SNDRV_PCM_DEFAULT_CON_SPDIF >> 24) & 0xff) | - /* left and right validity bits */ (1 << 13) | (1 << 12); - - return ins; - -error: - kfree(ins->modules); - kfree(ins->code.data); - vfree(ins->symbol_table.symbols); - kfree(ins); - return NULL; -} - -void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) -{ - int i; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (snd_BUG_ON(!ins)) - return; - - mutex_lock(&chip->spos_mutex); - for (i = 0; i < ins->nscb; ++i) { - if (ins->scbs[i].deleted) continue; - - cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); -#ifdef CONFIG_PM - kfree(ins->scbs[i].data); -#endif - } - - kfree(ins->code.data); - vfree(ins->symbol_table.symbols); - kfree(ins->modules); - kfree(ins); - mutex_unlock(&chip->spos_mutex); -} - -static int dsp_load_parameter(struct snd_cs46xx *chip, - struct dsp_segment_desc *parameter) -{ - u32 doffset, dsize; - - if (!parameter) { - snd_printdd("dsp_spos: module got no parameter segment\n"); - return 0; - } - - doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET); - dsize = parameter->size * 4; - - snd_printdd("dsp_spos: " - "downloading parameter data to chip (%08x-%08x)\n", - doffset,doffset + dsize); - if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) { - snd_printk(KERN_ERR "dsp_spos: " - "failed to download parameter data to DSP\n"); - return -EINVAL; - } - return 0; -} - -static int dsp_load_sample(struct snd_cs46xx *chip, - struct dsp_segment_desc *sample) -{ - u32 doffset, dsize; - - if (!sample) { - snd_printdd("dsp_spos: module got no sample segment\n"); - return 0; - } - - doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET); - dsize = sample->size * 4; - - snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n", - doffset,doffset + dsize); - - if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) { - snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n"); - return -EINVAL; - } - return 0; -} - -int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); - u32 doffset, dsize; - int err; - - if (ins->nmodules == DSP_MAX_MODULES - 1) { - snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); - return -ENOMEM; - } - - snd_printdd("dsp_spos: loading module %s into DSP\n", module->module_name); - - if (ins->nmodules == 0) { - snd_printdd("dsp_spos: clearing parameter area\n"); - snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); - } - - err = dsp_load_parameter(chip, get_segment_desc(module, - SEGTYPE_SP_PARAMETER)); - if (err < 0) - return err; - - if (ins->nmodules == 0) { - snd_printdd("dsp_spos: clearing sample area\n"); - snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); - } - - err = dsp_load_sample(chip, get_segment_desc(module, - SEGTYPE_SP_SAMPLE)); - if (err < 0) - return err; - - if (ins->nmodules == 0) { - snd_printdd("dsp_spos: clearing code area\n"); - snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE); - } - - if (code == NULL) { - snd_printdd("dsp_spos: module got no code segment\n"); - } else { - if (ins->code.offset + code->size > DSP_CODE_BYTE_SIZE) { - snd_printk(KERN_ERR "dsp_spos: no space available in DSP\n"); - return -ENOMEM; - } - - module->load_address = ins->code.offset; - module->overlay_begin_address = 0x000; - - /* if module has a code segment it must have - symbol table */ - if (snd_BUG_ON(!module->symbol_table.symbols)) - return -ENOMEM; - if (add_symbols(chip,module)) { - snd_printk(KERN_ERR "dsp_spos: failed to load symbol table\n"); - return -ENOMEM; - } - - doffset = (code->offset * 4 + ins->code.offset * 4 + DSP_CODE_BYTE_OFFSET); - dsize = code->size * 4; - snd_printdd("dsp_spos: downloading code to chip (%08x-%08x)\n", - doffset,doffset + dsize); - - module->nfixups = shadow_and_reallocate_code(chip,code->data,code->size,module->overlay_begin_address); - - if (snd_cs46xx_download (chip,(ins->code.data + ins->code.offset),doffset,dsize)) { - snd_printk(KERN_ERR "dsp_spos: failed to download code to DSP\n"); - return -EINVAL; - } - - ins->code.offset += code->size; - } - - /* NOTE: module segments and symbol table must be - statically allocated. Case that module data is - not generated by the ospparser */ - ins->modules[ins->nmodules] = *module; - ins->nmodules++; - - return 0; -} - -struct dsp_symbol_entry * -cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, int symbol_type) -{ - int i; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { - - if (ins->symbol_table.symbols[i].deleted) - continue; - - if (!strcmp(ins->symbol_table.symbols[i].symbol_name,symbol_name) && - ins->symbol_table.symbols[i].symbol_type == symbol_type) { - return (ins->symbol_table.symbols + i); - } - } - -#if 0 - printk ("dsp_spos: symbol <%s> type %02x not found\n", - symbol_name,symbol_type); -#endif - - return NULL; -} - - -#ifdef CONFIG_PROC_FS -static struct dsp_symbol_entry * -cs46xx_dsp_lookup_symbol_addr (struct snd_cs46xx * chip, u32 address, int symbol_type) -{ - int i; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { - - if (ins->symbol_table.symbols[i].deleted) - continue; - - if (ins->symbol_table.symbols[i].address == address && - ins->symbol_table.symbols[i].symbol_type == symbol_type) { - return (ins->symbol_table.symbols + i); - } - } - - - return NULL; -} - - -static void cs46xx_dsp_proc_symbol_table_read (struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_cs46xx *chip = entry->private_data; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int i; - - snd_iprintf(buffer, "SYMBOLS:\n"); - for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) { - char *module_str = "system"; - - if (ins->symbol_table.symbols[i].deleted) - continue; - - if (ins->symbol_table.symbols[i].module != NULL) { - module_str = ins->symbol_table.symbols[i].module->module_name; - } - - - snd_iprintf(buffer, "%04X <%02X> %s [%s]\n", - ins->symbol_table.symbols[i].address, - ins->symbol_table.symbols[i].symbol_type, - ins->symbol_table.symbols[i].symbol_name, - module_str); - } -} - - -static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_cs46xx *chip = entry->private_data; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int i,j; - - mutex_lock(&chip->spos_mutex); - snd_iprintf(buffer, "MODULES:\n"); - for ( i = 0; i < ins->nmodules; ++i ) { - snd_iprintf(buffer, "\n%s:\n", ins->modules[i].module_name); - snd_iprintf(buffer, " %d symbols\n", ins->modules[i].symbol_table.nsymbols); - snd_iprintf(buffer, " %d fixups\n", ins->modules[i].nfixups); - - for (j = 0; j < ins->modules[i].nsegments; ++ j) { - struct dsp_segment_desc * desc = (ins->modules[i].segments + j); - snd_iprintf(buffer, " segment %02x offset %08x size %08x\n", - desc->segment_type,desc->offset, desc->size); - } - } - mutex_unlock(&chip->spos_mutex); -} - -static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_cs46xx *chip = entry->private_data; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int i, j, col; - void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; - - mutex_lock(&chip->spos_mutex); - snd_iprintf(buffer, "TASK TREES:\n"); - for ( i = 0; i < ins->ntask; ++i) { - snd_iprintf(buffer,"\n%04x %s:\n",ins->tasks[i].address,ins->tasks[i].task_name); - - for (col = 0,j = 0;j < ins->tasks[i].size; j++,col++) { - u32 val; - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - val = readl(dst + (ins->tasks[i].address + j) * sizeof(u32)); - snd_iprintf(buffer,"%08x ",val); - } - } - - snd_iprintf(buffer,"\n"); - mutex_unlock(&chip->spos_mutex); -} - -static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_cs46xx *chip = entry->private_data; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int i; - - mutex_lock(&chip->spos_mutex); - snd_iprintf(buffer, "SCB's:\n"); - for ( i = 0; i < ins->nscb; ++i) { - if (ins->scbs[i].deleted) - continue; - snd_iprintf(buffer,"\n%04x %s:\n\n",ins->scbs[i].address,ins->scbs[i].scb_name); - - if (ins->scbs[i].parent_scb_ptr != NULL) { - snd_iprintf(buffer,"parent [%s:%04x] ", - ins->scbs[i].parent_scb_ptr->scb_name, - ins->scbs[i].parent_scb_ptr->address); - } else snd_iprintf(buffer,"parent [none] "); - - snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x] task_entry [%s:%04x]\n", - ins->scbs[i].sub_list_ptr->scb_name, - ins->scbs[i].sub_list_ptr->address, - ins->scbs[i].next_scb_ptr->scb_name, - ins->scbs[i].next_scb_ptr->address, - ins->scbs[i].task_entry->symbol_name, - ins->scbs[i].task_entry->address); - } - - snd_iprintf(buffer,"\n"); - mutex_unlock(&chip->spos_mutex); -} - -static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_cs46xx *chip = entry->private_data; - /*struct dsp_spos_instance * ins = chip->dsp_spos_instance; */ - unsigned int i, col = 0; - void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; - struct dsp_symbol_entry * symbol; - - for (i = 0;i < DSP_PARAMETER_BYTE_SIZE; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if ( (symbol = cs46xx_dsp_lookup_symbol_addr (chip,i / sizeof(u32), SYMBOL_PARAMETER)) != NULL) { - col = 0; - snd_iprintf (buffer,"\n%s:\n",symbol->symbol_name); - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ", i / (unsigned int)sizeof(u32)); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } -} - -static void cs46xx_dsp_proc_sample_dump_read (struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_cs46xx *chip = entry->private_data; - int i,col = 0; - void __iomem *dst = chip->region.idx[2].remap_addr; - - snd_iprintf(buffer,"PCMREADER:\n"); - for (i = PCM_READER_BUF1;i < PCM_READER_BUF1 + 0x30; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } - - snd_iprintf(buffer,"\nMIX_SAMPLE_BUF1:\n"); - - col = 0; - for (i = MIX_SAMPLE_BUF1;i < MIX_SAMPLE_BUF1 + 0x40; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } - - snd_iprintf(buffer,"\nSRC_TASK_SCB1:\n"); - col = 0; - for (i = 0x2480 ; i < 0x2480 + 0x40 ; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } - - - snd_iprintf(buffer,"\nSPDIFO_BUFFER:\n"); - col = 0; - for (i = SPDIFO_IP_OUTPUT_BUFFER1;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x30; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } - - snd_iprintf(buffer,"\n...\n"); - col = 0; - - for (i = SPDIFO_IP_OUTPUT_BUFFER1+0xD0;i < SPDIFO_IP_OUTPUT_BUFFER1 + 0x110; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } - - - snd_iprintf(buffer,"\nOUTPUT_SNOOP:\n"); - col = 0; - for (i = OUTPUT_SNOOP_BUFFER;i < OUTPUT_SNOOP_BUFFER + 0x40; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } - - snd_iprintf(buffer,"\nCODEC_INPUT_BUF1: \n"); - col = 0; - for (i = CODEC_INPUT_BUF1;i < CODEC_INPUT_BUF1 + 0x40; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } -#if 0 - snd_iprintf(buffer,"\nWRITE_BACK_BUF1: \n"); - col = 0; - for (i = WRITE_BACK_BUF1;i < WRITE_BACK_BUF1 + 0x40; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } -#endif - - snd_iprintf(buffer,"\nSPDIFI_IP_OUTPUT_BUFFER1: \n"); - col = 0; - for (i = SPDIFI_IP_OUTPUT_BUFFER1;i < SPDIFI_IP_OUTPUT_BUFFER1 + 0x80; i += sizeof(u32),col ++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - - if (col == 0) { - snd_iprintf(buffer, "%04X ",i); - } - - snd_iprintf(buffer,"%08X ",readl(dst + i)); - } - snd_iprintf(buffer,"\n"); -} - -int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) -{ - struct snd_info_entry *entry; - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int i; - - ins->snd_card = card; - - if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; - - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - - ins->proc_dsp_dir = entry; - - if (!ins->proc_dsp_dir) - return -ENOMEM; - - if ((entry = snd_info_create_card_entry(card, "spos_symbols", ins->proc_dsp_dir)) != NULL) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = chip; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read = cs46xx_dsp_proc_symbol_table_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - ins->proc_sym_info_entry = entry; - - if ((entry = snd_info_create_card_entry(card, "spos_modules", ins->proc_dsp_dir)) != NULL) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = chip; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read = cs46xx_dsp_proc_modules_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - ins->proc_modules_info_entry = entry; - - if ((entry = snd_info_create_card_entry(card, "parameter", ins->proc_dsp_dir)) != NULL) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = chip; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - ins->proc_parameter_dump_info_entry = entry; - - if ((entry = snd_info_create_card_entry(card, "sample", ins->proc_dsp_dir)) != NULL) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = chip; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read = cs46xx_dsp_proc_sample_dump_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - ins->proc_sample_dump_info_entry = entry; - - if ((entry = snd_info_create_card_entry(card, "task_tree", ins->proc_dsp_dir)) != NULL) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = chip; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read = cs46xx_dsp_proc_task_tree_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - ins->proc_task_info_entry = entry; - - if ((entry = snd_info_create_card_entry(card, "scb_info", ins->proc_dsp_dir)) != NULL) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = chip; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - entry->c.text.read = cs46xx_dsp_proc_scb_read; - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - entry = NULL; - } - } - ins->proc_scb_info_entry = entry; - - mutex_lock(&chip->spos_mutex); - /* register/update SCB's entries on proc */ - for (i = 0; i < ins->nscb; ++i) { - if (ins->scbs[i].deleted) continue; - - cs46xx_dsp_proc_register_scb_desc (chip, (ins->scbs + i)); - } - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int i; - - snd_info_free_entry(ins->proc_sym_info_entry); - ins->proc_sym_info_entry = NULL; - - snd_info_free_entry(ins->proc_modules_info_entry); - ins->proc_modules_info_entry = NULL; - - snd_info_free_entry(ins->proc_parameter_dump_info_entry); - ins->proc_parameter_dump_info_entry = NULL; - - snd_info_free_entry(ins->proc_sample_dump_info_entry); - ins->proc_sample_dump_info_entry = NULL; - - snd_info_free_entry(ins->proc_scb_info_entry); - ins->proc_scb_info_entry = NULL; - - snd_info_free_entry(ins->proc_task_info_entry); - ins->proc_task_info_entry = NULL; - - mutex_lock(&chip->spos_mutex); - for (i = 0; i < ins->nscb; ++i) { - if (ins->scbs[i].deleted) continue; - cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); - } - mutex_unlock(&chip->spos_mutex); - - snd_info_free_entry(ins->proc_dsp_dir); - ins->proc_dsp_dir = NULL; - - return 0; -} -#endif /* CONFIG_PROC_FS */ - -static int debug_tree; -static void _dsp_create_task_tree (struct snd_cs46xx *chip, u32 * task_data, - u32 dest, int size) -{ - void __iomem *spdst = chip->region.idx[1].remap_addr + - DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32); - int i; - - for (i = 0; i < size; ++i) { - if (debug_tree) printk ("addr %p, val %08x\n",spdst,task_data[i]); - writel(task_data[i],spdst); - spdst += sizeof(u32); - } -} - -static int debug_scb; -static void _dsp_create_scb (struct snd_cs46xx *chip, u32 * scb_data, u32 dest) -{ - void __iomem *spdst = chip->region.idx[1].remap_addr + - DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32); - int i; - - for (i = 0; i < 0x10; ++i) { - if (debug_scb) printk ("addr %p, val %08x\n",spdst,scb_data[i]); - writel(scb_data[i],spdst); - spdst += sizeof(u32); - } -} - -static int find_free_scb_index (struct dsp_spos_instance * ins) -{ - int index = ins->nscb, i; - - for (i = ins->scb_highest_frag_index; i < ins->nscb; ++i) { - if (ins->scbs[i].deleted) { - index = i; - break; - } - } - - return index; -} - -static struct dsp_scb_descriptor * _map_scb (struct snd_cs46xx *chip, char * name, u32 dest) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * desc = NULL; - int index; - - if (ins->nscb == DSP_MAX_SCB_DESC - 1) { - snd_printk(KERN_ERR "dsp_spos: got no place for other SCB\n"); - return NULL; - } - - index = find_free_scb_index (ins); - - memset(&ins->scbs[index], 0, sizeof(ins->scbs[index])); - strcpy(ins->scbs[index].scb_name, name); - ins->scbs[index].address = dest; - ins->scbs[index].index = index; - ins->scbs[index].ref_count = 1; - - desc = (ins->scbs + index); - ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER); - - if (index > ins->scb_highest_frag_index) - ins->scb_highest_frag_index = index; - - if (index == ins->nscb) - ins->nscb++; - - return desc; -} - -static struct dsp_task_descriptor * -_map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_task_descriptor * desc = NULL; - - if (ins->ntask == DSP_MAX_TASK_DESC - 1) { - snd_printk(KERN_ERR "dsp_spos: got no place for other TASK\n"); - return NULL; - } - - if (name) - strcpy(ins->tasks[ins->ntask].task_name, name); - else - strcpy(ins->tasks[ins->ntask].task_name, "(NULL)"); - ins->tasks[ins->ntask].address = dest; - ins->tasks[ins->ntask].size = size; - - /* quick find in list */ - ins->tasks[ins->ntask].index = ins->ntask; - desc = (ins->tasks + ins->ntask); - ins->ntask++; - - if (name) - add_symbol (chip,name,dest,SYMBOL_PARAMETER); - return desc; -} - -#define SCB_BYTES (0x10 * 4) - -struct dsp_scb_descriptor * -cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest) -{ - struct dsp_scb_descriptor * desc; - -#ifdef CONFIG_PM - /* copy the data for resume */ - scb_data = kmemdup(scb_data, SCB_BYTES, GFP_KERNEL); - if (!scb_data) - return NULL; -#endif - - desc = _map_scb (chip,name,dest); - if (desc) { - desc->data = scb_data; - _dsp_create_scb(chip,scb_data,dest); - } else { - snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); -#ifdef CONFIG_PM - kfree(scb_data); -#endif - } - - return desc; -} - - -static struct dsp_task_descriptor * -cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_data, - u32 dest, int size) -{ - struct dsp_task_descriptor * desc; - - desc = _map_task_tree (chip,name,dest,size); - if (desc) { - desc->data = task_data; - _dsp_create_task_tree(chip,task_data,dest,size); - } else { - snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); - } - - return desc; -} - -int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_symbol_entry * fg_task_tree_header_code; - struct dsp_symbol_entry * task_tree_header_code; - struct dsp_symbol_entry * task_tree_thread; - struct dsp_symbol_entry * null_algorithm; - struct dsp_symbol_entry * magic_snoop_task; - - struct dsp_scb_descriptor * timing_master_scb; - struct dsp_scb_descriptor * codec_out_scb; - struct dsp_scb_descriptor * codec_in_scb; - struct dsp_scb_descriptor * src_task_scb; - struct dsp_scb_descriptor * master_mix_scb; - struct dsp_scb_descriptor * rear_mix_scb; - struct dsp_scb_descriptor * record_mix_scb; - struct dsp_scb_descriptor * write_back_scb; - struct dsp_scb_descriptor * vari_decimate_scb; - struct dsp_scb_descriptor * rear_codec_out_scb; - struct dsp_scb_descriptor * clfe_codec_out_scb; - struct dsp_scb_descriptor * magic_snoop_scb; - - int fifo_addr, fifo_span, valid_slots; - - static struct dsp_spos_control_block sposcb = { - /* 0 */ HFG_TREE_SCB,HFG_STACK, - /* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR, - /* 2 */ DSP_SPOS_DC,0, - /* 3 */ DSP_SPOS_DC,DSP_SPOS_DC, - /* 4 */ 0,0, - /* 5 */ DSP_SPOS_UU,0, - /* 6 */ FG_TASK_HEADER_ADDR,0, - /* 7 */ 0,0, - /* 8 */ DSP_SPOS_UU,DSP_SPOS_DC, - /* 9 */ 0, - /* A */ 0,HFG_FIRST_EXECUTE_MODE, - /* B */ DSP_SPOS_UU,DSP_SPOS_UU, - /* C */ DSP_SPOS_DC_DC, - /* D */ DSP_SPOS_DC_DC, - /* E */ DSP_SPOS_DC_DC, - /* F */ DSP_SPOS_DC_DC - }; - - cs46xx_dsp_create_task_tree(chip, "sposCB", (u32 *)&sposcb, SPOSCB_ADDR, 0x10); - - null_algorithm = cs46xx_dsp_lookup_symbol(chip, "NULLALGORITHM", SYMBOL_CODE); - if (null_algorithm == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n"); - return -EIO; - } - - fg_task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "FGTASKTREEHEADERCODE", SYMBOL_CODE); - if (fg_task_tree_header_code == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol FGTASKTREEHEADERCODE not found\n"); - return -EIO; - } - - task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "TASKTREEHEADERCODE", SYMBOL_CODE); - if (task_tree_header_code == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol TASKTREEHEADERCODE not found\n"); - return -EIO; - } - - task_tree_thread = cs46xx_dsp_lookup_symbol(chip, "TASKTREETHREAD", SYMBOL_CODE); - if (task_tree_thread == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol TASKTREETHREAD not found\n"); - return -EIO; - } - - magic_snoop_task = cs46xx_dsp_lookup_symbol(chip, "MAGICSNOOPTASK", SYMBOL_CODE); - if (magic_snoop_task == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol MAGICSNOOPTASK not found\n"); - return -EIO; - } - - { - /* create the null SCB */ - static struct dsp_generic_scb null_scb = { - { 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 }, - NULL_SCB_ADDR, NULL_SCB_ADDR, - 0, 0, 0, 0, 0, - { - 0,0, - 0,0, - } - }; - - null_scb.entry_point = null_algorithm->address; - ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR); - ins->the_null_scb->task_entry = null_algorithm; - ins->the_null_scb->sub_list_ptr = ins->the_null_scb; - ins->the_null_scb->next_scb_ptr = ins->the_null_scb; - ins->the_null_scb->parent_scb_ptr = NULL; - cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb); - } - - { - /* setup foreground task tree */ - static struct dsp_task_tree_control_block fg_task_tree_hdr = { - { FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10), - DSP_SPOS_DC_DC, - DSP_SPOS_DC_DC, - 0x0000,DSP_SPOS_DC, - DSP_SPOS_DC, DSP_SPOS_DC, - DSP_SPOS_DC_DC, - DSP_SPOS_DC_DC, - DSP_SPOS_DC_DC, - DSP_SPOS_DC,DSP_SPOS_DC }, - - { - BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR, - 0, - FG_TASK_HEADER_ADDR + TCBData, - }, - - { - 4,0, - 1,0, - 2,SPOSCB_ADDR + HFGFlags, - 0,0, - FG_TASK_HEADER_ADDR + TCBContextBlk,FG_STACK - }, - - { - DSP_SPOS_DC,0, - DSP_SPOS_DC,DSP_SPOS_DC, - DSP_SPOS_DC,DSP_SPOS_DC, - DSP_SPOS_DC,DSP_SPOS_DC, - DSP_SPOS_DC,DSP_SPOS_DC, - DSP_SPOS_DCDC, - DSP_SPOS_UU,1, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC - }, - { - FG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU, - 0,0 - } - }; - - fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address; - fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address; - cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35); - } - - - { - /* setup foreground task tree */ - static struct dsp_task_tree_control_block bg_task_tree_hdr = { - { DSP_SPOS_DC_DC, - DSP_SPOS_DC_DC, - DSP_SPOS_DC_DC, - DSP_SPOS_DC, DSP_SPOS_DC, - DSP_SPOS_DC, DSP_SPOS_DC, - DSP_SPOS_DC_DC, - DSP_SPOS_DC_DC, - DSP_SPOS_DC_DC, - DSP_SPOS_DC,DSP_SPOS_DC }, - - { - NULL_SCB_ADDR,NULL_SCB_ADDR, /* Set up the background to do nothing */ - 0, - BG_TREE_SCB_ADDR + TCBData, - }, - - { - 9999,0, - 0,1, - 0,SPOSCB_ADDR + HFGFlags, - 0,0, - BG_TREE_SCB_ADDR + TCBContextBlk,BG_STACK - }, - - { - DSP_SPOS_DC,0, - DSP_SPOS_DC,DSP_SPOS_DC, - DSP_SPOS_DC,DSP_SPOS_DC, - DSP_SPOS_DC,DSP_SPOS_DC, - DSP_SPOS_DC,DSP_SPOS_DC, - DSP_SPOS_DCDC, - DSP_SPOS_UU,1, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC, - DSP_SPOS_DCDC - }, - { - BG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU, - 0,0 - } - }; - - bg_task_tree_hdr.links.entry_point = task_tree_header_code->address; - bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address; - cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35); - } - - /* create timing master SCB */ - timing_master_scb = cs46xx_dsp_create_timing_master_scb(chip); - - /* create the CODEC output task */ - codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_I",0x0010,0x0000, - MASTERMIX_SCB_ADDR, - CODECOUT_SCB_ADDR,timing_master_scb, - SCB_ON_PARENT_SUBLIST_SCB); - - if (!codec_out_scb) goto _fail_end; - /* create the master mix SCB */ - master_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"MasterMixSCB", - MIX_SAMPLE_BUF1,MASTERMIX_SCB_ADDR, - codec_out_scb, - SCB_ON_PARENT_SUBLIST_SCB); - ins->master_mix_scb = master_mix_scb; - - if (!master_mix_scb) goto _fail_end; - - /* create codec in */ - codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0, - CODEC_INPUT_BUF1, - CODECIN_SCB_ADDR,codec_out_scb, - SCB_ON_PARENT_NEXT_SCB); - if (!codec_in_scb) goto _fail_end; - ins->codec_in_scb = codec_in_scb; - - /* create write back scb */ - write_back_scb = cs46xx_dsp_create_mix_to_ostream_scb(chip,"WriteBackSCB", - WRITE_BACK_BUF1,WRITE_BACK_SPB, - WRITEBACK_SCB_ADDR, - timing_master_scb, - SCB_ON_PARENT_NEXT_SCB); - if (!write_back_scb) goto _fail_end; - - { - static struct dsp_mix2_ostream_spb mix2_ostream_spb = { - 0x00020000, - 0x0000ffff - }; - - if (!cs46xx_dsp_create_task_tree(chip, NULL, - (u32 *)&mix2_ostream_spb, - WRITE_BACK_SPB, 2)) - goto _fail_end; - } - - /* input sample converter */ - vari_decimate_scb = cs46xx_dsp_create_vari_decimate_scb(chip,"VariDecimateSCB", - VARI_DECIMATE_BUF0, - VARI_DECIMATE_BUF1, - VARIDECIMATE_SCB_ADDR, - write_back_scb, - SCB_ON_PARENT_SUBLIST_SCB); - if (!vari_decimate_scb) goto _fail_end; - - /* create the record mixer SCB */ - record_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RecordMixerSCB", - MIX_SAMPLE_BUF2, - RECORD_MIXER_SCB_ADDR, - vari_decimate_scb, - SCB_ON_PARENT_SUBLIST_SCB); - ins->record_mixer_scb = record_mix_scb; - - if (!record_mix_scb) goto _fail_end; - - valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV); - - if (snd_BUG_ON(chip->nr_ac97_codecs != 1 && chip->nr_ac97_codecs != 2)) - goto _fail_end; - - if (chip->nr_ac97_codecs == 1) { - /* output on slot 5 and 11 - on primary CODEC */ - fifo_addr = 0x20; - fifo_span = 0x60; - - /* enable slot 5 and 11 */ - valid_slots |= ACOSV_SLV5 | ACOSV_SLV11; - } else { - /* output on slot 7 and 8 - on secondary CODEC */ - fifo_addr = 0x40; - fifo_span = 0x10; - - /* enable slot 7 and 8 */ - valid_slots |= ACOSV_SLV7 | ACOSV_SLV8; - } - /* create CODEC tasklet for rear speakers output*/ - rear_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_Rear",fifo_span,fifo_addr, - REAR_MIXER_SCB_ADDR, - REAR_CODECOUT_SCB_ADDR,codec_in_scb, - SCB_ON_PARENT_NEXT_SCB); - if (!rear_codec_out_scb) goto _fail_end; - - - /* create the rear PCM channel mixer SCB */ - rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB", - MIX_SAMPLE_BUF3, - REAR_MIXER_SCB_ADDR, - rear_codec_out_scb, - SCB_ON_PARENT_SUBLIST_SCB); - ins->rear_mix_scb = rear_mix_scb; - if (!rear_mix_scb) goto _fail_end; - - if (chip->nr_ac97_codecs == 2) { - /* create CODEC tasklet for rear Center/LFE output - slot 6 and 9 on seconadry CODEC */ - clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030, - CLFE_MIXER_SCB_ADDR, - CLFE_CODEC_SCB_ADDR, - rear_codec_out_scb, - SCB_ON_PARENT_NEXT_SCB); - if (!clfe_codec_out_scb) goto _fail_end; - - - /* create the rear PCM channel mixer SCB */ - ins->center_lfe_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"CLFEMixerSCB", - MIX_SAMPLE_BUF4, - CLFE_MIXER_SCB_ADDR, - clfe_codec_out_scb, - SCB_ON_PARENT_SUBLIST_SCB); - if (!ins->center_lfe_mix_scb) goto _fail_end; - - /* enable slot 6 and 9 */ - valid_slots |= ACOSV_SLV6 | ACOSV_SLV9; - } else { - clfe_codec_out_scb = rear_codec_out_scb; - ins->center_lfe_mix_scb = rear_mix_scb; - } - - /* enable slots depending on CODEC configuration */ - snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots); - - /* the magic snooper */ - magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR, - OUTPUT_SNOOP_BUFFER, - codec_out_scb, - clfe_codec_out_scb, - SCB_ON_PARENT_NEXT_SCB); - - - if (!magic_snoop_scb) goto _fail_end; - ins->ref_snoop_scb = magic_snoop_scb; - - /* SP IO access */ - if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR, - magic_snoop_scb, - SCB_ON_PARENT_NEXT_SCB)) - goto _fail_end; - - /* SPDIF input sampel rate converter */ - src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI", - ins->spdif_in_sample_rate, - SRC_OUTPUT_BUF1, - SRC_DELAY_BUF1,SRCTASK_SCB_ADDR, - master_mix_scb, - SCB_ON_PARENT_SUBLIST_SCB,1); - - if (!src_task_scb) goto _fail_end; - cs46xx_src_unlink(chip,src_task_scb); - - /* NOTE: when we now how to detect the SPDIF input - sample rate we will use this SRC to adjust it */ - ins->spdif_in_src = src_task_scb; - - cs46xx_dsp_async_init(chip,timing_master_scb); - return 0; - - _fail_end: - snd_printk(KERN_ERR "dsp_spos: failed to setup SCB's in DSP\n"); - return -EINVAL; -} - -static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, - struct dsp_scb_descriptor * fg_entry) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_symbol_entry * s16_async_codec_input_task; - struct dsp_symbol_entry * spdifo_task; - struct dsp_symbol_entry * spdifi_task; - struct dsp_scb_descriptor * spdifi_scb_desc, * spdifo_scb_desc, * async_codec_scb_desc; - - s16_async_codec_input_task = cs46xx_dsp_lookup_symbol(chip, "S16_ASYNCCODECINPUTTASK", SYMBOL_CODE); - if (s16_async_codec_input_task == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol S16_ASYNCCODECINPUTTASK not found\n"); - return -EIO; - } - spdifo_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFOTASK", SYMBOL_CODE); - if (spdifo_task == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol SPDIFOTASK not found\n"); - return -EIO; - } - - spdifi_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFITASK", SYMBOL_CODE); - if (spdifi_task == NULL) { - snd_printk(KERN_ERR "dsp_spos: symbol SPDIFITASK not found\n"); - return -EIO; - } - - { - /* 0xBC0 */ - struct dsp_spdifoscb spdifo_scb = { - /* 0 */ DSP_SPOS_UUUU, - { - /* 1 */ 0xb0, - /* 2 */ 0, - /* 3 */ 0, - /* 4 */ 0, - }, - /* NOTE: the SPDIF output task read samples in mono - format, the AsynchFGTxSCB task writes to buffer - in stereo format - */ - /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_256, - /* 6 */ ( SPDIFO_IP_OUTPUT_BUFFER1 << 0x10 ) | 0xFFFC, - /* 7 */ 0,0, - /* 8 */ 0, - /* 9 */ FG_TASK_HEADER_ADDR, NULL_SCB_ADDR, - /* A */ spdifo_task->address, - SPDIFO_SCB_INST + SPDIFOFIFOPointer, - { - /* B */ 0x0040, /*DSP_SPOS_UUUU,*/ - /* C */ 0x20ff, /*DSP_SPOS_UUUU,*/ - }, - /* D */ 0x804c,0, /* SPDIFOFIFOPointer:SPDIFOStatRegAddr; */ - /* E */ 0x0108,0x0001, /* SPDIFOStMoFormat:SPDIFOFIFOBaseAddr; */ - /* F */ DSP_SPOS_UUUU /* SPDIFOFree; */ - }; - - /* 0xBB0 */ - struct dsp_spdifiscb spdifi_scb = { - /* 0 */ DSP_SPOS_UULO,DSP_SPOS_UUHI, - /* 1 */ 0, - /* 2 */ 0, - /* 3 */ 1,4000, /* SPDIFICountLimit SPDIFICount */ - /* 4 */ DSP_SPOS_UUUU, /* SPDIFIStatusData */ - /* 5 */ 0,DSP_SPOS_UUHI, /* StatusData, Free4 */ - /* 6 */ DSP_SPOS_UUUU, /* Free3 */ - /* 7 */ DSP_SPOS_UU,DSP_SPOS_DC, /* Free2 BitCount*/ - /* 8 */ DSP_SPOS_UUUU, /* TempStatus */ - /* 9 */ SPDIFO_SCB_INST, NULL_SCB_ADDR, - /* A */ spdifi_task->address, - SPDIFI_SCB_INST + SPDIFIFIFOPointer, - /* NOTE: The SPDIF input task write the sample in mono - format from the HW FIFO, the AsynchFGRxSCB task reads - them in stereo - */ - /* B */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_128, - /* C */ (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC, - /* D */ 0x8048,0, - /* E */ 0x01f0,0x0001, - /* F */ DSP_SPOS_UUUU /* SPDIN_STATUS monitor */ - }; - - /* 0xBA0 */ - struct dsp_async_codec_input_scb async_codec_input_scb = { - /* 0 */ DSP_SPOS_UUUU, - /* 1 */ 0, - /* 2 */ 0, - /* 3 */ 1,4000, - /* 4 */ 0x0118,0x0001, - /* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_64, - /* 6 */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC, - /* 7 */ DSP_SPOS_UU,0x3, - /* 8 */ DSP_SPOS_UUUU, - /* 9 */ SPDIFI_SCB_INST,NULL_SCB_ADDR, - /* A */ s16_async_codec_input_task->address, - HFG_TREE_SCB + AsyncCIOFIFOPointer, - - /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, - /* C */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10), /*(ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,*/ - -#ifdef UseASER1Input - /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr; - Init. 0000:8042: for ASER1 - 0000:8044: for ASER2 */ - /* D */ 0x8042,0, - - /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr; - Init 1 stero:8050 ASER1 - Init 0 mono:8070 ASER2 - Init 1 Stereo : 0100 ASER1 (Set by script) */ - /* E */ 0x0100,0x0001, - -#endif - -#ifdef UseASER2Input - /* short AsyncCIFIFOPointer:AsyncCIStatRegAddr; - Init. 0000:8042: for ASER1 - 0000:8044: for ASER2 */ - /* D */ 0x8044,0, - - /* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr; - Init 1 stero:8050 ASER1 - Init 0 mono:8070 ASER2 - Init 1 Stereo : 0100 ASER1 (Set by script) */ - /* E */ 0x0110,0x0001, - -#endif - - /* short AsyncCIOutputBufModulo:AsyncCIFree; - AsyncCIOutputBufModulo: The modulo size for - the output buffer of this task */ - /* F */ 0, /* DSP_SPOS_UUUU */ - }; - - spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST); - - if (snd_BUG_ON(!spdifo_scb_desc)) - return -EIO; - spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST); - if (snd_BUG_ON(!spdifi_scb_desc)) - return -EIO; - async_codec_scb_desc = cs46xx_dsp_create_scb(chip,"AsynCodecInputSCB",(u32 *)&async_codec_input_scb, HFG_TREE_SCB); - if (snd_BUG_ON(!async_codec_scb_desc)) - return -EIO; - - async_codec_scb_desc->parent_scb_ptr = NULL; - async_codec_scb_desc->next_scb_ptr = spdifi_scb_desc; - async_codec_scb_desc->sub_list_ptr = ins->the_null_scb; - async_codec_scb_desc->task_entry = s16_async_codec_input_task; - - spdifi_scb_desc->parent_scb_ptr = async_codec_scb_desc; - spdifi_scb_desc->next_scb_ptr = spdifo_scb_desc; - spdifi_scb_desc->sub_list_ptr = ins->the_null_scb; - spdifi_scb_desc->task_entry = spdifi_task; - - spdifo_scb_desc->parent_scb_ptr = spdifi_scb_desc; - spdifo_scb_desc->next_scb_ptr = fg_entry; - spdifo_scb_desc->sub_list_ptr = ins->the_null_scb; - spdifo_scb_desc->task_entry = spdifo_task; - - /* this one is faked, as the parnet of SPDIFO task - is the FG task tree */ - fg_entry->parent_scb_ptr = spdifo_scb_desc; - - /* for proc fs */ - cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc); - cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc); - cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc); - - /* Async MASTER ENABLE, affects both SPDIF input and output */ - snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 ); - } - - return 0; -} - -static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - /* set SPDIF output FIFO slot */ - snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0); - - /* SPDIF output MASTER ENABLE */ - cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0); - - /* right and left validate bit */ - /*cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);*/ - cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x0); - - /* clear fifo pointer */ - cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0); - - /* monitor state */ - ins->spdif_status_out &= ~DSP_SPDIF_STATUS_HW_ENABLED; -} - -int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - /* if hw-ctrl already enabled, turn off to reset logic ... */ - cs46xx_dsp_disable_spdif_hw (chip); - udelay(50); - - /* set SPDIF output FIFO slot */ - snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, ( 0x8000 | ((SP_SPDOUT_FIFO >> 4) << 4) )); - - /* SPDIF output MASTER ENABLE */ - cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000); - - /* right and left validate bit */ - cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default); - - /* monitor state */ - ins->spdif_status_out |= DSP_SPDIF_STATUS_HW_ENABLED; - - return 0; -} - -int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - /* turn on amplifier */ - chip->active_ctrl(chip, 1); - chip->amplifier_ctrl(chip, 1); - - if (snd_BUG_ON(ins->asynch_rx_scb)) - return -EINVAL; - if (snd_BUG_ON(!ins->spdif_in_src)) - return -EINVAL; - - mutex_lock(&chip->spos_mutex); - - if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) { - /* time countdown enable */ - cs46xx_poke_via_dsp (chip,SP_ASER_COUNTDOWN, 0x80000005); - /* NOTE: 80000005 value is just magic. With all values - that I've tested this one seem to give the best result. - Got no explication why. (Benny) */ - - /* SPDIF input MASTER ENABLE */ - cs46xx_poke_via_dsp (chip,SP_SPDIN_CONTROL, 0x800003ff); - - ins->spdif_status_out |= DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED; - } - - /* create and start the asynchronous receiver SCB */ - ins->asynch_rx_scb = cs46xx_dsp_create_asynch_fg_rx_scb(chip,"AsynchFGRxSCB", - ASYNCRX_SCB_ADDR, - SPDIFI_SCB_INST, - SPDIFI_IP_OUTPUT_BUFFER1, - ins->spdif_in_src, - SCB_ON_PARENT_SUBLIST_SCB); - - spin_lock_irq(&chip->reg_lock); - - /* reset SPDIF input sample buffer pointer */ - /*snd_cs46xx_poke (chip, (SPDIFI_SCB_INST + 0x0c) << 2, - (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC);*/ - - /* reset FIFO ptr */ - /*cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);*/ - cs46xx_src_link(chip,ins->spdif_in_src); - - /* unmute SRC volume */ - cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,0x7fff,0x7fff); - - spin_unlock_irq(&chip->reg_lock); - - /* set SPDIF input sample rate and unmute - NOTE: only 48khz support for SPDIF input this time */ - /* cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); */ - - /* monitor state */ - ins->spdif_status_in = 1; - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (snd_BUG_ON(!ins->asynch_rx_scb)) - return -EINVAL; - if (snd_BUG_ON(!ins->spdif_in_src)) - return -EINVAL; - - mutex_lock(&chip->spos_mutex); - - /* Remove the asynchronous receiver SCB */ - cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb); - ins->asynch_rx_scb = NULL; - - cs46xx_src_unlink(chip,ins->spdif_in_src); - - /* monitor state */ - ins->spdif_status_in = 0; - mutex_unlock(&chip->spos_mutex); - - /* restore amplifier */ - chip->active_ctrl(chip, -1); - chip->amplifier_ctrl(chip, -1); - - return 0; -} - -int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (snd_BUG_ON(ins->pcm_input)) - return -EINVAL; - if (snd_BUG_ON(!ins->ref_snoop_scb)) - return -EINVAL; - - mutex_lock(&chip->spos_mutex); - ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR, - "PCMSerialInput_Wave"); - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (snd_BUG_ON(!ins->pcm_input)) - return -EINVAL; - - mutex_lock(&chip->spos_mutex); - cs46xx_dsp_remove_scb (chip,ins->pcm_input); - ins->pcm_input = NULL; - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (snd_BUG_ON(ins->adc_input)) - return -EINVAL; - if (snd_BUG_ON(!ins->codec_in_scb)) - return -EINVAL; - - mutex_lock(&chip->spos_mutex); - ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR, - "PCMSerialInput_ADC"); - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (snd_BUG_ON(!ins->adc_input)) - return -EINVAL; - - mutex_lock(&chip->spos_mutex); - cs46xx_dsp_remove_scb (chip,ins->adc_input); - ins->adc_input = NULL; - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data) -{ - u32 temp; - int i; - - /* santiy check the parameters. (These numbers are not 100% correct. They are - a rough guess from looking at the controller spec.) */ - if (address < 0x8000 || address >= 0x9000) - return -EINVAL; - - /* initialize the SP_IO_WRITE SCB with the data. */ - temp = ( address << 16 ) | ( address & 0x0000FFFF); /* offset 0 <-- address2 : address1 */ - - snd_cs46xx_poke(chip,( SPIOWRITE_SCB_ADDR << 2), temp); - snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 1) << 2), data); /* offset 1 <-- data1 */ - snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 2) << 2), data); /* offset 1 <-- data2 */ - - /* Poke this location to tell the task to start */ - snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 6) << 2), SPIOWRITE_SCB_ADDR << 0x10); - - /* Verify that the task ran */ - for (i=0; i<25; i++) { - udelay(125); - - temp = snd_cs46xx_peek(chip,((SPIOWRITE_SCB_ADDR + 6) << 2)); - if (temp == 0x00000000) - break; - } - - if (i == 25) { - snd_printk(KERN_ERR "dsp_spos: SPIOWriteTask not responding\n"); - return -EBUSY; - } - - return 0; -} - -int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * scb; - - mutex_lock(&chip->spos_mutex); - - /* main output */ - scb = ins->master_mix_scb->sub_list_ptr; - while (scb != ins->the_null_scb) { - cs46xx_dsp_scb_set_volume (chip,scb,left,right); - scb = scb->next_scb_ptr; - } - - /* rear output */ - scb = ins->rear_mix_scb->sub_list_ptr; - while (scb != ins->the_null_scb) { - cs46xx_dsp_scb_set_volume (chip,scb,left,right); - scb = scb->next_scb_ptr; - } - - ins->dac_volume_left = left; - ins->dac_volume_right = right; - - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - mutex_lock(&chip->spos_mutex); - - if (ins->asynch_rx_scb != NULL) - cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb, - left,right); - - ins->spdif_input_volume_left = left; - ins->spdif_input_volume_right = right; - - mutex_unlock(&chip->spos_mutex); - - return 0; -} - -#ifdef CONFIG_PM -int cs46xx_dsp_resume(struct snd_cs46xx * chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int i, err; - - /* clear parameter, sample and code areas */ - snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, - DSP_PARAMETER_BYTE_SIZE); - snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, - DSP_SAMPLE_BYTE_SIZE); - snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE); - - for (i = 0; i < ins->nmodules; i++) { - struct dsp_module_desc *module = &ins->modules[i]; - struct dsp_segment_desc *seg; - u32 doffset, dsize; - - seg = get_segment_desc(module, SEGTYPE_SP_PARAMETER); - err = dsp_load_parameter(chip, seg); - if (err < 0) - return err; - - seg = get_segment_desc(module, SEGTYPE_SP_SAMPLE); - err = dsp_load_sample(chip, seg); - if (err < 0) - return err; - - seg = get_segment_desc(module, SEGTYPE_SP_PROGRAM); - if (!seg) - continue; - - doffset = seg->offset * 4 + module->load_address * 4 - + DSP_CODE_BYTE_OFFSET; - dsize = seg->size * 4; - err = snd_cs46xx_download(chip, - ins->code.data + module->load_address, - doffset, dsize); - if (err < 0) - return err; - } - - for (i = 0; i < ins->ntask; i++) { - struct dsp_task_descriptor *t = &ins->tasks[i]; - _dsp_create_task_tree(chip, t->data, t->address, t->size); - } - - for (i = 0; i < ins->nscb; i++) { - struct dsp_scb_descriptor *s = &ins->scbs[i]; - if (s->deleted) - continue; - _dsp_create_scb(chip, s->data, s->address); - } - for (i = 0; i < ins->nscb; i++) { - struct dsp_scb_descriptor *s = &ins->scbs[i]; - if (s->deleted) - continue; - if (s->updated) - cs46xx_dsp_spos_update_scb(chip, s); - if (s->volume_set) - cs46xx_dsp_scb_set_volume(chip, s, - s->volume[0], s->volume[1]); - } - if (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) { - cs46xx_dsp_enable_spdif_hw(chip); - snd_cs46xx_poke(chip, (ins->ref_snoop_scb->address + 2) << 2, - (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10); - if (ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) - cs46xx_poke_via_dsp(chip, SP_SPDOUT_CSUV, - ins->spdif_csuv_stream); - } - if (chip->dsp_spos_instance->spdif_status_in) { - cs46xx_poke_via_dsp(chip, SP_ASER_COUNTDOWN, 0x80000005); - cs46xx_poke_via_dsp(chip, SP_SPDIN_CONTROL, 0x800003ff); - } - return 0; -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.h b/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.h deleted file mode 100644 index ca47a811..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * The driver for the Cirrus Logic's Sound Fusion CS46XX based soundcards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - * - */ - -/* - * 2002-07 Benny Sjostrand benny@hostmobility.com - */ - -#ifdef CONFIG_SND_CS46XX_NEW_DSP /* hack ... */ -#ifndef __DSP_SPOS_H__ -#define __DSP_SPOS_H__ - -#define DSP_MAX_SYMBOLS 1024 -#define DSP_MAX_MODULES 64 - -#define DSP_CODE_BYTE_SIZE 0x00007000UL -#define DSP_PARAMETER_BYTE_SIZE 0x00003000UL -#define DSP_SAMPLE_BYTE_SIZE 0x00003800UL -#define DSP_PARAMETER_BYTE_OFFSET 0x00000000UL -#define DSP_SAMPLE_BYTE_OFFSET 0x00010000UL -#define DSP_CODE_BYTE_OFFSET 0x00020000UL - -#define WIDE_INSTR_MASK 0x0040 -#define WIDE_LADD_INSTR_MASK 0x0380 - -/* this instruction types - needs to be reallocated when load - code into DSP */ -enum wide_opcode { - WIDE_FOR_BEGIN_LOOP = 0x20, - WIDE_FOR_BEGIN_LOOP2, - - WIDE_COND_GOTO_ADDR = 0x30, - WIDE_COND_GOTO_CALL, - - WIDE_TBEQ_COND_GOTO_ADDR = 0x70, - WIDE_TBEQ_COND_CALL_ADDR, - WIDE_TBEQ_NCOND_GOTO_ADDR, - WIDE_TBEQ_NCOND_CALL_ADDR, - WIDE_TBEQ_COND_GOTO1_ADDR, - WIDE_TBEQ_COND_CALL1_ADDR, - WIDE_TBEQ_NCOND_GOTOI_ADDR, - WIDE_TBEQ_NCOND_CALL1_ADDR, -}; - -/* SAMPLE segment */ -#define VARI_DECIMATE_BUF1 0x0000 -#define WRITE_BACK_BUF1 0x0400 -#define CODEC_INPUT_BUF1 0x0500 -#define PCM_READER_BUF1 0x0600 -#define SRC_DELAY_BUF1 0x0680 -#define VARI_DECIMATE_BUF0 0x0780 -#define SRC_OUTPUT_BUF1 0x07A0 -#define ASYNC_IP_OUTPUT_BUFFER1 0x0A00 -#define OUTPUT_SNOOP_BUFFER 0x0B00 -#define SPDIFI_IP_OUTPUT_BUFFER1 0x0E00 -#define SPDIFO_IP_OUTPUT_BUFFER1 0x1000 -#define MIX_SAMPLE_BUF1 0x1400 -#define MIX_SAMPLE_BUF2 0x2E80 -#define MIX_SAMPLE_BUF3 0x2F00 -#define MIX_SAMPLE_BUF4 0x2F80 -#define MIX_SAMPLE_BUF5 0x3000 - -/* Task stack address */ -#define HFG_STACK 0x066A -#define FG_STACK 0x066E -#define BG_STACK 0x068E - -/* SCB's addresses */ -#define SPOSCB_ADDR 0x070 -#define BG_TREE_SCB_ADDR 0x635 -#define NULL_SCB_ADDR 0x000 -#define TIMINGMASTER_SCB_ADDR 0x010 -#define CODECOUT_SCB_ADDR 0x020 -#define PCMREADER_SCB_ADDR 0x030 -#define WRITEBACK_SCB_ADDR 0x040 -#define CODECIN_SCB_ADDR 0x080 -#define MASTERMIX_SCB_ADDR 0x090 -#define SRCTASK_SCB_ADDR 0x0A0 -#define VARIDECIMATE_SCB_ADDR 0x0B0 -#define PCMSERIALIN_SCB_ADDR 0x0C0 -#define FG_TASK_HEADER_ADDR 0x600 -#define ASYNCTX_SCB_ADDR 0x0E0 -#define ASYNCRX_SCB_ADDR 0x0F0 -#define SRCTASKII_SCB_ADDR 0x100 -#define OUTPUTSNOOP_SCB_ADDR 0x110 -#define PCMSERIALINII_SCB_ADDR 0x120 -#define SPIOWRITE_SCB_ADDR 0x130 -#define REAR_CODECOUT_SCB_ADDR 0x140 -#define OUTPUTSNOOPII_SCB_ADDR 0x150 -#define PCMSERIALIN_PCM_SCB_ADDR 0x160 -#define RECORD_MIXER_SCB_ADDR 0x170 -#define REAR_MIXER_SCB_ADDR 0x180 -#define CLFE_MIXER_SCB_ADDR 0x190 -#define CLFE_CODEC_SCB_ADDR 0x1A0 - -/* hyperforground SCB's*/ -#define HFG_TREE_SCB 0xBA0 -#define SPDIFI_SCB_INST 0xBB0 -#define SPDIFO_SCB_INST 0xBC0 -#define WRITE_BACK_SPB 0x0D0 - -/* offsets */ -#define AsyncCIOFIFOPointer 0xd -#define SPDIFOFIFOPointer 0xd -#define SPDIFIFIFOPointer 0xd -#define TCBData 0xb -#define HFGFlags 0xa -#define TCBContextBlk 0x10 -#define AFGTxAccumPhi 0x4 -#define SCBsubListPtr 0x9 -#define SCBfuncEntryPtr 0xA -#define SRCCorPerGof 0x2 -#define SRCPhiIncr6Int26Frac 0xd -#define SCBVolumeCtrl 0xe - -/* conf */ -#define UseASER1Input 1 - - - -/* - * The following defines are for the flags in the rsConfig01/23 registers of - * the SP. - */ - -#define RSCONFIG_MODULO_SIZE_MASK 0x0000000FL -#define RSCONFIG_MODULO_16 0x00000001L -#define RSCONFIG_MODULO_32 0x00000002L -#define RSCONFIG_MODULO_64 0x00000003L -#define RSCONFIG_MODULO_128 0x00000004L -#define RSCONFIG_MODULO_256 0x00000005L -#define RSCONFIG_MODULO_512 0x00000006L -#define RSCONFIG_MODULO_1024 0x00000007L -#define RSCONFIG_MODULO_4 0x00000008L -#define RSCONFIG_MODULO_8 0x00000009L -#define RSCONFIG_SAMPLE_SIZE_MASK 0x000000C0L -#define RSCONFIG_SAMPLE_8MONO 0x00000000L -#define RSCONFIG_SAMPLE_8STEREO 0x00000040L -#define RSCONFIG_SAMPLE_16MONO 0x00000080L -#define RSCONFIG_SAMPLE_16STEREO 0x000000C0L -#define RSCONFIG_UNDERRUN_ZERO 0x00004000L -#define RSCONFIG_DMA_TO_HOST 0x00008000L -#define RSCONFIG_STREAM_NUM_MASK 0x00FF0000L -#define RSCONFIG_MAX_DMA_SIZE_MASK 0x1F000000L -#define RSCONFIG_DMA_ENABLE 0x20000000L -#define RSCONFIG_PRIORITY_MASK 0xC0000000L -#define RSCONFIG_PRIORITY_HIGH 0x00000000L -#define RSCONFIG_PRIORITY_MEDIUM_HIGH 0x40000000L -#define RSCONFIG_PRIORITY_MEDIUM_LOW 0x80000000L -#define RSCONFIG_PRIORITY_LOW 0xC0000000L -#define RSCONFIG_STREAM_NUM_SHIFT 16L -#define RSCONFIG_MAX_DMA_SIZE_SHIFT 24L - -/* SP constants */ -#define FG_INTERVAL_TIMER_PERIOD 0x0051 -#define BG_INTERVAL_TIMER_PERIOD 0x0100 - - -/* Only SP accessible registers */ -#define SP_ASER_COUNTDOWN 0x8040 -#define SP_SPDOUT_FIFO 0x0108 -#define SP_SPDIN_MI_FIFO 0x01E0 -#define SP_SPDIN_D_FIFO 0x01F0 -#define SP_SPDIN_STATUS 0x8048 -#define SP_SPDIN_CONTROL 0x8049 -#define SP_SPDIN_FIFOPTR 0x804A -#define SP_SPDOUT_STATUS 0x804C -#define SP_SPDOUT_CONTROL 0x804D -#define SP_SPDOUT_CSUV 0x808E - -static inline u8 _wrap_all_bits (u8 val) -{ - u8 wrapped; - - /* wrap all 8 bits */ - wrapped = - ((val & 0x1 ) << 7) | - ((val & 0x2 ) << 5) | - ((val & 0x4 ) << 3) | - ((val & 0x8 ) << 1) | - ((val & 0x10) >> 1) | - ((val & 0x20) >> 3) | - ((val & 0x40) >> 5) | - ((val & 0x80) >> 7); - - return wrapped; -} - -static inline void cs46xx_dsp_spos_update_scb (struct snd_cs46xx * chip, - struct dsp_scb_descriptor * scb) -{ - /* update nextSCB and subListPtr in SCB */ - snd_cs46xx_poke(chip, - (scb->address + SCBsubListPtr) << 2, - (scb->sub_list_ptr->address << 0x10) | - (scb->next_scb_ptr->address)); - scb->updated = 1; -} - -static inline void cs46xx_dsp_scb_set_volume (struct snd_cs46xx * chip, - struct dsp_scb_descriptor * scb, - u16 left, u16 right) -{ - unsigned int val = ((0xffff - left) << 16 | (0xffff - right)); - - snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl) << 2, val); - snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl + 1) << 2, val); - scb->volume_set = 1; - scb->volume[0] = left; - scb->volume[1] = right; -} -#endif /* __DSP_SPOS_H__ */ -#endif /* CONFIG_SND_CS46XX_NEW_DSP */ diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos_scb_lib.c b/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos_scb_lib.c deleted file mode 100644 index 00b148a1..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ /dev/null @@ -1,1784 +0,0 @@ -/* - * - * 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 - * - */ - -/* - * 2002-07 Benny Sjostrand benny@hostmobility.com - */ - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "cs46xx_lib.h" -#include "dsp_spos.h" - -struct proc_scb_info { - struct dsp_scb_descriptor * scb_desc; - struct snd_cs46xx *chip; -}; - -static void remove_symbol (struct snd_cs46xx * chip, struct dsp_symbol_entry * symbol) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - int symbol_index = (int)(symbol - ins->symbol_table.symbols); - - if (snd_BUG_ON(ins->symbol_table.nsymbols <= 0)) - return; - if (snd_BUG_ON(symbol_index < 0 || - symbol_index >= ins->symbol_table.nsymbols)) - return; - - ins->symbol_table.symbols[symbol_index].deleted = 1; - - if (symbol_index < ins->symbol_table.highest_frag_index) { - ins->symbol_table.highest_frag_index = symbol_index; - } - - if (symbol_index == ins->symbol_table.nsymbols - 1) - ins->symbol_table.nsymbols --; - - if (ins->symbol_table.highest_frag_index > ins->symbol_table.nsymbols) { - ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols; - } - -} - -#ifdef CONFIG_PROC_FS -static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct proc_scb_info * scb_info = entry->private_data; - struct dsp_scb_descriptor * scb = scb_info->scb_desc; - struct dsp_spos_instance * ins; - struct snd_cs46xx *chip = scb_info->chip; - int j,col; - void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET; - - ins = chip->dsp_spos_instance; - - mutex_lock(&chip->spos_mutex); - snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name); - - for (col = 0,j = 0;j < 0x10; j++,col++) { - if (col == 4) { - snd_iprintf(buffer,"\n"); - col = 0; - } - snd_iprintf(buffer,"%08x ",readl(dst + (scb->address + j) * sizeof(u32))); - } - - snd_iprintf(buffer,"\n"); - - if (scb->parent_scb_ptr != NULL) { - snd_iprintf(buffer,"parent [%s:%04x] ", - scb->parent_scb_ptr->scb_name, - scb->parent_scb_ptr->address); - } else snd_iprintf(buffer,"parent [none] "); - - snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x] task_entry [%s:%04x]\n", - scb->sub_list_ptr->scb_name, - scb->sub_list_ptr->address, - scb->next_scb_ptr->scb_name, - scb->next_scb_ptr->address, - scb->task_entry->symbol_name, - scb->task_entry->address); - - snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count); - mutex_unlock(&chip->spos_mutex); -} -#endif - -static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if ( scb->parent_scb_ptr ) { - /* unlink parent SCB */ - if (snd_BUG_ON(scb->parent_scb_ptr->sub_list_ptr != scb && - scb->parent_scb_ptr->next_scb_ptr != scb)) - return; - - if (scb->parent_scb_ptr->sub_list_ptr == scb) { - - if (scb->next_scb_ptr == ins->the_null_scb) { - /* last and only node in parent sublist */ - scb->parent_scb_ptr->sub_list_ptr = scb->sub_list_ptr; - - if (scb->sub_list_ptr != ins->the_null_scb) { - scb->sub_list_ptr->parent_scb_ptr = scb->parent_scb_ptr; - } - scb->sub_list_ptr = ins->the_null_scb; - } else { - /* first node in parent sublist */ - scb->parent_scb_ptr->sub_list_ptr = scb->next_scb_ptr; - - if (scb->next_scb_ptr != ins->the_null_scb) { - /* update next node parent ptr. */ - scb->next_scb_ptr->parent_scb_ptr = scb->parent_scb_ptr; - } - scb->next_scb_ptr = ins->the_null_scb; - } - } else { - scb->parent_scb_ptr->next_scb_ptr = scb->next_scb_ptr; - - if (scb->next_scb_ptr != ins->the_null_scb) { - /* update next node parent ptr. */ - scb->next_scb_ptr->parent_scb_ptr = scb->parent_scb_ptr; - } - scb->next_scb_ptr = ins->the_null_scb; - } - - /* update parent first entry in DSP RAM */ - cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr); - - /* then update entry in DSP RAM */ - cs46xx_dsp_spos_update_scb(chip,scb); - - scb->parent_scb_ptr = NULL; - } -} - -static void _dsp_clear_sample_buffer (struct snd_cs46xx *chip, u32 sample_buffer_addr, - int dword_count) -{ - void __iomem *dst = chip->region.idx[2].remap_addr + sample_buffer_addr; - int i; - - for (i = 0; i < dword_count ; ++i ) { - writel(0, dst); - dst += 4; - } -} - -void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - unsigned long flags; - - /* check integrety */ - if (snd_BUG_ON(scb->index < 0 || - scb->index >= ins->nscb || - (ins->scbs + scb->index) != scb)) - return; - -#if 0 - /* can't remove a SCB with childs before - removing childs first */ - if (snd_BUG_ON(scb->sub_list_ptr != ins->the_null_scb || - scb->next_scb_ptr != ins->the_null_scb)) - goto _end; -#endif - - spin_lock_irqsave(&chip->reg_lock, flags); - _dsp_unlink_scb (chip,scb); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - cs46xx_dsp_proc_free_scb_desc(scb); - if (snd_BUG_ON(!scb->scb_symbol)) - return; - remove_symbol (chip,scb->scb_symbol); - - ins->scbs[scb->index].deleted = 1; -#ifdef CONFIG_PM - kfree(ins->scbs[scb->index].data); - ins->scbs[scb->index].data = NULL; -#endif - - if (scb->index < ins->scb_highest_frag_index) - ins->scb_highest_frag_index = scb->index; - - if (scb->index == ins->nscb - 1) { - ins->nscb --; - } - - if (ins->scb_highest_frag_index > ins->nscb) { - ins->scb_highest_frag_index = ins->nscb; - } - -#if 0 - /* !!!! THIS IS A PIECE OF SHIT MADE BY ME !!! */ - for(i = scb->index + 1;i < ins->nscb; ++i) { - ins->scbs[i - 1].index = i - 1; - } -#endif -} - - -#ifdef CONFIG_PROC_FS -void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb) -{ - if (scb->proc_info) { - struct proc_scb_info * scb_info = scb->proc_info->private_data; - - snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name); - - snd_info_free_entry(scb->proc_info); - scb->proc_info = NULL; - - kfree (scb_info); - } -} - -void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip, - struct dsp_scb_descriptor * scb) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct snd_info_entry * entry; - struct proc_scb_info * scb_info; - - /* register to proc */ - if (ins->snd_card != NULL && ins->proc_dsp_dir != NULL && - scb->proc_info == NULL) { - - if ((entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name, - ins->proc_dsp_dir)) != NULL) { - scb_info = kmalloc(sizeof(struct proc_scb_info), GFP_KERNEL); - if (!scb_info) { - snd_info_free_entry(entry); - entry = NULL; - goto out; - } - - scb_info->chip = chip; - scb_info->scb_desc = scb; - - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = scb_info; - entry->mode = S_IFREG | S_IRUGO | S_IWUSR; - - entry->c.text.read = cs46xx_dsp_proc_scb_info_read; - - if (snd_info_register(entry) < 0) { - snd_info_free_entry(entry); - kfree (scb_info); - entry = NULL; - } - } -out: - scb->proc_info = entry; - } -} -#endif /* CONFIG_PROC_FS */ - -static struct dsp_scb_descriptor * -_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest, - struct dsp_symbol_entry * task_entry, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * scb; - - unsigned long flags; - - if (snd_BUG_ON(!ins->the_null_scb)) - return NULL; - - /* fill the data that will be wroten to DSP */ - scb_data[SCBsubListPtr] = - (ins->the_null_scb->address << 0x10) | ins->the_null_scb->address; - - scb_data[SCBfuncEntryPtr] &= 0xFFFF0000; - scb_data[SCBfuncEntryPtr] |= task_entry->address; - - snd_printdd("dsp_spos: creating SCB <%s>\n",name); - - scb = cs46xx_dsp_create_scb(chip,name,scb_data,dest); - - - scb->sub_list_ptr = ins->the_null_scb; - scb->next_scb_ptr = ins->the_null_scb; - - scb->parent_scb_ptr = parent_scb; - scb->task_entry = task_entry; - - - /* update parent SCB */ - if (scb->parent_scb_ptr) { -#if 0 - printk ("scb->parent_scb_ptr = %s\n",scb->parent_scb_ptr->scb_name); - printk ("scb->parent_scb_ptr->next_scb_ptr = %s\n",scb->parent_scb_ptr->next_scb_ptr->scb_name); - printk ("scb->parent_scb_ptr->sub_list_ptr = %s\n",scb->parent_scb_ptr->sub_list_ptr->scb_name); -#endif - /* link to parent SCB */ - if (scb_child_type == SCB_ON_PARENT_NEXT_SCB) { - if (snd_BUG_ON(scb->parent_scb_ptr->next_scb_ptr != - ins->the_null_scb)) - return NULL; - - scb->parent_scb_ptr->next_scb_ptr = scb; - - } else if (scb_child_type == SCB_ON_PARENT_SUBLIST_SCB) { - if (snd_BUG_ON(scb->parent_scb_ptr->sub_list_ptr != - ins->the_null_scb)) - return NULL; - - scb->parent_scb_ptr->sub_list_ptr = scb; - } else { - snd_BUG(); - } - - spin_lock_irqsave(&chip->reg_lock, flags); - - /* update entry in DSP RAM */ - cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr); - - spin_unlock_irqrestore(&chip->reg_lock, flags); - } - - - cs46xx_dsp_proc_register_scb_desc (chip,scb); - - return scb; -} - -static struct dsp_scb_descriptor * -cs46xx_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, - u32 dest, char * task_entry_name, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_symbol_entry * task_entry; - - task_entry = cs46xx_dsp_lookup_symbol (chip,task_entry_name, - SYMBOL_CODE); - - if (task_entry == NULL) { - snd_printk (KERN_ERR "dsp_spos: symbol %s not found\n",task_entry_name); - return NULL; - } - - return _dsp_create_generic_scb (chip,name,scb_data,dest,task_entry, - parent_scb,scb_child_type); -} - -struct dsp_scb_descriptor * -cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip) -{ - struct dsp_scb_descriptor * scb; - - struct dsp_timing_master_scb timing_master_scb = { - { 0, - 0, - 0, - 0 - }, - { 0, - 0, - 0, - 0, - 0 - }, - 0,0, - 0,NULL_SCB_ADDR, - 0,0, /* extraSampleAccum:TMreserved */ - 0,0, /* codecFIFOptr:codecFIFOsyncd */ - 0x0001,0x8000, /* fracSampAccumQm1:TMfrmsLeftInGroup */ - 0x0001,0x0000, /* fracSampCorrectionQm1:TMfrmGroupLength */ - 0x00060000 /* nSampPerFrmQ15 */ - }; - - scb = cs46xx_dsp_create_generic_scb(chip,"TimingMasterSCBInst",(u32 *)&timing_master_scb, - TIMINGMASTER_SCB_ADDR, - "TIMINGMASTER",NULL,SCB_NO_PARENT); - - return scb; -} - - -struct dsp_scb_descriptor * -cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip, char * codec_name, - u16 channel_disp, u16 fifo_addr, u16 child_scb_addr, - u32 dest, struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_scb_descriptor * scb; - - struct dsp_codec_output_scb codec_out_scb = { - { 0, - 0, - 0, - 0 - }, - { - 0, - 0, - 0, - 0, - 0 - }, - 0,0, - 0,NULL_SCB_ADDR, - 0, /* COstrmRsConfig */ - 0, /* COstrmBufPtr */ - channel_disp,fifo_addr, /* leftChanBaseIOaddr:rightChanIOdisp */ - 0x0000,0x0080, /* (!AC97!) COexpVolChangeRate:COscaleShiftCount */ - 0,child_scb_addr /* COreserved - need child scb to work with rom code */ - }; - - - scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_out_scb, - dest,"S16_CODECOUTPUTTASK",parent_scb, - scb_child_type); - - return scb; -} - -struct dsp_scb_descriptor * -cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name, - u16 channel_disp, u16 fifo_addr, u16 sample_buffer_addr, - u32 dest, struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - - struct dsp_scb_descriptor * scb; - struct dsp_codec_input_scb codec_input_scb = { - { 0, - 0, - 0, - 0 - }, - { - 0, - 0, - 0, - 0, - 0 - }, - -#if 0 /* cs4620 */ - SyncIOSCB,NULL_SCB_ADDR -#else - 0 , 0, -#endif - 0,0, - - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, /* strmRsConfig */ - sample_buffer_addr << 0x10, /* strmBufPtr; defined as a dword ptr, used as a byte ptr */ - channel_disp,fifo_addr, /* (!AC97!) leftChanBaseINaddr=AC97primary - link input slot 3 :rightChanINdisp=""slot 4 */ - 0x0000,0x0000, /* (!AC97!) ????:scaleShiftCount; no shift needed - because AC97 is already 20 bits */ - 0x80008000 /* ??clw cwcgame.scb has 0 */ - }; - - scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_input_scb, - dest,"S16_CODECINPUTTASK",parent_scb, - scb_child_type); - return scb; -} - - -static struct dsp_scb_descriptor * -cs46xx_dsp_create_pcm_reader_scb(struct snd_cs46xx * chip, char * scb_name, - u16 sample_buffer_addr, u32 dest, - int virtual_channel, u32 playback_hw_addr, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * scb; - - struct dsp_generic_scb pcm_reader_scb = { - - /* - Play DMA Task xfers data from host buffer to SP buffer - init/runtime variables: - PlayAC: Play Audio Data Conversion - SCB loc: 2nd dword, mask: 0x0000F000L - DATA_FMT_16BIT_ST_LTLEND(0x00000000L) from 16-bit stereo, little-endian - DATA_FMT_8_BIT_ST_SIGNED(0x00001000L) from 8-bit stereo, signed - DATA_FMT_16BIT_MN_LTLEND(0x00002000L) from 16-bit mono, little-endian - DATA_FMT_8_BIT_MN_SIGNED(0x00003000L) from 8-bit mono, signed - DATA_FMT_16BIT_ST_BIGEND(0x00004000L) from 16-bit stereo, big-endian - DATA_FMT_16BIT_MN_BIGEND(0x00006000L) from 16-bit mono, big-endian - DATA_FMT_8_BIT_ST_UNSIGNED(0x00009000L) from 8-bit stereo, unsigned - DATA_FMT_8_BIT_MN_UNSIGNED(0x0000b000L) from 8-bit mono, unsigned - ? Other combinations possible from: - DMA_RQ_C2_AUDIO_CONVERT_MASK 0x0000F000L - DMA_RQ_C2_AC_NONE 0x00000000L - DMA_RQ_C2_AC_8_TO_16_BIT 0x00001000L - DMA_RQ_C2_AC_MONO_TO_STEREO 0x00002000L - DMA_RQ_C2_AC_ENDIAN_CONVERT 0x00004000L - DMA_RQ_C2_AC_SIGNED_CONVERT 0x00008000L - - HostBuffAddr: Host Buffer Physical Byte Address - SCB loc:3rd dword, Mask: 0xFFFFFFFFL - aligned to dword boundary - */ - /* Basic (non scatter/gather) DMA requestor (4 ints) */ - { DMA_RQ_C1_SOURCE_ON_HOST + /* source buffer is on the host */ - DMA_RQ_C1_SOURCE_MOD1024 + /* source buffer is 1024 dwords (4096 bytes) */ - DMA_RQ_C1_DEST_MOD32 + /* dest buffer(PCMreaderBuf) is 32 dwords*/ - DMA_RQ_C1_WRITEBACK_SRC_FLAG + /* ?? */ - DMA_RQ_C1_WRITEBACK_DEST_FLAG + /* ?? */ - 15, /* DwordCount-1: picked 16 for DwordCount because Jim */ - /* Barnette said that is what we should use since */ - /* we are not running in optimized mode? */ - DMA_RQ_C2_AC_NONE + - DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG + /* set play interrupt (bit0) in HISR when source */ - /* buffer (on host) crosses half-way point */ - virtual_channel, /* Play DMA channel arbitrarily set to 0 */ - playback_hw_addr, /* HostBuffAddr (source) */ - DMA_RQ_SD_SP_SAMPLE_ADDR + /* destination buffer is in SP Sample Memory */ - sample_buffer_addr /* SP Buffer Address (destination) */ - }, - /* Scatter/gather DMA requestor extension (5 ints) */ - { - 0, - 0, - 0, - 0, - 0 - }, - /* Sublist pointer & next stream control block (SCB) link. */ - NULL_SCB_ADDR,NULL_SCB_ADDR, - /* Pointer to this tasks parameter block & stream function pointer */ - 0,NULL_SCB_ADDR, - /* rsConfig register for stream buffer (rsDMA reg. is loaded from basicReq.daw */ - /* for incoming streams, or basicReq.saw, for outgoing streams) */ - RSCONFIG_DMA_ENABLE + /* enable DMA */ - (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + /* MAX_DMA_SIZE picked to be 19 since SPUD */ - /* uses it for some reason */ - ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) + /* stream number = SCBaddr/16 */ - RSCONFIG_SAMPLE_16STEREO + - RSCONFIG_MODULO_32, /* dest buffer(PCMreaderBuf) is 32 dwords (256 bytes) */ - /* Stream sample pointer & MAC-unit mode for this stream */ - (sample_buffer_addr << 0x10), - /* Fractional increment per output sample in the input sample buffer */ - 0, - { - /* Standard stereo volume control - default muted */ - 0xffff,0xffff, - 0xffff,0xffff - } - }; - - if (ins->null_algorithm == NULL) { - ins->null_algorithm = cs46xx_dsp_lookup_symbol (chip,"NULLALGORITHM", - SYMBOL_CODE); - - if (ins->null_algorithm == NULL) { - snd_printk (KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n"); - return NULL; - } - } - - scb = _dsp_create_generic_scb(chip,scb_name,(u32 *)&pcm_reader_scb, - dest,ins->null_algorithm,parent_scb, - scb_child_type); - - return scb; -} - -#define GOF_PER_SEC 200 - -struct dsp_scb_descriptor * -cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name, - int rate, - u16 src_buffer_addr, - u16 src_delay_buffer_addr, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type, - int pass_through) -{ - - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * scb; - unsigned int tmp1, tmp2; - unsigned int phiIncr; - unsigned int correctionPerGOF, correctionPerSec; - - snd_printdd( "dsp_spos: setting %s rate to %u\n",scb_name,rate); - - /* - * Compute the values used to drive the actual sample rate conversion. - * The following formulas are being computed, using inline assembly - * since we need to use 64 bit arithmetic to compute the values: - * - * phiIncr = floor((Fs,in * 2^26) / Fs,out) - * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) / - * GOF_PER_SEC) - * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M - * GOF_PER_SEC * correctionPerGOF - * - * i.e. - * - * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out) - * correctionPerGOF:correctionPerSec = - * dividend:remainder(ulOther / GOF_PER_SEC) - */ - tmp1 = rate << 16; - phiIncr = tmp1 / 48000; - tmp1 -= phiIncr * 48000; - tmp1 <<= 10; - phiIncr <<= 10; - tmp2 = tmp1 / 48000; - phiIncr += tmp2; - tmp1 -= tmp2 * 48000; - correctionPerGOF = tmp1 / GOF_PER_SEC; - tmp1 -= correctionPerGOF * GOF_PER_SEC; - correctionPerSec = tmp1; - - { - struct dsp_src_task_scb src_task_scb = { - 0x0028,0x00c8, - 0x5555,0x0000, - 0x0000,0x0000, - src_buffer_addr,1, - correctionPerGOF,correctionPerSec, - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32, - 0x0000,src_delay_buffer_addr, - 0x0, - 0x080,(src_delay_buffer_addr + (24 * 4)), - 0,0, /* next_scb, sub_list_ptr */ - 0,0, /* entry, this_spb */ - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8, - src_buffer_addr << 0x10, - phiIncr, - { - 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left, - 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left - } - }; - - if (ins->s16_up == NULL) { - ins->s16_up = cs46xx_dsp_lookup_symbol (chip,"S16_UPSRC", - SYMBOL_CODE); - - if (ins->s16_up == NULL) { - snd_printk (KERN_ERR "dsp_spos: symbol S16_UPSRC not found\n"); - return NULL; - } - } - - /* clear buffers */ - _dsp_clear_sample_buffer (chip,src_buffer_addr,8); - _dsp_clear_sample_buffer (chip,src_delay_buffer_addr,32); - - if (pass_through) { - /* wont work with any other rate than - the native DSP rate */ - snd_BUG_ON(rate != 48000); - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb, - dest,"DMAREADER",parent_scb, - scb_child_type); - } else { - scb = _dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb, - dest,ins->s16_up,parent_scb, - scb_child_type); - } - - - } - - return scb; -} - -#if 0 /* not used */ -struct dsp_scb_descriptor * -cs46xx_dsp_create_filter_scb(struct snd_cs46xx * chip, char * scb_name, - u16 buffer_addr, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) { - struct dsp_scb_descriptor * scb; - - struct dsp_filter_scb filter_scb = { - .a0_right = 0x41a9, - .a0_left = 0x41a9, - .a1_right = 0xb8e4, - .a1_left = 0xb8e4, - .a2_right = 0x3e55, - .a2_left = 0x3e55, - - .filter_unused3 = 0x0000, - .filter_unused2 = 0x0000, - - .output_buf_ptr = buffer_addr, - .init = 0x000, - - .prev_sample_output1 = 0x00000000, - .prev_sample_output2 = 0x00000000, - - .prev_sample_input1 = 0x00000000, - .prev_sample_input2 = 0x00000000, - - .next_scb_ptr = 0x0000, - .sub_list_ptr = 0x0000, - - .entry_point = 0x0000, - .spb_ptr = 0x0000, - - .b0_right = 0x0e38, - .b0_left = 0x0e38, - .b1_right = 0x1c71, - .b1_left = 0x1c71, - .b2_right = 0x0e38, - .b2_left = 0x0e38, - }; - - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&filter_scb, - dest,"FILTERTASK",parent_scb, - scb_child_type); - - return scb; -} -#endif /* not used */ - -struct dsp_scb_descriptor * -cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name, - u16 mix_buffer_addr, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_scb_descriptor * scb; - - struct dsp_mix_only_scb master_mix_scb = { - /* 0 */ { 0, - /* 1 */ 0, - /* 2 */ mix_buffer_addr, - /* 3 */ 0 - /* */ }, - { - /* 4 */ 0, - /* 5 */ 0, - /* 6 */ 0, - /* 7 */ 0, - /* 8 */ 0x00000080 - }, - /* 9 */ 0,0, - /* A */ 0,0, - /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32, - /* C */ (mix_buffer_addr + (16 * 4)) << 0x10, - /* D */ 0, - { - /* E */ 0x8000,0x8000, - /* F */ 0x8000,0x8000 - } - }; - - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&master_mix_scb, - dest,"S16_MIX",parent_scb, - scb_child_type); - return scb; -} - - -struct dsp_scb_descriptor * -cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name, - u16 mix_buffer_addr, u16 writeback_spb, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_scb_descriptor * scb; - - struct dsp_mix2_ostream_scb mix2_ostream_scb = { - /* Basic (non scatter/gather) DMA requestor (4 ints) */ - { - DMA_RQ_C1_SOURCE_MOD64 + - DMA_RQ_C1_DEST_ON_HOST + - DMA_RQ_C1_DEST_MOD1024 + - DMA_RQ_C1_WRITEBACK_SRC_FLAG + - DMA_RQ_C1_WRITEBACK_DEST_FLAG + - 15, - - DMA_RQ_C2_AC_NONE + - DMA_RQ_C2_SIGNAL_DEST_PINGPONG + - - CS46XX_DSP_CAPTURE_CHANNEL, - DMA_RQ_SD_SP_SAMPLE_ADDR + - mix_buffer_addr, - 0x0 - }, - - { 0, 0, 0, 0, 0, }, - 0,0, - 0,writeback_spb, - - RSCONFIG_DMA_ENABLE + - (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + - - ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) + - RSCONFIG_DMA_TO_HOST + - RSCONFIG_SAMPLE_16STEREO + - RSCONFIG_MODULO_64, - (mix_buffer_addr + (32 * 4)) << 0x10, - 1,0, - 0x0001,0x0080, - 0xFFFF,0 - }; - - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&mix2_ostream_scb, - - dest,"S16_MIX_TO_OSTREAM",parent_scb, - scb_child_type); - - return scb; -} - - -struct dsp_scb_descriptor * -cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip,char * scb_name, - u16 vari_buffer_addr0, - u16 vari_buffer_addr1, - u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - - struct dsp_scb_descriptor * scb; - - struct dsp_vari_decimate_scb vari_decimate_scb = { - 0x0028,0x00c8, - 0x5555,0x0000, - 0x0000,0x0000, - vari_buffer_addr0,vari_buffer_addr1, - - 0x0028,0x00c8, - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256, - - 0xFF800000, - 0, - 0x0080,vari_buffer_addr1 + (25 * 4), - - 0,0, - 0,0, - - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8, - vari_buffer_addr0 << 0x10, - 0x04000000, - { - 0x8000,0x8000, - 0xFFFF,0xFFFF - } - }; - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&vari_decimate_scb, - dest,"VARIDECIMATE",parent_scb, - scb_child_type); - - return scb; -} - - -static struct dsp_scb_descriptor * -cs46xx_dsp_create_pcm_serial_input_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, - struct dsp_scb_descriptor * input_scb, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - - struct dsp_scb_descriptor * scb; - - - struct dsp_pcm_serial_input_scb pcm_serial_input_scb = { - { 0, - 0, - 0, - 0 - }, - { - 0, - 0, - 0, - 0, - 0 - }, - - 0,0, - 0,0, - - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_16, - 0, - /* 0xD */ 0,input_scb->address, - { - /* 0xE */ 0x8000,0x8000, - /* 0xF */ 0x8000,0x8000 - } - }; - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&pcm_serial_input_scb, - dest,"PCMSERIALINPUTTASK",parent_scb, - scb_child_type); - return scb; -} - - -static struct dsp_scb_descriptor * -cs46xx_dsp_create_asynch_fg_tx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, - u16 hfg_scb_address, - u16 asynch_buffer_address, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - - struct dsp_scb_descriptor * scb; - - struct dsp_asynch_fg_tx_scb asynch_fg_tx_scb = { - 0xfc00,0x03ff, /* Prototype sample buffer size of 256 dwords */ - 0x0058,0x0028, /* Min Delta 7 dwords == 28 bytes */ - /* : Max delta 25 dwords == 100 bytes */ - 0,hfg_scb_address, /* Point to HFG task SCB */ - 0,0, /* Initialize current Delta and Consumer ptr adjustment count */ - 0, /* Initialize accumulated Phi to 0 */ - 0,0x2aab, /* Const 1/3 */ - - { - 0, /* Define the unused elements */ - 0, - 0 - }, - - 0,0, - 0,dest + AFGTxAccumPhi, - - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256, /* Stereo, 256 dword */ - (asynch_buffer_address) << 0x10, /* This should be automagically synchronized - to the producer pointer */ - - /* There is no correct initial value, it will depend upon the detected - rate etc */ - 0x18000000, /* Phi increment for approx 32k operation */ - 0x8000,0x8000, /* Volume controls are unused at this time */ - 0x8000,0x8000 - }; - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_tx_scb, - dest,"ASYNCHFGTXCODE",parent_scb, - scb_child_type); - - return scb; -} - - -struct dsp_scb_descriptor * -cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, - u16 hfg_scb_address, - u16 asynch_buffer_address, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * scb; - - struct dsp_asynch_fg_rx_scb asynch_fg_rx_scb = { - 0xfe00,0x01ff, /* Prototype sample buffer size of 128 dwords */ - 0x0064,0x001c, /* Min Delta 7 dwords == 28 bytes */ - /* : Max delta 25 dwords == 100 bytes */ - 0,hfg_scb_address, /* Point to HFG task SCB */ - 0,0, /* Initialize current Delta and Consumer ptr adjustment count */ - { - 0, /* Define the unused elements */ - 0, - 0, - 0, - 0 - }, - - 0,0, - 0,dest, - - RSCONFIG_MODULO_128 | - RSCONFIG_SAMPLE_16STEREO, /* Stereo, 128 dword */ - ( (asynch_buffer_address + (16 * 4)) << 0x10), /* This should be automagically - synchrinized to the producer pointer */ - - /* There is no correct initial value, it will depend upon the detected - rate etc */ - 0x18000000, - - /* Set IEC958 input volume */ - 0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left, - 0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left, - }; - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_rx_scb, - dest,"ASYNCHFGRXCODE",parent_scb, - scb_child_type); - - return scb; -} - - -#if 0 /* not used */ -struct dsp_scb_descriptor * -cs46xx_dsp_create_output_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, - u16 snoop_buffer_address, - struct dsp_scb_descriptor * snoop_scb, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - - struct dsp_scb_descriptor * scb; - - struct dsp_output_snoop_scb output_snoop_scb = { - { 0, /* not used. Zero */ - 0, - 0, - 0, - }, - { - 0, /* not used. Zero */ - 0, - 0, - 0, - 0 - }, - - 0,0, - 0,0, - - RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, - snoop_buffer_address << 0x10, - 0,0, - 0, - 0,snoop_scb->address - }; - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&output_snoop_scb, - dest,"OUTPUTSNOOP",parent_scb, - scb_child_type); - return scb; -} -#endif /* not used */ - - -struct dsp_scb_descriptor * -cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_scb_descriptor * scb; - - struct dsp_spio_write_scb spio_write_scb = { - 0,0, /* SPIOWAddress2:SPIOWAddress1; */ - 0, /* SPIOWData1; */ - 0, /* SPIOWData2; */ - 0,0, /* SPIOWAddress4:SPIOWAddress3; */ - 0, /* SPIOWData3; */ - 0, /* SPIOWData4; */ - 0,0, /* SPIOWDataPtr:Unused1; */ - { 0,0 }, /* Unused2[2]; */ - - 0,0, /* SPIOWChildPtr:SPIOWSiblingPtr; */ - 0,0, /* SPIOWThisPtr:SPIOWEntryPoint; */ - - { - 0, - 0, - 0, - 0, - 0 /* Unused3[5]; */ - } - }; - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&spio_write_scb, - dest,"SPIOWRITE",parent_scb, - scb_child_type); - - return scb; -} - -struct dsp_scb_descriptor * -cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest, - u16 snoop_buffer_address, - struct dsp_scb_descriptor * snoop_scb, - struct dsp_scb_descriptor * parent_scb, - int scb_child_type) -{ - struct dsp_scb_descriptor * scb; - - struct dsp_magic_snoop_task magic_snoop_scb = { - /* 0 */ 0, /* i0 */ - /* 1 */ 0, /* i1 */ - /* 2 */ snoop_buffer_address << 0x10, - /* 3 */ 0,snoop_scb->address, - /* 4 */ 0, /* i3 */ - /* 5 */ 0, /* i4 */ - /* 6 */ 0, /* i5 */ - /* 7 */ 0, /* i6 */ - /* 8 */ 0, /* i7 */ - /* 9 */ 0,0, /* next_scb, sub_list_ptr */ - /* A */ 0,0, /* entry_point, this_ptr */ - /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64, - /* C */ snoop_buffer_address << 0x10, - /* D */ 0, - /* E */ { 0x8000,0x8000, - /* F */ 0xffff,0xffff - } - }; - - scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&magic_snoop_scb, - dest,"MAGICSNOOPTASK",parent_scb, - scb_child_type); - - return scb; -} - -static struct dsp_scb_descriptor * -find_next_free_scb (struct snd_cs46xx * chip, struct dsp_scb_descriptor * from) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * scb = from; - - while (scb->next_scb_ptr != ins->the_null_scb) { - if (snd_BUG_ON(!scb->next_scb_ptr)) - return NULL; - - scb = scb->next_scb_ptr; - } - - return scb; -} - -static u32 pcm_reader_buffer_addr[DSP_MAX_PCM_CHANNELS] = { - 0x0600, /* 1 */ - 0x1500, /* 2 */ - 0x1580, /* 3 */ - 0x1600, /* 4 */ - 0x1680, /* 5 */ - 0x1700, /* 6 */ - 0x1780, /* 7 */ - 0x1800, /* 8 */ - 0x1880, /* 9 */ - 0x1900, /* 10 */ - 0x1980, /* 11 */ - 0x1A00, /* 12 */ - 0x1A80, /* 13 */ - 0x1B00, /* 14 */ - 0x1B80, /* 15 */ - 0x1C00, /* 16 */ - 0x1C80, /* 17 */ - 0x1D00, /* 18 */ - 0x1D80, /* 19 */ - 0x1E00, /* 20 */ - 0x1E80, /* 21 */ - 0x1F00, /* 22 */ - 0x1F80, /* 23 */ - 0x2000, /* 24 */ - 0x2080, /* 25 */ - 0x2100, /* 26 */ - 0x2180, /* 27 */ - 0x2200, /* 28 */ - 0x2280, /* 29 */ - 0x2300, /* 30 */ - 0x2380, /* 31 */ - 0x2400, /* 32 */ -}; - -static u32 src_output_buffer_addr[DSP_MAX_SRC_NR] = { - 0x2B80, - 0x2BA0, - 0x2BC0, - 0x2BE0, - 0x2D00, - 0x2D20, - 0x2D40, - 0x2D60, - 0x2D80, - 0x2DA0, - 0x2DC0, - 0x2DE0, - 0x2E00, - 0x2E20 -}; - -static u32 src_delay_buffer_addr[DSP_MAX_SRC_NR] = { - 0x2480, - 0x2500, - 0x2580, - 0x2600, - 0x2680, - 0x2700, - 0x2780, - 0x2800, - 0x2880, - 0x2900, - 0x2980, - 0x2A00, - 0x2A80, - 0x2B00 -}; - -struct dsp_pcm_channel_descriptor * -cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, - u32 sample_rate, void * private_data, - u32 hw_dma_addr, - int pcm_channel_id) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * src_scb = NULL, * pcm_scb, * mixer_scb = NULL; - struct dsp_scb_descriptor * src_parent_scb = NULL; - - /* struct dsp_scb_descriptor * pcm_parent_scb; */ - char scb_name[DSP_MAX_SCB_NAME]; - int i, pcm_index = -1, insert_point, src_index = -1, pass_through = 0; - unsigned long flags; - - switch (pcm_channel_id) { - case DSP_PCM_MAIN_CHANNEL: - mixer_scb = ins->master_mix_scb; - break; - case DSP_PCM_REAR_CHANNEL: - mixer_scb = ins->rear_mix_scb; - break; - case DSP_PCM_CENTER_LFE_CHANNEL: - mixer_scb = ins->center_lfe_mix_scb; - break; - case DSP_PCM_S71_CHANNEL: - /* TODO */ - snd_BUG(); - break; - case DSP_IEC958_CHANNEL: - if (snd_BUG_ON(!ins->asynch_tx_scb)) - return NULL; - mixer_scb = ins->asynch_tx_scb; - - /* if sample rate is set to 48khz we pass - the Sample Rate Converted (which could - alter the raw data stream ...) */ - if (sample_rate == 48000) { - snd_printdd ("IEC958 pass through\n"); - /* Hack to bypass creating a new SRC */ - pass_through = 1; - } - break; - default: - snd_BUG(); - return NULL; - } - /* default sample rate is 44100 */ - if (!sample_rate) sample_rate = 44100; - - /* search for a already created SRC SCB with the same sample rate */ - for (i = 0; i < DSP_MAX_PCM_CHANNELS && - (pcm_index == -1 || src_scb == NULL); ++i) { - - /* virtual channel reserved - for capture */ - if (i == CS46XX_DSP_CAPTURE_CHANNEL) continue; - - if (ins->pcm_channels[i].active) { - if (!src_scb && - ins->pcm_channels[i].sample_rate == sample_rate && - ins->pcm_channels[i].mixer_scb == mixer_scb) { - src_scb = ins->pcm_channels[i].src_scb; - ins->pcm_channels[i].src_scb->ref_count ++; - src_index = ins->pcm_channels[i].src_slot; - } - } else if (pcm_index == -1) { - pcm_index = i; - } - } - - if (pcm_index == -1) { - snd_printk (KERN_ERR "dsp_spos: no free PCM channel\n"); - return NULL; - } - - if (src_scb == NULL) { - if (ins->nsrc_scb >= DSP_MAX_SRC_NR) { - snd_printk(KERN_ERR "dsp_spos: to many SRC instances\n!"); - return NULL; - } - - /* find a free slot */ - for (i = 0; i < DSP_MAX_SRC_NR; ++i) { - if (ins->src_scb_slots[i] == 0) { - src_index = i; - ins->src_scb_slots[i] = 1; - break; - } - } - if (snd_BUG_ON(src_index == -1)) - return NULL; - - /* we need to create a new SRC SCB */ - if (mixer_scb->sub_list_ptr == ins->the_null_scb) { - src_parent_scb = mixer_scb; - insert_point = SCB_ON_PARENT_SUBLIST_SCB; - } else { - src_parent_scb = find_next_free_scb(chip,mixer_scb->sub_list_ptr); - insert_point = SCB_ON_PARENT_NEXT_SCB; - } - - snprintf (scb_name,DSP_MAX_SCB_NAME,"SrcTask_SCB%d",src_index); - - snd_printdd( "dsp_spos: creating SRC \"%s\"\n",scb_name); - src_scb = cs46xx_dsp_create_src_task_scb(chip,scb_name, - sample_rate, - src_output_buffer_addr[src_index], - src_delay_buffer_addr[src_index], - /* 0x400 - 0x600 source SCBs */ - 0x400 + (src_index * 0x10) , - src_parent_scb, - insert_point, - pass_through); - - if (!src_scb) { - snd_printk (KERN_ERR "dsp_spos: failed to create SRCtaskSCB\n"); - return NULL; - } - - /* cs46xx_dsp_set_src_sample_rate(chip,src_scb,sample_rate); */ - - ins->nsrc_scb ++; - } - - - snprintf (scb_name,DSP_MAX_SCB_NAME,"PCMReader_SCB%d",pcm_index); - - snd_printdd( "dsp_spos: creating PCM \"%s\" (%d)\n",scb_name, - pcm_channel_id); - - pcm_scb = cs46xx_dsp_create_pcm_reader_scb(chip,scb_name, - pcm_reader_buffer_addr[pcm_index], - /* 0x200 - 400 PCMreader SCBs */ - (pcm_index * 0x10) + 0x200, - pcm_index, /* virtual channel 0-31 */ - hw_dma_addr, /* pcm hw addr */ - NULL, /* parent SCB ptr */ - 0 /* insert point */ - ); - - if (!pcm_scb) { - snd_printk (KERN_ERR "dsp_spos: failed to create PCMreaderSCB\n"); - return NULL; - } - - spin_lock_irqsave(&chip->reg_lock, flags); - ins->pcm_channels[pcm_index].sample_rate = sample_rate; - ins->pcm_channels[pcm_index].pcm_reader_scb = pcm_scb; - ins->pcm_channels[pcm_index].src_scb = src_scb; - ins->pcm_channels[pcm_index].unlinked = 1; - ins->pcm_channels[pcm_index].private_data = private_data; - ins->pcm_channels[pcm_index].src_slot = src_index; - ins->pcm_channels[pcm_index].active = 1; - ins->pcm_channels[pcm_index].pcm_slot = pcm_index; - ins->pcm_channels[pcm_index].mixer_scb = mixer_scb; - ins->npcm_channels ++; - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return (ins->pcm_channels + pcm_index); -} - -int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip, - struct dsp_pcm_channel_descriptor * pcm_channel, - int period_size) -{ - u32 temp = snd_cs46xx_peek (chip,pcm_channel->pcm_reader_scb->address << 2); - temp &= ~DMA_RQ_C1_SOURCE_SIZE_MASK; - - switch (period_size) { - case 2048: - temp |= DMA_RQ_C1_SOURCE_MOD1024; - break; - case 1024: - temp |= DMA_RQ_C1_SOURCE_MOD512; - break; - case 512: - temp |= DMA_RQ_C1_SOURCE_MOD256; - break; - case 256: - temp |= DMA_RQ_C1_SOURCE_MOD128; - break; - case 128: - temp |= DMA_RQ_C1_SOURCE_MOD64; - break; - case 64: - temp |= DMA_RQ_C1_SOURCE_MOD32; - break; - case 32: - temp |= DMA_RQ_C1_SOURCE_MOD16; - break; - default: - snd_printdd ("period size (%d) not supported by HW\n", period_size); - return -EINVAL; - } - - snd_cs46xx_poke (chip,pcm_channel->pcm_reader_scb->address << 2,temp); - - return 0; -} - -int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip, - int period_size) -{ - u32 temp = snd_cs46xx_peek (chip,WRITEBACK_SCB_ADDR << 2); - temp &= ~DMA_RQ_C1_DEST_SIZE_MASK; - - switch (period_size) { - case 2048: - temp |= DMA_RQ_C1_DEST_MOD1024; - break; - case 1024: - temp |= DMA_RQ_C1_DEST_MOD512; - break; - case 512: - temp |= DMA_RQ_C1_DEST_MOD256; - break; - case 256: - temp |= DMA_RQ_C1_DEST_MOD128; - break; - case 128: - temp |= DMA_RQ_C1_DEST_MOD64; - break; - case 64: - temp |= DMA_RQ_C1_DEST_MOD32; - break; - case 32: - temp |= DMA_RQ_C1_DEST_MOD16; - break; - default: - snd_printdd ("period size (%d) not supported by HW\n", period_size); - return -EINVAL; - } - - snd_cs46xx_poke (chip,WRITEBACK_SCB_ADDR << 2,temp); - - return 0; -} - -void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip, - struct dsp_pcm_channel_descriptor * pcm_channel) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - unsigned long flags; - - if (snd_BUG_ON(!pcm_channel->active || - ins->npcm_channels <= 0 || - pcm_channel->src_scb->ref_count <= 0)) - return; - - spin_lock_irqsave(&chip->reg_lock, flags); - pcm_channel->unlinked = 1; - pcm_channel->active = 0; - pcm_channel->private_data = NULL; - pcm_channel->src_scb->ref_count --; - ins->npcm_channels --; - spin_unlock_irqrestore(&chip->reg_lock, flags); - - cs46xx_dsp_remove_scb(chip,pcm_channel->pcm_reader_scb); - - if (!pcm_channel->src_scb->ref_count) { - cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb); - - if (snd_BUG_ON(pcm_channel->src_slot < 0 || - pcm_channel->src_slot >= DSP_MAX_SRC_NR)) - return; - - ins->src_scb_slots[pcm_channel->src_slot] = 0; - ins->nsrc_scb --; - } -} - -int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip, - struct dsp_pcm_channel_descriptor * pcm_channel) -{ - unsigned long flags; - - if (snd_BUG_ON(!pcm_channel->active || - chip->dsp_spos_instance->npcm_channels <= 0)) - return -EIO; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (pcm_channel->unlinked) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -EIO; - } - - pcm_channel->unlinked = 1; - - _dsp_unlink_scb (chip,pcm_channel->pcm_reader_scb); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return 0; -} - -int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip, - struct dsp_pcm_channel_descriptor * pcm_channel) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * parent_scb; - struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - - if (pcm_channel->unlinked == 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -EIO; - } - - parent_scb = src_scb; - - if (src_scb->sub_list_ptr != ins->the_null_scb) { - src_scb->sub_list_ptr->parent_scb_ptr = pcm_channel->pcm_reader_scb; - pcm_channel->pcm_reader_scb->next_scb_ptr = src_scb->sub_list_ptr; - } - - src_scb->sub_list_ptr = pcm_channel->pcm_reader_scb; - - snd_BUG_ON(pcm_channel->pcm_reader_scb->parent_scb_ptr); - pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb; - - /* update SCB entry in DSP RAM */ - cs46xx_dsp_spos_update_scb(chip,pcm_channel->pcm_reader_scb); - - /* update parent SCB entry */ - cs46xx_dsp_spos_update_scb(chip,parent_scb); - - pcm_channel->unlinked = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -struct dsp_scb_descriptor * -cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source, - u16 addr, char * scb_name) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * parent; - struct dsp_scb_descriptor * pcm_input; - int insert_point; - - if (snd_BUG_ON(!ins->record_mixer_scb)) - return NULL; - - if (ins->record_mixer_scb->sub_list_ptr != ins->the_null_scb) { - parent = find_next_free_scb (chip,ins->record_mixer_scb->sub_list_ptr); - insert_point = SCB_ON_PARENT_NEXT_SCB; - } else { - parent = ins->record_mixer_scb; - insert_point = SCB_ON_PARENT_SUBLIST_SCB; - } - - pcm_input = cs46xx_dsp_create_pcm_serial_input_scb(chip,scb_name,addr, - source, parent, - insert_point); - - return pcm_input; -} - -int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src) -{ - unsigned long flags; - - if (snd_BUG_ON(!src->parent_scb_ptr)) - return -EINVAL; - - /* mute SCB */ - cs46xx_dsp_scb_set_volume (chip,src,0,0); - - spin_lock_irqsave(&chip->reg_lock, flags); - _dsp_unlink_scb (chip,src); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return 0; -} - -int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - struct dsp_scb_descriptor * parent_scb; - - if (snd_BUG_ON(src->parent_scb_ptr)) - return -EINVAL; - if (snd_BUG_ON(!ins->master_mix_scb)) - return -EINVAL; - - if (ins->master_mix_scb->sub_list_ptr != ins->the_null_scb) { - parent_scb = find_next_free_scb (chip,ins->master_mix_scb->sub_list_ptr); - parent_scb->next_scb_ptr = src; - } else { - parent_scb = ins->master_mix_scb; - parent_scb->sub_list_ptr = src; - } - - src->parent_scb_ptr = parent_scb; - - /* update entry in DSP RAM */ - cs46xx_dsp_spos_update_scb(chip,parent_scb); - - return 0; -} - -int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) { - cs46xx_dsp_enable_spdif_hw (chip); - } - - /* dont touch anything if SPDIF is open */ - if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) { - /* when cs46xx_iec958_post_close(...) is called it - will call this function if necessary depending on - this bit */ - ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED; - - return -EBUSY; - } - - if (snd_BUG_ON(ins->asynch_tx_scb)) - return -EINVAL; - if (snd_BUG_ON(ins->master_mix_scb->next_scb_ptr != - ins->the_null_scb)) - return -EINVAL; - - /* reset output snooper sample buffer pointer */ - snd_cs46xx_poke (chip, (ins->ref_snoop_scb->address + 2) << 2, - (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10 ); - - /* The asynch. transfer task */ - ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR, - SPDIFO_SCB_INST, - SPDIFO_IP_OUTPUT_BUFFER1, - ins->master_mix_scb, - SCB_ON_PARENT_NEXT_SCB); - if (!ins->asynch_tx_scb) return -ENOMEM; - - ins->spdif_pcm_input_scb = cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II", - PCMSERIALINII_SCB_ADDR, - ins->ref_snoop_scb, - ins->asynch_tx_scb, - SCB_ON_PARENT_SUBLIST_SCB); - - - if (!ins->spdif_pcm_input_scb) return -ENOMEM; - - /* monitor state */ - ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED; - - return 0; -} - -int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - /* dont touch anything if SPDIF is open */ - if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) { - ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED; - return -EBUSY; - } - - /* check integrety */ - if (snd_BUG_ON(!ins->asynch_tx_scb)) - return -EINVAL; - if (snd_BUG_ON(!ins->spdif_pcm_input_scb)) - return -EINVAL; - if (snd_BUG_ON(ins->master_mix_scb->next_scb_ptr != ins->asynch_tx_scb)) - return -EINVAL; - if (snd_BUG_ON(ins->asynch_tx_scb->parent_scb_ptr != - ins->master_mix_scb)) - return -EINVAL; - - cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb); - cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb); - - ins->spdif_pcm_input_scb = NULL; - ins->asynch_tx_scb = NULL; - - /* clear buffer to prevent any undesired noise */ - _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256); - - /* monitor state */ - ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED; - - - return 0; -} - -int cs46xx_iec958_pre_open (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) { - /* remove AsynchFGTxSCB and and PCMSerialInput_II */ - cs46xx_dsp_disable_spdif_out (chip); - - /* save state */ - ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED; - } - - /* if not enabled already */ - if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) { - cs46xx_dsp_enable_spdif_hw (chip); - } - - /* Create the asynch. transfer task for playback */ - ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR, - SPDIFO_SCB_INST, - SPDIFO_IP_OUTPUT_BUFFER1, - ins->master_mix_scb, - SCB_ON_PARENT_NEXT_SCB); - - - /* set spdif channel status value for streaming */ - cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_stream); - - ins->spdif_status_out |= DSP_SPDIF_STATUS_PLAYBACK_OPEN; - - return 0; -} - -int cs46xx_iec958_post_close (struct snd_cs46xx *chip) -{ - struct dsp_spos_instance * ins = chip->dsp_spos_instance; - - if (snd_BUG_ON(!ins->asynch_tx_scb)) - return -EINVAL; - - ins->spdif_status_out &= ~DSP_SPDIF_STATUS_PLAYBACK_OPEN; - - /* restore settings */ - cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default); - - /* deallocate stuff */ - if (ins->spdif_pcm_input_scb != NULL) { - cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb); - ins->spdif_pcm_input_scb = NULL; - } - - cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb); - ins->asynch_tx_scb = NULL; - - /* clear buffer to prevent any undesired noise */ - _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256); - - /* restore state */ - if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) { - cs46xx_dsp_enable_spdif_out (chip); - } - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwc4630.h b/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwc4630.h deleted file mode 100644 index 37c4f131..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwc4630.h +++ /dev/null @@ -1,320 +0,0 @@ -/* generated from cwc4630.osp DO NOT MODIFY */ - -#ifndef __HEADER_cwc4630_H__ -#define __HEADER_cwc4630_H__ - -static struct dsp_symbol_entry cwc4630_symbols[] = { - { 0x0000, "BEGINADDRESS",0x00 }, - { 0x8000, "EXECCHILD",0x03 }, - { 0x8001, "EXECCHILD_98",0x03 }, - { 0x8003, "EXECCHILD_PUSH1IND",0x03 }, - { 0x8008, "EXECSIBLING",0x03 }, - { 0x800a, "EXECSIBLING_298",0x03 }, - { 0x800b, "EXECSIBLING_2IND1",0x03 }, - { 0x8010, "TIMINGMASTER",0x03 }, - { 0x804f, "S16_CODECINPUTTASK",0x03 }, - { 0x805e, "PCMSERIALINPUTTASK",0x03 }, - { 0x806d, "S16_MIX_TO_OSTREAM",0x03 }, - { 0x809a, "S16_MIX",0x03 }, - { 0x80bb, "S16_UPSRC",0x03 }, - { 0x813b, "MIX3_EXP",0x03 }, - { 0x8164, "DECIMATEBYPOW2",0x03 }, - { 0x8197, "VARIDECIMATE",0x03 }, - { 0x81f2, "_3DINPUTTASK",0x03 }, - { 0x820a, "_3DPRLGCINPTASK",0x03 }, - { 0x8227, "_3DSTEREOINPUTTASK",0x03 }, - { 0x8242, "_3DOUTPUTTASK",0x03 }, - { 0x82c4, "HRTF_MORPH_TASK",0x03 }, - { 0x82c6, "WAIT4DATA",0x03 }, - { 0x82fa, "PROLOGIC",0x03 }, - { 0x8496, "DECORRELATOR",0x03 }, - { 0x84a4, "STEREO2MONO",0x03 }, - { 0x0070, "SPOSCB",0x02 }, - { 0x0107, "TASKTREETHREAD",0x03 }, - { 0x013c, "TASKTREEHEADERCODE",0x03 }, - { 0x0145, "FGTASKTREEHEADERCODE",0x03 }, - { 0x0169, "NULLALGORITHM",0x03 }, - { 0x016d, "HFGEXECCHILD",0x03 }, - { 0x016e, "HFGEXECCHILD_98",0x03 }, - { 0x0170, "HFGEXECCHILD_PUSH1IND",0x03 }, - { 0x0173, "HFGEXECSIBLING",0x03 }, - { 0x0175, "HFGEXECSIBLING_298",0x03 }, - { 0x0176, "HFGEXECSIBLING_2IND1",0x03 }, - { 0x0179, "S16_CODECOUTPUTTASK",0x03 }, - { 0x0194, "#CODE_END",0x00 }, -}; /* cwc4630 symbols */ - -static u32 cwc4630_code[] = { -/* BEGINADDRESS */ -/* 0000 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 0002 */ 0x00001705,0x00001400,0x000a411e,0x00001003, -/* 0004 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 0006 */ 0x00009705,0x00001400,0x000a411e,0x00001003, -/* 0008 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 000A */ 0x00011705,0x00001400,0x000a411e,0x00001003, -/* 000C */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 000E */ 0x00019705,0x00001400,0x000a411e,0x00001003, -/* 0010 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 0012 */ 0x00021705,0x00001400,0x000a411e,0x00001003, -/* 0014 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 0016 */ 0x00029705,0x00001400,0x000a411e,0x00001003, -/* 0018 */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 001A */ 0x00031705,0x00001400,0x000a411e,0x00001003, -/* 001C */ 0x00040730,0x00001002,0x000f619e,0x00001003, -/* 001E */ 0x00039705,0x00001400,0x000a411e,0x00001003, -/* 0020 */ 0x000fe19e,0x00001003,0x0009c730,0x00001003, -/* 0022 */ 0x0008e19c,0x00001003,0x000083c1,0x00093040, -/* 0024 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 0026 */ 0x00009705,0x00001400,0x000a211e,0x00001003, -/* 0028 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 002A */ 0x00011705,0x00001400,0x000a211e,0x00001003, -/* 002C */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 002E */ 0x00019705,0x00001400,0x000a211e,0x00001003, -/* 0030 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 0032 */ 0x00021705,0x00001400,0x000a211e,0x00001003, -/* 0034 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 0036 */ 0x00029705,0x00001400,0x000a211e,0x00001003, -/* 0038 */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 003A */ 0x00031705,0x00001400,0x000a211e,0x00001003, -/* 003C */ 0x00098730,0x00001002,0x000ee19e,0x00001003, -/* 003E */ 0x00039705,0x00001400,0x000a211e,0x00001003, -/* 0040 */ 0x0001a730,0x00001008,0x000e2730,0x00001002, -/* 0042 */ 0x0000a731,0x00001002,0x0000a731,0x00001002, -/* 0044 */ 0x0000a731,0x00001002,0x0000a731,0x00001002, -/* 0046 */ 0x0000a731,0x00001002,0x0000a731,0x00001002, -/* 0048 */ 0x00000000,0x00000000,0x000f619c,0x00001003, -/* 004A */ 0x0007f801,0x000c0000,0x00000037,0x00001000, -/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 004E */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0050 */ 0x00000000,0x000c0000,0x00000000,0x00000000, -/* 0052 */ 0x0000373c,0x00001000,0x00000000,0x00000000, -/* 0054 */ 0x000ee19c,0x00001003,0x0007f801,0x000c0000, -/* 0056 */ 0x00000037,0x00001000,0x00000000,0x00000000, -/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 005A */ 0x00000000,0x00000000,0x0000273c,0x00001000, -/* 005C */ 0x00000033,0x00001000,0x000e679e,0x00001003, -/* 005E */ 0x00007705,0x00001400,0x000ac71e,0x00001003, -/* 0060 */ 0x00087fc1,0x000c3be0,0x0007f801,0x000c0000, -/* 0062 */ 0x00000037,0x00001000,0x00000000,0x00000000, -/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0066 */ 0x00000000,0x00000000,0x0000a730,0x00001003, -/* 0068 */ 0x00000033,0x00001000,0x0007f801,0x000c0000, -/* 006A */ 0x00000037,0x00001000,0x00000000,0x00000000, -/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 006E */ 0x00000000,0x00000000,0x00000000,0x000c0000, -/* 0070 */ 0x00000032,0x00001000,0x0000273d,0x00001000, -/* 0072 */ 0x0004a730,0x00001003,0x00000f41,0x00097140, -/* 0074 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040, -/* 0076 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0, -/* 0078 */ 0x00000000,0x00000000,0x0001bf05,0x0003fc40, -/* 007A */ 0x00002725,0x000aa400,0x00013705,0x00093a00, -/* 007C */ 0x0000002e,0x0009d6c0,0x0002ef8a,0x00000000, -/* 007E */ 0x00040630,0x00001004,0x0004ef0a,0x000eb785, -/* 0080 */ 0x0003fc8a,0x00000000,0x00000000,0x000c70e0, -/* 0082 */ 0x0007d182,0x0002c640,0x00008630,0x00001004, -/* 0084 */ 0x000799b8,0x0002c6c0,0x00031705,0x00092240, -/* 0086 */ 0x00039f05,0x000932c0,0x0003520a,0x00000000, -/* 0088 */ 0x00070731,0x0000100b,0x00010705,0x000b20c0, -/* 008A */ 0x00000000,0x000eba44,0x00032108,0x000c60c4, -/* 008C */ 0x00065208,0x000c2917,0x000486b0,0x00001007, -/* 008E */ 0x00012f05,0x00036880,0x0002818e,0x000c0000, -/* 0090 */ 0x0004410a,0x00000000,0x00048630,0x00001007, -/* 0092 */ 0x00029705,0x000c0000,0x00000000,0x00000000, -/* 0094 */ 0x00003fc1,0x0003fc40,0x000037c1,0x00091b40, -/* 0096 */ 0x00003fc1,0x000911c0,0x000037c1,0x000957c0, -/* 0098 */ 0x00003fc1,0x000951c0,0x000037c1,0x00000000, -/* 009A */ 0x00003fc1,0x000991c0,0x000037c1,0x00000000, -/* 009C */ 0x00003fc1,0x0009d1c0,0x000037c1,0x00000000, -/* 009E */ 0x0001ccc1,0x000915c0,0x0001c441,0x0009d800, -/* 00A0 */ 0x0009cdc1,0x00091240,0x0001c541,0x00091d00, -/* 00A2 */ 0x0009cfc1,0x00095240,0x0001c741,0x00095c80, -/* 00A4 */ 0x000e8ca9,0x00099240,0x000e85ad,0x00095640, -/* 00A6 */ 0x00069ca9,0x00099d80,0x000e952d,0x00099640, -/* 00A8 */ 0x000eaca9,0x0009d6c0,0x000ea5ad,0x00091a40, -/* 00AA */ 0x0006bca9,0x0009de80,0x000eb52d,0x00095a40, -/* 00AC */ 0x000ecca9,0x00099ac0,0x000ec5ad,0x0009da40, -/* 00AE */ 0x000edca9,0x0009d300,0x000a6e0a,0x00001000, -/* 00B0 */ 0x000ed52d,0x00091e40,0x000eeca9,0x00095ec0, -/* 00B2 */ 0x000ee5ad,0x00099e40,0x0006fca9,0x00002500, -/* 00B4 */ 0x000fb208,0x000c59a0,0x000ef52d,0x0009de40, -/* 00B6 */ 0x00068ca9,0x000912c1,0x000683ad,0x00095241, -/* 00B8 */ 0x00020f05,0x000991c1,0x00000000,0x00000000, -/* 00BA */ 0x00086f88,0x00001000,0x0009cf81,0x000b5340, -/* 00BC */ 0x0009c701,0x000b92c0,0x0009de81,0x000bd300, -/* 00BE */ 0x0009d601,0x000b1700,0x0001fd81,0x000b9d80, -/* 00C0 */ 0x0009f501,0x000b57c0,0x000a0f81,0x000bd740, -/* 00C2 */ 0x00020701,0x000b5c80,0x000a1681,0x000b97c0, -/* 00C4 */ 0x00021601,0x00002500,0x000a0701,0x000b9b40, -/* 00C6 */ 0x000a0f81,0x000b1bc0,0x00021681,0x00002d00, -/* 00C8 */ 0x00020f81,0x000bd800,0x000a0701,0x000b5bc0, -/* 00CA */ 0x00021601,0x00003500,0x000a0f81,0x000b5f40, -/* 00CC */ 0x000a0701,0x000bdbc0,0x00021681,0x00003d00, -/* 00CE */ 0x00020f81,0x000b1d00,0x000a0701,0x000b1fc0, -/* 00D0 */ 0x00021601,0x00020500,0x00020f81,0x000b1341, -/* 00D2 */ 0x000a0701,0x000b9fc0,0x00021681,0x00020d00, -/* 00D4 */ 0x00020f81,0x000bde80,0x000a0701,0x000bdfc0, -/* 00D6 */ 0x00021601,0x00021500,0x00020f81,0x000b9341, -/* 00D8 */ 0x00020701,0x000b53c1,0x00021681,0x00021d00, -/* 00DA */ 0x000a0f81,0x000d0380,0x0000b601,0x000b15c0, -/* 00DC */ 0x00007b01,0x00000000,0x00007b81,0x000bd1c0, -/* 00DE */ 0x00007b01,0x00000000,0x00007b81,0x000b91c0, -/* 00E0 */ 0x00007b01,0x000b57c0,0x00007b81,0x000b51c0, -/* 00E2 */ 0x00007b01,0x000b1b40,0x00007b81,0x000b11c0, -/* 00E4 */ 0x00087b01,0x000c3dc0,0x0007e488,0x000d7e45, -/* 00E6 */ 0x00000000,0x000d7a44,0x0007e48a,0x00000000, -/* 00E8 */ 0x00011f05,0x00084080,0x00000000,0x00000000, -/* 00EA */ 0x00001705,0x000b3540,0x00008a01,0x000bf040, -/* 00EC */ 0x00007081,0x000bb5c0,0x00055488,0x00000000, -/* 00EE */ 0x0000d482,0x0003fc40,0x0003fc88,0x00000000, -/* 00F0 */ 0x0001e401,0x000b3a00,0x0001ec81,0x000bd6c0, -/* 00F2 */ 0x0002ef88,0x000e7784,0x00056f08,0x00000000, -/* 00F4 */ 0x000d86b0,0x00001007,0x00008281,0x000bb240, -/* 00F6 */ 0x0000b801,0x000b7140,0x00007888,0x00000000, -/* 00F8 */ 0x0000073c,0x00001000,0x0007f188,0x000c0000, -/* 00FA */ 0x00000000,0x00000000,0x00055288,0x000c555c, -/* 00FC */ 0x0005528a,0x000c0000,0x0009fa88,0x000c5d00, -/* 00FE */ 0x0000fa88,0x00000000,0x00000032,0x00001000, -/* 0100 */ 0x0000073d,0x00001000,0x0007f188,0x000c0000, -/* 0102 */ 0x00000000,0x00000000,0x0008c01c,0x00001003, -/* 0104 */ 0x00002705,0x00001008,0x0008b201,0x000c1392, -/* 0106 */ 0x0000ba01,0x00000000, -/* TASKTREETHREAD */ -/* 0107 */ 0x00008731,0x00001400,0x0004c108,0x000fe0c4, -/* 0109 */ 0x00057488,0x00000000,0x000a6388,0x00001001, -/* 010B */ 0x0008b334,0x000bc141,0x0003020e,0x00000000, -/* 010D */ 0x000986b0,0x00001008,0x00003625,0x000c5dfa, -/* 010F */ 0x000a638a,0x00001001,0x0008020e,0x00001002, -/* 0111 */ 0x0009a6b0,0x00001008,0x0007f301,0x00000000, -/* 0113 */ 0x00000000,0x00000000,0x00002725,0x000a8c40, -/* 0115 */ 0x000000ae,0x00000000,0x000e8630,0x00001008, -/* 0117 */ 0x00000000,0x000c74e0,0x0007d182,0x0002d640, -/* 0119 */ 0x000b8630,0x00001008,0x000799b8,0x0002d6c0, -/* 011B */ 0x0000748a,0x000c3ec5,0x0007420a,0x000c0000, -/* 011D */ 0x00062208,0x000c4117,0x000a0630,0x00001009, -/* 011F */ 0x00000000,0x000c0000,0x0001022e,0x00000000, -/* 0121 */ 0x0006a630,0x00001009,0x00000032,0x00001000, -/* 0123 */ 0x000ca21c,0x00001003,0x00005a02,0x00000000, -/* 0125 */ 0x0001a630,0x00001009,0x00000000,0x000c0000, -/* 0127 */ 0x00000036,0x00001000,0x00000000,0x00000000, -/* 0129 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 012B */ 0x00000000,0x00000000,0x0003a730,0x00001008, -/* 012D */ 0x0007f801,0x000c0000,0x00000037,0x00001000, -/* 012F */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0131 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0133 */ 0x0003a730,0x00001008,0x00000033,0x00001000, -/* 0135 */ 0x0003a705,0x00001008,0x00007a01,0x000c0000, -/* 0137 */ 0x000e6288,0x000d550a,0x0006428a,0x00000000, -/* 0139 */ 0x00090730,0x0000100a,0x00000000,0x000c0000, -/* 013B */ 0x00000000,0x00000000, -/* TASKTREEHEADERCODE */ -/* 013C */ 0x0007aab0,0x00034880,0x000a8fb0,0x0000100b, -/* 013E */ 0x00057488,0x00000000,0x00033b94,0x00081140, -/* 0140 */ 0x000183ae,0x00000000,0x000a86b0,0x0000100b, -/* 0142 */ 0x00022f05,0x000c3545,0x0000eb8a,0x00000000, -/* 0144 */ 0x00042731,0x00001003, -/* FGTASKTREEHEADERCODE */ -/* 0145 */ 0x0007aab0,0x00034880,0x00078fb0,0x0000100a, -/* 0147 */ 0x00057488,0x00000000,0x00033b94,0x00081140, -/* 0149 */ 0x000183ae,0x00000000,0x000b06b0,0x0000100b, -/* 014B */ 0x00022f05,0x00000000,0x00007401,0x00091140, -/* 014D */ 0x00048f05,0x000951c0,0x00042731,0x00001003, -/* 014F */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47, -/* 0151 */ 0x00080000,0x000bffc7,0x000fe19e,0x00001003, -/* 0153 */ 0x00000000,0x00000000,0x0008e19c,0x00001003, -/* 0155 */ 0x000083c1,0x00093040,0x00000f41,0x00097140, -/* 0157 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040, -/* 0159 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0, -/* 015B */ 0x00000000,0x000fdc44,0x00055208,0x00000000, -/* 015D */ 0x00010705,0x000a2880,0x0000a23a,0x00093a00, -/* 015F */ 0x0003fc8a,0x000df6c5,0x0004ef0a,0x000c0000, -/* 0161 */ 0x00012f05,0x00036880,0x00065308,0x000c2997, -/* 0163 */ 0x000086b0,0x0000100b,0x0004410a,0x000d40c7, -/* 0165 */ 0x00000000,0x00000000,0x00088730,0x00001004, -/* 0167 */ 0x00056f0a,0x000ea105,0x00000000,0x00000000, -/* NULLALGORITHM */ -/* 0169 */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47, -/* 016B */ 0x00080000,0x000bffc7,0x0000273d,0x00001000, -/* HFGEXECCHILD */ -/* 016D */ 0x00000000,0x000eba44, -/* HFGEXECCHILD_98 */ -/* 016E */ 0x00048f05,0x0000f440,0x00007401,0x0000f7c0, -/* HFGEXECCHILD_PUSH1IND */ -/* 0170 */ 0x00000734,0x00001000,0x00010705,0x000a6880, -/* 0172 */ 0x00006a88,0x000c75c4, -/* HFGEXECSIBLING */ -/* 0173 */ 0x00000000,0x000e5084,0x00000000,0x000eba44, -/* HFGEXECSIBLING_298 */ -/* 0175 */ 0x00087401,0x000e4782, -/* HFGEXECSIBLING_2IND1 */ -/* 0176 */ 0x00000734,0x00001000,0x00010705,0x000a6880, -/* 0178 */ 0x00006a88,0x000c75c4, -/* S16_CODECOUTPUTTASK */ -/* 0179 */ 0x0007c108,0x000c0000,0x0007e721,0x000bed40, -/* 017B */ 0x00005f25,0x000badc0,0x0003ba97,0x000beb80, -/* 017D */ 0x00065590,0x000b2e00,0x00033217,0x00003ec0, -/* 017F */ 0x00065590,0x000b8e40,0x0003ed80,0x000491c0, -/* 0181 */ 0x00073fb0,0x00074c80,0x000583a0,0x0000100c, -/* 0183 */ 0x000ee388,0x00042970,0x00008301,0x00021ef2, -/* 0185 */ 0x000b8f14,0x0000000f,0x000c4d8d,0x0000001b, -/* 0187 */ 0x000d6dc2,0x000e06c6,0x000032ac,0x000c3916, -/* 0189 */ 0x0004edc2,0x00074c80,0x00078898,0x00001000, -/* 018B */ 0x00038894,0x00000032,0x000c4d8d,0x00092e1b, -/* 018D */ 0x000d6dc2,0x000e06c6,0x0004edc2,0x000c1956, -/* 018F */ 0x0000722c,0x00034a00,0x00041705,0x0009ed40, -/* 0191 */ 0x00058730,0x00001400,0x000d7488,0x000c3a00, -/* 0193 */ 0x00048f05,0x00000000 -}; -/* #CODE_END */ - -static u32 cwc4630_parameter[] = { -/* 0000 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0004 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0008 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 000C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0010 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0014 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0018 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 001C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0020 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0024 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0028 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 002C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0030 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0034 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0038 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 003C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0040 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0044 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0048 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0050 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0054 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 005C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0060 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0068 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0070 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0074 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 0078 */ 0x00000000,0x00000000,0x00000000,0x00000000, -/* 007C */ 0x00000000,0x00000000,0x00000000,0x00000000 -}; /* #PARAMETER_END */ - - -static struct dsp_segment_desc cwc4630_segments[] = { - { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000328, cwc4630_code }, - { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000080, cwc4630_parameter }, -}; - -static struct dsp_module_desc cwc4630_module = { - "cwc4630", - { - 38, - cwc4630_symbols - }, - 2, - cwc4630_segments, -}; - -#endif /* __HEADER_cwc4630_H__ */ diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcasync.h b/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcasync.h deleted file mode 100644 index 70e63e13..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcasync.h +++ /dev/null @@ -1,176 +0,0 @@ -/* generated from cwcasync.osp DO NOT MODIFY */ - -#ifndef __HEADER_cwcasync_H__ -#define __HEADER_cwcasync_H__ - -static struct dsp_symbol_entry cwcasync_symbols[] = { - { 0x8000, "EXECCHILD",0x03 }, - { 0x8001, "EXECCHILD_98",0x03 }, - { 0x8003, "EXECCHILD_PUSH1IND",0x03 }, - { 0x8008, "EXECSIBLING",0x03 }, - { 0x800a, "EXECSIBLING_298",0x03 }, - { 0x800b, "EXECSIBLING_2IND1",0x03 }, - { 0x8010, "TIMINGMASTER",0x03 }, - { 0x804f, "S16_CODECINPUTTASK",0x03 }, - { 0x805e, "PCMSERIALINPUTTASK",0x03 }, - { 0x806d, "S16_MIX_TO_OSTREAM",0x03 }, - { 0x809a, "S16_MIX",0x03 }, - { 0x80bb, "S16_UPSRC",0x03 }, - { 0x813b, "MIX3_EXP",0x03 }, - { 0x8164, "DECIMATEBYPOW2",0x03 }, - { 0x8197, "VARIDECIMATE",0x03 }, - { 0x81f2, "_3DINPUTTASK",0x03 }, - { 0x820a, "_3DPRLGCINPTASK",0x03 }, - { 0x8227, "_3DSTEREOINPUTTASK",0x03 }, - { 0x8242, "_3DOUTPUTTASK",0x03 }, - { 0x82c4, "HRTF_MORPH_TASK",0x03 }, - { 0x82c6, "WAIT4DATA",0x03 }, - { 0x82fa, "PROLOGIC",0x03 }, - { 0x8496, "DECORRELATOR",0x03 }, - { 0x84a4, "STEREO2MONO",0x03 }, - { 0x0000, "OVERLAYBEGINADDRESS",0x00 }, - { 0x0000, "SPIOWRITE",0x03 }, - { 0x000d, "S16_ASYNCCODECINPUTTASK",0x03 }, - { 0x0043, "SPDIFITASK",0x03 }, - { 0x007b, "SPDIFOTASK",0x03 }, - { 0x0097, "ASYNCHFGTXCODE",0x03 }, - { 0x00be, "ASYNCHFGRXCODE",0x03 }, - { 0x00db, "#CODE_END",0x00 }, -}; /* cwcasync symbols */ - -static u32 cwcasync_code[] = { -/* OVERLAYBEGINADDRESS */ -/* 0000 */ 0x00002731,0x00001400,0x00003725,0x000a8440, -/* 0002 */ 0x000000ae,0x00000000,0x00060630,0x00001000, -/* 0004 */ 0x00000000,0x000c7560,0x00075282,0x0002d640, -/* 0006 */ 0x00021705,0x00000000,0x00072ab8,0x0002d6c0, -/* 0008 */ 0x00020630,0x00001000,0x000c74c2,0x000d4b82, -/* 000A */ 0x000475c2,0x00000000,0x0003430a,0x000c0000, -/* 000C */ 0x00042730,0x00001400, -/* S16_ASYNCCODECINPUTTASK */ -/* 000D */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x00000000, -/* 000F */ 0x000fa418,0x0000101f,0x0005d402,0x0001c500, -/* 0011 */ 0x000f0630,0x00001000,0x00004418,0x00001380, -/* 0013 */ 0x000e243d,0x000d394a,0x00049705,0x00000000, -/* 0015 */ 0x0007d530,0x000b4240,0x000e00f2,0x00001000, -/* 0017 */ 0x00009134,0x000ca20a,0x00004c90,0x00001000, -/* 0019 */ 0x0005d705,0x00000000,0x00004f25,0x00098240, -/* 001B */ 0x00004725,0x00000000,0x0000e48a,0x00000000, -/* 001D */ 0x00027295,0x0009c2c0,0x0003df25,0x00000000, -/* 001F */ 0x000e8030,0x00001001,0x0005f718,0x000ac600, -/* 0021 */ 0x0007cf30,0x000c2a01,0x00082630,0x00001001, -/* 0023 */ 0x000504a0,0x00001001,0x00029314,0x000bcb80, -/* 0025 */ 0x0003cf25,0x000b0e00,0x0004f5c0,0x00000000, -/* 0027 */ 0x00049118,0x000d888a,0x0007dd02,0x000c6efa, -/* 0029 */ 0x00000000,0x00000000,0x0004f5c0,0x00069c80, -/* 002B */ 0x0000d402,0x00000000,0x000e8630,0x00001001, -/* 002D */ 0x00079130,0x00000000,0x00049118,0x00090e00, -/* 002F */ 0x0006c10a,0x00000000,0x00000000,0x000c0000, -/* 0031 */ 0x0007cf30,0x00030580,0x00005725,0x00000000, -/* 0033 */ 0x000d84a0,0x00001001,0x00029314,0x000b4780, -/* 0035 */ 0x0003cf25,0x000b8600,0x00000000,0x00000000, -/* 0037 */ 0x00000000,0x000c0000,0x00000000,0x00042c80, -/* 0039 */ 0x0001dec1,0x000e488c,0x00031114,0x00000000, -/* 003B */ 0x0004f5c2,0x00000000,0x0003640a,0x00000000, -/* 003D */ 0x00000000,0x000e5084,0x00000000,0x000eb844, -/* 003F */ 0x00007001,0x00000000,0x00000734,0x00001000, -/* 0041 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4, -/* SPDIFITASK */ -/* 0043 */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x000d5384, -/* 0045 */ 0x0007e48a,0x00000000,0x00067718,0x00001000, -/* 0047 */ 0x0007a418,0x00001000,0x0007221a,0x00000000, -/* 0049 */ 0x0005d402,0x00014500,0x000b8630,0x00001002, -/* 004B */ 0x00004418,0x00001780,0x000e243d,0x000d394a, -/* 004D */ 0x00049705,0x00000000,0x0007d530,0x000b4240, -/* 004F */ 0x000ac0f2,0x00001002,0x00014414,0x00000000, -/* 0051 */ 0x00004c90,0x00001000,0x0005d705,0x00000000, -/* 0053 */ 0x00004f25,0x00098240,0x00004725,0x00000000, -/* 0055 */ 0x0000e48a,0x00000000,0x00027295,0x0009c2c0, -/* 0057 */ 0x0007df25,0x00000000,0x000ac030,0x00001003, -/* 0059 */ 0x0005f718,0x000fe798,0x00029314,0x000bcb80, -/* 005B */ 0x00000930,0x000b0e00,0x0004f5c0,0x000de204, -/* 005D */ 0x000884a0,0x00001003,0x0007cf25,0x000e3560, -/* 005F */ 0x00049118,0x00000000,0x00049118,0x000d888a, -/* 0061 */ 0x0007dd02,0x000c6efa,0x0000c434,0x00030040, -/* 0063 */ 0x000fda82,0x000c2312,0x000fdc0e,0x00001001, -/* 0065 */ 0x00083402,0x000c2b92,0x000706b0,0x00001003, -/* 0067 */ 0x00075a82,0x00000000,0x0000d625,0x000b0940, -/* 0069 */ 0x0000840e,0x00001002,0x0000aabc,0x000c511e, -/* 006B */ 0x00078730,0x00001003,0x0000aaf4,0x000e910a, -/* 006D */ 0x0004628a,0x00000000,0x00006aca,0x00000000, -/* 006F */ 0x00000930,0x00000000,0x0004f5c0,0x00069c80, -/* 0071 */ 0x00046ac0,0x00000000,0x0003c40a,0x000fc898, -/* 0073 */ 0x00049118,0x00090e00,0x0006c10a,0x00000000, -/* 0075 */ 0x00000000,0x000e5084,0x00000000,0x000eb844, -/* 0077 */ 0x00007001,0x00000000,0x00000734,0x00001000, -/* 0079 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4, -/* SPDIFOTASK */ -/* 007B */ 0x0006a108,0x000c0000,0x0004f4c0,0x000c3245, -/* 007D */ 0x0000a418,0x00001000,0x0003a20a,0x00000000, -/* 007F */ 0x00004418,0x00001380,0x000e243d,0x000d394a, -/* 0081 */ 0x000c9705,0x000def92,0x0008c030,0x00001004, -/* 0083 */ 0x0005f718,0x000fe798,0x00000000,0x000c0000, -/* 0085 */ 0x00005725,0x00000000,0x000704a0,0x00001004, -/* 0087 */ 0x00029314,0x000b4780,0x0003cf25,0x000b8600, -/* 0089 */ 0x00000000,0x00000000,0x00000000,0x000c0000, -/* 008B */ 0x00000000,0x00042c80,0x0001dec1,0x000e488c, -/* 008D */ 0x00031114,0x00000000,0x0004f5c2,0x00000000, -/* 008F */ 0x0004a918,0x00098600,0x0006c28a,0x00000000, -/* 0091 */ 0x00000000,0x000e5084,0x00000000,0x000eb844, -/* 0093 */ 0x00007001,0x00000000,0x00000734,0x00001000, -/* 0095 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4, -/* ASYNCHFGTXCODE */ -/* 0097 */ 0x0002a880,0x000b4e40,0x00042214,0x000e5548, -/* 0099 */ 0x000542bf,0x00000000,0x00000000,0x000481c0, -/* 009B */ 0x00000000,0x00000000,0x00000000,0x00000030, -/* 009D */ 0x0000072d,0x000fbf8a,0x00077f94,0x000ea7df, -/* 009F */ 0x0002ac95,0x000d3145,0x00002731,0x00001400, -/* 00A1 */ 0x00006288,0x000c71c4,0x00014108,0x000e6044, -/* 00A3 */ 0x00035408,0x00000000,0x00025418,0x000a0ec0, -/* 00A5 */ 0x0001443d,0x000ca21e,0x00046595,0x000d730c, -/* 00A7 */ 0x0006538e,0x00000000,0x00064630,0x00001005, -/* 00A9 */ 0x000e7b0e,0x000df782,0x000746b0,0x00001005, -/* 00AB */ 0x00036f05,0x000c0000,0x00043695,0x000d598c, -/* 00AD */ 0x0005331a,0x000f2185,0x00000000,0x00000000, -/* 00AF */ 0x000007ae,0x000bdb00,0x00040630,0x00001400, -/* 00B1 */ 0x0005e708,0x000c0000,0x0007ef30,0x000b1c00, -/* 00B3 */ 0x000d86a0,0x00001005,0x00066408,0x000c0000, -/* 00B5 */ 0x00000000,0x00000000,0x00021843,0x00000000, -/* 00B7 */ 0x00000cac,0x00062c00,0x00001dac,0x00063400, -/* 00B9 */ 0x00002cac,0x0006cc80,0x000db943,0x000e5ca1, -/* 00BB */ 0x00000000,0x00000000,0x0006680a,0x000f3205, -/* 00BD */ 0x00042730,0x00001400, -/* ASYNCHFGRXCODE */ -/* 00BE */ 0x00014108,0x000f2204,0x00025418,0x000a2ec0, -/* 00C0 */ 0x00015dbd,0x00038100,0x00015dbc,0x00000000, -/* 00C2 */ 0x0005e415,0x00034880,0x0001258a,0x000d730c, -/* 00C4 */ 0x0006538e,0x000baa40,0x00060630,0x00001006, -/* 00C6 */ 0x00067b0e,0x000ac380,0x0003ef05,0x00000000, -/* 00C8 */ 0x0000f734,0x0001c300,0x000586b0,0x00001400, -/* 00CA */ 0x000b6f05,0x000c3a00,0x00048f05,0x00000000, -/* 00CC */ 0x0005b695,0x0008c380,0x0002058e,0x00000000, -/* 00CE */ 0x000500b0,0x00001400,0x0002b318,0x000e998d, -/* 00D0 */ 0x0006430a,0x00000000,0x00000000,0x000ef384, -/* 00D2 */ 0x00004725,0x000c0000,0x00000000,0x000f3204, -/* 00D4 */ 0x00004f25,0x000c0000,0x00080000,0x000e5ca1, -/* 00D6 */ 0x000cb943,0x000e5ca1,0x0004b943,0x00000000, -/* 00D8 */ 0x00040730,0x00001400,0x000cb943,0x000e5ca1, -/* 00DA */ 0x0004b943,0x00000000 -}; -/* #CODE_END */ - -static struct dsp_segment_desc cwcasync_segments[] = { - { SEGTYPE_SP_PROGRAM, 0x00000000, 0x000001b6, cwcasync_code }, -}; - -static struct dsp_module_desc cwcasync_module = { - "cwcasync", - { - 32, - cwcasync_symbols - }, - 1, - cwcasync_segments, -}; - -#endif /* __HEADER_cwcasync_H__ */ diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcbinhack.h b/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcbinhack.h deleted file mode 100644 index f4d93689..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcbinhack.h +++ /dev/null @@ -1,48 +0,0 @@ -/* generated by Benny - MODIFY ON YOUR OWN RISK */ - -#ifndef __HEADER_cwcbinhack_H__ -#define __HEADER_cwcbinhack_H__ - -static struct dsp_symbol_entry cwcbinhack_symbols[] = { - { 0x02c8, "OVERLAYBEGINADDRESS",0x00 }, - { 0x02c8, "MAGICSNOOPTASK",0x03 }, - { 0x0308, "#CODE_END",0x00 }, -}; /* cwcbinhack symbols */ - -static u32 cwcbinhack_code[] = { - /* 0x02c8 */ - 0x0007bfb0,0x000bc240,0x00000c2e,0x000c6084, /* 1 */ - 0x000b8630,0x00001016,0x00006408,0x000efb84, /* 2 */ - 0x00016008,0x00000000,0x0001c088,0x000c0000, /* 3 */ - 0x000fc908,0x000e3392,0x0005f488,0x000efb84, /* 4 */ - 0x0001d402,0x000b2e00,0x0003d418,0x00001000, /* 5 */ - 0x0008d574,0x000c4293,0x00065625,0x000ea30e, /* 6 */ - 0x00096c01,0x000c6f92,0x0001a58a,0x000c6085, /* 7 */ - 0x00002f43,0x00000000,0x000e03a0,0x00001016, /* 8 */ - 0x0005e608,0x000c0000,0x00000000,0x00000000, /* 9 */ - 0x000ca108,0x000dcca1,0x00003bac,0x000c3205, /* 10 */ - 0x00073843,0x00000000,0x00010730,0x00001017, /* 11 */ - 0x0001600a,0x000c0000,0x00057488,0x00000000, /* 12 */ - 0x00000000,0x000e5084,0x00000000,0x000eba44, /* 13 */ - 0x00087401,0x000e4782,0x00000734,0x00001000, /* 14 */ - 0x00010705,0x000a6880,0x00006a88,0x000c75c4, /* 15 */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* 16 */ -}; -/* #CODE_END */ - -static struct dsp_segment_desc cwcbinhack_segments[] = { - { SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code }, -}; - -static struct dsp_module_desc cwcbinhack_module = { - "cwcbinhack", - { - 3, - cwcbinhack_symbols - }, - 1, - cwcbinhack_segments, -}; - -#endif /* __HEADER_cwcbinhack_H__ */ diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.asp b/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.asp deleted file mode 100644 index a65e1193..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.asp +++ /dev/null @@ -1,170 +0,0 @@ -// -// Copyright(c) by Benny Sjostrand (benny@hostmobility.com) -// -// 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 -// - - -// -// This code runs inside the DSP (cs4610, cs4612, cs4624, or cs4630), -// to compile it you need a tool named SPASM 3.0 and DSP code owned by -// Cirrus Logic(R). The SPASM program will generate a object file (cwcdma.osp), -// the "ospparser" tool will genereate the cwcdma.h file it's included from -// the cs46xx_lib.c file. -// -// -// The purpose of this code is very simple: make it possible to tranfser -// the samples 'as they are' with no alteration from a PCMreader -// SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF. -// SRC (source rate converters) task always alters the samples in somehow, -// however it's from 48khz -> 48khz. -// The alterations are not audible, but AC3 wont work. -// -// ... -// | -// +---------------+ -// | AsynchFGTxSCB | -// +---------------+ -// | -// subListPtr -// | -// +--------------+ -// | DMAReader | -// +--------------+ -// | -// subListPtr -// | -// +-------------+ -// | PCMReader | -// +-------------+ -// (DMA from host) -// - -struct dmaSCB - { - long dma_reserved1[3]; - - short dma_reserved2:dma_outBufPtr; - - short dma_unused1:dma_unused2; - - long dma_reserved3[4]; - - short dma_subListPtr:dma_nextSCB; - short dma_SPBptr:dma_entryPoint; - - long dma_strmRsConfig; - long dma_strmBufPtr; - - long dma_reserved4; - - VolumeControl s2m_volume; - }; - -#export DMAReader -void DMAReader() -{ - execChild(); - r2 = r0->dma_subListPtr; - r1 = r0->nextSCB; - - rsConfig01 = r2->strmRsConfig; - // Load rsConfig for input buffer - - rsDMA01 = r2->basicReq.daw, , tb = Z(0 - rf); - // Load rsDMA in case input buffer is a DMA buffer Test to see if there is any data to transfer - - if (tb) goto execSibling_2ind1 after { - r5 = rf + (-1); - r6 = r1->dma_entryPoint; // r6 = entry point of sibling task - r1 = r1->dma_SPBptr, // r1 = pointer to sibling task's SPB - , ind = r6; // Load entry point of sibling task - } - - rsConfig23 = r0->dma_strmRsConfig; - // Load rsConfig for output buffer (never a DMA buffer) - - r4 = r0->dma_outBufPtr; - - rsa0 = r2->strmBufPtr; - // rsa0 = input buffer pointer - - for (i = r5; i >= 0; --i) - after { - rsa2 = r4; - // rsa2 = output buffer pointer - - nop; - nop; - } - //***************************** - // TODO: cycles to this point * - //***************************** - { - acc0 = (rsd0 = *rsa0++1); - // get sample - - nop; // Those "nop"'s are really uggly, but there's - nop; // something with DSP's pipelines which I don't - nop; // understand, resulting this code to fail without - // having those "nop"'s (Benny) - - rsa0?reqDMA = r2; - // Trigger DMA transfer on input stream, - // if needed to replenish input buffer - - nop; - // Yet another magic "nop" to make stuff work - - ,,r98 = acc0 $+>> 0; - // store sample in ALU - - nop; - // latency on load register. - // (this one is understandable) - - *rsa2++1 = r98; - // store sample in output buffer - - nop; // The same story - nop; // as above again ... - nop; - } - // TODO: cycles per loop iteration - - r2->strmBufPtr = rsa0,, ; - // Update the modified buffer pointers - - r4 = rsa2; - // Load output pointer position into r4 - - r2 = r0->nextSCB; - // Sibling task - - goto execSibling_2ind1 // takes 6 cycles - after { - r98 = r2->thisSPB:entryPoint; - // Load child routine entry and data address - - r1 = r9; - // r9 is r2->thisSPB - - r0->dma_outBufPtr = r4,, - // Store updated output buffer pointer - - ind = r8; - // r8 is r2->entryPoint - } -} diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.h b/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.h deleted file mode 100644 index 7ff0d458..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcdma.h +++ /dev/null @@ -1,68 +0,0 @@ -/* generated from cwcdma.osp DO NOT MODIFY */ - -#ifndef __HEADER_cwcdma_H__ -#define __HEADER_cwcdma_H__ - -static struct dsp_symbol_entry cwcdma_symbols[] = { - { 0x8000, "EXECCHILD",0x03 }, - { 0x8001, "EXECCHILD_98",0x03 }, - { 0x8003, "EXECCHILD_PUSH1IND",0x03 }, - { 0x8008, "EXECSIBLING",0x03 }, - { 0x800a, "EXECSIBLING_298",0x03 }, - { 0x800b, "EXECSIBLING_2IND1",0x03 }, - { 0x8010, "TIMINGMASTER",0x03 }, - { 0x804f, "S16_CODECINPUTTASK",0x03 }, - { 0x805e, "PCMSERIALINPUTTASK",0x03 }, - { 0x806d, "S16_MIX_TO_OSTREAM",0x03 }, - { 0x809a, "S16_MIX",0x03 }, - { 0x80bb, "S16_UPSRC",0x03 }, - { 0x813b, "MIX3_EXP",0x03 }, - { 0x8164, "DECIMATEBYPOW2",0x03 }, - { 0x8197, "VARIDECIMATE",0x03 }, - { 0x81f2, "_3DINPUTTASK",0x03 }, - { 0x820a, "_3DPRLGCINPTASK",0x03 }, - { 0x8227, "_3DSTEREOINPUTTASK",0x03 }, - { 0x8242, "_3DOUTPUTTASK",0x03 }, - { 0x82c4, "HRTF_MORPH_TASK",0x03 }, - { 0x82c6, "WAIT4DATA",0x03 }, - { 0x82fa, "PROLOGIC",0x03 }, - { 0x8496, "DECORRELATOR",0x03 }, - { 0x84a4, "STEREO2MONO",0x03 }, - { 0x0000, "OVERLAYBEGINADDRESS",0x00 }, - { 0x0000, "DMAREADER",0x03 }, - { 0x0018, "#CODE_END",0x00 }, -}; /* cwcdma symbols */ - -static u32 cwcdma_code[] = { -/* OVERLAYBEGINADDRESS */ -/* 0000 */ 0x00002731,0x00001400,0x0004c108,0x000e5044, -/* 0002 */ 0x0005f608,0x00000000,0x000007ae,0x000be300, -/* 0004 */ 0x00058630,0x00001400,0x0007afb0,0x000e9584, -/* 0006 */ 0x00007301,0x000a9840,0x0005e708,0x000cd104, -/* 0008 */ 0x00067008,0x00000000,0x000902a0,0x00001000, -/* 000A */ 0x00012a01,0x000c0000,0x00000000,0x00000000, -/* 000C */ 0x00021843,0x000c0000,0x00000000,0x000c0000, -/* 000E */ 0x0000e101,0x000c0000,0x00000cac,0x00000000, -/* 0010 */ 0x00080000,0x000e5ca1,0x00000000,0x000c0000, -/* 0012 */ 0x00000000,0x00000000,0x00000000,0x00092c00, -/* 0014 */ 0x000122c1,0x000e5084,0x00058730,0x00001400, -/* 0016 */ 0x000d7488,0x000e4782,0x00007401,0x0001c100 -}; - -/* #CODE_END */ - -static struct dsp_segment_desc cwcdma_segments[] = { - { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code }, -}; - -static struct dsp_module_desc cwcdma_module = { - "cwcdma", - { - 27, - cwcdma_symbols - }, - 1, - cwcdma_segments, -}; - -#endif /* __HEADER_cwcdma_H__ */ diff --git a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcsnoop.h b/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcsnoop.h deleted file mode 100644 index 6929d0a5..00000000 --- a/ANDROID_3.4.5/sound/pci/cs46xx/imgs/cwcsnoop.h +++ /dev/null @@ -1,46 +0,0 @@ -/* generated from cwcsnoop.osp DO NOT MODIFY */ - -#ifndef __HEADER_cwcsnoop_H__ -#define __HEADER_cwcsnoop_H__ - -static struct dsp_symbol_entry cwcsnoop_symbols[] = { - { 0x0500, "OVERLAYBEGINADDRESS",0x00 }, - { 0x0500, "OUTPUTSNOOP",0x03 }, - { 0x051f, "#CODE_END",0x00 }, -}; /* cwcsnoop symbols */ - -static u32 cwcsnoop_code[] = { -/* 0000 */ 0x0007bfb0,0x000b4e40,0x0007c088,0x000c0617, -/* 0002 */ 0x00049705,0x00000000,0x00080630,0x00001028, -/* 0004 */ 0x00076408,0x000efb84,0x00066008,0x00000000, -/* 0006 */ 0x0007c908,0x000c0000,0x00046725,0x000efa44, -/* 0008 */ 0x0005f708,0x00000000,0x0001d402,0x000b2e00, -/* 000A */ 0x0003d418,0x00001000,0x0008d574,0x000c4293, -/* 000C */ 0x00065625,0x000ea30e,0x00096c01,0x000c6f92, -/* 000E */ 0x0006a58a,0x000f6085,0x00002f43,0x00000000, -/* 0010 */ 0x000a83a0,0x00001028,0x0005e608,0x000c0000, -/* 0012 */ 0x00000000,0x00000000,0x000ca108,0x000dcca1, -/* 0014 */ 0x00003bac,0x000fb205,0x00073843,0x00000000, -/* 0016 */ 0x000d8730,0x00001028,0x0006600a,0x000c0000, -/* 0018 */ 0x00057488,0x00000000,0x00000000,0x000e5084, -/* 001A */ 0x00000000,0x000eba44,0x00087401,0x000e4782, -/* 001C */ 0x00000734,0x00001000,0x00010705,0x000a6880, -/* 001E */ 0x00006a88,0x000c75c4 -}; -/* #CODE_END */ - -static struct dsp_segment_desc cwcsnoop_segments[] = { - { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code }, -}; - -static struct dsp_module_desc cwcsnoop_module = { - "cwcsnoop", - { - 3, - cwcsnoop_symbols - }, - 1, - cwcsnoop_segments, -}; - -#endif /* __HEADER_cwcsnoop_H__ */ diff --git a/ANDROID_3.4.5/sound/pci/cs5530.c b/ANDROID_3.4.5/sound/pci/cs5530.c deleted file mode 100644 index c47cabff..00000000 --- a/ANDROID_3.4.5/sound/pci/cs5530.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * cs5530.c - Initialisation code for Cyrix/NatSemi VSA1 softaudio - * - * (C) Copyright 2007 Ash Willis - * (C) Copyright 2003 Red Hat Inc - * - * This driver was ported (shamelessly ripped ;) from oss/kahlua.c but I did - * mess with it a bit. The chip seems to have to have trouble with full duplex - * mode. If we're recording in 8bit 8000kHz, say, and we then attempt to - * simultaneously play back audio at 16bit 44100kHz, the device actually plays - * back in the same format in which it is capturing. By forcing the chip to - * always play/capture in 16/44100, we can let alsa-lib convert the samples and - * that way we can hack up some full duplex audio. - * - * XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems. - * The older version (VSA1) provides fairly good soundblaster emulation - * although there are a couple of bugs: large DMA buffers break record, - * and the MPU event handling seems suspect. VSA2 allows the native driver - * to control the AC97 audio engine directly and requires a different driver. - * - * Thanks to National Semiconductor for providing the needed information - * on the XpressAudio(tm) internals. - * - * 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, 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. - * - * TO DO: - * Investigate whether we can portably support Cognac (5520) in the - * same manner. - */ - -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Ash Willis"); -MODULE_DESCRIPTION("CS5530 Audio"); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for CS5530 Audio driver."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for CS5530 Audio driver."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable CS5530 Audio driver."); - -struct snd_cs5530 { - struct snd_card *card; - struct pci_dev *pci; - struct snd_sb *sb; - unsigned long pci_base; -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_cs5530_ids) = { - {PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID, - PCI_ANY_ID, 0, 0}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, snd_cs5530_ids); - -static int snd_cs5530_free(struct snd_cs5530 *chip) -{ - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_cs5530_dev_free(struct snd_device *device) -{ - struct snd_cs5530 *chip = device->device_data; - return snd_cs5530_free(chip); -} - -static void __devexit snd_cs5530_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg) -{ - outb(reg, io + 4); - udelay(20); - reg = inb(io + 5); - udelay(20); - return reg; -} - -static int __devinit snd_cs5530_create(struct snd_card *card, - struct pci_dev *pci, - struct snd_cs5530 **rchip) -{ - struct snd_cs5530 *chip; - unsigned long sb_base; - u8 irq, dma8, dma16 = 0; - u16 map; - void __iomem *mem; - int err; - - static struct snd_device_ops ops = { - .dev_free = snd_cs5530_dev_free, - }; - *rchip = NULL; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - chip->pci = pci; - - err = pci_request_regions(pci, "CS5530"); - if (err < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->pci_base = pci_resource_start(pci, 0); - - mem = pci_ioremap_bar(pci, 0); - if (mem == NULL) { - kfree(chip); - pci_disable_device(pci); - return -EBUSY; - } - - map = readw(mem + 0x18); - iounmap(mem); - - /* Map bits - 0:1 * 0x20 + 0x200 = sb base - 2 sb enable - 3 adlib enable - 5 MPU enable 0x330 - 6 MPU enable 0x300 - - The other bits may be used internally so must be masked */ - - sb_base = 0x220 + 0x20 * (map & 3); - - if (map & (1<<2)) - printk(KERN_INFO "CS5530: XpressAudio at 0x%lx\n", sb_base); - else { - printk(KERN_ERR "Could not find XpressAudio!\n"); - snd_cs5530_free(chip); - return -ENODEV; - } - - if (map & (1<<5)) - printk(KERN_INFO "CS5530: MPU at 0x300\n"); - else if (map & (1<<6)) - printk(KERN_INFO "CS5530: MPU at 0x330\n"); - - irq = snd_cs5530_mixer_read(sb_base, 0x80) & 0x0F; - dma8 = snd_cs5530_mixer_read(sb_base, 0x81); - - if (dma8 & 0x20) - dma16 = 5; - else if (dma8 & 0x40) - dma16 = 6; - else if (dma8 & 0x80) - dma16 = 7; - else { - printk(KERN_ERR "CS5530: No 16bit DMA enabled\n"); - snd_cs5530_free(chip); - return -ENODEV; - } - - if (dma8 & 0x01) - dma8 = 0; - else if (dma8 & 02) - dma8 = 1; - else if (dma8 & 0x08) - dma8 = 3; - else { - printk(KERN_ERR "CS5530: No 8bit DMA enabled\n"); - snd_cs5530_free(chip); - return -ENODEV; - } - - if (irq & 1) - irq = 9; - else if (irq & 2) - irq = 5; - else if (irq & 4) - irq = 7; - else if (irq & 8) - irq = 10; - else { - printk(KERN_ERR "CS5530: SoundBlaster IRQ not set\n"); - snd_cs5530_free(chip); - return -ENODEV; - } - - printk(KERN_INFO "CS5530: IRQ: %d DMA8: %d DMA16: %d\n", irq, dma8, - dma16); - - err = snd_sbdsp_create(card, sb_base, irq, snd_sb16dsp_interrupt, dma8, - dma16, SB_HW_CS5530, &chip->sb); - if (err < 0) { - printk(KERN_ERR "CS5530: Could not create SoundBlaster\n"); - snd_cs5530_free(chip); - return err; - } - - err = snd_sb16dsp_pcm(chip->sb, 0, &chip->sb->pcm); - if (err < 0) { - printk(KERN_ERR "CS5530: Could not create PCM\n"); - snd_cs5530_free(chip); - return err; - } - - err = snd_sbmixer_new(chip->sb); - if (err < 0) { - printk(KERN_ERR "CS5530: Could not create Mixer\n"); - snd_cs5530_free(chip); - return err; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_cs5530_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - *rchip = chip; - return 0; -} - -static int __devinit snd_cs5530_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_cs5530 *chip = NULL; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - - if (err < 0) - return err; - - err = snd_cs5530_create(card, pci, &chip); - if (err < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "CS5530"); - strcpy(card->shortname, "CS5530 Audio"); - sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_cs5530_ids, - .probe = snd_cs5530_probe, - .remove = __devexit_p(snd_cs5530_remove), -}; - -static int __init alsa_card_cs5530_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_cs5530_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_cs5530_init) -module_exit(alsa_card_cs5530_exit) - diff --git a/ANDROID_3.4.5/sound/pci/cs5535audio/Makefile b/ANDROID_3.4.5/sound/pci/cs5535audio/Makefile deleted file mode 100644 index ccc64226..00000000 --- a/ANDROID_3.4.5/sound/pci/cs5535audio/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for cs5535audio -# - -snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o -snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o -snd-cs5535audio-$(CONFIG_OLPC) += cs5535audio_olpc.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o diff --git a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.c b/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.c deleted file mode 100644 index a2fb2173..00000000 --- a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Driver for audio on multifunction CS5535/6 companion device - * Copyright (C) Jaya Kumar - * - * Based on Jaroslav Kysela and Takashi Iwai's examples. - * This work was sponsored by CIS(M) Sdn Bhd. - * - * 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 -#include -#include -#include -#include -#include -#include "cs5535audio.h" - -#define DRIVER_NAME "cs5535audio" - -static char *ac97_quirk; -module_param(ac97_quirk, charp, 0444); -MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds."); - -static struct ac97_quirk ac97_quirks[] __devinitdata = { -#if 0 /* Not yet confirmed if all 5536 boards are HP only */ - { - .subvendor = PCI_VENDOR_ID_AMD, - .subdevice = PCI_DEVICE_ID_AMD_CS5536_AUDIO, - .name = "AMD RDK", - .type = AC97_TUNE_HP_ONLY - }, -#endif - {} -}; - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME); - -static DEFINE_PCI_DEVICE_TABLE(snd_cs5535audio_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO) }, - {} -}; - -MODULE_DEVICE_TABLE(pci, snd_cs5535audio_ids); - -static void wait_till_cmd_acked(struct cs5535audio *cs5535au, unsigned long timeout) -{ - unsigned int tmp; - do { - tmp = cs_readl(cs5535au, ACC_CODEC_CNTL); - if (!(tmp & CMD_NEW)) - break; - udelay(1); - } while (--timeout); - if (!timeout) - snd_printk(KERN_ERR "Failure writing to cs5535 codec\n"); -} - -static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au, - unsigned short reg) -{ - unsigned int regdata; - unsigned int timeout; - unsigned int val; - - regdata = ((unsigned int) reg) << 24; - regdata |= ACC_CODEC_CNTL_RD_CMD; - regdata |= CMD_NEW; - - cs_writel(cs5535au, ACC_CODEC_CNTL, regdata); - wait_till_cmd_acked(cs5535au, 50); - - timeout = 50; - do { - val = cs_readl(cs5535au, ACC_CODEC_STATUS); - if ((val & STS_NEW) && reg == (val >> 24)) - break; - udelay(1); - } while (--timeout); - if (!timeout) - snd_printk(KERN_ERR "Failure reading codec reg 0x%x," - "Last value=0x%x\n", reg, val); - - return (unsigned short) val; -} - -static void snd_cs5535audio_codec_write(struct cs5535audio *cs5535au, - unsigned short reg, unsigned short val) -{ - unsigned int regdata; - - regdata = ((unsigned int) reg) << 24; - regdata |= val; - regdata &= CMD_MASK; - regdata |= CMD_NEW; - regdata &= ACC_CODEC_CNTL_WR_CMD; - - cs_writel(cs5535au, ACC_CODEC_CNTL, regdata); - wait_till_cmd_acked(cs5535au, 50); -} - -static void snd_cs5535audio_ac97_codec_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - struct cs5535audio *cs5535au = ac97->private_data; - snd_cs5535audio_codec_write(cs5535au, reg, val); -} - -static unsigned short snd_cs5535audio_ac97_codec_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct cs5535audio *cs5535au = ac97->private_data; - return snd_cs5535audio_codec_read(cs5535au, reg); -} - -static int __devinit snd_cs5535audio_mixer(struct cs5535audio *cs5535au) -{ - struct snd_card *card = cs5535au->card; - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_cs5535audio_ac97_codec_write, - .read = snd_cs5535audio_ac97_codec_read, - }; - - if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.scaps = AC97_SCAP_AUDIO | AC97_SCAP_SKIP_MODEM - | AC97_SCAP_POWER_SAVE; - ac97.private_data = cs5535au; - ac97.pci = cs5535au->pci; - - /* set any OLPC-specific scaps */ - olpc_prequirks(card, &ac97); - - if ((err = snd_ac97_mixer(pbus, &ac97, &cs5535au->ac97)) < 0) { - snd_printk(KERN_ERR "mixer failed\n"); - return err; - } - - snd_ac97_tune_hardware(cs5535au->ac97, ac97_quirks, ac97_quirk); - - err = olpc_quirks(card, cs5535au->ac97); - if (err < 0) { - snd_printk(KERN_ERR "olpc quirks failed\n"); - return err; - } - - return 0; -} - -static void process_bm0_irq(struct cs5535audio *cs5535au) -{ - u8 bm_stat; - spin_lock(&cs5535au->reg_lock); - bm_stat = cs_readb(cs5535au, ACC_BM0_STATUS); - spin_unlock(&cs5535au->reg_lock); - if (bm_stat & EOP) { - struct cs5535audio_dma *dma; - dma = cs5535au->playback_substream->runtime->private_data; - snd_pcm_period_elapsed(cs5535au->playback_substream); - } else { - snd_printk(KERN_ERR "unexpected bm0 irq src, bm_stat=%x\n", - bm_stat); - } -} - -static void process_bm1_irq(struct cs5535audio *cs5535au) -{ - u8 bm_stat; - spin_lock(&cs5535au->reg_lock); - bm_stat = cs_readb(cs5535au, ACC_BM1_STATUS); - spin_unlock(&cs5535au->reg_lock); - if (bm_stat & EOP) { - struct cs5535audio_dma *dma; - dma = cs5535au->capture_substream->runtime->private_data; - snd_pcm_period_elapsed(cs5535au->capture_substream); - } -} - -static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id) -{ - u16 acc_irq_stat; - unsigned char count; - struct cs5535audio *cs5535au = dev_id; - - if (cs5535au == NULL) - return IRQ_NONE; - - acc_irq_stat = cs_readw(cs5535au, ACC_IRQ_STATUS); - - if (!acc_irq_stat) - return IRQ_NONE; - for (count = 0; count < 4; count++) { - if (acc_irq_stat & (1 << count)) { - switch (count) { - case IRQ_STS: - cs_readl(cs5535au, ACC_GPIO_STATUS); - break; - case WU_IRQ_STS: - cs_readl(cs5535au, ACC_GPIO_STATUS); - break; - case BM0_IRQ_STS: - process_bm0_irq(cs5535au); - break; - case BM1_IRQ_STS: - process_bm1_irq(cs5535au); - break; - default: - snd_printk(KERN_ERR "Unexpected irq src: " - "0x%x\n", acc_irq_stat); - break; - } - } - } - return IRQ_HANDLED; -} - -static int snd_cs5535audio_free(struct cs5535audio *cs5535au) -{ - synchronize_irq(cs5535au->irq); - pci_set_power_state(cs5535au->pci, 3); - - if (cs5535au->irq >= 0) - free_irq(cs5535au->irq, cs5535au); - - pci_release_regions(cs5535au->pci); - pci_disable_device(cs5535au->pci); - kfree(cs5535au); - return 0; -} - -static int snd_cs5535audio_dev_free(struct snd_device *device) -{ - struct cs5535audio *cs5535au = device->device_data; - return snd_cs5535audio_free(cs5535au); -} - -static int __devinit snd_cs5535audio_create(struct snd_card *card, - struct pci_dev *pci, - struct cs5535audio **rcs5535au) -{ - struct cs5535audio *cs5535au; - - int err; - static struct snd_device_ops ops = { - .dev_free = snd_cs5535audio_dev_free, - }; - - *rcs5535au = NULL; - if ((err = pci_enable_device(pci)) < 0) - return err; - - if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - printk(KERN_WARNING "unable to get 32bit dma\n"); - err = -ENXIO; - goto pcifail; - } - - cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL); - if (cs5535au == NULL) { - err = -ENOMEM; - goto pcifail; - } - - spin_lock_init(&cs5535au->reg_lock); - cs5535au->card = card; - cs5535au->pci = pci; - cs5535au->irq = -1; - - if ((err = pci_request_regions(pci, "CS5535 Audio")) < 0) { - kfree(cs5535au); - goto pcifail; - } - - cs5535au->port = pci_resource_start(pci, 0); - - if (request_irq(pci->irq, snd_cs5535audio_interrupt, - IRQF_SHARED, KBUILD_MODNAME, cs5535au)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - err = -EBUSY; - goto sndfail; - } - - cs5535au->irq = pci->irq; - pci_set_master(pci); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - cs5535au, &ops)) < 0) - goto sndfail; - - snd_card_set_dev(card, &pci->dev); - - *rcs5535au = cs5535au; - return 0; - -sndfail: /* leave the device alive, just kill the snd */ - snd_cs5535audio_free(cs5535au); - return err; - -pcifail: - pci_disable_device(pci); - return err; -} - -static int __devinit snd_cs5535audio_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct cs5535audio *cs5535au; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) - goto probefail_out; - - card->private_data = cs5535au; - - if ((err = snd_cs5535audio_mixer(cs5535au)) < 0) - goto probefail_out; - - if ((err = snd_cs5535audio_pcm(cs5535au)) < 0) - goto probefail_out; - - strcpy(card->driver, DRIVER_NAME); - - strcpy(card->shortname, "CS5535 Audio"); - sprintf(card->longname, "%s %s at 0x%lx, irq %i", - card->shortname, card->driver, - cs5535au->port, cs5535au->irq); - - if ((err = snd_card_register(card)) < 0) - goto probefail_out; - - pci_set_drvdata(pci, card); - dev++; - return 0; - -probefail_out: - snd_card_free(card); - return err; -} - -static void __devexit snd_cs5535audio_remove(struct pci_dev *pci) -{ - olpc_quirks_cleanup(); - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_cs5535audio_ids, - .probe = snd_cs5535audio_probe, - .remove = __devexit_p(snd_cs5535audio_remove), -#ifdef CONFIG_PM - .suspend = snd_cs5535audio_suspend, - .resume = snd_cs5535audio_resume, -#endif -}; - -static int __init alsa_card_cs5535audio_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_cs5535audio_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_cs5535audio_init) -module_exit(alsa_card_cs5535audio_exit) - -MODULE_AUTHOR("Jaya Kumar"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("CS5535 Audio"); -MODULE_SUPPORTED_DEVICE("CS5535 Audio"); diff --git a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.h b/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.h deleted file mode 100644 index 51966d78..00000000 --- a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef __SOUND_CS5535AUDIO_H -#define __SOUND_CS5535AUDIO_H - -#define cs_writel(cs5535au, reg, val) outl(val, (cs5535au)->port + reg) -#define cs_writeb(cs5535au, reg, val) outb(val, (cs5535au)->port + reg) -#define cs_readl(cs5535au, reg) inl((cs5535au)->port + reg) -#define cs_readw(cs5535au, reg) inw((cs5535au)->port + reg) -#define cs_readb(cs5535au, reg) inb((cs5535au)->port + reg) - -#define CS5535AUDIO_MAX_DESCRIPTORS 128 - -/* acc_codec bar0 reg addrs */ -#define ACC_GPIO_STATUS 0x00 -#define ACC_CODEC_STATUS 0x08 -#define ACC_CODEC_CNTL 0x0C -#define ACC_IRQ_STATUS 0x12 -#define ACC_BM0_CMD 0x20 -#define ACC_BM1_CMD 0x28 -#define ACC_BM0_PRD 0x24 -#define ACC_BM1_PRD 0x2C -#define ACC_BM0_STATUS 0x21 -#define ACC_BM1_STATUS 0x29 -#define ACC_BM0_PNTR 0x60 -#define ACC_BM1_PNTR 0x64 - -/* acc_codec bar0 reg bits */ -/* ACC_IRQ_STATUS */ -#define IRQ_STS 0 -#define WU_IRQ_STS 1 -#define BM0_IRQ_STS 2 -#define BM1_IRQ_STS 3 -/* ACC_BMX_STATUS */ -#define EOP (1<<0) -#define BM_EOP_ERR (1<<1) -/* ACC_BMX_CTL */ -#define BM_CTL_EN 0x01 -#define BM_CTL_PAUSE 0x03 -#define BM_CTL_DIS 0x00 -#define BM_CTL_BYTE_ORD_LE 0x00 -#define BM_CTL_BYTE_ORD_BE 0x04 -/* cs5535 specific ac97 codec register defines */ -#define CMD_MASK 0xFF00FFFF -#define CMD_NEW 0x00010000 -#define STS_NEW 0x00020000 -#define PRM_RDY_STS 0x00800000 -#define ACC_CODEC_CNTL_WR_CMD (~0x80000000) -#define ACC_CODEC_CNTL_RD_CMD 0x80000000 -#define ACC_CODEC_CNTL_LNK_SHUTDOWN 0x00040000 -#define ACC_CODEC_CNTL_LNK_WRM_RST 0x00020000 -#define PRD_JMP 0x2000 -#define PRD_EOP 0x4000 -#define PRD_EOT 0x8000 - -enum { CS5535AUDIO_DMA_PLAYBACK, CS5535AUDIO_DMA_CAPTURE, NUM_CS5535AUDIO_DMAS }; - -struct cs5535audio; - -struct cs5535audio_dma_ops { - int type; - void (*enable_dma)(struct cs5535audio *cs5535au); - void (*disable_dma)(struct cs5535audio *cs5535au); - void (*pause_dma)(struct cs5535audio *cs5535au); - void (*setup_prd)(struct cs5535audio *cs5535au, u32 prd_addr); - u32 (*read_prd)(struct cs5535audio *cs5535au); - u32 (*read_dma_pntr)(struct cs5535audio *cs5535au); -}; - -struct cs5535audio_dma_desc { - u32 addr; - u16 size; - u16 ctlreserved; -}; - -struct cs5535audio_dma { - const struct cs5535audio_dma_ops *ops; - struct snd_dma_buffer desc_buf; - struct snd_pcm_substream *substream; - unsigned int buf_addr, buf_bytes; - unsigned int period_bytes, periods; - u32 saved_prd; - int pcm_open_flag; -}; - -struct cs5535audio { - struct snd_card *card; - struct snd_ac97 *ac97; - struct snd_pcm *pcm; - int irq; - struct pci_dev *pci; - unsigned long port; - spinlock_t reg_lock; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS]; -}; - -#ifdef CONFIG_PM -int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state); -int snd_cs5535audio_resume(struct pci_dev *pci); -#endif - -#ifdef CONFIG_OLPC -void __devinit olpc_prequirks(struct snd_card *card, - struct snd_ac97_template *ac97); -int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97); -void __devexit olpc_quirks_cleanup(void); -void olpc_analog_input(struct snd_ac97 *ac97, int on); -void olpc_mic_bias(struct snd_ac97 *ac97, int on); - -static inline void olpc_capture_open(struct snd_ac97 *ac97) -{ - /* default to Analog Input off */ - olpc_analog_input(ac97, 0); - /* enable MIC Bias for recording */ - olpc_mic_bias(ac97, 1); -} - -static inline void olpc_capture_close(struct snd_ac97 *ac97) -{ - /* disable Analog Input */ - olpc_analog_input(ac97, 0); - /* disable the MIC Bias (so the recording LED turns off) */ - olpc_mic_bias(ac97, 0); -} -#else -static inline void olpc_prequirks(struct snd_card *card, - struct snd_ac97_template *ac97) { } -static inline int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) -{ - return 0; -} -static inline void olpc_quirks_cleanup(void) { } -static inline void olpc_analog_input(struct snd_ac97 *ac97, int on) { } -static inline void olpc_mic_bias(struct snd_ac97 *ac97, int on) { } -static inline void olpc_capture_open(struct snd_ac97 *ac97) { } -static inline void olpc_capture_close(struct snd_ac97 *ac97) { } -#endif - -int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio); - -#endif /* __SOUND_CS5535AUDIO_H */ - diff --git a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_olpc.c b/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_olpc.c deleted file mode 100644 index 50da49be..00000000 --- a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_olpc.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * OLPC XO-1 additional sound features - * - * Copyright © 2006 Jaya Kumar - * Copyright © 2007-2008 Andres Salomon - * - * 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. - */ -#include -#include -#include -#include -#include - -#include -#include "cs5535audio.h" - -#define DRV_NAME "cs5535audio-olpc" - -/* - * OLPC has an additional feature on top of the regular AD1888 codec features. - * It has an Analog Input mode that is switched into (after disabling the - * High Pass Filter) via GPIO. It is supported on B2 and later models. - */ -void olpc_analog_input(struct snd_ac97 *ac97, int on) -{ - int err; - - if (!machine_is_olpc()) - return; - - /* update the High Pass Filter (via AC97_AD_TEST2) */ - err = snd_ac97_update_bits(ac97, AC97_AD_TEST2, - 1 << AC97_AD_HPFD_SHIFT, on << AC97_AD_HPFD_SHIFT); - if (err < 0) { - snd_printk(KERN_ERR "setting High Pass Filter - %d\n", err); - return; - } - - /* set Analog Input through GPIO */ - gpio_set_value(OLPC_GPIO_MIC_AC, on); -} - -/* - * OLPC XO-1's V_REFOUT is a mic bias enable. - */ -void olpc_mic_bias(struct snd_ac97 *ac97, int on) -{ - int err; - - if (!machine_is_olpc()) - return; - - on = on ? 0 : 1; - err = snd_ac97_update_bits(ac97, AC97_AD_MISC, - 1 << AC97_AD_VREFD_SHIFT, on << AC97_AD_VREFD_SHIFT); - if (err < 0) - snd_printk(KERN_ERR "setting MIC Bias - %d\n", err); -} - -static int olpc_dc_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int olpc_dc_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v) -{ - v->value.integer.value[0] = gpio_get_value(OLPC_GPIO_MIC_AC); - return 0; -} - -static int olpc_dc_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v) -{ - struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl); - - olpc_analog_input(cs5535au->ac97, v->value.integer.value[0]); - return 1; -} - -static int olpc_mic_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int olpc_mic_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v) -{ - struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl); - struct snd_ac97 *ac97 = cs5535au->ac97; - int i; - - i = (snd_ac97_read(ac97, AC97_AD_MISC) >> AC97_AD_VREFD_SHIFT) & 0x1; - v->value.integer.value[0] = i ? 0 : 1; - return 0; -} - -static int olpc_mic_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v) -{ - struct cs5535audio *cs5535au = snd_kcontrol_chip(kctl); - - olpc_mic_bias(cs5535au->ac97, v->value.integer.value[0]); - return 1; -} - -static struct snd_kcontrol_new olpc_cs5535audio_ctls[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DC Mode Enable", - .info = olpc_dc_info, - .get = olpc_dc_get, - .put = olpc_dc_put, - .private_value = 0, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "MIC Bias Enable", - .info = olpc_mic_info, - .get = olpc_mic_get, - .put = olpc_mic_put, - .private_value = 0, -}, -}; - -void __devinit olpc_prequirks(struct snd_card *card, - struct snd_ac97_template *ac97) -{ - if (!machine_is_olpc()) - return; - - /* invert EAPD if on an OLPC B3 or higher */ - if (olpc_board_at_least(olpc_board_pre(0xb3))) - ac97->scaps |= AC97_SCAP_INV_EAPD; -} - -int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) -{ - struct snd_ctl_elem_id elem; - int i, err; - - if (!machine_is_olpc()) - return 0; - - if (gpio_request(OLPC_GPIO_MIC_AC, DRV_NAME)) { - printk(KERN_ERR DRV_NAME ": unable to allocate MIC GPIO\n"); - return -EIO; - } - gpio_direction_output(OLPC_GPIO_MIC_AC, 0); - - /* drop the original AD1888 HPF control */ - memset(&elem, 0, sizeof(elem)); - elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strncpy(elem.name, "High Pass Filter Enable", sizeof(elem.name)); - snd_ctl_remove_id(card, &elem); - - /* drop the original V_REFOUT control */ - memset(&elem, 0, sizeof(elem)); - elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strncpy(elem.name, "V_REFOUT Enable", sizeof(elem.name)); - snd_ctl_remove_id(card, &elem); - - /* add the OLPC-specific controls */ - for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) { - err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i], - ac97->private_data)); - if (err < 0) { - gpio_free(OLPC_GPIO_MIC_AC); - return err; - } - } - - /* turn off the mic by default */ - olpc_mic_bias(ac97, 0); - return 0; -} - -void __devexit olpc_quirks_cleanup(void) -{ - gpio_free(OLPC_GPIO_MIC_AC); -} diff --git a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_pcm.c b/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_pcm.c deleted file mode 100644 index dbf94b18..00000000 --- a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_pcm.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Driver for audio on multifunction CS5535 companion device - * Copyright (C) Jaya Kumar - * - * Based on Jaroslav Kysela and Takashi Iwai's examples. - * This work was sponsored by CIS(M) Sdn Bhd. - * - * 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 - * - * todo: add be fmt support, spdif, pm - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cs5535audio.h" - -static struct snd_pcm_hardware snd_cs5535audio_playback = -{ - .info = ( - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME - ), - .formats = ( - SNDRV_PCM_FMTBIT_S16_LE - ), - .rates = ( - SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000 - ), - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (64*1024 - 16), - .periods_min = 1, - .periods_max = CS5535AUDIO_MAX_DESCRIPTORS, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_cs5535audio_capture = -{ - .info = ( - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID - ), - .formats = ( - SNDRV_PCM_FMTBIT_S16_LE - ), - .rates = ( - SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000 - ), - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (64*1024 - 16), - .periods_min = 1, - .periods_max = CS5535AUDIO_MAX_DESCRIPTORS, - .fifo_size = 0, -}; - -static int snd_cs5535audio_playback_open(struct snd_pcm_substream *substream) -{ - int err; - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_cs5535audio_playback; - runtime->hw.rates = cs5535au->ac97->rates[AC97_RATES_FRONT_DAC]; - snd_pcm_limit_hw_rates(runtime); - cs5535au->playback_substream = substream; - runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]); - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - return 0; -} - -static int snd_cs5535audio_playback_close(struct snd_pcm_substream *substream) -{ - return 0; -} - -#define CS5535AUDIO_DESC_LIST_SIZE \ - PAGE_ALIGN(CS5535AUDIO_MAX_DESCRIPTORS * sizeof(struct cs5535audio_dma_desc)) - -static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, - struct cs5535audio_dma *dma, - struct snd_pcm_substream *substream, - unsigned int periods, - unsigned int period_bytes) -{ - unsigned int i; - u32 addr, desc_addr, jmpprd_addr; - struct cs5535audio_dma_desc *lastdesc; - - if (periods > CS5535AUDIO_MAX_DESCRIPTORS) - return -ENOMEM; - - if (dma->desc_buf.area == NULL) { - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(cs5535au->pci), - CS5535AUDIO_DESC_LIST_SIZE+1, - &dma->desc_buf) < 0) - return -ENOMEM; - dma->period_bytes = dma->periods = 0; - } - - if (dma->periods == periods && dma->period_bytes == period_bytes) - return 0; - - /* the u32 cast is okay because in snd*create we successfully told - pci alloc that we're only 32 bit capable so the uppper will be 0 */ - addr = (u32) substream->runtime->dma_addr; - desc_addr = (u32) dma->desc_buf.addr; - for (i = 0; i < periods; i++) { - struct cs5535audio_dma_desc *desc = - &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[i]; - desc->addr = cpu_to_le32(addr); - desc->size = cpu_to_le16(period_bytes); - desc->ctlreserved = cpu_to_le16(PRD_EOP); - desc_addr += sizeof(struct cs5535audio_dma_desc); - addr += period_bytes; - } - /* we reserved one dummy descriptor at the end to do the PRD jump */ - lastdesc = &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[periods]; - lastdesc->addr = cpu_to_le32((u32) dma->desc_buf.addr); - lastdesc->size = 0; - lastdesc->ctlreserved = cpu_to_le16(PRD_JMP); - jmpprd_addr = cpu_to_le32(lastdesc->addr + - (sizeof(struct cs5535audio_dma_desc)*periods)); - - dma->substream = substream; - dma->period_bytes = period_bytes; - dma->periods = periods; - spin_lock_irq(&cs5535au->reg_lock); - dma->ops->disable_dma(cs5535au); - dma->ops->setup_prd(cs5535au, jmpprd_addr); - spin_unlock_irq(&cs5535au->reg_lock); - return 0; -} - -static void cs5535audio_playback_enable_dma(struct cs5535audio *cs5535au) -{ - cs_writeb(cs5535au, ACC_BM0_CMD, BM_CTL_EN); -} - -static void cs5535audio_playback_disable_dma(struct cs5535audio *cs5535au) -{ - cs_writeb(cs5535au, ACC_BM0_CMD, 0); -} - -static void cs5535audio_playback_pause_dma(struct cs5535audio *cs5535au) -{ - cs_writeb(cs5535au, ACC_BM0_CMD, BM_CTL_PAUSE); -} - -static void cs5535audio_playback_setup_prd(struct cs5535audio *cs5535au, - u32 prd_addr) -{ - cs_writel(cs5535au, ACC_BM0_PRD, prd_addr); -} - -static u32 cs5535audio_playback_read_prd(struct cs5535audio *cs5535au) -{ - return cs_readl(cs5535au, ACC_BM0_PRD); -} - -static u32 cs5535audio_playback_read_dma_pntr(struct cs5535audio *cs5535au) -{ - return cs_readl(cs5535au, ACC_BM0_PNTR); -} - -static void cs5535audio_capture_enable_dma(struct cs5535audio *cs5535au) -{ - cs_writeb(cs5535au, ACC_BM1_CMD, BM_CTL_EN); -} - -static void cs5535audio_capture_disable_dma(struct cs5535audio *cs5535au) -{ - cs_writeb(cs5535au, ACC_BM1_CMD, 0); -} - -static void cs5535audio_capture_pause_dma(struct cs5535audio *cs5535au) -{ - cs_writeb(cs5535au, ACC_BM1_CMD, BM_CTL_PAUSE); -} - -static void cs5535audio_capture_setup_prd(struct cs5535audio *cs5535au, - u32 prd_addr) -{ - cs_writel(cs5535au, ACC_BM1_PRD, prd_addr); -} - -static u32 cs5535audio_capture_read_prd(struct cs5535audio *cs5535au) -{ - return cs_readl(cs5535au, ACC_BM1_PRD); -} - -static u32 cs5535audio_capture_read_dma_pntr(struct cs5535audio *cs5535au) -{ - return cs_readl(cs5535au, ACC_BM1_PNTR); -} - -static void cs5535audio_clear_dma_packets(struct cs5535audio *cs5535au, - struct cs5535audio_dma *dma, - struct snd_pcm_substream *substream) -{ - snd_dma_free_pages(&dma->desc_buf); - dma->desc_buf.area = NULL; - dma->substream = NULL; -} - -static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - struct cs5535audio_dma *dma = substream->runtime->private_data; - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - dma->buf_addr = substream->runtime->dma_addr; - dma->buf_bytes = params_buffer_bytes(hw_params); - - err = cs5535audio_build_dma_packets(cs5535au, dma, substream, - params_periods(hw_params), - params_period_bytes(hw_params)); - if (!err) - dma->pcm_open_flag = 1; - - return err; -} - -static int snd_cs5535audio_hw_free(struct snd_pcm_substream *substream) -{ - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - struct cs5535audio_dma *dma = substream->runtime->private_data; - - if (dma->pcm_open_flag) { - if (substream == cs5535au->playback_substream) - snd_ac97_update_power(cs5535au->ac97, - AC97_PCM_FRONT_DAC_RATE, 0); - else - snd_ac97_update_power(cs5535au->ac97, - AC97_PCM_LR_ADC_RATE, 0); - dma->pcm_open_flag = 0; - } - cs5535audio_clear_dma_packets(cs5535au, dma, substream); - return snd_pcm_lib_free_pages(substream); -} - -static int snd_cs5535audio_playback_prepare(struct snd_pcm_substream *substream) -{ - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - return snd_ac97_set_rate(cs5535au->ac97, AC97_PCM_FRONT_DAC_RATE, - substream->runtime->rate); -} - -static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - struct cs5535audio_dma *dma = substream->runtime->private_data; - int err = 0; - - spin_lock(&cs5535au->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - dma->ops->pause_dma(cs5535au); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - dma->ops->enable_dma(cs5535au); - break; - case SNDRV_PCM_TRIGGER_START: - dma->ops->enable_dma(cs5535au); - break; - case SNDRV_PCM_TRIGGER_RESUME: - dma->ops->enable_dma(cs5535au); - break; - case SNDRV_PCM_TRIGGER_STOP: - dma->ops->disable_dma(cs5535au); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - dma->ops->disable_dma(cs5535au); - break; - default: - snd_printk(KERN_ERR "unhandled trigger\n"); - err = -EINVAL; - break; - } - spin_unlock(&cs5535au->reg_lock); - return err; -} - -static snd_pcm_uframes_t snd_cs5535audio_pcm_pointer(struct snd_pcm_substream - *substream) -{ - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - u32 curdma; - struct cs5535audio_dma *dma; - - dma = substream->runtime->private_data; - curdma = dma->ops->read_dma_pntr(cs5535au); - if (curdma < dma->buf_addr) { - snd_printk(KERN_ERR "curdma=%x < %x bufaddr.\n", - curdma, dma->buf_addr); - return 0; - } - curdma -= dma->buf_addr; - if (curdma >= dma->buf_bytes) { - snd_printk(KERN_ERR "diff=%x >= %x buf_bytes.\n", - curdma, dma->buf_bytes); - return 0; - } - return bytes_to_frames(substream->runtime, curdma); -} - -static int snd_cs5535audio_capture_open(struct snd_pcm_substream *substream) -{ - int err; - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_cs5535audio_capture; - runtime->hw.rates = cs5535au->ac97->rates[AC97_RATES_ADC]; - snd_pcm_limit_hw_rates(runtime); - cs5535au->capture_substream = substream; - runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]); - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - olpc_capture_open(cs5535au->ac97); - return 0; -} - -static int snd_cs5535audio_capture_close(struct snd_pcm_substream *substream) -{ - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - olpc_capture_close(cs5535au->ac97); - return 0; -} - -static int snd_cs5535audio_capture_prepare(struct snd_pcm_substream *substream) -{ - struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream); - return snd_ac97_set_rate(cs5535au->ac97, AC97_PCM_LR_ADC_RATE, - substream->runtime->rate); -} - -static struct snd_pcm_ops snd_cs5535audio_playback_ops = { - .open = snd_cs5535audio_playback_open, - .close = snd_cs5535audio_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs5535audio_hw_params, - .hw_free = snd_cs5535audio_hw_free, - .prepare = snd_cs5535audio_playback_prepare, - .trigger = snd_cs5535audio_trigger, - .pointer = snd_cs5535audio_pcm_pointer, -}; - -static struct snd_pcm_ops snd_cs5535audio_capture_ops = { - .open = snd_cs5535audio_capture_open, - .close = snd_cs5535audio_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cs5535audio_hw_params, - .hw_free = snd_cs5535audio_hw_free, - .prepare = snd_cs5535audio_capture_prepare, - .trigger = snd_cs5535audio_trigger, - .pointer = snd_cs5535audio_pcm_pointer, -}; - -static struct cs5535audio_dma_ops snd_cs5535audio_playback_dma_ops = { - .type = CS5535AUDIO_DMA_PLAYBACK, - .enable_dma = cs5535audio_playback_enable_dma, - .disable_dma = cs5535audio_playback_disable_dma, - .setup_prd = cs5535audio_playback_setup_prd, - .read_prd = cs5535audio_playback_read_prd, - .pause_dma = cs5535audio_playback_pause_dma, - .read_dma_pntr = cs5535audio_playback_read_dma_pntr, -}; - -static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = { - .type = CS5535AUDIO_DMA_CAPTURE, - .enable_dma = cs5535audio_capture_enable_dma, - .disable_dma = cs5535audio_capture_disable_dma, - .setup_prd = cs5535audio_capture_setup_prd, - .read_prd = cs5535audio_capture_read_prd, - .pause_dma = cs5535audio_capture_pause_dma, - .read_dma_pntr = cs5535audio_capture_read_dma_pntr, -}; - -int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(cs5535au->card, "CS5535 Audio", 0, 1, 1, &pcm); - if (err < 0) - return err; - - cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK].ops = - &snd_cs5535audio_playback_dma_ops; - cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE].ops = - &snd_cs5535audio_capture_dma_ops; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_cs5535audio_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_cs5535audio_capture_ops); - - pcm->private_data = cs5535au; - pcm->info_flags = 0; - strcpy(pcm->name, "CS5535 Audio"); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(cs5535au->pci), - 64*1024, 128*1024); - cs5535au->pcm = pcm; - - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_pm.c b/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_pm.c deleted file mode 100644 index 185b0008..00000000 --- a/ANDROID_3.4.5/sound/pci/cs5535audio/cs5535audio_pm.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Power management for audio on multifunction CS5535 companion device - * Copyright (C) Jaya Kumar - * - * 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 -#include "cs5535audio.h" - -static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au) -{ - /* - we depend on snd_ac97_suspend to tell the - AC97 codec to shutdown. the amd spec suggests - that the LNK_SHUTDOWN be done at the same time - that the codec power-down is issued. instead, - we do it just after rather than at the same - time. excluding codec specific build_ops->suspend - ac97 powerdown hits: - 0x8000 EAPD - 0x4000 Headphone amplifier - 0x0300 ADC & DAC - 0x0400 Analog Mixer powerdown (Vref on) - I am not sure if this is the best that we can do. - The remainder to be investigated are: - - analog mixer (vref off) 0x0800 - - AC-link powerdown 0x1000 - - codec internal clock 0x2000 - */ - - /* set LNK_SHUTDOWN to shutdown AC link */ - cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN); - -} - -int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct cs5535audio *cs5535au = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(cs5535au->pcm); - snd_ac97_suspend(cs5535au->ac97); - for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { - struct cs5535audio_dma *dma = &cs5535au->dmas[i]; - if (dma && dma->substream) - dma->saved_prd = dma->ops->read_prd(cs5535au); - } - /* save important regs, then disable aclink in hw */ - snd_cs5535audio_stop_hardware(cs5535au); - - if (pci_save_state(pci)) { - printk(KERN_ERR "cs5535audio: pci_save_state failed!\n"); - return -EIO; - } - pci_disable_device(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -int snd_cs5535audio_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct cs5535audio *cs5535au = card->private_data; - u32 tmp; - int timeout; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "cs5535audio: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - /* set LNK_WRM_RST to reset AC link */ - cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST); - - timeout = 50; - do { - tmp = cs_readl(cs5535au, ACC_CODEC_STATUS); - if (tmp & PRM_RDY_STS) - break; - udelay(1); - } while (--timeout); - - if (!timeout) - snd_printk(KERN_ERR "Failure getting AC Link ready\n"); - - /* set up rate regs, dma. actual initiation is done in trig */ - for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { - struct cs5535audio_dma *dma = &cs5535au->dmas[i]; - if (dma && dma->substream) { - dma->substream->ops->prepare(dma->substream); - dma->ops->setup_prd(cs5535au, dma->saved_prd); - } - } - - /* we depend on ac97 to perform the codec power up */ - snd_ac97_resume(cs5535au->ac97); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/Makefile b/ANDROID_3.4.5/sound/pci/ctxfi/Makefile deleted file mode 100644 index 15075f89..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -snd-ctxfi-objs := xfi.o ctatc.o ctvmem.o ctpcm.o ctmixer.o ctresource.o \ - ctsrc.o ctamixer.o ctdaio.o ctimap.o cthardware.o cttimer.o \ - cthw20k2.o cthw20k1.o - -obj-$(CONFIG_SND_CTXFI) += snd-ctxfi.o diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ct20k1reg.h b/ANDROID_3.4.5/sound/pci/ctxfi/ct20k1reg.h deleted file mode 100644 index f2e34e3f..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ct20k1reg.h +++ /dev/null @@ -1,636 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - */ - -#ifndef CT20K1REG_H -#define CT20k1REG_H - -/* 20k1 registers */ -#define DSPXRAM_START 0x000000 -#define DSPXRAM_END 0x013FFC -#define DSPAXRAM_START 0x020000 -#define DSPAXRAM_END 0x023FFC -#define DSPYRAM_START 0x040000 -#define DSPYRAM_END 0x04FFFC -#define DSPAYRAM_START 0x020000 -#define DSPAYRAM_END 0x063FFC -#define DSPMICRO_START 0x080000 -#define DSPMICRO_END 0x0B3FFC -#define DSP0IO_START 0x100000 -#define DSP0IO_END 0x101FFC -#define AUDIORINGIPDSP0_START 0x100000 -#define AUDIORINGIPDSP0_END 0x1003FC -#define AUDIORINGOPDSP0_START 0x100400 -#define AUDIORINGOPDSP0_END 0x1007FC -#define AUDPARARINGIODSP0_START 0x100800 -#define AUDPARARINGIODSP0_END 0x100BFC -#define DSP0LOCALHWREG_START 0x100C00 -#define DSP0LOCALHWREG_END 0x100C3C -#define DSP0XYRAMAGINDEX_START 0x100C40 -#define DSP0XYRAMAGINDEX_END 0x100C5C -#define DSP0XYRAMAGMDFR_START 0x100C60 -#define DSP0XYRAMAGMDFR_END 0x100C7C -#define DSP0INTCONTLVEC_START 0x100C80 -#define DSP0INTCONTLVEC_END 0x100CD8 -#define INTCONTLGLOBALREG_START 0x100D1C -#define INTCONTLGLOBALREG_END 0x100D3C -#define HOSTINTFPORTADDRCONTDSP0 0x100D40 -#define HOSTINTFPORTDATADSP0 0x100D44 -#define TIME0PERENBDSP0 0x100D60 -#define TIME0COUNTERDSP0 0x100D64 -#define TIME1PERENBDSP0 0x100D68 -#define TIME1COUNTERDSP0 0x100D6C -#define TIME2PERENBDSP0 0x100D70 -#define TIME2COUNTERDSP0 0x100D74 -#define TIME3PERENBDSP0 0x100D78 -#define TIME3COUNTERDSP0 0x100D7C -#define XRAMINDOPERREFNOUP_STARTDSP0 0x100D80 -#define XRAMINDOPERREFNOUP_ENDDSP0 0x100D9C -#define XRAMINDOPERREFUP_STARTDSP0 0x100DA0 -#define XRAMINDOPERREFUP_ENDDSP0 0x100DBC -#define YRAMINDOPERREFNOUP_STARTDSP0 0x100DC0 -#define YRAMINDOPERREFNOUP_ENDDSP0 0x100DDC -#define YRAMINDOPERREFUP_STARTDSP0 0x100DE0 -#define YRAMINDOPERREFUP_ENDDSP0 0x100DFC -#define DSP0CONDCODE 0x100E00 -#define DSP0STACKFLAG 0x100E04 -#define DSP0PROGCOUNTSTACKPTREG 0x100E08 -#define DSP0PROGCOUNTSTACKDATAREG 0x100E0C -#define DSP0CURLOOPADDRREG 0x100E10 -#define DSP0CURLOOPCOUNT 0x100E14 -#define DSP0TOPLOOPCOUNTSTACK 0x100E18 -#define DSP0TOPLOOPADDRSTACK 0x100E1C -#define DSP0LOOPSTACKPTR 0x100E20 -#define DSP0STASSTACKDATAREG 0x100E24 -#define DSP0STASSTACKPTR 0x100E28 -#define DSP0PROGCOUNT 0x100E2C -#define GLOBDSPDEBGREG 0x100E30 -#define GLOBDSPBREPTRREG 0x100E30 -#define DSP0XYRAMBASE_START 0x100EA0 -#define DSP0XYRAMBASE_END 0x100EBC -#define DSP0XYRAMLENG_START 0x100EC0 -#define DSP0XYRAMLENG_END 0x100EDC -#define SEMAPHOREREGDSP0 0x100EE0 -#define DSP0INTCONTMASKREG 0x100EE4 -#define DSP0INTCONTPENDREG 0x100EE8 -#define DSP0INTCONTSERVINT 0x100EEC -#define DSPINTCONTEXTINTMODREG 0x100EEC -#define GPIODSP0 0x100EFC -#define DMADSPBASEADDRREG_STARTDSP0 0x100F00 -#define DMADSPBASEADDRREG_ENDDSP0 0x100F1C -#define DMAHOSTBASEADDRREG_STARTDSP0 0x100F20 -#define DMAHOSTBASEADDRREG_ENDDSP0 0x100F3C -#define DMADSPCURADDRREG_STARTDSP0 0x100F40 -#define DMADSPCURADDRREG_ENDDSP0 0x100F5C -#define DMAHOSTCURADDRREG_STARTDSP0 0x100F60 -#define DMAHOSTCURADDRREG_ENDDSP0 0x100F7C -#define DMATANXCOUNTREG_STARTDSP0 0x100F80 -#define DMATANXCOUNTREG_ENDDSP0 0x100F9C -#define DMATIMEBUGREG_STARTDSP0 0x100FA0 -#define DMATIMEBUGREG_ENDDSP0 0x100FAC -#define DMACNTLMODFREG_STARTDSP0 0x100FA0 -#define DMACNTLMODFREG_ENDDSP0 0x100FAC - -#define DMAGLOBSTATSREGDSP0 0x100FEC -#define DSP0XGPRAM_START 0x101000 -#define DSP0XGPRAM_END 0x1017FC -#define DSP0YGPRAM_START 0x101800 -#define DSP0YGPRAM_END 0x101FFC - - - - -#define AUDIORINGIPDSP1_START 0x102000 -#define AUDIORINGIPDSP1_END 0x1023FC -#define AUDIORINGOPDSP1_START 0x102400 -#define AUDIORINGOPDSP1_END 0x1027FC -#define AUDPARARINGIODSP1_START 0x102800 -#define AUDPARARINGIODSP1_END 0x102BFC -#define DSP1LOCALHWREG_START 0x102C00 -#define DSP1LOCALHWREG_END 0x102C3C -#define DSP1XYRAMAGINDEX_START 0x102C40 -#define DSP1XYRAMAGINDEX_END 0x102C5C -#define DSP1XYRAMAGMDFR_START 0x102C60 -#define DSP1XYRAMAGMDFR_END 0x102C7C -#define DSP1INTCONTLVEC_START 0x102C80 -#define DSP1INTCONTLVEC_END 0x102CD8 -#define HOSTINTFPORTADDRCONTDSP1 0x102D40 -#define HOSTINTFPORTDATADSP1 0x102D44 -#define TIME0PERENBDSP1 0x102D60 -#define TIME0COUNTERDSP1 0x102D64 -#define TIME1PERENBDSP1 0x102D68 -#define TIME1COUNTERDSP1 0x102D6C -#define TIME2PERENBDSP1 0x102D70 -#define TIME2COUNTERDSP1 0x102D74 -#define TIME3PERENBDSP1 0x102D78 -#define TIME3COUNTERDSP1 0x102D7C -#define XRAMINDOPERREFNOUP_STARTDSP1 0x102D80 -#define XRAMINDOPERREFNOUP_ENDDSP1 0x102D9C -#define XRAMINDOPERREFUP_STARTDSP1 0x102DA0 -#define XRAMINDOPERREFUP_ENDDSP1 0x102DBC -#define YRAMINDOPERREFNOUP_STARTDSP1 0x102DC0 -#define YRAMINDOPERREFNOUP_ENDDSP1 0x102DDC -#define YRAMINDOPERREFUP_STARTDSP1 0x102DE0 -#define YRAMINDOPERREFUP_ENDDSP1 0x102DFC - -#define DSP1CONDCODE 0x102E00 -#define DSP1STACKFLAG 0x102E04 -#define DSP1PROGCOUNTSTACKPTREG 0x102E08 -#define DSP1PROGCOUNTSTACKDATAREG 0x102E0C -#define DSP1CURLOOPADDRREG 0x102E10 -#define DSP1CURLOOPCOUNT 0x102E14 -#define DSP1TOPLOOPCOUNTSTACK 0x102E18 -#define DSP1TOPLOOPADDRSTACK 0x102E1C -#define DSP1LOOPSTACKPTR 0x102E20 -#define DSP1STASSTACKDATAREG 0x102E24 -#define DSP1STASSTACKPTR 0x102E28 -#define DSP1PROGCOUNT 0x102E2C -#define DSP1XYRAMBASE_START 0x102EA0 -#define DSP1XYRAMBASE_END 0x102EBC -#define DSP1XYRAMLENG_START 0x102EC0 -#define DSP1XYRAMLENG_END 0x102EDC -#define SEMAPHOREREGDSP1 0x102EE0 -#define DSP1INTCONTMASKREG 0x102EE4 -#define DSP1INTCONTPENDREG 0x102EE8 -#define DSP1INTCONTSERVINT 0x102EEC -#define GPIODSP1 0x102EFC -#define DMADSPBASEADDRREG_STARTDSP1 0x102F00 -#define DMADSPBASEADDRREG_ENDDSP1 0x102F1C -#define DMAHOSTBASEADDRREG_STARTDSP1 0x102F20 -#define DMAHOSTBASEADDRREG_ENDDSP1 0x102F3C -#define DMADSPCURADDRREG_STARTDSP1 0x102F40 -#define DMADSPCURADDRREG_ENDDSP1 0x102F5C -#define DMAHOSTCURADDRREG_STARTDSP1 0x102F60 -#define DMAHOSTCURADDRREG_ENDDSP1 0x102F7C -#define DMATANXCOUNTREG_STARTDSP1 0x102F80 -#define DMATANXCOUNTREG_ENDDSP1 0x102F9C -#define DMATIMEBUGREG_STARTDSP1 0x102FA0 -#define DMATIMEBUGREG_ENDDSP1 0x102FAC -#define DMACNTLMODFREG_STARTDSP1 0x102FA0 -#define DMACNTLMODFREG_ENDDSP1 0x102FAC - -#define DMAGLOBSTATSREGDSP1 0x102FEC -#define DSP1XGPRAM_START 0x103000 -#define DSP1XGPRAM_END 0x1033FC -#define DSP1YGPRAM_START 0x103400 -#define DSP1YGPRAM_END 0x1037FC - - - -#define AUDIORINGIPDSP2_START 0x104000 -#define AUDIORINGIPDSP2_END 0x1043FC -#define AUDIORINGOPDSP2_START 0x104400 -#define AUDIORINGOPDSP2_END 0x1047FC -#define AUDPARARINGIODSP2_START 0x104800 -#define AUDPARARINGIODSP2_END 0x104BFC -#define DSP2LOCALHWREG_START 0x104C00 -#define DSP2LOCALHWREG_END 0x104C3C -#define DSP2XYRAMAGINDEX_START 0x104C40 -#define DSP2XYRAMAGINDEX_END 0x104C5C -#define DSP2XYRAMAGMDFR_START 0x104C60 -#define DSP2XYRAMAGMDFR_END 0x104C7C -#define DSP2INTCONTLVEC_START 0x104C80 -#define DSP2INTCONTLVEC_END 0x104CD8 -#define HOSTINTFPORTADDRCONTDSP2 0x104D40 -#define HOSTINTFPORTDATADSP2 0x104D44 -#define TIME0PERENBDSP2 0x104D60 -#define TIME0COUNTERDSP2 0x104D64 -#define TIME1PERENBDSP2 0x104D68 -#define TIME1COUNTERDSP2 0x104D6C -#define TIME2PERENBDSP2 0x104D70 -#define TIME2COUNTERDSP2 0x104D74 -#define TIME3PERENBDSP2 0x104D78 -#define TIME3COUNTERDSP2 0x104D7C -#define XRAMINDOPERREFNOUP_STARTDSP2 0x104D80 -#define XRAMINDOPERREFNOUP_ENDDSP2 0x104D9C -#define XRAMINDOPERREFUP_STARTDSP2 0x104DA0 -#define XRAMINDOPERREFUP_ENDDSP2 0x104DBC -#define YRAMINDOPERREFNOUP_STARTDSP2 0x104DC0 -#define YRAMINDOPERREFNOUP_ENDDSP2 0x104DDC -#define YRAMINDOPERREFUP_STARTDSP2 0x104DE0 -#define YRAMINDOPERREFUP_ENDDSP2 0x104DFC -#define DSP2CONDCODE 0x104E00 -#define DSP2STACKFLAG 0x104E04 -#define DSP2PROGCOUNTSTACKPTREG 0x104E08 -#define DSP2PROGCOUNTSTACKDATAREG 0x104E0C -#define DSP2CURLOOPADDRREG 0x104E10 -#define DSP2CURLOOPCOUNT 0x104E14 -#define DSP2TOPLOOPCOUNTSTACK 0x104E18 -#define DSP2TOPLOOPADDRSTACK 0x104E1C -#define DSP2LOOPSTACKPTR 0x104E20 -#define DSP2STASSTACKDATAREG 0x104E24 -#define DSP2STASSTACKPTR 0x104E28 -#define DSP2PROGCOUNT 0x104E2C -#define DSP2XYRAMBASE_START 0x104EA0 -#define DSP2XYRAMBASE_END 0x104EBC -#define DSP2XYRAMLENG_START 0x104EC0 -#define DSP2XYRAMLENG_END 0x104EDC -#define SEMAPHOREREGDSP2 0x104EE0 -#define DSP2INTCONTMASKREG 0x104EE4 -#define DSP2INTCONTPENDREG 0x104EE8 -#define DSP2INTCONTSERVINT 0x104EEC -#define GPIODSP2 0x104EFC -#define DMADSPBASEADDRREG_STARTDSP2 0x104F00 -#define DMADSPBASEADDRREG_ENDDSP2 0x104F1C -#define DMAHOSTBASEADDRREG_STARTDSP2 0x104F20 -#define DMAHOSTBASEADDRREG_ENDDSP2 0x104F3C -#define DMADSPCURADDRREG_STARTDSP2 0x104F40 -#define DMADSPCURADDRREG_ENDDSP2 0x104F5C -#define DMAHOSTCURADDRREG_STARTDSP2 0x104F60 -#define DMAHOSTCURADDRREG_ENDDSP2 0x104F7C -#define DMATANXCOUNTREG_STARTDSP2 0x104F80 -#define DMATANXCOUNTREG_ENDDSP2 0x104F9C -#define DMATIMEBUGREG_STARTDSP2 0x104FA0 -#define DMATIMEBUGREG_ENDDSP2 0x104FAC -#define DMACNTLMODFREG_STARTDSP2 0x104FA0 -#define DMACNTLMODFREG_ENDDSP2 0x104FAC - -#define DMAGLOBSTATSREGDSP2 0x104FEC -#define DSP2XGPRAM_START 0x105000 -#define DSP2XGPRAM_END 0x1051FC -#define DSP2YGPRAM_START 0x105800 -#define DSP2YGPRAM_END 0x1059FC - - - -#define AUDIORINGIPDSP3_START 0x106000 -#define AUDIORINGIPDSP3_END 0x1063FC -#define AUDIORINGOPDSP3_START 0x106400 -#define AUDIORINGOPDSP3_END 0x1067FC -#define AUDPARARINGIODSP3_START 0x106800 -#define AUDPARARINGIODSP3_END 0x106BFC -#define DSP3LOCALHWREG_START 0x106C00 -#define DSP3LOCALHWREG_END 0x106C3C -#define DSP3XYRAMAGINDEX_START 0x106C40 -#define DSP3XYRAMAGINDEX_END 0x106C5C -#define DSP3XYRAMAGMDFR_START 0x106C60 -#define DSP3XYRAMAGMDFR_END 0x106C7C -#define DSP3INTCONTLVEC_START 0x106C80 -#define DSP3INTCONTLVEC_END 0x106CD8 -#define HOSTINTFPORTADDRCONTDSP3 0x106D40 -#define HOSTINTFPORTDATADSP3 0x106D44 -#define TIME0PERENBDSP3 0x106D60 -#define TIME0COUNTERDSP3 0x106D64 -#define TIME1PERENBDSP3 0x106D68 -#define TIME1COUNTERDSP3 0x106D6C -#define TIME2PERENBDSP3 0x106D70 -#define TIME2COUNTERDSP3 0x106D74 -#define TIME3PERENBDSP3 0x106D78 -#define TIME3COUNTERDSP3 0x106D7C -#define XRAMINDOPERREFNOUP_STARTDSP3 0x106D80 -#define XRAMINDOPERREFNOUP_ENDDSP3 0x106D9C -#define XRAMINDOPERREFUP_STARTDSP3 0x106DA0 -#define XRAMINDOPERREFUP_ENDDSP3 0x106DBC -#define YRAMINDOPERREFNOUP_STARTDSP3 0x106DC0 -#define YRAMINDOPERREFNOUP_ENDDSP3 0x106DDC -#define YRAMINDOPERREFUP_STARTDSP3 0x106DE0 -#define YRAMINDOPERREFUP_ENDDSP3 0x100DFC - -#define DSP3CONDCODE 0x106E00 -#define DSP3STACKFLAG 0x106E04 -#define DSP3PROGCOUNTSTACKPTREG 0x106E08 -#define DSP3PROGCOUNTSTACKDATAREG 0x106E0C -#define DSP3CURLOOPADDRREG 0x106E10 -#define DSP3CURLOOPCOUNT 0x106E14 -#define DSP3TOPLOOPCOUNTSTACK 0x106E18 -#define DSP3TOPLOOPADDRSTACK 0x106E1C -#define DSP3LOOPSTACKPTR 0x106E20 -#define DSP3STASSTACKDATAREG 0x106E24 -#define DSP3STASSTACKPTR 0x106E28 -#define DSP3PROGCOUNT 0x106E2C -#define DSP3XYRAMBASE_START 0x106EA0 -#define DSP3XYRAMBASE_END 0x106EBC -#define DSP3XYRAMLENG_START 0x106EC0 -#define DSP3XYRAMLENG_END 0x106EDC -#define SEMAPHOREREGDSP3 0x106EE0 -#define DSP3INTCONTMASKREG 0x106EE4 -#define DSP3INTCONTPENDREG 0x106EE8 -#define DSP3INTCONTSERVINT 0x106EEC -#define GPIODSP3 0x106EFC -#define DMADSPBASEADDRREG_STARTDSP3 0x106F00 -#define DMADSPBASEADDRREG_ENDDSP3 0x106F1C -#define DMAHOSTBASEADDRREG_STARTDSP3 0x106F20 -#define DMAHOSTBASEADDRREG_ENDDSP3 0x106F3C -#define DMADSPCURADDRREG_STARTDSP3 0x106F40 -#define DMADSPCURADDRREG_ENDDSP3 0x106F5C -#define DMAHOSTCURADDRREG_STARTDSP3 0x106F60 -#define DMAHOSTCURADDRREG_ENDDSP3 0x106F7C -#define DMATANXCOUNTREG_STARTDSP3 0x106F80 -#define DMATANXCOUNTREG_ENDDSP3 0x106F9C -#define DMATIMEBUGREG_STARTDSP3 0x106FA0 -#define DMATIMEBUGREG_ENDDSP3 0x106FAC -#define DMACNTLMODFREG_STARTDSP3 0x106FA0 -#define DMACNTLMODFREG_ENDDSP3 0x106FAC - -#define DMAGLOBSTATSREGDSP3 0x106FEC -#define DSP3XGPRAM_START 0x107000 -#define DSP3XGPRAM_END 0x1071FC -#define DSP3YGPRAM_START 0x107800 -#define DSP3YGPRAM_END 0x1079FC - -/* end of DSP reg definitions */ - -#define DSPAIMAP_START 0x108000 -#define DSPAIMAP_END 0x1083FC -#define DSPPIMAP_START 0x108400 -#define DSPPIMAP_END 0x1087FC -#define DSPPOMAP_START 0x108800 -#define DSPPOMAP_END 0x108BFC -#define DSPPOCTL 0x108C00 -#define TKCTL_START 0x110000 -#define TKCTL_END 0x110FFC -#define TKCC_START 0x111000 -#define TKCC_END 0x111FFC -#define TKIMAP_START 0x112000 -#define TKIMAP_END 0x112FFC -#define TKDCTR16 0x113000 -#define TKPB16 0x113004 -#define TKBS16 0x113008 -#define TKDCTR32 0x11300C -#define TKPB32 0x113010 -#define TKBS32 0x113014 -#define ICDCTR16 0x113018 -#define ITBS16 0x11301C -#define ICDCTR32 0x113020 -#define ITBS32 0x113024 -#define ITSTART 0x113028 -#define TKSQ 0x11302C - -#define TKSCCTL_START 0x114000 -#define TKSCCTL_END 0x11403C -#define TKSCADR_START 0x114100 -#define TKSCADR_END 0x11413C -#define TKSCDATAX_START 0x114800 -#define TKSCDATAX_END 0x1149FC -#define TKPCDATAX_START 0x120000 -#define TKPCDATAX_END 0x12FFFC - -#define MALSA 0x130000 -#define MAPPHA 0x130004 -#define MAPPLA 0x130008 -#define MALSB 0x130010 -#define MAPPHB 0x130014 -#define MAPPLB 0x130018 - -#define TANSPORTMAPABREGS_START 0x130020 -#define TANSPORTMAPABREGS_END 0x13A2FC - -#define PTPAHX 0x13B000 -#define PTPALX 0x13B004 - -#define TANSPPAGETABLEPHYADDR015_START 0x13B008 -#define TANSPPAGETABLEPHYADDR015_END 0x13B07C -#define TRNQADRX_START 0x13B100 -#define TRNQADRX_END 0x13B13C -#define TRNQTIMX_START 0x13B200 -#define TRNQTIMX_END 0x13B23C -#define TRNQAPARMX_START 0x13B300 -#define TRNQAPARMX_END 0x13B33C - -#define TRNQCNT 0x13B400 -#define TRNCTL 0x13B404 -#define TRNIS 0x13B408 -#define TRNCURTS 0x13B40C - -#define AMOP_START 0x140000 -#define AMOPLO 0x140000 -#define AMOPHI 0x140004 -#define AMOP_END 0x147FFC -#define PMOP_START 0x148000 -#define PMOPLO 0x148000 -#define PMOPHI 0x148004 -#define PMOP_END 0x14FFFC -#define PCURR_START 0x150000 -#define PCURR_END 0x153FFC -#define PTRAG_START 0x154000 -#define PTRAG_END 0x157FFC -#define PSR_START 0x158000 -#define PSR_END 0x15BFFC - -#define PFSTAT4SEG_START 0x160000 -#define PFSTAT4SEG_END 0x160BFC -#define PFSTAT2SEG_START 0x160C00 -#define PFSTAT2SEG_END 0x1617FC -#define PFTARG4SEG_START 0x164000 -#define PFTARG4SEG_END 0x164BFC -#define PFTARG2SEG_START 0x164C00 -#define PFTARG2SEG_END 0x1657FC -#define PFSR4SEG_START 0x168000 -#define PFSR4SEG_END 0x168BFC -#define PFSR2SEG_START 0x168C00 -#define PFSR2SEG_END 0x1697FC -#define PCURRMS4SEG_START 0x16C000 -#define PCURRMS4SEG_END 0x16CCFC -#define PCURRMS2SEG_START 0x16CC00 -#define PCURRMS2SEG_END 0x16D7FC -#define PTARGMS4SEG_START 0x170000 -#define PTARGMS4SEG_END 0x172FFC -#define PTARGMS2SEG_START 0x173000 -#define PTARGMS2SEG_END 0x1747FC -#define PSRMS4SEG_START 0x170000 -#define PSRMS4SEG_END 0x172FFC -#define PSRMS2SEG_START 0x173000 -#define PSRMS2SEG_END 0x1747FC - -#define PRING_LO_START 0x190000 -#define PRING_LO_END 0x193FFC -#define PRING_HI_START 0x194000 -#define PRING_HI_END 0x197FFC -#define PRING_LO_HI_START 0x198000 -#define PRING_LO_HI 0x198000 -#define PRING_LO_HI_END 0x19BFFC - -#define PINTFIFO 0x1A0000 -#define SRCCTL 0x1B0000 -#define SRCCCR 0x1B0004 -#define SRCIMAP 0x1B0008 -#define SRCODDC 0x1B000C -#define SRCCA 0x1B0010 -#define SRCCF 0x1B0014 -#define SRCSA 0x1B0018 -#define SRCLA 0x1B001C -#define SRCCTLSWR 0x1B0020 - -/* SRC HERE */ -#define SRCALBA 0x1B002C -#define SRCMCTL 0x1B012C -#define SRCCERR 0x1B022C -#define SRCITB 0x1B032C -#define SRCIPM 0x1B082C -#define SRCIP 0x1B102C -#define SRCENBSTAT 0x1B202C -#define SRCENBLO 0x1B212C -#define SRCENBHI 0x1B222C -#define SRCENBS 0x1B232C -#define SRCENB 0x1B282C -#define SRCENB07 0x1B282C -#define SRCENBS07 0x1B302C - -#define SRCDN0Z 0x1B0030 -#define SRCDN0Z0 0x1B0030 -#define SRCDN0Z1 0x1B0034 -#define SRCDN0Z2 0x1B0038 -#define SRCDN0Z3 0x1B003C -#define SRCDN1Z 0x1B0040 -#define SRCDN1Z0 0x1B0040 -#define SRCDN1Z1 0x1B0044 -#define SRCDN1Z2 0x1B0048 -#define SRCDN1Z3 0x1B004C -#define SRCDN1Z4 0x1B0050 -#define SRCDN1Z5 0x1B0054 -#define SRCDN1Z6 0x1B0058 -#define SRCDN1Z7 0x1B005C -#define SRCUPZ 0x1B0060 -#define SRCUPZ0 0x1B0060 -#define SRCUPZ1 0x1B0064 -#define SRCUPZ2 0x1B0068 -#define SRCUPZ3 0x1B006C -#define SRCUPZ4 0x1B0070 -#define SRCUPZ5 0x1B0074 -#define SRCUPZ6 0x1B0078 -#define SRCUPZ7 0x1B007C -#define SRCCD0 0x1B0080 -#define SRCCD1 0x1B0084 -#define SRCCD2 0x1B0088 -#define SRCCD3 0x1B008C -#define SRCCD4 0x1B0090 -#define SRCCD5 0x1B0094 -#define SRCCD6 0x1B0098 -#define SRCCD7 0x1B009C -#define SRCCD8 0x1B00A0 -#define SRCCD9 0x1B00A4 -#define SRCCDA 0x1B00A8 -#define SRCCDB 0x1B00AC -#define SRCCDC 0x1B00B0 -#define SRCCDD 0x1B00B4 -#define SRCCDE 0x1B00B8 -#define SRCCDF 0x1B00BC -#define SRCCD10 0x1B00C0 -#define SRCCD11 0x1B00C4 -#define SRCCD12 0x1B00C8 -#define SRCCD13 0x1B00CC -#define SRCCD14 0x1B00D0 -#define SRCCD15 0x1B00D4 -#define SRCCD16 0x1B00D8 -#define SRCCD17 0x1B00DC -#define SRCCD18 0x1B00E0 -#define SRCCD19 0x1B00E4 -#define SRCCD1A 0x1B00E8 -#define SRCCD1B 0x1B00EC -#define SRCCD1C 0x1B00F0 -#define SRCCD1D 0x1B00F4 -#define SRCCD1E 0x1B00F8 -#define SRCCD1F 0x1B00FC - -#define SRCCONTRBLOCK_START 0x1B0100 -#define SRCCONTRBLOCK_END 0x1BFFFC -#define FILTOP_START 0x1C0000 -#define FILTOP_END 0x1C05FC -#define FILTIMAP_START 0x1C0800 -#define FILTIMAP_END 0x1C0DFC -#define FILTZ1_START 0x1C1000 -#define FILTZ1_END 0x1C15FC -#define FILTZ2_START 0x1C1800 -#define FILTZ2_END 0x1C1DFC -#define DAOIMAP_START 0x1C5000 -#define DAOIMAP 0x1C5000 -#define DAOIMAP_END 0x1C5124 - -#define AC97D 0x1C5400 -#define AC97A 0x1C5404 -#define AC97CTL 0x1C5408 -#define I2SCTL 0x1C5420 - -#define SPOS 0x1C5440 -#define SPOSA 0x1C5440 -#define SPOSB 0x1C5444 -#define SPOSC 0x1C5448 -#define SPOSD 0x1C544C - -#define SPISA 0x1C5450 -#define SPISB 0x1C5454 -#define SPISC 0x1C5458 -#define SPISD 0x1C545C - -#define SPFSCTL 0x1C5460 - -#define SPFS0 0x1C5468 -#define SPFS1 0x1C546C -#define SPFS2 0x1C5470 -#define SPFS3 0x1C5474 -#define SPFS4 0x1C5478 -#define SPFS5 0x1C547C - -#define SPOCTL 0x1C5480 -#define SPICTL 0x1C5484 -#define SPISTS 0x1C5488 -#define SPINTP 0x1C548C -#define SPINTE 0x1C5490 -#define SPUTCTLAB 0x1C5494 -#define SPUTCTLCD 0x1C5498 - -#define SRTSPA 0x1C54C0 -#define SRTSPB 0x1C54C4 -#define SRTSPC 0x1C54C8 -#define SRTSPD 0x1C54CC - -#define SRTSCTL 0x1C54D0 -#define SRTSCTLA 0x1C54D0 -#define SRTSCTLB 0x1C54D4 -#define SRTSCTLC 0x1C54D8 -#define SRTSCTLD 0x1C54DC - -#define SRTI2S 0x1C54E0 -#define SRTICTL 0x1C54F0 - -#define WC 0x1C6000 -#define TIMR 0x1C6004 -# define TIMR_IE (1<<15) -# define TIMR_IP (1<<14) - -#define GIP 0x1C6010 -#define GIE 0x1C6014 -#define DIE 0x1C6018 -#define DIC 0x1C601C -#define GPIO 0x1C6020 -#define GPIOCTL 0x1C6024 -#define GPIP 0x1C6028 -#define GPIE 0x1C602C -#define DSPINT0 0x1C6030 -#define DSPEIOC 0x1C6034 -#define MUADAT 0x1C6040 -#define MUACMD 0x1C6044 -#define MUASTAT 0x1C6044 -#define MUBDAT 0x1C6048 -#define MUBCMD 0x1C604C -#define MUBSTAT 0x1C604C -#define UARTCMA 0x1C6050 -#define UARTCMB 0x1C6054 -#define UARTIP 0x1C6058 -#define UARTIE 0x1C605C -#define PLLCTL 0x1C6060 -#define PLLDCD 0x1C6064 -#define GCTL 0x1C6070 -#define ID0 0x1C6080 -#define ID1 0x1C6084 -#define ID2 0x1C6088 -#define ID3 0x1C608C -#define SDRCTL 0x1C7000 - - -#define I2SA_L 0x0L -#define I2SA_R 0x1L -#define I2SB_L 0x8L -#define I2SB_R 0x9L -#define I2SC_L 0x10L -#define I2SC_R 0x11L -#define I2SD_L 0x18L -#define I2SD_R 0x19L - -#endif /* CT20K1REG_H */ - - diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ct20k2reg.h b/ANDROID_3.4.5/sound/pci/ctxfi/ct20k2reg.h deleted file mode 100644 index ca501ba0..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ct20k2reg.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - */ - -#ifndef _20K2REGISTERS_H_ -#define _20K2REGISTERS_H_ - - -/* Timer Registers */ -#define WC 0x1b7000 -#define TIMR 0x1b7004 -# define TIMR_IE (1<<15) -# define TIMR_IP (1<<14) -#define GIP 0x1b7010 -#define GIE 0x1b7014 - -/* I2C Registers */ -#define I2C_IF_ADDRESS 0x1B9000 -#define I2C_IF_WDATA 0x1B9004 -#define I2C_IF_RDATA 0x1B9008 -#define I2C_IF_STATUS 0x1B900C -#define I2C_IF_WLOCK 0x1B9010 - -/* Global Control Registers */ -#define GLOBAL_CNTL_GCTL 0x1B7090 - -/* PLL Registers */ -#define PLL_CTL 0x1B7080 -#define PLL_STAT 0x1B7084 -#define PLL_ENB 0x1B7088 - -/* SRC Registers */ -#define SRC_CTL 0x1A0000 /* 0x1A0000 + (256 * Chn) */ -#define SRC_CCR 0x1A0004 /* 0x1A0004 + (256 * Chn) */ -#define SRC_IMAP 0x1A0008 /* 0x1A0008 + (256 * Chn) */ -#define SRC_CA 0x1A0010 /* 0x1A0010 + (256 * Chn) */ -#define SRC_CF 0x1A0014 /* 0x1A0014 + (256 * Chn) */ -#define SRC_SA 0x1A0018 /* 0x1A0018 + (256 * Chn) */ -#define SRC_LA 0x1A001C /* 0x1A001C + (256 * Chn) */ -#define SRC_CTLSWR 0x1A0020 /* 0x1A0020 + (256 * Chn) */ -#define SRC_CD 0x1A0080 /* 0x1A0080 + (256 * Chn) + (4 * Regn) */ -#define SRC_MCTL 0x1A012C -#define SRC_IP 0x1A102C /* 0x1A102C + (256 * Regn) */ -#define SRC_ENB 0x1A282C /* 0x1A282C + (256 * Regn) */ -#define SRC_ENBSTAT 0x1A202C -#define SRC_ENBSA 0x1A232C -#define SRC_DN0Z 0x1A0030 -#define SRC_DN1Z 0x1A0040 -#define SRC_UPZ 0x1A0060 - -/* GPIO Registers */ -#define GPIO_DATA 0x1B7020 -#define GPIO_CTRL 0x1B7024 -#define GPIO_EXT_DATA 0x1B70A0 - -/* Virtual memory registers */ -#define VMEM_PTPAL 0x1C6300 /* 0x1C6300 + (16 * Chn) */ -#define VMEM_PTPAH 0x1C6304 /* 0x1C6304 + (16 * Chn) */ -#define VMEM_CTL 0x1C7000 - -/* Transport Registers */ -#define TRANSPORT_ENB 0x1B6000 -#define TRANSPORT_CTL 0x1B6004 -#define TRANSPORT_INT 0x1B6008 - -/* Audio IO */ -#define AUDIO_IO_AIM 0x1B5000 /* 0x1B5000 + (0x04 * Chn) */ -#define AUDIO_IO_TX_CTL 0x1B5400 /* 0x1B5400 + (0x40 * Chn) */ -#define AUDIO_IO_TX_CSTAT_L 0x1B5408 /* 0x1B5408 + (0x40 * Chn) */ -#define AUDIO_IO_TX_CSTAT_H 0x1B540C /* 0x1B540C + (0x40 * Chn) */ -#define AUDIO_IO_RX_CTL 0x1B5410 /* 0x1B5410 + (0x40 * Chn) */ -#define AUDIO_IO_RX_SRT_CTL 0x1B5420 /* 0x1B5420 + (0x40 * Chn) */ -#define AUDIO_IO_MCLK 0x1B5600 -#define AUDIO_IO_TX_BLRCLK 0x1B5604 -#define AUDIO_IO_RX_BLRCLK 0x1B5608 - -/* Mixer */ -#define MIXER_AMOPLO 0x130000 /* 0x130000 + (8 * Chn) [4095 : 0] */ -#define MIXER_AMOPHI 0x130004 /* 0x130004 + (8 * Chn) [4095 : 0] */ -#define MIXER_PRING_LO_HI 0x188000 /* 0x188000 + (4 * Chn) [4095 : 0] */ -#define MIXER_PMOPLO 0x138000 /* 0x138000 + (8 * Chn) [4095 : 0] */ -#define MIXER_PMOPHI 0x138004 /* 0x138004 + (8 * Chn) [4095 : 0] */ -#define MIXER_AR_ENABLE 0x19000C - -#endif diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.c deleted file mode 100644 index fee35cfc..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.c +++ /dev/null @@ -1,486 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctamixer.c - * - * @Brief - * This file contains the implementation of the Audio Mixer - * resource management object. - * - * @Author Liu Chun - * @Date May 21 2008 - * - */ - -#include "ctamixer.h" -#include "cthardware.h" -#include - -#define AMIXER_RESOURCE_NUM 256 -#define SUM_RESOURCE_NUM 256 - -#define AMIXER_Y_IMMEDIATE 1 - -#define BLANK_SLOT 4094 - -static int amixer_master(struct rsc *rsc) -{ - rsc->conj = 0; - return rsc->idx = container_of(rsc, struct amixer, rsc)->idx[0]; -} - -static int amixer_next_conj(struct rsc *rsc) -{ - rsc->conj++; - return container_of(rsc, struct amixer, rsc)->idx[rsc->conj]; -} - -static int amixer_index(const struct rsc *rsc) -{ - return container_of(rsc, struct amixer, rsc)->idx[rsc->conj]; -} - -static int amixer_output_slot(const struct rsc *rsc) -{ - return (amixer_index(rsc) << 4) + 0x4; -} - -static struct rsc_ops amixer_basic_rsc_ops = { - .master = amixer_master, - .next_conj = amixer_next_conj, - .index = amixer_index, - .output_slot = amixer_output_slot, -}; - -static int amixer_set_input(struct amixer *amixer, struct rsc *rsc) -{ - struct hw *hw; - - hw = amixer->rsc.hw; - hw->amixer_set_mode(amixer->rsc.ctrl_blk, AMIXER_Y_IMMEDIATE); - amixer->input = rsc; - if (!rsc) - hw->amixer_set_x(amixer->rsc.ctrl_blk, BLANK_SLOT); - else - hw->amixer_set_x(amixer->rsc.ctrl_blk, - rsc->ops->output_slot(rsc)); - - return 0; -} - -/* y is a 14-bit immediate constant */ -static int amixer_set_y(struct amixer *amixer, unsigned int y) -{ - struct hw *hw; - - hw = amixer->rsc.hw; - hw->amixer_set_y(amixer->rsc.ctrl_blk, y); - - return 0; -} - -static int amixer_set_invalid_squash(struct amixer *amixer, unsigned int iv) -{ - struct hw *hw; - - hw = amixer->rsc.hw; - hw->amixer_set_iv(amixer->rsc.ctrl_blk, iv); - - return 0; -} - -static int amixer_set_sum(struct amixer *amixer, struct sum *sum) -{ - struct hw *hw; - - hw = amixer->rsc.hw; - amixer->sum = sum; - if (!sum) { - hw->amixer_set_se(amixer->rsc.ctrl_blk, 0); - } else { - hw->amixer_set_se(amixer->rsc.ctrl_blk, 1); - hw->amixer_set_sadr(amixer->rsc.ctrl_blk, - sum->rsc.ops->index(&sum->rsc)); - } - - return 0; -} - -static int amixer_commit_write(struct amixer *amixer) -{ - struct hw *hw; - unsigned int index; - int i; - struct rsc *input; - struct sum *sum; - - hw = amixer->rsc.hw; - input = amixer->input; - sum = amixer->sum; - - /* Program master and conjugate resources */ - amixer->rsc.ops->master(&amixer->rsc); - if (input) - input->ops->master(input); - - if (sum) - sum->rsc.ops->master(&sum->rsc); - - for (i = 0; i < amixer->rsc.msr; i++) { - hw->amixer_set_dirty_all(amixer->rsc.ctrl_blk); - if (input) { - hw->amixer_set_x(amixer->rsc.ctrl_blk, - input->ops->output_slot(input)); - input->ops->next_conj(input); - } - if (sum) { - hw->amixer_set_sadr(amixer->rsc.ctrl_blk, - sum->rsc.ops->index(&sum->rsc)); - sum->rsc.ops->next_conj(&sum->rsc); - } - index = amixer->rsc.ops->output_slot(&amixer->rsc); - hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk); - amixer->rsc.ops->next_conj(&amixer->rsc); - } - amixer->rsc.ops->master(&amixer->rsc); - if (input) - input->ops->master(input); - - if (sum) - sum->rsc.ops->master(&sum->rsc); - - return 0; -} - -static int amixer_commit_raw_write(struct amixer *amixer) -{ - struct hw *hw; - unsigned int index; - - hw = amixer->rsc.hw; - index = amixer->rsc.ops->output_slot(&amixer->rsc); - hw->amixer_commit_write(hw, index, amixer->rsc.ctrl_blk); - - return 0; -} - -static int amixer_get_y(struct amixer *amixer) -{ - struct hw *hw; - - hw = amixer->rsc.hw; - return hw->amixer_get_y(amixer->rsc.ctrl_blk); -} - -static int amixer_setup(struct amixer *amixer, struct rsc *input, - unsigned int scale, struct sum *sum) -{ - amixer_set_input(amixer, input); - amixer_set_y(amixer, scale); - amixer_set_sum(amixer, sum); - amixer_commit_write(amixer); - return 0; -} - -static struct amixer_rsc_ops amixer_ops = { - .set_input = amixer_set_input, - .set_invalid_squash = amixer_set_invalid_squash, - .set_scale = amixer_set_y, - .set_sum = amixer_set_sum, - .commit_write = amixer_commit_write, - .commit_raw_write = amixer_commit_raw_write, - .setup = amixer_setup, - .get_scale = amixer_get_y, -}; - -static int amixer_rsc_init(struct amixer *amixer, - const struct amixer_desc *desc, - struct amixer_mgr *mgr) -{ - int err; - - err = rsc_init(&amixer->rsc, amixer->idx[0], - AMIXER, desc->msr, mgr->mgr.hw); - if (err) - return err; - - /* Set amixer specific operations */ - amixer->rsc.ops = &amixer_basic_rsc_ops; - amixer->ops = &amixer_ops; - amixer->input = NULL; - amixer->sum = NULL; - - amixer_setup(amixer, NULL, 0, NULL); - - return 0; -} - -static int amixer_rsc_uninit(struct amixer *amixer) -{ - amixer_setup(amixer, NULL, 0, NULL); - rsc_uninit(&amixer->rsc); - amixer->ops = NULL; - amixer->input = NULL; - amixer->sum = NULL; - return 0; -} - -static int get_amixer_rsc(struct amixer_mgr *mgr, - const struct amixer_desc *desc, - struct amixer **ramixer) -{ - int err, i; - unsigned int idx; - struct amixer *amixer; - unsigned long flags; - - *ramixer = NULL; - - /* Allocate mem for amixer resource */ - amixer = kzalloc(sizeof(*amixer), GFP_KERNEL); - if (!amixer) - return -ENOMEM; - - /* Check whether there are sufficient - * amixer resources to meet request. */ - err = 0; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < desc->msr; i++) { - err = mgr_get_resource(&mgr->mgr, 1, &idx); - if (err) - break; - - amixer->idx[i] = idx; - } - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - if (err) { - printk(KERN_ERR "ctxfi: Can't meet AMIXER resource request!\n"); - goto error; - } - - err = amixer_rsc_init(amixer, desc, mgr); - if (err) - goto error; - - *ramixer = amixer; - - return 0; - -error: - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i--; i >= 0; i--) - mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - kfree(amixer); - return err; -} - -static int put_amixer_rsc(struct amixer_mgr *mgr, struct amixer *amixer) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < amixer->rsc.msr; i++) - mgr_put_resource(&mgr->mgr, 1, amixer->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - amixer_rsc_uninit(amixer); - kfree(amixer); - - return 0; -} - -int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr) -{ - int err; - struct amixer_mgr *amixer_mgr; - - *ramixer_mgr = NULL; - amixer_mgr = kzalloc(sizeof(*amixer_mgr), GFP_KERNEL); - if (!amixer_mgr) - return -ENOMEM; - - err = rsc_mgr_init(&amixer_mgr->mgr, AMIXER, AMIXER_RESOURCE_NUM, hw); - if (err) - goto error; - - spin_lock_init(&amixer_mgr->mgr_lock); - - amixer_mgr->get_amixer = get_amixer_rsc; - amixer_mgr->put_amixer = put_amixer_rsc; - - *ramixer_mgr = amixer_mgr; - - return 0; - -error: - kfree(amixer_mgr); - return err; -} - -int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr) -{ - rsc_mgr_uninit(&amixer_mgr->mgr); - kfree(amixer_mgr); - return 0; -} - -/* SUM resource management */ - -static int sum_master(struct rsc *rsc) -{ - rsc->conj = 0; - return rsc->idx = container_of(rsc, struct sum, rsc)->idx[0]; -} - -static int sum_next_conj(struct rsc *rsc) -{ - rsc->conj++; - return container_of(rsc, struct sum, rsc)->idx[rsc->conj]; -} - -static int sum_index(const struct rsc *rsc) -{ - return container_of(rsc, struct sum, rsc)->idx[rsc->conj]; -} - -static int sum_output_slot(const struct rsc *rsc) -{ - return (sum_index(rsc) << 4) + 0xc; -} - -static struct rsc_ops sum_basic_rsc_ops = { - .master = sum_master, - .next_conj = sum_next_conj, - .index = sum_index, - .output_slot = sum_output_slot, -}; - -static int sum_rsc_init(struct sum *sum, - const struct sum_desc *desc, - struct sum_mgr *mgr) -{ - int err; - - err = rsc_init(&sum->rsc, sum->idx[0], SUM, desc->msr, mgr->mgr.hw); - if (err) - return err; - - sum->rsc.ops = &sum_basic_rsc_ops; - - return 0; -} - -static int sum_rsc_uninit(struct sum *sum) -{ - rsc_uninit(&sum->rsc); - return 0; -} - -static int get_sum_rsc(struct sum_mgr *mgr, - const struct sum_desc *desc, - struct sum **rsum) -{ - int err, i; - unsigned int idx; - struct sum *sum; - unsigned long flags; - - *rsum = NULL; - - /* Allocate mem for sum resource */ - sum = kzalloc(sizeof(*sum), GFP_KERNEL); - if (!sum) - return -ENOMEM; - - /* Check whether there are sufficient sum resources to meet request. */ - err = 0; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < desc->msr; i++) { - err = mgr_get_resource(&mgr->mgr, 1, &idx); - if (err) - break; - - sum->idx[i] = idx; - } - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - if (err) { - printk(KERN_ERR "ctxfi: Can't meet SUM resource request!\n"); - goto error; - } - - err = sum_rsc_init(sum, desc, mgr); - if (err) - goto error; - - *rsum = sum; - - return 0; - -error: - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i--; i >= 0; i--) - mgr_put_resource(&mgr->mgr, 1, sum->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - kfree(sum); - return err; -} - -static int put_sum_rsc(struct sum_mgr *mgr, struct sum *sum) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < sum->rsc.msr; i++) - mgr_put_resource(&mgr->mgr, 1, sum->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - sum_rsc_uninit(sum); - kfree(sum); - - return 0; -} - -int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr) -{ - int err; - struct sum_mgr *sum_mgr; - - *rsum_mgr = NULL; - sum_mgr = kzalloc(sizeof(*sum_mgr), GFP_KERNEL); - if (!sum_mgr) - return -ENOMEM; - - err = rsc_mgr_init(&sum_mgr->mgr, SUM, SUM_RESOURCE_NUM, hw); - if (err) - goto error; - - spin_lock_init(&sum_mgr->mgr_lock); - - sum_mgr->get_sum = get_sum_rsc; - sum_mgr->put_sum = put_sum_rsc; - - *rsum_mgr = sum_mgr; - - return 0; - -error: - kfree(sum_mgr); - return err; -} - -int sum_mgr_destroy(struct sum_mgr *sum_mgr) -{ - rsc_mgr_uninit(&sum_mgr->mgr); - kfree(sum_mgr); - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.h deleted file mode 100644 index cc49e5ab..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctamixer.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctamixer.h - * - * @Brief - * This file contains the definition of the Audio Mixer - * resource management object. - * - * @Author Liu Chun - * @Date May 21 2008 - * - */ - -#ifndef CTAMIXER_H -#define CTAMIXER_H - -#include "ctresource.h" -#include - -/* Define the descriptor of a summation node resource */ -struct sum { - struct rsc rsc; /* Basic resource info */ - unsigned char idx[8]; -}; - -/* Define sum resource request description info */ -struct sum_desc { - unsigned int msr; -}; - -struct sum_mgr { - struct rsc_mgr mgr; /* Basic resource manager info */ - spinlock_t mgr_lock; - - /* request one sum resource */ - int (*get_sum)(struct sum_mgr *mgr, - const struct sum_desc *desc, struct sum **rsum); - /* return one sum resource */ - int (*put_sum)(struct sum_mgr *mgr, struct sum *sum); -}; - -/* Constructor and destructor of daio resource manager */ -int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr); -int sum_mgr_destroy(struct sum_mgr *sum_mgr); - -/* Define the descriptor of a amixer resource */ -struct amixer_rsc_ops; - -struct amixer { - struct rsc rsc; /* Basic resource info */ - unsigned char idx[8]; - struct rsc *input; /* pointer to a resource acting as source */ - struct sum *sum; /* Put amixer output to this summation node */ - struct amixer_rsc_ops *ops; /* AMixer specific operations */ -}; - -struct amixer_rsc_ops { - int (*set_input)(struct amixer *amixer, struct rsc *rsc); - int (*set_scale)(struct amixer *amixer, unsigned int scale); - int (*set_invalid_squash)(struct amixer *amixer, unsigned int iv); - int (*set_sum)(struct amixer *amixer, struct sum *sum); - int (*commit_write)(struct amixer *amixer); - /* Only for interleaved recording */ - int (*commit_raw_write)(struct amixer *amixer); - int (*setup)(struct amixer *amixer, struct rsc *input, - unsigned int scale, struct sum *sum); - int (*get_scale)(struct amixer *amixer); -}; - -/* Define amixer resource request description info */ -struct amixer_desc { - unsigned int msr; -}; - -struct amixer_mgr { - struct rsc_mgr mgr; /* Basic resource manager info */ - spinlock_t mgr_lock; - - /* request one amixer resource */ - int (*get_amixer)(struct amixer_mgr *mgr, - const struct amixer_desc *desc, - struct amixer **ramixer); - /* return one amixer resource */ - int (*put_amixer)(struct amixer_mgr *mgr, struct amixer *amixer); -}; - -/* Constructor and destructor of amixer resource manager */ -int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr); -int amixer_mgr_destroy(struct amixer_mgr *amixer_mgr); - -#endif /* CTAMIXER_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctatc.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctatc.c deleted file mode 100644 index d8a44235..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctatc.c +++ /dev/null @@ -1,1744 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctatc.c - * - * @Brief - * This file contains the implementation of the device resource management - * object. - * - * @Author Liu Chun - * @Date Mar 28 2008 - */ - -#include "ctatc.h" -#include "ctpcm.h" -#include "ctmixer.h" -#include "ctsrc.h" -#include "ctamixer.h" -#include "ctdaio.h" -#include "cttimer.h" -#include -#include -#include -#include -#include - -#define MONO_SUM_SCALE 0x19a8 /* 2^(-0.5) in 14-bit floating format */ -#define MAX_MULTI_CHN 8 - -#define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \ - | IEC958_AES0_CON_NOT_COPYRIGHT) \ - | ((IEC958_AES1_CON_MIXER \ - | IEC958_AES1_CON_ORIGINAL) << 8) \ - | (0x10 << 16) \ - | ((IEC958_AES3_CON_FS_48000) << 24)) - -static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = { - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X), - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X), - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X), - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0031, "SB073x", CTSB073X), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000, 0x6000, - "UAA", CTUAA), - { } /* terminator */ -}; - -static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = { - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760, - "SB0760", CTSB0760), - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270, - "SB1270", CTSB1270), - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801, - "SB0880", CTSB0880), - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802, - "SB0880", CTSB0880), - SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08803, - "SB0880", CTSB0880), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000, - PCI_SUBDEVICE_ID_CREATIVE_HENDRIX, "HENDRIX", - CTHENDRIX), - { } /* terminator */ -}; - -static const char *ct_subsys_name[NUM_CTCARDS] = { - /* 20k1 models */ - [CTSB055X] = "SB055x", - [CTSB073X] = "SB073x", - [CTUAA] = "UAA", - [CT20K1_UNKNOWN] = "Unknown", - /* 20k2 models */ - [CTSB0760] = "SB076x", - [CTHENDRIX] = "Hendrix", - [CTSB0880] = "SB0880", - [CTSB1270] = "SB1270", - [CT20K2_UNKNOWN] = "Unknown", -}; - -static struct { - int (*create)(struct ct_atc *atc, - enum CTALSADEVS device, const char *device_name); - int (*destroy)(void *alsa_dev); - const char *public_name; -} alsa_dev_funcs[NUM_CTALSADEVS] = { - [FRONT] = { .create = ct_alsa_pcm_create, - .destroy = NULL, - .public_name = "Front/WaveIn"}, - [SURROUND] = { .create = ct_alsa_pcm_create, - .destroy = NULL, - .public_name = "Surround"}, - [CLFE] = { .create = ct_alsa_pcm_create, - .destroy = NULL, - .public_name = "Center/LFE"}, - [SIDE] = { .create = ct_alsa_pcm_create, - .destroy = NULL, - .public_name = "Side"}, - [IEC958] = { .create = ct_alsa_pcm_create, - .destroy = NULL, - .public_name = "IEC958 Non-audio"}, - - [MIXER] = { .create = ct_alsa_mix_create, - .destroy = NULL, - .public_name = "Mixer"} -}; - -typedef int (*create_t)(void *, void **); -typedef int (*destroy_t)(void *); - -static struct { - int (*create)(void *hw, void **rmgr); - int (*destroy)(void *mgr); -} rsc_mgr_funcs[NUM_RSCTYP] = { - [SRC] = { .create = (create_t)src_mgr_create, - .destroy = (destroy_t)src_mgr_destroy }, - [SRCIMP] = { .create = (create_t)srcimp_mgr_create, - .destroy = (destroy_t)srcimp_mgr_destroy }, - [AMIXER] = { .create = (create_t)amixer_mgr_create, - .destroy = (destroy_t)amixer_mgr_destroy }, - [SUM] = { .create = (create_t)sum_mgr_create, - .destroy = (destroy_t)sum_mgr_destroy }, - [DAIO] = { .create = (create_t)daio_mgr_create, - .destroy = (destroy_t)daio_mgr_destroy } -}; - -static int -atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm); - -/* * - * Only mono and interleaved modes are supported now. - * Always allocates a contiguous channel block. - * */ - -static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct snd_pcm_runtime *runtime; - struct ct_vm *vm; - - if (!apcm->substream) - return 0; - - runtime = apcm->substream->runtime; - vm = atc->vm; - - apcm->vm_block = vm->map(vm, apcm->substream, runtime->dma_bytes); - - if (!apcm->vm_block) - return -ENOENT; - - return 0; -} - -static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct ct_vm *vm; - - if (!apcm->vm_block) - return; - - vm = atc->vm; - - vm->unmap(vm, apcm->vm_block); - - apcm->vm_block = NULL; -} - -static unsigned long atc_get_ptp_phys(struct ct_atc *atc, int index) -{ - return atc->vm->get_ptp_phys(atc->vm, index); -} - -static unsigned int convert_format(snd_pcm_format_t snd_format) -{ - switch (snd_format) { - case SNDRV_PCM_FORMAT_U8: - return SRC_SF_U8; - case SNDRV_PCM_FORMAT_S16_LE: - return SRC_SF_S16; - case SNDRV_PCM_FORMAT_S24_3LE: - return SRC_SF_S24; - case SNDRV_PCM_FORMAT_S32_LE: - return SRC_SF_S32; - case SNDRV_PCM_FORMAT_FLOAT_LE: - return SRC_SF_F32; - default: - printk(KERN_ERR "ctxfi: not recognized snd format is %d \n", - snd_format); - return SRC_SF_S16; - } -} - -static unsigned int -atc_get_pitch(unsigned int input_rate, unsigned int output_rate) -{ - unsigned int pitch; - int b; - - /* get pitch and convert to fixed-point 8.24 format. */ - pitch = (input_rate / output_rate) << 24; - input_rate %= output_rate; - input_rate /= 100; - output_rate /= 100; - for (b = 31; ((b >= 0) && !(input_rate >> b)); ) - b--; - - if (b >= 0) { - input_rate <<= (31 - b); - input_rate /= output_rate; - b = 24 - (31 - b); - if (b >= 0) - input_rate <<= b; - else - input_rate >>= -b; - - pitch |= input_rate; - } - - return pitch; -} - -static int select_rom(unsigned int pitch) -{ - if (pitch > 0x00428f5c && pitch < 0x01b851ec) { - /* 0.26 <= pitch <= 1.72 */ - return 1; - } else if (pitch == 0x01d66666 || pitch == 0x01d66667) { - /* pitch == 1.8375 */ - return 2; - } else if (pitch == 0x02000000) { - /* pitch == 2 */ - return 3; - } else if (pitch <= 0x08000000) { - /* 0 <= pitch <= 8 */ - return 0; - } else { - return -ENOENT; - } -} - -static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src_mgr *src_mgr = atc->rsc_mgrs[SRC]; - struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER]; - struct src_desc desc = {0}; - struct amixer_desc mix_dsc = {0}; - struct src *src; - struct amixer *amixer; - int err; - int n_amixer = apcm->substream->runtime->channels, i = 0; - int device = apcm->substream->pcm->device; - unsigned int pitch; - - /* first release old resources */ - atc_pcm_release_resources(atc, apcm); - - /* Get SRC resource */ - desc.multi = apcm->substream->runtime->channels; - desc.msr = atc->msr; - desc.mode = MEMRD; - err = src_mgr->get_src(src_mgr, &desc, (struct src **)&apcm->src); - if (err) - goto error1; - - pitch = atc_get_pitch(apcm->substream->runtime->rate, - (atc->rsr * atc->msr)); - src = apcm->src; - src->ops->set_pitch(src, pitch); - src->ops->set_rom(src, select_rom(pitch)); - src->ops->set_sf(src, convert_format(apcm->substream->runtime->format)); - src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL)); - - /* Get AMIXER resource */ - n_amixer = (n_amixer < 2) ? 2 : n_amixer; - apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); - if (!apcm->amixers) { - err = -ENOMEM; - goto error1; - } - mix_dsc.msr = atc->msr; - for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) { - err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc, - (struct amixer **)&apcm->amixers[i]); - if (err) - goto error1; - - apcm->n_amixer++; - } - - /* Set up device virtual mem map */ - err = ct_map_audio_buffer(atc, apcm); - if (err < 0) - goto error1; - - /* Connect resources */ - src = apcm->src; - for (i = 0; i < n_amixer; i++) { - amixer = apcm->amixers[i]; - mutex_lock(&atc->atc_mutex); - amixer->ops->setup(amixer, &src->rsc, - INIT_VOL, atc->pcm[i+device*2]); - mutex_unlock(&atc->atc_mutex); - src = src->ops->next_interleave(src); - if (!src) - src = apcm->src; - } - - ct_timer_prepare(apcm->timer); - - return 0; - -error1: - atc_pcm_release_resources(atc, apcm); - return err; -} - -static int -atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src_mgr *src_mgr = atc->rsc_mgrs[SRC]; - struct srcimp_mgr *srcimp_mgr = atc->rsc_mgrs[SRCIMP]; - struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER]; - struct sum_mgr *sum_mgr = atc->rsc_mgrs[SUM]; - struct srcimp *srcimp; - int i; - - if (apcm->srcimps) { - for (i = 0; i < apcm->n_srcimp; i++) { - srcimp = apcm->srcimps[i]; - srcimp->ops->unmap(srcimp); - srcimp_mgr->put_srcimp(srcimp_mgr, srcimp); - apcm->srcimps[i] = NULL; - } - kfree(apcm->srcimps); - apcm->srcimps = NULL; - } - - if (apcm->srccs) { - for (i = 0; i < apcm->n_srcc; i++) { - src_mgr->put_src(src_mgr, apcm->srccs[i]); - apcm->srccs[i] = NULL; - } - kfree(apcm->srccs); - apcm->srccs = NULL; - } - - if (apcm->amixers) { - for (i = 0; i < apcm->n_amixer; i++) { - amixer_mgr->put_amixer(amixer_mgr, apcm->amixers[i]); - apcm->amixers[i] = NULL; - } - kfree(apcm->amixers); - apcm->amixers = NULL; - } - - if (apcm->mono) { - sum_mgr->put_sum(sum_mgr, apcm->mono); - apcm->mono = NULL; - } - - if (apcm->src) { - src_mgr->put_src(src_mgr, apcm->src); - apcm->src = NULL; - } - - if (apcm->vm_block) { - /* Undo device virtual mem map */ - ct_unmap_audio_buffer(atc, apcm); - apcm->vm_block = NULL; - } - - return 0; -} - -static int atc_pcm_playback_start(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - unsigned int max_cisz; - struct src *src = apcm->src; - - if (apcm->started) - return 0; - apcm->started = 1; - - max_cisz = src->multi * src->rsc.msr; - max_cisz = 0x80 * (max_cisz < 8 ? max_cisz : 8); - - src->ops->set_sa(src, apcm->vm_block->addr); - src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size); - src->ops->set_ca(src, apcm->vm_block->addr + max_cisz); - src->ops->set_cisz(src, max_cisz); - - src->ops->set_bm(src, 1); - src->ops->set_state(src, SRC_STATE_INIT); - src->ops->commit_write(src); - - ct_timer_start(apcm->timer); - return 0; -} - -static int atc_pcm_stop(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src *src; - int i; - - ct_timer_stop(apcm->timer); - - src = apcm->src; - src->ops->set_bm(src, 0); - src->ops->set_state(src, SRC_STATE_OFF); - src->ops->commit_write(src); - - if (apcm->srccs) { - for (i = 0; i < apcm->n_srcc; i++) { - src = apcm->srccs[i]; - src->ops->set_bm(src, 0); - src->ops->set_state(src, SRC_STATE_OFF); - src->ops->commit_write(src); - } - } - - apcm->started = 0; - - return 0; -} - -static int -atc_pcm_playback_position(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src *src = apcm->src; - u32 size, max_cisz; - int position; - - if (!src) - return 0; - position = src->ops->get_ca(src); - - size = apcm->vm_block->size; - max_cisz = src->multi * src->rsc.msr; - max_cisz = 128 * (max_cisz < 8 ? max_cisz : 8); - - return (position + size - max_cisz - apcm->vm_block->addr) % size; -} - -struct src_node_conf_t { - unsigned int pitch; - unsigned int msr:8; - unsigned int mix_msr:8; - unsigned int imp_msr:8; - unsigned int vo:1; -}; - -static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm, - struct src_node_conf_t *conf, int *n_srcc) -{ - unsigned int pitch; - - /* get pitch and convert to fixed-point 8.24 format. */ - pitch = atc_get_pitch((atc->rsr * atc->msr), - apcm->substream->runtime->rate); - *n_srcc = 0; - - if (1 == atc->msr) { /* FIXME: do we really need SRC here if pitch==1 */ - *n_srcc = apcm->substream->runtime->channels; - conf[0].pitch = pitch; - conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1; - conf[0].vo = 1; - } else if (2 <= atc->msr) { - if (0x8000000 < pitch) { - /* Need two-stage SRCs, SRCIMPs and - * AMIXERs for converting format */ - conf[0].pitch = (atc->msr << 24); - conf[0].msr = conf[0].mix_msr = 1; - conf[0].imp_msr = atc->msr; - conf[0].vo = 0; - conf[1].pitch = atc_get_pitch(atc->rsr, - apcm->substream->runtime->rate); - conf[1].msr = conf[1].mix_msr = conf[1].imp_msr = 1; - conf[1].vo = 1; - *n_srcc = apcm->substream->runtime->channels * 2; - } else if (0x1000000 < pitch) { - /* Need one-stage SRCs, SRCIMPs and - * AMIXERs for converting format */ - conf[0].pitch = pitch; - conf[0].msr = conf[0].mix_msr - = conf[0].imp_msr = atc->msr; - conf[0].vo = 1; - *n_srcc = apcm->substream->runtime->channels; - } - } -} - -static int -atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src_mgr *src_mgr = atc->rsc_mgrs[SRC]; - struct srcimp_mgr *srcimp_mgr = atc->rsc_mgrs[SRCIMP]; - struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER]; - struct sum_mgr *sum_mgr = atc->rsc_mgrs[SUM]; - struct src_desc src_dsc = {0}; - struct src *src; - struct srcimp_desc srcimp_dsc = {0}; - struct srcimp *srcimp; - struct amixer_desc mix_dsc = {0}; - struct sum_desc sum_dsc = {0}; - unsigned int pitch; - int multi, err, i; - int n_srcimp, n_amixer, n_srcc, n_sum; - struct src_node_conf_t src_node_conf[2] = {{0} }; - - /* first release old resources */ - atc_pcm_release_resources(atc, apcm); - - /* The numbers of converting SRCs and SRCIMPs should be determined - * by pitch value. */ - - multi = apcm->substream->runtime->channels; - - /* get pitch and convert to fixed-point 8.24 format. */ - pitch = atc_get_pitch((atc->rsr * atc->msr), - apcm->substream->runtime->rate); - - setup_src_node_conf(atc, apcm, src_node_conf, &n_srcc); - n_sum = (1 == multi) ? 1 : 0; - n_amixer = n_sum * 2 + n_srcc; - n_srcimp = n_srcc; - if ((multi > 1) && (0x8000000 >= pitch)) { - /* Need extra AMIXERs and SRCIMPs for special treatment - * of interleaved recording of conjugate channels */ - n_amixer += multi * atc->msr; - n_srcimp += multi * atc->msr; - } else { - n_srcimp += multi; - } - - if (n_srcc) { - apcm->srccs = kzalloc(sizeof(void *)*n_srcc, GFP_KERNEL); - if (!apcm->srccs) - return -ENOMEM; - } - if (n_amixer) { - apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); - if (!apcm->amixers) { - err = -ENOMEM; - goto error1; - } - } - apcm->srcimps = kzalloc(sizeof(void *)*n_srcimp, GFP_KERNEL); - if (!apcm->srcimps) { - err = -ENOMEM; - goto error1; - } - - /* Allocate SRCs for sample rate conversion if needed */ - src_dsc.multi = 1; - src_dsc.mode = ARCRW; - for (i = 0, apcm->n_srcc = 0; i < n_srcc; i++) { - src_dsc.msr = src_node_conf[i/multi].msr; - err = src_mgr->get_src(src_mgr, &src_dsc, - (struct src **)&apcm->srccs[i]); - if (err) - goto error1; - - src = apcm->srccs[i]; - pitch = src_node_conf[i/multi].pitch; - src->ops->set_pitch(src, pitch); - src->ops->set_rom(src, select_rom(pitch)); - src->ops->set_vo(src, src_node_conf[i/multi].vo); - - apcm->n_srcc++; - } - - /* Allocate AMIXERs for routing SRCs of conversion if needed */ - for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) { - if (i < (n_sum*2)) - mix_dsc.msr = atc->msr; - else if (i < (n_sum*2+n_srcc)) - mix_dsc.msr = src_node_conf[(i-n_sum*2)/multi].mix_msr; - else - mix_dsc.msr = 1; - - err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc, - (struct amixer **)&apcm->amixers[i]); - if (err) - goto error1; - - apcm->n_amixer++; - } - - /* Allocate a SUM resource to mix all input channels together */ - sum_dsc.msr = atc->msr; - err = sum_mgr->get_sum(sum_mgr, &sum_dsc, (struct sum **)&apcm->mono); - if (err) - goto error1; - - pitch = atc_get_pitch((atc->rsr * atc->msr), - apcm->substream->runtime->rate); - /* Allocate SRCIMP resources */ - for (i = 0, apcm->n_srcimp = 0; i < n_srcimp; i++) { - if (i < (n_srcc)) - srcimp_dsc.msr = src_node_conf[i/multi].imp_msr; - else if (1 == multi) - srcimp_dsc.msr = (pitch <= 0x8000000) ? atc->msr : 1; - else - srcimp_dsc.msr = 1; - - err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, &srcimp); - if (err) - goto error1; - - apcm->srcimps[i] = srcimp; - apcm->n_srcimp++; - } - - /* Allocate a SRC for writing data to host memory */ - src_dsc.multi = apcm->substream->runtime->channels; - src_dsc.msr = 1; - src_dsc.mode = MEMWR; - err = src_mgr->get_src(src_mgr, &src_dsc, (struct src **)&apcm->src); - if (err) - goto error1; - - src = apcm->src; - src->ops->set_pitch(src, pitch); - - /* Set up device virtual mem map */ - err = ct_map_audio_buffer(atc, apcm); - if (err < 0) - goto error1; - - return 0; - -error1: - atc_pcm_release_resources(atc, apcm); - return err; -} - -static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src *src; - struct amixer *amixer; - struct srcimp *srcimp; - struct ct_mixer *mixer = atc->mixer; - struct sum *mono; - struct rsc *out_ports[8] = {NULL}; - int err, i, j, n_sum, multi; - unsigned int pitch; - int mix_base = 0, imp_base = 0; - - atc_pcm_release_resources(atc, apcm); - - /* Get needed resources. */ - err = atc_pcm_capture_get_resources(atc, apcm); - if (err) - return err; - - /* Connect resources */ - mixer->get_output_ports(mixer, MIX_PCMO_FRONT, - &out_ports[0], &out_ports[1]); - - multi = apcm->substream->runtime->channels; - if (1 == multi) { - mono = apcm->mono; - for (i = 0; i < 2; i++) { - amixer = apcm->amixers[i]; - amixer->ops->setup(amixer, out_ports[i], - MONO_SUM_SCALE, mono); - } - out_ports[0] = &mono->rsc; - n_sum = 1; - mix_base = n_sum * 2; - } - - for (i = 0; i < apcm->n_srcc; i++) { - src = apcm->srccs[i]; - srcimp = apcm->srcimps[imp_base+i]; - amixer = apcm->amixers[mix_base+i]; - srcimp->ops->map(srcimp, src, out_ports[i%multi]); - amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL); - out_ports[i%multi] = &amixer->rsc; - } - - pitch = atc_get_pitch((atc->rsr * atc->msr), - apcm->substream->runtime->rate); - - if ((multi > 1) && (pitch <= 0x8000000)) { - /* Special connection for interleaved - * recording with conjugate channels */ - for (i = 0; i < multi; i++) { - out_ports[i]->ops->master(out_ports[i]); - for (j = 0; j < atc->msr; j++) { - amixer = apcm->amixers[apcm->n_srcc+j*multi+i]; - amixer->ops->set_input(amixer, out_ports[i]); - amixer->ops->set_scale(amixer, INIT_VOL); - amixer->ops->set_sum(amixer, NULL); - amixer->ops->commit_raw_write(amixer); - out_ports[i]->ops->next_conj(out_ports[i]); - - srcimp = apcm->srcimps[apcm->n_srcc+j*multi+i]; - srcimp->ops->map(srcimp, apcm->src, - &amixer->rsc); - } - } - } else { - for (i = 0; i < multi; i++) { - srcimp = apcm->srcimps[apcm->n_srcc+i]; - srcimp->ops->map(srcimp, apcm->src, out_ports[i]); - } - } - - ct_timer_prepare(apcm->timer); - - return 0; -} - -static int atc_pcm_capture_start(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src *src; - struct src_mgr *src_mgr = atc->rsc_mgrs[SRC]; - int i, multi; - - if (apcm->started) - return 0; - - apcm->started = 1; - multi = apcm->substream->runtime->channels; - /* Set up converting SRCs */ - for (i = 0; i < apcm->n_srcc; i++) { - src = apcm->srccs[i]; - src->ops->set_pm(src, ((i%multi) != (multi-1))); - src_mgr->src_disable(src_mgr, src); - } - - /* Set up recording SRC */ - src = apcm->src; - src->ops->set_sf(src, convert_format(apcm->substream->runtime->format)); - src->ops->set_sa(src, apcm->vm_block->addr); - src->ops->set_la(src, apcm->vm_block->addr + apcm->vm_block->size); - src->ops->set_ca(src, apcm->vm_block->addr); - src_mgr->src_disable(src_mgr, src); - - /* Disable relevant SRCs firstly */ - src_mgr->commit_write(src_mgr); - - /* Enable SRCs respectively */ - for (i = 0; i < apcm->n_srcc; i++) { - src = apcm->srccs[i]; - src->ops->set_state(src, SRC_STATE_RUN); - src->ops->commit_write(src); - src_mgr->src_enable_s(src_mgr, src); - } - src = apcm->src; - src->ops->set_bm(src, 1); - src->ops->set_state(src, SRC_STATE_RUN); - src->ops->commit_write(src); - src_mgr->src_enable_s(src_mgr, src); - - /* Enable relevant SRCs synchronously */ - src_mgr->commit_write(src_mgr); - - ct_timer_start(apcm->timer); - return 0; -} - -static int -atc_pcm_capture_position(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src *src = apcm->src; - - if (!src) - return 0; - return src->ops->get_ca(src) - apcm->vm_block->addr; -} - -static int spdif_passthru_playback_get_resources(struct ct_atc *atc, - struct ct_atc_pcm *apcm) -{ - struct src_mgr *src_mgr = atc->rsc_mgrs[SRC]; - struct amixer_mgr *amixer_mgr = atc->rsc_mgrs[AMIXER]; - struct src_desc desc = {0}; - struct amixer_desc mix_dsc = {0}; - struct src *src; - int err; - int n_amixer = apcm->substream->runtime->channels, i; - unsigned int pitch, rsr = atc->pll_rate; - - /* first release old resources */ - atc_pcm_release_resources(atc, apcm); - - /* Get SRC resource */ - desc.multi = apcm->substream->runtime->channels; - desc.msr = 1; - while (apcm->substream->runtime->rate > (rsr * desc.msr)) - desc.msr <<= 1; - - desc.mode = MEMRD; - err = src_mgr->get_src(src_mgr, &desc, (struct src **)&apcm->src); - if (err) - goto error1; - - pitch = atc_get_pitch(apcm->substream->runtime->rate, (rsr * desc.msr)); - src = apcm->src; - src->ops->set_pitch(src, pitch); - src->ops->set_rom(src, select_rom(pitch)); - src->ops->set_sf(src, convert_format(apcm->substream->runtime->format)); - src->ops->set_pm(src, (src->ops->next_interleave(src) != NULL)); - src->ops->set_bp(src, 1); - - /* Get AMIXER resource */ - n_amixer = (n_amixer < 2) ? 2 : n_amixer; - apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); - if (!apcm->amixers) { - err = -ENOMEM; - goto error1; - } - mix_dsc.msr = desc.msr; - for (i = 0, apcm->n_amixer = 0; i < n_amixer; i++) { - err = amixer_mgr->get_amixer(amixer_mgr, &mix_dsc, - (struct amixer **)&apcm->amixers[i]); - if (err) - goto error1; - - apcm->n_amixer++; - } - - /* Set up device virtual mem map */ - err = ct_map_audio_buffer(atc, apcm); - if (err < 0) - goto error1; - - return 0; - -error1: - atc_pcm_release_resources(atc, apcm); - return err; -} - -static int atc_pll_init(struct ct_atc *atc, int rate) -{ - struct hw *hw = atc->hw; - int err; - err = hw->pll_init(hw, rate); - atc->pll_rate = err ? 0 : rate; - return err; -} - -static int -spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio); - unsigned int rate = apcm->substream->runtime->rate; - unsigned int status; - int err = 0; - unsigned char iec958_con_fs; - - switch (rate) { - case 48000: - iec958_con_fs = IEC958_AES3_CON_FS_48000; - break; - case 44100: - iec958_con_fs = IEC958_AES3_CON_FS_44100; - break; - case 32000: - iec958_con_fs = IEC958_AES3_CON_FS_32000; - break; - default: - return -ENOENT; - } - - mutex_lock(&atc->atc_mutex); - dao->ops->get_spos(dao, &status); - if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { - status &= ~(IEC958_AES3_CON_FS << 24); - status |= (iec958_con_fs << 24); - dao->ops->set_spos(dao, status); - dao->ops->commit_write(dao); - } - if ((rate != atc->pll_rate) && (32000 != rate)) - err = atc_pll_init(atc, rate); - mutex_unlock(&atc->atc_mutex); - - return err; -} - -static int -spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) -{ - struct src *src; - struct amixer *amixer; - struct dao *dao; - int err; - int i; - - atc_pcm_release_resources(atc, apcm); - - /* Configure SPDIFOO and PLL to passthrough mode; - * determine pll_rate. */ - err = spdif_passthru_playback_setup(atc, apcm); - if (err) - return err; - - /* Get needed resources. */ - err = spdif_passthru_playback_get_resources(atc, apcm); - if (err) - return err; - - /* Connect resources */ - src = apcm->src; - for (i = 0; i < apcm->n_amixer; i++) { - amixer = apcm->amixers[i]; - amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL); - src = src->ops->next_interleave(src); - if (!src) - src = apcm->src; - } - /* Connect to SPDIFOO */ - mutex_lock(&atc->atc_mutex); - dao = container_of(atc->daios[SPDIFOO], struct dao, daio); - amixer = apcm->amixers[0]; - dao->ops->set_left_input(dao, &amixer->rsc); - amixer = apcm->amixers[1]; - dao->ops->set_right_input(dao, &amixer->rsc); - mutex_unlock(&atc->atc_mutex); - - ct_timer_prepare(apcm->timer); - - return 0; -} - -static int atc_select_line_in(struct ct_atc *atc) -{ - struct hw *hw = atc->hw; - struct ct_mixer *mixer = atc->mixer; - struct src *src; - - if (hw->is_adc_source_selected(hw, ADC_LINEIN)) - return 0; - - mixer->set_input_left(mixer, MIX_MIC_IN, NULL); - mixer->set_input_right(mixer, MIX_MIC_IN, NULL); - - hw->select_adc_source(hw, ADC_LINEIN); - - src = atc->srcs[2]; - mixer->set_input_left(mixer, MIX_LINE_IN, &src->rsc); - src = atc->srcs[3]; - mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc); - - return 0; -} - -static int atc_select_mic_in(struct ct_atc *atc) -{ - struct hw *hw = atc->hw; - struct ct_mixer *mixer = atc->mixer; - struct src *src; - - if (hw->is_adc_source_selected(hw, ADC_MICIN)) - return 0; - - mixer->set_input_left(mixer, MIX_LINE_IN, NULL); - mixer->set_input_right(mixer, MIX_LINE_IN, NULL); - - hw->select_adc_source(hw, ADC_MICIN); - - src = atc->srcs[2]; - mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc); - src = atc->srcs[3]; - mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc); - - return 0; -} - -static struct capabilities atc_capabilities(struct ct_atc *atc) -{ - struct hw *hw = atc->hw; - - return hw->capabilities(hw); -} - -static int atc_output_switch_get(struct ct_atc *atc) -{ - struct hw *hw = atc->hw; - - return hw->output_switch_get(hw); -} - -static int atc_output_switch_put(struct ct_atc *atc, int position) -{ - struct hw *hw = atc->hw; - - return hw->output_switch_put(hw, position); -} - -static int atc_mic_source_switch_get(struct ct_atc *atc) -{ - struct hw *hw = atc->hw; - - return hw->mic_source_switch_get(hw); -} - -static int atc_mic_source_switch_put(struct ct_atc *atc, int position) -{ - struct hw *hw = atc->hw; - - return hw->mic_source_switch_put(hw, position); -} - -static int atc_select_digit_io(struct ct_atc *atc) -{ - struct hw *hw = atc->hw; - - if (hw->is_adc_source_selected(hw, ADC_NONE)) - return 0; - - hw->select_adc_source(hw, ADC_NONE); - - return 0; -} - -static int atc_daio_unmute(struct ct_atc *atc, unsigned char state, int type) -{ - struct daio_mgr *daio_mgr = atc->rsc_mgrs[DAIO]; - - if (state) - daio_mgr->daio_enable(daio_mgr, atc->daios[type]); - else - daio_mgr->daio_disable(daio_mgr, atc->daios[type]); - - daio_mgr->commit_write(daio_mgr); - - return 0; -} - -static int -atc_dao_get_status(struct ct_atc *atc, unsigned int *status, int type) -{ - struct dao *dao = container_of(atc->daios[type], struct dao, daio); - return dao->ops->get_spos(dao, status); -} - -static int -atc_dao_set_status(struct ct_atc *atc, unsigned int status, int type) -{ - struct dao *dao = container_of(atc->daios[type], struct dao, daio); - - dao->ops->set_spos(dao, status); - dao->ops->commit_write(dao); - return 0; -} - -static int atc_line_front_unmute(struct ct_atc *atc, unsigned char state) -{ - return atc_daio_unmute(atc, state, LINEO1); -} - -static int atc_line_surround_unmute(struct ct_atc *atc, unsigned char state) -{ - return atc_daio_unmute(atc, state, LINEO2); -} - -static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state) -{ - return atc_daio_unmute(atc, state, LINEO3); -} - -static int atc_line_rear_unmute(struct ct_atc *atc, unsigned char state) -{ - return atc_daio_unmute(atc, state, LINEO4); -} - -static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state) -{ - return atc_daio_unmute(atc, state, LINEIM); -} - -static int atc_mic_unmute(struct ct_atc *atc, unsigned char state) -{ - return atc_daio_unmute(atc, state, MIC); -} - -static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state) -{ - return atc_daio_unmute(atc, state, SPDIFOO); -} - -static int atc_spdif_in_unmute(struct ct_atc *atc, unsigned char state) -{ - return atc_daio_unmute(atc, state, SPDIFIO); -} - -static int atc_spdif_out_get_status(struct ct_atc *atc, unsigned int *status) -{ - return atc_dao_get_status(atc, status, SPDIFOO); -} - -static int atc_spdif_out_set_status(struct ct_atc *atc, unsigned int status) -{ - return atc_dao_set_status(atc, status, SPDIFOO); -} - -static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) -{ - struct dao_desc da_dsc = {0}; - struct dao *dao; - int err; - struct ct_mixer *mixer = atc->mixer; - struct rsc *rscs[2] = {NULL}; - unsigned int spos = 0; - - mutex_lock(&atc->atc_mutex); - dao = container_of(atc->daios[SPDIFOO], struct dao, daio); - da_dsc.msr = state ? 1 : atc->msr; - da_dsc.passthru = state ? 1 : 0; - err = dao->ops->reinit(dao, &da_dsc); - if (state) { - spos = IEC958_DEFAULT_CON; - } else { - mixer->get_output_ports(mixer, MIX_SPDIF_OUT, - &rscs[0], &rscs[1]); - dao->ops->set_left_input(dao, rscs[0]); - dao->ops->set_right_input(dao, rscs[1]); - /* Restore PLL to atc->rsr if needed. */ - if (atc->pll_rate != atc->rsr) - err = atc_pll_init(atc, atc->rsr); - } - dao->ops->set_spos(dao, spos); - dao->ops->commit_write(dao); - mutex_unlock(&atc->atc_mutex); - - return err; -} - -static int atc_release_resources(struct ct_atc *atc) -{ - int i; - struct daio_mgr *daio_mgr = NULL; - struct dao *dao = NULL; - struct dai *dai = NULL; - struct daio *daio = NULL; - struct sum_mgr *sum_mgr = NULL; - struct src_mgr *src_mgr = NULL; - struct srcimp_mgr *srcimp_mgr = NULL; - struct srcimp *srcimp = NULL; - struct ct_mixer *mixer = NULL; - - /* disconnect internal mixer objects */ - if (atc->mixer) { - mixer = atc->mixer; - mixer->set_input_left(mixer, MIX_LINE_IN, NULL); - mixer->set_input_right(mixer, MIX_LINE_IN, NULL); - mixer->set_input_left(mixer, MIX_MIC_IN, NULL); - mixer->set_input_right(mixer, MIX_MIC_IN, NULL); - mixer->set_input_left(mixer, MIX_SPDIF_IN, NULL); - mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL); - } - - if (atc->daios) { - daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; - for (i = 0; i < atc->n_daio; i++) { - daio = atc->daios[i]; - if (daio->type < LINEIM) { - dao = container_of(daio, struct dao, daio); - dao->ops->clear_left_input(dao); - dao->ops->clear_right_input(dao); - } else { - dai = container_of(daio, struct dai, daio); - /* some thing to do for dai ... */ - } - daio_mgr->put_daio(daio_mgr, daio); - } - kfree(atc->daios); - atc->daios = NULL; - } - - if (atc->pcm) { - sum_mgr = atc->rsc_mgrs[SUM]; - for (i = 0; i < atc->n_pcm; i++) - sum_mgr->put_sum(sum_mgr, atc->pcm[i]); - - kfree(atc->pcm); - atc->pcm = NULL; - } - - if (atc->srcs) { - src_mgr = atc->rsc_mgrs[SRC]; - for (i = 0; i < atc->n_src; i++) - src_mgr->put_src(src_mgr, atc->srcs[i]); - - kfree(atc->srcs); - atc->srcs = NULL; - } - - if (atc->srcimps) { - srcimp_mgr = atc->rsc_mgrs[SRCIMP]; - for (i = 0; i < atc->n_srcimp; i++) { - srcimp = atc->srcimps[i]; - srcimp->ops->unmap(srcimp); - srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]); - } - kfree(atc->srcimps); - atc->srcimps = NULL; - } - - return 0; -} - -static int ct_atc_destroy(struct ct_atc *atc) -{ - int i = 0; - - if (!atc) - return 0; - - if (atc->timer) { - ct_timer_free(atc->timer); - atc->timer = NULL; - } - - atc_release_resources(atc); - - /* Destroy internal mixer objects */ - if (atc->mixer) - ct_mixer_destroy(atc->mixer); - - for (i = 0; i < NUM_RSCTYP; i++) { - if (rsc_mgr_funcs[i].destroy && atc->rsc_mgrs[i]) - rsc_mgr_funcs[i].destroy(atc->rsc_mgrs[i]); - - } - - if (atc->hw) - destroy_hw_obj((struct hw *)atc->hw); - - /* Destroy device virtual memory manager object */ - if (atc->vm) { - ct_vm_destroy(atc->vm); - atc->vm = NULL; - } - - kfree(atc); - - return 0; -} - -static int atc_dev_free(struct snd_device *dev) -{ - struct ct_atc *atc = dev->device_data; - return ct_atc_destroy(atc); -} - -static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid) -{ - const struct snd_pci_quirk *p; - const struct snd_pci_quirk *list; - u16 vendor_id, device_id; - - switch (atc->chip_type) { - case ATC20K1: - atc->chip_name = "20K1"; - list = subsys_20k1_list; - break; - case ATC20K2: - atc->chip_name = "20K2"; - list = subsys_20k2_list; - break; - default: - return -ENOENT; - } - if (ssid) { - vendor_id = ssid >> 16; - device_id = ssid & 0xffff; - } else { - vendor_id = atc->pci->subsystem_vendor; - device_id = atc->pci->subsystem_device; - } - p = snd_pci_quirk_lookup_id(vendor_id, device_id, list); - if (p) { - if (p->value < 0) { - printk(KERN_ERR "ctxfi: " - "Device %04x:%04x is black-listed\n", - vendor_id, device_id); - return -ENOENT; - } - atc->model = p->value; - } else { - if (atc->chip_type == ATC20K1) - atc->model = CT20K1_UNKNOWN; - else - atc->model = CT20K2_UNKNOWN; - } - atc->model_name = ct_subsys_name[atc->model]; - snd_printd("ctxfi: chip %s model %s (%04x:%04x) is found\n", - atc->chip_name, atc->model_name, - vendor_id, device_id); - return 0; -} - -int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc) -{ - enum CTALSADEVS i; - int err; - - alsa_dev_funcs[MIXER].public_name = atc->chip_name; - - for (i = 0; i < NUM_CTALSADEVS; i++) { - if (!alsa_dev_funcs[i].create) - continue; - - err = alsa_dev_funcs[i].create(atc, i, - alsa_dev_funcs[i].public_name); - if (err) { - printk(KERN_ERR "ctxfi: " - "Creating alsa device %d failed!\n", i); - return err; - } - } - - return 0; -} - -static int __devinit atc_create_hw_devs(struct ct_atc *atc) -{ - struct hw *hw; - struct card_conf info = {0}; - int i, err; - - err = create_hw_obj(atc->pci, atc->chip_type, atc->model, &hw); - if (err) { - printk(KERN_ERR "Failed to create hw obj!!!\n"); - return err; - } - atc->hw = hw; - - /* Initialize card hardware. */ - info.rsr = atc->rsr; - info.msr = atc->msr; - info.vm_pgt_phys = atc_get_ptp_phys(atc, 0); - err = hw->card_init(hw, &info); - if (err < 0) - return err; - - for (i = 0; i < NUM_RSCTYP; i++) { - if (!rsc_mgr_funcs[i].create) - continue; - - err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]); - if (err) { - printk(KERN_ERR "ctxfi: " - "Failed to create rsc_mgr %d!!!\n", i); - return err; - } - } - - return 0; -} - -static int atc_get_resources(struct ct_atc *atc) -{ - struct daio_desc da_desc = {0}; - struct daio_mgr *daio_mgr; - struct src_desc src_dsc = {0}; - struct src_mgr *src_mgr; - struct srcimp_desc srcimp_dsc = {0}; - struct srcimp_mgr *srcimp_mgr; - struct sum_desc sum_dsc = {0}; - struct sum_mgr *sum_mgr; - int err, i, num_srcs, num_daios; - - num_daios = ((atc->model == CTSB1270) ? 8 : 7); - num_srcs = ((atc->model == CTSB1270) ? 6 : 4); - - atc->daios = kzalloc(sizeof(void *)*num_daios, GFP_KERNEL); - if (!atc->daios) - return -ENOMEM; - - atc->srcs = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); - if (!atc->srcs) - return -ENOMEM; - - atc->srcimps = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); - if (!atc->srcimps) - return -ENOMEM; - - atc->pcm = kzalloc(sizeof(void *)*(2*4), GFP_KERNEL); - if (!atc->pcm) - return -ENOMEM; - - daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; - da_desc.msr = atc->msr; - for (i = 0, atc->n_daio = 0; i < num_daios; i++) { - da_desc.type = (atc->model != CTSB073X) ? i : - ((i == SPDIFIO) ? SPDIFI1 : i); - err = daio_mgr->get_daio(daio_mgr, &da_desc, - (struct daio **)&atc->daios[i]); - if (err) { - printk(KERN_ERR "ctxfi: Failed to get DAIO " - "resource %d!!!\n", i); - return err; - } - atc->n_daio++; - } - - src_mgr = atc->rsc_mgrs[SRC]; - src_dsc.multi = 1; - src_dsc.msr = atc->msr; - src_dsc.mode = ARCRW; - for (i = 0, atc->n_src = 0; i < num_srcs; i++) { - err = src_mgr->get_src(src_mgr, &src_dsc, - (struct src **)&atc->srcs[i]); - if (err) - return err; - - atc->n_src++; - } - - srcimp_mgr = atc->rsc_mgrs[SRCIMP]; - srcimp_dsc.msr = 8; - for (i = 0, atc->n_srcimp = 0; i < num_srcs; i++) { - err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, - (struct srcimp **)&atc->srcimps[i]); - if (err) - return err; - - atc->n_srcimp++; - } - - sum_mgr = atc->rsc_mgrs[SUM]; - sum_dsc.msr = atc->msr; - for (i = 0, atc->n_pcm = 0; i < (2*4); i++) { - err = sum_mgr->get_sum(sum_mgr, &sum_dsc, - (struct sum **)&atc->pcm[i]); - if (err) - return err; - - atc->n_pcm++; - } - - return 0; -} - -static void -atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai, - struct src **srcs, struct srcimp **srcimps) -{ - struct rsc *rscs[2] = {NULL}; - struct src *src; - struct srcimp *srcimp; - int i = 0; - - rscs[0] = &dai->daio.rscl; - rscs[1] = &dai->daio.rscr; - for (i = 0; i < 2; i++) { - src = srcs[i]; - srcimp = srcimps[i]; - srcimp->ops->map(srcimp, src, rscs[i]); - src_mgr->src_disable(src_mgr, src); - } - - src_mgr->commit_write(src_mgr); /* Actually disable SRCs */ - - src = srcs[0]; - src->ops->set_pm(src, 1); - for (i = 0; i < 2; i++) { - src = srcs[i]; - src->ops->set_state(src, SRC_STATE_RUN); - src->ops->commit_write(src); - src_mgr->src_enable_s(src_mgr, src); - } - - dai->ops->set_srt_srcl(dai, &(srcs[0]->rsc)); - dai->ops->set_srt_srcr(dai, &(srcs[1]->rsc)); - - dai->ops->set_enb_src(dai, 1); - dai->ops->set_enb_srt(dai, 1); - dai->ops->commit_write(dai); - - src_mgr->commit_write(src_mgr); /* Synchronously enable SRCs */ -} - -static void atc_connect_resources(struct ct_atc *atc) -{ - struct dai *dai; - struct dao *dao; - struct src *src; - struct sum *sum; - struct ct_mixer *mixer; - struct rsc *rscs[2] = {NULL}; - int i, j; - - mixer = atc->mixer; - - for (i = MIX_WAVE_FRONT, j = LINEO1; i <= MIX_SPDIF_OUT; i++, j++) { - mixer->get_output_ports(mixer, i, &rscs[0], &rscs[1]); - dao = container_of(atc->daios[j], struct dao, daio); - dao->ops->set_left_input(dao, rscs[0]); - dao->ops->set_right_input(dao, rscs[1]); - } - - dai = container_of(atc->daios[LINEIM], struct dai, daio); - atc_connect_dai(atc->rsc_mgrs[SRC], dai, - (struct src **)&atc->srcs[2], - (struct srcimp **)&atc->srcimps[2]); - src = atc->srcs[2]; - mixer->set_input_left(mixer, MIX_LINE_IN, &src->rsc); - src = atc->srcs[3]; - mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc); - - if (atc->model == CTSB1270) { - /* Titanium HD has a dedicated ADC for the Mic. */ - dai = container_of(atc->daios[MIC], struct dai, daio); - atc_connect_dai(atc->rsc_mgrs[SRC], dai, - (struct src **)&atc->srcs[4], - (struct srcimp **)&atc->srcimps[4]); - src = atc->srcs[4]; - mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc); - src = atc->srcs[5]; - mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc); - } - - dai = container_of(atc->daios[SPDIFIO], struct dai, daio); - atc_connect_dai(atc->rsc_mgrs[SRC], dai, - (struct src **)&atc->srcs[0], - (struct srcimp **)&atc->srcimps[0]); - - src = atc->srcs[0]; - mixer->set_input_left(mixer, MIX_SPDIF_IN, &src->rsc); - src = atc->srcs[1]; - mixer->set_input_right(mixer, MIX_SPDIF_IN, &src->rsc); - - for (i = MIX_PCMI_FRONT, j = 0; i <= MIX_PCMI_SURROUND; i++, j += 2) { - sum = atc->pcm[j]; - mixer->set_input_left(mixer, i, &sum->rsc); - sum = atc->pcm[j+1]; - mixer->set_input_right(mixer, i, &sum->rsc); - } -} - -#ifdef CONFIG_PM -static int atc_suspend(struct ct_atc *atc, pm_message_t state) -{ - int i; - struct hw *hw = atc->hw; - - snd_power_change_state(atc->card, SNDRV_CTL_POWER_D3hot); - - for (i = FRONT; i < NUM_PCMS; i++) { - if (!atc->pcms[i]) - continue; - - snd_pcm_suspend_all(atc->pcms[i]); - } - - atc_release_resources(atc); - - hw->suspend(hw, state); - - return 0; -} - -static int atc_hw_resume(struct ct_atc *atc) -{ - struct hw *hw = atc->hw; - struct card_conf info = {0}; - - /* Re-initialize card hardware. */ - info.rsr = atc->rsr; - info.msr = atc->msr; - info.vm_pgt_phys = atc_get_ptp_phys(atc, 0); - return hw->resume(hw, &info); -} - -static int atc_resources_resume(struct ct_atc *atc) -{ - struct ct_mixer *mixer; - int err = 0; - - /* Get resources */ - err = atc_get_resources(atc); - if (err < 0) { - atc_release_resources(atc); - return err; - } - - /* Build topology */ - atc_connect_resources(atc); - - mixer = atc->mixer; - mixer->resume(mixer); - - return 0; -} - -static int atc_resume(struct ct_atc *atc) -{ - int err = 0; - - /* Do hardware resume. */ - err = atc_hw_resume(atc); - if (err < 0) { - printk(KERN_ERR "ctxfi: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(atc->card); - return err; - } - - err = atc_resources_resume(atc); - if (err < 0) - return err; - - snd_power_change_state(atc->card, SNDRV_CTL_POWER_D0); - - return 0; -} -#endif - -static struct ct_atc atc_preset __devinitdata = { - .map_audio_buffer = ct_map_audio_buffer, - .unmap_audio_buffer = ct_unmap_audio_buffer, - .pcm_playback_prepare = atc_pcm_playback_prepare, - .pcm_release_resources = atc_pcm_release_resources, - .pcm_playback_start = atc_pcm_playback_start, - .pcm_playback_stop = atc_pcm_stop, - .pcm_playback_position = atc_pcm_playback_position, - .pcm_capture_prepare = atc_pcm_capture_prepare, - .pcm_capture_start = atc_pcm_capture_start, - .pcm_capture_stop = atc_pcm_stop, - .pcm_capture_position = atc_pcm_capture_position, - .spdif_passthru_playback_prepare = spdif_passthru_playback_prepare, - .get_ptp_phys = atc_get_ptp_phys, - .select_line_in = atc_select_line_in, - .select_mic_in = atc_select_mic_in, - .select_digit_io = atc_select_digit_io, - .line_front_unmute = atc_line_front_unmute, - .line_surround_unmute = atc_line_surround_unmute, - .line_clfe_unmute = atc_line_clfe_unmute, - .line_rear_unmute = atc_line_rear_unmute, - .line_in_unmute = atc_line_in_unmute, - .mic_unmute = atc_mic_unmute, - .spdif_out_unmute = atc_spdif_out_unmute, - .spdif_in_unmute = atc_spdif_in_unmute, - .spdif_out_get_status = atc_spdif_out_get_status, - .spdif_out_set_status = atc_spdif_out_set_status, - .spdif_out_passthru = atc_spdif_out_passthru, - .capabilities = atc_capabilities, - .output_switch_get = atc_output_switch_get, - .output_switch_put = atc_output_switch_put, - .mic_source_switch_get = atc_mic_source_switch_get, - .mic_source_switch_put = atc_mic_source_switch_put, -#ifdef CONFIG_PM - .suspend = atc_suspend, - .resume = atc_resume, -#endif -}; - -/** - * ct_atc_create - create and initialize a hardware manager - * @card: corresponding alsa card object - * @pci: corresponding kernel pci device object - * @ratc: return created object address in it - * - * Creates and initializes a hardware manager. - * - * Creates kmallocated ct_atc structure. Initializes hardware. - * Returns 0 if succeeds, or negative error code if fails. - */ - -int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, - unsigned int rsr, unsigned int msr, - int chip_type, unsigned int ssid, - struct ct_atc **ratc) -{ - struct ct_atc *atc; - static struct snd_device_ops ops = { - .dev_free = atc_dev_free, - }; - int err; - - *ratc = NULL; - - atc = kzalloc(sizeof(*atc), GFP_KERNEL); - if (!atc) - return -ENOMEM; - - /* Set operations */ - *atc = atc_preset; - - atc->card = card; - atc->pci = pci; - atc->rsr = rsr; - atc->msr = msr; - atc->chip_type = chip_type; - - mutex_init(&atc->atc_mutex); - - /* Find card model */ - err = atc_identify_card(atc, ssid); - if (err < 0) { - printk(KERN_ERR "ctatc: Card not recognised\n"); - goto error1; - } - - /* Set up device virtual memory management object */ - err = ct_vm_create(&atc->vm, pci); - if (err < 0) - goto error1; - - /* Create all atc hw devices */ - err = atc_create_hw_devs(atc); - if (err < 0) - goto error1; - - err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer); - if (err) { - printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n"); - goto error1; - } - - /* Get resources */ - err = atc_get_resources(atc); - if (err < 0) - goto error1; - - /* Build topology */ - atc_connect_resources(atc); - - atc->timer = ct_timer_new(atc); - if (!atc->timer) - goto error1; - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops); - if (err < 0) - goto error1; - - snd_card_set_dev(card, &pci->dev); - - *ratc = atc; - return 0; - -error1: - ct_atc_destroy(atc); - printk(KERN_ERR "ctxfi: Something wrong!!!\n"); - return err; -} diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctatc.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctatc.h deleted file mode 100644 index 3a0def65..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctatc.h +++ /dev/null @@ -1,160 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctatc.h - * - * @Brief - * This file contains the definition of the device resource management object. - * - * @Author Liu Chun - * @Date Mar 28 2008 - * - */ - -#ifndef CTATC_H -#define CTATC_H - -#include -#include -#include -#include -#include - -#include "ctvmem.h" -#include "cthardware.h" -#include "ctresource.h" - -enum CTALSADEVS { /* Types of alsa devices */ - FRONT, - SURROUND, - CLFE, - SIDE, - IEC958, - MIXER, - NUM_CTALSADEVS /* This should always be the last */ -}; - -struct ct_atc_chip_sub_details { - u16 subsys; - const char *nm_model; -}; - -struct ct_atc_chip_details { - u16 vendor; - u16 device; - const struct ct_atc_chip_sub_details *sub_details; - const char *nm_card; -}; - -struct ct_atc; -struct ct_timer; -struct ct_timer_instance; - -/* alsa pcm stream descriptor */ -struct ct_atc_pcm { - struct snd_pcm_substream *substream; - void (*interrupt)(struct ct_atc_pcm *apcm); - struct ct_timer_instance *timer; - unsigned int started:1; - - /* Only mono and interleaved modes are supported now. */ - struct ct_vm_block *vm_block; - void *src; /* SRC for interacting with host memory */ - void **srccs; /* SRCs for sample rate conversion */ - void **srcimps; /* SRC Input Mappers */ - void **amixers; /* AMIXERs for routing converted data */ - void *mono; /* A SUM resource for mixing chs to one */ - unsigned char n_srcc; /* Number of converting SRCs */ - unsigned char n_srcimp; /* Number of SRC Input Mappers */ - unsigned char n_amixer; /* Number of AMIXERs */ -}; - -/* Chip resource management object */ -struct ct_atc { - struct pci_dev *pci; - struct snd_card *card; - unsigned int rsr; /* reference sample rate in Hz */ - unsigned int msr; /* master sample rate in rsr */ - unsigned int pll_rate; /* current rate of Phase Lock Loop */ - - int chip_type; - int model; - const char *chip_name; - const char *model_name; - - struct ct_vm *vm; /* device virtual memory manager for this card */ - int (*map_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm); - void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm); - unsigned long (*get_ptp_phys)(struct ct_atc *atc, int index); - - struct mutex atc_mutex; - - int (*pcm_playback_prepare)(struct ct_atc *atc, - struct ct_atc_pcm *apcm); - int (*pcm_playback_start)(struct ct_atc *atc, struct ct_atc_pcm *apcm); - int (*pcm_playback_stop)(struct ct_atc *atc, struct ct_atc_pcm *apcm); - int (*pcm_playback_position)(struct ct_atc *atc, - struct ct_atc_pcm *apcm); - int (*spdif_passthru_playback_prepare)(struct ct_atc *atc, - struct ct_atc_pcm *apcm); - int (*pcm_capture_prepare)(struct ct_atc *atc, struct ct_atc_pcm *apcm); - int (*pcm_capture_start)(struct ct_atc *atc, struct ct_atc_pcm *apcm); - int (*pcm_capture_stop)(struct ct_atc *atc, struct ct_atc_pcm *apcm); - int (*pcm_capture_position)(struct ct_atc *atc, - struct ct_atc_pcm *apcm); - int (*pcm_release_resources)(struct ct_atc *atc, - struct ct_atc_pcm *apcm); - int (*select_line_in)(struct ct_atc *atc); - int (*select_mic_in)(struct ct_atc *atc); - int (*select_digit_io)(struct ct_atc *atc); - int (*line_front_unmute)(struct ct_atc *atc, unsigned char state); - int (*line_surround_unmute)(struct ct_atc *atc, unsigned char state); - int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state); - int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state); - int (*line_in_unmute)(struct ct_atc *atc, unsigned char state); - int (*mic_unmute)(struct ct_atc *atc, unsigned char state); - int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state); - int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state); - int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status); - int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status); - int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state); - struct capabilities (*capabilities)(struct ct_atc *atc); - int (*output_switch_get)(struct ct_atc *atc); - int (*output_switch_put)(struct ct_atc *atc, int position); - int (*mic_source_switch_get)(struct ct_atc *atc); - int (*mic_source_switch_put)(struct ct_atc *atc, int position); - - /* Don't touch! Used for internal object. */ - void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */ - void *mixer; /* internal mixer object */ - void *hw; /* chip specific hardware access object */ - void **daios; /* digital audio io resources */ - void **pcm; /* SUMs for collecting all pcm stream */ - void **srcs; /* Sample Rate Converters for input signal */ - void **srcimps; /* input mappers for SRCs */ - unsigned char n_daio; - unsigned char n_src; - unsigned char n_srcimp; - unsigned char n_pcm; - - struct ct_timer *timer; - -#ifdef CONFIG_PM - int (*suspend)(struct ct_atc *atc, pm_message_t state); - int (*resume)(struct ct_atc *atc); -#define NUM_PCMS (NUM_CTALSADEVS - 1) - struct snd_pcm *pcms[NUM_PCMS]; -#endif -}; - - -int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, - unsigned int rsr, unsigned int msr, int chip_type, - unsigned int subsysid, struct ct_atc **ratc); -int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc); - -#endif /* CTATC_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.c deleted file mode 100644 index 0c00eb40..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.c +++ /dev/null @@ -1,762 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctdaio.c - * - * @Brief - * This file contains the implementation of Digital Audio Input Output - * resource management object. - * - * @Author Liu Chun - * @Date May 23 2008 - * - */ - -#include "ctdaio.h" -#include "cthardware.h" -#include "ctimap.h" -#include -#include - -#define DAIO_OUT_MAX SPDIFOO - -struct daio_usage { - unsigned short data; -}; - -struct daio_rsc_idx { - unsigned short left; - unsigned short right; -}; - -struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = { - [LINEO1] = {.left = 0x00, .right = 0x01}, - [LINEO2] = {.left = 0x18, .right = 0x19}, - [LINEO3] = {.left = 0x08, .right = 0x09}, - [LINEO4] = {.left = 0x10, .right = 0x11}, - [LINEIM] = {.left = 0x1b5, .right = 0x1bd}, - [SPDIFOO] = {.left = 0x20, .right = 0x21}, - [SPDIFIO] = {.left = 0x15, .right = 0x1d}, - [SPDIFI1] = {.left = 0x95, .right = 0x9d}, -}; - -struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { - [LINEO1] = {.left = 0x40, .right = 0x41}, - [LINEO2] = {.left = 0x60, .right = 0x61}, - [LINEO3] = {.left = 0x50, .right = 0x51}, - [LINEO4] = {.left = 0x70, .right = 0x71}, - [LINEIM] = {.left = 0x45, .right = 0xc5}, - [MIC] = {.left = 0x55, .right = 0xd5}, - [SPDIFOO] = {.left = 0x00, .right = 0x01}, - [SPDIFIO] = {.left = 0x05, .right = 0x85}, -}; - -static int daio_master(struct rsc *rsc) -{ - /* Actually, this is not the resource index of DAIO. - * For DAO, it is the input mapper index. And, for DAI, - * it is the output time-slot index. */ - return rsc->conj = rsc->idx; -} - -static int daio_index(const struct rsc *rsc) -{ - return rsc->conj; -} - -static int daio_out_next_conj(struct rsc *rsc) -{ - return rsc->conj += 2; -} - -static int daio_in_next_conj_20k1(struct rsc *rsc) -{ - return rsc->conj += 0x200; -} - -static int daio_in_next_conj_20k2(struct rsc *rsc) -{ - return rsc->conj += 0x100; -} - -static struct rsc_ops daio_out_rsc_ops = { - .master = daio_master, - .next_conj = daio_out_next_conj, - .index = daio_index, - .output_slot = NULL, -}; - -static struct rsc_ops daio_in_rsc_ops_20k1 = { - .master = daio_master, - .next_conj = daio_in_next_conj_20k1, - .index = NULL, - .output_slot = daio_index, -}; - -static struct rsc_ops daio_in_rsc_ops_20k2 = { - .master = daio_master, - .next_conj = daio_in_next_conj_20k2, - .index = NULL, - .output_slot = daio_index, -}; - -static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw) -{ - switch (hw->chip_type) { - case ATC20K1: - switch (type) { - case SPDIFOO: return 0; - case SPDIFIO: return 0; - case SPDIFI1: return 1; - case LINEO1: return 4; - case LINEO2: return 7; - case LINEO3: return 5; - case LINEO4: return 6; - case LINEIM: return 7; - default: return -EINVAL; - } - case ATC20K2: - switch (type) { - case SPDIFOO: return 0; - case SPDIFIO: return 0; - case LINEO1: return 4; - case LINEO2: return 7; - case LINEO3: return 5; - case LINEO4: return 6; - case LINEIM: return 4; - case MIC: return 5; - default: return -EINVAL; - } - default: - return -EINVAL; - } -} - -static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc); - -static int dao_spdif_get_spos(struct dao *dao, unsigned int *spos) -{ - ((struct hw *)dao->hw)->dao_get_spos(dao->ctrl_blk, spos); - return 0; -} - -static int dao_spdif_set_spos(struct dao *dao, unsigned int spos) -{ - ((struct hw *)dao->hw)->dao_set_spos(dao->ctrl_blk, spos); - return 0; -} - -static int dao_commit_write(struct dao *dao) -{ - ((struct hw *)dao->hw)->dao_commit_write(dao->hw, - daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk); - return 0; -} - -static int dao_set_left_input(struct dao *dao, struct rsc *input) -{ - struct imapper *entry; - struct daio *daio = &dao->daio; - int i; - - entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - dao->ops->clear_left_input(dao); - /* Program master and conjugate resources */ - input->ops->master(input); - daio->rscl.ops->master(&daio->rscl); - for (i = 0; i < daio->rscl.msr; i++, entry++) { - entry->slot = input->ops->output_slot(input); - entry->user = entry->addr = daio->rscl.ops->index(&daio->rscl); - dao->mgr->imap_add(dao->mgr, entry); - dao->imappers[i] = entry; - - input->ops->next_conj(input); - daio->rscl.ops->next_conj(&daio->rscl); - } - input->ops->master(input); - daio->rscl.ops->master(&daio->rscl); - - return 0; -} - -static int dao_set_right_input(struct dao *dao, struct rsc *input) -{ - struct imapper *entry; - struct daio *daio = &dao->daio; - int i; - - entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - dao->ops->clear_right_input(dao); - /* Program master and conjugate resources */ - input->ops->master(input); - daio->rscr.ops->master(&daio->rscr); - for (i = 0; i < daio->rscr.msr; i++, entry++) { - entry->slot = input->ops->output_slot(input); - entry->user = entry->addr = daio->rscr.ops->index(&daio->rscr); - dao->mgr->imap_add(dao->mgr, entry); - dao->imappers[daio->rscl.msr + i] = entry; - - input->ops->next_conj(input); - daio->rscr.ops->next_conj(&daio->rscr); - } - input->ops->master(input); - daio->rscr.ops->master(&daio->rscr); - - return 0; -} - -static int dao_clear_left_input(struct dao *dao) -{ - struct imapper *entry; - struct daio *daio = &dao->daio; - int i; - - if (!dao->imappers[0]) - return 0; - - entry = dao->imappers[0]; - dao->mgr->imap_delete(dao->mgr, entry); - /* Program conjugate resources */ - for (i = 1; i < daio->rscl.msr; i++) { - entry = dao->imappers[i]; - dao->mgr->imap_delete(dao->mgr, entry); - dao->imappers[i] = NULL; - } - - kfree(dao->imappers[0]); - dao->imappers[0] = NULL; - - return 0; -} - -static int dao_clear_right_input(struct dao *dao) -{ - struct imapper *entry; - struct daio *daio = &dao->daio; - int i; - - if (!dao->imappers[daio->rscl.msr]) - return 0; - - entry = dao->imappers[daio->rscl.msr]; - dao->mgr->imap_delete(dao->mgr, entry); - /* Program conjugate resources */ - for (i = 1; i < daio->rscr.msr; i++) { - entry = dao->imappers[daio->rscl.msr + i]; - dao->mgr->imap_delete(dao->mgr, entry); - dao->imappers[daio->rscl.msr + i] = NULL; - } - - kfree(dao->imappers[daio->rscl.msr]); - dao->imappers[daio->rscl.msr] = NULL; - - return 0; -} - -static struct dao_rsc_ops dao_ops = { - .set_spos = dao_spdif_set_spos, - .commit_write = dao_commit_write, - .get_spos = dao_spdif_get_spos, - .reinit = dao_rsc_reinit, - .set_left_input = dao_set_left_input, - .set_right_input = dao_set_right_input, - .clear_left_input = dao_clear_left_input, - .clear_right_input = dao_clear_right_input, -}; - -static int dai_set_srt_srcl(struct dai *dai, struct rsc *src) -{ - src->ops->master(src); - ((struct hw *)dai->hw)->dai_srt_set_srcm(dai->ctrl_blk, - src->ops->index(src)); - return 0; -} - -static int dai_set_srt_srcr(struct dai *dai, struct rsc *src) -{ - src->ops->master(src); - ((struct hw *)dai->hw)->dai_srt_set_srco(dai->ctrl_blk, - src->ops->index(src)); - return 0; -} - -static int dai_set_srt_msr(struct dai *dai, unsigned int msr) -{ - unsigned int rsr; - - for (rsr = 0; msr > 1; msr >>= 1) - rsr++; - - ((struct hw *)dai->hw)->dai_srt_set_rsr(dai->ctrl_blk, rsr); - return 0; -} - -static int dai_set_enb_src(struct dai *dai, unsigned int enb) -{ - ((struct hw *)dai->hw)->dai_srt_set_ec(dai->ctrl_blk, enb); - return 0; -} - -static int dai_set_enb_srt(struct dai *dai, unsigned int enb) -{ - ((struct hw *)dai->hw)->dai_srt_set_et(dai->ctrl_blk, enb); - return 0; -} - -static int dai_commit_write(struct dai *dai) -{ - ((struct hw *)dai->hw)->dai_commit_write(dai->hw, - daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); - return 0; -} - -static struct dai_rsc_ops dai_ops = { - .set_srt_srcl = dai_set_srt_srcl, - .set_srt_srcr = dai_set_srt_srcr, - .set_srt_msr = dai_set_srt_msr, - .set_enb_src = dai_set_enb_src, - .set_enb_srt = dai_set_enb_srt, - .commit_write = dai_commit_write, -}; - -static int daio_rsc_init(struct daio *daio, - const struct daio_desc *desc, - void *hw) -{ - int err; - unsigned int idx_l, idx_r; - - switch (((struct hw *)hw)->chip_type) { - case ATC20K1: - idx_l = idx_20k1[desc->type].left; - idx_r = idx_20k1[desc->type].right; - break; - case ATC20K2: - idx_l = idx_20k2[desc->type].left; - idx_r = idx_20k2[desc->type].right; - break; - default: - return -EINVAL; - } - err = rsc_init(&daio->rscl, idx_l, DAIO, desc->msr, hw); - if (err) - return err; - - err = rsc_init(&daio->rscr, idx_r, DAIO, desc->msr, hw); - if (err) - goto error1; - - /* Set daio->rscl/r->ops to daio specific ones */ - if (desc->type <= DAIO_OUT_MAX) { - daio->rscl.ops = daio->rscr.ops = &daio_out_rsc_ops; - } else { - switch (((struct hw *)hw)->chip_type) { - case ATC20K1: - daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k1; - break; - case ATC20K2: - daio->rscl.ops = daio->rscr.ops = &daio_in_rsc_ops_20k2; - break; - default: - break; - } - } - daio->type = desc->type; - - return 0; - -error1: - rsc_uninit(&daio->rscl); - return err; -} - -static int daio_rsc_uninit(struct daio *daio) -{ - rsc_uninit(&daio->rscl); - rsc_uninit(&daio->rscr); - - return 0; -} - -static int dao_rsc_init(struct dao *dao, - const struct daio_desc *desc, - struct daio_mgr *mgr) -{ - struct hw *hw = mgr->mgr.hw; - unsigned int conf; - int err; - - err = daio_rsc_init(&dao->daio, desc, mgr->mgr.hw); - if (err) - return err; - - dao->imappers = kzalloc(sizeof(void *)*desc->msr*2, GFP_KERNEL); - if (!dao->imappers) { - err = -ENOMEM; - goto error1; - } - dao->ops = &dao_ops; - dao->mgr = mgr; - dao->hw = hw; - err = hw->dao_get_ctrl_blk(&dao->ctrl_blk); - if (err) - goto error2; - - hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, - daio_device_index(dao->daio.type, hw)); - hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); - - conf = (desc->msr & 0x7) | (desc->passthru << 3); - hw->daio_mgr_dao_init(mgr->mgr.ctrl_blk, - daio_device_index(dao->daio.type, hw), conf); - hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, - daio_device_index(dao->daio.type, hw)); - hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); - - return 0; - -error2: - kfree(dao->imappers); - dao->imappers = NULL; -error1: - daio_rsc_uninit(&dao->daio); - return err; -} - -static int dao_rsc_uninit(struct dao *dao) -{ - if (dao->imappers) { - if (dao->imappers[0]) - dao_clear_left_input(dao); - - if (dao->imappers[dao->daio.rscl.msr]) - dao_clear_right_input(dao); - - kfree(dao->imappers); - dao->imappers = NULL; - } - ((struct hw *)dao->hw)->dao_put_ctrl_blk(dao->ctrl_blk); - dao->hw = dao->ctrl_blk = NULL; - daio_rsc_uninit(&dao->daio); - - return 0; -} - -static int dao_rsc_reinit(struct dao *dao, const struct dao_desc *desc) -{ - struct daio_mgr *mgr = dao->mgr; - struct daio_desc dsc = {0}; - - dsc.type = dao->daio.type; - dsc.msr = desc->msr; - dsc.passthru = desc->passthru; - dao_rsc_uninit(dao); - return dao_rsc_init(dao, &dsc, mgr); -} - -static int dai_rsc_init(struct dai *dai, - const struct daio_desc *desc, - struct daio_mgr *mgr) -{ - int err; - struct hw *hw = mgr->mgr.hw; - unsigned int rsr, msr; - - err = daio_rsc_init(&dai->daio, desc, mgr->mgr.hw); - if (err) - return err; - - dai->ops = &dai_ops; - dai->hw = mgr->mgr.hw; - err = hw->dai_get_ctrl_blk(&dai->ctrl_blk); - if (err) - goto error1; - - for (rsr = 0, msr = desc->msr; msr > 1; msr >>= 1) - rsr++; - - hw->dai_srt_set_rsr(dai->ctrl_blk, rsr); - hw->dai_srt_set_drat(dai->ctrl_blk, 0); - /* default to disabling control of a SRC */ - hw->dai_srt_set_ec(dai->ctrl_blk, 0); - hw->dai_srt_set_et(dai->ctrl_blk, 0); /* default to disabling SRT */ - hw->dai_commit_write(hw, - daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk); - - return 0; - -error1: - daio_rsc_uninit(&dai->daio); - return err; -} - -static int dai_rsc_uninit(struct dai *dai) -{ - ((struct hw *)dai->hw)->dai_put_ctrl_blk(dai->ctrl_blk); - dai->hw = dai->ctrl_blk = NULL; - daio_rsc_uninit(&dai->daio); - return 0; -} - -static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) -{ - if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type)) - return -ENOENT; - - ((struct daio_usage *)mgr->rscs)->data |= (0x1 << type); - - return 0; -} - -static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) -{ - ((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type); - - return 0; -} - -static int get_daio_rsc(struct daio_mgr *mgr, - const struct daio_desc *desc, - struct daio **rdaio) -{ - int err; - struct dai *dai = NULL; - struct dao *dao = NULL; - unsigned long flags; - - *rdaio = NULL; - - /* Check whether there are sufficient daio resources to meet request. */ - spin_lock_irqsave(&mgr->mgr_lock, flags); - err = daio_mgr_get_rsc(&mgr->mgr, desc->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - if (err) { - printk(KERN_ERR "Can't meet DAIO resource request!\n"); - return err; - } - - /* Allocate mem for daio resource */ - if (desc->type <= DAIO_OUT_MAX) { - dao = kzalloc(sizeof(*dao), GFP_KERNEL); - if (!dao) { - err = -ENOMEM; - goto error; - } - err = dao_rsc_init(dao, desc, mgr); - if (err) - goto error; - - *rdaio = &dao->daio; - } else { - dai = kzalloc(sizeof(*dai), GFP_KERNEL); - if (!dai) { - err = -ENOMEM; - goto error; - } - err = dai_rsc_init(dai, desc, mgr); - if (err) - goto error; - - *rdaio = &dai->daio; - } - - mgr->daio_enable(mgr, *rdaio); - mgr->commit_write(mgr); - - return 0; - -error: - if (dao) - kfree(dao); - else if (dai) - kfree(dai); - - spin_lock_irqsave(&mgr->mgr_lock, flags); - daio_mgr_put_rsc(&mgr->mgr, desc->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - return err; -} - -static int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio) -{ - unsigned long flags; - - mgr->daio_disable(mgr, daio); - mgr->commit_write(mgr); - - spin_lock_irqsave(&mgr->mgr_lock, flags); - daio_mgr_put_rsc(&mgr->mgr, daio->type); - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - - if (daio->type <= DAIO_OUT_MAX) { - dao_rsc_uninit(container_of(daio, struct dao, daio)); - kfree(container_of(daio, struct dao, daio)); - } else { - dai_rsc_uninit(container_of(daio, struct dai, daio)); - kfree(container_of(daio, struct dai, daio)); - } - - return 0; -} - -static int daio_mgr_enb_daio(struct daio_mgr *mgr, struct daio *daio) -{ - struct hw *hw = mgr->mgr.hw; - - if (DAIO_OUT_MAX >= daio->type) { - hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, - daio_device_index(daio->type, hw)); - } else { - hw->daio_mgr_enb_dai(mgr->mgr.ctrl_blk, - daio_device_index(daio->type, hw)); - } - return 0; -} - -static int daio_mgr_dsb_daio(struct daio_mgr *mgr, struct daio *daio) -{ - struct hw *hw = mgr->mgr.hw; - - if (DAIO_OUT_MAX >= daio->type) { - hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, - daio_device_index(daio->type, hw)); - } else { - hw->daio_mgr_dsb_dai(mgr->mgr.ctrl_blk, - daio_device_index(daio->type, hw)); - } - return 0; -} - -static int daio_map_op(void *data, struct imapper *entry) -{ - struct rsc_mgr *mgr = &((struct daio_mgr *)data)->mgr; - struct hw *hw = mgr->hw; - - hw->daio_mgr_set_imaparc(mgr->ctrl_blk, entry->slot); - hw->daio_mgr_set_imapnxt(mgr->ctrl_blk, entry->next); - hw->daio_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr); - hw->daio_mgr_commit_write(mgr->hw, mgr->ctrl_blk); - - return 0; -} - -static int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&mgr->imap_lock, flags); - if (!entry->addr && mgr->init_imap_added) { - input_mapper_delete(&mgr->imappers, mgr->init_imap, - daio_map_op, mgr); - mgr->init_imap_added = 0; - } - err = input_mapper_add(&mgr->imappers, entry, daio_map_op, mgr); - spin_unlock_irqrestore(&mgr->imap_lock, flags); - - return err; -} - -static int daio_imap_delete(struct daio_mgr *mgr, struct imapper *entry) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&mgr->imap_lock, flags); - err = input_mapper_delete(&mgr->imappers, entry, daio_map_op, mgr); - if (list_empty(&mgr->imappers)) { - input_mapper_add(&mgr->imappers, mgr->init_imap, - daio_map_op, mgr); - mgr->init_imap_added = 1; - } - spin_unlock_irqrestore(&mgr->imap_lock, flags); - - return err; -} - -static int daio_mgr_commit_write(struct daio_mgr *mgr) -{ - struct hw *hw = mgr->mgr.hw; - - hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk); - return 0; -} - -int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) -{ - int err, i; - struct daio_mgr *daio_mgr; - struct imapper *entry; - - *rdaio_mgr = NULL; - daio_mgr = kzalloc(sizeof(*daio_mgr), GFP_KERNEL); - if (!daio_mgr) - return -ENOMEM; - - err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw); - if (err) - goto error1; - - spin_lock_init(&daio_mgr->mgr_lock); - spin_lock_init(&daio_mgr->imap_lock); - INIT_LIST_HEAD(&daio_mgr->imappers); - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - err = -ENOMEM; - goto error2; - } - entry->slot = entry->addr = entry->next = entry->user = 0; - list_add(&entry->list, &daio_mgr->imappers); - daio_mgr->init_imap = entry; - daio_mgr->init_imap_added = 1; - - daio_mgr->get_daio = get_daio_rsc; - daio_mgr->put_daio = put_daio_rsc; - daio_mgr->daio_enable = daio_mgr_enb_daio; - daio_mgr->daio_disable = daio_mgr_dsb_daio; - daio_mgr->imap_add = daio_imap_add; - daio_mgr->imap_delete = daio_imap_delete; - daio_mgr->commit_write = daio_mgr_commit_write; - - for (i = 0; i < 8; i++) { - ((struct hw *)hw)->daio_mgr_dsb_dao(daio_mgr->mgr.ctrl_blk, i); - ((struct hw *)hw)->daio_mgr_dsb_dai(daio_mgr->mgr.ctrl_blk, i); - } - ((struct hw *)hw)->daio_mgr_commit_write(hw, daio_mgr->mgr.ctrl_blk); - - *rdaio_mgr = daio_mgr; - - return 0; - -error2: - rsc_mgr_uninit(&daio_mgr->mgr); -error1: - kfree(daio_mgr); - return err; -} - -int daio_mgr_destroy(struct daio_mgr *daio_mgr) -{ - unsigned long flags; - - /* free daio input mapper list */ - spin_lock_irqsave(&daio_mgr->imap_lock, flags); - free_input_mapper_list(&daio_mgr->imappers); - spin_unlock_irqrestore(&daio_mgr->imap_lock, flags); - - rsc_mgr_uninit(&daio_mgr->mgr); - kfree(daio_mgr); - - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.h deleted file mode 100644 index 85ccb6ee..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctdaio.h +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctdaio.h - * - * @Brief - * This file contains the definition of Digital Audio Input Output - * resource management object. - * - * @Author Liu Chun - * @Date May 23 2008 - * - */ - -#ifndef CTDAIO_H -#define CTDAIO_H - -#include "ctresource.h" -#include "ctimap.h" -#include -#include - -/* Define the descriptor of a daio resource */ -enum DAIOTYP { - LINEO1, - LINEO2, - LINEO3, - LINEO4, - SPDIFOO, /* S/PDIF Out (Flexijack/Optical) */ - LINEIM, - SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */ - MIC, /* Dedicated mic on Titanium HD */ - SPDIFI1, /* S/PDIF In on internal Drive Bay */ - NUM_DAIOTYP -}; - -struct dao_rsc_ops; -struct dai_rsc_ops; -struct daio_mgr; - -struct daio { - struct rsc rscl; /* Basic resource info for left TX/RX */ - struct rsc rscr; /* Basic resource info for right TX/RX */ - enum DAIOTYP type; -}; - -struct dao { - struct daio daio; - struct dao_rsc_ops *ops; /* DAO specific operations */ - struct imapper **imappers; - struct daio_mgr *mgr; - void *hw; - void *ctrl_blk; -}; - -struct dai { - struct daio daio; - struct dai_rsc_ops *ops; /* DAI specific operations */ - void *hw; - void *ctrl_blk; -}; - -struct dao_desc { - unsigned int msr:4; - unsigned int passthru:1; -}; - -struct dao_rsc_ops { - int (*set_spos)(struct dao *dao, unsigned int spos); - int (*commit_write)(struct dao *dao); - int (*get_spos)(struct dao *dao, unsigned int *spos); - int (*reinit)(struct dao *dao, const struct dao_desc *desc); - int (*set_left_input)(struct dao *dao, struct rsc *input); - int (*set_right_input)(struct dao *dao, struct rsc *input); - int (*clear_left_input)(struct dao *dao); - int (*clear_right_input)(struct dao *dao); -}; - -struct dai_rsc_ops { - int (*set_srt_srcl)(struct dai *dai, struct rsc *src); - int (*set_srt_srcr)(struct dai *dai, struct rsc *src); - int (*set_srt_msr)(struct dai *dai, unsigned int msr); - int (*set_enb_src)(struct dai *dai, unsigned int enb); - int (*set_enb_srt)(struct dai *dai, unsigned int enb); - int (*commit_write)(struct dai *dai); -}; - -/* Define daio resource request description info */ -struct daio_desc { - unsigned int type:4; - unsigned int msr:4; - unsigned int passthru:1; -}; - -struct daio_mgr { - struct rsc_mgr mgr; /* Basic resource manager info */ - spinlock_t mgr_lock; - spinlock_t imap_lock; - struct list_head imappers; - struct imapper *init_imap; - unsigned int init_imap_added; - - /* request one daio resource */ - int (*get_daio)(struct daio_mgr *mgr, - const struct daio_desc *desc, struct daio **rdaio); - /* return one daio resource */ - int (*put_daio)(struct daio_mgr *mgr, struct daio *daio); - int (*daio_enable)(struct daio_mgr *mgr, struct daio *daio); - int (*daio_disable)(struct daio_mgr *mgr, struct daio *daio); - int (*imap_add)(struct daio_mgr *mgr, struct imapper *entry); - int (*imap_delete)(struct daio_mgr *mgr, struct imapper *entry); - int (*commit_write)(struct daio_mgr *mgr); -}; - -/* Constructor and destructor of daio resource manager */ -int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr); -int daio_mgr_destroy(struct daio_mgr *daio_mgr); - -#endif /* CTDAIO_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/cthardware.c b/ANDROID_3.4.5/sound/pci/ctxfi/cthardware.c deleted file mode 100644 index 8e64f486..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/cthardware.c +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File cthardware.c - * - * @Brief - * This file contains the implementation of hardware access methord. - * - * @Author Liu Chun - * @Date Jun 26 2008 - * - */ - -#include "cthardware.h" -#include "cthw20k1.h" -#include "cthw20k2.h" -#include - -int __devinit create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type, - enum CTCARDS model, struct hw **rhw) -{ - int err; - - switch (chip_type) { - case ATC20K1: - err = create_20k1_hw_obj(rhw); - break; - case ATC20K2: - err = create_20k2_hw_obj(rhw); - break; - default: - err = -ENODEV; - break; - } - if (err) - return err; - - (*rhw)->pci = pci; - (*rhw)->chip_type = chip_type; - (*rhw)->model = model; - - return 0; -} - -int destroy_hw_obj(struct hw *hw) -{ - int err; - - switch (hw->pci->device) { - case 0x0005: /* 20k1 device */ - err = destroy_20k1_hw_obj(hw); - break; - case 0x000B: /* 20k2 device */ - err = destroy_20k2_hw_obj(hw); - break; - default: - err = -ENODEV; - break; - } - - return err; -} - -unsigned int get_field(unsigned int data, unsigned int field) -{ - int i; - - BUG_ON(!field); - /* @field should always be greater than 0 */ - for (i = 0; !(field & (1 << i)); ) - i++; - - return (data & field) >> i; -} - -void set_field(unsigned int *data, unsigned int field, unsigned int value) -{ - int i; - - BUG_ON(!field); - /* @field should always be greater than 0 */ - for (i = 0; !(field & (1 << i)); ) - i++; - - *data = (*data & (~field)) | ((value << i) & field); -} - diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/cthardware.h b/ANDROID_3.4.5/sound/pci/ctxfi/cthardware.h deleted file mode 100644 index 908315be..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/cthardware.h +++ /dev/null @@ -1,215 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File cthardware.h - * - * @Brief - * This file contains the definition of hardware access methord. - * - * @Author Liu Chun - * @Date May 13 2008 - * - */ - -#ifndef CTHARDWARE_H -#define CTHARDWARE_H - -#include -#include - -enum CHIPTYP { - ATC20K1, - ATC20K2, - ATCNONE -}; - -enum CTCARDS { - /* 20k1 models */ - CTSB055X, - CT20K1_MODEL_FIRST = CTSB055X, - CTSB073X, - CTUAA, - CT20K1_UNKNOWN, - /* 20k2 models */ - CTSB0760, - CT20K2_MODEL_FIRST = CTSB0760, - CTHENDRIX, - CTSB0880, - CTSB1270, - CT20K2_UNKNOWN, - NUM_CTCARDS /* This should always be the last */ -}; - -/* Type of input source for ADC */ -enum ADCSRC{ - ADC_MICIN, - ADC_LINEIN, - ADC_VIDEO, - ADC_AUX, - ADC_NONE /* Switch to digital input */ -}; - -struct card_conf { - /* device virtual mem page table page physical addr - * (supporting one page table page now) */ - unsigned long vm_pgt_phys; - unsigned int rsr; /* reference sample rate in Hzs*/ - unsigned int msr; /* master sample rate in rsrs */ -}; - -struct capabilities { - unsigned int digit_io_switch:1; - unsigned int dedicated_mic:1; - unsigned int output_switch:1; - unsigned int mic_source_switch:1; -}; - -struct hw { - int (*card_init)(struct hw *hw, struct card_conf *info); - int (*card_stop)(struct hw *hw); - int (*pll_init)(struct hw *hw, unsigned int rsr); -#ifdef CONFIG_PM - int (*suspend)(struct hw *hw, pm_message_t state); - int (*resume)(struct hw *hw, struct card_conf *info); -#endif - int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); - int (*select_adc_source)(struct hw *hw, enum ADCSRC source); - struct capabilities (*capabilities)(struct hw *hw); - int (*output_switch_get)(struct hw *hw); - int (*output_switch_put)(struct hw *hw, int position); - int (*mic_source_switch_get)(struct hw *hw); - int (*mic_source_switch_put)(struct hw *hw, int position); - - /* SRC operations */ - int (*src_rsc_get_ctrl_blk)(void **rblk); - int (*src_rsc_put_ctrl_blk)(void *blk); - int (*src_set_state)(void *blk, unsigned int state); - int (*src_set_bm)(void *blk, unsigned int bm); - int (*src_set_rsr)(void *blk, unsigned int rsr); - int (*src_set_sf)(void *blk, unsigned int sf); - int (*src_set_wr)(void *blk, unsigned int wr); - int (*src_set_pm)(void *blk, unsigned int pm); - int (*src_set_rom)(void *blk, unsigned int rom); - int (*src_set_vo)(void *blk, unsigned int vo); - int (*src_set_st)(void *blk, unsigned int st); - int (*src_set_ie)(void *blk, unsigned int ie); - int (*src_set_ilsz)(void *blk, unsigned int ilsz); - int (*src_set_bp)(void *blk, unsigned int bp); - int (*src_set_cisz)(void *blk, unsigned int cisz); - int (*src_set_ca)(void *blk, unsigned int ca); - int (*src_set_sa)(void *blk, unsigned int sa); - int (*src_set_la)(void *blk, unsigned int la); - int (*src_set_pitch)(void *blk, unsigned int pitch); - int (*src_set_clear_zbufs)(void *blk, unsigned int clear); - int (*src_set_dirty)(void *blk, unsigned int flags); - int (*src_set_dirty_all)(void *blk); - int (*src_commit_write)(struct hw *hw, unsigned int idx, void *blk); - int (*src_get_ca)(struct hw *hw, unsigned int idx, void *blk); - unsigned int (*src_get_dirty)(void *blk); - unsigned int (*src_dirty_conj_mask)(void); - int (*src_mgr_get_ctrl_blk)(void **rblk); - int (*src_mgr_put_ctrl_blk)(void *blk); - /* syncly enable src @idx */ - int (*src_mgr_enbs_src)(void *blk, unsigned int idx); - /* enable src @idx */ - int (*src_mgr_enb_src)(void *blk, unsigned int idx); - /* disable src @idx */ - int (*src_mgr_dsb_src)(void *blk, unsigned int idx); - int (*src_mgr_commit_write)(struct hw *hw, void *blk); - - /* SRC Input Mapper operations */ - int (*srcimp_mgr_get_ctrl_blk)(void **rblk); - int (*srcimp_mgr_put_ctrl_blk)(void *blk); - int (*srcimp_mgr_set_imaparc)(void *blk, unsigned int slot); - int (*srcimp_mgr_set_imapuser)(void *blk, unsigned int user); - int (*srcimp_mgr_set_imapnxt)(void *blk, unsigned int next); - int (*srcimp_mgr_set_imapaddr)(void *blk, unsigned int addr); - int (*srcimp_mgr_commit_write)(struct hw *hw, void *blk); - - /* AMIXER operations */ - int (*amixer_rsc_get_ctrl_blk)(void **rblk); - int (*amixer_rsc_put_ctrl_blk)(void *blk); - int (*amixer_mgr_get_ctrl_blk)(void **rblk); - int (*amixer_mgr_put_ctrl_blk)(void *blk); - int (*amixer_set_mode)(void *blk, unsigned int mode); - int (*amixer_set_iv)(void *blk, unsigned int iv); - int (*amixer_set_x)(void *blk, unsigned int x); - int (*amixer_set_y)(void *blk, unsigned int y); - int (*amixer_set_sadr)(void *blk, unsigned int sadr); - int (*amixer_set_se)(void *blk, unsigned int se); - int (*amixer_set_dirty)(void *blk, unsigned int flags); - int (*amixer_set_dirty_all)(void *blk); - int (*amixer_commit_write)(struct hw *hw, unsigned int idx, void *blk); - int (*amixer_get_y)(void *blk); - unsigned int (*amixer_get_dirty)(void *blk); - - /* DAIO operations */ - int (*dai_get_ctrl_blk)(void **rblk); - int (*dai_put_ctrl_blk)(void *blk); - int (*dai_srt_set_srco)(void *blk, unsigned int src); - int (*dai_srt_set_srcm)(void *blk, unsigned int src); - int (*dai_srt_set_rsr)(void *blk, unsigned int rsr); - int (*dai_srt_set_drat)(void *blk, unsigned int drat); - int (*dai_srt_set_ec)(void *blk, unsigned int ec); - int (*dai_srt_set_et)(void *blk, unsigned int et); - int (*dai_commit_write)(struct hw *hw, unsigned int idx, void *blk); - int (*dao_get_ctrl_blk)(void **rblk); - int (*dao_put_ctrl_blk)(void *blk); - int (*dao_set_spos)(void *blk, unsigned int spos); - int (*dao_commit_write)(struct hw *hw, unsigned int idx, void *blk); - int (*dao_get_spos)(void *blk, unsigned int *spos); - - int (*daio_mgr_get_ctrl_blk)(struct hw *hw, void **rblk); - int (*daio_mgr_put_ctrl_blk)(void *blk); - int (*daio_mgr_enb_dai)(void *blk, unsigned int idx); - int (*daio_mgr_dsb_dai)(void *blk, unsigned int idx); - int (*daio_mgr_enb_dao)(void *blk, unsigned int idx); - int (*daio_mgr_dsb_dao)(void *blk, unsigned int idx); - int (*daio_mgr_dao_init)(void *blk, unsigned int idx, - unsigned int conf); - int (*daio_mgr_set_imaparc)(void *blk, unsigned int slot); - int (*daio_mgr_set_imapnxt)(void *blk, unsigned int next); - int (*daio_mgr_set_imapaddr)(void *blk, unsigned int addr); - int (*daio_mgr_commit_write)(struct hw *hw, void *blk); - - int (*set_timer_irq)(struct hw *hw, int enable); - int (*set_timer_tick)(struct hw *hw, unsigned int tick); - unsigned int (*get_wc)(struct hw *hw); - - void (*irq_callback)(void *data, unsigned int bit); - void *irq_callback_data; - - struct pci_dev *pci; /* the pci kernel structure of this card */ - int irq; - unsigned long io_base; - unsigned long mem_base; - - enum CHIPTYP chip_type; - enum CTCARDS model; -}; - -int create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type, - enum CTCARDS model, struct hw **rhw); -int destroy_hw_obj(struct hw *hw); - -unsigned int get_field(unsigned int data, unsigned int field); -void set_field(unsigned int *data, unsigned int field, unsigned int value); - -/* IRQ bits */ -#define PLL_INT (1 << 10) /* PLL input-clock out-of-range */ -#define FI_INT (1 << 9) /* forced interrupt */ -#define IT_INT (1 << 8) /* timer interrupt */ -#define PCI_INT (1 << 7) /* PCI bus error pending */ -#define URT_INT (1 << 6) /* UART Tx/Rx */ -#define GPI_INT (1 << 5) /* GPI pin */ -#define MIX_INT (1 << 4) /* mixer parameter segment FIFO channels */ -#define DAI_INT (1 << 3) /* DAI (SR-tracker or SPDIF-receiver) */ -#define TP_INT (1 << 2) /* transport priority queue */ -#define DSP_INT (1 << 1) /* DSP */ -#define SRC_INT (1 << 0) /* SRC channels */ - -#endif /* CTHARDWARE_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.c b/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.c deleted file mode 100644 index a7df1979..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.c +++ /dev/null @@ -1,2304 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File cthw20k1.c - * - * @Brief - * This file contains the implementation of hardware access methord for 20k1. - * - * @Author Liu Chun - * @Date Jun 24 2008 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cthw20k1.h" -#include "ct20k1reg.h" - -#if BITS_PER_LONG == 32 -#define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bit PTE */ -#else -#define CT_XFI_DMA_MASK DMA_BIT_MASK(64) /* 64 bit PTE */ -#endif - -struct hw20k1 { - struct hw hw; - spinlock_t reg_20k1_lock; - spinlock_t reg_pci_lock; -}; - -static u32 hw_read_20kx(struct hw *hw, u32 reg); -static void hw_write_20kx(struct hw *hw, u32 reg, u32 data); -static u32 hw_read_pci(struct hw *hw, u32 reg); -static void hw_write_pci(struct hw *hw, u32 reg, u32 data); - -/* - * Type definition block. - * The layout of control structures can be directly applied on 20k2 chip. - */ - -/* - * SRC control block definitions. - */ - -/* SRC resource control block */ -#define SRCCTL_STATE 0x00000007 -#define SRCCTL_BM 0x00000008 -#define SRCCTL_RSR 0x00000030 -#define SRCCTL_SF 0x000001C0 -#define SRCCTL_WR 0x00000200 -#define SRCCTL_PM 0x00000400 -#define SRCCTL_ROM 0x00001800 -#define SRCCTL_VO 0x00002000 -#define SRCCTL_ST 0x00004000 -#define SRCCTL_IE 0x00008000 -#define SRCCTL_ILSZ 0x000F0000 -#define SRCCTL_BP 0x00100000 - -#define SRCCCR_CISZ 0x000007FF -#define SRCCCR_CWA 0x001FF800 -#define SRCCCR_D 0x00200000 -#define SRCCCR_RS 0x01C00000 -#define SRCCCR_NAL 0x3E000000 -#define SRCCCR_RA 0xC0000000 - -#define SRCCA_CA 0x03FFFFFF -#define SRCCA_RS 0x1C000000 -#define SRCCA_NAL 0xE0000000 - -#define SRCSA_SA 0x03FFFFFF - -#define SRCLA_LA 0x03FFFFFF - -/* Mixer Parameter Ring ram Low and Hight register. - * Fixed-point value in 8.24 format for parameter channel */ -#define MPRLH_PITCH 0xFFFFFFFF - -/* SRC resource register dirty flags */ -union src_dirty { - struct { - u16 ctl:1; - u16 ccr:1; - u16 sa:1; - u16 la:1; - u16 ca:1; - u16 mpr:1; - u16 czbfs:1; /* Clear Z-Buffers */ - u16 rsv:9; - } bf; - u16 data; -}; - -struct src_rsc_ctrl_blk { - unsigned int ctl; - unsigned int ccr; - unsigned int ca; - unsigned int sa; - unsigned int la; - unsigned int mpr; - union src_dirty dirty; -}; - -/* SRC manager control block */ -union src_mgr_dirty { - struct { - u16 enb0:1; - u16 enb1:1; - u16 enb2:1; - u16 enb3:1; - u16 enb4:1; - u16 enb5:1; - u16 enb6:1; - u16 enb7:1; - u16 enbsa:1; - u16 rsv:7; - } bf; - u16 data; -}; - -struct src_mgr_ctrl_blk { - unsigned int enbsa; - unsigned int enb[8]; - union src_mgr_dirty dirty; -}; - -/* SRCIMP manager control block */ -#define SRCAIM_ARC 0x00000FFF -#define SRCAIM_NXT 0x00FF0000 -#define SRCAIM_SRC 0xFF000000 - -struct srcimap { - unsigned int srcaim; - unsigned int idx; -}; - -/* SRCIMP manager register dirty flags */ -union srcimp_mgr_dirty { - struct { - u16 srcimap:1; - u16 rsv:15; - } bf; - u16 data; -}; - -struct srcimp_mgr_ctrl_blk { - struct srcimap srcimap; - union srcimp_mgr_dirty dirty; -}; - -/* - * Function implementation block. - */ - -static int src_get_rsc_ctrl_blk(void **rblk) -{ - struct src_rsc_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int src_put_rsc_ctrl_blk(void *blk) -{ - kfree((struct src_rsc_ctrl_blk *)blk); - - return 0; -} - -static int src_set_state(void *blk, unsigned int state) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_STATE, state); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_bm(void *blk, unsigned int bm) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_BM, bm); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_rsr(void *blk, unsigned int rsr) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_RSR, rsr); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_sf(void *blk, unsigned int sf) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_SF, sf); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_wr(void *blk, unsigned int wr) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_WR, wr); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_pm(void *blk, unsigned int pm) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_PM, pm); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_rom(void *blk, unsigned int rom) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_ROM, rom); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_vo(void *blk, unsigned int vo) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_VO, vo); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_st(void *blk, unsigned int st) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_ST, st); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_ie(void *blk, unsigned int ie) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_IE, ie); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_ilsz(void *blk, unsigned int ilsz) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_ILSZ, ilsz); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_bp(void *blk, unsigned int bp) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_BP, bp); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_cisz(void *blk, unsigned int cisz) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ccr, SRCCCR_CISZ, cisz); - ctl->dirty.bf.ccr = 1; - return 0; -} - -static int src_set_ca(void *blk, unsigned int ca) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ca, SRCCA_CA, ca); - ctl->dirty.bf.ca = 1; - return 0; -} - -static int src_set_sa(void *blk, unsigned int sa) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->sa, SRCSA_SA, sa); - ctl->dirty.bf.sa = 1; - return 0; -} - -static int src_set_la(void *blk, unsigned int la) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->la, SRCLA_LA, la); - ctl->dirty.bf.la = 1; - return 0; -} - -static int src_set_pitch(void *blk, unsigned int pitch) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->mpr, MPRLH_PITCH, pitch); - ctl->dirty.bf.mpr = 1; - return 0; -} - -static int src_set_clear_zbufs(void *blk, unsigned int clear) -{ - ((struct src_rsc_ctrl_blk *)blk)->dirty.bf.czbfs = (clear ? 1 : 0); - return 0; -} - -static int src_set_dirty(void *blk, unsigned int flags) -{ - ((struct src_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); - return 0; -} - -static int src_set_dirty_all(void *blk) -{ - ((struct src_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); - return 0; -} - -#define AR_SLOT_SIZE 4096 -#define AR_SLOT_BLOCK_SIZE 16 -#define AR_PTS_PITCH 6 -#define AR_PARAM_SRC_OFFSET 0x60 - -static unsigned int src_param_pitch_mixer(unsigned int src_idx) -{ - return ((src_idx << 4) + AR_PTS_PITCH + AR_SLOT_SIZE - - AR_PARAM_SRC_OFFSET) % AR_SLOT_SIZE; - -} - -static int src_commit_write(struct hw *hw, unsigned int idx, void *blk) -{ - struct src_rsc_ctrl_blk *ctl = blk; - int i; - - if (ctl->dirty.bf.czbfs) { - /* Clear Z-Buffer registers */ - for (i = 0; i < 8; i++) - hw_write_20kx(hw, SRCUPZ+idx*0x100+i*0x4, 0); - - for (i = 0; i < 4; i++) - hw_write_20kx(hw, SRCDN0Z+idx*0x100+i*0x4, 0); - - for (i = 0; i < 8; i++) - hw_write_20kx(hw, SRCDN1Z+idx*0x100+i*0x4, 0); - - ctl->dirty.bf.czbfs = 0; - } - if (ctl->dirty.bf.mpr) { - /* Take the parameter mixer resource in the same group as that - * the idx src is in for simplicity. Unlike src, all conjugate - * parameter mixer resources must be programmed for - * corresponding conjugate src resources. */ - unsigned int pm_idx = src_param_pitch_mixer(idx); - hw_write_20kx(hw, PRING_LO_HI+4*pm_idx, ctl->mpr); - hw_write_20kx(hw, PMOPLO+8*pm_idx, 0x3); - hw_write_20kx(hw, PMOPHI+8*pm_idx, 0x0); - ctl->dirty.bf.mpr = 0; - } - if (ctl->dirty.bf.sa) { - hw_write_20kx(hw, SRCSA+idx*0x100, ctl->sa); - ctl->dirty.bf.sa = 0; - } - if (ctl->dirty.bf.la) { - hw_write_20kx(hw, SRCLA+idx*0x100, ctl->la); - ctl->dirty.bf.la = 0; - } - if (ctl->dirty.bf.ca) { - hw_write_20kx(hw, SRCCA+idx*0x100, ctl->ca); - ctl->dirty.bf.ca = 0; - } - - /* Write srccf register */ - hw_write_20kx(hw, SRCCF+idx*0x100, 0x0); - - if (ctl->dirty.bf.ccr) { - hw_write_20kx(hw, SRCCCR+idx*0x100, ctl->ccr); - ctl->dirty.bf.ccr = 0; - } - if (ctl->dirty.bf.ctl) { - hw_write_20kx(hw, SRCCTL+idx*0x100, ctl->ctl); - ctl->dirty.bf.ctl = 0; - } - - return 0; -} - -static int src_get_ca(struct hw *hw, unsigned int idx, void *blk) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - ctl->ca = hw_read_20kx(hw, SRCCA+idx*0x100); - ctl->dirty.bf.ca = 0; - - return get_field(ctl->ca, SRCCA_CA); -} - -static unsigned int src_get_dirty(void *blk) -{ - return ((struct src_rsc_ctrl_blk *)blk)->dirty.data; -} - -static unsigned int src_dirty_conj_mask(void) -{ - return 0x20; -} - -static int src_mgr_enbs_src(void *blk, unsigned int idx) -{ - ((struct src_mgr_ctrl_blk *)blk)->enbsa = ~(0x0); - ((struct src_mgr_ctrl_blk *)blk)->dirty.bf.enbsa = 1; - ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); - return 0; -} - -static int src_mgr_enb_src(void *blk, unsigned int idx) -{ - ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); - ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); - return 0; -} - -static int src_mgr_dsb_src(void *blk, unsigned int idx) -{ - ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] &= ~(0x1 << (idx%32)); - ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); - return 0; -} - -static int src_mgr_commit_write(struct hw *hw, void *blk) -{ - struct src_mgr_ctrl_blk *ctl = blk; - int i; - unsigned int ret; - - if (ctl->dirty.bf.enbsa) { - do { - ret = hw_read_20kx(hw, SRCENBSTAT); - } while (ret & 0x1); - hw_write_20kx(hw, SRCENBS, ctl->enbsa); - ctl->dirty.bf.enbsa = 0; - } - for (i = 0; i < 8; i++) { - if ((ctl->dirty.data & (0x1 << i))) { - hw_write_20kx(hw, SRCENB+(i*0x100), ctl->enb[i]); - ctl->dirty.data &= ~(0x1 << i); - } - } - - return 0; -} - -static int src_mgr_get_ctrl_blk(void **rblk) -{ - struct src_mgr_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int src_mgr_put_ctrl_blk(void *blk) -{ - kfree((struct src_mgr_ctrl_blk *)blk); - - return 0; -} - -static int srcimp_mgr_get_ctrl_blk(void **rblk) -{ - struct srcimp_mgr_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int srcimp_mgr_put_ctrl_blk(void *blk) -{ - kfree((struct srcimp_mgr_ctrl_blk *)blk); - - return 0; -} - -static int srcimp_mgr_set_imaparc(void *blk, unsigned int slot) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->srcimap.srcaim, SRCAIM_ARC, slot); - ctl->dirty.bf.srcimap = 1; - return 0; -} - -static int srcimp_mgr_set_imapuser(void *blk, unsigned int user) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->srcimap.srcaim, SRCAIM_SRC, user); - ctl->dirty.bf.srcimap = 1; - return 0; -} - -static int srcimp_mgr_set_imapnxt(void *blk, unsigned int next) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->srcimap.srcaim, SRCAIM_NXT, next); - ctl->dirty.bf.srcimap = 1; - return 0; -} - -static int srcimp_mgr_set_imapaddr(void *blk, unsigned int addr) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - ctl->srcimap.idx = addr; - ctl->dirty.bf.srcimap = 1; - return 0; -} - -static int srcimp_mgr_commit_write(struct hw *hw, void *blk) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - if (ctl->dirty.bf.srcimap) { - hw_write_20kx(hw, SRCIMAP+ctl->srcimap.idx*0x100, - ctl->srcimap.srcaim); - ctl->dirty.bf.srcimap = 0; - } - - return 0; -} - -/* - * AMIXER control block definitions. - */ - -#define AMOPLO_M 0x00000003 -#define AMOPLO_X 0x0003FFF0 -#define AMOPLO_Y 0xFFFC0000 - -#define AMOPHI_SADR 0x000000FF -#define AMOPHI_SE 0x80000000 - -/* AMIXER resource register dirty flags */ -union amixer_dirty { - struct { - u16 amoplo:1; - u16 amophi:1; - u16 rsv:14; - } bf; - u16 data; -}; - -/* AMIXER resource control block */ -struct amixer_rsc_ctrl_blk { - unsigned int amoplo; - unsigned int amophi; - union amixer_dirty dirty; -}; - -static int amixer_set_mode(void *blk, unsigned int mode) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amoplo, AMOPLO_M, mode); - ctl->dirty.bf.amoplo = 1; - return 0; -} - -static int amixer_set_iv(void *blk, unsigned int iv) -{ - /* 20k1 amixer does not have this field */ - return 0; -} - -static int amixer_set_x(void *blk, unsigned int x) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amoplo, AMOPLO_X, x); - ctl->dirty.bf.amoplo = 1; - return 0; -} - -static int amixer_set_y(void *blk, unsigned int y) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amoplo, AMOPLO_Y, y); - ctl->dirty.bf.amoplo = 1; - return 0; -} - -static int amixer_set_sadr(void *blk, unsigned int sadr) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amophi, AMOPHI_SADR, sadr); - ctl->dirty.bf.amophi = 1; - return 0; -} - -static int amixer_set_se(void *blk, unsigned int se) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amophi, AMOPHI_SE, se); - ctl->dirty.bf.amophi = 1; - return 0; -} - -static int amixer_set_dirty(void *blk, unsigned int flags) -{ - ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); - return 0; -} - -static int amixer_set_dirty_all(void *blk) -{ - ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); - return 0; -} - -static int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) { - hw_write_20kx(hw, AMOPLO+idx*8, ctl->amoplo); - ctl->dirty.bf.amoplo = 0; - hw_write_20kx(hw, AMOPHI+idx*8, ctl->amophi); - ctl->dirty.bf.amophi = 0; - } - - return 0; -} - -static int amixer_get_y(void *blk) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - return get_field(ctl->amoplo, AMOPLO_Y); -} - -static unsigned int amixer_get_dirty(void *blk) -{ - return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data; -} - -static int amixer_rsc_get_ctrl_blk(void **rblk) -{ - struct amixer_rsc_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int amixer_rsc_put_ctrl_blk(void *blk) -{ - kfree((struct amixer_rsc_ctrl_blk *)blk); - - return 0; -} - -static int amixer_mgr_get_ctrl_blk(void **rblk) -{ - /*amixer_mgr_ctrl_blk_t *blk;*/ - - *rblk = NULL; - /*blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk;*/ - - return 0; -} - -static int amixer_mgr_put_ctrl_blk(void *blk) -{ - /*kfree((amixer_mgr_ctrl_blk_t *)blk);*/ - - return 0; -} - -/* - * DAIO control block definitions. - */ - -/* Receiver Sample Rate Tracker Control register */ -#define SRTCTL_SRCR 0x000000FF -#define SRTCTL_SRCL 0x0000FF00 -#define SRTCTL_RSR 0x00030000 -#define SRTCTL_DRAT 0x000C0000 -#define SRTCTL_RLE 0x10000000 -#define SRTCTL_RLP 0x20000000 -#define SRTCTL_EC 0x40000000 -#define SRTCTL_ET 0x80000000 - -/* DAIO Receiver register dirty flags */ -union dai_dirty { - struct { - u16 srtctl:1; - u16 rsv:15; - } bf; - u16 data; -}; - -/* DAIO Receiver control block */ -struct dai_ctrl_blk { - unsigned int srtctl; - union dai_dirty dirty; -}; - -/* S/PDIF Transmitter register dirty flags */ -union dao_dirty { - struct { - u16 spos:1; - u16 rsv:15; - } bf; - u16 data; -}; - -/* S/PDIF Transmitter control block */ -struct dao_ctrl_blk { - unsigned int spos; /* S/PDIF Output Channel Status Register */ - union dao_dirty dirty; -}; - -/* Audio Input Mapper RAM */ -#define AIM_ARC 0x00000FFF -#define AIM_NXT 0x007F0000 - -struct daoimap { - unsigned int aim; - unsigned int idx; -}; - -/* I2S Transmitter/Receiver Control register */ -#define I2SCTL_EA 0x00000004 -#define I2SCTL_EI 0x00000010 - -/* S/PDIF Transmitter Control register */ -#define SPOCTL_OE 0x00000001 -#define SPOCTL_OS 0x0000000E -#define SPOCTL_RIV 0x00000010 -#define SPOCTL_LIV 0x00000020 -#define SPOCTL_SR 0x000000C0 - -/* S/PDIF Receiver Control register */ -#define SPICTL_EN 0x00000001 -#define SPICTL_I24 0x00000002 -#define SPICTL_IB 0x00000004 -#define SPICTL_SM 0x00000008 -#define SPICTL_VM 0x00000010 - -/* DAIO manager register dirty flags */ -union daio_mgr_dirty { - struct { - u32 i2soctl:4; - u32 i2sictl:4; - u32 spoctl:4; - u32 spictl:4; - u32 daoimap:1; - u32 rsv:15; - } bf; - u32 data; -}; - -/* DAIO manager control block */ -struct daio_mgr_ctrl_blk { - unsigned int i2sctl; - unsigned int spoctl; - unsigned int spictl; - struct daoimap daoimap; - union daio_mgr_dirty dirty; -}; - -static int dai_srt_set_srcr(void *blk, unsigned int src) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srtctl, SRTCTL_SRCR, src); - ctl->dirty.bf.srtctl = 1; - return 0; -} - -static int dai_srt_set_srcl(void *blk, unsigned int src) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srtctl, SRTCTL_SRCL, src); - ctl->dirty.bf.srtctl = 1; - return 0; -} - -static int dai_srt_set_rsr(void *blk, unsigned int rsr) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srtctl, SRTCTL_RSR, rsr); - ctl->dirty.bf.srtctl = 1; - return 0; -} - -static int dai_srt_set_drat(void *blk, unsigned int drat) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srtctl, SRTCTL_DRAT, drat); - ctl->dirty.bf.srtctl = 1; - return 0; -} - -static int dai_srt_set_ec(void *blk, unsigned int ec) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srtctl, SRTCTL_EC, ec ? 1 : 0); - ctl->dirty.bf.srtctl = 1; - return 0; -} - -static int dai_srt_set_et(void *blk, unsigned int et) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srtctl, SRTCTL_ET, et ? 1 : 0); - ctl->dirty.bf.srtctl = 1; - return 0; -} - -static int dai_commit_write(struct hw *hw, unsigned int idx, void *blk) -{ - struct dai_ctrl_blk *ctl = blk; - - if (ctl->dirty.bf.srtctl) { - if (idx < 4) { - /* S/PDIF SRTs */ - hw_write_20kx(hw, SRTSCTL+0x4*idx, ctl->srtctl); - } else { - /* I2S SRT */ - hw_write_20kx(hw, SRTICTL, ctl->srtctl); - } - ctl->dirty.bf.srtctl = 0; - } - - return 0; -} - -static int dai_get_ctrl_blk(void **rblk) -{ - struct dai_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int dai_put_ctrl_blk(void *blk) -{ - kfree((struct dai_ctrl_blk *)blk); - - return 0; -} - -static int dao_set_spos(void *blk, unsigned int spos) -{ - ((struct dao_ctrl_blk *)blk)->spos = spos; - ((struct dao_ctrl_blk *)blk)->dirty.bf.spos = 1; - return 0; -} - -static int dao_commit_write(struct hw *hw, unsigned int idx, void *blk) -{ - struct dao_ctrl_blk *ctl = blk; - - if (ctl->dirty.bf.spos) { - if (idx < 4) { - /* S/PDIF SPOSx */ - hw_write_20kx(hw, SPOS+0x4*idx, ctl->spos); - } - ctl->dirty.bf.spos = 0; - } - - return 0; -} - -static int dao_get_spos(void *blk, unsigned int *spos) -{ - *spos = ((struct dao_ctrl_blk *)blk)->spos; - return 0; -} - -static int dao_get_ctrl_blk(void **rblk) -{ - struct dao_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int dao_put_ctrl_blk(void *blk) -{ - kfree((struct dao_ctrl_blk *)blk); - - return 0; -} - -static int daio_mgr_enb_dai(void *blk, unsigned int idx) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - if (idx < 4) { - /* S/PDIF input */ - set_field(&ctl->spictl, SPICTL_EN << (idx*8), 1); - ctl->dirty.bf.spictl |= (0x1 << idx); - } else { - /* I2S input */ - idx %= 4; - set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 1); - ctl->dirty.bf.i2sictl |= (0x1 << idx); - } - return 0; -} - -static int daio_mgr_dsb_dai(void *blk, unsigned int idx) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - if (idx < 4) { - /* S/PDIF input */ - set_field(&ctl->spictl, SPICTL_EN << (idx*8), 0); - ctl->dirty.bf.spictl |= (0x1 << idx); - } else { - /* I2S input */ - idx %= 4; - set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 0); - ctl->dirty.bf.i2sictl |= (0x1 << idx); - } - return 0; -} - -static int daio_mgr_enb_dao(void *blk, unsigned int idx) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - if (idx < 4) { - /* S/PDIF output */ - set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 1); - ctl->dirty.bf.spoctl |= (0x1 << idx); - } else { - /* I2S output */ - idx %= 4; - set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 1); - ctl->dirty.bf.i2soctl |= (0x1 << idx); - } - return 0; -} - -static int daio_mgr_dsb_dao(void *blk, unsigned int idx) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - if (idx < 4) { - /* S/PDIF output */ - set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 0); - ctl->dirty.bf.spoctl |= (0x1 << idx); - } else { - /* I2S output */ - idx %= 4; - set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 0); - ctl->dirty.bf.i2soctl |= (0x1 << idx); - } - return 0; -} - -static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - if (idx < 4) { - /* S/PDIF output */ - switch ((conf & 0x7)) { - case 0: - set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 3); - break; /* CDIF */ - case 1: - set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 0); - break; - case 2: - set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 1); - break; - case 4: - set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 2); - break; - default: - break; - } - set_field(&ctl->spoctl, SPOCTL_LIV << (idx*8), - (conf >> 4) & 0x1); /* Non-audio */ - set_field(&ctl->spoctl, SPOCTL_RIV << (idx*8), - (conf >> 4) & 0x1); /* Non-audio */ - set_field(&ctl->spoctl, SPOCTL_OS << (idx*8), - ((conf >> 3) & 0x1) ? 2 : 2); /* Raw */ - - ctl->dirty.bf.spoctl |= (0x1 << idx); - } else { - /* I2S output */ - /*idx %= 4; */ - } - return 0; -} - -static int daio_mgr_set_imaparc(void *blk, unsigned int slot) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->daoimap.aim, AIM_ARC, slot); - ctl->dirty.bf.daoimap = 1; - return 0; -} - -static int daio_mgr_set_imapnxt(void *blk, unsigned int next) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->daoimap.aim, AIM_NXT, next); - ctl->dirty.bf.daoimap = 1; - return 0; -} - -static int daio_mgr_set_imapaddr(void *blk, unsigned int addr) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - ctl->daoimap.idx = addr; - ctl->dirty.bf.daoimap = 1; - return 0; -} - -static int daio_mgr_commit_write(struct hw *hw, void *blk) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - int i; - - if (ctl->dirty.bf.i2sictl || ctl->dirty.bf.i2soctl) { - for (i = 0; i < 4; i++) { - if ((ctl->dirty.bf.i2sictl & (0x1 << i))) - ctl->dirty.bf.i2sictl &= ~(0x1 << i); - - if ((ctl->dirty.bf.i2soctl & (0x1 << i))) - ctl->dirty.bf.i2soctl &= ~(0x1 << i); - } - hw_write_20kx(hw, I2SCTL, ctl->i2sctl); - mdelay(1); - } - if (ctl->dirty.bf.spoctl) { - for (i = 0; i < 4; i++) { - if ((ctl->dirty.bf.spoctl & (0x1 << i))) - ctl->dirty.bf.spoctl &= ~(0x1 << i); - } - hw_write_20kx(hw, SPOCTL, ctl->spoctl); - mdelay(1); - } - if (ctl->dirty.bf.spictl) { - for (i = 0; i < 4; i++) { - if ((ctl->dirty.bf.spictl & (0x1 << i))) - ctl->dirty.bf.spictl &= ~(0x1 << i); - } - hw_write_20kx(hw, SPICTL, ctl->spictl); - mdelay(1); - } - if (ctl->dirty.bf.daoimap) { - hw_write_20kx(hw, DAOIMAP+ctl->daoimap.idx*4, - ctl->daoimap.aim); - ctl->dirty.bf.daoimap = 0; - } - - return 0; -} - -static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) -{ - struct daio_mgr_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - blk->i2sctl = hw_read_20kx(hw, I2SCTL); - blk->spoctl = hw_read_20kx(hw, SPOCTL); - blk->spictl = hw_read_20kx(hw, SPICTL); - - *rblk = blk; - - return 0; -} - -static int daio_mgr_put_ctrl_blk(void *blk) -{ - kfree((struct daio_mgr_ctrl_blk *)blk); - - return 0; -} - -/* Timer interrupt */ -static int set_timer_irq(struct hw *hw, int enable) -{ - hw_write_20kx(hw, GIE, enable ? IT_INT : 0); - return 0; -} - -static int set_timer_tick(struct hw *hw, unsigned int ticks) -{ - if (ticks) - ticks |= TIMR_IE | TIMR_IP; - hw_write_20kx(hw, TIMR, ticks); - return 0; -} - -static unsigned int get_wc(struct hw *hw) -{ - return hw_read_20kx(hw, WC); -} - -/* Card hardware initialization block */ -struct dac_conf { - unsigned int msr; /* master sample rate in rsrs */ -}; - -struct adc_conf { - unsigned int msr; /* master sample rate in rsrs */ - unsigned char input; /* the input source of ADC */ - unsigned char mic20db; /* boost mic by 20db if input is microphone */ -}; - -struct daio_conf { - unsigned int msr; /* master sample rate in rsrs */ -}; - -struct trn_conf { - unsigned long vm_pgt_phys; -}; - -static int hw_daio_init(struct hw *hw, const struct daio_conf *info) -{ - u32 i2sorg; - u32 spdorg; - - /* Read I2S CTL. Keep original value. */ - /*i2sorg = hw_read_20kx(hw, I2SCTL);*/ - i2sorg = 0x94040404; /* enable all audio out and I2S-D input */ - /* Program I2S with proper master sample rate and enable - * the correct I2S channel. */ - i2sorg &= 0xfffffffc; - - /* Enable S/PDIF-out-A in fixed 24-bit data - * format and default to 48kHz. */ - /* Disable all before doing any changes. */ - hw_write_20kx(hw, SPOCTL, 0x0); - spdorg = 0x05; - - switch (info->msr) { - case 1: - i2sorg |= 1; - spdorg |= (0x0 << 6); - break; - case 2: - i2sorg |= 2; - spdorg |= (0x1 << 6); - break; - case 4: - i2sorg |= 3; - spdorg |= (0x2 << 6); - break; - default: - i2sorg |= 1; - break; - } - - hw_write_20kx(hw, I2SCTL, i2sorg); - hw_write_20kx(hw, SPOCTL, spdorg); - - /* Enable S/PDIF-in-A in fixed 24-bit data format. */ - /* Disable all before doing any changes. */ - hw_write_20kx(hw, SPICTL, 0x0); - mdelay(1); - spdorg = 0x0a0a0a0a; - hw_write_20kx(hw, SPICTL, spdorg); - mdelay(1); - - return 0; -} - -/* TRANSPORT operations */ -static int hw_trn_init(struct hw *hw, const struct trn_conf *info) -{ - u32 trnctl; - u32 ptp_phys_low, ptp_phys_high; - - /* Set up device page table */ - if ((~0UL) == info->vm_pgt_phys) { - printk(KERN_ERR "Wrong device page table page address!\n"); - return -1; - } - - trnctl = 0x13; /* 32-bit, 4k-size page */ - ptp_phys_low = (u32)info->vm_pgt_phys; - ptp_phys_high = upper_32_bits(info->vm_pgt_phys); - if (sizeof(void *) == 8) /* 64bit address */ - trnctl |= (1 << 2); -#if 0 /* Only 4k h/w pages for simplicitiy */ -#if PAGE_SIZE == 8192 - trnctl |= (1<<5); -#endif -#endif - hw_write_20kx(hw, PTPALX, ptp_phys_low); - hw_write_20kx(hw, PTPAHX, ptp_phys_high); - hw_write_20kx(hw, TRNCTL, trnctl); - hw_write_20kx(hw, TRNIS, 0x200c01); /* really needed? */ - - return 0; -} - -/* Card initialization */ -#define GCTL_EAC 0x00000001 -#define GCTL_EAI 0x00000002 -#define GCTL_BEP 0x00000004 -#define GCTL_BES 0x00000008 -#define GCTL_DSP 0x00000010 -#define GCTL_DBP 0x00000020 -#define GCTL_ABP 0x00000040 -#define GCTL_TBP 0x00000080 -#define GCTL_SBP 0x00000100 -#define GCTL_FBP 0x00000200 -#define GCTL_XA 0x00000400 -#define GCTL_ET 0x00000800 -#define GCTL_PR 0x00001000 -#define GCTL_MRL 0x00002000 -#define GCTL_SDE 0x00004000 -#define GCTL_SDI 0x00008000 -#define GCTL_SM 0x00010000 -#define GCTL_SR 0x00020000 -#define GCTL_SD 0x00040000 -#define GCTL_SE 0x00080000 -#define GCTL_AID 0x00100000 - -static int hw_pll_init(struct hw *hw, unsigned int rsr) -{ - unsigned int pllctl; - int i; - - pllctl = (48000 == rsr) ? 0x1480a001 : 0x1480a731; - for (i = 0; i < 3; i++) { - if (hw_read_20kx(hw, PLLCTL) == pllctl) - break; - - hw_write_20kx(hw, PLLCTL, pllctl); - mdelay(40); - } - if (i >= 3) { - printk(KERN_ALERT "PLL initialization failed!!!\n"); - return -EBUSY; - } - - return 0; -} - -static int hw_auto_init(struct hw *hw) -{ - unsigned int gctl; - int i; - - gctl = hw_read_20kx(hw, GCTL); - set_field(&gctl, GCTL_EAI, 0); - hw_write_20kx(hw, GCTL, gctl); - set_field(&gctl, GCTL_EAI, 1); - hw_write_20kx(hw, GCTL, gctl); - mdelay(10); - for (i = 0; i < 400000; i++) { - gctl = hw_read_20kx(hw, GCTL); - if (get_field(gctl, GCTL_AID)) - break; - } - if (!get_field(gctl, GCTL_AID)) { - printk(KERN_ALERT "Card Auto-init failed!!!\n"); - return -EBUSY; - } - - return 0; -} - -static int i2c_unlock(struct hw *hw) -{ - if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) - return 0; - - hw_write_pci(hw, 0xcc, 0x8c); - hw_write_pci(hw, 0xcc, 0x0e); - if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) - return 0; - - hw_write_pci(hw, 0xcc, 0xee); - hw_write_pci(hw, 0xcc, 0xaa); - if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) - return 0; - - return -1; -} - -static void i2c_lock(struct hw *hw) -{ - if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) - hw_write_pci(hw, 0xcc, 0x00); -} - -static void i2c_write(struct hw *hw, u32 device, u32 addr, u32 data) -{ - unsigned int ret; - - do { - ret = hw_read_pci(hw, 0xEC); - } while (!(ret & 0x800000)); - hw_write_pci(hw, 0xE0, device); - hw_write_pci(hw, 0xE4, (data << 8) | (addr & 0xff)); -} - -/* DAC operations */ - -static int hw_reset_dac(struct hw *hw) -{ - u32 i; - u16 gpioorg; - unsigned int ret; - - if (i2c_unlock(hw)) - return -1; - - do { - ret = hw_read_pci(hw, 0xEC); - } while (!(ret & 0x800000)); - hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ - - /* To be effective, need to reset the DAC twice. */ - for (i = 0; i < 2; i++) { - /* set gpio */ - mdelay(100); - gpioorg = (u16)hw_read_20kx(hw, GPIO); - gpioorg &= 0xfffd; - hw_write_20kx(hw, GPIO, gpioorg); - mdelay(1); - hw_write_20kx(hw, GPIO, gpioorg | 0x2); - } - - i2c_write(hw, 0x00180080, 0x01, 0x80); - i2c_write(hw, 0x00180080, 0x02, 0x10); - - i2c_lock(hw); - - return 0; -} - -static int hw_dac_init(struct hw *hw, const struct dac_conf *info) -{ - u32 data; - u16 gpioorg; - unsigned int ret; - - if (hw->model == CTSB055X) { - /* SB055x, unmute outputs */ - gpioorg = (u16)hw_read_20kx(hw, GPIO); - gpioorg &= 0xffbf; /* set GPIO6 to low */ - gpioorg |= 2; /* set GPIO1 to high */ - hw_write_20kx(hw, GPIO, gpioorg); - return 0; - } - - /* mute outputs */ - gpioorg = (u16)hw_read_20kx(hw, GPIO); - gpioorg &= 0xffbf; - hw_write_20kx(hw, GPIO, gpioorg); - - hw_reset_dac(hw); - - if (i2c_unlock(hw)) - return -1; - - hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ - do { - ret = hw_read_pci(hw, 0xEC); - } while (!(ret & 0x800000)); - - switch (info->msr) { - case 1: - data = 0x24; - break; - case 2: - data = 0x25; - break; - case 4: - data = 0x26; - break; - default: - data = 0x24; - break; - } - - i2c_write(hw, 0x00180080, 0x06, data); - i2c_write(hw, 0x00180080, 0x09, data); - i2c_write(hw, 0x00180080, 0x0c, data); - i2c_write(hw, 0x00180080, 0x0f, data); - - i2c_lock(hw); - - /* unmute outputs */ - gpioorg = (u16)hw_read_20kx(hw, GPIO); - gpioorg = gpioorg | 0x40; - hw_write_20kx(hw, GPIO, gpioorg); - - return 0; -} - -/* ADC operations */ - -static int is_adc_input_selected_SB055x(struct hw *hw, enum ADCSRC type) -{ - return 0; -} - -static int is_adc_input_selected_SBx(struct hw *hw, enum ADCSRC type) -{ - u32 data; - - data = hw_read_20kx(hw, GPIO); - switch (type) { - case ADC_MICIN: - data = ((data & (0x1<<7)) && (data & (0x1<<8))); - break; - case ADC_LINEIN: - data = (!(data & (0x1<<7)) && (data & (0x1<<8))); - break; - case ADC_NONE: /* Digital I/O */ - data = (!(data & (0x1<<8))); - break; - default: - data = 0; - } - return data; -} - -static int is_adc_input_selected_hendrix(struct hw *hw, enum ADCSRC type) -{ - u32 data; - - data = hw_read_20kx(hw, GPIO); - switch (type) { - case ADC_MICIN: - data = (data & (0x1 << 7)) ? 1 : 0; - break; - case ADC_LINEIN: - data = (data & (0x1 << 7)) ? 0 : 1; - break; - default: - data = 0; - } - return data; -} - -static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) -{ - switch (hw->model) { - case CTSB055X: - return is_adc_input_selected_SB055x(hw, type); - case CTSB073X: - return is_adc_input_selected_hendrix(hw, type); - case CTUAA: - return is_adc_input_selected_hendrix(hw, type); - default: - return is_adc_input_selected_SBx(hw, type); - } -} - -static int -adc_input_select_SB055x(struct hw *hw, enum ADCSRC type, unsigned char boost) -{ - u32 data; - - /* - * check and set the following GPIO bits accordingly - * ADC_Gain = GPIO2 - * DRM_off = GPIO3 - * Mic_Pwr_on = GPIO7 - * Digital_IO_Sel = GPIO8 - * Mic_Sw = GPIO9 - * Aux/MicLine_Sw = GPIO12 - */ - data = hw_read_20kx(hw, GPIO); - data &= 0xec73; - switch (type) { - case ADC_MICIN: - data |= (0x1<<7) | (0x1<<8) | (0x1<<9) ; - data |= boost ? (0x1<<2) : 0; - break; - case ADC_LINEIN: - data |= (0x1<<8); - break; - case ADC_AUX: - data |= (0x1<<8) | (0x1<<12); - break; - case ADC_NONE: - data |= (0x1<<12); /* set to digital */ - break; - default: - return -1; - } - - hw_write_20kx(hw, GPIO, data); - - return 0; -} - - -static int -adc_input_select_SBx(struct hw *hw, enum ADCSRC type, unsigned char boost) -{ - u32 data; - u32 i2c_data; - unsigned int ret; - - if (i2c_unlock(hw)) - return -1; - - do { - ret = hw_read_pci(hw, 0xEC); - } while (!(ret & 0x800000)); /* i2c ready poll */ - /* set i2c access mode as Direct Control */ - hw_write_pci(hw, 0xEC, 0x05); - - data = hw_read_20kx(hw, GPIO); - switch (type) { - case ADC_MICIN: - data |= ((0x1 << 7) | (0x1 << 8)); - i2c_data = 0x1; /* Mic-in */ - break; - case ADC_LINEIN: - data &= ~(0x1 << 7); - data |= (0x1 << 8); - i2c_data = 0x2; /* Line-in */ - break; - case ADC_NONE: - data &= ~(0x1 << 8); - i2c_data = 0x0; /* set to Digital */ - break; - default: - i2c_lock(hw); - return -1; - } - hw_write_20kx(hw, GPIO, data); - i2c_write(hw, 0x001a0080, 0x2a, i2c_data); - if (boost) { - i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ - i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ - } else { - i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ - i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ - } - - i2c_lock(hw); - - return 0; -} - -static int -adc_input_select_hendrix(struct hw *hw, enum ADCSRC type, unsigned char boost) -{ - u32 data; - u32 i2c_data; - unsigned int ret; - - if (i2c_unlock(hw)) - return -1; - - do { - ret = hw_read_pci(hw, 0xEC); - } while (!(ret & 0x800000)); /* i2c ready poll */ - /* set i2c access mode as Direct Control */ - hw_write_pci(hw, 0xEC, 0x05); - - data = hw_read_20kx(hw, GPIO); - switch (type) { - case ADC_MICIN: - data |= (0x1 << 7); - i2c_data = 0x1; /* Mic-in */ - break; - case ADC_LINEIN: - data &= ~(0x1 << 7); - i2c_data = 0x2; /* Line-in */ - break; - default: - i2c_lock(hw); - return -1; - } - hw_write_20kx(hw, GPIO, data); - i2c_write(hw, 0x001a0080, 0x2a, i2c_data); - if (boost) { - i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ - i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ - } else { - i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ - i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ - } - - i2c_lock(hw); - - return 0; -} - -static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) -{ - int state = type == ADC_MICIN; - - switch (hw->model) { - case CTSB055X: - return adc_input_select_SB055x(hw, type, state); - case CTSB073X: - return adc_input_select_hendrix(hw, type, state); - case CTUAA: - return adc_input_select_hendrix(hw, type, state); - default: - return adc_input_select_SBx(hw, type, state); - } -} - -static int adc_init_SB055x(struct hw *hw, int input, int mic20db) -{ - return adc_input_select_SB055x(hw, input, mic20db); -} - -static int adc_init_SBx(struct hw *hw, int input, int mic20db) -{ - u16 gpioorg; - u16 input_source; - u32 adcdata; - unsigned int ret; - - input_source = 0x100; /* default to analog */ - switch (input) { - case ADC_MICIN: - adcdata = 0x1; - input_source = 0x180; /* set GPIO7 to select Mic */ - break; - case ADC_LINEIN: - adcdata = 0x2; - break; - case ADC_VIDEO: - adcdata = 0x4; - break; - case ADC_AUX: - adcdata = 0x8; - break; - case ADC_NONE: - adcdata = 0x0; - input_source = 0x0; /* set to Digital */ - break; - default: - adcdata = 0x0; - break; - } - - if (i2c_unlock(hw)) - return -1; - - do { - ret = hw_read_pci(hw, 0xEC); - } while (!(ret & 0x800000)); /* i2c ready poll */ - hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ - - i2c_write(hw, 0x001a0080, 0x0e, 0x08); - i2c_write(hw, 0x001a0080, 0x18, 0x0a); - i2c_write(hw, 0x001a0080, 0x28, 0x86); - i2c_write(hw, 0x001a0080, 0x2a, adcdata); - - if (mic20db) { - i2c_write(hw, 0x001a0080, 0x1c, 0xf7); - i2c_write(hw, 0x001a0080, 0x1e, 0xf7); - } else { - i2c_write(hw, 0x001a0080, 0x1c, 0xcf); - i2c_write(hw, 0x001a0080, 0x1e, 0xcf); - } - - if (!(hw_read_20kx(hw, ID0) & 0x100)) - i2c_write(hw, 0x001a0080, 0x16, 0x26); - - i2c_lock(hw); - - gpioorg = (u16)hw_read_20kx(hw, GPIO); - gpioorg &= 0xfe7f; - gpioorg |= input_source; - hw_write_20kx(hw, GPIO, gpioorg); - - return 0; -} - -static int hw_adc_init(struct hw *hw, const struct adc_conf *info) -{ - if (hw->model == CTSB055X) - return adc_init_SB055x(hw, info->input, info->mic20db); - else - return adc_init_SBx(hw, info->input, info->mic20db); -} - -static struct capabilities hw_capabilities(struct hw *hw) -{ - struct capabilities cap; - - /* SB073x and Vista compatible cards have no digit IO switch */ - cap.digit_io_switch = !(hw->model == CTSB073X || hw->model == CTUAA); - cap.dedicated_mic = 0; - cap.output_switch = 0; - cap.mic_source_switch = 0; - - return cap; -} - -#define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) - -#define UAA_CFG_PWRSTATUS 0x44 -#define UAA_CFG_SPACE_FLAG 0xA0 -#define UAA_CORE_CHANGE 0x3FFC -static int uaa_to_xfi(struct pci_dev *pci) -{ - unsigned int bar0, bar1, bar2, bar3, bar4, bar5; - unsigned int cmd, irq, cl_size, l_timer, pwr; - unsigned int is_uaa; - unsigned int data[4] = {0}; - unsigned int io_base; - void *mem_base; - int i; - const u32 CTLX = CTLBITS('C', 'T', 'L', 'X'); - const u32 CTL_ = CTLBITS('C', 'T', 'L', '-'); - const u32 CTLF = CTLBITS('C', 'T', 'L', 'F'); - const u32 CTLi = CTLBITS('C', 'T', 'L', 'i'); - const u32 CTLA = CTLBITS('C', 'T', 'L', 'A'); - const u32 CTLZ = CTLBITS('C', 'T', 'L', 'Z'); - const u32 CTLL = CTLBITS('C', 'T', 'L', 'L'); - - /* By default, Hendrix card UAA Bar0 should be using memory... */ - io_base = pci_resource_start(pci, 0); - mem_base = ioremap(io_base, pci_resource_len(pci, 0)); - if (!mem_base) - return -ENOENT; - - /* Read current mode from Mode Change Register */ - for (i = 0; i < 4; i++) - data[i] = readl(mem_base + UAA_CORE_CHANGE); - - /* Determine current mode... */ - if (data[0] == CTLA) { - is_uaa = ((data[1] == CTLZ && data[2] == CTLL - && data[3] == CTLA) || (data[1] == CTLA - && data[2] == CTLZ && data[3] == CTLL)); - } else if (data[0] == CTLZ) { - is_uaa = (data[1] == CTLL - && data[2] == CTLA && data[3] == CTLA); - } else if (data[0] == CTLL) { - is_uaa = (data[1] == CTLA - && data[2] == CTLA && data[3] == CTLZ); - } else { - is_uaa = 0; - } - - if (!is_uaa) { - /* Not in UAA mode currently. Return directly. */ - iounmap(mem_base); - return 0; - } - - pci_read_config_dword(pci, PCI_BASE_ADDRESS_0, &bar0); - pci_read_config_dword(pci, PCI_BASE_ADDRESS_1, &bar1); - pci_read_config_dword(pci, PCI_BASE_ADDRESS_2, &bar2); - pci_read_config_dword(pci, PCI_BASE_ADDRESS_3, &bar3); - pci_read_config_dword(pci, PCI_BASE_ADDRESS_4, &bar4); - pci_read_config_dword(pci, PCI_BASE_ADDRESS_5, &bar5); - pci_read_config_dword(pci, PCI_INTERRUPT_LINE, &irq); - pci_read_config_dword(pci, PCI_CACHE_LINE_SIZE, &cl_size); - pci_read_config_dword(pci, PCI_LATENCY_TIMER, &l_timer); - pci_read_config_dword(pci, UAA_CFG_PWRSTATUS, &pwr); - pci_read_config_dword(pci, PCI_COMMAND, &cmd); - - /* Set up X-Fi core PCI configuration space. */ - /* Switch to X-Fi config space with BAR0 exposed. */ - pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x87654321); - /* Copy UAA's BAR5 into X-Fi BAR0 */ - pci_write_config_dword(pci, PCI_BASE_ADDRESS_0, bar5); - /* Switch to X-Fi config space without BAR0 exposed. */ - pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x12345678); - pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, bar1); - pci_write_config_dword(pci, PCI_BASE_ADDRESS_2, bar2); - pci_write_config_dword(pci, PCI_BASE_ADDRESS_3, bar3); - pci_write_config_dword(pci, PCI_BASE_ADDRESS_4, bar4); - pci_write_config_dword(pci, PCI_INTERRUPT_LINE, irq); - pci_write_config_dword(pci, PCI_CACHE_LINE_SIZE, cl_size); - pci_write_config_dword(pci, PCI_LATENCY_TIMER, l_timer); - pci_write_config_dword(pci, UAA_CFG_PWRSTATUS, pwr); - pci_write_config_dword(pci, PCI_COMMAND, cmd); - - /* Switch to X-Fi mode */ - writel(CTLX, (mem_base + UAA_CORE_CHANGE)); - writel(CTL_, (mem_base + UAA_CORE_CHANGE)); - writel(CTLF, (mem_base + UAA_CORE_CHANGE)); - writel(CTLi, (mem_base + UAA_CORE_CHANGE)); - - iounmap(mem_base); - - return 0; -} - -static irqreturn_t ct_20k1_interrupt(int irq, void *dev_id) -{ - struct hw *hw = dev_id; - unsigned int status; - - status = hw_read_20kx(hw, GIP); - if (!status) - return IRQ_NONE; - - if (hw->irq_callback) - hw->irq_callback(hw->irq_callback_data, status); - - hw_write_20kx(hw, GIP, status); - return IRQ_HANDLED; -} - -static int hw_card_start(struct hw *hw) -{ - int err; - struct pci_dev *pci = hw->pci; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - /* Set DMA transfer mask */ - if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || - pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { - printk(KERN_ERR "architecture does not support PCI " - "busmaster DMA with mask 0x%llx\n", - CT_XFI_DMA_MASK); - err = -ENXIO; - goto error1; - } - - if (!hw->io_base) { - err = pci_request_regions(pci, "XFi"); - if (err < 0) - goto error1; - - if (hw->model == CTUAA) - hw->io_base = pci_resource_start(pci, 5); - else - hw->io_base = pci_resource_start(pci, 0); - - } - - /* Switch to X-Fi mode from UAA mode if neeeded */ - if (hw->model == CTUAA) { - err = uaa_to_xfi(pci); - if (err) - goto error2; - - } - - if (hw->irq < 0) { - err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, - KBUILD_MODNAME, hw); - if (err < 0) { - printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); - goto error2; - } - hw->irq = pci->irq; - } - - pci_set_master(pci); - - return 0; - -error2: - pci_release_regions(pci); - hw->io_base = 0; -error1: - pci_disable_device(pci); - return err; -} - -static int hw_card_stop(struct hw *hw) -{ - unsigned int data; - - /* disable transport bus master and queueing of request */ - hw_write_20kx(hw, TRNCTL, 0x00); - - /* disable pll */ - data = hw_read_20kx(hw, PLLCTL); - hw_write_20kx(hw, PLLCTL, (data & (~(0x0F<<12)))); - - /* TODO: Disable interrupt and so on... */ - if (hw->irq >= 0) - synchronize_irq(hw->irq); - return 0; -} - -static int hw_card_shutdown(struct hw *hw) -{ - if (hw->irq >= 0) - free_irq(hw->irq, hw); - - hw->irq = -1; - - if (hw->mem_base) - iounmap((void *)hw->mem_base); - - hw->mem_base = (unsigned long)NULL; - - if (hw->io_base) - pci_release_regions(hw->pci); - - hw->io_base = 0; - - pci_disable_device(hw->pci); - - return 0; -} - -static int hw_card_init(struct hw *hw, struct card_conf *info) -{ - int err; - unsigned int gctl; - u32 data; - struct dac_conf dac_info = {0}; - struct adc_conf adc_info = {0}; - struct daio_conf daio_info = {0}; - struct trn_conf trn_info = {0}; - - /* Get PCI io port base address and do Hendrix switch if needed. */ - err = hw_card_start(hw); - if (err) - return err; - - /* PLL init */ - err = hw_pll_init(hw, info->rsr); - if (err < 0) - return err; - - /* kick off auto-init */ - err = hw_auto_init(hw); - if (err < 0) - return err; - - /* Enable audio ring */ - gctl = hw_read_20kx(hw, GCTL); - set_field(&gctl, GCTL_EAC, 1); - set_field(&gctl, GCTL_DBP, 1); - set_field(&gctl, GCTL_TBP, 1); - set_field(&gctl, GCTL_FBP, 1); - set_field(&gctl, GCTL_ET, 1); - hw_write_20kx(hw, GCTL, gctl); - mdelay(10); - - /* Reset all global pending interrupts */ - hw_write_20kx(hw, GIE, 0); - /* Reset all SRC pending interrupts */ - hw_write_20kx(hw, SRCIP, 0); - mdelay(30); - - /* Detect the card ID and configure GPIO accordingly. */ - switch (hw->model) { - case CTSB055X: - hw_write_20kx(hw, GPIOCTL, 0x13fe); - break; - case CTSB073X: - hw_write_20kx(hw, GPIOCTL, 0x00e6); - break; - case CTUAA: - hw_write_20kx(hw, GPIOCTL, 0x00c2); - break; - default: - hw_write_20kx(hw, GPIOCTL, 0x01e6); - break; - } - - trn_info.vm_pgt_phys = info->vm_pgt_phys; - err = hw_trn_init(hw, &trn_info); - if (err < 0) - return err; - - daio_info.msr = info->msr; - err = hw_daio_init(hw, &daio_info); - if (err < 0) - return err; - - dac_info.msr = info->msr; - err = hw_dac_init(hw, &dac_info); - if (err < 0) - return err; - - adc_info.msr = info->msr; - adc_info.input = ADC_LINEIN; - adc_info.mic20db = 0; - err = hw_adc_init(hw, &adc_info); - if (err < 0) - return err; - - data = hw_read_20kx(hw, SRCMCTL); - data |= 0x1; /* Enables input from the audio ring */ - hw_write_20kx(hw, SRCMCTL, data); - - return 0; -} - -#ifdef CONFIG_PM -static int hw_suspend(struct hw *hw, pm_message_t state) -{ - struct pci_dev *pci = hw->pci; - - hw_card_stop(hw); - - if (hw->model == CTUAA) { - /* Switch to UAA config space. */ - pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0); - } - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - - return 0; -} - -static int hw_resume(struct hw *hw, struct card_conf *info) -{ - struct pci_dev *pci = hw->pci; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - - /* Re-initialize card hardware. */ - return hw_card_init(hw, info); -} -#endif - -static u32 hw_read_20kx(struct hw *hw, u32 reg) -{ - u32 value; - unsigned long flags; - - spin_lock_irqsave( - &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); - outl(reg, hw->io_base + 0x0); - value = inl(hw->io_base + 0x4); - spin_unlock_irqrestore( - &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); - - return value; -} - -static void hw_write_20kx(struct hw *hw, u32 reg, u32 data) -{ - unsigned long flags; - - spin_lock_irqsave( - &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); - outl(reg, hw->io_base + 0x0); - outl(data, hw->io_base + 0x4); - spin_unlock_irqrestore( - &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); - -} - -static u32 hw_read_pci(struct hw *hw, u32 reg) -{ - u32 value; - unsigned long flags; - - spin_lock_irqsave( - &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); - outl(reg, hw->io_base + 0x10); - value = inl(hw->io_base + 0x14); - spin_unlock_irqrestore( - &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); - - return value; -} - -static void hw_write_pci(struct hw *hw, u32 reg, u32 data) -{ - unsigned long flags; - - spin_lock_irqsave( - &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); - outl(reg, hw->io_base + 0x10); - outl(data, hw->io_base + 0x14); - spin_unlock_irqrestore( - &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); -} - -static struct hw ct20k1_preset __devinitdata = { - .irq = -1, - - .card_init = hw_card_init, - .card_stop = hw_card_stop, - .pll_init = hw_pll_init, - .is_adc_source_selected = hw_is_adc_input_selected, - .select_adc_source = hw_adc_input_select, - .capabilities = hw_capabilities, -#ifdef CONFIG_PM - .suspend = hw_suspend, - .resume = hw_resume, -#endif - - .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, - .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, - .src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk, - .src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk, - .src_set_state = src_set_state, - .src_set_bm = src_set_bm, - .src_set_rsr = src_set_rsr, - .src_set_sf = src_set_sf, - .src_set_wr = src_set_wr, - .src_set_pm = src_set_pm, - .src_set_rom = src_set_rom, - .src_set_vo = src_set_vo, - .src_set_st = src_set_st, - .src_set_ie = src_set_ie, - .src_set_ilsz = src_set_ilsz, - .src_set_bp = src_set_bp, - .src_set_cisz = src_set_cisz, - .src_set_ca = src_set_ca, - .src_set_sa = src_set_sa, - .src_set_la = src_set_la, - .src_set_pitch = src_set_pitch, - .src_set_dirty = src_set_dirty, - .src_set_clear_zbufs = src_set_clear_zbufs, - .src_set_dirty_all = src_set_dirty_all, - .src_commit_write = src_commit_write, - .src_get_ca = src_get_ca, - .src_get_dirty = src_get_dirty, - .src_dirty_conj_mask = src_dirty_conj_mask, - .src_mgr_enbs_src = src_mgr_enbs_src, - .src_mgr_enb_src = src_mgr_enb_src, - .src_mgr_dsb_src = src_mgr_dsb_src, - .src_mgr_commit_write = src_mgr_commit_write, - - .srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk, - .srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk, - .srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc, - .srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser, - .srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt, - .srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr, - .srcimp_mgr_commit_write = srcimp_mgr_commit_write, - - .amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk, - .amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk, - .amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk, - .amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk, - .amixer_set_mode = amixer_set_mode, - .amixer_set_iv = amixer_set_iv, - .amixer_set_x = amixer_set_x, - .amixer_set_y = amixer_set_y, - .amixer_set_sadr = amixer_set_sadr, - .amixer_set_se = amixer_set_se, - .amixer_set_dirty = amixer_set_dirty, - .amixer_set_dirty_all = amixer_set_dirty_all, - .amixer_commit_write = amixer_commit_write, - .amixer_get_y = amixer_get_y, - .amixer_get_dirty = amixer_get_dirty, - - .dai_get_ctrl_blk = dai_get_ctrl_blk, - .dai_put_ctrl_blk = dai_put_ctrl_blk, - .dai_srt_set_srco = dai_srt_set_srcr, - .dai_srt_set_srcm = dai_srt_set_srcl, - .dai_srt_set_rsr = dai_srt_set_rsr, - .dai_srt_set_drat = dai_srt_set_drat, - .dai_srt_set_ec = dai_srt_set_ec, - .dai_srt_set_et = dai_srt_set_et, - .dai_commit_write = dai_commit_write, - - .dao_get_ctrl_blk = dao_get_ctrl_blk, - .dao_put_ctrl_blk = dao_put_ctrl_blk, - .dao_set_spos = dao_set_spos, - .dao_commit_write = dao_commit_write, - .dao_get_spos = dao_get_spos, - - .daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk, - .daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk, - .daio_mgr_enb_dai = daio_mgr_enb_dai, - .daio_mgr_dsb_dai = daio_mgr_dsb_dai, - .daio_mgr_enb_dao = daio_mgr_enb_dao, - .daio_mgr_dsb_dao = daio_mgr_dsb_dao, - .daio_mgr_dao_init = daio_mgr_dao_init, - .daio_mgr_set_imaparc = daio_mgr_set_imaparc, - .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt, - .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr, - .daio_mgr_commit_write = daio_mgr_commit_write, - - .set_timer_irq = set_timer_irq, - .set_timer_tick = set_timer_tick, - .get_wc = get_wc, -}; - -int __devinit create_20k1_hw_obj(struct hw **rhw) -{ - struct hw20k1 *hw20k1; - - *rhw = NULL; - hw20k1 = kzalloc(sizeof(*hw20k1), GFP_KERNEL); - if (!hw20k1) - return -ENOMEM; - - spin_lock_init(&hw20k1->reg_20k1_lock); - spin_lock_init(&hw20k1->reg_pci_lock); - - hw20k1->hw = ct20k1_preset; - - *rhw = &hw20k1->hw; - - return 0; -} - -int destroy_20k1_hw_obj(struct hw *hw) -{ - if (hw->io_base) - hw_card_shutdown(hw); - - kfree(container_of(hw, struct hw20k1, hw)); - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.h b/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.h deleted file mode 100644 index 02f72fb4..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k1.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File cthw20k1.h - * - * @Brief - * This file contains the definition of hardware access methord. - * - * @Author Liu Chun - * @Date May 13 2008 - * - */ - -#ifndef CTHW20K1_H -#define CTHW20K1_H - -#include "cthardware.h" - -int create_20k1_hw_obj(struct hw **rhw); -int destroy_20k1_hw_obj(struct hw *hw); - -#endif /* CTHW20K1_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.c b/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.c deleted file mode 100644 index d6c54b52..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.c +++ /dev/null @@ -1,2370 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File cthw20k2.c - * - * @Brief - * This file contains the implementation of hardware access method for 20k2. - * - * @Author Liu Chun - * @Date May 14 2008 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "cthw20k2.h" -#include "ct20k2reg.h" - -#if BITS_PER_LONG == 32 -#define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bit PTE */ -#else -#define CT_XFI_DMA_MASK DMA_BIT_MASK(64) /* 64 bit PTE */ -#endif - -struct hw20k2 { - struct hw hw; - /* for i2c */ - unsigned char dev_id; - unsigned char addr_size; - unsigned char data_size; - - int mic_source; -}; - -static u32 hw_read_20kx(struct hw *hw, u32 reg); -static void hw_write_20kx(struct hw *hw, u32 reg, u32 data); - -/* - * Type definition block. - * The layout of control structures can be directly applied on 20k2 chip. - */ - -/* - * SRC control block definitions. - */ - -/* SRC resource control block */ -#define SRCCTL_STATE 0x00000007 -#define SRCCTL_BM 0x00000008 -#define SRCCTL_RSR 0x00000030 -#define SRCCTL_SF 0x000001C0 -#define SRCCTL_WR 0x00000200 -#define SRCCTL_PM 0x00000400 -#define SRCCTL_ROM 0x00001800 -#define SRCCTL_VO 0x00002000 -#define SRCCTL_ST 0x00004000 -#define SRCCTL_IE 0x00008000 -#define SRCCTL_ILSZ 0x000F0000 -#define SRCCTL_BP 0x00100000 - -#define SRCCCR_CISZ 0x000007FF -#define SRCCCR_CWA 0x001FF800 -#define SRCCCR_D 0x00200000 -#define SRCCCR_RS 0x01C00000 -#define SRCCCR_NAL 0x3E000000 -#define SRCCCR_RA 0xC0000000 - -#define SRCCA_CA 0x0FFFFFFF -#define SRCCA_RS 0xE0000000 - -#define SRCSA_SA 0x0FFFFFFF - -#define SRCLA_LA 0x0FFFFFFF - -/* Mixer Parameter Ring ram Low and Hight register. - * Fixed-point value in 8.24 format for parameter channel */ -#define MPRLH_PITCH 0xFFFFFFFF - -/* SRC resource register dirty flags */ -union src_dirty { - struct { - u16 ctl:1; - u16 ccr:1; - u16 sa:1; - u16 la:1; - u16 ca:1; - u16 mpr:1; - u16 czbfs:1; /* Clear Z-Buffers */ - u16 rsv:9; - } bf; - u16 data; -}; - -struct src_rsc_ctrl_blk { - unsigned int ctl; - unsigned int ccr; - unsigned int ca; - unsigned int sa; - unsigned int la; - unsigned int mpr; - union src_dirty dirty; -}; - -/* SRC manager control block */ -union src_mgr_dirty { - struct { - u16 enb0:1; - u16 enb1:1; - u16 enb2:1; - u16 enb3:1; - u16 enb4:1; - u16 enb5:1; - u16 enb6:1; - u16 enb7:1; - u16 enbsa:1; - u16 rsv:7; - } bf; - u16 data; -}; - -struct src_mgr_ctrl_blk { - unsigned int enbsa; - unsigned int enb[8]; - union src_mgr_dirty dirty; -}; - -/* SRCIMP manager control block */ -#define SRCAIM_ARC 0x00000FFF -#define SRCAIM_NXT 0x00FF0000 -#define SRCAIM_SRC 0xFF000000 - -struct srcimap { - unsigned int srcaim; - unsigned int idx; -}; - -/* SRCIMP manager register dirty flags */ -union srcimp_mgr_dirty { - struct { - u16 srcimap:1; - u16 rsv:15; - } bf; - u16 data; -}; - -struct srcimp_mgr_ctrl_blk { - struct srcimap srcimap; - union srcimp_mgr_dirty dirty; -}; - -/* - * Function implementation block. - */ - -static int src_get_rsc_ctrl_blk(void **rblk) -{ - struct src_rsc_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int src_put_rsc_ctrl_blk(void *blk) -{ - kfree(blk); - - return 0; -} - -static int src_set_state(void *blk, unsigned int state) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_STATE, state); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_bm(void *blk, unsigned int bm) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_BM, bm); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_rsr(void *blk, unsigned int rsr) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_RSR, rsr); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_sf(void *blk, unsigned int sf) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_SF, sf); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_wr(void *blk, unsigned int wr) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_WR, wr); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_pm(void *blk, unsigned int pm) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_PM, pm); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_rom(void *blk, unsigned int rom) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_ROM, rom); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_vo(void *blk, unsigned int vo) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_VO, vo); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_st(void *blk, unsigned int st) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_ST, st); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_ie(void *blk, unsigned int ie) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_IE, ie); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_ilsz(void *blk, unsigned int ilsz) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_ILSZ, ilsz); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_bp(void *blk, unsigned int bp) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ctl, SRCCTL_BP, bp); - ctl->dirty.bf.ctl = 1; - return 0; -} - -static int src_set_cisz(void *blk, unsigned int cisz) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ccr, SRCCCR_CISZ, cisz); - ctl->dirty.bf.ccr = 1; - return 0; -} - -static int src_set_ca(void *blk, unsigned int ca) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->ca, SRCCA_CA, ca); - ctl->dirty.bf.ca = 1; - return 0; -} - -static int src_set_sa(void *blk, unsigned int sa) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->sa, SRCSA_SA, sa); - ctl->dirty.bf.sa = 1; - return 0; -} - -static int src_set_la(void *blk, unsigned int la) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->la, SRCLA_LA, la); - ctl->dirty.bf.la = 1; - return 0; -} - -static int src_set_pitch(void *blk, unsigned int pitch) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->mpr, MPRLH_PITCH, pitch); - ctl->dirty.bf.mpr = 1; - return 0; -} - -static int src_set_clear_zbufs(void *blk, unsigned int clear) -{ - ((struct src_rsc_ctrl_blk *)blk)->dirty.bf.czbfs = (clear ? 1 : 0); - return 0; -} - -static int src_set_dirty(void *blk, unsigned int flags) -{ - ((struct src_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); - return 0; -} - -static int src_set_dirty_all(void *blk) -{ - ((struct src_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); - return 0; -} - -#define AR_SLOT_SIZE 4096 -#define AR_SLOT_BLOCK_SIZE 16 -#define AR_PTS_PITCH 6 -#define AR_PARAM_SRC_OFFSET 0x60 - -static unsigned int src_param_pitch_mixer(unsigned int src_idx) -{ - return ((src_idx << 4) + AR_PTS_PITCH + AR_SLOT_SIZE - - AR_PARAM_SRC_OFFSET) % AR_SLOT_SIZE; - -} - -static int src_commit_write(struct hw *hw, unsigned int idx, void *blk) -{ - struct src_rsc_ctrl_blk *ctl = blk; - int i; - - if (ctl->dirty.bf.czbfs) { - /* Clear Z-Buffer registers */ - for (i = 0; i < 8; i++) - hw_write_20kx(hw, SRC_UPZ+idx*0x100+i*0x4, 0); - - for (i = 0; i < 4; i++) - hw_write_20kx(hw, SRC_DN0Z+idx*0x100+i*0x4, 0); - - for (i = 0; i < 8; i++) - hw_write_20kx(hw, SRC_DN1Z+idx*0x100+i*0x4, 0); - - ctl->dirty.bf.czbfs = 0; - } - if (ctl->dirty.bf.mpr) { - /* Take the parameter mixer resource in the same group as that - * the idx src is in for simplicity. Unlike src, all conjugate - * parameter mixer resources must be programmed for - * corresponding conjugate src resources. */ - unsigned int pm_idx = src_param_pitch_mixer(idx); - hw_write_20kx(hw, MIXER_PRING_LO_HI+4*pm_idx, ctl->mpr); - hw_write_20kx(hw, MIXER_PMOPLO+8*pm_idx, 0x3); - hw_write_20kx(hw, MIXER_PMOPHI+8*pm_idx, 0x0); - ctl->dirty.bf.mpr = 0; - } - if (ctl->dirty.bf.sa) { - hw_write_20kx(hw, SRC_SA+idx*0x100, ctl->sa); - ctl->dirty.bf.sa = 0; - } - if (ctl->dirty.bf.la) { - hw_write_20kx(hw, SRC_LA+idx*0x100, ctl->la); - ctl->dirty.bf.la = 0; - } - if (ctl->dirty.bf.ca) { - hw_write_20kx(hw, SRC_CA+idx*0x100, ctl->ca); - ctl->dirty.bf.ca = 0; - } - - /* Write srccf register */ - hw_write_20kx(hw, SRC_CF+idx*0x100, 0x0); - - if (ctl->dirty.bf.ccr) { - hw_write_20kx(hw, SRC_CCR+idx*0x100, ctl->ccr); - ctl->dirty.bf.ccr = 0; - } - if (ctl->dirty.bf.ctl) { - hw_write_20kx(hw, SRC_CTL+idx*0x100, ctl->ctl); - ctl->dirty.bf.ctl = 0; - } - - return 0; -} - -static int src_get_ca(struct hw *hw, unsigned int idx, void *blk) -{ - struct src_rsc_ctrl_blk *ctl = blk; - - ctl->ca = hw_read_20kx(hw, SRC_CA+idx*0x100); - ctl->dirty.bf.ca = 0; - - return get_field(ctl->ca, SRCCA_CA); -} - -static unsigned int src_get_dirty(void *blk) -{ - return ((struct src_rsc_ctrl_blk *)blk)->dirty.data; -} - -static unsigned int src_dirty_conj_mask(void) -{ - return 0x20; -} - -static int src_mgr_enbs_src(void *blk, unsigned int idx) -{ - ((struct src_mgr_ctrl_blk *)blk)->enbsa |= (0x1 << ((idx%128)/4)); - ((struct src_mgr_ctrl_blk *)blk)->dirty.bf.enbsa = 1; - ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); - return 0; -} - -static int src_mgr_enb_src(void *blk, unsigned int idx) -{ - ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); - ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); - return 0; -} - -static int src_mgr_dsb_src(void *blk, unsigned int idx) -{ - ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] &= ~(0x1 << (idx%32)); - ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); - return 0; -} - -static int src_mgr_commit_write(struct hw *hw, void *blk) -{ - struct src_mgr_ctrl_blk *ctl = blk; - int i; - unsigned int ret; - - if (ctl->dirty.bf.enbsa) { - do { - ret = hw_read_20kx(hw, SRC_ENBSTAT); - } while (ret & 0x1); - hw_write_20kx(hw, SRC_ENBSA, ctl->enbsa); - ctl->dirty.bf.enbsa = 0; - } - for (i = 0; i < 8; i++) { - if ((ctl->dirty.data & (0x1 << i))) { - hw_write_20kx(hw, SRC_ENB+(i*0x100), ctl->enb[i]); - ctl->dirty.data &= ~(0x1 << i); - } - } - - return 0; -} - -static int src_mgr_get_ctrl_blk(void **rblk) -{ - struct src_mgr_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int src_mgr_put_ctrl_blk(void *blk) -{ - kfree(blk); - - return 0; -} - -static int srcimp_mgr_get_ctrl_blk(void **rblk) -{ - struct srcimp_mgr_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int srcimp_mgr_put_ctrl_blk(void *blk) -{ - kfree(blk); - - return 0; -} - -static int srcimp_mgr_set_imaparc(void *blk, unsigned int slot) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->srcimap.srcaim, SRCAIM_ARC, slot); - ctl->dirty.bf.srcimap = 1; - return 0; -} - -static int srcimp_mgr_set_imapuser(void *blk, unsigned int user) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->srcimap.srcaim, SRCAIM_SRC, user); - ctl->dirty.bf.srcimap = 1; - return 0; -} - -static int srcimp_mgr_set_imapnxt(void *blk, unsigned int next) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->srcimap.srcaim, SRCAIM_NXT, next); - ctl->dirty.bf.srcimap = 1; - return 0; -} - -static int srcimp_mgr_set_imapaddr(void *blk, unsigned int addr) -{ - ((struct srcimp_mgr_ctrl_blk *)blk)->srcimap.idx = addr; - ((struct srcimp_mgr_ctrl_blk *)blk)->dirty.bf.srcimap = 1; - return 0; -} - -static int srcimp_mgr_commit_write(struct hw *hw, void *blk) -{ - struct srcimp_mgr_ctrl_blk *ctl = blk; - - if (ctl->dirty.bf.srcimap) { - hw_write_20kx(hw, SRC_IMAP+ctl->srcimap.idx*0x100, - ctl->srcimap.srcaim); - ctl->dirty.bf.srcimap = 0; - } - - return 0; -} - -/* - * AMIXER control block definitions. - */ - -#define AMOPLO_M 0x00000003 -#define AMOPLO_IV 0x00000004 -#define AMOPLO_X 0x0003FFF0 -#define AMOPLO_Y 0xFFFC0000 - -#define AMOPHI_SADR 0x000000FF -#define AMOPHI_SE 0x80000000 - -/* AMIXER resource register dirty flags */ -union amixer_dirty { - struct { - u16 amoplo:1; - u16 amophi:1; - u16 rsv:14; - } bf; - u16 data; -}; - -/* AMIXER resource control block */ -struct amixer_rsc_ctrl_blk { - unsigned int amoplo; - unsigned int amophi; - union amixer_dirty dirty; -}; - -static int amixer_set_mode(void *blk, unsigned int mode) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amoplo, AMOPLO_M, mode); - ctl->dirty.bf.amoplo = 1; - return 0; -} - -static int amixer_set_iv(void *blk, unsigned int iv) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amoplo, AMOPLO_IV, iv); - ctl->dirty.bf.amoplo = 1; - return 0; -} - -static int amixer_set_x(void *blk, unsigned int x) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amoplo, AMOPLO_X, x); - ctl->dirty.bf.amoplo = 1; - return 0; -} - -static int amixer_set_y(void *blk, unsigned int y) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amoplo, AMOPLO_Y, y); - ctl->dirty.bf.amoplo = 1; - return 0; -} - -static int amixer_set_sadr(void *blk, unsigned int sadr) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amophi, AMOPHI_SADR, sadr); - ctl->dirty.bf.amophi = 1; - return 0; -} - -static int amixer_set_se(void *blk, unsigned int se) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - set_field(&ctl->amophi, AMOPHI_SE, se); - ctl->dirty.bf.amophi = 1; - return 0; -} - -static int amixer_set_dirty(void *blk, unsigned int flags) -{ - ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); - return 0; -} - -static int amixer_set_dirty_all(void *blk) -{ - ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); - return 0; -} - -static int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) { - hw_write_20kx(hw, MIXER_AMOPLO+idx*8, ctl->amoplo); - ctl->dirty.bf.amoplo = 0; - hw_write_20kx(hw, MIXER_AMOPHI+idx*8, ctl->amophi); - ctl->dirty.bf.amophi = 0; - } - - return 0; -} - -static int amixer_get_y(void *blk) -{ - struct amixer_rsc_ctrl_blk *ctl = blk; - - return get_field(ctl->amoplo, AMOPLO_Y); -} - -static unsigned int amixer_get_dirty(void *blk) -{ - return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data; -} - -static int amixer_rsc_get_ctrl_blk(void **rblk) -{ - struct amixer_rsc_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int amixer_rsc_put_ctrl_blk(void *blk) -{ - kfree(blk); - - return 0; -} - -static int amixer_mgr_get_ctrl_blk(void **rblk) -{ - *rblk = NULL; - - return 0; -} - -static int amixer_mgr_put_ctrl_blk(void *blk) -{ - return 0; -} - -/* - * DAIO control block definitions. - */ - -/* Receiver Sample Rate Tracker Control register */ -#define SRTCTL_SRCO 0x000000FF -#define SRTCTL_SRCM 0x0000FF00 -#define SRTCTL_RSR 0x00030000 -#define SRTCTL_DRAT 0x00300000 -#define SRTCTL_EC 0x01000000 -#define SRTCTL_ET 0x10000000 - -/* DAIO Receiver register dirty flags */ -union dai_dirty { - struct { - u16 srt:1; - u16 rsv:15; - } bf; - u16 data; -}; - -/* DAIO Receiver control block */ -struct dai_ctrl_blk { - unsigned int srt; - union dai_dirty dirty; -}; - -/* Audio Input Mapper RAM */ -#define AIM_ARC 0x00000FFF -#define AIM_NXT 0x007F0000 - -struct daoimap { - unsigned int aim; - unsigned int idx; -}; - -/* Audio Transmitter Control and Status register */ -#define ATXCTL_EN 0x00000001 -#define ATXCTL_MODE 0x00000010 -#define ATXCTL_CD 0x00000020 -#define ATXCTL_RAW 0x00000100 -#define ATXCTL_MT 0x00000200 -#define ATXCTL_NUC 0x00003000 -#define ATXCTL_BEN 0x00010000 -#define ATXCTL_BMUX 0x00700000 -#define ATXCTL_B24 0x01000000 -#define ATXCTL_CPF 0x02000000 -#define ATXCTL_RIV 0x10000000 -#define ATXCTL_LIV 0x20000000 -#define ATXCTL_RSAT 0x40000000 -#define ATXCTL_LSAT 0x80000000 - -/* XDIF Transmitter register dirty flags */ -union dao_dirty { - struct { - u16 atxcsl:1; - u16 rsv:15; - } bf; - u16 data; -}; - -/* XDIF Transmitter control block */ -struct dao_ctrl_blk { - /* XDIF Transmitter Channel Status Low Register */ - unsigned int atxcsl; - union dao_dirty dirty; -}; - -/* Audio Receiver Control register */ -#define ARXCTL_EN 0x00000001 - -/* DAIO manager register dirty flags */ -union daio_mgr_dirty { - struct { - u32 atxctl:8; - u32 arxctl:8; - u32 daoimap:1; - u32 rsv:15; - } bf; - u32 data; -}; - -/* DAIO manager control block */ -struct daio_mgr_ctrl_blk { - struct daoimap daoimap; - unsigned int txctl[8]; - unsigned int rxctl[8]; - union daio_mgr_dirty dirty; -}; - -static int dai_srt_set_srco(void *blk, unsigned int src) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srt, SRTCTL_SRCO, src); - ctl->dirty.bf.srt = 1; - return 0; -} - -static int dai_srt_set_srcm(void *blk, unsigned int src) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srt, SRTCTL_SRCM, src); - ctl->dirty.bf.srt = 1; - return 0; -} - -static int dai_srt_set_rsr(void *blk, unsigned int rsr) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srt, SRTCTL_RSR, rsr); - ctl->dirty.bf.srt = 1; - return 0; -} - -static int dai_srt_set_drat(void *blk, unsigned int drat) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srt, SRTCTL_DRAT, drat); - ctl->dirty.bf.srt = 1; - return 0; -} - -static int dai_srt_set_ec(void *blk, unsigned int ec) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srt, SRTCTL_EC, ec ? 1 : 0); - ctl->dirty.bf.srt = 1; - return 0; -} - -static int dai_srt_set_et(void *blk, unsigned int et) -{ - struct dai_ctrl_blk *ctl = blk; - - set_field(&ctl->srt, SRTCTL_ET, et ? 1 : 0); - ctl->dirty.bf.srt = 1; - return 0; -} - -static int dai_commit_write(struct hw *hw, unsigned int idx, void *blk) -{ - struct dai_ctrl_blk *ctl = blk; - - if (ctl->dirty.bf.srt) { - hw_write_20kx(hw, AUDIO_IO_RX_SRT_CTL+0x40*idx, ctl->srt); - ctl->dirty.bf.srt = 0; - } - - return 0; -} - -static int dai_get_ctrl_blk(void **rblk) -{ - struct dai_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int dai_put_ctrl_blk(void *blk) -{ - kfree(blk); - - return 0; -} - -static int dao_set_spos(void *blk, unsigned int spos) -{ - ((struct dao_ctrl_blk *)blk)->atxcsl = spos; - ((struct dao_ctrl_blk *)blk)->dirty.bf.atxcsl = 1; - return 0; -} - -static int dao_commit_write(struct hw *hw, unsigned int idx, void *blk) -{ - struct dao_ctrl_blk *ctl = blk; - - if (ctl->dirty.bf.atxcsl) { - if (idx < 4) { - /* S/PDIF SPOSx */ - hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_L+0x40*idx, - ctl->atxcsl); - } - ctl->dirty.bf.atxcsl = 0; - } - - return 0; -} - -static int dao_get_spos(void *blk, unsigned int *spos) -{ - *spos = ((struct dao_ctrl_blk *)blk)->atxcsl; - return 0; -} - -static int dao_get_ctrl_blk(void **rblk) -{ - struct dao_ctrl_blk *blk; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - *rblk = blk; - - return 0; -} - -static int dao_put_ctrl_blk(void *blk) -{ - kfree(blk); - - return 0; -} - -static int daio_mgr_enb_dai(void *blk, unsigned int idx) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->rxctl[idx], ARXCTL_EN, 1); - ctl->dirty.bf.arxctl |= (0x1 << idx); - return 0; -} - -static int daio_mgr_dsb_dai(void *blk, unsigned int idx) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->rxctl[idx], ARXCTL_EN, 0); - - ctl->dirty.bf.arxctl |= (0x1 << idx); - return 0; -} - -static int daio_mgr_enb_dao(void *blk, unsigned int idx) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->txctl[idx], ATXCTL_EN, 1); - ctl->dirty.bf.atxctl |= (0x1 << idx); - return 0; -} - -static int daio_mgr_dsb_dao(void *blk, unsigned int idx) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->txctl[idx], ATXCTL_EN, 0); - ctl->dirty.bf.atxctl |= (0x1 << idx); - return 0; -} - -static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - if (idx < 4) { - /* S/PDIF output */ - switch ((conf & 0x7)) { - case 1: - set_field(&ctl->txctl[idx], ATXCTL_NUC, 0); - break; - case 2: - set_field(&ctl->txctl[idx], ATXCTL_NUC, 1); - break; - case 4: - set_field(&ctl->txctl[idx], ATXCTL_NUC, 2); - break; - case 8: - set_field(&ctl->txctl[idx], ATXCTL_NUC, 3); - break; - default: - break; - } - /* CDIF */ - set_field(&ctl->txctl[idx], ATXCTL_CD, (!(conf & 0x7))); - /* Non-audio */ - set_field(&ctl->txctl[idx], ATXCTL_LIV, (conf >> 4) & 0x1); - /* Non-audio */ - set_field(&ctl->txctl[idx], ATXCTL_RIV, (conf >> 4) & 0x1); - set_field(&ctl->txctl[idx], ATXCTL_RAW, - ((conf >> 3) & 0x1) ? 0 : 0); - ctl->dirty.bf.atxctl |= (0x1 << idx); - } else { - /* I2S output */ - /*idx %= 4; */ - } - return 0; -} - -static int daio_mgr_set_imaparc(void *blk, unsigned int slot) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->daoimap.aim, AIM_ARC, slot); - ctl->dirty.bf.daoimap = 1; - return 0; -} - -static int daio_mgr_set_imapnxt(void *blk, unsigned int next) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - - set_field(&ctl->daoimap.aim, AIM_NXT, next); - ctl->dirty.bf.daoimap = 1; - return 0; -} - -static int daio_mgr_set_imapaddr(void *blk, unsigned int addr) -{ - ((struct daio_mgr_ctrl_blk *)blk)->daoimap.idx = addr; - ((struct daio_mgr_ctrl_blk *)blk)->dirty.bf.daoimap = 1; - return 0; -} - -static int daio_mgr_commit_write(struct hw *hw, void *blk) -{ - struct daio_mgr_ctrl_blk *ctl = blk; - unsigned int data; - int i; - - for (i = 0; i < 8; i++) { - if ((ctl->dirty.bf.atxctl & (0x1 << i))) { - data = ctl->txctl[i]; - hw_write_20kx(hw, (AUDIO_IO_TX_CTL+(0x40*i)), data); - ctl->dirty.bf.atxctl &= ~(0x1 << i); - mdelay(1); - } - if ((ctl->dirty.bf.arxctl & (0x1 << i))) { - data = ctl->rxctl[i]; - hw_write_20kx(hw, (AUDIO_IO_RX_CTL+(0x40*i)), data); - ctl->dirty.bf.arxctl &= ~(0x1 << i); - mdelay(1); - } - } - if (ctl->dirty.bf.daoimap) { - hw_write_20kx(hw, AUDIO_IO_AIM+ctl->daoimap.idx*4, - ctl->daoimap.aim); - ctl->dirty.bf.daoimap = 0; - } - - return 0; -} - -static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) -{ - struct daio_mgr_ctrl_blk *blk; - int i; - - *rblk = NULL; - blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) - return -ENOMEM; - - for (i = 0; i < 8; i++) { - blk->txctl[i] = hw_read_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i)); - blk->rxctl[i] = hw_read_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i)); - } - - *rblk = blk; - - return 0; -} - -static int daio_mgr_put_ctrl_blk(void *blk) -{ - kfree(blk); - - return 0; -} - -/* Timer interrupt */ -static int set_timer_irq(struct hw *hw, int enable) -{ - hw_write_20kx(hw, GIE, enable ? IT_INT : 0); - return 0; -} - -static int set_timer_tick(struct hw *hw, unsigned int ticks) -{ - if (ticks) - ticks |= TIMR_IE | TIMR_IP; - hw_write_20kx(hw, TIMR, ticks); - return 0; -} - -static unsigned int get_wc(struct hw *hw) -{ - return hw_read_20kx(hw, WC); -} - -/* Card hardware initialization block */ -struct dac_conf { - unsigned int msr; /* master sample rate in rsrs */ -}; - -struct adc_conf { - unsigned int msr; /* master sample rate in rsrs */ - unsigned char input; /* the input source of ADC */ - unsigned char mic20db; /* boost mic by 20db if input is microphone */ -}; - -struct daio_conf { - unsigned int msr; /* master sample rate in rsrs */ -}; - -struct trn_conf { - unsigned long vm_pgt_phys; -}; - -static int hw_daio_init(struct hw *hw, const struct daio_conf *info) -{ - u32 data; - int i; - - /* Program I2S with proper sample rate and enable the correct I2S - * channel. ED(0/8/16/24): Enable all I2S/I2X master clock output */ - if (1 == info->msr) { - hw_write_20kx(hw, AUDIO_IO_MCLK, 0x01010101); - hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); - hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); - } else if (2 == info->msr) { - if (hw->model != CTSB1270) { - hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); - } else { - /* PCM4220 on Titanium HD is different. */ - hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11011111); - } - /* Specify all playing 96khz - * EA [0] - Enabled - * RTA [4:5] - 96kHz - * EB [8] - Enabled - * RTB [12:13] - 96kHz - * EC [16] - Enabled - * RTC [20:21] - 96kHz - * ED [24] - Enabled - * RTD [28:29] - 96kHz */ - hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); - hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); - } else if ((4 == info->msr) && (hw->model == CTSB1270)) { - hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111); - hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); - hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); - } else { - printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); - return -EINVAL; - } - - for (i = 0; i < 8; i++) { - if (i <= 3) { - /* This comment looks wrong since loop is over 4 */ - /* channels and emu20k2 supports 4 spdif IOs. */ - /* 1st 3 channels are SPDIFs (SB0960) */ - if (i == 3) - data = 0x1001001; - else - data = 0x1000001; - - hw_write_20kx(hw, (AUDIO_IO_TX_CTL+(0x40*i)), data); - hw_write_20kx(hw, (AUDIO_IO_RX_CTL+(0x40*i)), data); - - /* Initialize the SPDIF Out Channel status registers. - * The value specified here is based on the typical - * values provided in the specification, namely: Clock - * Accuracy of 1000ppm, Sample Rate of 48KHz, - * unspecified source number, Generation status = 1, - * Category code = 0x12 (Digital Signal Mixer), - * Mode = 0, Emph = 0, Copy Permitted, AN = 0 - * (indicating that we're transmitting digital audio, - * and the Professional Use bit is 0. */ - - hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_L+(0x40*i), - 0x02109204); /* Default to 48kHz */ - - hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); - } else { - /* Again, loop is over 4 channels not 5. */ - /* Next 5 channels are I2S (SB0960) */ - data = 0x11; - hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); - if (2 == info->msr) { - /* Four channels per sample period */ - data |= 0x1000; - } else if (4 == info->msr) { - /* FIXME: check this against the chip spec */ - data |= 0x2000; - } - hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); - } - } - - return 0; -} - -/* TRANSPORT operations */ -static int hw_trn_init(struct hw *hw, const struct trn_conf *info) -{ - u32 vmctl, data; - u32 ptp_phys_low, ptp_phys_high; - int i; - - /* Set up device page table */ - if ((~0UL) == info->vm_pgt_phys) { - printk(KERN_ALERT "ctxfi: " - "Wrong device page table page address!!!\n"); - return -1; - } - - vmctl = 0x80000C0F; /* 32-bit, 4k-size page */ - ptp_phys_low = (u32)info->vm_pgt_phys; - ptp_phys_high = upper_32_bits(info->vm_pgt_phys); - if (sizeof(void *) == 8) /* 64bit address */ - vmctl |= (3 << 8); - /* Write page table physical address to all PTPAL registers */ - for (i = 0; i < 64; i++) { - hw_write_20kx(hw, VMEM_PTPAL+(16*i), ptp_phys_low); - hw_write_20kx(hw, VMEM_PTPAH+(16*i), ptp_phys_high); - } - /* Enable virtual memory transfer */ - hw_write_20kx(hw, VMEM_CTL, vmctl); - /* Enable transport bus master and queueing of request */ - hw_write_20kx(hw, TRANSPORT_CTL, 0x03); - hw_write_20kx(hw, TRANSPORT_INT, 0x200c01); - /* Enable transport ring */ - data = hw_read_20kx(hw, TRANSPORT_ENB); - hw_write_20kx(hw, TRANSPORT_ENB, (data | 0x03)); - - return 0; -} - -/* Card initialization */ -#define GCTL_AIE 0x00000001 -#define GCTL_UAA 0x00000002 -#define GCTL_DPC 0x00000004 -#define GCTL_DBP 0x00000008 -#define GCTL_ABP 0x00000010 -#define GCTL_TBP 0x00000020 -#define GCTL_SBP 0x00000040 -#define GCTL_FBP 0x00000080 -#define GCTL_ME 0x00000100 -#define GCTL_AID 0x00001000 - -#define PLLCTL_SRC 0x00000007 -#define PLLCTL_SPE 0x00000008 -#define PLLCTL_RD 0x000000F0 -#define PLLCTL_FD 0x0001FF00 -#define PLLCTL_OD 0x00060000 -#define PLLCTL_B 0x00080000 -#define PLLCTL_AS 0x00100000 -#define PLLCTL_LF 0x03E00000 -#define PLLCTL_SPS 0x1C000000 -#define PLLCTL_AD 0x60000000 - -#define PLLSTAT_CCS 0x00000007 -#define PLLSTAT_SPL 0x00000008 -#define PLLSTAT_CRD 0x000000F0 -#define PLLSTAT_CFD 0x0001FF00 -#define PLLSTAT_SL 0x00020000 -#define PLLSTAT_FAS 0x00040000 -#define PLLSTAT_B 0x00080000 -#define PLLSTAT_PD 0x00100000 -#define PLLSTAT_OCA 0x00200000 -#define PLLSTAT_NCA 0x00400000 - -static int hw_pll_init(struct hw *hw, unsigned int rsr) -{ - unsigned int pllenb; - unsigned int pllctl; - unsigned int pllstat; - int i; - - pllenb = 0xB; - hw_write_20kx(hw, PLL_ENB, pllenb); - pllctl = 0x20C00000; - set_field(&pllctl, PLLCTL_B, 0); - set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 4 : 147 - 4); - set_field(&pllctl, PLLCTL_RD, 48000 == rsr ? 1 - 1 : 10 - 1); - hw_write_20kx(hw, PLL_CTL, pllctl); - mdelay(40); - - pllctl = hw_read_20kx(hw, PLL_CTL); - set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 2 : 147 - 2); - hw_write_20kx(hw, PLL_CTL, pllctl); - mdelay(40); - - for (i = 0; i < 1000; i++) { - pllstat = hw_read_20kx(hw, PLL_STAT); - if (get_field(pllstat, PLLSTAT_PD)) - continue; - - if (get_field(pllstat, PLLSTAT_B) != - get_field(pllctl, PLLCTL_B)) - continue; - - if (get_field(pllstat, PLLSTAT_CCS) != - get_field(pllctl, PLLCTL_SRC)) - continue; - - if (get_field(pllstat, PLLSTAT_CRD) != - get_field(pllctl, PLLCTL_RD)) - continue; - - if (get_field(pllstat, PLLSTAT_CFD) != - get_field(pllctl, PLLCTL_FD)) - continue; - - break; - } - if (i >= 1000) { - printk(KERN_ALERT "ctxfi: PLL initialization failed!!!\n"); - return -EBUSY; - } - - return 0; -} - -static int hw_auto_init(struct hw *hw) -{ - unsigned int gctl; - int i; - - gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL); - set_field(&gctl, GCTL_AIE, 0); - hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); - set_field(&gctl, GCTL_AIE, 1); - hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); - mdelay(10); - for (i = 0; i < 400000; i++) { - gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL); - if (get_field(gctl, GCTL_AID)) - break; - } - if (!get_field(gctl, GCTL_AID)) { - printk(KERN_ALERT "ctxfi: Card Auto-init failed!!!\n"); - return -EBUSY; - } - - return 0; -} - -/* DAC operations */ - -#define CS4382_MC1 0x1 -#define CS4382_MC2 0x2 -#define CS4382_MC3 0x3 -#define CS4382_FC 0x4 -#define CS4382_IC 0x5 -#define CS4382_XC1 0x6 -#define CS4382_VCA1 0x7 -#define CS4382_VCB1 0x8 -#define CS4382_XC2 0x9 -#define CS4382_VCA2 0xA -#define CS4382_VCB2 0xB -#define CS4382_XC3 0xC -#define CS4382_VCA3 0xD -#define CS4382_VCB3 0xE -#define CS4382_XC4 0xF -#define CS4382_VCA4 0x10 -#define CS4382_VCB4 0x11 -#define CS4382_CREV 0x12 - -/* I2C status */ -#define STATE_LOCKED 0x00 -#define STATE_UNLOCKED 0xAA -#define DATA_READY 0x800000 /* Used with I2C_IF_STATUS */ -#define DATA_ABORT 0x10000 /* Used with I2C_IF_STATUS */ - -#define I2C_STATUS_DCM 0x00000001 -#define I2C_STATUS_BC 0x00000006 -#define I2C_STATUS_APD 0x00000008 -#define I2C_STATUS_AB 0x00010000 -#define I2C_STATUS_DR 0x00800000 - -#define I2C_ADDRESS_PTAD 0x0000FFFF -#define I2C_ADDRESS_SLAD 0x007F0000 - -struct regs_cs4382 { - u32 mode_control_1; - u32 mode_control_2; - u32 mode_control_3; - - u32 filter_control; - u32 invert_control; - - u32 mix_control_P1; - u32 vol_control_A1; - u32 vol_control_B1; - - u32 mix_control_P2; - u32 vol_control_A2; - u32 vol_control_B2; - - u32 mix_control_P3; - u32 vol_control_A3; - u32 vol_control_B3; - - u32 mix_control_P4; - u32 vol_control_A4; - u32 vol_control_B4; -}; - -static int hw20k2_i2c_unlock_full_access(struct hw *hw) -{ - u8 UnlockKeySequence_FLASH_FULLACCESS_MODE[2] = {0xB3, 0xD4}; - - /* Send keys for forced BIOS mode */ - hw_write_20kx(hw, I2C_IF_WLOCK, - UnlockKeySequence_FLASH_FULLACCESS_MODE[0]); - hw_write_20kx(hw, I2C_IF_WLOCK, - UnlockKeySequence_FLASH_FULLACCESS_MODE[1]); - /* Check whether the chip is unlocked */ - if (hw_read_20kx(hw, I2C_IF_WLOCK) == STATE_UNLOCKED) - return 0; - - return -1; -} - -static int hw20k2_i2c_lock_chip(struct hw *hw) -{ - /* Write twice */ - hw_write_20kx(hw, I2C_IF_WLOCK, STATE_LOCKED); - hw_write_20kx(hw, I2C_IF_WLOCK, STATE_LOCKED); - if (hw_read_20kx(hw, I2C_IF_WLOCK) == STATE_LOCKED) - return 0; - - return -1; -} - -static int hw20k2_i2c_init(struct hw *hw, u8 dev_id, u8 addr_size, u8 data_size) -{ - struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; - int err; - unsigned int i2c_status; - unsigned int i2c_addr; - - err = hw20k2_i2c_unlock_full_access(hw); - if (err < 0) - return err; - - hw20k2->addr_size = addr_size; - hw20k2->data_size = data_size; - hw20k2->dev_id = dev_id; - - i2c_addr = 0; - set_field(&i2c_addr, I2C_ADDRESS_SLAD, dev_id); - - hw_write_20kx(hw, I2C_IF_ADDRESS, i2c_addr); - - i2c_status = hw_read_20kx(hw, I2C_IF_STATUS); - - set_field(&i2c_status, I2C_STATUS_DCM, 1); /* Direct control mode */ - - hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); - - return 0; -} - -static int hw20k2_i2c_uninit(struct hw *hw) -{ - unsigned int i2c_status; - unsigned int i2c_addr; - - i2c_addr = 0; - set_field(&i2c_addr, I2C_ADDRESS_SLAD, 0x57); /* I2C id */ - - hw_write_20kx(hw, I2C_IF_ADDRESS, i2c_addr); - - i2c_status = hw_read_20kx(hw, I2C_IF_STATUS); - - set_field(&i2c_status, I2C_STATUS_DCM, 0); /* I2C mode */ - - hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); - - return hw20k2_i2c_lock_chip(hw); -} - -static int hw20k2_i2c_wait_data_ready(struct hw *hw) -{ - int i = 0x400000; - unsigned int ret; - - do { - ret = hw_read_20kx(hw, I2C_IF_STATUS); - } while ((!(ret & DATA_READY)) && --i); - - return i; -} - -static int hw20k2_i2c_read(struct hw *hw, u16 addr, u32 *datap) -{ - struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; - unsigned int i2c_status; - - i2c_status = hw_read_20kx(hw, I2C_IF_STATUS); - set_field(&i2c_status, I2C_STATUS_BC, - (4 == hw20k2->addr_size) ? 0 : hw20k2->addr_size); - hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); - if (!hw20k2_i2c_wait_data_ready(hw)) - return -1; - - hw_write_20kx(hw, I2C_IF_WDATA, addr); - if (!hw20k2_i2c_wait_data_ready(hw)) - return -1; - - /* Force a read operation */ - hw_write_20kx(hw, I2C_IF_RDATA, 0); - if (!hw20k2_i2c_wait_data_ready(hw)) - return -1; - - *datap = hw_read_20kx(hw, I2C_IF_RDATA); - - return 0; -} - -static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) -{ - struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; - unsigned int i2c_data = (data << (hw20k2->addr_size * 8)) | addr; - unsigned int i2c_status; - - i2c_status = hw_read_20kx(hw, I2C_IF_STATUS); - - set_field(&i2c_status, I2C_STATUS_BC, - (4 == (hw20k2->addr_size + hw20k2->data_size)) ? - 0 : (hw20k2->addr_size + hw20k2->data_size)); - - hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); - hw20k2_i2c_wait_data_ready(hw); - /* Dummy write to trigger the write operation */ - hw_write_20kx(hw, I2C_IF_WDATA, 0); - hw20k2_i2c_wait_data_ready(hw); - - /* This is the real data */ - hw_write_20kx(hw, I2C_IF_WDATA, i2c_data); - hw20k2_i2c_wait_data_ready(hw); - - return 0; -} - -static void hw_dac_stop(struct hw *hw) -{ - u32 data; - data = hw_read_20kx(hw, GPIO_DATA); - data &= 0xFFFFFFFD; - hw_write_20kx(hw, GPIO_DATA, data); - mdelay(10); -} - -static void hw_dac_start(struct hw *hw) -{ - u32 data; - data = hw_read_20kx(hw, GPIO_DATA); - data |= 0x2; - hw_write_20kx(hw, GPIO_DATA, data); - mdelay(50); -} - -static void hw_dac_reset(struct hw *hw) -{ - hw_dac_stop(hw); - hw_dac_start(hw); -} - -static int hw_dac_init(struct hw *hw, const struct dac_conf *info) -{ - int err; - u32 data; - int i; - struct regs_cs4382 cs_read = {0}; - struct regs_cs4382 cs_def = { - 0x00000001, /* Mode Control 1 */ - 0x00000000, /* Mode Control 2 */ - 0x00000084, /* Mode Control 3 */ - 0x00000000, /* Filter Control */ - 0x00000000, /* Invert Control */ - 0x00000024, /* Mixing Control Pair 1 */ - 0x00000000, /* Vol Control A1 */ - 0x00000000, /* Vol Control B1 */ - 0x00000024, /* Mixing Control Pair 2 */ - 0x00000000, /* Vol Control A2 */ - 0x00000000, /* Vol Control B2 */ - 0x00000024, /* Mixing Control Pair 3 */ - 0x00000000, /* Vol Control A3 */ - 0x00000000, /* Vol Control B3 */ - 0x00000024, /* Mixing Control Pair 4 */ - 0x00000000, /* Vol Control A4 */ - 0x00000000 /* Vol Control B4 */ - }; - - if (hw->model == CTSB1270) { - hw_dac_stop(hw); - data = hw_read_20kx(hw, GPIO_DATA); - data &= ~0x0600; - if (1 == info->msr) - data |= 0x0000; /* Single Speed Mode 0-50kHz */ - else if (2 == info->msr) - data |= 0x0200; /* Double Speed Mode 50-100kHz */ - else - data |= 0x0600; /* Quad Speed Mode 100-200kHz */ - hw_write_20kx(hw, GPIO_DATA, data); - hw_dac_start(hw); - return 0; - } - - /* Set DAC reset bit as output */ - data = hw_read_20kx(hw, GPIO_CTRL); - data |= 0x02; - hw_write_20kx(hw, GPIO_CTRL, data); - - err = hw20k2_i2c_init(hw, 0x18, 1, 1); - if (err < 0) - goto End; - - for (i = 0; i < 2; i++) { - /* Reset DAC twice just in-case the chip - * didn't initialized properly */ - hw_dac_reset(hw); - hw_dac_reset(hw); - - if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_MC2, &cs_read.mode_control_2)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_MC3, &cs_read.mode_control_3)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_FC, &cs_read.filter_control)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_IC, &cs_read.invert_control)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_XC1, &cs_read.mix_control_P1)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_VCA1, &cs_read.vol_control_A1)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_VCB1, &cs_read.vol_control_B1)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_XC2, &cs_read.mix_control_P2)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_VCA2, &cs_read.vol_control_A2)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_VCB2, &cs_read.vol_control_B2)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_XC3, &cs_read.mix_control_P3)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_VCA3, &cs_read.vol_control_A3)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_VCB3, &cs_read.vol_control_B3)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_XC4, &cs_read.mix_control_P4)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_VCA4, &cs_read.vol_control_A4)) - continue; - - if (hw20k2_i2c_read(hw, CS4382_VCB4, &cs_read.vol_control_B4)) - continue; - - if (memcmp(&cs_read, &cs_def, sizeof(cs_read))) - continue; - else - break; - } - - if (i >= 2) - goto End; - - /* Note: Every I2C write must have some delay. - * This is not a requirement but the delay works here... */ - hw20k2_i2c_write(hw, CS4382_MC1, 0x80); - hw20k2_i2c_write(hw, CS4382_MC2, 0x10); - if (1 == info->msr) { - hw20k2_i2c_write(hw, CS4382_XC1, 0x24); - hw20k2_i2c_write(hw, CS4382_XC2, 0x24); - hw20k2_i2c_write(hw, CS4382_XC3, 0x24); - hw20k2_i2c_write(hw, CS4382_XC4, 0x24); - } else if (2 == info->msr) { - hw20k2_i2c_write(hw, CS4382_XC1, 0x25); - hw20k2_i2c_write(hw, CS4382_XC2, 0x25); - hw20k2_i2c_write(hw, CS4382_XC3, 0x25); - hw20k2_i2c_write(hw, CS4382_XC4, 0x25); - } else { - hw20k2_i2c_write(hw, CS4382_XC1, 0x26); - hw20k2_i2c_write(hw, CS4382_XC2, 0x26); - hw20k2_i2c_write(hw, CS4382_XC3, 0x26); - hw20k2_i2c_write(hw, CS4382_XC4, 0x26); - } - - return 0; -End: - - hw20k2_i2c_uninit(hw); - return -1; -} - -/* ADC operations */ -#define MAKE_WM8775_ADDR(addr, data) (u32)(((addr<<1)&0xFE)|((data>>8)&0x1)) -#define MAKE_WM8775_DATA(data) (u32)(data&0xFF) - -#define WM8775_IC 0x0B -#define WM8775_MMC 0x0C -#define WM8775_AADCL 0x0E -#define WM8775_AADCR 0x0F -#define WM8775_ADCMC 0x15 -#define WM8775_RESET 0x17 - -static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) -{ - u32 data; - if (hw->model == CTSB1270) { - /* Titanium HD has two ADC chips, one for line in and one */ - /* for MIC. We don't need to switch the ADC input. */ - return 1; - } - data = hw_read_20kx(hw, GPIO_DATA); - switch (type) { - case ADC_MICIN: - data = (data & (0x1 << 14)) ? 1 : 0; - break; - case ADC_LINEIN: - data = (data & (0x1 << 14)) ? 0 : 1; - break; - default: - data = 0; - } - return data; -} - -#define MIC_BOOST_0DB 0xCF -#define MIC_BOOST_STEPS_PER_DB 2 - -static void hw_wm8775_input_select(struct hw *hw, u8 input, s8 gain_in_db) -{ - u32 adcmc, gain; - - if (input > 3) - input = 3; - - adcmc = ((u32)1 << input) | 0x100; /* Link L+R gain... */ - - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, adcmc), - MAKE_WM8775_DATA(adcmc)); - - if (gain_in_db < -103) - gain_in_db = -103; - if (gain_in_db > 24) - gain_in_db = 24; - - gain = gain_in_db * MIC_BOOST_STEPS_PER_DB + MIC_BOOST_0DB; - - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, gain), - MAKE_WM8775_DATA(gain)); - /* ...so there should be no need for the following. */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, gain), - MAKE_WM8775_DATA(gain)); -} - -static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) -{ - u32 data; - data = hw_read_20kx(hw, GPIO_DATA); - switch (type) { - case ADC_MICIN: - data |= (0x1 << 14); - hw_write_20kx(hw, GPIO_DATA, data); - hw_wm8775_input_select(hw, 0, 20); /* Mic, 20dB */ - break; - case ADC_LINEIN: - data &= ~(0x1 << 14); - hw_write_20kx(hw, GPIO_DATA, data); - hw_wm8775_input_select(hw, 1, 0); /* Line-in, 0dB */ - break; - default: - break; - } - - return 0; -} - -static int hw_adc_init(struct hw *hw, const struct adc_conf *info) -{ - int err; - u32 data, ctl; - - /* Set ADC reset bit as output */ - data = hw_read_20kx(hw, GPIO_CTRL); - data |= (0x1 << 15); - hw_write_20kx(hw, GPIO_CTRL, data); - - /* Initialize I2C */ - err = hw20k2_i2c_init(hw, 0x1A, 1, 1); - if (err < 0) { - printk(KERN_ALERT "ctxfi: Failure to acquire I2C!!!\n"); - goto error; - } - - /* Reset the ADC (reset is active low). */ - data = hw_read_20kx(hw, GPIO_DATA); - data &= ~(0x1 << 15); - hw_write_20kx(hw, GPIO_DATA, data); - - if (hw->model == CTSB1270) { - /* Set up the PCM4220 ADC on Titanium HD */ - data &= ~0x0C; - if (1 == info->msr) - data |= 0x00; /* Single Speed Mode 32-50kHz */ - else if (2 == info->msr) - data |= 0x08; /* Double Speed Mode 50-108kHz */ - else - data |= 0x04; /* Quad Speed Mode 108kHz-216kHz */ - hw_write_20kx(hw, GPIO_DATA, data); - } - - mdelay(10); - /* Return the ADC to normal operation. */ - data |= (0x1 << 15); - hw_write_20kx(hw, GPIO_DATA, data); - mdelay(50); - - /* I2C write to register offset 0x0B to set ADC LRCLK polarity */ - /* invert bit, interface format to I2S, word length to 24-bit, */ - /* enable ADC high pass filter. Fixes bug 5323? */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_IC, 0x26), - MAKE_WM8775_DATA(0x26)); - - /* Set the master mode (256fs) */ - if (1 == info->msr) { - /* slave mode, 128x oversampling 256fs */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), - MAKE_WM8775_DATA(0x02)); - } else if ((2 == info->msr) || (4 == info->msr)) { - /* slave mode, 64x oversampling, 256fs */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), - MAKE_WM8775_DATA(0x0A)); - } else { - printk(KERN_ALERT "ctxfi: Invalid master sampling " - "rate (msr %d)!!!\n", info->msr); - err = -EINVAL; - goto error; - } - - if (hw->model != CTSB1270) { - /* Configure GPIO bit 14 change to line-in/mic-in */ - ctl = hw_read_20kx(hw, GPIO_CTRL); - ctl |= 0x1 << 14; - hw_write_20kx(hw, GPIO_CTRL, ctl); - hw_adc_input_select(hw, ADC_LINEIN); - } else { - hw_wm8775_input_select(hw, 0, 0); - } - - return 0; -error: - hw20k2_i2c_uninit(hw); - return err; -} - -static struct capabilities hw_capabilities(struct hw *hw) -{ - struct capabilities cap; - - cap.digit_io_switch = 0; - cap.dedicated_mic = hw->model == CTSB1270; - cap.output_switch = hw->model == CTSB1270; - cap.mic_source_switch = hw->model == CTSB1270; - - return cap; -} - -static int hw_output_switch_get(struct hw *hw) -{ - u32 data = hw_read_20kx(hw, GPIO_EXT_DATA); - - switch (data & 0x30) { - case 0x00: - return 0; - case 0x10: - return 1; - case 0x20: - return 2; - default: - return 3; - } -} - -static int hw_output_switch_put(struct hw *hw, int position) -{ - u32 data; - - if (position == hw_output_switch_get(hw)) - return 0; - - /* Mute line and headphones (intended for anti-pop). */ - data = hw_read_20kx(hw, GPIO_DATA); - data |= (0x03 << 11); - hw_write_20kx(hw, GPIO_DATA, data); - - data = hw_read_20kx(hw, GPIO_EXT_DATA) & ~0x30; - switch (position) { - case 0: - break; - case 1: - data |= 0x10; - break; - default: - data |= 0x20; - } - hw_write_20kx(hw, GPIO_EXT_DATA, data); - - /* Unmute line and headphones. */ - data = hw_read_20kx(hw, GPIO_DATA); - data &= ~(0x03 << 11); - hw_write_20kx(hw, GPIO_DATA, data); - - return 1; -} - -static int hw_mic_source_switch_get(struct hw *hw) -{ - struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; - - return hw20k2->mic_source; -} - -static int hw_mic_source_switch_put(struct hw *hw, int position) -{ - struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; - - if (position == hw20k2->mic_source) - return 0; - - switch (position) { - case 0: - hw_wm8775_input_select(hw, 0, 0); /* Mic, 0dB */ - break; - case 1: - hw_wm8775_input_select(hw, 1, 0); /* FP Mic, 0dB */ - break; - case 2: - hw_wm8775_input_select(hw, 3, 0); /* Aux Ext, 0dB */ - break; - default: - return 0; - } - - hw20k2->mic_source = position; - - return 1; -} - -static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) -{ - struct hw *hw = dev_id; - unsigned int status; - - status = hw_read_20kx(hw, GIP); - if (!status) - return IRQ_NONE; - - if (hw->irq_callback) - hw->irq_callback(hw->irq_callback_data, status); - - hw_write_20kx(hw, GIP, status); - return IRQ_HANDLED; -} - -static int hw_card_start(struct hw *hw) -{ - int err = 0; - struct pci_dev *pci = hw->pci; - unsigned int gctl; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - /* Set DMA transfer mask */ - if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || - pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { - printk(KERN_ERR "ctxfi: architecture does not support PCI " - "busmaster DMA with mask 0x%llx\n", CT_XFI_DMA_MASK); - err = -ENXIO; - goto error1; - } - - if (!hw->io_base) { - err = pci_request_regions(pci, "XFi"); - if (err < 0) - goto error1; - - hw->io_base = pci_resource_start(hw->pci, 2); - hw->mem_base = (unsigned long)ioremap(hw->io_base, - pci_resource_len(hw->pci, 2)); - if (!hw->mem_base) { - err = -ENOENT; - goto error2; - } - } - - /* Switch to 20k2 mode from UAA mode. */ - gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL); - set_field(&gctl, GCTL_UAA, 0); - hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); - - if (hw->irq < 0) { - err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, - KBUILD_MODNAME, hw); - if (err < 0) { - printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); - goto error2; - } - hw->irq = pci->irq; - } - - pci_set_master(pci); - - return 0; - -/*error3: - iounmap((void *)hw->mem_base); - hw->mem_base = (unsigned long)NULL;*/ -error2: - pci_release_regions(pci); - hw->io_base = 0; -error1: - pci_disable_device(pci); - return err; -} - -static int hw_card_stop(struct hw *hw) -{ - unsigned int data; - - /* disable transport bus master and queueing of request */ - hw_write_20kx(hw, TRANSPORT_CTL, 0x00); - - /* disable pll */ - data = hw_read_20kx(hw, PLL_ENB); - hw_write_20kx(hw, PLL_ENB, (data & (~0x07))); - - /* TODO: Disable interrupt and so on... */ - return 0; -} - -static int hw_card_shutdown(struct hw *hw) -{ - if (hw->irq >= 0) - free_irq(hw->irq, hw); - - hw->irq = -1; - - if (hw->mem_base) - iounmap((void *)hw->mem_base); - - hw->mem_base = (unsigned long)NULL; - - if (hw->io_base) - pci_release_regions(hw->pci); - - hw->io_base = 0; - - pci_disable_device(hw->pci); - - return 0; -} - -static int hw_card_init(struct hw *hw, struct card_conf *info) -{ - int err; - unsigned int gctl; - u32 data = 0; - struct dac_conf dac_info = {0}; - struct adc_conf adc_info = {0}; - struct daio_conf daio_info = {0}; - struct trn_conf trn_info = {0}; - - /* Get PCI io port/memory base address and - * do 20kx core switch if needed. */ - err = hw_card_start(hw); - if (err) - return err; - - /* PLL init */ - err = hw_pll_init(hw, info->rsr); - if (err < 0) - return err; - - /* kick off auto-init */ - err = hw_auto_init(hw); - if (err < 0) - return err; - - gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL); - set_field(&gctl, GCTL_DBP, 1); - set_field(&gctl, GCTL_TBP, 1); - set_field(&gctl, GCTL_FBP, 1); - set_field(&gctl, GCTL_DPC, 0); - hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); - - /* Reset all global pending interrupts */ - hw_write_20kx(hw, GIE, 0); - /* Reset all SRC pending interrupts */ - hw_write_20kx(hw, SRC_IP, 0); - - if (hw->model != CTSB1270) { - /* TODO: detect the card ID and configure GPIO accordingly. */ - /* Configures GPIO (0xD802 0x98028) */ - /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ - /* Configures GPIO (SB0880) */ - /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ - hw_write_20kx(hw, GPIO_CTRL, 0xD802); - } else { - hw_write_20kx(hw, GPIO_CTRL, 0x9E5F); - } - /* Enable audio ring */ - hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); - - trn_info.vm_pgt_phys = info->vm_pgt_phys; - err = hw_trn_init(hw, &trn_info); - if (err < 0) - return err; - - daio_info.msr = info->msr; - err = hw_daio_init(hw, &daio_info); - if (err < 0) - return err; - - dac_info.msr = info->msr; - err = hw_dac_init(hw, &dac_info); - if (err < 0) - return err; - - adc_info.msr = info->msr; - adc_info.input = ADC_LINEIN; - adc_info.mic20db = 0; - err = hw_adc_init(hw, &adc_info); - if (err < 0) - return err; - - data = hw_read_20kx(hw, SRC_MCTL); - data |= 0x1; /* Enables input from the audio ring */ - hw_write_20kx(hw, SRC_MCTL, data); - - return 0; -} - -#ifdef CONFIG_PM -static int hw_suspend(struct hw *hw, pm_message_t state) -{ - struct pci_dev *pci = hw->pci; - - hw_card_stop(hw); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - - return 0; -} - -static int hw_resume(struct hw *hw, struct card_conf *info) -{ - struct pci_dev *pci = hw->pci; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - - /* Re-initialize card hardware. */ - return hw_card_init(hw, info); -} -#endif - -static u32 hw_read_20kx(struct hw *hw, u32 reg) -{ - return readl((void *)(hw->mem_base + reg)); -} - -static void hw_write_20kx(struct hw *hw, u32 reg, u32 data) -{ - writel(data, (void *)(hw->mem_base + reg)); -} - -static struct hw ct20k2_preset __devinitdata = { - .irq = -1, - - .card_init = hw_card_init, - .card_stop = hw_card_stop, - .pll_init = hw_pll_init, - .is_adc_source_selected = hw_is_adc_input_selected, - .select_adc_source = hw_adc_input_select, - .capabilities = hw_capabilities, - .output_switch_get = hw_output_switch_get, - .output_switch_put = hw_output_switch_put, - .mic_source_switch_get = hw_mic_source_switch_get, - .mic_source_switch_put = hw_mic_source_switch_put, -#ifdef CONFIG_PM - .suspend = hw_suspend, - .resume = hw_resume, -#endif - - .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, - .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, - .src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk, - .src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk, - .src_set_state = src_set_state, - .src_set_bm = src_set_bm, - .src_set_rsr = src_set_rsr, - .src_set_sf = src_set_sf, - .src_set_wr = src_set_wr, - .src_set_pm = src_set_pm, - .src_set_rom = src_set_rom, - .src_set_vo = src_set_vo, - .src_set_st = src_set_st, - .src_set_ie = src_set_ie, - .src_set_ilsz = src_set_ilsz, - .src_set_bp = src_set_bp, - .src_set_cisz = src_set_cisz, - .src_set_ca = src_set_ca, - .src_set_sa = src_set_sa, - .src_set_la = src_set_la, - .src_set_pitch = src_set_pitch, - .src_set_dirty = src_set_dirty, - .src_set_clear_zbufs = src_set_clear_zbufs, - .src_set_dirty_all = src_set_dirty_all, - .src_commit_write = src_commit_write, - .src_get_ca = src_get_ca, - .src_get_dirty = src_get_dirty, - .src_dirty_conj_mask = src_dirty_conj_mask, - .src_mgr_enbs_src = src_mgr_enbs_src, - .src_mgr_enb_src = src_mgr_enb_src, - .src_mgr_dsb_src = src_mgr_dsb_src, - .src_mgr_commit_write = src_mgr_commit_write, - - .srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk, - .srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk, - .srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc, - .srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser, - .srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt, - .srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr, - .srcimp_mgr_commit_write = srcimp_mgr_commit_write, - - .amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk, - .amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk, - .amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk, - .amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk, - .amixer_set_mode = amixer_set_mode, - .amixer_set_iv = amixer_set_iv, - .amixer_set_x = amixer_set_x, - .amixer_set_y = amixer_set_y, - .amixer_set_sadr = amixer_set_sadr, - .amixer_set_se = amixer_set_se, - .amixer_set_dirty = amixer_set_dirty, - .amixer_set_dirty_all = amixer_set_dirty_all, - .amixer_commit_write = amixer_commit_write, - .amixer_get_y = amixer_get_y, - .amixer_get_dirty = amixer_get_dirty, - - .dai_get_ctrl_blk = dai_get_ctrl_blk, - .dai_put_ctrl_blk = dai_put_ctrl_blk, - .dai_srt_set_srco = dai_srt_set_srco, - .dai_srt_set_srcm = dai_srt_set_srcm, - .dai_srt_set_rsr = dai_srt_set_rsr, - .dai_srt_set_drat = dai_srt_set_drat, - .dai_srt_set_ec = dai_srt_set_ec, - .dai_srt_set_et = dai_srt_set_et, - .dai_commit_write = dai_commit_write, - - .dao_get_ctrl_blk = dao_get_ctrl_blk, - .dao_put_ctrl_blk = dao_put_ctrl_blk, - .dao_set_spos = dao_set_spos, - .dao_commit_write = dao_commit_write, - .dao_get_spos = dao_get_spos, - - .daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk, - .daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk, - .daio_mgr_enb_dai = daio_mgr_enb_dai, - .daio_mgr_dsb_dai = daio_mgr_dsb_dai, - .daio_mgr_enb_dao = daio_mgr_enb_dao, - .daio_mgr_dsb_dao = daio_mgr_dsb_dao, - .daio_mgr_dao_init = daio_mgr_dao_init, - .daio_mgr_set_imaparc = daio_mgr_set_imaparc, - .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt, - .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr, - .daio_mgr_commit_write = daio_mgr_commit_write, - - .set_timer_irq = set_timer_irq, - .set_timer_tick = set_timer_tick, - .get_wc = get_wc, -}; - -int __devinit create_20k2_hw_obj(struct hw **rhw) -{ - struct hw20k2 *hw20k2; - - *rhw = NULL; - hw20k2 = kzalloc(sizeof(*hw20k2), GFP_KERNEL); - if (!hw20k2) - return -ENOMEM; - - hw20k2->hw = ct20k2_preset; - *rhw = &hw20k2->hw; - - return 0; -} - -int destroy_20k2_hw_obj(struct hw *hw) -{ - if (hw->io_base) - hw_card_shutdown(hw); - - kfree(hw); - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.h b/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.h deleted file mode 100644 index d2b7daab..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/cthw20k2.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File cthw20k2.h - * - * @Brief - * This file contains the definition of hardware access methord. - * - * @Author Liu Chun - * @Date May 13 2008 - * - */ - -#ifndef CTHW20K2_H -#define CTHW20K2_H - -#include "cthardware.h" - -int create_20k2_hw_obj(struct hw **rhw); -int destroy_20k2_hw_obj(struct hw *hw); - -#endif /* CTHW20K2_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctimap.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctimap.c deleted file mode 100644 index 0b73368a..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctimap.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctimap.c - * - * @Brief - * This file contains the implementation of generic input mapper operations - * for input mapper management. - * - * @Author Liu Chun - * @Date May 23 2008 - * - */ - -#include "ctimap.h" -#include - -int input_mapper_add(struct list_head *mappers, struct imapper *entry, - int (*map_op)(void *, struct imapper *), void *data) -{ - struct list_head *pos, *pre, *head; - struct imapper *pre_ent, *pos_ent; - - head = mappers; - - if (list_empty(head)) { - entry->next = entry->addr; - map_op(data, entry); - list_add(&entry->list, head); - return 0; - } - - list_for_each(pos, head) { - pos_ent = list_entry(pos, struct imapper, list); - if (pos_ent->slot > entry->slot) { - /* found a position in list */ - break; - } - } - - if (pos != head) { - pre = pos->prev; - if (pre == head) - pre = head->prev; - - __list_add(&entry->list, pos->prev, pos); - } else { - pre = head->prev; - pos = head->next; - list_add_tail(&entry->list, head); - } - - pre_ent = list_entry(pre, struct imapper, list); - pos_ent = list_entry(pos, struct imapper, list); - - entry->next = pos_ent->addr; - map_op(data, entry); - pre_ent->next = entry->addr; - map_op(data, pre_ent); - - return 0; -} - -int input_mapper_delete(struct list_head *mappers, struct imapper *entry, - int (*map_op)(void *, struct imapper *), void *data) -{ - struct list_head *next, *pre, *head; - struct imapper *pre_ent, *next_ent; - - head = mappers; - - if (list_empty(head)) - return 0; - - pre = (entry->list.prev == head) ? head->prev : entry->list.prev; - next = (entry->list.next == head) ? head->next : entry->list.next; - - if (pre == &entry->list) { - /* entry is the only one node in mappers list */ - entry->next = entry->addr = entry->user = entry->slot = 0; - map_op(data, entry); - list_del(&entry->list); - return 0; - } - - pre_ent = list_entry(pre, struct imapper, list); - next_ent = list_entry(next, struct imapper, list); - - pre_ent->next = next_ent->addr; - map_op(data, pre_ent); - list_del(&entry->list); - - return 0; -} - -void free_input_mapper_list(struct list_head *head) -{ - struct imapper *entry; - struct list_head *pos; - - while (!list_empty(head)) { - pos = head->next; - list_del(pos); - entry = list_entry(pos, struct imapper, list); - kfree(entry); - } -} - diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctimap.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctimap.h deleted file mode 100644 index 53ccf9be..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctimap.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctimap.h - * - * @Brief - * This file contains the definition of generic input mapper operations - * for input mapper management. - * - * @Author Liu Chun - * @Date May 23 2008 - * - */ - -#ifndef CTIMAP_H -#define CTIMAP_H - -#include - -struct imapper { - unsigned short slot; /* the id of the slot containing input data */ - unsigned short user; /* the id of the user resource consuming data */ - unsigned short addr; /* the input mapper ram id */ - unsigned short next; /* the next input mapper ram id */ - struct list_head list; -}; - -int input_mapper_add(struct list_head *mappers, struct imapper *entry, - int (*map_op)(void *, struct imapper *), void *data); - -int input_mapper_delete(struct list_head *mappers, struct imapper *entry, - int (*map_op)(void *, struct imapper *), void *data); - -void free_input_mapper_list(struct list_head *mappers); - -#endif /* CTIMAP_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.c deleted file mode 100644 index 0cc13eee..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.c +++ /dev/null @@ -1,1227 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctmixer.c - * - * @Brief - * This file contains the implementation of alsa mixer device functions. - * - * @Author Liu Chun - * @Date May 28 2008 - * - */ - - -#include "ctmixer.h" -#include "ctamixer.h" -#include -#include -#include -#include -#include -#include - -enum CT_SUM_CTL { - SUM_IN_F, - SUM_IN_R, - SUM_IN_C, - SUM_IN_S, - SUM_IN_F_C, - - NUM_CT_SUMS -}; - -enum CT_AMIXER_CTL { - /* volume control mixers */ - AMIXER_MASTER_F, - AMIXER_MASTER_R, - AMIXER_MASTER_C, - AMIXER_MASTER_S, - AMIXER_PCM_F, - AMIXER_PCM_R, - AMIXER_PCM_C, - AMIXER_PCM_S, - AMIXER_SPDIFI, - AMIXER_LINEIN, - AMIXER_MIC, - AMIXER_SPDIFO, - AMIXER_WAVE_F, - AMIXER_WAVE_R, - AMIXER_WAVE_C, - AMIXER_WAVE_S, - AMIXER_MASTER_F_C, - AMIXER_PCM_F_C, - AMIXER_SPDIFI_C, - AMIXER_LINEIN_C, - AMIXER_MIC_C, - - /* this should always be the last one */ - NUM_CT_AMIXERS -}; - -enum CTALSA_MIXER_CTL { - /* volume control mixers */ - MIXER_MASTER_P, - MIXER_PCM_P, - MIXER_LINEIN_P, - MIXER_MIC_P, - MIXER_SPDIFI_P, - MIXER_SPDIFO_P, - MIXER_WAVEF_P, - MIXER_WAVER_P, - MIXER_WAVEC_P, - MIXER_WAVES_P, - MIXER_MASTER_C, - MIXER_PCM_C, - MIXER_LINEIN_C, - MIXER_MIC_C, - MIXER_SPDIFI_C, - - /* switch control mixers */ - MIXER_PCM_C_S, - MIXER_LINEIN_C_S, - MIXER_MIC_C_S, - MIXER_SPDIFI_C_S, - MIXER_SPDIFO_P_S, - MIXER_WAVEF_P_S, - MIXER_WAVER_P_S, - MIXER_WAVEC_P_S, - MIXER_WAVES_P_S, - MIXER_DIGITAL_IO_S, - MIXER_IEC958_MASK, - MIXER_IEC958_DEFAULT, - MIXER_IEC958_STREAM, - - /* this should always be the last one */ - NUM_CTALSA_MIXERS -}; - -#define VOL_MIXER_START MIXER_MASTER_P -#define VOL_MIXER_END MIXER_SPDIFI_C -#define VOL_MIXER_NUM (VOL_MIXER_END - VOL_MIXER_START + 1) -#define SWH_MIXER_START MIXER_PCM_C_S -#define SWH_MIXER_END MIXER_DIGITAL_IO_S -#define SWH_CAPTURE_START MIXER_PCM_C_S -#define SWH_CAPTURE_END MIXER_SPDIFI_C_S - -#define CHN_NUM 2 - -struct ct_kcontrol_init { - unsigned char ctl; - char *name; -}; - -static struct ct_kcontrol_init -ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { - [MIXER_MASTER_P] = { - .ctl = 1, - .name = "Master Playback Volume", - }, - [MIXER_MASTER_C] = { - .ctl = 1, - .name = "Master Capture Volume", - }, - [MIXER_PCM_P] = { - .ctl = 1, - .name = "PCM Playback Volume", - }, - [MIXER_PCM_C] = { - .ctl = 1, - .name = "PCM Capture Volume", - }, - [MIXER_LINEIN_P] = { - .ctl = 1, - .name = "Line Playback Volume", - }, - [MIXER_LINEIN_C] = { - .ctl = 1, - .name = "Line Capture Volume", - }, - [MIXER_MIC_P] = { - .ctl = 1, - .name = "Mic Playback Volume", - }, - [MIXER_MIC_C] = { - .ctl = 1, - .name = "Mic Capture Volume", - }, - [MIXER_SPDIFI_P] = { - .ctl = 1, - .name = "IEC958 Playback Volume", - }, - [MIXER_SPDIFI_C] = { - .ctl = 1, - .name = "IEC958 Capture Volume", - }, - [MIXER_SPDIFO_P] = { - .ctl = 1, - .name = "Digital Playback Volume", - }, - [MIXER_WAVEF_P] = { - .ctl = 1, - .name = "Front Playback Volume", - }, - [MIXER_WAVES_P] = { - .ctl = 1, - .name = "Side Playback Volume", - }, - [MIXER_WAVEC_P] = { - .ctl = 1, - .name = "Center/LFE Playback Volume", - }, - [MIXER_WAVER_P] = { - .ctl = 1, - .name = "Surround Playback Volume", - }, - [MIXER_PCM_C_S] = { - .ctl = 1, - .name = "PCM Capture Switch", - }, - [MIXER_LINEIN_C_S] = { - .ctl = 1, - .name = "Line Capture Switch", - }, - [MIXER_MIC_C_S] = { - .ctl = 1, - .name = "Mic Capture Switch", - }, - [MIXER_SPDIFI_C_S] = { - .ctl = 1, - .name = "IEC958 Capture Switch", - }, - [MIXER_SPDIFO_P_S] = { - .ctl = 1, - .name = "Digital Playback Switch", - }, - [MIXER_WAVEF_P_S] = { - .ctl = 1, - .name = "Front Playback Switch", - }, - [MIXER_WAVES_P_S] = { - .ctl = 1, - .name = "Side Playback Switch", - }, - [MIXER_WAVEC_P_S] = { - .ctl = 1, - .name = "Center/LFE Playback Switch", - }, - [MIXER_WAVER_P_S] = { - .ctl = 1, - .name = "Surround Playback Switch", - }, - [MIXER_DIGITAL_IO_S] = { - .ctl = 0, - .name = "Digit-IO Playback Switch", - }, -}; - -static void -ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); - -static void -ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); - -/* FIXME: this static looks like it would fail if more than one card was */ -/* installed. */ -static struct snd_kcontrol *kctls[2] = {NULL}; - -static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) -{ - switch (alsa_index) { - case MIXER_MASTER_P: return AMIXER_MASTER_F; - case MIXER_MASTER_C: return AMIXER_MASTER_F_C; - case MIXER_PCM_P: return AMIXER_PCM_F; - case MIXER_PCM_C: - case MIXER_PCM_C_S: return AMIXER_PCM_F_C; - case MIXER_LINEIN_P: return AMIXER_LINEIN; - case MIXER_LINEIN_C: - case MIXER_LINEIN_C_S: return AMIXER_LINEIN_C; - case MIXER_MIC_P: return AMIXER_MIC; - case MIXER_MIC_C: - case MIXER_MIC_C_S: return AMIXER_MIC_C; - case MIXER_SPDIFI_P: return AMIXER_SPDIFI; - case MIXER_SPDIFI_C: - case MIXER_SPDIFI_C_S: return AMIXER_SPDIFI_C; - case MIXER_SPDIFO_P: return AMIXER_SPDIFO; - case MIXER_WAVEF_P: return AMIXER_WAVE_F; - case MIXER_WAVES_P: return AMIXER_WAVE_S; - case MIXER_WAVEC_P: return AMIXER_WAVE_C; - case MIXER_WAVER_P: return AMIXER_WAVE_R; - default: return NUM_CT_AMIXERS; - } -} - -static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index) -{ - switch (index) { - case AMIXER_MASTER_F: return AMIXER_MASTER_F_C; - case AMIXER_PCM_F: return AMIXER_PCM_F_C; - case AMIXER_SPDIFI: return AMIXER_SPDIFI_C; - case AMIXER_LINEIN: return AMIXER_LINEIN_C; - case AMIXER_MIC: return AMIXER_MIC_C; - default: return NUM_CT_AMIXERS; - } -} - -static unsigned char -get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type) -{ - return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START))) - ? 1 : 0; -} - -static void -set_switch_state(struct ct_mixer *mixer, - enum CTALSA_MIXER_CTL type, unsigned char state) -{ - if (state) - mixer->switch_state |= (0x1 << (type - SWH_MIXER_START)); - else - mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START)); -} - -#if 0 /* not used */ -/* Map integer value ranging from 0 to 65535 to 14-bit float value ranging - * from 2^-6 to (1+1023/1024) */ -static unsigned int uint16_to_float14(unsigned int x) -{ - unsigned int i; - - if (x < 17) - return 0; - - x *= 2031; - x /= 65535; - x += 16; - - /* i <= 6 */ - for (i = 0; !(x & 0x400); i++) - x <<= 1; - - x = (((7 - i) & 0x7) << 10) | (x & 0x3ff); - - return x; -} - -static unsigned int float14_to_uint16(unsigned int x) -{ - unsigned int e; - - if (!x) - return x; - - e = (x >> 10) & 0x7; - x &= 0x3ff; - x += 1024; - x >>= (7 - e); - x -= 16; - x *= 65535; - x /= 2031; - - return x; -} -#endif /* not used */ - -#define VOL_SCALE 0x1c -#define VOL_MAX 0x100 - -static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1); - -static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = VOL_MAX; - - return 0; -} - -static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value); - struct amixer *amixer; - int i, val; - - for (i = 0; i < 2; i++) { - amixer = ((struct ct_mixer *)atc->mixer)-> - amixers[type*CHN_NUM+i]; - val = amixer->ops->get_scale(amixer) / VOL_SCALE; - if (val < 0) - val = 0; - else if (val > VOL_MAX) - val = VOL_MAX; - ucontrol->value.integer.value[i] = val; - } - - return 0; -} - -static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - struct ct_mixer *mixer = atc->mixer; - enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value); - struct amixer *amixer; - int i, j, val, oval, change = 0; - - for (i = 0; i < 2; i++) { - val = ucontrol->value.integer.value[i]; - if (val < 0) - val = 0; - else if (val > VOL_MAX) - val = VOL_MAX; - val *= VOL_SCALE; - amixer = mixer->amixers[type*CHN_NUM+i]; - oval = amixer->ops->get_scale(amixer); - if (val != oval) { - amixer->ops->set_scale(amixer, val); - amixer->ops->commit_write(amixer); - change = 1; - /* Synchronize Master/PCM playback AMIXERs. */ - if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) { - for (j = 1; j < 4; j++) { - amixer = mixer-> - amixers[(type+j)*CHN_NUM+i]; - amixer->ops->set_scale(amixer, val); - amixer->ops->commit_write(amixer); - } - } - } - } - - return change; -} - -static struct snd_kcontrol_new vol_ctl = { - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = ct_alsa_mix_volume_info, - .get = ct_alsa_mix_volume_get, - .put = ct_alsa_mix_volume_put, - .tlv = { .p = ct_vol_db_scale }, -}; - -static int output_switch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "FP Headphones", "Headphones", "Speakers" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int output_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc); - return 0; -} - -static int output_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]); -} - -static struct snd_kcontrol_new output_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Output Playback Enum", - .info = output_switch_info, - .get = output_switch_get, - .put = output_switch_put, -}; - -static int mic_source_switch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "Mic", "FP Mic", "Aux" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int mic_source_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc); - return 0; -} - -static int mic_source_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - return atc->mic_source_switch_put(atc, - ucontrol->value.enumerated.item[0]); -} - -static struct snd_kcontrol_new mic_source_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Source Capture Enum", - .info = mic_source_switch_info, - .get = mic_source_switch_get, - .put = mic_source_switch_put, -}; - -static void -do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) -{ - - if (MIXER_LINEIN_C_S == type) { - atc->select_line_in(atc); - set_switch_state(atc->mixer, MIXER_MIC_C_S, 0); - snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE, - &kctls[1]->id); - } else if (MIXER_MIC_C_S == type) { - atc->select_mic_in(atc); - set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0); - snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE, - &kctls[0]->id); - } -} - -static void -do_digit_io_switch(struct ct_atc *atc, int state) -{ - struct ct_mixer *mixer = atc->mixer; - - if (state) { - atc->select_digit_io(atc); - atc->spdif_out_unmute(atc, - get_switch_state(mixer, MIXER_SPDIFO_P_S)); - atc->spdif_in_unmute(atc, 1); - atc->line_in_unmute(atc, 0); - return; - } - - if (get_switch_state(mixer, MIXER_LINEIN_C_S)) - atc->select_line_in(atc); - else if (get_switch_state(mixer, MIXER_MIC_C_S)) - atc->select_mic_in(atc); - - atc->spdif_out_unmute(atc, 0); - atc->spdif_in_unmute(atc, 0); - atc->line_in_unmute(atc, 1); - return; -} - -static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) -{ - struct ct_mixer *mixer = atc->mixer; - struct capabilities cap = atc->capabilities(atc); - - /* Do changes in mixer. */ - if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { - if (state) { - ct_mixer_recording_select(mixer, - get_amixer_index(type)); - } else { - ct_mixer_recording_unselect(mixer, - get_amixer_index(type)); - } - } - /* Do changes out of mixer. */ - if (!cap.dedicated_mic && - (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) { - if (state) - do_line_mic_switch(atc, type); - atc->line_in_unmute(atc, state); - } else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type)) - atc->line_in_unmute(atc, state); - else if (cap.dedicated_mic && (MIXER_MIC_C_S == type)) - atc->mic_unmute(atc, state); - else if (MIXER_SPDIFI_C_S == type) - atc->spdif_in_unmute(atc, state); - else if (MIXER_WAVEF_P_S == type) - atc->line_front_unmute(atc, state); - else if (MIXER_WAVES_P_S == type) - atc->line_surround_unmute(atc, state); - else if (MIXER_WAVEC_P_S == type) - atc->line_clfe_unmute(atc, state); - else if (MIXER_WAVER_P_S == type) - atc->line_rear_unmute(atc, state); - else if (MIXER_SPDIFO_P_S == type) - atc->spdif_out_unmute(atc, state); - else if (MIXER_DIGITAL_IO_S == type) - do_digit_io_switch(atc, state); - - return; -} - -static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - uinfo->value.integer.step = 1; - - return 0; -} - -static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_mixer *mixer = - ((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer; - enum CTALSA_MIXER_CTL type = kcontrol->private_value; - - ucontrol->value.integer.value[0] = get_switch_state(mixer, type); - return 0; -} - -static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - struct ct_mixer *mixer = atc->mixer; - enum CTALSA_MIXER_CTL type = kcontrol->private_value; - int state; - - state = ucontrol->value.integer.value[0]; - if (get_switch_state(mixer, type) == state) - return 0; - - set_switch_state(mixer, type, state); - do_switch(atc, type, state); - - return 1; -} - -static struct snd_kcontrol_new swh_ctl = { - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = ct_alsa_mix_switch_info, - .get = ct_alsa_mix_switch_get, - .put = ct_alsa_mix_switch_put -}; - -static int ct_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static int ct_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - unsigned int status; - - atc->spdif_out_get_status(atc, &status); - - if (status == 0) - status = SNDRV_PCM_DEFAULT_CON_SPDIF; - - ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (status >> 24) & 0xff; - - return 0; -} - -static int ct_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ct_atc *atc = snd_kcontrol_chip(kcontrol); - int change; - unsigned int status, old_status; - - status = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - - atc->spdif_out_get_status(atc, &old_status); - change = (old_status != status); - if (change) - atc->spdif_out_set_status(atc, status); - - return change; -} - -static struct snd_kcontrol_new iec958_mask_ctl = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), - .count = 1, - .info = ct_spdif_info, - .get = ct_spdif_get_mask, - .private_value = MIXER_IEC958_MASK -}; - -static struct snd_kcontrol_new iec958_default_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .count = 1, - .info = ct_spdif_info, - .get = ct_spdif_get, - .put = ct_spdif_put, - .private_value = MIXER_IEC958_DEFAULT -}; - -static struct snd_kcontrol_new iec958_ctl = { - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), - .count = 1, - .info = ct_spdif_info, - .get = ct_spdif_get, - .put = ct_spdif_put, - .private_value = MIXER_IEC958_STREAM -}; - -#define NUM_IEC958_CTL 3 - -static int -ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new) -{ - struct snd_kcontrol *kctl; - int err; - - kctl = snd_ctl_new1(new, mixer->atc); - if (!kctl) - return -ENOMEM; - - if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface) - kctl->id.device = IEC958; - - err = snd_ctl_add(mixer->atc->card, kctl); - if (err) - return err; - - switch (new->private_value) { - case MIXER_LINEIN_C_S: - kctls[0] = kctl; break; - case MIXER_MIC_C_S: - kctls[1] = kctl; break; - default: - break; - } - - return 0; -} - -static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) -{ - enum CTALSA_MIXER_CTL type; - struct ct_atc *atc = mixer->atc; - struct capabilities cap = atc->capabilities(atc); - int err; - - /* Create snd kcontrol instances on demand */ - for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) { - if (ct_kcontrol_init_table[type].ctl) { - vol_ctl.name = ct_kcontrol_init_table[type].name; - vol_ctl.private_value = (unsigned long)type; - err = ct_mixer_kcontrol_new(mixer, &vol_ctl); - if (err) - return err; - } - } - - ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch; - - for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) { - if (ct_kcontrol_init_table[type].ctl) { - swh_ctl.name = ct_kcontrol_init_table[type].name; - swh_ctl.private_value = (unsigned long)type; - err = ct_mixer_kcontrol_new(mixer, &swh_ctl); - if (err) - return err; - } - } - - err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl); - if (err) - return err; - - err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl); - if (err) - return err; - - err = ct_mixer_kcontrol_new(mixer, &iec958_ctl); - if (err) - return err; - - if (cap.output_switch) { - err = ct_mixer_kcontrol_new(mixer, &output_ctl); - if (err) - return err; - } - - if (cap.mic_source_switch) { - err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl); - if (err) - return err; - } - atc->line_front_unmute(atc, 1); - set_switch_state(mixer, MIXER_WAVEF_P_S, 1); - atc->line_surround_unmute(atc, 0); - set_switch_state(mixer, MIXER_WAVES_P_S, 0); - atc->line_clfe_unmute(atc, 0); - set_switch_state(mixer, MIXER_WAVEC_P_S, 0); - atc->line_rear_unmute(atc, 0); - set_switch_state(mixer, MIXER_WAVER_P_S, 0); - atc->spdif_out_unmute(atc, 0); - set_switch_state(mixer, MIXER_SPDIFO_P_S, 0); - atc->line_in_unmute(atc, 0); - if (cap.dedicated_mic) - atc->mic_unmute(atc, 0); - atc->spdif_in_unmute(atc, 0); - set_switch_state(mixer, MIXER_PCM_C_S, 0); - set_switch_state(mixer, MIXER_LINEIN_C_S, 0); - set_switch_state(mixer, MIXER_SPDIFI_C_S, 0); - - return 0; -} - -static void -ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type) -{ - struct amixer *amix_d; - struct sum *sum_c; - int i; - - for (i = 0; i < 2; i++) { - amix_d = mixer->amixers[type*CHN_NUM+i]; - sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i]; - amix_d->ops->set_sum(amix_d, sum_c); - amix_d->ops->commit_write(amix_d); - } -} - -static void -ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type) -{ - struct amixer *amix_d; - int i; - - for (i = 0; i < 2; i++) { - amix_d = mixer->amixers[type*CHN_NUM+i]; - amix_d->ops->set_sum(amix_d, NULL); - amix_d->ops->commit_write(amix_d); - } -} - -static int ct_mixer_get_resources(struct ct_mixer *mixer) -{ - struct sum_mgr *sum_mgr; - struct sum *sum; - struct sum_desc sum_desc = {0}; - struct amixer_mgr *amixer_mgr; - struct amixer *amixer; - struct amixer_desc am_desc = {0}; - int err; - int i; - - /* Allocate sum resources for mixer obj */ - sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM]; - sum_desc.msr = mixer->atc->msr; - for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) { - err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum); - if (err) { - printk(KERN_ERR "ctxfi:Failed to get sum resources for " - "front output!\n"); - break; - } - mixer->sums[i] = sum; - } - if (err) - goto error1; - - /* Allocate amixer resources for mixer obj */ - amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER]; - am_desc.msr = mixer->atc->msr; - for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) { - err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer); - if (err) { - printk(KERN_ERR "ctxfi:Failed to get amixer resources " - "for mixer obj!\n"); - break; - } - mixer->amixers[i] = amixer; - } - if (err) - goto error2; - - return 0; - -error2: - for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) { - if (NULL != mixer->amixers[i]) { - amixer = mixer->amixers[i]; - amixer_mgr->put_amixer(amixer_mgr, amixer); - mixer->amixers[i] = NULL; - } - } -error1: - for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) { - if (NULL != mixer->sums[i]) { - sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]); - mixer->sums[i] = NULL; - } - } - - return err; -} - -static int ct_mixer_get_mem(struct ct_mixer **rmixer) -{ - struct ct_mixer *mixer; - int err; - - *rmixer = NULL; - /* Allocate mem for mixer obj */ - mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); - if (!mixer) - return -ENOMEM; - - mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM), - GFP_KERNEL); - if (!mixer->amixers) { - err = -ENOMEM; - goto error1; - } - mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL); - if (!mixer->sums) { - err = -ENOMEM; - goto error2; - } - - *rmixer = mixer; - return 0; - -error2: - kfree(mixer->amixers); -error1: - kfree(mixer); - return err; -} - -static int ct_mixer_topology_build(struct ct_mixer *mixer) -{ - struct sum *sum; - struct amixer *amix_d, *amix_s; - enum CT_AMIXER_CTL i, j; - - /* Build topology from destination to source */ - - /* Set up Master mixer */ - for (i = AMIXER_MASTER_F, j = SUM_IN_F; - i <= AMIXER_MASTER_S; i++, j++) { - amix_d = mixer->amixers[i*CHN_NUM]; - sum = mixer->sums[j*CHN_NUM]; - amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); - amix_d = mixer->amixers[i*CHN_NUM+1]; - sum = mixer->sums[j*CHN_NUM+1]; - amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); - } - - /* Set up Wave-out mixer */ - for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F; - i <= AMIXER_WAVE_S; i++, j++) { - amix_d = mixer->amixers[i*CHN_NUM]; - amix_s = mixer->amixers[j*CHN_NUM]; - amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); - amix_d = mixer->amixers[i*CHN_NUM+1]; - amix_s = mixer->amixers[j*CHN_NUM+1]; - amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); - } - - /* Set up S/PDIF-out mixer */ - amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM]; - amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM]; - amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); - amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1]; - amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1]; - amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); - - /* Set up PCM-in mixer */ - for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) { - amix_d = mixer->amixers[i*CHN_NUM]; - sum = mixer->sums[j*CHN_NUM]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - amix_d = mixer->amixers[i*CHN_NUM+1]; - sum = mixer->sums[j*CHN_NUM+1]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - } - - /* Set up Line-in mixer */ - amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM]; - sum = mixer->sums[SUM_IN_F*CHN_NUM]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1]; - sum = mixer->sums[SUM_IN_F*CHN_NUM+1]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - - /* Set up Mic-in mixer */ - amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM]; - sum = mixer->sums[SUM_IN_F*CHN_NUM]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1]; - sum = mixer->sums[SUM_IN_F*CHN_NUM+1]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - - /* Set up S/PDIF-in mixer */ - amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM]; - sum = mixer->sums[SUM_IN_F*CHN_NUM]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM+1]; - sum = mixer->sums[SUM_IN_F*CHN_NUM+1]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - - /* Set up Master recording mixer */ - amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; - amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); - amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM+1]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; - amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); - - /* Set up PCM-in recording mixer */ - amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM+1]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - - /* Set up Line-in recording mixer */ - amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM+1]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - - /* Set up Mic-in recording mixer */ - amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM+1]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - - /* Set up S/PDIF-in recording mixer */ - amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM+1]; - sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; - amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); - - return 0; -} - -static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc) -{ - amixer->ops->set_input(amixer, rsc); - amixer->ops->commit_write(amixer); - - return 0; -} - -static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type) -{ - switch (type) { - case MIX_WAVE_FRONT: return AMIXER_WAVE_F; - case MIX_WAVE_SURROUND: return AMIXER_WAVE_S; - case MIX_WAVE_CENTLFE: return AMIXER_WAVE_C; - case MIX_WAVE_REAR: return AMIXER_WAVE_R; - case MIX_PCMO_FRONT: return AMIXER_MASTER_F_C; - case MIX_SPDIF_OUT: return AMIXER_SPDIFO; - case MIX_LINE_IN: return AMIXER_LINEIN; - case MIX_MIC_IN: return AMIXER_MIC; - case MIX_SPDIF_IN: return AMIXER_SPDIFI; - case MIX_PCMI_FRONT: return AMIXER_PCM_F; - case MIX_PCMI_SURROUND: return AMIXER_PCM_S; - case MIX_PCMI_CENTLFE: return AMIXER_PCM_C; - case MIX_PCMI_REAR: return AMIXER_PCM_R; - default: return 0; - } -} - -static int mixer_get_output_ports(struct ct_mixer *mixer, - enum MIXER_PORT_T type, - struct rsc **rleft, struct rsc **rright) -{ - enum CT_AMIXER_CTL amix = port_to_amixer(type); - - if (NULL != rleft) - *rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc; - - if (NULL != rright) - *rright = - &((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc; - - return 0; -} - -static int mixer_set_input_left(struct ct_mixer *mixer, - enum MIXER_PORT_T type, struct rsc *rsc) -{ - enum CT_AMIXER_CTL amix = port_to_amixer(type); - - mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc); - amix = get_recording_amixer(amix); - if (amix < NUM_CT_AMIXERS) - mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc); - - return 0; -} - -static int -mixer_set_input_right(struct ct_mixer *mixer, - enum MIXER_PORT_T type, struct rsc *rsc) -{ - enum CT_AMIXER_CTL amix = port_to_amixer(type); - - mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc); - amix = get_recording_amixer(amix); - if (amix < NUM_CT_AMIXERS) - mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc); - - return 0; -} - -#ifdef CONFIG_PM -static int mixer_resume(struct ct_mixer *mixer) -{ - int i, state; - struct amixer *amixer; - - /* resume topology and volume gain. */ - for (i = 0; i < NUM_CT_AMIXERS*CHN_NUM; i++) { - amixer = mixer->amixers[i]; - amixer->ops->commit_write(amixer); - } - - /* resume switch state. */ - for (i = SWH_MIXER_START; i <= SWH_MIXER_END; i++) { - state = get_switch_state(mixer, i); - do_switch(mixer->atc, i, state); - } - - return 0; -} -#endif - -int ct_mixer_destroy(struct ct_mixer *mixer) -{ - struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM]; - struct amixer_mgr *amixer_mgr = - (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER]; - struct amixer *amixer; - int i = 0; - - /* Release amixer resources */ - for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) { - if (NULL != mixer->amixers[i]) { - amixer = mixer->amixers[i]; - amixer_mgr->put_amixer(amixer_mgr, amixer); - } - } - - /* Release sum resources */ - for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) { - if (NULL != mixer->sums[i]) - sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]); - } - - /* Release mem assigned to mixer object */ - kfree(mixer->sums); - kfree(mixer->amixers); - kfree(mixer); - - return 0; -} - -int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer) -{ - struct ct_mixer *mixer; - int err; - - *rmixer = NULL; - - /* Allocate mem for mixer obj */ - err = ct_mixer_get_mem(&mixer); - if (err) - return err; - - mixer->switch_state = 0; - mixer->atc = atc; - /* Set operations */ - mixer->get_output_ports = mixer_get_output_ports; - mixer->set_input_left = mixer_set_input_left; - mixer->set_input_right = mixer_set_input_right; -#ifdef CONFIG_PM - mixer->resume = mixer_resume; -#endif - - /* Allocate chip resources for mixer obj */ - err = ct_mixer_get_resources(mixer); - if (err) - goto error; - - /* Build internal mixer topology */ - ct_mixer_topology_build(mixer); - - *rmixer = mixer; - - return 0; - -error: - ct_mixer_destroy(mixer); - return err; -} - -int ct_alsa_mix_create(struct ct_atc *atc, - enum CTALSADEVS device, - const char *device_name) -{ - int err; - - /* Create snd kcontrol instances on demand */ - /* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */ - err = ct_mixer_kcontrols_create((struct ct_mixer *)atc->mixer); - if (err) - return err; - - strcpy(atc->card->mixername, device_name); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.h deleted file mode 100644 index b009e989..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctmixer.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctmixer.h - * - * @Brief - * This file contains the definition of the mixer device functions. - * - * @Author Liu Chun - * @Date Mar 28 2008 - * - */ - -#ifndef CTMIXER_H -#define CTMIXER_H - -#include "ctatc.h" -#include "ctresource.h" - -#define INIT_VOL 0x1c00 - -enum MIXER_PORT_T { - MIX_WAVE_FRONT, - MIX_WAVE_REAR, - MIX_WAVE_CENTLFE, - MIX_WAVE_SURROUND, - MIX_SPDIF_OUT, - MIX_PCMO_FRONT, - MIX_MIC_IN, - MIX_LINE_IN, - MIX_SPDIF_IN, - MIX_PCMI_FRONT, - MIX_PCMI_REAR, - MIX_PCMI_CENTLFE, - MIX_PCMI_SURROUND, - - NUM_MIX_PORTS -}; - -/* alsa mixer descriptor */ -struct ct_mixer { - struct ct_atc *atc; - - void **amixers; /* amixer resources for volume control */ - void **sums; /* sum resources for signal collection */ - unsigned int switch_state; /* A bit-map to indicate state of switches */ - - int (*get_output_ports)(struct ct_mixer *mixer, enum MIXER_PORT_T type, - struct rsc **rleft, struct rsc **rright); - - int (*set_input_left)(struct ct_mixer *mixer, - enum MIXER_PORT_T type, struct rsc *rsc); - int (*set_input_right)(struct ct_mixer *mixer, - enum MIXER_PORT_T type, struct rsc *rsc); -#ifdef CONFIG_PM - int (*resume)(struct ct_mixer *mixer); -#endif -}; - -int ct_alsa_mix_create(struct ct_atc *atc, - enum CTALSADEVS device, - const char *device_name); -int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer); -int ct_mixer_destroy(struct ct_mixer *mixer); - -#endif /* CTMIXER_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.c deleted file mode 100644 index 2c862261..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.c +++ /dev/null @@ -1,435 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctpcm.c - * - * @Brief - * This file contains the definition of the pcm device functions. - * - * @Author Liu Chun - * @Date Apr 2 2008 - * - */ - -#include "ctpcm.h" -#include "cttimer.h" -#include -#include - -/* Hardware descriptions for playback */ -static struct snd_pcm_hardware ct_pcm_playback_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_FLOAT_LE), - .rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_192000), - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = (64), - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware ct_spdif_passthru_playback_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_32000), - .rate_min = 32000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = (64), - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* Hardware descriptions for capture */ -static struct snd_pcm_hardware ct_pcm_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_FLOAT_LE), - .rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_96000), - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = (384), - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm) -{ - struct ct_atc_pcm *apcm = atc_pcm; - - if (!apcm->substream) - return; - - snd_pcm_period_elapsed(apcm->substream); -} - -static void ct_atc_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - struct ct_atc_pcm *apcm = runtime->private_data; - struct ct_atc *atc = snd_pcm_substream_chip(apcm->substream); - - atc->pcm_release_resources(atc, apcm); - ct_timer_instance_free(apcm->timer); - kfree(apcm); - runtime->private_data = NULL; -} - -/* pcm playback operations */ -static int ct_pcm_playback_open(struct snd_pcm_substream *substream) -{ - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm; - int err; - - apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); - if (!apcm) - return -ENOMEM; - - apcm->substream = substream; - apcm->interrupt = ct_atc_pcm_interrupt; - if (IEC958 == substream->pcm->device) { - runtime->hw = ct_spdif_passthru_playback_hw; - atc->spdif_out_passthru(atc, 1); - } else { - runtime->hw = ct_pcm_playback_hw; - if (FRONT == substream->pcm->device) - runtime->hw.channels_max = 8; - } - - err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - kfree(apcm); - return err; - } - err = snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - 1024, UINT_MAX); - if (err < 0) { - kfree(apcm); - return err; - } - - apcm->timer = ct_timer_instance_new(atc->timer, apcm); - if (!apcm->timer) { - kfree(apcm); - return -ENOMEM; - } - runtime->private_data = apcm; - runtime->private_free = ct_atc_pcm_free_substream; - - return 0; -} - -static int ct_pcm_playback_close(struct snd_pcm_substream *substream) -{ - struct ct_atc *atc = snd_pcm_substream_chip(substream); - - /* TODO: Notify mixer inactive. */ - if (IEC958 == substream->pcm->device) - atc->spdif_out_passthru(atc, 0); - - /* The ct_atc_pcm object will be freed by runtime->private_free */ - - return 0; -} - -static int ct_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct ct_atc_pcm *apcm = substream->runtime->private_data; - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - /* clear previous resources */ - atc->pcm_release_resources(atc, apcm); - return err; -} - -static int ct_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct ct_atc_pcm *apcm = substream->runtime->private_data; - - /* clear previous resources */ - atc->pcm_release_resources(atc, apcm); - /* Free snd-allocated pages */ - return snd_pcm_lib_free_pages(substream); -} - - -static int ct_pcm_playback_prepare(struct snd_pcm_substream *substream) -{ - int err; - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm = runtime->private_data; - - if (IEC958 == substream->pcm->device) - err = atc->spdif_passthru_playback_prepare(atc, apcm); - else - err = atc->pcm_playback_prepare(atc, apcm); - - if (err < 0) { - printk(KERN_ERR "ctxfi: Preparing pcm playback failed!!!\n"); - return err; - } - - return 0; -} - -static int -ct_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm = runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - atc->pcm_playback_start(atc, apcm); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - atc->pcm_playback_stop(atc, apcm); - break; - default: - break; - } - - return 0; -} - -static snd_pcm_uframes_t -ct_pcm_playback_pointer(struct snd_pcm_substream *substream) -{ - unsigned long position; - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm = runtime->private_data; - - /* Read out playback position */ - position = atc->pcm_playback_position(atc, apcm); - position = bytes_to_frames(runtime, position); - if (position >= runtime->buffer_size) - position = 0; - return position; -} - -/* pcm capture operations */ -static int ct_pcm_capture_open(struct snd_pcm_substream *substream) -{ - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm; - int err; - - apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); - if (!apcm) - return -ENOMEM; - - apcm->started = 0; - apcm->substream = substream; - apcm->interrupt = ct_atc_pcm_interrupt; - runtime->hw = ct_pcm_capture_hw; - runtime->hw.rate_max = atc->rsr * atc->msr; - - err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - kfree(apcm); - return err; - } - err = snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - 1024, UINT_MAX); - if (err < 0) { - kfree(apcm); - return err; - } - - apcm->timer = ct_timer_instance_new(atc->timer, apcm); - if (!apcm->timer) { - kfree(apcm); - return -ENOMEM; - } - runtime->private_data = apcm; - runtime->private_free = ct_atc_pcm_free_substream; - - return 0; -} - -static int ct_pcm_capture_close(struct snd_pcm_substream *substream) -{ - /* The ct_atc_pcm object will be freed by runtime->private_free */ - /* TODO: Notify mixer inactive. */ - return 0; -} - -static int ct_pcm_capture_prepare(struct snd_pcm_substream *substream) -{ - int err; - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm = runtime->private_data; - - err = atc->pcm_capture_prepare(atc, apcm); - if (err < 0) { - printk(KERN_ERR "ctxfi: Preparing pcm capture failed!!!\n"); - return err; - } - - return 0; -} - -static int -ct_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm = runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - atc->pcm_capture_start(atc, apcm); - break; - case SNDRV_PCM_TRIGGER_STOP: - atc->pcm_capture_stop(atc, apcm); - break; - default: - atc->pcm_capture_stop(atc, apcm); - break; - } - - return 0; -} - -static snd_pcm_uframes_t -ct_pcm_capture_pointer(struct snd_pcm_substream *substream) -{ - unsigned long position; - struct ct_atc *atc = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm = runtime->private_data; - - /* Read out playback position */ - position = atc->pcm_capture_position(atc, apcm); - position = bytes_to_frames(runtime, position); - if (position >= runtime->buffer_size) - position = 0; - return position; -} - -/* PCM operators for playback */ -static struct snd_pcm_ops ct_pcm_playback_ops = { - .open = ct_pcm_playback_open, - .close = ct_pcm_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = ct_pcm_hw_params, - .hw_free = ct_pcm_hw_free, - .prepare = ct_pcm_playback_prepare, - .trigger = ct_pcm_playback_trigger, - .pointer = ct_pcm_playback_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -/* PCM operators for capture */ -static struct snd_pcm_ops ct_pcm_capture_ops = { - .open = ct_pcm_capture_open, - .close = ct_pcm_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = ct_pcm_hw_params, - .hw_free = ct_pcm_hw_free, - .prepare = ct_pcm_capture_prepare, - .trigger = ct_pcm_capture_trigger, - .pointer = ct_pcm_capture_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -/* Create ALSA pcm device */ -int ct_alsa_pcm_create(struct ct_atc *atc, - enum CTALSADEVS device, - const char *device_name) -{ - struct snd_pcm *pcm; - int err; - int playback_count, capture_count; - - playback_count = (IEC958 == device) ? 1 : 256; - capture_count = (FRONT == device) ? 1 : 0; - err = snd_pcm_new(atc->card, "ctxfi", device, - playback_count, capture_count, &pcm); - if (err < 0) { - printk(KERN_ERR "ctxfi: snd_pcm_new failed!! Err=%d\n", err); - return err; - } - - pcm->private_data = atc; - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strlcpy(pcm->name, device_name, sizeof(pcm->name)); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops); - - if (FRONT == device) - snd_pcm_set_ops(pcm, - SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(atc->pci), 128*1024, 128*1024); - -#ifdef CONFIG_PM - atc->pcms[device] = pcm; -#endif - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.h deleted file mode 100644 index 178da0dc..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctpcm.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctpcm.h - * - * @Brief - * This file contains the definition of the pcm device functions. - * - * @Author Liu Chun - * @Date Mar 28 2008 - * - */ - -#ifndef CTPCM_H -#define CTPCM_H - -#include "ctatc.h" - -int ct_alsa_pcm_create(struct ct_atc *atc, - enum CTALSADEVS device, - const char *device_name); - -#endif /* CTPCM_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctresource.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctresource.c deleted file mode 100644 index 7dfaf673..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctresource.c +++ /dev/null @@ -1,301 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctresource.c - * - * @Brief - * This file contains the implementation of some generic helper functions. - * - * @Author Liu Chun - * @Date May 15 2008 - * - */ - -#include "ctresource.h" -#include "cthardware.h" -#include -#include - -#define AUDIO_SLOT_BLOCK_NUM 256 - -/* Resource allocation based on bit-map management mechanism */ -static int -get_resource(u8 *rscs, unsigned int amount, - unsigned int multi, unsigned int *ridx) -{ - int i, j, k, n; - - /* Check whether there are sufficient resources to meet request. */ - for (i = 0, n = multi; i < amount; i++) { - j = i / 8; - k = i % 8; - if (rscs[j] & ((u8)1 << k)) { - n = multi; - continue; - } - if (!(--n)) - break; /* found sufficient contiguous resources */ - } - - if (i >= amount) { - /* Can not find sufficient contiguous resources */ - return -ENOENT; - } - - /* Mark the contiguous bits in resource bit-map as used */ - for (n = multi; n > 0; n--) { - j = i / 8; - k = i % 8; - rscs[j] |= ((u8)1 << k); - i--; - } - - *ridx = i + 1; - - return 0; -} - -static int put_resource(u8 *rscs, unsigned int multi, unsigned int idx) -{ - unsigned int i, j, k, n; - - /* Mark the contiguous bits in resource bit-map as used */ - for (n = multi, i = idx; n > 0; n--) { - j = i / 8; - k = i % 8; - rscs[j] &= ~((u8)1 << k); - i++; - } - - return 0; -} - -int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx) -{ - int err; - - if (n > mgr->avail) - return -ENOENT; - - err = get_resource(mgr->rscs, mgr->amount, n, ridx); - if (!err) - mgr->avail -= n; - - return err; -} - -int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx) -{ - put_resource(mgr->rscs, n, idx); - mgr->avail += n; - - return 0; -} - -static unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = { - /* SRC channel is at Audio Ring slot 1 every 16 slots. */ - [SRC] = 0x1, - [AMIXER] = 0x4, - [SUM] = 0xc, -}; - -static int rsc_index(const struct rsc *rsc) -{ - return rsc->conj; -} - -static int audio_ring_slot(const struct rsc *rsc) -{ - return (rsc->conj << 4) + offset_in_audio_slot_block[rsc->type]; -} - -static int rsc_next_conj(struct rsc *rsc) -{ - unsigned int i; - for (i = 0; (i < 8) && (!(rsc->msr & (0x1 << i))); ) - i++; - rsc->conj += (AUDIO_SLOT_BLOCK_NUM >> i); - return rsc->conj; -} - -static int rsc_master(struct rsc *rsc) -{ - return rsc->conj = rsc->idx; -} - -static struct rsc_ops rsc_generic_ops = { - .index = rsc_index, - .output_slot = audio_ring_slot, - .master = rsc_master, - .next_conj = rsc_next_conj, -}; - -int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw) -{ - int err = 0; - - rsc->idx = idx; - rsc->conj = idx; - rsc->type = type; - rsc->msr = msr; - rsc->hw = hw; - rsc->ops = &rsc_generic_ops; - if (!hw) { - rsc->ctrl_blk = NULL; - return 0; - } - - switch (type) { - case SRC: - err = ((struct hw *)hw)->src_rsc_get_ctrl_blk(&rsc->ctrl_blk); - break; - case AMIXER: - err = ((struct hw *)hw)-> - amixer_rsc_get_ctrl_blk(&rsc->ctrl_blk); - break; - case SRCIMP: - case SUM: - case DAIO: - break; - default: - printk(KERN_ERR - "ctxfi: Invalid resource type value %d!\n", type); - return -EINVAL; - } - - if (err) { - printk(KERN_ERR - "ctxfi: Failed to get resource control block!\n"); - return err; - } - - return 0; -} - -int rsc_uninit(struct rsc *rsc) -{ - if ((NULL != rsc->hw) && (NULL != rsc->ctrl_blk)) { - switch (rsc->type) { - case SRC: - ((struct hw *)rsc->hw)-> - src_rsc_put_ctrl_blk(rsc->ctrl_blk); - break; - case AMIXER: - ((struct hw *)rsc->hw)-> - amixer_rsc_put_ctrl_blk(rsc->ctrl_blk); - break; - case SUM: - case DAIO: - break; - default: - printk(KERN_ERR "ctxfi: " - "Invalid resource type value %d!\n", rsc->type); - break; - } - - rsc->hw = rsc->ctrl_blk = NULL; - } - - rsc->idx = rsc->conj = 0; - rsc->type = NUM_RSCTYP; - rsc->msr = 0; - - return 0; -} - -int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, - unsigned int amount, void *hw_obj) -{ - int err = 0; - struct hw *hw = hw_obj; - - mgr->type = NUM_RSCTYP; - - mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL); - if (!mgr->rscs) - return -ENOMEM; - - switch (type) { - case SRC: - err = hw->src_mgr_get_ctrl_blk(&mgr->ctrl_blk); - break; - case SRCIMP: - err = hw->srcimp_mgr_get_ctrl_blk(&mgr->ctrl_blk); - break; - case AMIXER: - err = hw->amixer_mgr_get_ctrl_blk(&mgr->ctrl_blk); - break; - case DAIO: - err = hw->daio_mgr_get_ctrl_blk(hw, &mgr->ctrl_blk); - break; - case SUM: - break; - default: - printk(KERN_ERR - "ctxfi: Invalid resource type value %d!\n", type); - err = -EINVAL; - goto error; - } - - if (err) { - printk(KERN_ERR - "ctxfi: Failed to get manager control block!\n"); - goto error; - } - - mgr->type = type; - mgr->avail = mgr->amount = amount; - mgr->hw = hw; - - return 0; - -error: - kfree(mgr->rscs); - return err; -} - -int rsc_mgr_uninit(struct rsc_mgr *mgr) -{ - if (NULL != mgr->rscs) { - kfree(mgr->rscs); - mgr->rscs = NULL; - } - - if ((NULL != mgr->hw) && (NULL != mgr->ctrl_blk)) { - switch (mgr->type) { - case SRC: - ((struct hw *)mgr->hw)-> - src_mgr_put_ctrl_blk(mgr->ctrl_blk); - break; - case SRCIMP: - ((struct hw *)mgr->hw)-> - srcimp_mgr_put_ctrl_blk(mgr->ctrl_blk); - break; - case AMIXER: - ((struct hw *)mgr->hw)-> - amixer_mgr_put_ctrl_blk(mgr->ctrl_blk); - break; - case DAIO: - ((struct hw *)mgr->hw)-> - daio_mgr_put_ctrl_blk(mgr->ctrl_blk); - break; - case SUM: - break; - default: - printk(KERN_ERR "ctxfi: " - "Invalid resource type value %d!\n", mgr->type); - break; - } - - mgr->hw = mgr->ctrl_blk = NULL; - } - - mgr->type = NUM_RSCTYP; - mgr->avail = mgr->amount = 0; - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctresource.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctresource.h deleted file mode 100644 index 0838c2e8..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctresource.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctresource.h - * - * @Brief - * This file contains the definition of generic hardware resources for - * resource management. - * - * @Author Liu Chun - * @Date May 13 2008 - * - */ - -#ifndef CTRESOURCE_H -#define CTRESOURCE_H - -#include - -enum RSCTYP { - SRC, - SRCIMP, - AMIXER, - SUM, - DAIO, - NUM_RSCTYP /* This must be the last one and less than 16 */ -}; - -struct rsc_ops; - -struct rsc { - u32 idx:12; /* The index of a resource */ - u32 type:4; /* The type (RSCTYP) of a resource */ - u32 conj:12; /* Current conjugate index */ - u32 msr:4; /* The Master Sample Rate a resource working on */ - void *ctrl_blk; /* Chip specific control info block for a resource */ - void *hw; /* Chip specific object for hardware access means */ - struct rsc_ops *ops; /* Generic resource operations */ -}; - -struct rsc_ops { - int (*master)(struct rsc *rsc); /* Move to master resource */ - int (*next_conj)(struct rsc *rsc); /* Move to next conjugate resource */ - int (*index)(const struct rsc *rsc); /* Return the index of resource */ - /* Return the output slot number */ - int (*output_slot)(const struct rsc *rsc); -}; - -int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw); -int rsc_uninit(struct rsc *rsc); - -struct rsc_mgr { - enum RSCTYP type; /* The type (RSCTYP) of resource to manage */ - unsigned int amount; /* The total amount of a kind of resource */ - unsigned int avail; /* The amount of currently available resources */ - unsigned char *rscs; /* The bit-map for resource allocation */ - void *ctrl_blk; /* Chip specific control info block */ - void *hw; /* Chip specific object for hardware access */ -}; - -/* Resource management is based on bit-map mechanism */ -int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, - unsigned int amount, void *hw); -int rsc_mgr_uninit(struct rsc_mgr *mgr); -int mgr_get_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int *ridx); -int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx); - -#endif /* CTRESOURCE_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.c deleted file mode 100644 index 6e77e863..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.c +++ /dev/null @@ -1,885 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctsrc.c - * - * @Brief - * This file contains the implementation of the Sample Rate Convertor - * resource management object. - * - * @Author Liu Chun - * @Date May 13 2008 - * - */ - -#include "ctsrc.h" -#include "cthardware.h" -#include - -#define SRC_RESOURCE_NUM 256 -#define SRCIMP_RESOURCE_NUM 256 - -static unsigned int conj_mask; - -static int src_default_config_memrd(struct src *src); -static int src_default_config_memwr(struct src *src); -static int src_default_config_arcrw(struct src *src); - -static int (*src_default_config[3])(struct src *) = { - [MEMRD] = src_default_config_memrd, - [MEMWR] = src_default_config_memwr, - [ARCRW] = src_default_config_arcrw -}; - -static int src_set_state(struct src *src, unsigned int state) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_state(src->rsc.ctrl_blk, state); - - return 0; -} - -static int src_set_bm(struct src *src, unsigned int bm) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_bm(src->rsc.ctrl_blk, bm); - - return 0; -} - -static int src_set_sf(struct src *src, unsigned int sf) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_sf(src->rsc.ctrl_blk, sf); - - return 0; -} - -static int src_set_pm(struct src *src, unsigned int pm) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_pm(src->rsc.ctrl_blk, pm); - - return 0; -} - -static int src_set_rom(struct src *src, unsigned int rom) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_rom(src->rsc.ctrl_blk, rom); - - return 0; -} - -static int src_set_vo(struct src *src, unsigned int vo) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_vo(src->rsc.ctrl_blk, vo); - - return 0; -} - -static int src_set_st(struct src *src, unsigned int st) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_st(src->rsc.ctrl_blk, st); - - return 0; -} - -static int src_set_bp(struct src *src, unsigned int bp) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_bp(src->rsc.ctrl_blk, bp); - - return 0; -} - -static int src_set_cisz(struct src *src, unsigned int cisz) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_cisz(src->rsc.ctrl_blk, cisz); - - return 0; -} - -static int src_set_ca(struct src *src, unsigned int ca) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_ca(src->rsc.ctrl_blk, ca); - - return 0; -} - -static int src_set_sa(struct src *src, unsigned int sa) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_sa(src->rsc.ctrl_blk, sa); - - return 0; -} - -static int src_set_la(struct src *src, unsigned int la) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_la(src->rsc.ctrl_blk, la); - - return 0; -} - -static int src_set_pitch(struct src *src, unsigned int pitch) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_pitch(src->rsc.ctrl_blk, pitch); - - return 0; -} - -static int src_set_clear_zbufs(struct src *src) -{ - struct hw *hw; - - hw = src->rsc.hw; - hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1); - - return 0; -} - -static int src_commit_write(struct src *src) -{ - struct hw *hw; - int i; - unsigned int dirty = 0; - - hw = src->rsc.hw; - src->rsc.ops->master(&src->rsc); - if (src->rsc.msr > 1) { - /* Save dirty flags for conjugate resource programming */ - dirty = hw->src_get_dirty(src->rsc.ctrl_blk) & conj_mask; - } - hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc), - src->rsc.ctrl_blk); - - /* Program conjugate parameter mixer resources */ - if (MEMWR == src->mode) - return 0; - - for (i = 1; i < src->rsc.msr; i++) { - src->rsc.ops->next_conj(&src->rsc); - hw->src_set_dirty(src->rsc.ctrl_blk, dirty); - hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc), - src->rsc.ctrl_blk); - } - src->rsc.ops->master(&src->rsc); - - return 0; -} - -static int src_get_ca(struct src *src) -{ - struct hw *hw; - - hw = src->rsc.hw; - return hw->src_get_ca(hw, src->rsc.ops->index(&src->rsc), - src->rsc.ctrl_blk); -} - -static int src_init(struct src *src) -{ - src_default_config[src->mode](src); - - return 0; -} - -static struct src *src_next_interleave(struct src *src) -{ - return src->intlv; -} - -static int src_default_config_memrd(struct src *src) -{ - struct hw *hw = src->rsc.hw; - unsigned int rsr, msr; - - hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF); - hw->src_set_bm(src->rsc.ctrl_blk, 1); - for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1) - rsr++; - - hw->src_set_rsr(src->rsc.ctrl_blk, rsr); - hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16); - hw->src_set_wr(src->rsc.ctrl_blk, 0); - hw->src_set_pm(src->rsc.ctrl_blk, 0); - hw->src_set_rom(src->rsc.ctrl_blk, 0); - hw->src_set_vo(src->rsc.ctrl_blk, 0); - hw->src_set_st(src->rsc.ctrl_blk, 0); - hw->src_set_ilsz(src->rsc.ctrl_blk, src->multi - 1); - hw->src_set_cisz(src->rsc.ctrl_blk, 0x80); - hw->src_set_sa(src->rsc.ctrl_blk, 0x0); - hw->src_set_la(src->rsc.ctrl_blk, 0x1000); - hw->src_set_ca(src->rsc.ctrl_blk, 0x80); - hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000); - hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1); - - src->rsc.ops->master(&src->rsc); - hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc), - src->rsc.ctrl_blk); - - for (msr = 1; msr < src->rsc.msr; msr++) { - src->rsc.ops->next_conj(&src->rsc); - hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000); - hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc), - src->rsc.ctrl_blk); - } - src->rsc.ops->master(&src->rsc); - - return 0; -} - -static int src_default_config_memwr(struct src *src) -{ - struct hw *hw = src->rsc.hw; - - hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF); - hw->src_set_bm(src->rsc.ctrl_blk, 1); - hw->src_set_rsr(src->rsc.ctrl_blk, 0); - hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_S16); - hw->src_set_wr(src->rsc.ctrl_blk, 1); - hw->src_set_pm(src->rsc.ctrl_blk, 0); - hw->src_set_rom(src->rsc.ctrl_blk, 0); - hw->src_set_vo(src->rsc.ctrl_blk, 0); - hw->src_set_st(src->rsc.ctrl_blk, 0); - hw->src_set_ilsz(src->rsc.ctrl_blk, 0); - hw->src_set_cisz(src->rsc.ctrl_blk, 0x80); - hw->src_set_sa(src->rsc.ctrl_blk, 0x0); - hw->src_set_la(src->rsc.ctrl_blk, 0x1000); - hw->src_set_ca(src->rsc.ctrl_blk, 0x80); - hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000); - hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1); - - src->rsc.ops->master(&src->rsc); - hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc), - src->rsc.ctrl_blk); - - return 0; -} - -static int src_default_config_arcrw(struct src *src) -{ - struct hw *hw = src->rsc.hw; - unsigned int rsr, msr; - unsigned int dirty; - - hw->src_set_state(src->rsc.ctrl_blk, SRC_STATE_OFF); - hw->src_set_bm(src->rsc.ctrl_blk, 0); - for (rsr = 0, msr = src->rsc.msr; msr > 1; msr >>= 1) - rsr++; - - hw->src_set_rsr(src->rsc.ctrl_blk, rsr); - hw->src_set_sf(src->rsc.ctrl_blk, SRC_SF_F32); - hw->src_set_wr(src->rsc.ctrl_blk, 0); - hw->src_set_pm(src->rsc.ctrl_blk, 0); - hw->src_set_rom(src->rsc.ctrl_blk, 0); - hw->src_set_vo(src->rsc.ctrl_blk, 0); - hw->src_set_st(src->rsc.ctrl_blk, 0); - hw->src_set_ilsz(src->rsc.ctrl_blk, 0); - hw->src_set_cisz(src->rsc.ctrl_blk, 0x80); - hw->src_set_sa(src->rsc.ctrl_blk, 0x0); - /*hw->src_set_sa(src->rsc.ctrl_blk, 0x100);*/ - hw->src_set_la(src->rsc.ctrl_blk, 0x1000); - /*hw->src_set_la(src->rsc.ctrl_blk, 0x03ffffe0);*/ - hw->src_set_ca(src->rsc.ctrl_blk, 0x80); - hw->src_set_pitch(src->rsc.ctrl_blk, 0x1000000); - hw->src_set_clear_zbufs(src->rsc.ctrl_blk, 1); - - dirty = hw->src_get_dirty(src->rsc.ctrl_blk); - src->rsc.ops->master(&src->rsc); - for (msr = 0; msr < src->rsc.msr; msr++) { - hw->src_set_dirty(src->rsc.ctrl_blk, dirty); - hw->src_commit_write(hw, src->rsc.ops->index(&src->rsc), - src->rsc.ctrl_blk); - src->rsc.ops->next_conj(&src->rsc); - } - src->rsc.ops->master(&src->rsc); - - return 0; -} - -static struct src_rsc_ops src_rsc_ops = { - .set_state = src_set_state, - .set_bm = src_set_bm, - .set_sf = src_set_sf, - .set_pm = src_set_pm, - .set_rom = src_set_rom, - .set_vo = src_set_vo, - .set_st = src_set_st, - .set_bp = src_set_bp, - .set_cisz = src_set_cisz, - .set_ca = src_set_ca, - .set_sa = src_set_sa, - .set_la = src_set_la, - .set_pitch = src_set_pitch, - .set_clr_zbufs = src_set_clear_zbufs, - .commit_write = src_commit_write, - .get_ca = src_get_ca, - .init = src_init, - .next_interleave = src_next_interleave, -}; - -static int -src_rsc_init(struct src *src, u32 idx, - const struct src_desc *desc, struct src_mgr *mgr) -{ - int err; - int i, n; - struct src *p; - - n = (MEMRD == desc->mode) ? desc->multi : 1; - for (i = 0, p = src; i < n; i++, p++) { - err = rsc_init(&p->rsc, idx + i, SRC, desc->msr, mgr->mgr.hw); - if (err) - goto error1; - - /* Initialize src specific rsc operations */ - p->ops = &src_rsc_ops; - p->multi = (0 == i) ? desc->multi : 1; - p->mode = desc->mode; - src_default_config[desc->mode](p); - mgr->src_enable(mgr, p); - p->intlv = p + 1; - } - (--p)->intlv = NULL; /* Set @intlv of the last SRC to NULL */ - - mgr->commit_write(mgr); - - return 0; - -error1: - for (i--, p--; i >= 0; i--, p--) { - mgr->src_disable(mgr, p); - rsc_uninit(&p->rsc); - } - mgr->commit_write(mgr); - return err; -} - -static int src_rsc_uninit(struct src *src, struct src_mgr *mgr) -{ - int i, n; - struct src *p; - - n = (MEMRD == src->mode) ? src->multi : 1; - for (i = 0, p = src; i < n; i++, p++) { - mgr->src_disable(mgr, p); - rsc_uninit(&p->rsc); - p->multi = 0; - p->ops = NULL; - p->mode = NUM_SRCMODES; - p->intlv = NULL; - } - mgr->commit_write(mgr); - - return 0; -} - -static int -get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc) -{ - unsigned int idx = SRC_RESOURCE_NUM; - int err; - struct src *src; - unsigned long flags; - - *rsrc = NULL; - - /* Check whether there are sufficient src resources to meet request. */ - spin_lock_irqsave(&mgr->mgr_lock, flags); - if (MEMRD == desc->mode) - err = mgr_get_resource(&mgr->mgr, desc->multi, &idx); - else - err = mgr_get_resource(&mgr->mgr, 1, &idx); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - if (err) { - printk(KERN_ERR "ctxfi: Can't meet SRC resource request!\n"); - return err; - } - - /* Allocate mem for master src resource */ - if (MEMRD == desc->mode) - src = kcalloc(desc->multi, sizeof(*src), GFP_KERNEL); - else - src = kzalloc(sizeof(*src), GFP_KERNEL); - - if (!src) { - err = -ENOMEM; - goto error1; - } - - err = src_rsc_init(src, idx, desc, mgr); - if (err) - goto error2; - - *rsrc = src; - - return 0; - -error2: - kfree(src); -error1: - spin_lock_irqsave(&mgr->mgr_lock, flags); - if (MEMRD == desc->mode) - mgr_put_resource(&mgr->mgr, desc->multi, idx); - else - mgr_put_resource(&mgr->mgr, 1, idx); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - return err; -} - -static int put_src_rsc(struct src_mgr *mgr, struct src *src) -{ - unsigned long flags; - - spin_lock_irqsave(&mgr->mgr_lock, flags); - src->rsc.ops->master(&src->rsc); - if (MEMRD == src->mode) - mgr_put_resource(&mgr->mgr, src->multi, - src->rsc.ops->index(&src->rsc)); - else - mgr_put_resource(&mgr->mgr, 1, src->rsc.ops->index(&src->rsc)); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - src_rsc_uninit(src, mgr); - kfree(src); - - return 0; -} - -static int src_enable_s(struct src_mgr *mgr, struct src *src) -{ - struct hw *hw = mgr->mgr.hw; - int i; - - src->rsc.ops->master(&src->rsc); - for (i = 0; i < src->rsc.msr; i++) { - hw->src_mgr_enbs_src(mgr->mgr.ctrl_blk, - src->rsc.ops->index(&src->rsc)); - src->rsc.ops->next_conj(&src->rsc); - } - src->rsc.ops->master(&src->rsc); - - return 0; -} - -static int src_enable(struct src_mgr *mgr, struct src *src) -{ - struct hw *hw = mgr->mgr.hw; - int i; - - src->rsc.ops->master(&src->rsc); - for (i = 0; i < src->rsc.msr; i++) { - hw->src_mgr_enb_src(mgr->mgr.ctrl_blk, - src->rsc.ops->index(&src->rsc)); - src->rsc.ops->next_conj(&src->rsc); - } - src->rsc.ops->master(&src->rsc); - - return 0; -} - -static int src_disable(struct src_mgr *mgr, struct src *src) -{ - struct hw *hw = mgr->mgr.hw; - int i; - - src->rsc.ops->master(&src->rsc); - for (i = 0; i < src->rsc.msr; i++) { - hw->src_mgr_dsb_src(mgr->mgr.ctrl_blk, - src->rsc.ops->index(&src->rsc)); - src->rsc.ops->next_conj(&src->rsc); - } - src->rsc.ops->master(&src->rsc); - - return 0; -} - -static int src_mgr_commit_write(struct src_mgr *mgr) -{ - struct hw *hw = mgr->mgr.hw; - - hw->src_mgr_commit_write(hw, mgr->mgr.ctrl_blk); - - return 0; -} - -int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr) -{ - int err, i; - struct src_mgr *src_mgr; - - *rsrc_mgr = NULL; - src_mgr = kzalloc(sizeof(*src_mgr), GFP_KERNEL); - if (!src_mgr) - return -ENOMEM; - - err = rsc_mgr_init(&src_mgr->mgr, SRC, SRC_RESOURCE_NUM, hw); - if (err) - goto error1; - - spin_lock_init(&src_mgr->mgr_lock); - conj_mask = ((struct hw *)hw)->src_dirty_conj_mask(); - - src_mgr->get_src = get_src_rsc; - src_mgr->put_src = put_src_rsc; - src_mgr->src_enable_s = src_enable_s; - src_mgr->src_enable = src_enable; - src_mgr->src_disable = src_disable; - src_mgr->commit_write = src_mgr_commit_write; - - /* Disable all SRC resources. */ - for (i = 0; i < 256; i++) - ((struct hw *)hw)->src_mgr_dsb_src(src_mgr->mgr.ctrl_blk, i); - - ((struct hw *)hw)->src_mgr_commit_write(hw, src_mgr->mgr.ctrl_blk); - - *rsrc_mgr = src_mgr; - - return 0; - -error1: - kfree(src_mgr); - return err; -} - -int src_mgr_destroy(struct src_mgr *src_mgr) -{ - rsc_mgr_uninit(&src_mgr->mgr); - kfree(src_mgr); - - return 0; -} - -/* SRCIMP resource manager operations */ - -static int srcimp_master(struct rsc *rsc) -{ - rsc->conj = 0; - return rsc->idx = container_of(rsc, struct srcimp, rsc)->idx[0]; -} - -static int srcimp_next_conj(struct rsc *rsc) -{ - rsc->conj++; - return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj]; -} - -static int srcimp_index(const struct rsc *rsc) -{ - return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj]; -} - -static struct rsc_ops srcimp_basic_rsc_ops = { - .master = srcimp_master, - .next_conj = srcimp_next_conj, - .index = srcimp_index, - .output_slot = NULL, -}; - -static int srcimp_map(struct srcimp *srcimp, struct src *src, struct rsc *input) -{ - struct imapper *entry; - int i; - - srcimp->rsc.ops->master(&srcimp->rsc); - src->rsc.ops->master(&src->rsc); - input->ops->master(input); - - /* Program master and conjugate resources */ - for (i = 0; i < srcimp->rsc.msr; i++) { - entry = &srcimp->imappers[i]; - entry->slot = input->ops->output_slot(input); - entry->user = src->rsc.ops->index(&src->rsc); - entry->addr = srcimp->rsc.ops->index(&srcimp->rsc); - srcimp->mgr->imap_add(srcimp->mgr, entry); - srcimp->mapped |= (0x1 << i); - - srcimp->rsc.ops->next_conj(&srcimp->rsc); - input->ops->next_conj(input); - } - - srcimp->rsc.ops->master(&srcimp->rsc); - input->ops->master(input); - - return 0; -} - -static int srcimp_unmap(struct srcimp *srcimp) -{ - int i; - - /* Program master and conjugate resources */ - for (i = 0; i < srcimp->rsc.msr; i++) { - if (srcimp->mapped & (0x1 << i)) { - srcimp->mgr->imap_delete(srcimp->mgr, - &srcimp->imappers[i]); - srcimp->mapped &= ~(0x1 << i); - } - } - - return 0; -} - -static struct srcimp_rsc_ops srcimp_ops = { - .map = srcimp_map, - .unmap = srcimp_unmap -}; - -static int srcimp_rsc_init(struct srcimp *srcimp, - const struct srcimp_desc *desc, - struct srcimp_mgr *mgr) -{ - int err; - - err = rsc_init(&srcimp->rsc, srcimp->idx[0], - SRCIMP, desc->msr, mgr->mgr.hw); - if (err) - return err; - - /* Reserve memory for imapper nodes */ - srcimp->imappers = kzalloc(sizeof(struct imapper)*desc->msr, - GFP_KERNEL); - if (!srcimp->imappers) { - err = -ENOMEM; - goto error1; - } - - /* Set srcimp specific operations */ - srcimp->rsc.ops = &srcimp_basic_rsc_ops; - srcimp->ops = &srcimp_ops; - srcimp->mgr = mgr; - - srcimp->rsc.ops->master(&srcimp->rsc); - - return 0; - -error1: - rsc_uninit(&srcimp->rsc); - return err; -} - -static int srcimp_rsc_uninit(struct srcimp *srcimp) -{ - if (NULL != srcimp->imappers) { - kfree(srcimp->imappers); - srcimp->imappers = NULL; - } - srcimp->ops = NULL; - srcimp->mgr = NULL; - rsc_uninit(&srcimp->rsc); - - return 0; -} - -static int get_srcimp_rsc(struct srcimp_mgr *mgr, - const struct srcimp_desc *desc, - struct srcimp **rsrcimp) -{ - int err, i; - unsigned int idx; - struct srcimp *srcimp; - unsigned long flags; - - *rsrcimp = NULL; - - /* Allocate mem for SRCIMP resource */ - srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL); - if (!srcimp) - return -ENOMEM; - - /* Check whether there are sufficient SRCIMP resources. */ - err = 0; - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < desc->msr; i++) { - err = mgr_get_resource(&mgr->mgr, 1, &idx); - if (err) - break; - - srcimp->idx[i] = idx; - } - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - if (err) { - printk(KERN_ERR "ctxfi: Can't meet SRCIMP resource request!\n"); - goto error1; - } - - err = srcimp_rsc_init(srcimp, desc, mgr); - if (err) - goto error1; - - *rsrcimp = srcimp; - - return 0; - -error1: - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i--; i >= 0; i--) - mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - kfree(srcimp); - return err; -} - -static int put_srcimp_rsc(struct srcimp_mgr *mgr, struct srcimp *srcimp) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&mgr->mgr_lock, flags); - for (i = 0; i < srcimp->rsc.msr; i++) - mgr_put_resource(&mgr->mgr, 1, srcimp->idx[i]); - - spin_unlock_irqrestore(&mgr->mgr_lock, flags); - srcimp_rsc_uninit(srcimp); - kfree(srcimp); - - return 0; -} - -static int srcimp_map_op(void *data, struct imapper *entry) -{ - struct rsc_mgr *mgr = &((struct srcimp_mgr *)data)->mgr; - struct hw *hw = mgr->hw; - - hw->srcimp_mgr_set_imaparc(mgr->ctrl_blk, entry->slot); - hw->srcimp_mgr_set_imapuser(mgr->ctrl_blk, entry->user); - hw->srcimp_mgr_set_imapnxt(mgr->ctrl_blk, entry->next); - hw->srcimp_mgr_set_imapaddr(mgr->ctrl_blk, entry->addr); - hw->srcimp_mgr_commit_write(mgr->hw, mgr->ctrl_blk); - - return 0; -} - -static int srcimp_imap_add(struct srcimp_mgr *mgr, struct imapper *entry) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&mgr->imap_lock, flags); - if ((0 == entry->addr) && (mgr->init_imap_added)) { - input_mapper_delete(&mgr->imappers, - mgr->init_imap, srcimp_map_op, mgr); - mgr->init_imap_added = 0; - } - err = input_mapper_add(&mgr->imappers, entry, srcimp_map_op, mgr); - spin_unlock_irqrestore(&mgr->imap_lock, flags); - - return err; -} - -static int srcimp_imap_delete(struct srcimp_mgr *mgr, struct imapper *entry) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&mgr->imap_lock, flags); - err = input_mapper_delete(&mgr->imappers, entry, srcimp_map_op, mgr); - if (list_empty(&mgr->imappers)) { - input_mapper_add(&mgr->imappers, mgr->init_imap, - srcimp_map_op, mgr); - mgr->init_imap_added = 1; - } - spin_unlock_irqrestore(&mgr->imap_lock, flags); - - return err; -} - -int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr) -{ - int err; - struct srcimp_mgr *srcimp_mgr; - struct imapper *entry; - - *rsrcimp_mgr = NULL; - srcimp_mgr = kzalloc(sizeof(*srcimp_mgr), GFP_KERNEL); - if (!srcimp_mgr) - return -ENOMEM; - - err = rsc_mgr_init(&srcimp_mgr->mgr, SRCIMP, SRCIMP_RESOURCE_NUM, hw); - if (err) - goto error1; - - spin_lock_init(&srcimp_mgr->mgr_lock); - spin_lock_init(&srcimp_mgr->imap_lock); - INIT_LIST_HEAD(&srcimp_mgr->imappers); - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - err = -ENOMEM; - goto error2; - } - entry->slot = entry->addr = entry->next = entry->user = 0; - list_add(&entry->list, &srcimp_mgr->imappers); - srcimp_mgr->init_imap = entry; - srcimp_mgr->init_imap_added = 1; - - srcimp_mgr->get_srcimp = get_srcimp_rsc; - srcimp_mgr->put_srcimp = put_srcimp_rsc; - srcimp_mgr->imap_add = srcimp_imap_add; - srcimp_mgr->imap_delete = srcimp_imap_delete; - - *rsrcimp_mgr = srcimp_mgr; - - return 0; - -error2: - rsc_mgr_uninit(&srcimp_mgr->mgr); -error1: - kfree(srcimp_mgr); - return err; -} - -int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr) -{ - unsigned long flags; - - /* free src input mapper list */ - spin_lock_irqsave(&srcimp_mgr->imap_lock, flags); - free_input_mapper_list(&srcimp_mgr->imappers); - spin_unlock_irqrestore(&srcimp_mgr->imap_lock, flags); - - rsc_mgr_uninit(&srcimp_mgr->mgr); - kfree(srcimp_mgr); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.h deleted file mode 100644 index 259366aa..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctsrc.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctsrc.h - * - * @Brief - * This file contains the definition of the Sample Rate Convertor - * resource management object. - * - * @Author Liu Chun - * @Date May 13 2008 - * - */ - -#ifndef CTSRC_H -#define CTSRC_H - -#include "ctresource.h" -#include "ctimap.h" -#include -#include - -#define SRC_STATE_OFF 0x0 -#define SRC_STATE_INIT 0x4 -#define SRC_STATE_RUN 0x5 - -#define SRC_SF_U8 0x0 -#define SRC_SF_S16 0x1 -#define SRC_SF_S24 0x2 -#define SRC_SF_S32 0x3 -#define SRC_SF_F32 0x4 - -/* Define the descriptor of a src resource */ -enum SRCMODE { - MEMRD, /* Read data from host memory */ - MEMWR, /* Write data to host memory */ - ARCRW, /* Read from and write to audio ring channel */ - NUM_SRCMODES -}; - -struct src_rsc_ops; - -struct src { - struct rsc rsc; /* Basic resource info */ - struct src *intlv; /* Pointer to next interleaved SRC in a series */ - struct src_rsc_ops *ops; /* SRC specific operations */ - /* Number of contiguous srcs for interleaved usage */ - unsigned char multi; - unsigned char mode; /* Working mode of this SRC resource */ -}; - -struct src_rsc_ops { - int (*set_state)(struct src *src, unsigned int state); - int (*set_bm)(struct src *src, unsigned int bm); - int (*set_sf)(struct src *src, unsigned int sf); - int (*set_pm)(struct src *src, unsigned int pm); - int (*set_rom)(struct src *src, unsigned int rom); - int (*set_vo)(struct src *src, unsigned int vo); - int (*set_st)(struct src *src, unsigned int st); - int (*set_bp)(struct src *src, unsigned int bp); - int (*set_cisz)(struct src *src, unsigned int cisz); - int (*set_ca)(struct src *src, unsigned int ca); - int (*set_sa)(struct src *src, unsigned int sa); - int (*set_la)(struct src *src, unsigned int la); - int (*set_pitch)(struct src *src, unsigned int pitch); - int (*set_clr_zbufs)(struct src *src); - int (*commit_write)(struct src *src); - int (*get_ca)(struct src *src); - int (*init)(struct src *src); - struct src* (*next_interleave)(struct src *src); -}; - -/* Define src resource request description info */ -struct src_desc { - /* Number of contiguous master srcs for interleaved usage */ - unsigned char multi; - unsigned char msr; - unsigned char mode; /* Working mode of the requested srcs */ -}; - -/* Define src manager object */ -struct src_mgr { - struct rsc_mgr mgr; /* Basic resource manager info */ - spinlock_t mgr_lock; - - /* request src resource */ - int (*get_src)(struct src_mgr *mgr, - const struct src_desc *desc, struct src **rsrc); - /* return src resource */ - int (*put_src)(struct src_mgr *mgr, struct src *src); - int (*src_enable_s)(struct src_mgr *mgr, struct src *src); - int (*src_enable)(struct src_mgr *mgr, struct src *src); - int (*src_disable)(struct src_mgr *mgr, struct src *src); - int (*commit_write)(struct src_mgr *mgr); -}; - -/* Define the descriptor of a SRC Input Mapper resource */ -struct srcimp_mgr; -struct srcimp_rsc_ops; - -struct srcimp { - struct rsc rsc; - unsigned char idx[8]; - struct imapper *imappers; - unsigned int mapped; /* A bit-map indicating which conj rsc is mapped */ - struct srcimp_mgr *mgr; - struct srcimp_rsc_ops *ops; -}; - -struct srcimp_rsc_ops { - int (*map)(struct srcimp *srcimp, struct src *user, struct rsc *input); - int (*unmap)(struct srcimp *srcimp); -}; - -/* Define SRCIMP resource request description info */ -struct srcimp_desc { - unsigned int msr; -}; - -struct srcimp_mgr { - struct rsc_mgr mgr; /* Basic resource manager info */ - spinlock_t mgr_lock; - spinlock_t imap_lock; - struct list_head imappers; - struct imapper *init_imap; - unsigned int init_imap_added; - - /* request srcimp resource */ - int (*get_srcimp)(struct srcimp_mgr *mgr, - const struct srcimp_desc *desc, - struct srcimp **rsrcimp); - /* return srcimp resource */ - int (*put_srcimp)(struct srcimp_mgr *mgr, struct srcimp *srcimp); - int (*imap_add)(struct srcimp_mgr *mgr, struct imapper *entry); - int (*imap_delete)(struct srcimp_mgr *mgr, struct imapper *entry); -}; - -/* Constructor and destructor of SRC resource manager */ -int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr); -int src_mgr_destroy(struct src_mgr *src_mgr); -/* Constructor and destructor of SRCIMP resource manager */ -int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrc_mgr); -int srcimp_mgr_destroy(struct srcimp_mgr *srcimp_mgr); - -#endif /* CTSRC_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/cttimer.c b/ANDROID_3.4.5/sound/pci/ctxfi/cttimer.c deleted file mode 100644 index 03fb9090..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/cttimer.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * PCM timer handling on ctxfi - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - */ - -#include -#include -#include -#include -#include -#include "ctatc.h" -#include "cthardware.h" -#include "cttimer.h" - -static bool use_system_timer; -MODULE_PARM_DESC(use_system_timer, "Force to use system-timer"); -module_param(use_system_timer, bool, S_IRUGO); - -struct ct_timer_ops { - void (*init)(struct ct_timer_instance *); - void (*prepare)(struct ct_timer_instance *); - void (*start)(struct ct_timer_instance *); - void (*stop)(struct ct_timer_instance *); - void (*free_instance)(struct ct_timer_instance *); - void (*interrupt)(struct ct_timer *); - void (*free_global)(struct ct_timer *); -}; - -/* timer instance -- assigned to each PCM stream */ -struct ct_timer_instance { - spinlock_t lock; - struct ct_timer *timer_base; - struct ct_atc_pcm *apcm; - struct snd_pcm_substream *substream; - struct timer_list timer; - struct list_head instance_list; - struct list_head running_list; - unsigned int position; - unsigned int frag_count; - unsigned int running:1; - unsigned int need_update:1; -}; - -/* timer instance manager */ -struct ct_timer { - spinlock_t lock; /* global timer lock (for xfitimer) */ - spinlock_t list_lock; /* lock for instance list */ - struct ct_atc *atc; - struct ct_timer_ops *ops; - struct list_head instance_head; - struct list_head running_head; - unsigned int wc; /* current wallclock */ - unsigned int irq_handling:1; /* in IRQ handling */ - unsigned int reprogram:1; /* need to reprogram the internval */ - unsigned int running:1; /* global timer running */ -}; - - -/* - * system-timer-based updates - */ - -static void ct_systimer_callback(unsigned long data) -{ - struct ct_timer_instance *ti = (struct ct_timer_instance *)data; - struct snd_pcm_substream *substream = ti->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - struct ct_atc_pcm *apcm = ti->apcm; - unsigned int period_size = runtime->period_size; - unsigned int buffer_size = runtime->buffer_size; - unsigned long flags; - unsigned int position, dist, interval; - - position = substream->ops->pointer(substream); - dist = (position + buffer_size - ti->position) % buffer_size; - if (dist >= period_size || - position / period_size != ti->position / period_size) { - apcm->interrupt(apcm); - ti->position = position; - } - /* Add extra HZ*5/1000 to avoid overrun issue when recording - * at 8kHz in 8-bit format or at 88kHz in 24-bit format. */ - interval = ((period_size - (position % period_size)) - * HZ + (runtime->rate - 1)) / runtime->rate + HZ * 5 / 1000; - spin_lock_irqsave(&ti->lock, flags); - if (ti->running) - mod_timer(&ti->timer, jiffies + interval); - spin_unlock_irqrestore(&ti->lock, flags); -} - -static void ct_systimer_init(struct ct_timer_instance *ti) -{ - setup_timer(&ti->timer, ct_systimer_callback, - (unsigned long)ti); -} - -static void ct_systimer_start(struct ct_timer_instance *ti) -{ - struct snd_pcm_runtime *runtime = ti->substream->runtime; - unsigned long flags; - - spin_lock_irqsave(&ti->lock, flags); - ti->running = 1; - mod_timer(&ti->timer, - jiffies + (runtime->period_size * HZ + - (runtime->rate - 1)) / runtime->rate); - spin_unlock_irqrestore(&ti->lock, flags); -} - -static void ct_systimer_stop(struct ct_timer_instance *ti) -{ - unsigned long flags; - - spin_lock_irqsave(&ti->lock, flags); - ti->running = 0; - del_timer(&ti->timer); - spin_unlock_irqrestore(&ti->lock, flags); -} - -static void ct_systimer_prepare(struct ct_timer_instance *ti) -{ - ct_systimer_stop(ti); - try_to_del_timer_sync(&ti->timer); -} - -#define ct_systimer_free ct_systimer_prepare - -static struct ct_timer_ops ct_systimer_ops = { - .init = ct_systimer_init, - .free_instance = ct_systimer_free, - .prepare = ct_systimer_prepare, - .start = ct_systimer_start, - .stop = ct_systimer_stop, -}; - - -/* - * Handling multiple streams using a global emu20k1 timer irq - */ - -#define CT_TIMER_FREQ 48000 -#define MIN_TICKS 1 -#define MAX_TICKS ((1 << 13) - 1) - -static void ct_xfitimer_irq_rearm(struct ct_timer *atimer, int ticks) -{ - struct hw *hw = atimer->atc->hw; - if (ticks > MAX_TICKS) - ticks = MAX_TICKS; - hw->set_timer_tick(hw, ticks); - if (!atimer->running) - hw->set_timer_irq(hw, 1); - atimer->running = 1; -} - -static void ct_xfitimer_irq_stop(struct ct_timer *atimer) -{ - if (atimer->running) { - struct hw *hw = atimer->atc->hw; - hw->set_timer_irq(hw, 0); - hw->set_timer_tick(hw, 0); - atimer->running = 0; - } -} - -static inline unsigned int ct_xfitimer_get_wc(struct ct_timer *atimer) -{ - struct hw *hw = atimer->atc->hw; - return hw->get_wc(hw); -} - -/* - * reprogram the timer interval; - * checks the running instance list and determines the next timer interval. - * also updates the each stream position, returns the number of streams - * to call snd_pcm_period_elapsed() appropriately - * - * call this inside the lock and irq disabled - */ -static int ct_xfitimer_reprogram(struct ct_timer *atimer, int can_update) -{ - struct ct_timer_instance *ti; - unsigned int min_intr = (unsigned int)-1; - int updates = 0; - unsigned int wc, diff; - - if (list_empty(&atimer->running_head)) { - ct_xfitimer_irq_stop(atimer); - atimer->reprogram = 0; /* clear flag */ - return 0; - } - - wc = ct_xfitimer_get_wc(atimer); - diff = wc - atimer->wc; - atimer->wc = wc; - list_for_each_entry(ti, &atimer->running_head, running_list) { - if (ti->frag_count > diff) - ti->frag_count -= diff; - else { - unsigned int pos; - unsigned int period_size, rate; - - period_size = ti->substream->runtime->period_size; - rate = ti->substream->runtime->rate; - pos = ti->substream->ops->pointer(ti->substream); - if (pos / period_size != ti->position / period_size) { - ti->need_update = 1; - ti->position = pos; - updates++; - } - pos %= period_size; - pos = period_size - pos; - ti->frag_count = div_u64((u64)pos * CT_TIMER_FREQ + - rate - 1, rate); - } - if (ti->need_update && !can_update) - min_intr = 0; /* pending to the next irq */ - if (ti->frag_count < min_intr) - min_intr = ti->frag_count; - } - - if (min_intr < MIN_TICKS) - min_intr = MIN_TICKS; - ct_xfitimer_irq_rearm(atimer, min_intr); - atimer->reprogram = 0; /* clear flag */ - return updates; -} - -/* look through the instance list and call period_elapsed if needed */ -static void ct_xfitimer_check_period(struct ct_timer *atimer) -{ - struct ct_timer_instance *ti; - unsigned long flags; - - spin_lock_irqsave(&atimer->list_lock, flags); - list_for_each_entry(ti, &atimer->instance_head, instance_list) { - if (ti->running && ti->need_update) { - ti->need_update = 0; - ti->apcm->interrupt(ti->apcm); - } - } - spin_unlock_irqrestore(&atimer->list_lock, flags); -} - -/* Handle timer-interrupt */ -static void ct_xfitimer_callback(struct ct_timer *atimer) -{ - int update; - unsigned long flags; - - spin_lock_irqsave(&atimer->lock, flags); - atimer->irq_handling = 1; - do { - update = ct_xfitimer_reprogram(atimer, 1); - spin_unlock(&atimer->lock); - if (update) - ct_xfitimer_check_period(atimer); - spin_lock(&atimer->lock); - } while (atimer->reprogram); - atimer->irq_handling = 0; - spin_unlock_irqrestore(&atimer->lock, flags); -} - -static void ct_xfitimer_prepare(struct ct_timer_instance *ti) -{ - ti->frag_count = ti->substream->runtime->period_size; - ti->running = 0; - ti->need_update = 0; -} - - -/* start/stop the timer */ -static void ct_xfitimer_update(struct ct_timer *atimer) -{ - unsigned long flags; - - spin_lock_irqsave(&atimer->lock, flags); - if (atimer->irq_handling) { - /* reached from IRQ handler; let it handle later */ - atimer->reprogram = 1; - spin_unlock_irqrestore(&atimer->lock, flags); - return; - } - - ct_xfitimer_irq_stop(atimer); - ct_xfitimer_reprogram(atimer, 0); - spin_unlock_irqrestore(&atimer->lock, flags); -} - -static void ct_xfitimer_start(struct ct_timer_instance *ti) -{ - struct ct_timer *atimer = ti->timer_base; - unsigned long flags; - - spin_lock_irqsave(&atimer->lock, flags); - if (list_empty(&ti->running_list)) - atimer->wc = ct_xfitimer_get_wc(atimer); - ti->running = 1; - ti->need_update = 0; - list_add(&ti->running_list, &atimer->running_head); - spin_unlock_irqrestore(&atimer->lock, flags); - ct_xfitimer_update(atimer); -} - -static void ct_xfitimer_stop(struct ct_timer_instance *ti) -{ - struct ct_timer *atimer = ti->timer_base; - unsigned long flags; - - spin_lock_irqsave(&atimer->lock, flags); - list_del_init(&ti->running_list); - ti->running = 0; - spin_unlock_irqrestore(&atimer->lock, flags); - ct_xfitimer_update(atimer); -} - -static void ct_xfitimer_free_global(struct ct_timer *atimer) -{ - ct_xfitimer_irq_stop(atimer); -} - -static struct ct_timer_ops ct_xfitimer_ops = { - .prepare = ct_xfitimer_prepare, - .start = ct_xfitimer_start, - .stop = ct_xfitimer_stop, - .interrupt = ct_xfitimer_callback, - .free_global = ct_xfitimer_free_global, -}; - -/* - * timer instance - */ - -struct ct_timer_instance * -ct_timer_instance_new(struct ct_timer *atimer, struct ct_atc_pcm *apcm) -{ - struct ct_timer_instance *ti; - - ti = kzalloc(sizeof(*ti), GFP_KERNEL); - if (!ti) - return NULL; - spin_lock_init(&ti->lock); - INIT_LIST_HEAD(&ti->instance_list); - INIT_LIST_HEAD(&ti->running_list); - ti->timer_base = atimer; - ti->apcm = apcm; - ti->substream = apcm->substream; - if (atimer->ops->init) - atimer->ops->init(ti); - - spin_lock_irq(&atimer->list_lock); - list_add(&ti->instance_list, &atimer->instance_head); - spin_unlock_irq(&atimer->list_lock); - - return ti; -} - -void ct_timer_prepare(struct ct_timer_instance *ti) -{ - if (ti->timer_base->ops->prepare) - ti->timer_base->ops->prepare(ti); - ti->position = 0; - ti->running = 0; -} - -void ct_timer_start(struct ct_timer_instance *ti) -{ - struct ct_timer *atimer = ti->timer_base; - atimer->ops->start(ti); -} - -void ct_timer_stop(struct ct_timer_instance *ti) -{ - struct ct_timer *atimer = ti->timer_base; - atimer->ops->stop(ti); -} - -void ct_timer_instance_free(struct ct_timer_instance *ti) -{ - struct ct_timer *atimer = ti->timer_base; - - atimer->ops->stop(ti); /* to be sure */ - if (atimer->ops->free_instance) - atimer->ops->free_instance(ti); - - spin_lock_irq(&atimer->list_lock); - list_del(&ti->instance_list); - spin_unlock_irq(&atimer->list_lock); - - kfree(ti); -} - -/* - * timer manager - */ - -static void ct_timer_interrupt(void *data, unsigned int status) -{ - struct ct_timer *timer = data; - - /* Interval timer interrupt */ - if ((status & IT_INT) && timer->ops->interrupt) - timer->ops->interrupt(timer); -} - -struct ct_timer *ct_timer_new(struct ct_atc *atc) -{ - struct ct_timer *atimer; - struct hw *hw; - - atimer = kzalloc(sizeof(*atimer), GFP_KERNEL); - if (!atimer) - return NULL; - spin_lock_init(&atimer->lock); - spin_lock_init(&atimer->list_lock); - INIT_LIST_HEAD(&atimer->instance_head); - INIT_LIST_HEAD(&atimer->running_head); - atimer->atc = atc; - hw = atc->hw; - if (!use_system_timer && hw->set_timer_irq) { - snd_printd(KERN_INFO "ctxfi: Use xfi-native timer\n"); - atimer->ops = &ct_xfitimer_ops; - hw->irq_callback_data = atimer; - hw->irq_callback = ct_timer_interrupt; - } else { - snd_printd(KERN_INFO "ctxfi: Use system timer\n"); - atimer->ops = &ct_systimer_ops; - } - return atimer; -} - -void ct_timer_free(struct ct_timer *atimer) -{ - struct hw *hw = atimer->atc->hw; - hw->irq_callback = NULL; - if (atimer->ops->free_global) - atimer->ops->free_global(atimer); - kfree(atimer); -} - diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/cttimer.h b/ANDROID_3.4.5/sound/pci/ctxfi/cttimer.h deleted file mode 100644 index 97934822..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/cttimer.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Timer handling - */ - -#ifndef __CTTIMER_H -#define __CTTIMER_H - -#include -#include -#include - -struct snd_pcm_substream; -struct ct_atc; -struct ct_atc_pcm; - -struct ct_timer; -struct ct_timer_instance; - -struct ct_timer *ct_timer_new(struct ct_atc *atc); -void ct_timer_free(struct ct_timer *atimer); - -struct ct_timer_instance * -ct_timer_instance_new(struct ct_timer *atimer, struct ct_atc_pcm *apcm); -void ct_timer_instance_free(struct ct_timer_instance *ti); -void ct_timer_start(struct ct_timer_instance *ti); -void ct_timer_stop(struct ct_timer_instance *ti); -void ct_timer_prepare(struct ct_timer_instance *ti); - -#endif /* __CTTIMER_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.c b/ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.c deleted file mode 100644 index 6109490b..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.c +++ /dev/null @@ -1,247 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctvmem.c - * - * @Brief - * This file contains the implementation of virtual memory management object - * for card device. - * - * @Author Liu Chun - * @Date Apr 1 2008 - */ - -#include "ctvmem.h" -#include -#include -#include -#include - -#define CT_PTES_PER_PAGE (CT_PAGE_SIZE / sizeof(void *)) -#define CT_ADDRS_PER_PAGE (CT_PTES_PER_PAGE * CT_PAGE_SIZE) - -/* * - * Find or create vm block based on requested @size. - * @size must be page aligned. - * */ -static struct ct_vm_block * -get_vm_block(struct ct_vm *vm, unsigned int size) -{ - struct ct_vm_block *block = NULL, *entry; - struct list_head *pos; - - size = CT_PAGE_ALIGN(size); - if (size > vm->size) { - printk(KERN_ERR "ctxfi: Fail! No sufficient device virtual " - "memory space available!\n"); - return NULL; - } - - mutex_lock(&vm->lock); - list_for_each(pos, &vm->unused) { - entry = list_entry(pos, struct ct_vm_block, list); - if (entry->size >= size) - break; /* found a block that is big enough */ - } - if (pos == &vm->unused) - goto out; - - if (entry->size == size) { - /* Move the vm node from unused list to used list directly */ - list_move(&entry->list, &vm->used); - vm->size -= size; - block = entry; - goto out; - } - - block = kzalloc(sizeof(*block), GFP_KERNEL); - if (!block) - goto out; - - block->addr = entry->addr; - block->size = size; - list_add(&block->list, &vm->used); - entry->addr += size; - entry->size -= size; - vm->size -= size; - - out: - mutex_unlock(&vm->lock); - return block; -} - -static void put_vm_block(struct ct_vm *vm, struct ct_vm_block *block) -{ - struct ct_vm_block *entry, *pre_ent; - struct list_head *pos, *pre; - - block->size = CT_PAGE_ALIGN(block->size); - - mutex_lock(&vm->lock); - list_del(&block->list); - vm->size += block->size; - - list_for_each(pos, &vm->unused) { - entry = list_entry(pos, struct ct_vm_block, list); - if (entry->addr >= (block->addr + block->size)) - break; /* found a position */ - } - if (pos == &vm->unused) { - list_add_tail(&block->list, &vm->unused); - entry = block; - } else { - if ((block->addr + block->size) == entry->addr) { - entry->addr = block->addr; - entry->size += block->size; - kfree(block); - } else { - __list_add(&block->list, pos->prev, pos); - entry = block; - } - } - - pos = &entry->list; - pre = pos->prev; - while (pre != &vm->unused) { - entry = list_entry(pos, struct ct_vm_block, list); - pre_ent = list_entry(pre, struct ct_vm_block, list); - if ((pre_ent->addr + pre_ent->size) > entry->addr) - break; - - pre_ent->size += entry->size; - list_del(pos); - kfree(entry); - pos = pre; - pre = pos->prev; - } - mutex_unlock(&vm->lock); -} - -/* Map host addr (kmalloced/vmalloced) to device logical addr. */ -static struct ct_vm_block * -ct_vm_map(struct ct_vm *vm, struct snd_pcm_substream *substream, int size) -{ - struct ct_vm_block *block; - unsigned int pte_start; - unsigned i, pages; - unsigned long *ptp; - - block = get_vm_block(vm, size); - if (block == NULL) { - printk(KERN_ERR "ctxfi: No virtual memory block that is big " - "enough to allocate!\n"); - return NULL; - } - - ptp = (unsigned long *)vm->ptp[0].area; - pte_start = (block->addr >> CT_PAGE_SHIFT); - pages = block->size >> CT_PAGE_SHIFT; - for (i = 0; i < pages; i++) { - unsigned long addr; - addr = snd_pcm_sgbuf_get_addr(substream, i << CT_PAGE_SHIFT); - ptp[pte_start + i] = addr; - } - - block->size = size; - return block; -} - -static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block) -{ - /* do unmapping */ - put_vm_block(vm, block); -} - -/* * - * return the host physical addr of the @index-th device - * page table page on success, or ~0UL on failure. - * The first returned ~0UL indicates the termination. - * */ -static dma_addr_t -ct_get_ptp_phys(struct ct_vm *vm, int index) -{ - dma_addr_t addr; - - addr = (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr; - - return addr; -} - -int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci) -{ - struct ct_vm *vm; - struct ct_vm_block *block; - int i, err = 0; - - *rvm = NULL; - - vm = kzalloc(sizeof(*vm), GFP_KERNEL); - if (!vm) - return -ENOMEM; - - mutex_init(&vm->lock); - - /* Allocate page table pages */ - for (i = 0; i < CT_PTP_NUM; i++) { - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(pci), - PAGE_SIZE, &vm->ptp[i]); - if (err < 0) - break; - } - if (err < 0) { - /* no page table pages are allocated */ - ct_vm_destroy(vm); - return -ENOMEM; - } - vm->size = CT_ADDRS_PER_PAGE * i; - vm->map = ct_vm_map; - vm->unmap = ct_vm_unmap; - vm->get_ptp_phys = ct_get_ptp_phys; - INIT_LIST_HEAD(&vm->unused); - INIT_LIST_HEAD(&vm->used); - block = kzalloc(sizeof(*block), GFP_KERNEL); - if (NULL != block) { - block->addr = 0; - block->size = vm->size; - list_add(&block->list, &vm->unused); - } - - *rvm = vm; - return 0; -} - -/* The caller must ensure no mapping pages are being used - * by hardware before calling this function */ -void ct_vm_destroy(struct ct_vm *vm) -{ - int i; - struct list_head *pos; - struct ct_vm_block *entry; - - /* free used and unused list nodes */ - while (!list_empty(&vm->used)) { - pos = vm->used.next; - list_del(pos); - entry = list_entry(pos, struct ct_vm_block, list); - kfree(entry); - } - while (!list_empty(&vm->unused)) { - pos = vm->unused.next; - list_del(pos); - entry = list_entry(pos, struct ct_vm_block, list); - kfree(entry); - } - - /* free allocated page table pages */ - for (i = 0; i < CT_PTP_NUM; i++) - snd_dma_free_pages(&vm->ptp[i]); - - vm->size = 0; - - kfree(vm); -} diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.h b/ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.h deleted file mode 100644 index e6da60eb..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/ctvmem.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - * - * @File ctvmem.h - * - * @Brief - * This file contains the definition of virtual memory management object - * for card device. - * - * @Author Liu Chun - * @Date Mar 28 2008 - */ - -#ifndef CTVMEM_H -#define CTVMEM_H - -#define CT_PTP_NUM 4 /* num of device page table pages */ - -#include -#include -#include -#include - -/* The chip can handle the page table of 4k pages - * (emu20k1 can handle even 8k pages, but we don't use it right now) - */ -#define CT_PAGE_SIZE 4096 -#define CT_PAGE_SHIFT 12 -#define CT_PAGE_MASK (~(PAGE_SIZE - 1)) -#define CT_PAGE_ALIGN(addr) ALIGN(addr, CT_PAGE_SIZE) - -struct ct_vm_block { - unsigned int addr; /* starting logical addr of this block */ - unsigned int size; /* size of this device virtual mem block */ - struct list_head list; -}; - -struct snd_pcm_substream; - -/* Virtual memory management object for card device */ -struct ct_vm { - struct snd_dma_buffer ptp[CT_PTP_NUM]; /* Device page table pages */ - unsigned int size; /* Available addr space in bytes */ - struct list_head unused; /* List of unused blocks */ - struct list_head used; /* List of used blocks */ - struct mutex lock; - - /* Map host addr (kmalloced/vmalloced) to device logical addr. */ - struct ct_vm_block *(*map)(struct ct_vm *, struct snd_pcm_substream *, - int size); - /* Unmap device logical addr area. */ - void (*unmap)(struct ct_vm *, struct ct_vm_block *block); - dma_addr_t (*get_ptp_phys)(struct ct_vm *vm, int index); -}; - -int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci); -void ct_vm_destroy(struct ct_vm *vm); - -#endif /* CTVMEM_H */ diff --git a/ANDROID_3.4.5/sound/pci/ctxfi/xfi.c b/ANDROID_3.4.5/sound/pci/ctxfi/xfi.c deleted file mode 100644 index 15d95d2b..00000000 --- a/ANDROID_3.4.5/sound/pci/ctxfi/xfi.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * xfi linux driver. - * - * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. - * - * This source file is released under GPL v2 license (no other versions). - * See the COPYING file included in the main directory of this source - * distribution for the license terms and conditions. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "ctatc.h" -#include "cthardware.h" - -MODULE_AUTHOR("Creative Technology Ltd"); -MODULE_DESCRIPTION("X-Fi driver version 1.03"); -MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs, Sound Blaster X-Fi}"); - -static unsigned int reference_rate = 48000; -static unsigned int multiple = 2; -MODULE_PARM_DESC(reference_rate, "Reference rate (default=48000)"); -module_param(reference_rate, uint, S_IRUGO); -MODULE_PARM_DESC(multiple, "Rate multiplier (default=2)"); -module_param(multiple, uint, S_IRUGO); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static unsigned int subsystem[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Creative X-Fi driver"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Creative X-Fi driver"); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Creative X-Fi driver"); -module_param_array(subsystem, int, NULL, 0444); -MODULE_PARM_DESC(subsystem, "Override subsystem ID for Creative X-Fi driver"); - -static DEFINE_PCI_DEVICE_TABLE(ct_pci_dev_ids) = { - /* only X-Fi is supported, so... */ - { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_20K1), - .driver_data = ATC20K1, - }, - { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_20K2), - .driver_data = ATC20K2, - }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, ct_pci_dev_ids); - -static int __devinit -ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct ct_atc *atc; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - - if (!enable[dev]) { - dev++; - return -ENOENT; - } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err) - return err; - if ((reference_rate != 48000) && (reference_rate != 44100)) { - printk(KERN_ERR "ctxfi: Invalid reference_rate value %u!!!\n", - reference_rate); - printk(KERN_ERR "ctxfi: The valid values for reference_rate " - "are 48000 and 44100, Value 48000 is assumed.\n"); - reference_rate = 48000; - } - if ((multiple != 1) && (multiple != 2) && (multiple != 4)) { - printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n", - multiple); - printk(KERN_ERR "ctxfi: The valid values for multiple are " - "1, 2 and 4, Value 2 is assumed.\n"); - multiple = 2; - } - err = ct_atc_create(card, pci, reference_rate, multiple, - pci_id->driver_data, subsystem[dev], &atc); - if (err < 0) - goto error; - - card->private_data = atc; - - /* Create alsa devices supported by this card */ - err = ct_atc_create_alsa_devs(atc); - if (err < 0) - goto error; - - strcpy(card->driver, "SB-XFi"); - strcpy(card->shortname, "Creative X-Fi"); - snprintf(card->longname, sizeof(card->longname), "%s %s %s", - card->shortname, atc->chip_name, atc->model_name); - - err = snd_card_register(card); - if (err < 0) - goto error; - - pci_set_drvdata(pci, card); - dev++; - - return 0; - -error: - snd_card_free(card); - return err; -} - -static void __devexit ct_card_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -#ifdef CONFIG_PM -static int ct_card_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct ct_atc *atc = card->private_data; - - return atc->suspend(atc, state); -} - -static int ct_card_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct ct_atc *atc = card->private_data; - - return atc->resume(atc); -} -#endif - -static struct pci_driver ct_driver = { - .name = KBUILD_MODNAME, - .id_table = ct_pci_dev_ids, - .probe = ct_card_probe, - .remove = __devexit_p(ct_card_remove), -#ifdef CONFIG_PM - .suspend = ct_card_suspend, - .resume = ct_card_resume, -#endif -}; - -static int __init ct_card_init(void) -{ - return pci_register_driver(&ct_driver); -} - -static void __exit ct_card_exit(void) -{ - pci_unregister_driver(&ct_driver); -} - -module_init(ct_card_init) -module_exit(ct_card_exit) diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/Makefile b/ANDROID_3.4.5/sound/pci/echoaudio/Makefile deleted file mode 100644 index 1361de77..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# -# Makefile for ALSA Echoaudio soundcard drivers -# Copyright (c) 2003 by Giuliano Pochini -# - -snd-darla20-objs := darla20.o -snd-gina20-objs := gina20.o -snd-layla20-objs := layla20.o -snd-darla24-objs := darla24.o -snd-gina24-objs := gina24.o -snd-layla24-objs := layla24.o -snd-mona-objs := mona.o -snd-mia-objs := mia.o -snd-echo3g-objs := echo3g.o -snd-indigo-objs := indigo.o -snd-indigoio-objs := indigoio.o -snd-indigodj-objs := indigodj.o -snd-indigoiox-objs := indigoiox.o -snd-indigodjx-objs := indigodjx.o - -obj-$(CONFIG_SND_DARLA20) += snd-darla20.o -obj-$(CONFIG_SND_GINA20) += snd-gina20.o -obj-$(CONFIG_SND_LAYLA20) += snd-layla20.o -obj-$(CONFIG_SND_DARLA24) += snd-darla24.o -obj-$(CONFIG_SND_GINA24) += snd-gina24.o -obj-$(CONFIG_SND_LAYLA24) += snd-layla24.o -obj-$(CONFIG_SND_MONA) += snd-mona.o -obj-$(CONFIG_SND_MIA) += snd-mia.o -obj-$(CONFIG_SND_ECHO3G) += snd-echo3g.o -obj-$(CONFIG_SND_INDIGO) += snd-indigo.o -obj-$(CONFIG_SND_INDIGOIO) += snd-indigoio.o -obj-$(CONFIG_SND_INDIGODJ) += snd-indigodj.o -obj-$(CONFIG_SND_INDIGOIOX) += snd-indigoiox.o -obj-$(CONFIG_SND_INDIGODJX) += snd-indigodjx.o diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/darla20.c b/ANDROID_3.4.5/sound/pci/echoaudio/darla20.c deleted file mode 100644 index d47e72ae..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/darla20.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHOGALS_FAMILY -#define ECHOCARD_DARLA20 -#define ECHOCARD_NAME "Darla20" -#define ECHOCARD_HAS_MONITOR - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 0 */ -#define PX_NUM 10 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 0 */ -#define BX_ANALOG_IN 8 /* 2 */ -#define BX_DIGITAL_IN 10 /* 0 */ -#define BX_NUM 10 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/darla20_dsp.fw"); - -#define FW_DARLA20_DSP 0 - -static const struct firmware card_fw[] = { - {0, "darla20_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x1801, 0xECC0, 0x0010, 0, 0, 0}, /* DSP 56301 Darla20 rev.0 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "darla20_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/darla20_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/darla20_dsp.c deleted file mode 100644 index 20c7cbc8..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/darla20_dsp.c +++ /dev/null @@ -1,130 +0,0 @@ -/*************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Darla20\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != DARLA20)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_DARLA20_DSP; - chip->spdif_status = GD_SPDIF_STATUS_UNDEF; - chip->clock_state = GD_CLOCK_UNDEF; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - return init_line_levels(chip); -} - - - -/* The Darla20 has no external clock sources */ -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The Darla20 has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u8 clock_state, spdif_status; - - if (wait_handshake(chip)) - return -EIO; - - switch (rate) { - case 44100: - clock_state = GD_CLOCK_44; - spdif_status = GD_SPDIF_STATUS_44; - break; - case 48000: - clock_state = GD_CLOCK_48; - spdif_status = GD_SPDIF_STATUS_48; - break; - default: - clock_state = GD_CLOCK_NOCHANGE; - spdif_status = GD_SPDIF_STATUS_NOCHANGE; - break; - } - - if (chip->clock_state == clock_state) - clock_state = GD_CLOCK_NOCHANGE; - if (spdif_status == chip->spdif_status) - spdif_status = GD_SPDIF_STATUS_NOCHANGE; - - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->comm_page->gd_clock_state = clock_state; - chip->comm_page->gd_spdif_status = spdif_status; - chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */ - - /* Save the new audio state if it changed */ - if (clock_state != GD_CLOCK_NOCHANGE) - chip->clock_state = clock_state; - if (spdif_status != GD_SPDIF_STATUS_NOCHANGE) - chip->spdif_status = spdif_status; - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/darla24.c b/ANDROID_3.4.5/sound/pci/echoaudio/darla24.c deleted file mode 100644 index 413acf70..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/darla24.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHOGALS_FAMILY -#define ECHOCARD_DARLA24 -#define ECHOCARD_NAME "Darla24" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_SUPER_INTERLEAVE - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 0 */ -#define PX_NUM 10 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 0 */ -#define BX_ANALOG_IN 8 /* 2 */ -#define BX_DIGITAL_IN 10 /* 0 */ -#define BX_NUM 10 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/darla24_dsp.fw"); - -#define FW_DARLA24_DSP 0 - -static const struct firmware card_fw[] = { - {0, "darla24_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x1801, 0xECC0, 0x0040, 0, 0, 0}, /* DSP 56301 Darla24 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0041, 0, 0, 0}, /* DSP 56301 Darla24 rev.1 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "darla24_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/darla24_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/darla24_dsp.c deleted file mode 100644 index 6da6663e..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/darla24_dsp.c +++ /dev/null @@ -1,162 +0,0 @@ -/*************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Darla24\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != DARLA24)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_DARLA24_DSP; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_ESYNC; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_ESYNC) - clock_bits |= ECHO_CLOCK_BIT_ESYNC; - - return clock_bits; -} - - - -/* The Darla24 has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u8 clock; - - switch (rate) { - case 96000: - clock = GD24_96000; - break; - case 88200: - clock = GD24_88200; - break; - case 48000: - clock = GD24_48000; - break; - case 44100: - clock = GD24_44100; - break; - case 32000: - clock = GD24_32000; - break; - case 22050: - clock = GD24_22050; - break; - case 16000: - clock = GD24_16000; - break; - case 11025: - clock = GD24_11025; - break; - case 8000: - clock = GD24_8000; - break; - default: - DE_ACT(("set_sample_rate: Error, invalid sample rate %d\n", - rate)); - return -EINVAL; - } - - if (wait_handshake(chip)) - return -EIO; - - DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); - chip->sample_rate = rate; - - /* Override the sample rate if this card is set to Echo sync. */ - if (chip->input_clock == ECHO_CLOCK_ESYNC) - clock = GD24_EXT_SYNC; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP ? */ - chip->comm_page->gd_clock_state = clock; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - if (snd_BUG_ON(clock != ECHO_CLOCK_INTERNAL && - clock != ECHO_CLOCK_ESYNC)) - return -EINVAL; - chip->input_clock = clock; - return set_sample_rate(chip, chip->sample_rate); -} - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/echo3g.c b/ANDROID_3.4.5/sound/pci/echoaudio/echo3g.c deleted file mode 100644 index 1ec4edca..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/echo3g.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHO3G_FAMILY -#define ECHOCARD_ECHO3G -#define ECHOCARD_NAME "Echo3G" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH -#define ECHOCARD_HAS_ADAT 6 -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 -#define ECHOCARD_HAS_MIDI -#define ECHOCARD_HAS_PHANTOM_POWER - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 -#define PX_DIGITAL_OUT chip->px_digital_out -#define PX_ANALOG_IN chip->px_analog_in -#define PX_DIGITAL_IN chip->px_digital_in -#define PX_NUM chip->px_num - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 -#define BX_DIGITAL_OUT chip->bx_digital_out -#define BX_ANALOG_IN chip->bx_analog_in -#define BX_DIGITAL_IN chip->bx_digital_in -#define BX_NUM chip->bx_num - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/echo3g_dsp.fw"); -MODULE_FIRMWARE("ea/3g_asic.fw"); - -#define FW_361_LOADER 0 -#define FW_ECHO3G_DSP 1 -#define FW_3G_ASIC 2 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "echo3g_dsp.fw"}, - {0, "3g_asic.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x3410, 0xECC0, 0x0100, 0, 0, 0}, /* Echo 3G */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 32000, - .rate_max = 100000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "echo3g_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio_3g.c" -#include "echoaudio.c" -#include "midi.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/echo3g_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/echo3g_dsp.c deleted file mode 100644 index 3cdc2ee2..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/echo3g_dsp.c +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - -static int load_asic(struct echoaudio *chip); -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode); -static int set_digital_mode(struct echoaudio *chip, u8 mode); -static int check_asic_status(struct echoaudio *chip); -static int set_sample_rate(struct echoaudio *chip, u32 rate); -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int set_phantom_power(struct echoaudio *chip, char on); -static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, - char force); - -#include - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - local_irq_enable(); - DE_INIT(("init_hw() - Echo3G\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != ECHO3G)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->comm_page->e3g_frq_register = - cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2); - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; - chip->dsp_code_to_load = FW_ECHO3G_DSP; - - /* Load the DSP code and the ASIC on the PCI card and get - what type of external box is attached */ - err = load_firmware(chip); - - if (err < 0) { - return err; - } else if (err == E3G_GINA3G_BOX_TYPE) { - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_ADAT; - chip->card_name = "Gina3G"; - chip->px_digital_out = chip->bx_digital_out = 6; - chip->px_analog_in = chip->bx_analog_in = 14; - chip->px_digital_in = chip->bx_digital_in = 16; - chip->px_num = chip->bx_num = 24; - chip->has_phantom_power = TRUE; - chip->hasnt_input_nominal_level = TRUE; - } else if (err == E3G_LAYLA3G_BOX_TYPE) { - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_ADAT | - ECHO_CLOCK_BIT_WORD; - chip->card_name = "Layla3G"; - chip->px_digital_out = chip->bx_digital_out = 8; - chip->px_analog_in = chip->bx_analog_in = 16; - chip->px_digital_in = chip->bx_digital_in = 24; - chip->px_num = chip->bx_num = 32; - } else { - return -ENODEV; - } - - chip->digital_modes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->non_audio_spdif = FALSE; - chip->bad_board = FALSE; - chip->phantom_power = FALSE; - return init_line_levels(chip); -} - - - -static int set_phantom_power(struct echoaudio *chip, char on) -{ - u32 control_reg = le32_to_cpu(chip->comm_page->control_register); - - if (on) - control_reg |= E3G_PHANTOM_POWER; - else - control_reg &= ~E3G_PHANTOM_POWER; - - chip->phantom_power = on; - return write_control_reg(chip, control_reg, - le32_to_cpu(chip->comm_page->e3g_frq_register), - 0); -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.c b/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.c deleted file mode 100644 index 595c11f9..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.c +++ /dev/null @@ -1,2360 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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 - -MODULE_AUTHOR("Giuliano Pochini "); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Echoaudio " ECHOCARD_NAME " soundcards driver"); -MODULE_SUPPORTED_DEVICE("{{Echoaudio," ECHOCARD_NAME "}}"); -MODULE_DEVICE_TABLE(pci, snd_echo_ids); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " ECHOCARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " ECHOCARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard."); - -static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999}; -static const DECLARE_TLV_DB_SCALE(db_scale_output_gain, -12800, 100, 1); - - - -static int get_firmware(const struct firmware **fw_entry, - struct echoaudio *chip, const short fw_index) -{ - int err; - char name[30]; - -#ifdef CONFIG_PM - if (chip->fw_cache[fw_index]) { - DE_ACT(("firmware requested: %s is cached\n", card_fw[fw_index].data)); - *fw_entry = chip->fw_cache[fw_index]; - return 0; - } -#endif - - DE_ACT(("firmware requested: %s\n", card_fw[fw_index].data)); - snprintf(name, sizeof(name), "ea/%s", card_fw[fw_index].data); - err = request_firmware(fw_entry, name, pci_device(chip)); - if (err < 0) - snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err); -#ifdef CONFIG_PM - else - chip->fw_cache[fw_index] = *fw_entry; -#endif - return err; -} - - - -static void free_firmware(const struct firmware *fw_entry) -{ -#ifdef CONFIG_PM - DE_ACT(("firmware not released (kept in cache)\n")); -#else - release_firmware(fw_entry); - DE_ACT(("firmware released\n")); -#endif -} - - - -static void free_firmware_cache(struct echoaudio *chip) -{ -#ifdef CONFIG_PM - int i; - - for (i = 0; i < 8 ; i++) - if (chip->fw_cache[i]) { - release_firmware(chip->fw_cache[i]); - DE_ACT(("release_firmware(%d)\n", i)); - } - - DE_ACT(("firmware_cache released\n")); -#endif -} - - - -/****************************************************************************** - PCM interface -******************************************************************************/ - -static void audiopipe_free(struct snd_pcm_runtime *runtime) -{ - struct audiopipe *pipe = runtime->private_data; - - if (pipe->sgpage.area) - snd_dma_free_pages(&pipe->sgpage); - kfree(pipe); -} - - - -static int hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_mask fmt; - - snd_mask_any(&fmt); - -#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - /* >=2 channels cannot be S32_BE */ - if (c->min == 2) { - fmt.bits[0] &= ~SNDRV_PCM_FMTBIT_S32_BE; - return snd_mask_refine(f, &fmt); - } -#endif - /* > 2 channels cannot be U8 and S32_BE */ - if (c->min > 2) { - fmt.bits[0] &= ~(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_BE); - return snd_mask_refine(f, &fmt); - } - /* Mono is ok with any format */ - return 0; -} - - - -static int hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_interval ch; - - snd_interval_any(&ch); - - /* S32_BE is mono (and stereo) only */ - if (f->bits[0] == SNDRV_PCM_FMTBIT_S32_BE) { - ch.min = 1; -#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - ch.max = 2; -#else - ch.max = 1; -#endif - ch.integer = 1; - return snd_interval_refine(c, &ch); - } - /* U8 can be only mono or stereo */ - if (f->bits[0] == SNDRV_PCM_FMTBIT_U8) { - ch.min = 1; - ch.max = 2; - ch.integer = 1; - return snd_interval_refine(c, &ch); - } - /* S16_LE, S24_3LE and S32_LE support any number of channels. */ - return 0; -} - - - -static int hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_mask fmt; - u64 fmask; - snd_mask_any(&fmt); - - fmask = fmt.bits[0] + ((u64)fmt.bits[1] << 32); - - /* >2 channels must be S16_LE, S24_3LE or S32_LE */ - if (c->min > 2) { - fmask &= SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE; - /* 1 channel must be S32_BE or S32_LE */ - } else if (c->max == 1) - fmask &= SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE; -#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - /* 2 channels cannot be S32_BE */ - else if (c->min == 2 && c->max == 2) - fmask &= ~SNDRV_PCM_FMTBIT_S32_BE; -#endif - else - return 0; - - fmt.bits[0] &= (u32)fmask; - fmt.bits[1] &= (u32)(fmask >> 32); - return snd_mask_refine(f, &fmt); -} - - - -static int hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_interval ch; - u64 fmask; - - snd_interval_any(&ch); - ch.integer = 1; - fmask = f->bits[0] + ((u64)f->bits[1] << 32); - - /* S32_BE is mono (and stereo) only */ - if (fmask == SNDRV_PCM_FMTBIT_S32_BE) { - ch.min = 1; -#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - ch.max = 2; -#else - ch.max = 1; -#endif - /* U8 is stereo only */ - } else if (fmask == SNDRV_PCM_FMTBIT_U8) - ch.min = ch.max = 2; - /* S16_LE and S24_3LE must be at least stereo */ - else if (!(fmask & ~(SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE))) - ch.min = 2; - else - return 0; - - return snd_interval_refine(c, &ch); -} - - - -/* Since the sample rate is a global setting, do allow the user to change the -sample rate only if there is only one pcm device open. */ -static int hw_rule_sample_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct echoaudio *chip = rule->private; - struct snd_interval fixed; - - if (!chip->can_set_rate) { - snd_interval_any(&fixed); - fixed.min = fixed.max = chip->sample_rate; - return snd_interval_refine(rate, &fixed); - } - return 0; -} - - -static int pcm_open(struct snd_pcm_substream *substream, - signed char max_channels) -{ - struct echoaudio *chip; - struct snd_pcm_runtime *runtime; - struct audiopipe *pipe; - int err, i; - - if (max_channels <= 0) - return -EAGAIN; - - chip = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - pipe = kzalloc(sizeof(struct audiopipe), GFP_KERNEL); - if (!pipe) - return -ENOMEM; - pipe->index = -1; /* Not configured yet */ - - /* Set up hw capabilities and contraints */ - memcpy(&pipe->hw, &pcm_hardware_skel, sizeof(struct snd_pcm_hardware)); - DE_HWP(("max_channels=%d\n", max_channels)); - pipe->constr.list = channels_list; - pipe->constr.mask = 0; - for (i = 0; channels_list[i] <= max_channels; i++); - pipe->constr.count = i; - if (pipe->hw.channels_max > max_channels) - pipe->hw.channels_max = max_channels; - if (chip->digital_mode == DIGITAL_MODE_ADAT) { - pipe->hw.rate_max = 48000; - pipe->hw.rates &= SNDRV_PCM_RATE_8000_48000; - } - - runtime->hw = pipe->hw; - runtime->private_data = pipe; - runtime->private_free = audiopipe_free; - snd_pcm_set_sync(substream); - - /* Only mono and any even number of channels are allowed */ - if ((err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &pipe->constr)) < 0) - return err; - - /* All periods should have the same size */ - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - /* The hw accesses memory in chunks 32 frames long and they should be - 32-bytes-aligned. It's not a requirement, but it seems that IRQs are - generated with a resolution of 32 frames. Thus we need the following */ - if ((err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 32)) < 0) - return err; - if ((err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - 32)) < 0) - return err; - - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - hw_rule_sample_rate, chip, - SNDRV_PCM_HW_PARAM_RATE, -1)) < 0) - return err; - - /* Finally allocate a page for the scatter-gather list */ - if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - PAGE_SIZE, &pipe->sgpage)) < 0) { - DE_HWP(("s-g list allocation failed\n")); - return err; - } - - return 0; -} - - - -static int pcm_analog_in_open(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int err; - - DE_ACT(("pcm_analog_in_open\n")); - if ((err = pcm_open(substream, num_analog_busses_in(chip) - - substream->number)) < 0) - return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_capture_channels_by_format, NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) - return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_capture_format_by_channels, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) - return err; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - DE_HWP(("pcm_analog_in_open cs=%d oc=%d r=%d\n", - chip->can_set_rate, atomic_read(&chip->opencount), - chip->sample_rate)); - return 0; -} - - - -static int pcm_analog_out_open(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int max_channels, err; - -#ifdef ECHOCARD_HAS_VMIXER - max_channels = num_pipes_out(chip); -#else - max_channels = num_analog_busses_out(chip); -#endif - DE_ACT(("pcm_analog_out_open\n")); - if ((err = pcm_open(substream, max_channels - substream->number)) < 0) - return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_playback_channels_by_format, - NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) - return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_playback_format_by_channels, - NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) - return err; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - DE_HWP(("pcm_analog_out_open cs=%d oc=%d r=%d\n", - chip->can_set_rate, atomic_read(&chip->opencount), - chip->sample_rate)); - return 0; -} - - - -#ifdef ECHOCARD_HAS_DIGITAL_IO - -static int pcm_digital_in_open(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int err, max_channels; - - DE_ACT(("pcm_digital_in_open\n")); - max_channels = num_digital_busses_in(chip) - substream->number; - mutex_lock(&chip->mode_mutex); - if (chip->digital_mode == DIGITAL_MODE_ADAT) - err = pcm_open(substream, max_channels); - else /* If the card has ADAT, subtract the 6 channels - * that S/PDIF doesn't have - */ - err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT); - - if (err < 0) - goto din_exit; - - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_capture_channels_by_format, NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) - goto din_exit; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_capture_format_by_channels, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) - goto din_exit; - - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - -din_exit: - mutex_unlock(&chip->mode_mutex); - return err; -} - - - -#ifndef ECHOCARD_HAS_VMIXER /* See the note in snd_echo_new_pcm() */ - -static int pcm_digital_out_open(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int err, max_channels; - - DE_ACT(("pcm_digital_out_open\n")); - max_channels = num_digital_busses_out(chip) - substream->number; - mutex_lock(&chip->mode_mutex); - if (chip->digital_mode == DIGITAL_MODE_ADAT) - err = pcm_open(substream, max_channels); - else /* If the card has ADAT, subtract the 6 channels - * that S/PDIF doesn't have - */ - err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT); - - if (err < 0) - goto dout_exit; - - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_playback_channels_by_format, - NULL, SNDRV_PCM_HW_PARAM_FORMAT, - -1)) < 0) - goto dout_exit; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_playback_format_by_channels, - NULL, SNDRV_PCM_HW_PARAM_CHANNELS, - -1)) < 0) - goto dout_exit; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; -dout_exit: - mutex_unlock(&chip->mode_mutex); - return err; -} - -#endif /* !ECHOCARD_HAS_VMIXER */ - -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - - - -static int pcm_close(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int oc; - - /* Nothing to do here. Audio is already off and pipe will be - * freed by its callback - */ - DE_ACT(("pcm_close\n")); - - atomic_dec(&chip->opencount); - oc = atomic_read(&chip->opencount); - DE_ACT(("pcm_close oc=%d cs=%d rs=%d\n", oc, - chip->can_set_rate, chip->rate_set)); - if (oc < 2) - chip->can_set_rate = 1; - if (oc == 0) - chip->rate_set = 0; - DE_ACT(("pcm_close2 oc=%d cs=%d rs=%d\n", oc, - chip->can_set_rate,chip->rate_set)); - - return 0; -} - - - -/* Channel allocation and scatter-gather list setup */ -static int init_engine(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params, - int pipe_index, int interleave) -{ - struct echoaudio *chip; - int err, per, rest, page, edge, offs; - struct audiopipe *pipe; - - chip = snd_pcm_substream_chip(substream); - pipe = (struct audiopipe *) substream->runtime->private_data; - - /* Sets up che hardware. If it's already initialized, reset and - * redo with the new parameters - */ - spin_lock_irq(&chip->lock); - if (pipe->index >= 0) { - DE_HWP(("hwp_ie free(%d)\n", pipe->index)); - err = free_pipes(chip, pipe); - snd_BUG_ON(err); - chip->substream[pipe->index] = NULL; - } - - err = allocate_pipes(chip, pipe, pipe_index, interleave); - if (err < 0) { - spin_unlock_irq(&chip->lock); - DE_ACT((KERN_NOTICE "allocate_pipes(%d) err=%d\n", - pipe_index, err)); - return err; - } - spin_unlock_irq(&chip->lock); - DE_ACT((KERN_NOTICE "allocate_pipes()=%d\n", pipe_index)); - - DE_HWP(("pcm_hw_params (bufsize=%dB periods=%d persize=%dB)\n", - params_buffer_bytes(hw_params), params_periods(hw_params), - params_period_bytes(hw_params))); - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) { - snd_printk(KERN_ERR "malloc_pages err=%d\n", err); - spin_lock_irq(&chip->lock); - free_pipes(chip, pipe); - spin_unlock_irq(&chip->lock); - pipe->index = -1; - return err; - } - - sglist_init(chip, pipe); - edge = PAGE_SIZE; - for (offs = page = per = 0; offs < params_buffer_bytes(hw_params); - per++) { - rest = params_period_bytes(hw_params); - if (offs + rest > params_buffer_bytes(hw_params)) - rest = params_buffer_bytes(hw_params) - offs; - while (rest) { - dma_addr_t addr; - addr = snd_pcm_sgbuf_get_addr(substream, offs); - if (rest <= edge - offs) { - sglist_add_mapping(chip, pipe, addr, rest); - sglist_add_irq(chip, pipe); - offs += rest; - rest = 0; - } else { - sglist_add_mapping(chip, pipe, addr, - edge - offs); - rest -= edge - offs; - offs = edge; - } - if (offs == edge) { - edge += PAGE_SIZE; - page++; - } - } - } - - /* Close the ring buffer */ - sglist_wrap(chip, pipe); - - /* This stuff is used by the irq handler, so it must be - * initialized before chip->substream - */ - chip->last_period[pipe_index] = 0; - pipe->last_counter = 0; - pipe->position = 0; - smp_wmb(); - chip->substream[pipe_index] = substream; - chip->rate_set = 1; - spin_lock_irq(&chip->lock); - set_sample_rate(chip, hw_params->rate_num / hw_params->rate_den); - spin_unlock_irq(&chip->lock); - DE_HWP(("pcm_hw_params ok\n")); - return 0; -} - - - -static int pcm_analog_in_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - - return init_engine(substream, hw_params, px_analog_in(chip) + - substream->number, params_channels(hw_params)); -} - - - -static int pcm_analog_out_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return init_engine(substream, hw_params, substream->number, - params_channels(hw_params)); -} - - - -#ifdef ECHOCARD_HAS_DIGITAL_IO - -static int pcm_digital_in_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - - return init_engine(substream, hw_params, px_digital_in(chip) + - substream->number, params_channels(hw_params)); -} - - - -#ifndef ECHOCARD_HAS_VMIXER /* See the note in snd_echo_new_pcm() */ -static int pcm_digital_out_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - - return init_engine(substream, hw_params, px_digital_out(chip) + - substream->number, params_channels(hw_params)); -} -#endif /* !ECHOCARD_HAS_VMIXER */ - -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - - - -static int pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip; - struct audiopipe *pipe; - - chip = snd_pcm_substream_chip(substream); - pipe = (struct audiopipe *) substream->runtime->private_data; - - spin_lock_irq(&chip->lock); - if (pipe->index >= 0) { - DE_HWP(("pcm_hw_free(%d)\n", pipe->index)); - free_pipes(chip, pipe); - chip->substream[pipe->index] = NULL; - pipe->index = -1; - } - spin_unlock_irq(&chip->lock); - - DE_HWP(("pcm_hw_freed\n")); - snd_pcm_lib_free_pages(substream); - return 0; -} - - - -static int pcm_prepare(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct audioformat format; - int pipe_index = ((struct audiopipe *)runtime->private_data)->index; - - DE_HWP(("Prepare rate=%d format=%d channels=%d\n", - runtime->rate, runtime->format, runtime->channels)); - format.interleave = runtime->channels; - format.data_are_bigendian = 0; - format.mono_to_stereo = 0; - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U8: - format.bits_per_sample = 8; - break; - case SNDRV_PCM_FORMAT_S16_LE: - format.bits_per_sample = 16; - break; - case SNDRV_PCM_FORMAT_S24_3LE: - format.bits_per_sample = 24; - break; - case SNDRV_PCM_FORMAT_S32_BE: - format.data_are_bigendian = 1; - case SNDRV_PCM_FORMAT_S32_LE: - format.bits_per_sample = 32; - break; - default: - DE_HWP(("Prepare error: unsupported format %d\n", - runtime->format)); - return -EINVAL; - } - - if (snd_BUG_ON(pipe_index >= px_num(chip))) - return -EINVAL; - if (snd_BUG_ON(!is_pipe_allocated(chip, pipe_index))) - return -EINVAL; - set_audio_format(chip, pipe_index, &format); - return 0; -} - - - -static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct audiopipe *pipe = runtime->private_data; - int i, err; - u32 channelmask = 0; - struct snd_pcm_substream *s; - - snd_pcm_group_for_each_entry(s, substream) { - for (i = 0; i < DSP_MAXPIPES; i++) { - if (s == chip->substream[i]) { - channelmask |= 1 << i; - snd_pcm_trigger_done(s, substream); - } - } - } - - spin_lock(&chip->lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - DE_ACT(("pcm_trigger resume\n")); - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - DE_ACT(("pcm_trigger start\n")); - for (i = 0; i < DSP_MAXPIPES; i++) { - if (channelmask & (1 << i)) { - pipe = chip->substream[i]->runtime->private_data; - switch (pipe->state) { - case PIPE_STATE_STOPPED: - chip->last_period[i] = 0; - pipe->last_counter = 0; - pipe->position = 0; - *pipe->dma_counter = 0; - case PIPE_STATE_PAUSED: - pipe->state = PIPE_STATE_STARTED; - break; - case PIPE_STATE_STARTED: - break; - } - } - } - err = start_transport(chip, channelmask, - chip->pipe_cyclic_mask); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - DE_ACT(("pcm_trigger suspend\n")); - case SNDRV_PCM_TRIGGER_STOP: - DE_ACT(("pcm_trigger stop\n")); - for (i = 0; i < DSP_MAXPIPES; i++) { - if (channelmask & (1 << i)) { - pipe = chip->substream[i]->runtime->private_data; - pipe->state = PIPE_STATE_STOPPED; - } - } - err = stop_transport(chip, channelmask); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - DE_ACT(("pcm_trigger pause\n")); - for (i = 0; i < DSP_MAXPIPES; i++) { - if (channelmask & (1 << i)) { - pipe = chip->substream[i]->runtime->private_data; - pipe->state = PIPE_STATE_PAUSED; - } - } - err = pause_transport(chip, channelmask); - break; - default: - err = -EINVAL; - } - spin_unlock(&chip->lock); - return err; -} - - - -static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct audiopipe *pipe = runtime->private_data; - size_t cnt, bufsize, pos; - - cnt = le32_to_cpu(*pipe->dma_counter); - pipe->position += cnt - pipe->last_counter; - pipe->last_counter = cnt; - bufsize = substream->runtime->buffer_size; - pos = bytes_to_frames(substream->runtime, pipe->position); - - while (pos >= bufsize) { - pipe->position -= frames_to_bytes(substream->runtime, bufsize); - pos -= bufsize; - } - return pos; -} - - - -/* pcm *_ops structures */ -static struct snd_pcm_ops analog_playback_ops = { - .open = pcm_analog_out_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_analog_out_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -static struct snd_pcm_ops analog_capture_ops = { - .open = pcm_analog_in_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_analog_in_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -#ifdef ECHOCARD_HAS_DIGITAL_IO -#ifndef ECHOCARD_HAS_VMIXER -static struct snd_pcm_ops digital_playback_ops = { - .open = pcm_digital_out_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_digital_out_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -#endif /* !ECHOCARD_HAS_VMIXER */ -static struct snd_pcm_ops digital_capture_ops = { - .open = pcm_digital_in_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_digital_in_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - - - -/* Preallocate memory only for the first substream because it's the most - * used one - */ -static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev) -{ - struct snd_pcm_substream *ss; - int stream, err; - - for (stream = 0; stream < 2; stream++) - for (ss = pcm->streams[stream].substream; ss; ss = ss->next) { - err = snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG, - dev, - ss->number ? 0 : 128<<10, - 256<<10); - if (err < 0) - return err; - } - return 0; -} - - - -/*<--snd_echo_probe() */ -static int __devinit snd_echo_new_pcm(struct echoaudio *chip) -{ - struct snd_pcm *pcm; - int err; - -#ifdef ECHOCARD_HAS_VMIXER - /* This card has a Vmixer, that is there is no direct mapping from PCM - streams to physical outputs. The user can mix the streams as he wishes - via control interface and it's possible to send any stream to any - output, thus it makes no sense to keep analog and digital outputs - separated */ - - /* PCM#0 Virtual outputs and analog inputs */ - if ((err = snd_pcm_new(chip->card, "PCM", 0, num_pipes_out(chip), - num_analog_busses_in(chip), &pcm)) < 0) - return err; - pcm->private_data = chip; - chip->analog_pcm = pcm; - strcpy(pcm->name, chip->card->shortname); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops); - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) - return err; - DE_INIT(("Analog PCM ok\n")); - -#ifdef ECHOCARD_HAS_DIGITAL_IO - /* PCM#1 Digital inputs, no outputs */ - if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, 0, - num_digital_busses_in(chip), &pcm)) < 0) - return err; - pcm->private_data = chip; - chip->digital_pcm = pcm; - strcpy(pcm->name, chip->card->shortname); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops); - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) - return err; - DE_INIT(("Digital PCM ok\n")); -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - -#else /* ECHOCARD_HAS_VMIXER */ - - /* The card can manage substreams formed by analog and digital channels - at the same time, but I prefer to keep analog and digital channels - separated, because that mixed thing is confusing and useless. So we - register two PCM devices: */ - - /* PCM#0 Analog i/o */ - if ((err = snd_pcm_new(chip->card, "Analog PCM", 0, - num_analog_busses_out(chip), - num_analog_busses_in(chip), &pcm)) < 0) - return err; - pcm->private_data = chip; - chip->analog_pcm = pcm; - strcpy(pcm->name, chip->card->shortname); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops); - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) - return err; - DE_INIT(("Analog PCM ok\n")); - -#ifdef ECHOCARD_HAS_DIGITAL_IO - /* PCM#1 Digital i/o */ - if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, - num_digital_busses_out(chip), - num_digital_busses_in(chip), &pcm)) < 0) - return err; - pcm->private_data = chip; - chip->digital_pcm = pcm; - strcpy(pcm->name, chip->card->shortname); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &digital_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops); - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) - return err; - DE_INIT(("Digital PCM ok\n")); -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - -#endif /* ECHOCARD_HAS_VMIXER */ - - return 0; -} - - - - -/****************************************************************************** - Control interface -******************************************************************************/ - -#if !defined(ECHOCARD_HAS_VMIXER) || defined(ECHOCARD_HAS_LINE_OUT_GAIN) - -/******************* PCM output volume *******************/ -static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = num_busses_out(chip); - uinfo->value.integer.min = ECHOGAIN_MINOUT; - uinfo->value.integer.max = ECHOGAIN_MAXOUT; - return 0; -} - -static int snd_echo_output_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c; - - chip = snd_kcontrol_chip(kcontrol); - for (c = 0; c < num_busses_out(chip); c++) - ucontrol->value.integer.value[c] = chip->output_gain[c]; - return 0; -} - -static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c, changed, gain; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - for (c = 0; c < num_busses_out(chip); c++) { - gain = ucontrol->value.integer.value[c]; - /* Ignore out of range values */ - if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) - continue; - if (chip->output_gain[c] != gain) { - set_output_gain(chip, c, gain); - changed = 1; - } - } - if (changed) - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - return changed; -} - -#ifdef ECHOCARD_HAS_LINE_OUT_GAIN -/* On the Mia this one controls the line-out volume */ -static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = { - .name = "Line Playback Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = snd_echo_output_gain_info, - .get = snd_echo_output_gain_get, - .put = snd_echo_output_gain_put, - .tlv = {.p = db_scale_output_gain}, -}; -#else -static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { - .name = "PCM Playback Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = snd_echo_output_gain_info, - .get = snd_echo_output_gain_get, - .put = snd_echo_output_gain_put, - .tlv = {.p = db_scale_output_gain}, -}; -#endif - -#endif /* !ECHOCARD_HAS_VMIXER || ECHOCARD_HAS_LINE_OUT_GAIN */ - - - -#ifdef ECHOCARD_HAS_INPUT_GAIN - -/******************* Analog input volume *******************/ -static int snd_echo_input_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = num_analog_busses_in(chip); - uinfo->value.integer.min = ECHOGAIN_MININP; - uinfo->value.integer.max = ECHOGAIN_MAXINP; - return 0; -} - -static int snd_echo_input_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c; - - chip = snd_kcontrol_chip(kcontrol); - for (c = 0; c < num_analog_busses_in(chip); c++) - ucontrol->value.integer.value[c] = chip->input_gain[c]; - return 0; -} - -static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c, gain, changed; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - for (c = 0; c < num_analog_busses_in(chip); c++) { - gain = ucontrol->value.integer.value[c]; - /* Ignore out of range values */ - if (gain < ECHOGAIN_MININP || gain > ECHOGAIN_MAXINP) - continue; - if (chip->input_gain[c] != gain) { - set_input_gain(chip, c, gain); - changed = 1; - } - } - if (changed) - update_input_line_level(chip); - spin_unlock_irq(&chip->lock); - return changed; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_input_gain, -2500, 50, 0); - -static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = { - .name = "Line Capture Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = snd_echo_input_gain_info, - .get = snd_echo_input_gain_get, - .put = snd_echo_input_gain_put, - .tlv = {.p = db_scale_input_gain}, -}; - -#endif /* ECHOCARD_HAS_INPUT_GAIN */ - - - -#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL - -/************ Analog output nominal level (+4dBu / -10dBV) ***************/ -static int snd_echo_output_nominal_info (struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = num_analog_busses_out(chip); - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_echo_output_nominal_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c; - - chip = snd_kcontrol_chip(kcontrol); - for (c = 0; c < num_analog_busses_out(chip); c++) - ucontrol->value.integer.value[c] = chip->nominal_level[c]; - return 0; -} - -static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c, changed; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - for (c = 0; c < num_analog_busses_out(chip); c++) { - if (chip->nominal_level[c] != ucontrol->value.integer.value[c]) { - set_nominal_level(chip, c, - ucontrol->value.integer.value[c]); - changed = 1; - } - } - if (changed) - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - return changed; -} - -static struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = { - .name = "Line Playback Switch (-10dBV)", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_output_nominal_info, - .get = snd_echo_output_nominal_get, - .put = snd_echo_output_nominal_put, -}; - -#endif /* ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL */ - - - -#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL - -/*************** Analog input nominal level (+4dBu / -10dBV) ***************/ -static int snd_echo_input_nominal_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = num_analog_busses_in(chip); - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_echo_input_nominal_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c; - - chip = snd_kcontrol_chip(kcontrol); - for (c = 0; c < num_analog_busses_in(chip); c++) - ucontrol->value.integer.value[c] = - chip->nominal_level[bx_analog_in(chip) + c]; - return 0; -} - -static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c, changed; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - for (c = 0; c < num_analog_busses_in(chip); c++) { - if (chip->nominal_level[bx_analog_in(chip) + c] != - ucontrol->value.integer.value[c]) { - set_nominal_level(chip, bx_analog_in(chip) + c, - ucontrol->value.integer.value[c]); - changed = 1; - } - } - if (changed) - update_output_line_level(chip); /* "Output" is not a mistake - * here. - */ - spin_unlock_irq(&chip->lock); - return changed; -} - -static struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = { - .name = "Line Capture Switch (-10dBV)", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_input_nominal_info, - .get = snd_echo_input_nominal_get, - .put = snd_echo_input_nominal_put, -}; - -#endif /* ECHOCARD_HAS_INPUT_NOMINAL_LEVEL */ - - - -#ifdef ECHOCARD_HAS_MONITOR - -/******************* Monitor mixer *******************/ -static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = ECHOGAIN_MINOUT; - uinfo->value.integer.max = ECHOGAIN_MAXOUT; - uinfo->dimen.d[0] = num_busses_out(chip); - uinfo->dimen.d[1] = num_busses_in(chip); - return 0; -} - -static int snd_echo_mixer_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = - chip->monitor_gain[ucontrol->id.index / num_busses_in(chip)] - [ucontrol->id.index % num_busses_in(chip)]; - return 0; -} - -static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int changed, gain; - short out, in; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - out = ucontrol->id.index / num_busses_in(chip); - in = ucontrol->id.index % num_busses_in(chip); - gain = ucontrol->value.integer.value[0]; - if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) - return -EINVAL; - if (chip->monitor_gain[out][in] != gain) { - spin_lock_irq(&chip->lock); - set_monitor_gain(chip, out, in, gain); - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - changed = 1; - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = { - .name = "Monitor Mixer Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = snd_echo_mixer_info, - .get = snd_echo_mixer_get, - .put = snd_echo_mixer_put, - .tlv = {.p = db_scale_output_gain}, -}; - -#endif /* ECHOCARD_HAS_MONITOR */ - - - -#ifdef ECHOCARD_HAS_VMIXER - -/******************* Vmixer *******************/ -static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = ECHOGAIN_MINOUT; - uinfo->value.integer.max = ECHOGAIN_MAXOUT; - uinfo->dimen.d[0] = num_busses_out(chip); - uinfo->dimen.d[1] = num_pipes_out(chip); - return 0; -} - -static int snd_echo_vmixer_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = - chip->vmixer_gain[ucontrol->id.index / num_pipes_out(chip)] - [ucontrol->id.index % num_pipes_out(chip)]; - return 0; -} - -static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int gain, changed; - short vch, out; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - out = ucontrol->id.index / num_pipes_out(chip); - vch = ucontrol->id.index % num_pipes_out(chip); - gain = ucontrol->value.integer.value[0]; - if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) - return -EINVAL; - if (chip->vmixer_gain[out][vch] != ucontrol->value.integer.value[0]) { - spin_lock_irq(&chip->lock); - set_vmixer_gain(chip, out, vch, ucontrol->value.integer.value[0]); - update_vmixer_level(chip); - spin_unlock_irq(&chip->lock); - changed = 1; - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = { - .name = "VMixer Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = snd_echo_vmixer_info, - .get = snd_echo_vmixer_get, - .put = snd_echo_vmixer_put, - .tlv = {.p = db_scale_output_gain}, -}; - -#endif /* ECHOCARD_HAS_VMIXER */ - - - -#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH - -/******************* Digital mode switch *******************/ -static int snd_echo_digital_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *names[4] = { - "S/PDIF Coaxial", "S/PDIF Optical", "ADAT Optical", - "S/PDIF Cdrom" - }; - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->value.enumerated.items = chip->num_digital_modes; - uinfo->count = 1; - if (uinfo->value.enumerated.item >= chip->num_digital_modes) - uinfo->value.enumerated.item = chip->num_digital_modes - 1; - strcpy(uinfo->value.enumerated.name, names[ - chip->digital_mode_list[uinfo->value.enumerated.item]]); - return 0; -} - -static int snd_echo_digital_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int i, mode; - - chip = snd_kcontrol_chip(kcontrol); - mode = chip->digital_mode; - for (i = chip->num_digital_modes - 1; i >= 0; i--) - if (mode == chip->digital_mode_list[i]) { - ucontrol->value.enumerated.item[0] = i; - break; - } - return 0; -} - -static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int changed; - unsigned short emode, dmode; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - - emode = ucontrol->value.enumerated.item[0]; - if (emode >= chip->num_digital_modes) - return -EINVAL; - dmode = chip->digital_mode_list[emode]; - - if (dmode != chip->digital_mode) { - /* mode_mutex is required to make this operation atomic wrt - pcm_digital_*_open() and set_input_clock() functions. */ - mutex_lock(&chip->mode_mutex); - - /* Do not allow the user to change the digital mode when a pcm - device is open because it also changes the number of channels - and the allowed sample rates */ - if (atomic_read(&chip->opencount)) { - changed = -EAGAIN; - } else { - changed = set_digital_mode(chip, dmode); - /* If we had to change the clock source, report it */ - if (changed > 0 && chip->clock_src_ctl) { - snd_ctl_notify(chip->card, - SNDRV_CTL_EVENT_MASK_VALUE, - &chip->clock_src_ctl->id); - DE_ACT(("SDM() =%d\n", changed)); - } - if (changed >= 0) - changed = 1; /* No errors */ - } - mutex_unlock(&chip->mode_mutex); - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = { - .name = "Digital mode Switch", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = snd_echo_digital_mode_info, - .get = snd_echo_digital_mode_get, - .put = snd_echo_digital_mode_put, -}; - -#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */ - - - -#ifdef ECHOCARD_HAS_DIGITAL_IO - -/******************* S/PDIF mode switch *******************/ -static int snd_echo_spdif_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *names[2] = {"Consumer", "Professional"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->value.enumerated.items = 2; - uinfo->count = 1; - if (uinfo->value.enumerated.item) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - names[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_echo_spdif_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = !!chip->professional_spdif; - return 0; -} - -static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int mode; - - chip = snd_kcontrol_chip(kcontrol); - mode = !!ucontrol->value.enumerated.item[0]; - if (mode != chip->professional_spdif) { - spin_lock_irq(&chip->lock); - set_professional_spdif(chip, mode); - spin_unlock_irq(&chip->lock); - return 1; - } - return 0; -} - -static struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = { - .name = "S/PDIF mode Switch", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = snd_echo_spdif_mode_info, - .get = snd_echo_spdif_mode_get, - .put = snd_echo_spdif_mode_put, -}; - -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - - - -#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK - -/******************* Select input clock source *******************/ -static int snd_echo_clock_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *names[8] = { - "Internal", "Word", "Super", "S/PDIF", "ADAT", "ESync", - "ESync96", "MTC" - }; - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->value.enumerated.items = chip->num_clock_sources; - uinfo->count = 1; - if (uinfo->value.enumerated.item >= chip->num_clock_sources) - uinfo->value.enumerated.item = chip->num_clock_sources - 1; - strcpy(uinfo->value.enumerated.name, names[ - chip->clock_source_list[uinfo->value.enumerated.item]]); - return 0; -} - -static int snd_echo_clock_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int i, clock; - - chip = snd_kcontrol_chip(kcontrol); - clock = chip->input_clock; - - for (i = 0; i < chip->num_clock_sources; i++) - if (clock == chip->clock_source_list[i]) - ucontrol->value.enumerated.item[0] = i; - - return 0; -} - -static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int changed; - unsigned int eclock, dclock; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - eclock = ucontrol->value.enumerated.item[0]; - if (eclock >= chip->input_clock_types) - return -EINVAL; - dclock = chip->clock_source_list[eclock]; - if (chip->input_clock != dclock) { - mutex_lock(&chip->mode_mutex); - spin_lock_irq(&chip->lock); - if ((changed = set_input_clock(chip, dclock)) == 0) - changed = 1; /* no errors */ - spin_unlock_irq(&chip->lock); - mutex_unlock(&chip->mode_mutex); - } - - if (changed < 0) - DE_ACT(("seticlk val%d err 0x%x\n", dclock, changed)); - - return changed; -} - -static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = { - .name = "Sample Clock Source", - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .info = snd_echo_clock_source_info, - .get = snd_echo_clock_source_get, - .put = snd_echo_clock_source_put, -}; - -#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */ - - - -#ifdef ECHOCARD_HAS_PHANTOM_POWER - -/******************* Phantom power switch *******************/ -#define snd_echo_phantom_power_info snd_ctl_boolean_mono_info - -static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = chip->phantom_power; - return 0; -} - -static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip = snd_kcontrol_chip(kcontrol); - int power, changed = 0; - - power = !!ucontrol->value.integer.value[0]; - if (chip->phantom_power != power) { - spin_lock_irq(&chip->lock); - changed = set_phantom_power(chip, power); - spin_unlock_irq(&chip->lock); - if (changed == 0) - changed = 1; /* no errors */ - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = { - .name = "Phantom power Switch", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = snd_echo_phantom_power_info, - .get = snd_echo_phantom_power_get, - .put = snd_echo_phantom_power_put, -}; - -#endif /* ECHOCARD_HAS_PHANTOM_POWER */ - - - -#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE - -/******************* Digital input automute switch *******************/ -#define snd_echo_automute_info snd_ctl_boolean_mono_info - -static int snd_echo_automute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = chip->digital_in_automute; - return 0; -} - -static int snd_echo_automute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip = snd_kcontrol_chip(kcontrol); - int automute, changed = 0; - - automute = !!ucontrol->value.integer.value[0]; - if (chip->digital_in_automute != automute) { - spin_lock_irq(&chip->lock); - changed = set_input_auto_mute(chip, automute); - spin_unlock_irq(&chip->lock); - if (changed == 0) - changed = 1; /* no errors */ - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = { - .name = "Digital Capture Switch (automute)", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = snd_echo_automute_info, - .get = snd_echo_automute_get, - .put = snd_echo_automute_put, -}; - -#endif /* ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE */ - - - -/******************* VU-meters switch *******************/ -#define snd_echo_vumeters_switch_info snd_ctl_boolean_mono_info - -static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - set_meters_on(chip, ucontrol->value.integer.value[0]); - spin_unlock_irq(&chip->lock); - return 1; -} - -static struct snd_kcontrol_new snd_echo_vumeters_switch __devinitdata = { - .name = "VU-meters Switch", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .access = SNDRV_CTL_ELEM_ACCESS_WRITE, - .info = snd_echo_vumeters_switch_info, - .put = snd_echo_vumeters_switch_put, -}; - - - -/***** Read VU-meters (input, output, analog and digital together) *****/ -static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 96; - uinfo->value.integer.min = ECHOGAIN_MINOUT; - uinfo->value.integer.max = 0; -#ifdef ECHOCARD_HAS_VMIXER - uinfo->dimen.d[0] = 3; /* Out, In, Virt */ -#else - uinfo->dimen.d[0] = 2; /* Out, In */ -#endif - uinfo->dimen.d[1] = 16; /* 16 channels */ - uinfo->dimen.d[2] = 2; /* 0=level, 1=peak */ - return 0; -} - -static int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - get_audio_meters(chip, ucontrol->value.integer.value); - return 0; -} - -static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = { - .name = "VU-meters", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = snd_echo_vumeters_info, - .get = snd_echo_vumeters_get, - .tlv = {.p = db_scale_output_gain}, -}; - - - -/*** Channels info - it exports informations about the number of channels ***/ -static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 6; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1 << ECHO_CLOCK_NUMBER; - return 0; -} - -static int snd_echo_channels_info_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int detected, clocks, bit, src; - - chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = num_busses_in(chip); - ucontrol->value.integer.value[1] = num_analog_busses_in(chip); - ucontrol->value.integer.value[2] = num_busses_out(chip); - ucontrol->value.integer.value[3] = num_analog_busses_out(chip); - ucontrol->value.integer.value[4] = num_pipes_out(chip); - - /* Compute the bitmask of the currently valid input clocks */ - detected = detect_input_clocks(chip); - clocks = 0; - src = chip->num_clock_sources - 1; - for (bit = ECHO_CLOCK_NUMBER - 1; bit >= 0; bit--) - if (detected & (1 << bit)) - for (; src >= 0; src--) - if (bit == chip->clock_source_list[src]) { - clocks |= 1 << src; - break; - } - ucontrol->value.integer.value[5] = clocks; - - return 0; -} - -static struct snd_kcontrol_new snd_echo_channels_info __devinitdata = { - .name = "Channels info", - .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_echo_channels_info_info, - .get = snd_echo_channels_info_get, -}; - - - - -/****************************************************************************** - IRQ Handler -******************************************************************************/ - -static irqreturn_t snd_echo_interrupt(int irq, void *dev_id) -{ - struct echoaudio *chip = dev_id; - struct snd_pcm_substream *substream; - int period, ss, st; - - spin_lock(&chip->lock); - st = service_irq(chip); - if (st < 0) { - spin_unlock(&chip->lock); - return IRQ_NONE; - } - /* The hardware doesn't tell us which substream caused the irq, - thus we have to check all running substreams. */ - for (ss = 0; ss < DSP_MAXPIPES; ss++) { - substream = chip->substream[ss]; - if (substream && ((struct audiopipe *)substream->runtime-> - private_data)->state == PIPE_STATE_STARTED) { - period = pcm_pointer(substream) / - substream->runtime->period_size; - if (period != chip->last_period[ss]) { - chip->last_period[ss] = period; - spin_unlock(&chip->lock); - snd_pcm_period_elapsed(substream); - spin_lock(&chip->lock); - } - } - } - spin_unlock(&chip->lock); - -#ifdef ECHOCARD_HAS_MIDI - if (st > 0 && chip->midi_in) { - snd_rawmidi_receive(chip->midi_in, chip->midi_buffer, st); - DE_MID(("rawmidi_iread=%d\n", st)); - } -#endif - return IRQ_HANDLED; -} - - - - -/****************************************************************************** - Module construction / destruction -******************************************************************************/ - -static int snd_echo_free(struct echoaudio *chip) -{ - DE_INIT(("Stop DSP...\n")); - if (chip->comm_page) - rest_in_peace(chip); - DE_INIT(("Stopped.\n")); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - if (chip->comm_page) - snd_dma_free_pages(&chip->commpage_dma_buf); - - if (chip->dsp_registers) - iounmap(chip->dsp_registers); - - if (chip->iores) - release_and_free_resource(chip->iores); - - DE_INIT(("MMIO freed.\n")); - - pci_disable_device(chip->pci); - - /* release chip data */ - free_firmware_cache(chip); - kfree(chip); - DE_INIT(("Chip freed.\n")); - return 0; -} - - - -static int snd_echo_dev_free(struct snd_device *device) -{ - struct echoaudio *chip = device->device_data; - - DE_INIT(("snd_echo_dev_free()...\n")); - return snd_echo_free(chip); -} - - - -/* <--snd_echo_probe() */ -static __devinit int snd_echo_create(struct snd_card *card, - struct pci_dev *pci, - struct echoaudio **rchip) -{ - struct echoaudio *chip; - int err; - size_t sz; - static struct snd_device_ops ops = { - .dev_free = snd_echo_dev_free, - }; - - *rchip = NULL; - - pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0); - - if ((err = pci_enable_device(pci)) < 0) - return err; - pci_set_master(pci); - - /* Allocate chip if needed */ - if (!*rchip) { - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) { - pci_disable_device(pci); - return -ENOMEM; - } - DE_INIT(("chip=%p\n", chip)); - spin_lock_init(&chip->lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - atomic_set(&chip->opencount, 0); - mutex_init(&chip->mode_mutex); - chip->can_set_rate = 1; - } else { - /* If this was called from the resume function, chip is - * already allocated and it contains current card settings. - */ - chip = *rchip; - } - - /* PCI resource allocation */ - chip->dsp_registers_phys = pci_resource_start(pci, 0); - sz = pci_resource_len(pci, 0); - if (sz > PAGE_SIZE) - sz = PAGE_SIZE; /* We map only the required part */ - - if ((chip->iores = request_mem_region(chip->dsp_registers_phys, sz, - ECHOCARD_NAME)) == NULL) { - snd_echo_free(chip); - snd_printk(KERN_ERR "cannot get memory region\n"); - return -EBUSY; - } - chip->dsp_registers = (volatile u32 __iomem *) - ioremap_nocache(chip->dsp_registers_phys, sz); - - if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_echo_free(chip); - snd_printk(KERN_ERR "cannot grab irq\n"); - return -EBUSY; - } - chip->irq = pci->irq; - DE_INIT(("pci=%p irq=%d subdev=%04x Init hardware...\n", - chip->pci, chip->irq, chip->pci->subsystem_device)); - - /* Create the DSP comm page - this is the area of memory used for most - of the communication with the DSP, which accesses it via bus mastering */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - sizeof(struct comm_page), - &chip->commpage_dma_buf) < 0) { - snd_echo_free(chip); - snd_printk(KERN_ERR "cannot allocate the comm page\n"); - return -ENOMEM; - } - chip->comm_page_phys = chip->commpage_dma_buf.addr; - chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area; - - err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device); - if (err >= 0) - err = set_mixer_defaults(chip); - if (err < 0) { - DE_INIT(("init_hw err=%d\n", err)); - snd_echo_free(chip); - return err; - } - DE_INIT(("Card init OK\n")); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_echo_free(chip); - return err; - } - *rchip = chip; - /* Init done ! */ - return 0; -} - - - -/* constructor */ -static int __devinit snd_echo_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct echoaudio *chip; - char *dsp; - int i, err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - DE_INIT(("Echoaudio driver starting...\n")); - i = 0; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - snd_card_set_dev(card, &pci->dev); - - chip = NULL; /* Tells snd_echo_create to allocate chip */ - if ((err = snd_echo_create(card, pci, &chip)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "Echo_" ECHOCARD_NAME); - strcpy(card->shortname, chip->card_name); - - dsp = "56301"; - if (pci_id->device == 0x3410) - dsp = "56361"; - - sprintf(card->longname, "%s rev.%d (DSP%s) at 0x%lx irq %i", - card->shortname, pci_id->subdevice & 0x000f, dsp, - chip->dsp_registers_phys, chip->irq); - - if ((err = snd_echo_new_pcm(chip)) < 0) { - snd_printk(KERN_ERR "new pcm error %d\n", err); - snd_card_free(card); - return err; - } - -#ifdef ECHOCARD_HAS_MIDI - if (chip->has_midi) { /* Some Mia's do not have midi */ - if ((err = snd_echo_midi_create(card, chip)) < 0) { - snd_printk(KERN_ERR "new midi error %d\n", err); - snd_card_free(card); - return err; - } - } -#endif - -#ifdef ECHOCARD_HAS_VMIXER - snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip); - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0) - goto ctl_error; -#ifdef ECHOCARD_HAS_LINE_OUT_GAIN - err = snd_ctl_add(chip->card, - snd_ctl_new1(&snd_echo_line_output_gain, chip)); - if (err < 0) - goto ctl_error; -#endif -#else /* ECHOCARD_HAS_VMIXER */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&snd_echo_pcm_output_gain, chip)); - if (err < 0) - goto ctl_error; -#endif /* ECHOCARD_HAS_VMIXER */ - -#ifdef ECHOCARD_HAS_INPUT_GAIN - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL - if (!chip->hasnt_input_nominal_level) - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip))) < 0) - goto ctl_error; -#endif - - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip))) < 0) - goto ctl_error; - - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip))) < 0) - goto ctl_error; - -#ifdef ECHOCARD_HAS_MONITOR - snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip); - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip))) < 0) - goto ctl_error; -#endif - - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip))) < 0) - goto ctl_error; - -#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH - /* Creates a list of available digital modes */ - chip->num_digital_modes = 0; - for (i = 0; i < 6; i++) - if (chip->digital_modes & (1 << i)) - chip->digital_mode_list[chip->num_digital_modes++] = i; - - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip))) < 0) - goto ctl_error; -#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */ - -#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK - /* Creates a list of available clock sources */ - chip->num_clock_sources = 0; - for (i = 0; i < 10; i++) - if (chip->input_clock_types & (1 << i)) - chip->clock_source_list[chip->num_clock_sources++] = i; - - if (chip->num_clock_sources > 1) { - chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip); - if ((err = snd_ctl_add(chip->card, chip->clock_src_ctl)) < 0) - goto ctl_error; - } -#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */ - -#ifdef ECHOCARD_HAS_DIGITAL_IO - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_PHANTOM_POWER - if (chip->has_phantom_power) - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip))) < 0) - goto ctl_error; -#endif - - err = snd_card_register(card); - if (err < 0) - goto ctl_error; - snd_printk(KERN_INFO "Card registered: %s\n", card->longname); - - pci_set_drvdata(pci, chip); - dev++; - return 0; - -ctl_error: - snd_printk(KERN_ERR "new control error %d\n", err); - snd_card_free(card); - return err; -} - - - -#if defined(CONFIG_PM) - -static int snd_echo_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct echoaudio *chip = pci_get_drvdata(pci); - - DE_INIT(("suspend start\n")); - snd_pcm_suspend_all(chip->analog_pcm); - snd_pcm_suspend_all(chip->digital_pcm); - -#ifdef ECHOCARD_HAS_MIDI - /* This call can sleep */ - if (chip->midi_out) - snd_echo_midi_output_trigger(chip->midi_out, 0); -#endif - spin_lock_irq(&chip->lock); - if (wait_handshake(chip)) { - spin_unlock_irq(&chip->lock); - return -EIO; - } - clear_handshake(chip); - if (send_vector(chip, DSP_VC_GO_COMATOSE) < 0) { - spin_unlock_irq(&chip->lock); - return -EIO; - } - spin_unlock_irq(&chip->lock); - - chip->dsp_code = NULL; - free_irq(chip->irq, chip); - chip->irq = -1; - pci_save_state(pci); - pci_disable_device(pci); - - DE_INIT(("suspend done\n")); - return 0; -} - - - -static int snd_echo_resume(struct pci_dev *pci) -{ - struct echoaudio *chip = pci_get_drvdata(pci); - struct comm_page *commpage, *commpage_bak; - u32 pipe_alloc_mask; - int err; - - DE_INIT(("resume start\n")); - pci_restore_state(pci); - commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL); - if (commpage_bak == NULL) - return -ENOMEM; - commpage = chip->comm_page; - memcpy(commpage_bak, commpage, sizeof(struct comm_page)); - - err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device); - if (err < 0) { - kfree(commpage_bak); - DE_INIT(("resume init_hw err=%d\n", err)); - snd_echo_free(chip); - return err; - } - DE_INIT(("resume init OK\n")); - - /* Temporarily set chip->pipe_alloc_mask=0 otherwise - * restore_dsp_settings() fails. - */ - pipe_alloc_mask = chip->pipe_alloc_mask; - chip->pipe_alloc_mask = 0; - err = restore_dsp_rettings(chip); - chip->pipe_alloc_mask = pipe_alloc_mask; - if (err < 0) { - kfree(commpage_bak); - return err; - } - DE_INIT(("resume restore OK\n")); - - memcpy(&commpage->audio_format, &commpage_bak->audio_format, - sizeof(commpage->audio_format)); - memcpy(&commpage->sglist_addr, &commpage_bak->sglist_addr, - sizeof(commpage->sglist_addr)); - memcpy(&commpage->midi_output, &commpage_bak->midi_output, - sizeof(commpage->midi_output)); - kfree(commpage_bak); - - if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_echo_free(chip); - snd_printk(KERN_ERR "cannot grab irq\n"); - return -EBUSY; - } - chip->irq = pci->irq; - DE_INIT(("resume irq=%d\n", chip->irq)); - -#ifdef ECHOCARD_HAS_MIDI - if (chip->midi_input_enabled) - enable_midi_input(chip, TRUE); - if (chip->midi_out) - snd_echo_midi_output_trigger(chip->midi_out, 1); -#endif - - DE_INIT(("resume done\n")); - return 0; -} - -#endif /* CONFIG_PM */ - - - -static void __devexit snd_echo_remove(struct pci_dev *pci) -{ - struct echoaudio *chip; - - chip = pci_get_drvdata(pci); - if (chip) - snd_card_free(chip->card); - pci_set_drvdata(pci, NULL); -} - - - -/****************************************************************************** - Everything starts and ends here -******************************************************************************/ - -/* pci_driver definition */ -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_echo_ids, - .probe = snd_echo_probe, - .remove = __devexit_p(snd_echo_remove), -#ifdef CONFIG_PM - .suspend = snd_echo_suspend, - .resume = snd_echo_resume, -#endif /* CONFIG_PM */ -}; - - - -/* initialization of the module */ -static int __init alsa_card_echo_init(void) -{ - return pci_register_driver(&driver); -} - - - -/* clean up the module */ -static void __exit alsa_card_echo_exit(void) -{ - pci_unregister_driver(&driver); -} - - -module_init(alsa_card_echo_init) -module_exit(alsa_card_echo_exit) diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.h b/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.h deleted file mode 100644 index 1df974dc..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio.h +++ /dev/null @@ -1,598 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - **************************************************************************** - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - - **************************************************************************** - - - Here's a block diagram of how most of the cards work: - - +-----------+ - record | |<-------------------- Inputs - <-------| | | - PCI | Transport | | - bus | engine | \|/ - ------->| | +-------+ - play | |--->|monitor|-------> Outputs - +-----------+ | mixer | - +-------+ - - The lines going to and from the PCI bus represent "pipes". A pipe performs - audio transport - moving audio data to and from buffers on the host via - bus mastering. - - The inputs and outputs on the right represent input and output "busses." - A bus is a physical, real connection to the outside world. An example - of a bus would be the 1/4" analog connectors on the back of Layla or - an RCA S/PDIF connector. - - For most cards, there is a one-to-one correspondence between outputs - and busses; that is, each individual pipe is hard-wired to a single bus. - - Cards that work this way are Darla20, Gina20, Layla20, Darla24, Gina24, - Layla24, Mona, and Indigo. - - - Mia has a feature called "virtual outputs." - - - +-----------+ - record | |<----------------------------- Inputs - <-------| | | - PCI | Transport | | - bus | engine | \|/ - ------->| | +------+ +-------+ - play | |-->|vmixer|-->|monitor|-------> Outputs - +-----------+ +------+ | mixer | - +-------+ - - - Obviously, the difference here is the box labeled "vmixer." Vmixer is - short for "virtual output mixer." For Mia, pipes are *not* hard-wired - to a single bus; the vmixer lets you mix any pipe to any bus in any - combination. - - Note, however, that the left-hand side of the diagram is unchanged. - Transport works exactly the same way - the difference is in the mixer stage. - - - Pipes and busses are numbered starting at zero. - - - - Pipe index - ========== - - A number of calls in CEchoGals refer to a "pipe index". A pipe index is - a unique number for a pipe that unambiguously refers to a playback or record - pipe. Pipe indices are numbered starting with analog outputs, followed by - digital outputs, then analog inputs, then digital inputs. - - Take Gina24 as an example: - - Pipe index - - 0-7 Analog outputs (0 .. FirstDigitalBusOut-1) - 8-15 Digital outputs (FirstDigitalBusOut .. NumBussesOut-1) - 16-17 Analog inputs - 18-25 Digital inputs - - - You get the pipe index by calling CEchoGals::OpenAudio; the other transport - functions take the pipe index as a parameter. If you need a pipe index for - some other reason, use the handy Makepipe_index method. - - - Some calls take a CChannelMask parameter; CChannelMask is a handy way to - group pipe indices. - - - - Digital mode switch - =================== - - Some cards (right now, Gina24, Layla24, and Mona) have a Digital Mode Switch - or DMS. Cards with a DMS can be set to one of three mutually exclusive - digital modes: S/PDIF RCA, S/PDIF optical, or ADAT optical. - - This may create some confusion since ADAT optical is 8 channels wide and - S/PDIF is only two channels wide. Gina24, Layla24, and Mona handle this - by acting as if they always have 8 digital outs and ins. If you are in - either S/PDIF mode, the last 6 channels don't do anything - data sent - out these channels is thrown away and you will always record zeros. - - Note that with Gina24, Layla24, and Mona, sample rates above 50 kHz are - only available if you have the card configured for S/PDIF optical or S/PDIF - RCA. - - - - Double speed mode - ================= - - Some of the cards support 88.2 kHz and 96 kHz sampling (Darla24, Gina24, - Layla24, Mona, Mia, and Indigo). For these cards, the driver sometimes has - to worry about "double speed mode"; double speed mode applies whenever the - sampling rate is above 50 kHz. - - For instance, Mona and Layla24 support word clock sync. However, they - actually support two different word clock modes - single speed (below - 50 kHz) and double speed (above 50 kHz). The hardware detects if a single - or double speed word clock signal is present; the generic code uses that - information to determine which mode to use. - - The generic code takes care of all this for you. -*/ - - -#ifndef _ECHOAUDIO_H_ -#define _ECHOAUDIO_H_ - - -#define TRUE 1 -#define FALSE 0 - -#include "echoaudio_dsp.h" - - - -/*********************************************************************** - - PCI configuration space - -***********************************************************************/ - -/* - * PCI vendor ID and device IDs for the hardware - */ -#define VENDOR_ID 0x1057 -#define DEVICE_ID_56301 0x1801 -#define DEVICE_ID_56361 0x3410 -#define SUBVENDOR_ID 0xECC0 - - -/* - * Valid Echo PCI subsystem card IDs - */ -#define DARLA20 0x0010 -#define GINA20 0x0020 -#define LAYLA20 0x0030 -#define DARLA24 0x0040 -#define GINA24 0x0050 -#define LAYLA24 0x0060 -#define MONA 0x0070 -#define MIA 0x0080 -#define INDIGO 0x0090 -#define INDIGO_IO 0x00a0 -#define INDIGO_DJ 0x00b0 -#define DC8 0x00c0 -#define INDIGO_IOX 0x00d0 -#define INDIGO_DJX 0x00e0 -#define ECHO3G 0x0100 - - -/************************************************************************ - - Array sizes and so forth - -***********************************************************************/ - -/* - * Sizes - */ -#define ECHO_MAXAUDIOINPUTS 32 /* Max audio input channels */ -#define ECHO_MAXAUDIOOUTPUTS 32 /* Max audio output channels */ -#define ECHO_MAXAUDIOPIPES 32 /* Max number of input and output - * pipes */ -#define E3G_MAX_OUTPUTS 16 -#define ECHO_MAXMIDIJACKS 1 /* Max MIDI ports */ -#define ECHO_MIDI_QUEUE_SZ 512 /* Max MIDI input queue entries */ -#define ECHO_MTC_QUEUE_SZ 32 /* Max MIDI time code input queue - * entries */ - -/* - * MIDI activity indicator timeout - */ -#define MIDI_ACTIVITY_TIMEOUT_USEC 200000 - - -/**************************************************************************** - - Clocks - -*****************************************************************************/ - -/* - * Clock numbers - */ -#define ECHO_CLOCK_INTERNAL 0 -#define ECHO_CLOCK_WORD 1 -#define ECHO_CLOCK_SUPER 2 -#define ECHO_CLOCK_SPDIF 3 -#define ECHO_CLOCK_ADAT 4 -#define ECHO_CLOCK_ESYNC 5 -#define ECHO_CLOCK_ESYNC96 6 -#define ECHO_CLOCK_MTC 7 -#define ECHO_CLOCK_NUMBER 8 -#define ECHO_CLOCKS 0xffff - -/* - * Clock bit numbers - used to report capabilities and whatever clocks - * are being detected dynamically. - */ -#define ECHO_CLOCK_BIT_INTERNAL (1 << ECHO_CLOCK_INTERNAL) -#define ECHO_CLOCK_BIT_WORD (1 << ECHO_CLOCK_WORD) -#define ECHO_CLOCK_BIT_SUPER (1 << ECHO_CLOCK_SUPER) -#define ECHO_CLOCK_BIT_SPDIF (1 << ECHO_CLOCK_SPDIF) -#define ECHO_CLOCK_BIT_ADAT (1 << ECHO_CLOCK_ADAT) -#define ECHO_CLOCK_BIT_ESYNC (1 << ECHO_CLOCK_ESYNC) -#define ECHO_CLOCK_BIT_ESYNC96 (1 << ECHO_CLOCK_ESYNC96) -#define ECHO_CLOCK_BIT_MTC (1<comm_page->handshake = 0; -} - -static inline u32 get_dsp_register(struct echoaudio *chip, u32 index) -{ - return readl(&chip->dsp_registers[index]); -} - -static inline void set_dsp_register(struct echoaudio *chip, u32 index, - u32 value) -{ - writel(value, &chip->dsp_registers[index]); -} - - -/* Pipe and bus indexes. PX_* and BX_* are defined as chip->px_* and chip->bx_* -for 3G cards because they depend on the external box. They are integer -constants for all other cards. -Never use those defines directly, use the following functions instead. */ - -static inline int px_digital_out(const struct echoaudio *chip) -{ - return PX_DIGITAL_OUT; -} - -static inline int px_analog_in(const struct echoaudio *chip) -{ - return PX_ANALOG_IN; -} - -static inline int px_digital_in(const struct echoaudio *chip) -{ - return PX_DIGITAL_IN; -} - -static inline int px_num(const struct echoaudio *chip) -{ - return PX_NUM; -} - -static inline int bx_digital_out(const struct echoaudio *chip) -{ - return BX_DIGITAL_OUT; -} - -static inline int bx_analog_in(const struct echoaudio *chip) -{ - return BX_ANALOG_IN; -} - -static inline int bx_digital_in(const struct echoaudio *chip) -{ - return BX_DIGITAL_IN; -} - -static inline int bx_num(const struct echoaudio *chip) -{ - return BX_NUM; -} - -static inline int num_pipes_out(const struct echoaudio *chip) -{ - return px_analog_in(chip); -} - -static inline int num_pipes_in(const struct echoaudio *chip) -{ - return px_num(chip) - px_analog_in(chip); -} - -static inline int num_busses_out(const struct echoaudio *chip) -{ - return bx_analog_in(chip); -} - -static inline int num_busses_in(const struct echoaudio *chip) -{ - return bx_num(chip) - bx_analog_in(chip); -} - -static inline int num_analog_busses_out(const struct echoaudio *chip) -{ - return bx_digital_out(chip); -} - -static inline int num_analog_busses_in(const struct echoaudio *chip) -{ - return bx_digital_in(chip) - bx_analog_in(chip); -} - -static inline int num_digital_busses_out(const struct echoaudio *chip) -{ - return num_busses_out(chip) - num_analog_busses_out(chip); -} - -static inline int num_digital_busses_in(const struct echoaudio *chip) -{ - return num_busses_in(chip) - num_analog_busses_in(chip); -} - -/* The monitor array is a one-dimensional array; compute the offset - * into the array */ -static inline int monitor_index(const struct echoaudio *chip, int out, int in) -{ - return out * num_busses_in(chip) + in; -} - - -#ifndef pci_device -#define pci_device(chip) (&chip->pci->dev) -#endif - - -#endif /* _ECHOAUDIO_H_ */ diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_3g.c b/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_3g.c deleted file mode 100644 index 658db44e..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_3g.c +++ /dev/null @@ -1,432 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - - -/* These functions are common for all "3G" cards */ - - -static int check_asic_status(struct echoaudio *chip) -{ - u32 box_status; - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->ext_box_status = cpu_to_le32(E3G_ASIC_NOT_LOADED); - chip->asic_loaded = FALSE; - clear_handshake(chip); - send_vector(chip, DSP_VC_TEST_ASIC); - - if (wait_handshake(chip)) { - chip->dsp_code = NULL; - return -EIO; - } - - box_status = le32_to_cpu(chip->comm_page->ext_box_status); - DE_INIT(("box_status=%x\n", box_status)); - if (box_status == E3G_ASIC_NOT_LOADED) - return -ENODEV; - - chip->asic_loaded = TRUE; - return box_status & E3G_BOX_TYPE_MASK; -} - - - -static inline u32 get_frq_reg(struct echoaudio *chip) -{ - return le32_to_cpu(chip->comm_page->e3g_frq_register); -} - - - -/* Most configuration of 3G cards is accomplished by writing the control -register. write_control_reg sends the new control register value to the DSP. */ -static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, - char force) -{ - if (wait_handshake(chip)) - return -EIO; - - DE_ACT(("WriteControlReg: Setting 0x%x, 0x%x\n", ctl, frq)); - - ctl = cpu_to_le32(ctl); - frq = cpu_to_le32(frq); - - if (ctl != chip->comm_page->control_register || - frq != chip->comm_page->e3g_frq_register || force) { - chip->comm_page->e3g_frq_register = frq; - chip->comm_page->control_register = ctl; - clear_handshake(chip); - return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); - } - - DE_ACT(("WriteControlReg: not written, no change\n")); - return 0; -} - - - -/* Set the digital mode - currently for Gina24, Layla24, Mona, 3G */ -static int set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u8 previous_mode; - int err, i, o; - - /* All audio channels must be closed before changing the digital mode */ - if (snd_BUG_ON(chip->pipe_alloc_mask)) - return -EAGAIN; - - if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) - return -EINVAL; - - previous_mode = chip->digital_mode; - err = dsp_set_digital_mode(chip, mode); - - /* If we successfully changed the digital mode from or to ADAT, - * then make sure all output, input and monitor levels are - * updated by the DSP comm object. */ - if (err >= 0 && previous_mode != mode && - (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { - spin_lock_irq(&chip->lock); - for (o = 0; o < num_busses_out(chip); o++) - for (i = 0; i < num_busses_in(chip); i++) - set_monitor_gain(chip, o, i, - chip->monitor_gain[o][i]); - -#ifdef ECHOCARD_HAS_INPUT_GAIN - for (i = 0; i < num_busses_in(chip); i++) - set_input_gain(chip, i, chip->input_gain[i]); - update_input_line_level(chip); -#endif - - for (o = 0; o < num_busses_out(chip); o++) - set_output_gain(chip, o, chip->output_gain[o]); - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - } - - return err; -} - - - -static u32 set_spdif_bits(struct echoaudio *chip, u32 control_reg, u32 rate) -{ - control_reg &= E3G_SPDIF_FORMAT_CLEAR_MASK; - - switch (rate) { - case 32000 : - control_reg |= E3G_SPDIF_SAMPLE_RATE0 | E3G_SPDIF_SAMPLE_RATE1; - break; - case 44100 : - if (chip->professional_spdif) - control_reg |= E3G_SPDIF_SAMPLE_RATE0; - break; - case 48000 : - control_reg |= E3G_SPDIF_SAMPLE_RATE1; - break; - } - - if (chip->professional_spdif) - control_reg |= E3G_SPDIF_PRO_MODE; - - if (chip->non_audio_spdif) - control_reg |= E3G_SPDIF_NOT_AUDIO; - - control_reg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | - E3G_SPDIF_COPY_PERMIT; - - return control_reg; -} - - - -/* Set the S/PDIF output format */ -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - u32 control_reg; - - control_reg = le32_to_cpu(chip->comm_page->control_register); - chip->professional_spdif = prof; - control_reg = set_spdif_bits(chip, control_reg, chip->sample_rate); - return write_control_reg(chip, control_reg, get_frq_reg(chip), 0); -} - - - -/* detect_input_clocks() returns a bitmask consisting of all the input clocks -currently connected to the hardware; this changes as the user connects and -disconnects clock inputs. You should use this information to determine which -clocks the user is allowed to select. */ -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - * detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD) - clock_bits |= ECHO_CLOCK_BIT_WORD; - - switch(chip->digital_mode) { - case DIGITAL_MODE_SPDIF_RCA: - case DIGITAL_MODE_SPDIF_OPTICAL: - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - break; - case DIGITAL_MODE_ADAT: - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_ADAT) - clock_bits |= ECHO_CLOCK_BIT_ADAT; - break; - } - - return clock_bits; -} - - - -static int load_asic(struct echoaudio *chip) -{ - int box_type, err; - - if (chip->asic_loaded) - return 0; - - /* Give the DSP a few milliseconds to settle down */ - mdelay(2); - - err = load_asic_generic(chip, DSP_FNC_LOAD_3G_ASIC, FW_3G_ASIC); - if (err < 0) - return err; - - chip->asic_code = FW_3G_ASIC; - - /* Now give the new ASIC some time to set up */ - msleep(1000); - /* See if it worked */ - box_type = check_asic_status(chip); - - /* Set up the control register if the load succeeded - - * 48 kHz, internal clock, S/PDIF RCA mode */ - if (box_type >= 0) { - err = write_control_reg(chip, E3G_48KHZ, - E3G_FREQ_REG_DEFAULT, TRUE); - if (err < 0) - return err; - } - - return box_type; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg, clock, base_rate, frq_reg; - - /* Only set the clock for internal mode. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - /* Save the rate anyhow */ - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - set_input_clock(chip, chip->input_clock); - return 0; - } - - if (snd_BUG_ON(rate >= 50000 && - chip->digital_mode == DIGITAL_MODE_ADAT)) - return -EINVAL; - - clock = 0; - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= E3G_CLOCK_CLEAR_MASK; - - switch (rate) { - case 96000: - clock = E3G_96KHZ; - break; - case 88200: - clock = E3G_88KHZ; - break; - case 48000: - clock = E3G_48KHZ; - break; - case 44100: - clock = E3G_44KHZ; - break; - case 32000: - clock = E3G_32KHZ; - break; - default: - clock = E3G_CONTINUOUS_CLOCK; - if (rate > 50000) - clock |= E3G_DOUBLE_SPEED_MODE; - break; - } - - control_reg |= clock; - control_reg = set_spdif_bits(chip, control_reg, rate); - - base_rate = rate; - if (base_rate > 50000) - base_rate /= 2; - if (base_rate < 32000) - base_rate = 32000; - - frq_reg = E3G_MAGIC_NUMBER / base_rate - 2; - if (frq_reg > E3G_FREQ_REG_MAX) - frq_reg = E3G_FREQ_REG_MAX; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->sample_rate = rate; - DE_ACT(("SetSampleRate: %d clock %x\n", rate, control_reg)); - - /* Tell the DSP about it - DSP reads both control reg & freq reg */ - return write_control_reg(chip, control_reg, frq_reg, 0); -} - - - -/* Set the sample clock source to internal, S/PDIF, ADAT */ -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - u32 control_reg, clocks_from_dsp; - - DE_ACT(("set_input_clock:\n")); - - /* Mask off the clock select bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register) & - E3G_CLOCK_CLEAR_MASK; - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - switch (clock) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Echo3G clock to INTERNAL\n")); - chip->input_clock = ECHO_CLOCK_INTERNAL; - return set_sample_rate(chip, chip->sample_rate); - case ECHO_CLOCK_SPDIF: - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EAGAIN; - DE_ACT(("Set Echo3G clock to SPDIF\n")); - control_reg |= E3G_SPDIF_CLOCK; - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF96) - control_reg |= E3G_DOUBLE_SPEED_MODE; - else - control_reg &= ~E3G_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ADAT: - if (chip->digital_mode != DIGITAL_MODE_ADAT) - return -EAGAIN; - DE_ACT(("Set Echo3G clock to ADAT\n")); - control_reg |= E3G_ADAT_CLOCK; - control_reg &= ~E3G_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_WORD: - DE_ACT(("Set Echo3G clock to WORD\n")); - control_reg |= E3G_WORD_CLOCK; - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD96) - control_reg |= E3G_DOUBLE_SPEED_MODE; - else - control_reg &= ~E3G_DOUBLE_SPEED_MODE; - break; - default: - DE_ACT(("Input clock 0x%x not supported for Echo3G\n", clock)); - return -EINVAL; - } - - chip->input_clock = clock; - return write_control_reg(chip, control_reg, get_frq_reg(chip), 1); -} - - - -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u32 control_reg; - int err, incompatible_clock; - - /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - case DIGITAL_MODE_SPDIF_RCA: - if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; - break; - case DIGITAL_MODE_ADAT: - if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; - break; - default: - DE_ACT(("Digital mode not supported: %d\n", mode)); - return -EINVAL; - } - - spin_lock_irq(&chip->lock); - - if (incompatible_clock) { - chip->sample_rate = 48000; - set_input_clock(chip, ECHO_CLOCK_INTERNAL); - } - - /* Clear the current digital mode */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= E3G_DIGITAL_MODE_CLEAR_MASK; - - /* Tweak the control reg */ - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - control_reg |= E3G_SPDIF_OPTICAL_MODE; - break; - case DIGITAL_MODE_SPDIF_RCA: - /* E3G_SPDIF_OPTICAL_MODE bit cleared */ - break; - case DIGITAL_MODE_ADAT: - control_reg |= E3G_ADAT_MODE; - control_reg &= ~E3G_DOUBLE_SPEED_MODE; /* @@ useless */ - break; - } - - err = write_control_reg(chip, control_reg, get_frq_reg(chip), 1); - spin_unlock_irq(&chip->lock); - if (err < 0) - return err; - chip->digital_mode = mode; - - DE_ACT(("set_digital_mode(%d)\n", chip->digital_mode)); - return incompatible_clock; -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.c deleted file mode 100644 index d8c670c9..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.c +++ /dev/null @@ -1,1151 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - -#if PAGE_SIZE < 4096 -#error PAGE_SIZE is < 4k -#endif - -static int restore_dsp_rettings(struct echoaudio *chip); - - -/* Some vector commands involve the DSP reading or writing data to and from the -comm page; if you send one of these commands to the DSP, it will complete the -command and then write a non-zero value to the Handshake field in the -comm page. This function waits for the handshake to show up. */ -static int wait_handshake(struct echoaudio *chip) -{ - int i; - - /* Wait up to 20ms for the handshake from the DSP */ - for (i = 0; i < HANDSHAKE_TIMEOUT; i++) { - /* Look for the handshake value */ - barrier(); - if (chip->comm_page->handshake) { - return 0; - } - udelay(1); - } - - snd_printk(KERN_ERR "wait_handshake(): Timeout waiting for DSP\n"); - return -EBUSY; -} - - - -/* Much of the interaction between the DSP and the driver is done via vector -commands; send_vector writes a vector command to the DSP. Typically, this -causes the DSP to read or write fields in the comm page. -PCI posting is not required thanks to the handshake logic. */ -static int send_vector(struct echoaudio *chip, u32 command) -{ - int i; - - wmb(); /* Flush all pending writes before sending the command */ - - /* Wait up to 100ms for the "vector busy" bit to be off */ - for (i = 0; i < VECTOR_BUSY_TIMEOUT; i++) { - if (!(get_dsp_register(chip, CHI32_VECTOR_REG) & - CHI32_VECTOR_BUSY)) { - set_dsp_register(chip, CHI32_VECTOR_REG, command); - /*if (i) DE_ACT(("send_vector time: %d\n", i));*/ - return 0; - } - udelay(1); - } - - DE_ACT((KERN_ERR "timeout on send_vector\n")); - return -EBUSY; -} - - - -/* write_dsp writes a 32-bit value to the DSP; this is used almost -exclusively for loading the DSP. */ -static int write_dsp(struct echoaudio *chip, u32 data) -{ - u32 status, i; - - for (i = 0; i < 10000000; i++) { /* timeout = 10s */ - status = get_dsp_register(chip, CHI32_STATUS_REG); - if ((status & CHI32_STATUS_HOST_WRITE_EMPTY) != 0) { - set_dsp_register(chip, CHI32_DATA_REG, data); - wmb(); /* write it immediately */ - return 0; - } - udelay(1); - cond_resched(); - } - - chip->bad_board = TRUE; /* Set TRUE until DSP re-loaded */ - DE_ACT((KERN_ERR "write_dsp: Set bad_board to TRUE\n")); - return -EIO; -} - - - -/* read_dsp reads a 32-bit value from the DSP; this is used almost -exclusively for loading the DSP and checking the status of the ASIC. */ -static int read_dsp(struct echoaudio *chip, u32 *data) -{ - u32 status, i; - - for (i = 0; i < READ_DSP_TIMEOUT; i++) { - status = get_dsp_register(chip, CHI32_STATUS_REG); - if ((status & CHI32_STATUS_HOST_READ_FULL) != 0) { - *data = get_dsp_register(chip, CHI32_DATA_REG); - return 0; - } - udelay(1); - cond_resched(); - } - - chip->bad_board = TRUE; /* Set TRUE until DSP re-loaded */ - DE_INIT((KERN_ERR "read_dsp: Set bad_board to TRUE\n")); - return -EIO; -} - - - -/**************************************************************************** - Firmware loading functions - ****************************************************************************/ - -/* This function is used to read back the serial number from the DSP; -this is triggered by the SET_COMMPAGE_ADDR command. -Only some early Echogals products have serial numbers in the ROM; -the serial number is not used, but you still need to do this as -part of the DSP load process. */ -static int read_sn(struct echoaudio *chip) -{ - int i; - u32 sn[6]; - - for (i = 0; i < 5; i++) { - if (read_dsp(chip, &sn[i])) { - snd_printk(KERN_ERR "Failed to read serial number\n"); - return -EIO; - } - } - DE_INIT(("Read serial number %08x %08x %08x %08x %08x\n", - sn[0], sn[1], sn[2], sn[3], sn[4])); - return 0; -} - - - -#ifndef ECHOCARD_HAS_ASIC -/* This card has no ASIC, just return ok */ -static inline int check_asic_status(struct echoaudio *chip) -{ - chip->asic_loaded = TRUE; - return 0; -} - -#endif /* !ECHOCARD_HAS_ASIC */ - - - -#ifdef ECHOCARD_HAS_ASIC - -/* Load ASIC code - done after the DSP is loaded */ -static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic) -{ - const struct firmware *fw; - int err; - u32 i, size; - u8 *code; - - err = get_firmware(&fw, chip, asic); - if (err < 0) { - snd_printk(KERN_WARNING "Firmware not found !\n"); - return err; - } - - code = (u8 *)fw->data; - size = fw->size; - - /* Send the "Here comes the ASIC" command */ - if (write_dsp(chip, cmd) < 0) - goto la_error; - - /* Write length of ASIC file in bytes */ - if (write_dsp(chip, size) < 0) - goto la_error; - - for (i = 0; i < size; i++) { - if (write_dsp(chip, code[i]) < 0) - goto la_error; - } - - DE_INIT(("ASIC loaded\n")); - free_firmware(fw); - return 0; - -la_error: - DE_INIT(("failed on write_dsp\n")); - free_firmware(fw); - return -EIO; -} - -#endif /* ECHOCARD_HAS_ASIC */ - - - -#ifdef DSP_56361 - -/* Install the resident loader for 56361 DSPs; The resident loader is on -the EPROM on the board for 56301 DSP. The resident loader is a tiny little -program that is used to load the real DSP code. */ -static int install_resident_loader(struct echoaudio *chip) -{ - u32 address; - int index, words, i; - u16 *code; - u32 status; - const struct firmware *fw; - - /* 56361 cards only! This check is required by the old 56301-based - Mona and Gina24 */ - if (chip->device_id != DEVICE_ID_56361) - return 0; - - /* Look to see if the resident loader is present. If the resident - loader is already installed, host flag 5 will be on. */ - status = get_dsp_register(chip, CHI32_STATUS_REG); - if (status & CHI32_STATUS_REG_HF5) { - DE_INIT(("Resident loader already installed; status is 0x%x\n", - status)); - return 0; - } - - i = get_firmware(&fw, chip, FW_361_LOADER); - if (i < 0) { - snd_printk(KERN_WARNING "Firmware not found !\n"); - return i; - } - - /* The DSP code is an array of 16 bit words. The array is divided up - into sections. The first word of each section is the size in words, - followed by the section type. - Since DSP addresses and data are 24 bits wide, they each take up two - 16 bit words in the array. - This is a lot like the other loader loop, but it's not a loop, you - don't write the memory type, and you don't write a zero at the end. */ - - /* Set DSP format bits for 24 bit mode */ - set_dsp_register(chip, CHI32_CONTROL_REG, - get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); - - code = (u16 *)fw->data; - - /* Skip the header section; the first word in the array is the size - of the first section, so the first real section of code is pointed - to by Code[0]. */ - index = code[0]; - - /* Skip the section size, LRS block type, and DSP memory type */ - index += 3; - - /* Get the number of DSP words to write */ - words = code[index++]; - - /* Get the DSP address for this block; 24 bits, so build from two words */ - address = ((u32)code[index] << 16) + code[index + 1]; - index += 2; - - /* Write the count to the DSP */ - if (write_dsp(chip, words)) { - DE_INIT(("install_resident_loader: Failed to write word count!\n")); - goto irl_error; - } - /* Write the DSP address */ - if (write_dsp(chip, address)) { - DE_INIT(("install_resident_loader: Failed to write DSP address!\n")); - goto irl_error; - } - /* Write out this block of code to the DSP */ - for (i = 0; i < words; i++) { - u32 data; - - data = ((u32)code[index] << 16) + code[index + 1]; - if (write_dsp(chip, data)) { - DE_INIT(("install_resident_loader: Failed to write DSP code\n")); - goto irl_error; - } - index += 2; - } - - /* Wait for flag 5 to come up */ - for (i = 0; i < 200; i++) { /* Timeout is 50us * 200 = 10ms */ - udelay(50); - status = get_dsp_register(chip, CHI32_STATUS_REG); - if (status & CHI32_STATUS_REG_HF5) - break; - } - - if (i == 200) { - DE_INIT(("Resident loader failed to set HF5\n")); - goto irl_error; - } - - DE_INIT(("Resident loader successfully installed\n")); - free_firmware(fw); - return 0; - -irl_error: - free_firmware(fw); - return -EIO; -} - -#endif /* DSP_56361 */ - - -static int load_dsp(struct echoaudio *chip, u16 *code) -{ - u32 address, data; - int index, words, i; - - if (chip->dsp_code == code) { - DE_INIT(("DSP is already loaded!\n")); - return 0; - } - chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ - chip->dsp_code = NULL; /* Current DSP code not loaded */ - chip->asic_loaded = FALSE; /* Loading the DSP code will reset the ASIC */ - - DE_INIT(("load_dsp: Set bad_board to TRUE\n")); - - /* If this board requires a resident loader, install it. */ -#ifdef DSP_56361 - if ((i = install_resident_loader(chip)) < 0) - return i; -#endif - - /* Send software reset command */ - if (send_vector(chip, DSP_VC_RESET) < 0) { - DE_INIT(("LoadDsp: send_vector DSP_VC_RESET failed, Critical Failure\n")); - return -EIO; - } - /* Delay 10us */ - udelay(10); - - /* Wait 10ms for HF3 to indicate that software reset is complete */ - for (i = 0; i < 1000; i++) { /* Timeout is 10us * 1000 = 10ms */ - if (get_dsp_register(chip, CHI32_STATUS_REG) & - CHI32_STATUS_REG_HF3) - break; - udelay(10); - } - - if (i == 1000) { - DE_INIT(("load_dsp: Timeout waiting for CHI32_STATUS_REG_HF3\n")); - return -EIO; - } - - /* Set DSP format bits for 24 bit mode now that soft reset is done */ - set_dsp_register(chip, CHI32_CONTROL_REG, - get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); - - /* Main loader loop */ - - index = code[0]; - for (;;) { - int block_type, mem_type; - - /* Total Block Size */ - index++; - - /* Block Type */ - block_type = code[index]; - if (block_type == 4) /* We're finished */ - break; - - index++; - - /* Memory Type P=0,X=1,Y=2 */ - mem_type = code[index++]; - - /* Block Code Size */ - words = code[index++]; - if (words == 0) /* We're finished */ - break; - - /* Start Address */ - address = ((u32)code[index] << 16) + code[index + 1]; - index += 2; - - if (write_dsp(chip, words) < 0) { - DE_INIT(("load_dsp: failed to write number of DSP words\n")); - return -EIO; - } - if (write_dsp(chip, address) < 0) { - DE_INIT(("load_dsp: failed to write DSP address\n")); - return -EIO; - } - if (write_dsp(chip, mem_type) < 0) { - DE_INIT(("load_dsp: failed to write DSP memory type\n")); - return -EIO; - } - /* Code */ - for (i = 0; i < words; i++, index+=2) { - data = ((u32)code[index] << 16) + code[index + 1]; - if (write_dsp(chip, data) < 0) { - DE_INIT(("load_dsp: failed to write DSP data\n")); - return -EIO; - } - } - } - - if (write_dsp(chip, 0) < 0) { /* We're done!!! */ - DE_INIT(("load_dsp: Failed to write final zero\n")); - return -EIO; - } - udelay(10); - - for (i = 0; i < 5000; i++) { /* Timeout is 100us * 5000 = 500ms */ - /* Wait for flag 4 - indicates that the DSP loaded OK */ - if (get_dsp_register(chip, CHI32_STATUS_REG) & - CHI32_STATUS_REG_HF4) { - set_dsp_register(chip, CHI32_CONTROL_REG, - get_dsp_register(chip, CHI32_CONTROL_REG) & ~0x1b00); - - if (write_dsp(chip, DSP_FNC_SET_COMMPAGE_ADDR) < 0) { - DE_INIT(("load_dsp: Failed to write DSP_FNC_SET_COMMPAGE_ADDR\n")); - return -EIO; - } - - if (write_dsp(chip, chip->comm_page_phys) < 0) { - DE_INIT(("load_dsp: Failed to write comm page address\n")); - return -EIO; - } - - /* Get the serial number via slave mode. - This is triggered by the SET_COMMPAGE_ADDR command. - We don't actually use the serial number but we have to - get it as part of the DSP init voodoo. */ - if (read_sn(chip) < 0) { - DE_INIT(("load_dsp: Failed to read serial number\n")); - return -EIO; - } - - chip->dsp_code = code; /* Show which DSP code loaded */ - chip->bad_board = FALSE; /* DSP OK */ - DE_INIT(("load_dsp: OK!\n")); - return 0; - } - udelay(100); - } - - DE_INIT(("load_dsp: DSP load timed out waiting for HF4\n")); - return -EIO; -} - - - -/* load_firmware takes care of loading the DSP and any ASIC code. */ -static int load_firmware(struct echoaudio *chip) -{ - const struct firmware *fw; - int box_type, err; - - if (snd_BUG_ON(!chip->comm_page)) - return -EPERM; - - /* See if the ASIC is present and working - only if the DSP is already loaded */ - if (chip->dsp_code) { - if ((box_type = check_asic_status(chip)) >= 0) - return box_type; - /* ASIC check failed; force the DSP to reload */ - chip->dsp_code = NULL; - } - - err = get_firmware(&fw, chip, chip->dsp_code_to_load); - if (err < 0) - return err; - err = load_dsp(chip, (u16 *)fw->data); - free_firmware(fw); - if (err < 0) - return err; - - if ((box_type = load_asic(chip)) < 0) - return box_type; /* error */ - - return box_type; -} - - - -/**************************************************************************** - Mixer functions - ****************************************************************************/ - -#if defined(ECHOCARD_HAS_INPUT_NOMINAL_LEVEL) || \ - defined(ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL) - -/* Set the nominal level for an input or output bus (true = -10dBV, false = +4dBu) */ -static int set_nominal_level(struct echoaudio *chip, u16 index, char consumer) -{ - if (snd_BUG_ON(index >= num_busses_out(chip) + num_busses_in(chip))) - return -EINVAL; - - /* Wait for the handshake (OK even if ASIC is not loaded) */ - if (wait_handshake(chip)) - return -EIO; - - chip->nominal_level[index] = consumer; - - if (consumer) - chip->comm_page->nominal_level_mask |= cpu_to_le32(1 << index); - else - chip->comm_page->nominal_level_mask &= ~cpu_to_le32(1 << index); - - return 0; -} - -#endif /* ECHOCARD_HAS_*_NOMINAL_LEVEL */ - - - -/* Set the gain for a single physical output channel (dB). */ -static int set_output_gain(struct echoaudio *chip, u16 channel, s8 gain) -{ - if (snd_BUG_ON(channel >= num_busses_out(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - /* Save the new value */ - chip->output_gain[channel] = gain; - chip->comm_page->line_out_level[channel] = gain; - return 0; -} - - - -#ifdef ECHOCARD_HAS_MONITOR -/* Set the monitor level from an input bus to an output bus. */ -static int set_monitor_gain(struct echoaudio *chip, u16 output, u16 input, - s8 gain) -{ - if (snd_BUG_ON(output >= num_busses_out(chip) || - input >= num_busses_in(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - chip->monitor_gain[output][input] = gain; - chip->comm_page->monitors[monitor_index(chip, output, input)] = gain; - return 0; -} -#endif /* ECHOCARD_HAS_MONITOR */ - - -/* Tell the DSP to read and update output, nominal & monitor levels in comm page. */ -static int update_output_line_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_OUTVOL); -} - - - -/* Tell the DSP to read and update input levels in comm page */ -static int update_input_line_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_INGAIN); -} - - - -/* set_meters_on turns the meters on or off. If meters are turned on, the DSP -will write the meter and clock detect values to the comm page at about 30Hz */ -static void set_meters_on(struct echoaudio *chip, char on) -{ - if (on && !chip->meters_enabled) { - send_vector(chip, DSP_VC_METERS_ON); - chip->meters_enabled = 1; - } else if (!on && chip->meters_enabled) { - send_vector(chip, DSP_VC_METERS_OFF); - chip->meters_enabled = 0; - memset((s8 *)chip->comm_page->vu_meter, ECHOGAIN_MUTED, - DSP_MAXPIPES); - memset((s8 *)chip->comm_page->peak_meter, ECHOGAIN_MUTED, - DSP_MAXPIPES); - } -} - - - -/* Fill out an the given array using the current values in the comm page. -Meters are written in the comm page by the DSP in this order: - Output busses - Input busses - Output pipes (vmixer cards only) - -This function assumes there are no more than 16 in/out busses or pipes -Meters is an array [3][16][2] of long. */ -static void get_audio_meters(struct echoaudio *chip, long *meters) -{ - int i, m, n; - - m = 0; - n = 0; - for (i = 0; i < num_busses_out(chip); i++, m++) { - meters[n++] = chip->comm_page->vu_meter[m]; - meters[n++] = chip->comm_page->peak_meter[m]; - } - for (; n < 32; n++) - meters[n] = 0; - -#ifdef ECHOCARD_ECHO3G - m = E3G_MAX_OUTPUTS; /* Skip unused meters */ -#endif - - for (i = 0; i < num_busses_in(chip); i++, m++) { - meters[n++] = chip->comm_page->vu_meter[m]; - meters[n++] = chip->comm_page->peak_meter[m]; - } - for (; n < 64; n++) - meters[n] = 0; - -#ifdef ECHOCARD_HAS_VMIXER - for (i = 0; i < num_pipes_out(chip); i++, m++) { - meters[n++] = chip->comm_page->vu_meter[m]; - meters[n++] = chip->comm_page->peak_meter[m]; - } -#endif - for (; n < 96; n++) - meters[n] = 0; -} - - - -static int restore_dsp_rettings(struct echoaudio *chip) -{ - int i, o, err; - DE_INIT(("restore_dsp_settings\n")); - - if ((err = check_asic_status(chip)) < 0) - return err; - - /* Gina20/Darla20 only. Should be harmless for other cards. */ - chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF; - chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF; - chip->comm_page->handshake = 0xffffffff; - - /* Restore output busses */ - for (i = 0; i < num_busses_out(chip); i++) { - err = set_output_gain(chip, i, chip->output_gain[i]); - if (err < 0) - return err; - } - -#ifdef ECHOCARD_HAS_VMIXER - for (i = 0; i < num_pipes_out(chip); i++) - for (o = 0; o < num_busses_out(chip); o++) { - err = set_vmixer_gain(chip, o, i, - chip->vmixer_gain[o][i]); - if (err < 0) - return err; - } - if (update_vmixer_level(chip) < 0) - return -EIO; -#endif /* ECHOCARD_HAS_VMIXER */ - -#ifdef ECHOCARD_HAS_MONITOR - for (o = 0; o < num_busses_out(chip); o++) - for (i = 0; i < num_busses_in(chip); i++) { - err = set_monitor_gain(chip, o, i, - chip->monitor_gain[o][i]); - if (err < 0) - return err; - } -#endif /* ECHOCARD_HAS_MONITOR */ - -#ifdef ECHOCARD_HAS_INPUT_GAIN - for (i = 0; i < num_busses_in(chip); i++) { - err = set_input_gain(chip, i, chip->input_gain[i]); - if (err < 0) - return err; - } -#endif /* ECHOCARD_HAS_INPUT_GAIN */ - - err = update_output_line_level(chip); - if (err < 0) - return err; - - err = update_input_line_level(chip); - if (err < 0) - return err; - - err = set_sample_rate(chip, chip->sample_rate); - if (err < 0) - return err; - - if (chip->meters_enabled) { - err = send_vector(chip, DSP_VC_METERS_ON); - if (err < 0) - return err; - } - -#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH - if (set_digital_mode(chip, chip->digital_mode) < 0) - return -EIO; -#endif - -#ifdef ECHOCARD_HAS_DIGITAL_IO - if (set_professional_spdif(chip, chip->professional_spdif) < 0) - return -EIO; -#endif - -#ifdef ECHOCARD_HAS_PHANTOM_POWER - if (set_phantom_power(chip, chip->phantom_power) < 0) - return -EIO; -#endif - -#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK - /* set_input_clock() also restores automute setting */ - if (set_input_clock(chip, chip->input_clock) < 0) - return -EIO; -#endif - -#ifdef ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH - if (set_output_clock(chip, chip->output_clock) < 0) - return -EIO; -#endif - - if (wait_handshake(chip) < 0) - return -EIO; - clear_handshake(chip); - if (send_vector(chip, DSP_VC_UPDATE_FLAGS) < 0) - return -EIO; - - DE_INIT(("restore_dsp_rettings done\n")); - return 0; -} - - - -/**************************************************************************** - Transport functions - ****************************************************************************/ - -/* set_audio_format() sets the format of the audio data in host memory for -this pipe. Note that _MS_ (mono-to-stereo) playback modes are not used by ALSA -but they are here because they are just mono while capturing */ -static void set_audio_format(struct echoaudio *chip, u16 pipe_index, - const struct audioformat *format) -{ - u16 dsp_format; - - dsp_format = DSP_AUDIOFORM_SS_16LE; - - /* Look for super-interleave (no big-endian and 8 bits) */ - if (format->interleave > 2) { - switch (format->bits_per_sample) { - case 16: - dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE; - break; - case 24: - dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE; - break; - case 32: - dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE; - break; - } - dsp_format |= format->interleave; - } else if (format->data_are_bigendian) { - /* For big-endian data, only 32 bit samples are supported */ - switch (format->interleave) { - case 1: - dsp_format = DSP_AUDIOFORM_MM_32BE; - break; -#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - case 2: - dsp_format = DSP_AUDIOFORM_SS_32BE; - break; -#endif - } - } else if (format->interleave == 1 && - format->bits_per_sample == 32 && !format->mono_to_stereo) { - /* 32 bit little-endian mono->mono case */ - dsp_format = DSP_AUDIOFORM_MM_32LE; - } else { - /* Handle the other little-endian formats */ - switch (format->bits_per_sample) { - case 8: - if (format->interleave == 2) - dsp_format = DSP_AUDIOFORM_SS_8; - else - dsp_format = DSP_AUDIOFORM_MS_8; - break; - default: - case 16: - if (format->interleave == 2) - dsp_format = DSP_AUDIOFORM_SS_16LE; - else - dsp_format = DSP_AUDIOFORM_MS_16LE; - break; - case 24: - if (format->interleave == 2) - dsp_format = DSP_AUDIOFORM_SS_24LE; - else - dsp_format = DSP_AUDIOFORM_MS_24LE; - break; - case 32: - if (format->interleave == 2) - dsp_format = DSP_AUDIOFORM_SS_32LE; - else - dsp_format = DSP_AUDIOFORM_MS_32LE; - break; - } - } - DE_ACT(("set_audio_format[%d] = %x\n", pipe_index, dsp_format)); - chip->comm_page->audio_format[pipe_index] = cpu_to_le16(dsp_format); -} - - - -/* start_transport starts transport for a set of pipes. -The bits 1 in channel_mask specify what pipes to start. Only the bit of the -first channel must be set, regardless its interleave. -Same thing for pause_ and stop_ -trasport below. */ -static int start_transport(struct echoaudio *chip, u32 channel_mask, - u32 cyclic_mask) -{ - DE_ACT(("start_transport %x\n", channel_mask)); - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->cmd_start |= cpu_to_le32(channel_mask); - - if (chip->comm_page->cmd_start) { - clear_handshake(chip); - send_vector(chip, DSP_VC_START_TRANSFER); - if (wait_handshake(chip)) - return -EIO; - /* Keep track of which pipes are transporting */ - chip->active_mask |= channel_mask; - chip->comm_page->cmd_start = 0; - return 0; - } - - DE_ACT(("start_transport: No pipes to start!\n")); - return -EINVAL; -} - - - -static int pause_transport(struct echoaudio *chip, u32 channel_mask) -{ - DE_ACT(("pause_transport %x\n", channel_mask)); - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->cmd_stop |= cpu_to_le32(channel_mask); - chip->comm_page->cmd_reset = 0; - if (chip->comm_page->cmd_stop) { - clear_handshake(chip); - send_vector(chip, DSP_VC_STOP_TRANSFER); - if (wait_handshake(chip)) - return -EIO; - /* Keep track of which pipes are transporting */ - chip->active_mask &= ~channel_mask; - chip->comm_page->cmd_stop = 0; - chip->comm_page->cmd_reset = 0; - return 0; - } - - DE_ACT(("pause_transport: No pipes to stop!\n")); - return 0; -} - - - -static int stop_transport(struct echoaudio *chip, u32 channel_mask) -{ - DE_ACT(("stop_transport %x\n", channel_mask)); - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->cmd_stop |= cpu_to_le32(channel_mask); - chip->comm_page->cmd_reset |= cpu_to_le32(channel_mask); - if (chip->comm_page->cmd_reset) { - clear_handshake(chip); - send_vector(chip, DSP_VC_STOP_TRANSFER); - if (wait_handshake(chip)) - return -EIO; - /* Keep track of which pipes are transporting */ - chip->active_mask &= ~channel_mask; - chip->comm_page->cmd_stop = 0; - chip->comm_page->cmd_reset = 0; - return 0; - } - - DE_ACT(("stop_transport: No pipes to stop!\n")); - return 0; -} - - - -static inline int is_pipe_allocated(struct echoaudio *chip, u16 pipe_index) -{ - return (chip->pipe_alloc_mask & (1 << pipe_index)); -} - - - -/* Stops everything and turns off the DSP. All pipes should be already -stopped and unallocated. */ -static int rest_in_peace(struct echoaudio *chip) -{ - DE_ACT(("rest_in_peace() open=%x\n", chip->pipe_alloc_mask)); - - /* Stops all active pipes (just to be sure) */ - stop_transport(chip, chip->active_mask); - - set_meters_on(chip, FALSE); - -#ifdef ECHOCARD_HAS_MIDI - enable_midi_input(chip, FALSE); -#endif - - /* Go to sleep */ - if (chip->dsp_code) { - /* Make load_firmware do a complete reload */ - chip->dsp_code = NULL; - /* Put the DSP to sleep */ - return send_vector(chip, DSP_VC_GO_COMATOSE); - } - return 0; -} - - - -/* Fills the comm page with default values */ -static int init_dsp_comm_page(struct echoaudio *chip) -{ - /* Check if the compiler added extra padding inside the structure */ - if (offsetof(struct comm_page, midi_output) != 0xbe0) { - DE_INIT(("init_dsp_comm_page() - Invalid struct comm_page structure\n")); - return -EPERM; - } - - /* Init all the basic stuff */ - chip->card_name = ECHOCARD_NAME; - chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ - chip->dsp_code = NULL; /* Current DSP code not loaded */ - chip->asic_loaded = FALSE; - memset(chip->comm_page, 0, sizeof(struct comm_page)); - - /* Init the comm page */ - chip->comm_page->comm_size = - cpu_to_le32(sizeof(struct comm_page)); - chip->comm_page->handshake = 0xffffffff; - chip->comm_page->midi_out_free_count = - cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE); - chip->comm_page->sample_rate = cpu_to_le32(44100); - - /* Set line levels so we don't blast any inputs on startup */ - memset(chip->comm_page->monitors, ECHOGAIN_MUTED, MONITOR_ARRAY_SIZE); - memset(chip->comm_page->vmixer, ECHOGAIN_MUTED, VMIXER_ARRAY_SIZE); - - return 0; -} - - - -/* This function initializes the chip structure with default values, ie. all - * muted and internal clock source. Then it copies the settings to the DSP. - * This MUST be called after the DSP is up and running ! - */ -static int init_line_levels(struct echoaudio *chip) -{ - DE_INIT(("init_line_levels\n")); - memset(chip->output_gain, ECHOGAIN_MUTED, sizeof(chip->output_gain)); - memset(chip->input_gain, ECHOGAIN_MUTED, sizeof(chip->input_gain)); - memset(chip->monitor_gain, ECHOGAIN_MUTED, sizeof(chip->monitor_gain)); - memset(chip->vmixer_gain, ECHOGAIN_MUTED, sizeof(chip->vmixer_gain)); - chip->input_clock = ECHO_CLOCK_INTERNAL; - chip->output_clock = ECHO_CLOCK_WORD; - chip->sample_rate = 44100; - return restore_dsp_rettings(chip); -} - - - -/* This is low level part of the interrupt handler. -It returns -1 if the IRQ is not ours, or N>=0 if it is, where N is the number -of midi data in the input queue. */ -static int service_irq(struct echoaudio *chip) -{ - int st; - - /* Read the DSP status register and see if this DSP generated this interrupt */ - if (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_IRQ) { - st = 0; -#ifdef ECHOCARD_HAS_MIDI - /* Get and parse midi data if present */ - if (chip->comm_page->midi_input[0]) /* The count is at index 0 */ - st = midi_service_irq(chip); /* Returns how many midi bytes we received */ -#endif - /* Clear the hardware interrupt */ - chip->comm_page->midi_input[0] = 0; - send_vector(chip, DSP_VC_ACK_INT); - return st; - } - return -1; -} - - - - -/****************************************************************************** - Functions for opening and closing pipes - ******************************************************************************/ - -/* allocate_pipes is used to reserve audio pipes for your exclusive use. -The call will fail if some pipes are already allocated. */ -static int allocate_pipes(struct echoaudio *chip, struct audiopipe *pipe, - int pipe_index, int interleave) -{ - int i; - u32 channel_mask; - char is_cyclic; - - DE_ACT(("allocate_pipes: ch=%d int=%d\n", pipe_index, interleave)); - - if (chip->bad_board) - return -EIO; - - is_cyclic = 1; /* This driver uses cyclic buffers only */ - - for (channel_mask = i = 0; i < interleave; i++) - channel_mask |= 1 << (pipe_index + i); - if (chip->pipe_alloc_mask & channel_mask) { - DE_ACT(("allocate_pipes: channel already open\n")); - return -EAGAIN; - } - - chip->comm_page->position[pipe_index] = 0; - chip->pipe_alloc_mask |= channel_mask; - if (is_cyclic) - chip->pipe_cyclic_mask |= channel_mask; - pipe->index = pipe_index; - pipe->interleave = interleave; - pipe->state = PIPE_STATE_STOPPED; - - /* The counter register is where the DSP writes the 32 bit DMA - position for a pipe. The DSP is constantly updating this value as - it moves data. The DMA counter is in units of bytes, not samples. */ - pipe->dma_counter = &chip->comm_page->position[pipe_index]; - *pipe->dma_counter = 0; - DE_ACT(("allocate_pipes: ok\n")); - return pipe_index; -} - - - -static int free_pipes(struct echoaudio *chip, struct audiopipe *pipe) -{ - u32 channel_mask; - int i; - - DE_ACT(("free_pipes: Pipe %d\n", pipe->index)); - if (snd_BUG_ON(!is_pipe_allocated(chip, pipe->index))) - return -EINVAL; - if (snd_BUG_ON(pipe->state != PIPE_STATE_STOPPED)) - return -EINVAL; - - for (channel_mask = i = 0; i < pipe->interleave; i++) - channel_mask |= 1 << (pipe->index + i); - - chip->pipe_alloc_mask &= ~channel_mask; - chip->pipe_cyclic_mask &= ~channel_mask; - return 0; -} - - - -/****************************************************************************** - Functions for managing the scatter-gather list -******************************************************************************/ - -static int sglist_init(struct echoaudio *chip, struct audiopipe *pipe) -{ - pipe->sglist_head = 0; - memset(pipe->sgpage.area, 0, PAGE_SIZE); - chip->comm_page->sglist_addr[pipe->index].addr = - cpu_to_le32(pipe->sgpage.addr); - return 0; -} - - - -static int sglist_add_mapping(struct echoaudio *chip, struct audiopipe *pipe, - dma_addr_t address, size_t length) -{ - int head = pipe->sglist_head; - struct sg_entry *list = (struct sg_entry *)pipe->sgpage.area; - - if (head < MAX_SGLIST_ENTRIES - 1) { - list[head].addr = cpu_to_le32(address); - list[head].size = cpu_to_le32(length); - pipe->sglist_head++; - } else { - DE_ACT(("SGlist: too many fragments\n")); - return -ENOMEM; - } - return 0; -} - - - -static inline int sglist_add_irq(struct echoaudio *chip, struct audiopipe *pipe) -{ - return sglist_add_mapping(chip, pipe, 0, 0); -} - - - -static inline int sglist_wrap(struct echoaudio *chip, struct audiopipe *pipe) -{ - return sglist_add_mapping(chip, pipe, pipe->sgpage.addr, 0); -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.h b/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.h deleted file mode 100644 index cb7d75a0..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_dsp.h +++ /dev/null @@ -1,698 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - -#ifndef _ECHO_DSP_ -#define _ECHO_DSP_ - - -/**** Echogals: Darla20, Gina20, Layla20, and Darla24 ****/ -#if defined(ECHOGALS_FAMILY) - -#define NUM_ASIC_TESTS 5 -#define READ_DSP_TIMEOUT 1000000L /* one second */ - -/**** Echo24: Gina24, Layla24, Mona, Mia, Mia-midi ****/ -#elif defined(ECHO24_FAMILY) - -#define DSP_56361 /* Some Echo24 cards use the 56361 DSP */ -#define READ_DSP_TIMEOUT 100000L /* .1 second */ - -/**** 3G: Gina3G, Layla3G ****/ -#elif defined(ECHO3G_FAMILY) - -#define DSP_56361 -#define READ_DSP_TIMEOUT 100000L /* .1 second */ -#define MIN_MTC_1X_RATE 32000 - -/**** Indigo: Indigo, Indigo IO, Indigo DJ ****/ -#elif defined(INDIGO_FAMILY) - -#define DSP_56361 -#define READ_DSP_TIMEOUT 100000L /* .1 second */ - -#else - -#error No family is defined - -#endif - - - -/* - * - * Max inputs and outputs - * - */ - -#define DSP_MAXAUDIOINPUTS 16 /* Max audio input channels */ -#define DSP_MAXAUDIOOUTPUTS 16 /* Max audio output channels */ -#define DSP_MAXPIPES 32 /* Max total pipes (input + output) */ - - -/* - * - * These are the offsets for the memory-mapped DSP registers; the DSP base - * address is treated as the start of a u32 array. - */ - -#define CHI32_CONTROL_REG 4 -#define CHI32_STATUS_REG 5 -#define CHI32_VECTOR_REG 6 -#define CHI32_DATA_REG 7 - - -/* - * - * Interesting bits within the DSP registers - * - */ - -#define CHI32_VECTOR_BUSY 0x00000001 -#define CHI32_STATUS_REG_HF3 0x00000008 -#define CHI32_STATUS_REG_HF4 0x00000010 -#define CHI32_STATUS_REG_HF5 0x00000020 -#define CHI32_STATUS_HOST_READ_FULL 0x00000004 -#define CHI32_STATUS_HOST_WRITE_EMPTY 0x00000002 -#define CHI32_STATUS_IRQ 0x00000040 - - -/* - * - * DSP commands sent via slave mode; these are sent to the DSP by write_dsp() - * - */ - -#define DSP_FNC_SET_COMMPAGE_ADDR 0x02 -#define DSP_FNC_LOAD_LAYLA_ASIC 0xa0 -#define DSP_FNC_LOAD_GINA24_ASIC 0xa0 -#define DSP_FNC_LOAD_MONA_PCI_CARD_ASIC 0xa0 -#define DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC 0xa0 -#define DSP_FNC_LOAD_MONA_EXTERNAL_ASIC 0xa1 -#define DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC 0xa1 -#define DSP_FNC_LOAD_3G_ASIC 0xa0 - - -/* - * - * Defines to handle the MIDI input state engine; these are used to properly - * extract MIDI time code bytes and their timestamps from the MIDI input stream. - * - */ - -#define MIDI_IN_STATE_NORMAL 0 -#define MIDI_IN_STATE_TS_HIGH 1 -#define MIDI_IN_STATE_TS_LOW 2 -#define MIDI_IN_STATE_F1_DATA 3 -#define MIDI_IN_SKIP_DATA (-1) - - -/*---------------------------------------------------------------------------- - -Setting the sample rates on Layla24 is somewhat schizophrenic. - -For standard rates, it works exactly like Mona and Gina24. That is, for -8, 11.025, 16, 22.05, 32, 44.1, 48, 88.2, and 96 kHz, you just set the -appropriate bits in the control register and write the control register. - -In order to support MIDI time code sync (and possibly SMPTE LTC sync in -the future), Layla24 also has "continuous sample rate mode". In this mode, -Layla24 can generate any sample rate between 25 and 50 kHz inclusive, or -50 to 100 kHz inclusive for double speed mode. - -To use continuous mode: - --Set the clock select bits in the control register to 0xe (see the #define - below) - --Set double-speed mode if you want to use sample rates above 50 kHz - --Write the control register as you would normally - --Now, you need to set the frequency register. First, you need to determine the - value for the frequency register. This is given by the following formula: - -frequency_reg = (LAYLA24_MAGIC_NUMBER / sample_rate) - 2 - -Note the #define below for the magic number - --Wait for the DSP handshake --Write the frequency_reg value to the .SampleRate field of the comm page --Send the vector command SET_LAYLA24_FREQUENCY_REG (see vmonkey.h) - -Once you have set the control register up for continuous mode, you can just -write the frequency register to change the sample rate. This could be -used for MIDI time code sync. For MTC sync, the control register is set for -continuous mode. The driver then just keeps writing the -SET_LAYLA24_FREQUENCY_REG command. - ------------------------------------------------------------------------------*/ - -#define LAYLA24_MAGIC_NUMBER 677376000 -#define LAYLA24_CONTINUOUS_CLOCK 0x000e - - -/* - * - * DSP vector commands - * - */ - -#define DSP_VC_RESET 0x80ff - -#ifndef DSP_56361 - -#define DSP_VC_ACK_INT 0x8073 -#define DSP_VC_SET_VMIXER_GAIN 0x0000 /* Not used, only for compile */ -#define DSP_VC_START_TRANSFER 0x0075 /* Handshke rqd. */ -#define DSP_VC_METERS_ON 0x0079 -#define DSP_VC_METERS_OFF 0x007b -#define DSP_VC_UPDATE_OUTVOL 0x007d /* Handshke rqd. */ -#define DSP_VC_UPDATE_INGAIN 0x007f /* Handshke rqd. */ -#define DSP_VC_ADD_AUDIO_BUFFER 0x0081 /* Handshke rqd. */ -#define DSP_VC_TEST_ASIC 0x00eb -#define DSP_VC_UPDATE_CLOCKS 0x00ef /* Handshke rqd. */ -#define DSP_VC_SET_LAYLA_SAMPLE_RATE 0x00f1 /* Handshke rqd. */ -#define DSP_VC_SET_GD_AUDIO_STATE 0x00f1 /* Handshke rqd. */ -#define DSP_VC_WRITE_CONTROL_REG 0x00f1 /* Handshke rqd. */ -#define DSP_VC_MIDI_WRITE 0x00f5 /* Handshke rqd. */ -#define DSP_VC_STOP_TRANSFER 0x00f7 /* Handshke rqd. */ -#define DSP_VC_UPDATE_FLAGS 0x00fd /* Handshke rqd. */ -#define DSP_VC_GO_COMATOSE 0x00f9 - -#else /* !DSP_56361 */ - -/* Vector commands for families that use either the 56301 or 56361 */ -#define DSP_VC_ACK_INT 0x80F5 -#define DSP_VC_SET_VMIXER_GAIN 0x00DB /* Handshke rqd. */ -#define DSP_VC_START_TRANSFER 0x00DD /* Handshke rqd. */ -#define DSP_VC_METERS_ON 0x00EF -#define DSP_VC_METERS_OFF 0x00F1 -#define DSP_VC_UPDATE_OUTVOL 0x00E3 /* Handshke rqd. */ -#define DSP_VC_UPDATE_INGAIN 0x00E5 /* Handshke rqd. */ -#define DSP_VC_ADD_AUDIO_BUFFER 0x00E1 /* Handshke rqd. */ -#define DSP_VC_TEST_ASIC 0x00ED -#define DSP_VC_UPDATE_CLOCKS 0x00E9 /* Handshke rqd. */ -#define DSP_VC_SET_LAYLA24_FREQUENCY_REG 0x00E9 /* Handshke rqd. */ -#define DSP_VC_SET_LAYLA_SAMPLE_RATE 0x00EB /* Handshke rqd. */ -#define DSP_VC_SET_GD_AUDIO_STATE 0x00EB /* Handshke rqd. */ -#define DSP_VC_WRITE_CONTROL_REG 0x00EB /* Handshke rqd. */ -#define DSP_VC_MIDI_WRITE 0x00E7 /* Handshke rqd. */ -#define DSP_VC_STOP_TRANSFER 0x00DF /* Handshke rqd. */ -#define DSP_VC_UPDATE_FLAGS 0x00FB /* Handshke rqd. */ -#define DSP_VC_GO_COMATOSE 0x00d9 - -#endif /* !DSP_56361 */ - - -/* - * - * Timeouts - * - */ - -#define HANDSHAKE_TIMEOUT 20000 /* send_vector command timeout (20ms) */ -#define VECTOR_BUSY_TIMEOUT 100000 /* 100ms */ -#define MIDI_OUT_DELAY_USEC 2000 /* How long to wait after MIDI fills up */ - - -/* - * - * Flags for .Flags field in the comm page - * - */ - -#define DSP_FLAG_MIDI_INPUT 0x0001 /* Enable MIDI input */ -#define DSP_FLAG_SPDIF_NONAUDIO 0x0002 /* Sets the "non-audio" bit - * in the S/PDIF out status - * bits. Clear this flag for - * audio data; - * set it for AC3 or WMA or - * some such */ -#define DSP_FLAG_PROFESSIONAL_SPDIF 0x0008 /* 1 Professional, 0 Consumer */ - - -/* - * - * Clock detect bits reported by the DSP for Gina20, Layla20, Darla24, and Mia - * - */ - -#define GLDM_CLOCK_DETECT_BIT_WORD 0x0002 -#define GLDM_CLOCK_DETECT_BIT_SUPER 0x0004 -#define GLDM_CLOCK_DETECT_BIT_SPDIF 0x0008 -#define GLDM_CLOCK_DETECT_BIT_ESYNC 0x0010 - - -/* - * - * Clock detect bits reported by the DSP for Gina24, Mona, and Layla24 - * - */ - -#define GML_CLOCK_DETECT_BIT_WORD96 0x0002 -#define GML_CLOCK_DETECT_BIT_WORD48 0x0004 -#define GML_CLOCK_DETECT_BIT_SPDIF48 0x0008 -#define GML_CLOCK_DETECT_BIT_SPDIF96 0x0010 -#define GML_CLOCK_DETECT_BIT_WORD (GML_CLOCK_DETECT_BIT_WORD96 | GML_CLOCK_DETECT_BIT_WORD48) -#define GML_CLOCK_DETECT_BIT_SPDIF (GML_CLOCK_DETECT_BIT_SPDIF48 | GML_CLOCK_DETECT_BIT_SPDIF96) -#define GML_CLOCK_DETECT_BIT_ESYNC 0x0020 -#define GML_CLOCK_DETECT_BIT_ADAT 0x0040 - - -/* - * - * Layla clock numbers to send to DSP - * - */ - -#define LAYLA20_CLOCK_INTERNAL 0 -#define LAYLA20_CLOCK_SPDIF 1 -#define LAYLA20_CLOCK_WORD 2 -#define LAYLA20_CLOCK_SUPER 3 - - -/* - * - * Gina/Darla clock states - * - */ - -#define GD_CLOCK_NOCHANGE 0 -#define GD_CLOCK_44 1 -#define GD_CLOCK_48 2 -#define GD_CLOCK_SPDIFIN 3 -#define GD_CLOCK_UNDEF 0xff - - -/* - * - * Gina/Darla S/PDIF status bits - * - */ - -#define GD_SPDIF_STATUS_NOCHANGE 0 -#define GD_SPDIF_STATUS_44 1 -#define GD_SPDIF_STATUS_48 2 -#define GD_SPDIF_STATUS_UNDEF 0xff - - -/* - * - * Layla20 output clocks - * - */ - -#define LAYLA20_OUTPUT_CLOCK_SUPER 0 -#define LAYLA20_OUTPUT_CLOCK_WORD 1 - - -/**************************************************************************** - - Magic constants for the Darla24 hardware - - ****************************************************************************/ - -#define GD24_96000 0x0 -#define GD24_48000 0x1 -#define GD24_44100 0x2 -#define GD24_32000 0x3 -#define GD24_22050 0x4 -#define GD24_16000 0x5 -#define GD24_11025 0x6 -#define GD24_8000 0x7 -#define GD24_88200 0x8 -#define GD24_EXT_SYNC 0x9 - - -/* - * - * Return values from the DSP when ASIC is loaded - * - */ - -#define ASIC_ALREADY_LOADED 0x1 -#define ASIC_NOT_LOADED 0x0 - - -/* - * - * DSP Audio formats - * - * These are the audio formats that the DSP can transfer - * via input and output pipes. LE means little-endian, - * BE means big-endian. - * - * DSP_AUDIOFORM_MS_8 - * - * 8-bit mono unsigned samples. For playback, - * mono data is duplicated out the left and right channels - * of the output bus. The "MS" part of the name - * means mono->stereo. - * - * DSP_AUDIOFORM_MS_16LE - * - * 16-bit signed little-endian mono samples. Playback works - * like the previous code. - * - * DSP_AUDIOFORM_MS_24LE - * - * 24-bit signed little-endian mono samples. Data is packed - * three bytes per sample; if you had two samples 0x112233 and 0x445566 - * they would be stored in memory like this: 33 22 11 66 55 44. - * - * DSP_AUDIOFORM_MS_32LE - * - * 24-bit signed little-endian mono samples in a 32-bit - * container. In other words, each sample is a 32-bit signed - * integer, where the actual audio data is left-justified - * in the 32 bits and only the 24 most significant bits are valid. - * - * DSP_AUDIOFORM_SS_8 - * DSP_AUDIOFORM_SS_16LE - * DSP_AUDIOFORM_SS_24LE - * DSP_AUDIOFORM_SS_32LE - * - * Like the previous ones, except now with stereo interleaved - * data. "SS" means stereo->stereo. - * - * DSP_AUDIOFORM_MM_32LE - * - * Similar to DSP_AUDIOFORM_MS_32LE, except that the mono - * data is not duplicated out both the left and right outputs. - * This mode is used by the ASIO driver. Here, "MM" means - * mono->mono. - * - * DSP_AUDIOFORM_MM_32BE - * - * Just like DSP_AUDIOFORM_MM_32LE, but now the data is - * in big-endian format. - * - */ - -#define DSP_AUDIOFORM_MS_8 0 /* 8 bit mono */ -#define DSP_AUDIOFORM_MS_16LE 1 /* 16 bit mono */ -#define DSP_AUDIOFORM_MS_24LE 2 /* 24 bit mono */ -#define DSP_AUDIOFORM_MS_32LE 3 /* 32 bit mono */ -#define DSP_AUDIOFORM_SS_8 4 /* 8 bit stereo */ -#define DSP_AUDIOFORM_SS_16LE 5 /* 16 bit stereo */ -#define DSP_AUDIOFORM_SS_24LE 6 /* 24 bit stereo */ -#define DSP_AUDIOFORM_SS_32LE 7 /* 32 bit stereo */ -#define DSP_AUDIOFORM_MM_32LE 8 /* 32 bit mono->mono little-endian */ -#define DSP_AUDIOFORM_MM_32BE 9 /* 32 bit mono->mono big-endian */ -#define DSP_AUDIOFORM_SS_32BE 10 /* 32 bit stereo big endian */ -#define DSP_AUDIOFORM_INVALID 0xFF /* Invalid audio format */ - - -/* - * - * Super-interleave is defined as interleaving by 4 or more. Darla20 and Gina20 - * do not support super interleave. - * - * 16 bit, 24 bit, and 32 bit little endian samples are supported for super - * interleave. The interleave factor must be even. 16 - way interleave is the - * current maximum, so you can interleave by 4, 6, 8, 10, 12, 14, and 16. - * - * The actual format code is derived by taking the define below and or-ing with - * the interleave factor. So, 32 bit interleave by 6 is 0x86 and - * 16 bit interleave by 16 is (0x40 | 0x10) = 0x50. - * - */ - -#define DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE 0x40 -#define DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE 0xc0 -#define DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE 0x80 - - -/* - * - * Gina24, Mona, and Layla24 control register defines - * - */ - -#define GML_CONVERTER_ENABLE 0x0010 -#define GML_SPDIF_PRO_MODE 0x0020 /* Professional S/PDIF == 1, - consumer == 0 */ -#define GML_SPDIF_SAMPLE_RATE0 0x0040 -#define GML_SPDIF_SAMPLE_RATE1 0x0080 -#define GML_SPDIF_TWO_CHANNEL 0x0100 /* 1 == two channels, - 0 == one channel */ -#define GML_SPDIF_NOT_AUDIO 0x0200 -#define GML_SPDIF_COPY_PERMIT 0x0400 -#define GML_SPDIF_24_BIT 0x0800 /* 1 == 24 bit, 0 == 20 bit */ -#define GML_ADAT_MODE 0x1000 /* 1 == ADAT mode, 0 == S/PDIF mode */ -#define GML_SPDIF_OPTICAL_MODE 0x2000 /* 1 == optical mode, 0 == RCA mode */ -#define GML_SPDIF_CDROM_MODE 0x3000 /* 1 == CDROM mode, - * 0 == RCA or optical mode */ -#define GML_DOUBLE_SPEED_MODE 0x4000 /* 1 == double speed, - 0 == single speed */ - -#define GML_DIGITAL_IN_AUTO_MUTE 0x800000 - -#define GML_96KHZ (0x0 | GML_DOUBLE_SPEED_MODE) -#define GML_88KHZ (0x1 | GML_DOUBLE_SPEED_MODE) -#define GML_48KHZ 0x2 -#define GML_44KHZ 0x3 -#define GML_32KHZ 0x4 -#define GML_22KHZ 0x5 -#define GML_16KHZ 0x6 -#define GML_11KHZ 0x7 -#define GML_8KHZ 0x8 -#define GML_SPDIF_CLOCK 0x9 -#define GML_ADAT_CLOCK 0xA -#define GML_WORD_CLOCK 0xB -#define GML_ESYNC_CLOCK 0xC -#define GML_ESYNCx2_CLOCK 0xD - -#define GML_CLOCK_CLEAR_MASK 0xffffbff0 -#define GML_SPDIF_RATE_CLEAR_MASK (~(GML_SPDIF_SAMPLE_RATE0|GML_SPDIF_SAMPLE_RATE1)) -#define GML_DIGITAL_MODE_CLEAR_MASK 0xffffcfff -#define GML_SPDIF_FORMAT_CLEAR_MASK 0xfffff01f - - -/* - * - * Mia sample rate and clock setting constants - * - */ - -#define MIA_32000 0x0040 -#define MIA_44100 0x0042 -#define MIA_48000 0x0041 -#define MIA_88200 0x0142 -#define MIA_96000 0x0141 - -#define MIA_SPDIF 0x00000044 -#define MIA_SPDIF96 0x00000144 - -#define MIA_MIDI_REV 1 /* Must be Mia rev 1 for MIDI support */ - - -/* - * - * 3G register bits - * - */ - -#define E3G_CONVERTER_ENABLE 0x0010 -#define E3G_SPDIF_PRO_MODE 0x0020 /* Professional S/PDIF == 1, - consumer == 0 */ -#define E3G_SPDIF_SAMPLE_RATE0 0x0040 -#define E3G_SPDIF_SAMPLE_RATE1 0x0080 -#define E3G_SPDIF_TWO_CHANNEL 0x0100 /* 1 == two channels, - 0 == one channel */ -#define E3G_SPDIF_NOT_AUDIO 0x0200 -#define E3G_SPDIF_COPY_PERMIT 0x0400 -#define E3G_SPDIF_24_BIT 0x0800 /* 1 == 24 bit, 0 == 20 bit */ -#define E3G_DOUBLE_SPEED_MODE 0x4000 /* 1 == double speed, - 0 == single speed */ -#define E3G_PHANTOM_POWER 0x8000 /* 1 == phantom power on, - 0 == phantom power off */ - -#define E3G_96KHZ (0x0 | E3G_DOUBLE_SPEED_MODE) -#define E3G_88KHZ (0x1 | E3G_DOUBLE_SPEED_MODE) -#define E3G_48KHZ 0x2 -#define E3G_44KHZ 0x3 -#define E3G_32KHZ 0x4 -#define E3G_22KHZ 0x5 -#define E3G_16KHZ 0x6 -#define E3G_11KHZ 0x7 -#define E3G_8KHZ 0x8 -#define E3G_SPDIF_CLOCK 0x9 -#define E3G_ADAT_CLOCK 0xA -#define E3G_WORD_CLOCK 0xB -#define E3G_CONTINUOUS_CLOCK 0xE - -#define E3G_ADAT_MODE 0x1000 -#define E3G_SPDIF_OPTICAL_MODE 0x2000 - -#define E3G_CLOCK_CLEAR_MASK 0xbfffbff0 -#define E3G_DIGITAL_MODE_CLEAR_MASK 0xffffcfff -#define E3G_SPDIF_FORMAT_CLEAR_MASK 0xfffff01f - -/* Clock detect bits reported by the DSP */ -#define E3G_CLOCK_DETECT_BIT_WORD96 0x0001 -#define E3G_CLOCK_DETECT_BIT_WORD48 0x0002 -#define E3G_CLOCK_DETECT_BIT_SPDIF48 0x0004 -#define E3G_CLOCK_DETECT_BIT_ADAT 0x0004 -#define E3G_CLOCK_DETECT_BIT_SPDIF96 0x0008 -#define E3G_CLOCK_DETECT_BIT_WORD (E3G_CLOCK_DETECT_BIT_WORD96|E3G_CLOCK_DETECT_BIT_WORD48) -#define E3G_CLOCK_DETECT_BIT_SPDIF (E3G_CLOCK_DETECT_BIT_SPDIF48|E3G_CLOCK_DETECT_BIT_SPDIF96) - -/* Frequency control register */ -#define E3G_MAGIC_NUMBER 677376000 -#define E3G_FREQ_REG_DEFAULT (E3G_MAGIC_NUMBER / 48000 - 2) -#define E3G_FREQ_REG_MAX 0xffff - -/* 3G external box types */ -#define E3G_GINA3G_BOX_TYPE 0x00 -#define E3G_LAYLA3G_BOX_TYPE 0x10 -#define E3G_ASIC_NOT_LOADED 0xffff -#define E3G_BOX_TYPE_MASK 0xf0 - -/* Indigo express control register values */ -#define INDIGO_EXPRESS_32000 0x02 -#define INDIGO_EXPRESS_44100 0x01 -#define INDIGO_EXPRESS_48000 0x00 -#define INDIGO_EXPRESS_DOUBLE_SPEED 0x10 -#define INDIGO_EXPRESS_QUAD_SPEED 0x04 -#define INDIGO_EXPRESS_CLOCK_MASK 0x17 - - -/* - * - * Gina20 & Layla20 have input gain controls for the analog inputs; - * this is the magic number for the hardware that gives you 0 dB at -10. - * - */ - -#define GL20_INPUT_GAIN_MAGIC_NUMBER 0xC8 - - -/* - * - * Defines how much time must pass between DSP load attempts - * - */ - -#define DSP_LOAD_ATTEMPT_PERIOD 1000000L /* One second */ - - -/* - * - * Size of arrays for the comm page. MAX_PLAY_TAPS and MAX_REC_TAPS are - * no longer used, but the sizes must still be right for the DSP to see - * the comm page correctly. - * - */ - -#define MONITOR_ARRAY_SIZE 0x180 -#define VMIXER_ARRAY_SIZE 0x40 -#define MIDI_OUT_BUFFER_SIZE 32 -#define MIDI_IN_BUFFER_SIZE 256 -#define MAX_PLAY_TAPS 168 -#define MAX_REC_TAPS 192 -#define DSP_MIDI_OUT_FIFO_SIZE 64 - - -/* sg_entry is a single entry for the scatter-gather list. The array of struct -sg_entry struct is read by the DSP, so all values must be little-endian. */ - -#define MAX_SGLIST_ENTRIES 512 - -struct sg_entry { - u32 addr; - u32 size; -}; - - -/**************************************************************************** - - The comm page. This structure is read and written by the DSP; the - DSP code is a firm believer in the byte offsets written in the comments - at the end of each line. This structure should not be changed. - - Any reads from or writes to this structure should be in little-endian format. - - ****************************************************************************/ - -struct comm_page { /* Base Length*/ - u32 comm_size; /* size of this object 0x000 4 */ - u32 flags; /* See Appendix A below 0x004 4 */ - u32 unused; /* Unused entry 0x008 4 */ - u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ - u32 handshake; /* DSP command handshake 0x010 4 */ - u32 cmd_start; /* Chs. to start mask 0x014 4 */ - u32 cmd_stop; /* Chs. to stop mask 0x018 4 */ - u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ - u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ - struct sg_entry sglist_addr[DSP_MAXPIPES]; - /* Chs. Physical sglist addrs 0x060 32*8 */ - u32 position[DSP_MAXPIPES]; - /* Positions for ea. ch. 0x160 32*4 */ - s8 vu_meter[DSP_MAXPIPES]; - /* VU meters 0x1e0 32*1 */ - s8 peak_meter[DSP_MAXPIPES]; - /* Peak meters 0x200 32*1 */ - s8 line_out_level[DSP_MAXAUDIOOUTPUTS]; - /* Output gain 0x220 16*1 */ - s8 line_in_level[DSP_MAXAUDIOINPUTS]; - /* Input gain 0x230 16*1 */ - s8 monitors[MONITOR_ARRAY_SIZE]; - /* Monitor map 0x240 0x180 */ - u32 play_coeff[MAX_PLAY_TAPS]; - /* Gina/Darla play filters - obsolete 0x3c0 168*4 */ - u32 rec_coeff[MAX_REC_TAPS]; - /* Gina/Darla record filters - obsolete 0x660 192*4 */ - u16 midi_input[MIDI_IN_BUFFER_SIZE]; - /* MIDI input data transfer buffer 0x960 256*2 */ - u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */ - u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */ - u8 gd_resampler_state; /* Should always be 3 0xb62 1 */ - u8 filler2; /* 0xb63 1 */ - u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ - u16 input_clock; /* Chg. Input clock state 0xb68 2 */ - u16 output_clock; /* Chg. Output clock state 0xb6a 2 */ - u32 status_clocks; /* Current Input clock state 0xb6c 4 */ - u32 ext_box_status; /* External box status 0xb70 4 */ - u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ - u32 midi_out_free_count; - /* # of bytes free in MIDI output FIFO 0xb78 4 */ - u32 unused2; /* Cyclic pipes 0xb7c 4 */ - u32 control_register; - /* Mona, Gina24, Layla24, 3G ctrl reg 0xb80 4 */ - u32 e3g_frq_register; /* 3G frequency register 0xb84 4 */ - u8 filler[24]; /* filler 0xb88 24*1 */ - s8 vmixer[VMIXER_ARRAY_SIZE]; - /* Vmixer levels 0xba0 64*1 */ - u8 midi_output[MIDI_OUT_BUFFER_SIZE]; - /* MIDI output data 0xbe0 32*1 */ -}; - -#endif /* _ECHO_DSP_ */ diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_gml.c b/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_gml.c deleted file mode 100644 index afa27333..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/echoaudio_gml.c +++ /dev/null @@ -1,200 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -/* These functions are common for Gina24, Layla24 and Mona cards */ - - -/* ASIC status check - some cards have one or two ASICs that need to be -loaded. Once that load is complete, this function is called to see if -the load was successful. -If this load fails, it does not necessarily mean that the hardware is -defective - the external box may be disconnected or turned off. */ -static int check_asic_status(struct echoaudio *chip) -{ - u32 asic_status; - - send_vector(chip, DSP_VC_TEST_ASIC); - - /* The DSP will return a value to indicate whether or not the - ASIC is currently loaded */ - if (read_dsp(chip, &asic_status) < 0) { - DE_INIT(("check_asic_status: failed on read_dsp\n")); - chip->asic_loaded = FALSE; - return -EIO; - } - - chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED); - return chip->asic_loaded ? 0 : -EIO; -} - - - -/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing -the control register. write_control_reg sends the new control register -value to the DSP. */ -static int write_control_reg(struct echoaudio *chip, u32 value, char force) -{ - /* Handle the digital input auto-mute */ - if (chip->digital_in_automute) - value |= GML_DIGITAL_IN_AUTO_MUTE; - else - value &= ~GML_DIGITAL_IN_AUTO_MUTE; - - DE_ACT(("write_control_reg: 0x%x\n", value)); - - /* Write the control register */ - value = cpu_to_le32(value); - if (value != chip->comm_page->control_register || force) { - if (wait_handshake(chip)) - return -EIO; - chip->comm_page->control_register = value; - clear_handshake(chip); - return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); - } - return 0; -} - - - -/* Gina24, Layla24, and Mona support digital input auto-mute. If the digital -input auto-mute is enabled, the DSP will only enable the digital inputs if -the card is syncing to a valid clock on the ADAT or S/PDIF inputs. -If the auto-mute is disabled, the digital inputs are enabled regardless of -what the input clock is set or what is connected. */ -static int set_input_auto_mute(struct echoaudio *chip, int automute) -{ - DE_ACT(("set_input_auto_mute %d\n", automute)); - - chip->digital_in_automute = automute; - - /* Re-set the input clock to the current value - indirectly causes - the auto-mute flag to be sent to the DSP */ - return set_input_clock(chip, chip->input_clock); -} - - - -/* S/PDIF coax / S/PDIF optical / ADAT - switch */ -static int set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u8 previous_mode; - int err, i, o; - - if (chip->bad_board) - return -EIO; - - /* All audio channels must be closed before changing the digital mode */ - if (snd_BUG_ON(chip->pipe_alloc_mask)) - return -EAGAIN; - - if (snd_BUG_ON(!(chip->digital_modes & (1 << mode)))) - return -EINVAL; - - previous_mode = chip->digital_mode; - err = dsp_set_digital_mode(chip, mode); - - /* If we successfully changed the digital mode from or to ADAT, - then make sure all output, input and monitor levels are - updated by the DSP comm object. */ - if (err >= 0 && previous_mode != mode && - (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { - spin_lock_irq(&chip->lock); - for (o = 0; o < num_busses_out(chip); o++) - for (i = 0; i < num_busses_in(chip); i++) - set_monitor_gain(chip, o, i, - chip->monitor_gain[o][i]); - -#ifdef ECHOCARD_HAS_INPUT_GAIN - for (i = 0; i < num_busses_in(chip); i++) - set_input_gain(chip, i, chip->input_gain[i]); - update_input_line_level(chip); -#endif - - for (o = 0; o < num_busses_out(chip); o++) - set_output_gain(chip, o, chip->output_gain[o]); - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - } - - return err; -} - - - -/* Set the S/PDIF output format */ -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - u32 control_reg; - int err; - - /* Clear the current S/PDIF flags */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK; - - /* Set the new S/PDIF flags depending on the mode */ - control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT | - GML_SPDIF_COPY_PERMIT; - if (prof) { - /* Professional mode */ - control_reg |= GML_SPDIF_PRO_MODE; - - switch (chip->sample_rate) { - case 32000: - control_reg |= GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 44100: - control_reg |= GML_SPDIF_SAMPLE_RATE0; - break; - case 48000: - control_reg |= GML_SPDIF_SAMPLE_RATE1; - break; - } - } else { - /* Consumer mode */ - switch (chip->sample_rate) { - case 32000: - control_reg |= GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 48000: - control_reg |= GML_SPDIF_SAMPLE_RATE1; - break; - } - } - - if ((err = write_control_reg(chip, control_reg, FALSE))) - return err; - chip->professional_spdif = prof; - DE_ACT(("set_professional_spdif to %s\n", - prof ? "Professional" : "Consumer")); - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/gina20.c b/ANDROID_3.4.5/sound/pci/echoaudio/gina20.c deleted file mode 100644 index 039125b7..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/gina20.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHOGALS_FAMILY -#define ECHOCARD_GINA20 -#define ECHOCARD_NAME "Gina20" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_INPUT_GAIN -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 2 */ -#define PX_ANALOG_IN 10 /* 2 */ -#define PX_DIGITAL_IN 12 /* 2 */ -#define PX_NUM 14 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 2 */ -#define BX_ANALOG_IN 10 /* 2 */ -#define BX_DIGITAL_IN 12 /* 2 */ -#define BX_NUM 14 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/gina20_dsp.fw"); - -#define FW_GINA20_DSP 0 - -static const struct firmware card_fw[] = { - {0, "gina20_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x1801, 0xECC0, 0x0020, 0, 0, 0}, /* DSP 56301 Gina20 rev.0 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "gina20_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/gina20_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/gina20_dsp.c deleted file mode 100644 index d1615a05..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/gina20_dsp.c +++ /dev/null @@ -1,220 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int update_flags(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Gina20\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA20)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_GINA20_DSP; - chip->spdif_status = GD_SPDIF_STATUS_UNDEF; - chip->clock_state = GD_CLOCK_UNDEF; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_SPDIF; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - chip->professional_spdif = FALSE; - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - return clock_bits; -} - - - -/* The Gina20 has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u8 clock_state, spdif_status; - - if (wait_handshake(chip)) - return -EIO; - - switch (rate) { - case 44100: - clock_state = GD_CLOCK_44; - spdif_status = GD_SPDIF_STATUS_44; - break; - case 48000: - clock_state = GD_CLOCK_48; - spdif_status = GD_SPDIF_STATUS_48; - break; - default: - clock_state = GD_CLOCK_NOCHANGE; - spdif_status = GD_SPDIF_STATUS_NOCHANGE; - break; - } - - if (chip->clock_state == clock_state) - clock_state = GD_CLOCK_NOCHANGE; - if (spdif_status == chip->spdif_status) - spdif_status = GD_SPDIF_STATUS_NOCHANGE; - - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->comm_page->gd_clock_state = clock_state; - chip->comm_page->gd_spdif_status = spdif_status; - chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */ - - /* Save the new audio state if it changed */ - if (clock_state != GD_CLOCK_NOCHANGE) - chip->clock_state = clock_state; - if (spdif_status != GD_SPDIF_STATUS_NOCHANGE) - chip->spdif_status = spdif_status; - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - DE_ACT(("set_input_clock:\n")); - - switch (clock) { - case ECHO_CLOCK_INTERNAL: - /* Reset the audio state to unknown (just in case) */ - chip->clock_state = GD_CLOCK_UNDEF; - chip->spdif_status = GD_SPDIF_STATUS_UNDEF; - set_sample_rate(chip, chip->sample_rate); - chip->input_clock = clock; - DE_ACT(("Set Gina clock to INTERNAL\n")); - break; - case ECHO_CLOCK_SPDIF: - chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN; - chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE; - clear_handshake(chip); - send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); - chip->clock_state = GD_CLOCK_SPDIFIN; - DE_ACT(("Set Gina20 clock to SPDIF\n")); - chip->input_clock = clock; - break; - default: - return -EINVAL; - } - - return 0; -} - - - -/* Set input bus gain (one unit is 0.5dB !) */ -static int set_input_gain(struct echoaudio *chip, u16 input, int gain) -{ - if (snd_BUG_ON(input >= num_busses_in(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - chip->input_gain[input] = gain; - gain += GL20_INPUT_GAIN_MAGIC_NUMBER; - chip->comm_page->line_in_level[input] = gain; - return 0; -} - - - -/* Tell the DSP to reread the flags from the comm page */ -static int update_flags(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - DE_ACT(("set_professional_spdif %d\n", prof)); - if (prof) - chip->comm_page->flags |= - cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - else - chip->comm_page->flags &= - ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - chip->professional_spdif = prof; - return update_flags(chip); -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/gina24.c b/ANDROID_3.4.5/sound/pci/echoaudio/gina24.c deleted file mode 100644 index 5e966f6f..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/gina24.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHO24_FAMILY -#define ECHOCARD_GINA24 -#define ECHOCARD_NAME "Gina24" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE -#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT 6 -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 8 */ -#define PX_ANALOG_IN 16 /* 2 */ -#define PX_DIGITAL_IN 18 /* 8 */ -#define PX_NUM 26 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 8 */ -#define BX_ANALOG_IN 16 /* 2 */ -#define BX_DIGITAL_IN 18 /* 8 */ -#define BX_NUM 26 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/gina24_301_dsp.fw"); -MODULE_FIRMWARE("ea/gina24_361_dsp.fw"); -MODULE_FIRMWARE("ea/gina24_301_asic.fw"); -MODULE_FIRMWARE("ea/gina24_361_asic.fw"); - -#define FW_361_LOADER 0 -#define FW_GINA24_301_DSP 1 -#define FW_GINA24_361_DSP 2 -#define FW_GINA24_301_ASIC 3 -#define FW_GINA24_361_ASIC 4 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "gina24_301_dsp.fw"}, - {0, "gina24_361_dsp.fw"}, - {0, "gina24_301_asic.fw"}, - {0, "gina24_361_asic.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x1801, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56301 Gina24 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56301 Gina24 rev.1 */ - {0x1057, 0x3410, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56361 Gina24 rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56361 Gina24 rev.1 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. - 220 ~= (512 - 1 - (BUFFER_BYTES_MAX / PAGE_SIZE)) / 2 */ -}; - -#include "gina24_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio_gml.c" -#include "echoaudio.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/gina24_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/gina24_dsp.c deleted file mode 100644 index 98f7cfa8..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/gina24_dsp.c +++ /dev/null @@ -1,349 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int write_control_reg(struct echoaudio *chip, u32 value, char force); -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int set_digital_mode(struct echoaudio *chip, u8 mode); -static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic); -static int check_asic_status(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Gina24\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA24)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->input_clock_types = - ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 | - ECHO_CLOCK_BIT_ADAT; - - /* Gina24 comes in both '301 and '361 flavors */ - if (chip->device_id == DEVICE_ID_56361) { - chip->dsp_code_to_load = FW_GINA24_361_DSP; - chip->digital_modes = - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - } else { - chip->dsp_code_to_load = FW_GINA24_301_DSP; - chip->digital_modes = - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM; - } - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) - clock_bits |= ECHO_CLOCK_BIT_ADAT; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ESYNC) - clock_bits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96; - - return clock_bits; -} - - - -/* Gina24 has an ASIC on the PCI card which must be loaded for anything -interesting to happen. */ -static int load_asic(struct echoaudio *chip) -{ - u32 control_reg; - int err; - short asic; - - if (chip->asic_loaded) - return 1; - - /* Give the DSP a few milliseconds to settle down */ - mdelay(10); - - /* Pick the correct ASIC for '301 or '361 Gina24 */ - if (chip->device_id == DEVICE_ID_56361) - asic = FW_GINA24_361_ASIC; - else - asic = FW_GINA24_301_ASIC; - - err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, asic); - if (err < 0) - return err; - - chip->asic_code = asic; - - /* Now give the new ASIC a little time to set up */ - mdelay(10); - /* See if it worked */ - err = check_asic_status(chip); - - /* Set up the control register if the load succeeded - - 48 kHz, internal clock, S/PDIF RCA mode */ - if (!err) { - control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; - err = write_control_reg(chip, control_reg, TRUE); - } - DE_INIT(("load_asic() done\n")); - return err; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg, clock; - - if (snd_BUG_ON(rate >= 50000 && - chip->digital_mode == DIGITAL_MODE_ADAT)) - return -EINVAL; - - /* Only set the clock for internal mode. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - /* Save the rate anyhow */ - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - return 0; - } - - clock = 0; - - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK; - - switch (rate) { - case 96000: - clock = GML_96KHZ; - break; - case 88200: - clock = GML_88KHZ; - break; - case 48000: - clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; - break; - case 44100: - clock = GML_44KHZ; - /* Professional mode ? */ - if (control_reg & GML_SPDIF_PRO_MODE) - clock |= GML_SPDIF_SAMPLE_RATE0; - break; - case 32000: - clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 22050: - clock = GML_22KHZ; - break; - case 16000: - clock = GML_16KHZ; - break; - case 11025: - clock = GML_11KHZ; - break; - case 8000: - clock = GML_8KHZ; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - control_reg |= clock; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->sample_rate = rate; - DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); - - return write_control_reg(chip, control_reg, FALSE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - u32 control_reg, clocks_from_dsp; - - DE_ACT(("set_input_clock:\n")); - - /* Mask off the clock select bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register) & - GML_CLOCK_CLEAR_MASK; - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - switch (clock) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Gina24 clock to INTERNAL\n")); - chip->input_clock = ECHO_CLOCK_INTERNAL; - return set_sample_rate(chip, chip->sample_rate); - case ECHO_CLOCK_SPDIF: - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EAGAIN; - DE_ACT(("Set Gina24 clock to SPDIF\n")); - control_reg |= GML_SPDIF_CLOCK; - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96) - control_reg |= GML_DOUBLE_SPEED_MODE; - else - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ADAT: - if (chip->digital_mode != DIGITAL_MODE_ADAT) - return -EAGAIN; - DE_ACT(("Set Gina24 clock to ADAT\n")); - control_reg |= GML_ADAT_CLOCK; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ESYNC: - DE_ACT(("Set Gina24 clock to ESYNC\n")); - control_reg |= GML_ESYNC_CLOCK; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ESYNC96: - DE_ACT(("Set Gina24 clock to ESYNC96\n")); - control_reg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE; - break; - default: - DE_ACT(("Input clock 0x%x not supported for Gina24\n", clock)); - return -EINVAL; - } - - chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); -} - - - -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u32 control_reg; - int err, incompatible_clock; - - /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - case DIGITAL_MODE_SPDIF_CDROM: - case DIGITAL_MODE_SPDIF_RCA: - if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; - break; - case DIGITAL_MODE_ADAT: - if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; - break; - default: - DE_ACT(("Digital mode not supported: %d\n", mode)); - return -EINVAL; - } - - spin_lock_irq(&chip->lock); - - if (incompatible_clock) { /* Switch to 48KHz, internal */ - chip->sample_rate = 48000; - set_input_clock(chip, ECHO_CLOCK_INTERNAL); - } - - /* Clear the current digital mode */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; - - /* Tweak the control reg */ - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - control_reg |= GML_SPDIF_OPTICAL_MODE; - break; - case DIGITAL_MODE_SPDIF_CDROM: - /* '361 Gina24 cards do not have the S/PDIF CD-ROM mode */ - if (chip->device_id == DEVICE_ID_56301) - control_reg |= GML_SPDIF_CDROM_MODE; - break; - case DIGITAL_MODE_SPDIF_RCA: - /* GML_SPDIF_OPTICAL_MODE bit cleared */ - break; - case DIGITAL_MODE_ADAT: - control_reg |= GML_ADAT_MODE; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - } - - err = write_control_reg(chip, control_reg, TRUE); - spin_unlock_irq(&chip->lock); - if (err < 0) - return err; - chip->digital_mode = mode; - - DE_ACT(("set_digital_mode to %d\n", chip->digital_mode)); - return incompatible_clock; -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigo.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigo.c deleted file mode 100644 index c166b7ee..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigo.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define INDIGO_FAMILY -#define ECHOCARD_INDIGO -#define ECHOCARD_NAME "Indigo" -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 0 */ -#define PX_DIGITAL_IN 8 /* 0 */ -#define PX_NUM 8 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 2 */ -#define BX_DIGITAL_OUT 2 /* 0 */ -#define BX_ANALOG_IN 2 /* 0 */ -#define BX_DIGITAL_IN 2 /* 0 */ -#define BX_NUM 2 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/indigo_dsp.fw"); - -#define FW_361_LOADER 0 -#define FW_INDIGO_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "indigo_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x3410, 0xECC0, 0x0090, 0, 0, 0}, /* Indigo */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "indigo_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigo_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigo_dsp.c deleted file mode 100644 index 5e85f14f..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigo_dsp.c +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain); -static int update_vmixer_level(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Indigo\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_INDIGO_DSP; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The Indigo has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg; - - switch (rate) { - case 96000: - control_reg = MIA_96000; - break; - case 88200: - control_reg = MIA_88200; - break; - case 48000: - control_reg = MIA_48000; - break; - case 44100: - control_reg = MIA_44100; - break; - case 32000: - control_reg = MIA_32000; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - /* Set the control register if it has changed */ - if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->comm_page->control_register = cpu_to_le32(control_reg); - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); - } - return 0; -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - if (snd_BUG_ON(pipe >= num_pipes_out(chip) || - output >= num_busses_out(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigo_express_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigo_express_dsp.c deleted file mode 100644 index 2e4ab3e3..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigo_express_dsp.c +++ /dev/null @@ -1,120 +0,0 @@ -/************************************************************************ - -This file is part of Echo Digital Audio's generic driver library. -Copyright Echo Digital Audio Corporation (c) 1998 - 2005 -All rights reserved -www.echoaudio.com - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -*************************************************************************/ - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 clock, control_reg, old_control_reg; - - if (wait_handshake(chip)) - return -EIO; - - old_control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg = old_control_reg & ~INDIGO_EXPRESS_CLOCK_MASK; - - switch (rate) { - case 32000: - clock = INDIGO_EXPRESS_32000; - break; - case 44100: - clock = INDIGO_EXPRESS_44100; - break; - case 48000: - clock = INDIGO_EXPRESS_48000; - break; - case 64000: - clock = INDIGO_EXPRESS_32000|INDIGO_EXPRESS_DOUBLE_SPEED; - break; - case 88200: - clock = INDIGO_EXPRESS_44100|INDIGO_EXPRESS_DOUBLE_SPEED; - break; - case 96000: - clock = INDIGO_EXPRESS_48000|INDIGO_EXPRESS_DOUBLE_SPEED; - break; - default: - return -EINVAL; - } - - control_reg |= clock; - if (control_reg != old_control_reg) { - DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); - chip->comm_page->control_register = cpu_to_le32(control_reg); - chip->sample_rate = rate; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); - } - return 0; -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - if (snd_BUG_ON(pipe >= num_pipes_out(chip) || - output >= num_busses_out(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The IndigoIO has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigodj.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigodj.c deleted file mode 100644 index a3ef3b99..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigodj.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define INDIGO_FAMILY -#define ECHOCARD_INDIGO_DJ -#define ECHOCARD_NAME "Indigo DJ" -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 0 */ -#define PX_DIGITAL_IN 8 /* 0 */ -#define PX_NUM 8 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 4 */ -#define BX_DIGITAL_OUT 4 /* 0 */ -#define BX_ANALOG_IN 4 /* 0 */ -#define BX_DIGITAL_IN 4 /* 0 */ -#define BX_NUM 4 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/indigo_dj_dsp.fw"); - -#define FW_361_LOADER 0 -#define FW_INDIGO_DJ_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "indigo_dj_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x3410, 0xECC0, 0x00B0, 0, 0, 0}, /* Indigo DJ*/ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 4, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "indigodj_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigodj_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigodj_dsp.c deleted file mode 100644 index 68f3c8cc..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigodj_dsp.c +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain); -static int update_vmixer_level(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Indigo DJ\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJ)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_INDIGO_DJ_DSP; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The IndigoDJ has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg; - - switch (rate) { - case 96000: - control_reg = MIA_96000; - break; - case 88200: - control_reg = MIA_88200; - break; - case 48000: - control_reg = MIA_48000; - break; - case 44100: - control_reg = MIA_44100; - break; - case 32000: - control_reg = MIA_32000; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - /* Set the control register if it has changed */ - if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->comm_page->control_register = cpu_to_le32(control_reg); - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); - } - return 0; -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - if (snd_BUG_ON(pipe >= num_pipes_out(chip) || - output >= num_busses_out(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigodjx.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigodjx.c deleted file mode 100644 index f516444f..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigodjx.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2009 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define INDIGO_FAMILY -#define ECHOCARD_INDIGO_DJX -#define ECHOCARD_NAME "Indigo DJx" -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 0 */ -#define PX_DIGITAL_IN 8 /* 0 */ -#define PX_NUM 8 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 4 */ -#define BX_DIGITAL_OUT 4 /* 0 */ -#define BX_ANALOG_IN 4 /* 0 */ -#define BX_DIGITAL_IN 4 /* 0 */ -#define BX_NUM 4 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/indigo_djx_dsp.fw"); - -#define FW_361_LOADER 0 -#define FW_INDIGO_DJX_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "indigo_djx_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x3410, 0xECC0, 0x00E0, 0, 0, 0}, /* Indigo DJx*/ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 4, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "indigodjx_dsp.c" -#include "indigo_express_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigodjx_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigodjx_dsp.c deleted file mode 100644 index bb9632c7..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigodjx_dsp.c +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************ - -This file is part of Echo Digital Audio's generic driver library. -Copyright Echo Digital Audio Corporation (c) 1998 - 2005 -All rights reserved -www.echoaudio.com - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -*************************************************************************/ - -static int update_vmixer_level(struct echoaudio *chip); -static int set_vmixer_gain(struct echoaudio *chip, u16 output, - u16 pipe, int gain); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Indigo DJx\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJX)) - return -ENODEV; - - err = init_dsp_comm_page(chip); - if (err < 0) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_INDIGO_DJX_DSP; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - err = load_firmware(chip); - if (err < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - return init_line_levels(chip); -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigoio.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigoio.c deleted file mode 100644 index c22c82fd..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigoio.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define INDIGO_FAMILY -#define ECHOCARD_INDIGO_IO -#define ECHOCARD_NAME "Indigo IO" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 0 */ -#define PX_NUM 10 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 2 */ -#define BX_DIGITAL_OUT 2 /* 0 */ -#define BX_ANALOG_IN 2 /* 2 */ -#define BX_DIGITAL_IN 4 /* 0 */ -#define BX_NUM 4 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/indigo_io_dsp.fw"); - -#define FW_361_LOADER 0 -#define FW_INDIGO_IO_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "indigo_io_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x3410, 0xECC0, 0x00A0, 0, 0, 0}, /* Indigo IO*/ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "indigoio_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigoio_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigoio_dsp.c deleted file mode 100644 index beb9a5b6..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigoio_dsp.c +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain); -static int update_vmixer_level(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Indigo IO\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_IO)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_INDIGO_IO_DSP; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The IndigoIO has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - if (wait_handshake(chip)) - return -EIO; - - chip->sample_rate = rate; - chip->comm_page->sample_rate = cpu_to_le32(rate); - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - if (snd_BUG_ON(pipe >= num_pipes_out(chip) || - output >= num_busses_out(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigoiox.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigoiox.c deleted file mode 100644 index 86cf2d07..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigoiox.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2009 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define INDIGO_FAMILY -#define ECHOCARD_INDIGO_IOX -#define ECHOCARD_NAME "Indigo IOx" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 0 */ -#define PX_NUM 10 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 2 */ -#define BX_DIGITAL_OUT 2 /* 0 */ -#define BX_ANALOG_IN 2 /* 2 */ -#define BX_DIGITAL_IN 4 /* 0 */ -#define BX_NUM 4 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/indigo_iox_dsp.fw"); - -#define FW_361_LOADER 0 -#define FW_INDIGO_IOX_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "indigo_iox_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x3410, 0xECC0, 0x00D0, 0, 0, 0}, /* Indigo IOx */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "indigoiox_dsp.c" -#include "indigo_express_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/indigoiox_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/indigoiox_dsp.c deleted file mode 100644 index 394c6e76..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/indigoiox_dsp.c +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************ - -This file is part of Echo Digital Audio's generic driver library. -Copyright Echo Digital Audio Corporation (c) 1998 - 2005 -All rights reserved -www.echoaudio.com - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -*************************************************************************/ - -static int update_vmixer_level(struct echoaudio *chip); -static int set_vmixer_gain(struct echoaudio *chip, u16 output, - u16 pipe, int gain); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Indigo IOx\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_IOX)) - return -ENODEV; - - err = init_dsp_comm_page(chip); - if (err < 0) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_INDIGO_IOX_DSP; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - err = load_firmware(chip); - if (err < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - return init_line_levels(chip); -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/layla20.c b/ANDROID_3.4.5/sound/pci/echoaudio/layla20.c deleted file mode 100644 index 6a027f39..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/layla20.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHOGALS_FAMILY -#define ECHOCARD_LAYLA20 -#define ECHOCARD_NAME "Layla20" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_INPUT_GAIN -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE -#define ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH -#define ECHOCARD_HAS_MIDI - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 10 */ -#define PX_DIGITAL_OUT 10 /* 2 */ -#define PX_ANALOG_IN 12 /* 8 */ -#define PX_DIGITAL_IN 20 /* 2 */ -#define PX_NUM 22 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 10 */ -#define BX_DIGITAL_OUT 10 /* 2 */ -#define BX_ANALOG_IN 12 /* 8 */ -#define BX_DIGITAL_IN 20 /* 2 */ -#define BX_NUM 22 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/layla20_dsp.fw"); -MODULE_FIRMWARE("ea/layla20_asic.fw"); - -#define FW_LAYLA20_DSP 0 -#define FW_LAYLA20_ASIC 1 - -static const struct firmware card_fw[] = { - {0, "layla20_dsp.fw"}, - {0, "layla20_asic.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x1801, 0xECC0, 0x0030, 0, 0, 0}, /* DSP 56301 Layla20 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0031, 0, 0, 0}, /* DSP 56301 Layla20 rev.1 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 8000, - .rate_max = 50000, - .channels_min = 1, - .channels_max = 10, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - -#include "layla20_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" -#include "midi.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/layla20_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/layla20_dsp.c deleted file mode 100644 index 53ce9460..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/layla20_dsp.c +++ /dev/null @@ -1,295 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int read_dsp(struct echoaudio *chip, u32 *data); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic); -static int check_asic_status(struct echoaudio *chip); -static int update_flags(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Layla20\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA20)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; - chip->dsp_code_to_load = FW_LAYLA20_DSP; - chip->input_clock_types = - ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; - chip->output_clock_types = - ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - chip->professional_spdif = FALSE; - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_WORD) { - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SUPER) - clock_bits |= ECHO_CLOCK_BIT_SUPER; - else - clock_bits |= ECHO_CLOCK_BIT_WORD; - } - - return clock_bits; -} - - - -/* ASIC status check - some cards have one or two ASICs that need to be -loaded. Once that load is complete, this function is called to see if -the load was successful. -If this load fails, it does not necessarily mean that the hardware is -defective - the external box may be disconnected or turned off. -This routine sometimes fails for Layla20; for Layla20, the loop runs -5 times and succeeds if it wins on three of the loops. */ -static int check_asic_status(struct echoaudio *chip) -{ - u32 asic_status; - int goodcnt, i; - - chip->asic_loaded = FALSE; - for (i = goodcnt = 0; i < 5; i++) { - send_vector(chip, DSP_VC_TEST_ASIC); - - /* The DSP will return a value to indicate whether or not - the ASIC is currently loaded */ - if (read_dsp(chip, &asic_status) < 0) { - DE_ACT(("check_asic_status: failed on read_dsp\n")); - return -EIO; - } - - if (asic_status == ASIC_ALREADY_LOADED) { - if (++goodcnt == 3) { - chip->asic_loaded = TRUE; - return 0; - } - } - } - return -EIO; -} - - - -/* Layla20 has an ASIC in the external box */ -static int load_asic(struct echoaudio *chip) -{ - int err; - - if (chip->asic_loaded) - return 0; - - err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA_ASIC, - FW_LAYLA20_ASIC); - if (err < 0) - return err; - - /* Check if ASIC is alive and well. */ - return check_asic_status(chip); -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - if (snd_BUG_ON(rate < 8000 || rate > 50000)) - return -EINVAL; - - /* Only set the clock for internal mode. Do not return failure, - simply treat it as a non-event. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - return 0; - } - - if (wait_handshake(chip)) - return -EIO; - - DE_ACT(("set_sample_rate(%d)\n", rate)); - chip->sample_rate = rate; - chip->comm_page->sample_rate = cpu_to_le32(rate); - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_LAYLA_SAMPLE_RATE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock_source) -{ - u16 clock; - u32 rate; - - DE_ACT(("set_input_clock:\n")); - rate = 0; - switch (clock_source) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Layla20 clock to INTERNAL\n")); - rate = chip->sample_rate; - clock = LAYLA20_CLOCK_INTERNAL; - break; - case ECHO_CLOCK_SPDIF: - DE_ACT(("Set Layla20 clock to SPDIF\n")); - clock = LAYLA20_CLOCK_SPDIF; - break; - case ECHO_CLOCK_WORD: - DE_ACT(("Set Layla20 clock to WORD\n")); - clock = LAYLA20_CLOCK_WORD; - break; - case ECHO_CLOCK_SUPER: - DE_ACT(("Set Layla20 clock to SUPER\n")); - clock = LAYLA20_CLOCK_SUPER; - break; - default: - DE_ACT(("Input clock 0x%x not supported for Layla24\n", - clock_source)); - return -EINVAL; - } - chip->input_clock = clock_source; - - chip->comm_page->input_clock = cpu_to_le16(clock); - clear_handshake(chip); - send_vector(chip, DSP_VC_UPDATE_CLOCKS); - - if (rate) - set_sample_rate(chip, rate); - - return 0; -} - - - -static int set_output_clock(struct echoaudio *chip, u16 clock) -{ - DE_ACT(("set_output_clock: %d\n", clock)); - switch (clock) { - case ECHO_CLOCK_SUPER: - clock = LAYLA20_OUTPUT_CLOCK_SUPER; - break; - case ECHO_CLOCK_WORD: - clock = LAYLA20_OUTPUT_CLOCK_WORD; - break; - default: - DE_ACT(("set_output_clock wrong clock\n")); - return -EINVAL; - } - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->output_clock = cpu_to_le16(clock); - chip->output_clock = clock; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); -} - - - -/* Set input bus gain (one unit is 0.5dB !) */ -static int set_input_gain(struct echoaudio *chip, u16 input, int gain) -{ - if (snd_BUG_ON(input >= num_busses_in(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - chip->input_gain[input] = gain; - gain += GL20_INPUT_GAIN_MAGIC_NUMBER; - chip->comm_page->line_in_level[input] = gain; - return 0; -} - - - -/* Tell the DSP to reread the flags from the comm page */ -static int update_flags(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - DE_ACT(("set_professional_spdif %d\n", prof)); - if (prof) - chip->comm_page->flags |= - cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - else - chip->comm_page->flags &= - ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - chip->professional_spdif = prof; - return update_flags(chip); -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/layla24.c b/ANDROID_3.4.5/sound/pci/echoaudio/layla24.c deleted file mode 100644 index 96a5991a..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/layla24.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHO24_FAMILY -#define ECHOCARD_LAYLA24 -#define ECHOCARD_NAME "Layla24" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE -#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT 6 -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 -#define ECHOCARD_HAS_MIDI - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 8 */ -#define PX_ANALOG_IN 16 /* 8 */ -#define PX_DIGITAL_IN 24 /* 8 */ -#define PX_NUM 32 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 8 */ -#define BX_ANALOG_IN 16 /* 8 */ -#define BX_DIGITAL_IN 24 /* 8 */ -#define BX_NUM 32 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/layla24_dsp.fw"); -MODULE_FIRMWARE("ea/layla24_1_asic.fw"); -MODULE_FIRMWARE("ea/layla24_2A_asic.fw"); -MODULE_FIRMWARE("ea/layla24_2S_asic.fw"); - -#define FW_361_LOADER 0 -#define FW_LAYLA24_DSP 1 -#define FW_LAYLA24_1_ASIC 2 -#define FW_LAYLA24_2A_ASIC 3 -#define FW_LAYLA24_2S_ASIC 4 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "layla24_dsp.fw"}, - {0, "layla24_1_asic.fw"}, - {0, "layla24_2A_asic.fw"}, - {0, "layla24_2S_asic.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x3410, 0xECC0, 0x0060, 0, 0, 0}, /* DSP 56361 Layla24 rev.0 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_96000, - .rate_min = 8000, - .rate_max = 100000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "layla24_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio_gml.c" -#include "echoaudio.c" -#include "midi.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/layla24_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/layla24_dsp.c deleted file mode 100644 index 8c041647..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/layla24_dsp.c +++ /dev/null @@ -1,398 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int write_control_reg(struct echoaudio *chip, u32 value, char force); -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int set_digital_mode(struct echoaudio *chip, u8 mode); -static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic); -static int check_asic_status(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Layla24\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA24)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; - chip->dsp_code_to_load = FW_LAYLA24_DSP; - chip->input_clock_types = - ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT; - chip->digital_modes = - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) - clock_bits |= ECHO_CLOCK_BIT_ADAT; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD) - clock_bits |= ECHO_CLOCK_BIT_WORD; - - return clock_bits; -} - - - -/* Layla24 has an ASIC on the PCI card and another ASIC in the external box; -both need to be loaded. */ -static int load_asic(struct echoaudio *chip) -{ - int err; - - if (chip->asic_loaded) - return 1; - - DE_INIT(("load_asic\n")); - - /* Give the DSP a few milliseconds to settle down */ - mdelay(10); - - /* Load the ASIC for the PCI card */ - err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC, - FW_LAYLA24_1_ASIC); - if (err < 0) - return err; - - chip->asic_code = FW_LAYLA24_2S_ASIC; - - /* Now give the new ASIC a little time to set up */ - mdelay(10); - - /* Do the external one */ - err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC, - FW_LAYLA24_2S_ASIC); - if (err < 0) - return FALSE; - - /* Now give the external ASIC a little time to set up */ - mdelay(10); - - /* See if it worked */ - err = check_asic_status(chip); - - /* Set up the control register if the load succeeded - - 48 kHz, internal clock, S/PDIF RCA mode */ - if (!err) - err = write_control_reg(chip, GML_CONVERTER_ENABLE | GML_48KHZ, - TRUE); - - DE_INIT(("load_asic() done\n")); - return err; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg, clock, base_rate; - - if (snd_BUG_ON(rate >= 50000 && - chip->digital_mode == DIGITAL_MODE_ADAT)) - return -EINVAL; - - /* Only set the clock for internal mode. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - /* Save the rate anyhow */ - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - return 0; - } - - /* Get the control register & clear the appropriate bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK; - - clock = 0; - - switch (rate) { - case 96000: - clock = GML_96KHZ; - break; - case 88200: - clock = GML_88KHZ; - break; - case 48000: - clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; - break; - case 44100: - clock = GML_44KHZ; - /* Professional mode */ - if (control_reg & GML_SPDIF_PRO_MODE) - clock |= GML_SPDIF_SAMPLE_RATE0; - break; - case 32000: - clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 22050: - clock = GML_22KHZ; - break; - case 16000: - clock = GML_16KHZ; - break; - case 11025: - clock = GML_11KHZ; - break; - case 8000: - clock = GML_8KHZ; - break; - default: - /* If this is a non-standard rate, then the driver needs to - use Layla24's special "continuous frequency" mode */ - clock = LAYLA24_CONTINUOUS_CLOCK; - if (rate > 50000) { - base_rate = rate >> 1; - control_reg |= GML_DOUBLE_SPEED_MODE; - } else { - base_rate = rate; - } - - if (base_rate < 25000) - base_rate = 25000; - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->sample_rate = - cpu_to_le32(LAYLA24_MAGIC_NUMBER / base_rate - 2); - - clear_handshake(chip); - send_vector(chip, DSP_VC_SET_LAYLA24_FREQUENCY_REG); - } - - control_reg |= clock; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP ? */ - chip->sample_rate = rate; - DE_ACT(("set_sample_rate: %d clock %d\n", rate, control_reg)); - - return write_control_reg(chip, control_reg, FALSE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - u32 control_reg, clocks_from_dsp; - - /* Mask off the clock select bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register) & - GML_CLOCK_CLEAR_MASK; - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - /* Pick the new clock */ - switch (clock) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Layla24 clock to INTERNAL\n")); - chip->input_clock = ECHO_CLOCK_INTERNAL; - return set_sample_rate(chip, chip->sample_rate); - case ECHO_CLOCK_SPDIF: - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EAGAIN; - control_reg |= GML_SPDIF_CLOCK; - /* Layla24 doesn't support 96KHz S/PDIF */ - control_reg &= ~GML_DOUBLE_SPEED_MODE; - DE_ACT(("Set Layla24 clock to SPDIF\n")); - break; - case ECHO_CLOCK_WORD: - control_reg |= GML_WORD_CLOCK; - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96) - control_reg |= GML_DOUBLE_SPEED_MODE; - else - control_reg &= ~GML_DOUBLE_SPEED_MODE; - DE_ACT(("Set Layla24 clock to WORD\n")); - break; - case ECHO_CLOCK_ADAT: - if (chip->digital_mode != DIGITAL_MODE_ADAT) - return -EAGAIN; - control_reg |= GML_ADAT_CLOCK; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - DE_ACT(("Set Layla24 clock to ADAT\n")); - break; - default: - DE_ACT(("Input clock 0x%x not supported for Layla24\n", clock)); - return -EINVAL; - } - - chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); -} - - - -/* Depending on what digital mode you want, Layla24 needs different ASICs -loaded. This function checks the ASIC needed for the new mode and sees -if it matches the one already loaded. */ -static int switch_asic(struct echoaudio *chip, short asic) -{ - s8 *monitors; - - /* Check to see if this is already loaded */ - if (asic != chip->asic_code) { - monitors = kmemdup(chip->comm_page->monitors, - MONITOR_ARRAY_SIZE, GFP_KERNEL); - if (! monitors) - return -ENOMEM; - - memset(chip->comm_page->monitors, ECHOGAIN_MUTED, - MONITOR_ARRAY_SIZE); - - /* Load the desired ASIC */ - if (load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC, - asic) < 0) { - memcpy(chip->comm_page->monitors, monitors, - MONITOR_ARRAY_SIZE); - kfree(monitors); - return -EIO; - } - chip->asic_code = asic; - memcpy(chip->comm_page->monitors, monitors, MONITOR_ARRAY_SIZE); - kfree(monitors); - } - - return 0; -} - - - -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u32 control_reg; - int err, incompatible_clock; - short asic; - - /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - case DIGITAL_MODE_SPDIF_RCA: - if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; - asic = FW_LAYLA24_2S_ASIC; - break; - case DIGITAL_MODE_ADAT: - if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; - asic = FW_LAYLA24_2A_ASIC; - break; - default: - DE_ACT(("Digital mode not supported: %d\n", mode)); - return -EINVAL; - } - - if (incompatible_clock) { /* Switch to 48KHz, internal */ - chip->sample_rate = 48000; - spin_lock_irq(&chip->lock); - set_input_clock(chip, ECHO_CLOCK_INTERNAL); - spin_unlock_irq(&chip->lock); - } - - /* switch_asic() can sleep */ - if (switch_asic(chip, asic) < 0) - return -EIO; - - spin_lock_irq(&chip->lock); - - /* Tweak the control register */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; - - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - control_reg |= GML_SPDIF_OPTICAL_MODE; - break; - case DIGITAL_MODE_SPDIF_RCA: - /* GML_SPDIF_OPTICAL_MODE bit cleared */ - break; - case DIGITAL_MODE_ADAT: - control_reg |= GML_ADAT_MODE; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - } - - err = write_control_reg(chip, control_reg, TRUE); - spin_unlock_irq(&chip->lock); - if (err < 0) - return err; - chip->digital_mode = mode; - - DE_ACT(("set_digital_mode to %d\n", mode)); - return incompatible_clock; -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/mia.c b/ANDROID_3.4.5/sound/pci/echoaudio/mia.c deleted file mode 100644 index b8ce27e6..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/mia.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHO24_FAMILY -#define ECHOCARD_MIA -#define ECHOCARD_NAME "Mia" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 -#define ECHOCARD_HAS_MIDI -#define ECHOCARD_HAS_LINE_OUT_GAIN - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 2 */ -#define PX_NUM 12 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 2 */ -#define BX_DIGITAL_OUT 2 /* 2 */ -#define BX_ANALOG_IN 4 /* 2 */ -#define BX_DIGITAL_IN 6 /* 2 */ -#define BX_NUM 8 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/mia_dsp.fw"); - -#define FW_361_LOADER 0 -#define FW_MIA_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "mia_dsp.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x3410, 0xECC0, 0x0080, 0, 0, 0}, /* DSP 56361 Mia rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0081, 0, 0, 0}, /* DSP 56361 Mia rev.1 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "mia_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" -#include "midi.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/mia_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/mia_dsp.c deleted file mode 100644 index 6ebfa6e7..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/mia_dsp.c +++ /dev/null @@ -1,224 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int update_flags(struct echoaudio *chip); -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain); -static int update_vmixer_level(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Mia\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != MIA)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = FW_MIA_DSP; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - if ((subdevice_id & 0x0000f) == MIA_MIDI_REV) - chip->has_midi = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_SPDIF; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - return clock_bits; -} - - - -/* The Mia has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg; - - switch (rate) { - case 96000: - control_reg = MIA_96000; - break; - case 88200: - control_reg = MIA_88200; - break; - case 48000: - control_reg = MIA_48000; - break; - case 44100: - control_reg = MIA_44100; - break; - case 32000: - control_reg = MIA_32000; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - /* Override the clock setting if this Mia is set to S/PDIF clock */ - if (chip->input_clock == ECHO_CLOCK_SPDIF) - control_reg |= MIA_SPDIF; - - /* Set the control register if it has changed */ - if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->comm_page->control_register = cpu_to_le32(control_reg); - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); - } - return 0; -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - DE_ACT(("set_input_clock(%d)\n", clock)); - if (snd_BUG_ON(clock != ECHO_CLOCK_INTERNAL && - clock != ECHO_CLOCK_SPDIF)) - return -EINVAL; - - chip->input_clock = clock; - return set_sample_rate(chip, chip->sample_rate); -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - if (snd_BUG_ON(pipe >= num_pipes_out(chip) || - output >= num_busses_out(chip))) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - - - -/* Tell the DSP to reread the flags from the comm page */ -static int update_flags(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - DE_ACT(("set_professional_spdif %d\n", prof)); - if (prof) - chip->comm_page->flags |= - cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - else - chip->comm_page->flags &= - ~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - chip->professional_spdif = prof; - return update_flags(chip); -} - diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/midi.c b/ANDROID_3.4.5/sound/pci/echoaudio/midi.c deleted file mode 100644 index a953d142..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/midi.c +++ /dev/null @@ -1,331 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -/****************************************************************************** - MIDI lowlevel code -******************************************************************************/ - -/* Start and stop Midi input */ -static int enable_midi_input(struct echoaudio *chip, char enable) -{ - DE_MID(("enable_midi_input(%d)\n", enable)); - - if (wait_handshake(chip)) - return -EIO; - - if (enable) { - chip->mtc_state = MIDI_IN_STATE_NORMAL; - chip->comm_page->flags |= - cpu_to_le32(DSP_FLAG_MIDI_INPUT); - } else - chip->comm_page->flags &= - ~cpu_to_le32(DSP_FLAG_MIDI_INPUT); - - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -/* Send a buffer full of MIDI data to the DSP -Returns how many actually written or < 0 on error */ -static int write_midi(struct echoaudio *chip, u8 *data, int bytes) -{ - if (snd_BUG_ON(bytes <= 0 || bytes >= MIDI_OUT_BUFFER_SIZE)) - return -EINVAL; - - if (wait_handshake(chip)) - return -EIO; - - /* HF4 indicates that it is safe to write MIDI output data */ - if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4)) - return 0; - - chip->comm_page->midi_output[0] = bytes; - memcpy(&chip->comm_page->midi_output[1], data, bytes); - chip->comm_page->midi_out_free_count = 0; - clear_handshake(chip); - send_vector(chip, DSP_VC_MIDI_WRITE); - DE_MID(("write_midi: %d\n", bytes)); - return bytes; -} - - - -/* Run the state machine for MIDI input data -MIDI time code sync isn't supported by this code right now, but you still need -this state machine to parse the incoming MIDI data stream. Every time the DSP -sees a 0xF1 byte come in, it adds the DSP sample position to the MIDI data -stream. The DSP sample position is represented as a 32 bit unsigned value, -with the high 16 bits first, followed by the low 16 bits. Since these aren't -real MIDI bytes, the following logic is needed to skip them. */ -static inline int mtc_process_data(struct echoaudio *chip, short midi_byte) -{ - switch (chip->mtc_state) { - case MIDI_IN_STATE_NORMAL: - if (midi_byte == 0xF1) - chip->mtc_state = MIDI_IN_STATE_TS_HIGH; - break; - case MIDI_IN_STATE_TS_HIGH: - chip->mtc_state = MIDI_IN_STATE_TS_LOW; - return MIDI_IN_SKIP_DATA; - break; - case MIDI_IN_STATE_TS_LOW: - chip->mtc_state = MIDI_IN_STATE_F1_DATA; - return MIDI_IN_SKIP_DATA; - break; - case MIDI_IN_STATE_F1_DATA: - chip->mtc_state = MIDI_IN_STATE_NORMAL; - break; - } - return 0; -} - - - -/* This function is called from the IRQ handler and it reads the midi data -from the DSP's buffer. It returns the number of bytes received. */ -static int midi_service_irq(struct echoaudio *chip) -{ - short int count, midi_byte, i, received; - - /* The count is at index 0, followed by actual data */ - count = le16_to_cpu(chip->comm_page->midi_input[0]); - - if (snd_BUG_ON(count >= MIDI_IN_BUFFER_SIZE)) - return 0; - - /* Get the MIDI data from the comm page */ - i = 1; - received = 0; - for (i = 1; i <= count; i++) { - /* Get the MIDI byte */ - midi_byte = le16_to_cpu(chip->comm_page->midi_input[i]); - - /* Parse the incoming MIDI stream. The incoming MIDI data - consists of MIDI bytes and timestamps for the MIDI time code - 0xF1 bytes. mtc_process_data() is a little state machine that - parses the stream. If you get MIDI_IN_SKIP_DATA back, then - this is a timestamp byte, not a MIDI byte, so don't store it - in the MIDI input buffer. */ - if (mtc_process_data(chip, midi_byte) == MIDI_IN_SKIP_DATA) - continue; - - chip->midi_buffer[received++] = (u8)midi_byte; - } - - return received; -} - - - - -/****************************************************************************** - MIDI interface -******************************************************************************/ - -static int snd_echo_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - chip->midi_in = substream; - DE_MID(("rawmidi_iopen\n")); - return 0; -} - - - -static void snd_echo_midi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - if (up != chip->midi_input_enabled) { - spin_lock_irq(&chip->lock); - enable_midi_input(chip, up); - spin_unlock_irq(&chip->lock); - chip->midi_input_enabled = up; - } -} - - - -static int snd_echo_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - chip->midi_in = NULL; - DE_MID(("rawmidi_iclose\n")); - return 0; -} - - - -static int snd_echo_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - chip->tinuse = 0; - chip->midi_full = 0; - chip->midi_out = substream; - DE_MID(("rawmidi_oopen\n")); - return 0; -} - - - -static void snd_echo_midi_output_write(unsigned long data) -{ - struct echoaudio *chip = (struct echoaudio *)data; - unsigned long flags; - int bytes, sent, time; - unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1]; - - DE_MID(("snd_echo_midi_output_write\n")); - /* No interrupts are involved: we have to check at regular intervals - if the card's output buffer has room for new data. */ - sent = bytes = 0; - spin_lock_irqsave(&chip->lock, flags); - chip->midi_full = 0; - if (!snd_rawmidi_transmit_empty(chip->midi_out)) { - bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf, - MIDI_OUT_BUFFER_SIZE - 1); - DE_MID(("Try to send %d bytes...\n", bytes)); - sent = write_midi(chip, buf, bytes); - if (sent < 0) { - snd_printk(KERN_ERR "write_midi() error %d\n", sent); - /* retry later */ - sent = 9000; - chip->midi_full = 1; - } else if (sent > 0) { - DE_MID(("%d bytes sent\n", sent)); - snd_rawmidi_transmit_ack(chip->midi_out, sent); - } else { - /* Buffer is full. DSP's internal buffer is 64 (128 ?) - bytes long. Let's wait until half of them are sent */ - DE_MID(("Full\n")); - sent = 32; - chip->midi_full = 1; - } - } - - /* We restart the timer only if there is some data left to send */ - if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) { - /* The timer will expire slightly after the data has been - sent */ - time = (sent << 3) / 25 + 1; /* 8/25=0.32ms to send a byte */ - mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000); - DE_MID(("Timer armed(%d)\n", ((time * HZ + 999) / 1000))); - } - spin_unlock_irqrestore(&chip->lock, flags); -} - - - -static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - DE_MID(("snd_echo_midi_output_trigger(%d)\n", up)); - spin_lock_irq(&chip->lock); - if (up) { - if (!chip->tinuse) { - init_timer(&chip->timer); - chip->timer.function = snd_echo_midi_output_write; - chip->timer.data = (unsigned long)chip; - chip->tinuse = 1; - } - } else { - if (chip->tinuse) { - chip->tinuse = 0; - spin_unlock_irq(&chip->lock); - del_timer_sync(&chip->timer); - DE_MID(("Timer removed\n")); - return; - } - } - spin_unlock_irq(&chip->lock); - - if (up && !chip->midi_full) - snd_echo_midi_output_write((unsigned long)chip); -} - - - -static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - chip->midi_out = NULL; - DE_MID(("rawmidi_oclose\n")); - return 0; -} - - - -static struct snd_rawmidi_ops snd_echo_midi_input = { - .open = snd_echo_midi_input_open, - .close = snd_echo_midi_input_close, - .trigger = snd_echo_midi_input_trigger, -}; - -static struct snd_rawmidi_ops snd_echo_midi_output = { - .open = snd_echo_midi_output_open, - .close = snd_echo_midi_output_close, - .trigger = snd_echo_midi_output_trigger, -}; - - - -/* <--snd_echo_probe() */ -static int __devinit snd_echo_midi_create(struct snd_card *card, - struct echoaudio *chip) -{ - int err; - - if ((err = snd_rawmidi_new(card, card->shortname, 0, 1, 1, - &chip->rmidi)) < 0) - return err; - - strcpy(chip->rmidi->name, card->shortname); - chip->rmidi->private_data = chip; - - snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_echo_midi_input); - snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_echo_midi_output); - - chip->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; - DE_INIT(("MIDI ok\n")); - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/mona.c b/ANDROID_3.4.5/sound/pci/echoaudio/mona.c deleted file mode 100644 index 1283bfb2..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/mona.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * 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; version 2 of the License. - * - * 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. - */ - -#define ECHO24_FAMILY -#define ECHOCARD_MONA -#define ECHOCARD_NAME "Mona" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE -#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT 6 -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 6 */ -#define PX_DIGITAL_OUT 6 /* 8 */ -#define PX_ANALOG_IN 14 /* 4 */ -#define PX_DIGITAL_IN 18 /* 8 */ -#define PX_NUM 26 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 6 */ -#define BX_DIGITAL_OUT 6 /* 8 */ -#define BX_ANALOG_IN 14 /* 4 */ -#define BX_DIGITAL_IN 18 /* 8 */ -#define BX_NUM 26 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -MODULE_FIRMWARE("ea/loader_dsp.fw"); -MODULE_FIRMWARE("ea/mona_301_dsp.fw"); -MODULE_FIRMWARE("ea/mona_361_dsp.fw"); -MODULE_FIRMWARE("ea/mona_301_1_asic_48.fw"); -MODULE_FIRMWARE("ea/mona_301_1_asic_96.fw"); -MODULE_FIRMWARE("ea/mona_361_1_asic_48.fw"); -MODULE_FIRMWARE("ea/mona_361_1_asic_96.fw"); -MODULE_FIRMWARE("ea/mona_2_asic.fw"); - -#define FW_361_LOADER 0 -#define FW_MONA_301_DSP 1 -#define FW_MONA_361_DSP 2 -#define FW_MONA_301_1_ASIC48 3 -#define FW_MONA_301_1_ASIC96 4 -#define FW_MONA_361_1_ASIC48 5 -#define FW_MONA_361_1_ASIC96 6 -#define FW_MONA_2_ASIC 7 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "mona_301_dsp.fw"}, - {0, "mona_361_dsp.fw"}, - {0, "mona_301_1_asic_48.fw"}, - {0, "mona_301_1_asic_96.fw"}, - {0, "mona_361_1_asic_48.fw"}, - {0, "mona_361_1_asic_96.fw"}, - {0, "mona_2_asic.fw"} -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_echo_ids) = { - {0x1057, 0x1801, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56301 Mona rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56301 Mona rev.1 */ - {0x1057, 0x1801, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56301 Mona rev.2 */ - {0x1057, 0x3410, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56361 Mona rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56361 Mona rev.1 */ - {0x1057, 0x3410, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56361 Mona rev.2 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "mona_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio_gml.c" -#include "echoaudio.c" diff --git a/ANDROID_3.4.5/sound/pci/echoaudio/mona_dsp.c b/ANDROID_3.4.5/sound/pci/echoaudio/mona_dsp.c deleted file mode 100644 index 6e6a7eb5..00000000 --- a/ANDROID_3.4.5/sound/pci/echoaudio/mona_dsp.c +++ /dev/null @@ -1,427 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library 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. - - 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. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int write_control_reg(struct echoaudio *chip, u32 value, char force); -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int set_digital_mode(struct echoaudio *chip, u8 mode); -static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic); -static int check_asic_status(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Mona\n")); - if (snd_BUG_ON((subdevice_id & 0xfff0) != MONA)) - return -ENODEV; - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->input_clock_types = - ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT; - chip->digital_modes = - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - - /* Mona comes in both '301 and '361 flavors */ - if (chip->device_id == DEVICE_ID_56361) - chip->dsp_code_to_load = FW_MONA_361_DSP; - else - chip->dsp_code_to_load = FW_MONA_301_DSP; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_mixer_defaults(struct echoaudio *chip) -{ - chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; - return init_line_levels(chip); -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) - clock_bits |= ECHO_CLOCK_BIT_ADAT; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD) - clock_bits |= ECHO_CLOCK_BIT_WORD; - - return clock_bits; -} - - - -/* Mona has an ASIC on the PCI card and another ASIC in the external box; -both need to be loaded. */ -static int load_asic(struct echoaudio *chip) -{ - u32 control_reg; - int err; - short asic; - - if (chip->asic_loaded) - return 0; - - mdelay(10); - - if (chip->device_id == DEVICE_ID_56361) - asic = FW_MONA_361_1_ASIC48; - else - asic = FW_MONA_301_1_ASIC48; - - err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, asic); - if (err < 0) - return err; - - chip->asic_code = asic; - mdelay(10); - - /* Do the external one */ - err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_EXTERNAL_ASIC, - FW_MONA_2_ASIC); - if (err < 0) - return err; - - mdelay(10); - err = check_asic_status(chip); - - /* Set up the control register if the load succeeded - - 48 kHz, internal clock, S/PDIF RCA mode */ - if (!err) { - control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; - err = write_control_reg(chip, control_reg, TRUE); - } - - return err; -} - - - -/* Depending on what digital mode you want, Mona needs different ASICs -loaded. This function checks the ASIC needed for the new mode and sees -if it matches the one already loaded. */ -static int switch_asic(struct echoaudio *chip, char double_speed) -{ - int err; - short asic; - - /* Check the clock detect bits to see if this is - a single-speed clock or a double-speed clock; load - a new ASIC if necessary. */ - if (chip->device_id == DEVICE_ID_56361) { - if (double_speed) - asic = FW_MONA_361_1_ASIC96; - else - asic = FW_MONA_361_1_ASIC48; - } else { - if (double_speed) - asic = FW_MONA_301_1_ASIC96; - else - asic = FW_MONA_301_1_ASIC48; - } - - if (asic != chip->asic_code) { - /* Load the desired ASIC */ - err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, - asic); - if (err < 0) - return err; - chip->asic_code = asic; - } - - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg, clock; - short asic; - char force_write; - - /* Only set the clock for internal mode. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - /* Save the rate anyhow */ - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - return 0; - } - - /* Now, check to see if the required ASIC is loaded */ - if (rate >= 88200) { - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EINVAL; - if (chip->device_id == DEVICE_ID_56361) - asic = FW_MONA_361_1_ASIC96; - else - asic = FW_MONA_301_1_ASIC96; - } else { - if (chip->device_id == DEVICE_ID_56361) - asic = FW_MONA_361_1_ASIC48; - else - asic = FW_MONA_301_1_ASIC48; - } - - force_write = 0; - if (asic != chip->asic_code) { - int err; - /* Load the desired ASIC (load_asic_generic() can sleep) */ - spin_unlock_irq(&chip->lock); - err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, - asic); - spin_lock_irq(&chip->lock); - - if (err < 0) - return err; - chip->asic_code = asic; - force_write = 1; - } - - /* Compute the new control register value */ - clock = 0; - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_CLOCK_CLEAR_MASK; - control_reg &= GML_SPDIF_RATE_CLEAR_MASK; - - switch (rate) { - case 96000: - clock = GML_96KHZ; - break; - case 88200: - clock = GML_88KHZ; - break; - case 48000: - clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; - break; - case 44100: - clock = GML_44KHZ; - /* Professional mode */ - if (control_reg & GML_SPDIF_PRO_MODE) - clock |= GML_SPDIF_SAMPLE_RATE0; - break; - case 32000: - clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 22050: - clock = GML_22KHZ; - break; - case 16000: - clock = GML_16KHZ; - break; - case 11025: - clock = GML_11KHZ; - break; - case 8000: - clock = GML_8KHZ; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - control_reg |= clock; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->sample_rate = rate; - DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); - - return write_control_reg(chip, control_reg, force_write); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - u32 control_reg, clocks_from_dsp; - int err; - - DE_ACT(("set_input_clock:\n")); - - /* Prevent two simultaneous calls to switch_asic() */ - if (atomic_read(&chip->opencount)) - return -EAGAIN; - - /* Mask off the clock select bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register) & - GML_CLOCK_CLEAR_MASK; - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - switch (clock) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Mona clock to INTERNAL\n")); - chip->input_clock = ECHO_CLOCK_INTERNAL; - return set_sample_rate(chip, chip->sample_rate); - case ECHO_CLOCK_SPDIF: - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EAGAIN; - spin_unlock_irq(&chip->lock); - err = switch_asic(chip, clocks_from_dsp & - GML_CLOCK_DETECT_BIT_SPDIF96); - spin_lock_irq(&chip->lock); - if (err < 0) - return err; - DE_ACT(("Set Mona clock to SPDIF\n")); - control_reg |= GML_SPDIF_CLOCK; - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96) - control_reg |= GML_DOUBLE_SPEED_MODE; - else - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_WORD: - DE_ACT(("Set Mona clock to WORD\n")); - spin_unlock_irq(&chip->lock); - err = switch_asic(chip, clocks_from_dsp & - GML_CLOCK_DETECT_BIT_WORD96); - spin_lock_irq(&chip->lock); - if (err < 0) - return err; - control_reg |= GML_WORD_CLOCK; - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96) - control_reg |= GML_DOUBLE_SPEED_MODE; - else - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ADAT: - DE_ACT(("Set Mona clock to ADAT\n")); - if (chip->digital_mode != DIGITAL_MODE_ADAT) - return -EAGAIN; - control_reg |= GML_ADAT_CLOCK; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - default: - DE_ACT(("Input clock 0x%x not supported for Mona\n", clock)); - return -EINVAL; - } - - chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); -} - - - -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u32 control_reg; - int err, incompatible_clock; - - /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - case DIGITAL_MODE_SPDIF_RCA: - if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; - break; - case DIGITAL_MODE_ADAT: - if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; - break; - default: - DE_ACT(("Digital mode not supported: %d\n", mode)); - return -EINVAL; - } - - spin_lock_irq(&chip->lock); - - if (incompatible_clock) { /* Switch to 48KHz, internal */ - chip->sample_rate = 48000; - set_input_clock(chip, ECHO_CLOCK_INTERNAL); - } - - /* Clear the current digital mode */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; - - /* Tweak the control reg */ - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - control_reg |= GML_SPDIF_OPTICAL_MODE; - break; - case DIGITAL_MODE_SPDIF_RCA: - /* GML_SPDIF_OPTICAL_MODE bit cleared */ - break; - case DIGITAL_MODE_ADAT: - /* If the current ASIC is the 96KHz ASIC, switch the ASIC - and set to 48 KHz */ - if (chip->asic_code == FW_MONA_361_1_ASIC96 || - chip->asic_code == FW_MONA_301_1_ASIC96) { - set_sample_rate(chip, 48000); - } - control_reg |= GML_ADAT_MODE; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - } - - err = write_control_reg(chip, control_reg, FALSE); - spin_unlock_irq(&chip->lock); - if (err < 0) - return err; - chip->digital_mode = mode; - - DE_ACT(("set_digital_mode to %d\n", mode)); - return incompatible_clock; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/Makefile b/ANDROID_3.4.5/sound/pci/emu10k1/Makefile deleted file mode 100644 index fc5591e7..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-emu10k1-objs := emu10k1.o emu10k1_main.o \ - irq.o memory.o voice.o emumpu401.o emupcm.o io.o \ - emuproc.o emumixer.o emufx.o timer.o p16v.o -snd-emu10k1-synth-objs := emu10k1_synth.o emu10k1_callback.o emu10k1_patch.o -snd-emu10k1x-objs := emu10k1x.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_EMU10K1) += snd-emu10k1.o -obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-emu10k1-synth.o -obj-$(CONFIG_SND_EMU10K1X) += snd-emu10k1x.o diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c deleted file mode 100644 index 790c65d9..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * The driver for the EMU10K1 (SB Live!) based soundcards - * Copyright (c) by Jaroslav Kysela - * - * Copyright (c) by James Courtier-Dutton - * Added support for Audigy 2 Value. - * - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("EMU10K1"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," - "{Creative Labs,SB Audigy}}"); - -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) -#define ENABLE_SYNTH -#include -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int extin[SNDRV_CARDS]; -static int extout[SNDRV_CARDS]; -static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; -static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; -static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; -static bool enable_ir[SNDRV_CARDS]; -static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ -static uint delay_pcm_irq[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the EMU10K1 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable the EMU10K1 soundcard."); -module_param_array(extin, int, NULL, 0444); -MODULE_PARM_DESC(extin, "Available external inputs for FX8010. Zero=default."); -module_param_array(extout, int, NULL, 0444); -MODULE_PARM_DESC(extout, "Available external outputs for FX8010. Zero=default."); -module_param_array(seq_ports, int, NULL, 0444); -MODULE_PARM_DESC(seq_ports, "Allocated sequencer ports for internal synthesizer."); -module_param_array(max_synth_voices, int, NULL, 0444); -MODULE_PARM_DESC(max_synth_voices, "Maximum number of voices for WaveTable."); -module_param_array(max_buffer_size, int, NULL, 0444); -MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB."); -module_param_array(enable_ir, bool, NULL, 0444); -MODULE_PARM_DESC(enable_ir, "Enable IR."); -module_param_array(subsystem, uint, NULL, 0444); -MODULE_PARM_DESC(subsystem, "Force card subsystem model."); -module_param_array(delay_pcm_irq, uint, NULL, 0444); -MODULE_PARM_DESC(delay_pcm_irq, "Delay PCM interrupt by specified number of samples (default 0)."); -/* - * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 - */ -static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1_ids) = { - { PCI_VDEVICE(CREATIVE, 0x0002), 0 }, /* EMU10K1 */ - { PCI_VDEVICE(CREATIVE, 0x0004), 1 }, /* Audigy */ - { PCI_VDEVICE(CREATIVE, 0x0008), 1 }, /* Audigy 2 Value SB0400 */ - { 0, } -}; - -/* - * Audigy 2 Value notes: - * A_IOCFG Input (GPIO) - * 0x400 = Front analog jack plugged in. (Green socket) - * 0x1000 = Read analog jack plugged in. (Black socket) - * 0x2000 = Center/LFE analog jack plugged in. (Orange socket) - * A_IOCFG Output (GPIO) - * 0x60 = Sound out of front Left. - * Win sets it to 0xXX61 - */ - -MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); - -static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_emu10k1 *emu; -#ifdef ENABLE_SYNTH - struct snd_seq_device *wave = NULL; -#endif - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - if (max_buffer_size[dev] < 32) - max_buffer_size[dev] = 32; - else if (max_buffer_size[dev] > 1024) - max_buffer_size[dev] = 1024; - if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], - (long)max_buffer_size[dev] * 1024 * 1024, - enable_ir[dev], subsystem[dev], - &emu)) < 0) - goto error; - card->private_data = emu; - emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; - if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) - goto error; - if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) - goto error; - if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) - goto error; - /* This stores the periods table. */ - if (emu->card_capabilities->ca0151_chip) { /* P16V */ - if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - 1024, &emu->p16v_buffer)) < 0) - goto error; - } - - if ((err = snd_emu10k1_mixer(emu, 0, 3)) < 0) - goto error; - - if ((err = snd_emu10k1_timer(emu, 0)) < 0) - goto error; - - if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) - goto error; - if (emu->card_capabilities->ca0151_chip) { /* P16V */ - if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) - goto error; - } - if (emu->audigy) { - if ((err = snd_emu10k1_audigy_midi(emu)) < 0) - goto error; - } else { - if ((err = snd_emu10k1_midi(emu)) < 0) - goto error; - } - if ((err = snd_emu10k1_fx8010_new(emu, 0, NULL)) < 0) - goto error; -#ifdef ENABLE_SYNTH - if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, - sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 || - wave == NULL) { - snd_printk(KERN_WARNING "can't initialize Emu10k1 wavetable synth\n"); - } else { - struct snd_emu10k1_synth_arg *arg; - arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); - strcpy(wave->name, "Emu-10k1 Synth"); - arg->hwptr = emu; - arg->index = 1; - arg->seq_ports = seq_ports[dev]; - arg->max_voices = max_synth_voices[dev]; - } -#endif - - strcpy(card->driver, emu->card_capabilities->driver); - strcpy(card->shortname, emu->card_capabilities->name); - snprintf(card->longname, sizeof(card->longname), - "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", - card->shortname, emu->revision, emu->serial, emu->port, emu->irq); - - if ((err = snd_card_register(card)) < 0) - goto error; - - pci_set_drvdata(pci, card); - dev++; - return 0; - - error: - snd_card_free(card); - return err; -} - -static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - - -#ifdef CONFIG_PM -static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_emu10k1 *emu = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(emu->pcm); - snd_pcm_suspend_all(emu->pcm_mic); - snd_pcm_suspend_all(emu->pcm_efx); - snd_pcm_suspend_all(emu->pcm_multi); - snd_pcm_suspend_all(emu->pcm_p16v); - - snd_ac97_suspend(emu->ac97); - - snd_emu10k1_efx_suspend(emu); - snd_emu10k1_suspend_regs(emu); - if (emu->card_capabilities->ca0151_chip) - snd_p16v_suspend(emu); - - snd_emu10k1_done(emu); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_emu10k1_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_emu10k1 *emu = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "emu10k1: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_emu10k1_resume_init(emu); - snd_emu10k1_efx_resume(emu); - snd_ac97_resume(emu->ac97); - snd_emu10k1_resume_regs(emu); - - if (emu->card_capabilities->ca0151_chip) - snd_p16v_resume(emu); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_emu10k1_ids, - .probe = snd_card_emu10k1_probe, - .remove = __devexit_p(snd_card_emu10k1_remove), -#ifdef CONFIG_PM - .suspend = snd_emu10k1_suspend, - .resume = snd_emu10k1_resume, -#endif -}; - -static int __init alsa_card_emu10k1_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_emu10k1_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_emu10k1_init) -module_exit(alsa_card_emu10k1_exit) diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c deleted file mode 100644 index a0afa505..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * synth callback routines for Emu10k1 - * - * Copyright (C) 2000 Takashi Iwai - * - * 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 "emu10k1_synth_local.h" -#include - -/* voice status */ -enum { - V_FREE=0, V_OFF, V_RELEASED, V_PLAYING, V_END -}; - -/* Keeps track of what we are finding */ -struct best_voice { - unsigned int time; - int voice; -}; - -/* - * prototypes - */ -static void lookup_voices(struct snd_emux *emux, struct snd_emu10k1 *hw, - struct best_voice *best, int active_only); -static struct snd_emux_voice *get_voice(struct snd_emux *emux, - struct snd_emux_port *port); -static int start_voice(struct snd_emux_voice *vp); -static void trigger_voice(struct snd_emux_voice *vp); -static void release_voice(struct snd_emux_voice *vp); -static void update_voice(struct snd_emux_voice *vp, int update); -static void terminate_voice(struct snd_emux_voice *vp); -static void free_voice(struct snd_emux_voice *vp); -static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); -static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); -static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); - -/* - * Ensure a value is between two points - * macro evaluates its args more than once, so changed to upper-case. - */ -#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0) -#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0) - - -/* - * set up operators - */ -static struct snd_emux_operators emu10k1_ops = { - .owner = THIS_MODULE, - .get_voice = get_voice, - .prepare = start_voice, - .trigger = trigger_voice, - .release = release_voice, - .update = update_voice, - .terminate = terminate_voice, - .free_voice = free_voice, - .sample_new = snd_emu10k1_sample_new, - .sample_free = snd_emu10k1_sample_free, -}; - -void -snd_emu10k1_ops_setup(struct snd_emux *emux) -{ - emux->ops = emu10k1_ops; -} - - -/* - * get more voice for pcm - * - * terminate most inactive voice and give it as a pcm voice. - */ -int -snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) -{ - struct snd_emux *emu; - struct snd_emux_voice *vp; - struct best_voice best[V_END]; - unsigned long flags; - int i; - - emu = hw->synth; - - spin_lock_irqsave(&emu->voice_lock, flags); - lookup_voices(emu, hw, best, 1); /* no OFF voices */ - for (i = 0; i < V_END; i++) { - if (best[i].voice >= 0) { - int ch; - vp = &emu->voices[best[i].voice]; - if ((ch = vp->ch) < 0) { - /* - printk(KERN_WARNING - "synth_get_voice: ch < 0 (%d) ??", i); - */ - continue; - } - vp->emu->num_voices--; - vp->ch = -1; - vp->state = SNDRV_EMUX_ST_OFF; - spin_unlock_irqrestore(&emu->voice_lock, flags); - return ch; - } - } - spin_unlock_irqrestore(&emu->voice_lock, flags); - - /* not found */ - return -ENOMEM; -} - - -/* - * turn off the voice (not terminated) - */ -static void -release_voice(struct snd_emux_voice *vp) -{ - int dcysusv; - struct snd_emu10k1 *hw; - - hw = vp->hw; - dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease; - snd_emu10k1_ptr_write(hw, DCYSUSM, vp->ch, dcysusv); - dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease | DCYSUSV_CHANNELENABLE_MASK; - snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, dcysusv); -} - - -/* - * terminate the voice - */ -static void -terminate_voice(struct snd_emux_voice *vp) -{ - struct snd_emu10k1 *hw; - - if (snd_BUG_ON(!vp)) - return; - hw = vp->hw; - snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); - if (vp->block) { - struct snd_emu10k1_memblk *emem; - emem = (struct snd_emu10k1_memblk *)vp->block; - if (emem->map_locked > 0) - emem->map_locked--; - } -} - -/* - * release the voice to system - */ -static void -free_voice(struct snd_emux_voice *vp) -{ - struct snd_emu10k1 *hw; - - hw = vp->hw; - /* FIXME: emu10k1_synth is broken. */ - /* This can get called with hw == 0 */ - /* Problem apparent on plug, unplug then plug */ - /* on the Audigy 2 ZS Notebook. */ - if (hw && (vp->ch >= 0)) { - snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00); - snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); - // snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0); - snd_emu10k1_ptr_write(hw, VTFT, vp->ch, 0xffff); - snd_emu10k1_ptr_write(hw, CVCF, vp->ch, 0xffff); - snd_emu10k1_voice_free(hw, &hw->voices[vp->ch]); - vp->emu->num_voices--; - vp->ch = -1; - } -} - - -/* - * update registers - */ -static void -update_voice(struct snd_emux_voice *vp, int update) -{ - struct snd_emu10k1 *hw; - - hw = vp->hw; - if (update & SNDRV_EMUX_UPDATE_VOLUME) - snd_emu10k1_ptr_write(hw, IFATN_ATTENUATION, vp->ch, vp->avol); - if (update & SNDRV_EMUX_UPDATE_PITCH) - snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch); - if (update & SNDRV_EMUX_UPDATE_PAN) { - snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_A, vp->ch, vp->apan); - snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_B, vp->ch, vp->aaux); - } - if (update & SNDRV_EMUX_UPDATE_FMMOD) - set_fmmod(hw, vp); - if (update & SNDRV_EMUX_UPDATE_TREMFREQ) - snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq); - if (update & SNDRV_EMUX_UPDATE_FM2FRQ2) - set_fm2frq2(hw, vp); - if (update & SNDRV_EMUX_UPDATE_Q) - set_filterQ(hw, vp); -} - - -/* - * look up voice table - get the best voice in order of preference - */ -/* spinlock held! */ -static void -lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw, - struct best_voice *best, int active_only) -{ - struct snd_emux_voice *vp; - struct best_voice *bp; - int i; - - for (i = 0; i < V_END; i++) { - best[i].time = (unsigned int)-1; /* XXX MAX_?INT really */; - best[i].voice = -1; - } - - /* - * Go through them all and get a best one to use. - * NOTE: could also look at volume and pick the quietest one. - */ - for (i = 0; i < emu->max_voices; i++) { - int state, val; - - vp = &emu->voices[i]; - state = vp->state; - if (state == SNDRV_EMUX_ST_OFF) { - if (vp->ch < 0) { - if (active_only) - continue; - bp = best + V_FREE; - } else - bp = best + V_OFF; - } - else if (state == SNDRV_EMUX_ST_RELEASED || - state == SNDRV_EMUX_ST_PENDING) { - bp = best + V_RELEASED; -#if 1 - val = snd_emu10k1_ptr_read(hw, CVCF_CURRENTVOL, vp->ch); - if (! val) - bp = best + V_OFF; -#endif - } - else if (state == SNDRV_EMUX_ST_STANDBY) - continue; - else if (state & SNDRV_EMUX_ST_ON) - bp = best + V_PLAYING; - else - continue; - - /* check if sample is finished playing (non-looping only) */ - if (bp != best + V_OFF && bp != best + V_FREE && - (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) { - val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch); - if (val >= vp->reg.loopstart) - bp = best + V_OFF; - } - - if (vp->time < bp->time) { - bp->time = vp->time; - bp->voice = i; - } - } -} - -/* - * get an empty voice - * - * emu->voice_lock is already held. - */ -static struct snd_emux_voice * -get_voice(struct snd_emux *emu, struct snd_emux_port *port) -{ - struct snd_emu10k1 *hw; - struct snd_emux_voice *vp; - struct best_voice best[V_END]; - int i; - - hw = emu->hw; - - lookup_voices(emu, hw, best, 0); - for (i = 0; i < V_END; i++) { - if (best[i].voice >= 0) { - vp = &emu->voices[best[i].voice]; - if (vp->ch < 0) { - /* allocate a voice */ - struct snd_emu10k1_voice *hwvoice; - if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL) - continue; - vp->ch = hwvoice->number; - emu->num_voices++; - } - return vp; - } - } - - /* not found */ - return NULL; -} - -/* - * prepare envelopes and LFOs - */ -static int -start_voice(struct snd_emux_voice *vp) -{ - unsigned int temp; - int ch; - unsigned int addr, mapped_offset; - struct snd_midi_channel *chan; - struct snd_emu10k1 *hw; - struct snd_emu10k1_memblk *emem; - - hw = vp->hw; - ch = vp->ch; - if (snd_BUG_ON(ch < 0)) - return -EINVAL; - chan = vp->chan; - - emem = (struct snd_emu10k1_memblk *)vp->block; - if (emem == NULL) - return -EINVAL; - emem->map_locked++; - if (snd_emu10k1_memblk_map(hw, emem) < 0) { - /* printk(KERN_ERR "emu: cannot map!\n"); */ - return -ENOMEM; - } - mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1; - vp->reg.start += mapped_offset; - vp->reg.end += mapped_offset; - vp->reg.loopstart += mapped_offset; - vp->reg.loopend += mapped_offset; - - /* set channel routing */ - /* A = left(0), B = right(1), C = reverb(c), D = chorus(d) */ - if (hw->audigy) { - temp = FXBUS_MIDI_LEFT | (FXBUS_MIDI_RIGHT << 8) | - (FXBUS_MIDI_REVERB << 16) | (FXBUS_MIDI_CHORUS << 24); - snd_emu10k1_ptr_write(hw, A_FXRT1, ch, temp); - } else { - temp = (FXBUS_MIDI_LEFT << 16) | (FXBUS_MIDI_RIGHT << 20) | - (FXBUS_MIDI_REVERB << 24) | (FXBUS_MIDI_CHORUS << 28); - snd_emu10k1_ptr_write(hw, FXRT, ch, temp); - } - - /* channel to be silent and idle */ - snd_emu10k1_ptr_write(hw, DCYSUSV, ch, 0x0000); - snd_emu10k1_ptr_write(hw, VTFT, ch, 0x0000FFFF); - snd_emu10k1_ptr_write(hw, CVCF, ch, 0x0000FFFF); - snd_emu10k1_ptr_write(hw, PTRX, ch, 0); - snd_emu10k1_ptr_write(hw, CPF, ch, 0); - - /* set pitch offset */ - snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch); - - /* set envelope parameters */ - snd_emu10k1_ptr_write(hw, ENVVAL, ch, vp->reg.parm.moddelay); - snd_emu10k1_ptr_write(hw, ATKHLDM, ch, vp->reg.parm.modatkhld); - snd_emu10k1_ptr_write(hw, DCYSUSM, ch, vp->reg.parm.moddcysus); - snd_emu10k1_ptr_write(hw, ENVVOL, ch, vp->reg.parm.voldelay); - snd_emu10k1_ptr_write(hw, ATKHLDV, ch, vp->reg.parm.volatkhld); - /* decay/sustain parameter for volume envelope is used - for triggerg the voice */ - - /* cutoff and volume */ - temp = (unsigned int)vp->acutoff << 8 | (unsigned char)vp->avol; - snd_emu10k1_ptr_write(hw, IFATN, vp->ch, temp); - - /* modulation envelope heights */ - snd_emu10k1_ptr_write(hw, PEFE, ch, vp->reg.parm.pefe); - - /* lfo1/2 delay */ - snd_emu10k1_ptr_write(hw, LFOVAL1, ch, vp->reg.parm.lfo1delay); - snd_emu10k1_ptr_write(hw, LFOVAL2, ch, vp->reg.parm.lfo2delay); - - /* lfo1 pitch & cutoff shift */ - set_fmmod(hw, vp); - /* lfo1 volume & freq */ - snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq); - /* lfo2 pitch & freq */ - set_fm2frq2(hw, vp); - - /* reverb and loop start (reverb 8bit, MSB) */ - temp = vp->reg.parm.reverb; - temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10; - LIMITMAX(temp, 255); - addr = vp->reg.loopstart; - snd_emu10k1_ptr_write(hw, PSST, vp->ch, (temp << 24) | addr); - - /* chorus & loop end (chorus 8bit, MSB) */ - addr = vp->reg.loopend; - temp = vp->reg.parm.chorus; - temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10; - LIMITMAX(temp, 255); - temp = (temp <<24) | addr; - snd_emu10k1_ptr_write(hw, DSL, ch, temp); - - /* clear filter delay memory */ - snd_emu10k1_ptr_write(hw, Z1, ch, 0); - snd_emu10k1_ptr_write(hw, Z2, ch, 0); - - /* invalidate maps */ - temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK; - snd_emu10k1_ptr_write(hw, MAPA, ch, temp); - snd_emu10k1_ptr_write(hw, MAPB, ch, temp); -#if 0 - /* cache */ - { - unsigned int val, sample; - val = 32; - if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS) - sample = 0x80808080; - else { - sample = 0; - val *= 2; - } - - /* cache */ - snd_emu10k1_ptr_write(hw, CCR, ch, 0x1c << 16); - snd_emu10k1_ptr_write(hw, CDE, ch, sample); - snd_emu10k1_ptr_write(hw, CDF, ch, sample); - - /* invalidate maps */ - temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK; - snd_emu10k1_ptr_write(hw, MAPA, ch, temp); - snd_emu10k1_ptr_write(hw, MAPB, ch, temp); - - /* fill cache */ - val -= 4; - val <<= 25; - val |= 0x1c << 16; - snd_emu10k1_ptr_write(hw, CCR, ch, val); - } -#endif - - /* Q & current address (Q 4bit value, MSB) */ - addr = vp->reg.start; - temp = vp->reg.parm.filterQ; - temp = (temp<<28) | addr; - if (vp->apitch < 0xe400) - temp |= CCCA_INTERPROM_0; - else { - unsigned int shift = (vp->apitch - 0xe000) >> 10; - temp |= shift << 25; - } - if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS) - temp |= CCCA_8BITSELECT; - snd_emu10k1_ptr_write(hw, CCCA, ch, temp); - - /* reset volume */ - temp = (unsigned int)vp->vtarget << 16; - snd_emu10k1_ptr_write(hw, VTFT, ch, temp | vp->ftarget); - snd_emu10k1_ptr_write(hw, CVCF, ch, temp | 0xff00); - return 0; -} - -/* - * Start envelope - */ -static void -trigger_voice(struct snd_emux_voice *vp) -{ - unsigned int temp, ptarget; - struct snd_emu10k1 *hw; - struct snd_emu10k1_memblk *emem; - - hw = vp->hw; - - emem = (struct snd_emu10k1_memblk *)vp->block; - if (! emem || emem->mapped_page < 0) - return; /* not mapped */ - -#if 0 - ptarget = (unsigned int)vp->ptarget << 16; -#else - ptarget = IP_TO_CP(vp->apitch); -#endif - /* set pitch target and pan (volume) */ - temp = ptarget | (vp->apan << 8) | vp->aaux; - snd_emu10k1_ptr_write(hw, PTRX, vp->ch, temp); - - /* pitch target */ - snd_emu10k1_ptr_write(hw, CPF, vp->ch, ptarget); - - /* trigger voice */ - snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, vp->reg.parm.voldcysus|DCYSUSV_CHANNELENABLE_MASK); -} - -#define MOD_SENSE 18 - -/* set lfo1 modulation height and cutoff */ -static void -set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) -{ - unsigned short fmmod; - short pitch; - unsigned char cutoff; - int modulation; - - pitch = (char)(vp->reg.parm.fmmod>>8); - cutoff = (vp->reg.parm.fmmod & 0xff); - modulation = vp->chan->gm_modulation + vp->chan->midi_pressure; - pitch += (MOD_SENSE * modulation) / 1200; - LIMITVALUE(pitch, -128, 127); - fmmod = ((unsigned char)pitch<<8) | cutoff; - snd_emu10k1_ptr_write(hw, FMMOD, vp->ch, fmmod); -} - -/* set lfo2 pitch & frequency */ -static void -set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) -{ - unsigned short fm2frq2; - short pitch; - unsigned char freq; - int modulation; - - pitch = (char)(vp->reg.parm.fm2frq2>>8); - freq = vp->reg.parm.fm2frq2 & 0xff; - modulation = vp->chan->gm_modulation + vp->chan->midi_pressure; - pitch += (MOD_SENSE * modulation) / 1200; - LIMITVALUE(pitch, -128, 127); - fm2frq2 = ((unsigned char)pitch<<8) | freq; - snd_emu10k1_ptr_write(hw, FM2FRQ2, vp->ch, fm2frq2); -} - -/* set filterQ */ -static void -set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) -{ - unsigned int val; - val = snd_emu10k1_ptr_read(hw, CCCA, vp->ch) & ~CCCA_RESONANCE; - val |= (vp->reg.parm.filterQ << 28); - snd_emu10k1_ptr_write(hw, CCCA, vp->ch, val); -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c deleted file mode 100644 index 75492408..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c +++ /dev/null @@ -1,2101 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips - * - * Copyright (c) by James Courtier-Dutton - * Added support for Audigy 2 Value. - * Added EMU 1010 support. - * General bug fixes and enhancements. - * - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 -#include - - -#include -#include -#include -#include "p16v.h" -#include "tina2.h" -#include "p17v.h" - - -#define HANA_FILENAME "emu/hana.fw" -#define DOCK_FILENAME "emu/audio_dock.fw" -#define EMU1010B_FILENAME "emu/emu1010b.fw" -#define MICRO_DOCK_FILENAME "emu/micro_dock.fw" -#define EMU0404_FILENAME "emu/emu0404.fw" -#define EMU1010_NOTEBOOK_FILENAME "emu/emu1010_notebook.fw" - -MODULE_FIRMWARE(HANA_FILENAME); -MODULE_FIRMWARE(DOCK_FILENAME); -MODULE_FIRMWARE(EMU1010B_FILENAME); -MODULE_FIRMWARE(MICRO_DOCK_FILENAME); -MODULE_FIRMWARE(EMU0404_FILENAME); -MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME); - - -/************************************************************************* - * EMU10K1 init / done - *************************************************************************/ - -void snd_emu10k1_voice_init(struct snd_emu10k1 *emu, int ch) -{ - snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0); - snd_emu10k1_ptr_write(emu, IP, ch, 0); - snd_emu10k1_ptr_write(emu, VTFT, ch, 0xffff); - snd_emu10k1_ptr_write(emu, CVCF, ch, 0xffff); - snd_emu10k1_ptr_write(emu, PTRX, ch, 0); - snd_emu10k1_ptr_write(emu, CPF, ch, 0); - snd_emu10k1_ptr_write(emu, CCR, ch, 0); - - snd_emu10k1_ptr_write(emu, PSST, ch, 0); - snd_emu10k1_ptr_write(emu, DSL, ch, 0x10); - snd_emu10k1_ptr_write(emu, CCCA, ch, 0); - snd_emu10k1_ptr_write(emu, Z1, ch, 0); - snd_emu10k1_ptr_write(emu, Z2, ch, 0); - snd_emu10k1_ptr_write(emu, FXRT, ch, 0x32100000); - - snd_emu10k1_ptr_write(emu, ATKHLDM, ch, 0); - snd_emu10k1_ptr_write(emu, DCYSUSM, ch, 0); - snd_emu10k1_ptr_write(emu, IFATN, ch, 0xffff); - snd_emu10k1_ptr_write(emu, PEFE, ch, 0); - snd_emu10k1_ptr_write(emu, FMMOD, ch, 0); - snd_emu10k1_ptr_write(emu, TREMFRQ, ch, 24); /* 1 Hz */ - snd_emu10k1_ptr_write(emu, FM2FRQ2, ch, 24); /* 1 Hz */ - snd_emu10k1_ptr_write(emu, TEMPENV, ch, 0); - - /*** these are last so OFF prevents writing ***/ - snd_emu10k1_ptr_write(emu, LFOVAL2, ch, 0); - snd_emu10k1_ptr_write(emu, LFOVAL1, ch, 0); - snd_emu10k1_ptr_write(emu, ATKHLDV, ch, 0); - snd_emu10k1_ptr_write(emu, ENVVOL, ch, 0); - snd_emu10k1_ptr_write(emu, ENVVAL, ch, 0); - - /* Audigy extra stuffs */ - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, 0x4c, ch, 0); /* ?? */ - snd_emu10k1_ptr_write(emu, 0x4d, ch, 0); /* ?? */ - snd_emu10k1_ptr_write(emu, 0x4e, ch, 0); /* ?? */ - snd_emu10k1_ptr_write(emu, 0x4f, ch, 0); /* ?? */ - snd_emu10k1_ptr_write(emu, A_FXRT1, ch, 0x03020100); - snd_emu10k1_ptr_write(emu, A_FXRT2, ch, 0x3f3f3f3f); - snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, ch, 0); - } -} - -static unsigned int spi_dac_init[] = { - 0x00ff, - 0x02ff, - 0x0400, - 0x0520, - 0x0600, - 0x08ff, - 0x0aff, - 0x0cff, - 0x0eff, - 0x10ff, - 0x1200, - 0x1400, - 0x1480, - 0x1800, - 0x1aff, - 0x1cff, - 0x1e00, - 0x0530, - 0x0602, - 0x0622, - 0x1400, -}; - -static unsigned int i2c_adc_init[][2] = { - { 0x17, 0x00 }, /* Reset */ - { 0x07, 0x00 }, /* Timeout */ - { 0x0b, 0x22 }, /* Interface control */ - { 0x0c, 0x22 }, /* Master mode control */ - { 0x0d, 0x08 }, /* Powerdown control */ - { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */ - { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */ - { 0x10, 0x7b }, /* ALC Control 1 */ - { 0x11, 0x00 }, /* ALC Control 2 */ - { 0x12, 0x32 }, /* ALC Control 3 */ - { 0x13, 0x00 }, /* Noise gate control */ - { 0x14, 0xa6 }, /* Limiter control */ - { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */ -}; - -static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) -{ - unsigned int silent_page; - int ch; - u32 tmp; - - /* disable audio and lock cache */ - outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | - HCFG_MUTEBUTTONENABLE, emu->port + HCFG); - - /* reset recording buffers */ - snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE); - snd_emu10k1_ptr_write(emu, MICBA, 0, 0); - snd_emu10k1_ptr_write(emu, FXBS, 0, ADCBS_BUFSIZE_NONE); - snd_emu10k1_ptr_write(emu, FXBA, 0, 0); - snd_emu10k1_ptr_write(emu, ADCBS, 0, ADCBS_BUFSIZE_NONE); - snd_emu10k1_ptr_write(emu, ADCBA, 0, 0); - - /* disable channel interrupt */ - outl(0, emu->port + INTE); - snd_emu10k1_ptr_write(emu, CLIEL, 0, 0); - snd_emu10k1_ptr_write(emu, CLIEH, 0, 0); - snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); - snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); - - if (emu->audigy) { - /* set SPDIF bypass mode */ - snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT); - /* enable rear left + rear right AC97 slots */ - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_REAR_RIGHT | - AC97SLOT_REAR_LEFT); - } - - /* init envelope engine */ - for (ch = 0; ch < NUM_G; ch++) - snd_emu10k1_voice_init(emu, ch); - - snd_emu10k1_ptr_write(emu, SPCS0, 0, emu->spdif_bits[0]); - snd_emu10k1_ptr_write(emu, SPCS1, 0, emu->spdif_bits[1]); - snd_emu10k1_ptr_write(emu, SPCS2, 0, emu->spdif_bits[2]); - - if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ - /* Hacks for Alice3 to work independent of haP16V driver */ - /* Setup SRCMulti_I2S SamplingRate */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - tmp &= 0xfffff1ff; - tmp |= (0x2<<9); - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); - - /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ - snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); - /* Setup SRCMulti Input Audio Enable */ - /* Use 0xFFFFFFFF to enable P16V sounds. */ - snd_emu10k1_ptr20_write(emu, SRCMULTI_ENABLE, 0, 0xFFFFFFFF); - - /* Enabled Phased (8-channel) P16V playback */ - outl(0x0201, emu->port + HCFG2); - /* Set playback routing. */ - snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); - } - if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ - /* Hacks for Alice3 to work independent of haP16V driver */ - snd_printk(KERN_INFO "Audigy2 value: Special config.\n"); - /* Setup SRCMulti_I2S SamplingRate */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - tmp &= 0xfffff1ff; - tmp |= (0x2<<9); - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); - - /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ - outl(0x600000, emu->port + 0x20); - outl(0x14, emu->port + 0x24); - - /* Setup SRCMulti Input Audio Enable */ - outl(0x7b0000, emu->port + 0x20); - outl(0xFF000000, emu->port + 0x24); - - /* Setup SPDIF Out Audio Enable */ - /* The Audigy 2 Value has a separate SPDIF out, - * so no need for a mixer switch - */ - outl(0x7a0000, emu->port + 0x20); - outl(0xFF000000, emu->port + 0x24); - tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */ - outl(tmp, emu->port + A_IOCFG); - } - if (emu->card_capabilities->spi_dac) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */ - int size, n; - - size = ARRAY_SIZE(spi_dac_init); - for (n = 0; n < size; n++) - snd_emu10k1_spi_write(emu, spi_dac_init[n]); - - snd_emu10k1_ptr20_write(emu, 0x60, 0, 0x10); - /* Enable GPIOs - * GPIO0: Unknown - * GPIO1: Speakers-enabled. - * GPIO2: Unknown - * GPIO3: Unknown - * GPIO4: IEC958 Output on. - * GPIO5: Unknown - * GPIO6: Unknown - * GPIO7: Unknown - */ - outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ - } - if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ - int size, n; - - snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f); - tmp = inl(emu->port + A_IOCFG); - outl(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */ - tmp = inl(emu->port + A_IOCFG); - size = ARRAY_SIZE(i2c_adc_init); - for (n = 0; n < size; n++) - snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]); - for (n = 0; n < 4; n++) { - emu->i2c_capture_volume[n][0] = 0xcf; - emu->i2c_capture_volume[n][1] = 0xcf; - } - } - - - snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr); - snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ - snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */ - - silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK; - for (ch = 0; ch < NUM_G; ch++) { - snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page); - snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page); - } - - if (emu->card_capabilities->emu_model) { - outl(HCFG_AUTOMUTE_ASYNC | - HCFG_EMU32_SLAVE | - HCFG_AUDIOENABLE, emu->port + HCFG); - /* - * Hokay, setup HCFG - * Mute Disable Audio = 0 - * Lock Tank Memory = 1 - * Lock Sound Memory = 0 - * Auto Mute = 1 - */ - } else if (emu->audigy) { - if (emu->revision == 4) /* audigy2 */ - outl(HCFG_AUDIOENABLE | - HCFG_AC3ENABLE_CDSPDIF | - HCFG_AC3ENABLE_GPSPDIF | - HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); - else - outl(HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); - /* FIXME: Remove all these emu->model and replace it with a card recognition parameter, - * e.g. card_capabilities->joystick */ - } else if (emu->model == 0x20 || - emu->model == 0xc400 || - (emu->model == 0x21 && emu->revision < 6)) - outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE, emu->port + HCFG); - else - /* With on-chip joystick */ - outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); - - if (enable_ir) { /* enable IR for SB Live */ - if (emu->card_capabilities->emu_model) { - ; /* Disable all access to A_IOCFG for the emu1010 */ - } else if (emu->card_capabilities->i2c_adc) { - ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ - } else if (emu->audigy) { - unsigned int reg = inl(emu->port + A_IOCFG); - outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); - udelay(500); - outl(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG); - udelay(100); - outl(reg, emu->port + A_IOCFG); - } else { - unsigned int reg = inl(emu->port + HCFG); - outl(reg | HCFG_GPOUT2, emu->port + HCFG); - udelay(500); - outl(reg | HCFG_GPOUT1 | HCFG_GPOUT2, emu->port + HCFG); - udelay(100); - outl(reg, emu->port + HCFG); - } - } - - if (emu->card_capabilities->emu_model) { - ; /* Disable all access to A_IOCFG for the emu1010 */ - } else if (emu->card_capabilities->i2c_adc) { - ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ - } else if (emu->audigy) { /* enable analog output */ - unsigned int reg = inl(emu->port + A_IOCFG); - outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); - } - - return 0; -} - -static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) -{ - /* - * Enable the audio bit - */ - outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG); - - /* Enable analog/digital outs on audigy */ - if (emu->card_capabilities->emu_model) { - ; /* Disable all access to A_IOCFG for the emu1010 */ - } else if (emu->card_capabilities->i2c_adc) { - ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ - } else if (emu->audigy) { - outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); - - if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ - /* Unmute Analog now. Set GPO6 to 1 for Apollo. - * This has to be done after init ALice3 I2SOut beyond 48KHz. - * So, sequence is important. */ - outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); - } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */ - /* Unmute Analog now. */ - outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); - } else { - /* Disable routing from AC97 line out to Front speakers */ - outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); - } - } - -#if 0 - { - unsigned int tmp; - /* FIXME: the following routine disables LiveDrive-II !! */ - /* TOSLink detection */ - emu->tos_link = 0; - tmp = inl(emu->port + HCFG); - if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) { - outl(tmp|0x800, emu->port + HCFG); - udelay(50); - if (tmp != (inl(emu->port + HCFG) & ~0x800)) { - emu->tos_link = 1; - outl(tmp, emu->port + HCFG); - } - } - } -#endif - - snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE); -} - -int snd_emu10k1_done(struct snd_emu10k1 *emu) -{ - int ch; - - outl(0, emu->port + INTE); - - /* - * Shutdown the chip - */ - for (ch = 0; ch < NUM_G; ch++) - snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0); - for (ch = 0; ch < NUM_G; ch++) { - snd_emu10k1_ptr_write(emu, VTFT, ch, 0); - snd_emu10k1_ptr_write(emu, CVCF, ch, 0); - snd_emu10k1_ptr_write(emu, PTRX, ch, 0); - snd_emu10k1_ptr_write(emu, CPF, ch, 0); - } - - /* reset recording buffers */ - snd_emu10k1_ptr_write(emu, MICBS, 0, 0); - snd_emu10k1_ptr_write(emu, MICBA, 0, 0); - snd_emu10k1_ptr_write(emu, FXBS, 0, 0); - snd_emu10k1_ptr_write(emu, FXBA, 0, 0); - snd_emu10k1_ptr_write(emu, FXWC, 0, 0); - snd_emu10k1_ptr_write(emu, ADCBS, 0, ADCBS_BUFSIZE_NONE); - snd_emu10k1_ptr_write(emu, ADCBA, 0, 0); - snd_emu10k1_ptr_write(emu, TCBS, 0, TCBS_BUFFSIZE_16K); - snd_emu10k1_ptr_write(emu, TCB, 0, 0); - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, EMU10K1_DBG_SINGLE_STEP); - - /* disable channel interrupt */ - snd_emu10k1_ptr_write(emu, CLIEL, 0, 0); - snd_emu10k1_ptr_write(emu, CLIEH, 0, 0); - snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); - snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); - - /* disable audio and lock cache */ - outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, emu->port + HCFG); - snd_emu10k1_ptr_write(emu, PTB, 0, 0); - - return 0; -} - -/************************************************************************* - * ECARD functional implementation - *************************************************************************/ - -/* In A1 Silicon, these bits are in the HC register */ -#define HOOKN_BIT (1L << 12) -#define HANDN_BIT (1L << 11) -#define PULSEN_BIT (1L << 10) - -#define EC_GDI1 (1 << 13) -#define EC_GDI0 (1 << 14) - -#define EC_NUM_CONTROL_BITS 20 - -#define EC_AC3_DATA_SELN 0x0001L -#define EC_EE_DATA_SEL 0x0002L -#define EC_EE_CNTRL_SELN 0x0004L -#define EC_EECLK 0x0008L -#define EC_EECS 0x0010L -#define EC_EESDO 0x0020L -#define EC_TRIM_CSN 0x0040L -#define EC_TRIM_SCLK 0x0080L -#define EC_TRIM_SDATA 0x0100L -#define EC_TRIM_MUTEN 0x0200L -#define EC_ADCCAL 0x0400L -#define EC_ADCRSTN 0x0800L -#define EC_DACCAL 0x1000L -#define EC_DACMUTEN 0x2000L -#define EC_LEDN 0x4000L - -#define EC_SPDIF0_SEL_SHIFT 15 -#define EC_SPDIF1_SEL_SHIFT 17 -#define EC_SPDIF0_SEL_MASK (0x3L << EC_SPDIF0_SEL_SHIFT) -#define EC_SPDIF1_SEL_MASK (0x7L << EC_SPDIF1_SEL_SHIFT) -#define EC_SPDIF0_SELECT(_x) (((_x) << EC_SPDIF0_SEL_SHIFT) & EC_SPDIF0_SEL_MASK) -#define EC_SPDIF1_SELECT(_x) (((_x) << EC_SPDIF1_SEL_SHIFT) & EC_SPDIF1_SEL_MASK) -#define EC_CURRENT_PROM_VERSION 0x01 /* Self-explanatory. This should - * be incremented any time the EEPROM's - * format is changed. */ - -#define EC_EEPROM_SIZE 0x40 /* ECARD EEPROM has 64 16-bit words */ - -/* Addresses for special values stored in to EEPROM */ -#define EC_PROM_VERSION_ADDR 0x20 /* Address of the current prom version */ -#define EC_BOARDREV0_ADDR 0x21 /* LSW of board rev */ -#define EC_BOARDREV1_ADDR 0x22 /* MSW of board rev */ - -#define EC_LAST_PROMFILE_ADDR 0x2f - -#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The - * can be up to 30 characters in length - * and is stored as a NULL-terminated - * ASCII string. Any unused bytes must be - * filled with zeros */ -#define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */ - - -/* Most of this stuff is pretty self-evident. According to the hardware - * dudes, we need to leave the ADCCAL bit low in order to avoid a DC - * offset problem. Weird. - */ -#define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \ - EC_TRIM_CSN) - - -#define EC_DEFAULT_ADC_GAIN 0xC4C4 -#define EC_DEFAULT_SPDIF0_SEL 0x0 -#define EC_DEFAULT_SPDIF1_SEL 0x4 - -/************************************************************************** - * @func Clock bits into the Ecard's control latch. The Ecard uses a - * control latch will is loaded bit-serially by toggling the Modem control - * lines from function 2 on the E8010. This function hides these details - * and presents the illusion that we are actually writing to a distinct - * register. - */ - -static void snd_emu10k1_ecard_write(struct snd_emu10k1 *emu, unsigned int value) -{ - unsigned short count; - unsigned int data; - unsigned long hc_port; - unsigned int hc_value; - - hc_port = emu->port + HCFG; - hc_value = inl(hc_port) & ~(HOOKN_BIT | HANDN_BIT | PULSEN_BIT); - outl(hc_value, hc_port); - - for (count = 0; count < EC_NUM_CONTROL_BITS; count++) { - - /* Set up the value */ - data = ((value & 0x1) ? PULSEN_BIT : 0); - value >>= 1; - - outl(hc_value | data, hc_port); - - /* Clock the shift register */ - outl(hc_value | data | HANDN_BIT, hc_port); - outl(hc_value | data, hc_port); - } - - /* Latch the bits */ - outl(hc_value | HOOKN_BIT, hc_port); - outl(hc_value, hc_port); -} - -/************************************************************************** - * @func Set the gain of the ECARD's CS3310 Trim/gain controller. The - * trim value consists of a 16bit value which is composed of two - * 8 bit gain/trim values, one for the left channel and one for the - * right channel. The following table maps from the Gain/Attenuation - * value in decibels into the corresponding bit pattern for a single - * channel. - */ - -static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 *emu, - unsigned short gain) -{ - unsigned int bit; - - /* Enable writing to the TRIM registers */ - snd_emu10k1_ecard_write(emu, emu->ecard_ctrl & ~EC_TRIM_CSN); - - /* Do it again to insure that we meet hold time requirements */ - snd_emu10k1_ecard_write(emu, emu->ecard_ctrl & ~EC_TRIM_CSN); - - for (bit = (1 << 15); bit; bit >>= 1) { - unsigned int value; - - value = emu->ecard_ctrl & ~(EC_TRIM_CSN | EC_TRIM_SDATA); - - if (gain & bit) - value |= EC_TRIM_SDATA; - - /* Clock the bit */ - snd_emu10k1_ecard_write(emu, value); - snd_emu10k1_ecard_write(emu, value | EC_TRIM_SCLK); - snd_emu10k1_ecard_write(emu, value); - } - - snd_emu10k1_ecard_write(emu, emu->ecard_ctrl); -} - -static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu) -{ - unsigned int hc_value; - - /* Set up the initial settings */ - emu->ecard_ctrl = EC_RAW_RUN_MODE | - EC_SPDIF0_SELECT(EC_DEFAULT_SPDIF0_SEL) | - EC_SPDIF1_SELECT(EC_DEFAULT_SPDIF1_SEL); - - /* Step 0: Set the codec type in the hardware control register - * and enable audio output */ - hc_value = inl(emu->port + HCFG); - outl(hc_value | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S, emu->port + HCFG); - inl(emu->port + HCFG); - - /* Step 1: Turn off the led and deassert TRIM_CS */ - snd_emu10k1_ecard_write(emu, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN); - - /* Step 2: Calibrate the ADC and DAC */ - snd_emu10k1_ecard_write(emu, EC_DACCAL | EC_LEDN | EC_TRIM_CSN); - - /* Step 3: Wait for awhile; XXX We can't get away with this - * under a real operating system; we'll need to block and wait that - * way. */ - snd_emu10k1_wait(emu, 48000); - - /* Step 4: Switch off the DAC and ADC calibration. Note - * That ADC_CAL is actually an inverted signal, so we assert - * it here to stop calibration. */ - snd_emu10k1_ecard_write(emu, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN); - - /* Step 4: Switch into run mode */ - snd_emu10k1_ecard_write(emu, emu->ecard_ctrl); - - /* Step 5: Set the analog input gain */ - snd_emu10k1_ecard_setadcgain(emu, EC_DEFAULT_ADC_GAIN); - - return 0; -} - -static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) -{ - unsigned long special_port; - unsigned int value; - - /* Special initialisation routine - * before the rest of the IO-Ports become active. - */ - special_port = emu->port + 0x38; - value = inl(special_port); - outl(0x00d00000, special_port); - value = inl(special_port); - outl(0x00d00001, special_port); - value = inl(special_port); - outl(0x00d0005f, special_port); - value = inl(special_port); - outl(0x00d0007f, special_port); - value = inl(special_port); - outl(0x0090007f, special_port); - value = inl(special_port); - - snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */ - /* Delay to give time for ADC chip to switch on. It needs 113ms */ - msleep(200); - return 0; -} - -static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename) -{ - int err; - int n, i; - int reg; - int value; - unsigned int write_post; - unsigned long flags; - const struct firmware *fw_entry; - - err = request_firmware(&fw_entry, filename, &emu->pci->dev); - if (err != 0) { - snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err); - return err; - } - snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size); - - /* The FPGA is a Xilinx Spartan IIE XC2S50E */ - /* GPIO7 -> FPGA PGMN - * GPIO6 -> FPGA CCLK - * GPIO5 -> FPGA DIN - * FPGA CONFIG OFF -> FPGA PGMN - */ - spin_lock_irqsave(&emu->emu_lock, flags); - outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */ - write_post = inl(emu->port + A_IOCFG); - udelay(100); - outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */ - write_post = inl(emu->port + A_IOCFG); - udelay(100); /* Allow FPGA memory to clean */ - for (n = 0; n < fw_entry->size; n++) { - value = fw_entry->data[n]; - for (i = 0; i < 8; i++) { - reg = 0x80; - if (value & 0x1) - reg = reg | 0x20; - value = value >> 1; - outl(reg, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); - outl(reg | 0x40, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); - } - } - /* After programming, set GPIO bit 4 high again. */ - outl(0x10, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); - spin_unlock_irqrestore(&emu->emu_lock, flags); - - release_firmware(fw_entry); - return 0; -} - -static int emu1010_firmware_thread(void *data) -{ - struct snd_emu10k1 *emu = data; - u32 tmp, tmp2, reg; - int err; - - for (;;) { - /* Delay to allow Audio Dock to settle */ - msleep_interruptible(1000); - if (kthread_should_stop()) - break; - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ - if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { - /* Audio Dock attached */ - /* Return to Audio Dock programming mode */ - snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); - if (emu->card_capabilities->emu_model == - EMU_MODEL_EMU1010) { - err = snd_emu1010_load_firmware(emu, DOCK_FILENAME); - if (err != 0) - continue; - } else if (emu->card_capabilities->emu_model == - EMU_MODEL_EMU1010B) { - err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); - if (err != 0) - continue; - } else if (emu->card_capabilities->emu_model == - EMU_MODEL_EMU1616) { - err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); - if (err != 0) - continue; - } - - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); - snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", reg); - /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg); - if ((reg & 0x1f) != 0x15) { - /* FPGA failed to be programmed */ - snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", reg); - continue; - } - snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); - snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); - snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); - snd_printk(KERN_INFO "Audio Dock ver: %u.%u\n", - tmp, tmp2); - /* Sync clocking between 1010 and Dock */ - /* Allow DLL to settle */ - msleep(10); - /* Unmute all. Default is muted after a firmware load */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); - } - } - snd_printk(KERN_INFO "emu1010: firmware thread stopping\n"); - return 0; -} - -/* - * EMU-1010 - details found out from this driver, official MS Win drivers, - * testing the card: - * - * Audigy2 (aka Alice2): - * --------------------- - * * communication over PCI - * * conversion of 32-bit data coming over EMU32 links from HANA FPGA - * to 2 x 16-bit, using internal DSP instructions - * * slave mode, clock supplied by HANA - * * linked to HANA using: - * 32 x 32-bit serial EMU32 output channels - * 16 x EMU32 input channels - * (?) x I2S I/O channels (?) - * - * FPGA (aka HANA): - * --------------- - * * provides all (?) physical inputs and outputs of the card - * (ADC, DAC, SPDIF I/O, ADAT I/O, etc.) - * * provides clock signal for the card and Alice2 - * * two crystals - for 44.1kHz and 48kHz multiples - * * provides internal routing of signal sources to signal destinations - * * inputs/outputs to Alice2 - see above - * - * Current status of the driver: - * ---------------------------- - * * only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz) - * * PCM device nb. 2: - * 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops - * 16 x 32-bit capture - snd_emu10k1_capture_efx_ops - */ -static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) -{ - unsigned int i; - u32 tmp, tmp2, reg; - int err; - const char *filename = NULL; - - snd_printk(KERN_INFO "emu1010: Special config.\n"); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0005a00c, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0005a004, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Mute all codecs. - */ - outl(0x0005a000, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Mute all codecs. - */ - outl(0x0005a000, emu->port + HCFG); - - /* Disable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); - - /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printdd("reg1 = 0x%x\n", reg); - if ((reg & 0x3f) == 0x15) { - /* FPGA netlist already present so clear it */ - /* Return to programming mode */ - - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02); - } - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printdd("reg2 = 0x%x\n", reg); - if ((reg & 0x3f) == 0x15) { - /* FPGA failed to return to programming mode */ - snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n"); - return -ENODEV; - } - snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg); - switch (emu->card_capabilities->emu_model) { - case EMU_MODEL_EMU1010: - filename = HANA_FILENAME; - break; - case EMU_MODEL_EMU1010B: - filename = EMU1010B_FILENAME; - break; - case EMU_MODEL_EMU1616: - filename = EMU1010_NOTEBOOK_FILENAME; - break; - case EMU_MODEL_EMU0404: - filename = EMU0404_FILENAME; - break; - default: - filename = NULL; - return -ENODEV; - break; - } - snd_printk(KERN_INFO "emu1010: filename %s testing\n", filename); - err = snd_emu1010_load_firmware(emu, filename); - if (err != 0) { - snd_printk( - KERN_INFO "emu1010: Loading Firmware file %s failed\n", - filename); - return err; - } - - /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - if ((reg & 0x3f) != 0x15) { - /* FPGA failed to be programmed */ - snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); - return -ENODEV; - } - - snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); - snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp); - snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2); - snd_printk(KERN_INFO "emu1010: Hana version: %u.%u\n", tmp, tmp2); - /* Enable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON); - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp); - /* Optical -> ADAT I/O */ - /* 0 : SPDIF - * 1 : ADAT - */ - emu->emu1010.optical_in = 1; /* IN_ADAT */ - emu->emu1010.optical_out = 1; /* IN_ADAT */ - tmp = 0; - tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | - (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); - snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); - snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp); - /* Set no attenuation on Audio Dock pads. */ - snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00); - emu->emu1010.adc_pads = 0x00; - snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); - /* Unmute Audio dock DACs, Headphone source DAC-4. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); - snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp); - /* DAC PADs. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f); - emu->emu1010.dac_pads = 0x0f; - snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); - snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); - /* SPDIF Format. Set Consumer mode, 24bit, copy enable */ - snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); - /* MIDI routing */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); - /* Unknown. */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); - /* IRQ Enable: All on */ - /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */ - /* IRQ Enable: All off */ - snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options3 = 0x%x\n", reg); - /* Default WCLK set to 48kHz. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00); - /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); - /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ - /* Audio Dock LEDs. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); - -#if 0 - /* For 96kHz */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT2); -#endif -#if 0 - /* For 192kHz */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_RIGHT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT3); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT3); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_6, EMU_SRC_HAMOA_ADC_LEFT4); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_7, EMU_SRC_HAMOA_ADC_RIGHT4); -#endif -#if 1 - /* For 48kHz */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_0, EMU_SRC_DOCK_MIC_A1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_1, EMU_SRC_DOCK_MIC_B1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_4, EMU_SRC_DOCK_ADC1_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_5, EMU_SRC_DOCK_ADC1_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1); - /* Pavel Hofman - setting defaults for 8 more capture channels - * Defaults only, users will set their own values anyways, let's - * just copy/paste. - */ - - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_9, EMU_SRC_DOCK_MIC_B1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_A, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_B, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_ADC1_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_ADC1_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_E, EMU_SRC_DOCK_ADC2_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_F, EMU_SRC_DOCK_ADC2_RIGHT1); -#endif -#if 0 - /* Original */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_4, EMU_SRC_HANA_ADAT); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_5, EMU_SRC_HANA_ADAT + 1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_6, EMU_SRC_HANA_ADAT + 2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_7, EMU_SRC_HANA_ADAT + 3); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_8, EMU_SRC_HANA_ADAT + 4); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_9, EMU_SRC_HANA_ADAT + 5); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_A, EMU_SRC_HANA_ADAT + 6); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_B, EMU_SRC_HANA_ADAT + 7); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_MIC_A1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_MIC_B1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_E, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2); -#endif - for (i = 0; i < 0x20; i++) { - /* AudioDock Elink <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0100 + i, EMU_SRC_SILENCE); - } - for (i = 0; i < 4; i++) { - /* Hana SPDIF Out <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0200 + i, EMU_SRC_SILENCE); - } - for (i = 0; i < 7; i++) { - /* Hamoa DAC <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0300 + i, EMU_SRC_SILENCE); - } - for (i = 0; i < 7; i++) { - /* Hana ADAT Out <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE); - } - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S0_LEFT, EMU_SRC_DOCK_ADC1_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S0_RIGHT, EMU_SRC_DOCK_ADC1_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S1_LEFT, EMU_SRC_DOCK_ADC2_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S1_RIGHT, EMU_SRC_DOCK_ADC2_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1); - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */ - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); - - /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0000a000, emu->port + HCFG); - /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Un-Mute all codecs. - */ - outl(0x0000a001, emu->port + HCFG); - - /* Initial boot complete. Now patches */ - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ - snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ - - /* Start Micro/Audio Dock firmware loader thread */ - if (!emu->emu1010.firmware_thread) { - emu->emu1010.firmware_thread = - kthread_create(emu1010_firmware_thread, emu, - "emu1010_firmware"); - wake_up_process(emu->emu1010.firmware_thread); - } - -#if 0 - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32B + 3); /* ALICE2 bus 0xa3 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 2); /* ALICE2 bus 0xb2 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); /* ALICE2 bus 0xb3 */ -#endif - /* Default outputs */ - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { - /* 1616(M) cardbus default outputs */ - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[0] = 17; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[1] = 18; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2); - emu->emu1010.output_source[2] = 19; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); - emu->emu1010.output_source[3] = 20; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4); - emu->emu1010.output_source[4] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5); - emu->emu1010.output_source[5] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_MANA_DAC_LEFT, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[16] = 17; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_MANA_DAC_RIGHT, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[17] = 18; - } else { - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[0] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[1] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2); - emu->emu1010.output_source[2] = 23; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); - emu->emu1010.output_source[3] = 24; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4); - emu->emu1010.output_source[4] = 25; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5); - emu->emu1010.output_source[5] = 26; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC4_LEFT1, EMU_SRC_ALICE_EMU32A + 6); - emu->emu1010.output_source[6] = 27; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC4_RIGHT1, EMU_SRC_ALICE_EMU32A + 7); - emu->emu1010.output_source[7] = 28; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_PHONES_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[8] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_PHONES_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[9] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[10] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[11] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[12] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[13] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[14] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[15] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[16] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[17] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 2, EMU_SRC_ALICE_EMU32A + 2); - emu->emu1010.output_source[18] = 23; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 3, EMU_SRC_ALICE_EMU32A + 3); - emu->emu1010.output_source[19] = 24; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 4, EMU_SRC_ALICE_EMU32A + 4); - emu->emu1010.output_source[20] = 25; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 5, EMU_SRC_ALICE_EMU32A + 5); - emu->emu1010.output_source[21] = 26; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 6, EMU_SRC_ALICE_EMU32A + 6); - emu->emu1010.output_source[22] = 27; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7); - emu->emu1010.output_source[23] = 28; - } - /* TEMP: Select SPDIF in/out */ - /* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */ - - /* TEMP: Select 48kHz SPDIF out */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */ - /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); - /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ - emu->emu1010.internal_clock = 1; /* 48000 */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */ - /* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */ - /* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */ - /* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */ - - return 0; -} -/* - * Create the EMU10K1 instance - */ - -#ifdef CONFIG_PM -static int alloc_pm_buffer(struct snd_emu10k1 *emu); -static void free_pm_buffer(struct snd_emu10k1 *emu); -#endif - -static int snd_emu10k1_free(struct snd_emu10k1 *emu) -{ - if (emu->port) { /* avoid access to already used hardware */ - snd_emu10k1_fx8010_tram_setup(emu, 0); - snd_emu10k1_done(emu); - snd_emu10k1_free_efx(emu); - } - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { - /* Disable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); - } - if (emu->emu1010.firmware_thread) - kthread_stop(emu->emu1010.firmware_thread); - if (emu->irq >= 0) - free_irq(emu->irq, emu); - /* remove reserved page */ - if (emu->reserved_page) { - snd_emu10k1_synth_free(emu, - (struct snd_util_memblk *)emu->reserved_page); - emu->reserved_page = NULL; - } - if (emu->memhdr) - snd_util_memhdr_free(emu->memhdr); - if (emu->silent_page.area) - snd_dma_free_pages(&emu->silent_page); - if (emu->ptb_pages.area) - snd_dma_free_pages(&emu->ptb_pages); - vfree(emu->page_ptr_table); - vfree(emu->page_addr_table); -#ifdef CONFIG_PM - free_pm_buffer(emu); -#endif - if (emu->port) - pci_release_regions(emu->pci); - if (emu->card_capabilities->ca0151_chip) /* P16V */ - snd_p16v_free(emu); - pci_disable_device(emu->pci); - kfree(emu); - return 0; -} - -static int snd_emu10k1_dev_free(struct snd_device *device) -{ - struct snd_emu10k1 *emu = device->device_data; - return snd_emu10k1_free(emu); -} - -static struct snd_emu_chip_details emu_chip_details[] = { - /* Audigy4 (Not PRO) SB0610 */ - /* Tested by James@superbug.co.uk 4th April 2006 */ - /* A_IOCFG bits - * Output - * 0: ? - * 1: ? - * 2: ? - * 3: 0 - Digital Out, 1 - Line in - * 4: ? - * 5: ? - * 6: ? - * 7: ? - * Input - * 8: ? - * 9: ? - * A: Green jack sense (Front) - * B: ? - * C: Black jack sense (Rear/Side Right) - * D: Yellow jack sense (Center/LFE/Side Left) - * E: ? - * F: ? - * - * Digital Out/Line in switch using A_IOCFG bit 3 (0x08) - * 0 - Digital Out - * 1 - Line in - */ - /* Mic input not tested. - * Analog CD input not tested - * Digital Out not tested. - * Line in working. - * Audio output 5.1 working. Side outputs not working. - */ - /* DSP: CA10300-IAT LF - * DAC: Cirrus Logic CS4382-KQZ - * ADC: Philips 1361T - * AC97: Sigmatel STAC9750 - * CA0151: None - */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, - .driver = "Audigy2", .name = "SB Audigy 4 [SB0610]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .adc_1361t = 1, /* 24 bit capture instead of 16bit */ - .ac97_chip = 1} , - /* Audigy 2 Value AC3 out does not work yet. - * Need to find out how to turn off interpolators. - */ - /* Tested by James@superbug.co.uk 3rd July 2005 */ - /* DSP: CA0108-IAT - * DAC: CS4382-KQ - * ADC: Philips 1361T - * AC97: STAC9750 - * CA0151: None - */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, - .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .ac97_chip = 1} , - /* Audigy 2 ZS Notebook Cardbus card.*/ - /* Tested by James@superbug.co.uk 6th November 2006 */ - /* Audio output 7.1/Headphones working. - * Digital output working. (AC3 not checked, only PCM) - * Audio Mic/Line inputs working. - * Digital input not tested. - */ - /* DSP: Tina2 - * DAC: Wolfson WM8768/WM8568 - * ADC: Wolfson WM8775 - * AC97: None - * CA0151: None - */ - /* Tested by James@superbug.co.uk 4th April 2006 */ - /* A_IOCFG bits - * Output - * 0: Not Used - * 1: 0 = Mute all the 7.1 channel out. 1 = unmute. - * 2: Analog input 0 = line in, 1 = mic in - * 3: Not Used - * 4: Digital output 0 = off, 1 = on. - * 5: Not Used - * 6: Not Used - * 7: Not Used - * Input - * All bits 1 (0x3fxx) means nothing plugged in. - * 8-9: 0 = Line in/Mic, 2 = Optical in, 3 = Nothing. - * A-B: 0 = Headphones, 2 = Optical out, 3 = Nothing. - * C-D: 2 = Front/Rear/etc, 3 = nothing. - * E-F: Always 0 - * - */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .ca_cardbus_chip = 1, - .spi_dac = 1, - .i2c_adc = 1, - .spk71 = 1} , - /* Tested by James@superbug.co.uk 4th Nov 2007. */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, - .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", - .id = "EMU1010", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .ca_cardbus_chip = 1, - .spk71 = 1 , - .emu_model = EMU_MODEL_EMU1616}, - /* Tested by James@superbug.co.uk 4th Nov 2007. */ - /* This is MAEM8960, 0202 is MAEM 8980 */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, - .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]", - .id = "EMU1010", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ - /* Tested by James@superbug.co.uk 8th July 2005. */ - /* This is MAEM8810, 0202 is MAEM8820 */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, - .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]", - .id = "EMU1010", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */ - /* EMU0404b */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, - .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]", - .id = "EMU0404", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */ - /* Tested by James@superbug.co.uk 20-3-2007. */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, - .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]", - .id = "EMU0404", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ - /* EMU0404 PCIe */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, - .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", - .id = "EMU0404", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ - /* Note that all E-mu cards require kernel 2.6 or newer. */ - {.vendor = 0x1102, .device = 0x0008, - .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .ac97_chip = 1} , - /* Tested by James@superbug.co.uk 3rd July 2005 */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, - .driver = "Audigy2", .name = "SB Audigy 4 PRO [SB0380]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .ac97_chip = 1} , - /* Tested by shane-alsa@cm.nu 5th Nov 2005 */ - /* The 0x20061102 does have SB0350 written on it - * Just like 0x20021102 - */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102, - .driver = "Audigy2", .name = "SB Audigy 2 [SB0350b]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - /* 0x20051102 also has SB0350 written on it, treated as Audigy 2 ZS by - Creative's Windows driver */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20051102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350a]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0360]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - /* Audigy 2 */ - /* Tested by James@superbug.co.uk 3rd July 2005 */ - /* DSP: CA0102-IAT - * DAC: CS4382-KQ - * ADC: Philips 1361T - * AC97: STAC9721 - * CA0151: Yes - */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, - .driver = "Audigy2", .name = "SB Audigy 2 [SB0240]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .adc_1361t = 1, /* 24 bit capture instead of 16bit */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, - .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1} , - /* Dell OEM/Creative Labs Audigy 2 ZS */ - /* See ALSA bug#1365 */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0353]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, - .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, - .driver = "Audigy2", .name = "SB Audigy 2 [Unknown]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spdif_bug = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, - .driver = "Audigy", .name = "SB Audigy 1 [SB0092]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102, - .driver = "Audigy", .name = "SB Audigy 1 ES [SB0160]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .spdif_bug = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, - .driver = "Audigy", .name = "SB Audigy 1 [SB0090]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, - .driver = "Audigy", .name = "Audigy 1 [Unknown]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102, - .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806b1102, - .driver = "EMU10K1", .name = "SB Live! [SB0105]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806a1102, - .driver = "EMU10K1", .name = "SB Live! Value [SB0103]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, - .driver = "EMU10K1", .name = "SB Live! Value [SB0101]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - /* Tested by ALSA bug#1680 26th December 2005 */ - /* note: It really has SB0220 written on the card, */ - /* but it's SB0228 according to kx.inf */ - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80661102, - .driver = "EMU10K1", .name = "SB Live! 5.1 Dell OEM [SB0228]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - /* Tested by Thomas Zehetbauer 27th Aug 2005 */ - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102, - .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, - .driver = "EMU10K1", .name = "SB Live! 5.1", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */ - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, - .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0060]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum - * share the same IDs! - */ - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4850]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, - .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4871]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4831]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4870]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - /* Tested by James@superbug.co.uk 3rd July 2005 */ - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4832]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4830]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, - .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4780]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, - .driver = "EMU10K1", .name = "E-mu APS [PC545]", - .id = "APS", - .emu10k1_chip = 1, - .ecard = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, - .driver = "EMU10K1", .name = "SB Live! [CT4620]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4670]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, - .driver = "EMU10K1", .name = "SB Live! [Unknown]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - { } /* terminator */ -}; - -int __devinit snd_emu10k1_create(struct snd_card *card, - struct pci_dev *pci, - unsigned short extin_mask, - unsigned short extout_mask, - long max_cache_bytes, - int enable_ir, - uint subsystem, - struct snd_emu10k1 **remu) -{ - struct snd_emu10k1 *emu; - int idx, err; - int is_audigy; - unsigned int silent_page; - const struct snd_emu_chip_details *c; - static struct snd_device_ops ops = { - .dev_free = snd_emu10k1_dev_free, - }; - - *remu = NULL; - - /* enable PCI device */ - err = pci_enable_device(pci); - if (err < 0) - return err; - - emu = kzalloc(sizeof(*emu), GFP_KERNEL); - if (emu == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - emu->card = card; - spin_lock_init(&emu->reg_lock); - spin_lock_init(&emu->emu_lock); - spin_lock_init(&emu->spi_lock); - spin_lock_init(&emu->i2c_lock); - spin_lock_init(&emu->voice_lock); - spin_lock_init(&emu->synth_lock); - spin_lock_init(&emu->memblk_lock); - mutex_init(&emu->fx8010.lock); - INIT_LIST_HEAD(&emu->mapped_link_head); - INIT_LIST_HEAD(&emu->mapped_order_link_head); - emu->pci = pci; - emu->irq = -1; - emu->synth = NULL; - emu->get_synth_voice = NULL; - /* read revision & serial */ - emu->revision = pci->revision; - pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); - snd_printdd("vendor = 0x%x, device = 0x%x, subsystem_vendor_id = 0x%x, subsystem_id = 0x%x\n", pci->vendor, pci->device, emu->serial, emu->model); - - for (c = emu_chip_details; c->vendor; c++) { - if (c->vendor == pci->vendor && c->device == pci->device) { - if (subsystem) { - if (c->subsystem && (c->subsystem == subsystem)) - break; - else - continue; - } else { - if (c->subsystem && (c->subsystem != emu->serial)) - continue; - if (c->revision && c->revision != emu->revision) - continue; - } - break; - } - } - if (c->vendor == 0) { - snd_printk(KERN_ERR "emu10k1: Card not recognised\n"); - kfree(emu); - pci_disable_device(pci); - return -ENOENT; - } - emu->card_capabilities = c; - if (c->subsystem && !subsystem) - snd_printdd("Sound card name = %s\n", c->name); - else if (subsystem) - snd_printdd("Sound card name = %s, " - "vendor = 0x%x, device = 0x%x, subsystem = 0x%x. " - "Forced to subsystem = 0x%x\n", c->name, - pci->vendor, pci->device, emu->serial, c->subsystem); - else - snd_printdd("Sound card name = %s, " - "vendor = 0x%x, device = 0x%x, subsystem = 0x%x.\n", - c->name, pci->vendor, pci->device, - emu->serial); - - if (!*card->id && c->id) { - int i, n = 0; - strlcpy(card->id, c->id, sizeof(card->id)); - for (;;) { - for (i = 0; i < snd_ecards_limit; i++) { - if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id)) - break; - } - if (i >= snd_ecards_limit) - break; - n++; - if (n >= SNDRV_CARDS) - break; - snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n); - } - } - - is_audigy = emu->audigy = c->emu10k2_chip; - - /* set the DMA transfer mask */ - emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; - if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || - pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { - snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); - kfree(emu); - pci_disable_device(pci); - return -ENXIO; - } - if (is_audigy) - emu->gpr_base = A_FXGPREGBASE; - else - emu->gpr_base = FXGPREGBASE; - - err = pci_request_regions(pci, "EMU10K1"); - if (err < 0) { - kfree(emu); - pci_disable_device(pci); - return err; - } - emu->port = pci_resource_start(pci, 0); - - emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - 32 * 1024, &emu->ptb_pages) < 0) { - err = -ENOMEM; - goto error; - } - - emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *)); - emu->page_addr_table = vmalloc(emu->max_cache_pages * - sizeof(unsigned long)); - if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) { - err = -ENOMEM; - goto error; - } - - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - EMUPAGESIZE, &emu->silent_page) < 0) { - err = -ENOMEM; - goto error; - } - emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE); - if (emu->memhdr == NULL) { - err = -ENOMEM; - goto error; - } - emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) - - sizeof(struct snd_util_memblk); - - pci_set_master(pci); - - emu->fx8010.fxbus_mask = 0x303f; - if (extin_mask == 0) - extin_mask = 0x3fcf; - if (extout_mask == 0) - extout_mask = 0x7fff; - emu->fx8010.extin_mask = extin_mask; - emu->fx8010.extout_mask = extout_mask; - emu->enable_ir = enable_ir; - - if (emu->card_capabilities->ca_cardbus_chip) { - err = snd_emu10k1_cardbus_init(emu); - if (err < 0) - goto error; - } - if (emu->card_capabilities->ecard) { - err = snd_emu10k1_ecard_init(emu); - if (err < 0) - goto error; - } else if (emu->card_capabilities->emu_model) { - err = snd_emu10k1_emu1010_init(emu); - if (err < 0) { - snd_emu10k1_free(emu); - return err; - } - } else { - /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version - does not support this, it shouldn't do any harm */ - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, - AC97SLOT_CNTR|AC97SLOT_LFE); - } - - /* initialize TRAM setup */ - emu->fx8010.itram_size = (16 * 1024)/2; - emu->fx8010.etram_pages.area = NULL; - emu->fx8010.etram_pages.bytes = 0; - - /* irq handler must be registered after I/O ports are activated */ - if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED, - KBUILD_MODNAME, emu)) { - err = -EBUSY; - goto error; - } - emu->irq = pci->irq; - - /* - * Init to 0x02109204 : - * Clock accuracy = 0 (1000ppm) - * Sample Rate = 2 (48kHz) - * Audio Channel = 1 (Left of 2) - * Source Number = 0 (Unspecified) - * Generation Status = 1 (Original for Cat Code 12) - * Cat Code = 12 (Digital Signal Mixer) - * Mode = 0 (Mode 0) - * Emphasis = 0 (None) - * CP = 1 (Copyright unasserted) - * AN = 0 (Audio data) - * P = 0 (Consumer) - */ - emu->spdif_bits[0] = emu->spdif_bits[1] = - emu->spdif_bits[2] = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; - - emu->reserved_page = (struct snd_emu10k1_memblk *) - snd_emu10k1_synth_alloc(emu, 4096); - if (emu->reserved_page) - emu->reserved_page->map_locked = 1; - - /* Clear silent pages and set up pointers */ - memset(emu->silent_page.area, 0, PAGE_SIZE); - silent_page = emu->silent_page.addr << 1; - for (idx = 0; idx < MAXPAGES; idx++) - ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); - - /* set up voice indices */ - for (idx = 0; idx < NUM_G; idx++) { - emu->voices[idx].emu = emu; - emu->voices[idx].number = idx; - } - - err = snd_emu10k1_init(emu, enable_ir, 0); - if (err < 0) - goto error; -#ifdef CONFIG_PM - err = alloc_pm_buffer(emu); - if (err < 0) - goto error; -#endif - - /* Initialize the effect engine */ - err = snd_emu10k1_init_efx(emu); - if (err < 0) - goto error; - snd_emu10k1_audio_enable(emu); - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops); - if (err < 0) - goto error; - -#ifdef CONFIG_PROC_FS - snd_emu10k1_proc_init(emu); -#endif - - snd_card_set_dev(card, &pci->dev); - *remu = emu; - return 0; - - error: - snd_emu10k1_free(emu); - return err; -} - -#ifdef CONFIG_PM -static unsigned char saved_regs[] = { - CPF, PTRX, CVCF, VTFT, Z1, Z2, PSST, DSL, CCCA, CCR, CLP, - FXRT, MAPA, MAPB, ENVVOL, ATKHLDV, DCYSUSV, LFOVAL1, ENVVAL, - ATKHLDM, DCYSUSM, LFOVAL2, IP, IFATN, PEFE, FMMOD, TREMFRQ, FM2FRQ2, - TEMPENV, ADCCR, FXWC, MICBA, ADCBA, FXBA, - MICBS, ADCBS, FXBS, CDCS, GPSCS, SPCS0, SPCS1, SPCS2, - SPBYPASS, AC97SLOT, CDSRCS, GPSRCS, ZVSRCS, MICIDX, ADCIDX, FXIDX, - 0xff /* end */ -}; -static unsigned char saved_regs_audigy[] = { - A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_SAMPLE_RATE, - A_FXRT2, A_SENDAMOUNTS, A_FXRT1, - 0xff /* end */ -}; - -static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu) -{ - int size; - - size = ARRAY_SIZE(saved_regs); - if (emu->audigy) - size += ARRAY_SIZE(saved_regs_audigy); - emu->saved_ptr = vmalloc(4 * NUM_G * size); - if (!emu->saved_ptr) - return -ENOMEM; - if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0) - return -ENOMEM; - if (emu->card_capabilities->ca0151_chip && - snd_p16v_alloc_pm_buffer(emu) < 0) - return -ENOMEM; - return 0; -} - -static void free_pm_buffer(struct snd_emu10k1 *emu) -{ - vfree(emu->saved_ptr); - snd_emu10k1_efx_free_pm_buffer(emu); - if (emu->card_capabilities->ca0151_chip) - snd_p16v_free_pm_buffer(emu); -} - -void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu) -{ - int i; - unsigned char *reg; - unsigned int *val; - - val = emu->saved_ptr; - for (reg = saved_regs; *reg != 0xff; reg++) - for (i = 0; i < NUM_G; i++, val++) - *val = snd_emu10k1_ptr_read(emu, *reg, i); - if (emu->audigy) { - for (reg = saved_regs_audigy; *reg != 0xff; reg++) - for (i = 0; i < NUM_G; i++, val++) - *val = snd_emu10k1_ptr_read(emu, *reg, i); - } - if (emu->audigy) - emu->saved_a_iocfg = inl(emu->port + A_IOCFG); - emu->saved_hcfg = inl(emu->port + HCFG); -} - -void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) -{ - if (emu->card_capabilities->ca_cardbus_chip) - snd_emu10k1_cardbus_init(emu); - if (emu->card_capabilities->ecard) - snd_emu10k1_ecard_init(emu); - else if (emu->card_capabilities->emu_model) - snd_emu10k1_emu1010_init(emu); - else - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); - snd_emu10k1_init(emu, emu->enable_ir, 1); -} - -void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) -{ - int i; - unsigned char *reg; - unsigned int *val; - - snd_emu10k1_audio_enable(emu); - - /* resore for spdif */ - if (emu->audigy) - outl(emu->saved_a_iocfg, emu->port + A_IOCFG); - outl(emu->saved_hcfg, emu->port + HCFG); - - val = emu->saved_ptr; - for (reg = saved_regs; *reg != 0xff; reg++) - for (i = 0; i < NUM_G; i++, val++) - snd_emu10k1_ptr_write(emu, *reg, i, *val); - if (emu->audigy) { - for (reg = saved_regs_audigy; *reg != 0xff; reg++) - for (i = 0; i < NUM_G; i++, val++) - snd_emu10k1_ptr_write(emu, *reg, i, *val); - } -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c deleted file mode 100644 index e10f027b..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Patch transfer callback for Emu10k1 - * - * Copyright (C) 2000 Takashi iwai - * - * 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 - */ -/* - * All the code for loading in a patch. There is very little that is - * chip specific here. Just the actual writing to the board. - */ - -#include "emu10k1_synth_local.h" - -/* - */ -#define BLANK_LOOP_START 4 -#define BLANK_LOOP_END 8 -#define BLANK_LOOP_SIZE 12 -#define BLANK_HEAD_SIZE 32 - -/* - * allocate a sample block and copy data from userspace - */ -int -snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *data, long count) -{ - int offset; - int truesize, size, loopsize, blocksize; - int loopend, sampleend; - unsigned int start_addr; - struct snd_emu10k1 *emu; - - emu = rec->hw; - if (snd_BUG_ON(!sp || !hdr)) - return -EINVAL; - - if (sp->v.size == 0) { - snd_printd("emu: rom font for sample %d\n", sp->v.sample); - return 0; - } - - /* recalculate address offset */ - sp->v.end -= sp->v.start; - sp->v.loopstart -= sp->v.start; - sp->v.loopend -= sp->v.start; - sp->v.start = 0; - - /* some samples have invalid data. the addresses are corrected in voice info */ - sampleend = sp->v.end; - if (sampleend > sp->v.size) - sampleend = sp->v.size; - loopend = sp->v.loopend; - if (loopend > sampleend) - loopend = sampleend; - - /* be sure loop points start < end */ - if (sp->v.loopstart >= sp->v.loopend) { - int tmp = sp->v.loopstart; - sp->v.loopstart = sp->v.loopend; - sp->v.loopend = tmp; - } - - /* compute true data size to be loaded */ - truesize = sp->v.size + BLANK_HEAD_SIZE; - loopsize = 0; -#if 0 /* not supported */ - if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) - loopsize = sp->v.loopend - sp->v.loopstart; - truesize += loopsize; -#endif - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) - truesize += BLANK_LOOP_SIZE; - - /* try to allocate a memory block */ - blocksize = truesize; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - blocksize *= 2; - sp->block = snd_emu10k1_synth_alloc(emu, blocksize); - if (sp->block == NULL) { - snd_printd("emu10k1: synth malloc failed (size=%d)\n", blocksize); - /* not ENOMEM (for compatibility with OSS) */ - return -ENOSPC; - } - /* set the total size */ - sp->v.truesize = blocksize; - - /* write blank samples at head */ - offset = 0; - size = BLANK_HEAD_SIZE; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - size *= 2; - if (offset + size > blocksize) - return -EINVAL; - snd_emu10k1_synth_bzero(emu, sp->block, offset, size); - offset += size; - - /* copy start->loopend */ - size = loopend; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - size *= 2; - if (offset + size > blocksize) - return -EINVAL; - if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) { - snd_emu10k1_synth_free(emu, sp->block); - sp->block = NULL; - return -EFAULT; - } - offset += size; - data += size; - -#if 0 /* not suppported yet */ - /* handle reverse (or bidirectional) loop */ - if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) { - /* copy loop in reverse */ - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) { - int woffset; - unsigned short *wblock = (unsigned short*)block; - woffset = offset / 2; - if (offset + loopsize * 2 > blocksize) - return -EINVAL; - for (i = 0; i < loopsize; i++) - wblock[woffset + i] = wblock[woffset - i -1]; - offset += loopsize * 2; - } else { - if (offset + loopsize > blocksize) - return -EINVAL; - for (i = 0; i < loopsize; i++) - block[offset + i] = block[offset - i -1]; - offset += loopsize; - } - - /* modify loop pointers */ - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) { - sp->v.loopend += loopsize; - } else { - sp->v.loopstart += loopsize; - sp->v.loopend += loopsize; - } - /* add sample pointer */ - sp->v.end += loopsize; - } -#endif - - /* loopend -> sample end */ - size = sp->v.size - loopend; - if (size < 0) - return -EINVAL; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - size *= 2; - if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) { - snd_emu10k1_synth_free(emu, sp->block); - sp->block = NULL; - return -EFAULT; - } - offset += size; - - /* clear rest of samples (if any) */ - if (offset < blocksize) - snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset); - - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) { - /* if no blank loop is attached in the sample, add it */ - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) { - sp->v.loopstart = sp->v.end + BLANK_LOOP_START; - sp->v.loopend = sp->v.end + BLANK_LOOP_END; - } - } - -#if 0 /* not supported yet */ - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) { - /* unsigned -> signed */ - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) { - unsigned short *wblock = (unsigned short*)block; - for (i = 0; i < truesize; i++) - wblock[i] ^= 0x8000; - } else { - for (i = 0; i < truesize; i++) - block[i] ^= 0x80; - } - } -#endif - - /* recalculate offset */ - start_addr = BLANK_HEAD_SIZE * 2; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - start_addr >>= 1; - sp->v.start += start_addr; - sp->v.end += start_addr; - sp->v.loopstart += start_addr; - sp->v.loopend += start_addr; - - return 0; -} - -/* - * free a sample block - */ -int -snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr) -{ - struct snd_emu10k1 *emu; - - emu = rec->hw; - if (snd_BUG_ON(!sp || !hdr)) - return -EINVAL; - - if (sp->block) { - snd_emu10k1_synth_free(emu, sp->block); - sp->block = NULL; - } - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c deleted file mode 100644 index 4c41c903..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2000 Takashi Iwai - * - * Routines for control of EMU10K1 WaveTable synth - * - * 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 "emu10k1_synth_local.h" -#include -#include - -MODULE_AUTHOR("Takashi Iwai"); -MODULE_DESCRIPTION("Routines for control of EMU10K1 WaveTable synth"); -MODULE_LICENSE("GPL"); - -/* - * create a new hardware dependent device for Emu10k1 - */ -static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) -{ - struct snd_emux *emux; - struct snd_emu10k1 *hw; - struct snd_emu10k1_synth_arg *arg; - unsigned long flags; - - arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (arg == NULL) - return -EINVAL; - - if (arg->seq_ports <= 0) - return 0; /* nothing */ - if (arg->max_voices < 1) - arg->max_voices = 1; - else if (arg->max_voices > 64) - arg->max_voices = 64; - - if (snd_emux_new(&emux) < 0) - return -ENOMEM; - - snd_emu10k1_ops_setup(emux); - hw = arg->hwptr; - emux->hw = hw; - emux->max_voices = arg->max_voices; - emux->num_ports = arg->seq_ports; - emux->pitch_shift = -501; - emux->memhdr = hw->memhdr; - /* maximum two ports */ - emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; - /* audigy has two external midis */ - emux->midi_devidx = hw->audigy ? 2 : 1; - emux->linear_panning = 0; - emux->hwdep_idx = 2; /* FIXED */ - - if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) { - snd_emux_free(emux); - return -ENOMEM; - } - - spin_lock_irqsave(&hw->voice_lock, flags); - hw->synth = emux; - hw->get_synth_voice = snd_emu10k1_synth_get_voice; - spin_unlock_irqrestore(&hw->voice_lock, flags); - - dev->driver_data = emux; - - return 0; -} - -static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev) -{ - struct snd_emux *emux; - struct snd_emu10k1 *hw; - unsigned long flags; - - if (dev->driver_data == NULL) - return 0; /* not registered actually */ - - emux = dev->driver_data; - - hw = emux->hw; - spin_lock_irqsave(&hw->voice_lock, flags); - hw->synth = NULL; - hw->get_synth_voice = NULL; - spin_unlock_irqrestore(&hw->voice_lock, flags); - - snd_emux_free(emux); - return 0; -} - -/* - * INIT part - */ - -static int __init alsa_emu10k1_synth_init(void) -{ - - static struct snd_seq_dev_ops ops = { - snd_emu10k1_synth_new_device, - snd_emu10k1_synth_delete_device, - }; - return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, &ops, - sizeof(struct snd_emu10k1_synth_arg)); -} - -static void __exit alsa_emu10k1_synth_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH); -} - -module_init(alsa_emu10k1_synth_init) -module_exit(alsa_emu10k1_synth_exit) diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth_local.h b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth_local.h deleted file mode 100644 index 25f328ff..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth_local.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __EMU10K1_SYNTH_LOCAL_H -#define __EMU10K1_SYNTH_LOCAL_H -/* - * Local defininitons for Emu10k1 wavetable - * - * Copyright (C) 2000 Takashi Iwai - * - * 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 - -/* emu10k1_patch.c */ -int snd_emu10k1_sample_new(struct snd_emux *private_data, - struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *_data, long count); -int snd_emu10k1_sample_free(struct snd_emux *private_data, - struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr); -int snd_emu10k1_memhdr_init(struct snd_emux *emu); - -/* emu10k1_callback.c */ -void snd_emu10k1_ops_setup(struct snd_emux *emu); -int snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw); - - -#endif /* __EMU10K1_SYNTH_LOCAL_H */ diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c deleted file mode 100644 index 47a651cb..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c +++ /dev/null @@ -1,1635 +0,0 @@ -/* - * Copyright (c) by Francisco Moraes - * Driver EMU10K1X chips - * - * Parts of this code were adapted from audigyls.c driver which is - * Copyright (c) by James Courtier-Dutton - * - * BUGS: - * -- - * - * TODO: - * - * Chips (SB0200 model): - * - EMU10K1X-DBQ - * - STAC 9708T - * - * 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 -#include -#include -#include - -MODULE_AUTHOR("Francisco Moraes "); -MODULE_DESCRIPTION("EMU10K1X"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Dell Creative Labs,SB Live!}"); - -// module parameters (see "Module Parameters") -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the EMU10K1X soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the EMU10K1X soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable the EMU10K1X soundcard."); - - -// some definitions were borrowed from emu10k1 driver as they seem to be the same -/************************************************************************************************/ -/* PCI function 0 registers, address = + PCIBASE0 */ -/************************************************************************************************/ - -#define PTR 0x00 /* Indexed register set pointer register */ - /* NOTE: The CHANNELNUM and ADDRESS words can */ - /* be modified independently of each other. */ - -#define DATA 0x04 /* Indexed register set data register */ - -#define IPR 0x08 /* Global interrupt pending register */ - /* Clear pending interrupts by writing a 1 to */ - /* the relevant bits and zero to the other bits */ -#define IPR_MIDITRANSBUFEMPTY 0x00000001 /* MIDI UART transmit buffer empty */ -#define IPR_MIDIRECVBUFEMPTY 0x00000002 /* MIDI UART receive buffer empty */ -#define IPR_CH_0_LOOP 0x00000800 /* Channel 0 loop */ -#define IPR_CH_0_HALF_LOOP 0x00000100 /* Channel 0 half loop */ -#define IPR_CAP_0_LOOP 0x00080000 /* Channel capture loop */ -#define IPR_CAP_0_HALF_LOOP 0x00010000 /* Channel capture half loop */ - -#define INTE 0x0c /* Interrupt enable register */ -#define INTE_MIDITXENABLE 0x00000001 /* Enable MIDI transmit-buffer-empty interrupts */ -#define INTE_MIDIRXENABLE 0x00000002 /* Enable MIDI receive-buffer-empty interrupts */ -#define INTE_CH_0_LOOP 0x00000800 /* Channel 0 loop */ -#define INTE_CH_0_HALF_LOOP 0x00000100 /* Channel 0 half loop */ -#define INTE_CAP_0_LOOP 0x00080000 /* Channel capture loop */ -#define INTE_CAP_0_HALF_LOOP 0x00010000 /* Channel capture half loop */ - -#define HCFG 0x14 /* Hardware config register */ - -#define HCFG_LOCKSOUNDCACHE 0x00000008 /* 1 = Cancel bustmaster accesses to soundcache */ - /* NOTE: This should generally never be used. */ -#define HCFG_AUDIOENABLE 0x00000001 /* 0 = CODECs transmit zero-valued samples */ - /* Should be set to 1 when the EMU10K1 is */ - /* completely initialized. */ -#define GPIO 0x18 /* Defaults: 00001080-Analog, 00001000-SPDIF. */ - - -#define AC97DATA 0x1c /* AC97 register set data register (16 bit) */ - -#define AC97ADDRESS 0x1e /* AC97 register set address register (8 bit) */ - -/********************************************************************************************************/ -/* Emu10k1x pointer-offset register set, accessed through the PTR and DATA registers */ -/********************************************************************************************************/ -#define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */ - /* One list entry: 4 bytes for DMA address, - * 4 bytes for period_size << 16. - * One list entry is 8 bytes long. - * One list entry for each period in the buffer. - */ -#define PLAYBACK_LIST_SIZE 0x01 /* Size of list in bytes << 16. E.g. 8 periods -> 0x00380000 */ -#define PLAYBACK_LIST_PTR 0x02 /* Pointer to the current period being played */ -#define PLAYBACK_DMA_ADDR 0x04 /* Playback DMA address */ -#define PLAYBACK_PERIOD_SIZE 0x05 /* Playback period size */ -#define PLAYBACK_POINTER 0x06 /* Playback period pointer. Sample currently in DAC */ -#define PLAYBACK_UNKNOWN1 0x07 -#define PLAYBACK_UNKNOWN2 0x08 - -/* Only one capture channel supported */ -#define CAPTURE_DMA_ADDR 0x10 /* Capture DMA address */ -#define CAPTURE_BUFFER_SIZE 0x11 /* Capture buffer size */ -#define CAPTURE_POINTER 0x12 /* Capture buffer pointer. Sample currently in ADC */ -#define CAPTURE_UNKNOWN 0x13 - -/* From 0x20 - 0x3f, last samples played on each channel */ - -#define TRIGGER_CHANNEL 0x40 /* Trigger channel playback */ -#define TRIGGER_CHANNEL_0 0x00000001 /* Trigger channel 0 */ -#define TRIGGER_CHANNEL_1 0x00000002 /* Trigger channel 1 */ -#define TRIGGER_CHANNEL_2 0x00000004 /* Trigger channel 2 */ -#define TRIGGER_CAPTURE 0x00000100 /* Trigger capture channel */ - -#define ROUTING 0x41 /* Setup sound routing ? */ -#define ROUTING_FRONT_LEFT 0x00000001 -#define ROUTING_FRONT_RIGHT 0x00000002 -#define ROUTING_REAR_LEFT 0x00000004 -#define ROUTING_REAR_RIGHT 0x00000008 -#define ROUTING_CENTER_LFE 0x00010000 - -#define SPCS0 0x42 /* SPDIF output Channel Status 0 register */ - -#define SPCS1 0x43 /* SPDIF output Channel Status 1 register */ - -#define SPCS2 0x44 /* SPDIF output Channel Status 2 register */ - -#define SPCS_CLKACCYMASK 0x30000000 /* Clock accuracy */ -#define SPCS_CLKACCY_1000PPM 0x00000000 /* 1000 parts per million */ -#define SPCS_CLKACCY_50PPM 0x10000000 /* 50 parts per million */ -#define SPCS_CLKACCY_VARIABLE 0x20000000 /* Variable accuracy */ -#define SPCS_SAMPLERATEMASK 0x0f000000 /* Sample rate */ -#define SPCS_SAMPLERATE_44 0x00000000 /* 44.1kHz sample rate */ -#define SPCS_SAMPLERATE_48 0x02000000 /* 48kHz sample rate */ -#define SPCS_SAMPLERATE_32 0x03000000 /* 32kHz sample rate */ -#define SPCS_CHANNELNUMMASK 0x00f00000 /* Channel number */ -#define SPCS_CHANNELNUM_UNSPEC 0x00000000 /* Unspecified channel number */ -#define SPCS_CHANNELNUM_LEFT 0x00100000 /* Left channel */ -#define SPCS_CHANNELNUM_RIGHT 0x00200000 /* Right channel */ -#define SPCS_SOURCENUMMASK 0x000f0000 /* Source number */ -#define SPCS_SOURCENUM_UNSPEC 0x00000000 /* Unspecified source number */ -#define SPCS_GENERATIONSTATUS 0x00008000 /* Originality flag (see IEC-958 spec) */ -#define SPCS_CATEGORYCODEMASK 0x00007f00 /* Category code (see IEC-958 spec) */ -#define SPCS_MODEMASK 0x000000c0 /* Mode (see IEC-958 spec) */ -#define SPCS_EMPHASISMASK 0x00000038 /* Emphasis */ -#define SPCS_EMPHASIS_NONE 0x00000000 /* No emphasis */ -#define SPCS_EMPHASIS_50_15 0x00000008 /* 50/15 usec 2 channel */ -#define SPCS_COPYRIGHT 0x00000004 /* Copyright asserted flag -- do not modify */ -#define SPCS_NOTAUDIODATA 0x00000002 /* 0 = Digital audio, 1 = not audio */ -#define SPCS_PROFESSIONAL 0x00000001 /* 0 = Consumer (IEC-958), 1 = pro (AES3-1992) */ - -#define SPDIF_SELECT 0x45 /* Enables SPDIF or Analogue outputs 0-Analogue, 0x700-SPDIF */ - -/* This is the MPU port on the card */ -#define MUDATA 0x47 -#define MUCMD 0x48 -#define MUSTAT MUCMD - -/* From 0x50 - 0x5f, last samples captured */ - -/** - * The hardware has 3 channels for playback and 1 for capture. - * - channel 0 is the front channel - * - channel 1 is the rear channel - * - channel 2 is the center/lfe channel - * Volume is controlled by the AC97 for the front and rear channels by - * the PCM Playback Volume, Sigmatel Surround Playback Volume and - * Surround Playback Volume. The Sigmatel 4-Speaker Stereo switch affects - * the front/rear channel mixing in the REAR OUT jack. When using the - * 4-Speaker Stereo, both front and rear channels will be mixed in the - * REAR OUT. - * The center/lfe channel has no volume control and cannot be muted during - * playback. - */ - -struct emu10k1x_voice { - struct emu10k1x *emu; - int number; - int use; - - struct emu10k1x_pcm *epcm; -}; - -struct emu10k1x_pcm { - struct emu10k1x *emu; - struct snd_pcm_substream *substream; - struct emu10k1x_voice *voice; - unsigned short running; -}; - -struct emu10k1x_midi { - struct emu10k1x *emu; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream_input; - struct snd_rawmidi_substream *substream_output; - unsigned int midi_mode; - spinlock_t input_lock; - spinlock_t output_lock; - spinlock_t open_lock; - int tx_enable, rx_enable; - int port; - int ipr_tx, ipr_rx; - void (*interrupt)(struct emu10k1x *emu, unsigned int status); -}; - -// definition of the chip-specific record -struct emu10k1x { - struct snd_card *card; - struct pci_dev *pci; - - unsigned long port; - struct resource *res_port; - int irq; - - unsigned char revision; /* chip revision */ - unsigned int serial; /* serial number */ - unsigned short model; /* subsystem id */ - - spinlock_t emu_lock; - spinlock_t voice_lock; - - struct snd_ac97 *ac97; - struct snd_pcm *pcm; - - struct emu10k1x_voice voices[3]; - struct emu10k1x_voice capture_voice; - u32 spdif_bits[3]; // SPDIF out setup - - struct snd_dma_buffer dma_buffer; - - struct emu10k1x_midi midi; -}; - -/* hardware definition */ -static struct snd_pcm_hardware snd_emu10k1x_playback_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 64, - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = 8, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_emu10k1x_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 64, - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static unsigned int snd_emu10k1x_ptr_read(struct emu10k1x * emu, - unsigned int reg, - unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -static void snd_emu10k1x_ptr_write(struct emu10k1x *emu, - unsigned int reg, - unsigned int chn, - unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_emu10k1x_intr_enable(struct emu10k1x *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int intr_enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - intr_enable = inl(emu->port + INTE) | intrenb; - outl(intr_enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_emu10k1x_intr_disable(struct emu10k1x *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int intr_enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - intr_enable = inl(emu->port + INTE) & ~intrenb; - outl(intr_enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_emu10k1x_gpio_write(struct emu10k1x *emu, unsigned int value) -{ - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(value, emu->port + GPIO); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_emu10k1x_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static void snd_emu10k1x_pcm_interrupt(struct emu10k1x *emu, struct emu10k1x_voice *voice) -{ - struct emu10k1x_pcm *epcm; - - if ((epcm = voice->epcm) == NULL) - return; - if (epcm->substream == NULL) - return; -#if 0 - snd_printk(KERN_INFO "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", - epcm->substream->ops->pointer(epcm->substream), - snd_pcm_lib_period_bytes(epcm->substream), - snd_pcm_lib_buffer_bytes(epcm->substream)); -#endif - snd_pcm_period_elapsed(epcm->substream); -} - -/* open callback */ -static int snd_emu10k1x_playback_open(struct snd_pcm_substream *substream) -{ - struct emu10k1x *chip = snd_pcm_substream_chip(substream); - struct emu10k1x_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) { - return err; - } - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) - return err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = chip; - epcm->substream = substream; - - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1x_pcm_free_substream; - - runtime->hw = snd_emu10k1x_playback_hw; - - return 0; -} - -/* close callback */ -static int snd_emu10k1x_playback_close(struct snd_pcm_substream *substream) -{ - return 0; -} - -/* hw_params callback */ -static int snd_emu10k1x_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - - if (! epcm->voice) { - epcm->voice = &epcm->emu->voices[substream->pcm->device]; - epcm->voice->use = 1; - epcm->voice->epcm = epcm; - } - - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_emu10k1x_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm; - - if (runtime->private_data == NULL) - return 0; - - epcm = runtime->private_data; - - if (epcm->voice) { - epcm->voice->use = 0; - epcm->voice->epcm = NULL; - epcm->voice = NULL; - } - - return snd_pcm_lib_free_pages(substream); -} - -/* prepare callback */ -static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - int voice = epcm->voice->number; - u32 *table_base = (u32 *)(emu->dma_buffer.area+1024*voice); - u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); - int i; - - for(i = 0; i < runtime->periods; i++) { - *table_base++=runtime->dma_addr+(i*period_size_bytes); - *table_base++=period_size_bytes<<16; - } - - snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer.addr+1024*voice); - snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_SIZE, voice, (runtime->periods - 1) << 19); - snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_PTR, voice, 0); - snd_emu10k1x_ptr_write(emu, PLAYBACK_POINTER, voice, 0); - snd_emu10k1x_ptr_write(emu, PLAYBACK_UNKNOWN1, voice, 0); - snd_emu10k1x_ptr_write(emu, PLAYBACK_UNKNOWN2, voice, 0); - snd_emu10k1x_ptr_write(emu, PLAYBACK_DMA_ADDR, voice, runtime->dma_addr); - - snd_emu10k1x_ptr_write(emu, PLAYBACK_PERIOD_SIZE, voice, frames_to_bytes(runtime, runtime->period_size)<<16); - - return 0; -} - -/* trigger callback */ -static int snd_emu10k1x_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - int channel = epcm->voice->number; - int result = 0; - -// snd_printk(KERN_INFO "trigger - emu10k1x = 0x%x, cmd = %i, pointer = %d\n", (int)emu, cmd, (int)substream->ops->pointer(substream)); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if(runtime->periods == 2) - snd_emu10k1x_intr_enable(emu, (INTE_CH_0_LOOP | INTE_CH_0_HALF_LOOP) << channel); - else - snd_emu10k1x_intr_enable(emu, INTE_CH_0_LOOP << channel); - epcm->running = 1; - snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0)|(TRIGGER_CHANNEL_0<running = 0; - snd_emu10k1x_intr_disable(emu, (INTE_CH_0_LOOP | INTE_CH_0_HALF_LOOP) << channel); - snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0) & ~(TRIGGER_CHANNEL_0<runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - int channel = epcm->voice->number; - snd_pcm_uframes_t ptr = 0, ptr1 = 0, ptr2= 0,ptr3 = 0,ptr4 = 0; - - if (!epcm->running) - return 0; - - ptr3 = snd_emu10k1x_ptr_read(emu, PLAYBACK_LIST_PTR, channel); - ptr1 = snd_emu10k1x_ptr_read(emu, PLAYBACK_POINTER, channel); - ptr4 = snd_emu10k1x_ptr_read(emu, PLAYBACK_LIST_PTR, channel); - - if(ptr4 == 0 && ptr1 == frames_to_bytes(runtime, runtime->buffer_size)) - return 0; - - if (ptr3 != ptr4) - ptr1 = snd_emu10k1x_ptr_read(emu, PLAYBACK_POINTER, channel); - ptr2 = bytes_to_frames(runtime, ptr1); - ptr2 += (ptr4 >> 3) * runtime->period_size; - ptr = ptr2; - - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - - return ptr; -} - -/* operators */ -static struct snd_pcm_ops snd_emu10k1x_playback_ops = { - .open = snd_emu10k1x_playback_open, - .close = snd_emu10k1x_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1x_pcm_hw_params, - .hw_free = snd_emu10k1x_pcm_hw_free, - .prepare = snd_emu10k1x_pcm_prepare, - .trigger = snd_emu10k1x_pcm_trigger, - .pointer = snd_emu10k1x_pcm_pointer, -}; - -/* open_capture callback */ -static int snd_emu10k1x_pcm_open_capture(struct snd_pcm_substream *substream) -{ - struct emu10k1x *chip = snd_pcm_substream_chip(substream); - struct emu10k1x_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) - return err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - - epcm->emu = chip; - epcm->substream = substream; - - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1x_pcm_free_substream; - - runtime->hw = snd_emu10k1x_capture_hw; - - return 0; -} - -/* close callback */ -static int snd_emu10k1x_pcm_close_capture(struct snd_pcm_substream *substream) -{ - return 0; -} - -/* hw_params callback */ -static int snd_emu10k1x_pcm_hw_params_capture(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - - if (! epcm->voice) { - if (epcm->emu->capture_voice.use) - return -EBUSY; - epcm->voice = &epcm->emu->capture_voice; - epcm->voice->epcm = epcm; - epcm->voice->use = 1; - } - - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_emu10k1x_pcm_hw_free_capture(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - struct emu10k1x_pcm *epcm; - - if (runtime->private_data == NULL) - return 0; - epcm = runtime->private_data; - - if (epcm->voice) { - epcm->voice->use = 0; - epcm->voice->epcm = NULL; - epcm->voice = NULL; - } - - return snd_pcm_lib_free_pages(substream); -} - -/* prepare capture callback */ -static int snd_emu10k1x_pcm_prepare_capture(struct snd_pcm_substream *substream) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_emu10k1x_ptr_write(emu, CAPTURE_DMA_ADDR, 0, runtime->dma_addr); - snd_emu10k1x_ptr_write(emu, CAPTURE_BUFFER_SIZE, 0, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes - snd_emu10k1x_ptr_write(emu, CAPTURE_POINTER, 0, 0); - snd_emu10k1x_ptr_write(emu, CAPTURE_UNKNOWN, 0, 0); - - return 0; -} - -/* trigger_capture callback */ -static int snd_emu10k1x_pcm_trigger_capture(struct snd_pcm_substream *substream, - int cmd) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - int result = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_emu10k1x_intr_enable(emu, INTE_CAP_0_LOOP | - INTE_CAP_0_HALF_LOOP); - snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0)|TRIGGER_CAPTURE); - epcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - epcm->running = 0; - snd_emu10k1x_intr_disable(emu, INTE_CAP_0_LOOP | - INTE_CAP_0_HALF_LOOP); - snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0) & ~(TRIGGER_CAPTURE)); - break; - default: - result = -EINVAL; - break; - } - return result; -} - -/* pointer_capture callback */ -static snd_pcm_uframes_t -snd_emu10k1x_pcm_pointer_capture(struct snd_pcm_substream *substream) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - snd_pcm_uframes_t ptr; - - if (!epcm->running) - return 0; - - ptr = bytes_to_frames(runtime, snd_emu10k1x_ptr_read(emu, CAPTURE_POINTER, 0)); - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - - return ptr; -} - -static struct snd_pcm_ops snd_emu10k1x_capture_ops = { - .open = snd_emu10k1x_pcm_open_capture, - .close = snd_emu10k1x_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1x_pcm_hw_params_capture, - .hw_free = snd_emu10k1x_pcm_hw_free_capture, - .prepare = snd_emu10k1x_pcm_prepare_capture, - .trigger = snd_emu10k1x_pcm_trigger_capture, - .pointer = snd_emu10k1x_pcm_pointer_capture, -}; - -static unsigned short snd_emu10k1x_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct emu10k1x *emu = ac97->private_data; - unsigned long flags; - unsigned short val; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - val = inw(emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -static void snd_emu10k1x_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - struct emu10k1x *emu = ac97->private_data; - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - outw(val, emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static int snd_emu10k1x_ac97(struct emu10k1x *chip) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_emu10k1x_ac97_write, - .read = snd_emu10k1x_ac97_read, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) - return err; - pbus->no_vra = 1; /* we don't need VRA */ - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.scaps = AC97_SCAP_NO_SPDIF; - return snd_ac97_mixer(pbus, &ac97, &chip->ac97); -} - -static int snd_emu10k1x_free(struct emu10k1x *chip) -{ - snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0); - // disable interrupts - outl(0, chip->port + INTE); - // disable audio - outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); - - /* release the irq */ - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - // release the i/o port - release_and_free_resource(chip->res_port); - - // release the DMA - if (chip->dma_buffer.area) { - snd_dma_free_pages(&chip->dma_buffer); - } - - pci_disable_device(chip->pci); - - // release the data - kfree(chip); - return 0; -} - -static int snd_emu10k1x_dev_free(struct snd_device *device) -{ - struct emu10k1x *chip = device->device_data; - return snd_emu10k1x_free(chip); -} - -static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id) -{ - unsigned int status; - - struct emu10k1x *chip = dev_id; - struct emu10k1x_voice *pvoice = chip->voices; - int i; - int mask; - - status = inl(chip->port + IPR); - - if (! status) - return IRQ_NONE; - - // capture interrupt - if (status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) { - struct emu10k1x_voice *cap_voice = &chip->capture_voice; - if (cap_voice->use) - snd_emu10k1x_pcm_interrupt(chip, cap_voice); - else - snd_emu10k1x_intr_disable(chip, - INTE_CAP_0_LOOP | - INTE_CAP_0_HALF_LOOP); - } - - mask = IPR_CH_0_LOOP|IPR_CH_0_HALF_LOOP; - for (i = 0; i < 3; i++) { - if (status & mask) { - if (pvoice->use) - snd_emu10k1x_pcm_interrupt(chip, pvoice); - else - snd_emu10k1x_intr_disable(chip, mask); - } - pvoice++; - mask <<= 1; - } - - if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) { - if (chip->midi.interrupt) - chip->midi.interrupt(chip, status); - else - snd_emu10k1x_intr_disable(chip, INTE_MIDITXENABLE|INTE_MIDIRXENABLE); - } - - // acknowledge the interrupt if necessary - outl(status, chip->port + IPR); - - // snd_printk(KERN_INFO "interrupt %08x\n", status); - return IRQ_HANDLED; -} - -static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - int capture = 0; - - if (rpcm) - *rpcm = NULL; - if (device == 0) - capture = 1; - - if ((err = snd_pcm_new(emu->card, "emu10k1x", device, 1, capture, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - switch(device) { - case 0: - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1x_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1x_capture_ops); - break; - case 1: - case 2: - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1x_playback_ops); - break; - } - - pcm->info_flags = 0; - switch(device) { - case 0: - strcpy(pcm->name, "EMU10K1X Front"); - break; - case 1: - strcpy(pcm->name, "EMU10K1X Rear"); - break; - case 2: - strcpy(pcm->name, "EMU10K1X Center/LFE"); - break; - } - emu->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - 32*1024, 32*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -static int __devinit snd_emu10k1x_create(struct snd_card *card, - struct pci_dev *pci, - struct emu10k1x **rchip) -{ - struct emu10k1x *chip; - int err; - int ch; - static struct snd_device_ops ops = { - .dev_free = snd_emu10k1x_dev_free, - }; - - *rchip = NULL; - - if ((err = pci_enable_device(pci)) < 0) - return err; - if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "error to set 28bit mask DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - spin_lock_init(&chip->emu_lock); - spin_lock_init(&chip->voice_lock); - - chip->port = pci_resource_start(pci, 0); - if ((chip->res_port = request_region(chip->port, 8, - "EMU10K1X")) == NULL) { - snd_printk(KERN_ERR "emu10k1x: cannot allocate the port 0x%lx\n", chip->port); - snd_emu10k1x_free(chip); - return -EBUSY; - } - - if (request_irq(pci->irq, snd_emu10k1x_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq); - snd_emu10k1x_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - - if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - 4 * 1024, &chip->dma_buffer) < 0) { - snd_emu10k1x_free(chip); - return -ENOMEM; - } - - pci_set_master(pci); - /* read revision & serial */ - chip->revision = pci->revision; - pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); - snd_printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model, - chip->revision, chip->serial); - - outl(0, chip->port + INTE); - - for(ch = 0; ch < 3; ch++) { - chip->voices[ch].emu = chip; - chip->voices[ch].number = ch; - } - - /* - * Init to 0x02109204 : - * Clock accuracy = 0 (1000ppm) - * Sample Rate = 2 (48kHz) - * Audio Channel = 1 (Left of 2) - * Source Number = 0 (Unspecified) - * Generation Status = 1 (Original for Cat Code 12) - * Cat Code = 12 (Digital Signal Mixer) - * Mode = 0 (Mode 0) - * Emphasis = 0 (None) - * CP = 1 (Copyright unasserted) - * AN = 0 (Audio data) - * P = 0 (Consumer) - */ - snd_emu10k1x_ptr_write(chip, SPCS0, 0, - chip->spdif_bits[0] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - snd_emu10k1x_ptr_write(chip, SPCS1, 0, - chip->spdif_bits[1] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - snd_emu10k1x_ptr_write(chip, SPCS2, 0, - chip->spdif_bits[2] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - - snd_emu10k1x_ptr_write(chip, SPDIF_SELECT, 0, 0x700); // disable SPDIF - snd_emu10k1x_ptr_write(chip, ROUTING, 0, 0x1003F); // routing - snd_emu10k1x_gpio_write(chip, 0x1080); // analog mode - - outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - chip, &ops)) < 0) { - snd_emu10k1x_free(chip); - return err; - } - *rchip = chip; - return 0; -} - -static void snd_emu10k1x_proc_reg_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct emu10k1x *emu = entry->private_data; - unsigned long value,value1,value2; - unsigned long flags; - int i; - - snd_iprintf(buffer, "Registers:\n\n"); - for(i = 0; i < 0x20; i+=4) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inl(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "Register %02X: %08lX\n", i, value); - } - snd_iprintf(buffer, "\nRegisters\n\n"); - for(i = 0; i <= 0x48; i++) { - value = snd_emu10k1x_ptr_read(emu, i, 0); - if(i < 0x10 || (i >= 0x20 && i < 0x40)) { - value1 = snd_emu10k1x_ptr_read(emu, i, 1); - value2 = snd_emu10k1x_ptr_read(emu, i, 2); - snd_iprintf(buffer, "%02X: %08lX %08lX %08lX\n", i, value, value1, value2); - } else { - snd_iprintf(buffer, "%02X: %08lX\n", i, value); - } - } -} - -static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct emu10k1x *emu = entry->private_data; - char line[64]; - unsigned int reg, channel_id , val; - - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x %x", ®, &channel_id, &val) != 3) - continue; - - if (reg < 0x49 && val <= 0xffffffff && channel_id <= 2) - snd_emu10k1x_ptr_write(emu, reg, channel_id, val); - } -} - -static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu) -{ - struct snd_info_entry *entry; - - if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu10k1x_proc_reg_read); - entry->c.text.write = snd_emu10k1x_proc_reg_write; - entry->mode |= S_IWUSR; - entry->private_data = emu; - } - - return 0; -} - -#define snd_emu10k1x_shared_spdif_info snd_ctl_boolean_mono_info - -static int snd_emu10k1x_shared_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct emu10k1x *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = (snd_emu10k1x_ptr_read(emu, SPDIF_SELECT, 0) == 0x700) ? 0 : 1; - - return 0; -} - -static int snd_emu10k1x_shared_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct emu10k1x *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.integer.value[0] ; - - if (val) { - // enable spdif output - snd_emu10k1x_ptr_write(emu, SPDIF_SELECT, 0, 0x000); - snd_emu10k1x_ptr_write(emu, ROUTING, 0, 0x700); - snd_emu10k1x_gpio_write(emu, 0x1000); - } else { - // disable spdif output - snd_emu10k1x_ptr_write(emu, SPDIF_SELECT, 0, 0x700); - snd_emu10k1x_ptr_write(emu, ROUTING, 0, 0x1003F); - snd_emu10k1x_gpio_write(emu, 0x1080); - } - return change; -} - -static struct snd_kcontrol_new snd_emu10k1x_shared_spdif __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog/Digital Output Jack", - .info = snd_emu10k1x_shared_spdif_info, - .get = snd_emu10k1x_shared_spdif_get, - .put = snd_emu10k1x_shared_spdif_put -}; - -static int snd_emu10k1x_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_emu10k1x_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct emu10k1x *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; - return 0; -} - -static int snd_emu10k1x_spdif_get_mask(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static int snd_emu10k1x_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct emu10k1x *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - int change; - unsigned int val; - - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - change = val != emu->spdif_bits[idx]; - if (change) { - snd_emu10k1x_ptr_write(emu, SPCS0 + idx, 0, val); - emu->spdif_bits[idx] = val; - } - return change; -} - -static struct snd_kcontrol_new snd_emu10k1x_spdif_mask_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .count = 3, - .info = snd_emu10k1x_spdif_info, - .get = snd_emu10k1x_spdif_get_mask -}; - -static struct snd_kcontrol_new snd_emu10k1x_spdif_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .count = 3, - .info = snd_emu10k1x_spdif_info, - .get = snd_emu10k1x_spdif_get, - .put = snd_emu10k1x_spdif_put -}; - -static int __devinit snd_emu10k1x_mixer(struct emu10k1x *emu) -{ - int err; - struct snd_kcontrol *kctl; - struct snd_card *card = emu->card; - - if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_mask_control, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1x_shared_spdif, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_control, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - - return 0; -} - -#define EMU10K1X_MIDI_MODE_INPUT (1<<0) -#define EMU10K1X_MIDI_MODE_OUTPUT (1<<1) - -static inline unsigned char mpu401_read(struct emu10k1x *emu, struct emu10k1x_midi *mpu, int idx) -{ - return (unsigned char)snd_emu10k1x_ptr_read(emu, mpu->port + idx, 0); -} - -static inline void mpu401_write(struct emu10k1x *emu, struct emu10k1x_midi *mpu, int data, int idx) -{ - snd_emu10k1x_ptr_write(emu, mpu->port + idx, 0, data); -} - -#define mpu401_write_data(emu, mpu, data) mpu401_write(emu, mpu, data, 0) -#define mpu401_write_cmd(emu, mpu, data) mpu401_write(emu, mpu, data, 1) -#define mpu401_read_data(emu, mpu) mpu401_read(emu, mpu, 0) -#define mpu401_read_stat(emu, mpu) mpu401_read(emu, mpu, 1) - -#define mpu401_input_avail(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x80)) -#define mpu401_output_ready(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x40)) - -#define MPU401_RESET 0xff -#define MPU401_ENTER_UART 0x3f -#define MPU401_ACK 0xfe - -static void mpu401_clear_rx(struct emu10k1x *emu, struct emu10k1x_midi *mpu) -{ - int timeout = 100000; - for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--) - mpu401_read_data(emu, mpu); -#ifdef CONFIG_SND_DEBUG - if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", mpu401_read_stat(emu, mpu)); -#endif -} - -/* - - */ - -static void do_emu10k1x_midi_interrupt(struct emu10k1x *emu, - struct emu10k1x_midi *midi, unsigned int status) -{ - unsigned char byte; - - if (midi->rmidi == NULL) { - snd_emu10k1x_intr_disable(emu, midi->tx_enable | midi->rx_enable); - return; - } - - spin_lock(&midi->input_lock); - if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - mpu401_clear_rx(emu, midi); - } else { - byte = mpu401_read_data(emu, midi); - if (midi->substream_input) - snd_rawmidi_receive(midi->substream_input, &byte, 1); - } - } - spin_unlock(&midi->input_lock); - - spin_lock(&midi->output_lock); - if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { - if (midi->substream_output && - snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { - mpu401_write_data(emu, midi, byte); - } else { - snd_emu10k1x_intr_disable(emu, midi->tx_enable); - } - } - spin_unlock(&midi->output_lock); -} - -static void snd_emu10k1x_midi_interrupt(struct emu10k1x *emu, unsigned int status) -{ - do_emu10k1x_midi_interrupt(emu, &emu->midi, status); -} - -static int snd_emu10k1x_midi_cmd(struct emu10k1x * emu, - struct emu10k1x_midi *midi, unsigned char cmd, int ack) -{ - unsigned long flags; - int timeout, ok; - - spin_lock_irqsave(&midi->input_lock, flags); - mpu401_write_data(emu, midi, 0x00); - /* mpu401_clear_rx(emu, midi); */ - - mpu401_write_cmd(emu, midi, cmd); - if (ack) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (mpu401_input_avail(emu, midi)) { - if (mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; - } - } - if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; - } else { - ok = 1; - } - spin_unlock_irqrestore(&midi->input_lock, flags); - if (!ok) { - snd_printk(KERN_ERR "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", - cmd, emu->port, - mpu401_read_stat(emu, midi), - mpu401_read_data(emu, midi)); - return 1; - } - return 0; -} - -static int snd_emu10k1x_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1X_MIDI_MODE_INPUT; - midi->substream_input = substream; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; - -error_out: - return -EIO; -} - -static int snd_emu10k1x_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1X_MIDI_MODE_OUTPUT; - midi->substream_output = substream; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; - -error_out: - return -EIO; -} - -static int snd_emu10k1x_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - int err = 0; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1x_intr_disable(emu, midi->rx_enable); - midi->midi_mode &= ~EMU10K1X_MIDI_MODE_INPUT; - midi->substream_input = NULL; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return err; -} - -static int snd_emu10k1x_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - int err = 0; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1x_intr_disable(emu, midi->tx_enable); - midi->midi_mode &= ~EMU10K1X_MIDI_MODE_OUTPUT; - midi->substream_output = NULL; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return err; -} - -static void snd_emu10k1x_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return; - - if (up) - snd_emu10k1x_intr_enable(emu, midi->rx_enable); - else - snd_emu10k1x_intr_disable(emu, midi->rx_enable); -} - -static void snd_emu10k1x_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return; - - if (up) { - int max = 4; - unsigned char byte; - - /* try to send some amount of bytes here before interrupts */ - spin_lock_irqsave(&midi->output_lock, flags); - while (max > 0) { - if (mpu401_output_ready(emu, midi)) { - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT) || - snd_rawmidi_transmit(substream, &byte, 1) != 1) { - /* no more data */ - spin_unlock_irqrestore(&midi->output_lock, flags); - return; - } - mpu401_write_data(emu, midi, byte); - max--; - } else { - break; - } - } - spin_unlock_irqrestore(&midi->output_lock, flags); - snd_emu10k1x_intr_enable(emu, midi->tx_enable); - } else { - snd_emu10k1x_intr_disable(emu, midi->tx_enable); - } -} - -/* - - */ - -static struct snd_rawmidi_ops snd_emu10k1x_midi_output = -{ - .open = snd_emu10k1x_midi_output_open, - .close = snd_emu10k1x_midi_output_close, - .trigger = snd_emu10k1x_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_emu10k1x_midi_input = -{ - .open = snd_emu10k1x_midi_input_open, - .close = snd_emu10k1x_midi_input_close, - .trigger = snd_emu10k1x_midi_input_trigger, -}; - -static void snd_emu10k1x_midi_free(struct snd_rawmidi *rmidi) -{ - struct emu10k1x_midi *midi = rmidi->private_data; - midi->interrupt = NULL; - midi->rmidi = NULL; -} - -static int __devinit emu10k1x_midi_init(struct emu10k1x *emu, - struct emu10k1x_midi *midi, int device, char *name) -{ - struct snd_rawmidi *rmidi; - int err; - - if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0) - return err; - midi->emu = emu; - spin_lock_init(&midi->open_lock); - spin_lock_init(&midi->input_lock); - spin_lock_init(&midi->output_lock); - strcpy(rmidi->name, name); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1x_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1x_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = midi; - rmidi->private_free = snd_emu10k1x_midi_free; - midi->rmidi = rmidi; - return 0; -} - -static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu) -{ - struct emu10k1x_midi *midi = &emu->midi; - int err; - - if ((err = emu10k1x_midi_init(emu, midi, 0, "EMU10K1X MPU-401 (UART)")) < 0) - return err; - - midi->tx_enable = INTE_MIDITXENABLE; - midi->rx_enable = INTE_MIDIRXENABLE; - midi->port = MUDATA; - midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; - midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; - midi->interrupt = snd_emu10k1x_midi_interrupt; - return 0; -} - -static int __devinit snd_emu10k1x_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct emu10k1x *chip; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_emu10k1x_create(card, pci, &chip)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_emu10k1x_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_emu10k1x_pcm(chip, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_emu10k1x_pcm(chip, 2, NULL)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_emu10k1x_ac97(chip)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_emu10k1x_mixer(chip)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_emu10k1x_midi(chip)) < 0) { - snd_card_free(card); - return err; - } - - snd_emu10k1x_proc_init(chip); - - strcpy(card->driver, "EMU10K1X"); - strcpy(card->shortname, "Dell Sound Blaster Live!"); - sprintf(card->longname, "%s at 0x%lx irq %i", - card->shortname, chip->port, chip->irq); - - snd_card_set_dev(card, &pci->dev); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_emu10k1x_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -// PCI IDs -static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1x_ids) = { - { PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */ - { 0, } -}; -MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids); - -// pci_driver definition -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_emu10k1x_ids, - .probe = snd_emu10k1x_probe, - .remove = __devexit_p(snd_emu10k1x_remove), -}; - -// initialization of the module -static int __init alsa_card_emu10k1x_init(void) -{ - return pci_register_driver(&driver); -} - -// clean up the module -static void __exit alsa_card_emu10k1x_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_emu10k1x_init) -module_exit(alsa_card_emu10k1x_exit) diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emufx.c b/ANDROID_3.4.5/sound/pci/emu10k1/emufx.c deleted file mode 100644 index dae4050e..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emufx.c +++ /dev/null @@ -1,2758 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Creative Labs, Inc. - * Routines for effect processor FX8010 - * - * Copyright (c) by James Courtier-Dutton - * Added EMU 1010 support. - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 -#include -#include - -#if 0 /* for testing purposes - digital out -> capture */ -#define EMU10K1_CAPTURE_DIGITAL_OUT -#endif -#if 0 /* for testing purposes - set S/PDIF to AC3 output */ -#define EMU10K1_SET_AC3_IEC958 -#endif -#if 0 /* for testing purposes - feed the front signal to Center/LFE outputs */ -#define EMU10K1_CENTER_LFE_FROM_FRONT -#endif - -static bool high_res_gpr_volume; -module_param(high_res_gpr_volume, bool, 0444); -MODULE_PARM_DESC(high_res_gpr_volume, "GPR mixer controls use 31-bit range."); - -/* - * Tables - */ - -static char *fxbuses[16] = { - /* 0x00 */ "PCM Left", - /* 0x01 */ "PCM Right", - /* 0x02 */ "PCM Surround Left", - /* 0x03 */ "PCM Surround Right", - /* 0x04 */ "MIDI Left", - /* 0x05 */ "MIDI Right", - /* 0x06 */ "Center", - /* 0x07 */ "LFE", - /* 0x08 */ NULL, - /* 0x09 */ NULL, - /* 0x0a */ NULL, - /* 0x0b */ NULL, - /* 0x0c */ "MIDI Reverb", - /* 0x0d */ "MIDI Chorus", - /* 0x0e */ NULL, - /* 0x0f */ NULL -}; - -static char *creative_ins[16] = { - /* 0x00 */ "AC97 Left", - /* 0x01 */ "AC97 Right", - /* 0x02 */ "TTL IEC958 Left", - /* 0x03 */ "TTL IEC958 Right", - /* 0x04 */ "Zoom Video Left", - /* 0x05 */ "Zoom Video Right", - /* 0x06 */ "Optical IEC958 Left", - /* 0x07 */ "Optical IEC958 Right", - /* 0x08 */ "Line/Mic 1 Left", - /* 0x09 */ "Line/Mic 1 Right", - /* 0x0a */ "Coaxial IEC958 Left", - /* 0x0b */ "Coaxial IEC958 Right", - /* 0x0c */ "Line/Mic 2 Left", - /* 0x0d */ "Line/Mic 2 Right", - /* 0x0e */ NULL, - /* 0x0f */ NULL -}; - -static char *audigy_ins[16] = { - /* 0x00 */ "AC97 Left", - /* 0x01 */ "AC97 Right", - /* 0x02 */ "Audigy CD Left", - /* 0x03 */ "Audigy CD Right", - /* 0x04 */ "Optical IEC958 Left", - /* 0x05 */ "Optical IEC958 Right", - /* 0x06 */ NULL, - /* 0x07 */ NULL, - /* 0x08 */ "Line/Mic 2 Left", - /* 0x09 */ "Line/Mic 2 Right", - /* 0x0a */ "SPDIF Left", - /* 0x0b */ "SPDIF Right", - /* 0x0c */ "Aux2 Left", - /* 0x0d */ "Aux2 Right", - /* 0x0e */ NULL, - /* 0x0f */ NULL -}; - -static char *creative_outs[32] = { - /* 0x00 */ "AC97 Left", - /* 0x01 */ "AC97 Right", - /* 0x02 */ "Optical IEC958 Left", - /* 0x03 */ "Optical IEC958 Right", - /* 0x04 */ "Center", - /* 0x05 */ "LFE", - /* 0x06 */ "Headphone Left", - /* 0x07 */ "Headphone Right", - /* 0x08 */ "Surround Left", - /* 0x09 */ "Surround Right", - /* 0x0a */ "PCM Capture Left", - /* 0x0b */ "PCM Capture Right", - /* 0x0c */ "MIC Capture", - /* 0x0d */ "AC97 Surround Left", - /* 0x0e */ "AC97 Surround Right", - /* 0x0f */ NULL, - /* 0x10 */ NULL, - /* 0x11 */ "Analog Center", - /* 0x12 */ "Analog LFE", - /* 0x13 */ NULL, - /* 0x14 */ NULL, - /* 0x15 */ NULL, - /* 0x16 */ NULL, - /* 0x17 */ NULL, - /* 0x18 */ NULL, - /* 0x19 */ NULL, - /* 0x1a */ NULL, - /* 0x1b */ NULL, - /* 0x1c */ NULL, - /* 0x1d */ NULL, - /* 0x1e */ NULL, - /* 0x1f */ NULL, -}; - -static char *audigy_outs[32] = { - /* 0x00 */ "Digital Front Left", - /* 0x01 */ "Digital Front Right", - /* 0x02 */ "Digital Center", - /* 0x03 */ "Digital LEF", - /* 0x04 */ "Headphone Left", - /* 0x05 */ "Headphone Right", - /* 0x06 */ "Digital Rear Left", - /* 0x07 */ "Digital Rear Right", - /* 0x08 */ "Front Left", - /* 0x09 */ "Front Right", - /* 0x0a */ "Center", - /* 0x0b */ "LFE", - /* 0x0c */ NULL, - /* 0x0d */ NULL, - /* 0x0e */ "Rear Left", - /* 0x0f */ "Rear Right", - /* 0x10 */ "AC97 Front Left", - /* 0x11 */ "AC97 Front Right", - /* 0x12 */ "ADC Caputre Left", - /* 0x13 */ "ADC Capture Right", - /* 0x14 */ NULL, - /* 0x15 */ NULL, - /* 0x16 */ NULL, - /* 0x17 */ NULL, - /* 0x18 */ NULL, - /* 0x19 */ NULL, - /* 0x1a */ NULL, - /* 0x1b */ NULL, - /* 0x1c */ NULL, - /* 0x1d */ NULL, - /* 0x1e */ NULL, - /* 0x1f */ NULL, -}; - -static const u32 bass_table[41][5] = { - { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 }, - { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d }, - { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee }, - { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c }, - { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b }, - { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 }, - { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f }, - { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 }, - { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 }, - { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 }, - { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 }, - { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be }, - { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b }, - { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c }, - { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b }, - { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 }, - { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a }, - { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 }, - { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 }, - { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e }, - { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee }, - { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 }, - { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 }, - { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 }, - { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 }, - { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e }, - { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 }, - { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 }, - { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 }, - { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 }, - { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 }, - { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca }, - { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 }, - { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 }, - { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 }, - { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 }, - { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a }, - { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f }, - { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 }, - { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 }, - { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 } -}; - -static const u32 treble_table[41][5] = { - { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 }, - { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 }, - { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 }, - { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca }, - { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 }, - { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 }, - { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 }, - { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 }, - { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 }, - { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df }, - { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff }, - { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 }, - { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c }, - { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 }, - { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 }, - { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 }, - { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 }, - { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d }, - { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 }, - { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 }, - { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f }, - { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb }, - { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 }, - { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 }, - { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd }, - { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 }, - { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad }, - { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 }, - { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 }, - { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c }, - { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 }, - { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 }, - { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 }, - { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 }, - { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 }, - { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 }, - { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d }, - { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b }, - { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 }, - { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd }, - { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 } -}; - -/* dB gain = (float) 20 * log10( float(db_table_value) / 0x8000000 ) */ -static const u32 db_table[101] = { - 0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540, - 0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8, - 0x0207567a, 0x021fd03d, 0x0239714c, 0x02544792, 0x027061a1, - 0x028dcebb, 0x02ac9edc, 0x02cce2bf, 0x02eeabe8, 0x03120cb0, - 0x0337184e, 0x035de2df, 0x03868173, 0x03b10a18, 0x03dd93e9, - 0x040c3713, 0x043d0cea, 0x04702ff3, 0x04a5bbf2, 0x04ddcdfb, - 0x0518847f, 0x0555ff62, 0x05966005, 0x05d9c95d, 0x06206005, - 0x066a4a52, 0x06b7b067, 0x0708bc4c, 0x075d9a01, 0x07b6779d, - 0x08138561, 0x0874f5d5, 0x08dafde1, 0x0945d4ed, 0x09b5b4fd, - 0x0a2adad1, 0x0aa58605, 0x0b25f936, 0x0bac7a24, 0x0c3951d8, - 0x0ccccccc, 0x0d673b17, 0x0e08f093, 0x0eb24510, 0x0f639481, - 0x101d3f2d, 0x10dfa9e6, 0x11ab3e3f, 0x12806ac3, 0x135fa333, - 0x144960c5, 0x153e2266, 0x163e6cfe, 0x174acbb7, 0x1863d04d, - 0x198a1357, 0x1abe349f, 0x1c00db77, 0x1d52b712, 0x1eb47ee6, - 0x2026f30f, 0x21aadcb6, 0x23410e7e, 0x24ea64f9, 0x26a7c71d, - 0x287a26c4, 0x2a62812c, 0x2c61df84, 0x2e795779, 0x30aa0bcf, - 0x32f52cfe, 0x355bf9d8, 0x37dfc033, 0x3a81dda4, 0x3d43c038, - 0x4026e73c, 0x432ce40f, 0x46575af8, 0x49a8040f, 0x4d20ac2a, - 0x50c335d3, 0x54919a57, 0x588dead1, 0x5cba514a, 0x611911ea, - 0x65ac8c2f, 0x6a773c39, 0x6f7bbc23, 0x74bcc56c, 0x7a3d3272, - 0x7fffffff, -}; - -/* EMU10k1/EMU10k2 DSP control db gain */ -static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); -static const DECLARE_TLV_DB_LINEAR(snd_emu10k1_db_linear, TLV_DB_GAIN_MUTE, 0); - -/* EMU10K1 bass/treble db gain */ -static const DECLARE_TLV_DB_SCALE(snd_emu10k1_bass_treble_db_scale, -1200, 60, 0); - -static const u32 onoff_table[2] = { - 0x00000000, 0x00000001 -}; - -/* - */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* - * controls - */ - -static int snd_emu10k1_gpr_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1_fx8010_ctl *ctl = - (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value; - - if (ctl->min == 0 && ctl->max == 1) - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - else - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = ctl->vcount; - uinfo->value.integer.min = ctl->min; - uinfo->value.integer.max = ctl->max; - return 0; -} - -static int snd_emu10k1_gpr_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_fx8010_ctl *ctl = - (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value; - unsigned long flags; - unsigned int i; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (i = 0; i < ctl->vcount; i++) - ucontrol->value.integer.value[i] = ctl->value[i]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_gpr_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_fx8010_ctl *ctl = - (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value; - unsigned long flags; - unsigned int nval, val; - unsigned int i, j; - int change = 0; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (i = 0; i < ctl->vcount; i++) { - nval = ucontrol->value.integer.value[i]; - if (nval < ctl->min) - nval = ctl->min; - if (nval > ctl->max) - nval = ctl->max; - if (nval != ctl->value[i]) - change = 1; - val = ctl->value[i] = nval; - switch (ctl->translation) { - case EMU10K1_GPR_TRANSLATION_NONE: - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, val); - break; - case EMU10K1_GPR_TRANSLATION_TABLE100: - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]); - break; - case EMU10K1_GPR_TRANSLATION_BASS: - if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { - change = -EIO; - goto __error; - } - for (j = 0; j < 5; j++) - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]); - break; - case EMU10K1_GPR_TRANSLATION_TREBLE: - if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { - change = -EIO; - goto __error; - } - for (j = 0; j < 5; j++) - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]); - break; - case EMU10K1_GPR_TRANSLATION_ONOFF: - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, onoff_table[val]); - break; - } - } - __error: - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -/* - * Interrupt handler - */ - -static void snd_emu10k1_fx8010_interrupt(struct snd_emu10k1 *emu) -{ - struct snd_emu10k1_fx8010_irq *irq, *nirq; - - irq = emu->fx8010.irq_handlers; - while (irq) { - nirq = irq->next; /* irq ptr can be removed from list */ - if (snd_emu10k1_ptr_read(emu, emu->gpr_base + irq->gpr_running, 0) & 0xffff0000) { - if (irq->handler) - irq->handler(emu, irq->private_data); - snd_emu10k1_ptr_write(emu, emu->gpr_base + irq->gpr_running, 0, 1); - } - irq = nirq; - } -} - -int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu, - snd_fx8010_irq_handler_t *handler, - unsigned char gpr_running, - void *private_data, - struct snd_emu10k1_fx8010_irq **r_irq) -{ - struct snd_emu10k1_fx8010_irq *irq; - unsigned long flags; - - irq = kmalloc(sizeof(*irq), GFP_ATOMIC); - if (irq == NULL) - return -ENOMEM; - irq->handler = handler; - irq->gpr_running = gpr_running; - irq->private_data = private_data; - irq->next = NULL; - spin_lock_irqsave(&emu->fx8010.irq_lock, flags); - if (emu->fx8010.irq_handlers == NULL) { - emu->fx8010.irq_handlers = irq; - emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt; - snd_emu10k1_intr_enable(emu, INTE_FXDSPENABLE); - } else { - irq->next = emu->fx8010.irq_handlers; - emu->fx8010.irq_handlers = irq; - } - spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags); - if (r_irq) - *r_irq = irq; - return 0; -} - -int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_irq *irq) -{ - struct snd_emu10k1_fx8010_irq *tmp; - unsigned long flags; - - spin_lock_irqsave(&emu->fx8010.irq_lock, flags); - if ((tmp = emu->fx8010.irq_handlers) == irq) { - emu->fx8010.irq_handlers = tmp->next; - if (emu->fx8010.irq_handlers == NULL) { - snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); - emu->dsp_interrupt = NULL; - } - } else { - while (tmp && tmp->next != irq) - tmp = tmp->next; - if (tmp) - tmp->next = tmp->next->next; - } - spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags); - kfree(irq); - return 0; -} - -/************************************************************************* - * EMU10K1 effect manager - *************************************************************************/ - -static void snd_emu10k1_write_op(struct snd_emu10k1_fx8010_code *icode, - unsigned int *ptr, - u32 op, u32 r, u32 a, u32 x, u32 y) -{ - u_int32_t *code; - if (snd_BUG_ON(*ptr >= 512)) - return; - code = (u_int32_t __force *)icode->code + (*ptr) * 2; - set_bit(*ptr, icode->code_valid); - code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff); - code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff); - (*ptr)++; -} - -#define OP(icode, ptr, op, r, a, x, y) \ - snd_emu10k1_write_op(icode, ptr, op, r, a, x, y) - -static void snd_emu10k1_audigy_write_op(struct snd_emu10k1_fx8010_code *icode, - unsigned int *ptr, - u32 op, u32 r, u32 a, u32 x, u32 y) -{ - u_int32_t *code; - if (snd_BUG_ON(*ptr >= 1024)) - return; - code = (u_int32_t __force *)icode->code + (*ptr) * 2; - set_bit(*ptr, icode->code_valid); - code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff); - code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff); - (*ptr)++; -} - -#define A_OP(icode, ptr, op, r, a, x, y) \ - snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y) - -static void snd_emu10k1_efx_write(struct snd_emu10k1 *emu, unsigned int pc, unsigned int data) -{ - pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE; - snd_emu10k1_ptr_write(emu, pc, 0, data); -} - -unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc) -{ - pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE; - return snd_emu10k1_ptr_read(emu, pc, 0); -} - -static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int gpr; - u32 val; - - for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { - if (!test_bit(gpr, icode->gpr_valid)) - continue; - if (get_user(val, &icode->gpr_map[gpr])) - return -EFAULT; - snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val); - } - return 0; -} - -static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int gpr; - u32 val; - - for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { - set_bit(gpr, icode->gpr_valid); - val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0); - if (put_user(val, &icode->gpr_map[gpr])) - return -EFAULT; - } - return 0; -} - -static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int tram; - u32 addr, val; - - for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { - if (!test_bit(tram, icode->tram_valid)) - continue; - if (get_user(val, &icode->tram_data_map[tram]) || - get_user(addr, &icode->tram_addr_map[tram])) - return -EFAULT; - snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val); - if (!emu->audigy) { - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr); - } else { - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr << 12); - snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, addr >> 20); - } - } - return 0; -} - -static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int tram; - u32 val, addr; - - memset(icode->tram_valid, 0, sizeof(icode->tram_valid)); - for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { - set_bit(tram, icode->tram_valid); - val = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0); - if (!emu->audigy) { - addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0); - } else { - addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12; - addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20; - } - if (put_user(val, &icode->tram_data_map[tram]) || - put_user(addr, &icode->tram_addr_map[tram])) - return -EFAULT; - } - return 0; -} - -static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - u32 pc, lo, hi; - - for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { - if (!test_bit(pc / 2, icode->code_valid)) - continue; - if (get_user(lo, &icode->code[pc + 0]) || - get_user(hi, &icode->code[pc + 1])) - return -EFAULT; - snd_emu10k1_efx_write(emu, pc + 0, lo); - snd_emu10k1_efx_write(emu, pc + 1, hi); - } - return 0; -} - -static int snd_emu10k1_code_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - u32 pc; - - memset(icode->code_valid, 0, sizeof(icode->code_valid)); - for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { - set_bit(pc / 2, icode->code_valid); - if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0])) - return -EFAULT; - if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1])) - return -EFAULT; - } - return 0; -} - -static struct snd_emu10k1_fx8010_ctl * -snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id) -{ - struct snd_emu10k1_fx8010_ctl *ctl; - struct snd_kcontrol *kcontrol; - - list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { - kcontrol = ctl->kcontrol; - if (kcontrol->id.iface == id->iface && - !strcmp(kcontrol->id.name, id->name) && - kcontrol->id.index == id->index) - return ctl; - } - return NULL; -} - -#define MAX_TLV_SIZE 256 - -static unsigned int *copy_tlv(const unsigned int __user *_tlv) -{ - unsigned int data[2]; - unsigned int *tlv; - - if (!_tlv) - return NULL; - if (copy_from_user(data, _tlv, sizeof(data))) - return NULL; - if (data[1] >= MAX_TLV_SIZE) - return NULL; - tlv = kmalloc(data[1] + sizeof(data), GFP_KERNEL); - if (!tlv) - return NULL; - memcpy(tlv, data, sizeof(data)); - if (copy_from_user(tlv + 2, _tlv + 2, data[1])) { - kfree(tlv); - return NULL; - } - return tlv; -} - -static int copy_gctl(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_control_gpr *gctl, - struct snd_emu10k1_fx8010_control_gpr __user *_gctl, - int idx) -{ - struct snd_emu10k1_fx8010_control_old_gpr __user *octl; - - if (emu->support_tlv) - return copy_from_user(gctl, &_gctl[idx], sizeof(*gctl)); - octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl; - if (copy_from_user(gctl, &octl[idx], sizeof(*octl))) - return -EFAULT; - gctl->tlv = NULL; - return 0; -} - -static int copy_gctl_to_user(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_control_gpr __user *_gctl, - struct snd_emu10k1_fx8010_control_gpr *gctl, - int idx) -{ - struct snd_emu10k1_fx8010_control_old_gpr __user *octl; - - if (emu->support_tlv) - return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl)); - - octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl; - return copy_to_user(&octl[idx], gctl, sizeof(*octl)); -} - -static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - unsigned int i; - struct snd_ctl_elem_id __user *_id; - struct snd_ctl_elem_id id; - struct snd_emu10k1_fx8010_control_gpr *gctl; - int err; - - for (i = 0, _id = icode->gpr_del_controls; - i < icode->gpr_del_control_count; i++, _id++) { - if (copy_from_user(&id, _id, sizeof(id))) - return -EFAULT; - if (snd_emu10k1_look_for_ctl(emu, &id) == NULL) - return -ENOENT; - } - gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); - if (! gctl) - return -ENOMEM; - err = 0; - for (i = 0; i < icode->gpr_add_control_count; i++) { - if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { - err = -EFAULT; - goto __error; - } - if (snd_emu10k1_look_for_ctl(emu, &gctl->id)) - continue; - down_read(&emu->card->controls_rwsem); - if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) { - up_read(&emu->card->controls_rwsem); - err = -EEXIST; - goto __error; - } - up_read(&emu->card->controls_rwsem); - if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER && - gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) { - err = -EINVAL; - goto __error; - } - } - for (i = 0; i < icode->gpr_list_control_count; i++) { - /* FIXME: we need to check the WRITE access */ - if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) { - err = -EFAULT; - goto __error; - } - } - __error: - kfree(gctl); - return err; -} - -static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl) -{ - struct snd_emu10k1_fx8010_ctl *ctl; - - ctl = (struct snd_emu10k1_fx8010_ctl *) kctl->private_value; - kctl->private_value = 0; - list_del(&ctl->list); - kfree(ctl); - if (kctl->tlv.p) - kfree(kctl->tlv.p); -} - -static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - unsigned int i, j; - struct snd_emu10k1_fx8010_control_gpr *gctl; - struct snd_emu10k1_fx8010_ctl *ctl, *nctl; - struct snd_kcontrol_new knew; - struct snd_kcontrol *kctl; - struct snd_ctl_elem_value *val; - int err = 0; - - val = kmalloc(sizeof(*val), GFP_KERNEL); - gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); - nctl = kmalloc(sizeof(*nctl), GFP_KERNEL); - if (!val || !gctl || !nctl) { - err = -ENOMEM; - goto __error; - } - - for (i = 0; i < icode->gpr_add_control_count; i++) { - if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { - err = -EFAULT; - goto __error; - } - if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER && - gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) { - err = -EINVAL; - goto __error; - } - if (! gctl->id.name[0]) { - err = -EINVAL; - goto __error; - } - ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id); - memset(&knew, 0, sizeof(knew)); - knew.iface = gctl->id.iface; - knew.name = gctl->id.name; - knew.index = gctl->id.index; - knew.device = gctl->id.device; - knew.subdevice = gctl->id.subdevice; - knew.info = snd_emu10k1_gpr_ctl_info; - knew.tlv.p = copy_tlv(gctl->tlv); - if (knew.tlv.p) - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - knew.get = snd_emu10k1_gpr_ctl_get; - knew.put = snd_emu10k1_gpr_ctl_put; - memset(nctl, 0, sizeof(*nctl)); - nctl->vcount = gctl->vcount; - nctl->count = gctl->count; - for (j = 0; j < 32; j++) { - nctl->gpr[j] = gctl->gpr[j]; - nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */ - val->value.integer.value[j] = gctl->value[j]; - } - nctl->min = gctl->min; - nctl->max = gctl->max; - nctl->translation = gctl->translation; - if (ctl == NULL) { - ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); - if (ctl == NULL) { - err = -ENOMEM; - kfree(knew.tlv.p); - goto __error; - } - knew.private_value = (unsigned long)ctl; - *ctl = *nctl; - if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) { - kfree(ctl); - kfree(knew.tlv.p); - goto __error; - } - kctl->private_free = snd_emu10k1_ctl_private_free; - ctl->kcontrol = kctl; - list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl); - } else { - /* overwrite */ - nctl->list = ctl->list; - nctl->kcontrol = ctl->kcontrol; - *ctl = *nctl; - snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id); - } - snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val); - } - __error: - kfree(nctl); - kfree(gctl); - kfree(val); - return err; -} - -static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - unsigned int i; - struct snd_ctl_elem_id id; - struct snd_ctl_elem_id __user *_id; - struct snd_emu10k1_fx8010_ctl *ctl; - struct snd_card *card = emu->card; - - for (i = 0, _id = icode->gpr_del_controls; - i < icode->gpr_del_control_count; i++, _id++) { - if (copy_from_user(&id, _id, sizeof(id))) - return -EFAULT; - down_write(&card->controls_rwsem); - ctl = snd_emu10k1_look_for_ctl(emu, &id); - if (ctl) - snd_ctl_remove(card, ctl->kcontrol); - up_write(&card->controls_rwsem); - } - return 0; -} - -static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - unsigned int i = 0, j; - unsigned int total = 0; - struct snd_emu10k1_fx8010_control_gpr *gctl; - struct snd_emu10k1_fx8010_ctl *ctl; - struct snd_ctl_elem_id *id; - - gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); - if (! gctl) - return -ENOMEM; - - list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { - total++; - if (icode->gpr_list_controls && - i < icode->gpr_list_control_count) { - memset(gctl, 0, sizeof(*gctl)); - id = &ctl->kcontrol->id; - gctl->id.iface = id->iface; - strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name)); - gctl->id.index = id->index; - gctl->id.device = id->device; - gctl->id.subdevice = id->subdevice; - gctl->vcount = ctl->vcount; - gctl->count = ctl->count; - for (j = 0; j < 32; j++) { - gctl->gpr[j] = ctl->gpr[j]; - gctl->value[j] = ctl->value[j]; - } - gctl->min = ctl->min; - gctl->max = ctl->max; - gctl->translation = ctl->translation; - if (copy_gctl_to_user(emu, icode->gpr_list_controls, - gctl, i)) { - kfree(gctl); - return -EFAULT; - } - i++; - } - } - icode->gpr_list_control_total = total; - kfree(gctl); - return 0; -} - -static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int err = 0; - - mutex_lock(&emu->fx8010.lock); - if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0) - goto __error; - strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); - /* stop FX processor - this may be dangerous, but it's better to miss - some samples than generate wrong ones - [jk] */ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); - /* ok, do the main job */ - if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 || - (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 || - (err = snd_emu10k1_tram_poke(emu, icode)) < 0 || - (err = snd_emu10k1_code_poke(emu, icode)) < 0 || - (err = snd_emu10k1_add_controls(emu, icode)) < 0) - goto __error; - /* start FX processor when the DSP code is updated */ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); - __error: - mutex_unlock(&emu->fx8010.lock); - return err; -} - -static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int err; - - mutex_lock(&emu->fx8010.lock); - strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name)); - /* ok, do the main job */ - err = snd_emu10k1_gpr_peek(emu, icode); - if (err >= 0) - err = snd_emu10k1_tram_peek(emu, icode); - if (err >= 0) - err = snd_emu10k1_code_peek(emu, icode); - if (err >= 0) - err = snd_emu10k1_list_controls(emu, icode); - mutex_unlock(&emu->fx8010.lock); - return err; -} - -static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_pcm_rec *ipcm) -{ - unsigned int i; - int err = 0; - struct snd_emu10k1_fx8010_pcm *pcm; - - if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) - return -EINVAL; - if (ipcm->channels > 32) - return -EINVAL; - pcm = &emu->fx8010.pcm[ipcm->substream]; - mutex_lock(&emu->fx8010.lock); - spin_lock_irq(&emu->reg_lock); - if (pcm->opened) { - err = -EBUSY; - goto __error; - } - if (ipcm->channels == 0) { /* remove */ - pcm->valid = 0; - } else { - /* FIXME: we need to add universal code to the PCM transfer routine */ - if (ipcm->channels != 2) { - err = -EINVAL; - goto __error; - } - pcm->valid = 1; - pcm->opened = 0; - pcm->channels = ipcm->channels; - pcm->tram_start = ipcm->tram_start; - pcm->buffer_size = ipcm->buffer_size; - pcm->gpr_size = ipcm->gpr_size; - pcm->gpr_count = ipcm->gpr_count; - pcm->gpr_tmpcount = ipcm->gpr_tmpcount; - pcm->gpr_ptr = ipcm->gpr_ptr; - pcm->gpr_trigger = ipcm->gpr_trigger; - pcm->gpr_running = ipcm->gpr_running; - for (i = 0; i < pcm->channels; i++) - pcm->etram[i] = ipcm->etram[i]; - } - __error: - spin_unlock_irq(&emu->reg_lock); - mutex_unlock(&emu->fx8010.lock); - return err; -} - -static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_pcm_rec *ipcm) -{ - unsigned int i; - int err = 0; - struct snd_emu10k1_fx8010_pcm *pcm; - - if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) - return -EINVAL; - pcm = &emu->fx8010.pcm[ipcm->substream]; - mutex_lock(&emu->fx8010.lock); - spin_lock_irq(&emu->reg_lock); - ipcm->channels = pcm->channels; - ipcm->tram_start = pcm->tram_start; - ipcm->buffer_size = pcm->buffer_size; - ipcm->gpr_size = pcm->gpr_size; - ipcm->gpr_ptr = pcm->gpr_ptr; - ipcm->gpr_count = pcm->gpr_count; - ipcm->gpr_tmpcount = pcm->gpr_tmpcount; - ipcm->gpr_trigger = pcm->gpr_trigger; - ipcm->gpr_running = pcm->gpr_running; - for (i = 0; i < pcm->channels; i++) - ipcm->etram[i] = pcm->etram[i]; - ipcm->res1 = ipcm->res2 = 0; - ipcm->pad = 0; - spin_unlock_irq(&emu->reg_lock); - mutex_unlock(&emu->fx8010.lock); - return err; -} - -#define SND_EMU10K1_GPR_CONTROLS 44 -#define SND_EMU10K1_INPUTS 12 -#define SND_EMU10K1_PLAYBACK_CHANNELS 8 -#define SND_EMU10K1_CAPTURE_CHANNELS 4 - -static void __devinit -snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) -{ - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, name); - ctl->vcount = ctl->count = 1; - ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; - if (high_res_gpr_volume) { - ctl->min = 0; - ctl->max = 0x7fffffff; - ctl->tlv = snd_emu10k1_db_linear; - ctl->translation = EMU10K1_GPR_TRANSLATION_NONE; - } else { - ctl->min = 0; - ctl->max = 100; - ctl->tlv = snd_emu10k1_db_scale1; - ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; - } -} - -static void __devinit -snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) -{ - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, name); - ctl->vcount = ctl->count = 2; - ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; - ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; - if (high_res_gpr_volume) { - ctl->min = 0; - ctl->max = 0x7fffffff; - ctl->tlv = snd_emu10k1_db_linear; - ctl->translation = EMU10K1_GPR_TRANSLATION_NONE; - } else { - ctl->min = 0; - ctl->max = 100; - ctl->tlv = snd_emu10k1_db_scale1; - ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; - } -} - -static void __devinit -snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) -{ - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, name); - ctl->vcount = ctl->count = 1; - ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; - ctl->min = 0; - ctl->max = 1; - ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; -} - -static void __devinit -snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) -{ - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, name); - ctl->vcount = ctl->count = 2; - ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; - ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; - ctl->min = 0; - ctl->max = 1; - ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; -} - -/* - * Used for emu1010 - conversion from 32-bit capture inputs from HANA - * to 2 x 16-bit registers in audigy - their values are read via DMA. - * Conversion is performed by Audigy DSP instructions of FX8010. - */ -static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( - struct snd_emu10k1_fx8010_code *icode, - u32 *ptr, int tmp, int bit_shifter16, - int reg_in, int reg_out) -{ - A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000); - A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000); - A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2)); - A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000); - A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000); - A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000); - A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2)); - A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000); - return 1; -} - -/* - * initial DSP configuration for Audigy - */ - -static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) -{ - int err, i, z, gpr, nctl; - int bit_shifter16; - const int playback = 10; - const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */ - const int stereo_mix = capture + 2; - const int tmp = 0x88; - u32 ptr; - struct snd_emu10k1_fx8010_code *icode = NULL; - struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; - u32 *gpr_map; - mm_segment_t seg; - - if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL || - (icode->gpr_map = (u_int32_t __user *) - kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), - GFP_KERNEL)) == NULL || - (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, - sizeof(*controls), GFP_KERNEL)) == NULL) { - err = -ENOMEM; - goto __err; - } - gpr_map = (u32 __force *)icode->gpr_map; - - icode->tram_data_map = icode->gpr_map + 512; - icode->tram_addr_map = icode->tram_data_map + 256; - icode->code = icode->tram_addr_map + 256; - - /* clear free GPRs */ - for (i = 0; i < 512; i++) - set_bit(i, icode->gpr_valid); - - /* clear TRAM data & address lines */ - for (i = 0; i < 256; i++) - set_bit(i, icode->tram_valid); - - strcpy(icode->name, "Audigy DSP code for ALSA"); - ptr = 0; - nctl = 0; - gpr = stereo_mix + 10; - gpr_map[gpr++] = 0x00007fff; - gpr_map[gpr++] = 0x00008000; - gpr_map[gpr++] = 0x0000ffff; - bit_shifter16 = gpr; - - /* stop FX processor */ - snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); - -#if 1 - /* PCM front Playback Volume (independent from stereo mix) - * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31) - * where gpr contains attenuation from corresponding mixer control - * (snd_emu10k1_init_stereo_control) - */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); - gpr += 2; - - /* PCM Surround Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100); - gpr += 2; - - /* PCM Side Playback (independent from stereo mix) */ - if (emu->card_capabilities->spk71) { - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100); - gpr += 2; - } - - /* PCM Center Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER)); - snd_emu10k1_init_mono_control(&controls[nctl++], "PCM Center Playback Volume", gpr, 100); - gpr++; - - /* PCM LFE Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE)); - snd_emu10k1_init_mono_control(&controls[nctl++], "PCM LFE Playback Volume", gpr, 100); - gpr++; - - /* - * Stereo Mix - */ - /* Wave (PCM) Playback Volume (will be renamed later) */ - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100); - gpr += 2; - - /* Synth Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100); - gpr += 2; - - /* Wave (PCM) Capture */ - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0); - gpr += 2; - - /* Synth Capture */ - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0); - gpr += 2; - - /* - * inputs - */ -#define A_ADD_VOLUME_IN(var,vol,input) \ -A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) - - /* emu1212 DSP 0 and DSP 1 Capture */ - if (emu->card_capabilities->emu_model) { - if (emu->card_capabilities->ca0108_chip) { - /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */ - A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_GPR(tmp)); - A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x1), A_C_00000001); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr), A_GPR(tmp)); - } else { - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1)); - } - snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); - gpr += 2; - } - /* AC'97 Playback Volume - used only for mic (renamed later) */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], "AMic Playback Volume", gpr, 0); - gpr += 2; - /* AC'97 Capture Volume - used only for mic */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AC97_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AC97_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Mic Capture Volume", gpr, 0); - gpr += 2; - - /* mic capture buffer */ - A_OP(icode, &ptr, iINTERP, A_EXTOUT(A_EXTOUT_MIC_CAP), A_EXTIN(A_EXTIN_AC97_L), 0xcd, A_EXTIN(A_EXTIN_AC97_R)); - - /* Audigy CD Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume", - gpr, 0); - gpr += 2; - /* Audigy CD Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume", - gpr, 0); - gpr += 2; - - /* Optical SPDIF Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_OPT_SPDIF_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_OPT_SPDIF_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",PLAYBACK,VOLUME), gpr, 0); - gpr += 2; - /* Optical SPDIF Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_OPT_SPDIF_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_OPT_SPDIF_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",CAPTURE,VOLUME), gpr, 0); - gpr += 2; - - /* Line2 Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume", - gpr, 0); - gpr += 2; - /* Line2 Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume", - gpr, 0); - gpr += 2; - - /* Philips ADC Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_ADC_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_ADC_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Playback Volume", gpr, 0); - gpr += 2; - /* Philips ADC Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_ADC_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_ADC_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Capture Volume", gpr, 0); - gpr += 2; - - /* Aux2 Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume", - gpr, 0); - gpr += 2; - /* Aux2 Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume", - gpr, 0); - gpr += 2; - - /* Stereo Mix Front Playback Volume */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_GPR(playback), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_GPR(playback+1), A_GPR(gpr+1), A_GPR(stereo_mix+1)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Front Playback Volume", gpr, 100); - gpr += 2; - - /* Stereo Mix Surround Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_GPR(playback+2), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_GPR(playback+3), A_GPR(gpr+1), A_GPR(stereo_mix+1)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Surround Playback Volume", gpr, 0); - gpr += 2; - - /* Stereo Mix Center Playback */ - /* Center = sub = Left/2 + Right/2 */ - A_OP(icode, &ptr, iINTERP, A_GPR(tmp), A_GPR(stereo_mix), 0xcd, A_GPR(stereo_mix+1)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_GPR(tmp)); - snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 0); - gpr++; - - /* Stereo Mix LFE Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp)); - snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0); - gpr++; - - if (emu->card_capabilities->spk71) { - /* Stereo Mix Side Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0); - gpr += 2; - } - - /* - * outputs - */ -#define A_PUT_OUTPUT(out,src) A_OP(icode, &ptr, iACC3, A_EXTOUT(out), A_C_00000000, A_C_00000000, A_GPR(src)) -#define A_PUT_STEREO_OUTPUT(out1,out2,src) \ - {A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);} - -#define _A_SWITCH(icode, ptr, dst, src, sw) \ - A_OP((icode), ptr, iMACINT0, dst, A_C_00000000, src, sw); -#define A_SWITCH(icode, ptr, dst, src, sw) \ - _A_SWITCH(icode, ptr, A_GPR(dst), A_GPR(src), A_GPR(sw)) -#define _A_SWITCH_NEG(icode, ptr, dst, src) \ - A_OP((icode), ptr, iANDXOR, dst, src, A_C_00000001, A_C_00000001); -#define A_SWITCH_NEG(icode, ptr, dst, src) \ - _A_SWITCH_NEG(icode, ptr, A_GPR(dst), A_GPR(src)) - - - /* - * Process tone control - */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), A_GPR(playback + 0), A_C_00000000, A_C_00000000); /* left */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), A_GPR(playback + 1), A_C_00000000, A_C_00000000); /* right */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), A_GPR(playback + 2), A_C_00000000, A_C_00000000); /* rear left */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */ - if (emu->card_capabilities->spk71) { - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */ - } - - - ctl = &controls[nctl + 0]; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, "Tone Control - Bass"); - ctl->vcount = 2; - ctl->count = 10; - ctl->min = 0; - ctl->max = 40; - ctl->value[0] = ctl->value[1] = 20; - ctl->translation = EMU10K1_GPR_TRANSLATION_BASS; - ctl = &controls[nctl + 1]; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, "Tone Control - Treble"); - ctl->vcount = 2; - ctl->count = 10; - ctl->min = 0; - ctl->max = 40; - ctl->value[0] = ctl->value[1] = 20; - ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE; - -#define BASS_GPR 0x8c -#define TREBLE_GPR 0x96 - - for (z = 0; z < 5; z++) { - int j; - for (j = 0; j < 2; j++) { - controls[nctl + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j; - controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j; - } - } - for (z = 0; z < 4; z++) { /* front/rear/center-lfe/side */ - int j, k, l, d; - for (j = 0; j < 2; j++) { /* left/right */ - k = 0xb0 + (z * 8) + (j * 4); - l = 0xe0 + (z * 8) + (j * 4); - d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j; - - A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(d), A_GPR(BASS_GPR + 0 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(k+1), A_GPR(k), A_GPR(k+1), A_GPR(BASS_GPR + 4 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(k), A_GPR(d), A_GPR(k), A_GPR(BASS_GPR + 2 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(k+3), A_GPR(k+2), A_GPR(k+3), A_GPR(BASS_GPR + 8 + j)); - A_OP(icode, &ptr, iMAC0, A_GPR(k+2), A_GPR_ACCU, A_GPR(k+2), A_GPR(BASS_GPR + 6 + j)); - A_OP(icode, &ptr, iACC3, A_GPR(k+2), A_GPR(k+2), A_GPR(k+2), A_C_00000000); - - A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(k+2), A_GPR(TREBLE_GPR + 0 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(l+1), A_GPR(l), A_GPR(l+1), A_GPR(TREBLE_GPR + 4 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(l), A_GPR(k+2), A_GPR(l), A_GPR(TREBLE_GPR + 2 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(l+3), A_GPR(l+2), A_GPR(l+3), A_GPR(TREBLE_GPR + 8 + j)); - A_OP(icode, &ptr, iMAC0, A_GPR(l+2), A_GPR_ACCU, A_GPR(l+2), A_GPR(TREBLE_GPR + 6 + j)); - A_OP(icode, &ptr, iMACINT0, A_GPR(l+2), A_C_00000000, A_GPR(l+2), A_C_00000010); - - A_OP(icode, &ptr, iACC3, A_GPR(d), A_GPR(l+2), A_C_00000000, A_C_00000000); - - if (z == 2) /* center */ - break; - } - } - nctl += 2; - -#undef BASS_GPR -#undef TREBLE_GPR - - for (z = 0; z < 8; z++) { - A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0); - A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0); - A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1); - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); - } - snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0); - gpr += 2; - - /* Master volume (will be renamed later) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS)); - snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0); - gpr += 2; - - /* analog speakers */ - A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); - if (emu->card_capabilities->spk71) - A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS); - - /* headphone */ - A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); - - /* digital outputs */ - /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ - if (emu->card_capabilities->emu_model) { - /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ - snd_printk(KERN_INFO "EMU outputs on\n"); - for (z = 0; z < 8; z++) { - if (emu->card_capabilities->ca0108_chip) { - A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); - } else { - A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); - } - } - } - - /* IEC958 Optical Raw Playback Switch */ - gpr_map[gpr++] = 0; - gpr_map[gpr++] = 0x1008; - gpr_map[gpr++] = 0xffff0000; - for (z = 0; z < 2; z++) { - A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000); - A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001); - A_OP(icode, &ptr, iACC3, A_GPR(tmp + 2), A_C_00000000, A_C_00010000, A_GPR(tmp + 2)); - A_OP(icode, &ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_GPR(gpr - 1), A_C_00000000); - A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z); - A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z); - A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1); - if ((z==1) && (emu->card_capabilities->spdif_bug)) { - /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */ - snd_printk(KERN_INFO "Installing spdif_bug patch: %s\n", emu->card_capabilities->name); - A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); - } else { - A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); - } - } - snd_emu10k1_init_stereo_onoff_control(controls + nctl++, SNDRV_CTL_NAME_IEC958("Optical Raw ",PLAYBACK,SWITCH), gpr, 0); - gpr += 2; - - A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); - - /* ADC buffer */ -#ifdef EMU10K1_CAPTURE_DIGITAL_OUT - A_PUT_STEREO_OUTPUT(A_EXTOUT_ADC_CAP_L, A_EXTOUT_ADC_CAP_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); -#else - A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture); - A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); -#endif - - if (emu->card_capabilities->emu_model) { - if (emu->card_capabilities->ca0108_chip) { - snd_printk(KERN_INFO "EMU2 inputs on\n"); - for (z = 0; z < 0x10; z++) { - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, - bit_shifter16, - A3_EMU32IN(z), - A_FXBUS2(z*2) ); - } - } else { - snd_printk(KERN_INFO "EMU inputs on\n"); - /* Capture 16 (originally 8) channels of S32_LE sound */ - - /* - printk(KERN_DEBUG "emufx.c: gpr=0x%x, tmp=0x%x\n", - gpr, tmp); - */ - /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ - /* A_P16VIN(0) is delayed by one sample, - * so all other A_P16VIN channels will need to also be delayed - */ - /* Left ADC in. 1 of 2 */ - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); - /* Right ADC in 1 of 2 */ - gpr_map[gpr++] = 0x00000000; - /* Delaying by one sample: instead of copying the input - * value A_P16VIN to output A_FXBUS2 as in the first channel, - * we use an auxiliary register, delaying the value by one - * sample - */ - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); - /* For 96kHz mode */ - /* Left ADC in. 2 of 2 */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); - /* Right ADC in 2 of 2 */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); - /* Pavel Hofman - we still have voices, A_FXBUS2s, and - * A_P16VINs available - - * let's add 8 more capture channels - total of 16 - */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x10)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x12)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x14)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x16)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x18)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1a)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1c)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1e)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), - A_C_00000000, A_C_00000000); - } - -#if 0 - for (z = 4; z < 8; z++) { - A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000); - } - for (z = 0xc; z < 0x10; z++) { - A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000); - } -#endif - } else { - /* EFX capture - capture the 16 EXTINs */ - /* Capture 16 channels of S16_LE sound */ - for (z = 0; z < 16; z++) { - A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z)); - } - } - -#endif /* JCD test */ - /* - * ok, set up done.. - */ - - if (gpr > tmp) { - snd_BUG(); - err = -EIO; - goto __err; - } - /* clear remaining instruction memory */ - while (ptr < 0x400) - A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0); - - seg = snd_enter_user(); - icode->gpr_add_control_count = nctl; - icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; - emu->support_tlv = 1; /* support TLV */ - err = snd_emu10k1_icode_poke(emu, icode); - emu->support_tlv = 0; /* clear again */ - snd_leave_user(seg); - - __err: - kfree(controls); - if (icode != NULL) { - kfree((void __force *)icode->gpr_map); - kfree(icode); - } - return err; -} - - -/* - * initial DSP configuration for Emu10k1 - */ - -/* when volume = max, then copy only to avoid volume modification */ -/* with iMAC0 (negative values) */ -static void __devinit _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) -{ - OP(icode, ptr, iMAC0, dst, C_00000000, src, vol); - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001); - OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000); -} -static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) -{ - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); - OP(icode, ptr, iMACINT0, dst, dst, src, C_00000001); - OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001); - OP(icode, ptr, iMAC0, dst, dst, src, vol); -} -static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) -{ - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); - OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000); - OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001); - OP(icode, ptr, iMAC0, dst, C_00000000, src, vol); -} - -#define VOLUME(icode, ptr, dst, src, vol) \ - _volume(icode, ptr, GPR(dst), GPR(src), GPR(vol)) -#define VOLUME_IN(icode, ptr, dst, src, vol) \ - _volume(icode, ptr, GPR(dst), EXTIN(src), GPR(vol)) -#define VOLUME_ADD(icode, ptr, dst, src, vol) \ - _volume_add(icode, ptr, GPR(dst), GPR(src), GPR(vol)) -#define VOLUME_ADDIN(icode, ptr, dst, src, vol) \ - _volume_add(icode, ptr, GPR(dst), EXTIN(src), GPR(vol)) -#define VOLUME_OUT(icode, ptr, dst, src, vol) \ - _volume_out(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol)) -#define _SWITCH(icode, ptr, dst, src, sw) \ - OP((icode), ptr, iMACINT0, dst, C_00000000, src, sw); -#define SWITCH(icode, ptr, dst, src, sw) \ - _SWITCH(icode, ptr, GPR(dst), GPR(src), GPR(sw)) -#define SWITCH_IN(icode, ptr, dst, src, sw) \ - _SWITCH(icode, ptr, GPR(dst), EXTIN(src), GPR(sw)) -#define _SWITCH_NEG(icode, ptr, dst, src) \ - OP((icode), ptr, iANDXOR, dst, src, C_00000001, C_00000001); -#define SWITCH_NEG(icode, ptr, dst, src) \ - _SWITCH_NEG(icode, ptr, GPR(dst), GPR(src)) - - -static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) -{ - int err, i, z, gpr, tmp, playback, capture; - u32 ptr; - struct snd_emu10k1_fx8010_code *icode; - struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL; - struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; - u32 *gpr_map; - mm_segment_t seg; - - if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL) - return -ENOMEM; - if ((icode->gpr_map = (u_int32_t __user *) - kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), - GFP_KERNEL)) == NULL || - (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, - sizeof(struct snd_emu10k1_fx8010_control_gpr), - GFP_KERNEL)) == NULL || - (ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) { - err = -ENOMEM; - goto __err; - } - gpr_map = (u32 __force *)icode->gpr_map; - - icode->tram_data_map = icode->gpr_map + 256; - icode->tram_addr_map = icode->tram_data_map + 160; - icode->code = icode->tram_addr_map + 160; - - /* clear free GPRs */ - for (i = 0; i < 256; i++) - set_bit(i, icode->gpr_valid); - - /* clear TRAM data & address lines */ - for (i = 0; i < 160; i++) - set_bit(i, icode->tram_valid); - - strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela"); - ptr = 0; i = 0; - /* we have 12 inputs */ - playback = SND_EMU10K1_INPUTS; - /* we have 6 playback channels and tone control doubles */ - capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); - gpr = capture + SND_EMU10K1_CAPTURE_CHANNELS; - tmp = 0x88; /* we need 4 temporary GPR */ - /* from 0x8c to 0xff is the area for tone control */ - - /* stop FX processor */ - snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP); - - /* - * Process FX Buses - */ - OP(icode, &ptr, iMACINT0, GPR(0), C_00000000, FXBUS(FXBUS_PCM_LEFT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(1), C_00000000, FXBUS(FXBUS_PCM_RIGHT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(2), C_00000000, FXBUS(FXBUS_MIDI_LEFT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(3), C_00000000, FXBUS(FXBUS_MIDI_RIGHT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(4), C_00000000, FXBUS(FXBUS_PCM_LEFT_REAR), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(5), C_00000000, FXBUS(FXBUS_PCM_RIGHT_REAR), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(6), C_00000000, FXBUS(FXBUS_PCM_CENTER), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(7), C_00000000, FXBUS(FXBUS_PCM_LFE), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(8), C_00000000, C_00000000, C_00000000); /* S/PDIF left */ - OP(icode, &ptr, iMACINT0, GPR(9), C_00000000, C_00000000, C_00000000); /* S/PDIF right */ - OP(icode, &ptr, iMACINT0, GPR(10), C_00000000, FXBUS(FXBUS_PCM_LEFT_FRONT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(11), C_00000000, FXBUS(FXBUS_PCM_RIGHT_FRONT), C_00000004); - - /* Raw S/PDIF PCM */ - ipcm->substream = 0; - ipcm->channels = 2; - ipcm->tram_start = 0; - ipcm->buffer_size = (64 * 1024) / 2; - ipcm->gpr_size = gpr++; - ipcm->gpr_ptr = gpr++; - ipcm->gpr_count = gpr++; - ipcm->gpr_tmpcount = gpr++; - ipcm->gpr_trigger = gpr++; - ipcm->gpr_running = gpr++; - ipcm->etram[0] = 0; - ipcm->etram[1] = 1; - - gpr_map[gpr + 0] = 0xfffff000; - gpr_map[gpr + 1] = 0xffff0000; - gpr_map[gpr + 2] = 0x70000000; - gpr_map[gpr + 3] = 0x00000007; - gpr_map[gpr + 4] = 0x001f << 11; - gpr_map[gpr + 5] = 0x001c << 11; - gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */ - gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */ - gpr_map[gpr + 8] = 0x2000000 + (2<<11); - gpr_map[gpr + 9] = 0x4000000 + (2<<11); - gpr_map[gpr + 10] = 1<<11; - gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */ - gpr_map[gpr + 12] = 0; - - /* if the trigger flag is not set, skip */ - /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000); - /* 01: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_ZERO, GPR(gpr + 6)); - /* if the running flag is set, we're running */ - /* 02: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_running), C_00000000, C_00000000); - /* 03: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000004); - /* wait until ((GPR_DBAC>>11) & 0x1f) == 0x1c) */ - /* 04: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), GPR_DBAC, GPR(gpr + 4), C_00000000); - /* 05: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(gpr + 5)); - /* 06: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 7)); - /* 07: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000010, C_00000001, C_00000000); - - /* 08: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000000, C_00000001); - /* 09: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), GPR(gpr + 12), C_ffffffff, C_00000000); - /* 0a: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 11)); - /* 0b: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000001, C_00000000, C_00000000); - - /* 0c: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[0]), GPR(gpr + 0), C_00000000); - /* 0d: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000); - /* 0e: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2)); - /* 0f: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001); - /* 10: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(8), GPR(gpr + 1), GPR(gpr + 2)); - - /* 11: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[1]), GPR(gpr + 0), C_00000000); - /* 12: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000); - /* 13: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2)); - /* 14: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001); - /* 15: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(9), GPR(gpr + 1), GPR(gpr + 2)); - - /* 16: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(ipcm->gpr_ptr), C_00000001, C_00000000); - /* 17: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(ipcm->gpr_size)); - /* 18: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_MINUS, C_00000001); - /* 19: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), C_00000000, C_00000000, C_00000000); - /* 1a: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_ptr), GPR(tmp + 0), C_00000000, C_00000000); - - /* 1b: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_tmpcount), C_ffffffff, C_00000000); - /* 1c: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); - /* 1d: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_count), C_00000000, C_00000000); - /* 1e: */ OP(icode, &ptr, iACC3, GPR_IRQ, C_80000000, C_00000000, C_00000000); - /* 1f: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000001, C_00010000); - - /* 20: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00010000, C_00000001); - /* 21: */ OP(icode, &ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000002); - - /* 22: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[0]), GPR(gpr + 8), GPR_DBAC, C_ffffffff); - /* 23: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[1]), GPR(gpr + 9), GPR_DBAC, C_ffffffff); - - /* 24: */ - gpr += 13; - - /* Wave Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME(icode, &ptr, playback + z, z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Wave Playback Volume", gpr, 100); - gpr += 2; - - /* Wave Surround Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME(icode, &ptr, playback + 2 + z, z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Wave Surround Playback Volume", gpr, 0); - gpr += 2; - - /* Wave Center/LFE Playback Volume */ - OP(icode, &ptr, iACC3, GPR(tmp + 0), FXBUS(FXBUS_PCM_LEFT), FXBUS(FXBUS_PCM_RIGHT), C_00000000); - OP(icode, &ptr, iMACINT0, GPR(tmp + 0), C_00000000, GPR(tmp + 0), C_00000002); - VOLUME(icode, &ptr, playback + 4, tmp + 0, gpr); - snd_emu10k1_init_mono_control(controls + i++, "Wave Center Playback Volume", gpr++, 0); - VOLUME(icode, &ptr, playback + 5, tmp + 0, gpr); - snd_emu10k1_init_mono_control(controls + i++, "Wave LFE Playback Volume", gpr++, 0); - - /* Wave Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, z, gpr + 2 + z); - VOLUME(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Wave Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0); - gpr += 4; - - /* Synth Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100); - gpr += 2; - - /* Synth Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0); - gpr += 4; - - /* Surround Digital Playback Volume (renamed later without Digital) */ - for (z = 0; z < 2; z++) - VOLUME_ADD(icode, &ptr, playback + 2 + z, 4 + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Surround Digital Playback Volume", gpr, 100); - gpr += 2; - - /* Surround Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, 4 + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Surround Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Surround Capture Switch", gpr + 2, 0); - gpr += 4; - - /* Center Playback Volume (renamed later without Digital) */ - VOLUME_ADD(icode, &ptr, playback + 4, 6, gpr); - snd_emu10k1_init_mono_control(controls + i++, "Center Digital Playback Volume", gpr++, 100); - - /* LFE Playback Volume + Switch (renamed later without Digital) */ - VOLUME_ADD(icode, &ptr, playback + 5, 7, gpr); - snd_emu10k1_init_mono_control(controls + i++, "LFE Digital Playback Volume", gpr++, 100); - - /* Front Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADD(icode, &ptr, playback + z, 10 + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Front Playback Volume", gpr, 100); - gpr += 2; - - /* Front Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, 10 + z, gpr + 2); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Front Capture Volume", gpr, 0); - snd_emu10k1_init_mono_onoff_control(controls + i++, "Front Capture Switch", gpr + 2, 0); - gpr += 3; - - /* - * Process inputs - */ - - if (emu->fx8010.extin_mask & ((1<fx8010.extin_mask & ((1<fx8010.extin_mask & ((1<fx8010.extin_mask & ((1<fx8010.extin_mask & ((1<fx8010.extin_mask & ((1<fx8010.extin_mask & ((1<id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, "Tone Control - Bass"); - ctl->vcount = 2; - ctl->count = 10; - ctl->min = 0; - ctl->max = 40; - ctl->value[0] = ctl->value[1] = 20; - ctl->tlv = snd_emu10k1_bass_treble_db_scale; - ctl->translation = EMU10K1_GPR_TRANSLATION_BASS; - ctl = &controls[i + 1]; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, "Tone Control - Treble"); - ctl->vcount = 2; - ctl->count = 10; - ctl->min = 0; - ctl->max = 40; - ctl->value[0] = ctl->value[1] = 20; - ctl->tlv = snd_emu10k1_bass_treble_db_scale; - ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE; - -#define BASS_GPR 0x8c -#define TREBLE_GPR 0x96 - - for (z = 0; z < 5; z++) { - int j; - for (j = 0; j < 2; j++) { - controls[i + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j; - controls[i + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j; - } - } - for (z = 0; z < 3; z++) { /* front/rear/center-lfe */ - int j, k, l, d; - for (j = 0; j < 2; j++) { /* left/right */ - k = 0xa0 + (z * 8) + (j * 4); - l = 0xd0 + (z * 8) + (j * 4); - d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j; - - OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(d), GPR(BASS_GPR + 0 + j)); - OP(icode, &ptr, iMACMV, GPR(k+1), GPR(k), GPR(k+1), GPR(BASS_GPR + 4 + j)); - OP(icode, &ptr, iMACMV, GPR(k), GPR(d), GPR(k), GPR(BASS_GPR + 2 + j)); - OP(icode, &ptr, iMACMV, GPR(k+3), GPR(k+2), GPR(k+3), GPR(BASS_GPR + 8 + j)); - OP(icode, &ptr, iMAC0, GPR(k+2), GPR_ACCU, GPR(k+2), GPR(BASS_GPR + 6 + j)); - OP(icode, &ptr, iACC3, GPR(k+2), GPR(k+2), GPR(k+2), C_00000000); - - OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(k+2), GPR(TREBLE_GPR + 0 + j)); - OP(icode, &ptr, iMACMV, GPR(l+1), GPR(l), GPR(l+1), GPR(TREBLE_GPR + 4 + j)); - OP(icode, &ptr, iMACMV, GPR(l), GPR(k+2), GPR(l), GPR(TREBLE_GPR + 2 + j)); - OP(icode, &ptr, iMACMV, GPR(l+3), GPR(l+2), GPR(l+3), GPR(TREBLE_GPR + 8 + j)); - OP(icode, &ptr, iMAC0, GPR(l+2), GPR_ACCU, GPR(l+2), GPR(TREBLE_GPR + 6 + j)); - OP(icode, &ptr, iMACINT0, GPR(l+2), C_00000000, GPR(l+2), C_00000010); - - OP(icode, &ptr, iACC3, GPR(d), GPR(l+2), C_00000000, C_00000000); - - if (z == 2) /* center */ - break; - } - } - i += 2; - -#undef BASS_GPR -#undef TREBLE_GPR - - for (z = 0; z < 6; z++) { - SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0); - SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0); - SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1); - OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000); - } - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Tone Control - Switch", gpr, 0); - gpr += 2; - - /* - * Process outputs - */ - if (emu->fx8010.extout_mask & ((1<fx8010.extout_mask & ((1<fx8010.extout_mask & ((1<fx8010.extout_mask & ((1<fx8010.extout_mask & ((1<fx8010.extout_mask & (1<fx8010.extout_mask & (1<fx8010.extout_mask & (1<card_capabilities->sblive51) { - /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER - * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording. - * - * Since only 14 of the 16 EXTINs are used, this is not a big problem. - * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture - * 0 and 3, then the rest of the EXTINs to the corresponding FX capture - * channel. Multitrack recorders will still see the center/lfe output signal - * on the second and third channels. - */ - OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0)); - OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1)); - OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2)); - OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3)); - for (z = 4; z < 14; z++) - OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); - } else { - for (z = 0; z < 16; z++) - OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); - } - - - if (gpr > tmp) { - snd_BUG(); - err = -EIO; - goto __err; - } - if (i > SND_EMU10K1_GPR_CONTROLS) { - snd_BUG(); - err = -EIO; - goto __err; - } - - /* clear remaining instruction memory */ - while (ptr < 0x200) - OP(icode, &ptr, iACC3, C_00000000, C_00000000, C_00000000, C_00000000); - - if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0) - goto __err; - seg = snd_enter_user(); - icode->gpr_add_control_count = i; - icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; - emu->support_tlv = 1; /* support TLV */ - err = snd_emu10k1_icode_poke(emu, icode); - emu->support_tlv = 0; /* clear again */ - snd_leave_user(seg); - if (err >= 0) - err = snd_emu10k1_ipcm_poke(emu, ipcm); - __err: - kfree(ipcm); - kfree(controls); - if (icode != NULL) { - kfree((void __force *)icode->gpr_map); - kfree(icode); - } - return err; -} - -int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu) -{ - spin_lock_init(&emu->fx8010.irq_lock); - INIT_LIST_HEAD(&emu->fx8010.gpr_ctl); - if (emu->audigy) - return _snd_emu10k1_audigy_init_efx(emu); - else - return _snd_emu10k1_init_efx(emu); -} - -void snd_emu10k1_free_efx(struct snd_emu10k1 *emu) -{ - /* stop processor */ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP); -} - -#if 0 /* FIXME: who use them? */ -int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output) -{ - if (output < 0 || output >= 6) - return -EINVAL; - snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 1); - return 0; -} - -int snd_emu10k1_fx8010_tone_control_deactivate(struct snd_emu10k1 *emu, int output) -{ - if (output < 0 || output >= 6) - return -EINVAL; - snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 0); - return 0; -} -#endif - -int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size) -{ - u8 size_reg = 0; - - /* size is in samples */ - if (size != 0) { - size = (size - 1) >> 13; - - while (size) { - size >>= 1; - size_reg++; - } - size = 0x2000 << size_reg; - } - if ((emu->fx8010.etram_pages.bytes / 2) == size) - return 0; - spin_lock_irq(&emu->emu_lock); - outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG); - spin_unlock_irq(&emu->emu_lock); - snd_emu10k1_ptr_write(emu, TCB, 0, 0); - snd_emu10k1_ptr_write(emu, TCBS, 0, 0); - if (emu->fx8010.etram_pages.area != NULL) { - snd_dma_free_pages(&emu->fx8010.etram_pages); - emu->fx8010.etram_pages.area = NULL; - emu->fx8010.etram_pages.bytes = 0; - } - - if (size > 0) { - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), - size * 2, &emu->fx8010.etram_pages) < 0) - return -ENOMEM; - memset(emu->fx8010.etram_pages.area, 0, size * 2); - snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr); - snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg); - spin_lock_irq(&emu->emu_lock); - outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); - spin_unlock_irq(&emu->emu_lock); - } - - return 0; -} - -static int snd_emu10k1_fx8010_open(struct snd_hwdep * hw, struct file *file) -{ - return 0; -} - -static void copy_string(char *dst, char *src, char *null, int idx) -{ - if (src == NULL) - sprintf(dst, "%s %02X", null, idx); - else - strcpy(dst, src); -} - -static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_info *info) -{ - char **fxbus, **extin, **extout; - unsigned short fxbus_mask, extin_mask, extout_mask; - int res; - - info->internal_tram_size = emu->fx8010.itram_size; - info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; - fxbus = fxbuses; - extin = emu->audigy ? audigy_ins : creative_ins; - extout = emu->audigy ? audigy_outs : creative_outs; - fxbus_mask = emu->fx8010.fxbus_mask; - extin_mask = emu->fx8010.extin_mask; - extout_mask = emu->fx8010.extout_mask; - for (res = 0; res < 16; res++, fxbus++, extin++, extout++) { - copy_string(info->fxbus_names[res], fxbus_mask & (1 << res) ? *fxbus : NULL, "FXBUS", res); - copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res); - copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); - } - for (res = 16; res < 32; res++, extout++) - copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); - info->gpr_controls = emu->fx8010.gpr_count; -} - -static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_emu10k1 *emu = hw->private_data; - struct snd_emu10k1_fx8010_info *info; - struct snd_emu10k1_fx8010_code *icode; - struct snd_emu10k1_fx8010_pcm_rec *ipcm; - unsigned int addr; - void __user *argp = (void __user *)arg; - int res; - - switch (cmd) { - case SNDRV_EMU10K1_IOCTL_PVERSION: - emu->support_tlv = 1; - return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp); - case SNDRV_EMU10K1_IOCTL_INFO: - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - snd_emu10k1_fx8010_info(emu, info); - if (copy_to_user(argp, info, sizeof(*info))) { - kfree(info); - return -EFAULT; - } - kfree(info); - return 0; - case SNDRV_EMU10K1_IOCTL_CODE_POKE: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - 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 = 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); - return -EFAULT; - } - kfree(icode); - return res; - case SNDRV_EMU10K1_IOCTL_PCM_POKE: - 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 = 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); - return -EFAULT; - } - kfree(ipcm); - return res; - case SNDRV_EMU10K1_IOCTL_TRAM_SETUP: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (get_user(addr, (unsigned int __user *)argp)) - return -EFAULT; - mutex_lock(&emu->fx8010.lock); - res = snd_emu10k1_fx8010_tram_setup(emu, addr); - mutex_unlock(&emu->fx8010.lock); - return res; - case SNDRV_EMU10K1_IOCTL_STOP: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP); - return 0; - case SNDRV_EMU10K1_IOCTL_CONTINUE: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = 0); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = 0); - return 0; - case SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_ZC); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_ZC); - udelay(10); - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); - return 0; - case SNDRV_EMU10K1_IOCTL_SINGLE_STEP: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (get_user(addr, (unsigned int __user *)argp)) - return -EFAULT; - if (addr > 0x1ff) - return -EINVAL; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr); - udelay(10); - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr); - return 0; - case SNDRV_EMU10K1_IOCTL_DBG_READ: - if (emu->audigy) - addr = snd_emu10k1_ptr_read(emu, A_DBG, 0); - else - addr = snd_emu10k1_ptr_read(emu, DBG, 0); - if (put_user(addr, (unsigned int __user *)argp)) - return -EFAULT; - return 0; - } - return -ENOTTY; -} - -static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file) -{ - return 0; -} - -int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep) -{ - struct snd_hwdep *hw; - int err; - - if (rhwdep) - *rhwdep = NULL; - if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0) - return err; - strcpy(hw->name, "EMU10K1 (FX8010)"); - hw->iface = SNDRV_HWDEP_IFACE_EMU10K1; - hw->ops.open = snd_emu10k1_fx8010_open; - hw->ops.ioctl = snd_emu10k1_fx8010_ioctl; - hw->ops.release = snd_emu10k1_fx8010_release; - hw->private_data = emu; - if (rhwdep) - *rhwdep = hw; - return 0; -} - -#ifdef CONFIG_PM -int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu) -{ - int len; - - len = emu->audigy ? 0x200 : 0x100; - emu->saved_gpr = kmalloc(len * 4, GFP_KERNEL); - if (! emu->saved_gpr) - return -ENOMEM; - len = emu->audigy ? 0x100 : 0xa0; - emu->tram_val_saved = kmalloc(len * 4, GFP_KERNEL); - emu->tram_addr_saved = kmalloc(len * 4, GFP_KERNEL); - if (! emu->tram_val_saved || ! emu->tram_addr_saved) - return -ENOMEM; - len = emu->audigy ? 2 * 1024 : 2 * 512; - emu->saved_icode = vmalloc(len * 4); - if (! emu->saved_icode) - return -ENOMEM; - return 0; -} - -void snd_emu10k1_efx_free_pm_buffer(struct snd_emu10k1 *emu) -{ - kfree(emu->saved_gpr); - kfree(emu->tram_val_saved); - kfree(emu->tram_addr_saved); - vfree(emu->saved_icode); -} - -/* - * save/restore GPR, TRAM and codes - */ -void snd_emu10k1_efx_suspend(struct snd_emu10k1 *emu) -{ - int i, len; - - len = emu->audigy ? 0x200 : 0x100; - for (i = 0; i < len; i++) - emu->saved_gpr[i] = snd_emu10k1_ptr_read(emu, emu->gpr_base + i, 0); - - len = emu->audigy ? 0x100 : 0xa0; - for (i = 0; i < len; i++) { - emu->tram_val_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + i, 0); - emu->tram_addr_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + i, 0); - if (emu->audigy) { - emu->tram_addr_saved[i] >>= 12; - emu->tram_addr_saved[i] |= - snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + i, 0) << 20; - } - } - - len = emu->audigy ? 2 * 1024 : 2 * 512; - for (i = 0; i < len; i++) - emu->saved_icode[i] = snd_emu10k1_efx_read(emu, i); -} - -void snd_emu10k1_efx_resume(struct snd_emu10k1 *emu) -{ - int i, len; - - /* set up TRAM */ - if (emu->fx8010.etram_pages.bytes > 0) { - unsigned size, size_reg = 0; - size = emu->fx8010.etram_pages.bytes / 2; - size = (size - 1) >> 13; - while (size) { - size >>= 1; - size_reg++; - } - outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG); - snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr); - snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg); - outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); - } - - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); - - len = emu->audigy ? 0x200 : 0x100; - for (i = 0; i < len; i++) - snd_emu10k1_ptr_write(emu, emu->gpr_base + i, 0, emu->saved_gpr[i]); - - len = emu->audigy ? 0x100 : 0xa0; - for (i = 0; i < len; i++) { - snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + i, 0, - emu->tram_val_saved[i]); - if (! emu->audigy) - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, - emu->tram_addr_saved[i]); - else { - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, - emu->tram_addr_saved[i] << 12); - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, - emu->tram_addr_saved[i] >> 20); - } - } - - len = emu->audigy ? 2 * 1024 : 2 * 512; - for (i = 0; i < len; i++) - snd_emu10k1_efx_write(emu, i, emu->saved_icode[i]); - - /* start FX processor when the DSP code is updated */ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c b/ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c deleted file mode 100644 index 9d890a5a..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c +++ /dev/null @@ -1,2143 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela , - * Takashi Iwai - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips / mixer routines - * Multichannel PCM support Copyright (c) Lee Revell - * - * Copyright (c) by James Courtier-Dutton - * Added EMU 1010 support. - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 "p17v.h" - -#define AC97_ID_STAC9758 0x83847658 - -static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */ - -static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned long flags; - - /* Limit: emu->spdif_bits */ - if (idx >= 3) - return -EINVAL; - spin_lock_irqsave(&emu->reg_lock, flags); - ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -/* - * Items labels in enum mixer controls assigning source data to - * each destination - */ -static char *emu1010_src_texts[] = { - "Silence", - "Dock Mic A", - "Dock Mic B", - "Dock ADC1 Left", - "Dock ADC1 Right", - "Dock ADC2 Left", - "Dock ADC2 Right", - "Dock ADC3 Left", - "Dock ADC3 Right", - "0202 ADC Left", - "0202 ADC Right", - "0202 SPDIF Left", - "0202 SPDIF Right", - "ADAT 0", - "ADAT 1", - "ADAT 2", - "ADAT 3", - "ADAT 4", - "ADAT 5", - "ADAT 6", - "ADAT 7", - "DSP 0", - "DSP 1", - "DSP 2", - "DSP 3", - "DSP 4", - "DSP 5", - "DSP 6", - "DSP 7", - "DSP 8", - "DSP 9", - "DSP 10", - "DSP 11", - "DSP 12", - "DSP 13", - "DSP 14", - "DSP 15", - "DSP 16", - "DSP 17", - "DSP 18", - "DSP 19", - "DSP 20", - "DSP 21", - "DSP 22", - "DSP 23", - "DSP 24", - "DSP 25", - "DSP 26", - "DSP 27", - "DSP 28", - "DSP 29", - "DSP 30", - "DSP 31", -}; - -/* 1616(m) cardbus */ - -static char *emu1616_src_texts[] = { - "Silence", - "Dock Mic A", - "Dock Mic B", - "Dock ADC1 Left", - "Dock ADC1 Right", - "Dock ADC2 Left", - "Dock ADC2 Right", - "Dock SPDIF Left", - "Dock SPDIF Right", - "ADAT 0", - "ADAT 1", - "ADAT 2", - "ADAT 3", - "ADAT 4", - "ADAT 5", - "ADAT 6", - "ADAT 7", - "DSP 0", - "DSP 1", - "DSP 2", - "DSP 3", - "DSP 4", - "DSP 5", - "DSP 6", - "DSP 7", - "DSP 8", - "DSP 9", - "DSP 10", - "DSP 11", - "DSP 12", - "DSP 13", - "DSP 14", - "DSP 15", - "DSP 16", - "DSP 17", - "DSP 18", - "DSP 19", - "DSP 20", - "DSP 21", - "DSP 22", - "DSP 23", - "DSP 24", - "DSP 25", - "DSP 26", - "DSP 27", - "DSP 28", - "DSP 29", - "DSP 30", - "DSP 31", -}; - - -/* - * List of data sources available for each destination - */ -static unsigned int emu1010_src_regs[] = { - EMU_SRC_SILENCE,/* 0 */ - EMU_SRC_DOCK_MIC_A1, /* 1 */ - EMU_SRC_DOCK_MIC_B1, /* 2 */ - EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */ - EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */ - EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */ - EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */ - EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */ - EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */ - EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */ - EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */ - EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */ - EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */ - EMU_SRC_HANA_ADAT, /* 13 */ - EMU_SRC_HANA_ADAT+1, /* 14 */ - EMU_SRC_HANA_ADAT+2, /* 15 */ - EMU_SRC_HANA_ADAT+3, /* 16 */ - EMU_SRC_HANA_ADAT+4, /* 17 */ - EMU_SRC_HANA_ADAT+5, /* 18 */ - EMU_SRC_HANA_ADAT+6, /* 19 */ - EMU_SRC_HANA_ADAT+7, /* 20 */ - EMU_SRC_ALICE_EMU32A, /* 21 */ - EMU_SRC_ALICE_EMU32A+1, /* 22 */ - EMU_SRC_ALICE_EMU32A+2, /* 23 */ - EMU_SRC_ALICE_EMU32A+3, /* 24 */ - EMU_SRC_ALICE_EMU32A+4, /* 25 */ - EMU_SRC_ALICE_EMU32A+5, /* 26 */ - EMU_SRC_ALICE_EMU32A+6, /* 27 */ - EMU_SRC_ALICE_EMU32A+7, /* 28 */ - EMU_SRC_ALICE_EMU32A+8, /* 29 */ - EMU_SRC_ALICE_EMU32A+9, /* 30 */ - EMU_SRC_ALICE_EMU32A+0xa, /* 31 */ - EMU_SRC_ALICE_EMU32A+0xb, /* 32 */ - EMU_SRC_ALICE_EMU32A+0xc, /* 33 */ - EMU_SRC_ALICE_EMU32A+0xd, /* 34 */ - EMU_SRC_ALICE_EMU32A+0xe, /* 35 */ - EMU_SRC_ALICE_EMU32A+0xf, /* 36 */ - EMU_SRC_ALICE_EMU32B, /* 37 */ - EMU_SRC_ALICE_EMU32B+1, /* 38 */ - EMU_SRC_ALICE_EMU32B+2, /* 39 */ - EMU_SRC_ALICE_EMU32B+3, /* 40 */ - EMU_SRC_ALICE_EMU32B+4, /* 41 */ - EMU_SRC_ALICE_EMU32B+5, /* 42 */ - EMU_SRC_ALICE_EMU32B+6, /* 43 */ - EMU_SRC_ALICE_EMU32B+7, /* 44 */ - EMU_SRC_ALICE_EMU32B+8, /* 45 */ - EMU_SRC_ALICE_EMU32B+9, /* 46 */ - EMU_SRC_ALICE_EMU32B+0xa, /* 47 */ - EMU_SRC_ALICE_EMU32B+0xb, /* 48 */ - EMU_SRC_ALICE_EMU32B+0xc, /* 49 */ - EMU_SRC_ALICE_EMU32B+0xd, /* 50 */ - EMU_SRC_ALICE_EMU32B+0xe, /* 51 */ - EMU_SRC_ALICE_EMU32B+0xf, /* 52 */ -}; - -/* 1616(m) cardbus */ -static unsigned int emu1616_src_regs[] = { - EMU_SRC_SILENCE, - EMU_SRC_DOCK_MIC_A1, - EMU_SRC_DOCK_MIC_B1, - EMU_SRC_DOCK_ADC1_LEFT1, - EMU_SRC_DOCK_ADC1_RIGHT1, - EMU_SRC_DOCK_ADC2_LEFT1, - EMU_SRC_DOCK_ADC2_RIGHT1, - EMU_SRC_MDOCK_SPDIF_LEFT1, - EMU_SRC_MDOCK_SPDIF_RIGHT1, - EMU_SRC_MDOCK_ADAT, - EMU_SRC_MDOCK_ADAT+1, - EMU_SRC_MDOCK_ADAT+2, - EMU_SRC_MDOCK_ADAT+3, - EMU_SRC_MDOCK_ADAT+4, - EMU_SRC_MDOCK_ADAT+5, - EMU_SRC_MDOCK_ADAT+6, - EMU_SRC_MDOCK_ADAT+7, - EMU_SRC_ALICE_EMU32A, - EMU_SRC_ALICE_EMU32A+1, - EMU_SRC_ALICE_EMU32A+2, - EMU_SRC_ALICE_EMU32A+3, - EMU_SRC_ALICE_EMU32A+4, - EMU_SRC_ALICE_EMU32A+5, - EMU_SRC_ALICE_EMU32A+6, - EMU_SRC_ALICE_EMU32A+7, - EMU_SRC_ALICE_EMU32A+8, - EMU_SRC_ALICE_EMU32A+9, - EMU_SRC_ALICE_EMU32A+0xa, - EMU_SRC_ALICE_EMU32A+0xb, - EMU_SRC_ALICE_EMU32A+0xc, - EMU_SRC_ALICE_EMU32A+0xd, - EMU_SRC_ALICE_EMU32A+0xe, - EMU_SRC_ALICE_EMU32A+0xf, - EMU_SRC_ALICE_EMU32B, - EMU_SRC_ALICE_EMU32B+1, - EMU_SRC_ALICE_EMU32B+2, - EMU_SRC_ALICE_EMU32B+3, - EMU_SRC_ALICE_EMU32B+4, - EMU_SRC_ALICE_EMU32B+5, - EMU_SRC_ALICE_EMU32B+6, - EMU_SRC_ALICE_EMU32B+7, - EMU_SRC_ALICE_EMU32B+8, - EMU_SRC_ALICE_EMU32B+9, - EMU_SRC_ALICE_EMU32B+0xa, - EMU_SRC_ALICE_EMU32B+0xb, - EMU_SRC_ALICE_EMU32B+0xc, - EMU_SRC_ALICE_EMU32B+0xd, - EMU_SRC_ALICE_EMU32B+0xe, - EMU_SRC_ALICE_EMU32B+0xf, -}; - -/* - * Data destinations - physical EMU outputs. - * Each destination has an enum mixer control to choose a data source - */ -static unsigned int emu1010_output_dst[] = { - EMU_DST_DOCK_DAC1_LEFT1, /* 0 */ - EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */ - EMU_DST_DOCK_DAC2_LEFT1, /* 2 */ - EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */ - EMU_DST_DOCK_DAC3_LEFT1, /* 4 */ - EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */ - EMU_DST_DOCK_DAC4_LEFT1, /* 6 */ - EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */ - EMU_DST_DOCK_PHONES_LEFT1, /* 8 */ - EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */ - EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */ - EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */ - EMU_DST_HANA_SPDIF_LEFT1, /* 12 */ - EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */ - EMU_DST_HAMOA_DAC_LEFT1, /* 14 */ - EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */ - EMU_DST_HANA_ADAT, /* 16 */ - EMU_DST_HANA_ADAT+1, /* 17 */ - EMU_DST_HANA_ADAT+2, /* 18 */ - EMU_DST_HANA_ADAT+3, /* 19 */ - EMU_DST_HANA_ADAT+4, /* 20 */ - EMU_DST_HANA_ADAT+5, /* 21 */ - EMU_DST_HANA_ADAT+6, /* 22 */ - EMU_DST_HANA_ADAT+7, /* 23 */ -}; - -/* 1616(m) cardbus */ -static unsigned int emu1616_output_dst[] = { - EMU_DST_DOCK_DAC1_LEFT1, - EMU_DST_DOCK_DAC1_RIGHT1, - EMU_DST_DOCK_DAC2_LEFT1, - EMU_DST_DOCK_DAC2_RIGHT1, - EMU_DST_DOCK_DAC3_LEFT1, - EMU_DST_DOCK_DAC3_RIGHT1, - EMU_DST_MDOCK_SPDIF_LEFT1, - EMU_DST_MDOCK_SPDIF_RIGHT1, - EMU_DST_MDOCK_ADAT, - EMU_DST_MDOCK_ADAT+1, - EMU_DST_MDOCK_ADAT+2, - EMU_DST_MDOCK_ADAT+3, - EMU_DST_MDOCK_ADAT+4, - EMU_DST_MDOCK_ADAT+5, - EMU_DST_MDOCK_ADAT+6, - EMU_DST_MDOCK_ADAT+7, - EMU_DST_MANA_DAC_LEFT, - EMU_DST_MANA_DAC_RIGHT, -}; - -/* - * Data destinations - HANA outputs going to Alice2 (audigy) for - * capture (EMU32 + I2S links) - * Each destination has an enum mixer control to choose a data source - */ -static unsigned int emu1010_input_dst[] = { - EMU_DST_ALICE2_EMU32_0, - EMU_DST_ALICE2_EMU32_1, - EMU_DST_ALICE2_EMU32_2, - EMU_DST_ALICE2_EMU32_3, - EMU_DST_ALICE2_EMU32_4, - EMU_DST_ALICE2_EMU32_5, - EMU_DST_ALICE2_EMU32_6, - EMU_DST_ALICE2_EMU32_7, - EMU_DST_ALICE2_EMU32_8, - EMU_DST_ALICE2_EMU32_9, - EMU_DST_ALICE2_EMU32_A, - EMU_DST_ALICE2_EMU32_B, - EMU_DST_ALICE2_EMU32_C, - EMU_DST_ALICE2_EMU32_D, - EMU_DST_ALICE2_EMU32_E, - EMU_DST_ALICE2_EMU32_F, - EMU_DST_ALICE_I2S0_LEFT, - EMU_DST_ALICE_I2S0_RIGHT, - EMU_DST_ALICE_I2S1_LEFT, - EMU_DST_ALICE_I2S1_RIGHT, - EMU_DST_ALICE_I2S2_LEFT, - EMU_DST_ALICE_I2S2_RIGHT, -}; - -static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - char **items; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { - uinfo->value.enumerated.items = 49; - items = emu1616_src_texts; - } else { - uinfo->value.enumerated.items = 53; - items = emu1010_src_texts; - } - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - items[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int channel; - - channel = (kcontrol->private_value) & 0xff; - /* Limit: emu1010_output_dst, emu->emu1010.output_source */ - if (channel >= 24 || - (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && - channel >= 18)) - return -EINVAL; - ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel]; - return 0; -} - -static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - unsigned int channel; - - val = ucontrol->value.enumerated.item[0]; - if (val >= 53 || - (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && - val >= 49)) - return -EINVAL; - channel = (kcontrol->private_value) & 0xff; - /* Limit: emu1010_output_dst, emu->emu1010.output_source */ - if (channel >= 24 || - (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && - channel >= 18)) - return -EINVAL; - if (emu->emu1010.output_source[channel] == val) - return 0; - emu->emu1010.output_source[channel] = val; - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) - snd_emu1010_fpga_link_dst_src_write(emu, - emu1616_output_dst[channel], emu1616_src_regs[val]); - else - snd_emu1010_fpga_link_dst_src_write(emu, - emu1010_output_dst[channel], emu1010_src_regs[val]); - return 1; -} - -static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int channel; - - channel = (kcontrol->private_value) & 0xff; - /* Limit: emu1010_input_dst, emu->emu1010.input_source */ - if (channel >= 22) - return -EINVAL; - ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel]; - return 0; -} - -static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - unsigned int channel; - - val = ucontrol->value.enumerated.item[0]; - if (val >= 53 || - (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && - val >= 49)) - return -EINVAL; - channel = (kcontrol->private_value) & 0xff; - /* Limit: emu1010_input_dst, emu->emu1010.input_source */ - if (channel >= 22) - return -EINVAL; - if (emu->emu1010.input_source[channel] == val) - return 0; - emu->emu1010.input_source[channel] = val; - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) - snd_emu1010_fpga_link_dst_src_write(emu, - emu1010_input_dst[channel], emu1616_src_regs[val]); - else - snd_emu1010_fpga_link_dst_src_write(emu, - emu1010_input_dst[channel], emu1010_src_regs[val]); - return 1; -} - -#define EMU1010_SOURCE_OUTPUT(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = snd_emu1010_input_output_source_info, \ - .get = snd_emu1010_output_source_get, \ - .put = snd_emu1010_output_source_put, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = { - EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0), - EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1), - EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2), - EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3), - EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4), - EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5), - EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6), - EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7), - EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8), - EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9), - EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa), - EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb), - EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc), - EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd), - EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe), - EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf), - EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10), - EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11), - EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12), - EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13), - EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14), - EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15), - EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16), - EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17), -}; - - -/* 1616(m) cardbus */ -static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = { - EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0), - EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1), - EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2), - EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3), - EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4), - EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5), - EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 6), - EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 7), - EMU1010_SOURCE_OUTPUT("Dock ADAT 0 Playback Enum", 8), - EMU1010_SOURCE_OUTPUT("Dock ADAT 1 Playback Enum", 9), - EMU1010_SOURCE_OUTPUT("Dock ADAT 2 Playback Enum", 0xa), - EMU1010_SOURCE_OUTPUT("Dock ADAT 3 Playback Enum", 0xb), - EMU1010_SOURCE_OUTPUT("Dock ADAT 4 Playback Enum", 0xc), - EMU1010_SOURCE_OUTPUT("Dock ADAT 5 Playback Enum", 0xd), - EMU1010_SOURCE_OUTPUT("Dock ADAT 6 Playback Enum", 0xe), - EMU1010_SOURCE_OUTPUT("Dock ADAT 7 Playback Enum", 0xf), - EMU1010_SOURCE_OUTPUT("Mana DAC Left Playback Enum", 0x10), - EMU1010_SOURCE_OUTPUT("Mana DAC Right Playback Enum", 0x11), -}; - - -#define EMU1010_SOURCE_INPUT(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = snd_emu1010_input_output_source_info, \ - .get = snd_emu1010_input_source_get, \ - .put = snd_emu1010_input_source_put, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = { - EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0), - EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1), - EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2), - EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3), - EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4), - EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5), - EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6), - EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7), - EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8), - EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9), - EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa), - EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb), - EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc), - EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd), - EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe), - EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf), - EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10), - EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11), - EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12), - EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13), - EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14), - EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15), -}; - - - -#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info - -static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int mask = kcontrol->private_value & 0xff; - ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0; - return 0; -} - -static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int mask = kcontrol->private_value & 0xff; - unsigned int val, cache; - val = ucontrol->value.integer.value[0]; - cache = emu->emu1010.adc_pads; - if (val == 1) - cache = cache | mask; - else - cache = cache & ~mask; - if (cache != emu->emu1010.adc_pads) { - snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache ); - emu->emu1010.adc_pads = cache; - } - - return 0; -} - - - -#define EMU1010_ADC_PADS(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = snd_emu1010_adc_pads_info, \ - .get = snd_emu1010_adc_pads_get, \ - .put = snd_emu1010_adc_pads_put, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = { - EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1), - EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2), - EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3), - EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1), -}; - -#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info - -static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int mask = kcontrol->private_value & 0xff; - ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0; - return 0; -} - -static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int mask = kcontrol->private_value & 0xff; - unsigned int val, cache; - val = ucontrol->value.integer.value[0]; - cache = emu->emu1010.dac_pads; - if (val == 1) - cache = cache | mask; - else - cache = cache & ~mask; - if (cache != emu->emu1010.dac_pads) { - snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache ); - emu->emu1010.dac_pads = cache; - } - - return 0; -} - - - -#define EMU1010_DAC_PADS(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = snd_emu1010_dac_pads_info, \ - .get = snd_emu1010_dac_pads_get, \ - .put = snd_emu1010_dac_pads_put, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = { - EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1), - EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2), - EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3), - EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4), - EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1), -}; - - -static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { - "44100", "48000", "SPDIF", "ADAT" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; - - -} - -static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock; - return 0; -} - -static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.enumerated.item[0] ; - /* Limit: uinfo->value.enumerated.items = 4; */ - if (val >= 4) - return -EINVAL; - change = (emu->emu1010.internal_clock != val); - if (change) { - emu->emu1010.internal_clock = val; - switch (val) { - case 0: - /* 44100 */ - /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K ); - /* Word Clock source, Internal 44.1kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, - EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X ); - /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, - EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK ); - /* Allow DLL to settle */ - msleep(10); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - break; - case 1: - /* 48000 */ - /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); - /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, - EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X ); - /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, - EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK ); - /* Allow DLL to settle */ - msleep(10); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - break; - - case 2: /* Take clock from S/PDIF IN */ - /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); - /* Word Clock source, sync to S/PDIF input */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, - EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X ); - /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, - EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); - /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ - /* Allow DLL to settle */ - msleep(10); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - break; - - case 3: - /* Take clock from ADAT IN */ - /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); - /* Word Clock source, sync to ADAT input */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, - EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X ); - /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); - /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ - /* Allow DLL to settle */ - msleep(10); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - - - break; - } - } - return change; -} - -static struct snd_kcontrol_new snd_emu1010_internal_clock = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Clock Internal Rate", - .count = 1, - .info = snd_emu1010_internal_clock_info, - .get = snd_emu1010_internal_clock_get, - .put = snd_emu1010_internal_clock_put -}; - -static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ -#if 0 - static char *texts[4] = { - "Unknown1", "Unknown2", "Mic", "Line" - }; -#endif - static char *texts[2] = { - "Mic", "Line" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; - return 0; -} - -static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int source_id; - unsigned int ngain, ogain; - u32 gpio; - int change = 0; - unsigned long flags; - u32 source; - /* If the capture source has changed, - * update the capture volume from the cached value - * for the particular source. - */ - source_id = ucontrol->value.enumerated.item[0]; - /* Limit: uinfo->value.enumerated.items = 2; */ - /* emu->i2c_capture_volume */ - if (source_id >= 2) - return -EINVAL; - change = (emu->i2c_capture_source != source_id); - if (change) { - snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ - spin_lock_irqsave(&emu->emu_lock, flags); - gpio = inl(emu->port + A_IOCFG); - if (source_id==0) - outl(gpio | 0x4, emu->port + A_IOCFG); - else - outl(gpio & ~0x4, emu->port + A_IOCFG); - spin_unlock_irqrestore(&emu->emu_lock, flags); - - ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ - ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ - if (ngain != ogain) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); - ngain = emu->i2c_capture_volume[source_id][1]; /* Right */ - ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */ - if (ngain != ogain) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - - source = 1 << (source_id + 2); - snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */ - emu->i2c_capture_source = source_id; - } - return change; -} - -static struct snd_kcontrol_new snd_audigy_i2c_capture_source = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_audigy_i2c_capture_source_info, - .get = snd_audigy_i2c_capture_source_get, - .put = snd_audigy_i2c_capture_source_put -}; - -static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int source_id; - - source_id = kcontrol->private_value; - /* Limit: emu->i2c_capture_volume */ - /* capture_source: uinfo->value.enumerated.items = 2 */ - if (source_id >= 2) - return -EINVAL; - - ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; - ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; - return 0; -} - -static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int ogain; - unsigned int ngain; - unsigned int source_id; - int change = 0; - - source_id = kcontrol->private_value; - /* Limit: emu->i2c_capture_volume */ - /* capture_source: uinfo->value.enumerated.items = 2 */ - if (source_id >= 2) - return -EINVAL; - ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ - ngain = ucontrol->value.integer.value[0]; - if (ngain > 0xff) - return 0; - if (ogain != ngain) { - if (emu->i2c_capture_source == source_id) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); - emu->i2c_capture_volume[source_id][0] = ngain; - change = 1; - } - ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ - ngain = ucontrol->value.integer.value[1]; - if (ngain > 0xff) - return 0; - if (ogain != ngain) { - if (emu->i2c_capture_source == source_id) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - emu->i2c_capture_volume[source_id][1] = ngain; - change = 1; - } - - return change; -} - -#define I2C_VOLUME(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_audigy_i2c_volume_info, \ - .get = snd_audigy_i2c_volume_get, \ - .put = snd_audigy_i2c_volume_put, \ - .tlv = { .p = snd_audigy_db_scale2 }, \ - .private_value = chid \ -} - - -static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = { - I2C_VOLUME("Mic Capture Volume", 0), - I2C_VOLUME("Line Capture Volume", 0) -}; - -#if 0 -static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"44100", "48000", "96000"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int tmp; - unsigned long flags; - - - spin_lock_irqsave(&emu->reg_lock, flags); - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - switch (tmp & A_SPDIF_RATE_MASK) { - case A_SPDIF_44100: - ucontrol->value.enumerated.item[0] = 0; - break; - case A_SPDIF_48000: - ucontrol->value.enumerated.item[0] = 1; - break; - case A_SPDIF_96000: - ucontrol->value.enumerated.item[0] = 2; - break; - default: - ucontrol->value.enumerated.item[0] = 1; - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int change; - unsigned int reg, val, tmp; - unsigned long flags; - - switch(ucontrol->value.enumerated.item[0]) { - case 0: - val = A_SPDIF_44100; - break; - case 1: - val = A_SPDIF_48000; - break; - case 2: - val = A_SPDIF_96000; - break; - default: - val = A_SPDIF_48000; - break; - } - - - spin_lock_irqsave(&emu->reg_lock, flags); - reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - tmp = reg & ~A_SPDIF_RATE_MASK; - tmp |= val; - if ((change = (tmp != reg))) - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_audigy_spdif_output_rate = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Audigy SPDIF Output Sample Rate", - .count = 1, - .info = snd_audigy_spdif_output_rate_info, - .get = snd_audigy_spdif_output_rate_get, - .put = snd_audigy_spdif_output_rate_put -}; -#endif - -static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - int change; - unsigned int val; - unsigned long flags; - - /* Limit: emu->spdif_bits */ - if (idx >= 3) - return -EINVAL; - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - spin_lock_irqsave(&emu->reg_lock, flags); - change = val != emu->spdif_bits[idx]; - if (change) { - snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val); - emu->spdif_bits[idx] = val; - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .count = 3, - .info = snd_emu10k1_spdif_info, - .get = snd_emu10k1_spdif_get_mask -}; - -static struct snd_kcontrol_new snd_emu10k1_spdif_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .count = 3, - .info = snd_emu10k1_spdif_info, - .get = snd_emu10k1_spdif_get, - .put = snd_emu10k1_spdif_put -}; - - -static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route) -{ - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXRT1, voice, - snd_emu10k1_compose_audigy_fxrt1(route)); - snd_emu10k1_ptr_write(emu, A_FXRT2, voice, - snd_emu10k1_compose_audigy_fxrt2(route)); - } else { - snd_emu10k1_ptr_write(emu, FXRT, voice, - snd_emu10k1_compose_send_routing(route)); - } -} - -static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume) -{ - snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]); - snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]); - snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]); - snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]); - if (emu->audigy) { - unsigned int val = ((unsigned int)volume[4] << 24) | - ((unsigned int)volume[5] << 16) | - ((unsigned int)volume[6] << 8) | - (unsigned int)volume[7]; - snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val); - } -} - -/* PCM stream controls */ - -static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = emu->audigy ? 3*8 : 3*4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; - return 0; -} - -static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int voice, idx; - int num_efx = emu->audigy ? 8 : 4; - int mask = emu->audigy ? 0x3f : 0x0f; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (voice = 0; voice < 3; voice++) - for (idx = 0; idx < num_efx; idx++) - ucontrol->value.integer.value[(voice * num_efx) + idx] = - mix->send_routing[voice][idx] & mask; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int change = 0, voice, idx, val; - int num_efx = emu->audigy ? 8 : 4; - int mask = emu->audigy ? 0x3f : 0x0f; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (voice = 0; voice < 3; voice++) - for (idx = 0; idx < num_efx; idx++) { - val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask; - if (mix->send_routing[voice][idx] != val) { - mix->send_routing[voice][idx] = val; - change = 1; - } - } - if (change && mix->epcm) { - if (mix->epcm->voices[0] && mix->epcm->voices[1]) { - update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number, - &mix->send_routing[1][0]); - update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number, - &mix->send_routing[2][0]); - } else if (mix->epcm->voices[0]) { - update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number, - &mix->send_routing[0][0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_send_routing_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "EMU10K1 PCM Send Routing", - .count = 32, - .info = snd_emu10k1_send_routing_info, - .get = snd_emu10k1_send_routing_get, - .put = snd_emu10k1_send_routing_put -}; - -static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = emu->audigy ? 3*8 : 3*4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int idx; - int num_efx = emu->audigy ? 8 : 4; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < 3*num_efx; idx++) - ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int change = 0, idx, val; - int num_efx = emu->audigy ? 8 : 4; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < 3*num_efx; idx++) { - val = ucontrol->value.integer.value[idx] & 255; - if (mix->send_volume[idx/num_efx][idx%num_efx] != val) { - mix->send_volume[idx/num_efx][idx%num_efx] = val; - change = 1; - } - } - if (change && mix->epcm) { - if (mix->epcm->voices[0] && mix->epcm->voices[1]) { - update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number, - &mix->send_volume[1][0]); - update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number, - &mix->send_volume[2][0]); - } else if (mix->epcm->voices[0]) { - update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number, - &mix->send_volume[0][0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_send_volume_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "EMU10K1 PCM Send Volume", - .count = 32, - .info = snd_emu10k1_send_volume_info, - .get = snd_emu10k1_send_volume_get, - .put = snd_emu10k1_send_volume_put -}; - -static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 3; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xffff; - return 0; -} - -static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - unsigned long flags; - int idx; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < 3; idx++) - ucontrol->value.integer.value[idx] = mix->attn[idx]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int change = 0, idx, val; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < 3; idx++) { - val = ucontrol->value.integer.value[idx] & 0xffff; - if (mix->attn[idx] != val) { - mix->attn[idx] = val; - change = 1; - } - } - if (change && mix->epcm) { - if (mix->epcm->voices[0] && mix->epcm->voices[1]) { - snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]); - snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]); - } else if (mix->epcm->voices[0]) { - snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_attn_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "EMU10K1 PCM Volume", - .count = 32, - .info = snd_emu10k1_attn_info, - .get = snd_emu10k1_attn_get, - .put = snd_emu10k1_attn_put -}; - -/* Mutichannel PCM stream controls */ - -static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = emu->audigy ? 8 : 4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; - return 0; -} - -static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int idx; - int num_efx = emu->audigy ? 8 : 4; - int mask = emu->audigy ? 0x3f : 0x0f; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < num_efx; idx++) - ucontrol->value.integer.value[idx] = - mix->send_routing[0][idx] & mask; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; - int change = 0, idx, val; - int num_efx = emu->audigy ? 8 : 4; - int mask = emu->audigy ? 0x3f : 0x0f; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < num_efx; idx++) { - val = ucontrol->value.integer.value[idx] & mask; - if (mix->send_routing[0][idx] != val) { - mix->send_routing[0][idx] = val; - change = 1; - } - } - - if (change && mix->epcm) { - if (mix->epcm->voices[ch]) { - update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number, - &mix->send_routing[0][0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Multichannel PCM Send Routing", - .count = 16, - .info = snd_emu10k1_efx_send_routing_info, - .get = snd_emu10k1_efx_send_routing_get, - .put = snd_emu10k1_efx_send_routing_put -}; - -static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = emu->audigy ? 8 : 4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int idx; - int num_efx = emu->audigy ? 8 : 4; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < num_efx; idx++) - ucontrol->value.integer.value[idx] = mix->send_volume[0][idx]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; - int change = 0, idx, val; - int num_efx = emu->audigy ? 8 : 4; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < num_efx; idx++) { - val = ucontrol->value.integer.value[idx] & 255; - if (mix->send_volume[0][idx] != val) { - mix->send_volume[0][idx] = val; - change = 1; - } - } - if (change && mix->epcm) { - if (mix->epcm->voices[ch]) { - update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number, - &mix->send_volume[0][0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - - -static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Multichannel PCM Send Volume", - .count = 16, - .info = snd_emu10k1_efx_send_volume_info, - .get = snd_emu10k1_efx_send_volume_get, - .put = snd_emu10k1_efx_send_volume_put -}; - -static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xffff; - return 0; -} - -static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - unsigned long flags; - - spin_lock_irqsave(&emu->reg_lock, flags); - ucontrol->value.integer.value[0] = mix->attn[0]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; - int change = 0, val; - - spin_lock_irqsave(&emu->reg_lock, flags); - val = ucontrol->value.integer.value[0] & 0xffff; - if (mix->attn[0] != val) { - mix->attn[0] = val; - change = 1; - } - if (change && mix->epcm) { - if (mix->epcm->voices[ch]) { - snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_efx_attn_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Multichannel PCM Volume", - .count = 16, - .info = snd_emu10k1_efx_attn_info, - .get = snd_emu10k1_efx_attn_get, - .put = snd_emu10k1_efx_attn_put -}; - -#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info - -static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - if (emu->audigy) - ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0; - else - ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0; - if (emu->card_capabilities->invert_shared_spdif) - ucontrol->value.integer.value[0] = - !ucontrol->value.integer.value[0]; - - return 0; -} - -static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int reg, val, sw; - int change = 0; - - sw = ucontrol->value.integer.value[0]; - if (emu->card_capabilities->invert_shared_spdif) - sw = !sw; - spin_lock_irqsave(&emu->reg_lock, flags); - if ( emu->card_capabilities->i2c_adc) { - /* Do nothing for Audigy 2 ZS Notebook */ - } else if (emu->audigy) { - reg = inl(emu->port + A_IOCFG); - val = sw ? A_IOCFG_GPOUT0 : 0; - change = (reg & A_IOCFG_GPOUT0) != val; - if (change) { - reg &= ~A_IOCFG_GPOUT0; - reg |= val; - outl(reg | val, emu->port + A_IOCFG); - } - } - reg = inl(emu->port + HCFG); - val = sw ? HCFG_GPOUT0 : 0; - change |= (reg & HCFG_GPOUT0) != val; - if (change) { - reg &= ~HCFG_GPOUT0; - reg |= val; - outl(reg | val, emu->port + HCFG); - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "SB Live Analog/Digital Output Jack", - .info = snd_emu10k1_shared_spdif_info, - .get = snd_emu10k1_shared_spdif_get, - .put = snd_emu10k1_shared_spdif_put -}; - -static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Audigy Analog/Digital Output Jack", - .info = snd_emu10k1_shared_spdif_info, - .get = snd_emu10k1_shared_spdif_get, - .put = snd_emu10k1_shared_spdif_put -}; - -/* workaround for too low volume on Audigy due to 16bit/24bit conversion */ - -#define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info - -static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - - /* FIXME: better to use a cached version */ - val = snd_ac97_read(emu->ac97, AC97_REC_GAIN); - ucontrol->value.integer.value[0] = !!val; - return 0; -} - -static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - - if (ucontrol->value.integer.value[0]) - val = 0x0f0f; - else - val = 0; - return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val); -} - -static struct snd_kcontrol_new snd_audigy_capture_boost __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Capture Boost", - .info = snd_audigy_capture_boost_info, - .get = snd_audigy_capture_boost_get, - .put = snd_audigy_capture_boost_put -}; - - -/* - */ -static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct snd_emu10k1 *emu = ac97->private_data; - emu->ac97 = NULL; -} - -/* - */ -static int remove_ctl(struct snd_card *card, const char *name) -{ - struct snd_ctl_elem_id id; - memset(&id, 0, sizeof(id)); - strcpy(id.name, name); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_remove_id(card, &id); -} - -static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) -{ - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - strcpy(sid.name, name); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_find_id(card, &sid); -} - -static int rename_ctl(struct snd_card *card, const char *src, const char *dst) -{ - struct snd_kcontrol *kctl = ctl_find(card, src); - if (kctl) { - strcpy(kctl->id.name, dst); - return 0; - } - return -ENOENT; -} - -int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, - int pcm_device, int multi_device) -{ - int err, pcm; - struct snd_kcontrol *kctl; - struct snd_card *card = emu->card; - char **c; - static char *emu10k1_remove_ctls[] = { - /* no AC97 mono, surround, center/lfe */ - "Master Mono Playback Switch", - "Master Mono Playback Volume", - "PCM Out Path & Mute", - "Mono Output Select", - "Surround Playback Switch", - "Surround Playback Volume", - "Center Playback Switch", - "Center Playback Volume", - "LFE Playback Switch", - "LFE Playback Volume", - NULL - }; - static char *emu10k1_rename_ctls[] = { - "Surround Digital Playback Volume", "Surround Playback Volume", - "Center Digital Playback Volume", "Center Playback Volume", - "LFE Digital Playback Volume", "LFE Playback Volume", - NULL - }; - static char *audigy_remove_ctls[] = { - /* Master/PCM controls on ac97 of Audigy has no effect */ - /* On the Audigy2 the AC97 playback is piped into - * the Philips ADC for 24bit capture */ - "PCM Playback Switch", - "PCM Playback Volume", - "Master Mono Playback Switch", - "Master Mono Playback Volume", - "Master Playback Switch", - "Master Playback Volume", - "PCM Out Path & Mute", - "Mono Output Select", - /* remove unused AC97 capture controls */ - "Capture Source", - "Capture Switch", - "Capture Volume", - "Mic Select", - "Video Playback Switch", - "Video Playback Volume", - "Mic Playback Switch", - "Mic Playback Volume", - NULL - }; - static char *audigy_rename_ctls[] = { - /* use conventional names */ - "Wave Playback Volume", "PCM Playback Volume", - /* "Wave Capture Volume", "PCM Capture Volume", */ - "Wave Master Playback Volume", "Master Playback Volume", - "AMic Playback Volume", "Mic Playback Volume", - NULL - }; - static char *audigy_rename_ctls_i2c_adc[] = { - //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume", - "Line Capture Volume", "Analog Mix Capture Volume", - "Wave Playback Volume", "OLD PCM Playback Volume", - "Wave Master Playback Volume", "Master Playback Volume", - "AMic Playback Volume", "Old Mic Playback Volume", - "CD Capture Volume", "IEC958 Optical Capture Volume", - NULL - }; - static char *audigy_remove_ctls_i2c_adc[] = { - /* On the Audigy2 ZS Notebook - * Capture via WM8775 */ - "Mic Capture Volume", - "Analog Mix Capture Volume", - "Aux Capture Volume", - "IEC958 Optical Capture Volume", - NULL - }; - static char *audigy_remove_ctls_1361t_adc[] = { - /* On the Audigy2 the AC97 playback is piped into - * the Philips ADC for 24bit capture */ - "PCM Playback Switch", - "PCM Playback Volume", - "Master Mono Playback Switch", - "Master Mono Playback Volume", - "Capture Source", - "Capture Switch", - "Capture Volume", - "Mic Capture Volume", - "Headphone Playback Switch", - "Headphone Playback Volume", - "3D Control - Center", - "3D Control - Depth", - "3D Control - Switch", - "Line2 Playback Volume", - "Line2 Capture Volume", - NULL - }; - static char *audigy_rename_ctls_1361t_adc[] = { - "Master Playback Switch", "Master Capture Switch", - "Master Playback Volume", "Master Capture Volume", - "Wave Master Playback Volume", "Master Playback Volume", - "Beep Playback Switch", "Beep Capture Switch", - "Beep Playback Volume", "Beep Capture Volume", - "Phone Playback Switch", "Phone Capture Switch", - "Phone Playback Volume", "Phone Capture Volume", - "Mic Playback Switch", "Mic Capture Switch", - "Mic Playback Volume", "Mic Capture Volume", - "Line Playback Switch", "Line Capture Switch", - "Line Playback Volume", "Line Capture Volume", - "CD Playback Switch", "CD Capture Switch", - "CD Playback Volume", "CD Capture Volume", - "Aux Playback Switch", "Aux Capture Switch", - "Aux Playback Volume", "Aux Capture Volume", - "Video Playback Switch", "Video Capture Switch", - "Video Playback Volume", "Video Capture Volume", - - NULL - }; - - if (emu->card_capabilities->ac97_chip) { - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = snd_emu10k1_ac97_write, - .read = snd_emu10k1_ac97_read, - }; - - if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) - return err; - pbus->no_vra = 1; /* we don't need VRA */ - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = emu; - ac97.private_free = snd_emu10k1_mixer_free_ac97; - ac97.scaps = AC97_SCAP_NO_SPDIF; - if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) { - if (emu->card_capabilities->ac97_chip == 1) - return err; - snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n"); - snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n"); - snd_device_free(emu->card, pbus); - goto no_ac97; /* FIXME: get rid of ugly gotos.. */ - } - if (emu->audigy) { - /* set master volume to 0 dB */ - snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); - /* set capture source to mic */ - snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); - if (emu->card_capabilities->adc_1361t) - c = audigy_remove_ctls_1361t_adc; - else - c = audigy_remove_ctls; - } else { - /* - * Credits for cards based on STAC9758: - * James Courtier-Dutton - * Voluspa - */ - if (emu->ac97->id == AC97_ID_STAC9758) { - emu->rear_ac97 = 1; - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT); - snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202); - remove_ctl(card,"Front Playback Volume"); - remove_ctl(card,"Front Playback Switch"); - } - /* remove unused AC97 controls */ - snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202); - snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202); - c = emu10k1_remove_ctls; - } - for (; *c; c++) - remove_ctl(card, *c); - } else if (emu->card_capabilities->i2c_adc) { - c = audigy_remove_ctls_i2c_adc; - for (; *c; c++) - remove_ctl(card, *c); - } else { - no_ac97: - if (emu->card_capabilities->ecard) - strcpy(emu->card->mixername, "EMU APS"); - else if (emu->audigy) - strcpy(emu->card->mixername, "SB Audigy"); - else - strcpy(emu->card->mixername, "Emu10k1"); - } - - if (emu->audigy) - if (emu->card_capabilities->adc_1361t) - c = audigy_rename_ctls_1361t_adc; - else if (emu->card_capabilities->i2c_adc) - c = audigy_rename_ctls_i2c_adc; - else - c = audigy_rename_ctls; - else - c = emu10k1_rename_ctls; - for (; *c; c += 2) - rename_ctl(card, c[0], c[1]); - - if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */ - remove_ctl(card, "Center Playback Volume"); - remove_ctl(card, "LFE Playback Volume"); - remove_ctl(card, "Wave Center Playback Volume"); - remove_ctl(card, "Wave LFE Playback Volume"); - } - if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ - rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); - rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); - rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume"); - rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume"); - remove_ctl(card, "Headphone Playback Switch"); - remove_ctl(card, "Headphone Playback Volume"); - remove_ctl(card, "3D Control - Center"); - remove_ctl(card, "3D Control - Depth"); - remove_ctl(card, "3D Control - Switch"); - } - if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - - if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - - if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - - if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - - /* initialize the routing and volume table for each pcm playback stream */ - for (pcm = 0; pcm < 32; pcm++) { - struct snd_emu10k1_pcm_mixer *mix; - int v; - - mix = &emu->pcm_mixer[pcm]; - mix->epcm = NULL; - - for (v = 0; v < 4; v++) - mix->send_routing[0][v] = - mix->send_routing[1][v] = - mix->send_routing[2][v] = v; - - memset(&mix->send_volume, 0, sizeof(mix->send_volume)); - mix->send_volume[0][0] = mix->send_volume[0][1] = - mix->send_volume[1][0] = mix->send_volume[2][1] = 255; - - mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff; - } - - /* initialize the routing and volume table for the multichannel playback stream */ - for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) { - struct snd_emu10k1_pcm_mixer *mix; - int v; - - mix = &emu->efx_pcm_mixer[pcm]; - mix->epcm = NULL; - - mix->send_routing[0][0] = pcm; - mix->send_routing[0][1] = (pcm == 0) ? 1 : 0; - for (v = 0; v < 2; v++) - mix->send_routing[0][2+v] = 13+v; - if (emu->audigy) - for (v = 0; v < 4; v++) - mix->send_routing[0][4+v] = 60+v; - - memset(&mix->send_volume, 0, sizeof(mix->send_volume)); - mix->send_volume[0][0] = 255; - - mix->attn[0] = 0xffff; - } - - if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */ - /* sb live! and audigy */ - if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) - return -ENOMEM; - if (!emu->audigy) - kctl->id.device = emu->pcm_efx->device; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL) - return -ENOMEM; - if (!emu->audigy) - kctl->id.device = emu->pcm_efx->device; - if ((err = snd_ctl_add(card, kctl))) - return err; - } - - if (emu->card_capabilities->emu_model) { - ; /* Disable the snd_audigy_spdif_shared_spdif */ - } else if (emu->audigy) { - if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; -#if 0 - if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; -#endif - } else if (! emu->card_capabilities->ecard) { - /* sb live! */ - if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - } - if (emu->card_capabilities->ca0151_chip) { /* P16V */ - if ((err = snd_p16v_mixer(emu))) - return err; - } - - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { - /* 1616(m) cardbus */ - int i; - - for (i = 0; i < ARRAY_SIZE(snd_emu1616_output_enum_ctls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1616_output_enum_ctls[i], - emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], - emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads) - 2; i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_adc_pads[i], emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads) - 2; i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_dac_pads[i], emu)); - if (err < 0) - return err; - } - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_internal_clock, emu)); - if (err < 0) - return err; - - } else if (emu->card_capabilities->emu_model) { - /* all other e-mu cards for now */ - int i; - - for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], - emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], - emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_adc_pads[i], emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_dac_pads[i], emu)); - if (err < 0) - return err; - } - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_internal_clock, emu)); - if (err < 0) - return err; - } - - if ( emu->card_capabilities->i2c_adc) { - int i; - - err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu)); - if (err < 0) - return err; - - for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu)); - if (err < 0) - return err; - } - } - - if (emu->card_capabilities->ac97_chip && emu->audigy) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost, - emu)); - if (err < 0) - return err; - } - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c b/ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c deleted file mode 100644 index bab56482..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of EMU10K1 MPU-401 in UART mode - * - * - * 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 - -#define EMU10K1_MIDI_MODE_INPUT (1<<0) -#define EMU10K1_MIDI_MODE_OUTPUT (1<<1) - -static inline unsigned char mpu401_read(struct snd_emu10k1 *emu, - struct snd_emu10k1_midi *mpu, int idx) -{ - if (emu->audigy) - return (unsigned char)snd_emu10k1_ptr_read(emu, mpu->port + idx, 0); - else - return inb(emu->port + mpu->port + idx); -} - -static inline void mpu401_write(struct snd_emu10k1 *emu, - struct snd_emu10k1_midi *mpu, int data, int idx) -{ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, mpu->port + idx, 0, data); - else - outb(data, emu->port + mpu->port + idx); -} - -#define mpu401_write_data(emu, mpu, data) mpu401_write(emu, mpu, data, 0) -#define mpu401_write_cmd(emu, mpu, data) mpu401_write(emu, mpu, data, 1) -#define mpu401_read_data(emu, mpu) mpu401_read(emu, mpu, 0) -#define mpu401_read_stat(emu, mpu) mpu401_read(emu, mpu, 1) - -#define mpu401_input_avail(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x80)) -#define mpu401_output_ready(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x40)) - -#define MPU401_RESET 0xff -#define MPU401_ENTER_UART 0x3f -#define MPU401_ACK 0xfe - -static void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mpu) -{ - int timeout = 100000; - for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--) - mpu401_read_data(emu, mpu); -#ifdef CONFIG_SND_DEBUG - if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", mpu401_read_stat(emu, mpu)); -#endif -} - -/* - - */ - -static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status) -{ - unsigned char byte; - - if (midi->rmidi == NULL) { - snd_emu10k1_intr_disable(emu, midi->tx_enable | midi->rx_enable); - return; - } - - spin_lock(&midi->input_lock); - if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - mpu401_clear_rx(emu, midi); - } else { - byte = mpu401_read_data(emu, midi); - if (midi->substream_input) - snd_rawmidi_receive(midi->substream_input, &byte, 1); - } - } - spin_unlock(&midi->input_lock); - - spin_lock(&midi->output_lock); - if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { - if (midi->substream_output && - snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { - mpu401_write_data(emu, midi, byte); - } else { - snd_emu10k1_intr_disable(emu, midi->tx_enable); - } - } - spin_unlock(&midi->output_lock); -} - -static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status) -{ - do_emu10k1_midi_interrupt(emu, &emu->midi, status); -} - -static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status) -{ - do_emu10k1_midi_interrupt(emu, &emu->midi2, status); -} - -static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack) -{ - unsigned long flags; - int timeout, ok; - - spin_lock_irqsave(&midi->input_lock, flags); - mpu401_write_data(emu, midi, 0x00); - /* mpu401_clear_rx(emu, midi); */ - - mpu401_write_cmd(emu, midi, cmd); - if (ack) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (mpu401_input_avail(emu, midi)) { - if (mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; - } - } - if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; - } else { - ok = 1; - } - spin_unlock_irqrestore(&midi->input_lock, flags); - if (!ok) { - snd_printk(KERN_ERR "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", - cmd, emu->port, - mpu401_read_stat(emu, midi), - mpu401_read_data(emu, midi)); - return 1; - } - return 0; -} - -static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT; - midi->substream_input = substream; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; - -error_out: - return -EIO; -} - -static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT; - midi->substream_output = substream; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; - -error_out: - return -EIO; -} - -static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - int err = 0; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1_intr_disable(emu, midi->rx_enable); - midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT; - midi->substream_input = NULL; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return err; -} - -static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - int err = 0; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1_intr_disable(emu, midi->tx_enable); - midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; - midi->substream_output = NULL; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return err; -} - -static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return; - - if (up) - snd_emu10k1_intr_enable(emu, midi->rx_enable); - else - snd_emu10k1_intr_disable(emu, midi->rx_enable); -} - -static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return; - - if (up) { - int max = 4; - unsigned char byte; - - /* try to send some amount of bytes here before interrupts */ - spin_lock_irqsave(&midi->output_lock, flags); - while (max > 0) { - if (mpu401_output_ready(emu, midi)) { - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || - snd_rawmidi_transmit(substream, &byte, 1) != 1) { - /* no more data */ - spin_unlock_irqrestore(&midi->output_lock, flags); - return; - } - mpu401_write_data(emu, midi, byte); - max--; - } else { - break; - } - } - spin_unlock_irqrestore(&midi->output_lock, flags); - snd_emu10k1_intr_enable(emu, midi->tx_enable); - } else { - snd_emu10k1_intr_disable(emu, midi->tx_enable); - } -} - -/* - - */ - -static struct snd_rawmidi_ops snd_emu10k1_midi_output = -{ - .open = snd_emu10k1_midi_output_open, - .close = snd_emu10k1_midi_output_close, - .trigger = snd_emu10k1_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_emu10k1_midi_input = -{ - .open = snd_emu10k1_midi_input_open, - .close = snd_emu10k1_midi_input_close, - .trigger = snd_emu10k1_midi_input_trigger, -}; - -static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi) -{ - struct snd_emu10k1_midi *midi = rmidi->private_data; - midi->interrupt = NULL; - midi->rmidi = NULL; -} - -static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name) -{ - struct snd_rawmidi *rmidi; - int err; - - if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0) - return err; - midi->emu = emu; - spin_lock_init(&midi->open_lock); - spin_lock_init(&midi->input_lock); - spin_lock_init(&midi->output_lock); - strcpy(rmidi->name, name); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = midi; - rmidi->private_free = snd_emu10k1_midi_free; - midi->rmidi = rmidi; - return 0; -} - -int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu) -{ - struct snd_emu10k1_midi *midi = &emu->midi; - int err; - - if ((err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)")) < 0) - return err; - - midi->tx_enable = INTE_MIDITXENABLE; - midi->rx_enable = INTE_MIDIRXENABLE; - midi->port = MUDATA; - midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; - midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; - midi->interrupt = snd_emu10k1_midi_interrupt; - return 0; -} - -int __devinit snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu) -{ - struct snd_emu10k1_midi *midi; - int err; - - midi = &emu->midi; - if ((err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)")) < 0) - return err; - - midi->tx_enable = INTE_MIDITXENABLE; - midi->rx_enable = INTE_MIDIRXENABLE; - midi->port = A_MUDATA1; - midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; - midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; - midi->interrupt = snd_emu10k1_midi_interrupt; - - midi = &emu->midi2; - if ((err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2")) < 0) - return err; - - midi->tx_enable = INTE_A_MIDITXENABLE2; - midi->rx_enable = INTE_A_MIDIRXENABLE2; - midi->port = A_MUDATA2; - midi->ipr_tx = IPR_A_MIDITRANSBUFEMPTY2; - midi->ipr_rx = IPR_A_MIDIRECVBUFEMPTY2; - midi->interrupt = snd_emu10k1_midi_interrupt2; - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c b/ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c deleted file mode 100644 index e22b8e2b..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c +++ /dev/null @@ -1,1870 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips / PCM routines - * Multichannel PCM support Copyright (c) Lee Revell - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 - -static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu, - struct snd_emu10k1_voice *voice) -{ - struct snd_emu10k1_pcm *epcm; - - if ((epcm = voice->epcm) == NULL) - return; - if (epcm->substream == NULL) - return; -#if 0 - printk(KERN_DEBUG "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", - epcm->substream->runtime->hw->pointer(emu, epcm->substream), - snd_pcm_lib_period_bytes(epcm->substream), - snd_pcm_lib_buffer_bytes(epcm->substream)); -#endif - snd_pcm_period_elapsed(epcm->substream); -} - -static void snd_emu10k1_pcm_ac97adc_interrupt(struct snd_emu10k1 *emu, - unsigned int status) -{ -#if 0 - if (status & IPR_ADCBUFHALFFULL) { - if (emu->pcm_capture_substream->runtime->mode == SNDRV_PCM_MODE_FRAME) - return; - } -#endif - snd_pcm_period_elapsed(emu->pcm_capture_substream); -} - -static void snd_emu10k1_pcm_ac97mic_interrupt(struct snd_emu10k1 *emu, - unsigned int status) -{ -#if 0 - if (status & IPR_MICBUFHALFFULL) { - if (emu->pcm_capture_mic_substream->runtime->mode == SNDRV_PCM_MODE_FRAME) - return; - } -#endif - snd_pcm_period_elapsed(emu->pcm_capture_mic_substream); -} - -static void snd_emu10k1_pcm_efx_interrupt(struct snd_emu10k1 *emu, - unsigned int status) -{ -#if 0 - if (status & IPR_EFXBUFHALFFULL) { - if (emu->pcm_capture_efx_substream->runtime->mode == SNDRV_PCM_MODE_FRAME) - return; - } -#endif - snd_pcm_period_elapsed(emu->pcm_capture_efx_substream); -} - -static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int ptr; - - if (!epcm->running) - return 0; - ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff; - ptr += runtime->buffer_size; - ptr -= epcm->ccca_start_addr; - ptr %= runtime->buffer_size; - - return ptr; -} - -static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voices) -{ - int err, i; - - if (epcm->voices[1] != NULL && voices < 2) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]); - epcm->voices[1] = NULL; - } - for (i = 0; i < voices; i++) { - if (epcm->voices[i] == NULL) - break; - } - if (i == voices) - return 0; /* already allocated */ - - for (i = 0; i < ARRAY_SIZE(epcm->voices); i++) { - if (epcm->voices[i]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); - epcm->voices[i] = NULL; - } - } - err = snd_emu10k1_voice_alloc(epcm->emu, - epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX, - voices, - &epcm->voices[0]); - - if (err < 0) - return err; - epcm->voices[0]->epcm = epcm; - if (voices > 1) { - for (i = 1; i < voices; i++) { - epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i]; - epcm->voices[i]->epcm = epcm; - } - } - if (epcm->extra == NULL) { - err = snd_emu10k1_voice_alloc(epcm->emu, - epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX, - 1, - &epcm->extra); - if (err < 0) { - /* - printk(KERN_DEBUG "pcm_channel_alloc: " - "failed extra: voices=%d, frame=%d\n", - voices, frame); - */ - for (i = 0; i < voices; i++) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); - epcm->voices[i] = NULL; - } - return err; - } - epcm->extra->epcm = epcm; - epcm->extra->interrupt = snd_emu10k1_pcm_interrupt; - } - return 0; -} - -static unsigned int capture_period_sizes[31] = { - 384, 448, 512, 640, - 384*2, 448*2, 512*2, 640*2, - 384*4, 448*4, 512*4, 640*4, - 384*8, 448*8, 512*8, 640*8, - 384*16, 448*16, 512*16, 640*16, - 384*32, 448*32, 512*32, 640*32, - 384*64, 448*64, 512*64, 640*64, - 384*128,448*128,512*128 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_capture_period_sizes = { - .count = 31, - .list = capture_period_sizes, - .mask = 0 -}; - -static unsigned int capture_rates[8] = { - 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_capture_rates = { - .count = 8, - .list = capture_rates, - .mask = 0 -}; - -static unsigned int snd_emu10k1_capture_rate_reg(unsigned int rate) -{ - switch (rate) { - case 8000: return ADCCR_SAMPLERATE_8; - case 11025: return ADCCR_SAMPLERATE_11; - case 16000: return ADCCR_SAMPLERATE_16; - case 22050: return ADCCR_SAMPLERATE_22; - case 24000: return ADCCR_SAMPLERATE_24; - case 32000: return ADCCR_SAMPLERATE_32; - case 44100: return ADCCR_SAMPLERATE_44; - case 48000: return ADCCR_SAMPLERATE_48; - default: - snd_BUG(); - return ADCCR_SAMPLERATE_8; - } -} - -static unsigned int snd_emu10k1_audigy_capture_rate_reg(unsigned int rate) -{ - switch (rate) { - case 8000: return A_ADCCR_SAMPLERATE_8; - case 11025: return A_ADCCR_SAMPLERATE_11; - case 12000: return A_ADCCR_SAMPLERATE_12; /* really supported? */ - case 16000: return ADCCR_SAMPLERATE_16; - case 22050: return ADCCR_SAMPLERATE_22; - case 24000: return ADCCR_SAMPLERATE_24; - case 32000: return ADCCR_SAMPLERATE_32; - case 44100: return ADCCR_SAMPLERATE_44; - case 48000: return ADCCR_SAMPLERATE_48; - default: - snd_BUG(); - return A_ADCCR_SAMPLERATE_8; - } -} - -static unsigned int emu10k1_calc_pitch_target(unsigned int rate) -{ - unsigned int pitch_target; - - pitch_target = (rate << 8) / 375; - pitch_target = (pitch_target >> 1) + (pitch_target & 1); - return pitch_target; -} - -#define PITCH_48000 0x00004000 -#define PITCH_96000 0x00008000 -#define PITCH_85000 0x00007155 -#define PITCH_80726 0x00006ba2 -#define PITCH_67882 0x00005a82 -#define PITCH_57081 0x00004c1c - -static unsigned int emu10k1_select_interprom(unsigned int pitch_target) -{ - if (pitch_target == PITCH_48000) - return CCCA_INTERPROM_0; - else if (pitch_target < PITCH_48000) - return CCCA_INTERPROM_1; - else if (pitch_target >= PITCH_96000) - return CCCA_INTERPROM_0; - else if (pitch_target >= PITCH_85000) - return CCCA_INTERPROM_6; - else if (pitch_target >= PITCH_80726) - return CCCA_INTERPROM_5; - else if (pitch_target >= PITCH_67882) - return CCCA_INTERPROM_4; - else if (pitch_target >= PITCH_57081) - return CCCA_INTERPROM_3; - else - return CCCA_INTERPROM_2; -} - -/* - * calculate cache invalidate size - * - * stereo: channel is stereo - * w_16: using 16bit samples - * - * returns: cache invalidate size in samples - */ -static inline int emu10k1_ccis(int stereo, int w_16) -{ - if (w_16) { - return stereo ? 24 : 26; - } else { - return stereo ? 24*2 : 26*2; - } -} - -static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, - int master, int extra, - struct snd_emu10k1_voice *evoice, - unsigned int start_addr, - unsigned int end_addr, - struct snd_emu10k1_pcm_mixer *mix) -{ - struct snd_pcm_substream *substream = evoice->epcm->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int silent_page, tmp; - int voice, stereo, w_16; - unsigned char attn, send_amount[8]; - unsigned char send_routing[8]; - unsigned long flags; - unsigned int pitch_target; - unsigned int ccis; - - voice = evoice->number; - stereo = runtime->channels == 2; - w_16 = snd_pcm_format_width(runtime->format) == 16; - - if (!extra && stereo) { - start_addr >>= 1; - end_addr >>= 1; - } - if (w_16) { - start_addr >>= 1; - end_addr >>= 1; - } - - spin_lock_irqsave(&emu->reg_lock, flags); - - /* volume parameters */ - if (extra) { - attn = 0; - memset(send_routing, 0, sizeof(send_routing)); - send_routing[0] = 0; - send_routing[1] = 1; - send_routing[2] = 2; - send_routing[3] = 3; - memset(send_amount, 0, sizeof(send_amount)); - } else { - /* mono, left, right (master voice = left) */ - tmp = stereo ? (master ? 1 : 2) : 0; - memcpy(send_routing, &mix->send_routing[tmp][0], 8); - memcpy(send_amount, &mix->send_volume[tmp][0], 8); - } - - ccis = emu10k1_ccis(stereo, w_16); - - if (master) { - evoice->epcm->ccca_start_addr = start_addr + ccis; - if (extra) { - start_addr += ccis; - end_addr += ccis + emu->delay_pcm_irq; - } - if (stereo && !extra) { - snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK); - snd_emu10k1_ptr_write(emu, CPF, (voice + 1), CPF_STEREO_MASK); - } else { - snd_emu10k1_ptr_write(emu, CPF, voice, 0); - } - } - - /* setup routing */ - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXRT1, voice, - snd_emu10k1_compose_audigy_fxrt1(send_routing)); - snd_emu10k1_ptr_write(emu, A_FXRT2, voice, - snd_emu10k1_compose_audigy_fxrt2(send_routing)); - snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, - ((unsigned int)send_amount[4] << 24) | - ((unsigned int)send_amount[5] << 16) | - ((unsigned int)send_amount[6] << 8) | - (unsigned int)send_amount[7]); - } else - snd_emu10k1_ptr_write(emu, FXRT, voice, - snd_emu10k1_compose_send_routing(send_routing)); - /* Stop CA */ - /* Assumption that PT is already 0 so no harm overwriting */ - snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); - snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); - snd_emu10k1_ptr_write(emu, PSST, voice, - (start_addr + (extra ? emu->delay_pcm_irq : 0)) | - (send_amount[2] << 24)); - if (emu->card_capabilities->emu_model) - pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ - else - pitch_target = emu10k1_calc_pitch_target(runtime->rate); - if (extra) - snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr | - emu10k1_select_interprom(pitch_target) | - (w_16 ? 0 : CCCA_8BITSELECT)); - else - snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) | - emu10k1_select_interprom(pitch_target) | - (w_16 ? 0 : CCCA_8BITSELECT)); - /* Clear filter delay memory */ - snd_emu10k1_ptr_write(emu, Z1, voice, 0); - snd_emu10k1_ptr_write(emu, Z2, voice, 0); - /* invalidate maps */ - silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK; - snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); - snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); - /* modulation envelope */ - snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff); - snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff); - snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0); - snd_emu10k1_ptr_write(emu, DCYSUSM, voice, 0x007f); - snd_emu10k1_ptr_write(emu, LFOVAL1, voice, 0x8000); - snd_emu10k1_ptr_write(emu, LFOVAL2, voice, 0x8000); - snd_emu10k1_ptr_write(emu, FMMOD, voice, 0); - snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0); - snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0); - snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000); - /* volume envelope */ - snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f); - snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000); - /* filter envelope */ - snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f); - /* pitch envelope */ - snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0); - - spin_unlock_irqrestore(&emu->reg_lock, flags); -} - -static int snd_emu10k1_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int err; - - if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0) - return err; - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - if (err > 0) { /* change */ - int mapped; - if (epcm->memblk != NULL) - snd_emu10k1_free_pages(emu, epcm->memblk); - epcm->memblk = snd_emu10k1_alloc_pages(emu, substream); - epcm->start_addr = 0; - if (! epcm->memblk) - return -ENOMEM; - mapped = ((struct snd_emu10k1_memblk *)epcm->memblk)->mapped_page; - if (mapped < 0) - return -ENOMEM; - epcm->start_addr = mapped << PAGE_SHIFT; - } - return 0; -} - -static int snd_emu10k1_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm; - - if (runtime->private_data == NULL) - return 0; - epcm = runtime->private_data; - if (epcm->extra) { - snd_emu10k1_voice_free(epcm->emu, epcm->extra); - epcm->extra = NULL; - } - if (epcm->voices[1]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]); - epcm->voices[1] = NULL; - } - if (epcm->voices[0]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]); - epcm->voices[0] = NULL; - } - if (epcm->memblk) { - snd_emu10k1_free_pages(emu, epcm->memblk); - epcm->memblk = NULL; - epcm->start_addr = 0; - } - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_emu10k1_efx_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm; - int i; - - if (runtime->private_data == NULL) - return 0; - epcm = runtime->private_data; - if (epcm->extra) { - snd_emu10k1_voice_free(epcm->emu, epcm->extra); - epcm->extra = NULL; - } - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - if (epcm->voices[i]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); - epcm->voices[i] = NULL; - } - } - if (epcm->memblk) { - snd_emu10k1_free_pages(emu, epcm->memblk); - epcm->memblk = NULL; - epcm->start_addr = 0; - } - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_emu10k1_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int start_addr, end_addr; - - start_addr = epcm->start_addr; - end_addr = snd_pcm_lib_period_bytes(substream); - if (runtime->channels == 2) { - start_addr >>= 1; - end_addr >>= 1; - } - end_addr += start_addr; - snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, - start_addr, end_addr, NULL); - start_addr = epcm->start_addr; - end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); - snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0], - start_addr, end_addr, - &emu->pcm_mixer[substream->number]); - if (epcm->voices[1]) - snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[1], - start_addr, end_addr, - &emu->pcm_mixer[substream->number]); - return 0; -} - -static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int start_addr, end_addr; - unsigned int channel_size; - int i; - - start_addr = epcm->start_addr; - end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); - - /* - * the kX driver leaves some space between voices - */ - channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK; - - snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, - start_addr, start_addr + (channel_size / 2), NULL); - - /* only difference with the master voice is we use it for the pointer */ - snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0], - start_addr, start_addr + channel_size, - &emu->efx_pcm_mixer[0]); - - start_addr += channel_size; - for (i = 1; i < NUM_EFX_PLAYBACK; i++) { - snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[i], - start_addr, start_addr + channel_size, - &emu->efx_pcm_mixer[i]); - start_addr += channel_size; - } - - return 0; -} - -static struct snd_pcm_hardware snd_emu10k1_efx_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = NUM_EFX_PLAYBACK, - .channels_max = NUM_EFX_PLAYBACK, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 64, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static int snd_emu10k1_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_emu10k1_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_emu10k1_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int idx; - - /* zeroing the buffer size will stop capture */ - snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0); - switch (epcm->type) { - case CAPTURE_AC97ADC: - snd_emu10k1_ptr_write(emu, ADCCR, 0, 0); - break; - case CAPTURE_EFX: - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0); - snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0); - } else - snd_emu10k1_ptr_write(emu, FXWC, 0, 0); - break; - default: - break; - } - snd_emu10k1_ptr_write(emu, epcm->capture_ba_reg, 0, runtime->dma_addr); - epcm->capture_bufsize = snd_pcm_lib_buffer_bytes(substream); - epcm->capture_bs_val = 0; - for (idx = 0; idx < 31; idx++) { - if (capture_period_sizes[idx] == epcm->capture_bufsize) { - epcm->capture_bs_val = idx + 1; - break; - } - } - if (epcm->capture_bs_val == 0) { - snd_BUG(); - epcm->capture_bs_val++; - } - if (epcm->type == CAPTURE_AC97ADC) { - epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE; - if (runtime->channels > 1) - epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE; - epcm->capture_cr_val |= emu->audigy ? - snd_emu10k1_audigy_capture_rate_reg(runtime->rate) : - snd_emu10k1_capture_rate_reg(runtime->rate); - } - return 0; -} - -static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int extra, struct snd_emu10k1_voice *evoice) -{ - struct snd_pcm_runtime *runtime; - unsigned int voice, stereo, i, ccis, cra = 64, cs, sample; - - if (evoice == NULL) - return; - runtime = evoice->epcm->substream->runtime; - voice = evoice->number; - stereo = (!extra && runtime->channels == 2); - sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080; - ccis = emu10k1_ccis(stereo, sample == 0); - /* set cs to 2 * number of cache registers beside the invalidated */ - cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1; - if (cs > 16) cs = 16; - for (i = 0; i < cs; i++) { - snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample); - if (stereo) { - snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample); - } - } - /* reset cache */ - snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0); - snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra); - if (stereo) { - snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0); - snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra); - } - /* fill cache */ - snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis); - if (stereo) { - snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis); - } -} - -static void snd_emu10k1_playback_prepare_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice, - int master, int extra, - struct snd_emu10k1_pcm_mixer *mix) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - unsigned int attn, vattn; - unsigned int voice, tmp; - - if (evoice == NULL) /* skip second voice for mono */ - return; - substream = evoice->epcm->substream; - runtime = substream->runtime; - voice = evoice->number; - - attn = extra ? 0 : 0x00ff; - tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0; - vattn = mix != NULL ? (mix->attn[tmp] << 16) : 0; - snd_emu10k1_ptr_write(emu, IFATN, voice, attn); - snd_emu10k1_ptr_write(emu, VTFT, voice, vattn | 0xffff); - snd_emu10k1_ptr_write(emu, CVCF, voice, vattn | 0xffff); - snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f); - snd_emu10k1_voice_clear_loop_stop(emu, voice); -} - -static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice, int master, int extra) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - unsigned int voice, pitch, pitch_target; - - if (evoice == NULL) /* skip second voice for mono */ - return; - substream = evoice->epcm->substream; - runtime = substream->runtime; - voice = evoice->number; - - pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8; - if (emu->card_capabilities->emu_model) - pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ - else - pitch_target = emu10k1_calc_pitch_target(runtime->rate); - snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target); - if (master || evoice->epcm->type == PLAYBACK_EFX) - snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target); - snd_emu10k1_ptr_write(emu, IP, voice, pitch); - if (extra) - snd_emu10k1_voice_intr_enable(emu, voice); -} - -static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice) -{ - unsigned int voice; - - if (evoice == NULL) - return; - voice = evoice->number; - snd_emu10k1_voice_intr_disable(emu, voice); - snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, 0); - snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, 0); - snd_emu10k1_ptr_write(emu, IFATN, voice, 0xffff); - snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff); - snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff); - snd_emu10k1_ptr_write(emu, IP, voice, 0); -} - -static inline void snd_emu10k1_playback_mangle_extra(struct snd_emu10k1 *emu, - struct snd_emu10k1_pcm *epcm, - struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) -{ - unsigned int ptr, period_pos; - - /* try to sychronize the current position for the interrupt - source voice */ - period_pos = runtime->status->hw_ptr - runtime->hw_ptr_interrupt; - period_pos %= runtime->period_size; - ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->extra->number); - ptr &= ~0x00ffffff; - ptr |= epcm->ccca_start_addr + period_pos; - snd_emu10k1_ptr_write(emu, CCCA, epcm->extra->number, ptr); -} - -static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - struct snd_emu10k1_pcm_mixer *mix; - int result = 0; - - /* - printk(KERN_DEBUG "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", - (int)emu, cmd, substream->ops->pointer(substream)) - */ - spin_lock(&emu->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); /* do we need this? */ - snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]); - /* follow thru */ - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) - snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime); - mix = &emu->pcm_mixer[substream->number]; - snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix); - snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix); - snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL); - snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0); - snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0); - snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1); - epcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - epcm->running = 0; - snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]); - snd_emu10k1_playback_stop_voice(emu, epcm->voices[1]); - snd_emu10k1_playback_stop_voice(emu, epcm->extra); - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&emu->reg_lock); - return result; -} - -static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int result = 0; - - spin_lock(&emu->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - /* hmm this should cause full and half full interrupt to be raised? */ - outl(epcm->capture_ipr, emu->port + IPR); - snd_emu10k1_intr_enable(emu, epcm->capture_inte); - /* - printk(KERN_DEBUG "adccr = 0x%x, adcbs = 0x%x\n", - epcm->adccr, epcm->adcbs); - */ - switch (epcm->type) { - case CAPTURE_AC97ADC: - snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val); - break; - case CAPTURE_EFX: - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val); - snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2); - snd_printdd("cr_val=0x%x, cr_val2=0x%x\n", epcm->capture_cr_val, epcm->capture_cr_val2); - } else - snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val); - break; - default: - break; - } - snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, epcm->capture_bs_val); - epcm->running = 1; - epcm->first_ptr = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - epcm->running = 0; - snd_emu10k1_intr_disable(emu, epcm->capture_inte); - outl(epcm->capture_ipr, emu->port + IPR); - snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0); - switch (epcm->type) { - case CAPTURE_AC97ADC: - snd_emu10k1_ptr_write(emu, ADCCR, 0, 0); - break; - case CAPTURE_EFX: - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0); - snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0); - } else - snd_emu10k1_ptr_write(emu, FXWC, 0, 0); - break; - default: - break; - } - break; - default: - result = -EINVAL; - } - spin_unlock(&emu->reg_lock); - return result; -} - -static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int ptr; - - if (!epcm->running) - return 0; - ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff; -#if 0 /* Perex's code */ - ptr += runtime->buffer_size; - ptr -= epcm->ccca_start_addr; - ptr %= runtime->buffer_size; -#else /* EMU10K1 Open Source code from Creative */ - if (ptr < epcm->ccca_start_addr) - ptr += runtime->buffer_size - epcm->ccca_start_addr; - else { - ptr -= epcm->ccca_start_addr; - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - } -#endif - /* - printk(KERN_DEBUG - "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n", - (long)ptr, (long)runtime->buffer_size, - (long)runtime->period_size); - */ - return ptr; -} - - -static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int i; - int result = 0; - - spin_lock(&emu->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* prepare voices */ - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]); - } - snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); - - /* follow thru */ - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL); - snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0, - &emu->efx_pcm_mixer[0]); - for (i = 1; i < NUM_EFX_PLAYBACK; i++) - snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0, - &emu->efx_pcm_mixer[i]); - snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0); - snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1); - for (i = 1; i < NUM_EFX_PLAYBACK; i++) - snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0); - epcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - epcm->running = 0; - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]); - } - snd_emu10k1_playback_stop_voice(emu, epcm->extra); - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&emu->reg_lock); - return result; -} - - -static snd_pcm_uframes_t snd_emu10k1_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int ptr; - - if (!epcm->running) - return 0; - if (epcm->first_ptr) { - udelay(50); /* hack, it takes awhile until capture is started */ - epcm->first_ptr = 0; - } - ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff; - return bytes_to_frames(runtime, ptr); -} - -/* - * Playback support device description - */ - -static struct snd_pcm_hardware snd_emu10k1_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000, - .rate_min = 4000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * Capture support device description - */ - -static struct snd_pcm_hardware snd_emu10k1_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 384, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_emu10k1_capture_efx = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, - .rate_min = 44100, - .rate_max = 192000, - .channels_min = 8, - .channels_max = 8, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 384, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -/* - * - */ - -static void snd_emu10k1_pcm_mixer_notify1(struct snd_emu10k1 *emu, struct snd_kcontrol *kctl, int idx, int activate) -{ - struct snd_ctl_elem_id id; - - if (! kctl) - return; - if (activate) - kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - else - kctl->vd[idx].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - snd_ctl_build_ioff(&id, kctl, idx)); -} - -static void snd_emu10k1_pcm_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate) -{ - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_routing, idx, activate); - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_volume, idx, activate); - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate); -} - -static void snd_emu10k1_pcm_efx_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate) -{ - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate); - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate); - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate); -} - -static void snd_emu10k1_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static int snd_emu10k1_efx_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm_mixer *mix; - int i; - - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - mix = &emu->efx_pcm_mixer[i]; - mix->epcm = NULL; - snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0); - } - return 0; -} - -static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm *epcm; - struct snd_emu10k1_pcm_mixer *mix; - struct snd_pcm_runtime *runtime = substream->runtime; - int i; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = PLAYBACK_EFX; - epcm->substream = substream; - - emu->pcm_playback_efx_substream = substream; - - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_efx_playback; - - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - mix = &emu->efx_pcm_mixer[i]; - mix->send_routing[0][0] = i; - memset(&mix->send_volume, 0, sizeof(mix->send_volume)); - mix->send_volume[0][0] = 255; - mix->attn[0] = 0xffff; - mix->epcm = epcm; - snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1); - } - return 0; -} - -static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm *epcm; - struct snd_emu10k1_pcm_mixer *mix; - struct snd_pcm_runtime *runtime = substream->runtime; - int i, err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = PLAYBACK_EMUVOICE; - epcm->substream = substream; - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_playback; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) { - kfree(epcm); - return err; - } - if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) { - kfree(epcm); - return err; - } - err = snd_pcm_hw_rule_noresample(runtime, 48000); - if (err < 0) { - kfree(epcm); - return err; - } - mix = &emu->pcm_mixer[substream->number]; - for (i = 0; i < 4; i++) - mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i; - memset(&mix->send_volume, 0, sizeof(mix->send_volume)); - mix->send_volume[0][0] = mix->send_volume[0][1] = - mix->send_volume[1][0] = mix->send_volume[2][1] = 255; - mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff; - mix->epcm = epcm; - snd_emu10k1_pcm_mixer_notify(emu, substream->number, 1); - return 0; -} - -static int snd_emu10k1_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[substream->number]; - - mix->epcm = NULL; - snd_emu10k1_pcm_mixer_notify(emu, substream->number, 0); - return 0; -} - -static int snd_emu10k1_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = CAPTURE_AC97ADC; - epcm->substream = substream; - epcm->capture_ipr = IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL; - epcm->capture_inte = INTE_ADCBUFENABLE; - epcm->capture_ba_reg = ADCBA; - epcm->capture_bs_reg = ADCBS; - epcm->capture_idx_reg = emu->audigy ? A_ADCIDX : ADCIDX; - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_capture; - emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt; - emu->pcm_capture_substream = substream; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates); - return 0; -} - -static int snd_emu10k1_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - - emu->capture_interrupt = NULL; - emu->pcm_capture_substream = NULL; - return 0; -} - -static int snd_emu10k1_capture_mic_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = CAPTURE_AC97MIC; - epcm->substream = substream; - epcm->capture_ipr = IPR_MICBUFFULL|IPR_MICBUFHALFFULL; - epcm->capture_inte = INTE_MICBUFENABLE; - epcm->capture_ba_reg = MICBA; - epcm->capture_bs_reg = MICBS; - epcm->capture_idx_reg = emu->audigy ? A_MICIDX : MICIDX; - substream->runtime->private_data = epcm; - substream->runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_capture; - runtime->hw.rates = SNDRV_PCM_RATE_8000; - runtime->hw.rate_min = runtime->hw.rate_max = 8000; - runtime->hw.channels_min = 1; - emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt; - emu->pcm_capture_mic_substream = substream; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes); - return 0; -} - -static int snd_emu10k1_capture_mic_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - - emu->capture_interrupt = NULL; - emu->pcm_capture_mic_substream = NULL; - return 0; -} - -static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int nefx = emu->audigy ? 64 : 32; - int idx; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = CAPTURE_EFX; - epcm->substream = substream; - epcm->capture_ipr = IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL; - epcm->capture_inte = INTE_EFXBUFENABLE; - epcm->capture_ba_reg = FXBA; - epcm->capture_bs_reg = FXBS; - epcm->capture_idx_reg = FXIDX; - substream->runtime->private_data = epcm; - substream->runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_capture_efx; - runtime->hw.rates = SNDRV_PCM_RATE_48000; - runtime->hw.rate_min = runtime->hw.rate_max = 48000; - spin_lock_irq(&emu->reg_lock); - if (emu->card_capabilities->emu_model) { - /* Nb. of channels has been increased to 16 */ - /* TODO - * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE - * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 - * rate_min = 44100, - * rate_max = 192000, - * channels_min = 16, - * channels_max = 16, - * Need to add mixer control to fix sample rate - * - * There are 32 mono channels of 16bits each. - * 24bit Audio uses 2x channels over 16bit - * 96kHz uses 2x channels over 48kHz - * 192kHz uses 4x channels over 48kHz - * So, for 48kHz 24bit, one has 16 channels - * for 96kHz 24bit, one has 8 channels - * for 192kHz 24bit, one has 4 channels - * - */ -#if 1 - switch (emu->emu1010.internal_clock) { - case 0: - /* For 44.1kHz */ - runtime->hw.rates = SNDRV_PCM_RATE_44100; - runtime->hw.rate_min = runtime->hw.rate_max = 44100; - runtime->hw.channels_min = - runtime->hw.channels_max = 16; - break; - case 1: - /* For 48kHz */ - runtime->hw.rates = SNDRV_PCM_RATE_48000; - runtime->hw.rate_min = runtime->hw.rate_max = 48000; - runtime->hw.channels_min = - runtime->hw.channels_max = 16; - break; - }; -#endif -#if 0 - /* For 96kHz */ - runtime->hw.rates = SNDRV_PCM_RATE_96000; - runtime->hw.rate_min = runtime->hw.rate_max = 96000; - runtime->hw.channels_min = runtime->hw.channels_max = 4; -#endif -#if 0 - /* For 192kHz */ - runtime->hw.rates = SNDRV_PCM_RATE_192000; - runtime->hw.rate_min = runtime->hw.rate_max = 192000; - runtime->hw.channels_min = runtime->hw.channels_max = 2; -#endif - runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; - /* efx_voices_mask[0] is expected to be zero - * efx_voices_mask[1] is expected to have 32bits set - */ - } else { - runtime->hw.channels_min = runtime->hw.channels_max = 0; - for (idx = 0; idx < nefx; idx++) { - if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) { - runtime->hw.channels_min++; - runtime->hw.channels_max++; - } - } - } - epcm->capture_cr_val = emu->efx_voices_mask[0]; - epcm->capture_cr_val2 = emu->efx_voices_mask[1]; - spin_unlock_irq(&emu->reg_lock); - emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt; - emu->pcm_capture_efx_substream = substream; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes); - return 0; -} - -static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - - emu->capture_interrupt = NULL; - emu->pcm_capture_efx_substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_emu10k1_playback_ops = { - .open = snd_emu10k1_playback_open, - .close = snd_emu10k1_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_playback_hw_params, - .hw_free = snd_emu10k1_playback_hw_free, - .prepare = snd_emu10k1_playback_prepare, - .trigger = snd_emu10k1_playback_trigger, - .pointer = snd_emu10k1_playback_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -static struct snd_pcm_ops snd_emu10k1_capture_ops = { - .open = snd_emu10k1_capture_open, - .close = snd_emu10k1_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_capture_hw_params, - .hw_free = snd_emu10k1_capture_hw_free, - .prepare = snd_emu10k1_capture_prepare, - .trigger = snd_emu10k1_capture_trigger, - .pointer = snd_emu10k1_capture_pointer, -}; - -/* EFX playback */ -static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { - .open = snd_emu10k1_efx_playback_open, - .close = snd_emu10k1_efx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_playback_hw_params, - .hw_free = snd_emu10k1_efx_playback_hw_free, - .prepare = snd_emu10k1_efx_playback_prepare, - .trigger = snd_emu10k1_efx_playback_trigger, - .pointer = snd_emu10k1_efx_playback_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_ops); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, "ADC Capture/Standard PCM Playback"); - emu->pcm = pcm; - - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) - if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0) - return err; - - for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) - snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -int __devinit snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_efx_playback_ops); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, "Multichannel Playback"); - emu->pcm_multi = pcm; - - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) - if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0) - return err; - - if (rpcm) - *rpcm = pcm; - - return 0; -} - - -static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = { - .open = snd_emu10k1_capture_mic_open, - .close = snd_emu10k1_capture_mic_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_capture_hw_params, - .hw_free = snd_emu10k1_capture_hw_free, - .prepare = snd_emu10k1_capture_prepare, - .trigger = snd_emu10k1_capture_trigger, - .pointer = snd_emu10k1_capture_pointer, -}; - -int __devinit snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, "Mic Capture"); - emu->pcm_mic = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -static int snd_emu10k1_pcm_efx_voices_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int nefx = emu->audigy ? 64 : 32; - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = nefx; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_emu10k1_pcm_efx_voices_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int nefx = emu->audigy ? 64 : 32; - int idx; - - spin_lock_irq(&emu->reg_lock); - for (idx = 0; idx < nefx; idx++) - ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0; - spin_unlock_irq(&emu->reg_lock); - return 0; -} - -static int snd_emu10k1_pcm_efx_voices_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int nval[2], bits; - int nefx = emu->audigy ? 64 : 32; - int nefxb = emu->audigy ? 7 : 6; - int change, idx; - - nval[0] = nval[1] = 0; - for (idx = 0, bits = 0; idx < nefx; idx++) - if (ucontrol->value.integer.value[idx]) { - nval[idx / 32] |= 1 << (idx % 32); - bits++; - } - - for (idx = 0; idx < nefxb; idx++) - if (1 << idx == bits) - break; - - if (idx >= nefxb) - return -EINVAL; - - spin_lock_irq(&emu->reg_lock); - change = (nval[0] != emu->efx_voices_mask[0]) || - (nval[1] != emu->efx_voices_mask[1]); - emu->efx_voices_mask[0] = nval[0]; - emu->efx_voices_mask[1] = nval[1]; - spin_unlock_irq(&emu->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_pcm_efx_voices_mask = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Captured FX8010 Outputs", - .info = snd_emu10k1_pcm_efx_voices_mask_info, - .get = snd_emu10k1_pcm_efx_voices_mask_get, - .put = snd_emu10k1_pcm_efx_voices_mask_put -}; - -static struct snd_pcm_ops snd_emu10k1_capture_efx_ops = { - .open = snd_emu10k1_capture_efx_open, - .close = snd_emu10k1_capture_efx_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_capture_hw_params, - .hw_free = snd_emu10k1_capture_hw_free, - .prepare = snd_emu10k1_capture_prepare, - .trigger = snd_emu10k1_capture_trigger, - .pointer = snd_emu10k1_capture_pointer, -}; - - -/* EFX playback */ - -#define INITIAL_TRAM_SHIFT 14 -#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1) - -static void snd_emu10k1_fx8010_playback_irq(struct snd_emu10k1 *emu, void *private_data) -{ - struct snd_pcm_substream *substream = private_data; - snd_pcm_period_elapsed(substream); -} - -static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left, - unsigned short *dst_right, - unsigned short *src, - unsigned int count, - unsigned int tram_shift) -{ - /* - printk(KERN_DEBUG "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, " - "src = 0x%p, count = 0x%x\n", - dst_left, dst_right, src, count); - */ - if ((tram_shift & 1) == 0) { - while (count--) { - *dst_left-- = *src++; - *dst_right-- = *src++; - } - } else { - while (count--) { - *dst_right-- = *src++; - *dst_left-- = *src++; - } - } -} - -static void fx8010_pb_trans_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - unsigned int tram_size = pcm->buffer_size; - unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data); - unsigned int frames = bytes >> 2, count; - unsigned int tram_pos = pcm->tram_pos; - unsigned int tram_shift = pcm->tram_shift; - - while (frames > tram_pos) { - count = tram_pos + 1; - snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos, - (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2, - src, count, tram_shift); - src += count * 2; - frames -= count; - tram_pos = (tram_size / 2) - 1; - tram_shift++; - } - snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos, - (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2, - src, frames, tram_shift); - tram_pos -= frames; - pcm->tram_pos = tram_pos; - pcm->tram_shift = tram_shift; -} - -static int snd_emu10k1_fx8010_playback_transfer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - - snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy); - return 0; -} - -static int snd_emu10k1_fx8010_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_emu10k1_fx8010_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - unsigned int i; - - for (i = 0; i < pcm->channels; i++) - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0); - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - unsigned int i; - - /* - printk(KERN_DEBUG "prepare: etram_pages = 0x%p, dma_area = 0x%x, " - "buffer_size = 0x%x (0x%x)\n", - emu->fx8010.etram_pages, runtime->dma_area, - runtime->buffer_size, runtime->buffer_size << 2); - */ - memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec)); - pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */ - pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size); - pcm->tram_shift = 0; - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0); /* reset */ - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0); /* reset */ - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size); - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0); /* reset ptr number */ - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size); - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size); - for (i = 0; i < pcm->channels; i++) - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels)); - return 0; -} - -static int snd_emu10k1_fx8010_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - int result = 0; - - spin_lock(&emu->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* follow thru */ - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: -#ifdef EMU10K1_SET_AC3_IEC958 - { - int i; - for (i = 0; i < 3; i++) { - unsigned int bits; - bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | - 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA; - snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits); - } - } -#endif - result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq); - if (result < 0) - goto __err; - snd_emu10k1_fx8010_playback_transfer(substream); /* roll the ball */ - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL; - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0); - pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size); - pcm->tram_shift = 0; - break; - default: - result = -EINVAL; - break; - } - __err: - spin_unlock(&emu->reg_lock); - return result; -} - -static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - size_t ptr; /* byte pointer */ - - if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0)) - return 0; - ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0) << 2; - return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr); -} - -static struct snd_pcm_hardware snd_emu10k1_fx8010_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | - /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 1024, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_emu10k1_fx8010_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - - runtime->hw = snd_emu10k1_fx8010_playback; - runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels; - runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2; - spin_lock_irq(&emu->reg_lock); - if (pcm->valid == 0) { - spin_unlock_irq(&emu->reg_lock); - return -ENODEV; - } - pcm->opened = 1; - spin_unlock_irq(&emu->reg_lock); - return 0; -} - -static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - - spin_lock_irq(&emu->reg_lock); - pcm->opened = 0; - spin_unlock_irq(&emu->reg_lock); - return 0; -} - -static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = { - .open = snd_emu10k1_fx8010_playback_open, - .close = snd_emu10k1_fx8010_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_fx8010_playback_hw_params, - .hw_free = snd_emu10k1_fx8010_playback_hw_free, - .prepare = snd_emu10k1_fx8010_playback_prepare, - .trigger = snd_emu10k1_fx8010_playback_trigger, - .pointer = snd_emu10k1_fx8010_playback_pointer, - .ack = snd_emu10k1_fx8010_playback_transfer, -}; - -int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - struct snd_kcontrol *kctl; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, "Multichannel Capture/PT Playback"); - emu->pcm_efx = pcm; - if (rpcm) - *rpcm = pcm; - - /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs - * to these - */ - - /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ - if (emu->audigy) { - emu->efx_voices_mask[0] = 0; - if (emu->card_capabilities->emu_model) - /* Pavel Hofman - 32 voices will be used for - * capture (write mode) - - * each bit = corresponding voice - */ - emu->efx_voices_mask[1] = 0xffffffff; - else - emu->efx_voices_mask[1] = 0xffff; - } else { - emu->efx_voices_mask[0] = 0xffff0000; - emu->efx_voices_mask[1] = 0; - } - /* For emu1010, the control has to set 32 upper bits (voices) - * out of the 64 bits (voices) to true for the 16-channels capture - * to work correctly. Correct A_FXWC2 initial value (0xffffffff) - * is already defined but the snd_emu10k1_pcm_efx_voices_mask - * control can override this register's value. - */ - kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu); - if (!kctl) - return -ENOMEM; - kctl->id.device = device; - snd_ctl_add(emu->card, kctl); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c b/ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c deleted file mode 100644 index bc38dd4d..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips / proc interface routines - * - * Copyright (c) by James Courtier-Dutton - * Added EMU 1010 support. - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 "p16v.h" - -#ifdef CONFIG_PROC_FS -static void snd_emu10k1_proc_spdif_status(struct snd_emu10k1 * emu, - struct snd_info_buffer *buffer, - char *title, - int status_reg, - int rate_reg) -{ - static char *clkaccy[4] = { "1000ppm", "50ppm", "variable", "unknown" }; - static int samplerate[16] = { 44100, 1, 48000, 32000, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - static char *channel[16] = { "unspec", "left", "right", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" }; - static char *emphasis[8] = { "none", "50/15 usec 2 channel", "2", "3", "4", "5", "6", "7" }; - unsigned int status, rate = 0; - - status = snd_emu10k1_ptr_read(emu, status_reg, 0); - - snd_iprintf(buffer, "\n%s\n", title); - - if (status != 0xffffffff) { - snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no"); - snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no"); - snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no"); - snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]); - snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6); - snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8); - snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy"); - snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16); - snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]); - snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]); - snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]); - - if (rate_reg > 0) { - rate = snd_emu10k1_ptr_read(emu, rate_reg, 0); - snd_iprintf(buffer, "S/PDIF Valid : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off"); - snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off"); - snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off"); - /* From ((Rate * 48000 ) / 262144); */ - snd_iprintf(buffer, "Estimated Sample Rate : %d\n", ((rate & 0xFFFFF ) * 375) >> 11); - } - } else { - snd_iprintf(buffer, "No signal detected.\n"); - } - -} - -static void snd_emu10k1_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - /* FIXME - output names are in emufx.c too */ - static char *creative_outs[32] = { - /* 00 */ "AC97 Left", - /* 01 */ "AC97 Right", - /* 02 */ "Optical IEC958 Left", - /* 03 */ "Optical IEC958 Right", - /* 04 */ "Center", - /* 05 */ "LFE", - /* 06 */ "Headphone Left", - /* 07 */ "Headphone Right", - /* 08 */ "Surround Left", - /* 09 */ "Surround Right", - /* 10 */ "PCM Capture Left", - /* 11 */ "PCM Capture Right", - /* 12 */ "MIC Capture", - /* 13 */ "AC97 Surround Left", - /* 14 */ "AC97 Surround Right", - /* 15 */ "???", - /* 16 */ "???", - /* 17 */ "Analog Center", - /* 18 */ "Analog LFE", - /* 19 */ "???", - /* 20 */ "???", - /* 21 */ "???", - /* 22 */ "???", - /* 23 */ "???", - /* 24 */ "???", - /* 25 */ "???", - /* 26 */ "???", - /* 27 */ "???", - /* 28 */ "???", - /* 29 */ "???", - /* 30 */ "???", - /* 31 */ "???" - }; - - static char *audigy_outs[64] = { - /* 00 */ "Digital Front Left", - /* 01 */ "Digital Front Right", - /* 02 */ "Digital Center", - /* 03 */ "Digital LEF", - /* 04 */ "Headphone Left", - /* 05 */ "Headphone Right", - /* 06 */ "Digital Rear Left", - /* 07 */ "Digital Rear Right", - /* 08 */ "Front Left", - /* 09 */ "Front Right", - /* 10 */ "Center", - /* 11 */ "LFE", - /* 12 */ "???", - /* 13 */ "???", - /* 14 */ "Rear Left", - /* 15 */ "Rear Right", - /* 16 */ "AC97 Front Left", - /* 17 */ "AC97 Front Right", - /* 18 */ "ADC Caputre Left", - /* 19 */ "ADC Capture Right", - /* 20 */ "???", - /* 21 */ "???", - /* 22 */ "???", - /* 23 */ "???", - /* 24 */ "???", - /* 25 */ "???", - /* 26 */ "???", - /* 27 */ "???", - /* 28 */ "???", - /* 29 */ "???", - /* 30 */ "???", - /* 31 */ "???", - /* 32 */ "FXBUS2_0", - /* 33 */ "FXBUS2_1", - /* 34 */ "FXBUS2_2", - /* 35 */ "FXBUS2_3", - /* 36 */ "FXBUS2_4", - /* 37 */ "FXBUS2_5", - /* 38 */ "FXBUS2_6", - /* 39 */ "FXBUS2_7", - /* 40 */ "FXBUS2_8", - /* 41 */ "FXBUS2_9", - /* 42 */ "FXBUS2_10", - /* 43 */ "FXBUS2_11", - /* 44 */ "FXBUS2_12", - /* 45 */ "FXBUS2_13", - /* 46 */ "FXBUS2_14", - /* 47 */ "FXBUS2_15", - /* 48 */ "FXBUS2_16", - /* 49 */ "FXBUS2_17", - /* 50 */ "FXBUS2_18", - /* 51 */ "FXBUS2_19", - /* 52 */ "FXBUS2_20", - /* 53 */ "FXBUS2_21", - /* 54 */ "FXBUS2_22", - /* 55 */ "FXBUS2_23", - /* 56 */ "FXBUS2_24", - /* 57 */ "FXBUS2_25", - /* 58 */ "FXBUS2_26", - /* 59 */ "FXBUS2_27", - /* 60 */ "FXBUS2_28", - /* 61 */ "FXBUS2_29", - /* 62 */ "FXBUS2_30", - /* 63 */ "FXBUS2_31" - }; - - struct snd_emu10k1 *emu = entry->private_data; - unsigned int val, val1; - int nefx = emu->audigy ? 64 : 32; - char **outputs = emu->audigy ? audigy_outs : creative_outs; - int idx; - - snd_iprintf(buffer, "EMU10K1\n\n"); - snd_iprintf(buffer, "Card : %s\n", - emu->audigy ? "Audigy" : (emu->card_capabilities->ecard ? "EMU APS" : "Creative")); - snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size); - snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2); - snd_iprintf(buffer, "\n"); - snd_iprintf(buffer, "Effect Send Routing :\n"); - for (idx = 0; idx < NUM_G; idx++) { - val = emu->audigy ? - snd_emu10k1_ptr_read(emu, A_FXRT1, idx) : - snd_emu10k1_ptr_read(emu, FXRT, idx); - val1 = emu->audigy ? - snd_emu10k1_ptr_read(emu, A_FXRT2, idx) : - 0; - if (emu->audigy) { - snd_iprintf(buffer, "Ch%i: A=%i, B=%i, C=%i, D=%i, ", - idx, - val & 0x3f, - (val >> 8) & 0x3f, - (val >> 16) & 0x3f, - (val >> 24) & 0x3f); - snd_iprintf(buffer, "E=%i, F=%i, G=%i, H=%i\n", - val1 & 0x3f, - (val1 >> 8) & 0x3f, - (val1 >> 16) & 0x3f, - (val1 >> 24) & 0x3f); - } else { - snd_iprintf(buffer, "Ch%i: A=%i, B=%i, C=%i, D=%i\n", - idx, - (val >> 16) & 0x0f, - (val >> 20) & 0x0f, - (val >> 24) & 0x0f, - (val >> 28) & 0x0f); - } - } - snd_iprintf(buffer, "\nCaptured FX Outputs :\n"); - for (idx = 0; idx < nefx; idx++) { - if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) - snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); - } - snd_iprintf(buffer, "\nAll FX Outputs :\n"); - for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++) - snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); -} - -static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - u32 value; - u32 value2; - unsigned long flags; - u32 rate; - - if (emu->card_capabilities->emu_model) { - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, 0x38, &value); - spin_unlock_irqrestore(&emu->emu_lock, flags); - if ((value & 0x1) == 0) { - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, 0x2a, &value); - snd_emu1010_fpga_read(emu, 0x2b, &value2); - spin_unlock_irqrestore(&emu->emu_lock, flags); - rate = 0x1770000 / (((value << 5) | value2)+1); - snd_iprintf(buffer, "ADAT Locked : %u\n", rate); - } else { - snd_iprintf(buffer, "ADAT Unlocked\n"); - } - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, 0x20, &value); - spin_unlock_irqrestore(&emu->emu_lock, flags); - if ((value & 0x4) == 0) { - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, 0x28, &value); - snd_emu1010_fpga_read(emu, 0x29, &value2); - spin_unlock_irqrestore(&emu->emu_lock, flags); - rate = 0x1770000 / (((value << 5) | value2)+1); - snd_iprintf(buffer, "SPDIF Locked : %d\n", rate); - } else { - snd_iprintf(buffer, "SPDIF Unlocked\n"); - } - } else { - snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); - snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); - } -#if 0 - val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); - snd_iprintf(buffer, "\nZoomed Video\n"); - snd_iprintf(buffer, "Rate Locked : %s\n", val & SRCS_RATELOCKED ? "on" : "off"); - snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE); -#endif -} - -static void snd_emu10k1_proc_rates_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 }; - struct snd_emu10k1 *emu = entry->private_data; - unsigned int val, tmp, n; - val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0); - tmp = (val >> 16) & 0x8; - for (n = 0; n < 4; n++) { - tmp = val >> (16 + (n*4)); - if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]); - else snd_iprintf(buffer, "Channel %d: No input\n", n); - } -} - -static void snd_emu10k1_proc_acode_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - u32 pc; - struct snd_emu10k1 *emu = entry->private_data; - - snd_iprintf(buffer, "FX8010 Instruction List '%s'\n", emu->fx8010.name); - snd_iprintf(buffer, " Code dump :\n"); - for (pc = 0; pc < (emu->audigy ? 1024 : 512); pc++) { - u32 low, high; - - low = snd_emu10k1_efx_read(emu, pc * 2); - high = snd_emu10k1_efx_read(emu, pc * 2 + 1); - if (emu->audigy) - snd_iprintf(buffer, " OP(0x%02x, 0x%03x, 0x%03x, 0x%03x, 0x%03x) /* 0x%04x: 0x%08x%08x */\n", - (high >> 24) & 0x0f, - (high >> 12) & 0x7ff, - (high >> 0) & 0x7ff, - (low >> 12) & 0x7ff, - (low >> 0) & 0x7ff, - pc, - high, low); - else - snd_iprintf(buffer, " OP(0x%02x, 0x%03x, 0x%03x, 0x%03x, 0x%03x) /* 0x%04x: 0x%08x%08x */\n", - (high >> 20) & 0x0f, - (high >> 10) & 0x3ff, - (high >> 0) & 0x3ff, - (low >> 10) & 0x3ff, - (low >> 0) & 0x3ff, - pc, - high, low); - } -} - -#define TOTAL_SIZE_GPR (0x100*4) -#define A_TOTAL_SIZE_GPR (0x200*4) -#define TOTAL_SIZE_TANKMEM_DATA (0xa0*4) -#define TOTAL_SIZE_TANKMEM_ADDR (0xa0*4) -#define A_TOTAL_SIZE_TANKMEM_DATA (0x100*4) -#define A_TOTAL_SIZE_TANKMEM_ADDR (0x100*4) -#define TOTAL_SIZE_CODE (0x200*8) -#define A_TOTAL_SIZE_CODE (0x400*8) - -static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct snd_emu10k1 *emu = entry->private_data; - unsigned int offset; - int tram_addr = 0; - unsigned int *tmp; - long res; - unsigned int idx; - - if (!strcmp(entry->name, "fx8010_tram_addr")) { - offset = TANKMEMADDRREGBASE; - tram_addr = 1; - } else if (!strcmp(entry->name, "fx8010_tram_data")) { - offset = TANKMEMDATAREGBASE; - } else if (!strcmp(entry->name, "fx8010_code")) { - offset = emu->audigy ? A_MICROCODEBASE : MICROCODEBASE; - } else { - offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE; - } - - tmp = kmalloc(count + 8, GFP_KERNEL); - if (!tmp) - return -ENOMEM; - for (idx = 0; idx < ((pos & 3) + count + 3) >> 2; idx++) { - unsigned int val; - val = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0); - if (tram_addr && emu->audigy) { - val >>= 11; - val |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20; - } - tmp[idx] = val; - } - if (copy_to_user(buf, ((char *)tmp) + (pos & 3), count)) - res = -EFAULT; - else - res = count; - kfree(tmp); - return res; -} - -static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - struct snd_emu10k1_voice *voice; - int idx; - - snd_iprintf(buffer, "ch\tuse\tpcm\tefx\tsynth\tmidi\n"); - for (idx = 0; idx < NUM_G; idx++) { - voice = &emu->voices[idx]; - snd_iprintf(buffer, "%i\t%i\t%i\t%i\t%i\t%i\n", - idx, - voice->use, - voice->pcm, - voice->efx, - voice->synth, - voice->midi); - } -} - -#ifdef CONFIG_SND_DEBUG -static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - u32 value; - unsigned long flags; - int i; - snd_iprintf(buffer, "EMU1010 Registers:\n\n"); - - for(i = 0; i < 0x40; i+=1) { - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, i, &value); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f); - } -} - -static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - unsigned long value; - unsigned long flags; - int i; - snd_iprintf(buffer, "IO Registers:\n\n"); - for(i = 0; i < 0x40; i+=4) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inl(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "%02X: %08lX\n", i, value); - } -} - -static void snd_emu_proc_io_reg_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - unsigned long flags; - char line[64]; - u32 reg, val; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x", ®, &val) != 2) - continue; - if (reg < 0x40 && val <= 0xffffffff) { - spin_lock_irqsave(&emu->emu_lock, flags); - outl(val, emu->port + (reg & 0xfffffffc)); - spin_unlock_irqrestore(&emu->emu_lock, flags); - } - } -} - -static unsigned int snd_ptr_read(struct snd_emu10k1 * emu, - unsigned int iobase, - unsigned int reg, - unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + iobase + PTR); - val = inl(emu->port + iobase + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -static void snd_ptr_write(struct snd_emu10k1 *emu, - unsigned int iobase, - unsigned int reg, - unsigned int chn, - unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + iobase + PTR); - outl(data, emu->port + iobase + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - - -static void snd_emu_proc_ptr_reg_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer, int iobase, int offset, int length, int voices) -{ - struct snd_emu10k1 *emu = entry->private_data; - unsigned long value; - int i,j; - if (offset+length > 0xa0) { - snd_iprintf(buffer, "Input values out of range\n"); - return; - } - snd_iprintf(buffer, "Registers 0x%x\n", iobase); - for(i = offset; i < offset+length; i++) { - snd_iprintf(buffer, "%02X: ",i); - for (j = 0; j < voices; j++) { - if(iobase == 0) - value = snd_ptr_read(emu, 0, i, j); - else - value = snd_ptr_read(emu, 0x20, i, j); - snd_iprintf(buffer, "%08lX ", value); - } - snd_iprintf(buffer, "\n"); - } -} - -static void snd_emu_proc_ptr_reg_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer, int iobase) -{ - struct snd_emu10k1 *emu = entry->private_data; - char line[64]; - unsigned int reg, channel_id , val; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x %x", ®, &channel_id, &val) != 3) - continue; - if (reg < 0xa0 && val <= 0xffffffff && channel_id <= 3) - snd_ptr_write(emu, iobase, reg, channel_id, val); - } -} - -static void snd_emu_proc_ptr_reg_write00(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_write(entry, buffer, 0); -} - -static void snd_emu_proc_ptr_reg_write20(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_write(entry, buffer, 0x20); -} - - -static void snd_emu_proc_ptr_reg_read00a(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0, 0x40, 64); -} - -static void snd_emu_proc_ptr_reg_read00b(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0x40, 0x40, 64); -} - -static void snd_emu_proc_ptr_reg_read20a(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0, 0x40, 4); -} - -static void snd_emu_proc_ptr_reg_read20b(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40, 4); -} - -static void snd_emu_proc_ptr_reg_read20c(struct snd_info_entry *entry, - struct snd_info_buffer * buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x80, 0x20, 4); -} -#endif - -static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = { - .read = snd_emu10k1_fx8010_read, -}; - -int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) -{ - struct snd_info_entry *entry; -#ifdef CONFIG_SND_DEBUG - if (emu->card_capabilities->emu_model) { - if (! snd_card_proc_new(emu->card, "emu1010_regs", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read); - } - if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); - entry->c.text.write = snd_emu_proc_io_reg_write; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00a); - entry->c.text.write = snd_emu_proc_ptr_reg_write00; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00b); - entry->c.text.write = snd_emu_proc_ptr_reg_write00; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20a); - entry->c.text.write = snd_emu_proc_ptr_reg_write20; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20b); - entry->c.text.write = snd_emu_proc_ptr_reg_write20; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20c); - entry->c.text.write = snd_emu_proc_ptr_reg_write20; - entry->mode |= S_IWUSR; - } -#endif - - if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_read); - - if (emu->card_capabilities->emu10k2_chip) { - if (! snd_card_proc_new(emu->card, "spdif-in", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_spdif_read); - } - if (emu->card_capabilities->ca0151_chip) { - if (! snd_card_proc_new(emu->card, "capture-rates", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_rates_read); - } - - if (! snd_card_proc_new(emu->card, "voices", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_voices_read); - - if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = emu->audigy ? A_TOTAL_SIZE_GPR : TOTAL_SIZE_GPR; - entry->c.ops = &snd_emu10k1_proc_ops_fx8010; - } - if (! snd_card_proc_new(emu->card, "fx8010_tram_data", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_DATA : TOTAL_SIZE_TANKMEM_DATA ; - entry->c.ops = &snd_emu10k1_proc_ops_fx8010; - } - if (! snd_card_proc_new(emu->card, "fx8010_tram_addr", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_ADDR : TOTAL_SIZE_TANKMEM_ADDR ; - entry->c.ops = &snd_emu10k1_proc_ops_fx8010; - } - if (! snd_card_proc_new(emu->card, "fx8010_code", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = emu->audigy ? A_TOTAL_SIZE_CODE : TOTAL_SIZE_CODE; - entry->c.ops = &snd_emu10k1_proc_ops_fx8010; - } - if (! snd_card_proc_new(emu->card, "fx8010_acode", &entry)) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->c.text.read = snd_emu10k1_proc_acode_read; - } - return 0; -} -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/io.c b/ANDROID_3.4.5/sound/pci/emu10k1/io.c deleted file mode 100644 index e4fba49f..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/io.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 "p17v.h" - -unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - unsigned int mask; - - mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; - regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); - - if (reg & 0xff000000) { - unsigned char size, offset; - - size = (reg >> 24) & 0x3f; - offset = (reg >> 16) & 0x1f; - mask = ((1 << size) - 1) << offset; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - - return (val & mask) >> offset; - } else { - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; - } -} - -EXPORT_SYMBOL(snd_emu10k1_ptr_read); - -void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - unsigned int mask; - - if (!emu) { - snd_printk(KERN_ERR "ptr_write: emu is null!\n"); - dump_stack(); - return; - } - mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; - regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); - - if (reg & 0xff000000) { - unsigned char size, offset; - - size = (reg >> 24) & 0x3f; - offset = (reg >> 16) & 0x1f; - mask = ((1 << size) - 1) << offset; - data = (data << offset) & mask; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - data |= inl(emu->port + DATA) & ~mask; - outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - } else { - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - } -} - -EXPORT_SYMBOL(snd_emu10k1_ptr_write); - -unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, - unsigned int reg, - unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + 0x20 + PTR); - val = inl(emu->port + 0x20 + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, - unsigned int reg, - unsigned int chn, - unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + 0x20 + PTR); - outl(data, emu->port + 0x20 + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, - unsigned int data) -{ - unsigned int reset, set; - unsigned int reg, tmp; - int n, result; - int err = 0; - - /* This function is not re-entrant, so protect against it. */ - spin_lock(&emu->spi_lock); - if (emu->card_capabilities->ca0108_chip) - reg = 0x3c; /* PTR20, reg 0x3c */ - else { - /* For other chip types the SPI register - * is currently unknown. */ - err = 1; - goto spi_write_exit; - } - if (data > 0xffff) { - /* Only 16bit values allowed */ - err = 1; - goto spi_write_exit; - } - - tmp = snd_emu10k1_ptr20_read(emu, reg, 0); - reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */ - set = reset | 0x10000; /* Set xxx1xxxx */ - snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); - tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */ - snd_emu10k1_ptr20_write(emu, reg, 0, set | data); - result = 1; - /* Wait for status bit to return to 0 */ - for (n = 0; n < 100; n++) { - udelay(10); - tmp = snd_emu10k1_ptr20_read(emu, reg, 0); - if (!(tmp & 0x10000)) { - result = 0; - break; - } - } - if (result) { - /* Timed out */ - err = 1; - goto spi_write_exit; - } - snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); - tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */ - err = 0; -spi_write_exit: - spin_unlock(&emu->spi_lock); - return err; -} - -/* The ADC does not support i2c read, so only write is implemented */ -int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, - u32 reg, - u32 value) -{ - u32 tmp; - int timeout = 0; - int status; - int retry; - int err = 0; - - if ((reg > 0x7f) || (value > 0x1ff)) { - snd_printk(KERN_ERR "i2c_write: invalid values.\n"); - return -EINVAL; - } - - /* This function is not re-entrant, so protect against it. */ - spin_lock(&emu->i2c_lock); - - tmp = reg << 25 | value << 16; - - /* This controls the I2C connected to the WM8775 ADC Codec */ - snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp); - tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */ - - for (retry = 0; retry < 10; retry++) { - /* Send the data to i2c */ - tmp = 0; - tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); - snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp); - - /* Wait till the transaction ends */ - while (1) { - mdelay(1); - status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0); - timeout++; - if ((status & I2C_A_ADC_START) == 0) - break; - - if (timeout > 1000) { - snd_printk(KERN_WARNING - "emu10k1:I2C:timeout status=0x%x\n", - status); - break; - } - } - //Read back and see if the transaction is successful - if ((status & I2C_A_ADC_ABORT) == 0) - break; - } - - if (retry == 10) { - snd_printk(KERN_ERR "Writing to ADC failed!\n"); - snd_printk(KERN_ERR "status=0x%x, reg=%d, value=%d\n", - status, reg, value); - /* dump_stack(); */ - err = -EINVAL; - } - - spin_unlock(&emu->i2c_lock); - return err; -} - -int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) -{ - unsigned long flags; - - if (reg > 0x3f) - return 1; - reg += 0x40; /* 0x40 upwards are registers. */ - if (value > 0x3f) /* 0 to 0x3f are values */ - return 1; - spin_lock_irqsave(&emu->emu_lock, flags); - outl(reg, emu->port + A_IOCFG); - udelay(10); - outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ - udelay(10); - outl(value, emu->port + A_IOCFG); - udelay(10); - outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ - spin_unlock_irqrestore(&emu->emu_lock, flags); - - return 0; -} - -int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value) -{ - unsigned long flags; - if (reg > 0x3f) - return 1; - reg += 0x40; /* 0x40 upwards are registers. */ - spin_lock_irqsave(&emu->emu_lock, flags); - outl(reg, emu->port + A_IOCFG); - udelay(10); - outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ - udelay(10); - *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f); - spin_unlock_irqrestore(&emu->emu_lock, flags); - - return 0; -} - -/* Each Destination has one and only one Source, - * but one Source can feed any number of Destinations simultaneously. - */ -int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src) -{ - snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) ); - - return 0; -} - -void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - enable = inl(emu->port + INTE) | intrenb; - outl(enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - enable = inl(emu->port + INTE) & ~intrenb; - outl(enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(CLIEH << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val |= 1 << (voicenum - 32); - } else { - outl(CLIEL << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val |= 1 << voicenum; - } - outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(CLIEH << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val &= ~(1 << (voicenum - 32)); - } else { - outl(CLIEL << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val &= ~(1 << voicenum); - } - outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(CLIPH << 16, emu->port + PTR); - voicenum = 1 << (voicenum - 32); - } else { - outl(CLIPL << 16, emu->port + PTR); - voicenum = 1 << voicenum; - } - outl(voicenum, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(HLIEH << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val |= 1 << (voicenum - 32); - } else { - outl(HLIEL << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val |= 1 << voicenum; - } - outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(HLIEH << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val &= ~(1 << (voicenum - 32)); - } else { - outl(HLIEL << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val &= ~(1 << voicenum); - } - outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(HLIPH << 16, emu->port + PTR); - voicenum = 1 << (voicenum - 32); - } else { - outl(HLIPL << 16, emu->port + PTR); - voicenum = 1 << voicenum; - } - outl(voicenum, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int sol; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(SOLEH << 16, emu->port + PTR); - sol = inl(emu->port + DATA); - sol |= 1 << (voicenum - 32); - } else { - outl(SOLEL << 16, emu->port + PTR); - sol = inl(emu->port + DATA); - sol |= 1 << voicenum; - } - outl(sol, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int sol; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(SOLEH << 16, emu->port + PTR); - sol = inl(emu->port + DATA); - sol &= ~(1 << (voicenum - 32)); - } else { - outl(SOLEL << 16, emu->port + PTR); - sol = inl(emu->port + DATA); - sol &= ~(1 << voicenum); - } - outl(sol, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait) -{ - volatile unsigned count; - unsigned int newtime = 0, curtime; - - curtime = inl(emu->port + WC) >> 6; - while (wait-- > 0) { - count = 0; - while (count++ < 16384) { - newtime = inl(emu->port + WC) >> 6; - if (newtime != curtime) - break; - } - if (count > 16384) - break; - curtime = newtime; - } -} - -unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_emu10k1 *emu = ac97->private_data; - unsigned long flags; - unsigned short val; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - val = inw(emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data) -{ - struct snd_emu10k1 *emu = ac97->private_data; - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - outw(data, emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -/* - * convert rate to pitch - */ - -unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate) -{ - static u32 logMagTable[128] = { - 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2, - 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5, - 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081, - 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191, - 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, - 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, - 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e, - 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26, - 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d, - 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885, - 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, - 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, - 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, - 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3, - 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83, - 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df - }; - static char logSlopeTable[128] = { - 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, - 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53, - 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f, - 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b, - 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, - 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44, - 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41, - 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, - 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, - 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, - 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35, - 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f - }; - int i; - - if (rate == 0) - return 0; /* Bail out if no leading "1" */ - rate *= 11185; /* Scale 48000 to 0x20002380 */ - for (i = 31; i > 0; i--) { - if (rate & 0x80000000) { /* Detect leading "1" */ - return (((unsigned int) (i - 15) << 20) + - logMagTable[0x7f & (rate >> 24)] + - (0x7f & (rate >> 17)) * - logSlopeTable[0x7f & (rate >> 24)]); - } - rate <<= 1; - } - - return 0; /* Should never reach this point */ -} - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/irq.c b/ANDROID_3.4.5/sound/pci/emu10k1/irq.c deleted file mode 100644 index 30bfed6f..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/irq.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Creative Labs, Inc. - * Routines for IRQ control of EMU10K1 chips - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 - -irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) -{ - struct snd_emu10k1 *emu = dev_id; - unsigned int status, status2, orig_status, orig_status2; - int handled = 0; - int timeout = 0; - - while (((status = inl(emu->port + IPR)) != 0) && (timeout < 1000)) { - timeout++; - orig_status = status; - handled = 1; - if ((status & 0xffffffff) == 0xffffffff) { - snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n"); - break; - } - if (status & IPR_PCIERROR) { - snd_printk(KERN_ERR "interrupt: PCI error\n"); - snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE); - status &= ~IPR_PCIERROR; - } - if (status & (IPR_VOLINCR|IPR_VOLDECR|IPR_MUTE)) { - if (emu->hwvol_interrupt) - emu->hwvol_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_VOLINCRENABLE|INTE_VOLDECRENABLE|INTE_MUTEENABLE); - status &= ~(IPR_VOLINCR|IPR_VOLDECR|IPR_MUTE); - } - if (status & IPR_CHANNELLOOP) { - int voice; - int voice_max = status & IPR_CHANNELNUMBERMASK; - u32 val; - struct snd_emu10k1_voice *pvoice = emu->voices; - - val = snd_emu10k1_ptr_read(emu, CLIPL, 0); - for (voice = 0; voice <= voice_max; voice++) { - if (voice == 0x20) - val = snd_emu10k1_ptr_read(emu, CLIPH, 0); - if (val & 1) { - if (pvoice->use && pvoice->interrupt != NULL) { - pvoice->interrupt(emu, pvoice); - snd_emu10k1_voice_intr_ack(emu, voice); - } else { - snd_emu10k1_voice_intr_disable(emu, voice); - } - } - val >>= 1; - pvoice++; - } - val = snd_emu10k1_ptr_read(emu, HLIPL, 0); - for (voice = 0; voice <= voice_max; voice++) { - if (voice == 0x20) - val = snd_emu10k1_ptr_read(emu, HLIPH, 0); - if (val & 1) { - if (pvoice->use && pvoice->interrupt != NULL) { - pvoice->interrupt(emu, pvoice); - snd_emu10k1_voice_half_loop_intr_ack(emu, voice); - } else { - snd_emu10k1_voice_half_loop_intr_disable(emu, voice); - } - } - val >>= 1; - pvoice++; - } - status &= ~IPR_CHANNELLOOP; - } - status &= ~IPR_CHANNELNUMBERMASK; - if (status & (IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL)) { - if (emu->capture_interrupt) - emu->capture_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_ADCBUFENABLE); - status &= ~(IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL); - } - if (status & (IPR_MICBUFFULL|IPR_MICBUFHALFFULL)) { - if (emu->capture_mic_interrupt) - emu->capture_mic_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_MICBUFENABLE); - status &= ~(IPR_MICBUFFULL|IPR_MICBUFHALFFULL); - } - if (status & (IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL)) { - if (emu->capture_efx_interrupt) - emu->capture_efx_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_EFXBUFENABLE); - status &= ~(IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL); - } - if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) { - if (emu->midi.interrupt) - emu->midi.interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_MIDITXENABLE|INTE_MIDIRXENABLE); - status &= ~(IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY); - } - if (status & (IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2)) { - if (emu->midi2.interrupt) - emu->midi2.interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_A_MIDITXENABLE2|INTE_A_MIDIRXENABLE2); - status &= ~(IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2); - } - if (status & IPR_INTERVALTIMER) { - if (emu->timer) - snd_timer_interrupt(emu->timer, emu->timer->sticks); - else - snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB); - status &= ~IPR_INTERVALTIMER; - } - if (status & (IPR_GPSPDIFSTATUSCHANGE|IPR_CDROMSTATUSCHANGE)) { - if (emu->spdif_interrupt) - emu->spdif_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_GPSPDIFENABLE|INTE_CDSPDIFENABLE); - status &= ~(IPR_GPSPDIFSTATUSCHANGE|IPR_CDROMSTATUSCHANGE); - } - if (status & IPR_FXDSP) { - if (emu->dsp_interrupt) - emu->dsp_interrupt(emu); - else - snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); - status &= ~IPR_FXDSP; - } - if (status & IPR_P16V) { - while ((status2 = inl(emu->port + IPR2)) != 0) { - u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ - struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]); - struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice); - - //printk(KERN_INFO "status2=0x%x\n", status2); - orig_status2 = status2; - if(status2 & mask) { - if(pvoice->use) { - snd_pcm_period_elapsed(pvoice->epcm->substream); - } else { - snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use); - } - } - if(status2 & 0x110000) { - //printk(KERN_INFO "capture int found\n"); - if(cvoice->use) { - //printk(KERN_INFO "capture period_elapsed\n"); - snd_pcm_period_elapsed(cvoice->epcm->substream); - } - } - outl(orig_status2, emu->port + IPR2); /* ack all */ - } - status &= ~IPR_P16V; - } - - if (status) { - unsigned int bits; - snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status); - //make sure any interrupts we don't handle are disabled: - bits = INTE_FXDSPENABLE | - INTE_PCIERRORENABLE | - INTE_VOLINCRENABLE | - INTE_VOLDECRENABLE | - INTE_MUTEENABLE | - INTE_MICBUFENABLE | - INTE_ADCBUFENABLE | - INTE_EFXBUFENABLE | - INTE_GPSPDIFENABLE | - INTE_CDSPDIFENABLE | - INTE_INTERVALTIMERENB | - INTE_MIDITXENABLE | - INTE_MIDIRXENABLE; - if (emu->audigy) - bits |= INTE_A_MIDITXENABLE2 | INTE_A_MIDIRXENABLE2; - snd_emu10k1_intr_disable(emu, bits); - } - outl(orig_status, emu->port + IPR); /* ack all */ - } - if (timeout == 1000) - snd_printk(KERN_INFO "emu10k1 irq routine failure\n"); - - return IRQ_RETVAL(handled); -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/memory.c b/ANDROID_3.4.5/sound/pci/emu10k1/memory.c deleted file mode 100644 index 4f502a2b..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/memory.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Copyright (c) by Takashi Iwai - * - * EMU10K1 memory page allocation (PTB area) - * - * - * 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 - -/* page arguments of these two macros are Emu page (4096 bytes), not like - * aligned pages in others - */ -#define __set_ptb_entry(emu,page,addr) \ - (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page))) - -#define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) -#define MAX_ALIGN_PAGES (MAXPAGES / UNIT_PAGES) -/* get aligned page from offset address */ -#define get_aligned_page(offset) ((offset) >> PAGE_SHIFT) -/* get offset address from aligned page */ -#define aligned_page_offset(page) ((page) << PAGE_SHIFT) - -#if PAGE_SIZE == 4096 -/* page size == EMUPAGESIZE */ -/* fill PTB entrie(s) corresponding to page with addr */ -#define set_ptb_entry(emu,page,addr) __set_ptb_entry(emu,page,addr) -/* fill PTB entrie(s) corresponding to page with silence pointer */ -#define set_silent_ptb(emu,page) __set_ptb_entry(emu,page,emu->silent_page.addr) -#else -/* fill PTB entries -- we need to fill UNIT_PAGES entries */ -static inline void set_ptb_entry(struct snd_emu10k1 *emu, int page, dma_addr_t addr) -{ - int i; - page *= UNIT_PAGES; - for (i = 0; i < UNIT_PAGES; i++, page++) { - __set_ptb_entry(emu, page, addr); - addr += EMUPAGESIZE; - } -} -static inline void set_silent_ptb(struct snd_emu10k1 *emu, int page) -{ - int i; - page *= UNIT_PAGES; - for (i = 0; i < UNIT_PAGES; i++, page++) - /* do not increment ptr */ - __set_ptb_entry(emu, page, emu->silent_page.addr); -} -#endif /* PAGE_SIZE */ - - -/* - */ -static int synth_alloc_pages(struct snd_emu10k1 *hw, struct snd_emu10k1_memblk *blk); -static int synth_free_pages(struct snd_emu10k1 *hw, struct snd_emu10k1_memblk *blk); - -#define get_emu10k1_memblk(l,member) list_entry(l, struct snd_emu10k1_memblk, member) - - -/* initialize emu10k1 part */ -static void emu10k1_memblk_init(struct snd_emu10k1_memblk *blk) -{ - blk->mapped_page = -1; - INIT_LIST_HEAD(&blk->mapped_link); - INIT_LIST_HEAD(&blk->mapped_order_link); - blk->map_locked = 0; - - blk->first_page = get_aligned_page(blk->mem.offset); - blk->last_page = get_aligned_page(blk->mem.offset + blk->mem.size - 1); - blk->pages = blk->last_page - blk->first_page + 1; -} - -/* - * search empty region on PTB with the given size - * - * if an empty region is found, return the page and store the next mapped block - * in nextp - * if not found, return a negative error code. - */ -static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct list_head **nextp) -{ - int page = 0, found_page = -ENOMEM; - int max_size = npages; - int size; - struct list_head *candidate = &emu->mapped_link_head; - struct list_head *pos; - - list_for_each (pos, &emu->mapped_link_head) { - struct snd_emu10k1_memblk *blk = get_emu10k1_memblk(pos, mapped_link); - if (blk->mapped_page < 0) - continue; - size = blk->mapped_page - page; - if (size == npages) { - *nextp = pos; - return page; - } - else if (size > max_size) { - /* we look for the maximum empty hole */ - max_size = size; - candidate = pos; - found_page = page; - } - page = blk->mapped_page + blk->pages; - } - size = MAX_ALIGN_PAGES - page; - if (size >= max_size) { - *nextp = pos; - return page; - } - *nextp = candidate; - return found_page; -} - -/* - * map a memory block onto emu10k1's PTB - * - * call with memblk_lock held - */ -static int map_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int page, pg; - struct list_head *next; - - page = search_empty_map_area(emu, blk->pages, &next); - if (page < 0) /* not found */ - return page; - /* insert this block in the proper position of mapped list */ - list_add_tail(&blk->mapped_link, next); - /* append this as a newest block in order list */ - list_add_tail(&blk->mapped_order_link, &emu->mapped_order_link_head); - blk->mapped_page = page; - /* fill PTB */ - for (pg = blk->first_page; pg <= blk->last_page; pg++) { - set_ptb_entry(emu, page, emu->page_addr_table[pg]); - page++; - } - return 0; -} - -/* - * unmap the block - * return the size of resultant empty pages - * - * call with memblk_lock held - */ -static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int start_page, end_page, mpage, pg; - struct list_head *p; - struct snd_emu10k1_memblk *q; - - /* calculate the expected size of empty region */ - if ((p = blk->mapped_link.prev) != &emu->mapped_link_head) { - q = get_emu10k1_memblk(p, mapped_link); - start_page = q->mapped_page + q->pages; - } else - start_page = 0; - if ((p = blk->mapped_link.next) != &emu->mapped_link_head) { - q = get_emu10k1_memblk(p, mapped_link); - end_page = q->mapped_page; - } else - end_page = MAX_ALIGN_PAGES; - - /* remove links */ - list_del(&blk->mapped_link); - list_del(&blk->mapped_order_link); - /* clear PTB */ - mpage = blk->mapped_page; - for (pg = blk->first_page; pg <= blk->last_page; pg++) { - set_silent_ptb(emu, mpage); - mpage++; - } - blk->mapped_page = -1; - return end_page - start_page; /* return the new empty size */ -} - -/* - * search empty pages with the given size, and create a memory block - * - * unlike synth_alloc the memory block is aligned to the page start - */ -static struct snd_emu10k1_memblk * -search_empty(struct snd_emu10k1 *emu, int size) -{ - struct list_head *p; - struct snd_emu10k1_memblk *blk; - int page, psize; - - psize = get_aligned_page(size + PAGE_SIZE -1); - page = 0; - list_for_each(p, &emu->memhdr->block) { - blk = get_emu10k1_memblk(p, mem.list); - if (page + psize <= blk->first_page) - goto __found_pages; - page = blk->last_page + 1; - } - if (page + psize > emu->max_cache_pages) - return NULL; - -__found_pages: - /* create a new memory block */ - blk = (struct snd_emu10k1_memblk *)__snd_util_memblk_new(emu->memhdr, psize << PAGE_SHIFT, p->prev); - if (blk == NULL) - return NULL; - blk->mem.offset = aligned_page_offset(page); /* set aligned offset */ - emu10k1_memblk_init(blk); - return blk; -} - - -/* - * check if the given pointer is valid for pages - */ -static int is_valid_page(struct snd_emu10k1 *emu, dma_addr_t addr) -{ - if (addr & ~emu->dma_mask) { - snd_printk(KERN_ERR "max memory size is 0x%lx (addr = 0x%lx)!!\n", emu->dma_mask, (unsigned long)addr); - return 0; - } - if (addr & (EMUPAGESIZE-1)) { - snd_printk(KERN_ERR "page is not aligned\n"); - return 0; - } - return 1; -} - -/* - * map the given memory block on PTB. - * if the block is already mapped, update the link order. - * if no empty pages are found, tries to release unused memory blocks - * and retry the mapping. - */ -int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int err; - int size; - struct list_head *p, *nextp; - struct snd_emu10k1_memblk *deleted; - unsigned long flags; - - spin_lock_irqsave(&emu->memblk_lock, flags); - if (blk->mapped_page >= 0) { - /* update order link */ - list_del(&blk->mapped_order_link); - list_add_tail(&blk->mapped_order_link, &emu->mapped_order_link_head); - spin_unlock_irqrestore(&emu->memblk_lock, flags); - return 0; - } - if ((err = map_memblk(emu, blk)) < 0) { - /* no enough page - try to unmap some blocks */ - /* starting from the oldest block */ - p = emu->mapped_order_link_head.next; - for (; p != &emu->mapped_order_link_head; p = nextp) { - nextp = p->next; - deleted = get_emu10k1_memblk(p, mapped_order_link); - if (deleted->map_locked) - continue; - size = unmap_memblk(emu, deleted); - if (size >= blk->pages) { - /* ok the empty region is enough large */ - err = map_memblk(emu, blk); - break; - } - } - } - spin_unlock_irqrestore(&emu->memblk_lock, flags); - return err; -} - -EXPORT_SYMBOL(snd_emu10k1_memblk_map); - -/* - * page allocation for DMA - */ -struct snd_util_memblk * -snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_util_memhdr *hdr; - struct snd_emu10k1_memblk *blk; - int page, err, idx; - - if (snd_BUG_ON(!emu)) - return NULL; - if (snd_BUG_ON(runtime->dma_bytes <= 0 || - runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE)) - return NULL; - hdr = emu->memhdr; - if (snd_BUG_ON(!hdr)) - return NULL; - - idx = runtime->period_size >= runtime->buffer_size ? - (emu->delay_pcm_irq * 2) : 0; - mutex_lock(&hdr->block_mutex); - blk = search_empty(emu, runtime->dma_bytes + idx); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); - return NULL; - } - /* fill buffer addresses but pointers are not stored so that - * snd_free_pci_page() is not called in in synth_free() - */ - idx = 0; - for (page = blk->first_page; page <= blk->last_page; page++, idx++) { - unsigned long ofs = idx << PAGE_SHIFT; - dma_addr_t addr; - addr = snd_pcm_sgbuf_get_addr(substream, ofs); - if (! is_valid_page(emu, addr)) { - printk(KERN_ERR "emu: failure page = %d\n", idx); - mutex_unlock(&hdr->block_mutex); - return NULL; - } - emu->page_addr_table[page] = addr; - emu->page_ptr_table[page] = NULL; - } - - /* set PTB entries */ - blk->map_locked = 1; /* do not unmap this block! */ - err = snd_emu10k1_memblk_map(emu, blk); - if (err < 0) { - __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); - mutex_unlock(&hdr->block_mutex); - return NULL; - } - mutex_unlock(&hdr->block_mutex); - return (struct snd_util_memblk *)blk; -} - - -/* - * release DMA buffer from page table - */ -int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk) -{ - if (snd_BUG_ON(!emu || !blk)) - return -EINVAL; - return snd_emu10k1_synth_free(emu, blk); -} - - -/* - * memory allocation using multiple pages (for synth) - * Unlike the DMA allocation above, non-contiguous pages are assined. - */ - -/* - * allocate a synth sample area - */ -struct snd_util_memblk * -snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size) -{ - struct snd_emu10k1_memblk *blk; - struct snd_util_memhdr *hdr = hw->memhdr; - - mutex_lock(&hdr->block_mutex); - blk = (struct snd_emu10k1_memblk *)__snd_util_mem_alloc(hdr, size); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); - return NULL; - } - if (synth_alloc_pages(hw, blk)) { - __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); - mutex_unlock(&hdr->block_mutex); - return NULL; - } - snd_emu10k1_memblk_map(hw, blk); - mutex_unlock(&hdr->block_mutex); - return (struct snd_util_memblk *)blk; -} - -EXPORT_SYMBOL(snd_emu10k1_synth_alloc); - -/* - * free a synth sample area - */ -int -snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk) -{ - struct snd_util_memhdr *hdr = emu->memhdr; - struct snd_emu10k1_memblk *blk = (struct snd_emu10k1_memblk *)memblk; - unsigned long flags; - - mutex_lock(&hdr->block_mutex); - spin_lock_irqsave(&emu->memblk_lock, flags); - if (blk->mapped_page >= 0) - unmap_memblk(emu, blk); - spin_unlock_irqrestore(&emu->memblk_lock, flags); - synth_free_pages(emu, blk); - __snd_util_mem_free(hdr, memblk); - mutex_unlock(&hdr->block_mutex); - return 0; -} - -EXPORT_SYMBOL(snd_emu10k1_synth_free); - -/* check new allocation range */ -static void get_single_page_range(struct snd_util_memhdr *hdr, - struct snd_emu10k1_memblk *blk, - int *first_page_ret, int *last_page_ret) -{ - struct list_head *p; - struct snd_emu10k1_memblk *q; - int first_page, last_page; - first_page = blk->first_page; - if ((p = blk->mem.list.prev) != &hdr->block) { - q = get_emu10k1_memblk(p, mem.list); - if (q->last_page == first_page) - first_page++; /* first page was already allocated */ - } - last_page = blk->last_page; - if ((p = blk->mem.list.next) != &hdr->block) { - q = get_emu10k1_memblk(p, mem.list); - if (q->first_page == last_page) - last_page--; /* last page was already allocated */ - } - *first_page_ret = first_page; - *last_page_ret = last_page; -} - -/* release allocated pages */ -static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page, - int last_page) -{ - int page; - - for (page = first_page; page <= last_page; page++) { - free_page((unsigned long)emu->page_ptr_table[page]); - emu->page_addr_table[page] = 0; - emu->page_ptr_table[page] = NULL; - } -} - -/* - * allocate kernel pages - */ -static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int page, first_page, last_page; - - emu10k1_memblk_init(blk); - get_single_page_range(emu->memhdr, blk, &first_page, &last_page); - /* allocate kernel pages */ - for (page = first_page; page <= last_page; page++) { - /* first try to allocate from <4GB zone */ - struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 | - __GFP_NOWARN); - if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) { - if (p) - __free_page(p); - /* try to allocate from <16MB zone */ - p = alloc_page(GFP_ATOMIC | GFP_DMA | - __GFP_NORETRY | /* no OOM-killer */ - __GFP_NOWARN); - } - if (!p) { - __synth_free_pages(emu, first_page, page - 1); - return -ENOMEM; - } - emu->page_addr_table[page] = page_to_phys(p); - emu->page_ptr_table[page] = page_address(p); - } - return 0; -} - -/* - * free pages - */ -static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int first_page, last_page; - - get_single_page_range(emu->memhdr, blk, &first_page, &last_page); - __synth_free_pages(emu, first_page, last_page); - return 0; -} - -/* calculate buffer pointer from offset address */ -static inline void *offset_ptr(struct snd_emu10k1 *emu, int page, int offset) -{ - char *ptr; - if (snd_BUG_ON(page < 0 || page >= emu->max_cache_pages)) - return NULL; - ptr = emu->page_ptr_table[page]; - if (! ptr) { - printk(KERN_ERR "emu10k1: access to NULL ptr: page = %d\n", page); - return NULL; - } - ptr += offset & (PAGE_SIZE - 1); - return (void*)ptr; -} - -/* - * bzero(blk + offset, size) - */ -int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, - int offset, int size) -{ - int page, nextofs, end_offset, temp, temp1; - void *ptr; - struct snd_emu10k1_memblk *p = (struct snd_emu10k1_memblk *)blk; - - offset += blk->offset & (PAGE_SIZE - 1); - end_offset = offset + size; - page = get_aligned_page(offset); - do { - nextofs = aligned_page_offset(page + 1); - temp = nextofs - offset; - temp1 = end_offset - offset; - if (temp1 < temp) - temp = temp1; - ptr = offset_ptr(emu, page + p->first_page, offset); - if (ptr) - memset(ptr, 0, temp); - offset = nextofs; - page++; - } while (offset < end_offset); - return 0; -} - -EXPORT_SYMBOL(snd_emu10k1_synth_bzero); - -/* - * copy_from_user(blk + offset, data, size) - */ -int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, - int offset, const char __user *data, int size) -{ - int page, nextofs, end_offset, temp, temp1; - void *ptr; - struct snd_emu10k1_memblk *p = (struct snd_emu10k1_memblk *)blk; - - offset += blk->offset & (PAGE_SIZE - 1); - end_offset = offset + size; - page = get_aligned_page(offset); - do { - nextofs = aligned_page_offset(page + 1); - temp = nextofs - offset; - temp1 = end_offset - offset; - if (temp1 < temp) - temp = temp1; - ptr = offset_ptr(emu, page + p->first_page, offset); - if (ptr && copy_from_user(ptr, data, temp)) - return -EFAULT; - offset = nextofs; - data += temp; - page++; - } while (offset < end_offset); - return 0; -} - -EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user); diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/p16v.c b/ANDROID_3.4.5/sound/pci/emu10k1/p16v.c deleted file mode 100644 index a81dc442..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/p16v.c +++ /dev/null @@ -1,934 +0,0 @@ -/* - * Copyright (c) by James Courtier-Dutton - * Driver p16v chips - * Version: 0.25 - * - * FEATURES currently supported: - * Output fixed at S32_LE, 2 channel to hw:0,0 - * Rates: 44.1, 48, 96, 192. - * - * Changelog: - * 0.8 - * Use separate card based buffer for periods table. - * 0.9 - * Use 2 channel output streams instead of 8 channel. - * (8 channel output streams might be good for ASIO type output) - * Corrected speaker output, so Front -> Front etc. - * 0.10 - * Fixed missed interrupts. - * 0.11 - * Add Sound card model number and names. - * Add Analog volume controls. - * 0.12 - * Corrected playback interrupts. Now interrupt per period, instead of half period. - * 0.13 - * Use single trigger for multichannel. - * 0.14 - * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo. - * 0.15 - * Force buffer_size / period_size == INTEGER. - * 0.16 - * Update p16v.c to work with changed alsa api. - * 0.17 - * Update p16v.c to work with changed alsa api. Removed boot_devs. - * 0.18 - * Merging with snd-emu10k1 driver. - * 0.19 - * One stereo channel at 24bit now works. - * 0.20 - * Added better register defines. - * 0.21 - * Integrated with snd-emu10k1 driver. - * 0.22 - * Removed #if 0 ... #endif - * 0.23 - * Implement different capture rates. - * 0.24 - * Implement different capture source channels. - * e.g. When HD Capture source is set to SPDIF, - * setting HD Capture channel to 0 captures from CDROM digital input. - * setting HD Capture channel to 1 captures from SPDIF in. - * 0.25 - * Include capture buffer sizes. - * - * BUGS: - * Some stability problems when unloading the snd-p16v kernel module. - * -- - * - * TODO: - * SPDIF out. - * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz. - * Currently capture fixed at 48000Hz. - * - * -- - * GENERAL INFO: - * Model: SB0240 - * P16V Chip: CA0151-DBS - * Audigy 2 Chip: CA0102-IAT - * AC97 Codec: STAC 9721 - * ADC: Philips 1361T (Stereo 24bit) - * DAC: CS4382-K (8-channel, 24bit, 192Khz) - * - * This code was initially based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes - * - * 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 -#include -#include -#include -#include -#include -#include "p16v.h" - -#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ -#define PCM_FRONT_CHANNEL 0 -#define PCM_REAR_CHANNEL 1 -#define PCM_CENTER_LFE_CHANNEL 2 -#define PCM_SIDE_CHANNEL 3 -#define CONTROL_FRONT_CHANNEL 0 -#define CONTROL_REAR_CHANNEL 3 -#define CONTROL_CENTER_LFE_CHANNEL 1 -#define CONTROL_SIDE_CHANNEL 2 - -/* Card IDs: - * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350 - * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1 Model:SB0240 - * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum Model:SB msb0240230009266 - * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB0380472001901E - * - */ - - /* hardware definition */ -static struct snd_pcm_hardware snd_p16v_playback_hw = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ - .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .rate_min = 44100, - .rate_max = 192000, - .channels_min = 8, - .channels_max = 8, - .buffer_bytes_max = ((65536 - 64) * 8), - .period_bytes_min = 64, - .period_bytes_max = (65536 - 64), - .periods_min = 2, - .periods_max = 8, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_p16v_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .rate_min = 44100, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (65536 - 64), - .period_bytes_min = 64, - .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */ - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - struct snd_emu10k1_pcm *epcm = runtime->private_data; - - if (epcm) { - /* snd_printk(KERN_DEBUG "epcm free: %p\n", epcm); */ - kfree(epcm); - } -} - -/* open_playback callback */ -static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]); - struct snd_emu10k1_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ - - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->substream = substream; - /* - snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", - substream->pcm->device, channel_id); - */ - runtime->private_data = epcm; - runtime->private_free = snd_p16v_pcm_free_substream; - - runtime->hw = snd_p16v_playback_hw; - - channel->emu = emu; - channel->number = channel_id; - - channel->use=1; -#if 0 /* debug */ - snd_printk(KERN_DEBUG - "p16v: open channel_id=%d, channel=%p, use=0x%x\n", - channel_id, channel, channel->use); - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", - channel_id, chip, channel); -#endif /* debug */ - /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ - channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - runtime->sync.id32[0] = substream->pcm->card->number; - runtime->sync.id32[1] = 'P'; - runtime->sync.id32[2] = 16; - runtime->sync.id32[3] = 'V'; - - return 0; -} -/* open_capture callback */ -static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice); - struct snd_emu10k1_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ - - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->substream = substream; - /* - snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", - substream->pcm->device, channel_id); - */ - runtime->private_data = epcm; - runtime->private_free = snd_p16v_pcm_free_substream; - - runtime->hw = snd_p16v_capture_hw; - - channel->emu = emu; - channel->number = channel_id; - - channel->use=1; -#if 0 /* debug */ - snd_printk(KERN_DEBUG - "p16v: open channel_id=%d, channel=%p, use=0x%x\n", - channel_id, channel, channel->use); - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", - channel_id, chip, channel); -#endif /* debug */ - /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ - channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - return 0; -} - - -/* close callback */ -static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - //struct snd_pcm_runtime *runtime = substream->runtime; - //struct snd_emu10k1_pcm *epcm = runtime->private_data; - emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0; - /* FIXME: maybe zero others */ - return 0; -} - -/* close callback */ -static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - //struct snd_pcm_runtime *runtime = substream->runtime; - //struct snd_emu10k1_pcm *epcm = runtime->private_data; - emu->p16v_capture_voice.use = 0; - /* FIXME: maybe zero others */ - return 0; -} - -static int snd_p16v_pcm_open_playback_front(struct snd_pcm_substream *substream) -{ - return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL); -} - -static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream) -{ - // Only using channel 0 for now, but the card has 2 channels. - return snd_p16v_pcm_open_capture_channel(substream, 0); -} - -/* hw_params callback */ -static int snd_p16v_pcm_hw_params_playback(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int result; - result = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - return result; -} - -/* hw_params callback */ -static int snd_p16v_pcm_hw_params_capture(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int result; - result = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - return result; -} - - -/* hw_free callback */ -static int snd_p16v_pcm_hw_free_playback(struct snd_pcm_substream *substream) -{ - int result; - result = snd_pcm_lib_free_pages(substream); - return result; -} - -/* hw_free callback */ -static int snd_p16v_pcm_hw_free_capture(struct snd_pcm_substream *substream) -{ - int result; - result = snd_pcm_lib_free_pages(substream); - return result; -} - - -/* prepare playback callback */ -static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int channel = substream->pcm->device - emu->p16v_device_offset; - u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel)); - u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); - int i; - u32 tmp; - -#if 0 /* debug */ - snd_printk(KERN_DEBUG "prepare:channel_number=%d, rate=%d, " - "format=0x%x, channels=%d, buffer_size=%ld, " - "period_size=%ld, periods=%u, frames_to_bytes=%d\n", - channel, runtime->rate, runtime->format, runtime->channels, - runtime->buffer_size, runtime->period_size, - runtime->periods, frames_to_bytes(runtime, 1)); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", - runtime->dma_addr, runtime->dma_area, table_base); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", - emu->p16v_buffer.addr, emu->p16v_buffer.area, - emu->p16v_buffer.bytes); -#endif /* debug */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); - switch (runtime->rate) { - case 44100: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080); - break; - case 96000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040); - break; - case 192000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020); - break; - case 48000: - default: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000); - break; - } - /* FIXME: Check emu->buffer.size before actually writing to it. */ - for(i = 0; i < runtime->periods; i++) { - table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); - table_base[(i*2)+1]=period_size_bytes<<16; - } - - snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel)); - snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); - snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0); - snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); - //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes - snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes - snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0); - snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0); - snd_emu10k1_ptr20_write(emu, 0x08, channel, 0); - - return 0; -} - -/* prepare capture callback */ -static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int channel = substream->pcm->device - emu->p16v_device_offset; - u32 tmp; - - /* - printk(KERN_DEBUG "prepare capture:channel_number=%d, rate=%d, " - "format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, " - "frames_to_bytes=%d\n", - channel, runtime->rate, runtime->format, runtime->channels, - runtime->buffer_size, runtime->period_size, - frames_to_bytes(runtime, 1)); - */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); - switch (runtime->rate) { - case 44100: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800); - break; - case 96000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400); - break; - case 192000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200); - break; - case 48000: - default: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000); - break; - } - /* FIXME: Check emu->buffer.size before actually writing to it. */ - snd_emu10k1_ptr20_write(emu, 0x13, channel, 0); - snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); - snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes - snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0); - //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */ - //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<emu_lock, flags); - enable = inl(emu->port + INTE2) | intrenb; - outl(enable, emu->port + INTE2); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int disable; - - spin_lock_irqsave(&emu->emu_lock, flags); - disable = inl(emu->port + INTE2) & (~intrenb); - outl(disable, emu->port + INTE2); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -/* trigger_playback callback */ -static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime; - struct snd_emu10k1_pcm *epcm; - int channel; - int result = 0; - struct snd_pcm_substream *s; - u32 basic = 0; - u32 inte = 0; - int running = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - running=1; - break; - case SNDRV_PCM_TRIGGER_STOP: - default: - running = 0; - break; - } - snd_pcm_group_for_each_entry(s, substream) { - if (snd_pcm_substream_chip(s) != emu || - s->stream != SNDRV_PCM_STREAM_PLAYBACK) - continue; - runtime = s->runtime; - epcm = runtime->private_data; - channel = substream->pcm->device-emu->p16v_device_offset; - /* snd_printk(KERN_DEBUG "p16v channel=%d\n", channel); */ - epcm->running = running; - basic |= (0x1<runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int channel = 0; - int result = 0; - u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_p16v_intr_enable(emu, inte); - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<running = 0; - break; - default: - result = -EINVAL; - break; - } - return result; -} - -/* pointer_playback callback */ -static snd_pcm_uframes_t -snd_p16v_pcm_pointer_playback(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0; - int channel = substream->pcm->device - emu->p16v_device_offset; - if (!epcm->running) - return 0; - - ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); - ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel); - ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); - if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel); - ptr2 = bytes_to_frames(runtime, ptr1); - ptr2+= (ptr4 >> 3) * runtime->period_size; - ptr=ptr2; - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - - return ptr; -} - -/* pointer_capture callback */ -static snd_pcm_uframes_t -snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - snd_pcm_uframes_t ptr, ptr1, ptr2 = 0; - int channel = 0; - - if (!epcm->running) - return 0; - - ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel); - ptr2 = bytes_to_frames(runtime, ptr1); - ptr=ptr2; - if (ptr >= runtime->buffer_size) { - ptr -= runtime->buffer_size; - printk(KERN_WARNING "buffer capture limited!\n"); - } - /* - printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " - "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", - ptr1, ptr2, ptr, (int)runtime->buffer_size, - (int)runtime->period_size, (int)runtime->frame_bits, - (int)runtime->rate); - */ - return ptr; -} - -/* operators */ -static struct snd_pcm_ops snd_p16v_playback_front_ops = { - .open = snd_p16v_pcm_open_playback_front, - .close = snd_p16v_pcm_close_playback, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_p16v_pcm_hw_params_playback, - .hw_free = snd_p16v_pcm_hw_free_playback, - .prepare = snd_p16v_pcm_prepare_playback, - .trigger = snd_p16v_pcm_trigger_playback, - .pointer = snd_p16v_pcm_pointer_playback, -}; - -static struct snd_pcm_ops snd_p16v_capture_ops = { - .open = snd_p16v_pcm_open_capture, - .close = snd_p16v_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_p16v_pcm_hw_params_capture, - .hw_free = snd_p16v_pcm_hw_free_capture, - .prepare = snd_p16v_pcm_prepare_capture, - .trigger = snd_p16v_pcm_trigger_capture, - .pointer = snd_p16v_pcm_pointer_capture, -}; - - -int snd_p16v_free(struct snd_emu10k1 *chip) -{ - // release the data - if (chip->p16v_buffer.area) { - snd_dma_free_pages(&chip->p16v_buffer); - /* - snd_printk(KERN_DEBUG "period lables free: %p\n", - &chip->p16v_buffer); - */ - } - return 0; -} - -int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int err; - int capture=1; - - /* snd_printk(KERN_DEBUG "snd_p16v_pcm called. device=%d\n", device); */ - emu->p16v_device_offset = device; - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0) - return err; - - pcm->private_data = emu; - // Single playback 8 channel device. - // Single capture 2 channel device. - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, "p16v"); - emu->pcm_p16v = pcm; - - for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - substream; - substream = substream->next) { - if ((err = snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) - return err; - /* - snd_printk(KERN_DEBUG - "preallocate playback substream: err=%d\n", err); - */ - } - - for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - substream; - substream = substream->next) { - if ((err = snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - 65536 - 64, 65536 - 64)) < 0) - return err; - /* - snd_printk(KERN_DEBUG - "preallocate capture substream: err=%d\n", err); - */ - } - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -static int snd_p16v_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_p16v_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int high_low = (kcontrol->private_value >> 8) & 0xff; - int reg = kcontrol->private_value & 0xff; - u32 value; - - value = snd_emu10k1_ptr20_read(emu, reg, high_low); - if (high_low) { - ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */ - ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */ - } else { - ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */ - ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */ - } - return 0; -} - -static int snd_p16v_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int high_low = (kcontrol->private_value >> 8) & 0xff; - int reg = kcontrol->private_value & 0xff; - u32 value, oval; - - oval = value = snd_emu10k1_ptr20_read(emu, reg, 0); - if (high_low == 1) { - value &= 0xffff; - value |= ((0xff - ucontrol->value.integer.value[0]) << 24) | - ((0xff - ucontrol->value.integer.value[1]) << 16); - } else { - value &= 0xffff0000; - value |= ((0xff - ucontrol->value.integer.value[0]) << 8) | - ((0xff - ucontrol->value.integer.value[1]) ); - } - if (value != oval) { - snd_emu10k1_ptr20_write(emu, reg, 0, value); - return 1; - } - return 0; -} - -static int snd_p16v_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[8] = { - "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", - "CDIF", "FX", "AC97" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item > 7) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_p16v_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->p16v_capture_source; - return 0; -} - -static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - u32 mask; - u32 source; - - val = ucontrol->value.enumerated.item[0] ; - if (val > 7) - return -EINVAL; - change = (emu->p16v_capture_source != val); - if (change) { - emu->p16v_capture_source = val; - source = (val << 28) | (val << 24) | (val << 20) | (val << 16); - mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff; - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask); - } - return change; -} - -static int snd_p16v_capture_channel_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { "0", "1", "2", "3", }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_p16v_capture_channel_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel; - return 0; -} - -static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - u32 tmp; - - val = ucontrol->value.enumerated.item[0] ; - if (val > 3) - return -EINVAL; - change = (emu->p16v_capture_channel != val); - if (change) { - emu->p16v_capture_channel = val; - tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc; - snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val); - } - return change; -} -static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1); - -#define P16V_VOL(xname,xreg,xhl) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_p16v_volume_info, \ - .get = snd_p16v_volume_get, \ - .put = snd_p16v_volume_put, \ - .tlv = { .p = snd_p16v_db_scale1 }, \ - .private_value = ((xreg) | ((xhl) << 8)) \ -} - -static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = { - P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0), - P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1), - P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1), - P16V_VOL("HD Analog Side Playback Volume", PLAYBACK_VOLUME_MIXER10, 0), - P16V_VOL("HD SPDIF Front Playback Volume", PLAYBACK_VOLUME_MIXER7, 0), - P16V_VOL("HD SPDIF Rear Playback Volume", PLAYBACK_VOLUME_MIXER8, 1), - P16V_VOL("HD SPDIF Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER7, 1), - P16V_VOL("HD SPDIF Side Playback Volume", PLAYBACK_VOLUME_MIXER8, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HD source Capture", - .info = snd_p16v_capture_source_info, - .get = snd_p16v_capture_source_get, - .put = snd_p16v_capture_source_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HD channel Capture", - .info = snd_p16v_capture_channel_info, - .get = snd_p16v_capture_channel_get, - .put = snd_p16v_capture_channel_put - }, -}; - - -int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu) -{ - int i, err; - struct snd_card *card = emu->card; - - for (i = 0; i < ARRAY_SIZE(p16v_mixer_controls); i++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&p16v_mixer_controls[i], - emu))) < 0) - return err; - } - return 0; -} - -#ifdef CONFIG_PM - -#define NUM_CHS 1 /* up to 4, but only first channel is used */ - -int __devinit snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu) -{ - emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80); - if (! emu->p16v_saved) - return -ENOMEM; - return 0; -} - -void snd_p16v_free_pm_buffer(struct snd_emu10k1 *emu) -{ - vfree(emu->p16v_saved); -} - -void snd_p16v_suspend(struct snd_emu10k1 *emu) -{ - int i, ch; - unsigned int *val; - - val = emu->p16v_saved; - for (ch = 0; ch < NUM_CHS; ch++) - for (i = 0; i < 0x80; i++, val++) - *val = snd_emu10k1_ptr20_read(emu, i, ch); -} - -void snd_p16v_resume(struct snd_emu10k1 *emu) -{ - int i, ch; - unsigned int *val; - - val = emu->p16v_saved; - for (ch = 0; ch < NUM_CHS; ch++) - for (i = 0; i < 0x80; i++, val++) - snd_emu10k1_ptr20_write(emu, i, ch, *val); -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/p16v.h b/ANDROID_3.4.5/sound/pci/emu10k1/p16v.h deleted file mode 100644 index 4e0ee1a9..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/p16v.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) by James Courtier-Dutton - * Driver p16v chips - * Version: 0.21 - * - * FEATURES currently supported: - * Output fixed at S32_LE, 2 channel to hw:0,0 - * Rates: 44.1, 48, 96, 192. - * - * Changelog: - * 0.8 - * Use separate card based buffer for periods table. - * 0.9 - * Use 2 channel output streams instead of 8 channel. - * (8 channel output streams might be good for ASIO type output) - * Corrected speaker output, so Front -> Front etc. - * 0.10 - * Fixed missed interrupts. - * 0.11 - * Add Sound card model number and names. - * Add Analog volume controls. - * 0.12 - * Corrected playback interrupts. Now interrupt per period, instead of half period. - * 0.13 - * Use single trigger for multichannel. - * 0.14 - * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo. - * 0.15 - * Force buffer_size / period_size == INTEGER. - * 0.16 - * Update p16v.c to work with changed alsa api. - * 0.17 - * Update p16v.c to work with changed alsa api. Removed boot_devs. - * 0.18 - * Merging with snd-emu10k1 driver. - * 0.19 - * One stereo channel at 24bit now works. - * 0.20 - * Added better register defines. - * 0.21 - * Split from p16v.c - * - * - * BUGS: - * Some stability problems when unloading the snd-p16v kernel module. - * -- - * - * TODO: - * SPDIF out. - * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz. - * Currently capture fixed at 48000Hz. - * - * -- - * GENERAL INFO: - * Model: SB0240 - * P16V Chip: CA0151-DBS - * Audigy 2 Chip: CA0102-IAT - * AC97 Codec: STAC 9721 - * ADC: Philips 1361T (Stereo 24bit) - * DAC: CS4382-K (8-channel, 24bit, 192Khz) - * - * This code was initially based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes - * - * 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 - * - */ - -/********************************************************************************************************/ -/* Audigy2 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers */ -/********************************************************************************************************/ - -/* The sample rate of the SPDIF outputs is set by modifying a register in the EMU10K2 PTR register A_SPDIF_SAMPLERATE. - * The sample rate is also controlled by the same registers that control the rate of the EMU10K2 sample rate converters. - */ - -/* Initially all registers from 0x00 to 0x3f have zero contents. */ -#define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */ - /* One list entry: 4 bytes for DMA address, - * 4 bytes for period_size << 16. - * One list entry is 8 bytes long. - * One list entry for each period in the buffer. - */ -#define PLAYBACK_LIST_SIZE 0x01 /* Size of list in bytes << 16. E.g. 8 periods -> 0x00380000 */ -#define PLAYBACK_LIST_PTR 0x02 /* Pointer to the current period being played */ -#define PLAYBACK_UNKNOWN3 0x03 /* Not used */ -#define PLAYBACK_DMA_ADDR 0x04 /* Playback DMA address */ -#define PLAYBACK_PERIOD_SIZE 0x05 /* Playback period size. win2000 uses 0x04000000 */ -#define PLAYBACK_POINTER 0x06 /* Playback period pointer. Used with PLAYBACK_LIST_PTR to determine buffer position currently in DAC */ -#define PLAYBACK_FIFO_END_ADDRESS 0x07 /* Playback FIFO end address */ -#define PLAYBACK_FIFO_POINTER 0x08 /* Playback FIFO pointer and number of valid sound samples in cache */ -#define PLAYBACK_UNKNOWN9 0x09 /* Not used */ -#define CAPTURE_DMA_ADDR 0x10 /* Capture DMA address */ -#define CAPTURE_BUFFER_SIZE 0x11 /* Capture buffer size */ -#define CAPTURE_POINTER 0x12 /* Capture buffer pointer. Sample currently in ADC */ -#define CAPTURE_FIFO_POINTER 0x13 /* Capture FIFO pointer and number of valid sound samples in cache */ -#define CAPTURE_P16V_VOLUME1 0x14 /* Low: Capture volume 0xXXXX3030 */ -#define CAPTURE_P16V_VOLUME2 0x15 /* High:Has no effect on capture volume */ -#define CAPTURE_P16V_SOURCE 0x16 /* P16V source select. Set to 0x0700E4E5 for AC97 CAPTURE */ - /* [0:1] Capture input 0 channel select. 0 = Capture output 0. - * 1 = Capture output 1. - * 2 = Capture output 2. - * 3 = Capture output 3. - * [3:2] Capture input 1 channel select. 0 = Capture output 0. - * 1 = Capture output 1. - * 2 = Capture output 2. - * 3 = Capture output 3. - * [5:4] Capture input 2 channel select. 0 = Capture output 0. - * 1 = Capture output 1. - * 2 = Capture output 2. - * 3 = Capture output 3. - * [7:6] Capture input 3 channel select. 0 = Capture output 0. - * 1 = Capture output 1. - * 2 = Capture output 2. - * 3 = Capture output 3. - * [9:8] Playback input 0 channel select. 0 = Play output 0. - * 1 = Play output 1. - * 2 = Play output 2. - * 3 = Play output 3. - * [11:10] Playback input 1 channel select. 0 = Play output 0. - * 1 = Play output 1. - * 2 = Play output 2. - * 3 = Play output 3. - * [13:12] Playback input 2 channel select. 0 = Play output 0. - * 1 = Play output 1. - * 2 = Play output 2. - * 3 = Play output 3. - * [15:14] Playback input 3 channel select. 0 = Play output 0. - * 1 = Play output 1. - * 2 = Play output 2. - * 3 = Play output 3. - * [19:16] Playback mixer output enable. 1 bit per channel. - * [23:20] Capture mixer output enable. 1 bit per channel. - * [26:24] FX engine channel capture 0 = 0x60-0x67. - * 1 = 0x68-0x6f. - * 2 = 0x70-0x77. - * 3 = 0x78-0x7f. - * 4 = 0x80-0x87. - * 5 = 0x88-0x8f. - * 6 = 0x90-0x97. - * 7 = 0x98-0x9f. - * [31:27] Not used. - */ - - /* 0x1 = capture on. - * 0x100 = capture off. - * 0x200 = capture off. - * 0x1000 = capture off. - */ -#define CAPTURE_RATE_STATUS 0x17 /* Capture sample rate. Read only */ - /* [15:0] Not used. - * [18:16] Channel 0 Detected sample rate. 0 - 44.1khz - * 1 - 48 khz - * 2 - 96 khz - * 3 - 192 khz - * 7 - undefined rate. - * [19] Channel 0. 1 - Valid, 0 - Not Valid. - * [22:20] Channel 1 Detected sample rate. - * [23] Channel 1. 1 - Valid, 0 - Not Valid. - * [26:24] Channel 2 Detected sample rate. - * [27] Channel 2. 1 - Valid, 0 - Not Valid. - * [30:28] Channel 3 Detected sample rate. - * [31] Channel 3. 1 - Valid, 0 - Not Valid. - */ -/* 0x18 - 0x1f unused */ -#define PLAYBACK_LAST_SAMPLE 0x20 /* The sample currently being played. Read only */ -/* 0x21 - 0x3f unused */ -#define BASIC_INTERRUPT 0x40 /* Used by both playback and capture interrupt handler */ - /* Playback (0x1< 77770000 so it must be some sort of route. - * bit 0x1 starts DMA playback on channel_id 0 - */ -/* 0x41,42 take values from 0 - 0xffffffff, but have no effect on playback */ -/* 0x43,0x48 do not remember settings */ -/* 0x41-45 unused */ -#define WATERMARK 0x46 /* Test bit to indicate cache level usage */ - /* Values it can have while playing on channel 0. - * 0000f000, 0000f004, 0000f008, 0000f00c. - * Readonly. - */ -/* 0x47-0x4f unused */ -/* 0x50-0x5f Capture cache data */ -#define SRCSel 0x60 /* SRCSel. Default 0x4. Bypass P16V 0x14 */ - /* [0] 0 = 10K2 audio, 1 = SRC48 mixer output. - * [2] 0 = 10K2 audio, 1 = SRCMulti SPDIF mixer output. - * [4] 0 = 10K2 audio, 1 = SRCMulti I2S mixer output. - */ - /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */ - /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */ - /* SRC48 and SRCMULTI sample rate select and output select. */ - /* 0xffffffff -> 0xC0000015 - * 0xXXXXXXX4 = Enable Front Left/Right - * Enable PCMs - */ - -/* 0x61 -> 0x6c are Volume controls */ -#define PLAYBACK_VOLUME_MIXER1 0x61 /* SRC48 Low to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER2 0x62 /* SRC48 High to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER3 0x63 /* SRCMULTI SPDIF Low to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER4 0x64 /* SRCMULTI SPDIF High to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER5 0x65 /* SRCMULTI I2S Low to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER6 0x66 /* SRCMULTI I2S High to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER7 0x67 /* P16V Low to SRCMULTI SPDIF mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER8 0x68 /* P16V High to SRCMULTI SPDIF mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER9 0x69 /* P16V Low to SRCMULTI I2S mixer input volume control. */ - /* 0xXXXX3030 = PCM0 Volume (Front). - * 0x3030XXXX = PCM1 Volume (Center) - */ -#define PLAYBACK_VOLUME_MIXER10 0x6a /* P16V High to SRCMULTI I2S mixer input volume control. */ - /* 0x3030XXXX = PCM3 Volume (Rear). */ -#define PLAYBACK_VOLUME_MIXER11 0x6b /* E10K2 Low to SRC48 mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER12 0x6c /* E10K2 High to SRC48 mixer input volume control. */ - -#define SRC48_ENABLE 0x6d /* SRC48 input audio enable */ - /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */ - /* [23:16] The corresponding P16V channel to SRC48 enabled if == 1. - * [31:24] The corresponding E10K2 channel to SRC48 enabled. - */ -#define SRCMULTI_ENABLE 0x6e /* SRCMulti input audio enable. Default 0xffffffff */ - /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */ - /* [7:0] The corresponding P16V channel to SRCMulti_I2S enabled if == 1. - * [15:8] The corresponding E10K2 channel to SRCMulti I2S enabled. - * [23:16] The corresponding P16V channel to SRCMulti SPDIF enabled. - * [31:24] The corresponding E10K2 channel to SRCMulti SPDIF enabled. - */ - /* Bypass P16V 0xff00ff00 - * Bitmap. 0 = Off, 1 = On. - * P16V playback outputs: - * 0xXXXXXXX1 = PCM0 Left. (Front) - * 0xXXXXXXX2 = PCM0 Right. - * 0xXXXXXXX4 = PCM1 Left. (Center/LFE) - * 0xXXXXXXX8 = PCM1 Right. - * 0xXXXXXX1X = PCM2 Left. (Unknown) - * 0xXXXXXX2X = PCM2 Right. - * 0xXXXXXX4X = PCM3 Left. (Rear) - * 0xXXXXXX8X = PCM3 Right. - */ -#define AUDIO_OUT_ENABLE 0x6f /* Default: 000100FF */ - /* [3:0] Does something, but not documented. Probably capture enable. - * [7:4] Playback channels enable. not documented. - * [16] AC97 output enable if == 1 - * [30] 0 = SRCMulti_I2S input from fxengine 0x68-0x6f. - * 1 = SRCMulti_I2S input from SRC48 output. - * [31] 0 = SRCMulti_SPDIF input from fxengine 0x60-0x67. - * 1 = SRCMulti_SPDIF input from SRC48 output. - */ - /* 0xffffffff -> C00100FF */ - /* 0 -> Not playback sound, irq still running */ - /* 0xXXXXXX10 = PCM0 Left/Right On. (Front) - * 0xXXXXXX20 = PCM1 Left/Right On. (Center/LFE) - * 0xXXXXXX40 = PCM2 Left/Right On. (Unknown) - * 0xXXXXXX80 = PCM3 Left/Right On. (Rear) - */ -#define PLAYBACK_SPDIF_SELECT 0x70 /* Default: 12030F00 */ - /* 0xffffffff -> 3FF30FFF */ - /* 0x00000001 pauses stream/irq fail. */ - /* All other bits do not effect playback */ -#define PLAYBACK_SPDIF_SRC_SELECT 0x71 /* Default: 0000E4E4 */ - /* 0xffffffff -> F33FFFFF */ - /* All bits do not effect playback */ -#define PLAYBACK_SPDIF_USER_DATA0 0x72 /* SPDIF out user data 0 */ -#define PLAYBACK_SPDIF_USER_DATA1 0x73 /* SPDIF out user data 1 */ -/* 0x74-0x75 unknown */ -#define CAPTURE_SPDIF_CONTROL 0x76 /* SPDIF in control setting */ -#define CAPTURE_SPDIF_STATUS 0x77 /* SPDIF in status */ -#define CAPURE_SPDIF_USER_DATA0 0x78 /* SPDIF in user data 0 */ -#define CAPURE_SPDIF_USER_DATA1 0x79 /* SPDIF in user data 1 */ -#define CAPURE_SPDIF_USER_DATA2 0x7a /* SPDIF in user data 2 */ - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/p17v.h b/ANDROID_3.4.5/sound/pci/emu10k1/p17v.h deleted file mode 100644 index 4ef5f68a..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/p17v.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) by James Courtier-Dutton - * Driver p17v chips - * Version: 0.01 - * - * 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 - * - */ - -/******************************************************************************/ -/* Audigy2Value Tina (P17V) pointer-offset register set, - * accessed through the PTR20 and DATA24 registers */ -/******************************************************************************/ - -/* 00 - 07: Not used */ -#define P17V_PLAYBACK_FIFO_PTR 0x08 /* Current playback fifo pointer - * and number of sound samples in cache. - */ -/* 09 - 12: Not used */ -#define P17V_CAPTURE_FIFO_PTR 0x13 /* Current capture fifo pointer - * and number of sound samples in cache. - */ -/* 14 - 17: Not used */ -#define P17V_PB_CHN_SEL 0x18 /* P17v playback channel select */ -#define P17V_SE_SLOT_SEL_L 0x19 /* Sound Engine slot select low */ -#define P17V_SE_SLOT_SEL_H 0x1a /* Sound Engine slot select high */ -/* 1b - 1f: Not used */ -/* 20 - 2f: Not used */ -/* 30 - 3b: Not used */ -#define P17V_SPI 0x3c /* SPI interface register */ -#define P17V_I2C_ADDR 0x3d /* I2C Address */ -#define P17V_I2C_0 0x3e /* I2C Data */ -#define P17V_I2C_1 0x3f /* I2C Data */ -/* I2C values */ -#define I2C_A_ADC_ADD_MASK 0x000000fe /*The address is a 7 bit address */ -#define I2C_A_ADC_RW_MASK 0x00000001 /*bit mask for R/W */ -#define I2C_A_ADC_TRANS_MASK 0x00000010 /*Bit mask for I2c address DAC value */ -#define I2C_A_ADC_ABORT_MASK 0x00000020 /*Bit mask for I2C transaction abort flag */ -#define I2C_A_ADC_LAST_MASK 0x00000040 /*Bit mask for Last word transaction */ -#define I2C_A_ADC_BYTE_MASK 0x00000080 /*Bit mask for Byte Mode */ - -#define I2C_A_ADC_ADD 0x00000034 /*This is the Device address for ADC */ -#define I2C_A_ADC_READ 0x00000001 /*To perform a read operation */ -#define I2C_A_ADC_START 0x00000100 /*Start I2C transaction */ -#define I2C_A_ADC_ABORT 0x00000200 /*I2C transaction abort */ -#define I2C_A_ADC_LAST 0x00000400 /*I2C last transaction */ -#define I2C_A_ADC_BYTE 0x00000800 /*I2C one byte mode */ - -#define I2C_D_ADC_REG_MASK 0xfe000000 /*ADC address register */ -#define I2C_D_ADC_DAT_MASK 0x01ff0000 /*ADC data register */ - -#define ADC_TIMEOUT 0x00000007 /*ADC Timeout Clock Disable */ -#define ADC_IFC_CTRL 0x0000000b /*ADC Interface Control */ -#define ADC_MASTER 0x0000000c /*ADC Master Mode Control */ -#define ADC_POWER 0x0000000d /*ADC PowerDown Control */ -#define ADC_ATTEN_ADCL 0x0000000e /*ADC Attenuation ADCL */ -#define ADC_ATTEN_ADCR 0x0000000f /*ADC Attenuation ADCR */ -#define ADC_ALC_CTRL1 0x00000010 /*ADC ALC Control 1 */ -#define ADC_ALC_CTRL2 0x00000011 /*ADC ALC Control 2 */ -#define ADC_ALC_CTRL3 0x00000012 /*ADC ALC Control 3 */ -#define ADC_NOISE_CTRL 0x00000013 /*ADC Noise Gate Control */ -#define ADC_LIMIT_CTRL 0x00000014 /*ADC Limiter Control */ -#define ADC_MUX 0x00000015 /*ADC Mux offset */ -#if 0 -/* FIXME: Not tested yet. */ -#define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain -#define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB -#define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute -#define ADC_MUTE 0x000000c0 //Value to mute ADC -#define ADC_OSR 0x00000008 //Mask for ADC oversample rate select -#define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock -#define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter -#define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window -#endif - -#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux -#define ADC_MUX_0 0x00000001 //Value to select Unknown at ADC Mux (Not used) -#define ADC_MUX_1 0x00000002 //Value to select Unknown at ADC Mux (Not used) -#define ADC_MUX_2 0x00000004 //Value to select Mic at ADC Mux -#define ADC_MUX_3 0x00000008 //Value to select Line-In at ADC Mux - -#define P17V_START_AUDIO 0x40 /* Start Audio bit */ -/* 41 - 47: Reserved */ -#define P17V_START_CAPTURE 0x48 /* Start Capture bit */ -#define P17V_CAPTURE_FIFO_BASE 0x49 /* Record FIFO base address */ -#define P17V_CAPTURE_FIFO_SIZE 0x4a /* Record FIFO buffer size */ -#define P17V_CAPTURE_FIFO_INDEX 0x4b /* Record FIFO capture index */ -#define P17V_CAPTURE_VOL_H 0x4c /* P17v capture volume control */ -#define P17V_CAPTURE_VOL_L 0x4d /* P17v capture volume control */ -/* 4e - 4f: Not used */ -/* 50 - 5f: Not used */ -#define P17V_SRCSel 0x60 /* SRC48 and SRCMulti sample rate select - * and output select - */ -#define P17V_MIXER_AC97_10K1_VOL_L 0x61 /* 10K to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_10K1_VOL_H 0x62 /* 10K to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_P17V_VOL_L 0x63 /* P17V to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_P17V_VOL_H 0x64 /* P17V to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_SRP_REC_VOL_L 0x65 /* SRP Record to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_SRP_REC_VOL_H 0x66 /* SRP Record to Mixer_AC97 input volume control */ -/* 67 - 68: Reserved */ -#define P17V_MIXER_Spdif_10K1_VOL_L 0x69 /* 10K to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_10K1_VOL_H 0x6A /* 10K to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_P17V_VOL_L 0x6B /* P17V to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_P17V_VOL_H 0x6C /* P17V to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_SRP_REC_VOL_L 0x6D /* SRP Record to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_SRP_REC_VOL_H 0x6E /* SRP Record to Mixer_Spdif input volume control */ -/* 6f - 70: Reserved */ -#define P17V_MIXER_I2S_10K1_VOL_L 0x71 /* 10K to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_10K1_VOL_H 0x72 /* 10K to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_P17V_VOL_L 0x73 /* P17V to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_P17V_VOL_H 0x74 /* P17V to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_SRP_REC_VOL_L 0x75 /* SRP Record to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_SRP_REC_VOL_H 0x76 /* SRP Record to Mixer_I2S input volume control */ -/* 77 - 78: Reserved */ -#define P17V_MIXER_AC97_ENABLE 0x79 /* Mixer AC97 input audio enable */ -#define P17V_MIXER_SPDIF_ENABLE 0x7A /* Mixer SPDIF input audio enable */ -#define P17V_MIXER_I2S_ENABLE 0x7B /* Mixer I2S input audio enable */ -#define P17V_AUDIO_OUT_ENABLE 0x7C /* Audio out enable */ -#define P17V_MIXER_ATT 0x7D /* SRP Mixer Attenuation Select */ -#define P17V_SRP_RECORD_SRR 0x7E /* SRP Record channel source Select */ -#define P17V_SOFT_RESET_SRP_MIXER 0x7F /* SRP and mixer soft reset */ - -#define P17V_AC97_OUT_MASTER_VOL_L 0x80 /* AC97 Output master volume control */ -#define P17V_AC97_OUT_MASTER_VOL_H 0x81 /* AC97 Output master volume control */ -#define P17V_SPDIF_OUT_MASTER_VOL_L 0x82 /* SPDIF Output master volume control */ -#define P17V_SPDIF_OUT_MASTER_VOL_H 0x83 /* SPDIF Output master volume control */ -#define P17V_I2S_OUT_MASTER_VOL_L 0x84 /* I2S Output master volume control */ -#define P17V_I2S_OUT_MASTER_VOL_H 0x85 /* I2S Output master volume control */ -/* 86 - 87: Not used */ -#define P17V_I2S_CHANNEL_SWAP_PHASE_INVERSE 0x88 /* I2S out mono channel swap - * and phase inverse */ -#define P17V_SPDIF_CHANNEL_SWAP_PHASE_INVERSE 0x89 /* SPDIF out mono channel swap - * and phase inverse */ -/* 8A: Not used */ -#define P17V_SRP_P17V_ESR 0x8B /* SRP_P17V estimated sample rate and rate lock */ -#define P17V_SRP_REC_ESR 0x8C /* SRP_REC estimated sample rate and rate lock */ -#define P17V_SRP_BYPASS 0x8D /* srps channel bypass and srps bypass */ -/* 8E - 92: Not used */ -#define P17V_I2S_SRC_SEL 0x93 /* I2SIN mode sel */ - - - - - - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/timer.c b/ANDROID_3.4.5/sound/pci/emu10k1/timer.c deleted file mode 100644 index 72321e94..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/timer.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) by Lee Revell - * Clemens Ladisch - * Routines for control of EMU10K1 chips - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 - -static int snd_emu10k1_timer_start(struct snd_timer *timer) -{ - struct snd_emu10k1 *emu; - unsigned long flags; - unsigned int delay; - - emu = snd_timer_chip(timer); - delay = timer->sticks - 1; - if (delay < 5 ) /* minimum time is 5 ticks */ - delay = 5; - spin_lock_irqsave(&emu->reg_lock, flags); - snd_emu10k1_intr_enable(emu, INTE_INTERVALTIMERENB); - outw(delay & TIMER_RATE_MASK, emu->port + TIMER); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_timer_stop(struct snd_timer *timer) -{ - struct snd_emu10k1 *emu; - unsigned long flags; - - emu = snd_timer_chip(timer); - spin_lock_irqsave(&emu->reg_lock, flags); - snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_timer_precise_resolution(struct snd_timer *timer, - unsigned long *num, unsigned long *den) -{ - *num = 1; - *den = 48000; - return 0; -} - -static struct snd_timer_hardware snd_emu10k1_timer_hw = { - .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 20833, /* 1 sample @ 48KHZ = 20.833...us */ - .ticks = 1024, - .start = snd_emu10k1_timer_start, - .stop = snd_emu10k1_timer_stop, - .precise_resolution = snd_emu10k1_timer_precise_resolution, -}; - -int __devinit snd_emu10k1_timer(struct snd_emu10k1 *emu, int device) -{ - struct snd_timer *timer = NULL; - struct snd_timer_id tid; - int err; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = emu->card->number; - tid.device = device; - tid.subdevice = 0; - if ((err = snd_timer_new(emu->card, "EMU10K1", &tid, &timer)) >= 0) { - strcpy(timer->name, "EMU10K1 timer"); - timer->private_data = emu; - timer->hw = snd_emu10k1_timer_hw; - } - emu->timer = timer; - return err; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/tina2.h b/ANDROID_3.4.5/sound/pci/emu10k1/tina2.h deleted file mode 100644 index f2d8eb6c..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/tina2.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) by James Courtier-Dutton - * Driver tina2 chips - * Version: 0.1 - * - * 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 - * - */ - -/********************************************************************************************************/ -/* Audigy2 Tina2 (notebook) pointer-offset register set, accessed through the PTR2 and DATA2 registers */ -/********************************************************************************************************/ - -#define TINA2_VOLUME 0x71 /* Attenuate playback volume to prevent distortion. */ - /* The windows driver does not use this register, - * so it must use some other attenuation method. - * Without this, the output is 12dB too loud, - * resulting in distortion. - */ - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/voice.c b/ANDROID_3.4.5/sound/pci/emu10k1/voice.c deleted file mode 100644 index 101e7cb7..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/voice.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Creative Labs, Inc. - * Lee Revell - * Routines for control of EMU10K1 chips - voice manager - * - * Rewrote voice allocator for multichannel support - rlrevell 12/2004 - * - * BUGS: - * -- - * - * TODO: - * -- - * - * 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 - -/* Previously the voice allocator started at 0 every time. The new voice - * allocator uses a round robin scheme. The next free voice is tracked in - * the card record and each allocation begins where the last left off. The - * hardware requires stereo interleaved voices be aligned to an even/odd - * boundary. For multichannel voice allocation we ensure than the block of - * voices does not cross the 32 voice boundary. This simplifies the - * multichannel support and ensures we can use a single write to the - * (set|clear)_loop_stop registers. Otherwise (for example) the voices would - * get out of sync when pausing/resuming a stream. - * --rlrevell - */ - -static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, - struct snd_emu10k1_voice **rvoice) -{ - struct snd_emu10k1_voice *voice; - int i, j, k, first_voice, last_voice, skip; - - *rvoice = NULL; - first_voice = last_voice = 0; - for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) { - /* - printk(KERN_DEBUG "i %d j %d next free %d!\n", - i, j, emu->next_free_voice); - */ - i %= NUM_G; - - /* stereo voices must be even/odd */ - if ((number == 2) && (i % 2)) { - i++; - continue; - } - - skip = 0; - for (k = 0; k < number; k++) { - voice = &emu->voices[(i+k) % NUM_G]; - if (voice->use) { - skip = 1; - break; - } - } - if (!skip) { - /* printk(KERN_DEBUG "allocated voice %d\n", i); */ - first_voice = i; - last_voice = (i + number) % NUM_G; - emu->next_free_voice = last_voice; - break; - } - } - - if (first_voice == last_voice) - return -ENOMEM; - - for (i = 0; i < number; i++) { - voice = &emu->voices[(first_voice + i) % NUM_G]; - /* - printk(kERN_DEBUG "voice alloc - %i, %i of %i\n", - voice->number, idx-first_voice+1, number); - */ - voice->use = 1; - switch (type) { - case EMU10K1_PCM: - voice->pcm = 1; - break; - case EMU10K1_SYNTH: - voice->synth = 1; - break; - case EMU10K1_MIDI: - voice->midi = 1; - break; - case EMU10K1_EFX: - voice->efx = 1; - break; - } - } - *rvoice = &emu->voices[first_voice]; - return 0; -} - -int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number, - struct snd_emu10k1_voice **rvoice) -{ - unsigned long flags; - int result; - - if (snd_BUG_ON(!rvoice)) - return -EINVAL; - if (snd_BUG_ON(!number)) - return -EINVAL; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (;;) { - result = voice_alloc(emu, type, number, rvoice); - if (result == 0 || type == EMU10K1_SYNTH || type == EMU10K1_MIDI) - break; - - /* free a voice from synth */ - if (emu->get_synth_voice) { - result = emu->get_synth_voice(emu); - if (result >= 0) { - struct snd_emu10k1_voice *pvoice = &emu->voices[result]; - pvoice->interrupt = NULL; - pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0; - pvoice->epcm = NULL; - } - } - if (result < 0) - break; - } - spin_unlock_irqrestore(&emu->voice_lock, flags); - - return result; -} - -EXPORT_SYMBOL(snd_emu10k1_voice_alloc); - -int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, - struct snd_emu10k1_voice *pvoice) -{ - unsigned long flags; - - if (snd_BUG_ON(!pvoice)) - return -EINVAL; - spin_lock_irqsave(&emu->voice_lock, flags); - pvoice->interrupt = NULL; - pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0; - pvoice->epcm = NULL; - snd_emu10k1_voice_init(emu, pvoice->number); - spin_unlock_irqrestore(&emu->voice_lock, flags); - return 0; -} - -EXPORT_SYMBOL(snd_emu10k1_voice_free); diff --git a/ANDROID_3.4.5/sound/pci/ens1370.c b/ANDROID_3.4.5/sound/pci/ens1370.c deleted file mode 100644 index 47a245e8..00000000 --- a/ANDROID_3.4.5/sound/pci/ens1370.c +++ /dev/null @@ -1,2513 +0,0 @@ -/* - * Driver for Ensoniq ES1370/ES1371 AudioPCI soundcard - * Copyright (c) by Jaroslav Kysela , - * Thomas Sailer - * - * 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 - * - */ - -/* Power-Management-Code ( CONFIG_PM ) - * for ens1371 only ( FIXME ) - * derived from cs4281.c, atiixp.c and via82xx.c - * using http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/ - * by Kurt J. Bosch - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#ifdef CHIP1371 -#include -#else -#include -#endif -#include -#include - -#ifndef CHIP1371 -#undef CHIP1370 -#define CHIP1370 -#endif - -#ifdef CHIP1370 -#define DRIVER_NAME "ENS1370" -#else -#define DRIVER_NAME "ENS1371" -#endif - - -MODULE_AUTHOR("Jaroslav Kysela , Thomas Sailer "); -MODULE_LICENSE("GPL"); -#ifdef CHIP1370 -MODULE_DESCRIPTION("Ensoniq AudioPCI ES1370"); -MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI-97 ES1370}," - "{Creative Labs,SB PCI64/128 (ES1370)}}"); -#endif -#ifdef CHIP1371 -MODULE_DESCRIPTION("Ensoniq/Creative AudioPCI ES1371+"); -MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI ES1371/73}," - "{Ensoniq,AudioPCI ES1373}," - "{Creative Labs,Ectiva EV1938}," - "{Creative Labs,SB PCI64/128 (ES1371/73)}," - "{Creative Labs,Vibra PCI128}," - "{Ectiva,EV1938}}"); -#endif - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ -#ifdef SUPPORT_JOYSTICK -#ifdef CHIP1371 -static int joystick_port[SNDRV_CARDS]; -#else -static bool joystick[SNDRV_CARDS]; -#endif -#endif -#ifdef CHIP1371 -static int spdif[SNDRV_CARDS]; -static int lineio[SNDRV_CARDS]; -#endif - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Ensoniq AudioPCI soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Ensoniq AudioPCI soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Ensoniq AudioPCI soundcard."); -#ifdef SUPPORT_JOYSTICK -#ifdef CHIP1371 -module_param_array(joystick_port, int, NULL, 0444); -MODULE_PARM_DESC(joystick_port, "Joystick port address."); -#else -module_param_array(joystick, bool, NULL, 0444); -MODULE_PARM_DESC(joystick, "Enable joystick."); -#endif -#endif /* SUPPORT_JOYSTICK */ -#ifdef CHIP1371 -module_param_array(spdif, int, NULL, 0444); -MODULE_PARM_DESC(spdif, "S/PDIF output (-1 = none, 0 = auto, 1 = force)."); -module_param_array(lineio, int, NULL, 0444); -MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force)."); -#endif - -/* ES1371 chip ID */ -/* This is a little confusing because all ES1371 compatible chips have the - same DEVICE_ID, the only thing differentiating them is the REV_ID field. - This is only significant if you want to enable features on the later parts. - Yes, I know it's stupid and why didn't we use the sub IDs? -*/ -#define ES1371REV_ES1373_A 0x04 -#define ES1371REV_ES1373_B 0x06 -#define ES1371REV_CT5880_A 0x07 -#define CT5880REV_CT5880_C 0x02 -#define CT5880REV_CT5880_D 0x03 /* ??? -jk */ -#define CT5880REV_CT5880_E 0x04 /* mw */ -#define ES1371REV_ES1371_B 0x09 -#define EV1938REV_EV1938_A 0x00 -#define ES1371REV_ES1373_8 0x08 - -/* - * Direct registers - */ - -#define ES_REG(ensoniq, x) ((ensoniq)->port + ES_REG_##x) - -#define ES_REG_CONTROL 0x00 /* R/W: Interrupt/Chip select control register */ -#define ES_1370_ADC_STOP (1<<31) /* disable capture buffer transfers */ -#define ES_1370_XCTL1 (1<<30) /* general purpose output bit */ -#define ES_1373_BYPASS_P1 (1<<31) /* bypass SRC for PB1 */ -#define ES_1373_BYPASS_P2 (1<<30) /* bypass SRC for PB2 */ -#define ES_1373_BYPASS_R (1<<29) /* bypass SRC for REC */ -#define ES_1373_TEST_BIT (1<<28) /* should be set to 0 for normal operation */ -#define ES_1373_RECEN_B (1<<27) /* mix record with playback for I2S/SPDIF out */ -#define ES_1373_SPDIF_THRU (1<<26) /* 0 = SPDIF thru mode, 1 = SPDIF == dig out */ -#define ES_1371_JOY_ASEL(o) (((o)&0x03)<<24)/* joystick port mapping */ -#define ES_1371_JOY_ASELM (0x03<<24) /* mask for above */ -#define ES_1371_JOY_ASELI(i) (((i)>>24)&0x03) -#define ES_1371_GPIO_IN(i) (((i)>>20)&0x0f)/* GPIO in [3:0] pins - R/O */ -#define ES_1370_PCLKDIVO(o) (((o)&0x1fff)<<16)/* clock divide ratio for DAC2 */ -#define ES_1370_PCLKDIVM ((0x1fff)<<16) /* mask for above */ -#define ES_1370_PCLKDIVI(i) (((i)>>16)&0x1fff)/* clock divide ratio for DAC2 */ -#define ES_1371_GPIO_OUT(o) (((o)&0x0f)<<16)/* GPIO out [3:0] pins - W/R */ -#define ES_1371_GPIO_OUTM (0x0f<<16) /* mask for above */ -#define ES_MSFMTSEL (1<<15) /* MPEG serial data format; 0 = SONY, 1 = I2S */ -#define ES_1370_M_SBB (1<<14) /* clock source for DAC - 0 = clock generator; 1 = MPEG clocks */ -#define ES_1371_SYNC_RES (1<<14) /* Warm AC97 reset */ -#define ES_1370_WTSRSEL(o) (((o)&0x03)<<12)/* fixed frequency clock for DAC1 */ -#define ES_1370_WTSRSELM (0x03<<12) /* mask for above */ -#define ES_1371_ADC_STOP (1<<13) /* disable CCB transfer capture information */ -#define ES_1371_PWR_INTRM (1<<12) /* power level change interrupts enable */ -#define ES_1370_DAC_SYNC (1<<11) /* DAC's are synchronous */ -#define ES_1371_M_CB (1<<11) /* capture clock source; 0 = AC'97 ADC; 1 = I2S */ -#define ES_CCB_INTRM (1<<10) /* CCB voice interrupts enable */ -#define ES_1370_M_CB (1<<9) /* capture clock source; 0 = ADC; 1 = MPEG */ -#define ES_1370_XCTL0 (1<<8) /* generap purpose output bit */ -#define ES_1371_PDLEV(o) (((o)&0x03)<<8) /* current power down level */ -#define ES_1371_PDLEVM (0x03<<8) /* mask for above */ -#define ES_BREQ (1<<7) /* memory bus request enable */ -#define ES_DAC1_EN (1<<6) /* DAC1 playback channel enable */ -#define ES_DAC2_EN (1<<5) /* DAC2 playback channel enable */ -#define ES_ADC_EN (1<<4) /* ADC capture channel enable */ -#define ES_UART_EN (1<<3) /* UART enable */ -#define ES_JYSTK_EN (1<<2) /* Joystick module enable */ -#define ES_1370_CDC_EN (1<<1) /* Codec interface enable */ -#define ES_1371_XTALCKDIS (1<<1) /* Xtal clock disable */ -#define ES_1370_SERR_DISABLE (1<<0) /* PCI serr signal disable */ -#define ES_1371_PCICLKDIS (1<<0) /* PCI clock disable */ -#define ES_REG_STATUS 0x04 /* R/O: Interrupt/Chip select status register */ -#define ES_INTR (1<<31) /* Interrupt is pending */ -#define ES_1371_ST_AC97_RST (1<<29) /* CT5880 AC'97 Reset bit */ -#define ES_1373_REAR_BIT27 (1<<27) /* rear bits: 000 - front, 010 - mirror, 101 - separate */ -#define ES_1373_REAR_BIT26 (1<<26) -#define ES_1373_REAR_BIT24 (1<<24) -#define ES_1373_GPIO_INT_EN(o)(((o)&0x0f)<<20)/* GPIO [3:0] pins - interrupt enable */ -#define ES_1373_SPDIF_EN (1<<18) /* SPDIF enable */ -#define ES_1373_SPDIF_TEST (1<<17) /* SPDIF test */ -#define ES_1371_TEST (1<<16) /* test ASIC */ -#define ES_1373_GPIO_INT(i) (((i)&0x0f)>>12)/* GPIO [3:0] pins - interrupt pending */ -#define ES_1370_CSTAT (1<<10) /* CODEC is busy or register write in progress */ -#define ES_1370_CBUSY (1<<9) /* CODEC is busy */ -#define ES_1370_CWRIP (1<<8) /* CODEC register write in progress */ -#define ES_1371_SYNC_ERR (1<<8) /* CODEC synchronization error occurred */ -#define ES_1371_VC(i) (((i)>>6)&0x03) /* voice code from CCB module */ -#define ES_1370_VC(i) (((i)>>5)&0x03) /* voice code from CCB module */ -#define ES_1371_MPWR (1<<5) /* power level interrupt pending */ -#define ES_MCCB (1<<4) /* CCB interrupt pending */ -#define ES_UART (1<<3) /* UART interrupt pending */ -#define ES_DAC1 (1<<2) /* DAC1 channel interrupt pending */ -#define ES_DAC2 (1<<1) /* DAC2 channel interrupt pending */ -#define ES_ADC (1<<0) /* ADC channel interrupt pending */ -#define ES_REG_UART_DATA 0x08 /* R/W: UART data register */ -#define ES_REG_UART_STATUS 0x09 /* R/O: UART status register */ -#define ES_RXINT (1<<7) /* RX interrupt occurred */ -#define ES_TXINT (1<<2) /* TX interrupt occurred */ -#define ES_TXRDY (1<<1) /* transmitter ready */ -#define ES_RXRDY (1<<0) /* receiver ready */ -#define ES_REG_UART_CONTROL 0x09 /* W/O: UART control register */ -#define ES_RXINTEN (1<<7) /* RX interrupt enable */ -#define ES_TXINTENO(o) (((o)&0x03)<<5) /* TX interrupt enable */ -#define ES_TXINTENM (0x03<<5) /* mask for above */ -#define ES_TXINTENI(i) (((i)>>5)&0x03) -#define ES_CNTRL(o) (((o)&0x03)<<0) /* control */ -#define ES_CNTRLM (0x03<<0) /* mask for above */ -#define ES_REG_UART_RES 0x0a /* R/W: UART reserver register */ -#define ES_TEST_MODE (1<<0) /* test mode enabled */ -#define ES_REG_MEM_PAGE 0x0c /* R/W: Memory page register */ -#define ES_MEM_PAGEO(o) (((o)&0x0f)<<0) /* memory page select - out */ -#define ES_MEM_PAGEM (0x0f<<0) /* mask for above */ -#define ES_MEM_PAGEI(i) (((i)>>0)&0x0f) /* memory page select - in */ -#define ES_REG_1370_CODEC 0x10 /* W/O: Codec write register address */ -#define ES_1370_CODEC_WRITE(a,d) ((((a)&0xff)<<8)|(((d)&0xff)<<0)) -#define ES_REG_1371_CODEC 0x14 /* W/R: Codec Read/Write register address */ -#define ES_1371_CODEC_RDY (1<<31) /* codec ready */ -#define ES_1371_CODEC_WIP (1<<30) /* codec register access in progress */ -#define EV_1938_CODEC_MAGIC (1<<26) -#define ES_1371_CODEC_PIRD (1<<23) /* codec read/write select register */ -#define ES_1371_CODEC_WRITE(a,d) ((((a)&0x7f)<<16)|(((d)&0xffff)<<0)) -#define ES_1371_CODEC_READS(a) ((((a)&0x7f)<<16)|ES_1371_CODEC_PIRD) -#define ES_1371_CODEC_READ(i) (((i)>>0)&0xffff) - -#define ES_REG_1371_SMPRATE 0x10 /* W/R: Codec rate converter interface register */ -#define ES_1371_SRC_RAM_ADDRO(o) (((o)&0x7f)<<25)/* address of the sample rate converter */ -#define ES_1371_SRC_RAM_ADDRM (0x7f<<25) /* mask for above */ -#define ES_1371_SRC_RAM_ADDRI(i) (((i)>>25)&0x7f)/* address of the sample rate converter */ -#define ES_1371_SRC_RAM_WE (1<<24) /* R/W: read/write control for sample rate converter */ -#define ES_1371_SRC_RAM_BUSY (1<<23) /* R/O: sample rate memory is busy */ -#define ES_1371_SRC_DISABLE (1<<22) /* sample rate converter disable */ -#define ES_1371_DIS_P1 (1<<21) /* playback channel 1 accumulator update disable */ -#define ES_1371_DIS_P2 (1<<20) /* playback channel 1 accumulator update disable */ -#define ES_1371_DIS_R1 (1<<19) /* capture channel accumulator update disable */ -#define ES_1371_SRC_RAM_DATAO(o) (((o)&0xffff)<<0)/* current value of the sample rate converter */ -#define ES_1371_SRC_RAM_DATAM (0xffff<<0) /* mask for above */ -#define ES_1371_SRC_RAM_DATAI(i) (((i)>>0)&0xffff)/* current value of the sample rate converter */ - -#define ES_REG_1371_LEGACY 0x18 /* W/R: Legacy control/status register */ -#define ES_1371_JFAST (1<<31) /* fast joystick timing */ -#define ES_1371_HIB (1<<30) /* host interrupt blocking enable */ -#define ES_1371_VSB (1<<29) /* SB; 0 = addr 0x220xH, 1 = 0x22FxH */ -#define ES_1371_VMPUO(o) (((o)&0x03)<<27)/* base register address; 0 = 0x320xH; 1 = 0x330xH; 2 = 0x340xH; 3 = 0x350xH */ -#define ES_1371_VMPUM (0x03<<27) /* mask for above */ -#define ES_1371_VMPUI(i) (((i)>>27)&0x03)/* base register address */ -#define ES_1371_VCDCO(o) (((o)&0x03)<<25)/* CODEC; 0 = 0x530xH; 1 = undefined; 2 = 0xe80xH; 3 = 0xF40xH */ -#define ES_1371_VCDCM (0x03<<25) /* mask for above */ -#define ES_1371_VCDCI(i) (((i)>>25)&0x03)/* CODEC address */ -#define ES_1371_FIRQ (1<<24) /* force an interrupt */ -#define ES_1371_SDMACAP (1<<23) /* enable event capture for slave DMA controller */ -#define ES_1371_SPICAP (1<<22) /* enable event capture for slave IRQ controller */ -#define ES_1371_MDMACAP (1<<21) /* enable event capture for master DMA controller */ -#define ES_1371_MPICAP (1<<20) /* enable event capture for master IRQ controller */ -#define ES_1371_ADCAP (1<<19) /* enable event capture for ADLIB register; 0x388xH */ -#define ES_1371_SVCAP (1<<18) /* enable event capture for SB registers */ -#define ES_1371_CDCCAP (1<<17) /* enable event capture for CODEC registers */ -#define ES_1371_BACAP (1<<16) /* enable event capture for SoundScape base address */ -#define ES_1371_EXI(i) (((i)>>8)&0x07) /* event number */ -#define ES_1371_AI(i) (((i)>>3)&0x1f) /* event significant I/O address */ -#define ES_1371_WR (1<<2) /* event capture; 0 = read; 1 = write */ -#define ES_1371_LEGINT (1<<0) /* interrupt for legacy events; 0 = interrupt did occur */ - -#define ES_REG_CHANNEL_STATUS 0x1c /* R/W: first 32-bits from S/PDIF channel status block, es1373 */ - -#define ES_REG_SERIAL 0x20 /* R/W: Serial interface control register */ -#define ES_1371_DAC_TEST (1<<22) /* DAC test mode enable */ -#define ES_P2_END_INCO(o) (((o)&0x07)<<19)/* binary offset value to increment / loop end */ -#define ES_P2_END_INCM (0x07<<19) /* mask for above */ -#define ES_P2_END_INCI(i) (((i)>>16)&0x07)/* binary offset value to increment / loop end */ -#define ES_P2_ST_INCO(o) (((o)&0x07)<<16)/* binary offset value to increment / start */ -#define ES_P2_ST_INCM (0x07<<16) /* mask for above */ -#define ES_P2_ST_INCI(i) (((i)<<16)&0x07)/* binary offset value to increment / start */ -#define ES_R1_LOOP_SEL (1<<15) /* ADC; 0 - loop mode; 1 = stop mode */ -#define ES_P2_LOOP_SEL (1<<14) /* DAC2; 0 - loop mode; 1 = stop mode */ -#define ES_P1_LOOP_SEL (1<<13) /* DAC1; 0 - loop mode; 1 = stop mode */ -#define ES_P2_PAUSE (1<<12) /* DAC2; 0 - play mode; 1 = pause mode */ -#define ES_P1_PAUSE (1<<11) /* DAC1; 0 - play mode; 1 = pause mode */ -#define ES_R1_INT_EN (1<<10) /* ADC interrupt enable */ -#define ES_P2_INT_EN (1<<9) /* DAC2 interrupt enable */ -#define ES_P1_INT_EN (1<<8) /* DAC1 interrupt enable */ -#define ES_P1_SCT_RLD (1<<7) /* force sample counter reload for DAC1 */ -#define ES_P2_DAC_SEN (1<<6) /* when stop mode: 0 - DAC2 play back zeros; 1 = DAC2 play back last sample */ -#define ES_R1_MODEO(o) (((o)&0x03)<<4) /* ADC mode; 0 = 8-bit mono; 1 = 8-bit stereo; 2 = 16-bit mono; 3 = 16-bit stereo */ -#define ES_R1_MODEM (0x03<<4) /* mask for above */ -#define ES_R1_MODEI(i) (((i)>>4)&0x03) -#define ES_P2_MODEO(o) (((o)&0x03)<<2) /* DAC2 mode; -- '' -- */ -#define ES_P2_MODEM (0x03<<2) /* mask for above */ -#define ES_P2_MODEI(i) (((i)>>2)&0x03) -#define ES_P1_MODEO(o) (((o)&0x03)<<0) /* DAC1 mode; -- '' -- */ -#define ES_P1_MODEM (0x03<<0) /* mask for above */ -#define ES_P1_MODEI(i) (((i)>>0)&0x03) - -#define ES_REG_DAC1_COUNT 0x24 /* R/W: DAC1 sample count register */ -#define ES_REG_DAC2_COUNT 0x28 /* R/W: DAC2 sample count register */ -#define ES_REG_ADC_COUNT 0x2c /* R/W: ADC sample count register */ -#define ES_REG_CURR_COUNT(i) (((i)>>16)&0xffff) -#define ES_REG_COUNTO(o) (((o)&0xffff)<<0) -#define ES_REG_COUNTM (0xffff<<0) -#define ES_REG_COUNTI(i) (((i)>>0)&0xffff) - -#define ES_REG_DAC1_FRAME 0x30 /* R/W: PAGE 0x0c; DAC1 frame address */ -#define ES_REG_DAC1_SIZE 0x34 /* R/W: PAGE 0x0c; DAC1 frame size */ -#define ES_REG_DAC2_FRAME 0x38 /* R/W: PAGE 0x0c; DAC2 frame address */ -#define ES_REG_DAC2_SIZE 0x3c /* R/W: PAGE 0x0c; DAC2 frame size */ -#define ES_REG_ADC_FRAME 0x30 /* R/W: PAGE 0x0d; ADC frame address */ -#define ES_REG_ADC_SIZE 0x34 /* R/W: PAGE 0x0d; ADC frame size */ -#define ES_REG_FCURR_COUNTO(o) (((o)&0xffff)<<16) -#define ES_REG_FCURR_COUNTM (0xffff<<16) -#define ES_REG_FCURR_COUNTI(i) (((i)>>14)&0x3fffc) -#define ES_REG_FSIZEO(o) (((o)&0xffff)<<0) -#define ES_REG_FSIZEM (0xffff<<0) -#define ES_REG_FSIZEI(i) (((i)>>0)&0xffff) -#define ES_REG_PHANTOM_FRAME 0x38 /* R/W: PAGE 0x0d: phantom frame address */ -#define ES_REG_PHANTOM_COUNT 0x3c /* R/W: PAGE 0x0d: phantom frame count */ - -#define ES_REG_UART_FIFO 0x30 /* R/W: PAGE 0x0e; UART FIFO register */ -#define ES_REG_UF_VALID (1<<8) -#define ES_REG_UF_BYTEO(o) (((o)&0xff)<<0) -#define ES_REG_UF_BYTEM (0xff<<0) -#define ES_REG_UF_BYTEI(i) (((i)>>0)&0xff) - - -/* - * Pages - */ - -#define ES_PAGE_DAC 0x0c -#define ES_PAGE_ADC 0x0d -#define ES_PAGE_UART 0x0e -#define ES_PAGE_UART1 0x0f - -/* - * Sample rate converter addresses - */ - -#define ES_SMPREG_DAC1 0x70 -#define ES_SMPREG_DAC2 0x74 -#define ES_SMPREG_ADC 0x78 -#define ES_SMPREG_VOL_ADC 0x6c -#define ES_SMPREG_VOL_DAC1 0x7c -#define ES_SMPREG_VOL_DAC2 0x7e -#define ES_SMPREG_TRUNC_N 0x00 -#define ES_SMPREG_INT_REGS 0x01 -#define ES_SMPREG_ACCUM_FRAC 0x02 -#define ES_SMPREG_VFREQ_FRAC 0x03 - -/* - * Some contants - */ - -#define ES_1370_SRCLOCK 1411200 -#define ES_1370_SRTODIV(x) (ES_1370_SRCLOCK/(x)-2) - -/* - * Open modes - */ - -#define ES_MODE_PLAY1 0x0001 -#define ES_MODE_PLAY2 0x0002 -#define ES_MODE_CAPTURE 0x0004 - -#define ES_MODE_OUTPUT 0x0001 /* for MIDI */ -#define ES_MODE_INPUT 0x0002 /* for MIDI */ - -/* - - */ - -struct ensoniq { - spinlock_t reg_lock; - struct mutex src_mutex; - - int irq; - - unsigned long playback1size; - unsigned long playback2size; - unsigned long capture3size; - - unsigned long port; - unsigned int mode; - unsigned int uartm; /* UART mode */ - - unsigned int ctrl; /* control register */ - unsigned int sctrl; /* serial control register */ - unsigned int cssr; /* control status register */ - unsigned int uartc; /* uart control register */ - unsigned int rev; /* chip revision */ - - union { -#ifdef CHIP1371 - struct { - struct snd_ac97 *ac97; - } es1371; -#else - struct { - int pclkdiv_lock; - struct snd_ak4531 *ak4531; - } es1370; -#endif - } u; - - struct pci_dev *pci; - struct snd_card *card; - struct snd_pcm *pcm1; /* DAC1/ADC PCM */ - struct snd_pcm *pcm2; /* DAC2 PCM */ - struct snd_pcm_substream *playback1_substream; - struct snd_pcm_substream *playback2_substream; - struct snd_pcm_substream *capture_substream; - unsigned int p1_dma_size; - unsigned int p2_dma_size; - unsigned int c_dma_size; - unsigned int p1_period_size; - unsigned int p2_period_size; - unsigned int c_period_size; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *midi_input; - struct snd_rawmidi_substream *midi_output; - - unsigned int spdif; - unsigned int spdif_default; - unsigned int spdif_stream; - -#ifdef CHIP1370 - struct snd_dma_buffer dma_bug; -#endif - -#ifdef SUPPORT_JOYSTICK - struct gameport *gameport; -#endif -}; - -static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id); - -static DEFINE_PCI_DEVICE_TABLE(snd_audiopci_ids) = { -#ifdef CHIP1370 - { PCI_VDEVICE(ENSONIQ, 0x5000), 0, }, /* ES1370 */ -#endif -#ifdef CHIP1371 - { PCI_VDEVICE(ENSONIQ, 0x1371), 0, }, /* ES1371 */ - { PCI_VDEVICE(ENSONIQ, 0x5880), 0, }, /* ES1373 - CT5880 */ - { PCI_VDEVICE(ECTIVA, 0x8938), 0, }, /* Ectiva EV1938 */ -#endif - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_audiopci_ids); - -/* - * constants - */ - -#define POLL_COUNT 0xa000 - -#ifdef CHIP1370 -static unsigned int snd_es1370_fixed_rates[] = - {5512, 11025, 22050, 44100}; -static struct snd_pcm_hw_constraint_list snd_es1370_hw_constraints_rates = { - .count = 4, - .list = snd_es1370_fixed_rates, - .mask = 0, -}; -static struct snd_ratnum es1370_clock = { - .num = ES_1370_SRCLOCK, - .den_min = 29, - .den_max = 353, - .den_step = 1, -}; -static struct snd_pcm_hw_constraint_ratnums snd_es1370_hw_constraints_clock = { - .nrats = 1, - .rats = &es1370_clock, -}; -#else -static struct snd_ratden es1371_dac_clock = { - .num_min = 3000 * (1 << 15), - .num_max = 48000 * (1 << 15), - .num_step = 3000, - .den = 1 << 15, -}; -static struct snd_pcm_hw_constraint_ratdens snd_es1371_hw_constraints_dac_clock = { - .nrats = 1, - .rats = &es1371_dac_clock, -}; -static struct snd_ratnum es1371_adc_clock = { - .num = 48000 << 15, - .den_min = 32768, - .den_max = 393216, - .den_step = 1, -}; -static struct snd_pcm_hw_constraint_ratnums snd_es1371_hw_constraints_adc_clock = { - .nrats = 1, - .rats = &es1371_adc_clock, -}; -#endif -static const unsigned int snd_ensoniq_sample_shift[] = - {0, 1, 1, 2}; - -/* - * common I/O routines - */ - -#ifdef CHIP1371 - -static unsigned int snd_es1371_wait_src_ready(struct ensoniq * ensoniq) -{ - unsigned int t, r = 0; - - for (t = 0; t < POLL_COUNT; t++) { - r = inl(ES_REG(ensoniq, 1371_SMPRATE)); - if ((r & ES_1371_SRC_RAM_BUSY) == 0) - return r; - cond_resched(); - } - snd_printk(KERN_ERR "wait src ready timeout 0x%lx [0x%x]\n", - ES_REG(ensoniq, 1371_SMPRATE), r); - return 0; -} - -static unsigned int snd_es1371_src_read(struct ensoniq * ensoniq, unsigned short reg) -{ - unsigned int temp, i, orig, r; - - /* wait for ready */ - temp = orig = snd_es1371_wait_src_ready(ensoniq); - - /* expose the SRC state bits */ - r = temp & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | - ES_1371_DIS_P2 | ES_1371_DIS_R1); - r |= ES_1371_SRC_RAM_ADDRO(reg) | 0x10000; - outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - - /* now, wait for busy and the correct time to read */ - temp = snd_es1371_wait_src_ready(ensoniq); - - if ((temp & 0x00870000) != 0x00010000) { - /* wait for the right state */ - for (i = 0; i < POLL_COUNT; i++) { - temp = inl(ES_REG(ensoniq, 1371_SMPRATE)); - if ((temp & 0x00870000) == 0x00010000) - break; - } - } - - /* hide the state bits */ - r = orig & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | - ES_1371_DIS_P2 | ES_1371_DIS_R1); - r |= ES_1371_SRC_RAM_ADDRO(reg); - outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - - return temp; -} - -static void snd_es1371_src_write(struct ensoniq * ensoniq, - unsigned short reg, unsigned short data) -{ - unsigned int r; - - r = snd_es1371_wait_src_ready(ensoniq) & - (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | - ES_1371_DIS_P2 | ES_1371_DIS_R1); - r |= ES_1371_SRC_RAM_ADDRO(reg) | ES_1371_SRC_RAM_DATAO(data); - outl(r | ES_1371_SRC_RAM_WE, ES_REG(ensoniq, 1371_SMPRATE)); -} - -#endif /* CHIP1371 */ - -#ifdef CHIP1370 - -static void snd_es1370_codec_write(struct snd_ak4531 *ak4531, - unsigned short reg, unsigned short val) -{ - struct ensoniq *ensoniq = ak4531->private_data; - unsigned long end_time = jiffies + HZ / 10; - -#if 0 - printk(KERN_DEBUG - "CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", - reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); -#endif - do { - if (!(inl(ES_REG(ensoniq, STATUS)) & ES_1370_CSTAT)) { - outw(ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); - return; - } - schedule_timeout_uninterruptible(1); - } while (time_after(end_time, jiffies)); - snd_printk(KERN_ERR "codec write timeout, status = 0x%x\n", - inl(ES_REG(ensoniq, STATUS))); -} - -#endif /* CHIP1370 */ - -#ifdef CHIP1371 - -static inline bool is_ev1938(struct ensoniq *ensoniq) -{ - return ensoniq->pci->device == 0x8938; -} - -static void snd_es1371_codec_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - struct ensoniq *ensoniq = ac97->private_data; - unsigned int t, x, flag; - - flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0; - mutex_lock(&ensoniq->src_mutex); - for (t = 0; t < POLL_COUNT; t++) { - if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { - /* save the current state for latter */ - x = snd_es1371_wait_src_ready(ensoniq); - outl((x & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | - ES_1371_DIS_P2 | ES_1371_DIS_R1)) | 0x00010000, - ES_REG(ensoniq, 1371_SMPRATE)); - /* wait for not busy (state 0) first to avoid - transition states */ - for (t = 0; t < POLL_COUNT; t++) { - if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) == - 0x00000000) - break; - } - /* wait for a SAFE time to write addr/data and then do it, dammit */ - for (t = 0; t < POLL_COUNT; t++) { - if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) == - 0x00010000) - break; - } - outl(ES_1371_CODEC_WRITE(reg, val) | flag, - ES_REG(ensoniq, 1371_CODEC)); - /* restore SRC reg */ - snd_es1371_wait_src_ready(ensoniq); - outl(x, ES_REG(ensoniq, 1371_SMPRATE)); - mutex_unlock(&ensoniq->src_mutex); - return; - } - } - mutex_unlock(&ensoniq->src_mutex); - snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n", - ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); -} - -static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct ensoniq *ensoniq = ac97->private_data; - unsigned int t, x, flag, fail = 0; - - flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0; - __again: - mutex_lock(&ensoniq->src_mutex); - for (t = 0; t < POLL_COUNT; t++) { - if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { - /* save the current state for latter */ - x = snd_es1371_wait_src_ready(ensoniq); - outl((x & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | - ES_1371_DIS_P2 | ES_1371_DIS_R1)) | 0x00010000, - ES_REG(ensoniq, 1371_SMPRATE)); - /* wait for not busy (state 0) first to avoid - transition states */ - for (t = 0; t < POLL_COUNT; t++) { - if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) == - 0x00000000) - break; - } - /* wait for a SAFE time to write addr/data and then do it, dammit */ - for (t = 0; t < POLL_COUNT; t++) { - if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) == - 0x00010000) - break; - } - outl(ES_1371_CODEC_READS(reg) | flag, - ES_REG(ensoniq, 1371_CODEC)); - /* restore SRC reg */ - snd_es1371_wait_src_ready(ensoniq); - outl(x, ES_REG(ensoniq, 1371_SMPRATE)); - /* wait for WIP again */ - for (t = 0; t < POLL_COUNT; t++) { - if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) - break; - } - /* now wait for the stinkin' data (RDY) */ - for (t = 0; t < POLL_COUNT; t++) { - if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { - if (is_ev1938(ensoniq)) { - for (t = 0; t < 100; t++) - inl(ES_REG(ensoniq, CONTROL)); - x = inl(ES_REG(ensoniq, 1371_CODEC)); - } - mutex_unlock(&ensoniq->src_mutex); - return ES_1371_CODEC_READ(x); - } - } - mutex_unlock(&ensoniq->src_mutex); - if (++fail > 10) { - snd_printk(KERN_ERR "codec read timeout (final) " - "at 0x%lx, reg = 0x%x [0x%x]\n", - ES_REG(ensoniq, 1371_CODEC), reg, - inl(ES_REG(ensoniq, 1371_CODEC))); - return 0; - } - goto __again; - } - } - mutex_unlock(&ensoniq->src_mutex); - snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n", - ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); - return 0; -} - -static void snd_es1371_codec_wait(struct snd_ac97 *ac97) -{ - msleep(750); - snd_es1371_codec_read(ac97, AC97_RESET); - snd_es1371_codec_read(ac97, AC97_VENDOR_ID1); - snd_es1371_codec_read(ac97, AC97_VENDOR_ID2); - msleep(50); -} - -static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate) -{ - unsigned int n, truncm, freq, result; - - mutex_lock(&ensoniq->src_mutex); - n = rate / 3000; - if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) - n--; - truncm = (21 * n - 1) | 1; - freq = ((48000UL << 15) / rate) * n; - result = (48000UL << 15) / (freq / n); - if (rate >= 24000) { - if (truncm > 239) - truncm = 239; - snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, - (((239 - truncm) >> 1) << 9) | (n << 4)); - } else { - if (truncm > 119) - truncm = 119; - snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N, - 0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4)); - } - snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_INT_REGS, - (snd_es1371_src_read(ensoniq, ES_SMPREG_ADC + - ES_SMPREG_INT_REGS) & 0x00ff) | - ((freq >> 5) & 0xfc00)); - snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); - snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8); - snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8); - mutex_unlock(&ensoniq->src_mutex); -} - -static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate) -{ - unsigned int freq, r; - - mutex_lock(&ensoniq->src_mutex); - freq = ((rate << 15) + 1500) / 3000; - r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | - ES_1371_DIS_P2 | ES_1371_DIS_R1)) | - ES_1371_DIS_P1; - outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, - (snd_es1371_src_read(ensoniq, ES_SMPREG_DAC1 + - ES_SMPREG_INT_REGS) & 0x00ff) | - ((freq >> 5) & 0xfc00)); - snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); - r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | - ES_1371_DIS_P2 | ES_1371_DIS_R1)); - outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - mutex_unlock(&ensoniq->src_mutex); -} - -static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate) -{ - unsigned int freq, r; - - mutex_lock(&ensoniq->src_mutex); - freq = ((rate << 15) + 1500) / 3000; - r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | - ES_1371_DIS_P1 | ES_1371_DIS_R1)) | - ES_1371_DIS_P2; - outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, - (snd_es1371_src_read(ensoniq, ES_SMPREG_DAC2 + - ES_SMPREG_INT_REGS) & 0x00ff) | - ((freq >> 5) & 0xfc00)); - snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC, - freq & 0x7fff); - r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | - ES_1371_DIS_P1 | ES_1371_DIS_R1)); - outl(r, ES_REG(ensoniq, 1371_SMPRATE)); - mutex_unlock(&ensoniq->src_mutex); -} - -#endif /* CHIP1371 */ - -static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - { - unsigned int what = 0; - struct snd_pcm_substream *s; - snd_pcm_group_for_each_entry(s, substream) { - if (s == ensoniq->playback1_substream) { - what |= ES_P1_PAUSE; - snd_pcm_trigger_done(s, substream); - } else if (s == ensoniq->playback2_substream) { - what |= ES_P2_PAUSE; - snd_pcm_trigger_done(s, substream); - } else if (s == ensoniq->capture_substream) - return -EINVAL; - } - spin_lock(&ensoniq->reg_lock); - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) - ensoniq->sctrl |= what; - else - ensoniq->sctrl &= ~what; - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - spin_unlock(&ensoniq->reg_lock); - break; - } - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_STOP: - { - unsigned int what = 0; - struct snd_pcm_substream *s; - snd_pcm_group_for_each_entry(s, substream) { - if (s == ensoniq->playback1_substream) { - what |= ES_DAC1_EN; - snd_pcm_trigger_done(s, substream); - } else if (s == ensoniq->playback2_substream) { - what |= ES_DAC2_EN; - snd_pcm_trigger_done(s, substream); - } else if (s == ensoniq->capture_substream) { - what |= ES_ADC_EN; - snd_pcm_trigger_done(s, substream); - } - } - spin_lock(&ensoniq->reg_lock); - if (cmd == SNDRV_PCM_TRIGGER_START) - ensoniq->ctrl |= what; - else - ensoniq->ctrl &= ~what; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock(&ensoniq->reg_lock); - break; - } - default: - return -EINVAL; - } - return 0; -} - -/* - * PCM part - */ - -static int snd_ensoniq_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_ensoniq_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_ensoniq_playback1_prepare(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int mode = 0; - - ensoniq->p1_dma_size = snd_pcm_lib_buffer_bytes(substream); - ensoniq->p1_period_size = snd_pcm_lib_period_bytes(substream); - if (snd_pcm_format_width(runtime->format) == 16) - mode |= 0x02; - if (runtime->channels > 1) - mode |= 0x01; - spin_lock_irq(&ensoniq->reg_lock); - ensoniq->ctrl &= ~ES_DAC1_EN; -#ifdef CHIP1371 - /* 48k doesn't need SRC (it breaks AC3-passthru) */ - if (runtime->rate == 48000) - ensoniq->ctrl |= ES_1373_BYPASS_P1; - else - ensoniq->ctrl &= ~ES_1373_BYPASS_P1; -#endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); - outl(runtime->dma_addr, ES_REG(ensoniq, DAC1_FRAME)); - outl((ensoniq->p1_dma_size >> 2) - 1, ES_REG(ensoniq, DAC1_SIZE)); - ensoniq->sctrl &= ~(ES_P1_LOOP_SEL | ES_P1_PAUSE | ES_P1_SCT_RLD | ES_P1_MODEM); - ensoniq->sctrl |= ES_P1_INT_EN | ES_P1_MODEO(mode); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - outl((ensoniq->p1_period_size >> snd_ensoniq_sample_shift[mode]) - 1, - ES_REG(ensoniq, DAC1_COUNT)); -#ifdef CHIP1370 - ensoniq->ctrl &= ~ES_1370_WTSRSELM; - switch (runtime->rate) { - case 5512: ensoniq->ctrl |= ES_1370_WTSRSEL(0); break; - case 11025: ensoniq->ctrl |= ES_1370_WTSRSEL(1); break; - case 22050: ensoniq->ctrl |= ES_1370_WTSRSEL(2); break; - case 44100: ensoniq->ctrl |= ES_1370_WTSRSEL(3); break; - default: snd_BUG(); - } -#endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); -#ifndef CHIP1370 - snd_es1371_dac1_rate(ensoniq, runtime->rate); -#endif - return 0; -} - -static int snd_ensoniq_playback2_prepare(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int mode = 0; - - ensoniq->p2_dma_size = snd_pcm_lib_buffer_bytes(substream); - ensoniq->p2_period_size = snd_pcm_lib_period_bytes(substream); - if (snd_pcm_format_width(runtime->format) == 16) - mode |= 0x02; - if (runtime->channels > 1) - mode |= 0x01; - spin_lock_irq(&ensoniq->reg_lock); - ensoniq->ctrl &= ~ES_DAC2_EN; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); - outl(runtime->dma_addr, ES_REG(ensoniq, DAC2_FRAME)); - outl((ensoniq->p2_dma_size >> 2) - 1, ES_REG(ensoniq, DAC2_SIZE)); - ensoniq->sctrl &= ~(ES_P2_LOOP_SEL | ES_P2_PAUSE | ES_P2_DAC_SEN | - ES_P2_END_INCM | ES_P2_ST_INCM | ES_P2_MODEM); - ensoniq->sctrl |= ES_P2_INT_EN | ES_P2_MODEO(mode) | - ES_P2_END_INCO(mode & 2 ? 2 : 1) | ES_P2_ST_INCO(0); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - outl((ensoniq->p2_period_size >> snd_ensoniq_sample_shift[mode]) - 1, - ES_REG(ensoniq, DAC2_COUNT)); -#ifdef CHIP1370 - if (!(ensoniq->u.es1370.pclkdiv_lock & ES_MODE_CAPTURE)) { - ensoniq->ctrl &= ~ES_1370_PCLKDIVM; - ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate)); - ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_PLAY2; - } -#endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); -#ifndef CHIP1370 - snd_es1371_dac2_rate(ensoniq, runtime->rate); -#endif - return 0; -} - -static int snd_ensoniq_capture_prepare(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int mode = 0; - - ensoniq->c_dma_size = snd_pcm_lib_buffer_bytes(substream); - ensoniq->c_period_size = snd_pcm_lib_period_bytes(substream); - if (snd_pcm_format_width(runtime->format) == 16) - mode |= 0x02; - if (runtime->channels > 1) - mode |= 0x01; - spin_lock_irq(&ensoniq->reg_lock); - ensoniq->ctrl &= ~ES_ADC_EN; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE)); - outl(runtime->dma_addr, ES_REG(ensoniq, ADC_FRAME)); - outl((ensoniq->c_dma_size >> 2) - 1, ES_REG(ensoniq, ADC_SIZE)); - ensoniq->sctrl &= ~(ES_R1_LOOP_SEL | ES_R1_MODEM); - ensoniq->sctrl |= ES_R1_INT_EN | ES_R1_MODEO(mode); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - outl((ensoniq->c_period_size >> snd_ensoniq_sample_shift[mode]) - 1, - ES_REG(ensoniq, ADC_COUNT)); -#ifdef CHIP1370 - if (!(ensoniq->u.es1370.pclkdiv_lock & ES_MODE_PLAY2)) { - ensoniq->ctrl &= ~ES_1370_PCLKDIVM; - ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate)); - ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_CAPTURE; - } -#endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); -#ifndef CHIP1370 - snd_es1371_adc_rate(ensoniq, runtime->rate); -#endif - return 0; -} - -static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - size_t ptr; - - spin_lock(&ensoniq->reg_lock); - if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC1_EN) { - outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); - ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC1_SIZE))); - ptr = bytes_to_frames(substream->runtime, ptr); - } else { - ptr = 0; - } - spin_unlock(&ensoniq->reg_lock); - return ptr; -} - -static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - size_t ptr; - - spin_lock(&ensoniq->reg_lock); - if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC2_EN) { - outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); - ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC2_SIZE))); - ptr = bytes_to_frames(substream->runtime, ptr); - } else { - ptr = 0; - } - spin_unlock(&ensoniq->reg_lock); - return ptr; -} - -static snd_pcm_uframes_t snd_ensoniq_capture_pointer(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - size_t ptr; - - spin_lock(&ensoniq->reg_lock); - if (inl(ES_REG(ensoniq, CONTROL)) & ES_ADC_EN) { - outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE)); - ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, ADC_SIZE))); - ptr = bytes_to_frames(substream->runtime, ptr); - } else { - ptr = 0; - } - spin_unlock(&ensoniq->reg_lock); - return ptr; -} - -static struct snd_pcm_hardware snd_ensoniq_playback1 = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = -#ifndef CHIP1370 - SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, -#else - (SNDRV_PCM_RATE_KNOT | /* 5512Hz rate */ - SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050 | - SNDRV_PCM_RATE_44100), -#endif - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_ensoniq_playback2 = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_ensoniq_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_ensoniq_playback1_open(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - ensoniq->mode |= ES_MODE_PLAY1; - ensoniq->playback1_substream = substream; - runtime->hw = snd_ensoniq_playback1; - snd_pcm_set_sync(substream); - spin_lock_irq(&ensoniq->reg_lock); - if (ensoniq->spdif && ensoniq->playback2_substream == NULL) - ensoniq->spdif_stream = ensoniq->spdif_default; - spin_unlock_irq(&ensoniq->reg_lock); -#ifdef CHIP1370 - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &snd_es1370_hw_constraints_rates); -#else - snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &snd_es1371_hw_constraints_dac_clock); -#endif - return 0; -} - -static int snd_ensoniq_playback2_open(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - ensoniq->mode |= ES_MODE_PLAY2; - ensoniq->playback2_substream = substream; - runtime->hw = snd_ensoniq_playback2; - snd_pcm_set_sync(substream); - spin_lock_irq(&ensoniq->reg_lock); - if (ensoniq->spdif && ensoniq->playback1_substream == NULL) - ensoniq->spdif_stream = ensoniq->spdif_default; - spin_unlock_irq(&ensoniq->reg_lock); -#ifdef CHIP1370 - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &snd_es1370_hw_constraints_clock); -#else - snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &snd_es1371_hw_constraints_dac_clock); -#endif - return 0; -} - -static int snd_ensoniq_capture_open(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - ensoniq->mode |= ES_MODE_CAPTURE; - ensoniq->capture_substream = substream; - runtime->hw = snd_ensoniq_capture; - snd_pcm_set_sync(substream); -#ifdef CHIP1370 - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &snd_es1370_hw_constraints_clock); -#else - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &snd_es1371_hw_constraints_adc_clock); -#endif - return 0; -} - -static int snd_ensoniq_playback1_close(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - - ensoniq->playback1_substream = NULL; - ensoniq->mode &= ~ES_MODE_PLAY1; - return 0; -} - -static int snd_ensoniq_playback2_close(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - - ensoniq->playback2_substream = NULL; - spin_lock_irq(&ensoniq->reg_lock); -#ifdef CHIP1370 - ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_PLAY2; -#endif - ensoniq->mode &= ~ES_MODE_PLAY2; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream) -{ - struct ensoniq *ensoniq = snd_pcm_substream_chip(substream); - - ensoniq->capture_substream = NULL; - spin_lock_irq(&ensoniq->reg_lock); -#ifdef CHIP1370 - ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_CAPTURE; -#endif - ensoniq->mode &= ~ES_MODE_CAPTURE; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static struct snd_pcm_ops snd_ensoniq_playback1_ops = { - .open = snd_ensoniq_playback1_open, - .close = snd_ensoniq_playback1_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ensoniq_hw_params, - .hw_free = snd_ensoniq_hw_free, - .prepare = snd_ensoniq_playback1_prepare, - .trigger = snd_ensoniq_trigger, - .pointer = snd_ensoniq_playback1_pointer, -}; - -static struct snd_pcm_ops snd_ensoniq_playback2_ops = { - .open = snd_ensoniq_playback2_open, - .close = snd_ensoniq_playback2_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ensoniq_hw_params, - .hw_free = snd_ensoniq_hw_free, - .prepare = snd_ensoniq_playback2_prepare, - .trigger = snd_ensoniq_trigger, - .pointer = snd_ensoniq_playback2_pointer, -}; - -static struct snd_pcm_ops snd_ensoniq_capture_ops = { - .open = snd_ensoniq_capture_open, - .close = snd_ensoniq_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ensoniq_hw_params, - .hw_free = snd_ensoniq_hw_free, - .prepare = snd_ensoniq_capture_prepare, - .trigger = snd_ensoniq_trigger, - .pointer = snd_ensoniq_capture_pointer, -}; - -static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, - struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; -#ifdef CHIP1370 - err = snd_pcm_new(ensoniq->card, "ES1370/1", device, 1, 1, &pcm); -#else - err = snd_pcm_new(ensoniq->card, "ES1371/1", device, 1, 1, &pcm); -#endif - if (err < 0) - return err; - -#ifdef CHIP1370 - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback2_ops); -#else - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback1_ops); -#endif - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ensoniq_capture_ops); - - pcm->private_data = ensoniq; - pcm->info_flags = 0; -#ifdef CHIP1370 - strcpy(pcm->name, "ES1370 DAC2/ADC"); -#else - strcpy(pcm->name, "ES1371 DAC2/ADC"); -#endif - ensoniq->pcm1 = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device, - struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; -#ifdef CHIP1370 - err = snd_pcm_new(ensoniq->card, "ES1370/2", device, 1, 0, &pcm); -#else - err = snd_pcm_new(ensoniq->card, "ES1371/2", device, 1, 0, &pcm); -#endif - if (err < 0) - return err; - -#ifdef CHIP1370 - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback1_ops); -#else - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback2_ops); -#endif - pcm->private_data = ensoniq; - pcm->info_flags = 0; -#ifdef CHIP1370 - strcpy(pcm->name, "ES1370 DAC1"); -#else - strcpy(pcm->name, "ES1371 DAC1"); -#endif - ensoniq->pcm2 = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* - * Mixer section - */ - -/* - * ENS1371 mixer (including SPDIF interface) - */ -#ifdef CHIP1371 -static int snd_ens1373_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ens1373_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&ensoniq->reg_lock); - ucontrol->value.iec958.status[0] = (ensoniq->spdif_default >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (ensoniq->spdif_default >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (ensoniq->spdif_default >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (ensoniq->spdif_default >> 24) & 0xff; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_ens1373_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ((u32)ucontrol->value.iec958.status[0] << 0) | - ((u32)ucontrol->value.iec958.status[1] << 8) | - ((u32)ucontrol->value.iec958.status[2] << 16) | - ((u32)ucontrol->value.iec958.status[3] << 24); - spin_lock_irq(&ensoniq->reg_lock); - change = ensoniq->spdif_default != val; - ensoniq->spdif_default = val; - if (change && ensoniq->playback1_substream == NULL && - ensoniq->playback2_substream == NULL) - outl(val, ES_REG(ensoniq, CHANNEL_STATUS)); - spin_unlock_irq(&ensoniq->reg_lock); - return change; -} - -static int snd_ens1373_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static int snd_ens1373_spdif_stream_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&ensoniq->reg_lock); - ucontrol->value.iec958.status[0] = (ensoniq->spdif_stream >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (ensoniq->spdif_stream >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (ensoniq->spdif_stream >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (ensoniq->spdif_stream >> 24) & 0xff; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_ens1373_spdif_stream_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ((u32)ucontrol->value.iec958.status[0] << 0) | - ((u32)ucontrol->value.iec958.status[1] << 8) | - ((u32)ucontrol->value.iec958.status[2] << 16) | - ((u32)ucontrol->value.iec958.status[3] << 24); - spin_lock_irq(&ensoniq->reg_lock); - change = ensoniq->spdif_stream != val; - ensoniq->spdif_stream = val; - if (change && (ensoniq->playback1_substream != NULL || - ensoniq->playback2_substream != NULL)) - outl(val, ES_REG(ensoniq, CHANNEL_STATUS)); - spin_unlock_irq(&ensoniq->reg_lock); - return change; -} - -#define ES1371_SPDIF(xname) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \ - .get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put } - -#define snd_es1371_spdif_info snd_ctl_boolean_mono_info - -static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&ensoniq->reg_lock); - ucontrol->value.integer.value[0] = ensoniq->ctrl & ES_1373_SPDIF_THRU ? 1 : 0; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - unsigned int nval1, nval2; - int change; - - nval1 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_THRU : 0; - nval2 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_EN : 0; - spin_lock_irq(&ensoniq->reg_lock); - change = (ensoniq->ctrl & ES_1373_SPDIF_THRU) != nval1; - ensoniq->ctrl &= ~ES_1373_SPDIF_THRU; - ensoniq->ctrl |= nval1; - ensoniq->cssr &= ~ES_1373_SPDIF_EN; - ensoniq->cssr |= nval2; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); - spin_unlock_irq(&ensoniq->reg_lock); - return change; -} - - -/* spdif controls */ -static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = { - ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)), - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_ens1373_spdif_info, - .get = snd_ens1373_spdif_default_get, - .put = snd_ens1373_spdif_default_put, - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .info = snd_ens1373_spdif_info, - .get = snd_ens1373_spdif_mask_get - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_ens1373_spdif_info, - .get = snd_ens1373_spdif_stream_get, - .put = snd_ens1373_spdif_stream_put - }, -}; - - -#define snd_es1373_rear_info snd_ctl_boolean_mono_info - -static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - int val = 0; - - spin_lock_irq(&ensoniq->reg_lock); - if ((ensoniq->cssr & (ES_1373_REAR_BIT27|ES_1373_REAR_BIT26| - ES_1373_REAR_BIT24)) == ES_1373_REAR_BIT26) - val = 1; - ucontrol->value.integer.value[0] = val; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_es1373_rear_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - unsigned int nval1; - int change; - - nval1 = ucontrol->value.integer.value[0] ? - ES_1373_REAR_BIT26 : (ES_1373_REAR_BIT27|ES_1373_REAR_BIT24); - spin_lock_irq(&ensoniq->reg_lock); - change = (ensoniq->cssr & (ES_1373_REAR_BIT27| - ES_1373_REAR_BIT26|ES_1373_REAR_BIT24)) != nval1; - ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|ES_1373_REAR_BIT24); - ensoniq->cssr |= nval1; - outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); - spin_unlock_irq(&ensoniq->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_ens1373_rear __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "AC97 2ch->4ch Copy Switch", - .info = snd_es1373_rear_info, - .get = snd_es1373_rear_get, - .put = snd_es1373_rear_put, -}; - -#define snd_es1373_line_info snd_ctl_boolean_mono_info - -static int snd_es1373_line_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - int val = 0; - - spin_lock_irq(&ensoniq->reg_lock); - if ((ensoniq->ctrl & ES_1371_GPIO_OUTM) >= 4) - val = 1; - ucontrol->value.integer.value[0] = val; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_es1373_line_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - int changed; - unsigned int ctrl; - - spin_lock_irq(&ensoniq->reg_lock); - ctrl = ensoniq->ctrl; - if (ucontrol->value.integer.value[0]) - ensoniq->ctrl |= ES_1371_GPIO_OUT(4); /* switch line-in -> rear out */ - else - ensoniq->ctrl &= ~ES_1371_GPIO_OUT(4); - changed = (ctrl != ensoniq->ctrl); - if (changed) - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); - return changed; -} - -static struct snd_kcontrol_new snd_ens1373_line __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line In->Rear Out Switch", - .info = snd_es1373_line_info, - .get = snd_es1373_line_get, - .put = snd_es1373_line_put, -}; - -static void snd_ensoniq_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct ensoniq *ensoniq = ac97->private_data; - ensoniq->u.es1371.ac97 = NULL; -} - -struct es1371_quirk { - unsigned short vid; /* vendor ID */ - unsigned short did; /* device ID */ - unsigned char rev; /* revision */ -}; - -static int es1371_quirk_lookup(struct ensoniq *ensoniq, - struct es1371_quirk *list) -{ - while (list->vid != (unsigned short)PCI_ANY_ID) { - if (ensoniq->pci->vendor == list->vid && - ensoniq->pci->device == list->did && - ensoniq->rev == list->rev) - return 1; - list++; - } - return 0; -} - -static struct es1371_quirk es1371_spdif_present[] __devinitdata = { - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_CT5880_A }, - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_ES1373_8 }, - { .vid = PCI_ANY_ID, .did = PCI_ANY_ID } -}; - -static struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = { - SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */ - SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */ - { } /* end */ -}; - -static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq, - int has_spdif, int has_line) -{ - struct snd_card *card = ensoniq->card; - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_es1371_codec_write, - .read = snd_es1371_codec_read, - .wait = snd_es1371_codec_wait, - }; - - if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = ensoniq; - ac97.private_free = snd_ensoniq_mixer_free_ac97; - ac97.pci = ensoniq->pci; - ac97.scaps = AC97_SCAP_AUDIO; - if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0) - return err; - if (has_spdif > 0 || - (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) { - struct snd_kcontrol *kctl; - int i, is_spdif = 0; - - ensoniq->spdif_default = ensoniq->spdif_stream = - SNDRV_PCM_DEFAULT_CON_SPDIF; - outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS)); - - if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF) - is_spdif++; - - for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) { - kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq); - if (!kctl) - return -ENOMEM; - kctl->id.index = is_spdif; - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - } - } - if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) { - /* mirror rear to front speakers */ - ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24); - ensoniq->cssr |= ES_1373_REAR_BIT26; - err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_rear, ensoniq)); - if (err < 0) - return err; - } - if (has_line > 0 || - snd_pci_quirk_lookup(ensoniq->pci, ens1373_line_quirk)) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, - ensoniq)); - if (err < 0) - return err; - } - - return 0; -} - -#endif /* CHIP1371 */ - -/* generic control callbacks for ens1370 */ -#ifdef CHIP1370 -#define ENSONIQ_CONTROL(xname, mask) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = xname, .info = snd_ensoniq_control_info, \ - .get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \ - .private_value = mask } - -#define snd_ensoniq_control_info snd_ctl_boolean_mono_info - -static int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - int mask = kcontrol->private_value; - - spin_lock_irq(&ensoniq->reg_lock); - ucontrol->value.integer.value[0] = ensoniq->ctrl & mask ? 1 : 0; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_ensoniq_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol); - int mask = kcontrol->private_value; - unsigned int nval; - int change; - - nval = ucontrol->value.integer.value[0] ? mask : 0; - spin_lock_irq(&ensoniq->reg_lock); - change = (ensoniq->ctrl & mask) != nval; - ensoniq->ctrl &= ~mask; - ensoniq->ctrl |= nval; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - spin_unlock_irq(&ensoniq->reg_lock); - return change; -} - -/* - * ENS1370 mixer - */ - -static struct snd_kcontrol_new snd_es1370_controls[2] __devinitdata = { -ENSONIQ_CONTROL("PCM 0 Output also on Line-In Jack", ES_1370_XCTL0), -ENSONIQ_CONTROL("Mic +5V bias", ES_1370_XCTL1) -}; - -#define ES1370_CONTROLS ARRAY_SIZE(snd_es1370_controls) - -static void snd_ensoniq_mixer_free_ak4531(struct snd_ak4531 *ak4531) -{ - struct ensoniq *ensoniq = ak4531->private_data; - ensoniq->u.es1370.ak4531 = NULL; -} - -static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq) -{ - struct snd_card *card = ensoniq->card; - struct snd_ak4531 ak4531; - unsigned int idx; - int err; - - /* try reset AK4531 */ - outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x02), ES_REG(ensoniq, 1370_CODEC)); - inw(ES_REG(ensoniq, 1370_CODEC)); - udelay(100); - outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x03), ES_REG(ensoniq, 1370_CODEC)); - inw(ES_REG(ensoniq, 1370_CODEC)); - udelay(100); - - memset(&ak4531, 0, sizeof(ak4531)); - ak4531.write = snd_es1370_codec_write; - ak4531.private_data = ensoniq; - ak4531.private_free = snd_ensoniq_mixer_free_ak4531; - if ((err = snd_ak4531_mixer(card, &ak4531, &ensoniq->u.es1370.ak4531)) < 0) - return err; - for (idx = 0; idx < ES1370_CONTROLS; idx++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_es1370_controls[idx], ensoniq)); - if (err < 0) - return err; - } - return 0; -} - -#endif /* CHIP1370 */ - -#ifdef SUPPORT_JOYSTICK - -#ifdef CHIP1371 -static int __devinit snd_ensoniq_get_joystick_port(int dev) -{ - switch (joystick_port[dev]) { - case 0: /* disabled */ - case 1: /* auto-detect */ - case 0x200: - case 0x208: - case 0x210: - case 0x218: - return joystick_port[dev]; - - default: - printk(KERN_ERR "ens1371: invalid joystick port %#x", joystick_port[dev]); - return 0; - } -} -#else -static inline int snd_ensoniq_get_joystick_port(int dev) -{ - return joystick[dev] ? 0x200 : 0; -} -#endif - -static int __devinit snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev) -{ - struct gameport *gp; - int io_port; - - io_port = snd_ensoniq_get_joystick_port(dev); - - switch (io_port) { - case 0: - return -ENOSYS; - - case 1: /* auto_detect */ - for (io_port = 0x200; io_port <= 0x218; io_port += 8) - if (request_region(io_port, 8, "ens137x: gameport")) - break; - if (io_port > 0x218) { - printk(KERN_WARNING "ens137x: no gameport ports available\n"); - return -EBUSY; - } - break; - - default: - if (!request_region(io_port, 8, "ens137x: gameport")) { - printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n", - io_port); - return -EBUSY; - } - break; - } - - ensoniq->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "ens137x: cannot allocate memory for gameport\n"); - release_region(io_port, 8); - return -ENOMEM; - } - - gameport_set_name(gp, "ES137x"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(ensoniq->pci)); - gameport_set_dev_parent(gp, &ensoniq->pci->dev); - gp->io = io_port; - - ensoniq->ctrl |= ES_JYSTK_EN; -#ifdef CHIP1371 - ensoniq->ctrl &= ~ES_1371_JOY_ASELM; - ensoniq->ctrl |= ES_1371_JOY_ASEL((io_port - 0x200) / 8); -#endif - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - - gameport_register_port(ensoniq->gameport); - - return 0; -} - -static void snd_ensoniq_free_gameport(struct ensoniq *ensoniq) -{ - if (ensoniq->gameport) { - int port = ensoniq->gameport->io; - - gameport_unregister_port(ensoniq->gameport); - ensoniq->gameport = NULL; - ensoniq->ctrl &= ~ES_JYSTK_EN; - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - release_region(port, 8); - } -} -#else -static inline int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, long port) { return -ENOSYS; } -static inline void snd_ensoniq_free_gameport(struct ensoniq *ensoniq) { } -#endif /* SUPPORT_JOYSTICK */ - -/* - - */ - -static void snd_ensoniq_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct ensoniq *ensoniq = entry->private_data; - -#ifdef CHIP1370 - snd_iprintf(buffer, "Ensoniq AudioPCI ES1370\n\n"); -#else - snd_iprintf(buffer, "Ensoniq AudioPCI ES1371\n\n"); -#endif - snd_iprintf(buffer, "Joystick enable : %s\n", - ensoniq->ctrl & ES_JYSTK_EN ? "on" : "off"); -#ifdef CHIP1370 - snd_iprintf(buffer, "MIC +5V bias : %s\n", - ensoniq->ctrl & ES_1370_XCTL1 ? "on" : "off"); - snd_iprintf(buffer, "Line In to AOUT : %s\n", - ensoniq->ctrl & ES_1370_XCTL0 ? "on" : "off"); -#else - snd_iprintf(buffer, "Joystick port : 0x%x\n", - (ES_1371_JOY_ASELI(ensoniq->ctrl) * 8) + 0x200); -#endif -} - -static void __devinit snd_ensoniq_proc_init(struct ensoniq * ensoniq) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry)) - snd_info_set_text_ops(entry, ensoniq, snd_ensoniq_proc_read); -} - -/* - - */ - -static int snd_ensoniq_free(struct ensoniq *ensoniq) -{ - snd_ensoniq_free_gameport(ensoniq); - if (ensoniq->irq < 0) - goto __hw_end; -#ifdef CHIP1370 - outl(ES_1370_SERR_DISABLE, ES_REG(ensoniq, CONTROL)); /* switch everything off */ - outl(0, ES_REG(ensoniq, SERIAL)); /* clear serial interface */ -#else - outl(0, ES_REG(ensoniq, CONTROL)); /* switch everything off */ - outl(0, ES_REG(ensoniq, SERIAL)); /* clear serial interface */ -#endif - if (ensoniq->irq >= 0) - synchronize_irq(ensoniq->irq); - pci_set_power_state(ensoniq->pci, 3); - __hw_end: -#ifdef CHIP1370 - if (ensoniq->dma_bug.area) - snd_dma_free_pages(&ensoniq->dma_bug); -#endif - if (ensoniq->irq >= 0) - free_irq(ensoniq->irq, ensoniq); - pci_release_regions(ensoniq->pci); - pci_disable_device(ensoniq->pci); - kfree(ensoniq); - return 0; -} - -static int snd_ensoniq_dev_free(struct snd_device *device) -{ - struct ensoniq *ensoniq = device->device_data; - return snd_ensoniq_free(ensoniq); -} - -#ifdef CHIP1371 -static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = { - SND_PCI_QUIRK_ID(0x107b, 0x2150), /* Gateway Solo 2150 */ - SND_PCI_QUIRK_ID(0x13bd, 0x100c), /* EV1938 on Mebius PC-MJ100V */ - SND_PCI_QUIRK_ID(0x1102, 0x5938), /* Targa Xtender300 */ - SND_PCI_QUIRK_ID(0x1102, 0x8938), /* IPC Topnote G notebook */ - { } /* end */ -}; - -static struct es1371_quirk es1371_ac97_reset_hack[] = { - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_CT5880_A }, - { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_ES1373_8 }, - { .vid = PCI_ANY_ID, .did = PCI_ANY_ID } -}; -#endif - -static void snd_ensoniq_chip_init(struct ensoniq *ensoniq) -{ -#ifdef CHIP1371 - int idx; -#endif - /* this code was part of snd_ensoniq_create before intruduction - * of suspend/resume - */ -#ifdef CHIP1370 - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE)); - outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME)); - outl(0, ES_REG(ensoniq, PHANTOM_COUNT)); -#else - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - outl(0, ES_REG(ensoniq, 1371_LEGACY)); - if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack)) { - outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); - /* need to delay around 20ms(bleech) to give - some CODECs enough time to wakeup */ - msleep(20); - } - /* AC'97 warm reset to start the bitclk */ - outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL)); - inl(ES_REG(ensoniq, CONTROL)); - udelay(20); - outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); - /* Init the sample rate converter */ - snd_es1371_wait_src_ready(ensoniq); - outl(ES_1371_SRC_DISABLE, ES_REG(ensoniq, 1371_SMPRATE)); - for (idx = 0; idx < 0x80; idx++) - snd_es1371_src_write(ensoniq, idx, 0); - snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4); - snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10); - snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4); - snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10); - snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, 1 << 12); - snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, 1 << 12); - snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1, 1 << 12); - snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1 + 1, 1 << 12); - snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2, 1 << 12); - snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2 + 1, 1 << 12); - snd_es1371_adc_rate(ensoniq, 22050); - snd_es1371_dac1_rate(ensoniq, 22050); - snd_es1371_dac2_rate(ensoniq, 22050); - /* WARNING: - * enabling the sample rate converter without properly programming - * its parameters causes the chip to lock up (the SRC busy bit will - * be stuck high, and I've found no way to rectify this other than - * power cycle) - Thomas Sailer - */ - snd_es1371_wait_src_ready(ensoniq); - outl(0, ES_REG(ensoniq, 1371_SMPRATE)); - /* try reset codec directly */ - outl(ES_1371_CODEC_WRITE(0, 0), ES_REG(ensoniq, 1371_CODEC)); -#endif - outb(ensoniq->uartc = 0x00, ES_REG(ensoniq, UART_CONTROL)); - outb(0x00, ES_REG(ensoniq, UART_RES)); - outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); - synchronize_irq(ensoniq->irq); -} - -#ifdef CONFIG_PM -static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct ensoniq *ensoniq = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(ensoniq->pcm1); - snd_pcm_suspend_all(ensoniq->pcm2); - -#ifdef CHIP1371 - snd_ac97_suspend(ensoniq->u.es1371.ac97); -#else - /* try to reset AK4531 */ - outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x02), ES_REG(ensoniq, 1370_CODEC)); - inw(ES_REG(ensoniq, 1370_CODEC)); - udelay(100); - outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x03), ES_REG(ensoniq, 1370_CODEC)); - inw(ES_REG(ensoniq, 1370_CODEC)); - udelay(100); - snd_ak4531_suspend(ensoniq->u.es1370.ak4531); -#endif - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_ensoniq_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct ensoniq *ensoniq = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR DRIVER_NAME ": pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_ensoniq_chip_init(ensoniq); - -#ifdef CHIP1371 - snd_ac97_resume(ensoniq->u.es1371.ac97); -#else - snd_ak4531_resume(ensoniq->u.es1370.ak4531); -#endif - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - - -static int __devinit snd_ensoniq_create(struct snd_card *card, - struct pci_dev *pci, - struct ensoniq ** rensoniq) -{ - struct ensoniq *ensoniq; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_ensoniq_dev_free, - }; - - *rensoniq = NULL; - if ((err = pci_enable_device(pci)) < 0) - return err; - ensoniq = kzalloc(sizeof(*ensoniq), GFP_KERNEL); - if (ensoniq == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&ensoniq->reg_lock); - mutex_init(&ensoniq->src_mutex); - ensoniq->card = card; - ensoniq->pci = pci; - ensoniq->irq = -1; - if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) { - kfree(ensoniq); - pci_disable_device(pci); - return err; - } - ensoniq->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_SHARED, - KBUILD_MODNAME, ensoniq)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_ensoniq_free(ensoniq); - return -EBUSY; - } - ensoniq->irq = pci->irq; -#ifdef CHIP1370 - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - 16, &ensoniq->dma_bug) < 0) { - snd_printk(KERN_ERR "unable to allocate space for phantom area - dma_bug\n"); - snd_ensoniq_free(ensoniq); - return -EBUSY; - } -#endif - pci_set_master(pci); - ensoniq->rev = pci->revision; -#ifdef CHIP1370 -#if 0 - ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | - ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000)); -#else /* get microphone working */ - ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000)); -#endif - ensoniq->sctrl = 0; -#else - ensoniq->ctrl = 0; - ensoniq->sctrl = 0; - ensoniq->cssr = 0; - if (snd_pci_quirk_lookup(pci, es1371_amplifier_hack)) - ensoniq->ctrl |= ES_1371_GPIO_OUT(1); /* turn amplifier on */ - - if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack)) - ensoniq->cssr |= ES_1371_ST_AC97_RST; -#endif - - snd_ensoniq_chip_init(ensoniq); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops)) < 0) { - snd_ensoniq_free(ensoniq); - return err; - } - - snd_ensoniq_proc_init(ensoniq); - - snd_card_set_dev(card, &pci->dev); - - *rensoniq = ensoniq; - return 0; -} - -/* - * MIDI section - */ - -static void snd_ensoniq_midi_interrupt(struct ensoniq * ensoniq) -{ - struct snd_rawmidi *rmidi = ensoniq->rmidi; - unsigned char status, mask, byte; - - if (rmidi == NULL) - return; - /* do Rx at first */ - spin_lock(&ensoniq->reg_lock); - mask = ensoniq->uartm & ES_MODE_INPUT ? ES_RXRDY : 0; - while (mask) { - status = inb(ES_REG(ensoniq, UART_STATUS)); - if ((status & mask) == 0) - break; - byte = inb(ES_REG(ensoniq, UART_DATA)); - snd_rawmidi_receive(ensoniq->midi_input, &byte, 1); - } - spin_unlock(&ensoniq->reg_lock); - - /* do Tx at second */ - spin_lock(&ensoniq->reg_lock); - mask = ensoniq->uartm & ES_MODE_OUTPUT ? ES_TXRDY : 0; - while (mask) { - status = inb(ES_REG(ensoniq, UART_STATUS)); - if ((status & mask) == 0) - break; - if (snd_rawmidi_transmit(ensoniq->midi_output, &byte, 1) != 1) { - ensoniq->uartc &= ~ES_TXINTENM; - outb(ensoniq->uartc, ES_REG(ensoniq, UART_CONTROL)); - mask &= ~ES_TXRDY; - } else { - outb(byte, ES_REG(ensoniq, UART_DATA)); - } - } - spin_unlock(&ensoniq->reg_lock); -} - -static int snd_ensoniq_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct ensoniq *ensoniq = substream->rmidi->private_data; - - spin_lock_irq(&ensoniq->reg_lock); - ensoniq->uartm |= ES_MODE_INPUT; - ensoniq->midi_input = substream; - if (!(ensoniq->uartm & ES_MODE_OUTPUT)) { - outb(ES_CNTRL(3), ES_REG(ensoniq, UART_CONTROL)); - outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL)); - outl(ensoniq->ctrl |= ES_UART_EN, ES_REG(ensoniq, CONTROL)); - } - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_ensoniq_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct ensoniq *ensoniq = substream->rmidi->private_data; - - spin_lock_irq(&ensoniq->reg_lock); - if (!(ensoniq->uartm & ES_MODE_OUTPUT)) { - outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL)); - outl(ensoniq->ctrl &= ~ES_UART_EN, ES_REG(ensoniq, CONTROL)); - } else { - outb(ensoniq->uartc &= ~ES_RXINTEN, ES_REG(ensoniq, UART_CONTROL)); - } - ensoniq->midi_input = NULL; - ensoniq->uartm &= ~ES_MODE_INPUT; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_ensoniq_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct ensoniq *ensoniq = substream->rmidi->private_data; - - spin_lock_irq(&ensoniq->reg_lock); - ensoniq->uartm |= ES_MODE_OUTPUT; - ensoniq->midi_output = substream; - if (!(ensoniq->uartm & ES_MODE_INPUT)) { - outb(ES_CNTRL(3), ES_REG(ensoniq, UART_CONTROL)); - outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL)); - outl(ensoniq->ctrl |= ES_UART_EN, ES_REG(ensoniq, CONTROL)); - } - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static int snd_ensoniq_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct ensoniq *ensoniq = substream->rmidi->private_data; - - spin_lock_irq(&ensoniq->reg_lock); - if (!(ensoniq->uartm & ES_MODE_INPUT)) { - outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL)); - outl(ensoniq->ctrl &= ~ES_UART_EN, ES_REG(ensoniq, CONTROL)); - } else { - outb(ensoniq->uartc &= ~ES_TXINTENM, ES_REG(ensoniq, UART_CONTROL)); - } - ensoniq->midi_output = NULL; - ensoniq->uartm &= ~ES_MODE_OUTPUT; - spin_unlock_irq(&ensoniq->reg_lock); - return 0; -} - -static void snd_ensoniq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct ensoniq *ensoniq = substream->rmidi->private_data; - int idx; - - spin_lock_irqsave(&ensoniq->reg_lock, flags); - if (up) { - if ((ensoniq->uartc & ES_RXINTEN) == 0) { - /* empty input FIFO */ - for (idx = 0; idx < 32; idx++) - inb(ES_REG(ensoniq, UART_DATA)); - ensoniq->uartc |= ES_RXINTEN; - outb(ensoniq->uartc, ES_REG(ensoniq, UART_CONTROL)); - } - } else { - if (ensoniq->uartc & ES_RXINTEN) { - ensoniq->uartc &= ~ES_RXINTEN; - outb(ensoniq->uartc, ES_REG(ensoniq, UART_CONTROL)); - } - } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); -} - -static void snd_ensoniq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct ensoniq *ensoniq = substream->rmidi->private_data; - unsigned char byte; - - spin_lock_irqsave(&ensoniq->reg_lock, flags); - if (up) { - if (ES_TXINTENI(ensoniq->uartc) == 0) { - ensoniq->uartc |= ES_TXINTENO(1); - /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */ - while (ES_TXINTENI(ensoniq->uartc) == 1 && - (inb(ES_REG(ensoniq, UART_STATUS)) & ES_TXRDY)) { - if (snd_rawmidi_transmit(substream, &byte, 1) != 1) { - ensoniq->uartc &= ~ES_TXINTENM; - } else { - outb(byte, ES_REG(ensoniq, UART_DATA)); - } - } - outb(ensoniq->uartc, ES_REG(ensoniq, UART_CONTROL)); - } - } else { - if (ES_TXINTENI(ensoniq->uartc) == 1) { - ensoniq->uartc &= ~ES_TXINTENM; - outb(ensoniq->uartc, ES_REG(ensoniq, UART_CONTROL)); - } - } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); -} - -static struct snd_rawmidi_ops snd_ensoniq_midi_output = -{ - .open = snd_ensoniq_midi_output_open, - .close = snd_ensoniq_midi_output_close, - .trigger = snd_ensoniq_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_ensoniq_midi_input = -{ - .open = snd_ensoniq_midi_input_open, - .close = snd_ensoniq_midi_input_close, - .trigger = snd_ensoniq_midi_input_trigger, -}; - -static int __devinit snd_ensoniq_midi(struct ensoniq * ensoniq, int device, - struct snd_rawmidi **rrawmidi) -{ - struct snd_rawmidi *rmidi; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0) - return err; -#ifdef CHIP1370 - strcpy(rmidi->name, "ES1370"); -#else - strcpy(rmidi->name, "ES1371"); -#endif - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_ensoniq_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_ensoniq_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = ensoniq; - ensoniq->rmidi = rmidi; - if (rrawmidi) - *rrawmidi = rmidi; - return 0; -} - -/* - * Interrupt handler - */ - -static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id) -{ - struct ensoniq *ensoniq = dev_id; - unsigned int status, sctrl; - - if (ensoniq == NULL) - return IRQ_NONE; - - status = inl(ES_REG(ensoniq, STATUS)); - if (!(status & ES_INTR)) - return IRQ_NONE; - - spin_lock(&ensoniq->reg_lock); - sctrl = ensoniq->sctrl; - if (status & ES_DAC1) - sctrl &= ~ES_P1_INT_EN; - if (status & ES_DAC2) - sctrl &= ~ES_P2_INT_EN; - if (status & ES_ADC) - sctrl &= ~ES_R1_INT_EN; - outl(sctrl, ES_REG(ensoniq, SERIAL)); - outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); - spin_unlock(&ensoniq->reg_lock); - - if (status & ES_UART) - snd_ensoniq_midi_interrupt(ensoniq); - if ((status & ES_DAC2) && ensoniq->playback2_substream) - snd_pcm_period_elapsed(ensoniq->playback2_substream); - if ((status & ES_ADC) && ensoniq->capture_substream) - snd_pcm_period_elapsed(ensoniq->capture_substream); - if ((status & ES_DAC1) && ensoniq->playback1_substream) - snd_pcm_period_elapsed(ensoniq->playback1_substream); - return IRQ_HANDLED; -} - -static int __devinit snd_audiopci_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct ensoniq *ensoniq; - int err, pcm_devs[2]; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_ensoniq_create(card, pci, &ensoniq)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = ensoniq; - - pcm_devs[0] = 0; pcm_devs[1] = 1; -#ifdef CHIP1370 - if ((err = snd_ensoniq_1370_mixer(ensoniq)) < 0) { - snd_card_free(card); - return err; - } -#endif -#ifdef CHIP1371 - if ((err = snd_ensoniq_1371_mixer(ensoniq, spdif[dev], lineio[dev])) < 0) { - snd_card_free(card); - return err; - } -#endif - if ((err = snd_ensoniq_pcm(ensoniq, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_ensoniq_pcm2(ensoniq, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_ensoniq_midi(ensoniq, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - - snd_ensoniq_create_gameport(ensoniq, dev); - - strcpy(card->driver, DRIVER_NAME); - - strcpy(card->shortname, "Ensoniq AudioPCI"); - sprintf(card->longname, "%s %s at 0x%lx, irq %i", - card->shortname, - card->driver, - ensoniq->port, - ensoniq->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_audiopci_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_audiopci_ids, - .probe = snd_audiopci_probe, - .remove = __devexit_p(snd_audiopci_remove), -#ifdef CONFIG_PM - .suspend = snd_ensoniq_suspend, - .resume = snd_ensoniq_resume, -#endif -}; - -static int __init alsa_card_ens137x_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_ens137x_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_ens137x_init) -module_exit(alsa_card_ens137x_exit) diff --git a/ANDROID_3.4.5/sound/pci/ens1371.c b/ANDROID_3.4.5/sound/pci/ens1371.c deleted file mode 100644 index ca0da0ab..00000000 --- a/ANDROID_3.4.5/sound/pci/ens1371.c +++ /dev/null @@ -1,2 +0,0 @@ -#define CHIP1371 -#include "ens1370.c" diff --git a/ANDROID_3.4.5/sound/pci/es1938.c b/ANDROID_3.4.5/sound/pci/es1938.c deleted file mode 100644 index 53eb76b4..00000000 --- a/ANDROID_3.4.5/sound/pci/es1938.c +++ /dev/null @@ -1,1907 +0,0 @@ -/* - * Driver for ESS Solo-1 (ES1938, ES1946, ES1969) soundcard - * Copyright (c) by Jaromir Koutek , - * Jaroslav Kysela , - * Thomas Sailer , - * Abramo Bagnara , - * Markus Gruber - * - * Rewritten from sonicvibes.c source. - * - * TODO: - * Rewrite better spinlocks - * - * - * 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 - * - */ - -/* - NOTES: - - Capture data is written unaligned starting from dma_base + 1 so I need to - disable mmap and to add a copy callback. - - After several cycle of the following: - while : ; do arecord -d1 -f cd -t raw | aplay -f cd ; done - a "playback write error (DMA or IRQ trouble?)" may happen. - This is due to playback interrupts not generated. - I suspect a timing issue. - - Sometimes the interrupt handler is invoked wrongly during playback. - This generates some harmless "Unexpected hw_pointer: wrong interrupt - acknowledge". - I've seen that using small period sizes. - Reproducible with: - mpg123 test.mp3 & - hdparm -t -T /dev/hda -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -MODULE_AUTHOR("Jaromir Koutek "); -MODULE_DESCRIPTION("ESS Solo-1"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESS,ES1938}," - "{ESS,ES1946}," - "{ESS,ES1969}," - "{TerraTec,128i PCI}}"); - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ESS Solo-1 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ESS Solo-1 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ESS Solo-1 soundcard."); - -#define SLIO_REG(chip, x) ((chip)->io_port + ESSIO_REG_##x) - -#define SLDM_REG(chip, x) ((chip)->ddma_port + ESSDM_REG_##x) - -#define SLSB_REG(chip, x) ((chip)->sb_port + ESSSB_REG_##x) - -#define SL_PCI_LEGACYCONTROL 0x40 -#define SL_PCI_CONFIG 0x50 -#define SL_PCI_DDMACONTROL 0x60 - -#define ESSIO_REG_AUDIO2DMAADDR 0 -#define ESSIO_REG_AUDIO2DMACOUNT 4 -#define ESSIO_REG_AUDIO2MODE 6 -#define ESSIO_REG_IRQCONTROL 7 - -#define ESSDM_REG_DMAADDR 0x00 -#define ESSDM_REG_DMACOUNT 0x04 -#define ESSDM_REG_DMACOMMAND 0x08 -#define ESSDM_REG_DMASTATUS 0x08 -#define ESSDM_REG_DMAMODE 0x0b -#define ESSDM_REG_DMACLEAR 0x0d -#define ESSDM_REG_DMAMASK 0x0f - -#define ESSSB_REG_FMLOWADDR 0x00 -#define ESSSB_REG_FMHIGHADDR 0x02 -#define ESSSB_REG_MIXERADDR 0x04 -#define ESSSB_REG_MIXERDATA 0x05 - -#define ESSSB_IREG_AUDIO1 0x14 -#define ESSSB_IREG_MICMIX 0x1a -#define ESSSB_IREG_RECSRC 0x1c -#define ESSSB_IREG_MASTER 0x32 -#define ESSSB_IREG_FM 0x36 -#define ESSSB_IREG_AUXACD 0x38 -#define ESSSB_IREG_AUXB 0x3a -#define ESSSB_IREG_PCSPEAKER 0x3c -#define ESSSB_IREG_LINE 0x3e -#define ESSSB_IREG_SPATCONTROL 0x50 -#define ESSSB_IREG_SPATLEVEL 0x52 -#define ESSSB_IREG_MASTER_LEFT 0x60 -#define ESSSB_IREG_MASTER_RIGHT 0x62 -#define ESSSB_IREG_MPU401CONTROL 0x64 -#define ESSSB_IREG_MICMIXRECORD 0x68 -#define ESSSB_IREG_AUDIO2RECORD 0x69 -#define ESSSB_IREG_AUXACDRECORD 0x6a -#define ESSSB_IREG_FMRECORD 0x6b -#define ESSSB_IREG_AUXBRECORD 0x6c -#define ESSSB_IREG_MONO 0x6d -#define ESSSB_IREG_LINERECORD 0x6e -#define ESSSB_IREG_MONORECORD 0x6f -#define ESSSB_IREG_AUDIO2SAMPLE 0x70 -#define ESSSB_IREG_AUDIO2MODE 0x71 -#define ESSSB_IREG_AUDIO2FILTER 0x72 -#define ESSSB_IREG_AUDIO2TCOUNTL 0x74 -#define ESSSB_IREG_AUDIO2TCOUNTH 0x76 -#define ESSSB_IREG_AUDIO2CONTROL1 0x78 -#define ESSSB_IREG_AUDIO2CONTROL2 0x7a -#define ESSSB_IREG_AUDIO2 0x7c - -#define ESSSB_REG_RESET 0x06 - -#define ESSSB_REG_READDATA 0x0a -#define ESSSB_REG_WRITEDATA 0x0c -#define ESSSB_REG_READSTATUS 0x0c - -#define ESSSB_REG_STATUS 0x0e - -#define ESS_CMD_EXTSAMPLERATE 0xa1 -#define ESS_CMD_FILTERDIV 0xa2 -#define ESS_CMD_DMACNTRELOADL 0xa4 -#define ESS_CMD_DMACNTRELOADH 0xa5 -#define ESS_CMD_ANALOGCONTROL 0xa8 -#define ESS_CMD_IRQCONTROL 0xb1 -#define ESS_CMD_DRQCONTROL 0xb2 -#define ESS_CMD_RECLEVEL 0xb4 -#define ESS_CMD_SETFORMAT 0xb6 -#define ESS_CMD_SETFORMAT2 0xb7 -#define ESS_CMD_DMACONTROL 0xb8 -#define ESS_CMD_DMATYPE 0xb9 -#define ESS_CMD_OFFSETLEFT 0xba -#define ESS_CMD_OFFSETRIGHT 0xbb -#define ESS_CMD_READREG 0xc0 -#define ESS_CMD_ENABLEEXT 0xc6 -#define ESS_CMD_PAUSEDMA 0xd0 -#define ESS_CMD_ENABLEAUDIO1 0xd1 -#define ESS_CMD_STOPAUDIO1 0xd3 -#define ESS_CMD_AUDIO1STATUS 0xd8 -#define ESS_CMD_CONTDMA 0xd4 -#define ESS_CMD_TESTIRQ 0xf2 - -#define ESS_RECSRC_MIC 0 -#define ESS_RECSRC_AUXACD 2 -#define ESS_RECSRC_AUXB 5 -#define ESS_RECSRC_LINE 6 -#define ESS_RECSRC_NONE 7 - -#define DAC1 0x01 -#define ADC1 0x02 -#define DAC2 0x04 - -/* - - */ - -#define SAVED_REG_SIZE 32 /* max. number of registers to save */ - -struct es1938 { - int irq; - - unsigned long io_port; - unsigned long sb_port; - unsigned long vc_port; - unsigned long mpu_port; - unsigned long game_port; - unsigned long ddma_port; - - unsigned char irqmask; - unsigned char revision; - - struct snd_kcontrol *hw_volume; - struct snd_kcontrol *hw_switch; - struct snd_kcontrol *master_volume; - struct snd_kcontrol *master_switch; - - struct pci_dev *pci; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_pcm_substream *capture_substream; - struct snd_pcm_substream *playback1_substream; - struct snd_pcm_substream *playback2_substream; - struct snd_rawmidi *rmidi; - - unsigned int dma1_size; - unsigned int dma2_size; - unsigned int dma1_start; - unsigned int dma2_start; - unsigned int dma1_shift; - unsigned int dma2_shift; - unsigned int last_capture_dmaaddr; - unsigned int active; - - spinlock_t reg_lock; - spinlock_t mixer_lock; - struct snd_info_entry *proc_entry; - -#ifdef SUPPORT_JOYSTICK - struct gameport *gameport; -#endif -#ifdef CONFIG_PM - unsigned char saved_regs[SAVED_REG_SIZE]; -#endif -}; - -static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id); - -static DEFINE_PCI_DEVICE_TABLE(snd_es1938_ids) = { - { PCI_VDEVICE(ESS, 0x1969), 0, }, /* Solo-1 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_es1938_ids); - -#define RESET_LOOP_TIMEOUT 0x10000 -#define WRITE_LOOP_TIMEOUT 0x10000 -#define GET_LOOP_TIMEOUT 0x01000 - -#undef REG_DEBUG -/* ----------------------------------------------------------------- - * Write to a mixer register - * -----------------------------------------------------------------*/ -static void snd_es1938_mixer_write(struct es1938 *chip, unsigned char reg, unsigned char val) -{ - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, SLSB_REG(chip, MIXERADDR)); - outb(val, SLSB_REG(chip, MIXERDATA)); - spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x set to %02x\n", reg, val); -#endif -} - -/* ----------------------------------------------------------------- - * Read from a mixer register - * -----------------------------------------------------------------*/ -static int snd_es1938_mixer_read(struct es1938 *chip, unsigned char reg) -{ - int data; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, SLSB_REG(chip, MIXERADDR)); - data = inb(SLSB_REG(chip, MIXERDATA)); - spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x now is %02x\n", reg, data); -#endif - return data; -} - -/* ----------------------------------------------------------------- - * Write to some bits of a mixer register (return old value) - * -----------------------------------------------------------------*/ -static int snd_es1938_mixer_bits(struct es1938 *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - unsigned long flags; - unsigned char old, new, oval; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, SLSB_REG(chip, MIXERADDR)); - old = inb(SLSB_REG(chip, MIXERDATA)); - oval = old & mask; - if (val != oval) { - new = (old & ~mask) | (val & mask); - outb(new, SLSB_REG(chip, MIXERDATA)); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x\n", - reg, old, new); -#endif - } - spin_unlock_irqrestore(&chip->mixer_lock, flags); - return oval; -} - -/* ----------------------------------------------------------------- - * Write command to Controller Registers - * -----------------------------------------------------------------*/ -static void snd_es1938_write_cmd(struct es1938 *chip, unsigned char cmd) -{ - int i; - unsigned char v; - for (i = 0; i < WRITE_LOOP_TIMEOUT; i++) { - if (!(v = inb(SLSB_REG(chip, READSTATUS)) & 0x80)) { - outb(cmd, SLSB_REG(chip, WRITEDATA)); - return; - } - } - printk(KERN_ERR "snd_es1938_write_cmd timeout (0x02%x/0x02%x)\n", cmd, v); -} - -/* ----------------------------------------------------------------- - * Read the Read Data Buffer - * -----------------------------------------------------------------*/ -static int snd_es1938_get_byte(struct es1938 *chip) -{ - int i; - unsigned char v; - for (i = GET_LOOP_TIMEOUT; i; i--) - if ((v = inb(SLSB_REG(chip, STATUS))) & 0x80) - return inb(SLSB_REG(chip, READDATA)); - snd_printk(KERN_ERR "get_byte timeout: status 0x02%x\n", v); - return -ENODEV; -} - -/* ----------------------------------------------------------------- - * Write value cmd register - * -----------------------------------------------------------------*/ -static void snd_es1938_write(struct es1938 *chip, unsigned char reg, unsigned char val) -{ - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1938_write_cmd(chip, reg); - snd_es1938_write_cmd(chip, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x set to %02x\n", reg, val); -#endif -} - -/* ----------------------------------------------------------------- - * Read data from cmd register and return it - * -----------------------------------------------------------------*/ -static unsigned char snd_es1938_read(struct es1938 *chip, unsigned char reg) -{ - unsigned char val; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1938_write_cmd(chip, ESS_CMD_READREG); - snd_es1938_write_cmd(chip, reg); - val = snd_es1938_get_byte(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x now is %02x\n", reg, val); -#endif - return val; -} - -/* ----------------------------------------------------------------- - * Write data to cmd register and return old value - * -----------------------------------------------------------------*/ -static int snd_es1938_bits(struct es1938 *chip, unsigned char reg, unsigned char mask, - unsigned char val) -{ - unsigned long flags; - unsigned char old, new, oval; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1938_write_cmd(chip, ESS_CMD_READREG); - snd_es1938_write_cmd(chip, reg); - old = snd_es1938_get_byte(chip); - oval = old & mask; - if (val != oval) { - snd_es1938_write_cmd(chip, reg); - new = (old & ~mask) | (val & mask); - snd_es1938_write_cmd(chip, new); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x was %02x, set to %02x\n", - reg, old, new); -#endif - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return oval; -} - -/* -------------------------------------------------------------------- - * Reset the chip - * --------------------------------------------------------------------*/ -static void snd_es1938_reset(struct es1938 *chip) -{ - int i; - - outb(3, SLSB_REG(chip, RESET)); - inb(SLSB_REG(chip, RESET)); - outb(0, SLSB_REG(chip, RESET)); - for (i = 0; i < RESET_LOOP_TIMEOUT; i++) { - if (inb(SLSB_REG(chip, STATUS)) & 0x80) { - if (inb(SLSB_REG(chip, READDATA)) == 0xaa) - goto __next; - } - } - snd_printk(KERN_ERR "ESS Solo-1 reset failed\n"); - - __next: - snd_es1938_write_cmd(chip, ESS_CMD_ENABLEEXT); - - /* Demand transfer DMA: 4 bytes per DMA request */ - snd_es1938_write(chip, ESS_CMD_DMATYPE, 2); - - /* Change behaviour of register A1 - 4x oversampling - 2nd channel DAC asynchronous */ - snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2MODE, 0x32); - /* enable/select DMA channel and IRQ channel */ - snd_es1938_bits(chip, ESS_CMD_IRQCONTROL, 0xf0, 0x50); - snd_es1938_bits(chip, ESS_CMD_DRQCONTROL, 0xf0, 0x50); - snd_es1938_write_cmd(chip, ESS_CMD_ENABLEAUDIO1); - /* Set spatializer parameters to recommended values */ - snd_es1938_mixer_write(chip, 0x54, 0x8f); - snd_es1938_mixer_write(chip, 0x56, 0x95); - snd_es1938_mixer_write(chip, 0x58, 0x94); - snd_es1938_mixer_write(chip, 0x5a, 0x80); -} - -/* -------------------------------------------------------------------- - * Reset the FIFOs - * --------------------------------------------------------------------*/ -static void snd_es1938_reset_fifo(struct es1938 *chip) -{ - outb(2, SLSB_REG(chip, RESET)); - outb(0, SLSB_REG(chip, RESET)); -} - -static struct snd_ratnum clocks[2] = { - { - .num = 793800, - .den_min = 1, - .den_max = 128, - .den_step = 1, - }, - { - .num = 768000, - .den_min = 1, - .den_max = 128, - .den_step = 1, - } -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { - .nrats = 2, - .rats = clocks, -}; - - -static void snd_es1938_rate_set(struct es1938 *chip, - struct snd_pcm_substream *substream, - int mode) -{ - unsigned int bits, div0; - struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->rate_num == clocks[0].num) - bits = 128 - runtime->rate_den; - else - bits = 256 - runtime->rate_den; - - /* set filter register */ - div0 = 256 - 7160000*20/(8*82*runtime->rate); - - if (mode == DAC2) { - snd_es1938_mixer_write(chip, 0x70, bits); - snd_es1938_mixer_write(chip, 0x72, div0); - } else { - snd_es1938_write(chip, 0xA1, bits); - snd_es1938_write(chip, 0xA2, div0); - } -} - -/* -------------------------------------------------------------------- - * Configure Solo1 builtin DMA Controller - * --------------------------------------------------------------------*/ - -static void snd_es1938_playback1_setdma(struct es1938 *chip) -{ - outb(0x00, SLIO_REG(chip, AUDIO2MODE)); - outl(chip->dma2_start, SLIO_REG(chip, AUDIO2DMAADDR)); - outw(0, SLIO_REG(chip, AUDIO2DMACOUNT)); - outw(chip->dma2_size, SLIO_REG(chip, AUDIO2DMACOUNT)); -} - -static void snd_es1938_playback2_setdma(struct es1938 *chip) -{ - /* Enable DMA controller */ - outb(0xc4, SLDM_REG(chip, DMACOMMAND)); - /* 1. Master reset */ - outb(0, SLDM_REG(chip, DMACLEAR)); - /* 2. Mask DMA */ - outb(1, SLDM_REG(chip, DMAMASK)); - outb(0x18, SLDM_REG(chip, DMAMODE)); - outl(chip->dma1_start, SLDM_REG(chip, DMAADDR)); - outw(chip->dma1_size - 1, SLDM_REG(chip, DMACOUNT)); - /* 3. Unmask DMA */ - outb(0, SLDM_REG(chip, DMAMASK)); -} - -static void snd_es1938_capture_setdma(struct es1938 *chip) -{ - /* Enable DMA controller */ - outb(0xc4, SLDM_REG(chip, DMACOMMAND)); - /* 1. Master reset */ - outb(0, SLDM_REG(chip, DMACLEAR)); - /* 2. Mask DMA */ - outb(1, SLDM_REG(chip, DMAMASK)); - outb(0x14, SLDM_REG(chip, DMAMODE)); - outl(chip->dma1_start, SLDM_REG(chip, DMAADDR)); - chip->last_capture_dmaaddr = chip->dma1_start; - outw(chip->dma1_size - 1, SLDM_REG(chip, DMACOUNT)); - /* 3. Unmask DMA */ - outb(0, SLDM_REG(chip, DMAMASK)); -} - -/* ---------------------------------------------------------------------- - * - * *** PCM part *** - */ - -static int snd_es1938_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - int val; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - val = 0x0f; - chip->active |= ADC1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - val = 0x00; - chip->active &= ~ADC1; - break; - default: - return -EINVAL; - } - snd_es1938_write(chip, ESS_CMD_DMACONTROL, val); - return 0; -} - -static int snd_es1938_playback1_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - /* According to the documentation this should be: - 0x13 but that value may randomly swap stereo channels */ - snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x92); - udelay(10); - snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x93); - /* This two stage init gives the FIFO -> DAC connection time to - * settle before first data from DMA flows in. This should ensure - * no swapping of stereo channels. Report a bug if otherwise :-) */ - outb(0x0a, SLIO_REG(chip, AUDIO2MODE)); - chip->active |= DAC2; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - outb(0, SLIO_REG(chip, AUDIO2MODE)); - snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0); - chip->active &= ~DAC2; - break; - default: - return -EINVAL; - } - return 0; -} - -static int snd_es1938_playback2_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - int val; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - val = 5; - chip->active |= DAC1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - val = 0; - chip->active &= ~DAC1; - break; - default: - return -EINVAL; - } - snd_es1938_write(chip, ESS_CMD_DMACONTROL, val); - return 0; -} - -static int snd_es1938_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - switch (substream->number) { - case 0: - return snd_es1938_playback1_trigger(substream, cmd); - case 1: - return snd_es1938_playback2_trigger(substream, cmd); - } - snd_BUG(); - return -EINVAL; -} - -/* -------------------------------------------------------------------- - * First channel for Extended Mode Audio 1 ADC Operation - * --------------------------------------------------------------------*/ -static int snd_es1938_capture_prepare(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int u, is8, mono; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->dma1_size = size; - chip->dma1_start = runtime->dma_addr; - - mono = (runtime->channels > 1) ? 0 : 1; - is8 = snd_pcm_format_width(runtime->format) == 16 ? 0 : 1; - u = snd_pcm_format_unsigned(runtime->format); - - chip->dma1_shift = 2 - mono - is8; - - snd_es1938_reset_fifo(chip); - - /* program type */ - snd_es1938_bits(chip, ESS_CMD_ANALOGCONTROL, 0x03, (mono ? 2 : 1)); - - /* set clock and counters */ - snd_es1938_rate_set(chip, substream, ADC1); - - count = 0x10000 - count; - snd_es1938_write(chip, ESS_CMD_DMACNTRELOADL, count & 0xff); - snd_es1938_write(chip, ESS_CMD_DMACNTRELOADH, count >> 8); - - /* initialize and configure ADC */ - snd_es1938_write(chip, ESS_CMD_SETFORMAT2, u ? 0x51 : 0x71); - snd_es1938_write(chip, ESS_CMD_SETFORMAT2, 0x90 | - (u ? 0x00 : 0x20) | - (is8 ? 0x00 : 0x04) | - (mono ? 0x40 : 0x08)); - - // snd_es1938_reset_fifo(chip); - - /* 11. configure system interrupt controller and DMA controller */ - snd_es1938_capture_setdma(chip); - - return 0; -} - - -/* ------------------------------------------------------------------------------ - * Second Audio channel DAC Operation - * ------------------------------------------------------------------------------*/ -static int snd_es1938_playback1_prepare(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int u, is8, mono; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->dma2_size = size; - chip->dma2_start = runtime->dma_addr; - - mono = (runtime->channels > 1) ? 0 : 1; - is8 = snd_pcm_format_width(runtime->format) == 16 ? 0 : 1; - u = snd_pcm_format_unsigned(runtime->format); - - chip->dma2_shift = 2 - mono - is8; - - snd_es1938_reset_fifo(chip); - - /* set clock and counters */ - snd_es1938_rate_set(chip, substream, DAC2); - - count >>= 1; - count = 0x10000 - count; - snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2TCOUNTL, count & 0xff); - snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2TCOUNTH, count >> 8); - - /* initialize and configure Audio 2 DAC */ - snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL2, 0x40 | (u ? 0 : 4) | - (mono ? 0 : 2) | (is8 ? 0 : 1)); - - /* program DMA */ - snd_es1938_playback1_setdma(chip); - - return 0; -} - -static int snd_es1938_playback2_prepare(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int u, is8, mono; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->dma1_size = size; - chip->dma1_start = runtime->dma_addr; - - mono = (runtime->channels > 1) ? 0 : 1; - is8 = snd_pcm_format_width(runtime->format) == 16 ? 0 : 1; - u = snd_pcm_format_unsigned(runtime->format); - - chip->dma1_shift = 2 - mono - is8; - - count = 0x10000 - count; - - /* reset */ - snd_es1938_reset_fifo(chip); - - snd_es1938_bits(chip, ESS_CMD_ANALOGCONTROL, 0x03, (mono ? 2 : 1)); - - /* set clock and counters */ - snd_es1938_rate_set(chip, substream, DAC1); - snd_es1938_write(chip, ESS_CMD_DMACNTRELOADL, count & 0xff); - snd_es1938_write(chip, ESS_CMD_DMACNTRELOADH, count >> 8); - - /* initialized and configure DAC */ - snd_es1938_write(chip, ESS_CMD_SETFORMAT, u ? 0x80 : 0x00); - snd_es1938_write(chip, ESS_CMD_SETFORMAT, u ? 0x51 : 0x71); - snd_es1938_write(chip, ESS_CMD_SETFORMAT2, - 0x90 | (mono ? 0x40 : 0x08) | - (is8 ? 0x00 : 0x04) | (u ? 0x00 : 0x20)); - - /* program DMA */ - snd_es1938_playback2_setdma(chip); - - return 0; -} - -static int snd_es1938_playback_prepare(struct snd_pcm_substream *substream) -{ - switch (substream->number) { - case 0: - return snd_es1938_playback1_prepare(substream); - case 1: - return snd_es1938_playback2_prepare(substream); - } - snd_BUG(); - return -EINVAL; -} - -/* during the incrementing of dma counters the DMA register reads sometimes - returns garbage. To ensure a valid hw pointer, the following checks which - should be very unlikely to fail are used: - - is the current DMA address in the valid DMA range ? - - is the sum of DMA address and DMA counter pointing to the last DMA byte ? - One can argue this could differ by one byte depending on which register is - updated first, so the implementation below allows for that. -*/ -static snd_pcm_uframes_t snd_es1938_capture_pointer(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - size_t ptr; -#if 0 - size_t old, new; - /* This stuff is *needed*, don't ask why - AB */ - old = inw(SLDM_REG(chip, DMACOUNT)); - while ((new = inw(SLDM_REG(chip, DMACOUNT))) != old) - old = new; - ptr = chip->dma1_size - 1 - new; -#else - size_t count; - unsigned int diff; - - ptr = inl(SLDM_REG(chip, DMAADDR)); - count = inw(SLDM_REG(chip, DMACOUNT)); - diff = chip->dma1_start + chip->dma1_size - ptr - count; - - if (diff > 3 || ptr < chip->dma1_start - || ptr >= chip->dma1_start+chip->dma1_size) - ptr = chip->last_capture_dmaaddr; /* bad, use last saved */ - else - chip->last_capture_dmaaddr = ptr; /* good, remember it */ - - ptr -= chip->dma1_start; -#endif - return ptr >> chip->dma1_shift; -} - -static snd_pcm_uframes_t snd_es1938_playback1_pointer(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - size_t ptr; -#if 1 - ptr = chip->dma2_size - inw(SLIO_REG(chip, AUDIO2DMACOUNT)); -#else - ptr = inl(SLIO_REG(chip, AUDIO2DMAADDR)) - chip->dma2_start; -#endif - return ptr >> chip->dma2_shift; -} - -static snd_pcm_uframes_t snd_es1938_playback2_pointer(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - size_t ptr; - size_t old, new; -#if 1 - /* This stuff is *needed*, don't ask why - AB */ - old = inw(SLDM_REG(chip, DMACOUNT)); - while ((new = inw(SLDM_REG(chip, DMACOUNT))) != old) - old = new; - ptr = chip->dma1_size - 1 - new; -#else - ptr = inl(SLDM_REG(chip, DMAADDR)) - chip->dma1_start; -#endif - return ptr >> chip->dma1_shift; -} - -static snd_pcm_uframes_t snd_es1938_playback_pointer(struct snd_pcm_substream *substream) -{ - switch (substream->number) { - case 0: - return snd_es1938_playback1_pointer(substream); - case 1: - return snd_es1938_playback2_pointer(substream); - } - snd_BUG(); - return -EINVAL; -} - -static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, - int channel, - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct es1938 *chip = snd_pcm_substream_chip(substream); - pos <<= chip->dma1_shift; - count <<= chip->dma1_shift; - if (snd_BUG_ON(pos + count > chip->dma1_size)) - return -EINVAL; - if (pos + count < chip->dma1_size) { - if (copy_to_user(dst, runtime->dma_area + pos + 1, count)) - return -EFAULT; - } else { - if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1)) - return -EFAULT; - if (put_user(runtime->dma_area[0], ((unsigned char __user *)dst) + count - 1)) - return -EFAULT; - } - return 0; -} - -/* - * buffer management - */ -static int snd_es1938_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) - -{ - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - return 0; -} - -static int snd_es1938_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -/* ---------------------------------------------------------------------- - * Audio1 Capture (ADC) - * ----------------------------------------------------------------------*/ -static struct snd_pcm_hardware snd_es1938_capture = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 6000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 0x8000, /* DMA controller screws on higher values */ - .period_bytes_min = 64, - .period_bytes_max = 0x8000, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 256, -}; - -/* ----------------------------------------------------------------------- - * Audio2 Playback (DAC) - * -----------------------------------------------------------------------*/ -static struct snd_pcm_hardware snd_es1938_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 6000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 0x8000, /* DMA controller screws on higher values */ - .period_bytes_min = 64, - .period_bytes_max = 0x8000, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 256, -}; - -static int snd_es1938_capture_open(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (chip->playback2_substream) - return -EAGAIN; - chip->capture_substream = substream; - runtime->hw = snd_es1938_capture; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, 0xff00); - return 0; -} - -static int snd_es1938_playback_open(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - switch (substream->number) { - case 0: - chip->playback1_substream = substream; - break; - case 1: - if (chip->capture_substream) - return -EAGAIN; - chip->playback2_substream = substream; - break; - default: - snd_BUG(); - return -EINVAL; - } - runtime->hw = snd_es1938_playback; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, 0xff00); - return 0; -} - -static int snd_es1938_capture_close(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - return 0; -} - -static int snd_es1938_playback_close(struct snd_pcm_substream *substream) -{ - struct es1938 *chip = snd_pcm_substream_chip(substream); - - switch (substream->number) { - case 0: - chip->playback1_substream = NULL; - break; - case 1: - chip->playback2_substream = NULL; - break; - default: - snd_BUG(); - return -EINVAL; - } - return 0; -} - -static struct snd_pcm_ops snd_es1938_playback_ops = { - .open = snd_es1938_playback_open, - .close = snd_es1938_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_es1938_pcm_hw_params, - .hw_free = snd_es1938_pcm_hw_free, - .prepare = snd_es1938_playback_prepare, - .trigger = snd_es1938_playback_trigger, - .pointer = snd_es1938_playback_pointer, -}; - -static struct snd_pcm_ops snd_es1938_capture_ops = { - .open = snd_es1938_capture_open, - .close = snd_es1938_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_es1938_pcm_hw_params, - .hw_free = snd_es1938_pcm_hw_free, - .prepare = snd_es1938_capture_prepare, - .trigger = snd_es1938_capture_trigger, - .pointer = snd_es1938_capture_pointer, - .copy = snd_es1938_capture_copy, -}; - -static int __devinit snd_es1938_new_pcm(struct es1938 *chip, int device) -{ - struct snd_pcm *pcm; - int err; - - if ((err = snd_pcm_new(chip->card, "es-1938-1946", device, 2, 1, &pcm)) < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1938_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1938_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, "ESS Solo-1"); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 64*1024); - - chip->pcm = pcm; - return 0; -} - -/* ------------------------------------------------------------------- - * - * *** Mixer part *** - */ - -static int snd_es1938_info_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[8] = { - "Mic", "Mic Master", "CD", "AOUT", - "Mic1", "Mix", "Line", "Master" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item > 7) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_es1938_get_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = snd_es1938_mixer_read(chip, 0x1c) & 0x07; - return 0; -} - -static int snd_es1938_put_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - unsigned char val = ucontrol->value.enumerated.item[0]; - - if (val > 7) - return -EINVAL; - return snd_es1938_mixer_bits(chip, 0x1c, 0x07, val) != val; -} - -#define snd_es1938_info_spatializer_enable snd_ctl_boolean_mono_info - -static int snd_es1938_get_spatializer_enable(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - unsigned char val = snd_es1938_mixer_read(chip, 0x50); - ucontrol->value.integer.value[0] = !!(val & 8); - return 0; -} - -static int snd_es1938_put_spatializer_enable(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - unsigned char oval, nval; - int change; - nval = ucontrol->value.integer.value[0] ? 0x0c : 0x04; - oval = snd_es1938_mixer_read(chip, 0x50) & 0x0c; - change = nval != oval; - if (change) { - snd_es1938_mixer_write(chip, 0x50, nval & ~0x04); - snd_es1938_mixer_write(chip, 0x50, nval); - } - return change; -} - -static int snd_es1938_info_hw_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 63; - return 0; -} - -static int snd_es1938_get_hw_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = snd_es1938_mixer_read(chip, 0x61) & 0x3f; - ucontrol->value.integer.value[1] = snd_es1938_mixer_read(chip, 0x63) & 0x3f; - return 0; -} - -#define snd_es1938_info_hw_switch snd_ctl_boolean_stereo_info - -static int snd_es1938_get_hw_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = !(snd_es1938_mixer_read(chip, 0x61) & 0x40); - ucontrol->value.integer.value[1] = !(snd_es1938_mixer_read(chip, 0x63) & 0x40); - return 0; -} - -static void snd_es1938_hwv_free(struct snd_kcontrol *kcontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - chip->master_volume = NULL; - chip->master_switch = NULL; - chip->hw_volume = NULL; - chip->hw_switch = NULL; -} - -static int snd_es1938_reg_bits(struct es1938 *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - if (reg < 0xa0) - return snd_es1938_mixer_bits(chip, reg, mask, val); - else - return snd_es1938_bits(chip, reg, mask, val); -} - -static int snd_es1938_reg_read(struct es1938 *chip, unsigned char reg) -{ - if (reg < 0xa0) - return snd_es1938_mixer_read(chip, reg); - else - return snd_es1938_read(chip, reg); -} - -#define ES1938_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,\ - .name = xname, .index = xindex, \ - .info = snd_es1938_info_single, \ - .get = snd_es1938_get_single, .put = snd_es1938_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = xtlv } } -#define ES1938_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es1938_info_single, \ - .get = snd_es1938_get_single, .put = snd_es1938_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_es1938_info_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es1938_get_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int val; - - val = snd_es1938_reg_read(chip, reg); - ucontrol->value.integer.value[0] = (val >> shift) & mask; - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_es1938_put_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned char val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - mask <<= shift; - val <<= shift; - return snd_es1938_reg_bits(chip, reg, mask, val) != val; -} - -#define ES1938_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,\ - .name = xname, .index = xindex, \ - .info = snd_es1938_info_double, \ - .get = snd_es1938_get_double, .put = snd_es1938_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = xtlv } } -#define ES1938_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es1938_info_double, \ - .get = snd_es1938_get_double, .put = snd_es1938_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -static int snd_es1938_info_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es1938_get_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - unsigned char left, right; - - left = snd_es1938_reg_read(chip, left_reg); - if (left_reg != right_reg) - right = snd_es1938_reg_read(chip, right_reg); - else - right = left; - ucontrol->value.integer.value[0] = (left >> shift_left) & mask; - ucontrol->value.integer.value[1] = (right >> shift_right) & mask; - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_es1938_put_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct es1938 *chip = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned char val1, val2, mask1, mask2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - mask1 = mask << shift_left; - mask2 = mask << shift_right; - if (left_reg != right_reg) { - change = 0; - if (snd_es1938_reg_bits(chip, left_reg, mask1, val1) != val1) - change = 1; - if (snd_es1938_reg_bits(chip, right_reg, mask2, val2) != val2) - change = 1; - } else { - change = (snd_es1938_reg_bits(chip, left_reg, mask1 | mask2, - val1 | val2) != (val1 | val2)); - } - return change; -} - -static unsigned int db_scale_master[] = { - TLV_DB_RANGE_HEAD(2), - 0, 54, TLV_DB_SCALE_ITEM(-3600, 50, 1), - 54, 63, TLV_DB_SCALE_ITEM(-900, 100, 0), -}; - -static unsigned int db_scale_audio1[] = { - TLV_DB_RANGE_HEAD(2), - 0, 8, TLV_DB_SCALE_ITEM(-3300, 300, 1), - 8, 15, TLV_DB_SCALE_ITEM(-900, 150, 0), -}; - -static unsigned int db_scale_audio2[] = { - TLV_DB_RANGE_HEAD(2), - 0, 8, TLV_DB_SCALE_ITEM(-3450, 300, 1), - 8, 15, TLV_DB_SCALE_ITEM(-1050, 150, 0), -}; - -static unsigned int db_scale_mic[] = { - TLV_DB_RANGE_HEAD(2), - 0, 8, TLV_DB_SCALE_ITEM(-2400, 300, 1), - 8, 15, TLV_DB_SCALE_ITEM(0, 150, 0), -}; - -static unsigned int db_scale_line[] = { - TLV_DB_RANGE_HEAD(2), - 0, 8, TLV_DB_SCALE_ITEM(-3150, 300, 1), - 8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0), -}; - -static const DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0); - -static struct snd_kcontrol_new snd_es1938_controls[] = { -ES1938_DOUBLE_TLV("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0, - db_scale_master), -ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Hardware Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_es1938_info_hw_volume, - .get = snd_es1938_get_hw_volume, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Hardware Master Playback Switch", - .info = snd_es1938_info_hw_switch, - .get = snd_es1938_get_hw_switch, - .tlv = { .p = db_scale_master }, -}, -ES1938_SINGLE("Hardware Volume Split", 0, 0x64, 7, 1, 0), -ES1938_DOUBLE_TLV("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0), -ES1938_DOUBLE_TLV("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0, - db_scale_mic), -ES1938_DOUBLE_TLV("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0, - db_scale_mic), -ES1938_DOUBLE_TLV("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0, - db_scale_capture), -ES1938_SINGLE("Beep Volume", 0, 0x3c, 0, 7, 0), -ES1938_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0), -ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_es1938_info_mux, - .get = snd_es1938_get_mux, - .put = snd_es1938_put_mux, -}, -ES1938_DOUBLE_TLV("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0, - db_scale_audio2), -ES1938_DOUBLE_TLV("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0, - db_scale_mic), -ES1938_DOUBLE_TLV("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0, - db_scale_mic), -ES1938_DOUBLE_TLV("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0, - db_scale_audio2), -ES1938_DOUBLE_TLV("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0, - db_scale_audio1), -ES1938_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "3D Control - Switch", - .info = snd_es1938_info_spatializer_enable, - .get = snd_es1938_get_spatializer_enable, - .put = snd_es1938_put_spatializer_enable, -}, -ES1938_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0) -}; - - -/* ---------------------------------------------------------------------------- */ -/* ---------------------------------------------------------------------------- */ - -/* - * initialize the chip - used by resume callback, too - */ -static void snd_es1938_chip_init(struct es1938 *chip) -{ - /* reset chip */ - snd_es1938_reset(chip); - - /* configure native mode */ - - /* enable bus master */ - pci_set_master(chip->pci); - - /* disable legacy audio */ - pci_write_config_word(chip->pci, SL_PCI_LEGACYCONTROL, 0x805f); - - /* set DDMA base */ - pci_write_config_word(chip->pci, SL_PCI_DDMACONTROL, chip->ddma_port | 1); - - /* set DMA/IRQ policy */ - pci_write_config_dword(chip->pci, SL_PCI_CONFIG, 0); - - /* enable Audio 1, Audio 2, MPU401 IRQ and HW volume IRQ*/ - outb(0xf0, SLIO_REG(chip, IRQCONTROL)); - - /* reset DMA */ - outb(0, SLDM_REG(chip, DMACLEAR)); -} - -#ifdef CONFIG_PM -/* - * PM support - */ - -static unsigned char saved_regs[SAVED_REG_SIZE+1] = { - 0x14, 0x1a, 0x1c, 0x3a, 0x3c, 0x3e, 0x36, 0x38, - 0x50, 0x52, 0x60, 0x61, 0x62, 0x63, 0x64, 0x68, - 0x69, 0x6a, 0x6b, 0x6d, 0x6e, 0x6f, 0x7c, 0x7d, - 0xa8, 0xb4, -}; - - -static int es1938_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct es1938 *chip = card->private_data; - unsigned char *s, *d; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - - /* save mixer-related registers */ - for (s = saved_regs, d = chip->saved_regs; *s; s++, d++) - *d = snd_es1938_reg_read(chip, *s); - - outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */ - if (chip->irq >= 0) { - free_irq(chip->irq, chip); - chip->irq = -1; - } - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int es1938_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct es1938 *chip = card->private_data; - unsigned char *s, *d; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "es1938: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - - if (request_irq(pci->irq, snd_es1938_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "es1938: unable to grab IRQ %d, " - "disabling device\n", pci->irq); - snd_card_disconnect(card); - return -EIO; - } - chip->irq = pci->irq; - snd_es1938_chip_init(chip); - - /* restore mixer-related registers */ - for (s = saved_regs, d = chip->saved_regs; *s; s++, d++) { - if (*s < 0xa0) - snd_es1938_mixer_write(chip, *s, *d); - else - snd_es1938_write(chip, *s, *d); - } - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -#ifdef SUPPORT_JOYSTICK -static int __devinit snd_es1938_create_gameport(struct es1938 *chip) -{ - struct gameport *gp; - - chip->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "es1938: cannot allocate memory for gameport\n"); - return -ENOMEM; - } - - gameport_set_name(gp, "ES1938"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); - gameport_set_dev_parent(gp, &chip->pci->dev); - gp->io = chip->game_port; - - gameport_register_port(gp); - - return 0; -} - -static void snd_es1938_free_gameport(struct es1938 *chip) -{ - if (chip->gameport) { - gameport_unregister_port(chip->gameport); - chip->gameport = NULL; - } -} -#else -static inline int snd_es1938_create_gameport(struct es1938 *chip) { return -ENOSYS; } -static inline void snd_es1938_free_gameport(struct es1938 *chip) { } -#endif /* SUPPORT_JOYSTICK */ - -static int snd_es1938_free(struct es1938 *chip) -{ - /* disable irqs */ - outb(0x00, SLIO_REG(chip, IRQCONTROL)); - if (chip->rmidi) - snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0); - - snd_es1938_free_gameport(chip); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_es1938_dev_free(struct snd_device *device) -{ - struct es1938 *chip = device->device_data; - return snd_es1938_free(chip); -} - -static int __devinit snd_es1938_create(struct snd_card *card, - struct pci_dev * pci, - struct es1938 ** rchip) -{ - struct es1938 *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_es1938_dev_free, - }; - - *rchip = NULL; - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { - snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->mixer_lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - if ((err = pci_request_regions(pci, "ESS Solo-1")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->io_port = pci_resource_start(pci, 0); - chip->sb_port = pci_resource_start(pci, 1); - chip->vc_port = pci_resource_start(pci, 2); - chip->mpu_port = pci_resource_start(pci, 3); - chip->game_port = pci_resource_start(pci, 4); - if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_es1938_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; -#ifdef ES1938_DDEBUG - snd_printk(KERN_DEBUG "create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n", - chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port); -#endif - - chip->ddma_port = chip->vc_port + 0x00; /* fix from Thomas Sailer */ - - snd_es1938_chip_init(chip); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_es1938_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - return 0; -} - -/* -------------------------------------------------------------------- - * Interrupt handler - * -------------------------------------------------------------------- */ -static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id) -{ - struct es1938 *chip = dev_id; - unsigned char status, audiostatus; - int handled = 0; - - status = inb(SLIO_REG(chip, IRQCONTROL)); -#if 0 - printk(KERN_DEBUG "Es1938debug - interrupt status: =0x%x\n", status); -#endif - - /* AUDIO 1 */ - if (status & 0x10) { -#if 0 - printk(KERN_DEBUG - "Es1938debug - AUDIO channel 1 interrupt\n"); - printk(KERN_DEBUG - "Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n", - inw(SLDM_REG(chip, DMACOUNT))); - printk(KERN_DEBUG - "Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n", - inl(SLDM_REG(chip, DMAADDR))); - printk(KERN_DEBUG - "Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n", - inl(SLDM_REG(chip, DMASTATUS))); -#endif - /* clear irq */ - handled = 1; - audiostatus = inb(SLSB_REG(chip, STATUS)); - if (chip->active & ADC1) - snd_pcm_period_elapsed(chip->capture_substream); - else if (chip->active & DAC1) - snd_pcm_period_elapsed(chip->playback2_substream); - } - - /* AUDIO 2 */ - if (status & 0x20) { -#if 0 - printk(KERN_DEBUG - "Es1938debug - AUDIO channel 2 interrupt\n"); - printk(KERN_DEBUG - "Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n", - inw(SLIO_REG(chip, AUDIO2DMACOUNT))); - printk(KERN_DEBUG - "Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n", - inl(SLIO_REG(chip, AUDIO2DMAADDR))); - -#endif - /* clear irq */ - handled = 1; - snd_es1938_mixer_bits(chip, ESSSB_IREG_AUDIO2CONTROL2, 0x80, 0); - if (chip->active & DAC2) - snd_pcm_period_elapsed(chip->playback1_substream); - } - - /* Hardware volume */ - if (status & 0x40) { - int split = snd_es1938_mixer_read(chip, 0x64) & 0x80; - handled = 1; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_switch->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_volume->id); - if (!split) { - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_switch->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); - } - /* ack interrupt */ - snd_es1938_mixer_write(chip, 0x66, 0x00); - } - - /* MPU401 */ - if (status & 0x80) { - // the following line is evil! It switches off MIDI interrupt handling after the first interrupt received. - // replacing the last 0 by 0x40 works for ESS-Solo1, but just doing nothing works as well! - // andreas@flying-snail.de - // snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0); /* ack? */ - if (chip->rmidi) { - handled = 1; - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - } - } - return IRQ_RETVAL(handled); -} - -#define ES1938_DMA_SIZE 64 - -static int __devinit snd_es1938_mixer(struct es1938 *chip) -{ - struct snd_card *card; - unsigned int idx; - int err; - - card = chip->card; - - strcpy(card->mixername, "ESS Solo-1"); - - for (idx = 0; idx < ARRAY_SIZE(snd_es1938_controls); idx++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(&snd_es1938_controls[idx], chip); - switch (idx) { - case 0: - chip->master_volume = kctl; - kctl->private_free = snd_es1938_hwv_free; - break; - case 1: - chip->master_switch = kctl; - kctl->private_free = snd_es1938_hwv_free; - break; - case 2: - chip->hw_volume = kctl; - kctl->private_free = snd_es1938_hwv_free; - break; - case 3: - chip->hw_switch = kctl; - kctl->private_free = snd_es1938_hwv_free; - break; - } - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - } - return 0; -} - - -static int __devinit snd_es1938_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct es1938 *chip; - struct snd_opl3 *opl3; - int idx, err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - for (idx = 0; idx < 5; idx++) { - if (pci_resource_start(pci, idx) == 0 || - !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { - snd_card_free(card); - return -ENODEV; - } - } - if ((err = snd_es1938_create(card, pci, &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - strcpy(card->driver, "ES1938"); - strcpy(card->shortname, "ESS ES1938 (Solo-1)"); - sprintf(card->longname, "%s rev %i, irq %i", - card->shortname, - chip->revision, - chip->irq); - - if ((err = snd_es1938_new_pcm(chip, 0)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_es1938_mixer(chip)) < 0) { - snd_card_free(card); - return err; - } - if (snd_opl3_create(card, - SLSB_REG(chip, FMLOWADDR), - SLSB_REG(chip, FMHIGHADDR), - OPL3_HW_OPL3, 1, &opl3) < 0) { - printk(KERN_ERR "es1938: OPL3 not detected at 0x%lx\n", - SLSB_REG(chip, FMLOWADDR)); - } else { - if ((err = snd_opl3_timer_new(opl3, 0, 1)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - } - if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - chip->mpu_port, - MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi) < 0) { - printk(KERN_ERR "es1938: unable to initialize MPU-401\n"); - } else { - // this line is vital for MIDI interrupt handling on ess-solo1 - // andreas@flying-snail.de - snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0x40); - } - - snd_es1938_create_gameport(chip); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_es1938_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_es1938_ids, - .probe = snd_es1938_probe, - .remove = __devexit_p(snd_es1938_remove), -#ifdef CONFIG_PM - .suspend = es1938_suspend, - .resume = es1938_resume, -#endif -}; - -static int __init alsa_card_es1938_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_es1938_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_es1938_init) -module_exit(alsa_card_es1938_exit) diff --git a/ANDROID_3.4.5/sound/pci/es1968.c b/ANDROID_3.4.5/sound/pci/es1968.c deleted file mode 100644 index a8faae1c..00000000 --- a/ANDROID_3.4.5/sound/pci/es1968.c +++ /dev/null @@ -1,2923 +0,0 @@ -/* - * Driver for ESS Maestro 1/2/2E Sound Card (started 21.8.99) - * Copyright (c) by Matze Braun . - * Takashi Iwai - * - * Most of the driver code comes from Zach Brown(zab@redhat.com) - * Alan Cox OSS Driver - * Rewritted from card-es1938.c source. - * - * TODO: - * Perhaps Synth - * - * 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 - * - * - * Notes from Zach Brown about the driver code - * - * Hardware Description - * - * A working Maestro setup contains the Maestro chip wired to a - * codec or 2. In the Maestro we have the APUs, the ASSP, and the - * Wavecache. The APUs can be though of as virtual audio routing - * channels. They can take data from a number of sources and perform - * basic encodings of the data. The wavecache is a storehouse for - * PCM data. Typically it deals with PCI and interracts with the - * APUs. The ASSP is a wacky DSP like device that ESS is loth - * to release docs on. Thankfully it isn't required on the Maestro - * until you start doing insane things like FM emulation and surround - * encoding. The codecs are almost always AC-97 compliant codecs, - * but it appears that early Maestros may have had PT101 (an ESS - * part?) wired to them. The only real difference in the Maestro - * families is external goop like docking capability, memory for - * the ASSP, and initialization differences. - * - * Driver Operation - * - * We only drive the APU/Wavecache as typical DACs and drive the - * mixers in the codecs. There are 64 APUs. We assign 6 to each - * /dev/dsp? device. 2 channels for output, and 4 channels for - * input. - * - * Each APU can do a number of things, but we only really use - * 3 basic functions. For playback we use them to convert PCM - * data fetched over PCI by the wavecahche into analog data that - * is handed to the codec. One APU for mono, and a pair for stereo. - * When in stereo, the combination of smarts in the APU and Wavecache - * decide which wavecache gets the left or right channel. - * - * For record we still use the old overly mono system. For each in - * coming channel the data comes in from the codec, through a 'input' - * APU, through another rate converter APU, and then into memory via - * the wavecache and PCI. If its stereo, we mash it back into LRLR in - * software. The pass between the 2 APUs is supposedly what requires us - * to have a 512 byte buffer sitting around in wavecache/memory. - * - * The wavecache makes our life even more fun. First off, it can - * only address the first 28 bits of PCI address space, making it - * useless on quite a few architectures. Secondly, its insane. - * It claims to fetch from 4 regions of PCI space, each 4 meg in length. - * But that doesn't really work. You can only use 1 region. So all our - * allocations have to be in 4meg of each other. Booo. Hiss. - * So we have a module parameter, dsps_order, that is the order of - * the number of dsps to provide. All their buffer space is allocated - * on open time. The sonicvibes OSS routines we inherited really want - * power of 2 buffers, so we have all those next to each other, then - * 512 byte regions for the recording wavecaches. This ends up - * wasting quite a bit of memory. The only fixes I can see would be - * getting a kernel allocator that could work in zones, or figuring out - * just how to coerce the WP into doing what we want. - * - * The indirection of the various registers means we have to spinlock - * nearly all register accesses. We have the main register indirection - * like the wave cache, maestro registers, etc. Then we have beasts - * like the APU interface that is indirect registers gotten at through - * the main maestro indirection. Ouch. We spinlock around the actual - * ports on a per card basis. This means spinlock activity at each IO - * operation, but the only IO operation clusters are in non critical - * paths and it makes the code far easier to follow. Interrupts are - * blocked while holding the locks because the int handler has to - * get at some of them :(. The mixer interface doesn't, however. - * We also have an OSS state lock that is thrown around in a few - * places. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef CONFIG_SND_ES1968_RADIO -#include -#endif - -#define CARD_NAME "ESS Maestro1/2" -#define DRIVER_NAME "ES1968" - -MODULE_DESCRIPTION("ESS Maestro"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESS,Maestro 2e}," - "{ESS,Maestro 2}," - "{ESS,Maestro 1}," - "{TerraTec,DMX}}"); - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 1-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 }; -static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 }; -static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 }; -static int clock[SNDRV_CARDS]; -static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; -static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; -#ifdef SUPPORT_JOYSTICK -static bool joystick[SNDRV_CARDS]; -#endif -static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); -module_param_array(total_bufsize, int, NULL, 0444); -MODULE_PARM_DESC(total_bufsize, "Total buffer size in kB."); -module_param_array(pcm_substreams_p, int, NULL, 0444); -MODULE_PARM_DESC(pcm_substreams_p, "PCM Playback substreams for " CARD_NAME " soundcard."); -module_param_array(pcm_substreams_c, int, NULL, 0444); -MODULE_PARM_DESC(pcm_substreams_c, "PCM Capture substreams for " CARD_NAME " soundcard."); -module_param_array(clock, int, NULL, 0444); -MODULE_PARM_DESC(clock, "Clock on " CARD_NAME " soundcard. (0 = auto-detect)"); -module_param_array(use_pm, int, NULL, 0444); -MODULE_PARM_DESC(use_pm, "Toggle power-management. (0 = off, 1 = on, 2 = auto)"); -module_param_array(enable_mpu, int, NULL, 0444); -MODULE_PARM_DESC(enable_mpu, "Enable MPU401. (0 = off, 1 = on, 2 = auto)"); -#ifdef SUPPORT_JOYSTICK -module_param_array(joystick, bool, NULL, 0444); -MODULE_PARM_DESC(joystick, "Enable joystick."); -#endif -module_param_array(radio_nr, int, NULL, 0444); -MODULE_PARM_DESC(radio_nr, "Radio device numbers"); - - - -#define NR_APUS 64 -#define NR_APU_REGS 16 - -/* NEC Versas ? */ -#define NEC_VERSA_SUBID1 0x80581033 -#define NEC_VERSA_SUBID2 0x803c1033 - -/* Mode Flags */ -#define ESS_FMT_STEREO 0x01 -#define ESS_FMT_16BIT 0x02 - -#define DAC_RUNNING 1 -#define ADC_RUNNING 2 - -/* Values for the ESM_LEGACY_AUDIO_CONTROL */ - -#define ESS_DISABLE_AUDIO 0x8000 -#define ESS_ENABLE_SERIAL_IRQ 0x4000 -#define IO_ADRESS_ALIAS 0x0020 -#define MPU401_IRQ_ENABLE 0x0010 -#define MPU401_IO_ENABLE 0x0008 -#define GAME_IO_ENABLE 0x0004 -#define FM_IO_ENABLE 0x0002 -#define SB_IO_ENABLE 0x0001 - -/* Values for the ESM_CONFIG_A */ - -#define PIC_SNOOP1 0x4000 -#define PIC_SNOOP2 0x2000 -#define SAFEGUARD 0x0800 -#define DMA_CLEAR 0x0700 -#define DMA_DDMA 0x0000 -#define DMA_TDMA 0x0100 -#define DMA_PCPCI 0x0200 -#define POST_WRITE 0x0080 -#define PCI_TIMING 0x0040 -#define SWAP_LR 0x0020 -#define SUBTR_DECODE 0x0002 - -/* Values for the ESM_CONFIG_B */ - -#define SPDIF_CONFB 0x0100 -#define HWV_CONFB 0x0080 -#define DEBOUNCE 0x0040 -#define GPIO_CONFB 0x0020 -#define CHI_CONFB 0x0010 -#define IDMA_CONFB 0x0008 /*undoc */ -#define MIDI_FIX 0x0004 /*undoc */ -#define IRQ_TO_ISA 0x0001 /*undoc */ - -/* Values for Ring Bus Control B */ -#define RINGB_2CODEC_ID_MASK 0x0003 -#define RINGB_DIS_VALIDATION 0x0008 -#define RINGB_EN_SPDIF 0x0010 -#define RINGB_EN_2CODEC 0x0020 -#define RINGB_SING_BIT_DUAL 0x0040 - -/* ****Port Addresses**** */ - -/* Write & Read */ -#define ESM_INDEX 0x02 -#define ESM_DATA 0x00 - -/* AC97 + RingBus */ -#define ESM_AC97_INDEX 0x30 -#define ESM_AC97_DATA 0x32 -#define ESM_RING_BUS_DEST 0x34 -#define ESM_RING_BUS_CONTR_A 0x36 -#define ESM_RING_BUS_CONTR_B 0x38 -#define ESM_RING_BUS_SDO 0x3A - -/* WaveCache*/ -#define WC_INDEX 0x10 -#define WC_DATA 0x12 -#define WC_CONTROL 0x14 - -/* ASSP*/ -#define ASSP_INDEX 0x80 -#define ASSP_MEMORY 0x82 -#define ASSP_DATA 0x84 -#define ASSP_CONTROL_A 0xA2 -#define ASSP_CONTROL_B 0xA4 -#define ASSP_CONTROL_C 0xA6 -#define ASSP_HOSTW_INDEX 0xA8 -#define ASSP_HOSTW_DATA 0xAA -#define ASSP_HOSTW_IRQ 0xAC -/* Midi */ -#define ESM_MPU401_PORT 0x98 -/* Others */ -#define ESM_PORT_HOST_IRQ 0x18 - -#define IDR0_DATA_PORT 0x00 -#define IDR1_CRAM_POINTER 0x01 -#define IDR2_CRAM_DATA 0x02 -#define IDR3_WAVE_DATA 0x03 -#define IDR4_WAVE_PTR_LOW 0x04 -#define IDR5_WAVE_PTR_HI 0x05 -#define IDR6_TIMER_CTRL 0x06 -#define IDR7_WAVE_ROMRAM 0x07 - -#define WRITEABLE_MAP 0xEFFFFF -#define READABLE_MAP 0x64003F - -/* PCI Register */ - -#define ESM_LEGACY_AUDIO_CONTROL 0x40 -#define ESM_ACPI_COMMAND 0x54 -#define ESM_CONFIG_A 0x50 -#define ESM_CONFIG_B 0x52 -#define ESM_DDMA 0x60 - -/* Bob Bits */ -#define ESM_BOB_ENABLE 0x0001 -#define ESM_BOB_START 0x0001 - -/* Host IRQ Control Bits */ -#define ESM_RESET_MAESTRO 0x8000 -#define ESM_RESET_DIRECTSOUND 0x4000 -#define ESM_HIRQ_ClkRun 0x0100 -#define ESM_HIRQ_HW_VOLUME 0x0040 -#define ESM_HIRQ_HARPO 0x0030 /* What's that? */ -#define ESM_HIRQ_ASSP 0x0010 -#define ESM_HIRQ_DSIE 0x0004 -#define ESM_HIRQ_MPU401 0x0002 -#define ESM_HIRQ_SB 0x0001 - -/* Host IRQ Status Bits */ -#define ESM_MPU401_IRQ 0x02 -#define ESM_SB_IRQ 0x01 -#define ESM_SOUND_IRQ 0x04 -#define ESM_ASSP_IRQ 0x10 -#define ESM_HWVOL_IRQ 0x40 - -#define ESS_SYSCLK 50000000 -#define ESM_BOB_FREQ 200 -#define ESM_BOB_FREQ_MAX 800 - -#define ESM_FREQ_ESM1 (49152000L / 1024L) /* default rate 48000 */ -#define ESM_FREQ_ESM2 (50000000L / 1024L) - -/* APU Modes: reg 0x00, bit 4-7 */ -#define ESM_APU_MODE_SHIFT 4 -#define ESM_APU_MODE_MASK (0xf << 4) -#define ESM_APU_OFF 0x00 -#define ESM_APU_16BITLINEAR 0x01 /* 16-Bit Linear Sample Player */ -#define ESM_APU_16BITSTEREO 0x02 /* 16-Bit Stereo Sample Player */ -#define ESM_APU_8BITLINEAR 0x03 /* 8-Bit Linear Sample Player */ -#define ESM_APU_8BITSTEREO 0x04 /* 8-Bit Stereo Sample Player */ -#define ESM_APU_8BITDIFF 0x05 /* 8-Bit Differential Sample Playrer */ -#define ESM_APU_DIGITALDELAY 0x06 /* Digital Delay Line */ -#define ESM_APU_DUALTAP 0x07 /* Dual Tap Reader */ -#define ESM_APU_CORRELATOR 0x08 /* Correlator */ -#define ESM_APU_INPUTMIXER 0x09 /* Input Mixer */ -#define ESM_APU_WAVETABLE 0x0A /* Wave Table Mode */ -#define ESM_APU_SRCONVERTOR 0x0B /* Sample Rate Convertor */ -#define ESM_APU_16BITPINGPONG 0x0C /* 16-Bit Ping-Pong Sample Player */ -#define ESM_APU_RESERVED1 0x0D /* Reserved 1 */ -#define ESM_APU_RESERVED2 0x0E /* Reserved 2 */ -#define ESM_APU_RESERVED3 0x0F /* Reserved 3 */ - -/* reg 0x00 */ -#define ESM_APU_FILTER_Q_SHIFT 0 -#define ESM_APU_FILTER_Q_MASK (3 << 0) -/* APU Filtey Q Control */ -#define ESM_APU_FILTER_LESSQ 0x00 -#define ESM_APU_FILTER_MOREQ 0x03 - -#define ESM_APU_FILTER_TYPE_SHIFT 2 -#define ESM_APU_FILTER_TYPE_MASK (3 << 2) -#define ESM_APU_ENV_TYPE_SHIFT 8 -#define ESM_APU_ENV_TYPE_MASK (3 << 8) -#define ESM_APU_ENV_STATE_SHIFT 10 -#define ESM_APU_ENV_STATE_MASK (3 << 10) -#define ESM_APU_END_CURVE (1 << 12) -#define ESM_APU_INT_ON_LOOP (1 << 13) -#define ESM_APU_DMA_ENABLE (1 << 14) - -/* reg 0x02 */ -#define ESM_APU_SUBMIX_GROUP_SHIRT 0 -#define ESM_APU_SUBMIX_GROUP_MASK (7 << 0) -#define ESM_APU_SUBMIX_MODE (1 << 3) -#define ESM_APU_6dB (1 << 4) -#define ESM_APU_DUAL_EFFECT (1 << 5) -#define ESM_APU_EFFECT_CHANNELS_SHIFT 6 -#define ESM_APU_EFFECT_CHANNELS_MASK (3 << 6) - -/* reg 0x03 */ -#define ESM_APU_STEP_SIZE_MASK 0x0fff - -/* reg 0x04 */ -#define ESM_APU_PHASE_SHIFT 0 -#define ESM_APU_PHASE_MASK (0xff << 0) -#define ESM_APU_WAVE64K_PAGE_SHIFT 8 /* most 8bit of wave start offset */ -#define ESM_APU_WAVE64K_PAGE_MASK (0xff << 8) - -/* reg 0x05 - wave start offset */ -/* reg 0x06 - wave end offset */ -/* reg 0x07 - wave loop length */ - -/* reg 0x08 */ -#define ESM_APU_EFFECT_GAIN_SHIFT 0 -#define ESM_APU_EFFECT_GAIN_MASK (0xff << 0) -#define ESM_APU_TREMOLO_DEPTH_SHIFT 8 -#define ESM_APU_TREMOLO_DEPTH_MASK (0xf << 8) -#define ESM_APU_TREMOLO_RATE_SHIFT 12 -#define ESM_APU_TREMOLO_RATE_MASK (0xf << 12) - -/* reg 0x09 */ -/* bit 0-7 amplitude dest? */ -#define ESM_APU_AMPLITUDE_NOW_SHIFT 8 -#define ESM_APU_AMPLITUDE_NOW_MASK (0xff << 8) - -/* reg 0x0a */ -#define ESM_APU_POLAR_PAN_SHIFT 0 -#define ESM_APU_POLAR_PAN_MASK (0x3f << 0) -/* Polar Pan Control */ -#define ESM_APU_PAN_CENTER_CIRCLE 0x00 -#define ESM_APU_PAN_MIDDLE_RADIUS 0x01 -#define ESM_APU_PAN_OUTSIDE_RADIUS 0x02 - -#define ESM_APU_FILTER_TUNING_SHIFT 8 -#define ESM_APU_FILTER_TUNING_MASK (0xff << 8) - -/* reg 0x0b */ -#define ESM_APU_DATA_SRC_A_SHIFT 0 -#define ESM_APU_DATA_SRC_A_MASK (0x7f << 0) -#define ESM_APU_INV_POL_A (1 << 7) -#define ESM_APU_DATA_SRC_B_SHIFT 8 -#define ESM_APU_DATA_SRC_B_MASK (0x7f << 8) -#define ESM_APU_INV_POL_B (1 << 15) - -#define ESM_APU_VIBRATO_RATE_SHIFT 0 -#define ESM_APU_VIBRATO_RATE_MASK (0xf << 0) -#define ESM_APU_VIBRATO_DEPTH_SHIFT 4 -#define ESM_APU_VIBRATO_DEPTH_MASK (0xf << 4) -#define ESM_APU_VIBRATO_PHASE_SHIFT 8 -#define ESM_APU_VIBRATO_PHASE_MASK (0xff << 8) - -/* reg 0x0c */ -#define ESM_APU_RADIUS_SELECT (1 << 6) - -/* APU Filter Control */ -#define ESM_APU_FILTER_2POLE_LOPASS 0x00 -#define ESM_APU_FILTER_2POLE_BANDPASS 0x01 -#define ESM_APU_FILTER_2POLE_HIPASS 0x02 -#define ESM_APU_FILTER_1POLE_LOPASS 0x03 -#define ESM_APU_FILTER_1POLE_HIPASS 0x04 -#define ESM_APU_FILTER_OFF 0x05 - -/* APU ATFP Type */ -#define ESM_APU_ATFP_AMPLITUDE 0x00 -#define ESM_APU_ATFP_TREMELO 0x01 -#define ESM_APU_ATFP_FILTER 0x02 -#define ESM_APU_ATFP_PAN 0x03 - -/* APU ATFP Flags */ -#define ESM_APU_ATFP_FLG_OFF 0x00 -#define ESM_APU_ATFP_FLG_WAIT 0x01 -#define ESM_APU_ATFP_FLG_DONE 0x02 -#define ESM_APU_ATFP_FLG_INPROCESS 0x03 - - -/* capture mixing buffer size */ -#define ESM_MEM_ALIGN 0x1000 -#define ESM_MIXBUF_SIZE 0x400 - -#define ESM_MODE_PLAY 0 -#define ESM_MODE_CAPTURE 1 - - -/* APU use in the driver */ -enum snd_enum_apu_type { - ESM_APU_PCM_PLAY, - ESM_APU_PCM_CAPTURE, - ESM_APU_PCM_RATECONV, - ESM_APU_FREE -}; - -/* chip type */ -enum { - TYPE_MAESTRO, TYPE_MAESTRO2, TYPE_MAESTRO2E -}; - -/* DMA Hack! */ -struct esm_memory { - struct snd_dma_buffer buf; - int empty; /* status */ - struct list_head list; -}; - -/* Playback Channel */ -struct esschan { - int running; - - u8 apu[4]; - u8 apu_mode[4]; - - /* playback/capture pcm buffer */ - struct esm_memory *memory; - /* capture mixer buffer */ - struct esm_memory *mixbuf; - - unsigned int hwptr; /* current hw pointer in bytes */ - unsigned int count; /* sample counter in bytes */ - unsigned int dma_size; /* total buffer size in bytes */ - unsigned int frag_size; /* period size in bytes */ - unsigned int wav_shift; - u16 base[4]; /* offset for ptr */ - - /* stereo/16bit flag */ - unsigned char fmt; - int mode; /* playback / capture */ - - int bob_freq; /* required timer frequency */ - - struct snd_pcm_substream *substream; - - /* linked list */ - struct list_head list; - -#ifdef CONFIG_PM - u16 wc_map[4]; -#endif -}; - -struct es1968 { - /* Module Config */ - int total_bufsize; /* in bytes */ - - int playback_streams, capture_streams; - - unsigned int clock; /* clock */ - /* for clock measurement */ - unsigned int in_measurement: 1; - unsigned int measure_apu; - unsigned int measure_lastpos; - unsigned int measure_count; - - /* buffer */ - struct snd_dma_buffer dma; - - /* Resources... */ - int irq; - unsigned long io_port; - int type; - struct pci_dev *pci; - struct snd_card *card; - struct snd_pcm *pcm; - int do_pm; /* power-management enabled */ - - /* DMA memory block */ - struct list_head buf_list; - - /* ALSA Stuff */ - struct snd_ac97 *ac97; - struct snd_rawmidi *rmidi; - - spinlock_t reg_lock; - unsigned int in_suspend; - - /* Maestro Stuff */ - u16 maestro_map[32]; - int bobclient; /* active timer instancs */ - int bob_freq; /* timer frequency */ - struct mutex memory_mutex; /* memory lock */ - - /* APU states */ - unsigned char apu[NR_APUS]; - - /* active substreams */ - struct list_head substream_list; - spinlock_t substream_lock; - -#ifdef CONFIG_PM - u16 apu_map[NR_APUS][NR_APU_REGS]; -#endif - -#ifdef SUPPORT_JOYSTICK - struct gameport *gameport; -#endif - -#ifdef CONFIG_SND_ES1968_INPUT - struct input_dev *input_dev; - char phys[64]; /* physical device path */ -#else - struct snd_kcontrol *master_switch; /* for h/w volume control */ - struct snd_kcontrol *master_volume; -#endif - struct work_struct hwvol_work; - -#ifdef CONFIG_SND_ES1968_RADIO - struct v4l2_device v4l2_dev; - struct snd_tea575x tea; -#endif -}; - -static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); - -static DEFINE_PCI_DEVICE_TABLE(snd_es1968_ids) = { - /* Maestro 1 */ - { 0x1285, 0x0100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO }, - /* Maestro 2 */ - { 0x125d, 0x1968, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO2 }, - /* Maestro 2E */ - { 0x125d, 0x1978, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO2E }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_es1968_ids); - -/* ********************* - * Low Level Funcs! * - *********************/ - -/* no spinlock */ -static void __maestro_write(struct es1968 *chip, u16 reg, u16 data) -{ - outw(reg, chip->io_port + ESM_INDEX); - outw(data, chip->io_port + ESM_DATA); - chip->maestro_map[reg] = data; -} - -static inline void maestro_write(struct es1968 *chip, u16 reg, u16 data) -{ - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - __maestro_write(chip, reg, data); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -/* no spinlock */ -static u16 __maestro_read(struct es1968 *chip, u16 reg) -{ - if (READABLE_MAP & (1 << reg)) { - outw(reg, chip->io_port + ESM_INDEX); - chip->maestro_map[reg] = inw(chip->io_port + ESM_DATA); - } - return chip->maestro_map[reg]; -} - -static inline u16 maestro_read(struct es1968 *chip, u16 reg) -{ - unsigned long flags; - u16 result; - spin_lock_irqsave(&chip->reg_lock, flags); - result = __maestro_read(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return result; -} - -/* Wait for the codec bus to be free */ -static int snd_es1968_ac97_wait(struct es1968 *chip) -{ - int timeout = 100000; - - while (timeout-- > 0) { - if (!(inb(chip->io_port + ESM_AC97_INDEX) & 1)) - return 0; - cond_resched(); - } - snd_printd("es1968: ac97 timeout\n"); - return 1; /* timeout */ -} - -static int snd_es1968_ac97_wait_poll(struct es1968 *chip) -{ - int timeout = 100000; - - while (timeout-- > 0) { - if (!(inb(chip->io_port + ESM_AC97_INDEX) & 1)) - return 0; - } - snd_printd("es1968: ac97 timeout\n"); - return 1; /* timeout */ -} - -static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) -{ - struct es1968 *chip = ac97->private_data; - - snd_es1968_ac97_wait(chip); - - /* Write the bus */ - outw(val, chip->io_port + ESM_AC97_DATA); - /*msleep(1);*/ - outb(reg, chip->io_port + ESM_AC97_INDEX); - /*msleep(1);*/ -} - -static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - u16 data = 0; - struct es1968 *chip = ac97->private_data; - - snd_es1968_ac97_wait(chip); - - outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX); - /*msleep(1);*/ - - if (!snd_es1968_ac97_wait_poll(chip)) { - data = inw(chip->io_port + ESM_AC97_DATA); - /*msleep(1);*/ - } - - return data; -} - -/* no spinlock */ -static void apu_index_set(struct es1968 *chip, u16 index) -{ - int i; - __maestro_write(chip, IDR1_CRAM_POINTER, index); - for (i = 0; i < 1000; i++) - if (__maestro_read(chip, IDR1_CRAM_POINTER) == index) - return; - snd_printd("es1968: APU register select failed. (Timeout)\n"); -} - -/* no spinlock */ -static void apu_data_set(struct es1968 *chip, u16 data) -{ - int i; - for (i = 0; i < 1000; i++) { - if (__maestro_read(chip, IDR0_DATA_PORT) == data) - return; - __maestro_write(chip, IDR0_DATA_PORT, data); - } - snd_printd("es1968: APU register set probably failed (Timeout)!\n"); -} - -/* no spinlock */ -static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) -{ - if (snd_BUG_ON(channel >= NR_APUS)) - return; -#ifdef CONFIG_PM - chip->apu_map[channel][reg] = data; -#endif - reg |= (channel << 4); - apu_index_set(chip, reg); - apu_data_set(chip, data); -} - -static void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data) -{ - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - __apu_set_register(chip, channel, reg, data); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg) -{ - if (snd_BUG_ON(channel >= NR_APUS)) - return 0; - reg |= (channel << 4); - apu_index_set(chip, reg); - return __maestro_read(chip, IDR0_DATA_PORT); -} - -static u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg) -{ - unsigned long flags; - u16 v; - spin_lock_irqsave(&chip->reg_lock, flags); - v = __apu_get_register(chip, channel, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return v; -} - -#if 0 /* ASSP is not supported */ - -static void assp_set_register(struct es1968 *chip, u32 reg, u32 value) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - outl(reg, chip->io_port + ASSP_INDEX); - outl(value, chip->io_port + ASSP_DATA); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static u32 assp_get_register(struct es1968 *chip, u32 reg) -{ - unsigned long flags; - u32 value; - - spin_lock_irqsave(&chip->reg_lock, flags); - outl(reg, chip->io_port + ASSP_INDEX); - value = inl(chip->io_port + ASSP_DATA); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return value; -} - -#endif - -static void wave_set_register(struct es1968 *chip, u16 reg, u16 value) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - outw(reg, chip->io_port + WC_INDEX); - outw(value, chip->io_port + WC_DATA); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static u16 wave_get_register(struct es1968 *chip, u16 reg) -{ - unsigned long flags; - u16 value; - - spin_lock_irqsave(&chip->reg_lock, flags); - outw(reg, chip->io_port + WC_INDEX); - value = inw(chip->io_port + WC_DATA); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return value; -} - -/* ******************* - * Bob the Timer! * - *******************/ - -static void snd_es1968_bob_stop(struct es1968 *chip) -{ - u16 reg; - - reg = __maestro_read(chip, 0x11); - reg &= ~ESM_BOB_ENABLE; - __maestro_write(chip, 0x11, reg); - reg = __maestro_read(chip, 0x17); - reg &= ~ESM_BOB_START; - __maestro_write(chip, 0x17, reg); -} - -static void snd_es1968_bob_start(struct es1968 *chip) -{ - int prescale; - int divide; - - /* compute ideal interrupt frequency for buffer size & play rate */ - /* first, find best prescaler value to match freq */ - for (prescale = 5; prescale < 12; prescale++) - if (chip->bob_freq > (ESS_SYSCLK >> (prescale + 9))) - break; - - /* next, back off prescaler whilst getting divider into optimum range */ - divide = 1; - while ((prescale > 5) && (divide < 32)) { - prescale--; - divide <<= 1; - } - divide >>= 1; - - /* now fine-tune the divider for best match */ - for (; divide < 31; divide++) - if (chip->bob_freq > - ((ESS_SYSCLK >> (prescale + 9)) / (divide + 1))) break; - - /* divide = 0 is illegal, but don't let prescale = 4! */ - if (divide == 0) { - divide++; - if (prescale > 5) - prescale--; - } else if (divide > 1) - divide--; - - __maestro_write(chip, 6, 0x9000 | (prescale << 5) | divide); /* set reg */ - - /* Now set IDR 11/17 */ - __maestro_write(chip, 0x11, __maestro_read(chip, 0x11) | 1); - __maestro_write(chip, 0x17, __maestro_read(chip, 0x17) | 1); -} - -/* call with substream spinlock */ -static void snd_es1968_bob_inc(struct es1968 *chip, int freq) -{ - chip->bobclient++; - if (chip->bobclient == 1) { - chip->bob_freq = freq; - snd_es1968_bob_start(chip); - } else if (chip->bob_freq < freq) { - snd_es1968_bob_stop(chip); - chip->bob_freq = freq; - snd_es1968_bob_start(chip); - } -} - -/* call with substream spinlock */ -static void snd_es1968_bob_dec(struct es1968 *chip) -{ - chip->bobclient--; - if (chip->bobclient <= 0) - snd_es1968_bob_stop(chip); - else if (chip->bob_freq > ESM_BOB_FREQ) { - /* check reduction of timer frequency */ - int max_freq = ESM_BOB_FREQ; - struct esschan *es; - list_for_each_entry(es, &chip->substream_list, list) { - if (max_freq < es->bob_freq) - max_freq = es->bob_freq; - } - if (max_freq != chip->bob_freq) { - snd_es1968_bob_stop(chip); - chip->bob_freq = max_freq; - snd_es1968_bob_start(chip); - } - } -} - -static int -snd_es1968_calc_bob_rate(struct es1968 *chip, struct esschan *es, - struct snd_pcm_runtime *runtime) -{ - /* we acquire 4 interrupts per period for precise control.. */ - int freq = runtime->rate * 4; - if (es->fmt & ESS_FMT_STEREO) - freq <<= 1; - if (es->fmt & ESS_FMT_16BIT) - freq <<= 1; - freq /= es->frag_size; - if (freq < ESM_BOB_FREQ) - freq = ESM_BOB_FREQ; - else if (freq > ESM_BOB_FREQ_MAX) - freq = ESM_BOB_FREQ_MAX; - return freq; -} - - -/************* - * PCM Part * - *************/ - -static u32 snd_es1968_compute_rate(struct es1968 *chip, u32 freq) -{ - u32 rate = (freq << 16) / chip->clock; -#if 0 /* XXX: do we need this? */ - if (rate > 0x10000) - rate = 0x10000; -#endif - return rate; -} - -/* get current pointer */ -static inline unsigned int -snd_es1968_get_dma_ptr(struct es1968 *chip, struct esschan *es) -{ - unsigned int offset; - - offset = apu_get_register(chip, es->apu[0], 5); - - offset -= es->base[0]; - - return (offset & 0xFFFE); /* hardware is in words */ -} - -static void snd_es1968_apu_set_freq(struct es1968 *chip, int apu, int freq) -{ - apu_set_register(chip, apu, 2, - (apu_get_register(chip, apu, 2) & 0x00FF) | - ((freq & 0xff) << 8) | 0x10); - apu_set_register(chip, apu, 3, freq >> 8); -} - -/* spin lock held */ -static inline void snd_es1968_trigger_apu(struct es1968 *esm, int apu, int mode) -{ - /* set the APU mode */ - __apu_set_register(esm, apu, 0, - (__apu_get_register(esm, apu, 0) & 0xff0f) | - (mode << 4)); -} - -static void snd_es1968_pcm_start(struct es1968 *chip, struct esschan *es) -{ - spin_lock(&chip->reg_lock); - __apu_set_register(chip, es->apu[0], 5, es->base[0]); - snd_es1968_trigger_apu(chip, es->apu[0], es->apu_mode[0]); - if (es->mode == ESM_MODE_CAPTURE) { - __apu_set_register(chip, es->apu[2], 5, es->base[2]); - snd_es1968_trigger_apu(chip, es->apu[2], es->apu_mode[2]); - } - if (es->fmt & ESS_FMT_STEREO) { - __apu_set_register(chip, es->apu[1], 5, es->base[1]); - snd_es1968_trigger_apu(chip, es->apu[1], es->apu_mode[1]); - if (es->mode == ESM_MODE_CAPTURE) { - __apu_set_register(chip, es->apu[3], 5, es->base[3]); - snd_es1968_trigger_apu(chip, es->apu[3], es->apu_mode[3]); - } - } - spin_unlock(&chip->reg_lock); -} - -static void snd_es1968_pcm_stop(struct es1968 *chip, struct esschan *es) -{ - spin_lock(&chip->reg_lock); - snd_es1968_trigger_apu(chip, es->apu[0], 0); - snd_es1968_trigger_apu(chip, es->apu[1], 0); - if (es->mode == ESM_MODE_CAPTURE) { - snd_es1968_trigger_apu(chip, es->apu[2], 0); - snd_es1968_trigger_apu(chip, es->apu[3], 0); - } - spin_unlock(&chip->reg_lock); -} - -/* set the wavecache control reg */ -static void snd_es1968_program_wavecache(struct es1968 *chip, struct esschan *es, - int channel, u32 addr, int capture) -{ - u32 tmpval = (addr - 0x10) & 0xFFF8; - - if (! capture) { - if (!(es->fmt & ESS_FMT_16BIT)) - tmpval |= 4; /* 8bit */ - if (es->fmt & ESS_FMT_STEREO) - tmpval |= 2; /* stereo */ - } - - /* set the wavecache control reg */ - wave_set_register(chip, es->apu[channel] << 3, tmpval); - -#ifdef CONFIG_PM - es->wc_map[channel] = tmpval; -#endif -} - - -static void snd_es1968_playback_setup(struct es1968 *chip, struct esschan *es, - struct snd_pcm_runtime *runtime) -{ - u32 pa; - int high_apu = 0; - int channel, apu; - int i, size; - unsigned long flags; - u32 freq; - - size = es->dma_size >> es->wav_shift; - - if (es->fmt & ESS_FMT_STEREO) - high_apu++; - - for (channel = 0; channel <= high_apu; channel++) { - apu = es->apu[channel]; - - snd_es1968_program_wavecache(chip, es, channel, es->memory->buf.addr, 0); - - /* Offset to PCMBAR */ - pa = es->memory->buf.addr; - pa -= chip->dma.addr; - pa >>= 1; /* words */ - - pa |= 0x00400000; /* System RAM (Bit 22) */ - - if (es->fmt & ESS_FMT_STEREO) { - /* Enable stereo */ - if (channel) - pa |= 0x00800000; /* (Bit 23) */ - if (es->fmt & ESS_FMT_16BIT) - pa >>= 1; - } - - /* base offset of dma calcs when reading the pointer - on this left one */ - es->base[channel] = pa & 0xFFFF; - - for (i = 0; i < 16; i++) - apu_set_register(chip, apu, i, 0x0000); - - /* Load the buffer into the wave engine */ - apu_set_register(chip, apu, 4, ((pa >> 16) & 0xFF) << 8); - apu_set_register(chip, apu, 5, pa & 0xFFFF); - apu_set_register(chip, apu, 6, (pa + size) & 0xFFFF); - /* setting loop == sample len */ - apu_set_register(chip, apu, 7, size); - - /* clear effects/env.. */ - apu_set_register(chip, apu, 8, 0x0000); - /* set amp now to 0xd0 (?), low byte is 'amplitude dest'? */ - apu_set_register(chip, apu, 9, 0xD000); - - /* clear routing stuff */ - apu_set_register(chip, apu, 11, 0x0000); - /* dma on, no envelopes, filter to all 1s) */ - apu_set_register(chip, apu, 0, 0x400F); - - if (es->fmt & ESS_FMT_16BIT) - es->apu_mode[channel] = ESM_APU_16BITLINEAR; - else - es->apu_mode[channel] = ESM_APU_8BITLINEAR; - - if (es->fmt & ESS_FMT_STEREO) { - /* set panning: left or right */ - /* Check: different panning. On my Canyon 3D Chipset the - Channels are swapped. I don't know, about the output - to the SPDif Link. Perhaps you have to change this - and not the APU Regs 4-5. */ - apu_set_register(chip, apu, 10, - 0x8F00 | (channel ? 0 : 0x10)); - es->apu_mode[channel] += 1; /* stereo */ - } else - apu_set_register(chip, apu, 10, 0x8F08); - } - - spin_lock_irqsave(&chip->reg_lock, flags); - /* clear WP interrupts */ - outw(1, chip->io_port + 0x04); - /* enable WP ints */ - outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - freq = runtime->rate; - /* set frequency */ - if (freq > 48000) - freq = 48000; - if (freq < 4000) - freq = 4000; - - /* hmmm.. */ - if (!(es->fmt & ESS_FMT_16BIT) && !(es->fmt & ESS_FMT_STEREO)) - freq >>= 1; - - freq = snd_es1968_compute_rate(chip, freq); - - /* Load the frequency, turn on 6dB */ - snd_es1968_apu_set_freq(chip, es->apu[0], freq); - snd_es1968_apu_set_freq(chip, es->apu[1], freq); -} - - -static void init_capture_apu(struct es1968 *chip, struct esschan *es, int channel, - unsigned int pa, unsigned int bsize, - int mode, int route) -{ - int i, apu = es->apu[channel]; - - es->apu_mode[channel] = mode; - - /* set the wavecache control reg */ - snd_es1968_program_wavecache(chip, es, channel, pa, 1); - - /* Offset to PCMBAR */ - pa -= chip->dma.addr; - pa >>= 1; /* words */ - - /* base offset of dma calcs when reading the pointer - on this left one */ - es->base[channel] = pa & 0xFFFF; - pa |= 0x00400000; /* bit 22 -> System RAM */ - - /* Begin loading the APU */ - for (i = 0; i < 16; i++) - apu_set_register(chip, apu, i, 0x0000); - - /* need to enable subgroups.. and we should probably - have different groups for different /dev/dsps.. */ - apu_set_register(chip, apu, 2, 0x8); - - /* Load the buffer into the wave engine */ - apu_set_register(chip, apu, 4, ((pa >> 16) & 0xFF) << 8); - apu_set_register(chip, apu, 5, pa & 0xFFFF); - apu_set_register(chip, apu, 6, (pa + bsize) & 0xFFFF); - apu_set_register(chip, apu, 7, bsize); - /* clear effects/env.. */ - apu_set_register(chip, apu, 8, 0x00F0); - /* amplitude now? sure. why not. */ - apu_set_register(chip, apu, 9, 0x0000); - /* set filter tune, radius, polar pan */ - apu_set_register(chip, apu, 10, 0x8F08); - /* route input */ - apu_set_register(chip, apu, 11, route); - /* dma on, no envelopes, filter to all 1s) */ - apu_set_register(chip, apu, 0, 0x400F); -} - -static void snd_es1968_capture_setup(struct es1968 *chip, struct esschan *es, - struct snd_pcm_runtime *runtime) -{ - int size; - u32 freq; - unsigned long flags; - - size = es->dma_size >> es->wav_shift; - - /* APU assignments: - 0 = mono/left SRC - 1 = right SRC - 2 = mono/left Input Mixer - 3 = right Input Mixer - */ - /* data seems to flow from the codec, through an apu into - the 'mixbuf' bit of page, then through the SRC apu - and out to the real 'buffer'. ok. sure. */ - - /* input mixer (left/mono) */ - /* parallel in crap, see maestro reg 0xC [8-11] */ - init_capture_apu(chip, es, 2, - es->mixbuf->buf.addr, ESM_MIXBUF_SIZE/4, /* in words */ - ESM_APU_INPUTMIXER, 0x14); - /* SRC (left/mono); get input from inputing apu */ - init_capture_apu(chip, es, 0, es->memory->buf.addr, size, - ESM_APU_SRCONVERTOR, es->apu[2]); - if (es->fmt & ESS_FMT_STEREO) { - /* input mixer (right) */ - init_capture_apu(chip, es, 3, - es->mixbuf->buf.addr + ESM_MIXBUF_SIZE/2, - ESM_MIXBUF_SIZE/4, /* in words */ - ESM_APU_INPUTMIXER, 0x15); - /* SRC (right) */ - init_capture_apu(chip, es, 1, - es->memory->buf.addr + size*2, size, - ESM_APU_SRCONVERTOR, es->apu[3]); - } - - freq = runtime->rate; - /* Sample Rate conversion APUs don't like 0x10000 for their rate */ - if (freq > 47999) - freq = 47999; - if (freq < 4000) - freq = 4000; - - freq = snd_es1968_compute_rate(chip, freq); - - /* Load the frequency, turn on 6dB */ - snd_es1968_apu_set_freq(chip, es->apu[0], freq); - snd_es1968_apu_set_freq(chip, es->apu[1], freq); - - /* fix mixer rate at 48khz. and its _must_ be 0x10000. */ - freq = 0x10000; - snd_es1968_apu_set_freq(chip, es->apu[2], freq); - snd_es1968_apu_set_freq(chip, es->apu[3], freq); - - spin_lock_irqsave(&chip->reg_lock, flags); - /* clear WP interrupts */ - outw(1, chip->io_port + 0x04); - /* enable WP ints */ - outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -/******************* - * ALSA Interface * - *******************/ - -static int snd_es1968_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct esschan *es = runtime->private_data; - - es->dma_size = snd_pcm_lib_buffer_bytes(substream); - es->frag_size = snd_pcm_lib_period_bytes(substream); - - es->wav_shift = 1; /* maestro handles always 16bit */ - es->fmt = 0; - if (snd_pcm_format_width(runtime->format) == 16) - es->fmt |= ESS_FMT_16BIT; - if (runtime->channels > 1) { - es->fmt |= ESS_FMT_STEREO; - if (es->fmt & ESS_FMT_16BIT) /* 8bit is already word shifted */ - es->wav_shift++; - } - es->bob_freq = snd_es1968_calc_bob_rate(chip, es, runtime); - - switch (es->mode) { - case ESM_MODE_PLAY: - snd_es1968_playback_setup(chip, es, runtime); - break; - case ESM_MODE_CAPTURE: - snd_es1968_capture_setup(chip, es, runtime); - break; - } - - return 0; -} - -static int snd_es1968_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct esschan *es = substream->runtime->private_data; - - spin_lock(&chip->substream_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (es->running) - break; - snd_es1968_bob_inc(chip, es->bob_freq); - es->count = 0; - es->hwptr = 0; - snd_es1968_pcm_start(chip, es); - es->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (! es->running) - break; - snd_es1968_pcm_stop(chip, es); - es->running = 0; - snd_es1968_bob_dec(chip); - break; - } - spin_unlock(&chip->substream_lock); - return 0; -} - -static snd_pcm_uframes_t snd_es1968_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct esschan *es = substream->runtime->private_data; - unsigned int ptr; - - ptr = snd_es1968_get_dma_ptr(chip, es) << es->wav_shift; - - return bytes_to_frames(substream->runtime, ptr % es->dma_size); -} - -static struct snd_pcm_hardware snd_es1968_playback = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - /*SNDRV_PCM_INFO_PAUSE |*/ - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 256, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_es1968_capture = { - .info = (SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - /*SNDRV_PCM_INFO_PAUSE |*/ - SNDRV_PCM_INFO_RESUME), - .formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 256, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* ************************* - * DMA memory management * - *************************/ - -/* Because the Maestro can only take addresses relative to the PCM base address - register :( */ - -static int calc_available_memory_size(struct es1968 *chip) -{ - int max_size = 0; - struct esm_memory *buf; - - mutex_lock(&chip->memory_mutex); - list_for_each_entry(buf, &chip->buf_list, list) { - if (buf->empty && buf->buf.bytes > max_size) - max_size = buf->buf.bytes; - } - mutex_unlock(&chip->memory_mutex); - if (max_size >= 128*1024) - max_size = 127*1024; - return max_size; -} - -/* allocate a new memory chunk with the specified size */ -static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size) -{ - struct esm_memory *buf; - - size = ALIGN(size, ESM_MEM_ALIGN); - mutex_lock(&chip->memory_mutex); - list_for_each_entry(buf, &chip->buf_list, list) { - if (buf->empty && buf->buf.bytes >= size) - goto __found; - } - mutex_unlock(&chip->memory_mutex); - return NULL; - -__found: - if (buf->buf.bytes > size) { - struct esm_memory *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL); - if (chunk == NULL) { - mutex_unlock(&chip->memory_mutex); - return NULL; - } - chunk->buf = buf->buf; - chunk->buf.bytes -= size; - chunk->buf.area += size; - chunk->buf.addr += size; - chunk->empty = 1; - buf->buf.bytes = size; - list_add(&chunk->list, &buf->list); - } - buf->empty = 0; - mutex_unlock(&chip->memory_mutex); - return buf; -} - -/* free a memory chunk */ -static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf) -{ - struct esm_memory *chunk; - - mutex_lock(&chip->memory_mutex); - buf->empty = 1; - if (buf->list.prev != &chip->buf_list) { - chunk = list_entry(buf->list.prev, struct esm_memory, list); - if (chunk->empty) { - chunk->buf.bytes += buf->buf.bytes; - list_del(&buf->list); - kfree(buf); - buf = chunk; - } - } - if (buf->list.next != &chip->buf_list) { - chunk = list_entry(buf->list.next, struct esm_memory, list); - if (chunk->empty) { - buf->buf.bytes += chunk->buf.bytes; - list_del(&chunk->list); - kfree(chunk); - } - } - mutex_unlock(&chip->memory_mutex); -} - -static void snd_es1968_free_dmabuf(struct es1968 *chip) -{ - struct list_head *p; - - if (! chip->dma.area) - return; - snd_dma_reserve_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci)); - while ((p = chip->buf_list.next) != &chip->buf_list) { - struct esm_memory *chunk = list_entry(p, struct esm_memory, list); - list_del(p); - kfree(chunk); - } -} - -static int __devinit -snd_es1968_init_dmabuf(struct es1968 *chip) -{ - int err; - struct esm_memory *chunk; - - chip->dma.dev.type = SNDRV_DMA_TYPE_DEV; - chip->dma.dev.dev = snd_dma_pci_data(chip->pci); - if (! snd_dma_get_reserved_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci))) { - err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - chip->total_bufsize, &chip->dma); - if (err < 0 || ! chip->dma.area) { - snd_printk(KERN_ERR "es1968: can't allocate dma pages for size %d\n", - chip->total_bufsize); - return -ENOMEM; - } - if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) { - snd_dma_free_pages(&chip->dma); - snd_printk(KERN_ERR "es1968: DMA buffer beyond 256MB.\n"); - return -ENOMEM; - } - } - - INIT_LIST_HEAD(&chip->buf_list); - /* allocate an empty chunk */ - chunk = kmalloc(sizeof(*chunk), GFP_KERNEL); - if (chunk == NULL) { - snd_es1968_free_dmabuf(chip); - return -ENOMEM; - } - memset(chip->dma.area, 0, ESM_MEM_ALIGN); - chunk->buf = chip->dma; - chunk->buf.area += ESM_MEM_ALIGN; - chunk->buf.addr += ESM_MEM_ALIGN; - chunk->buf.bytes -= ESM_MEM_ALIGN; - chunk->empty = 1; - list_add(&chunk->list, &chip->buf_list); - - return 0; -} - -/* setup the dma_areas */ -/* buffer is extracted from the pre-allocated memory chunk */ -static int snd_es1968_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct esschan *chan = runtime->private_data; - int size = params_buffer_bytes(hw_params); - - if (chan->memory) { - if (chan->memory->buf.bytes >= size) { - runtime->dma_bytes = size; - return 0; - } - snd_es1968_free_memory(chip, chan->memory); - } - chan->memory = snd_es1968_new_memory(chip, size); - if (chan->memory == NULL) { - // snd_printd("cannot allocate dma buffer: size = %d\n", size); - return -ENOMEM; - } - snd_pcm_set_runtime_buffer(substream, &chan->memory->buf); - return 1; /* area was changed */ -} - -/* remove dma areas if allocated */ -static int snd_es1968_hw_free(struct snd_pcm_substream *substream) -{ - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct esschan *chan; - - if (runtime->private_data == NULL) - return 0; - chan = runtime->private_data; - if (chan->memory) { - snd_es1968_free_memory(chip, chan->memory); - chan->memory = NULL; - } - return 0; -} - - -/* - * allocate APU pair - */ -static int snd_es1968_alloc_apu_pair(struct es1968 *chip, int type) -{ - int apu; - - for (apu = 0; apu < NR_APUS; apu += 2) { - if (chip->apu[apu] == ESM_APU_FREE && - chip->apu[apu + 1] == ESM_APU_FREE) { - chip->apu[apu] = chip->apu[apu + 1] = type; - return apu; - } - } - return -EBUSY; -} - -/* - * release APU pair - */ -static void snd_es1968_free_apu_pair(struct es1968 *chip, int apu) -{ - chip->apu[apu] = chip->apu[apu + 1] = ESM_APU_FREE; -} - - -/****************** - * PCM open/close * - ******************/ - -static int snd_es1968_playback_open(struct snd_pcm_substream *substream) -{ - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct esschan *es; - int apu1; - - /* search 2 APUs */ - apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY); - if (apu1 < 0) - return apu1; - - es = kzalloc(sizeof(*es), GFP_KERNEL); - if (!es) { - snd_es1968_free_apu_pair(chip, apu1); - return -ENOMEM; - } - - es->apu[0] = apu1; - es->apu[1] = apu1 + 1; - es->apu_mode[0] = 0; - es->apu_mode[1] = 0; - es->running = 0; - es->substream = substream; - es->mode = ESM_MODE_PLAY; - - runtime->private_data = es; - runtime->hw = snd_es1968_playback; - runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = - calc_available_memory_size(chip); - - spin_lock_irq(&chip->substream_lock); - list_add(&es->list, &chip->substream_list); - spin_unlock_irq(&chip->substream_lock); - - return 0; -} - -static int snd_es1968_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct esschan *es; - int apu1, apu2; - - apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE); - if (apu1 < 0) - return apu1; - apu2 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_RATECONV); - if (apu2 < 0) { - snd_es1968_free_apu_pair(chip, apu1); - return apu2; - } - - es = kzalloc(sizeof(*es), GFP_KERNEL); - if (!es) { - snd_es1968_free_apu_pair(chip, apu1); - snd_es1968_free_apu_pair(chip, apu2); - return -ENOMEM; - } - - es->apu[0] = apu1; - es->apu[1] = apu1 + 1; - es->apu[2] = apu2; - es->apu[3] = apu2 + 1; - es->apu_mode[0] = 0; - es->apu_mode[1] = 0; - es->apu_mode[2] = 0; - es->apu_mode[3] = 0; - es->running = 0; - es->substream = substream; - es->mode = ESM_MODE_CAPTURE; - - /* get mixbuffer */ - if ((es->mixbuf = snd_es1968_new_memory(chip, ESM_MIXBUF_SIZE)) == NULL) { - snd_es1968_free_apu_pair(chip, apu1); - snd_es1968_free_apu_pair(chip, apu2); - kfree(es); - return -ENOMEM; - } - memset(es->mixbuf->buf.area, 0, ESM_MIXBUF_SIZE); - - runtime->private_data = es; - runtime->hw = snd_es1968_capture; - runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = - calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */ - snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES); - - spin_lock_irq(&chip->substream_lock); - list_add(&es->list, &chip->substream_list); - spin_unlock_irq(&chip->substream_lock); - - return 0; -} - -static int snd_es1968_playback_close(struct snd_pcm_substream *substream) -{ - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct esschan *es; - - if (substream->runtime->private_data == NULL) - return 0; - es = substream->runtime->private_data; - spin_lock_irq(&chip->substream_lock); - list_del(&es->list); - spin_unlock_irq(&chip->substream_lock); - snd_es1968_free_apu_pair(chip, es->apu[0]); - kfree(es); - - return 0; -} - -static int snd_es1968_capture_close(struct snd_pcm_substream *substream) -{ - struct es1968 *chip = snd_pcm_substream_chip(substream); - struct esschan *es; - - if (substream->runtime->private_data == NULL) - return 0; - es = substream->runtime->private_data; - spin_lock_irq(&chip->substream_lock); - list_del(&es->list); - spin_unlock_irq(&chip->substream_lock); - snd_es1968_free_memory(chip, es->mixbuf); - snd_es1968_free_apu_pair(chip, es->apu[0]); - snd_es1968_free_apu_pair(chip, es->apu[2]); - kfree(es); - - return 0; -} - -static struct snd_pcm_ops snd_es1968_playback_ops = { - .open = snd_es1968_playback_open, - .close = snd_es1968_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_es1968_hw_params, - .hw_free = snd_es1968_hw_free, - .prepare = snd_es1968_pcm_prepare, - .trigger = snd_es1968_pcm_trigger, - .pointer = snd_es1968_pcm_pointer, -}; - -static struct snd_pcm_ops snd_es1968_capture_ops = { - .open = snd_es1968_capture_open, - .close = snd_es1968_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_es1968_hw_params, - .hw_free = snd_es1968_hw_free, - .prepare = snd_es1968_pcm_prepare, - .trigger = snd_es1968_pcm_trigger, - .pointer = snd_es1968_pcm_pointer, -}; - - -/* - * measure clock - */ -#define CLOCK_MEASURE_BUFSIZE 16768 /* enough large for a single shot */ - -static void __devinit es1968_measure_clock(struct es1968 *chip) -{ - int i, apu; - unsigned int pa, offset, t; - struct esm_memory *memory; - struct timeval start_time, stop_time; - - if (chip->clock == 0) - chip->clock = 48000; /* default clock value */ - - /* search 2 APUs (although one apu is enough) */ - if ((apu = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY)) < 0) { - snd_printk(KERN_ERR "Hmm, cannot find empty APU pair!?\n"); - return; - } - if ((memory = snd_es1968_new_memory(chip, CLOCK_MEASURE_BUFSIZE)) == NULL) { - snd_printk(KERN_ERR "cannot allocate dma buffer - using default clock %d\n", chip->clock); - snd_es1968_free_apu_pair(chip, apu); - return; - } - - memset(memory->buf.area, 0, CLOCK_MEASURE_BUFSIZE); - - wave_set_register(chip, apu << 3, (memory->buf.addr - 0x10) & 0xfff8); - - pa = (unsigned int)((memory->buf.addr - chip->dma.addr) >> 1); - pa |= 0x00400000; /* System RAM (Bit 22) */ - - /* initialize apu */ - for (i = 0; i < 16; i++) - apu_set_register(chip, apu, i, 0x0000); - - apu_set_register(chip, apu, 0, 0x400f); - apu_set_register(chip, apu, 4, ((pa >> 16) & 0xff) << 8); - apu_set_register(chip, apu, 5, pa & 0xffff); - apu_set_register(chip, apu, 6, (pa + CLOCK_MEASURE_BUFSIZE/2) & 0xffff); - apu_set_register(chip, apu, 7, CLOCK_MEASURE_BUFSIZE/2); - apu_set_register(chip, apu, 8, 0x0000); - apu_set_register(chip, apu, 9, 0xD000); - apu_set_register(chip, apu, 10, 0x8F08); - apu_set_register(chip, apu, 11, 0x0000); - spin_lock_irq(&chip->reg_lock); - outw(1, chip->io_port + 0x04); /* clear WP interrupts */ - outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); /* enable WP ints */ - spin_unlock_irq(&chip->reg_lock); - - snd_es1968_apu_set_freq(chip, apu, ((unsigned int)48000 << 16) / chip->clock); /* 48000 Hz */ - - chip->in_measurement = 1; - chip->measure_apu = apu; - spin_lock_irq(&chip->reg_lock); - snd_es1968_bob_inc(chip, ESM_BOB_FREQ); - __apu_set_register(chip, apu, 5, pa & 0xffff); - snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR); - do_gettimeofday(&start_time); - spin_unlock_irq(&chip->reg_lock); - msleep(50); - spin_lock_irq(&chip->reg_lock); - offset = __apu_get_register(chip, apu, 5); - do_gettimeofday(&stop_time); - snd_es1968_trigger_apu(chip, apu, 0); /* stop */ - snd_es1968_bob_dec(chip); - chip->in_measurement = 0; - spin_unlock_irq(&chip->reg_lock); - - /* check the current position */ - offset -= (pa & 0xffff); - offset &= 0xfffe; - offset += chip->measure_count * (CLOCK_MEASURE_BUFSIZE/2); - - t = stop_time.tv_sec - start_time.tv_sec; - t *= 1000000; - if (stop_time.tv_usec < start_time.tv_usec) - t -= start_time.tv_usec - stop_time.tv_usec; - else - t += stop_time.tv_usec - start_time.tv_usec; - if (t == 0) { - snd_printk(KERN_ERR "?? calculation error..\n"); - } else { - offset *= 1000; - offset = (offset / t) * 1000 + ((offset % t) * 1000) / t; - if (offset < 47500 || offset > 48500) { - if (offset >= 40000 && offset <= 50000) - chip->clock = (chip->clock * offset) / 48000; - } - printk(KERN_INFO "es1968: clocking to %d\n", chip->clock); - } - snd_es1968_free_memory(chip, memory); - snd_es1968_free_apu_pair(chip, apu); -} - - -/* - */ - -static void snd_es1968_pcm_free(struct snd_pcm *pcm) -{ - struct es1968 *esm = pcm->private_data; - snd_es1968_free_dmabuf(esm); - esm->pcm = NULL; -} - -static int __devinit -snd_es1968_pcm(struct es1968 *chip, int device) -{ - struct snd_pcm *pcm; - int err; - - /* get DMA buffer */ - if ((err = snd_es1968_init_dmabuf(chip)) < 0) - return err; - - /* set PCMBAR */ - wave_set_register(chip, 0x01FC, chip->dma.addr >> 12); - wave_set_register(chip, 0x01FD, chip->dma.addr >> 12); - wave_set_register(chip, 0x01FE, chip->dma.addr >> 12); - wave_set_register(chip, 0x01FF, chip->dma.addr >> 12); - - if ((err = snd_pcm_new(chip->card, "ESS Maestro", device, - chip->playback_streams, - chip->capture_streams, &pcm)) < 0) - return err; - - pcm->private_data = chip; - pcm->private_free = snd_es1968_pcm_free; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1968_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1968_capture_ops); - - pcm->info_flags = 0; - - strcpy(pcm->name, "ESS Maestro"); - - chip->pcm = pcm; - - return 0; -} -/* - * suppress jitter on some maestros when playing stereo - */ -static void snd_es1968_suppress_jitter(struct es1968 *chip, struct esschan *es) -{ - unsigned int cp1; - unsigned int cp2; - unsigned int diff; - - cp1 = __apu_get_register(chip, 0, 5); - cp2 = __apu_get_register(chip, 1, 5); - diff = (cp1 > cp2 ? cp1 - cp2 : cp2 - cp1); - - if (diff > 1) - __maestro_write(chip, IDR0_DATA_PORT, cp1); -} - -/* - * update pointer - */ -static void snd_es1968_update_pcm(struct es1968 *chip, struct esschan *es) -{ - unsigned int hwptr; - unsigned int diff; - struct snd_pcm_substream *subs = es->substream; - - if (subs == NULL || !es->running) - return; - - hwptr = snd_es1968_get_dma_ptr(chip, es) << es->wav_shift; - hwptr %= es->dma_size; - - diff = (es->dma_size + hwptr - es->hwptr) % es->dma_size; - - es->hwptr = hwptr; - es->count += diff; - - if (es->count > es->frag_size) { - spin_unlock(&chip->substream_lock); - snd_pcm_period_elapsed(subs); - spin_lock(&chip->substream_lock); - es->count %= es->frag_size; - } -} - -/* The hardware volume works by incrementing / decrementing 2 counters - (without wrap around) in response to volume button presses and then - generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 - of a byte wide register. The meaning of bits 0 and 4 is unknown. */ -static void es1968_update_hw_volume(struct work_struct *work) -{ - struct es1968 *chip = container_of(work, struct es1968, hwvol_work); - int x, val; - - /* Figure out which volume control button was pushed, - based on differences from the default register - values. */ - x = inb(chip->io_port + 0x1c) & 0xee; - /* Reset the volume control registers. */ - outb(0x88, chip->io_port + 0x1c); - outb(0x88, chip->io_port + 0x1d); - outb(0x88, chip->io_port + 0x1e); - outb(0x88, chip->io_port + 0x1f); - - if (chip->in_suspend) - return; - -#ifndef CONFIG_SND_ES1968_INPUT - if (! chip->master_switch || ! chip->master_volume) - return; - - val = snd_ac97_read(chip->ac97, AC97_MASTER); - switch (x) { - case 0x88: - /* mute */ - val ^= 0x8000; - break; - case 0xaa: - /* volume up */ - if ((val & 0x7f) > 0) - val--; - if ((val & 0x7f00) > 0) - val -= 0x0100; - break; - case 0x66: - /* volume down */ - if ((val & 0x7f) < 0x1f) - val++; - if ((val & 0x7f00) < 0x1f00) - val += 0x0100; - break; - } - if (snd_ac97_update(chip->ac97, AC97_MASTER, val)) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); -#else - if (!chip->input_dev) - return; - - val = 0; - switch (x) { - case 0x88: - /* The counters have not changed, yet we've received a HV - interrupt. According to tests run by various people this - happens when pressing the mute button. */ - val = KEY_MUTE; - break; - case 0xaa: - /* counters increased by 1 -> volume up */ - val = KEY_VOLUMEUP; - break; - case 0x66: - /* counters decreased by 1 -> volume down */ - val = KEY_VOLUMEDOWN; - break; - } - - if (val) { - input_report_key(chip->input_dev, val, 1); - input_sync(chip->input_dev); - input_report_key(chip->input_dev, val, 0); - input_sync(chip->input_dev); - } -#endif -} - -/* - * interrupt handler - */ -static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id) -{ - struct es1968 *chip = dev_id; - u32 event; - - if (!(event = inb(chip->io_port + 0x1A))) - return IRQ_NONE; - - outw(inw(chip->io_port + 4) & 1, chip->io_port + 4); - - if (event & ESM_HWVOL_IRQ) - schedule_work(&chip->hwvol_work); - - /* else ack 'em all, i imagine */ - outb(0xFF, chip->io_port + 0x1A); - - if ((event & ESM_MPU401_IRQ) && chip->rmidi) { - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - } - - if (event & ESM_SOUND_IRQ) { - struct esschan *es; - spin_lock(&chip->substream_lock); - list_for_each_entry(es, &chip->substream_list, list) { - if (es->running) { - snd_es1968_update_pcm(chip, es); - if (es->fmt & ESS_FMT_STEREO) - snd_es1968_suppress_jitter(chip, es); - } - } - spin_unlock(&chip->substream_lock); - if (chip->in_measurement) { - unsigned int curp = __apu_get_register(chip, chip->measure_apu, 5); - if (curp < chip->measure_lastpos) - chip->measure_count++; - chip->measure_lastpos = curp; - } - } - - return IRQ_HANDLED; -} - -/* - * Mixer stuff - */ - -static int __devinit -snd_es1968_mixer(struct es1968 *chip) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; -#ifndef CONFIG_SND_ES1968_INPUT - struct snd_ctl_elem_id elem_id; -#endif - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_es1968_ac97_write, - .read = snd_es1968_ac97_read, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) - return err; - pbus->no_vra = 1; /* ES1968 doesn't need VRA */ - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) - return err; - -#ifndef CONFIG_SND_ES1968_INPUT - /* attach master switch / volumes for h/w volume control */ - memset(&elem_id, 0, sizeof(elem_id)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(elem_id.name, "Master Playback Switch"); - chip->master_switch = snd_ctl_find_id(chip->card, &elem_id); - memset(&elem_id, 0, sizeof(elem_id)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(elem_id.name, "Master Playback Volume"); - chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); -#endif - - return 0; -} - -/* - * reset ac97 codec - */ - -static void snd_es1968_ac97_reset(struct es1968 *chip) -{ - unsigned long ioaddr = chip->io_port; - - unsigned short save_ringbus_a; - unsigned short save_68; - unsigned short w; - unsigned int vend; - - /* save configuration */ - save_ringbus_a = inw(ioaddr + 0x36); - - //outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38); /* clear second codec id? */ - /* set command/status address i/o to 1st codec */ - outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a); - outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c); - - /* disable ac link */ - outw(0x0000, ioaddr + 0x36); - save_68 = inw(ioaddr + 0x68); - pci_read_config_word(chip->pci, 0x58, &w); /* something magical with gpio and bus arb. */ - pci_read_config_dword(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend); - if (w & 1) - save_68 |= 0x10; - outw(0xfffe, ioaddr + 0x64); /* unmask gpio 0 */ - outw(0x0001, ioaddr + 0x68); /* gpio write */ - outw(0x0000, ioaddr + 0x60); /* write 0 to gpio 0 */ - udelay(20); - outw(0x0001, ioaddr + 0x60); /* write 1 to gpio 1 */ - msleep(20); - - outw(save_68 | 0x1, ioaddr + 0x68); /* now restore .. */ - outw((inw(ioaddr + 0x38) & 0xfffc) | 0x1, ioaddr + 0x38); - outw((inw(ioaddr + 0x3a) & 0xfffc) | 0x1, ioaddr + 0x3a); - outw((inw(ioaddr + 0x3c) & 0xfffc) | 0x1, ioaddr + 0x3c); - - /* now the second codec */ - /* disable ac link */ - outw(0x0000, ioaddr + 0x36); - outw(0xfff7, ioaddr + 0x64); /* unmask gpio 3 */ - save_68 = inw(ioaddr + 0x68); - outw(0x0009, ioaddr + 0x68); /* gpio write 0 & 3 ?? */ - outw(0x0001, ioaddr + 0x60); /* write 1 to gpio */ - udelay(20); - outw(0x0009, ioaddr + 0x60); /* write 9 to gpio */ - msleep(500); - //outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38); - outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a); - outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c); - -#if 0 /* the loop here needs to be much better if we want it.. */ - snd_printk(KERN_INFO "trying software reset\n"); - /* try and do a software reset */ - outb(0x80 | 0x7c, ioaddr + 0x30); - for (w = 0;; w++) { - if ((inw(ioaddr + 0x30) & 1) == 0) { - if (inb(ioaddr + 0x32) != 0) - break; - - outb(0x80 | 0x7d, ioaddr + 0x30); - if (((inw(ioaddr + 0x30) & 1) == 0) - && (inb(ioaddr + 0x32) != 0)) - break; - outb(0x80 | 0x7f, ioaddr + 0x30); - if (((inw(ioaddr + 0x30) & 1) == 0) - && (inb(ioaddr + 0x32) != 0)) - break; - } - - if (w > 10000) { - outb(inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37); /* do a software reset */ - msleep(500); /* oh my.. */ - outb(inb(ioaddr + 0x37) & ~0x08, - ioaddr + 0x37); - udelay(1); - outw(0x80, ioaddr + 0x30); - for (w = 0; w < 10000; w++) { - if ((inw(ioaddr + 0x30) & 1) == 0) - break; - } - } - } -#endif - if (vend == NEC_VERSA_SUBID1 || vend == NEC_VERSA_SUBID2) { - /* turn on external amp? */ - outw(0xf9ff, ioaddr + 0x64); - outw(inw(ioaddr + 0x68) | 0x600, ioaddr + 0x68); - outw(0x0209, ioaddr + 0x60); - } - - /* restore.. */ - outw(save_ringbus_a, ioaddr + 0x36); - - /* Turn on the 978 docking chip. - First frob the "master output enable" bit, - then set most of the playback volume control registers to max. */ - outb(inb(ioaddr+0xc0)|(1<<5), ioaddr+0xc0); - outb(0xff, ioaddr+0xc3); - outb(0xff, ioaddr+0xc4); - outb(0xff, ioaddr+0xc6); - outb(0xff, ioaddr+0xc8); - outb(0x3f, ioaddr+0xcf); - outb(0x3f, ioaddr+0xd0); -} - -static void snd_es1968_reset(struct es1968 *chip) -{ - /* Reset */ - outw(ESM_RESET_MAESTRO | ESM_RESET_DIRECTSOUND, - chip->io_port + ESM_PORT_HOST_IRQ); - udelay(10); - outw(0x0000, chip->io_port + ESM_PORT_HOST_IRQ); - udelay(10); -} - -/* - * initialize maestro chip - */ -static void snd_es1968_chip_init(struct es1968 *chip) -{ - struct pci_dev *pci = chip->pci; - int i; - unsigned long iobase = chip->io_port; - u16 w; - u32 n; - - /* We used to muck around with pci config space that - * we had no business messing with. We don't know enough - * about the machine to know which DMA mode is appropriate, - * etc. We were guessing wrong on some machines and making - * them unhappy. We now trust in the BIOS to do things right, - * which almost certainly means a new host of problems will - * arise with broken BIOS implementations. screw 'em. - * We're already intolerant of machines that don't assign - * IRQs. - */ - - /* Config Reg A */ - pci_read_config_word(pci, ESM_CONFIG_A, &w); - - w &= ~DMA_CLEAR; /* Clear DMA bits */ - w &= ~(PIC_SNOOP1 | PIC_SNOOP2); /* Clear Pic Snoop Mode Bits */ - w &= ~SAFEGUARD; /* Safeguard off */ - w |= POST_WRITE; /* Posted write */ - w |= PCI_TIMING; /* PCI timing on */ - /* XXX huh? claims to be reserved.. */ - w &= ~SWAP_LR; /* swap left/right - seems to only have effect on SB - Emulation */ - w &= ~SUBTR_DECODE; /* Subtractive decode off */ - - pci_write_config_word(pci, ESM_CONFIG_A, w); - - /* Config Reg B */ - - pci_read_config_word(pci, ESM_CONFIG_B, &w); - - w &= ~(1 << 15); /* Turn off internal clock multiplier */ - /* XXX how do we know which to use? */ - w &= ~(1 << 14); /* External clock */ - - w &= ~SPDIF_CONFB; /* disable S/PDIF output */ - w |= HWV_CONFB; /* HWV on */ - w |= DEBOUNCE; /* Debounce off: easier to push the HW buttons */ - w &= ~GPIO_CONFB; /* GPIO 4:5 */ - w |= CHI_CONFB; /* Disconnect from the CHI. Enabling this made a dell 7500 work. */ - w &= ~IDMA_CONFB; /* IDMA off (undocumented) */ - w &= ~MIDI_FIX; /* MIDI fix off (undoc) */ - w &= ~(1 << 1); /* reserved, always write 0 */ - w &= ~IRQ_TO_ISA; /* IRQ to ISA off (undoc) */ - - pci_write_config_word(pci, ESM_CONFIG_B, w); - - /* DDMA off */ - - pci_read_config_word(pci, ESM_DDMA, &w); - w &= ~(1 << 0); - pci_write_config_word(pci, ESM_DDMA, w); - - /* - * Legacy mode - */ - - pci_read_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, &w); - - w |= ESS_DISABLE_AUDIO; /* Disable Legacy Audio */ - w &= ~ESS_ENABLE_SERIAL_IRQ; /* Disable SIRQ */ - w &= ~(0x1f); /* disable mpu irq/io, game port, fm, SB */ - - pci_write_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, w); - - /* Set up 978 docking control chip. */ - pci_read_config_word(pci, 0x58, &w); - w|=1<<2; /* Enable 978. */ - w|=1<<3; /* Turn on 978 hardware volume control. */ - w&=~(1<<11); /* Turn on 978 mixer volume control. */ - pci_write_config_word(pci, 0x58, w); - - /* Sound Reset */ - - snd_es1968_reset(chip); - - /* - * Ring Bus Setup - */ - - /* setup usual 0x34 stuff.. 0x36 may be chip specific */ - outw(0xC090, iobase + ESM_RING_BUS_DEST); /* direct sound, stereo */ - udelay(20); - outw(0x3000, iobase + ESM_RING_BUS_CONTR_A); /* enable ringbus/serial */ - udelay(20); - - /* - * Reset the CODEC - */ - - snd_es1968_ac97_reset(chip); - - /* Ring Bus Control B */ - - n = inl(iobase + ESM_RING_BUS_CONTR_B); - n &= ~RINGB_EN_SPDIF; /* SPDIF off */ - //w |= RINGB_EN_2CODEC; /* enable 2nd codec */ - outl(n, iobase + ESM_RING_BUS_CONTR_B); - - /* Set hardware volume control registers to midpoints. - We can tell which button was pushed based on how they change. */ - outb(0x88, iobase+0x1c); - outb(0x88, iobase+0x1d); - outb(0x88, iobase+0x1e); - outb(0x88, iobase+0x1f); - - /* it appears some maestros (dell 7500) only work if these are set, - regardless of wether we use the assp or not. */ - - outb(0, iobase + ASSP_CONTROL_B); - outb(3, iobase + ASSP_CONTROL_A); /* M: Reserved bits... */ - outb(0, iobase + ASSP_CONTROL_C); /* M: Disable ASSP, ASSP IRQ's and FM Port */ - - /* - * set up wavecache - */ - for (i = 0; i < 16; i++) { - /* Write 0 into the buffer area 0x1E0->1EF */ - outw(0x01E0 + i, iobase + WC_INDEX); - outw(0x0000, iobase + WC_DATA); - - /* The 1.10 test program seem to write 0 into the buffer area - * 0x1D0-0x1DF too.*/ - outw(0x01D0 + i, iobase + WC_INDEX); - outw(0x0000, iobase + WC_DATA); - } - wave_set_register(chip, IDR7_WAVE_ROMRAM, - (wave_get_register(chip, IDR7_WAVE_ROMRAM) & 0xFF00)); - wave_set_register(chip, IDR7_WAVE_ROMRAM, - wave_get_register(chip, IDR7_WAVE_ROMRAM) | 0x100); - wave_set_register(chip, IDR7_WAVE_ROMRAM, - wave_get_register(chip, IDR7_WAVE_ROMRAM) & ~0x200); - wave_set_register(chip, IDR7_WAVE_ROMRAM, - wave_get_register(chip, IDR7_WAVE_ROMRAM) | ~0x400); - - - maestro_write(chip, IDR2_CRAM_DATA, 0x0000); - /* Now back to the DirectSound stuff */ - /* audio serial configuration.. ? */ - maestro_write(chip, 0x08, 0xB004); - maestro_write(chip, 0x09, 0x001B); - maestro_write(chip, 0x0A, 0x8000); - maestro_write(chip, 0x0B, 0x3F37); - maestro_write(chip, 0x0C, 0x0098); - - /* parallel in, has something to do with recording :) */ - maestro_write(chip, 0x0C, - (maestro_read(chip, 0x0C) & ~0xF000) | 0x8000); - /* parallel out */ - maestro_write(chip, 0x0C, - (maestro_read(chip, 0x0C) & ~0x0F00) | 0x0500); - - maestro_write(chip, 0x0D, 0x7632); - - /* Wave cache control on - test off, sg off, - enable, enable extra chans 1Mb */ - - w = inw(iobase + WC_CONTROL); - - w &= ~0xFA00; /* Seems to be reserved? I don't know */ - w |= 0xA000; /* reserved... I don't know */ - w &= ~0x0200; /* Channels 56,57,58,59 as Extra Play,Rec Channel enable - Seems to crash the Computer if enabled... */ - w |= 0x0100; /* Wave Cache Operation Enabled */ - w |= 0x0080; /* Channels 60/61 as Placback/Record enabled */ - w &= ~0x0060; /* Clear Wavtable Size */ - w |= 0x0020; /* Wavetable Size : 1MB */ - /* Bit 4 is reserved */ - w &= ~0x000C; /* DMA Stuff? I don't understand what the datasheet means */ - /* Bit 1 is reserved */ - w &= ~0x0001; /* Test Mode off */ - - outw(w, iobase + WC_CONTROL); - - /* Now clear the APU control ram */ - for (i = 0; i < NR_APUS; i++) { - for (w = 0; w < NR_APU_REGS; w++) - apu_set_register(chip, i, w, 0); - - } -} - -/* Enable IRQ's */ -static void snd_es1968_start_irq(struct es1968 *chip) -{ - unsigned short w; - w = ESM_HIRQ_DSIE | ESM_HIRQ_HW_VOLUME; - if (chip->rmidi) - w |= ESM_HIRQ_MPU401; - outb(w, chip->io_port + 0x1A); - outw(w, chip->io_port + ESM_PORT_HOST_IRQ); -} - -#ifdef CONFIG_PM -/* - * PM support - */ -static int es1968_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct es1968 *chip = card->private_data; - - if (! chip->do_pm) - return 0; - - chip->in_suspend = 1; - cancel_work_sync(&chip->hwvol_work); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_ac97_suspend(chip->ac97); - snd_es1968_bob_stop(chip); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int es1968_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct es1968 *chip = card->private_data; - struct esschan *es; - - if (! chip->do_pm) - return 0; - - /* restore all our config */ - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "es1968: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_es1968_chip_init(chip); - - /* need to restore the base pointers.. */ - if (chip->dma.addr) { - /* set PCMBAR */ - wave_set_register(chip, 0x01FC, chip->dma.addr >> 12); - } - - snd_es1968_start_irq(chip); - - /* restore ac97 state */ - snd_ac97_resume(chip->ac97); - - list_for_each_entry(es, &chip->substream_list, list) { - switch (es->mode) { - case ESM_MODE_PLAY: - snd_es1968_playback_setup(chip, es, es->substream->runtime); - break; - case ESM_MODE_CAPTURE: - snd_es1968_capture_setup(chip, es, es->substream->runtime); - break; - } - } - - /* start timer again */ - if (chip->bobclient) - snd_es1968_bob_start(chip); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - chip->in_suspend = 0; - return 0; -} -#endif /* CONFIG_PM */ - -#ifdef SUPPORT_JOYSTICK -#define JOYSTICK_ADDR 0x200 -static int __devinit snd_es1968_create_gameport(struct es1968 *chip, int dev) -{ - struct gameport *gp; - struct resource *r; - u16 val; - - if (!joystick[dev]) - return -ENODEV; - - r = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport"); - if (!r) - return -EBUSY; - - chip->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "es1968: cannot allocate memory for gameport\n"); - release_and_free_resource(r); - return -ENOMEM; - } - - pci_read_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, &val); - pci_write_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04); - - gameport_set_name(gp, "ES1968 Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); - gameport_set_dev_parent(gp, &chip->pci->dev); - gp->io = JOYSTICK_ADDR; - gameport_set_port_data(gp, r); - - gameport_register_port(gp); - - return 0; -} - -static void snd_es1968_free_gameport(struct es1968 *chip) -{ - if (chip->gameport) { - struct resource *r = gameport_get_port_data(chip->gameport); - - gameport_unregister_port(chip->gameport); - chip->gameport = NULL; - - release_and_free_resource(r); - } -} -#else -static inline int snd_es1968_create_gameport(struct es1968 *chip, int dev) { return -ENOSYS; } -static inline void snd_es1968_free_gameport(struct es1968 *chip) { } -#endif - -#ifdef CONFIG_SND_ES1968_INPUT -static int __devinit snd_es1968_input_register(struct es1968 *chip) -{ - struct input_dev *input_dev; - int err; - - input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - - snprintf(chip->phys, sizeof(chip->phys), "pci-%s/input0", - pci_name(chip->pci)); - - input_dev->name = chip->card->driver; - input_dev->phys = chip->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.vendor = chip->pci->vendor; - input_dev->id.product = chip->pci->device; - input_dev->dev.parent = &chip->pci->dev; - - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(KEY_MUTE, input_dev->keybit); - __set_bit(KEY_VOLUMEDOWN, input_dev->keybit); - __set_bit(KEY_VOLUMEUP, input_dev->keybit); - - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } - - chip->input_dev = input_dev; - return 0; -} -#endif /* CONFIG_SND_ES1968_INPUT */ - -#ifdef CONFIG_SND_ES1968_RADIO -#define GPIO_DATA 0x60 -#define IO_MASK 4 /* mask register offset from GPIO_DATA - bits 1=unmask write to given bit */ -#define IO_DIR 8 /* direction register offset from GPIO_DATA - bits 0/1=read/write direction */ -/* mask bits for GPIO lines */ -#define STR_DATA 0x0040 /* GPIO6 */ -#define STR_CLK 0x0080 /* GPIO7 */ -#define STR_WREN 0x0100 /* GPIO8 */ -#define STR_MOST 0x0200 /* GPIO9 */ - -static void snd_es1968_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) -{ - struct es1968 *chip = tea->private_data; - unsigned long io = chip->io_port + GPIO_DATA; - u16 val = 0; - - val |= (pins & TEA575X_DATA) ? STR_DATA : 0; - val |= (pins & TEA575X_CLK) ? STR_CLK : 0; - val |= (pins & TEA575X_WREN) ? STR_WREN : 0; - - outw(val, io); -} - -static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea) -{ - struct es1968 *chip = tea->private_data; - unsigned long io = chip->io_port + GPIO_DATA; - u16 val = inw(io); - - return (val & STR_DATA) ? TEA575X_DATA : 0 | - (val & STR_MOST) ? TEA575X_MOST : 0; -} - -static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output) -{ - struct es1968 *chip = tea->private_data; - unsigned long io = chip->io_port + GPIO_DATA; - u16 odir = inw(io + IO_DIR); - - if (output) { - outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK); - outw(odir | STR_DATA | STR_CLK | STR_WREN, io + IO_DIR); - } else { - outw(~(STR_CLK | STR_WREN | STR_DATA | STR_MOST), io + IO_MASK); - outw((odir & ~(STR_DATA | STR_MOST)) | STR_CLK | STR_WREN, io + IO_DIR); - } -} - -static struct snd_tea575x_ops snd_es1968_tea_ops = { - .set_pins = snd_es1968_tea575x_set_pins, - .get_pins = snd_es1968_tea575x_get_pins, - .set_direction = snd_es1968_tea575x_set_direction, -}; -#endif - -static int snd_es1968_free(struct es1968 *chip) -{ - cancel_work_sync(&chip->hwvol_work); -#ifdef CONFIG_SND_ES1968_INPUT - if (chip->input_dev) - input_unregister_device(chip->input_dev); -#endif - - if (chip->io_port) { - if (chip->irq >= 0) - synchronize_irq(chip->irq); - outw(1, chip->io_port + 0x04); /* clear WP interrupts */ - outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */ - } - -#ifdef CONFIG_SND_ES1968_RADIO - snd_tea575x_exit(&chip->tea); - v4l2_device_unregister(&chip->v4l2_dev); -#endif - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - snd_es1968_free_gameport(chip); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_es1968_dev_free(struct snd_device *device) -{ - struct es1968 *chip = device->device_data; - return snd_es1968_free(chip); -} - -struct ess_device_list { - unsigned short type; /* chip type */ - unsigned short vendor; /* subsystem vendor id */ -}; - -static struct ess_device_list pm_whitelist[] __devinitdata = { - { TYPE_MAESTRO2E, 0x0e11 }, /* Compaq Armada */ - { TYPE_MAESTRO2E, 0x1028 }, - { TYPE_MAESTRO2E, 0x103c }, - { TYPE_MAESTRO2E, 0x1179 }, - { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ - { TYPE_MAESTRO2E, 0x1558 }, -}; - -static struct ess_device_list mpu_blacklist[] __devinitdata = { - { TYPE_MAESTRO2, 0x125d }, -}; - -static int __devinit snd_es1968_create(struct snd_card *card, - struct pci_dev *pci, - int total_bufsize, - int play_streams, - int capt_streams, - int chip_type, - int do_pm, - int radio_nr, - struct es1968 **chip_ret) -{ - static struct snd_device_ops ops = { - .dev_free = snd_es1968_dev_free, - }; - struct es1968 *chip; - int i, err; - - *chip_ret = NULL; - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (! chip) { - pci_disable_device(pci); - return -ENOMEM; - } - - /* Set Vars */ - chip->type = chip_type; - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->substream_lock); - INIT_LIST_HEAD(&chip->buf_list); - INIT_LIST_HEAD(&chip->substream_list); - mutex_init(&chip->memory_mutex); - INIT_WORK(&chip->hwvol_work, es1968_update_hw_volume); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - chip->total_bufsize = total_bufsize; /* in bytes */ - chip->playback_streams = play_streams; - chip->capture_streams = capt_streams; - - if ((err = pci_request_regions(pci, "ESS Maestro")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->io_port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_es1968_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - - /* Clear Maestro_map */ - for (i = 0; i < 32; i++) - chip->maestro_map[i] = 0; - - /* Clear Apu Map */ - for (i = 0; i < NR_APUS; i++) - chip->apu[i] = ESM_APU_FREE; - - /* just to be sure */ - pci_set_master(pci); - - if (do_pm > 1) { - /* disable power-management if not on the whitelist */ - unsigned short vend; - pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend); - for (i = 0; i < (int)ARRAY_SIZE(pm_whitelist); i++) { - if (chip->type == pm_whitelist[i].type && - vend == pm_whitelist[i].vendor) { - do_pm = 1; - break; - } - } - if (do_pm > 1) { - /* not matched; disabling pm */ - printk(KERN_INFO "es1968: not attempting power management.\n"); - do_pm = 0; - } - } - chip->do_pm = do_pm; - - snd_es1968_chip_init(chip); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_es1968_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - -#ifdef CONFIG_SND_ES1968_RADIO - err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); - if (err < 0) { - snd_es1968_free(chip); - return err; - } - chip->tea.v4l2_dev = &chip->v4l2_dev; - chip->tea.private_data = chip; - chip->tea.radio_nr = radio_nr; - chip->tea.ops = &snd_es1968_tea_ops; - strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card)); - sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); - if (!snd_tea575x_init(&chip->tea)) - printk(KERN_INFO "es1968: detected TEA575x radio\n"); -#endif - - *chip_ret = chip; - - return 0; -} - - -/* - */ -static int __devinit snd_es1968_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct es1968 *chip; - unsigned int i; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if (total_bufsize[dev] < 128) - total_bufsize[dev] = 128; - if (total_bufsize[dev] > 4096) - total_bufsize[dev] = 4096; - if ((err = snd_es1968_create(card, pci, - total_bufsize[dev] * 1024, /* in bytes */ - pcm_substreams_p[dev], - pcm_substreams_c[dev], - pci_id->driver_data, - use_pm[dev], - radio_nr[dev], - &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - switch (chip->type) { - case TYPE_MAESTRO2E: - strcpy(card->driver, "ES1978"); - strcpy(card->shortname, "ESS ES1978 (Maestro 2E)"); - break; - case TYPE_MAESTRO2: - strcpy(card->driver, "ES1968"); - strcpy(card->shortname, "ESS ES1968 (Maestro 2)"); - break; - case TYPE_MAESTRO: - strcpy(card->driver, "ESM1"); - strcpy(card->shortname, "ESS Maestro 1"); - break; - } - - if ((err = snd_es1968_pcm(chip, 0)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_es1968_mixer(chip)) < 0) { - snd_card_free(card); - return err; - } - - if (enable_mpu[dev] == 2) { - /* check the black list */ - unsigned short vend; - pci_read_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, &vend); - for (i = 0; i < ARRAY_SIZE(mpu_blacklist); i++) { - if (chip->type == mpu_blacklist[i].type && - vend == mpu_blacklist[i].vendor) { - enable_mpu[dev] = 0; - break; - } - } - } - if (enable_mpu[dev]) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - chip->io_port + ESM_MPU401_PORT, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi)) < 0) { - printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n"); - } - } - - snd_es1968_create_gameport(chip, dev); - -#ifdef CONFIG_SND_ES1968_INPUT - err = snd_es1968_input_register(chip); - if (err) - snd_printk(KERN_WARNING "Input device registration " - "failed with error %i", err); -#endif - - snd_es1968_start_irq(chip); - - chip->clock = clock[dev]; - if (! chip->clock) - es1968_measure_clock(chip); - - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, chip->io_port, chip->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_es1968_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_es1968_ids, - .probe = snd_es1968_probe, - .remove = __devexit_p(snd_es1968_remove), -#ifdef CONFIG_PM - .suspend = es1968_suspend, - .resume = es1968_resume, -#endif -}; - -static int __init alsa_card_es1968_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_es1968_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_es1968_init) -module_exit(alsa_card_es1968_exit) diff --git a/ANDROID_3.4.5/sound/pci/fm801.c b/ANDROID_3.4.5/sound/pci/fm801.c deleted file mode 100644 index a416ea8a..00000000 --- a/ANDROID_3.4.5/sound/pci/fm801.c +++ /dev/null @@ -1,1441 +0,0 @@ -/* - * The driver for the ForteMedia FM801 based soundcards - * Copyright (c) by Jaroslav Kysela - * - * Support FM only card by Andy Shevchenko - * - * 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 -#include -#include -#include -#include - -#include - -#ifdef CONFIG_SND_FM801_TEA575X_BOOL -#include -#endif - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("ForteMedia FM801"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801}," - "{Genius,SoundMaker Live 5.1}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -/* - * Enable TEA575x tuner - * 1 = MediaForte 256-PCS - * 2 = MediaForte 256-PCP - * 3 = MediaForte 64-PCR - * 16 = setup tuner only (this is additional bit), i.e. SF64-PCR FM card - * High 16-bits are video (radio) device number + 1 - */ -static int tea575x_tuner[SNDRV_CARDS]; -static int radio_nr[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the FM801 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable FM801 soundcard."); -module_param_array(tea575x_tuner, int, NULL, 0444); -MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only)."); -module_param_array(radio_nr, int, NULL, 0444); -MODULE_PARM_DESC(radio_nr, "Radio device numbers"); - - -#define TUNER_DISABLED (1<<3) -#define TUNER_ONLY (1<<4) -#define TUNER_TYPE_MASK (~TUNER_ONLY & 0xFFFF) - -/* - * Direct registers - */ - -#define FM801_REG(chip, reg) (chip->port + FM801_##reg) - -#define FM801_PCM_VOL 0x00 /* PCM Output Volume */ -#define FM801_FM_VOL 0x02 /* FM Output Volume */ -#define FM801_I2S_VOL 0x04 /* I2S Volume */ -#define FM801_REC_SRC 0x06 /* Record Source */ -#define FM801_PLY_CTRL 0x08 /* Playback Control */ -#define FM801_PLY_COUNT 0x0a /* Playback Count */ -#define FM801_PLY_BUF1 0x0c /* Playback Bufer I */ -#define FM801_PLY_BUF2 0x10 /* Playback Buffer II */ -#define FM801_CAP_CTRL 0x14 /* Capture Control */ -#define FM801_CAP_COUNT 0x16 /* Capture Count */ -#define FM801_CAP_BUF1 0x18 /* Capture Buffer I */ -#define FM801_CAP_BUF2 0x1c /* Capture Buffer II */ -#define FM801_CODEC_CTRL 0x22 /* Codec Control */ -#define FM801_I2S_MODE 0x24 /* I2S Mode Control */ -#define FM801_VOLUME 0x26 /* Volume Up/Down/Mute Status */ -#define FM801_I2C_CTRL 0x29 /* I2C Control */ -#define FM801_AC97_CMD 0x2a /* AC'97 Command */ -#define FM801_AC97_DATA 0x2c /* AC'97 Data */ -#define FM801_MPU401_DATA 0x30 /* MPU401 Data */ -#define FM801_MPU401_CMD 0x31 /* MPU401 Command */ -#define FM801_GPIO_CTRL 0x52 /* General Purpose I/O Control */ -#define FM801_GEN_CTRL 0x54 /* General Control */ -#define FM801_IRQ_MASK 0x56 /* Interrupt Mask */ -#define FM801_IRQ_STATUS 0x5a /* Interrupt Status */ -#define FM801_OPL3_BANK0 0x68 /* OPL3 Status Read / Bank 0 Write */ -#define FM801_OPL3_DATA0 0x69 /* OPL3 Data 0 Write */ -#define FM801_OPL3_BANK1 0x6a /* OPL3 Bank 1 Write */ -#define FM801_OPL3_DATA1 0x6b /* OPL3 Bank 1 Write */ -#define FM801_POWERDOWN 0x70 /* Blocks Power Down Control */ - -/* codec access */ -#define FM801_AC97_READ (1<<7) /* read=1, write=0 */ -#define FM801_AC97_VALID (1<<8) /* port valid=1 */ -#define FM801_AC97_BUSY (1<<9) /* busy=1 */ -#define FM801_AC97_ADDR_SHIFT 10 /* codec id (2bit) */ - -/* playback and record control register bits */ -#define FM801_BUF1_LAST (1<<1) -#define FM801_BUF2_LAST (1<<2) -#define FM801_START (1<<5) -#define FM801_PAUSE (1<<6) -#define FM801_IMMED_STOP (1<<7) -#define FM801_RATE_SHIFT 8 -#define FM801_RATE_MASK (15 << FM801_RATE_SHIFT) -#define FM801_CHANNELS_4 (1<<12) /* playback only */ -#define FM801_CHANNELS_6 (2<<12) /* playback only */ -#define FM801_CHANNELS_6MS (3<<12) /* playback only */ -#define FM801_CHANNELS_MASK (3<<12) -#define FM801_16BIT (1<<14) -#define FM801_STEREO (1<<15) - -/* IRQ status bits */ -#define FM801_IRQ_PLAYBACK (1<<8) -#define FM801_IRQ_CAPTURE (1<<9) -#define FM801_IRQ_VOLUME (1<<14) -#define FM801_IRQ_MPU (1<<15) - -/* GPIO control register */ -#define FM801_GPIO_GP0 (1<<0) /* read/write */ -#define FM801_GPIO_GP1 (1<<1) -#define FM801_GPIO_GP2 (1<<2) -#define FM801_GPIO_GP3 (1<<3) -#define FM801_GPIO_GP(x) (1<<(0+(x))) -#define FM801_GPIO_GD0 (1<<8) /* directions: 1 = input, 0 = output*/ -#define FM801_GPIO_GD1 (1<<9) -#define FM801_GPIO_GD2 (1<<10) -#define FM801_GPIO_GD3 (1<<11) -#define FM801_GPIO_GD(x) (1<<(8+(x))) -#define FM801_GPIO_GS0 (1<<12) /* function select: */ -#define FM801_GPIO_GS1 (1<<13) /* 1 = GPIO */ -#define FM801_GPIO_GS2 (1<<14) /* 0 = other (S/PDIF, VOL) */ -#define FM801_GPIO_GS3 (1<<15) -#define FM801_GPIO_GS(x) (1<<(12+(x))) - -/* - - */ - -struct fm801 { - int irq; - - unsigned long port; /* I/O port number */ - unsigned int multichannel: 1, /* multichannel support */ - secondary: 1; /* secondary codec */ - unsigned char secondary_addr; /* address of the secondary codec */ - unsigned int tea575x_tuner; /* tuner access method & flags */ - - unsigned short ply_ctrl; /* playback control */ - unsigned short cap_ctrl; /* capture control */ - - unsigned long ply_buffer; - unsigned int ply_buf; - unsigned int ply_count; - unsigned int ply_size; - unsigned int ply_pos; - - unsigned long cap_buffer; - unsigned int cap_buf; - unsigned int cap_count; - unsigned int cap_size; - unsigned int cap_pos; - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97; - struct snd_ac97 *ac97_sec; - - struct pci_dev *pci; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_rawmidi *rmidi; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - unsigned int p_dma_size; - unsigned int c_dma_size; - - spinlock_t reg_lock; - struct snd_info_entry *proc_entry; - -#ifdef CONFIG_SND_FM801_TEA575X_BOOL - struct v4l2_device v4l2_dev; - struct snd_tea575x tea; -#endif - -#ifdef CONFIG_PM - u16 saved_regs[0x20]; -#endif -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_fm801_ids) = { - { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */ - { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_fm801_ids); - -/* - * common I/O routines - */ - -static int snd_fm801_update_bits(struct fm801 *chip, unsigned short reg, - unsigned short mask, unsigned short value) -{ - int change; - unsigned long flags; - unsigned short old, new; - - spin_lock_irqsave(&chip->reg_lock, flags); - old = inw(chip->port + reg); - new = (old & ~mask) | value; - change = old != new; - if (change) - outw(new, chip->port + reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static void snd_fm801_codec_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct fm801 *chip = ac97->private_data; - int idx; - - /* - * Wait until the codec interface is not ready.. - */ - for (idx = 0; idx < 100; idx++) { - if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY)) - goto ok1; - udelay(10); - } - snd_printk(KERN_ERR "AC'97 interface is busy (1)\n"); - return; - - ok1: - /* write data and address */ - outw(val, FM801_REG(chip, AC97_DATA)); - outw(reg | (ac97->addr << FM801_AC97_ADDR_SHIFT), FM801_REG(chip, AC97_CMD)); - /* - * Wait until the write command is not completed.. - */ - for (idx = 0; idx < 1000; idx++) { - if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY)) - return; - udelay(10); - } - snd_printk(KERN_ERR "AC'97 interface #%d is busy (2)\n", ac97->num); -} - -static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct fm801 *chip = ac97->private_data; - int idx; - - /* - * Wait until the codec interface is not ready.. - */ - for (idx = 0; idx < 100; idx++) { - if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY)) - goto ok1; - udelay(10); - } - snd_printk(KERN_ERR "AC'97 interface is busy (1)\n"); - return 0; - - ok1: - /* read command */ - outw(reg | (ac97->addr << FM801_AC97_ADDR_SHIFT) | FM801_AC97_READ, - FM801_REG(chip, AC97_CMD)); - for (idx = 0; idx < 100; idx++) { - if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY)) - goto ok2; - udelay(10); - } - snd_printk(KERN_ERR "AC'97 interface #%d is busy (2)\n", ac97->num); - return 0; - - ok2: - for (idx = 0; idx < 1000; idx++) { - if (inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_VALID) - goto ok3; - udelay(10); - } - snd_printk(KERN_ERR "AC'97 interface #%d is not valid (2)\n", ac97->num); - return 0; - - ok3: - return inw(FM801_REG(chip, AC97_DATA)); -} - -static unsigned int rates[] = { - 5500, 8000, 9600, 11025, - 16000, 19200, 22050, 32000, - 38400, 44100, 48000 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static unsigned int channels[] = { - 2, 4, 6 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, -}; - -/* - * Sample rate routines - */ - -static unsigned short snd_fm801_rate_bits(unsigned int rate) -{ - unsigned int idx; - - for (idx = 0; idx < ARRAY_SIZE(rates); idx++) - if (rates[idx] == rate) - return idx; - snd_BUG(); - return ARRAY_SIZE(rates) - 1; -} - -/* - * PCM part - */ - -static int snd_fm801_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - chip->ply_ctrl &= ~(FM801_BUF1_LAST | - FM801_BUF2_LAST | - FM801_PAUSE); - chip->ply_ctrl |= FM801_START | - FM801_IMMED_STOP; - break; - case SNDRV_PCM_TRIGGER_STOP: - chip->ply_ctrl &= ~(FM801_START | FM801_PAUSE); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - chip->ply_ctrl |= FM801_PAUSE; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - chip->ply_ctrl &= ~FM801_PAUSE; - break; - default: - spin_unlock(&chip->reg_lock); - snd_BUG(); - return -EINVAL; - } - outw(chip->ply_ctrl, FM801_REG(chip, PLY_CTRL)); - spin_unlock(&chip->reg_lock); - return 0; -} - -static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - chip->cap_ctrl &= ~(FM801_BUF1_LAST | - FM801_BUF2_LAST | - FM801_PAUSE); - chip->cap_ctrl |= FM801_START | - FM801_IMMED_STOP; - break; - case SNDRV_PCM_TRIGGER_STOP: - chip->cap_ctrl &= ~(FM801_START | FM801_PAUSE); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - chip->cap_ctrl |= FM801_PAUSE; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - chip->cap_ctrl &= ~FM801_PAUSE; - break; - default: - spin_unlock(&chip->reg_lock); - snd_BUG(); - return -EINVAL; - } - outw(chip->cap_ctrl, FM801_REG(chip, CAP_CTRL)); - spin_unlock(&chip->reg_lock); - return 0; -} - -static int snd_fm801_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_fm801_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - chip->ply_size = snd_pcm_lib_buffer_bytes(substream); - chip->ply_count = snd_pcm_lib_period_bytes(substream); - spin_lock_irq(&chip->reg_lock); - chip->ply_ctrl &= ~(FM801_START | FM801_16BIT | - FM801_STEREO | FM801_RATE_MASK | - FM801_CHANNELS_MASK); - if (snd_pcm_format_width(runtime->format) == 16) - chip->ply_ctrl |= FM801_16BIT; - if (runtime->channels > 1) { - chip->ply_ctrl |= FM801_STEREO; - if (runtime->channels == 4) - chip->ply_ctrl |= FM801_CHANNELS_4; - else if (runtime->channels == 6) - chip->ply_ctrl |= FM801_CHANNELS_6; - } - chip->ply_ctrl |= snd_fm801_rate_bits(runtime->rate) << FM801_RATE_SHIFT; - chip->ply_buf = 0; - outw(chip->ply_ctrl, FM801_REG(chip, PLY_CTRL)); - outw(chip->ply_count - 1, FM801_REG(chip, PLY_COUNT)); - chip->ply_buffer = runtime->dma_addr; - chip->ply_pos = 0; - outl(chip->ply_buffer, FM801_REG(chip, PLY_BUF1)); - outl(chip->ply_buffer + (chip->ply_count % chip->ply_size), FM801_REG(chip, PLY_BUF2)); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_fm801_capture_prepare(struct snd_pcm_substream *substream) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - chip->cap_size = snd_pcm_lib_buffer_bytes(substream); - chip->cap_count = snd_pcm_lib_period_bytes(substream); - spin_lock_irq(&chip->reg_lock); - chip->cap_ctrl &= ~(FM801_START | FM801_16BIT | - FM801_STEREO | FM801_RATE_MASK); - if (snd_pcm_format_width(runtime->format) == 16) - chip->cap_ctrl |= FM801_16BIT; - if (runtime->channels > 1) - chip->cap_ctrl |= FM801_STEREO; - chip->cap_ctrl |= snd_fm801_rate_bits(runtime->rate) << FM801_RATE_SHIFT; - chip->cap_buf = 0; - outw(chip->cap_ctrl, FM801_REG(chip, CAP_CTRL)); - outw(chip->cap_count - 1, FM801_REG(chip, CAP_COUNT)); - chip->cap_buffer = runtime->dma_addr; - chip->cap_pos = 0; - outl(chip->cap_buffer, FM801_REG(chip, CAP_BUF1)); - outl(chip->cap_buffer + (chip->cap_count % chip->cap_size), FM801_REG(chip, CAP_BUF2)); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static snd_pcm_uframes_t snd_fm801_playback_pointer(struct snd_pcm_substream *substream) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(chip->ply_ctrl & FM801_START)) - return 0; - spin_lock(&chip->reg_lock); - ptr = chip->ply_pos + (chip->ply_count - 1) - inw(FM801_REG(chip, PLY_COUNT)); - if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_PLAYBACK) { - ptr += chip->ply_count; - ptr %= chip->ply_size; - } - spin_unlock(&chip->reg_lock); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_fm801_capture_pointer(struct snd_pcm_substream *substream) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(chip->cap_ctrl & FM801_START)) - return 0; - spin_lock(&chip->reg_lock); - ptr = chip->cap_pos + (chip->cap_count - 1) - inw(FM801_REG(chip, CAP_COUNT)); - if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_CAPTURE) { - ptr += chip->cap_count; - ptr %= chip->cap_size; - } - spin_unlock(&chip->reg_lock); - return bytes_to_frames(substream->runtime, ptr); -} - -static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id) -{ - struct fm801 *chip = dev_id; - unsigned short status; - unsigned int tmp; - - status = inw(FM801_REG(chip, IRQ_STATUS)); - status &= FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU|FM801_IRQ_VOLUME; - if (! status) - return IRQ_NONE; - /* ack first */ - outw(status, FM801_REG(chip, IRQ_STATUS)); - if (chip->pcm && (status & FM801_IRQ_PLAYBACK) && chip->playback_substream) { - spin_lock(&chip->reg_lock); - chip->ply_buf++; - chip->ply_pos += chip->ply_count; - chip->ply_pos %= chip->ply_size; - tmp = chip->ply_pos + chip->ply_count; - tmp %= chip->ply_size; - outl(chip->ply_buffer + tmp, - (chip->ply_buf & 1) ? - FM801_REG(chip, PLY_BUF1) : - FM801_REG(chip, PLY_BUF2)); - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(chip->playback_substream); - } - if (chip->pcm && (status & FM801_IRQ_CAPTURE) && chip->capture_substream) { - spin_lock(&chip->reg_lock); - chip->cap_buf++; - chip->cap_pos += chip->cap_count; - chip->cap_pos %= chip->cap_size; - tmp = chip->cap_pos + chip->cap_count; - tmp %= chip->cap_size; - outl(chip->cap_buffer + tmp, - (chip->cap_buf & 1) ? - FM801_REG(chip, CAP_BUF1) : - FM801_REG(chip, CAP_BUF2)); - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(chip->capture_substream); - } - if (chip->rmidi && (status & FM801_IRQ_MPU)) - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - if (status & FM801_IRQ_VOLUME) - ;/* TODO */ - - return IRQ_HANDLED; -} - -static struct snd_pcm_hardware snd_fm801_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5500, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_fm801_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5500, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_fm801_playback_open(struct snd_pcm_substream *substream) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - chip->playback_substream = substream; - runtime->hw = snd_fm801_playback; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates); - if (chip->multichannel) { - runtime->hw.channels_max = 6; - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &hw_constraints_channels); - } - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - return 0; -} - -static int snd_fm801_capture_open(struct snd_pcm_substream *substream) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - chip->capture_substream = substream; - runtime->hw = snd_fm801_capture; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates); - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - return 0; -} - -static int snd_fm801_playback_close(struct snd_pcm_substream *substream) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - return 0; -} - -static int snd_fm801_capture_close(struct snd_pcm_substream *substream) -{ - struct fm801 *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_fm801_playback_ops = { - .open = snd_fm801_playback_open, - .close = snd_fm801_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_fm801_hw_params, - .hw_free = snd_fm801_hw_free, - .prepare = snd_fm801_playback_prepare, - .trigger = snd_fm801_playback_trigger, - .pointer = snd_fm801_playback_pointer, -}; - -static struct snd_pcm_ops snd_fm801_capture_ops = { - .open = snd_fm801_capture_open, - .close = snd_fm801_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_fm801_hw_params, - .hw_free = snd_fm801_hw_free, - .prepare = snd_fm801_capture_prepare, - .trigger = snd_fm801_capture_trigger, - .pointer = snd_fm801_capture_pointer, -}; - -static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm)) < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_fm801_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_fm801_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, "FM801"); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - chip->multichannel ? 128*1024 : 64*1024, 128*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* - * TEA5757 radio - */ - -#ifdef CONFIG_SND_FM801_TEA575X_BOOL - -/* GPIO to TEA575x maps */ -struct snd_fm801_tea575x_gpio { - u8 data, clk, wren, most; - char *name; -}; - -static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = { - { .data = 1, .clk = 3, .wren = 2, .most = 0, .name = "SF256-PCS" }, - { .data = 1, .clk = 0, .wren = 2, .most = 3, .name = "SF256-PCP" }, - { .data = 2, .clk = 0, .wren = 1, .most = 3, .name = "SF64-PCR" }, -}; - -#define get_tea575x_gpio(chip) \ - (&snd_fm801_tea575x_gpios[((chip)->tea575x_tuner & TUNER_TYPE_MASK) - 1]) - -static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) -{ - struct fm801 *chip = tea->private_data; - unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); - struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); - - reg &= ~(FM801_GPIO_GP(gpio.data) | - FM801_GPIO_GP(gpio.clk) | - FM801_GPIO_GP(gpio.wren)); - - reg |= (pins & TEA575X_DATA) ? FM801_GPIO_GP(gpio.data) : 0; - reg |= (pins & TEA575X_CLK) ? FM801_GPIO_GP(gpio.clk) : 0; - /* WRITE_ENABLE is inverted */ - reg |= (pins & TEA575X_WREN) ? 0 : FM801_GPIO_GP(gpio.wren); - - outw(reg, FM801_REG(chip, GPIO_CTRL)); -} - -static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea) -{ - struct fm801 *chip = tea->private_data; - unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); - struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); - - return (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 | - (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0; -} - -static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output) -{ - struct fm801 *chip = tea->private_data; - unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); - struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); - - /* use GPIO lines and set write enable bit */ - reg |= FM801_GPIO_GS(gpio.data) | - FM801_GPIO_GS(gpio.wren) | - FM801_GPIO_GS(gpio.clk) | - FM801_GPIO_GS(gpio.most); - if (output) { - /* all of lines are in the write direction */ - /* clear data and clock lines */ - reg &= ~(FM801_GPIO_GD(gpio.data) | - FM801_GPIO_GD(gpio.wren) | - FM801_GPIO_GD(gpio.clk) | - FM801_GPIO_GP(gpio.data) | - FM801_GPIO_GP(gpio.clk) | - FM801_GPIO_GP(gpio.wren)); - } else { - /* use GPIO lines, set data direction to input */ - reg |= FM801_GPIO_GD(gpio.data) | - FM801_GPIO_GD(gpio.most) | - FM801_GPIO_GP(gpio.data) | - FM801_GPIO_GP(gpio.most) | - FM801_GPIO_GP(gpio.wren); - /* all of lines are in the write direction, except data */ - /* clear data, write enable and clock lines */ - reg &= ~(FM801_GPIO_GD(gpio.wren) | - FM801_GPIO_GD(gpio.clk) | - FM801_GPIO_GP(gpio.clk)); - } - - outw(reg, FM801_REG(chip, GPIO_CTRL)); -} - -static struct snd_tea575x_ops snd_fm801_tea_ops = { - .set_pins = snd_fm801_tea575x_set_pins, - .get_pins = snd_fm801_tea575x_get_pins, - .set_direction = snd_fm801_tea575x_set_direction, -}; -#endif - -/* - * Mixer routines - */ - -#define FM801_SINGLE(xname, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_fm801_info_single, \ - .get = snd_fm801_get_single, .put = snd_fm801_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_fm801_info_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_fm801_get_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct fm801 *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - ucontrol->value.integer.value[0] = (inw(chip->port + reg) >> shift) & mask; - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_fm801_put_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct fm801 *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - return snd_fm801_update_bits(chip, reg, mask << shift, val << shift); -} - -#define FM801_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_fm801_info_double, \ - .get = snd_fm801_get_double, .put = snd_fm801_put_double, \ - .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) } -#define FM801_DOUBLE_TLV(xname, reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .info = snd_fm801_info_double, \ - .get = snd_fm801_get_double, .put = snd_fm801_put_double, \ - .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - -static int snd_fm801_info_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_fm801_get_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct fm801 *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irq(&chip->reg_lock); - ucontrol->value.integer.value[0] = (inw(chip->port + reg) >> shift_left) & mask; - ucontrol->value.integer.value[1] = (inw(chip->port + reg) >> shift_right) & mask; - spin_unlock_irq(&chip->reg_lock); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_fm801_put_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct fm801 *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - return snd_fm801_update_bits(chip, reg, - (mask << shift_left) | (mask << shift_right), - (val1 << shift_left ) | (val2 << shift_right)); -} - -static int snd_fm801_info_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[5] = { - "AC97 Primary", "FM", "I2S", "PCM", "AC97 Secondary" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_fm801_get_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct fm801 *chip = snd_kcontrol_chip(kcontrol); - unsigned short val; - - val = inw(FM801_REG(chip, REC_SRC)) & 7; - if (val > 4) - val = 4; - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -static int snd_fm801_put_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct fm801 *chip = snd_kcontrol_chip(kcontrol); - unsigned short val; - - if ((val = ucontrol->value.enumerated.item[0]) > 4) - return -EINVAL; - return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val); -} - -static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0); - -#define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls) - -static struct snd_kcontrol_new snd_fm801_controls[] __devinitdata = { -FM801_DOUBLE_TLV("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1, - db_scale_dsp), -FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1), -FM801_DOUBLE_TLV("I2S Playback Volume", FM801_I2S_VOL, 0, 8, 31, 1, - db_scale_dsp), -FM801_SINGLE("I2S Playback Switch", FM801_I2S_VOL, 15, 1, 1), -FM801_DOUBLE_TLV("FM Playback Volume", FM801_FM_VOL, 0, 8, 31, 1, - db_scale_dsp), -FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Capture Source", - .info = snd_fm801_info_mux, - .get = snd_fm801_get_mux, - .put = snd_fm801_put_mux, -} -}; - -#define FM801_CONTROLS_MULTI ARRAY_SIZE(snd_fm801_controls_multi) - -static struct snd_kcontrol_new snd_fm801_controls_multi[] __devinitdata = { -FM801_SINGLE("AC97 2ch->4ch Copy Switch", FM801_CODEC_CTRL, 7, 1, 0), -FM801_SINGLE("AC97 18-bit Switch", FM801_CODEC_CTRL, 10, 1, 0), -FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), FM801_I2S_MODE, 8, 1, 0), -FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",PLAYBACK,SWITCH), FM801_I2S_MODE, 9, 1, 0), -FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",CAPTURE,SWITCH), FM801_I2S_MODE, 10, 1, 0), -FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), FM801_GEN_CTRL, 2, 1, 0), -}; - -static void snd_fm801_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct fm801 *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct fm801 *chip = ac97->private_data; - if (ac97->num == 0) { - chip->ac97 = NULL; - } else { - chip->ac97_sec = NULL; - } -} - -static int __devinit snd_fm801_mixer(struct fm801 *chip) -{ - struct snd_ac97_template ac97; - unsigned int i; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_fm801_codec_write, - .read = snd_fm801_codec_read, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) - return err; - chip->ac97_bus->private_free = snd_fm801_mixer_free_ac97_bus; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_fm801_mixer_free_ac97; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) - return err; - if (chip->secondary) { - ac97.num = 1; - ac97.addr = chip->secondary_addr; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_sec)) < 0) - return err; - } - for (i = 0; i < FM801_CONTROLS; i++) - snd_ctl_add(chip->card, snd_ctl_new1(&snd_fm801_controls[i], chip)); - if (chip->multichannel) { - for (i = 0; i < FM801_CONTROLS_MULTI; i++) - snd_ctl_add(chip->card, snd_ctl_new1(&snd_fm801_controls_multi[i], chip)); - } - return 0; -} - -/* - * initialization routines - */ - -static int wait_for_codec(struct fm801 *chip, unsigned int codec_id, - unsigned short reg, unsigned long waits) -{ - unsigned long timeout = jiffies + waits; - - outw(FM801_AC97_READ | (codec_id << FM801_AC97_ADDR_SHIFT) | reg, - FM801_REG(chip, AC97_CMD)); - udelay(5); - do { - if ((inw(FM801_REG(chip, AC97_CMD)) & (FM801_AC97_VALID|FM801_AC97_BUSY)) - == FM801_AC97_VALID) - return 0; - schedule_timeout_uninterruptible(1); - } while (time_after(timeout, jiffies)); - return -EIO; -} - -static int snd_fm801_chip_init(struct fm801 *chip, int resume) -{ - unsigned short cmdw; - - if (chip->tea575x_tuner & TUNER_ONLY) - goto __ac97_ok; - - /* codec cold reset + AC'97 warm reset */ - outw((1<<5) | (1<<6), FM801_REG(chip, CODEC_CTRL)); - inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */ - udelay(100); - outw(0, FM801_REG(chip, CODEC_CTRL)); - - if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0) - if (!resume) { - snd_printk(KERN_INFO "Primary AC'97 codec not found, " - "assume SF64-PCR (tuner-only)\n"); - chip->tea575x_tuner = 3 | TUNER_ONLY; - goto __ac97_ok; - } - - if (chip->multichannel) { - if (chip->secondary_addr) { - wait_for_codec(chip, chip->secondary_addr, - AC97_VENDOR_ID1, msecs_to_jiffies(50)); - } else { - /* my card has the secondary codec */ - /* at address #3, so the loop is inverted */ - int i; - for (i = 3; i > 0; i--) { - if (!wait_for_codec(chip, i, AC97_VENDOR_ID1, - msecs_to_jiffies(50))) { - cmdw = inw(FM801_REG(chip, AC97_DATA)); - if (cmdw != 0xffff && cmdw != 0) { - chip->secondary = 1; - chip->secondary_addr = i; - break; - } - } - } - } - - /* the recovery phase, it seems that probing for non-existing codec might */ - /* cause timeout problems */ - wait_for_codec(chip, 0, AC97_VENDOR_ID1, msecs_to_jiffies(750)); - } - - __ac97_ok: - - /* init volume */ - outw(0x0808, FM801_REG(chip, PCM_VOL)); - outw(0x9f1f, FM801_REG(chip, FM_VOL)); - outw(0x8808, FM801_REG(chip, I2S_VOL)); - - /* I2S control - I2S mode */ - outw(0x0003, FM801_REG(chip, I2S_MODE)); - - /* interrupt setup */ - cmdw = inw(FM801_REG(chip, IRQ_MASK)); - if (chip->irq < 0) - cmdw |= 0x00c3; /* mask everything, no PCM nor MPU */ - else - cmdw &= ~0x0083; /* unmask MPU, PLAYBACK & CAPTURE */ - outw(cmdw, FM801_REG(chip, IRQ_MASK)); - - /* interrupt clear */ - outw(FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU, FM801_REG(chip, IRQ_STATUS)); - - return 0; -} - - -static int snd_fm801_free(struct fm801 *chip) -{ - unsigned short cmdw; - - if (chip->irq < 0) - goto __end_hw; - - /* interrupt setup - mask everything */ - cmdw = inw(FM801_REG(chip, IRQ_MASK)); - cmdw |= 0x00c3; - outw(cmdw, FM801_REG(chip, IRQ_MASK)); - - __end_hw: -#ifdef CONFIG_SND_FM801_TEA575X_BOOL - if (!(chip->tea575x_tuner & TUNER_DISABLED)) { - snd_tea575x_exit(&chip->tea); - v4l2_device_unregister(&chip->v4l2_dev); - } -#endif - if (chip->irq >= 0) - free_irq(chip->irq, chip); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - - kfree(chip); - return 0; -} - -static int snd_fm801_dev_free(struct snd_device *device) -{ - struct fm801 *chip = device->device_data; - return snd_fm801_free(chip); -} - -static int __devinit snd_fm801_create(struct snd_card *card, - struct pci_dev * pci, - int tea575x_tuner, - int radio_nr, - struct fm801 ** rchip) -{ - struct fm801 *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_fm801_dev_free, - }; - - *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) - return err; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&chip->reg_lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - chip->tea575x_tuner = tea575x_tuner; - if ((err = pci_request_regions(pci, "FM801")) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->port = pci_resource_start(pci, 0); - if ((tea575x_tuner & TUNER_ONLY) == 0) { - if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); - snd_fm801_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - pci_set_master(pci); - } - - if (pci->revision >= 0xb1) /* FM801-AU */ - chip->multichannel = 1; - - snd_fm801_chip_init(chip, 0); - /* init might set tuner access method */ - tea575x_tuner = chip->tea575x_tuner; - - if (chip->irq >= 0 && (tea575x_tuner & TUNER_ONLY)) { - pci_clear_master(pci); - free_irq(chip->irq, chip); - chip->irq = -1; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_fm801_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - -#ifdef CONFIG_SND_FM801_TEA575X_BOOL - err = v4l2_device_register(&pci->dev, &chip->v4l2_dev); - if (err < 0) { - snd_fm801_free(chip); - return err; - } - chip->tea.v4l2_dev = &chip->v4l2_dev; - chip->tea.radio_nr = radio_nr; - chip->tea.private_data = chip; - chip->tea.ops = &snd_fm801_tea_ops; - sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci)); - if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 && - (tea575x_tuner & TUNER_TYPE_MASK) < 4) { - if (snd_tea575x_init(&chip->tea)) { - snd_printk(KERN_ERR "TEA575x radio not found\n"); - snd_fm801_free(chip); - return -ENODEV; - } - } else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) { - /* autodetect tuner connection */ - for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) { - chip->tea575x_tuner = tea575x_tuner; - if (!snd_tea575x_init(&chip->tea)) { - snd_printk(KERN_INFO "detected TEA575x radio type %s\n", - get_tea575x_gpio(chip)->name); - break; - } - } - if (tea575x_tuner == 4) { - snd_printk(KERN_ERR "TEA575x radio not found\n"); - chip->tea575x_tuner = TUNER_DISABLED; - } - } - if (!(chip->tea575x_tuner & TUNER_DISABLED)) { - strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name, - sizeof(chip->tea.card)); - } -#endif - - *rchip = chip; - return 0; -} - -static int __devinit snd_card_fm801_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct fm801 *chip; - struct snd_opl3 *opl3; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - strcpy(card->driver, "FM801"); - strcpy(card->shortname, "ForteMedia FM801-"); - strcat(card->shortname, chip->multichannel ? "AU" : "AS"); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, chip->port, chip->irq); - - if (chip->tea575x_tuner & TUNER_ONLY) - goto __fm801_tuner_only; - - if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_fm801_mixer(chip)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, - FM801_REG(chip, MPU401_DATA), - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_opl3_create(card, FM801_REG(chip, OPL3_BANK0), - FM801_REG(chip, OPL3_BANK1), - OPL3_HW_OPL3_FM801, 1, &opl3)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - - __fm801_tuner_only: - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_card_fm801_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -#ifdef CONFIG_PM -static unsigned char saved_regs[] = { - FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC, - FM801_PLY_CTRL, FM801_PLY_COUNT, FM801_PLY_BUF1, FM801_PLY_BUF2, - FM801_CAP_CTRL, FM801_CAP_COUNT, FM801_CAP_BUF1, FM801_CAP_BUF2, - FM801_CODEC_CTRL, FM801_I2S_MODE, FM801_VOLUME, FM801_GEN_CTRL, -}; - -static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct fm801 *chip = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_ac97_suspend(chip->ac97); - snd_ac97_suspend(chip->ac97_sec); - for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - chip->saved_regs[i] = inw(chip->port + saved_regs[i]); - /* FIXME: tea575x suspend */ - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_fm801_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct fm801 *chip = card->private_data; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "fm801: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_fm801_chip_init(chip, 1); - snd_ac97_resume(chip->ac97); - snd_ac97_resume(chip->ac97_sec); - for (i = 0; i < ARRAY_SIZE(saved_regs); i++) - outw(chip->saved_regs[i], chip->port + saved_regs[i]); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_fm801_ids, - .probe = snd_card_fm801_probe, - .remove = __devexit_p(snd_card_fm801_remove), -#ifdef CONFIG_PM - .suspend = snd_fm801_suspend, - .resume = snd_fm801_resume, -#endif -}; - -static int __init alsa_card_fm801_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_fm801_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_fm801_init) -module_exit(alsa_card_fm801_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/Kconfig b/ANDROID_3.4.5/sound/pci/hda/Kconfig deleted file mode 100644 index 163b6b5d..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/Kconfig +++ /dev/null @@ -1,261 +0,0 @@ -menuconfig SND_HDA_INTEL - tristate "Intel HD Audio" - select SND_PCM - select SND_VMASTER - select SND_KCTL_JACK - help - Say Y here to include support for Intel "High Definition - Audio" (Azalia) and its compatible devices. - - This option enables the HD-audio controller. Don't forget - to choose the appropriate codec options below. - - To compile this driver as a module, choose M here: the module - will be called snd-hda-intel. - -if SND_HDA_INTEL - -config SND_HDA_PREALLOC_SIZE - int "Pre-allocated buffer size for HD-audio driver" - range 0 32768 - default 64 - help - Specifies the default pre-allocated buffer-size in kB for the - HD-audio driver. A larger buffer (e.g. 2048) is preferred - for systems using PulseAudio. The default 64 is chosen just - for compatibility reasons. - - Note that the pre-allocation size can be changed dynamically - via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too. - -config SND_HDA_HWDEP - bool "Build hwdep interface for HD-audio driver" - select SND_HWDEP - help - Say Y here to build a hwdep interface for HD-audio driver. - This interface can be used for out-of-band communication - with codecs for debugging purposes. - -config SND_HDA_RECONFIG - bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)" - depends on SND_HDA_HWDEP && EXPERIMENTAL - help - Say Y here to enable the HD-audio codec re-configuration feature. - This adds the sysfs interfaces to allow user to clear the whole - codec configuration, change the codec setup, add extra verbs, - and re-configure the codec dynamically. - -config SND_HDA_INPUT_BEEP - bool "Support digital beep via input layer" - depends on INPUT=y || INPUT=SND_HDA_INTEL - help - Say Y here to build a digital beep interface for HD-audio - driver. This interface is used to generate digital beeps. - -config SND_HDA_INPUT_BEEP_MODE - int "Digital beep registration mode (0=off, 1=on, 2=mute sw on/off)" - depends on SND_HDA_INPUT_BEEP=y - default "1" - range 0 2 - help - Set 0 to disable the digital beep interface for HD-audio by default. - Set 1 to always enable the digital beep interface for HD-audio by - default. Set 2 to control the beep device registration to input - layer using a "Beep Switch" in mixer applications. - -config SND_HDA_INPUT_JACK - bool "Support jack plugging notification via input layer" - depends on INPUT=y || INPUT=SND - select SND_JACK - help - Say Y here to enable the jack plugging notification via - input layer. - -config SND_HDA_PATCH_LOADER - bool "Support initialization patch loading for HD-audio" - depends on EXPERIMENTAL - select FW_LOADER - select SND_HDA_HWDEP - select SND_HDA_RECONFIG - help - Say Y here to allow the HD-audio driver to load a pseudo - firmware file ("patch") for overriding the BIOS setup at - start up. The "patch" file can be specified via patch module - option, such as patch=hda-init. - - This option turns on hwdep and reconfig features automatically. - -config SND_HDA_CODEC_REALTEK - bool "Build Realtek HD-audio codec support" - default y - help - Say Y here to include Realtek HD-audio codec support in - snd-hda-intel driver, such as ALC880. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-realtek. - This module is automatically loaded at probing. - -config SND_HDA_ENABLE_REALTEK_QUIRKS - bool "Build static quirks for Realtek codecs" - depends on SND_HDA_CODEC_REALTEK - default y - help - Say Y here to build the static quirks codes for Realtek codecs. - If you need the "model" preset that the default BIOS auto-parser - can't handle, turn this option on. - - If your device works with model=auto option, basically you don't - need the quirk code. By turning this off, you can reduce the - module size quite a lot. - -config SND_HDA_CODEC_ANALOG - bool "Build Analog Device HD-audio codec support" - default y - help - Say Y here to include Analog Device HD-audio codec support in - snd-hda-intel driver, such as AD1986A. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-analog. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_SIGMATEL - bool "Build IDT/Sigmatel HD-audio codec support" - default y - help - Say Y here to include IDT (Sigmatel) HD-audio codec support in - snd-hda-intel driver, such as STAC9200. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-idt. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_VIA - bool "Build VIA HD-audio codec support" - default y - help - Say Y here to include VIA HD-audio codec support in - snd-hda-intel driver, such as VT1708. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-via. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_HDMI - bool "Build HDMI/DisplayPort HD-audio codec support" - select SND_DYNAMIC_MINORS - default y - help - Say Y here to include HDMI and DisplayPort HD-audio codec - support in snd-hda-intel driver. This includes all AMD/ATI, - Intel and Nvidia HDMI/DisplayPort codecs. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-hdmi. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_CIRRUS - bool "Build Cirrus Logic codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include Cirrus Logic codec support in - snd-hda-intel driver, such as CS4206. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-cirrus. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_CONEXANT - bool "Build Conexant HD-audio codec support" - default y - help - Say Y here to include Conexant HD-audio codec support in - snd-hda-intel driver, such as CX20549. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-conexant. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_CA0110 - bool "Build Creative CA0110-IBG codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include Creative CA0110-IBG codec support in - snd-hda-intel driver, found on some Creative X-Fi cards. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-ca0110. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_CA0132 - bool "Build Creative CA0132 codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include Creative CA0132 codec support in - snd-hda-intel driver. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-ca0132. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_CMEDIA - bool "Build C-Media HD-audio codec support" - default y - help - Say Y here to include C-Media HD-audio codec support in - snd-hda-intel driver, such as CMI9880. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-cmedia. - This module is automatically loaded at probing. - -config SND_HDA_CODEC_SI3054 - bool "Build Silicon Labs 3054 HD-modem codec support" - default y - help - Say Y here to include Silicon Labs 3054 HD-modem codec - (and compatibles) support in snd-hda-intel driver. - - When the HD-audio driver is built as a module, the codec - support code is also built as another module, - snd-hda-codec-si3054. - This module is automatically loaded at probing. - -config SND_HDA_GENERIC - bool "Enable generic HD-audio codec parser" - default y - help - Say Y here to enable the generic HD-audio codec parser - in snd-hda-intel driver. - -config SND_HDA_POWER_SAVE - bool "Aggressive power-saving on HD-audio" - depends on PM - help - Say Y here to enable more aggressive power-saving mode on - HD-audio driver. The power-saving timeout can be configured - via power_save option or over sysfs on-the-fly. - -config SND_HDA_POWER_SAVE_DEFAULT - int "Default time-out for HD-audio power-save mode" - depends on SND_HDA_POWER_SAVE - default 0 - help - The default time-out value in seconds for HD-audio automatic - power-save mode. 0 means to disable the power-save mode. - -endif diff --git a/ANDROID_3.4.5/sound/pci/hda/Makefile b/ANDROID_3.4.5/sound/pci/hda/Makefile deleted file mode 100644 index ace157cc..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -snd-hda-intel-objs := hda_intel.o - -snd-hda-codec-y := hda_codec.o hda_jack.o -snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o -snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o -snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o -snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o - -# for trace-points -CFLAGS_hda_codec.o := -I$(src) - -snd-hda-codec-realtek-objs := patch_realtek.o -snd-hda-codec-cmedia-objs := patch_cmedia.o -snd-hda-codec-analog-objs := patch_analog.o -snd-hda-codec-idt-objs := patch_sigmatel.o -snd-hda-codec-si3054-objs := patch_si3054.o -snd-hda-codec-cirrus-objs := patch_cirrus.o -snd-hda-codec-ca0110-objs := patch_ca0110.o -snd-hda-codec-ca0132-objs := patch_ca0132.o -snd-hda-codec-conexant-objs := patch_conexant.o -snd-hda-codec-via-objs := patch_via.o -snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o - -# common driver -obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o - -# codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans) -ifdef CONFIG_SND_HDA_CODEC_REALTEK -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o -endif -ifdef CONFIG_SND_HDA_CODEC_CMEDIA -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cmedia.o -endif -ifdef CONFIG_SND_HDA_CODEC_ANALOG -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-analog.o -endif -ifdef CONFIG_SND_HDA_CODEC_SIGMATEL -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-idt.o -endif -ifdef CONFIG_SND_HDA_CODEC_SI3054 -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o -endif -ifdef CONFIG_SND_HDA_CODEC_CIRRUS -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o -endif -ifdef CONFIG_SND_HDA_CODEC_CA0110 -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0110.o -endif -ifdef CONFIG_SND_HDA_CODEC_CA0132 -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-ca0132.o -endif -ifdef CONFIG_SND_HDA_CODEC_CONEXANT -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o -endif -ifdef CONFIG_SND_HDA_CODEC_VIA -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o -endif -ifdef CONFIG_SND_HDA_CODEC_HDMI -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o -endif - -# this must be the last entry after codec drivers; -# otherwise the codec patches won't be hooked before the PCI probe -# when built in kernel -obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_beep.c b/ANDROID_3.4.5/sound/pci/hda/hda_beep.c deleted file mode 100644 index 60738e52..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_beep.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Digital Beep Input Interface for HD-audio codec - * - * Author: Matthew Ranostay - * Copyright (c) 2008 Embedded Alley Solutions Inc - * - * This driver 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 driver 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 "hda_beep.h" -#include "hda_local.h" - -enum { - DIGBEEP_HZ_STEP = 46875, /* 46.875 Hz */ - DIGBEEP_HZ_MIN = 93750, /* 93.750 Hz */ - DIGBEEP_HZ_MAX = 12000000, /* 12 KHz */ -}; - -static void snd_hda_generate_beep(struct work_struct *work) -{ - struct hda_beep *beep = - container_of(work, struct hda_beep, beep_work); - struct hda_codec *codec = beep->codec; - - if (!beep->enabled) - return; - - /* generate tone */ - snd_hda_codec_write(codec, beep->nid, 0, - AC_VERB_SET_BEEP_CONTROL, beep->tone); -} - -/* (non-standard) Linear beep tone calculation for IDT/STAC codecs - * - * The tone frequency of beep generator on IDT/STAC codecs is - * defined from the 8bit tone parameter, in Hz, - * freq = 48000 * (257 - tone) / 1024 - * that is from 12kHz to 93.75Hz in steps of 46.875 Hz - */ -static int beep_linear_tone(struct hda_beep *beep, int hz) -{ - if (hz <= 0) - return 0; - hz *= 1000; /* fixed point */ - hz = hz - DIGBEEP_HZ_MIN - + DIGBEEP_HZ_STEP / 2; /* round to nearest step */ - if (hz < 0) - hz = 0; /* turn off PC beep*/ - else if (hz >= (DIGBEEP_HZ_MAX - DIGBEEP_HZ_MIN)) - hz = 1; /* max frequency */ - else { - hz /= DIGBEEP_HZ_STEP; - hz = 255 - hz; - } - return hz; -} - -/* HD-audio standard beep tone parameter calculation - * - * The tone frequency in Hz is calculated as - * freq = 48000 / (tone * 4) - * from 47Hz to 12kHz - */ -static int beep_standard_tone(struct hda_beep *beep, int hz) -{ - if (hz <= 0) - return 0; /* disabled */ - hz = 12000 / hz; - if (hz > 0xff) - return 0xff; - if (hz <= 0) - return 1; - return hz; -} - -static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, - unsigned int code, int hz) -{ - struct hda_beep *beep = input_get_drvdata(dev); - - switch (code) { - case SND_BELL: - if (hz) - hz = 1000; - case SND_TONE: - if (beep->linear_tone) - beep->tone = beep_linear_tone(beep, hz); - else - beep->tone = beep_standard_tone(beep, hz); - break; - default: - return -1; - } - - /* schedule beep event */ - schedule_work(&beep->beep_work); - return 0; -} - -static void snd_hda_do_detach(struct hda_beep *beep) -{ - input_unregister_device(beep->dev); - beep->dev = NULL; - cancel_work_sync(&beep->beep_work); - /* turn off beep for sure */ - snd_hda_codec_write(beep->codec, beep->nid, 0, - AC_VERB_SET_BEEP_CONTROL, 0); -} - -static int snd_hda_do_attach(struct hda_beep *beep) -{ - struct input_dev *input_dev; - struct hda_codec *codec = beep->codec; - int err; - - input_dev = input_allocate_device(); - if (!input_dev) { - printk(KERN_INFO "hda_beep: unable to allocate input device\n"); - return -ENOMEM; - } - - /* setup digital beep device */ - input_dev->name = "HDA Digital PCBeep"; - input_dev->phys = beep->phys; - input_dev->id.bustype = BUS_PCI; - - input_dev->id.vendor = codec->vendor_id >> 16; - input_dev->id.product = codec->vendor_id & 0xffff; - input_dev->id.version = 0x01; - - input_dev->evbit[0] = BIT_MASK(EV_SND); - input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); - input_dev->event = snd_hda_beep_event; - input_dev->dev.parent = &codec->bus->pci->dev; - input_set_drvdata(input_dev, beep); - - err = input_register_device(input_dev); - if (err < 0) { - input_free_device(input_dev); - printk(KERN_INFO "hda_beep: unable to register input device\n"); - return err; - } - beep->dev = input_dev; - return 0; -} - -static void snd_hda_do_register(struct work_struct *work) -{ - struct hda_beep *beep = - container_of(work, struct hda_beep, register_work); - - mutex_lock(&beep->mutex); - if (beep->enabled && !beep->dev) - snd_hda_do_attach(beep); - mutex_unlock(&beep->mutex); -} - -static void snd_hda_do_unregister(struct work_struct *work) -{ - struct hda_beep *beep = - container_of(work, struct hda_beep, unregister_work.work); - - mutex_lock(&beep->mutex); - if (!beep->enabled && beep->dev) - snd_hda_do_detach(beep); - mutex_unlock(&beep->mutex); -} - -int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) -{ - struct hda_beep *beep = codec->beep; - enable = !!enable; - if (beep == NULL) - return 0; - if (beep->enabled != enable) { - beep->enabled = enable; - if (!enable) { - /* turn off beep */ - snd_hda_codec_write(beep->codec, beep->nid, 0, - AC_VERB_SET_BEEP_CONTROL, 0); - } - if (beep->mode == HDA_BEEP_MODE_SWREG) { - if (enable) { - cancel_delayed_work(&beep->unregister_work); - schedule_work(&beep->register_work); - } else { - schedule_delayed_work(&beep->unregister_work, - HZ); - } - } - return 1; - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device); - -int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) -{ - struct hda_beep *beep; - - if (!snd_hda_get_bool_hint(codec, "beep")) - return 0; /* disabled explicitly by hints */ - if (codec->beep_mode == HDA_BEEP_MODE_OFF) - return 0; /* disabled by module option */ - - beep = kzalloc(sizeof(*beep), GFP_KERNEL); - if (beep == NULL) - return -ENOMEM; - snprintf(beep->phys, sizeof(beep->phys), - "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); - /* enable linear scale */ - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_DIGI_CONVERT_2, 0x01); - - beep->nid = nid; - beep->codec = codec; - beep->mode = codec->beep_mode; - codec->beep = beep; - - INIT_WORK(&beep->register_work, &snd_hda_do_register); - INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister); - INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); - mutex_init(&beep->mutex); - - if (beep->mode == HDA_BEEP_MODE_ON) { - int err = snd_hda_do_attach(beep); - if (err < 0) { - kfree(beep); - codec->beep = NULL; - return err; - } - } - - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device); - -void snd_hda_detach_beep_device(struct hda_codec *codec) -{ - struct hda_beep *beep = codec->beep; - if (beep) { - cancel_work_sync(&beep->register_work); - cancel_delayed_work(&beep->unregister_work); - if (beep->dev) - snd_hda_do_detach(beep); - codec->beep = NULL; - kfree(beep); - } -} -EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_beep.h b/ANDROID_3.4.5/sound/pci/hda/hda_beep.h deleted file mode 100644 index 55f06474..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_beep.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Digital Beep Input Interface for HD-audio codec - * - * Author: Matthew Ranostay - * Copyright (c) 2008 Embedded Alley Solutions Inc - * - * This driver 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 driver 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 - */ - -#ifndef __SOUND_HDA_BEEP_H -#define __SOUND_HDA_BEEP_H - -#include "hda_codec.h" - -#define HDA_BEEP_MODE_OFF 0 -#define HDA_BEEP_MODE_ON 1 -#define HDA_BEEP_MODE_SWREG 2 - -/* beep information */ -struct hda_beep { - struct input_dev *dev; - struct hda_codec *codec; - unsigned int mode; - char phys[32]; - int tone; - hda_nid_t nid; - unsigned int enabled:1; - unsigned int request_enable:1; - unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ - struct work_struct register_work; /* registration work */ - struct delayed_work unregister_work; /* unregistration work */ - struct work_struct beep_work; /* scheduled task for beep event */ - struct mutex mutex; -}; - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -int snd_hda_enable_beep_device(struct hda_codec *codec, int enable); -int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); -void snd_hda_detach_beep_device(struct hda_codec *codec); -#else -static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) -{ - return 0; -} -static inline void snd_hda_detach_beep_device(struct hda_codec *codec) -{ -} -#endif -#endif diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_codec.c b/ANDROID_3.4.5/sound/pci/hda/hda_codec.c deleted file mode 100644 index 926b4553..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_codec.c +++ /dev/null @@ -1,5548 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * Copyright (c) 2004 Takashi Iwai - * - * - * This driver 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 driver 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 "hda_codec.h" -#include -#include -#include -#include -#include "hda_local.h" -#include "hda_beep.h" -#include "hda_jack.h" -#include - -#define CREATE_TRACE_POINTS -#include "hda_trace.h" - -/* - * vendor / preset table - */ - -struct hda_vendor_id { - unsigned int id; - const char *name; -}; - -/* codec vendor labels */ -static struct hda_vendor_id hda_vendor_ids[] = { - { 0x1002, "ATI" }, - { 0x1013, "Cirrus Logic" }, - { 0x1057, "Motorola" }, - { 0x1095, "Silicon Image" }, - { 0x10de, "Nvidia" }, - { 0x10ec, "Realtek" }, - { 0x1102, "Creative" }, - { 0x1106, "VIA" }, - { 0x111d, "IDT" }, - { 0x11c1, "LSI" }, - { 0x11d4, "Analog Devices" }, - { 0x13f6, "C-Media" }, - { 0x14f1, "Conexant" }, - { 0x17e8, "Chrontel" }, - { 0x1854, "LG" }, - { 0x1aec, "Wolfson Microelectronics" }, - { 0x434d, "C-Media" }, - { 0x8086, "Intel" }, - { 0x8384, "SigmaTel" }, - {} /* terminator */ -}; - -static DEFINE_MUTEX(preset_mutex); -static LIST_HEAD(hda_preset_tables); - -int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset) -{ - mutex_lock(&preset_mutex); - list_add_tail(&preset->list, &hda_preset_tables); - mutex_unlock(&preset_mutex); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset); - -int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset) -{ - mutex_lock(&preset_mutex); - list_del(&preset->list); - mutex_unlock(&preset_mutex); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static void hda_power_work(struct work_struct *work); -static void hda_keep_power_on(struct hda_codec *codec); -#define hda_codec_is_power_on(codec) ((codec)->power_on) -#else -static inline void hda_keep_power_on(struct hda_codec *codec) {} -#define hda_codec_is_power_on(codec) 1 -#endif - -/** - * snd_hda_get_jack_location - Give a location string of the jack - * @cfg: pin default config value - * - * Parse the pin default config value and returns the string of the - * jack location, e.g. "Rear", "Front", etc. - */ -const char *snd_hda_get_jack_location(u32 cfg) -{ - static char *bases[7] = { - "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", - }; - static unsigned char specials_idx[] = { - 0x07, 0x08, - 0x17, 0x18, 0x19, - 0x37, 0x38 - }; - static char *specials[] = { - "Rear Panel", "Drive Bar", - "Riser", "HDMI", "ATAPI", - "Mobile-In", "Mobile-Out" - }; - int i; - cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; - if ((cfg & 0x0f) < 7) - return bases[cfg & 0x0f]; - for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { - if (cfg == specials_idx[i]) - return specials[i]; - } - return "UNKNOWN"; -} -EXPORT_SYMBOL_HDA(snd_hda_get_jack_location); - -/** - * snd_hda_get_jack_connectivity - Give a connectivity string of the jack - * @cfg: pin default config value - * - * Parse the pin default config value and returns the string of the - * jack connectivity, i.e. external or internal connection. - */ -const char *snd_hda_get_jack_connectivity(u32 cfg) -{ - static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; - - return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3]; -} -EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity); - -/** - * snd_hda_get_jack_type - Give a type string of the jack - * @cfg: pin default config value - * - * Parse the pin default config value and returns the string of the - * jack type, i.e. the purpose of the jack, such as Line-Out or CD. - */ -const char *snd_hda_get_jack_type(u32 cfg) -{ - static char *jack_types[16] = { - "Line Out", "Speaker", "HP Out", "CD", - "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", - "Line In", "Aux", "Mic", "Telephony", - "SPDIF In", "Digitial In", "Reserved", "Other" - }; - - return jack_types[(cfg & AC_DEFCFG_DEVICE) - >> AC_DEFCFG_DEVICE_SHIFT]; -} -EXPORT_SYMBOL_HDA(snd_hda_get_jack_type); - -/* - * Compose a 32bit command word to be sent to the HD-audio controller - */ -static inline unsigned int -make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, - unsigned int verb, unsigned int parm) -{ - u32 val; - - if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) || - (verb & ~0xfff) || (parm & ~0xffff)) { - printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n", - codec->addr, direct, nid, verb, parm); - return ~0; - } - - val = (u32)codec->addr << 28; - val |= (u32)direct << 27; - val |= (u32)nid << 20; - val |= verb << 8; - val |= parm; - return val; -} - -/* - * Send and receive a verb - */ -static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, - unsigned int *res) -{ - struct hda_bus *bus = codec->bus; - int err; - - if (cmd == ~0) - return -1; - - if (res) - *res = -1; - again: - snd_hda_power_up(codec); - mutex_lock(&bus->cmd_mutex); - trace_hda_send_cmd(codec, cmd); - err = bus->ops.command(bus, cmd); - if (!err && res) { - *res = bus->ops.get_response(bus, codec->addr); - trace_hda_get_response(codec, *res); - } - mutex_unlock(&bus->cmd_mutex); - snd_hda_power_down(codec); - if (res && *res == -1 && bus->rirb_error) { - if (bus->response_reset) { - snd_printd("hda_codec: resetting BUS due to " - "fatal communication error\n"); - trace_hda_bus_reset(bus); - bus->ops.bus_reset(bus); - } - goto again; - } - /* clear reset-flag when the communication gets recovered */ - if (!err) - bus->response_reset = 0; - return err; -} - -/** - * snd_hda_codec_read - send a command and get the response - * @codec: the HDA codec - * @nid: NID to send the command - * @direct: direct flag - * @verb: the verb to send - * @parm: the parameter for the verb - * - * Send a single command and read the corresponding response. - * - * Returns the obtained response value, or -1 for an error. - */ -unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, - int direct, - unsigned int verb, unsigned int parm) -{ - unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm); - unsigned int res; - if (codec_exec_verb(codec, cmd, &res)) - return -1; - return res; -} -EXPORT_SYMBOL_HDA(snd_hda_codec_read); - -/** - * snd_hda_codec_write - send a single command without waiting for response - * @codec: the HDA codec - * @nid: NID to send the command - * @direct: direct flag - * @verb: the verb to send - * @parm: the parameter for the verb - * - * Send a single command without waiting for response. - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, - unsigned int verb, unsigned int parm) -{ - unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); - unsigned int res; - return codec_exec_verb(codec, cmd, - codec->bus->sync_write ? &res : NULL); -} -EXPORT_SYMBOL_HDA(snd_hda_codec_write); - -/** - * snd_hda_sequence_write - sequence writes - * @codec: the HDA codec - * @seq: VERB array to send - * - * Send the commands sequentially from the given array. - * The array must be terminated with NID=0. - */ -void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq) -{ - for (; seq->nid; seq++) - snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); -} -EXPORT_SYMBOL_HDA(snd_hda_sequence_write); - -/** - * snd_hda_get_sub_nodes - get the range of sub nodes - * @codec: the HDA codec - * @nid: NID to parse - * @start_id: the pointer to store the start NID - * - * Parse the NID and store the start NID of its sub-nodes. - * Returns the number of sub-nodes. - */ -int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t *start_id) -{ - unsigned int parm; - - parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT); - if (parm == -1) - return 0; - *start_id = (parm >> 16) & 0x7fff; - return (int)(parm & 0x7fff); -} -EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes); - -/* look up the cached results */ -static hda_nid_t *lookup_conn_list(struct snd_array *array, hda_nid_t nid) -{ - int i, len; - for (i = 0; i < array->used; ) { - hda_nid_t *p = snd_array_elem(array, i); - if (nid == *p) - return p; - len = p[1]; - i += len + 2; - } - return NULL; -} - -/** - * snd_hda_get_conn_list - get connection list - * @codec: the HDA codec - * @nid: NID to parse - * @listp: the pointer to store NID list - * - * Parses the connection list of the given widget and stores the list - * of NIDs. - * - * Returns the number of connections, or a negative error code. - */ -int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, - const hda_nid_t **listp) -{ - struct snd_array *array = &codec->conn_lists; - int len, err; - hda_nid_t list[HDA_MAX_CONNECTIONS]; - hda_nid_t *p; - bool added = false; - - again: - /* if the connection-list is already cached, read it */ - p = lookup_conn_list(array, nid); - if (p) { - if (listp) - *listp = p + 2; - return p[1]; - } - if (snd_BUG_ON(added)) - return -EINVAL; - - /* read the connection and add to the cache */ - len = snd_hda_get_raw_connections(codec, nid, list, HDA_MAX_CONNECTIONS); - if (len < 0) - return len; - err = snd_hda_override_conn_list(codec, nid, len, list); - if (err < 0) - return err; - added = true; - goto again; -} -EXPORT_SYMBOL_HDA(snd_hda_get_conn_list); - -/** - * snd_hda_get_connections - copy connection list - * @codec: the HDA codec - * @nid: NID to parse - * @conn_list: connection list array - * @max_conns: max. number of connections to store - * - * Parses the connection list of the given widget and stores the list - * of NIDs. - * - * Returns the number of connections, or a negative error code. - */ -int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t *conn_list, int max_conns) -{ - const hda_nid_t *list; - int len = snd_hda_get_conn_list(codec, nid, &list); - - if (len <= 0) - return len; - if (len > max_conns) { - snd_printk(KERN_ERR "hda_codec: " - "Too many connections %d for NID 0x%x\n", - len, nid); - return -EINVAL; - } - memcpy(conn_list, list, len * sizeof(hda_nid_t)); - return len; -} -EXPORT_SYMBOL_HDA(snd_hda_get_connections); - -/** - * snd_hda_get_raw_connections - copy connection list without cache - * @codec: the HDA codec - * @nid: NID to parse - * @conn_list: connection list array - * @max_conns: max. number of connections to store - * - * Like snd_hda_get_connections(), copy the connection list but without - * checking through the connection-list cache. - * Currently called only from hda_proc.c, so not exported. - */ -int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t *conn_list, int max_conns) -{ - unsigned int parm; - int i, conn_len, conns; - unsigned int shift, num_elems, mask; - unsigned int wcaps; - hda_nid_t prev_nid; - - if (snd_BUG_ON(!conn_list || max_conns <= 0)) - return -EINVAL; - - wcaps = get_wcaps(codec, nid); - if (!(wcaps & AC_WCAP_CONN_LIST) && - get_wcaps_type(wcaps) != AC_WID_VOL_KNB) - return 0; - - parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); - if (parm & AC_CLIST_LONG) { - /* long form */ - shift = 16; - num_elems = 2; - } else { - /* short form */ - shift = 8; - num_elems = 4; - } - conn_len = parm & AC_CLIST_LENGTH; - mask = (1 << (shift-1)) - 1; - - if (!conn_len) - return 0; /* no connection */ - - if (conn_len == 1) { - /* single connection */ - parm = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CONNECT_LIST, 0); - if (parm == -1 && codec->bus->rirb_error) - return -EIO; - conn_list[0] = parm & mask; - return 1; - } - - /* multi connection */ - conns = 0; - prev_nid = 0; - for (i = 0; i < conn_len; i++) { - int range_val; - hda_nid_t val, n; - - if (i % num_elems == 0) { - parm = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CONNECT_LIST, i); - if (parm == -1 && codec->bus->rirb_error) - return -EIO; - } - range_val = !!(parm & (1 << (shift-1))); /* ranges */ - val = parm & mask; - if (val == 0) { - snd_printk(KERN_WARNING "hda_codec: " - "invalid CONNECT_LIST verb %x[%i]:%x\n", - nid, i, parm); - return 0; - } - parm >>= shift; - if (range_val) { - /* ranges between the previous and this one */ - if (!prev_nid || prev_nid >= val) { - snd_printk(KERN_WARNING "hda_codec: " - "invalid dep_range_val %x:%x\n", - prev_nid, val); - continue; - } - for (n = prev_nid + 1; n <= val; n++) { - if (conns >= max_conns) { - snd_printk(KERN_ERR "hda_codec: " - "Too many connections %d for NID 0x%x\n", - conns, nid); - return -EINVAL; - } - conn_list[conns++] = n; - } - } else { - if (conns >= max_conns) { - snd_printk(KERN_ERR "hda_codec: " - "Too many connections %d for NID 0x%x\n", - conns, nid); - return -EINVAL; - } - conn_list[conns++] = val; - } - prev_nid = val; - } - return conns; -} - -static bool add_conn_list(struct snd_array *array, hda_nid_t nid) -{ - hda_nid_t *p = snd_array_new(array); - if (!p) - return false; - *p = nid; - return true; -} - -/** - * snd_hda_override_conn_list - add/modify the connection-list to cache - * @codec: the HDA codec - * @nid: NID to parse - * @len: number of connection list entries - * @list: the list of connection entries - * - * Add or modify the given connection-list to the cache. If the corresponding - * cache already exists, invalidate it and append a new one. - * - * Returns zero or a negative error code. - */ -int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len, - const hda_nid_t *list) -{ - struct snd_array *array = &codec->conn_lists; - hda_nid_t *p; - int i, old_used; - - p = lookup_conn_list(array, nid); - if (p) - *p = -1; /* invalidate the old entry */ - - old_used = array->used; - if (!add_conn_list(array, nid) || !add_conn_list(array, len)) - goto error_add; - for (i = 0; i < len; i++) - if (!add_conn_list(array, list[i])) - goto error_add; - return 0; - - error_add: - array->used = old_used; - return -ENOMEM; -} -EXPORT_SYMBOL_HDA(snd_hda_override_conn_list); - -/** - * snd_hda_get_conn_index - get the connection index of the given NID - * @codec: the HDA codec - * @mux: NID containing the list - * @nid: NID to select - * @recursive: 1 when searching NID recursively, otherwise 0 - * - * Parses the connection list of the widget @mux and checks whether the - * widget @nid is present. If it is, return the connection index. - * Otherwise it returns -1. - */ -int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, - hda_nid_t nid, int recursive) -{ - hda_nid_t conn[HDA_MAX_NUM_INPUTS]; - int i, nums; - - nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); - for (i = 0; i < nums; i++) - if (conn[i] == nid) - return i; - if (!recursive) - return -1; - if (recursive > 5) { - snd_printd("hda_codec: too deep connection for 0x%x\n", nid); - return -1; - } - recursive++; - for (i = 0; i < nums; i++) { - unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i])); - if (type == AC_WID_PIN || type == AC_WID_AUD_OUT) - continue; - if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0) - return i; - } - return -1; -} -EXPORT_SYMBOL_HDA(snd_hda_get_conn_index); - -/** - * snd_hda_queue_unsol_event - add an unsolicited event to queue - * @bus: the BUS - * @res: unsolicited event (lower 32bit of RIRB entry) - * @res_ex: codec addr and flags (upper 32bit or RIRB entry) - * - * Adds the given event to the queue. The events are processed in - * the workqueue asynchronously. Call this function in the interrupt - * hanlder when RIRB receives an unsolicited event. - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) -{ - struct hda_bus_unsolicited *unsol; - unsigned int wp; - - trace_hda_unsol_event(bus, res, res_ex); - unsol = bus->unsol; - if (!unsol) - return 0; - - wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE; - unsol->wp = wp; - - wp <<= 1; - unsol->queue[wp] = res; - unsol->queue[wp + 1] = res_ex; - - queue_work(bus->workq, &unsol->work); - - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event); - -/* - * process queued unsolicited events - */ -static void process_unsol_events(struct work_struct *work) -{ - struct hda_bus_unsolicited *unsol = - container_of(work, struct hda_bus_unsolicited, work); - struct hda_bus *bus = unsol->bus; - struct hda_codec *codec; - unsigned int rp, caddr, res; - - while (unsol->rp != unsol->wp) { - rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE; - unsol->rp = rp; - rp <<= 1; - res = unsol->queue[rp]; - caddr = unsol->queue[rp + 1]; - if (!(caddr & (1 << 4))) /* no unsolicited event? */ - continue; - codec = bus->caddr_tbl[caddr & 0x0f]; - if (codec && codec->patch_ops.unsol_event) - codec->patch_ops.unsol_event(codec, res); - } -} - -/* - * initialize unsolicited queue - */ -static int init_unsol_queue(struct hda_bus *bus) -{ - struct hda_bus_unsolicited *unsol; - - if (bus->unsol) /* already initialized */ - return 0; - - unsol = kzalloc(sizeof(*unsol), GFP_KERNEL); - if (!unsol) { - snd_printk(KERN_ERR "hda_codec: " - "can't allocate unsolicited queue\n"); - return -ENOMEM; - } - INIT_WORK(&unsol->work, process_unsol_events); - unsol->bus = bus; - bus->unsol = unsol; - return 0; -} - -/* - * destructor - */ -static void snd_hda_codec_free(struct hda_codec *codec); - -static int snd_hda_bus_free(struct hda_bus *bus) -{ - struct hda_codec *codec, *n; - - if (!bus) - return 0; - if (bus->workq) - flush_workqueue(bus->workq); - if (bus->unsol) - kfree(bus->unsol); - list_for_each_entry_safe(codec, n, &bus->codec_list, list) { - snd_hda_codec_free(codec); - } - if (bus->ops.private_free) - bus->ops.private_free(bus); - if (bus->workq) - destroy_workqueue(bus->workq); - kfree(bus); - return 0; -} - -static int snd_hda_bus_dev_free(struct snd_device *device) -{ - struct hda_bus *bus = device->device_data; - bus->shutdown = 1; - return snd_hda_bus_free(bus); -} - -#ifdef CONFIG_SND_HDA_HWDEP -static int snd_hda_bus_dev_register(struct snd_device *device) -{ - struct hda_bus *bus = device->device_data; - struct hda_codec *codec; - list_for_each_entry(codec, &bus->codec_list, list) { - snd_hda_hwdep_add_sysfs(codec); - snd_hda_hwdep_add_power_sysfs(codec); - } - return 0; -} -#else -#define snd_hda_bus_dev_register NULL -#endif - -/** - * snd_hda_bus_new - create a HDA bus - * @card: the card entry - * @temp: the template for hda_bus information - * @busp: the pointer to store the created bus instance - * - * Returns 0 if successful, or a negative error code. - */ -int /*__devinit*/ snd_hda_bus_new(struct snd_card *card, - const struct hda_bus_template *temp, - struct hda_bus **busp) -{ - struct hda_bus *bus; - int err; - static struct snd_device_ops dev_ops = { - .dev_register = snd_hda_bus_dev_register, - .dev_free = snd_hda_bus_dev_free, - }; - - if (snd_BUG_ON(!temp)) - return -EINVAL; - if (snd_BUG_ON(!temp->ops.command || !temp->ops.get_response)) - return -EINVAL; - - if (busp) - *busp = NULL; - - bus = kzalloc(sizeof(*bus), GFP_KERNEL); - if (bus == NULL) { - snd_printk(KERN_ERR "can't allocate struct hda_bus\n"); - return -ENOMEM; - } - - bus->card = card; - bus->private_data = temp->private_data; - bus->pci = temp->pci; - bus->modelname = temp->modelname; - bus->power_save = temp->power_save; - bus->ops = temp->ops; - - mutex_init(&bus->cmd_mutex); - mutex_init(&bus->prepare_mutex); - INIT_LIST_HEAD(&bus->codec_list); - - snprintf(bus->workq_name, sizeof(bus->workq_name), - "hd-audio%d", card->number); - bus->workq = create_singlethread_workqueue(bus->workq_name); - if (!bus->workq) { - snd_printk(KERN_ERR "cannot create workqueue %s\n", - bus->workq_name); - kfree(bus); - return -ENOMEM; - } - - err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); - if (err < 0) { - snd_hda_bus_free(bus); - return err; - } - if (busp) - *busp = bus; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_bus_new); - -#ifdef CONFIG_SND_HDA_GENERIC -#define is_generic_config(codec) \ - (codec->modelname && !strcmp(codec->modelname, "generic")) -#else -#define is_generic_config(codec) 0 -#endif - -#ifdef MODULE -#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */ -#else -#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */ -#endif - -/* - * find a matching codec preset - */ -static const struct hda_codec_preset * -find_codec_preset(struct hda_codec *codec) -{ - struct hda_codec_preset_list *tbl; - const struct hda_codec_preset *preset; - int mod_requested = 0; - - if (is_generic_config(codec)) - return NULL; /* use the generic parser */ - - again: - mutex_lock(&preset_mutex); - list_for_each_entry(tbl, &hda_preset_tables, list) { - if (!try_module_get(tbl->owner)) { - snd_printk(KERN_ERR "hda_codec: cannot module_get\n"); - continue; - } - for (preset = tbl->preset; preset->id; preset++) { - u32 mask = preset->mask; - if (preset->afg && preset->afg != codec->afg) - continue; - if (preset->mfg && preset->mfg != codec->mfg) - continue; - if (!mask) - mask = ~0; - if (preset->id == (codec->vendor_id & mask) && - (!preset->rev || - preset->rev == codec->revision_id)) { - mutex_unlock(&preset_mutex); - codec->owner = tbl->owner; - return preset; - } - } - module_put(tbl->owner); - } - mutex_unlock(&preset_mutex); - - if (mod_requested < HDA_MODREQ_MAX_COUNT) { - char name[32]; - if (!mod_requested) - snprintf(name, sizeof(name), "snd-hda-codec-id:%08x", - codec->vendor_id); - else - snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*", - (codec->vendor_id >> 16) & 0xffff); - request_module(name); - mod_requested++; - goto again; - } - return NULL; -} - -/* - * get_codec_name - store the codec name - */ -static int get_codec_name(struct hda_codec *codec) -{ - const struct hda_vendor_id *c; - const char *vendor = NULL; - u16 vendor_id = codec->vendor_id >> 16; - char tmp[16]; - - if (codec->vendor_name) - goto get_chip_name; - - for (c = hda_vendor_ids; c->id; c++) { - if (c->id == vendor_id) { - vendor = c->name; - break; - } - } - if (!vendor) { - sprintf(tmp, "Generic %04x", vendor_id); - vendor = tmp; - } - codec->vendor_name = kstrdup(vendor, GFP_KERNEL); - if (!codec->vendor_name) - return -ENOMEM; - - get_chip_name: - if (codec->chip_name) - return 0; - - if (codec->preset && codec->preset->name) - codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL); - else { - sprintf(tmp, "ID %x", codec->vendor_id & 0xffff); - codec->chip_name = kstrdup(tmp, GFP_KERNEL); - } - if (!codec->chip_name) - return -ENOMEM; - return 0; -} - -/* - * look for an AFG and MFG nodes - */ -static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec) -{ - 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++) { - function_id = snd_hda_param_read(codec, nid, - AC_PAR_FUNCTION_TYPE); - switch (function_id & 0xff) { - case AC_GRP_AUDIO_FUNCTION: - codec->afg = nid; - codec->afg_function_id = function_id & 0xff; - codec->afg_unsol = (function_id >> 8) & 1; - break; - case AC_GRP_MODEM_FUNCTION: - codec->mfg = nid; - codec->mfg_function_id = function_id & 0xff; - codec->mfg_unsol = (function_id >> 8) & 1; - break; - default: - break; - } - } -} - -/* - * read widget caps for each widget and store in cache - */ -static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) -{ - int i; - hda_nid_t nid; - - codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node, - &codec->start_nid); - codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL); - if (!codec->wcaps) - return -ENOMEM; - nid = codec->start_nid; - for (i = 0; i < codec->num_nodes; i++, nid++) - codec->wcaps[i] = snd_hda_param_read(codec, nid, - AC_PAR_AUDIO_WIDGET_CAP); - return 0; -} - -/* read all pin default configurations and save codec->init_pins */ -static int read_pin_defaults(struct hda_codec *codec) -{ - int i; - hda_nid_t nid = codec->start_nid; - - for (i = 0; i < codec->num_nodes; i++, nid++) { - struct hda_pincfg *pin; - unsigned int wcaps = get_wcaps(codec, nid); - unsigned int wid_type = get_wcaps_type(wcaps); - if (wid_type != AC_WID_PIN) - continue; - pin = snd_array_new(&codec->init_pins); - if (!pin) - return -ENOMEM; - pin->nid = nid; - pin->cfg = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CONFIG_DEFAULT, 0); - pin->ctrl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, - 0); - } - return 0; -} - -/* look up the given pin config list and return the item matching with NID */ -static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec, - struct snd_array *array, - hda_nid_t nid) -{ - int i; - for (i = 0; i < array->used; i++) { - struct hda_pincfg *pin = snd_array_elem(array, i); - if (pin->nid == nid) - return pin; - } - return NULL; -} - -/* write a config value for the given NID */ -static void set_pincfg(struct hda_codec *codec, hda_nid_t nid, - unsigned int cfg) -{ - int i; - for (i = 0; i < 4; i++) { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, - cfg & 0xff); - cfg >>= 8; - } -} - -/* set the current pin config value for the given NID. - * the value is cached, and read via snd_hda_codec_get_pincfg() - */ -int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, - hda_nid_t nid, unsigned int cfg) -{ - struct hda_pincfg *pin; - unsigned int oldcfg; - - if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) - return -EINVAL; - - oldcfg = snd_hda_codec_get_pincfg(codec, nid); - pin = look_up_pincfg(codec, list, nid); - if (!pin) { - pin = snd_array_new(list); - if (!pin) - return -ENOMEM; - pin->nid = nid; - } - pin->cfg = cfg; - - /* change only when needed; e.g. if the pincfg is already present - * in user_pins[], don't write it - */ - cfg = snd_hda_codec_get_pincfg(codec, nid); - if (oldcfg != cfg) - set_pincfg(codec, nid, cfg); - return 0; -} - -/** - * snd_hda_codec_set_pincfg - Override a pin default configuration - * @codec: the HDA codec - * @nid: NID to set the pin config - * @cfg: the pin default config value - * - * Override a pin default configuration value in the cache. - * This value can be read by snd_hda_codec_get_pincfg() in a higher - * priority than the real hardware value. - */ -int snd_hda_codec_set_pincfg(struct hda_codec *codec, - hda_nid_t nid, unsigned int cfg) -{ - return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg); -} -EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg); - -/** - * snd_hda_codec_get_pincfg - Obtain a pin-default configuration - * @codec: the HDA codec - * @nid: NID to get the pin config - * - * Get the current pin config value of the given pin NID. - * If the pincfg value is cached or overridden via sysfs or driver, - * returns the cached value. - */ -unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid) -{ - struct hda_pincfg *pin; - -#ifdef CONFIG_SND_HDA_HWDEP - pin = look_up_pincfg(codec, &codec->user_pins, nid); - if (pin) - return pin->cfg; -#endif - pin = look_up_pincfg(codec, &codec->driver_pins, nid); - if (pin) - return pin->cfg; - pin = look_up_pincfg(codec, &codec->init_pins, nid); - if (pin) - return pin->cfg; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg); - -/* restore all current pin configs */ -static void restore_pincfgs(struct hda_codec *codec) -{ - int i; - for (i = 0; i < codec->init_pins.used; i++) { - struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); - set_pincfg(codec, pin->nid, - snd_hda_codec_get_pincfg(codec, pin->nid)); - } -} - -/** - * snd_hda_shutup_pins - Shut up all pins - * @codec: the HDA codec - * - * Clear all pin controls to shup up before suspend for avoiding click noise. - * The controls aren't cached so that they can be resumed properly. - */ -void snd_hda_shutup_pins(struct hda_codec *codec) -{ - int i; - /* don't shut up pins when unloading the driver; otherwise it breaks - * the default pin setup at the next load of the driver - */ - if (codec->bus->shutdown) - return; - for (i = 0; i < codec->init_pins.used; i++) { - struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); - /* use read here for syncing after issuing each verb */ - snd_hda_codec_read(codec, pin->nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, 0); - } - codec->pins_shutup = 1; -} -EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); - -#ifdef CONFIG_PM -/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */ -static void restore_shutup_pins(struct hda_codec *codec) -{ - int i; - if (!codec->pins_shutup) - return; - if (codec->bus->shutdown) - return; - for (i = 0; i < codec->init_pins.used; i++) { - struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); - snd_hda_codec_write(codec, pin->nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pin->ctrl); - } - codec->pins_shutup = 0; -} -#endif - -static void init_hda_cache(struct hda_cache_rec *cache, - unsigned int record_size); -static void free_hda_cache(struct hda_cache_rec *cache); - -/* restore the initial pin cfgs and release all pincfg lists */ -static void restore_init_pincfgs(struct hda_codec *codec) -{ - /* first free driver_pins and user_pins, then call restore_pincfg - * so that only the values in init_pins are restored - */ - snd_array_free(&codec->driver_pins); -#ifdef CONFIG_SND_HDA_HWDEP - snd_array_free(&codec->user_pins); -#endif - restore_pincfgs(codec); - snd_array_free(&codec->init_pins); -} - -/* - * audio-converter setup caches - */ -struct hda_cvt_setup { - hda_nid_t nid; - u8 stream_tag; - u8 channel_id; - u16 format_id; - unsigned char active; /* cvt is currently used */ - unsigned char dirty; /* setups should be cleared */ -}; - -/* get or create a cache entry for the given audio converter NID */ -static struct hda_cvt_setup * -get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) -{ - struct hda_cvt_setup *p; - int i; - - for (i = 0; i < codec->cvt_setups.used; i++) { - p = snd_array_elem(&codec->cvt_setups, i); - if (p->nid == nid) - return p; - } - p = snd_array_new(&codec->cvt_setups); - if (p) - p->nid = nid; - return p; -} - -/* - * codec destructor - */ -static void snd_hda_codec_free(struct hda_codec *codec) -{ - if (!codec) - return; - snd_hda_jack_tbl_clear(codec); - restore_init_pincfgs(codec); -#ifdef CONFIG_SND_HDA_POWER_SAVE - cancel_delayed_work(&codec->power_work); - flush_workqueue(codec->bus->workq); -#endif - list_del(&codec->list); - snd_array_free(&codec->mixers); - snd_array_free(&codec->nids); - snd_array_free(&codec->cvt_setups); - snd_array_free(&codec->conn_lists); - snd_array_free(&codec->spdif_out); - codec->bus->caddr_tbl[codec->addr] = NULL; - if (codec->patch_ops.free) - codec->patch_ops.free(codec); - module_put(codec->owner); - free_hda_cache(&codec->amp_cache); - free_hda_cache(&codec->cmd_cache); - kfree(codec->vendor_name); - kfree(codec->chip_name); - kfree(codec->modelname); - kfree(codec->wcaps); - kfree(codec); -} - -static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, - unsigned int power_state); - -/** - * snd_hda_codec_new - create a HDA codec - * @bus: the bus to assign - * @codec_addr: the codec address - * @codecp: the pointer to store the generated codec - * - * Returns 0 if successful, or a negative error code. - */ -int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, - unsigned int codec_addr, - struct hda_codec **codecp) -{ - struct hda_codec *codec; - char component[31]; - int err; - - if (snd_BUG_ON(!bus)) - return -EINVAL; - if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS)) - return -EINVAL; - - if (bus->caddr_tbl[codec_addr]) { - snd_printk(KERN_ERR "hda_codec: " - "address 0x%x is already occupied\n", codec_addr); - return -EBUSY; - } - - codec = kzalloc(sizeof(*codec), GFP_KERNEL); - if (codec == NULL) { - snd_printk(KERN_ERR "can't allocate struct hda_codec\n"); - return -ENOMEM; - } - - codec->bus = bus; - codec->addr = codec_addr; - mutex_init(&codec->spdif_mutex); - mutex_init(&codec->control_mutex); - init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); - init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); - snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); - snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); - snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); - snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); - snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); - snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); - snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); - if (codec->bus->modelname) { - codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL); - if (!codec->modelname) { - snd_hda_codec_free(codec); - return -ENODEV; - } - } - -#ifdef CONFIG_SND_HDA_POWER_SAVE - INIT_DELAYED_WORK(&codec->power_work, hda_power_work); - /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. - * the caller has to power down appropriatley after initialization - * phase. - */ - hda_keep_power_on(codec); -#endif - - list_add_tail(&codec->list, &bus->codec_list); - bus->caddr_tbl[codec_addr] = codec; - - codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, - AC_PAR_VENDOR_ID); - if (codec->vendor_id == -1) - /* read again, hopefully the access method was corrected - * in the last read... - */ - codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, - AC_PAR_VENDOR_ID); - codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, - AC_PAR_SUBSYSTEM_ID); - codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, - AC_PAR_REV_ID); - - setup_fg_nodes(codec); - if (!codec->afg && !codec->mfg) { - snd_printdd("hda_codec: no AFG or MFG node found\n"); - err = -ENODEV; - goto error; - } - - err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg); - if (err < 0) { - snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); - goto error; - } - err = read_pin_defaults(codec); - if (err < 0) - goto error; - - if (!codec->subsystem_id) { - hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; - codec->subsystem_id = - snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_SUBSYSTEM_ID, 0); - } - - /* power-up all before initialization */ - hda_set_power_state(codec, - codec->afg ? codec->afg : codec->mfg, - AC_PWRST_D0); - - snd_hda_codec_proc_new(codec); - - snd_hda_create_hwdep(codec); - - sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, - codec->subsystem_id, codec->revision_id); - snd_component_add(codec->bus->card, component); - - if (codecp) - *codecp = codec; - return 0; - - error: - snd_hda_codec_free(codec); - return err; -} -EXPORT_SYMBOL_HDA(snd_hda_codec_new); - -/** - * snd_hda_codec_configure - (Re-)configure the HD-audio codec - * @codec: the HDA codec - * - * Start parsing of the given codec tree and (re-)initialize the whole - * patch instance. - * - * Returns 0 if successful or a negative error code. - */ -int snd_hda_codec_configure(struct hda_codec *codec) -{ - int err; - - codec->preset = find_codec_preset(codec); - if (!codec->vendor_name || !codec->chip_name) { - err = get_codec_name(codec); - if (err < 0) - return err; - } - - if (is_generic_config(codec)) { - err = snd_hda_parse_generic_codec(codec); - goto patched; - } - if (codec->preset && codec->preset->patch) { - err = codec->preset->patch(codec); - goto patched; - } - - /* call the default parser */ - err = snd_hda_parse_generic_codec(codec); - if (err < 0) - printk(KERN_ERR "hda-codec: No codec parser is available\n"); - - patched: - if (!err && codec->patch_ops.unsol_event) - err = init_unsol_queue(codec->bus); - /* audio codec should override the mixer name */ - if (!err && (codec->afg || !*codec->bus->card->mixername)) - snprintf(codec->bus->card->mixername, - sizeof(codec->bus->card->mixername), - "%s %s", codec->vendor_name, codec->chip_name); - return err; -} -EXPORT_SYMBOL_HDA(snd_hda_codec_configure); - -/** - * snd_hda_codec_setup_stream - set up the codec for streaming - * @codec: the CODEC to set up - * @nid: the NID to set up - * @stream_tag: stream tag to pass, it's between 0x1 and 0xf. - * @channel_id: channel id to pass, zero based. - * @format: stream format. - */ -void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, - int channel_id, int format) -{ - struct hda_codec *c; - struct hda_cvt_setup *p; - unsigned int oldval, newval; - int type; - int i; - - if (!nid) - return; - - snd_printdd("hda_codec_setup_stream: " - "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", - nid, stream_tag, channel_id, format); - p = get_hda_cvt_setup(codec, nid); - if (!p) - return; - /* update the stream-id if changed */ - if (p->stream_tag != stream_tag || p->channel_id != channel_id) { - oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); - newval = (stream_tag << 4) | channel_id; - if (oldval != newval) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - newval); - p->stream_tag = stream_tag; - p->channel_id = channel_id; - } - /* update the format-id if changed */ - if (p->format_id != format) { - oldval = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_STREAM_FORMAT, 0); - if (oldval != format) { - msleep(1); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, - format); - } - p->format_id = format; - } - p->active = 1; - p->dirty = 0; - - /* make other inactive cvts with the same stream-tag dirty */ - type = get_wcaps_type(get_wcaps(codec, nid)); - list_for_each_entry(c, &codec->bus->codec_list, list) { - for (i = 0; i < c->cvt_setups.used; i++) { - p = snd_array_elem(&c->cvt_setups, i); - if (!p->active && p->stream_tag == stream_tag && - get_wcaps_type(get_wcaps(c, p->nid)) == type) - p->dirty = 1; - } - } -} -EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream); - -static void really_cleanup_stream(struct hda_codec *codec, - struct hda_cvt_setup *q); - -/** - * __snd_hda_codec_cleanup_stream - clean up the codec for closing - * @codec: the CODEC to clean up - * @nid: the NID to clean up - * @do_now: really clean up the stream instead of clearing the active flag - */ -void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, - int do_now) -{ - struct hda_cvt_setup *p; - - if (!nid) - return; - - if (codec->no_sticky_stream) - do_now = 1; - - snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); - p = get_hda_cvt_setup(codec, nid); - if (p) { - /* here we just clear the active flag when do_now isn't set; - * actual clean-ups will be done later in - * purify_inactive_streams() called from snd_hda_codec_prpapre() - */ - if (do_now) - really_cleanup_stream(codec, p); - else - p->active = 0; - } -} -EXPORT_SYMBOL_HDA(__snd_hda_codec_cleanup_stream); - -static void really_cleanup_stream(struct hda_codec *codec, - struct hda_cvt_setup *q) -{ - hda_nid_t nid = q->nid; - if (q->stream_tag || q->channel_id) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); - if (q->format_id) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0 -); - memset(q, 0, sizeof(*q)); - q->nid = nid; -} - -/* clean up the all conflicting obsolete streams */ -static void purify_inactive_streams(struct hda_codec *codec) -{ - struct hda_codec *c; - int i; - - list_for_each_entry(c, &codec->bus->codec_list, list) { - for (i = 0; i < c->cvt_setups.used; i++) { - struct hda_cvt_setup *p; - p = snd_array_elem(&c->cvt_setups, i); - if (p->dirty) - really_cleanup_stream(c, p); - } - } -} - -#ifdef CONFIG_PM -/* clean up all streams; called from suspend */ -static void hda_cleanup_all_streams(struct hda_codec *codec) -{ - int i; - - for (i = 0; i < codec->cvt_setups.used; i++) { - struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i); - if (p->stream_tag) - really_cleanup_stream(codec, p); - } -} -#endif - -/* - * amp access functions - */ - -/* FIXME: more better hash key? */ -#define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) -#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) -#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) -#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) -#define INFO_AMP_CAPS (1<<0) -#define INFO_AMP_VOL(ch) (1 << (1 + (ch))) - -/* initialize the hash table */ -static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache, - unsigned int record_size) -{ - memset(cache, 0, sizeof(*cache)); - memset(cache->hash, 0xff, sizeof(cache->hash)); - snd_array_init(&cache->buf, record_size, 64); -} - -static void free_hda_cache(struct hda_cache_rec *cache) -{ - snd_array_free(&cache->buf); -} - -/* query the hash. allocate an entry if not found. */ -static struct hda_cache_head *get_hash(struct hda_cache_rec *cache, u32 key) -{ - u16 idx = key % (u16)ARRAY_SIZE(cache->hash); - u16 cur = cache->hash[idx]; - struct hda_cache_head *info; - - while (cur != 0xffff) { - info = snd_array_elem(&cache->buf, cur); - if (info->key == key) - return info; - cur = info->next; - } - return NULL; -} - -/* query the hash. allocate an entry if not found. */ -static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache, - u32 key) -{ - struct hda_cache_head *info = get_hash(cache, key); - if (!info) { - u16 idx, cur; - /* add a new hash entry */ - info = snd_array_new(&cache->buf); - if (!info) - return NULL; - cur = snd_array_index(&cache->buf, info); - info->key = key; - info->val = 0; - idx = key % (u16)ARRAY_SIZE(cache->hash); - info->next = cache->hash[idx]; - cache->hash[idx] = cur; - } - return info; -} - -/* query and allocate an amp hash entry */ -static inline struct hda_amp_info * -get_alloc_amp_hash(struct hda_codec *codec, u32 key) -{ - return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key); -} - -/** - * query_amp_caps - query AMP capabilities - * @codec: the HD-auio codec - * @nid: the NID to query - * @direction: either #HDA_INPUT or #HDA_OUTPUT - * - * Query AMP capabilities for the given widget and direction. - * Returns the obtained capability bits. - * - * When cap bits have been already read, this doesn't read again but - * returns the cached value. - */ -u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) -{ - struct hda_amp_info *info; - - info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0)); - if (!info) - return 0; - if (!(info->head.val & INFO_AMP_CAPS)) { - if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD)) - nid = codec->afg; - info->amp_caps = snd_hda_param_read(codec, nid, - direction == HDA_OUTPUT ? - AC_PAR_AMP_OUT_CAP : - AC_PAR_AMP_IN_CAP); - if (info->amp_caps) - info->head.val |= INFO_AMP_CAPS; - } - return info->amp_caps; -} -EXPORT_SYMBOL_HDA(query_amp_caps); - -/** - * snd_hda_override_amp_caps - Override the AMP capabilities - * @codec: the CODEC to clean up - * @nid: the NID to clean up - * @direction: either #HDA_INPUT or #HDA_OUTPUT - * @caps: the capability bits to set - * - * Override the cached AMP caps bits value by the given one. - * This function is useful if the driver needs to adjust the AMP ranges, - * e.g. limit to 0dB, etc. - * - * Returns zero if successful or a negative error code. - */ -int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, - unsigned int caps) -{ - struct hda_amp_info *info; - - info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0)); - if (!info) - return -EINVAL; - info->amp_caps = caps; - info->head.val |= INFO_AMP_CAPS; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); - -static unsigned int -query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key, - unsigned int (*func)(struct hda_codec *, hda_nid_t)) -{ - struct hda_amp_info *info; - - info = get_alloc_amp_hash(codec, key); - if (!info) - return 0; - if (!info->head.val) { - info->head.val |= INFO_AMP_CAPS; - info->amp_caps = func(codec, nid); - } - return info->amp_caps; -} - -static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid) -{ - return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); -} - -/** - * snd_hda_query_pin_caps - Query PIN capabilities - * @codec: the HD-auio codec - * @nid: the NID to query - * - * Query PIN capabilities for the given widget. - * Returns the obtained capability bits. - * - * When cap bits have been already read, this doesn't read again but - * returns the cached value. - */ -u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) -{ - return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid), - read_pin_cap); -} -EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); - -/** - * snd_hda_override_pin_caps - Override the pin capabilities - * @codec: the CODEC - * @nid: the NID to override - * @caps: the capability bits to set - * - * Override the cached PIN capabilitiy bits value by the given one. - * - * Returns zero if successful or a negative error code. - */ -int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, - unsigned int caps) -{ - struct hda_amp_info *info; - info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid)); - if (!info) - return -ENOMEM; - info->amp_caps = caps; - info->head.val |= INFO_AMP_CAPS; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps); - -/* - * read the current volume to info - * if the cache exists, read the cache value. - */ -static unsigned int get_vol_mute(struct hda_codec *codec, - struct hda_amp_info *info, hda_nid_t nid, - int ch, int direction, int index) -{ - u32 val, parm; - - if (info->head.val & INFO_AMP_VOL(ch)) - return info->vol[ch]; - - parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; - parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; - parm |= index; - val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_AMP_GAIN_MUTE, parm); - info->vol[ch] = val & 0xff; - info->head.val |= INFO_AMP_VOL(ch); - return info->vol[ch]; -} - -/* - * write the current volume in info to the h/w and update the cache - */ -static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, - hda_nid_t nid, int ch, int direction, int index, - int val) -{ - u32 parm; - - parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT; - parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT; - parm |= index << AC_AMP_SET_INDEX_SHIFT; - if ((val & HDA_AMP_MUTE) && !(info->amp_caps & AC_AMPCAP_MUTE) && - (info->amp_caps & AC_AMPCAP_MIN_MUTE)) - ; /* set the zero value as a fake mute */ - else - parm |= val; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); - info->vol[ch] = val; -} - -/** - * snd_hda_codec_amp_read - Read AMP value - * @codec: HD-audio codec - * @nid: NID to read the AMP value - * @ch: channel (left=0 or right=1) - * @direction: #HDA_INPUT or #HDA_OUTPUT - * @index: the index value (only for input direction) - * - * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. - */ -int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, - int direction, int index) -{ - struct hda_amp_info *info; - info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); - if (!info) - return 0; - return get_vol_mute(codec, info, nid, ch, direction, index); -} -EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read); - -/** - * snd_hda_codec_amp_update - update the AMP value - * @codec: HD-audio codec - * @nid: NID to read the AMP value - * @ch: channel (left=0 or right=1) - * @direction: #HDA_INPUT or #HDA_OUTPUT - * @idx: the index value (only for input direction) - * @mask: bit mask to set - * @val: the bits value to set - * - * Update the AMP value with a bit mask. - * Returns 0 if the value is unchanged, 1 if changed. - */ -int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, - int direction, int idx, int mask, int val) -{ - struct hda_amp_info *info; - - info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); - if (!info) - return 0; - if (snd_BUG_ON(mask & ~0xff)) - mask &= 0xff; - val &= mask; - val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; - if (info->vol[ch] == val) - return 0; - put_vol_mute(codec, info, nid, ch, direction, idx, val); - return 1; -} -EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update); - -/** - * snd_hda_codec_amp_stereo - update the AMP stereo values - * @codec: HD-audio codec - * @nid: NID to read the AMP value - * @direction: #HDA_INPUT or #HDA_OUTPUT - * @idx: the index value (only for input direction) - * @mask: bit mask to set - * @val: the bits value to set - * - * Update the AMP values like snd_hda_codec_amp_update(), but for a - * stereo widget with the same mask and value. - */ -int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, - int direction, int idx, int mask, int val) -{ - int ch, ret = 0; - - if (snd_BUG_ON(mask & ~0xff)) - mask &= 0xff; - for (ch = 0; ch < 2; ch++) - ret |= snd_hda_codec_amp_update(codec, nid, ch, direction, - idx, mask, val); - return ret; -} -EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo); - -#ifdef CONFIG_PM -/** - * snd_hda_codec_resume_amp - Resume all AMP commands from the cache - * @codec: HD-audio codec - * - * Resume the all amp commands from the cache. - */ -void snd_hda_codec_resume_amp(struct hda_codec *codec) -{ - struct hda_amp_info *buffer = codec->amp_cache.buf.list; - int i; - - for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) { - u32 key = buffer->head.key; - hda_nid_t nid; - unsigned int idx, dir, ch; - if (!key) - continue; - nid = key & 0xff; - idx = (key >> 16) & 0xff; - dir = (key >> 24) & 0xff; - for (ch = 0; ch < 2; ch++) { - if (!(buffer->head.val & INFO_AMP_VOL(ch))) - continue; - put_vol_mute(codec, buffer, nid, ch, dir, idx, - buffer->vol[ch]); - } - } -} -EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); -#endif /* CONFIG_PM */ - -static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, - unsigned int ofs) -{ - u32 caps = query_amp_caps(codec, nid, dir); - /* get num steps */ - caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; - if (ofs < caps) - caps -= ofs; - return caps; -} - -/** - * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - u16 nid = get_amp_nid(kcontrol); - u8 chs = get_amp_channels(kcontrol); - int dir = get_amp_direction(kcontrol); - unsigned int ofs = get_amp_offset(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = chs == 3 ? 2 : 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs); - if (!uinfo->value.integer.max) { - printk(KERN_WARNING "hda_codec: " - "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, - kcontrol->id.name); - return -EINVAL; - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); - - -static inline unsigned int -read_amp_value(struct hda_codec *codec, hda_nid_t nid, - int ch, int dir, int idx, unsigned int ofs) -{ - unsigned int val; - val = snd_hda_codec_amp_read(codec, nid, ch, dir, idx); - val &= HDA_AMP_VOLMASK; - if (val >= ofs) - val -= ofs; - else - val = 0; - return val; -} - -static inline int -update_amp_value(struct hda_codec *codec, hda_nid_t nid, - int ch, int dir, int idx, unsigned int ofs, - unsigned int val) -{ - unsigned int maxval; - - if (val > 0) - val += ofs; - /* ofs = 0: raw max value */ - maxval = get_amp_max_value(codec, nid, dir, 0); - if (val > maxval) - val = maxval; - return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, - HDA_AMP_VOLMASK, val); -} - -/** - * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = get_amp_nid(kcontrol); - int chs = get_amp_channels(kcontrol); - int dir = get_amp_direction(kcontrol); - int idx = get_amp_index(kcontrol); - unsigned int ofs = get_amp_offset(kcontrol); - long *valp = ucontrol->value.integer.value; - - if (chs & 1) - *valp++ = read_amp_value(codec, nid, 0, dir, idx, ofs); - if (chs & 2) - *valp = read_amp_value(codec, nid, 1, dir, idx, ofs); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get); - -/** - * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = get_amp_nid(kcontrol); - int chs = get_amp_channels(kcontrol); - int dir = get_amp_direction(kcontrol); - int idx = get_amp_index(kcontrol); - unsigned int ofs = get_amp_offset(kcontrol); - long *valp = ucontrol->value.integer.value; - int change = 0; - - snd_hda_power_up(codec); - if (chs & 1) { - change = update_amp_value(codec, nid, 0, dir, idx, ofs, *valp); - valp++; - } - if (chs & 2) - change |= update_amp_value(codec, nid, 1, dir, idx, ofs, *valp); - snd_hda_power_down(codec); - return change; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put); - -/** - * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *_tlv) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = get_amp_nid(kcontrol); - int dir = get_amp_direction(kcontrol); - unsigned int ofs = get_amp_offset(kcontrol); - bool min_mute = get_amp_min_mute(kcontrol); - u32 caps, val1, val2; - - if (size < 4 * sizeof(unsigned int)) - return -ENOMEM; - caps = query_amp_caps(codec, nid, dir); - val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; - val2 = (val2 + 1) * 25; - val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); - val1 += ofs; - val1 = ((int)val1) * ((int)val2); - if (min_mute || (caps & AC_AMPCAP_MIN_MUTE)) - val2 |= TLV_DB_SCALE_MUTE; - if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) - return -EFAULT; - if (put_user(2 * sizeof(unsigned int), _tlv + 1)) - return -EFAULT; - if (put_user(val1, _tlv + 2)) - return -EFAULT; - if (put_user(val2, _tlv + 3)) - return -EFAULT; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv); - -/** - * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control - * @codec: HD-audio codec - * @nid: NID of a reference widget - * @dir: #HDA_INPUT or #HDA_OUTPUT - * @tlv: TLV data to be stored, at least 4 elements - * - * Set (static) TLV data for a virtual master volume using the AMP caps - * obtained from the reference NID. - * The volume range is recalculated as if the max volume is 0dB. - */ -void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, - unsigned int *tlv) -{ - u32 caps; - int nums, step; - - caps = query_amp_caps(codec, nid, dir); - nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; - step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; - step = (step + 1) * 25; - tlv[0] = SNDRV_CTL_TLVT_DB_SCALE; - tlv[1] = 2 * sizeof(unsigned int); - tlv[2] = -nums * step; - tlv[3] = step; -} -EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv); - -/* find a mixer control element with the given name */ -static struct snd_kcontrol * -_snd_hda_find_mixer_ctl(struct hda_codec *codec, - const char *name, int idx) -{ - struct snd_ctl_elem_id id; - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - id.index = idx; - if (snd_BUG_ON(strlen(name) >= sizeof(id.name))) - return NULL; - strcpy(id.name, name); - return snd_ctl_find_id(codec->bus->card, &id); -} - -/** - * snd_hda_find_mixer_ctl - Find a mixer control element with the given name - * @codec: HD-audio codec - * @name: ctl id name string - * - * Get the control element with the given id string and IFACE_MIXER. - */ -struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, - const char *name) -{ - return _snd_hda_find_mixer_ctl(codec, name, 0); -} -EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); - -static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name) -{ - int idx; - for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */ - if (!_snd_hda_find_mixer_ctl(codec, name, idx)) - return idx; - } - return -EBUSY; -} - -/** - * snd_hda_ctl_add - Add a control element and assign to the codec - * @codec: HD-audio codec - * @nid: corresponding NID (optional) - * @kctl: the control element to assign - * - * Add the given control element to an array inside the codec instance. - * All control elements belonging to a codec are supposed to be added - * by this function so that a proper clean-up works at the free or - * reconfiguration time. - * - * If non-zero @nid is passed, the NID is assigned to the control element. - * The assignment is shown in the codec proc file. - * - * snd_hda_ctl_add() checks the control subdev id field whether - * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower - * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit - * specifies if kctl->private_value is a HDA amplifier value. - */ -int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, - struct snd_kcontrol *kctl) -{ - int err; - unsigned short flags = 0; - struct hda_nid_item *item; - - if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) { - flags |= HDA_NID_ITEM_AMP; - if (nid == 0) - nid = get_amp_nid_(kctl->private_value); - } - if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0) - nid = kctl->id.subdevice & 0xffff; - if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG)) - kctl->id.subdevice = 0; - err = snd_ctl_add(codec->bus->card, kctl); - if (err < 0) - return err; - item = snd_array_new(&codec->mixers); - if (!item) - return -ENOMEM; - item->kctl = kctl; - item->nid = nid; - item->flags = flags; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_ctl_add); - -/** - * snd_hda_add_nid - Assign a NID to a control element - * @codec: HD-audio codec - * @nid: corresponding NID (optional) - * @kctl: the control element to assign - * @index: index to kctl - * - * Add the given control element to an array inside the codec instance. - * This function is used when #snd_hda_ctl_add cannot be used for 1:1 - * NID:KCTL mapping - for example "Capture Source" selector. - */ -int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, - unsigned int index, hda_nid_t nid) -{ - struct hda_nid_item *item; - - if (nid > 0) { - item = snd_array_new(&codec->nids); - if (!item) - return -ENOMEM; - item->kctl = kctl; - item->index = index; - item->nid = nid; - return 0; - } - printk(KERN_ERR "hda-codec: no NID for mapping control %s:%d:%d\n", - kctl->id.name, kctl->id.index, index); - return -EINVAL; -} -EXPORT_SYMBOL_HDA(snd_hda_add_nid); - -/** - * snd_hda_ctls_clear - Clear all controls assigned to the given codec - * @codec: HD-audio codec - */ -void snd_hda_ctls_clear(struct hda_codec *codec) -{ - int i; - struct hda_nid_item *items = codec->mixers.list; - for (i = 0; i < codec->mixers.used; i++) - snd_ctl_remove(codec->bus->card, items[i].kctl); - snd_array_free(&codec->mixers); - snd_array_free(&codec->nids); -} - -/* pseudo device locking - * toggle card->shutdown to allow/disallow the device access (as a hack) - */ -static int hda_lock_devices(struct snd_card *card) -{ - spin_lock(&card->files_lock); - if (card->shutdown) { - spin_unlock(&card->files_lock); - return -EINVAL; - } - card->shutdown = 1; - spin_unlock(&card->files_lock); - return 0; -} - -static void hda_unlock_devices(struct snd_card *card) -{ - spin_lock(&card->files_lock); - card->shutdown = 0; - spin_unlock(&card->files_lock); -} - -/** - * snd_hda_codec_reset - Clear all objects assigned to the codec - * @codec: HD-audio codec - * - * This frees the all PCM and control elements assigned to the codec, and - * clears the caches and restores the pin default configurations. - * - * When a device is being used, it returns -EBSY. If successfully freed, - * returns zero. - */ -int snd_hda_codec_reset(struct hda_codec *codec) -{ - struct snd_card *card = codec->bus->card; - int i, pcm; - - if (hda_lock_devices(card) < 0) - return -EBUSY; - /* check whether the codec isn't used by any mixer or PCM streams */ - if (!list_empty(&card->ctl_files)) { - hda_unlock_devices(card); - return -EBUSY; - } - for (pcm = 0; pcm < codec->num_pcms; pcm++) { - struct hda_pcm *cpcm = &codec->pcm_info[pcm]; - if (!cpcm->pcm) - continue; - if (cpcm->pcm->streams[0].substream_opened || - cpcm->pcm->streams[1].substream_opened) { - hda_unlock_devices(card); - return -EBUSY; - } - } - - /* OK, let it free */ - -#ifdef CONFIG_SND_HDA_POWER_SAVE - cancel_delayed_work(&codec->power_work); - flush_workqueue(codec->bus->workq); -#endif - snd_hda_ctls_clear(codec); - /* relase PCMs */ - for (i = 0; i < codec->num_pcms; i++) { - if (codec->pcm_info[i].pcm) { - snd_device_free(card, codec->pcm_info[i].pcm); - clear_bit(codec->pcm_info[i].device, - codec->bus->pcm_dev_bits); - } - } - if (codec->patch_ops.free) - codec->patch_ops.free(codec); - snd_hda_jack_tbl_clear(codec); - codec->proc_widget_hook = NULL; - codec->spec = NULL; - free_hda_cache(&codec->amp_cache); - free_hda_cache(&codec->cmd_cache); - init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); - init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); - /* free only driver_pins so that init_pins + user_pins are restored */ - snd_array_free(&codec->driver_pins); - restore_pincfgs(codec); - codec->num_pcms = 0; - codec->pcm_info = NULL; - codec->preset = NULL; - memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); - codec->slave_dig_outs = NULL; - codec->spdif_status_reset = 0; - module_put(codec->owner); - codec->owner = NULL; - - /* allow device access again */ - hda_unlock_devices(card); - return 0; -} - -typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); - -/* apply the function to all matching slave ctls in the mixer list */ -static int map_slaves(struct hda_codec *codec, const char * const *slaves, - const char *suffix, map_slave_func_t func, void *data) -{ - struct hda_nid_item *items; - const char * const *s; - int i, err; - - items = codec->mixers.list; - for (i = 0; i < codec->mixers.used; i++) { - struct snd_kcontrol *sctl = items[i].kctl; - if (!sctl || !sctl->id.name || - sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) - continue; - for (s = slaves; *s; s++) { - char tmpname[sizeof(sctl->id.name)]; - const char *name = *s; - if (suffix) { - snprintf(tmpname, sizeof(tmpname), "%s %s", - name, suffix); - name = tmpname; - } - if (!strcmp(sctl->id.name, name)) { - err = func(data, sctl); - if (err) - return err; - break; - } - } - } - return 0; -} - -static int check_slave_present(void *data, struct snd_kcontrol *sctl) -{ - return 1; -} - -/* guess the value corresponding to 0dB */ -static int get_kctl_0dB_offset(struct snd_kcontrol *kctl) -{ - int _tlv[4]; - const int *tlv = NULL; - int val = -1; - - if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - /* FIXME: set_fs() hack for obtaining user-space TLV data */ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv)) - tlv = _tlv; - set_fs(fs); - } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) - tlv = kctl->tlv.p; - if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) - val = -tlv[2] / tlv[3]; - return val; -} - -/* call kctl->put with the given value(s) */ -static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) -{ - struct snd_ctl_elem_value *ucontrol; - ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL); - if (!ucontrol) - return -ENOMEM; - ucontrol->value.integer.value[0] = val; - ucontrol->value.integer.value[1] = val; - kctl->put(kctl, ucontrol); - kfree(ucontrol); - return 0; -} - -/* initialize the slave volume with 0dB */ -static int init_slave_0dB(void *data, struct snd_kcontrol *slave) -{ - int offset = get_kctl_0dB_offset(slave); - if (offset > 0) - put_kctl_with_value(slave, offset); - return 0; -} - -/* unmute the slave */ -static int init_slave_unmute(void *data, struct snd_kcontrol *slave) -{ - return put_kctl_with_value(slave, 1); -} - -/** - * snd_hda_add_vmaster - create a virtual master control and add slaves - * @codec: HD-audio codec - * @name: vmaster control name - * @tlv: TLV data (optional) - * @slaves: slave control names (optional) - * @suffix: suffix string to each slave name (optional) - * @init_slave_vol: initialize slaves to unmute/0dB - * @ctl_ret: store the vmaster kcontrol in return - * - * Create a virtual master control with the given name. The TLV data - * must be either NULL or a valid data. - * - * @slaves is a NULL-terminated array of strings, each of which is a - * slave control name. All controls with these names are assigned to - * the new virtual master control. - * - * This function returns zero if successful or a negative error code. - */ -int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, - unsigned int *tlv, const char * const *slaves, - const char *suffix, bool init_slave_vol, - struct snd_kcontrol **ctl_ret) -{ - struct snd_kcontrol *kctl; - int err; - - if (ctl_ret) - *ctl_ret = NULL; - - err = map_slaves(codec, slaves, suffix, check_slave_present, NULL); - if (err != 1) { - snd_printdd("No slave found for %s\n", name); - return 0; - } - kctl = snd_ctl_make_virtual_master(name, tlv); - if (!kctl) - return -ENOMEM; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - - err = map_slaves(codec, slaves, suffix, - (map_slave_func_t)snd_ctl_add_slave, kctl); - if (err < 0) - return err; - - /* init with master mute & zero volume */ - put_kctl_with_value(kctl, 0); - if (init_slave_vol) - map_slaves(codec, slaves, suffix, - tlv ? init_slave_0dB : init_slave_unmute, kctl); - - if (ctl_ret) - *ctl_ret = kctl; - return 0; -} -EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster); - -/* - * mute-LED control using vmaster - */ -static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "Off", "On", "Follow Master" - }; - unsigned int index; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - index = uinfo->value.enumerated.item; - if (index >= 3) - index = 2; - strcpy(uinfo->value.enumerated.name, texts[index]); - return 0; -} - -static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = hook->mute_mode; - return 0; -} - -static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol); - unsigned int old_mode = hook->mute_mode; - - hook->mute_mode = ucontrol->value.enumerated.item[0]; - if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER) - hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; - if (old_mode == hook->mute_mode) - return 0; - snd_hda_sync_vmaster_hook(hook); - return 1; -} - -static struct snd_kcontrol_new vmaster_mute_mode = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mute-LED Mode", - .info = vmaster_mute_mode_info, - .get = vmaster_mute_mode_get, - .put = vmaster_mute_mode_put, -}; - -/* - * Add a mute-LED hook with the given vmaster switch kctl - * "Mute-LED Mode" control is automatically created and associated with - * the given hook. - */ -int snd_hda_add_vmaster_hook(struct hda_codec *codec, - struct hda_vmaster_mute_hook *hook, - bool expose_enum_ctl) -{ - struct snd_kcontrol *kctl; - - if (!hook->hook || !hook->sw_kctl) - return 0; - snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); - hook->codec = codec; - hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; - if (!expose_enum_ctl) - return 0; - kctl = snd_ctl_new1(&vmaster_mute_mode, hook); - if (!kctl) - return -ENOMEM; - return snd_hda_ctl_add(codec, 0, kctl); -} -EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook); - -/* - * Call the hook with the current value for synchronization - * Should be called in init callback - */ -void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook) -{ - if (!hook->hook || !hook->codec) - return; - switch (hook->mute_mode) { - case HDA_VMUTE_FOLLOW_MASTER: - snd_ctl_sync_vmaster_hook(hook->sw_kctl); - break; - default: - hook->hook(hook->codec, hook->mute_mode); - break; - } -} -EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook); - - -/** - * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int chs = get_amp_channels(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = chs == 3 ? 2 : 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info); - -/** - * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = get_amp_nid(kcontrol); - int chs = get_amp_channels(kcontrol); - int dir = get_amp_direction(kcontrol); - int idx = get_amp_index(kcontrol); - long *valp = ucontrol->value.integer.value; - - if (chs & 1) - *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & - HDA_AMP_MUTE) ? 0 : 1; - if (chs & 2) - *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & - HDA_AMP_MUTE) ? 0 : 1; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get); - -/** - * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = get_amp_nid(kcontrol); - int chs = get_amp_channels(kcontrol); - int dir = get_amp_direction(kcontrol); - int idx = get_amp_index(kcontrol); - long *valp = ucontrol->value.integer.value; - int change = 0; - - snd_hda_power_up(codec); - if (chs & 1) { - change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, - HDA_AMP_MUTE, - *valp ? 0 : HDA_AMP_MUTE); - valp++; - } - if (chs & 2) - change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, - HDA_AMP_MUTE, - *valp ? 0 : HDA_AMP_MUTE); - hda_call_check_power_status(codec, nid); - snd_hda_power_down(codec); - return change; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put); - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -/** - * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch - * - * This function calls snd_hda_enable_beep_device(), which behaves differently - * depending on beep_mode option. - */ -int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - long *valp = ucontrol->value.integer.value; - - snd_hda_enable_beep_device(codec, *valp); - return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); -#endif /* CONFIG_SND_HDA_INPUT_BEEP */ - -/* - * bound volume controls - * - * bind multiple volumes (# indices, from 0) - */ - -#define AMP_VAL_IDX_SHIFT 19 -#define AMP_VAL_IDX_MASK (0x0f<<19) - -/** - * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_MUTE*() macros. - */ -int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned long pval; - int err; - - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ - err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get); - -/** - * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_MUTE*() macros. - */ -int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned long pval; - int i, indices, err = 0, change = 0; - - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; - for (i = 0; i < indices; i++) { - kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | - (i << AMP_VAL_IDX_SHIFT); - err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); - if (err < 0) - break; - change |= err; - } - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); - return err < 0 ? err : change; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put); - -/** - * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->info(kcontrol, uinfo); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info); - -/** - * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->get(kcontrol, ucontrol); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get); - -/** - * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - unsigned long *vals; - int err = 0, change = 0; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - for (vals = c->values; *vals; vals++) { - kcontrol->private_value = *vals; - err = c->ops->put(kcontrol, ucontrol); - if (err < 0) - break; - change |= err; - } - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err < 0 ? err : change; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put); - -/** - * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() macro. - */ -int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->tlv(kcontrol, op_flag, size, tlv); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv); - -struct hda_ctl_ops snd_hda_bind_vol = { - .info = snd_hda_mixer_amp_volume_info, - .get = snd_hda_mixer_amp_volume_get, - .put = snd_hda_mixer_amp_volume_put, - .tlv = snd_hda_mixer_amp_tlv -}; -EXPORT_SYMBOL_HDA(snd_hda_bind_vol); - -struct hda_ctl_ops snd_hda_bind_sw = { - .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_amp_switch_get, - .put = snd_hda_mixer_amp_switch_put, - .tlv = snd_hda_mixer_amp_tlv -}; -EXPORT_SYMBOL_HDA(snd_hda_bind_sw); - -/* - * SPDIF out controls - */ - -static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | - IEC958_AES0_NONAUDIO | - IEC958_AES0_CON_EMPHASIS_5015 | - IEC958_AES0_CON_NOT_COPYRIGHT; - ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY | - IEC958_AES1_CON_ORIGINAL; - return 0; -} - -static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL | - IEC958_AES0_NONAUDIO | - IEC958_AES0_PRO_EMPHASIS_5015; - return 0; -} - -static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - int idx = kcontrol->private_value; - struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); - - ucontrol->value.iec958.status[0] = spdif->status & 0xff; - ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff; - - return 0; -} - -/* convert from SPDIF status bits to HDA SPDIF bits - * bit 0 (DigEn) is always set zero (to be filled later) - */ -static unsigned short convert_from_spdif_status(unsigned int sbits) -{ - unsigned short val = 0; - - if (sbits & IEC958_AES0_PROFESSIONAL) - val |= AC_DIG1_PROFESSIONAL; - if (sbits & IEC958_AES0_NONAUDIO) - val |= AC_DIG1_NONAUDIO; - if (sbits & IEC958_AES0_PROFESSIONAL) { - if ((sbits & IEC958_AES0_PRO_EMPHASIS) == - IEC958_AES0_PRO_EMPHASIS_5015) - val |= AC_DIG1_EMPHASIS; - } else { - if ((sbits & IEC958_AES0_CON_EMPHASIS) == - IEC958_AES0_CON_EMPHASIS_5015) - val |= AC_DIG1_EMPHASIS; - if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT)) - val |= AC_DIG1_COPYRIGHT; - if (sbits & (IEC958_AES1_CON_ORIGINAL << 8)) - val |= AC_DIG1_LEVEL; - val |= sbits & (IEC958_AES1_CON_CATEGORY << 8); - } - return val; -} - -/* convert to SPDIF status bits from HDA SPDIF bits - */ -static unsigned int convert_to_spdif_status(unsigned short val) -{ - unsigned int sbits = 0; - - if (val & AC_DIG1_NONAUDIO) - sbits |= IEC958_AES0_NONAUDIO; - if (val & AC_DIG1_PROFESSIONAL) - sbits |= IEC958_AES0_PROFESSIONAL; - if (sbits & IEC958_AES0_PROFESSIONAL) { - if (sbits & AC_DIG1_EMPHASIS) - sbits |= IEC958_AES0_PRO_EMPHASIS_5015; - } else { - if (val & AC_DIG1_EMPHASIS) - sbits |= IEC958_AES0_CON_EMPHASIS_5015; - if (!(val & AC_DIG1_COPYRIGHT)) - sbits |= IEC958_AES0_CON_NOT_COPYRIGHT; - if (val & AC_DIG1_LEVEL) - sbits |= (IEC958_AES1_CON_ORIGINAL << 8); - sbits |= val & (0x7f << 8); - } - return sbits; -} - -/* set digital convert verbs both for the given NID and its slaves */ -static void set_dig_out(struct hda_codec *codec, hda_nid_t nid, - int verb, int val) -{ - const hda_nid_t *d; - - snd_hda_codec_write_cache(codec, nid, 0, verb, val); - d = codec->slave_dig_outs; - if (!d) - return; - for (; *d; d++) - snd_hda_codec_write_cache(codec, *d, 0, verb, val); -} - -static inline void set_dig_out_convert(struct hda_codec *codec, hda_nid_t nid, - int dig1, int dig2) -{ - if (dig1 != -1) - set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_1, dig1); - if (dig2 != -1) - set_dig_out(codec, nid, AC_VERB_SET_DIGI_CONVERT_2, dig2); -} - -static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - int idx = kcontrol->private_value; - struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); - hda_nid_t nid = spdif->nid; - unsigned short val; - int change; - - mutex_lock(&codec->spdif_mutex); - spdif->status = ucontrol->value.iec958.status[0] | - ((unsigned int)ucontrol->value.iec958.status[1] << 8) | - ((unsigned int)ucontrol->value.iec958.status[2] << 16) | - ((unsigned int)ucontrol->value.iec958.status[3] << 24); - val = convert_from_spdif_status(spdif->status); - val |= spdif->ctls & 1; - change = spdif->ctls != val; - spdif->ctls = val; - if (change && nid != (u16)-1) - set_dig_out_convert(codec, nid, val & 0xff, (val >> 8) & 0xff); - mutex_unlock(&codec->spdif_mutex); - return change; -} - -#define snd_hda_spdif_out_switch_info snd_ctl_boolean_mono_info - -static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - int idx = kcontrol->private_value; - struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); - - ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE; - return 0; -} - -static inline void set_spdif_ctls(struct hda_codec *codec, hda_nid_t nid, - int dig1, int dig2) -{ - set_dig_out_convert(codec, nid, dig1, dig2); - /* unmute amp switch (if any) */ - if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) && - (dig1 & AC_DIG1_ENABLE)) - snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, - HDA_AMP_MUTE, 0); -} - -static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - int idx = kcontrol->private_value; - struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); - hda_nid_t nid = spdif->nid; - unsigned short val; - int change; - - mutex_lock(&codec->spdif_mutex); - val = spdif->ctls & ~AC_DIG1_ENABLE; - if (ucontrol->value.integer.value[0]) - val |= AC_DIG1_ENABLE; - change = spdif->ctls != val; - spdif->ctls = val; - if (change && nid != (u16)-1) - set_spdif_ctls(codec, nid, val & 0xff, -1); - mutex_unlock(&codec->spdif_mutex); - return change; -} - -static struct snd_kcontrol_new dig_mixes[] = { - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), - .info = snd_hda_spdif_mask_info, - .get = snd_hda_spdif_cmask_get, - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), - .info = snd_hda_spdif_mask_info, - .get = snd_hda_spdif_pmask_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = snd_hda_spdif_mask_info, - .get = snd_hda_spdif_default_get, - .put = snd_hda_spdif_default_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), - .info = snd_hda_spdif_out_switch_info, - .get = snd_hda_spdif_out_switch_get, - .put = snd_hda_spdif_out_switch_put, - }, - { } /* end */ -}; - -/** - * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls - * @codec: the HDA codec - * @nid: audio out widget NID - * - * Creates controls related with the SPDIF output. - * Called from each patch supporting the SPDIF out. - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, - hda_nid_t associated_nid, - hda_nid_t cvt_nid) -{ - int err; - struct snd_kcontrol *kctl; - struct snd_kcontrol_new *dig_mix; - int idx; - struct hda_spdif_out *spdif; - - idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch"); - if (idx < 0) { - printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); - return -EBUSY; - } - spdif = snd_array_new(&codec->spdif_out); - for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) { - kctl = snd_ctl_new1(dig_mix, codec); - if (!kctl) - return -ENOMEM; - kctl->id.index = idx; - kctl->private_value = codec->spdif_out.used - 1; - err = snd_hda_ctl_add(codec, associated_nid, kctl); - if (err < 0) - return err; - } - spdif->nid = cvt_nid; - spdif->ctls = snd_hda_codec_read(codec, cvt_nid, 0, - AC_VERB_GET_DIGI_CONVERT_1, 0); - spdif->status = convert_to_spdif_status(spdif->ctls); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls); - -struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec, - hda_nid_t nid) -{ - int i; - for (i = 0; i < codec->spdif_out.used; i++) { - struct hda_spdif_out *spdif = - snd_array_elem(&codec->spdif_out, i); - if (spdif->nid == nid) - return spdif; - } - return NULL; -} -EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid); - -void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx) -{ - struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); - - mutex_lock(&codec->spdif_mutex); - spdif->nid = (u16)-1; - mutex_unlock(&codec->spdif_mutex); -} -EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign); - -void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid) -{ - struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx); - unsigned short val; - - mutex_lock(&codec->spdif_mutex); - if (spdif->nid != nid) { - spdif->nid = nid; - val = spdif->ctls; - set_spdif_ctls(codec, nid, val & 0xff, (val >> 8) & 0xff); - } - mutex_unlock(&codec->spdif_mutex); -} -EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_assign); - -/* - * SPDIF sharing with analog output - */ -static int spdif_share_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = mout->share_spdif; - return 0; -} - -static int spdif_share_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_multi_out *mout = snd_kcontrol_chip(kcontrol); - mout->share_spdif = !!ucontrol->value.integer.value[0]; - return 0; -} - -static struct snd_kcontrol_new spdif_share_sw = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Default PCM Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = spdif_share_sw_get, - .put = spdif_share_sw_put, -}; - -/** - * snd_hda_create_spdif_share_sw - create Default PCM switch - * @codec: the HDA codec - * @mout: multi-out instance - */ -int snd_hda_create_spdif_share_sw(struct hda_codec *codec, - struct hda_multi_out *mout) -{ - if (!mout->dig_out_nid) - return 0; - /* ATTENTION: here mout is passed as private_data, instead of codec */ - return snd_hda_ctl_add(codec, mout->dig_out_nid, - snd_ctl_new1(&spdif_share_sw, mout)); -} -EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw); - -/* - * SPDIF input - */ - -#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info - -static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = codec->spdif_in_enable; - return 0; -} - -static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value; - unsigned int val = !!ucontrol->value.integer.value[0]; - int change; - - mutex_lock(&codec->spdif_mutex); - change = codec->spdif_in_enable != val; - if (change) { - codec->spdif_in_enable = val; - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_DIGI_CONVERT_1, val); - } - mutex_unlock(&codec->spdif_mutex); - return change; -} - -static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value; - unsigned short val; - unsigned int sbits; - - val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT_1, 0); - sbits = convert_to_spdif_status(val); - ucontrol->value.iec958.status[0] = sbits; - ucontrol->value.iec958.status[1] = sbits >> 8; - ucontrol->value.iec958.status[2] = sbits >> 16; - ucontrol->value.iec958.status[3] = sbits >> 24; - return 0; -} - -static struct snd_kcontrol_new dig_in_ctls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), - .info = snd_hda_spdif_in_switch_info, - .get = snd_hda_spdif_in_switch_get, - .put = snd_hda_spdif_in_switch_put, - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), - .info = snd_hda_spdif_mask_info, - .get = snd_hda_spdif_in_status_get, - }, - { } /* end */ -}; - -/** - * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls - * @codec: the HDA codec - * @nid: audio in widget NID - * - * Creates controls related with the SPDIF input. - * Called from each patch supporting the SPDIF in. - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) -{ - int err; - struct snd_kcontrol *kctl; - struct snd_kcontrol_new *dig_mix; - int idx; - - idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch"); - if (idx < 0) { - printk(KERN_ERR "hda_codec: too many IEC958 inputs\n"); - return -EBUSY; - } - for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) { - kctl = snd_ctl_new1(dig_mix, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = nid; - err = snd_hda_ctl_add(codec, nid, kctl); - if (err < 0) - return err; - } - codec->spdif_in_enable = - snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DIGI_CONVERT_1, 0) & - AC_DIG1_ENABLE; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls); - -#ifdef CONFIG_PM -/* - * command cache - */ - -/* build a 32bit cache key with the widget id and the command parameter */ -#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid) -#define get_cmd_cache_nid(key) ((key) & 0xff) -#define get_cmd_cache_cmd(key) (((key) >> 8) & 0xffff) - -/** - * snd_hda_codec_write_cache - send a single command with caching - * @codec: the HDA codec - * @nid: NID to send the command - * @direct: direct flag - * @verb: the verb to send - * @parm: the parameter for the verb - * - * Send a single command without waiting for response. - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, - int direct, unsigned int verb, unsigned int parm) -{ - int err = snd_hda_codec_write(codec, nid, direct, verb, parm); - struct hda_cache_head *c; - u32 key; - - if (err < 0) - return err; - /* parm may contain the verb stuff for get/set amp */ - verb = verb | (parm >> 8); - parm &= 0xff; - key = build_cmd_cache_key(nid, verb); - mutex_lock(&codec->bus->cmd_mutex); - c = get_alloc_hash(&codec->cmd_cache, key); - if (c) - c->val = parm; - mutex_unlock(&codec->bus->cmd_mutex); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); - -/** - * snd_hda_codec_update_cache - check cache and write the cmd only when needed - * @codec: the HDA codec - * @nid: NID to send the command - * @direct: direct flag - * @verb: the verb to send - * @parm: the parameter for the verb - * - * This function works like snd_hda_codec_write_cache(), but it doesn't send - * command if the parameter is already identical with the cached value. - * If not, it sends the command and refreshes the cache. - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, - int direct, unsigned int verb, unsigned int parm) -{ - struct hda_cache_head *c; - 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); - mutex_lock(&codec->bus->cmd_mutex); - c = get_hash(&codec->cmd_cache, key); - if (c && c->val == parm) { - mutex_unlock(&codec->bus->cmd_mutex); - return 0; - } - mutex_unlock(&codec->bus->cmd_mutex); - return snd_hda_codec_write_cache(codec, nid, direct, verb, parm); -} -EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache); - -/** - * snd_hda_codec_resume_cache - Resume the all commands from the cache - * @codec: HD-audio codec - * - * Execute all verbs recorded in the command caches to resume. - */ -void snd_hda_codec_resume_cache(struct hda_codec *codec) -{ - struct hda_cache_head *buffer = codec->cmd_cache.buf.list; - int i; - - for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) { - u32 key = buffer->key; - if (!key) - continue; - snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0, - get_cmd_cache_cmd(key), buffer->val); - } -} -EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache); - -/** - * snd_hda_sequence_write_cache - sequence writes with caching - * @codec: the HDA codec - * @seq: VERB array to send - * - * Send the commands sequentially from the given array. - * Thte commands are recorded on cache for power-save and resume. - * The array must be terminated with NID=0. - */ -void snd_hda_sequence_write_cache(struct hda_codec *codec, - const struct hda_verb *seq) -{ - for (; seq->nid; seq++) - snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb, - seq->param); -} -EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache); -#endif /* CONFIG_PM */ - -void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, - unsigned int power_state, - bool eapd_workaround) -{ - hda_nid_t nid = codec->start_nid; - int i; - - for (i = 0; i < codec->num_nodes; i++, nid++) { - unsigned int wcaps = get_wcaps(codec, nid); - if (!(wcaps & AC_WCAP_POWER)) - continue; - /* don't power down the widget if it controls eapd and - * EAPD_BTLENABLE is set. - */ - if (eapd_workaround && power_state == AC_PWRST_D3 && - get_wcaps_type(wcaps) == AC_WID_PIN && - (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) { - int eapd = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_EAPD_BTLENABLE, 0); - if (eapd & 0x02) - continue; - } - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, - power_state); - } - - if (power_state == AC_PWRST_D0) { - unsigned long end_time; - int state; - /* wait until the codec reachs to D0 */ - end_time = jiffies + msecs_to_jiffies(500); - do { - state = snd_hda_codec_read(codec, fg, 0, - AC_VERB_GET_POWER_STATE, 0); - if (state == power_state) - break; - msleep(1); - } while (time_after_eq(end_time, jiffies)); - } -} -EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); - -/* - * set power state of the codec - */ -static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, - unsigned int power_state) -{ - if (codec->patch_ops.set_power_state) { - codec->patch_ops.set_power_state(codec, fg, power_state); - return; - } - - /* this delay seems necessary to avoid click noise at power-down */ - if (power_state == AC_PWRST_D3) - msleep(100); - snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, - power_state); - snd_hda_codec_set_power_to_all(codec, fg, power_state, true); -} - -#ifdef CONFIG_SND_HDA_HWDEP -/* execute additional init verbs */ -static void hda_exec_init_verbs(struct hda_codec *codec) -{ - if (codec->init_verbs.list) - snd_hda_sequence_write(codec, codec->init_verbs.list); -} -#else -static inline void hda_exec_init_verbs(struct hda_codec *codec) {} -#endif - -#ifdef CONFIG_PM -/* - * call suspend and power-down; used both from PM and power-save - */ -static void hda_call_codec_suspend(struct hda_codec *codec) -{ - if (codec->patch_ops.suspend) - codec->patch_ops.suspend(codec, PMSG_SUSPEND); - hda_cleanup_all_streams(codec); - hda_set_power_state(codec, - codec->afg ? codec->afg : codec->mfg, - AC_PWRST_D3); -#ifdef CONFIG_SND_HDA_POWER_SAVE - snd_hda_update_power_acct(codec); - cancel_delayed_work(&codec->power_work); - codec->power_on = 0; - codec->power_transition = 0; - codec->power_jiffies = jiffies; -#endif -} - -/* - * kick up codec; used both from PM and power-save - */ -static void hda_call_codec_resume(struct hda_codec *codec) -{ - hda_set_power_state(codec, - codec->afg ? codec->afg : codec->mfg, - AC_PWRST_D0); - restore_pincfgs(codec); /* restore all current pin configs */ - restore_shutup_pins(codec); - hda_exec_init_verbs(codec); - snd_hda_jack_set_dirty_all(codec); - if (codec->patch_ops.resume) - codec->patch_ops.resume(codec); - else { - if (codec->patch_ops.init) - codec->patch_ops.init(codec); - snd_hda_codec_resume_amp(codec); - snd_hda_codec_resume_cache(codec); - } -} -#endif /* CONFIG_PM */ - - -/** - * snd_hda_build_controls - build mixer controls - * @bus: the BUS - * - * Creates mixer controls for each codec included in the bus. - * - * Returns 0 if successful, otherwise a negative error code. - */ -int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) -{ - struct hda_codec *codec; - - list_for_each_entry(codec, &bus->codec_list, list) { - int err = snd_hda_codec_build_controls(codec); - if (err < 0) { - printk(KERN_ERR "hda_codec: cannot build controls " - "for #%d (error %d)\n", codec->addr, err); - err = snd_hda_codec_reset(codec); - if (err < 0) { - printk(KERN_ERR - "hda_codec: cannot revert codec\n"); - return err; - } - } - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_build_controls); - -int snd_hda_codec_build_controls(struct hda_codec *codec) -{ - int err = 0; - hda_exec_init_verbs(codec); - /* continue to initialize... */ - if (codec->patch_ops.init) - err = codec->patch_ops.init(codec); - if (!err && codec->patch_ops.build_controls) - err = codec->patch_ops.build_controls(codec); - if (err < 0) - return err; - return 0; -} - -/* - * stream formats - */ -struct hda_rate_tbl { - unsigned int hz; - unsigned int alsa_bits; - unsigned int hda_fmt; -}; - -/* rate = base * mult / div */ -#define HDA_RATE(base, mult, div) \ - (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ - (((div) - 1) << AC_FMT_DIV_SHIFT)) - -static struct hda_rate_tbl rate_bits[] = { - /* rate in Hz, ALSA rate bitmask, HDA format value */ - - /* autodetected value used in snd_hda_query_supported_pcm */ - { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, - { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, - { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, - { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, - { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, - { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, - { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, - { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, - { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, - { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, - { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, -#define AC_PAR_PCM_RATE_BITS 11 - /* up to bits 10, 384kHZ isn't supported properly */ - - /* not autodetected value */ - { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, - - { 0 } /* terminator */ -}; - -/** - * snd_hda_calc_stream_format - calculate format bitset - * @rate: the sample rate - * @channels: the number of channels - * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) - * @maxbps: the max. bps - * - * Calculate the format bitset from the given rate, channels and th PCM format. - * - * Return zero if invalid. - */ -unsigned int snd_hda_calc_stream_format(unsigned int rate, - unsigned int channels, - unsigned int format, - unsigned int maxbps, - unsigned short spdif_ctls) -{ - int i; - unsigned int val = 0; - - for (i = 0; rate_bits[i].hz; i++) - if (rate_bits[i].hz == rate) { - val = rate_bits[i].hda_fmt; - break; - } - if (!rate_bits[i].hz) { - snd_printdd("invalid rate %d\n", rate); - return 0; - } - - if (channels == 0 || channels > 8) { - snd_printdd("invalid channels %d\n", channels); - return 0; - } - val |= channels - 1; - - switch (snd_pcm_format_width(format)) { - case 8: - val |= AC_FMT_BITS_8; - break; - case 16: - val |= AC_FMT_BITS_16; - break; - case 20: - case 24: - case 32: - if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) - val |= AC_FMT_BITS_32; - else if (maxbps >= 24) - val |= AC_FMT_BITS_24; - else - val |= AC_FMT_BITS_20; - break; - default: - snd_printdd("invalid format width %d\n", - snd_pcm_format_width(format)); - return 0; - } - - if (spdif_ctls & AC_DIG1_NONAUDIO) - val |= AC_FMT_TYPE_NON_PCM; - - return val; -} -EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); - -static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int val = 0; - if (nid != codec->afg && - (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) - val = snd_hda_param_read(codec, nid, AC_PAR_PCM); - if (!val || val == -1) - val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); - if (!val || val == -1) - return 0; - return val; -} - -static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid) -{ - return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid), - get_pcm_param); -} - -static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); - if (!streams || streams == -1) - streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); - if (!streams || streams == -1) - return 0; - return streams; -} - -static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid) -{ - return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid), - get_stream_param); -} - -/** - * snd_hda_query_supported_pcm - query the supported PCM rates and formats - * @codec: the HDA codec - * @nid: NID to query - * @ratesp: the pointer to store the detected rate bitflags - * @formatsp: the pointer to store the detected formats - * @bpsp: the pointer to store the detected format widths - * - * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp - * or @bsps argument is ignored. - * - * Returns 0 if successful, otherwise a negative error code. - */ -int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, - u32 *ratesp, u64 *formatsp, unsigned int *bpsp) -{ - unsigned int i, val, wcaps; - - wcaps = get_wcaps(codec, nid); - val = query_pcm_param(codec, nid); - - if (ratesp) { - u32 rates = 0; - for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) { - if (val & (1 << i)) - rates |= rate_bits[i].alsa_bits; - } - if (rates == 0) { - snd_printk(KERN_ERR "hda_codec: rates == 0 " - "(nid=0x%x, val=0x%x, ovrd=%i)\n", - nid, val, - (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); - return -EIO; - } - *ratesp = rates; - } - - if (formatsp || bpsp) { - u64 formats = 0; - unsigned int streams, bps; - - streams = query_stream_param(codec, nid); - if (!streams) - return -EIO; - - bps = 0; - if (streams & AC_SUPFMT_PCM) { - if (val & AC_SUPPCM_BITS_8) { - formats |= SNDRV_PCM_FMTBIT_U8; - bps = 8; - } - if (val & AC_SUPPCM_BITS_16) { - formats |= SNDRV_PCM_FMTBIT_S16_LE; - bps = 16; - } - if (wcaps & AC_WCAP_DIGITAL) { - if (val & AC_SUPPCM_BITS_32) - formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; - if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24)) - formats |= SNDRV_PCM_FMTBIT_S32_LE; - if (val & AC_SUPPCM_BITS_24) - bps = 24; - else if (val & AC_SUPPCM_BITS_20) - bps = 20; - } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24| - AC_SUPPCM_BITS_32)) { - formats |= SNDRV_PCM_FMTBIT_S32_LE; - if (val & AC_SUPPCM_BITS_32) - bps = 32; - else if (val & AC_SUPPCM_BITS_24) - bps = 24; - else if (val & AC_SUPPCM_BITS_20) - bps = 20; - } - } - if (streams & AC_SUPFMT_FLOAT32) { - formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; - if (!bps) - bps = 32; - } - if (streams == AC_SUPFMT_AC3) { - /* should be exclusive */ - /* temporary hack: we have still no proper support - * for the direct AC3 stream... - */ - formats |= SNDRV_PCM_FMTBIT_U8; - bps = 8; - } - if (formats == 0) { - snd_printk(KERN_ERR "hda_codec: formats == 0 " - "(nid=0x%x, val=0x%x, ovrd=%i, " - "streams=0x%x)\n", - nid, val, - (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, - streams); - return -EIO; - } - if (formatsp) - *formatsp = formats; - if (bpsp) - *bpsp = bps; - } - - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_query_supported_pcm); - -/** - * snd_hda_is_supported_format - Check the validity of the format - * @codec: HD-audio codec - * @nid: NID to check - * @format: the HD-audio format value to check - * - * Check whether the given node supports the format value. - * - * Returns 1 if supported, 0 if not. - */ -int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, - unsigned int format) -{ - int i; - unsigned int val = 0, rate, stream; - - val = query_pcm_param(codec, nid); - if (!val) - return 0; - - rate = format & 0xff00; - for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) - if (rate_bits[i].hda_fmt == rate) { - if (val & (1 << i)) - break; - return 0; - } - if (i >= AC_PAR_PCM_RATE_BITS) - return 0; - - stream = query_stream_param(codec, nid); - if (!stream) - return 0; - - if (stream & AC_SUPFMT_PCM) { - switch (format & 0xf0) { - case 0x00: - if (!(val & AC_SUPPCM_BITS_8)) - return 0; - break; - case 0x10: - if (!(val & AC_SUPPCM_BITS_16)) - return 0; - break; - case 0x20: - if (!(val & AC_SUPPCM_BITS_20)) - return 0; - break; - case 0x30: - if (!(val & AC_SUPPCM_BITS_24)) - return 0; - break; - case 0x40: - if (!(val & AC_SUPPCM_BITS_32)) - return 0; - break; - default: - return 0; - } - } else { - /* FIXME: check for float32 and AC3? */ - } - - return 1; -} -EXPORT_SYMBOL_HDA(snd_hda_is_supported_format); - -/* - * PCM stuff - */ -static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - return 0; -} - -static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format); - return 0; -} - -static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - snd_hda_codec_cleanup_stream(codec, hinfo->nid); - return 0; -} - -static int set_pcm_default_values(struct hda_codec *codec, - struct hda_pcm_stream *info) -{ - int err; - - /* query support PCM information from the given NID */ - if (info->nid && (!info->rates || !info->formats)) { - err = snd_hda_query_supported_pcm(codec, info->nid, - info->rates ? NULL : &info->rates, - info->formats ? NULL : &info->formats, - info->maxbps ? NULL : &info->maxbps); - if (err < 0) - return err; - } - if (info->ops.open == NULL) - info->ops.open = hda_pcm_default_open_close; - if (info->ops.close == NULL) - info->ops.close = hda_pcm_default_open_close; - if (info->ops.prepare == NULL) { - if (snd_BUG_ON(!info->nid)) - return -EINVAL; - info->ops.prepare = hda_pcm_default_prepare; - } - if (info->ops.cleanup == NULL) { - if (snd_BUG_ON(!info->nid)) - return -EINVAL; - info->ops.cleanup = hda_pcm_default_cleanup; - } - return 0; -} - -/* - * codec prepare/cleanup entries - */ -int snd_hda_codec_prepare(struct hda_codec *codec, - struct hda_pcm_stream *hinfo, - unsigned int stream, - unsigned int format, - struct snd_pcm_substream *substream) -{ - int ret; - mutex_lock(&codec->bus->prepare_mutex); - ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream); - if (ret >= 0) - purify_inactive_streams(codec); - mutex_unlock(&codec->bus->prepare_mutex); - return ret; -} -EXPORT_SYMBOL_HDA(snd_hda_codec_prepare); - -void snd_hda_codec_cleanup(struct hda_codec *codec, - struct hda_pcm_stream *hinfo, - struct snd_pcm_substream *substream) -{ - mutex_lock(&codec->bus->prepare_mutex); - hinfo->ops.cleanup(hinfo, codec, substream); - mutex_unlock(&codec->bus->prepare_mutex); -} -EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup); - -/* global */ -const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { - "Audio", "SPDIF", "HDMI", "Modem" -}; - -/* - * get the empty PCM device number to assign - * - * note the max device number is limited by HDA_MAX_PCMS, currently 10 - */ -static int get_empty_pcm_device(struct hda_bus *bus, int type) -{ - /* audio device indices; not linear to keep compatibility */ - static int audio_idx[HDA_PCM_NTYPES][5] = { - [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 }, - [HDA_PCM_TYPE_SPDIF] = { 1, -1 }, - [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 }, - [HDA_PCM_TYPE_MODEM] = { 6, -1 }, - }; - int i; - - if (type >= HDA_PCM_NTYPES) { - snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); - return -EINVAL; - } - - for (i = 0; audio_idx[type][i] >= 0 ; i++) - if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) - return audio_idx[type][i]; - - /* non-fixed slots starting from 10 */ - for (i = 10; i < 32; i++) { - if (!test_and_set_bit(i, bus->pcm_dev_bits)) - return i; - } - - snd_printk(KERN_WARNING "Too many %s devices\n", - snd_hda_pcm_type_name[type]); - return -EAGAIN; -} - -/* - * attach a new PCM stream - */ -static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) -{ - struct hda_bus *bus = codec->bus; - struct hda_pcm_stream *info; - int stream, err; - - if (snd_BUG_ON(!pcm->name)) - return -EINVAL; - for (stream = 0; stream < 2; stream++) { - info = &pcm->stream[stream]; - if (info->substreams) { - err = set_pcm_default_values(codec, info); - if (err < 0) - return err; - } - } - return bus->ops.attach_pcm(bus, codec, pcm); -} - -/* assign all PCMs of the given codec */ -int snd_hda_codec_build_pcms(struct hda_codec *codec) -{ - unsigned int pcm; - int err; - - if (!codec->num_pcms) { - if (!codec->patch_ops.build_pcms) - return 0; - err = codec->patch_ops.build_pcms(codec); - if (err < 0) { - printk(KERN_ERR "hda_codec: cannot build PCMs" - "for #%d (error %d)\n", codec->addr, err); - err = snd_hda_codec_reset(codec); - if (err < 0) { - printk(KERN_ERR - "hda_codec: cannot revert codec\n"); - return err; - } - } - } - for (pcm = 0; pcm < codec->num_pcms; pcm++) { - struct hda_pcm *cpcm = &codec->pcm_info[pcm]; - int dev; - - if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) - continue; /* no substreams assigned */ - - if (!cpcm->pcm) { - dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); - if (dev < 0) - continue; /* no fatal error */ - cpcm->device = dev; - err = snd_hda_attach_pcm(codec, cpcm); - if (err < 0) { - printk(KERN_ERR "hda_codec: cannot attach " - "PCM stream %d for codec #%d\n", - dev, codec->addr); - continue; /* no fatal error */ - } - } - } - return 0; -} - -/** - * snd_hda_build_pcms - build PCM information - * @bus: the BUS - * - * Create PCM information for each codec included in the bus. - * - * The build_pcms codec patch is requested to set up codec->num_pcms and - * codec->pcm_info properly. The array is referred by the top-level driver - * to create its PCM instances. - * The allocated codec->pcm_info should be released in codec->patch_ops.free - * callback. - * - * At least, substreams, channels_min and channels_max must be filled for - * each stream. substreams = 0 indicates that the stream doesn't exist. - * When rates and/or formats are zero, the supported values are queried - * from the given nid. The nid is used also by the default ops.prepare - * and ops.cleanup callbacks. - * - * The driver needs to call ops.open in its open callback. Similarly, - * ops.close is supposed to be called in the close callback. - * ops.prepare should be called in the prepare or hw_params callback - * with the proper parameters for set up. - * ops.cleanup should be called in hw_free for clean up of streams. - * - * This function returns 0 if successful, or a negative error code. - */ -int __devinit snd_hda_build_pcms(struct hda_bus *bus) -{ - struct hda_codec *codec; - - list_for_each_entry(codec, &bus->codec_list, list) { - int err = snd_hda_codec_build_pcms(codec); - if (err < 0) - return err; - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_build_pcms); - -/** - * snd_hda_check_board_config - compare the current codec with the config table - * @codec: the HDA codec - * @num_configs: number of config enums - * @models: array of model name strings - * @tbl: configuration table, terminated by null entries - * - * Compares the modelname or PCI subsystem id of the current codec with the - * given configuration table. If a matching entry is found, returns its - * config value (supposed to be 0 or positive). - * - * If no entries are matching, the function returns a negative value. - */ -int snd_hda_check_board_config(struct hda_codec *codec, - int num_configs, const char * const *models, - const struct snd_pci_quirk *tbl) -{ - if (codec->modelname && models) { - int i; - for (i = 0; i < num_configs; i++) { - if (models[i] && - !strcmp(codec->modelname, models[i])) { - snd_printd(KERN_INFO "hda_codec: model '%s' is " - "selected\n", models[i]); - return i; - } - } - } - - if (!codec->bus->pci || !tbl) - return -1; - - tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl); - if (!tbl) - return -1; - if (tbl->value >= 0 && tbl->value < num_configs) { -#ifdef CONFIG_SND_DEBUG_VERBOSE - char tmp[10]; - const char *model = NULL; - if (models) - model = models[tbl->value]; - if (!model) { - sprintf(tmp, "#%d", tbl->value); - model = tmp; - } - snd_printdd(KERN_INFO "hda_codec: model '%s' is selected " - "for config %x:%x (%s)\n", - model, tbl->subvendor, tbl->subdevice, - (tbl->name ? tbl->name : "Unknown device")); -#endif - return tbl->value; - } - return -1; -} -EXPORT_SYMBOL_HDA(snd_hda_check_board_config); - -/** - * snd_hda_check_board_codec_sid_config - compare the current codec - subsystem ID with the - config table - - This is important for Gateway notebooks with SB450 HDA Audio - where the vendor ID of the PCI device is: - ATI Technologies Inc SB450 HDA Audio [1002:437b] - and the vendor/subvendor are found only at the codec. - - * @codec: the HDA codec - * @num_configs: number of config enums - * @models: array of model name strings - * @tbl: configuration table, terminated by null entries - * - * Compares the modelname or PCI subsystem id of the current codec with the - * given configuration table. If a matching entry is found, returns its - * config value (supposed to be 0 or positive). - * - * If no entries are matching, the function returns a negative value. - */ -int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, - int num_configs, const char * const *models, - const struct snd_pci_quirk *tbl) -{ - const struct snd_pci_quirk *q; - - /* Search for codec ID */ - for (q = tbl; q->subvendor; q++) { - unsigned int mask = 0xffff0000 | q->subdevice_mask; - unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask; - if ((codec->subsystem_id & mask) == id) - break; - } - - if (!q->subvendor) - return -1; - - tbl = q; - - if (tbl->value >= 0 && tbl->value < num_configs) { -#ifdef CONFIG_SND_DEBUG_VERBOSE - char tmp[10]; - const char *model = NULL; - if (models) - model = models[tbl->value]; - if (!model) { - sprintf(tmp, "#%d", tbl->value); - model = tmp; - } - snd_printdd(KERN_INFO "hda_codec: model '%s' is selected " - "for config %x:%x (%s)\n", - model, tbl->subvendor, tbl->subdevice, - (tbl->name ? tbl->name : "Unknown device")); -#endif - return tbl->value; - } - return -1; -} -EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config); - -/** - * snd_hda_add_new_ctls - create controls from the array - * @codec: the HDA codec - * @knew: the array of struct snd_kcontrol_new - * - * This helper function creates and add new controls in the given array. - * The array must be terminated with an empty entry as terminator. - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hda_add_new_ctls(struct hda_codec *codec, - const struct snd_kcontrol_new *knew) -{ - int err; - - for (; knew->name; knew++) { - struct snd_kcontrol *kctl; - int addr = 0, idx = 0; - if (knew->iface == -1) /* skip this codec private value */ - continue; - for (;;) { - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - if (addr > 0) - kctl->id.device = addr; - if (idx > 0) - kctl->id.index = idx; - err = snd_hda_ctl_add(codec, 0, kctl); - if (!err) - break; - /* try first with another device index corresponding to - * the codec addr; if it still fails (or it's the - * primary codec), then try another control index - */ - if (!addr && codec->addr) - addr = codec->addr; - else if (!idx && !knew->index) { - idx = find_empty_mixer_ctl_idx(codec, - knew->name); - if (idx <= 0) - return err; - } else - return err; - } - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static void hda_power_work(struct work_struct *work) -{ - struct hda_codec *codec = - container_of(work, struct hda_codec, power_work.work); - struct hda_bus *bus = codec->bus; - - if (!codec->power_on || codec->power_count) { - codec->power_transition = 0; - return; - } - - trace_hda_power_down(codec); - hda_call_codec_suspend(codec); - if (bus->ops.pm_notify) - bus->ops.pm_notify(bus); -} - -static void hda_keep_power_on(struct hda_codec *codec) -{ - codec->power_count++; - codec->power_on = 1; - codec->power_jiffies = jiffies; -} - -/* update the power on/off account with the current jiffies */ -void snd_hda_update_power_acct(struct hda_codec *codec) -{ - unsigned long delta = jiffies - codec->power_jiffies; - if (codec->power_on) - codec->power_on_acct += delta; - else - codec->power_off_acct += delta; - codec->power_jiffies += delta; -} - -/** - * snd_hda_power_up - Power-up the codec - * @codec: HD-audio codec - * - * Increment the power-up counter and power up the hardware really when - * not turned on yet. - */ -void snd_hda_power_up(struct hda_codec *codec) -{ - struct hda_bus *bus = codec->bus; - - codec->power_count++; - if (codec->power_on || codec->power_transition) - return; - - trace_hda_power_up(codec); - snd_hda_update_power_acct(codec); - codec->power_on = 1; - codec->power_jiffies = jiffies; - if (bus->ops.pm_notify) - bus->ops.pm_notify(bus); - hda_call_codec_resume(codec); - cancel_delayed_work(&codec->power_work); - codec->power_transition = 0; -} -EXPORT_SYMBOL_HDA(snd_hda_power_up); - -#define power_save(codec) \ - ((codec)->bus->power_save ? *(codec)->bus->power_save : 0) - -/** - * snd_hda_power_down - Power-down the codec - * @codec: HD-audio codec - * - * Decrement the power-up counter and schedules the power-off work if - * the counter rearches to zero. - */ -void snd_hda_power_down(struct hda_codec *codec) -{ - --codec->power_count; - if (!codec->power_on || codec->power_count || codec->power_transition) - return; - if (power_save(codec)) { - codec->power_transition = 1; /* avoid reentrance */ - queue_delayed_work(codec->bus->workq, &codec->power_work, - msecs_to_jiffies(power_save(codec) * 1000)); - } -} -EXPORT_SYMBOL_HDA(snd_hda_power_down); - -/** - * snd_hda_check_amp_list_power - Check the amp list and update the power - * @codec: HD-audio codec - * @check: the object containing an AMP list and the status - * @nid: NID to check / update - * - * Check whether the given NID is in the amp list. If it's in the list, - * check the current AMP status, and update the the power-status according - * to the mute status. - * - * This function is supposed to be set or called from the check_power_status - * patch ops. - */ -int snd_hda_check_amp_list_power(struct hda_codec *codec, - struct hda_loopback_check *check, - hda_nid_t nid) -{ - const struct hda_amp_list *p; - int ch, v; - - if (!check->amplist) - return 0; - for (p = check->amplist; p->nid; p++) { - if (p->nid == nid) - break; - } - if (!p->nid) - return 0; /* nothing changed */ - - for (p = check->amplist; p->nid; p++) { - for (ch = 0; ch < 2; ch++) { - v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir, - p->idx); - if (!(v & HDA_AMP_MUTE) && v > 0) { - if (!check->power_on) { - check->power_on = 1; - snd_hda_power_up(codec); - } - return 1; - } - } - } - if (check->power_on) { - check->power_on = 0; - snd_hda_power_down(codec); - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power); -#endif - -/* - * Channel mode helper - */ - -/** - * snd_hda_ch_mode_info - Info callback helper for the channel mode enum - */ -int snd_hda_ch_mode_info(struct hda_codec *codec, - struct snd_ctl_elem_info *uinfo, - const struct hda_channel_mode *chmode, - int num_chmodes) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = num_chmodes; - if (uinfo->value.enumerated.item >= num_chmodes) - uinfo->value.enumerated.item = num_chmodes - 1; - sprintf(uinfo->value.enumerated.name, "%dch", - chmode[uinfo->value.enumerated.item].channels); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info); - -/** - * snd_hda_ch_mode_get - Get callback helper for the channel mode enum - */ -int snd_hda_ch_mode_get(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol, - const struct hda_channel_mode *chmode, - int num_chmodes, - int max_channels) -{ - int i; - - for (i = 0; i < num_chmodes; i++) { - if (max_channels == chmode[i].channels) { - ucontrol->value.enumerated.item[0] = i; - break; - } - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get); - -/** - * snd_hda_ch_mode_put - Put callback helper for the channel mode enum - */ -int snd_hda_ch_mode_put(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol, - const struct hda_channel_mode *chmode, - int num_chmodes, - int *max_channelsp) -{ - unsigned int mode; - - mode = ucontrol->value.enumerated.item[0]; - if (mode >= num_chmodes) - return -EINVAL; - if (*max_channelsp == chmode[mode].channels) - return 0; - /* change the current channel setting */ - *max_channelsp = chmode[mode].channels; - if (chmode[mode].sequence) - snd_hda_sequence_write_cache(codec, chmode[mode].sequence); - return 1; -} -EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put); - -/* - * input MUX helper - */ - -/** - * snd_hda_input_mux_info_info - Info callback helper for the input-mux enum - */ -int snd_hda_input_mux_info(const struct hda_input_mux *imux, - struct snd_ctl_elem_info *uinfo) -{ - unsigned int index; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = imux->num_items; - if (!imux->num_items) - return 0; - index = uinfo->value.enumerated.item; - if (index >= imux->num_items) - index = imux->num_items - 1; - strcpy(uinfo->value.enumerated.name, imux->items[index].label); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_input_mux_info); - -/** - * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum - */ -int snd_hda_input_mux_put(struct hda_codec *codec, - const struct hda_input_mux *imux, - struct snd_ctl_elem_value *ucontrol, - hda_nid_t nid, - unsigned int *cur_val) -{ - unsigned int idx; - - if (!imux->num_items) - return 0; - idx = ucontrol->value.enumerated.item[0]; - if (idx >= imux->num_items) - idx = imux->num_items - 1; - if (*cur_val == idx) - return 0; - snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, - imux->items[idx].index); - *cur_val = idx; - return 1; -} -EXPORT_SYMBOL_HDA(snd_hda_input_mux_put); - - -/* - * Multi-channel / digital-out PCM helper functions - */ - -/* setup SPDIF output stream */ -static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, - unsigned int stream_tag, unsigned int format) -{ - struct hda_spdif_out *spdif = snd_hda_spdif_out_of_nid(codec, nid); - - /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ - if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) - set_dig_out_convert(codec, nid, - spdif->ctls & ~AC_DIG1_ENABLE & 0xff, - -1); - snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); - if (codec->slave_dig_outs) { - const hda_nid_t *d; - for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_setup_stream(codec, *d, stream_tag, 0, - format); - } - /* turn on again (if needed) */ - if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) - set_dig_out_convert(codec, nid, - spdif->ctls & 0xff, -1); -} - -static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid) -{ - snd_hda_codec_cleanup_stream(codec, nid); - if (codec->slave_dig_outs) { - const hda_nid_t *d; - for (d = codec->slave_dig_outs; *d; d++) - snd_hda_codec_cleanup_stream(codec, *d); - } -} - -/** - * snd_hda_bus_reboot_notify - call the reboot notifier of each codec - * @bus: HD-audio bus - */ -void snd_hda_bus_reboot_notify(struct hda_bus *bus) -{ - struct hda_codec *codec; - - if (!bus) - return; - list_for_each_entry(codec, &bus->codec_list, list) { - if (hda_codec_is_power_on(codec) && - codec->patch_ops.reboot_notify) - codec->patch_ops.reboot_notify(codec); - } -} -EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify); - -/** - * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode - */ -int snd_hda_multi_out_dig_open(struct hda_codec *codec, - struct hda_multi_out *mout) -{ - mutex_lock(&codec->spdif_mutex); - if (mout->dig_out_used == HDA_DIG_ANALOG_DUP) - /* already opened as analog dup; reset it once */ - cleanup_dig_out_stream(codec, mout->dig_out_nid); - mout->dig_out_used = HDA_DIG_EXCLUSIVE; - mutex_unlock(&codec->spdif_mutex); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open); - -/** - * snd_hda_multi_out_dig_prepare - prepare the digital out stream - */ -int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, - struct hda_multi_out *mout, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - mutex_lock(&codec->spdif_mutex); - setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format); - mutex_unlock(&codec->spdif_mutex); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare); - -/** - * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream - */ -int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec, - struct hda_multi_out *mout) -{ - mutex_lock(&codec->spdif_mutex); - cleanup_dig_out_stream(codec, mout->dig_out_nid); - mutex_unlock(&codec->spdif_mutex); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup); - -/** - * snd_hda_multi_out_dig_close - release the digital out stream - */ -int snd_hda_multi_out_dig_close(struct hda_codec *codec, - struct hda_multi_out *mout) -{ - mutex_lock(&codec->spdif_mutex); - mout->dig_out_used = 0; - mutex_unlock(&codec->spdif_mutex); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close); - -/** - * snd_hda_multi_out_analog_open - open analog outputs - * - * Open analog outputs and set up the hw-constraints. - * If the digital outputs can be opened as slave, open the digital - * outputs, too. - */ -int snd_hda_multi_out_analog_open(struct hda_codec *codec, - struct hda_multi_out *mout, - struct snd_pcm_substream *substream, - struct hda_pcm_stream *hinfo) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.channels_max = mout->max_channels; - if (mout->dig_out_nid) { - if (!mout->analog_rates) { - mout->analog_rates = hinfo->rates; - mout->analog_formats = hinfo->formats; - mout->analog_maxbps = hinfo->maxbps; - } else { - runtime->hw.rates = mout->analog_rates; - runtime->hw.formats = mout->analog_formats; - hinfo->maxbps = mout->analog_maxbps; - } - if (!mout->spdif_rates) { - snd_hda_query_supported_pcm(codec, mout->dig_out_nid, - &mout->spdif_rates, - &mout->spdif_formats, - &mout->spdif_maxbps); - } - mutex_lock(&codec->spdif_mutex); - if (mout->share_spdif) { - if ((runtime->hw.rates & mout->spdif_rates) && - (runtime->hw.formats & mout->spdif_formats)) { - runtime->hw.rates &= mout->spdif_rates; - runtime->hw.formats &= mout->spdif_formats; - if (mout->spdif_maxbps < hinfo->maxbps) - hinfo->maxbps = mout->spdif_maxbps; - } else { - mout->share_spdif = 0; - /* FIXME: need notify? */ - } - } - mutex_unlock(&codec->spdif_mutex); - } - return snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, 2); -} -EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open); - -/** - * snd_hda_multi_out_analog_prepare - Preapre the analog outputs. - * - * Set up the i/o for analog out. - * When the digital out is available, copy the front out to digital out, too. - */ -int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, - struct hda_multi_out *mout, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - const hda_nid_t *nids = mout->dac_nids; - int chs = substream->runtime->channels; - struct hda_spdif_out *spdif = - snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid); - int i; - - mutex_lock(&codec->spdif_mutex); - if (mout->dig_out_nid && mout->share_spdif && - mout->dig_out_used != HDA_DIG_EXCLUSIVE) { - if (chs == 2 && - snd_hda_is_supported_format(codec, mout->dig_out_nid, - format) && - !(spdif->status & IEC958_AES0_NONAUDIO)) { - mout->dig_out_used = HDA_DIG_ANALOG_DUP; - setup_dig_out_stream(codec, mout->dig_out_nid, - stream_tag, format); - } else { - mout->dig_out_used = 0; - cleanup_dig_out_stream(codec, mout->dig_out_nid); - } - } - mutex_unlock(&codec->spdif_mutex); - - /* front */ - snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, - 0, format); - if (!mout->no_share_stream && - mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) - /* headphone out will just decode front left/right (stereo) */ - snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, - 0, format); - /* extra outputs copied from front */ - for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++) - if (!mout->no_share_stream && mout->hp_out_nid[i]) - snd_hda_codec_setup_stream(codec, - mout->hp_out_nid[i], - stream_tag, 0, format); - for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) - if (!mout->no_share_stream && mout->extra_out_nid[i]) - snd_hda_codec_setup_stream(codec, - mout->extra_out_nid[i], - stream_tag, 0, format); - - /* surrounds */ - for (i = 1; i < mout->num_dacs; i++) { - if (chs >= (i + 1) * 2) /* independent out */ - snd_hda_codec_setup_stream(codec, nids[i], stream_tag, - i * 2, format); - else if (!mout->no_share_stream) /* copy front */ - snd_hda_codec_setup_stream(codec, nids[i], stream_tag, - 0, format); - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare); - -/** - * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out - */ -int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, - struct hda_multi_out *mout) -{ - const hda_nid_t *nids = mout->dac_nids; - int i; - - for (i = 0; i < mout->num_dacs; i++) - snd_hda_codec_cleanup_stream(codec, nids[i]); - if (mout->hp_nid) - snd_hda_codec_cleanup_stream(codec, mout->hp_nid); - for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++) - if (mout->hp_out_nid[i]) - snd_hda_codec_cleanup_stream(codec, - mout->hp_out_nid[i]); - for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) - if (mout->extra_out_nid[i]) - snd_hda_codec_cleanup_stream(codec, - mout->extra_out_nid[i]); - mutex_lock(&codec->spdif_mutex); - if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { - cleanup_dig_out_stream(codec, mout->dig_out_nid); - mout->dig_out_used = 0; - } - mutex_unlock(&codec->spdif_mutex); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup); - -/* - * Helper for automatic pin configuration - */ - -static int is_in_nid_list(hda_nid_t nid, const hda_nid_t *list) -{ - for (; *list; list++) - if (*list == nid) - return 1; - return 0; -} - - -/* - * Sort an associated group of pins according to their sequence numbers. - */ -static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, - int num_pins) -{ - int i, j; - short seq; - hda_nid_t nid; - - for (i = 0; i < num_pins; i++) { - for (j = i + 1; j < num_pins; j++) { - if (sequences[i] > sequences[j]) { - seq = sequences[i]; - sequences[i] = sequences[j]; - sequences[j] = seq; - nid = pins[i]; - pins[i] = pins[j]; - pins[j] = nid; - } - } - } -} - - -/* add the found input-pin to the cfg->inputs[] table */ -static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid, - int type) -{ - if (cfg->num_inputs < AUTO_CFG_MAX_INS) { - cfg->inputs[cfg->num_inputs].pin = nid; - cfg->inputs[cfg->num_inputs].type = type; - cfg->num_inputs++; - } -} - -/* sort inputs in the order of AUTO_PIN_* type */ -static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg) -{ - int i, j; - - for (i = 0; i < cfg->num_inputs; i++) { - for (j = i + 1; j < cfg->num_inputs; j++) { - if (cfg->inputs[i].type > cfg->inputs[j].type) { - struct auto_pin_cfg_item tmp; - tmp = cfg->inputs[i]; - cfg->inputs[i] = cfg->inputs[j]; - cfg->inputs[j] = tmp; - } - } - } -} - -/* Reorder the surround channels - * ALSA sequence is front/surr/clfe/side - * HDA sequence is: - * 4-ch: front/surr => OK as it is - * 6-ch: front/clfe/surr - * 8-ch: front/clfe/rear/side|fc - */ -static void reorder_outputs(unsigned int nums, hda_nid_t *pins) -{ - hda_nid_t nid; - - switch (nums) { - case 3: - case 4: - nid = pins[1]; - pins[1] = pins[2]; - pins[2] = nid; - break; - } -} - -/* - * Parse all pin widgets and store the useful pin nids to cfg - * - * The number of line-outs or any primary output is stored in line_outs, - * and the corresponding output pins are assigned to line_out_pins[], - * in the order of front, rear, CLFE, side, ... - * - * If more extra outputs (speaker and headphone) are found, the pins are - * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack - * is detected, one of speaker of HP pins is assigned as the primary - * output, i.e. to line_out_pins[0]. So, line_outs is always positive - * if any analog output exists. - * - * The analog input pins are assigned to inputs array. - * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, - * respectively. - */ -int snd_hda_parse_pin_defcfg(struct hda_codec *codec, - struct auto_pin_cfg *cfg, - const hda_nid_t *ignore_nids, - unsigned int cond_flags) -{ - hda_nid_t nid, end_nid; - short seq, assoc_line_out; - short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; - short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; - short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; - int i; - - memset(cfg, 0, sizeof(*cfg)); - - memset(sequences_line_out, 0, sizeof(sequences_line_out)); - memset(sequences_speaker, 0, sizeof(sequences_speaker)); - memset(sequences_hp, 0, sizeof(sequences_hp)); - assoc_line_out = 0; - - codec->ignore_misc_bit = true; - end_nid = codec->start_nid + codec->num_nodes; - for (nid = codec->start_nid; nid < end_nid; nid++) { - unsigned int wid_caps = get_wcaps(codec, nid); - unsigned int wid_type = get_wcaps_type(wid_caps); - unsigned int def_conf; - short assoc, loc, conn, dev; - - /* read all default configuration for pin complex */ - if (wid_type != AC_WID_PIN) - continue; - /* ignore the given nids (e.g. pc-beep returns error) */ - if (ignore_nids && is_in_nid_list(nid, ignore_nids)) - continue; - - def_conf = snd_hda_codec_get_pincfg(codec, nid); - if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & - AC_DEFCFG_MISC_NO_PRESENCE)) - codec->ignore_misc_bit = false; - conn = get_defcfg_connect(def_conf); - if (conn == AC_JACK_PORT_NONE) - continue; - loc = get_defcfg_location(def_conf); - dev = get_defcfg_device(def_conf); - - /* workaround for buggy BIOS setups */ - if (dev == AC_JACK_LINE_OUT) { - if (conn == AC_JACK_PORT_FIXED) - dev = AC_JACK_SPEAKER; - } - - switch (dev) { - case AC_JACK_LINE_OUT: - seq = get_defcfg_sequence(def_conf); - assoc = get_defcfg_association(def_conf); - - if (!(wid_caps & AC_WCAP_STEREO)) - if (!cfg->mono_out_pin) - cfg->mono_out_pin = nid; - if (!assoc) - continue; - if (!assoc_line_out) - assoc_line_out = assoc; - else if (assoc_line_out != assoc) - continue; - if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) - continue; - cfg->line_out_pins[cfg->line_outs] = nid; - sequences_line_out[cfg->line_outs] = seq; - cfg->line_outs++; - break; - case AC_JACK_SPEAKER: - seq = get_defcfg_sequence(def_conf); - assoc = get_defcfg_association(def_conf); - if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) - continue; - cfg->speaker_pins[cfg->speaker_outs] = nid; - sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq; - cfg->speaker_outs++; - break; - case AC_JACK_HP_OUT: - seq = get_defcfg_sequence(def_conf); - assoc = get_defcfg_association(def_conf); - if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) - continue; - cfg->hp_pins[cfg->hp_outs] = nid; - sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; - cfg->hp_outs++; - break; - case AC_JACK_MIC_IN: - add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC); - break; - case AC_JACK_LINE_IN: - add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN); - break; - case AC_JACK_CD: - add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD); - break; - case AC_JACK_AUX: - add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX); - break; - case AC_JACK_SPDIF_OUT: - case AC_JACK_DIG_OTHER_OUT: - if (cfg->dig_outs >= ARRAY_SIZE(cfg->dig_out_pins)) - continue; - cfg->dig_out_pins[cfg->dig_outs] = nid; - cfg->dig_out_type[cfg->dig_outs] = - (loc == AC_JACK_LOC_HDMI) ? - HDA_PCM_TYPE_HDMI : HDA_PCM_TYPE_SPDIF; - cfg->dig_outs++; - break; - case AC_JACK_SPDIF_IN: - case AC_JACK_DIG_OTHER_IN: - cfg->dig_in_pin = nid; - if (loc == AC_JACK_LOC_HDMI) - cfg->dig_in_type = HDA_PCM_TYPE_HDMI; - else - cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; - break; - } - } - - /* FIX-UP: - * If no line-out is defined but multiple HPs are found, - * some of them might be the real line-outs. - */ - if (!cfg->line_outs && cfg->hp_outs > 1 && - !(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) { - int i = 0; - while (i < cfg->hp_outs) { - /* The real HPs should have the sequence 0x0f */ - if ((sequences_hp[i] & 0x0f) == 0x0f) { - i++; - continue; - } - /* Move it to the line-out table */ - cfg->line_out_pins[cfg->line_outs] = cfg->hp_pins[i]; - sequences_line_out[cfg->line_outs] = sequences_hp[i]; - cfg->line_outs++; - cfg->hp_outs--; - memmove(cfg->hp_pins + i, cfg->hp_pins + i + 1, - sizeof(cfg->hp_pins[0]) * (cfg->hp_outs - i)); - memmove(sequences_hp + i, sequences_hp + i + 1, - sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); - } - memset(cfg->hp_pins + cfg->hp_outs, 0, - sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); - if (!cfg->hp_outs) - cfg->line_out_type = AUTO_PIN_HP_OUT; - - } - - /* sort by sequence */ - sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out, - cfg->line_outs); - sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker, - cfg->speaker_outs); - sort_pins_by_sequence(cfg->hp_pins, sequences_hp, - cfg->hp_outs); - - /* - * FIX-UP: if no line-outs are detected, try to use speaker or HP pin - * as a primary output - */ - if (!cfg->line_outs && - !(cond_flags & HDA_PINCFG_NO_LO_FIXUP)) { - if (cfg->speaker_outs) { - cfg->line_outs = cfg->speaker_outs; - memcpy(cfg->line_out_pins, cfg->speaker_pins, - sizeof(cfg->speaker_pins)); - cfg->speaker_outs = 0; - memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); - cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; - } else if (cfg->hp_outs) { - cfg->line_outs = cfg->hp_outs; - memcpy(cfg->line_out_pins, cfg->hp_pins, - sizeof(cfg->hp_pins)); - cfg->hp_outs = 0; - memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); - cfg->line_out_type = AUTO_PIN_HP_OUT; - } - } - - reorder_outputs(cfg->line_outs, cfg->line_out_pins); - reorder_outputs(cfg->hp_outs, cfg->hp_pins); - reorder_outputs(cfg->speaker_outs, cfg->speaker_pins); - - sort_autocfg_input_pins(cfg); - - /* - * debug prints of the parsed results - */ - snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n", - cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1], - cfg->line_out_pins[2], cfg->line_out_pins[3], - cfg->line_out_pins[4], - cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" : - (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ? - "speaker" : "line")); - snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", - cfg->speaker_outs, cfg->speaker_pins[0], - cfg->speaker_pins[1], cfg->speaker_pins[2], - cfg->speaker_pins[3], cfg->speaker_pins[4]); - snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", - cfg->hp_outs, cfg->hp_pins[0], - cfg->hp_pins[1], cfg->hp_pins[2], - cfg->hp_pins[3], cfg->hp_pins[4]); - snd_printd(" mono: mono_out=0x%x\n", cfg->mono_out_pin); - if (cfg->dig_outs) - snd_printd(" dig-out=0x%x/0x%x\n", - cfg->dig_out_pins[0], cfg->dig_out_pins[1]); - snd_printd(" inputs:"); - for (i = 0; i < cfg->num_inputs; i++) { - snd_printd(" %s=0x%x", - hda_get_autocfg_input_label(codec, cfg, i), - cfg->inputs[i].pin); - } - snd_printd("\n"); - if (cfg->dig_in_pin) - snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); - - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_parse_pin_defcfg); - -int snd_hda_get_input_pin_attr(unsigned int def_conf) -{ - unsigned int loc = get_defcfg_location(def_conf); - unsigned int conn = get_defcfg_connect(def_conf); - if (conn == AC_JACK_PORT_NONE) - return INPUT_PIN_ATTR_UNUSED; - /* Windows may claim the internal mic to be BOTH, too */ - if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH) - return INPUT_PIN_ATTR_INT; - if ((loc & 0x30) == AC_JACK_LOC_INTERNAL) - return INPUT_PIN_ATTR_INT; - if ((loc & 0x30) == AC_JACK_LOC_SEPARATE) - return INPUT_PIN_ATTR_DOCK; - if (loc == AC_JACK_LOC_REAR) - return INPUT_PIN_ATTR_REAR; - if (loc == AC_JACK_LOC_FRONT) - return INPUT_PIN_ATTR_FRONT; - return INPUT_PIN_ATTR_NORMAL; -} -EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr); - -/** - * hda_get_input_pin_label - Give a label for the given input pin - * - * When check_location is true, the function checks the pin location - * for mic and line-in pins, and set an appropriate prefix like "Front", - * "Rear", "Internal". - */ - -static const char *hda_get_input_pin_label(struct hda_codec *codec, - hda_nid_t pin, bool check_location) -{ - unsigned int def_conf; - static const char * const mic_names[] = { - "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic", - }; - int attr; - - def_conf = snd_hda_codec_get_pincfg(codec, pin); - - switch (get_defcfg_device(def_conf)) { - case AC_JACK_MIC_IN: - if (!check_location) - return "Mic"; - attr = snd_hda_get_input_pin_attr(def_conf); - if (!attr) - return "None"; - return mic_names[attr - 1]; - case AC_JACK_LINE_IN: - if (!check_location) - return "Line"; - attr = snd_hda_get_input_pin_attr(def_conf); - if (!attr) - return "None"; - if (attr == INPUT_PIN_ATTR_DOCK) - return "Dock Line"; - return "Line"; - case AC_JACK_AUX: - return "Aux"; - case AC_JACK_CD: - return "CD"; - case AC_JACK_SPDIF_IN: - return "SPDIF In"; - case AC_JACK_DIG_OTHER_IN: - return "Digital In"; - default: - return "Misc"; - } -} - -/* Check whether the location prefix needs to be added to the label. - * If all mic-jacks are in the same location (e.g. rear panel), we don't - * have to put "Front" prefix to each label. In such a case, returns false. - */ -static int check_mic_location_need(struct hda_codec *codec, - const struct auto_pin_cfg *cfg, - int input) -{ - unsigned int defc; - int i, attr, attr2; - - defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin); - attr = snd_hda_get_input_pin_attr(defc); - /* for internal or docking mics, we need locations */ - if (attr <= INPUT_PIN_ATTR_NORMAL) - return 1; - - attr = 0; - for (i = 0; i < cfg->num_inputs; i++) { - defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin); - attr2 = snd_hda_get_input_pin_attr(defc); - if (attr2 >= INPUT_PIN_ATTR_NORMAL) { - if (attr && attr != attr2) - return 1; /* different locations found */ - attr = attr2; - } - } - return 0; -} - -/** - * hda_get_autocfg_input_label - Get a label for the given input - * - * Get a label for the given input pin defined by the autocfg item. - * Unlike hda_get_input_pin_label(), this function checks all inputs - * defined in autocfg and avoids the redundant mic/line prefix as much as - * possible. - */ -const char *hda_get_autocfg_input_label(struct hda_codec *codec, - const struct auto_pin_cfg *cfg, - int input) -{ - int type = cfg->inputs[input].type; - int has_multiple_pins = 0; - - if ((input > 0 && cfg->inputs[input - 1].type == type) || - (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type)) - has_multiple_pins = 1; - if (has_multiple_pins && type == AUTO_PIN_MIC) - has_multiple_pins &= check_mic_location_need(codec, cfg, input); - return hda_get_input_pin_label(codec, cfg->inputs[input].pin, - has_multiple_pins); -} -EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); - -/* return the position of NID in the list, or -1 if not found */ -static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) -{ - int i; - for (i = 0; i < nums; i++) - if (list[i] == nid) - return i; - return -1; -} - -/* get a unique suffix or an index number */ -static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins, - int num_pins, int *indexp) -{ - static const char * const channel_sfx[] = { - " Front", " Surround", " CLFE", " Side" - }; - int i; - - i = find_idx_in_nid_list(nid, pins, num_pins); - if (i < 0) - return NULL; - if (num_pins == 1) - return ""; - if (num_pins > ARRAY_SIZE(channel_sfx)) { - if (indexp) - *indexp = i; - return ""; - } - return channel_sfx[i]; -} - -static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid, - const struct auto_pin_cfg *cfg, - const char *name, char *label, int maxlen, - int *indexp) -{ - unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); - int attr = snd_hda_get_input_pin_attr(def_conf); - const char *pfx = "", *sfx = ""; - - /* handle as a speaker if it's a fixed line-out */ - if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT) - name = "Speaker"; - /* check the location */ - switch (attr) { - case INPUT_PIN_ATTR_DOCK: - pfx = "Dock "; - break; - case INPUT_PIN_ATTR_FRONT: - pfx = "Front "; - break; - } - if (cfg) { - /* try to give a unique suffix if needed */ - sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs, - indexp); - if (!sfx) - sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs, - indexp); - if (!sfx) { - /* don't add channel suffix for Headphone controls */ - int idx = find_idx_in_nid_list(nid, cfg->hp_pins, - cfg->hp_outs); - if (idx >= 0) - *indexp = idx; - sfx = ""; - } - } - snprintf(label, maxlen, "%s%s%s", pfx, name, sfx); - return 1; -} - -/** - * snd_hda_get_pin_label - Get a label for the given I/O pin - * - * Get a label for the given pin. This function works for both input and - * output pins. When @cfg is given as non-NULL, the function tries to get - * an optimized label using hda_get_autocfg_input_label(). - * - * This function tries to give a unique label string for the pin as much as - * possible. For example, when the multiple line-outs are present, it adds - * the channel suffix like "Front", "Surround", etc (only when @cfg is given). - * If no unique name with a suffix is available and @indexp is non-NULL, the - * index number is stored in the pointer. - */ -int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid, - const struct auto_pin_cfg *cfg, - char *label, int maxlen, int *indexp) -{ - unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); - const char *name = NULL; - int i; - - if (indexp) - *indexp = 0; - if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) - return 0; - - switch (get_defcfg_device(def_conf)) { - case AC_JACK_LINE_OUT: - return fill_audio_out_name(codec, nid, cfg, "Line Out", - label, maxlen, indexp); - case AC_JACK_SPEAKER: - return fill_audio_out_name(codec, nid, cfg, "Speaker", - label, maxlen, indexp); - case AC_JACK_HP_OUT: - return fill_audio_out_name(codec, nid, cfg, "Headphone", - label, maxlen, indexp); - case AC_JACK_SPDIF_OUT: - case AC_JACK_DIG_OTHER_OUT: - if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI) - name = "HDMI"; - else - name = "SPDIF"; - if (cfg && indexp) { - i = find_idx_in_nid_list(nid, cfg->dig_out_pins, - cfg->dig_outs); - if (i >= 0) - *indexp = i; - } - break; - default: - if (cfg) { - for (i = 0; i < cfg->num_inputs; i++) { - if (cfg->inputs[i].pin != nid) - continue; - name = hda_get_autocfg_input_label(codec, cfg, i); - if (name) - break; - } - } - if (!name) - name = hda_get_input_pin_label(codec, nid, true); - break; - } - if (!name) - return 0; - strlcpy(label, name, maxlen); - return 1; -} -EXPORT_SYMBOL_HDA(snd_hda_get_pin_label); - -/** - * snd_hda_add_imux_item - Add an item to input_mux - * - * When the same label is used already in the existing items, the number - * suffix is appended to the label. This label index number is stored - * to type_idx when non-NULL pointer is given. - */ -int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, - int index, int *type_idx) -{ - int i, label_idx = 0; - if (imux->num_items >= HDA_MAX_NUM_INPUTS) { - snd_printd(KERN_ERR "hda_codec: Too many imux items!\n"); - return -EINVAL; - } - for (i = 0; i < imux->num_items; i++) { - if (!strncmp(label, imux->items[i].label, strlen(label))) - label_idx++; - } - if (type_idx) - *type_idx = label_idx; - if (label_idx > 0) - snprintf(imux->items[imux->num_items].label, - sizeof(imux->items[imux->num_items].label), - "%s %d", label, label_idx); - else - strlcpy(imux->items[imux->num_items].label, label, - sizeof(imux->items[imux->num_items].label)); - imux->items[imux->num_items].index = index; - imux->num_items++; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_add_imux_item); - - -#ifdef CONFIG_PM -/* - * power management - */ - -/** - * snd_hda_suspend - suspend the codecs - * @bus: the HDA bus - * - * Returns 0 if successful. - */ -int snd_hda_suspend(struct hda_bus *bus) -{ - struct hda_codec *codec; - - list_for_each_entry(codec, &bus->codec_list, list) { - if (hda_codec_is_power_on(codec)) - hda_call_codec_suspend(codec); - if (codec->patch_ops.post_suspend) - codec->patch_ops.post_suspend(codec); - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_suspend); - -/** - * snd_hda_resume - resume the codecs - * @bus: the HDA bus - * - * Returns 0 if successful. - * - * This function is defined only when POWER_SAVE isn't set. - * In the power-save mode, the codec is resumed dynamically. - */ -int snd_hda_resume(struct hda_bus *bus) -{ - struct hda_codec *codec; - - list_for_each_entry(codec, &bus->codec_list, list) { - if (codec->patch_ops.pre_resume) - codec->patch_ops.pre_resume(codec); - if (snd_hda_codec_needs_resume(codec)) - hda_call_codec_resume(codec); - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_resume); -#endif /* CONFIG_PM */ - -/* - * generic arrays - */ - -/** - * snd_array_new - get a new element from the given array - * @array: the array object - * - * Get a new element from the given array. If it exceeds the - * pre-allocated array size, re-allocate the array. - * - * Returns NULL if allocation failed. - */ -void *snd_array_new(struct snd_array *array) -{ - if (array->used >= array->alloced) { - int num = array->alloced + array->alloc_align; - int size = (num + 1) * array->elem_size; - int oldsize = array->alloced * array->elem_size; - void *nlist; - if (snd_BUG_ON(num >= 4096)) - return NULL; - nlist = krealloc(array->list, size, GFP_KERNEL); - if (!nlist) - return NULL; - memset(nlist + oldsize, 0, size - oldsize); - array->list = nlist; - array->alloced = num; - } - return snd_array_elem(array, array->used++); -} -EXPORT_SYMBOL_HDA(snd_array_new); - -/** - * snd_array_free - free the given array elements - * @array: the array object - */ -void snd_array_free(struct snd_array *array) -{ - kfree(array->list); - array->used = 0; - array->alloced = 0; - array->list = NULL; -} -EXPORT_SYMBOL_HDA(snd_array_free); - -/** - * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer - * @pcm: PCM caps bits - * @buf: the string buffer to write - * @buflen: the max buffer length - * - * used by hda_proc.c and hda_eld.c - */ -void snd_print_pcm_bits(int pcm, char *buf, int buflen) -{ - static unsigned int bits[] = { 8, 16, 20, 24, 32 }; - int i, j; - - for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++) - if (pcm & (AC_SUPPCM_BITS_8 << i)) - j += snprintf(buf + j, buflen - j, " %d", bits[i]); - - buf[j] = '\0'; /* necessary when j == 0 */ -} -EXPORT_SYMBOL_HDA(snd_print_pcm_bits); - -MODULE_DESCRIPTION("HDA codec core"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_codec.h b/ANDROID_3.4.5/sound/pci/hda/hda_codec.h deleted file mode 100644 index 56b4f74c..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_codec.h +++ /dev/null @@ -1,1084 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * Copyright (c) 2004 Takashi Iwai - * - * 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. - */ - -#ifndef __SOUND_HDA_CODEC_H -#define __SOUND_HDA_CODEC_H - -#include -#include -#include -#include - -/* - * nodes - */ -#define AC_NODE_ROOT 0x00 - -/* - * function group types - */ -enum { - AC_GRP_AUDIO_FUNCTION = 0x01, - AC_GRP_MODEM_FUNCTION = 0x02, -}; - -/* - * widget types - */ -enum { - AC_WID_AUD_OUT, /* Audio Out */ - AC_WID_AUD_IN, /* Audio In */ - AC_WID_AUD_MIX, /* Audio Mixer */ - AC_WID_AUD_SEL, /* Audio Selector */ - AC_WID_PIN, /* Pin Complex */ - AC_WID_POWER, /* Power */ - AC_WID_VOL_KNB, /* Volume Knob */ - AC_WID_BEEP, /* Beep Generator */ - AC_WID_VENDOR = 0x0f /* Vendor specific */ -}; - -/* - * GET verbs - */ -#define AC_VERB_GET_STREAM_FORMAT 0x0a00 -#define AC_VERB_GET_AMP_GAIN_MUTE 0x0b00 -#define AC_VERB_GET_PROC_COEF 0x0c00 -#define AC_VERB_GET_COEF_INDEX 0x0d00 -#define AC_VERB_PARAMETERS 0x0f00 -#define AC_VERB_GET_CONNECT_SEL 0x0f01 -#define AC_VERB_GET_CONNECT_LIST 0x0f02 -#define AC_VERB_GET_PROC_STATE 0x0f03 -#define AC_VERB_GET_SDI_SELECT 0x0f04 -#define AC_VERB_GET_POWER_STATE 0x0f05 -#define AC_VERB_GET_CONV 0x0f06 -#define AC_VERB_GET_PIN_WIDGET_CONTROL 0x0f07 -#define AC_VERB_GET_UNSOLICITED_RESPONSE 0x0f08 -#define AC_VERB_GET_PIN_SENSE 0x0f09 -#define AC_VERB_GET_BEEP_CONTROL 0x0f0a -#define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c -#define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d -#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e /* unused */ -#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f -/* f10-f1a: GPIO */ -#define AC_VERB_GET_GPIO_DATA 0x0f15 -#define AC_VERB_GET_GPIO_MASK 0x0f16 -#define AC_VERB_GET_GPIO_DIRECTION 0x0f17 -#define AC_VERB_GET_GPIO_WAKE_MASK 0x0f18 -#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK 0x0f19 -#define AC_VERB_GET_GPIO_STICKY_MASK 0x0f1a -#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c -/* f20: AFG/MFG */ -#define AC_VERB_GET_SUBSYSTEM_ID 0x0f20 -#define AC_VERB_GET_CVT_CHAN_COUNT 0x0f2d -#define AC_VERB_GET_HDMI_DIP_SIZE 0x0f2e -#define AC_VERB_GET_HDMI_ELDD 0x0f2f -#define AC_VERB_GET_HDMI_DIP_INDEX 0x0f30 -#define AC_VERB_GET_HDMI_DIP_DATA 0x0f31 -#define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32 -#define AC_VERB_GET_HDMI_CP_CTRL 0x0f33 -#define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34 - -/* - * SET verbs - */ -#define AC_VERB_SET_STREAM_FORMAT 0x200 -#define AC_VERB_SET_AMP_GAIN_MUTE 0x300 -#define AC_VERB_SET_PROC_COEF 0x400 -#define AC_VERB_SET_COEF_INDEX 0x500 -#define AC_VERB_SET_CONNECT_SEL 0x701 -#define AC_VERB_SET_PROC_STATE 0x703 -#define AC_VERB_SET_SDI_SELECT 0x704 -#define AC_VERB_SET_POWER_STATE 0x705 -#define AC_VERB_SET_CHANNEL_STREAMID 0x706 -#define AC_VERB_SET_PIN_WIDGET_CONTROL 0x707 -#define AC_VERB_SET_UNSOLICITED_ENABLE 0x708 -#define AC_VERB_SET_PIN_SENSE 0x709 -#define AC_VERB_SET_BEEP_CONTROL 0x70a -#define AC_VERB_SET_EAPD_BTLENABLE 0x70c -#define AC_VERB_SET_DIGI_CONVERT_1 0x70d -#define AC_VERB_SET_DIGI_CONVERT_2 0x70e -#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f -#define AC_VERB_SET_GPIO_DATA 0x715 -#define AC_VERB_SET_GPIO_MASK 0x716 -#define AC_VERB_SET_GPIO_DIRECTION 0x717 -#define AC_VERB_SET_GPIO_WAKE_MASK 0x718 -#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK 0x719 -#define AC_VERB_SET_GPIO_STICKY_MASK 0x71a -#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c -#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d -#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e -#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f -#define AC_VERB_SET_EAPD 0x788 -#define AC_VERB_SET_CODEC_RESET 0x7ff -#define AC_VERB_SET_CVT_CHAN_COUNT 0x72d -#define AC_VERB_SET_HDMI_DIP_INDEX 0x730 -#define AC_VERB_SET_HDMI_DIP_DATA 0x731 -#define AC_VERB_SET_HDMI_DIP_XMIT 0x732 -#define AC_VERB_SET_HDMI_CP_CTRL 0x733 -#define AC_VERB_SET_HDMI_CHAN_SLOT 0x734 - -/* - * Parameter IDs - */ -#define AC_PAR_VENDOR_ID 0x00 -#define AC_PAR_SUBSYSTEM_ID 0x01 -#define AC_PAR_REV_ID 0x02 -#define AC_PAR_NODE_COUNT 0x04 -#define AC_PAR_FUNCTION_TYPE 0x05 -#define AC_PAR_AUDIO_FG_CAP 0x08 -#define AC_PAR_AUDIO_WIDGET_CAP 0x09 -#define AC_PAR_PCM 0x0a -#define AC_PAR_STREAM 0x0b -#define AC_PAR_PIN_CAP 0x0c -#define AC_PAR_AMP_IN_CAP 0x0d -#define AC_PAR_CONNLIST_LEN 0x0e -#define AC_PAR_POWER_STATE 0x0f -#define AC_PAR_PROC_CAP 0x10 -#define AC_PAR_GPIO_CAP 0x11 -#define AC_PAR_AMP_OUT_CAP 0x12 -#define AC_PAR_VOL_KNB_CAP 0x13 -#define AC_PAR_HDMI_LPCM_CAP 0x20 - -/* - * AC_VERB_PARAMETERS results (32bit) - */ - -/* Function Group Type */ -#define AC_FGT_TYPE (0xff<<0) -#define AC_FGT_TYPE_SHIFT 0 -#define AC_FGT_UNSOL_CAP (1<<8) - -/* Audio Function Group Capabilities */ -#define AC_AFG_OUT_DELAY (0xf<<0) -#define AC_AFG_IN_DELAY (0xf<<8) -#define AC_AFG_BEEP_GEN (1<<16) - -/* Audio Widget Capabilities */ -#define AC_WCAP_STEREO (1<<0) /* stereo I/O */ -#define AC_WCAP_IN_AMP (1<<1) /* AMP-in present */ -#define AC_WCAP_OUT_AMP (1<<2) /* AMP-out present */ -#define AC_WCAP_AMP_OVRD (1<<3) /* AMP-parameter override */ -#define AC_WCAP_FORMAT_OVRD (1<<4) /* format override */ -#define AC_WCAP_STRIPE (1<<5) /* stripe */ -#define AC_WCAP_PROC_WID (1<<6) /* Proc Widget */ -#define AC_WCAP_UNSOL_CAP (1<<7) /* Unsol capable */ -#define AC_WCAP_CONN_LIST (1<<8) /* connection list */ -#define AC_WCAP_DIGITAL (1<<9) /* digital I/O */ -#define AC_WCAP_POWER (1<<10) /* power control */ -#define AC_WCAP_LR_SWAP (1<<11) /* L/R swap */ -#define AC_WCAP_CP_CAPS (1<<12) /* content protection */ -#define AC_WCAP_CHAN_CNT_EXT (7<<13) /* channel count ext */ -#define AC_WCAP_DELAY (0xf<<16) -#define AC_WCAP_DELAY_SHIFT 16 -#define AC_WCAP_TYPE (0xf<<20) -#define AC_WCAP_TYPE_SHIFT 20 - -/* supported PCM rates and bits */ -#define AC_SUPPCM_RATES (0xfff << 0) -#define AC_SUPPCM_BITS_8 (1<<16) -#define AC_SUPPCM_BITS_16 (1<<17) -#define AC_SUPPCM_BITS_20 (1<<18) -#define AC_SUPPCM_BITS_24 (1<<19) -#define AC_SUPPCM_BITS_32 (1<<20) - -/* supported PCM stream format */ -#define AC_SUPFMT_PCM (1<<0) -#define AC_SUPFMT_FLOAT32 (1<<1) -#define AC_SUPFMT_AC3 (1<<2) - -/* GP I/O count */ -#define AC_GPIO_IO_COUNT (0xff<<0) -#define AC_GPIO_O_COUNT (0xff<<8) -#define AC_GPIO_O_COUNT_SHIFT 8 -#define AC_GPIO_I_COUNT (0xff<<16) -#define AC_GPIO_I_COUNT_SHIFT 16 -#define AC_GPIO_UNSOLICITED (1<<30) -#define AC_GPIO_WAKE (1<<31) - -/* Converter stream, channel */ -#define AC_CONV_CHANNEL (0xf<<0) -#define AC_CONV_STREAM (0xf<<4) -#define AC_CONV_STREAM_SHIFT 4 - -/* Input converter SDI select */ -#define AC_SDI_SELECT (0xf<<0) - -/* stream format id */ -#define AC_FMT_CHAN_SHIFT 0 -#define AC_FMT_CHAN_MASK (0x0f << 0) -#define AC_FMT_BITS_SHIFT 4 -#define AC_FMT_BITS_MASK (7 << 4) -#define AC_FMT_BITS_8 (0 << 4) -#define AC_FMT_BITS_16 (1 << 4) -#define AC_FMT_BITS_20 (2 << 4) -#define AC_FMT_BITS_24 (3 << 4) -#define AC_FMT_BITS_32 (4 << 4) -#define AC_FMT_DIV_SHIFT 8 -#define AC_FMT_DIV_MASK (7 << 8) -#define AC_FMT_MULT_SHIFT 11 -#define AC_FMT_MULT_MASK (7 << 11) -#define AC_FMT_BASE_SHIFT 14 -#define AC_FMT_BASE_48K (0 << 14) -#define AC_FMT_BASE_44K (1 << 14) -#define AC_FMT_TYPE_SHIFT 15 -#define AC_FMT_TYPE_PCM (0 << 15) -#define AC_FMT_TYPE_NON_PCM (1 << 15) - -/* Unsolicited response control */ -#define AC_UNSOL_TAG (0x3f<<0) -#define AC_UNSOL_ENABLED (1<<7) -#define AC_USRSP_EN AC_UNSOL_ENABLED - -/* Unsolicited responses */ -#define AC_UNSOL_RES_TAG (0x3f<<26) -#define AC_UNSOL_RES_TAG_SHIFT 26 -#define AC_UNSOL_RES_SUBTAG (0x1f<<21) -#define AC_UNSOL_RES_SUBTAG_SHIFT 21 -#define AC_UNSOL_RES_ELDV (1<<1) /* ELD Data valid (for HDMI) */ -#define AC_UNSOL_RES_PD (1<<0) /* pinsense detect */ -#define AC_UNSOL_RES_CP_STATE (1<<1) /* content protection */ -#define AC_UNSOL_RES_CP_READY (1<<0) /* content protection */ - -/* Pin widget capabilies */ -#define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */ -#define AC_PINCAP_TRIG_REQ (1<<1) /* trigger required */ -#define AC_PINCAP_PRES_DETECT (1<<2) /* presence detect capable */ -#define AC_PINCAP_HP_DRV (1<<3) /* headphone drive capable */ -#define AC_PINCAP_OUT (1<<4) /* output capable */ -#define AC_PINCAP_IN (1<<5) /* input capable */ -#define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */ -/* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification, - * but is marked reserved in the Intel HDA specification. - */ -#define AC_PINCAP_LR_SWAP (1<<7) /* L/R swap */ -/* Note: The same bit as LR_SWAP is newly defined as HDMI capability - * in HD-audio specification - */ -#define AC_PINCAP_HDMI (1<<7) /* HDMI pin */ -#define AC_PINCAP_DP (1<<24) /* DisplayPort pin, can - * coexist with AC_PINCAP_HDMI - */ -#define AC_PINCAP_VREF (0x37<<8) -#define AC_PINCAP_VREF_SHIFT 8 -#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ -#define AC_PINCAP_HBR (1<<27) /* High Bit Rate */ -/* Vref status (used in pin cap) */ -#define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ -#define AC_PINCAP_VREF_50 (1<<1) /* 50% */ -#define AC_PINCAP_VREF_GRD (1<<2) /* ground */ -#define AC_PINCAP_VREF_80 (1<<4) /* 80% */ -#define AC_PINCAP_VREF_100 (1<<5) /* 100% */ - -/* Amplifier capabilities */ -#define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */ -#define AC_AMPCAP_OFFSET_SHIFT 0 -#define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */ -#define AC_AMPCAP_NUM_STEPS_SHIFT 8 -#define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB - * in 0.25dB - */ -#define AC_AMPCAP_STEP_SIZE_SHIFT 16 -#define AC_AMPCAP_MUTE (1<<31) /* mute capable */ -#define AC_AMPCAP_MUTE_SHIFT 31 - -/* driver-specific amp-caps: using bits 24-30 */ -#define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */ - -/* Connection list */ -#define AC_CLIST_LENGTH (0x7f<<0) -#define AC_CLIST_LONG (1<<7) - -/* Supported power status */ -#define AC_PWRST_D0SUP (1<<0) -#define AC_PWRST_D1SUP (1<<1) -#define AC_PWRST_D2SUP (1<<2) -#define AC_PWRST_D3SUP (1<<3) -#define AC_PWRST_D3COLDSUP (1<<4) -#define AC_PWRST_S3D3COLDSUP (1<<29) -#define AC_PWRST_CLKSTOP (1<<30) -#define AC_PWRST_EPSS (1U<<31) - -/* Power state values */ -#define AC_PWRST_SETTING (0xf<<0) -#define AC_PWRST_ACTUAL (0xf<<4) -#define AC_PWRST_ACTUAL_SHIFT 4 -#define AC_PWRST_D0 0x00 -#define AC_PWRST_D1 0x01 -#define AC_PWRST_D2 0x02 -#define AC_PWRST_D3 0x03 - -/* Processing capabilies */ -#define AC_PCAP_BENIGN (1<<0) -#define AC_PCAP_NUM_COEF (0xff<<8) -#define AC_PCAP_NUM_COEF_SHIFT 8 - -/* Volume knobs capabilities */ -#define AC_KNBCAP_NUM_STEPS (0x7f<<0) -#define AC_KNBCAP_DELTA (1<<7) - -/* HDMI LPCM capabilities */ -#define AC_LPCMCAP_48K_CP_CHNS (0x0f<<0) /* max channels w/ CP-on */ -#define AC_LPCMCAP_48K_NO_CHNS (0x0f<<4) /* max channels w/o CP-on */ -#define AC_LPCMCAP_48K_20BIT (1<<8) /* 20b bitrate supported */ -#define AC_LPCMCAP_48K_24BIT (1<<9) /* 24b bitrate supported */ -#define AC_LPCMCAP_96K_CP_CHNS (0x0f<<10) /* max channels w/ CP-on */ -#define AC_LPCMCAP_96K_NO_CHNS (0x0f<<14) /* max channels w/o CP-on */ -#define AC_LPCMCAP_96K_20BIT (1<<18) /* 20b bitrate supported */ -#define AC_LPCMCAP_96K_24BIT (1<<19) /* 24b bitrate supported */ -#define AC_LPCMCAP_192K_CP_CHNS (0x0f<<20) /* max channels w/ CP-on */ -#define AC_LPCMCAP_192K_NO_CHNS (0x0f<<24) /* max channels w/o CP-on */ -#define AC_LPCMCAP_192K_20BIT (1<<28) /* 20b bitrate supported */ -#define AC_LPCMCAP_192K_24BIT (1<<29) /* 24b bitrate supported */ -#define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */ -#define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */ - -/* - * Control Parameters - */ - -/* Amp gain/mute */ -#define AC_AMP_MUTE (1<<7) -#define AC_AMP_GAIN (0x7f) -#define AC_AMP_GET_INDEX (0xf<<0) - -#define AC_AMP_GET_LEFT (1<<13) -#define AC_AMP_GET_RIGHT (0<<13) -#define AC_AMP_GET_OUTPUT (1<<15) -#define AC_AMP_GET_INPUT (0<<15) - -#define AC_AMP_SET_INDEX (0xf<<8) -#define AC_AMP_SET_INDEX_SHIFT 8 -#define AC_AMP_SET_RIGHT (1<<12) -#define AC_AMP_SET_LEFT (1<<13) -#define AC_AMP_SET_INPUT (1<<14) -#define AC_AMP_SET_OUTPUT (1<<15) - -/* DIGITAL1 bits */ -#define AC_DIG1_ENABLE (1<<0) -#define AC_DIG1_V (1<<1) -#define AC_DIG1_VCFG (1<<2) -#define AC_DIG1_EMPHASIS (1<<3) -#define AC_DIG1_COPYRIGHT (1<<4) -#define AC_DIG1_NONAUDIO (1<<5) -#define AC_DIG1_PROFESSIONAL (1<<6) -#define AC_DIG1_LEVEL (1<<7) - -/* DIGITAL2 bits */ -#define AC_DIG2_CC (0x7f<<0) - -/* Pin widget control - 8bit */ -#define AC_PINCTL_EPT (0x3<<0) -#define AC_PINCTL_EPT_NATIVE 0 -#define AC_PINCTL_EPT_HBR 3 -#define AC_PINCTL_VREFEN (0x7<<0) -#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ -#define AC_PINCTL_VREF_50 1 /* 50% */ -#define AC_PINCTL_VREF_GRD 2 /* ground */ -#define AC_PINCTL_VREF_80 4 /* 80% */ -#define AC_PINCTL_VREF_100 5 /* 100% */ -#define AC_PINCTL_IN_EN (1<<5) -#define AC_PINCTL_OUT_EN (1<<6) -#define AC_PINCTL_HP_EN (1<<7) - -/* Pin sense - 32bit */ -#define AC_PINSENSE_IMPEDANCE_MASK (0x7fffffff) -#define AC_PINSENSE_PRESENCE (1<<31) -#define AC_PINSENSE_ELDV (1<<30) /* ELD valid (HDMI) */ - -/* EAPD/BTL enable - 32bit */ -#define AC_EAPDBTL_BALANCED (1<<0) -#define AC_EAPDBTL_EAPD (1<<1) -#define AC_EAPDBTL_LR_SWAP (1<<2) - -/* HDMI ELD data */ -#define AC_ELDD_ELD_VALID (1<<31) -#define AC_ELDD_ELD_DATA 0xff - -/* HDMI DIP size */ -#define AC_DIPSIZE_ELD_BUF (1<<3) /* ELD buf size of packet size */ -#define AC_DIPSIZE_PACK_IDX (0x07<<0) /* packet index */ - -/* HDMI DIP index */ -#define AC_DIPIDX_PACK_IDX (0x07<<5) /* packet idnex */ -#define AC_DIPIDX_BYTE_IDX (0x1f<<0) /* byte index */ - -/* HDMI DIP xmit (transmit) control */ -#define AC_DIPXMIT_MASK (0x3<<6) -#define AC_DIPXMIT_DISABLE (0x0<<6) /* disable xmit */ -#define AC_DIPXMIT_ONCE (0x2<<6) /* xmit once then disable */ -#define AC_DIPXMIT_BEST (0x3<<6) /* best effort */ - -/* HDMI content protection (CP) control */ -#define AC_CPCTRL_CES (1<<9) /* current encryption state */ -#define AC_CPCTRL_READY (1<<8) /* ready bit */ -#define AC_CPCTRL_SUBTAG (0x1f<<3) /* subtag for unsol-resp */ -#define AC_CPCTRL_STATE (3<<0) /* current CP request state */ - -/* Converter channel <-> HDMI slot mapping */ -#define AC_CVTMAP_HDMI_SLOT (0xf<<0) /* HDMI slot number */ -#define AC_CVTMAP_CHAN (0xf<<4) /* converter channel number */ - -/* configuration default - 32bit */ -#define AC_DEFCFG_SEQUENCE (0xf<<0) -#define AC_DEFCFG_DEF_ASSOC (0xf<<4) -#define AC_DEFCFG_ASSOC_SHIFT 4 -#define AC_DEFCFG_MISC (0xf<<8) -#define AC_DEFCFG_MISC_SHIFT 8 -#define AC_DEFCFG_MISC_NO_PRESENCE (1<<0) -#define AC_DEFCFG_COLOR (0xf<<12) -#define AC_DEFCFG_COLOR_SHIFT 12 -#define AC_DEFCFG_CONN_TYPE (0xf<<16) -#define AC_DEFCFG_CONN_TYPE_SHIFT 16 -#define AC_DEFCFG_DEVICE (0xf<<20) -#define AC_DEFCFG_DEVICE_SHIFT 20 -#define AC_DEFCFG_LOCATION (0x3f<<24) -#define AC_DEFCFG_LOCATION_SHIFT 24 -#define AC_DEFCFG_PORT_CONN (0x3<<30) -#define AC_DEFCFG_PORT_CONN_SHIFT 30 - -/* device device types (0x0-0xf) */ -enum { - AC_JACK_LINE_OUT, - AC_JACK_SPEAKER, - AC_JACK_HP_OUT, - AC_JACK_CD, - AC_JACK_SPDIF_OUT, - AC_JACK_DIG_OTHER_OUT, - AC_JACK_MODEM_LINE_SIDE, - AC_JACK_MODEM_HAND_SIDE, - AC_JACK_LINE_IN, - AC_JACK_AUX, - AC_JACK_MIC_IN, - AC_JACK_TELEPHONY, - AC_JACK_SPDIF_IN, - AC_JACK_DIG_OTHER_IN, - AC_JACK_OTHER = 0xf, -}; - -/* jack connection types (0x0-0xf) */ -enum { - AC_JACK_CONN_UNKNOWN, - AC_JACK_CONN_1_8, - AC_JACK_CONN_1_4, - AC_JACK_CONN_ATAPI, - AC_JACK_CONN_RCA, - AC_JACK_CONN_OPTICAL, - AC_JACK_CONN_OTHER_DIGITAL, - AC_JACK_CONN_OTHER_ANALOG, - AC_JACK_CONN_DIN, - AC_JACK_CONN_XLR, - AC_JACK_CONN_RJ11, - AC_JACK_CONN_COMB, - AC_JACK_CONN_OTHER = 0xf, -}; - -/* jack colors (0x0-0xf) */ -enum { - AC_JACK_COLOR_UNKNOWN, - AC_JACK_COLOR_BLACK, - AC_JACK_COLOR_GREY, - AC_JACK_COLOR_BLUE, - AC_JACK_COLOR_GREEN, - AC_JACK_COLOR_RED, - AC_JACK_COLOR_ORANGE, - AC_JACK_COLOR_YELLOW, - AC_JACK_COLOR_PURPLE, - AC_JACK_COLOR_PINK, - AC_JACK_COLOR_WHITE = 0xe, - AC_JACK_COLOR_OTHER, -}; - -/* Jack location (0x0-0x3f) */ -/* common case */ -enum { - AC_JACK_LOC_NONE, - AC_JACK_LOC_REAR, - AC_JACK_LOC_FRONT, - AC_JACK_LOC_LEFT, - AC_JACK_LOC_RIGHT, - AC_JACK_LOC_TOP, - AC_JACK_LOC_BOTTOM, -}; -/* bits 4-5 */ -enum { - AC_JACK_LOC_EXTERNAL = 0x00, - AC_JACK_LOC_INTERNAL = 0x10, - AC_JACK_LOC_SEPARATE = 0x20, - AC_JACK_LOC_OTHER = 0x30, -}; -enum { - /* external on primary chasis */ - AC_JACK_LOC_REAR_PANEL = 0x07, - AC_JACK_LOC_DRIVE_BAY, - /* internal */ - AC_JACK_LOC_RISER = 0x17, - AC_JACK_LOC_HDMI, - AC_JACK_LOC_ATAPI, - /* others */ - AC_JACK_LOC_MOBILE_IN = 0x37, - AC_JACK_LOC_MOBILE_OUT, -}; - -/* Port connectivity (0-3) */ -enum { - AC_JACK_PORT_COMPLEX, - AC_JACK_PORT_NONE, - AC_JACK_PORT_FIXED, - AC_JACK_PORT_BOTH, -}; - -/* max. connections to a widget */ -#define HDA_MAX_CONNECTIONS 32 - -/* max. codec address */ -#define HDA_MAX_CODEC_ADDRESS 0x0f - -/* - * generic arrays - */ -struct snd_array { - unsigned int used; - unsigned int alloced; - unsigned int elem_size; - unsigned int alloc_align; - void *list; -}; - -void *snd_array_new(struct snd_array *array); -void snd_array_free(struct snd_array *array); -static inline void snd_array_init(struct snd_array *array, unsigned int size, - unsigned int align) -{ - array->elem_size = size; - array->alloc_align = align; -} - -static inline void *snd_array_elem(struct snd_array *array, unsigned int idx) -{ - return array->list + idx * array->elem_size; -} - -static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) -{ - return (unsigned long)(ptr - array->list) / array->elem_size; -} - -/* - * Structures - */ - -struct hda_bus; -struct hda_beep; -struct hda_codec; -struct hda_pcm; -struct hda_pcm_stream; -struct hda_bus_unsolicited; - -/* NID type */ -typedef u16 hda_nid_t; - -/* bus operators */ -struct hda_bus_ops { - /* send a single command */ - int (*command)(struct hda_bus *bus, unsigned int cmd); - /* get a response from the last command */ - unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr); - /* free the private data */ - void (*private_free)(struct hda_bus *); - /* attach a PCM stream */ - int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, - struct hda_pcm *pcm); - /* reset bus for retry verb */ - void (*bus_reset)(struct hda_bus *bus); -#ifdef CONFIG_SND_HDA_POWER_SAVE - /* notify power-up/down from codec to controller */ - void (*pm_notify)(struct hda_bus *bus); -#endif -}; - -/* template to pass to the bus constructor */ -struct hda_bus_template { - void *private_data; - struct pci_dev *pci; - const char *modelname; - int *power_save; - struct hda_bus_ops ops; -}; - -/* - * codec bus - * - * each controller needs to creata a hda_bus to assign the accessor. - * A hda_bus contains several codecs in the list codec_list. - */ -struct hda_bus { - struct snd_card *card; - - /* copied from template */ - void *private_data; - struct pci_dev *pci; - const char *modelname; - int *power_save; - struct hda_bus_ops ops; - - /* codec linked list */ - struct list_head codec_list; - /* link caddr -> codec */ - struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; - - struct mutex cmd_mutex; - struct mutex prepare_mutex; - - /* unsolicited event queue */ - struct hda_bus_unsolicited *unsol; - char workq_name[16]; - struct workqueue_struct *workq; /* common workqueue for codecs */ - - /* assigned PCMs */ - DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES); - - /* misc op flags */ - unsigned int needs_damn_long_delay :1; - unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */ - unsigned int sync_write:1; /* sync after verb write */ - /* status for codec/controller */ - unsigned int shutdown :1; /* being unloaded */ - unsigned int rirb_error:1; /* error in codec communication */ - unsigned int response_reset:1; /* controller was reset */ - unsigned int in_reset:1; /* during reset operation */ - unsigned int power_keep_link_on:1; /* don't power off HDA link */ -}; - -/* - * codec preset - * - * Known codecs have the patch to build and set up the controls/PCMs - * better than the generic parser. - */ -struct hda_codec_preset { - unsigned int id; - unsigned int mask; - unsigned int subs; - unsigned int subs_mask; - unsigned int rev; - hda_nid_t afg, mfg; - const char *name; - int (*patch)(struct hda_codec *codec); -}; - -struct hda_codec_preset_list { - const struct hda_codec_preset *preset; - struct module *owner; - struct list_head list; -}; - -/* initial hook */ -int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset); -int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset); - -/* ops set by the preset patch */ -struct hda_codec_ops { - int (*build_controls)(struct hda_codec *codec); - int (*build_pcms)(struct hda_codec *codec); - int (*init)(struct hda_codec *codec); - void (*free)(struct hda_codec *codec); - void (*unsol_event)(struct hda_codec *codec, unsigned int res); - void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg, - unsigned int power_state); -#ifdef CONFIG_PM - int (*suspend)(struct hda_codec *codec, pm_message_t state); - int (*post_suspend)(struct hda_codec *codec); - int (*pre_resume)(struct hda_codec *codec); - int (*resume)(struct hda_codec *codec); -#endif -#ifdef CONFIG_SND_HDA_POWER_SAVE - int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); -#endif - void (*reboot_notify)(struct hda_codec *codec); -}; - -/* record for amp information cache */ -struct hda_cache_head { - u32 key; /* hash key */ - u16 val; /* assigned value */ - u16 next; /* next link; -1 = terminal */ -}; - -struct hda_amp_info { - struct hda_cache_head head; - u32 amp_caps; /* amp capabilities */ - u16 vol[2]; /* current volume & mute */ -}; - -struct hda_cache_rec { - u16 hash[64]; /* hash table for index */ - struct snd_array buf; /* record entries */ -}; - -/* PCM callbacks */ -struct hda_pcm_ops { - int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec, - struct snd_pcm_substream *substream); - int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec, - struct snd_pcm_substream *substream); - int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec, - unsigned int stream_tag, unsigned int format, - struct snd_pcm_substream *substream); - int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec, - struct snd_pcm_substream *substream); -}; - -/* PCM information for each substream */ -struct hda_pcm_stream { - unsigned int substreams; /* number of substreams, 0 = not exist*/ - unsigned int channels_min; /* min. number of channels */ - unsigned int channels_max; /* max. number of channels */ - hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ - u32 rates; /* supported rates */ - u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */ - unsigned int maxbps; /* supported max. bit per sample */ - struct hda_pcm_ops ops; -}; - -/* PCM types */ -enum { - HDA_PCM_TYPE_AUDIO, - HDA_PCM_TYPE_SPDIF, - HDA_PCM_TYPE_HDMI, - HDA_PCM_TYPE_MODEM, - HDA_PCM_NTYPES -}; - -/* for PCM creation */ -struct hda_pcm { - char *name; - struct hda_pcm_stream stream[2]; - unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ - int device; /* device number to assign */ - struct snd_pcm *pcm; /* assigned PCM instance */ -}; - -/* codec information */ -struct hda_codec { - struct hda_bus *bus; - unsigned int addr; /* codec addr*/ - struct list_head list; /* list point */ - - hda_nid_t afg; /* AFG node id */ - hda_nid_t mfg; /* MFG node id */ - - /* ids */ - u8 afg_function_id; - u8 mfg_function_id; - u8 afg_unsol; - u8 mfg_unsol; - u32 vendor_id; - u32 subsystem_id; - u32 revision_id; - - /* detected preset */ - const struct hda_codec_preset *preset; - struct module *owner; - const char *vendor_name; /* codec vendor name */ - const char *chip_name; /* codec chip name */ - const char *modelname; /* model name for preset */ - - /* set by patch */ - struct hda_codec_ops patch_ops; - - /* PCM to create, set by patch_ops.build_pcms callback */ - unsigned int num_pcms; - struct hda_pcm *pcm_info; - - /* codec specific info */ - void *spec; - - /* beep device */ - struct hda_beep *beep; - unsigned int beep_mode; - - /* widget capabilities cache */ - unsigned int num_nodes; - hda_nid_t start_nid; - u32 *wcaps; - - struct snd_array mixers; /* list of assigned mixer elements */ - struct snd_array nids; /* list of mapped mixer elements */ - - struct hda_cache_rec amp_cache; /* cache for amp access */ - struct hda_cache_rec cmd_cache; /* cache for other commands */ - - struct snd_array conn_lists; /* connection-list array */ - - struct mutex spdif_mutex; - struct mutex control_mutex; - struct snd_array spdif_out; - unsigned int spdif_in_enable; /* SPDIF input enable? */ - const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ - struct snd_array init_pins; /* initial (BIOS) pin configurations */ - struct snd_array driver_pins; /* pin configs set by codec parser */ - struct snd_array cvt_setups; /* audio convert setups */ - -#ifdef CONFIG_SND_HDA_HWDEP - struct snd_hwdep *hwdep; /* assigned hwdep device */ - struct snd_array init_verbs; /* additional init verbs */ - struct snd_array hints; /* additional hints */ - struct snd_array user_pins; /* default pin configs to override */ -#endif - - /* misc flags */ - unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each - * status change - * (e.g. Realtek codecs) - */ - unsigned int pin_amp_workaround:1; /* pin out-amp takes index - * (e.g. Conexant codecs) - */ - unsigned int single_adc_amp:1; /* adc in-amp takes no index - * (e.g. CX20549 codec) - */ - unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ - unsigned int pins_shutup:1; /* pins are shut up */ - unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ - unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ - unsigned int no_jack_detect:1; /* Machine has no jack-detection */ -#ifdef CONFIG_SND_HDA_POWER_SAVE - unsigned int power_on :1; /* current (global) power-state */ - unsigned int power_transition :1; /* power-state in transition */ - int power_count; /* current (global) power refcount */ - struct delayed_work power_work; /* delayed task for powerdown */ - unsigned long power_on_acct; - unsigned long power_off_acct; - unsigned long power_jiffies; -#endif - - /* codec-specific additional proc output */ - void (*proc_widget_hook)(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid); - - /* jack detection */ - struct snd_array jacktbl; - -#ifdef CONFIG_SND_HDA_INPUT_JACK - /* jack detection */ - struct snd_array jacks; -#endif -}; - -/* direction */ -enum { - HDA_INPUT, HDA_OUTPUT -}; - - -/* - * constructors - */ -int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, - struct hda_bus **busp); -int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, - struct hda_codec **codecp); -int snd_hda_codec_configure(struct hda_codec *codec); - -/* - * low level functions - */ -unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, - int direct, - unsigned int verb, unsigned int parm); -int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, - unsigned int verb, unsigned int parm); -#define snd_hda_param_read(codec, nid, param) \ - snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param) -int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t *start_id); -int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t *conn_list, int max_conns); -int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t *conn_list, int max_conns); -int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, - const hda_nid_t **listp); -int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums, - const hda_nid_t *list); -int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, - hda_nid_t nid, int recursive); -int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, - u32 *ratesp, u64 *formatsp, unsigned int *bpsp); - -struct hda_verb { - hda_nid_t nid; - u32 verb; - u32 param; -}; - -void snd_hda_sequence_write(struct hda_codec *codec, - const struct hda_verb *seq); - -/* unsolicited event */ -int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex); - -/* cached write */ -#ifdef CONFIG_PM -int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, - int direct, unsigned int verb, unsigned int parm); -void snd_hda_sequence_write_cache(struct hda_codec *codec, - const struct hda_verb *seq); -int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid, - int direct, unsigned int verb, unsigned int parm); -void snd_hda_codec_resume_cache(struct hda_codec *codec); -#else -#define snd_hda_codec_write_cache snd_hda_codec_write -#define snd_hda_codec_update_cache snd_hda_codec_write -#define snd_hda_sequence_write_cache snd_hda_sequence_write -#endif - -/* the struct for codec->pin_configs */ -struct hda_pincfg { - hda_nid_t nid; - unsigned char ctrl; /* current pin control value */ - unsigned char pad; /* reserved */ - unsigned int cfg; /* default configuration */ -}; - -unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid); -int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid, - unsigned int cfg); -int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list, - hda_nid_t nid, unsigned int cfg); /* for hwdep */ -void snd_hda_shutup_pins(struct hda_codec *codec); - -/* SPDIF controls */ -struct hda_spdif_out { - hda_nid_t nid; /* Converter nid values relate to */ - unsigned int status; /* IEC958 status bits */ - unsigned short ctls; /* SPDIF control bits */ -}; -struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec, - hda_nid_t nid); -void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx); -void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid); - -/* - * Mixer - */ -int snd_hda_build_controls(struct hda_bus *bus); -int snd_hda_codec_build_controls(struct hda_codec *codec); - -/* - * PCM - */ -int snd_hda_build_pcms(struct hda_bus *bus); -int snd_hda_codec_build_pcms(struct hda_codec *codec); - -int snd_hda_codec_prepare(struct hda_codec *codec, - struct hda_pcm_stream *hinfo, - unsigned int stream, - unsigned int format, - struct snd_pcm_substream *substream); -void snd_hda_codec_cleanup(struct hda_codec *codec, - struct hda_pcm_stream *hinfo, - struct snd_pcm_substream *substream); - -void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, - int channel_id, int format); -void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, - int do_now); -#define snd_hda_codec_cleanup_stream(codec, nid) \ - __snd_hda_codec_cleanup_stream(codec, nid, 0) -unsigned int snd_hda_calc_stream_format(unsigned int rate, - unsigned int channels, - unsigned int format, - unsigned int maxbps, - unsigned short spdif_ctls); -int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, - unsigned int format); - -/* - * Misc - */ -void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); -void snd_hda_bus_reboot_notify(struct hda_bus *bus); -void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, - unsigned int power_state, - bool eapd_workaround); - -/* - * power management - */ -#ifdef CONFIG_PM -int snd_hda_suspend(struct hda_bus *bus); -int snd_hda_resume(struct hda_bus *bus); -#endif - -static inline -int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) -{ -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (codec->patch_ops.check_power_status) - return codec->patch_ops.check_power_status(codec, nid); -#endif - return 0; -} - -/* - * get widget information - */ -const char *snd_hda_get_jack_connectivity(u32 cfg); -const char *snd_hda_get_jack_type(u32 cfg); -const char *snd_hda_get_jack_location(u32 cfg); - -/* - * power saving - */ -#ifdef CONFIG_SND_HDA_POWER_SAVE -void snd_hda_power_up(struct hda_codec *codec); -void snd_hda_power_down(struct hda_codec *codec); -#define snd_hda_codec_needs_resume(codec) codec->power_count -void snd_hda_update_power_acct(struct hda_codec *codec); -#else -static inline void snd_hda_power_up(struct hda_codec *codec) {} -static inline void snd_hda_power_down(struct hda_codec *codec) {} -#define snd_hda_codec_needs_resume(codec) 1 -#endif - -#ifdef CONFIG_SND_HDA_PATCH_LOADER -/* - * patch firmware - */ -int snd_hda_load_patch(struct hda_bus *bus, const char *patch); -#endif - -/* - * Codec modularization - */ - -/* Export symbols only for communication with codec drivers; - * When built in kernel, all HD-audio drivers are supposed to be statically - * linked to the kernel. Thus, the symbols don't have to (or shouldn't) be - * exported unless it's built as a module. - */ -#ifdef MODULE -#define EXPORT_SYMBOL_HDA(sym) EXPORT_SYMBOL_GPL(sym) -#else -#define EXPORT_SYMBOL_HDA(sym) -#endif - -#endif /* __SOUND_HDA_CODEC_H */ diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_eld.c b/ANDROID_3.4.5/sound/pci/hda/hda_eld.c deleted file mode 100644 index 4c054f44..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_eld.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Generic routines and proc interface for ELD(EDID Like Data) information - * - * Copyright(c) 2008 Intel Corporation. - * - * Authors: - * Wu Fengguang - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" - -enum eld_versions { - ELD_VER_CEA_861D = 2, - ELD_VER_PARTIAL = 31, -}; - -enum cea_edid_versions { - CEA_EDID_VER_NONE = 0, - CEA_EDID_VER_CEA861 = 1, - CEA_EDID_VER_CEA861A = 2, - CEA_EDID_VER_CEA861BCD = 3, - CEA_EDID_VER_RESERVED = 4, -}; - -static char *cea_speaker_allocation_names[] = { - /* 0 */ "FL/FR", - /* 1 */ "LFE", - /* 2 */ "FC", - /* 3 */ "RL/RR", - /* 4 */ "RC", - /* 5 */ "FLC/FRC", - /* 6 */ "RLC/RRC", - /* 7 */ "FLW/FRW", - /* 8 */ "FLH/FRH", - /* 9 */ "TC", - /* 10 */ "FCH", -}; - -static char *eld_connection_type_names[4] = { - "HDMI", - "DisplayPort", - "2-reserved", - "3-reserved" -}; - -enum cea_audio_coding_types { - AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0, - AUDIO_CODING_TYPE_LPCM = 1, - AUDIO_CODING_TYPE_AC3 = 2, - AUDIO_CODING_TYPE_MPEG1 = 3, - AUDIO_CODING_TYPE_MP3 = 4, - AUDIO_CODING_TYPE_MPEG2 = 5, - AUDIO_CODING_TYPE_AACLC = 6, - AUDIO_CODING_TYPE_DTS = 7, - AUDIO_CODING_TYPE_ATRAC = 8, - AUDIO_CODING_TYPE_SACD = 9, - AUDIO_CODING_TYPE_EAC3 = 10, - AUDIO_CODING_TYPE_DTS_HD = 11, - AUDIO_CODING_TYPE_MLP = 12, - AUDIO_CODING_TYPE_DST = 13, - AUDIO_CODING_TYPE_WMAPRO = 14, - AUDIO_CODING_TYPE_REF_CXT = 15, - /* also include valid xtypes below */ - AUDIO_CODING_TYPE_HE_AAC = 15, - AUDIO_CODING_TYPE_HE_AAC2 = 16, - AUDIO_CODING_TYPE_MPEG_SURROUND = 17, -}; - -enum cea_audio_coding_xtypes { - AUDIO_CODING_XTYPE_HE_REF_CT = 0, - AUDIO_CODING_XTYPE_HE_AAC = 1, - AUDIO_CODING_XTYPE_HE_AAC2 = 2, - AUDIO_CODING_XTYPE_MPEG_SURROUND = 3, - AUDIO_CODING_XTYPE_FIRST_RESERVED = 4, -}; - -static char *cea_audio_coding_type_names[] = { - /* 0 */ "undefined", - /* 1 */ "LPCM", - /* 2 */ "AC-3", - /* 3 */ "MPEG1", - /* 4 */ "MP3", - /* 5 */ "MPEG2", - /* 6 */ "AAC-LC", - /* 7 */ "DTS", - /* 8 */ "ATRAC", - /* 9 */ "DSD (One Bit Audio)", - /* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)", - /* 11 */ "DTS-HD", - /* 12 */ "MLP (Dolby TrueHD)", - /* 13 */ "DST", - /* 14 */ "WMAPro", - /* 15 */ "HE-AAC", - /* 16 */ "HE-AACv2", - /* 17 */ "MPEG Surround", -}; - -/* - * The following two lists are shared between - * - HDMI audio InfoFrame (source to sink) - * - CEA E-EDID Extension (sink to source) - */ - -/* - * SS1:SS0 index => sample size - */ -static int cea_sample_sizes[4] = { - 0, /* 0: Refer to Stream Header */ - AC_SUPPCM_BITS_16, /* 1: 16 bits */ - AC_SUPPCM_BITS_20, /* 2: 20 bits */ - AC_SUPPCM_BITS_24, /* 3: 24 bits */ -}; - -/* - * SF2:SF1:SF0 index => sampling frequency - */ -static int cea_sampling_frequencies[8] = { - 0, /* 0: Refer to Stream Header */ - SNDRV_PCM_RATE_32000, /* 1: 32000Hz */ - SNDRV_PCM_RATE_44100, /* 2: 44100Hz */ - SNDRV_PCM_RATE_48000, /* 3: 48000Hz */ - SNDRV_PCM_RATE_88200, /* 4: 88200Hz */ - SNDRV_PCM_RATE_96000, /* 5: 96000Hz */ - SNDRV_PCM_RATE_176400, /* 6: 176400Hz */ - SNDRV_PCM_RATE_192000, /* 7: 192000Hz */ -}; - -static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid, - int byte_index) -{ - unsigned int val; - - val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_HDMI_ELDD, byte_index); -#ifdef BE_PARANOID - printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val); -#endif - return val; -} - -#define GRAB_BITS(buf, byte, lowbit, bits) \ -({ \ - BUILD_BUG_ON(lowbit > 7); \ - BUILD_BUG_ON(bits > 8); \ - BUILD_BUG_ON(bits <= 0); \ - \ - (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \ -}) - -static void hdmi_update_short_audio_desc(struct cea_sad *a, - const unsigned char *buf) -{ - int i; - int val; - - val = GRAB_BITS(buf, 1, 0, 7); - a->rates = 0; - for (i = 0; i < 7; i++) - if (val & (1 << i)) - a->rates |= cea_sampling_frequencies[i + 1]; - - a->channels = GRAB_BITS(buf, 0, 0, 3); - a->channels++; - - a->sample_bits = 0; - a->max_bitrate = 0; - - a->format = GRAB_BITS(buf, 0, 3, 4); - switch (a->format) { - case AUDIO_CODING_TYPE_REF_STREAM_HEADER: - snd_printd(KERN_INFO - "HDMI: audio coding type 0 not expected\n"); - break; - - case AUDIO_CODING_TYPE_LPCM: - val = GRAB_BITS(buf, 2, 0, 3); - for (i = 0; i < 3; i++) - if (val & (1 << i)) - a->sample_bits |= cea_sample_sizes[i + 1]; - break; - - case AUDIO_CODING_TYPE_AC3: - case AUDIO_CODING_TYPE_MPEG1: - case AUDIO_CODING_TYPE_MP3: - case AUDIO_CODING_TYPE_MPEG2: - case AUDIO_CODING_TYPE_AACLC: - case AUDIO_CODING_TYPE_DTS: - case AUDIO_CODING_TYPE_ATRAC: - a->max_bitrate = GRAB_BITS(buf, 2, 0, 8); - a->max_bitrate *= 8000; - break; - - case AUDIO_CODING_TYPE_SACD: - break; - - case AUDIO_CODING_TYPE_EAC3: - break; - - case AUDIO_CODING_TYPE_DTS_HD: - break; - - case AUDIO_CODING_TYPE_MLP: - break; - - case AUDIO_CODING_TYPE_DST: - break; - - case AUDIO_CODING_TYPE_WMAPRO: - a->profile = GRAB_BITS(buf, 2, 0, 3); - break; - - case AUDIO_CODING_TYPE_REF_CXT: - a->format = GRAB_BITS(buf, 2, 3, 5); - if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT || - a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) { - snd_printd(KERN_INFO - "HDMI: audio coding xtype %d not expected\n", - a->format); - a->format = 0; - } else - a->format += AUDIO_CODING_TYPE_HE_AAC - - AUDIO_CODING_XTYPE_HE_AAC; - break; - } -} - -/* - * Be careful, ELD buf could be totally rubbish! - */ -static int hdmi_update_eld(struct hdmi_eld *e, - const unsigned char *buf, int size) -{ - int mnl; - int i; - - e->eld_ver = GRAB_BITS(buf, 0, 3, 5); - if (e->eld_ver != ELD_VER_CEA_861D && - e->eld_ver != ELD_VER_PARTIAL) { - snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n", - e->eld_ver); - goto out_fail; - } - - e->eld_size = size; - e->baseline_len = GRAB_BITS(buf, 2, 0, 8); - mnl = GRAB_BITS(buf, 4, 0, 5); - e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3); - - e->support_hdcp = GRAB_BITS(buf, 5, 0, 1); - e->support_ai = GRAB_BITS(buf, 5, 1, 1); - e->conn_type = GRAB_BITS(buf, 5, 2, 2); - e->sad_count = GRAB_BITS(buf, 5, 4, 4); - - e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2; - e->spk_alloc = GRAB_BITS(buf, 7, 0, 7); - - e->port_id = get_unaligned_le64(buf + 8); - - /* not specified, but the spec's tendency is little endian */ - e->manufacture_id = get_unaligned_le16(buf + 16); - e->product_id = get_unaligned_le16(buf + 18); - - if (mnl > ELD_MAX_MNL) { - snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl); - goto out_fail; - } else if (ELD_FIXED_BYTES + mnl > size) { - snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl); - goto out_fail; - } else - strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1); - - for (i = 0; i < e->sad_count; i++) { - if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) { - snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i); - goto out_fail; - } - hdmi_update_short_audio_desc(e->sad + i, - buf + ELD_FIXED_BYTES + mnl + 3 * i); - } - - /* - * HDMI sink's ELD info cannot always be retrieved for now, e.g. - * in console or for audio devices. Assume the highest speakers - * configuration, to _not_ prohibit multi-channel audio playback. - */ - if (!e->spk_alloc) - e->spk_alloc = 0xffff; - - e->eld_valid = true; - return 0; - -out_fail: - return -EINVAL; -} - -int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) -{ - return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, - AC_DIPSIZE_ELD_BUF); -} - -int snd_hdmi_get_eld(struct hdmi_eld *eld, - struct hda_codec *codec, hda_nid_t nid) -{ - int i; - int ret; - int size; - unsigned char *buf; - - /* - * ELD size is initialized to zero in caller function. If no errors and - * ELD is valid, actual eld_size is assigned in hdmi_update_eld() - */ - - size = snd_hdmi_get_eld_size(codec, nid); - if (size == 0) { - /* wfg: workaround for ASUS P5E-VM HDMI board */ - snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n"); - size = 128; - } - if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) { - snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size); - return -ERANGE; - } - - /* set ELD buffer */ - buf = eld->eld_buffer; - - for (i = 0; i < size; i++) { - unsigned int val = hdmi_get_eld_data(codec, nid, i); - /* - * Graphics driver might be writing to ELD buffer right now. - * Just abort. The caller will repoll after a while. - */ - if (!(val & AC_ELDD_ELD_VALID)) { - snd_printd(KERN_INFO - "HDMI: invalid ELD data byte %d\n", i); - ret = -EINVAL; - goto error; - } - val &= AC_ELDD_ELD_DATA; - /* - * The first byte cannot be zero. This can happen on some DVI - * connections. Some Intel chips may also need some 250ms delay - * to return non-zero ELD data, even when the graphics driver - * correctly writes ELD content before setting ELD_valid bit. - */ - if (!val && !i) { - snd_printdd(KERN_INFO "HDMI: 0 ELD data\n"); - ret = -EINVAL; - goto error; - } - buf[i] = val; - } - - ret = hdmi_update_eld(eld, buf, size); - -error: - return ret; -} - -/** - * SNDRV_PCM_RATE_* and AC_PAR_PCM values don't match, print correct rates with - * hdmi-specific routine. - */ -static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) -{ - static unsigned int alsa_rates[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, - 88200, 96000, 176400, 192000, 384000 - }; - int i, j; - - for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++) - if (pcm & (1 << i)) - j += snprintf(buf + j, buflen - j, " %d", - alsa_rates[i]); - - buf[j] = '\0'; /* necessary when j == 0 */ -} - -#define SND_PRINT_RATES_ADVISED_BUFSIZE 80 - -static void hdmi_show_short_audio_desc(struct cea_sad *a) -{ - char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; - char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits ="; - - if (!a->format) - return; - - hdmi_print_pcm_rates(a->rates, buf, sizeof(buf)); - - if (a->format == AUDIO_CODING_TYPE_LPCM) - snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2) - 8); - else if (a->max_bitrate) - snprintf(buf2, sizeof(buf2), - ", max bitrate = %d", a->max_bitrate); - else - buf2[0] = '\0'; - - _snd_printd(SND_PR_VERBOSE, "HDMI: supports coding type %s:" - " channels = %d, rates =%s%s\n", - cea_audio_coding_type_names[a->format], - a->channels, - buf, - buf2); -} - -void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) -{ - int i, j; - - for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) { - if (spk_alloc & (1 << i)) - j += snprintf(buf + j, buflen - j, " %s", - cea_speaker_allocation_names[i]); - } - buf[j] = '\0'; /* necessary when j == 0 */ -} - -void snd_hdmi_show_eld(struct hdmi_eld *e) -{ - int i; - - _snd_printd(SND_PR_VERBOSE, "HDMI: detected monitor %s at connection type %s\n", - e->monitor_name, - eld_connection_type_names[e->conn_type]); - - if (e->spk_alloc) { - char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; - snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); - _snd_printd(SND_PR_VERBOSE, "HDMI: available speakers:%s\n", buf); - } - - for (i = 0; i < e->sad_count; i++) - hdmi_show_short_audio_desc(e->sad + i); -} - -#ifdef CONFIG_PROC_FS - -static void hdmi_print_sad_info(int i, struct cea_sad *a, - struct snd_info_buffer *buffer) -{ - char buf[SND_PRINT_RATES_ADVISED_BUFSIZE]; - - snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n", - i, a->format, cea_audio_coding_type_names[a->format]); - snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels); - - hdmi_print_pcm_rates(a->rates, buf, sizeof(buf)); - snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf); - - if (a->format == AUDIO_CODING_TYPE_LPCM) { - snd_print_pcm_bits(a->sample_bits, buf, sizeof(buf)); - snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n", - i, a->sample_bits, buf); - } - - if (a->max_bitrate) - snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n", - i, a->max_bitrate); - - if (a->profile) - snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile); -} - -static void hdmi_print_eld_info(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct hdmi_eld *e = entry->private_data; - char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; - int i; - static char *eld_versoin_names[32] = { - "reserved", - "reserved", - "CEA-861D or below", - [3 ... 30] = "reserved", - [31] = "partial" - }; - static char *cea_edid_version_names[8] = { - "no CEA EDID Timing Extension block present", - "CEA-861", - "CEA-861-A", - "CEA-861-B, C or D", - [4 ... 7] = "reserved" - }; - - snd_iprintf(buffer, "monitor_present\t\t%d\n", e->monitor_present); - snd_iprintf(buffer, "eld_valid\t\t%d\n", e->eld_valid); - if (!e->eld_valid) - return; - snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name); - snd_iprintf(buffer, "connection_type\t\t%s\n", - eld_connection_type_names[e->conn_type]); - snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver, - eld_versoin_names[e->eld_ver]); - snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver, - cea_edid_version_names[e->cea_edid_ver]); - snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id); - snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id); - snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id); - snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp); - snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai); - snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay); - - snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf)); - snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf); - - snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count); - - for (i = 0; i < e->sad_count; i++) - hdmi_print_sad_info(i, e->sad + i, buffer); -} - -static void hdmi_write_eld_info(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct hdmi_eld *e = entry->private_data; - char line[64]; - char name[64]; - char *sname; - long long val; - unsigned int n; - - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%s %llx", name, &val) != 2) - continue; - /* - * We don't allow modification to these fields: - * monitor_name manufacture_id product_id - * eld_version edid_version - */ - if (!strcmp(name, "monitor_present")) - e->monitor_present = val; - else if (!strcmp(name, "eld_valid")) - e->eld_valid = val; - else if (!strcmp(name, "connection_type")) - e->conn_type = val; - else if (!strcmp(name, "port_id")) - e->port_id = val; - else if (!strcmp(name, "support_hdcp")) - e->support_hdcp = val; - else if (!strcmp(name, "support_ai")) - e->support_ai = val; - else if (!strcmp(name, "audio_sync_delay")) - e->aud_synch_delay = val; - else if (!strcmp(name, "speakers")) - e->spk_alloc = val; - else if (!strcmp(name, "sad_count")) - e->sad_count = val; - else if (!strncmp(name, "sad", 3)) { - sname = name + 4; - n = name[3] - '0'; - if (name[4] >= '0' && name[4] <= '9') { - sname++; - n = 10 * n + name[4] - '0'; - } - if (n >= ELD_MAX_SAD) - continue; - if (!strcmp(sname, "_coding_type")) - e->sad[n].format = val; - else if (!strcmp(sname, "_channels")) - e->sad[n].channels = val; - else if (!strcmp(sname, "_rates")) - e->sad[n].rates = val; - else if (!strcmp(sname, "_bits")) - e->sad[n].sample_bits = val; - else if (!strcmp(sname, "_max_bitrate")) - e->sad[n].max_bitrate = val; - else if (!strcmp(sname, "_profile")) - e->sad[n].profile = val; - if (n >= e->sad_count) - e->sad_count = n + 1; - } - } -} - - -int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, - int index) -{ - char name[32]; - struct snd_info_entry *entry; - int err; - - snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index); - err = snd_card_proc_new(codec->bus->card, name, &entry); - if (err < 0) - return err; - - snd_info_set_text_ops(entry, eld, hdmi_print_eld_info); - entry->c.text.write = hdmi_write_eld_info; - entry->mode |= S_IWUSR; - eld->proc_entry = entry; - - return 0; -} - -void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) -{ - if (!codec->bus->shutdown && eld->proc_entry) { - snd_device_free(codec->bus->card, eld->proc_entry); - eld->proc_entry = NULL; - } -} - -#endif /* CONFIG_PROC_FS */ - -/* update PCM info based on ELD */ -void snd_hdmi_eld_update_pcm_info(struct hdmi_eld *eld, - struct hda_pcm_stream *hinfo) -{ - u32 rates; - u64 formats; - unsigned int maxbps; - unsigned int channels_max; - int i; - - /* assume basic audio support (the basic audio flag is not in ELD; - * however, all audio capable sinks are required to support basic - * audio) */ - rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000; - formats = SNDRV_PCM_FMTBIT_S16_LE; - maxbps = 16; - channels_max = 2; - for (i = 0; i < eld->sad_count; i++) { - struct cea_sad *a = &eld->sad[i]; - rates |= a->rates; - if (a->channels > channels_max) - channels_max = a->channels; - if (a->format == AUDIO_CODING_TYPE_LPCM) { - if (a->sample_bits & AC_SUPPCM_BITS_20) { - formats |= SNDRV_PCM_FMTBIT_S32_LE; - if (maxbps < 20) - maxbps = 20; - } - if (a->sample_bits & AC_SUPPCM_BITS_24) { - formats |= SNDRV_PCM_FMTBIT_S32_LE; - if (maxbps < 24) - maxbps = 24; - } - } - } - - /* restrict the parameters by the values the codec provides */ - hinfo->rates &= rates; - hinfo->formats &= formats; - hinfo->maxbps = min(hinfo->maxbps, maxbps); - hinfo->channels_max = min(hinfo->channels_max, channels_max); -} diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_generic.c b/ANDROID_3.4.5/sound/pci/hda/hda_generic.c deleted file mode 100644 index 431bf868..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_generic.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * Generic widget tree parser - * - * Copyright (c) 2004 Takashi Iwai - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" - -/* widget node for parsing */ -struct hda_gnode { - hda_nid_t nid; /* NID of this widget */ - unsigned short nconns; /* number of input connections */ - hda_nid_t *conn_list; - hda_nid_t slist[2]; /* temporay list */ - unsigned int wid_caps; /* widget capabilities */ - unsigned char type; /* widget type */ - unsigned char pin_ctl; /* pin controls */ - unsigned char checked; /* the flag indicates that the node is already parsed */ - unsigned int pin_caps; /* pin widget capabilities */ - unsigned int def_cfg; /* default configuration */ - unsigned int amp_out_caps; /* AMP out capabilities */ - unsigned int amp_in_caps; /* AMP in capabilities */ - struct list_head list; -}; - -/* patch-specific record */ - -#define MAX_PCM_VOLS 2 -struct pcm_vol { - struct hda_gnode *node; /* Node for PCM volume */ - unsigned int index; /* connection of PCM volume */ -}; - -struct hda_gspec { - struct hda_gnode *dac_node[2]; /* DAC node */ - struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ - struct pcm_vol pcm_vol[MAX_PCM_VOLS]; /* PCM volumes */ - unsigned int pcm_vol_nodes; /* number of PCM volumes */ - - struct hda_gnode *adc_node; /* ADC node */ - struct hda_gnode *cap_vol_node; /* Node for capture volume */ - unsigned int cur_cap_src; /* current capture source */ - struct hda_input_mux input_mux; - - unsigned int def_amp_in_caps; - unsigned int def_amp_out_caps; - - struct hda_pcm pcm_rec; /* PCM information */ - - struct list_head nid_list; /* list of widgets */ - -#ifdef CONFIG_SND_HDA_POWER_SAVE -#define MAX_LOOPBACK_AMPS 7 - struct hda_loopback_check loopback; - int num_loopbacks; - struct hda_amp_list loopback_list[MAX_LOOPBACK_AMPS + 1]; -#endif -}; - -/* - * retrieve the default device type from the default config value - */ -#define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> \ - AC_DEFCFG_DEVICE_SHIFT) -#define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> \ - AC_DEFCFG_LOCATION_SHIFT) -#define defcfg_port_conn(node) (((node)->def_cfg & AC_DEFCFG_PORT_CONN) >> \ - AC_DEFCFG_PORT_CONN_SHIFT) - -/* - * destructor - */ -static void snd_hda_generic_free(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - struct hda_gnode *node, *n; - - if (! spec) - return; - /* free all widgets */ - list_for_each_entry_safe(node, n, &spec->nid_list, list) { - if (node->conn_list != node->slist) - kfree(node->conn_list); - kfree(node); - } - kfree(spec); -} - - -/* - * add a new widget node and read its attributes - */ -static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid_t nid) -{ - struct hda_gnode *node; - int nconns; - hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (node == NULL) - return -ENOMEM; - node->nid = nid; - node->wid_caps = get_wcaps(codec, nid); - node->type = get_wcaps_type(node->wid_caps); - if (node->wid_caps & AC_WCAP_CONN_LIST) { - nconns = snd_hda_get_connections(codec, nid, conn_list, - HDA_MAX_CONNECTIONS); - if (nconns < 0) { - kfree(node); - return nconns; - } - } else { - nconns = 0; - } - if (nconns <= ARRAY_SIZE(node->slist)) - node->conn_list = node->slist; - else { - node->conn_list = kmalloc(sizeof(hda_nid_t) * nconns, - GFP_KERNEL); - if (! node->conn_list) { - snd_printk(KERN_ERR "hda-generic: cannot malloc\n"); - kfree(node); - return -ENOMEM; - } - } - memcpy(node->conn_list, conn_list, nconns * sizeof(hda_nid_t)); - node->nconns = nconns; - - if (node->type == AC_WID_PIN) { - node->pin_caps = snd_hda_query_pin_caps(codec, node->nid); - node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - node->def_cfg = snd_hda_codec_get_pincfg(codec, node->nid); - } - - if (node->wid_caps & AC_WCAP_OUT_AMP) { - if (node->wid_caps & AC_WCAP_AMP_OVRD) - node->amp_out_caps = snd_hda_param_read(codec, node->nid, AC_PAR_AMP_OUT_CAP); - if (! node->amp_out_caps) - node->amp_out_caps = spec->def_amp_out_caps; - } - if (node->wid_caps & AC_WCAP_IN_AMP) { - if (node->wid_caps & AC_WCAP_AMP_OVRD) - node->amp_in_caps = snd_hda_param_read(codec, node->nid, AC_PAR_AMP_IN_CAP); - if (! node->amp_in_caps) - node->amp_in_caps = spec->def_amp_in_caps; - } - list_add_tail(&node->list, &spec->nid_list); - return 0; -} - -/* - * build the AFG subtree - */ -static int build_afg_tree(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - int i, nodes, err; - hda_nid_t nid; - - if (snd_BUG_ON(!spec)) - return -EINVAL; - - spec->def_amp_out_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_OUT_CAP); - spec->def_amp_in_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_IN_CAP); - - nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); - if (! nid || nodes < 0) { - printk(KERN_ERR "Invalid AFG subtree\n"); - return -EINVAL; - } - - /* parse all nodes belonging to the AFG */ - for (i = 0; i < nodes; i++, nid++) { - if ((err = add_new_node(codec, spec, nid)) < 0) - return err; - } - - return 0; -} - - -/* - * look for the node record for the given NID - */ -/* FIXME: should avoid the braindead linear search */ -static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid) -{ - struct hda_gnode *node; - - list_for_each_entry(node, &spec->nid_list, list) { - if (node->nid == nid) - return node; - } - return NULL; -} - -/* - * unmute (and set max vol) the output amplifier - */ -static int unmute_output(struct hda_codec *codec, struct hda_gnode *node) -{ - unsigned int val, ofs; - snd_printdd("UNMUTE OUT: NID=0x%x\n", node->nid); - val = (node->amp_out_caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; - ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; - if (val >= ofs) - val -= ofs; - snd_hda_codec_amp_stereo(codec, node->nid, HDA_OUTPUT, 0, 0xff, val); - return 0; -} - -/* - * unmute (and set max vol) the input amplifier - */ -static int unmute_input(struct hda_codec *codec, struct hda_gnode *node, unsigned int index) -{ - unsigned int val, ofs; - snd_printdd("UNMUTE IN: NID=0x%x IDX=0x%x\n", node->nid, index); - val = (node->amp_in_caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; - ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; - if (val >= ofs) - val -= ofs; - snd_hda_codec_amp_stereo(codec, node->nid, HDA_INPUT, index, 0xff, val); - return 0; -} - -/* - * select the input connection of the given node. - */ -static int select_input_connection(struct hda_codec *codec, struct hda_gnode *node, - unsigned int index) -{ - snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index); - return snd_hda_codec_write_cache(codec, node->nid, 0, - AC_VERB_SET_CONNECT_SEL, index); -} - -/* - * clear checked flag of each node in the node list - */ -static void clear_check_flags(struct hda_gspec *spec) -{ - struct hda_gnode *node; - - list_for_each_entry(node, &spec->nid_list, list) { - node->checked = 0; - } -} - -/* - * parse the output path recursively until reach to an audio output widget - * - * returns 0 if not found, 1 if found, or a negative error code. - */ -static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, - struct hda_gnode *node, int dac_idx) -{ - int i, err; - struct hda_gnode *child; - - if (node->checked) - return 0; - - node->checked = 1; - if (node->type == AC_WID_AUD_OUT) { - if (node->wid_caps & AC_WCAP_DIGITAL) { - snd_printdd("Skip Digital OUT node %x\n", node->nid); - return 0; - } - snd_printdd("AUD_OUT found %x\n", node->nid); - if (spec->dac_node[dac_idx]) { - /* already DAC node is assigned, just unmute & connect */ - return node == spec->dac_node[dac_idx]; - } - spec->dac_node[dac_idx] = node; - if ((node->wid_caps & AC_WCAP_OUT_AMP) && - spec->pcm_vol_nodes < MAX_PCM_VOLS) { - spec->pcm_vol[spec->pcm_vol_nodes].node = node; - spec->pcm_vol[spec->pcm_vol_nodes].index = 0; - spec->pcm_vol_nodes++; - } - return 1; /* found */ - } - - for (i = 0; i < node->nconns; i++) { - child = hda_get_node(spec, node->conn_list[i]); - if (! child) - continue; - err = parse_output_path(codec, spec, child, dac_idx); - if (err < 0) - return err; - else if (err > 0) { - /* found one, - * select the path, unmute both input and output - */ - if (node->nconns > 1) - select_input_connection(codec, node, i); - unmute_input(codec, node, i); - unmute_output(codec, node); - if (spec->dac_node[dac_idx] && - spec->pcm_vol_nodes < MAX_PCM_VOLS && - !(spec->dac_node[dac_idx]->wid_caps & - AC_WCAP_OUT_AMP)) { - if ((node->wid_caps & AC_WCAP_IN_AMP) || - (node->wid_caps & AC_WCAP_OUT_AMP)) { - int n = spec->pcm_vol_nodes; - spec->pcm_vol[n].node = node; - spec->pcm_vol[n].index = i; - spec->pcm_vol_nodes++; - } - } - return 1; - } - } - return 0; -} - -/* - * Look for the output PIN widget with the given jack type - * and parse the output path to that PIN. - * - * Returns the PIN node when the path to DAC is established. - */ -static struct hda_gnode *parse_output_jack(struct hda_codec *codec, - struct hda_gspec *spec, - int jack_type) -{ - struct hda_gnode *node; - int err; - - list_for_each_entry(node, &spec->nid_list, list) { - if (node->type != AC_WID_PIN) - continue; - /* output capable? */ - if (! (node->pin_caps & AC_PINCAP_OUT)) - continue; - if (defcfg_port_conn(node) == AC_JACK_PORT_NONE) - continue; /* unconnected */ - if (jack_type >= 0) { - if (jack_type != defcfg_type(node)) - continue; - if (node->wid_caps & AC_WCAP_DIGITAL) - continue; /* skip SPDIF */ - } else { - /* output as default? */ - if (! (node->pin_ctl & AC_PINCTL_OUT_EN)) - continue; - } - clear_check_flags(spec); - err = parse_output_path(codec, spec, node, 0); - if (err < 0) - return NULL; - if (! err && spec->out_pin_node[0]) { - err = parse_output_path(codec, spec, node, 1); - if (err < 0) - return NULL; - } - if (err > 0) { - /* unmute the PIN output */ - unmute_output(codec, node); - /* set PIN-Out enable */ - snd_hda_codec_write_cache(codec, node->nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - AC_PINCTL_OUT_EN | - ((node->pin_caps & AC_PINCAP_HP_DRV) ? - AC_PINCTL_HP_EN : 0)); - return node; - } - } - return NULL; -} - - -/* - * parse outputs - */ -static int parse_output(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - struct hda_gnode *node; - - /* - * Look for the output PIN widget - */ - /* first, look for the line-out pin */ - node = parse_output_jack(codec, spec, AC_JACK_LINE_OUT); - if (node) /* found, remember the PIN node */ - spec->out_pin_node[0] = node; - else { - /* if no line-out is found, try speaker out */ - node = parse_output_jack(codec, spec, AC_JACK_SPEAKER); - if (node) - spec->out_pin_node[0] = node; - } - /* look for the HP-out pin */ - node = parse_output_jack(codec, spec, AC_JACK_HP_OUT); - if (node) { - if (! spec->out_pin_node[0]) - spec->out_pin_node[0] = node; - else - spec->out_pin_node[1] = node; - } - - if (! spec->out_pin_node[0]) { - /* no line-out or HP pins found, - * then choose for the first output pin - */ - spec->out_pin_node[0] = parse_output_jack(codec, spec, -1); - if (! spec->out_pin_node[0]) - snd_printd("hda_generic: no proper output path found\n"); - } - - return 0; -} - -/* - * input MUX - */ - -/* control callbacks */ -static int capture_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_gspec *spec = codec->spec; - return snd_hda_input_mux_info(&spec->input_mux, uinfo); -} - -static int capture_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_gspec *spec = codec->spec; - - ucontrol->value.enumerated.item[0] = spec->cur_cap_src; - return 0; -} - -static int capture_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_gspec *spec = codec->spec; - return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol, - spec->adc_node->nid, &spec->cur_cap_src); -} - -/* - * return the string name of the given input PIN widget - */ -static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) -{ - unsigned int location = defcfg_location(node); - switch (defcfg_type(node)) { - case AC_JACK_LINE_IN: - if ((location & 0x0f) == AC_JACK_LOC_FRONT) - return "Front Line"; - return "Line"; - case AC_JACK_CD: -#if 0 - if (pinctl) - *pinctl |= AC_PINCTL_VREF_GRD; -#endif - return "CD"; - case AC_JACK_AUX: - if ((location & 0x0f) == AC_JACK_LOC_FRONT) - return "Front Aux"; - return "Aux"; - case AC_JACK_MIC_IN: - if (pinctl && - (node->pin_caps & - (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT))) - *pinctl |= AC_PINCTL_VREF_80; - if ((location & 0x0f) == AC_JACK_LOC_FRONT) - return "Front Mic"; - return "Mic"; - case AC_JACK_SPDIF_IN: - return "SPDIF"; - case AC_JACK_DIG_OTHER_IN: - return "Digital"; - } - return NULL; -} - -/* - * parse the nodes recursively until reach to the input PIN - * - * returns 0 if not found, 1 if found, or a negative error code. - */ -static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, - struct hda_gnode *node, int idx) -{ - int i, err; - unsigned int pinctl; - const char *type; - - if (node->checked) - return 0; - - node->checked = 1; - if (node->type != AC_WID_PIN) { - for (i = 0; i < node->nconns; i++) { - struct hda_gnode *child; - child = hda_get_node(spec, node->conn_list[i]); - if (! child) - continue; - err = parse_adc_sub_nodes(codec, spec, child, idx); - if (err < 0) - return err; - if (err > 0) { - /* found one, - * select the path, unmute both input and output - */ - if (node->nconns > 1) - select_input_connection(codec, node, i); - unmute_input(codec, node, i); - unmute_output(codec, node); - return err; - } - } - return 0; - } - - /* input capable? */ - if (! (node->pin_caps & AC_PINCAP_IN)) - return 0; - - if (defcfg_port_conn(node) == AC_JACK_PORT_NONE) - return 0; /* unconnected */ - - if (node->wid_caps & AC_WCAP_DIGITAL) - return 0; /* skip SPDIF */ - - if (spec->input_mux.num_items >= HDA_MAX_NUM_INPUTS) { - snd_printk(KERN_ERR "hda_generic: Too many items for capture\n"); - return -EINVAL; - } - - pinctl = AC_PINCTL_IN_EN; - /* create a proper capture source label */ - type = get_input_type(node, &pinctl); - if (! type) { - /* input as default? */ - if (! (node->pin_ctl & AC_PINCTL_IN_EN)) - return 0; - type = "Input"; - } - snd_hda_add_imux_item(&spec->input_mux, type, idx, NULL); - - /* unmute the PIN external input */ - unmute_input(codec, node, 0); /* index = 0? */ - /* set PIN-In enable */ - snd_hda_codec_write_cache(codec, node->nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); - - return 1; /* found */ -} - -/* - * parse input - */ -static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) -{ - struct hda_gspec *spec = codec->spec; - struct hda_gnode *node; - int i, err; - - snd_printdd("AUD_IN = %x\n", adc_node->nid); - clear_check_flags(spec); - - // awk added - fixed no recording due to muted widget - unmute_input(codec, adc_node, 0); - - /* - * check each connection of the ADC - * if it reaches to a proper input PIN, add the path as the - * input path. - */ - /* first, check the direct connections to PIN widgets */ - for (i = 0; i < adc_node->nconns; i++) { - node = hda_get_node(spec, adc_node->conn_list[i]); - if (node && node->type == AC_WID_PIN) { - err = parse_adc_sub_nodes(codec, spec, node, i); - if (err < 0) - return err; - } - } - /* ... then check the rests, more complicated connections */ - for (i = 0; i < adc_node->nconns; i++) { - node = hda_get_node(spec, adc_node->conn_list[i]); - if (node && node->type != AC_WID_PIN) { - err = parse_adc_sub_nodes(codec, spec, node, i); - if (err < 0) - return err; - } - } - - if (! spec->input_mux.num_items) - return 0; /* no input path found... */ - - snd_printdd("[Capture Source] NID=0x%x, #SRC=%d\n", adc_node->nid, spec->input_mux.num_items); - for (i = 0; i < spec->input_mux.num_items; i++) - snd_printdd(" [%s] IDX=0x%x\n", spec->input_mux.items[i].label, - spec->input_mux.items[i].index); - - spec->adc_node = adc_node; - return 1; -} - -/* - * parse input - */ -static int parse_input(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - struct hda_gnode *node; - int err; - - /* - * At first we look for an audio input widget. - * If it reaches to certain input PINs, we take it as the - * input path. - */ - list_for_each_entry(node, &spec->nid_list, list) { - if (node->wid_caps & AC_WCAP_DIGITAL) - continue; /* skip SPDIF */ - if (node->type == AC_WID_AUD_IN) { - err = parse_input_path(codec, node); - if (err < 0) - return err; - else if (err > 0) - return 0; - } - } - snd_printd("hda_generic: no proper input path found\n"); - return 0; -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static void add_input_loopback(struct hda_codec *codec, hda_nid_t nid, - int dir, int idx) -{ - struct hda_gspec *spec = codec->spec; - struct hda_amp_list *p; - - if (spec->num_loopbacks >= MAX_LOOPBACK_AMPS) { - snd_printk(KERN_ERR "hda_generic: Too many loopback ctls\n"); - return; - } - p = &spec->loopback_list[spec->num_loopbacks++]; - p->nid = nid; - p->dir = dir; - p->idx = idx; - spec->loopback.amplist = spec->loopback_list; -} -#else -#define add_input_loopback(codec,nid,dir,idx) -#endif - -/* - * create mixer controls if possible - */ -static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, - unsigned int index, const char *type, - const char *dir_sfx, int is_loopback) -{ - char name[32]; - int err; - int created = 0; - struct snd_kcontrol_new knew; - - if (type) - sprintf(name, "%s %s Switch", type, dir_sfx); - else - sprintf(name, "%s Switch", dir_sfx); - if ((node->wid_caps & AC_WCAP_IN_AMP) && - (node->amp_in_caps & AC_AMPCAP_MUTE)) { - knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT); - if (is_loopback) - add_input_loopback(codec, node->nid, HDA_INPUT, index); - snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); - err = snd_hda_ctl_add(codec, node->nid, - snd_ctl_new1(&knew, codec)); - if (err < 0) - return err; - created = 1; - } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && - (node->amp_out_caps & AC_AMPCAP_MUTE)) { - knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT); - if (is_loopback) - add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); - snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); - err = snd_hda_ctl_add(codec, node->nid, - snd_ctl_new1(&knew, codec)); - if (err < 0) - return err; - created = 1; - } - - if (type) - sprintf(name, "%s %s Volume", type, dir_sfx); - else - sprintf(name, "%s Volume", dir_sfx); - if ((node->wid_caps & AC_WCAP_IN_AMP) && - (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { - knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); - snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); - err = snd_hda_ctl_add(codec, node->nid, - snd_ctl_new1(&knew, codec)); - if (err < 0) - return err; - created = 1; - } else if ((node->wid_caps & AC_WCAP_OUT_AMP) && - (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { - knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); - snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); - err = snd_hda_ctl_add(codec, node->nid, - snd_ctl_new1(&knew, codec)); - if (err < 0) - return err; - created = 1; - } - - return created; -} - -/* - * check whether the controls with the given name and direction suffix already exist - */ -static int check_existing_control(struct hda_codec *codec, const char *type, const char *dir) -{ - struct snd_ctl_elem_id id; - memset(&id, 0, sizeof(id)); - sprintf(id.name, "%s %s Volume", type, dir); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - if (snd_ctl_find_id(codec->bus->card, &id)) - return 1; - sprintf(id.name, "%s %s Switch", type, dir); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - if (snd_ctl_find_id(codec->bus->card, &id)) - return 1; - return 0; -} - -/* - * build output mixer controls - */ -static int create_output_mixers(struct hda_codec *codec, - const char * const *names) -{ - struct hda_gspec *spec = codec->spec; - int i, err; - - for (i = 0; i < spec->pcm_vol_nodes; i++) { - err = create_mixer(codec, spec->pcm_vol[i].node, - spec->pcm_vol[i].index, - names[i], "Playback", 0); - if (err < 0) - return err; - } - return 0; -} - -static int build_output_controls(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - static const char * const types_speaker[] = { "Speaker", "Headphone" }; - static const char * const types_line[] = { "Front", "Headphone" }; - - switch (spec->pcm_vol_nodes) { - case 1: - return create_mixer(codec, spec->pcm_vol[0].node, - spec->pcm_vol[0].index, - "Master", "Playback", 0); - case 2: - if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) - return create_output_mixers(codec, types_speaker); - else - return create_output_mixers(codec, types_line); - } - return 0; -} - -/* create capture volume/switch */ -static int build_input_controls(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - struct hda_gnode *adc_node = spec->adc_node; - int i, err; - static struct snd_kcontrol_new cap_sel = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = capture_source_info, - .get = capture_source_get, - .put = capture_source_put, - }; - - if (! adc_node || ! spec->input_mux.num_items) - return 0; /* not found */ - - spec->cur_cap_src = 0; - select_input_connection(codec, adc_node, - spec->input_mux.items[0].index); - - /* create capture volume and switch controls if the ADC has an amp */ - /* do we have only a single item? */ - if (spec->input_mux.num_items == 1) { - err = create_mixer(codec, adc_node, - spec->input_mux.items[0].index, - NULL, "Capture", 0); - if (err < 0) - return err; - return 0; - } - - /* create input MUX if multiple sources are available */ - err = snd_hda_ctl_add(codec, spec->adc_node->nid, - snd_ctl_new1(&cap_sel, codec)); - if (err < 0) - return err; - - /* no volume control? */ - if (! (adc_node->wid_caps & AC_WCAP_IN_AMP) || - ! (adc_node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) - return 0; - - for (i = 0; i < spec->input_mux.num_items; i++) { - struct snd_kcontrol_new knew; - char name[32]; - sprintf(name, "%s Capture Volume", - spec->input_mux.items[i].label); - knew = (struct snd_kcontrol_new) - HDA_CODEC_VOLUME(name, adc_node->nid, - spec->input_mux.items[i].index, - HDA_INPUT); - err = snd_hda_ctl_add(codec, adc_node->nid, - snd_ctl_new1(&knew, codec)); - if (err < 0) - return err; - } - - return 0; -} - - -/* - * parse the nodes recursively until reach to the output PIN. - * - * returns 0 - if not found, - * 1 - if found, but no mixer is created - * 2 - if found and mixer was already created, (just skip) - * a negative error code - */ -static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec, - struct hda_gnode *node, struct hda_gnode *dest_node, - const char *type) -{ - int i, err; - - if (node->checked) - return 0; - - node->checked = 1; - if (node == dest_node) { - /* loopback connection found */ - return 1; - } - - for (i = 0; i < node->nconns; i++) { - struct hda_gnode *child = hda_get_node(spec, node->conn_list[i]); - if (! child) - continue; - err = parse_loopback_path(codec, spec, child, dest_node, type); - if (err < 0) - return err; - else if (err >= 1) { - if (err == 1) { - err = create_mixer(codec, node, i, type, - "Playback", 1); - if (err < 0) - return err; - if (err > 0) - return 2; /* ok, created */ - /* not created, maybe in the lower path */ - err = 1; - } - /* connect and unmute */ - if (node->nconns > 1) - select_input_connection(codec, node, i); - unmute_input(codec, node, i); - unmute_output(codec, node); - return err; - } - } - return 0; -} - -/* - * parse the tree and build the loopback controls - */ -static int build_loopback_controls(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - struct hda_gnode *node; - int err; - const char *type; - - if (! spec->out_pin_node[0]) - return 0; - - list_for_each_entry(node, &spec->nid_list, list) { - if (node->type != AC_WID_PIN) - continue; - /* input capable? */ - if (! (node->pin_caps & AC_PINCAP_IN)) - return 0; - type = get_input_type(node, NULL); - if (type) { - if (check_existing_control(codec, type, "Playback")) - continue; - clear_check_flags(spec); - err = parse_loopback_path(codec, spec, - spec->out_pin_node[0], - node, type); - if (err < 0) - return err; - if (! err) - continue; - } - } - return 0; -} - -/* - * build mixer controls - */ -static int build_generic_controls(struct hda_codec *codec) -{ - int err; - - if ((err = build_input_controls(codec)) < 0 || - (err = build_output_controls(codec)) < 0 || - (err = build_loopback_controls(codec)) < 0) - return err; - - return 0; -} - -/* - * PCM - */ -static struct hda_pcm_stream generic_pcm_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, -}; - -static int generic_pcm2_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct hda_gspec *spec = codec->spec; - - snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format); - snd_hda_codec_setup_stream(codec, spec->dac_node[1]->nid, - stream_tag, 0, format); - return 0; -} - -static int generic_pcm2_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct hda_gspec *spec = codec->spec; - - snd_hda_codec_cleanup_stream(codec, hinfo->nid); - snd_hda_codec_cleanup_stream(codec, spec->dac_node[1]->nid); - return 0; -} - -static int build_generic_pcms(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - struct hda_pcm *info = &spec->pcm_rec; - - if (! spec->dac_node[0] && ! spec->adc_node) { - snd_printd("hda_generic: no PCM found\n"); - return 0; - } - - codec->num_pcms = 1; - codec->pcm_info = info; - - info->name = "HDA Generic"; - if (spec->dac_node[0]) { - info->stream[0] = generic_pcm_playback; - info->stream[0].nid = spec->dac_node[0]->nid; - if (spec->dac_node[1]) { - info->stream[0].ops.prepare = generic_pcm2_prepare; - info->stream[0].ops.cleanup = generic_pcm2_cleanup; - } - } - if (spec->adc_node) { - info->stream[1] = generic_pcm_playback; - info->stream[1].nid = spec->adc_node->nid; - } - - return 0; -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid) -{ - struct hda_gspec *spec = codec->spec; - return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); -} -#endif - - -/* - */ -static struct hda_codec_ops generic_patch_ops = { - .build_controls = build_generic_controls, - .build_pcms = build_generic_pcms, - .free = snd_hda_generic_free, -#ifdef CONFIG_SND_HDA_POWER_SAVE - .check_power_status = generic_check_power_status, -#endif -}; - -/* - * the generic parser - */ -int snd_hda_parse_generic_codec(struct hda_codec *codec) -{ - struct hda_gspec *spec; - int err; - - if(!codec->afg) - return 0; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) { - printk(KERN_ERR "hda_generic: can't allocate spec\n"); - return -ENOMEM; - } - codec->spec = spec; - INIT_LIST_HEAD(&spec->nid_list); - - if ((err = build_afg_tree(codec)) < 0) - goto error; - - if ((err = parse_input(codec)) < 0 || - (err = parse_output(codec)) < 0) - goto error; - - codec->patch_ops = generic_patch_ops; - - return 0; - - error: - snd_hda_generic_free(codec); - return err; -} -EXPORT_SYMBOL(snd_hda_parse_generic_codec); diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_hwdep.c b/ANDROID_3.4.5/sound/pci/hda/hda_hwdep.c deleted file mode 100644 index 6b2efb8c..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_hwdep.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * HWDEP Interface for HD-audio codec - * - * Copyright (c) 2007 Takashi Iwai - * - * This driver 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 driver 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 -#include -#include "hda_codec.h" -#include "hda_local.h" -#include -#include - -/* hint string pair */ -struct hda_hint { - const char *key; - const char *val; /* contained in the same alloc as key */ -}; - -/* - * write/read an out-of-bound verb - */ -static int verb_write_ioctl(struct hda_codec *codec, - struct hda_verb_ioctl __user *arg) -{ - u32 verb, res; - - if (get_user(verb, &arg->verb)) - return -EFAULT; - res = snd_hda_codec_read(codec, verb >> 24, 0, - (verb >> 8) & 0xffff, verb & 0xff); - if (put_user(res, &arg->res)) - return -EFAULT; - return 0; -} - -static int get_wcap_ioctl(struct hda_codec *codec, - struct hda_verb_ioctl __user *arg) -{ - u32 verb, res; - - if (get_user(verb, &arg->verb)) - return -EFAULT; - res = get_wcaps(codec, verb >> 24); - if (put_user(res, &arg->res)) - return -EFAULT; - return 0; -} - - -/* - */ -static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct hda_codec *codec = hw->private_data; - void __user *argp = (void __user *)arg; - - switch (cmd) { - case HDA_IOCTL_PVERSION: - return put_user(HDA_HWDEP_VERSION, (int __user *)argp); - case HDA_IOCTL_VERB_WRITE: - return verb_write_ioctl(codec, argp); - case HDA_IOCTL_GET_WCAP: - return get_wcap_ioctl(codec, argp); - } - return -ENOIOCTLCMD; -} - -#ifdef CONFIG_COMPAT -static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return hda_hwdep_ioctl(hw, file, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - -static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file) -{ -#ifndef CONFIG_SND_DEBUG_VERBOSE - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; -#endif - return 0; -} - -static void clear_hwdep_elements(struct hda_codec *codec) -{ - int i; - - /* clear init verbs */ - snd_array_free(&codec->init_verbs); - /* clear hints */ - for (i = 0; i < codec->hints.used; i++) { - struct hda_hint *hint = snd_array_elem(&codec->hints, i); - kfree(hint->key); /* we don't need to free hint->val */ - } - snd_array_free(&codec->hints); - snd_array_free(&codec->user_pins); -} - -static void hwdep_free(struct snd_hwdep *hwdep) -{ - clear_hwdep_elements(hwdep->private_data); -} - -int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) -{ - char hwname[16]; - struct snd_hwdep *hwdep; - int err; - - sprintf(hwname, "HDA Codec %d", codec->addr); - err = snd_hwdep_new(codec->bus->card, hwname, codec->addr, &hwdep); - if (err < 0) - return err; - codec->hwdep = hwdep; - sprintf(hwdep->name, "HDA Codec %d", codec->addr); - hwdep->iface = SNDRV_HWDEP_IFACE_HDA; - hwdep->private_data = codec; - hwdep->private_free = hwdep_free; - hwdep->exclusive = 1; - - hwdep->ops.open = hda_hwdep_open; - hwdep->ops.ioctl = hda_hwdep_ioctl; -#ifdef CONFIG_COMPAT - hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; -#endif - - snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32); - snd_array_init(&codec->hints, sizeof(struct hda_hint), 32); - snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16); - - return 0; -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static ssize_t power_on_acct_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - snd_hda_update_power_acct(codec); - return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct)); -} - -static ssize_t power_off_acct_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - snd_hda_update_power_acct(codec); - return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct)); -} - -static struct device_attribute power_attrs[] = { - __ATTR_RO(power_on_acct), - __ATTR_RO(power_off_acct), -}; - -int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) -{ - struct snd_hwdep *hwdep = codec->hwdep; - int i; - - for (i = 0; i < ARRAY_SIZE(power_attrs); i++) - snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, - hwdep->device, &power_attrs[i]); - return 0; -} -#endif /* CONFIG_SND_HDA_POWER_SAVE */ - -#ifdef CONFIG_SND_HDA_RECONFIG - -/* - * sysfs interface - */ - -static int clear_codec(struct hda_codec *codec) -{ - int err; - - err = snd_hda_codec_reset(codec); - if (err < 0) { - snd_printk(KERN_ERR "The codec is being used, can't free.\n"); - return err; - } - clear_hwdep_elements(codec); - return 0; -} - -static int reconfig_codec(struct hda_codec *codec) -{ - int err; - - snd_hda_power_up(codec); - snd_printk(KERN_INFO "hda-codec: reconfiguring\n"); - err = snd_hda_codec_reset(codec); - if (err < 0) { - snd_printk(KERN_ERR - "The codec is being used, can't reconfigure.\n"); - goto error; - } - err = snd_hda_codec_configure(codec); - if (err < 0) - goto error; - /* rebuild PCMs */ - err = snd_hda_codec_build_pcms(codec); - if (err < 0) - goto error; - /* rebuild mixers */ - err = snd_hda_codec_build_controls(codec); - if (err < 0) - goto error; - err = snd_card_register(codec->bus->card); - error: - snd_hda_power_down(codec); - return err; -} - -/* - * allocate a string at most len chars, and remove the trailing EOL - */ -static char *kstrndup_noeol(const char *src, size_t len) -{ - char *s = kstrndup(src, len, GFP_KERNEL); - char *p; - if (!s) - return NULL; - p = strchr(s, '\n'); - if (p) - *p = 0; - return s; -} - -#define CODEC_INFO_SHOW(type) \ -static ssize_t type##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - return sprintf(buf, "0x%x\n", codec->type); \ -} - -#define CODEC_INFO_STR_SHOW(type) \ -static ssize_t type##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - return sprintf(buf, "%s\n", \ - codec->type ? codec->type : ""); \ -} - -CODEC_INFO_SHOW(vendor_id); -CODEC_INFO_SHOW(subsystem_id); -CODEC_INFO_SHOW(revision_id); -CODEC_INFO_SHOW(afg); -CODEC_INFO_SHOW(mfg); -CODEC_INFO_STR_SHOW(vendor_name); -CODEC_INFO_STR_SHOW(chip_name); -CODEC_INFO_STR_SHOW(modelname); - -#define CODEC_INFO_STORE(type) \ -static ssize_t type##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - unsigned long val; \ - int err = strict_strtoul(buf, 0, &val); \ - if (err < 0) \ - return err; \ - codec->type = val; \ - return count; \ -} - -#define CODEC_INFO_STR_STORE(type) \ -static ssize_t type##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - char *s = kstrndup_noeol(buf, 64); \ - if (!s) \ - return -ENOMEM; \ - kfree(codec->type); \ - codec->type = s; \ - return count; \ -} - -CODEC_INFO_STORE(vendor_id); -CODEC_INFO_STORE(subsystem_id); -CODEC_INFO_STORE(revision_id); -CODEC_INFO_STR_STORE(vendor_name); -CODEC_INFO_STR_STORE(chip_name); -CODEC_INFO_STR_STORE(modelname); - -#define CODEC_ACTION_STORE(type) \ -static ssize_t type##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); \ - struct hda_codec *codec = hwdep->private_data; \ - int err = 0; \ - if (*buf) \ - err = type##_codec(codec); \ - return err < 0 ? err : count; \ -} - -CODEC_ACTION_STORE(reconfig); -CODEC_ACTION_STORE(clear); - -static ssize_t init_verbs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int i, len = 0; - for (i = 0; i < codec->init_verbs.used; i++) { - struct hda_verb *v = snd_array_elem(&codec->init_verbs, i); - len += snprintf(buf + len, PAGE_SIZE - len, - "0x%02x 0x%03x 0x%04x\n", - v->nid, v->verb, v->param); - } - return len; -} - -static int parse_init_verbs(struct hda_codec *codec, const char *buf) -{ - struct hda_verb *v; - int nid, verb, param; - - if (sscanf(buf, "%i %i %i", &nid, &verb, ¶m) != 3) - return -EINVAL; - if (!nid || !verb) - return -EINVAL; - v = snd_array_new(&codec->init_verbs); - if (!v) - return -ENOMEM; - v->nid = nid; - v->verb = verb; - v->param = param; - return 0; -} - -static ssize_t init_verbs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int err = parse_init_verbs(codec, buf); - if (err < 0) - return err; - return count; -} - -static ssize_t hints_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int i, len = 0; - for (i = 0; i < codec->hints.used; i++) { - struct hda_hint *hint = snd_array_elem(&codec->hints, i); - len += snprintf(buf + len, PAGE_SIZE - len, - "%s = %s\n", hint->key, hint->val); - } - return len; -} - -static struct hda_hint *get_hint(struct hda_codec *codec, const char *key) -{ - int i; - - for (i = 0; i < codec->hints.used; i++) { - struct hda_hint *hint = snd_array_elem(&codec->hints, i); - if (!strcmp(hint->key, key)) - return hint; - } - return NULL; -} - -static void remove_trail_spaces(char *str) -{ - char *p; - if (!*str) - return; - p = str + strlen(str) - 1; - for (; isspace(*p); p--) { - *p = 0; - if (p == str) - return; - } -} - -#define MAX_HINTS 1024 - -static int parse_hints(struct hda_codec *codec, const char *buf) -{ - char *key, *val; - struct hda_hint *hint; - - buf = skip_spaces(buf); - if (!*buf || *buf == '#' || *buf == '\n') - return 0; - if (*buf == '=') - return -EINVAL; - key = kstrndup_noeol(buf, 1024); - if (!key) - return -ENOMEM; - /* extract key and val */ - val = strchr(key, '='); - if (!val) { - kfree(key); - return -EINVAL; - } - *val++ = 0; - val = skip_spaces(val); - remove_trail_spaces(key); - remove_trail_spaces(val); - hint = get_hint(codec, key); - if (hint) { - /* replace */ - kfree(hint->key); - hint->key = key; - hint->val = val; - return 0; - } - /* allocate a new hint entry */ - if (codec->hints.used >= MAX_HINTS) - hint = NULL; - else - hint = snd_array_new(&codec->hints); - if (!hint) { - kfree(key); - return -ENOMEM; - } - hint->key = key; - hint->val = val; - return 0; -} - -static ssize_t hints_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int err = parse_hints(codec, buf); - if (err < 0) - return err; - return count; -} - -static ssize_t pin_configs_show(struct hda_codec *codec, - struct snd_array *list, - char *buf) -{ - int i, len = 0; - for (i = 0; i < list->used; i++) { - struct hda_pincfg *pin = snd_array_elem(list, i); - len += sprintf(buf + len, "0x%02x 0x%08x\n", - pin->nid, pin->cfg); - } - return len; -} - -static ssize_t init_pin_configs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - return pin_configs_show(codec, &codec->init_pins, buf); -} - -static ssize_t user_pin_configs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - return pin_configs_show(codec, &codec->user_pins, buf); -} - -static ssize_t driver_pin_configs_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - return pin_configs_show(codec, &codec->driver_pins, buf); -} - -#define MAX_PIN_CONFIGS 32 - -static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) -{ - int nid, cfg; - - if (sscanf(buf, "%i %i", &nid, &cfg) != 2) - return -EINVAL; - if (!nid) - return -EINVAL; - return snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg); -} - -static ssize_t user_pin_configs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct snd_hwdep *hwdep = dev_get_drvdata(dev); - struct hda_codec *codec = hwdep->private_data; - int err = parse_user_pin_configs(codec, buf); - if (err < 0) - return err; - return count; -} - -#define CODEC_ATTR_RW(type) \ - __ATTR(type, 0644, type##_show, type##_store) -#define CODEC_ATTR_RO(type) \ - __ATTR_RO(type) -#define CODEC_ATTR_WO(type) \ - __ATTR(type, 0200, NULL, type##_store) - -static struct device_attribute codec_attrs[] = { - CODEC_ATTR_RW(vendor_id), - CODEC_ATTR_RW(subsystem_id), - CODEC_ATTR_RW(revision_id), - CODEC_ATTR_RO(afg), - CODEC_ATTR_RO(mfg), - CODEC_ATTR_RW(vendor_name), - CODEC_ATTR_RW(chip_name), - CODEC_ATTR_RW(modelname), - CODEC_ATTR_RW(init_verbs), - CODEC_ATTR_RW(hints), - CODEC_ATTR_RO(init_pin_configs), - CODEC_ATTR_RW(user_pin_configs), - CODEC_ATTR_RO(driver_pin_configs), - CODEC_ATTR_WO(reconfig), - CODEC_ATTR_WO(clear), -}; - -/* - * create sysfs files on hwdep directory - */ -int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) -{ - struct snd_hwdep *hwdep = codec->hwdep; - int i; - - for (i = 0; i < ARRAY_SIZE(codec_attrs); i++) - snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, - hwdep->device, &codec_attrs[i]); - return 0; -} - -/* - * Look for hint string - */ -const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) -{ - struct hda_hint *hint = get_hint(codec, key); - return hint ? hint->val : NULL; -} -EXPORT_SYMBOL_HDA(snd_hda_get_hint); - -int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) -{ - const char *p = snd_hda_get_hint(codec, key); - if (!p || !*p) - return -ENOENT; - switch (toupper(*p)) { - case 'T': /* true */ - case 'Y': /* yes */ - case '1': - return 1; - } - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint); - -#endif /* CONFIG_SND_HDA_RECONFIG */ - -#ifdef CONFIG_SND_HDA_PATCH_LOADER - -/* parser mode */ -enum { - LINE_MODE_NONE, - LINE_MODE_CODEC, - LINE_MODE_MODEL, - LINE_MODE_PINCFG, - LINE_MODE_VERB, - LINE_MODE_HINT, - LINE_MODE_VENDOR_ID, - LINE_MODE_SUBSYSTEM_ID, - LINE_MODE_REVISION_ID, - LINE_MODE_CHIP_NAME, - NUM_LINE_MODES, -}; - -static inline int strmatch(const char *a, const char *b) -{ - return strnicmp(a, b, strlen(b)) == 0; -} - -/* parse the contents after the line "[codec]" - * accept only the line with three numbers, and assign the current codec - */ -static void parse_codec_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - int vendorid, subid, caddr; - struct hda_codec *codec; - - *codecp = NULL; - if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) { - list_for_each_entry(codec, &bus->codec_list, list) { - if ((vendorid <= 0 || codec->vendor_id == vendorid) && - (subid <= 0 || codec->subsystem_id == subid) && - codec->addr == caddr) { - *codecp = codec; - break; - } - } - } -} - -/* parse the contents after the other command tags, [pincfg], [verb], - * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model] - * just pass to the sysfs helper (only when any codec was specified) - */ -static void parse_pincfg_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - parse_user_pin_configs(*codecp, buf); -} - -static void parse_verb_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - parse_init_verbs(*codecp, buf); -} - -static void parse_hint_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - parse_hints(*codecp, buf); -} - -static void parse_model_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - kfree((*codecp)->modelname); - (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); -} - -static void parse_chip_name_mode(char *buf, struct hda_bus *bus, - struct hda_codec **codecp) -{ - kfree((*codecp)->chip_name); - (*codecp)->chip_name = kstrdup(buf, GFP_KERNEL); -} - -#define DEFINE_PARSE_ID_MODE(name) \ -static void parse_##name##_mode(char *buf, struct hda_bus *bus, \ - struct hda_codec **codecp) \ -{ \ - unsigned long val; \ - if (!strict_strtoul(buf, 0, &val)) \ - (*codecp)->name = val; \ -} - -DEFINE_PARSE_ID_MODE(vendor_id); -DEFINE_PARSE_ID_MODE(subsystem_id); -DEFINE_PARSE_ID_MODE(revision_id); - - -struct hda_patch_item { - const char *tag; - void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); - int need_codec; -}; - -static struct hda_patch_item patch_items[NUM_LINE_MODES] = { - [LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 }, - [LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 }, - [LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 }, - [LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 }, - [LINE_MODE_HINT] = { "[hint]", parse_hint_mode, 1 }, - [LINE_MODE_VENDOR_ID] = { "[vendor_id]", parse_vendor_id_mode, 1 }, - [LINE_MODE_SUBSYSTEM_ID] = { "[subsystem_id]", parse_subsystem_id_mode, 1 }, - [LINE_MODE_REVISION_ID] = { "[revision_id]", parse_revision_id_mode, 1 }, - [LINE_MODE_CHIP_NAME] = { "[chip_name]", parse_chip_name_mode, 1 }, -}; - -/* check the line starting with '[' -- change the parser mode accodingly */ -static int parse_line_mode(char *buf, struct hda_bus *bus) -{ - int i; - for (i = 0; i < ARRAY_SIZE(patch_items); i++) { - if (!patch_items[i].tag) - continue; - if (strmatch(buf, patch_items[i].tag)) - return i; - } - return LINE_MODE_NONE; -} - -/* copy one line from the buffer in fw, and update the fields in fw - * return zero if it reaches to the end of the buffer, or non-zero - * if successfully copied a line - * - * the spaces at the beginning and the end of the line are stripped - */ -static int get_line_from_fw(char *buf, int size, struct firmware *fw) -{ - int len; - const char *p = fw->data; - while (isspace(*p) && fw->size) { - p++; - fw->size--; - } - if (!fw->size) - return 0; - - for (len = 0; len < fw->size; len++) { - if (!*p) - break; - if (*p == '\n') { - p++; - len++; - break; - } - if (len < size) - *buf++ = *p++; - } - *buf = 0; - fw->size -= len; - fw->data = p; - remove_trail_spaces(buf); - return 1; -} - -/* - * load a "patch" firmware file and parse it - */ -int snd_hda_load_patch(struct hda_bus *bus, const char *patch) -{ - int err; - const struct firmware *fw; - struct firmware tmp; - char buf[128]; - struct hda_codec *codec; - int line_mode; - struct device *dev = bus->card->dev; - - if (snd_BUG_ON(!dev)) - return -ENODEV; - err = request_firmware(&fw, patch, dev); - if (err < 0) { - printk(KERN_ERR "hda-codec: Cannot load the patch '%s'\n", - patch); - return err; - } - - tmp = *fw; - line_mode = LINE_MODE_NONE; - codec = NULL; - while (get_line_from_fw(buf, sizeof(buf) - 1, &tmp)) { - if (!*buf || *buf == '#' || *buf == '\n') - continue; - if (*buf == '[') - line_mode = parse_line_mode(buf, bus); - else if (patch_items[line_mode].parser && - (codec || !patch_items[line_mode].need_codec)) - patch_items[line_mode].parser(buf, bus, &codec); - } - release_firmware(fw); - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_load_patch); -#endif /* CONFIG_SND_HDA_PATCH_LOADER */ diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_intel.c b/ANDROID_3.4.5/sound/pci/hda/hda_intel.c deleted file mode 100644 index 1f350522..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_intel.c +++ /dev/null @@ -1,3173 +0,0 @@ -/* - * - * hda_intel.c - Implementation of primary alsa driver code base - * for Intel HD Audio. - * - * Copyright(c) 2004 Intel Corporation. All rights reserved. - * - * Copyright (c) 2004 Takashi Iwai - * PeiSen Hou - * - * 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. - * - * CONTACTS: - * - * Matt Jared matt.jared@intel.com - * Andy Kopp andy.kopp@intel.com - * Dan Kogan dan.d.kogan@intel.com - * - * CHANGES: - * - * 2004.12.01 Major rewrite by tiwai, merged the work of pshou - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_X86 -/* for snoop control */ -#include -#include -#endif -#include -#include -#include "hda_codec.h" - - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -static char *model[SNDRV_CARDS]; -static int position_fix[SNDRV_CARDS]; -static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; -static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; -static int probe_only[SNDRV_CARDS]; -static bool single_cmd; -static int enable_msi = -1; -#ifdef CONFIG_SND_HDA_PATCH_LOADER -static char *patch[SNDRV_CARDS]; -#endif -#ifdef CONFIG_SND_HDA_INPUT_BEEP -static int beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = - CONFIG_SND_HDA_INPUT_BEEP_MODE}; -#endif - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Intel HD audio interface."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); -module_param_array(model, charp, NULL, 0444); -MODULE_PARM_DESC(model, "Use the given board model."); -module_param_array(position_fix, int, NULL, 0444); -MODULE_PARM_DESC(position_fix, "DMA pointer read method." - "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO)."); -module_param_array(bdl_pos_adj, int, NULL, 0644); -MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); -module_param_array(probe_mask, int, NULL, 0444); -MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); -module_param_array(probe_only, int, NULL, 0444); -MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); -module_param(single_cmd, bool, 0444); -MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " - "(for debugging only)."); -module_param(enable_msi, bint, 0444); -MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); -#ifdef CONFIG_SND_HDA_PATCH_LOADER -module_param_array(patch, charp, NULL, 0444); -MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface."); -#endif -#ifdef CONFIG_SND_HDA_INPUT_BEEP -module_param_array(beep_mode, int, NULL, 0444); -MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " - "(0=off, 1=on, 2=mute switch on/off) (default=1)."); -#endif - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; -module_param(power_save, int, 0644); -MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " - "(in second, 0 = disable)."); - -/* reset the HD-audio controller in power save mode. - * this may give more power-saving, but will take longer time to - * wake up. - */ -static bool power_save_controller = 1; -module_param(power_save_controller, bool, 0644); -MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); -#endif - -static int align_buffer_size = -1; -module_param(align_buffer_size, bint, 0644); -MODULE_PARM_DESC(align_buffer_size, - "Force buffer and period sizes to be multiple of 128 bytes."); - -#ifdef CONFIG_X86 -static bool hda_snoop = true; -module_param_named(snoop, hda_snoop, bool, 0444); -MODULE_PARM_DESC(snoop, "Enable/disable snooping"); -#define azx_snoop(chip) (chip)->snoop -#else -#define hda_snoop true -#define azx_snoop(chip) true -#endif - - -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," - "{Intel, ICH6M}," - "{Intel, ICH7}," - "{Intel, ESB2}," - "{Intel, ICH8}," - "{Intel, ICH9}," - "{Intel, ICH10}," - "{Intel, PCH}," - "{Intel, CPT}," - "{Intel, PPT}," - "{Intel, LPT}," - "{Intel, PBG}," - "{Intel, SCH}," - "{ATI, SB450}," - "{ATI, SB600}," - "{ATI, RS600}," - "{ATI, RS690}," - "{ATI, RS780}," - "{ATI, R600}," - "{ATI, RV630}," - "{ATI, RV610}," - "{ATI, RV670}," - "{ATI, RV635}," - "{ATI, RV620}," - "{ATI, RV770}," - "{VIA, VT8251}," - "{VIA, VT8237A}," - "{SiS, SIS966}," - "{ULI, M5461}}"); -MODULE_DESCRIPTION("Intel HDA driver"); - -#ifdef CONFIG_SND_VERBOSE_PRINTK -#define SFX /* nop */ -#else -#define SFX "hda-intel: " -#endif - -/* - * registers - */ -#define ICH6_REG_GCAP 0x00 -#define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */ -#define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */ -#define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */ -#define ICH6_GCAP_ISS (15 << 8) /* # of input streams */ -#define ICH6_GCAP_OSS (15 << 12) /* # of output streams */ -#define ICH6_REG_VMIN 0x02 -#define ICH6_REG_VMAJ 0x03 -#define ICH6_REG_OUTPAY 0x04 -#define ICH6_REG_INPAY 0x06 -#define ICH6_REG_GCTL 0x08 -#define ICH6_GCTL_RESET (1 << 0) /* controller reset */ -#define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */ -#define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ -#define ICH6_REG_WAKEEN 0x0c -#define ICH6_REG_STATESTS 0x0e -#define ICH6_REG_GSTS 0x10 -#define ICH6_GSTS_FSTS (1 << 1) /* flush status */ -#define ICH6_REG_INTCTL 0x20 -#define ICH6_REG_INTSTS 0x24 -#define ICH6_REG_WALLCLK 0x30 /* 24Mhz source */ -#define ICH6_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ -#define ICH6_REG_SSYNC 0x38 -#define ICH6_REG_CORBLBASE 0x40 -#define ICH6_REG_CORBUBASE 0x44 -#define ICH6_REG_CORBWP 0x48 -#define ICH6_REG_CORBRP 0x4a -#define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */ -#define ICH6_REG_CORBCTL 0x4c -#define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */ -#define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ -#define ICH6_REG_CORBSTS 0x4d -#define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */ -#define ICH6_REG_CORBSIZE 0x4e - -#define ICH6_REG_RIRBLBASE 0x50 -#define ICH6_REG_RIRBUBASE 0x54 -#define ICH6_REG_RIRBWP 0x58 -#define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */ -#define ICH6_REG_RINTCNT 0x5a -#define ICH6_REG_RIRBCTL 0x5c -#define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ -#define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */ -#define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ -#define ICH6_REG_RIRBSTS 0x5d -#define ICH6_RBSTS_IRQ (1 << 0) /* response irq */ -#define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */ -#define ICH6_REG_RIRBSIZE 0x5e - -#define ICH6_REG_IC 0x60 -#define ICH6_REG_IR 0x64 -#define ICH6_REG_IRS 0x68 -#define ICH6_IRS_VALID (1<<1) -#define ICH6_IRS_BUSY (1<<0) - -#define ICH6_REG_DPLBASE 0x70 -#define ICH6_REG_DPUBASE 0x74 -#define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */ - -/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ -enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; - -/* stream register offsets from stream base */ -#define ICH6_REG_SD_CTL 0x00 -#define ICH6_REG_SD_STS 0x03 -#define ICH6_REG_SD_LPIB 0x04 -#define ICH6_REG_SD_CBL 0x08 -#define ICH6_REG_SD_LVI 0x0c -#define ICH6_REG_SD_FIFOW 0x0e -#define ICH6_REG_SD_FIFOSIZE 0x10 -#define ICH6_REG_SD_FORMAT 0x12 -#define ICH6_REG_SD_BDLPL 0x18 -#define ICH6_REG_SD_BDLPU 0x1c - -/* PCI space */ -#define ICH6_PCIREG_TCSEL 0x44 - -/* - * other constants - */ - -/* max number of SDs */ -/* ICH, ATI and VIA have 4 playback and 4 capture */ -#define ICH6_NUM_CAPTURE 4 -#define ICH6_NUM_PLAYBACK 4 - -/* ULI has 6 playback and 5 capture */ -#define ULI_NUM_CAPTURE 5 -#define ULI_NUM_PLAYBACK 6 - -/* ATI HDMI has 1 playback and 0 capture */ -#define ATIHDMI_NUM_CAPTURE 0 -#define ATIHDMI_NUM_PLAYBACK 1 - -/* TERA has 4 playback and 3 capture */ -#define TERA_NUM_CAPTURE 3 -#define TERA_NUM_PLAYBACK 4 - -/* this number is statically defined for simplicity */ -#define MAX_AZX_DEV 16 - -/* max number of fragments - we may use more if allocating more pages for BDL */ -#define BDL_SIZE 4096 -#define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) -#define AZX_MAX_FRAG 32 -/* max buffer size - no h/w limit, you can increase as you like */ -#define AZX_MAX_BUF_SIZE (1024*1024*1024) - -/* RIRB int mask: overrun[2], response[0] */ -#define RIRB_INT_RESPONSE 0x01 -#define RIRB_INT_OVERRUN 0x04 -#define RIRB_INT_MASK 0x05 - -/* STATESTS int mask: S3,SD2,SD1,SD0 */ -#define AZX_MAX_CODECS 8 -#define AZX_DEFAULT_CODECS 4 -#define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) - -/* SD_CTL bits */ -#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ -#define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ -#define SD_CTL_STRIPE (3 << 16) /* stripe control */ -#define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ -#define SD_CTL_DIR (1 << 19) /* bi-directional stream */ -#define SD_CTL_STREAM_TAG_MASK (0xf << 20) -#define SD_CTL_STREAM_TAG_SHIFT 20 - -/* SD_CTL and SD_STS */ -#define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ -#define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ -#define SD_INT_COMPLETE 0x04 /* completion interrupt */ -#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ - SD_INT_COMPLETE) - -/* SD_STS */ -#define SD_STS_FIFO_READY 0x20 /* FIFO ready */ - -/* INTCTL and INTSTS */ -#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */ -#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ -#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ - -/* below are so far hardcoded - should read registers in future */ -#define ICH6_MAX_CORB_ENTRIES 256 -#define ICH6_MAX_RIRB_ENTRIES 256 - -/* position fix mode */ -enum { - POS_FIX_AUTO, - POS_FIX_LPIB, - POS_FIX_POSBUF, - POS_FIX_VIACOMBO, - POS_FIX_COMBO, -}; - -/* Defines for ATI HD Audio support in SB450 south bridge */ -#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 -#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 - -/* Defines for Nvidia HDA support */ -#define NVIDIA_HDA_TRANSREG_ADDR 0x4e -#define NVIDIA_HDA_ENABLE_COHBITS 0x0f -#define NVIDIA_HDA_ISTRM_COH 0x4d -#define NVIDIA_HDA_OSTRM_COH 0x4c -#define NVIDIA_HDA_ENABLE_COHBIT 0x01 - -/* Defines for Intel SCH HDA snoop control */ -#define INTEL_SCH_HDA_DEVC 0x78 -#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) - -/* Define IN stream 0 FIFO size offset in VIA controller */ -#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET 0x90 -/* Define VIA HD Audio Device ID*/ -#define VIA_HDAC_DEVICE_ID 0x3288 - -/* HD Audio class code */ -#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403 - -/* - */ - -struct azx_dev { - struct snd_dma_buffer bdl; /* BDL buffer */ - u32 *posbuf; /* position buffer pointer */ - - unsigned int bufsize; /* size of the play buffer in bytes */ - 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 long start_wallclk; /* start + minimum wallclk */ - unsigned long period_wallclk; /* wallclk for period */ - - void __iomem *sd_addr; /* stream descriptor pointer */ - - u32 sd_int_sta_mask; /* stream int status mask */ - - /* pcm support */ - struct snd_pcm_substream *substream; /* assigned substream, - * set in PCM open - */ - unsigned int format_val; /* format value to be set in the - * controller and the codec - */ - unsigned char stream_tag; /* assigned stream */ - unsigned char index; /* stream index */ - int assigned_key; /* last device# key assigned to */ - - unsigned int opened :1; - unsigned int running :1; - unsigned int irq_pending :1; - /* - * For VIA: - * A flag to ensure DMA position is 0 - * when link position is not greater than FIFO size - */ - unsigned int insufficient :1; - unsigned int wc_marked:1; -}; - -/* CORB/RIRB */ -struct azx_rb { - u32 *buf; /* CORB/RIRB buffer - * Each CORB entry is 4byte, RIRB is 8byte - */ - dma_addr_t addr; /* physical address of CORB/RIRB buffer */ - /* for RIRB */ - unsigned short rp, wp; /* read/write pointers */ - int cmds[AZX_MAX_CODECS]; /* number of pending requests */ - u32 res[AZX_MAX_CODECS]; /* last read value */ -}; - -struct azx_pcm { - struct azx *chip; - struct snd_pcm *pcm; - struct hda_codec *codec; - struct hda_pcm_stream *hinfo[2]; - struct list_head list; -}; - -struct azx { - struct snd_card *card; - struct pci_dev *pci; - int dev_index; - - /* chip type specific */ - int driver_type; - unsigned int driver_caps; - int playback_streams; - int playback_index_offset; - int capture_streams; - int capture_index_offset; - int num_streams; - - /* pci resources */ - unsigned long addr; - void __iomem *remap_addr; - int irq; - - /* locks */ - spinlock_t reg_lock; - struct mutex open_mutex; - - /* streams (x num_streams) */ - struct azx_dev *azx_dev; - - /* PCM */ - struct list_head pcm_list; /* azx_pcm list */ - - /* HD codec */ - unsigned short codec_mask; - int codec_probe_mask; /* copied from probe_mask option */ - struct hda_bus *bus; - unsigned int beep_mode; - - /* CORB/RIRB */ - struct azx_rb corb; - struct azx_rb rirb; - - /* CORB/RIRB and position buffers */ - struct snd_dma_buffer rb; - struct snd_dma_buffer posbuf; - - /* flags */ - int position_fix[2]; /* for both playback/capture streams */ - int poll_count; - unsigned int running :1; - unsigned int initialized :1; - unsigned int single_cmd :1; - unsigned int polling_mode :1; - unsigned int msi :1; - unsigned int irq_pending_warned :1; - unsigned int probing :1; /* codec probing phase */ - unsigned int snoop:1; - unsigned int align_buffer_size:1; - - /* for debugging */ - unsigned int last_cmd[AZX_MAX_CODECS]; - - /* for pending irqs */ - struct work_struct irq_pending_work; - - /* reboot notifier (for mysterious hangup problem at power-down) */ - struct notifier_block reboot_notifier; -}; - -/* driver types */ -enum { - AZX_DRIVER_ICH, - AZX_DRIVER_PCH, - AZX_DRIVER_SCH, - AZX_DRIVER_ATI, - AZX_DRIVER_ATIHDMI, - AZX_DRIVER_ATIHDMI_NS, - AZX_DRIVER_VIA, - AZX_DRIVER_SIS, - AZX_DRIVER_ULI, - AZX_DRIVER_NVIDIA, - AZX_DRIVER_TERA, - AZX_DRIVER_CTX, - AZX_DRIVER_GENERIC, - AZX_NUM_DRIVERS, /* keep this as last entry */ -}; - -/* driver quirks (capabilities) */ -/* bits 0-7 are used for indicating driver type */ -#define AZX_DCAPS_NO_TCSEL (1 << 8) /* No Intel TCSEL bit */ -#define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ -#define AZX_DCAPS_ATI_SNOOP (1 << 10) /* ATI snoop enable */ -#define AZX_DCAPS_NVIDIA_SNOOP (1 << 11) /* Nvidia snoop enable */ -#define AZX_DCAPS_SCH_SNOOP (1 << 12) /* SCH/PCH snoop enable */ -#define AZX_DCAPS_RIRB_DELAY (1 << 13) /* Long delay in read loop */ -#define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14) /* Put a delay before read */ -#define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ -#define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ -#define AZX_DCAPS_POSFIX_VIA (1 << 17) /* Use VIACOMBO as default */ -#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */ -#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */ -#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ -#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ -#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ - -/* quirks for ATI SB / AMD Hudson */ -#define AZX_DCAPS_PRESET_ATI_SB \ - (AZX_DCAPS_ATI_SNOOP | AZX_DCAPS_NO_TCSEL | \ - AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB) - -/* quirks for ATI/AMD HDMI */ -#define AZX_DCAPS_PRESET_ATI_HDMI \ - (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB) - -/* quirks for Nvidia */ -#define AZX_DCAPS_PRESET_NVIDIA \ - (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\ - AZX_DCAPS_ALIGN_BUFSIZE) - -static char *driver_short_names[] __devinitdata = { - [AZX_DRIVER_ICH] = "HDA Intel", - [AZX_DRIVER_PCH] = "HDA Intel PCH", - [AZX_DRIVER_SCH] = "HDA Intel MID", - [AZX_DRIVER_ATI] = "HDA ATI SB", - [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", - [AZX_DRIVER_ATIHDMI_NS] = "HDA ATI HDMI", - [AZX_DRIVER_VIA] = "HDA VIA VT82xx", - [AZX_DRIVER_SIS] = "HDA SIS966", - [AZX_DRIVER_ULI] = "HDA ULI M5461", - [AZX_DRIVER_NVIDIA] = "HDA NVidia", - [AZX_DRIVER_TERA] = "HDA Teradici", - [AZX_DRIVER_CTX] = "HDA Creative", - [AZX_DRIVER_GENERIC] = "HD-Audio Generic", -}; - -/* - * macros for easy use - */ -#define azx_writel(chip,reg,value) \ - writel(value, (chip)->remap_addr + ICH6_REG_##reg) -#define azx_readl(chip,reg) \ - readl((chip)->remap_addr + ICH6_REG_##reg) -#define azx_writew(chip,reg,value) \ - writew(value, (chip)->remap_addr + ICH6_REG_##reg) -#define azx_readw(chip,reg) \ - readw((chip)->remap_addr + ICH6_REG_##reg) -#define azx_writeb(chip,reg,value) \ - writeb(value, (chip)->remap_addr + ICH6_REG_##reg) -#define azx_readb(chip,reg) \ - readb((chip)->remap_addr + ICH6_REG_##reg) - -#define azx_sd_writel(dev,reg,value) \ - writel(value, (dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_readl(dev,reg) \ - readl((dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_writew(dev,reg,value) \ - writew(value, (dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_readw(dev,reg) \ - readw((dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_writeb(dev,reg,value) \ - writeb(value, (dev)->sd_addr + ICH6_REG_##reg) -#define azx_sd_readb(dev,reg) \ - readb((dev)->sd_addr + ICH6_REG_##reg) - -/* for pcm support */ -#define get_azx_dev(substream) (substream->runtime->private_data) - -#ifdef CONFIG_X86 -static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on) -{ - if (azx_snoop(chip)) - return; - if (addr && size) { - int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; - if (on) - set_memory_wc((unsigned long)addr, pages); - else - set_memory_wb((unsigned long)addr, pages); - } -} - -static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, - bool on) -{ - __mark_pages_wc(chip, buf->area, buf->bytes, on); -} -static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, - struct snd_pcm_runtime *runtime, bool on) -{ - if (azx_dev->wc_marked != on) { - __mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on); - azx_dev->wc_marked = on; - } -} -#else -/* NOP for other archs */ -static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, - bool on) -{ -} -static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, - struct snd_pcm_runtime *runtime, bool on) -{ -} -#endif - -static int azx_acquire_irq(struct azx *chip, int do_disconnect); -static int azx_send_cmd(struct hda_bus *bus, unsigned int val); -/* - * Interface for HD codec - */ - -/* - * CORB / RIRB interface - */ -static int azx_alloc_cmd_io(struct azx *chip) -{ - int err; - - /* single page (at least 4096 bytes) must suffice for both ringbuffes */ - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - PAGE_SIZE, &chip->rb); - if (err < 0) { - snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n"); - return err; - } - mark_pages_wc(chip, &chip->rb, true); - return 0; -} - -static void azx_init_cmd_io(struct azx *chip) -{ - spin_lock_irq(&chip->reg_lock); - /* CORB set up */ - chip->corb.addr = chip->rb.addr; - chip->corb.buf = (u32 *)chip->rb.area; - azx_writel(chip, CORBLBASE, (u32)chip->corb.addr); - azx_writel(chip, CORBUBASE, upper_32_bits(chip->corb.addr)); - - /* set the corb size to 256 entries (ULI requires explicitly) */ - azx_writeb(chip, CORBSIZE, 0x02); - /* set the corb write pointer to 0 */ - azx_writew(chip, CORBWP, 0); - /* reset the corb hw read pointer */ - azx_writew(chip, CORBRP, ICH6_CORBRP_RST); - /* enable corb dma */ - azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN); - - /* RIRB set up */ - chip->rirb.addr = chip->rb.addr + 2048; - chip->rirb.buf = (u32 *)(chip->rb.area + 2048); - chip->rirb.wp = chip->rirb.rp = 0; - memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds)); - azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); - azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); - - /* set the rirb size to 256 entries (ULI requires explicitly) */ - azx_writeb(chip, RIRBSIZE, 0x02); - /* reset the rirb hw write pointer */ - azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); - /* set N=1, get RIRB response interrupt for new entry */ - if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) - azx_writew(chip, RINTCNT, 0xc0); - else - azx_writew(chip, RINTCNT, 1); - /* enable rirb dma and response irq */ - azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); - spin_unlock_irq(&chip->reg_lock); -} - -static void azx_free_cmd_io(struct azx *chip) -{ - spin_lock_irq(&chip->reg_lock); - /* disable ringbuffer DMAs */ - azx_writeb(chip, RIRBCTL, 0); - azx_writeb(chip, CORBCTL, 0); - spin_unlock_irq(&chip->reg_lock); -} - -static unsigned int azx_command_addr(u32 cmd) -{ - unsigned int addr = cmd >> 28; - - if (addr >= AZX_MAX_CODECS) { - snd_BUG(); - addr = 0; - } - - return addr; -} - -static unsigned int azx_response_addr(u32 res) -{ - unsigned int addr = res & 0xf; - - if (addr >= AZX_MAX_CODECS) { - snd_BUG(); - addr = 0; - } - - return addr; -} - -/* send a command */ -static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) -{ - struct azx *chip = bus->private_data; - unsigned int addr = azx_command_addr(val); - unsigned int wp; - - spin_lock_irq(&chip->reg_lock); - - /* add command to corb */ - wp = azx_readb(chip, CORBWP); - wp++; - wp %= ICH6_MAX_CORB_ENTRIES; - - chip->rirb.cmds[addr]++; - chip->corb.buf[wp] = cpu_to_le32(val); - azx_writel(chip, CORBWP, wp); - - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - -#define ICH6_RIRB_EX_UNSOL_EV (1<<4) - -/* retrieve RIRB entry - called from interrupt handler */ -static void azx_update_rirb(struct azx *chip) -{ - unsigned int rp, wp; - unsigned int addr; - u32 res, res_ex; - - wp = azx_readb(chip, RIRBWP); - if (wp == chip->rirb.wp) - return; - chip->rirb.wp = wp; - - while (chip->rirb.rp != wp) { - chip->rirb.rp++; - chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; - - rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ - res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); - res = le32_to_cpu(chip->rirb.buf[rp]); - addr = azx_response_addr(res_ex); - if (res_ex & ICH6_RIRB_EX_UNSOL_EV) - snd_hda_queue_unsol_event(chip->bus, res, res_ex); - else if (chip->rirb.cmds[addr]) { - chip->rirb.res[addr] = res; - smp_wmb(); - chip->rirb.cmds[addr]--; - } else - snd_printk(KERN_ERR SFX "spurious response %#x:%#x, " - "last cmd=%#08x\n", - res, res_ex, - chip->last_cmd[addr]); - } -} - -/* receive a response */ -static unsigned int azx_rirb_get_response(struct hda_bus *bus, - unsigned int addr) -{ - struct azx *chip = bus->private_data; - unsigned long timeout; - unsigned long loopcounter; - int do_poll = 0; - - again: - timeout = jiffies + msecs_to_jiffies(1000); - - for (loopcounter = 0;; loopcounter++) { - if (chip->polling_mode || do_poll) { - spin_lock_irq(&chip->reg_lock); - azx_update_rirb(chip); - spin_unlock_irq(&chip->reg_lock); - } - if (!chip->rirb.cmds[addr]) { - smp_rmb(); - bus->rirb_error = 0; - - if (!do_poll) - chip->poll_count = 0; - return chip->rirb.res[addr]; /* the last value */ - } - if (time_after(jiffies, timeout)) - break; - if (bus->needs_damn_long_delay || loopcounter > 3000) - msleep(2); /* temporary workaround */ - else { - udelay(10); - cond_resched(); - } - } - - if (!chip->polling_mode && chip->poll_count < 2) { - snd_printdd(SFX "azx_get_response timeout, " - "polling the codec once: last cmd=0x%08x\n", - chip->last_cmd[addr]); - do_poll = 1; - chip->poll_count++; - goto again; - } - - - if (!chip->polling_mode) { - snd_printk(KERN_WARNING SFX "azx_get_response timeout, " - "switching to polling mode: last cmd=0x%08x\n", - chip->last_cmd[addr]); - chip->polling_mode = 1; - goto again; - } - - if (chip->msi) { - snd_printk(KERN_WARNING SFX "No response from codec, " - "disabling MSI: last cmd=0x%08x\n", - chip->last_cmd[addr]); - free_irq(chip->irq, chip); - chip->irq = -1; - pci_disable_msi(chip->pci); - chip->msi = 0; - if (azx_acquire_irq(chip, 1) < 0) { - bus->rirb_error = 1; - return -1; - } - goto again; - } - - if (chip->probing) { - /* If this critical timeout happens during the codec probing - * phase, this is likely an access to a non-existing codec - * slot. Better to return an error and reset the system. - */ - return -1; - } - - /* a fatal communication error; need either to reset or to fallback - * to the single_cmd mode - */ - bus->rirb_error = 1; - if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { - bus->response_reset = 1; - return -1; /* give a chance to retry */ - } - - snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " - "switching to single_cmd mode: last cmd=0x%08x\n", - chip->last_cmd[addr]); - chip->single_cmd = 1; - bus->response_reset = 0; - /* release CORB/RIRB */ - azx_free_cmd_io(chip); - /* disable unsolicited responses */ - azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL); - return -1; -} - -/* - * Use the single immediate command instead of CORB/RIRB for simplicity - * - * Note: according to Intel, this is not preferred use. The command was - * intended for the BIOS only, and may get confused with unsolicited - * responses. So, we shouldn't use it for normal operation from the - * driver. - * I left the codes, however, for debugging/testing purposes. - */ - -/* receive a response */ -static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) -{ - int timeout = 50; - - while (timeout--) { - /* check IRV busy bit */ - if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { - /* reuse rirb.res as the response return value */ - chip->rirb.res[addr] = azx_readl(chip, IR); - return 0; - } - udelay(1); - } - if (printk_ratelimit()) - snd_printd(SFX "get_response timeout: IRS=0x%x\n", - azx_readw(chip, IRS)); - chip->rirb.res[addr] = -1; - return -EIO; -} - -/* send a command */ -static int azx_single_send_cmd(struct hda_bus *bus, u32 val) -{ - struct azx *chip = bus->private_data; - unsigned int addr = azx_command_addr(val); - int timeout = 50; - - bus->rirb_error = 0; - while (timeout--) { - /* check ICB busy bit */ - if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { - /* Clear IRV valid bit */ - azx_writew(chip, IRS, azx_readw(chip, IRS) | - ICH6_IRS_VALID); - azx_writel(chip, IC, val); - azx_writew(chip, IRS, azx_readw(chip, IRS) | - ICH6_IRS_BUSY); - return azx_single_wait_for_response(chip, addr); - } - udelay(1); - } - if (printk_ratelimit()) - snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", - azx_readw(chip, IRS), val); - return -EIO; -} - -/* receive a response */ -static unsigned int azx_single_get_response(struct hda_bus *bus, - unsigned int addr) -{ - struct azx *chip = bus->private_data; - return chip->rirb.res[addr]; -} - -/* - * The below are the main callbacks from hda_codec. - * - * They are just the skeleton to call sub-callbacks according to the - * current setting of chip->single_cmd. - */ - -/* send a command */ -static int azx_send_cmd(struct hda_bus *bus, unsigned int val) -{ - struct azx *chip = bus->private_data; - - chip->last_cmd[azx_command_addr(val)] = val; - if (chip->single_cmd) - return azx_single_send_cmd(bus, val); - else - return azx_corb_send_cmd(bus, val); -} - -/* get a response */ -static unsigned int azx_get_response(struct hda_bus *bus, - unsigned int addr) -{ - struct azx *chip = bus->private_data; - if (chip->single_cmd) - return azx_single_get_response(bus, addr); - else - return azx_rirb_get_response(bus, addr); -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static void azx_power_notify(struct hda_bus *bus); -#endif - -/* reset codec link */ -static int azx_reset(struct azx *chip, int full_reset) -{ - int count; - - if (!full_reset) - goto __skip; - - /* clear STATESTS */ - azx_writeb(chip, STATESTS, STATESTS_INT_MASK); - - /* reset controller */ - azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET); - - count = 50; - while (azx_readb(chip, GCTL) && --count) - msleep(1); - - /* delay for >= 100us for codec PLL to settle per spec - * Rev 0.9 section 5.5.1 - */ - msleep(1); - - /* Bring controller out of reset */ - azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); - - count = 50; - while (!azx_readb(chip, GCTL) && --count) - msleep(1); - - /* Brent Chartrand said to wait >= 540us for codecs to initialize */ - msleep(1); - - __skip: - /* check to see if controller is ready */ - if (!azx_readb(chip, GCTL)) { - snd_printd(SFX "azx_reset: controller not ready!\n"); - return -EBUSY; - } - - /* Accept unsolicited responses */ - if (!chip->single_cmd) - azx_writel(chip, GCTL, azx_readl(chip, GCTL) | - ICH6_GCTL_UNSOL); - - /* detect codecs */ - if (!chip->codec_mask) { - chip->codec_mask = azx_readw(chip, STATESTS); - snd_printdd(SFX "codec_mask = 0x%x\n", chip->codec_mask); - } - - return 0; -} - - -/* - * Lowlevel interface - */ - -/* enable interrupts */ -static void azx_int_enable(struct azx *chip) -{ - /* enable controller CIE and GIE */ - azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | - ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN); -} - -/* disable interrupts */ -static void azx_int_disable(struct azx *chip) -{ - int i; - - /* disable interrupts in stream descriptor */ - for (i = 0; i < chip->num_streams; i++) { - struct azx_dev *azx_dev = &chip->azx_dev[i]; - azx_sd_writeb(azx_dev, SD_CTL, - azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK); - } - - /* disable SIE for all streams */ - azx_writeb(chip, INTCTL, 0); - - /* disable controller CIE and GIE */ - azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & - ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN)); -} - -/* clear interrupts */ -static void azx_int_clear(struct azx *chip) -{ - int i; - - /* clear stream status */ - for (i = 0; i < chip->num_streams; i++) { - struct azx_dev *azx_dev = &chip->azx_dev[i]; - azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); - } - - /* clear STATESTS */ - azx_writeb(chip, STATESTS, STATESTS_INT_MASK); - - /* clear rirb status */ - azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); - - /* clear int status */ - azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM); -} - -/* start a stream */ -static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) -{ - /* - * Before stream start, initialize parameter - */ - azx_dev->insufficient = 1; - - /* enable SIE */ - azx_writel(chip, INTCTL, - azx_readl(chip, INTCTL) | (1 << azx_dev->index)); - /* set DMA start and interrupt mask */ - azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | - SD_CTL_DMA_START | SD_INT_MASK); -} - -/* stop DMA */ -static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) -{ - azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & - ~(SD_CTL_DMA_START | SD_INT_MASK)); - azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ -} - -/* stop a stream */ -static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) -{ - azx_stream_clear(chip, azx_dev); - /* disable SIE */ - azx_writel(chip, INTCTL, - azx_readl(chip, INTCTL) & ~(1 << azx_dev->index)); -} - - -/* - * reset and start the controller registers - */ -static void azx_init_chip(struct azx *chip, int full_reset) -{ - if (chip->initialized) - return; - - /* reset controller */ - azx_reset(chip, full_reset); - - /* initialize interrupts */ - azx_int_clear(chip); - azx_int_enable(chip); - - /* initialize the codec command I/O */ - if (!chip->single_cmd) - azx_init_cmd_io(chip); - - /* program the position buffer */ - azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); - azx_writel(chip, DPUBASE, upper_32_bits(chip->posbuf.addr)); - - chip->initialized = 1; -} - -/* - * initialize the PCI registers - */ -/* update bits in a PCI register byte */ -static void update_pci_byte(struct pci_dev *pci, unsigned int reg, - unsigned char mask, unsigned char val) -{ - unsigned char data; - - pci_read_config_byte(pci, reg, &data); - data &= ~mask; - data |= (val & mask); - pci_write_config_byte(pci, reg, data); -} - -static void azx_init_pci(struct azx *chip) -{ - /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) - * TCSEL == Traffic Class Select Register, which sets PCI express QOS - * Ensuring these bits are 0 clears playback static on some HD Audio - * codecs. - * The PCI register TCSEL is defined in the Intel manuals. - */ - if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) { - snd_printdd(SFX "Clearing TCSEL\n"); - update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); - } - - /* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio, - * we need to enable snoop. - */ - if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) { - snd_printdd(SFX "Setting ATI snoop: %d\n", azx_snoop(chip)); - update_pci_byte(chip->pci, - ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07, - azx_snoop(chip) ? ATI_SB450_HDAUDIO_ENABLE_SNOOP : 0); - } - - /* For NVIDIA HDA, enable snoop */ - if (chip->driver_caps & AZX_DCAPS_NVIDIA_SNOOP) { - snd_printdd(SFX "Setting Nvidia snoop: %d\n", azx_snoop(chip)); - update_pci_byte(chip->pci, - NVIDIA_HDA_TRANSREG_ADDR, - 0x0f, NVIDIA_HDA_ENABLE_COHBITS); - update_pci_byte(chip->pci, - NVIDIA_HDA_ISTRM_COH, - 0x01, NVIDIA_HDA_ENABLE_COHBIT); - update_pci_byte(chip->pci, - NVIDIA_HDA_OSTRM_COH, - 0x01, NVIDIA_HDA_ENABLE_COHBIT); - } - - /* Enable SCH/PCH snoop if needed */ - if (chip->driver_caps & AZX_DCAPS_SCH_SNOOP) { - unsigned short snoop; - pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); - if ((!azx_snoop(chip) && !(snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)) || - (azx_snoop(chip) && (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP))) { - snoop &= ~INTEL_SCH_HDA_DEVC_NOSNOOP; - if (!azx_snoop(chip)) - snoop |= INTEL_SCH_HDA_DEVC_NOSNOOP; - pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, snoop); - pci_read_config_word(chip->pci, - INTEL_SCH_HDA_DEVC, &snoop); - } - snd_printdd(SFX "SCH snoop: %s\n", - (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) - ? "Disabled" : "Enabled"); - } -} - - -static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev); - -/* - * interrupt handler - */ -static irqreturn_t azx_interrupt(int irq, void *dev_id) -{ - struct azx *chip = dev_id; - struct azx_dev *azx_dev; - u32 status; - u8 sd_status; - int i, ok; - - spin_lock(&chip->reg_lock); - - status = azx_readl(chip, INTSTS); - if (status == 0) { - spin_unlock(&chip->reg_lock); - return IRQ_NONE; - } - - for (i = 0; i < chip->num_streams; i++) { - azx_dev = &chip->azx_dev[i]; - if (status & azx_dev->sd_int_sta_mask) { - sd_status = azx_sd_readb(azx_dev, SD_STS); - azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); - if (!azx_dev->substream || !azx_dev->running || - !(sd_status & SD_INT_COMPLETE)) - continue; - /* check whether this IRQ is really acceptable */ - 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 (ok == 0 && chip->bus && chip->bus->workq) { - /* bogus IRQ, process it later */ - azx_dev->irq_pending = 1; - queue_work(chip->bus->workq, - &chip->irq_pending_work); - } - } - } - - /* clear rirb int */ - status = azx_readb(chip, RIRBSTS); - if (status & RIRB_INT_MASK) { - if (status & RIRB_INT_RESPONSE) { - if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) - udelay(80); - azx_update_rirb(chip); - } - azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); - } - -#if 0 - /* clear state status int */ - if (azx_readb(chip, STATESTS) & 0x04) - azx_writeb(chip, STATESTS, 0x04); -#endif - spin_unlock(&chip->reg_lock); - - return IRQ_HANDLED; -} - - -/* - * set up a BDL entry - */ -static int setup_bdle(struct snd_pcm_substream *substream, - struct azx_dev *azx_dev, u32 **bdlp, - int ofs, int size, int with_ioc) -{ - u32 *bdl = *bdlp; - - while (size > 0) { - dma_addr_t addr; - int chunk; - - if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) - return -EINVAL; - - addr = snd_pcm_sgbuf_get_addr(substream, ofs); - /* program the address field of the BDL entry */ - bdl[0] = cpu_to_le32((u32)addr); - bdl[1] = cpu_to_le32(upper_32_bits(addr)); - /* program the size field of the BDL entry */ - chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size); - bdl[2] = cpu_to_le32(chunk); - /* program the IOC to enable interrupt - * only when the whole fragment is processed - */ - size -= chunk; - bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01); - bdl += 4; - azx_dev->frags++; - ofs += chunk; - } - *bdlp = bdl; - return ofs; -} - -/* - * set up BDL entries - */ -static int azx_setup_periods(struct azx *chip, - struct snd_pcm_substream *substream, - struct azx_dev *azx_dev) -{ - u32 *bdl; - int i, ofs, periods, period_bytes; - int pos_adj; - - /* reset BDL address */ - azx_sd_writel(azx_dev, SD_BDLPL, 0); - azx_sd_writel(azx_dev, SD_BDLPU, 0); - - period_bytes = azx_dev->period_bytes; - periods = azx_dev->bufsize / period_bytes; - - /* program the initial BDL entries */ - bdl = (u32 *)azx_dev->bdl.area; - ofs = 0; - azx_dev->frags = 0; - pos_adj = bdl_pos_adj[chip->dev_index]; - if (pos_adj > 0) { - struct snd_pcm_runtime *runtime = substream->runtime; - int pos_align = pos_adj; - pos_adj = (pos_adj * runtime->rate + 47999) / 48000; - if (!pos_adj) - pos_adj = pos_align; - else - pos_adj = ((pos_adj + pos_align - 1) / pos_align) * - pos_align; - pos_adj = frames_to_bytes(runtime, pos_adj); - if (pos_adj >= period_bytes) { - snd_printk(KERN_WARNING SFX "Too big adjustment %d\n", - bdl_pos_adj[chip->dev_index]); - pos_adj = 0; - } else { - ofs = setup_bdle(substream, azx_dev, - &bdl, ofs, pos_adj, - !substream->runtime->no_period_wakeup); - if (ofs < 0) - goto error; - } - } else - pos_adj = 0; - for (i = 0; i < periods; i++) { - if (i == periods - 1 && pos_adj) - ofs = setup_bdle(substream, azx_dev, &bdl, ofs, - period_bytes - pos_adj, 0); - else - ofs = setup_bdle(substream, azx_dev, &bdl, ofs, - period_bytes, - !substream->runtime->no_period_wakeup); - if (ofs < 0) - goto error; - } - return 0; - - error: - snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n", - azx_dev->bufsize, period_bytes); - return -EINVAL; -} - -/* reset stream */ -static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) -{ - unsigned char val; - int timeout; - - azx_stream_clear(chip, azx_dev); - - azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | - SD_CTL_STREAM_RESET); - udelay(3); - timeout = 300; - while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && - --timeout) - ; - val &= ~SD_CTL_STREAM_RESET; - azx_sd_writeb(azx_dev, SD_CTL, val); - udelay(3); - - timeout = 300; - /* waiting for hardware to report that the stream is out of reset */ - 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; -} - -/* - * set up the SD for streaming - */ -static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) -{ - unsigned int val; - /* make sure the run bit is zero for SD */ - azx_stream_clear(chip, azx_dev); - /* program the stream_tag */ - val = azx_sd_readl(azx_dev, SD_CTL); - val = (val & ~SD_CTL_STREAM_TAG_MASK) | - (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); - if (!azx_snoop(chip)) - val |= SD_CTL_TRAFFIC_PRIO; - azx_sd_writel(azx_dev, SD_CTL, val); - - /* program the length of samples in cyclic buffer */ - azx_sd_writel(azx_dev, SD_CBL, azx_dev->bufsize); - - /* program the stream format */ - /* this value needs to be the same as the one programmed */ - azx_sd_writew(azx_dev, SD_FORMAT, azx_dev->format_val); - - /* program the stream LVI (last valid index) of the BDL */ - azx_sd_writew(azx_dev, SD_LVI, azx_dev->frags - 1); - - /* program the BDL address */ - /* lower BDL address */ - azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); - /* upper BDL address */ - azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); - - /* enable the position buffer */ - if (chip->position_fix[0] != POS_FIX_LPIB || - chip->position_fix[1] != POS_FIX_LPIB) { - if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) - azx_writel(chip, DPLBASE, - (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); - } - - /* set the interrupt enable bits in the descriptor control register */ - azx_sd_writel(azx_dev, SD_CTL, - azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); - - return 0; -} - -/* - * Probe the given codec address - */ -static int probe_codec(struct azx *chip, int addr) -{ - unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | - (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; - unsigned int res; - - mutex_lock(&chip->bus->cmd_mutex); - chip->probing = 1; - azx_send_cmd(chip->bus, cmd); - res = azx_get_response(chip->bus, addr); - chip->probing = 0; - mutex_unlock(&chip->bus->cmd_mutex); - if (res == -1) - return -EIO; - snd_printdd(SFX "codec #%d probed OK\n", addr); - return 0; -} - -static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, - struct hda_pcm *cpcm); -static void azx_stop_chip(struct azx *chip); - -static void azx_bus_reset(struct hda_bus *bus) -{ - struct azx *chip = bus->private_data; - - bus->in_reset = 1; - azx_stop_chip(chip); - azx_init_chip(chip, 1); -#ifdef CONFIG_PM - if (chip->initialized) { - struct azx_pcm *p; - list_for_each_entry(p, &chip->pcm_list, list) - snd_pcm_suspend_all(p->pcm); - snd_hda_suspend(chip->bus); - snd_hda_resume(chip->bus); - } -#endif - bus->in_reset = 0; -} - -/* - * Codec initialization - */ - -/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ -static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { - [AZX_DRIVER_NVIDIA] = 8, - [AZX_DRIVER_TERA] = 1, -}; - -static int __devinit azx_codec_create(struct azx *chip, const char *model) -{ - struct hda_bus_template bus_temp; - int c, codecs, err; - int max_slots; - - memset(&bus_temp, 0, sizeof(bus_temp)); - bus_temp.private_data = chip; - bus_temp.modelname = model; - bus_temp.pci = chip->pci; - bus_temp.ops.command = azx_send_cmd; - bus_temp.ops.get_response = azx_get_response; - bus_temp.ops.attach_pcm = azx_attach_pcm_stream; - bus_temp.ops.bus_reset = azx_bus_reset; -#ifdef CONFIG_SND_HDA_POWER_SAVE - bus_temp.power_save = &power_save; - bus_temp.ops.pm_notify = azx_power_notify; -#endif - - err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); - if (err < 0) - return err; - - if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) { - snd_printd(SFX "Enable delay in RIRB handling\n"); - chip->bus->needs_damn_long_delay = 1; - } - - codecs = 0; - max_slots = azx_max_codecs[chip->driver_type]; - if (!max_slots) - max_slots = AZX_DEFAULT_CODECS; - - /* First try to probe all given codec slots */ - for (c = 0; c < max_slots; c++) { - if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { - if (probe_codec(chip, c) < 0) { - /* Some BIOSen give you wrong codec addresses - * that don't exist - */ - snd_printk(KERN_WARNING SFX - "Codec #%d probe error; " - "disabling it...\n", c); - chip->codec_mask &= ~(1 << c); - /* More badly, accessing to a non-existing - * codec often screws up the controller chip, - * and disturbs the further communications. - * Thus if an error occurs during probing, - * better to reset the controller chip to - * get back to the sanity state. - */ - azx_stop_chip(chip); - azx_init_chip(chip, 1); - } - } - } - - /* AMD chipsets often cause the communication stalls upon certain - * sequence like the pin-detection. It seems that forcing the synced - * access works around the stall. Grrr... - */ - if (chip->driver_caps & AZX_DCAPS_SYNC_WRITE) { - snd_printd(SFX "Enable sync_write for stable communication\n"); - chip->bus->sync_write = 1; - chip->bus->allow_bus_reset = 1; - } - - /* Then create codec instances */ - for (c = 0; c < max_slots; c++) { - if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { - struct hda_codec *codec; - err = snd_hda_codec_new(chip->bus, c, &codec); - if (err < 0) - continue; - codec->beep_mode = chip->beep_mode; - codecs++; - } - } - if (!codecs) { - snd_printk(KERN_ERR SFX "no codecs initialized\n"); - return -ENXIO; - } - return 0; -} - -/* configure each codec instance */ -static int __devinit azx_codec_configure(struct azx *chip) -{ - struct hda_codec *codec; - list_for_each_entry(codec, &chip->bus->codec_list, list) { - snd_hda_codec_configure(codec); - } - return 0; -} - - -/* - * PCM support - */ - -/* assign a stream for the PCM */ -static inline struct azx_dev * -azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) -{ - int dev, i, nums; - struct azx_dev *res = NULL; - /* make a non-zero unique key for the substream */ - int key = (substream->pcm->device << 16) | (substream->number << 2) | - (substream->stream + 1); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dev = chip->playback_index_offset; - nums = chip->playback_streams; - } else { - dev = chip->capture_index_offset; - nums = chip->capture_streams; - } - for (i = 0; i < nums; i++, dev++) - if (!chip->azx_dev[dev].opened) { - res = &chip->azx_dev[dev]; - if (res->assigned_key == key) - break; - } - if (res) { - res->opened = 1; - res->assigned_key = key; - } - return res; -} - -/* release the assigned stream */ -static inline void azx_release_device(struct azx_dev *azx_dev) -{ - azx_dev->opened = 0; -} - -static struct snd_pcm_hardware azx_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - /* No full-resume yet implemented */ - /* SNDRV_PCM_INFO_RESUME |*/ - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = AZX_MAX_BUF_SIZE, - .period_bytes_min = 128, - .period_bytes_max = AZX_MAX_BUF_SIZE / 2, - .periods_min = 2, - .periods_max = AZX_MAX_FRAG, - .fifo_size = 0, -}; - -static int azx_pcm_open(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - int err; - int buff_step; - - mutex_lock(&chip->open_mutex); - azx_dev = azx_assign_device(chip, substream); - if (azx_dev == NULL) { - mutex_unlock(&chip->open_mutex); - return -EBUSY; - } - runtime->hw = azx_pcm_hw; - runtime->hw.channels_min = hinfo->channels_min; - runtime->hw.channels_max = hinfo->channels_max; - runtime->hw.formats = hinfo->formats; - runtime->hw.rates = hinfo->rates; - snd_pcm_limit_hw_rates(runtime); - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (chip->align_buffer_size) - /* constrain buffer sizes to be multiple of 128 - bytes. This is more efficient in terms of memory - access but isn't required by the HDA spec and - prevents users from specifying exact period/buffer - sizes. For example for 44.1kHz, a period size set - to 20ms will be rounded to 19.59ms. */ - buff_step = 128; - else - /* Don't enforce steps on buffer sizes, still need to - be multiple of 4 bytes (HDA spec). Tested on Intel - HDA controllers, may not work on all devices where - option needs to be disabled */ - buff_step = 4; - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - buff_step); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - buff_step); - snd_hda_power_up(apcm->codec); - err = hinfo->ops.open(hinfo, apcm->codec, substream); - if (err < 0) { - azx_release_device(azx_dev); - snd_hda_power_down(apcm->codec); - mutex_unlock(&chip->open_mutex); - return err; - } - snd_pcm_limit_hw_rates(runtime); - /* sanity check */ - if (snd_BUG_ON(!runtime->hw.channels_min) || - snd_BUG_ON(!runtime->hw.channels_max) || - snd_BUG_ON(!runtime->hw.formats) || - snd_BUG_ON(!runtime->hw.rates)) { - azx_release_device(azx_dev); - hinfo->ops.close(hinfo, apcm->codec, substream); - snd_hda_power_down(apcm->codec); - mutex_unlock(&chip->open_mutex); - return -EINVAL; - } - spin_lock_irqsave(&chip->reg_lock, flags); - azx_dev->substream = substream; - azx_dev->running = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - - runtime->private_data = azx_dev; - snd_pcm_set_sync(substream); - mutex_unlock(&chip->open_mutex); - return 0; -} - -static int azx_pcm_close(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev = get_azx_dev(substream); - unsigned long flags; - - mutex_lock(&chip->open_mutex); - spin_lock_irqsave(&chip->reg_lock, flags); - azx_dev->substream = NULL; - azx_dev->running = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - azx_release_device(azx_dev); - hinfo->ops.close(hinfo, apcm->codec, substream); - snd_hda_power_down(apcm->codec); - mutex_unlock(&chip->open_mutex); - return 0; -} - -static int azx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - struct snd_pcm_runtime *runtime = substream->runtime; - struct azx_dev *azx_dev = get_azx_dev(substream); - int ret; - - mark_runtime_wc(chip, azx_dev, runtime, false); - azx_dev->bufsize = 0; - azx_dev->period_bytes = 0; - azx_dev->format_val = 0; - ret = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (ret < 0) - return ret; - mark_runtime_wc(chip, azx_dev, runtime, true); - return ret; -} - -static int azx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx_dev *azx_dev = get_azx_dev(substream); - struct azx *chip = apcm->chip; - struct snd_pcm_runtime *runtime = substream->runtime; - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - - /* reset BDL address */ - azx_sd_writel(azx_dev, SD_BDLPL, 0); - azx_sd_writel(azx_dev, SD_BDLPU, 0); - azx_sd_writel(azx_dev, SD_CTL, 0); - azx_dev->bufsize = 0; - azx_dev->period_bytes = 0; - azx_dev->format_val = 0; - - snd_hda_codec_cleanup(apcm->codec, hinfo, substream); - - mark_runtime_wc(chip, azx_dev, runtime, false); - return snd_pcm_lib_free_pages(substream); -} - -static int azx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev = get_azx_dev(substream); - struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int bufsize, period_bytes, format_val, stream_tag; - int err; - struct hda_spdif_out *spdif = - snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); - unsigned short ctls = spdif ? spdif->ctls : 0; - - azx_stream_reset(chip, azx_dev); - format_val = snd_hda_calc_stream_format(runtime->rate, - runtime->channels, - runtime->format, - hinfo->maxbps, - ctls); - if (!format_val) { - snd_printk(KERN_ERR SFX - "invalid format_val, rate=%d, ch=%d, format=%d\n", - runtime->rate, runtime->channels, runtime->format); - return -EINVAL; - } - - bufsize = snd_pcm_lib_buffer_bytes(substream); - period_bytes = snd_pcm_lib_period_bytes(substream); - - snd_printdd(SFX "azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", - bufsize, format_val); - - if (bufsize != azx_dev->bufsize || - period_bytes != azx_dev->period_bytes || - format_val != azx_dev->format_val) { - azx_dev->bufsize = bufsize; - azx_dev->period_bytes = period_bytes; - azx_dev->format_val = format_val; - err = azx_setup_periods(chip, substream, azx_dev); - if (err < 0) - return err; - } - - /* wallclk has 24Mhz clock source */ - azx_dev->period_wallclk = (((runtime->period_size * 24000) / - runtime->rate) * 1000); - 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; - else - azx_dev->fifo_size = 0; - - stream_tag = azx_dev->stream_tag; - /* CA-IBG chips need the playback stream starting from 1 */ - if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && - stream_tag > chip->capture_streams) - stream_tag -= chip->capture_streams; - return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, - azx_dev->format_val, substream); -} - -static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev; - struct snd_pcm_substream *s; - 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: - start = 1; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - start = 0; - break; - default: - return -EINVAL; - } - - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - sbits |= 1 << azx_dev->index; - nsync++; - snd_pcm_trigger_done(s, substream); - } - - spin_lock(&chip->reg_lock); - if (nsync > 1) { - /* first, set SYNC bits of corresponding streams */ - if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) - azx_writel(chip, OLD_SSYNC, - azx_readl(chip, OLD_SSYNC) | sbits); - else - azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits); - } - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - if (start) { - azx_dev->start_wallclk = azx_readl(chip, WALLCLK); - if (!rstart) - azx_dev->start_wallclk -= - azx_dev->period_wallclk; - azx_stream_start(chip, azx_dev); - } else { - azx_stream_stop(chip, azx_dev); - } - azx_dev->running = start; - } - spin_unlock(&chip->reg_lock); - if (start) { - if (nsync == 1) - return 0; - /* wait until all FIFOs get ready */ - for (timeout = 5000; timeout; timeout--) { - nwait = 0; - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - if (!(azx_sd_readb(azx_dev, SD_STS) & - SD_STS_FIFO_READY)) - nwait++; - } - if (!nwait) - break; - cpu_relax(); - } - } else { - /* wait until all RUN bits are cleared */ - for (timeout = 5000; timeout; timeout--) { - nwait = 0; - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - azx_dev = get_azx_dev(s); - if (azx_sd_readb(azx_dev, SD_CTL) & - SD_CTL_DMA_START) - nwait++; - } - if (!nwait) - break; - cpu_relax(); - } - } - if (nsync > 1) { - spin_lock(&chip->reg_lock); - /* reset SYNC bits */ - if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) - azx_writel(chip, OLD_SSYNC, - azx_readl(chip, OLD_SSYNC) & ~sbits); - else - azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); - spin_unlock(&chip->reg_lock); - } - return 0; -} - -/* get the current DMA position with correction on VIA chips */ -static unsigned int azx_via_get_position(struct azx *chip, - struct azx_dev *azx_dev) -{ - unsigned int link_pos, mini_pos, bound_pos; - unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos; - unsigned int fifo_size; - - link_pos = azx_sd_readl(azx_dev, SD_LPIB); - if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* Playback, no problem using link position */ - return link_pos; - } - - /* Capture */ - /* For new chipset, - * use mod to get the DMA position just like old chipset - */ - mod_dma_pos = le32_to_cpu(*azx_dev->posbuf); - mod_dma_pos %= azx_dev->period_bytes; - - /* azx_dev->fifo_size can't get FIFO size of in stream. - * Get from base address + offset. - */ - fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); - - if (azx_dev->insufficient) { - /* Link position never gather than FIFO size */ - if (link_pos <= fifo_size) - return 0; - - azx_dev->insufficient = 0; - } - - if (link_pos <= fifo_size) - mini_pos = azx_dev->bufsize + link_pos - fifo_size; - else - mini_pos = link_pos - fifo_size; - - /* Find nearest previous boudary */ - mod_mini_pos = mini_pos % azx_dev->period_bytes; - mod_link_pos = link_pos % azx_dev->period_bytes; - if (mod_link_pos >= fifo_size) - bound_pos = link_pos - mod_link_pos; - else if (mod_dma_pos >= mod_mini_pos) - bound_pos = mini_pos - mod_mini_pos; - else { - bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes; - if (bound_pos >= azx_dev->bufsize) - bound_pos = 0; - } - - /* Calculate real DMA position we want */ - return bound_pos + mod_dma_pos; -} - -static unsigned int azx_get_position(struct azx *chip, - struct azx_dev *azx_dev, - bool with_check) -{ - unsigned int pos; - int stream = azx_dev->substream->stream; - - switch (chip->position_fix[stream]) { - case POS_FIX_LPIB: - /* read LPIB */ - pos = azx_sd_readl(azx_dev, SD_LPIB); - break; - case POS_FIX_VIACOMBO: - pos = azx_via_get_position(chip, azx_dev); - break; - default: - /* use the position buffer */ - pos = le32_to_cpu(*azx_dev->posbuf); - if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) { - if (!pos || pos == (u32)-1) { - printk(KERN_WARNING - "hda-intel: Invalid position buffer, " - "using LPIB read method instead.\n"); - chip->position_fix[stream] = POS_FIX_LPIB; - pos = azx_sd_readl(azx_dev, SD_LPIB); - } else - chip->position_fix[stream] = POS_FIX_POSBUF; - } - break; - } - - if (pos >= azx_dev->bufsize) - pos = 0; - return pos; -} - -static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - struct azx_dev *azx_dev = get_azx_dev(substream); - return bytes_to_frames(substream->runtime, - azx_get_position(chip, azx_dev, false)); -} - -/* - * Check whether the current DMA position is acceptable for updating - * periods. Returns non-zero if it's OK. - * - * Many HD-audio controllers appear pretty inaccurate about - * the update-IRQ timing. The IRQ is issued before actually the - * data is processed. So, we need to process it afterwords in a - * workqueue. - */ -static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) -{ - u32 wallclk; - unsigned int pos; - int stream; - - wallclk = azx_readl(chip, WALLCLK) - azx_dev->start_wallclk; - if (wallclk < (azx_dev->period_wallclk * 2) / 3) - return -1; /* bogus (too early) interrupt */ - - stream = azx_dev->substream->stream; - pos = azx_get_position(chip, azx_dev, true); - - if (WARN_ONCE(!azx_dev->period_bytes, - "hda-intel: zero azx_dev->period_bytes")) - return -1; /* this shouldn't happen! */ - if (wallclk < (azx_dev->period_wallclk * 5) / 4 && - pos % azx_dev->period_bytes > azx_dev->period_bytes / 2) - /* NG - it's below the first next period boundary */ - return bdl_pos_adj[chip->dev_index] ? 0 : -1; - azx_dev->start_wallclk += wallclk; - return 1; /* OK, it's fine */ -} - -/* - * The work for pending PCM period updates. - */ -static void azx_irq_pending_work(struct work_struct *work) -{ - struct azx *chip = container_of(work, struct azx, irq_pending_work); - int i, pending, ok; - - if (!chip->irq_pending_warned) { - printk(KERN_WARNING - "hda-intel: IRQ timing workaround is activated " - "for card #%d. Suggest a bigger bdl_pos_adj.\n", - chip->card->number); - chip->irq_pending_warned = 1; - } - - for (;;) { - pending = 0; - spin_lock_irq(&chip->reg_lock); - for (i = 0; i < chip->num_streams; i++) { - struct azx_dev *azx_dev = &chip->azx_dev[i]; - if (!azx_dev->irq_pending || - !azx_dev->substream || - !azx_dev->running) - continue; - ok = azx_position_ok(chip, azx_dev); - if (ok > 0) { - azx_dev->irq_pending = 0; - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(azx_dev->substream); - spin_lock(&chip->reg_lock); - } else if (ok < 0) { - pending = 0; /* too early */ - } else - pending++; - } - spin_unlock_irq(&chip->reg_lock); - if (!pending) - return; - msleep(1); - } -} - -/* clear irq_pending flags and assure no on-going workq */ -static void azx_clear_irq_pending(struct azx *chip) -{ - int i; - - spin_lock_irq(&chip->reg_lock); - for (i = 0; i < chip->num_streams; i++) - chip->azx_dev[i].irq_pending = 0; - spin_unlock_irq(&chip->reg_lock); -} - -#ifdef CONFIG_X86 -static int azx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *area) -{ - struct azx_pcm *apcm = snd_pcm_substream_chip(substream); - struct azx *chip = apcm->chip; - if (!azx_snoop(chip)) - area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); - return snd_pcm_lib_default_mmap(substream, area); -} -#else -#define azx_pcm_mmap NULL -#endif - -static struct snd_pcm_ops azx_pcm_ops = { - .open = azx_pcm_open, - .close = azx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = azx_pcm_hw_params, - .hw_free = azx_pcm_hw_free, - .prepare = azx_pcm_prepare, - .trigger = azx_pcm_trigger, - .pointer = azx_pcm_pointer, - .mmap = azx_pcm_mmap, - .page = snd_pcm_sgbuf_ops_page, -}; - -static void azx_pcm_free(struct snd_pcm *pcm) -{ - struct azx_pcm *apcm = pcm->private_data; - if (apcm) { - list_del(&apcm->list); - kfree(apcm); - } -} - -#define MAX_PREALLOC_SIZE (32 * 1024 * 1024) - -static int -azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, - struct hda_pcm *cpcm) -{ - struct azx *chip = bus->private_data; - struct snd_pcm *pcm; - struct azx_pcm *apcm; - int pcm_dev = cpcm->device; - unsigned int size; - int s, err; - - list_for_each_entry(apcm, &chip->pcm_list, list) { - if (apcm->pcm->device == pcm_dev) { - snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); - return -EBUSY; - } - } - err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, - cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, - cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams, - &pcm); - if (err < 0) - return err; - strlcpy(pcm->name, cpcm->name, sizeof(pcm->name)); - apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); - if (apcm == NULL) - return -ENOMEM; - apcm->chip = chip; - apcm->pcm = pcm; - apcm->codec = codec; - pcm->private_data = apcm; - pcm->private_free = azx_pcm_free; - if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) - pcm->dev_class = SNDRV_PCM_CLASS_MODEM; - list_add_tail(&apcm->list, &chip->pcm_list); - cpcm->pcm = pcm; - for (s = 0; s < 2; s++) { - apcm->hinfo[s] = &cpcm->stream[s]; - if (cpcm->stream[s].substreams) - snd_pcm_set_ops(pcm, s, &azx_pcm_ops); - } - /* buffer pre-allocation */ - size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024; - if (size > MAX_PREALLOC_SIZE) - size = MAX_PREALLOC_SIZE; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - size, MAX_PREALLOC_SIZE); - return 0; -} - -/* - * mixer creation - all stuff is implemented in hda module - */ -static int __devinit azx_mixer_create(struct azx *chip) -{ - return snd_hda_build_controls(chip->bus); -} - - -/* - * initialize SD streams - */ -static int __devinit azx_init_stream(struct azx *chip) -{ - int i; - - /* initialize each stream (aka device) - * assign the starting bdl address to each stream (device) - * and initialize - */ - for (i = 0; i < chip->num_streams; i++) { - struct azx_dev *azx_dev = &chip->azx_dev[i]; - azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); - /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ - azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); - /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ - azx_dev->sd_int_sta_mask = 1 << i; - /* stream tag: must be non-zero and unique */ - azx_dev->index = i; - azx_dev->stream_tag = i + 1; - } - - return 0; -} - -static int azx_acquire_irq(struct azx *chip, int do_disconnect) -{ - if (request_irq(chip->pci->irq, azx_interrupt, - chip->msi ? 0 : IRQF_SHARED, - KBUILD_MODNAME, chip)) { - printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " - "disabling device\n", chip->pci->irq); - if (do_disconnect) - snd_card_disconnect(chip->card); - return -1; - } - chip->irq = chip->pci->irq; - pci_intx(chip->pci, !chip->msi); - return 0; -} - - -static void azx_stop_chip(struct azx *chip) -{ - if (!chip->initialized) - return; - - /* disable interrupts */ - azx_int_disable(chip); - azx_int_clear(chip); - - /* disable CORB/RIRB */ - azx_free_cmd_io(chip); - - /* disable position buffer */ - azx_writel(chip, DPLBASE, 0); - azx_writel(chip, DPUBASE, 0); - - chip->initialized = 0; -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -/* power-up/down the controller */ -static void azx_power_notify(struct hda_bus *bus) -{ - struct azx *chip = bus->private_data; - struct hda_codec *c; - int power_on = 0; - - list_for_each_entry(c, &bus->codec_list, list) { - if (c->power_on) { - power_on = 1; - break; - } - } - if (power_on) - azx_init_chip(chip, 1); - else if (chip->running && power_save_controller && - !bus->power_keep_link_on) - azx_stop_chip(chip); -} -#endif /* CONFIG_SND_HDA_POWER_SAVE */ - -#ifdef CONFIG_PM -/* - * power management - */ - -static int snd_hda_codecs_inuse(struct hda_bus *bus) -{ - struct hda_codec *codec; - - list_for_each_entry(codec, &bus->codec_list, list) { - if (snd_hda_codec_needs_resume(codec)) - return 1; - } - return 0; -} - -static int azx_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct azx *chip = card->private_data; - struct azx_pcm *p; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - azx_clear_irq_pending(chip); - list_for_each_entry(p, &chip->pcm_list, list) - snd_pcm_suspend_all(p->pcm); - if (chip->initialized) - snd_hda_suspend(chip->bus); - azx_stop_chip(chip); - if (chip->irq >= 0) { - free_irq(chip->irq, chip); - chip->irq = -1; - } - if (chip->msi) - pci_disable_msi(chip->pci); - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int azx_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct azx *chip = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "hda-intel: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - if (chip->msi) - if (pci_enable_msi(pci) < 0) - chip->msi = 0; - if (azx_acquire_irq(chip, 1) < 0) - return -EIO; - azx_init_pci(chip); - - if (snd_hda_codecs_inuse(chip->bus)) - azx_init_chip(chip, 1); - - snd_hda_resume(chip->bus); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - - -/* - * reboot notifier for hang-up problem at power-down - */ -static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) -{ - struct azx *chip = container_of(nb, struct azx, reboot_notifier); - snd_hda_bus_reboot_notify(chip->bus); - azx_stop_chip(chip); - return NOTIFY_OK; -} - -static void azx_notifier_register(struct azx *chip) -{ - chip->reboot_notifier.notifier_call = azx_halt; - register_reboot_notifier(&chip->reboot_notifier); -} - -static void azx_notifier_unregister(struct azx *chip) -{ - if (chip->reboot_notifier.notifier_call) - unregister_reboot_notifier(&chip->reboot_notifier); -} - -/* - * destructor - */ -static int azx_free(struct azx *chip) -{ - int i; - - azx_notifier_unregister(chip); - - if (chip->initialized) { - azx_clear_irq_pending(chip); - for (i = 0; i < chip->num_streams; i++) - azx_stream_stop(chip, &chip->azx_dev[i]); - azx_stop_chip(chip); - } - - if (chip->irq >= 0) - free_irq(chip->irq, (void*)chip); - if (chip->msi) - pci_disable_msi(chip->pci); - if (chip->remap_addr) - iounmap(chip->remap_addr); - - if (chip->azx_dev) { - for (i = 0; i < chip->num_streams; i++) - if (chip->azx_dev[i].bdl.area) { - mark_pages_wc(chip, &chip->azx_dev[i].bdl, false); - snd_dma_free_pages(&chip->azx_dev[i].bdl); - } - } - if (chip->rb.area) { - mark_pages_wc(chip, &chip->rb, false); - snd_dma_free_pages(&chip->rb); - } - if (chip->posbuf.area) { - mark_pages_wc(chip, &chip->posbuf, false); - snd_dma_free_pages(&chip->posbuf); - } - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip->azx_dev); - kfree(chip); - - return 0; -} - -static int azx_dev_free(struct snd_device *device) -{ - return azx_free(device->device_data); -} - -/* - * white/black-listing for position_fix - */ -static struct snd_pci_quirk position_fix_list[] __devinitdata = { - SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), - SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), - SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), - SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1849, 0x0888, "775Dual-VSTA", POS_FIX_LPIB), - SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB), - {} -}; - -static int __devinit check_position_fix(struct azx *chip, int fix) -{ - const struct snd_pci_quirk *q; - - switch (fix) { - case POS_FIX_LPIB: - case POS_FIX_POSBUF: - case POS_FIX_VIACOMBO: - case POS_FIX_COMBO: - return fix; - } - - q = snd_pci_quirk_lookup(chip->pci, position_fix_list); - if (q) { - printk(KERN_INFO - "hda_intel: position_fix set to %d " - "for device %04x:%04x\n", - q->value, q->subvendor, q->subdevice); - return q->value; - } - - /* Check VIA/ATI HD Audio Controller exist */ - if (chip->driver_caps & AZX_DCAPS_POSFIX_VIA) { - snd_printd(SFX "Using VIACOMBO position fix\n"); - return POS_FIX_VIACOMBO; - } - if (chip->driver_caps & AZX_DCAPS_POSFIX_LPIB) { - snd_printd(SFX "Using LPIB position fix\n"); - return POS_FIX_LPIB; - } - return POS_FIX_AUTO; -} - -/* - * black-lists for probe_mask - */ -static struct snd_pci_quirk probe_mask_list[] __devinitdata = { - /* Thinkpad often breaks the controller communication when accessing - * to the non-working (or non-existing) modem codec slot. - */ - SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01), - SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01), - SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01), - /* broken BIOS */ - SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01), - /* including bogus ALC268 in slot#2 that conflicts with ALC888 */ - SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01), - /* forced codec slots */ - SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103), - SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103), - {} -}; - -#define AZX_FORCE_CODEC_MASK 0x100 - -static void __devinit check_probe_mask(struct azx *chip, int dev) -{ - const struct snd_pci_quirk *q; - - chip->codec_probe_mask = probe_mask[dev]; - if (chip->codec_probe_mask == -1) { - q = snd_pci_quirk_lookup(chip->pci, probe_mask_list); - if (q) { - printk(KERN_INFO - "hda_intel: probe_mask set to 0x%x " - "for device %04x:%04x\n", - q->value, q->subvendor, q->subdevice); - chip->codec_probe_mask = q->value; - } - } - - /* check forced option */ - if (chip->codec_probe_mask != -1 && - (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) { - chip->codec_mask = chip->codec_probe_mask & 0xff; - printk(KERN_INFO "hda_intel: codec_mask forced to 0x%x\n", - chip->codec_mask); - } -} - -/* - * white/black-list for enable_msi - */ -static struct snd_pci_quirk msi_black_list[] __devinitdata = { - SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ - SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ - SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */ - SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */ - SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */ - {} -}; - -static void __devinit check_msi(struct azx *chip) -{ - const struct snd_pci_quirk *q; - - if (enable_msi >= 0) { - chip->msi = !!enable_msi; - return; - } - chip->msi = 1; /* enable MSI as default */ - q = snd_pci_quirk_lookup(chip->pci, msi_black_list); - if (q) { - printk(KERN_INFO - "hda_intel: msi for device %04x:%04x set to %d\n", - q->subvendor, q->subdevice, q->value); - chip->msi = q->value; - return; - } - - /* NVidia chipsets seem to cause troubles with MSI */ - if (chip->driver_caps & AZX_DCAPS_NO_MSI) { - printk(KERN_INFO "hda_intel: Disabling MSI\n"); - chip->msi = 0; - } -} - -/* check the snoop mode availability */ -static void __devinit azx_check_snoop_available(struct azx *chip) -{ - bool snoop = chip->snoop; - - switch (chip->driver_type) { - case AZX_DRIVER_VIA: - /* force to non-snoop mode for a new VIA controller - * when BIOS is set - */ - if (snoop) { - u8 val; - pci_read_config_byte(chip->pci, 0x42, &val); - if (!(val & 0x80) && chip->pci->revision == 0x30) - snoop = false; - } - break; - case AZX_DRIVER_ATIHDMI_NS: - /* new ATI HDMI requires non-snoop */ - snoop = false; - break; - } - - if (snoop != chip->snoop) { - snd_printk(KERN_INFO SFX "Force to %s mode\n", - snoop ? "snoop" : "non-snoop"); - chip->snoop = snoop; - } -} - -/* - * constructor - */ -static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, - int dev, unsigned int driver_caps, - struct azx **rchip) -{ - struct azx *chip; - int i, err; - unsigned short gcap; - static struct snd_device_ops ops = { - .dev_free = azx_dev_free, - }; - - *rchip = NULL; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) { - snd_printk(KERN_ERR SFX "cannot allocate chip\n"); - pci_disable_device(pci); - return -ENOMEM; - } - - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->open_mutex); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - chip->driver_caps = driver_caps; - chip->driver_type = driver_caps & 0xff; - check_msi(chip); - chip->dev_index = dev; - INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); - INIT_LIST_HEAD(&chip->pcm_list); - - chip->position_fix[0] = chip->position_fix[1] = - check_position_fix(chip, position_fix[dev]); - /* combo mode uses LPIB for playback */ - if (chip->position_fix[0] == POS_FIX_COMBO) { - chip->position_fix[0] = POS_FIX_LPIB; - chip->position_fix[1] = POS_FIX_AUTO; - } - - check_probe_mask(chip, dev); - - chip->single_cmd = single_cmd; - chip->snoop = hda_snoop; - azx_check_snoop_available(chip); - - if (bdl_pos_adj[dev] < 0) { - switch (chip->driver_type) { - case AZX_DRIVER_ICH: - case AZX_DRIVER_PCH: - bdl_pos_adj[dev] = 1; - break; - default: - bdl_pos_adj[dev] = 32; - break; - } - } - -#if BITS_PER_LONG != 64 - /* Fix up base address on ULI M5461 */ - if (chip->driver_type == AZX_DRIVER_ULI) { - u16 tmp3; - pci_read_config_word(pci, 0x40, &tmp3); - pci_write_config_word(pci, 0x40, tmp3 | 0x10); - pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, 0); - } -#endif - - err = pci_request_regions(pci, "ICH HD audio"); - if (err < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - - chip->addr = pci_resource_start(pci, 0); - chip->remap_addr = pci_ioremap_bar(pci, 0); - if (chip->remap_addr == NULL) { - snd_printk(KERN_ERR SFX "ioremap error\n"); - err = -ENXIO; - goto errout; - } - - if (chip->msi) - if (pci_enable_msi(pci) < 0) - chip->msi = 0; - - if (azx_acquire_irq(chip, 0) < 0) { - err = -EBUSY; - goto errout; - } - - pci_set_master(pci); - synchronize_irq(chip->irq); - - gcap = azx_readw(chip, GCAP); - snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap); - - /* disable SB600 64bit support for safety */ - if (chip->pci->vendor == PCI_VENDOR_ID_ATI) { - struct pci_dev *p_smbus; - p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, - PCI_DEVICE_ID_ATI_SBX00_SMBUS, - NULL); - if (p_smbus) { - if (p_smbus->revision < 0x30) - gcap &= ~ICH6_GCAP_64OK; - pci_dev_put(p_smbus); - } - } - - /* disable 64bit DMA address on some devices */ - if (chip->driver_caps & AZX_DCAPS_NO_64BIT) { - snd_printd(SFX "Disabling 64bit DMA\n"); - gcap &= ~ICH6_GCAP_64OK; - } - - /* disable buffer size rounding to 128-byte multiples if supported */ - if (align_buffer_size >= 0) - chip->align_buffer_size = !!align_buffer_size; - else { - if (chip->driver_caps & AZX_DCAPS_BUFSIZE) - chip->align_buffer_size = 0; - else if (chip->driver_caps & AZX_DCAPS_ALIGN_BUFSIZE) - chip->align_buffer_size = 1; - else - chip->align_buffer_size = 1; - } - - /* allow 64bit DMA address if supported by H/W */ - if ((gcap & ICH6_GCAP_64OK) && !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_BIT_MASK(32)); - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)); - } - - /* read number of streams from GCAP register instead of using - * hardcoded value - */ - chip->capture_streams = (gcap >> 8) & 0x0f; - chip->playback_streams = (gcap >> 12) & 0x0f; - if (!chip->playback_streams && !chip->capture_streams) { - /* gcap didn't give any info, switching to old method */ - - switch (chip->driver_type) { - case AZX_DRIVER_ULI: - chip->playback_streams = ULI_NUM_PLAYBACK; - chip->capture_streams = ULI_NUM_CAPTURE; - break; - case AZX_DRIVER_ATIHDMI: - case AZX_DRIVER_ATIHDMI_NS: - chip->playback_streams = ATIHDMI_NUM_PLAYBACK; - chip->capture_streams = ATIHDMI_NUM_CAPTURE; - break; - case AZX_DRIVER_GENERIC: - default: - chip->playback_streams = ICH6_NUM_PLAYBACK; - chip->capture_streams = ICH6_NUM_CAPTURE; - break; - } - } - chip->capture_index_offset = 0; - chip->playback_index_offset = chip->capture_streams; - chip->num_streams = chip->playback_streams + chip->capture_streams; - chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), - GFP_KERNEL); - if (!chip->azx_dev) { - snd_printk(KERN_ERR SFX "cannot malloc azx_dev\n"); - goto errout; - } - - for (i = 0; i < chip->num_streams; i++) { - /* allocate memory for the BDL for each stream */ - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - BDL_SIZE, &chip->azx_dev[i].bdl); - if (err < 0) { - snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); - goto errout; - } - mark_pages_wc(chip, &chip->azx_dev[i].bdl, true); - } - /* allocate memory for the position buffer */ - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - chip->num_streams * 8, &chip->posbuf); - if (err < 0) { - snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); - goto errout; - } - mark_pages_wc(chip, &chip->posbuf, true); - /* allocate CORB/RIRB */ - err = azx_alloc_cmd_io(chip); - if (err < 0) - goto errout; - - /* initialize streams */ - azx_init_stream(chip); - - /* initialize chip */ - azx_init_pci(chip); - azx_init_chip(chip, (probe_only[dev] & 2) == 0); - - /* codec detection */ - if (!chip->codec_mask) { - snd_printk(KERN_ERR SFX "no codecs found!\n"); - err = -ENODEV; - goto errout; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err <0) { - snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); - goto errout; - } - - strcpy(card->driver, "HDA-Intel"); - strlcpy(card->shortname, driver_short_names[chip->driver_type], - sizeof(card->shortname)); - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%lx irq %i", - card->shortname, chip->addr, chip->irq); - - *rchip = chip; - return 0; - - errout: - azx_free(chip); - return err; -} - -static void power_down_all_codecs(struct azx *chip) -{ -#ifdef CONFIG_SND_HDA_POWER_SAVE - /* The codecs were powered up in snd_hda_codec_new(). - * Now all initialization done, so turn them down if possible - */ - struct hda_codec *codec; - list_for_each_entry(codec, &chip->bus->codec_list, list) { - snd_hda_power_down(codec); - } -#endif -} - -static int __devinit azx_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct azx *chip; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printk(KERN_ERR SFX "Error creating card!\n"); - return err; - } - - /* set this here since it's referred in snd_hda_load_patch() */ - snd_card_set_dev(card, &pci->dev); - - err = azx_create(card, pci, dev, pci_id->driver_data, &chip); - if (err < 0) - goto out_free; - card->private_data = chip; - -#ifdef CONFIG_SND_HDA_INPUT_BEEP - chip->beep_mode = beep_mode[dev]; -#endif - - /* create codec instances */ - err = azx_codec_create(chip, model[dev]); - if (err < 0) - goto out_free; -#ifdef CONFIG_SND_HDA_PATCH_LOADER - if (patch[dev] && *patch[dev]) { - snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n", - patch[dev]); - err = snd_hda_load_patch(chip->bus, patch[dev]); - if (err < 0) - goto out_free; - } -#endif - if ((probe_only[dev] & 1) == 0) { - err = azx_codec_configure(chip); - if (err < 0) - goto out_free; - } - - /* create PCM streams */ - err = snd_hda_build_pcms(chip->bus); - if (err < 0) - goto out_free; - - /* create mixer controls */ - err = azx_mixer_create(chip); - if (err < 0) - goto out_free; - - err = snd_card_register(card); - if (err < 0) - goto out_free; - - pci_set_drvdata(pci, card); - chip->running = 1; - power_down_all_codecs(chip); - azx_notifier_register(chip); - - dev++; - return err; -out_free: - snd_card_free(card); - return err; -} - -static void __devexit azx_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -/* PCI IDs */ -static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { - /* CPT */ - { PCI_DEVICE(0x8086, 0x1c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE }, - /* PBG */ - { PCI_DEVICE(0x8086, 0x1d20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, - /* Panther Point */ - { PCI_DEVICE(0x8086, 0x1e20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, - /* Lynx Point */ - { PCI_DEVICE(0x8086, 0x8c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, - /* SCH */ - { PCI_DEVICE(0x8086, 0x811b), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */ - { PCI_DEVICE(0x8086, 0x080a), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */ - /* ICH */ - { PCI_DEVICE(0x8086, 0x2668), - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | - AZX_DCAPS_BUFSIZE }, /* ICH6 */ - { PCI_DEVICE(0x8086, 0x27d8), - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | - AZX_DCAPS_BUFSIZE }, /* ICH7 */ - { PCI_DEVICE(0x8086, 0x269a), - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | - AZX_DCAPS_BUFSIZE }, /* ESB2 */ - { PCI_DEVICE(0x8086, 0x284b), - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | - AZX_DCAPS_BUFSIZE }, /* ICH8 */ - { PCI_DEVICE(0x8086, 0x293e), - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | - AZX_DCAPS_BUFSIZE }, /* ICH9 */ - { PCI_DEVICE(0x8086, 0x293f), - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | - AZX_DCAPS_BUFSIZE }, /* ICH9 */ - { PCI_DEVICE(0x8086, 0x3a3e), - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | - AZX_DCAPS_BUFSIZE }, /* ICH10 */ - { PCI_DEVICE(0x8086, 0x3a6e), - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | - AZX_DCAPS_BUFSIZE }, /* ICH10 */ - /* Generic Intel */ - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID), - .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, - .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_BUFSIZE }, - /* ATI SB 450/600/700/800/900 */ - { PCI_DEVICE(0x1002, 0x437b), - .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB }, - { PCI_DEVICE(0x1002, 0x4383), - .driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB }, - /* AMD Hudson */ - { PCI_DEVICE(0x1022, 0x780d), - .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, - /* ATI HDMI */ - { PCI_DEVICE(0x1002, 0x793b), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0x7919), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0x960f), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0x970f), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa00), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa08), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa10), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa18), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa20), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa28), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa30), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa38), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa40), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaa48), - .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0x9902), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaaa0), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaaa8), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(0x1002, 0xaab0), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI }, - /* VIA VT8251/VT8237A */ - { PCI_DEVICE(0x1106, 0x3288), - .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, - /* SIS966 */ - { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS }, - /* ULI M5461 */ - { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI }, - /* NVIDIA MCP */ - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID), - .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, - .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_NVIDIA | AZX_DCAPS_PRESET_NVIDIA }, - /* Teradici */ - { PCI_DEVICE(0x6549, 0x1200), - .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, - /* Creative X-Fi (CA0110-IBG) */ -#if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE) - /* the following entry conflicts with snd-ctxfi driver, - * as ctxfi driver mutates from HD-audio to native mode with - * a special command sequence. - */ - { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), - .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, - .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | - AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, -#else - /* this entry seems still valid -- i.e. without emu20kx chip */ - { PCI_DEVICE(0x1102, 0x0009), - .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | - AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, -#endif - /* Vortex86MX */ - { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, - /* VMware HDAudio */ - { PCI_DEVICE(0x15ad, 0x1977), .driver_data = AZX_DRIVER_GENERIC }, - /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */ - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), - .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, - .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_ANY_ID), - .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, - .class_mask = 0xffffff, - .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, azx_ids); - -/* pci_driver definition */ -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = azx_ids, - .probe = azx_probe, - .remove = __devexit_p(azx_remove), -#ifdef CONFIG_PM - .suspend = azx_suspend, - .resume = azx_resume, -#endif -}; - -static int __init alsa_card_azx_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_azx_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_azx_init) -module_exit(alsa_card_azx_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_jack.c b/ANDROID_3.4.5/sound/pci/hda/hda_jack.c deleted file mode 100644 index d6894849..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_jack.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Jack-detection handling for HD-audio - * - * Copyright (c) 2011 Takashi Iwai - * - * This driver 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. - */ - -#include -#include -#include -#include -#include -#include -#include "hda_codec.h" -#include "hda_local.h" -#include "hda_jack.h" - -bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) -{ - if (codec->no_jack_detect) - return false; - if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) - return false; - if (!codec->ignore_misc_bit && - (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & - AC_DEFCFG_MISC_NO_PRESENCE)) - return false; - if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) - return false; - return true; -} -EXPORT_SYMBOL_HDA(is_jack_detectable); - -/* execute pin sense measurement */ -static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) -{ - u32 pincap; - - if (!codec->no_trigger_sense) { - pincap = snd_hda_query_pin_caps(codec, nid); - if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ - snd_hda_codec_read(codec, nid, 0, - AC_VERB_SET_PIN_SENSE, 0); - } - return snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_SENSE, 0); -} - -/** - * snd_hda_jack_tbl_get - query the jack-table entry for the given NID - */ -struct hda_jack_tbl * -snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid) -{ - struct hda_jack_tbl *jack = codec->jacktbl.list; - int i; - - if (!nid || !jack) - return NULL; - for (i = 0; i < codec->jacktbl.used; i++, jack++) - if (jack->nid == nid) - return jack; - return NULL; -} -EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get); - -/** - * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag - */ -struct hda_jack_tbl * -snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag) -{ - struct hda_jack_tbl *jack = codec->jacktbl.list; - int i; - - if (!tag || !jack) - return NULL; - for (i = 0; i < codec->jacktbl.used; i++, jack++) - if (jack->tag == tag) - return jack; - return NULL; -} -EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag); - -/** - * snd_hda_jack_tbl_new - create a jack-table entry for the given NID - */ -struct hda_jack_tbl * -snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) -{ - struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); - if (jack) - return jack; - snd_array_init(&codec->jacktbl, sizeof(*jack), 16); - jack = snd_array_new(&codec->jacktbl); - if (!jack) - return NULL; - jack->nid = nid; - jack->jack_dirty = 1; - jack->tag = codec->jacktbl.used; - return jack; -} -EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new); - -void snd_hda_jack_tbl_clear(struct hda_codec *codec) -{ -#ifdef CONFIG_SND_HDA_INPUT_JACK - /* free jack instances manually when clearing/reconfiguring */ - if (!codec->bus->shutdown && codec->jacktbl.list) { - struct hda_jack_tbl *jack = codec->jacktbl.list; - int i; - for (i = 0; i < codec->jacktbl.used; i++, jack++) { - if (jack->jack) - snd_device_free(codec->bus->card, jack->jack); - } - } -#endif - snd_array_free(&codec->jacktbl); -} - -/* update the cached value and notification flag if needed */ -static void jack_detect_update(struct hda_codec *codec, - struct hda_jack_tbl *jack) -{ - if (jack->jack_dirty || !jack->jack_detect) { - jack->pin_sense = read_pin_sense(codec, jack->nid); - jack->jack_dirty = 0; - } -} - -/** - * snd_hda_set_dirty_all - Mark all the cached as dirty - * - * This function sets the dirty flag to all entries of jack table. - * It's called from the resume path in hda_codec.c. - */ -void snd_hda_jack_set_dirty_all(struct hda_codec *codec) -{ - struct hda_jack_tbl *jack = codec->jacktbl.list; - int i; - - for (i = 0; i < codec->jacktbl.used; i++, jack++) - if (jack->nid) - jack->jack_dirty = 1; -} -EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all); - -/** - * snd_hda_pin_sense - execute pin sense measurement - * @codec: the CODEC to sense - * @nid: the pin NID to sense - * - * Execute necessary pin sense measurement and return its Presence Detect, - * Impedance, ELD Valid etc. status bits. - */ -u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) -{ - struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); - if (jack) { - jack_detect_update(codec, jack); - return jack->pin_sense; - } - return read_pin_sense(codec, nid); -} -EXPORT_SYMBOL_HDA(snd_hda_pin_sense); - -#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE) - -/** - * snd_hda_jack_detect - query pin Presence Detect status - * @codec: the CODEC to sense - * @nid: the pin NID to sense - * - * Query and return the pin's Presence Detect status. - */ -int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) -{ - u32 sense = snd_hda_pin_sense(codec, nid); - return get_jack_plug_state(sense); -} -EXPORT_SYMBOL_HDA(snd_hda_jack_detect); - -/** - * snd_hda_jack_detect_enable - enable the jack-detection - */ -int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, - unsigned char action) -{ - struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); - if (!jack) - return -ENOMEM; - if (jack->jack_detect) - return 0; /* already registered */ - jack->jack_detect = 1; - if (action) - jack->action = action; - return snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_UNSOLICITED_ENABLE, - AC_USRSP_EN | jack->tag); -} -EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); - -/** - * snd_hda_jack_report_sync - sync the states of all jacks and report if changed - */ -void snd_hda_jack_report_sync(struct hda_codec *codec) -{ - struct hda_jack_tbl *jack = codec->jacktbl.list; - int i, state; - - for (i = 0; i < codec->jacktbl.used; i++, jack++) - if (jack->nid) { - jack_detect_update(codec, jack); - if (!jack->kctl) - continue; - state = get_jack_plug_state(jack->pin_sense); - snd_kctl_jack_report(codec->bus->card, jack->kctl, state); -#ifdef CONFIG_SND_HDA_INPUT_JACK - if (jack->jack) - snd_jack_report(jack->jack, - state ? jack->type : 0); -#endif - } -} -EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync); - -#ifdef CONFIG_SND_HDA_INPUT_JACK -/* guess the jack type from the pin-config */ -static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); - switch (get_defcfg_device(def_conf)) { - case AC_JACK_LINE_OUT: - case AC_JACK_SPEAKER: - return SND_JACK_LINEOUT; - case AC_JACK_HP_OUT: - return SND_JACK_HEADPHONE; - case AC_JACK_SPDIF_OUT: - case AC_JACK_DIG_OTHER_OUT: - return SND_JACK_AVOUT; - case AC_JACK_MIC_IN: - return SND_JACK_MICROPHONE; - default: - return SND_JACK_LINEIN; - } -} - -static void hda_free_jack_priv(struct snd_jack *jack) -{ - struct hda_jack_tbl *jacks = jack->private_data; - jacks->nid = 0; - jacks->jack = NULL; -} -#endif - -/** - * snd_hda_jack_add_kctl - Add a kctl for the given pin - * - * This assigns a jack-detection kctl to the given pin. The kcontrol - * will have the given name and index. - */ -int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, - const char *name, int idx) -{ - struct hda_jack_tbl *jack; - struct snd_kcontrol *kctl; - int err, state; - - jack = snd_hda_jack_tbl_new(codec, nid); - if (!jack) - return 0; - if (jack->kctl) - return 0; /* already created */ - kctl = snd_kctl_jack_new(name, idx, codec); - if (!kctl) - return -ENOMEM; - err = snd_hda_ctl_add(codec, nid, kctl); - if (err < 0) - return err; - jack->kctl = kctl; - state = snd_hda_jack_detect(codec, nid); - snd_kctl_jack_report(codec->bus->card, kctl, state); -#ifdef CONFIG_SND_HDA_INPUT_JACK - jack->type = get_input_jack_type(codec, nid); - err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack); - if (err < 0) - return err; - jack->jack->private_data = jack; - jack->jack->private_free = hda_free_jack_priv; - snd_jack_report(jack->jack, state ? jack->type : 0); -#endif - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); - -static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, - const struct auto_pin_cfg *cfg, - char *lastname, int *lastidx) -{ - unsigned int def_conf, conn; - char name[44]; - int idx, err; - - if (!nid) - return 0; - if (!is_jack_detectable(codec, nid)) - return 0; - def_conf = snd_hda_codec_get_pincfg(codec, nid); - conn = get_defcfg_connect(def_conf); - if (conn != AC_JACK_PORT_COMPLEX) - return 0; - - snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); - if (!strcmp(name, lastname) && idx == *lastidx) - idx++; - strncpy(lastname, name, 44); - *lastidx = idx; - err = snd_hda_jack_add_kctl(codec, nid, name, idx); - if (err < 0) - return err; - return snd_hda_jack_detect_enable(codec, nid, 0); -} - -/** - * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg - */ -int snd_hda_jack_add_kctls(struct hda_codec *codec, - const struct auto_pin_cfg *cfg) -{ - const hda_nid_t *p; - int i, err, lastidx = 0; - char lastname[44] = ""; - - for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { - err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); - if (err < 0) - return err; - } - for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { - if (*p == *cfg->line_out_pins) /* might be duplicated */ - break; - err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); - if (err < 0) - return err; - } - for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { - if (*p == *cfg->line_out_pins) /* might be duplicated */ - break; - err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); - if (err < 0) - return err; - } - for (i = 0; i < cfg->num_inputs; i++) { - err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx); - if (err < 0) - return err; - } - for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { - err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx); - if (err < 0) - return err; - } - err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx); - if (err < 0) - return err; - err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx); - if (err < 0) - return err; - return 0; -} -EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_jack.h b/ANDROID_3.4.5/sound/pci/hda/hda_jack.h deleted file mode 100644 index c66655cf..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_jack.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Jack-detection handling for HD-audio - * - * Copyright (c) 2011 Takashi Iwai - * - * This driver 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. - */ - -#ifndef __SOUND_HDA_JACK_H -#define __SOUND_HDA_JACK_H - -struct hda_jack_tbl { - hda_nid_t nid; - unsigned char action; /* event action (0 = none) */ - unsigned char tag; /* unsol event tag */ - unsigned int private_data; /* arbitrary data */ - /* jack-detection stuff */ - unsigned int pin_sense; /* cached pin-sense value */ - unsigned int jack_detect:1; /* capable of jack-detection? */ - unsigned int jack_dirty:1; /* needs to update? */ - struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ -#ifdef CONFIG_SND_HDA_INPUT_JACK - int type; - struct snd_jack *jack; -#endif -}; - -struct hda_jack_tbl * -snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); -struct hda_jack_tbl * -snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag); - -struct hda_jack_tbl * -snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); -void snd_hda_jack_tbl_clear(struct hda_codec *codec); - -/** - * snd_hda_jack_get_action - get jack-tbl entry for the tag - * - * Call this from the unsol event handler to get the assigned action for the - * event. This will mark the dirty flag for the later reporting, too. - */ -static inline unsigned char -snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag) -{ - struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag); - if (jack) { - jack->jack_dirty = 1; - return jack->action; - } - return 0; -} - -void snd_hda_jack_set_dirty_all(struct hda_codec *codec); - -int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, - unsigned char action); - -u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); -int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); - -bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); - -int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, - const char *name, int idx); -int snd_hda_jack_add_kctls(struct hda_codec *codec, - const struct auto_pin_cfg *cfg); - -void snd_hda_jack_report_sync(struct hda_codec *codec); - - -#endif /* __SOUND_HDA_JACK_H */ diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_local.h b/ANDROID_3.4.5/sound/pci/hda/hda_local.h deleted file mode 100644 index 0ec92481..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_local.h +++ /dev/null @@ -1,708 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * Local helper functions - * - * Copyright (c) 2004 Takashi Iwai - * - * 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. - */ - -#ifndef __SOUND_HDA_LOCAL_H -#define __SOUND_HDA_LOCAL_H - -/* We abuse kcontrol_new.subdev field to pass the NID corresponding to - * the given new control. If id.subdev has a bit flag HDA_SUBDEV_NID_FLAG, - * snd_hda_ctl_add() takes the lower-bit subdev value as a valid NID. - * - * Note that the subdevice field is cleared again before the real registration - * in snd_hda_ctl_add(), so that this value won't appear in the outside. - */ -#define HDA_SUBDEV_NID_FLAG (1U << 31) -#define HDA_SUBDEV_AMP_FLAG (1U << 30) - -/* - * for mixer controls - */ -#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ - ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) -#define HDA_AMP_VAL_MIN_MUTE (1<<29) -#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ - HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) -/* mono volume with index (index=0,1,...) (channel=1,2) */ -#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, dir, flags) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ - .subdevice = HDA_SUBDEV_AMP_FLAG, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ - .info = snd_hda_mixer_amp_volume_info, \ - .get = snd_hda_mixer_amp_volume_get, \ - .put = snd_hda_mixer_amp_volume_put, \ - .tlv = { .c = snd_hda_mixer_amp_tlv }, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, dir) | flags } -/* stereo volume with index */ -#define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ - HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction, 0) -/* mono volume */ -#define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ - HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction, 0) -/* stereo volume */ -#define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ - HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) -/* stereo volume with min=mute */ -#define HDA_CODEC_VOLUME_MIN_MUTE(xname, nid, xindex, direction) \ - HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, 3, xindex, direction, \ - HDA_AMP_VAL_MIN_MUTE) -/* mono mute switch with index (index=0,1,...) (channel=1,2) */ -#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ - .subdevice = HDA_SUBDEV_AMP_FLAG, \ - .info = snd_hda_mixer_amp_switch_info, \ - .get = snd_hda_mixer_amp_switch_get, \ - .put = snd_hda_mixer_amp_switch_put, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } -/* stereo mute switch with index */ -#define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \ - HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) -/* mono mute switch */ -#define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \ - HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction) -/* stereo mute switch */ -#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ - HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) -#ifdef CONFIG_SND_HDA_INPUT_BEEP -/* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */ -#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ - .subdevice = HDA_SUBDEV_AMP_FLAG, \ - .info = snd_hda_mixer_amp_switch_info, \ - .get = snd_hda_mixer_amp_switch_get, \ - .put = snd_hda_mixer_amp_switch_put_beep, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } -#else -/* no digital beep - just the standard one */ -#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, ch, xidx, dir) \ - HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, ch, xidx, dir) -#endif /* CONFIG_SND_HDA_INPUT_BEEP */ -/* special beep mono mute switch */ -#define HDA_CODEC_MUTE_BEEP_MONO(xname, nid, channel, xindex, direction) \ - HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, 0, nid, channel, xindex, direction) -/* special beep stereo mute switch */ -#define HDA_CODEC_MUTE_BEEP(xname, nid, xindex, direction) \ - HDA_CODEC_MUTE_BEEP_MONO(xname, nid, 3, xindex, direction) - -extern const char *snd_hda_pcm_type_name[]; - -int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv); -int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -#ifdef CONFIG_SND_HDA_INPUT_BEEP -int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -#endif -/* lowlevel accessor with caching; use carefully */ -int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, - int direction, int index); -int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, - int direction, int idx, int mask, int val); -int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, - int dir, int idx, int mask, int val); -#ifdef CONFIG_PM -void snd_hda_codec_resume_amp(struct hda_codec *codec); -#endif - -void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir, - unsigned int *tlv); -struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, - const char *name); -int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, - unsigned int *tlv, const char * const *slaves, - const char *suffix, bool init_slave_vol, - struct snd_kcontrol **ctl_ret); -#define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \ - __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL) -int snd_hda_codec_reset(struct hda_codec *codec); - -enum { - HDA_VMUTE_OFF, - HDA_VMUTE_ON, - HDA_VMUTE_FOLLOW_MASTER, -}; - -struct hda_vmaster_mute_hook { - /* below two fields must be filled by the caller of - * snd_hda_add_vmaster_hook() beforehand - */ - struct snd_kcontrol *sw_kctl; - void (*hook)(void *, int); - /* below are initialized automatically */ - unsigned int mute_mode; /* HDA_VMUTE_XXX */ - struct hda_codec *codec; -}; - -int snd_hda_add_vmaster_hook(struct hda_codec *codec, - struct hda_vmaster_mute_hook *hook, - bool expose_enum_ctl); -void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook); - -/* amp value bits */ -#define HDA_AMP_MUTE 0x80 -#define HDA_AMP_UNMUTE 0x00 -#define HDA_AMP_VOLMASK 0x7f - -/* mono switch binding multiple inputs */ -#define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = snd_hda_mixer_amp_switch_info, \ - .get = snd_hda_mixer_bind_switch_get, \ - .put = snd_hda_mixer_bind_switch_put, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } - -/* stereo switch binding multiple inputs */ -#define HDA_BIND_MUTE(xname,nid,indices,dir) \ - HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) - -int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - -/* more generic bound controls */ -struct hda_ctl_ops { - snd_kcontrol_info_t *info; - snd_kcontrol_get_t *get; - snd_kcontrol_put_t *put; - snd_kcontrol_tlv_rw_t *tlv; -}; - -extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */ -extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ - -struct hda_bind_ctls { - struct hda_ctl_ops *ops; - unsigned long values[]; -}; - -int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv); - -#define HDA_BIND_VOL(xname, bindrec) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\ - .info = snd_hda_mixer_bind_ctls_info,\ - .get = snd_hda_mixer_bind_ctls_get,\ - .put = snd_hda_mixer_bind_ctls_put,\ - .tlv = { .c = snd_hda_mixer_bind_tlv },\ - .private_value = (long) (bindrec) } -#define HDA_BIND_SW(xname, bindrec) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = snd_hda_mixer_bind_ctls_info,\ - .get = snd_hda_mixer_bind_ctls_get,\ - .put = snd_hda_mixer_bind_ctls_put,\ - .private_value = (long) (bindrec) } - -/* - * SPDIF I/O - */ -int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, - hda_nid_t associated_nid, - hda_nid_t cvt_nid); -int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); - -/* - * input MUX helper - */ -#define HDA_MAX_NUM_INPUTS 16 -struct hda_input_mux_item { - char label[32]; - unsigned int index; -}; -struct hda_input_mux { - unsigned int num_items; - struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS]; -}; - -int snd_hda_input_mux_info(const struct hda_input_mux *imux, - struct snd_ctl_elem_info *uinfo); -int snd_hda_input_mux_put(struct hda_codec *codec, - const struct hda_input_mux *imux, - struct snd_ctl_elem_value *ucontrol, hda_nid_t nid, - unsigned int *cur_val); - -/* - * Channel mode helper - */ -struct hda_channel_mode { - int channels; - const struct hda_verb *sequence; -}; - -int snd_hda_ch_mode_info(struct hda_codec *codec, - struct snd_ctl_elem_info *uinfo, - const struct hda_channel_mode *chmode, - int num_chmodes); -int snd_hda_ch_mode_get(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol, - const struct hda_channel_mode *chmode, - int num_chmodes, - int max_channels); -int snd_hda_ch_mode_put(struct hda_codec *codec, - struct snd_ctl_elem_value *ucontrol, - const struct hda_channel_mode *chmode, - int num_chmodes, - int *max_channelsp); - -/* - * Multi-channel / digital-out PCM helper - */ - -enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */ -enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */ - -#define HDA_MAX_OUTS 5 - -struct hda_multi_out { - int num_dacs; /* # of DACs, must be more than 1 */ - const hda_nid_t *dac_nids; /* DAC list */ - hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ - hda_nid_t hp_out_nid[HDA_MAX_OUTS]; /* DACs for multiple HPs */ - hda_nid_t extra_out_nid[HDA_MAX_OUTS]; /* other (e.g. speaker) DACs */ - hda_nid_t dig_out_nid; /* digital out audio widget */ - const hda_nid_t *slave_dig_outs; - int max_channels; /* currently supported analog channels */ - int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ - int no_share_stream; /* don't share a stream with multiple pins */ - int share_spdif; /* share SPDIF pin */ - /* PCM information for both analog and SPDIF DACs */ - unsigned int analog_rates; - unsigned int analog_maxbps; - u64 analog_formats; - unsigned int spdif_rates; - unsigned int spdif_maxbps; - u64 spdif_formats; -}; - -int snd_hda_create_spdif_share_sw(struct hda_codec *codec, - struct hda_multi_out *mout); -int snd_hda_multi_out_dig_open(struct hda_codec *codec, - struct hda_multi_out *mout); -int snd_hda_multi_out_dig_close(struct hda_codec *codec, - struct hda_multi_out *mout); -int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, - struct hda_multi_out *mout, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream); -int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec, - struct hda_multi_out *mout); -int snd_hda_multi_out_analog_open(struct hda_codec *codec, - struct hda_multi_out *mout, - struct snd_pcm_substream *substream, - struct hda_pcm_stream *hinfo); -int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, - struct hda_multi_out *mout, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream); -int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, - struct hda_multi_out *mout); - -/* - * generic codec parser - */ -#ifdef CONFIG_SND_HDA_GENERIC -int snd_hda_parse_generic_codec(struct hda_codec *codec); -#else -static inline int snd_hda_parse_generic_codec(struct hda_codec *codec) -{ - return -ENODEV; -} -#endif - -/* - * generic proc interface - */ -#ifdef CONFIG_PROC_FS -int snd_hda_codec_proc_new(struct hda_codec *codec); -#else -static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } -#endif - -#define SND_PRINT_BITS_ADVISED_BUFSIZE 16 -void snd_print_pcm_bits(int pcm, char *buf, int buflen); - -/* - * Misc - */ -int snd_hda_check_board_config(struct hda_codec *codec, int num_configs, - const char * const *modelnames, - const struct snd_pci_quirk *pci_list); -int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, - int num_configs, const char * const *models, - const struct snd_pci_quirk *tbl); -int snd_hda_add_new_ctls(struct hda_codec *codec, - const struct snd_kcontrol_new *knew); - -/* - * unsolicited event handler - */ - -#define HDA_UNSOL_QUEUE_SIZE 64 - -struct hda_bus_unsolicited { - /* ring buffer */ - u32 queue[HDA_UNSOL_QUEUE_SIZE * 2]; - unsigned int rp, wp; - - /* workqueue */ - struct work_struct work; - struct hda_bus *bus; -}; - -/* - * Helper for automatic pin configuration - */ - -enum { - AUTO_PIN_MIC, - AUTO_PIN_LINE_IN, - AUTO_PIN_CD, - AUTO_PIN_AUX, - AUTO_PIN_LAST -}; - -enum { - AUTO_PIN_LINE_OUT, - AUTO_PIN_SPEAKER_OUT, - AUTO_PIN_HP_OUT -}; - -#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS -#define AUTO_CFG_MAX_INS 8 - -struct auto_pin_cfg_item { - hda_nid_t pin; - int type; -}; - -struct auto_pin_cfg; -const char *hda_get_autocfg_input_label(struct hda_codec *codec, - const struct auto_pin_cfg *cfg, - int input); -int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid, - const struct auto_pin_cfg *cfg, - char *label, int maxlen, int *indexp); -int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, - int index, int *type_index_ret); - -enum { - INPUT_PIN_ATTR_UNUSED, /* pin not connected */ - INPUT_PIN_ATTR_INT, /* internal mic/line-in */ - INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */ - INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */ - INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */ - INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */ -}; - -int snd_hda_get_input_pin_attr(unsigned int def_conf); - -struct auto_pin_cfg { - int line_outs; - /* sorted in the order of Front/Surr/CLFE/Side */ - hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS]; - int speaker_outs; - hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS]; - int hp_outs; - int line_out_type; /* AUTO_PIN_XXX_OUT */ - hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; - int num_inputs; - struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS]; - int dig_outs; - hda_nid_t dig_out_pins[2]; - hda_nid_t dig_in_pin; - hda_nid_t mono_out_pin; - int dig_out_type[2]; /* HDA_PCM_TYPE_XXX */ - int dig_in_type; /* HDA_PCM_TYPE_XXX */ -}; - -#define get_defcfg_connect(cfg) \ - ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) -#define get_defcfg_association(cfg) \ - ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) -#define get_defcfg_location(cfg) \ - ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) -#define get_defcfg_sequence(cfg) \ - (cfg & AC_DEFCFG_SEQUENCE) -#define get_defcfg_device(cfg) \ - ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) -#define get_defcfg_misc(cfg) \ - ((cfg & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT) - -/* bit-flags for snd_hda_parse_pin_def_config() behavior */ -#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */ -#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */ - -int snd_hda_parse_pin_defcfg(struct hda_codec *codec, - struct auto_pin_cfg *cfg, - const hda_nid_t *ignore_nids, - unsigned int cond_flags); - -/* older function */ -#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \ - snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0) - -/* amp values */ -#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) -#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) -#define AMP_OUT_MUTE 0xb080 -#define AMP_OUT_UNMUTE 0xb000 -#define AMP_OUT_ZERO 0xb000 -/* pinctl values */ -#define PIN_IN (AC_PINCTL_IN_EN) -#define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ) -#define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50) -#define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD) -#define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80) -#define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100) -#define PIN_OUT (AC_PINCTL_OUT_EN) -#define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN) -#define PIN_HP_AMP (AC_PINCTL_HP_EN) - -/* - * get widget capabilities - */ -static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid) -{ - if (nid < codec->start_nid || - nid >= codec->start_nid + codec->num_nodes) - return 0; - return codec->wcaps[nid - codec->start_nid]; -} - -/* get the widget type from widget capability bits */ -static inline int get_wcaps_type(unsigned int wcaps) -{ - if (!wcaps) - return -1; /* invalid type */ - return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; -} - -static inline unsigned int get_wcaps_channels(u32 wcaps) -{ - unsigned int chans; - - chans = (wcaps & AC_WCAP_CHAN_CNT_EXT) >> 13; - chans = ((chans << 1) | 1) + 1; - - return chans; -} - -u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); -int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, - unsigned int caps); -u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); -int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, - unsigned int caps); - -/* flags for hda_nid_item */ -#define HDA_NID_ITEM_AMP (1<<0) - -struct hda_nid_item { - struct snd_kcontrol *kctl; - unsigned int index; - hda_nid_t nid; - unsigned short flags; -}; - -int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, - struct snd_kcontrol *kctl); -int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, - unsigned int index, hda_nid_t nid); -void snd_hda_ctls_clear(struct hda_codec *codec); - -/* - * hwdep interface - */ -#ifdef CONFIG_SND_HDA_HWDEP -int snd_hda_create_hwdep(struct hda_codec *codec); -#else -static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } -#endif - -#if defined(CONFIG_SND_HDA_POWER_SAVE) && defined(CONFIG_SND_HDA_HWDEP) -int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec); -#else -static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) -{ - return 0; -} -#endif - -#ifdef CONFIG_SND_HDA_RECONFIG -int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); -#else -static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec) -{ - return 0; -} -#endif - -#ifdef CONFIG_SND_HDA_RECONFIG -const char *snd_hda_get_hint(struct hda_codec *codec, const char *key); -int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key); -#else -static inline -const char *snd_hda_get_hint(struct hda_codec *codec, const char *key) -{ - return NULL; -} - -static inline -int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key) -{ - return -ENOENT; -} -#endif - -/* - * power-management - */ - -void snd_hda_schedule_power_save(struct hda_codec *codec); - -struct hda_amp_list { - hda_nid_t nid; - unsigned char dir; - unsigned char idx; -}; - -struct hda_loopback_check { - const struct hda_amp_list *amplist; - int power_on; -}; - -int snd_hda_check_amp_list_power(struct hda_codec *codec, - struct hda_loopback_check *check, - hda_nid_t nid); - -/* - * AMP control callbacks - */ -/* retrieve parameters from private_value */ -#define get_amp_nid_(pv) ((pv) & 0xffff) -#define get_amp_nid(kc) get_amp_nid_((kc)->private_value) -#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) -#define get_amp_direction_(pv) (((pv) >> 18) & 0x1) -#define get_amp_direction(kc) get_amp_direction_((kc)->private_value) -#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) -#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) -#define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1) - -/* - * CEA Short Audio Descriptor data - */ -struct cea_sad { - int channels; - int format; /* (format == 0) indicates invalid SAD */ - int rates; - int sample_bits; /* for LPCM */ - int max_bitrate; /* for AC3...ATRAC */ - int profile; /* for WMAPRO */ -}; - -#define ELD_FIXED_BYTES 20 -#define ELD_MAX_SIZE 256 -#define ELD_MAX_MNL 16 -#define ELD_MAX_SAD 16 - -/* - * ELD: EDID Like Data - */ -struct hdmi_eld { - bool monitor_present; - bool eld_valid; - int eld_size; - int baseline_len; - int eld_ver; - int cea_edid_ver; - char monitor_name[ELD_MAX_MNL + 1]; - int manufacture_id; - int product_id; - u64 port_id; - int support_hdcp; - int support_ai; - int conn_type; - int aud_synch_delay; - int spk_alloc; - int sad_count; - struct cea_sad sad[ELD_MAX_SAD]; - /* - * all fields above eld_buffer will be cleared before updating ELD - */ - char eld_buffer[ELD_MAX_SIZE]; -#ifdef CONFIG_PROC_FS - struct snd_info_entry *proc_entry; -#endif -}; - -int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); -int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t); -void snd_hdmi_show_eld(struct hdmi_eld *eld); -void snd_hdmi_eld_update_pcm_info(struct hdmi_eld *eld, - struct hda_pcm_stream *hinfo); - -#ifdef CONFIG_PROC_FS -int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, - int index); -void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld); -#else -static inline int snd_hda_eld_proc_new(struct hda_codec *codec, - struct hdmi_eld *eld, - int index) -{ - return 0; -} -static inline void snd_hda_eld_proc_free(struct hda_codec *codec, - struct hdmi_eld *eld) -{ -} -#endif - -#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 -void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); - -#endif /* __SOUND_HDA_LOCAL_H */ diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_proc.c b/ANDROID_3.4.5/sound/pci/hda/hda_proc.c deleted file mode 100644 index e59e2f05..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_proc.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * Generic proc interface - * - * Copyright (c) 2004 Takashi Iwai - * - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" - -static char *bits_names(unsigned int bits, char *names[], int size) -{ - int i, n; - static char buf[128]; - - for (i = 0, n = 0; i < size; i++) { - if (bits & (1U<list, *item; - struct snd_kcontrol *kctl; - for (i = 0; i < array->used; i++) { - item = &items[i]; - if (item->nid == nid) { - kctl = item->kctl; - snd_iprintf(buffer, - " Control: name=\"%s\", index=%i, device=%i\n", - kctl->id.name, kctl->id.index + item->index, - kctl->id.device); - if (item->flags & HDA_NID_ITEM_AMP) - snd_iprintf(buffer, - " ControlAmp: chs=%lu, dir=%s, " - "idx=%lu, ofs=%lu\n", - get_amp_channels(kctl), - get_amp_direction(kctl) ? "Out" : "In", - get_amp_index(kctl), - get_amp_offset(kctl)); - } - } -} - -static void print_nid_pcms(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - int pcm, type; - struct hda_pcm *cpcm; - for (pcm = 0; pcm < codec->num_pcms; pcm++) { - cpcm = &codec->pcm_info[pcm]; - for (type = 0; type < 2; type++) { - if (cpcm->stream[type].nid != nid || cpcm->pcm == NULL) - continue; - snd_iprintf(buffer, " Device: name=\"%s\", " - "type=\"%s\", device=%i\n", - cpcm->name, - snd_hda_pcm_type_name[cpcm->pcm_type], - cpcm->pcm->device); - } - } -} - -static void print_amp_caps(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid, int dir) -{ - unsigned int caps; - caps = snd_hda_param_read(codec, nid, - dir == HDA_OUTPUT ? - AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); - if (caps == -1 || caps == 0) { - snd_iprintf(buffer, "N/A\n"); - return; - } - snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, " - "mute=%x\n", - caps & AC_AMPCAP_OFFSET, - (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT, - (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT, - (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT); -} - -static void print_amp_vals(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid, - int dir, int stereo, int indices) -{ - unsigned int val; - int i; - - dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; - for (i = 0; i < indices; i++) { - snd_iprintf(buffer, " ["); - if (stereo) { - val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_LEFT | dir | i); - snd_iprintf(buffer, "0x%02x ", val); - } - val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_RIGHT | dir | i); - snd_iprintf(buffer, "0x%02x]", val); - } - snd_iprintf(buffer, "\n"); -} - -static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm) -{ - static unsigned int rates[] = { - 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, - 96000, 176400, 192000, 384000 - }; - int i; - - pcm &= AC_SUPPCM_RATES; - snd_iprintf(buffer, " rates [0x%x]:", pcm); - for (i = 0; i < ARRAY_SIZE(rates); i++) - if (pcm & (1 << i)) - snd_iprintf(buffer, " %d", rates[i]); - snd_iprintf(buffer, "\n"); -} - -static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm) -{ - char buf[SND_PRINT_BITS_ADVISED_BUFSIZE]; - - snd_iprintf(buffer, " bits [0x%x]:", (pcm >> 16) & 0xff); - snd_print_pcm_bits(pcm, buf, sizeof(buf)); - snd_iprintf(buffer, "%s\n", buf); -} - -static void print_pcm_formats(struct snd_info_buffer *buffer, - unsigned int streams) -{ - snd_iprintf(buffer, " formats [0x%x]:", streams & 0xf); - if (streams & AC_SUPFMT_PCM) - snd_iprintf(buffer, " PCM"); - if (streams & AC_SUPFMT_FLOAT32) - snd_iprintf(buffer, " FLOAT"); - if (streams & AC_SUPFMT_AC3) - snd_iprintf(buffer, " AC3"); - snd_iprintf(buffer, "\n"); -} - -static void print_pcm_caps(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM); - unsigned int stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); - if (pcm == -1 || stream == -1) { - snd_iprintf(buffer, "N/A\n"); - return; - } - print_pcm_rates(buffer, pcm); - print_pcm_bits(buffer, pcm); - print_pcm_formats(buffer, stream); -} - -static const char *get_jack_connection(u32 cfg) -{ - static char *names[16] = { - "Unknown", "1/8", "1/4", "ATAPI", - "RCA", "Optical","Digital", "Analog", - "DIN", "XLR", "RJ11", "Comb", - NULL, NULL, NULL, "Other" - }; - cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT; - if (names[cfg]) - return names[cfg]; - else - return "UNKNOWN"; -} - -static const char *get_jack_color(u32 cfg) -{ - static char *names[16] = { - "Unknown", "Black", "Grey", "Blue", - "Green", "Red", "Orange", "Yellow", - "Purple", "Pink", NULL, NULL, - NULL, NULL, "White", "Other", - }; - cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT; - if (names[cfg]) - return names[cfg]; - else - return "UNKNOWN"; -} - -static void print_pin_caps(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid, - int *supports_vref) -{ - static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; - unsigned int caps, val; - - caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); - snd_iprintf(buffer, " Pincap 0x%08x:", caps); - if (caps & AC_PINCAP_IN) - snd_iprintf(buffer, " IN"); - if (caps & AC_PINCAP_OUT) - snd_iprintf(buffer, " OUT"); - if (caps & AC_PINCAP_HP_DRV) - snd_iprintf(buffer, " HP"); - if (caps & AC_PINCAP_EAPD) - snd_iprintf(buffer, " EAPD"); - if (caps & AC_PINCAP_PRES_DETECT) - snd_iprintf(buffer, " Detect"); - if (caps & AC_PINCAP_BALANCE) - snd_iprintf(buffer, " Balanced"); - if (caps & AC_PINCAP_HDMI) { - /* Realtek uses this bit as a different meaning */ - if ((codec->vendor_id >> 16) == 0x10ec) - snd_iprintf(buffer, " R/L"); - else { - if (caps & AC_PINCAP_HBR) - snd_iprintf(buffer, " HBR"); - snd_iprintf(buffer, " HDMI"); - } - } - if (caps & AC_PINCAP_DP) - snd_iprintf(buffer, " DP"); - if (caps & AC_PINCAP_TRIG_REQ) - snd_iprintf(buffer, " Trigger"); - if (caps & AC_PINCAP_IMP_SENSE) - snd_iprintf(buffer, " ImpSense"); - snd_iprintf(buffer, "\n"); - if (caps & AC_PINCAP_VREF) { - unsigned int vref = - (caps & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; - snd_iprintf(buffer, " Vref caps:"); - if (vref & AC_PINCAP_VREF_HIZ) - snd_iprintf(buffer, " HIZ"); - if (vref & AC_PINCAP_VREF_50) - snd_iprintf(buffer, " 50"); - if (vref & AC_PINCAP_VREF_GRD) - snd_iprintf(buffer, " GRD"); - if (vref & AC_PINCAP_VREF_80) - snd_iprintf(buffer, " 80"); - if (vref & AC_PINCAP_VREF_100) - snd_iprintf(buffer, " 100"); - snd_iprintf(buffer, "\n"); - *supports_vref = 1; - } else - *supports_vref = 0; - if (caps & AC_PINCAP_EAPD) { - val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_EAPD_BTLENABLE, 0); - snd_iprintf(buffer, " EAPD 0x%x:", val); - if (val & AC_EAPDBTL_BALANCED) - snd_iprintf(buffer, " BALANCED"); - if (val & AC_EAPDBTL_EAPD) - snd_iprintf(buffer, " EAPD"); - if (val & AC_EAPDBTL_LR_SWAP) - snd_iprintf(buffer, " R/L"); - snd_iprintf(buffer, "\n"); - } - caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); - snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, - jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], - snd_hda_get_jack_type(caps), - snd_hda_get_jack_connectivity(caps), - snd_hda_get_jack_location(caps)); - snd_iprintf(buffer, " Conn = %s, Color = %s\n", - get_jack_connection(caps), - get_jack_color(caps)); - /* Default association and sequence values refer to default grouping - * of pin complexes and their sequence within the group. This is used - * for priority and resource allocation. - */ - snd_iprintf(buffer, " DefAssociation = 0x%x, Sequence = 0x%x\n", - (caps & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT, - caps & AC_DEFCFG_SEQUENCE); - if (((caps & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT) & - AC_DEFCFG_MISC_NO_PRESENCE) { - /* Miscellaneous bit indicates external hardware does not - * support presence detection even if the pin complex - * indicates it is supported. - */ - snd_iprintf(buffer, " Misc = NO_PRESENCE\n"); - } -} - -static void print_pin_ctls(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid, - int supports_vref) -{ - unsigned int pinctls; - - pinctls = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls); - if (pinctls & AC_PINCTL_IN_EN) - snd_iprintf(buffer, " IN"); - if (pinctls & AC_PINCTL_OUT_EN) - snd_iprintf(buffer, " OUT"); - if (pinctls & AC_PINCTL_HP_EN) - snd_iprintf(buffer, " HP"); - if (supports_vref) { - int vref = pinctls & AC_PINCTL_VREFEN; - switch (vref) { - case AC_PINCTL_VREF_HIZ: - snd_iprintf(buffer, " VREF_HIZ"); - break; - case AC_PINCTL_VREF_50: - snd_iprintf(buffer, " VREF_50"); - break; - case AC_PINCTL_VREF_GRD: - snd_iprintf(buffer, " VREF_GRD"); - break; - case AC_PINCTL_VREF_80: - snd_iprintf(buffer, " VREF_80"); - break; - case AC_PINCTL_VREF_100: - snd_iprintf(buffer, " VREF_100"); - break; - } - } - snd_iprintf(buffer, "\n"); -} - -static void print_vol_knob(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int cap = snd_hda_param_read(codec, nid, - AC_PAR_VOL_KNB_CAP); - snd_iprintf(buffer, " Volume-Knob: delta=%d, steps=%d, ", - (cap >> 7) & 1, cap & 0x7f); - cap = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); - snd_iprintf(buffer, "direct=%d, val=%d\n", - (cap >> 7) & 1, cap & 0x7f); -} - -static void print_audio_io(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid, - unsigned int wid_type) -{ - int conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); - snd_iprintf(buffer, - " Converter: stream=%d, channel=%d\n", - (conv & AC_CONV_STREAM) >> AC_CONV_STREAM_SHIFT, - conv & AC_CONV_CHANNEL); - - if (wid_type == AC_WID_AUD_IN && (conv & AC_CONV_CHANNEL) == 0) { - int sdi = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_SDI_SELECT, 0); - snd_iprintf(buffer, " SDI-Select: %d\n", - sdi & AC_SDI_SELECT); - } -} - -static void print_digital_conv(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int digi1 = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DIGI_CONVERT_1, 0); - snd_iprintf(buffer, " Digital:"); - if (digi1 & AC_DIG1_ENABLE) - snd_iprintf(buffer, " Enabled"); - if (digi1 & AC_DIG1_V) - snd_iprintf(buffer, " Validity"); - if (digi1 & AC_DIG1_VCFG) - snd_iprintf(buffer, " ValidityCfg"); - if (digi1 & AC_DIG1_EMPHASIS) - snd_iprintf(buffer, " Preemphasis"); - if (digi1 & AC_DIG1_COPYRIGHT) - snd_iprintf(buffer, " Copyright"); - if (digi1 & AC_DIG1_NONAUDIO) - snd_iprintf(buffer, " Non-Audio"); - if (digi1 & AC_DIG1_PROFESSIONAL) - snd_iprintf(buffer, " Pro"); - if (digi1 & AC_DIG1_LEVEL) - snd_iprintf(buffer, " GenLevel"); - snd_iprintf(buffer, "\n"); - snd_iprintf(buffer, " Digital category: 0x%x\n", - (digi1 >> 8) & AC_DIG2_CC); -} - -static const char *get_pwr_state(u32 state) -{ - static const char * const buf[4] = { - "D0", "D1", "D2", "D3" - }; - if (state < 4) - return buf[state]; - return "UNKNOWN"; -} - -static void print_power_state(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - static char *names[] = { - [ilog2(AC_PWRST_D0SUP)] = "D0", - [ilog2(AC_PWRST_D1SUP)] = "D1", - [ilog2(AC_PWRST_D2SUP)] = "D2", - [ilog2(AC_PWRST_D3SUP)] = "D3", - [ilog2(AC_PWRST_D3COLDSUP)] = "D3cold", - [ilog2(AC_PWRST_S3D3COLDSUP)] = "S3D3cold", - [ilog2(AC_PWRST_CLKSTOP)] = "CLKSTOP", - [ilog2(AC_PWRST_EPSS)] = "EPSS", - }; - - int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE); - int pwr = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_POWER_STATE, 0); - if (sup) - snd_iprintf(buffer, " Power states: %s\n", - bits_names(sup, names, ARRAY_SIZE(names))); - - snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", - get_pwr_state(pwr & AC_PWRST_SETTING), - get_pwr_state((pwr & AC_PWRST_ACTUAL) >> - AC_PWRST_ACTUAL_SHIFT)); -} - -static void print_unsol_cap(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - int unsol = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_UNSOLICITED_RESPONSE, 0); - snd_iprintf(buffer, - " Unsolicited: tag=%02x, enabled=%d\n", - unsol & AC_UNSOL_TAG, - (unsol & AC_UNSOL_ENABLED) ? 1 : 0); -} - -static void print_proc_caps(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int proc_caps = snd_hda_param_read(codec, nid, - AC_PAR_PROC_CAP); - snd_iprintf(buffer, " Processing caps: benign=%d, ncoeff=%d\n", - proc_caps & AC_PCAP_BENIGN, - (proc_caps & AC_PCAP_NUM_COEF) >> AC_PCAP_NUM_COEF_SHIFT); -} - -static void print_conn_list(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid, - unsigned int wid_type, hda_nid_t *conn, - int conn_len) -{ - int c, curr = -1; - - if (conn_len > 1 && - wid_type != AC_WID_AUD_MIX && - wid_type != AC_WID_VOL_KNB && - wid_type != AC_WID_POWER) - curr = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CONNECT_SEL, 0); - snd_iprintf(buffer, " Connection: %d\n", conn_len); - if (conn_len > 0) { - snd_iprintf(buffer, " "); - for (c = 0; c < conn_len; c++) { - snd_iprintf(buffer, " 0x%02x", conn[c]); - if (c == curr) - snd_iprintf(buffer, "*"); - } - snd_iprintf(buffer, "\n"); - } -} - -static void print_gpio(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int gpio = - snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); - unsigned int enable, direction, wake, unsol, sticky, data; - int i, max; - snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, " - "unsolicited=%d, wake=%d\n", - gpio & AC_GPIO_IO_COUNT, - (gpio & AC_GPIO_O_COUNT) >> AC_GPIO_O_COUNT_SHIFT, - (gpio & AC_GPIO_I_COUNT) >> AC_GPIO_I_COUNT_SHIFT, - (gpio & AC_GPIO_UNSOLICITED) ? 1 : 0, - (gpio & AC_GPIO_WAKE) ? 1 : 0); - max = gpio & AC_GPIO_IO_COUNT; - if (!max || max > 8) - return; - enable = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_MASK, 0); - direction = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_DIRECTION, 0); - wake = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_WAKE_MASK, 0); - unsol = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK, 0); - sticky = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_STICKY_MASK, 0); - data = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_DATA, 0); - for (i = 0; i < max; ++i) - snd_iprintf(buffer, - " IO[%d]: enable=%d, dir=%d, wake=%d, " - "sticky=%d, data=%d, unsol=%d\n", i, - (enable & (1<mixers); - print_nid_array(buffer, codec, nid, &codec->nids); -} - -static void print_codec_info(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct hda_codec *codec = entry->private_data; - hda_nid_t nid; - int i, nodes; - - snd_iprintf(buffer, "Codec: "); - if (codec->vendor_name && codec->chip_name) - snd_iprintf(buffer, "%s %s\n", - codec->vendor_name, codec->chip_name); - else - snd_iprintf(buffer, "Not Set\n"); - snd_iprintf(buffer, "Address: %d\n", codec->addr); - if (codec->afg) - snd_iprintf(buffer, "AFG Function Id: 0x%x (unsol %u)\n", - codec->afg_function_id, codec->afg_unsol); - if (codec->mfg) - snd_iprintf(buffer, "MFG Function Id: 0x%x (unsol %u)\n", - codec->mfg_function_id, codec->mfg_unsol); - snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id); - snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id); - snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); - - if (codec->mfg) - snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg); - else - snd_iprintf(buffer, "No Modem Function Group found\n"); - - if (! codec->afg) - return; - snd_hda_power_up(codec); - snd_iprintf(buffer, "Default PCM:\n"); - print_pcm_caps(buffer, codec, codec->afg); - snd_iprintf(buffer, "Default Amp-In caps: "); - print_amp_caps(buffer, codec, codec->afg, HDA_INPUT); - snd_iprintf(buffer, "Default Amp-Out caps: "); - print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT); - - nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); - if (! nid || nodes < 0) { - snd_iprintf(buffer, "Invalid AFG subtree\n"); - snd_hda_power_down(codec); - return; - } - - print_gpio(buffer, codec, codec->afg); - if (codec->proc_widget_hook) - codec->proc_widget_hook(buffer, codec, codec->afg); - - for (i = 0; i < nodes; i++, nid++) { - unsigned int wid_caps = - snd_hda_param_read(codec, nid, - AC_PAR_AUDIO_WIDGET_CAP); - unsigned int wid_type = get_wcaps_type(wid_caps); - hda_nid_t conn[HDA_MAX_CONNECTIONS]; - int conn_len = 0; - - snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid, - get_wid_type_name(wid_type), wid_caps); - if (wid_caps & AC_WCAP_STEREO) { - unsigned int chans = get_wcaps_channels(wid_caps); - if (chans == 2) - snd_iprintf(buffer, " Stereo"); - else - snd_iprintf(buffer, " %d-Channels", chans); - } else - snd_iprintf(buffer, " Mono"); - if (wid_caps & AC_WCAP_DIGITAL) - snd_iprintf(buffer, " Digital"); - if (wid_caps & AC_WCAP_IN_AMP) - snd_iprintf(buffer, " Amp-In"); - if (wid_caps & AC_WCAP_OUT_AMP) - snd_iprintf(buffer, " Amp-Out"); - if (wid_caps & AC_WCAP_STRIPE) - snd_iprintf(buffer, " Stripe"); - if (wid_caps & AC_WCAP_LR_SWAP) - snd_iprintf(buffer, " R/L"); - if (wid_caps & AC_WCAP_CP_CAPS) - snd_iprintf(buffer, " CP"); - snd_iprintf(buffer, "\n"); - - print_nid_array(buffer, codec, nid, &codec->mixers); - print_nid_array(buffer, codec, nid, &codec->nids); - print_nid_pcms(buffer, codec, nid); - - /* volume knob is a special widget that always have connection - * list - */ - if (wid_type == AC_WID_VOL_KNB) - wid_caps |= AC_WCAP_CONN_LIST; - - if (wid_caps & AC_WCAP_CONN_LIST) - conn_len = snd_hda_get_raw_connections(codec, nid, conn, - HDA_MAX_CONNECTIONS); - - if (wid_caps & AC_WCAP_IN_AMP) { - snd_iprintf(buffer, " Amp-In caps: "); - print_amp_caps(buffer, codec, nid, HDA_INPUT); - snd_iprintf(buffer, " Amp-In vals: "); - if (wid_type == AC_WID_PIN || - (codec->single_adc_amp && - wid_type == AC_WID_AUD_IN)) - print_amp_vals(buffer, codec, nid, HDA_INPUT, - wid_caps & AC_WCAP_STEREO, - 1); - else - print_amp_vals(buffer, codec, nid, HDA_INPUT, - wid_caps & AC_WCAP_STEREO, - conn_len); - } - if (wid_caps & AC_WCAP_OUT_AMP) { - snd_iprintf(buffer, " Amp-Out caps: "); - print_amp_caps(buffer, codec, nid, HDA_OUTPUT); - snd_iprintf(buffer, " Amp-Out vals: "); - if (wid_type == AC_WID_PIN && - codec->pin_amp_workaround) - print_amp_vals(buffer, codec, nid, HDA_OUTPUT, - wid_caps & AC_WCAP_STEREO, - conn_len); - else - print_amp_vals(buffer, codec, nid, HDA_OUTPUT, - wid_caps & AC_WCAP_STEREO, 1); - } - - switch (wid_type) { - case AC_WID_PIN: { - int supports_vref; - print_pin_caps(buffer, codec, nid, &supports_vref); - print_pin_ctls(buffer, codec, nid, supports_vref); - break; - } - case AC_WID_VOL_KNB: - print_vol_knob(buffer, codec, nid); - break; - case AC_WID_AUD_OUT: - case AC_WID_AUD_IN: - print_audio_io(buffer, codec, nid, wid_type); - if (wid_caps & AC_WCAP_DIGITAL) - print_digital_conv(buffer, codec, nid); - if (wid_caps & AC_WCAP_FORMAT_OVRD) { - snd_iprintf(buffer, " PCM:\n"); - print_pcm_caps(buffer, codec, nid); - } - break; - } - - if (wid_caps & AC_WCAP_UNSOL_CAP) - print_unsol_cap(buffer, codec, nid); - - if (wid_caps & AC_WCAP_POWER) - print_power_state(buffer, codec, nid); - - if (wid_caps & AC_WCAP_DELAY) - snd_iprintf(buffer, " Delay: %d samples\n", - (wid_caps & AC_WCAP_DELAY) >> - AC_WCAP_DELAY_SHIFT); - - if (wid_caps & AC_WCAP_CONN_LIST) - print_conn_list(buffer, codec, nid, wid_type, - conn, conn_len); - - if (wid_caps & AC_WCAP_PROC_WID) - print_proc_caps(buffer, codec, nid); - - if (codec->proc_widget_hook) - codec->proc_widget_hook(buffer, codec, nid); - } - snd_hda_power_down(codec); -} - -/* - * create a proc read - */ -int snd_hda_codec_proc_new(struct hda_codec *codec) -{ - char name[32]; - struct snd_info_entry *entry; - int err; - - snprintf(name, sizeof(name), "codec#%d", codec->addr); - err = snd_card_proc_new(codec->bus->card, name, &entry); - if (err < 0) - return err; - - snd_info_set_text_ops(entry, codec, print_codec_info); - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pci/hda/hda_trace.h b/ANDROID_3.4.5/sound/pci/hda/hda_trace.h deleted file mode 100644 index 9884871d..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/hda_trace.h +++ /dev/null @@ -1,117 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM hda -#define TRACE_INCLUDE_FILE hda_trace - -#if !defined(_TRACE_HDA_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_HDA_H - -#include - -struct hda_bus; -struct hda_codec; - -DECLARE_EVENT_CLASS(hda_cmd, - - TP_PROTO(struct hda_codec *codec, unsigned int val), - - TP_ARGS(codec, val), - - TP_STRUCT__entry( - __field( unsigned int, card ) - __field( unsigned int, addr ) - __field( unsigned int, val ) - ), - - TP_fast_assign( - __entry->card = (codec)->bus->card->number; - __entry->addr = (codec)->addr; - __entry->val = (val); - ), - - TP_printk("[%d:%d] val=%x", __entry->card, __entry->addr, __entry->val) -); - -DEFINE_EVENT(hda_cmd, hda_send_cmd, - TP_PROTO(struct hda_codec *codec, unsigned int val), - TP_ARGS(codec, val) -); - -DEFINE_EVENT(hda_cmd, hda_get_response, - TP_PROTO(struct hda_codec *codec, unsigned int val), - TP_ARGS(codec, val) -); - -TRACE_EVENT(hda_bus_reset, - - TP_PROTO(struct hda_bus *bus), - - TP_ARGS(bus), - - TP_STRUCT__entry( - __field( unsigned int, card ) - ), - - TP_fast_assign( - __entry->card = (bus)->card->number; - ), - - TP_printk("[%d]", __entry->card) -); - -DECLARE_EVENT_CLASS(hda_power, - - TP_PROTO(struct hda_codec *codec), - - TP_ARGS(codec), - - TP_STRUCT__entry( - __field( unsigned int, card ) - __field( unsigned int, addr ) - ), - - TP_fast_assign( - __entry->card = (codec)->bus->card->number; - __entry->addr = (codec)->addr; - ), - - TP_printk("[%d:%d]", __entry->card, __entry->addr) -); - -DEFINE_EVENT(hda_power, hda_power_down, - TP_PROTO(struct hda_codec *codec), - TP_ARGS(codec) -); - -DEFINE_EVENT(hda_power, hda_power_up, - TP_PROTO(struct hda_codec *codec), - TP_ARGS(codec) -); - -TRACE_EVENT(hda_unsol_event, - - TP_PROTO(struct hda_bus *bus, u32 res, u32 res_ex), - - TP_ARGS(bus, res, res_ex), - - TP_STRUCT__entry( - __field( unsigned int, card ) - __field( u32, res ) - __field( u32, res_ex ) - ), - - TP_fast_assign( - __entry->card = (bus)->card->number; - __entry->res = res; - __entry->res_ex = res_ex; - ), - - TP_printk("[%d] res=%x, res_ex=%x", __entry->card, - __entry->res, __entry->res_ex) -); - -#endif /* _TRACE_HDA_H */ - -/* This part must be outside protection */ -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . -#include diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_analog.c b/ANDROID_3.4.5/sound/pci/hda/patch_analog.c deleted file mode 100644 index 71433939..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_analog.c +++ /dev/null @@ -1,5067 +0,0 @@ -/* - * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984, - * AD1986A, AD1988 - * - * Copyright (c) 2005-2007 Takashi Iwai - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" -#include "hda_beep.h" -#include "hda_jack.h" - -struct ad198x_spec { - const struct snd_kcontrol_new *mixers[6]; - int num_mixers; - unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ - const struct hda_verb *init_verbs[6]; /* initialization verbs - * don't forget NULL termination! - */ - unsigned int num_init_verbs; - - /* playback */ - struct hda_multi_out multiout; /* playback set-up - * max_channels, dacs must be set - * dig_out_nid and hp_nid are optional - */ - unsigned int cur_eapd; - unsigned int need_dac_fix; - - const hda_nid_t *alt_dac_nid; - const struct hda_pcm_stream *stream_analog_alt_playback; - int independent_hp; - int num_active_streams; - - /* capture */ - unsigned int num_adc_nids; - const hda_nid_t *adc_nids; - hda_nid_t dig_in_nid; /* digital-in NID; optional */ - - /* capture source */ - const struct hda_input_mux *input_mux; - const hda_nid_t *capsrc_nids; - unsigned int cur_mux[3]; - - /* channel model */ - const struct hda_channel_mode *channel_mode; - int num_channel_mode; - - /* PCM information */ - struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ - - unsigned int spdif_route; - - /* dynamic controls, init_verbs and input_mux */ - struct auto_pin_cfg autocfg; - struct snd_array kctls; - struct hda_input_mux private_imux; - hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; - - unsigned int jack_present: 1; - unsigned int inv_jack_detect: 1;/* inverted jack-detection */ - unsigned int inv_eapd: 1; /* inverted EAPD implementation */ - unsigned int analog_beep: 1; /* analog beep input present */ - unsigned int avoid_init_slave_vol:1; - -#ifdef CONFIG_SND_HDA_POWER_SAVE - struct hda_loopback_check loopback; -#endif - /* for virtual master */ - hda_nid_t vmaster_nid; - const char * const *slave_vols; - const char * const *slave_sws; -}; - -/* - * input MUX handling (common part) - */ -static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - - return snd_hda_input_mux_info(spec->input_mux, uinfo); -} - -static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; - return 0; -} - -static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - spec->capsrc_nids[adc_idx], - &spec->cur_mux[adc_idx]); -} - -/* - * initialization (common callbacks) - */ -static int ad198x_init(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->num_init_verbs; i++) - snd_hda_sequence_write(codec, spec->init_verbs[i]); - return 0; -} - -static const char * const ad_slave_pfxs[] = { - "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Mono", "Speaker", "IEC958", - NULL -}; - -static const char * const ad1988_6stack_fp_slave_pfxs[] = { - "Front", "Surround", "Center", "LFE", "Side", "IEC958", - NULL -}; - -static void ad198x_free_kctls(struct hda_codec *codec); - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -/* additional beep mixers; the actual parameters are overwritten at build */ -static const struct snd_kcontrol_new ad_beep_mixer[] = { - HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), - HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad_beep2_mixer[] = { - HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0, 0, HDA_OUTPUT), - HDA_CODEC_MUTE_BEEP("Digital Beep Playback Switch", 0, 0, HDA_OUTPUT), - { } /* end */ -}; - -#define set_beep_amp(spec, nid, idx, dir) \ - ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ -#else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ -#endif - -static int ad198x_build_controls(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - struct snd_kcontrol *kctl; - unsigned int i; - int err; - - for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - if (spec->multiout.dig_out_nid) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - err = snd_hda_create_spdif_share_sw(codec, - &spec->multiout); - if (err < 0) - return err; - spec->multiout.share_spdif = 1; - } - if (spec->dig_in_nid) { - err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); - if (err < 0) - return err; - } - - /* create beep controls if needed */ -#ifdef CONFIG_SND_HDA_INPUT_BEEP - if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - knew = spec->analog_beep ? ad_beep2_mixer : ad_beep_mixer; - for ( ; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } - } -#endif - - /* if we have no master control, let's create it */ - if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { - unsigned int vmaster_tlv[4]; - snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, - HDA_OUTPUT, vmaster_tlv); - err = __snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, - (spec->slave_vols ? - spec->slave_vols : ad_slave_pfxs), - "Playback Volume", - !spec->avoid_init_slave_vol, NULL); - if (err < 0) - return err; - } - if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { - err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, - (spec->slave_sws ? - spec->slave_sws : ad_slave_pfxs), - "Playback Switch"); - if (err < 0) - return err; - } - - ad198x_free_kctls(codec); /* no longer needed */ - - /* assign Capture Source enums to NID */ - kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); - if (!kctl) - kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); - for (i = 0; kctl && i < kctl->count; i++) { - err = snd_hda_add_nid(codec, kctl, i, spec->capsrc_nids[i]); - if (err < 0) - return err; - } - - /* assign IEC958 enums to NID */ - kctl = snd_hda_find_mixer_ctl(codec, - SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source"); - if (kctl) { - err = snd_hda_add_nid(codec, kctl, 0, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - } - - return 0; -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); -} -#endif - -static void activate_ctl(struct hda_codec *codec, const char *name, int active) -{ - struct snd_kcontrol *ctl = snd_hda_find_mixer_ctl(codec, name); - if (ctl) { - ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - ctl->vd[0].access |= active ? 0 : - SNDRV_CTL_ELEM_ACCESS_INACTIVE; - ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE; - ctl->vd[0].access |= active ? - SNDRV_CTL_ELEM_ACCESS_WRITE : 0; - snd_ctl_notify(codec->bus->card, - SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); - } -} - -static void set_stream_active(struct hda_codec *codec, bool active) -{ - struct ad198x_spec *spec = codec->spec; - if (active) - spec->num_active_streams++; - else - spec->num_active_streams--; - activate_ctl(codec, "Independent HP", spec->num_active_streams == 0); -} - -static int ad1988_independent_hp_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { "OFF", "ON", NULL}; - int index; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - index = uinfo->value.enumerated.item; - if (index >= 2) - index = 1; - strcpy(uinfo->value.enumerated.name, texts[index]); - return 0; -} - -static int ad1988_independent_hp_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - ucontrol->value.enumerated.item[0] = spec->independent_hp; - return 0; -} - -static int ad1988_independent_hp_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - unsigned int select = ucontrol->value.enumerated.item[0]; - if (spec->independent_hp != select) { - spec->independent_hp = select; - if (spec->independent_hp) - spec->multiout.hp_nid = 0; - else - spec->multiout.hp_nid = spec->alt_dac_nid[0]; - return 1; - } - return 0; -} - -/* - * Analog playback callbacks - */ -static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - int err; - set_stream_active(codec, true); - err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); - if (err < 0) { - set_stream_active(codec, false); - return err; - } - return 0; -} - -static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, - format, substream); -} - -static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -static int ad198x_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - set_stream_active(codec, false); - return 0; -} - -static int ad1988_alt_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - if (!spec->independent_hp) - return -EBUSY; - set_stream_active(codec, true); - return 0; -} - -static int ad1988_alt_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - set_stream_active(codec, false); - return 0; -} - -static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .open = ad1988_alt_playback_pcm_open, - .close = ad1988_alt_playback_pcm_close - }, -}; - -/* - * Digital out - */ -static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, - format, substream); -} - -static int ad198x_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); -} - -/* - * Analog capture - */ -static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], - stream_tag, 0, format); - return 0; -} - -static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ad198x_spec *spec = codec->spec; - snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); - return 0; -} - -/* - */ -static const struct hda_pcm_stream ad198x_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 6, /* changed later */ - .nid = 0, /* fill later */ - .ops = { - .open = ad198x_playback_pcm_open, - .prepare = ad198x_playback_pcm_prepare, - .cleanup = ad198x_playback_pcm_cleanup, - .close = ad198x_playback_pcm_close - }, -}; - -static const struct hda_pcm_stream ad198x_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .prepare = ad198x_capture_pcm_prepare, - .cleanup = ad198x_capture_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream ad198x_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .open = ad198x_dig_playback_pcm_open, - .close = ad198x_dig_playback_pcm_close, - .prepare = ad198x_dig_playback_pcm_prepare, - .cleanup = ad198x_dig_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream ad198x_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in alc_build_pcms */ -}; - -static int ad198x_build_pcms(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->num_pcms = 1; - codec->pcm_info = info; - - info->name = "AD198x Analog"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; - - if (spec->multiout.dig_out_nid) { - info++; - codec->num_pcms++; - info->name = "AD198x Digital"; - info->pcm_type = HDA_PCM_TYPE_SPDIF; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; - if (spec->dig_in_nid) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; - } - } - - if (spec->alt_dac_nid && spec->stream_analog_alt_playback) { - codec->num_pcms++; - info = spec->pcm_rec + 2; - info->name = "AD198x Headphone"; - info->pcm_type = HDA_PCM_TYPE_AUDIO; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = - *spec->stream_analog_alt_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->alt_dac_nid[0]; - } - - return 0; -} - -static void ad198x_free_kctls(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - - if (spec->kctls.list) { - struct snd_kcontrol_new *kctl = spec->kctls.list; - int i; - for (i = 0; i < spec->kctls.used; i++) - kfree(kctl[i].name); - } - snd_array_free(&spec->kctls); -} - -static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front, - hda_nid_t hp) -{ - struct ad198x_spec *spec = codec->spec; - if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD) - snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE, - !spec->inv_eapd ? 0x00 : 0x02); - if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD) - snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE, - !spec->inv_eapd ? 0x00 : 0x02); -} - -static void ad198x_power_eapd(struct hda_codec *codec) -{ - /* We currently only handle front, HP */ - switch (codec->vendor_id) { - case 0x11d41882: - case 0x11d4882a: - case 0x11d41884: - case 0x11d41984: - case 0x11d41883: - case 0x11d4184a: - case 0x11d4194a: - case 0x11d4194b: - case 0x11d41988: - case 0x11d4198b: - case 0x11d4989a: - case 0x11d4989b: - ad198x_power_eapd_write(codec, 0x12, 0x11); - break; - case 0x11d41981: - case 0x11d41983: - ad198x_power_eapd_write(codec, 0x05, 0x06); - break; - case 0x11d41986: - ad198x_power_eapd_write(codec, 0x1b, 0x1a); - break; - } -} - -static void ad198x_shutup(struct hda_codec *codec) -{ - snd_hda_shutup_pins(codec); - ad198x_power_eapd(codec); -} - -static void ad198x_free(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - - if (!spec) - return; - - ad198x_shutup(codec); - ad198x_free_kctls(codec); - kfree(spec); - snd_hda_detach_beep_device(codec); -} - -#ifdef CONFIG_PM -static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) -{ - ad198x_shutup(codec); - return 0; -} -#endif - -static const struct hda_codec_ops ad198x_patch_ops = { - .build_controls = ad198x_build_controls, - .build_pcms = ad198x_build_pcms, - .init = ad198x_init, - .free = ad198x_free, -#ifdef CONFIG_SND_HDA_POWER_SAVE - .check_power_status = ad198x_check_power_status, -#endif -#ifdef CONFIG_PM - .suspend = ad198x_suspend, -#endif - .reboot_notify = ad198x_shutup, -}; - - -/* - * EAPD control - * the private value = nid - */ -#define ad198x_eapd_info snd_ctl_boolean_mono_info - -static int ad198x_eapd_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - if (spec->inv_eapd) - ucontrol->value.integer.value[0] = ! spec->cur_eapd; - else - ucontrol->value.integer.value[0] = spec->cur_eapd; - return 0; -} - -static int ad198x_eapd_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - hda_nid_t nid = kcontrol->private_value & 0xff; - unsigned int eapd; - eapd = !!ucontrol->value.integer.value[0]; - if (spec->inv_eapd) - eapd = !eapd; - if (eapd == spec->cur_eapd) - return 0; - spec->cur_eapd = eapd; - snd_hda_codec_write_cache(codec, nid, - 0, AC_VERB_SET_EAPD_BTLENABLE, - eapd ? 0x02 : 0x00); - return 1; -} - -static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - - -/* - * AD1986A specific - */ - -#define AD1986A_SPDIF_OUT 0x02 -#define AD1986A_FRONT_DAC 0x03 -#define AD1986A_SURR_DAC 0x04 -#define AD1986A_CLFE_DAC 0x05 -#define AD1986A_ADC 0x06 - -static const hda_nid_t ad1986a_dac_nids[3] = { - AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC -}; -static const hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC }; -static const hda_nid_t ad1986a_capsrc_nids[1] = { 0x12 }; - -static const struct hda_input_mux ad1986a_capture_source = { - .num_items = 7, - .items = { - { "Mic", 0x0 }, - { "CD", 0x1 }, - { "Aux", 0x3 }, - { "Line", 0x4 }, - { "Mix", 0x5 }, - { "Mono", 0x6 }, - { "Phone", 0x7 }, - }, -}; - - -static const struct hda_bind_ctls ad1986a_bind_pcm_vol = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), - 0 - }, -}; - -static const struct hda_bind_ctls ad1986a_bind_pcm_sw = { - .ops = &snd_hda_bind_sw, - .values = { - HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT), - 0 - }, -}; - -/* - * mixers - */ -static const struct snd_kcontrol_new ad1986a_mixers[] = { - /* - * bind volumes/mutes of 3 DACs as a single PCM control for simplicity - */ - HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol), - HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw), - HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -/* additional mixers for 3stack mode */ -static const struct snd_kcontrol_new ad1986a_3st_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = ad198x_ch_mode_info, - .get = ad198x_ch_mode_get, - .put = ad198x_ch_mode_put, - }, - { } /* end */ -}; - -/* laptop model - 2ch only */ -static const hda_nid_t ad1986a_laptop_dac_nids[1] = { AD1986A_FRONT_DAC }; - -/* master controls both pins 0x1a and 0x1b */ -static const struct hda_bind_ctls ad1986a_laptop_master_vol = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), - 0, - }, -}; - -static const struct hda_bind_ctls ad1986a_laptop_master_sw = { - .ops = &snd_hda_bind_sw, - .values = { - HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), - 0, - }, -}; - -static const struct snd_kcontrol_new ad1986a_laptop_mixers[] = { - HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), - HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), - HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), - /* - HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT), */ - HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { } /* end */ -}; - -/* laptop-eapd model - 2ch only */ - -static const struct hda_input_mux ad1986a_laptop_eapd_capture_source = { - .num_items = 3, - .items = { - { "Mic", 0x0 }, - { "Internal Mic", 0x4 }, - { "Mix", 0x5 }, - }, -}; - -static const struct hda_input_mux ad1986a_automic_capture_source = { - .num_items = 2, - .items = { - { "Mic", 0x0 }, - { "Mix", 0x5 }, - }, -}; - -static const struct snd_kcontrol_new ad1986a_laptop_master_mixers[] = { - HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), - HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { - HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "External Amplifier", - .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, - .info = ad198x_eapd_info, - .get = ad198x_eapd_get, - .put = ad198x_eapd_put, - .private_value = 0x1b, /* port-D */ - }, - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = { - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT), - { } /* end */ -}; - -/* re-connect the mic boost input according to the jack sensing */ -static void ad1986a_automic(struct hda_codec *codec) -{ - unsigned int present; - present = snd_hda_jack_detect(codec, 0x1f); - /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */ - snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL, - present ? 0 : 2); -} - -#define AD1986A_MIC_EVENT 0x36 - -static void ad1986a_automic_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - if ((res >> 26) != AD1986A_MIC_EVENT) - return; - ad1986a_automic(codec); -} - -static int ad1986a_automic_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1986a_automic(codec); - return 0; -} - -/* laptop-automute - 2ch only */ - -static void ad1986a_update_hp(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - unsigned int mute; - - if (spec->jack_present) - mute = HDA_AMP_MUTE; /* mute internal speaker */ - else - /* unmute internal speaker if necessary */ - mute = snd_hda_codec_amp_read(codec, 0x1a, 0, HDA_OUTPUT, 0); - snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, - HDA_AMP_MUTE, mute); -} - -static void ad1986a_hp_automute(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - - spec->jack_present = snd_hda_jack_detect(codec, 0x1a); - if (spec->inv_jack_detect) - spec->jack_present = !spec->jack_present; - ad1986a_update_hp(codec); -} - -#define AD1986A_HP_EVENT 0x37 - -static void ad1986a_hp_unsol_event(struct hda_codec *codec, unsigned int res) -{ - if ((res >> 26) != AD1986A_HP_EVENT) - return; - ad1986a_hp_automute(codec); -} - -static int ad1986a_hp_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1986a_hp_automute(codec); - return 0; -} - -/* bind hp and internal speaker mute (with plug check) */ -static int ad1986a_hp_master_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - long *valp = ucontrol->value.integer.value; - int change; - - change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, - HDA_AMP_MUTE, - valp[0] ? 0 : HDA_AMP_MUTE); - change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, - HDA_AMP_MUTE, - valp[1] ? 0 : HDA_AMP_MUTE); - if (change) - ad1986a_update_hp(codec); - return change; -} - -static const struct snd_kcontrol_new ad1986a_automute_master_mixers[] = { - HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .subdevice = HDA_SUBDEV_AMP_FLAG, - .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_amp_switch_get, - .put = ad1986a_hp_master_sw_put, - .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), - }, - { } /* end */ -}; - - -/* - * initialization verbs - */ -static const struct hda_verb ad1986a_init_verbs[] = { - /* Front, Surround, CLFE DAC; mute as default */ - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Downmix - off */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* HP, Line-Out, Surround, CLFE selectors */ - {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Mono selector */ - {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Mic selector: Mic 1/2 pin */ - {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Line-in selector: Line-in */ - {0x10, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Mic 1/2 swap */ - {0x11, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Record selector: mic */ - {0x12, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Mic, Phone, CD, Aux, Line-In amp; mute as default */ - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* PC beep */ - {0x18, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */ - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* HP Pin */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, - /* Front, Surround, CLFE Pins */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* Mono Pin */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* Mic Pin */ - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - /* Line, Aux, CD, Beep-In Pin */ - {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - { } /* end */ -}; - -static const struct hda_verb ad1986a_ch2_init[] = { - /* Surround out -> Line In */ - { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - /* Line-in selectors */ - { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 }, - /* CLFE -> Mic in */ - { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, - { } /* end */ -}; - -static const struct hda_verb ad1986a_ch4_init[] = { - /* Surround out -> Surround */ - { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, - /* CLFE -> Mic in */ - { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, - { } /* end */ -}; - -static const struct hda_verb ad1986a_ch6_init[] = { - /* Surround out -> Surround out */ - { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, - /* CLFE -> CLFE */ - { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 }, - { } /* end */ -}; - -static const struct hda_channel_mode ad1986a_modes[3] = { - { 2, ad1986a_ch2_init }, - { 4, ad1986a_ch4_init }, - { 6, ad1986a_ch6_init }, -}; - -/* eapd initialization */ -static const struct hda_verb ad1986a_eapd_init_verbs[] = { - {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, - {} -}; - -static const struct hda_verb ad1986a_automic_verbs[] = { - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - /*{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},*/ - {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x1f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_MIC_EVENT}, - {} -}; - -/* Ultra initialization */ -static const struct hda_verb ad1986a_ultra_init[] = { - /* eapd initialization */ - { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, - /* CLFE -> Mic in */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 }, - { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, - { } /* end */ -}; - -/* pin sensing on HP jack */ -static const struct hda_verb ad1986a_hp_init_verbs[] = { - {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1986A_HP_EVENT}, - {} -}; - -static void ad1986a_samsung_p50_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - switch (res >> 26) { - case AD1986A_HP_EVENT: - ad1986a_hp_automute(codec); - break; - case AD1986A_MIC_EVENT: - ad1986a_automic(codec); - break; - } -} - -static int ad1986a_samsung_p50_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1986a_hp_automute(codec); - ad1986a_automic(codec); - return 0; -} - - -/* models */ -enum { - AD1986A_6STACK, - AD1986A_3STACK, - AD1986A_LAPTOP, - AD1986A_LAPTOP_EAPD, - AD1986A_LAPTOP_AUTOMUTE, - AD1986A_ULTRA, - AD1986A_SAMSUNG, - AD1986A_SAMSUNG_P50, - AD1986A_MODELS -}; - -static const char * const ad1986a_models[AD1986A_MODELS] = { - [AD1986A_6STACK] = "6stack", - [AD1986A_3STACK] = "3stack", - [AD1986A_LAPTOP] = "laptop", - [AD1986A_LAPTOP_EAPD] = "laptop-eapd", - [AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute", - [AD1986A_ULTRA] = "ultra", - [AD1986A_SAMSUNG] = "samsung", - [AD1986A_SAMSUNG_P50] = "samsung-p50", -}; - -static const struct snd_pci_quirk ad1986a_cfg_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD), - SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD), - SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD), - SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD), - SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD), - SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD), - SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD), - SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD), - SND_PCI_QUIRK(0x1043, 0x1443, "ASUS VX1", AD1986A_LAPTOP), - SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK), - SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK), - SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP), - SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK), - SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK), - SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK), - SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK), - SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK), - SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), - SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), - SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50), - SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA), - SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_SAMSUNG), - SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK), - SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP), - SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK), - SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_AUTOMUTE), - SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP), - {} -}; - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list ad1986a_loopbacks[] = { - { 0x13, HDA_OUTPUT, 0 }, /* Mic */ - { 0x14, HDA_OUTPUT, 0 }, /* Phone */ - { 0x15, HDA_OUTPUT, 0 }, /* CD */ - { 0x16, HDA_OUTPUT, 0 }, /* Aux */ - { 0x17, HDA_OUTPUT, 0 }, /* Line */ - { } /* end */ -}; -#endif - -static int is_jack_available(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int conf = snd_hda_codec_get_pincfg(codec, nid); - return get_defcfg_connect(conf) != AC_JACK_PORT_NONE; -} - -static int patch_ad1986a(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int err, board_config; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - err = snd_hda_attach_beep_device(codec, 0x19); - if (err < 0) { - ad198x_free(codec); - return err; - } - set_beep_amp(spec, 0x18, 0, HDA_OUTPUT); - - spec->multiout.max_channels = 6; - spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); - spec->multiout.dac_nids = ad1986a_dac_nids; - spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; - spec->num_adc_nids = 1; - spec->adc_nids = ad1986a_adc_nids; - spec->capsrc_nids = ad1986a_capsrc_nids; - spec->input_mux = &ad1986a_capture_source; - spec->num_mixers = 1; - spec->mixers[0] = ad1986a_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1986a_init_verbs; -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->loopback.amplist = ad1986a_loopbacks; -#endif - spec->vmaster_nid = 0x1b; - spec->inv_eapd = 1; /* AD1986A has the inverted EAPD implementation */ - - codec->patch_ops = ad198x_patch_ops; - - /* override some parameters */ - board_config = snd_hda_check_board_config(codec, AD1986A_MODELS, - ad1986a_models, - ad1986a_cfg_tbl); - switch (board_config) { - case AD1986A_3STACK: - spec->num_mixers = 2; - spec->mixers[1] = ad1986a_3st_mixers; - spec->num_init_verbs = 2; - spec->init_verbs[1] = ad1986a_ch2_init; - spec->channel_mode = ad1986a_modes; - spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); - spec->need_dac_fix = 1; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - break; - case AD1986A_LAPTOP: - spec->mixers[0] = ad1986a_laptop_mixers; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = ad1986a_laptop_dac_nids; - break; - case AD1986A_LAPTOP_EAPD: - spec->num_mixers = 3; - spec->mixers[0] = ad1986a_laptop_master_mixers; - spec->mixers[1] = ad1986a_laptop_eapd_mixers; - spec->mixers[2] = ad1986a_laptop_intmic_mixers; - spec->num_init_verbs = 2; - spec->init_verbs[1] = ad1986a_eapd_init_verbs; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = ad1986a_laptop_dac_nids; - if (!is_jack_available(codec, 0x25)) - spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1986a_laptop_eapd_capture_source; - break; - case AD1986A_SAMSUNG: - spec->num_mixers = 2; - spec->mixers[0] = ad1986a_laptop_master_mixers; - spec->mixers[1] = ad1986a_laptop_eapd_mixers; - spec->num_init_verbs = 3; - spec->init_verbs[1] = ad1986a_eapd_init_verbs; - spec->init_verbs[2] = ad1986a_automic_verbs; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = ad1986a_laptop_dac_nids; - if (!is_jack_available(codec, 0x25)) - spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1986a_automic_capture_source; - codec->patch_ops.unsol_event = ad1986a_automic_unsol_event; - codec->patch_ops.init = ad1986a_automic_init; - break; - case AD1986A_SAMSUNG_P50: - spec->num_mixers = 2; - spec->mixers[0] = ad1986a_automute_master_mixers; - spec->mixers[1] = ad1986a_laptop_eapd_mixers; - spec->num_init_verbs = 4; - spec->init_verbs[1] = ad1986a_eapd_init_verbs; - spec->init_verbs[2] = ad1986a_automic_verbs; - spec->init_verbs[3] = ad1986a_hp_init_verbs; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = ad1986a_laptop_dac_nids; - if (!is_jack_available(codec, 0x25)) - spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1986a_automic_capture_source; - codec->patch_ops.unsol_event = ad1986a_samsung_p50_unsol_event; - codec->patch_ops.init = ad1986a_samsung_p50_init; - break; - case AD1986A_LAPTOP_AUTOMUTE: - spec->num_mixers = 3; - spec->mixers[0] = ad1986a_automute_master_mixers; - spec->mixers[1] = ad1986a_laptop_eapd_mixers; - spec->mixers[2] = ad1986a_laptop_intmic_mixers; - spec->num_init_verbs = 3; - spec->init_verbs[1] = ad1986a_eapd_init_verbs; - spec->init_verbs[2] = ad1986a_hp_init_verbs; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = ad1986a_laptop_dac_nids; - if (!is_jack_available(codec, 0x25)) - spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1986a_laptop_eapd_capture_source; - codec->patch_ops.unsol_event = ad1986a_hp_unsol_event; - codec->patch_ops.init = ad1986a_hp_init; - /* Lenovo N100 seems to report the reversed bit - * for HP jack-sensing - */ - spec->inv_jack_detect = 1; - break; - case AD1986A_ULTRA: - spec->mixers[0] = ad1986a_laptop_eapd_mixers; - spec->num_init_verbs = 2; - spec->init_verbs[1] = ad1986a_ultra_init; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = ad1986a_laptop_dac_nids; - spec->multiout.dig_out_nid = 0; - break; - } - - /* AD1986A has a hardware problem that it can't share a stream - * with multiple output pins. The copy of front to surrounds - * causes noisy or silent outputs at a certain timing, e.g. - * changing the volume. - * So, let's disable the shared stream. - */ - spec->multiout.no_share_stream = 1; - - codec->no_trigger_sense = 1; - codec->no_sticky_stream = 1; - - return 0; -} - -/* - * AD1983 specific - */ - -#define AD1983_SPDIF_OUT 0x02 -#define AD1983_DAC 0x03 -#define AD1983_ADC 0x04 - -static const hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; -static const hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC }; -static const hda_nid_t ad1983_capsrc_nids[1] = { 0x15 }; - -static const struct hda_input_mux ad1983_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Line", 0x1 }, - { "Mix", 0x2 }, - { "Mix Mono", 0x3 }, - }, -}; - -/* - * SPDIF playback route - */ -static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { "PCM", "ADC" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - - ucontrol->value.enumerated.item[0] = spec->spdif_route; - return 0; -} - -static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - - if (ucontrol->value.enumerated.item[0] > 1) - return -EINVAL; - if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { - spec->spdif_route = ucontrol->value.enumerated.item[0]; - snd_hda_codec_write_cache(codec, spec->multiout.dig_out_nid, 0, - AC_VERB_SET_CONNECT_SEL, - spec->spdif_route); - return 1; - } - return 0; -} - -static const struct snd_kcontrol_new ad1983_mixers[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, - }, - { } /* end */ -}; - -static const struct hda_verb ad1983_init_verbs[] = { - /* Front, HP, Mono; mute as default */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Beep, PCM, Mic, Line-In: mute */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Front, HP selectors; from Mix */ - {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, - /* Mono selector; from Mix */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, - /* Mic selector; Mic */ - {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Line-in selector: Line-in */ - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Mic boost: 0dB */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - /* Record selector: mic */ - {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* SPDIF route: PCM */ - {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Front Pin */ - {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* HP Pin */ - {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, - /* Mono Pin */ - {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* Mic Pin */ - {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - /* Line Pin */ - {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - { } /* end */ -}; - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list ad1983_loopbacks[] = { - { 0x12, HDA_OUTPUT, 0 }, /* Mic */ - { 0x13, HDA_OUTPUT, 0 }, /* Line */ - { } /* end */ -}; -#endif - -static int patch_ad1983(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - err = snd_hda_attach_beep_device(codec, 0x10); - if (err < 0) { - ad198x_free(codec); - return err; - } - set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); - spec->multiout.dac_nids = ad1983_dac_nids; - spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; - spec->num_adc_nids = 1; - spec->adc_nids = ad1983_adc_nids; - spec->capsrc_nids = ad1983_capsrc_nids; - spec->input_mux = &ad1983_capture_source; - spec->num_mixers = 1; - spec->mixers[0] = ad1983_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1983_init_verbs; - spec->spdif_route = 0; -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->loopback.amplist = ad1983_loopbacks; -#endif - spec->vmaster_nid = 0x05; - - codec->patch_ops = ad198x_patch_ops; - - codec->no_trigger_sense = 1; - codec->no_sticky_stream = 1; - - return 0; -} - - -/* - * AD1981 HD specific - */ - -#define AD1981_SPDIF_OUT 0x02 -#define AD1981_DAC 0x03 -#define AD1981_ADC 0x04 - -static const hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; -static const hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC }; -static const hda_nid_t ad1981_capsrc_nids[1] = { 0x15 }; - -/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ -static const struct hda_input_mux ad1981_capture_source = { - .num_items = 7, - .items = { - { "Front Mic", 0x0 }, - { "Line", 0x1 }, - { "Mix", 0x2 }, - { "Mix Mono", 0x3 }, - { "CD", 0x4 }, - { "Mic", 0x6 }, - { "Aux", 0x7 }, - }, -}; - -static const struct snd_kcontrol_new ad1981_mixers[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - /* identical with AD1983 */ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, - }, - { } /* end */ -}; - -static const struct hda_verb ad1981_init_verbs[] = { - /* Front, HP, Mono; mute as default */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Front, HP selectors; from Mix */ - {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, - /* Mono selector; from Mix */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, - /* Mic Mixer; select Front Mic */ - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* Mic boost: 0dB */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* Record selector: Front mic */ - {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - /* SPDIF route: PCM */ - {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Front Pin */ - {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* HP Pin */ - {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, - /* Mono Pin */ - {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - /* Front & Rear Mic Pins */ - {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - /* Line Pin */ - {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - /* Digital Beep */ - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Line-Out as Input: disabled */ - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - { } /* end */ -}; - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list ad1981_loopbacks[] = { - { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ - { 0x13, HDA_OUTPUT, 0 }, /* Line */ - { 0x1b, HDA_OUTPUT, 0 }, /* Aux */ - { 0x1c, HDA_OUTPUT, 0 }, /* Mic */ - { 0x1d, HDA_OUTPUT, 0 }, /* CD */ - { } /* end */ -}; -#endif - -/* - * Patch for HP nx6320 - * - * nx6320 uses EAPD in the reverse way - EAPD-on means the internal - * speaker output enabled _and_ mute-LED off. - */ - -#define AD1981_HP_EVENT 0x37 -#define AD1981_MIC_EVENT 0x38 - -static const struct hda_verb ad1981_hp_init_verbs[] = { - {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x00 }, /* default off */ - /* pin sensing on HP and Mic jacks */ - {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, - {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, - {} -}; - -/* turn on/off EAPD (+ mute HP) as a master switch */ -static int ad1981_hp_master_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - - if (! ad198x_eapd_put(kcontrol, ucontrol)) - return 0; - /* change speaker pin appropriately */ - snd_hda_codec_write(codec, 0x05, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - spec->cur_eapd ? PIN_OUT : 0); - /* toggle HP mute appropriately */ - snd_hda_codec_amp_stereo(codec, 0x06, HDA_OUTPUT, 0, - HDA_AMP_MUTE, - spec->cur_eapd ? 0 : HDA_AMP_MUTE); - return 1; -} - -/* bind volumes of both NID 0x05 and 0x06 */ -static const struct hda_bind_ctls ad1981_hp_bind_master_vol = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x06, 3, 0, HDA_OUTPUT), - 0 - }, -}; - -/* mute internal speaker if HP is plugged */ -static void ad1981_hp_automute(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x06); - snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, - HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); -} - -/* toggle input of built-in and mic jack appropriately */ -static void ad1981_hp_automic(struct hda_codec *codec) -{ - static const struct hda_verb mic_jack_on[] = { - {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {} - }; - static const struct hda_verb mic_jack_off[] = { - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {} - }; - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x08); - if (present) - snd_hda_sequence_write(codec, mic_jack_on); - else - snd_hda_sequence_write(codec, mic_jack_off); -} - -/* unsolicited event for HP jack sensing */ -static void ad1981_hp_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - res >>= 26; - switch (res) { - case AD1981_HP_EVENT: - ad1981_hp_automute(codec); - break; - case AD1981_MIC_EVENT: - ad1981_hp_automic(codec); - break; - } -} - -static const struct hda_input_mux ad1981_hp_capture_source = { - .num_items = 3, - .items = { - { "Mic", 0x0 }, - { "Docking-Station", 0x1 }, - { "Mix", 0x2 }, - }, -}; - -static const struct snd_kcontrol_new ad1981_hp_mixers[] = { - HDA_BIND_VOL("Master Playback Volume", &ad1981_hp_bind_master_vol), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .subdevice = HDA_SUBDEV_NID_FLAG | 0x05, - .name = "Master Playback Switch", - .info = ad198x_eapd_info, - .get = ad198x_eapd_get, - .put = ad1981_hp_master_sw_put, - .private_value = 0x05, - }, - HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), -#if 0 - /* FIXME: analog mic/line loopback doesn't work with my tests... - * (although recording is OK) - */ - HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), - /* FIXME: does this laptop have analog CD connection? */ - HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), -#endif - HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x18, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { } /* end */ -}; - -/* initialize jack-sensing, too */ -static int ad1981_hp_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1981_hp_automute(codec); - ad1981_hp_automic(codec); - return 0; -} - -/* configuration for Toshiba Laptops */ -static const struct hda_verb ad1981_toshiba_init_verbs[] = { - {0x05, AC_VERB_SET_EAPD_BTLENABLE, 0x01 }, /* default on */ - /* pin sensing on HP and Mic jacks */ - {0x06, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_HP_EVENT}, - {0x08, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1981_MIC_EVENT}, - {} -}; - -static const struct snd_kcontrol_new ad1981_toshiba_mixers[] = { - HDA_CODEC_VOLUME("Amp Volume", 0x1a, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Amp Switch", 0x1a, 0x0, HDA_OUTPUT), - { } -}; - -/* configuration for Lenovo Thinkpad T60 */ -static const struct snd_kcontrol_new ad1981_thinkpad_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - /* identical with AD1983 */ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, - }, - { } /* end */ -}; - -static const struct hda_input_mux ad1981_thinkpad_capture_source = { - .num_items = 3, - .items = { - { "Mic", 0x0 }, - { "Mix", 0x2 }, - { "CD", 0x4 }, - }, -}; - -/* models */ -enum { - AD1981_BASIC, - AD1981_HP, - AD1981_THINKPAD, - AD1981_TOSHIBA, - AD1981_MODELS -}; - -static const char * const ad1981_models[AD1981_MODELS] = { - [AD1981_HP] = "hp", - [AD1981_THINKPAD] = "thinkpad", - [AD1981_BASIC] = "basic", - [AD1981_TOSHIBA] = "toshiba" -}; - -static const struct snd_pci_quirk ad1981_cfg_tbl[] = { - SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD), - SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD), - /* All HP models */ - SND_PCI_QUIRK_VENDOR(0x103c, "HP nx", AD1981_HP), - SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA), - /* Lenovo Thinkpad T60/X60/Z6xx */ - SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1981_THINKPAD), - /* HP nx6320 (reversed SSID, H/W bug) */ - SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP), - {} -}; - -static int patch_ad1981(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int err, board_config; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - err = snd_hda_attach_beep_device(codec, 0x10); - if (err < 0) { - ad198x_free(codec); - return err; - } - set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); - spec->multiout.dac_nids = ad1981_dac_nids; - spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; - spec->num_adc_nids = 1; - spec->adc_nids = ad1981_adc_nids; - spec->capsrc_nids = ad1981_capsrc_nids; - spec->input_mux = &ad1981_capture_source; - spec->num_mixers = 1; - spec->mixers[0] = ad1981_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1981_init_verbs; - spec->spdif_route = 0; -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->loopback.amplist = ad1981_loopbacks; -#endif - spec->vmaster_nid = 0x05; - - codec->patch_ops = ad198x_patch_ops; - - /* override some parameters */ - board_config = snd_hda_check_board_config(codec, AD1981_MODELS, - ad1981_models, - ad1981_cfg_tbl); - switch (board_config) { - case AD1981_HP: - spec->mixers[0] = ad1981_hp_mixers; - spec->num_init_verbs = 2; - spec->init_verbs[1] = ad1981_hp_init_verbs; - if (!is_jack_available(codec, 0x0a)) - spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1981_hp_capture_source; - - codec->patch_ops.init = ad1981_hp_init; - codec->patch_ops.unsol_event = ad1981_hp_unsol_event; - /* set the upper-limit for mixer amp to 0dB for avoiding the - * possible damage by overloading - */ - snd_hda_override_amp_caps(codec, 0x11, 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 AD1981_THINKPAD: - spec->mixers[0] = ad1981_thinkpad_mixers; - spec->input_mux = &ad1981_thinkpad_capture_source; - /* set the upper-limit for mixer amp to 0dB for avoiding the - * possible damage by overloading - */ - snd_hda_override_amp_caps(codec, 0x11, 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 AD1981_TOSHIBA: - spec->mixers[0] = ad1981_hp_mixers; - spec->mixers[1] = ad1981_toshiba_mixers; - spec->num_init_verbs = 2; - spec->init_verbs[1] = ad1981_toshiba_init_verbs; - spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1981_hp_capture_source; - codec->patch_ops.init = ad1981_hp_init; - codec->patch_ops.unsol_event = ad1981_hp_unsol_event; - break; - } - - codec->no_trigger_sense = 1; - codec->no_sticky_stream = 1; - - return 0; -} - - -/* - * AD1988 - * - * Output pins and routes - * - * Pin Mix Sel DAC (*) - * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06 - * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06 - * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a - * port-D 0x12 (mute/hp) <- 0x29 <- 04 - * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a - * port-F 0x16 (mute) <- 0x2a <- 06 - * port-G 0x24 (mute) <- 0x27 <- 05 - * port-H 0x25 (mute) <- 0x28 <- 0a - * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06 - * - * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah - * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug. - * - * Input pins and routes - * - * pin boost mix input # / adc input # - * port-A 0x11 -> 0x38 -> mix 2, ADC 0 - * port-B 0x14 -> 0x39 -> mix 0, ADC 1 - * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2 - * port-D 0x12 -> 0x3d -> mix 3, ADC 8 - * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4 - * port-F 0x16 -> 0x3b -> mix 5, ADC 3 - * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6 - * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7 - * - * - * DAC assignment - * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03 - * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03 - * - * Inputs of Analog Mix (0x20) - * 0:Port-B (front mic) - * 1:Port-C/G/H (line-in) - * 2:Port-A - * 3:Port-D (line-in/2) - * 4:Port-E/G/H (mic-in) - * 5:Port-F (mic2-in) - * 6:CD - * 7:Beep - * - * ADC selection - * 0:Port-A - * 1:Port-B (front mic-in) - * 2:Port-C (line-in) - * 3:Port-F (mic2-in) - * 4:Port-E (mic-in) - * 5:CD - * 6:Port-G - * 7:Port-H - * 8:Port-D (line-in/2) - * 9:Mix - * - * Proposed pin assignments by the datasheet - * - * 6-stack - * Port-A front headphone - * B front mic-in - * C rear line-in - * D rear front-out - * E rear mic-in - * F rear surround - * G rear CLFE - * H rear side - * - * 3-stack - * Port-A front headphone - * B front mic - * C rear line-in/surround - * D rear front-out - * E rear mic-in/CLFE - * - * laptop - * Port-A headphone - * B mic-in - * C docking station - * D internal speaker (with EAPD) - * E/F quad mic array - */ - - -/* models */ -enum { - AD1988_6STACK, - AD1988_6STACK_DIG, - AD1988_3STACK, - AD1988_3STACK_DIG, - AD1988_LAPTOP, - AD1988_LAPTOP_DIG, - AD1988_AUTO, - AD1988_MODEL_LAST, -}; - -/* reivision id to check workarounds */ -#define AD1988A_REV2 0x100200 - -#define is_rev2(codec) \ - ((codec)->vendor_id == 0x11d41988 && \ - (codec)->revision_id == AD1988A_REV2) - -/* - * mixers - */ - -static const hda_nid_t ad1988_6stack_dac_nids[4] = { - 0x04, 0x06, 0x05, 0x0a -}; - -static const hda_nid_t ad1988_3stack_dac_nids[3] = { - 0x04, 0x05, 0x0a -}; - -/* for AD1988A revision-2, DAC2-4 are swapped */ -static const hda_nid_t ad1988_6stack_dac_nids_rev2[4] = { - 0x04, 0x05, 0x0a, 0x06 -}; - -static const hda_nid_t ad1988_alt_dac_nid[1] = { - 0x03 -}; - -static const hda_nid_t ad1988_3stack_dac_nids_rev2[3] = { - 0x04, 0x0a, 0x06 -}; - -static const hda_nid_t ad1988_adc_nids[3] = { - 0x08, 0x09, 0x0f -}; - -static const hda_nid_t ad1988_capsrc_nids[3] = { - 0x0c, 0x0d, 0x0e -}; - -#define AD1988_SPDIF_OUT 0x02 -#define AD1988_SPDIF_OUT_HDMI 0x0b -#define AD1988_SPDIF_IN 0x07 - -static const hda_nid_t ad1989b_slave_dig_outs[] = { - AD1988_SPDIF_OUT, AD1988_SPDIF_OUT_HDMI, 0 -}; - -static const struct hda_input_mux ad1988_6stack_capture_source = { - .num_items = 5, - .items = { - { "Front Mic", 0x1 }, /* port-B */ - { "Line", 0x2 }, /* port-C */ - { "Mic", 0x4 }, /* port-E */ - { "CD", 0x5 }, - { "Mix", 0x9 }, - }, -}; - -static const struct hda_input_mux ad1988_laptop_capture_source = { - .num_items = 3, - .items = { - { "Mic/Line", 0x1 }, /* port-B */ - { "CD", 0x5 }, - { "Mix", 0x9 }, - }, -}; - -/* - */ -static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, - spec->num_channel_mode); -} - -static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, spec->multiout.max_channels); -} - -static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ad198x_spec *spec = codec->spec; - int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - &spec->multiout.max_channels); - if (err >= 0 && spec->need_dac_fix) - spec->multiout.num_dacs = spec->multiout.max_channels / 2; - return err; -} - -static const struct snd_kcontrol_new ad1988_hp_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Independent HP", - .info = ad1988_independent_hp_info, - .get = ad1988_independent_hp_get, - .put = ad1988_independent_hp_put, - }, - { } /* end */ -}; - -/* 6-stack mode */ -static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT), - HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), - HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), - - HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), - - HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -/* 3-stack mode */ -static const struct snd_kcontrol_new ad1988_3stack_mixers1[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT), - HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), - HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), - - HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), - - HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = ad198x_ch_mode_info, - .get = ad198x_ch_mode_get, - .put = ad198x_ch_mode_put, - }, - - { } /* end */ -}; - -/* laptop mode */ -static const struct snd_kcontrol_new ad1988_laptop_mixers[] = { - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT), - HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), - - HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), - - HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME("Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), - - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "External Amplifier", - .subdevice = HDA_SUBDEV_NID_FLAG | 0x12, - .info = ad198x_eapd_info, - .get = ad198x_eapd_get, - .put = ad198x_eapd_put, - .private_value = 0x12, /* port-D */ - }, - - { } /* end */ -}; - -/* capture */ -static const struct snd_kcontrol_new ad1988_capture_mixers[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 3, - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { } /* end */ -}; - -static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "PCM", "ADC1", "ADC2", "ADC3" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= 4) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int sel; - - sel = snd_hda_codec_read(codec, 0x1d, 0, AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_INPUT); - if (!(sel & 0x80)) - ucontrol->value.enumerated.item[0] = 0; - else { - sel = snd_hda_codec_read(codec, 0x0b, 0, - AC_VERB_GET_CONNECT_SEL, 0); - if (sel < 3) - sel++; - else - sel = 0; - ucontrol->value.enumerated.item[0] = sel; - } - return 0; -} - -static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int val, sel; - int change; - - val = ucontrol->value.enumerated.item[0]; - if (val > 3) - return -EINVAL; - if (!val) { - sel = snd_hda_codec_read(codec, 0x1d, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_INPUT); - change = sel & 0x80; - if (change) { - snd_hda_codec_write_cache(codec, 0x1d, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(0)); - snd_hda_codec_write_cache(codec, 0x1d, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_MUTE(1)); - } - } else { - sel = snd_hda_codec_read(codec, 0x1d, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_INPUT | 0x01); - change = sel & 0x80; - if (change) { - snd_hda_codec_write_cache(codec, 0x1d, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_MUTE(0)); - snd_hda_codec_write_cache(codec, 0x1d, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(1)); - } - sel = snd_hda_codec_read(codec, 0x0b, 0, - AC_VERB_GET_CONNECT_SEL, 0) + 1; - change |= sel != val; - if (change) - snd_hda_codec_write_cache(codec, 0x0b, 0, - AC_VERB_SET_CONNECT_SEL, - val - 1); - } - return change; -} - -static const struct snd_kcontrol_new ad1988_spdif_out_mixers[] = { - HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Playback Source", - .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b, - .info = ad1988_spdif_playback_source_info, - .get = ad1988_spdif_playback_source_get, - .put = ad1988_spdif_playback_source_put, - }, - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1988_spdif_in_mixers[] = { - HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1989_spdif_out_mixers[] = { - HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("HDMI Playback Volume", 0x1d, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -/* - * initialization verbs - */ - -/* - * for 6-stack (+dig) - */ -static const struct hda_verb ad1988_6stack_init_verbs[] = { - /* Front, Surround, CLFE, side DAC; unmute as default */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Port-A front headphon path */ - {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - /* Port-D line-out path */ - {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Port-F surround path */ - {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Port-G CLFE path */ - {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Port-H side path */ - {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Mono out path */ - {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ - /* Port-B front mic-in path */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Port-C line-in path */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Port-E mic-in path */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Analog CD Input */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* Analog Mix output amp */ - {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ - - { } -}; - -static const struct hda_verb ad1988_6stack_fp_init_verbs[] = { - /* Headphone; unmute as default */ - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Port-A front headphon path */ - {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - - { } -}; - -static const struct hda_verb ad1988_capture_init_verbs[] = { - /* mute analog mix */ - {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)}, - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, - /* select ADCs - front-mic */ - {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, - - { } -}; - -static const struct hda_verb ad1988_spdif_init_verbs[] = { - /* SPDIF out sel */ - {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */ - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* SPDIF out pin */ - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ - - { } -}; - -static const struct hda_verb ad1988_spdif_in_init_verbs[] = { - /* unmute SPDIF input pin */ - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - { } -}; - -/* AD1989 has no ADC -> SPDIF route */ -static const struct hda_verb ad1989_spdif_init_verbs[] = { - /* SPDIF-1 out pin */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ - /* SPDIF-2/HDMI out pin */ - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ - { } -}; - -/* - * verbs for 3stack (+dig) - */ -static const struct hda_verb ad1988_3stack_ch2_init[] = { - /* set port-C to line-in */ - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - /* set port-E to mic-in */ - { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { } /* end */ -}; - -static const struct hda_verb ad1988_3stack_ch6_init[] = { - /* set port-C to surround out */ - { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - /* set port-E to CLFE out */ - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { } /* end */ -}; - -static const struct hda_channel_mode ad1988_3stack_modes[2] = { - { 2, ad1988_3stack_ch2_init }, - { 6, ad1988_3stack_ch6_init }, -}; - -static const struct hda_verb ad1988_3stack_init_verbs[] = { - /* Front, Surround, CLFE, side DAC; unmute as default */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Port-A front headphon path */ - {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - /* Port-D line-out path */ - {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Mono out path */ - {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ - /* Port-B front mic-in path */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Port-C line-in/surround path - 6ch mode as default */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */ - {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* Port-E mic-in/CLFE path - 6ch mode as default */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */ - {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* mute analog mix */ - {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)}, - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, - /* select ADCs - front-mic */ - {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* Analog Mix output amp */ - {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ - { } -}; - -/* - * verbs for laptop mode (+dig) - */ -static const struct hda_verb ad1988_laptop_hp_on[] = { - /* unmute port-A and mute port-D */ - { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; -static const struct hda_verb ad1988_laptop_hp_off[] = { - /* mute port-A and unmute port-D */ - { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { } /* end */ -}; - -#define AD1988_HP_EVENT 0x01 - -static const struct hda_verb ad1988_laptop_init_verbs[] = { - /* Front, Surround, CLFE, side DAC; unmute as default */ - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Port-A front headphon path */ - {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - /* unsolicited event for pin-sense */ - {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT }, - /* Port-D line-out path + EAPD */ - {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */ - /* Mono out path */ - {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ - /* Port-B mic-in path */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Port-C docking station - try to output */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* mute analog mix */ - {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)}, - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, - /* select ADCs - mic */ - {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* Analog Mix output amp */ - {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ - { } -}; - -static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) -{ - if ((res >> 26) != AD1988_HP_EVENT) - return; - if (snd_hda_jack_detect(codec, 0x11)) - snd_hda_sequence_write(codec, ad1988_laptop_hp_on); - else - snd_hda_sequence_write(codec, ad1988_laptop_hp_off); -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list ad1988_loopbacks[] = { - { 0x20, HDA_INPUT, 0 }, /* Front Mic */ - { 0x20, HDA_INPUT, 1 }, /* Line */ - { 0x20, HDA_INPUT, 4 }, /* Mic */ - { 0x20, HDA_INPUT, 6 }, /* CD */ - { } /* end */ -}; -#endif - -/* - * Automatic parse of I/O pins from the BIOS configuration - */ - -enum { - AD_CTL_WIDGET_VOL, - AD_CTL_WIDGET_MUTE, - AD_CTL_BIND_MUTE, -}; -static const struct snd_kcontrol_new ad1988_control_templates[] = { - HDA_CODEC_VOLUME(NULL, 0, 0, 0), - HDA_CODEC_MUTE(NULL, 0, 0, 0), - HDA_BIND_MUTE(NULL, 0, 0, 0), -}; - -/* add dynamic controls */ -static int add_control(struct ad198x_spec *spec, int type, const char *name, - unsigned long val) -{ - struct snd_kcontrol_new *knew; - - snd_array_init(&spec->kctls, sizeof(*knew), 32); - knew = snd_array_new(&spec->kctls); - if (!knew) - return -ENOMEM; - *knew = ad1988_control_templates[type]; - knew->name = kstrdup(name, GFP_KERNEL); - if (! knew->name) - return -ENOMEM; - if (get_amp_nid_(val)) - knew->subdevice = HDA_SUBDEV_AMP_FLAG; - knew->private_value = val; - return 0; -} - -#define AD1988_PIN_CD_NID 0x18 -#define AD1988_PIN_BEEP_NID 0x10 - -static const hda_nid_t ad1988_mixer_nids[8] = { - /* A B C D E F G H */ - 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28 -}; - -static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx) -{ - static const hda_nid_t idx_to_dac[8] = { - /* A B C D E F G H */ - 0x03, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a - }; - static const hda_nid_t idx_to_dac_rev2[8] = { - /* A B C D E F G H */ - 0x03, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06 - }; - if (is_rev2(codec)) - return idx_to_dac_rev2[idx]; - else - return idx_to_dac[idx]; -} - -static const hda_nid_t ad1988_boost_nids[8] = { - 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0 -}; - -static int ad1988_pin_idx(hda_nid_t nid) -{ - static const hda_nid_t ad1988_io_pins[8] = { - 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25 - }; - int i; - for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++) - if (ad1988_io_pins[i] == nid) - return i; - return 0; /* should be -1 */ -} - -static int ad1988_pin_to_loopback_idx(hda_nid_t nid) -{ - static const int loopback_idx[8] = { - 2, 0, 1, 3, 4, 5, 1, 4 - }; - switch (nid) { - case AD1988_PIN_CD_NID: - return 6; - default: - return loopback_idx[ad1988_pin_idx(nid)]; - } -} - -static int ad1988_pin_to_adc_idx(hda_nid_t nid) -{ - static const int adc_idx[8] = { - 0, 1, 2, 8, 4, 3, 6, 7 - }; - switch (nid) { - case AD1988_PIN_CD_NID: - return 5; - default: - return adc_idx[ad1988_pin_idx(nid)]; - } -} - -/* fill in the dac_nids table from the parsed pin configuration */ -static int ad1988_auto_fill_dac_nids(struct hda_codec *codec, - const struct auto_pin_cfg *cfg) -{ - struct ad198x_spec *spec = codec->spec; - int i, idx; - - spec->multiout.dac_nids = spec->private_dac_nids; - - /* check the pins hardwired to audio widget */ - for (i = 0; i < cfg->line_outs; i++) { - idx = ad1988_pin_idx(cfg->line_out_pins[i]); - spec->private_dac_nids[i] = ad1988_idx_to_dac(codec, idx); - } - spec->multiout.num_dacs = cfg->line_outs; - return 0; -} - -/* add playback controls from the parsed DAC table */ -static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec, - const struct auto_pin_cfg *cfg) -{ - char name[32]; - static const char * const chname[4] = { - "Front", "Surround", NULL /*CLFE*/, "Side" - }; - hda_nid_t nid; - int i, err; - - for (i = 0; i < cfg->line_outs; i++) { - hda_nid_t dac = spec->multiout.dac_nids[i]; - if (! dac) - continue; - nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])]; - if (i == 2) { - /* Center/LFE */ - err = add_control(spec, AD_CTL_WIDGET_VOL, - "Center Playback Volume", - HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT)); - if (err < 0) - return err; - err = add_control(spec, AD_CTL_WIDGET_VOL, - "LFE Playback Volume", - HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT)); - if (err < 0) - return err; - err = add_control(spec, AD_CTL_BIND_MUTE, - "Center Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT)); - if (err < 0) - return err; - err = add_control(spec, AD_CTL_BIND_MUTE, - "LFE Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT)); - if (err < 0) - return err; - } else { - sprintf(name, "%s Playback Volume", chname[i]); - err = add_control(spec, AD_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT)); - if (err < 0) - return err; - sprintf(name, "%s Playback Switch", chname[i]); - err = add_control(spec, AD_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); - if (err < 0) - return err; - } - } - return 0; -} - -/* add playback controls for speaker and HP outputs */ -static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, - const char *pfx) -{ - struct ad198x_spec *spec = codec->spec; - hda_nid_t nid; - int i, idx, err; - char name[32]; - - if (! pin) - return 0; - - idx = ad1988_pin_idx(pin); - nid = ad1988_idx_to_dac(codec, idx); - /* check whether the corresponding DAC was already taken */ - for (i = 0; i < spec->autocfg.line_outs; i++) { - hda_nid_t pin = spec->autocfg.line_out_pins[i]; - hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin)); - if (dac == nid) - break; - } - if (i >= spec->autocfg.line_outs) { - /* specify the DAC as the extra output */ - if (!spec->multiout.hp_nid) - spec->multiout.hp_nid = nid; - else - spec->multiout.extra_out_nid[0] = nid; - /* control HP volume/switch on the output mixer amp */ - sprintf(name, "%s Playback Volume", pfx); - err = add_control(spec, AD_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); - if (err < 0) - return err; - } - nid = ad1988_mixer_nids[idx]; - sprintf(name, "%s Playback Switch", pfx); - if ((err = add_control(spec, AD_CTL_BIND_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) - return err; - return 0; -} - -/* create input playback/capture controls for the given pin */ -static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, - const char *ctlname, int ctlidx, int boost) -{ - char name[32]; - int err, idx; - - sprintf(name, "%s Playback Volume", ctlname); - idx = ad1988_pin_to_loopback_idx(pin); - if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0) - return err; - sprintf(name, "%s Playback Switch", ctlname); - if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0) - return err; - if (boost) { - hda_nid_t bnid; - idx = ad1988_pin_idx(pin); - bnid = ad1988_boost_nids[idx]; - if (bnid) { - sprintf(name, "%s Boost Volume", ctlname); - return add_control(spec, AD_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT)); - - } - } - return 0; -} - -/* create playback/capture controls for input pins */ -static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec, - const struct auto_pin_cfg *cfg) -{ - struct ad198x_spec *spec = codec->spec; - struct hda_input_mux *imux = &spec->private_imux; - int i, err, type, type_idx; - - for (i = 0; i < cfg->num_inputs; i++) { - const char *label; - type = cfg->inputs[i].type; - label = hda_get_autocfg_input_label(codec, cfg, i); - snd_hda_add_imux_item(imux, label, - ad1988_pin_to_adc_idx(cfg->inputs[i].pin), - &type_idx); - err = new_analog_input(spec, cfg->inputs[i].pin, - label, type_idx, - type == AUTO_PIN_MIC); - if (err < 0) - return err; - } - snd_hda_add_imux_item(imux, "Mix", 9, NULL); - - if ((err = add_control(spec, AD_CTL_WIDGET_VOL, - "Analog Mix Playback Volume", - HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0) - return err; - if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, - "Analog Mix Playback Switch", - HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0) - return err; - - return 0; -} - -static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec, - hda_nid_t nid, int pin_type, - int dac_idx) -{ - /* set as output */ - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - switch (nid) { - case 0x11: /* port-A - DAC 03 */ - snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x00); - break; - case 0x14: /* port-B - DAC 06 */ - snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02); - break; - case 0x15: /* port-C - DAC 05 */ - snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00); - break; - case 0x17: /* port-E - DAC 0a */ - snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01); - break; - case 0x13: /* mono - DAC 04 */ - snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01); - break; - } -} - -static void ad1988_auto_init_multi_out(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->autocfg.line_outs; i++) { - hda_nid_t nid = spec->autocfg.line_out_pins[i]; - ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); - } -} - -static void ad1988_auto_init_extra_out(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - hda_nid_t pin; - - pin = spec->autocfg.speaker_pins[0]; - if (pin) /* connect to front */ - ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); - pin = spec->autocfg.hp_pins[0]; - if (pin) /* connect to front */ - ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); -} - -static void ad1988_auto_init_analog_input(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; - int i, idx; - - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; - int type = cfg->inputs[i].type; - switch (nid) { - case 0x15: /* port-C */ - snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); - break; - case 0x17: /* port-E */ - snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0); - break; - } - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN); - if (nid != AD1988_PIN_CD_NID) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE); - idx = ad1988_pin_idx(nid); - if (ad1988_boost_nids[idx]) - snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_ZERO); - } -} - -/* parse the BIOS configuration and set up the alc_spec */ -/* return 1 if successful, 0 if the proper config is not found, or a negative error code */ -static int ad1988_parse_auto_config(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - int err; - - if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) - return err; - if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) - return err; - if (! spec->autocfg.line_outs) - return 0; /* can't find valid BIOS pin config */ - if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || - (err = ad1988_auto_create_extra_out(codec, - spec->autocfg.speaker_pins[0], - "Speaker")) < 0 || - (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], - "Headphone")) < 0 || - (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) - return err; - - spec->multiout.max_channels = spec->multiout.num_dacs * 2; - - if (spec->autocfg.dig_outs) - spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; - if (spec->autocfg.dig_in_pin) - spec->dig_in_nid = AD1988_SPDIF_IN; - - if (spec->kctls.list) - spec->mixers[spec->num_mixers++] = spec->kctls.list; - - spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs; - - spec->input_mux = &spec->private_imux; - - return 1; -} - -/* init callback for auto-configuration model -- overriding the default init */ -static int ad1988_auto_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1988_auto_init_multi_out(codec); - ad1988_auto_init_extra_out(codec); - ad1988_auto_init_analog_input(codec); - return 0; -} - -/* - */ - -static const char * const ad1988_models[AD1988_MODEL_LAST] = { - [AD1988_6STACK] = "6stack", - [AD1988_6STACK_DIG] = "6stack-dig", - [AD1988_3STACK] = "3stack", - [AD1988_3STACK_DIG] = "3stack-dig", - [AD1988_LAPTOP] = "laptop", - [AD1988_LAPTOP_DIG] = "laptop-dig", - [AD1988_AUTO] = "auto", -}; - -static const struct snd_pci_quirk ad1988_cfg_tbl[] = { - SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG), - SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG), - SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG), - SND_PCI_QUIRK(0x1043, 0x82c0, "Asus M3N-HT Deluxe", AD1988_6STACK_DIG), - SND_PCI_QUIRK(0x1043, 0x8311, "Asus P5Q-Premium/Pro", AD1988_6STACK_DIG), - {} -}; - -static int patch_ad1988(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int err, board_config; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - if (is_rev2(codec)) - snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); - - board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST, - ad1988_models, ad1988_cfg_tbl); - if (board_config < 0) { - printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - board_config = AD1988_AUTO; - } - - if (board_config == AD1988_AUTO) { - /* automatic parse from the BIOS config */ - err = ad1988_parse_auto_config(codec); - if (err < 0) { - ad198x_free(codec); - return err; - } else if (! err) { - printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n"); - board_config = AD1988_6STACK; - } - } - - err = snd_hda_attach_beep_device(codec, 0x10); - if (err < 0) { - ad198x_free(codec); - return err; - } - set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); - - if (!spec->multiout.hp_nid) - spec->multiout.hp_nid = ad1988_alt_dac_nid[0]; - switch (board_config) { - case AD1988_6STACK: - case AD1988_6STACK_DIG: - spec->multiout.max_channels = 8; - spec->multiout.num_dacs = 4; - if (is_rev2(codec)) - spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2; - else - spec->multiout.dac_nids = ad1988_6stack_dac_nids; - spec->input_mux = &ad1988_6stack_capture_source; - spec->num_mixers = 2; - if (is_rev2(codec)) - spec->mixers[0] = ad1988_6stack_mixers1_rev2; - else - spec->mixers[0] = ad1988_6stack_mixers1; - spec->mixers[1] = ad1988_6stack_mixers2; - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1988_6stack_init_verbs; - if (board_config == AD1988_6STACK_DIG) { - spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; - spec->dig_in_nid = AD1988_SPDIF_IN; - } - break; - case AD1988_3STACK: - case AD1988_3STACK_DIG: - spec->multiout.max_channels = 6; - spec->multiout.num_dacs = 3; - if (is_rev2(codec)) - spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2; - else - spec->multiout.dac_nids = ad1988_3stack_dac_nids; - spec->input_mux = &ad1988_6stack_capture_source; - spec->channel_mode = ad1988_3stack_modes; - spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes); - spec->num_mixers = 2; - if (is_rev2(codec)) - spec->mixers[0] = ad1988_3stack_mixers1_rev2; - else - spec->mixers[0] = ad1988_3stack_mixers1; - spec->mixers[1] = ad1988_3stack_mixers2; - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1988_3stack_init_verbs; - if (board_config == AD1988_3STACK_DIG) - spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; - break; - case AD1988_LAPTOP: - case AD1988_LAPTOP_DIG: - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = ad1988_3stack_dac_nids; - spec->input_mux = &ad1988_laptop_capture_source; - spec->num_mixers = 1; - spec->mixers[0] = ad1988_laptop_mixers; - spec->inv_eapd = 1; /* inverted EAPD */ - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1988_laptop_init_verbs; - if (board_config == AD1988_LAPTOP_DIG) - spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; - break; - } - - if (spec->autocfg.hp_pins[0]) { - spec->mixers[spec->num_mixers++] = ad1988_hp_mixers; - spec->slave_vols = ad1988_6stack_fp_slave_pfxs; - spec->slave_sws = ad1988_6stack_fp_slave_pfxs; - spec->alt_dac_nid = ad1988_alt_dac_nid; - spec->stream_analog_alt_playback = - &ad198x_pcm_analog_alt_playback; - } - - spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids); - spec->adc_nids = ad1988_adc_nids; - spec->capsrc_nids = ad1988_capsrc_nids; - spec->mixers[spec->num_mixers++] = ad1988_capture_mixers; - spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs; - if (spec->multiout.dig_out_nid) { - if (codec->vendor_id >= 0x11d4989a) { - spec->mixers[spec->num_mixers++] = - ad1989_spdif_out_mixers; - spec->init_verbs[spec->num_init_verbs++] = - ad1989_spdif_init_verbs; - codec->slave_dig_outs = ad1989b_slave_dig_outs; - } else { - spec->mixers[spec->num_mixers++] = - ad1988_spdif_out_mixers; - spec->init_verbs[spec->num_init_verbs++] = - ad1988_spdif_init_verbs; - } - } - if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) { - spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; - spec->init_verbs[spec->num_init_verbs++] = - ad1988_spdif_in_init_verbs; - } - - codec->patch_ops = ad198x_patch_ops; - switch (board_config) { - case AD1988_AUTO: - codec->patch_ops.init = ad1988_auto_init; - break; - case AD1988_LAPTOP: - case AD1988_LAPTOP_DIG: - codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; - break; - } -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->loopback.amplist = ad1988_loopbacks; -#endif - spec->vmaster_nid = 0x04; - - codec->no_trigger_sense = 1; - codec->no_sticky_stream = 1; - - return 0; -} - - -/* - * AD1884 / AD1984 - * - * port-B - front line/mic-in - * port-E - aux in/out - * port-F - aux in/out - * port-C - rear line/mic-in - * port-D - rear line/hp-out - * port-A - front line/hp-out - * - * AD1984 = AD1884 + two digital mic-ins - * - * FIXME: - * For simplicity, we share the single DAC for both HP and line-outs - * right now. The inidividual playbacks could be easily implemented, - * but no build-up framework is given, so far. - */ - -static const hda_nid_t ad1884_dac_nids[1] = { - 0x04, -}; - -static const hda_nid_t ad1884_adc_nids[2] = { - 0x08, 0x09, -}; - -static const hda_nid_t ad1884_capsrc_nids[2] = { - 0x0c, 0x0d, -}; - -#define AD1884_SPDIF_OUT 0x02 - -static const struct hda_input_mux ad1884_capture_source = { - .num_items = 4, - .items = { - { "Front Mic", 0x0 }, - { "Mic", 0x1 }, - { "CD", 0x2 }, - { "Mix", 0x3 }, - }, -}; - -static const struct snd_kcontrol_new ad1884_base_mixers[] = { - HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), - /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ - HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - /* SPDIF controls */ - HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - /* identical with ad1983 */ - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, - }, - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1984_dmic_mixers[] = { - HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0, - HDA_INPUT), - HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0, - HDA_INPUT), - { } /* end */ -}; - -/* - * initialization verbs - */ -static const struct hda_verb ad1884_init_verbs[] = { - /* DACs; mute as default */ - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Port-A (HP) mixer */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Port-A pin */ - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* HP selector - select DAC2 */ - {0x22, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* Port-D (Line-out) mixer */ - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Port-D pin */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Mono-out mixer */ - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Mono-out pin */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Mono selector */ - {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* Port-B (front mic) pin */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* Port-C (rear mic) pin */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* 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)}, - /* Analog Mix output amp */ - {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ - /* SPDIF output selector */ - {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ - { } /* end */ -}; - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list ad1884_loopbacks[] = { - { 0x20, HDA_INPUT, 0 }, /* Front Mic */ - { 0x20, HDA_INPUT, 1 }, /* Mic */ - { 0x20, HDA_INPUT, 2 }, /* CD */ - { 0x20, HDA_INPUT, 4 }, /* Docking */ - { } /* end */ -}; -#endif - -static const char * const ad1884_slave_vols[] = { - "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", - "Internal Mic", "Docking Mic", /* "Beep", */ "IEC958", - NULL -}; - -static int patch_ad1884(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - err = snd_hda_attach_beep_device(codec, 0x10); - if (err < 0) { - ad198x_free(codec); - return err; - } - set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); - spec->multiout.dac_nids = ad1884_dac_nids; - spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; - spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids); - spec->adc_nids = ad1884_adc_nids; - spec->capsrc_nids = ad1884_capsrc_nids; - spec->input_mux = &ad1884_capture_source; - spec->num_mixers = 1; - spec->mixers[0] = ad1884_base_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1884_init_verbs; - spec->spdif_route = 0; -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->loopback.amplist = ad1884_loopbacks; -#endif - spec->vmaster_nid = 0x04; - /* we need to cover all playback volumes */ - spec->slave_vols = ad1884_slave_vols; - /* slaves may contain input volumes, so we can't raise to 0dB blindly */ - spec->avoid_init_slave_vol = 1; - - codec->patch_ops = ad198x_patch_ops; - - codec->no_trigger_sense = 1; - codec->no_sticky_stream = 1; - - return 0; -} - -/* - * Lenovo Thinkpad T61/X61 - */ -static const struct hda_input_mux ad1984_thinkpad_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Internal Mic", 0x1 }, - { "Mix", 0x3 }, - { "Docking-Station", 0x4 }, - }, -}; - - -/* - * Dell Precision T3400 - */ -static const struct hda_input_mux ad1984_dell_desktop_capture_source = { - .num_items = 3, - .items = { - { "Front Mic", 0x0 }, - { "Line-In", 0x1 }, - { "Mix", 0x3 }, - }, -}; - - -static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { - HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), - /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ - HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), - HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - /* SPDIF controls */ - HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - /* identical with ad1983 */ - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, - }, - { } /* end */ -}; - -/* additional verbs */ -static const struct hda_verb ad1984_thinkpad_init_verbs[] = { - /* Port-E (docking station mic) pin */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* docking mic boost */ - {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Analog PC Beeper - allow firmware/ACPI beeps */ - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3) | 0x1a}, - /* Analog mixer - docking mic; mute as default */ - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* enable EAPD bit */ - {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, - { } /* end */ -}; - -/* - * Dell Precision T3400 - */ -static const struct snd_kcontrol_new ad1984_dell_desktop_mixers[] = { - HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Line-In Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Line-In Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Line-In Boost Volume", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { } /* end */ -}; - -/* Digial MIC ADC NID 0x05 + 0x06 */ -static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - snd_hda_codec_setup_stream(codec, 0x05 + substream->number, - stream_tag, 0, format); - return 0; -} - -static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - snd_hda_codec_cleanup_stream(codec, 0x05 + substream->number); - return 0; -} - -static const struct hda_pcm_stream ad1984_pcm_dmic_capture = { - .substreams = 2, - .channels_min = 2, - .channels_max = 2, - .nid = 0x05, - .ops = { - .prepare = ad1984_pcm_dmic_prepare, - .cleanup = ad1984_pcm_dmic_cleanup - }, -}; - -static int ad1984_build_pcms(struct hda_codec *codec) -{ - struct ad198x_spec *spec = codec->spec; - struct hda_pcm *info; - int err; - - err = ad198x_build_pcms(codec); - if (err < 0) - return err; - - info = spec->pcm_rec + codec->num_pcms; - codec->num_pcms++; - info->name = "AD1984 Digital Mic"; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture; - return 0; -} - -/* models */ -enum { - AD1984_BASIC, - AD1984_THINKPAD, - AD1984_DELL_DESKTOP, - AD1984_MODELS -}; - -static const char * const ad1984_models[AD1984_MODELS] = { - [AD1984_BASIC] = "basic", - [AD1984_THINKPAD] = "thinkpad", - [AD1984_DELL_DESKTOP] = "dell_desktop", -}; - -static const struct snd_pci_quirk ad1984_cfg_tbl[] = { - /* Lenovo Thinkpad T61/X61 */ - SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1984_THINKPAD), - SND_PCI_QUIRK(0x1028, 0x0214, "Dell T3400", AD1984_DELL_DESKTOP), - SND_PCI_QUIRK(0x1028, 0x0233, "Dell Latitude E6400", AD1984_DELL_DESKTOP), - {} -}; - -static int patch_ad1984(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int board_config, err; - - err = patch_ad1884(codec); - if (err < 0) - return err; - spec = codec->spec; - board_config = snd_hda_check_board_config(codec, AD1984_MODELS, - ad1984_models, ad1984_cfg_tbl); - switch (board_config) { - case AD1984_BASIC: - /* additional digital mics */ - spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers; - codec->patch_ops.build_pcms = ad1984_build_pcms; - break; - case AD1984_THINKPAD: - if (codec->subsystem_id == 0x17aa20fb) { - /* Thinpad X300 does not have the ability to do SPDIF, - or attach to docking station to use SPDIF */ - spec->multiout.dig_out_nid = 0; - } else - spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; - spec->input_mux = &ad1984_thinkpad_capture_source; - spec->mixers[0] = ad1984_thinkpad_mixers; - spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; - spec->analog_beep = 1; - break; - case AD1984_DELL_DESKTOP: - spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1984_dell_desktop_capture_source; - spec->mixers[0] = ad1984_dell_desktop_mixers; - break; - } - return 0; -} - - -/* - * AD1883 / AD1884A / AD1984A / AD1984B - * - * port-B (0x14) - front mic-in - * port-E (0x1c) - rear mic-in - * port-F (0x16) - CD / ext out - * port-C (0x15) - rear line-in - * port-D (0x12) - rear line-out - * port-A (0x11) - front hp-out - * - * AD1984A = AD1884A + digital-mic - * AD1883 = equivalent with AD1984A - * AD1984B = AD1984A + extra SPDIF-out - * - * FIXME: - * We share the single DAC for both HP and line-outs (see AD1884/1984). - */ - -static const hda_nid_t ad1884a_dac_nids[1] = { - 0x03, -}; - -#define ad1884a_adc_nids ad1884_adc_nids -#define ad1884a_capsrc_nids ad1884_capsrc_nids - -#define AD1884A_SPDIF_OUT 0x02 - -static const struct hda_input_mux ad1884a_capture_source = { - .num_items = 5, - .items = { - { "Front Mic", 0x0 }, - { "Mic", 0x4 }, - { "Line", 0x1 }, - { "CD", 0x2 }, - { "Mix", 0x3 }, - }, -}; - -static const struct snd_kcontrol_new ad1884a_base_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x14, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - /* SPDIF controls */ - HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - /* identical with ad1983 */ - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, - }, - { } /* end */ -}; - -/* - * initialization verbs - */ -static const struct hda_verb ad1884a_init_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}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Port-D (Line-out) mixer - route only from analog mixer */ - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Port-D pin */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Mono-out mixer - route only from analog mixer */ - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Mono-out pin */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Port-B (front mic) pin */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* Port-C (rear line-in) pin */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* Port-E (rear mic) pin */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */ - /* Port-F (CD) pin */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {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_UNMUTE(4)}, /* aux */ - {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}, - {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}, - /* SPDIF output amp */ - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ - { } /* end */ -}; - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list ad1884a_loopbacks[] = { - { 0x20, HDA_INPUT, 0 }, /* Front Mic */ - { 0x20, HDA_INPUT, 1 }, /* Mic */ - { 0x20, HDA_INPUT, 2 }, /* CD */ - { 0x20, HDA_INPUT, 4 }, /* Docking */ - { } /* end */ -}; -#endif - -/* - * Laptop model - * - * Port A: Headphone jack - * Port B: MIC jack - * Port C: Internal MIC - * Port D: Dock Line Out (if enabled) - * Port E: Dock Line In (if enabled) - * Port F: Internal speakers - */ - -static int ad1884a_mobile_master_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - int ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); - int mute = (!ucontrol->value.integer.value[0] && - !ucontrol->value.integer.value[1]); - /* toggle GPIO1 according to the mute state */ - snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - mute ? 0x02 : 0x0); - return ret; -} - -static const struct snd_kcontrol_new ad1884a_laptop_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .subdevice = HDA_SUBDEV_AMP_FLAG, - .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_amp_switch_get, - .put = ad1884a_mobile_master_sw_put, - .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), - }, - HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1884a_mobile_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), - /*HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .subdevice = HDA_SUBDEV_AMP_FLAG, - .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_amp_switch_get, - .put = ad1884a_mobile_master_sw_put, - .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), - }, - HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Capture Volume", 0x14, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Capture Volume", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -/* mute internal speaker if HP is plugged */ -static void ad1884a_hp_automute(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x11); - snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, - HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); - snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, - present ? 0x00 : 0x02); -} - -/* switch to external mic if plugged */ -static void ad1884a_hp_automic(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x14); - snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, - present ? 0 : 1); -} - -#define AD1884A_HP_EVENT 0x37 -#define AD1884A_MIC_EVENT 0x36 - -/* unsolicited event for HP jack sensing */ -static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res) -{ - switch (res >> 26) { - case AD1884A_HP_EVENT: - ad1884a_hp_automute(codec); - break; - case AD1884A_MIC_EVENT: - ad1884a_hp_automic(codec); - break; - } -} - -/* initialize jack-sensing, too */ -static int ad1884a_hp_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1884a_hp_automute(codec); - ad1884a_hp_automic(codec); - return 0; -} - -/* mute internal speaker if HP or docking HP is plugged */ -static void ad1884a_laptop_automute(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x11); - if (!present) - present = snd_hda_jack_detect(codec, 0x12); - snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, - HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); - snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, - present ? 0x00 : 0x02); -} - -/* switch to external mic if plugged */ -static void ad1884a_laptop_automic(struct hda_codec *codec) -{ - unsigned int idx; - - if (snd_hda_jack_detect(codec, 0x14)) - idx = 0; - else if (snd_hda_jack_detect(codec, 0x1c)) - idx = 4; - else - idx = 1; - snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, idx); -} - -/* unsolicited event for HP jack sensing */ -static void ad1884a_laptop_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - switch (res >> 26) { - case AD1884A_HP_EVENT: - ad1884a_laptop_automute(codec); - break; - case AD1884A_MIC_EVENT: - ad1884a_laptop_automic(codec); - break; - } -} - -/* initialize jack-sensing, too */ -static int ad1884a_laptop_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1884a_laptop_automute(codec); - ad1884a_laptop_automic(codec); - return 0; -} - -/* additional verbs for laptop model */ -static const struct hda_verb ad1884a_laptop_verbs[] = { - /* Port-A (HP) pin - always unmuted */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* 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 (int speaker) pin */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* required for compaq 6530s/6531s speaker output */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* Port-C pin - internal mic-in */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ - /* Port-D (docking line-out) pin - default unmuted */ - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* analog mix */ - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* unsolicited event for pin-sense */ - {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, - {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, - {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, - {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, - /* allow to touch GPIO1 (for mute control) */ - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ - { } /* end */ -}; - -static const 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}, - /* allow to touch GPIO1 (for mute control) */ - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ - { } /* end */ -}; - -/* - * Thinkpad X300 - * 0x11 - HP - * 0x12 - speaker - * 0x14 - mic-in - * 0x17 - built-in mic - */ - -static const struct hda_verb ad1984a_thinkpad_verbs[] = { - /* HP unmute */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* analog mix */ - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* turn on EAPD */ - {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, - /* unsolicited event for pin-sense */ - {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, - /* internal mic - dmic */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* set magic COEFs for dmic */ - {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, - {0x01, AC_VERB_SET_PROC_COEF, 0x08}, - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - { } /* end */ -}; - -static const struct hda_input_mux ad1984a_thinkpad_capture_source = { - .num_items = 3, - .items = { - { "Mic", 0x0 }, - { "Internal Mic", 0x5 }, - { "Mix", 0x3 }, - }, -}; - -/* mute internal speaker if HP is plugged */ -static void ad1984a_thinkpad_automute(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x11); - snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, - HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); -} - -/* unsolicited event for HP jack sensing */ -static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - if ((res >> 26) != AD1884A_HP_EVENT) - return; - ad1984a_thinkpad_automute(codec); -} - -/* initialize jack-sensing, too */ -static int ad1984a_thinkpad_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1984a_thinkpad_automute(codec); - return 0; -} - -/* - * Precision R5500 - * 0x12 - HP/line-out - * 0x13 - speaker (mono) - * 0x15 - mic-in - */ - -static const struct hda_verb ad1984a_precision_verbs[] = { - /* Unmute main output path */ - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ - {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */ - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */ - /* 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)}, - /* Select mic as input */ - {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */ - /* Configure as mic */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ - /* HP unmute */ - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* turn on EAPD */ - {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, - /* unsolicited event for pin-sense */ - {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1984a_precision_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - { } /* end */ -}; - - -/* mute internal speaker if HP is plugged */ -static void ad1984a_precision_automute(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x12); - snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, - HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); -} - - -/* unsolicited event for HP jack sensing */ -static void ad1984a_precision_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - if ((res >> 26) != AD1884A_HP_EVENT) - return; - ad1984a_precision_automute(codec); -} - -/* initialize jack-sensing, too */ -static int ad1984a_precision_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1984a_precision_automute(codec); - return 0; -} - - -/* - * HP Touchsmart - * port-A (0x11) - front hp-out - * port-B (0x14) - unused - * port-C (0x15) - unused - * port-D (0x12) - rear line out - * port-E (0x1c) - front mic-in - * port-F (0x16) - Internal speakers - * digital-mic (0x17) - Internal mic - */ - -static const struct hda_verb ad1984a_touchsmart_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-E (int speaker) mixer - route only from analog mixer */ - {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, - /* Port-E pin */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - /* 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}, - {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, - /* allow to touch GPIO1 (for mute control) */ - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ - /* internal mic - dmic */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - /* set magic COEFs for dmic */ - {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, - {0x01, AC_VERB_SET_PROC_COEF, 0x08}, - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), -/* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .subdevice = HDA_SUBDEV_AMP_FLAG, - .name = "Master Playback Switch", - .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_amp_switch_get, - .put = ad1884a_mobile_master_sw_put, - .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), - }, - HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x17, 0x0, HDA_INPUT), - { } /* end */ -}; - -/* switch to external mic if plugged */ -static void ad1984a_touchsmart_automic(struct hda_codec *codec) -{ - if (snd_hda_jack_detect(codec, 0x1c)) - snd_hda_codec_write(codec, 0x0c, 0, - AC_VERB_SET_CONNECT_SEL, 0x4); - else - snd_hda_codec_write(codec, 0x0c, 0, - AC_VERB_SET_CONNECT_SEL, 0x5); -} - - -/* unsolicited event for HP jack sensing */ -static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - switch (res >> 26) { - case AD1884A_HP_EVENT: - ad1884a_hp_automute(codec); - break; - case AD1884A_MIC_EVENT: - ad1984a_touchsmart_automic(codec); - break; - } -} - -/* initialize jack-sensing, too */ -static int ad1984a_touchsmart_init(struct hda_codec *codec) -{ - ad198x_init(codec); - ad1884a_hp_automute(codec); - ad1984a_touchsmart_automic(codec); - return 0; -} - - -/* - */ - -enum { - AD1884A_DESKTOP, - AD1884A_LAPTOP, - AD1884A_MOBILE, - AD1884A_THINKPAD, - AD1984A_TOUCHSMART, - AD1984A_PRECISION, - AD1884A_MODELS -}; - -static const char * const ad1884a_models[AD1884A_MODELS] = { - [AD1884A_DESKTOP] = "desktop", - [AD1884A_LAPTOP] = "laptop", - [AD1884A_MOBILE] = "mobile", - [AD1884A_THINKPAD] = "thinkpad", - [AD1984A_TOUCHSMART] = "touchsmart", - [AD1984A_PRECISION] = "precision", -}; - -static const struct snd_pci_quirk ad1884a_cfg_tbl[] = { - SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION), - SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), - SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP), - SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), - SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x3070, "HP", AD1884A_MOBILE), - SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30d0, "HP laptop", AD1884A_LAPTOP), - SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x30e0, "HP laptop", AD1884A_LAPTOP), - SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), - SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), - SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), - SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), - {} -}; - -static int patch_ad1884a(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int err, board_config; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - err = snd_hda_attach_beep_device(codec, 0x10); - if (err < 0) { - ad198x_free(codec); - return err; - } - set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); - spec->multiout.dac_nids = ad1884a_dac_nids; - spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT; - spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids); - spec->adc_nids = ad1884a_adc_nids; - spec->capsrc_nids = ad1884a_capsrc_nids; - spec->input_mux = &ad1884a_capture_source; - spec->num_mixers = 1; - spec->mixers[0] = ad1884a_base_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1884a_init_verbs; - spec->spdif_route = 0; -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->loopback.amplist = ad1884a_loopbacks; -#endif - codec->patch_ops = ad198x_patch_ops; - - /* override some parameters */ - board_config = snd_hda_check_board_config(codec, AD1884A_MODELS, - ad1884a_models, - ad1884a_cfg_tbl); - switch (board_config) { - case AD1884A_LAPTOP: - spec->mixers[0] = ad1884a_laptop_mixers; - spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; - spec->multiout.dig_out_nid = 0; - codec->patch_ops.unsol_event = ad1884a_laptop_unsol_event; - codec->patch_ops.init = ad1884a_laptop_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; - 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; - /* 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_THINKPAD: - spec->mixers[0] = ad1984a_thinkpad_mixers; - spec->init_verbs[spec->num_init_verbs++] = - ad1984a_thinkpad_verbs; - spec->multiout.dig_out_nid = 0; - spec->input_mux = &ad1984a_thinkpad_capture_source; - codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; - codec->patch_ops.init = ad1984a_thinkpad_init; - break; - case AD1984A_PRECISION: - spec->mixers[0] = ad1984a_precision_mixers; - spec->init_verbs[spec->num_init_verbs++] = - ad1984a_precision_verbs; - spec->multiout.dig_out_nid = 0; - codec->patch_ops.unsol_event = ad1984a_precision_unsol_event; - codec->patch_ops.init = ad1984a_precision_init; - break; - case AD1984A_TOUCHSMART: - spec->mixers[0] = ad1984a_touchsmart_mixers; - spec->init_verbs[0] = ad1984a_touchsmart_verbs; - spec->multiout.dig_out_nid = 0; - codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; - codec->patch_ops.init = ad1984a_touchsmart_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; - } - - codec->no_trigger_sense = 1; - codec->no_sticky_stream = 1; - - return 0; -} - - -/* - * AD1882 / AD1882A - * - * port-A - front hp-out - * port-B - front mic-in - * port-C - rear line-in, shared surr-out (3stack) - * port-D - rear line-out - * port-E - rear mic-in, shared clfe-out (3stack) - * port-F - rear surr-out (6stack) - * port-G - rear clfe-out (6stack) - */ - -static const hda_nid_t ad1882_dac_nids[3] = { - 0x04, 0x03, 0x05 -}; - -static const hda_nid_t ad1882_adc_nids[2] = { - 0x08, 0x09, -}; - -static const hda_nid_t ad1882_capsrc_nids[2] = { - 0x0c, 0x0d, -}; - -#define AD1882_SPDIF_OUT 0x02 - -/* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */ -static const struct hda_input_mux ad1882_capture_source = { - .num_items = 5, - .items = { - { "Front Mic", 0x1 }, - { "Mic", 0x4 }, - { "Line", 0x2 }, - { "CD", 0x3 }, - { "Mix", 0x7 }, - }, -}; - -/* list: 0x11, 0x39, 0x3a, 0x3c, 0x18, 0x1f, 0x12, 0x20 */ -static const struct hda_input_mux ad1882a_capture_source = { - .num_items = 5, - .items = { - { "Front Mic", 0x1 }, - { "Mic", 0x4}, - { "Line", 0x2 }, - { "Digital Mic", 0x06 }, - { "Mix", 0x7 }, - }, -}; - -static const struct snd_kcontrol_new ad1882_base_mixers[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line-In Boost Volume", 0x3a, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = ad198x_mux_enum_info, - .get = ad198x_mux_enum_get, - .put = ad198x_mux_enum_put, - }, - /* SPDIF controls */ - HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", - /* identical with ad1983 */ - .info = ad1983_spdif_route_info, - .get = ad1983_spdif_route_get, - .put = ad1983_spdif_route_put, - }, - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1882_loopback_mixers[] = { - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1882a_loopback_mixers[] = { - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), - HDA_CODEC_VOLUME("Digital Mic Boost Volume", 0x1f, 0x0, HDA_INPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1882_3stack_mixers[] = { - HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = ad198x_ch_mode_info, - .get = ad198x_ch_mode_get, - .put = ad198x_ch_mode_put, - }, - { } /* end */ -}; - -static const struct snd_kcontrol_new ad1882_6stack_mixers[] = { - HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct hda_verb ad1882_ch2_init[] = { - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - { } /* end */ -}; - -static const struct hda_verb ad1882_ch4_init[] = { - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - { } /* end */ -}; - -static const struct hda_verb ad1882_ch6_init[] = { - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - { } /* end */ -}; - -static const struct hda_channel_mode ad1882_modes[3] = { - { 2, ad1882_ch2_init }, - { 4, ad1882_ch4_init }, - { 6, ad1882_ch6_init }, -}; - -/* - * initialization verbs - */ -static const struct hda_verb ad1882_init_verbs[] = { - /* DACs; mute as default */ - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* Port-A (HP) mixer */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Port-A pin */ - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* HP selector - select DAC2 */ - {0x37, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* Port-D (Line-out) mixer */ - {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Port-D pin */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Mono-out mixer */ - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - /* Mono-out pin */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Port-B (front mic) pin */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ - /* Port-C (line-in) pin */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ - /* Port-C mixer - mute as input */ - {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Port-E (mic-in) pin */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ - /* Port-E mixer - mute as input */ - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Port-F (surround) */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Port-G (CLFE) */ - {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Analog mixer; mute as default */ - /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */ - {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)}, - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, - {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, - /* Analog Mix output amp */ - {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ - /* SPDIF output selector */ - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ - {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ - { } /* end */ -}; - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static const struct hda_amp_list ad1882_loopbacks[] = { - { 0x20, HDA_INPUT, 0 }, /* Front Mic */ - { 0x20, HDA_INPUT, 1 }, /* Mic */ - { 0x20, HDA_INPUT, 4 }, /* Line */ - { 0x20, HDA_INPUT, 6 }, /* CD */ - { } /* end */ -}; -#endif - -/* models */ -enum { - AD1882_3STACK, - AD1882_6STACK, - AD1882_MODELS -}; - -static const char * const ad1882_models[AD1986A_MODELS] = { - [AD1882_3STACK] = "3stack", - [AD1882_6STACK] = "6stack", -}; - - -static int patch_ad1882(struct hda_codec *codec) -{ - struct ad198x_spec *spec; - int err, board_config; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - err = snd_hda_attach_beep_device(codec, 0x10); - if (err < 0) { - ad198x_free(codec); - return err; - } - set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); - - spec->multiout.max_channels = 6; - spec->multiout.num_dacs = 3; - spec->multiout.dac_nids = ad1882_dac_nids; - spec->multiout.dig_out_nid = AD1882_SPDIF_OUT; - spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids); - spec->adc_nids = ad1882_adc_nids; - spec->capsrc_nids = ad1882_capsrc_nids; - if (codec->vendor_id == 0x11d41882) - spec->input_mux = &ad1882_capture_source; - else - spec->input_mux = &ad1882a_capture_source; - spec->num_mixers = 2; - spec->mixers[0] = ad1882_base_mixers; - if (codec->vendor_id == 0x11d41882) - spec->mixers[1] = ad1882_loopback_mixers; - else - spec->mixers[1] = ad1882a_loopback_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = ad1882_init_verbs; - spec->spdif_route = 0; -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->loopback.amplist = ad1882_loopbacks; -#endif - spec->vmaster_nid = 0x04; - - codec->patch_ops = ad198x_patch_ops; - - /* override some parameters */ - board_config = snd_hda_check_board_config(codec, AD1882_MODELS, - ad1882_models, NULL); - switch (board_config) { - default: - case AD1882_3STACK: - spec->num_mixers = 3; - spec->mixers[2] = ad1882_3stack_mixers; - spec->channel_mode = ad1882_modes; - spec->num_channel_mode = ARRAY_SIZE(ad1882_modes); - spec->need_dac_fix = 1; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - break; - case AD1882_6STACK: - spec->num_mixers = 3; - spec->mixers[2] = ad1882_6stack_mixers; - break; - } - - codec->no_trigger_sense = 1; - codec->no_sticky_stream = 1; - - return 0; -} - - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_analog[] = { - { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a }, - { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 }, - { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a }, - { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 }, - { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a }, - { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a }, - { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, - { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, - { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 }, - { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, - { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, - { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, - { .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 }, - { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 }, - { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 }, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:11d4*"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Analog Devices HD-audio codec"); - -static struct hda_codec_preset_list analog_list = { - .preset = snd_hda_preset_analog, - .owner = THIS_MODULE, -}; - -static int __init patch_analog_init(void) -{ - return snd_hda_add_codec_preset(&analog_list); -} - -static void __exit patch_analog_exit(void) -{ - snd_hda_delete_codec_preset(&analog_list); -} - -module_init(patch_analog_init) -module_exit(patch_analog_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_ca0110.c b/ANDROID_3.4.5/sound/pci/hda/patch_ca0110.c deleted file mode 100644 index 09ccfabb..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_ca0110.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * HD audio interface patch for Creative X-Fi CA0110-IBG chip - * - * Copyright (c) 2008 Takashi Iwai - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" - -/* - */ - -struct ca0110_spec { - struct auto_pin_cfg autocfg; - struct hda_multi_out multiout; - hda_nid_t out_pins[AUTO_CFG_MAX_OUTS]; - hda_nid_t dacs[AUTO_CFG_MAX_OUTS]; - hda_nid_t hp_dac; - hda_nid_t input_pins[AUTO_PIN_LAST]; - hda_nid_t adcs[AUTO_PIN_LAST]; - hda_nid_t dig_out; - hda_nid_t dig_in; - unsigned int num_inputs; - char input_labels[AUTO_PIN_LAST][32]; - struct hda_pcm pcm_rec[2]; /* PCM information */ -}; - -/* - * PCM callbacks - */ -static int ca0110_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0110_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); -} - -static int ca0110_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ca0110_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, - stream_tag, format, substream); -} - -static int ca0110_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0110_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -/* - * Digital out - */ -static int ca0110_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0110_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int ca0110_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0110_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int ca0110_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ca0110_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, - format, substream); -} - -/* - * Analog capture - */ -static int ca0110_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ca0110_spec *spec = codec->spec; - - snd_hda_codec_setup_stream(codec, spec->adcs[substream->number], - stream_tag, 0, format); - return 0; -} - -static int ca0110_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0110_spec *spec = codec->spec; - - snd_hda_codec_cleanup_stream(codec, spec->adcs[substream->number]); - return 0; -} - -/* - */ - -static const char * const dirstr[2] = { "Playback", "Capture" }; - -static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, - int chan, int dir) -{ - char namestr[44]; - int type = dir ? HDA_INPUT : HDA_OUTPUT; - struct snd_kcontrol_new knew = - HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); - sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); - return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); -} - -static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, - int chan, int dir) -{ - char namestr[44]; - int type = dir ? HDA_INPUT : HDA_OUTPUT; - struct snd_kcontrol_new knew = - HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); - sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); - return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); -} - -#define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0) -#define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0) -#define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1) -#define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1) -#define add_mono_switch(codec, nid, pfx, chan) \ - _add_switch(codec, nid, pfx, chan, 0) -#define add_mono_volume(codec, nid, pfx, chan) \ - _add_volume(codec, nid, pfx, chan, 0) - -static int ca0110_build_controls(struct hda_codec *codec) -{ - struct ca0110_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - static const char * const prefix[AUTO_CFG_MAX_OUTS] = { - "Front", "Surround", NULL, "Side", "Multi" - }; - hda_nid_t mutenid; - int i, err; - - for (i = 0; i < spec->multiout.num_dacs; i++) { - if (get_wcaps(codec, spec->out_pins[i]) & AC_WCAP_OUT_AMP) - mutenid = spec->out_pins[i]; - else - mutenid = spec->multiout.dac_nids[i]; - if (!prefix[i]) { - err = add_mono_switch(codec, mutenid, - "Center", 1); - if (err < 0) - return err; - err = add_mono_switch(codec, mutenid, - "LFE", 1); - if (err < 0) - return err; - err = add_mono_volume(codec, spec->multiout.dac_nids[i], - "Center", 1); - if (err < 0) - return err; - err = add_mono_volume(codec, spec->multiout.dac_nids[i], - "LFE", 1); - if (err < 0) - return err; - } else { - err = add_out_switch(codec, mutenid, - prefix[i]); - if (err < 0) - return err; - err = add_out_volume(codec, spec->multiout.dac_nids[i], - prefix[i]); - if (err < 0) - return err; - } - } - if (cfg->hp_outs) { - if (get_wcaps(codec, cfg->hp_pins[0]) & AC_WCAP_OUT_AMP) - mutenid = cfg->hp_pins[0]; - else - mutenid = spec->multiout.dac_nids[i]; - - err = add_out_switch(codec, mutenid, "Headphone"); - if (err < 0) - return err; - if (spec->hp_dac) { - err = add_out_volume(codec, spec->hp_dac, "Headphone"); - if (err < 0) - return err; - } - } - for (i = 0; i < spec->num_inputs; i++) { - const char *label = spec->input_labels[i]; - if (get_wcaps(codec, spec->input_pins[i]) & AC_WCAP_IN_AMP) - mutenid = spec->input_pins[i]; - else - mutenid = spec->adcs[i]; - err = add_in_switch(codec, mutenid, label); - if (err < 0) - return err; - err = add_in_volume(codec, spec->adcs[i], label); - if (err < 0) - return err; - } - - if (spec->dig_out) { - err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out, - spec->dig_out); - if (err < 0) - return err; - err = snd_hda_create_spdif_share_sw(codec, &spec->multiout); - if (err < 0) - return err; - spec->multiout.share_spdif = 1; - } - if (spec->dig_in) { - err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in); - if (err < 0) - return err; - err = add_in_volume(codec, spec->dig_in, "IEC958"); - } - return 0; -} - -/* - */ -static const struct hda_pcm_stream ca0110_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 8, - .ops = { - .open = ca0110_playback_pcm_open, - .prepare = ca0110_playback_pcm_prepare, - .cleanup = ca0110_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream ca0110_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .prepare = ca0110_capture_pcm_prepare, - .cleanup = ca0110_capture_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream ca0110_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .open = ca0110_dig_playback_pcm_open, - .close = ca0110_dig_playback_pcm_close, - .prepare = ca0110_dig_playback_pcm_prepare - }, -}; - -static const struct hda_pcm_stream ca0110_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, -}; - -static int ca0110_build_pcms(struct hda_codec *codec) -{ - struct ca0110_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->pcm_info = info; - codec->num_pcms = 0; - - info->name = "CA0110 Analog"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0110_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0]; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = - spec->multiout.max_channels; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0110_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_inputs; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; - codec->num_pcms++; - - if (!spec->dig_out && !spec->dig_in) - return 0; - - info++; - info->name = "CA0110 Digital"; - info->pcm_type = HDA_PCM_TYPE_SPDIF; - if (spec->dig_out) { - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = - ca0110_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out; - } - if (spec->dig_in) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - ca0110_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in; - } - codec->num_pcms++; - - return 0; -} - -static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) -{ - if (pin) { - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); - if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); - } - if (dac) - snd_hda_codec_write(codec, dac, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO); -} - -static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc) -{ - if (pin) { - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80); - if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP) - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(0)); - } - if (adc) - snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(0)); -} - -static int ca0110_init(struct hda_codec *codec) -{ - struct ca0110_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - for (i = 0; i < spec->multiout.num_dacs; i++) - init_output(codec, spec->out_pins[i], - spec->multiout.dac_nids[i]); - init_output(codec, cfg->hp_pins[0], spec->hp_dac); - init_output(codec, cfg->dig_out_pins[0], spec->dig_out); - - for (i = 0; i < spec->num_inputs; i++) - init_input(codec, spec->input_pins[i], spec->adcs[i]); - init_input(codec, cfg->dig_in_pin, spec->dig_in); - return 0; -} - -static void ca0110_free(struct hda_codec *codec) -{ - kfree(codec->spec); -} - -static const struct hda_codec_ops ca0110_patch_ops = { - .build_controls = ca0110_build_controls, - .build_pcms = ca0110_build_pcms, - .init = ca0110_init, - .free = ca0110_free, -}; - - -static void parse_line_outs(struct hda_codec *codec) -{ - struct ca0110_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, n; - unsigned int def_conf; - hda_nid_t nid; - - n = 0; - for (i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - def_conf = snd_hda_codec_get_pincfg(codec, nid); - if (!def_conf) - continue; /* invalid pin */ - if (snd_hda_get_connections(codec, nid, &spec->dacs[i], 1) != 1) - continue; - spec->out_pins[n++] = nid; - } - spec->multiout.dac_nids = spec->dacs; - spec->multiout.num_dacs = n; - spec->multiout.max_channels = n * 2; -} - -static void parse_hp_out(struct hda_codec *codec) -{ - struct ca0110_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - unsigned int def_conf; - hda_nid_t nid, dac; - - if (!cfg->hp_outs) - return; - nid = cfg->hp_pins[0]; - def_conf = snd_hda_codec_get_pincfg(codec, nid); - if (!def_conf) { - cfg->hp_outs = 0; - return; - } - if (snd_hda_get_connections(codec, nid, &dac, 1) != 1) - return; - - for (i = 0; i < cfg->line_outs; i++) - if (dac == spec->dacs[i]) - break; - if (i >= cfg->line_outs) { - spec->hp_dac = dac; - spec->multiout.hp_nid = dac; - } -} - -static void parse_input(struct hda_codec *codec) -{ - struct ca0110_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t nid, pin; - int n, i, j; - - n = 0; - nid = codec->start_nid; - for (i = 0; i < codec->num_nodes; i++, nid++) { - unsigned int wcaps = get_wcaps(codec, nid); - unsigned int type = get_wcaps_type(wcaps); - if (type != AC_WID_AUD_IN) - continue; - if (snd_hda_get_connections(codec, nid, &pin, 1) != 1) - continue; - if (pin == cfg->dig_in_pin) { - spec->dig_in = nid; - continue; - } - for (j = 0; j < cfg->num_inputs; j++) - if (cfg->inputs[j].pin == pin) - break; - if (j >= cfg->num_inputs) - continue; - spec->input_pins[n] = pin; - snd_hda_get_pin_label(codec, pin, cfg, - spec->input_labels[n], - sizeof(spec->input_labels[n]), NULL); - spec->adcs[n] = nid; - n++; - } - spec->num_inputs = n; -} - -static void parse_digital(struct hda_codec *codec) -{ - struct ca0110_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - - if (cfg->dig_outs && - snd_hda_get_connections(codec, cfg->dig_out_pins[0], - &spec->dig_out, 1) == 1) - spec->multiout.dig_out_nid = spec->dig_out; -} - -static int ca0110_parse_auto_config(struct hda_codec *codec) -{ - struct ca0110_spec *spec = codec->spec; - int err; - - err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); - if (err < 0) - return err; - - parse_line_outs(codec); - parse_hp_out(codec); - parse_digital(codec); - parse_input(codec); - return 0; -} - - -static int patch_ca0110(struct hda_codec *codec) -{ - struct ca0110_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - - codec->bus->needs_damn_long_delay = 1; - - err = ca0110_parse_auto_config(codec); - if (err < 0) - goto error; - - codec->patch_ops = ca0110_patch_ops; - - return 0; - - error: - kfree(codec->spec); - codec->spec = NULL; - return err; -} - - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_ca0110[] = { - { .id = 0x1102000a, .name = "CA0110-IBG", .patch = patch_ca0110 }, - { .id = 0x1102000b, .name = "CA0110-IBG", .patch = patch_ca0110 }, - { .id = 0x1102000d, .name = "SB0880 X-Fi", .patch = patch_ca0110 }, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:1102000a"); -MODULE_ALIAS("snd-hda-codec-id:1102000b"); -MODULE_ALIAS("snd-hda-codec-id:1102000d"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec"); - -static struct hda_codec_preset_list ca0110_list = { - .preset = snd_hda_preset_ca0110, - .owner = THIS_MODULE, -}; - -static int __init patch_ca0110_init(void) -{ - return snd_hda_add_codec_preset(&ca0110_list); -} - -static void __exit patch_ca0110_exit(void) -{ - snd_hda_delete_codec_preset(&ca0110_list); -} - -module_init(patch_ca0110_init) -module_exit(patch_ca0110_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_ca0132.c b/ANDROID_3.4.5/sound/pci/hda/patch_ca0132.c deleted file mode 100644 index 21d91d58..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_ca0132.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * HD audio interface patch for Creative CA0132 chip - * - * Copyright (c) 2011, Creative Technology Ltd. - * - * Based on patch_ca0110.c - * Copyright (c) 2008 Takashi Iwai - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" - -#define WIDGET_CHIP_CTRL 0x15 -#define WIDGET_DSP_CTRL 0x16 - -#define WUH_MEM_CONNID 10 -#define DSP_MEM_CONNID 16 - -enum hda_cmd_vendor_io { - /* for DspIO node */ - VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000, - VENDOR_DSPIO_SCP_WRITE_DATA_HIGH = 0x100, - - VENDOR_DSPIO_STATUS = 0xF01, - VENDOR_DSPIO_SCP_POST_READ_DATA = 0x702, - VENDOR_DSPIO_SCP_READ_DATA = 0xF02, - VENDOR_DSPIO_DSP_INIT = 0x703, - VENDOR_DSPIO_SCP_POST_COUNT_QUERY = 0x704, - VENDOR_DSPIO_SCP_READ_COUNT = 0xF04, - - /* for ChipIO node */ - VENDOR_CHIPIO_ADDRESS_LOW = 0x000, - VENDOR_CHIPIO_ADDRESS_HIGH = 0x100, - VENDOR_CHIPIO_STREAM_FORMAT = 0x200, - VENDOR_CHIPIO_DATA_LOW = 0x300, - VENDOR_CHIPIO_DATA_HIGH = 0x400, - - VENDOR_CHIPIO_GET_PARAMETER = 0xF00, - VENDOR_CHIPIO_STATUS = 0xF01, - VENDOR_CHIPIO_HIC_POST_READ = 0x702, - VENDOR_CHIPIO_HIC_READ_DATA = 0xF03, - - VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE = 0x70A, - - VENDOR_CHIPIO_PLL_PMU_WRITE = 0x70C, - VENDOR_CHIPIO_PLL_PMU_READ = 0xF0C, - VENDOR_CHIPIO_8051_ADDRESS_LOW = 0x70D, - VENDOR_CHIPIO_8051_ADDRESS_HIGH = 0x70E, - VENDOR_CHIPIO_FLAG_SET = 0x70F, - VENDOR_CHIPIO_FLAGS_GET = 0xF0F, - VENDOR_CHIPIO_PARAMETER_SET = 0x710, - VENDOR_CHIPIO_PARAMETER_GET = 0xF10, - - VENDOR_CHIPIO_PORT_ALLOC_CONFIG_SET = 0x711, - VENDOR_CHIPIO_PORT_ALLOC_SET = 0x712, - VENDOR_CHIPIO_PORT_ALLOC_GET = 0xF12, - VENDOR_CHIPIO_PORT_FREE_SET = 0x713, - - VENDOR_CHIPIO_PARAMETER_EX_ID_GET = 0xF17, - VENDOR_CHIPIO_PARAMETER_EX_ID_SET = 0x717, - VENDOR_CHIPIO_PARAMETER_EX_VALUE_GET = 0xF18, - VENDOR_CHIPIO_PARAMETER_EX_VALUE_SET = 0x718 -}; - -/* - * Control flag IDs - */ -enum control_flag_id { - /* Connection manager stream setup is bypassed/enabled */ - CONTROL_FLAG_C_MGR = 0, - /* DSP DMA is bypassed/enabled */ - CONTROL_FLAG_DMA = 1, - /* 8051 'idle' mode is disabled/enabled */ - CONTROL_FLAG_IDLE_ENABLE = 2, - /* Tracker for the SPDIF-in path is bypassed/enabled */ - CONTROL_FLAG_TRACKER = 3, - /* DigitalOut to Spdif2Out connection is disabled/enabled */ - CONTROL_FLAG_SPDIF2OUT = 4, - /* Digital Microphone is disabled/enabled */ - CONTROL_FLAG_DMIC = 5, - /* ADC_B rate is 48 kHz/96 kHz */ - CONTROL_FLAG_ADC_B_96KHZ = 6, - /* ADC_C rate is 48 kHz/96 kHz */ - CONTROL_FLAG_ADC_C_96KHZ = 7, - /* DAC rate is 48 kHz/96 kHz (affects all DACs) */ - CONTROL_FLAG_DAC_96KHZ = 8, - /* DSP rate is 48 kHz/96 kHz */ - CONTROL_FLAG_DSP_96KHZ = 9, - /* SRC clock is 98 MHz/196 MHz (196 MHz forces rate to 96 KHz) */ - CONTROL_FLAG_SRC_CLOCK_196MHZ = 10, - /* SRC rate is 48 kHz/96 kHz (48 kHz disabled when clock is 196 MHz) */ - CONTROL_FLAG_SRC_RATE_96KHZ = 11, - /* Decode Loop (DSP->SRC->DSP) is disabled/enabled */ - CONTROL_FLAG_DECODE_LOOP = 12, - /* De-emphasis filter on DAC-1 disabled/enabled */ - CONTROL_FLAG_DAC1_DEEMPHASIS = 13, - /* De-emphasis filter on DAC-2 disabled/enabled */ - CONTROL_FLAG_DAC2_DEEMPHASIS = 14, - /* De-emphasis filter on DAC-3 disabled/enabled */ - CONTROL_FLAG_DAC3_DEEMPHASIS = 15, - /* High-pass filter on ADC_B disabled/enabled */ - CONTROL_FLAG_ADC_B_HIGH_PASS = 16, - /* High-pass filter on ADC_C disabled/enabled */ - CONTROL_FLAG_ADC_C_HIGH_PASS = 17, - /* Common mode on Port_A disabled/enabled */ - CONTROL_FLAG_PORT_A_COMMON_MODE = 18, - /* Common mode on Port_D disabled/enabled */ - CONTROL_FLAG_PORT_D_COMMON_MODE = 19, - /* Impedance for ramp generator on Port_A 16 Ohm/10K Ohm */ - CONTROL_FLAG_PORT_A_10KOHM_LOAD = 20, - /* Impedance for ramp generator on Port_D, 16 Ohm/10K Ohm */ - CONTROL_FLAG_PORT_D_10K0HM_LOAD = 21, - /* ASI rate is 48kHz/96kHz */ - CONTROL_FLAG_ASI_96KHZ = 22, - /* DAC power settings able to control attached ports no/yes */ - CONTROL_FLAG_DACS_CONTROL_PORTS = 23, - /* Clock Stop OK reporting is disabled/enabled */ - CONTROL_FLAG_CONTROL_STOP_OK_ENABLE = 24, - /* Number of control flags */ - CONTROL_FLAGS_MAX = (CONTROL_FLAG_CONTROL_STOP_OK_ENABLE+1) -}; - -/* - * Control parameter IDs - */ -enum control_parameter_id { - /* 0: force HDA, 1: allow DSP if HDA Spdif1Out stream is idle */ - CONTROL_PARAM_SPDIF1_SOURCE = 2, - - /* Stream Control */ - - /* Select stream with the given ID */ - CONTROL_PARAM_STREAM_ID = 24, - /* Source connection point for the selected stream */ - CONTROL_PARAM_STREAM_SOURCE_CONN_POINT = 25, - /* Destination connection point for the selected stream */ - CONTROL_PARAM_STREAM_DEST_CONN_POINT = 26, - /* Number of audio channels in the selected stream */ - CONTROL_PARAM_STREAMS_CHANNELS = 27, - /*Enable control for the selected stream */ - CONTROL_PARAM_STREAM_CONTROL = 28, - - /* Connection Point Control */ - - /* Select connection point with the given ID */ - CONTROL_PARAM_CONN_POINT_ID = 29, - /* Connection point sample rate */ - CONTROL_PARAM_CONN_POINT_SAMPLE_RATE = 30, - - /* Node Control */ - - /* Select HDA node with the given ID */ - CONTROL_PARAM_NODE_ID = 31 -}; - -/* - * Dsp Io Status codes - */ -enum hda_vendor_status_dspio { - /* Success */ - VENDOR_STATUS_DSPIO_OK = 0x00, - /* Busy, unable to accept new command, the host must retry */ - VENDOR_STATUS_DSPIO_BUSY = 0x01, - /* SCP command queue is full */ - VENDOR_STATUS_DSPIO_SCP_COMMAND_QUEUE_FULL = 0x02, - /* SCP response queue is empty */ - VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY = 0x03 -}; - -/* - * Chip Io Status codes - */ -enum hda_vendor_status_chipio { - /* Success */ - VENDOR_STATUS_CHIPIO_OK = 0x00, - /* Busy, unable to accept new command, the host must retry */ - VENDOR_STATUS_CHIPIO_BUSY = 0x01 -}; - -/* - * CA0132 sample rate - */ -enum ca0132_sample_rate { - SR_6_000 = 0x00, - SR_8_000 = 0x01, - SR_9_600 = 0x02, - SR_11_025 = 0x03, - SR_16_000 = 0x04, - SR_22_050 = 0x05, - SR_24_000 = 0x06, - SR_32_000 = 0x07, - SR_44_100 = 0x08, - SR_48_000 = 0x09, - SR_88_200 = 0x0A, - SR_96_000 = 0x0B, - SR_144_000 = 0x0C, - SR_176_400 = 0x0D, - SR_192_000 = 0x0E, - SR_384_000 = 0x0F, - - SR_COUNT = 0x10, - - SR_RATE_UNKNOWN = 0x1F -}; - -/* - * Scp Helper function - */ -enum get_set { - IS_SET = 0, - IS_GET = 1, -}; - -/* - * Duplicated from ca0110 codec - */ - -static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) -{ - if (pin) { - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); - if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); - } - if (dac) - snd_hda_codec_write(codec, dac, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO); -} - -static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc) -{ - if (pin) { - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_VREF80); - if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP) - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(0)); - } - if (adc) - snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(0)); -} - -static char *dirstr[2] = { "Playback", "Capture" }; - -static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, - int chan, int dir) -{ - char namestr[44]; - int type = dir ? HDA_INPUT : HDA_OUTPUT; - struct snd_kcontrol_new knew = - HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); - sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); - return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); -} - -static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, - int chan, int dir) -{ - char namestr[44]; - int type = dir ? HDA_INPUT : HDA_OUTPUT; - struct snd_kcontrol_new knew = - HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); - sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); - return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); -} - -#define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0) -#define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0) -#define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1) -#define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1) -#define add_mono_switch(codec, nid, pfx, chan) \ - _add_switch(codec, nid, pfx, chan, 0) -#define add_mono_volume(codec, nid, pfx, chan) \ - _add_volume(codec, nid, pfx, chan, 0) -#define add_in_mono_switch(codec, nid, pfx, chan) \ - _add_switch(codec, nid, pfx, chan, 1) -#define add_in_mono_volume(codec, nid, pfx, chan) \ - _add_volume(codec, nid, pfx, chan, 1) - - -/* - * CA0132 specific - */ - -struct ca0132_spec { - struct auto_pin_cfg autocfg; - struct hda_multi_out multiout; - hda_nid_t out_pins[AUTO_CFG_MAX_OUTS]; - hda_nid_t dacs[AUTO_CFG_MAX_OUTS]; - hda_nid_t hp_dac; - hda_nid_t input_pins[AUTO_PIN_LAST]; - hda_nid_t adcs[AUTO_PIN_LAST]; - hda_nid_t dig_out; - hda_nid_t dig_in; - unsigned int num_inputs; - long curr_hp_switch; - long curr_hp_volume[2]; - long curr_speaker_switch; - struct mutex chipio_mutex; - const char *input_labels[AUTO_PIN_LAST]; - struct hda_pcm pcm_rec[2]; /* PCM information */ -}; - -/* Chip access helper function */ -static int chipio_send(struct hda_codec *codec, - unsigned int reg, - unsigned int data) -{ - unsigned int res; - int retry = 50; - - /* send bits of data specified by reg */ - do { - res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, - reg, data); - if (res == VENDOR_STATUS_CHIPIO_OK) - return 0; - } while (--retry); - return -EIO; -} - -/* - * Write chip address through the vendor widget -- NOT protected by the Mutex! - */ -static int chipio_write_address(struct hda_codec *codec, - unsigned int chip_addx) -{ - int res; - - /* send low 16 bits of the address */ - res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_LOW, - chip_addx & 0xffff); - - if (res != -EIO) { - /* send high 16 bits of the address */ - res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_HIGH, - chip_addx >> 16); - } - - return res; -} - -/* - * Write data through the vendor widget -- NOT protected by the Mutex! - */ - -static int chipio_write_data(struct hda_codec *codec, unsigned int data) -{ - int res; - - /* send low 16 bits of the data */ - res = chipio_send(codec, VENDOR_CHIPIO_DATA_LOW, data & 0xffff); - - if (res != -EIO) { - /* send high 16 bits of the data */ - res = chipio_send(codec, VENDOR_CHIPIO_DATA_HIGH, - data >> 16); - } - - return res; -} - -/* - * Read data through the vendor widget -- NOT protected by the Mutex! - */ -static int chipio_read_data(struct hda_codec *codec, unsigned int *data) -{ - int res; - - /* post read */ - res = chipio_send(codec, VENDOR_CHIPIO_HIC_POST_READ, 0); - - if (res != -EIO) { - /* read status */ - res = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0); - } - - if (res != -EIO) { - /* read data */ - *data = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_HIC_READ_DATA, - 0); - } - - return res; -} - -/* - * Write given value to the given address through the chip I/O widget. - * protected by the Mutex - */ -static int chipio_write(struct hda_codec *codec, - unsigned int chip_addx, const unsigned int data) -{ - struct ca0132_spec *spec = codec->spec; - int err; - - mutex_lock(&spec->chipio_mutex); - - /* write the address, and if successful proceed to write data */ - err = chipio_write_address(codec, chip_addx); - if (err < 0) - goto exit; - - err = chipio_write_data(codec, data); - if (err < 0) - goto exit; - -exit: - mutex_unlock(&spec->chipio_mutex); - return err; -} - -/* - * Read the given address through the chip I/O widget - * protected by the Mutex - */ -static int chipio_read(struct hda_codec *codec, - unsigned int chip_addx, unsigned int *data) -{ - struct ca0132_spec *spec = codec->spec; - int err; - - mutex_lock(&spec->chipio_mutex); - - /* write the address, and if successful proceed to write data */ - err = chipio_write_address(codec, chip_addx); - if (err < 0) - goto exit; - - err = chipio_read_data(codec, data); - if (err < 0) - goto exit; - -exit: - mutex_unlock(&spec->chipio_mutex); - return err; -} - -/* - * PCM stuffs - */ -static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, - int channel_id, int format) -{ - unsigned int oldval, newval; - - if (!nid) - return; - - snd_printdd("ca0132_setup_stream: " - "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", - nid, stream_tag, channel_id, format); - - /* update the format-id if changed */ - oldval = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_STREAM_FORMAT, - 0); - if (oldval != format) { - msleep(20); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, - format); - } - - oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); - newval = (stream_tag << 4) | channel_id; - if (oldval != newval) { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, - newval); - } -} - -static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) -{ - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); -} - -/* - * PCM callbacks - */ -static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); - - return 0; -} - -static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_cleanup_stream(codec, spec->dacs[0]); - - return 0; -} - -/* - * Digital out - */ -static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_setup_stream(codec, spec->dig_out, stream_tag, 0, format); - - return 0; -} - -static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_cleanup_stream(codec, spec->dig_out); - - return 0; -} - -/* - * Analog capture - */ -static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_setup_stream(codec, spec->adcs[substream->number], - stream_tag, 0, format); - - return 0; -} - -static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_cleanup_stream(codec, spec->adcs[substream->number]); - - return 0; -} - -/* - * Digital capture - */ -static int ca0132_dig_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_setup_stream(codec, spec->dig_in, stream_tag, 0, format); - - return 0; -} - -static int ca0132_dig_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct ca0132_spec *spec = codec->spec; - - ca0132_cleanup_stream(codec, spec->dig_in); - - return 0; -} - -/* - */ -static struct hda_pcm_stream ca0132_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .prepare = ca0132_playback_pcm_prepare, - .cleanup = ca0132_playback_pcm_cleanup - }, -}; - -static struct hda_pcm_stream ca0132_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .prepare = ca0132_capture_pcm_prepare, - .cleanup = ca0132_capture_pcm_cleanup - }, -}; - -static struct hda_pcm_stream ca0132_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .prepare = ca0132_dig_playback_pcm_prepare, - .cleanup = ca0132_dig_playback_pcm_cleanup - }, -}; - -static struct hda_pcm_stream ca0132_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .prepare = ca0132_dig_capture_pcm_prepare, - .cleanup = ca0132_dig_capture_pcm_cleanup - }, -}; - -static int ca0132_build_pcms(struct hda_codec *codec) -{ - struct ca0132_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->pcm_info = info; - codec->num_pcms = 0; - - info->name = "CA0132 Analog"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0]; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = - spec->multiout.max_channels; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_inputs; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; - codec->num_pcms++; - - if (!spec->dig_out && !spec->dig_in) - return 0; - - info++; - info->name = "CA0132 Digital"; - info->pcm_type = HDA_PCM_TYPE_SPDIF; - if (spec->dig_out) { - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = - ca0132_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out; - } - if (spec->dig_in) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - ca0132_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in; - } - codec->num_pcms++; - - return 0; -} - -#define REG_CODEC_MUTE 0x18b014 -#define REG_CODEC_HP_VOL_L 0x18b070 -#define REG_CODEC_HP_VOL_R 0x18b074 - -static int ca0132_hp_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ca0132_spec *spec = codec->spec; - long *valp = ucontrol->value.integer.value; - - *valp = spec->curr_hp_switch; - return 0; -} - -static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ca0132_spec *spec = codec->spec; - long *valp = ucontrol->value.integer.value; - unsigned int data; - int err; - - /* any change? */ - if (spec->curr_hp_switch == *valp) - return 0; - - snd_hda_power_up(codec); - - err = chipio_read(codec, REG_CODEC_MUTE, &data); - if (err < 0) - goto exit; - - /* *valp 0 is mute, 1 is unmute */ - data = (data & 0x7f) | (*valp ? 0 : 0x80); - err = chipio_write(codec, REG_CODEC_MUTE, data); - if (err < 0) - goto exit; - - spec->curr_hp_switch = *valp; - - exit: - snd_hda_power_down(codec); - return err < 0 ? err : 1; -} - -static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ca0132_spec *spec = codec->spec; - long *valp = ucontrol->value.integer.value; - - *valp = spec->curr_speaker_switch; - return 0; -} - -static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ca0132_spec *spec = codec->spec; - long *valp = ucontrol->value.integer.value; - unsigned int data; - int err; - - /* any change? */ - if (spec->curr_speaker_switch == *valp) - return 0; - - snd_hda_power_up(codec); - - err = chipio_read(codec, REG_CODEC_MUTE, &data); - if (err < 0) - goto exit; - - /* *valp 0 is mute, 1 is unmute */ - data = (data & 0xef) | (*valp ? 0 : 0x10); - err = chipio_write(codec, REG_CODEC_MUTE, data); - if (err < 0) - goto exit; - - spec->curr_speaker_switch = *valp; - - exit: - snd_hda_power_down(codec); - return err < 0 ? err : 1; -} - -static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ca0132_spec *spec = codec->spec; - long *valp = ucontrol->value.integer.value; - - *valp++ = spec->curr_hp_volume[0]; - *valp = spec->curr_hp_volume[1]; - return 0; -} - -static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct ca0132_spec *spec = codec->spec; - long *valp = ucontrol->value.integer.value; - long left_vol, right_vol; - unsigned int data; - int val; - int err; - - left_vol = *valp++; - right_vol = *valp; - - /* any change? */ - if ((spec->curr_hp_volume[0] == left_vol) && - (spec->curr_hp_volume[1] == right_vol)) - return 0; - - snd_hda_power_up(codec); - - err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data); - if (err < 0) - goto exit; - - val = 31 - left_vol; - data = (data & 0xe0) | val; - err = chipio_write(codec, REG_CODEC_HP_VOL_L, data); - if (err < 0) - goto exit; - - val = 31 - right_vol; - data = (data & 0xe0) | val; - err = chipio_write(codec, REG_CODEC_HP_VOL_R, data); - if (err < 0) - goto exit; - - spec->curr_hp_volume[0] = left_vol; - spec->curr_hp_volume[1] = right_vol; - - exit: - snd_hda_power_down(codec); - return err < 0 ? err : 1; -} - -static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid) -{ - struct snd_kcontrol_new knew = - HDA_CODEC_MUTE_MONO("Headphone Playback Switch", - nid, 1, 0, HDA_OUTPUT); - knew.get = ca0132_hp_switch_get; - knew.put = ca0132_hp_switch_put; - return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); -} - -static int add_hp_volume(struct hda_codec *codec, hda_nid_t nid) -{ - struct snd_kcontrol_new knew = - HDA_CODEC_VOLUME_MONO("Headphone Playback Volume", - nid, 3, 0, HDA_OUTPUT); - knew.get = ca0132_hp_volume_get; - knew.put = ca0132_hp_volume_put; - return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); -} - -static int add_speaker_switch(struct hda_codec *codec, hda_nid_t nid) -{ - struct snd_kcontrol_new knew = - HDA_CODEC_MUTE_MONO("Speaker Playback Switch", - nid, 1, 0, HDA_OUTPUT); - knew.get = ca0132_speaker_switch_get; - knew.put = ca0132_speaker_switch_put; - return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); -} - -static void ca0132_fix_hp_caps(struct hda_codec *codec) -{ - struct ca0132_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int caps; - - /* set mute-capable, 1db step, 32 steps, ofs 6 */ - caps = 0x80031f06; - snd_hda_override_amp_caps(codec, cfg->hp_pins[0], HDA_OUTPUT, caps); -} - -static int ca0132_build_controls(struct hda_codec *codec) -{ - struct ca0132_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, err; - - if (spec->multiout.num_dacs) { - err = add_speaker_switch(codec, spec->out_pins[0]); - if (err < 0) - return err; - } - - if (cfg->hp_outs) { - ca0132_fix_hp_caps(codec); - err = add_hp_switch(codec, cfg->hp_pins[0]); - if (err < 0) - return err; - err = add_hp_volume(codec, cfg->hp_pins[0]); - if (err < 0) - return err; - } - - for (i = 0; i < spec->num_inputs; i++) { - const char *label = spec->input_labels[i]; - - err = add_in_switch(codec, spec->adcs[i], label); - if (err < 0) - return err; - err = add_in_volume(codec, spec->adcs[i], label); - if (err < 0) - return err; - if (cfg->inputs[i].type == AUTO_PIN_MIC) { - /* add Mic-Boost */ - err = add_in_mono_volume(codec, spec->input_pins[i], - "Mic Boost", 1); - if (err < 0) - return err; - } - } - - if (spec->dig_out) { - err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out, - spec->dig_out); - if (err < 0) - return err; - err = add_out_volume(codec, spec->dig_out, "IEC958"); - if (err < 0) - return err; - } - - if (spec->dig_in) { - err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in); - if (err < 0) - return err; - err = add_in_volume(codec, spec->dig_in, "IEC958"); - if (err < 0) - return err; - } - return 0; -} - - -static void ca0132_set_ct_ext(struct hda_codec *codec, int enable) -{ - /* Set Creative extension */ - snd_printdd("SET CREATIVE EXTENSION\n"); - snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, - VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, - enable); - msleep(20); -} - - -static void ca0132_config(struct hda_codec *codec) -{ - struct ca0132_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - - /* line-outs */ - cfg->line_outs = 1; - cfg->line_out_pins[0] = 0x0b; /* front */ - cfg->line_out_type = AUTO_PIN_LINE_OUT; - - spec->dacs[0] = 0x02; - spec->out_pins[0] = 0x0b; - spec->multiout.dac_nids = spec->dacs; - spec->multiout.num_dacs = 1; - spec->multiout.max_channels = 2; - - /* headphone */ - cfg->hp_outs = 1; - cfg->hp_pins[0] = 0x0f; - - spec->hp_dac = 0; - spec->multiout.hp_nid = 0; - - /* inputs */ - cfg->num_inputs = 2; /* Mic-in and line-in */ - cfg->inputs[0].pin = 0x12; - cfg->inputs[0].type = AUTO_PIN_MIC; - cfg->inputs[1].pin = 0x11; - cfg->inputs[1].type = AUTO_PIN_LINE_IN; - - /* Mic-in */ - spec->input_pins[0] = 0x12; - spec->input_labels[0] = "Mic-In"; - spec->adcs[0] = 0x07; - - /* Line-In */ - spec->input_pins[1] = 0x11; - spec->input_labels[1] = "Line-In"; - spec->adcs[1] = 0x08; - spec->num_inputs = 2; -} - -static void ca0132_init_chip(struct hda_codec *codec) -{ - struct ca0132_spec *spec = codec->spec; - - mutex_init(&spec->chipio_mutex); -} - -static void ca0132_exit_chip(struct hda_codec *codec) -{ - /* put any chip cleanup stuffs here. */ -} - -static int ca0132_init(struct hda_codec *codec) -{ - struct ca0132_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - for (i = 0; i < spec->multiout.num_dacs; i++) { - init_output(codec, spec->out_pins[i], - spec->multiout.dac_nids[i]); - } - init_output(codec, cfg->hp_pins[0], spec->hp_dac); - init_output(codec, cfg->dig_out_pins[0], spec->dig_out); - - for (i = 0; i < spec->num_inputs; i++) - init_input(codec, spec->input_pins[i], spec->adcs[i]); - - init_input(codec, cfg->dig_in_pin, spec->dig_in); - - ca0132_set_ct_ext(codec, 1); - - return 0; -} - - -static void ca0132_free(struct hda_codec *codec) -{ - ca0132_set_ct_ext(codec, 0); - ca0132_exit_chip(codec); - kfree(codec->spec); -} - -static struct hda_codec_ops ca0132_patch_ops = { - .build_controls = ca0132_build_controls, - .build_pcms = ca0132_build_pcms, - .init = ca0132_init, - .free = ca0132_free, -}; - - - -static int patch_ca0132(struct hda_codec *codec) -{ - struct ca0132_spec *spec; - - snd_printdd("patch_ca0132\n"); - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - - ca0132_init_chip(codec); - - ca0132_config(codec); - - codec->patch_ops = ca0132_patch_ops; - - return 0; -} - -/* - * patch entries - */ -static struct hda_codec_preset snd_hda_preset_ca0132[] = { - { .id = 0x11020011, .name = "CA0132", .patch = patch_ca0132 }, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:11020011"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Creative CA0132, CA0132 HD-audio codec"); - -static struct hda_codec_preset_list ca0132_list = { - .preset = snd_hda_preset_ca0132, - .owner = THIS_MODULE, -}; - -static int __init patch_ca0132_init(void) -{ - return snd_hda_add_codec_preset(&ca0132_list); -} - -static void __exit patch_ca0132_exit(void) -{ - snd_hda_delete_codec_preset(&ca0132_list); -} - -module_init(patch_ca0132_init) -module_exit(patch_ca0132_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_cirrus.c b/ANDROID_3.4.5/sound/pci/hda/patch_cirrus.c deleted file mode 100644 index c83ccdba..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_cirrus.c +++ /dev/null @@ -1,2053 +0,0 @@ -/* - * HD audio interface patch for Cirrus Logic CS420x chip - * - * Copyright (c) 2009 Takashi Iwai - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" -#include "hda_jack.h" -#include - -/* - */ - -struct cs_spec { - int board_config; - struct auto_pin_cfg autocfg; - struct hda_multi_out multiout; - struct snd_kcontrol *vmaster_sw; - struct snd_kcontrol *vmaster_vol; - - hda_nid_t dac_nid[AUTO_CFG_MAX_OUTS]; - hda_nid_t slave_dig_outs[2]; - - unsigned int input_idx[AUTO_PIN_LAST]; - unsigned int capsrc_idx[AUTO_PIN_LAST]; - hda_nid_t adc_nid[AUTO_PIN_LAST]; - unsigned int adc_idx[AUTO_PIN_LAST]; - unsigned int num_inputs; - unsigned int cur_input; - unsigned int automic_idx; - hda_nid_t cur_adc; - unsigned int cur_adc_stream_tag; - unsigned int cur_adc_format; - hda_nid_t dig_in; - - const struct hda_bind_ctls *capture_bind[2]; - - unsigned int gpio_mask; - unsigned int gpio_dir; - unsigned int gpio_data; - unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */ - unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */ - - struct hda_pcm pcm_rec[2]; /* PCM information */ - - unsigned int hp_detect:1; - unsigned int mic_detect:1; - /* CS421x */ - unsigned int spdif_detect:1; - unsigned int sense_b:1; - hda_nid_t vendor_nid; - struct hda_input_mux input_mux; - unsigned int last_input; -}; - -/* available models with CS420x */ -enum { - CS420X_MBP53, - CS420X_MBP55, - CS420X_IMAC27, - CS420X_IMAC27_122, - CS420X_APPLE, - CS420X_AUTO, - CS420X_MODELS -}; - -/* CS421x boards */ -enum { - CS421X_CDB4210, - CS421X_MODELS -}; - -/* Vendor-specific processing widget */ -#define CS420X_VENDOR_NID 0x11 -#define CS_DIG_OUT1_PIN_NID 0x10 -#define CS_DIG_OUT2_PIN_NID 0x15 -#define CS_DMIC1_PIN_NID 0x12 -#define CS_DMIC2_PIN_NID 0x0e - -/* coef indices */ -#define IDX_SPDIF_STAT 0x0000 -#define IDX_SPDIF_CTL 0x0001 -#define IDX_ADC_CFG 0x0002 -/* SZC bitmask, 4 modes below: - * 0 = immediate, - * 1 = digital immediate, analog zero-cross - * 2 = digtail & analog soft-ramp - * 3 = digital soft-ramp, analog zero-cross - */ -#define CS_COEF_ADC_SZC_MASK (3 << 0) -#define CS_COEF_ADC_MIC_SZC_MODE (3 << 0) /* SZC setup for mic */ -#define CS_COEF_ADC_LI_SZC_MODE (3 << 0) /* SZC setup for line-in */ -/* PGA mode: 0 = differential, 1 = signle-ended */ -#define CS_COEF_ADC_MIC_PGA_MODE (1 << 5) /* PGA setup for mic */ -#define CS_COEF_ADC_LI_PGA_MODE (1 << 6) /* PGA setup for line-in */ -#define IDX_DAC_CFG 0x0003 -/* SZC bitmask, 4 modes below: - * 0 = Immediate - * 1 = zero-cross - * 2 = soft-ramp - * 3 = soft-ramp on zero-cross - */ -#define CS_COEF_DAC_HP_SZC_MODE (3 << 0) /* nid 0x02 */ -#define CS_COEF_DAC_LO_SZC_MODE (3 << 2) /* nid 0x03 */ -#define CS_COEF_DAC_SPK_SZC_MODE (3 << 4) /* nid 0x04 */ - -#define IDX_BEEP_CFG 0x0004 -/* 0x0008 - test reg key */ -/* 0x0009 - 0x0014 -> 12 test regs */ -/* 0x0015 - visibility reg */ - -/* - * Cirrus Logic CS4210 - * - * 1 DAC => HP(sense) / Speakers, - * 1 ADC <= LineIn(sense) / MicIn / DMicIn, - * 1 SPDIF OUT => SPDIF Trasmitter(sense) -*/ -#define CS4210_DAC_NID 0x02 -#define CS4210_ADC_NID 0x03 -#define CS4210_VENDOR_NID 0x0B -#define CS421X_DMIC_PIN_NID 0x09 /* Port E */ -#define CS421X_SPDIF_PIN_NID 0x0A /* Port H */ - -#define CS421X_IDX_DEV_CFG 0x01 -#define CS421X_IDX_ADC_CFG 0x02 -#define CS421X_IDX_DAC_CFG 0x03 -#define CS421X_IDX_SPK_CTL 0x04 - -#define SPDIF_EVENT 0x04 - -/* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */ -#define CS4213_VENDOR_NID 0x09 - - -static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx) -{ - struct cs_spec *spec = codec->spec; - snd_hda_codec_write(codec, spec->vendor_nid, 0, - AC_VERB_SET_COEF_INDEX, idx); - return snd_hda_codec_read(codec, spec->vendor_nid, 0, - AC_VERB_GET_PROC_COEF, 0); -} - -static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx, - unsigned int coef) -{ - struct cs_spec *spec = codec->spec; - snd_hda_codec_write(codec, spec->vendor_nid, 0, - AC_VERB_SET_COEF_INDEX, idx); - snd_hda_codec_write(codec, spec->vendor_nid, 0, - AC_VERB_SET_PROC_COEF, coef); -} - - -#define HP_EVENT 1 -#define MIC_EVENT 2 - -/* - * PCM callbacks - */ -static int cs_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); -} - -static int cs_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, - stream_tag, format, substream); -} - -static int cs_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -/* - * Digital out - */ -static int cs_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int cs_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int cs_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, - format, substream); -} - -static int cs_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); -} - -static void cs_update_input_select(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - if (spec->cur_adc) - snd_hda_codec_write(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[spec->cur_input]); -} - -/* - * Analog capture - */ -static int cs_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - spec->cur_adc = spec->adc_nid[spec->cur_input]; - spec->cur_adc_stream_tag = stream_tag; - spec->cur_adc_format = format; - cs_update_input_select(codec); - snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); - return 0; -} - -static int cs_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cs_spec *spec = codec->spec; - snd_hda_codec_cleanup_stream(codec, spec->cur_adc); - spec->cur_adc = 0; - return 0; -} - -/* - */ -static const struct hda_pcm_stream cs_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .open = cs_playback_pcm_open, - .prepare = cs_playback_pcm_prepare, - .cleanup = cs_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream cs_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .prepare = cs_capture_pcm_prepare, - .cleanup = cs_capture_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream cs_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .ops = { - .open = cs_dig_playback_pcm_open, - .close = cs_dig_playback_pcm_close, - .prepare = cs_dig_playback_pcm_prepare, - .cleanup = cs_dig_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream cs_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, -}; - -static int cs_build_pcms(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->pcm_info = info; - codec->num_pcms = 0; - - info->name = "Cirrus Analog"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cs_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dac_nid[0]; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = - spec->multiout.max_channels; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = cs_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = - spec->adc_nid[spec->cur_input]; - codec->num_pcms++; - - if (!spec->multiout.dig_out_nid && !spec->dig_in) - return 0; - - info++; - info->name = "Cirrus Digital"; - info->pcm_type = spec->autocfg.dig_out_type[0]; - if (!info->pcm_type) - info->pcm_type = HDA_PCM_TYPE_SPDIF; - if (spec->multiout.dig_out_nid) { - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = - cs_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->multiout.dig_out_nid; - } - if (spec->dig_in) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - cs_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in; - } - codec->num_pcms++; - - return 0; -} - -/* - * parse codec topology - */ - -static hda_nid_t get_dac(struct hda_codec *codec, hda_nid_t pin) -{ - hda_nid_t dac; - if (!pin) - return 0; - if (snd_hda_get_connections(codec, pin, &dac, 1) != 1) - return 0; - return dac; -} - -static int is_ext_mic(struct hda_codec *codec, unsigned int idx) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t pin = cfg->inputs[idx].pin; - unsigned int val; - if (!is_jack_detectable(codec, pin)) - return 0; - val = snd_hda_codec_get_pincfg(codec, pin); - return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT); -} - -static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, - unsigned int *idxp) -{ - int i, idx; - hda_nid_t nid; - - nid = codec->start_nid; - for (i = 0; i < codec->num_nodes; i++, nid++) { - unsigned int type; - type = get_wcaps_type(get_wcaps(codec, nid)); - if (type != AC_WID_AUD_IN) - continue; - idx = snd_hda_get_conn_index(codec, nid, pin, false); - if (idx >= 0) { - *idxp = idx; - return nid; - } - } - return 0; -} - -static int is_active_pin(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int val; - val = snd_hda_codec_get_pincfg(codec, nid); - return (get_defcfg_connect(val) != AC_JACK_PORT_NONE); -} - -static int parse_output(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, extra_nids; - hda_nid_t dac; - - for (i = 0; i < cfg->line_outs; i++) { - dac = get_dac(codec, cfg->line_out_pins[i]); - if (!dac) - break; - spec->dac_nid[i] = dac; - } - spec->multiout.num_dacs = i; - spec->multiout.dac_nids = spec->dac_nid; - spec->multiout.max_channels = i * 2; - - /* add HP and speakers */ - extra_nids = 0; - for (i = 0; i < cfg->hp_outs; i++) { - dac = get_dac(codec, cfg->hp_pins[i]); - if (!dac) - break; - if (!i) - spec->multiout.hp_nid = dac; - else - spec->multiout.extra_out_nid[extra_nids++] = dac; - } - for (i = 0; i < cfg->speaker_outs; i++) { - dac = get_dac(codec, cfg->speaker_pins[i]); - if (!dac) - break; - spec->multiout.extra_out_nid[extra_nids++] = dac; - } - - if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { - cfg->speaker_outs = cfg->line_outs; - memcpy(cfg->speaker_pins, cfg->line_out_pins, - sizeof(cfg->speaker_pins)); - cfg->line_outs = 0; - } - - return 0; -} - -static int parse_input(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t pin = cfg->inputs[i].pin; - spec->input_idx[spec->num_inputs] = i; - spec->capsrc_idx[i] = spec->num_inputs++; - spec->cur_input = i; - spec->adc_nid[i] = get_adc(codec, pin, &spec->adc_idx[i]); - } - if (!spec->num_inputs) - return 0; - - /* check whether the automatic mic switch is available */ - if (spec->num_inputs == 2 && - cfg->inputs[0].type == AUTO_PIN_MIC && - cfg->inputs[1].type == AUTO_PIN_MIC) { - if (is_ext_mic(codec, cfg->inputs[0].pin)) { - if (!is_ext_mic(codec, cfg->inputs[1].pin)) { - spec->mic_detect = 1; - spec->automic_idx = 0; - } - } else { - if (is_ext_mic(codec, cfg->inputs[1].pin)) { - spec->mic_detect = 1; - spec->automic_idx = 1; - } - } - } - return 0; -} - - -static int parse_digital_output(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t nid; - - if (!cfg->dig_outs) - return 0; - if (snd_hda_get_connections(codec, cfg->dig_out_pins[0], &nid, 1) < 1) - return 0; - spec->multiout.dig_out_nid = nid; - spec->multiout.share_spdif = 1; - if (cfg->dig_outs > 1 && - snd_hda_get_connections(codec, cfg->dig_out_pins[1], &nid, 1) > 0) { - spec->slave_dig_outs[0] = nid; - codec->slave_dig_outs = spec->slave_dig_outs; - } - return 0; -} - -static int parse_digital_input(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int idx; - - if (cfg->dig_in_pin) - spec->dig_in = get_adc(codec, cfg->dig_in_pin, &idx); - return 0; -} - -/* - * create mixer controls - */ - -static const char * const dir_sfx[2] = { "Playback", "Capture" }; - -static int add_mute(struct hda_codec *codec, const char *name, int index, - unsigned int pval, int dir, struct snd_kcontrol **kctlp) -{ - char tmp[44]; - struct snd_kcontrol_new knew = - HDA_CODEC_MUTE_IDX(tmp, index, 0, 0, HDA_OUTPUT); - knew.private_value = pval; - snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); - *kctlp = snd_ctl_new1(&knew, codec); - (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG; - return snd_hda_ctl_add(codec, 0, *kctlp); -} - -static int add_volume(struct hda_codec *codec, const char *name, - int index, unsigned int pval, int dir, - struct snd_kcontrol **kctlp) -{ - char tmp[44]; - struct snd_kcontrol_new knew = - HDA_CODEC_VOLUME_IDX(tmp, index, 0, 0, HDA_OUTPUT); - knew.private_value = pval; - snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); - *kctlp = snd_ctl_new1(&knew, codec); - (*kctlp)->id.subdevice = HDA_SUBDEV_AMP_FLAG; - return snd_hda_ctl_add(codec, 0, *kctlp); -} - -static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) -{ - unsigned int caps; - - /* set the upper-limit for mixer amp to 0dB */ - caps = query_amp_caps(codec, dac, HDA_OUTPUT); - caps &= ~(0x7f << AC_AMPCAP_NUM_STEPS_SHIFT); - caps |= ((caps >> AC_AMPCAP_OFFSET_SHIFT) & 0x7f) - << AC_AMPCAP_NUM_STEPS_SHIFT; - snd_hda_override_amp_caps(codec, dac, HDA_OUTPUT, caps); -} - -static int add_vmaster(struct hda_codec *codec, hda_nid_t dac) -{ - struct cs_spec *spec = codec->spec; - unsigned int tlv[4]; - int err; - - spec->vmaster_sw = - snd_ctl_make_virtual_master("Master Playback Switch", NULL); - err = snd_hda_ctl_add(codec, dac, spec->vmaster_sw); - if (err < 0) - return err; - - snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv); - spec->vmaster_vol = - snd_ctl_make_virtual_master("Master Playback Volume", tlv); - err = snd_hda_ctl_add(codec, dac, spec->vmaster_vol); - if (err < 0) - return err; - return 0; -} - -static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx, - int num_ctls, int type) -{ - struct cs_spec *spec = codec->spec; - const char *name; - int err, index; - struct snd_kcontrol *kctl; - static const char * const speakers[] = { - "Front Speaker", "Surround Speaker", "Bass Speaker" - }; - static const char * const line_outs[] = { - "Front Line Out", "Surround Line Out", "Bass Line Out" - }; - - fix_volume_caps(codec, dac); - if (!spec->vmaster_sw) { - err = add_vmaster(codec, dac); - if (err < 0) - return err; - } - - index = 0; - switch (type) { - case AUTO_PIN_HP_OUT: - name = "Headphone"; - index = idx; - break; - case AUTO_PIN_SPEAKER_OUT: - if (num_ctls > 1) - name = speakers[idx]; - else - name = "Speaker"; - break; - default: - if (num_ctls > 1) - name = line_outs[idx]; - else - name = "Line Out"; - break; - } - - err = add_mute(codec, name, index, - HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl); - if (err < 0) - return err; - err = snd_ctl_add_slave(spec->vmaster_sw, kctl); - if (err < 0) - return err; - - err = add_volume(codec, name, index, - HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl); - if (err < 0) - return err; - err = snd_ctl_add_slave(spec->vmaster_vol, kctl); - if (err < 0) - return err; - - return 0; -} - -static int build_output(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, err; - - for (i = 0; i < cfg->line_outs; i++) { - err = add_output(codec, get_dac(codec, cfg->line_out_pins[i]), - i, cfg->line_outs, cfg->line_out_type); - if (err < 0) - return err; - } - for (i = 0; i < cfg->hp_outs; i++) { - err = add_output(codec, get_dac(codec, cfg->hp_pins[i]), - i, cfg->hp_outs, AUTO_PIN_HP_OUT); - if (err < 0) - return err; - } - for (i = 0; i < cfg->speaker_outs; i++) { - err = add_output(codec, get_dac(codec, cfg->speaker_pins[i]), - i, cfg->speaker_outs, AUTO_PIN_SPEAKER_OUT); - if (err < 0) - return err; - } - return 0; -} - -/* - */ - -static const struct snd_kcontrol_new cs_capture_ctls[] = { - HDA_BIND_SW("Capture Switch", 0), - HDA_BIND_VOL("Capture Volume", 0), -}; - -static int change_cur_input(struct hda_codec *codec, unsigned int idx, - int force) -{ - struct cs_spec *spec = codec->spec; - - if (spec->cur_input == idx && !force) - return 0; - if (spec->cur_adc && spec->cur_adc != spec->adc_nid[idx]) { - /* stream is running, let's swap the current ADC */ - __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); - spec->cur_adc = spec->adc_nid[idx]; - snd_hda_codec_setup_stream(codec, spec->cur_adc, - spec->cur_adc_stream_tag, 0, - spec->cur_adc_format); - } - spec->cur_input = idx; - cs_update_input_select(codec); - return 1; -} - -static int cs_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int idx; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = spec->num_inputs; - if (uinfo->value.enumerated.item >= spec->num_inputs) - uinfo->value.enumerated.item = spec->num_inputs - 1; - idx = spec->input_idx[uinfo->value.enumerated.item]; - snd_hda_get_pin_label(codec, cfg->inputs[idx].pin, cfg, - uinfo->value.enumerated.name, - sizeof(uinfo->value.enumerated.name), NULL); - return 0; -} - -static int cs_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs_spec *spec = codec->spec; - ucontrol->value.enumerated.item[0] = spec->capsrc_idx[spec->cur_input]; - return 0; -} - -static int cs_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs_spec *spec = codec->spec; - unsigned int idx = ucontrol->value.enumerated.item[0]; - - if (idx >= spec->num_inputs) - return -EINVAL; - idx = spec->input_idx[idx]; - return change_cur_input(codec, idx, 0); -} - -static const struct snd_kcontrol_new cs_capture_source = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = cs_capture_source_info, - .get = cs_capture_source_get, - .put = cs_capture_source_put, -}; - -static const struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec, - struct hda_ctl_ops *ops) -{ - struct cs_spec *spec = codec->spec; - struct hda_bind_ctls *bind; - int i, n; - - bind = kzalloc(sizeof(*bind) + sizeof(long) * (spec->num_inputs + 1), - GFP_KERNEL); - if (!bind) - return NULL; - bind->ops = ops; - n = 0; - for (i = 0; i < AUTO_PIN_LAST; i++) { - if (!spec->adc_nid[i]) - continue; - bind->values[n++] = - HDA_COMPOSE_AMP_VAL(spec->adc_nid[i], 3, - spec->adc_idx[i], HDA_INPUT); - } - return bind; -} - -/* add a (input-boost) volume control to the given input pin */ -static int add_input_volume_control(struct hda_codec *codec, - struct auto_pin_cfg *cfg, - int item) -{ - hda_nid_t pin = cfg->inputs[item].pin; - u32 caps; - const char *label; - struct snd_kcontrol *kctl; - - if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP)) - return 0; - caps = query_amp_caps(codec, pin, HDA_INPUT); - caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; - if (caps <= 1) - return 0; - label = hda_get_autocfg_input_label(codec, cfg, item); - return add_volume(codec, label, 0, - HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl); -} - -static int build_input(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - int i, err; - - if (!spec->num_inputs) - return 0; - - /* make bind-capture */ - spec->capture_bind[0] = make_bind_capture(codec, &snd_hda_bind_sw); - spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); - for (i = 0; i < 2; i++) { - struct snd_kcontrol *kctl; - int n; - if (!spec->capture_bind[i]) - return -ENOMEM; - kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = (long)spec->capture_bind[i]; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - for (n = 0; n < AUTO_PIN_LAST; n++) { - if (!spec->adc_nid[n]) - continue; - err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]); - if (err < 0) - return err; - } - } - - if (spec->num_inputs > 1 && !spec->mic_detect) { - err = snd_hda_ctl_add(codec, 0, - snd_ctl_new1(&cs_capture_source, codec)); - if (err < 0) - return err; - } - - for (i = 0; i < spec->num_inputs; i++) { - err = add_input_volume_control(codec, &spec->autocfg, i); - if (err < 0) - return err; - } - - return 0; -} - -/* - */ - -static int build_digital_output(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - int err; - - if (!spec->multiout.dig_out_nid) - return 0; - - err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - err = snd_hda_create_spdif_share_sw(codec, &spec->multiout); - if (err < 0) - return err; - return 0; -} - -static int build_digital_input(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - if (spec->dig_in) - return snd_hda_create_spdif_in_ctls(codec, spec->dig_in); - return 0; -} - -/* - * auto-mute and auto-mic switching - * CS421x auto-output redirecting - * HP/SPK/SPDIF - */ - -static void cs_automute(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int hp_present; - unsigned int spdif_present; - hda_nid_t nid; - int i; - - spdif_present = 0; - if (cfg->dig_outs) { - nid = cfg->dig_out_pins[0]; - if (is_jack_detectable(codec, nid)) { - /* - TODO: SPDIF output redirect when SENSE_B is enabled. - Shared (SENSE_A) jack (e.g HP/mini-TOSLINK) - assumed. - */ - if (snd_hda_jack_detect(codec, nid) - /* && spec->sense_b */) - spdif_present = 1; - } - } - - hp_present = 0; - for (i = 0; i < cfg->hp_outs; i++) { - nid = cfg->hp_pins[i]; - if (!is_jack_detectable(codec, nid)) - continue; - hp_present = snd_hda_jack_detect(codec, nid); - if (hp_present) - break; - } - - /* mute speakers if spdif or hp jack is plugged in */ - for (i = 0; i < cfg->speaker_outs; i++) { - int pin_ctl = hp_present ? 0 : PIN_OUT; - /* detect on spdif is specific to CS4210 */ - if (spdif_present && (spec->vendor_nid == CS4210_VENDOR_NID)) - pin_ctl = 0; - - nid = cfg->speaker_pins[i]; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl); - } - if (spec->gpio_eapd_hp) { - unsigned int gpio = hp_present ? - spec->gpio_eapd_hp : spec->gpio_eapd_speaker; - snd_hda_codec_write(codec, 0x01, 0, - AC_VERB_SET_GPIO_DATA, gpio); - } - - /* specific to CS4210 */ - if (spec->vendor_nid == CS4210_VENDOR_NID) { - /* mute HPs if spdif jack (SENSE_B) is present */ - for (i = 0; i < cfg->hp_outs; i++) { - nid = cfg->hp_pins[i]; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - (spdif_present && spec->sense_b) ? 0 : PIN_HP); - } - - /* SPDIF TX on/off */ - if (cfg->dig_outs) { - nid = cfg->dig_out_pins[0]; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - spdif_present ? PIN_OUT : 0); - - } - /* Update board GPIOs if neccessary ... */ - } -} - -/* - * Auto-input redirect for CS421x - * Switch max 3 inputs of a single ADC (nid 3) -*/ - -static void cs_automic(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t nid; - unsigned int present; - - nid = cfg->inputs[spec->automic_idx].pin; - present = snd_hda_jack_detect(codec, nid); - - /* specific to CS421x, single ADC */ - if (spec->vendor_nid == CS420X_VENDOR_NID) { - if (present) - change_cur_input(codec, spec->automic_idx, 0); - else - change_cur_input(codec, !spec->automic_idx, 0); - } else { - if (present) { - if (spec->cur_input != spec->automic_idx) { - spec->last_input = spec->cur_input; - spec->cur_input = spec->automic_idx; - } - } else { - spec->cur_input = spec->last_input; - } - cs_update_input_select(codec); - } -} - -/* - */ - -static void init_output(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - /* mute first */ - for (i = 0; i < spec->multiout.num_dacs; i++) - snd_hda_codec_write(codec, spec->multiout.dac_nids[i], 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); - if (spec->multiout.hp_nid) - snd_hda_codec_write(codec, spec->multiout.hp_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); - for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) { - if (!spec->multiout.extra_out_nid[i]) - break; - snd_hda_codec_write(codec, spec->multiout.extra_out_nid[i], 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); - } - - /* set appropriate pin controls */ - for (i = 0; i < cfg->line_outs; i++) - snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - /* HP */ - for (i = 0; i < cfg->hp_outs; i++) { - hda_nid_t nid = cfg->hp_pins[i]; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); - if (!cfg->speaker_outs) - continue; - if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { - snd_hda_jack_detect_enable(codec, nid, HP_EVENT); - spec->hp_detect = 1; - } - } - - /* Speaker */ - for (i = 0; i < cfg->speaker_outs; i++) - snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - - /* SPDIF is enabled on presence detect for CS421x */ - if (spec->hp_detect || spec->spdif_detect) - cs_automute(codec); -} - -static void init_input(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int coef; - int i; - - for (i = 0; i < cfg->num_inputs; i++) { - unsigned int ctl; - hda_nid_t pin = cfg->inputs[i].pin; - if (!spec->adc_nid[i]) - continue; - /* set appropriate pin control and mute first */ - ctl = PIN_IN; - if (cfg->inputs[i].type == AUTO_PIN_MIC) { - unsigned int caps = snd_hda_query_pin_caps(codec, pin); - caps >>= AC_PINCAP_VREF_SHIFT; - if (caps & AC_PINCAP_VREF_80) - ctl = PIN_VREF80; - } - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, ctl); - snd_hda_codec_write(codec, spec->adc_nid[i], 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_MUTE(spec->adc_idx[i])); - if (spec->mic_detect && spec->automic_idx == i) - snd_hda_jack_detect_enable(codec, pin, MIC_EVENT); - } - /* CS420x has multiple ADC, CS421x has single ADC */ - if (spec->vendor_nid == CS420X_VENDOR_NID) { - change_cur_input(codec, spec->cur_input, 1); - if (spec->mic_detect) - cs_automic(codec); - - coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ - if (is_active_pin(codec, CS_DMIC2_PIN_NID)) - coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ - if (is_active_pin(codec, CS_DMIC1_PIN_NID)) - coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off - * No effect if SPDIF_OUT2 is - * selected in IDX_SPDIF_CTL. - */ - cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); - } else { - if (spec->mic_detect) - cs_automic(codec); - else { - spec->cur_adc = spec->adc_nid[spec->cur_input]; - cs_update_input_select(codec); - } - } -} - -static const struct hda_verb cs_coef_init_verbs[] = { - {0x11, AC_VERB_SET_PROC_STATE, 1}, - {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, - {0x11, AC_VERB_SET_PROC_COEF, - (0x002a /* DAC1/2/3 SZCMode Soft Ramp */ - | 0x0040 /* Mute DACs on FIFO error */ - | 0x1000 /* Enable DACs High Pass Filter */ - | 0x0400 /* Disable Coefficient Auto increment */ - )}, - /* Beep */ - {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, - {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ - - {} /* terminator */ -}; - -/* Errata: CS4207 rev C0/C1/C2 Silicon - * - * http://www.cirrus.com/en/pubs/errata/ER880C3.pdf - * - * 6. At high temperature (TA > +85°C), the digital supply current (IVD) - * may be excessive (up to an additional 200 μA), which is most easily - * observed while the part is being held in reset (RESET# active low). - * - * Root Cause: At initial powerup of the device, the logic that drives - * the clock and write enable to the S/PDIF SRC RAMs is not properly - * initialized. - * Certain random patterns will cause a steady leakage current in those - * RAM cells. The issue will resolve once the SRCs are used (turned on). - * - * Workaround: The following verb sequence briefly turns on the S/PDIF SRC - * blocks, which will alleviate the issue. - */ - -static const struct hda_verb cs_errata_init_verbs[] = { - {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */ - {0x11, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */ - - {0x11, AC_VERB_SET_COEF_INDEX, 0x0008}, - {0x11, AC_VERB_SET_PROC_COEF, 0x9999}, - {0x11, AC_VERB_SET_COEF_INDEX, 0x0017}, - {0x11, AC_VERB_SET_PROC_COEF, 0xa412}, - {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, - {0x11, AC_VERB_SET_PROC_COEF, 0x0009}, - - {0x07, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Rx: D0 */ - {0x08, AC_VERB_SET_POWER_STATE, 0x00}, /* S/PDIF Tx: D0 */ - - {0x11, AC_VERB_SET_COEF_INDEX, 0x0017}, - {0x11, AC_VERB_SET_PROC_COEF, 0x2412}, - {0x11, AC_VERB_SET_COEF_INDEX, 0x0008}, - {0x11, AC_VERB_SET_PROC_COEF, 0x0000}, - {0x11, AC_VERB_SET_COEF_INDEX, 0x0001}, - {0x11, AC_VERB_SET_PROC_COEF, 0x0008}, - {0x11, AC_VERB_SET_PROC_STATE, 0x00}, - -#if 0 /* Don't to set to D3 as we are in power-up sequence */ - {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */ - {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */ - /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */ -#endif - - {} /* terminator */ -}; - -/* SPDIF setup */ -static void init_digital(struct hda_codec *codec) -{ - unsigned int coef; - - coef = 0x0002; /* SRC_MUTE soft-mute on SPDIF (if no lock) */ - coef |= 0x0008; /* Replace with mute on error */ - if (is_active_pin(codec, CS_DIG_OUT2_PIN_NID)) - coef |= 0x4000; /* RX to TX1 or TX2 Loopthru / SPDIF2 - * SPDIF_OUT2 is shared with GPIO1 and - * DMIC_SDA2. - */ - cs_vendor_coef_set(codec, IDX_SPDIF_CTL, coef); -} - -static int cs_init(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - - /* init_verb sequence for C0/C1/C2 errata*/ - snd_hda_sequence_write(codec, cs_errata_init_verbs); - - snd_hda_sequence_write(codec, cs_coef_init_verbs); - - if (spec->gpio_mask) { - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, - spec->gpio_mask); - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION, - spec->gpio_dir); - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - spec->gpio_data); - } - - init_output(codec); - init_input(codec); - init_digital(codec); - snd_hda_jack_report_sync(codec); - - return 0; -} - -static int cs_build_controls(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - int err; - - err = build_output(codec); - if (err < 0) - return err; - err = build_input(codec); - if (err < 0) - return err; - err = build_digital_output(codec); - if (err < 0) - return err; - err = build_digital_input(codec); - if (err < 0) - return err; - err = cs_init(codec); - if (err < 0) - return err; - - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); - if (err < 0) - return err; - - return 0; -} - -static void cs_free(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - kfree(spec->capture_bind[0]); - kfree(spec->capture_bind[1]); - kfree(codec->spec); -} - -static void cs_unsol_event(struct hda_codec *codec, unsigned int res) -{ - switch (snd_hda_jack_get_action(codec, res >> 26)) { - case HP_EVENT: - cs_automute(codec); - break; - case MIC_EVENT: - cs_automic(codec); - break; - } - snd_hda_jack_report_sync(codec); -} - -static const struct hda_codec_ops cs_patch_ops = { - .build_controls = cs_build_controls, - .build_pcms = cs_build_pcms, - .init = cs_init, - .free = cs_free, - .unsol_event = cs_unsol_event, -}; - -static int cs_parse_auto_config(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - int err; - - err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); - if (err < 0) - return err; - - err = parse_output(codec); - if (err < 0) - return err; - err = parse_input(codec); - if (err < 0) - return err; - err = parse_digital_output(codec); - if (err < 0) - return err; - err = parse_digital_input(codec); - if (err < 0) - return err; - return 0; -} - -static const char * const cs420x_models[CS420X_MODELS] = { - [CS420X_MBP53] = "mbp53", - [CS420X_MBP55] = "mbp55", - [CS420X_IMAC27] = "imac27", - [CS420X_IMAC27_122] = "imac27_122", - [CS420X_APPLE] = "apple", - [CS420X_AUTO] = "auto", -}; - - -static const struct snd_pci_quirk cs420x_cfg_tbl[] = { - SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), - SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), - SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), - SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), - /* this conflicts with too many other models */ - /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ - {} /* terminator */ -}; - -static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = { - SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), - SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), - {} /* terminator */ -}; - -struct cs_pincfg { - hda_nid_t nid; - u32 val; -}; - -static const struct cs_pincfg mbp53_pincfgs[] = { - { 0x09, 0x012b4050 }, - { 0x0a, 0x90100141 }, - { 0x0b, 0x90100140 }, - { 0x0c, 0x018b3020 }, - { 0x0d, 0x90a00110 }, - { 0x0e, 0x400000f0 }, - { 0x0f, 0x01cbe030 }, - { 0x10, 0x014be060 }, - { 0x12, 0x400000f0 }, - { 0x15, 0x400000f0 }, - {} /* terminator */ -}; - -static const struct cs_pincfg mbp55_pincfgs[] = { - { 0x09, 0x012b4030 }, - { 0x0a, 0x90100121 }, - { 0x0b, 0x90100120 }, - { 0x0c, 0x400000f0 }, - { 0x0d, 0x90a00110 }, - { 0x0e, 0x400000f0 }, - { 0x0f, 0x400000f0 }, - { 0x10, 0x014be040 }, - { 0x12, 0x400000f0 }, - { 0x15, 0x400000f0 }, - {} /* terminator */ -}; - -static const struct cs_pincfg imac27_pincfgs[] = { - { 0x09, 0x012b4050 }, - { 0x0a, 0x90100140 }, - { 0x0b, 0x90100142 }, - { 0x0c, 0x018b3020 }, - { 0x0d, 0x90a00110 }, - { 0x0e, 0x400000f0 }, - { 0x0f, 0x01cbe030 }, - { 0x10, 0x014be060 }, - { 0x12, 0x01ab9070 }, - { 0x15, 0x400000f0 }, - {} /* terminator */ -}; - -static const struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { - [CS420X_MBP53] = mbp53_pincfgs, - [CS420X_MBP55] = mbp55_pincfgs, - [CS420X_IMAC27] = imac27_pincfgs, -}; - -static void fix_pincfg(struct hda_codec *codec, int model, - const struct cs_pincfg **pin_configs) -{ - const struct cs_pincfg *cfg = pin_configs[model]; - if (!cfg) - return; - for (; cfg->nid; cfg++) - snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); -} - -static int patch_cs420x(struct hda_codec *codec) -{ - struct cs_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - - spec->vendor_nid = CS420X_VENDOR_NID; - - spec->board_config = - snd_hda_check_board_config(codec, CS420X_MODELS, - cs420x_models, cs420x_cfg_tbl); - if (spec->board_config < 0) - spec->board_config = - snd_hda_check_board_codec_sid_config(codec, - CS420X_MODELS, NULL, cs420x_codec_cfg_tbl); - if (spec->board_config >= 0) - fix_pincfg(codec, spec->board_config, cs_pincfgs); - - switch (spec->board_config) { - case CS420X_IMAC27: - case CS420X_MBP53: - case CS420X_MBP55: - case CS420X_APPLE: - spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */ - spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ - spec->gpio_mask = spec->gpio_dir = - spec->gpio_eapd_hp | spec->gpio_eapd_speaker; - break; - case CS420X_IMAC27_122: - spec->gpio_eapd_hp = 4; /* GPIO2 = headphones */ - spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ - spec->gpio_mask = spec->gpio_dir = - spec->gpio_eapd_hp | spec->gpio_eapd_speaker; - break; - } - - err = cs_parse_auto_config(codec); - if (err < 0) - goto error; - - codec->patch_ops = cs_patch_ops; - - return 0; - - error: - kfree(codec->spec); - codec->spec = NULL; - return err; -} - -/* - * Cirrus Logic CS4210 - * - * 1 DAC => HP(sense) / Speakers, - * 1 ADC <= LineIn(sense) / MicIn / DMicIn, - * 1 SPDIF OUT => SPDIF Trasmitter(sense) -*/ - -/* CS4210 board names */ -static const char *cs421x_models[CS421X_MODELS] = { - [CS421X_CDB4210] = "cdb4210", -}; - -static const struct snd_pci_quirk cs421x_cfg_tbl[] = { - /* Test Intel board + CDB2410 */ - SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210), - {} /* terminator */ -}; - -/* CS4210 board pinconfigs */ -/* Default CS4210 (CDB4210)*/ -static const struct cs_pincfg cdb4210_pincfgs[] = { - { 0x05, 0x0321401f }, - { 0x06, 0x90170010 }, - { 0x07, 0x03813031 }, - { 0x08, 0xb7a70037 }, - { 0x09, 0xb7a6003e }, - { 0x0a, 0x034510f0 }, - {} /* terminator */ -}; - -static const struct cs_pincfg *cs421x_pincfgs[CS421X_MODELS] = { - [CS421X_CDB4210] = cdb4210_pincfgs, -}; - -static const struct hda_verb cs421x_coef_init_verbs[] = { - {0x0B, AC_VERB_SET_PROC_STATE, 1}, - {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DEV_CFG}, - /* - Disable Coefficient Index Auto-Increment(DAI)=1, - PDREF=0 - */ - {0x0B, AC_VERB_SET_PROC_COEF, 0x0001 }, - - {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_ADC_CFG}, - /* ADC SZCMode = Digital Soft Ramp */ - {0x0B, AC_VERB_SET_PROC_COEF, 0x0002 }, - - {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DAC_CFG}, - {0x0B, AC_VERB_SET_PROC_COEF, - (0x0002 /* DAC SZCMode = Digital Soft Ramp */ - | 0x0004 /* Mute DAC on FIFO error */ - | 0x0008 /* Enable DAC High Pass Filter */ - )}, - {} /* terminator */ -}; - -/* Errata: CS4210 rev A1 Silicon - * - * http://www.cirrus.com/en/pubs/errata/ - * - * Description: - * 1. Performance degredation is present in the ADC. - * 2. Speaker output is not completely muted upon HP detect. - * 3. Noise is present when clipping occurs on the amplified - * speaker outputs. - * - * Workaround: - * The following verb sequence written to the registers during - * initialization will correct the issues listed above. - */ - -static const struct hda_verb cs421x_coef_init_verbs_A1_silicon_fixes[] = { - {0x0B, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */ - - {0x0B, AC_VERB_SET_COEF_INDEX, 0x0006}, - {0x0B, AC_VERB_SET_PROC_COEF, 0x9999}, /* Test mode: on */ - - {0x0B, AC_VERB_SET_COEF_INDEX, 0x000A}, - {0x0B, AC_VERB_SET_PROC_COEF, 0x14CB}, /* Chop double */ - - {0x0B, AC_VERB_SET_COEF_INDEX, 0x0011}, - {0x0B, AC_VERB_SET_PROC_COEF, 0xA2D0}, /* Increase ADC current */ - - {0x0B, AC_VERB_SET_COEF_INDEX, 0x001A}, - {0x0B, AC_VERB_SET_PROC_COEF, 0x02A9}, /* Mute speaker */ - - {0x0B, AC_VERB_SET_COEF_INDEX, 0x001B}, - {0x0B, AC_VERB_SET_PROC_COEF, 0X1006}, /* Remove noise */ - - {} /* terminator */ -}; - -/* Speaker Amp Gain is controlled by the vendor widget's coef 4 */ -static const DECLARE_TLV_DB_SCALE(cs421x_speaker_boost_db_scale, 900, 300, 0); - -static int cs421x_boost_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 3; - return 0; -} - -static int cs421x_boost_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL) & 0x0003; - return 0; -} - -static int cs421x_boost_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - - unsigned int vol = ucontrol->value.integer.value[0]; - unsigned int coef = - cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL); - unsigned int original_coef = coef; - - coef &= ~0x0003; - coef |= (vol & 0x0003); - if (original_coef == coef) - return 0; - else { - cs_vendor_coef_set(codec, CS421X_IDX_SPK_CTL, coef); - return 1; - } -} - -static const struct snd_kcontrol_new cs421x_speaker_bost_ctl = { - - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Speaker Boost Playback Volume", - .info = cs421x_boost_vol_info, - .get = cs421x_boost_vol_get, - .put = cs421x_boost_vol_put, - .tlv = { .p = cs421x_speaker_boost_db_scale }, -}; - -static void cs4210_pinmux_init(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - unsigned int def_conf, coef; - - /* GPIO, DMIC_SCL, DMIC_SDA and SENSE_B are multiplexed */ - coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG); - - if (spec->gpio_mask) - coef |= 0x0008; /* B1,B2 are GPIOs */ - else - coef &= ~0x0008; - - if (spec->sense_b) - coef |= 0x0010; /* B2 is SENSE_B, not inverted */ - else - coef &= ~0x0010; - - cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef); - - if ((spec->gpio_mask || spec->sense_b) && - is_active_pin(codec, CS421X_DMIC_PIN_NID)) { - - /* - GPIO or SENSE_B forced - disconnect the DMIC pin. - */ - def_conf = snd_hda_codec_get_pincfg(codec, CS421X_DMIC_PIN_NID); - def_conf &= ~AC_DEFCFG_PORT_CONN; - def_conf |= (AC_JACK_PORT_NONE << AC_DEFCFG_PORT_CONN_SHIFT); - snd_hda_codec_set_pincfg(codec, CS421X_DMIC_PIN_NID, def_conf); - } -} - -static void init_cs421x_digital(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - - for (i = 0; i < cfg->dig_outs; i++) { - hda_nid_t nid = cfg->dig_out_pins[i]; - if (!cfg->speaker_outs) - continue; - if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { - snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT); - spec->spdif_detect = 1; - } - } -} - -static int cs421x_init(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - - if (spec->vendor_nid == CS4210_VENDOR_NID) { - snd_hda_sequence_write(codec, cs421x_coef_init_verbs); - snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes); - cs4210_pinmux_init(codec); - } - - if (spec->gpio_mask) { - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, - spec->gpio_mask); - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION, - spec->gpio_dir); - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - spec->gpio_data); - } - - init_output(codec); - init_input(codec); - init_cs421x_digital(codec); - snd_hda_jack_report_sync(codec); - - return 0; -} - -/* - * CS4210 Input MUX (1 ADC) - */ -static int cs421x_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs_spec *spec = codec->spec; - - return snd_hda_input_mux_info(&spec->input_mux, uinfo); -} - -static int cs421x_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs_spec *spec = codec->spec; - - ucontrol->value.enumerated.item[0] = spec->cur_input; - return 0; -} - -static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs_spec *spec = codec->spec; - - return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol, - spec->adc_nid[0], &spec->cur_input); - -} - -static struct snd_kcontrol_new cs421x_capture_source = { - - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = cs421x_mux_enum_info, - .get = cs421x_mux_enum_get, - .put = cs421x_mux_enum_put, -}; - -static int cs421x_add_input_volume_control(struct hda_codec *codec, int item) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - const struct hda_input_mux *imux = &spec->input_mux; - hda_nid_t pin = cfg->inputs[item].pin; - struct snd_kcontrol *kctl; - u32 caps; - - if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP)) - return 0; - - caps = query_amp_caps(codec, pin, HDA_INPUT); - caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; - if (caps <= 1) - return 0; - - return add_volume(codec, imux->items[item].label, 0, - HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl); -} - -/* add a (input-boost) volume control to the given input pin */ -static int build_cs421x_input(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - struct hda_input_mux *imux = &spec->input_mux; - int i, err, type_idx; - const char *label; - - if (!spec->num_inputs) - return 0; - - /* make bind-capture */ - spec->capture_bind[0] = make_bind_capture(codec, &snd_hda_bind_sw); - spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol); - for (i = 0; i < 2; i++) { - struct snd_kcontrol *kctl; - int n; - if (!spec->capture_bind[i]) - return -ENOMEM; - kctl = snd_ctl_new1(&cs_capture_ctls[i], codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = (long)spec->capture_bind[i]; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - for (n = 0; n < AUTO_PIN_LAST; n++) { - if (!spec->adc_nid[n]) - continue; - err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]); - if (err < 0) - return err; - } - } - - /* Add Input MUX Items + Capture Volume/Switch */ - for (i = 0; i < spec->num_inputs; i++) { - label = hda_get_autocfg_input_label(codec, cfg, i); - snd_hda_add_imux_item(imux, label, spec->adc_idx[i], &type_idx); - - err = cs421x_add_input_volume_control(codec, i); - if (err < 0) - return err; - } - - /* - Add 'Capture Source' Switch if - * 2 inputs and no mic detec - * 3 inputs - */ - if ((spec->num_inputs == 2 && !spec->mic_detect) || - (spec->num_inputs == 3)) { - - err = snd_hda_ctl_add(codec, spec->adc_nid[0], - snd_ctl_new1(&cs421x_capture_source, codec)); - if (err < 0) - return err; - } - - return 0; -} - -/* Single DAC (Mute/Gain) */ -static int build_cs421x_output(struct hda_codec *codec) -{ - hda_nid_t dac = CS4210_DAC_NID; - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - struct snd_kcontrol *kctl; - int err; - char *name = "Master"; - - fix_volume_caps(codec, dac); - - err = add_mute(codec, name, 0, - HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl); - if (err < 0) - return err; - - err = add_volume(codec, name, 0, - HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl); - if (err < 0) - return err; - - if (cfg->speaker_outs && (spec->vendor_nid == CS4210_VENDOR_NID)) { - err = snd_hda_ctl_add(codec, 0, - snd_ctl_new1(&cs421x_speaker_bost_ctl, codec)); - if (err < 0) - return err; - } - return err; -} - -static int cs421x_build_controls(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - int err; - - err = build_cs421x_output(codec); - if (err < 0) - return err; - err = build_cs421x_input(codec); - if (err < 0) - return err; - err = build_digital_output(codec); - if (err < 0) - return err; - err = cs421x_init(codec); - if (err < 0) - return err; - - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); - if (err < 0) - return err; - - return 0; -} - -static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) -{ - switch (snd_hda_jack_get_action(codec, res >> 26)) { - case HP_EVENT: - case SPDIF_EVENT: - cs_automute(codec); - break; - - case MIC_EVENT: - cs_automic(codec); - break; - } - snd_hda_jack_report_sync(codec); -} - -static int parse_cs421x_input(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t pin = cfg->inputs[i].pin; - spec->adc_nid[i] = get_adc(codec, pin, &spec->adc_idx[i]); - spec->cur_input = spec->last_input = i; - spec->num_inputs++; - - /* check whether the automatic mic switch is available */ - if (is_ext_mic(codec, i) && cfg->num_inputs >= 2) { - spec->mic_detect = 1; - spec->automic_idx = i; - } - } - return 0; -} - -static int cs421x_parse_auto_config(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - int err; - - err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); - if (err < 0) - return err; - err = parse_output(codec); - if (err < 0) - return err; - err = parse_cs421x_input(codec); - if (err < 0) - return err; - err = parse_digital_output(codec); - if (err < 0) - return err; - return 0; -} - -#ifdef CONFIG_PM -/* - Manage PDREF, when transitioning to D3hot - (DAC,ADC) -> D3, PDREF=1, AFG->D3 -*/ -static int cs421x_suspend(struct hda_codec *codec, pm_message_t state) -{ - struct cs_spec *spec = codec->spec; - unsigned int coef; - - snd_hda_shutup_pins(codec); - - snd_hda_codec_write(codec, CS4210_DAC_NID, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - snd_hda_codec_write(codec, CS4210_ADC_NID, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - - if (spec->vendor_nid == CS4210_VENDOR_NID) { - coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG); - coef |= 0x0004; /* PDREF */ - cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef); - } - - return 0; -} -#endif - -static struct hda_codec_ops cs421x_patch_ops = { - .build_controls = cs421x_build_controls, - .build_pcms = cs_build_pcms, - .init = cs421x_init, - .free = cs_free, - .unsol_event = cs421x_unsol_event, -#ifdef CONFIG_PM - .suspend = cs421x_suspend, -#endif -}; - -static int patch_cs4210(struct hda_codec *codec) -{ - struct cs_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - - spec->vendor_nid = CS4210_VENDOR_NID; - - spec->board_config = - snd_hda_check_board_config(codec, CS421X_MODELS, - cs421x_models, cs421x_cfg_tbl); - if (spec->board_config >= 0) - fix_pincfg(codec, spec->board_config, cs421x_pincfgs); - /* - Setup GPIO/SENSE for each board (if used) - */ - switch (spec->board_config) { - case CS421X_CDB4210: - snd_printd("CS4210 board: %s\n", - cs421x_models[spec->board_config]); -/* spec->gpio_mask = 3; - spec->gpio_dir = 3; - spec->gpio_data = 3; -*/ - spec->sense_b = 1; - - break; - } - - /* - Update the GPIO/DMIC/SENSE_B pinmux before the configuration - is auto-parsed. If GPIO or SENSE_B is forced, DMIC input - is disabled. - */ - cs4210_pinmux_init(codec); - - err = cs421x_parse_auto_config(codec); - if (err < 0) - goto error; - - codec->patch_ops = cs421x_patch_ops; - - return 0; - - error: - kfree(codec->spec); - codec->spec = NULL; - return err; -} - -static int patch_cs4213(struct hda_codec *codec) -{ - struct cs_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - - spec->vendor_nid = CS4213_VENDOR_NID; - - err = cs421x_parse_auto_config(codec); - if (err < 0) - goto error; - - codec->patch_ops = cs421x_patch_ops; - return 0; - - error: - kfree(codec->spec); - codec->spec = NULL; - return err; -} - - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_cirrus[] = { - { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, - { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, - { .id = 0x10134210, .name = "CS4210", .patch = patch_cs4210 }, - { .id = 0x10134213, .name = "CS4213", .patch = patch_cs4213 }, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:10134206"); -MODULE_ALIAS("snd-hda-codec-id:10134207"); -MODULE_ALIAS("snd-hda-codec-id:10134210"); -MODULE_ALIAS("snd-hda-codec-id:10134213"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cirrus Logic HD-audio codec"); - -static struct hda_codec_preset_list cirrus_list = { - .preset = snd_hda_preset_cirrus, - .owner = THIS_MODULE, -}; - -static int __init patch_cirrus_init(void) -{ - return snd_hda_add_codec_preset(&cirrus_list); -} - -static void __exit patch_cirrus_exit(void) -{ - snd_hda_delete_codec_preset(&cirrus_list); -} - -module_init(patch_cirrus_init) -module_exit(patch_cirrus_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_cmedia.c b/ANDROID_3.4.5/sound/pci/hda/patch_cmedia.c deleted file mode 100644 index b6767b4c..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_cmedia.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * HD audio interface patch for C-Media CMI9880 - * - * Copyright (c) 2004 Takashi Iwai - * - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" -#define NUM_PINS 11 - - -/* board config type */ -enum { - CMI_MINIMAL, /* back 3-jack */ - CMI_MIN_FP, /* back 3-jack + front-panel 2-jack */ - CMI_FULL, /* back 6-jack + front-panel 2-jack */ - CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */ - CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */ - CMI_AUTO, /* let driver guess it */ - CMI_MODELS -}; - -struct cmi_spec { - int board_config; - unsigned int no_line_in: 1; /* no line-in (5-jack) */ - unsigned int front_panel: 1; /* has front-panel 2-jack */ - - /* playback */ - struct hda_multi_out multiout; - hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS]; /* NID for each DAC */ - int num_dacs; - - /* capture */ - const hda_nid_t *adc_nids; - hda_nid_t dig_in_nid; - - /* capture source */ - const struct hda_input_mux *input_mux; - unsigned int cur_mux[2]; - - /* channel mode */ - int num_channel_modes; - const struct hda_channel_mode *channel_modes; - - struct hda_pcm pcm_rec[2]; /* PCM information */ - - /* pin default configuration */ - hda_nid_t pin_nid[NUM_PINS]; - unsigned int def_conf[NUM_PINS]; - unsigned int pin_def_confs; - - /* multichannel pins */ - struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ -}; - -/* - * input MUX - */ -static int cmi_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cmi_spec *spec = codec->spec; - return snd_hda_input_mux_info(spec->input_mux, uinfo); -} - -static int cmi_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cmi_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; - return 0; -} - -static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cmi_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); -} - -/* - * shared line-in, mic for surrounds - */ - -/* 3-stack / 2 channel */ -static const struct hda_verb cmi9880_ch2_init[] = { - /* set line-in PIN for input */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - /* set mic PIN for input, also enable vref */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - /* route front PCM (DAC1) to HP */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, - {} -}; - -/* 3-stack / 6 channel */ -static const struct hda_verb cmi9880_ch6_init[] = { - /* set line-in PIN for output */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - /* set mic PIN for output */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - /* route front PCM (DAC1) to HP */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, - {} -}; - -/* 3-stack+front / 8 channel */ -static const struct hda_verb cmi9880_ch8_init[] = { - /* set line-in PIN for output */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - /* set mic PIN for output */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - /* route rear-surround PCM (DAC4) to HP */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, - {} -}; - -static const struct hda_channel_mode cmi9880_channel_modes[3] = { - { 2, cmi9880_ch2_init }, - { 6, cmi9880_ch6_init }, - { 8, cmi9880_ch8_init }, -}; - -static int cmi_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cmi_spec *spec = codec->spec; - return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes, - spec->num_channel_modes); -} - -static int cmi_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cmi_spec *spec = codec->spec; - return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes, - spec->num_channel_modes, spec->multiout.max_channels); -} - -static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct cmi_spec *spec = codec->spec; - return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes, - spec->num_channel_modes, &spec->multiout.max_channels); -} - -/* - */ -static const struct snd_kcontrol_new cmi9880_basic_mixer[] = { - /* CMI9880 has no playback volumes! */ - HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */ - HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = cmi_mux_enum_info, - .get = cmi_mux_enum_get, - .put = cmi_mux_enum_put, - }, - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT), - HDA_CODEC_VOLUME("Beep Playback Volume", 0x23, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Beep Playback Switch", 0x23, 0, HDA_OUTPUT), - { } /* end */ -}; - -/* - * shared I/O pins - */ -static const struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = cmi_ch_mode_info, - .get = cmi_ch_mode_get, - .put = cmi_ch_mode_put, - }, - { } /* end */ -}; - -/* AUD-in selections: - * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20 - */ -static const struct hda_input_mux cmi9880_basic_mux = { - .num_items = 4, - .items = { - { "Front Mic", 0x5 }, - { "Rear Mic", 0x2 }, - { "Line", 0x1 }, - { "CD", 0x7 }, - } -}; - -static const struct hda_input_mux cmi9880_no_line_mux = { - .num_items = 3, - .items = { - { "Front Mic", 0x5 }, - { "Rear Mic", 0x2 }, - { "CD", 0x7 }, - } -}; - -/* front, rear, clfe, rear_surr */ -static const hda_nid_t cmi9880_dac_nids[4] = { - 0x03, 0x04, 0x05, 0x06 -}; -/* ADC0, ADC1 */ -static const hda_nid_t cmi9880_adc_nids[2] = { - 0x08, 0x09 -}; - -#define CMI_DIG_OUT_NID 0x07 -#define CMI_DIG_IN_NID 0x0a - -/* - */ -static const struct hda_verb cmi9880_basic_init[] = { - /* port-D for line out (rear panel) */ - { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - /* port-E for HP out (front panel) */ - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - /* route front PCM to HP */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, - /* port-A for surround (rear panel) */ - { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - /* port-G for CLFE (rear panel) */ - { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, - /* port-H for side (rear panel) */ - { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, - /* port-C for line-in (rear panel) */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - /* port-B for mic-in (rear panel) with vref */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - /* port-F for mic-in (front panel) with vref */ - { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - /* CD-in */ - { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - /* route front mic to ADC1/2 */ - { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, - { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, - {} /* terminator */ -}; - -static const struct hda_verb cmi9880_allout_init[] = { - /* port-D for line out (rear panel) */ - { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - /* port-E for HP out (front panel) */ - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - /* route front PCM to HP */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, - /* port-A for side (rear panel) */ - { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - /* port-G for CLFE (rear panel) */ - { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, - /* port-H for side (rear panel) */ - { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, - /* port-C for surround (rear panel) */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - /* port-B for mic-in (rear panel) with vref */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - /* port-F for mic-in (front panel) with vref */ - { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - /* CD-in */ - { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - /* route front mic to ADC1/2 */ - { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, - { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, - {} /* terminator */ -}; - -/* - */ -static int cmi9880_build_controls(struct hda_codec *codec) -{ - struct cmi_spec *spec = codec->spec; - struct snd_kcontrol *kctl; - int i, err; - - err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer); - if (err < 0) - return err; - if (spec->channel_modes) { - err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer); - if (err < 0) - return err; - } - if (spec->multiout.dig_out_nid) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - err = snd_hda_create_spdif_share_sw(codec, - &spec->multiout); - if (err < 0) - return err; - spec->multiout.share_spdif = 1; - } - if (spec->dig_in_nid) { - err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); - if (err < 0) - return err; - } - - /* assign Capture Source enums to NID */ - kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); - for (i = 0; kctl && i < kctl->count; i++) { - err = snd_hda_add_nid(codec, kctl, i, spec->adc_nids[i]); - if (err < 0) - return err; - } - return 0; -} - -/* fill in the multi_dac_nids table, which will decide - which audio widget to use for each channel */ -static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) -{ - struct cmi_spec *spec = codec->spec; - hda_nid_t nid; - int assigned[4]; - int i, j; - - /* clear the table, only one c-media dac assumed here */ - memset(spec->dac_nids, 0, sizeof(spec->dac_nids)); - memset(assigned, 0, sizeof(assigned)); - /* check the pins we found */ - for (i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */ - if (nid >= 0x0b && nid <= 0x0e) { - spec->dac_nids[i] = (nid - 0x0b) + 0x03; - assigned[nid - 0x0b] = 1; - } - } - /* left pin can be connect to any audio widget */ - for (i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - if (nid <= 0x0e) - continue; - /* search for an empty channel */ - for (j = 0; j < cfg->line_outs; j++) { - if (! assigned[j]) { - spec->dac_nids[i] = j + 0x03; - assigned[j] = 1; - break; - } - } - } - spec->num_dacs = cfg->line_outs; - return 0; -} - -/* create multi_init table, which is used for multichannel initialization */ -static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pin_cfg *cfg) -{ - struct cmi_spec *spec = codec->spec; - hda_nid_t nid; - int i, j, k; - - /* clear the table, only one c-media dac assumed here */ - memset(spec->multi_init, 0, sizeof(spec->multi_init)); - for (j = 0, i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - /* set as output */ - spec->multi_init[j].nid = nid; - spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL; - spec->multi_init[j].param = PIN_OUT; - j++; - if (nid > 0x0e) { - /* set connection */ - spec->multi_init[j].nid = nid; - spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL; - spec->multi_init[j].param = 0; - /* find the index in connect list */ - k = snd_hda_get_conn_index(codec, nid, - spec->dac_nids[i], 0); - if (k >= 0) - spec->multi_init[j].param = k; - j++; - } - } - return 0; -} - -static int cmi9880_init(struct hda_codec *codec) -{ - struct cmi_spec *spec = codec->spec; - if (spec->board_config == CMI_ALLOUT) - snd_hda_sequence_write(codec, cmi9880_allout_init); - else - snd_hda_sequence_write(codec, cmi9880_basic_init); - if (spec->board_config == CMI_AUTO) - snd_hda_sequence_write(codec, spec->multi_init); - return 0; -} - -/* - * Analog playback callbacks - */ -static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cmi_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); -} - -static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct cmi_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, - format, substream); -} - -static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cmi_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -/* - * Digital out - */ -static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cmi_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cmi_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct cmi_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, - format, substream); -} - -/* - * Analog capture - */ -static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct cmi_spec *spec = codec->spec; - - snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], - stream_tag, 0, format); - return 0; -} - -static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct cmi_spec *spec = codec->spec; - - snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); - return 0; -} - - -/* - */ -static const struct hda_pcm_stream cmi9880_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 8, - .nid = 0x03, /* NID to query formats and rates */ - .ops = { - .open = cmi9880_playback_pcm_open, - .prepare = cmi9880_playback_pcm_prepare, - .cleanup = cmi9880_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream cmi9880_pcm_analog_capture = { - .substreams = 2, - .channels_min = 2, - .channels_max = 2, - .nid = 0x08, /* NID to query formats and rates */ - .ops = { - .prepare = cmi9880_capture_pcm_prepare, - .cleanup = cmi9880_capture_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream cmi9880_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in cmi9880_build_pcms */ - .ops = { - .open = cmi9880_dig_playback_pcm_open, - .close = cmi9880_dig_playback_pcm_close, - .prepare = cmi9880_dig_playback_pcm_prepare - }, -}; - -static const struct hda_pcm_stream cmi9880_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in cmi9880_build_pcms */ -}; - -static int cmi9880_build_pcms(struct hda_codec *codec) -{ - struct cmi_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->num_pcms = 1; - codec->pcm_info = info; - - info->name = "CMI9880"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture; - - if (spec->multiout.dig_out_nid || spec->dig_in_nid) { - codec->num_pcms++; - info++; - info->name = "CMI9880 Digital"; - info->pcm_type = HDA_PCM_TYPE_SPDIF; - if (spec->multiout.dig_out_nid) { - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; - } - if (spec->dig_in_nid) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; - } - } - - return 0; -} - -static void cmi9880_free(struct hda_codec *codec) -{ - kfree(codec->spec); -} - -/* - */ - -static const char * const cmi9880_models[CMI_MODELS] = { - [CMI_MINIMAL] = "minimal", - [CMI_MIN_FP] = "min_fp", - [CMI_FULL] = "full", - [CMI_FULL_DIG] = "full_dig", - [CMI_ALLOUT] = "allout", - [CMI_AUTO] = "auto", -}; - -static const struct snd_pci_quirk cmi9880_cfg_tbl[] = { - SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG), - SND_PCI_QUIRK(0x1854, 0x002b, "LG LS75", CMI_MINIMAL), - SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG), - {} /* terminator */ -}; - -static const struct hda_codec_ops cmi9880_patch_ops = { - .build_controls = cmi9880_build_controls, - .build_pcms = cmi9880_build_pcms, - .init = cmi9880_init, - .free = cmi9880_free, -}; - -static int patch_cmi9880(struct hda_codec *codec) -{ - struct cmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS, - cmi9880_models, - cmi9880_cfg_tbl); - if (spec->board_config < 0) { - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - spec->board_config = CMI_AUTO; /* try everything */ - } - - /* copy default DAC NIDs */ - memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); - spec->num_dacs = 4; - - switch (spec->board_config) { - case CMI_MINIMAL: - case CMI_MIN_FP: - spec->channel_modes = cmi9880_channel_modes; - if (spec->board_config == CMI_MINIMAL) - spec->num_channel_modes = 2; - else { - spec->front_panel = 1; - spec->num_channel_modes = 3; - } - spec->multiout.max_channels = cmi9880_channel_modes[0].channels; - spec->input_mux = &cmi9880_basic_mux; - break; - case CMI_FULL: - case CMI_FULL_DIG: - spec->front_panel = 1; - spec->multiout.max_channels = 8; - spec->input_mux = &cmi9880_basic_mux; - if (spec->board_config == CMI_FULL_DIG) { - spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; - spec->dig_in_nid = CMI_DIG_IN_NID; - } - break; - case CMI_ALLOUT: - spec->front_panel = 1; - spec->multiout.max_channels = 8; - spec->no_line_in = 1; - spec->input_mux = &cmi9880_no_line_mux; - spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; - break; - case CMI_AUTO: - { - unsigned int port_e, port_f, port_g, port_h; - unsigned int port_spdifi, port_spdifo; - struct auto_pin_cfg cfg; - - /* collect pin default configuration */ - port_e = snd_hda_codec_get_pincfg(codec, 0x0f); - port_f = snd_hda_codec_get_pincfg(codec, 0x10); - spec->front_panel = 1; - if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || - get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { - port_g = snd_hda_codec_get_pincfg(codec, 0x1f); - port_h = snd_hda_codec_get_pincfg(codec, 0x20); - spec->channel_modes = cmi9880_channel_modes; - /* no front panel */ - if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || - get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) { - /* no optional rear panel */ - spec->board_config = CMI_MINIMAL; - spec->front_panel = 0; - spec->num_channel_modes = 2; - } else { - spec->board_config = CMI_MIN_FP; - spec->num_channel_modes = 3; - } - spec->input_mux = &cmi9880_basic_mux; - spec->multiout.max_channels = cmi9880_channel_modes[0].channels; - } else { - spec->input_mux = &cmi9880_basic_mux; - port_spdifi = snd_hda_codec_get_pincfg(codec, 0x13); - port_spdifo = snd_hda_codec_get_pincfg(codec, 0x12); - if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) - spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; - if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) - spec->dig_in_nid = CMI_DIG_IN_NID; - spec->multiout.max_channels = 8; - } - snd_hda_parse_pin_def_config(codec, &cfg, NULL); - if (cfg.line_outs) { - spec->multiout.max_channels = cfg.line_outs * 2; - cmi9880_fill_multi_dac_nids(codec, &cfg); - cmi9880_fill_multi_init(codec, &cfg); - } else - snd_printd("patch_cmedia: cannot detect association in defcfg\n"); - break; - } - } - - spec->multiout.num_dacs = spec->num_dacs; - spec->multiout.dac_nids = spec->dac_nids; - - spec->adc_nids = cmi9880_adc_nids; - - codec->patch_ops = cmi9880_patch_ops; - - return 0; -} - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_cmedia[] = { - { .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 }, - { .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 }, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:13f69880"); -MODULE_ALIAS("snd-hda-codec-id:434d4980"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("C-Media HD-audio codec"); - -static struct hda_codec_preset_list cmedia_list = { - .preset = snd_hda_preset_cmedia, - .owner = THIS_MODULE, -}; - -static int __init patch_cmedia_init(void) -{ - return snd_hda_add_codec_preset(&cmedia_list); -} - -static void __exit patch_cmedia_exit(void) -{ - snd_hda_delete_codec_preset(&cmedia_list); -} - -module_init(patch_cmedia_init) -module_exit(patch_cmedia_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_conexant.c b/ANDROID_3.4.5/sound/pci/hda/patch_conexant.c deleted file mode 100644 index d906c5b7..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_conexant.c +++ /dev/null @@ -1,4599 +0,0 @@ -/* - * HD audio interface patch for Conexant HDA audio codec - * - * Copyright (c) 2006 Pototskiy Akex - * Takashi Iwai - * Tobin Davis - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" -#include "hda_beep.h" -#include "hda_jack.h" - -#define CXT_PIN_DIR_IN 0x00 -#define CXT_PIN_DIR_OUT 0x01 -#define CXT_PIN_DIR_INOUT 0x02 -#define CXT_PIN_DIR_IN_NOMICBIAS 0x03 -#define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04 - -#define CONEXANT_HP_EVENT 0x37 -#define CONEXANT_MIC_EVENT 0x38 -#define CONEXANT_LINE_EVENT 0x39 - -/* Conexant 5051 specific */ - -#define CXT5051_SPDIF_OUT 0x12 -#define CXT5051_PORTB_EVENT 0x38 -#define CXT5051_PORTC_EVENT 0x39 - -#define AUTO_MIC_PORTB (1 << 1) -#define AUTO_MIC_PORTC (1 << 2) - -struct pin_dac_pair { - hda_nid_t pin; - hda_nid_t dac; - int type; -}; - -struct imux_info { - hda_nid_t pin; /* input pin NID */ - hda_nid_t adc; /* connected ADC NID */ - hda_nid_t boost; /* optional boost volume NID */ - int index; /* corresponding to autocfg.input */ -}; - -struct conexant_spec { - - const struct snd_kcontrol_new *mixers[5]; - int num_mixers; - hda_nid_t vmaster_nid; - struct hda_vmaster_mute_hook vmaster_mute; - bool vmaster_mute_led; - - const struct hda_verb *init_verbs[5]; /* initialization verbs - * don't forget NULL - * termination! - */ - unsigned int num_init_verbs; - - /* playback */ - struct hda_multi_out multiout; /* playback set-up - * max_channels, dacs must be set - * dig_out_nid and hp_nid are optional - */ - unsigned int cur_eapd; - unsigned int hp_present; - unsigned int line_present; - unsigned int auto_mic; - int auto_mic_ext; /* imux_pins[] index for ext mic */ - int auto_mic_dock; /* imux_pins[] index for dock mic */ - int auto_mic_int; /* imux_pins[] index for int mic */ - unsigned int need_dac_fix; - hda_nid_t slave_dig_outs[2]; - - /* capture */ - unsigned int num_adc_nids; - const hda_nid_t *adc_nids; - hda_nid_t dig_in_nid; /* digital-in NID; optional */ - - unsigned int cur_adc_idx; - hda_nid_t cur_adc; - unsigned int cur_adc_stream_tag; - unsigned int cur_adc_format; - - const struct hda_pcm_stream *capture_stream; - - /* capture source */ - const struct hda_input_mux *input_mux; - const hda_nid_t *capsrc_nids; - unsigned int cur_mux[3]; - - /* channel model */ - const struct hda_channel_mode *channel_mode; - int num_channel_mode; - - /* PCM information */ - struct hda_pcm pcm_rec[2]; /* used in build_pcms() */ - - unsigned int spdif_route; - - /* dynamic controls, init_verbs and input_mux */ - struct auto_pin_cfg autocfg; - struct hda_input_mux private_imux; - struct imux_info imux_info[HDA_MAX_NUM_INPUTS]; - hda_nid_t private_adc_nids[HDA_MAX_NUM_INPUTS]; - hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; - struct pin_dac_pair dac_info[8]; - int dac_info_filled; - - unsigned int port_d_mode; - unsigned int auto_mute:1; /* used in auto-parser */ - unsigned int detect_line:1; /* Line-out detection enabled */ - unsigned int automute_lines:1; /* automute line-out as well */ - unsigned int automute_hp_lo:1; /* both HP and LO available */ - unsigned int dell_automute:1; - unsigned int dell_vostro:1; - unsigned int ideapad:1; - unsigned int thinkpad:1; - unsigned int hp_laptop:1; - unsigned int asus:1; - unsigned int pin_eapd_ctrls:1; - - unsigned int adc_switching:1; - - unsigned int ext_mic_present; - unsigned int recording; - void (*capture_prepare)(struct hda_codec *codec); - void (*capture_cleanup)(struct hda_codec *codec); - - /* OLPC XO-1.5 supports DC input mode (e.g. for use with analog sensors) - * through the microphone jack. - * When the user enables this through a mixer switch, both internal and - * external microphones are disabled. Gain is fixed at 0dB. In this mode, - * we also allow the bias to be configured through a separate mixer - * control. */ - unsigned int dc_enable; - unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */ - unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */ - - unsigned int beep_amp; - - /* extra EAPD pins */ - unsigned int num_eapds; - hda_nid_t eapds[4]; -}; - -static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); -} - -static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, - stream_tag, - format, substream); -} - -static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -/* - * Digital out - */ -static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, - stream_tag, - format, substream); -} - -/* - * Analog capture - */ -static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - if (spec->capture_prepare) - spec->capture_prepare(codec); - snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], - stream_tag, 0, format); - return 0; -} - -static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); - if (spec->capture_cleanup) - spec->capture_cleanup(codec); - return 0; -} - - - -static const struct hda_pcm_stream conexant_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .open = conexant_playback_pcm_open, - .prepare = conexant_playback_pcm_prepare, - .cleanup = conexant_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream conexant_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .prepare = conexant_capture_pcm_prepare, - .cleanup = conexant_capture_pcm_cleanup - }, -}; - - -static const struct hda_pcm_stream conexant_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .open = conexant_dig_playback_pcm_open, - .close = conexant_dig_playback_pcm_close, - .prepare = conexant_dig_playback_pcm_prepare - }, -}; - -static const struct hda_pcm_stream conexant_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in alc_build_pcms */ -}; - -static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - spec->cur_adc = spec->adc_nids[spec->cur_adc_idx]; - spec->cur_adc_stream_tag = stream_tag; - spec->cur_adc_format = format; - snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); - return 0; -} - -static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - snd_hda_codec_cleanup_stream(codec, spec->cur_adc); - spec->cur_adc = 0; - return 0; -} - -static const struct hda_pcm_stream cx5051_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .prepare = cx5051_capture_pcm_prepare, - .cleanup = cx5051_capture_pcm_cleanup - }, -}; - -static int conexant_build_pcms(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->num_pcms = 1; - codec->pcm_info = info; - - info->name = "CONEXANT Analog"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = - spec->multiout.max_channels; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->multiout.dac_nids[0]; - if (spec->capture_stream) - info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream; - else { - if (codec->vendor_id == 0x14f15051) - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - cx5051_pcm_analog_capture; - else { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - conexant_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = - spec->num_adc_nids; - } - } - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; - - if (spec->multiout.dig_out_nid) { - info++; - codec->num_pcms++; - info->name = "Conexant Digital"; - info->pcm_type = HDA_PCM_TYPE_SPDIF; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = - conexant_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->multiout.dig_out_nid; - if (spec->dig_in_nid) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - conexant_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = - spec->dig_in_nid; - } - if (spec->slave_dig_outs[0]) - codec->slave_dig_outs = spec->slave_dig_outs; - } - - return 0; -} - -static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - - return snd_hda_input_mux_info(spec->input_mux, uinfo); -} - -static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; - return 0; -} - -static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - spec->capsrc_nids[adc_idx], - &spec->cur_mux[adc_idx]); -} - -static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg, - unsigned int power_state) -{ - if (power_state == AC_PWRST_D3) - msleep(100); - snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, - power_state); - /* partial workaround for "azx_get_response timeout" */ - if (power_state == AC_PWRST_D0) - msleep(10); - snd_hda_codec_set_power_to_all(codec, fg, power_state, true); -} - -static int conexant_init(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->num_init_verbs; i++) - snd_hda_sequence_write(codec, spec->init_verbs[i]); - return 0; -} - -static void conexant_free(struct hda_codec *codec) -{ - snd_hda_detach_beep_device(codec); - kfree(codec->spec); -} - -static const struct snd_kcontrol_new cxt_capture_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = conexant_mux_enum_info, - .get = conexant_mux_enum_get, - .put = conexant_mux_enum_put - }, - {} -}; - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -/* additional beep mixers; the actual parameters are overwritten at build */ -static const struct snd_kcontrol_new cxt_beep_mixer[] = { - HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), - HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT), - { } /* end */ -}; -#endif - -static const char * const slave_pfxs[] = { - "Headphone", "Speaker", "Front", "Surround", "CLFE", - NULL -}; - -static int conexant_build_controls(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int i; - int err; - - for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - if (spec->multiout.dig_out_nid) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - err = snd_hda_create_spdif_share_sw(codec, - &spec->multiout); - if (err < 0) - return err; - spec->multiout.share_spdif = 1; - } - if (spec->dig_in_nid) { - err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid); - if (err < 0) - return err; - } - - /* if we have no master control, let's create it */ - if (spec->vmaster_nid && - !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { - unsigned int vmaster_tlv[4]; - snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, - HDA_OUTPUT, vmaster_tlv); - err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, slave_pfxs, - "Playback Volume"); - if (err < 0) - return err; - } - if (spec->vmaster_nid && - !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { - err = __snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, slave_pfxs, - "Playback Switch", true, - &spec->vmaster_mute.sw_kctl); - if (err < 0) - return err; - } - - if (spec->input_mux) { - err = snd_hda_add_new_ctls(codec, cxt_capture_mixers); - if (err < 0) - return err; - } - -#ifdef CONFIG_SND_HDA_INPUT_BEEP - /* create beep controls if needed */ - if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - for (knew = cxt_beep_mixer; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } - } -#endif - - return 0; -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static int conexant_suspend(struct hda_codec *codec, pm_message_t state) -{ - snd_hda_shutup_pins(codec); - return 0; -} -#endif - -static const struct hda_codec_ops conexant_patch_ops = { - .build_controls = conexant_build_controls, - .build_pcms = conexant_build_pcms, - .init = conexant_init, - .free = conexant_free, - .set_power_state = conexant_set_power, -#ifdef CONFIG_SND_HDA_POWER_SAVE - .suspend = conexant_suspend, -#endif - .reboot_notify = snd_hda_shutup_pins, -}; - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -#define set_beep_amp(spec, nid, idx, dir) \ - ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) -#else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ -#endif - -static int patch_conexant_auto(struct hda_codec *codec); -/* - * EAPD control - * the private value = nid | (invert << 8) - */ - -#define cxt_eapd_info snd_ctl_boolean_mono_info - -static int cxt_eapd_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - int invert = (kcontrol->private_value >> 8) & 1; - if (invert) - ucontrol->value.integer.value[0] = !spec->cur_eapd; - else - ucontrol->value.integer.value[0] = spec->cur_eapd; - return 0; - -} - -static int cxt_eapd_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - int invert = (kcontrol->private_value >> 8) & 1; - hda_nid_t nid = kcontrol->private_value & 0xff; - unsigned int eapd; - - eapd = !!ucontrol->value.integer.value[0]; - if (invert) - eapd = !eapd; - if (eapd == spec->cur_eapd) - return 0; - - spec->cur_eapd = eapd; - snd_hda_codec_write_cache(codec, nid, - 0, AC_VERB_SET_EAPD_BTLENABLE, - eapd ? 0x02 : 0x00); - return 1; -} - -/* controls for test mode */ -#ifdef CONFIG_SND_DEBUG - -#define CXT_EAPD_SWITCH(xname, nid, mask) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = cxt_eapd_info, \ - .get = cxt_eapd_get, \ - .put = cxt_eapd_put, \ - .private_value = nid | (mask<<16) } - - - -static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode, - spec->num_channel_mode); -} - -static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - spec->multiout.max_channels); -} - -static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - &spec->multiout.max_channels); - if (err >= 0 && spec->need_dac_fix) - spec->multiout.num_dacs = spec->multiout.max_channels / 2; - return err; -} - -#define CXT_PIN_MODE(xname, nid, dir) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = conexant_ch_mode_info, \ - .get = conexant_ch_mode_get, \ - .put = conexant_ch_mode_put, \ - .private_value = nid | (dir<<16) } - -#endif /* CONFIG_SND_DEBUG */ - -/* Conexant 5045 specific */ - -static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 }; -static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a }; -static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a }; -#define CXT5045_SPDIF_OUT 0x18 - -static const struct hda_channel_mode cxt5045_modes[1] = { - { 2, NULL }, -}; - -static const struct hda_input_mux cxt5045_capture_source = { - .num_items = 2, - .items = { - { "Internal Mic", 0x1 }, - { "Mic", 0x2 }, - } -}; - -static const struct hda_input_mux cxt5045_capture_source_benq = { - .num_items = 4, - .items = { - { "Internal Mic", 0x1 }, - { "Mic", 0x2 }, - { "Line", 0x3 }, - { "Mixer", 0x0 }, - } -}; - -static const struct hda_input_mux cxt5045_capture_source_hp530 = { - .num_items = 2, - .items = { - { "Mic", 0x1 }, - { "Internal Mic", 0x2 }, - } -}; - -/* turn on/off EAPD (+ mute HP) as a master switch */ -static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - unsigned int bits; - - if (!cxt_eapd_put(kcontrol, ucontrol)) - return 0; - - /* toggle internal speakers mute depending of presence of - * the headphone jack - */ - bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; - snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, - HDA_AMP_MUTE, bits); - - bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; - snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0, - HDA_AMP_MUTE, bits); - return 1; -} - -/* bind volumes of both NID 0x10 and 0x11 */ -static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT), - 0 - }, -}; - -/* toggle input of built-in and mic jack appropriately */ -static void cxt5045_hp_automic(struct hda_codec *codec) -{ - static const struct hda_verb mic_jack_on[] = { - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {} - }; - static const struct hda_verb mic_jack_off[] = { - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {} - }; - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x12); - if (present) - snd_hda_sequence_write(codec, mic_jack_on); - else - snd_hda_sequence_write(codec, mic_jack_off); -} - - -/* mute internal speaker if HP is plugged */ -static void cxt5045_hp_automute(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int bits; - - spec->hp_present = snd_hda_jack_detect(codec, 0x11); - - bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; - snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0, - HDA_AMP_MUTE, bits); -} - -/* unsolicited event for HP jack sensing */ -static void cxt5045_hp_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - res >>= 26; - switch (res) { - case CONEXANT_HP_EVENT: - cxt5045_hp_automute(codec); - break; - case CONEXANT_MIC_EVENT: - cxt5045_hp_automic(codec); - break; - - } -} - -static const struct snd_kcontrol_new cxt5045_mixers[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT), - HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = cxt_eapd_info, - .get = cxt_eapd_get, - .put = cxt5045_hp_master_sw_put, - .private_value = 0x10, - }, - - {} -}; - -static const struct snd_kcontrol_new cxt5045_benq_mixers[] = { - HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x3, HDA_INPUT), - - {} -}; - -static const struct snd_kcontrol_new cxt5045_mixers_hp530[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x1, HDA_INPUT), - HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = cxt_eapd_info, - .get = cxt_eapd_get, - .put = cxt5045_hp_master_sw_put, - .private_value = 0x10, - }, - - {} -}; - -static const struct hda_verb cxt5045_init_verbs[] = { - /* Line in, Mic */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, - /* HP, Amp */ - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* Record selector: Internal mic */ - {0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, - /* SPDIF route: PCM */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 }, - /* EAPD */ - {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ - { } /* end */ -}; - -static const struct hda_verb cxt5045_benq_init_verbs[] = { - /* Internal Mic, Mic */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 }, - /* Line In,HP, Amp */ - {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x11, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - /* Record selector: Internal mic */ - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x1}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, - /* SPDIF route: PCM */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* EAPD */ - {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - { } /* end */ -}; - -static const struct hda_verb cxt5045_hp_sense_init_verbs[] = { - /* pin sensing on HP jack */ - {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - { } /* end */ -}; - -static const struct hda_verb cxt5045_mic_sense_init_verbs[] = { - /* pin sensing on HP jack */ - {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - { } /* end */ -}; - -#ifdef CONFIG_SND_DEBUG -/* Test configuration for debugging, modelled after the ALC260 test - * configuration. - */ -static const struct hda_input_mux cxt5045_test_capture_source = { - .num_items = 5, - .items = { - { "MIXER", 0x0 }, - { "MIC1 pin", 0x1 }, - { "LINE1 pin", 0x2 }, - { "HP-OUT pin", 0x3 }, - { "CD pin", 0x4 }, - }, -}; - -static const struct snd_kcontrol_new cxt5045_test_mixer[] = { - - /* Output controls */ - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("HP-OUT Playback Volume", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("HP-OUT Playback Switch", 0x11, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x12, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("LINE1 Playback Switch", 0x12, 0x0, HDA_OUTPUT), - - /* Modes for retasking pin widgets */ - CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT), - CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT), - - /* EAPD Switch Control */ - CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0), - - /* Loopback mixer controls */ - - HDA_CODEC_VOLUME("PCM Volume", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("PCM Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("MIC1 pin Volume", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("MIC1 pin Switch", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("LINE1 pin Volume", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("LINE1 pin Switch", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("HP-OUT pin Volume", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("HP-OUT pin Switch", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME("CD pin Volume", 0x17, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("CD pin Switch", 0x17, 0x4, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .info = conexant_mux_enum_info, - .get = conexant_mux_enum_get, - .put = conexant_mux_enum_put, - }, - /* Audio input controls */ - HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT), - { } /* end */ -}; - -static const struct hda_verb cxt5045_test_init_verbs[] = { - /* Set connections */ - { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, - { 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 }, - { 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 }, - /* Enable retasking pins as output, initially without power amp */ - {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - - /* Disable digital (SPDIF) pins initially, but users can enable - * them via a mixer switch. In the case of SPDIF-out, this initverb - * payload also sets the generation to 0, output to be in "consumer" - * PCM format, copyright asserted, no pre-emphasis and no validity - * control. - */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, - - /* Unmute retasking pin widget output buffers since the default - * state appears to be output. As the pin mode is changed by the - * user the pin mode control will take care of enabling the pin's - * input/output buffers as needed. - */ - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* Mute capture amp left and right */ - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - - /* Set ADC connection select to match default mixer setting (mic1 - * pin) - */ - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, - {0x17, AC_VERB_SET_CONNECT_SEL, 0x01}, - - /* Mute all inputs to mixer widget (even unconnected ones) */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ - - { } -}; -#endif - - -/* initialize jack-sensing, too */ -static int cxt5045_init(struct hda_codec *codec) -{ - conexant_init(codec); - cxt5045_hp_automute(codec); - return 0; -} - - -enum { - CXT5045_LAPTOP_HPSENSE, - CXT5045_LAPTOP_MICSENSE, - CXT5045_LAPTOP_HPMICSENSE, - CXT5045_BENQ, - CXT5045_LAPTOP_HP530, -#ifdef CONFIG_SND_DEBUG - CXT5045_TEST, -#endif - CXT5045_AUTO, - CXT5045_MODELS -}; - -static const char * const cxt5045_models[CXT5045_MODELS] = { - [CXT5045_LAPTOP_HPSENSE] = "laptop-hpsense", - [CXT5045_LAPTOP_MICSENSE] = "laptop-micsense", - [CXT5045_LAPTOP_HPMICSENSE] = "laptop-hpmicsense", - [CXT5045_BENQ] = "benq", - [CXT5045_LAPTOP_HP530] = "laptop-hp530", -#ifdef CONFIG_SND_DEBUG - [CXT5045_TEST] = "test", -#endif - [CXT5045_AUTO] = "auto", -}; - -static const struct snd_pci_quirk cxt5045_cfg_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530), - SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE), - SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ), - SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE), - SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE), - SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", - CXT5045_LAPTOP_HPMICSENSE), - SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE), - SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE), - SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE), - SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell", - CXT5045_LAPTOP_HPMICSENSE), - SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE), - {} -}; - -static int patch_cxt5045(struct hda_codec *codec) -{ - struct conexant_spec *spec; - int board_config; - - board_config = snd_hda_check_board_config(codec, CXT5045_MODELS, - cxt5045_models, - cxt5045_cfg_tbl); - if (board_config < 0) - board_config = CXT5045_AUTO; /* model=auto as default */ - if (board_config == CXT5045_AUTO) - return patch_conexant_auto(codec); - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - codec->single_adc_amp = 1; - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids); - spec->multiout.dac_nids = cxt5045_dac_nids; - spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT; - spec->num_adc_nids = 1; - spec->adc_nids = cxt5045_adc_nids; - spec->capsrc_nids = cxt5045_capsrc_nids; - spec->input_mux = &cxt5045_capture_source; - spec->num_mixers = 1; - spec->mixers[0] = cxt5045_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = cxt5045_init_verbs; - spec->spdif_route = 0; - spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes); - spec->channel_mode = cxt5045_modes; - - set_beep_amp(spec, 0x16, 0, 1); - - codec->patch_ops = conexant_patch_ops; - - switch (board_config) { - case CXT5045_LAPTOP_HPSENSE: - codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; - spec->input_mux = &cxt5045_capture_source; - spec->num_init_verbs = 2; - spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; - spec->mixers[0] = cxt5045_mixers; - codec->patch_ops.init = cxt5045_init; - break; - case CXT5045_LAPTOP_MICSENSE: - codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; - spec->input_mux = &cxt5045_capture_source; - spec->num_init_verbs = 2; - spec->init_verbs[1] = cxt5045_mic_sense_init_verbs; - spec->mixers[0] = cxt5045_mixers; - codec->patch_ops.init = cxt5045_init; - break; - default: - case CXT5045_LAPTOP_HPMICSENSE: - codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; - spec->input_mux = &cxt5045_capture_source; - spec->num_init_verbs = 3; - spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; - spec->init_verbs[2] = cxt5045_mic_sense_init_verbs; - spec->mixers[0] = cxt5045_mixers; - codec->patch_ops.init = cxt5045_init; - break; - case CXT5045_BENQ: - codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; - spec->input_mux = &cxt5045_capture_source_benq; - spec->num_init_verbs = 1; - spec->init_verbs[0] = cxt5045_benq_init_verbs; - spec->mixers[0] = cxt5045_mixers; - spec->mixers[1] = cxt5045_benq_mixers; - spec->num_mixers = 2; - codec->patch_ops.init = cxt5045_init; - break; - case CXT5045_LAPTOP_HP530: - codec->patch_ops.unsol_event = cxt5045_hp_unsol_event; - spec->input_mux = &cxt5045_capture_source_hp530; - spec->num_init_verbs = 2; - spec->init_verbs[1] = cxt5045_hp_sense_init_verbs; - spec->mixers[0] = cxt5045_mixers_hp530; - codec->patch_ops.init = cxt5045_init; - break; -#ifdef CONFIG_SND_DEBUG - case CXT5045_TEST: - spec->input_mux = &cxt5045_test_capture_source; - spec->mixers[0] = cxt5045_test_mixer; - spec->init_verbs[0] = cxt5045_test_init_verbs; - break; - -#endif - } - - switch (codec->subsystem_id >> 16) { - case 0x103c: - case 0x1631: - case 0x1734: - case 0x17aa: - /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have - * really bad sound over 0dB on NID 0x17. Fix max PCM level to - * 0 dB (originally it has 0x2b steps with 0dB offset 0x14) - */ - snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, - (0x14 << AC_AMPCAP_OFFSET_SHIFT) | - (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) | - (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | - (1 << AC_AMPCAP_MUTE_SHIFT)); - break; - } - - if (spec->beep_amp) - snd_hda_attach_beep_device(codec, spec->beep_amp); - - return 0; -} - - -/* Conexant 5047 specific */ -#define CXT5047_SPDIF_OUT 0x11 - -static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */ -static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 }; -static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a }; - -static const struct hda_channel_mode cxt5047_modes[1] = { - { 2, NULL }, -}; - -static const struct hda_input_mux cxt5047_toshiba_capture_source = { - .num_items = 2, - .items = { - { "ExtMic", 0x2 }, - { "Line-In", 0x1 }, - } -}; - -/* turn on/off EAPD (+ mute HP) as a master switch */ -static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - unsigned int bits; - - if (!cxt_eapd_put(kcontrol, ucontrol)) - return 0; - - /* toggle internal speakers mute depending of presence of - * the headphone jack - */ - bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE; - /* NOTE: Conexat codec needs the index for *OUTPUT* amp of - * pin widgets unlike other codecs. In this case, we need to - * set index 0x01 for the volume from the mixer amp 0x19. - */ - snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, - HDA_AMP_MUTE, bits); - bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE; - snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0, - HDA_AMP_MUTE, bits); - return 1; -} - -/* mute internal speaker if HP is plugged */ -static void cxt5047_hp_automute(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int bits; - - spec->hp_present = snd_hda_jack_detect(codec, 0x13); - - bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; - /* See the note in cxt5047_hp_master_sw_put */ - snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01, - HDA_AMP_MUTE, bits); -} - -/* toggle input of built-in and mic jack appropriately */ -static void cxt5047_hp_automic(struct hda_codec *codec) -{ - static const struct hda_verb mic_jack_on[] = { - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {} - }; - static const struct hda_verb mic_jack_off[] = { - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {} - }; - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x15); - if (present) - snd_hda_sequence_write(codec, mic_jack_on); - else - snd_hda_sequence_write(codec, mic_jack_off); -} - -/* unsolicited event for HP jack sensing */ -static void cxt5047_hp_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - switch (res >> 26) { - case CONEXANT_HP_EVENT: - cxt5047_hp_automute(codec); - break; - case CONEXANT_MIC_EVENT: - cxt5047_hp_automic(codec); - break; - } -} - -static const struct snd_kcontrol_new cxt5047_base_mixers[] = { - HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT), - HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = cxt_eapd_info, - .get = cxt_eapd_get, - .put = cxt5047_hp_master_sw_put, - .private_value = 0x13, - }, - - {} -}; - -static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = { - /* See the note in cxt5047_hp_master_sw_put */ - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT), - {} -}; - -static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT), - { } /* end */ -}; - -static const struct hda_verb cxt5047_init_verbs[] = { - /* Line in, Mic, Built-in Mic */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 }, - /* HP, Speaker */ - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, - {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */ - {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */ - /* Record selector: Mic */ - {0x12, AC_VERB_SET_CONNECT_SEL,0x03}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17}, - {0x1A, AC_VERB_SET_CONNECT_SEL,0x02}, - {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00}, - {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, - /* SPDIF route: PCM */ - { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 }, - /* Enable unsolicited events */ - {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - { } /* end */ -}; - -/* configuration for Toshiba Laptops */ -static const struct hda_verb cxt5047_toshiba_init_verbs[] = { - {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */ - {} -}; - -/* Test configuration for debugging, modelled after the ALC260 test - * configuration. - */ -#ifdef CONFIG_SND_DEBUG -static const struct hda_input_mux cxt5047_test_capture_source = { - .num_items = 4, - .items = { - { "LINE1 pin", 0x0 }, - { "MIC1 pin", 0x1 }, - { "MIC2 pin", 0x2 }, - { "CD pin", 0x3 }, - }, -}; - -static const struct snd_kcontrol_new cxt5047_test_mixer[] = { - - /* Output only controls */ - HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT), - - /* Modes for retasking pin widgets */ - CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT), - CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT), - - /* EAPD Switch Control */ - CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0), - - /* Loopback mixer controls */ - HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT), - - HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT), - HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .info = conexant_mux_enum_info, - .get = conexant_mux_enum_get, - .put = conexant_mux_enum_put, - }, - HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT), - - { } /* end */ -}; - -static const struct hda_verb cxt5047_test_init_verbs[] = { - /* Enable retasking pins as output, initially without power amp */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - - /* Disable digital (SPDIF) pins initially, but users can enable - * them via a mixer switch. In the case of SPDIF-out, this initverb - * payload also sets the generation to 0, output to be in "consumer" - * PCM format, copyright asserted, no pre-emphasis and no validity - * control. - */ - {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0}, - - /* Ensure mic1, mic2, line1 pin widgets take input from the - * OUT1 sum bus when acting as an output. - */ - {0x1a, AC_VERB_SET_CONNECT_SEL, 0}, - {0x1b, AC_VERB_SET_CONNECT_SEL, 0}, - - /* Start with output sum widgets muted and their output gains at min */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - - /* Unmute retasking pin widget output buffers since the default - * state appears to be output. As the pin mode is changed by the - * user the pin mode control will take care of enabling the pin's - * input/output buffers as needed. - */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* Mute capture amp left and right */ - {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - - /* Set ADC connection select to match default mixer setting (mic1 - * pin) - */ - {0x12, AC_VERB_SET_CONNECT_SEL, 0x00}, - - /* Mute all inputs to mixer widget (even unconnected ones) */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */ - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */ - - { } -}; -#endif - - -/* initialize jack-sensing, too */ -static int cxt5047_hp_init(struct hda_codec *codec) -{ - conexant_init(codec); - cxt5047_hp_automute(codec); - return 0; -} - - -enum { - CXT5047_LAPTOP, /* Laptops w/o EAPD support */ - CXT5047_LAPTOP_HP, /* Some HP laptops */ - CXT5047_LAPTOP_EAPD, /* Laptops with EAPD support */ -#ifdef CONFIG_SND_DEBUG - CXT5047_TEST, -#endif - CXT5047_AUTO, - CXT5047_MODELS -}; - -static const char * const cxt5047_models[CXT5047_MODELS] = { - [CXT5047_LAPTOP] = "laptop", - [CXT5047_LAPTOP_HP] = "laptop-hp", - [CXT5047_LAPTOP_EAPD] = "laptop-eapd", -#ifdef CONFIG_SND_DEBUG - [CXT5047_TEST] = "test", -#endif - [CXT5047_AUTO] = "auto", -}; - -static const struct snd_pci_quirk cxt5047_cfg_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP), - SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series", - CXT5047_LAPTOP), - SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD), - {} -}; - -static int patch_cxt5047(struct hda_codec *codec) -{ - struct conexant_spec *spec; - int board_config; - - board_config = snd_hda_check_board_config(codec, CXT5047_MODELS, - cxt5047_models, - cxt5047_cfg_tbl); - if (board_config < 0) - board_config = CXT5047_AUTO; /* model=auto as default */ - if (board_config == CXT5047_AUTO) - return patch_conexant_auto(codec); - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - codec->pin_amp_workaround = 1; - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids); - spec->multiout.dac_nids = cxt5047_dac_nids; - spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT; - spec->num_adc_nids = 1; - spec->adc_nids = cxt5047_adc_nids; - spec->capsrc_nids = cxt5047_capsrc_nids; - spec->num_mixers = 1; - spec->mixers[0] = cxt5047_base_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = cxt5047_init_verbs; - spec->spdif_route = 0; - spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes), - spec->channel_mode = cxt5047_modes, - - codec->patch_ops = conexant_patch_ops; - - switch (board_config) { - case CXT5047_LAPTOP: - spec->num_mixers = 2; - spec->mixers[1] = cxt5047_hp_spk_mixers; - codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; - break; - case CXT5047_LAPTOP_HP: - spec->num_mixers = 2; - spec->mixers[1] = cxt5047_hp_only_mixers; - codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; - codec->patch_ops.init = cxt5047_hp_init; - break; - case CXT5047_LAPTOP_EAPD: - spec->input_mux = &cxt5047_toshiba_capture_source; - spec->num_mixers = 2; - spec->mixers[1] = cxt5047_hp_spk_mixers; - spec->num_init_verbs = 2; - spec->init_verbs[1] = cxt5047_toshiba_init_verbs; - codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; - break; -#ifdef CONFIG_SND_DEBUG - case CXT5047_TEST: - spec->input_mux = &cxt5047_test_capture_source; - spec->mixers[0] = cxt5047_test_mixer; - spec->init_verbs[0] = cxt5047_test_init_verbs; - codec->patch_ops.unsol_event = cxt5047_hp_unsol_event; -#endif - } - spec->vmaster_nid = 0x13; - - switch (codec->subsystem_id >> 16) { - case 0x103c: - /* HP laptops have really bad sound over 0 dB on NID 0x10. - * Fix max PCM level to 0 dB (originally it has 0x1e steps - * with 0 dB offset 0x17) - */ - snd_hda_override_amp_caps(codec, 0x10, 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; - } - - return 0; -} - -/* Conexant 5051 specific */ -static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 }; -static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 }; - -static const struct hda_channel_mode cxt5051_modes[1] = { - { 2, NULL }, -}; - -static void cxt5051_update_speaker(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int pinctl; - /* headphone pin */ - pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; - snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl); - /* speaker pin */ - pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl); - /* on ideapad there is an additional speaker (subwoofer) to mute */ - if (spec->ideapad) - snd_hda_codec_write(codec, 0x1b, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl); -} - -/* turn on/off EAPD (+ mute HP) as a master switch */ -static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - - if (!cxt_eapd_put(kcontrol, ucontrol)) - return 0; - cxt5051_update_speaker(codec); - return 1; -} - -/* toggle input of built-in and mic jack appropriately */ -static void cxt5051_portb_automic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int present; - - if (!(spec->auto_mic & AUTO_MIC_PORTB)) - return; - present = snd_hda_jack_detect(codec, 0x17); - snd_hda_codec_write(codec, 0x14, 0, - AC_VERB_SET_CONNECT_SEL, - present ? 0x01 : 0x00); -} - -/* switch the current ADC according to the jack state */ -static void cxt5051_portc_automic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int present; - hda_nid_t new_adc; - - if (!(spec->auto_mic & AUTO_MIC_PORTC)) - return; - present = snd_hda_jack_detect(codec, 0x18); - if (present) - spec->cur_adc_idx = 1; - else - spec->cur_adc_idx = 0; - new_adc = spec->adc_nids[spec->cur_adc_idx]; - if (spec->cur_adc && spec->cur_adc != new_adc) { - /* stream is running, let's swap the current ADC */ - __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); - spec->cur_adc = new_adc; - snd_hda_codec_setup_stream(codec, new_adc, - spec->cur_adc_stream_tag, 0, - spec->cur_adc_format); - } -} - -/* mute internal speaker if HP is plugged */ -static void cxt5051_hp_automute(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - - spec->hp_present = snd_hda_jack_detect(codec, 0x16); - cxt5051_update_speaker(codec); -} - -/* unsolicited event for HP jack sensing */ -static void cxt5051_hp_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - switch (res >> 26) { - case CONEXANT_HP_EVENT: - cxt5051_hp_automute(codec); - break; - case CXT5051_PORTB_EVENT: - cxt5051_portb_automic(codec); - break; - case CXT5051_PORTC_EVENT: - cxt5051_portc_automic(codec); - break; - } -} - -static const struct snd_kcontrol_new cxt5051_playback_mixers[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = cxt_eapd_info, - .get = cxt_eapd_get, - .put = cxt5051_hp_master_sw_put, - .private_value = 0x1a, - }, - {} -}; - -static const struct snd_kcontrol_new cxt5051_capture_mixers[] = { - HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT), - {} -}; - -static const struct snd_kcontrol_new cxt5051_hp_mixers[] = { - HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT), - {} -}; - -static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT), - {} -}; - -static const struct snd_kcontrol_new cxt5051_f700_mixers[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT), - {} -}; - -static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = { - HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT), - HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), - {} -}; - -static const struct hda_verb cxt5051_init_verbs[] = { - /* Line in, Mic */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, - /* SPK */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* HP, Amp */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Record selector: Internal mic */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44}, - /* SPDIF route: PCM */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* EAPD */ - {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, - { } /* end */ -}; - -static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { - /* Line in, Mic */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, - /* SPK */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* HP, Amp */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Record selector: Internal mic */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* SPDIF route: PCM */ - {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* EAPD */ - {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, - { } /* end */ -}; - -static const struct hda_verb cxt5051_f700_init_verbs[] = { - /* Line in, Mic */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03}, - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, - /* SPK */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* HP, Amp */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - /* Record selector: Internal mic */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x1}, - /* SPDIF route: PCM */ - {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* EAPD */ - {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, - { } /* end */ -}; - -static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, - unsigned int event) -{ - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_UNSOLICITED_ENABLE, - AC_USRSP_EN | event); -} - -static const struct hda_verb cxt5051_ideapad_init_verbs[] = { - /* Subwoofer */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, - { } /* end */ -}; - -/* initialize jack-sensing, too */ -static int cxt5051_init(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - - conexant_init(codec); - - if (spec->auto_mic & AUTO_MIC_PORTB) - cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT); - if (spec->auto_mic & AUTO_MIC_PORTC) - cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT); - - if (codec->patch_ops.unsol_event) { - cxt5051_hp_automute(codec); - cxt5051_portb_automic(codec); - cxt5051_portc_automic(codec); - } - return 0; -} - - -enum { - CXT5051_LAPTOP, /* Laptops w/ EAPD support */ - CXT5051_HP, /* no docking */ - CXT5051_HP_DV6736, /* HP without mic switch */ - CXT5051_F700, /* HP Compaq Presario F700 */ - CXT5051_TOSHIBA, /* Toshiba M300 & co */ - CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */ - CXT5051_AUTO, /* auto-parser */ - CXT5051_MODELS -}; - -static const char *const cxt5051_models[CXT5051_MODELS] = { - [CXT5051_LAPTOP] = "laptop", - [CXT5051_HP] = "hp", - [CXT5051_HP_DV6736] = "hp-dv6736", - [CXT5051_F700] = "hp-700", - [CXT5051_TOSHIBA] = "toshiba", - [CXT5051_IDEAPAD] = "ideapad", - [CXT5051_AUTO] = "auto", -}; - -static const struct snd_pci_quirk cxt5051_cfg_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), - SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), - SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700), - SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA), - SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", - CXT5051_LAPTOP), - SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), - SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD), - {} -}; - -static int patch_cxt5051(struct hda_codec *codec) -{ - struct conexant_spec *spec; - int board_config; - - board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, - cxt5051_models, - cxt5051_cfg_tbl); - if (board_config < 0) - board_config = CXT5051_AUTO; /* model=auto as default */ - if (board_config == CXT5051_AUTO) - return patch_conexant_auto(codec); - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - codec->pin_amp_workaround = 1; - - codec->patch_ops = conexant_patch_ops; - codec->patch_ops.init = cxt5051_init; - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids); - spec->multiout.dac_nids = cxt5051_dac_nids; - spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT; - spec->num_adc_nids = 1; /* not 2; via auto-mic switch */ - spec->adc_nids = cxt5051_adc_nids; - spec->num_mixers = 2; - spec->mixers[0] = cxt5051_capture_mixers; - spec->mixers[1] = cxt5051_playback_mixers; - spec->num_init_verbs = 1; - spec->init_verbs[0] = cxt5051_init_verbs; - spec->spdif_route = 0; - spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes); - spec->channel_mode = cxt5051_modes; - spec->cur_adc = 0; - spec->cur_adc_idx = 0; - - set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); - - codec->patch_ops.unsol_event = cxt5051_hp_unsol_event; - - spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC; - switch (board_config) { - case CXT5051_HP: - spec->mixers[0] = cxt5051_hp_mixers; - break; - case CXT5051_HP_DV6736: - spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; - spec->mixers[0] = cxt5051_hp_dv6736_mixers; - spec->auto_mic = 0; - break; - case CXT5051_F700: - spec->init_verbs[0] = cxt5051_f700_init_verbs; - spec->mixers[0] = cxt5051_f700_mixers; - spec->auto_mic = 0; - break; - case CXT5051_TOSHIBA: - spec->mixers[0] = cxt5051_toshiba_mixers; - spec->auto_mic = AUTO_MIC_PORTB; - break; - case CXT5051_IDEAPAD: - spec->init_verbs[spec->num_init_verbs++] = - cxt5051_ideapad_init_verbs; - spec->ideapad = 1; - break; - } - - if (spec->beep_amp) - snd_hda_attach_beep_device(codec, spec->beep_amp); - - return 0; -} - -/* Conexant 5066 specific */ - -static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 }; -static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 }; -static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 }; -static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 }; - -/* OLPC's microphone port is DC coupled for use with external sensors, - * therefore we use a 50% mic bias in order to center the input signal with - * the DC input range of the codec. */ -#define CXT5066_OLPC_EXT_MIC_BIAS PIN_VREF50 - -static const struct hda_channel_mode cxt5066_modes[1] = { - { 2, NULL }, -}; - -#define HP_PRESENT_PORT_A (1 << 0) -#define HP_PRESENT_PORT_D (1 << 1) -#define hp_port_a_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_A) -#define hp_port_d_present(spec) ((spec)->hp_present & HP_PRESENT_PORT_D) - -static void cxt5066_update_speaker(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int pinctl; - - snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n", - spec->hp_present, spec->cur_eapd); - - /* Port A (HP) */ - pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; - snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl); - - /* Port D (HP/LO) */ - pinctl = spec->cur_eapd ? spec->port_d_mode : 0; - if (spec->dell_automute || spec->thinkpad) { - /* Mute if Port A is connected */ - if (hp_port_a_present(spec)) - pinctl = 0; - } else { - /* Thinkpad/Dell doesn't give pin-D status */ - if (!hp_port_d_present(spec)) - pinctl = 0; - } - snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl); - - /* CLASS_D AMP */ - pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; - snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl); -} - -/* turn on/off EAPD (+ mute HP) as a master switch */ -static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - - if (!cxt_eapd_put(kcontrol, ucontrol)) - return 0; - - cxt5066_update_speaker(codec); - return 1; -} - -static const struct hda_input_mux cxt5066_olpc_dc_bias = { - .num_items = 3, - .items = { - { "Off", PIN_IN }, - { "50%", PIN_VREF50 }, - { "80%", PIN_VREF80 }, - }, -}; - -static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - /* Even though port F is the DC input, the bias is controlled on port B. - * we also leave that port as an active input (but unselected) in DC mode - * just in case that is necessary to make the bias setting take effect. */ - return snd_hda_codec_write_cache(codec, 0x1a, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); -} - -/* OLPC defers mic widget control until when capture is started because the - * microphone LED comes on as soon as these settings are put in place. if we - * did this before recording, it would give the false indication that recording - * is happening when it is not. */ -static void cxt5066_olpc_select_mic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - if (!spec->recording) - return; - - if (spec->dc_enable) { - /* in DC mode we ignore presence detection and just use the jack - * through our special DC port */ - const struct hda_verb enable_dc_mode[] = { - /* disble internal mic, port C */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* enable DC capture, port F */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {}, - }; - - snd_hda_sequence_write(codec, enable_dc_mode); - /* port B input disabled (and bias set) through the following call */ - cxt5066_set_olpc_dc_bias(codec); - return; - } - - /* disable DC (port F) */ - snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0); - - /* external mic, port B */ - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); - - /* internal mic, port C */ - snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - spec->ext_mic_present ? 0 : PIN_VREF80); -} - -/* toggle input of built-in and mic jack appropriately */ -static void cxt5066_olpc_automic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int present; - - if (spec->dc_enable) /* don't do presence detection in DC mode */ - return; - - present = snd_hda_codec_read(codec, 0x1a, 0, - AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; - if (present) - snd_printdd("CXT5066: external microphone detected\n"); - else - snd_printdd("CXT5066: external microphone absent\n"); - - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, - present ? 0 : 1); - spec->ext_mic_present = !!present; - - cxt5066_olpc_select_mic(codec); -} - -/* toggle input of built-in digital mic and mic jack appropriately */ -static void cxt5066_vostro_automic(struct hda_codec *codec) -{ - unsigned int present; - - struct hda_verb ext_mic_present[] = { - /* enable external mic, port B */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - - /* switch to external mic input */ - {0x17, AC_VERB_SET_CONNECT_SEL, 0}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0}, - - /* disable internal digital mic */ - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {} - }; - static const struct hda_verb ext_mic_absent[] = { - /* enable internal mic, port C */ - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - /* switch to internal mic input */ - {0x14, AC_VERB_SET_CONNECT_SEL, 2}, - - /* disable external mic, port B */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {} - }; - - present = snd_hda_jack_detect(codec, 0x1a); - if (present) { - snd_printdd("CXT5066: external microphone detected\n"); - snd_hda_sequence_write(codec, ext_mic_present); - } else { - snd_printdd("CXT5066: external microphone absent\n"); - snd_hda_sequence_write(codec, ext_mic_absent); - } -} - -/* toggle input of built-in digital mic and mic jack appropriately */ -static void cxt5066_ideapad_automic(struct hda_codec *codec) -{ - unsigned int present; - - struct hda_verb ext_mic_present[] = { - {0x14, AC_VERB_SET_CONNECT_SEL, 0}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {} - }; - static const struct hda_verb ext_mic_absent[] = { - {0x14, AC_VERB_SET_CONNECT_SEL, 2}, - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {} - }; - - present = snd_hda_jack_detect(codec, 0x1b); - if (present) { - snd_printdd("CXT5066: external microphone detected\n"); - snd_hda_sequence_write(codec, ext_mic_present); - } else { - snd_printdd("CXT5066: external microphone absent\n"); - snd_hda_sequence_write(codec, ext_mic_absent); - } -} - - -/* toggle input of built-in digital mic and mic jack appropriately */ -static void cxt5066_asus_automic(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x1b); - snd_printdd("CXT5066: external microphone present=%d\n", present); - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, - present ? 1 : 0); -} - - -/* toggle input of built-in digital mic and mic jack appropriately */ -static void cxt5066_hp_laptop_automic(struct hda_codec *codec) -{ - unsigned int present; - - present = snd_hda_jack_detect(codec, 0x1b); - snd_printdd("CXT5066: external microphone present=%d\n", present); - snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL, - present ? 1 : 3); -} - - -/* toggle input of built-in digital mic and mic jack appropriately - order is: external mic -> dock mic -> interal mic */ -static void cxt5066_thinkpad_automic(struct hda_codec *codec) -{ - unsigned int ext_present, dock_present; - - static const struct hda_verb ext_mic_present[] = { - {0x14, AC_VERB_SET_CONNECT_SEL, 0}, - {0x17, AC_VERB_SET_CONNECT_SEL, 1}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {} - }; - static const struct hda_verb dock_mic_present[] = { - {0x14, AC_VERB_SET_CONNECT_SEL, 0}, - {0x17, AC_VERB_SET_CONNECT_SEL, 0}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {} - }; - static const struct hda_verb ext_mic_absent[] = { - {0x14, AC_VERB_SET_CONNECT_SEL, 2}, - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {} - }; - - ext_present = snd_hda_jack_detect(codec, 0x1b); - dock_present = snd_hda_jack_detect(codec, 0x1a); - if (ext_present) { - snd_printdd("CXT5066: external microphone detected\n"); - snd_hda_sequence_write(codec, ext_mic_present); - } else if (dock_present) { - snd_printdd("CXT5066: dock microphone detected\n"); - snd_hda_sequence_write(codec, dock_mic_present); - } else { - snd_printdd("CXT5066: external microphone absent\n"); - snd_hda_sequence_write(codec, ext_mic_absent); - } -} - -/* mute internal speaker if HP is plugged */ -static void cxt5066_hp_automute(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - unsigned int portA, portD; - - /* Port A */ - portA = snd_hda_jack_detect(codec, 0x19); - - /* Port D */ - portD = snd_hda_jack_detect(codec, 0x1c); - - spec->hp_present = portA ? HP_PRESENT_PORT_A : 0; - spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0; - snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n", - portA, portD, spec->hp_present); - cxt5066_update_speaker(codec); -} - -/* Dispatch the right mic autoswitch function */ -static void cxt5066_automic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - - if (spec->dell_vostro) - cxt5066_vostro_automic(codec); - else if (spec->ideapad) - cxt5066_ideapad_automic(codec); - else if (spec->thinkpad) - cxt5066_thinkpad_automic(codec); - else if (spec->hp_laptop) - cxt5066_hp_laptop_automic(codec); - else if (spec->asus) - cxt5066_asus_automic(codec); -} - -/* unsolicited event for jack sensing */ -static void cxt5066_olpc_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct conexant_spec *spec = codec->spec; - snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); - switch (res >> 26) { - case CONEXANT_HP_EVENT: - cxt5066_hp_automute(codec); - break; - case CONEXANT_MIC_EVENT: - /* ignore mic events in DC mode; we're always using the jack */ - if (!spec->dc_enable) - cxt5066_olpc_automic(codec); - break; - } -} - -/* unsolicited event for jack sensing */ -static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res) -{ - snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26); - switch (res >> 26) { - case CONEXANT_HP_EVENT: - cxt5066_hp_automute(codec); - break; - case CONEXANT_MIC_EVENT: - cxt5066_automic(codec); - break; - } -} - - -static const struct hda_input_mux cxt5066_analog_mic_boost = { - .num_items = 5, - .items = { - { "0dB", 0 }, - { "10dB", 1 }, - { "20dB", 2 }, - { "30dB", 3 }, - { "40dB", 4 }, - }, -}; - -static void cxt5066_set_mic_boost(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - snd_hda_codec_write_cache(codec, 0x17, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | - cxt5066_analog_mic_boost.items[spec->mic_boost].index); - if (spec->ideapad || spec->thinkpad) { - /* adjust the internal mic as well...it is not through 0x17 */ - snd_hda_codec_write_cache(codec, 0x23, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT | - cxt5066_analog_mic_boost. - items[spec->mic_boost].index); - } -} - -static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo); -} - -static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - ucontrol->value.enumerated.item[0] = spec->mic_boost; - return 0; -} - -static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; - unsigned int idx; - idx = ucontrol->value.enumerated.item[0]; - if (idx >= imux->num_items) - idx = imux->num_items - 1; - - spec->mic_boost = idx; - if (!spec->dc_enable) - cxt5066_set_mic_boost(codec); - return 1; -} - -static void cxt5066_enable_dc(struct hda_codec *codec) -{ - const struct hda_verb enable_dc_mode[] = { - /* disable gain */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* switch to DC input */ - {0x17, AC_VERB_SET_CONNECT_SEL, 3}, - {} - }; - - /* configure as input source */ - snd_hda_sequence_write(codec, enable_dc_mode); - cxt5066_olpc_select_mic(codec); /* also sets configured bias */ -} - -static void cxt5066_disable_dc(struct hda_codec *codec) -{ - /* reconfigure input source */ - cxt5066_set_mic_boost(codec); - /* automic also selects the right mic if we're recording */ - cxt5066_olpc_automic(codec); -} - -static int cxt5066_olpc_dc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - ucontrol->value.integer.value[0] = spec->dc_enable; - return 0; -} - -static int cxt5066_olpc_dc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - int dc_enable = !!ucontrol->value.integer.value[0]; - - if (dc_enable == spec->dc_enable) - return 0; - - spec->dc_enable = dc_enable; - if (dc_enable) - cxt5066_enable_dc(codec); - else - cxt5066_disable_dc(codec); - - return 1; -} - -static int cxt5066_olpc_dc_bias_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - return snd_hda_input_mux_info(&cxt5066_olpc_dc_bias, uinfo); -} - -static int cxt5066_olpc_dc_bias_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - ucontrol->value.enumerated.item[0] = spec->dc_input_bias; - return 0; -} - -static int cxt5066_olpc_dc_bias_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; - unsigned int idx; - - idx = ucontrol->value.enumerated.item[0]; - if (idx >= imux->num_items) - idx = imux->num_items - 1; - - spec->dc_input_bias = idx; - if (spec->dc_enable) - cxt5066_set_olpc_dc_bias(codec); - return 1; -} - -static void cxt5066_olpc_capture_prepare(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - /* mark as recording and configure the microphone widget so that the - * recording LED comes on. */ - spec->recording = 1; - cxt5066_olpc_select_mic(codec); -} - -static void cxt5066_olpc_capture_cleanup(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - const struct hda_verb disable_mics[] = { - /* disable external mic, port B */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* disble internal mic, port C */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* disable DC capture, port F */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {}, - }; - - snd_hda_sequence_write(codec, disable_mics); - spec->recording = 0; -} - -static void conexant_check_dig_outs(struct hda_codec *codec, - const hda_nid_t *dig_pins, - int num_pins) -{ - struct conexant_spec *spec = codec->spec; - hda_nid_t *nid_loc = &spec->multiout.dig_out_nid; - int i; - - for (i = 0; i < num_pins; i++, dig_pins++) { - unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins); - if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE) - continue; - if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1) - continue; - if (spec->slave_dig_outs[0]) - nid_loc++; - else - nid_loc = spec->slave_dig_outs; - } -} - -static const struct hda_input_mux cxt5066_capture_source = { - .num_items = 4, - .items = { - { "Mic B", 0 }, - { "Mic C", 1 }, - { "Mic E", 2 }, - { "Mic F", 3 }, - }, -}; - -static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = { - .ops = &snd_hda_bind_vol, - .values = { - HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), - 0 - }, -}; - -static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = { - .ops = &snd_hda_bind_sw, - .values = { - HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT), - 0 - }, -}; - -static const struct snd_kcontrol_new cxt5066_mixer_master[] = { - HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), - {} -}; - -static const struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, - .subdevice = HDA_SUBDEV_AMP_FLAG, - .info = snd_hda_mixer_amp_volume_info, - .get = snd_hda_mixer_amp_volume_get, - .put = snd_hda_mixer_amp_volume_put, - .tlv = { .c = snd_hda_mixer_amp_tlv }, - /* offset by 28 volume steps to limit minimum gain to -46dB */ - .private_value = - HDA_COMPOSE_AMP_VAL_OFS(0x10, 3, 0, HDA_OUTPUT, 28), - }, - {} -}; - -static const struct snd_kcontrol_new cxt5066_mixer_olpc_dc[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DC Mode Enable Switch", - .info = snd_ctl_boolean_mono_info, - .get = cxt5066_olpc_dc_get, - .put = cxt5066_olpc_dc_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DC Input Bias Enum", - .info = cxt5066_olpc_dc_bias_enum_info, - .get = cxt5066_olpc_dc_bias_enum_get, - .put = cxt5066_olpc_dc_bias_enum_put, - }, - {} -}; - -static const struct snd_kcontrol_new cxt5066_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = cxt_eapd_info, - .get = cxt_eapd_get, - .put = cxt5066_hp_master_sw_put, - .private_value = 0x1d, - }, - - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Mic Boost Capture Enum", - .info = cxt5066_mic_boost_mux_enum_info, - .get = cxt5066_mic_boost_mux_enum_get, - .put = cxt5066_mic_boost_mux_enum_put, - }, - - HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), - HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others), - {} -}; - -static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Internal Mic Boost Capture Enum", - .info = cxt5066_mic_boost_mux_enum_info, - .get = cxt5066_mic_boost_mux_enum_get, - .put = cxt5066_mic_boost_mux_enum_put, - .private_value = 0x23 | 0x100, - }, - {} -}; - -static const struct hda_verb cxt5066_init_verbs[] = { - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ - - /* Speakers */ - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* HP, Amp */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - - /* no digital microphone support yet */ - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Audio input selector */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, - - /* SPDIF route: PCM */ - {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, - - {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - - /* EAPD */ - {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - - /* not handling these yet */ - {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, - {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, - {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, - {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, - {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, - {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, - {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, - {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0}, - { } /* end */ -}; - -static const struct hda_verb cxt5066_init_verbs_olpc[] = { - /* Port A: headphones */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* Port B: external microphone */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port C: internal microphone */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port D: unused */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port E: unused, but has primary EAPD */ - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - - /* Port F: external DC input through microphone port */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port G: internal speakers */ - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* DAC2: unused */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - - /* Disable digital microphone port */ - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Audio input selectors */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - - /* Disable SPDIF */ - {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* enable unsolicited events for Port A and B */ - {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - { } /* end */ -}; - -static const struct hda_verb cxt5066_init_verbs_vostro[] = { - /* Port A: headphones */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* Port B: external microphone */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port C: unused */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port D: unused */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port E: unused, but has primary EAPD */ - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - - /* Port F: unused */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port G: internal speakers */ - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* DAC2: unused */ - {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - - /* Digital microphone port */ - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - /* Audio input selectors */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - - /* Disable SPDIF */ - {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* enable unsolicited events for Port A and B */ - {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - { } /* end */ -}; - -static const struct hda_verb cxt5066_init_verbs_ideapad[] = { - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ - - /* Speakers */ - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* HP, Amp */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ - - /* Audio input selector */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, - {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ - - /* SPDIF route: PCM */ - {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, - - {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - - /* internal microphone */ - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ - - /* EAPD */ - {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - - {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - { } /* end */ -}; - -static const struct hda_verb cxt5066_init_verbs_thinkpad[] = { - {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */ - {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */ - - /* Port G: internal speakers */ - {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* Port A: HP, Amp */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* Port B: Mic Dock */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port C: Mic */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - - /* Port D: HP Dock, Amp */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, - {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */ - - /* DAC1 */ - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */ - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, - {0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */ - - /* Audio input selector */ - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2}, - {0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */ - - /* SPDIF route: PCM */ - {0x20, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x22, AC_VERB_SET_CONNECT_SEL, 0x0}, - - {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - - /* internal microphone */ - {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */ - - /* EAPD */ - {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ - - /* enable unsolicited events for Port A, B, C and D */ - {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - { } /* end */ -}; - -static const struct hda_verb cxt5066_init_verbs_portd_lo[] = { - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - { } /* end */ -}; - - -static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = { - {0x14, AC_VERB_SET_CONNECT_SEL, 0x0}, - {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT}, - {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT}, - { } /* end */ -}; - -/* initialize jack-sensing, too */ -static int cxt5066_init(struct hda_codec *codec) -{ - snd_printdd("CXT5066: init\n"); - conexant_init(codec); - if (codec->patch_ops.unsol_event) { - cxt5066_hp_automute(codec); - cxt5066_automic(codec); - } - cxt5066_set_mic_boost(codec); - return 0; -} - -static int cxt5066_olpc_init(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - snd_printdd("CXT5066: init\n"); - conexant_init(codec); - cxt5066_hp_automute(codec); - if (!spec->dc_enable) { - cxt5066_set_mic_boost(codec); - cxt5066_olpc_automic(codec); - } else { - cxt5066_enable_dc(codec); - } - return 0; -} - -enum { - CXT5066_LAPTOP, /* Laptops w/ EAPD support */ - CXT5066_DELL_LAPTOP, /* Dell Laptop */ - CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ - CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ - CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ - CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ - CXT5066_ASUS, /* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */ - CXT5066_HP_LAPTOP, /* HP Laptop */ - CXT5066_AUTO, /* BIOS auto-parser */ - CXT5066_MODELS -}; - -static const char * const cxt5066_models[CXT5066_MODELS] = { - [CXT5066_LAPTOP] = "laptop", - [CXT5066_DELL_LAPTOP] = "dell-laptop", - [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", - [CXT5066_DELL_VOSTRO] = "dell-vostro", - [CXT5066_IDEAPAD] = "ideapad", - [CXT5066_THINKPAD] = "thinkpad", - [CXT5066_ASUS] = "asus", - [CXT5066_HP_LAPTOP] = "hp-laptop", - [CXT5066_AUTO] = "auto", -}; - -static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { - SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT5066_AUTO), - SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), - SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), - SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), - SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), - SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), - SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), - SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), - SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD), - SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), - SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS), - SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS), - SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), - SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), - SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), - SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", - CXT5066_LAPTOP), - SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), - SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), - SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), - SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), - SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T510", CXT5066_AUTO), - SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO), - SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD), - SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD), - SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS), - SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), - SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), - SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), - {} -}; - -static int patch_cxt5066(struct hda_codec *codec) -{ - struct conexant_spec *spec; - int board_config; - - board_config = snd_hda_check_board_config(codec, CXT5066_MODELS, - cxt5066_models, cxt5066_cfg_tbl); - if (board_config < 0) - board_config = CXT5066_AUTO; /* model=auto as default */ - if (board_config == CXT5066_AUTO) - return patch_conexant_auto(codec); - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - - codec->patch_ops = conexant_patch_ops; - codec->patch_ops.init = conexant_init; - - spec->dell_automute = 0; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids); - spec->multiout.dac_nids = cxt5066_dac_nids; - conexant_check_dig_outs(codec, cxt5066_digout_pin_nids, - ARRAY_SIZE(cxt5066_digout_pin_nids)); - spec->num_adc_nids = 1; - spec->adc_nids = cxt5066_adc_nids; - spec->capsrc_nids = cxt5066_capsrc_nids; - spec->input_mux = &cxt5066_capture_source; - - spec->port_d_mode = PIN_HP; - - spec->num_init_verbs = 1; - spec->init_verbs[0] = cxt5066_init_verbs; - spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes); - spec->channel_mode = cxt5066_modes; - spec->cur_adc = 0; - spec->cur_adc_idx = 0; - - set_beep_amp(spec, 0x13, 0, HDA_OUTPUT); - - switch (board_config) { - default: - case CXT5066_LAPTOP: - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; - spec->mixers[spec->num_mixers++] = cxt5066_mixers; - break; - case CXT5066_DELL_LAPTOP: - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; - spec->mixers[spec->num_mixers++] = cxt5066_mixers; - - spec->port_d_mode = PIN_OUT; - spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo; - spec->num_init_verbs++; - spec->dell_automute = 1; - break; - case CXT5066_ASUS: - case CXT5066_HP_LAPTOP: - codec->patch_ops.init = cxt5066_init; - codec->patch_ops.unsol_event = cxt5066_unsol_event; - spec->init_verbs[spec->num_init_verbs] = - cxt5066_init_verbs_hp_laptop; - spec->num_init_verbs++; - spec->hp_laptop = board_config == CXT5066_HP_LAPTOP; - spec->asus = board_config == CXT5066_ASUS; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; - spec->mixers[spec->num_mixers++] = cxt5066_mixers; - /* no S/PDIF out */ - if (board_config == CXT5066_HP_LAPTOP) - spec->multiout.dig_out_nid = 0; - /* input source automatically selected */ - spec->input_mux = NULL; - spec->port_d_mode = 0; - spec->mic_boost = 3; /* default 30dB gain */ - break; - - case CXT5066_OLPC_XO_1_5: - codec->patch_ops.init = cxt5066_olpc_init; - codec->patch_ops.unsol_event = cxt5066_olpc_unsol_event; - spec->init_verbs[0] = cxt5066_init_verbs_olpc; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_olpc_dc; - spec->mixers[spec->num_mixers++] = cxt5066_mixers; - spec->port_d_mode = 0; - spec->mic_boost = 3; /* default 30dB gain */ - - /* no S/PDIF out */ - spec->multiout.dig_out_nid = 0; - - /* input source automatically selected */ - spec->input_mux = NULL; - - /* our capture hooks which allow us to turn on the microphone LED - * at the right time */ - spec->capture_prepare = cxt5066_olpc_capture_prepare; - spec->capture_cleanup = cxt5066_olpc_capture_cleanup; - break; - case CXT5066_DELL_VOSTRO: - codec->patch_ops.init = cxt5066_init; - codec->patch_ops.unsol_event = cxt5066_unsol_event; - spec->init_verbs[0] = cxt5066_init_verbs_vostro; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; - spec->mixers[spec->num_mixers++] = cxt5066_mixers; - spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; - spec->port_d_mode = 0; - spec->dell_vostro = 1; - spec->mic_boost = 3; /* default 30dB gain */ - - /* no S/PDIF out */ - spec->multiout.dig_out_nid = 0; - - /* input source automatically selected */ - spec->input_mux = NULL; - break; - case CXT5066_IDEAPAD: - codec->patch_ops.init = cxt5066_init; - codec->patch_ops.unsol_event = cxt5066_unsol_event; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; - spec->mixers[spec->num_mixers++] = cxt5066_mixers; - spec->init_verbs[0] = cxt5066_init_verbs_ideapad; - spec->port_d_mode = 0; - spec->ideapad = 1; - spec->mic_boost = 2; /* default 20dB gain */ - - /* no S/PDIF out */ - spec->multiout.dig_out_nid = 0; - - /* input source automatically selected */ - spec->input_mux = NULL; - break; - case CXT5066_THINKPAD: - codec->patch_ops.init = cxt5066_init; - codec->patch_ops.unsol_event = cxt5066_unsol_event; - spec->mixers[spec->num_mixers++] = cxt5066_mixer_master; - spec->mixers[spec->num_mixers++] = cxt5066_mixers; - spec->init_verbs[0] = cxt5066_init_verbs_thinkpad; - spec->thinkpad = 1; - spec->port_d_mode = PIN_OUT; - spec->mic_boost = 2; /* default 20dB gain */ - - /* no S/PDIF out */ - spec->multiout.dig_out_nid = 0; - - /* input source automatically selected */ - spec->input_mux = NULL; - break; - } - - if (spec->beep_amp) - snd_hda_attach_beep_device(codec, spec->beep_amp); - - return 0; -} - -/* - * Automatic parser for CX20641 & co - */ - -static int cx_auto_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - hda_nid_t adc = spec->imux_info[spec->cur_mux[0]].adc; - if (spec->adc_switching) { - spec->cur_adc = adc; - spec->cur_adc_stream_tag = stream_tag; - spec->cur_adc_format = format; - } - snd_hda_codec_setup_stream(codec, adc, stream_tag, 0, format); - return 0; -} - -static int cx_auto_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct conexant_spec *spec = codec->spec; - snd_hda_codec_cleanup_stream(codec, spec->cur_adc); - spec->cur_adc = 0; - return 0; -} - -static const struct hda_pcm_stream cx_auto_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .prepare = cx_auto_capture_pcm_prepare, - .cleanup = cx_auto_capture_pcm_cleanup - }, -}; - -static const hda_nid_t cx_auto_adc_nids[] = { 0x14 }; - -#define get_connection_index(codec, mux, nid)\ - snd_hda_get_conn_index(codec, mux, nid, 0) - -/* get an unassigned DAC from the given list. - * Return the nid if found and reduce the DAC list, or return zero if - * not found - */ -static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin, - hda_nid_t *dacs, int *num_dacs) -{ - int i, nums = *num_dacs; - hda_nid_t ret = 0; - - for (i = 0; i < nums; i++) { - if (get_connection_index(codec, pin, dacs[i]) >= 0) { - ret = dacs[i]; - break; - } - } - if (!ret) - return 0; - if (--nums > 0) - memmove(dacs, dacs + 1, nums * sizeof(hda_nid_t)); - *num_dacs = nums; - return ret; -} - -#define MAX_AUTO_DACS 5 - -#define DAC_SLAVE_FLAG 0x8000 /* filled dac is a slave */ - -/* fill analog DAC list from the widget tree */ -static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs) -{ - hda_nid_t nid, end_nid; - int nums = 0; - - end_nid = codec->start_nid + codec->num_nodes; - for (nid = codec->start_nid; nid < end_nid; nid++) { - unsigned int wcaps = get_wcaps(codec, nid); - unsigned int type = get_wcaps_type(wcaps); - if (type == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) { - dacs[nums++] = nid; - if (nums >= MAX_AUTO_DACS) - break; - } - } - return nums; -} - -/* fill pin_dac_pair list from the pin and dac list */ -static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins, - int num_pins, hda_nid_t *dacs, int *rest, - struct pin_dac_pair *filled, int nums, - int type) -{ - int i, start = nums; - - for (i = 0; i < num_pins; i++, nums++) { - filled[nums].pin = pins[i]; - filled[nums].type = type; - filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest); - if (filled[nums].dac) - continue; - if (filled[start].dac && get_connection_index(codec, pins[i], filled[start].dac) >= 0) { - filled[nums].dac = filled[start].dac | DAC_SLAVE_FLAG; - continue; - } - if (filled[0].dac && get_connection_index(codec, pins[i], filled[0].dac) >= 0) { - filled[nums].dac = filled[0].dac | DAC_SLAVE_FLAG; - continue; - } - snd_printdd("Failed to find a DAC for pin 0x%x", pins[i]); - } - return nums; -} - -/* parse analog output paths */ -static void cx_auto_parse_output(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t dacs[MAX_AUTO_DACS]; - int i, j, nums, rest; - - rest = fill_cx_auto_dacs(codec, dacs); - /* parse all analog output pins */ - nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs, - dacs, &rest, spec->dac_info, 0, - AUTO_PIN_LINE_OUT); - nums = fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs, - dacs, &rest, spec->dac_info, nums, - AUTO_PIN_HP_OUT); - nums = fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs, - dacs, &rest, spec->dac_info, nums, - AUTO_PIN_SPEAKER_OUT); - spec->dac_info_filled = nums; - /* fill multiout struct */ - for (i = 0; i < nums; i++) { - hda_nid_t dac = spec->dac_info[i].dac; - if (!dac || (dac & DAC_SLAVE_FLAG)) - continue; - switch (spec->dac_info[i].type) { - case AUTO_PIN_LINE_OUT: - spec->private_dac_nids[spec->multiout.num_dacs] = dac; - spec->multiout.num_dacs++; - break; - case AUTO_PIN_HP_OUT: - case AUTO_PIN_SPEAKER_OUT: - if (!spec->multiout.hp_nid) { - spec->multiout.hp_nid = dac; - break; - } - for (j = 0; j < ARRAY_SIZE(spec->multiout.extra_out_nid); j++) - if (!spec->multiout.extra_out_nid[j]) { - spec->multiout.extra_out_nid[j] = dac; - break; - } - break; - } - } - spec->multiout.dac_nids = spec->private_dac_nids; - spec->multiout.max_channels = spec->multiout.num_dacs * 2; - - for (i = 0; i < cfg->hp_outs; i++) { - if (is_jack_detectable(codec, cfg->hp_pins[i])) { - spec->auto_mute = 1; - break; - } - } - if (spec->auto_mute && - cfg->line_out_pins[0] && - cfg->line_out_type != AUTO_PIN_SPEAKER_OUT && - cfg->line_out_pins[0] != cfg->hp_pins[0] && - cfg->line_out_pins[0] != cfg->speaker_pins[0]) { - for (i = 0; i < cfg->line_outs; i++) { - if (is_jack_detectable(codec, cfg->line_out_pins[i])) { - spec->detect_line = 1; - break; - } - } - spec->automute_lines = spec->detect_line; - } - - spec->vmaster_nid = spec->private_dac_nids[0]; -} - -static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins, - hda_nid_t *pins, bool on); - -static void do_automute(struct hda_codec *codec, int num_pins, - hda_nid_t *pins, bool on) -{ - struct conexant_spec *spec = codec->spec; - int i; - for (i = 0; i < num_pins; i++) - snd_hda_codec_write(codec, pins[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - on ? PIN_OUT : 0); - if (spec->pin_eapd_ctrls) - cx_auto_turn_eapd(codec, num_pins, pins, on); -} - -static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins) -{ - int i, present = 0; - - for (i = 0; i < num_pins; i++) { - hda_nid_t nid = pins[i]; - if (!nid || !is_jack_detectable(codec, nid)) - break; - present |= snd_hda_jack_detect(codec, nid); - } - return present; -} - -/* auto-mute/unmute speaker and line outs according to headphone jack */ -static void cx_auto_update_speakers(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int on = 1; - - /* turn on HP EAPD when HP jacks are present */ - if (spec->pin_eapd_ctrls) { - if (spec->auto_mute) - on = spec->hp_present; - cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); - } - - /* mute speakers in auto-mode if HP or LO jacks are plugged */ - if (spec->auto_mute) - on = !(spec->hp_present || - (spec->detect_line && spec->line_present)); - do_automute(codec, cfg->speaker_outs, cfg->speaker_pins, on); - - /* toggle line-out mutes if needed, too */ - /* if LO is a copy of either HP or Speaker, don't need to handle it */ - if (cfg->line_out_pins[0] == cfg->hp_pins[0] || - cfg->line_out_pins[0] == cfg->speaker_pins[0]) - return; - if (spec->auto_mute) { - /* mute LO in auto-mode when HP jack is present */ - if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT || - spec->automute_lines) - on = !spec->hp_present; - else - on = 1; - } - do_automute(codec, cfg->line_outs, cfg->line_out_pins, on); -} - -static void cx_auto_hp_automute(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - - if (!spec->auto_mute) - return; - spec->hp_present = detect_jacks(codec, cfg->hp_outs, cfg->hp_pins); - cx_auto_update_speakers(codec); -} - -static void cx_auto_line_automute(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - - if (!spec->auto_mute || !spec->detect_line) - return; - spec->line_present = detect_jacks(codec, cfg->line_outs, - cfg->line_out_pins); - cx_auto_update_speakers(codec); -} - -static int cx_automute_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - static const char * const texts2[] = { - "Disabled", "Enabled" - }; - static const char * const texts3[] = { - "Disabled", "Speaker Only", "Line Out+Speaker" - }; - const char * const *texts; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - if (spec->automute_hp_lo) { - uinfo->value.enumerated.items = 3; - texts = texts3; - } else { - uinfo->value.enumerated.items = 2; - texts = texts2; - } - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int cx_automute_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - unsigned int val; - if (!spec->auto_mute) - val = 0; - else if (!spec->automute_lines) - val = 1; - else - val = 2; - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -static int cx_automute_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - - switch (ucontrol->value.enumerated.item[0]) { - case 0: - if (!spec->auto_mute) - return 0; - spec->auto_mute = 0; - break; - case 1: - if (spec->auto_mute && !spec->automute_lines) - return 0; - spec->auto_mute = 1; - spec->automute_lines = 0; - break; - case 2: - if (!spec->automute_hp_lo) - return -EINVAL; - if (spec->auto_mute && spec->automute_lines) - return 0; - spec->auto_mute = 1; - spec->automute_lines = 1; - break; - default: - return -EINVAL; - } - cx_auto_update_speakers(codec); - return 1; -} - -static const struct snd_kcontrol_new cx_automute_mode_enum[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Auto-Mute Mode", - .info = cx_automute_mode_info, - .get = cx_automute_mode_get, - .put = cx_automute_mode_put, - }, - { } -}; - -static int cx_auto_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - - return snd_hda_input_mux_info(&spec->private_imux, uinfo); -} - -static int cx_auto_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - - ucontrol->value.enumerated.item[0] = spec->cur_mux[0]; - return 0; -} - -/* look for the route the given pin from mux and return the index; - * if do_select is set, actually select the route. - */ -static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux, - hda_nid_t pin, hda_nid_t *srcp, - bool do_select, int depth) -{ - hda_nid_t conn[HDA_MAX_NUM_INPUTS]; - int i, nums; - - switch (get_wcaps_type(get_wcaps(codec, mux))) { - case AC_WID_AUD_IN: - case AC_WID_AUD_SEL: - case AC_WID_AUD_MIX: - break; - default: - return -1; - } - - nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); - for (i = 0; i < nums; i++) - if (conn[i] == pin) { - if (do_select) - snd_hda_codec_write(codec, mux, 0, - AC_VERB_SET_CONNECT_SEL, i); - if (srcp) - *srcp = mux; - return i; - } - depth++; - if (depth == 2) - return -1; - for (i = 0; i < nums; i++) { - int ret = __select_input_connection(codec, conn[i], pin, srcp, - do_select, depth); - if (ret >= 0) { - if (do_select) - snd_hda_codec_write(codec, mux, 0, - AC_VERB_SET_CONNECT_SEL, i); - return i; - } - } - return -1; -} - -static void select_input_connection(struct hda_codec *codec, hda_nid_t mux, - hda_nid_t pin) -{ - __select_input_connection(codec, mux, pin, NULL, true, 0); -} - -static int get_input_connection(struct hda_codec *codec, hda_nid_t mux, - hda_nid_t pin) -{ - return __select_input_connection(codec, mux, pin, NULL, false, 0); -} - -static int cx_auto_mux_enum_update(struct hda_codec *codec, - const struct hda_input_mux *imux, - unsigned int idx) -{ - struct conexant_spec *spec = codec->spec; - hda_nid_t adc; - int changed = 1; - - if (!imux->num_items) - return 0; - if (idx >= imux->num_items) - idx = imux->num_items - 1; - if (spec->cur_mux[0] == idx) - changed = 0; - adc = spec->imux_info[idx].adc; - select_input_connection(codec, spec->imux_info[idx].adc, - spec->imux_info[idx].pin); - if (spec->cur_adc && spec->cur_adc != adc) { - /* stream is running, let's swap the current ADC */ - __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); - spec->cur_adc = adc; - snd_hda_codec_setup_stream(codec, adc, - spec->cur_adc_stream_tag, 0, - spec->cur_adc_format); - } - spec->cur_mux[0] = idx; - return changed; -} - -static int cx_auto_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct conexant_spec *spec = codec->spec; - - return cx_auto_mux_enum_update(codec, &spec->private_imux, - ucontrol->value.enumerated.item[0]); -} - -static const struct snd_kcontrol_new cx_auto_capture_mixers[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = cx_auto_mux_enum_info, - .get = cx_auto_mux_enum_get, - .put = cx_auto_mux_enum_put - }, - {} -}; - -static bool select_automic(struct hda_codec *codec, int idx, bool detect) -{ - struct conexant_spec *spec = codec->spec; - if (idx < 0) - return false; - if (detect && !snd_hda_jack_detect(codec, spec->imux_info[idx].pin)) - return false; - cx_auto_mux_enum_update(codec, &spec->private_imux, idx); - return true; -} - -/* automatic switch internal and external mic */ -static void cx_auto_automic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - - if (!spec->auto_mic) - return; - if (!select_automic(codec, spec->auto_mic_ext, true)) - if (!select_automic(codec, spec->auto_mic_dock, true)) - select_automic(codec, spec->auto_mic_int, false); -} - -static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) -{ - switch (snd_hda_jack_get_action(codec, res >> 26)) { - case CONEXANT_HP_EVENT: - cx_auto_hp_automute(codec); - break; - case CONEXANT_LINE_EVENT: - cx_auto_line_automute(codec); - break; - case CONEXANT_MIC_EVENT: - cx_auto_automic(codec); - break; - } - snd_hda_jack_report_sync(codec); -} - -/* check whether the pin config is suitable for auto-mic switching; - * auto-mic is enabled only when one int-mic and one ext- and/or - * one dock-mic exist - */ -static void cx_auto_check_auto_mic(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - int pset[INPUT_PIN_ATTR_NORMAL + 1]; - int i; - - for (i = 0; i < ARRAY_SIZE(pset); i++) - pset[i] = -1; - for (i = 0; i < spec->private_imux.num_items; i++) { - hda_nid_t pin = spec->imux_info[i].pin; - unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin); - int type, attr; - attr = snd_hda_get_input_pin_attr(def_conf); - if (attr == INPUT_PIN_ATTR_UNUSED) - return; /* invalid entry */ - if (attr > INPUT_PIN_ATTR_NORMAL) - attr = INPUT_PIN_ATTR_NORMAL; - if (attr != INPUT_PIN_ATTR_INT && - !is_jack_detectable(codec, pin)) - return; /* non-detectable pin */ - type = get_defcfg_device(def_conf); - if (type != AC_JACK_MIC_IN && - (attr != INPUT_PIN_ATTR_DOCK || type != AC_JACK_LINE_IN)) - return; /* no valid input type */ - if (pset[attr] >= 0) - return; /* already occupied */ - pset[attr] = i; - } - if (pset[INPUT_PIN_ATTR_INT] < 0 || - (pset[INPUT_PIN_ATTR_NORMAL] < 0 && pset[INPUT_PIN_ATTR_DOCK])) - return; /* no input to switch*/ - spec->auto_mic = 1; - spec->auto_mic_ext = pset[INPUT_PIN_ATTR_NORMAL]; - spec->auto_mic_dock = pset[INPUT_PIN_ATTR_DOCK]; - spec->auto_mic_int = pset[INPUT_PIN_ATTR_INT]; -} - -static void cx_auto_parse_input(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - struct hda_input_mux *imux; - int i, j; - - imux = &spec->private_imux; - for (i = 0; i < cfg->num_inputs; i++) { - for (j = 0; j < spec->num_adc_nids; j++) { - hda_nid_t adc = spec->adc_nids[j]; - int idx = get_input_connection(codec, adc, - cfg->inputs[i].pin); - if (idx >= 0) { - const char *label; - label = hda_get_autocfg_input_label(codec, cfg, i); - spec->imux_info[imux->num_items].index = i; - spec->imux_info[imux->num_items].boost = 0; - spec->imux_info[imux->num_items].adc = adc; - spec->imux_info[imux->num_items].pin = - cfg->inputs[i].pin; - snd_hda_add_imux_item(imux, label, idx, NULL); - break; - } - } - } - if (imux->num_items >= 2 && cfg->num_inputs == imux->num_items) - cx_auto_check_auto_mic(codec); - if (imux->num_items > 1) { - for (i = 1; i < imux->num_items; i++) { - if (spec->imux_info[i].adc != spec->imux_info[0].adc) { - spec->adc_switching = 1; - break; - } - } - } -} - -/* get digital-input audio widget corresponding to the given pin */ -static hda_nid_t cx_auto_get_dig_in(struct hda_codec *codec, hda_nid_t pin) -{ - hda_nid_t nid, end_nid; - - end_nid = codec->start_nid + codec->num_nodes; - for (nid = codec->start_nid; nid < end_nid; nid++) { - unsigned int wcaps = get_wcaps(codec, nid); - unsigned int type = get_wcaps_type(wcaps); - if (type == AC_WID_AUD_IN && (wcaps & AC_WCAP_DIGITAL)) { - if (get_connection_index(codec, nid, pin) >= 0) - return nid; - } - } - return 0; -} - -static void cx_auto_parse_digital(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t nid; - - if (cfg->dig_outs && - snd_hda_get_connections(codec, cfg->dig_out_pins[0], &nid, 1) == 1) - spec->multiout.dig_out_nid = nid; - if (cfg->dig_in_pin) - spec->dig_in_nid = cx_auto_get_dig_in(codec, cfg->dig_in_pin); -} - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -static void cx_auto_parse_beep(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - hda_nid_t nid, end_nid; - - end_nid = codec->start_nid + codec->num_nodes; - for (nid = codec->start_nid; nid < end_nid; nid++) - if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) { - set_beep_amp(spec, nid, 0, HDA_OUTPUT); - break; - } -} -#else -#define cx_auto_parse_beep(codec) -#endif - -/* parse EAPDs */ -static void cx_auto_parse_eapd(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - hda_nid_t nid, end_nid; - - end_nid = codec->start_nid + codec->num_nodes; - for (nid = codec->start_nid; nid < end_nid; nid++) { - if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) - continue; - if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) - continue; - spec->eapds[spec->num_eapds++] = nid; - if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) - break; - } - - /* NOTE: below is a wild guess; if we have more than two EAPDs, - * it's a new chip, where EAPDs are supposed to be associated to - * pins, and we can control EAPD per pin. - * OTOH, if only one or two EAPDs are found, it's an old chip, - * thus it might control over all pins. - */ - spec->pin_eapd_ctrls = spec->num_eapds > 2; -} - -static int cx_auto_parse_auto_config(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - int err; - - err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); - if (err < 0) - return err; - - cx_auto_parse_output(codec); - cx_auto_parse_input(codec); - cx_auto_parse_digital(codec); - cx_auto_parse_beep(codec); - cx_auto_parse_eapd(codec); - return 0; -} - -static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins, - hda_nid_t *pins, bool on) -{ - int i; - for (i = 0; i < num_pins; i++) { - if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD) - snd_hda_codec_write(codec, pins[i], 0, - AC_VERB_SET_EAPD_BTLENABLE, - on ? 0x02 : 0); - } -} - -static void select_connection(struct hda_codec *codec, hda_nid_t pin, - hda_nid_t src) -{ - int idx = get_connection_index(codec, pin, src); - if (idx >= 0) - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_CONNECT_SEL, idx); -} - -static void mute_outputs(struct hda_codec *codec, int num_nids, - const hda_nid_t *nids) -{ - int i, val; - - for (i = 0; i < num_nids; i++) { - hda_nid_t nid = nids[i]; - if (!(get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) - continue; - if (query_amp_caps(codec, nid, HDA_OUTPUT) & AC_AMPCAP_MUTE) - val = AMP_OUT_MUTE; - else - val = AMP_OUT_ZERO; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, val); - } -} - -static void enable_unsol_pins(struct hda_codec *codec, int num_pins, - hda_nid_t *pins, unsigned int action) -{ - int i; - for (i = 0; i < num_pins; i++) - snd_hda_jack_detect_enable(codec, pins[i], action); -} - -static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) -{ - int i; - for (i = 0; i < nums; i++) - if (list[i] == nid) - return true; - return false; -} - -/* is the given NID found in any of autocfg items? */ -static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid) -{ - int i; - - if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) || - found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) || - found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) || - found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs)) - return true; - for (i = 0; i < cfg->num_inputs; i++) - if (cfg->inputs[i].pin == nid) - return true; - if (cfg->dig_in_pin == nid) - return true; - return false; -} - -/* clear unsol-event tags on unused pins; Conexant codecs seem to leave - * invalid unsol tags by some reason - */ -static void clear_unsol_on_unused_pins(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - for (i = 0; i < codec->init_pins.used; i++) { - struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); - if (!found_in_autocfg(cfg, pin->nid)) - snd_hda_codec_write(codec, pin->nid, 0, - AC_VERB_SET_UNSOLICITED_ENABLE, 0); - } -} - -/* turn on/off EAPD according to Master switch */ -static void cx_auto_vmaster_hook(void *private_data, int enabled) -{ - struct hda_codec *codec = private_data; - struct conexant_spec *spec = codec->spec; - - if (enabled && spec->pin_eapd_ctrls) { - cx_auto_update_speakers(codec); - return; - } - cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled); -} - -static void cx_auto_init_output(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t nid; - int i; - - mute_outputs(codec, spec->multiout.num_dacs, spec->multiout.dac_nids); - for (i = 0; i < cfg->hp_outs; i++) { - unsigned int val = PIN_OUT; - if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) & - AC_PINCAP_HP_DRV) - val |= AC_PINCTL_HP_EN; - snd_hda_codec_write(codec, cfg->hp_pins[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, val); - } - mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); - mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); - mute_outputs(codec, cfg->speaker_outs, cfg->speaker_pins); - for (i = 0; i < spec->dac_info_filled; i++) { - nid = spec->dac_info[i].dac; - if (!nid) - nid = spec->multiout.dac_nids[0]; - else if (nid & DAC_SLAVE_FLAG) - nid &= ~DAC_SLAVE_FLAG; - select_connection(codec, spec->dac_info[i].pin, nid); - } - if (spec->auto_mute) { - enable_unsol_pins(codec, cfg->hp_outs, cfg->hp_pins, - CONEXANT_HP_EVENT); - spec->hp_present = detect_jacks(codec, cfg->hp_outs, - cfg->hp_pins); - if (spec->detect_line) { - enable_unsol_pins(codec, cfg->line_outs, - cfg->line_out_pins, - CONEXANT_LINE_EVENT); - spec->line_present = - detect_jacks(codec, cfg->line_outs, - cfg->line_out_pins); - } - } - cx_auto_update_speakers(codec); - /* turn on all EAPDs if no individual EAPD control is available */ - if (!spec->pin_eapd_ctrls) - cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); - clear_unsol_on_unused_pins(codec); -} - -static void cx_auto_init_input(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, val; - - for (i = 0; i < spec->num_adc_nids; i++) { - hda_nid_t nid = spec->adc_nids[i]; - if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) - continue; - if (query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE) - val = AMP_IN_MUTE(0); - else - val = AMP_IN_UNMUTE(0); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - val); - } - - for (i = 0; i < cfg->num_inputs; i++) { - unsigned int type; - if (cfg->inputs[i].type == AUTO_PIN_MIC) - type = PIN_VREF80; - else - type = PIN_IN; - snd_hda_codec_write(codec, cfg->inputs[i].pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, type); - } - - if (spec->auto_mic) { - if (spec->auto_mic_ext >= 0) { - snd_hda_jack_detect_enable(codec, - cfg->inputs[spec->auto_mic_ext].pin, - CONEXANT_MIC_EVENT); - } - if (spec->auto_mic_dock >= 0) { - snd_hda_jack_detect_enable(codec, - cfg->inputs[spec->auto_mic_dock].pin, - CONEXANT_MIC_EVENT); - } - cx_auto_automic(codec); - } else { - select_input_connection(codec, spec->imux_info[0].adc, - spec->imux_info[0].pin); - } -} - -static void cx_auto_init_digital(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - - if (spec->multiout.dig_out_nid) - snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - if (spec->dig_in_nid) - snd_hda_codec_write(codec, cfg->dig_in_pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); -} - -static int cx_auto_init(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ - cx_auto_init_output(codec); - cx_auto_init_input(codec); - cx_auto_init_digital(codec); - snd_hda_jack_report_sync(codec); - snd_hda_sync_vmaster_hook(&spec->vmaster_mute); - return 0; -} - -static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, - const char *dir, int cidx, - hda_nid_t nid, int hda_dir, int amp_idx) -{ - static char name[32]; - static struct snd_kcontrol_new knew[] = { - HDA_CODEC_VOLUME(name, 0, 0, 0), - HDA_CODEC_MUTE(name, 0, 0, 0), - }; - static const char * const sfx[2] = { "Volume", "Switch" }; - int i, err; - - for (i = 0; i < 2; i++) { - struct snd_kcontrol *kctl; - knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx, - hda_dir); - knew[i].subdevice = HDA_SUBDEV_AMP_FLAG; - knew[i].index = cidx; - snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]); - kctl = snd_ctl_new1(&knew[i], codec); - if (!kctl) - return -ENOMEM; - err = snd_hda_ctl_add(codec, nid, kctl); - if (err < 0) - return err; - if (!(query_amp_caps(codec, nid, hda_dir) & - (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))) - break; - } - return 0; -} - -#define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \ - cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0) - -#define cx_auto_add_pb_volume(codec, nid, str, idx) \ - cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) - -static int try_add_pb_volume(struct hda_codec *codec, hda_nid_t dac, - hda_nid_t pin, const char *name, int idx) -{ - unsigned int caps; - if (dac && !(dac & DAC_SLAVE_FLAG)) { - caps = query_amp_caps(codec, dac, HDA_OUTPUT); - if (caps & AC_AMPCAP_NUM_STEPS) - return cx_auto_add_pb_volume(codec, dac, name, idx); - } - caps = query_amp_caps(codec, pin, HDA_OUTPUT); - if (caps & AC_AMPCAP_NUM_STEPS) - return cx_auto_add_pb_volume(codec, pin, name, idx); - return 0; -} - -static int cx_auto_build_output_controls(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - int i, err; - int num_line = 0, num_hp = 0, num_spk = 0; - static const char * const texts[3] = { "Front", "Surround", "CLFE" }; - - if (spec->dac_info_filled == 1) - return try_add_pb_volume(codec, spec->dac_info[0].dac, - spec->dac_info[0].pin, - "Master", 0); - - for (i = 0; i < spec->dac_info_filled; i++) { - const char *label; - int idx, type; - hda_nid_t dac = spec->dac_info[i].dac; - type = spec->dac_info[i].type; - if (type == AUTO_PIN_LINE_OUT) - type = spec->autocfg.line_out_type; - switch (type) { - case AUTO_PIN_LINE_OUT: - default: - label = texts[num_line++]; - idx = 0; - break; - case AUTO_PIN_HP_OUT: - label = "Headphone"; - idx = num_hp++; - break; - case AUTO_PIN_SPEAKER_OUT: - label = "Speaker"; - idx = num_spk++; - break; - } - err = try_add_pb_volume(codec, dac, - spec->dac_info[i].pin, - label, idx); - if (err < 0) - return err; - } - - if (spec->auto_mute) { - err = snd_hda_add_new_ctls(codec, cx_automute_mode_enum); - if (err < 0) - return err; - } - - return 0; -} - -static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, - const char *label, const char *pfx, - int cidx) -{ - struct conexant_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->num_adc_nids; i++) { - hda_nid_t adc_nid = spec->adc_nids[i]; - int idx = get_input_connection(codec, adc_nid, nid); - if (idx < 0) - continue; - if (codec->single_adc_amp) - idx = 0; - return cx_auto_add_volume_idx(codec, label, pfx, - cidx, adc_nid, HDA_INPUT, idx); - } - return 0; -} - -static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx, - const char *label, int cidx) -{ - struct conexant_spec *spec = codec->spec; - hda_nid_t mux, nid; - int i, con; - - nid = spec->imux_info[idx].pin; - if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) - return cx_auto_add_volume(codec, label, " Boost", cidx, - nid, HDA_INPUT); - con = __select_input_connection(codec, spec->imux_info[idx].adc, nid, - &mux, false, 0); - if (con < 0) - return 0; - for (i = 0; i < idx; i++) { - if (spec->imux_info[i].boost == mux) - return 0; /* already present */ - } - - if (get_wcaps(codec, mux) & AC_WCAP_OUT_AMP) { - spec->imux_info[idx].boost = mux; - return cx_auto_add_volume(codec, label, " Boost", 0, - mux, HDA_OUTPUT); - } - return 0; -} - -static int cx_auto_build_input_controls(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - struct hda_input_mux *imux = &spec->private_imux; - const char *prev_label; - int input_conn[HDA_MAX_NUM_INPUTS]; - int i, j, err, cidx; - int multi_connection; - - if (!imux->num_items) - return 0; - - multi_connection = 0; - for (i = 0; i < imux->num_items; i++) { - cidx = get_input_connection(codec, spec->imux_info[i].adc, - spec->imux_info[i].pin); - if (cidx < 0) - continue; - input_conn[i] = spec->imux_info[i].adc; - if (!codec->single_adc_amp) - input_conn[i] |= cidx << 8; - if (i > 0 && input_conn[i] != input_conn[0]) - multi_connection = 1; - } - - prev_label = NULL; - cidx = 0; - for (i = 0; i < imux->num_items; i++) { - hda_nid_t nid = spec->imux_info[i].pin; - const char *label; - - label = hda_get_autocfg_input_label(codec, &spec->autocfg, - spec->imux_info[i].index); - if (label == prev_label) - cidx++; - else - cidx = 0; - prev_label = label; - - err = cx_auto_add_boost_volume(codec, i, label, cidx); - if (err < 0) - return err; - - if (!multi_connection) { - if (i > 0) - continue; - err = cx_auto_add_capture_volume(codec, nid, - "Capture", "", cidx); - } else { - bool dup_found = false; - for (j = 0; j < i; j++) { - if (input_conn[j] == input_conn[i]) { - dup_found = true; - break; - } - } - if (dup_found) - continue; - err = cx_auto_add_capture_volume(codec, nid, - label, " Capture", cidx); - } - if (err < 0) - return err; - } - - if (spec->private_imux.num_items > 1 && !spec->auto_mic) { - err = snd_hda_add_new_ctls(codec, cx_auto_capture_mixers); - if (err < 0) - return err; - } - - return 0; -} - -static int cx_auto_build_controls(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - int err; - - err = cx_auto_build_output_controls(codec); - if (err < 0) - return err; - err = cx_auto_build_input_controls(codec); - if (err < 0) - return err; - err = conexant_build_controls(codec); - if (err < 0) - return err; - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); - if (err < 0) - return err; - if (spec->vmaster_mute.sw_kctl) { - spec->vmaster_mute.hook = cx_auto_vmaster_hook; - err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, - spec->vmaster_mute_led); - if (err < 0) - return err; - } - return 0; -} - -static int cx_auto_search_adcs(struct hda_codec *codec) -{ - struct conexant_spec *spec = codec->spec; - hda_nid_t nid, end_nid; - - end_nid = codec->start_nid + codec->num_nodes; - for (nid = codec->start_nid; nid < end_nid; nid++) { - unsigned int caps = get_wcaps(codec, nid); - if (get_wcaps_type(caps) != AC_WID_AUD_IN) - continue; - if (caps & AC_WCAP_DIGITAL) - continue; - if (snd_BUG_ON(spec->num_adc_nids >= - ARRAY_SIZE(spec->private_adc_nids))) - break; - spec->private_adc_nids[spec->num_adc_nids++] = nid; - } - spec->adc_nids = spec->private_adc_nids; - return 0; -} - -static const struct hda_codec_ops cx_auto_patch_ops = { - .build_controls = cx_auto_build_controls, - .build_pcms = conexant_build_pcms, - .init = cx_auto_init, - .free = conexant_free, - .unsol_event = cx_auto_unsol_event, -#ifdef CONFIG_SND_HDA_POWER_SAVE - .suspend = conexant_suspend, -#endif - .reboot_notify = snd_hda_shutup_pins, -}; - -/* - * pin fix-up - */ -struct cxt_pincfg { - hda_nid_t nid; - u32 val; -}; - -static void apply_pincfg(struct hda_codec *codec, const struct cxt_pincfg *cfg) -{ - for (; cfg->nid; cfg++) - snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); - -} - -static void apply_pin_fixup(struct hda_codec *codec, - const struct snd_pci_quirk *quirk, - const struct cxt_pincfg **table) -{ - quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); - if (quirk) { - snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n", - quirk->name); - apply_pincfg(codec, table[quirk->value]); - } -} - -enum { - CXT_PINCFG_LENOVO_X200, - CXT_PINCFG_LENOVO_TP410, -}; - -/* ThinkPad X200 & co with cxt5051 */ -static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { - { 0x16, 0x042140ff }, /* HP (seq# overridden) */ - { 0x17, 0x21a11000 }, /* dock-mic */ - { 0x19, 0x2121103f }, /* dock-HP */ - { 0x1c, 0x21440100 }, /* dock SPDIF out */ - {} -}; - -/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */ -static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = { - { 0x19, 0x042110ff }, /* HP (seq# overridden) */ - { 0x1a, 0x21a190f0 }, /* dock-mic */ - { 0x1c, 0x212140ff }, /* dock-HP */ - {} -}; - -static const struct cxt_pincfg *cxt_pincfg_tbl[] = { - [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200, - [CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410, -}; - -static const struct snd_pci_quirk cxt5051_fixups[] = { - SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200), - {} -}; - -static const struct snd_pci_quirk cxt5066_fixups[] = { - SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), - SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410), - SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), - SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), - SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), - {} -}; - -/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches - * can be created (bko#42825) - */ -static void add_cx5051_fake_mutes(struct hda_codec *codec) -{ - static hda_nid_t out_nids[] = { - 0x10, 0x11, 0 - }; - hda_nid_t *p; - - for (p = out_nids; *p; p++) - snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT, - AC_AMPCAP_MIN_MUTE | - query_amp_caps(codec, *p, HDA_OUTPUT)); -} - -static int patch_conexant_auto(struct hda_codec *codec) -{ - struct conexant_spec *spec; - int err; - - printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - codec->spec = spec; - - switch (codec->vendor_id) { - case 0x14f15045: - codec->single_adc_amp = 1; - break; - case 0x14f15051: - add_cx5051_fake_mutes(codec); - codec->pin_amp_workaround = 1; - apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); - break; - default: - codec->pin_amp_workaround = 1; - apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); - } - - /* Show mute-led control only on HP laptops - * This is a sort of white-list: on HP laptops, EAPD corresponds - * only to the mute-LED without actualy amp function. Meanwhile, - * others may use EAPD really as an amp switch, so it might be - * not good to expose it blindly. - */ - switch (codec->subsystem_id >> 16) { - case 0x103c: - spec->vmaster_mute_led = 1; - break; - } - - err = cx_auto_search_adcs(codec); - if (err < 0) - return err; - err = cx_auto_parse_auto_config(codec); - if (err < 0) { - kfree(codec->spec); - codec->spec = NULL; - return err; - } - spec->capture_stream = &cx_auto_pcm_analog_capture; - codec->patch_ops = cx_auto_patch_ops; - if (spec->beep_amp) - snd_hda_attach_beep_device(codec, spec->beep_amp); - - /* Some laptops with Conexant chips show stalls in S3 resume, - * which falls into the single-cmd mode. - * Better to make reset, then. - */ - if (!codec->bus->sync_write) { - snd_printd("hda_codec: " - "Enable sync_write for stable communication\n"); - codec->bus->sync_write = 1; - codec->bus->allow_bus_reset = 1; - } - - return 0; -} - -/* - */ - -static const struct hda_codec_preset snd_hda_preset_conexant[] = { - { .id = 0x14f15045, .name = "CX20549 (Venice)", - .patch = patch_cxt5045 }, - { .id = 0x14f15047, .name = "CX20551 (Waikiki)", - .patch = patch_cxt5047 }, - { .id = 0x14f15051, .name = "CX20561 (Hermosa)", - .patch = patch_cxt5051 }, - { .id = 0x14f15066, .name = "CX20582 (Pebble)", - .patch = patch_cxt5066 }, - { .id = 0x14f15067, .name = "CX20583 (Pebble HSF)", - .patch = patch_cxt5066 }, - { .id = 0x14f15068, .name = "CX20584", - .patch = patch_cxt5066 }, - { .id = 0x14f15069, .name = "CX20585", - .patch = patch_cxt5066 }, - { .id = 0x14f1506c, .name = "CX20588", - .patch = patch_cxt5066 }, - { .id = 0x14f1506e, .name = "CX20590", - .patch = patch_cxt5066 }, - { .id = 0x14f15097, .name = "CX20631", - .patch = patch_conexant_auto }, - { .id = 0x14f15098, .name = "CX20632", - .patch = patch_conexant_auto }, - { .id = 0x14f150a1, .name = "CX20641", - .patch = patch_conexant_auto }, - { .id = 0x14f150a2, .name = "CX20642", - .patch = patch_conexant_auto }, - { .id = 0x14f150ab, .name = "CX20651", - .patch = patch_conexant_auto }, - { .id = 0x14f150ac, .name = "CX20652", - .patch = patch_conexant_auto }, - { .id = 0x14f150b8, .name = "CX20664", - .patch = patch_conexant_auto }, - { .id = 0x14f150b9, .name = "CX20665", - .patch = patch_conexant_auto }, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:14f15045"); -MODULE_ALIAS("snd-hda-codec-id:14f15047"); -MODULE_ALIAS("snd-hda-codec-id:14f15051"); -MODULE_ALIAS("snd-hda-codec-id:14f15066"); -MODULE_ALIAS("snd-hda-codec-id:14f15067"); -MODULE_ALIAS("snd-hda-codec-id:14f15068"); -MODULE_ALIAS("snd-hda-codec-id:14f15069"); -MODULE_ALIAS("snd-hda-codec-id:14f1506c"); -MODULE_ALIAS("snd-hda-codec-id:14f1506e"); -MODULE_ALIAS("snd-hda-codec-id:14f15097"); -MODULE_ALIAS("snd-hda-codec-id:14f15098"); -MODULE_ALIAS("snd-hda-codec-id:14f150a1"); -MODULE_ALIAS("snd-hda-codec-id:14f150a2"); -MODULE_ALIAS("snd-hda-codec-id:14f150ab"); -MODULE_ALIAS("snd-hda-codec-id:14f150ac"); -MODULE_ALIAS("snd-hda-codec-id:14f150b8"); -MODULE_ALIAS("snd-hda-codec-id:14f150b9"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Conexant HD-audio codec"); - -static struct hda_codec_preset_list conexant_list = { - .preset = snd_hda_preset_conexant, - .owner = THIS_MODULE, -}; - -static int __init patch_conexant_init(void) -{ - return snd_hda_add_codec_preset(&conexant_list); -} - -static void __exit patch_conexant_exit(void) -{ - snd_hda_delete_codec_preset(&conexant_list); -} - -module_init(patch_conexant_init) -module_exit(patch_conexant_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_hdmi.c b/ANDROID_3.4.5/sound/pci/hda/patch_hdmi.c deleted file mode 100644 index 83f345f3..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_hdmi.c +++ /dev/null @@ -1,1986 +0,0 @@ -/* - * - * patch_hdmi.c - routines for HDMI/DisplayPort codecs - * - * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. - * Copyright (c) 2006 ATI Technologies Inc. - * Copyright (c) 2008 NVIDIA Corp. All rights reserved. - * Copyright (c) 2008 Wei Ni - * - * Authors: - * Wu Fengguang - * - * Maintained by: - * Wu Fengguang - * - * 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 "hda_codec.h" -#include "hda_local.h" -#include "hda_jack.h" - -static bool static_hdmi_pcm; -module_param(static_hdmi_pcm, bool, 0644); -MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); - -/* - * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device - * could support N independent pipes, each of them can be connected to one or - * more ports (DVI, HDMI or DisplayPort). - * - * The HDA correspondence of pipes/ports are converter/pin nodes. - */ -#define MAX_HDMI_CVTS 8 -#define MAX_HDMI_PINS 8 - -struct hdmi_spec_per_cvt { - hda_nid_t cvt_nid; - int assigned; - unsigned int channels_min; - unsigned int channels_max; - u32 rates; - u64 formats; - unsigned int maxbps; -}; - -struct hdmi_spec_per_pin { - hda_nid_t pin_nid; - int num_mux_nids; - hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; - - struct hda_codec *codec; - struct hdmi_eld sink_eld; - struct delayed_work work; - int repoll_count; -}; - -struct hdmi_spec { - int num_cvts; - struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS]; - - int num_pins; - struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; - struct hda_pcm pcm_rec[MAX_HDMI_PINS]; - - /* - * Non-generic ATI/NVIDIA specific - */ - struct hda_multi_out multiout; - const struct hda_pcm_stream *pcm_playback; -}; - - -struct hdmi_audio_infoframe { - u8 type; /* 0x84 */ - u8 ver; /* 0x01 */ - u8 len; /* 0x0a */ - - u8 checksum; - - u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ - u8 SS01_SF24; - u8 CXT04; - u8 CA; - u8 LFEPBL01_LSV36_DM_INH7; -}; - -struct dp_audio_infoframe { - u8 type; /* 0x84 */ - u8 len; /* 0x1b */ - u8 ver; /* 0x11 << 2 */ - - u8 CC02_CT47; /* match with HDMI infoframe from this on */ - u8 SS01_SF24; - u8 CXT04; - u8 CA; - u8 LFEPBL01_LSV36_DM_INH7; -}; - -union audio_infoframe { - struct hdmi_audio_infoframe hdmi; - struct dp_audio_infoframe dp; - u8 bytes[0]; -}; - -/* - * CEA speaker placement: - * - * FLH FCH FRH - * FLW FL FLC FC FRC FR FRW - * - * LFE - * TC - * - * RL RLC RC RRC RR - * - * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to - * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. - */ -enum cea_speaker_placement { - FL = (1 << 0), /* Front Left */ - FC = (1 << 1), /* Front Center */ - FR = (1 << 2), /* Front Right */ - FLC = (1 << 3), /* Front Left Center */ - FRC = (1 << 4), /* Front Right Center */ - RL = (1 << 5), /* Rear Left */ - RC = (1 << 6), /* Rear Center */ - RR = (1 << 7), /* Rear Right */ - RLC = (1 << 8), /* Rear Left Center */ - RRC = (1 << 9), /* Rear Right Center */ - LFE = (1 << 10), /* Low Frequency Effect */ - FLW = (1 << 11), /* Front Left Wide */ - FRW = (1 << 12), /* Front Right Wide */ - FLH = (1 << 13), /* Front Left High */ - FCH = (1 << 14), /* Front Center High */ - FRH = (1 << 15), /* Front Right High */ - TC = (1 << 16), /* Top Center */ -}; - -/* - * ELD SA bits in the CEA Speaker Allocation data block - */ -static int eld_speaker_allocation_bits[] = { - [0] = FL | FR, - [1] = LFE, - [2] = FC, - [3] = RL | RR, - [4] = RC, - [5] = FLC | FRC, - [6] = RLC | RRC, - /* the following are not defined in ELD yet */ - [7] = FLW | FRW, - [8] = FLH | FRH, - [9] = TC, - [10] = FCH, -}; - -struct cea_channel_speaker_allocation { - int ca_index; - int speakers[8]; - - /* derived values, just for convenience */ - int channels; - int spk_mask; -}; - -/* - * ALSA sequence is: - * - * surround40 surround41 surround50 surround51 surround71 - * ch0 front left = = = = - * ch1 front right = = = = - * ch2 rear left = = = = - * ch3 rear right = = = = - * ch4 LFE center center center - * ch5 LFE LFE - * ch6 side left - * ch7 side right - * - * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} - */ -static int hdmi_channel_mapping[0x32][8] = { - /* stereo */ - [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* 2.1 */ - [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* Dolby Surround */ - [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, - /* surround40 */ - [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, - /* 4ch */ - [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, - /* surround41 */ - [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, - /* surround50 */ - [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, - /* surround51 */ - [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, - /* 7.1 */ - [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, -}; - -/* - * This is an ordered list! - * - * The preceding ones have better chances to be selected by - * hdmi_channel_allocation(). - */ -static struct cea_channel_speaker_allocation channel_allocations[] = { -/* channel: 7 6 5 4 3 2 1 0 */ -{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, - /* 2.1 */ -{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, - /* Dolby Surround */ -{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, - /* surround40 */ -{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, - /* surround41 */ -{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, - /* surround50 */ -{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, - /* surround51 */ -{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, - /* 6.1 */ -{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, - /* surround71 */ -{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, - -{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, -{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, -{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, -{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, -}; - - -/* - * HDMI routines - */ - -static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid) -{ - int pin_idx; - - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) - if (spec->pins[pin_idx].pin_nid == pin_nid) - return pin_idx; - - snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid); - return -EINVAL; -} - -static int hinfo_to_pin_index(struct hdmi_spec *spec, - struct hda_pcm_stream *hinfo) -{ - int pin_idx; - - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) - if (&spec->pcm_rec[pin_idx].stream[0] == hinfo) - return pin_idx; - - snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo); - return -EINVAL; -} - -static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid) -{ - int cvt_idx; - - for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) - if (spec->cvts[cvt_idx].cvt_nid == cvt_nid) - return cvt_idx; - - snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid); - return -EINVAL; -} - -static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hdmi_spec *spec; - int pin_idx; - - spec = codec->spec; - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - - pin_idx = kcontrol->private_value; - uinfo->count = spec->pins[pin_idx].sink_eld.eld_size; - - return 0; -} - -static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hdmi_spec *spec; - int pin_idx; - - spec = codec->spec; - pin_idx = kcontrol->private_value; - - memcpy(ucontrol->value.bytes.data, - spec->pins[pin_idx].sink_eld.eld_buffer, ELD_MAX_SIZE); - - return 0; -} - -static struct snd_kcontrol_new eld_bytes_ctl = { - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "ELD", - .info = hdmi_eld_ctl_info, - .get = hdmi_eld_ctl_get, -}; - -static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, - int device) -{ - struct snd_kcontrol *kctl; - struct hdmi_spec *spec = codec->spec; - int err; - - kctl = snd_ctl_new1(&eld_bytes_ctl, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = pin_idx; - kctl->id.device = device; - - err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl); - if (err < 0) - return err; - - return 0; -} - -#ifdef BE_PARANOID -static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int *packet_index, int *byte_index) -{ - int val; - - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_INDEX, 0); - - *packet_index = val >> 5; - *byte_index = val & 0x1f; -} -#endif - -static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int packet_index, int byte_index) -{ - int val; - - val = (packet_index << 5) | (byte_index & 0x1f); - - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); -} - -static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, - unsigned char val) -{ - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); -} - -static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) -{ - /* Unmute */ - if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - /* Disable pin out until stream is active*/ - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, 0); -} - -static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) -{ - return 1 + snd_hda_codec_read(codec, cvt_nid, 0, - AC_VERB_GET_CVT_CHAN_COUNT, 0); -} - -static void hdmi_set_channel_count(struct hda_codec *codec, - hda_nid_t cvt_nid, int chs) -{ - if (chs != hdmi_get_channel_count(codec, cvt_nid)) - snd_hda_codec_write(codec, cvt_nid, 0, - AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); -} - - -/* - * Channel mapping routines - */ - -/* - * Compute derived values in channel_allocations[]. - */ -static void init_channel_allocations(void) -{ - int i, j; - struct cea_channel_speaker_allocation *p; - - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - p = channel_allocations + i; - p->channels = 0; - p->spk_mask = 0; - for (j = 0; j < ARRAY_SIZE(p->speakers); j++) - if (p->speakers[j]) { - p->channels++; - p->spk_mask |= p->speakers[j]; - } - } -} - -/* - * The transformation takes two steps: - * - * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask - * spk_mask => (channel_allocations[]) => ai->CA - * - * TODO: it could select the wrong CA from multiple candidates. -*/ -static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) -{ - int i; - int ca = 0; - int spk_mask = 0; - char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; - - /* - * CA defaults to 0 for basic stereo audio - */ - if (channels <= 2) - return 0; - - /* - * expand ELD's speaker allocation mask - * - * ELD tells the speaker mask in a compact(paired) form, - * expand ELD's notions to match the ones used by Audio InfoFrame. - */ - for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { - if (eld->spk_alloc & (1 << i)) - spk_mask |= eld_speaker_allocation_bits[i]; - } - - /* search for the first working match in the CA table */ - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - if (channels == channel_allocations[i].channels && - (spk_mask & channel_allocations[i].spk_mask) == - channel_allocations[i].spk_mask) { - ca = channel_allocations[i].ca_index; - break; - } - } - - snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); - snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", - ca, channels, buf); - - return ca; -} - -static void hdmi_debug_channel_mapping(struct hda_codec *codec, - hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int slot; - - for (i = 0; i < 8; i++) { - slot = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_CHAN_SLOT, i); - printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", - slot >> 4, slot & 0xf); - } -#endif -} - - -static void hdmi_setup_channel_mapping(struct hda_codec *codec, - hda_nid_t pin_nid, - int ca) -{ - int i; - int err; - - if (hdmi_channel_mapping[ca][1] == 0) { - for (i = 0; i < channel_allocations[ca].channels; i++) - hdmi_channel_mapping[ca][i] = i | (i << 4); - for (; i < 8; i++) - hdmi_channel_mapping[ca][i] = 0xf | (i << 4); - } - - for (i = 0; i < 8; i++) { - err = snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_HDMI_CHAN_SLOT, - hdmi_channel_mapping[ca][i]); - if (err) { - snd_printdd(KERN_NOTICE - "HDMI: channel mapping failed\n"); - break; - } - } - - hdmi_debug_channel_mapping(codec, pin_nid); -} - - -/* - * Audio InfoFrame routines - */ - -/* - * Enable Audio InfoFrame Transmission - */ -static void hdmi_start_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_BEST); -} - -/* - * Disable Audio InfoFrame Transmission - */ -static void hdmi_stop_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_DISABLE); -} - -static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int size; - - size = snd_hdmi_get_eld_size(codec, pin_nid); - printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); - - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); - } -#endif -} - -static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef BE_PARANOID - int i, j; - int size; - int pi, bi; - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - if (size == 0) - continue; - - hdmi_set_dip_index(codec, pin_nid, i, 0x0); - for (j = 1; j < 1000; j++) { - hdmi_write_dip_byte(codec, pin_nid, 0x0); - hdmi_get_dip_index(codec, pin_nid, &pi, &bi); - if (pi != i) - snd_printd(KERN_INFO "dip index %d: %d != %d\n", - bi, pi, i); - if (bi == 0) /* byte index wrapped around */ - break; - } - snd_printd(KERN_INFO - "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", - i, size, j); - } -#endif -} - -static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) -{ - u8 *bytes = (u8 *)hdmi_ai; - u8 sum = 0; - int i; - - hdmi_ai->checksum = 0; - - for (i = 0; i < sizeof(*hdmi_ai); i++) - sum += bytes[i]; - - hdmi_ai->checksum = -sum; -} - -static void hdmi_fill_audio_infoframe(struct hda_codec *codec, - hda_nid_t pin_nid, - u8 *dip, int size) -{ - int i; - - hdmi_debug_dip_size(codec, pin_nid); - hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < size; i++) - hdmi_write_dip_byte(codec, pin_nid, dip[i]); -} - -static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, - u8 *dip, int size) -{ - u8 val; - int i; - - if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) - != AC_DIPXMIT_BEST) - return false; - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < size; i++) { - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_DATA, 0); - if (val != dip[i]) - return false; - } - - return true; -} - -static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; - hda_nid_t pin_nid = per_pin->pin_nid; - int channels = substream->runtime->channels; - struct hdmi_eld *eld; - int ca; - union audio_infoframe ai; - - eld = &spec->pins[pin_idx].sink_eld; - if (!eld->monitor_present) - return; - - ca = hdmi_channel_allocation(eld, channels); - - memset(&ai, 0, sizeof(ai)); - if (eld->conn_type == 0) { /* HDMI */ - struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; - - hdmi_ai->type = 0x84; - hdmi_ai->ver = 0x01; - hdmi_ai->len = 0x0a; - hdmi_ai->CC02_CT47 = channels - 1; - hdmi_ai->CA = ca; - hdmi_checksum_audio_infoframe(hdmi_ai); - } else if (eld->conn_type == 1) { /* DisplayPort */ - struct dp_audio_infoframe *dp_ai = &ai.dp; - - dp_ai->type = 0x84; - dp_ai->len = 0x1b; - dp_ai->ver = 0x11 << 2; - dp_ai->CC02_CT47 = channels - 1; - dp_ai->CA = ca; - } else { - snd_printd("HDMI: unknown connection type at pin %d\n", - pin_nid); - return; - } - - /* - * sizeof(ai) is used instead of sizeof(*hdmi_ai) or - * sizeof(*dp_ai) to avoid partial match/update problems when - * the user switches between HDMI/DP monitors. - */ - if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, - sizeof(ai))) { - snd_printdd("hdmi_setup_audio_infoframe: " - "pin=%d channels=%d\n", - pin_nid, - channels); - hdmi_setup_channel_mapping(codec, pin_nid, ca); - hdmi_stop_infoframe_trans(codec, pin_nid); - hdmi_fill_audio_infoframe(codec, pin_nid, - ai.bytes, sizeof(ai)); - hdmi_start_infoframe_trans(codec, pin_nid); - } -} - - -/* - * Unsolicited events - */ - -static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); - -static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - struct hdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int pin_nid; - int pin_idx; - struct hda_jack_tbl *jack; - - jack = snd_hda_jack_tbl_get_from_tag(codec, tag); - if (!jack) - return; - pin_nid = jack->nid; - jack->jack_dirty = 1; - - _snd_printd(SND_PR_VERBOSE, - "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - codec->addr, pin_nid, - !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); - - pin_idx = pin_nid_to_pin_index(spec, pin_nid); - if (pin_idx < 0) - return; - - hdmi_present_sense(&spec->pins[pin_idx], 1); - snd_hda_jack_report_sync(codec); -} - -static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); - int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); - - printk(KERN_INFO - "HDMI CP event: CODEC=%d PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", - codec->addr, - tag, - subtag, - cp_state, - cp_ready); - - /* TODO */ - if (cp_state) - ; - if (cp_ready) - ; -} - - -static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) -{ - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - - if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { - snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); - return; - } - - if (subtag == 0) - hdmi_intrinsic_event(codec, res); - else - hdmi_non_intrinsic_event(codec, res); -} - -/* - * Callbacks - */ - -/* HBR should be Non-PCM, 8 channels */ -#define is_hbr_format(format) \ - ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7) - -static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format) -{ - int pinctl; - int new_pinctl = 0; - - if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { - pinctl = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - - new_pinctl = pinctl & ~AC_PINCTL_EPT; - if (is_hbr_format(format)) - new_pinctl |= AC_PINCTL_EPT_HBR; - else - new_pinctl |= AC_PINCTL_EPT_NATIVE; - - snd_printdd("hdmi_setup_stream: " - "NID=0x%x, %spinctl=0x%x\n", - pin_nid, - pinctl == new_pinctl ? "" : "new-", - new_pinctl); - - if (pinctl != new_pinctl) - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - new_pinctl); - - } - if (is_hbr_format(format) && !new_pinctl) { - snd_printdd("hdmi_setup_stream: HBR is not supported\n"); - return -EINVAL; - } - - snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); - return 0; -} - -/* - * HDA PCM callbacks - */ -static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - struct snd_pcm_runtime *runtime = substream->runtime; - int pin_idx, cvt_idx, mux_idx = 0; - struct hdmi_spec_per_pin *per_pin; - struct hdmi_eld *eld; - struct hdmi_spec_per_cvt *per_cvt = NULL; - int pinctl; - - /* Validate hinfo */ - pin_idx = hinfo_to_pin_index(spec, hinfo); - if (snd_BUG_ON(pin_idx < 0)) - return -EINVAL; - per_pin = &spec->pins[pin_idx]; - eld = &per_pin->sink_eld; - - /* Dynamically assign converter to stream */ - for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { - per_cvt = &spec->cvts[cvt_idx]; - - /* Must not already be assigned */ - if (per_cvt->assigned) - continue; - /* Must be in pin's mux's list of converters */ - for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++) - if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid) - break; - /* Not in mux list */ - if (mux_idx == per_pin->num_mux_nids) - continue; - break; - } - /* No free converters */ - if (cvt_idx == spec->num_cvts) - return -ENODEV; - - /* Claim converter */ - per_cvt->assigned = 1; - hinfo->nid = per_cvt->cvt_nid; - - snd_hda_codec_write(codec, per_pin->pin_nid, 0, - AC_VERB_SET_CONNECT_SEL, - mux_idx); - pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - snd_hda_codec_write(codec, per_pin->pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl | PIN_OUT); - snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); - - /* Initially set the converter's capabilities */ - hinfo->channels_min = per_cvt->channels_min; - hinfo->channels_max = per_cvt->channels_max; - hinfo->rates = per_cvt->rates; - hinfo->formats = per_cvt->formats; - hinfo->maxbps = per_cvt->maxbps; - - /* Restrict capabilities by ELD if this isn't disabled */ - if (!static_hdmi_pcm && eld->eld_valid) { - snd_hdmi_eld_update_pcm_info(eld, hinfo); - if (hinfo->channels_min > hinfo->channels_max || - !hinfo->rates || !hinfo->formats) - return -ENODEV; - } - - /* Store the updated parameters */ - runtime->hw.channels_min = hinfo->channels_min; - runtime->hw.channels_max = hinfo->channels_max; - runtime->hw.formats = hinfo->formats; - runtime->hw.rates = hinfo->rates; - - snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, 2); - return 0; -} - -/* - * HDA/HDMI auto parsing - */ -static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) -{ - struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; - hda_nid_t pin_nid = per_pin->pin_nid; - - if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { - snd_printk(KERN_WARNING - "HDMI: pin %d wcaps %#x " - "does not support connection list\n", - pin_nid, get_wcaps(codec, pin_nid)); - return -EINVAL; - } - - per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid, - per_pin->mux_nids, - HDA_MAX_CONNECTIONS); - - return 0; -} - -static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) -{ - struct hda_codec *codec = per_pin->codec; - struct hdmi_eld *eld = &per_pin->sink_eld; - hda_nid_t pin_nid = per_pin->pin_nid; - /* - * Always execute a GetPinSense verb here, even when called from - * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited - * response's PD bit is not the real PD value, but indicates that - * the real PD value changed. An older version of the HD-audio - * specification worked this way. Hence, we just ignore the data in - * the unsolicited response to avoid custom WARs. - */ - int present = snd_hda_pin_sense(codec, pin_nid); - bool eld_valid = false; - - memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer)); - - eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); - if (eld->monitor_present) - eld_valid = !!(present & AC_PINSENSE_ELDV); - - _snd_printd(SND_PR_VERBOSE, - "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - codec->addr, pin_nid, eld->monitor_present, eld_valid); - - if (eld_valid) { - if (!snd_hdmi_get_eld(eld, codec, pin_nid)) - snd_hdmi_show_eld(eld); - else if (repoll) { - queue_delayed_work(codec->bus->workq, - &per_pin->work, - msecs_to_jiffies(300)); - } - } -} - -static void hdmi_repoll_eld(struct work_struct *work) -{ - struct hdmi_spec_per_pin *per_pin = - container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); - - if (per_pin->repoll_count++ > 6) - per_pin->repoll_count = 0; - - hdmi_present_sense(per_pin, per_pin->repoll_count); -} - -static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct hdmi_spec *spec = codec->spec; - unsigned int caps, config; - int pin_idx; - struct hdmi_spec_per_pin *per_pin; - int err; - - caps = snd_hda_param_read(codec, pin_nid, AC_PAR_PIN_CAP); - if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) - return 0; - - config = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_CONFIG_DEFAULT, 0); - if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) - return 0; - - if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS)) - return -E2BIG; - - pin_idx = spec->num_pins; - per_pin = &spec->pins[pin_idx]; - - per_pin->pin_nid = pin_nid; - - err = hdmi_read_pin_conn(codec, pin_idx); - if (err < 0) - return err; - - spec->num_pins++; - - return 0; -} - -static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) -{ - struct hdmi_spec *spec = codec->spec; - int cvt_idx; - struct hdmi_spec_per_cvt *per_cvt; - unsigned int chans; - int err; - - if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS)) - return -E2BIG; - - chans = get_wcaps(codec, cvt_nid); - chans = get_wcaps_channels(chans); - - cvt_idx = spec->num_cvts; - per_cvt = &spec->cvts[cvt_idx]; - - per_cvt->cvt_nid = cvt_nid; - per_cvt->channels_min = 2; - if (chans <= 16) - per_cvt->channels_max = chans; - - err = snd_hda_query_supported_pcm(codec, cvt_nid, - &per_cvt->rates, - &per_cvt->formats, - &per_cvt->maxbps); - if (err < 0) - return err; - - spec->num_cvts++; - - return 0; -} - -static int hdmi_parse_codec(struct hda_codec *codec) -{ - hda_nid_t nid; - int i, nodes; - - nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); - if (!nid || nodes < 0) { - snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); - return -EINVAL; - } - - for (i = 0; i < nodes; i++, nid++) { - unsigned int caps; - unsigned int type; - - caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); - type = get_wcaps_type(caps); - - if (!(caps & AC_WCAP_DIGITAL)) - continue; - - switch (type) { - case AC_WID_AUD_OUT: - hdmi_add_cvt(codec, nid); - break; - case AC_WID_PIN: - hdmi_add_pin(codec, nid); - break; - } - } - - /* - * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event - * can be lost and presence sense verb will become inaccurate if the - * HDA link is powered off at hot plug or hw initialization time. - */ -#ifdef CONFIG_SND_HDA_POWER_SAVE - if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & - AC_PWRST_EPSS)) - codec->bus->power_keep_link_on = 1; -#endif - - return 0; -} - -/* - */ -static char *get_hdmi_pcm_name(int idx) -{ - static char names[MAX_HDMI_PINS][8]; - sprintf(&names[idx][0], "HDMI %d", idx); - return &names[idx][0]; -} - -/* - * HDMI callbacks - */ - -static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - hda_nid_t cvt_nid = hinfo->nid; - struct hdmi_spec *spec = codec->spec; - int pin_idx = hinfo_to_pin_index(spec, hinfo); - hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; - - hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); - - hdmi_setup_audio_infoframe(codec, pin_idx, substream); - - return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); -} - -static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - int cvt_idx, pin_idx; - struct hdmi_spec_per_cvt *per_cvt; - struct hdmi_spec_per_pin *per_pin; - int pinctl; - - snd_hda_codec_cleanup_stream(codec, hinfo->nid); - - if (hinfo->nid) { - cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); - if (snd_BUG_ON(cvt_idx < 0)) - return -EINVAL; - per_cvt = &spec->cvts[cvt_idx]; - - snd_BUG_ON(!per_cvt->assigned); - per_cvt->assigned = 0; - hinfo->nid = 0; - - pin_idx = hinfo_to_pin_index(spec, hinfo); - if (snd_BUG_ON(pin_idx < 0)) - return -EINVAL; - per_pin = &spec->pins[pin_idx]; - - pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - snd_hda_codec_write(codec, per_pin->pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl & ~PIN_OUT); - snd_hda_spdif_ctls_unassign(codec, pin_idx); - } - - return 0; -} - -static const struct hda_pcm_ops generic_ops = { - .open = hdmi_pcm_open, - .prepare = generic_hdmi_playback_pcm_prepare, - .cleanup = generic_hdmi_playback_pcm_cleanup, -}; - -static int generic_hdmi_build_pcms(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - int pin_idx; - - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { - struct hda_pcm *info; - struct hda_pcm_stream *pstr; - - info = &spec->pcm_rec[pin_idx]; - info->name = get_hdmi_pcm_name(pin_idx); - info->pcm_type = HDA_PCM_TYPE_HDMI; - - pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; - pstr->substreams = 1; - pstr->ops = generic_ops; - /* other pstr fields are set in open */ - } - - codec->num_pcms = spec->num_pins; - codec->pcm_info = spec->pcm_rec; - - return 0; -} - -static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) -{ - char hdmi_str[32] = "HDMI/DP"; - struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; - int pcmdev = spec->pcm_rec[pin_idx].device; - - if (pcmdev > 0) - sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); - - return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); -} - -static int generic_hdmi_build_controls(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - int err; - int pin_idx; - - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { - struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; - - err = generic_hdmi_build_jack(codec, pin_idx); - if (err < 0) - return err; - - err = snd_hda_create_spdif_out_ctls(codec, - per_pin->pin_nid, - per_pin->mux_nids[0]); - if (err < 0) - return err; - snd_hda_spdif_ctls_unassign(codec, pin_idx); - - /* add control for ELD Bytes */ - err = hdmi_create_eld_ctl(codec, - pin_idx, - spec->pcm_rec[pin_idx].device); - - if (err < 0) - return err; - - hdmi_present_sense(per_pin, 0); - } - - return 0; -} - -static int generic_hdmi_init(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - int pin_idx; - - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { - struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; - hda_nid_t pin_nid = per_pin->pin_nid; - struct hdmi_eld *eld = &per_pin->sink_eld; - - hdmi_init_pin(codec, pin_nid); - snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); - - per_pin->codec = codec; - INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); - snd_hda_eld_proc_new(codec, eld, pin_idx); - } - snd_hda_jack_report_sync(codec); - return 0; -} - -static void generic_hdmi_free(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - int pin_idx; - - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { - struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; - struct hdmi_eld *eld = &per_pin->sink_eld; - - cancel_delayed_work(&per_pin->work); - snd_hda_eld_proc_free(codec, eld); - } - - flush_workqueue(codec->bus->workq); - kfree(spec); -} - -static const struct hda_codec_ops generic_hdmi_patch_ops = { - .init = generic_hdmi_init, - .free = generic_hdmi_free, - .build_pcms = generic_hdmi_build_pcms, - .build_controls = generic_hdmi_build_controls, - .unsol_event = hdmi_unsol_event, -}; - -static int patch_generic_hdmi(struct hda_codec *codec) -{ - struct hdmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - if (hdmi_parse_codec(codec) < 0) { - codec->spec = NULL; - kfree(spec); - return -EINVAL; - } - codec->patch_ops = generic_hdmi_patch_ops; - - init_channel_allocations(); - - return 0; -} - -/* - * Shared non-generic implementations - */ - -static int simple_playback_build_pcms(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - int i; - - codec->num_pcms = spec->num_cvts; - codec->pcm_info = info; - - for (i = 0; i < codec->num_pcms; i++, info++) { - unsigned int chans; - struct hda_pcm_stream *pstr; - - chans = get_wcaps(codec, spec->cvts[i].cvt_nid); - chans = get_wcaps_channels(chans); - - info->name = get_hdmi_pcm_name(i); - info->pcm_type = HDA_PCM_TYPE_HDMI; - pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; - snd_BUG_ON(!spec->pcm_playback); - *pstr = *spec->pcm_playback; - pstr->nid = spec->cvts[i].cvt_nid; - if (pstr->channels_max <= 2 && chans && chans <= 16) - pstr->channels_max = chans; - } - - return 0; -} - -static int simple_playback_build_controls(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - int err; - int i; - - for (i = 0; i < codec->num_pcms; i++) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->cvts[i].cvt_nid, - spec->cvts[i].cvt_nid); - if (err < 0) - return err; - } - - return 0; -} - -static void simple_playback_free(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - - kfree(spec); -} - -/* - * Nvidia specific implementations - */ - -#define Nv_VERB_SET_Channel_Allocation 0xF79 -#define Nv_VERB_SET_Info_Frame_Checksum 0xF7A -#define Nv_VERB_SET_Audio_Protection_On 0xF98 -#define Nv_VERB_SET_Audio_Protection_Off 0xF99 - -#define nvhdmi_master_con_nid_7x 0x04 -#define nvhdmi_master_pin_nid_7x 0x05 - -static const hda_nid_t nvhdmi_con_nids_7x[4] = { - /*front, rear, clfe, rear_surr */ - 0x6, 0x8, 0xa, 0xc, -}; - -static const struct hda_verb nvhdmi_basic_init_7x[] = { - /* set audio protect on */ - { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, - /* enable digital output on pin widget */ - { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, - { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, - { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, - { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, - { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, - {} /* terminator */ -}; - -#ifdef LIMITED_RATE_FMT_SUPPORT -/* support only the safe format and rate */ -#define SUPPORTED_RATES SNDRV_PCM_RATE_48000 -#define SUPPORTED_MAXBPS 16 -#define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE -#else -/* support all rates and formats */ -#define SUPPORTED_RATES \ - (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ - SNDRV_PCM_RATE_192000) -#define SUPPORTED_MAXBPS 24 -#define SUPPORTED_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) -#endif - -static int nvhdmi_7x_init(struct hda_codec *codec) -{ - snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); - return 0; -} - -static unsigned int channels_2_6_8[] = { - 2, 6, 8 -}; - -static unsigned int channels_2_8[] = { - 2, 8 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { - .count = ARRAY_SIZE(channels_2_6_8), - .list = channels_2_6_8, - .mask = 0, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { - .count = ARRAY_SIZE(channels_2_8), - .list = channels_2_8, - .mask = 0, -}; - -static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; - - switch (codec->preset->id) { - case 0x10de0002: - case 0x10de0003: - case 0x10de0005: - case 0x10de0006: - hw_constraints_channels = &hw_constraints_2_8_channels; - break; - case 0x10de0007: - hw_constraints_channels = &hw_constraints_2_6_8_channels; - break; - default: - break; - } - - if (hw_constraints_channels != NULL) { - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_constraints_channels); - } else { - snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, 2); - } - - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, - stream_tag, format, substream); -} - -static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, - int channels) -{ - unsigned int chanmask; - int chan = channels ? (channels - 1) : 1; - - switch (channels) { - default: - case 0: - case 2: - chanmask = 0x00; - break; - case 4: - chanmask = 0x08; - break; - case 6: - chanmask = 0x0b; - break; - case 8: - chanmask = 0x13; - break; - } - - /* Set the audio infoframe channel allocation and checksum fields. The - * channel count is computed implicitly by the hardware. */ - snd_hda_codec_write(codec, 0x1, 0, - Nv_VERB_SET_Channel_Allocation, chanmask); - - snd_hda_codec_write(codec, 0x1, 0, - Nv_VERB_SET_Info_Frame_Checksum, - (0x71 - chan - chanmask)); -} - -static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - int i; - - snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, - 0, AC_VERB_SET_CHANNEL_STREAMID, 0); - for (i = 0; i < 4; i++) { - /* set the stream id */ - snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, - AC_VERB_SET_CHANNEL_STREAMID, 0); - /* set the stream format */ - snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, - AC_VERB_SET_STREAM_FORMAT, 0); - } - - /* The audio hardware sends a channel count of 0x7 (8ch) when all the - * streams are disabled. */ - nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); - - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - int chs; - unsigned int dataDCC2, channel_id; - int i; - struct hdmi_spec *spec = codec->spec; - struct hda_spdif_out *spdif = - snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid); - - mutex_lock(&codec->spdif_mutex); - - chs = substream->runtime->channels; - - dataDCC2 = 0x2; - - /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ - if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) - snd_hda_codec_write(codec, - nvhdmi_master_con_nid_7x, - 0, - AC_VERB_SET_DIGI_CONVERT_1, - spdif->ctls & ~AC_DIG1_ENABLE & 0xff); - - /* set the stream id */ - snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, - AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); - - /* set the stream format */ - snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, - AC_VERB_SET_STREAM_FORMAT, format); - - /* turn on again (if needed) */ - /* enable and set the channel status audio/data flag */ - if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) { - snd_hda_codec_write(codec, - nvhdmi_master_con_nid_7x, - 0, - AC_VERB_SET_DIGI_CONVERT_1, - spdif->ctls & 0xff); - snd_hda_codec_write(codec, - nvhdmi_master_con_nid_7x, - 0, - AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); - } - - for (i = 0; i < 4; i++) { - if (chs == 2) - channel_id = 0; - else - channel_id = i * 2; - - /* turn off SPDIF once; - *otherwise the IEC958 bits won't be updated - */ - if (codec->spdif_status_reset && - (spdif->ctls & AC_DIG1_ENABLE)) - snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], - 0, - AC_VERB_SET_DIGI_CONVERT_1, - spdif->ctls & ~AC_DIG1_ENABLE & 0xff); - /* set the stream id */ - snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], - 0, - AC_VERB_SET_CHANNEL_STREAMID, - (stream_tag << 4) | channel_id); - /* set the stream format */ - snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], - 0, - AC_VERB_SET_STREAM_FORMAT, - format); - /* turn on again (if needed) */ - /* enable and set the channel status audio/data flag */ - if (codec->spdif_status_reset && - (spdif->ctls & AC_DIG1_ENABLE)) { - snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], - 0, - AC_VERB_SET_DIGI_CONVERT_1, - spdif->ctls & 0xff); - snd_hda_codec_write(codec, - nvhdmi_con_nids_7x[i], - 0, - AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); - } - } - - nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs); - - mutex_unlock(&codec->spdif_mutex); - return 0; -} - -static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { - .substreams = 1, - .channels_min = 2, - .channels_max = 8, - .nid = nvhdmi_master_con_nid_7x, - .rates = SUPPORTED_RATES, - .maxbps = SUPPORTED_MAXBPS, - .formats = SUPPORTED_FORMATS, - .ops = { - .open = simple_playback_pcm_open, - .close = nvhdmi_8ch_7x_pcm_close, - .prepare = nvhdmi_8ch_7x_pcm_prepare - }, -}; - -static const struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = nvhdmi_master_con_nid_7x, - .rates = SUPPORTED_RATES, - .maxbps = SUPPORTED_MAXBPS, - .formats = SUPPORTED_FORMATS, - .ops = { - .open = simple_playback_pcm_open, - .close = simple_playback_pcm_close, - .prepare = simple_playback_pcm_prepare - }, -}; - -static const struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = nvhdmi_7x_init, - .free = simple_playback_free, -}; - -static const struct hda_codec_ops nvhdmi_patch_ops_2ch = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = nvhdmi_7x_init, - .free = simple_playback_free, -}; - -static int patch_nvhdmi_2ch(struct hda_codec *codec) -{ - struct hdmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->multiout.num_dacs = 0; /* no analog */ - spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; - spec->num_cvts = 1; - spec->cvts[0].cvt_nid = nvhdmi_master_con_nid_7x; - spec->pcm_playback = &nvhdmi_pcm_playback_2ch; - - codec->patch_ops = nvhdmi_patch_ops_2ch; - - return 0; -} - -static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) -{ - struct hdmi_spec *spec; - int err = patch_nvhdmi_2ch(codec); - - if (err < 0) - return err; - spec = codec->spec; - spec->multiout.max_channels = 8; - spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; - codec->patch_ops = nvhdmi_patch_ops_8ch_7x; - - /* Initialize the audio infoframe channel mask and checksum to something - * valid */ - nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); - - return 0; -} - -/* - * ATI-specific implementations - * - * FIXME: we may omit the whole this and use the generic code once after - * it's confirmed to work. - */ - -#define ATIHDMI_CVT_NID 0x02 /* audio converter */ -#define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */ - -static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct hdmi_spec *spec = codec->spec; - int chans = substream->runtime->channels; - int i, err; - - err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format, - substream); - if (err < 0) - return err; - snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0, - AC_VERB_SET_CVT_CHAN_COUNT, chans - 1); - /* FIXME: XXX */ - for (i = 0; i < chans; i++) { - snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0, - AC_VERB_SET_HDMI_CHAN_SLOT, - (i << 4) | i); - } - return 0; -} - -static const struct hda_pcm_stream atihdmi_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = ATIHDMI_CVT_NID, - .ops = { - .open = simple_playback_pcm_open, - .close = simple_playback_pcm_close, - .prepare = atihdmi_playback_pcm_prepare - }, -}; - -static const struct hda_verb atihdmi_basic_init[] = { - /* enable digital output on pin widget */ - { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {} /* terminator */ -}; - -static int atihdmi_init(struct hda_codec *codec) -{ - struct hdmi_spec *spec = codec->spec; - - snd_hda_sequence_write(codec, atihdmi_basic_init); - /* SI codec requires to unmute the pin */ - if (get_wcaps(codec, spec->pins[0].pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, spec->pins[0].pin_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); - return 0; -} - -static const struct hda_codec_ops atihdmi_patch_ops = { - .build_controls = simple_playback_build_controls, - .build_pcms = simple_playback_build_pcms, - .init = atihdmi_init, - .free = simple_playback_free, -}; - - -static int patch_atihdmi(struct hda_codec *codec) -{ - struct hdmi_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->multiout.num_dacs = 0; /* no analog */ - spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; - spec->num_cvts = 1; - spec->cvts[0].cvt_nid = ATIHDMI_CVT_NID; - spec->pins[0].pin_nid = ATIHDMI_PIN_NID; - spec->pcm_playback = &atihdmi_pcm_digital_playback; - - codec->patch_ops = atihdmi_patch_ops; - - return 0; -} - - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_hdmi[] = { -{ .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, -{ .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, -{ .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, -{ .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, -{ .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, -{ .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, -{ .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, -{ .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, -{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_generic_hdmi }, -/* 17 is known to be absent */ -{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, -{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, -{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, -{ .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, -{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, -{} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:1002793c"); -MODULE_ALIAS("snd-hda-codec-id:10027919"); -MODULE_ALIAS("snd-hda-codec-id:1002791a"); -MODULE_ALIAS("snd-hda-codec-id:1002aa01"); -MODULE_ALIAS("snd-hda-codec-id:10951390"); -MODULE_ALIAS("snd-hda-codec-id:10951392"); -MODULE_ALIAS("snd-hda-codec-id:10de0002"); -MODULE_ALIAS("snd-hda-codec-id:10de0003"); -MODULE_ALIAS("snd-hda-codec-id:10de0005"); -MODULE_ALIAS("snd-hda-codec-id:10de0006"); -MODULE_ALIAS("snd-hda-codec-id:10de0007"); -MODULE_ALIAS("snd-hda-codec-id:10de000a"); -MODULE_ALIAS("snd-hda-codec-id:10de000b"); -MODULE_ALIAS("snd-hda-codec-id:10de000c"); -MODULE_ALIAS("snd-hda-codec-id:10de000d"); -MODULE_ALIAS("snd-hda-codec-id:10de0010"); -MODULE_ALIAS("snd-hda-codec-id:10de0011"); -MODULE_ALIAS("snd-hda-codec-id:10de0012"); -MODULE_ALIAS("snd-hda-codec-id:10de0013"); -MODULE_ALIAS("snd-hda-codec-id:10de0014"); -MODULE_ALIAS("snd-hda-codec-id:10de0015"); -MODULE_ALIAS("snd-hda-codec-id:10de0016"); -MODULE_ALIAS("snd-hda-codec-id:10de0018"); -MODULE_ALIAS("snd-hda-codec-id:10de0019"); -MODULE_ALIAS("snd-hda-codec-id:10de001a"); -MODULE_ALIAS("snd-hda-codec-id:10de001b"); -MODULE_ALIAS("snd-hda-codec-id:10de001c"); -MODULE_ALIAS("snd-hda-codec-id:10de0040"); -MODULE_ALIAS("snd-hda-codec-id:10de0041"); -MODULE_ALIAS("snd-hda-codec-id:10de0042"); -MODULE_ALIAS("snd-hda-codec-id:10de0043"); -MODULE_ALIAS("snd-hda-codec-id:10de0044"); -MODULE_ALIAS("snd-hda-codec-id:10de0067"); -MODULE_ALIAS("snd-hda-codec-id:10de8001"); -MODULE_ALIAS("snd-hda-codec-id:17e80047"); -MODULE_ALIAS("snd-hda-codec-id:80860054"); -MODULE_ALIAS("snd-hda-codec-id:80862801"); -MODULE_ALIAS("snd-hda-codec-id:80862802"); -MODULE_ALIAS("snd-hda-codec-id:80862803"); -MODULE_ALIAS("snd-hda-codec-id:80862804"); -MODULE_ALIAS("snd-hda-codec-id:80862805"); -MODULE_ALIAS("snd-hda-codec-id:80862806"); -MODULE_ALIAS("snd-hda-codec-id:80862880"); -MODULE_ALIAS("snd-hda-codec-id:808629fb"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("HDMI HD-audio codec"); -MODULE_ALIAS("snd-hda-codec-intelhdmi"); -MODULE_ALIAS("snd-hda-codec-nvhdmi"); -MODULE_ALIAS("snd-hda-codec-atihdmi"); - -static struct hda_codec_preset_list intel_list = { - .preset = snd_hda_preset_hdmi, - .owner = THIS_MODULE, -}; - -static int __init patch_hdmi_init(void) -{ - return snd_hda_add_codec_preset(&intel_list); -} - -static void __exit patch_hdmi_exit(void) -{ - snd_hda_delete_codec_preset(&intel_list); -} - -module_init(patch_hdmi_init) -module_exit(patch_hdmi_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_realtek.c b/ANDROID_3.4.5/sound/pci/hda/patch_realtek.c deleted file mode 100644 index c43264f5..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_realtek.c +++ /dev/null @@ -1,7034 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * HD audio interface patch for Realtek ALC codecs - * - * Copyright (c) 2004 Kailang Yang - * PeiSen Hou - * Takashi Iwai - * Jonathan Woithe - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" -#include "hda_beep.h" -#include "hda_jack.h" - -/* unsol event tags */ -#define ALC_FRONT_EVENT 0x01 -#define ALC_DCVOL_EVENT 0x02 -#define ALC_HP_EVENT 0x04 -#define ALC_MIC_EVENT 0x08 - -/* for GPIO Poll */ -#define GPIO_MASK 0x03 - -/* extra amp-initialization sequence types */ -enum { - ALC_INIT_NONE, - ALC_INIT_DEFAULT, - ALC_INIT_GPIO1, - ALC_INIT_GPIO2, - ALC_INIT_GPIO3, -}; - -struct alc_customize_define { - unsigned int sku_cfg; - unsigned char port_connectivity; - unsigned char check_sum; - unsigned char customization; - unsigned char external_amp; - unsigned int enable_pcbeep:1; - unsigned int platform_type:1; - unsigned int swap:1; - unsigned int override:1; - unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */ -}; - -struct alc_fixup; - -struct alc_multi_io { - hda_nid_t pin; /* multi-io widget pin NID */ - hda_nid_t dac; /* DAC to be connected */ - unsigned int ctl_in; /* cached input-pin control value */ -}; - -enum { - ALC_AUTOMUTE_PIN, /* change the pin control */ - ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */ - ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */ -}; - -#define MAX_VOL_NIDS 0x40 - -struct alc_spec { - /* codec parameterization */ - const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ - unsigned int num_mixers; - const struct snd_kcontrol_new *cap_mixer; /* capture mixer */ - unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ - - const struct hda_verb *init_verbs[10]; /* initialization verbs - * don't forget NULL - * termination! - */ - unsigned int num_init_verbs; - - char stream_name_analog[32]; /* analog PCM stream */ - const struct hda_pcm_stream *stream_analog_playback; - const struct hda_pcm_stream *stream_analog_capture; - const struct hda_pcm_stream *stream_analog_alt_playback; - const struct hda_pcm_stream *stream_analog_alt_capture; - - char stream_name_digital[32]; /* digital PCM stream */ - const struct hda_pcm_stream *stream_digital_playback; - const struct hda_pcm_stream *stream_digital_capture; - - /* playback */ - struct hda_multi_out multiout; /* playback set-up - * max_channels, dacs must be set - * dig_out_nid and hp_nid are optional - */ - hda_nid_t alt_dac_nid; - hda_nid_t slave_dig_outs[3]; /* optional - for auto-parsing */ - int dig_out_type; - - /* capture */ - unsigned int num_adc_nids; - const hda_nid_t *adc_nids; - const hda_nid_t *capsrc_nids; - hda_nid_t dig_in_nid; /* digital-in NID; optional */ - hda_nid_t mixer_nid; /* analog-mixer NID */ - DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1); - DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1); - - /* capture setup for dynamic dual-adc switch */ - hda_nid_t cur_adc; - unsigned int cur_adc_stream_tag; - unsigned int cur_adc_format; - - /* capture source */ - unsigned int num_mux_defs; - const struct hda_input_mux *input_mux; - unsigned int cur_mux[3]; - hda_nid_t ext_mic_pin; - hda_nid_t dock_mic_pin; - hda_nid_t int_mic_pin; - - /* channel model */ - const struct hda_channel_mode *channel_mode; - int num_channel_mode; - int need_dac_fix; - int const_channel_count; - int ext_channel_count; - - /* PCM information */ - struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ - - /* dynamic controls, init_verbs and input_mux */ - struct auto_pin_cfg autocfg; - struct alc_customize_define cdefine; - struct snd_array kctls; - struct hda_input_mux private_imux[3]; - hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; - hda_nid_t private_adc_nids[AUTO_CFG_MAX_OUTS]; - hda_nid_t private_capsrc_nids[AUTO_CFG_MAX_OUTS]; - hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; - unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; - int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */ - - /* hooks */ - void (*init_hook)(struct hda_codec *codec); - void (*unsol_event)(struct hda_codec *codec, unsigned int res); -#ifdef CONFIG_SND_HDA_POWER_SAVE - void (*power_hook)(struct hda_codec *codec); -#endif - void (*shutup)(struct hda_codec *codec); - void (*automute_hook)(struct hda_codec *codec); - - /* for pin sensing */ - unsigned int hp_jack_present:1; - unsigned int line_jack_present:1; - unsigned int master_mute:1; - unsigned int auto_mic:1; - unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */ - unsigned int automute_speaker:1; /* automute speaker outputs */ - unsigned int automute_lo:1; /* automute LO outputs */ - unsigned int detect_hp:1; /* Headphone detection enabled */ - unsigned int detect_lo:1; /* Line-out detection enabled */ - unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */ - unsigned int automute_lo_possible:1; /* there are line outs and HP */ - unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ - - /* other flags */ - unsigned int no_analog :1; /* digital I/O only */ - unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */ - unsigned int single_input_src:1; - unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ - unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ - unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ - - /* auto-mute control */ - int automute_mode; - hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS]; - - int init_amp; - int codec_variant; /* flag for other variants */ - - /* for virtual master */ - hda_nid_t vmaster_nid; - struct hda_vmaster_mute_hook vmaster_mute; -#ifdef CONFIG_SND_HDA_POWER_SAVE - struct hda_loopback_check loopback; - int num_loopbacks; - struct hda_amp_list loopback_list[8]; -#endif - - /* for PLL fix */ - hda_nid_t pll_nid; - unsigned int pll_coef_idx, pll_coef_bit; - unsigned int coef0; - - /* fix-up list */ - int fixup_id; - const struct alc_fixup *fixup_list; - const char *fixup_name; - - /* multi-io */ - int multi_ios; - struct alc_multi_io multi_io[4]; - - /* bind volumes */ - struct snd_array bind_ctls; -}; - -static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, - int dir, unsigned int bits) -{ - if (!nid) - return false; - if (get_wcaps(codec, nid) & (1 << (dir + 1))) - if (query_amp_caps(codec, nid, dir) & bits) - return true; - return false; -} - -#define nid_has_mute(codec, nid, dir) \ - check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE) -#define nid_has_volume(codec, nid, dir) \ - check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS) - -/* - * input MUX handling - */ -static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); - if (mux_idx >= spec->num_mux_defs) - mux_idx = 0; - if (!spec->input_mux[mux_idx].num_items && mux_idx > 0) - mux_idx = 0; - return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); -} - -static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; - return 0; -} - -static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]]; - - if (spec->cur_adc && spec->cur_adc != new_adc) { - /* stream is running, let's swap the current ADC */ - __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); - spec->cur_adc = new_adc; - snd_hda_codec_setup_stream(codec, new_adc, - spec->cur_adc_stream_tag, 0, - spec->cur_adc_format); - return true; - } - return false; -} - -static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) -{ - return spec->capsrc_nids ? - spec->capsrc_nids[idx] : spec->adc_nids[idx]; -} - -static void call_update_outputs(struct hda_codec *codec); - -/* select the given imux item; either unmute exclusively or select the route */ -static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, - unsigned int idx, bool force) -{ - struct alc_spec *spec = codec->spec; - const struct hda_input_mux *imux; - unsigned int mux_idx; - int i, type, num_conns; - hda_nid_t nid; - - if (!spec->input_mux) - return 0; - - mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; - imux = &spec->input_mux[mux_idx]; - if (!imux->num_items && mux_idx > 0) - imux = &spec->input_mux[0]; - if (!imux->num_items) - return 0; - - if (idx >= imux->num_items) - idx = imux->num_items - 1; - if (spec->cur_mux[adc_idx] == idx && !force) - return 0; - spec->cur_mux[adc_idx] = idx; - - /* for shared I/O, change the pin-control accordingly */ - if (spec->shared_mic_hp) { - /* NOTE: this assumes that there are only two inputs, the - * first is the real internal mic and the second is HP jack. - */ - snd_hda_codec_write(codec, spec->autocfg.inputs[1].pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - spec->cur_mux[adc_idx] ? - PIN_VREF80 : PIN_HP); - spec->automute_speaker = !spec->cur_mux[adc_idx]; - call_update_outputs(codec); - } - - if (spec->dyn_adc_switch) { - alc_dyn_adc_pcm_resetup(codec, idx); - adc_idx = spec->dyn_adc_idx[idx]; - } - - nid = get_capsrc(spec, adc_idx); - - /* no selection? */ - num_conns = snd_hda_get_conn_list(codec, nid, NULL); - if (num_conns <= 1) - return 1; - - type = get_wcaps_type(get_wcaps(codec, nid)); - if (type == AC_WID_AUD_MIX) { - /* Matrix-mixer style (e.g. ALC882) */ - int active = imux->items[idx].index; - for (i = 0; i < num_conns; i++) { - unsigned int v = (i == active) ? 0 : HDA_AMP_MUTE; - snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, i, - HDA_AMP_MUTE, v); - } - } else { - /* MUX style (e.g. ALC880) */ - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, - imux->items[idx].index); - } - return 1; -} - -static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - return alc_mux_select(codec, adc_idx, - ucontrol->value.enumerated.item[0], false); -} - -/* - * set up the input pin config (depending on the given auto-pin type) - */ -static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, - int auto_pin_type) -{ - unsigned int val = PIN_IN; - - if (auto_pin_type == AUTO_PIN_MIC) { - unsigned int pincap; - unsigned int oldval; - oldval = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - pincap = snd_hda_query_pin_caps(codec, nid); - pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; - /* if the default pin setup is vref50, we give it priority */ - if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50) - val = PIN_VREF80; - else if (pincap & AC_PINCAP_VREF_50) - val = PIN_VREF50; - else if (pincap & AC_PINCAP_VREF_100) - val = PIN_VREF100; - else if (pincap & AC_PINCAP_VREF_GRD) - val = PIN_VREFGRD; - } - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); -} - -/* - * Append the given mixer and verb elements for the later use - * The mixer array is referred in build_controls(), and init_verbs are - * called in init(). - */ -static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix) -{ - if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers))) - return; - spec->mixers[spec->num_mixers++] = mix; -} - -static void add_verb(struct alc_spec *spec, const struct hda_verb *verb) -{ - if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs))) - return; - spec->init_verbs[spec->num_init_verbs++] = verb; -} - -/* - * GPIO setup tables, used in initialization - */ -/* Enable GPIO mask and set output */ -static const struct hda_verb alc_gpio1_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - { } -}; - -static const struct hda_verb alc_gpio2_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, - { } -}; - -static const struct hda_verb alc_gpio3_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, - { } -}; - -/* - * Fix hardware PLL issue - * On some codecs, the analog PLL gating control must be off while - * the default value is 1. - */ -static void alc_fix_pll(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - unsigned int val; - - if (!spec->pll_nid) - return; - snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX, - spec->pll_coef_idx); - val = snd_hda_codec_read(codec, spec->pll_nid, 0, - AC_VERB_GET_PROC_COEF, 0); - snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX, - spec->pll_coef_idx); - snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF, - val & ~(1 << spec->pll_coef_bit)); -} - -static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, - unsigned int coef_idx, unsigned int coef_bit) -{ - struct alc_spec *spec = codec->spec; - spec->pll_nid = nid; - spec->pll_coef_idx = coef_idx; - spec->pll_coef_bit = coef_bit; - alc_fix_pll(codec); -} - -/* - * Jack detections for HP auto-mute and mic-switch - */ - -/* check each pin in the given array; returns true if any of them is plugged */ -static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins) -{ - int i, present = 0; - - for (i = 0; i < num_pins; i++) { - hda_nid_t nid = pins[i]; - if (!nid) - break; - present |= snd_hda_jack_detect(codec, nid); - } - return present; -} - -/* standard HP/line-out auto-mute helper */ -static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins, - bool mute, bool hp_out) -{ - struct alc_spec *spec = codec->spec; - unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0; - unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT); - int i; - - for (i = 0; i < num_pins; i++) { - hda_nid_t nid = pins[i]; - unsigned int val; - if (!nid) - break; - switch (spec->automute_mode) { - case ALC_AUTOMUTE_PIN: - /* don't reset VREF value in case it's controlling - * the amp (see alc861_fixup_asus_amp_vref_0f()) - */ - if (spec->keep_vref_in_automute) { - val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - val &= ~PIN_HP; - } else - val = 0; - val |= pin_bits; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - val); - break; - case ALC_AUTOMUTE_AMP: - snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, - HDA_AMP_MUTE, mute_bits); - break; - case ALC_AUTOMUTE_MIXER: - nid = spec->automute_mixer_nid[i]; - if (!nid) - break; - snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0, - HDA_AMP_MUTE, mute_bits); - snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1, - HDA_AMP_MUTE, mute_bits); - break; - } - } -} - -/* Toggle outputs muting */ -static void update_outputs(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int on; - - /* Control HP pins/amps depending on master_mute state; - * in general, HP pins/amps control should be enabled in all cases, - * but currently set only for master_mute, just to be safe - */ - if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */ - do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), - spec->autocfg.hp_pins, spec->master_mute, true); - - if (!spec->automute_speaker) - on = 0; - else - on = spec->hp_jack_present | spec->line_jack_present; - on |= spec->master_mute; - do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins), - spec->autocfg.speaker_pins, on, false); - - /* toggle line-out mutes if needed, too */ - /* if LO is a copy of either HP or Speaker, don't need to handle it */ - if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] || - spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0]) - return; - if (!spec->automute_lo) - on = 0; - else - on = spec->hp_jack_present; - on |= spec->master_mute; - do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins), - spec->autocfg.line_out_pins, on, false); -} - -static void call_update_outputs(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - if (spec->automute_hook) - spec->automute_hook(codec); - else - update_outputs(codec); -} - -/* standard HP-automute helper */ -static void alc_hp_automute(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - spec->hp_jack_present = - detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins), - spec->autocfg.hp_pins); - if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo)) - return; - call_update_outputs(codec); -} - -/* standard line-out-automute helper */ -static void alc_line_automute(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - /* check LO jack only when it's different from HP */ - if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0]) - return; - - spec->line_jack_present = - detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins), - spec->autocfg.line_out_pins); - if (!spec->automute_speaker || !spec->detect_lo) - return; - call_update_outputs(codec); -} - -#define get_connection_index(codec, mux, nid) \ - snd_hda_get_conn_index(codec, mux, nid, 0) - -/* standard mic auto-switch helper */ -static void alc_mic_automute(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t *pins = spec->imux_pins; - - if (!spec->auto_mic || !spec->auto_mic_valid_imux) - return; - if (snd_BUG_ON(!spec->adc_nids)) - return; - if (snd_BUG_ON(spec->int_mic_idx < 0 || spec->ext_mic_idx < 0)) - return; - - if (snd_hda_jack_detect(codec, pins[spec->ext_mic_idx])) - alc_mux_select(codec, 0, spec->ext_mic_idx, false); - else if (spec->dock_mic_idx >= 0 && - snd_hda_jack_detect(codec, pins[spec->dock_mic_idx])) - alc_mux_select(codec, 0, spec->dock_mic_idx, false); - else - alc_mux_select(codec, 0, spec->int_mic_idx, false); -} - -/* handle the specified unsol action (ALC_XXX_EVENT) */ -static void alc_exec_unsol_event(struct hda_codec *codec, int action) -{ - switch (action) { - case ALC_HP_EVENT: - alc_hp_automute(codec); - break; - case ALC_FRONT_EVENT: - alc_line_automute(codec); - break; - case ALC_MIC_EVENT: - alc_mic_automute(codec); - break; - } - snd_hda_jack_report_sync(codec); -} - -/* update the master volume per volume-knob's unsol event */ -static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int val; - struct snd_kcontrol *kctl; - struct snd_ctl_elem_value *uctl; - - kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume"); - if (!kctl) - return; - uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); - if (!uctl) - return; - val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); - val &= HDA_AMP_VOLMASK; - uctl->value.integer.value[0] = val; - uctl->value.integer.value[1] = val; - kctl->put(kctl, uctl); - kfree(uctl); -} - -/* unsolicited event for HP jack sensing */ -static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) -{ - int action; - - if (codec->vendor_id == 0x10ec0880) - res >>= 28; - else - res >>= 26; - action = snd_hda_jack_get_action(codec, res); - if (action == ALC_DCVOL_EVENT) { - /* Execute the dc-vol event here as it requires the NID - * but we don't pass NID to alc_exec_unsol_event(). - * Once when we convert all static quirks to the auto-parser, - * this can be integerated into there. - */ - struct hda_jack_tbl *jack; - jack = snd_hda_jack_tbl_get_from_tag(codec, res); - if (jack) - alc_update_knob_master(codec, jack->nid); - return; - } - alc_exec_unsol_event(codec, action); -} - -/* call init functions of standard auto-mute helpers */ -static void alc_inithook(struct hda_codec *codec) -{ - alc_hp_automute(codec); - alc_line_automute(codec); - alc_mic_automute(codec); -} - -/* additional initialization for ALC888 variants */ -static void alc888_coef_init(struct hda_codec *codec) -{ - unsigned int tmp; - - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0); - tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); - if ((tmp & 0xf0) == 0x20) - /* alc888S-VC */ - snd_hda_codec_read(codec, 0x20, 0, - AC_VERB_SET_PROC_COEF, 0x830); - else - /* alc888-VB */ - snd_hda_codec_read(codec, 0x20, 0, - AC_VERB_SET_PROC_COEF, 0x3030); -} - -/* additional initialization for ALC889 variants */ -static void alc889_coef_init(struct hda_codec *codec) -{ - unsigned int tmp; - - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); - tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010); -} - -/* turn on/off EAPD control (only if available) */ -static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on) -{ - if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) - return; - if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, - on ? 2 : 0); -} - -/* turn on/off EAPD controls of the codec */ -static void alc_auto_setup_eapd(struct hda_codec *codec, bool on) -{ - /* We currently only handle front, HP */ - static hda_nid_t pins[] = { - 0x0f, 0x10, 0x14, 0x15, 0 - }; - hda_nid_t *p; - for (p = pins; *p; p++) - set_eapd(codec, *p, on); -} - -/* generic shutup callback; - * just turning off EPAD and a little pause for avoiding pop-noise - */ -static void alc_eapd_shutup(struct hda_codec *codec) -{ - alc_auto_setup_eapd(codec, false); - msleep(200); -} - -/* generic EAPD initialization */ -static void alc_auto_init_amp(struct hda_codec *codec, int type) -{ - unsigned int tmp; - - alc_auto_setup_eapd(codec, true); - switch (type) { - case ALC_INIT_GPIO1: - snd_hda_sequence_write(codec, alc_gpio1_init_verbs); - break; - case ALC_INIT_GPIO2: - snd_hda_sequence_write(codec, alc_gpio2_init_verbs); - break; - case ALC_INIT_GPIO3: - snd_hda_sequence_write(codec, alc_gpio3_init_verbs); - break; - case ALC_INIT_DEFAULT: - switch (codec->vendor_id) { - case 0x10ec0260: - snd_hda_codec_write(codec, 0x1a, 0, - AC_VERB_SET_COEF_INDEX, 7); - tmp = snd_hda_codec_read(codec, 0x1a, 0, - AC_VERB_GET_PROC_COEF, 0); - snd_hda_codec_write(codec, 0x1a, 0, - AC_VERB_SET_COEF_INDEX, 7); - snd_hda_codec_write(codec, 0x1a, 0, - AC_VERB_SET_PROC_COEF, - tmp | 0x2010); - break; - case 0x10ec0262: - case 0x10ec0880: - case 0x10ec0882: - case 0x10ec0883: - case 0x10ec0885: - case 0x10ec0887: - /*case 0x10ec0889:*/ /* this causes an SPDIF problem */ - alc889_coef_init(codec); - break; - case 0x10ec0888: - alc888_coef_init(codec); - break; -#if 0 /* XXX: This may cause the silent output on speaker on some machines */ - case 0x10ec0267: - case 0x10ec0268: - snd_hda_codec_write(codec, 0x20, 0, - AC_VERB_SET_COEF_INDEX, 7); - tmp = snd_hda_codec_read(codec, 0x20, 0, - AC_VERB_GET_PROC_COEF, 0); - snd_hda_codec_write(codec, 0x20, 0, - AC_VERB_SET_COEF_INDEX, 7); - snd_hda_codec_write(codec, 0x20, 0, - AC_VERB_SET_PROC_COEF, - tmp | 0x3000); - break; -#endif /* XXX */ - } - break; - } -} - -/* - * Auto-Mute mode mixer enum support - */ -static int alc_automute_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - static const char * const texts2[] = { - "Disabled", "Enabled" - }; - static const char * const texts3[] = { - "Disabled", "Speaker Only", "Line Out+Speaker" - }; - const char * const *texts; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - if (spec->automute_speaker_possible && spec->automute_lo_possible) { - uinfo->value.enumerated.items = 3; - texts = texts3; - } else { - uinfo->value.enumerated.items = 2; - texts = texts2; - } - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int alc_automute_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - unsigned int val = 0; - if (spec->automute_speaker) - val++; - if (spec->automute_lo) - val++; - - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -static int alc_automute_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - - switch (ucontrol->value.enumerated.item[0]) { - case 0: - if (!spec->automute_speaker && !spec->automute_lo) - return 0; - spec->automute_speaker = 0; - spec->automute_lo = 0; - break; - case 1: - if (spec->automute_speaker_possible) { - if (!spec->automute_lo && spec->automute_speaker) - return 0; - spec->automute_speaker = 1; - spec->automute_lo = 0; - } else if (spec->automute_lo_possible) { - if (spec->automute_lo) - return 0; - spec->automute_lo = 1; - } else - return -EINVAL; - break; - case 2: - if (!spec->automute_lo_possible || !spec->automute_speaker_possible) - return -EINVAL; - if (spec->automute_speaker && spec->automute_lo) - return 0; - spec->automute_speaker = 1; - spec->automute_lo = 1; - break; - default: - return -EINVAL; - } - call_update_outputs(codec); - return 1; -} - -static const struct snd_kcontrol_new alc_automute_mode_enum = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Auto-Mute Mode", - .info = alc_automute_mode_info, - .get = alc_automute_mode_get, - .put = alc_automute_mode_put, -}; - -static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec) -{ - snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); - return snd_array_new(&spec->kctls); -} - -static int alc_add_automute_mode_enum(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct snd_kcontrol_new *knew; - - knew = alc_kcontrol_new(spec); - if (!knew) - return -ENOMEM; - *knew = alc_automute_mode_enum; - knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL); - if (!knew->name) - return -ENOMEM; - return 0; -} - -/* - * Check the availability of HP/line-out auto-mute; - * Set up appropriately if really supported - */ -static void alc_init_automute(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int present = 0; - int i; - - if (cfg->hp_pins[0]) - present++; - if (cfg->line_out_pins[0]) - present++; - if (cfg->speaker_pins[0]) - present++; - if (present < 2) /* need two different output types */ - return; - - if (!cfg->speaker_pins[0] && - cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { - memcpy(cfg->speaker_pins, cfg->line_out_pins, - sizeof(cfg->speaker_pins)); - cfg->speaker_outs = cfg->line_outs; - } - - if (!cfg->hp_pins[0] && - cfg->line_out_type == AUTO_PIN_HP_OUT) { - memcpy(cfg->hp_pins, cfg->line_out_pins, - sizeof(cfg->hp_pins)); - cfg->hp_outs = cfg->line_outs; - } - - spec->automute_mode = ALC_AUTOMUTE_PIN; - - for (i = 0; i < cfg->hp_outs; i++) { - hda_nid_t nid = cfg->hp_pins[i]; - if (!is_jack_detectable(codec, nid)) - continue; - snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", - nid); - snd_hda_jack_detect_enable(codec, nid, ALC_HP_EVENT); - spec->detect_hp = 1; - } - - if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) { - if (cfg->speaker_outs) - for (i = 0; i < cfg->line_outs; i++) { - hda_nid_t nid = cfg->line_out_pins[i]; - if (!is_jack_detectable(codec, nid)) - continue; - snd_printdd("realtek: Enable Line-Out " - "auto-muting on NID 0x%x\n", nid); - snd_hda_jack_detect_enable(codec, nid, - ALC_FRONT_EVENT); - spec->detect_lo = 1; - } - spec->automute_lo_possible = spec->detect_hp; - } - - spec->automute_speaker_possible = cfg->speaker_outs && - (spec->detect_hp || spec->detect_lo); - - spec->automute_lo = spec->automute_lo_possible; - spec->automute_speaker = spec->automute_speaker_possible; - - if (spec->automute_speaker_possible || spec->automute_lo_possible) { - /* create a control for automute mode */ - alc_add_automute_mode_enum(codec); - spec->unsol_event = alc_sku_unsol_event; - } -} - -/* return the position of NID in the list, or -1 if not found */ -static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) -{ - int i; - for (i = 0; i < nums; i++) - if (list[i] == nid) - return i; - return -1; -} - -/* check whether dynamic ADC-switching is available */ -static bool alc_check_dyn_adc_switch(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct hda_input_mux *imux = &spec->private_imux[0]; - int i, n, idx; - hda_nid_t cap, pin; - - if (imux != spec->input_mux) /* no dynamic imux? */ - return false; - - for (n = 0; n < spec->num_adc_nids; n++) { - cap = spec->private_capsrc_nids[n]; - for (i = 0; i < imux->num_items; i++) { - pin = spec->imux_pins[i]; - if (!pin) - return false; - if (get_connection_index(codec, cap, pin) < 0) - break; - } - if (i >= imux->num_items) - return true; /* no ADC-switch is needed */ - } - - for (i = 0; i < imux->num_items; i++) { - pin = spec->imux_pins[i]; - for (n = 0; n < spec->num_adc_nids; n++) { - cap = spec->private_capsrc_nids[n]; - idx = get_connection_index(codec, cap, pin); - if (idx >= 0) { - imux->items[i].index = idx; - spec->dyn_adc_idx[i] = n; - break; - } - } - } - - snd_printdd("realtek: enabling ADC switching\n"); - spec->dyn_adc_switch = 1; - return true; -} - -/* check whether all auto-mic pins are valid; setup indices if OK */ -static bool alc_auto_mic_check_imux(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - const struct hda_input_mux *imux; - - if (!spec->auto_mic) - return false; - if (spec->auto_mic_valid_imux) - return true; /* already checked */ - - /* fill up imux indices */ - if (!alc_check_dyn_adc_switch(codec)) { - spec->auto_mic = 0; - return false; - } - - imux = spec->input_mux; - spec->ext_mic_idx = find_idx_in_nid_list(spec->ext_mic_pin, - spec->imux_pins, imux->num_items); - spec->int_mic_idx = find_idx_in_nid_list(spec->int_mic_pin, - spec->imux_pins, imux->num_items); - spec->dock_mic_idx = find_idx_in_nid_list(spec->dock_mic_pin, - spec->imux_pins, imux->num_items); - if (spec->ext_mic_idx < 0 || spec->int_mic_idx < 0) { - spec->auto_mic = 0; - return false; /* no corresponding imux */ - } - - snd_hda_jack_detect_enable(codec, spec->ext_mic_pin, ALC_MIC_EVENT); - if (spec->dock_mic_pin) - snd_hda_jack_detect_enable(codec, spec->dock_mic_pin, - ALC_MIC_EVENT); - - spec->auto_mic_valid_imux = 1; - spec->auto_mic = 1; - return true; -} - -/* - * Check the availability of auto-mic switch; - * Set up if really supported - */ -static void alc_init_auto_mic(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t fixed, ext, dock; - int i; - - if (spec->shared_mic_hp) - return; /* no auto-mic for the shared I/O */ - - spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1; - - fixed = ext = dock = 0; - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; - unsigned int defcfg; - defcfg = snd_hda_codec_get_pincfg(codec, nid); - switch (snd_hda_get_input_pin_attr(defcfg)) { - case INPUT_PIN_ATTR_INT: - if (fixed) - return; /* already occupied */ - if (cfg->inputs[i].type != AUTO_PIN_MIC) - return; /* invalid type */ - fixed = nid; - break; - case INPUT_PIN_ATTR_UNUSED: - return; /* invalid entry */ - case INPUT_PIN_ATTR_DOCK: - if (dock) - return; /* already occupied */ - if (cfg->inputs[i].type > AUTO_PIN_LINE_IN) - return; /* invalid type */ - dock = nid; - break; - default: - if (ext) - return; /* already occupied */ - if (cfg->inputs[i].type != AUTO_PIN_MIC) - return; /* invalid type */ - ext = nid; - break; - } - } - if (!ext && dock) { - ext = dock; - dock = 0; - } - if (!ext || !fixed) - return; - if (!is_jack_detectable(codec, ext)) - return; /* no unsol support */ - if (dock && !is_jack_detectable(codec, dock)) - return; /* no unsol support */ - - /* check imux indices */ - spec->ext_mic_pin = ext; - spec->int_mic_pin = fixed; - spec->dock_mic_pin = dock; - - spec->auto_mic = 1; - if (!alc_auto_mic_check_imux(codec)) - return; - - snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n", - ext, fixed, dock); - spec->unsol_event = alc_sku_unsol_event; -} - -/* check the availabilities of auto-mute and auto-mic switches */ -static void alc_auto_check_switches(struct hda_codec *codec) -{ - alc_init_automute(codec); - alc_init_auto_mic(codec); -} - -/* - * Realtek SSID verification - */ - -/* Could be any non-zero and even value. When used as fixup, tells - * the driver to ignore any present sku defines. - */ -#define ALC_FIXUP_SKU_IGNORE (2) - -static int alc_auto_parse_customize_define(struct hda_codec *codec) -{ - unsigned int ass, tmp, i; - unsigned nid = 0; - struct alc_spec *spec = codec->spec; - - spec->cdefine.enable_pcbeep = 1; /* assume always enabled */ - - if (spec->cdefine.fixup) { - ass = spec->cdefine.sku_cfg; - if (ass == ALC_FIXUP_SKU_IGNORE) - return -1; - goto do_sku; - } - - ass = codec->subsystem_id & 0xffff; - if (ass != codec->bus->pci->subsystem_device && (ass & 1)) - goto do_sku; - - nid = 0x1d; - if (codec->vendor_id == 0x10ec0260) - nid = 0x17; - ass = snd_hda_codec_get_pincfg(codec, nid); - - if (!(ass & 1)) { - printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n", - codec->chip_name, ass); - return -1; - } - - /* check sum */ - tmp = 0; - for (i = 1; i < 16; i++) { - if ((ass >> i) & 1) - tmp++; - } - if (((ass >> 16) & 0xf) != tmp) - return -1; - - spec->cdefine.port_connectivity = ass >> 30; - spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20; - spec->cdefine.check_sum = (ass >> 16) & 0xf; - spec->cdefine.customization = ass >> 8; -do_sku: - spec->cdefine.sku_cfg = ass; - spec->cdefine.external_amp = (ass & 0x38) >> 3; - spec->cdefine.platform_type = (ass & 0x4) >> 2; - spec->cdefine.swap = (ass & 0x2) >> 1; - spec->cdefine.override = ass & 0x1; - - snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n", - nid, spec->cdefine.sku_cfg); - snd_printd("SKU: port_connectivity=0x%x\n", - spec->cdefine.port_connectivity); - snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep); - snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum); - snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization); - snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp); - snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type); - snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap); - snd_printd("SKU: override=0x%x\n", spec->cdefine.override); - - return 0; -} - -/* return true if the given NID is found in the list */ -static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) -{ - return find_idx_in_nid_list(nid, list, nums) >= 0; -} - -/* check subsystem ID and set up device-specific initialization; - * return 1 if initialized, 0 if invalid SSID - */ -/* 32-bit subsystem ID for BIOS loading in HD Audio codec. - * 31 ~ 16 : Manufacture ID - * 15 ~ 8 : SKU ID - * 7 ~ 0 : Assembly ID - * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36 - */ -static int alc_subsystem_id(struct hda_codec *codec, - hda_nid_t porta, hda_nid_t porte, - hda_nid_t portd, hda_nid_t porti) -{ - unsigned int ass, tmp, i; - unsigned nid; - struct alc_spec *spec = codec->spec; - - if (spec->cdefine.fixup) { - ass = spec->cdefine.sku_cfg; - if (ass == ALC_FIXUP_SKU_IGNORE) - return 0; - goto do_sku; - } - - ass = codec->subsystem_id & 0xffff; - if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) - goto do_sku; - - /* invalid SSID, check the special NID pin defcfg instead */ - /* - * 31~30 : port connectivity - * 29~21 : reserve - * 20 : PCBEEP input - * 19~16 : Check sum (15:1) - * 15~1 : Custom - * 0 : override - */ - nid = 0x1d; - if (codec->vendor_id == 0x10ec0260) - nid = 0x17; - ass = snd_hda_codec_get_pincfg(codec, nid); - snd_printd("realtek: No valid SSID, " - "checking pincfg 0x%08x for NID 0x%x\n", - ass, nid); - if (!(ass & 1)) - return 0; - if ((ass >> 30) != 1) /* no physical connection */ - return 0; - - /* check sum */ - tmp = 0; - for (i = 1; i < 16; i++) { - if ((ass >> i) & 1) - tmp++; - } - if (((ass >> 16) & 0xf) != tmp) - return 0; -do_sku: - snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n", - ass & 0xffff, codec->vendor_id); - /* - * 0 : override - * 1 : Swap Jack - * 2 : 0 --> Desktop, 1 --> Laptop - * 3~5 : External Amplifier control - * 7~6 : Reserved - */ - tmp = (ass & 0x38) >> 3; /* external Amp control */ - switch (tmp) { - case 1: - spec->init_amp = ALC_INIT_GPIO1; - break; - case 3: - spec->init_amp = ALC_INIT_GPIO2; - break; - case 7: - spec->init_amp = ALC_INIT_GPIO3; - break; - case 5: - default: - spec->init_amp = ALC_INIT_DEFAULT; - break; - } - - /* is laptop or Desktop and enable the function "Mute internal speaker - * when the external headphone out jack is plugged" - */ - if (!(ass & 0x8000)) - return 1; - /* - * 10~8 : Jack location - * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered - * 14~13: Resvered - * 15 : 1 --> enable the function "Mute internal speaker - * when the external headphone out jack is plugged" - */ - if (!spec->autocfg.hp_pins[0] && - !(spec->autocfg.line_out_pins[0] && - spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)) { - hda_nid_t nid; - tmp = (ass >> 11) & 0x3; /* HP to chassis */ - if (tmp == 0) - nid = porta; - else if (tmp == 1) - nid = porte; - else if (tmp == 2) - nid = portd; - else if (tmp == 3) - nid = porti; - else - return 1; - if (found_in_nid_list(nid, spec->autocfg.line_out_pins, - spec->autocfg.line_outs)) - return 1; - spec->autocfg.hp_pins[0] = nid; - } - return 1; -} - -/* Check the validity of ALC subsystem-id - * ports contains an array of 4 pin NIDs for port-A, E, D and I */ -static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports) -{ - if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) { - struct alc_spec *spec = codec->spec; - snd_printd("realtek: " - "Enable default setup for auto mode as fallback\n"); - spec->init_amp = ALC_INIT_DEFAULT; - } -} - -/* - * Fix-up pin default configurations and add default verbs - */ - -struct alc_pincfg { - hda_nid_t nid; - u32 val; -}; - -struct alc_model_fixup { - const int id; - const char *name; -}; - -struct alc_fixup { - int type; - bool chained; - int chain_id; - union { - unsigned int sku; - const struct alc_pincfg *pins; - const struct hda_verb *verbs; - void (*func)(struct hda_codec *codec, - const struct alc_fixup *fix, - int action); - } v; -}; - -enum { - ALC_FIXUP_INVALID, - ALC_FIXUP_SKU, - ALC_FIXUP_PINS, - ALC_FIXUP_VERBS, - ALC_FIXUP_FUNC, -}; - -enum { - ALC_FIXUP_ACT_PRE_PROBE, - ALC_FIXUP_ACT_PROBE, - ALC_FIXUP_ACT_INIT, - ALC_FIXUP_ACT_BUILD, -}; - -static void alc_apply_pincfgs(struct hda_codec *codec, - const struct alc_pincfg *cfg) -{ - for (; cfg->nid; cfg++) - snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); -} - -static void alc_apply_fixup(struct hda_codec *codec, int action) -{ - struct alc_spec *spec = codec->spec; - int id = spec->fixup_id; -#ifdef CONFIG_SND_DEBUG_VERBOSE - const char *modelname = spec->fixup_name; -#endif - int depth = 0; - - if (!spec->fixup_list) - return; - - while (id >= 0) { - const struct alc_fixup *fix = spec->fixup_list + id; - const struct alc_pincfg *cfg; - - switch (fix->type) { - case ALC_FIXUP_SKU: - if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku) - break; - snd_printdd(KERN_INFO "hda_codec: %s: " - "Apply sku override for %s\n", - codec->chip_name, modelname); - spec->cdefine.sku_cfg = fix->v.sku; - spec->cdefine.fixup = 1; - break; - case ALC_FIXUP_PINS: - cfg = fix->v.pins; - if (action != ALC_FIXUP_ACT_PRE_PROBE || !cfg) - break; - snd_printdd(KERN_INFO "hda_codec: %s: " - "Apply pincfg for %s\n", - codec->chip_name, modelname); - alc_apply_pincfgs(codec, cfg); - break; - case ALC_FIXUP_VERBS: - if (action != ALC_FIXUP_ACT_PROBE || !fix->v.verbs) - break; - snd_printdd(KERN_INFO "hda_codec: %s: " - "Apply fix-verbs for %s\n", - codec->chip_name, modelname); - add_verb(codec->spec, fix->v.verbs); - break; - case ALC_FIXUP_FUNC: - if (!fix->v.func) - break; - snd_printdd(KERN_INFO "hda_codec: %s: " - "Apply fix-func for %s\n", - codec->chip_name, modelname); - fix->v.func(codec, fix, action); - break; - default: - snd_printk(KERN_ERR "hda_codec: %s: " - "Invalid fixup type %d\n", - codec->chip_name, fix->type); - break; - } - if (!fix->chained) - break; - if (++depth > 10) - break; - id = fix->chain_id; - } -} - -static void alc_pick_fixup(struct hda_codec *codec, - const struct alc_model_fixup *models, - const struct snd_pci_quirk *quirk, - const struct alc_fixup *fixlist) -{ - struct alc_spec *spec = codec->spec; - const struct snd_pci_quirk *q; - int id = -1; - const char *name = NULL; - - /* when model=nofixup is given, don't pick up any fixups */ - if (codec->modelname && !strcmp(codec->modelname, "nofixup")) { - spec->fixup_list = NULL; - spec->fixup_id = -1; - return; - } - - if (codec->modelname && models) { - while (models->name) { - if (!strcmp(codec->modelname, models->name)) { - id = models->id; - name = models->name; - break; - } - models++; - } - } - if (id < 0) { - q = snd_pci_quirk_lookup(codec->bus->pci, quirk); - if (q) { - id = q->value; -#ifdef CONFIG_SND_DEBUG_VERBOSE - name = q->name; -#endif - } - } - if (id < 0) { - for (q = quirk; q->subvendor; q++) { - unsigned int vendorid = - q->subdevice | (q->subvendor << 16); - if (vendorid == codec->subsystem_id) { - id = q->value; -#ifdef CONFIG_SND_DEBUG_VERBOSE - name = q->name; -#endif - break; - } - } - } - - spec->fixup_id = id; - if (id >= 0) { - spec->fixup_list = fixlist; - spec->fixup_name = name; - } -} - -/* - * COEF access helper functions - */ -static int alc_read_coef_idx(struct hda_codec *codec, - unsigned int coef_idx) -{ - unsigned int val; - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, - coef_idx); - val = snd_hda_codec_read(codec, 0x20, 0, - AC_VERB_GET_PROC_COEF, 0); - return val; -} - -static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx, - unsigned int coef_val) -{ - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, - coef_idx); - snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, - coef_val); -} - -/* a special bypass for COEF 0; read the cached value at the second time */ -static unsigned int alc_get_coef0(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - if (!spec->coef0) - spec->coef0 = alc_read_coef_idx(codec, 0); - return spec->coef0; -} - -/* - * Digital I/O handling - */ - -/* set right pin controls for digital I/O */ -static void alc_auto_init_digital(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int i; - hda_nid_t pin, dac; - - for (i = 0; i < spec->autocfg.dig_outs; i++) { - pin = spec->autocfg.dig_out_pins[i]; - if (!pin) - continue; - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); - if (!i) - dac = spec->multiout.dig_out_nid; - else - dac = spec->slave_dig_outs[i - 1]; - if (!dac || !(get_wcaps(codec, dac) & AC_WCAP_OUT_AMP)) - continue; - snd_hda_codec_write(codec, dac, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); - } - pin = spec->autocfg.dig_in_pin; - if (pin) - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_IN); -} - -/* parse digital I/Os and set up NIDs in BIOS auto-parse mode */ -static void alc_auto_parse_digital(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int i, err, nums; - hda_nid_t dig_nid; - - /* support multiple SPDIFs; the secondary is set up as a slave */ - nums = 0; - for (i = 0; i < spec->autocfg.dig_outs; i++) { - hda_nid_t conn[4]; - err = snd_hda_get_connections(codec, - spec->autocfg.dig_out_pins[i], - conn, ARRAY_SIZE(conn)); - if (err <= 0) - continue; - dig_nid = conn[0]; /* assume the first element is audio-out */ - if (!nums) { - spec->multiout.dig_out_nid = dig_nid; - spec->dig_out_type = spec->autocfg.dig_out_type[0]; - } else { - spec->multiout.slave_dig_outs = spec->slave_dig_outs; - if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1) - break; - spec->slave_dig_outs[nums - 1] = dig_nid; - } - nums++; - } - - if (spec->autocfg.dig_in_pin) { - dig_nid = codec->start_nid; - for (i = 0; i < codec->num_nodes; i++, dig_nid++) { - unsigned int wcaps = get_wcaps(codec, dig_nid); - if (get_wcaps_type(wcaps) != AC_WID_AUD_IN) - continue; - if (!(wcaps & AC_WCAP_DIGITAL)) - continue; - if (!(wcaps & AC_WCAP_CONN_LIST)) - continue; - err = get_connection_index(codec, dig_nid, - spec->autocfg.dig_in_pin); - if (err >= 0) { - spec->dig_in_nid = dig_nid; - break; - } - } - } -} - -/* - * capture mixer elements - */ -static int alc_cap_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - unsigned long val; - int err; - - mutex_lock(&codec->control_mutex); - if (spec->vol_in_capsrc) - val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT); - else - val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT); - kcontrol->private_value = val; - err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); - mutex_unlock(&codec->control_mutex); - return err; -} - -static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - unsigned long val; - int err; - - mutex_lock(&codec->control_mutex); - if (spec->vol_in_capsrc) - val = HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[0], 3, 0, HDA_OUTPUT); - else - val = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0, HDA_INPUT); - kcontrol->private_value = val; - err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); - mutex_unlock(&codec->control_mutex); - return err; -} - -typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - -static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol, - getput_call_t func, bool check_adc_switch) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - int i, err = 0; - - mutex_lock(&codec->control_mutex); - if (check_adc_switch && spec->dyn_adc_switch) { - for (i = 0; i < spec->num_adc_nids; i++) { - kcontrol->private_value = - HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], - 3, 0, HDA_INPUT); - err = func(kcontrol, ucontrol); - if (err < 0) - goto error; - } - } else { - i = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - if (spec->vol_in_capsrc) - kcontrol->private_value = - HDA_COMPOSE_AMP_VAL(spec->capsrc_nids[i], - 3, 0, HDA_OUTPUT); - else - kcontrol->private_value = - HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], - 3, 0, HDA_INPUT); - err = func(kcontrol, ucontrol); - } - error: - mutex_unlock(&codec->control_mutex); - return err; -} - -static int alc_cap_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return alc_cap_getput_caller(kcontrol, ucontrol, - snd_hda_mixer_amp_volume_get, false); -} - -static int alc_cap_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return alc_cap_getput_caller(kcontrol, ucontrol, - snd_hda_mixer_amp_volume_put, true); -} - -/* capture mixer elements */ -#define alc_cap_sw_info snd_ctl_boolean_stereo_info - -static int alc_cap_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return alc_cap_getput_caller(kcontrol, ucontrol, - snd_hda_mixer_amp_switch_get, false); -} - -static int alc_cap_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return alc_cap_getput_caller(kcontrol, ucontrol, - snd_hda_mixer_amp_switch_put, true); -} - -#define _DEFINE_CAPMIX(num) \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Capture Switch", \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .count = num, \ - .info = alc_cap_sw_info, \ - .get = alc_cap_sw_get, \ - .put = alc_cap_sw_put, \ - }, \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Capture Volume", \ - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \ - .count = num, \ - .info = alc_cap_vol_info, \ - .get = alc_cap_vol_get, \ - .put = alc_cap_vol_put, \ - .tlv = { .c = alc_cap_vol_tlv }, \ - } - -#define _DEFINE_CAPSRC(num) \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - /* .name = "Capture Source", */ \ - .name = "Input Source", \ - .count = num, \ - .info = alc_mux_enum_info, \ - .get = alc_mux_enum_get, \ - .put = alc_mux_enum_put, \ - } - -#define DEFINE_CAPMIX(num) \ -static const struct snd_kcontrol_new alc_capture_mixer ## num[] = { \ - _DEFINE_CAPMIX(num), \ - _DEFINE_CAPSRC(num), \ - { } /* end */ \ -} - -#define DEFINE_CAPMIX_NOSRC(num) \ -static const struct snd_kcontrol_new alc_capture_mixer_nosrc ## num[] = { \ - _DEFINE_CAPMIX(num), \ - { } /* end */ \ -} - -/* up to three ADCs */ -DEFINE_CAPMIX(1); -DEFINE_CAPMIX(2); -DEFINE_CAPMIX(3); -DEFINE_CAPMIX_NOSRC(1); -DEFINE_CAPMIX_NOSRC(2); -DEFINE_CAPMIX_NOSRC(3); - -/* - * virtual master controls - */ - -/* - * slave controls for virtual master - */ -static const char * const alc_slave_pfxs[] = { - "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Speaker", "Mono", "Line Out", - "CLFE", "Bass Speaker", "PCM", - NULL, -}; - -/* - * build control elements - */ - -#define NID_MAPPING (-1) - -#define SUBDEV_SPEAKER_ (0 << 6) -#define SUBDEV_HP_ (1 << 6) -#define SUBDEV_LINE_ (2 << 6) -#define SUBDEV_SPEAKER(x) (SUBDEV_SPEAKER_ | ((x) & 0x3f)) -#define SUBDEV_HP(x) (SUBDEV_HP_ | ((x) & 0x3f)) -#define SUBDEV_LINE(x) (SUBDEV_LINE_ | ((x) & 0x3f)) - -static void alc_free_kctls(struct hda_codec *codec); - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -/* additional beep mixers; the actual parameters are overwritten at build */ -static const struct snd_kcontrol_new alc_beep_mixer[] = { - HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), - HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT), - { } /* end */ -}; -#endif - -static int __alc_build_controls(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct snd_kcontrol *kctl = NULL; - const struct snd_kcontrol_new *knew; - int i, j, err; - unsigned int u; - hda_nid_t nid; - - for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - if (spec->cap_mixer) { - err = snd_hda_add_new_ctls(codec, spec->cap_mixer); - if (err < 0) - return err; - } - if (spec->multiout.dig_out_nid) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - if (!spec->no_analog) { - err = snd_hda_create_spdif_share_sw(codec, - &spec->multiout); - if (err < 0) - return err; - spec->multiout.share_spdif = 1; - } - } - if (spec->dig_in_nid) { - err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); - if (err < 0) - return err; - } - -#ifdef CONFIG_SND_HDA_INPUT_BEEP - /* create beep controls if needed */ - if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - for (knew = alc_beep_mixer; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } - } -#endif - - /* if we have no master control, let's create it */ - if (!spec->no_analog && - !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { - unsigned int vmaster_tlv[4]; - snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, - HDA_OUTPUT, vmaster_tlv); - err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, alc_slave_pfxs, - "Playback Volume"); - if (err < 0) - return err; - } - if (!spec->no_analog && - !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { - err = __snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, alc_slave_pfxs, - "Playback Switch", - true, &spec->vmaster_mute.sw_kctl); - if (err < 0) - return err; - } - - /* assign Capture Source enums to NID */ - if (spec->capsrc_nids || spec->adc_nids) { - kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); - if (!kctl) - kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); - for (i = 0; kctl && i < kctl->count; i++) { - err = snd_hda_add_nid(codec, kctl, i, - get_capsrc(spec, i)); - if (err < 0) - return err; - } - } - if (spec->cap_mixer && spec->adc_nids) { - const char *kname = kctl ? kctl->id.name : NULL; - for (knew = spec->cap_mixer; knew->name; knew++) { - if (kname && strcmp(knew->name, kname) == 0) - continue; - kctl = snd_hda_find_mixer_ctl(codec, knew->name); - for (i = 0; kctl && i < kctl->count; i++) { - err = snd_hda_add_nid(codec, kctl, i, - spec->adc_nids[i]); - if (err < 0) - return err; - } - } - } - - /* other nid->control mapping */ - for (i = 0; i < spec->num_mixers; i++) { - for (knew = spec->mixers[i]; knew->name; knew++) { - if (knew->iface != NID_MAPPING) - continue; - kctl = snd_hda_find_mixer_ctl(codec, knew->name); - if (kctl == NULL) - continue; - u = knew->subdevice; - for (j = 0; j < 4; j++, u >>= 8) { - nid = u & 0x3f; - if (nid == 0) - continue; - switch (u & 0xc0) { - case SUBDEV_SPEAKER_: - nid = spec->autocfg.speaker_pins[nid]; - break; - case SUBDEV_LINE_: - nid = spec->autocfg.line_out_pins[nid]; - break; - case SUBDEV_HP_: - nid = spec->autocfg.hp_pins[nid]; - break; - default: - continue; - } - err = snd_hda_add_nid(codec, kctl, 0, nid); - if (err < 0) - return err; - } - u = knew->private_value; - for (j = 0; j < 4; j++, u >>= 8) { - nid = u & 0xff; - if (nid == 0) - continue; - err = snd_hda_add_nid(codec, kctl, 0, nid); - if (err < 0) - return err; - } - } - } - - alc_free_kctls(codec); /* no longer needed */ - - return 0; -} - -static int alc_build_controls(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int err = __alc_build_controls(codec); - if (err < 0) - return err; - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); - if (err < 0) - return err; - alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); - return 0; -} - - -/* - * Common callbacks - */ - -static void alc_init_special_input_src(struct hda_codec *codec); -static void alc_auto_init_std(struct hda_codec *codec); - -static int alc_init(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - unsigned int i; - - if (spec->init_hook) - spec->init_hook(codec); - - alc_fix_pll(codec); - alc_auto_init_amp(codec, spec->init_amp); - - for (i = 0; i < spec->num_init_verbs; i++) - snd_hda_sequence_write(codec, spec->init_verbs[i]); - alc_init_special_input_src(codec); - alc_auto_init_std(codec); - - alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); - - snd_hda_jack_report_sync(codec); - - hda_call_check_power_status(codec, 0x01); - return 0; -} - -static void alc_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct alc_spec *spec = codec->spec; - - if (spec->unsol_event) - spec->unsol_event(codec, res); -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) -{ - struct alc_spec *spec = codec->spec; - return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); -} -#endif - -/* - * Analog playback callbacks - */ -static int alc_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); -} - -static int alc_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, - stream_tag, format, substream); -} - -static int alc_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -/* - * Digital out - */ -static int alc_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int alc_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, - stream_tag, format, substream); -} - -static int alc_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); -} - -static int alc_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -/* - * Analog capture - */ -static int alc_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - - snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1], - stream_tag, 0, format); - return 0; -} - -static int alc_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - - snd_hda_codec_cleanup_stream(codec, - spec->adc_nids[substream->number + 1]); - return 0; -} - -/* analog capture with dynamic dual-adc changes */ -static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]]; - spec->cur_adc_stream_tag = stream_tag; - spec->cur_adc_format = format; - snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); - return 0; -} - -static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct alc_spec *spec = codec->spec; - snd_hda_codec_cleanup_stream(codec, spec->cur_adc); - spec->cur_adc = 0; - return 0; -} - -static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0, /* fill later */ - .ops = { - .prepare = dyn_adc_capture_pcm_prepare, - .cleanup = dyn_adc_capture_pcm_cleanup - }, -}; - -/* - */ -static const struct hda_pcm_stream alc_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 8, - /* NID is set in alc_build_pcms */ - .ops = { - .open = alc_playback_pcm_open, - .prepare = alc_playback_pcm_prepare, - .cleanup = alc_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream alc_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in alc_build_pcms */ -}; - -static const struct hda_pcm_stream alc_pcm_analog_alt_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in alc_build_pcms */ -}; - -static const struct hda_pcm_stream alc_pcm_analog_alt_capture = { - .substreams = 2, /* can be overridden */ - .channels_min = 2, - .channels_max = 2, - /* NID is set in alc_build_pcms */ - .ops = { - .prepare = alc_alt_capture_pcm_prepare, - .cleanup = alc_alt_capture_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream alc_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in alc_build_pcms */ - .ops = { - .open = alc_dig_playback_pcm_open, - .close = alc_dig_playback_pcm_close, - .prepare = alc_dig_playback_pcm_prepare, - .cleanup = alc_dig_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream alc_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in alc_build_pcms */ -}; - -/* Used by alc_build_pcms to flag that a PCM has no playback stream */ -static const struct hda_pcm_stream alc_pcm_null_stream = { - .substreams = 0, - .channels_min = 0, - .channels_max = 0, -}; - -static int alc_build_pcms(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - const struct hda_pcm_stream *p; - bool have_multi_adcs; - int i; - - codec->num_pcms = 1; - codec->pcm_info = info; - - if (spec->no_analog) - goto skip_analog; - - snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog), - "%s Analog", codec->chip_name); - info->name = spec->stream_name_analog; - - if (spec->multiout.num_dacs > 0) { - p = spec->stream_analog_playback; - if (!p) - p = &alc_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; - } - if (spec->adc_nids) { - p = spec->stream_analog_capture; - if (!p) { - if (spec->dyn_adc_switch) - p = &dyn_adc_pcm_analog_capture; - else - p = &alc_pcm_analog_capture; - } - info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; - } - - if (spec->channel_mode) { - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; - for (i = 0; i < spec->num_channel_mode; i++) { - if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) { - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels; - } - } - } - - skip_analog: - /* SPDIF for stream index #1 */ - if (spec->multiout.dig_out_nid || spec->dig_in_nid) { - snprintf(spec->stream_name_digital, - sizeof(spec->stream_name_digital), - "%s Digital", codec->chip_name); - codec->num_pcms = 2; - codec->slave_dig_outs = spec->multiout.slave_dig_outs; - info = spec->pcm_rec + 1; - info->name = spec->stream_name_digital; - if (spec->dig_out_type) - info->pcm_type = spec->dig_out_type; - else - info->pcm_type = HDA_PCM_TYPE_SPDIF; - if (spec->multiout.dig_out_nid) { - p = spec->stream_digital_playback; - if (!p) - p = &alc_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; - } - if (spec->dig_in_nid) { - p = spec->stream_digital_capture; - if (!p) - p = &alc_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; - } - /* FIXME: do we need this for all Realtek codec models? */ - codec->spdif_status_reset = 1; - } - - if (spec->no_analog) - return 0; - - /* If the use of more than one ADC is requested for the current - * model, configure a second analog capture-only PCM. - */ - have_multi_adcs = (spec->num_adc_nids > 1) && - !spec->dyn_adc_switch && !spec->auto_mic && - (!spec->input_mux || spec->input_mux->num_items > 1); - /* Additional Analaog capture for index #2 */ - if (spec->alt_dac_nid || have_multi_adcs) { - codec->num_pcms = 3; - info = spec->pcm_rec + 2; - info->name = spec->stream_name_analog; - if (spec->alt_dac_nid) { - p = spec->stream_analog_alt_playback; - if (!p) - p = &alc_pcm_analog_alt_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->alt_dac_nid; - } else { - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = - alc_pcm_null_stream; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; - } - if (have_multi_adcs) { - p = spec->stream_analog_alt_capture; - if (!p) - p = &alc_pcm_analog_alt_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = - spec->adc_nids[1]; - info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = - spec->num_adc_nids - 1; - } else { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - alc_pcm_null_stream; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0; - } - } - - return 0; -} - -static inline void alc_shutup(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - if (spec && spec->shutup) - spec->shutup(codec); - snd_hda_shutup_pins(codec); -} - -static void alc_free_kctls(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - if (spec->kctls.list) { - struct snd_kcontrol_new *kctl = spec->kctls.list; - int i; - for (i = 0; i < spec->kctls.used; i++) - kfree(kctl[i].name); - } - snd_array_free(&spec->kctls); -} - -static void alc_free_bind_ctls(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - if (spec->bind_ctls.list) { - struct hda_bind_ctls **ctl = spec->bind_ctls.list; - int i; - for (i = 0; i < spec->bind_ctls.used; i++) - kfree(ctl[i]); - } - snd_array_free(&spec->bind_ctls); -} - -static void alc_free(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - if (!spec) - return; - - alc_shutup(codec); - alc_free_kctls(codec); - alc_free_bind_ctls(codec); - kfree(spec); - snd_hda_detach_beep_device(codec); -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static void alc_power_eapd(struct hda_codec *codec) -{ - alc_auto_setup_eapd(codec, false); -} - -static int alc_suspend(struct hda_codec *codec, pm_message_t state) -{ - struct alc_spec *spec = codec->spec; - alc_shutup(codec); - if (spec && spec->power_hook) - spec->power_hook(codec); - return 0; -} -#endif - -#ifdef CONFIG_PM -static int alc_resume(struct hda_codec *codec) -{ - msleep(150); /* to avoid pop noise */ - codec->patch_ops.init(codec); - snd_hda_codec_resume_amp(codec); - snd_hda_codec_resume_cache(codec); - hda_call_check_power_status(codec, 0x01); - return 0; -} -#endif - -/* - */ -static const struct hda_codec_ops alc_patch_ops = { - .build_controls = alc_build_controls, - .build_pcms = alc_build_pcms, - .init = alc_init, - .free = alc_free, - .unsol_event = alc_unsol_event, -#ifdef CONFIG_PM - .resume = alc_resume, -#endif -#ifdef CONFIG_SND_HDA_POWER_SAVE - .suspend = alc_suspend, - .check_power_status = alc_check_power_status, -#endif - .reboot_notify = alc_shutup, -}; - -/* replace the codec chip_name with the given string */ -static int alc_codec_rename(struct hda_codec *codec, const char *name) -{ - kfree(codec->chip_name); - codec->chip_name = kstrdup(name, GFP_KERNEL); - if (!codec->chip_name) { - alc_free(codec); - return -ENOMEM; - } - return 0; -} - -/* - * Rename codecs appropriately from COEF value - */ -struct alc_codec_rename_table { - unsigned int vendor_id; - unsigned short coef_mask; - unsigned short coef_bits; - const char *name; -}; - -static struct alc_codec_rename_table rename_tbl[] = { - { 0x10ec0269, 0xfff0, 0x3010, "ALC277" }, - { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" }, - { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" }, - { 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" }, - { 0x10ec0269, 0xffff, 0xa023, "ALC259" }, - { 0x10ec0269, 0xffff, 0x6023, "ALC281X" }, - { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" }, - { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" }, - { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" }, - { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" }, - { 0x10ec0899, 0x2000, 0x2000, "ALC899" }, - { 0x10ec0892, 0xffff, 0x8020, "ALC661" }, - { 0x10ec0892, 0xffff, 0x8011, "ALC661" }, - { 0x10ec0892, 0xffff, 0x4011, "ALC656" }, - { } /* terminator */ -}; - -static int alc_codec_rename_from_preset(struct hda_codec *codec) -{ - const struct alc_codec_rename_table *p; - - for (p = rename_tbl; p->vendor_id; p++) { - if (p->vendor_id != codec->vendor_id) - continue; - if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits) - return alc_codec_rename(codec, p->name); - } - return 0; -} - -/* - * Automatic parse of I/O pins from the BIOS configuration - */ - -enum { - ALC_CTL_WIDGET_VOL, - ALC_CTL_WIDGET_MUTE, - ALC_CTL_BIND_MUTE, - ALC_CTL_BIND_VOL, - ALC_CTL_BIND_SW, -}; -static const struct snd_kcontrol_new alc_control_templates[] = { - HDA_CODEC_VOLUME(NULL, 0, 0, 0), - HDA_CODEC_MUTE(NULL, 0, 0, 0), - HDA_BIND_MUTE(NULL, 0, 0, 0), - HDA_BIND_VOL(NULL, 0), - HDA_BIND_SW(NULL, 0), -}; - -/* add dynamic controls */ -static int add_control(struct alc_spec *spec, int type, const char *name, - int cidx, unsigned long val) -{ - struct snd_kcontrol_new *knew; - - knew = alc_kcontrol_new(spec); - if (!knew) - return -ENOMEM; - *knew = alc_control_templates[type]; - knew->name = kstrdup(name, GFP_KERNEL); - if (!knew->name) - return -ENOMEM; - knew->index = cidx; - if (get_amp_nid_(val)) - knew->subdevice = HDA_SUBDEV_AMP_FLAG; - knew->private_value = val; - return 0; -} - -static int add_control_with_pfx(struct alc_spec *spec, int type, - const char *pfx, const char *dir, - const char *sfx, int cidx, unsigned long val) -{ - char name[32]; - snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); - return add_control(spec, type, name, cidx, val); -} - -#define add_pb_vol_ctrl(spec, type, pfx, val) \ - add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val) -#define add_pb_sw_ctrl(spec, type, pfx, val) \ - add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val) -#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \ - add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val) -#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \ - add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val) - -static const char * const channel_name[4] = { - "Front", "Surround", "CLFE", "Side" -}; - -static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, - bool can_be_master, int *index) -{ - struct auto_pin_cfg *cfg = &spec->autocfg; - - *index = 0; - if (cfg->line_outs == 1 && !spec->multi_ios && - !cfg->hp_outs && !cfg->speaker_outs && can_be_master) - return "Master"; - - switch (cfg->line_out_type) { - case AUTO_PIN_SPEAKER_OUT: - if (cfg->line_outs == 1) - return "Speaker"; - if (cfg->line_outs == 2) - return ch ? "Bass Speaker" : "Speaker"; - break; - case AUTO_PIN_HP_OUT: - /* for multi-io case, only the primary out */ - if (ch && spec->multi_ios) - break; - *index = ch; - return "Headphone"; - default: - if (cfg->line_outs == 1 && !spec->multi_ios) - return "PCM"; - break; - } - if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name))) - return "PCM"; - - return channel_name[ch]; -} - -#ifdef CONFIG_SND_HDA_POWER_SAVE -/* add the powersave loopback-list entry */ -static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx) -{ - struct hda_amp_list *list; - - if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1) - return; - list = spec->loopback_list + spec->num_loopbacks; - list->nid = mix; - list->dir = HDA_INPUT; - list->idx = idx; - spec->num_loopbacks++; - spec->loopback.amplist = spec->loopback_list; -} -#else -#define add_loopback_list(spec, mix, idx) /* NOP */ -#endif - -/* create input playback/capture controls for the given pin */ -static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, - const char *ctlname, int ctlidx, - int idx, hda_nid_t mix_nid) -{ - int err; - - err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx, - HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); - if (err < 0) - return err; - err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx, - HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); - if (err < 0) - return err; - add_loopback_list(spec, mix_nid, idx); - return 0; -} - -static int alc_is_input_pin(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int pincap = snd_hda_query_pin_caps(codec, nid); - return (pincap & AC_PINCAP_IN) != 0; -} - -/* Parse the codec tree and retrieve ADCs and corresponding capsrc MUXs */ -static int alc_auto_fill_adc_caps(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t nid; - hda_nid_t *adc_nids = spec->private_adc_nids; - hda_nid_t *cap_nids = spec->private_capsrc_nids; - int max_nums = ARRAY_SIZE(spec->private_adc_nids); - int i, nums = 0; - - nid = codec->start_nid; - for (i = 0; i < codec->num_nodes; i++, nid++) { - hda_nid_t src; - const hda_nid_t *list; - unsigned int caps = get_wcaps(codec, nid); - int type = get_wcaps_type(caps); - - if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL)) - continue; - adc_nids[nums] = nid; - cap_nids[nums] = nid; - src = nid; - for (;;) { - int n; - type = get_wcaps_type(get_wcaps(codec, src)); - if (type == AC_WID_PIN) - break; - if (type == AC_WID_AUD_SEL) { - cap_nids[nums] = src; - break; - } - n = snd_hda_get_conn_list(codec, src, &list); - if (n > 1) { - cap_nids[nums] = src; - break; - } else if (n != 1) - break; - src = *list; - } - if (++nums >= max_nums) - break; - } - spec->adc_nids = spec->private_adc_nids; - spec->capsrc_nids = spec->private_capsrc_nids; - spec->num_adc_nids = nums; - return nums; -} - -/* create playback/capture controls for input pins */ -static int alc_auto_create_input_ctls(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t mixer = spec->mixer_nid; - struct hda_input_mux *imux = &spec->private_imux[0]; - int num_adcs; - int i, c, err, idx, type_idx = 0; - const char *prev_label = NULL; - - num_adcs = alc_auto_fill_adc_caps(codec); - if (num_adcs < 0) - return 0; - - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t pin; - const char *label; - - pin = cfg->inputs[i].pin; - if (!alc_is_input_pin(codec, pin)) - continue; - - label = hda_get_autocfg_input_label(codec, cfg, i); - if (spec->shared_mic_hp && !strcmp(label, "Misc")) - label = "Headphone Mic"; - if (prev_label && !strcmp(label, prev_label)) - type_idx++; - else - type_idx = 0; - prev_label = label; - - if (mixer) { - idx = get_connection_index(codec, mixer, pin); - if (idx >= 0) { - err = new_analog_input(spec, pin, - label, type_idx, - idx, mixer); - if (err < 0) - return err; - } - } - - for (c = 0; c < num_adcs; c++) { - hda_nid_t cap = get_capsrc(spec, c); - idx = get_connection_index(codec, cap, pin); - if (idx >= 0) { - spec->imux_pins[imux->num_items] = pin; - snd_hda_add_imux_item(imux, label, idx, NULL); - break; - } - } - } - - spec->num_mux_defs = 1; - spec->input_mux = imux; - - return 0; -} - -/* create a shared input with the headphone out */ -static int alc_auto_create_shared_input(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int defcfg; - hda_nid_t nid; - - /* only one internal input pin? */ - if (cfg->num_inputs != 1) - return 0; - defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin); - if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT) - return 0; - - if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) - nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */ - else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT) - nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */ - else - return 0; /* both not available */ - - if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN)) - return 0; /* no input */ - - cfg->inputs[1].pin = nid; - cfg->inputs[1].type = AUTO_PIN_MIC; - cfg->num_inputs = 2; - spec->shared_mic_hp = 1; - snd_printdd("realtek: Enable shared I/O jack on NID 0x%x\n", nid); - return 0; -} - -static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid, - unsigned int pin_type) -{ - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_type); - /* unmute pin */ - if (nid_has_mute(codec, nid, HDA_OUTPUT)) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); -} - -static int get_pin_type(int line_out_type) -{ - if (line_out_type == AUTO_PIN_HP_OUT) - return PIN_HP; - else - return PIN_OUT; -} - -static void alc_auto_init_analog_input(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; - if (alc_is_input_pin(codec, nid)) { - alc_set_input_pin(codec, nid, cfg->inputs[i].type); - if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE); - } - } - - /* mute all loopback inputs */ - if (spec->mixer_nid) { - int nums = snd_hda_get_conn_list(codec, spec->mixer_nid, NULL); - for (i = 0; i < nums; i++) - snd_hda_codec_write(codec, spec->mixer_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_MUTE(i)); - } -} - -/* convert from MIX nid to DAC */ -static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid) -{ - hda_nid_t list[5]; - int i, num; - - if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_AUD_OUT) - return nid; - num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list)); - for (i = 0; i < num; i++) { - if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT) - return list[i]; - } - return 0; -} - -/* go down to the selector widget before the mixer */ -static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin) -{ - hda_nid_t srcs[5]; - int num = snd_hda_get_connections(codec, pin, srcs, - ARRAY_SIZE(srcs)); - if (num != 1 || - get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL) - return pin; - return srcs[0]; -} - -/* get MIX nid connected to the given pin targeted to DAC */ -static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin, - hda_nid_t dac) -{ - hda_nid_t mix[5]; - int i, num; - - pin = alc_go_down_to_selector(codec, pin); - num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix)); - for (i = 0; i < num; i++) { - if (alc_auto_mix_to_dac(codec, mix[i]) == dac) - return mix[i]; - } - return 0; -} - -/* select the connection from pin to DAC if needed */ -static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin, - hda_nid_t dac) -{ - hda_nid_t mix[5]; - int i, num; - - pin = alc_go_down_to_selector(codec, pin); - num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix)); - if (num < 2) - return 0; - for (i = 0; i < num; i++) { - if (alc_auto_mix_to_dac(codec, mix[i]) == dac) { - snd_hda_codec_update_cache(codec, pin, 0, - AC_VERB_SET_CONNECT_SEL, i); - return 0; - } - } - return 0; -} - -static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid) -{ - struct alc_spec *spec = codec->spec; - int i; - if (found_in_nid_list(nid, spec->multiout.dac_nids, - ARRAY_SIZE(spec->private_dac_nids)) || - found_in_nid_list(nid, spec->multiout.hp_out_nid, - ARRAY_SIZE(spec->multiout.hp_out_nid)) || - found_in_nid_list(nid, spec->multiout.extra_out_nid, - ARRAY_SIZE(spec->multiout.extra_out_nid))) - return true; - for (i = 0; i < spec->multi_ios; i++) { - if (spec->multi_io[i].dac == nid) - return true; - } - return false; -} - -/* look for an empty DAC slot */ -static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) -{ - hda_nid_t srcs[5]; - int i, num; - - pin = alc_go_down_to_selector(codec, pin); - num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); - for (i = 0; i < num; i++) { - hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]); - if (!nid) - continue; - if (!alc_is_dac_already_used(codec, nid)) - return nid; - } - return 0; -} - -/* check whether the DAC is reachable from the pin */ -static bool alc_auto_is_dac_reachable(struct hda_codec *codec, - hda_nid_t pin, hda_nid_t dac) -{ - hda_nid_t srcs[5]; - int i, num; - - if (!pin || !dac) - return false; - pin = alc_go_down_to_selector(codec, pin); - num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); - for (i = 0; i < num; i++) { - hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]); - if (nid == dac) - return true; - } - return false; -} - -static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t sel = alc_go_down_to_selector(codec, pin); - hda_nid_t nid, nid_found, srcs[5]; - int i, num = snd_hda_get_connections(codec, sel, srcs, - ARRAY_SIZE(srcs)); - if (num == 1) - return alc_auto_look_for_dac(codec, pin); - nid_found = 0; - for (i = 0; i < num; i++) { - if (srcs[i] == spec->mixer_nid) - continue; - nid = alc_auto_mix_to_dac(codec, srcs[i]); - if (nid && !alc_is_dac_already_used(codec, nid)) { - if (nid_found) - return 0; - nid_found = nid; - } - } - return nid_found; -} - -/* mark up volume and mute control NIDs: used during badness parsing and - * at creating actual controls - */ -static inline unsigned int get_ctl_pos(unsigned int data) -{ - hda_nid_t nid = get_amp_nid_(data); - unsigned int dir; - if (snd_BUG_ON(nid >= MAX_VOL_NIDS)) - return 0; - dir = get_amp_direction_(data); - return (nid << 1) | dir; -} - -#define is_ctl_used(bits, data) \ - test_bit(get_ctl_pos(data), bits) -#define mark_ctl_usage(bits, data) \ - set_bit(get_ctl_pos(data), bits) - -static void clear_vol_marks(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls)); - memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls)); -} - -/* badness definition */ -enum { - /* No primary DAC is found for the main output */ - BAD_NO_PRIMARY_DAC = 0x10000, - /* No DAC is found for the extra output */ - BAD_NO_DAC = 0x4000, - /* No possible multi-ios */ - BAD_MULTI_IO = 0x103, - /* No individual DAC for extra output */ - BAD_NO_EXTRA_DAC = 0x102, - /* No individual DAC for extra surrounds */ - BAD_NO_EXTRA_SURR_DAC = 0x101, - /* Primary DAC shared with main surrounds */ - BAD_SHARED_SURROUND = 0x100, - /* Primary DAC shared with main CLFE */ - BAD_SHARED_CLFE = 0x10, - /* Primary DAC shared with extra surrounds */ - BAD_SHARED_EXTRA_SURROUND = 0x10, - /* Volume widget is shared */ - BAD_SHARED_VOL = 0x10, -}; - -static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, - hda_nid_t pin, hda_nid_t dac); -static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, - hda_nid_t pin, hda_nid_t dac); - -static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin, - hda_nid_t dac) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t nid; - unsigned int val; - int badness = 0; - - nid = alc_look_for_out_vol_nid(codec, pin, dac); - if (nid) { - val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); - if (is_ctl_used(spec->vol_ctls, nid)) - badness += BAD_SHARED_VOL; - else - mark_ctl_usage(spec->vol_ctls, val); - } else - badness += BAD_SHARED_VOL; - nid = alc_look_for_out_mute_nid(codec, pin, dac); - if (nid) { - unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid)); - if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) - val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); - else - val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT); - if (is_ctl_used(spec->sw_ctls, val)) - badness += BAD_SHARED_VOL; - else - mark_ctl_usage(spec->sw_ctls, val); - } else - badness += BAD_SHARED_VOL; - return badness; -} - -struct badness_table { - int no_primary_dac; /* no primary DAC */ - int no_dac; /* no secondary DACs */ - int shared_primary; /* primary DAC is shared with main output */ - int shared_surr; /* secondary DAC shared with main or primary */ - int shared_clfe; /* third DAC shared with main or primary */ - int shared_surr_main; /* secondary DAC sahred with main/DAC0 */ -}; - -static struct badness_table main_out_badness = { - .no_primary_dac = BAD_NO_PRIMARY_DAC, - .no_dac = BAD_NO_DAC, - .shared_primary = BAD_NO_PRIMARY_DAC, - .shared_surr = BAD_SHARED_SURROUND, - .shared_clfe = BAD_SHARED_CLFE, - .shared_surr_main = BAD_SHARED_SURROUND, -}; - -static struct badness_table extra_out_badness = { - .no_primary_dac = BAD_NO_DAC, - .no_dac = BAD_NO_DAC, - .shared_primary = BAD_NO_EXTRA_DAC, - .shared_surr = BAD_SHARED_EXTRA_SURROUND, - .shared_clfe = BAD_SHARED_EXTRA_SURROUND, - .shared_surr_main = BAD_NO_EXTRA_SURR_DAC, -}; - -/* try to assign DACs to pins and return the resultant badness */ -static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs, - const hda_nid_t *pins, hda_nid_t *dacs, - const struct badness_table *bad) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, j; - int badness = 0; - hda_nid_t dac; - - if (!num_outs) - return 0; - - for (i = 0; i < num_outs; i++) { - hda_nid_t pin = pins[i]; - if (!dacs[i]) - dacs[i] = alc_auto_look_for_dac(codec, pin); - if (!dacs[i] && !i) { - for (j = 1; j < num_outs; j++) { - if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) { - dacs[0] = dacs[j]; - dacs[j] = 0; - break; - } - } - } - dac = dacs[i]; - if (!dac) { - if (alc_auto_is_dac_reachable(codec, pin, dacs[0])) - dac = dacs[0]; - else if (cfg->line_outs > i && - alc_auto_is_dac_reachable(codec, pin, - spec->private_dac_nids[i])) - dac = spec->private_dac_nids[i]; - if (dac) { - if (!i) - badness += bad->shared_primary; - else if (i == 1) - badness += bad->shared_surr; - else - badness += bad->shared_clfe; - } else if (alc_auto_is_dac_reachable(codec, pin, - spec->private_dac_nids[0])) { - dac = spec->private_dac_nids[0]; - badness += bad->shared_surr_main; - } else if (!i) - badness += bad->no_primary_dac; - else - badness += bad->no_dac; - } - if (dac) - badness += eval_shared_vol_badness(codec, pin, dac); - } - - return badness; -} - -static int alc_auto_fill_multi_ios(struct hda_codec *codec, - hda_nid_t reference_pin, - bool hardwired, int offset); - -static bool alc_map_singles(struct hda_codec *codec, int outs, - const hda_nid_t *pins, hda_nid_t *dacs) -{ - int i; - bool found = false; - for (i = 0; i < outs; i++) { - if (dacs[i]) - continue; - dacs[i] = get_dac_if_single(codec, pins[i]); - if (dacs[i]) - found = true; - } - return found; -} - -/* fill in the dac_nids table from the parsed pin configuration */ -static int fill_and_eval_dacs(struct hda_codec *codec, - bool fill_hardwired, - bool fill_mio_first) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, err, badness; - - /* set num_dacs once to full for alc_auto_look_for_dac() */ - spec->multiout.num_dacs = cfg->line_outs; - spec->multiout.dac_nids = spec->private_dac_nids; - memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); - memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid)); - memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid)); - spec->multi_ios = 0; - clear_vol_marks(codec); - badness = 0; - - /* fill hard-wired DACs first */ - if (fill_hardwired) { - bool mapped; - do { - mapped = alc_map_singles(codec, cfg->line_outs, - cfg->line_out_pins, - spec->private_dac_nids); - mapped |= alc_map_singles(codec, cfg->hp_outs, - cfg->hp_pins, - spec->multiout.hp_out_nid); - mapped |= alc_map_singles(codec, cfg->speaker_outs, - cfg->speaker_pins, - spec->multiout.extra_out_nid); - if (fill_mio_first && cfg->line_outs == 1 && - cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { - err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], true, 0); - if (!err) - mapped = true; - } - } while (mapped); - } - - badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins, - spec->private_dac_nids, - &main_out_badness); - - /* re-count num_dacs and squash invalid entries */ - spec->multiout.num_dacs = 0; - for (i = 0; i < cfg->line_outs; i++) { - if (spec->private_dac_nids[i]) - spec->multiout.num_dacs++; - else { - memmove(spec->private_dac_nids + i, - spec->private_dac_nids + i + 1, - sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); - spec->private_dac_nids[cfg->line_outs - 1] = 0; - } - } - - if (fill_mio_first && - cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { - /* try to fill multi-io first */ - err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0); - if (err < 0) - return err; - /* we don't count badness at this stage yet */ - } - - if (cfg->line_out_type != AUTO_PIN_HP_OUT) { - err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins, - spec->multiout.hp_out_nid, - &extra_out_badness); - if (err < 0) - return err; - badness += err; - } - if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { - err = alc_auto_fill_dacs(codec, cfg->speaker_outs, - cfg->speaker_pins, - spec->multiout.extra_out_nid, - &extra_out_badness); - if (err < 0) - return err; - badness += err; - } - if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { - err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0); - if (err < 0) - return err; - badness += err; - } - if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { - /* try multi-ios with HP + inputs */ - int offset = 0; - if (cfg->line_outs >= 3) - offset = 1; - err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false, - offset); - if (err < 0) - return err; - badness += err; - } - - if (spec->multi_ios == 2) { - for (i = 0; i < 2; i++) - spec->private_dac_nids[spec->multiout.num_dacs++] = - spec->multi_io[i].dac; - spec->ext_channel_count = 2; - } else if (spec->multi_ios) { - spec->multi_ios = 0; - badness += BAD_MULTI_IO; - } - - return badness; -} - -#define DEBUG_BADNESS - -#ifdef DEBUG_BADNESS -#define debug_badness snd_printdd -#else -#define debug_badness(...) -#endif - -static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg) -{ - debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", - cfg->line_out_pins[0], cfg->line_out_pins[1], - cfg->line_out_pins[2], cfg->line_out_pins[2], - spec->multiout.dac_nids[0], - spec->multiout.dac_nids[1], - spec->multiout.dac_nids[2], - spec->multiout.dac_nids[3]); - if (spec->multi_ios > 0) - debug_badness("multi_ios(%d) = %x/%x : %x/%x\n", - spec->multi_ios, - spec->multi_io[0].pin, spec->multi_io[1].pin, - spec->multi_io[0].dac, spec->multi_io[1].dac); - debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", - cfg->hp_pins[0], cfg->hp_pins[1], - cfg->hp_pins[2], cfg->hp_pins[2], - spec->multiout.hp_out_nid[0], - spec->multiout.hp_out_nid[1], - spec->multiout.hp_out_nid[2], - spec->multiout.hp_out_nid[3]); - debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n", - cfg->speaker_pins[0], cfg->speaker_pins[1], - cfg->speaker_pins[2], cfg->speaker_pins[3], - spec->multiout.extra_out_nid[0], - spec->multiout.extra_out_nid[1], - spec->multiout.extra_out_nid[2], - spec->multiout.extra_out_nid[3]); -} - -static int alc_auto_fill_dac_nids(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - struct auto_pin_cfg *best_cfg; - int best_badness = INT_MAX; - int badness; - bool fill_hardwired = true, fill_mio_first = true; - bool best_wired = true, best_mio = true; - bool hp_spk_swapped = false; - - best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL); - if (!best_cfg) - return -ENOMEM; - *best_cfg = *cfg; - - for (;;) { - badness = fill_and_eval_dacs(codec, fill_hardwired, - fill_mio_first); - if (badness < 0) { - kfree(best_cfg); - return badness; - } - debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n", - cfg->line_out_type, fill_hardwired, fill_mio_first, - badness); - debug_show_configs(spec, cfg); - if (badness < best_badness) { - best_badness = badness; - *best_cfg = *cfg; - best_wired = fill_hardwired; - best_mio = fill_mio_first; - } - if (!badness) - break; - fill_mio_first = !fill_mio_first; - if (!fill_mio_first) - continue; - fill_hardwired = !fill_hardwired; - if (!fill_hardwired) - continue; - if (hp_spk_swapped) - break; - hp_spk_swapped = true; - if (cfg->speaker_outs > 0 && - cfg->line_out_type == AUTO_PIN_HP_OUT) { - cfg->hp_outs = cfg->line_outs; - memcpy(cfg->hp_pins, cfg->line_out_pins, - sizeof(cfg->hp_pins)); - cfg->line_outs = cfg->speaker_outs; - memcpy(cfg->line_out_pins, cfg->speaker_pins, - sizeof(cfg->speaker_pins)); - cfg->speaker_outs = 0; - memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); - cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; - fill_hardwired = true; - continue; - } - if (cfg->hp_outs > 0 && - cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { - cfg->speaker_outs = cfg->line_outs; - memcpy(cfg->speaker_pins, cfg->line_out_pins, - sizeof(cfg->speaker_pins)); - cfg->line_outs = cfg->hp_outs; - memcpy(cfg->line_out_pins, cfg->hp_pins, - sizeof(cfg->hp_pins)); - cfg->hp_outs = 0; - memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); - cfg->line_out_type = AUTO_PIN_HP_OUT; - fill_hardwired = true; - continue; - } - break; - } - - if (badness) { - *cfg = *best_cfg; - fill_and_eval_dacs(codec, best_wired, best_mio); - } - debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n", - cfg->line_out_type, best_wired, best_mio); - debug_show_configs(spec, cfg); - - if (cfg->line_out_pins[0]) - spec->vmaster_nid = - alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0], - spec->multiout.dac_nids[0]); - - /* clear the bitmap flags for creating controls */ - clear_vol_marks(codec); - kfree(best_cfg); - return 0; -} - -static int alc_auto_add_vol_ctl(struct hda_codec *codec, - const char *pfx, int cidx, - hda_nid_t nid, unsigned int chs) -{ - struct alc_spec *spec = codec->spec; - unsigned int val; - if (!nid) - return 0; - val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT); - if (is_ctl_used(spec->vol_ctls, val) && chs != 2) /* exclude LFE */ - return 0; - mark_ctl_usage(spec->vol_ctls, val); - return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx, - val); -} - -static int alc_auto_add_stereo_vol(struct hda_codec *codec, - const char *pfx, int cidx, - hda_nid_t nid) -{ - int chs = 1; - if (get_wcaps(codec, nid) & AC_WCAP_STEREO) - chs = 3; - return alc_auto_add_vol_ctl(codec, pfx, cidx, nid, chs); -} - -/* create a mute-switch for the given mixer widget; - * if it has multiple sources (e.g. DAC and loopback), create a bind-mute - */ -static int alc_auto_add_sw_ctl(struct hda_codec *codec, - const char *pfx, int cidx, - hda_nid_t nid, unsigned int chs) -{ - struct alc_spec *spec = codec->spec; - int wid_type; - int type; - unsigned long val; - if (!nid) - return 0; - wid_type = get_wcaps_type(get_wcaps(codec, nid)); - if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT) { - type = ALC_CTL_WIDGET_MUTE; - val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT); - } else if (snd_hda_get_conn_list(codec, nid, NULL) == 1) { - type = ALC_CTL_WIDGET_MUTE; - val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT); - } else { - type = ALC_CTL_BIND_MUTE; - val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT); - } - if (is_ctl_used(spec->sw_ctls, val) && chs != 2) /* exclude LFE */ - return 0; - mark_ctl_usage(spec->sw_ctls, val); - return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val); -} - -static int alc_auto_add_stereo_sw(struct hda_codec *codec, const char *pfx, - int cidx, hda_nid_t nid) -{ - int chs = 1; - if (get_wcaps(codec, nid) & AC_WCAP_STEREO) - chs = 3; - return alc_auto_add_sw_ctl(codec, pfx, cidx, nid, chs); -} - -static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec, - hda_nid_t pin, hda_nid_t dac) -{ - hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac); - if (nid_has_mute(codec, pin, HDA_OUTPUT)) - return pin; - else if (mix && nid_has_mute(codec, mix, HDA_INPUT)) - return mix; - else if (nid_has_mute(codec, dac, HDA_OUTPUT)) - return dac; - return 0; -} - -static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec, - hda_nid_t pin, hda_nid_t dac) -{ - hda_nid_t mix = alc_auto_dac_to_mix(codec, pin, dac); - if (nid_has_volume(codec, dac, HDA_OUTPUT)) - return dac; - else if (nid_has_volume(codec, mix, HDA_OUTPUT)) - return mix; - else if (nid_has_volume(codec, pin, HDA_OUTPUT)) - return pin; - return 0; -} - -/* add playback controls from the parsed DAC table */ -static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, - const struct auto_pin_cfg *cfg) -{ - struct alc_spec *spec = codec->spec; - int i, err, noutputs; - - noutputs = cfg->line_outs; - if (spec->multi_ios > 0 && cfg->line_outs < 3) - noutputs += spec->multi_ios; - - for (i = 0; i < noutputs; i++) { - const char *name; - int index; - hda_nid_t dac, pin; - hda_nid_t sw, vol; - - dac = spec->multiout.dac_nids[i]; - if (!dac) - continue; - if (i >= cfg->line_outs) { - pin = spec->multi_io[i - 1].pin; - index = 0; - name = channel_name[i]; - } else { - pin = cfg->line_out_pins[i]; - name = alc_get_line_out_pfx(spec, i, true, &index); - } - - sw = alc_look_for_out_mute_nid(codec, pin, dac); - vol = alc_look_for_out_vol_nid(codec, pin, dac); - if (!name || !strcmp(name, "CLFE")) { - /* Center/LFE */ - err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1); - if (err < 0) - return err; - err = alc_auto_add_vol_ctl(codec, "LFE", 0, vol, 2); - if (err < 0) - return err; - err = alc_auto_add_sw_ctl(codec, "Center", 0, sw, 1); - if (err < 0) - return err; - err = alc_auto_add_sw_ctl(codec, "LFE", 0, sw, 2); - if (err < 0) - return err; - } else { - err = alc_auto_add_stereo_vol(codec, name, index, vol); - if (err < 0) - return err; - err = alc_auto_add_stereo_sw(codec, name, index, sw); - if (err < 0) - return err; - } - } - return 0; -} - -static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, - hda_nid_t dac, const char *pfx, - int cidx) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t sw, vol; - int err; - - if (!dac) { - unsigned int val; - /* the corresponding DAC is already occupied */ - if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) - return 0; /* no way */ - /* create a switch only */ - val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT); - if (is_ctl_used(spec->sw_ctls, val)) - return 0; /* already created */ - mark_ctl_usage(spec->sw_ctls, val); - return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val); - } - - sw = alc_look_for_out_mute_nid(codec, pin, dac); - vol = alc_look_for_out_vol_nid(codec, pin, dac); - err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol); - if (err < 0) - return err; - err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw); - if (err < 0) - return err; - return 0; -} - -static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec, - unsigned int nums, - struct hda_ctl_ops *ops) -{ - struct alc_spec *spec = codec->spec; - struct hda_bind_ctls **ctlp, *ctl; - snd_array_init(&spec->bind_ctls, sizeof(ctl), 8); - ctlp = snd_array_new(&spec->bind_ctls); - if (!ctlp) - return NULL; - ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL); - *ctlp = ctl; - if (ctl) - ctl->ops = ops; - return ctl; -} - -/* add playback controls for speaker and HP outputs */ -static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, - const hda_nid_t *pins, - const hda_nid_t *dacs, - const char *pfx) -{ - struct alc_spec *spec = codec->spec; - struct hda_bind_ctls *ctl; - char name[32]; - int i, n, err; - - if (!num_pins || !pins[0]) - return 0; - - if (num_pins == 1) { - hda_nid_t dac = *dacs; - if (!dac) - dac = spec->multiout.dac_nids[0]; - return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); - } - - for (i = 0; i < num_pins; i++) { - hda_nid_t dac; - if (dacs[num_pins - 1]) - dac = dacs[i]; /* with individual volumes */ - else - dac = 0; - if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) { - err = alc_auto_create_extra_out(codec, pins[i], dac, - "Bass Speaker", 0); - } else if (num_pins >= 3) { - snprintf(name, sizeof(name), "%s %s", - pfx, channel_name[i]); - err = alc_auto_create_extra_out(codec, pins[i], dac, - name, 0); - } else { - err = alc_auto_create_extra_out(codec, pins[i], dac, - pfx, i); - } - if (err < 0) - return err; - } - if (dacs[num_pins - 1]) - return 0; - - /* Let's create a bind-controls for volumes */ - ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol); - if (!ctl) - return -ENOMEM; - n = 0; - for (i = 0; i < num_pins; i++) { - hda_nid_t vol; - if (!pins[i] || !dacs[i]) - continue; - vol = alc_look_for_out_vol_nid(codec, pins[i], dacs[i]); - if (vol) - ctl->values[n++] = - HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT); - } - if (n) { - snprintf(name, sizeof(name), "%s Playback Volume", pfx); - err = add_control(spec, ALC_CTL_BIND_VOL, name, 0, (long)ctl); - if (err < 0) - return err; - } - return 0; -} - -static int alc_auto_create_hp_out(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - return alc_auto_create_extra_outs(codec, spec->autocfg.hp_outs, - spec->autocfg.hp_pins, - spec->multiout.hp_out_nid, - "Headphone"); -} - -static int alc_auto_create_speaker_out(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - return alc_auto_create_extra_outs(codec, spec->autocfg.speaker_outs, - spec->autocfg.speaker_pins, - spec->multiout.extra_out_nid, - "Speaker"); -} - -static void alc_auto_set_output_and_unmute(struct hda_codec *codec, - hda_nid_t pin, int pin_type, - hda_nid_t dac) -{ - int i, num; - hda_nid_t nid, mix = 0; - hda_nid_t srcs[HDA_MAX_CONNECTIONS]; - - alc_set_pin_output(codec, pin, pin_type); - nid = alc_go_down_to_selector(codec, pin); - num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs)); - for (i = 0; i < num; i++) { - if (alc_auto_mix_to_dac(codec, srcs[i]) != dac) - continue; - mix = srcs[i]; - break; - } - if (!mix) - return; - - /* need the manual connection? */ - if (num > 1) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i); - /* unmute mixer widget inputs */ - if (nid_has_mute(codec, mix, HDA_INPUT)) { - snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(0)); - snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(1)); - } - /* initialize volume */ - nid = alc_look_for_out_vol_nid(codec, pin, dac); - if (nid) - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_ZERO); - - /* unmute DAC if it's not assigned to a mixer */ - nid = alc_look_for_out_mute_nid(codec, pin, dac); - if (nid == mix && nid_has_mute(codec, dac, HDA_OUTPUT)) - snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_ZERO); -} - -static void alc_auto_init_multi_out(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int pin_type = get_pin_type(spec->autocfg.line_out_type); - int i; - - for (i = 0; i <= HDA_SIDE; i++) { - hda_nid_t nid = spec->autocfg.line_out_pins[i]; - if (nid) - alc_auto_set_output_and_unmute(codec, nid, pin_type, - spec->multiout.dac_nids[i]); - } -} - -static void alc_auto_init_extra_out(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int i; - hda_nid_t pin, dac; - - for (i = 0; i < spec->autocfg.hp_outs; i++) { - if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT) - break; - pin = spec->autocfg.hp_pins[i]; - if (!pin) - break; - dac = spec->multiout.hp_out_nid[i]; - if (!dac) { - if (i > 0 && spec->multiout.hp_out_nid[0]) - dac = spec->multiout.hp_out_nid[0]; - else - dac = spec->multiout.dac_nids[0]; - } - alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); - } - for (i = 0; i < spec->autocfg.speaker_outs; i++) { - if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) - break; - pin = spec->autocfg.speaker_pins[i]; - if (!pin) - break; - dac = spec->multiout.extra_out_nid[i]; - if (!dac) { - if (i > 0 && spec->multiout.extra_out_nid[0]) - dac = spec->multiout.extra_out_nid[0]; - else - dac = spec->multiout.dac_nids[0]; - } - alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); - } -} - -/* check whether the given pin can be a multi-io pin */ -static bool can_be_multiio_pin(struct hda_codec *codec, - unsigned int location, hda_nid_t nid) -{ - unsigned int defcfg, caps; - - defcfg = snd_hda_codec_get_pincfg(codec, nid); - if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX) - return false; - if (location && get_defcfg_location(defcfg) != location) - return false; - caps = snd_hda_query_pin_caps(codec, nid); - if (!(caps & AC_PINCAP_OUT)) - return false; - return true; -} - -/* - * multi-io helper - * - * When hardwired is set, try to fill ony hardwired pins, and returns - * zero if any pins are filled, non-zero if nothing found. - * When hardwired is off, try to fill possible input pins, and returns - * the badness value. - */ -static int alc_auto_fill_multi_ios(struct hda_codec *codec, - hda_nid_t reference_pin, - bool hardwired, int offset) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int type, i, j, dacs, num_pins, old_pins; - unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin); - unsigned int location = get_defcfg_location(defcfg); - int badness = 0; - - old_pins = spec->multi_ios; - if (old_pins >= 2) - goto end_fill; - - num_pins = 0; - for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { - for (i = 0; i < cfg->num_inputs; i++) { - if (cfg->inputs[i].type != type) - continue; - if (can_be_multiio_pin(codec, location, - cfg->inputs[i].pin)) - num_pins++; - } - } - if (num_pins < 2) - goto end_fill; - - dacs = spec->multiout.num_dacs; - for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) { - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; - hda_nid_t dac = 0; - - if (cfg->inputs[i].type != type) - continue; - if (!can_be_multiio_pin(codec, location, nid)) - continue; - for (j = 0; j < spec->multi_ios; j++) { - if (nid == spec->multi_io[j].pin) - break; - } - if (j < spec->multi_ios) - continue; - - if (offset && offset + spec->multi_ios < dacs) { - dac = spec->private_dac_nids[offset + spec->multi_ios]; - if (!alc_auto_is_dac_reachable(codec, nid, dac)) - dac = 0; - } - if (hardwired) - dac = get_dac_if_single(codec, nid); - else if (!dac) - dac = alc_auto_look_for_dac(codec, nid); - if (!dac) { - badness++; - continue; - } - spec->multi_io[spec->multi_ios].pin = nid; - spec->multi_io[spec->multi_ios].dac = dac; - spec->multi_ios++; - if (spec->multi_ios >= 2) - break; - } - } - end_fill: - if (badness) - badness = BAD_MULTI_IO; - if (old_pins == spec->multi_ios) { - if (hardwired) - return 1; /* nothing found */ - else - return badness; /* no badness if nothing found */ - } - if (!hardwired && spec->multi_ios < 2) { - spec->multi_ios = old_pins; - return badness; - } - - return 0; -} - -static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = spec->multi_ios + 1; - if (uinfo->value.enumerated.item > spec->multi_ios) - uinfo->value.enumerated.item = spec->multi_ios; - sprintf(uinfo->value.enumerated.name, "%dch", - (uinfo->value.enumerated.item + 1) * 2); - return 0; -} - -static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2; - return 0; -} - -static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t nid = spec->multi_io[idx].pin; - - if (!spec->multi_io[idx].ctl_in) - spec->multi_io[idx].ctl_in = - snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - if (output) { - snd_hda_codec_update_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_OUT); - if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, - HDA_AMP_MUTE, 0); - alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac); - } else { - if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, - HDA_AMP_MUTE, HDA_AMP_MUTE); - snd_hda_codec_update_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - spec->multi_io[idx].ctl_in); - } - return 0; -} - -static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - int i, ch; - - ch = ucontrol->value.enumerated.item[0]; - if (ch < 0 || ch > spec->multi_ios) - return -EINVAL; - if (ch == (spec->ext_channel_count - 1) / 2) - return 0; - spec->ext_channel_count = (ch + 1) * 2; - for (i = 0; i < spec->multi_ios; i++) - alc_set_multi_io(codec, i, i < ch); - spec->multiout.max_channels = spec->ext_channel_count; - if (spec->need_dac_fix && !spec->const_channel_count) - spec->multiout.num_dacs = spec->multiout.max_channels / 2; - return 1; -} - -static const struct snd_kcontrol_new alc_auto_channel_mode_enum = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_auto_ch_mode_info, - .get = alc_auto_ch_mode_get, - .put = alc_auto_ch_mode_put, -}; - -static int alc_auto_add_multi_channel_mode(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - - if (spec->multi_ios > 0) { - struct snd_kcontrol_new *knew; - - knew = alc_kcontrol_new(spec); - if (!knew) - return -ENOMEM; - *knew = alc_auto_channel_mode_enum; - knew->name = kstrdup("Channel Mode", GFP_KERNEL); - if (!knew->name) - return -ENOMEM; - } - return 0; -} - -/* filter out invalid adc_nids (and capsrc_nids) that don't give all - * active input pins - */ -static void alc_remove_invalid_adc_nids(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - const struct hda_input_mux *imux; - hda_nid_t adc_nids[ARRAY_SIZE(spec->private_adc_nids)]; - hda_nid_t capsrc_nids[ARRAY_SIZE(spec->private_adc_nids)]; - int i, n, nums; - - imux = spec->input_mux; - if (!imux) - return; - if (spec->dyn_adc_switch) - return; - - again: - nums = 0; - for (n = 0; n < spec->num_adc_nids; n++) { - hda_nid_t cap = spec->private_capsrc_nids[n]; - int num_conns = snd_hda_get_conn_list(codec, cap, NULL); - for (i = 0; i < imux->num_items; i++) { - hda_nid_t pin = spec->imux_pins[i]; - if (pin) { - if (get_connection_index(codec, cap, pin) < 0) - break; - } else if (num_conns <= imux->items[i].index) - break; - } - if (i >= imux->num_items) { - adc_nids[nums] = spec->private_adc_nids[n]; - capsrc_nids[nums++] = cap; - } - } - if (!nums) { - /* check whether ADC-switch is possible */ - if (!alc_check_dyn_adc_switch(codec)) { - if (spec->shared_mic_hp) { - spec->shared_mic_hp = 0; - spec->private_imux[0].num_items = 1; - goto again; - } - printk(KERN_WARNING "hda_codec: %s: no valid ADC found;" - " using fallback 0x%x\n", - codec->chip_name, spec->private_adc_nids[0]); - spec->num_adc_nids = 1; - spec->auto_mic = 0; - return; - } - } else if (nums != spec->num_adc_nids) { - memcpy(spec->private_adc_nids, adc_nids, - nums * sizeof(hda_nid_t)); - memcpy(spec->private_capsrc_nids, capsrc_nids, - nums * sizeof(hda_nid_t)); - spec->num_adc_nids = nums; - } - - if (spec->auto_mic) - alc_auto_mic_check_imux(codec); /* check auto-mic setups */ - else if (spec->input_mux->num_items == 1 || spec->shared_mic_hp) - spec->num_adc_nids = 1; /* reduce to a single ADC */ -} - -/* - * initialize ADC paths - */ -static void alc_auto_init_adc(struct hda_codec *codec, int adc_idx) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t nid; - - nid = spec->adc_nids[adc_idx]; - /* mute ADC */ - if (nid_has_mute(codec, nid, HDA_INPUT)) { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_MUTE(0)); - return; - } - if (!spec->capsrc_nids) - return; - nid = spec->capsrc_nids[adc_idx]; - if (nid_has_mute(codec, nid, HDA_OUTPUT)) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE); -} - -static void alc_auto_init_input_src(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int c, nums; - - for (c = 0; c < spec->num_adc_nids; c++) - alc_auto_init_adc(codec, c); - if (spec->dyn_adc_switch) - nums = 1; - else - nums = spec->num_adc_nids; - for (c = 0; c < nums; c++) - alc_mux_select(codec, c, spec->cur_mux[c], true); -} - -/* add mic boosts if needed */ -static int alc_auto_add_mic_boost(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, err; - int type_idx = 0; - hda_nid_t nid; - const char *prev_label = NULL; - - for (i = 0; i < cfg->num_inputs; i++) { - if (cfg->inputs[i].type > AUTO_PIN_MIC) - break; - nid = cfg->inputs[i].pin; - if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { - const char *label; - char boost_label[32]; - - label = hda_get_autocfg_input_label(codec, cfg, i); - if (spec->shared_mic_hp && !strcmp(label, "Misc")) - label = "Headphone Mic"; - if (prev_label && !strcmp(label, prev_label)) - type_idx++; - else - type_idx = 0; - prev_label = label; - - snprintf(boost_label, sizeof(boost_label), - "%s Boost Volume", label); - err = add_control(spec, ALC_CTL_WIDGET_VOL, - boost_label, type_idx, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); - if (err < 0) - return err; - } - } - return 0; -} - -/* select or unmute the given capsrc route */ -static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap, - int idx) -{ - if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) { - snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx, - HDA_AMP_MUTE, 0); - } else if (snd_hda_get_conn_list(codec, cap, NULL) > 1) { - snd_hda_codec_write_cache(codec, cap, 0, - AC_VERB_SET_CONNECT_SEL, idx); - } -} - -/* set the default connection to that pin */ -static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) -{ - struct alc_spec *spec = codec->spec; - int i; - - if (!pin) - return 0; - for (i = 0; i < spec->num_adc_nids; i++) { - hda_nid_t cap = get_capsrc(spec, i); - int idx; - - idx = get_connection_index(codec, cap, pin); - if (idx < 0) - continue; - select_or_unmute_capsrc(codec, cap, idx); - return i; /* return the found index */ - } - return -1; /* not found */ -} - -/* initialize some special cases for input sources */ -static void alc_init_special_input_src(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->autocfg.num_inputs; i++) - init_capsrc_for_pin(codec, spec->autocfg.inputs[i].pin); -} - -/* assign appropriate capture mixers */ -static void set_capture_mixer(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - static const struct snd_kcontrol_new *caps[2][3] = { - { alc_capture_mixer_nosrc1, - alc_capture_mixer_nosrc2, - alc_capture_mixer_nosrc3 }, - { alc_capture_mixer1, - alc_capture_mixer2, - alc_capture_mixer3 }, - }; - - /* check whether either of ADC or MUX has a volume control */ - if (!nid_has_volume(codec, spec->adc_nids[0], HDA_INPUT)) { - if (!spec->capsrc_nids) - return; /* no volume */ - if (!nid_has_volume(codec, spec->capsrc_nids[0], HDA_OUTPUT)) - return; /* no volume in capsrc, too */ - spec->vol_in_capsrc = 1; - } - - if (spec->num_adc_nids > 0) { - int mux = 0; - int num_adcs = 0; - - if (spec->input_mux && spec->input_mux->num_items > 1) - mux = 1; - if (spec->auto_mic) { - num_adcs = 1; - mux = 0; - } else if (spec->dyn_adc_switch) - num_adcs = 1; - if (!num_adcs) { - if (spec->num_adc_nids > 3) - spec->num_adc_nids = 3; - else if (!spec->num_adc_nids) - return; - num_adcs = spec->num_adc_nids; - } - spec->cap_mixer = caps[mux][num_adcs - 1]; - } -} - -/* - * standard auto-parser initializations - */ -static void alc_auto_init_std(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - alc_auto_init_multi_out(codec); - alc_auto_init_extra_out(codec); - alc_auto_init_analog_input(codec); - alc_auto_init_input_src(codec); - alc_auto_init_digital(codec); - if (spec->unsol_event) - alc_inithook(codec); -} - -/* - * Digital-beep handlers - */ -#ifdef CONFIG_SND_HDA_INPUT_BEEP -#define set_beep_amp(spec, nid, idx, dir) \ - ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) - -static const struct snd_pci_quirk beep_white_list[] = { - SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), - SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), - SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), - SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1), - SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1), - SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), - {} -}; - -static inline int has_cdefine_beep(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - const struct snd_pci_quirk *q; - q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list); - if (q) - return q->value; - return spec->cdefine.enable_pcbeep; -} -#else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ -#define has_cdefine_beep(codec) 0 -#endif - -/* parse the BIOS configuration and set up the alc_spec */ -/* return 1 if successful, 0 if the proper config is not found, - * or a negative error code - */ -static int alc_parse_auto_config(struct hda_codec *codec, - const hda_nid_t *ignore_nids, - const hda_nid_t *ssid_nids) -{ - struct alc_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int err; - - err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids, - spec->parse_flags); - if (err < 0) - return err; - if (!cfg->line_outs) { - if (cfg->dig_outs || cfg->dig_in_pin) { - spec->multiout.max_channels = 2; - spec->no_analog = 1; - goto dig_only; - } - return 0; /* can't find valid BIOS pin config */ - } - - if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && - cfg->line_outs <= cfg->hp_outs) { - /* use HP as primary out */ - cfg->speaker_outs = cfg->line_outs; - memcpy(cfg->speaker_pins, cfg->line_out_pins, - sizeof(cfg->speaker_pins)); - cfg->line_outs = cfg->hp_outs; - memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins)); - cfg->hp_outs = 0; - memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); - cfg->line_out_type = AUTO_PIN_HP_OUT; - } - - err = alc_auto_fill_dac_nids(codec); - if (err < 0) - return err; - err = alc_auto_add_multi_channel_mode(codec); - if (err < 0) - return err; - err = alc_auto_create_multi_out_ctls(codec, cfg); - if (err < 0) - return err; - err = alc_auto_create_hp_out(codec); - if (err < 0) - return err; - err = alc_auto_create_speaker_out(codec); - if (err < 0) - return err; - err = alc_auto_create_shared_input(codec); - if (err < 0) - return err; - err = alc_auto_create_input_ctls(codec); - if (err < 0) - return err; - - spec->multiout.max_channels = spec->multiout.num_dacs * 2; - - dig_only: - alc_auto_parse_digital(codec); - - if (!spec->no_analog) - alc_remove_invalid_adc_nids(codec); - - if (ssid_nids) - alc_ssid_check(codec, ssid_nids); - - if (!spec->no_analog) { - alc_auto_check_switches(codec); - err = alc_auto_add_mic_boost(codec); - if (err < 0) - return err; - } - - if (spec->kctls.list) - add_mixer(spec, spec->kctls.list); - - if (!spec->no_analog && !spec->cap_mixer) - set_capture_mixer(codec); - - return 1; -} - -static int alc880_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc880_ignore[] = { 0x1d, 0 }; - static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 }; - return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids); -} - -/* - * ALC880 fix-ups - */ -enum { - ALC880_FIXUP_GPIO1, - ALC880_FIXUP_GPIO2, - ALC880_FIXUP_MEDION_RIM, - ALC880_FIXUP_LG, - ALC880_FIXUP_W810, - ALC880_FIXUP_EAPD_COEF, - ALC880_FIXUP_TCL_S700, - ALC880_FIXUP_VOL_KNOB, - ALC880_FIXUP_FUJITSU, - ALC880_FIXUP_F1734, - ALC880_FIXUP_UNIWILL, - ALC880_FIXUP_UNIWILL_DIG, - ALC880_FIXUP_Z71V, - ALC880_FIXUP_3ST_BASE, - ALC880_FIXUP_3ST, - ALC880_FIXUP_3ST_DIG, - ALC880_FIXUP_5ST_BASE, - ALC880_FIXUP_5ST, - ALC880_FIXUP_5ST_DIG, - ALC880_FIXUP_6ST_BASE, - ALC880_FIXUP_6ST, - ALC880_FIXUP_6ST_DIG, -}; - -/* enable the volume-knob widget support on NID 0x21 */ -static void alc880_fixup_vol_knob(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action == ALC_FIXUP_ACT_PROBE) - snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT); -} - -static const struct alc_fixup alc880_fixups[] = { - [ALC880_FIXUP_GPIO1] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, - }, - [ALC880_FIXUP_GPIO2] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = alc_gpio2_init_verbs, - }, - [ALC880_FIXUP_MEDION_RIM] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 }, - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_GPIO2, - }, - [ALC880_FIXUP_LG] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - /* disable bogus unused pins */ - { 0x16, 0x411111f0 }, - { 0x18, 0x411111f0 }, - { 0x1a, 0x411111f0 }, - { } - } - }, - [ALC880_FIXUP_W810] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - /* disable bogus unused pins */ - { 0x17, 0x411111f0 }, - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_GPIO2, - }, - [ALC880_FIXUP_EAPD_COEF] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* change to EAPD mode */ - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 }, - {} - }, - }, - [ALC880_FIXUP_TCL_S700] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* change to EAPD mode */ - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 }, - {} - }, - .chained = true, - .chain_id = ALC880_FIXUP_GPIO2, - }, - [ALC880_FIXUP_VOL_KNOB] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc880_fixup_vol_knob, - }, - [ALC880_FIXUP_FUJITSU] = { - /* override all pins as BIOS on old Amilo is broken */ - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x0121411f }, /* HP */ - { 0x15, 0x99030120 }, /* speaker */ - { 0x16, 0x99030130 }, /* bass speaker */ - { 0x17, 0x411111f0 }, /* N/A */ - { 0x18, 0x411111f0 }, /* N/A */ - { 0x19, 0x01a19950 }, /* mic-in */ - { 0x1a, 0x411111f0 }, /* N/A */ - { 0x1b, 0x411111f0 }, /* N/A */ - { 0x1c, 0x411111f0 }, /* N/A */ - { 0x1d, 0x411111f0 }, /* N/A */ - { 0x1e, 0x01454140 }, /* SPDIF out */ - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_VOL_KNOB, - }, - [ALC880_FIXUP_F1734] = { - /* almost compatible with FUJITSU, but no bass and SPDIF */ - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x0121411f }, /* HP */ - { 0x15, 0x99030120 }, /* speaker */ - { 0x16, 0x411111f0 }, /* N/A */ - { 0x17, 0x411111f0 }, /* N/A */ - { 0x18, 0x411111f0 }, /* N/A */ - { 0x19, 0x01a19950 }, /* mic-in */ - { 0x1a, 0x411111f0 }, /* N/A */ - { 0x1b, 0x411111f0 }, /* N/A */ - { 0x1c, 0x411111f0 }, /* N/A */ - { 0x1d, 0x411111f0 }, /* N/A */ - { 0x1e, 0x411111f0 }, /* N/A */ - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_VOL_KNOB, - }, - [ALC880_FIXUP_UNIWILL] = { - /* need to fix HP and speaker pins to be parsed correctly */ - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x0121411f }, /* HP */ - { 0x15, 0x99030120 }, /* speaker */ - { 0x16, 0x99030130 }, /* bass speaker */ - { } - }, - }, - [ALC880_FIXUP_UNIWILL_DIG] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - /* disable bogus unused pins */ - { 0x17, 0x411111f0 }, - { 0x19, 0x411111f0 }, - { 0x1b, 0x411111f0 }, - { 0x1f, 0x411111f0 }, - { } - } - }, - [ALC880_FIXUP_Z71V] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - /* set up the whole pins as BIOS is utterly broken */ - { 0x14, 0x99030120 }, /* speaker */ - { 0x15, 0x0121411f }, /* HP */ - { 0x16, 0x411111f0 }, /* N/A */ - { 0x17, 0x411111f0 }, /* N/A */ - { 0x18, 0x01a19950 }, /* mic-in */ - { 0x19, 0x411111f0 }, /* N/A */ - { 0x1a, 0x01813031 }, /* line-in */ - { 0x1b, 0x411111f0 }, /* N/A */ - { 0x1c, 0x411111f0 }, /* N/A */ - { 0x1d, 0x411111f0 }, /* N/A */ - { 0x1e, 0x0144111e }, /* SPDIF */ - { } - } - }, - [ALC880_FIXUP_3ST_BASE] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x01014010 }, /* line-out */ - { 0x15, 0x411111f0 }, /* N/A */ - { 0x16, 0x411111f0 }, /* N/A */ - { 0x17, 0x411111f0 }, /* N/A */ - { 0x18, 0x01a19c30 }, /* mic-in */ - { 0x19, 0x0121411f }, /* HP */ - { 0x1a, 0x01813031 }, /* line-in */ - { 0x1b, 0x02a19c40 }, /* front-mic */ - { 0x1c, 0x411111f0 }, /* N/A */ - { 0x1d, 0x411111f0 }, /* N/A */ - /* 0x1e is filled in below */ - { 0x1f, 0x411111f0 }, /* N/A */ - { } - } - }, - [ALC880_FIXUP_3ST] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1e, 0x411111f0 }, /* N/A */ - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_3ST_BASE, - }, - [ALC880_FIXUP_3ST_DIG] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1e, 0x0144111e }, /* SPDIF */ - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_3ST_BASE, - }, - [ALC880_FIXUP_5ST_BASE] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x01014010 }, /* front */ - { 0x15, 0x411111f0 }, /* N/A */ - { 0x16, 0x01011411 }, /* CLFE */ - { 0x17, 0x01016412 }, /* surr */ - { 0x18, 0x01a19c30 }, /* mic-in */ - { 0x19, 0x0121411f }, /* HP */ - { 0x1a, 0x01813031 }, /* line-in */ - { 0x1b, 0x02a19c40 }, /* front-mic */ - { 0x1c, 0x411111f0 }, /* N/A */ - { 0x1d, 0x411111f0 }, /* N/A */ - /* 0x1e is filled in below */ - { 0x1f, 0x411111f0 }, /* N/A */ - { } - } - }, - [ALC880_FIXUP_5ST] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1e, 0x411111f0 }, /* N/A */ - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_5ST_BASE, - }, - [ALC880_FIXUP_5ST_DIG] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1e, 0x0144111e }, /* SPDIF */ - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_5ST_BASE, - }, - [ALC880_FIXUP_6ST_BASE] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x01014010 }, /* front */ - { 0x15, 0x01016412 }, /* surr */ - { 0x16, 0x01011411 }, /* CLFE */ - { 0x17, 0x01012414 }, /* side */ - { 0x18, 0x01a19c30 }, /* mic-in */ - { 0x19, 0x02a19c40 }, /* front-mic */ - { 0x1a, 0x01813031 }, /* line-in */ - { 0x1b, 0x0121411f }, /* HP */ - { 0x1c, 0x411111f0 }, /* N/A */ - { 0x1d, 0x411111f0 }, /* N/A */ - /* 0x1e is filled in below */ - { 0x1f, 0x411111f0 }, /* N/A */ - { } - } - }, - [ALC880_FIXUP_6ST] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1e, 0x411111f0 }, /* N/A */ - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_6ST_BASE, - }, - [ALC880_FIXUP_6ST_DIG] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1e, 0x0144111e }, /* SPDIF */ - { } - }, - .chained = true, - .chain_id = ALC880_FIXUP_6ST_BASE, - }, -}; - -static const struct snd_pci_quirk alc880_fixup_tbl[] = { - SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810), - SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V), - SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1), - SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2), - SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF), - SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG), - SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734), - SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL), - SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), - SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), - SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), - SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), - SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), - SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), - SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU), - SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG), - SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG), - SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG), - SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700), - - /* Below is the copied entries from alc880_quirks.c. - * It's not quite sure whether BIOS sets the correct pin-config table - * on these machines, thus they are kept to be compatible with - * the old static quirks. Once when it's confirmed to work without - * these overrides, it'd be better to remove. - */ - SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST), - SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG), - SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG), - SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST), - SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST), - SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST), - SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST), - SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST), - SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST), - SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */ - SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG), - SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG), - /* default Intel */ - SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST), - SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG), - SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG), - {} -}; - -static const struct alc_model_fixup alc880_fixup_models[] = { - {.id = ALC880_FIXUP_3ST, .name = "3stack"}, - {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"}, - {.id = ALC880_FIXUP_5ST, .name = "5stack"}, - {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"}, - {.id = ALC880_FIXUP_6ST, .name = "6stack"}, - {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"}, - {} -}; - - -/* - * OK, here we have finally the patch for ALC880 - */ -static int patch_alc880(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->mixer_nid = 0x0b; - spec->need_dac_fix = 1; - - alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl, - alc880_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - /* automatic parse from the BIOS config */ - err = alc880_parse_auto_config(codec); - if (err < 0) - goto error; - - if (!spec->no_analog) { - err = snd_hda_attach_beep_device(codec, 0x1); - if (err < 0) - goto error; - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); - } - - codec->patch_ops = alc_patch_ops; - - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - - return 0; - - error: - alc_free(codec); - return err; -} - - -/* - * ALC260 support - */ -static int alc260_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc260_ignore[] = { 0x17, 0 }; - static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 }; - return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids); -} - -/* - * Pin config fixes - */ -enum { - ALC260_FIXUP_HP_DC5750, - ALC260_FIXUP_HP_PIN_0F, - ALC260_FIXUP_COEF, - ALC260_FIXUP_GPIO1, - ALC260_FIXUP_GPIO1_TOGGLE, - ALC260_FIXUP_REPLACER, - ALC260_FIXUP_HP_B1900, - ALC260_FIXUP_KN1, -}; - -static void alc260_gpio1_automute(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - spec->hp_jack_present); -} - -static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - struct alc_spec *spec = codec->spec; - if (action == ALC_FIXUP_ACT_PROBE) { - /* although the machine has only one output pin, we need to - * toggle GPIO1 according to the jack state - */ - spec->automute_hook = alc260_gpio1_automute; - spec->detect_hp = 1; - spec->automute_speaker = 1; - spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ - snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); - spec->unsol_event = alc_sku_unsol_event; - add_verb(codec->spec, alc_gpio1_init_verbs); - } -} - -static void alc260_fixup_kn1(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - struct alc_spec *spec = codec->spec; - static const struct alc_pincfg pincfgs[] = { - { 0x0f, 0x02214000 }, /* HP/speaker */ - { 0x12, 0x90a60160 }, /* int mic */ - { 0x13, 0x02a19000 }, /* ext mic */ - { 0x18, 0x01446000 }, /* SPDIF out */ - /* disable bogus I/O pins */ - { 0x10, 0x411111f0 }, - { 0x11, 0x411111f0 }, - { 0x14, 0x411111f0 }, - { 0x15, 0x411111f0 }, - { 0x16, 0x411111f0 }, - { 0x17, 0x411111f0 }, - { 0x19, 0x411111f0 }, - { } - }; - - switch (action) { - case ALC_FIXUP_ACT_PRE_PROBE: - alc_apply_pincfgs(codec, pincfgs); - break; - case ALC_FIXUP_ACT_PROBE: - spec->init_amp = ALC_INIT_NONE; - break; - } -} - -static const struct alc_fixup alc260_fixups[] = { - [ALC260_FIXUP_HP_DC5750] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x11, 0x90130110 }, /* speaker */ - { } - } - }, - [ALC260_FIXUP_HP_PIN_0F] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x0f, 0x01214000 }, /* HP */ - { } - } - }, - [ALC260_FIXUP_COEF] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 }, - { } - }, - .chained = true, - .chain_id = ALC260_FIXUP_HP_PIN_0F, - }, - [ALC260_FIXUP_GPIO1] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, - }, - [ALC260_FIXUP_GPIO1_TOGGLE] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc260_fixup_gpio1_toggle, - .chained = true, - .chain_id = ALC260_FIXUP_HP_PIN_0F, - }, - [ALC260_FIXUP_REPLACER] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, - { } - }, - .chained = true, - .chain_id = ALC260_FIXUP_GPIO1_TOGGLE, - }, - [ALC260_FIXUP_HP_B1900] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc260_fixup_gpio1_toggle, - .chained = true, - .chain_id = ALC260_FIXUP_COEF, - }, - [ALC260_FIXUP_KN1] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc260_fixup_kn1, - }, -}; - -static const struct snd_pci_quirk alc260_fixup_tbl[] = { - SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1), - SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF), - SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1), - SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750), - SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900), - SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1), - SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1), - SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER), - SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF), - {} -}; - -/* - */ -static int patch_alc260(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->mixer_nid = 0x07; - - alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - /* automatic parse from the BIOS config */ - err = alc260_parse_auto_config(codec); - if (err < 0) - goto error; - - if (!spec->no_analog) { - err = snd_hda_attach_beep_device(codec, 0x1); - if (err < 0) - goto error; - set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); - } - - codec->patch_ops = alc_patch_ops; - spec->shutup = alc_eapd_shutup; - - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - - return 0; - - error: - alc_free(codec); - return err; -} - - -/* - * ALC882/883/885/888/889 support - * - * ALC882 is almost identical with ALC880 but has cleaner and more flexible - * configuration. Each pin widget can choose any input DACs and a mixer. - * Each ADC is connected from a mixer of all inputs. This makes possible - * 6-channel independent captures. - * - * In addition, an independent DAC for the multi-playback (not used in this - * driver yet). - */ - -/* - * Pin config fixes - */ -enum { - ALC882_FIXUP_ABIT_AW9D_MAX, - ALC882_FIXUP_LENOVO_Y530, - ALC882_FIXUP_PB_M5210, - ALC882_FIXUP_ACER_ASPIRE_7736, - ALC882_FIXUP_ASUS_W90V, - ALC889_FIXUP_CD, - ALC889_FIXUP_VAIO_TT, - ALC888_FIXUP_EEE1601, - ALC882_FIXUP_EAPD, - ALC883_FIXUP_EAPD, - ALC883_FIXUP_ACER_EAPD, - ALC882_FIXUP_GPIO1, - ALC882_FIXUP_GPIO2, - ALC882_FIXUP_GPIO3, - ALC889_FIXUP_COEF, - ALC882_FIXUP_ASUS_W2JC, - ALC882_FIXUP_ACER_ASPIRE_4930G, - ALC882_FIXUP_ACER_ASPIRE_8930G, - ALC882_FIXUP_ASPIRE_8930G_VERBS, - ALC885_FIXUP_MACPRO_GPIO, - ALC889_FIXUP_DAC_ROUTE, - ALC889_FIXUP_MBP_VREF, - ALC889_FIXUP_IMAC91_VREF, -}; - -static void alc889_fixup_coef(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action != ALC_FIXUP_ACT_INIT) - return; - alc889_coef_init(codec); -} - -/* toggle speaker-output according to the hp-jack state */ -static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) -{ - unsigned int gpiostate, gpiomask, gpiodir; - - gpiostate = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_DATA, 0); - - if (!muted) - gpiostate |= (1 << pin); - else - gpiostate &= ~(1 << pin); - - gpiomask = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_MASK, 0); - gpiomask |= (1 << pin); - - gpiodir = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_DIRECTION, 0); - gpiodir |= (1 << pin); - - - snd_hda_codec_write(codec, codec->afg, 0, - AC_VERB_SET_GPIO_MASK, gpiomask); - snd_hda_codec_write(codec, codec->afg, 0, - AC_VERB_SET_GPIO_DIRECTION, gpiodir); - - msleep(1); - - snd_hda_codec_write(codec, codec->afg, 0, - AC_VERB_SET_GPIO_DATA, gpiostate); -} - -/* set up GPIO at initialization */ -static void alc885_fixup_macpro_gpio(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action != ALC_FIXUP_ACT_INIT) - return; - alc882_gpio_mute(codec, 0, 0); - alc882_gpio_mute(codec, 1, 0); -} - -/* Fix the connection of some pins for ALC889: - * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't - * work correctly (bko#42740) - */ -static void alc889_fixup_dac_route(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action == ALC_FIXUP_ACT_PRE_PROBE) { - /* fake the connections during parsing the tree */ - hda_nid_t conn1[2] = { 0x0c, 0x0d }; - hda_nid_t conn2[2] = { 0x0e, 0x0f }; - snd_hda_override_conn_list(codec, 0x14, 2, conn1); - snd_hda_override_conn_list(codec, 0x15, 2, conn1); - snd_hda_override_conn_list(codec, 0x18, 2, conn2); - snd_hda_override_conn_list(codec, 0x1a, 2, conn2); - } else if (action == ALC_FIXUP_ACT_PROBE) { - /* restore the connections */ - hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 }; - snd_hda_override_conn_list(codec, 0x14, 5, conn); - snd_hda_override_conn_list(codec, 0x15, 5, conn); - snd_hda_override_conn_list(codec, 0x18, 5, conn); - snd_hda_override_conn_list(codec, 0x1a, 5, conn); - } -} - -/* Set VREF on HP pin */ -static void alc889_fixup_mbp_vref(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - struct alc_spec *spec = codec->spec; - static hda_nid_t nids[2] = { 0x14, 0x15 }; - int i; - - if (action != ALC_FIXUP_ACT_INIT) - return; - for (i = 0; i < ARRAY_SIZE(nids); i++) { - unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]); - if (get_defcfg_device(val) != AC_JACK_HP_OUT) - continue; - val = snd_hda_codec_read(codec, nids[i], 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - val |= AC_PINCTL_VREF_80; - snd_hda_codec_write(codec, nids[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, val); - spec->keep_vref_in_automute = 1; - break; - } -} - -/* Set VREF on speaker pins on imac91 */ -static void alc889_fixup_imac91_vref(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - struct alc_spec *spec = codec->spec; - static hda_nid_t nids[2] = { 0x18, 0x1a }; - int i; - - if (action != ALC_FIXUP_ACT_INIT) - return; - for (i = 0; i < ARRAY_SIZE(nids); i++) { - unsigned int val; - val = snd_hda_codec_read(codec, nids[i], 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - val |= AC_PINCTL_VREF_50; - snd_hda_codec_write(codec, nids[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, val); - } - spec->keep_vref_in_automute = 1; -} - -static const struct alc_fixup alc882_fixups[] = { - [ALC882_FIXUP_ABIT_AW9D_MAX] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x15, 0x01080104 }, /* side */ - { 0x16, 0x01011012 }, /* rear */ - { 0x17, 0x01016011 }, /* clfe */ - { } - } - }, - [ALC882_FIXUP_LENOVO_Y530] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x15, 0x99130112 }, /* rear int speakers */ - { 0x16, 0x99130111 }, /* subwoofer */ - { } - } - }, - [ALC882_FIXUP_PB_M5210] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, - {} - } - }, - [ALC882_FIXUP_ACER_ASPIRE_7736] = { - .type = ALC_FIXUP_SKU, - .v.sku = ALC_FIXUP_SKU_IGNORE, - }, - [ALC882_FIXUP_ASUS_W90V] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x16, 0x99130110 }, /* fix sequence for CLFE */ - { } - } - }, - [ALC889_FIXUP_CD] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1c, 0x993301f0 }, /* CD */ - { } - } - }, - [ALC889_FIXUP_VAIO_TT] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x17, 0x90170111 }, /* hidden surround speaker */ - { } - } - }, - [ALC888_FIXUP_EEE1601] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x0838 }, - { } - } - }, - [ALC882_FIXUP_EAPD] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* change to EAPD mode */ - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 }, - { } - } - }, - [ALC883_FIXUP_EAPD] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* change to EAPD mode */ - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 }, - { } - } - }, - [ALC883_FIXUP_ACER_EAPD] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* eanable EAPD on Acer laptops */ - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, - { } - } - }, - [ALC882_FIXUP_GPIO1] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, - }, - [ALC882_FIXUP_GPIO2] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = alc_gpio2_init_verbs, - }, - [ALC882_FIXUP_GPIO3] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = alc_gpio3_init_verbs, - }, - [ALC882_FIXUP_ASUS_W2JC] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, - .chained = true, - .chain_id = ALC882_FIXUP_EAPD, - }, - [ALC889_FIXUP_COEF] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc889_fixup_coef, - }, - [ALC882_FIXUP_ACER_ASPIRE_4930G] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x16, 0x99130111 }, /* CLFE speaker */ - { 0x17, 0x99130112 }, /* surround speaker */ - { } - }, - .chained = true, - .chain_id = ALC882_FIXUP_GPIO1, - }, - [ALC882_FIXUP_ACER_ASPIRE_8930G] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x16, 0x99130111 }, /* CLFE speaker */ - { 0x1b, 0x99130112 }, /* surround speaker */ - { } - }, - .chained = true, - .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS, - }, - [ALC882_FIXUP_ASPIRE_8930G_VERBS] = { - /* additional init verbs for Acer Aspire 8930G */ - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* Enable all DACs */ - /* DAC DISABLE/MUTE 1? */ - /* setting bits 1-5 disables DAC nids 0x02-0x06 - * apparently. Init=0x38 */ - { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, - /* DAC DISABLE/MUTE 2? */ - /* some bit here disables the other DACs. - * Init=0x4900 */ - { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 }, - /* DMIC fix - * This laptop has a stereo digital microphone. - * The mics are only 1cm apart which makes the stereo - * useless. However, either the mic or the ALC889 - * makes the signal become a difference/sum signal - * instead of standard stereo, which is annoying. - * So instead we flip this bit which makes the - * codec replicate the sum signal to both channels, - * turning it into a normal mono mic. - */ - /* DMIC_CONTROL? Init value = 0x0001 */ - { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 }, - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, - { } - }, - .chained = true, - .chain_id = ALC882_FIXUP_GPIO1, - }, - [ALC885_FIXUP_MACPRO_GPIO] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc885_fixup_macpro_gpio, - }, - [ALC889_FIXUP_DAC_ROUTE] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc889_fixup_dac_route, - }, - [ALC889_FIXUP_MBP_VREF] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc889_fixup_mbp_vref, - .chained = true, - .chain_id = ALC882_FIXUP_GPIO1, - }, - [ALC889_FIXUP_IMAC91_VREF] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc889_fixup_imac91_vref, - .chained = true, - .chain_id = ALC882_FIXUP_GPIO1, - }, -}; - -static const struct snd_pci_quirk alc882_fixup_tbl[] = { - SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD), - SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), - SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD), - SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), - SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD), - SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD), - SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G", - ALC882_FIXUP_ACER_ASPIRE_4930G), - SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G", - ALC882_FIXUP_ACER_ASPIRE_4930G), - SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G", - ALC882_FIXUP_ACER_ASPIRE_8930G), - SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G", - ALC882_FIXUP_ACER_ASPIRE_8930G), - SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", - ALC882_FIXUP_ACER_ASPIRE_4930G), - SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", - ALC882_FIXUP_ACER_ASPIRE_4930G), - SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G", - ALC882_FIXUP_ACER_ASPIRE_4930G), - SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), - SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G", - ALC882_FIXUP_ACER_ASPIRE_4930G), - SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE), - SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G), - SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736), - SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD), - SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), - SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC), - SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601), - SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), - - /* All Apple entries are in codec SSIDs */ - SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO), - SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO), - SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO), - SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD), - SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF), - SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO), - SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF), - SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), - SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), - SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), - SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), - SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), - SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), - - SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), - SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), - SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), - SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3", ALC889_FIXUP_CD), - SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), - SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), - SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), - SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530), - SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF), - {} -}; - -static const struct alc_model_fixup alc882_fixup_models[] = { - {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, - {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, - {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, - {} -}; - -/* - * BIOS auto configuration - */ -/* almost identical with ALC880 parser... */ -static int alc882_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc882_ignore[] = { 0x1d, 0 }; - static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 }; - return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids); -} - -/* - */ -static int patch_alc882(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->mixer_nid = 0x0b; - - switch (codec->vendor_id) { - case 0x10ec0882: - case 0x10ec0885: - break; - default: - /* ALC883 and variants */ - alc_fix_pll_init(codec, 0x20, 0x0a, 10); - break; - } - - err = alc_codec_rename_from_preset(codec); - if (err < 0) - goto error; - - alc_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl, - alc882_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - alc_auto_parse_customize_define(codec); - - /* automatic parse from the BIOS config */ - err = alc882_parse_auto_config(codec); - if (err < 0) - goto error; - - if (!spec->no_analog && has_cdefine_beep(codec)) { - err = snd_hda_attach_beep_device(codec, 0x1); - if (err < 0) - goto error; - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); - } - - codec->patch_ops = alc_patch_ops; - - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - - return 0; - - error: - alc_free(codec); - return err; -} - - -/* - * ALC262 support - */ -static int alc262_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc262_ignore[] = { 0x1d, 0 }; - static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 }; - return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids); -} - -/* - * Pin config fixes - */ -enum { - ALC262_FIXUP_FSC_H270, - ALC262_FIXUP_HP_Z200, - ALC262_FIXUP_TYAN, - ALC262_FIXUP_LENOVO_3000, - ALC262_FIXUP_BENQ, - ALC262_FIXUP_BENQ_T31, -}; - -static const struct alc_fixup alc262_fixups[] = { - [ALC262_FIXUP_FSC_H270] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x15, 0x0221142f }, /* front HP */ - { 0x1b, 0x0121141f }, /* rear HP */ - { } - } - }, - [ALC262_FIXUP_HP_Z200] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x16, 0x99130120 }, /* internal speaker */ - { } - } - }, - [ALC262_FIXUP_TYAN] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x1993e1f0 }, /* int AUX */ - { } - } - }, - [ALC262_FIXUP_LENOVO_3000] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, - {} - }, - .chained = true, - .chain_id = ALC262_FIXUP_BENQ, - }, - [ALC262_FIXUP_BENQ] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 }, - {} - } - }, - [ALC262_FIXUP_BENQ_T31] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, - {} - } - }, -}; - -static const struct snd_pci_quirk alc262_fixup_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200), - SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ), - SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ), - SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), - SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270), - SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000), - SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), - SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31), - {} -}; - - -/* - */ -static int patch_alc262(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->mixer_nid = 0x0b; - -#if 0 - /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is - * under-run - */ - { - int tmp; - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); - tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0); - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7); - snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80); - } -#endif - alc_fix_pll_init(codec, 0x20, 0x0a, 10); - - alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - alc_auto_parse_customize_define(codec); - - /* automatic parse from the BIOS config */ - err = alc262_parse_auto_config(codec); - if (err < 0) - goto error; - - if (!spec->no_analog && has_cdefine_beep(codec)) { - err = snd_hda_attach_beep_device(codec, 0x1); - if (err < 0) - goto error; - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); - } - - codec->patch_ops = alc_patch_ops; - spec->shutup = alc_eapd_shutup; - - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - - return 0; - - error: - alc_free(codec); - return err; -} - -/* - * ALC268 - */ -/* bind Beep switches of both NID 0x0f and 0x10 */ -static const struct hda_bind_ctls alc268_bind_beep_sw = { - .ops = &snd_hda_bind_sw, - .values = { - HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT), - 0 - }, -}; - -static const struct snd_kcontrol_new alc268_beep_mixer[] = { - HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT), - HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw), - { } -}; - -/* set PCBEEP vol = 0, mute connections */ -static const struct hda_verb alc268_beep_init_verbs[] = { - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - { } -}; - -/* - * BIOS auto configuration - */ -static int alc268_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 }; - struct alc_spec *spec = codec->spec; - int err = alc_parse_auto_config(codec, NULL, alc268_ssids); - if (err > 0) { - if (!spec->no_analog && spec->autocfg.speaker_pins[0] != 0x1d) { - add_mixer(spec, alc268_beep_mixer); - add_verb(spec, alc268_beep_init_verbs); - } - } - return err; -} - -/* - */ -static int patch_alc268(struct hda_codec *codec) -{ - struct alc_spec *spec; - int i, has_beep, err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - /* ALC268 has no aa-loopback mixer */ - - /* automatic parse from the BIOS config */ - err = alc268_parse_auto_config(codec); - if (err < 0) - goto error; - - has_beep = 0; - for (i = 0; i < spec->num_mixers; i++) { - if (spec->mixers[i] == alc268_beep_mixer) { - has_beep = 1; - break; - } - } - - if (has_beep) { - err = snd_hda_attach_beep_device(codec, 0x1); - if (err < 0) - goto error; - if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) - /* override the amp caps for beep generator */ - snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT, - (0x0c << AC_AMPCAP_OFFSET_SHIFT) | - (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) | - (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) | - (0 << AC_AMPCAP_MUTE_SHIFT)); - } - - codec->patch_ops = alc_patch_ops; - spec->shutup = alc_eapd_shutup; - - return 0; - - error: - alc_free(codec); - return err; -} - -/* - * ALC269 - */ -static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_44100, /* fixed rate */ - /* NID is set in alc_build_pcms */ - .ops = { - .open = alc_playback_pcm_open, - .prepare = alc_playback_pcm_prepare, - .cleanup = alc_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_44100, /* fixed rate */ - /* NID is set in alc_build_pcms */ -}; - -/* different alc269-variants */ -enum { - ALC269_TYPE_ALC269VA, - ALC269_TYPE_ALC269VB, - ALC269_TYPE_ALC269VC, -}; - -/* - * BIOS auto configuration - */ -static int alc269_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc269_ignore[] = { 0x1d, 0 }; - static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 }; - static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 }; - struct alc_spec *spec = codec->spec; - const hda_nid_t *ssids = spec->codec_variant == ALC269_TYPE_ALC269VA ? - alc269va_ssids : alc269_ssids; - - return alc_parse_auto_config(codec, alc269_ignore, ssids); -} - -static void alc269_toggle_power_output(struct hda_codec *codec, int power_up) -{ - int val = alc_read_coef_idx(codec, 0x04); - if (power_up) - val |= 1 << 11; - else - val &= ~(1 << 11); - alc_write_coef_idx(codec, 0x04, val); -} - -static void alc269_shutup(struct hda_codec *codec) -{ - if ((alc_get_coef0(codec) & 0x00ff) == 0x017) - alc269_toggle_power_output(codec, 0); - if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { - alc269_toggle_power_output(codec, 0); - msleep(150); - } -} - -#ifdef CONFIG_PM -static int alc269_resume(struct hda_codec *codec) -{ - if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { - alc269_toggle_power_output(codec, 0); - msleep(150); - } - - codec->patch_ops.init(codec); - - if ((alc_get_coef0(codec) & 0x00ff) == 0x017) { - alc269_toggle_power_output(codec, 1); - msleep(200); - } - - if ((alc_get_coef0(codec) & 0x00ff) == 0x018) - alc269_toggle_power_output(codec, 1); - - snd_hda_codec_resume_amp(codec); - snd_hda_codec_resume_cache(codec); - hda_call_check_power_status(codec, 0x01); - return 0; -} -#endif /* CONFIG_PM */ - -static void alc269_fixup_hweq(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - int coef; - - if (action != ALC_FIXUP_ACT_INIT) - return; - coef = alc_read_coef_idx(codec, 0x1e); - alc_write_coef_idx(codec, 0x1e, coef | 0x80); -} - -static void alc271_fixup_dmic(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - static const struct hda_verb verbs[] = { - {0x20, AC_VERB_SET_COEF_INDEX, 0x0d}, - {0x20, AC_VERB_SET_PROC_COEF, 0x4000}, - {} - }; - unsigned int cfg; - - if (strcmp(codec->chip_name, "ALC271X")) - return; - cfg = snd_hda_codec_get_pincfg(codec, 0x12); - if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED) - snd_hda_sequence_write(codec, verbs); -} - -static void alc269_fixup_pcm_44k(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - struct alc_spec *spec = codec->spec; - - if (action != ALC_FIXUP_ACT_PROBE) - return; - - /* Due to a hardware problem on Lenovo Ideadpad, we need to - * fix the sample rate of analog I/O to 44.1kHz - */ - spec->stream_analog_playback = &alc269_44k_pcm_analog_playback; - spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; -} - -static void alc269_fixup_stereo_dmic(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - int coef; - - if (action != ALC_FIXUP_ACT_INIT) - return; - /* The digital-mic unit sends PDM (differential signal) instead of - * the standard PCM, thus you can't record a valid mono stream as is. - * Below is a workaround specific to ALC269 to control the dmic - * signal source as mono. - */ - coef = alc_read_coef_idx(codec, 0x07); - alc_write_coef_idx(codec, 0x07, coef | 0x80); -} - -static void alc269_quanta_automute(struct hda_codec *codec) -{ - update_outputs(codec); - - snd_hda_codec_write(codec, 0x20, 0, - AC_VERB_SET_COEF_INDEX, 0x0c); - snd_hda_codec_write(codec, 0x20, 0, - AC_VERB_SET_PROC_COEF, 0x680); - - snd_hda_codec_write(codec, 0x20, 0, - AC_VERB_SET_COEF_INDEX, 0x0c); - snd_hda_codec_write(codec, 0x20, 0, - AC_VERB_SET_PROC_COEF, 0x480); -} - -static void alc269_fixup_quanta_mute(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - struct alc_spec *spec = codec->spec; - if (action != ALC_FIXUP_ACT_PROBE) - return; - spec->automute_hook = alc269_quanta_automute; -} - -/* update mute-LED according to the speaker mute state via mic2 VREF pin */ -static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled) -{ - struct hda_codec *codec = private_data; - unsigned int pinval = enabled ? 0x20 : 0x24; - snd_hda_codec_update_cache(codec, 0x19, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pinval); -} - -static void alc269_fixup_mic2_mute(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - struct alc_spec *spec = codec->spec; - switch (action) { - case ALC_FIXUP_ACT_BUILD: - spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook; - snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); - /* fallthru */ - case ALC_FIXUP_ACT_INIT: - snd_hda_sync_vmaster_hook(&spec->vmaster_mute); - break; - } -} - -enum { - ALC269_FIXUP_SONY_VAIO, - ALC275_FIXUP_SONY_VAIO_GPIO2, - ALC269_FIXUP_DELL_M101Z, - ALC269_FIXUP_SKU_IGNORE, - ALC269_FIXUP_ASUS_G73JW, - ALC269_FIXUP_LENOVO_EAPD, - ALC275_FIXUP_SONY_HWEQ, - ALC271_FIXUP_DMIC, - ALC269_FIXUP_PCM_44K, - ALC269_FIXUP_STEREO_DMIC, - ALC269_FIXUP_QUANTA_MUTE, - ALC269_FIXUP_LIFEBOOK, - ALC269_FIXUP_AMIC, - ALC269_FIXUP_DMIC, - ALC269VB_FIXUP_AMIC, - ALC269VB_FIXUP_DMIC, - ALC269_FIXUP_MIC2_MUTE_LED, -}; - -static const struct alc_fixup alc269_fixups[] = { - [ALC269_FIXUP_SONY_VAIO] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, - {} - } - }, - [ALC275_FIXUP_SONY_VAIO_GPIO2] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - {0x01, AC_VERB_SET_GPIO_MASK, 0x04}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, - { } - }, - .chained = true, - .chain_id = ALC269_FIXUP_SONY_VAIO - }, - [ALC269_FIXUP_DELL_M101Z] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* Enables internal speaker */ - {0x20, AC_VERB_SET_COEF_INDEX, 13}, - {0x20, AC_VERB_SET_PROC_COEF, 0x4040}, - {} - } - }, - [ALC269_FIXUP_SKU_IGNORE] = { - .type = ALC_FIXUP_SKU, - .v.sku = ALC_FIXUP_SKU_IGNORE, - }, - [ALC269_FIXUP_ASUS_G73JW] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x17, 0x99130111 }, /* subwoofer */ - { } - } - }, - [ALC269_FIXUP_LENOVO_EAPD] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0}, - {} - } - }, - [ALC275_FIXUP_SONY_HWEQ] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc269_fixup_hweq, - .chained = true, - .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2 - }, - [ALC271_FIXUP_DMIC] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc271_fixup_dmic, - }, - [ALC269_FIXUP_PCM_44K] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc269_fixup_pcm_44k, - }, - [ALC269_FIXUP_STEREO_DMIC] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc269_fixup_stereo_dmic, - }, - [ALC269_FIXUP_QUANTA_MUTE] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc269_fixup_quanta_mute, - }, - [ALC269_FIXUP_LIFEBOOK] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1a, 0x2101103f }, /* dock line-out */ - { 0x1b, 0x23a11040 }, /* dock mic-in */ - { } - }, - .chained = true, - .chain_id = ALC269_FIXUP_QUANTA_MUTE - }, - [ALC269_FIXUP_AMIC] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x15, 0x0121401f }, /* HP out */ - { 0x18, 0x01a19c20 }, /* mic */ - { 0x19, 0x99a3092f }, /* int-mic */ - { } - }, - }, - [ALC269_FIXUP_DMIC] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x12, 0x99a3092f }, /* int-mic */ - { 0x14, 0x99130110 }, /* speaker */ - { 0x15, 0x0121401f }, /* HP out */ - { 0x18, 0x01a19c20 }, /* mic */ - { } - }, - }, - [ALC269VB_FIXUP_AMIC] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x18, 0x01a19c20 }, /* mic */ - { 0x19, 0x99a3092f }, /* int-mic */ - { 0x21, 0x0121401f }, /* HP out */ - { } - }, - }, - [ALC269VB_FIXUP_DMIC] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x12, 0x99a3092f }, /* int-mic */ - { 0x14, 0x99130110 }, /* speaker */ - { 0x18, 0x01a19c20 }, /* mic */ - { 0x21, 0x0121401f }, /* HP out */ - { } - }, - }, - [ALC269_FIXUP_MIC2_MUTE_LED] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc269_fixup_mic2_mute, - }, -}; - -static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), - SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), - SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), - SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), - SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), - SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), - SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), - SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), - SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), - SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), - SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), - SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), - -#if 0 - /* Below is a quirk table taken from the old code. - * Basically the device should work as is without the fixup table. - * If BIOS doesn't give a proper info, enable the corresponding - * fixup entry. - */ - SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", - ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC), - SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC), - SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC), - SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC), -#endif - {} -}; - -static const struct alc_model_fixup alc269_fixup_models[] = { - {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, - {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, - {} -}; - - -static void alc269_fill_coef(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int val; - - if (spec->codec_variant != ALC269_TYPE_ALC269VB) - return; - - if ((alc_get_coef0(codec) & 0x00ff) < 0x015) { - alc_write_coef_idx(codec, 0xf, 0x960b); - alc_write_coef_idx(codec, 0xe, 0x8817); - } - - if ((alc_get_coef0(codec) & 0x00ff) == 0x016) { - alc_write_coef_idx(codec, 0xf, 0x960b); - alc_write_coef_idx(codec, 0xe, 0x8814); - } - - if ((alc_get_coef0(codec) & 0x00ff) == 0x017) { - val = alc_read_coef_idx(codec, 0x04); - /* Power up output pin */ - alc_write_coef_idx(codec, 0x04, val | (1<<11)); - } - - if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { - val = alc_read_coef_idx(codec, 0xd); - if ((val & 0x0c00) >> 10 != 0x1) { - /* Capless ramp up clock control */ - alc_write_coef_idx(codec, 0xd, val | (1<<10)); - } - val = alc_read_coef_idx(codec, 0x17); - if ((val & 0x01c0) >> 6 != 0x4) { - /* Class D power on reset */ - alc_write_coef_idx(codec, 0x17, val | (1<<7)); - } - } - - val = alc_read_coef_idx(codec, 0xd); /* Class D */ - alc_write_coef_idx(codec, 0xd, val | (1<<14)); - - val = alc_read_coef_idx(codec, 0x4); /* HP */ - alc_write_coef_idx(codec, 0x4, val | (1<<11)); -} - -/* - */ -static int patch_alc269(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err = 0; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->mixer_nid = 0x0b; - - err = alc_codec_rename_from_preset(codec); - if (err < 0) - goto error; - - if (codec->vendor_id == 0x10ec0269) { - spec->codec_variant = ALC269_TYPE_ALC269VA; - switch (alc_get_coef0(codec) & 0x00f0) { - case 0x0010: - if (codec->bus->pci->subsystem_vendor == 0x1025 && - spec->cdefine.platform_type == 1) - err = alc_codec_rename(codec, "ALC271X"); - spec->codec_variant = ALC269_TYPE_ALC269VB; - break; - case 0x0020: - if (codec->bus->pci->subsystem_vendor == 0x17aa && - codec->bus->pci->subsystem_device == 0x21f3) - err = alc_codec_rename(codec, "ALC3202"); - spec->codec_variant = ALC269_TYPE_ALC269VC; - break; - default: - alc_fix_pll_init(codec, 0x20, 0x04, 15); - } - if (err < 0) - goto error; - spec->init_hook = alc269_fill_coef; - alc269_fill_coef(codec); - } - - alc_pick_fixup(codec, alc269_fixup_models, - alc269_fixup_tbl, alc269_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - alc_auto_parse_customize_define(codec); - - /* automatic parse from the BIOS config */ - err = alc269_parse_auto_config(codec); - if (err < 0) - goto error; - - if (!spec->no_analog && has_cdefine_beep(codec)) { - err = snd_hda_attach_beep_device(codec, 0x1); - if (err < 0) - goto error; - set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); - } - - codec->patch_ops = alc_patch_ops; -#ifdef CONFIG_PM - codec->patch_ops.resume = alc269_resume; -#endif - spec->shutup = alc269_shutup; - - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - - return 0; - - error: - alc_free(codec); - return err; -} - -/* - * ALC861 - */ - -static int alc861_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc861_ignore[] = { 0x1d, 0 }; - static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 }; - return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids); -} - -/* Pin config fixes */ -enum { - ALC861_FIXUP_FSC_AMILO_PI1505, - ALC861_FIXUP_AMP_VREF_0F, - ALC861_FIXUP_NO_JACK_DETECT, - ALC861_FIXUP_ASUS_A6RP, -}; - -/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ -static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - struct alc_spec *spec = codec->spec; - unsigned int val; - - if (action != ALC_FIXUP_ACT_INIT) - return; - val = snd_hda_codec_read(codec, 0x0f, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))) - val |= AC_PINCTL_IN_EN; - val |= AC_PINCTL_VREF_50; - snd_hda_codec_write(codec, 0x0f, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, val); - spec->keep_vref_in_automute = 1; -} - -/* suppress the jack-detection */ -static void alc_fixup_no_jack_detect(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action == ALC_FIXUP_ACT_PRE_PROBE) - codec->no_jack_detect = 1; -} - -static const struct alc_fixup alc861_fixups[] = { - [ALC861_FIXUP_FSC_AMILO_PI1505] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x0b, 0x0221101f }, /* HP */ - { 0x0f, 0x90170310 }, /* speaker */ - { } - } - }, - [ALC861_FIXUP_AMP_VREF_0F] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc861_fixup_asus_amp_vref_0f, - }, - [ALC861_FIXUP_NO_JACK_DETECT] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc_fixup_no_jack_detect, - }, - [ALC861_FIXUP_ASUS_A6RP] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc861_fixup_asus_amp_vref_0f, - .chained = true, - .chain_id = ALC861_FIXUP_NO_JACK_DETECT, - } -}; - -static const struct snd_pci_quirk alc861_fixup_tbl[] = { - SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP), - SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F), - SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT), - SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F), - SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F), - SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505), - {} -}; - -/* - */ -static int patch_alc861(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->mixer_nid = 0x15; - - alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - /* automatic parse from the BIOS config */ - err = alc861_parse_auto_config(codec); - if (err < 0) - goto error; - - if (!spec->no_analog) { - err = snd_hda_attach_beep_device(codec, 0x23); - if (err < 0) - goto error; - set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); - } - - codec->patch_ops = alc_patch_ops; -#ifdef CONFIG_SND_HDA_POWER_SAVE - spec->power_hook = alc_power_eapd; -#endif - - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - - return 0; - - error: - alc_free(codec); - return err; -} - -/* - * ALC861-VD support - * - * Based on ALC882 - * - * In addition, an independent DAC - */ -static int alc861vd_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 }; - static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 }; - return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids); -} - -enum { - ALC660VD_FIX_ASUS_GPIO1, - ALC861VD_FIX_DALLAS, -}; - -/* exclude VREF80 */ -static void alc861vd_fixup_dallas(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action == ALC_FIXUP_ACT_PRE_PROBE) { - snd_hda_override_pin_caps(codec, 0x18, 0x00001714); - snd_hda_override_pin_caps(codec, 0x19, 0x0000171c); - } -} - -static const struct alc_fixup alc861vd_fixups[] = { - [ALC660VD_FIX_ASUS_GPIO1] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* reset GPIO1 */ - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - { } - } - }, - [ALC861VD_FIX_DALLAS] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc861vd_fixup_dallas, - }, -}; - -static const struct snd_pci_quirk alc861vd_fixup_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS), - SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1), - SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS), - {} -}; - -static const struct hda_verb alc660vd_eapd_verbs[] = { - {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, - {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, - { } -}; - -/* - */ -static int patch_alc861vd(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - spec->mixer_nid = 0x0b; - - alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - /* automatic parse from the BIOS config */ - err = alc861vd_parse_auto_config(codec); - if (err < 0) - goto error; - - if (codec->vendor_id == 0x10ec0660) { - /* always turn on EAPD */ - add_verb(spec, alc660vd_eapd_verbs); - } - - if (!spec->no_analog) { - err = snd_hda_attach_beep_device(codec, 0x23); - if (err < 0) - goto error; - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); - } - - codec->patch_ops = alc_patch_ops; - - spec->shutup = alc_eapd_shutup; - - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - - return 0; - - error: - alc_free(codec); - return err; -} - -/* - * ALC662 support - * - * ALC662 is almost identical with ALC880 but has cleaner and more flexible - * configuration. Each pin widget can choose any input DACs and a mixer. - * Each ADC is connected from a mixer of all inputs. This makes possible - * 6-channel independent captures. - * - * In addition, an independent DAC for the multi-playback (not used in this - * driver yet). - */ - -/* - * BIOS auto configuration - */ - -static int alc662_parse_auto_config(struct hda_codec *codec) -{ - static const hda_nid_t alc662_ignore[] = { 0x1d, 0 }; - static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 }; - static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 }; - const hda_nid_t *ssids; - - if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || - codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670) - ssids = alc663_ssids; - else - ssids = alc662_ssids; - return alc_parse_auto_config(codec, alc662_ignore, ssids); -} - -static void alc272_fixup_mario(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action != ALC_FIXUP_ACT_PROBE) - return; - if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT, - (0x3b << AC_AMPCAP_OFFSET_SHIFT) | - (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) | - (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) | - (0 << AC_AMPCAP_MUTE_SHIFT))) - printk(KERN_WARNING - "hda_codec: failed to override amp caps for NID 0x2\n"); -} - -enum { - ALC662_FIXUP_ASPIRE, - ALC662_FIXUP_IDEAPAD, - ALC272_FIXUP_MARIO, - ALC662_FIXUP_CZC_P10T, - ALC662_FIXUP_SKU_IGNORE, - ALC662_FIXUP_HP_RP5800, - ALC662_FIXUP_ASUS_MODE1, - ALC662_FIXUP_ASUS_MODE2, - ALC662_FIXUP_ASUS_MODE3, - ALC662_FIXUP_ASUS_MODE4, - ALC662_FIXUP_ASUS_MODE5, - ALC662_FIXUP_ASUS_MODE6, - ALC662_FIXUP_ASUS_MODE7, - ALC662_FIXUP_ASUS_MODE8, - ALC662_FIXUP_NO_JACK_DETECT, - ALC662_FIXUP_ZOTAC_Z68, -}; - -static const struct alc_fixup alc662_fixups[] = { - [ALC662_FIXUP_ASPIRE] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x15, 0x99130112 }, /* subwoofer */ - { } - } - }, - [ALC662_FIXUP_IDEAPAD] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x17, 0x99130112 }, /* subwoofer */ - { } - } - }, - [ALC272_FIXUP_MARIO] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc272_fixup_mario, - }, - [ALC662_FIXUP_CZC_P10T] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0}, - {} - } - }, - [ALC662_FIXUP_SKU_IGNORE] = { - .type = ALC_FIXUP_SKU, - .v.sku = ALC_FIXUP_SKU_IGNORE, - }, - [ALC662_FIXUP_HP_RP5800] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x0221201f }, /* HP out */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_ASUS_MODE1] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x18, 0x01a19c20 }, /* mic */ - { 0x19, 0x99a3092f }, /* int-mic */ - { 0x21, 0x0121401f }, /* HP out */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_ASUS_MODE2] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x18, 0x01a19820 }, /* mic */ - { 0x19, 0x99a3092f }, /* int-mic */ - { 0x1b, 0x0121401f }, /* HP out */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_ASUS_MODE3] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x15, 0x0121441f }, /* HP */ - { 0x18, 0x01a19840 }, /* mic */ - { 0x19, 0x99a3094f }, /* int-mic */ - { 0x21, 0x01211420 }, /* HP2 */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_ASUS_MODE4] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x16, 0x99130111 }, /* speaker */ - { 0x18, 0x01a19840 }, /* mic */ - { 0x19, 0x99a3094f }, /* int-mic */ - { 0x21, 0x0121441f }, /* HP */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_ASUS_MODE5] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x15, 0x0121441f }, /* HP */ - { 0x16, 0x99130111 }, /* speaker */ - { 0x18, 0x01a19840 }, /* mic */ - { 0x19, 0x99a3094f }, /* int-mic */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_ASUS_MODE6] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x15, 0x01211420 }, /* HP2 */ - { 0x18, 0x01a19840 }, /* mic */ - { 0x19, 0x99a3094f }, /* int-mic */ - { 0x1b, 0x0121441f }, /* HP */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_ASUS_MODE7] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x17, 0x99130111 }, /* speaker */ - { 0x18, 0x01a19840 }, /* mic */ - { 0x19, 0x99a3094f }, /* int-mic */ - { 0x1b, 0x01214020 }, /* HP */ - { 0x21, 0x0121401f }, /* HP */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_ASUS_MODE8] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x14, 0x99130110 }, /* speaker */ - { 0x12, 0x99a30970 }, /* int-mic */ - { 0x15, 0x01214020 }, /* HP */ - { 0x17, 0x99130111 }, /* speaker */ - { 0x18, 0x01a19840 }, /* mic */ - { 0x21, 0x0121401f }, /* HP */ - { } - }, - .chained = true, - .chain_id = ALC662_FIXUP_SKU_IGNORE - }, - [ALC662_FIXUP_NO_JACK_DETECT] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc_fixup_no_jack_detect, - }, - [ALC662_FIXUP_ZOTAC_Z68] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1b, 0x02214020 }, /* Front HP */ - { } - } - }, -}; - -static const struct snd_pci_quirk alc662_fixup_tbl[] = { - SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE), - SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), - SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), - SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), - SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), - SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), - SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), - SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68), - SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T), - -#if 0 - /* Below is a quirk table taken from the old code. - * Basically the device should work as is without the fixup table. - * If BIOS doesn't give a proper info, enable the corresponding - * fixup entry. - */ - SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7), - SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7), - SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8), - SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6), - SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6), - SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5), - SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6), - SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3), - SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2), - SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1), - SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4), -#endif - {} -}; - -static const struct alc_model_fixup alc662_fixup_models[] = { - {.id = ALC272_FIXUP_MARIO, .name = "mario"}, - {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"}, - {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"}, - {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"}, - {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"}, - {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"}, - {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"}, - {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"}, - {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"}, - {} -}; - - -/* - */ -static int patch_alc662(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err = 0; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - - codec->spec = spec; - - spec->mixer_nid = 0x0b; - - /* handle multiple HPs as is */ - spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; - - alc_fix_pll_init(codec, 0x20, 0x04, 15); - - err = alc_codec_rename_from_preset(codec); - if (err < 0) - goto error; - - if ((alc_get_coef0(codec) & (1 << 14)) && - codec->bus->pci->subsystem_vendor == 0x1025 && - spec->cdefine.platform_type == 1) { - if (alc_codec_rename(codec, "ALC272X") < 0) - goto error; - } - - alc_pick_fixup(codec, alc662_fixup_models, - alc662_fixup_tbl, alc662_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - alc_auto_parse_customize_define(codec); - - /* automatic parse from the BIOS config */ - err = alc662_parse_auto_config(codec); - if (err < 0) - goto error; - - if (!spec->no_analog && has_cdefine_beep(codec)) { - err = snd_hda_attach_beep_device(codec, 0x1); - if (err < 0) - goto error; - switch (codec->vendor_id) { - case 0x10ec0662: - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); - break; - case 0x10ec0272: - case 0x10ec0663: - case 0x10ec0665: - set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); - break; - case 0x10ec0273: - set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); - break; - } - } - - codec->patch_ops = alc_patch_ops; - spec->shutup = alc_eapd_shutup; - - alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); - - return 0; - - error: - alc_free(codec); - return err; -} - -/* - * ALC680 support - */ - -static int alc680_parse_auto_config(struct hda_codec *codec) -{ - return alc_parse_auto_config(codec, NULL, NULL); -} - -/* - */ -static int patch_alc680(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - /* ALC680 has no aa-loopback mixer */ - - /* automatic parse from the BIOS config */ - err = alc680_parse_auto_config(codec); - if (err < 0) { - alc_free(codec); - return err; - } - - codec->patch_ops = alc_patch_ops; - - return 0; -} - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_realtek[] = { - { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 }, - { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, - { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, - { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 }, - { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, - { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 }, - { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 }, - { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 }, - { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, - { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, - { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, - { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", - .patch = patch_alc861 }, - { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, - { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, - { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd }, - { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2", - .patch = patch_alc882 }, - { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", - .patch = patch_alc662 }, - { .id = 0x10ec0662, .rev = 0x100300, .name = "ALC662 rev3", - .patch = patch_alc662 }, - { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, - { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, - { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, - { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, - { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, - { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, - { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, - { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A", - .patch = patch_alc882 }, - { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A", - .patch = patch_alc882 }, - { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, - { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 }, - { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200", - .patch = patch_alc882 }, - { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 }, - { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, - { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 }, - { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:10ec*"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek HD-audio codec"); - -static struct hda_codec_preset_list realtek_list = { - .preset = snd_hda_preset_realtek, - .owner = THIS_MODULE, -}; - -static int __init patch_realtek_init(void) -{ - return snd_hda_add_codec_preset(&realtek_list); -} - -static void __exit patch_realtek_exit(void) -{ - snd_hda_delete_codec_preset(&realtek_list); -} - -module_init(patch_realtek_init) -module_exit(patch_realtek_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_si3054.c b/ANDROID_3.4.5/sound/pci/hda/patch_si3054.c deleted file mode 100644 index 6679a509..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_si3054.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * HD audio interface patch for Silicon Labs 3054/5 modem codec - * - * Copyright (c) 2005 Sasha Khapyorsky - * Takashi Iwai - * - * - * This driver 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 driver 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 "hda_codec.h" -#include "hda_local.h" - -/* si3054 verbs */ -#define SI3054_VERB_READ_NODE 0x900 -#define SI3054_VERB_WRITE_NODE 0x100 - -/* si3054 nodes (registers) */ -#define SI3054_EXTENDED_MID 2 -#define SI3054_LINE_RATE 3 -#define SI3054_LINE_LEVEL 4 -#define SI3054_GPIO_CFG 5 -#define SI3054_GPIO_POLARITY 6 -#define SI3054_GPIO_STICKY 7 -#define SI3054_GPIO_WAKEUP 8 -#define SI3054_GPIO_STATUS 9 -#define SI3054_GPIO_CONTROL 10 -#define SI3054_MISC_AFE 11 -#define SI3054_CHIPID 12 -#define SI3054_LINE_CFG1 13 -#define SI3054_LINE_STATUS 14 -#define SI3054_DC_TERMINATION 15 -#define SI3054_LINE_CONFIG 16 -#define SI3054_CALLPROG_ATT 17 -#define SI3054_SQ_CONTROL 18 -#define SI3054_MISC_CONTROL 19 -#define SI3054_RING_CTRL1 20 -#define SI3054_RING_CTRL2 21 - -/* extended MID */ -#define SI3054_MEI_READY 0xf - -/* line level */ -#define SI3054_ATAG_MASK 0x00f0 -#define SI3054_DTAG_MASK 0xf000 - -/* GPIO bits */ -#define SI3054_GPIO_OH 0x0001 -#define SI3054_GPIO_CID 0x0002 - -/* chipid and revisions */ -#define SI3054_CHIPID_CODEC_REV_MASK 0x000f -#define SI3054_CHIPID_DAA_REV_MASK 0x00f0 -#define SI3054_CHIPID_INTERNATIONAL 0x0100 -#define SI3054_CHIPID_DAA_ID 0x0f00 -#define SI3054_CHIPID_CODEC_ID (1<<12) - -/* si3054 codec registers (nodes) access macros */ -#define GET_REG(codec,reg) (snd_hda_codec_read(codec,reg,0,SI3054_VERB_READ_NODE,0)) -#define SET_REG(codec,reg,val) (snd_hda_codec_write(codec,reg,0,SI3054_VERB_WRITE_NODE,val)) -#define SET_REG_CACHE(codec,reg,val) \ - snd_hda_codec_write_cache(codec,reg,0,SI3054_VERB_WRITE_NODE,val) - - -struct si3054_spec { - unsigned international; - struct hda_pcm pcm; -}; - - -/* - * Modem mixer - */ - -#define PRIVATE_VALUE(reg,mask) ((reg<<16)|(mask&0xffff)) -#define PRIVATE_REG(val) ((val>>16)&0xffff) -#define PRIVATE_MASK(val) (val&0xffff) - -#define si3054_switch_info snd_ctl_boolean_mono_info - -static int si3054_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *uvalue) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - u16 reg = PRIVATE_REG(kcontrol->private_value); - u16 mask = PRIVATE_MASK(kcontrol->private_value); - uvalue->value.integer.value[0] = (GET_REG(codec, reg)) & mask ? 1 : 0 ; - return 0; -} - -static int si3054_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *uvalue) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - u16 reg = PRIVATE_REG(kcontrol->private_value); - u16 mask = PRIVATE_MASK(kcontrol->private_value); - if (uvalue->value.integer.value[0]) - SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) | mask); - else - SET_REG_CACHE(codec, reg, (GET_REG(codec, reg)) & ~mask); - return 0; -} - -#define SI3054_KCONTROL(kname,reg,mask) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = kname, \ - .subdevice = HDA_SUBDEV_NID_FLAG | reg, \ - .info = si3054_switch_info, \ - .get = si3054_switch_get, \ - .put = si3054_switch_put, \ - .private_value = PRIVATE_VALUE(reg,mask), \ -} - - -static const struct snd_kcontrol_new si3054_modem_mixer[] = { - SI3054_KCONTROL("Off-hook Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_OH), - SI3054_KCONTROL("Caller ID Switch", SI3054_GPIO_CONTROL, SI3054_GPIO_CID), - {} -}; - -static int si3054_build_controls(struct hda_codec *codec) -{ - return snd_hda_add_new_ctls(codec, si3054_modem_mixer); -} - - -/* - * PCM callbacks - */ - -static int si3054_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - u16 val; - - SET_REG(codec, SI3054_LINE_RATE, substream->runtime->rate); - val = GET_REG(codec, SI3054_LINE_LEVEL); - val &= 0xff << (8 * (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)); - val |= ((stream_tag & 0xf) << 4) << (8 * (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)); - SET_REG(codec, SI3054_LINE_LEVEL, val); - - snd_hda_codec_setup_stream(codec, hinfo->nid, - stream_tag, 0, format); - return 0; -} - -static int si3054_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - static unsigned int rates[] = { 8000, 9600, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - substream->runtime->hw.period_bytes_min = 80; - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); -} - - -static const struct hda_pcm_stream si3054_pcm = { - .substreams = 1, - .channels_min = 1, - .channels_max = 1, - .nid = 0x1, - .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_KNOT, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .maxbps = 16, - .ops = { - .open = si3054_pcm_open, - .prepare = si3054_pcm_prepare, - }, -}; - - -static int si3054_build_pcms(struct hda_codec *codec) -{ - struct si3054_spec *spec = codec->spec; - struct hda_pcm *info = &spec->pcm; - codec->num_pcms = 1; - codec->pcm_info = info; - info->name = "Si3054 Modem"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = codec->mfg; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = codec->mfg; - info->pcm_type = HDA_PCM_TYPE_MODEM; - return 0; -} - - -/* - * Init part - */ - -static int si3054_init(struct hda_codec *codec) -{ - struct si3054_spec *spec = codec->spec; - unsigned wait_count; - u16 val; - - snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0); - snd_hda_codec_write(codec, codec->mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0); - SET_REG(codec, SI3054_LINE_RATE, 9600); - SET_REG(codec, SI3054_LINE_LEVEL, SI3054_DTAG_MASK|SI3054_ATAG_MASK); - SET_REG(codec, SI3054_EXTENDED_MID, 0); - - wait_count = 10; - do { - msleep(2); - val = GET_REG(codec, SI3054_EXTENDED_MID); - } while ((val & SI3054_MEI_READY) != SI3054_MEI_READY && wait_count--); - - if((val&SI3054_MEI_READY) != SI3054_MEI_READY) { - snd_printk(KERN_ERR "si3054: cannot initialize. EXT MID = %04x\n", val); - /* let's pray that this is no fatal error */ - /* return -EACCES; */ - } - - SET_REG(codec, SI3054_GPIO_POLARITY, 0xffff); - SET_REG(codec, SI3054_GPIO_CFG, 0x0); - SET_REG(codec, SI3054_MISC_AFE, 0); - SET_REG(codec, SI3054_LINE_CFG1,0x200); - - if((GET_REG(codec,SI3054_LINE_STATUS) & (1<<6)) == 0) { - snd_printd("Link Frame Detect(FDT) is not ready (line status: %04x)\n", - GET_REG(codec,SI3054_LINE_STATUS)); - } - - spec->international = GET_REG(codec, SI3054_CHIPID) & SI3054_CHIPID_INTERNATIONAL; - - return 0; -} - -static void si3054_free(struct hda_codec *codec) -{ - kfree(codec->spec); -} - - -/* - */ - -static const struct hda_codec_ops si3054_patch_ops = { - .build_controls = si3054_build_controls, - .build_pcms = si3054_build_pcms, - .init = si3054_init, - .free = si3054_free, -}; - -static int patch_si3054(struct hda_codec *codec) -{ - struct si3054_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - codec->spec = spec; - codec->patch_ops = si3054_patch_ops; - return 0; -} - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_si3054[] = { - { .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 }, - { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, - { .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 }, - { .id = 0x11c13055, .name = "Si3054", .patch = patch_si3054 }, - { .id = 0x11c13155, .name = "Si3054", .patch = patch_si3054 }, - { .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 }, - { .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 }, - { .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 }, - /* VIA HDA on Clevo m540 */ - { .id = 0x11063288, .name = "Si3054", .patch = patch_si3054 }, - /* Asus A8J Modem (SM56) */ - { .id = 0x15433155, .name = "Si3054", .patch = patch_si3054 }, - /* LG LW20 modem */ - { .id = 0x18540018, .name = "Si3054", .patch = patch_si3054 }, - {} -}; - -MODULE_ALIAS("snd-hda-codec-id:163c3055"); -MODULE_ALIAS("snd-hda-codec-id:163c3155"); -MODULE_ALIAS("snd-hda-codec-id:11c13026"); -MODULE_ALIAS("snd-hda-codec-id:11c13055"); -MODULE_ALIAS("snd-hda-codec-id:11c13155"); -MODULE_ALIAS("snd-hda-codec-id:10573055"); -MODULE_ALIAS("snd-hda-codec-id:10573057"); -MODULE_ALIAS("snd-hda-codec-id:10573155"); -MODULE_ALIAS("snd-hda-codec-id:11063288"); -MODULE_ALIAS("snd-hda-codec-id:15433155"); -MODULE_ALIAS("snd-hda-codec-id:18540018"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Si3054 HD-audio modem codec"); - -static struct hda_codec_preset_list si3054_list = { - .preset = snd_hda_preset_si3054, - .owner = THIS_MODULE, -}; - -static int __init patch_si3054_init(void) -{ - return snd_hda_add_codec_preset(&si3054_list); -} - -static void __exit patch_si3054_exit(void) -{ - snd_hda_delete_codec_preset(&si3054_list); -} - -module_init(patch_si3054_init) -module_exit(patch_si3054_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_sigmatel.c b/ANDROID_3.4.5/sound/pci/hda/patch_sigmatel.c deleted file mode 100644 index 7494fbc1..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_sigmatel.c +++ /dev/null @@ -1,6515 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * HD audio interface patch for SigmaTel STAC92xx - * - * Copyright (c) 2005 Embedded Alley Solutions, Inc. - * Matt Porter - * - * Based on patch_cmedia.c and patch_realtek.c - * Copyright (c) 2004 Takashi Iwai - * - * This driver 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 driver 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 -#include -#include "hda_codec.h" -#include "hda_local.h" -#include "hda_beep.h" -#include "hda_jack.h" - -enum { - STAC_VREF_EVENT = 1, - STAC_INSERT_EVENT, - STAC_PWR_EVENT, - STAC_HP_EVENT, - STAC_LO_EVENT, - STAC_MIC_EVENT, -}; - -enum { - STAC_AUTO, - STAC_REF, - STAC_9200_OQO, - STAC_9200_DELL_D21, - STAC_9200_DELL_D22, - STAC_9200_DELL_D23, - STAC_9200_DELL_M21, - STAC_9200_DELL_M22, - STAC_9200_DELL_M23, - STAC_9200_DELL_M24, - STAC_9200_DELL_M25, - STAC_9200_DELL_M26, - STAC_9200_DELL_M27, - STAC_9200_M4, - STAC_9200_M4_2, - STAC_9200_PANASONIC, - STAC_9200_MODELS -}; - -enum { - STAC_9205_AUTO, - STAC_9205_REF, - STAC_9205_DELL_M42, - STAC_9205_DELL_M43, - STAC_9205_DELL_M44, - STAC_9205_EAPD, - STAC_9205_MODELS -}; - -enum { - STAC_92HD73XX_AUTO, - STAC_92HD73XX_NO_JD, /* no jack-detection */ - STAC_92HD73XX_REF, - STAC_92HD73XX_INTEL, - STAC_DELL_M6_AMIC, - STAC_DELL_M6_DMIC, - STAC_DELL_M6_BOTH, - STAC_DELL_EQ, - STAC_ALIENWARE_M17X, - STAC_92HD73XX_MODELS -}; - -enum { - STAC_92HD83XXX_AUTO, - STAC_92HD83XXX_REF, - STAC_92HD83XXX_PWR_REF, - STAC_DELL_S14, - STAC_DELL_VOSTRO_3500, - STAC_92HD83XXX_HP_cNB11_INTQUAD, - STAC_HP_DV7_4000, - STAC_HP_ZEPHYR, - STAC_92HD83XXX_MODELS -}; - -enum { - STAC_92HD71BXX_AUTO, - STAC_92HD71BXX_REF, - STAC_DELL_M4_1, - STAC_DELL_M4_2, - STAC_DELL_M4_3, - STAC_HP_M4, - STAC_HP_DV4, - STAC_HP_DV5, - STAC_HP_HDX, - STAC_HP_DV4_1222NR, - STAC_92HD71BXX_MODELS -}; - -enum { - STAC_925x_AUTO, - STAC_925x_REF, - STAC_M1, - STAC_M1_2, - STAC_M2, - STAC_M2_2, - STAC_M3, - STAC_M5, - STAC_M6, - STAC_925x_MODELS -}; - -enum { - STAC_922X_AUTO, - STAC_D945_REF, - STAC_D945GTP3, - STAC_D945GTP5, - STAC_INTEL_MAC_V1, - STAC_INTEL_MAC_V2, - STAC_INTEL_MAC_V3, - STAC_INTEL_MAC_V4, - STAC_INTEL_MAC_V5, - STAC_INTEL_MAC_AUTO, /* This model is selected if no module parameter - * is given, one of the above models will be - * chosen according to the subsystem id. */ - /* for backward compatibility */ - STAC_MACMINI, - STAC_MACBOOK, - STAC_MACBOOK_PRO_V1, - STAC_MACBOOK_PRO_V2, - STAC_IMAC_INTEL, - STAC_IMAC_INTEL_20, - STAC_ECS_202, - STAC_922X_DELL_D81, - STAC_922X_DELL_D82, - STAC_922X_DELL_M81, - STAC_922X_DELL_M82, - STAC_922X_MODELS -}; - -enum { - STAC_927X_AUTO, - STAC_D965_REF_NO_JD, /* no jack-detection */ - STAC_D965_REF, - STAC_D965_3ST, - STAC_D965_5ST, - STAC_D965_5ST_NO_FP, - STAC_DELL_3ST, - STAC_DELL_BIOS, - STAC_927X_VOLKNOB, - STAC_927X_MODELS -}; - -enum { - STAC_9872_AUTO, - STAC_9872_VAIO, - STAC_9872_MODELS -}; - -struct sigmatel_mic_route { - hda_nid_t pin; - signed char mux_idx; - signed char dmux_idx; -}; - -#define MAX_PINS_NUM 16 -#define MAX_ADCS_NUM 4 -#define MAX_DMICS_NUM 4 - -struct sigmatel_spec { - struct snd_kcontrol_new *mixers[4]; - unsigned int num_mixers; - - int board_config; - unsigned int eapd_switch: 1; - unsigned int surr_switch: 1; - unsigned int alt_switch: 1; - unsigned int hp_detect: 1; - unsigned int spdif_mute: 1; - unsigned int check_volume_offset:1; - unsigned int auto_mic:1; - unsigned int linear_tone_beep:1; - - /* gpio lines */ - unsigned int eapd_mask; - unsigned int gpio_mask; - unsigned int gpio_dir; - unsigned int gpio_data; - unsigned int gpio_mute; - unsigned int gpio_led; - unsigned int gpio_led_polarity; - unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ - unsigned int vref_led; - - /* stream */ - unsigned int stream_delay; - - /* analog loopback */ - const struct snd_kcontrol_new *aloopback_ctl; - unsigned char aloopback_mask; - unsigned char aloopback_shift; - - /* power management */ - unsigned int num_pwrs; - const hda_nid_t *pwr_nids; - const hda_nid_t *dac_list; - - /* playback */ - struct hda_input_mux *mono_mux; - unsigned int cur_mmux; - struct hda_multi_out multiout; - hda_nid_t dac_nids[5]; - hda_nid_t hp_dacs[5]; - hda_nid_t speaker_dacs[5]; - - int volume_offset; - - /* capture */ - const hda_nid_t *adc_nids; - unsigned int num_adcs; - const hda_nid_t *mux_nids; - unsigned int num_muxes; - const hda_nid_t *dmic_nids; - unsigned int num_dmics; - const hda_nid_t *dmux_nids; - unsigned int num_dmuxes; - const hda_nid_t *smux_nids; - unsigned int num_smuxes; - unsigned int num_analog_muxes; - - const unsigned long *capvols; /* amp-volume attr: HDA_COMPOSE_AMP_VAL() */ - const unsigned long *capsws; /* amp-mute attr: HDA_COMPOSE_AMP_VAL() */ - unsigned int num_caps; /* number of capture volume/switch elements */ - - struct sigmatel_mic_route ext_mic; - struct sigmatel_mic_route int_mic; - struct sigmatel_mic_route dock_mic; - - const char * const *spdif_labels; - - hda_nid_t dig_in_nid; - hda_nid_t mono_nid; - hda_nid_t anabeep_nid; - hda_nid_t digbeep_nid; - - /* pin widgets */ - const hda_nid_t *pin_nids; - unsigned int num_pins; - - /* codec specific stuff */ - const struct hda_verb *init; - const struct snd_kcontrol_new *mixer; - - /* capture source */ - struct hda_input_mux *dinput_mux; - unsigned int cur_dmux[2]; - struct hda_input_mux *input_mux; - unsigned int cur_mux[3]; - struct hda_input_mux *sinput_mux; - unsigned int cur_smux[2]; - unsigned int cur_amux; - hda_nid_t *amp_nids; - unsigned int powerdown_adcs; - - /* i/o switches */ - unsigned int io_switch[2]; - unsigned int clfe_swap; - hda_nid_t line_switch; /* shared line-in for input and output */ - hda_nid_t mic_switch; /* shared mic-in for input and output */ - hda_nid_t hp_switch; /* NID of HP as line-out */ - unsigned int aloopback; - - struct hda_pcm pcm_rec[2]; /* PCM information */ - - /* dynamic controls and input_mux */ - struct auto_pin_cfg autocfg; - struct snd_array kctls; - struct hda_input_mux private_dimux; - struct hda_input_mux private_imux; - struct hda_input_mux private_smux; - struct hda_input_mux private_mono_mux; - - /* auto spec */ - unsigned auto_pin_cnt; - hda_nid_t auto_pin_nids[MAX_PINS_NUM]; - unsigned auto_adc_cnt; - hda_nid_t auto_adc_nids[MAX_ADCS_NUM]; - hda_nid_t auto_mux_nids[MAX_ADCS_NUM]; - hda_nid_t auto_dmux_nids[MAX_ADCS_NUM]; - unsigned long auto_capvols[MAX_ADCS_NUM]; - unsigned auto_dmic_cnt; - hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; - - struct hda_vmaster_mute_hook vmaster_mute; -}; - -static const hda_nid_t stac9200_adc_nids[1] = { - 0x03, -}; - -static const hda_nid_t stac9200_mux_nids[1] = { - 0x0c, -}; - -static const hda_nid_t stac9200_dac_nids[1] = { - 0x02, -}; - -static const hda_nid_t stac92hd73xx_pwr_nids[8] = { - 0x0a, 0x0b, 0x0c, 0xd, 0x0e, - 0x0f, 0x10, 0x11 -}; - -static const hda_nid_t stac92hd73xx_slave_dig_outs[2] = { - 0x26, 0, -}; - -static const hda_nid_t stac92hd73xx_adc_nids[2] = { - 0x1a, 0x1b -}; - -#define STAC92HD73XX_NUM_DMICS 2 -static const hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = { - 0x13, 0x14, 0 -}; - -#define STAC92HD73_DAC_COUNT 5 - -static const hda_nid_t stac92hd73xx_mux_nids[2] = { - 0x20, 0x21, -}; - -static const hda_nid_t stac92hd73xx_dmux_nids[2] = { - 0x20, 0x21, -}; - -static const hda_nid_t stac92hd73xx_smux_nids[2] = { - 0x22, 0x23, -}; - -#define STAC92HD73XX_NUM_CAPS 2 -static const unsigned long stac92hd73xx_capvols[] = { - HDA_COMPOSE_AMP_VAL(0x20, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), -}; -#define stac92hd73xx_capsws stac92hd73xx_capvols - -#define STAC92HD83_DAC_COUNT 3 - -static const hda_nid_t stac92hd83xxx_pwr_nids[7] = { - 0x0a, 0x0b, 0x0c, 0xd, 0x0e, - 0x0f, 0x10 -}; - -static const hda_nid_t stac92hd83xxx_slave_dig_outs[2] = { - 0x1e, 0, -}; - -static const hda_nid_t stac92hd83xxx_dmic_nids[] = { - 0x11, 0x20, -}; - -static const hda_nid_t stac92hd71bxx_pwr_nids[3] = { - 0x0a, 0x0d, 0x0f -}; - -static const hda_nid_t stac92hd71bxx_adc_nids[2] = { - 0x12, 0x13, -}; - -static const hda_nid_t stac92hd71bxx_mux_nids[2] = { - 0x1a, 0x1b -}; - -static const hda_nid_t stac92hd71bxx_dmux_nids[2] = { - 0x1c, 0x1d, -}; - -static const hda_nid_t stac92hd71bxx_smux_nids[2] = { - 0x24, 0x25, -}; - -#define STAC92HD71BXX_NUM_DMICS 2 -static const hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = { - 0x18, 0x19, 0 -}; - -static const hda_nid_t stac92hd71bxx_dmic_5port_nids[STAC92HD71BXX_NUM_DMICS] = { - 0x18, 0 -}; - -static const hda_nid_t stac92hd71bxx_slave_dig_outs[2] = { - 0x22, 0 -}; - -#define STAC92HD71BXX_NUM_CAPS 2 -static const unsigned long stac92hd71bxx_capvols[] = { - HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), -}; -#define stac92hd71bxx_capsws stac92hd71bxx_capvols - -static const hda_nid_t stac925x_adc_nids[1] = { - 0x03, -}; - -static const hda_nid_t stac925x_mux_nids[1] = { - 0x0f, -}; - -static const hda_nid_t stac925x_dac_nids[1] = { - 0x02, -}; - -#define STAC925X_NUM_DMICS 1 -static const hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = { - 0x15, 0 -}; - -static const hda_nid_t stac925x_dmux_nids[1] = { - 0x14, -}; - -static const unsigned long stac925x_capvols[] = { - HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT), -}; -static const unsigned long stac925x_capsws[] = { - HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), -}; - -static const hda_nid_t stac922x_adc_nids[2] = { - 0x06, 0x07, -}; - -static const hda_nid_t stac922x_mux_nids[2] = { - 0x12, 0x13, -}; - -#define STAC922X_NUM_CAPS 2 -static const unsigned long stac922x_capvols[] = { - HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT), -}; -#define stac922x_capsws stac922x_capvols - -static const hda_nid_t stac927x_slave_dig_outs[2] = { - 0x1f, 0, -}; - -static const hda_nid_t stac927x_adc_nids[3] = { - 0x07, 0x08, 0x09 -}; - -static const hda_nid_t stac927x_mux_nids[3] = { - 0x15, 0x16, 0x17 -}; - -static const hda_nid_t stac927x_smux_nids[1] = { - 0x21, -}; - -static const hda_nid_t stac927x_dac_nids[6] = { - 0x02, 0x03, 0x04, 0x05, 0x06, 0 -}; - -static const hda_nid_t stac927x_dmux_nids[1] = { - 0x1b, -}; - -#define STAC927X_NUM_DMICS 2 -static const hda_nid_t stac927x_dmic_nids[STAC927X_NUM_DMICS + 1] = { - 0x13, 0x14, 0 -}; - -#define STAC927X_NUM_CAPS 3 -static const unsigned long stac927x_capvols[] = { - HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x19, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_INPUT), -}; -static const unsigned long stac927x_capsws[] = { - HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), -}; - -static const char * const stac927x_spdif_labels[5] = { - "Digital Playback", "ADAT", "Analog Mux 1", - "Analog Mux 2", "Analog Mux 3" -}; - -static const hda_nid_t stac9205_adc_nids[2] = { - 0x12, 0x13 -}; - -static const hda_nid_t stac9205_mux_nids[2] = { - 0x19, 0x1a -}; - -static const hda_nid_t stac9205_dmux_nids[1] = { - 0x1d, -}; - -static const hda_nid_t stac9205_smux_nids[1] = { - 0x21, -}; - -#define STAC9205_NUM_DMICS 2 -static const hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { - 0x17, 0x18, 0 -}; - -#define STAC9205_NUM_CAPS 2 -static const unsigned long stac9205_capvols[] = { - HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_INPUT), -}; -static const unsigned long stac9205_capsws[] = { - HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), - HDA_COMPOSE_AMP_VAL(0x1e, 3, 0, HDA_OUTPUT), -}; - -static const hda_nid_t stac9200_pin_nids[8] = { - 0x08, 0x09, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, -}; - -static const hda_nid_t stac925x_pin_nids[8] = { - 0x07, 0x08, 0x0a, 0x0b, - 0x0c, 0x0d, 0x10, 0x11, -}; - -static const hda_nid_t stac922x_pin_nids[10] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x15, 0x1b, -}; - -static const hda_nid_t stac92hd73xx_pin_nids[13] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x22, 0x23 -}; - -#define STAC92HD71BXX_NUM_PINS 13 -static const hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x00, - 0x00, 0x14, 0x18, 0x19, 0x1e, - 0x1f, 0x20, 0x27 -}; -static const hda_nid_t stac92hd71bxx_pin_nids_6port[STAC92HD71BXX_NUM_PINS] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x14, 0x18, 0x19, 0x1e, - 0x1f, 0x20, 0x27 -}; - -static const hda_nid_t stac927x_pin_nids[14] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, 0x13, - 0x14, 0x21, 0x22, 0x23, -}; - -static const hda_nid_t stac9205_pin_nids[12] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x14, 0x16, 0x17, 0x18, - 0x21, 0x22, -}; - -static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - return snd_hda_input_mux_info(spec->dinput_mux, uinfo); -} - -static int stac92xx_dmux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - unsigned int dmux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.enumerated.item[0] = spec->cur_dmux[dmux_idx]; - return 0; -} - -static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - unsigned int dmux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol, - spec->dmux_nids[dmux_idx], &spec->cur_dmux[dmux_idx]); -} - -static int stac92xx_smux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - return snd_hda_input_mux_info(spec->sinput_mux, uinfo); -} - -static int stac92xx_smux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.enumerated.item[0] = spec->cur_smux[smux_idx]; - return 0; -} - -static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - struct hda_input_mux *smux = &spec->private_smux; - unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - int err, val; - hda_nid_t nid; - - err = snd_hda_input_mux_put(codec, spec->sinput_mux, ucontrol, - spec->smux_nids[smux_idx], &spec->cur_smux[smux_idx]); - if (err < 0) - return err; - - if (spec->spdif_mute) { - if (smux_idx == 0) - nid = spec->multiout.dig_out_nid; - else - nid = codec->slave_dig_outs[smux_idx - 1]; - if (spec->cur_smux[smux_idx] == smux->num_items - 1) - val = HDA_AMP_MUTE; - else - val = 0; - /* un/mute SPDIF out */ - snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, - HDA_AMP_MUTE, val); - } - return 0; -} - -static int stac_vrefout_set(struct hda_codec *codec, - hda_nid_t nid, unsigned int new_vref) -{ - int error, pinctl; - - snd_printdd("%s, nid %x ctl %x\n", __func__, nid, new_vref); - pinctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - - if (pinctl < 0) - return pinctl; - - pinctl &= 0xff; - pinctl &= ~AC_PINCTL_VREFEN; - pinctl |= (new_vref & AC_PINCTL_VREFEN); - - error = snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); - if (error < 0) - return error; - - return 1; -} - -static unsigned int stac92xx_vref_set(struct hda_codec *codec, - hda_nid_t nid, unsigned int new_vref) -{ - int error; - unsigned int pincfg; - pincfg = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - - pincfg &= 0xff; - pincfg &= ~(AC_PINCTL_VREFEN | AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); - pincfg |= new_vref; - - if (new_vref == AC_PINCTL_VREF_HIZ) - pincfg |= AC_PINCTL_OUT_EN; - else - pincfg |= AC_PINCTL_IN_EN; - - error = snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, pincfg); - if (error < 0) - return error; - else - return 1; -} - -static unsigned int stac92xx_vref_get(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int vref; - vref = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - vref &= AC_PINCTL_VREFEN; - return vref; -} - -static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - return snd_hda_input_mux_info(spec->input_mux, uinfo); -} - -static int stac92xx_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; - return 0; -} - -static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - const struct hda_input_mux *imux = spec->input_mux; - unsigned int idx, prev_idx, didx; - - idx = ucontrol->value.enumerated.item[0]; - if (idx >= imux->num_items) - idx = imux->num_items - 1; - prev_idx = spec->cur_mux[adc_idx]; - if (prev_idx == idx) - return 0; - if (idx < spec->num_analog_muxes) { - snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0, - AC_VERB_SET_CONNECT_SEL, - imux->items[idx].index); - if (prev_idx >= spec->num_analog_muxes && - spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) { - imux = spec->dinput_mux; - /* 0 = analog */ - snd_hda_codec_write_cache(codec, - spec->dmux_nids[adc_idx], 0, - AC_VERB_SET_CONNECT_SEL, - imux->items[0].index); - } - } else { - imux = spec->dinput_mux; - /* first dimux item is hardcoded to select analog imux, - * so lets skip it - */ - didx = idx - spec->num_analog_muxes + 1; - snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0, - AC_VERB_SET_CONNECT_SEL, - imux->items[didx].index); - } - spec->cur_mux[adc_idx] = idx; - return 1; -} - -static int stac92xx_mono_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - return snd_hda_input_mux_info(spec->mono_mux, uinfo); -} - -static int stac92xx_mono_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - - ucontrol->value.enumerated.item[0] = spec->cur_mmux; - return 0; -} - -static int stac92xx_mono_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - - return snd_hda_input_mux_put(codec, spec->mono_mux, ucontrol, - spec->mono_nid, &spec->cur_mmux); -} - -#define stac92xx_aloopback_info snd_ctl_boolean_mono_info - -static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - struct sigmatel_spec *spec = codec->spec; - - ucontrol->value.integer.value[0] = !!(spec->aloopback & - (spec->aloopback_mask << idx)); - return 0; -} - -static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned int dac_mode; - unsigned int val, idx_val; - - idx_val = spec->aloopback_mask << idx; - if (ucontrol->value.integer.value[0]) - val = spec->aloopback | idx_val; - else - val = spec->aloopback & ~idx_val; - if (spec->aloopback == val) - return 0; - - spec->aloopback = val; - - /* Only return the bits defined by the shift value of the - * first two bytes of the mask - */ - dac_mode = snd_hda_codec_read(codec, codec->afg, 0, - kcontrol->private_value & 0xFFFF, 0x0); - dac_mode >>= spec->aloopback_shift; - - if (spec->aloopback & idx_val) { - snd_hda_power_up(codec); - dac_mode |= idx_val; - } else { - snd_hda_power_down(codec); - dac_mode &= ~idx_val; - } - - snd_hda_codec_write_cache(codec, codec->afg, 0, - kcontrol->private_value >> 16, dac_mode); - - return 1; -} - -static const struct hda_verb stac9200_core_init[] = { - /* set dac0mux for dac converter */ - { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {} -}; - -static const struct hda_verb stac9200_eapd_init[] = { - /* set dac0mux for dac converter */ - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, - {} -}; - -static const struct hda_verb dell_eq_core_init[] = { - /* set master volume to max value without distortion - * and direct control */ - { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, - {} -}; - -static const struct hda_verb stac92hd73xx_core_init[] = { - /* set master volume and direct control */ - { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - {} -}; - -static const struct hda_verb stac92hd83xxx_core_init[] = { - /* power state controls amps */ - { 0x01, AC_VERB_SET_EAPD, 1 << 2}, - {} -}; - -static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = { - { 0x22, 0x785, 0x43 }, - { 0x22, 0x782, 0xe0 }, - { 0x22, 0x795, 0x00 }, - {} -}; - -static const struct hda_verb stac92hd71bxx_core_init[] = { - /* set master volume and direct control */ - { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - {} -}; - -static const struct hda_verb stac92hd71bxx_unmute_core_init[] = { - /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ - { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {} -}; - -static const struct hda_verb stac925x_core_init[] = { - /* set dac0mux for dac converter */ - { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* mute the master volume */ - { 0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - {} -}; - -static const struct hda_verb stac922x_core_init[] = { - /* set master volume and direct control */ - { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - {} -}; - -static const struct hda_verb d965_core_init[] = { - /* set master volume and direct control */ - { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* unmute node 0x1b */ - { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - /* select node 0x03 as DAC */ - { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, - {} -}; - -static const struct hda_verb dell_3st_core_init[] = { - /* don't set delta bit */ - {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f}, - /* unmute node 0x1b */ - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - /* select node 0x03 as DAC */ - {0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, - {} -}; - -static const struct hda_verb stac927x_core_init[] = { - /* set master volume and direct control */ - { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* enable analog pc beep path */ - { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, - {} -}; - -static const struct hda_verb stac927x_volknob_core_init[] = { - /* don't set delta bit */ - {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f}, - /* enable analog pc beep path */ - {0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, - {} -}; - -static const struct hda_verb stac9205_core_init[] = { - /* set master volume and direct control */ - { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* enable analog pc beep path */ - { 0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, - {} -}; - -#define STAC_MONO_MUX \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Mono Mux", \ - .count = 1, \ - .info = stac92xx_mono_mux_enum_info, \ - .get = stac92xx_mono_mux_enum_get, \ - .put = stac92xx_mono_mux_enum_put, \ - } - -#define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Analog Loopback", \ - .count = cnt, \ - .info = stac92xx_aloopback_info, \ - .get = stac92xx_aloopback_get, \ - .put = stac92xx_aloopback_put, \ - .private_value = verb_read | (verb_write << 16), \ - } - -#define DC_BIAS(xname, idx, nid) \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = idx, \ - .info = stac92xx_dc_bias_info, \ - .get = stac92xx_dc_bias_get, \ - .put = stac92xx_dc_bias_put, \ - .private_value = nid, \ - } - -static const struct snd_kcontrol_new stac9200_mixer[] = { - HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = { - STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), - {} -}; - -static const struct snd_kcontrol_new stac92hd73xx_8ch_loopback[] = { - STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4), - {} -}; - -static const struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = { - STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5), - {} -}; - - -static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = { - STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2) -}; - -static const struct snd_kcontrol_new stac925x_mixer[] = { - HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct snd_kcontrol_new stac9205_loopback[] = { - STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), - {} -}; - -static const struct snd_kcontrol_new stac927x_loopback[] = { - STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), - {} -}; - -static struct snd_kcontrol_new stac_dmux_mixer = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Input Source", - /* count set later */ - .info = stac92xx_dmux_enum_info, - .get = stac92xx_dmux_enum_get, - .put = stac92xx_dmux_enum_put, -}; - -static struct snd_kcontrol_new stac_smux_mixer = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Playback Source", - /* count set later */ - .info = stac92xx_smux_enum_info, - .get = stac92xx_smux_enum_get, - .put = stac92xx_smux_enum_put, -}; - -static const char * const slave_pfxs[] = { - "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Speaker", "IEC958", - NULL -}; - -static void stac92xx_update_led_status(struct hda_codec *codec, int enabled); - -static void stac92xx_vmaster_hook(void *private_data, int val) -{ - stac92xx_update_led_status(private_data, val); -} - -static void stac92xx_free_kctls(struct hda_codec *codec); - -static int stac92xx_build_controls(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - unsigned int vmaster_tlv[4]; - int err; - int i; - - if (spec->mixer) { - err = snd_hda_add_new_ctls(codec, spec->mixer); - if (err < 0) - return err; - } - - for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - if (!spec->auto_mic && spec->num_dmuxes > 0 && - snd_hda_get_bool_hint(codec, "separate_dmux") == 1) { - stac_dmux_mixer.count = spec->num_dmuxes; - err = snd_hda_ctl_add(codec, 0, - snd_ctl_new1(&stac_dmux_mixer, codec)); - if (err < 0) - return err; - } - if (spec->num_smuxes > 0) { - int wcaps = get_wcaps(codec, spec->multiout.dig_out_nid); - struct hda_input_mux *smux = &spec->private_smux; - /* check for mute support on SPDIF out */ - if (wcaps & AC_WCAP_OUT_AMP) { - snd_hda_add_imux_item(smux, "Off", 0, NULL); - spec->spdif_mute = 1; - } - stac_smux_mixer.count = spec->num_smuxes; - err = snd_hda_ctl_add(codec, 0, - snd_ctl_new1(&stac_smux_mixer, codec)); - if (err < 0) - return err; - } - - if (spec->multiout.dig_out_nid) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - err = snd_hda_create_spdif_share_sw(codec, - &spec->multiout); - if (err < 0) - return err; - spec->multiout.share_spdif = 1; - } - if (spec->dig_in_nid && !(spec->gpio_dir & 0x01)) { - err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); - if (err < 0) - return err; - } - - /* if we have no master control, let's create it */ - snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], - HDA_OUTPUT, vmaster_tlv); - /* correct volume offset */ - vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; - /* minimum value is actually mute */ - vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; - err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, slave_pfxs, - "Playback Volume"); - if (err < 0) - return err; - - err = __snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, slave_pfxs, - "Playback Switch", true, - &spec->vmaster_mute.sw_kctl); - if (err < 0) - return err; - - if (spec->gpio_led) { - spec->vmaster_mute.hook = stac92xx_vmaster_hook; - err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true); - if (err < 0) - return err; - } - - if (spec->aloopback_ctl && - snd_hda_get_bool_hint(codec, "loopback") == 1) { - err = snd_hda_add_new_ctls(codec, spec->aloopback_ctl); - if (err < 0) - return err; - } - - stac92xx_free_kctls(codec); /* no longer needed */ - - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); - if (err < 0) - return err; - - return 0; -} - -static const unsigned int ref9200_pin_configs[8] = { - 0x01c47010, 0x01447010, 0x0221401f, 0x01114010, - 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, -}; - -static const unsigned int gateway9200_m4_pin_configs[8] = { - 0x400000fe, 0x404500f4, 0x400100f0, 0x90110010, - 0x400100f1, 0x02a1902e, 0x500000f2, 0x500000f3, -}; -static const unsigned int gateway9200_m4_2_pin_configs[8] = { - 0x400000fe, 0x404500f4, 0x400100f0, 0x90110010, - 0x400100f1, 0x02a1902e, 0x500000f2, 0x500000f3, -}; - -/* - STAC 9200 pin configs for - 102801A8 - 102801DE - 102801E8 -*/ -static const unsigned int dell9200_d21_pin_configs[8] = { - 0x400001f0, 0x400001f1, 0x02214030, 0x01014010, - 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, -}; - -/* - STAC 9200 pin configs for - 102801C0 - 102801C1 -*/ -static const unsigned int dell9200_d22_pin_configs[8] = { - 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010, - 0x01813020, 0x02a19021, 0x90100140, 0x400001f2, -}; - -/* - STAC 9200 pin configs for - 102801C4 (Dell Dimension E310) - 102801C5 - 102801C7 - 102801D9 - 102801DA - 102801E3 -*/ -static const unsigned int dell9200_d23_pin_configs[8] = { - 0x400001f0, 0x400001f1, 0x0221401f, 0x01014010, - 0x01813020, 0x01a19021, 0x90100140, 0x400001f2, -}; - - -/* - STAC 9200-32 pin configs for - 102801B5 (Dell Inspiron 630m) - 102801D8 (Dell Inspiron 640m) -*/ -static const unsigned int dell9200_m21_pin_configs[8] = { - 0x40c003fa, 0x03441340, 0x0321121f, 0x90170310, - 0x408003fb, 0x03a11020, 0x401003fc, 0x403003fd, -}; - -/* - STAC 9200-32 pin configs for - 102801C2 (Dell Latitude D620) - 102801C8 - 102801CC (Dell Latitude D820) - 102801D4 - 102801D6 -*/ -static const unsigned int dell9200_m22_pin_configs[8] = { - 0x40c003fa, 0x0144131f, 0x0321121f, 0x90170310, - 0x90a70321, 0x03a11020, 0x401003fb, 0x40f000fc, -}; - -/* - STAC 9200-32 pin configs for - 102801CE (Dell XPS M1710) - 102801CF (Dell Precision M90) -*/ -static const unsigned int dell9200_m23_pin_configs[8] = { - 0x40c003fa, 0x01441340, 0x0421421f, 0x90170310, - 0x408003fb, 0x04a1102e, 0x90170311, 0x403003fc, -}; - -/* - STAC 9200-32 pin configs for - 102801C9 - 102801CA - 102801CB (Dell Latitude 120L) - 102801D3 -*/ -static const unsigned int dell9200_m24_pin_configs[8] = { - 0x40c003fa, 0x404003fb, 0x0321121f, 0x90170310, - 0x408003fc, 0x03a11020, 0x401003fd, 0x403003fe, -}; - -/* - STAC 9200-32 pin configs for - 102801BD (Dell Inspiron E1505n) - 102801EE - 102801EF -*/ -static const unsigned int dell9200_m25_pin_configs[8] = { - 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310, - 0x408003fb, 0x04a11020, 0x401003fc, 0x403003fd, -}; - -/* - STAC 9200-32 pin configs for - 102801F5 (Dell Inspiron 1501) - 102801F6 -*/ -static const unsigned int dell9200_m26_pin_configs[8] = { - 0x40c003fa, 0x404003fb, 0x0421121f, 0x90170310, - 0x408003fc, 0x04a11020, 0x401003fd, 0x403003fe, -}; - -/* - STAC 9200-32 - 102801CD (Dell Inspiron E1705/9400) -*/ -static const unsigned int dell9200_m27_pin_configs[8] = { - 0x40c003fa, 0x01441340, 0x0421121f, 0x90170310, - 0x90170310, 0x04a11020, 0x90170310, 0x40f003fc, -}; - -static const unsigned int oqo9200_pin_configs[8] = { - 0x40c000f0, 0x404000f1, 0x0221121f, 0x02211210, - 0x90170111, 0x90a70120, 0x400000f2, 0x400000f3, -}; - - -static const unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { - [STAC_REF] = ref9200_pin_configs, - [STAC_9200_OQO] = oqo9200_pin_configs, - [STAC_9200_DELL_D21] = dell9200_d21_pin_configs, - [STAC_9200_DELL_D22] = dell9200_d22_pin_configs, - [STAC_9200_DELL_D23] = dell9200_d23_pin_configs, - [STAC_9200_DELL_M21] = dell9200_m21_pin_configs, - [STAC_9200_DELL_M22] = dell9200_m22_pin_configs, - [STAC_9200_DELL_M23] = dell9200_m23_pin_configs, - [STAC_9200_DELL_M24] = dell9200_m24_pin_configs, - [STAC_9200_DELL_M25] = dell9200_m25_pin_configs, - [STAC_9200_DELL_M26] = dell9200_m26_pin_configs, - [STAC_9200_DELL_M27] = dell9200_m27_pin_configs, - [STAC_9200_M4] = gateway9200_m4_pin_configs, - [STAC_9200_M4_2] = gateway9200_m4_2_pin_configs, - [STAC_9200_PANASONIC] = ref9200_pin_configs, -}; - -static const char * const stac9200_models[STAC_9200_MODELS] = { - [STAC_AUTO] = "auto", - [STAC_REF] = "ref", - [STAC_9200_OQO] = "oqo", - [STAC_9200_DELL_D21] = "dell-d21", - [STAC_9200_DELL_D22] = "dell-d22", - [STAC_9200_DELL_D23] = "dell-d23", - [STAC_9200_DELL_M21] = "dell-m21", - [STAC_9200_DELL_M22] = "dell-m22", - [STAC_9200_DELL_M23] = "dell-m23", - [STAC_9200_DELL_M24] = "dell-m24", - [STAC_9200_DELL_M25] = "dell-m25", - [STAC_9200_DELL_M26] = "dell-m26", - [STAC_9200_DELL_M27] = "dell-m27", - [STAC_9200_M4] = "gateway-m4", - [STAC_9200_M4_2] = "gateway-m4-2", - [STAC_9200_PANASONIC] = "panasonic", -}; - -static const struct snd_pci_quirk stac9200_cfg_tbl[] = { - /* SigmaTel reference board */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, - "DFI LanParty", STAC_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, - "DFI LanParty", STAC_REF), - /* Dell laptops have BIOS problem */ - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a8, - "unknown Dell", STAC_9200_DELL_D21), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5, - "Dell Inspiron 630m", STAC_9200_DELL_M21), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bd, - "Dell Inspiron E1505n", STAC_9200_DELL_M25), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c0, - "unknown Dell", STAC_9200_DELL_D22), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c1, - "unknown Dell", STAC_9200_DELL_D22), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2, - "Dell Latitude D620", STAC_9200_DELL_M22), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c5, - "unknown Dell", STAC_9200_DELL_D23), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c7, - "unknown Dell", STAC_9200_DELL_D23), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c8, - "unknown Dell", STAC_9200_DELL_M22), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c9, - "unknown Dell", STAC_9200_DELL_M24), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ca, - "unknown Dell", STAC_9200_DELL_M24), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb, - "Dell Latitude 120L", STAC_9200_DELL_M24), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc, - "Dell Latitude D820", STAC_9200_DELL_M22), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd, - "Dell Inspiron E1705/9400", STAC_9200_DELL_M27), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce, - "Dell XPS M1710", STAC_9200_DELL_M23), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf, - "Dell Precision M90", STAC_9200_DELL_M23), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d3, - "unknown Dell", STAC_9200_DELL_M22), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d4, - "unknown Dell", STAC_9200_DELL_M22), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6, - "unknown Dell", STAC_9200_DELL_M22), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8, - "Dell Inspiron 640m", STAC_9200_DELL_M21), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d9, - "unknown Dell", STAC_9200_DELL_D23), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01da, - "unknown Dell", STAC_9200_DELL_D23), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01de, - "unknown Dell", STAC_9200_DELL_D21), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e3, - "unknown Dell", STAC_9200_DELL_D23), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01e8, - "unknown Dell", STAC_9200_DELL_D21), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ee, - "unknown Dell", STAC_9200_DELL_M25), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ef, - "unknown Dell", STAC_9200_DELL_M25), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5, - "Dell Inspiron 1501", STAC_9200_DELL_M26), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, - "unknown Dell", STAC_9200_DELL_M26), - /* Panasonic */ - SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC), - /* Gateway machines needs EAPD to be set on resume */ - SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_M4), - SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*", STAC_9200_M4_2), - SND_PCI_QUIRK(0x107b, 0x0318, "Gateway ML3019, MT3707", STAC_9200_M4_2), - /* OQO Mobile */ - SND_PCI_QUIRK(0x1106, 0x3288, "OQO Model 2", STAC_9200_OQO), - {} /* terminator */ -}; - -static const unsigned int ref925x_pin_configs[8] = { - 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021, - 0x90a70320, 0x02214210, 0x01019020, 0x9033032e, -}; - -static const unsigned int stac925xM1_pin_configs[8] = { - 0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020, - 0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e, -}; - -static const unsigned int stac925xM1_2_pin_configs[8] = { - 0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020, - 0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e, -}; - -static const unsigned int stac925xM2_pin_configs[8] = { - 0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020, - 0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e, -}; - -static const unsigned int stac925xM2_2_pin_configs[8] = { - 0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020, - 0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e, -}; - -static const unsigned int stac925xM3_pin_configs[8] = { - 0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020, - 0x40a000f0, 0x90100210, 0x400003f1, 0x503303f3, -}; - -static const unsigned int stac925xM5_pin_configs[8] = { - 0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020, - 0x40a000f0, 0x90100210, 0x400003f1, 0x9033032e, -}; - -static const unsigned int stac925xM6_pin_configs[8] = { - 0x40c003f4, 0x424503f2, 0x400000f3, 0x02a19020, - 0x40a000f0, 0x90100210, 0x400003f1, 0x90330320, -}; - -static const unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = { - [STAC_REF] = ref925x_pin_configs, - [STAC_M1] = stac925xM1_pin_configs, - [STAC_M1_2] = stac925xM1_2_pin_configs, - [STAC_M2] = stac925xM2_pin_configs, - [STAC_M2_2] = stac925xM2_2_pin_configs, - [STAC_M3] = stac925xM3_pin_configs, - [STAC_M5] = stac925xM5_pin_configs, - [STAC_M6] = stac925xM6_pin_configs, -}; - -static const char * const stac925x_models[STAC_925x_MODELS] = { - [STAC_925x_AUTO] = "auto", - [STAC_REF] = "ref", - [STAC_M1] = "m1", - [STAC_M1_2] = "m1-2", - [STAC_M2] = "m2", - [STAC_M2_2] = "m2-2", - [STAC_M3] = "m3", - [STAC_M5] = "m5", - [STAC_M6] = "m6", -}; - -static const struct snd_pci_quirk stac925x_codec_id_cfg_tbl[] = { - SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_M2), - SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_M5), - SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_M1), - SND_PCI_QUIRK(0x107b, 0x0681, "Gateway NX860", STAC_M2), - SND_PCI_QUIRK(0x107b, 0x0367, "Gateway MX6453", STAC_M1_2), - /* Not sure about the brand name for those */ - SND_PCI_QUIRK(0x107b, 0x0281, "Gateway mobile", STAC_M1), - SND_PCI_QUIRK(0x107b, 0x0507, "Gateway mobile", STAC_M3), - SND_PCI_QUIRK(0x107b, 0x0281, "Gateway mobile", STAC_M6), - SND_PCI_QUIRK(0x107b, 0x0685, "Gateway mobile", STAC_M2_2), - {} /* terminator */ -}; - -static const struct snd_pci_quirk stac925x_cfg_tbl[] = { - /* SigmaTel reference board */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_REF), - SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF), - - /* Default table for unknown ID */ - SND_PCI_QUIRK(0x1002, 0x437b, "Gateway mobile", STAC_M2_2), - - {} /* terminator */ -}; - -static const unsigned int ref92hd73xx_pin_configs[13] = { - 0x02214030, 0x02a19040, 0x01a19020, 0x02214030, - 0x0181302e, 0x01014010, 0x01014020, 0x01014030, - 0x02319040, 0x90a000f0, 0x90a000f0, 0x01452050, - 0x01452050, -}; - -static const unsigned int dell_m6_pin_configs[13] = { - 0x0321101f, 0x4f00000f, 0x4f0000f0, 0x90170110, - 0x03a11020, 0x0321101f, 0x4f0000f0, 0x4f0000f0, - 0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0, - 0x4f0000f0, -}; - -static const unsigned int alienware_m17x_pin_configs[13] = { - 0x0321101f, 0x0321101f, 0x03a11020, 0x03014020, - 0x90170110, 0x4f0000f0, 0x4f0000f0, 0x4f0000f0, - 0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0, - 0x904601b0, -}; - -static const unsigned int intel_dg45id_pin_configs[13] = { - 0x02214230, 0x02A19240, 0x01013214, 0x01014210, - 0x01A19250, 0x01011212, 0x01016211 -}; - -static const unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { - [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, - [STAC_DELL_M6_AMIC] = dell_m6_pin_configs, - [STAC_DELL_M6_DMIC] = dell_m6_pin_configs, - [STAC_DELL_M6_BOTH] = dell_m6_pin_configs, - [STAC_DELL_EQ] = dell_m6_pin_configs, - [STAC_ALIENWARE_M17X] = alienware_m17x_pin_configs, - [STAC_92HD73XX_INTEL] = intel_dg45id_pin_configs, -}; - -static const char * const stac92hd73xx_models[STAC_92HD73XX_MODELS] = { - [STAC_92HD73XX_AUTO] = "auto", - [STAC_92HD73XX_NO_JD] = "no-jd", - [STAC_92HD73XX_REF] = "ref", - [STAC_92HD73XX_INTEL] = "intel", - [STAC_DELL_M6_AMIC] = "dell-m6-amic", - [STAC_DELL_M6_DMIC] = "dell-m6-dmic", - [STAC_DELL_M6_BOTH] = "dell-m6", - [STAC_DELL_EQ] = "dell-eq", - [STAC_ALIENWARE_M17X] = "alienware", -}; - -static const struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { - /* SigmaTel reference board */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, - "DFI LanParty", STAC_92HD73XX_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, - "DFI LanParty", STAC_92HD73XX_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002, - "Intel DG45ID", STAC_92HD73XX_INTEL), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003, - "Intel DG45FC", STAC_92HD73XX_INTEL), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, - "Dell Studio 1535", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, - "unknown Dell", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0256, - "unknown Dell", STAC_DELL_M6_BOTH), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0257, - "unknown Dell", STAC_DELL_M6_BOTH), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025e, - "unknown Dell", STAC_DELL_M6_AMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x025f, - "unknown Dell", STAC_DELL_M6_AMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0271, - "unknown Dell", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0272, - "unknown Dell", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x029f, - "Dell Studio 1537", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0, - "Dell Studio 17", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be, - "Dell Studio 1555", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd, - "Dell Studio 1557", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe, - "Dell Studio XPS 1645", STAC_DELL_M6_DMIC), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413, - "Dell Studio 1558", STAC_DELL_M6_DMIC), - {} /* terminator */ -}; - -static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = { - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1, - "Alienware M17x", STAC_ALIENWARE_M17X), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, - "Alienware M17x", STAC_ALIENWARE_M17X), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, - "Alienware M17x R3", STAC_DELL_EQ), - {} /* terminator */ -}; - -static const unsigned int ref92hd83xxx_pin_configs[10] = { - 0x02214030, 0x02211010, 0x02a19020, 0x02170130, - 0x01014050, 0x01819040, 0x01014020, 0x90a3014e, - 0x01451160, 0x98560170, -}; - -static const unsigned int dell_s14_pin_configs[10] = { - 0x0221403f, 0x0221101f, 0x02a19020, 0x90170110, - 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a60160, - 0x40f000f0, 0x40f000f0, -}; - -static const unsigned int dell_vostro_3500_pin_configs[10] = { - 0x02a11020, 0x0221101f, 0x400000f0, 0x90170110, - 0x400000f1, 0x400000f2, 0x400000f3, 0x90a60160, - 0x400000f4, 0x400000f5, -}; - -static const unsigned int hp_dv7_4000_pin_configs[10] = { - 0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110, - 0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140, - 0x40f000f0, 0x40f000f0, -}; - -static const unsigned int hp_zephyr_pin_configs[10] = { - 0x01813050, 0x0421201f, 0x04a1205e, 0x96130310, - 0x96130310, 0x0101401f, 0x1111611f, 0xd5a30130, - 0, 0, -}; - -static const unsigned int hp_cNB11_intquad_pin_configs[10] = { - 0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110, - 0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130, - 0x40f000f0, 0x40f000f0, -}; - -static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { - [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, - [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, - [STAC_DELL_S14] = dell_s14_pin_configs, - [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, - [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, - [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, - [STAC_HP_ZEPHYR] = hp_zephyr_pin_configs, -}; - -static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { - [STAC_92HD83XXX_AUTO] = "auto", - [STAC_92HD83XXX_REF] = "ref", - [STAC_92HD83XXX_PWR_REF] = "mic-ref", - [STAC_DELL_S14] = "dell-s14", - [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", - [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", - [STAC_HP_DV7_4000] = "hp-dv7-4000", - [STAC_HP_ZEPHYR] = "hp-zephyr", -}; - -static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { - /* SigmaTel reference board */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, - "DFI LanParty", STAC_92HD83XXX_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, - "DFI LanParty", STAC_92HD83XXX_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, - "unknown Dell", STAC_DELL_S14), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028, - "Dell Vostro 3500", STAC_DELL_VOSTRO_3500), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355B, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355C, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355D, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355E, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x355F, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3560, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358B, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358C, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x358D, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3591, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3592, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, - "HP", STAC_HP_ZEPHYR), - {} /* terminator */ -}; - -static const struct snd_pci_quirk stac92hd83xxx_codec_id_cfg_tbl[] = { - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, - "HP", STAC_HP_ZEPHYR), - {} /* terminator */ -}; - -static const unsigned int ref92hd71bxx_pin_configs[STAC92HD71BXX_NUM_PINS] = { - 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, - 0x0181302e, 0x01014010, 0x01019020, 0x90a000f0, - 0x90a000f0, 0x01452050, 0x01452050, 0x00000000, - 0x00000000 -}; - -static const unsigned int dell_m4_1_pin_configs[STAC92HD71BXX_NUM_PINS] = { - 0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110, - 0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0, - 0x40f000f0, 0x4f0000f0, 0x4f0000f0, 0x00000000, - 0x00000000 -}; - -static const unsigned int dell_m4_2_pin_configs[STAC92HD71BXX_NUM_PINS] = { - 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, - 0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0, - 0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000, - 0x00000000 -}; - -static const unsigned int dell_m4_3_pin_configs[STAC92HD71BXX_NUM_PINS] = { - 0x0421101f, 0x04a11221, 0x90a70330, 0x90170110, - 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a000f0, - 0x40f000f0, 0x044413b0, 0x044413b0, 0x00000000, - 0x00000000 -}; - -static const unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { - [STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs, - [STAC_DELL_M4_1] = dell_m4_1_pin_configs, - [STAC_DELL_M4_2] = dell_m4_2_pin_configs, - [STAC_DELL_M4_3] = dell_m4_3_pin_configs, - [STAC_HP_M4] = NULL, - [STAC_HP_DV4] = NULL, - [STAC_HP_DV5] = NULL, - [STAC_HP_HDX] = NULL, - [STAC_HP_DV4_1222NR] = NULL, -}; - -static const char * const stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { - [STAC_92HD71BXX_AUTO] = "auto", - [STAC_92HD71BXX_REF] = "ref", - [STAC_DELL_M4_1] = "dell-m4-1", - [STAC_DELL_M4_2] = "dell-m4-2", - [STAC_DELL_M4_3] = "dell-m4-3", - [STAC_HP_M4] = "hp-m4", - [STAC_HP_DV4] = "hp-dv4", - [STAC_HP_DV5] = "hp-dv5", - [STAC_HP_HDX] = "hp-hdx", - [STAC_HP_DV4_1222NR] = "hp-dv4-1222nr", -}; - -static const struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { - /* SigmaTel reference board */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, - "DFI LanParty", STAC_92HD71BXX_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, - "DFI LanParty", STAC_92HD71BXX_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fb, - "HP dv4-1222nr", STAC_HP_DV4_1222NR), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x1720, - "HP", STAC_HP_DV5), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, - "HP", STAC_HP_DV5), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, - "HP dv4-7", STAC_HP_DV4), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, - "HP dv4-7", STAC_HP_DV5), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, - "HP HDX", STAC_HP_HDX), /* HDX18 */ - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, - "HP mini 1000", STAC_HP_M4), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b, - "HP HDX", STAC_HP_HDX), /* HDX16 */ - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620, - "HP dv6", STAC_HP_DV5), - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061, - "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */ - SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x363e, - "HP DV6", STAC_HP_DV5), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, - "HP", STAC_HP_DV5), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, - "unknown Dell", STAC_DELL_M4_1), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0234, - "unknown Dell", STAC_DELL_M4_1), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0250, - "unknown Dell", STAC_DELL_M4_1), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024f, - "unknown Dell", STAC_DELL_M4_1), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x024d, - "unknown Dell", STAC_DELL_M4_1), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0251, - "unknown Dell", STAC_DELL_M4_1), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0277, - "unknown Dell", STAC_DELL_M4_1), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0263, - "unknown Dell", STAC_DELL_M4_2), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0265, - "unknown Dell", STAC_DELL_M4_2), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0262, - "unknown Dell", STAC_DELL_M4_2), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0264, - "unknown Dell", STAC_DELL_M4_2), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02aa, - "unknown Dell", STAC_DELL_M4_3), - {} /* terminator */ -}; - -static const unsigned int ref922x_pin_configs[10] = { - 0x01014010, 0x01016011, 0x01012012, 0x0221401f, - 0x01813122, 0x01011014, 0x01441030, 0x01c41030, - 0x40000100, 0x40000100, -}; - -/* - STAC 922X pin configs for - 102801A7 - 102801AB - 102801A9 - 102801D1 - 102801D2 -*/ -static const unsigned int dell_922x_d81_pin_configs[10] = { - 0x02214030, 0x01a19021, 0x01111012, 0x01114010, - 0x02a19020, 0x01117011, 0x400001f0, 0x400001f1, - 0x01813122, 0x400001f2, -}; - -/* - STAC 922X pin configs for - 102801AC - 102801D0 -*/ -static const unsigned int dell_922x_d82_pin_configs[10] = { - 0x02214030, 0x01a19021, 0x01111012, 0x01114010, - 0x02a19020, 0x01117011, 0x01451140, 0x400001f0, - 0x01813122, 0x400001f1, -}; - -/* - STAC 922X pin configs for - 102801BF -*/ -static const unsigned int dell_922x_m81_pin_configs[10] = { - 0x0321101f, 0x01112024, 0x01111222, 0x91174220, - 0x03a11050, 0x01116221, 0x90a70330, 0x01452340, - 0x40C003f1, 0x405003f0, -}; - -/* - STAC 9221 A1 pin configs for - 102801D7 (Dell XPS M1210) -*/ -static const unsigned int dell_922x_m82_pin_configs[10] = { - 0x02211211, 0x408103ff, 0x02a1123e, 0x90100310, - 0x408003f1, 0x0221121f, 0x03451340, 0x40c003f2, - 0x508003f3, 0x405003f4, -}; - -static const unsigned int d945gtp3_pin_configs[10] = { - 0x0221401f, 0x01a19022, 0x01813021, 0x01014010, - 0x40000100, 0x40000100, 0x40000100, 0x40000100, - 0x02a19120, 0x40000100, -}; - -static const unsigned int d945gtp5_pin_configs[10] = { - 0x0221401f, 0x01011012, 0x01813024, 0x01014010, - 0x01a19021, 0x01016011, 0x01452130, 0x40000100, - 0x02a19320, 0x40000100, -}; - -static const unsigned int intel_mac_v1_pin_configs[10] = { - 0x0121e21f, 0x400000ff, 0x9017e110, 0x400000fd, - 0x400000fe, 0x0181e020, 0x1145e030, 0x11c5e240, - 0x400000fc, 0x400000fb, -}; - -static const unsigned int intel_mac_v2_pin_configs[10] = { - 0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd, - 0x400000fe, 0x0181e020, 0x1145e230, 0x500000fa, - 0x400000fc, 0x400000fb, -}; - -static const unsigned int intel_mac_v3_pin_configs[10] = { - 0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd, - 0x400000fe, 0x0181e020, 0x1145e230, 0x11c5e240, - 0x400000fc, 0x400000fb, -}; - -static const unsigned int intel_mac_v4_pin_configs[10] = { - 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f, - 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240, - 0x400000fc, 0x400000fb, -}; - -static const unsigned int intel_mac_v5_pin_configs[10] = { - 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f, - 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240, - 0x400000fc, 0x400000fb, -}; - -static const unsigned int ecs202_pin_configs[10] = { - 0x0221401f, 0x02a19020, 0x01a19020, 0x01114010, - 0x408000f0, 0x01813022, 0x074510a0, 0x40c400f1, - 0x9037012e, 0x40e000f2, -}; - -static const unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { - [STAC_D945_REF] = ref922x_pin_configs, - [STAC_D945GTP3] = d945gtp3_pin_configs, - [STAC_D945GTP5] = d945gtp5_pin_configs, - [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs, - [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs, - [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs, - [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs, - [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs, - [STAC_INTEL_MAC_AUTO] = intel_mac_v3_pin_configs, - /* for backward compatibility */ - [STAC_MACMINI] = intel_mac_v3_pin_configs, - [STAC_MACBOOK] = intel_mac_v5_pin_configs, - [STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs, - [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs, - [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs, - [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs, - [STAC_ECS_202] = ecs202_pin_configs, - [STAC_922X_DELL_D81] = dell_922x_d81_pin_configs, - [STAC_922X_DELL_D82] = dell_922x_d82_pin_configs, - [STAC_922X_DELL_M81] = dell_922x_m81_pin_configs, - [STAC_922X_DELL_M82] = dell_922x_m82_pin_configs, -}; - -static const char * const stac922x_models[STAC_922X_MODELS] = { - [STAC_922X_AUTO] = "auto", - [STAC_D945_REF] = "ref", - [STAC_D945GTP5] = "5stack", - [STAC_D945GTP3] = "3stack", - [STAC_INTEL_MAC_V1] = "intel-mac-v1", - [STAC_INTEL_MAC_V2] = "intel-mac-v2", - [STAC_INTEL_MAC_V3] = "intel-mac-v3", - [STAC_INTEL_MAC_V4] = "intel-mac-v4", - [STAC_INTEL_MAC_V5] = "intel-mac-v5", - [STAC_INTEL_MAC_AUTO] = "intel-mac-auto", - /* for backward compatibility */ - [STAC_MACMINI] = "macmini", - [STAC_MACBOOK] = "macbook", - [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", - [STAC_MACBOOK_PRO_V2] = "macbook-pro", - [STAC_IMAC_INTEL] = "imac-intel", - [STAC_IMAC_INTEL_20] = "imac-intel-20", - [STAC_ECS_202] = "ecs202", - [STAC_922X_DELL_D81] = "dell-d81", - [STAC_922X_DELL_D82] = "dell-d82", - [STAC_922X_DELL_M81] = "dell-m81", - [STAC_922X_DELL_M82] = "dell-m82", -}; - -static const struct snd_pci_quirk stac922x_cfg_tbl[] = { - /* SigmaTel reference board */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, - "DFI LanParty", STAC_D945_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, - "DFI LanParty", STAC_D945_REF), - /* Intel 945G based systems */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0202, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0606, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0601, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0111, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1115, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1116, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1117, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1118, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1119, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8826, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5049, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5055, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5048, - "Intel D945G", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0110, - "Intel D945G", STAC_D945GTP3), - /* Intel D945G 5-stack systems */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0404, - "Intel D945G", STAC_D945GTP5), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0303, - "Intel D945G", STAC_D945GTP5), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0013, - "Intel D945G", STAC_D945GTP5), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0417, - "Intel D945G", STAC_D945GTP5), - /* Intel 945P based systems */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0b0b, - "Intel D945P", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0112, - "Intel D945P", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0d0d, - "Intel D945P", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0909, - "Intel D945P", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0505, - "Intel D945P", STAC_D945GTP3), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707, - "Intel D945P", STAC_D945GTP5), - /* other intel */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0204, - "Intel D945", STAC_D945_REF), - /* other systems */ - /* Apple Intel Mac (Mac Mini, MacBook, MacBook Pro...) */ - SND_PCI_QUIRK(0x8384, 0x7680, - "Mac", STAC_INTEL_MAC_AUTO), - /* Dell systems */ - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a7, - "unknown Dell", STAC_922X_DELL_D81), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01a9, - "unknown Dell", STAC_922X_DELL_D81), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ab, - "unknown Dell", STAC_922X_DELL_D81), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ac, - "unknown Dell", STAC_922X_DELL_D82), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01bf, - "unknown Dell", STAC_922X_DELL_M81), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d0, - "unknown Dell", STAC_922X_DELL_D82), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d1, - "unknown Dell", STAC_922X_DELL_D81), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d2, - "unknown Dell", STAC_922X_DELL_D81), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d7, - "Dell XPS M1210", STAC_922X_DELL_M82), - /* ECS/PC Chips boards */ - SND_PCI_QUIRK_MASK(0x1019, 0xf000, 0x2000, - "ECS/PC chips", STAC_ECS_202), - {} /* terminator */ -}; - -static const unsigned int ref927x_pin_configs[14] = { - 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, - 0x01a19040, 0x01011012, 0x01016011, 0x0101201f, - 0x183301f0, 0x18a001f0, 0x18a001f0, 0x01442070, - 0x01c42190, 0x40000100, -}; - -static const unsigned int d965_3st_pin_configs[14] = { - 0x0221401f, 0x02a19120, 0x40000100, 0x01014011, - 0x01a19021, 0x01813024, 0x40000100, 0x40000100, - 0x40000100, 0x40000100, 0x40000100, 0x40000100, - 0x40000100, 0x40000100 -}; - -static const unsigned int d965_5st_pin_configs[14] = { - 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, - 0x01a19040, 0x01011012, 0x01016011, 0x40000100, - 0x40000100, 0x40000100, 0x40000100, 0x01442070, - 0x40000100, 0x40000100 -}; - -static const unsigned int d965_5st_no_fp_pin_configs[14] = { - 0x40000100, 0x40000100, 0x0181304e, 0x01014010, - 0x01a19040, 0x01011012, 0x01016011, 0x40000100, - 0x40000100, 0x40000100, 0x40000100, 0x01442070, - 0x40000100, 0x40000100 -}; - -static const unsigned int dell_3st_pin_configs[14] = { - 0x02211230, 0x02a11220, 0x01a19040, 0x01114210, - 0x01111212, 0x01116211, 0x01813050, 0x01112214, - 0x403003fa, 0x90a60040, 0x90a60040, 0x404003fb, - 0x40c003fc, 0x40000100 -}; - -static const unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { - [STAC_D965_REF_NO_JD] = ref927x_pin_configs, - [STAC_D965_REF] = ref927x_pin_configs, - [STAC_D965_3ST] = d965_3st_pin_configs, - [STAC_D965_5ST] = d965_5st_pin_configs, - [STAC_D965_5ST_NO_FP] = d965_5st_no_fp_pin_configs, - [STAC_DELL_3ST] = dell_3st_pin_configs, - [STAC_DELL_BIOS] = NULL, - [STAC_927X_VOLKNOB] = NULL, -}; - -static const char * const stac927x_models[STAC_927X_MODELS] = { - [STAC_927X_AUTO] = "auto", - [STAC_D965_REF_NO_JD] = "ref-no-jd", - [STAC_D965_REF] = "ref", - [STAC_D965_3ST] = "3stack", - [STAC_D965_5ST] = "5stack", - [STAC_D965_5ST_NO_FP] = "5stack-no-fp", - [STAC_DELL_3ST] = "dell-3stack", - [STAC_DELL_BIOS] = "dell-bios", - [STAC_927X_VOLKNOB] = "volknob", -}; - -static const struct snd_pci_quirk stac927x_cfg_tbl[] = { - /* SigmaTel reference board */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, - "DFI LanParty", STAC_D965_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, - "DFI LanParty", STAC_D965_REF), - /* Intel 946 based systems */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST), - /* 965 based 3 stack systems */ - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2100, - "Intel D965", STAC_D965_3ST), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2000, - "Intel D965", STAC_D965_3ST), - /* Dell 3 stack systems */ - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST), - /* Dell 3 stack systems with verb table in BIOS */ - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS), - /* 965 based 5 stack systems */ - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2300, - "Intel D965", STAC_D965_5ST), - SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500, - "Intel D965", STAC_D965_5ST), - /* volume-knob fixes */ - SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB), - {} /* terminator */ -}; - -static const unsigned int ref9205_pin_configs[12] = { - 0x40000100, 0x40000100, 0x01016011, 0x01014010, - 0x01813122, 0x01a19021, 0x01019020, 0x40000100, - 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 -}; - -/* - STAC 9205 pin configs for - 102801F1 - 102801F2 - 102801FC - 102801FD - 10280204 - 1028021F - 10280228 (Dell Vostro 1500) - 10280229 (Dell Vostro 1700) -*/ -static const unsigned int dell_9205_m42_pin_configs[12] = { - 0x0321101F, 0x03A11020, 0x400003FA, 0x90170310, - 0x400003FB, 0x400003FC, 0x400003FD, 0x40F000F9, - 0x90A60330, 0x400003FF, 0x0144131F, 0x40C003FE, -}; - -/* - STAC 9205 pin configs for - 102801F9 - 102801FA - 102801FE - 102801FF (Dell Precision M4300) - 10280206 - 10280200 - 10280201 -*/ -static const unsigned int dell_9205_m43_pin_configs[12] = { - 0x0321101f, 0x03a11020, 0x90a70330, 0x90170310, - 0x400000fe, 0x400000ff, 0x400000fd, 0x40f000f9, - 0x400000fa, 0x400000fc, 0x0144131f, 0x40c003f8, -}; - -static const unsigned int dell_9205_m44_pin_configs[12] = { - 0x0421101f, 0x04a11020, 0x400003fa, 0x90170310, - 0x400003fb, 0x400003fc, 0x400003fd, 0x400003f9, - 0x90a60330, 0x400003ff, 0x01441340, 0x40c003fe, -}; - -static const unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { - [STAC_9205_REF] = ref9205_pin_configs, - [STAC_9205_DELL_M42] = dell_9205_m42_pin_configs, - [STAC_9205_DELL_M43] = dell_9205_m43_pin_configs, - [STAC_9205_DELL_M44] = dell_9205_m44_pin_configs, - [STAC_9205_EAPD] = NULL, -}; - -static const char * const stac9205_models[STAC_9205_MODELS] = { - [STAC_9205_AUTO] = "auto", - [STAC_9205_REF] = "ref", - [STAC_9205_DELL_M42] = "dell-m42", - [STAC_9205_DELL_M43] = "dell-m43", - [STAC_9205_DELL_M44] = "dell-m44", - [STAC_9205_EAPD] = "eapd", -}; - -static const struct snd_pci_quirk stac9205_cfg_tbl[] = { - /* SigmaTel reference board */ - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, - "DFI LanParty", STAC_9205_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xfb30, - "SigmaTel", STAC_9205_REF), - SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, - "DFI LanParty", STAC_9205_REF), - /* Dell */ - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1, - "unknown Dell", STAC_9205_DELL_M42), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2, - "unknown Dell", STAC_9205_DELL_M42), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8, - "Dell Precision", STAC_9205_DELL_M43), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9, - "Dell Precision", STAC_9205_DELL_M43), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa, - "Dell Precision", STAC_9205_DELL_M43), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc, - "unknown Dell", STAC_9205_DELL_M42), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd, - "unknown Dell", STAC_9205_DELL_M42), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fe, - "Dell Precision", STAC_9205_DELL_M43), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff, - "Dell Precision M4300", STAC_9205_DELL_M43), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204, - "unknown Dell", STAC_9205_DELL_M42), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206, - "Dell Precision", STAC_9205_DELL_M43), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b, - "Dell Precision", STAC_9205_DELL_M43), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c, - "Dell Precision", STAC_9205_DELL_M43), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, - "Dell Inspiron", STAC_9205_DELL_M44), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, - "Dell Vostro 1500", STAC_9205_DELL_M42), - SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0229, - "Dell Vostro 1700", STAC_9205_DELL_M42), - /* Gateway */ - SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD), - SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), - {} /* terminator */ -}; - -static void stac92xx_set_config_regs(struct hda_codec *codec, - const unsigned int *pincfgs) -{ - int i; - struct sigmatel_spec *spec = codec->spec; - - if (!pincfgs) - return; - - for (i = 0; i < spec->num_pins; i++) - if (spec->pin_nids[i] && pincfgs[i]) - snd_hda_codec_set_pincfg(codec, spec->pin_nids[i], - pincfgs[i]); -} - -/* - * Analog playback callbacks - */ -static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - if (spec->stream_delay) - msleep(spec->stream_delay); - return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); -} - -static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, format, substream); -} - -static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); -} - -/* - * Digital playback callbacks - */ -static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, - stream_tag, format, substream); -} - -static int stac92xx_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); -} - - -/* - * Analog capture callbacks - */ -static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid = spec->adc_nids[substream->number]; - - if (spec->powerdown_adcs) { - msleep(40); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D0); - } - snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); - return 0; -} - -static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid = spec->adc_nids[substream->number]; - - snd_hda_codec_cleanup_stream(codec, nid); - if (spec->powerdown_adcs) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - return 0; -} - -static const struct hda_pcm_stream stac92xx_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in stac92xx_build_pcms */ - .ops = { - .open = stac92xx_dig_playback_pcm_open, - .close = stac92xx_dig_playback_pcm_close, - .prepare = stac92xx_dig_playback_pcm_prepare, - .cleanup = stac92xx_dig_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream stac92xx_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in stac92xx_build_pcms */ -}; - -static const struct hda_pcm_stream stac92xx_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 8, - .nid = 0x02, /* NID to query formats and rates */ - .ops = { - .open = stac92xx_playback_pcm_open, - .prepare = stac92xx_playback_pcm_prepare, - .cleanup = stac92xx_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - .nid = 0x06, /* NID to query formats and rates */ - .ops = { - .open = stac92xx_playback_pcm_open, - .prepare = stac92xx_playback_pcm_prepare, - .cleanup = stac92xx_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream stac92xx_pcm_analog_capture = { - .channels_min = 2, - .channels_max = 2, - /* NID + .substreams is set in stac92xx_build_pcms */ - .ops = { - .prepare = stac92xx_capture_pcm_prepare, - .cleanup = stac92xx_capture_pcm_cleanup - }, -}; - -static int stac92xx_build_pcms(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->num_pcms = 1; - codec->pcm_info = info; - - info->name = "STAC92xx Analog"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->multiout.dac_nids[0]; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; - info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adcs; - - if (spec->alt_switch) { - codec->num_pcms++; - info++; - info->name = "STAC92xx Analog Alt"; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_alt_playback; - } - - if (spec->multiout.dig_out_nid || spec->dig_in_nid) { - codec->num_pcms++; - info++; - info->name = "STAC92xx Digital"; - info->pcm_type = spec->autocfg.dig_out_type[0]; - if (spec->multiout.dig_out_nid) { - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; - } - if (spec->dig_in_nid) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; - } - } - - return 0; -} - -static unsigned int stac92xx_get_default_vref(struct hda_codec *codec, - hda_nid_t nid) -{ - unsigned int pincap = snd_hda_query_pin_caps(codec, nid); - pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; - if (pincap & AC_PINCAP_VREF_100) - return AC_PINCTL_VREF_100; - if (pincap & AC_PINCAP_VREF_80) - return AC_PINCTL_VREF_80; - if (pincap & AC_PINCAP_VREF_50) - return AC_PINCTL_VREF_50; - if (pincap & AC_PINCAP_VREF_GRD) - return AC_PINCTL_VREF_GRD; - return 0; -} - -static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) - -{ - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); -} - -#define stac92xx_hp_switch_info snd_ctl_boolean_mono_info - -static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - - ucontrol->value.integer.value[0] = !!spec->hp_switch; - return 0; -} - -static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid); - -static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - int nid = kcontrol->private_value; - - spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0; - - /* check to be sure that the ports are up to date with - * switch changes - */ - stac_issue_unsol_event(codec, nid); - - return 1; -} - -static int stac92xx_dc_bias_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int i; - static const char * const texts[] = { - "Mic In", "Line In", "Line Out" - }; - - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid = kcontrol->private_value; - - if (nid == spec->mic_switch || nid == spec->line_switch) - i = 3; - else - i = 2; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->value.enumerated.items = i; - uinfo->count = 1; - if (uinfo->value.enumerated.item >= i) - uinfo->value.enumerated.item = i-1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = kcontrol->private_value; - unsigned int vref = stac92xx_vref_get(codec, nid); - - if (vref == stac92xx_get_default_vref(codec, nid)) - ucontrol->value.enumerated.item[0] = 0; - else if (vref == AC_PINCTL_VREF_GRD) - ucontrol->value.enumerated.item[0] = 1; - else if (vref == AC_PINCTL_VREF_HIZ) - ucontrol->value.enumerated.item[0] = 2; - - return 0; -} - -static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int new_vref = 0; - int error; - hda_nid_t nid = kcontrol->private_value; - - if (ucontrol->value.enumerated.item[0] == 0) - new_vref = stac92xx_get_default_vref(codec, nid); - else if (ucontrol->value.enumerated.item[0] == 1) - new_vref = AC_PINCTL_VREF_GRD; - else if (ucontrol->value.enumerated.item[0] == 2) - new_vref = AC_PINCTL_VREF_HIZ; - else - return 0; - - if (new_vref != stac92xx_vref_get(codec, nid)) { - error = stac92xx_vref_set(codec, nid, new_vref); - return error; - } - - return 0; -} - -static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - char *texts[2]; - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - - if (kcontrol->private_value == spec->line_switch) - texts[0] = "Line In"; - else - texts[0] = "Mic In"; - texts[1] = "Line Out"; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->value.enumerated.items = 2; - uinfo->count = 1; - - if (uinfo->value.enumerated.item >= 2) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid = kcontrol->private_value; - int io_idx = (nid == spec->mic_switch) ? 1 : 0; - - ucontrol->value.enumerated.item[0] = spec->io_switch[io_idx]; - return 0; -} - -static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid = kcontrol->private_value; - int io_idx = (nid == spec->mic_switch) ? 1 : 0; - unsigned short val = !!ucontrol->value.enumerated.item[0]; - - spec->io_switch[io_idx] = val; - - if (val) - stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); - else { - unsigned int pinctl = AC_PINCTL_IN_EN; - if (io_idx) /* set VREF for mic */ - pinctl |= stac92xx_get_default_vref(codec, nid); - stac92xx_auto_set_pinctl(codec, nid, pinctl); - } - - /* check the auto-mute again: we need to mute/unmute the speaker - * appropriately according to the pin direction - */ - if (spec->hp_detect) - stac_issue_unsol_event(codec, nid); - - return 1; -} - -#define stac92xx_clfe_switch_info snd_ctl_boolean_mono_info - -static int stac92xx_clfe_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - - ucontrol->value.integer.value[0] = spec->clfe_swap; - return 0; -} - -static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid = kcontrol->private_value & 0xff; - unsigned int val = !!ucontrol->value.integer.value[0]; - - if (spec->clfe_swap == val) - return 0; - - spec->clfe_swap = val; - - snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, - spec->clfe_swap ? 0x4 : 0x0); - - return 1; -} - -#define STAC_CODEC_HP_SWITCH(xname) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = 0, \ - .info = stac92xx_hp_switch_info, \ - .get = stac92xx_hp_switch_get, \ - .put = stac92xx_hp_switch_put, \ - } - -#define STAC_CODEC_IO_SWITCH(xname, xpval) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = 0, \ - .info = stac92xx_io_switch_info, \ - .get = stac92xx_io_switch_get, \ - .put = stac92xx_io_switch_put, \ - .private_value = xpval, \ - } - -#define STAC_CODEC_CLFE_SWITCH(xname, xpval) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = 0, \ - .info = stac92xx_clfe_switch_info, \ - .get = stac92xx_clfe_switch_get, \ - .put = stac92xx_clfe_switch_put, \ - .private_value = xpval, \ - } - -enum { - STAC_CTL_WIDGET_VOL, - STAC_CTL_WIDGET_MUTE, - STAC_CTL_WIDGET_MUTE_BEEP, - STAC_CTL_WIDGET_MONO_MUX, - STAC_CTL_WIDGET_HP_SWITCH, - STAC_CTL_WIDGET_IO_SWITCH, - STAC_CTL_WIDGET_CLFE_SWITCH, - STAC_CTL_WIDGET_DC_BIAS -}; - -static const struct snd_kcontrol_new stac92xx_control_templates[] = { - HDA_CODEC_VOLUME(NULL, 0, 0, 0), - HDA_CODEC_MUTE(NULL, 0, 0, 0), - HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0), - STAC_MONO_MUX, - STAC_CODEC_HP_SWITCH(NULL), - STAC_CODEC_IO_SWITCH(NULL, 0), - STAC_CODEC_CLFE_SWITCH(NULL, 0), - DC_BIAS(NULL, 0, 0), -}; - -/* add dynamic controls */ -static struct snd_kcontrol_new * -stac_control_new(struct sigmatel_spec *spec, - const struct snd_kcontrol_new *ktemp, - const char *name, - unsigned int subdev) -{ - struct snd_kcontrol_new *knew; - - snd_array_init(&spec->kctls, sizeof(*knew), 32); - knew = snd_array_new(&spec->kctls); - if (!knew) - return NULL; - *knew = *ktemp; - knew->name = kstrdup(name, GFP_KERNEL); - if (!knew->name) { - /* roolback */ - memset(knew, 0, sizeof(*knew)); - spec->kctls.alloced--; - return NULL; - } - knew->subdevice = subdev; - return knew; -} - -static int stac92xx_add_control_temp(struct sigmatel_spec *spec, - const struct snd_kcontrol_new *ktemp, - int idx, const char *name, - unsigned long val) -{ - struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, - HDA_SUBDEV_AMP_FLAG); - if (!knew) - return -ENOMEM; - knew->index = idx; - knew->private_value = val; - return 0; -} - -static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec, - int type, int idx, const char *name, - unsigned long val) -{ - return stac92xx_add_control_temp(spec, - &stac92xx_control_templates[type], - idx, name, val); -} - - -/* add dynamic controls */ -static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type, - const char *name, unsigned long val) -{ - return stac92xx_add_control_idx(spec, type, 0, name, val); -} - -static const struct snd_kcontrol_new stac_input_src_temp = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, -}; - -static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, - hda_nid_t nid, int idx) -{ - int def_conf = snd_hda_codec_get_pincfg(codec, nid); - int control = 0; - struct sigmatel_spec *spec = codec->spec; - char name[22]; - - if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { - if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD - && nid == spec->line_switch) - control = STAC_CTL_WIDGET_IO_SWITCH; - else if (snd_hda_query_pin_caps(codec, nid) - & (AC_PINCAP_VREF_GRD << AC_PINCAP_VREF_SHIFT)) - control = STAC_CTL_WIDGET_DC_BIAS; - else if (nid == spec->mic_switch) - control = STAC_CTL_WIDGET_IO_SWITCH; - } - - if (control) { - snd_hda_get_pin_label(codec, nid, &spec->autocfg, - name, sizeof(name), NULL); - return stac92xx_add_control(codec->spec, control, - strcat(name, " Jack Mode"), nid); - } - - return 0; -} - -static int stac92xx_add_input_source(struct sigmatel_spec *spec) -{ - struct snd_kcontrol_new *knew; - struct hda_input_mux *imux = &spec->private_imux; - - if (spec->auto_mic) - return 0; /* no need for input source */ - if (!spec->num_adcs || imux->num_items <= 1) - return 0; /* no need for input source control */ - knew = stac_control_new(spec, &stac_input_src_temp, - stac_input_src_temp.name, 0); - if (!knew) - return -ENOMEM; - knew->count = spec->num_adcs; - return 0; -} - -/* check whether the line-input can be used as line-out */ -static hda_nid_t check_line_out_switch(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t nid; - unsigned int pincap; - int i; - - if (cfg->line_out_type != AUTO_PIN_LINE_OUT) - return 0; - for (i = 0; i < cfg->num_inputs; i++) { - if (cfg->inputs[i].type == AUTO_PIN_LINE_IN) { - nid = cfg->inputs[i].pin; - pincap = snd_hda_query_pin_caps(codec, nid); - if (pincap & AC_PINCAP_OUT) - return nid; - } - } - return 0; -} - -static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid); - -/* check whether the mic-input can be used as line-out */ -static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int def_conf, pincap; - int i; - - *dac = 0; - if (cfg->line_out_type != AUTO_PIN_LINE_OUT) - return 0; - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; - if (cfg->inputs[i].type != AUTO_PIN_MIC) - continue; - def_conf = snd_hda_codec_get_pincfg(codec, nid); - /* some laptops have an internal analog microphone - * which can't be used as a output */ - if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { - pincap = snd_hda_query_pin_caps(codec, nid); - if (pincap & AC_PINCAP_OUT) { - *dac = get_unassigned_dac(codec, nid); - if (*dac) - return nid; - } - } - } - return 0; -} - -static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) -{ - int i; - - for (i = 0; i < spec->multiout.num_dacs; i++) { - if (spec->multiout.dac_nids[i] == nid) - return 1; - } - - return 0; -} - -static int check_all_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) -{ - int i; - if (is_in_dac_nids(spec, nid)) - return 1; - for (i = 0; i < spec->autocfg.hp_outs; i++) - if (spec->hp_dacs[i] == nid) - return 1; - for (i = 0; i < spec->autocfg.speaker_outs; i++) - if (spec->speaker_dacs[i] == nid) - return 1; - return 0; -} - -static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int j, conn_len; - hda_nid_t conn[HDA_MAX_CONNECTIONS], fallback_dac; - unsigned int wcaps, wtype; - - conn_len = snd_hda_get_connections(codec, nid, conn, - HDA_MAX_CONNECTIONS); - /* 92HD88: trace back up the link of nids to find the DAC */ - while (conn_len == 1 && (get_wcaps_type(get_wcaps(codec, conn[0])) - != AC_WID_AUD_OUT)) { - nid = conn[0]; - conn_len = snd_hda_get_connections(codec, nid, conn, - HDA_MAX_CONNECTIONS); - } - for (j = 0; j < conn_len; j++) { - wcaps = get_wcaps(codec, conn[j]); - wtype = get_wcaps_type(wcaps); - /* we check only analog outputs */ - if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) - continue; - /* if this route has a free DAC, assign it */ - if (!check_all_dac_nids(spec, conn[j])) { - if (conn_len > 1) { - /* select this DAC in the pin's input mux */ - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, j); - } - return conn[j]; - } - } - - /* if all DACs are already assigned, connect to the primary DAC, - unless we're assigning a secondary headphone */ - fallback_dac = spec->multiout.dac_nids[0]; - if (spec->multiout.hp_nid) { - for (j = 0; j < cfg->hp_outs; j++) - if (cfg->hp_pins[j] == nid) { - fallback_dac = spec->multiout.hp_nid; - break; - } - } - - if (conn_len > 1) { - for (j = 0; j < conn_len; j++) { - if (conn[j] == fallback_dac) { - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_CONNECT_SEL, j); - break; - } - } - } - return 0; -} - -static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid); -static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid); - -/* - * Fill in the dac_nids table from the parsed pin configuration - * This function only works when every pin in line_out_pins[] - * contains atleast one DAC in its connection list. Some 92xx - * codecs are not connected directly to a DAC, such as the 9200 - * and 9202/925x. For those, dac_nids[] must be hard-coded. - */ -static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - hda_nid_t nid, dac; - - for (i = 0; i < cfg->line_outs; i++) { - nid = cfg->line_out_pins[i]; - dac = get_unassigned_dac(codec, nid); - if (!dac) { - if (spec->multiout.num_dacs > 0) { - /* we have already working output pins, - * so let's drop the broken ones again - */ - cfg->line_outs = spec->multiout.num_dacs; - break; - } - /* error out, no available DAC found */ - snd_printk(KERN_ERR - "%s: No available DAC for pin 0x%x\n", - __func__, nid); - return -ENODEV; - } - add_spec_dacs(spec, dac); - } - - for (i = 0; i < cfg->hp_outs; i++) { - nid = cfg->hp_pins[i]; - dac = get_unassigned_dac(codec, nid); - if (dac) { - if (!spec->multiout.hp_nid) - spec->multiout.hp_nid = dac; - else - add_spec_extra_dacs(spec, dac); - } - spec->hp_dacs[i] = dac; - } - - for (i = 0; i < cfg->speaker_outs; i++) { - nid = cfg->speaker_pins[i]; - dac = get_unassigned_dac(codec, nid); - if (dac) - add_spec_extra_dacs(spec, dac); - spec->speaker_dacs[i] = dac; - } - - /* add line-in as output */ - nid = check_line_out_switch(codec); - if (nid) { - dac = get_unassigned_dac(codec, nid); - if (dac) { - snd_printdd("STAC: Add line-in 0x%x as output %d\n", - nid, cfg->line_outs); - cfg->line_out_pins[cfg->line_outs] = nid; - cfg->line_outs++; - spec->line_switch = nid; - add_spec_dacs(spec, dac); - } - } - /* add mic as output */ - nid = check_mic_out_switch(codec, &dac); - if (nid && dac) { - snd_printdd("STAC: Add mic-in 0x%x as output %d\n", - nid, cfg->line_outs); - cfg->line_out_pins[cfg->line_outs] = nid; - cfg->line_outs++; - spec->mic_switch = nid; - add_spec_dacs(spec, dac); - } - - snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", - spec->multiout.num_dacs, - spec->multiout.dac_nids[0], - spec->multiout.dac_nids[1], - spec->multiout.dac_nids[2], - spec->multiout.dac_nids[3], - spec->multiout.dac_nids[4]); - - return 0; -} - -/* create volume control/switch for the given prefx type */ -static int create_controls_idx(struct hda_codec *codec, const char *pfx, - int idx, hda_nid_t nid, int chs) -{ - struct sigmatel_spec *spec = codec->spec; - char name[32]; - int err; - - if (!spec->check_volume_offset) { - unsigned int caps, step, nums, db_scale; - caps = query_amp_caps(codec, nid, HDA_OUTPUT); - step = (caps & AC_AMPCAP_STEP_SIZE) >> - AC_AMPCAP_STEP_SIZE_SHIFT; - step = (step + 1) * 25; /* in .01dB unit */ - nums = (caps & AC_AMPCAP_NUM_STEPS) >> - AC_AMPCAP_NUM_STEPS_SHIFT; - db_scale = nums * step; - /* if dB scale is over -64dB, and finer enough, - * let's reduce it to half - */ - if (db_scale > 6400 && nums >= 0x1f) - spec->volume_offset = nums / 2; - spec->check_volume_offset = 1; - } - - sprintf(name, "%s Playback Volume", pfx); - err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, idx, name, - HDA_COMPOSE_AMP_VAL_OFS(nid, chs, 0, HDA_OUTPUT, - spec->volume_offset)); - if (err < 0) - return err; - sprintf(name, "%s Playback Switch", pfx); - err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_MUTE, idx, name, - HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); - if (err < 0) - return err; - return 0; -} - -#define create_controls(codec, pfx, nid, chs) \ - create_controls_idx(codec, pfx, 0, nid, chs) - -static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) -{ - if (spec->multiout.num_dacs > 4) { - printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); - return 1; - } else { - snd_BUG_ON(spec->multiout.dac_nids != spec->dac_nids); - spec->dac_nids[spec->multiout.num_dacs] = nid; - spec->multiout.num_dacs++; - } - return 0; -} - -static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid) -{ - int i; - for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) { - if (!spec->multiout.extra_out_nid[i]) { - spec->multiout.extra_out_nid[i] = nid; - return 0; - } - } - printk(KERN_WARNING "stac92xx: No space for extra DAC 0x%x\n", nid); - return 1; -} - -/* Create output controls - * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT) - */ -static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, - const hda_nid_t *pins, - const hda_nid_t *dac_nids, - int type) -{ - struct sigmatel_spec *spec = codec->spec; - static const char * const chname[4] = { - "Front", "Surround", NULL /*CLFE*/, "Side" - }; - hda_nid_t nid; - int i, err; - unsigned int wid_caps; - - for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) { - if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) { - if (is_jack_detectable(codec, pins[i])) - spec->hp_detect = 1; - } - nid = dac_nids[i]; - if (!nid) - continue; - if (type != AUTO_PIN_HP_OUT && i == 2) { - /* Center/LFE */ - err = create_controls(codec, "Center", nid, 1); - if (err < 0) - return err; - err = create_controls(codec, "LFE", nid, 2); - if (err < 0) - return err; - - wid_caps = get_wcaps(codec, nid); - - if (wid_caps & AC_WCAP_LR_SWAP) { - err = stac92xx_add_control(spec, - STAC_CTL_WIDGET_CLFE_SWITCH, - "Swap Center/LFE Playback Switch", nid); - - if (err < 0) - return err; - } - - } else { - const char *name; - int idx; - switch (type) { - case AUTO_PIN_HP_OUT: - name = "Headphone"; - idx = i; - break; - case AUTO_PIN_SPEAKER_OUT: - name = "Speaker"; - idx = i; - break; - default: - name = chname[i]; - idx = 0; - break; - } - err = create_controls_idx(codec, name, idx, nid, 3); - if (err < 0) - return err; - } - } - return 0; -} - -static int stac92xx_add_capvol_ctls(struct hda_codec *codec, unsigned long vol, - unsigned long sw, int idx) -{ - int err; - err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, - "Capture Volume", vol); - if (err < 0) - return err; - err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_MUTE, idx, - "Capture Switch", sw); - if (err < 0) - return err; - return 0; -} - -/* add playback controls from the parsed DAC table */ -static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, - const struct auto_pin_cfg *cfg) -{ - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid; - int err; - int idx; - - err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins, - spec->multiout.dac_nids, - cfg->line_out_type); - if (err < 0) - return err; - - if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { - err = stac92xx_add_control(spec, - STAC_CTL_WIDGET_HP_SWITCH, - "Headphone as Line Out Switch", - cfg->hp_pins[cfg->hp_outs - 1]); - if (err < 0) - return err; - } - - for (idx = 0; idx < cfg->num_inputs; idx++) { - if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN) - break; - nid = cfg->inputs[idx].pin; - err = stac92xx_add_jack_mode_control(codec, nid, idx); - if (err < 0) - return err; - } - - return 0; -} - -/* add playback controls for Speaker and HP outputs */ -static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, - struct auto_pin_cfg *cfg) -{ - struct sigmatel_spec *spec = codec->spec; - int err; - - err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins, - spec->hp_dacs, AUTO_PIN_HP_OUT); - if (err < 0) - return err; - - err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, - spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT); - if (err < 0) - return err; - - return 0; -} - -/* labels for mono mux outputs */ -static const char * const stac92xx_mono_labels[4] = { - "DAC0", "DAC1", "Mixer", "DAC2" -}; - -/* create mono mux for mono out on capable codecs */ -static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct hda_input_mux *mono_mux = &spec->private_mono_mux; - int i, num_cons; - hda_nid_t con_lst[ARRAY_SIZE(stac92xx_mono_labels)]; - - num_cons = snd_hda_get_connections(codec, - spec->mono_nid, - con_lst, - HDA_MAX_NUM_INPUTS); - if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) - return -EINVAL; - - for (i = 0; i < num_cons; i++) - snd_hda_add_imux_item(mono_mux, stac92xx_mono_labels[i], i, - NULL); - - return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, - "Mono Mux", spec->mono_nid); -} - -/* create PC beep volume controls */ -static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec, - hda_nid_t nid) -{ - struct sigmatel_spec *spec = codec->spec; - u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); - int err, type = STAC_CTL_WIDGET_MUTE_BEEP; - - if (spec->anabeep_nid == nid) - type = STAC_CTL_WIDGET_MUTE; - - /* check for mute support for the the amp */ - if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { - err = stac92xx_add_control(spec, type, - "Beep Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); - if (err < 0) - return err; - } - - /* check to see if there is volume support for the amp */ - if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { - err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, - "Beep Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); - if (err < 0) - return err; - } - return 0; -} - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -#define stac92xx_dig_beep_switch_info snd_ctl_boolean_mono_info - -static int stac92xx_dig_beep_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = codec->beep->enabled; - return 0; -} - -static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]); -} - -static const struct snd_kcontrol_new stac92xx_dig_beep_ctrl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = stac92xx_dig_beep_switch_info, - .get = stac92xx_dig_beep_switch_get, - .put = stac92xx_dig_beep_switch_put, -}; - -static int stac92xx_beep_switch_ctl(struct hda_codec *codec) -{ - return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl, - 0, "Beep Playback Switch", 0); -} -#endif - -static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int i, j, err = 0; - - for (i = 0; i < spec->num_muxes; i++) { - hda_nid_t nid; - unsigned int wcaps; - unsigned long val; - - nid = spec->mux_nids[i]; - wcaps = get_wcaps(codec, nid); - if (!(wcaps & AC_WCAP_OUT_AMP)) - continue; - - /* check whether already the same control was created as - * normal Capture Volume. - */ - val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); - for (j = 0; j < spec->num_caps; j++) { - if (spec->capvols[j] == val) - break; - } - if (j < spec->num_caps) - continue; - - err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, i, - "Mux Capture Volume", val); - if (err < 0) - return err; - } - return 0; -}; - -static const char * const stac92xx_spdif_labels[3] = { - "Digital Playback", "Analog Mux 1", "Analog Mux 2", -}; - -static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct hda_input_mux *spdif_mux = &spec->private_smux; - const char * const *labels = spec->spdif_labels; - int i, num_cons; - hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; - - num_cons = snd_hda_get_connections(codec, - spec->smux_nids[0], - con_lst, - HDA_MAX_NUM_INPUTS); - if (num_cons <= 0) - return -EINVAL; - - if (!labels) - labels = stac92xx_spdif_labels; - - for (i = 0; i < num_cons; i++) - snd_hda_add_imux_item(spdif_mux, labels[i], i, NULL); - - return 0; -} - -/* labels for dmic mux inputs */ -static const char * const stac92xx_dmic_labels[5] = { - "Analog Inputs", "Digital Mic 1", "Digital Mic 2", - "Digital Mic 3", "Digital Mic 4" -}; - -static hda_nid_t get_connected_node(struct hda_codec *codec, hda_nid_t mux, - int idx) -{ - hda_nid_t conn[HDA_MAX_NUM_INPUTS]; - int nums; - nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); - if (idx >= 0 && idx < nums) - return conn[idx]; - return 0; -} - -/* look for NID recursively */ -#define get_connection_index(codec, mux, nid) \ - snd_hda_get_conn_index(codec, mux, nid, 1) - -/* create a volume assigned to the given pin (only if supported) */ -/* return 1 if the volume control is created */ -static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, - const char *label, int idx, int direction) -{ - unsigned int caps, nums; - char name[32]; - int err; - - if (direction == HDA_OUTPUT) - caps = AC_WCAP_OUT_AMP; - else - caps = AC_WCAP_IN_AMP; - if (!(get_wcaps(codec, nid) & caps)) - return 0; - caps = query_amp_caps(codec, nid, direction); - nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; - if (!nums) - return 0; - snprintf(name, sizeof(name), "%s Capture Volume", label); - err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); - if (err < 0) - return err; - return 1; -} - -/* create playback/capture controls for input pins on dmic capable codecs */ -static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, - const struct auto_pin_cfg *cfg) -{ - struct sigmatel_spec *spec = codec->spec; - struct hda_input_mux *imux = &spec->private_imux; - struct hda_input_mux *dimux = &spec->private_dimux; - int err, i; - unsigned int def_conf; - - snd_hda_add_imux_item(dimux, stac92xx_dmic_labels[0], 0, NULL); - - for (i = 0; i < spec->num_dmics; i++) { - hda_nid_t nid; - int index, type_idx; - char label[32]; - - nid = spec->dmic_nids[i]; - if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) - continue; - def_conf = snd_hda_codec_get_pincfg(codec, nid); - if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) - continue; - - index = get_connection_index(codec, spec->dmux_nids[0], nid); - if (index < 0) - continue; - - snd_hda_get_pin_label(codec, nid, &spec->autocfg, - label, sizeof(label), NULL); - snd_hda_add_imux_item(dimux, label, index, &type_idx); - if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) - snd_hda_add_imux_item(imux, label, index, &type_idx); - - err = create_elem_capture_vol(codec, nid, label, type_idx, - HDA_INPUT); - if (err < 0) - return err; - if (!err) { - err = create_elem_capture_vol(codec, nid, label, - type_idx, HDA_OUTPUT); - if (err < 0) - return err; - if (!err) { - nid = get_connected_node(codec, - spec->dmux_nids[0], index); - if (nid) - err = create_elem_capture_vol(codec, - nid, label, - type_idx, HDA_INPUT); - if (err < 0) - return err; - } - } - } - - return 0; -} - -static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock) -{ - unsigned int cfg; - unsigned int type; - - if (!nid) - return 0; - cfg = snd_hda_codec_get_pincfg(codec, nid); - type = get_defcfg_device(cfg); - switch (snd_hda_get_input_pin_attr(cfg)) { - case INPUT_PIN_ATTR_INT: - if (*fixed) - return 1; /* already occupied */ - if (type != AC_JACK_MIC_IN) - return 1; /* invalid type */ - *fixed = nid; - break; - case INPUT_PIN_ATTR_UNUSED: - break; - case INPUT_PIN_ATTR_DOCK: - if (*dock) - return 1; /* already occupied */ - if (type != AC_JACK_MIC_IN && type != AC_JACK_LINE_IN) - return 1; /* invalid type */ - *dock = nid; - break; - default: - if (*ext) - return 1; /* already occupied */ - if (type != AC_JACK_MIC_IN) - return 1; /* invalid type */ - *ext = nid; - break; - } - return 0; -} - -static int set_mic_route(struct hda_codec *codec, - struct sigmatel_mic_route *mic, - hda_nid_t pin) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - mic->pin = pin; - if (pin == 0) - return 0; - for (i = 0; i < cfg->num_inputs; i++) { - if (pin == cfg->inputs[i].pin) - break; - } - if (i < cfg->num_inputs && cfg->inputs[i].type == AUTO_PIN_MIC) { - /* analog pin */ - i = get_connection_index(codec, spec->mux_nids[0], pin); - if (i < 0) - return -1; - mic->mux_idx = i; - mic->dmux_idx = -1; - if (spec->dmux_nids) - mic->dmux_idx = get_connection_index(codec, - spec->dmux_nids[0], - spec->mux_nids[0]); - } else if (spec->dmux_nids) { - /* digital pin */ - i = get_connection_index(codec, spec->dmux_nids[0], pin); - if (i < 0) - return -1; - mic->dmux_idx = i; - mic->mux_idx = -1; - if (spec->mux_nids) - mic->mux_idx = get_connection_index(codec, - spec->mux_nids[0], - spec->dmux_nids[0]); - } - return 0; -} - -/* return non-zero if the device is for automatic mic switch */ -static int stac_check_auto_mic(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t fixed, ext, dock; - int i; - - fixed = ext = dock = 0; - for (i = 0; i < cfg->num_inputs; i++) - if (check_mic_pin(codec, cfg->inputs[i].pin, - &fixed, &ext, &dock)) - return 0; - for (i = 0; i < spec->num_dmics; i++) - if (check_mic_pin(codec, spec->dmic_nids[i], - &fixed, &ext, &dock)) - return 0; - if (!fixed || (!ext && !dock)) - return 0; /* no input to switch */ - if (!is_jack_detectable(codec, ext)) - return 0; /* no unsol support */ - if (set_mic_route(codec, &spec->ext_mic, ext) || - set_mic_route(codec, &spec->int_mic, fixed) || - set_mic_route(codec, &spec->dock_mic, dock)) - return 0; /* something is wrong */ - return 1; -} - -/* create playback/capture controls for input pins */ -static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) -{ - struct sigmatel_spec *spec = codec->spec; - struct hda_input_mux *imux = &spec->private_imux; - int i, j; - const char *label; - - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; - int index, err, type_idx; - - index = -1; - for (j = 0; j < spec->num_muxes; j++) { - index = get_connection_index(codec, spec->mux_nids[j], - nid); - if (index >= 0) - break; - } - if (index < 0) - continue; - - label = hda_get_autocfg_input_label(codec, cfg, i); - snd_hda_add_imux_item(imux, label, index, &type_idx); - - err = create_elem_capture_vol(codec, nid, - label, type_idx, - HDA_INPUT); - if (err < 0) - return err; - } - spec->num_analog_muxes = imux->num_items; - - if (imux->num_items) { - /* - * Set the current input for the muxes. - * The STAC9221 has two input muxes with identical source - * NID lists. Hopefully this won't get confused. - */ - for (i = 0; i < spec->num_muxes; i++) { - snd_hda_codec_write_cache(codec, spec->mux_nids[i], 0, - AC_VERB_SET_CONNECT_SEL, - imux->items[0].index); - } - } - - return 0; -} - -static void stac92xx_auto_init_multi_out(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->autocfg.line_outs; i++) { - hda_nid_t nid = spec->autocfg.line_out_pins[i]; - stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); - } -} - -static void stac92xx_auto_init_hp_out(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->autocfg.hp_outs; i++) { - hda_nid_t pin; - pin = spec->autocfg.hp_pins[i]; - if (pin) /* connect to front */ - stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); - } - for (i = 0; i < spec->autocfg.speaker_outs; i++) { - hda_nid_t pin; - pin = spec->autocfg.speaker_pins[i]; - if (pin) /* connect to front */ - stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN); - } -} - -static int is_dual_headphones(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int i, valid_hps; - - if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT || - spec->autocfg.hp_outs <= 1) - return 0; - valid_hps = 0; - for (i = 0; i < spec->autocfg.hp_outs; i++) { - hda_nid_t nid = spec->autocfg.hp_pins[i]; - unsigned int cfg = snd_hda_codec_get_pincfg(codec, nid); - if (get_defcfg_location(cfg) & AC_JACK_LOC_SEPARATE) - continue; - valid_hps++; - } - return (valid_hps > 1); -} - - -static int stac92xx_parse_auto_config(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - hda_nid_t dig_out = 0, dig_in = 0; - int hp_swap = 0; - int i, err; - - if ((err = snd_hda_parse_pin_def_config(codec, - &spec->autocfg, - spec->dmic_nids)) < 0) - return err; - if (! spec->autocfg.line_outs) - return 0; /* can't find valid pin config */ - - /* If we have no real line-out pin and multiple hp-outs, HPs should - * be set up as multi-channel outputs. - */ - if (is_dual_headphones(codec)) { - /* Copy hp_outs to line_outs, backup line_outs in - * speaker_outs so that the following routines can handle - * HP pins as primary outputs. - */ - snd_printdd("stac92xx: Enabling multi-HPs workaround\n"); - memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins, - sizeof(spec->autocfg.line_out_pins)); - spec->autocfg.speaker_outs = spec->autocfg.line_outs; - memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins, - sizeof(spec->autocfg.hp_pins)); - spec->autocfg.line_outs = spec->autocfg.hp_outs; - spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; - spec->autocfg.hp_outs = 0; - hp_swap = 1; - } - if (spec->autocfg.mono_out_pin) { - int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & - (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); - u32 caps = query_amp_caps(codec, - spec->autocfg.mono_out_pin, dir); - hda_nid_t conn_list[1]; - - /* get the mixer node and then the mono mux if it exists */ - if (snd_hda_get_connections(codec, - spec->autocfg.mono_out_pin, conn_list, 1) && - snd_hda_get_connections(codec, conn_list[0], - conn_list, 1) > 0) { - - int wcaps = get_wcaps(codec, conn_list[0]); - int wid_type = get_wcaps_type(wcaps); - /* LR swap check, some stac925x have a mux that - * changes the DACs output path instead of the - * mono-mux path. - */ - if (wid_type == AC_WID_AUD_SEL && - !(wcaps & AC_WCAP_LR_SWAP)) - spec->mono_nid = conn_list[0]; - } - if (dir) { - hda_nid_t nid = spec->autocfg.mono_out_pin; - - /* most mono outs have a least a mute/unmute switch */ - dir = (dir & AC_WCAP_OUT_AMP) ? HDA_OUTPUT : HDA_INPUT; - err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, - "Mono Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 1, 0, dir)); - if (err < 0) - return err; - /* check for volume support for the amp */ - if ((caps & AC_AMPCAP_NUM_STEPS) - >> AC_AMPCAP_NUM_STEPS_SHIFT) { - err = stac92xx_add_control(spec, - STAC_CTL_WIDGET_VOL, - "Mono Playback Volume", - HDA_COMPOSE_AMP_VAL(nid, 1, 0, dir)); - if (err < 0) - return err; - } - } - - stac92xx_auto_set_pinctl(codec, spec->autocfg.mono_out_pin, - AC_PINCTL_OUT_EN); - } - - if (!spec->multiout.num_dacs) { - err = stac92xx_auto_fill_dac_nids(codec); - if (err < 0) - return err; - err = stac92xx_auto_create_multi_out_ctls(codec, - &spec->autocfg); - if (err < 0) - return err; - } - - /* setup analog beep controls */ - if (spec->anabeep_nid > 0) { - err = stac92xx_auto_create_beep_ctls(codec, - spec->anabeep_nid); - if (err < 0) - return err; - } - - /* setup digital beep controls and input device */ -#ifdef CONFIG_SND_HDA_INPUT_BEEP - if (spec->digbeep_nid > 0) { - hda_nid_t nid = spec->digbeep_nid; - unsigned int caps; - - err = stac92xx_auto_create_beep_ctls(codec, nid); - if (err < 0) - return err; - err = snd_hda_attach_beep_device(codec, nid); - if (err < 0) - return err; - if (codec->beep) { - /* IDT/STAC codecs have linear beep tone parameter */ - codec->beep->linear_tone = spec->linear_tone_beep; - /* if no beep switch is available, make its own one */ - caps = query_amp_caps(codec, nid, HDA_OUTPUT); - if (!(caps & AC_AMPCAP_MUTE)) { - err = stac92xx_beep_switch_ctl(codec); - if (err < 0) - return err; - } - } - } -#endif - - err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); - if (err < 0) - return err; - - /* All output parsing done, now restore the swapped hp pins */ - if (hp_swap) { - memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, - sizeof(spec->autocfg.hp_pins)); - spec->autocfg.hp_outs = spec->autocfg.line_outs; - spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; - spec->autocfg.line_outs = 0; - } - - if (stac_check_auto_mic(codec)) { - spec->auto_mic = 1; - /* only one capture for auto-mic */ - spec->num_adcs = 1; - spec->num_caps = 1; - spec->num_muxes = 1; - } - - for (i = 0; i < spec->num_caps; i++) { - err = stac92xx_add_capvol_ctls(codec, spec->capvols[i], - spec->capsws[i], i); - if (err < 0) - return err; - } - - err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); - if (err < 0) - return err; - - if (spec->mono_nid > 0) { - err = stac92xx_auto_create_mono_output_ctls(codec); - if (err < 0) - return err; - } - if (spec->num_dmics > 0 && !spec->dinput_mux) - if ((err = stac92xx_auto_create_dmic_input_ctls(codec, - &spec->autocfg)) < 0) - return err; - if (spec->num_muxes > 0) { - err = stac92xx_auto_create_mux_input_ctls(codec); - if (err < 0) - return err; - } - if (spec->num_smuxes > 0) { - err = stac92xx_auto_create_spdif_mux_ctls(codec); - if (err < 0) - return err; - } - - err = stac92xx_add_input_source(spec); - if (err < 0) - return err; - - spec->multiout.max_channels = spec->multiout.num_dacs * 2; - if (spec->multiout.max_channels > 2) - spec->surr_switch = 1; - - /* find digital out and in converters */ - for (i = codec->start_nid; i < codec->start_nid + codec->num_nodes; i++) { - unsigned int wid_caps = get_wcaps(codec, i); - if (wid_caps & AC_WCAP_DIGITAL) { - switch (get_wcaps_type(wid_caps)) { - case AC_WID_AUD_OUT: - if (!dig_out) - dig_out = i; - break; - case AC_WID_AUD_IN: - if (!dig_in) - dig_in = i; - break; - } - } - } - if (spec->autocfg.dig_outs) - spec->multiout.dig_out_nid = dig_out; - if (dig_in && spec->autocfg.dig_in_pin) - spec->dig_in_nid = dig_in; - - if (spec->kctls.list) - spec->mixers[spec->num_mixers++] = spec->kctls.list; - - spec->input_mux = &spec->private_imux; - if (!spec->dinput_mux) - spec->dinput_mux = &spec->private_dimux; - spec->sinput_mux = &spec->private_smux; - spec->mono_mux = &spec->private_mono_mux; - return 1; -} - -/* add playback controls for HP output */ -static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, - struct auto_pin_cfg *cfg) -{ - struct sigmatel_spec *spec = codec->spec; - hda_nid_t pin = cfg->hp_pins[0]; - - if (! pin) - return 0; - - if (is_jack_detectable(codec, pin)) - spec->hp_detect = 1; - - return 0; -} - -/* add playback controls for LFE output */ -static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, - struct auto_pin_cfg *cfg) -{ - struct sigmatel_spec *spec = codec->spec; - int err; - hda_nid_t lfe_pin = 0x0; - int i; - - /* - * search speaker outs and line outs for a mono speaker pin - * with an amp. If one is found, add LFE controls - * for it. - */ - for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) { - hda_nid_t pin = spec->autocfg.speaker_pins[i]; - unsigned int wcaps = get_wcaps(codec, pin); - wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); - if (wcaps == AC_WCAP_OUT_AMP) - /* found a mono speaker with an amp, must be lfe */ - lfe_pin = pin; - } - - /* if speaker_outs is 0, then speakers may be in line_outs */ - if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) { - for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { - hda_nid_t pin = spec->autocfg.line_out_pins[i]; - unsigned int defcfg; - defcfg = snd_hda_codec_get_pincfg(codec, pin); - if (get_defcfg_device(defcfg) == AC_JACK_SPEAKER) { - unsigned int wcaps = get_wcaps(codec, pin); - wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); - if (wcaps == AC_WCAP_OUT_AMP) - /* found a mono speaker with an amp, - must be lfe */ - lfe_pin = pin; - } - } - } - - if (lfe_pin) { - err = create_controls(codec, "LFE", lfe_pin, 1); - if (err < 0) - return err; - } - - return 0; -} - -static int stac9200_parse_auto_config(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int err; - - if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) - return err; - - if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) - return err; - - if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) - return err; - - if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) - return err; - - if (spec->num_muxes > 0) { - err = stac92xx_auto_create_mux_input_ctls(codec); - if (err < 0) - return err; - } - - err = stac92xx_add_input_source(spec); - if (err < 0) - return err; - - if (spec->autocfg.dig_outs) - spec->multiout.dig_out_nid = 0x05; - if (spec->autocfg.dig_in_pin) - spec->dig_in_nid = 0x04; - - if (spec->kctls.list) - spec->mixers[spec->num_mixers++] = spec->kctls.list; - - spec->input_mux = &spec->private_imux; - spec->dinput_mux = &spec->private_dimux; - - return 1; -} - -/* - * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a - * funky external mute control using GPIO pins. - */ - -static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, - unsigned int dir_mask, unsigned int data) -{ - unsigned int gpiostate, gpiomask, gpiodir; - - snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data); - - gpiostate = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_DATA, 0); - gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); - - gpiomask = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_MASK, 0); - gpiomask |= mask; - - gpiodir = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_DIRECTION, 0); - gpiodir |= dir_mask; - - /* Configure GPIOx as CMOS */ - snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); - - snd_hda_codec_write(codec, codec->afg, 0, - AC_VERB_SET_GPIO_MASK, gpiomask); - snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */ - - msleep(1); - - snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ -} - -static int stac_add_event(struct hda_codec *codec, hda_nid_t nid, - unsigned char type, int data) -{ - struct hda_jack_tbl *event; - - event = snd_hda_jack_tbl_new(codec, nid); - if (!event) - return -ENOMEM; - event->action = type; - event->private_data = data; - - return 0; -} - -/* check if given nid is a valid pin and no other events are assigned - * to it. If OK, assign the event, set the unsol flag, and returns 1. - * Otherwise, returns zero. - */ -static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, - unsigned int type) -{ - struct hda_jack_tbl *event; - - if (!is_jack_detectable(codec, nid)) - return 0; - event = snd_hda_jack_tbl_new(codec, nid); - if (!event) - return -ENOMEM; - if (event->action && event->action != type) - return 0; - event->action = type; - snd_hda_jack_detect_enable(codec, nid, 0); - return 1; -} - -static int is_nid_out_jack_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) -{ - int i; - for (i = 0; i < cfg->hp_outs; i++) - if (cfg->hp_pins[i] == nid) - return 1; /* nid is a HP-Out */ - for (i = 0; i < cfg->line_outs; i++) - if (cfg->line_out_pins[i] == nid) - return 1; /* nid is a line-Out */ - return 0; /* nid is not a HP-Out */ -}; - -static void stac92xx_power_down(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - - /* power down inactive DACs */ - const hda_nid_t *dac; - for (dac = spec->dac_list; *dac; dac++) - if (!check_all_dac_nids(spec, *dac)) - snd_hda_codec_write(codec, *dac, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); -} - -static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, - int enable); - -static inline int get_int_hint(struct hda_codec *codec, const char *key, - int *valp) -{ - const char *p; - p = snd_hda_get_hint(codec, key); - if (p) { - unsigned long val; - if (!strict_strtoul(p, 0, &val)) { - *valp = val; - return 1; - } - } - return 0; -} - -/* override some hints from the hwdep entry */ -static void stac_store_hints(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - int val; - - val = snd_hda_get_bool_hint(codec, "hp_detect"); - if (val >= 0) - spec->hp_detect = val; - if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) { - spec->eapd_mask = spec->gpio_dir = spec->gpio_data = - spec->gpio_mask; - } - if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) - spec->gpio_mask &= spec->gpio_mask; - if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) - spec->gpio_dir &= spec->gpio_mask; - if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) - spec->eapd_mask &= spec->gpio_mask; - if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) - spec->gpio_mute &= spec->gpio_mask; - val = snd_hda_get_bool_hint(codec, "eapd_switch"); - if (val >= 0) - spec->eapd_switch = val; - get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); - if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { - spec->gpio_mask |= spec->gpio_led; - spec->gpio_dir |= spec->gpio_led; - if (spec->gpio_led_polarity) - spec->gpio_data |= spec->gpio_led; - } -} - -static void stac_issue_unsol_events(struct hda_codec *codec, int num_pins, - const hda_nid_t *pins) -{ - while (num_pins--) - stac_issue_unsol_event(codec, *pins++); -} - -/* fake event to set up pins */ -static void stac_fake_hp_events(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - - if (spec->autocfg.hp_outs) - stac_issue_unsol_events(codec, spec->autocfg.hp_outs, - spec->autocfg.hp_pins); - if (spec->autocfg.line_outs && - spec->autocfg.line_out_pins[0] != spec->autocfg.hp_pins[0]) - stac_issue_unsol_events(codec, spec->autocfg.line_outs, - spec->autocfg.line_out_pins); -} - -static int stac92xx_init(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int gpio; - int i; - - snd_hda_sequence_write(codec, spec->init); - - /* power down adcs initially */ - if (spec->powerdown_adcs) - for (i = 0; i < spec->num_adcs; i++) - snd_hda_codec_write(codec, - spec->adc_nids[i], 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - - /* override some hints */ - stac_store_hints(codec); - - /* set up GPIO */ - gpio = spec->gpio_data; - /* turn on EAPD statically when spec->eapd_switch isn't set. - * otherwise, unsol event will turn it on/off dynamically - */ - if (!spec->eapd_switch) - gpio |= spec->eapd_mask; - stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, gpio); - - /* set up pins */ - if (spec->hp_detect) { - /* Enable unsolicited responses on the HP widget */ - for (i = 0; i < cfg->hp_outs; i++) { - hda_nid_t nid = cfg->hp_pins[i]; - enable_pin_detect(codec, nid, STAC_HP_EVENT); - } - if (cfg->line_out_type == AUTO_PIN_LINE_OUT && - cfg->speaker_outs > 0) { - /* enable pin-detect for line-outs as well */ - for (i = 0; i < cfg->line_outs; i++) { - hda_nid_t nid = cfg->line_out_pins[i]; - enable_pin_detect(codec, nid, STAC_LO_EVENT); - } - } - - /* force to enable the first line-out; the others are set up - * in unsol_event - */ - stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], - AC_PINCTL_OUT_EN); - /* fake event to set up pins */ - stac_fake_hp_events(codec); - } else { - stac92xx_auto_init_multi_out(codec); - stac92xx_auto_init_hp_out(codec); - for (i = 0; i < cfg->hp_outs; i++) - stac_toggle_power_map(codec, cfg->hp_pins[i], 1); - } - if (spec->auto_mic) { - /* initialize connection to analog input */ - if (spec->dmux_nids) - snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, - AC_VERB_SET_CONNECT_SEL, 0); - if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) - stac_issue_unsol_event(codec, spec->ext_mic.pin); - if (enable_pin_detect(codec, spec->dock_mic.pin, - STAC_MIC_EVENT)) - stac_issue_unsol_event(codec, spec->dock_mic.pin); - } - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; - int type = cfg->inputs[i].type; - unsigned int pinctl, conf; - if (type == AUTO_PIN_MIC) { - /* for mic pins, force to initialize */ - pinctl = stac92xx_get_default_vref(codec, nid); - pinctl |= AC_PINCTL_IN_EN; - stac92xx_auto_set_pinctl(codec, nid, pinctl); - } else { - pinctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - /* if PINCTL already set then skip */ - /* Also, if both INPUT and OUTPUT are set, - * it must be a BIOS bug; need to override, too - */ - if (!(pinctl & AC_PINCTL_IN_EN) || - (pinctl & AC_PINCTL_OUT_EN)) { - pinctl &= ~AC_PINCTL_OUT_EN; - pinctl |= AC_PINCTL_IN_EN; - stac92xx_auto_set_pinctl(codec, nid, pinctl); - } - } - conf = snd_hda_codec_get_pincfg(codec, nid); - if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { - if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT)) - stac_issue_unsol_event(codec, nid); - } - } - for (i = 0; i < spec->num_dmics; i++) - stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], - AC_PINCTL_IN_EN); - if (cfg->dig_out_pins[0]) - stac92xx_auto_set_pinctl(codec, cfg->dig_out_pins[0], - AC_PINCTL_OUT_EN); - if (cfg->dig_in_pin) - stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, - AC_PINCTL_IN_EN); - for (i = 0; i < spec->num_pwrs; i++) { - hda_nid_t nid = spec->pwr_nids[i]; - unsigned int pinctl, def_conf; - - /* power on when no jack detection is available */ - /* or when the VREF is used for controlling LED */ - if (!spec->hp_detect || - spec->vref_mute_led_nid == nid) { - stac_toggle_power_map(codec, nid, 1); - continue; - } - - if (is_nid_out_jack_pin(cfg, nid)) - continue; /* already has an unsol event */ - - pinctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - /* outputs are only ports capable of power management - * any attempts on powering down a input port cause the - * referenced VREF to act quirky. - */ - if (pinctl & AC_PINCTL_IN_EN) { - stac_toggle_power_map(codec, nid, 1); - continue; - } - def_conf = snd_hda_codec_get_pincfg(codec, nid); - def_conf = get_defcfg_connect(def_conf); - /* skip any ports that don't have jacks since presence - * detection is useless */ - if (def_conf != AC_JACK_PORT_COMPLEX || - !is_jack_detectable(codec, nid)) { - stac_toggle_power_map(codec, nid, 1); - continue; - } - if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) { - stac_issue_unsol_event(codec, nid); - continue; - } - /* none of the above, turn the port OFF */ - stac_toggle_power_map(codec, nid, 0); - } - - snd_hda_jack_report_sync(codec); - - /* sync mute LED */ - snd_hda_sync_vmaster_hook(&spec->vmaster_mute); - if (spec->dac_list) - stac92xx_power_down(codec); - return 0; -} - -static void stac92xx_free_kctls(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - - if (spec->kctls.list) { - struct snd_kcontrol_new *kctl = spec->kctls.list; - int i; - for (i = 0; i < spec->kctls.used; i++) - kfree(kctl[i].name); - } - snd_array_free(&spec->kctls); -} - -static void stac92xx_shutup_pins(struct hda_codec *codec) -{ - unsigned int i, def_conf; - - if (codec->bus->shutdown) - return; - for (i = 0; i < codec->init_pins.used; i++) { - struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); - def_conf = snd_hda_codec_get_pincfg(codec, pin->nid); - if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) - snd_hda_codec_write(codec, pin->nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, 0); - } -} - -static void stac92xx_shutup(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - - stac92xx_shutup_pins(codec); - - if (spec->eapd_mask) - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data & - ~spec->eapd_mask); -} - -static void stac92xx_free(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - - if (! spec) - return; - - stac92xx_shutup(codec); - - kfree(spec); - snd_hda_detach_beep_device(codec); -} - -static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, - unsigned int flag) -{ - unsigned int old_ctl, pin_ctl; - - pin_ctl = snd_hda_codec_read(codec, nid, - 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); - - if (pin_ctl & AC_PINCTL_IN_EN) { - /* - * we need to check the current set-up direction of - * shared input pins since they can be switched via - * "xxx as Output" mixer switch - */ - struct sigmatel_spec *spec = codec->spec; - if (nid == spec->line_switch || nid == spec->mic_switch) - return; - } - - old_ctl = pin_ctl; - /* if setting pin direction bits, clear the current - direction bits first */ - if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)) - pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); - - pin_ctl |= flag; - if (old_ctl != pin_ctl) - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_ctl); -} - -static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, - unsigned int flag) -{ - unsigned int pin_ctl = snd_hda_codec_read(codec, nid, - 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); - if (pin_ctl & flag) - snd_hda_codec_write_cache(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_ctl & ~flag); -} - -static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) -{ - if (!nid) - return 0; - return snd_hda_jack_detect(codec, nid); -} - -static void stac92xx_line_out_detect(struct hda_codec *codec, - int presence) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i; - - for (i = 0; i < cfg->line_outs; i++) { - if (presence) - break; - presence = get_pin_presence(codec, cfg->line_out_pins[i]); - if (presence) { - unsigned int pinctl; - pinctl = snd_hda_codec_read(codec, - cfg->line_out_pins[i], 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - if (pinctl & AC_PINCTL_IN_EN) - presence = 0; /* mic- or line-input */ - } - } - - if (presence) { - /* disable speakers */ - for (i = 0; i < cfg->speaker_outs; i++) - stac92xx_reset_pinctl(codec, cfg->speaker_pins[i], - AC_PINCTL_OUT_EN); - if (spec->eapd_mask && spec->eapd_switch) - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data & - ~spec->eapd_mask); - } else { - /* enable speakers */ - for (i = 0; i < cfg->speaker_outs; i++) - stac92xx_set_pinctl(codec, cfg->speaker_pins[i], - AC_PINCTL_OUT_EN); - if (spec->eapd_mask && spec->eapd_switch) - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data | - spec->eapd_mask); - } -} - -/* return non-zero if the hp-pin of the given array index isn't - * a jack-detection target - */ -static int no_hp_sensing(struct sigmatel_spec *spec, int i) -{ - struct auto_pin_cfg *cfg = &spec->autocfg; - - /* ignore sensing of shared line and mic jacks */ - if (cfg->hp_pins[i] == spec->line_switch) - return 1; - if (cfg->hp_pins[i] == spec->mic_switch) - return 1; - /* ignore if the pin is set as line-out */ - if (cfg->hp_pins[i] == spec->hp_switch) - return 1; - return 0; -} - -static void stac92xx_hp_detect(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - int i, presence; - - presence = 0; - if (spec->gpio_mute) - presence = !(snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute); - - for (i = 0; i < cfg->hp_outs; i++) { - if (presence) - break; - if (no_hp_sensing(spec, i)) - continue; - presence = get_pin_presence(codec, cfg->hp_pins[i]); - if (presence) { - unsigned int pinctl; - pinctl = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - if (pinctl & AC_PINCTL_IN_EN) - presence = 0; /* mic- or line-input */ - } - } - - if (presence) { - /* disable lineouts */ - if (spec->hp_switch) - stac92xx_reset_pinctl(codec, spec->hp_switch, - AC_PINCTL_OUT_EN); - for (i = 0; i < cfg->line_outs; i++) - stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], - AC_PINCTL_OUT_EN); - } else { - /* enable lineouts */ - if (spec->hp_switch) - stac92xx_set_pinctl(codec, spec->hp_switch, - AC_PINCTL_OUT_EN); - for (i = 0; i < cfg->line_outs; i++) - stac92xx_set_pinctl(codec, cfg->line_out_pins[i], - AC_PINCTL_OUT_EN); - } - stac92xx_line_out_detect(codec, presence); - /* toggle hp outs */ - for (i = 0; i < cfg->hp_outs; i++) { - unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN; - if (no_hp_sensing(spec, i)) - continue; - if (1 /*presence*/) - stac92xx_set_pinctl(codec, cfg->hp_pins[i], val); -#if 0 /* FIXME */ -/* Resetting the pinctl like below may lead to (a sort of) regressions - * on some devices since they use the HP pin actually for line/speaker - * outs although the default pin config shows a different pin (that is - * wrong and useless). - * - * So, it's basically a problem of default pin configs, likely a BIOS issue. - * But, disabling the code below just works around it, and I'm too tired of - * bug reports with such devices... - */ - else - stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val); -#endif /* FIXME */ - } -} - -static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, - int enable) -{ - struct sigmatel_spec *spec = codec->spec; - unsigned int idx, val; - - for (idx = 0; idx < spec->num_pwrs; idx++) { - if (spec->pwr_nids[idx] == nid) - break; - } - if (idx >= spec->num_pwrs) - return; - - idx = 1 << idx; - - val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff; - if (enable) - val &= ~idx; - else - val |= idx; - - /* power down unused output ports */ - snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); -} - -static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) -{ - stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); -} - -/* get the pin connection (fixed, none, etc) */ -static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) -{ - struct sigmatel_spec *spec = codec->spec; - unsigned int cfg; - - cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); - return get_defcfg_connect(cfg); -} - -static int stac92xx_connected_ports(struct hda_codec *codec, - const hda_nid_t *nids, int num_nids) -{ - struct sigmatel_spec *spec = codec->spec; - int idx, num; - unsigned int def_conf; - - for (num = 0; num < num_nids; num++) { - for (idx = 0; idx < spec->num_pins; idx++) - if (spec->pin_nids[idx] == nids[num]) - break; - if (idx >= spec->num_pins) - break; - def_conf = stac_get_defcfg_connect(codec, idx); - if (def_conf == AC_JACK_PORT_NONE) - break; - } - return num; -} - -static void stac92xx_mic_detect(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct sigmatel_mic_route *mic; - - if (get_pin_presence(codec, spec->ext_mic.pin)) - mic = &spec->ext_mic; - else if (get_pin_presence(codec, spec->dock_mic.pin)) - mic = &spec->dock_mic; - else - mic = &spec->int_mic; - if (mic->dmux_idx >= 0) - snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, - AC_VERB_SET_CONNECT_SEL, - mic->dmux_idx); - if (mic->mux_idx >= 0) - snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0, - AC_VERB_SET_CONNECT_SEL, - mic->mux_idx); -} - -static void handle_unsol_event(struct hda_codec *codec, - struct hda_jack_tbl *event) -{ - struct sigmatel_spec *spec = codec->spec; - int data; - - switch (event->action) { - case STAC_HP_EVENT: - case STAC_LO_EVENT: - stac92xx_hp_detect(codec); - break; - case STAC_MIC_EVENT: - stac92xx_mic_detect(codec); - break; - } - - switch (event->action) { - case STAC_HP_EVENT: - case STAC_LO_EVENT: - case STAC_MIC_EVENT: - case STAC_INSERT_EVENT: - case STAC_PWR_EVENT: - if (spec->num_pwrs > 0) - stac92xx_pin_sense(codec, event->nid); - - switch (codec->subsystem_id) { - case 0x103c308f: - if (event->nid == 0xb) { - int pin = AC_PINCTL_IN_EN; - - if (get_pin_presence(codec, 0xa) - && get_pin_presence(codec, 0xb)) - pin |= AC_PINCTL_VREF_80; - if (!get_pin_presence(codec, 0xb)) - pin |= AC_PINCTL_VREF_80; - - /* toggle VREF state based on mic + hp pin - * status - */ - stac92xx_auto_set_pinctl(codec, 0x0a, pin); - } - } - break; - case STAC_VREF_EVENT: - data = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_DATA, 0); - /* toggle VREF state based on GPIOx status */ - snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, - !!(data & (1 << event->private_data))); - break; - } -} - -static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) -{ - struct hda_jack_tbl *event = snd_hda_jack_tbl_get(codec, nid); - if (!event) - return; - handle_unsol_event(codec, event); -} - -static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct hda_jack_tbl *event; - int tag; - - tag = (res >> 26) & 0x7f; - event = snd_hda_jack_tbl_get_from_tag(codec, tag); - if (!event) - return; - event->jack_dirty = 1; - handle_unsol_event(codec, event); - snd_hda_jack_report_sync(codec); -} - -static int hp_blike_system(u32 subsystem_id); - -static void set_hp_led_gpio(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - unsigned int gpio; - - if (spec->gpio_led) - return; - - gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); - gpio &= AC_GPIO_IO_COUNT; - if (gpio > 3) - spec->gpio_led = 0x08; /* GPIO 3 */ - else - spec->gpio_led = 0x01; /* GPIO 0 */ -} - -/* - * This method searches for the mute LED GPIO configuration - * provided as OEM string in SMBIOS. The format of that string - * is HP_Mute_LED_P_G or HP_Mute_LED_P - * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) - * that corresponds to the NOT muted state of the master volume - * and G is the index of the GPIO to use as the mute LED control (0..9) - * If _G portion is missing it is assigned based on the codec ID - * - * So, HP B-series like systems may have HP_Mute_LED_0 (current models) - * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings - * - * - * The dv-series laptops don't seem to have the HP_Mute_LED* strings in - * SMBIOS - at least the ones I have seen do not have them - which include - * my own system (HP Pavilion dv6-1110ax) and my cousin's - * HP Pavilion dv9500t CTO. - * Need more information on whether it is true across the entire series. - * -- kunal - */ -static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) -{ - struct sigmatel_spec *spec = codec->spec; - const struct dmi_device *dev = NULL; - - if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { - while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, - NULL, dev))) { - if (sscanf(dev->name, "HP_Mute_LED_%d_%x", - &spec->gpio_led_polarity, - &spec->gpio_led) == 2) { - unsigned int max_gpio; - max_gpio = snd_hda_param_read(codec, codec->afg, - AC_PAR_GPIO_CAP); - max_gpio &= AC_GPIO_IO_COUNT; - if (spec->gpio_led < max_gpio) - spec->gpio_led = 1 << spec->gpio_led; - else - spec->vref_mute_led_nid = spec->gpio_led; - return 1; - } - if (sscanf(dev->name, "HP_Mute_LED_%d", - &spec->gpio_led_polarity) == 1) { - set_hp_led_gpio(codec); - return 1; - } - /* BIOS bug: unfilled OEM string */ - if (strstr(dev->name, "HP_Mute_LED_P_G")) { - set_hp_led_gpio(codec); - switch (codec->subsystem_id) { - case 0x103c148a: - spec->gpio_led_polarity = 0; - break; - default: - spec->gpio_led_polarity = 1; - break; - } - return 1; - } - } - - /* - * Fallback case - if we don't find the DMI strings, - * we statically set the GPIO - if not a B-series system - * and default polarity is provided - */ - if (!hp_blike_system(codec->subsystem_id) && - (default_polarity == 0 || default_polarity == 1)) { - set_hp_led_gpio(codec); - spec->gpio_led_polarity = default_polarity; - return 1; - } - } - return 0; -} - -static int hp_blike_system(u32 subsystem_id) -{ - switch (subsystem_id) { - case 0x103c1520: - case 0x103c1521: - case 0x103c1523: - case 0x103c1524: - case 0x103c1525: - case 0x103c1722: - case 0x103c1723: - case 0x103c1724: - case 0x103c1725: - case 0x103c1726: - case 0x103c1727: - case 0x103c1728: - case 0x103c1729: - case 0x103c172a: - case 0x103c172b: - case 0x103c307e: - case 0x103c307f: - case 0x103c3080: - case 0x103c3081: - case 0x103c7007: - case 0x103c7008: - return 1; - } - return 0; -} - -#ifdef CONFIG_PROC_FS -static void stac92hd_proc_hook(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - if (nid == codec->afg) - snd_iprintf(buffer, "Power-Map: 0x%02x\n", - snd_hda_codec_read(codec, nid, 0, 0x0fec, 0x0)); -} - -static void analog_loop_proc_hook(struct snd_info_buffer *buffer, - struct hda_codec *codec, - unsigned int verb) -{ - snd_iprintf(buffer, "Analog Loopback: 0x%02x\n", - snd_hda_codec_read(codec, codec->afg, 0, verb, 0)); -} - -/* stac92hd71bxx, stac92hd73xx */ -static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - stac92hd_proc_hook(buffer, codec, nid); - if (nid == codec->afg) - analog_loop_proc_hook(buffer, codec, 0xfa0); -} - -static void stac9205_proc_hook(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - if (nid == codec->afg) - analog_loop_proc_hook(buffer, codec, 0xfe0); -} - -static void stac927x_proc_hook(struct snd_info_buffer *buffer, - struct hda_codec *codec, hda_nid_t nid) -{ - if (nid == codec->afg) - analog_loop_proc_hook(buffer, codec, 0xfeb); -} -#else -#define stac92hd_proc_hook NULL -#define stac92hd7x_proc_hook NULL -#define stac9205_proc_hook NULL -#define stac927x_proc_hook NULL -#endif - -#ifdef CONFIG_PM -static int stac92xx_resume(struct hda_codec *codec) -{ - stac92xx_init(codec); - snd_hda_codec_resume_amp(codec); - snd_hda_codec_resume_cache(codec); - /* fake event to set up pins again to override cached values */ - stac_fake_hp_events(codec); - return 0; -} - -static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) -{ - stac92xx_shutup(codec); - return 0; -} - -static int stac92xx_pre_resume(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - - /* sync mute LED */ - if (spec->vref_mute_led_nid) - stac_vrefout_set(codec, spec->vref_mute_led_nid, - spec->vref_led); - else if (spec->gpio_led) - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data); - return 0; -} - -static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, - unsigned int power_state) -{ - unsigned int afg_power_state = power_state; - struct sigmatel_spec *spec = codec->spec; - - if (power_state == AC_PWRST_D3) { - if (spec->vref_mute_led_nid) { - /* with vref-out pin used for mute led control - * codec AFG is prevented from D3 state - */ - afg_power_state = AC_PWRST_D1; - } - /* this delay seems necessary to avoid click noise at power-down */ - msleep(100); - } - snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, - afg_power_state); - snd_hda_codec_set_power_to_all(codec, fg, power_state, true); -} -#else -#define stac92xx_suspend NULL -#define stac92xx_resume NULL -#define stac92xx_pre_resume NULL -#define stac92xx_set_power_state NULL -#endif /* CONFIG_PM */ - -/* update mute-LED accoring to the master switch */ -static void stac92xx_update_led_status(struct hda_codec *codec, int enabled) -{ - struct sigmatel_spec *spec = codec->spec; - int muted = !enabled; - - if (!spec->gpio_led) - return; - - /* LED state is inverted on these systems */ - if (spec->gpio_led_polarity) - muted = !muted; - - if (!spec->vref_mute_led_nid) { - if (muted) - spec->gpio_data |= spec->gpio_led; - else - spec->gpio_data &= ~spec->gpio_led; - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data); - } else { - spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; - stac_vrefout_set(codec, spec->vref_mute_led_nid, - spec->vref_led); - } -} - -static const struct hda_codec_ops stac92xx_patch_ops = { - .build_controls = stac92xx_build_controls, - .build_pcms = stac92xx_build_pcms, - .init = stac92xx_init, - .free = stac92xx_free, - .unsol_event = stac92xx_unsol_event, -#ifdef CONFIG_PM - .suspend = stac92xx_suspend, - .resume = stac92xx_resume, -#endif - .reboot_notify = stac92xx_shutup, -}; - -static int patch_stac9200(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->no_trigger_sense = 1; - codec->spec = spec; - spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); - spec->pin_nids = stac9200_pin_nids; - spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, - stac9200_models, - stac9200_cfg_tbl); - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac9200_brd_tbl[spec->board_config]); - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = stac9200_dac_nids; - spec->adc_nids = stac9200_adc_nids; - spec->mux_nids = stac9200_mux_nids; - spec->num_muxes = 1; - spec->num_dmics = 0; - spec->num_adcs = 1; - spec->num_pwrs = 0; - - if (spec->board_config == STAC_9200_M4 || - spec->board_config == STAC_9200_M4_2 || - spec->board_config == STAC_9200_OQO) - spec->init = stac9200_eapd_init; - else - spec->init = stac9200_core_init; - spec->mixer = stac9200_mixer; - - if (spec->board_config == STAC_9200_PANASONIC) { - spec->gpio_mask = spec->gpio_dir = 0x09; - spec->gpio_data = 0x00; - } - - err = stac9200_parse_auto_config(codec); - if (err < 0) { - stac92xx_free(codec); - return err; - } - - /* CF-74 has no headphone detection, and the driver should *NOT* - * do detection and HP/speaker toggle because the hardware does it. - */ - if (spec->board_config == STAC_9200_PANASONIC) - spec->hp_detect = 0; - - codec->patch_ops = stac92xx_patch_ops; - - return 0; -} - -static int patch_stac925x(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->no_trigger_sense = 1; - codec->spec = spec; - spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); - spec->pin_nids = stac925x_pin_nids; - - /* Check first for codec ID */ - spec->board_config = snd_hda_check_board_codec_sid_config(codec, - STAC_925x_MODELS, - stac925x_models, - stac925x_codec_id_cfg_tbl); - - /* Now checks for PCI ID, if codec ID is not found */ - if (spec->board_config < 0) - spec->board_config = snd_hda_check_board_config(codec, - STAC_925x_MODELS, - stac925x_models, - stac925x_cfg_tbl); - again: - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac925x_brd_tbl[spec->board_config]); - - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = 1; - spec->multiout.dac_nids = stac925x_dac_nids; - spec->adc_nids = stac925x_adc_nids; - spec->mux_nids = stac925x_mux_nids; - spec->num_muxes = 1; - spec->num_adcs = 1; - spec->num_pwrs = 0; - switch (codec->vendor_id) { - case 0x83847632: /* STAC9202 */ - case 0x83847633: /* STAC9202D */ - case 0x83847636: /* STAC9251 */ - case 0x83847637: /* STAC9251D */ - spec->num_dmics = STAC925X_NUM_DMICS; - spec->dmic_nids = stac925x_dmic_nids; - spec->num_dmuxes = ARRAY_SIZE(stac925x_dmux_nids); - spec->dmux_nids = stac925x_dmux_nids; - break; - default: - spec->num_dmics = 0; - break; - } - - spec->init = stac925x_core_init; - spec->mixer = stac925x_mixer; - spec->num_caps = 1; - spec->capvols = stac925x_capvols; - spec->capsws = stac925x_capsws; - - err = stac92xx_parse_auto_config(codec); - if (!err) { - if (spec->board_config < 0) { - printk(KERN_WARNING "hda_codec: No auto-config is " - "available, default to model=ref\n"); - spec->board_config = STAC_925x_REF; - goto again; - } - err = -EINVAL; - } - if (err < 0) { - stac92xx_free(codec); - return err; - } - - codec->patch_ops = stac92xx_patch_ops; - - return 0; -} - -static int patch_stac92hd73xx(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; - int err = 0; - int num_dacs; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->no_trigger_sense = 1; - codec->spec = spec; - spec->linear_tone_beep = 0; - codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; - spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); - spec->pin_nids = stac92hd73xx_pin_nids; - spec->board_config = snd_hda_check_board_config(codec, - STAC_92HD73XX_MODELS, - stac92hd73xx_models, - stac92hd73xx_cfg_tbl); - /* check codec subsystem id if not found */ - if (spec->board_config < 0) - spec->board_config = - snd_hda_check_board_codec_sid_config(codec, - STAC_92HD73XX_MODELS, stac92hd73xx_models, - stac92hd73xx_codec_id_cfg_tbl); -again: - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac92hd73xx_brd_tbl[spec->board_config]); - - num_dacs = snd_hda_get_connections(codec, 0x0a, - conn, STAC92HD73_DAC_COUNT + 2) - 1; - - if (num_dacs < 3 || num_dacs > 5) { - printk(KERN_WARNING "hda_codec: Could not determine " - "number of channels defaulting to DAC count\n"); - num_dacs = STAC92HD73_DAC_COUNT; - } - spec->init = stac92hd73xx_core_init; - switch (num_dacs) { - case 0x3: /* 6 Channel */ - spec->aloopback_ctl = stac92hd73xx_6ch_loopback; - break; - case 0x4: /* 8 Channel */ - spec->aloopback_ctl = stac92hd73xx_8ch_loopback; - break; - case 0x5: /* 10 Channel */ - spec->aloopback_ctl = stac92hd73xx_10ch_loopback; - break; - } - spec->multiout.dac_nids = spec->dac_nids; - - spec->aloopback_mask = 0x01; - spec->aloopback_shift = 8; - - spec->digbeep_nid = 0x1c; - spec->mux_nids = stac92hd73xx_mux_nids; - spec->adc_nids = stac92hd73xx_adc_nids; - spec->dmic_nids = stac92hd73xx_dmic_nids; - spec->dmux_nids = stac92hd73xx_dmux_nids; - spec->smux_nids = stac92hd73xx_smux_nids; - - spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids); - spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids); - spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids); - - spec->num_caps = STAC92HD73XX_NUM_CAPS; - spec->capvols = stac92hd73xx_capvols; - spec->capsws = stac92hd73xx_capsws; - - switch (spec->board_config) { - case STAC_DELL_EQ: - spec->init = dell_eq_core_init; - /* fallthru */ - case STAC_DELL_M6_AMIC: - case STAC_DELL_M6_DMIC: - case STAC_DELL_M6_BOTH: - spec->num_smuxes = 0; - spec->eapd_switch = 0; - - switch (spec->board_config) { - case STAC_DELL_M6_AMIC: /* Analog Mics */ - snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); - spec->num_dmics = 0; - break; - case STAC_DELL_M6_DMIC: /* Digital Mics */ - snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); - spec->num_dmics = 1; - break; - case STAC_DELL_M6_BOTH: /* Both */ - snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); - snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); - spec->num_dmics = 1; - break; - } - break; - case STAC_ALIENWARE_M17X: - spec->num_dmics = STAC92HD73XX_NUM_DMICS; - spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); - spec->eapd_switch = 0; - break; - default: - spec->num_dmics = STAC92HD73XX_NUM_DMICS; - spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); - spec->eapd_switch = 1; - break; - } - if (spec->board_config != STAC_92HD73XX_REF) { - /* GPIO0 High = Enable EAPD */ - spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; - spec->gpio_data = 0x01; - } - - spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); - spec->pwr_nids = stac92hd73xx_pwr_nids; - - err = stac92xx_parse_auto_config(codec); - - if (!err) { - if (spec->board_config < 0) { - printk(KERN_WARNING "hda_codec: No auto-config is " - "available, default to model=ref\n"); - spec->board_config = STAC_92HD73XX_REF; - goto again; - } - err = -EINVAL; - } - - if (err < 0) { - stac92xx_free(codec); - return err; - } - - if (spec->board_config == STAC_92HD73XX_NO_JD) - spec->hp_detect = 0; - - codec->patch_ops = stac92xx_patch_ops; - - codec->proc_widget_hook = stac92hd7x_proc_hook; - - return 0; -} - -static int hp_bnb2011_with_dock(struct hda_codec *codec) -{ - if (codec->vendor_id != 0x111d7605 && - codec->vendor_id != 0x111d76d1) - return 0; - - switch (codec->subsystem_id) { - case 0x103c1618: - case 0x103c1619: - case 0x103c161a: - case 0x103c161b: - case 0x103c161c: - case 0x103c161d: - case 0x103c161e: - case 0x103c161f: - - case 0x103c162a: - case 0x103c162b: - - case 0x103c1630: - case 0x103c1631: - - case 0x103c1633: - case 0x103c1634: - case 0x103c1635: - - case 0x103c3587: - case 0x103c3588: - case 0x103c3589: - case 0x103c358a: - - case 0x103c3667: - case 0x103c3668: - case 0x103c3669: - - return 1; - } - return 0; -} - -static void stac92hd8x_add_pin(struct hda_codec *codec, hda_nid_t nid) -{ - struct sigmatel_spec *spec = codec->spec; - unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); - int i; - - spec->auto_pin_nids[spec->auto_pin_cnt] = nid; - spec->auto_pin_cnt++; - - if (get_defcfg_device(def_conf) == AC_JACK_MIC_IN && - get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) { - for (i = 0; i < ARRAY_SIZE(stac92hd83xxx_dmic_nids); i++) { - if (nid == stac92hd83xxx_dmic_nids[i]) { - spec->auto_dmic_nids[spec->auto_dmic_cnt] = nid; - spec->auto_dmic_cnt++; - } - } - } -} - -static void stac92hd8x_add_adc(struct hda_codec *codec, hda_nid_t nid) -{ - struct sigmatel_spec *spec = codec->spec; - - spec->auto_adc_nids[spec->auto_adc_cnt] = nid; - spec->auto_adc_cnt++; -} - -static void stac92hd8x_add_mux(struct hda_codec *codec, hda_nid_t nid) -{ - int i, j; - struct sigmatel_spec *spec = codec->spec; - - for (i = 0; i < spec->auto_adc_cnt; i++) { - if (get_connection_index(codec, - spec->auto_adc_nids[i], nid) >= 0) { - /* mux and volume for adc_nids[i] */ - if (!spec->auto_mux_nids[i]) { - spec->auto_mux_nids[i] = nid; - /* 92hd codecs capture volume is in mux */ - spec->auto_capvols[i] = HDA_COMPOSE_AMP_VAL(nid, - 3, 0, HDA_OUTPUT); - } - for (j = 0; j < spec->auto_dmic_cnt; j++) { - if (get_connection_index(codec, nid, - spec->auto_dmic_nids[j]) >= 0) { - /* dmux for adc_nids[i] */ - if (!spec->auto_dmux_nids[i]) - spec->auto_dmux_nids[i] = nid; - break; - } - } - break; - } - } -} - -static void stac92hd8x_fill_auto_spec(struct hda_codec *codec) -{ - hda_nid_t nid, end_nid; - unsigned int wid_caps, wid_type; - struct sigmatel_spec *spec = codec->spec; - - end_nid = codec->start_nid + codec->num_nodes; - - for (nid = codec->start_nid; nid < end_nid; nid++) { - wid_caps = get_wcaps(codec, nid); - wid_type = get_wcaps_type(wid_caps); - - if (wid_type == AC_WID_PIN) - stac92hd8x_add_pin(codec, nid); - - if (wid_type == AC_WID_AUD_IN && !(wid_caps & AC_WCAP_DIGITAL)) - stac92hd8x_add_adc(codec, nid); - } - - for (nid = codec->start_nid; nid < end_nid; nid++) { - wid_caps = get_wcaps(codec, nid); - wid_type = get_wcaps_type(wid_caps); - - if (wid_type == AC_WID_AUD_SEL) - stac92hd8x_add_mux(codec, nid); - } - - spec->pin_nids = spec->auto_pin_nids; - spec->num_pins = spec->auto_pin_cnt; - spec->adc_nids = spec->auto_adc_nids; - spec->num_adcs = spec->auto_adc_cnt; - spec->capvols = spec->auto_capvols; - spec->capsws = spec->auto_capvols; - spec->num_caps = spec->auto_adc_cnt; - spec->mux_nids = spec->auto_mux_nids; - spec->num_muxes = spec->auto_adc_cnt; - spec->dmux_nids = spec->auto_dmux_nids; - spec->num_dmuxes = spec->auto_adc_cnt; - spec->dmic_nids = spec->auto_dmic_nids; - spec->num_dmics = spec->auto_dmic_cnt; -} - -static int patch_stac92hd83xxx(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - if (hp_bnb2011_with_dock(codec)) { - snd_hda_codec_set_pincfg(codec, 0xa, 0x2101201f); - snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e); - } - - codec->no_trigger_sense = 1; - codec->spec = spec; - - stac92hd8x_fill_auto_spec(codec); - - spec->linear_tone_beep = 0; - codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; - spec->digbeep_nid = 0x21; - spec->pwr_nids = stac92hd83xxx_pwr_nids; - spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); - spec->multiout.dac_nids = spec->dac_nids; - spec->init = stac92hd83xxx_core_init; - - spec->board_config = snd_hda_check_board_config(codec, - STAC_92HD83XXX_MODELS, - stac92hd83xxx_models, - stac92hd83xxx_cfg_tbl); - /* check codec subsystem id if not found */ - if (spec->board_config < 0) - spec->board_config = - snd_hda_check_board_codec_sid_config(codec, - STAC_92HD83XXX_MODELS, stac92hd83xxx_models, - stac92hd83xxx_codec_id_cfg_tbl); -again: - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac92hd83xxx_brd_tbl[spec->board_config]); - - codec->patch_ops = stac92xx_patch_ops; - - switch (spec->board_config) { - case STAC_HP_ZEPHYR: - spec->init = stac92hd83xxx_hp_zephyr_init; - break; - } - - if (find_mute_led_cfg(codec, -1/*no default cfg*/)) - snd_printd("mute LED gpio %d polarity %d\n", - spec->gpio_led, - spec->gpio_led_polarity); - - if (spec->gpio_led) { - if (!spec->vref_mute_led_nid) { - spec->gpio_mask |= spec->gpio_led; - spec->gpio_dir |= spec->gpio_led; - spec->gpio_data |= spec->gpio_led; - } else { - codec->patch_ops.set_power_state = - stac92xx_set_power_state; - } -#ifdef CONFIG_PM - codec->patch_ops.pre_resume = stac92xx_pre_resume; -#endif - } - - err = stac92xx_parse_auto_config(codec); - if (!err) { - if (spec->board_config < 0) { - printk(KERN_WARNING "hda_codec: No auto-config is " - "available, default to model=ref\n"); - spec->board_config = STAC_92HD83XXX_REF; - goto again; - } - err = -EINVAL; - } - - if (err < 0) { - stac92xx_free(codec); - return err; - } - - codec->proc_widget_hook = stac92hd_proc_hook; - - return 0; -} - -static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, - hda_nid_t dig0pin) -{ - struct sigmatel_spec *spec = codec->spec; - int idx; - - for (idx = 0; idx < spec->num_pins; idx++) - if (spec->pin_nids[idx] == dig0pin) - break; - if ((idx + 2) >= spec->num_pins) - return 0; - - /* dig1pin case */ - if (stac_get_defcfg_connect(codec, idx + 1) != AC_JACK_PORT_NONE) - return 2; - - /* dig0pin + dig2pin case */ - if (stac_get_defcfg_connect(codec, idx + 2) != AC_JACK_PORT_NONE) - return 2; - if (stac_get_defcfg_connect(codec, idx) != AC_JACK_PORT_NONE) - return 1; - else - return 0; -} - -/* HP dv7 bass switch - GPIO5 */ -#define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info -static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20); - return 0; -} - -static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - unsigned int gpio_data; - - gpio_data = (spec->gpio_data & ~0x20) | - (ucontrol->value.integer.value[0] ? 0x20 : 0); - if (gpio_data == spec->gpio_data) - return 0; - spec->gpio_data = gpio_data; - stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); - return 1; -} - -static const struct snd_kcontrol_new stac_hp_bass_sw_ctrl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = stac_hp_bass_gpio_info, - .get = stac_hp_bass_gpio_get, - .put = stac_hp_bass_gpio_put, -}; - -static int stac_add_hp_bass_switch(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - - if (!stac_control_new(spec, &stac_hp_bass_sw_ctrl, - "Bass Speaker Playback Switch", 0)) - return -ENOMEM; - - spec->gpio_mask |= 0x20; - spec->gpio_dir |= 0x20; - spec->gpio_data |= 0x20; - return 0; -} - -static int patch_stac92hd71bxx(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - const struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; - unsigned int pin_cfg; - int err = 0; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->no_trigger_sense = 1; - codec->spec = spec; - spec->linear_tone_beep = 0; - codec->patch_ops = stac92xx_patch_ops; - spec->num_pins = STAC92HD71BXX_NUM_PINS; - switch (codec->vendor_id) { - case 0x111d76b6: - case 0x111d76b7: - spec->pin_nids = stac92hd71bxx_pin_nids_4port; - break; - case 0x111d7603: - case 0x111d7608: - /* On 92HD75Bx 0x27 isn't a pin nid */ - spec->num_pins--; - /* fallthrough */ - default: - spec->pin_nids = stac92hd71bxx_pin_nids_6port; - } - spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); - spec->board_config = snd_hda_check_board_config(codec, - STAC_92HD71BXX_MODELS, - stac92hd71bxx_models, - stac92hd71bxx_cfg_tbl); -again: - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac92hd71bxx_brd_tbl[spec->board_config]); - - if (spec->board_config != STAC_92HD71BXX_REF) { - /* GPIO0 = EAPD */ - spec->gpio_mask = 0x01; - spec->gpio_dir = 0x01; - spec->gpio_data = 0x01; - } - - spec->dmic_nids = stac92hd71bxx_dmic_nids; - spec->dmux_nids = stac92hd71bxx_dmux_nids; - - spec->num_caps = STAC92HD71BXX_NUM_CAPS; - spec->capvols = stac92hd71bxx_capvols; - spec->capsws = stac92hd71bxx_capsws; - - switch (codec->vendor_id) { - case 0x111d76b6: /* 4 Port without Analog Mixer */ - case 0x111d76b7: - unmute_init++; - /* fallthru */ - case 0x111d76b4: /* 6 Port without Analog Mixer */ - case 0x111d76b5: - spec->init = stac92hd71bxx_core_init; - codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; - spec->num_dmics = stac92xx_connected_ports(codec, - stac92hd71bxx_dmic_nids, - STAC92HD71BXX_NUM_DMICS); - break; - case 0x111d7608: /* 5 Port with Analog Mixer */ - switch (spec->board_config) { - case STAC_HP_M4: - /* Enable VREF power saving on GPIO1 detect */ - err = stac_add_event(codec, codec->afg, - STAC_VREF_EVENT, 0x02); - if (err < 0) - return err; - snd_hda_codec_write_cache(codec, codec->afg, 0, - AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); - snd_hda_jack_detect_enable(codec, codec->afg, 0); - spec->gpio_mask |= 0x02; - break; - } - if ((codec->revision_id & 0xf) == 0 || - (codec->revision_id & 0xf) == 1) - spec->stream_delay = 40; /* 40 milliseconds */ - - /* disable VSW */ - spec->init = stac92hd71bxx_core_init; - unmute_init++; - snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); - snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); - spec->dmic_nids = stac92hd71bxx_dmic_5port_nids; - spec->num_dmics = stac92xx_connected_ports(codec, - stac92hd71bxx_dmic_5port_nids, - STAC92HD71BXX_NUM_DMICS - 1); - break; - case 0x111d7603: /* 6 Port with Analog Mixer */ - if ((codec->revision_id & 0xf) == 1) - spec->stream_delay = 40; /* 40 milliseconds */ - - /* fallthru */ - default: - spec->init = stac92hd71bxx_core_init; - codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; - spec->num_dmics = stac92xx_connected_ports(codec, - stac92hd71bxx_dmic_nids, - STAC92HD71BXX_NUM_DMICS); - break; - } - - if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) - snd_hda_sequence_write_cache(codec, unmute_init); - - spec->aloopback_ctl = stac92hd71bxx_loopback; - spec->aloopback_mask = 0x50; - spec->aloopback_shift = 0; - - spec->powerdown_adcs = 1; - spec->digbeep_nid = 0x26; - spec->mux_nids = stac92hd71bxx_mux_nids; - spec->adc_nids = stac92hd71bxx_adc_nids; - spec->smux_nids = stac92hd71bxx_smux_nids; - spec->pwr_nids = stac92hd71bxx_pwr_nids; - - spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); - spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); - spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); - spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e); - - snd_printdd("Found board config: %d\n", spec->board_config); - - switch (spec->board_config) { - case STAC_HP_M4: - /* enable internal microphone */ - snd_hda_codec_set_pincfg(codec, 0x0e, 0x01813040); - stac92xx_auto_set_pinctl(codec, 0x0e, - AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); - /* fallthru */ - case STAC_DELL_M4_2: - spec->num_dmics = 0; - spec->num_smuxes = 0; - spec->num_dmuxes = 0; - break; - case STAC_DELL_M4_1: - case STAC_DELL_M4_3: - spec->num_dmics = 1; - spec->num_smuxes = 0; - spec->num_dmuxes = 1; - break; - case STAC_HP_DV4_1222NR: - spec->num_dmics = 1; - /* I don't know if it needs 1 or 2 smuxes - will wait for - * bug reports to fix if needed - */ - spec->num_smuxes = 1; - spec->num_dmuxes = 1; - /* fallthrough */ - case STAC_HP_DV4: - spec->gpio_led = 0x01; - /* fallthrough */ - case STAC_HP_DV5: - snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); - stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); - /* HP dv6 gives the headphone pin as a line-out. Thus we - * need to set hp_detect flag here to force to enable HP - * detection. - */ - spec->hp_detect = 1; - break; - case STAC_HP_HDX: - spec->num_dmics = 1; - spec->num_dmuxes = 1; - spec->num_smuxes = 1; - spec->gpio_led = 0x08; - break; - } - - if (hp_blike_system(codec->subsystem_id)) { - pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); - if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || - get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || - get_defcfg_device(pin_cfg) == AC_JACK_HP_OUT) { - /* It was changed in the BIOS to just satisfy MS DTM. - * Lets turn it back into slaved HP - */ - pin_cfg = (pin_cfg & (~AC_DEFCFG_DEVICE)) - | (AC_JACK_HP_OUT << - AC_DEFCFG_DEVICE_SHIFT); - pin_cfg = (pin_cfg & (~(AC_DEFCFG_DEF_ASSOC - | AC_DEFCFG_SEQUENCE))) - | 0x1f; - snd_hda_codec_set_pincfg(codec, 0x0f, pin_cfg); - } - } - - if (find_mute_led_cfg(codec, 1)) - snd_printd("mute LED gpio %d polarity %d\n", - spec->gpio_led, - spec->gpio_led_polarity); - - if (spec->gpio_led) { - if (!spec->vref_mute_led_nid) { - spec->gpio_mask |= spec->gpio_led; - spec->gpio_dir |= spec->gpio_led; - spec->gpio_data |= spec->gpio_led; - } else { - codec->patch_ops.set_power_state = - stac92xx_set_power_state; - } -#ifdef CONFIG_PM - codec->patch_ops.pre_resume = stac92xx_pre_resume; -#endif - } - - spec->multiout.dac_nids = spec->dac_nids; - - err = stac92xx_parse_auto_config(codec); - if (!err) { - if (spec->board_config < 0) { - printk(KERN_WARNING "hda_codec: No auto-config is " - "available, default to model=ref\n"); - spec->board_config = STAC_92HD71BXX_REF; - goto again; - } - err = -EINVAL; - } - - if (err < 0) { - stac92xx_free(codec); - return err; - } - - /* enable bass on HP dv7 */ - if (spec->board_config == STAC_HP_DV4 || - spec->board_config == STAC_HP_DV5) { - unsigned int cap; - cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); - cap &= AC_GPIO_IO_COUNT; - if (cap >= 6) - stac_add_hp_bass_switch(codec); - } - - codec->proc_widget_hook = stac92hd7x_proc_hook; - - return 0; -} - -static int patch_stac922x(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->no_trigger_sense = 1; - codec->spec = spec; - spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); - spec->pin_nids = stac922x_pin_nids; - spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, - stac922x_models, - stac922x_cfg_tbl); - if (spec->board_config == STAC_INTEL_MAC_AUTO) { - spec->gpio_mask = spec->gpio_dir = 0x03; - spec->gpio_data = 0x03; - /* Intel Macs have all same PCI SSID, so we need to check - * codec SSID to distinguish the exact models - */ - printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id); - switch (codec->subsystem_id) { - - case 0x106b0800: - spec->board_config = STAC_INTEL_MAC_V1; - break; - case 0x106b0600: - case 0x106b0700: - spec->board_config = STAC_INTEL_MAC_V2; - break; - case 0x106b0e00: - case 0x106b0f00: - case 0x106b1600: - case 0x106b1700: - case 0x106b0200: - case 0x106b1e00: - spec->board_config = STAC_INTEL_MAC_V3; - break; - case 0x106b1a00: - case 0x00000100: - spec->board_config = STAC_INTEL_MAC_V4; - break; - case 0x106b0a00: - case 0x106b2200: - spec->board_config = STAC_INTEL_MAC_V5; - break; - default: - spec->board_config = STAC_INTEL_MAC_V3; - break; - } - } - - again: - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac922x_brd_tbl[spec->board_config]); - - spec->adc_nids = stac922x_adc_nids; - spec->mux_nids = stac922x_mux_nids; - spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); - spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids); - spec->num_dmics = 0; - spec->num_pwrs = 0; - - spec->init = stac922x_core_init; - - spec->num_caps = STAC922X_NUM_CAPS; - spec->capvols = stac922x_capvols; - spec->capsws = stac922x_capsws; - - spec->multiout.dac_nids = spec->dac_nids; - - err = stac92xx_parse_auto_config(codec); - if (!err) { - if (spec->board_config < 0) { - printk(KERN_WARNING "hda_codec: No auto-config is " - "available, default to model=ref\n"); - spec->board_config = STAC_D945_REF; - goto again; - } - err = -EINVAL; - } - if (err < 0) { - stac92xx_free(codec); - return err; - } - - codec->patch_ops = stac92xx_patch_ops; - - /* Fix Mux capture level; max to 2 */ - snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT, - (0 << AC_AMPCAP_OFFSET_SHIFT) | - (2 << AC_AMPCAP_NUM_STEPS_SHIFT) | - (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | - (0 << AC_AMPCAP_MUTE_SHIFT)); - - return 0; -} - -static int patch_stac927x(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->no_trigger_sense = 1; - codec->spec = spec; - spec->linear_tone_beep = 1; - codec->slave_dig_outs = stac927x_slave_dig_outs; - spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); - spec->pin_nids = stac927x_pin_nids; - spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, - stac927x_models, - stac927x_cfg_tbl); - again: - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac927x_brd_tbl[spec->board_config]); - - spec->digbeep_nid = 0x23; - spec->adc_nids = stac927x_adc_nids; - spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); - spec->mux_nids = stac927x_mux_nids; - spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); - spec->smux_nids = stac927x_smux_nids; - spec->num_smuxes = ARRAY_SIZE(stac927x_smux_nids); - spec->spdif_labels = stac927x_spdif_labels; - spec->dac_list = stac927x_dac_nids; - spec->multiout.dac_nids = spec->dac_nids; - - if (spec->board_config != STAC_D965_REF) { - /* GPIO0 High = Enable EAPD */ - spec->eapd_mask = spec->gpio_mask = 0x01; - spec->gpio_dir = spec->gpio_data = 0x01; - } - - switch (spec->board_config) { - case STAC_D965_3ST: - case STAC_D965_5ST: - /* GPIO0 High = Enable EAPD */ - spec->num_dmics = 0; - spec->init = d965_core_init; - break; - case STAC_DELL_BIOS: - switch (codec->subsystem_id) { - case 0x10280209: - case 0x1028022e: - /* correct the device field to SPDIF out */ - snd_hda_codec_set_pincfg(codec, 0x21, 0x01442070); - break; - } - /* configure the analog microphone on some laptops */ - snd_hda_codec_set_pincfg(codec, 0x0c, 0x90a79130); - /* correct the front output jack as a hp out */ - snd_hda_codec_set_pincfg(codec, 0x0f, 0x0227011f); - /* correct the front input jack as a mic */ - snd_hda_codec_set_pincfg(codec, 0x0e, 0x02a79130); - /* fallthru */ - case STAC_DELL_3ST: - if (codec->subsystem_id != 0x1028022f) { - /* GPIO2 High = Enable EAPD */ - spec->eapd_mask = spec->gpio_mask = 0x04; - spec->gpio_dir = spec->gpio_data = 0x04; - } - spec->dmic_nids = stac927x_dmic_nids; - spec->num_dmics = STAC927X_NUM_DMICS; - - spec->init = dell_3st_core_init; - spec->dmux_nids = stac927x_dmux_nids; - spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids); - break; - case STAC_927X_VOLKNOB: - spec->num_dmics = 0; - spec->init = stac927x_volknob_core_init; - break; - default: - spec->num_dmics = 0; - spec->init = stac927x_core_init; - break; - } - - spec->num_caps = STAC927X_NUM_CAPS; - spec->capvols = stac927x_capvols; - spec->capsws = stac927x_capsws; - - spec->num_pwrs = 0; - spec->aloopback_ctl = stac927x_loopback; - spec->aloopback_mask = 0x40; - spec->aloopback_shift = 0; - spec->eapd_switch = 1; - - err = stac92xx_parse_auto_config(codec); - if (!err) { - if (spec->board_config < 0) { - printk(KERN_WARNING "hda_codec: No auto-config is " - "available, default to model=ref\n"); - spec->board_config = STAC_D965_REF; - goto again; - } - err = -EINVAL; - } - if (err < 0) { - stac92xx_free(codec); - return err; - } - - codec->patch_ops = stac92xx_patch_ops; - - codec->proc_widget_hook = stac927x_proc_hook; - - /* - * !!FIXME!! - * The STAC927x seem to require fairly long delays for certain - * command sequences. With too short delays (even if the answer - * is set to RIRB properly), it results in the silence output - * on some hardwares like Dell. - * - * The below flag enables the longer delay (see get_response - * in hda_intel.c). - */ - codec->bus->needs_damn_long_delay = 1; - - /* no jack detecion for ref-no-jd model */ - if (spec->board_config == STAC_D965_REF_NO_JD) - spec->hp_detect = 0; - - return 0; -} - -static int patch_stac9205(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->no_trigger_sense = 1; - codec->spec = spec; - spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); - spec->pin_nids = stac9205_pin_nids; - spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, - stac9205_models, - stac9205_cfg_tbl); - again: - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac9205_brd_tbl[spec->board_config]); - - spec->digbeep_nid = 0x23; - spec->adc_nids = stac9205_adc_nids; - spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); - spec->mux_nids = stac9205_mux_nids; - spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); - spec->smux_nids = stac9205_smux_nids; - spec->num_smuxes = ARRAY_SIZE(stac9205_smux_nids); - spec->dmic_nids = stac9205_dmic_nids; - spec->num_dmics = STAC9205_NUM_DMICS; - spec->dmux_nids = stac9205_dmux_nids; - spec->num_dmuxes = ARRAY_SIZE(stac9205_dmux_nids); - spec->num_pwrs = 0; - - spec->init = stac9205_core_init; - spec->aloopback_ctl = stac9205_loopback; - - spec->num_caps = STAC9205_NUM_CAPS; - spec->capvols = stac9205_capvols; - spec->capsws = stac9205_capsws; - - spec->aloopback_mask = 0x40; - spec->aloopback_shift = 0; - /* Turn on/off EAPD per HP plugging */ - if (spec->board_config != STAC_9205_EAPD) - spec->eapd_switch = 1; - spec->multiout.dac_nids = spec->dac_nids; - - switch (spec->board_config){ - case STAC_9205_DELL_M43: - /* Enable SPDIF in/out */ - snd_hda_codec_set_pincfg(codec, 0x1f, 0x01441030); - snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030); - - /* Enable unsol response for GPIO4/Dock HP connection */ - err = stac_add_event(codec, codec->afg, STAC_VREF_EVENT, 0x01); - if (err < 0) - return err; - snd_hda_codec_write_cache(codec, codec->afg, 0, - AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); - snd_hda_jack_detect_enable(codec, codec->afg, 0); - - spec->gpio_dir = 0x0b; - spec->eapd_mask = 0x01; - spec->gpio_mask = 0x1b; - spec->gpio_mute = 0x10; - /* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute, - * GPIO3 Low = DRM - */ - spec->gpio_data = 0x01; - break; - case STAC_9205_REF: - /* SPDIF-In enabled */ - break; - default: - /* GPIO0 High = EAPD */ - spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; - spec->gpio_data = 0x01; - break; - } - - err = stac92xx_parse_auto_config(codec); - if (!err) { - if (spec->board_config < 0) { - printk(KERN_WARNING "hda_codec: No auto-config is " - "available, default to model=ref\n"); - spec->board_config = STAC_9205_REF; - goto again; - } - err = -EINVAL; - } - if (err < 0) { - stac92xx_free(codec); - return err; - } - - codec->patch_ops = stac92xx_patch_ops; - - codec->proc_widget_hook = stac9205_proc_hook; - - return 0; -} - -/* - * STAC9872 hack - */ - -static const struct hda_verb stac9872_core_init[] = { - {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ - {} -}; - -static const hda_nid_t stac9872_pin_nids[] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x11, 0x13, 0x14, -}; - -static const hda_nid_t stac9872_adc_nids[] = { - 0x8 /*,0x6*/ -}; - -static const hda_nid_t stac9872_mux_nids[] = { - 0x15 -}; - -static const unsigned long stac9872_capvols[] = { - HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), -}; -#define stac9872_capsws stac9872_capvols - -static const unsigned int stac9872_vaio_pin_configs[9] = { - 0x03211020, 0x411111f0, 0x411111f0, 0x03a15030, - 0x411111f0, 0x90170110, 0x411111f0, 0x411111f0, - 0x90a7013e -}; - -static const char * const stac9872_models[STAC_9872_MODELS] = { - [STAC_9872_AUTO] = "auto", - [STAC_9872_VAIO] = "vaio", -}; - -static const unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = { - [STAC_9872_VAIO] = stac9872_vaio_pin_configs, -}; - -static const struct snd_pci_quirk stac9872_cfg_tbl[] = { - SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0, - "Sony VAIO F/S", STAC_9872_VAIO), - {} /* terminator */ -}; - -static int patch_stac9872(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - codec->no_trigger_sense = 1; - codec->spec = spec; - spec->linear_tone_beep = 1; - spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); - spec->pin_nids = stac9872_pin_nids; - - spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, - stac9872_models, - stac9872_cfg_tbl); - if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", - codec->chip_name); - else - stac92xx_set_config_regs(codec, - stac9872_brd_tbl[spec->board_config]); - - spec->multiout.dac_nids = spec->dac_nids; - spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); - spec->adc_nids = stac9872_adc_nids; - spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids); - spec->mux_nids = stac9872_mux_nids; - spec->init = stac9872_core_init; - spec->num_caps = 1; - spec->capvols = stac9872_capvols; - spec->capsws = stac9872_capsws; - - err = stac92xx_parse_auto_config(codec); - if (err < 0) { - stac92xx_free(codec); - return -EINVAL; - } - spec->input_mux = &spec->private_imux; - codec->patch_ops = stac92xx_patch_ops; - return 0; -} - - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_sigmatel[] = { - { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, - { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, - { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, - { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x }, - { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, - { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, - { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, - { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac927x }, - { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac927x }, - { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac927x }, - { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac927x }, - { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac927x }, - { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac927x }, - { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, - { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, - { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, - { .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x }, - { .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x }, - { .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x }, - { .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x }, - { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, - { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, - { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, - { .id = 0x83847632, .name = "STAC9202", .patch = patch_stac925x }, - { .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x }, - { .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x }, - { .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x }, - { .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x }, - { .id = 0x83847637, .name = "STAC9250D", .patch = patch_stac925x }, - { .id = 0x83847645, .name = "92HD206X", .patch = patch_stac927x }, - { .id = 0x83847646, .name = "92HD206D", .patch = patch_stac927x }, - /* The following does not take into account .id=0x83847661 when subsys = - * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are - * currently not fully supported. - */ - { .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 }, - { .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 }, - { .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 }, - { .id = 0x83847698, .name = "STAC9205", .patch = patch_stac9205 }, - { .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 }, - { .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 }, - { .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 }, - { .id = 0x838476a3, .name = "STAC9204D", .patch = patch_stac9205 }, - { .id = 0x838476a4, .name = "STAC9255", .patch = patch_stac9205 }, - { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, - { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, - { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, - { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, - { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76d1, .name = "92HD87B1/3", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76d9, .name = "92HD87B2/4", .patch = patch_stac92hd83xxx}, - { .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx}, - { .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx}, - { .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx}, - { .id = 0x111d7669, .name = "92HD88B4", .patch = patch_stac92hd83xxx}, - { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, - { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, - { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, - { .id = 0x111d7676, .name = "92HD73E1X5", .patch = patch_stac92hd73xx }, - { .id = 0x111d76b0, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, - { .id = 0x111d76b1, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, - { .id = 0x111d76b2, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, - { .id = 0x111d76b3, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, - { .id = 0x111d76b4, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, - { .id = 0x111d76b5, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, - { .id = 0x111d76b6, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, - { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, - { .id = 0x111d76c0, .name = "92HD89C3", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c1, .name = "92HD89C2", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c2, .name = "92HD89C1", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c3, .name = "92HD89B3", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c4, .name = "92HD89B2", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c5, .name = "92HD89B1", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c6, .name = "92HD89E3", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c7, .name = "92HD89E2", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c8, .name = "92HD89E1", .patch = patch_stac92hd73xx }, - { .id = 0x111d76c9, .name = "92HD89D3", .patch = patch_stac92hd73xx }, - { .id = 0x111d76ca, .name = "92HD89D2", .patch = patch_stac92hd73xx }, - { .id = 0x111d76cb, .name = "92HD89D1", .patch = patch_stac92hd73xx }, - { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, - { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, - { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, - { .id = 0x111d76df, .name = "92HD93BXX", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76e3, .name = "92HD98BXX", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76e5, .name = "92HD99BXX", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76e8, .name = "92HD66B1X5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76e9, .name = "92HD66B2X5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76ea, .name = "92HD66B3X5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76eb, .name = "92HD66C1X5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76ec, .name = "92HD66C2X5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76ed, .name = "92HD66C3X5", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76ee, .name = "92HD66B1X3", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76ef, .name = "92HD66B2X3", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76f0, .name = "92HD66B3X3", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76f1, .name = "92HD66C1X3", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76f2, .name = "92HD66C2X3", .patch = patch_stac92hd83xxx}, - { .id = 0x111d76f3, .name = "92HD66C3/65", .patch = patch_stac92hd83xxx}, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:8384*"); -MODULE_ALIAS("snd-hda-codec-id:111d*"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec"); - -static struct hda_codec_preset_list sigmatel_list = { - .preset = snd_hda_preset_sigmatel, - .owner = THIS_MODULE, -}; - -static int __init patch_sigmatel_init(void) -{ - return snd_hda_add_codec_preset(&sigmatel_list); -} - -static void __exit patch_sigmatel_exit(void) -{ - snd_hda_delete_codec_preset(&sigmatel_list); -} - -module_init(patch_sigmatel_init) -module_exit(patch_sigmatel_exit) diff --git a/ANDROID_3.4.5/sound/pci/hda/patch_via.c b/ANDROID_3.4.5/sound/pci/hda/patch_via.c deleted file mode 100644 index 06214fdc..00000000 --- a/ANDROID_3.4.5/sound/pci/hda/patch_via.c +++ /dev/null @@ -1,3935 +0,0 @@ -/* - * Universal Interface for Intel High Definition Audio Codec - * - * HD audio interface patch for VIA VT17xx/VT18xx/VT20xx codec - * - * (C) 2006-2009 VIA Technology, Inc. - * (C) 2006-2008 Takashi Iwai - * - * This driver 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 driver 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 - */ - -/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */ -/* */ -/* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */ -/* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */ -/* 2006-08-02 Lydia Wang Add support to VT1709 codec */ -/* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */ -/* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */ -/* 2007-09-17 Lydia Wang Add VT1708B codec support */ -/* 2007-11-14 Lydia Wang Add VT1708A codec HP and CD pin connect config */ -/* 2008-02-03 Lydia Wang Fix Rear channels and Back channels inverse issue */ -/* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */ -/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */ -/* 2008-04-09 Lydia Wang Add Independent HP feature */ -/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */ -/* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */ -/* 2009-02-16 Logan Li Add support for VT1718S */ -/* 2009-03-13 Logan Li Add support for VT1716S */ -/* 2009-04-14 Lydai Wang Add support for VT1828S and VT2020 */ -/* 2009-07-08 Lydia Wang Add support for VT2002P */ -/* 2009-07-21 Lydia Wang Add support for VT1812 */ -/* 2009-09-19 Lydia Wang Add support for VT1818S */ -/* */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - - -#include -#include -#include -#include -#include -#include -#include "hda_codec.h" -#include "hda_local.h" -#include "hda_jack.h" - -/* Pin Widget NID */ -#define VT1708_HP_PIN_NID 0x20 -#define VT1708_CD_PIN_NID 0x24 - -enum VIA_HDA_CODEC { - UNKNOWN = -1, - VT1708, - VT1709_10CH, - VT1709_6CH, - VT1708B_8CH, - VT1708B_4CH, - VT1708S, - VT1708BCE, - VT1702, - VT1718S, - VT1716S, - VT2002P, - VT1812, - VT1802, - CODEC_TYPES, -}; - -#define VT2002P_COMPATIBLE(spec) \ - ((spec)->codec_type == VT2002P ||\ - (spec)->codec_type == VT1812 ||\ - (spec)->codec_type == VT1802) - -#define MAX_NID_PATH_DEPTH 5 - -/* output-path: DAC -> ... -> pin - * idx[] contains the source index number of the next widget; - * e.g. idx[0] is the index of the DAC selected by path[1] widget - * multi[] indicates whether it's a selector widget with multi-connectors - * (i.e. the connection selection is mandatory) - * vol_ctl and mute_ctl contains the NIDs for the assigned mixers - */ -struct nid_path { - int depth; - hda_nid_t path[MAX_NID_PATH_DEPTH]; - unsigned char idx[MAX_NID_PATH_DEPTH]; - unsigned char multi[MAX_NID_PATH_DEPTH]; - unsigned int vol_ctl; - unsigned int mute_ctl; -}; - -/* input-path */ -struct via_input { - hda_nid_t pin; /* input-pin or aa-mix */ - int adc_idx; /* ADC index to be used */ - int mux_idx; /* MUX index (if any) */ - const char *label; /* input-source label */ -}; - -#define VIA_MAX_ADCS 3 - -enum { - STREAM_MULTI_OUT = (1 << 0), - STREAM_INDEP_HP = (1 << 1), -}; - -struct via_spec { - /* codec parameterization */ - const struct snd_kcontrol_new *mixers[6]; - unsigned int num_mixers; - - const struct hda_verb *init_verbs[5]; - unsigned int num_iverbs; - - char stream_name_analog[32]; - char stream_name_hp[32]; - const struct hda_pcm_stream *stream_analog_playback; - const struct hda_pcm_stream *stream_analog_capture; - - char stream_name_digital[32]; - const struct hda_pcm_stream *stream_digital_playback; - const struct hda_pcm_stream *stream_digital_capture; - - /* playback */ - struct hda_multi_out multiout; - hda_nid_t slave_dig_outs[2]; - hda_nid_t hp_dac_nid; - hda_nid_t speaker_dac_nid; - int hp_indep_shared; /* indep HP-DAC is shared with side ch */ - int opened_streams; /* STREAM_* bits */ - int active_streams; /* STREAM_* bits */ - int aamix_mode; /* loopback is enabled for output-path? */ - - /* Output-paths: - * There are different output-paths depending on the setup. - * out_path, hp_path and speaker_path are primary paths. If both - * direct DAC and aa-loopback routes are available, these contain - * the former paths. Meanwhile *_mix_path contain the paths with - * loopback mixer. (Since the loopback is only for front channel, - * no out_mix_path for surround channels.) - * The HP output has another path, hp_indep_path, which is used in - * the independent-HP mode. - */ - struct nid_path out_path[HDA_SIDE + 1]; - struct nid_path out_mix_path; - struct nid_path hp_path; - struct nid_path hp_mix_path; - struct nid_path hp_indep_path; - struct nid_path speaker_path; - struct nid_path speaker_mix_path; - - /* capture */ - unsigned int num_adc_nids; - hda_nid_t adc_nids[VIA_MAX_ADCS]; - hda_nid_t mux_nids[VIA_MAX_ADCS]; - hda_nid_t aa_mix_nid; - hda_nid_t dig_in_nid; - - /* capture source */ - bool dyn_adc_switch; - int num_inputs; - struct via_input inputs[AUTO_CFG_MAX_INS + 1]; - unsigned int cur_mux[VIA_MAX_ADCS]; - - /* dynamic DAC switching */ - unsigned int cur_dac_stream_tag; - unsigned int cur_dac_format; - unsigned int cur_hp_stream_tag; - unsigned int cur_hp_format; - - /* dynamic ADC switching */ - hda_nid_t cur_adc; - unsigned int cur_adc_stream_tag; - unsigned int cur_adc_format; - - /* PCM information */ - struct hda_pcm pcm_rec[3]; - - /* dynamic controls, init_verbs and input_mux */ - struct auto_pin_cfg autocfg; - struct snd_array kctls; - hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; - - /* HP mode source */ - unsigned int hp_independent_mode; - unsigned int dmic_enabled; - unsigned int no_pin_power_ctl; - enum VIA_HDA_CODEC codec_type; - - /* analog low-power control */ - bool alc_mode; - - /* smart51 setup */ - unsigned int smart51_nums; - hda_nid_t smart51_pins[2]; - int smart51_idxs[2]; - const char *smart51_labels[2]; - unsigned int smart51_enabled; - - /* work to check hp jack state */ - struct hda_codec *codec; - struct delayed_work vt1708_hp_work; - int hp_work_active; - int vt1708_jack_detect; - int vt1708_hp_present; - - void (*set_widgets_power_state)(struct hda_codec *codec); - - struct hda_loopback_check loopback; - int num_loopbacks; - struct hda_amp_list loopback_list[8]; - - /* bind capture-volume */ - struct hda_bind_ctls *bind_cap_vol; - struct hda_bind_ctls *bind_cap_sw; - - struct mutex config_mutex; -}; - -static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec); -static struct via_spec * via_new_spec(struct hda_codec *codec) -{ - struct via_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return NULL; - - mutex_init(&spec->config_mutex); - codec->spec = spec; - spec->codec = codec; - spec->codec_type = get_codec_type(codec); - /* VT1708BCE & VT1708S are almost same */ - if (spec->codec_type == VT1708BCE) - spec->codec_type = VT1708S; - return spec; -} - -static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec) -{ - u32 vendor_id = codec->vendor_id; - u16 ven_id = vendor_id >> 16; - u16 dev_id = vendor_id & 0xffff; - enum VIA_HDA_CODEC codec_type; - - /* get codec type */ - if (ven_id != 0x1106) - codec_type = UNKNOWN; - else if (dev_id >= 0x1708 && dev_id <= 0x170b) - codec_type = VT1708; - else if (dev_id >= 0xe710 && dev_id <= 0xe713) - codec_type = VT1709_10CH; - else if (dev_id >= 0xe714 && dev_id <= 0xe717) - codec_type = VT1709_6CH; - else if (dev_id >= 0xe720 && dev_id <= 0xe723) { - codec_type = VT1708B_8CH; - if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7) - codec_type = VT1708BCE; - } else if (dev_id >= 0xe724 && dev_id <= 0xe727) - codec_type = VT1708B_4CH; - else if ((dev_id & 0xfff) == 0x397 - && (dev_id >> 12) < 8) - codec_type = VT1708S; - else if ((dev_id & 0xfff) == 0x398 - && (dev_id >> 12) < 8) - codec_type = VT1702; - else if ((dev_id & 0xfff) == 0x428 - && (dev_id >> 12) < 8) - codec_type = VT1718S; - else if (dev_id == 0x0433 || dev_id == 0xa721) - codec_type = VT1716S; - else if (dev_id == 0x0441 || dev_id == 0x4441) - codec_type = VT1718S; - else if (dev_id == 0x0438 || dev_id == 0x4438) - codec_type = VT2002P; - else if (dev_id == 0x0448) - codec_type = VT1812; - else if (dev_id == 0x0440) - codec_type = VT1708S; - else if ((dev_id & 0xfff) == 0x446) - codec_type = VT1802; - else - codec_type = UNKNOWN; - return codec_type; -}; - -#define VIA_JACK_EVENT 0x20 -#define VIA_HP_EVENT 0x01 -#define VIA_GPIO_EVENT 0x02 -#define VIA_LINE_EVENT 0x03 - -enum { - VIA_CTL_WIDGET_VOL, - VIA_CTL_WIDGET_MUTE, - VIA_CTL_WIDGET_ANALOG_MUTE, -}; - -static void analog_low_current_mode(struct hda_codec *codec); -static bool is_aa_path_mute(struct hda_codec *codec); - -#define hp_detect_with_aa(codec) \ - (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \ - !is_aa_path_mute(codec)) - -static void vt1708_stop_hp_work(struct via_spec *spec) -{ - if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) - return; - if (spec->hp_work_active) { - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1); - cancel_delayed_work_sync(&spec->vt1708_hp_work); - spec->hp_work_active = 0; - } -} - -static void vt1708_update_hp_work(struct via_spec *spec) -{ - if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) - return; - if (spec->vt1708_jack_detect && - (spec->active_streams || hp_detect_with_aa(spec->codec))) { - if (!spec->hp_work_active) { - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0); - schedule_delayed_work(&spec->vt1708_hp_work, - msecs_to_jiffies(100)); - spec->hp_work_active = 1; - } - } else if (!hp_detect_with_aa(spec->codec)) - vt1708_stop_hp_work(spec); -} - -static void set_widgets_power_state(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - if (spec->set_widgets_power_state) - spec->set_widgets_power_state(codec); -} - -static int analog_input_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - - set_widgets_power_state(codec); - analog_low_current_mode(snd_kcontrol_chip(kcontrol)); - vt1708_update_hp_work(codec->spec); - return change; -} - -/* modify .put = snd_hda_mixer_amp_switch_put */ -#define ANALOG_INPUT_MUTE \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = NULL, \ - .index = 0, \ - .info = snd_hda_mixer_amp_switch_info, \ - .get = snd_hda_mixer_amp_switch_get, \ - .put = analog_input_switch_put, \ - .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0) } - -static const struct snd_kcontrol_new via_control_templates[] = { - HDA_CODEC_VOLUME(NULL, 0, 0, 0), - HDA_CODEC_MUTE(NULL, 0, 0, 0), - ANALOG_INPUT_MUTE, -}; - - -/* add dynamic controls */ -static struct snd_kcontrol_new *__via_clone_ctl(struct via_spec *spec, - const struct snd_kcontrol_new *tmpl, - const char *name) -{ - struct snd_kcontrol_new *knew; - - snd_array_init(&spec->kctls, sizeof(*knew), 32); - knew = snd_array_new(&spec->kctls); - if (!knew) - return NULL; - *knew = *tmpl; - if (!name) - name = tmpl->name; - if (name) { - knew->name = kstrdup(name, GFP_KERNEL); - if (!knew->name) - return NULL; - } - return knew; -} - -static int __via_add_control(struct via_spec *spec, int type, const char *name, - int idx, unsigned long val) -{ - struct snd_kcontrol_new *knew; - - knew = __via_clone_ctl(spec, &via_control_templates[type], name); - if (!knew) - return -ENOMEM; - knew->index = idx; - if (get_amp_nid_(val)) - knew->subdevice = HDA_SUBDEV_AMP_FLAG; - knew->private_value = val; - return 0; -} - -#define via_add_control(spec, type, name, val) \ - __via_add_control(spec, type, name, 0, val) - -#define via_clone_control(spec, tmpl) __via_clone_ctl(spec, tmpl, NULL) - -static void via_free_kctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - - if (spec->kctls.list) { - struct snd_kcontrol_new *kctl = spec->kctls.list; - int i; - for (i = 0; i < spec->kctls.used; i++) - kfree(kctl[i].name); - } - snd_array_free(&spec->kctls); -} - -/* create input playback/capture controls for the given pin */ -static int via_new_analog_input(struct via_spec *spec, const char *ctlname, - int type_idx, int idx, int mix_nid) -{ - char name[32]; - int err; - - sprintf(name, "%s Playback Volume", ctlname); - err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, - HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); - if (err < 0) - return err; - sprintf(name, "%s Playback Switch", ctlname); - err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx, - HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); - if (err < 0) - return err; - return 0; -} - -#define get_connection_index(codec, mux, nid) \ - snd_hda_get_conn_index(codec, mux, nid, 0) - -static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, - unsigned int mask) -{ - unsigned int caps; - if (!nid) - return false; - caps = get_wcaps(codec, nid); - if (dir == HDA_INPUT) - caps &= AC_WCAP_IN_AMP; - else - caps &= AC_WCAP_OUT_AMP; - if (!caps) - return false; - if (query_amp_caps(codec, nid, dir) & mask) - return true; - return false; -} - -#define have_mute(codec, nid, dir) \ - check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE) - -/* enable/disable the output-route mixers */ -static void activate_output_mix(struct hda_codec *codec, struct nid_path *path, - hda_nid_t mix_nid, int idx, bool enable) -{ - int i, num, val; - - if (!path) - return; - num = snd_hda_get_conn_list(codec, mix_nid, NULL); - for (i = 0; i < num; i++) { - if (i == idx) - val = AMP_IN_UNMUTE(i); - else - val = AMP_IN_MUTE(i); - snd_hda_codec_write(codec, mix_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, val); - } -} - -/* enable/disable the output-route */ -static void activate_output_path(struct hda_codec *codec, struct nid_path *path, - bool enable, bool force) -{ - struct via_spec *spec = codec->spec; - int i; - for (i = 0; i < path->depth; i++) { - hda_nid_t src, dst; - int idx = path->idx[i]; - src = path->path[i]; - if (i < path->depth - 1) - dst = path->path[i + 1]; - else - dst = 0; - if (enable && path->multi[i]) - snd_hda_codec_write(codec, dst, 0, - AC_VERB_SET_CONNECT_SEL, idx); - if (!force && (dst == spec->aa_mix_nid)) - continue; - if (have_mute(codec, dst, HDA_INPUT)) - activate_output_mix(codec, path, dst, idx, enable); - if (!force && (src == path->vol_ctl || src == path->mute_ctl)) - continue; - if (have_mute(codec, src, HDA_OUTPUT)) { - int val = enable ? AMP_OUT_UNMUTE : AMP_OUT_MUTE; - snd_hda_codec_write(codec, src, 0, - AC_VERB_SET_AMP_GAIN_MUTE, val); - } - } -} - -/* set the given pin as output */ -static void init_output_pin(struct hda_codec *codec, hda_nid_t pin, - int pin_type) -{ - if (!pin) - return; - snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_type); - if (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD) - snd_hda_codec_write(codec, pin, 0, - AC_VERB_SET_EAPD_BTLENABLE, 0x02); -} - -static void via_auto_init_output(struct hda_codec *codec, - struct nid_path *path, int pin_type) -{ - unsigned int caps; - hda_nid_t pin; - - if (!path->depth) - return; - pin = path->path[path->depth - 1]; - - init_output_pin(codec, pin, pin_type); - if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) - caps = query_amp_caps(codec, pin, HDA_OUTPUT); - else - caps = 0; - if (caps & AC_AMPCAP_MUTE) { - unsigned int val; - val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT; - snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE | val); - } - activate_output_path(codec, path, true, true); /* force on */ -} - -static void via_auto_init_multi_out(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct nid_path *path; - int i; - - for (i = 0; i < spec->autocfg.line_outs + spec->smart51_nums; i++) { - path = &spec->out_path[i]; - if (!i && spec->aamix_mode && spec->out_mix_path.depth) - path = &spec->out_mix_path; - via_auto_init_output(codec, path, PIN_OUT); - } -} - -/* deactivate the inactive headphone-paths */ -static void deactivate_hp_paths(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int shared = spec->hp_indep_shared; - - if (spec->hp_independent_mode) { - activate_output_path(codec, &spec->hp_path, false, false); - activate_output_path(codec, &spec->hp_mix_path, false, false); - if (shared) - activate_output_path(codec, &spec->out_path[shared], - false, false); - } else if (spec->aamix_mode || !spec->hp_path.depth) { - activate_output_path(codec, &spec->hp_indep_path, false, false); - activate_output_path(codec, &spec->hp_path, false, false); - } else { - activate_output_path(codec, &spec->hp_indep_path, false, false); - activate_output_path(codec, &spec->hp_mix_path, false, false); - } -} - -static void via_auto_init_hp_out(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - - if (!spec->hp_path.depth) { - via_auto_init_output(codec, &spec->hp_mix_path, PIN_HP); - return; - } - deactivate_hp_paths(codec); - if (spec->hp_independent_mode) - via_auto_init_output(codec, &spec->hp_indep_path, PIN_HP); - else if (spec->aamix_mode) - via_auto_init_output(codec, &spec->hp_mix_path, PIN_HP); - else - via_auto_init_output(codec, &spec->hp_path, PIN_HP); -} - -static void via_auto_init_speaker_out(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - - if (!spec->autocfg.speaker_outs) - return; - if (!spec->speaker_path.depth) { - via_auto_init_output(codec, &spec->speaker_mix_path, PIN_OUT); - return; - } - if (!spec->aamix_mode) { - activate_output_path(codec, &spec->speaker_mix_path, - false, false); - via_auto_init_output(codec, &spec->speaker_path, PIN_OUT); - } else { - activate_output_path(codec, &spec->speaker_path, false, false); - via_auto_init_output(codec, &spec->speaker_mix_path, PIN_OUT); - } -} - -static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin); -static void via_hp_automute(struct hda_codec *codec); - -static void via_auto_init_analog_input(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t conn[HDA_MAX_CONNECTIONS]; - unsigned int ctl; - int i, num_conns; - - /* init ADCs */ - for (i = 0; i < spec->num_adc_nids; i++) { - hda_nid_t nid = spec->adc_nids[i]; - if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP) || - !(query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE)) - continue; - snd_hda_codec_write(codec, spec->adc_nids[i], 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(0)); - } - - /* init pins */ - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; - if (spec->smart51_enabled && is_smart51_pins(codec, nid)) - ctl = PIN_OUT; - else if (cfg->inputs[i].type == AUTO_PIN_MIC) - ctl = PIN_VREF50; - else - ctl = PIN_IN; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, ctl); - } - - /* init input-src */ - for (i = 0; i < spec->num_adc_nids; i++) { - int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx; - /* secondary ADCs must have the unique MUX */ - if (i > 0 && !spec->mux_nids[i]) - break; - if (spec->mux_nids[adc_idx]) { - int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx; - snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0, - AC_VERB_SET_CONNECT_SEL, - mux_idx); - } - if (spec->dyn_adc_switch) - break; /* only one input-src */ - } - - /* init aa-mixer */ - if (!spec->aa_mix_nid) - return; - num_conns = snd_hda_get_connections(codec, spec->aa_mix_nid, conn, - ARRAY_SIZE(conn)); - for (i = 0; i < num_conns; i++) { - unsigned int caps = get_wcaps(codec, conn[i]); - if (get_wcaps_type(caps) == AC_WID_PIN) - snd_hda_codec_write(codec, spec->aa_mix_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_MUTE(i)); - } -} - -static void update_power_state(struct hda_codec *codec, hda_nid_t nid, - unsigned int parm) -{ - if (snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_POWER_STATE, 0) == parm) - return; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); -} - -static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, - unsigned int *affected_parm) -{ - unsigned parm; - unsigned def_conf = snd_hda_codec_get_pincfg(codec, nid); - unsigned no_presence = (def_conf & AC_DEFCFG_MISC) - >> AC_DEFCFG_MISC_SHIFT - & AC_DEFCFG_MISC_NO_PRESENCE; /* do not support pin sense */ - struct via_spec *spec = codec->spec; - unsigned present = 0; - - no_presence |= spec->no_pin_power_ctl; - if (!no_presence) - present = snd_hda_jack_detect(codec, nid); - if ((spec->smart51_enabled && is_smart51_pins(codec, nid)) - || ((no_presence || present) - && get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)) { - *affected_parm = AC_PWRST_D0; /* if it's connected */ - parm = AC_PWRST_D0; - } else - parm = AC_PWRST_D3; - - update_power_state(codec, nid, parm); -} - -static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "Disabled", "Enabled" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - ucontrol->value.enumerated.item[0] = !spec->no_pin_power_ctl; - return 0; -} - -static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - unsigned int val = !ucontrol->value.enumerated.item[0]; - - if (val == spec->no_pin_power_ctl) - return 0; - spec->no_pin_power_ctl = val; - set_widgets_power_state(codec); - analog_low_current_mode(codec); - return 1; -} - -static const struct snd_kcontrol_new via_pin_power_ctl_enum = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Dynamic Power-Control", - .info = via_pin_power_ctl_info, - .get = via_pin_power_ctl_get, - .put = via_pin_power_ctl_put, -}; - - -static int via_independent_hp_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { "OFF", "ON" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= 2) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int via_independent_hp_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - - ucontrol->value.enumerated.item[0] = spec->hp_independent_mode; - return 0; -} - -/* adjust spec->multiout setup according to the current flags */ -static void setup_playback_multi_pcm(struct via_spec *spec) -{ - const struct auto_pin_cfg *cfg = &spec->autocfg; - spec->multiout.num_dacs = cfg->line_outs + spec->smart51_nums; - spec->multiout.hp_nid = 0; - if (!spec->hp_independent_mode) { - if (!spec->hp_indep_shared) - spec->multiout.hp_nid = spec->hp_dac_nid; - } else { - if (spec->hp_indep_shared) - spec->multiout.num_dacs = cfg->line_outs - 1; - } -} - -/* update DAC setups according to indep-HP switch; - * this function is called only when indep-HP is modified - */ -static void switch_indep_hp_dacs(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int shared = spec->hp_indep_shared; - hda_nid_t shared_dac, hp_dac; - - if (!spec->opened_streams) - return; - - shared_dac = shared ? spec->multiout.dac_nids[shared] : 0; - hp_dac = spec->hp_dac_nid; - if (spec->hp_independent_mode) { - /* switch to indep-HP mode */ - if (spec->active_streams & STREAM_MULTI_OUT) { - __snd_hda_codec_cleanup_stream(codec, hp_dac, 1); - __snd_hda_codec_cleanup_stream(codec, shared_dac, 1); - } - if (spec->active_streams & STREAM_INDEP_HP) - snd_hda_codec_setup_stream(codec, hp_dac, - spec->cur_hp_stream_tag, 0, - spec->cur_hp_format); - } else { - /* back to HP or shared-DAC */ - if (spec->active_streams & STREAM_INDEP_HP) - __snd_hda_codec_cleanup_stream(codec, hp_dac, 1); - if (spec->active_streams & STREAM_MULTI_OUT) { - hda_nid_t dac; - int ch; - if (shared_dac) { /* reset mutli-ch DAC */ - dac = shared_dac; - ch = shared * 2; - } else { /* reset HP DAC */ - dac = hp_dac; - ch = 0; - } - snd_hda_codec_setup_stream(codec, dac, - spec->cur_dac_stream_tag, ch, - spec->cur_dac_format); - } - } - setup_playback_multi_pcm(spec); -} - -static int via_independent_hp_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - int cur, shared; - - mutex_lock(&spec->config_mutex); - cur = !!ucontrol->value.enumerated.item[0]; - if (spec->hp_independent_mode == cur) { - mutex_unlock(&spec->config_mutex); - return 0; - } - spec->hp_independent_mode = cur; - shared = spec->hp_indep_shared; - deactivate_hp_paths(codec); - if (cur) - activate_output_path(codec, &spec->hp_indep_path, true, false); - else { - if (shared) - activate_output_path(codec, &spec->out_path[shared], - true, false); - if (spec->aamix_mode || !spec->hp_path.depth) - activate_output_path(codec, &spec->hp_mix_path, - true, false); - else - activate_output_path(codec, &spec->hp_path, - true, false); - } - - switch_indep_hp_dacs(codec); - mutex_unlock(&spec->config_mutex); - - /* update jack power state */ - set_widgets_power_state(codec); - via_hp_automute(codec); - return 1; -} - -static const struct snd_kcontrol_new via_hp_mixer = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Independent HP", - .info = via_independent_hp_info, - .get = via_independent_hp_get, - .put = via_independent_hp_put, -}; - -static int via_hp_build(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct snd_kcontrol_new *knew; - hda_nid_t nid; - - nid = spec->autocfg.hp_pins[0]; - knew = via_clone_control(spec, &via_hp_mixer); - if (knew == NULL) - return -ENOMEM; - - knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; - - return 0; -} - -static void notify_aa_path_ctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->smart51_nums; i++) { - struct snd_kcontrol *ctl; - struct snd_ctl_elem_id id; - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - sprintf(id.name, "%s Playback Volume", spec->smart51_labels[i]); - ctl = snd_hda_find_mixer_ctl(codec, id.name); - if (ctl) - snd_ctl_notify(codec->bus->card, - SNDRV_CTL_EVENT_MASK_VALUE, - &ctl->id); - } -} - -static void mute_aa_path(struct hda_codec *codec, int mute) -{ - struct via_spec *spec = codec->spec; - int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE; - int i; - - /* check AA path's mute status */ - for (i = 0; i < spec->smart51_nums; i++) { - if (spec->smart51_idxs[i] < 0) - continue; - snd_hda_codec_amp_stereo(codec, spec->aa_mix_nid, - HDA_INPUT, spec->smart51_idxs[i], - HDA_AMP_MUTE, val); - } -} - -static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin) -{ - struct via_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->smart51_nums; i++) - if (spec->smart51_pins[i] == pin) - return true; - return false; -} - -static int via_smart51_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - - *ucontrol->value.integer.value = spec->smart51_enabled; - return 0; -} - -static int via_smart51_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - int out_in = *ucontrol->value.integer.value - ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; - int i; - - for (i = 0; i < spec->smart51_nums; i++) { - hda_nid_t nid = spec->smart51_pins[i]; - unsigned int parm; - - parm = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); - parm |= out_in; - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - parm); - if (out_in == AC_PINCTL_OUT_EN) { - mute_aa_path(codec, 1); - notify_aa_path_ctls(codec); - } - } - spec->smart51_enabled = *ucontrol->value.integer.value; - set_widgets_power_state(codec); - return 1; -} - -static const struct snd_kcontrol_new via_smart51_mixer = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Smart 5.1", - .count = 1, - .info = snd_ctl_boolean_mono_info, - .get = via_smart51_get, - .put = via_smart51_put, -}; - -static int via_smart51_build(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - - if (!spec->smart51_nums) - return 0; - if (!via_clone_control(spec, &via_smart51_mixer)) - return -ENOMEM; - return 0; -} - -/* check AA path's mute status */ -static bool is_aa_path_mute(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - const struct hda_amp_list *p; - int i, ch, v; - - for (i = 0; i < spec->num_loopbacks; i++) { - p = &spec->loopback_list[i]; - for (ch = 0; ch < 2; ch++) { - v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir, - p->idx); - if (!(v & HDA_AMP_MUTE) && v > 0) - return false; - } - } - return true; -} - -/* enter/exit analog low-current mode */ -static void __analog_low_current_mode(struct hda_codec *codec, bool force) -{ - struct via_spec *spec = codec->spec; - bool enable; - unsigned int verb, parm; - - if (spec->no_pin_power_ctl) - enable = false; - else - enable = is_aa_path_mute(codec) && !spec->opened_streams; - if (enable == spec->alc_mode && !force) - return; - spec->alc_mode = enable; - - /* decide low current mode's verb & parameter */ - switch (spec->codec_type) { - case VT1708B_8CH: - case VT1708B_4CH: - verb = 0xf70; - parm = enable ? 0x02 : 0x00; /* 0x02: 2/3x, 0x00: 1x */ - break; - case VT1708S: - case VT1718S: - case VT1716S: - verb = 0xf73; - parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */ - break; - case VT1702: - verb = 0xf73; - parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */ - break; - case VT2002P: - case VT1812: - case VT1802: - verb = 0xf93; - parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */ - break; - default: - return; /* other codecs are not supported */ - } - /* send verb */ - snd_hda_codec_write(codec, codec->afg, 0, verb, parm); -} - -static void analog_low_current_mode(struct hda_codec *codec) -{ - return __analog_low_current_mode(codec, false); -} - -/* - * generic initialization of ADC, input mixers and output mixers - */ -static const struct hda_verb vt1708_init_verbs[] = { - /* power down jack detect function */ - {0x1, 0xf81, 0x1}, - { } -}; - -static void set_stream_open(struct hda_codec *codec, int bit, bool active) -{ - struct via_spec *spec = codec->spec; - - if (active) - spec->opened_streams |= bit; - else - spec->opened_streams &= ~bit; - analog_low_current_mode(codec); -} - -static int via_playback_multi_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; - int err; - - spec->multiout.num_dacs = cfg->line_outs + spec->smart51_nums; - spec->multiout.max_channels = spec->multiout.num_dacs * 2; - set_stream_open(codec, STREAM_MULTI_OUT, true); - err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, - hinfo); - if (err < 0) { - set_stream_open(codec, STREAM_MULTI_OUT, false); - return err; - } - return 0; -} - -static int via_playback_multi_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - set_stream_open(codec, STREAM_MULTI_OUT, false); - return 0; -} - -static int via_playback_hp_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - - if (snd_BUG_ON(!spec->hp_dac_nid)) - return -EINVAL; - set_stream_open(codec, STREAM_INDEP_HP, true); - return 0; -} - -static int via_playback_hp_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - set_stream_open(codec, STREAM_INDEP_HP, false); - return 0; -} - -static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - - mutex_lock(&spec->config_mutex); - setup_playback_multi_pcm(spec); - snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, - format, substream); - /* remember for dynamic DAC switch with indep-HP */ - spec->active_streams |= STREAM_MULTI_OUT; - spec->cur_dac_stream_tag = stream_tag; - spec->cur_dac_format = format; - mutex_unlock(&spec->config_mutex); - vt1708_update_hp_work(spec); - return 0; -} - -static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - - mutex_lock(&spec->config_mutex); - if (spec->hp_independent_mode) - snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, - stream_tag, 0, format); - spec->active_streams |= STREAM_INDEP_HP; - spec->cur_hp_stream_tag = stream_tag; - spec->cur_hp_format = format; - mutex_unlock(&spec->config_mutex); - vt1708_update_hp_work(spec); - return 0; -} - -static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - - mutex_lock(&spec->config_mutex); - snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); - spec->active_streams &= ~STREAM_MULTI_OUT; - mutex_unlock(&spec->config_mutex); - vt1708_update_hp_work(spec); - return 0; -} - -static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - - mutex_lock(&spec->config_mutex); - if (spec->hp_independent_mode) - snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0); - spec->active_streams &= ~STREAM_INDEP_HP; - mutex_unlock(&spec->config_mutex); - vt1708_update_hp_work(spec); - return 0; -} - -/* - * Digital out - */ -static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - return snd_hda_multi_out_dig_open(codec, &spec->multiout); -} - -static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - return snd_hda_multi_out_dig_close(codec, &spec->multiout); -} - -static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, - stream_tag, format, substream); -} - -static int via_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); - return 0; -} - -/* - * Analog capture - */ -static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - - snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], - stream_tag, 0, format); - return 0; -} - -static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]); - return 0; -} - -/* analog capture with dynamic ADC switching */ -static int via_dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - unsigned int stream_tag, - unsigned int format, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - int adc_idx = spec->inputs[spec->cur_mux[0]].adc_idx; - - mutex_lock(&spec->config_mutex); - spec->cur_adc = spec->adc_nids[adc_idx]; - spec->cur_adc_stream_tag = stream_tag; - spec->cur_adc_format = format; - snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); - mutex_unlock(&spec->config_mutex); - return 0; -} - -static int via_dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, - struct hda_codec *codec, - struct snd_pcm_substream *substream) -{ - struct via_spec *spec = codec->spec; - - mutex_lock(&spec->config_mutex); - snd_hda_codec_cleanup_stream(codec, spec->cur_adc); - spec->cur_adc = 0; - mutex_unlock(&spec->config_mutex); - return 0; -} - -/* re-setup the stream if running; called from input-src put */ -static bool via_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur) -{ - struct via_spec *spec = codec->spec; - int adc_idx = spec->inputs[cur].adc_idx; - hda_nid_t adc = spec->adc_nids[adc_idx]; - bool ret = false; - - mutex_lock(&spec->config_mutex); - if (spec->cur_adc && spec->cur_adc != adc) { - /* stream is running, let's swap the current ADC */ - __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); - spec->cur_adc = adc; - snd_hda_codec_setup_stream(codec, adc, - spec->cur_adc_stream_tag, 0, - spec->cur_adc_format); - ret = true; - } - mutex_unlock(&spec->config_mutex); - return ret; -} - -static const struct hda_pcm_stream via_pcm_analog_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 8, - /* NID is set in via_build_pcms */ - .ops = { - .open = via_playback_multi_pcm_open, - .close = via_playback_multi_pcm_close, - .prepare = via_playback_multi_pcm_prepare, - .cleanup = via_playback_multi_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream via_pcm_hp_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in via_build_pcms */ - .ops = { - .open = via_playback_hp_pcm_open, - .close = via_playback_hp_pcm_close, - .prepare = via_playback_hp_pcm_prepare, - .cleanup = via_playback_hp_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 8, - /* NID is set in via_build_pcms */ - /* We got noisy outputs on the right channel on VT1708 when - * 24bit samples are used. Until any workaround is found, - * disable the 24bit format, so far. - */ - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .ops = { - .open = via_playback_multi_pcm_open, - .close = via_playback_multi_pcm_close, - .prepare = via_playback_multi_pcm_prepare, - .cleanup = via_playback_multi_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream via_pcm_analog_capture = { - .substreams = 1, /* will be changed in via_build_pcms() */ - .channels_min = 2, - .channels_max = 2, - /* NID is set in via_build_pcms */ - .ops = { - .prepare = via_capture_pcm_prepare, - .cleanup = via_capture_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream via_pcm_dyn_adc_analog_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in via_build_pcms */ - .ops = { - .prepare = via_dyn_adc_capture_pcm_prepare, - .cleanup = via_dyn_adc_capture_pcm_cleanup, - }, -}; - -static const struct hda_pcm_stream via_pcm_digital_playback = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, - /* NID is set in via_build_pcms */ - .ops = { - .open = via_dig_playback_pcm_open, - .close = via_dig_playback_pcm_close, - .prepare = via_dig_playback_pcm_prepare, - .cleanup = via_dig_playback_pcm_cleanup - }, -}; - -static const struct hda_pcm_stream via_pcm_digital_capture = { - .substreams = 1, - .channels_min = 2, - .channels_max = 2, -}; - -/* - * slave controls for virtual master - */ -static const char * const via_slave_pfxs[] = { - "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Speaker", - NULL, -}; - -static int via_build_controls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct snd_kcontrol *kctl; - int err, i; - - spec->no_pin_power_ctl = 1; - if (spec->set_widgets_power_state) - if (!via_clone_control(spec, &via_pin_power_ctl_enum)) - return -ENOMEM; - - for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - - if (spec->multiout.dig_out_nid) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->multiout.dig_out_nid, - spec->multiout.dig_out_nid); - if (err < 0) - return err; - err = snd_hda_create_spdif_share_sw(codec, - &spec->multiout); - if (err < 0) - return err; - spec->multiout.share_spdif = 1; - } - if (spec->dig_in_nid) { - err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); - if (err < 0) - return err; - } - - /* if we have no master control, let's create it */ - if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { - unsigned int vmaster_tlv[4]; - snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], - HDA_OUTPUT, vmaster_tlv); - err = snd_hda_add_vmaster(codec, "Master Playback Volume", - vmaster_tlv, via_slave_pfxs, - "Playback Volume"); - if (err < 0) - return err; - } - if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { - err = snd_hda_add_vmaster(codec, "Master Playback Switch", - NULL, via_slave_pfxs, - "Playback Switch"); - if (err < 0) - return err; - } - - /* assign Capture Source enums to NID */ - kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); - for (i = 0; kctl && i < kctl->count; i++) { - if (!spec->mux_nids[i]) - continue; - err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]); - if (err < 0) - return err; - } - - via_free_kctls(codec); /* no longer needed */ - - err = snd_hda_jack_add_kctls(codec, &spec->autocfg); - if (err < 0) - return err; - - return 0; -} - -static int via_build_pcms(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct hda_pcm *info = spec->pcm_rec; - - codec->num_pcms = 0; - codec->pcm_info = info; - - if (spec->multiout.num_dacs || spec->num_adc_nids) { - snprintf(spec->stream_name_analog, - sizeof(spec->stream_name_analog), - "%s Analog", codec->chip_name); - info->name = spec->stream_name_analog; - - if (spec->multiout.num_dacs) { - if (!spec->stream_analog_playback) - spec->stream_analog_playback = - &via_pcm_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = - *spec->stream_analog_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->multiout.dac_nids[0]; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = - spec->multiout.max_channels; - } - - if (!spec->stream_analog_capture) { - if (spec->dyn_adc_switch) - spec->stream_analog_capture = - &via_pcm_dyn_adc_analog_capture; - else - spec->stream_analog_capture = - &via_pcm_analog_capture; - } - if (spec->num_adc_nids) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - *spec->stream_analog_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = - spec->adc_nids[0]; - if (!spec->dyn_adc_switch) - info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = - spec->num_adc_nids; - } - codec->num_pcms++; - info++; - } - - if (spec->multiout.dig_out_nid || spec->dig_in_nid) { - snprintf(spec->stream_name_digital, - sizeof(spec->stream_name_digital), - "%s Digital", codec->chip_name); - info->name = spec->stream_name_digital; - info->pcm_type = HDA_PCM_TYPE_SPDIF; - if (spec->multiout.dig_out_nid) { - if (!spec->stream_digital_playback) - spec->stream_digital_playback = - &via_pcm_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = - *spec->stream_digital_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->multiout.dig_out_nid; - } - if (spec->dig_in_nid) { - if (!spec->stream_digital_capture) - spec->stream_digital_capture = - &via_pcm_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE] = - *spec->stream_digital_capture; - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = - spec->dig_in_nid; - } - codec->num_pcms++; - info++; - } - - if (spec->hp_dac_nid) { - snprintf(spec->stream_name_hp, sizeof(spec->stream_name_hp), - "%s HP", codec->chip_name); - info->name = spec->stream_name_hp; - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = via_pcm_hp_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = - spec->hp_dac_nid; - codec->num_pcms++; - info++; - } - return 0; -} - -static void via_free(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - - if (!spec) - return; - - via_free_kctls(codec); - vt1708_stop_hp_work(spec); - kfree(spec->bind_cap_vol); - kfree(spec->bind_cap_sw); - kfree(spec); -} - -/* mute/unmute outputs */ -static void toggle_output_mutes(struct hda_codec *codec, int num_pins, - hda_nid_t *pins, bool mute) -{ - int i; - for (i = 0; i < num_pins; i++) { - unsigned int parm = snd_hda_codec_read(codec, pins[i], 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - if (parm & AC_PINCTL_IN_EN) - continue; - if (mute) - parm &= ~AC_PINCTL_OUT_EN; - else - parm |= AC_PINCTL_OUT_EN; - snd_hda_codec_write(codec, pins[i], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, parm); - } -} - -/* mute internal speaker if line-out is plugged */ -static void via_line_automute(struct hda_codec *codec, int present) -{ - struct via_spec *spec = codec->spec; - - if (!spec->autocfg.speaker_outs) - return; - if (!present) - present = snd_hda_jack_detect(codec, - spec->autocfg.line_out_pins[0]); - toggle_output_mutes(codec, spec->autocfg.speaker_outs, - spec->autocfg.speaker_pins, - present); -} - -/* mute internal speaker if HP is plugged */ -static void via_hp_automute(struct hda_codec *codec) -{ - int present = 0; - int nums; - struct via_spec *spec = codec->spec; - - if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] && - (spec->codec_type != VT1708 || spec->vt1708_jack_detect)) - present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); - - if (spec->smart51_enabled) - nums = spec->autocfg.line_outs + spec->smart51_nums; - else - nums = spec->autocfg.line_outs; - toggle_output_mutes(codec, nums, spec->autocfg.line_out_pins, present); - - via_line_automute(codec, present); -} - -static void via_gpio_control(struct hda_codec *codec) -{ - unsigned int gpio_data; - unsigned int vol_counter; - unsigned int vol; - unsigned int master_vol; - - struct via_spec *spec = codec->spec; - - gpio_data = snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_GET_GPIO_DATA, 0) & 0x03; - - vol_counter = (snd_hda_codec_read(codec, codec->afg, 0, - 0xF84, 0) & 0x3F0000) >> 16; - - vol = vol_counter & 0x1F; - master_vol = snd_hda_codec_read(codec, 0x1A, 0, - AC_VERB_GET_AMP_GAIN_MUTE, - AC_AMP_GET_INPUT); - - if (gpio_data == 0x02) { - /* unmute line out */ - snd_hda_codec_write(codec, spec->autocfg.line_out_pins[0], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_OUT); - if (vol_counter & 0x20) { - /* decrease volume */ - if (vol > master_vol) - vol = master_vol; - snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, - 0, HDA_AMP_VOLMASK, - master_vol-vol); - } else { - /* increase volume */ - snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0, - HDA_AMP_VOLMASK, - ((master_vol+vol) > 0x2A) ? 0x2A : - (master_vol+vol)); - } - } else if (!(gpio_data & 0x02)) { - /* mute line out */ - snd_hda_codec_write(codec, spec->autocfg.line_out_pins[0], 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - 0); - } -} - -/* unsolicited event for jack sensing */ -static void via_unsol_event(struct hda_codec *codec, - unsigned int res) -{ - res >>= 26; - res = snd_hda_jack_get_action(codec, res); - - if (res & VIA_JACK_EVENT) - set_widgets_power_state(codec); - - res &= ~VIA_JACK_EVENT; - - if (res == VIA_HP_EVENT || res == VIA_LINE_EVENT) - via_hp_automute(codec); - else if (res == VIA_GPIO_EVENT) - via_gpio_control(codec); - snd_hda_jack_report_sync(codec); -} - -#ifdef CONFIG_PM -static int via_suspend(struct hda_codec *codec, pm_message_t state) -{ - struct via_spec *spec = codec->spec; - vt1708_stop_hp_work(spec); - return 0; -} -#endif - -#ifdef CONFIG_SND_HDA_POWER_SAVE -static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) -{ - struct via_spec *spec = codec->spec; - return snd_hda_check_amp_list_power(codec, &spec->loopback, nid); -} -#endif - -/* - */ - -static int via_init(struct hda_codec *codec); - -static const struct hda_codec_ops via_patch_ops = { - .build_controls = via_build_controls, - .build_pcms = via_build_pcms, - .init = via_init, - .free = via_free, - .unsol_event = via_unsol_event, -#ifdef CONFIG_PM - .suspend = via_suspend, -#endif -#ifdef CONFIG_SND_HDA_POWER_SAVE - .check_power_status = via_check_power_status, -#endif -}; - -static bool is_empty_dac(struct hda_codec *codec, hda_nid_t dac) -{ - struct via_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->multiout.num_dacs; i++) { - if (spec->multiout.dac_nids[i] == dac) - return false; - } - if (spec->hp_dac_nid == dac) - return false; - return true; -} - -static bool __parse_output_path(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t target_dac, int with_aa_mix, - struct nid_path *path, int depth) -{ - struct via_spec *spec = codec->spec; - hda_nid_t conn[8]; - int i, nums; - - if (nid == spec->aa_mix_nid) { - if (!with_aa_mix) - return false; - with_aa_mix = 2; /* mark aa-mix is included */ - } - - nums = snd_hda_get_connections(codec, nid, conn, ARRAY_SIZE(conn)); - for (i = 0; i < nums; i++) { - if (get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT) - continue; - if (conn[i] == target_dac || is_empty_dac(codec, conn[i])) { - /* aa-mix is requested but not included? */ - if (!(spec->aa_mix_nid && with_aa_mix == 1)) - goto found; - } - } - if (depth >= MAX_NID_PATH_DEPTH) - return false; - for (i = 0; i < nums; i++) { - unsigned int type; - type = get_wcaps_type(get_wcaps(codec, conn[i])); - if (type == AC_WID_AUD_OUT) - continue; - if (__parse_output_path(codec, conn[i], target_dac, - with_aa_mix, path, depth + 1)) - goto found; - } - return false; - - found: - path->path[path->depth] = conn[i]; - path->idx[path->depth] = i; - if (nums > 1 && get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_MIX) - path->multi[path->depth] = 1; - path->depth++; - return true; -} - -static bool parse_output_path(struct hda_codec *codec, hda_nid_t nid, - hda_nid_t target_dac, int with_aa_mix, - struct nid_path *path) -{ - if (__parse_output_path(codec, nid, target_dac, with_aa_mix, path, 1)) { - path->path[path->depth] = nid; - path->depth++; - snd_printdd("output-path: depth=%d, %02x/%02x/%02x/%02x/%02x\n", - path->depth, path->path[0], path->path[1], - path->path[2], path->path[3], path->path[4]); - return true; - } - return false; -} - -static int via_auto_fill_dac_nids(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; - int i, dac_num; - hda_nid_t nid; - - spec->multiout.dac_nids = spec->private_dac_nids; - dac_num = 0; - for (i = 0; i < cfg->line_outs; i++) { - hda_nid_t dac = 0; - nid = cfg->line_out_pins[i]; - if (!nid) - continue; - if (parse_output_path(codec, nid, 0, 0, &spec->out_path[i])) - dac = spec->out_path[i].path[0]; - if (!i && parse_output_path(codec, nid, dac, 1, - &spec->out_mix_path)) - dac = spec->out_mix_path.path[0]; - if (dac) { - spec->private_dac_nids[i] = dac; - dac_num++; - } - } - if (!spec->out_path[0].depth && spec->out_mix_path.depth) { - spec->out_path[0] = spec->out_mix_path; - spec->out_mix_path.depth = 0; - } - spec->multiout.num_dacs = dac_num; - return 0; -} - -static int create_ch_ctls(struct hda_codec *codec, const char *pfx, - int chs, bool check_dac, struct nid_path *path) -{ - struct via_spec *spec = codec->spec; - char name[32]; - hda_nid_t dac, pin, sel, nid; - int err; - - dac = check_dac ? path->path[0] : 0; - pin = path->path[path->depth - 1]; - sel = path->depth > 1 ? path->path[1] : 0; - - if (dac && check_amp_caps(codec, dac, HDA_OUTPUT, AC_AMPCAP_NUM_STEPS)) - nid = dac; - else if (check_amp_caps(codec, pin, HDA_OUTPUT, AC_AMPCAP_NUM_STEPS)) - nid = pin; - else if (check_amp_caps(codec, sel, HDA_OUTPUT, AC_AMPCAP_NUM_STEPS)) - nid = sel; - else - nid = 0; - if (nid) { - sprintf(name, "%s Playback Volume", pfx); - err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); - if (err < 0) - return err; - path->vol_ctl = nid; - } - - if (dac && check_amp_caps(codec, dac, HDA_OUTPUT, AC_AMPCAP_MUTE)) - nid = dac; - else if (check_amp_caps(codec, pin, HDA_OUTPUT, AC_AMPCAP_MUTE)) - nid = pin; - else if (check_amp_caps(codec, sel, HDA_OUTPUT, AC_AMPCAP_MUTE)) - nid = sel; - else - nid = 0; - if (nid) { - sprintf(name, "%s Playback Switch", pfx); - err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); - if (err < 0) - return err; - path->mute_ctl = nid; - } - return 0; -} - -static void mangle_smart51(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - struct auto_pin_cfg_item *ins = cfg->inputs; - int i, j, nums, attr; - int pins[AUTO_CFG_MAX_INS]; - - for (attr = INPUT_PIN_ATTR_REAR; attr >= INPUT_PIN_ATTR_NORMAL; attr--) { - nums = 0; - for (i = 0; i < cfg->num_inputs; i++) { - unsigned int def; - if (ins[i].type > AUTO_PIN_LINE_IN) - continue; - def = snd_hda_codec_get_pincfg(codec, ins[i].pin); - if (snd_hda_get_input_pin_attr(def) != attr) - continue; - for (j = 0; j < nums; j++) - if (ins[pins[j]].type < ins[i].type) { - memmove(pins + j + 1, pins + j, - (nums - j) * sizeof(int)); - break; - } - pins[j] = i; - nums++; - } - if (cfg->line_outs + nums < 3) - continue; - for (i = 0; i < nums; i++) { - hda_nid_t pin = ins[pins[i]].pin; - spec->smart51_pins[spec->smart51_nums++] = pin; - cfg->line_out_pins[cfg->line_outs++] = pin; - if (cfg->line_outs == 3) - break; - } - return; - } -} - -static void copy_path_mixer_ctls(struct nid_path *dst, struct nid_path *src) -{ - dst->vol_ctl = src->vol_ctl; - dst->mute_ctl = src->mute_ctl; -} - -/* add playback controls from the parsed DAC table */ -static int via_auto_create_multi_out_ctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - struct nid_path *path; - static const char * const chname[4] = { - "Front", "Surround", "C/LFE", "Side" - }; - int i, idx, err; - int old_line_outs; - - /* check smart51 */ - old_line_outs = cfg->line_outs; - if (cfg->line_outs == 1) - mangle_smart51(codec); - - err = via_auto_fill_dac_nids(codec); - if (err < 0) - return err; - - if (spec->multiout.num_dacs < 3) { - spec->smart51_nums = 0; - cfg->line_outs = old_line_outs; - } - for (i = 0; i < cfg->line_outs; i++) { - hda_nid_t pin, dac; - pin = cfg->line_out_pins[i]; - dac = spec->multiout.dac_nids[i]; - if (!pin || !dac) - continue; - path = spec->out_path + i; - if (i == HDA_CLFE) { - err = create_ch_ctls(codec, "Center", 1, true, path); - if (err < 0) - return err; - err = create_ch_ctls(codec, "LFE", 2, true, path); - if (err < 0) - return err; - } else { - const char *pfx = chname[i]; - if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && - cfg->line_outs == 1) - pfx = "Speaker"; - err = create_ch_ctls(codec, pfx, 3, true, path); - if (err < 0) - return err; - } - if (path != spec->out_path + i) - copy_path_mixer_ctls(&spec->out_path[i], path); - if (path == spec->out_path && spec->out_mix_path.depth) - copy_path_mixer_ctls(&spec->out_mix_path, path); - } - - idx = get_connection_index(codec, spec->aa_mix_nid, - spec->multiout.dac_nids[0]); - if (idx >= 0) { - /* add control to mixer */ - const char *name; - name = spec->out_mix_path.depth ? - "PCM Loopback Playback Volume" : "PCM Playback Volume"; - err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(spec->aa_mix_nid, 3, - idx, HDA_INPUT)); - if (err < 0) - return err; - name = spec->out_mix_path.depth ? - "PCM Loopback Playback Switch" : "PCM Playback Switch"; - err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(spec->aa_mix_nid, 3, - idx, HDA_INPUT)); - if (err < 0) - return err; - } - - cfg->line_outs = old_line_outs; - - return 0; -} - -static int via_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin) -{ - struct via_spec *spec = codec->spec; - struct nid_path *path; - bool check_dac; - int i, err; - - if (!pin) - return 0; - - if (!parse_output_path(codec, pin, 0, 0, &spec->hp_indep_path)) { - for (i = HDA_SIDE; i >= HDA_CLFE; i--) { - if (i < spec->multiout.num_dacs && - parse_output_path(codec, pin, - spec->multiout.dac_nids[i], 0, - &spec->hp_indep_path)) { - spec->hp_indep_shared = i; - break; - } - } - } - if (spec->hp_indep_path.depth) { - spec->hp_dac_nid = spec->hp_indep_path.path[0]; - if (!spec->hp_indep_shared) - spec->hp_path = spec->hp_indep_path; - } - /* optionally check front-path w/o AA-mix */ - if (!spec->hp_path.depth) - parse_output_path(codec, pin, - spec->multiout.dac_nids[HDA_FRONT], 0, - &spec->hp_path); - - if (!parse_output_path(codec, pin, spec->multiout.dac_nids[HDA_FRONT], - 1, &spec->hp_mix_path) && !spec->hp_path.depth) - return 0; - - if (spec->hp_path.depth) { - path = &spec->hp_path; - check_dac = true; - } else { - path = &spec->hp_mix_path; - check_dac = false; - } - err = create_ch_ctls(codec, "Headphone", 3, check_dac, path); - if (err < 0) - return err; - if (check_dac) - copy_path_mixer_ctls(&spec->hp_mix_path, path); - else - copy_path_mixer_ctls(&spec->hp_path, path); - if (spec->hp_indep_path.depth) - copy_path_mixer_ctls(&spec->hp_indep_path, path); - return 0; -} - -static int via_auto_create_speaker_ctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct nid_path *path; - bool check_dac; - hda_nid_t pin, dac = 0; - int err; - - pin = spec->autocfg.speaker_pins[0]; - if (!spec->autocfg.speaker_outs || !pin) - return 0; - - if (parse_output_path(codec, pin, 0, 0, &spec->speaker_path)) - dac = spec->speaker_path.path[0]; - if (!dac) - parse_output_path(codec, pin, - spec->multiout.dac_nids[HDA_FRONT], 0, - &spec->speaker_path); - if (!parse_output_path(codec, pin, spec->multiout.dac_nids[HDA_FRONT], - 1, &spec->speaker_mix_path) && !dac) - return 0; - - /* no AA-path for front? */ - if (!spec->out_mix_path.depth && spec->speaker_mix_path.depth) - dac = 0; - - spec->speaker_dac_nid = dac; - spec->multiout.extra_out_nid[0] = dac; - if (dac) { - path = &spec->speaker_path; - check_dac = true; - } else { - path = &spec->speaker_mix_path; - check_dac = false; - } - err = create_ch_ctls(codec, "Speaker", 3, check_dac, path); - if (err < 0) - return err; - if (check_dac) - copy_path_mixer_ctls(&spec->speaker_mix_path, path); - else - copy_path_mixer_ctls(&spec->speaker_path, path); - return 0; -} - -#define via_aamix_ctl_info via_pin_power_ctl_info - -static int via_aamix_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - ucontrol->value.enumerated.item[0] = spec->aamix_mode; - return 0; -} - -static void update_aamix_paths(struct hda_codec *codec, int do_mix, - struct nid_path *nomix, struct nid_path *mix) -{ - if (do_mix) { - activate_output_path(codec, nomix, false, false); - activate_output_path(codec, mix, true, false); - } else { - activate_output_path(codec, mix, false, false); - activate_output_path(codec, nomix, true, false); - } -} - -static int via_aamix_ctl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - unsigned int val = ucontrol->value.enumerated.item[0]; - - if (val == spec->aamix_mode) - return 0; - spec->aamix_mode = val; - /* update front path */ - update_aamix_paths(codec, val, &spec->out_path[0], &spec->out_mix_path); - /* update HP path */ - if (!spec->hp_independent_mode) { - update_aamix_paths(codec, val, &spec->hp_path, - &spec->hp_mix_path); - } - /* update speaker path */ - update_aamix_paths(codec, val, &spec->speaker_path, - &spec->speaker_mix_path); - return 1; -} - -static const struct snd_kcontrol_new via_aamix_ctl_enum = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Loopback Mixing", - .info = via_aamix_ctl_info, - .get = via_aamix_ctl_get, - .put = via_aamix_ctl_put, -}; - -static int via_auto_create_loopback_switch(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - - if (!spec->aa_mix_nid) - return 0; /* no loopback switching available */ - if (!(spec->out_mix_path.depth || spec->hp_mix_path.depth || - spec->speaker_path.depth)) - return 0; /* no loopback switching available */ - if (!via_clone_control(spec, &via_aamix_ctl_enum)) - return -ENOMEM; - return 0; -} - -/* look for ADCs */ -static int via_fill_adcs(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - hda_nid_t nid = codec->start_nid; - int i; - - for (i = 0; i < codec->num_nodes; i++, nid++) { - unsigned int wcaps = get_wcaps(codec, nid); - if (get_wcaps_type(wcaps) != AC_WID_AUD_IN) - continue; - if (wcaps & AC_WCAP_DIGITAL) - continue; - if (!(wcaps & AC_WCAP_CONN_LIST)) - continue; - if (spec->num_adc_nids >= ARRAY_SIZE(spec->adc_nids)) - return -ENOMEM; - spec->adc_nids[spec->num_adc_nids++] = nid; - } - return 0; -} - -/* input-src control */ -static int via_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = spec->num_inputs; - if (uinfo->value.enumerated.item >= spec->num_inputs) - uinfo->value.enumerated.item = spec->num_inputs - 1; - strcpy(uinfo->value.enumerated.name, - spec->inputs[uinfo->value.enumerated.item].label); - return 0; -} - -static int via_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.enumerated.item[0] = spec->cur_mux[idx]; - return 0; -} - -static int via_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - hda_nid_t mux; - int cur; - - cur = ucontrol->value.enumerated.item[0]; - if (cur < 0 || cur >= spec->num_inputs) - return -EINVAL; - if (spec->cur_mux[idx] == cur) - return 0; - spec->cur_mux[idx] = cur; - if (spec->dyn_adc_switch) { - int adc_idx = spec->inputs[cur].adc_idx; - mux = spec->mux_nids[adc_idx]; - via_dyn_adc_pcm_resetup(codec, cur); - } else { - mux = spec->mux_nids[idx]; - if (snd_BUG_ON(!mux)) - return -EINVAL; - } - - if (mux) { - /* switch to D0 beofre change index */ - update_power_state(codec, mux, AC_PWRST_D0); - snd_hda_codec_write(codec, mux, 0, - AC_VERB_SET_CONNECT_SEL, - spec->inputs[cur].mux_idx); - } - - /* update jack power state */ - set_widgets_power_state(codec); - return 0; -} - -static const struct snd_kcontrol_new via_input_src_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .info = via_mux_enum_info, - .get = via_mux_enum_get, - .put = via_mux_enum_put, -}; - -static int create_input_src_ctls(struct hda_codec *codec, int count) -{ - struct via_spec *spec = codec->spec; - struct snd_kcontrol_new *knew; - - if (spec->num_inputs <= 1 || !count) - return 0; /* no need for single src */ - - knew = via_clone_control(spec, &via_input_src_ctl); - if (!knew) - return -ENOMEM; - knew->count = count; - return 0; -} - -/* add the powersave loopback-list entry */ -static void add_loopback_list(struct via_spec *spec, hda_nid_t mix, int idx) -{ - struct hda_amp_list *list; - - if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1) - return; - list = spec->loopback_list + spec->num_loopbacks; - list->nid = mix; - list->dir = HDA_INPUT; - list->idx = idx; - spec->num_loopbacks++; - spec->loopback.amplist = spec->loopback_list; -} - -static bool is_reachable_nid(struct hda_codec *codec, hda_nid_t src, - hda_nid_t dst) -{ - return snd_hda_get_conn_index(codec, src, dst, 1) >= 0; -} - -/* add the input-route to the given pin */ -static bool add_input_route(struct hda_codec *codec, hda_nid_t pin) -{ - struct via_spec *spec = codec->spec; - int c, idx; - - spec->inputs[spec->num_inputs].adc_idx = -1; - spec->inputs[spec->num_inputs].pin = pin; - for (c = 0; c < spec->num_adc_nids; c++) { - if (spec->mux_nids[c]) { - idx = get_connection_index(codec, spec->mux_nids[c], - pin); - if (idx < 0) - continue; - spec->inputs[spec->num_inputs].mux_idx = idx; - } else { - if (!is_reachable_nid(codec, spec->adc_nids[c], pin)) - continue; - } - spec->inputs[spec->num_inputs].adc_idx = c; - /* Can primary ADC satisfy all inputs? */ - if (!spec->dyn_adc_switch && - spec->num_inputs > 0 && spec->inputs[0].adc_idx != c) { - snd_printd(KERN_INFO - "via: dynamic ADC switching enabled\n"); - spec->dyn_adc_switch = 1; - } - return true; - } - return false; -} - -static int get_mux_nids(struct hda_codec *codec); - -/* parse input-routes; fill ADCs, MUXs and input-src entries */ -static int parse_analog_inputs(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; - int i, err; - - err = via_fill_adcs(codec); - if (err < 0) - return err; - err = get_mux_nids(codec); - if (err < 0) - return err; - - /* fill all input-routes */ - for (i = 0; i < cfg->num_inputs; i++) { - if (add_input_route(codec, cfg->inputs[i].pin)) - spec->inputs[spec->num_inputs++].label = - hda_get_autocfg_input_label(codec, cfg, i); - } - - /* check for internal loopback recording */ - if (spec->aa_mix_nid && - add_input_route(codec, spec->aa_mix_nid)) - spec->inputs[spec->num_inputs++].label = "Stereo Mixer"; - - return 0; -} - -/* create analog-loopback volume/switch controls */ -static int create_loopback_ctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; - const char *prev_label = NULL; - int type_idx = 0; - int i, j, err, idx; - - if (!spec->aa_mix_nid) - return 0; - - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t pin = cfg->inputs[i].pin; - const char *label = hda_get_autocfg_input_label(codec, cfg, i); - - if (prev_label && !strcmp(label, prev_label)) - type_idx++; - else - type_idx = 0; - prev_label = label; - idx = get_connection_index(codec, spec->aa_mix_nid, pin); - if (idx >= 0) { - err = via_new_analog_input(spec, label, type_idx, - idx, spec->aa_mix_nid); - if (err < 0) - return err; - add_loopback_list(spec, spec->aa_mix_nid, idx); - } - - /* remember the label for smart51 control */ - for (j = 0; j < spec->smart51_nums; j++) { - if (spec->smart51_pins[j] == pin) { - spec->smart51_idxs[j] = idx; - spec->smart51_labels[j] = label; - break; - } - } - } - return 0; -} - -/* create mic-boost controls (if present) */ -static int create_mic_boost_ctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; - const char *prev_label = NULL; - int type_idx = 0; - int i, err; - - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t pin = cfg->inputs[i].pin; - unsigned int caps; - const char *label; - char name[32]; - - if (cfg->inputs[i].type != AUTO_PIN_MIC) - continue; - caps = query_amp_caps(codec, pin, HDA_INPUT); - if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS)) - continue; - label = hda_get_autocfg_input_label(codec, cfg, i); - if (prev_label && !strcmp(label, prev_label)) - type_idx++; - else - type_idx = 0; - prev_label = label; - snprintf(name, sizeof(name), "%s Boost Volume", label); - err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, - HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT)); - if (err < 0) - return err; - } - return 0; -} - -/* create capture and input-src controls for multiple streams */ -static int create_multi_adc_ctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int i, err; - - /* create capture mixer elements */ - for (i = 0; i < spec->num_adc_nids; i++) { - hda_nid_t adc = spec->adc_nids[i]; - err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, - "Capture Volume", i, - HDA_COMPOSE_AMP_VAL(adc, 3, 0, - HDA_INPUT)); - if (err < 0) - return err; - err = __via_add_control(spec, VIA_CTL_WIDGET_MUTE, - "Capture Switch", i, - HDA_COMPOSE_AMP_VAL(adc, 3, 0, - HDA_INPUT)); - if (err < 0) - return err; - } - - /* input-source control */ - for (i = 0; i < spec->num_adc_nids; i++) - if (!spec->mux_nids[i]) - break; - err = create_input_src_ctls(codec, i); - if (err < 0) - return err; - return 0; -} - -/* bind capture volume/switch */ -static struct snd_kcontrol_new via_bind_cap_vol_ctl = - HDA_BIND_VOL("Capture Volume", 0); -static struct snd_kcontrol_new via_bind_cap_sw_ctl = - HDA_BIND_SW("Capture Switch", 0); - -static int init_bind_ctl(struct via_spec *spec, struct hda_bind_ctls **ctl_ret, - struct hda_ctl_ops *ops) -{ - struct hda_bind_ctls *ctl; - int i; - - ctl = kzalloc(sizeof(*ctl) + sizeof(long) * 4, GFP_KERNEL); - if (!ctl) - return -ENOMEM; - ctl->ops = ops; - for (i = 0; i < spec->num_adc_nids; i++) - ctl->values[i] = - HDA_COMPOSE_AMP_VAL(spec->adc_nids[i], 3, 0, HDA_INPUT); - *ctl_ret = ctl; - return 0; -} - -/* create capture and input-src controls for dynamic ADC-switch case */ -static int create_dyn_adc_ctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct snd_kcontrol_new *knew; - int err; - - /* set up the bind capture ctls */ - err = init_bind_ctl(spec, &spec->bind_cap_vol, &snd_hda_bind_vol); - if (err < 0) - return err; - err = init_bind_ctl(spec, &spec->bind_cap_sw, &snd_hda_bind_sw); - if (err < 0) - return err; - - /* create capture mixer elements */ - knew = via_clone_control(spec, &via_bind_cap_vol_ctl); - if (!knew) - return -ENOMEM; - knew->private_value = (long)spec->bind_cap_vol; - - knew = via_clone_control(spec, &via_bind_cap_sw_ctl); - if (!knew) - return -ENOMEM; - knew->private_value = (long)spec->bind_cap_sw; - - /* input-source control */ - err = create_input_src_ctls(codec, 1); - if (err < 0) - return err; - return 0; -} - -/* parse and create capture-related stuff */ -static int via_auto_create_analog_input_ctls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int err; - - err = parse_analog_inputs(codec); - if (err < 0) - return err; - if (spec->dyn_adc_switch) - err = create_dyn_adc_ctls(codec); - else - err = create_multi_adc_ctls(codec); - if (err < 0) - return err; - err = create_loopback_ctls(codec); - if (err < 0) - return err; - err = create_mic_boost_ctls(codec); - if (err < 0) - return err; - return 0; -} - -static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid) -{ - unsigned int def_conf; - unsigned char seqassoc; - - def_conf = snd_hda_codec_get_pincfg(codec, nid); - seqassoc = (unsigned char) get_defcfg_association(def_conf); - seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf); - if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE - && (seqassoc == 0xf0 || seqassoc == 0xff)) { - def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30)); - snd_hda_codec_set_pincfg(codec, nid, def_conf); - } - - return; -} - -static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - - if (spec->codec_type != VT1708) - return 0; - ucontrol->value.integer.value[0] = spec->vt1708_jack_detect; - return 0; -} - -static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - int val; - - if (spec->codec_type != VT1708) - return 0; - val = !!ucontrol->value.integer.value[0]; - if (spec->vt1708_jack_detect == val) - return 0; - spec->vt1708_jack_detect = val; - if (spec->vt1708_jack_detect && - snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) { - mute_aa_path(codec, 1); - notify_aa_path_ctls(codec); - } - via_hp_automute(codec); - vt1708_update_hp_work(spec); - return 1; -} - -static const struct snd_kcontrol_new vt1708_jack_detect_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Jack Detect", - .count = 1, - .info = snd_ctl_boolean_mono_info, - .get = vt1708_jack_detect_get, - .put = vt1708_jack_detect_put, -}; - -static void fill_dig_outs(struct hda_codec *codec); -static void fill_dig_in(struct hda_codec *codec); - -static int via_parse_auto_config(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int err; - - err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); - if (err < 0) - return err; - if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0]) - return -EINVAL; - - err = via_auto_create_multi_out_ctls(codec); - if (err < 0) - return err; - err = via_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]); - if (err < 0) - return err; - err = via_auto_create_speaker_ctls(codec); - if (err < 0) - return err; - err = via_auto_create_loopback_switch(codec); - if (err < 0) - return err; - err = via_auto_create_analog_input_ctls(codec); - if (err < 0) - return err; - - spec->multiout.max_channels = spec->multiout.num_dacs * 2; - - fill_dig_outs(codec); - fill_dig_in(codec); - - if (spec->kctls.list) - spec->mixers[spec->num_mixers++] = spec->kctls.list; - - - if (spec->hp_dac_nid && spec->hp_mix_path.depth) { - err = via_hp_build(codec); - if (err < 0) - return err; - } - - err = via_smart51_build(codec); - if (err < 0) - return err; - - /* assign slave outs */ - if (spec->slave_dig_outs[0]) - codec->slave_dig_outs = spec->slave_dig_outs; - - return 1; -} - -static void via_auto_init_dig_outs(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - if (spec->multiout.dig_out_nid) - init_output_pin(codec, spec->autocfg.dig_out_pins[0], PIN_OUT); - if (spec->slave_dig_outs[0]) - init_output_pin(codec, spec->autocfg.dig_out_pins[1], PIN_OUT); -} - -static void via_auto_init_dig_in(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - if (!spec->dig_in_nid) - return; - snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); -} - -/* initialize the unsolicited events */ -static void via_auto_init_unsol_event(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - struct auto_pin_cfg *cfg = &spec->autocfg; - unsigned int ev; - int i; - - if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0])) - snd_hda_jack_detect_enable(codec, cfg->hp_pins[0], - VIA_HP_EVENT | VIA_JACK_EVENT); - - if (cfg->speaker_pins[0]) - ev = VIA_LINE_EVENT; - else - ev = 0; - for (i = 0; i < cfg->line_outs; i++) { - if (cfg->line_out_pins[i] && - is_jack_detectable(codec, cfg->line_out_pins[i])) - snd_hda_jack_detect_enable(codec, cfg->line_out_pins[i], - ev | VIA_JACK_EVENT); - } - - for (i = 0; i < cfg->num_inputs; i++) { - if (is_jack_detectable(codec, cfg->inputs[i].pin)) - snd_hda_jack_detect_enable(codec, cfg->inputs[i].pin, - VIA_JACK_EVENT); - } -} - -static int via_init(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->num_iverbs; i++) - snd_hda_sequence_write(codec, spec->init_verbs[i]); - - /* init power states */ - set_widgets_power_state(codec); - __analog_low_current_mode(codec, true); - - via_auto_init_multi_out(codec); - via_auto_init_hp_out(codec); - via_auto_init_speaker_out(codec); - via_auto_init_analog_input(codec); - via_auto_init_dig_outs(codec); - via_auto_init_dig_in(codec); - - via_auto_init_unsol_event(codec); - - via_hp_automute(codec); - vt1708_update_hp_work(spec); - snd_hda_jack_report_sync(codec); - - return 0; -} - -static void vt1708_update_hp_jack_state(struct work_struct *work) -{ - struct via_spec *spec = container_of(work, struct via_spec, - vt1708_hp_work.work); - if (spec->codec_type != VT1708) - return; - snd_hda_jack_set_dirty_all(spec->codec); - /* if jack state toggled */ - if (spec->vt1708_hp_present - != snd_hda_jack_detect(spec->codec, spec->autocfg.hp_pins[0])) { - spec->vt1708_hp_present ^= 1; - via_hp_automute(spec->codec); - } - if (spec->vt1708_jack_detect) - schedule_delayed_work(&spec->vt1708_hp_work, - msecs_to_jiffies(100)); -} - -static int get_mux_nids(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - hda_nid_t nid, conn[8]; - unsigned int type; - int i, n; - - for (i = 0; i < spec->num_adc_nids; i++) { - nid = spec->adc_nids[i]; - while (nid) { - type = get_wcaps_type(get_wcaps(codec, nid)); - if (type == AC_WID_PIN) - break; - n = snd_hda_get_connections(codec, nid, conn, - ARRAY_SIZE(conn)); - if (n <= 0) - break; - if (n > 1) { - spec->mux_nids[i] = nid; - break; - } - nid = conn[0]; - } - } - return 0; -} - -static int patch_vt1708(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x17; - - /* Add HP and CD pin config connect bit re-config action */ - vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID); - vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID); - - /* automatic parse from the BIOS config */ - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - /* add jack detect on/off control */ - if (!via_clone_control(spec, &vt1708_jack_detect_ctl)) - return -ENOMEM; - - /* disable 32bit format on VT1708 */ - if (codec->vendor_id == 0x11061708) - spec->stream_analog_playback = &vt1708_pcm_analog_s16_playback; - - spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs; - - codec->patch_ops = via_patch_ops; - - INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state); - return 0; -} - -static int patch_vt1709(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x18; - - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - codec->patch_ops = via_patch_ops; - - return 0; -} - -static void set_widgets_power_state_vt1708B(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int imux_is_smixer; - unsigned int parm; - int is_8ch = 0; - if ((spec->codec_type != VT1708B_4CH) && - (codec->vendor_id != 0x11064397)) - is_8ch = 1; - - /* SW0 (17h) = stereo mixer */ - imux_is_smixer = - (snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) - == ((spec->codec_type == VT1708S) ? 5 : 0)); - /* inputs */ - /* PW 1/2/5 (1ah/1bh/1eh) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x1a, &parm); - set_pin_power_state(codec, 0x1b, &parm); - set_pin_power_state(codec, 0x1e, &parm); - if (imux_is_smixer) - parm = AC_PWRST_D0; - /* SW0 (17h), AIW 0/1 (13h/14h) */ - update_power_state(codec, 0x17, parm); - update_power_state(codec, 0x13, parm); - update_power_state(codec, 0x14, parm); - - /* outputs */ - /* PW0 (19h), SW1 (18h), AOW1 (11h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x19, &parm); - if (spec->smart51_enabled) - set_pin_power_state(codec, 0x1b, &parm); - update_power_state(codec, 0x18, parm); - update_power_state(codec, 0x11, parm); - - /* PW6 (22h), SW2 (26h), AOW2 (24h) */ - if (is_8ch) { - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x22, &parm); - if (spec->smart51_enabled) - set_pin_power_state(codec, 0x1a, &parm); - update_power_state(codec, 0x26, parm); - update_power_state(codec, 0x24, parm); - } else if (codec->vendor_id == 0x11064397) { - /* PW7(23h), SW2(27h), AOW2(25h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x23, &parm); - if (spec->smart51_enabled) - set_pin_power_state(codec, 0x1a, &parm); - update_power_state(codec, 0x27, parm); - update_power_state(codec, 0x25, parm); - } - - /* PW 3/4/7 (1ch/1dh/23h) */ - parm = AC_PWRST_D3; - /* force to D0 for internal Speaker */ - set_pin_power_state(codec, 0x1c, &parm); - set_pin_power_state(codec, 0x1d, &parm); - if (is_8ch) - set_pin_power_state(codec, 0x23, &parm); - - /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */ - update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm); - update_power_state(codec, 0x10, parm); - if (is_8ch) { - update_power_state(codec, 0x25, parm); - update_power_state(codec, 0x27, parm); - } else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode) - update_power_state(codec, 0x25, parm); -} - -static int patch_vt1708S(struct hda_codec *codec); -static int patch_vt1708B(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - if (get_codec_type(codec) == VT1708BCE) - return patch_vt1708S(codec); - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x16; - - /* automatic parse from the BIOS config */ - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - codec->patch_ops = via_patch_ops; - - spec->set_widgets_power_state = set_widgets_power_state_vt1708B; - - return 0; -} - -/* Patch for VT1708S */ -static const struct hda_verb vt1708S_init_verbs[] = { - /* Enable Mic Boost Volume backdoor */ - {0x1, 0xf98, 0x1}, - /* don't bybass mixer */ - {0x1, 0xf88, 0xc0}, - { } -}; - -/* fill out digital output widgets; one for master and one for slave outputs */ -static void fill_dig_outs(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->autocfg.dig_outs; i++) { - hda_nid_t nid; - int conn; - - nid = spec->autocfg.dig_out_pins[i]; - if (!nid) - continue; - conn = snd_hda_get_connections(codec, nid, &nid, 1); - if (conn < 1) - continue; - if (!spec->multiout.dig_out_nid) - spec->multiout.dig_out_nid = nid; - else { - spec->slave_dig_outs[0] = nid; - break; /* at most two dig outs */ - } - } -} - -static void fill_dig_in(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - hda_nid_t dig_nid; - int i, err; - - if (!spec->autocfg.dig_in_pin) - return; - - dig_nid = codec->start_nid; - for (i = 0; i < codec->num_nodes; i++, dig_nid++) { - unsigned int wcaps = get_wcaps(codec, dig_nid); - if (get_wcaps_type(wcaps) != AC_WID_AUD_IN) - continue; - if (!(wcaps & AC_WCAP_DIGITAL)) - continue; - if (!(wcaps & AC_WCAP_CONN_LIST)) - continue; - err = get_connection_index(codec, dig_nid, - spec->autocfg.dig_in_pin); - if (err >= 0) { - spec->dig_in_nid = dig_nid; - break; - } - } -} - -static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin, - int offset, int num_steps, int step_size) -{ - snd_hda_override_amp_caps(codec, pin, HDA_INPUT, - (offset << AC_AMPCAP_OFFSET_SHIFT) | - (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) | - (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) | - (0 << AC_AMPCAP_MUTE_SHIFT)); -} - -static int patch_vt1708S(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x16; - override_mic_boost(codec, 0x1a, 0, 3, 40); - override_mic_boost(codec, 0x1e, 0, 3, 40); - - /* automatic parse from the BIOS config */ - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs; - - codec->patch_ops = via_patch_ops; - - /* correct names for VT1708BCE */ - if (get_codec_type(codec) == VT1708BCE) { - kfree(codec->chip_name); - codec->chip_name = kstrdup("VT1708BCE", GFP_KERNEL); - snprintf(codec->bus->card->mixername, - sizeof(codec->bus->card->mixername), - "%s %s", codec->vendor_name, codec->chip_name); - } - /* correct names for VT1705 */ - if (codec->vendor_id == 0x11064397) { - kfree(codec->chip_name); - codec->chip_name = kstrdup("VT1705", GFP_KERNEL); - snprintf(codec->bus->card->mixername, - sizeof(codec->bus->card->mixername), - "%s %s", codec->vendor_name, codec->chip_name); - } - spec->set_widgets_power_state = set_widgets_power_state_vt1708B; - return 0; -} - -/* Patch for VT1702 */ - -static const struct hda_verb vt1702_init_verbs[] = { - /* mixer enable */ - {0x1, 0xF88, 0x3}, - /* GPIO 0~2 */ - {0x1, 0xF82, 0x3F}, - { } -}; - -static void set_widgets_power_state_vt1702(struct hda_codec *codec) -{ - int imux_is_smixer = - snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3; - unsigned int parm; - /* inputs */ - /* PW 1/2/5 (14h/15h/18h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x14, &parm); - set_pin_power_state(codec, 0x15, &parm); - set_pin_power_state(codec, 0x18, &parm); - if (imux_is_smixer) - parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */ - /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */ - update_power_state(codec, 0x13, parm); - update_power_state(codec, 0x12, parm); - update_power_state(codec, 0x1f, parm); - update_power_state(codec, 0x20, parm); - - /* outputs */ - /* PW 3/4 (16h/17h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x17, &parm); - set_pin_power_state(codec, 0x16, &parm); - /* MW0 (1ah), AOW 0/1 (10h/1dh) */ - update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm); - update_power_state(codec, 0x10, parm); - update_power_state(codec, 0x1d, parm); -} - -static int patch_vt1702(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x1a; - - /* limit AA path volume to 0 dB */ - snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT, - (0x17 << AC_AMPCAP_OFFSET_SHIFT) | - (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | - (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | - (1 << AC_AMPCAP_MUTE_SHIFT)); - - /* automatic parse from the BIOS config */ - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs; - - codec->patch_ops = via_patch_ops; - - spec->set_widgets_power_state = set_widgets_power_state_vt1702; - return 0; -} - -/* Patch for VT1718S */ - -static const struct hda_verb vt1718S_init_verbs[] = { - /* Enable MW0 adjust Gain 5 */ - {0x1, 0xfb2, 0x10}, - /* Enable Boost Volume backdoor */ - {0x1, 0xf88, 0x8}, - - { } -}; - -static void set_widgets_power_state_vt1718S(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int imux_is_smixer; - unsigned int parm; - /* MUX6 (1eh) = stereo mixer */ - imux_is_smixer = - snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5; - /* inputs */ - /* PW 5/6/7 (29h/2ah/2bh) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x29, &parm); - set_pin_power_state(codec, 0x2a, &parm); - set_pin_power_state(codec, 0x2b, &parm); - if (imux_is_smixer) - parm = AC_PWRST_D0; - /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */ - update_power_state(codec, 0x1e, parm); - update_power_state(codec, 0x1f, parm); - update_power_state(codec, 0x10, parm); - update_power_state(codec, 0x11, parm); - - /* outputs */ - /* PW3 (27h), MW2 (1ah), AOW3 (bh) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x27, &parm); - update_power_state(codec, 0x1a, parm); - update_power_state(codec, 0xb, parm); - - /* PW2 (26h), AOW2 (ah) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x26, &parm); - if (spec->smart51_enabled) - set_pin_power_state(codec, 0x2b, &parm); - update_power_state(codec, 0xa, parm); - - /* PW0 (24h), AOW0 (8h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x24, &parm); - if (!spec->hp_independent_mode) /* check for redirected HP */ - set_pin_power_state(codec, 0x28, &parm); - update_power_state(codec, 0x8, parm); - /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */ - update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm); - - /* PW1 (25h), AOW1 (9h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x25, &parm); - if (spec->smart51_enabled) - set_pin_power_state(codec, 0x2a, &parm); - update_power_state(codec, 0x9, parm); - - if (spec->hp_independent_mode) { - /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x28, &parm); - update_power_state(codec, 0x1b, parm); - update_power_state(codec, 0x34, parm); - update_power_state(codec, 0xc, parm); - } -} - -/* Add a connection to the primary DAC from AA-mixer for some codecs - * This isn't listed from the raw info, but the chip has a secret connection. - */ -static int add_secret_dac_path(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int i, nums; - hda_nid_t conn[8]; - hda_nid_t nid; - - if (!spec->aa_mix_nid) - return 0; - nums = snd_hda_get_connections(codec, spec->aa_mix_nid, conn, - ARRAY_SIZE(conn) - 1); - for (i = 0; i < nums; i++) { - if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT) - return 0; - } - - /* find the primary DAC and add to the connection list */ - nid = codec->start_nid; - for (i = 0; i < codec->num_nodes; i++, nid++) { - unsigned int caps = get_wcaps(codec, nid); - if (get_wcaps_type(caps) == AC_WID_AUD_OUT && - !(caps & AC_WCAP_DIGITAL)) { - conn[nums++] = nid; - return snd_hda_override_conn_list(codec, - spec->aa_mix_nid, - nums, conn); - } - } - return 0; -} - - -static int patch_vt1718S(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x21; - override_mic_boost(codec, 0x2b, 0, 3, 40); - override_mic_boost(codec, 0x29, 0, 3, 40); - add_secret_dac_path(codec); - - /* automatic parse from the BIOS config */ - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs; - - codec->patch_ops = via_patch_ops; - - spec->set_widgets_power_state = set_widgets_power_state_vt1718S; - - return 0; -} - -/* Patch for VT1716S */ - -static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - int index = 0; - - index = snd_hda_codec_read(codec, 0x26, 0, - AC_VERB_GET_CONNECT_SEL, 0); - if (index != -1) - *ucontrol->value.integer.value = index; - - return 0; -} - -static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct via_spec *spec = codec->spec; - int index = *ucontrol->value.integer.value; - - snd_hda_codec_write(codec, 0x26, 0, - AC_VERB_SET_CONNECT_SEL, index); - spec->dmic_enabled = index; - set_widgets_power_state(codec); - return 1; -} - -static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = { - HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Mic Capture Switch", - .subdevice = HDA_SUBDEV_NID_FLAG | 0x26, - .count = 1, - .info = vt1716s_dmic_info, - .get = vt1716s_dmic_get, - .put = vt1716s_dmic_put, - }, - {} /* end */ -}; - - -/* mono-out mixer elements */ -static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = { - HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static const struct hda_verb vt1716S_init_verbs[] = { - /* Enable Boost Volume backdoor */ - {0x1, 0xf8a, 0x80}, - /* don't bybass mixer */ - {0x1, 0xf88, 0xc0}, - /* Enable mono output */ - {0x1, 0xf90, 0x08}, - { } -}; - -static void set_widgets_power_state_vt1716S(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int imux_is_smixer; - unsigned int parm; - unsigned int mono_out, present; - /* SW0 (17h) = stereo mixer */ - imux_is_smixer = - (snd_hda_codec_read(codec, 0x17, 0, - AC_VERB_GET_CONNECT_SEL, 0x00) == 5); - /* inputs */ - /* PW 1/2/5 (1ah/1bh/1eh) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x1a, &parm); - set_pin_power_state(codec, 0x1b, &parm); - set_pin_power_state(codec, 0x1e, &parm); - if (imux_is_smixer) - parm = AC_PWRST_D0; - /* SW0 (17h), AIW0(13h) */ - update_power_state(codec, 0x17, parm); - update_power_state(codec, 0x13, parm); - - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x1e, &parm); - /* PW11 (22h) */ - if (spec->dmic_enabled) - set_pin_power_state(codec, 0x22, &parm); - else - update_power_state(codec, 0x22, AC_PWRST_D3); - - /* SW2(26h), AIW1(14h) */ - update_power_state(codec, 0x26, parm); - update_power_state(codec, 0x14, parm); - - /* outputs */ - /* PW0 (19h), SW1 (18h), AOW1 (11h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x19, &parm); - /* Smart 5.1 PW2(1bh) */ - if (spec->smart51_enabled) - set_pin_power_state(codec, 0x1b, &parm); - update_power_state(codec, 0x18, parm); - update_power_state(codec, 0x11, parm); - - /* PW7 (23h), SW3 (27h), AOW3 (25h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x23, &parm); - /* Smart 5.1 PW1(1ah) */ - if (spec->smart51_enabled) - set_pin_power_state(codec, 0x1a, &parm); - update_power_state(codec, 0x27, parm); - - /* Smart 5.1 PW5(1eh) */ - if (spec->smart51_enabled) - set_pin_power_state(codec, 0x1e, &parm); - update_power_state(codec, 0x25, parm); - - /* Mono out */ - /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/ - present = snd_hda_jack_detect(codec, 0x1c); - - if (present) - mono_out = 0; - else { - present = snd_hda_jack_detect(codec, 0x1d); - if (!spec->hp_independent_mode && present) - mono_out = 0; - else - mono_out = 1; - } - parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3; - update_power_state(codec, 0x28, parm); - update_power_state(codec, 0x29, parm); - update_power_state(codec, 0x2a, parm); - - /* PW 3/4 (1ch/1dh) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x1c, &parm); - set_pin_power_state(codec, 0x1d, &parm); - /* HP Independent Mode, power on AOW3 */ - if (spec->hp_independent_mode) - update_power_state(codec, 0x25, parm); - - /* force to D0 for internal Speaker */ - /* MW0 (16h), AOW0 (10h) */ - update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm); - update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm); -} - -static int patch_vt1716S(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x16; - override_mic_boost(codec, 0x1a, 0, 3, 40); - override_mic_boost(codec, 0x1e, 0, 3, 40); - - /* automatic parse from the BIOS config */ - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs; - - spec->mixers[spec->num_mixers] = vt1716s_dmic_mixer; - spec->num_mixers++; - - spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer; - - codec->patch_ops = via_patch_ops; - - spec->set_widgets_power_state = set_widgets_power_state_vt1716S; - return 0; -} - -/* for vt2002P */ - -static const struct hda_verb vt2002P_init_verbs[] = { - /* Class-D speaker related verbs */ - {0x1, 0xfe0, 0x4}, - {0x1, 0xfe9, 0x80}, - {0x1, 0xfe2, 0x22}, - /* Enable Boost Volume backdoor */ - {0x1, 0xfb9, 0x24}, - /* Enable AOW0 to MW9 */ - {0x1, 0xfb8, 0x88}, - { } -}; - -static const struct hda_verb vt1802_init_verbs[] = { - /* Enable Boost Volume backdoor */ - {0x1, 0xfb9, 0x24}, - /* Enable AOW0 to MW9 */ - {0x1, 0xfb8, 0x88}, - { } -}; - -static void set_widgets_power_state_vt2002P(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int imux_is_smixer; - unsigned int parm; - unsigned int present; - /* MUX9 (1eh) = stereo mixer */ - imux_is_smixer = - snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3; - /* inputs */ - /* PW 5/6/7 (29h/2ah/2bh) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x29, &parm); - set_pin_power_state(codec, 0x2a, &parm); - set_pin_power_state(codec, 0x2b, &parm); - parm = AC_PWRST_D0; - /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */ - update_power_state(codec, 0x1e, parm); - update_power_state(codec, 0x1f, parm); - update_power_state(codec, 0x10, parm); - update_power_state(codec, 0x11, parm); - - /* outputs */ - /* AOW0 (8h)*/ - update_power_state(codec, 0x8, parm); - - if (spec->codec_type == VT1802) { - /* PW4 (28h), MW4 (18h), MUX4(38h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x28, &parm); - update_power_state(codec, 0x18, parm); - update_power_state(codec, 0x38, parm); - } else { - /* PW4 (26h), MW4 (1ch), MUX4(37h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x26, &parm); - update_power_state(codec, 0x1c, parm); - update_power_state(codec, 0x37, parm); - } - - if (spec->codec_type == VT1802) { - /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x25, &parm); - update_power_state(codec, 0x15, parm); - update_power_state(codec, 0x35, parm); - } else { - /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x25, &parm); - update_power_state(codec, 0x19, parm); - update_power_state(codec, 0x35, parm); - } - - if (spec->hp_independent_mode) - update_power_state(codec, 0x9, AC_PWRST_D0); - - /* Class-D */ - /* PW0 (24h), MW0(18h/14h), MUX0(34h) */ - present = snd_hda_jack_detect(codec, 0x25); - - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x24, &parm); - parm = present ? AC_PWRST_D3 : AC_PWRST_D0; - if (spec->codec_type == VT1802) - update_power_state(codec, 0x14, parm); - else - update_power_state(codec, 0x18, parm); - update_power_state(codec, 0x34, parm); - - /* Mono Out */ - present = snd_hda_jack_detect(codec, 0x26); - - parm = present ? AC_PWRST_D3 : AC_PWRST_D0; - if (spec->codec_type == VT1802) { - /* PW15 (33h), MW8(1ch), MUX8(3ch) */ - update_power_state(codec, 0x33, parm); - update_power_state(codec, 0x1c, parm); - update_power_state(codec, 0x3c, parm); - } else { - /* PW15 (31h), MW8(17h), MUX8(3bh) */ - update_power_state(codec, 0x31, parm); - update_power_state(codec, 0x17, parm); - update_power_state(codec, 0x3b, parm); - } - /* MW9 (21h) */ - if (imux_is_smixer || !is_aa_path_mute(codec)) - update_power_state(codec, 0x21, AC_PWRST_D0); - else - update_power_state(codec, 0x21, AC_PWRST_D3); -} - -/* patch for vt2002P */ -static int patch_vt2002P(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x21; - override_mic_boost(codec, 0x2b, 0, 3, 40); - override_mic_boost(codec, 0x29, 0, 3, 40); - add_secret_dac_path(codec); - - /* automatic parse from the BIOS config */ - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - if (spec->codec_type == VT1802) - spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs; - else - spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs; - - codec->patch_ops = via_patch_ops; - - spec->set_widgets_power_state = set_widgets_power_state_vt2002P; - return 0; -} - -/* for vt1812 */ - -static const struct hda_verb vt1812_init_verbs[] = { - /* Enable Boost Volume backdoor */ - {0x1, 0xfb9, 0x24}, - /* Enable AOW0 to MW9 */ - {0x1, 0xfb8, 0xa8}, - { } -}; - -static void set_widgets_power_state_vt1812(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - unsigned int parm; - unsigned int present; - /* inputs */ - /* PW 5/6/7 (29h/2ah/2bh) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x29, &parm); - set_pin_power_state(codec, 0x2a, &parm); - set_pin_power_state(codec, 0x2b, &parm); - parm = AC_PWRST_D0; - /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */ - update_power_state(codec, 0x1e, parm); - update_power_state(codec, 0x1f, parm); - update_power_state(codec, 0x10, parm); - update_power_state(codec, 0x11, parm); - - /* outputs */ - /* AOW0 (8h)*/ - update_power_state(codec, 0x8, AC_PWRST_D0); - - /* PW4 (28h), MW4 (18h), MUX4(38h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x28, &parm); - update_power_state(codec, 0x18, parm); - update_power_state(codec, 0x38, parm); - - /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x25, &parm); - update_power_state(codec, 0x15, parm); - update_power_state(codec, 0x35, parm); - if (spec->hp_independent_mode) - update_power_state(codec, 0x9, AC_PWRST_D0); - - /* Internal Speaker */ - /* PW0 (24h), MW0(14h), MUX0(34h) */ - present = snd_hda_jack_detect(codec, 0x25); - - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x24, &parm); - if (present) { - update_power_state(codec, 0x14, AC_PWRST_D3); - update_power_state(codec, 0x34, AC_PWRST_D3); - } else { - update_power_state(codec, 0x14, AC_PWRST_D0); - update_power_state(codec, 0x34, AC_PWRST_D0); - } - - - /* Mono Out */ - /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */ - present = snd_hda_jack_detect(codec, 0x28); - - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x31, &parm); - if (present) { - update_power_state(codec, 0x1c, AC_PWRST_D3); - update_power_state(codec, 0x3c, AC_PWRST_D3); - update_power_state(codec, 0x3e, AC_PWRST_D3); - } else { - update_power_state(codec, 0x1c, AC_PWRST_D0); - update_power_state(codec, 0x3c, AC_PWRST_D0); - update_power_state(codec, 0x3e, AC_PWRST_D0); - } - - /* PW15 (33h), MW15 (1dh), MUX15(3dh) */ - parm = AC_PWRST_D3; - set_pin_power_state(codec, 0x33, &parm); - update_power_state(codec, 0x1d, parm); - update_power_state(codec, 0x3d, parm); - -} - -/* patch for vt1812 */ -static int patch_vt1812(struct hda_codec *codec) -{ - struct via_spec *spec; - int err; - - /* create a codec specific record */ - spec = via_new_spec(codec); - if (spec == NULL) - return -ENOMEM; - - spec->aa_mix_nid = 0x21; - override_mic_boost(codec, 0x2b, 0, 3, 40); - override_mic_boost(codec, 0x29, 0, 3, 40); - add_secret_dac_path(codec); - - /* automatic parse from the BIOS config */ - err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } - - spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs; - - codec->patch_ops = via_patch_ops; - - spec->set_widgets_power_state = set_widgets_power_state_vt1812; - return 0; -} - -/* - * patch entries - */ -static const struct hda_codec_preset snd_hda_preset_via[] = { - { .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708}, - { .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708}, - { .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708}, - { .id = 0x1106170b, .name = "VT1708", .patch = patch_vt1708}, - { .id = 0x1106e710, .name = "VT1709 10-Ch", - .patch = patch_vt1709}, - { .id = 0x1106e711, .name = "VT1709 10-Ch", - .patch = patch_vt1709}, - { .id = 0x1106e712, .name = "VT1709 10-Ch", - .patch = patch_vt1709}, - { .id = 0x1106e713, .name = "VT1709 10-Ch", - .patch = patch_vt1709}, - { .id = 0x1106e714, .name = "VT1709 6-Ch", - .patch = patch_vt1709}, - { .id = 0x1106e715, .name = "VT1709 6-Ch", - .patch = patch_vt1709}, - { .id = 0x1106e716, .name = "VT1709 6-Ch", - .patch = patch_vt1709}, - { .id = 0x1106e717, .name = "VT1709 6-Ch", - .patch = patch_vt1709}, - { .id = 0x1106e720, .name = "VT1708B 8-Ch", - .patch = patch_vt1708B}, - { .id = 0x1106e721, .name = "VT1708B 8-Ch", - .patch = patch_vt1708B}, - { .id = 0x1106e722, .name = "VT1708B 8-Ch", - .patch = patch_vt1708B}, - { .id = 0x1106e723, .name = "VT1708B 8-Ch", - .patch = patch_vt1708B}, - { .id = 0x1106e724, .name = "VT1708B 4-Ch", - .patch = patch_vt1708B}, - { .id = 0x1106e725, .name = "VT1708B 4-Ch", - .patch = patch_vt1708B}, - { .id = 0x1106e726, .name = "VT1708B 4-Ch", - .patch = patch_vt1708B}, - { .id = 0x1106e727, .name = "VT1708B 4-Ch", - .patch = patch_vt1708B}, - { .id = 0x11060397, .name = "VT1708S", - .patch = patch_vt1708S}, - { .id = 0x11061397, .name = "VT1708S", - .patch = patch_vt1708S}, - { .id = 0x11062397, .name = "VT1708S", - .patch = patch_vt1708S}, - { .id = 0x11063397, .name = "VT1708S", - .patch = patch_vt1708S}, - { .id = 0x11064397, .name = "VT1705", - .patch = patch_vt1708S}, - { .id = 0x11065397, .name = "VT1708S", - .patch = patch_vt1708S}, - { .id = 0x11066397, .name = "VT1708S", - .patch = patch_vt1708S}, - { .id = 0x11067397, .name = "VT1708S", - .patch = patch_vt1708S}, - { .id = 0x11060398, .name = "VT1702", - .patch = patch_vt1702}, - { .id = 0x11061398, .name = "VT1702", - .patch = patch_vt1702}, - { .id = 0x11062398, .name = "VT1702", - .patch = patch_vt1702}, - { .id = 0x11063398, .name = "VT1702", - .patch = patch_vt1702}, - { .id = 0x11064398, .name = "VT1702", - .patch = patch_vt1702}, - { .id = 0x11065398, .name = "VT1702", - .patch = patch_vt1702}, - { .id = 0x11066398, .name = "VT1702", - .patch = patch_vt1702}, - { .id = 0x11067398, .name = "VT1702", - .patch = patch_vt1702}, - { .id = 0x11060428, .name = "VT1718S", - .patch = patch_vt1718S}, - { .id = 0x11064428, .name = "VT1718S", - .patch = patch_vt1718S}, - { .id = 0x11060441, .name = "VT2020", - .patch = patch_vt1718S}, - { .id = 0x11064441, .name = "VT1828S", - .patch = patch_vt1718S}, - { .id = 0x11060433, .name = "VT1716S", - .patch = patch_vt1716S}, - { .id = 0x1106a721, .name = "VT1716S", - .patch = patch_vt1716S}, - { .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P}, - { .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P}, - { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812}, - { .id = 0x11060440, .name = "VT1818S", - .patch = patch_vt1708S}, - { .id = 0x11060446, .name = "VT1802", - .patch = patch_vt2002P}, - { .id = 0x11068446, .name = "VT1802", - .patch = patch_vt2002P}, - {} /* terminator */ -}; - -MODULE_ALIAS("snd-hda-codec-id:1106*"); - -static struct hda_codec_preset_list via_list = { - .preset = snd_hda_preset_via, - .owner = THIS_MODULE, -}; - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("VIA HD-audio codec"); - -static int __init patch_via_init(void) -{ - return snd_hda_add_codec_preset(&via_list); -} - -static void __exit patch_via_exit(void) -{ - snd_hda_delete_codec_preset(&via_list); -} - -module_init(patch_via_init) -module_exit(patch_via_exit) diff --git a/ANDROID_3.4.5/sound/pci/ice1712/Makefile b/ANDROID_3.4.5/sound/pci/ice1712/Makefile deleted file mode 100644 index f7ce33f0..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-ice17xx-ak4xxx-objs := ak4xxx.o -snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o -snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o -obj-$(CONFIG_SND_ICE1724) += snd-ice1724.o snd-ice17xx-ak4xxx.o diff --git a/ANDROID_3.4.5/sound/pci/ice1712/ak4xxx.c b/ANDROID_3.4.5/sound/pci/ice1712/ak4xxx.c deleted file mode 100644 index 3981823f..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/ak4xxx.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 "ice1712.h" - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); -MODULE_LICENSE("GPL"); - -static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ice1712 *ice = ak->private_data[0]; - - snd_ice1712_save_gpio_status(ice); -} - -static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ice1712 *ice = ak->private_data[0]; - - snd_ice1712_restore_gpio_status(ice); -} - -/* - * write AK4xxx register - */ -static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip, - unsigned char addr, unsigned char data) -{ - unsigned int tmp; - int idx; - unsigned int addrdata; - struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; - struct snd_ice1712 *ice = ak->private_data[0]; - - if (snd_BUG_ON(chip < 0 || chip >= 4)) - return; - - tmp = snd_ice1712_gpio_read(ice); - tmp |= priv->add_flags; - tmp &= ~priv->mask_flags; - if (priv->cs_mask == priv->cs_addr) { - if (priv->cif) { - tmp |= priv->cs_mask; /* start without chip select */ - } else { - tmp &= ~priv->cs_mask; /* chip select low */ - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - } else { - /* doesn't handle cf=1 yet */ - tmp &= ~priv->cs_mask; - tmp |= priv->cs_addr; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - - /* build I2C address + data byte */ - addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f); - addrdata = (addrdata << 8) | data; - for (idx = 15; idx >= 0; idx--) { - /* drop clock */ - tmp &= ~priv->clk_mask; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - /* set data */ - if (addrdata & (1 << idx)) - tmp |= priv->data_mask; - else - tmp &= ~priv->data_mask; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - /* raise clock */ - tmp |= priv->clk_mask; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - - if (priv->cs_mask == priv->cs_addr) { - if (priv->cif) { - /* assert a cs pulse to trigger */ - tmp &= ~priv->cs_mask; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - tmp |= priv->cs_mask; /* chip select high to trigger */ - } else { - tmp &= ~priv->cs_mask; - tmp |= priv->cs_none; /* deselect address */ - } - snd_ice1712_gpio_write(ice, tmp); - udelay(1); -} - -/* - * initialize the struct snd_akm4xxx record with the template - */ -int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp, - const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice) -{ - struct snd_ak4xxx_private *priv; - - if (_priv != NULL) { - priv = kmalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - *priv = *_priv; - } else { - priv = NULL; - } - *ak = *temp; - ak->card = ice->card; - ak->private_value[0] = (unsigned long)priv; - ak->private_data[0] = ice; - if (ak->ops.lock == NULL) - ak->ops.lock = snd_ice1712_akm4xxx_lock; - if (ak->ops.unlock == NULL) - ak->ops.unlock = snd_ice1712_akm4xxx_unlock; - if (ak->ops.write == NULL) - ak->ops.write = snd_ice1712_akm4xxx_write; - snd_akm4xxx_init(ak); - return 0; -} - -void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice) -{ - unsigned int akidx; - if (ice->akm == NULL) - return; - for (akidx = 0; akidx < ice->akm_codecs; akidx++) { - struct snd_akm4xxx *ak = &ice->akm[akidx]; - kfree((void*)ak->private_value[0]); - } - kfree(ice->akm); -} - -/* - * build AK4xxx controls - */ -int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice) -{ - unsigned int akidx; - int err; - - for (akidx = 0; akidx < ice->akm_codecs; akidx++) { - struct snd_akm4xxx *ak = &ice->akm[akidx]; - err = snd_akm4xxx_build_controls(ak); - if (err < 0) - return err; - } - return 0; -} - -static int __init alsa_ice1712_akm4xxx_module_init(void) -{ - return 0; -} - -static void __exit alsa_ice1712_akm4xxx_module_exit(void) -{ -} - -module_init(alsa_ice1712_akm4xxx_module_init) -module_exit(alsa_ice1712_akm4xxx_module_exit) - -EXPORT_SYMBOL(snd_ice1712_akm4xxx_init); -EXPORT_SYMBOL(snd_ice1712_akm4xxx_free); -EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls); diff --git a/ANDROID_3.4.5/sound/pci/ice1712/amp.c b/ANDROID_3.4.5/sound/pci/ice1712/amp.c deleted file mode 100644 index e525da26..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/amp.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include "amp.h" - -static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - unsigned short cval; - cval = (reg << 9) | val; - snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff); -} - -static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice) -{ - static const unsigned short wm_inits[] = { - WM_ATTEN_L, 0x0000, /* 0 db */ - WM_ATTEN_R, 0x0000, /* 0 db */ - WM_DAC_CTRL, 0x0008, /* 24bit I2S */ - WM_INT_CTRL, 0x0001, /* 24bit I2S */ - }; - - unsigned int i; - - /* only use basic functionality for now */ - - /* VT1616 6ch codec connected to PSDOUT0 using packed mode */ - ice->num_total_dacs = 6; - ice->num_total_adcs = 2; - - /* Chaintech AV-710 has another WM8728 codec connected to PSDOUT4 - (shared with the SPDIF output). Mixer control for this codec - is not yet supported. */ - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) { - for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) - wm_put(ice, wm_inits[i], wm_inits[i+1]); - } - - return 0; -} - -static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice) -{ - if (ice->ac97) - /* we use pins 39 and 41 of the VT1616 for left and right - read outputs */ - snd_ac97_write_cache(ice->ac97, 0x5a, - snd_ac97_read(ice->ac97, 0x5a) & ~0x8000); - return 0; -} - - -/* entry point */ -struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_AV710, - .name = "Chaintech AV-710", - .model = "av710", - .chip_init = snd_vt1724_amp_init, - .build_controls = snd_vt1724_amp_add_controls, - }, - { - .subvendor = VT1724_SUBDEVICE_AUDIO2000, - .name = "AMP Ltd AUDIO2000", - .model = "amp2000", - .chip_init = snd_vt1724_amp_init, - .build_controls = snd_vt1724_amp_add_controls, - }, - { } /* terminator */ -}; - diff --git a/ANDROID_3.4.5/sound/pci/ice1712/amp.h b/ANDROID_3.4.5/sound/pci/ice1712/amp.h deleted file mode 100644 index bf81d30d..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/amp.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __SOUND_AMP_H -#define __SOUND_AMP_H - -/* - * ALSA driver for VIA VT1724 (Envy24HT) - * - * Lowlevel functions for Advanced Micro Peripherals Ltd AUDIO2000 - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 - * - */ - -#define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000},"\ - "{Chaintech,AV-710}," - -#if 0 -#define VT1724_SUBDEVICE_AUDIO2000 0x12142417 /* Advanced Micro Peripherals Ltd AUDIO2000 */ -#else -#define VT1724_SUBDEVICE_AUDIO2000 0x00030003 /* a dummy ID for AMP Audio2000 */ -#endif -#define VT1724_SUBDEVICE_AV710 0x12142417 /* AV710 - the same ID with Audio2000! */ - -/* WM8728 on I2C for AV710 */ -#define WM_DEV 0x36 - -#define WM_ATTEN_L 0x00 -#define WM_ATTEN_R 0x01 -#define WM_DAC_CTRL 0x02 -#define WM_INT_CTRL 0x03 - -extern struct snd_ice1712_card_info snd_vt1724_amp_cards[]; - - -#endif /* __SOUND_AMP_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/aureon.c b/ANDROID_3.4.5/sound/pci/ice1712/aureon.c deleted file mode 100644 index 3e4f8c12..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/aureon.c +++ /dev/null @@ -1,2308 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for Terratec Aureon cards - * - * Copyright (c) 2003 Takashi Iwai - * - * 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 - * - * - * NOTES: - * - * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data. - * both wm and akm codecs are pretty similar, so we can integrate - * both controls in the future, once if wm codecs are reused in - * many boards. - * - * - DAC digital volumes are not implemented in the mixer. - * if they show better response than DAC analog volumes, we can use them - * instead. - * - * Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards - * Copyright (c) 2003 Dimitromanolakis Apostolos - * - * version 0.82: Stable / not all features work yet (no communication with AC97 secondary) - * added 64x/128x oversampling switch (should be 64x only for 96khz) - * fixed some recording labels (still need to check the rest) - * recording is working probably thanks to correct wm8770 initialization - * - * version 0.5: Initial release: - * working: analog output, mixer, headphone amplifier switch - * not working: prety much everything else, at least i could verify that - * we have no digital output, no capture, pretty bad clicks and poops - * on mixer switch and other coll stuff. - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "ice1712.h" -#include "envy24ht.h" -#include "aureon.h" -#include - -/* AC97 register cache for Aureon */ -struct aureon_spec { - unsigned short stac9744[64]; - unsigned int cs8415_mux; - unsigned short master[2]; - unsigned short vol[8]; - unsigned char pca9554_out; -}; - -/* WM8770 registers */ -#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ -#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ -#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */ -#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */ -#define WM_PHASE_SWAP 0x12 /* DAC phase */ -#define WM_DAC_CTRL1 0x13 /* DAC control bits */ -#define WM_MUTE 0x14 /* mute controls */ -#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */ -#define WM_INT_CTRL 0x16 /* interface control */ -#define WM_MASTER 0x17 /* master clock and mode */ -#define WM_POWERDOWN 0x18 /* power-down controls */ -#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */ -#define WM_ADC_MUX 0x1b /* input MUX */ -#define WM_OUT_MUX1 0x1c /* output MUX */ -#define WM_OUT_MUX2 0x1e /* output MUX */ -#define WM_RESET 0x1f /* software reset */ - -/* CS8415A registers */ -#define CS8415_CTRL1 0x01 -#define CS8415_CTRL2 0x02 -#define CS8415_QSUB 0x14 -#define CS8415_RATIO 0x1E -#define CS8415_C_BUFFER 0x20 -#define CS8415_ID 0x7F - -/* PCA9554 registers */ -#define PCA9554_DEV 0x40 /* I2C device address */ -#define PCA9554_IN 0x00 /* input port */ -#define PCA9554_OUT 0x01 /* output port */ -#define PCA9554_INVERT 0x02 /* input invert */ -#define PCA9554_DIR 0x03 /* port directions */ - -/* - * Aureon Universe additional controls using PCA9554 - */ - -/* - * Send data to pca9554 - */ -static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg, - unsigned char data) -{ - unsigned int tmp; - int i, j; - unsigned char dev = PCA9554_DEV; /* ID 0100000, write */ - unsigned char val = 0; - - tmp = snd_ice1712_gpio_read(ice); - - snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK| - AUREON_WM_RW|AUREON_WM_CS| - AUREON_CS8415_CS)); - tmp |= AUREON_WM_RW; - tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */ - - tmp &= ~AUREON_SPI_MOSI; - tmp &= ~AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(50); - - /* - * send i2c stop condition and start condition - * to obtain sane state - */ - tmp |= AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(50); - tmp |= AUREON_SPI_MOSI; - snd_ice1712_gpio_write(ice, tmp); - udelay(100); - tmp &= ~AUREON_SPI_MOSI; - snd_ice1712_gpio_write(ice, tmp); - udelay(50); - tmp &= ~AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(100); - /* - * send device address, command and value, - * skipping ack cycles in between - */ - for (j = 0; j < 3; j++) { - switch (j) { - case 0: - val = dev; - break; - case 1: - val = reg; - break; - case 2: - val = data; - break; - } - for (i = 7; i >= 0; i--) { - tmp &= ~AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(40); - if (val & (1 << i)) - tmp |= AUREON_SPI_MOSI; - else - tmp &= ~AUREON_SPI_MOSI; - snd_ice1712_gpio_write(ice, tmp); - udelay(40); - tmp |= AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(40); - } - tmp &= ~AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(40); - tmp |= AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(40); - tmp &= ~AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(40); - } - tmp &= ~AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(40); - tmp &= ~AUREON_SPI_MOSI; - snd_ice1712_gpio_write(ice, tmp); - udelay(40); - tmp |= AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(50); - tmp |= AUREON_SPI_MOSI; - snd_ice1712_gpio_write(ice, tmp); - udelay(100); -} - -static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - ucontrol->value.enumerated.item[0] = spec->pca9554_out; - return 0; -} - -static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - unsigned char oval, nval; - int change; - - nval = ucontrol->value.enumerated.item[0]; - if (nval >= 3) - return -EINVAL; - snd_ice1712_save_gpio_status(ice); - oval = spec->pca9554_out; - change = (oval != nval); - if (change) { - aureon_pca9554_write(ice, PCA9554_OUT, nval); - spec->pca9554_out = nval; - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - - -static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, - unsigned short val) -{ - struct aureon_spec *spec = ice->spec; - unsigned int tmp; - - /* Send address to XILINX chip */ - tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F); - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - tmp |= AUREON_AC97_ADDR; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - tmp &= ~AUREON_AC97_ADDR; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - - /* Send low-order byte to XILINX chip */ - tmp &= ~AUREON_AC97_DATA_MASK; - tmp |= val & AUREON_AC97_DATA_MASK; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - tmp |= AUREON_AC97_DATA_LOW; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - tmp &= ~AUREON_AC97_DATA_LOW; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - - /* Send high-order byte to XILINX chip */ - tmp &= ~AUREON_AC97_DATA_MASK; - tmp |= (val >> 8) & AUREON_AC97_DATA_MASK; - - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - tmp |= AUREON_AC97_DATA_HIGH; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - tmp &= ~AUREON_AC97_DATA_HIGH; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - - /* Instruct XILINX chip to parse the data to the STAC9744 chip */ - tmp |= AUREON_AC97_COMMIT; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - tmp &= ~AUREON_AC97_COMMIT; - snd_ice1712_gpio_write(ice, tmp); - udelay(10); - - /* Store the data in out private buffer */ - spec->stac9744[(reg & 0x7F) >> 1] = val; -} - -static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg) -{ - struct aureon_spec *spec = ice->spec; - return spec->stac9744[(reg & 0x7F) >> 1]; -} - -/* - * Initialize STAC9744 chip - */ -static int aureon_ac97_init(struct snd_ice1712 *ice) -{ - struct aureon_spec *spec = ice->spec; - int i; - static const unsigned short ac97_defaults[] = { - 0x00, 0x9640, - 0x02, 0x8000, - 0x04, 0x8000, - 0x06, 0x8000, - 0x0C, 0x8008, - 0x0E, 0x8008, - 0x10, 0x8808, - 0x12, 0x8808, - 0x14, 0x8808, - 0x16, 0x8808, - 0x18, 0x8808, - 0x1C, 0x8000, - 0x26, 0x000F, - 0x28, 0x0201, - 0x2C, 0xBB80, - 0x32, 0xBB80, - 0x7C, 0x8384, - 0x7E, 0x7644, - (unsigned short)-1 - }; - unsigned int tmp; - - /* Cold reset */ - tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK; - snd_ice1712_gpio_write(ice, tmp); - udelay(3); - - tmp &= ~AUREON_AC97_RESET; - snd_ice1712_gpio_write(ice, tmp); - udelay(3); - - tmp |= AUREON_AC97_RESET; - snd_ice1712_gpio_write(ice, tmp); - udelay(3); - - memset(&spec->stac9744, 0, sizeof(spec->stac9744)); - for (i = 0; ac97_defaults[i] != (unsigned short)-1; i += 2) - spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1]; - - /* Unmute AC'97 master volume permanently - muting is done by WM8770 */ - aureon_ac97_write(ice, AC97_MASTER, 0x0000); - - return 0; -} - -#define AUREON_AC97_STEREO 0x80 - -/* - * AC'97 volume controls - */ -static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 31; - return 0; -} - -static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short vol; - - mutex_lock(&ice->gpio_mutex); - - vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); - ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F); - if (kcontrol->private_value & AUREON_AC97_STEREO) - ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F); - - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int change; - - snd_ice1712_save_gpio_status(ice); - - ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); - nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F; - if (kcontrol->private_value & AUREON_AC97_STEREO) - nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00; - nvol |= ovol & ~0x1F1F; - - change = (ovol != nvol); - if (change) - aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol); - - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * AC'97 mute controls - */ -#define aureon_ac97_mute_info snd_ctl_boolean_mono_info - -static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - - ucontrol->value.integer.value[0] = aureon_ac97_read(ice, - kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1; - - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int change; - - snd_ice1712_save_gpio_status(ice); - - ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F); - nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~0x8000); - - change = (ovol != nvol); - if (change) - aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol); - - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * AC'97 mute controls - */ -#define aureon_ac97_micboost_info snd_ctl_boolean_mono_info - -static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - - ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1; - - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int change; - - snd_ice1712_save_gpio_status(ice); - - ovol = aureon_ac97_read(ice, AC97_MIC); - nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020); - - change = (ovol != nvol); - if (change) - aureon_ac97_write(ice, AC97_MIC, nvol); - - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * write data in the SPI mode - */ -static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits) -{ - unsigned int tmp; - int i; - unsigned int mosi, clk; - - tmp = snd_ice1712_gpio_read(ice); - - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT || - ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) { - snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS)); - mosi = PRODIGY_SPI_MOSI; - clk = PRODIGY_SPI_CLK; - } else { - snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK| - AUREON_WM_CS|AUREON_CS8415_CS)); - mosi = AUREON_SPI_MOSI; - clk = AUREON_SPI_CLK; - - tmp |= AUREON_WM_RW; - } - - tmp &= ~cs; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - for (i = bits - 1; i >= 0; i--) { - tmp &= ~clk; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - if (data & (1 << i)) - tmp |= mosi; - else - tmp &= ~mosi; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= clk; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - - tmp &= ~clk; - tmp |= cs; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= clk; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); -} - -/* - * Read data in SPI mode - */ -static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, - unsigned int data, int bits, unsigned char *buffer, int size) -{ - int i, j; - unsigned int tmp; - - tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS; - snd_ice1712_gpio_write(ice, tmp); - tmp &= ~cs; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - for (i = bits-1; i >= 0; i--) { - if (data & (1 << i)) - tmp |= AUREON_SPI_MOSI; - else - tmp &= ~AUREON_SPI_MOSI; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - tmp |= AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - tmp &= ~AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - - for (j = 0; j < size; j++) { - unsigned char outdata = 0; - for (i = 7; i >= 0; i--) { - tmp = snd_ice1712_gpio_read(ice); - outdata <<= 1; - outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0; - udelay(1); - - tmp |= AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - tmp &= ~AUREON_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - buffer[j] = outdata; - } - - tmp |= cs; - snd_ice1712_gpio_write(ice, tmp); -} - -static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) -{ - unsigned char val; - aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16); - aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1); - return val; -} - -static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, - unsigned char *buffer, int size) -{ - aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16); - aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size); -} - -static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, - unsigned char val) -{ - aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24); -} - -/* - * get the current register value of WM codec - */ -static unsigned short wm_get(struct snd_ice1712 *ice, int reg) -{ - reg <<= 1; - return ((unsigned short)ice->akm[0].images[reg] << 8) | - ice->akm[0].images[reg + 1]; -} - -/* - * set the register value of WM codec - */ -static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - aureon_spi_write(ice, - ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT || - ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ? - PRODIGY_WM_CS : AUREON_WM_CS), - (reg << 9) | (val & 0x1ff), 16); -} - -/* - * set the register value of WM codec and remember it - */ -static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - wm_put_nocache(ice, reg, val); - reg <<= 1; - ice->akm[0].images[reg] = val >> 8; - ice->akm[0].images[reg + 1] = val; -} - -/* - */ -#define aureon_mono_bool_info snd_ctl_boolean_mono_info - -/* - * AC'97 master playback mute controls (Mute on WM8770 chip) - */ -#define aureon_ac97_mmute_info snd_ctl_boolean_mono_info - -static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - - ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01; - - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int change; - - snd_ice1712_save_gpio_status(ice); - - ovol = wm_get(ice, WM_OUT_MUX1); - nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00); - change = (ovol != nvol); - if (change) - wm_put(ice, WM_OUT_MUX1, nvol); - - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -10000, 100, 1); -static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); -static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0); - -#define WM_VOL_MAX 100 -#define WM_VOL_CNT 101 /* 0dB .. -100dB */ -#define WM_VOL_MUTE 0x8000 - -static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master) -{ - unsigned char nvol; - - if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) { - nvol = 0; - } else { - nvol = ((vol % WM_VOL_CNT) * (master % WM_VOL_CNT)) / - WM_VOL_MAX; - nvol += 0x1b; - } - - wm_put(ice, index, nvol); - wm_put_nocache(ice, index, 0x180 | nvol); -} - -/* - * DAC mute control - */ -#define wm_pcm_mute_info snd_ctl_boolean_mono_info - -static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short nval, oval; - int change; - - snd_ice1712_save_gpio_status(ice); - oval = wm_get(ice, WM_MUTE); - nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10); - change = (oval != nval); - if (change) - wm_put(ice, WM_MUTE, nval); - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * Master volume attenuation mixer control - */ -static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = WM_VOL_MAX; - return 0; -} - -static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - int i; - for (i = 0; i < 2; i++) - ucontrol->value.integer.value[i] = - spec->master[i] & ~WM_VOL_MUTE; - return 0; -} - -static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - int ch, change = 0; - - snd_ice1712_save_gpio_status(ice); - for (ch = 0; ch < 2; ch++) { - unsigned int vol = ucontrol->value.integer.value[ch]; - if (vol > WM_VOL_MAX) - vol = WM_VOL_MAX; - vol |= spec->master[ch] & WM_VOL_MUTE; - if (vol != spec->master[ch]) { - int dac; - spec->master[ch] = vol; - for (dac = 0; dac < ice->num_total_dacs; dac += 2) - wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, - spec->vol[dac + ch], - spec->master[ch]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * DAC volume attenuation mixer control - */ -static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int voices = kcontrol->private_value >> 8; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = voices; - uinfo->value.integer.min = 0; /* mute (-101dB) */ - uinfo->value.integer.max = WM_VOL_MAX; /* 0dB */ - return 0; -} - -static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - int i, ofs, voices; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xff; - for (i = 0; i < voices; i++) - ucontrol->value.integer.value[i] = - spec->vol[ofs+i] & ~WM_VOL_MUTE; - return 0; -} - -static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - int i, idx, ofs, voices; - int change = 0; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xff; - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < voices; i++) { - unsigned int vol = ucontrol->value.integer.value[i]; - if (vol > WM_VOL_MAX) - vol = WM_VOL_MAX; - vol |= spec->vol[ofs+i] & WM_VOL_MUTE; - if (vol != spec->vol[ofs+i]) { - spec->vol[ofs+i] = vol; - idx = WM_DAC_ATTEN + ofs + i; - wm_set_vol(ice, idx, spec->vol[ofs + i], - spec->master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * WM8770 mute control - */ -static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = kcontrol->private_value >> 8; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - int voices, ofs, i; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xFF; - - for (i = 0; i < voices; i++) - ucontrol->value.integer.value[i] = - (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; - return 0; -} - -static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - int change = 0, voices, ofs, i; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xFF; - - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < voices; i++) { - int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; - if (ucontrol->value.integer.value[i] != val) { - spec->vol[ofs + i] &= ~WM_VOL_MUTE; - spec->vol[ofs + i] |= - ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; - wm_set_vol(ice, ofs + i, spec->vol[ofs + i], - spec->master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * WM8770 master mute control - */ -#define wm_master_mute_info snd_ctl_boolean_stereo_info - -static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - - ucontrol->value.integer.value[0] = - (spec->master[0] & WM_VOL_MUTE) ? 0 : 1; - ucontrol->value.integer.value[1] = - (spec->master[1] & WM_VOL_MUTE) ? 0 : 1; - return 0; -} - -static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - int change = 0, i; - - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < 2; i++) { - int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1; - if (ucontrol->value.integer.value[i] != val) { - int dac; - spec->master[i] &= ~WM_VOL_MUTE; - spec->master[i] |= - ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; - for (dac = 0; dac < ice->num_total_dacs; dac += 2) - wm_set_vol(ice, WM_DAC_ATTEN + dac + i, - spec->vol[dac + i], - spec->master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* digital master volume */ -#define PCM_0dB 0xff -#define PCM_RES 128 /* -64dB */ -#define PCM_MIN (PCM_0dB - PCM_RES) -static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; /* mute (-64dB) */ - uinfo->value.integer.max = PCM_RES; /* 0dB */ - return 0; -} - -static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val; - - mutex_lock(&ice->gpio_mutex); - val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; - val = val > PCM_MIN ? (val - PCM_MIN) : 0; - ucontrol->value.integer.value[0] = val; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int change = 0; - - nvol = ucontrol->value.integer.value[0]; - if (nvol > PCM_RES) - return -EINVAL; - snd_ice1712_save_gpio_status(ice); - nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; - ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; - if (ovol != nvol) { - wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */ - wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */ - change = 1; - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * ADC mute control - */ -#define wm_adc_mute_info snd_ctl_boolean_stereo_info - -static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val; - int i; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - val = wm_get(ice, WM_ADC_GAIN + i); - ucontrol->value.integer.value[i] = ~val>>5 & 0x1; - } - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short new, old; - int i, change = 0; - - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < 2; i++) { - old = wm_get(ice, WM_ADC_GAIN + i); - new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20); - if (new != old) { - wm_put(ice, WM_ADC_GAIN + i, new); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * ADC gain mixer control - */ -static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* -12dB */ - uinfo->value.integer.max = 0x1f; /* 19dB */ - return 0; -} - -static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int i, idx; - unsigned short vol; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - idx = WM_ADC_GAIN + i; - vol = wm_get(ice, idx) & 0x1f; - ucontrol->value.integer.value[i] = vol; - } - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int i, idx; - unsigned short ovol, nvol; - int change = 0; - - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < 2; i++) { - idx = WM_ADC_GAIN + i; - nvol = ucontrol->value.integer.value[i] & 0x1f; - ovol = wm_get(ice, idx); - if ((ovol & 0x1f) != nvol) { - wm_put(ice, idx, nvol | (ovol & ~0x1f)); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * ADC input mux mixer control - */ -static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "CD", /* AIN1 */ - "Aux", /* AIN2 */ - "Line", /* AIN3 */ - "Mic", /* AIN4 */ - "AC97" /* AIN5 */ - }; - static const char * const universe_texts[] = { - "Aux1", /* AIN1 */ - "CD", /* AIN2 */ - "Phono", /* AIN3 */ - "Line", /* AIN4 */ - "Aux2", /* AIN5 */ - "Mic", /* AIN6 */ - "Aux3", /* AIN7 */ - "AC97" /* AIN8 */ - }; - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) { - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]); - } else { - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - } - return 0; -} - -static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val; - - mutex_lock(&ice->gpio_mutex); - val = wm_get(ice, WM_ADC_MUX); - ucontrol->value.enumerated.item[0] = val & 7; - ucontrol->value.enumerated.item[1] = (val >> 4) & 7; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short oval, nval; - int change; - - snd_ice1712_save_gpio_status(ice); - oval = wm_get(ice, WM_ADC_MUX); - nval = oval & ~0x77; - nval |= ucontrol->value.enumerated.item[0] & 7; - nval |= (ucontrol->value.enumerated.item[1] & 7) << 4; - change = (oval != nval); - if (change) - wm_put(ice, WM_ADC_MUX, nval); - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * CS8415 Input mux - */ -static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - static const char * const aureon_texts[] = { - "CD", /* RXP0 */ - "Optical" /* RXP1 */ - }; - static const char * const prodigy_texts[] = { - "CD", - "Coax" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71) - strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]); - else - strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]); - return 0; -} - -static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - - /* snd_ice1712_save_gpio_status(ice); */ - /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */ - ucontrol->value.enumerated.item[0] = spec->cs8415_mux; - /* snd_ice1712_restore_gpio_status(ice); */ - return 0; -} - -static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct aureon_spec *spec = ice->spec; - unsigned short oval, nval; - int change; - - snd_ice1712_save_gpio_status(ice); - oval = aureon_cs8415_get(ice, CS8415_CTRL2); - nval = oval & ~0x07; - nval |= ucontrol->value.enumerated.item[0] & 7; - change = (oval != nval); - if (change) - aureon_cs8415_put(ice, CS8415_CTRL2, nval); - snd_ice1712_restore_gpio_status(ice); - spec->cs8415_mux = ucontrol->value.enumerated.item[0]; - return change; -} - -static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 192000; - return 0; -} - -static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char ratio; - ratio = aureon_cs8415_get(ice, CS8415_RATIO); - ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750); - return 0; -} - -/* - * CS8415A Mute - */ -#define aureon_cs8415_mute_info snd_ctl_boolean_mono_info - -static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - snd_ice1712_save_gpio_status(ice); - ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1; - snd_ice1712_restore_gpio_status(ice); - return 0; -} - -static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char oval, nval; - int change; - snd_ice1712_save_gpio_status(ice); - oval = aureon_cs8415_get(ice, CS8415_CTRL1); - if (ucontrol->value.integer.value[0]) - nval = oval & ~0x20; - else - nval = oval | 0x20; - change = (oval != nval); - if (change) - aureon_cs8415_put(ice, CS8415_CTRL1, nval); - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * CS8415A Q-Sub info - */ -static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = 10; - return 0; -} - -static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - snd_ice1712_save_gpio_status(ice); - aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10); - snd_ice1712_restore_gpio_status(ice); - - return 0; -} - -static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - memset(ucontrol->value.iec958.status, 0xFF, 24); - return 0; -} - -static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - snd_ice1712_save_gpio_status(ice); - aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24); - snd_ice1712_restore_gpio_status(ice); - return 0; -} - -/* - * Headphone Amplifier - */ -static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable) -{ - unsigned int tmp, tmp2; - - tmp2 = tmp = snd_ice1712_gpio_read(ice); - if (enable) - if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && - ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) - tmp |= AUREON_HP_SEL; - else - tmp |= PRODIGY_HP_SEL; - else - if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && - ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) - tmp &= ~AUREON_HP_SEL; - else - tmp &= ~PRODIGY_HP_SEL; - if (tmp != tmp2) { - snd_ice1712_gpio_write(ice, tmp); - return 1; - } - return 0; -} - -static int aureon_get_headphone_amp(struct snd_ice1712 *ice) -{ - unsigned int tmp = snd_ice1712_gpio_read(ice); - - return (tmp & AUREON_HP_SEL) != 0; -} - -#define aureon_hpamp_info snd_ctl_boolean_mono_info - -static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice); - return 0; -} - - -static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]); -} - -/* - * Deemphasis - */ - -#define aureon_deemp_info snd_ctl_boolean_mono_info - -static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf; - return 0; -} - -static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int temp, temp2; - temp2 = temp = wm_get(ice, WM_DAC_CTRL2); - if (ucontrol->value.integer.value[0]) - temp |= 0xf; - else - temp &= ~0xf; - if (temp != temp2) { - wm_put(ice, WM_DAC_CTRL2, temp); - return 1; - } - return 0; -} - -/* - * ADC Oversampling - */ -static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[2] = { "128x", "64x" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8; - return 0; -} - -static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - int temp, temp2; - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - temp2 = temp = wm_get(ice, WM_MASTER); - - if (ucontrol->value.enumerated.item[0]) - temp |= 0x8; - else - temp &= ~0x8; - - if (temp != temp2) { - wm_put(ice, WM_MASTER, temp); - return 1; - } - return 0; -} - -/* - * mixers - */ - -static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = wm_master_mute_info, - .get = wm_master_mute_get, - .put = wm_master_mute_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Master Playback Volume", - .info = wm_master_vol_info, - .get = wm_master_vol_get, - .put = wm_master_vol_put, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Front Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 0 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Front Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 0, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Rear Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 2 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Rear Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 2, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Center Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (1 << 8) | 4 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Center Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (1 << 8) | 4, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "LFE Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (1 << 8) | 5 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "LFE Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (1 << 8) | 5, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Side Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 6 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Side Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 6, - .tlv = { .p = db_scale_wm_dac } - } -}; - -static struct snd_kcontrol_new wm_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .info = wm_pcm_mute_info, - .get = wm_pcm_mute_get, - .put = wm_pcm_mute_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "PCM Playback Volume", - .info = wm_pcm_vol_info, - .get = wm_pcm_vol_get, - .put = wm_pcm_vol_put, - .tlv = { .p = db_scale_wm_pcm } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Switch", - .info = wm_adc_mute_info, - .get = wm_adc_mute_get, - .put = wm_adc_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Capture Volume", - .info = wm_adc_vol_info, - .get = wm_adc_vol_get, - .put = wm_adc_vol_put, - .tlv = { .p = db_scale_wm_adc } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = wm_adc_mux_info, - .get = wm_adc_mux_get, - .put = wm_adc_mux_put, - .private_value = 5 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "External Amplifier", - .info = aureon_hpamp_info, - .get = aureon_hpamp_get, - .put = aureon_hpamp_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Deemphasis Switch", - .info = aureon_deemp_info, - .get = aureon_deemp_get, - .put = aureon_deemp_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Oversampling", - .info = aureon_oversampling_info, - .get = aureon_oversampling_get, - .put = aureon_oversampling_put - } -}; - -static struct snd_kcontrol_new ac97_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "AC97 Playback Switch", - .info = aureon_ac97_mmute_info, - .get = aureon_ac97_mmute_get, - .put = aureon_ac97_mmute_put, - .private_value = AC97_MASTER - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "AC97 Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_MASTER|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_master } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "CD Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_CD - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "CD Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_CD|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Aux Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_AUX, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Aux Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_AUX|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_LINE - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Line Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_LINE|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_MIC - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Mic Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_MIC, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Boost (+20dB)", - .info = aureon_ac97_micboost_info, - .get = aureon_ac97_micboost_get, - .put = aureon_ac97_micboost_put - } -}; - -static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "AC97 Playback Switch", - .info = aureon_ac97_mmute_info, - .get = aureon_ac97_mmute_get, - .put = aureon_ac97_mmute_put, - .private_value = AC97_MASTER - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "AC97 Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_MASTER|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_master } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "CD Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_AUX - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "CD Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_AUX|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Phono Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_CD - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Phono Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_CD|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_LINE - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Line Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_LINE|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_MIC - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Mic Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_MIC, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Boost (+20dB)", - .info = aureon_ac97_micboost_info, - .get = aureon_ac97_micboost_get, - .put = aureon_ac97_micboost_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Aux Playback Switch", - .info = aureon_ac97_mute_info, - .get = aureon_ac97_mute_get, - .put = aureon_ac97_mute_put, - .private_value = AC97_VIDEO, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Aux Playback Volume", - .info = aureon_ac97_vol_info, - .get = aureon_ac97_vol_get, - .put = aureon_ac97_vol_put, - .private_value = AC97_VIDEO|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Aux Source", - .info = aureon_universe_inmux_info, - .get = aureon_universe_inmux_get, - .put = aureon_universe_inmux_put - } - -}; - -static struct snd_kcontrol_new cs8415_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), - .info = aureon_cs8415_mute_info, - .get = aureon_cs8415_mute_get, - .put = aureon_cs8415_mute_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source", - .info = aureon_cs8415_mux_info, - .get = aureon_cs8415_mux_get, - .put = aureon_cs8415_mux_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT), - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = aureon_cs8415_qsub_info, - .get = aureon_cs8415_qsub_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = aureon_cs8415_spdif_info, - .get = aureon_cs8415_mask_get - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = aureon_cs8415_spdif_info, - .get = aureon_cs8415_spdif_get - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = aureon_cs8415_rate_info, - .get = aureon_cs8415_rate_get - } -}; - -static int __devinit aureon_add_controls(struct snd_ice1712 *ice) -{ - unsigned int i, counts; - int err; - - counts = ARRAY_SIZE(aureon_dac_controls); - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) - counts -= 2; /* no side */ - for (i = 0; i < counts; i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice)); - if (err < 0) - return err; - } - - for (i = 0; i < ARRAY_SIZE(wm_controls); i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice)); - if (err < 0) - return err; - } - - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) { - for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice)); - if (err < 0) - return err; - } - } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && - ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { - for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice)); - if (err < 0) - return err; - } - } - - if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && - ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { - unsigned char id; - snd_ice1712_save_gpio_status(ice); - id = aureon_cs8415_get(ice, CS8415_ID); - if (id != 0x41) - snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n"); - else if ((id & 0x0F) != 0x01) - snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1)); - else { - for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) { - struct snd_kcontrol *kctl; - err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice))); - if (err < 0) - return err; - if (i > 1) - kctl->id.device = ice->pcm->device; - } - } - snd_ice1712_restore_gpio_status(ice); - } - - return 0; -} - -/* - * reset the chip - */ -static int aureon_reset(struct snd_ice1712 *ice) -{ - static const unsigned short wm_inits_aureon[] = { - /* These come first to reduce init pop noise */ - 0x1b, 0x044, /* ADC Mux (AC'97 source) */ - 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ - 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */ - - 0x18, 0x000, /* All power-up */ - - 0x16, 0x122, /* I2S, normal polarity, 24bit */ - 0x17, 0x022, /* 256fs, slave mode */ - 0x00, 0, /* DAC1 analog mute */ - 0x01, 0, /* DAC2 analog mute */ - 0x02, 0, /* DAC3 analog mute */ - 0x03, 0, /* DAC4 analog mute */ - 0x04, 0, /* DAC5 analog mute */ - 0x05, 0, /* DAC6 analog mute */ - 0x06, 0, /* DAC7 analog mute */ - 0x07, 0, /* DAC8 analog mute */ - 0x08, 0x100, /* master analog mute */ - 0x09, 0xff, /* DAC1 digital full */ - 0x0a, 0xff, /* DAC2 digital full */ - 0x0b, 0xff, /* DAC3 digital full */ - 0x0c, 0xff, /* DAC4 digital full */ - 0x0d, 0xff, /* DAC5 digital full */ - 0x0e, 0xff, /* DAC6 digital full */ - 0x0f, 0xff, /* DAC7 digital full */ - 0x10, 0xff, /* DAC8 digital full */ - 0x11, 0x1ff, /* master digital full */ - 0x12, 0x000, /* phase normal */ - 0x13, 0x090, /* unmute DAC L/R */ - 0x14, 0x000, /* all unmute */ - 0x15, 0x000, /* no deemphasis, no ZFLG */ - 0x19, 0x000, /* -12dB ADC/L */ - 0x1a, 0x000, /* -12dB ADC/R */ - (unsigned short)-1 - }; - static const unsigned short wm_inits_prodigy[] = { - - /* These come first to reduce init pop noise */ - 0x1b, 0x000, /* ADC Mux */ - 0x1c, 0x009, /* Out Mux1 */ - 0x1d, 0x009, /* Out Mux2 */ - - 0x18, 0x000, /* All power-up */ - - 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */ - 0x17, 0x006, /* 128fs, slave mode */ - - 0x00, 0, /* DAC1 analog mute */ - 0x01, 0, /* DAC2 analog mute */ - 0x02, 0, /* DAC3 analog mute */ - 0x03, 0, /* DAC4 analog mute */ - 0x04, 0, /* DAC5 analog mute */ - 0x05, 0, /* DAC6 analog mute */ - 0x06, 0, /* DAC7 analog mute */ - 0x07, 0, /* DAC8 analog mute */ - 0x08, 0x100, /* master analog mute */ - - 0x09, 0x7f, /* DAC1 digital full */ - 0x0a, 0x7f, /* DAC2 digital full */ - 0x0b, 0x7f, /* DAC3 digital full */ - 0x0c, 0x7f, /* DAC4 digital full */ - 0x0d, 0x7f, /* DAC5 digital full */ - 0x0e, 0x7f, /* DAC6 digital full */ - 0x0f, 0x7f, /* DAC7 digital full */ - 0x10, 0x7f, /* DAC8 digital full */ - 0x11, 0x1FF, /* master digital full */ - - 0x12, 0x000, /* phase normal */ - 0x13, 0x090, /* unmute DAC L/R */ - 0x14, 0x000, /* all unmute */ - 0x15, 0x000, /* no deemphasis, no ZFLG */ - - 0x19, 0x000, /* -12dB ADC/L */ - 0x1a, 0x000, /* -12dB ADC/R */ - (unsigned short)-1 - - }; - static const unsigned short cs_inits[] = { - 0x0441, /* RUN */ - 0x0180, /* no mute, OMCK output on RMCK pin */ - 0x0201, /* S/PDIF source on RXP1 */ - 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */ - (unsigned short)-1 - }; - unsigned int tmp; - const unsigned short *p; - int err; - struct aureon_spec *spec = ice->spec; - - err = aureon_ac97_init(ice); - if (err != 0) - return err; - - snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */ - - /* reset the wm codec as the SPI mode */ - snd_ice1712_save_gpio_status(ice); - snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL)); - - tmp = snd_ice1712_gpio_read(ice); - tmp &= ~AUREON_WM_RESET; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= AUREON_WM_CS | AUREON_CS8415_CS; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= AUREON_WM_RESET; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - /* initialize WM8770 codec */ - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 || - ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT || - ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) - p = wm_inits_prodigy; - else - p = wm_inits_aureon; - for (; *p != (unsigned short)-1; p += 2) - wm_put(ice, p[0], p[1]); - - /* initialize CS8415A codec */ - if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT && - ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) { - for (p = cs_inits; *p != (unsigned short)-1; p++) - aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); - spec->cs8415_mux = 1; - - aureon_set_headphone_amp(ice, 1); - } - - snd_ice1712_restore_gpio_status(ice); - - /* initialize PCA9554 pin directions & set default input */ - aureon_pca9554_write(ice, PCA9554_DIR, 0x00); - aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */ - return 0; -} - -/* - * suspend/resume - */ -#ifdef CONFIG_PM -static int aureon_resume(struct snd_ice1712 *ice) -{ - struct aureon_spec *spec = ice->spec; - int err, i; - - err = aureon_reset(ice); - if (err != 0) - return err; - - /* workaround for poking volume with alsamixer after resume: - * just set stored volume again */ - for (i = 0; i < ice->num_total_dacs; i++) - wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); - return 0; -} -#endif - -/* - * initialize the chip - */ -static int __devinit aureon_init(struct snd_ice1712 *ice) -{ - struct aureon_spec *spec; - int i, err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { - ice->num_total_dacs = 6; - ice->num_total_adcs = 2; - } else { - /* aureon 7.1 and prodigy 7.1 */ - ice->num_total_dacs = 8; - ice->num_total_adcs = 2; - } - - /* to remember the register values of CS8415 */ - ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (!ice->akm) - return -ENOMEM; - ice->akm_codecs = 1; - - err = aureon_reset(ice); - if (err != 0) - return err; - - spec->master[0] = WM_VOL_MUTE; - spec->master[1] = WM_VOL_MUTE; - for (i = 0; i < ice->num_total_dacs; i++) { - spec->vol[i] = WM_VOL_MUTE; - wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); - } - -#ifdef CONFIG_PM - ice->pm_resume = aureon_resume; - ice->pm_suspend_enabled = 1; -#endif - - return 0; -} - - -/* - * Aureon boards don't provide the EEPROM data except for the vendor IDs. - * hence the driver needs to sets up it properly. - */ - -static unsigned char aureon51_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0x5f, - [ICE_EEP2_GPIO_MASK] = 0x00, - [ICE_EEP2_GPIO_MASK1] = 0x00, - [ICE_EEP2_GPIO_MASK2] = 0x00, - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, -}; - -static unsigned char aureon71_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0x5f, - [ICE_EEP2_GPIO_MASK] = 0x00, - [ICE_EEP2_GPIO_MASK1] = 0x00, - [ICE_EEP2_GPIO_MASK2] = 0x00, - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, -}; -#define prodigy71_eeprom aureon71_eeprom - -static unsigned char aureon71_universe_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC, - * 4DACs - */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0x5f, - [ICE_EEP2_GPIO_MASK] = 0x00, - [ICE_EEP2_GPIO_MASK1] = 0x00, - [ICE_EEP2_GPIO_MASK2] = 0x00, - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, -}; - -static unsigned char prodigy71lt_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0x5f, - [ICE_EEP2_GPIO_MASK] = 0x00, - [ICE_EEP2_GPIO_MASK1] = 0x00, - [ICE_EEP2_GPIO_MASK2] = 0x00, - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, -}; -#define prodigy71xt_eeprom prodigy71lt_eeprom - -/* entry point */ -struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_AUREON51_SKY, - .name = "Terratec Aureon 5.1-Sky", - .model = "aureon51", - .chip_init = aureon_init, - .build_controls = aureon_add_controls, - .eeprom_size = sizeof(aureon51_eeprom), - .eeprom_data = aureon51_eeprom, - .driver = "Aureon51", - }, - { - .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE, - .name = "Terratec Aureon 7.1-Space", - .model = "aureon71", - .chip_init = aureon_init, - .build_controls = aureon_add_controls, - .eeprom_size = sizeof(aureon71_eeprom), - .eeprom_data = aureon71_eeprom, - .driver = "Aureon71", - }, - { - .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE, - .name = "Terratec Aureon 7.1-Universe", - .model = "universe", - .chip_init = aureon_init, - .build_controls = aureon_add_controls, - .eeprom_size = sizeof(aureon71_universe_eeprom), - .eeprom_data = aureon71_universe_eeprom, - .driver = "Aureon71Univ", /* keep in 15 letters */ - }, - { - .subvendor = VT1724_SUBDEVICE_PRODIGY71, - .name = "Audiotrak Prodigy 7.1", - .model = "prodigy71", - .chip_init = aureon_init, - .build_controls = aureon_add_controls, - .eeprom_size = sizeof(prodigy71_eeprom), - .eeprom_data = prodigy71_eeprom, - .driver = "Prodigy71", /* should be identical with Aureon71 */ - }, - { - .subvendor = VT1724_SUBDEVICE_PRODIGY71LT, - .name = "Audiotrak Prodigy 7.1 LT", - .model = "prodigy71lt", - .chip_init = aureon_init, - .build_controls = aureon_add_controls, - .eeprom_size = sizeof(prodigy71lt_eeprom), - .eeprom_data = prodigy71lt_eeprom, - .driver = "Prodigy71LT", - }, - { - .subvendor = VT1724_SUBDEVICE_PRODIGY71XT, - .name = "Audiotrak Prodigy 7.1 XT", - .model = "prodigy71xt", - .chip_init = aureon_init, - .build_controls = aureon_add_controls, - .eeprom_size = sizeof(prodigy71xt_eeprom), - .eeprom_data = prodigy71xt_eeprom, - .driver = "Prodigy71LT", - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/aureon.h b/ANDROID_3.4.5/sound/pci/ice1712/aureon.h deleted file mode 100644 index c253b8e2..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/aureon.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __SOUND_AUREON_H -#define __SOUND_AUREON_H - -/* - * ALSA driver for VIA VT1724 (Envy24HT) - * - * Lowlevel functions for Terratec Aureon cards - * - * Copyright (c) 2003 Takashi Iwai - * - * 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 - * - */ - -#define AUREON_DEVICE_DESC "{Terratec,Aureon 5.1 Sky},"\ - "{Terratec,Aureon 7.1 Space},"\ - "{Terratec,Aureon 7.1 Universe}," \ - "{AudioTrak,Prodigy 7.1}," \ - "{AudioTrak,Prodigy 7.1 LT},"\ - "{AudioTrak,Prodigy 7.1 XT}," - -#define VT1724_SUBDEVICE_AUREON51_SKY 0x3b154711 /* Aureon 5.1 Sky */ -#define VT1724_SUBDEVICE_AUREON71_SPACE 0x3b154511 /* Aureon 7.1 Space */ -#define VT1724_SUBDEVICE_AUREON71_UNIVERSE 0x3b155311 /* Aureon 7.1 Universe */ -#define VT1724_SUBDEVICE_PRODIGY71 0x33495345 /* PRODIGY 7.1 */ -#define VT1724_SUBDEVICE_PRODIGY71LT 0x32315441 /* PRODIGY 7.1 LT */ -#define VT1724_SUBDEVICE_PRODIGY71XT 0x36315441 /* PRODIGY 7.1 XT*/ - -extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; - -/* GPIO bits */ -#define AUREON_CS8415_CS (1 << 22) -#define AUREON_SPI_MISO (1 << 21) -#define AUREON_WM_RESET (1 << 20) -#define AUREON_SPI_CLK (1 << 19) -#define AUREON_SPI_MOSI (1 << 18) -#define AUREON_WM_RW (1 << 17) -#define AUREON_AC97_RESET (1 << 16) -#define AUREON_DIGITAL_SEL1 (1 << 15) -#define AUREON_HP_SEL (1 << 14) -#define AUREON_WM_CS (1 << 12) -#define AUREON_AC97_COMMIT (1 << 11) -#define AUREON_AC97_ADDR (1 << 10) -#define AUREON_AC97_DATA_LOW (1 << 9) -#define AUREON_AC97_DATA_HIGH (1 << 8) -#define AUREON_AC97_DATA_MASK 0xFF - -#define PRODIGY_WM_CS (1 << 8) -#define PRODIGY_SPI_MOSI (1 << 10) -#define PRODIGY_SPI_CLK (1 << 9) -#define PRODIGY_HP_SEL (1 << 5) - -#endif /* __SOUND_AUREON_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/delta.c b/ANDROID_3.4.5/sound/pci/ice1712/delta.c deleted file mode 100644 index 20c6b079..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/delta.c +++ /dev/null @@ -1,881 +0,0 @@ -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for M-Audio Delta 1010, 1010E, 44, 66, 66E, Dio2496, - * Audiophile, Digigram VX442 - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 - -#include "ice1712.h" -#include "delta.h" - -#define SND_CS8403 -#include - - -/* - * CS8427 via SPI mode (for Audiophile), emulated I2C - */ - -/* send 8 bits */ -static void ap_cs8427_write_byte(struct snd_ice1712 *ice, unsigned char data, unsigned char tmp) -{ - int idx; - - for (idx = 7; idx >= 0; idx--) { - tmp &= ~(ICE1712_DELTA_AP_DOUT|ICE1712_DELTA_AP_CCLK); - if (data & (1 << idx)) - tmp |= ICE1712_DELTA_AP_DOUT; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(5); - tmp |= ICE1712_DELTA_AP_CCLK; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(5); - } -} - -/* read 8 bits */ -static unsigned char ap_cs8427_read_byte(struct snd_ice1712 *ice, unsigned char tmp) -{ - unsigned char data = 0; - int idx; - - for (idx = 7; idx >= 0; idx--) { - tmp &= ~ICE1712_DELTA_AP_CCLK; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(5); - if (snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ICE1712_DELTA_AP_DIN) - data |= 1 << idx; - tmp |= ICE1712_DELTA_AP_CCLK; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(5); - } - return data; -} - -/* assert chip select */ -static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice) -{ - unsigned char tmp; - tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_DELTA1010E: - case ICE1712_SUBDEVICE_DELTA1010LT: - tmp &= ~ICE1712_DELTA_1010LT_CS; - tmp |= ICE1712_DELTA_1010LT_CCLK | ICE1712_DELTA_1010LT_CS_CS8427; - break; - case ICE1712_SUBDEVICE_AUDIOPHILE: - case ICE1712_SUBDEVICE_DELTA410: - tmp |= ICE1712_DELTA_AP_CCLK | ICE1712_DELTA_AP_CS_CODEC; - tmp &= ~ICE1712_DELTA_AP_CS_DIGITAL; - break; - case ICE1712_SUBDEVICE_DELTA66E: - tmp |= ICE1712_DELTA_66E_CCLK | ICE1712_DELTA_66E_CS_CHIP_A | - ICE1712_DELTA_66E_CS_CHIP_B; - tmp &= ~ICE1712_DELTA_66E_CS_CS8427; - break; - case ICE1712_SUBDEVICE_VX442: - tmp |= ICE1712_VX442_CCLK | ICE1712_VX442_CODEC_CHIP_A | ICE1712_VX442_CODEC_CHIP_B; - tmp &= ~ICE1712_VX442_CS_DIGITAL; - break; - } - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(5); - return tmp; -} - -/* deassert chip select */ -static void ap_cs8427_codec_deassert(struct snd_ice1712 *ice, unsigned char tmp) -{ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_DELTA1010E: - case ICE1712_SUBDEVICE_DELTA1010LT: - tmp &= ~ICE1712_DELTA_1010LT_CS; - tmp |= ICE1712_DELTA_1010LT_CS_NONE; - break; - case ICE1712_SUBDEVICE_AUDIOPHILE: - case ICE1712_SUBDEVICE_DELTA410: - tmp |= ICE1712_DELTA_AP_CS_DIGITAL; - break; - case ICE1712_SUBDEVICE_DELTA66E: - tmp |= ICE1712_DELTA_66E_CS_CS8427; - break; - case ICE1712_SUBDEVICE_VX442: - tmp |= ICE1712_VX442_CS_DIGITAL; - break; - } - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); -} - -/* sequential write */ -static int ap_cs8427_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) -{ - struct snd_ice1712 *ice = device->bus->private_data; - int res = count; - unsigned char tmp; - - mutex_lock(&ice->gpio_mutex); - tmp = ap_cs8427_codec_select(ice); - ap_cs8427_write_byte(ice, (device->addr << 1) | 0, tmp); /* address + write mode */ - while (count-- > 0) - ap_cs8427_write_byte(ice, *bytes++, tmp); - ap_cs8427_codec_deassert(ice, tmp); - mutex_unlock(&ice->gpio_mutex); - return res; -} - -/* sequential read */ -static int ap_cs8427_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) -{ - struct snd_ice1712 *ice = device->bus->private_data; - int res = count; - unsigned char tmp; - - mutex_lock(&ice->gpio_mutex); - tmp = ap_cs8427_codec_select(ice); - ap_cs8427_write_byte(ice, (device->addr << 1) | 1, tmp); /* address + read mode */ - while (count-- > 0) - *bytes++ = ap_cs8427_read_byte(ice, tmp); - ap_cs8427_codec_deassert(ice, tmp); - mutex_unlock(&ice->gpio_mutex); - return res; -} - -static int ap_cs8427_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) -{ - if (addr == 0x10) - return 1; - return -ENOENT; -} - -static struct snd_i2c_ops ap_cs8427_i2c_ops = { - .sendbytes = ap_cs8427_sendbytes, - .readbytes = ap_cs8427_readbytes, - .probeaddr = ap_cs8427_probeaddr, -}; - -/* - */ - -static void snd_ice1712_delta_cs8403_spdif_write(struct snd_ice1712 *ice, unsigned char bits) -{ - unsigned char tmp, mask1, mask2; - int idx; - /* send byte to transmitter */ - mask1 = ICE1712_DELTA_SPDIF_OUT_STAT_CLOCK; - mask2 = ICE1712_DELTA_SPDIF_OUT_STAT_DATA; - mutex_lock(&ice->gpio_mutex); - tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); - for (idx = 7; idx >= 0; idx--) { - tmp &= ~(mask1 | mask2); - if (bits & (1 << idx)) - tmp |= mask2; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(100); - tmp |= mask1; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(100); - } - tmp &= ~mask1; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - mutex_unlock(&ice->gpio_mutex); -} - - -static void delta_spdif_default_get(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol) -{ - snd_cs8403_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_bits); -} - -static int delta_spdif_default_put(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol) -{ - unsigned int val; - int change; - - val = snd_cs8403_encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - change = ice->spdif.cs8403_bits != val; - ice->spdif.cs8403_bits = val; - if (change && ice->playback_pro_substream == NULL) { - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_delta_cs8403_spdif_write(ice, val); - } else { - spin_unlock_irq(&ice->reg_lock); - } - return change; -} - -static void delta_spdif_stream_get(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol) -{ - snd_cs8403_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_stream_bits); -} - -static int delta_spdif_stream_put(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol) -{ - unsigned int val; - int change; - - val = snd_cs8403_encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - change = ice->spdif.cs8403_stream_bits != val; - ice->spdif.cs8403_stream_bits = val; - if (change && ice->playback_pro_substream != NULL) { - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_delta_cs8403_spdif_write(ice, val); - } else { - spin_unlock_irq(&ice->reg_lock); - } - return change; -} - - -/* - * AK4524 on Delta 44 and 66 to choose the chip mask - */ -static void delta_ak4524_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; - struct snd_ice1712 *ice = ak->private_data[0]; - - snd_ice1712_save_gpio_status(ice); - priv->cs_mask = - priv->cs_addr = chip == 0 ? ICE1712_DELTA_CODEC_CHIP_A : - ICE1712_DELTA_CODEC_CHIP_B; -} - -/* - * AK4524 on Delta1010LT to choose the chip address - */ -static void delta1010lt_ak4524_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; - struct snd_ice1712 *ice = ak->private_data[0]; - - snd_ice1712_save_gpio_status(ice); - priv->cs_mask = ICE1712_DELTA_1010LT_CS; - priv->cs_addr = chip << 4; -} - -/* - * AK4524 on Delta66 rev E to choose the chip address - */ -static void delta66e_ak4524_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; - struct snd_ice1712 *ice = ak->private_data[0]; - - snd_ice1712_save_gpio_status(ice); - priv->cs_mask = - priv->cs_addr = chip == 0 ? ICE1712_DELTA_66E_CS_CHIP_A : - ICE1712_DELTA_66E_CS_CHIP_B; -} - -/* - * AK4528 on VX442 to choose the chip mask - */ -static void vx442_ak4524_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; - struct snd_ice1712 *ice = ak->private_data[0]; - - snd_ice1712_save_gpio_status(ice); - priv->cs_mask = - priv->cs_addr = chip == 0 ? ICE1712_VX442_CODEC_CHIP_A : - ICE1712_VX442_CODEC_CHIP_B; -} - -/* - * change the DFS bit according rate for Delta1010 - */ -static void delta_1010_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) -{ - unsigned char tmp, tmp2; - - if (rate == 0) /* no hint - S/PDIF input is master, simply return */ - return; - - mutex_lock(&ice->gpio_mutex); - tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); - tmp2 = tmp & ~ICE1712_DELTA_DFS; - if (rate > 48000) - tmp2 |= ICE1712_DELTA_DFS; - if (tmp != tmp2) - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp2); - mutex_unlock(&ice->gpio_mutex); -} - -/* - * change the rate of AK4524 on Delta 44/66, AP, 1010LT - */ -static void delta_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) -{ - unsigned char tmp, tmp2; - struct snd_ice1712 *ice = ak->private_data[0]; - - if (rate == 0) /* no hint - S/PDIF input is master, simply return */ - return; - - /* check before reset ak4524 to avoid unnecessary clicks */ - mutex_lock(&ice->gpio_mutex); - tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); - mutex_unlock(&ice->gpio_mutex); - tmp2 = tmp & ~ICE1712_DELTA_DFS; - if (rate > 48000) - tmp2 |= ICE1712_DELTA_DFS; - if (tmp == tmp2) - return; - - /* do it again */ - snd_akm4xxx_reset(ak, 1); - mutex_lock(&ice->gpio_mutex); - tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ~ICE1712_DELTA_DFS; - if (rate > 48000) - tmp |= ICE1712_DELTA_DFS; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - mutex_unlock(&ice->gpio_mutex); - snd_akm4xxx_reset(ak, 0); -} - -/* - * change the rate of AK4524 on VX442 - */ -static void vx442_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) -{ - unsigned char val; - - val = (rate > 48000) ? 0x65 : 0x60; - if (snd_akm4xxx_get(ak, 0, 0x02) != val || - snd_akm4xxx_get(ak, 1, 0x02) != val) { - snd_akm4xxx_reset(ak, 1); - snd_akm4xxx_write(ak, 0, 0x02, val); - snd_akm4xxx_write(ak, 1, 0x02, val); - snd_akm4xxx_reset(ak, 0); - } -} - - -/* - * SPDIF ops for Delta 1010, Dio, 66 - */ - -/* open callback */ -static void delta_open_spdif(struct snd_ice1712 *ice, struct snd_pcm_substream *substream) -{ - ice->spdif.cs8403_stream_bits = ice->spdif.cs8403_bits; -} - -/* set up */ -static void delta_setup_spdif(struct snd_ice1712 *ice, int rate) -{ - unsigned long flags; - unsigned int tmp; - int change; - - spin_lock_irqsave(&ice->reg_lock, flags); - tmp = ice->spdif.cs8403_stream_bits; - if (tmp & 0x01) /* consumer */ - tmp &= (tmp & 0x01) ? ~0x06 : ~0x18; - switch (rate) { - case 32000: tmp |= (tmp & 0x01) ? 0x04 : 0x00; break; - case 44100: tmp |= (tmp & 0x01) ? 0x00 : 0x10; break; - case 48000: tmp |= (tmp & 0x01) ? 0x02 : 0x08; break; - default: tmp |= (tmp & 0x01) ? 0x00 : 0x18; break; - } - change = ice->spdif.cs8403_stream_bits != tmp; - ice->spdif.cs8403_stream_bits = tmp; - spin_unlock_irqrestore(&ice->reg_lock, flags); - if (change) - snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &ice->spdif.stream_ctl->id); - snd_ice1712_delta_cs8403_spdif_write(ice, tmp); -} - -#define snd_ice1712_delta1010lt_wordclock_status_info \ - snd_ctl_boolean_mono_info - -static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - char reg = 0x10; /* CS8427 receiver error register */ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - if (snd_i2c_sendbytes(ice->cs8427, ®, 1) != 1) - snd_printk(KERN_ERR "unable to send register 0x%x byte to CS8427\n", reg); - snd_i2c_readbytes(ice->cs8427, ®, 1); - ucontrol->value.integer.value[0] = (reg & CS8427_UNLOCK) ? 1 : 0; - return 0; -} - -static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata = -{ - .access = (SNDRV_CTL_ELEM_ACCESS_READ), - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Word Clock Status", - .info = snd_ice1712_delta1010lt_wordclock_status_info, - .get = snd_ice1712_delta1010lt_wordclock_status_get, -}; - -/* - * initialize the chips on M-Audio cards - */ - -static struct snd_akm4xxx akm_audiophile __devinitdata = { - .type = SND_AK4528, - .num_adcs = 2, - .num_dacs = 2, - .ops = { - .set_rate_val = delta_ak4524_set_rate_val - } -}; - -static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = { - .caddr = 2, - .cif = 0, - .data_mask = ICE1712_DELTA_AP_DOUT, - .clk_mask = ICE1712_DELTA_AP_CCLK, - .cs_mask = ICE1712_DELTA_AP_CS_CODEC, - .cs_addr = ICE1712_DELTA_AP_CS_CODEC, - .cs_none = 0, - .add_flags = ICE1712_DELTA_AP_CS_DIGITAL, - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_delta410 __devinitdata = { - .type = SND_AK4529, - .num_adcs = 2, - .num_dacs = 8, - .ops = { - .set_rate_val = delta_ak4524_set_rate_val - } -}; - -static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = { - .caddr = 0, - .cif = 0, - .data_mask = ICE1712_DELTA_AP_DOUT, - .clk_mask = ICE1712_DELTA_AP_CCLK, - .cs_mask = ICE1712_DELTA_AP_CS_CODEC, - .cs_addr = ICE1712_DELTA_AP_CS_CODEC, - .cs_none = 0, - .add_flags = ICE1712_DELTA_AP_CS_DIGITAL, - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_delta1010lt __devinitdata = { - .type = SND_AK4524, - .num_adcs = 8, - .num_dacs = 8, - .ops = { - .lock = delta1010lt_ak4524_lock, - .set_rate_val = delta_ak4524_set_rate_val - } -}; - -static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = { - .caddr = 2, - .cif = 0, /* the default level of the CIF pin from AK4524 */ - .data_mask = ICE1712_DELTA_1010LT_DOUT, - .clk_mask = ICE1712_DELTA_1010LT_CCLK, - .cs_mask = 0, - .cs_addr = 0, /* set later */ - .cs_none = ICE1712_DELTA_1010LT_CS_NONE, - .add_flags = 0, - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_delta66e __devinitdata = { - .type = SND_AK4524, - .num_adcs = 4, - .num_dacs = 4, - .ops = { - .lock = delta66e_ak4524_lock, - .set_rate_val = delta_ak4524_set_rate_val - } -}; - -static struct snd_ak4xxx_private akm_delta66e_priv __devinitdata = { - .caddr = 2, - .cif = 0, /* the default level of the CIF pin from AK4524 */ - .data_mask = ICE1712_DELTA_66E_DOUT, - .clk_mask = ICE1712_DELTA_66E_CCLK, - .cs_mask = 0, - .cs_addr = 0, /* set later */ - .cs_none = 0, - .add_flags = 0, - .mask_flags = 0, -}; - - -static struct snd_akm4xxx akm_delta44 __devinitdata = { - .type = SND_AK4524, - .num_adcs = 4, - .num_dacs = 4, - .ops = { - .lock = delta_ak4524_lock, - .set_rate_val = delta_ak4524_set_rate_val - } -}; - -static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = { - .caddr = 2, - .cif = 0, /* the default level of the CIF pin from AK4524 */ - .data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA, - .clk_mask = ICE1712_DELTA_CODEC_SERIAL_CLOCK, - .cs_mask = 0, - .cs_addr = 0, /* set later */ - .cs_none = 0, - .add_flags = 0, - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_vx442 __devinitdata = { - .type = SND_AK4524, - .num_adcs = 4, - .num_dacs = 4, - .ops = { - .lock = vx442_ak4524_lock, - .set_rate_val = vx442_ak4524_set_rate_val - } -}; - -static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = { - .caddr = 2, - .cif = 0, - .data_mask = ICE1712_VX442_DOUT, - .clk_mask = ICE1712_VX442_CCLK, - .cs_mask = 0, - .cs_addr = 0, /* set later */ - .cs_none = 0, - .add_flags = 0, - .mask_flags = 0, -}; - -static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice) -{ - int err; - struct snd_akm4xxx *ak; - unsigned char tmp; - - if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010 && - ice->eeprom.gpiodir == 0x7b) - ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA1010E; - - if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA66 && - ice->eeprom.gpiodir == 0xfb) - ice->eeprom.subvendor = ICE1712_SUBDEVICE_DELTA66E; - - /* determine I2C, DACs and ADCs */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_AUDIOPHILE: - ice->num_total_dacs = 2; - ice->num_total_adcs = 2; - break; - case ICE1712_SUBDEVICE_DELTA410: - ice->num_total_dacs = 8; - ice->num_total_adcs = 2; - break; - case ICE1712_SUBDEVICE_DELTA44: - case ICE1712_SUBDEVICE_DELTA66: - ice->num_total_dacs = ice->omni ? 8 : 4; - ice->num_total_adcs = ice->omni ? 8 : 4; - break; - case ICE1712_SUBDEVICE_DELTA1010: - case ICE1712_SUBDEVICE_DELTA1010E: - case ICE1712_SUBDEVICE_DELTA1010LT: - case ICE1712_SUBDEVICE_MEDIASTATION: - case ICE1712_SUBDEVICE_EDIROLDA2496: - ice->num_total_dacs = 8; - ice->num_total_adcs = 8; - break; - case ICE1712_SUBDEVICE_DELTADIO2496: - ice->num_total_dacs = 4; /* two AK4324 codecs */ - break; - case ICE1712_SUBDEVICE_VX442: - case ICE1712_SUBDEVICE_DELTA66E: /* omni not suported yet */ - ice->num_total_dacs = 4; - ice->num_total_adcs = 4; - break; - } - - /* initialize the SPI clock to high */ - tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); - tmp |= ICE1712_DELTA_AP_CCLK; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(5); - - /* initialize spdif */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_AUDIOPHILE: - case ICE1712_SUBDEVICE_DELTA410: - case ICE1712_SUBDEVICE_DELTA1010E: - case ICE1712_SUBDEVICE_DELTA1010LT: - case ICE1712_SUBDEVICE_VX442: - case ICE1712_SUBDEVICE_DELTA66E: - if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { - snd_printk(KERN_ERR "unable to create I2C bus\n"); - return err; - } - ice->i2c->private_data = ice; - ice->i2c->ops = &ap_cs8427_i2c_ops; - if ((err = snd_ice1712_init_cs8427(ice, CS8427_BASE_ADDR)) < 0) - return err; - break; - case ICE1712_SUBDEVICE_DELTA1010: - case ICE1712_SUBDEVICE_MEDIASTATION: - ice->gpio.set_pro_rate = delta_1010_set_rate_val; - break; - case ICE1712_SUBDEVICE_DELTADIO2496: - ice->gpio.set_pro_rate = delta_1010_set_rate_val; - /* fall thru */ - case ICE1712_SUBDEVICE_DELTA66: - ice->spdif.ops.open = delta_open_spdif; - ice->spdif.ops.setup_rate = delta_setup_spdif; - ice->spdif.ops.default_get = delta_spdif_default_get; - ice->spdif.ops.default_put = delta_spdif_default_put; - ice->spdif.ops.stream_get = delta_spdif_stream_get; - ice->spdif.ops.stream_put = delta_spdif_stream_put; - /* Set spdif defaults */ - snd_ice1712_delta_cs8403_spdif_write(ice, ice->spdif.cs8403_bits); - break; - } - - /* no analog? */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_DELTA1010: - case ICE1712_SUBDEVICE_DELTA1010E: - case ICE1712_SUBDEVICE_DELTADIO2496: - case ICE1712_SUBDEVICE_MEDIASTATION: - return 0; - } - - /* second stage of initialization, analog parts and others */ - ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (! ak) - return -ENOMEM; - ice->akm_codecs = 1; - - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_AUDIOPHILE: - err = snd_ice1712_akm4xxx_init(ak, &akm_audiophile, &akm_audiophile_priv, ice); - break; - case ICE1712_SUBDEVICE_DELTA410: - err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice); - break; - case ICE1712_SUBDEVICE_DELTA1010LT: - case ICE1712_SUBDEVICE_EDIROLDA2496: - err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice); - break; - case ICE1712_SUBDEVICE_DELTA66: - case ICE1712_SUBDEVICE_DELTA44: - err = snd_ice1712_akm4xxx_init(ak, &akm_delta44, &akm_delta44_priv, ice); - break; - case ICE1712_SUBDEVICE_VX442: - err = snd_ice1712_akm4xxx_init(ak, &akm_vx442, &akm_vx442_priv, ice); - break; - case ICE1712_SUBDEVICE_DELTA66E: - err = snd_ice1712_akm4xxx_init(ak, &akm_delta66e, &akm_delta66e_priv, ice); - break; - default: - snd_BUG(); - return -EINVAL; - } - - return err; -} - - -/* - * additional controls for M-Audio cards - */ - -static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata = -ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0); -static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata = -ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0); -static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata = -ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE); -static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata = -ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0); -static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata = -ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE); - - -static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice) -{ - int err; - - /* 1010 and dio specific controls */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_DELTA1010: - case ICE1712_SUBDEVICE_MEDIASTATION: - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010_wordclock_select, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010_wordclock_status, ice)); - if (err < 0) - return err; - break; - case ICE1712_SUBDEVICE_DELTADIO2496: - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_deltadio2496_spdif_in_select, ice)); - if (err < 0) - return err; - break; - case ICE1712_SUBDEVICE_DELTA1010E: - case ICE1712_SUBDEVICE_DELTA1010LT: - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_select, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_status, ice)); - if (err < 0) - return err; - break; - } - - /* normal spdif controls */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_DELTA1010: - case ICE1712_SUBDEVICE_DELTADIO2496: - case ICE1712_SUBDEVICE_DELTA66: - case ICE1712_SUBDEVICE_MEDIASTATION: - err = snd_ice1712_spdif_build_controls(ice); - if (err < 0) - return err; - break; - } - - /* spdif status in */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_DELTA1010: - case ICE1712_SUBDEVICE_DELTADIO2496: - case ICE1712_SUBDEVICE_DELTA66: - case ICE1712_SUBDEVICE_MEDIASTATION: - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta_spdif_in_status, ice)); - if (err < 0) - return err; - break; - } - - /* ak4524 controls */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_DELTA1010LT: - case ICE1712_SUBDEVICE_AUDIOPHILE: - case ICE1712_SUBDEVICE_DELTA410: - case ICE1712_SUBDEVICE_DELTA44: - case ICE1712_SUBDEVICE_DELTA66: - case ICE1712_SUBDEVICE_VX442: - case ICE1712_SUBDEVICE_DELTA66E: - case ICE1712_SUBDEVICE_EDIROLDA2496: - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - break; - } - - return 0; -} - - -/* entry point */ -struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = { - { - .subvendor = ICE1712_SUBDEVICE_DELTA1010, - .name = "M Audio Delta 1010", - .model = "delta1010", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_DELTADIO2496, - .name = "M Audio Delta DiO 2496", - .model = "dio2496", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - .no_mpu401 = 1, - }, - { - .subvendor = ICE1712_SUBDEVICE_DELTA66, - .name = "M Audio Delta 66", - .model = "delta66", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - .no_mpu401 = 1, - }, - { - .subvendor = ICE1712_SUBDEVICE_DELTA44, - .name = "M Audio Delta 44", - .model = "delta44", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - .no_mpu401 = 1, - }, - { - .subvendor = ICE1712_SUBDEVICE_AUDIOPHILE, - .name = "M Audio Audiophile 24/96", - .model = "audiophile", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_DELTA410, - .name = "M Audio Delta 410", - .model = "delta410", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_DELTA1010LT, - .name = "M Audio Delta 1010LT", - .model = "delta1010lt", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_VX442, - .name = "Digigram VX442", - .model = "vx442", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - .no_mpu401 = 1, - }, - { - .subvendor = ICE1712_SUBDEVICE_MEDIASTATION, - .name = "Lionstracs Mediastation", - .model = "mediastation", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_EDIROLDA2496, - .name = "Edirol DA2496", - .model = "da2496", - .chip_init = snd_ice1712_delta_init, - .build_controls = snd_ice1712_delta_add_controls, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/delta.h b/ANDROID_3.4.5/sound/pci/ice1712/delta.h deleted file mode 100644 index 11a9c3a7..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/delta.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef __SOUND_DELTA_H -#define __SOUND_DELTA_H - -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for M-Audio Delta 1010, 44, 66, Dio2496, Audiophile - * Digigram VX442 - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 - * - */ - -#define DELTA_DEVICE_DESC \ - "{MidiMan M Audio,Delta 1010},"\ - "{MidiMan M Audio,Delta 1010LT},"\ - "{MidiMan M Audio,Delta DiO 2496},"\ - "{MidiMan M Audio,Delta 66},"\ - "{MidiMan M Audio,Delta 44},"\ - "{MidiMan M Audio,Delta 410},"\ - "{MidiMan M Audio,Audiophile 24/96},"\ - "{Digigram,VX442},"\ - "{Lionstracs,Mediastation},"\ - "{Edirol,DA2496}," - -#define ICE1712_SUBDEVICE_DELTA1010 0x121430d6 -#define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6 -#define ICE1712_SUBDEVICE_DELTADIO2496 0x121431d6 -#define ICE1712_SUBDEVICE_DELTA66 0x121432d6 -#define ICE1712_SUBDEVICE_DELTA66E 0xff1432d6 -#define ICE1712_SUBDEVICE_DELTA44 0x121433d6 -#define ICE1712_SUBDEVICE_AUDIOPHILE 0x121434d6 -#define ICE1712_SUBDEVICE_DELTA410 0x121438d6 -#define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6 -#define ICE1712_SUBDEVICE_VX442 0x12143cd6 -#define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100 -#define ICE1712_SUBDEVICE_EDIROLDA2496 0xce164010 - -/* entry point */ -extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; - - -/* - * MidiMan M-Audio Delta GPIO definitions - */ - -/* MidiMan M-Audio Delta shared pins */ -#define ICE1712_DELTA_DFS 0x01 /* fast/slow sample rate mode */ - /* (>48kHz must be 1) */ -#define ICE1712_DELTA_SPDIF_IN_STAT 0x02 - /* S/PDIF input status */ - /* 0 = valid signal is present */ - /* all except Delta44 */ - /* look to CS8414 datasheet */ -#define ICE1712_DELTA_SPDIF_OUT_STAT_CLOCK 0x04 - /* S/PDIF output status clock */ - /* (writing on rising edge - 0->1) */ - /* all except Delta44 */ - /* look to CS8404A datasheet */ -#define ICE1712_DELTA_SPDIF_OUT_STAT_DATA 0x08 - /* S/PDIF output status data */ - /* all except Delta44 */ - /* look to CS8404A datasheet */ -/* MidiMan M-Audio DeltaDiO */ -/* 0x01 = DFS */ -/* 0x02 = SPDIF_IN_STAT */ -/* 0x04 = SPDIF_OUT_STAT_CLOCK */ -/* 0x08 = SPDIF_OUT_STAT_DATA */ -#define ICE1712_DELTA_SPDIF_INPUT_SELECT 0x10 - /* coaxial (0), optical (1) */ - /* S/PDIF input select*/ - -/* MidiMan M-Audio Delta1010 */ -/* 0x01 = DFS */ -/* 0x02 = SPDIF_IN_STAT */ -/* 0x04 = SPDIF_OUT_STAT_CLOCK */ -/* 0x08 = SPDIF_OUT_STAT_DATA */ -#define ICE1712_DELTA_WORD_CLOCK_SELECT 0x10 - /* 1 - clock are taken from S/PDIF input */ - /* 0 - clock are taken from Word Clock input */ - /* affected SPMCLKIN pin of Envy24 */ -#define ICE1712_DELTA_WORD_CLOCK_STATUS 0x20 - /* 0 = valid word clock signal is present */ - -/* MidiMan M-Audio Delta66 */ -/* 0x01 = DFS */ -/* 0x02 = SPDIF_IN_STAT */ -/* 0x04 = SPDIF_OUT_STAT_CLOCK */ -/* 0x08 = SPDIF_OUT_STAT_DATA */ -#define ICE1712_DELTA_CODEC_SERIAL_DATA 0x10 - /* AKM4524 serial data */ -#define ICE1712_DELTA_CODEC_SERIAL_CLOCK 0x20 - /* AKM4524 serial clock */ - /* (writing on rising edge - 0->1 */ -#define ICE1712_DELTA_CODEC_CHIP_A 0x40 -#define ICE1712_DELTA_CODEC_CHIP_B 0x80 - /* 1 - select chip A or B */ - -/* MidiMan M-Audio Delta44 */ -/* 0x01 = DFS */ -/* 0x10 = CODEC_SERIAL_DATA */ -/* 0x20 = CODEC_SERIAL_CLOCK */ -/* 0x40 = CODEC_CHIP_A */ -/* 0x80 = CODEC_CHIP_B */ - -/* MidiMan M-Audio Audiophile/Delta410 definitions */ -/* thanks to Kristof Pelckmans for Delta410 info */ -/* 0x01 = DFS */ -#define ICE1712_DELTA_AP_CCLK 0x02 /* SPI clock */ - /* (clocking on rising edge - 0->1) */ -#define ICE1712_DELTA_AP_DIN 0x04 /* data input */ -#define ICE1712_DELTA_AP_DOUT 0x08 /* data output */ -#define ICE1712_DELTA_AP_CS_DIGITAL 0x10 /* CS8427 chip select */ - /* low signal = select */ -#define ICE1712_DELTA_AP_CS_CODEC 0x20 /* AK4528 (audiophile), AK4529 (Delta410) chip select */ - /* low signal = select */ - -/* MidiMan M-Audio Delta1010LT definitions */ -/* thanks to Anders Johansson */ -/* 0x01 = DFS */ -#define ICE1712_DELTA_1010LT_CCLK 0x02 /* SPI clock (AK4524 + CS8427) */ -#define ICE1712_DELTA_1010LT_DIN 0x04 /* data input (CS8427) */ -#define ICE1712_DELTA_1010LT_DOUT 0x08 /* data output (AK4524 + CS8427) */ -#define ICE1712_DELTA_1010LT_CS 0x70 /* mask for CS address */ -#define ICE1712_DELTA_1010LT_CS_CHIP_A 0x00 /* AK4524 #0 */ -#define ICE1712_DELTA_1010LT_CS_CHIP_B 0x10 /* AK4524 #1 */ -#define ICE1712_DELTA_1010LT_CS_CHIP_C 0x20 /* AK4524 #2 */ -#define ICE1712_DELTA_1010LT_CS_CHIP_D 0x30 /* AK4524 #3 */ -#define ICE1712_DELTA_1010LT_CS_CS8427 0x40 /* CS8427 */ -#define ICE1712_DELTA_1010LT_CS_NONE 0x50 /* nothing */ -#define ICE1712_DELTA_1010LT_WORDCLOCK 0x80 /* sample clock source: 0 = Word Clock Input, 1 = S/PDIF Input ??? */ - -/* M-Audio Delta 66 rev. E definitions. - * Newer revisions of Delta 66 have CS8427 over SPI for - * S/PDIF transceiver instead of CS8404/CS8414. */ -/* 0x01 = DFS */ -#define ICE1712_DELTA_66E_CCLK 0x02 /* SPI clock */ -#define ICE1712_DELTA_66E_DIN 0x04 /* data input */ -#define ICE1712_DELTA_66E_DOUT 0x08 /* data output */ -#define ICE1712_DELTA_66E_CS_CS8427 0x10 /* chip select, low = CS8427 */ -#define ICE1712_DELTA_66E_CS_CHIP_A 0x20 /* AK4524 #0 */ -#define ICE1712_DELTA_66E_CS_CHIP_B 0x40 /* AK4524 #1 */ - -/* Digigram VX442 definitions */ -#define ICE1712_VX442_CCLK 0x02 /* SPI clock */ -#define ICE1712_VX442_DIN 0x04 /* data input */ -#define ICE1712_VX442_DOUT 0x08 /* data output */ -#define ICE1712_VX442_CS_DIGITAL 0x10 /* chip select, low = CS8427 */ -#define ICE1712_VX442_CODEC_CHIP_A 0x20 /* select chip A */ -#define ICE1712_VX442_CODEC_CHIP_B 0x40 /* select chip B */ - -#endif /* __SOUND_DELTA_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/envy24ht.h b/ANDROID_3.4.5/sound/pci/ice1712/envy24ht.h deleted file mode 100644 index 4ca33a80..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/envy24ht.h +++ /dev/null @@ -1,220 +0,0 @@ -#ifndef __SOUND_VT1724_H -#define __SOUND_VT1724_H - -/* - * ALSA driver for ICEnsemble VT1724 (Envy24) - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 "ice1712.h" - -enum { - ICE_EEP2_SYSCONF = 0, /* 06 */ - ICE_EEP2_ACLINK, /* 07 */ - ICE_EEP2_I2S, /* 08 */ - ICE_EEP2_SPDIF, /* 09 */ - ICE_EEP2_GPIO_DIR, /* 0a */ - ICE_EEP2_GPIO_DIR1, /* 0b */ - ICE_EEP2_GPIO_DIR2, /* 0c */ - ICE_EEP2_GPIO_MASK, /* 0d */ - ICE_EEP2_GPIO_MASK1, /* 0e */ - ICE_EEP2_GPIO_MASK2, /* 0f */ - ICE_EEP2_GPIO_STATE, /* 10 */ - ICE_EEP2_GPIO_STATE1, /* 11 */ - ICE_EEP2_GPIO_STATE2 /* 12 */ -}; - -/* - * Direct registers - */ - -#define ICEREG1724(ice, x) ((ice)->port + VT1724_REG_##x) - -#define VT1724_REG_CONTROL 0x00 /* byte */ -#define VT1724_RESET 0x80 /* reset whole chip */ -#define VT1724_REG_IRQMASK 0x01 /* byte */ -#define VT1724_IRQ_MPU_RX 0x80 -#define VT1724_IRQ_MPU_TX 0x20 -#define VT1724_IRQ_MTPCM 0x10 -#define VT1724_REG_IRQSTAT 0x02 /* byte */ -/* look to VT1724_IRQ_* */ -#define VT1724_REG_SYS_CFG 0x04 /* byte - system configuration PCI60 on Envy24*/ -#define VT1724_CFG_CLOCK 0xc0 -#define VT1724_CFG_CLOCK512 0x00 /* 22.5692Mhz, 44.1kHz*512 */ -#define VT1724_CFG_CLOCK384 0x40 /* 16.9344Mhz, 44.1kHz*384 */ -#define VT1724_CFG_MPU401 0x20 /* MPU401 UARTs */ -#define VT1724_CFG_ADC_MASK 0x0c /* one, two or one and S/PDIF, stereo ADCs */ -#define VT1724_CFG_ADC_NONE 0x0c /* no ADCs */ -#define VT1724_CFG_DAC_MASK 0x03 /* one, two, three, four stereo DACs */ - -#define VT1724_REG_AC97_CFG 0x05 /* byte */ -#define VT1724_CFG_PRO_I2S 0x80 /* multitrack converter: I2S or AC'97 */ -#define VT1724_CFG_AC97_PACKED 0x01 /* split or packed mode - AC'97 */ - -#define VT1724_REG_I2S_FEATURES 0x06 /* byte */ -#define VT1724_CFG_I2S_VOLUME 0x80 /* volume/mute capability */ -#define VT1724_CFG_I2S_96KHZ 0x40 /* supports 96kHz sampling */ -#define VT1724_CFG_I2S_RESMASK 0x30 /* resolution mask, 16,18,20,24-bit */ -#define VT1724_CFG_I2S_192KHZ 0x08 /* supports 192kHz sampling */ -#define VT1724_CFG_I2S_OTHER 0x07 /* other I2S IDs */ - -#define VT1724_REG_SPDIF_CFG 0x07 /* byte */ -#define VT1724_CFG_SPDIF_OUT_EN 0x80 /*Internal S/PDIF output is enabled*/ -#define VT1724_CFG_SPDIF_OUT_INT 0x40 /*Internal S/PDIF output is implemented*/ -#define VT1724_CFG_I2S_CHIPID 0x3c /* I2S chip ID */ -#define VT1724_CFG_SPDIF_IN 0x02 /* S/PDIF input is present */ -#define VT1724_CFG_SPDIF_OUT 0x01 /* External S/PDIF output is present */ - -/*there is no consumer AC97 codec with the VT1724*/ -//#define VT1724_REG_AC97_INDEX 0x08 /* byte */ -//#define VT1724_REG_AC97_CMD 0x09 /* byte */ - -#define VT1724_REG_MPU_TXFIFO 0x0a /*byte ro. number of bytes in TX fifo*/ -#define VT1724_REG_MPU_RXFIFO 0x0b /*byte ro. number of bytes in RX fifo*/ - -#define VT1724_REG_MPU_DATA 0x0c /* byte */ -#define VT1724_REG_MPU_CTRL 0x0d /* byte */ -#define VT1724_MPU_UART 0x01 -#define VT1724_MPU_TX_EMPTY 0x02 -#define VT1724_MPU_TX_FULL 0x04 -#define VT1724_MPU_RX_EMPTY 0x08 -#define VT1724_MPU_RX_FULL 0x10 - -#define VT1724_REG_MPU_FIFO_WM 0x0e /*byte set the high/low watermarks for RX/TX fifos*/ -#define VT1724_MPU_RX_FIFO 0x20 //1=rx fifo watermark 0=tx fifo watermark -#define VT1724_MPU_FIFO_MASK 0x1f - -#define VT1724_REG_I2C_DEV_ADDR 0x10 /* byte */ -#define VT1724_I2C_WRITE 0x01 /* write direction */ -#define VT1724_REG_I2C_BYTE_ADDR 0x11 /* byte */ -#define VT1724_REG_I2C_DATA 0x12 /* byte */ -#define VT1724_REG_I2C_CTRL 0x13 /* byte */ -#define VT1724_I2C_EEPROM 0x80 /* 1 = EEPROM exists */ -#define VT1724_I2C_BUSY 0x01 /* busy bit */ - -#define VT1724_REG_GPIO_DATA 0x14 /* word */ -#define VT1724_REG_GPIO_WRITE_MASK 0x16 /* word */ -#define VT1724_REG_GPIO_DIRECTION 0x18 /* dword? (3 bytes) 0=input 1=output. - bit3 - during reset used for Eeprom power-on strapping - if TESTEN# pin active, bit 2 always input*/ -#define VT1724_REG_POWERDOWN 0x1c -#define VT1724_REG_GPIO_DATA_22 0x1e /* byte direction for GPIO 16:22 */ -#define VT1724_REG_GPIO_WRITE_MASK_22 0x1f /* byte write mask for GPIO 16:22 */ - - -/* - * Professional multi-track direct control registers - */ - -#define ICEMT1724(ice, x) ((ice)->profi_port + VT1724_MT_##x) - -#define VT1724_MT_IRQ 0x00 /* byte - interrupt mask */ -#define VT1724_MULTI_PDMA4 0x80 /* SPDIF Out / PDMA4 */ -#define VT1724_MULTI_PDMA3 0x40 /* PDMA3 */ -#define VT1724_MULTI_PDMA2 0x20 /* PDMA2 */ -#define VT1724_MULTI_PDMA1 0x10 /* PDMA1 */ -#define VT1724_MULTI_FIFO_ERR 0x08 /* DMA FIFO underrun/overrun. */ -#define VT1724_MULTI_RDMA1 0x04 /* RDMA1 (S/PDIF input) */ -#define VT1724_MULTI_RDMA0 0x02 /* RMDA0 */ -#define VT1724_MULTI_PDMA0 0x01 /* MC Interleave/PDMA0 */ - -#define VT1724_MT_RATE 0x01 /* byte - sampling rate select */ -#define VT1724_SPDIF_MASTER 0x10 /* S/PDIF input is master clock */ -#define VT1724_MT_I2S_FORMAT 0x02 /* byte - I2S data format */ -#define VT1724_MT_I2S_MCLK_128X 0x08 -#define VT1724_MT_I2S_FORMAT_MASK 0x03 -#define VT1724_MT_I2S_FORMAT_I2S 0x00 -#define VT1724_MT_DMA_INT_MASK 0x03 /* byte -DMA Interrupt Mask */ -/* lool to VT1724_MULTI_* */ -#define VT1724_MT_AC97_INDEX 0x04 /* byte - AC'97 index */ -#define VT1724_MT_AC97_CMD 0x05 /* byte - AC'97 command & status */ -#define VT1724_AC97_COLD 0x80 /* cold reset */ -#define VT1724_AC97_WARM 0x40 /* warm reset */ -#define VT1724_AC97_WRITE 0x20 /* W: write, R: write in progress */ -#define VT1724_AC97_READ 0x10 /* W: read, R: read in progress */ -#define VT1724_AC97_READY 0x08 /* codec ready status bit */ -#define VT1724_AC97_ID_MASK 0x03 /* codec id mask */ -#define VT1724_MT_AC97_DATA 0x06 /* word - AC'97 data */ -#define VT1724_MT_PLAYBACK_ADDR 0x10 /* dword - playback address */ -#define VT1724_MT_PLAYBACK_SIZE 0x14 /* dword - playback size */ -#define VT1724_MT_DMA_CONTROL 0x18 /* byte - control */ -#define VT1724_PDMA4_START 0x80 /* SPDIF out / PDMA4 start */ -#define VT1724_PDMA3_START 0x40 /* PDMA3 start */ -#define VT1724_PDMA2_START 0x20 /* PDMA2 start */ -#define VT1724_PDMA1_START 0x10 /* PDMA1 start */ -#define VT1724_RDMA1_START 0x04 /* RDMA1 start */ -#define VT1724_RDMA0_START 0x02 /* RMDA0 start */ -#define VT1724_PDMA0_START 0x01 /* MC Interleave / PDMA0 start */ -#define VT1724_MT_BURST 0x19 /* Interleaved playback DMA Active streams / PCI burst size */ -#define VT1724_MT_DMA_FIFO_ERR 0x1a /*Global playback and record DMA FIFO Underrun/Overrun */ -#define VT1724_PDMA4_UNDERRUN 0x80 -#define VT1724_PDMA2_UNDERRUN 0x40 -#define VT1724_PDMA3_UNDERRUN 0x20 -#define VT1724_PDMA1_UNDERRUN 0x10 -#define VT1724_RDMA1_UNDERRUN 0x04 -#define VT1724_RDMA0_UNDERRUN 0x02 -#define VT1724_PDMA0_UNDERRUN 0x01 -#define VT1724_MT_DMA_PAUSE 0x1b /*Global playback and record DMA FIFO pause/resume */ -#define VT1724_PDMA4_PAUSE 0x80 -#define VT1724_PDMA3_PAUSE 0x40 -#define VT1724_PDMA2_PAUSE 0x20 -#define VT1724_PDMA1_PAUSE 0x10 -#define VT1724_RDMA1_PAUSE 0x04 -#define VT1724_RDMA0_PAUSE 0x02 -#define VT1724_PDMA0_PAUSE 0x01 -#define VT1724_MT_PLAYBACK_COUNT 0x1c /* word - playback count */ -#define VT1724_MT_CAPTURE_ADDR 0x20 /* dword - capture address */ -#define VT1724_MT_CAPTURE_SIZE 0x24 /* word - capture size */ -#define VT1724_MT_CAPTURE_COUNT 0x26 /* word - capture count */ - -#define VT1724_MT_ROUTE_PLAYBACK 0x2c /* word */ - -#define VT1724_MT_RDMA1_ADDR 0x30 /* dword - RDMA1 capture address */ -#define VT1724_MT_RDMA1_SIZE 0x34 /* word - RDMA1 capture size */ -#define VT1724_MT_RDMA1_COUNT 0x36 /* word - RDMA1 capture count */ - -#define VT1724_MT_SPDIF_CTRL 0x3c /* word */ -#define VT1724_MT_MONITOR_PEAKINDEX 0x3e /* byte */ -#define VT1724_MT_MONITOR_PEAKDATA 0x3f /* byte */ - -/* concurrent stereo channels */ -#define VT1724_MT_PDMA4_ADDR 0x40 /* dword */ -#define VT1724_MT_PDMA4_SIZE 0x44 /* word */ -#define VT1724_MT_PDMA4_COUNT 0x46 /* word */ -#define VT1724_MT_PDMA3_ADDR 0x50 /* dword */ -#define VT1724_MT_PDMA3_SIZE 0x54 /* word */ -#define VT1724_MT_PDMA3_COUNT 0x56 /* word */ -#define VT1724_MT_PDMA2_ADDR 0x60 /* dword */ -#define VT1724_MT_PDMA2_SIZE 0x64 /* word */ -#define VT1724_MT_PDMA2_COUNT 0x66 /* word */ -#define VT1724_MT_PDMA1_ADDR 0x70 /* dword */ -#define VT1724_MT_PDMA1_SIZE 0x74 /* word */ -#define VT1724_MT_PDMA1_COUNT 0x76 /* word */ - - -unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, unsigned char dev, unsigned char addr); -void snd_vt1724_write_i2c(struct snd_ice1712 *ice, unsigned char dev, unsigned char addr, unsigned char data); - -#endif /* __SOUND_VT1724_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/ews.c b/ANDROID_3.4.5/sound/pci/ice1712/ews.c deleted file mode 100644 index 6fe35b81..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/ews.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire - * - * Copyright (c) 2000 Jaroslav Kysela - * 2002 Takashi Iwai - * - * 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 "ice1712.h" -#include "ews.h" - -#define SND_CS8404 -#include - -enum { - EWS_I2C_CS8404 = 0, EWS_I2C_PCF1, EWS_I2C_PCF2, - EWS_I2C_88D = 0, - EWS_I2C_6FIRE = 0 -}; - - -/* additional i2c devices for EWS boards */ -struct ews_spec { - struct snd_i2c_device *i2cdevs[3]; -}; - -/* - * access via i2c mode (for EWX 24/96, EWS 88MT&D) - */ - -/* send SDA and SCL */ -static void ewx_i2c_setlines(struct snd_i2c_bus *bus, int clk, int data) -{ - struct snd_ice1712 *ice = bus->private_data; - unsigned char tmp = 0; - if (clk) - tmp |= ICE1712_EWX2496_SERIAL_CLOCK; - if (data) - tmp |= ICE1712_EWX2496_SERIAL_DATA; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp); - udelay(5); -} - -static int ewx_i2c_getclock(struct snd_i2c_bus *bus) -{ - struct snd_ice1712 *ice = bus->private_data; - return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ICE1712_EWX2496_SERIAL_CLOCK ? 1 : 0; -} - -static int ewx_i2c_getdata(struct snd_i2c_bus *bus, int ack) -{ - struct snd_ice1712 *ice = bus->private_data; - int bit; - /* set RW pin to low */ - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~ICE1712_EWX2496_RW); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, 0); - if (ack) - udelay(5); - bit = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ICE1712_EWX2496_SERIAL_DATA ? 1 : 0; - /* set RW pin to high */ - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ICE1712_EWX2496_RW); - /* reset write mask */ - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~ICE1712_EWX2496_SERIAL_CLOCK); - return bit; -} - -static void ewx_i2c_start(struct snd_i2c_bus *bus) -{ - struct snd_ice1712 *ice = bus->private_data; - unsigned char mask; - - snd_ice1712_save_gpio_status(ice); - /* set RW high */ - mask = ICE1712_EWX2496_RW; - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_EWX2496: - mask |= ICE1712_EWX2496_AK4524_CS; /* CS high also */ - break; - case ICE1712_SUBDEVICE_DMX6FIRE: - mask |= ICE1712_6FIRE_AK4524_CS_MASK; /* CS high also */ - break; - } - snd_ice1712_gpio_write_bits(ice, mask, mask); -} - -static void ewx_i2c_stop(struct snd_i2c_bus *bus) -{ - struct snd_ice1712 *ice = bus->private_data; - snd_ice1712_restore_gpio_status(ice); -} - -static void ewx_i2c_direction(struct snd_i2c_bus *bus, int clock, int data) -{ - struct snd_ice1712 *ice = bus->private_data; - unsigned char mask = 0; - - if (clock) - mask |= ICE1712_EWX2496_SERIAL_CLOCK; /* write SCL */ - if (data) - mask |= ICE1712_EWX2496_SERIAL_DATA; /* write SDA */ - ice->gpio.direction &= ~(ICE1712_EWX2496_SERIAL_CLOCK|ICE1712_EWX2496_SERIAL_DATA); - ice->gpio.direction |= mask; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->gpio.direction); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~mask); -} - -static struct snd_i2c_bit_ops snd_ice1712_ewx_cs8427_bit_ops = { - .start = ewx_i2c_start, - .stop = ewx_i2c_stop, - .direction = ewx_i2c_direction, - .setlines = ewx_i2c_setlines, - .getclock = ewx_i2c_getclock, - .getdata = ewx_i2c_getdata, -}; - - -/* - * AK4524 access - */ - -/* AK4524 chip select; address 0x48 bit 0-3 */ -static int snd_ice1712_ews88mt_chip_select(struct snd_ice1712 *ice, int chip_mask) -{ - struct ews_spec *spec = ice->spec; - unsigned char data, ndata; - - if (snd_BUG_ON(chip_mask < 0 || chip_mask > 0x0f)) - return -EINVAL; - snd_i2c_lock(ice->i2c); - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) - goto __error; - ndata = (data & 0xf0) | chip_mask; - if (ndata != data) - if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_PCF2], &ndata, 1) - != 1) - goto __error; - snd_i2c_unlock(ice->i2c); - return 0; - - __error: - snd_i2c_unlock(ice->i2c); - snd_printk(KERN_ERR "AK4524 chip select failed, check cable to the front module\n"); - return -EIO; -} - -/* start callback for EWS88MT, needs to select a certain chip mask */ -static void ews88mt_ak4524_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ice1712 *ice = ak->private_data[0]; - unsigned char tmp; - /* assert AK4524 CS */ - if (snd_ice1712_ews88mt_chip_select(ice, ~(1 << chip) & 0x0f) < 0) - snd_printk(KERN_ERR "fatal error (ews88mt chip select)\n"); - snd_ice1712_save_gpio_status(ice); - tmp = ICE1712_EWS88_SERIAL_DATA | - ICE1712_EWS88_SERIAL_CLOCK | - ICE1712_EWS88_RW; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, - ice->gpio.direction | tmp); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp); -} - -/* stop callback for EWS88MT, needs to deselect chip mask */ -static void ews88mt_ak4524_unlock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ice1712 *ice = ak->private_data[0]; - snd_ice1712_restore_gpio_status(ice); - udelay(1); - snd_ice1712_ews88mt_chip_select(ice, 0x0f); -} - -/* start callback for EWX24/96 */ -static void ewx2496_ak4524_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ice1712 *ice = ak->private_data[0]; - unsigned char tmp; - snd_ice1712_save_gpio_status(ice); - tmp = ICE1712_EWX2496_SERIAL_DATA | - ICE1712_EWX2496_SERIAL_CLOCK | - ICE1712_EWX2496_AK4524_CS | - ICE1712_EWX2496_RW; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, - ice->gpio.direction | tmp); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp); -} - -/* start callback for DMX 6fire */ -static void dmx6fire_ak4524_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; - struct snd_ice1712 *ice = ak->private_data[0]; - unsigned char tmp; - snd_ice1712_save_gpio_status(ice); - tmp = priv->cs_mask = priv->cs_addr = (1 << chip) & ICE1712_6FIRE_AK4524_CS_MASK; - tmp |= ICE1712_6FIRE_SERIAL_DATA | - ICE1712_6FIRE_SERIAL_CLOCK | - ICE1712_6FIRE_RW; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, - ice->gpio.direction | tmp); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp); -} - -/* - * CS8404 interface on EWS88MT/D - */ - -static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned char bits) -{ - struct ews_spec *spec = ice->spec; - unsigned char bytes[2]; - - snd_i2c_lock(ice->i2c); - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_EWS88MT: - case ICE1712_SUBDEVICE_EWS88MT_NEW: - case ICE1712_SUBDEVICE_PHASE88: - case ICE1712_SUBDEVICE_TS88: - if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_CS8404], &bits, 1) - != 1) - goto _error; - break; - case ICE1712_SUBDEVICE_EWS88D: - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_88D], bytes, 2) - != 2) - goto _error; - if (bits != bytes[1]) { - bytes[1] = bits; - if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_88D], - bytes, 2) != 2) - goto _error; - } - break; - } - _error: - snd_i2c_unlock(ice->i2c); -} - -/* - */ - -static void ews88_spdif_default_get(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol) -{ - snd_cs8404_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_bits); -} - -static int ews88_spdif_default_put(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol) -{ - unsigned int val; - int change; - - val = snd_cs8404_encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - change = ice->spdif.cs8403_bits != val; - ice->spdif.cs8403_bits = val; - if (change && ice->playback_pro_substream == NULL) { - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_ews_cs8404_spdif_write(ice, val); - } else { - spin_unlock_irq(&ice->reg_lock); - } - return change; -} - -static void ews88_spdif_stream_get(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol) -{ - snd_cs8404_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_stream_bits); -} - -static int ews88_spdif_stream_put(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol) -{ - unsigned int val; - int change; - - val = snd_cs8404_encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - change = ice->spdif.cs8403_stream_bits != val; - ice->spdif.cs8403_stream_bits = val; - if (change && ice->playback_pro_substream != NULL) { - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_ews_cs8404_spdif_write(ice, val); - } else { - spin_unlock_irq(&ice->reg_lock); - } - return change; -} - - -/* open callback */ -static void ews88_open_spdif(struct snd_ice1712 *ice, struct snd_pcm_substream *substream) -{ - ice->spdif.cs8403_stream_bits = ice->spdif.cs8403_bits; -} - -/* set up SPDIF for EWS88MT / EWS88D */ -static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate) -{ - unsigned long flags; - unsigned char tmp; - int change; - - spin_lock_irqsave(&ice->reg_lock, flags); - tmp = ice->spdif.cs8403_stream_bits; - if (tmp & 0x10) /* consumer */ - tmp &= (tmp & 0x01) ? ~0x06 : ~0x60; - switch (rate) { - case 32000: tmp |= (tmp & 0x01) ? 0x02 : 0x00; break; - case 44100: tmp |= (tmp & 0x01) ? 0x06 : 0x40; break; - case 48000: tmp |= (tmp & 0x01) ? 0x04 : 0x20; break; - default: tmp |= (tmp & 0x01) ? 0x06 : 0x40; break; - } - change = ice->spdif.cs8403_stream_bits != tmp; - ice->spdif.cs8403_stream_bits = tmp; - spin_unlock_irqrestore(&ice->reg_lock, flags); - if (change) - snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &ice->spdif.stream_ctl->id); - snd_ice1712_ews_cs8404_spdif_write(ice, tmp); -} - - -/* - */ -static struct snd_akm4xxx akm_ews88mt __devinitdata = { - .num_adcs = 8, - .num_dacs = 8, - .type = SND_AK4524, - .ops = { - .lock = ews88mt_ak4524_lock, - .unlock = ews88mt_ak4524_unlock - } -}; - -static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = { - .caddr = 2, - .cif = 1, /* CIF high */ - .data_mask = ICE1712_EWS88_SERIAL_DATA, - .clk_mask = ICE1712_EWS88_SERIAL_CLOCK, - .cs_mask = 0, - .cs_addr = 0, - .cs_none = 0, /* no chip select on gpio */ - .add_flags = ICE1712_EWS88_RW, /* set rw bit high */ - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_ewx2496 __devinitdata = { - .num_adcs = 2, - .num_dacs = 2, - .type = SND_AK4524, - .ops = { - .lock = ewx2496_ak4524_lock - } -}; - -static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = { - .caddr = 2, - .cif = 1, /* CIF high */ - .data_mask = ICE1712_EWS88_SERIAL_DATA, - .clk_mask = ICE1712_EWS88_SERIAL_CLOCK, - .cs_mask = ICE1712_EWX2496_AK4524_CS, - .cs_addr = ICE1712_EWX2496_AK4524_CS, - .cs_none = 0, - .add_flags = ICE1712_EWS88_RW, /* set rw bit high */ - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_6fire __devinitdata = { - .num_adcs = 6, - .num_dacs = 6, - .type = SND_AK4524, - .ops = { - .lock = dmx6fire_ak4524_lock - } -}; - -static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = { - .caddr = 2, - .cif = 1, /* CIF high */ - .data_mask = ICE1712_6FIRE_SERIAL_DATA, - .clk_mask = ICE1712_6FIRE_SERIAL_CLOCK, - .cs_mask = 0, - .cs_addr = 0, /* set later */ - .cs_none = 0, - .add_flags = ICE1712_6FIRE_RW, /* set rw bit high */ - .mask_flags = 0, -}; - -/* - * initialize the chip - */ - -/* 6fire specific */ -#define PCF9554_REG_INPUT 0 -#define PCF9554_REG_OUTPUT 1 -#define PCF9554_REG_POLARITY 2 -#define PCF9554_REG_CONFIG 3 - -static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data); - -static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice) -{ - int err; - struct snd_akm4xxx *ak; - struct ews_spec *spec; - - /* set the analog DACs */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_EWX2496: - ice->num_total_dacs = 2; - ice->num_total_adcs = 2; - break; - case ICE1712_SUBDEVICE_EWS88MT: - case ICE1712_SUBDEVICE_EWS88MT_NEW: - case ICE1712_SUBDEVICE_PHASE88: - case ICE1712_SUBDEVICE_TS88: - ice->num_total_dacs = 8; - ice->num_total_adcs = 8; - break; - case ICE1712_SUBDEVICE_EWS88D: - /* Note: not analog but ADAT I/O */ - ice->num_total_dacs = 8; - ice->num_total_adcs = 8; - break; - case ICE1712_SUBDEVICE_DMX6FIRE: - ice->num_total_dacs = 6; - ice->num_total_adcs = 6; - break; - } - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - /* create i2c */ - if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { - snd_printk(KERN_ERR "unable to create I2C bus\n"); - return err; - } - ice->i2c->private_data = ice; - ice->i2c->hw_ops.bit = &snd_ice1712_ewx_cs8427_bit_ops; - - /* create i2c devices */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_DMX6FIRE: - err = snd_i2c_device_create(ice->i2c, "PCF9554", - ICE1712_6FIRE_PCF9554_ADDR, - &spec->i2cdevs[EWS_I2C_6FIRE]); - if (err < 0) { - snd_printk(KERN_ERR "PCF9554 initialization failed\n"); - return err; - } - snd_ice1712_6fire_write_pca(ice, PCF9554_REG_CONFIG, 0x80); - break; - case ICE1712_SUBDEVICE_EWS88MT: - case ICE1712_SUBDEVICE_EWS88MT_NEW: - case ICE1712_SUBDEVICE_PHASE88: - case ICE1712_SUBDEVICE_TS88: - - err = snd_i2c_device_create(ice->i2c, "CS8404", - ICE1712_EWS88MT_CS8404_ADDR, - &spec->i2cdevs[EWS_I2C_CS8404]); - if (err < 0) - return err; - err = snd_i2c_device_create(ice->i2c, "PCF8574 (1st)", - ICE1712_EWS88MT_INPUT_ADDR, - &spec->i2cdevs[EWS_I2C_PCF1]); - if (err < 0) - return err; - err = snd_i2c_device_create(ice->i2c, "PCF8574 (2nd)", - ICE1712_EWS88MT_OUTPUT_ADDR, - &spec->i2cdevs[EWS_I2C_PCF2]); - if (err < 0) - return err; - /* Check if the front module is connected */ - if ((err = snd_ice1712_ews88mt_chip_select(ice, 0x0f)) < 0) - return err; - break; - case ICE1712_SUBDEVICE_EWS88D: - err = snd_i2c_device_create(ice->i2c, "PCF8575", - ICE1712_EWS88D_PCF_ADDR, - &spec->i2cdevs[EWS_I2C_88D]); - if (err < 0) - return err; - break; - } - - /* set up SPDIF interface */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_EWX2496: - if ((err = snd_ice1712_init_cs8427(ice, CS8427_BASE_ADDR)) < 0) - return err; - snd_cs8427_reg_write(ice->cs8427, CS8427_REG_RECVERRMASK, CS8427_UNLOCK | CS8427_CONF | CS8427_BIP | CS8427_PAR); - break; - case ICE1712_SUBDEVICE_DMX6FIRE: - if ((err = snd_ice1712_init_cs8427(ice, ICE1712_6FIRE_CS8427_ADDR)) < 0) - return err; - snd_cs8427_reg_write(ice->cs8427, CS8427_REG_RECVERRMASK, CS8427_UNLOCK | CS8427_CONF | CS8427_BIP | CS8427_PAR); - break; - case ICE1712_SUBDEVICE_EWS88MT: - case ICE1712_SUBDEVICE_EWS88MT_NEW: - case ICE1712_SUBDEVICE_PHASE88: - case ICE1712_SUBDEVICE_TS88: - case ICE1712_SUBDEVICE_EWS88D: - /* set up CS8404 */ - ice->spdif.ops.open = ews88_open_spdif; - ice->spdif.ops.setup_rate = ews88_setup_spdif; - ice->spdif.ops.default_get = ews88_spdif_default_get; - ice->spdif.ops.default_put = ews88_spdif_default_put; - ice->spdif.ops.stream_get = ews88_spdif_stream_get; - ice->spdif.ops.stream_put = ews88_spdif_stream_put; - /* Set spdif defaults */ - snd_ice1712_ews_cs8404_spdif_write(ice, ice->spdif.cs8403_bits); - break; - } - - /* no analog? */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_EWS88D: - return 0; - } - - /* analog section */ - ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (! ak) - return -ENOMEM; - ice->akm_codecs = 1; - - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_EWS88MT: - case ICE1712_SUBDEVICE_EWS88MT_NEW: - case ICE1712_SUBDEVICE_PHASE88: - case ICE1712_SUBDEVICE_TS88: - err = snd_ice1712_akm4xxx_init(ak, &akm_ews88mt, &akm_ews88mt_priv, ice); - break; - case ICE1712_SUBDEVICE_EWX2496: - err = snd_ice1712_akm4xxx_init(ak, &akm_ewx2496, &akm_ewx2496_priv, ice); - break; - case ICE1712_SUBDEVICE_DMX6FIRE: - err = snd_ice1712_akm4xxx_init(ak, &akm_6fire, &akm_6fire_priv, ice); - break; - default: - err = 0; - } - - return err; -} - -/* - * EWX 24/96 specific controls - */ - -/* i/o sensitivity - this callback is shared among other devices, too */ -static int snd_ice1712_ewx_io_sense_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ - - static char *texts[2] = { - "+4dBu", "-10dBV", - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= 2) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ice1712_ewx_io_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char mask = kcontrol->private_value & 0xff; - - snd_ice1712_save_gpio_status(ice); - ucontrol->value.enumerated.item[0] = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & mask ? 1 : 0; - snd_ice1712_restore_gpio_status(ice); - return 0; -} - -static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char mask = kcontrol->private_value & 0xff; - int val, nval; - - if (kcontrol->private_value & (1 << 31)) - return -EPERM; - nval = ucontrol->value.enumerated.item[0] ? mask : 0; - snd_ice1712_save_gpio_status(ice); - val = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); - nval |= val & ~mask; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, nval); - snd_ice1712_restore_gpio_status(ice); - return val != nval; -} - -static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Sensitivity Switch", - .info = snd_ice1712_ewx_io_sense_info, - .get = snd_ice1712_ewx_io_sense_get, - .put = snd_ice1712_ewx_io_sense_put, - .private_value = ICE1712_EWX2496_AIN_SEL, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Output Sensitivity Switch", - .info = snd_ice1712_ewx_io_sense_info, - .get = snd_ice1712_ewx_io_sense_get, - .put = snd_ice1712_ewx_io_sense_put, - .private_value = ICE1712_EWX2496_AOUT_SEL, - }, -}; - - -/* - * EWS88MT specific controls - */ -/* analog output sensitivity;; address 0x48 bit 6 */ -static int snd_ice1712_ews88mt_output_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct ews_spec *spec = ice->spec; - unsigned char data; - - snd_i2c_lock(ice->i2c); - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - snd_i2c_unlock(ice->i2c); - ucontrol->value.enumerated.item[0] = data & ICE1712_EWS88MT_OUTPUT_SENSE ? 1 : 0; /* high = -10dBV, low = +4dBu */ - return 0; -} - -/* analog output sensitivity;; address 0x48 bit 6 */ -static int snd_ice1712_ews88mt_output_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct ews_spec *spec = ice->spec; - unsigned char data, ndata; - - snd_i2c_lock(ice->i2c); - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - ndata = (data & ~ICE1712_EWS88MT_OUTPUT_SENSE) | (ucontrol->value.enumerated.item[0] ? ICE1712_EWS88MT_OUTPUT_SENSE : 0); - if (ndata != data && snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_PCF2], - &ndata, 1) != 1) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - snd_i2c_unlock(ice->i2c); - return ndata != data; -} - -/* analog input sensitivity; address 0x46 */ -static int snd_ice1712_ews88mt_input_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct ews_spec *spec = ice->spec; - int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned char data; - - if (snd_BUG_ON(channel < 0 || channel > 7)) - return 0; - snd_i2c_lock(ice->i2c); - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - /* reversed; high = +4dBu, low = -10dBV */ - ucontrol->value.enumerated.item[0] = data & (1 << channel) ? 0 : 1; - snd_i2c_unlock(ice->i2c); - return 0; -} - -/* analog output sensitivity; address 0x46 */ -static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct ews_spec *spec = ice->spec; - int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned char data, ndata; - - if (snd_BUG_ON(channel < 0 || channel > 7)) - return 0; - snd_i2c_lock(ice->i2c); - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - ndata = (data & ~(1 << channel)) | (ucontrol->value.enumerated.item[0] ? 0 : (1 << channel)); - if (ndata != data && snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_PCF1], - &ndata, 1) != 1) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - snd_i2c_unlock(ice->i2c); - return ndata != data; -} - -static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Sensitivity Switch", - .info = snd_ice1712_ewx_io_sense_info, - .get = snd_ice1712_ews88mt_input_sense_get, - .put = snd_ice1712_ews88mt_input_sense_put, - .count = 8, -}; - -static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Output Sensitivity Switch", - .info = snd_ice1712_ewx_io_sense_info, - .get = snd_ice1712_ews88mt_output_sense_get, - .put = snd_ice1712_ews88mt_output_sense_put, -}; - - -/* - * EWS88D specific controls - */ - -#define snd_ice1712_ews88d_control_info snd_ctl_boolean_mono_info - -static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct ews_spec *spec = ice->spec; - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value >> 8) & 1; - unsigned char data[2]; - - snd_i2c_lock(ice->i2c); - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_88D], data, 2) != 2) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - snd_i2c_unlock(ice->i2c); - data[0] = (data[shift >> 3] >> (shift & 7)) & 0x01; - if (invert) - data[0] ^= 0x01; - ucontrol->value.integer.value[0] = data[0]; - return 0; -} - -static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct ews_spec *spec = ice->spec; - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value >> 8) & 1; - unsigned char data[2], ndata[2]; - int change; - - snd_i2c_lock(ice->i2c); - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_88D], data, 2) != 2) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - ndata[shift >> 3] = data[shift >> 3] & ~(1 << (shift & 7)); - if (invert) { - if (! ucontrol->value.integer.value[0]) - ndata[shift >> 3] |= (1 << (shift & 7)); - } else { - if (ucontrol->value.integer.value[0]) - ndata[shift >> 3] |= (1 << (shift & 7)); - } - change = (data[shift >> 3] != ndata[shift >> 3]); - if (change && - snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_88D], data, 2) != 2) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - snd_i2c_unlock(ice->i2c); - return change; -} - -#define EWS88D_CONTROL(xiface, xname, xshift, xinvert, xaccess) \ -{ .iface = xiface,\ - .name = xname,\ - .access = xaccess,\ - .info = snd_ice1712_ews88d_control_info,\ - .get = snd_ice1712_ews88d_control_get,\ - .put = snd_ice1712_ews88d_control_put,\ - .private_value = xshift | (xinvert << 8),\ -} - -static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = { - EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */ - EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0), - EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0), - EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "Enable ADAT", 3, 0, 0), - EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Through", 4, 1, 0), -}; - - -/* - * DMX 6Fire specific controls - */ - -static int snd_ice1712_6fire_read_pca(struct snd_ice1712 *ice, unsigned char reg) -{ - unsigned char byte; - struct ews_spec *spec = ice->spec; - - snd_i2c_lock(ice->i2c); - byte = reg; - snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1); - byte = 0; - if (snd_i2c_readbytes(spec->i2cdevs[EWS_I2C_6FIRE], &byte, 1) != 1) { - snd_i2c_unlock(ice->i2c); - printk(KERN_ERR "cannot read pca\n"); - return -EIO; - } - snd_i2c_unlock(ice->i2c); - return byte; -} - -static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data) -{ - unsigned char bytes[2]; - struct ews_spec *spec = ice->spec; - - snd_i2c_lock(ice->i2c); - bytes[0] = reg; - bytes[1] = data; - if (snd_i2c_sendbytes(spec->i2cdevs[EWS_I2C_6FIRE], bytes, 2) != 2) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - snd_i2c_unlock(ice->i2c); - return 0; -} - -#define snd_ice1712_6fire_control_info snd_ctl_boolean_mono_info - -static int snd_ice1712_6fire_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value >> 8) & 1; - int data; - - if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) - return data; - data = (data >> shift) & 1; - if (invert) - data ^= 1; - ucontrol->value.integer.value[0] = data; - return 0; -} - -static int snd_ice1712_6fire_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value >> 8) & 1; - int data, ndata; - - if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) - return data; - ndata = data & ~(1 << shift); - if (ucontrol->value.integer.value[0]) - ndata |= (1 << shift); - if (invert) - ndata ^= (1 << shift); - if (data != ndata) { - snd_ice1712_6fire_write_pca(ice, PCF9554_REG_OUTPUT, (unsigned char)ndata); - return 1; - } - return 0; -} - -static int snd_ice1712_6fire_select_input_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { - "Internal", "Front Input", "Rear Input", "Wave Table" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= 4) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ice1712_6fire_select_input_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int data; - - if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) - return data; - ucontrol->value.integer.value[0] = data & 3; - return 0; -} - -static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int data, ndata; - - if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) - return data; - ndata = data & ~3; - ndata |= (ucontrol->value.integer.value[0] & 3); - if (data != ndata) { - snd_ice1712_6fire_write_pca(ice, PCF9554_REG_OUTPUT, (unsigned char)ndata); - return 1; - } - return 0; -} - - -#define DMX6FIRE_CONTROL(xname, xshift, xinvert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname,\ - .info = snd_ice1712_6fire_control_info,\ - .get = snd_ice1712_6fire_control_get,\ - .put = snd_ice1712_6fire_control_put,\ - .private_value = xshift | (xinvert << 8),\ -} - -static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Select", - .info = snd_ice1712_6fire_select_input_info, - .get = snd_ice1712_6fire_select_input_get, - .put = snd_ice1712_6fire_select_input_put, - }, - DMX6FIRE_CONTROL("Front Digital Input Switch", 2, 1), - // DMX6FIRE_CONTROL("Master Clock Select", 3, 0), - DMX6FIRE_CONTROL("Optical Digital Input Switch", 4, 0), - DMX6FIRE_CONTROL("Phono Analog Input Switch", 5, 0), - DMX6FIRE_CONTROL("Breakbox LED", 6, 0), -}; - - -static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice) -{ - unsigned int idx; - int err; - - /* all terratec cards have spdif, but cs8427 module builds it's own controls */ - if (ice->cs8427 == NULL) { - err = snd_ice1712_spdif_build_controls(ice); - if (err < 0) - return err; - } - - /* ak4524 controls */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_EWX2496: - case ICE1712_SUBDEVICE_EWS88MT: - case ICE1712_SUBDEVICE_EWS88MT_NEW: - case ICE1712_SUBDEVICE_PHASE88: - case ICE1712_SUBDEVICE_TS88: - case ICE1712_SUBDEVICE_DMX6FIRE: - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - break; - } - - /* card specific controls */ - switch (ice->eeprom.subvendor) { - case ICE1712_SUBDEVICE_EWX2496: - for (idx = 0; idx < ARRAY_SIZE(snd_ice1712_ewx2496_controls); idx++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ewx2496_controls[idx], ice)); - if (err < 0) - return err; - } - break; - case ICE1712_SUBDEVICE_EWS88MT: - case ICE1712_SUBDEVICE_EWS88MT_NEW: - case ICE1712_SUBDEVICE_PHASE88: - case ICE1712_SUBDEVICE_TS88: - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88mt_input_sense, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88mt_output_sense, ice)); - if (err < 0) - return err; - break; - case ICE1712_SUBDEVICE_EWS88D: - for (idx = 0; idx < ARRAY_SIZE(snd_ice1712_ews88d_controls); idx++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88d_controls[idx], ice)); - if (err < 0) - return err; - } - break; - case ICE1712_SUBDEVICE_DMX6FIRE: - for (idx = 0; idx < ARRAY_SIZE(snd_ice1712_6fire_controls); idx++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_6fire_controls[idx], ice)); - if (err < 0) - return err; - } - break; - } - return 0; -} - - -/* entry point */ -struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = { - { - .subvendor = ICE1712_SUBDEVICE_EWX2496, - .name = "TerraTec EWX24/96", - .model = "ewx2496", - .chip_init = snd_ice1712_ews_init, - .build_controls = snd_ice1712_ews_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_EWS88MT, - .name = "TerraTec EWS88MT", - .model = "ews88mt", - .chip_init = snd_ice1712_ews_init, - .build_controls = snd_ice1712_ews_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_EWS88MT_NEW, - .name = "TerraTec EWS88MT", - .model = "ews88mt_new", - .chip_init = snd_ice1712_ews_init, - .build_controls = snd_ice1712_ews_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_PHASE88, - .name = "TerraTec Phase88", - .model = "phase88", - .chip_init = snd_ice1712_ews_init, - .build_controls = snd_ice1712_ews_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_TS88, - .name = "terrasoniq TS88", - .model = "phase88", - .chip_init = snd_ice1712_ews_init, - .build_controls = snd_ice1712_ews_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_EWS88D, - .name = "TerraTec EWS88D", - .model = "ews88d", - .chip_init = snd_ice1712_ews_init, - .build_controls = snd_ice1712_ews_add_controls, - }, - { - .subvendor = ICE1712_SUBDEVICE_DMX6FIRE, - .name = "TerraTec DMX6Fire", - .model = "dmx6fire", - .chip_init = snd_ice1712_ews_init, - .build_controls = snd_ice1712_ews_add_controls, - .mpu401_1_name = "MIDI-Front DMX6fire", - .mpu401_2_name = "Wavetable DMX6fire", - .mpu401_2_info_flags = MPU401_INFO_OUTPUT, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/ews.h b/ANDROID_3.4.5/sound/pci/ice1712/ews.h deleted file mode 100644 index 1c443718..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/ews.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef __SOUND_EWS_H -#define __SOUND_EWS_H - -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for Terratec EWS88MT/D, EWX24/96, DMX 6Fire - * - * Copyright (c) 2000 Jaroslav Kysela - * 2002 Takashi Iwai - * - * 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 - * - */ - -#define EWS_DEVICE_DESC \ - "{TerraTec,EWX 24/96},"\ - "{TerraTec,EWS 88MT},"\ - "{TerraTec,EWS 88D},"\ - "{TerraTec,DMX 6Fire},"\ - "{TerraTec,Phase 88}," \ - "{terrasoniq,TS 88}," - -#define ICE1712_SUBDEVICE_EWX2496 0x3b153011 -#define ICE1712_SUBDEVICE_EWS88MT 0x3b151511 -#define ICE1712_SUBDEVICE_EWS88MT_NEW 0x3b152511 -#define ICE1712_SUBDEVICE_EWS88D 0x3b152b11 -#define ICE1712_SUBDEVICE_DMX6FIRE 0x3b153811 -#define ICE1712_SUBDEVICE_PHASE88 0x3b155111 -#define ICE1712_SUBDEVICE_TS88 0x3b157c11 - -/* entry point */ -extern struct snd_ice1712_card_info snd_ice1712_ews_cards[]; - - -/* TerraTec EWX 24/96 configuration definitions */ - -#define ICE1712_EWX2496_AK4524_CS 0x01 /* AK4524 chip select; low = active */ -#define ICE1712_EWX2496_AIN_SEL 0x02 /* input sensitivity switch; high = louder */ -#define ICE1712_EWX2496_AOUT_SEL 0x04 /* output sensitivity switch; high = louder */ -#define ICE1712_EWX2496_RW 0x08 /* read/write switch for i2c; high = write */ -#define ICE1712_EWX2496_SERIAL_DATA 0x10 /* i2c & ak4524 data */ -#define ICE1712_EWX2496_SERIAL_CLOCK 0x20 /* i2c & ak4524 clock */ -#define ICE1712_EWX2496_TX2 0x40 /* MIDI2 (not used) */ -#define ICE1712_EWX2496_RX2 0x80 /* MIDI2 (not used) */ - -/* TerraTec EWS 88MT/D configuration definitions */ -/* RW, SDA snd SCLK are identical with EWX24/96 */ -#define ICE1712_EWS88_CS8414_RATE 0x07 /* CS8414 sample rate: gpio 0-2 */ -#define ICE1712_EWS88_RW 0x08 /* read/write switch for i2c; high = write */ -#define ICE1712_EWS88_SERIAL_DATA 0x10 /* i2c & ak4524 data */ -#define ICE1712_EWS88_SERIAL_CLOCK 0x20 /* i2c & ak4524 clock */ -#define ICE1712_EWS88_TX2 0x40 /* MIDI2 (only on 88D) */ -#define ICE1712_EWS88_RX2 0x80 /* MIDI2 (only on 88D) */ - -/* i2c address */ -#define ICE1712_EWS88MT_CS8404_ADDR (0x40>>1) -#define ICE1712_EWS88MT_INPUT_ADDR (0x46>>1) -#define ICE1712_EWS88MT_OUTPUT_ADDR (0x48>>1) -#define ICE1712_EWS88MT_OUTPUT_SENSE 0x40 /* mask */ -#define ICE1712_EWS88D_PCF_ADDR (0x40>>1) - -/* TerraTec DMX 6Fire configuration definitions */ -#define ICE1712_6FIRE_AK4524_CS_MASK 0x07 /* AK4524 chip select #1-#3 */ -#define ICE1712_6FIRE_RW 0x08 /* read/write switch for i2c; high = write */ -#define ICE1712_6FIRE_SERIAL_DATA 0x10 /* i2c & ak4524 data */ -#define ICE1712_6FIRE_SERIAL_CLOCK 0x20 /* i2c & ak4524 clock */ -#define ICE1712_6FIRE_TX2 0x40 /* MIDI2 */ -#define ICE1712_6FIRE_RX2 0x80 /* MIDI2 */ - -#define ICE1712_6FIRE_PCF9554_ADDR (0x40>>1) -#define ICE1712_6FIRE_CS8427_ADDR (0x22) - -#endif /* __SOUND_EWS_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/hoontech.c b/ANDROID_3.4.5/sound/pci/ice1712/hoontech.c deleted file mode 100644 index 69141890..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/hoontech.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for Hoontech STDSP24 - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 "ice1712.h" -#include "hoontech.h" - -/* Hoontech-specific setting */ -struct hoontech_spec { - unsigned char boxbits[4]; - unsigned int config; - unsigned short boxconfig[4]; -}; - -static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte) -{ - byte |= ICE1712_STDSP24_CLOCK_BIT; - udelay(100); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte); - byte &= ~ICE1712_STDSP24_CLOCK_BIT; - udelay(100); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte); - byte |= ICE1712_STDSP24_CLOCK_BIT; - udelay(100); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte); -} - -static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate) -{ - struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); - ICE1712_STDSP24_0_DAREAR(spec->boxbits, activate); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]); - mutex_unlock(&ice->gpio_mutex); -} - -static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate) -{ - struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); - ICE1712_STDSP24_3_MUTE(spec->boxbits, activate); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); - mutex_unlock(&ice->gpio_mutex); -} - -static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate) -{ - struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); - ICE1712_STDSP24_3_INSEL(spec->boxbits, activate); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); - mutex_unlock(&ice->gpio_mutex); -} - -static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate) -{ - struct hoontech_spec *spec = ice->spec; - - mutex_lock(&ice->gpio_mutex); - - /* select box */ - ICE1712_STDSP24_0_BOX(spec->boxbits, box); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]); - - /* prepare for write */ - if (chn == 3) - ICE1712_STDSP24_2_CHN4(spec->boxbits, 0); - ICE1712_STDSP24_2_MIDI1(spec->boxbits, activate); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); - - ICE1712_STDSP24_1_CHN1(spec->boxbits, 1); - ICE1712_STDSP24_1_CHN2(spec->boxbits, 1); - ICE1712_STDSP24_1_CHN3(spec->boxbits, 1); - ICE1712_STDSP24_2_CHN4(spec->boxbits, 1); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - udelay(100); - if (chn == 3) { - ICE1712_STDSP24_2_CHN4(spec->boxbits, 0); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - } else { - switch (chn) { - case 0: ICE1712_STDSP24_1_CHN1(spec->boxbits, 0); break; - case 1: ICE1712_STDSP24_1_CHN2(spec->boxbits, 0); break; - case 2: ICE1712_STDSP24_1_CHN3(spec->boxbits, 0); break; - } - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]); - } - udelay(100); - ICE1712_STDSP24_1_CHN1(spec->boxbits, 1); - ICE1712_STDSP24_1_CHN2(spec->boxbits, 1); - ICE1712_STDSP24_1_CHN3(spec->boxbits, 1); - ICE1712_STDSP24_2_CHN4(spec->boxbits, 1); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - udelay(100); - - ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - - mutex_unlock(&ice->gpio_mutex); -} - -static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master) -{ - struct hoontech_spec *spec = ice->spec; - - mutex_lock(&ice->gpio_mutex); - - /* select box */ - ICE1712_STDSP24_0_BOX(spec->boxbits, box); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]); - - ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1); - ICE1712_STDSP24_2_MIDI1(spec->boxbits, master); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); - - udelay(100); - - ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 0); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - - mdelay(10); - - ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]); - - mutex_unlock(&ice->gpio_mutex); -} - -static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate) -{ - struct hoontech_spec *spec = ice->spec; - mutex_lock(&ice->gpio_mutex); - ICE1712_STDSP24_3_MIDI2(spec->boxbits, activate); - snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]); - mutex_unlock(&ice->gpio_mutex); -} - -static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice) -{ - struct hoontech_spec *spec; - int box, chn; - - ice->num_total_dacs = 8; - ice->num_total_adcs = 8; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - ICE1712_STDSP24_SET_ADDR(spec->boxbits, 0); - ICE1712_STDSP24_CLOCK(spec->boxbits, 0, 1); - ICE1712_STDSP24_0_BOX(spec->boxbits, 0); - ICE1712_STDSP24_0_DAREAR(spec->boxbits, 0); - - ICE1712_STDSP24_SET_ADDR(spec->boxbits, 1); - ICE1712_STDSP24_CLOCK(spec->boxbits, 1, 1); - ICE1712_STDSP24_1_CHN1(spec->boxbits, 1); - ICE1712_STDSP24_1_CHN2(spec->boxbits, 1); - ICE1712_STDSP24_1_CHN3(spec->boxbits, 1); - - ICE1712_STDSP24_SET_ADDR(spec->boxbits, 2); - ICE1712_STDSP24_CLOCK(spec->boxbits, 2, 1); - ICE1712_STDSP24_2_CHN4(spec->boxbits, 1); - ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1); - ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0); - - ICE1712_STDSP24_SET_ADDR(spec->boxbits, 3); - ICE1712_STDSP24_CLOCK(spec->boxbits, 3, 1); - ICE1712_STDSP24_3_MIDI2(spec->boxbits, 0); - ICE1712_STDSP24_3_MUTE(spec->boxbits, 1); - ICE1712_STDSP24_3_INSEL(spec->boxbits, 0); - - /* let's go - activate only functions in first box */ - spec->config = 0; - /* ICE1712_STDSP24_MUTE | - ICE1712_STDSP24_INSEL | - ICE1712_STDSP24_DAREAR; */ - /* These boxconfigs have caused problems in the past. - * The code is not optimal, but should now enable a working config to - * be achieved. - * ** MIDI IN can only be configured on one box ** - * ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box. - * Tests on a ADAC2000 box suggest the box config flags do not - * work as would be expected, and the inputs are crossed. - * Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2 - * on the same box connects MIDI-In to both 401 uarts; both outputs - * are then active on all boxes. - * The default config here sets up everything on the first box. - * Alan Horstmann 5.2.2008 - */ - spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 | - ICE1712_STDSP24_BOX_CHN2 | - ICE1712_STDSP24_BOX_CHN3 | - ICE1712_STDSP24_BOX_CHN4 | - ICE1712_STDSP24_BOX_MIDI1 | - ICE1712_STDSP24_BOX_MIDI2; - spec->boxconfig[1] = - spec->boxconfig[2] = - spec->boxconfig[3] = 0; - snd_ice1712_stdsp24_darear(ice, - (spec->config & ICE1712_STDSP24_DAREAR) ? 1 : 0); - snd_ice1712_stdsp24_mute(ice, - (spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0); - snd_ice1712_stdsp24_insel(ice, - (spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0); - for (box = 0; box < 4; box++) { - if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2) - snd_ice1712_stdsp24_midi2(ice, 1); - for (chn = 0; chn < 4; chn++) - snd_ice1712_stdsp24_box_channel(ice, box, chn, - (spec->boxconfig[box] & (1 << chn)) ? 1 : 0); - if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) - snd_ice1712_stdsp24_box_midi(ice, box, 1); - } - - return 0; -} - -/* - * AK4524 access - */ - -/* start callback for STDSP24 with modified hardware */ -static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip) -{ - struct snd_ice1712 *ice = ak->private_data[0]; - unsigned char tmp; - snd_ice1712_save_gpio_status(ice); - tmp = ICE1712_STDSP24_SERIAL_DATA | - ICE1712_STDSP24_SERIAL_CLOCK | - ICE1712_STDSP24_AK4524_CS; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, - ice->gpio.direction | tmp); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp); -} - -static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice) -{ - /* Hoontech STDSP24 with modified hardware */ - static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = { - .num_adcs = 2, - .num_dacs = 2, - .type = SND_AK4524, - .ops = { - .lock = stdsp24_ak4524_lock - } - }; - - static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = { - .caddr = 2, - .cif = 1, /* CIF high */ - .data_mask = ICE1712_STDSP24_SERIAL_DATA, - .clk_mask = ICE1712_STDSP24_SERIAL_CLOCK, - .cs_mask = ICE1712_STDSP24_AK4524_CS, - .cs_addr = ICE1712_STDSP24_AK4524_CS, - .cs_none = 0, - .add_flags = 0, - }; - - int err; - struct snd_akm4xxx *ak; - - /* set the analog DACs */ - ice->num_total_dacs = 2; - - /* set the analog ADCs */ - ice->num_total_adcs = 2; - - /* analog section */ - ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (! ak) - return -ENOMEM; - ice->akm_codecs = 1; - - err = snd_ice1712_akm4xxx_init(ak, &akm_stdsp24_mv, &akm_stdsp24_mv_priv, ice); - if (err < 0) - return err; - - /* ak4524 controls */ - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - - return 0; -} - -static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice) -{ - ice->gpio.write_mask = ice->eeprom.gpiomask; - ice->gpio.direction = ice->eeprom.gpiodir; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ice->eeprom.gpiomask); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->eeprom.gpiodir); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ice->eeprom.gpiostate); - return 0; -} - - -/* entry point */ -struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = { - { - .subvendor = ICE1712_SUBDEVICE_STDSP24, - .name = "Hoontech SoundTrack Audio DSP24", - .model = "dsp24", - .chip_init = snd_ice1712_hoontech_init, - .mpu401_1_name = "MIDI-1 Hoontech/STA DSP24", - .mpu401_2_name = "MIDI-2 Hoontech/STA DSP24", - }, - { - .subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE, /* a dummy id */ - .name = "Hoontech SoundTrack Audio DSP24 Value", - .model = "dsp24_value", - .chip_init = snd_ice1712_value_init, - }, - { - .subvendor = ICE1712_SUBDEVICE_STDSP24_MEDIA7_1, - .name = "Hoontech STA DSP24 Media 7.1", - .model = "dsp24_71", - .chip_init = snd_ice1712_hoontech_init, - }, - { - .subvendor = ICE1712_SUBDEVICE_EVENT_EZ8, /* a dummy id */ - .name = "Event Electronics EZ8", - .model = "ez8", - .chip_init = snd_ice1712_ez8_init, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/hoontech.h b/ANDROID_3.4.5/sound/pci/ice1712/hoontech.h deleted file mode 100644 index cc1da1e6..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/hoontech.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __SOUND_HOONTECH_H -#define __SOUND_HOONTECH_H - -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for Hoontech STDSP24 - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 - * - */ - -#define HOONTECH_DEVICE_DESC \ - "{Hoontech,SoundTrack DSP 24}," \ - "{Hoontech,SoundTrack DSP 24 Value}," \ - "{Hoontech,SoundTrack DSP 24 Media 7.1}," \ - "{Event Electronics,EZ8}," - -#define ICE1712_SUBDEVICE_STDSP24 0x12141217 /* Hoontech SoundTrack Audio DSP 24 */ -#define ICE1712_SUBDEVICE_STDSP24_VALUE 0x00010010 /* A dummy id for Hoontech SoundTrack Audio DSP 24 Value */ -#define ICE1712_SUBDEVICE_STDSP24_MEDIA7_1 0x16141217 /* Hoontech ST Audio DSP24 Media 7.1 */ -#define ICE1712_SUBDEVICE_EVENT_EZ8 0x00010001 /* A dummy id for EZ8 */ - -extern struct snd_ice1712_card_info snd_ice1712_hoontech_cards[]; - - -/* Hoontech SoundTrack Audio DSP 24 GPIO definitions */ - -#define ICE1712_STDSP24_0_BOX(r, x) r[0] = ((r[0] & ~3) | ((x)&3)) -#define ICE1712_STDSP24_0_DAREAR(r, x) r[0] = ((r[0] & ~4) | (((x)&1)<<2)) -#define ICE1712_STDSP24_1_CHN1(r, x) r[1] = ((r[1] & ~1) | ((x)&1)) -#define ICE1712_STDSP24_1_CHN2(r, x) r[1] = ((r[1] & ~2) | (((x)&1)<<1)) -#define ICE1712_STDSP24_1_CHN3(r, x) r[1] = ((r[1] & ~4) | (((x)&1)<<2)) -#define ICE1712_STDSP24_2_CHN4(r, x) r[2] = ((r[2] & ~1) | ((x)&1)) -#define ICE1712_STDSP24_2_MIDIIN(r, x) r[2] = ((r[2] & ~2) | (((x)&1)<<1)) -#define ICE1712_STDSP24_2_MIDI1(r, x) r[2] = ((r[2] & ~4) | (((x)&1)<<2)) -#define ICE1712_STDSP24_3_MIDI2(r, x) r[3] = ((r[3] & ~1) | ((x)&1)) -#define ICE1712_STDSP24_3_MUTE(r, x) r[3] = ((r[3] & ~2) | (((x)&1)<<1)) -#define ICE1712_STDSP24_3_INSEL(r, x) r[3] = ((r[3] & ~4) | (((x)&1)<<2)) -#define ICE1712_STDSP24_SET_ADDR(r, a) r[a&3] = ((r[a&3] & ~0x18) | (((a)&3)<<3)) -#define ICE1712_STDSP24_CLOCK(r, a, c) r[a&3] = ((r[a&3] & ~0x20) | (((c)&1)<<5)) -#define ICE1712_STDSP24_CLOCK_BIT (1<<5) - -/* Hoontech SoundTrack Audio DSP 24 box configuration definitions */ - -#define ICE1712_STDSP24_DAREAR (1<<0) -#define ICE1712_STDSP24_MUTE (1<<1) -#define ICE1712_STDSP24_INSEL (1<<2) - -#define ICE1712_STDSP24_BOX_CHN1 (1<<0) /* input channel 1 */ -#define ICE1712_STDSP24_BOX_CHN2 (1<<1) /* input channel 2 */ -#define ICE1712_STDSP24_BOX_CHN3 (1<<2) /* input channel 3 */ -#define ICE1712_STDSP24_BOX_CHN4 (1<<3) /* input channel 4 */ -#define ICE1712_STDSP24_BOX_MIDI1 (1<<8) -#define ICE1712_STDSP24_BOX_MIDI2 (1<<9) - -/* Hoontech SoundTrack Audio DSP 24 Value definitions for modified hardware */ - -#define ICE1712_STDSP24_AK4524_CS 0x03 /* AK4524 chip select; low = active */ -#define ICE1712_STDSP24_SERIAL_DATA 0x0c /* ak4524 data */ -#define ICE1712_STDSP24_SERIAL_CLOCK 0x30 /* ak4524 clock */ - -#endif /* __SOUND_HOONTECH_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/ice1712.c b/ANDROID_3.4.5/sound/pci/ice1712/ice1712.c deleted file mode 100644 index 132a86e0..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/ice1712.c +++ /dev/null @@ -1,2824 +0,0 @@ -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 - * - */ - -/* - NOTES: - - spdif nonaudio consumer mode does not work (at least with my - Sony STR-DB830) -*/ - -/* - * Changes: - * - * 2002.09.09 Takashi Iwai - * split the code to several files. each low-level routine - * is stored in the local file and called from registration - * function from card_info struct. - * - * 2002.11.26 James Stafford - * Added support for VT1724 (Envy24HT) - * I have left out support for 176.4 and 192 KHz for the moment. - * I also haven't done anything with the internal S/PDIF transmitter or the MPU-401 - * - * 2003.02.20 Taksahi Iwai - * Split vt1724 part to an independent driver. - * The GPIO is accessed through the callback functions now. - * - * 2004.03.31 Doug McLain - * Added support for Event Electronics EZ8 card to hoontech.c. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "ice1712.h" - -/* lowlevel routines */ -#include "delta.h" -#include "ews.h" -#include "hoontech.h" - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{" - HOONTECH_DEVICE_DESC - DELTA_DEVICE_DESC - EWS_DEVICE_DESC - "{ICEnsemble,Generic ICE1712}," - "{ICEnsemble,Generic Envy24}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ -static char *model[SNDRV_CARDS]; -static bool omni[SNDRV_CARDS]; /* Delta44 & 66 Omni I/O support */ -static int cs8427_timeout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 500}; /* CS8427 S/PDIF transceiver reset timeout value in msec */ -static int dxr_enable[SNDRV_CARDS]; /* DXR enable for DMX6FIRE */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ICE1712 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ICE1712 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ICE1712 soundcard."); -module_param_array(omni, bool, NULL, 0444); -MODULE_PARM_DESC(omni, "Enable Midiman M-Audio Delta Omni I/O support."); -module_param_array(cs8427_timeout, int, NULL, 0444); -MODULE_PARM_DESC(cs8427_timeout, "Define reset timeout for cs8427 chip in msec resolution."); -module_param_array(model, charp, NULL, 0444); -MODULE_PARM_DESC(model, "Use the given board model."); -module_param_array(dxr_enable, int, NULL, 0444); -MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE."); - - -static DEFINE_PCI_DEVICE_TABLE(snd_ice1712_ids) = { - { PCI_VDEVICE(ICE, PCI_DEVICE_ID_ICE_1712), 0 }, /* ICE1712 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_ice1712_ids); - -static int snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice); -static int snd_ice1712_build_controls(struct snd_ice1712 *ice); - -static int PRO_RATE_LOCKED; -static int PRO_RATE_RESET = 1; -static unsigned int PRO_RATE_DEFAULT = 44100; - -/* - * Basic I/O - */ - -/* check whether the clock mode is spdif-in */ -static inline int is_spdif_master(struct snd_ice1712 *ice) -{ - return (inb(ICEMT(ice, RATE)) & ICE1712_SPDIF_MASTER) ? 1 : 0; -} - -static inline int is_pro_rate_locked(struct snd_ice1712 *ice) -{ - return is_spdif_master(ice) || PRO_RATE_LOCKED; -} - -static inline void snd_ice1712_ds_write(struct snd_ice1712 *ice, u8 channel, u8 addr, u32 data) -{ - outb((channel << 4) | addr, ICEDS(ice, INDEX)); - outl(data, ICEDS(ice, DATA)); -} - -static inline u32 snd_ice1712_ds_read(struct snd_ice1712 *ice, u8 channel, u8 addr) -{ - outb((channel << 4) | addr, ICEDS(ice, INDEX)); - return inl(ICEDS(ice, DATA)); -} - -static void snd_ice1712_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct snd_ice1712 *ice = ac97->private_data; - int tm; - unsigned char old_cmd = 0; - - for (tm = 0; tm < 0x10000; tm++) { - old_cmd = inb(ICEREG(ice, AC97_CMD)); - if (old_cmd & (ICE1712_AC97_WRITE | ICE1712_AC97_READ)) - continue; - if (!(old_cmd & ICE1712_AC97_READY)) - continue; - break; - } - outb(reg, ICEREG(ice, AC97_INDEX)); - outw(val, ICEREG(ice, AC97_DATA)); - old_cmd &= ~(ICE1712_AC97_PBK_VSR | ICE1712_AC97_CAP_VSR); - outb(old_cmd | ICE1712_AC97_WRITE, ICEREG(ice, AC97_CMD)); - for (tm = 0; tm < 0x10000; tm++) - if ((inb(ICEREG(ice, AC97_CMD)) & ICE1712_AC97_WRITE) == 0) - break; -} - -static unsigned short snd_ice1712_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct snd_ice1712 *ice = ac97->private_data; - int tm; - unsigned char old_cmd = 0; - - for (tm = 0; tm < 0x10000; tm++) { - old_cmd = inb(ICEREG(ice, AC97_CMD)); - if (old_cmd & (ICE1712_AC97_WRITE | ICE1712_AC97_READ)) - continue; - if (!(old_cmd & ICE1712_AC97_READY)) - continue; - break; - } - outb(reg, ICEREG(ice, AC97_INDEX)); - outb(old_cmd | ICE1712_AC97_READ, ICEREG(ice, AC97_CMD)); - for (tm = 0; tm < 0x10000; tm++) - if ((inb(ICEREG(ice, AC97_CMD)) & ICE1712_AC97_READ) == 0) - break; - if (tm >= 0x10000) /* timeout */ - return ~0; - return inw(ICEREG(ice, AC97_DATA)); -} - -/* - * pro ac97 section - */ - -static void snd_ice1712_pro_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct snd_ice1712 *ice = ac97->private_data; - int tm; - unsigned char old_cmd = 0; - - for (tm = 0; tm < 0x10000; tm++) { - old_cmd = inb(ICEMT(ice, AC97_CMD)); - if (old_cmd & (ICE1712_AC97_WRITE | ICE1712_AC97_READ)) - continue; - if (!(old_cmd & ICE1712_AC97_READY)) - continue; - break; - } - outb(reg, ICEMT(ice, AC97_INDEX)); - outw(val, ICEMT(ice, AC97_DATA)); - old_cmd &= ~(ICE1712_AC97_PBK_VSR | ICE1712_AC97_CAP_VSR); - outb(old_cmd | ICE1712_AC97_WRITE, ICEMT(ice, AC97_CMD)); - for (tm = 0; tm < 0x10000; tm++) - if ((inb(ICEMT(ice, AC97_CMD)) & ICE1712_AC97_WRITE) == 0) - break; -} - - -static unsigned short snd_ice1712_pro_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct snd_ice1712 *ice = ac97->private_data; - int tm; - unsigned char old_cmd = 0; - - for (tm = 0; tm < 0x10000; tm++) { - old_cmd = inb(ICEMT(ice, AC97_CMD)); - if (old_cmd & (ICE1712_AC97_WRITE | ICE1712_AC97_READ)) - continue; - if (!(old_cmd & ICE1712_AC97_READY)) - continue; - break; - } - outb(reg, ICEMT(ice, AC97_INDEX)); - outb(old_cmd | ICE1712_AC97_READ, ICEMT(ice, AC97_CMD)); - for (tm = 0; tm < 0x10000; tm++) - if ((inb(ICEMT(ice, AC97_CMD)) & ICE1712_AC97_READ) == 0) - break; - if (tm >= 0x10000) /* timeout */ - return ~0; - return inw(ICEMT(ice, AC97_DATA)); -} - -/* - * consumer ac97 digital mix - */ -#define snd_ice1712_digmix_route_ac97_info snd_ctl_boolean_mono_info - -static int snd_ice1712_digmix_route_ac97_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = inb(ICEMT(ice, MONITOR_ROUTECTRL)) & ICE1712_ROUTE_AC97 ? 1 : 0; - return 0; -} - -static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val, nval; - - spin_lock_irq(&ice->reg_lock); - val = inb(ICEMT(ice, MONITOR_ROUTECTRL)); - nval = val & ~ICE1712_ROUTE_AC97; - if (ucontrol->value.integer.value[0]) - nval |= ICE1712_ROUTE_AC97; - outb(nval, ICEMT(ice, MONITOR_ROUTECTRL)); - spin_unlock_irq(&ice->reg_lock); - return val != nval; -} - -static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Mixer To AC97", - .info = snd_ice1712_digmix_route_ac97_info, - .get = snd_ice1712_digmix_route_ac97_get, - .put = snd_ice1712_digmix_route_ac97_put, -}; - - -/* - * gpio operations - */ -static void snd_ice1712_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) -{ - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, data); - inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ -} - -static unsigned int snd_ice1712_get_gpio_dir(struct snd_ice1712 *ice) -{ - return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION); -} - -static unsigned int snd_ice1712_get_gpio_mask(struct snd_ice1712 *ice) -{ - return snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK); -} - -static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) -{ - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); - inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ -} - -static unsigned int snd_ice1712_get_gpio_data(struct snd_ice1712 *ice) -{ - return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA); -} - -static void snd_ice1712_set_gpio_data(struct snd_ice1712 *ice, unsigned int val) -{ - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, val); - inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ -} - -/* - * - * CS8427 interface - * - */ - -/* - * change the input clock selection - * spdif_clock = 1 - IEC958 input, 0 - Envy24 - */ -static int snd_ice1712_cs8427_set_input_clock(struct snd_ice1712 *ice, int spdif_clock) -{ - unsigned char reg[2] = { 0x80 | 4, 0 }; /* CS8427 auto increment | register number 4 + data */ - unsigned char val, nval; - int res = 0; - - snd_i2c_lock(ice->i2c); - if (snd_i2c_sendbytes(ice->cs8427, reg, 1) != 1) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - if (snd_i2c_readbytes(ice->cs8427, &val, 1) != 1) { - snd_i2c_unlock(ice->i2c); - return -EIO; - } - nval = val & 0xf0; - if (spdif_clock) - nval |= 0x01; - else - nval |= 0x04; - if (val != nval) { - reg[1] = nval; - if (snd_i2c_sendbytes(ice->cs8427, reg, 2) != 2) { - res = -EIO; - } else { - res++; - } - } - snd_i2c_unlock(ice->i2c); - return res; -} - -/* - * spdif callbacks - */ -static void open_cs8427(struct snd_ice1712 *ice, struct snd_pcm_substream *substream) -{ - snd_cs8427_iec958_active(ice->cs8427, 1); -} - -static void close_cs8427(struct snd_ice1712 *ice, struct snd_pcm_substream *substream) -{ - snd_cs8427_iec958_active(ice->cs8427, 0); -} - -static void setup_cs8427(struct snd_ice1712 *ice, int rate) -{ - snd_cs8427_iec958_pcm(ice->cs8427, rate); -} - -/* - * create and initialize callbacks for cs8427 interface - */ -int __devinit snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr) -{ - int err; - - err = snd_cs8427_create(ice->i2c, addr, - (ice->cs8427_timeout * HZ) / 1000, &ice->cs8427); - if (err < 0) { - snd_printk(KERN_ERR "CS8427 initialization failed\n"); - return err; - } - ice->spdif.ops.open = open_cs8427; - ice->spdif.ops.close = close_cs8427; - ice->spdif.ops.setup_rate = setup_cs8427; - return 0; -} - -static void snd_ice1712_set_input_clock_source(struct snd_ice1712 *ice, int spdif_is_master) -{ - /* change CS8427 clock source too */ - if (ice->cs8427) - snd_ice1712_cs8427_set_input_clock(ice, spdif_is_master); - /* notify ak4524 chip as well */ - if (spdif_is_master) { - unsigned int i; - for (i = 0; i < ice->akm_codecs; i++) { - if (ice->akm[i].ops.set_rate_val) - ice->akm[i].ops.set_rate_val(&ice->akm[i], 0); - } - } -} - -/* - * Interrupt handler - */ - -static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id) -{ - struct snd_ice1712 *ice = dev_id; - unsigned char status; - int handled = 0; - - while (1) { - status = inb(ICEREG(ice, IRQSTAT)); - if (status == 0) - break; - handled = 1; - if (status & ICE1712_IRQ_MPU1) { - if (ice->rmidi[0]) - snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data); - outb(ICE1712_IRQ_MPU1, ICEREG(ice, IRQSTAT)); - status &= ~ICE1712_IRQ_MPU1; - } - if (status & ICE1712_IRQ_TIMER) - outb(ICE1712_IRQ_TIMER, ICEREG(ice, IRQSTAT)); - if (status & ICE1712_IRQ_MPU2) { - if (ice->rmidi[1]) - snd_mpu401_uart_interrupt(irq, ice->rmidi[1]->private_data); - outb(ICE1712_IRQ_MPU2, ICEREG(ice, IRQSTAT)); - status &= ~ICE1712_IRQ_MPU2; - } - if (status & ICE1712_IRQ_PROPCM) { - unsigned char mtstat = inb(ICEMT(ice, IRQ)); - if (mtstat & ICE1712_MULTI_PBKSTATUS) { - if (ice->playback_pro_substream) - snd_pcm_period_elapsed(ice->playback_pro_substream); - outb(ICE1712_MULTI_PBKSTATUS, ICEMT(ice, IRQ)); - } - if (mtstat & ICE1712_MULTI_CAPSTATUS) { - if (ice->capture_pro_substream) - snd_pcm_period_elapsed(ice->capture_pro_substream); - outb(ICE1712_MULTI_CAPSTATUS, ICEMT(ice, IRQ)); - } - } - if (status & ICE1712_IRQ_FM) - outb(ICE1712_IRQ_FM, ICEREG(ice, IRQSTAT)); - if (status & ICE1712_IRQ_PBKDS) { - u32 idx; - u16 pbkstatus; - struct snd_pcm_substream *substream; - pbkstatus = inw(ICEDS(ice, INTSTAT)); - /* printk(KERN_DEBUG "pbkstatus = 0x%x\n", pbkstatus); */ - for (idx = 0; idx < 6; idx++) { - if ((pbkstatus & (3 << (idx * 2))) == 0) - continue; - substream = ice->playback_con_substream_ds[idx]; - if (substream != NULL) - snd_pcm_period_elapsed(substream); - outw(3 << (idx * 2), ICEDS(ice, INTSTAT)); - } - outb(ICE1712_IRQ_PBKDS, ICEREG(ice, IRQSTAT)); - } - if (status & ICE1712_IRQ_CONCAP) { - if (ice->capture_con_substream) - snd_pcm_period_elapsed(ice->capture_con_substream); - outb(ICE1712_IRQ_CONCAP, ICEREG(ice, IRQSTAT)); - } - if (status & ICE1712_IRQ_CONPBK) { - if (ice->playback_con_substream) - snd_pcm_period_elapsed(ice->playback_con_substream); - outb(ICE1712_IRQ_CONPBK, ICEREG(ice, IRQSTAT)); - } - } - return IRQ_RETVAL(handled); -} - - -/* - * PCM part - misc - */ - -static int snd_ice1712_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_ice1712_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -/* - * PCM part - consumer I/O - */ - -static int snd_ice1712_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - int result = 0; - u32 tmp; - - spin_lock(&ice->reg_lock); - tmp = snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL); - if (cmd == SNDRV_PCM_TRIGGER_START) { - tmp |= 1; - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - tmp &= ~1; - } else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) { - tmp |= 2; - } else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) { - tmp &= ~2; - } else { - result = -EINVAL; - } - snd_ice1712_write(ice, ICE1712_IREG_PBK_CTRL, tmp); - spin_unlock(&ice->reg_lock); - return result; -} - -static int snd_ice1712_playback_ds_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - int result = 0; - u32 tmp; - - spin_lock(&ice->reg_lock); - tmp = snd_ice1712_ds_read(ice, substream->number * 2, ICE1712_DSC_CONTROL); - if (cmd == SNDRV_PCM_TRIGGER_START) { - tmp |= 1; - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - tmp &= ~1; - } else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) { - tmp |= 2; - } else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) { - tmp &= ~2; - } else { - result = -EINVAL; - } - snd_ice1712_ds_write(ice, substream->number * 2, ICE1712_DSC_CONTROL, tmp); - spin_unlock(&ice->reg_lock); - return result; -} - -static int snd_ice1712_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - int result = 0; - u8 tmp; - - spin_lock(&ice->reg_lock); - tmp = snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL); - if (cmd == SNDRV_PCM_TRIGGER_START) { - tmp |= 1; - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - tmp &= ~1; - } else { - result = -EINVAL; - } - snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp); - spin_unlock(&ice->reg_lock); - return result; -} - -static int snd_ice1712_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - u32 period_size, buf_size, rate, tmp; - - period_size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1; - buf_size = snd_pcm_lib_buffer_bytes(substream) - 1; - tmp = 0x0000; - if (snd_pcm_format_width(runtime->format) == 16) - tmp |= 0x10; - if (runtime->channels == 2) - tmp |= 0x08; - rate = (runtime->rate * 8192) / 375; - if (rate > 0x000fffff) - rate = 0x000fffff; - spin_lock_irq(&ice->reg_lock); - outb(0, ice->ddma_port + 15); - outb(ICE1712_DMA_MODE_WRITE | ICE1712_DMA_AUTOINIT, ice->ddma_port + 0x0b); - outl(runtime->dma_addr, ice->ddma_port + 0); - outw(buf_size, ice->ddma_port + 4); - snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_LO, rate & 0xff); - snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_MID, (rate >> 8) & 0xff); - snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_HI, (rate >> 16) & 0xff); - snd_ice1712_write(ice, ICE1712_IREG_PBK_CTRL, tmp); - snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_LO, period_size & 0xff); - snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_HI, period_size >> 8); - snd_ice1712_write(ice, ICE1712_IREG_PBK_LEFT, 0); - snd_ice1712_write(ice, ICE1712_IREG_PBK_RIGHT, 0); - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static int snd_ice1712_playback_ds_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - u32 period_size, buf_size, rate, tmp, chn; - - period_size = snd_pcm_lib_period_bytes(substream) - 1; - buf_size = snd_pcm_lib_buffer_bytes(substream) - 1; - tmp = 0x0064; - if (snd_pcm_format_width(runtime->format) == 16) - tmp &= ~0x04; - if (runtime->channels == 2) - tmp |= 0x08; - rate = (runtime->rate * 8192) / 375; - if (rate > 0x000fffff) - rate = 0x000fffff; - ice->playback_con_active_buf[substream->number] = 0; - ice->playback_con_virt_addr[substream->number] = runtime->dma_addr; - chn = substream->number * 2; - spin_lock_irq(&ice->reg_lock); - snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR0, runtime->dma_addr); - snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT0, period_size); - snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR1, runtime->dma_addr + (runtime->periods > 1 ? period_size + 1 : 0)); - snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT1, period_size); - snd_ice1712_ds_write(ice, chn, ICE1712_DSC_RATE, rate); - snd_ice1712_ds_write(ice, chn, ICE1712_DSC_VOLUME, 0); - snd_ice1712_ds_write(ice, chn, ICE1712_DSC_CONTROL, tmp); - if (runtime->channels == 2) { - snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_RATE, rate); - snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_VOLUME, 0); - } - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static int snd_ice1712_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - u32 period_size, buf_size; - u8 tmp; - - period_size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1; - buf_size = snd_pcm_lib_buffer_bytes(substream) - 1; - tmp = 0x06; - if (snd_pcm_format_width(runtime->format) == 16) - tmp &= ~0x04; - if (runtime->channels == 2) - tmp &= ~0x02; - spin_lock_irq(&ice->reg_lock); - outl(ice->capture_con_virt_addr = runtime->dma_addr, ICEREG(ice, CONCAP_ADDR)); - outw(buf_size, ICEREG(ice, CONCAP_COUNT)); - snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_HI, period_size >> 8); - snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_LO, period_size & 0xff); - snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp); - spin_unlock_irq(&ice->reg_lock); - snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); - return 0; -} - -static snd_pcm_uframes_t snd_ice1712_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - size_t ptr; - - if (!(snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL) & 1)) - return 0; - ptr = runtime->buffer_size - inw(ice->ddma_port + 4); - if (ptr == runtime->buffer_size) - ptr = 0; - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_ice1712_playback_ds_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - u8 addr; - size_t ptr; - - if (!(snd_ice1712_ds_read(ice, substream->number * 2, ICE1712_DSC_CONTROL) & 1)) - return 0; - if (ice->playback_con_active_buf[substream->number]) - addr = ICE1712_DSC_ADDR1; - else - addr = ICE1712_DSC_ADDR0; - ptr = snd_ice1712_ds_read(ice, substream->number * 2, addr) - - ice->playback_con_virt_addr[substream->number]; - if (ptr == substream->runtime->buffer_size) - ptr = 0; - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_ice1712_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL) & 1)) - return 0; - ptr = inl(ICEREG(ice, CONCAP_ADDR)) - ice->capture_con_virt_addr; - if (ptr == substream->runtime->buffer_size) - ptr = 0; - return bytes_to_frames(substream->runtime, ptr); -} - -static const struct snd_pcm_hardware snd_ice1712_playback = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 64, - .period_bytes_max = (64*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static const struct snd_pcm_hardware snd_ice1712_playback_ds = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static const struct snd_pcm_hardware snd_ice1712_capture = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 64, - .period_bytes_max = (64*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_ice1712_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - ice->playback_con_substream = substream; - runtime->hw = snd_ice1712_playback; - return 0; -} - -static int snd_ice1712_playback_ds_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - u32 tmp; - - ice->playback_con_substream_ds[substream->number] = substream; - runtime->hw = snd_ice1712_playback_ds; - spin_lock_irq(&ice->reg_lock); - tmp = inw(ICEDS(ice, INTMASK)) & ~(1 << (substream->number * 2)); - outw(tmp, ICEDS(ice, INTMASK)); - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static int snd_ice1712_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - ice->capture_con_substream = substream; - runtime->hw = snd_ice1712_capture; - runtime->hw.rates = ice->ac97->rates[AC97_RATES_ADC]; - if (!(runtime->hw.rates & SNDRV_PCM_RATE_8000)) - runtime->hw.rate_min = 48000; - return 0; -} - -static int snd_ice1712_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - ice->playback_con_substream = NULL; - return 0; -} - -static int snd_ice1712_playback_ds_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - u32 tmp; - - spin_lock_irq(&ice->reg_lock); - tmp = inw(ICEDS(ice, INTMASK)) | (3 << (substream->number * 2)); - outw(tmp, ICEDS(ice, INTMASK)); - spin_unlock_irq(&ice->reg_lock); - ice->playback_con_substream_ds[substream->number] = NULL; - return 0; -} - -static int snd_ice1712_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - ice->capture_con_substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_ice1712_playback_ops = { - .open = snd_ice1712_playback_open, - .close = snd_ice1712_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ice1712_hw_params, - .hw_free = snd_ice1712_hw_free, - .prepare = snd_ice1712_playback_prepare, - .trigger = snd_ice1712_playback_trigger, - .pointer = snd_ice1712_playback_pointer, -}; - -static struct snd_pcm_ops snd_ice1712_playback_ds_ops = { - .open = snd_ice1712_playback_ds_open, - .close = snd_ice1712_playback_ds_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ice1712_hw_params, - .hw_free = snd_ice1712_hw_free, - .prepare = snd_ice1712_playback_ds_prepare, - .trigger = snd_ice1712_playback_ds_trigger, - .pointer = snd_ice1712_playback_ds_pointer, -}; - -static struct snd_pcm_ops snd_ice1712_capture_ops = { - .open = snd_ice1712_capture_open, - .close = snd_ice1712_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ice1712_hw_params, - .hw_free = snd_ice1712_hw_free, - .prepare = snd_ice1712_capture_prepare, - .trigger = snd_ice1712_capture_trigger, - .pointer = snd_ice1712_capture_pointer, -}; - -static int __devinit snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - err = snd_pcm_new(ice->card, "ICE1712 consumer", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ice1712_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ice1712_capture_ops); - - pcm->private_data = ice; - pcm->info_flags = 0; - strcpy(pcm->name, "ICE1712 consumer"); - ice->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(ice->pci), 64*1024, 64*1024); - - if (rpcm) - *rpcm = pcm; - - printk(KERN_WARNING "Consumer PCM code does not work well at the moment --jk\n"); - - return 0; -} - -static int __devinit snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - err = snd_pcm_new(ice->card, "ICE1712 consumer (DS)", device, 6, 0, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ice1712_playback_ds_ops); - - pcm->private_data = ice; - pcm->info_flags = 0; - strcpy(pcm->name, "ICE1712 consumer (DS)"); - ice->pcm_ds = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(ice->pci), 64*1024, 128*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -/* - * PCM code - professional part (multitrack) - */ - -static unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000, - 32000, 44100, 48000, 64000, 88200, 96000 }; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static int snd_ice1712_pro_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - { - unsigned int what; - unsigned int old; - if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) - return -EINVAL; - what = ICE1712_PLAYBACK_PAUSE; - snd_pcm_trigger_done(substream, substream); - spin_lock(&ice->reg_lock); - old = inl(ICEMT(ice, PLAYBACK_CONTROL)); - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) - old |= what; - else - old &= ~what; - outl(old, ICEMT(ice, PLAYBACK_CONTROL)); - spin_unlock(&ice->reg_lock); - break; - } - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_STOP: - { - unsigned int what = 0; - unsigned int old; - struct snd_pcm_substream *s; - - snd_pcm_group_for_each_entry(s, substream) { - if (s == ice->playback_pro_substream) { - what |= ICE1712_PLAYBACK_START; - snd_pcm_trigger_done(s, substream); - } else if (s == ice->capture_pro_substream) { - what |= ICE1712_CAPTURE_START_SHADOW; - snd_pcm_trigger_done(s, substream); - } - } - spin_lock(&ice->reg_lock); - old = inl(ICEMT(ice, PLAYBACK_CONTROL)); - if (cmd == SNDRV_PCM_TRIGGER_START) - old |= what; - else - old &= ~what; - outl(old, ICEMT(ice, PLAYBACK_CONTROL)); - spin_unlock(&ice->reg_lock); - break; - } - default: - return -EINVAL; - } - return 0; -} - -/* - */ -static void snd_ice1712_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, int force) -{ - unsigned long flags; - unsigned char val, old; - unsigned int i; - - switch (rate) { - case 8000: val = 6; break; - case 9600: val = 3; break; - case 11025: val = 10; break; - case 12000: val = 2; break; - case 16000: val = 5; break; - case 22050: val = 9; break; - case 24000: val = 1; break; - case 32000: val = 4; break; - case 44100: val = 8; break; - case 48000: val = 0; break; - case 64000: val = 15; break; - case 88200: val = 11; break; - case 96000: val = 7; break; - default: - snd_BUG(); - val = 0; - rate = 48000; - break; - } - - spin_lock_irqsave(&ice->reg_lock, flags); - if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW| - ICE1712_PLAYBACK_PAUSE| - ICE1712_PLAYBACK_START)) { -__out: - spin_unlock_irqrestore(&ice->reg_lock, flags); - return; - } - if (!force && is_pro_rate_locked(ice)) - goto __out; - - old = inb(ICEMT(ice, RATE)); - if (!force && old == val) - goto __out; - outb(val, ICEMT(ice, RATE)); - spin_unlock_irqrestore(&ice->reg_lock, flags); - - if (ice->gpio.set_pro_rate) - ice->gpio.set_pro_rate(ice, rate); - for (i = 0; i < ice->akm_codecs; i++) { - if (ice->akm[i].ops.set_rate_val) - ice->akm[i].ops.set_rate_val(&ice->akm[i], rate); - } - if (ice->spdif.ops.setup_rate) - ice->spdif.ops.setup_rate(ice, rate); -} - -static int snd_ice1712_playback_pro_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - ice->playback_pro_size = snd_pcm_lib_buffer_bytes(substream); - spin_lock_irq(&ice->reg_lock); - outl(substream->runtime->dma_addr, ICEMT(ice, PLAYBACK_ADDR)); - outw((ice->playback_pro_size >> 2) - 1, ICEMT(ice, PLAYBACK_SIZE)); - outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, PLAYBACK_COUNT)); - spin_unlock_irq(&ice->reg_lock); - - return 0; -} - -static int snd_ice1712_playback_pro_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - snd_ice1712_set_pro_rate(ice, params_rate(hw_params), 0); - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_ice1712_capture_pro_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - ice->capture_pro_size = snd_pcm_lib_buffer_bytes(substream); - spin_lock_irq(&ice->reg_lock); - outl(substream->runtime->dma_addr, ICEMT(ice, CAPTURE_ADDR)); - outw((ice->capture_pro_size >> 2) - 1, ICEMT(ice, CAPTURE_SIZE)); - outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, CAPTURE_COUNT)); - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static int snd_ice1712_capture_pro_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - snd_ice1712_set_pro_rate(ice, params_rate(hw_params), 0); - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static snd_pcm_uframes_t snd_ice1712_playback_pro_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(inl(ICEMT(ice, PLAYBACK_CONTROL)) & ICE1712_PLAYBACK_START)) - return 0; - ptr = ice->playback_pro_size - (inw(ICEMT(ice, PLAYBACK_SIZE)) << 2); - if (ptr == substream->runtime->buffer_size) - ptr = 0; - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_ice1712_capture_pro_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(inl(ICEMT(ice, PLAYBACK_CONTROL)) & ICE1712_CAPTURE_START_SHADOW)) - return 0; - ptr = ice->capture_pro_size - (inw(ICEMT(ice, CAPTURE_SIZE)) << 2); - if (ptr == substream->runtime->buffer_size) - ptr = 0; - return bytes_to_frames(substream->runtime, ptr); -} - -static const struct snd_pcm_hardware snd_ice1712_playback_pro = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_96000, - .rate_min = 4000, - .rate_max = 96000, - .channels_min = 10, - .channels_max = 10, - .buffer_bytes_max = (256*1024), - .period_bytes_min = 10 * 4 * 2, - .period_bytes_max = 131040, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static const struct snd_pcm_hardware snd_ice1712_capture_pro = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_96000, - .rate_min = 4000, - .rate_max = 96000, - .channels_min = 12, - .channels_max = 12, - .buffer_bytes_max = (256*1024), - .period_bytes_min = 12 * 4 * 2, - .period_bytes_max = 131040, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_ice1712_playback_pro_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - ice->playback_pro_substream = substream; - runtime->hw = snd_ice1712_playback_pro; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - if (is_pro_rate_locked(ice)) { - runtime->hw.rate_min = PRO_RATE_DEFAULT; - runtime->hw.rate_max = PRO_RATE_DEFAULT; - } - - if (ice->spdif.ops.open) - ice->spdif.ops.open(ice, substream); - - return 0; -} - -static int snd_ice1712_capture_pro_open(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - ice->capture_pro_substream = substream; - runtime->hw = snd_ice1712_capture_pro; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - if (is_pro_rate_locked(ice)) { - runtime->hw.rate_min = PRO_RATE_DEFAULT; - runtime->hw.rate_max = PRO_RATE_DEFAULT; - } - - return 0; -} - -static int snd_ice1712_playback_pro_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - if (PRO_RATE_RESET) - snd_ice1712_set_pro_rate(ice, PRO_RATE_DEFAULT, 0); - ice->playback_pro_substream = NULL; - if (ice->spdif.ops.close) - ice->spdif.ops.close(ice, substream); - - return 0; -} - -static int snd_ice1712_capture_pro_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - if (PRO_RATE_RESET) - snd_ice1712_set_pro_rate(ice, PRO_RATE_DEFAULT, 0); - ice->capture_pro_substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_ice1712_playback_pro_ops = { - .open = snd_ice1712_playback_pro_open, - .close = snd_ice1712_playback_pro_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ice1712_playback_pro_hw_params, - .hw_free = snd_ice1712_hw_free, - .prepare = snd_ice1712_playback_pro_prepare, - .trigger = snd_ice1712_pro_trigger, - .pointer = snd_ice1712_playback_pro_pointer, -}; - -static struct snd_pcm_ops snd_ice1712_capture_pro_ops = { - .open = snd_ice1712_capture_pro_open, - .close = snd_ice1712_capture_pro_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ice1712_capture_pro_hw_params, - .hw_free = snd_ice1712_hw_free, - .prepare = snd_ice1712_capture_pro_prepare, - .trigger = snd_ice1712_pro_trigger, - .pointer = snd_ice1712_capture_pro_pointer, -}; - -static int __devinit snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - err = snd_pcm_new(ice->card, "ICE1712 multi", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ice1712_playback_pro_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ice1712_capture_pro_ops); - - pcm->private_data = ice; - pcm->info_flags = 0; - strcpy(pcm->name, "ICE1712 multi"); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(ice->pci), 256*1024, 256*1024); - - ice->pcm_pro = pcm; - if (rpcm) - *rpcm = pcm; - - if (ice->cs8427) { - /* assign channels to iec958 */ - err = snd_cs8427_iec958_build(ice->cs8427, - pcm->streams[0].substream, - pcm->streams[1].substream); - if (err < 0) - return err; - } - - err = snd_ice1712_build_pro_mixer(ice); - if (err < 0) - return err; - return 0; -} - -/* - * Mixer section - */ - -static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index) -{ - unsigned int vol = ice->pro_volumes[index]; - unsigned short val = 0; - - val |= (vol & 0x8000) == 0 ? (96 - (vol & 0x7f)) : 0x7f; - val |= ((vol & 0x80000000) == 0 ? (96 - ((vol >> 16) & 0x7f)) : 0x7f) << 8; - outb(index, ICEMT(ice, MONITOR_INDEX)); - outw(val, ICEMT(ice, MONITOR_VOLUME)); -} - -#define snd_ice1712_pro_mixer_switch_info snd_ctl_boolean_stereo_info - -static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + - kcontrol->private_value; - - spin_lock_irq(&ice->reg_lock); - ucontrol->value.integer.value[0] = - !((ice->pro_volumes[priv_idx] >> 15) & 1); - ucontrol->value.integer.value[1] = - !((ice->pro_volumes[priv_idx] >> 31) & 1); - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static int snd_ice1712_pro_mixer_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + - kcontrol->private_value; - unsigned int nval, change; - - nval = (ucontrol->value.integer.value[0] ? 0 : 0x00008000) | - (ucontrol->value.integer.value[1] ? 0 : 0x80000000); - spin_lock_irq(&ice->reg_lock); - nval |= ice->pro_volumes[priv_idx] & ~0x80008000; - change = nval != ice->pro_volumes[priv_idx]; - ice->pro_volumes[priv_idx] = nval; - snd_ice1712_update_volume(ice, priv_idx); - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static int snd_ice1712_pro_mixer_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 96; - return 0; -} - -static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + - kcontrol->private_value; - - spin_lock_irq(&ice->reg_lock); - ucontrol->value.integer.value[0] = - (ice->pro_volumes[priv_idx] >> 0) & 127; - ucontrol->value.integer.value[1] = - (ice->pro_volumes[priv_idx] >> 16) & 127; - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int priv_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + - kcontrol->private_value; - unsigned int nval, change; - - nval = (ucontrol->value.integer.value[0] & 127) | - ((ucontrol->value.integer.value[1] & 127) << 16); - spin_lock_irq(&ice->reg_lock); - nval |= ice->pro_volumes[priv_idx] & ~0x007f007f; - change = nval != ice->pro_volumes[priv_idx]; - ice->pro_volumes[priv_idx] = nval; - snd_ice1712_update_volume(ice, priv_idx); - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0); - -static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Playback Switch", - .info = snd_ice1712_pro_mixer_switch_info, - .get = snd_ice1712_pro_mixer_switch_get, - .put = snd_ice1712_pro_mixer_switch_put, - .private_value = 0, - .count = 10, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Multi Playback Volume", - .info = snd_ice1712_pro_mixer_volume_info, - .get = snd_ice1712_pro_mixer_volume_get, - .put = snd_ice1712_pro_mixer_volume_put, - .private_value = 0, - .count = 10, - .tlv = { .p = db_scale_playback } - }, -}; - -static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "H/W Multi Capture Switch", - .info = snd_ice1712_pro_mixer_switch_info, - .get = snd_ice1712_pro_mixer_switch_get, - .put = snd_ice1712_pro_mixer_switch_put, - .private_value = 10, -}; - -static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Multi ", CAPTURE, SWITCH), - .info = snd_ice1712_pro_mixer_switch_info, - .get = snd_ice1712_pro_mixer_switch_get, - .put = snd_ice1712_pro_mixer_switch_put, - .private_value = 18, - .count = 2, -}; - -static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "H/W Multi Capture Volume", - .info = snd_ice1712_pro_mixer_volume_info, - .get = snd_ice1712_pro_mixer_volume_get, - .put = snd_ice1712_pro_mixer_volume_put, - .private_value = 10, - .tlv = { .p = db_scale_playback } -}; - -static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Multi ", CAPTURE, VOLUME), - .info = snd_ice1712_pro_mixer_volume_info, - .get = snd_ice1712_pro_mixer_volume_get, - .put = snd_ice1712_pro_mixer_volume_put, - .private_value = 18, - .count = 2, -}; - -static int __devinit snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice) -{ - struct snd_card *card = ice->card; - unsigned int idx; - int err; - - /* multi-channel mixer */ - for (idx = 0; idx < ARRAY_SIZE(snd_ice1712_multi_playback_ctrls); idx++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_ice1712_multi_playback_ctrls[idx], ice)); - if (err < 0) - return err; - } - - if (ice->num_total_adcs > 0) { - struct snd_kcontrol_new tmp = snd_ice1712_multi_capture_analog_switch; - tmp.count = ice->num_total_adcs; - err = snd_ctl_add(card, snd_ctl_new1(&tmp, ice)); - if (err < 0) - return err; - } - - err = snd_ctl_add(card, snd_ctl_new1(&snd_ice1712_multi_capture_spdif_switch, ice)); - if (err < 0) - return err; - - if (ice->num_total_adcs > 0) { - struct snd_kcontrol_new tmp = snd_ice1712_multi_capture_analog_volume; - tmp.count = ice->num_total_adcs; - err = snd_ctl_add(card, snd_ctl_new1(&tmp, ice)); - if (err < 0) - return err; - } - - err = snd_ctl_add(card, snd_ctl_new1(&snd_ice1712_multi_capture_spdif_volume, ice)); - if (err < 0) - return err; - - /* initialize volumes */ - for (idx = 0; idx < 10; idx++) { - ice->pro_volumes[idx] = 0x80008000; /* mute */ - snd_ice1712_update_volume(ice, idx); - } - for (idx = 10; idx < 10 + ice->num_total_adcs; idx++) { - ice->pro_volumes[idx] = 0x80008000; /* mute */ - snd_ice1712_update_volume(ice, idx); - } - for (idx = 18; idx < 20; idx++) { - ice->pro_volumes[idx] = 0x80008000; /* mute */ - snd_ice1712_update_volume(ice, idx); - } - return 0; -} - -static void snd_ice1712_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct snd_ice1712 *ice = ac97->private_data; - ice->ac97 = NULL; -} - -static int __devinit snd_ice1712_ac97_mixer(struct snd_ice1712 *ice) -{ - int err, bus_num = 0; - struct snd_ac97_template ac97; - struct snd_ac97_bus *pbus; - static struct snd_ac97_bus_ops con_ops = { - .write = snd_ice1712_ac97_write, - .read = snd_ice1712_ac97_read, - }; - static struct snd_ac97_bus_ops pro_ops = { - .write = snd_ice1712_pro_ac97_write, - .read = snd_ice1712_pro_ac97_read, - }; - - if (ice_has_con_ac97(ice)) { - err = snd_ac97_bus(ice->card, bus_num++, &con_ops, NULL, &pbus); - if (err < 0) - return err; - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = ice; - ac97.private_free = snd_ice1712_mixer_free_ac97; - err = snd_ac97_mixer(pbus, &ac97, &ice->ac97); - if (err < 0) - printk(KERN_WARNING "ice1712: cannot initialize ac97 for consumer, skipped\n"); - else { - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_digmix_route_ac97, ice)); - if (err < 0) - return err; - return 0; - } - } - - if (!(ice->eeprom.data[ICE_EEP1_ACLINK] & ICE1712_CFG_PRO_I2S)) { - err = snd_ac97_bus(ice->card, bus_num, &pro_ops, NULL, &pbus); - if (err < 0) - return err; - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = ice; - ac97.private_free = snd_ice1712_mixer_free_ac97; - err = snd_ac97_mixer(pbus, &ac97, &ice->ac97); - if (err < 0) - printk(KERN_WARNING "ice1712: cannot initialize pro ac97, skipped\n"); - else - return 0; - } - /* I2S mixer only */ - strcat(ice->card->mixername, "ICE1712 - multitrack"); - return 0; -} - -/* - * - */ - -static inline unsigned int eeprom_double(struct snd_ice1712 *ice, int idx) -{ - return (unsigned int)ice->eeprom.data[idx] | ((unsigned int)ice->eeprom.data[idx + 1] << 8); -} - -static void snd_ice1712_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - unsigned int idx; - - snd_iprintf(buffer, "%s\n\n", ice->card->longname); - snd_iprintf(buffer, "EEPROM:\n"); - - snd_iprintf(buffer, " Subvendor : 0x%x\n", ice->eeprom.subvendor); - snd_iprintf(buffer, " Size : %i bytes\n", ice->eeprom.size); - snd_iprintf(buffer, " Version : %i\n", ice->eeprom.version); - snd_iprintf(buffer, " Codec : 0x%x\n", ice->eeprom.data[ICE_EEP1_CODEC]); - snd_iprintf(buffer, " ACLink : 0x%x\n", ice->eeprom.data[ICE_EEP1_ACLINK]); - snd_iprintf(buffer, " I2S ID : 0x%x\n", ice->eeprom.data[ICE_EEP1_I2SID]); - snd_iprintf(buffer, " S/PDIF : 0x%x\n", ice->eeprom.data[ICE_EEP1_SPDIF]); - snd_iprintf(buffer, " GPIO mask : 0x%x\n", ice->eeprom.gpiomask); - snd_iprintf(buffer, " GPIO state : 0x%x\n", ice->eeprom.gpiostate); - snd_iprintf(buffer, " GPIO direction : 0x%x\n", ice->eeprom.gpiodir); - snd_iprintf(buffer, " AC'97 main : 0x%x\n", eeprom_double(ice, ICE_EEP1_AC97_MAIN_LO)); - snd_iprintf(buffer, " AC'97 pcm : 0x%x\n", eeprom_double(ice, ICE_EEP1_AC97_PCM_LO)); - snd_iprintf(buffer, " AC'97 record : 0x%x\n", eeprom_double(ice, ICE_EEP1_AC97_REC_LO)); - snd_iprintf(buffer, " AC'97 record src : 0x%x\n", ice->eeprom.data[ICE_EEP1_AC97_RECSRC]); - for (idx = 0; idx < 4; idx++) - snd_iprintf(buffer, " DAC ID #%i : 0x%x\n", idx, ice->eeprom.data[ICE_EEP1_DAC_ID + idx]); - for (idx = 0; idx < 4; idx++) - snd_iprintf(buffer, " ADC ID #%i : 0x%x\n", idx, ice->eeprom.data[ICE_EEP1_ADC_ID + idx]); - for (idx = 0x1c; idx < ice->eeprom.size; idx++) - snd_iprintf(buffer, " Extra #%02i : 0x%x\n", idx, ice->eeprom.data[idx]); - - snd_iprintf(buffer, "\nRegisters:\n"); - snd_iprintf(buffer, " PSDOUT03 : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_PSDOUT03))); - snd_iprintf(buffer, " CAPTURE : 0x%08x\n", inl(ICEMT(ice, ROUTE_CAPTURE))); - snd_iprintf(buffer, " SPDOUT : 0x%04x\n", (unsigned)inw(ICEMT(ice, ROUTE_SPDOUT))); - snd_iprintf(buffer, " RATE : 0x%02x\n", (unsigned)inb(ICEMT(ice, RATE))); - snd_iprintf(buffer, " GPIO_DATA : 0x%02x\n", (unsigned)snd_ice1712_get_gpio_data(ice)); - snd_iprintf(buffer, " GPIO_WRITE_MASK : 0x%02x\n", (unsigned)snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK)); - snd_iprintf(buffer, " GPIO_DIRECTION : 0x%02x\n", (unsigned)snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION)); -} - -static void __devinit snd_ice1712_proc_init(struct snd_ice1712 *ice) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(ice->card, "ice1712", &entry)) - snd_info_set_text_ops(entry, ice, snd_ice1712_proc_read); -} - -/* - * - */ - -static int snd_ice1712_eeprom_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = sizeof(struct snd_ice1712_eeprom); - return 0; -} - -static int snd_ice1712_eeprom_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - memcpy(ucontrol->value.bytes.data, &ice->eeprom, sizeof(ice->eeprom)); - return 0; -} - -static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "ICE1712 EEPROM", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_ice1712_eeprom_info, - .get = snd_ice1712_eeprom_get -}; - -/* - */ -static int snd_ice1712_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ice1712_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - if (ice->spdif.ops.default_get) - ice->spdif.ops.default_get(ice, ucontrol); - return 0; -} - -static int snd_ice1712_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - if (ice->spdif.ops.default_put) - return ice->spdif.ops.default_put(ice, ucontrol); - return 0; -} - -static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = snd_ice1712_spdif_info, - .get = snd_ice1712_spdif_default_get, - .put = snd_ice1712_spdif_default_put -}; - -static int snd_ice1712_spdif_maskc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - if (ice->spdif.ops.default_get) { - ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_CON_NOT_COPYRIGHT | - IEC958_AES0_CON_EMPHASIS; - ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL | - IEC958_AES1_CON_CATEGORY; - ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS; - } else { - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - ucontrol->value.iec958.status[4] = 0xff; - } - return 0; -} - -static int snd_ice1712_spdif_maskp_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - if (ice->spdif.ops.default_get) { - ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_PRO_FS | - IEC958_AES0_PRO_EMPHASIS; - ucontrol->value.iec958.status[1] = IEC958_AES1_PRO_MODE; - } else { - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - ucontrol->value.iec958.status[4] = 0xff; - } - return 0; -} - -static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), - .info = snd_ice1712_spdif_info, - .get = snd_ice1712_spdif_maskc_get, -}; - -static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), - .info = snd_ice1712_spdif_info, - .get = snd_ice1712_spdif_maskp_get, -}; - -static int snd_ice1712_spdif_stream_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - if (ice->spdif.ops.stream_get) - ice->spdif.ops.stream_get(ice, ucontrol); - return 0; -} - -static int snd_ice1712_spdif_stream_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - if (ice->spdif.ops.stream_put) - return ice->spdif.ops.stream_put(ice, ucontrol); - return 0; -} - -static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata = -{ - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_INACTIVE), - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), - .info = snd_ice1712_spdif_info, - .get = snd_ice1712_spdif_stream_get, - .put = snd_ice1712_spdif_stream_put -}; - -int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char mask = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value & (1<<24)) ? 1 : 0; - - snd_ice1712_save_gpio_status(ice); - ucontrol->value.integer.value[0] = - (snd_ice1712_gpio_read(ice) & mask ? 1 : 0) ^ invert; - snd_ice1712_restore_gpio_status(ice); - return 0; -} - -int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char mask = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value & (1<<24)) ? mask : 0; - unsigned int val, nval; - - if (kcontrol->private_value & (1 << 31)) - return -EPERM; - nval = (ucontrol->value.integer.value[0] ? mask : 0) ^ invert; - snd_ice1712_save_gpio_status(ice); - val = snd_ice1712_gpio_read(ice); - nval |= val & ~mask; - if (val != nval) - snd_ice1712_gpio_write(ice, nval); - snd_ice1712_restore_gpio_status(ice); - return val != nval; -} - -/* - * rate - */ -static int snd_ice1712_pro_internal_clock_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "8000", /* 0: 6 */ - "9600", /* 1: 3 */ - "11025", /* 2: 10 */ - "12000", /* 3: 2 */ - "16000", /* 4: 5 */ - "22050", /* 5: 9 */ - "24000", /* 6: 1 */ - "32000", /* 7: 4 */ - "44100", /* 8: 8 */ - "48000", /* 9: 0 */ - "64000", /* 10: 15 */ - "88200", /* 11: 11 */ - "96000", /* 12: 7 */ - "IEC958 Input", /* 13: -- */ - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 14; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ice1712_pro_internal_clock_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - static const unsigned char xlate[16] = { - 9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 255, 255, 255, 10 - }; - unsigned char val; - - spin_lock_irq(&ice->reg_lock); - if (is_spdif_master(ice)) { - ucontrol->value.enumerated.item[0] = 13; - } else { - val = xlate[inb(ICEMT(ice, RATE)) & 15]; - if (val == 255) { - snd_BUG(); - val = 0; - } - ucontrol->value.enumerated.item[0] = val; - } - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - static const unsigned int xrate[13] = { - 8000, 9600, 11025, 12000, 16000, 22050, 24000, - 32000, 44100, 48000, 64000, 88200, 96000 - }; - unsigned char oval; - int change = 0; - - spin_lock_irq(&ice->reg_lock); - oval = inb(ICEMT(ice, RATE)); - if (ucontrol->value.enumerated.item[0] == 13) { - outb(oval | ICE1712_SPDIF_MASTER, ICEMT(ice, RATE)); - } else { - PRO_RATE_DEFAULT = xrate[ucontrol->value.integer.value[0] % 13]; - spin_unlock_irq(&ice->reg_lock); - snd_ice1712_set_pro_rate(ice, PRO_RATE_DEFAULT, 1); - spin_lock_irq(&ice->reg_lock); - } - change = inb(ICEMT(ice, RATE)) != oval; - spin_unlock_irq(&ice->reg_lock); - - if ((oval & ICE1712_SPDIF_MASTER) != - (inb(ICEMT(ice, RATE)) & ICE1712_SPDIF_MASTER)) - snd_ice1712_set_input_clock_source(ice, is_spdif_master(ice)); - - return change; -} - -static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Track Internal Clock", - .info = snd_ice1712_pro_internal_clock_info, - .get = snd_ice1712_pro_internal_clock_get, - .put = snd_ice1712_pro_internal_clock_put -}; - -static int snd_ice1712_pro_internal_clock_default_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "8000", /* 0: 6 */ - "9600", /* 1: 3 */ - "11025", /* 2: 10 */ - "12000", /* 3: 2 */ - "16000", /* 4: 5 */ - "22050", /* 5: 9 */ - "24000", /* 6: 1 */ - "32000", /* 7: 4 */ - "44100", /* 8: 8 */ - "48000", /* 9: 0 */ - "64000", /* 10: 15 */ - "88200", /* 11: 11 */ - "96000", /* 12: 7 */ - /* "IEC958 Input", 13: -- */ - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 13; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ice1712_pro_internal_clock_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int val; - static const unsigned int xrate[13] = { - 8000, 9600, 11025, 12000, 16000, 22050, 24000, - 32000, 44100, 48000, 64000, 88200, 96000 - }; - - for (val = 0; val < 13; val++) { - if (xrate[val] == PRO_RATE_DEFAULT) - break; - } - - ucontrol->value.enumerated.item[0] = val; - return 0; -} - -static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - static const unsigned int xrate[13] = { - 8000, 9600, 11025, 12000, 16000, 22050, 24000, - 32000, 44100, 48000, 64000, 88200, 96000 - }; - unsigned char oval; - int change = 0; - - oval = PRO_RATE_DEFAULT; - PRO_RATE_DEFAULT = xrate[ucontrol->value.integer.value[0] % 13]; - change = PRO_RATE_DEFAULT != oval; - - return change; -} - -static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Track Internal Clock Default", - .info = snd_ice1712_pro_internal_clock_default_info, - .get = snd_ice1712_pro_internal_clock_default_get, - .put = snd_ice1712_pro_internal_clock_default_put -}; - -#define snd_ice1712_pro_rate_locking_info snd_ctl_boolean_mono_info - -static int snd_ice1712_pro_rate_locking_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = PRO_RATE_LOCKED; - return 0; -} - -static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int change = 0, nval; - - nval = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&ice->reg_lock); - change = PRO_RATE_LOCKED != nval; - PRO_RATE_LOCKED = nval; - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Track Rate Locking", - .info = snd_ice1712_pro_rate_locking_info, - .get = snd_ice1712_pro_rate_locking_get, - .put = snd_ice1712_pro_rate_locking_put -}; - -#define snd_ice1712_pro_rate_reset_info snd_ctl_boolean_mono_info - -static int snd_ice1712_pro_rate_reset_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = PRO_RATE_RESET; - return 0; -} - -static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int change = 0, nval; - - nval = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&ice->reg_lock); - change = PRO_RATE_RESET != nval; - PRO_RATE_RESET = nval; - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Track Rate Reset", - .info = snd_ice1712_pro_rate_reset_info, - .get = snd_ice1712_pro_rate_reset_get, - .put = snd_ice1712_pro_rate_reset_put -}; - -/* - * routing - */ -static int snd_ice1712_pro_route_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "PCM Out", /* 0 */ - "H/W In 0", "H/W In 1", "H/W In 2", "H/W In 3", /* 1-4 */ - "H/W In 4", "H/W In 5", "H/W In 6", "H/W In 7", /* 5-8 */ - "IEC958 In L", "IEC958 In R", /* 9-10 */ - "Digital Mixer", /* 11 - optional */ - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = - snd_ctl_get_ioffidx(kcontrol, &uinfo->id) < 2 ? 12 : 11; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ice1712_pro_route_analog_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned int val, cval; - - spin_lock_irq(&ice->reg_lock); - val = inw(ICEMT(ice, ROUTE_PSDOUT03)); - cval = inl(ICEMT(ice, ROUTE_CAPTURE)); - spin_unlock_irq(&ice->reg_lock); - - val >>= ((idx % 2) * 8) + ((idx / 2) * 2); - val &= 3; - cval >>= ((idx / 2) * 8) + ((idx % 2) * 4); - if (val == 1 && idx < 2) - ucontrol->value.enumerated.item[0] = 11; - else if (val == 2) - ucontrol->value.enumerated.item[0] = (cval & 7) + 1; - else if (val == 3) - ucontrol->value.enumerated.item[0] = ((cval >> 3) & 1) + 9; - else - ucontrol->value.enumerated.item[0] = 0; - return 0; -} - -static int snd_ice1712_pro_route_analog_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int change, shift; - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned int val, old_val, nval; - - /* update PSDOUT */ - if (ucontrol->value.enumerated.item[0] >= 11) - nval = idx < 2 ? 1 : 0; /* dig mixer (or pcm) */ - else if (ucontrol->value.enumerated.item[0] >= 9) - nval = 3; /* spdif in */ - else if (ucontrol->value.enumerated.item[0] >= 1) - nval = 2; /* analog in */ - else - nval = 0; /* pcm */ - shift = ((idx % 2) * 8) + ((idx / 2) * 2); - spin_lock_irq(&ice->reg_lock); - val = old_val = inw(ICEMT(ice, ROUTE_PSDOUT03)); - val &= ~(0x03 << shift); - val |= nval << shift; - change = val != old_val; - if (change) - outw(val, ICEMT(ice, ROUTE_PSDOUT03)); - spin_unlock_irq(&ice->reg_lock); - if (nval < 2) /* dig mixer of pcm */ - return change; - - /* update CAPTURE */ - spin_lock_irq(&ice->reg_lock); - val = old_val = inl(ICEMT(ice, ROUTE_CAPTURE)); - shift = ((idx / 2) * 8) + ((idx % 2) * 4); - if (nval == 2) { /* analog in */ - nval = ucontrol->value.enumerated.item[0] - 1; - val &= ~(0x07 << shift); - val |= nval << shift; - } else { /* spdif in */ - nval = (ucontrol->value.enumerated.item[0] - 9) << 3; - val &= ~(0x08 << shift); - val |= nval << shift; - } - if (val != old_val) { - change = 1; - outl(val, ICEMT(ice, ROUTE_CAPTURE)); - } - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static int snd_ice1712_pro_route_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned int val, cval; - val = inw(ICEMT(ice, ROUTE_SPDOUT)); - cval = (val >> (idx * 4 + 8)) & 0x0f; - val = (val >> (idx * 2)) & 0x03; - if (val == 1) - ucontrol->value.enumerated.item[0] = 11; - else if (val == 2) - ucontrol->value.enumerated.item[0] = (cval & 7) + 1; - else if (val == 3) - ucontrol->value.enumerated.item[0] = ((cval >> 3) & 1) + 9; - else - ucontrol->value.enumerated.item[0] = 0; - return 0; -} - -static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int change, shift; - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned int val, old_val, nval; - - /* update SPDOUT */ - spin_lock_irq(&ice->reg_lock); - val = old_val = inw(ICEMT(ice, ROUTE_SPDOUT)); - if (ucontrol->value.enumerated.item[0] >= 11) - nval = 1; - else if (ucontrol->value.enumerated.item[0] >= 9) - nval = 3; - else if (ucontrol->value.enumerated.item[0] >= 1) - nval = 2; - else - nval = 0; - shift = idx * 2; - val &= ~(0x03 << shift); - val |= nval << shift; - shift = idx * 4 + 8; - if (nval == 2) { - nval = ucontrol->value.enumerated.item[0] - 1; - val &= ~(0x07 << shift); - val |= nval << shift; - } else if (nval == 3) { - nval = (ucontrol->value.enumerated.item[0] - 9) << 3; - val &= ~(0x08 << shift); - val |= nval << shift; - } - change = val != old_val; - if (change) - outw(val, ICEMT(ice, ROUTE_SPDOUT)); - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "H/W Playback Route", - .info = snd_ice1712_pro_route_info, - .get = snd_ice1712_pro_route_analog_get, - .put = snd_ice1712_pro_route_analog_put, -}; - -static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Route", - .info = snd_ice1712_pro_route_info, - .get = snd_ice1712_pro_route_spdif_get, - .put = snd_ice1712_pro_route_spdif_put, - .count = 2, -}; - - -static int snd_ice1712_pro_volume_rate_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_ice1712_pro_volume_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = inb(ICEMT(ice, MONITOR_RATE)); - return 0; -} - -static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int change; - - spin_lock_irq(&ice->reg_lock); - change = inb(ICEMT(ice, MONITOR_RATE)) != ucontrol->value.integer.value[0]; - outb(ucontrol->value.integer.value[0], ICEMT(ice, MONITOR_RATE)); - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Track Volume Rate", - .info = snd_ice1712_pro_volume_rate_info, - .get = snd_ice1712_pro_volume_rate_get, - .put = snd_ice1712_pro_volume_rate_put -}; - -static int snd_ice1712_pro_peak_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 22; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx; - - spin_lock_irq(&ice->reg_lock); - for (idx = 0; idx < 22; idx++) { - outb(idx, ICEMT(ice, MONITOR_PEAKINDEX)); - ucontrol->value.integer.value[idx] = inb(ICEMT(ice, MONITOR_PEAKDATA)); - } - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Multi Track Peak", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_ice1712_pro_peak_info, - .get = snd_ice1712_pro_peak_get -}; - -/* - * - */ - -/* - * list of available boards - */ -static struct snd_ice1712_card_info *card_tables[] __devinitdata = { - snd_ice1712_hoontech_cards, - snd_ice1712_delta_cards, - snd_ice1712_ews_cards, - NULL, -}; - -static unsigned char __devinit snd_ice1712_read_i2c(struct snd_ice1712 *ice, - unsigned char dev, - unsigned char addr) -{ - long t = 0x10000; - - outb(addr, ICEREG(ice, I2C_BYTE_ADDR)); - outb(dev & ~ICE1712_I2C_WRITE, ICEREG(ice, I2C_DEV_ADDR)); - while (t-- > 0 && (inb(ICEREG(ice, I2C_CTRL)) & ICE1712_I2C_BUSY)) ; - return inb(ICEREG(ice, I2C_DATA)); -} - -static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice, - const char *modelname) -{ - int dev = 0xa0; /* EEPROM device address */ - unsigned int i, size; - struct snd_ice1712_card_info * const *tbl, *c; - - if (!modelname || !*modelname) { - ice->eeprom.subvendor = 0; - if ((inb(ICEREG(ice, I2C_CTRL)) & ICE1712_I2C_EEPROM) != 0) - ice->eeprom.subvendor = (snd_ice1712_read_i2c(ice, dev, 0x00) << 0) | - (snd_ice1712_read_i2c(ice, dev, 0x01) << 8) | - (snd_ice1712_read_i2c(ice, dev, 0x02) << 16) | - (snd_ice1712_read_i2c(ice, dev, 0x03) << 24); - if (ice->eeprom.subvendor == 0 || - ice->eeprom.subvendor == (unsigned int)-1) { - /* invalid subvendor from EEPROM, try the PCI subststem ID instead */ - u16 vendor, device; - pci_read_config_word(ice->pci, PCI_SUBSYSTEM_VENDOR_ID, &vendor); - pci_read_config_word(ice->pci, PCI_SUBSYSTEM_ID, &device); - ice->eeprom.subvendor = ((unsigned int)swab16(vendor) << 16) | swab16(device); - if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) { - printk(KERN_ERR "ice1712: No valid ID is found\n"); - return -ENXIO; - } - } - } - for (tbl = card_tables; *tbl; tbl++) { - for (c = *tbl; c->subvendor; c++) { - if (modelname && c->model && !strcmp(modelname, c->model)) { - printk(KERN_INFO "ice1712: Using board model %s\n", c->name); - ice->eeprom.subvendor = c->subvendor; - } else if (c->subvendor != ice->eeprom.subvendor) - continue; - if (!c->eeprom_size || !c->eeprom_data) - goto found; - /* if the EEPROM is given by the driver, use it */ - snd_printdd("using the defined eeprom..\n"); - ice->eeprom.version = 1; - ice->eeprom.size = c->eeprom_size + 6; - memcpy(ice->eeprom.data, c->eeprom_data, c->eeprom_size); - goto read_skipped; - } - } - printk(KERN_WARNING "ice1712: No matching model found for ID 0x%x\n", - ice->eeprom.subvendor); - - found: - ice->eeprom.size = snd_ice1712_read_i2c(ice, dev, 0x04); - if (ice->eeprom.size < 6) - ice->eeprom.size = 32; /* FIXME: any cards without the correct size? */ - else if (ice->eeprom.size > 32) { - snd_printk(KERN_ERR "invalid EEPROM (size = %i)\n", ice->eeprom.size); - return -EIO; - } - ice->eeprom.version = snd_ice1712_read_i2c(ice, dev, 0x05); - if (ice->eeprom.version != 1) { - snd_printk(KERN_ERR "invalid EEPROM version %i\n", - ice->eeprom.version); - /* return -EIO; */ - } - size = ice->eeprom.size - 6; - for (i = 0; i < size; i++) - ice->eeprom.data[i] = snd_ice1712_read_i2c(ice, dev, i + 6); - - read_skipped: - ice->eeprom.gpiomask = ice->eeprom.data[ICE_EEP1_GPIO_MASK]; - ice->eeprom.gpiostate = ice->eeprom.data[ICE_EEP1_GPIO_STATE]; - ice->eeprom.gpiodir = ice->eeprom.data[ICE_EEP1_GPIO_DIR]; - - return 0; -} - - - -static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice) -{ - outb(ICE1712_RESET | ICE1712_NATIVE, ICEREG(ice, CONTROL)); - udelay(200); - outb(ICE1712_NATIVE, ICEREG(ice, CONTROL)); - udelay(200); - if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && - !ice->dxr_enable) - /* Set eeprom value to limit active ADCs and DACs to 6; - * Also disable AC97 as no hardware in standard 6fire card/box - * Note: DXR extensions are not currently supported - */ - ice->eeprom.data[ICE_EEP1_CODEC] = 0x3a; - pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); - pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]); - pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]); - pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]); - if (ice->eeprom.subvendor != ICE1712_SUBDEVICE_STDSP24) { - ice->gpio.write_mask = ice->eeprom.gpiomask; - ice->gpio.direction = ice->eeprom.gpiodir; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, - ice->eeprom.gpiomask); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, - ice->eeprom.gpiodir); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, - ice->eeprom.gpiostate); - } else { - ice->gpio.write_mask = 0xc0; - ice->gpio.direction = 0xff; - snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, 0xc0); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, 0xff); - snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, - ICE1712_STDSP24_CLOCK_BIT); - } - snd_ice1712_write(ice, ICE1712_IREG_PRO_POWERDOWN, 0); - if (!(ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97)) { - outb(ICE1712_AC97_WARM, ICEREG(ice, AC97_CMD)); - udelay(100); - outb(0, ICEREG(ice, AC97_CMD)); - udelay(200); - snd_ice1712_write(ice, ICE1712_IREG_CONSUMER_POWERDOWN, 0); - } - snd_ice1712_set_pro_rate(ice, 48000, 1); - - return 0; -} - -int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice) -{ - int err; - struct snd_kcontrol *kctl; - - if (snd_BUG_ON(!ice->pcm_pro)) - return -EIO; - err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_ice1712_spdif_default, ice)); - if (err < 0) - return err; - kctl->id.device = ice->pcm_pro->device; - err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_ice1712_spdif_maskc, ice)); - if (err < 0) - return err; - kctl->id.device = ice->pcm_pro->device; - err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_ice1712_spdif_maskp, ice)); - if (err < 0) - return err; - kctl->id.device = ice->pcm_pro->device; - err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_ice1712_spdif_stream, ice)); - if (err < 0) - return err; - kctl->id.device = ice->pcm_pro->device; - ice->spdif.stream_ctl = kctl; - return 0; -} - - -static int __devinit snd_ice1712_build_controls(struct snd_ice1712 *ice) -{ - int err; - - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_eeprom, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_internal_clock, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_internal_clock_default, ice)); - if (err < 0) - return err; - - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_rate_locking, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_pro_rate_reset, ice)); - if (err < 0) - return err; - - if (ice->num_total_dacs > 0) { - struct snd_kcontrol_new tmp = snd_ice1712_mixer_pro_analog_route; - tmp.count = ice->num_total_dacs; - err = snd_ctl_add(ice->card, snd_ctl_new1(&tmp, ice)); - if (err < 0) - return err; - } - - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_pro_spdif_route, ice)); - if (err < 0) - return err; - - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_pro_volume_rate, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_mixer_pro_peak, ice)); - if (err < 0) - return err; - - return 0; -} - -static int snd_ice1712_free(struct snd_ice1712 *ice) -{ - if (!ice->port) - goto __hw_end; - /* mask all interrupts */ - outb(0xc0, ICEMT(ice, IRQ)); - outb(0xff, ICEREG(ice, IRQMASK)); - /* --- */ -__hw_end: - if (ice->irq >= 0) - free_irq(ice->irq, ice); - - if (ice->port) - pci_release_regions(ice->pci); - snd_ice1712_akm4xxx_free(ice); - pci_disable_device(ice->pci); - kfree(ice->spec); - kfree(ice); - return 0; -} - -static int snd_ice1712_dev_free(struct snd_device *device) -{ - struct snd_ice1712 *ice = device->device_data; - return snd_ice1712_free(ice); -} - -static int __devinit snd_ice1712_create(struct snd_card *card, - struct pci_dev *pci, - const char *modelname, - int omni, - int cs8427_timeout, - int dxr_enable, - struct snd_ice1712 **r_ice1712) -{ - struct snd_ice1712 *ice; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_ice1712_dev_free, - }; - - *r_ice1712 = NULL; - - /* enable PCI device */ - err = pci_enable_device(pci); - if (err < 0) - return err; - /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - ice = kzalloc(sizeof(*ice), GFP_KERNEL); - if (ice == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - ice->omni = omni ? 1 : 0; - if (cs8427_timeout < 1) - cs8427_timeout = 1; - else if (cs8427_timeout > 1000) - cs8427_timeout = 1000; - ice->cs8427_timeout = cs8427_timeout; - ice->dxr_enable = dxr_enable; - spin_lock_init(&ice->reg_lock); - mutex_init(&ice->gpio_mutex); - mutex_init(&ice->i2c_mutex); - mutex_init(&ice->open_mutex); - ice->gpio.set_mask = snd_ice1712_set_gpio_mask; - ice->gpio.get_mask = snd_ice1712_get_gpio_mask; - ice->gpio.set_dir = snd_ice1712_set_gpio_dir; - ice->gpio.get_dir = snd_ice1712_get_gpio_dir; - ice->gpio.set_data = snd_ice1712_set_gpio_data; - ice->gpio.get_data = snd_ice1712_get_gpio_data; - - ice->spdif.cs8403_bits = - ice->spdif.cs8403_stream_bits = (0x01 | /* consumer format */ - 0x10 | /* no emphasis */ - 0x20); /* PCM encoder/decoder */ - ice->card = card; - ice->pci = pci; - ice->irq = -1; - pci_set_master(pci); - pci_write_config_word(ice->pci, 0x40, 0x807f); - pci_write_config_word(ice->pci, 0x42, 0x0006); - snd_ice1712_proc_init(ice); - synchronize_irq(pci->irq); - - err = pci_request_regions(pci, "ICE1712"); - if (err < 0) { - kfree(ice); - pci_disable_device(pci); - return err; - } - ice->port = pci_resource_start(pci, 0); - ice->ddma_port = pci_resource_start(pci, 1); - ice->dmapath_port = pci_resource_start(pci, 2); - ice->profi_port = pci_resource_start(pci, 3); - - if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_SHARED, - KBUILD_MODNAME, ice)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_ice1712_free(ice); - return -EIO; - } - - ice->irq = pci->irq; - - if (snd_ice1712_read_eeprom(ice, modelname) < 0) { - snd_ice1712_free(ice); - return -EIO; - } - if (snd_ice1712_chip_init(ice) < 0) { - snd_ice1712_free(ice); - return -EIO; - } - - /* unmask used interrupts */ - outb(((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ? - ICE1712_IRQ_MPU2 : 0) | - ((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ? - ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0), - ICEREG(ice, IRQMASK)); - outb(0x00, ICEMT(ice, IRQ)); - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops); - if (err < 0) { - snd_ice1712_free(ice); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *r_ice1712 = ice; - return 0; -} - - -/* - * - * Registration - * - */ - -static struct snd_ice1712_card_info no_matched __devinitdata; - -static int __devinit snd_ice1712_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_ice1712 *ice; - int pcm_dev = 0, err; - struct snd_ice1712_card_info * const *tbl, *c; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - strcpy(card->driver, "ICE1712"); - strcpy(card->shortname, "ICEnsemble ICE1712"); - - err = snd_ice1712_create(card, pci, model[dev], omni[dev], - cs8427_timeout[dev], dxr_enable[dev], &ice); - if (err < 0) { - snd_card_free(card); - return err; - } - - for (tbl = card_tables; *tbl; tbl++) { - for (c = *tbl; c->subvendor; c++) { - if (c->subvendor == ice->eeprom.subvendor) { - strcpy(card->shortname, c->name); - if (c->driver) /* specific driver? */ - strcpy(card->driver, c->driver); - if (c->chip_init) { - err = c->chip_init(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - } - goto __found; - } - } - } - c = &no_matched; - __found: - - err = snd_ice1712_pcm_profi(ice, pcm_dev++, NULL); - if (err < 0) { - snd_card_free(card); - return err; - } - - if (ice_has_con_ac97(ice)) { - err = snd_ice1712_pcm(ice, pcm_dev++, NULL); - if (err < 0) { - snd_card_free(card); - return err; - } - } - - err = snd_ice1712_ac97_mixer(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - - err = snd_ice1712_build_controls(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - - if (c->build_controls) { - err = c->build_controls(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - } - - if (ice_has_con_ac97(ice)) { - err = snd_ice1712_pcm_ds(ice, pcm_dev++, NULL); - if (err < 0) { - snd_card_free(card); - return err; - } - } - - if (!c->no_mpu401) { - err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, - ICEREG(ice, MPU1_CTRL), - c->mpu401_1_info_flags | - MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, - -1, &ice->rmidi[0]); - if (err < 0) { - snd_card_free(card); - return err; - } - if (c->mpu401_1_name) - /* Preferred name available in card_info */ - snprintf(ice->rmidi[0]->name, - sizeof(ice->rmidi[0]->name), - "%s %d", c->mpu401_1_name, card->number); - - if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) { - /* 2nd port used */ - err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712, - ICEREG(ice, MPU2_CTRL), - c->mpu401_2_info_flags | - MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, - -1, &ice->rmidi[1]); - - if (err < 0) { - snd_card_free(card); - return err; - } - if (c->mpu401_2_name) - /* Preferred name available in card_info */ - snprintf(ice->rmidi[1]->name, - sizeof(ice->rmidi[1]->name), - "%s %d", c->mpu401_2_name, - card->number); - } - } - - snd_ice1712_set_input_clock_source(ice, 0); - - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, ice->port, ice->irq); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_ice1712_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_ice1712_ids, - .probe = snd_ice1712_probe, - .remove = __devexit_p(snd_ice1712_remove), -}; - -static int __init alsa_card_ice1712_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_ice1712_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_ice1712_init) -module_exit(alsa_card_ice1712_exit) diff --git a/ANDROID_3.4.5/sound/pci/ice1712/ice1712.h b/ANDROID_3.4.5/sound/pci/ice1712/ice1712.h deleted file mode 100644 index 0da778a6..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/ice1712.h +++ /dev/null @@ -1,531 +0,0 @@ -#ifndef __SOUND_ICE1712_H -#define __SOUND_ICE1712_H - -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Copyright (c) 2000 Jaroslav Kysela - * - * 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 - - -/* - * Direct registers - */ - -#define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x) - -#define ICE1712_REG_CONTROL 0x00 /* byte */ -#define ICE1712_RESET 0x80 /* reset whole chip */ -#define ICE1712_SERR_LEVEL 0x04 /* SERR# level otherwise edge */ -#define ICE1712_NATIVE 0x01 /* native mode otherwise SB */ -#define ICE1712_REG_IRQMASK 0x01 /* byte */ -#define ICE1712_IRQ_MPU1 0x80 -#define ICE1712_IRQ_TIMER 0x40 -#define ICE1712_IRQ_MPU2 0x20 -#define ICE1712_IRQ_PROPCM 0x10 -#define ICE1712_IRQ_FM 0x08 /* FM/MIDI - legacy */ -#define ICE1712_IRQ_PBKDS 0x04 /* playback DS channels */ -#define ICE1712_IRQ_CONCAP 0x02 /* consumer capture */ -#define ICE1712_IRQ_CONPBK 0x01 /* consumer playback */ -#define ICE1712_REG_IRQSTAT 0x02 /* byte */ -/* look to ICE1712_IRQ_* */ -#define ICE1712_REG_INDEX 0x03 /* byte - indirect CCIxx regs */ -#define ICE1712_REG_DATA 0x04 /* byte - indirect CCIxx regs */ -#define ICE1712_REG_NMI_STAT1 0x05 /* byte */ -#define ICE1712_REG_NMI_DATA 0x06 /* byte */ -#define ICE1712_REG_NMI_INDEX 0x07 /* byte */ -#define ICE1712_REG_AC97_INDEX 0x08 /* byte */ -#define ICE1712_REG_AC97_CMD 0x09 /* byte */ -#define ICE1712_AC97_COLD 0x80 /* cold reset */ -#define ICE1712_AC97_WARM 0x40 /* warm reset */ -#define ICE1712_AC97_WRITE 0x20 /* W: write, R: write in progress */ -#define ICE1712_AC97_READ 0x10 /* W: read, R: read in progress */ -#define ICE1712_AC97_READY 0x08 /* codec ready status bit */ -#define ICE1712_AC97_PBK_VSR 0x02 /* playback VSR */ -#define ICE1712_AC97_CAP_VSR 0x01 /* capture VSR */ -#define ICE1712_REG_AC97_DATA 0x0a /* word (little endian) */ -#define ICE1712_REG_MPU1_CTRL 0x0c /* byte */ -#define ICE1712_REG_MPU1_DATA 0x0d /* byte */ -#define ICE1712_REG_I2C_DEV_ADDR 0x10 /* byte */ -#define ICE1712_I2C_WRITE 0x01 /* write direction */ -#define ICE1712_REG_I2C_BYTE_ADDR 0x11 /* byte */ -#define ICE1712_REG_I2C_DATA 0x12 /* byte */ -#define ICE1712_REG_I2C_CTRL 0x13 /* byte */ -#define ICE1712_I2C_EEPROM 0x80 /* EEPROM exists */ -#define ICE1712_I2C_BUSY 0x01 /* busy bit */ -#define ICE1712_REG_CONCAP_ADDR 0x14 /* dword - consumer capture */ -#define ICE1712_REG_CONCAP_COUNT 0x18 /* word - current/base count */ -#define ICE1712_REG_SERR_SHADOW 0x1b /* byte */ -#define ICE1712_REG_MPU2_CTRL 0x1c /* byte */ -#define ICE1712_REG_MPU2_DATA 0x1d /* byte */ -#define ICE1712_REG_TIMER 0x1e /* word */ - -/* - * Indirect registers - */ - -#define ICE1712_IREG_PBK_COUNT_LO 0x00 -#define ICE1712_IREG_PBK_COUNT_HI 0x01 -#define ICE1712_IREG_PBK_CTRL 0x02 -#define ICE1712_IREG_PBK_LEFT 0x03 /* left volume */ -#define ICE1712_IREG_PBK_RIGHT 0x04 /* right volume */ -#define ICE1712_IREG_PBK_SOFT 0x05 /* soft volume */ -#define ICE1712_IREG_PBK_RATE_LO 0x06 -#define ICE1712_IREG_PBK_RATE_MID 0x07 -#define ICE1712_IREG_PBK_RATE_HI 0x08 -#define ICE1712_IREG_CAP_COUNT_LO 0x10 -#define ICE1712_IREG_CAP_COUNT_HI 0x11 -#define ICE1712_IREG_CAP_CTRL 0x12 -#define ICE1712_IREG_GPIO_DATA 0x20 -#define ICE1712_IREG_GPIO_WRITE_MASK 0x21 -#define ICE1712_IREG_GPIO_DIRECTION 0x22 -#define ICE1712_IREG_CONSUMER_POWERDOWN 0x30 -#define ICE1712_IREG_PRO_POWERDOWN 0x31 - -/* - * Consumer section direct DMA registers - */ - -#define ICEDS(ice, x) ((ice)->dmapath_port + ICE1712_DS_##x) - -#define ICE1712_DS_INTMASK 0x00 /* word - interrupt mask */ -#define ICE1712_DS_INTSTAT 0x02 /* word - interrupt status */ -#define ICE1712_DS_DATA 0x04 /* dword - channel data */ -#define ICE1712_DS_INDEX 0x08 /* dword - channel index */ - -/* - * Consumer section channel registers - */ - -#define ICE1712_DSC_ADDR0 0x00 /* dword - base address 0 */ -#define ICE1712_DSC_COUNT0 0x01 /* word - count 0 */ -#define ICE1712_DSC_ADDR1 0x02 /* dword - base address 1 */ -#define ICE1712_DSC_COUNT1 0x03 /* word - count 1 */ -#define ICE1712_DSC_CONTROL 0x04 /* byte - control & status */ -#define ICE1712_BUFFER1 0x80 /* buffer1 is active */ -#define ICE1712_BUFFER1_AUTO 0x40 /* buffer1 auto init */ -#define ICE1712_BUFFER0_AUTO 0x20 /* buffer0 auto init */ -#define ICE1712_FLUSH 0x10 /* flush FIFO */ -#define ICE1712_STEREO 0x08 /* stereo */ -#define ICE1712_16BIT 0x04 /* 16-bit data */ -#define ICE1712_PAUSE 0x02 /* pause */ -#define ICE1712_START 0x01 /* start */ -#define ICE1712_DSC_RATE 0x05 /* dword - rate */ -#define ICE1712_DSC_VOLUME 0x06 /* word - volume control */ - -/* - * Professional multi-track direct control registers - */ - -#define ICEMT(ice, x) ((ice)->profi_port + ICE1712_MT_##x) - -#define ICE1712_MT_IRQ 0x00 /* byte - interrupt mask */ -#define ICE1712_MULTI_CAPTURE 0x80 /* capture IRQ */ -#define ICE1712_MULTI_PLAYBACK 0x40 /* playback IRQ */ -#define ICE1712_MULTI_CAPSTATUS 0x02 /* capture IRQ status */ -#define ICE1712_MULTI_PBKSTATUS 0x01 /* playback IRQ status */ -#define ICE1712_MT_RATE 0x01 /* byte - sampling rate select */ -#define ICE1712_SPDIF_MASTER 0x10 /* S/PDIF input is master clock */ -#define ICE1712_MT_I2S_FORMAT 0x02 /* byte - I2S data format */ -#define ICE1712_MT_AC97_INDEX 0x04 /* byte - AC'97 index */ -#define ICE1712_MT_AC97_CMD 0x05 /* byte - AC'97 command & status */ -/* look to ICE1712_AC97_* */ -#define ICE1712_MT_AC97_DATA 0x06 /* word - AC'97 data */ -#define ICE1712_MT_PLAYBACK_ADDR 0x10 /* dword - playback address */ -#define ICE1712_MT_PLAYBACK_SIZE 0x14 /* word - playback size */ -#define ICE1712_MT_PLAYBACK_COUNT 0x16 /* word - playback count */ -#define ICE1712_MT_PLAYBACK_CONTROL 0x18 /* byte - control */ -#define ICE1712_CAPTURE_START_SHADOW 0x04 /* capture start */ -#define ICE1712_PLAYBACK_PAUSE 0x02 /* playback pause */ -#define ICE1712_PLAYBACK_START 0x01 /* playback start */ -#define ICE1712_MT_CAPTURE_ADDR 0x20 /* dword - capture address */ -#define ICE1712_MT_CAPTURE_SIZE 0x24 /* word - capture size */ -#define ICE1712_MT_CAPTURE_COUNT 0x26 /* word - capture count */ -#define ICE1712_MT_CAPTURE_CONTROL 0x28 /* byte - control */ -#define ICE1712_CAPTURE_START 0x01 /* capture start */ -#define ICE1712_MT_ROUTE_PSDOUT03 0x30 /* word */ -#define ICE1712_MT_ROUTE_SPDOUT 0x32 /* word */ -#define ICE1712_MT_ROUTE_CAPTURE 0x34 /* dword */ -#define ICE1712_MT_MONITOR_VOLUME 0x38 /* word */ -#define ICE1712_MT_MONITOR_INDEX 0x3a /* byte */ -#define ICE1712_MT_MONITOR_RATE 0x3b /* byte */ -#define ICE1712_MT_MONITOR_ROUTECTRL 0x3c /* byte */ -#define ICE1712_ROUTE_AC97 0x01 /* route digital mixer output to AC'97 */ -#define ICE1712_MT_MONITOR_PEAKINDEX 0x3e /* byte */ -#define ICE1712_MT_MONITOR_PEAKDATA 0x3f /* byte */ - -/* - * Codec configuration bits - */ - -/* PCI[60] System Configuration */ -#define ICE1712_CFG_CLOCK 0xc0 -#define ICE1712_CFG_CLOCK512 0x00 /* 22.5692Mhz, 44.1kHz*512 */ -#define ICE1712_CFG_CLOCK384 0x40 /* 16.9344Mhz, 44.1kHz*384 */ -#define ICE1712_CFG_EXT 0x80 /* external clock */ -#define ICE1712_CFG_2xMPU401 0x20 /* two MPU401 UARTs */ -#define ICE1712_CFG_NO_CON_AC97 0x10 /* consumer AC'97 codec is not present */ -#define ICE1712_CFG_ADC_MASK 0x0c /* one, two, three, four stereo ADCs */ -#define ICE1712_CFG_DAC_MASK 0x03 /* one, two, three, four stereo DACs */ -/* PCI[61] AC-Link Configuration */ -#define ICE1712_CFG_PRO_I2S 0x80 /* multitrack converter: I2S or AC'97 */ -#define ICE1712_CFG_AC97_PACKED 0x01 /* split or packed mode - AC'97 */ -/* PCI[62] I2S Features */ -#define ICE1712_CFG_I2S_VOLUME 0x80 /* volume/mute capability */ -#define ICE1712_CFG_I2S_96KHZ 0x40 /* supports 96kHz sampling */ -#define ICE1712_CFG_I2S_RESMASK 0x30 /* resolution mask, 16,18,20,24-bit */ -#define ICE1712_CFG_I2S_OTHER 0x0f /* other I2S IDs */ -/* PCI[63] S/PDIF Configuration */ -#define ICE1712_CFG_I2S_CHIPID 0xfc /* I2S chip ID */ -#define ICE1712_CFG_SPDIF_IN 0x02 /* S/PDIF input is present */ -#define ICE1712_CFG_SPDIF_OUT 0x01 /* S/PDIF output is present */ - -/* - * DMA mode values - * identical with DMA_XXX on i386 architecture. - */ -#define ICE1712_DMA_MODE_WRITE 0x48 -#define ICE1712_DMA_AUTOINIT 0x10 - - -/* - * - */ - -struct snd_ice1712; - -struct snd_ice1712_eeprom { - unsigned int subvendor; /* PCI[2c-2f] */ - unsigned char size; /* size of EEPROM image in bytes */ - unsigned char version; /* must be 1 (or 2 for vt1724) */ - unsigned char data[32]; - unsigned int gpiomask; - unsigned int gpiostate; - unsigned int gpiodir; -}; - -enum { - ICE_EEP1_CODEC = 0, /* 06 */ - ICE_EEP1_ACLINK, /* 07 */ - ICE_EEP1_I2SID, /* 08 */ - ICE_EEP1_SPDIF, /* 09 */ - ICE_EEP1_GPIO_MASK, /* 0a */ - ICE_EEP1_GPIO_STATE, /* 0b */ - ICE_EEP1_GPIO_DIR, /* 0c */ - ICE_EEP1_AC97_MAIN_LO, /* 0d */ - ICE_EEP1_AC97_MAIN_HI, /* 0e */ - ICE_EEP1_AC97_PCM_LO, /* 0f */ - ICE_EEP1_AC97_PCM_HI, /* 10 */ - ICE_EEP1_AC97_REC_LO, /* 11 */ - ICE_EEP1_AC97_REC_HI, /* 12 */ - ICE_EEP1_AC97_RECSRC, /* 13 */ - ICE_EEP1_DAC_ID, /* 14 */ - ICE_EEP1_DAC_ID1, - ICE_EEP1_DAC_ID2, - ICE_EEP1_DAC_ID3, - ICE_EEP1_ADC_ID, /* 18 */ - ICE_EEP1_ADC_ID1, - ICE_EEP1_ADC_ID2, - ICE_EEP1_ADC_ID3 -}; - -#define ice_has_con_ac97(ice) (!((ice)->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97)) - - -struct snd_ak4xxx_private { - unsigned int cif:1; /* CIF mode */ - unsigned char caddr; /* C0 and C1 bits */ - unsigned int data_mask; /* DATA gpio bit */ - unsigned int clk_mask; /* CLK gpio bit */ - unsigned int cs_mask; /* bit mask for select/deselect address */ - unsigned int cs_addr; /* bits to select address */ - unsigned int cs_none; /* bits to deselect address */ - unsigned int add_flags; /* additional bits at init */ - unsigned int mask_flags; /* total mask bits */ - struct snd_akm4xxx_ops { - void (*set_rate_val)(struct snd_akm4xxx *ak, unsigned int rate); - } ops; -}; - -struct snd_ice1712_spdif { - unsigned char cs8403_bits; - unsigned char cs8403_stream_bits; - struct snd_kcontrol *stream_ctl; - - struct snd_ice1712_spdif_ops { - void (*open)(struct snd_ice1712 *, struct snd_pcm_substream *); - void (*setup_rate)(struct snd_ice1712 *, int rate); - void (*close)(struct snd_ice1712 *, struct snd_pcm_substream *); - void (*default_get)(struct snd_ice1712 *, struct snd_ctl_elem_value *ucontrol); - int (*default_put)(struct snd_ice1712 *, struct snd_ctl_elem_value *ucontrol); - void (*stream_get)(struct snd_ice1712 *, struct snd_ctl_elem_value *ucontrol); - int (*stream_put)(struct snd_ice1712 *, struct snd_ctl_elem_value *ucontrol); - } ops; -}; - - -struct snd_ice1712 { - unsigned long conp_dma_size; - unsigned long conc_dma_size; - unsigned long prop_dma_size; - unsigned long proc_dma_size; - int irq; - - unsigned long port; - unsigned long ddma_port; - unsigned long dmapath_port; - unsigned long profi_port; - - struct pci_dev *pci; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_pcm *pcm_ds; - struct snd_pcm *pcm_pro; - struct snd_pcm_substream *playback_con_substream; - struct snd_pcm_substream *playback_con_substream_ds[6]; - struct snd_pcm_substream *capture_con_substream; - struct snd_pcm_substream *playback_pro_substream; - struct snd_pcm_substream *capture_pro_substream; - unsigned int playback_pro_size; - unsigned int capture_pro_size; - unsigned int playback_con_virt_addr[6]; - unsigned int playback_con_active_buf[6]; - unsigned int capture_con_virt_addr; - unsigned int ac97_ext_id; - struct snd_ac97 *ac97; - struct snd_rawmidi *rmidi[2]; - - spinlock_t reg_lock; - struct snd_info_entry *proc_entry; - - struct snd_ice1712_eeprom eeprom; - - unsigned int pro_volumes[20]; - unsigned int omni:1; /* Delta Omni I/O */ - unsigned int dxr_enable:1; /* Terratec DXR enable for DMX6FIRE */ - unsigned int vt1724:1; - unsigned int vt1720:1; - unsigned int has_spdif:1; /* VT1720/4 - has SPDIF I/O */ - unsigned int force_pdma4:1; /* VT1720/4 - PDMA4 as non-spdif */ - unsigned int force_rdma1:1; /* VT1720/4 - RDMA1 as non-spdif */ - unsigned int midi_output:1; /* VT1720/4: MIDI output triggered */ - unsigned int midi_input:1; /* VT1720/4: MIDI input triggered */ - unsigned int own_routing:1; /* VT1720/4: use own routing ctls */ - unsigned int num_total_dacs; /* total DACs */ - unsigned int num_total_adcs; /* total ADCs */ - unsigned int cur_rate; /* current rate */ - - struct mutex open_mutex; - struct snd_pcm_substream *pcm_reserved[4]; - struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */ - - unsigned int akm_codecs; - struct snd_akm4xxx *akm; - struct snd_ice1712_spdif spdif; - - struct mutex i2c_mutex; /* I2C mutex for ICE1724 registers */ - struct snd_i2c_bus *i2c; /* I2C bus */ - struct snd_i2c_device *cs8427; /* CS8427 I2C device */ - unsigned int cs8427_timeout; /* CS8427 reset timeout in HZ/100 */ - - struct ice1712_gpio { - unsigned int direction; /* current direction bits */ - unsigned int write_mask; /* current mask bits */ - unsigned int saved[2]; /* for ewx_i2c */ - /* operators */ - void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); - unsigned int (*get_mask)(struct snd_ice1712 *ice); - void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); - unsigned int (*get_dir)(struct snd_ice1712 *ice); - void (*set_data)(struct snd_ice1712 *ice, unsigned int data); - unsigned int (*get_data)(struct snd_ice1712 *ice); - /* misc operators - move to another place? */ - void (*set_pro_rate)(struct snd_ice1712 *ice, unsigned int rate); - void (*i2s_mclk_changed)(struct snd_ice1712 *ice); - } gpio; - struct mutex gpio_mutex; - - /* other board-specific data */ - void *spec; - - /* VT172x specific */ - int pro_rate_default; - int (*is_spdif_master)(struct snd_ice1712 *ice); - unsigned int (*get_rate)(struct snd_ice1712 *ice); - void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); - unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); - int (*set_spdif_clock)(struct snd_ice1712 *ice, int type); - int (*get_spdif_master_type)(struct snd_ice1712 *ice); - char **ext_clock_names; - int ext_clock_count; - void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *); -#ifdef CONFIG_PM - int (*pm_suspend)(struct snd_ice1712 *); - int (*pm_resume)(struct snd_ice1712 *); - unsigned int pm_suspend_enabled:1; - unsigned int pm_saved_is_spdif_master:1; - unsigned int pm_saved_spdif_ctrl; - unsigned char pm_saved_spdif_cfg; - unsigned int pm_saved_route; -#endif -}; - - -/* - * gpio access functions - */ -static inline void snd_ice1712_gpio_set_dir(struct snd_ice1712 *ice, unsigned int bits) -{ - ice->gpio.set_dir(ice, bits); -} - -static inline unsigned int snd_ice1712_gpio_get_dir(struct snd_ice1712 *ice) -{ - return ice->gpio.get_dir(ice); -} - -static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) -{ - ice->gpio.set_mask(ice, bits); -} - -static inline void snd_ice1712_gpio_write(struct snd_ice1712 *ice, unsigned int val) -{ - ice->gpio.set_data(ice, val); -} - -static inline unsigned int snd_ice1712_gpio_read(struct snd_ice1712 *ice) -{ - return ice->gpio.get_data(ice); -} - -/* - * save and restore gpio status - * The access to gpio will be protected by mutex, so don't forget to - * restore! - */ -static inline void snd_ice1712_save_gpio_status(struct snd_ice1712 *ice) -{ - mutex_lock(&ice->gpio_mutex); - ice->gpio.saved[0] = ice->gpio.direction; - ice->gpio.saved[1] = ice->gpio.write_mask; -} - -static inline void snd_ice1712_restore_gpio_status(struct snd_ice1712 *ice) -{ - ice->gpio.set_dir(ice, ice->gpio.saved[0]); - ice->gpio.set_mask(ice, ice->gpio.saved[1]); - ice->gpio.direction = ice->gpio.saved[0]; - ice->gpio.write_mask = ice->gpio.saved[1]; - mutex_unlock(&ice->gpio_mutex); -} - -/* for bit controls */ -#define ICE1712_GPIO(xiface, xname, xindex, mask, invert, xaccess) \ -{ .iface = xiface, .name = xname, .access = xaccess, .info = snd_ctl_boolean_mono_info, \ - .get = snd_ice1712_gpio_get, .put = snd_ice1712_gpio_put, \ - .private_value = mask | (invert << 24) } - -int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); - -/* - * set gpio direction, write mask and data - */ -static inline void snd_ice1712_gpio_write_bits(struct snd_ice1712 *ice, - unsigned int mask, unsigned int bits) -{ - unsigned val; - - ice->gpio.direction |= mask; - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); - val = snd_ice1712_gpio_read(ice); - val &= ~mask; - val |= mask & bits; - snd_ice1712_gpio_write(ice, val); -} - -static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice, - unsigned int mask) -{ - ice->gpio.direction &= ~mask; - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); - return snd_ice1712_gpio_read(ice) & mask; -} - -/* route access functions */ -int snd_ice1724_get_route_val(struct snd_ice1712 *ice, int shift); -int snd_ice1724_put_route_val(struct snd_ice1712 *ice, unsigned int val, - int shift); - -int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice); - -int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, - const struct snd_akm4xxx *template, - const struct snd_ak4xxx_private *priv, - struct snd_ice1712 *ice); -void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice); -int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice); - -int snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr); - -static inline void snd_ice1712_write(struct snd_ice1712 *ice, u8 addr, u8 data) -{ - outb(addr, ICEREG(ice, INDEX)); - outb(data, ICEREG(ice, DATA)); -} - -static inline u8 snd_ice1712_read(struct snd_ice1712 *ice, u8 addr) -{ - outb(addr, ICEREG(ice, INDEX)); - return inb(ICEREG(ice, DATA)); -} - - -/* - * entry pointer - */ - -struct snd_ice1712_card_info { - unsigned int subvendor; - char *name; - char *model; - char *driver; - int (*chip_init)(struct snd_ice1712 *); - int (*build_controls)(struct snd_ice1712 *); - unsigned int no_mpu401:1; - unsigned int mpu401_1_info_flags; - unsigned int mpu401_2_info_flags; - const char *mpu401_1_name; - const char *mpu401_2_name; - const unsigned int eeprom_size; - const unsigned char *eeprom_data; -}; - - -#endif /* __SOUND_ICE1712_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/ice1724.c b/ANDROID_3.4.5/sound/pci/ice1712/ice1724.c deleted file mode 100644 index 812d10e4..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/ice1724.c +++ /dev/null @@ -1,2898 +0,0 @@ -/* - * ALSA driver for VT1724 ICEnsemble ICE1724 / VIA VT1724 (Envy24HT) - * VIA VT1720 (Envy24PT) - * - * Copyright (c) 2000 Jaroslav Kysela - * 2002 James Stafford - * 2003 Takashi Iwai - * - * 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 -#include -#include -#include - -#include - -#include "ice1712.h" -#include "envy24ht.h" - -/* lowlevel routines */ -#include "amp.h" -#include "revo.h" -#include "aureon.h" -#include "vt1720_mobo.h" -#include "pontis.h" -#include "prodigy192.h" -#include "prodigy_hifi.h" -#include "juli.h" -#include "maya44.h" -#include "phase.h" -#include "wtm.h" -#include "se.h" -#include "quartet.h" - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{" - REVO_DEVICE_DESC - AMP_AUDIO2000_DEVICE_DESC - AUREON_DEVICE_DESC - VT1720_MOBO_DEVICE_DESC - PONTIS_DEVICE_DESC - PRODIGY192_DEVICE_DESC - PRODIGY_HIFI_DEVICE_DESC - JULI_DEVICE_DESC - MAYA44_DEVICE_DESC - PHASE_DEVICE_DESC - WTM_DEVICE_DESC - SE_DEVICE_DESC - QTET_DEVICE_DESC - "{VIA,VT1720}," - "{VIA,VT1724}," - "{ICEnsemble,Generic ICE1724}," - "{ICEnsemble,Generic Envy24HT}" - "{ICEnsemble,Generic Envy24PT}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static char *model[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ICE1724 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ICE1724 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ICE1724 soundcard."); -module_param_array(model, charp, NULL, 0444); -MODULE_PARM_DESC(model, "Use the given board model."); - - -/* Both VT1720 and VT1724 have the same PCI IDs */ -static DEFINE_PCI_DEVICE_TABLE(snd_vt1724_ids) = { - { PCI_VDEVICE(ICE, PCI_DEVICE_ID_VT1724), 0 }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_vt1724_ids); - - -static int PRO_RATE_LOCKED; -static int PRO_RATE_RESET = 1; -static unsigned int PRO_RATE_DEFAULT = 44100; - -static char *ext_clock_names[1] = { "IEC958 In" }; - -/* - * Basic I/O - */ - -/* - * default rates, default clock routines - */ - -/* check whether the clock mode is spdif-in */ -static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice) -{ - return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0; -} - -/* - * locking rate makes sense only for internal clock mode - */ -static inline int is_pro_rate_locked(struct snd_ice1712 *ice) -{ - return (!ice->is_spdif_master(ice)) && PRO_RATE_LOCKED; -} - -/* - * ac97 section - */ - -static unsigned char snd_vt1724_ac97_ready(struct snd_ice1712 *ice) -{ - unsigned char old_cmd; - int tm; - for (tm = 0; tm < 0x10000; tm++) { - old_cmd = inb(ICEMT1724(ice, AC97_CMD)); - if (old_cmd & (VT1724_AC97_WRITE | VT1724_AC97_READ)) - continue; - if (!(old_cmd & VT1724_AC97_READY)) - continue; - return old_cmd; - } - snd_printd(KERN_ERR "snd_vt1724_ac97_ready: timeout\n"); - return old_cmd; -} - -static int snd_vt1724_ac97_wait_bit(struct snd_ice1712 *ice, unsigned char bit) -{ - int tm; - for (tm = 0; tm < 0x10000; tm++) - if ((inb(ICEMT1724(ice, AC97_CMD)) & bit) == 0) - return 0; - snd_printd(KERN_ERR "snd_vt1724_ac97_wait_bit: timeout\n"); - return -EIO; -} - -static void snd_vt1724_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct snd_ice1712 *ice = ac97->private_data; - unsigned char old_cmd; - - old_cmd = snd_vt1724_ac97_ready(ice); - old_cmd &= ~VT1724_AC97_ID_MASK; - old_cmd |= ac97->num; - outb(reg, ICEMT1724(ice, AC97_INDEX)); - outw(val, ICEMT1724(ice, AC97_DATA)); - outb(old_cmd | VT1724_AC97_WRITE, ICEMT1724(ice, AC97_CMD)); - snd_vt1724_ac97_wait_bit(ice, VT1724_AC97_WRITE); -} - -static unsigned short snd_vt1724_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_ice1712 *ice = ac97->private_data; - unsigned char old_cmd; - - old_cmd = snd_vt1724_ac97_ready(ice); - old_cmd &= ~VT1724_AC97_ID_MASK; - old_cmd |= ac97->num; - outb(reg, ICEMT1724(ice, AC97_INDEX)); - outb(old_cmd | VT1724_AC97_READ, ICEMT1724(ice, AC97_CMD)); - if (snd_vt1724_ac97_wait_bit(ice, VT1724_AC97_READ) < 0) - return ~0; - return inw(ICEMT1724(ice, AC97_DATA)); -} - - -/* - * GPIO operations - */ - -/* set gpio direction 0 = read, 1 = write */ -static void snd_vt1724_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) -{ - outl(data, ICEREG1724(ice, GPIO_DIRECTION)); - inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */ -} - -/* get gpio direction 0 = read, 1 = write */ -static unsigned int snd_vt1724_get_gpio_dir(struct snd_ice1712 *ice) -{ - return inl(ICEREG1724(ice, GPIO_DIRECTION)); -} - -/* set the gpio mask (0 = writable) */ -static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) -{ - outw(data, ICEREG1724(ice, GPIO_WRITE_MASK)); - if (!ice->vt1720) /* VT1720 supports only 16 GPIO bits */ - outb((data >> 16) & 0xff, ICEREG1724(ice, GPIO_WRITE_MASK_22)); - inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */ -} - -static unsigned int snd_vt1724_get_gpio_mask(struct snd_ice1712 *ice) -{ - unsigned int mask; - if (!ice->vt1720) - mask = (unsigned int)inb(ICEREG1724(ice, GPIO_WRITE_MASK_22)); - else - mask = 0; - mask = (mask << 16) | inw(ICEREG1724(ice, GPIO_WRITE_MASK)); - return mask; -} - -static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data) -{ - outw(data, ICEREG1724(ice, GPIO_DATA)); - if (!ice->vt1720) - outb(data >> 16, ICEREG1724(ice, GPIO_DATA_22)); - inw(ICEREG1724(ice, GPIO_DATA)); /* dummy read for pci-posting */ -} - -static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice) -{ - unsigned int data; - if (!ice->vt1720) - data = (unsigned int)inb(ICEREG1724(ice, GPIO_DATA_22)); - else - data = 0; - data = (data << 16) | inw(ICEREG1724(ice, GPIO_DATA)); - return data; -} - -/* - * MIDI - */ - -static void vt1724_midi_clear_rx(struct snd_ice1712 *ice) -{ - unsigned int count; - - for (count = inb(ICEREG1724(ice, MPU_RXFIFO)); count > 0; --count) - inb(ICEREG1724(ice, MPU_DATA)); -} - -static inline struct snd_rawmidi_substream * -get_rawmidi_substream(struct snd_ice1712 *ice, unsigned int stream) -{ - return list_first_entry(&ice->rmidi[0]->streams[stream].substreams, - struct snd_rawmidi_substream, list); -} - -static void enable_midi_irq(struct snd_ice1712 *ice, u8 flag, int enable); - -static void vt1724_midi_write(struct snd_ice1712 *ice) -{ - struct snd_rawmidi_substream *s; - int count, i; - u8 buffer[32]; - - s = get_rawmidi_substream(ice, SNDRV_RAWMIDI_STREAM_OUTPUT); - count = 31 - inb(ICEREG1724(ice, MPU_TXFIFO)); - if (count > 0) { - count = snd_rawmidi_transmit(s, buffer, count); - for (i = 0; i < count; ++i) - outb(buffer[i], ICEREG1724(ice, MPU_DATA)); - } - /* mask irq when all bytes have been transmitted. - * enabled again in output_trigger when the new data comes in. - */ - enable_midi_irq(ice, VT1724_IRQ_MPU_TX, - !snd_rawmidi_transmit_empty(s)); -} - -static void vt1724_midi_read(struct snd_ice1712 *ice) -{ - struct snd_rawmidi_substream *s; - int count, i; - u8 buffer[32]; - - s = get_rawmidi_substream(ice, SNDRV_RAWMIDI_STREAM_INPUT); - count = inb(ICEREG1724(ice, MPU_RXFIFO)); - if (count > 0) { - count = min(count, 32); - for (i = 0; i < count; ++i) - buffer[i] = inb(ICEREG1724(ice, MPU_DATA)); - snd_rawmidi_receive(s, buffer, count); - } -} - -/* call with ice->reg_lock */ -static void enable_midi_irq(struct snd_ice1712 *ice, u8 flag, int enable) -{ - u8 mask = inb(ICEREG1724(ice, IRQMASK)); - if (enable) - mask &= ~flag; - else - mask |= flag; - outb(mask, ICEREG1724(ice, IRQMASK)); -} - -static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream, - u8 flag, int enable) -{ - struct snd_ice1712 *ice = substream->rmidi->private_data; - - spin_lock_irq(&ice->reg_lock); - enable_midi_irq(ice, flag, enable); - spin_unlock_irq(&ice->reg_lock); -} - -static int vt1724_midi_output_open(struct snd_rawmidi_substream *s) -{ - return 0; -} - -static int vt1724_midi_output_close(struct snd_rawmidi_substream *s) -{ - return 0; -} - -static void vt1724_midi_output_trigger(struct snd_rawmidi_substream *s, int up) -{ - struct snd_ice1712 *ice = s->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&ice->reg_lock, flags); - if (up) { - ice->midi_output = 1; - vt1724_midi_write(ice); - } else { - ice->midi_output = 0; - enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); - } - spin_unlock_irqrestore(&ice->reg_lock, flags); -} - -static void vt1724_midi_output_drain(struct snd_rawmidi_substream *s) -{ - struct snd_ice1712 *ice = s->rmidi->private_data; - unsigned long timeout; - - vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0); - /* 32 bytes should be transmitted in less than about 12 ms */ - timeout = jiffies + msecs_to_jiffies(15); - do { - if (inb(ICEREG1724(ice, MPU_CTRL)) & VT1724_MPU_TX_EMPTY) - break; - schedule_timeout_uninterruptible(1); - } while (time_after(timeout, jiffies)); -} - -static struct snd_rawmidi_ops vt1724_midi_output_ops = { - .open = vt1724_midi_output_open, - .close = vt1724_midi_output_close, - .trigger = vt1724_midi_output_trigger, - .drain = vt1724_midi_output_drain, -}; - -static int vt1724_midi_input_open(struct snd_rawmidi_substream *s) -{ - vt1724_midi_clear_rx(s->rmidi->private_data); - vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_RX, 1); - return 0; -} - -static int vt1724_midi_input_close(struct snd_rawmidi_substream *s) -{ - vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_RX, 0); - return 0; -} - -static void vt1724_midi_input_trigger(struct snd_rawmidi_substream *s, int up) -{ - struct snd_ice1712 *ice = s->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&ice->reg_lock, flags); - if (up) { - ice->midi_input = 1; - vt1724_midi_read(ice); - } else { - ice->midi_input = 0; - } - spin_unlock_irqrestore(&ice->reg_lock, flags); -} - -static struct snd_rawmidi_ops vt1724_midi_input_ops = { - .open = vt1724_midi_input_open, - .close = vt1724_midi_input_close, - .trigger = vt1724_midi_input_trigger, -}; - - -/* - * Interrupt handler - */ - -static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) -{ - struct snd_ice1712 *ice = dev_id; - unsigned char status; - unsigned char status_mask = - VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM; - int handled = 0; - int timeout = 0; - - while (1) { - status = inb(ICEREG1724(ice, IRQSTAT)); - status &= status_mask; - if (status == 0) - break; - spin_lock(&ice->reg_lock); - if (++timeout > 10) { - status = inb(ICEREG1724(ice, IRQSTAT)); - printk(KERN_ERR "ice1724: Too long irq loop, " - "status = 0x%x\n", status); - if (status & VT1724_IRQ_MPU_TX) { - printk(KERN_ERR "ice1724: Disabling MPU_TX\n"); - enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); - } - spin_unlock(&ice->reg_lock); - break; - } - handled = 1; - if (status & VT1724_IRQ_MPU_TX) { - if (ice->midi_output) - vt1724_midi_write(ice); - else - enable_midi_irq(ice, VT1724_IRQ_MPU_TX, 0); - /* Due to mysterical reasons, MPU_TX is always - * generated (and can't be cleared) when a PCM - * playback is going. So let's ignore at the - * next loop. - */ - status_mask &= ~VT1724_IRQ_MPU_TX; - } - if (status & VT1724_IRQ_MPU_RX) { - if (ice->midi_input) - vt1724_midi_read(ice); - else - vt1724_midi_clear_rx(ice); - } - /* ack MPU irq */ - outb(status, ICEREG1724(ice, IRQSTAT)); - spin_unlock(&ice->reg_lock); - if (status & VT1724_IRQ_MTPCM) { - /* - * Multi-track PCM - * PCM assignment are: - * Playback DMA0 (M/C) = playback_pro_substream - * Playback DMA1 = playback_con_substream_ds[0] - * Playback DMA2 = playback_con_substream_ds[1] - * Playback DMA3 = playback_con_substream_ds[2] - * Playback DMA4 (SPDIF) = playback_con_substream - * Record DMA0 = capture_pro_substream - * Record DMA1 = capture_con_substream - */ - unsigned char mtstat = inb(ICEMT1724(ice, IRQ)); - if (mtstat & VT1724_MULTI_PDMA0) { - if (ice->playback_pro_substream) - snd_pcm_period_elapsed(ice->playback_pro_substream); - } - if (mtstat & VT1724_MULTI_RDMA0) { - if (ice->capture_pro_substream) - snd_pcm_period_elapsed(ice->capture_pro_substream); - } - if (mtstat & VT1724_MULTI_PDMA1) { - if (ice->playback_con_substream_ds[0]) - snd_pcm_period_elapsed(ice->playback_con_substream_ds[0]); - } - if (mtstat & VT1724_MULTI_PDMA2) { - if (ice->playback_con_substream_ds[1]) - snd_pcm_period_elapsed(ice->playback_con_substream_ds[1]); - } - if (mtstat & VT1724_MULTI_PDMA3) { - if (ice->playback_con_substream_ds[2]) - snd_pcm_period_elapsed(ice->playback_con_substream_ds[2]); - } - if (mtstat & VT1724_MULTI_PDMA4) { - if (ice->playback_con_substream) - snd_pcm_period_elapsed(ice->playback_con_substream); - } - if (mtstat & VT1724_MULTI_RDMA1) { - if (ice->capture_con_substream) - snd_pcm_period_elapsed(ice->capture_con_substream); - } - /* ack anyway to avoid freeze */ - outb(mtstat, ICEMT1724(ice, IRQ)); - /* ought to really handle this properly */ - if (mtstat & VT1724_MULTI_FIFO_ERR) { - unsigned char fstat = inb(ICEMT1724(ice, DMA_FIFO_ERR)); - outb(fstat, ICEMT1724(ice, DMA_FIFO_ERR)); - outb(VT1724_MULTI_FIFO_ERR | inb(ICEMT1724(ice, DMA_INT_MASK)), ICEMT1724(ice, DMA_INT_MASK)); - /* If I don't do this, I get machine lockup due to continual interrupts */ - } - - } - } - return IRQ_RETVAL(handled); -} - -/* - * PCM code - professional part (multitrack) - */ - -static unsigned int rates[] = { - 8000, 9600, 11025, 12000, 16000, 22050, 24000, - 32000, 44100, 48000, 64000, 88200, 96000, - 176400, 192000, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates_96 = { - .count = ARRAY_SIZE(rates) - 2, /* up to 96000 */ - .list = rates, - .mask = 0, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates_48 = { - .count = ARRAY_SIZE(rates) - 5, /* up to 48000 */ - .list = rates, - .mask = 0, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates_192 = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -struct vt1724_pcm_reg { - unsigned int addr; /* ADDR register offset */ - unsigned int size; /* SIZE register offset */ - unsigned int count; /* COUNT register offset */ - unsigned int start; /* start & pause bit */ -}; - -static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - unsigned char what; - unsigned char old; - struct snd_pcm_substream *s; - - what = 0; - snd_pcm_group_for_each_entry(s, substream) { - if (snd_pcm_substream_chip(s) == ice) { - const struct vt1724_pcm_reg *reg; - reg = s->runtime->private_data; - what |= reg->start; - snd_pcm_trigger_done(s, substream); - } - } - - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock(&ice->reg_lock); - old = inb(ICEMT1724(ice, DMA_PAUSE)); - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) - old |= what; - else - old &= ~what; - outb(old, ICEMT1724(ice, DMA_PAUSE)); - spin_unlock(&ice->reg_lock); - break; - - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - spin_lock(&ice->reg_lock); - old = inb(ICEMT1724(ice, DMA_CONTROL)); - if (cmd == SNDRV_PCM_TRIGGER_START) - old |= what; - else - old &= ~what; - outb(old, ICEMT1724(ice, DMA_CONTROL)); - spin_unlock(&ice->reg_lock); - break; - - case SNDRV_PCM_TRIGGER_RESUME: - /* apps will have to restart stream */ - break; - - default: - return -EINVAL; - } - return 0; -} - -/* - */ - -#define DMA_STARTS (VT1724_RDMA0_START|VT1724_PDMA0_START|VT1724_RDMA1_START|\ - VT1724_PDMA1_START|VT1724_PDMA2_START|VT1724_PDMA3_START|VT1724_PDMA4_START) -#define DMA_PAUSES (VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\ - VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE) - -static const unsigned int stdclock_rate_list[16] = { - 48000, 24000, 12000, 9600, 32000, 16000, 8000, 96000, 44100, - 22050, 11025, 88200, 176400, 0, 192000, 64000 -}; - -static unsigned int stdclock_get_rate(struct snd_ice1712 *ice) -{ - unsigned int rate; - rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15]; - return rate; -} - -static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate) -{ - int i; - for (i = 0; i < ARRAY_SIZE(stdclock_rate_list); i++) { - if (stdclock_rate_list[i] == rate) { - outb(i, ICEMT1724(ice, RATE)); - return; - } - } -} - -static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice, - unsigned int rate) -{ - unsigned char val, old; - /* check MT02 */ - if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) { - val = old = inb(ICEMT1724(ice, I2S_FORMAT)); - if (rate > 96000) - val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */ - else - val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */ - if (val != old) { - outb(val, ICEMT1724(ice, I2S_FORMAT)); - /* master clock changed */ - return 1; - } - } - /* no change in master clock */ - return 0; -} - -static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, - int force) -{ - unsigned long flags; - unsigned char mclk_change; - unsigned int i, old_rate; - - if (rate > ice->hw_rates->list[ice->hw_rates->count - 1]) - return -EINVAL; - - spin_lock_irqsave(&ice->reg_lock, flags); - if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || - (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) { - /* running? we cannot change the rate now... */ - spin_unlock_irqrestore(&ice->reg_lock, flags); - return ((rate == ice->cur_rate) && !force) ? 0 : -EBUSY; - } - if (!force && is_pro_rate_locked(ice)) { - /* comparing required and current rate - makes sense for - * internal clock only */ - spin_unlock_irqrestore(&ice->reg_lock, flags); - return (rate == ice->cur_rate) ? 0 : -EBUSY; - } - - if (force || !ice->is_spdif_master(ice)) { - /* force means the rate was switched by ucontrol, otherwise - * setting clock rate for internal clock mode */ - old_rate = ice->get_rate(ice); - if (force || (old_rate != rate)) - ice->set_rate(ice, rate); - else if (rate == ice->cur_rate) { - spin_unlock_irqrestore(&ice->reg_lock, flags); - return 0; - } - } - - ice->cur_rate = rate; - - /* setting master clock */ - mclk_change = ice->set_mclk(ice, rate); - - spin_unlock_irqrestore(&ice->reg_lock, flags); - - if (mclk_change && ice->gpio.i2s_mclk_changed) - ice->gpio.i2s_mclk_changed(ice); - if (ice->gpio.set_pro_rate) - ice->gpio.set_pro_rate(ice, rate); - - /* set up codecs */ - for (i = 0; i < ice->akm_codecs; i++) { - if (ice->akm[i].ops.set_rate_val) - ice->akm[i].ops.set_rate_val(&ice->akm[i], rate); - } - if (ice->spdif.ops.setup_rate) - ice->spdif.ops.setup_rate(ice, rate); - - return 0; -} - -static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - int i, chs, err; - - chs = params_channels(hw_params); - mutex_lock(&ice->open_mutex); - /* mark surround channels */ - if (substream == ice->playback_pro_substream) { - /* PDMA0 can be multi-channel up to 8 */ - chs = chs / 2 - 1; - for (i = 0; i < chs; i++) { - if (ice->pcm_reserved[i] && - ice->pcm_reserved[i] != substream) { - mutex_unlock(&ice->open_mutex); - return -EBUSY; - } - ice->pcm_reserved[i] = substream; - } - for (; i < 3; i++) { - if (ice->pcm_reserved[i] == substream) - ice->pcm_reserved[i] = NULL; - } - } else { - for (i = 0; i < 3; i++) { - /* check individual playback stream */ - if (ice->playback_con_substream_ds[i] == substream) { - if (ice->pcm_reserved[i] && - ice->pcm_reserved[i] != substream) { - mutex_unlock(&ice->open_mutex); - return -EBUSY; - } - ice->pcm_reserved[i] = substream; - break; - } - } - } - mutex_unlock(&ice->open_mutex); - - err = snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0); - if (err < 0) - return err; - - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - int i; - - mutex_lock(&ice->open_mutex); - /* unmark surround channels */ - for (i = 0; i < 3; i++) - if (ice->pcm_reserved[i] == substream) - ice->pcm_reserved[i] = NULL; - mutex_unlock(&ice->open_mutex); - return snd_pcm_lib_free_pages(substream); -} - -static int snd_vt1724_playback_pro_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - unsigned char val; - unsigned int size; - - spin_lock_irq(&ice->reg_lock); - val = (8 - substream->runtime->channels) >> 1; - outb(val, ICEMT1724(ice, BURST)); - - outl(substream->runtime->dma_addr, ICEMT1724(ice, PLAYBACK_ADDR)); - - size = (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1; - /* outl(size, ICEMT1724(ice, PLAYBACK_SIZE)); */ - outw(size, ICEMT1724(ice, PLAYBACK_SIZE)); - outb(size >> 16, ICEMT1724(ice, PLAYBACK_SIZE) + 2); - size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1; - /* outl(size, ICEMT1724(ice, PLAYBACK_COUNT)); */ - outw(size, ICEMT1724(ice, PLAYBACK_COUNT)); - outb(size >> 16, ICEMT1724(ice, PLAYBACK_COUNT) + 2); - - spin_unlock_irq(&ice->reg_lock); - - /* - printk(KERN_DEBUG "pro prepare: ch = %d, addr = 0x%x, " - "buffer = 0x%x, period = 0x%x\n", - substream->runtime->channels, - (unsigned int)substream->runtime->dma_addr, - snd_pcm_lib_buffer_bytes(substream), - snd_pcm_lib_period_bytes(substream)); - */ - return 0; -} - -static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & VT1724_PDMA0_START)) - return 0; -#if 0 /* read PLAYBACK_ADDR */ - ptr = inl(ICEMT1724(ice, PLAYBACK_ADDR)); - if (ptr < substream->runtime->dma_addr) { - snd_printd("ice1724: invalid negative ptr\n"); - return 0; - } - ptr -= substream->runtime->dma_addr; - ptr = bytes_to_frames(substream->runtime, ptr); - if (ptr >= substream->runtime->buffer_size) { - snd_printd("ice1724: invalid ptr %d (size=%d)\n", - (int)ptr, (int)substream->runtime->period_size); - return 0; - } -#else /* read PLAYBACK_SIZE */ - ptr = inl(ICEMT1724(ice, PLAYBACK_SIZE)) & 0xffffff; - ptr = (ptr + 1) << 2; - ptr = bytes_to_frames(substream->runtime, ptr); - if (!ptr) - ; - else if (ptr <= substream->runtime->buffer_size) - ptr = substream->runtime->buffer_size - ptr; - else { - snd_printd("ice1724: invalid ptr %d (size=%d)\n", - (int)ptr, (int)substream->runtime->buffer_size); - ptr = 0; - } -#endif - return ptr; -} - -static int snd_vt1724_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - const struct vt1724_pcm_reg *reg = substream->runtime->private_data; - - spin_lock_irq(&ice->reg_lock); - outl(substream->runtime->dma_addr, ice->profi_port + reg->addr); - outw((snd_pcm_lib_buffer_bytes(substream) >> 2) - 1, - ice->profi_port + reg->size); - outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, - ice->profi_port + reg->count); - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static snd_pcm_uframes_t snd_vt1724_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - const struct vt1724_pcm_reg *reg = substream->runtime->private_data; - size_t ptr; - - if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & reg->start)) - return 0; -#if 0 /* use ADDR register */ - ptr = inl(ice->profi_port + reg->addr); - ptr -= substream->runtime->dma_addr; - return bytes_to_frames(substream->runtime, ptr); -#else /* use SIZE register */ - ptr = inw(ice->profi_port + reg->size); - ptr = (ptr + 1) << 2; - ptr = bytes_to_frames(substream->runtime, ptr); - if (!ptr) - ; - else if (ptr <= substream->runtime->buffer_size) - ptr = substream->runtime->buffer_size - ptr; - else { - snd_printd("ice1724: invalid ptr %d (size=%d)\n", - (int)ptr, (int)substream->runtime->buffer_size); - ptr = 0; - } - return ptr; -#endif -} - -static const struct vt1724_pcm_reg vt1724_pdma0_reg = { - .addr = VT1724_MT_PLAYBACK_ADDR, - .size = VT1724_MT_PLAYBACK_SIZE, - .count = VT1724_MT_PLAYBACK_COUNT, - .start = VT1724_PDMA0_START, -}; - -static const struct vt1724_pcm_reg vt1724_pdma4_reg = { - .addr = VT1724_MT_PDMA4_ADDR, - .size = VT1724_MT_PDMA4_SIZE, - .count = VT1724_MT_PDMA4_COUNT, - .start = VT1724_PDMA4_START, -}; - -static const struct vt1724_pcm_reg vt1724_rdma0_reg = { - .addr = VT1724_MT_CAPTURE_ADDR, - .size = VT1724_MT_CAPTURE_SIZE, - .count = VT1724_MT_CAPTURE_COUNT, - .start = VT1724_RDMA0_START, -}; - -static const struct vt1724_pcm_reg vt1724_rdma1_reg = { - .addr = VT1724_MT_RDMA1_ADDR, - .size = VT1724_MT_RDMA1_SIZE, - .count = VT1724_MT_RDMA1_COUNT, - .start = VT1724_RDMA1_START, -}; - -#define vt1724_playback_pro_reg vt1724_pdma0_reg -#define vt1724_playback_spdif_reg vt1724_pdma4_reg -#define vt1724_capture_pro_reg vt1724_rdma0_reg -#define vt1724_capture_spdif_reg vt1724_rdma1_reg - -static const struct snd_pcm_hardware snd_vt1724_playback_pro = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_192000, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 8, - .buffer_bytes_max = (1UL << 21), /* 19bits dword */ - .period_bytes_min = 8 * 4 * 2, /* FIXME: constraints needed */ - .period_bytes_max = (1UL << 21), - .periods_min = 2, - .periods_max = 1024, -}; - -static const struct snd_pcm_hardware snd_vt1724_spdif = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100| - SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_88200| - SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_176400| - SNDRV_PCM_RATE_192000), - .rate_min = 32000, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (1UL << 18), /* 16bits dword */ - .period_bytes_min = 2 * 4 * 2, - .period_bytes_max = (1UL << 18), - .periods_min = 2, - .periods_max = 1024, -}; - -static const struct snd_pcm_hardware snd_vt1724_2ch_stereo = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_192000, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (1UL << 18), /* 16bits dword */ - .period_bytes_min = 2 * 4 * 2, - .period_bytes_max = (1UL << 18), - .periods_min = 2, - .periods_max = 1024, -}; - -/* - * set rate constraints - */ -static void set_std_hw_rates(struct snd_ice1712 *ice) -{ - if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) { - /* I2S */ - /* VT1720 doesn't support more than 96kHz */ - if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720) - ice->hw_rates = &hw_constraints_rates_192; - else - ice->hw_rates = &hw_constraints_rates_96; - } else { - /* ACLINK */ - ice->hw_rates = &hw_constraints_rates_48; - } -} - -static int set_rate_constraints(struct snd_ice1712 *ice, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.rate_min = ice->hw_rates->list[0]; - runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1]; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - return snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - ice->hw_rates); -} - -/* if the card has the internal rate locked (is_pro_locked), limit runtime - hw rates to the current internal rate only. -*/ -static void constrain_rate_if_locked(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int rate; - if (is_pro_rate_locked(ice)) { - rate = ice->get_rate(ice); - if (rate >= runtime->hw.rate_min - && rate <= runtime->hw.rate_max) { - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - } -} - - -/* multi-channel playback needs alignment 8x32bit regardless of the channels - * actually used - */ -#define VT1724_BUFFER_ALIGN 0x20 - -static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - int chs, num_indeps; - - runtime->private_data = (void *)&vt1724_playback_pro_reg; - ice->playback_pro_substream = substream; - runtime->hw = snd_vt1724_playback_pro; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - set_rate_constraints(ice, substream); - mutex_lock(&ice->open_mutex); - /* calculate the currently available channels */ - num_indeps = ice->num_total_dacs / 2 - 1; - for (chs = 0; chs < num_indeps; chs++) { - if (ice->pcm_reserved[chs]) - break; - } - chs = (chs + 1) * 2; - runtime->hw.channels_max = chs; - if (chs > 2) /* channels must be even */ - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); - mutex_unlock(&ice->open_mutex); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - VT1724_BUFFER_ALIGN); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - VT1724_BUFFER_ALIGN); - constrain_rate_if_locked(substream); - if (ice->pro_open) - ice->pro_open(ice, substream); - return 0; -} - -static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->private_data = (void *)&vt1724_capture_pro_reg; - ice->capture_pro_substream = substream; - runtime->hw = snd_vt1724_2ch_stereo; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - set_rate_constraints(ice, substream); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - VT1724_BUFFER_ALIGN); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - VT1724_BUFFER_ALIGN); - constrain_rate_if_locked(substream); - if (ice->pro_open) - ice->pro_open(ice, substream); - return 0; -} - -static int snd_vt1724_playback_pro_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - if (PRO_RATE_RESET) - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0); - ice->playback_pro_substream = NULL; - - return 0; -} - -static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - if (PRO_RATE_RESET) - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0); - ice->capture_pro_substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_vt1724_playback_pro_ops = { - .open = snd_vt1724_playback_pro_open, - .close = snd_vt1724_playback_pro_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_vt1724_pcm_hw_params, - .hw_free = snd_vt1724_pcm_hw_free, - .prepare = snd_vt1724_playback_pro_prepare, - .trigger = snd_vt1724_pcm_trigger, - .pointer = snd_vt1724_playback_pro_pointer, -}; - -static struct snd_pcm_ops snd_vt1724_capture_pro_ops = { - .open = snd_vt1724_capture_pro_open, - .close = snd_vt1724_capture_pro_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_vt1724_pcm_hw_params, - .hw_free = snd_vt1724_pcm_hw_free, - .prepare = snd_vt1724_pcm_prepare, - .trigger = snd_vt1724_pcm_trigger, - .pointer = snd_vt1724_pcm_pointer, -}; - -static int __devinit snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device) -{ - struct snd_pcm *pcm; - int capt, err; - - if ((ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_ADC_MASK) == - VT1724_CFG_ADC_NONE) - capt = 0; - else - capt = 1; - err = snd_pcm_new(ice->card, "ICE1724", device, 1, capt, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_vt1724_playback_pro_ops); - if (capt) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_vt1724_capture_pro_ops); - - pcm->private_data = ice; - pcm->info_flags = 0; - strcpy(pcm->name, "ICE1724"); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(ice->pci), - 256*1024, 256*1024); - - ice->pcm_pro = pcm; - - return 0; -} - - -/* - * SPDIF PCM - */ - -/* update spdif control bits; call with reg_lock */ -static void update_spdif_bits(struct snd_ice1712 *ice, unsigned int val) -{ - unsigned char cbit, disabled; - - cbit = inb(ICEREG1724(ice, SPDIF_CFG)); - disabled = cbit & ~VT1724_CFG_SPDIF_OUT_EN; - if (cbit != disabled) - outb(disabled, ICEREG1724(ice, SPDIF_CFG)); - outw(val, ICEMT1724(ice, SPDIF_CTRL)); - if (cbit != disabled) - outb(cbit, ICEREG1724(ice, SPDIF_CFG)); - outw(val, ICEMT1724(ice, SPDIF_CTRL)); -} - -/* update SPDIF control bits according to the given rate */ -static void update_spdif_rate(struct snd_ice1712 *ice, unsigned int rate) -{ - unsigned int val, nval; - unsigned long flags; - - spin_lock_irqsave(&ice->reg_lock, flags); - nval = val = inw(ICEMT1724(ice, SPDIF_CTRL)); - nval &= ~(7 << 12); - switch (rate) { - case 44100: break; - case 48000: nval |= 2 << 12; break; - case 32000: nval |= 3 << 12; break; - case 88200: nval |= 4 << 12; break; - case 96000: nval |= 5 << 12; break; - case 192000: nval |= 6 << 12; break; - case 176400: nval |= 7 << 12; break; - } - if (val != nval) - update_spdif_bits(ice, nval); - spin_unlock_irqrestore(&ice->reg_lock, flags); -} - -static int snd_vt1724_playback_spdif_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - if (!ice->force_pdma4) - update_spdif_rate(ice, substream->runtime->rate); - return snd_vt1724_pcm_prepare(substream); -} - -static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->private_data = (void *)&vt1724_playback_spdif_reg; - ice->playback_con_substream = substream; - if (ice->force_pdma4) { - runtime->hw = snd_vt1724_2ch_stereo; - set_rate_constraints(ice, substream); - } else - runtime->hw = snd_vt1724_spdif; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - VT1724_BUFFER_ALIGN); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - VT1724_BUFFER_ALIGN); - constrain_rate_if_locked(substream); - if (ice->spdif.ops.open) - ice->spdif.ops.open(ice, substream); - return 0; -} - -static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - if (PRO_RATE_RESET) - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0); - ice->playback_con_substream = NULL; - if (ice->spdif.ops.close) - ice->spdif.ops.close(ice, substream); - - return 0; -} - -static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->private_data = (void *)&vt1724_capture_spdif_reg; - ice->capture_con_substream = substream; - if (ice->force_rdma1) { - runtime->hw = snd_vt1724_2ch_stereo; - set_rate_constraints(ice, substream); - } else - runtime->hw = snd_vt1724_spdif; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - VT1724_BUFFER_ALIGN); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - VT1724_BUFFER_ALIGN); - constrain_rate_if_locked(substream); - if (ice->spdif.ops.open) - ice->spdif.ops.open(ice, substream); - return 0; -} - -static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - if (PRO_RATE_RESET) - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0); - ice->capture_con_substream = NULL; - if (ice->spdif.ops.close) - ice->spdif.ops.close(ice, substream); - - return 0; -} - -static struct snd_pcm_ops snd_vt1724_playback_spdif_ops = { - .open = snd_vt1724_playback_spdif_open, - .close = snd_vt1724_playback_spdif_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_vt1724_pcm_hw_params, - .hw_free = snd_vt1724_pcm_hw_free, - .prepare = snd_vt1724_playback_spdif_prepare, - .trigger = snd_vt1724_pcm_trigger, - .pointer = snd_vt1724_pcm_pointer, -}; - -static struct snd_pcm_ops snd_vt1724_capture_spdif_ops = { - .open = snd_vt1724_capture_spdif_open, - .close = snd_vt1724_capture_spdif_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_vt1724_pcm_hw_params, - .hw_free = snd_vt1724_pcm_hw_free, - .prepare = snd_vt1724_pcm_prepare, - .trigger = snd_vt1724_pcm_trigger, - .pointer = snd_vt1724_pcm_pointer, -}; - - -static int __devinit snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device) -{ - char *name; - struct snd_pcm *pcm; - int play, capt; - int err; - - if (ice->force_pdma4 || - (ice->eeprom.data[ICE_EEP2_SPDIF] & VT1724_CFG_SPDIF_OUT_INT)) { - play = 1; - ice->has_spdif = 1; - } else - play = 0; - if (ice->force_rdma1 || - (ice->eeprom.data[ICE_EEP2_SPDIF] & VT1724_CFG_SPDIF_IN)) { - capt = 1; - ice->has_spdif = 1; - } else - capt = 0; - if (!play && !capt) - return 0; /* no spdif device */ - - if (ice->force_pdma4 || ice->force_rdma1) - name = "ICE1724 Secondary"; - else - name = "ICE1724 IEC958"; - err = snd_pcm_new(ice->card, name, device, play, capt, &pcm); - if (err < 0) - return err; - - if (play) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_vt1724_playback_spdif_ops); - if (capt) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_vt1724_capture_spdif_ops); - - pcm->private_data = ice; - pcm->info_flags = 0; - strcpy(pcm->name, name); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(ice->pci), - 256*1024, 256*1024); - - ice->pcm = pcm; - - return 0; -} - - -/* - * independent surround PCMs - */ - -static const struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = { - { - .addr = VT1724_MT_PDMA1_ADDR, - .size = VT1724_MT_PDMA1_SIZE, - .count = VT1724_MT_PDMA1_COUNT, - .start = VT1724_PDMA1_START, - }, - { - .addr = VT1724_MT_PDMA2_ADDR, - .size = VT1724_MT_PDMA2_SIZE, - .count = VT1724_MT_PDMA2_COUNT, - .start = VT1724_PDMA2_START, - }, - { - .addr = VT1724_MT_PDMA3_ADDR, - .size = VT1724_MT_PDMA3_SIZE, - .count = VT1724_MT_PDMA3_COUNT, - .start = VT1724_PDMA3_START, - }, -}; - -static int snd_vt1724_playback_indep_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - unsigned char val; - - spin_lock_irq(&ice->reg_lock); - val = 3 - substream->number; - if (inb(ICEMT1724(ice, BURST)) < val) - outb(val, ICEMT1724(ice, BURST)); - spin_unlock_irq(&ice->reg_lock); - return snd_vt1724_pcm_prepare(substream); -} - -static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - mutex_lock(&ice->open_mutex); - /* already used by PDMA0? */ - if (ice->pcm_reserved[substream->number]) { - mutex_unlock(&ice->open_mutex); - return -EBUSY; /* FIXME: should handle blocking mode properly */ - } - mutex_unlock(&ice->open_mutex); - runtime->private_data = (void *)&vt1724_playback_dma_regs[substream->number]; - ice->playback_con_substream_ds[substream->number] = substream; - runtime->hw = snd_vt1724_2ch_stereo; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - set_rate_constraints(ice, substream); - return 0; -} - -static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream) -{ - struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); - - if (PRO_RATE_RESET) - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0); - ice->playback_con_substream_ds[substream->number] = NULL; - ice->pcm_reserved[substream->number] = NULL; - - return 0; -} - -static struct snd_pcm_ops snd_vt1724_playback_indep_ops = { - .open = snd_vt1724_playback_indep_open, - .close = snd_vt1724_playback_indep_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_vt1724_pcm_hw_params, - .hw_free = snd_vt1724_pcm_hw_free, - .prepare = snd_vt1724_playback_indep_prepare, - .trigger = snd_vt1724_pcm_trigger, - .pointer = snd_vt1724_pcm_pointer, -}; - - -static int __devinit snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device) -{ - struct snd_pcm *pcm; - int play; - int err; - - play = ice->num_total_dacs / 2 - 1; - if (play <= 0) - return 0; - - err = snd_pcm_new(ice->card, "ICE1724 Surrounds", device, play, 0, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_vt1724_playback_indep_ops); - - pcm->private_data = ice; - pcm->info_flags = 0; - strcpy(pcm->name, "ICE1724 Surround PCM"); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(ice->pci), - 256*1024, 256*1024); - - ice->pcm_ds = pcm; - - return 0; -} - - -/* - * Mixer section - */ - -static int __devinit snd_vt1724_ac97_mixer(struct snd_ice1712 *ice) -{ - int err; - - if (!(ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S)) { - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = snd_vt1724_ac97_write, - .read = snd_vt1724_ac97_read, - }; - - /* cold reset */ - outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); - mdelay(5); /* FIXME */ - outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); - - err = snd_ac97_bus(ice->card, 0, &ops, NULL, &pbus); - if (err < 0) - return err; - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = ice; - err = snd_ac97_mixer(pbus, &ac97, &ice->ac97); - if (err < 0) - printk(KERN_WARNING "ice1712: cannot initialize pro ac97, skipped\n"); - else - return 0; - } - /* I2S mixer only */ - strcat(ice->card->mixername, "ICE1724 - multitrack"); - return 0; -} - -/* - * - */ - -static inline unsigned int eeprom_triple(struct snd_ice1712 *ice, int idx) -{ - return (unsigned int)ice->eeprom.data[idx] | \ - ((unsigned int)ice->eeprom.data[idx + 1] << 8) | \ - ((unsigned int)ice->eeprom.data[idx + 2] << 16); -} - -static void snd_vt1724_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - unsigned int idx; - - snd_iprintf(buffer, "%s\n\n", ice->card->longname); - snd_iprintf(buffer, "EEPROM:\n"); - - snd_iprintf(buffer, " Subvendor : 0x%x\n", ice->eeprom.subvendor); - snd_iprintf(buffer, " Size : %i bytes\n", ice->eeprom.size); - snd_iprintf(buffer, " Version : %i\n", ice->eeprom.version); - snd_iprintf(buffer, " System Config : 0x%x\n", - ice->eeprom.data[ICE_EEP2_SYSCONF]); - snd_iprintf(buffer, " ACLink : 0x%x\n", - ice->eeprom.data[ICE_EEP2_ACLINK]); - snd_iprintf(buffer, " I2S : 0x%x\n", - ice->eeprom.data[ICE_EEP2_I2S]); - snd_iprintf(buffer, " S/PDIF : 0x%x\n", - ice->eeprom.data[ICE_EEP2_SPDIF]); - snd_iprintf(buffer, " GPIO direction : 0x%x\n", - ice->eeprom.gpiodir); - snd_iprintf(buffer, " GPIO mask : 0x%x\n", - ice->eeprom.gpiomask); - snd_iprintf(buffer, " GPIO state : 0x%x\n", - ice->eeprom.gpiostate); - for (idx = 0x12; idx < ice->eeprom.size; idx++) - snd_iprintf(buffer, " Extra #%02i : 0x%x\n", - idx, ice->eeprom.data[idx]); - - snd_iprintf(buffer, "\nRegisters:\n"); - - snd_iprintf(buffer, " PSDOUT03 : 0x%08x\n", - (unsigned)inl(ICEMT1724(ice, ROUTE_PLAYBACK))); - for (idx = 0x0; idx < 0x20 ; idx++) - snd_iprintf(buffer, " CCS%02x : 0x%02x\n", - idx, inb(ice->port+idx)); - for (idx = 0x0; idx < 0x30 ; idx++) - snd_iprintf(buffer, " MT%02x : 0x%02x\n", - idx, inb(ice->profi_port+idx)); -} - -static void __devinit snd_vt1724_proc_init(struct snd_ice1712 *ice) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(ice->card, "ice1724", &entry)) - snd_info_set_text_ops(entry, ice, snd_vt1724_proc_read); -} - -/* - * - */ - -static int snd_vt1724_eeprom_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = sizeof(struct snd_ice1712_eeprom); - return 0; -} - -static int snd_vt1724_eeprom_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - memcpy(ucontrol->value.bytes.data, &ice->eeprom, sizeof(ice->eeprom)); - return 0; -} - -static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "ICE1724 EEPROM", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_vt1724_eeprom_info, - .get = snd_vt1724_eeprom_get -}; - -/* - */ -static int snd_vt1724_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static unsigned int encode_spdif_bits(struct snd_aes_iec958 *diga) -{ - unsigned int val, rbits; - - val = diga->status[0] & 0x03; /* professional, non-audio */ - if (val & 0x01) { - /* professional */ - if ((diga->status[0] & IEC958_AES0_PRO_EMPHASIS) == - IEC958_AES0_PRO_EMPHASIS_5015) - val |= 1U << 3; - rbits = (diga->status[4] >> 3) & 0x0f; - if (rbits) { - switch (rbits) { - case 2: val |= 5 << 12; break; /* 96k */ - case 3: val |= 6 << 12; break; /* 192k */ - case 10: val |= 4 << 12; break; /* 88.2k */ - case 11: val |= 7 << 12; break; /* 176.4k */ - } - } else { - switch (diga->status[0] & IEC958_AES0_PRO_FS) { - case IEC958_AES0_PRO_FS_44100: - break; - case IEC958_AES0_PRO_FS_32000: - val |= 3U << 12; - break; - default: - val |= 2U << 12; - break; - } - } - } else { - /* consumer */ - val |= diga->status[1] & 0x04; /* copyright */ - if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS) == - IEC958_AES0_CON_EMPHASIS_5015) - val |= 1U << 3; - val |= (unsigned int)(diga->status[1] & 0x3f) << 4; /* category */ - val |= (unsigned int)(diga->status[3] & IEC958_AES3_CON_FS) << 12; /* fs */ - } - return val; -} - -static void decode_spdif_bits(struct snd_aes_iec958 *diga, unsigned int val) -{ - memset(diga->status, 0, sizeof(diga->status)); - diga->status[0] = val & 0x03; /* professional, non-audio */ - if (val & 0x01) { - /* professional */ - if (val & (1U << 3)) - diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; - switch ((val >> 12) & 0x7) { - case 0: - break; - case 2: - diga->status[0] |= IEC958_AES0_PRO_FS_32000; - break; - default: - diga->status[0] |= IEC958_AES0_PRO_FS_48000; - break; - } - } else { - /* consumer */ - diga->status[0] |= val & (1U << 2); /* copyright */ - if (val & (1U << 3)) - diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015; - diga->status[1] |= (val >> 4) & 0x3f; /* category */ - diga->status[3] |= (val >> 12) & 0x07; /* fs */ - } -} - -static int snd_vt1724_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val; - val = inw(ICEMT1724(ice, SPDIF_CTRL)); - decode_spdif_bits(&ucontrol->value.iec958, val); - return 0; -} - -static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val, old; - - val = encode_spdif_bits(&ucontrol->value.iec958); - spin_lock_irq(&ice->reg_lock); - old = inw(ICEMT1724(ice, SPDIF_CTRL)); - if (val != old) - update_spdif_bits(ice, val); - spin_unlock_irq(&ice->reg_lock); - return val != old; -} - -static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = snd_vt1724_spdif_info, - .get = snd_vt1724_spdif_default_get, - .put = snd_vt1724_spdif_default_put -}; - -static int snd_vt1724_spdif_maskc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_CON_NOT_COPYRIGHT | - IEC958_AES0_CON_EMPHASIS; - ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL | - IEC958_AES1_CON_CATEGORY; - ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS; - return 0; -} - -static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_PRO_FS | - IEC958_AES0_PRO_EMPHASIS; - return 0; -} - -static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), - .info = snd_vt1724_spdif_info, - .get = snd_vt1724_spdif_maskc_get, -}; - -static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), - .info = snd_vt1724_spdif_info, - .get = snd_vt1724_spdif_maskp_get, -}; - -#define snd_vt1724_spdif_sw_info snd_ctl_boolean_mono_info - -static int snd_vt1724_spdif_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = inb(ICEREG1724(ice, SPDIF_CFG)) & - VT1724_CFG_SPDIF_OUT_EN ? 1 : 0; - return 0; -} - -static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char old, val; - - spin_lock_irq(&ice->reg_lock); - old = val = inb(ICEREG1724(ice, SPDIF_CFG)); - val &= ~VT1724_CFG_SPDIF_OUT_EN; - if (ucontrol->value.integer.value[0]) - val |= VT1724_CFG_SPDIF_OUT_EN; - if (old != val) - outb(val, ICEREG1724(ice, SPDIF_CFG)); - spin_unlock_irq(&ice->reg_lock); - return old != val; -} - -static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* FIXME: the following conflict with IEC958 Playback Route */ - /* .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), */ - .name = SNDRV_CTL_NAME_IEC958("Output ", NONE, SWITCH), - .info = snd_vt1724_spdif_sw_info, - .get = snd_vt1724_spdif_sw_get, - .put = snd_vt1724_spdif_sw_put -}; - - -#if 0 /* NOT USED YET */ -/* - * GPIO access from extern - */ - -#define snd_vt1724_gpio_info snd_ctl_boolean_mono_info - -int snd_vt1724_gpio_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value & (1<<24)) ? 1 : 0; - - snd_ice1712_save_gpio_status(ice); - ucontrol->value.integer.value[0] = - (snd_ice1712_gpio_read(ice) & (1 << shift) ? 1 : 0) ^ invert; - snd_ice1712_restore_gpio_status(ice); - return 0; -} - -int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value & (1<<24)) ? mask : 0; - unsigned int val, nval; - - if (kcontrol->private_value & (1 << 31)) - return -EPERM; - nval = (ucontrol->value.integer.value[0] ? (1 << shift) : 0) ^ invert; - snd_ice1712_save_gpio_status(ice); - val = snd_ice1712_gpio_read(ice); - nval |= val & ~(1 << shift); - if (val != nval) - snd_ice1712_gpio_write(ice, nval); - snd_ice1712_restore_gpio_status(ice); - return val != nval; -} -#endif /* NOT USED YET */ - -/* - * rate - */ -static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int hw_rates_count = ice->hw_rates->count; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - - /* internal clocks */ - uinfo->value.enumerated.items = hw_rates_count; - /* external clocks */ - if (ice->force_rdma1 || - (ice->eeprom.data[ICE_EEP2_SPDIF] & VT1724_CFG_SPDIF_IN)) - uinfo->value.enumerated.items += ice->ext_clock_count; - /* upper limit - keep at top */ - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - if (uinfo->value.enumerated.item >= hw_rates_count) - /* ext_clock items */ - strcpy(uinfo->value.enumerated.name, - ice->ext_clock_names[ - uinfo->value.enumerated.item - hw_rates_count]); - else - /* int clock items */ - sprintf(uinfo->value.enumerated.name, "%d", - ice->hw_rates->list[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int i, rate; - - spin_lock_irq(&ice->reg_lock); - if (ice->is_spdif_master(ice)) { - ucontrol->value.enumerated.item[0] = ice->hw_rates->count + - ice->get_spdif_master_type(ice); - } else { - rate = ice->get_rate(ice); - ucontrol->value.enumerated.item[0] = 0; - for (i = 0; i < ice->hw_rates->count; i++) { - if (ice->hw_rates->list[i] == rate) { - ucontrol->value.enumerated.item[0] = i; - break; - } - } - } - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static int stdclock_get_spdif_master_type(struct snd_ice1712 *ice) -{ - /* standard external clock - only single type - SPDIF IN */ - return 0; -} - -/* setting clock to external - SPDIF */ -static int stdclock_set_spdif_clock(struct snd_ice1712 *ice, int type) -{ - unsigned char oval; - unsigned char i2s_oval; - oval = inb(ICEMT1724(ice, RATE)); - outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); - /* setting 256fs */ - i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT)); - outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT)); - return 0; -} - - -static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int old_rate, new_rate; - unsigned int item = ucontrol->value.enumerated.item[0]; - unsigned int first_ext_clock = ice->hw_rates->count; - - if (item > first_ext_clock + ice->ext_clock_count - 1) - return -EINVAL; - - /* if rate = 0 => external clock */ - spin_lock_irq(&ice->reg_lock); - if (ice->is_spdif_master(ice)) - old_rate = 0; - else - old_rate = ice->get_rate(ice); - if (item >= first_ext_clock) { - /* switching to external clock */ - ice->set_spdif_clock(ice, item - first_ext_clock); - new_rate = 0; - } else { - /* internal on-card clock */ - new_rate = ice->hw_rates->list[item]; - ice->pro_rate_default = new_rate; - spin_unlock_irq(&ice->reg_lock); - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); - spin_lock_irq(&ice->reg_lock); - } - spin_unlock_irq(&ice->reg_lock); - - /* the first switch to the ext. clock mode? */ - if (old_rate != new_rate && !new_rate) { - /* notify akm chips as well */ - unsigned int i; - if (ice->gpio.set_pro_rate) - ice->gpio.set_pro_rate(ice, 0); - for (i = 0; i < ice->akm_codecs; i++) { - if (ice->akm[i].ops.set_rate_val) - ice->akm[i].ops.set_rate_val(&ice->akm[i], 0); - } - } - return old_rate != new_rate; -} - -static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Track Internal Clock", - .info = snd_vt1724_pro_internal_clock_info, - .get = snd_vt1724_pro_internal_clock_get, - .put = snd_vt1724_pro_internal_clock_put -}; - -#define snd_vt1724_pro_rate_locking_info snd_ctl_boolean_mono_info - -static int snd_vt1724_pro_rate_locking_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = PRO_RATE_LOCKED; - return 0; -} - -static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int change = 0, nval; - - nval = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&ice->reg_lock); - change = PRO_RATE_LOCKED != nval; - PRO_RATE_LOCKED = nval; - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Track Rate Locking", - .info = snd_vt1724_pro_rate_locking_info, - .get = snd_vt1724_pro_rate_locking_get, - .put = snd_vt1724_pro_rate_locking_put -}; - -#define snd_vt1724_pro_rate_reset_info snd_ctl_boolean_mono_info - -static int snd_vt1724_pro_rate_reset_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = PRO_RATE_RESET ? 1 : 0; - return 0; -} - -static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int change = 0, nval; - - nval = ucontrol->value.integer.value[0] ? 1 : 0; - spin_lock_irq(&ice->reg_lock); - change = PRO_RATE_RESET != nval; - PRO_RATE_RESET = nval; - spin_unlock_irq(&ice->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Multi Track Rate Reset", - .info = snd_vt1724_pro_rate_reset_info, - .get = snd_vt1724_pro_rate_reset_get, - .put = snd_vt1724_pro_rate_reset_put -}; - - -/* - * routing - */ -static int snd_vt1724_pro_route_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { - "PCM Out", /* 0 */ - "H/W In 0", "H/W In 1", /* 1-2 */ - "IEC958 In L", "IEC958 In R", /* 3-4 */ - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static inline int analog_route_shift(int idx) -{ - return (idx % 2) * 12 + ((idx / 2) * 3) + 8; -} - -static inline int digital_route_shift(int idx) -{ - return idx * 3; -} - -int snd_ice1724_get_route_val(struct snd_ice1712 *ice, int shift) -{ - unsigned long val; - unsigned char eitem; - static const unsigned char xlate[8] = { - 0, 255, 1, 2, 255, 255, 3, 4, - }; - - val = inl(ICEMT1724(ice, ROUTE_PLAYBACK)); - val >>= shift; - val &= 7; /* we now have 3 bits per output */ - eitem = xlate[val]; - if (eitem == 255) { - snd_BUG(); - return 0; - } - return eitem; -} - -int snd_ice1724_put_route_val(struct snd_ice1712 *ice, unsigned int val, - int shift) -{ - unsigned int old_val, nval; - int change; - static const unsigned char xroute[8] = { - 0, /* PCM */ - 2, /* PSDIN0 Left */ - 3, /* PSDIN0 Right */ - 6, /* SPDIN Left */ - 7, /* SPDIN Right */ - }; - - nval = xroute[val % 5]; - val = old_val = inl(ICEMT1724(ice, ROUTE_PLAYBACK)); - val &= ~(0x07 << shift); - val |= nval << shift; - change = val != old_val; - if (change) - outl(val, ICEMT1724(ice, ROUTE_PLAYBACK)); - return change; -} - -static int snd_vt1724_pro_route_analog_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - ucontrol->value.enumerated.item[0] = - snd_ice1724_get_route_val(ice, analog_route_shift(idx)); - return 0; -} - -static int snd_vt1724_pro_route_analog_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - return snd_ice1724_put_route_val(ice, - ucontrol->value.enumerated.item[0], - analog_route_shift(idx)); -} - -static int snd_vt1724_pro_route_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - ucontrol->value.enumerated.item[0] = - snd_ice1724_get_route_val(ice, digital_route_shift(idx)); - return 0; -} - -static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - return snd_ice1724_put_route_val(ice, - ucontrol->value.enumerated.item[0], - digital_route_shift(idx)); -} - -static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "H/W Playback Route", - .info = snd_vt1724_pro_route_info, - .get = snd_vt1724_pro_route_analog_get, - .put = snd_vt1724_pro_route_analog_put, -}; - -static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Route", - .info = snd_vt1724_pro_route_info, - .get = snd_vt1724_pro_route_spdif_get, - .put = snd_vt1724_pro_route_spdif_put, - .count = 2, -}; - - -static int snd_vt1724_pro_peak_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 22; /* FIXME: for compatibility with ice1712... */ - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx; - - spin_lock_irq(&ice->reg_lock); - for (idx = 0; idx < 22; idx++) { - outb(idx, ICEMT1724(ice, MONITOR_PEAKINDEX)); - ucontrol->value.integer.value[idx] = - inb(ICEMT1724(ice, MONITOR_PEAKDATA)); - } - spin_unlock_irq(&ice->reg_lock); - return 0; -} - -static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Multi Track Peak", - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_vt1724_pro_peak_info, - .get = snd_vt1724_pro_peak_get -}; - -/* - * - */ - -static struct snd_ice1712_card_info no_matched __devinitdata; - - -/* - ooAoo cards with no controls -*/ -static unsigned char ooaoo_sq210_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x4c, /* 49MHz crystal, no mpu401, no ADC, - 1xDACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0x78, /* no volume, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc1, /* out-en, out-int, out-ext */ - [ICE_EEP2_GPIO_DIR] = 0x00, /* no GPIOs are used */ - [ICE_EEP2_GPIO_DIR1] = 0x00, - [ICE_EEP2_GPIO_DIR2] = 0x00, - [ICE_EEP2_GPIO_MASK] = 0xff, - [ICE_EEP2_GPIO_MASK1] = 0xff, - [ICE_EEP2_GPIO_MASK2] = 0xff, - - [ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */ - [ICE_EEP2_GPIO_STATE1] = 0x00, /* all 1, but GPIO_CPLD_RW - and GPIO15 always zero */ - [ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */ -}; - - -struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = { - { - .name = "ooAoo SQ210a", - .model = "sq210a", - .eeprom_size = sizeof(ooaoo_sq210_eeprom), - .eeprom_data = ooaoo_sq210_eeprom, - }, - { } /* terminator */ -}; - -static struct snd_ice1712_card_info *card_tables[] __devinitdata = { - snd_vt1724_revo_cards, - snd_vt1724_amp_cards, - snd_vt1724_aureon_cards, - snd_vt1720_mobo_cards, - snd_vt1720_pontis_cards, - snd_vt1724_prodigy_hifi_cards, - snd_vt1724_prodigy192_cards, - snd_vt1724_juli_cards, - snd_vt1724_maya44_cards, - snd_vt1724_phase_cards, - snd_vt1724_wtm_cards, - snd_vt1724_se_cards, - snd_vt1724_qtet_cards, - snd_vt1724_ooaoo_cards, - NULL, -}; - - -/* - */ - -static void wait_i2c_busy(struct snd_ice1712 *ice) -{ - int t = 0x10000; - while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--) - ; - if (t == -1) - printk(KERN_ERR "ice1724: i2c busy timeout\n"); -} - -unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, - unsigned char dev, unsigned char addr) -{ - unsigned char val; - - mutex_lock(&ice->i2c_mutex); - wait_i2c_busy(ice); - outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); - outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); - wait_i2c_busy(ice); - val = inb(ICEREG1724(ice, I2C_DATA)); - mutex_unlock(&ice->i2c_mutex); - /* - printk(KERN_DEBUG "i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val); - */ - return val; -} - -void snd_vt1724_write_i2c(struct snd_ice1712 *ice, - unsigned char dev, unsigned char addr, unsigned char data) -{ - mutex_lock(&ice->i2c_mutex); - wait_i2c_busy(ice); - /* - printk(KERN_DEBUG "i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data); - */ - outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR)); - outb(data, ICEREG1724(ice, I2C_DATA)); - outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR)); - wait_i2c_busy(ice); - mutex_unlock(&ice->i2c_mutex); -} - -static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice, - const char *modelname) -{ - const int dev = 0xa0; /* EEPROM device address */ - unsigned int i, size; - struct snd_ice1712_card_info * const *tbl, *c; - - if (!modelname || !*modelname) { - ice->eeprom.subvendor = 0; - if ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_EEPROM) != 0) - ice->eeprom.subvendor = - (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) | - (snd_vt1724_read_i2c(ice, dev, 0x01) << 8) | - (snd_vt1724_read_i2c(ice, dev, 0x02) << 16) | - (snd_vt1724_read_i2c(ice, dev, 0x03) << 24); - if (ice->eeprom.subvendor == 0 || - ice->eeprom.subvendor == (unsigned int)-1) { - /* invalid subvendor from EEPROM, try the PCI - * subststem ID instead - */ - u16 vendor, device; - pci_read_config_word(ice->pci, PCI_SUBSYSTEM_VENDOR_ID, - &vendor); - pci_read_config_word(ice->pci, PCI_SUBSYSTEM_ID, &device); - ice->eeprom.subvendor = - ((unsigned int)swab16(vendor) << 16) | swab16(device); - if (ice->eeprom.subvendor == 0 || - ice->eeprom.subvendor == (unsigned int)-1) { - printk(KERN_ERR "ice1724: No valid ID is found\n"); - return -ENXIO; - } - } - } - for (tbl = card_tables; *tbl; tbl++) { - for (c = *tbl; c->name; c++) { - if (modelname && c->model && - !strcmp(modelname, c->model)) { - printk(KERN_INFO "ice1724: Using board model %s\n", - c->name); - ice->eeprom.subvendor = c->subvendor; - } else if (c->subvendor != ice->eeprom.subvendor) - continue; - if (!c->eeprom_size || !c->eeprom_data) - goto found; - /* if the EEPROM is given by the driver, use it */ - snd_printdd("using the defined eeprom..\n"); - ice->eeprom.version = 2; - ice->eeprom.size = c->eeprom_size + 6; - memcpy(ice->eeprom.data, c->eeprom_data, c->eeprom_size); - goto read_skipped; - } - } - printk(KERN_WARNING "ice1724: No matching model found for ID 0x%x\n", - ice->eeprom.subvendor); - - found: - ice->eeprom.size = snd_vt1724_read_i2c(ice, dev, 0x04); - if (ice->eeprom.size < 6) - ice->eeprom.size = 32; - else if (ice->eeprom.size > 32) { - printk(KERN_ERR "ice1724: Invalid EEPROM (size = %i)\n", - ice->eeprom.size); - return -EIO; - } - ice->eeprom.version = snd_vt1724_read_i2c(ice, dev, 0x05); - if (ice->eeprom.version != 2) - printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n", - ice->eeprom.version); - size = ice->eeprom.size - 6; - for (i = 0; i < size; i++) - ice->eeprom.data[i] = snd_vt1724_read_i2c(ice, dev, i + 6); - - read_skipped: - ice->eeprom.gpiomask = eeprom_triple(ice, ICE_EEP2_GPIO_MASK); - ice->eeprom.gpiostate = eeprom_triple(ice, ICE_EEP2_GPIO_STATE); - ice->eeprom.gpiodir = eeprom_triple(ice, ICE_EEP2_GPIO_DIR); - - return 0; -} - - - -static void snd_vt1724_chip_reset(struct snd_ice1712 *ice) -{ - outb(VT1724_RESET , ICEREG1724(ice, CONTROL)); - inb(ICEREG1724(ice, CONTROL)); /* pci posting flush */ - msleep(10); - outb(0, ICEREG1724(ice, CONTROL)); - inb(ICEREG1724(ice, CONTROL)); /* pci posting flush */ - msleep(10); -} - -static int snd_vt1724_chip_init(struct snd_ice1712 *ice) -{ - outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG)); - outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG)); - outb(ice->eeprom.data[ICE_EEP2_I2S], ICEREG1724(ice, I2S_FEATURES)); - outb(ice->eeprom.data[ICE_EEP2_SPDIF], ICEREG1724(ice, SPDIF_CFG)); - - ice->gpio.write_mask = ice->eeprom.gpiomask; - ice->gpio.direction = ice->eeprom.gpiodir; - snd_vt1724_set_gpio_mask(ice, ice->eeprom.gpiomask); - snd_vt1724_set_gpio_dir(ice, ice->eeprom.gpiodir); - snd_vt1724_set_gpio_data(ice, ice->eeprom.gpiostate); - - outb(0, ICEREG1724(ice, POWERDOWN)); - - /* MPU_RX and TX irq masks are cleared later dynamically */ - outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK)); - - /* don't handle FIFO overrun/underruns (just yet), - * since they cause machine lockups - */ - outb(VT1724_MULTI_FIFO_ERR, ICEMT1724(ice, DMA_INT_MASK)); - - return 0; -} - -static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice) -{ - int err; - struct snd_kcontrol *kctl; - - if (snd_BUG_ON(!ice->pcm)) - return -EIO; - - if (!ice->own_routing) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&snd_vt1724_mixer_pro_spdif_route, ice)); - if (err < 0) - return err; - } - - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_spdif_switch, ice)); - if (err < 0) - return err; - - err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_vt1724_spdif_default, ice)); - if (err < 0) - return err; - kctl->id.device = ice->pcm->device; - err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_vt1724_spdif_maskc, ice)); - if (err < 0) - return err; - kctl->id.device = ice->pcm->device; - err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_vt1724_spdif_maskp, ice)); - if (err < 0) - return err; - kctl->id.device = ice->pcm->device; -#if 0 /* use default only */ - err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_vt1724_spdif_stream, ice)); - if (err < 0) - return err; - kctl->id.device = ice->pcm->device; - ice->spdif.stream_ctl = kctl; -#endif - return 0; -} - - -static int __devinit snd_vt1724_build_controls(struct snd_ice1712 *ice) -{ - int err; - - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_eeprom, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_pro_internal_clock, ice)); - if (err < 0) - return err; - - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_pro_rate_locking, ice)); - if (err < 0) - return err; - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_pro_rate_reset, ice)); - if (err < 0) - return err; - - if (!ice->own_routing && ice->num_total_dacs > 0) { - struct snd_kcontrol_new tmp = snd_vt1724_mixer_pro_analog_route; - tmp.count = ice->num_total_dacs; - if (ice->vt1720 && tmp.count > 2) - tmp.count = 2; - err = snd_ctl_add(ice->card, snd_ctl_new1(&tmp, ice)); - if (err < 0) - return err; - } - - err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_mixer_pro_peak, ice)); - if (err < 0) - return err; - - return 0; -} - -static int snd_vt1724_free(struct snd_ice1712 *ice) -{ - if (!ice->port) - goto __hw_end; - /* mask all interrupts */ - outb(0xff, ICEMT1724(ice, DMA_INT_MASK)); - outb(0xff, ICEREG1724(ice, IRQMASK)); - /* --- */ -__hw_end: - if (ice->irq >= 0) - free_irq(ice->irq, ice); - pci_release_regions(ice->pci); - snd_ice1712_akm4xxx_free(ice); - pci_disable_device(ice->pci); - kfree(ice->spec); - kfree(ice); - return 0; -} - -static int snd_vt1724_dev_free(struct snd_device *device) -{ - struct snd_ice1712 *ice = device->device_data; - return snd_vt1724_free(ice); -} - -static int __devinit snd_vt1724_create(struct snd_card *card, - struct pci_dev *pci, - const char *modelname, - struct snd_ice1712 **r_ice1712) -{ - struct snd_ice1712 *ice; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_vt1724_dev_free, - }; - - *r_ice1712 = NULL; - - /* enable PCI device */ - err = pci_enable_device(pci); - if (err < 0) - return err; - - ice = kzalloc(sizeof(*ice), GFP_KERNEL); - if (ice == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - ice->vt1724 = 1; - spin_lock_init(&ice->reg_lock); - mutex_init(&ice->gpio_mutex); - mutex_init(&ice->open_mutex); - mutex_init(&ice->i2c_mutex); - ice->gpio.set_mask = snd_vt1724_set_gpio_mask; - ice->gpio.get_mask = snd_vt1724_get_gpio_mask; - ice->gpio.set_dir = snd_vt1724_set_gpio_dir; - ice->gpio.get_dir = snd_vt1724_get_gpio_dir; - ice->gpio.set_data = snd_vt1724_set_gpio_data; - ice->gpio.get_data = snd_vt1724_get_gpio_data; - ice->card = card; - ice->pci = pci; - ice->irq = -1; - pci_set_master(pci); - snd_vt1724_proc_init(ice); - synchronize_irq(pci->irq); - - card->private_data = ice; - - err = pci_request_regions(pci, "ICE1724"); - if (err < 0) { - kfree(ice); - pci_disable_device(pci); - return err; - } - ice->port = pci_resource_start(pci, 0); - ice->profi_port = pci_resource_start(pci, 1); - - if (request_irq(pci->irq, snd_vt1724_interrupt, - IRQF_SHARED, KBUILD_MODNAME, ice)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_vt1724_free(ice); - return -EIO; - } - - ice->irq = pci->irq; - - snd_vt1724_chip_reset(ice); - if (snd_vt1724_read_eeprom(ice, modelname) < 0) { - snd_vt1724_free(ice); - return -EIO; - } - if (snd_vt1724_chip_init(ice) < 0) { - snd_vt1724_free(ice); - return -EIO; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops); - if (err < 0) { - snd_vt1724_free(ice); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *r_ice1712 = ice; - return 0; -} - - -/* - * - * Registration - * - */ - -static int __devinit snd_vt1724_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_ice1712 *ice; - int pcm_dev = 0, err; - struct snd_ice1712_card_info * const *tbl, *c; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - strcpy(card->driver, "ICE1724"); - strcpy(card->shortname, "ICEnsemble ICE1724"); - - err = snd_vt1724_create(card, pci, model[dev], &ice); - if (err < 0) { - snd_card_free(card); - return err; - } - - /* field init before calling chip_init */ - ice->ext_clock_count = 0; - - for (tbl = card_tables; *tbl; tbl++) { - for (c = *tbl; c->name; c++) { - if ((model[dev] && c->model && - !strcmp(model[dev], c->model)) || - (c->subvendor == ice->eeprom.subvendor)) { - strcpy(card->shortname, c->name); - if (c->driver) /* specific driver? */ - strcpy(card->driver, c->driver); - if (c->chip_init) { - err = c->chip_init(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - } - goto __found; - } - } - } - c = &no_matched; -__found: - /* - * VT1724 has separate DMAs for the analog and the SPDIF streams while - * ICE1712 has only one for both (mixed up). - * - * Confusingly the analog PCM is named "professional" here because it - * was called so in ice1712 driver, and vt1724 driver is derived from - * ice1712 driver. - */ - ice->pro_rate_default = PRO_RATE_DEFAULT; - if (!ice->is_spdif_master) - ice->is_spdif_master = stdclock_is_spdif_master; - if (!ice->get_rate) - ice->get_rate = stdclock_get_rate; - if (!ice->set_rate) - ice->set_rate = stdclock_set_rate; - if (!ice->set_mclk) - ice->set_mclk = stdclock_set_mclk; - if (!ice->set_spdif_clock) - ice->set_spdif_clock = stdclock_set_spdif_clock; - if (!ice->get_spdif_master_type) - ice->get_spdif_master_type = stdclock_get_spdif_master_type; - if (!ice->ext_clock_names) - ice->ext_clock_names = ext_clock_names; - if (!ice->ext_clock_count) - ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); - - if (!ice->hw_rates) - set_std_hw_rates(ice); - - err = snd_vt1724_pcm_profi(ice, pcm_dev++); - if (err < 0) { - snd_card_free(card); - return err; - } - - err = snd_vt1724_pcm_spdif(ice, pcm_dev++); - if (err < 0) { - snd_card_free(card); - return err; - } - - err = snd_vt1724_pcm_indep(ice, pcm_dev++); - if (err < 0) { - snd_card_free(card); - return err; - } - - err = snd_vt1724_ac97_mixer(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - - err = snd_vt1724_build_controls(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - - if (ice->pcm && ice->has_spdif) { /* has SPDIF I/O */ - err = snd_vt1724_spdif_build_controls(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - } - - if (c->build_controls) { - err = c->build_controls(ice); - if (err < 0) { - snd_card_free(card); - return err; - } - } - - if (!c->no_mpu401) { - if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) { - struct snd_rawmidi *rmidi; - - err = snd_rawmidi_new(card, "MIDI", 0, 1, 1, &rmidi); - if (err < 0) { - snd_card_free(card); - return err; - } - ice->rmidi[0] = rmidi; - rmidi->private_data = ice; - strcpy(rmidi->name, "ICE1724 MIDI"); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &vt1724_midi_output_ops); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &vt1724_midi_input_ops); - - /* set watermarks */ - outb(VT1724_MPU_RX_FIFO | 0x1, - ICEREG1724(ice, MPU_FIFO_WM)); - outb(0x1, ICEREG1724(ice, MPU_FIFO_WM)); - /* set UART mode */ - outb(VT1724_MPU_UART, ICEREG1724(ice, MPU_CTRL)); - } - } - - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, ice->port, ice->irq); - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_vt1724_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -#ifdef CONFIG_PM -static int snd_vt1724_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ice1712 *ice = card->private_data; - - if (!ice->pm_suspend_enabled) - return 0; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(ice->pcm); - snd_pcm_suspend_all(ice->pcm_pro); - snd_pcm_suspend_all(ice->pcm_ds); - snd_ac97_suspend(ice->ac97); - - spin_lock_irq(&ice->reg_lock); - ice->pm_saved_is_spdif_master = ice->is_spdif_master(ice); - ice->pm_saved_spdif_ctrl = inw(ICEMT1724(ice, SPDIF_CTRL)); - ice->pm_saved_spdif_cfg = inb(ICEREG1724(ice, SPDIF_CFG)); - ice->pm_saved_route = inl(ICEMT1724(ice, ROUTE_PLAYBACK)); - spin_unlock_irq(&ice->reg_lock); - - if (ice->pm_suspend) - ice->pm_suspend(ice); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_vt1724_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ice1712 *ice = card->private_data; - - if (!ice->pm_suspend_enabled) - return 0; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - - if (pci_enable_device(pci) < 0) { - snd_card_disconnect(card); - return -EIO; - } - - pci_set_master(pci); - - snd_vt1724_chip_reset(ice); - - if (snd_vt1724_chip_init(ice) < 0) { - snd_card_disconnect(card); - return -EIO; - } - - if (ice->pm_resume) - ice->pm_resume(ice); - - if (ice->pm_saved_is_spdif_master) { - /* switching to external clock via SPDIF */ - ice->set_spdif_clock(ice, 0); - } else { - /* internal on-card clock */ - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); - } - - update_spdif_bits(ice, ice->pm_saved_spdif_ctrl); - - outb(ice->pm_saved_spdif_cfg, ICEREG1724(ice, SPDIF_CFG)); - outl(ice->pm_saved_route, ICEMT1724(ice, ROUTE_PLAYBACK)); - - if (ice->ac97) - snd_ac97_resume(ice->ac97); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_vt1724_ids, - .probe = snd_vt1724_probe, - .remove = __devexit_p(snd_vt1724_remove), -#ifdef CONFIG_PM - .suspend = snd_vt1724_suspend, - .resume = snd_vt1724_resume, -#endif -}; - -static int __init alsa_card_ice1724_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_ice1724_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_ice1724_init) -module_exit(alsa_card_ice1724_exit) diff --git a/ANDROID_3.4.5/sound/pci/ice1712/juli.c b/ANDROID_3.4.5/sound/pci/ice1712/juli.c deleted file mode 100644 index 98bc3b76..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/juli.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for ESI Juli@ cards - * - * Copyright (c) 2004 Jaroslav Kysela - * 2008 Pavel Hofman - * - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include "juli.h" - -struct juli_spec { - struct ak4114 *ak4114; - unsigned int analog:1; -}; - -/* - * chip addresses on I2C bus - */ -#define AK4114_ADDR 0x20 /* S/PDIF receiver */ -#define AK4358_ADDR 0x22 /* DAC */ - -/* - * Juli does not use the standard ICE1724 clock scheme. Juli's ice1724 chip is - * supplied by external clock provided by Xilinx array and MK73-1 PLL frequency - * multiplier. Actual frequency is set by ice1724 GPIOs hooked to the Xilinx. - * - * The clock circuitry is supplied by the two ice1724 crystals. This - * arrangement allows to generate independent clock signal for AK4114's input - * rate detection circuit. As a result, Juli, unlike most other - * ice1724+ak4114-based cards, detects spdif input rate correctly. - * This fact is applied in the driver, allowing to modify PCM stream rate - * parameter according to the actual input rate. - * - * Juli uses the remaining three stereo-channels of its DAC to optionally - * monitor analog input, digital input, and digital output. The corresponding - * I2S signals are routed by Xilinx, controlled by GPIOs. - * - * The master mute is implemented using output muting transistors (GPIO) in - * combination with smuting the DAC. - * - * The card itself has no HW master volume control, implemented using the - * vmaster control. - * - * TODO: - * researching and fixing the input monitors - */ - -/* - * GPIO pins - */ -#define GPIO_FREQ_MASK (3<<0) -#define GPIO_FREQ_32KHZ (0<<0) -#define GPIO_FREQ_44KHZ (1<<0) -#define GPIO_FREQ_48KHZ (2<<0) -#define GPIO_MULTI_MASK (3<<2) -#define GPIO_MULTI_4X (0<<2) -#define GPIO_MULTI_2X (1<<2) -#define GPIO_MULTI_1X (2<<2) /* also external */ -#define GPIO_MULTI_HALF (3<<2) -#define GPIO_INTERNAL_CLOCK (1<<4) /* 0 = external, 1 = internal */ -#define GPIO_CLOCK_MASK (1<<4) -#define GPIO_ANALOG_PRESENT (1<<5) /* RO only: 0 = present */ -#define GPIO_RXMCLK_SEL (1<<7) /* must be 0 */ -#define GPIO_AK5385A_CKS0 (1<<8) -#define GPIO_AK5385A_DFS1 (1<<9) -#define GPIO_AK5385A_DFS0 (1<<10) -#define GPIO_DIGOUT_MONITOR (1<<11) /* 1 = active */ -#define GPIO_DIGIN_MONITOR (1<<12) /* 1 = active */ -#define GPIO_ANAIN_MONITOR (1<<13) /* 1 = active */ -#define GPIO_AK5385A_CKS1 (1<<14) /* must be 0 */ -#define GPIO_MUTE_CONTROL (1<<15) /* output mute, 1 = muted */ - -#define GPIO_RATE_MASK (GPIO_FREQ_MASK | GPIO_MULTI_MASK | \ - GPIO_CLOCK_MASK) -#define GPIO_AK5385A_MASK (GPIO_AK5385A_CKS0 | GPIO_AK5385A_DFS0 | \ - GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS1) - -#define JULI_PCM_RATE (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ - SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) - -#define GPIO_RATE_16000 (GPIO_FREQ_32KHZ | GPIO_MULTI_HALF | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_22050 (GPIO_FREQ_44KHZ | GPIO_MULTI_HALF | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_24000 (GPIO_FREQ_48KHZ | GPIO_MULTI_HALF | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_32000 (GPIO_FREQ_32KHZ | GPIO_MULTI_1X | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_44100 (GPIO_FREQ_44KHZ | GPIO_MULTI_1X | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_48000 (GPIO_FREQ_48KHZ | GPIO_MULTI_1X | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_64000 (GPIO_FREQ_32KHZ | GPIO_MULTI_2X | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_88200 (GPIO_FREQ_44KHZ | GPIO_MULTI_2X | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_96000 (GPIO_FREQ_48KHZ | GPIO_MULTI_2X | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_176400 (GPIO_FREQ_44KHZ | GPIO_MULTI_4X | \ - GPIO_INTERNAL_CLOCK) -#define GPIO_RATE_192000 (GPIO_FREQ_48KHZ | GPIO_MULTI_4X | \ - GPIO_INTERNAL_CLOCK) - -/* - * Initial setup of the conversion array GPIO <-> rate - */ -static unsigned int juli_rates[] = { - 16000, 22050, 24000, 32000, - 44100, 48000, 64000, 88200, - 96000, 176400, 192000, -}; - -static unsigned int gpio_vals[] = { - GPIO_RATE_16000, GPIO_RATE_22050, GPIO_RATE_24000, GPIO_RATE_32000, - GPIO_RATE_44100, GPIO_RATE_48000, GPIO_RATE_64000, GPIO_RATE_88200, - GPIO_RATE_96000, GPIO_RATE_176400, GPIO_RATE_192000, -}; - -static struct snd_pcm_hw_constraint_list juli_rates_info = { - .count = ARRAY_SIZE(juli_rates), - .list = juli_rates, - .mask = 0, -}; - -static int get_gpio_val(int rate) -{ - int i; - for (i = 0; i < ARRAY_SIZE(juli_rates); i++) - if (juli_rates[i] == rate) - return gpio_vals[i]; - return 0; -} - -static void juli_ak4114_write(void *private_data, unsigned char reg, - unsigned char val) -{ - snd_vt1724_write_i2c((struct snd_ice1712 *)private_data, AK4114_ADDR, - reg, val); -} - -static unsigned char juli_ak4114_read(void *private_data, unsigned char reg) -{ - return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, - AK4114_ADDR, reg); -} - -/* - * If SPDIF capture and slaved to SPDIF-IN, setting runtime rate - * to the external rate - */ -static void juli_spdif_in_open(struct snd_ice1712 *ice, - struct snd_pcm_substream *substream) -{ - struct juli_spec *spec = ice->spec; - struct snd_pcm_runtime *runtime = substream->runtime; - int rate; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - !ice->is_spdif_master(ice)) - return; - rate = snd_ak4114_external_rate(spec->ak4114); - if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) { - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } -} - -/* - * AK4358 section - */ - -static void juli_akm_lock(struct snd_akm4xxx *ak, int chip) -{ -} - -static void juli_akm_unlock(struct snd_akm4xxx *ak, int chip) -{ -} - -static void juli_akm_write(struct snd_akm4xxx *ak, int chip, - unsigned char addr, unsigned char data) -{ - struct snd_ice1712 *ice = ak->private_data[0]; - - if (snd_BUG_ON(chip)) - return; - snd_vt1724_write_i2c(ice, AK4358_ADDR, addr, data); -} - -/* - * change the rate of envy24HT, AK4358, AK5385 - */ -static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) -{ - unsigned char old, tmp, ak4358_dfs; - unsigned int ak5385_pins, old_gpio, new_gpio; - struct snd_ice1712 *ice = ak->private_data[0]; - struct juli_spec *spec = ice->spec; - - if (rate == 0) /* no hint - S/PDIF input is master or the new spdif - input rate undetected, simply return */ - return; - - /* adjust DFS on codecs */ - if (rate > 96000) { - ak4358_dfs = 2; - ak5385_pins = GPIO_AK5385A_DFS1 | GPIO_AK5385A_CKS0; - } else if (rate > 48000) { - ak4358_dfs = 1; - ak5385_pins = GPIO_AK5385A_DFS0; - } else { - ak4358_dfs = 0; - ak5385_pins = 0; - } - /* AK5385 first, since it requires cold reset affecting both codecs */ - old_gpio = ice->gpio.get_data(ice); - new_gpio = (old_gpio & ~GPIO_AK5385A_MASK) | ak5385_pins; - /* printk(KERN_DEBUG "JULI - ak5385 set_rate_val: new gpio 0x%x\n", - new_gpio); */ - ice->gpio.set_data(ice, new_gpio); - - /* cold reset */ - old = inb(ICEMT1724(ice, AC97_CMD)); - outb(old | VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD)); - udelay(1); - outb(old & ~VT1724_AC97_COLD, ICEMT1724(ice, AC97_CMD)); - - /* AK4358 */ - /* set new value, reset DFS */ - tmp = snd_akm4xxx_get(ak, 0, 2); - snd_akm4xxx_reset(ak, 1); - tmp = snd_akm4xxx_get(ak, 0, 2); - tmp &= ~(0x03 << 4); - tmp |= ak4358_dfs << 4; - snd_akm4xxx_set(ak, 0, 2, tmp); - snd_akm4xxx_reset(ak, 0); - - /* reinit ak4114 */ - snd_ak4114_reinit(spec->ak4114); -} - -#define AK_DAC(xname, xch) { .name = xname, .num_channels = xch } -#define PCM_VOLUME "PCM Playback Volume" -#define MONITOR_AN_IN_VOLUME "Monitor Analog In Volume" -#define MONITOR_DIG_IN_VOLUME "Monitor Digital In Volume" -#define MONITOR_DIG_OUT_VOLUME "Monitor Digital Out Volume" - -static const struct snd_akm4xxx_dac_channel juli_dac[] = { - AK_DAC(PCM_VOLUME, 2), - AK_DAC(MONITOR_AN_IN_VOLUME, 2), - AK_DAC(MONITOR_DIG_OUT_VOLUME, 2), - AK_DAC(MONITOR_DIG_IN_VOLUME, 2), -}; - - -static struct snd_akm4xxx akm_juli_dac __devinitdata = { - .type = SND_AK4358, - .num_dacs = 8, /* DAC1 - analog out - DAC2 - analog in monitor - DAC3 - digital out monitor - DAC4 - digital in monitor - */ - .ops = { - .lock = juli_akm_lock, - .unlock = juli_akm_unlock, - .write = juli_akm_write, - .set_rate_val = juli_akm_set_rate_val - }, - .dac_info = juli_dac, -}; - -#define juli_mute_info snd_ctl_boolean_mono_info - -static int juli_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val; - val = ice->gpio.get_data(ice) & (unsigned int) kcontrol->private_value; - if (kcontrol->private_value == GPIO_MUTE_CONTROL) - /* val 0 = signal on */ - ucontrol->value.integer.value[0] = (val) ? 0 : 1; - else - /* val 1 = signal on */ - ucontrol->value.integer.value[0] = (val) ? 1 : 0; - return 0; -} - -static int juli_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int old_gpio, new_gpio; - old_gpio = ice->gpio.get_data(ice); - if (ucontrol->value.integer.value[0]) { - /* unmute */ - if (kcontrol->private_value == GPIO_MUTE_CONTROL) { - /* 0 = signal on */ - new_gpio = old_gpio & ~GPIO_MUTE_CONTROL; - /* un-smuting DAC */ - snd_akm4xxx_write(ice->akm, 0, 0x01, 0x01); - } else - /* 1 = signal on */ - new_gpio = old_gpio | - (unsigned int) kcontrol->private_value; - } else { - /* mute */ - if (kcontrol->private_value == GPIO_MUTE_CONTROL) { - /* 1 = signal off */ - new_gpio = old_gpio | GPIO_MUTE_CONTROL; - /* smuting DAC */ - snd_akm4xxx_write(ice->akm, 0, 0x01, 0x03); - } else - /* 0 = signal off */ - new_gpio = old_gpio & - ~((unsigned int) kcontrol->private_value); - } - /* printk(KERN_DEBUG - "JULI - mute/unmute: control_value: 0x%x, old_gpio: 0x%x, " - "new_gpio 0x%x\n", - (unsigned int)ucontrol->value.integer.value[0], old_gpio, - new_gpio); */ - if (old_gpio != new_gpio) { - ice->gpio.set_data(ice, new_gpio); - return 1; - } - /* no change */ - return 0; -} - -static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = juli_mute_info, - .get = juli_mute_get, - .put = juli_mute_put, - .private_value = GPIO_MUTE_CONTROL, - }, - /* Although the following functionality respects the succint NDA'd - * documentation from the card manufacturer, and the same way of - * operation is coded in OSS Juli driver, only Digital Out monitor - * seems to work. Surprisingly, Analog input monitor outputs Digital - * output data. The two are independent, as enabling both doubles - * volume of the monitor sound. - * - * Checking traces on the board suggests the functionality described - * by the manufacturer is correct - I2S from ADC and AK4114 - * go to ICE as well as to Xilinx, I2S inputs of DAC2,3,4 (the monitor - * inputs) are fed from Xilinx. - * - * I even checked traces on board and coded a support in driver for - * an alternative possibility - the unused I2S ICE output channels - * switched to HW-IN/SPDIF-IN and providing the monitoring signal to - * the DAC - to no avail. The I2S outputs seem to be unconnected. - * - * The windows driver supports the monitoring correctly. - */ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitor Analog In Switch", - .info = juli_mute_info, - .get = juli_mute_get, - .put = juli_mute_put, - .private_value = GPIO_ANAIN_MONITOR, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitor Digital Out Switch", - .info = juli_mute_info, - .get = juli_mute_get, - .put = juli_mute_put, - .private_value = GPIO_DIGOUT_MONITOR, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitor Digital In Switch", - .info = juli_mute_info, - .get = juli_mute_get, - .put = juli_mute_put, - .private_value = GPIO_DIGIN_MONITOR, - }, -}; - -static char *slave_vols[] __devinitdata = { - PCM_VOLUME, - MONITOR_AN_IN_VOLUME, - MONITOR_DIG_IN_VOLUME, - MONITOR_DIG_OUT_VOLUME, - NULL -}; - -static __devinitdata -DECLARE_TLV_DB_SCALE(juli_master_db_scale, -6350, 50, 1); - -static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, - const char *name) -{ - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - /* FIXME: strcpy is bad. */ - strcpy(sid.name, name); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_find_id(card, &sid); -} - -static void __devinit add_slaves(struct snd_card *card, - struct snd_kcontrol *master, char **list) -{ - for (; *list; list++) { - struct snd_kcontrol *slave = ctl_find(card, *list); - /* printk(KERN_DEBUG "add_slaves - %s\n", *list); */ - if (slave) { - /* printk(KERN_DEBUG "slave %s found\n", *list); */ - snd_ctl_add_slave(master, slave); - } - } -} - -static int __devinit juli_add_controls(struct snd_ice1712 *ice) -{ - struct juli_spec *spec = ice->spec; - int err; - unsigned int i; - struct snd_kcontrol *vmaster; - - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - - for (i = 0; i < ARRAY_SIZE(juli_mute_controls); i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&juli_mute_controls[i], ice)); - if (err < 0) - return err; - } - /* Create virtual master control */ - vmaster = snd_ctl_make_virtual_master("Master Playback Volume", - juli_master_db_scale); - if (!vmaster) - return -ENOMEM; - add_slaves(ice->card, vmaster, slave_vols); - err = snd_ctl_add(ice->card, vmaster); - if (err < 0) - return err; - - /* only capture SPDIF over AK4114 */ - err = snd_ak4114_build(spec->ak4114, NULL, - ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); - if (err < 0) - return err; - return 0; -} - -/* - * suspend/resume - * */ - -#ifdef CONFIG_PM -static int juli_resume(struct snd_ice1712 *ice) -{ - struct snd_akm4xxx *ak = ice->akm; - struct juli_spec *spec = ice->spec; - /* akm4358 un-reset, un-mute */ - snd_akm4xxx_reset(ak, 0); - /* reinit ak4114 */ - snd_ak4114_reinit(spec->ak4114); - return 0; -} - -static int juli_suspend(struct snd_ice1712 *ice) -{ - struct snd_akm4xxx *ak = ice->akm; - /* akm4358 reset and soft-mute */ - snd_akm4xxx_reset(ak, 1); - return 0; -} -#endif - -/* - * initialize the chip - */ - -static inline int juli_is_spdif_master(struct snd_ice1712 *ice) -{ - return (ice->gpio.get_data(ice) & GPIO_INTERNAL_CLOCK) ? 0 : 1; -} - -static unsigned int juli_get_rate(struct snd_ice1712 *ice) -{ - int i; - unsigned char result; - - result = ice->gpio.get_data(ice) & GPIO_RATE_MASK; - for (i = 0; i < ARRAY_SIZE(gpio_vals); i++) - if (gpio_vals[i] == result) - return juli_rates[i]; - return 0; -} - -/* setting new rate */ -static void juli_set_rate(struct snd_ice1712 *ice, unsigned int rate) -{ - unsigned int old, new; - unsigned char val; - - old = ice->gpio.get_data(ice); - new = (old & ~GPIO_RATE_MASK) | get_gpio_val(rate); - /* printk(KERN_DEBUG "JULI - set_rate: old %x, new %x\n", - old & GPIO_RATE_MASK, - new & GPIO_RATE_MASK); */ - - ice->gpio.set_data(ice, new); - /* switching to external clock - supplied by external circuits */ - val = inb(ICEMT1724(ice, RATE)); - outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); -} - -static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice, - unsigned int rate) -{ - /* no change in master clock */ - return 0; -} - -/* setting clock to external - SPDIF */ -static int juli_set_spdif_clock(struct snd_ice1712 *ice, int type) -{ - unsigned int old; - old = ice->gpio.get_data(ice); - /* external clock (= 0), multiply 1x, 48kHz */ - ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X | - GPIO_FREQ_48KHZ); - return 0; -} - -/* Called when ak4114 detects change in the input SPDIF stream */ -static void juli_ak4114_change(struct ak4114 *ak4114, unsigned char c0, - unsigned char c1) -{ - struct snd_ice1712 *ice = ak4114->change_callback_private; - int rate; - if (ice->is_spdif_master(ice) && c1) { - /* only for SPDIF master mode, rate was changed */ - rate = snd_ak4114_external_rate(ak4114); - /* printk(KERN_DEBUG "ak4114 - input rate changed to %d\n", - rate); */ - juli_akm_set_rate_val(ice->akm, rate); - } -} - -static int __devinit juli_init(struct snd_ice1712 *ice) -{ - static const unsigned char ak4114_init_vals[] = { - /* AK4117_REG_PWRDN */ AK4114_RST | AK4114_PWN | - AK4114_OCKS0 | AK4114_OCKS1, - /* AK4114_REQ_FORMAT */ AK4114_DIF_I24I2S, - /* AK4114_REG_IO0 */ AK4114_TX1E, - /* AK4114_REG_IO1 */ AK4114_EFH_1024 | AK4114_DIT | - AK4114_IPS(1), - /* AK4114_REG_INT0_MASK */ 0, - /* AK4114_REG_INT1_MASK */ 0 - }; - static const unsigned char ak4114_init_txcsb[] = { - 0x41, 0x02, 0x2c, 0x00, 0x00 - }; - int err; - struct juli_spec *spec; - struct snd_akm4xxx *ak; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - err = snd_ak4114_create(ice->card, - juli_ak4114_read, - juli_ak4114_write, - ak4114_init_vals, ak4114_init_txcsb, - ice, &spec->ak4114); - if (err < 0) - return err; - /* callback for codecs rate setting */ - spec->ak4114->change_callback = juli_ak4114_change; - spec->ak4114->change_callback_private = ice; - /* AK4114 in Juli can detect external rate correctly */ - spec->ak4114->check_flags = 0; - -#if 0 -/* - * it seems that the analog doughter board detection does not work reliably, so - * force the analog flag; it should be very rare (if ever) to come at Juli@ - * used without the analog daughter board - */ - spec->analog = (ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT) ? 0 : 1; -#else - spec->analog = 1; -#endif - - if (spec->analog) { - printk(KERN_INFO "juli@: analog I/O detected\n"); - ice->num_total_dacs = 2; - ice->num_total_adcs = 2; - - ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - ak = ice->akm; - if (!ak) - return -ENOMEM; - ice->akm_codecs = 1; - err = snd_ice1712_akm4xxx_init(ak, &akm_juli_dac, NULL, ice); - if (err < 0) - return err; - } - - /* juli is clocked by Xilinx array */ - ice->hw_rates = &juli_rates_info; - ice->is_spdif_master = juli_is_spdif_master; - ice->get_rate = juli_get_rate; - ice->set_rate = juli_set_rate; - ice->set_mclk = juli_set_mclk; - ice->set_spdif_clock = juli_set_spdif_clock; - - ice->spdif.ops.open = juli_spdif_in_open; - -#ifdef CONFIG_PM - ice->pm_resume = juli_resume; - ice->pm_suspend = juli_suspend; - ice->pm_suspend_enabled = 1; -#endif - - return 0; -} - - -/* - * Juli@ boards don't provide the EEPROM data except for the vendor IDs. - * hence the driver needs to sets up it properly. - */ - -static unsigned char juli_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, 1xADC, 1xDACs, - SPDIF in */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0x9f, /* 5, 6:inputs; 7, 4-0 outputs*/ - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0x7f, - [ICE_EEP2_GPIO_MASK] = 0x60, /* 5, 6: locked; 7, 4-0 writable */ - [ICE_EEP2_GPIO_MASK1] = 0x00, /* 0-7 writable */ - [ICE_EEP2_GPIO_MASK2] = 0x7f, - [ICE_EEP2_GPIO_STATE] = GPIO_FREQ_48KHZ | GPIO_MULTI_1X | - GPIO_INTERNAL_CLOCK, /* internal clock, multiple 1x, 48kHz*/ - [ICE_EEP2_GPIO_STATE1] = 0x00, /* unmuted */ - [ICE_EEP2_GPIO_STATE2] = 0x00, -}; - -/* entry point */ -struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_JULI, - .name = "ESI Juli@", - .model = "juli", - .chip_init = juli_init, - .build_controls = juli_add_controls, - .eeprom_size = sizeof(juli_eeprom), - .eeprom_data = juli_eeprom, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/juli.h b/ANDROID_3.4.5/sound/pci/ice1712/juli.h deleted file mode 100644 index d9f8534f..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/juli.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __SOUND_JULI_H -#define __SOUND_JULI_H - -#define JULI_DEVICE_DESC "{ESI,Juli@}," - -#define VT1724_SUBDEVICE_JULI 0x31305345 /* Juli@ */ - -extern struct snd_ice1712_card_info snd_vt1724_juli_cards[]; - -#endif /* __SOUND_JULI_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/maya44.c b/ANDROID_3.4.5/sound/pci/ice1712/maya44.c deleted file mode 100644 index 726fd4b9..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/maya44.c +++ /dev/null @@ -1,779 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for ESI Maya44 cards - * - * Copyright (c) 2009 Takashi Iwai - * Based on the patches by Rainer Zimmermann - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include "maya44.h" - -/* WM8776 register indexes */ -#define WM8776_REG_HEADPHONE_L 0x00 -#define WM8776_REG_HEADPHONE_R 0x01 -#define WM8776_REG_HEADPHONE_MASTER 0x02 -#define WM8776_REG_DAC_ATTEN_L 0x03 -#define WM8776_REG_DAC_ATTEN_R 0x04 -#define WM8776_REG_DAC_ATTEN_MASTER 0x05 -#define WM8776_REG_DAC_PHASE 0x06 -#define WM8776_REG_DAC_CONTROL 0x07 -#define WM8776_REG_DAC_MUTE 0x08 -#define WM8776_REG_DAC_DEEMPH 0x09 -#define WM8776_REG_DAC_IF_CONTROL 0x0a -#define WM8776_REG_ADC_IF_CONTROL 0x0b -#define WM8776_REG_MASTER_MODE_CONTROL 0x0c -#define WM8776_REG_POWERDOWN 0x0d -#define WM8776_REG_ADC_ATTEN_L 0x0e -#define WM8776_REG_ADC_ATTEN_R 0x0f -#define WM8776_REG_ADC_ALC1 0x10 -#define WM8776_REG_ADC_ALC2 0x11 -#define WM8776_REG_ADC_ALC3 0x12 -#define WM8776_REG_ADC_NOISE_GATE 0x13 -#define WM8776_REG_ADC_LIMITER 0x14 -#define WM8776_REG_ADC_MUX 0x15 -#define WM8776_REG_OUTPUT_MUX 0x16 -#define WM8776_REG_RESET 0x17 - -#define WM8776_NUM_REGS 0x18 - -/* clock ratio identifiers for snd_wm8776_set_rate() */ -#define WM8776_CLOCK_RATIO_128FS 0 -#define WM8776_CLOCK_RATIO_192FS 1 -#define WM8776_CLOCK_RATIO_256FS 2 -#define WM8776_CLOCK_RATIO_384FS 3 -#define WM8776_CLOCK_RATIO_512FS 4 -#define WM8776_CLOCK_RATIO_768FS 5 - -enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS }; -enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES }; - -struct snd_wm8776 { - unsigned char addr; - unsigned short regs[WM8776_NUM_REGS]; - unsigned char volumes[WM_NUM_VOLS][2]; - unsigned int switch_bits; -}; - -struct snd_maya44 { - struct snd_ice1712 *ice; - struct snd_wm8776 wm[2]; - struct mutex mutex; -}; - - -/* write the given register and save the data to the cache */ -static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm, - unsigned char reg, unsigned short val) -{ - /* - * WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB - * of the address field - */ - snd_vt1724_write_i2c(ice, wm->addr, - (reg << 1) | ((val >> 8) & 1), - val & 0xff); - wm->regs[reg] = val; -} - -/* - * update the given register with and/or mask and save the data to the cache - */ -static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm, - unsigned char reg, - unsigned short mask, unsigned short val) -{ - val |= wm->regs[reg] & ~mask; - if (val != wm->regs[reg]) { - wm8776_write(ice, wm, reg, val); - return 1; - } - return 0; -} - - -/* - * WM8776 volume controls - */ - -struct maya_vol_info { - unsigned int maxval; /* volume range: 0..maxval */ - unsigned char regs[2]; /* left and right registers */ - unsigned short mask; /* value mask */ - unsigned short offset; /* zero-value offset */ - unsigned short mute; /* mute bit */ - unsigned short update; /* update bits */ - unsigned char mux_bits[2]; /* extra bits for ADC mute */ -}; - -static struct maya_vol_info vol_info[WM_NUM_VOLS] = { - [WM_VOL_HP] = { - .maxval = 80, - .regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R }, - .mask = 0x7f, - .offset = 0x30, - .mute = 0x00, - .update = 0x180, /* update and zero-cross enable */ - }, - [WM_VOL_DAC] = { - .maxval = 255, - .regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R }, - .mask = 0xff, - .offset = 0x01, - .mute = 0x00, - .update = 0x100, /* zero-cross enable */ - }, - [WM_VOL_ADC] = { - .maxval = 91, - .regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R }, - .mask = 0xff, - .offset = 0xa5, - .mute = 0xa5, - .update = 0x100, /* update */ - .mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */ - }, -}; - -/* - * dB tables - */ -/* headphone output: mute, -73..+6db (1db step) */ -static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1); -/* DAC output: mute, -127..0db (0.5db step) */ -static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1); -/* ADC gain: mute, -21..+24db (0.5db step) */ -static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1); - -static int maya_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - unsigned int idx = kcontrol->private_value; - struct maya_vol_info *vol = &vol_info[idx]; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = vol->maxval; - return 0; -} - -static int maya_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - struct snd_wm8776 *wm = - &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)]; - unsigned int idx = kcontrol->private_value; - - mutex_lock(&chip->mutex); - ucontrol->value.integer.value[0] = wm->volumes[idx][0]; - ucontrol->value.integer.value[1] = wm->volumes[idx][1]; - mutex_unlock(&chip->mutex); - return 0; -} - -static int maya_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - struct snd_wm8776 *wm = - &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)]; - unsigned int idx = kcontrol->private_value; - struct maya_vol_info *vol = &vol_info[idx]; - unsigned int val, data; - int ch, changed = 0; - - mutex_lock(&chip->mutex); - for (ch = 0; ch < 2; ch++) { - val = ucontrol->value.integer.value[ch]; - if (val > vol->maxval) - val = vol->maxval; - if (val == wm->volumes[idx][ch]) - continue; - if (!val) - data = vol->mute; - else - data = (val - 1) + vol->offset; - data |= vol->update; - changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch], - vol->mask | vol->update, data); - if (vol->mux_bits[ch]) - wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX, - vol->mux_bits[ch], - val ? 0 : vol->mux_bits[ch]); - wm->volumes[idx][ch] = val; - } - mutex_unlock(&chip->mutex); - return changed; -} - -/* - * WM8776 switch controls - */ - -#define COMPOSE_SW_VAL(idx, reg, mask) ((idx) | ((reg) << 8) | ((mask) << 16)) -#define GET_SW_VAL_IDX(val) ((val) & 0xff) -#define GET_SW_VAL_REG(val) (((val) >> 8) & 0xff) -#define GET_SW_VAL_MASK(val) (((val) >> 16) & 0xff) - -#define maya_sw_info snd_ctl_boolean_mono_info - -static int maya_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - struct snd_wm8776 *wm = - &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)]; - unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value); - - ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1; - return 0; -} - -static int maya_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - struct snd_wm8776 *wm = - &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)]; - unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value); - unsigned int mask, val; - int changed; - - mutex_lock(&chip->mutex); - mask = 1 << idx; - wm->switch_bits &= ~mask; - val = ucontrol->value.integer.value[0]; - if (val) - wm->switch_bits |= mask; - mask = GET_SW_VAL_MASK(kcontrol->private_value); - changed = wm8776_write_bits(chip->ice, wm, - GET_SW_VAL_REG(kcontrol->private_value), - mask, val ? mask : 0); - mutex_unlock(&chip->mutex); - return changed; -} - -/* - * GPIO pins (known ones for maya44) - */ -#define GPIO_PHANTOM_OFF 2 -#define GPIO_MIC_RELAY 4 -#define GPIO_SPDIF_IN_INV 5 -#define GPIO_MUST_BE_0 7 - -/* - * GPIO switch controls - */ - -#define COMPOSE_GPIO_VAL(shift, inv) ((shift) | ((inv) << 8)) -#define GET_GPIO_VAL_SHIFT(val) ((val) & 0xff) -#define GET_GPIO_VAL_INV(val) (((val) >> 8) & 1) - -static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask, - unsigned int bits) -{ - unsigned int data; - data = snd_ice1712_gpio_read(ice); - if ((data & mask) == bits) - return 0; - snd_ice1712_gpio_write(ice, (data & ~mask) | bits); - return 1; -} - -#define maya_gpio_sw_info snd_ctl_boolean_mono_info - -static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value); - unsigned int val; - - val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1; - if (GET_GPIO_VAL_INV(kcontrol->private_value)) - val = !val; - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value); - unsigned int val, mask; - int changed; - - mutex_lock(&chip->mutex); - mask = 1 << shift; - val = ucontrol->value.integer.value[0]; - if (GET_GPIO_VAL_INV(kcontrol->private_value)) - val = !val; - val = val ? mask : 0; - changed = maya_set_gpio_bits(chip->ice, mask, val); - mutex_unlock(&chip->mutex); - return changed; -} - -/* - * capture source selection - */ - -/* known working input slots (0-4) */ -#define MAYA_LINE_IN 1 /* in-2 */ -#define MAYA_MIC_IN 3 /* in-4 */ - -static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line) -{ - wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX, - 0x1f, 1 << line); -} - -static int maya_rec_src_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "Line", "Mic" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = ARRAY_SIZE(texts); - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int maya_rec_src_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - int sel; - - if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY)) - sel = 1; - else - sel = 0; - ucontrol->value.enumerated.item[0] = sel; - return 0; -} - -static int maya_rec_src_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - int sel = ucontrol->value.enumerated.item[0]; - int changed; - - mutex_lock(&chip->mutex); - changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY, - sel ? (1 << GPIO_MIC_RELAY) : 0); - wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN); - mutex_unlock(&chip->mutex); - return changed; -} - -/* - * Maya44 routing switch settings have different meanings than the standard - * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c). - */ -static int maya_pb_route_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { - "PCM Out", /* 0 */ - "Input 1", "Input 2", "Input 3", "Input 4" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = ARRAY_SIZE(texts); - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int maya_pb_route_shift(int idx) -{ - static const unsigned char shift[10] = - { 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 }; - return shift[idx % 10]; -} - -static int maya_pb_route_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - ucontrol->value.enumerated.item[0] = - snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx)); - return 0; -} - -static int maya_pb_route_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - return snd_ice1724_put_route_val(chip->ice, - ucontrol->value.enumerated.item[0], - maya_pb_route_shift(idx)); -} - - -/* - * controls to be added - */ - -static struct snd_kcontrol_new maya_controls[] __devinitdata = { - { - .name = "Crossmix Playback Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = maya_vol_info, - .get = maya_vol_get, - .put = maya_vol_put, - .tlv = { .p = db_scale_hp }, - .private_value = WM_VOL_HP, - .count = 2, - }, - { - .name = "PCM Playback Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = maya_vol_info, - .get = maya_vol_get, - .put = maya_vol_put, - .tlv = { .p = db_scale_dac }, - .private_value = WM_VOL_DAC, - .count = 2, - }, - { - .name = "Line Capture Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = maya_vol_info, - .get = maya_vol_get, - .put = maya_vol_put, - .tlv = { .p = db_scale_adc }, - .private_value = WM_VOL_ADC, - .count = 2, - }, - { - .name = "PCM Playback Switch", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = maya_sw_info, - .get = maya_sw_get, - .put = maya_sw_put, - .private_value = COMPOSE_SW_VAL(WM_SW_DAC, - WM8776_REG_OUTPUT_MUX, 0x01), - .count = 2, - }, - { - .name = "Bypass Playback Switch", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = maya_sw_info, - .get = maya_sw_get, - .put = maya_sw_put, - .private_value = COMPOSE_SW_VAL(WM_SW_BYPASS, - WM8776_REG_OUTPUT_MUX, 0x04), - .count = 2, - }, - { - .name = "Capture Source", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = maya_rec_src_info, - .get = maya_rec_src_get, - .put = maya_rec_src_put, - }, - { - .name = "Mic Phantom Power Switch", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = maya_gpio_sw_info, - .get = maya_gpio_sw_get, - .put = maya_gpio_sw_put, - .private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1), - }, - { - .name = "SPDIF Capture Switch", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = maya_gpio_sw_info, - .get = maya_gpio_sw_get, - .put = maya_gpio_sw_put, - .private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1), - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "H/W Playback Route", - .info = maya_pb_route_info, - .get = maya_pb_route_get, - .put = maya_pb_route_put, - .count = 4, /* FIXME: do controls 5-9 have any meaning? */ - }, -}; - -static int __devinit maya44_add_controls(struct snd_ice1712 *ice) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(maya_controls); i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i], - ice->spec)); - if (err < 0) - return err; - } - return 0; -} - - -/* - * initialize a wm8776 chip - */ -static void __devinit wm8776_init(struct snd_ice1712 *ice, - struct snd_wm8776 *wm, unsigned int addr) -{ - static const unsigned short inits_wm8776[] = { - 0x02, 0x100, /* R2: headphone L+R muted + update */ - 0x05, 0x100, /* R5: DAC output L+R muted + update */ - 0x06, 0x000, /* R6: DAC output phase normal */ - 0x07, 0x091, /* R7: DAC enable zero cross detection, - normal output */ - 0x08, 0x000, /* R8: DAC soft mute off */ - 0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */ - 0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */ - 0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit, - highpass filter enabled */ - 0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */ - 0x0d, 0x000, /* R13: all power up */ - 0x0e, 0x100, /* R14: ADC left muted, - enable zero cross detection */ - 0x0f, 0x100, /* R15: ADC right muted, - enable zero cross detection */ - /* R16: ALC...*/ - 0x11, 0x000, /* R17: disable ALC */ - /* R18: ALC...*/ - /* R19: noise gate...*/ - 0x15, 0x000, /* R21: ADC input mux init, mute all inputs */ - 0x16, 0x001, /* R22: output mux, select DAC */ - 0xff, 0xff - }; - - const unsigned short *ptr; - unsigned char reg; - unsigned short data; - - wm->addr = addr; - /* enable DAC output; mute bypass, aux & all inputs */ - wm->switch_bits = (1 << WM_SW_DAC); - - ptr = inits_wm8776; - while (*ptr != 0xff) { - reg = *ptr++; - data = *ptr++; - wm8776_write(ice, wm, reg, data); - } -} - - -/* - * change the rate on the WM8776 codecs. - * this assumes that the VT17xx's rate is changed by the calling function. - * NOTE: even though the WM8776's are running in slave mode and rate - * selection is automatic, we need to call snd_wm8776_set_rate() here - * to make sure some flags are set correctly. - */ -static void set_rate(struct snd_ice1712 *ice, unsigned int rate) -{ - struct snd_maya44 *chip = ice->spec; - unsigned int ratio, adc_ratio, val; - int i; - - switch (rate) { - case 192000: - ratio = WM8776_CLOCK_RATIO_128FS; - break; - case 176400: - ratio = WM8776_CLOCK_RATIO_128FS; - break; - case 96000: - ratio = WM8776_CLOCK_RATIO_256FS; - break; - case 88200: - ratio = WM8776_CLOCK_RATIO_384FS; - break; - case 48000: - ratio = WM8776_CLOCK_RATIO_512FS; - break; - case 44100: - ratio = WM8776_CLOCK_RATIO_512FS; - break; - case 32000: - ratio = WM8776_CLOCK_RATIO_768FS; - break; - case 0: - /* no hint - S/PDIF input is master, simply return */ - return; - default: - snd_BUG(); - return; - } - - /* - * this currently sets the same rate for ADC and DAC, but limits - * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC - * oversampling to 64x, as recommended by WM8776 datasheet. - * Setting the rate is not really necessary in slave mode. - */ - adc_ratio = ratio; - if (adc_ratio < WM8776_CLOCK_RATIO_256FS) - adc_ratio = WM8776_CLOCK_RATIO_256FS; - - val = adc_ratio; - if (adc_ratio == WM8776_CLOCK_RATIO_256FS) - val |= 8; - val |= ratio << 4; - - mutex_lock(&chip->mutex); - for (i = 0; i < 2; i++) - wm8776_write_bits(ice, &chip->wm[i], - WM8776_REG_MASTER_MODE_CONTROL, - 0x180, val); - mutex_unlock(&chip->mutex); -} - -/* - * supported sample rates (to override the default one) - */ - -static unsigned int rates[] = { - 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000 -}; - -/* playback rates: 32..192 kHz */ -static struct snd_pcm_hw_constraint_list dac_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0 -}; - - -/* - * chip addresses on I2C bus - */ -static unsigned char wm8776_addr[2] __devinitdata = { - 0x34, 0x36, /* codec 0 & 1 */ -}; - -/* - * initialize the chip - */ -static int __devinit maya44_init(struct snd_ice1712 *ice) -{ - int i; - struct snd_maya44 *chip; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - mutex_init(&chip->mutex); - chip->ice = ice; - ice->spec = chip; - - /* initialise codecs */ - ice->num_total_dacs = 4; - ice->num_total_adcs = 4; - ice->akm_codecs = 0; - - for (i = 0; i < 2; i++) { - wm8776_init(ice, &chip->wm[i], wm8776_addr[i]); - wm8776_select_input(chip, i, MAYA_LINE_IN); - } - - /* set card specific rates */ - ice->hw_rates = &dac_rates; - - /* register change rate notifier */ - ice->gpio.set_pro_rate = set_rate; - - /* RDMA1 (2nd input channel) is used for ADC by default */ - ice->force_rdma1 = 1; - - /* have an own routing control */ - ice->own_routing = 1; - - return 0; -} - - -/* - * Maya44 boards don't provide the EEPROM data except for the vendor IDs. - * hence the driver needs to sets up it properly. - */ - -static unsigned char maya44_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x45, - /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */ - [ICE_EEP2_ACLINK] = 0x80, - /* I2S */ - [ICE_EEP2_I2S] = 0xf8, - /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, - /* enable spdif out, spdif out supp, spdif-in, ext spdif out */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0xff, - [ICE_EEP2_GPIO_MASK] = 0/*0x9f*/, - [ICE_EEP2_GPIO_MASK1] = 0/*0xff*/, - [ICE_EEP2_GPIO_MASK2] = 0/*0x7f*/, - [ICE_EEP2_GPIO_STATE] = (1 << GPIO_PHANTOM_OFF) | - (1 << GPIO_SPDIF_IN_INV), - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, -}; - -/* entry point */ -struct snd_ice1712_card_info snd_vt1724_maya44_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_MAYA44, - .name = "ESI Maya44", - .model = "maya44", - .chip_init = maya44_init, - .build_controls = maya44_add_controls, - .eeprom_size = sizeof(maya44_eeprom), - .eeprom_data = maya44_eeprom, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/maya44.h b/ANDROID_3.4.5/sound/pci/ice1712/maya44.h deleted file mode 100644 index eafd03a8..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/maya44.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __SOUND_MAYA44_H -#define __SOUND_MAYA44_H - -#define MAYA44_DEVICE_DESC "{ESI,Maya44}," - -#define VT1724_SUBDEVICE_MAYA44 0x34315441 /* Maya44 */ - -extern struct snd_ice1712_card_info snd_vt1724_maya44_cards[]; - -#endif /* __SOUND_MAYA44_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/phase.c b/ANDROID_3.4.5/sound/pci/ice1712/phase.c deleted file mode 100644 index de29be8c..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/phase.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - * ALSA driver for ICEnsemble ICE1724 (Envy24) - * - * Lowlevel functions for Terratec PHASE 22 - * - * Copyright (c) 2005 Misha Zhilin - * - * 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 - * - */ - -/* PHASE 22 overview: - * Audio controller: VIA Envy24HT-S (slightly trimmed down Envy24HT, 4in/4out) - * Analog chip: AK4524 (partially via Philip's 74HCT125) - * Digital receiver: CS8414-CS (supported in this release) - * PHASE 22 revision 2.0 and Terrasoniq/Musonik TS22PCI have CS8416 - * (support status unknown, please test and report) - * - * Envy connects to AK4524 - * - CS directly from GPIO 10 - * - CCLK via 74HCT125's gate #4 from GPIO 4 - * - CDTI via 74HCT125's gate #2 from GPIO 5 - * CDTI may be completely blocked by 74HCT125's gate #1 - * controlled by GPIO 3 - */ - -/* PHASE 28 overview: - * Audio controller: VIA Envy24HT (full untrimmed version, 4in/8out) - * Analog chip: WM8770 (8 channel 192k DAC, 2 channel 96k ADC) - * Digital receiver: CS8414-CS (supported in this release) - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "ice1712.h" -#include "envy24ht.h" -#include "phase.h" -#include - -/* AC97 register cache for Phase28 */ -struct phase28_spec { - unsigned short master[2]; - unsigned short vol[8]; -}; - -/* WM8770 registers */ -#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ -#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ -#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */ -#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */ -#define WM_PHASE_SWAP 0x12 /* DAC phase */ -#define WM_DAC_CTRL1 0x13 /* DAC control bits */ -#define WM_MUTE 0x14 /* mute controls */ -#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */ -#define WM_INT_CTRL 0x16 /* interface control */ -#define WM_MASTER 0x17 /* master clock and mode */ -#define WM_POWERDOWN 0x18 /* power-down controls */ -#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */ -#define WM_ADC_MUX 0x1b /* input MUX */ -#define WM_OUT_MUX1 0x1c /* output MUX */ -#define WM_OUT_MUX2 0x1e /* output MUX */ -#define WM_RESET 0x1f /* software reset */ - - -/* - * Logarithmic volume values for WM8770 - * Computed as 20 * Log10(255 / x) - */ -static const unsigned char wm_vol[256] = { - 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, - 24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, - 17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, - 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#define WM_VOL_MAX (sizeof(wm_vol) - 1) -#define WM_VOL_MUTE 0x8000 - -static struct snd_akm4xxx akm_phase22 __devinitdata = { - .type = SND_AK4524, - .num_dacs = 2, - .num_adcs = 2, -}; - -static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = { - .caddr = 2, - .cif = 1, - .data_mask = 1 << 4, - .clk_mask = 1 << 5, - .cs_mask = 1 << 10, - .cs_addr = 1 << 10, - .cs_none = 0, - .add_flags = 1 << 3, - .mask_flags = 0, -}; - -static int __devinit phase22_init(struct snd_ice1712 *ice) -{ - struct snd_akm4xxx *ak; - int err; - - /* Configure DAC/ADC description for generic part of ice1724 */ - switch (ice->eeprom.subvendor) { - case VT1724_SUBDEVICE_PHASE22: - case VT1724_SUBDEVICE_TS22: - ice->num_total_dacs = 2; - ice->num_total_adcs = 2; - ice->vt1720 = 1; /* Envy24HT-S have 16 bit wide GPIO */ - break; - default: - snd_BUG(); - return -EINVAL; - } - - /* Initialize analog chips */ - ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - ak = ice->akm; - if (!ak) - return -ENOMEM; - ice->akm_codecs = 1; - switch (ice->eeprom.subvendor) { - case VT1724_SUBDEVICE_PHASE22: - case VT1724_SUBDEVICE_TS22: - err = snd_ice1712_akm4xxx_init(ak, &akm_phase22, - &akm_phase22_priv, ice); - if (err < 0) - return err; - break; - } - - return 0; -} - -static int __devinit phase22_add_controls(struct snd_ice1712 *ice) -{ - int err = 0; - - switch (ice->eeprom.subvendor) { - case VT1724_SUBDEVICE_PHASE22: - case VT1724_SUBDEVICE_TS22: - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - } - return 0; -} - -static unsigned char phase22_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x28, /* clock 512, mpu 401, - spdif-in/1xADC, 1xDACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xf0, /* vol, 96k, 24bit */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0xff, - [ICE_EEP2_GPIO_MASK] = 0x00, - [ICE_EEP2_GPIO_MASK1] = 0x00, - [ICE_EEP2_GPIO_MASK2] = 0x00, - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, -}; - -static unsigned char phase28_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, - spdif-in/1xADC, 4xDACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0x5f, - [ICE_EEP2_GPIO_MASK] = 0x00, - [ICE_EEP2_GPIO_MASK1] = 0x00, - [ICE_EEP2_GPIO_MASK2] = 0x00, - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, -}; - -/* - * write data in the SPI mode - */ -static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs, - unsigned int data, int bits) -{ - unsigned int tmp; - int i; - - tmp = snd_ice1712_gpio_read(ice); - - snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI| - PHASE28_SPI_CLK|PHASE28_WM_CS)); - tmp |= PHASE28_WM_RW; - tmp &= ~cs; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - for (i = bits - 1; i >= 0; i--) { - tmp &= ~PHASE28_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - if (data & (1 << i)) - tmp |= PHASE28_SPI_MOSI; - else - tmp &= ~PHASE28_SPI_MOSI; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= PHASE28_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - } - - tmp &= ~PHASE28_SPI_CLK; - tmp |= cs; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= PHASE28_SPI_CLK; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); -} - -/* - * get the current register value of WM codec - */ -static unsigned short wm_get(struct snd_ice1712 *ice, int reg) -{ - reg <<= 1; - return ((unsigned short)ice->akm[0].images[reg] << 8) | - ice->akm[0].images[reg + 1]; -} - -/* - * set the register value of WM codec - */ -static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16); -} - -/* - * set the register value of WM codec and remember it - */ -static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - wm_put_nocache(ice, reg, val); - reg <<= 1; - ice->akm[0].images[reg] = val >> 8; - ice->akm[0].images[reg + 1] = val; -} - -static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, - unsigned short vol, unsigned short master) -{ - unsigned char nvol; - - if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) - nvol = 0; - else - nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * - (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX]; - - wm_put(ice, index, nvol); - wm_put_nocache(ice, index, 0x180 | nvol); -} - -/* - * DAC mute control - */ -#define wm_pcm_mute_info snd_ctl_boolean_mono_info - -static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? - 0 : 1; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short nval, oval; - int change; - - snd_ice1712_save_gpio_status(ice); - oval = wm_get(ice, WM_MUTE); - nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10); - change = (nval != oval); - if (change) - wm_put(ice, WM_MUTE, nval); - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * Master volume attenuation mixer control - */ -static int wm_master_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = WM_VOL_MAX; - return 0; -} - -static int wm_master_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct phase28_spec *spec = ice->spec; - int i; - for (i = 0; i < 2; i++) - ucontrol->value.integer.value[i] = spec->master[i] & - ~WM_VOL_MUTE; - return 0; -} - -static int wm_master_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct phase28_spec *spec = ice->spec; - int ch, change = 0; - - snd_ice1712_save_gpio_status(ice); - for (ch = 0; ch < 2; ch++) { - unsigned int vol = ucontrol->value.integer.value[ch]; - if (vol > WM_VOL_MAX) - continue; - vol |= spec->master[ch] & WM_VOL_MUTE; - if (vol != spec->master[ch]) { - int dac; - spec->master[ch] = vol; - for (dac = 0; dac < ice->num_total_dacs; dac += 2) - wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, - spec->vol[dac + ch], - spec->master[ch]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -static int __devinit phase28_init(struct snd_ice1712 *ice) -{ - static const unsigned short wm_inits_phase28[] = { - /* These come first to reduce init pop noise */ - 0x1b, 0x044, /* ADC Mux (AC'97 source) */ - 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ - 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */ - - 0x18, 0x000, /* All power-up */ - - 0x16, 0x122, /* I2S, normal polarity, 24bit */ - 0x17, 0x022, /* 256fs, slave mode */ - 0x00, 0, /* DAC1 analog mute */ - 0x01, 0, /* DAC2 analog mute */ - 0x02, 0, /* DAC3 analog mute */ - 0x03, 0, /* DAC4 analog mute */ - 0x04, 0, /* DAC5 analog mute */ - 0x05, 0, /* DAC6 analog mute */ - 0x06, 0, /* DAC7 analog mute */ - 0x07, 0, /* DAC8 analog mute */ - 0x08, 0x100, /* master analog mute */ - 0x09, 0xff, /* DAC1 digital full */ - 0x0a, 0xff, /* DAC2 digital full */ - 0x0b, 0xff, /* DAC3 digital full */ - 0x0c, 0xff, /* DAC4 digital full */ - 0x0d, 0xff, /* DAC5 digital full */ - 0x0e, 0xff, /* DAC6 digital full */ - 0x0f, 0xff, /* DAC7 digital full */ - 0x10, 0xff, /* DAC8 digital full */ - 0x11, 0x1ff, /* master digital full */ - 0x12, 0x000, /* phase normal */ - 0x13, 0x090, /* unmute DAC L/R */ - 0x14, 0x000, /* all unmute */ - 0x15, 0x000, /* no deemphasis, no ZFLG */ - 0x19, 0x000, /* -12dB ADC/L */ - 0x1a, 0x000, /* -12dB ADC/R */ - (unsigned short)-1 - }; - - unsigned int tmp; - struct snd_akm4xxx *ak; - struct phase28_spec *spec; - const unsigned short *p; - int i; - - ice->num_total_dacs = 8; - ice->num_total_adcs = 2; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - /* Initialize analog chips */ - ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - ak = ice->akm; - if (!ak) - return -ENOMEM; - ice->akm_codecs = 1; - - snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for time being */ - - /* reset the wm codec as the SPI mode */ - snd_ice1712_save_gpio_status(ice); - snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS| - PHASE28_HP_SEL)); - - tmp = snd_ice1712_gpio_read(ice); - tmp &= ~PHASE28_WM_RESET; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= PHASE28_WM_CS; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - tmp |= PHASE28_WM_RESET; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - - p = wm_inits_phase28; - for (; *p != (unsigned short)-1; p += 2) - wm_put(ice, p[0], p[1]); - - snd_ice1712_restore_gpio_status(ice); - - spec->master[0] = WM_VOL_MUTE; - spec->master[1] = WM_VOL_MUTE; - for (i = 0; i < ice->num_total_dacs; i++) { - spec->vol[i] = WM_VOL_MUTE; - wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); - } - - return 0; -} - -/* - * DAC volume attenuation mixer control - */ -static int wm_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int voices = kcontrol->private_value >> 8; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = voices; - uinfo->value.integer.min = 0; /* mute (-101dB) */ - uinfo->value.integer.max = 0x7F; /* 0dB */ - return 0; -} - -static int wm_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct phase28_spec *spec = ice->spec; - int i, ofs, voices; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xff; - for (i = 0; i < voices; i++) - ucontrol->value.integer.value[i] = - spec->vol[ofs+i] & ~WM_VOL_MUTE; - return 0; -} - -static int wm_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct phase28_spec *spec = ice->spec; - int i, idx, ofs, voices; - int change = 0; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xff; - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < voices; i++) { - unsigned int vol; - vol = ucontrol->value.integer.value[i]; - if (vol > 0x7f) - continue; - vol |= spec->vol[ofs+i] & WM_VOL_MUTE; - if (vol != spec->vol[ofs+i]) { - spec->vol[ofs+i] = vol; - idx = WM_DAC_ATTEN + ofs + i; - wm_set_vol(ice, idx, spec->vol[ofs+i], - spec->master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * WM8770 mute control - */ -static int wm_mute_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) { - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = kcontrol->private_value >> 8; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int wm_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct phase28_spec *spec = ice->spec; - int voices, ofs, i; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xFF; - - for (i = 0; i < voices; i++) - ucontrol->value.integer.value[i] = - (spec->vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1; - return 0; -} - -static int wm_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct phase28_spec *spec = ice->spec; - int change = 0, voices, ofs, i; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xFF; - - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < voices; i++) { - int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; - if (ucontrol->value.integer.value[i] != val) { - spec->vol[ofs + i] &= ~WM_VOL_MUTE; - spec->vol[ofs + i] |= - ucontrol->value.integer.value[i] ? 0 : - WM_VOL_MUTE; - wm_set_vol(ice, ofs + i, spec->vol[ofs + i], - spec->master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* - * WM8770 master mute control - */ -#define wm_master_mute_info snd_ctl_boolean_stereo_info - -static int wm_master_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct phase28_spec *spec = ice->spec; - - ucontrol->value.integer.value[0] = - (spec->master[0] & WM_VOL_MUTE) ? 0 : 1; - ucontrol->value.integer.value[1] = - (spec->master[1] & WM_VOL_MUTE) ? 0 : 1; - return 0; -} - -static int wm_master_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct phase28_spec *spec = ice->spec; - int change = 0, i; - - snd_ice1712_save_gpio_status(ice); - for (i = 0; i < 2; i++) { - int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1; - if (ucontrol->value.integer.value[i] != val) { - int dac; - spec->master[i] &= ~WM_VOL_MUTE; - spec->master[i] |= - ucontrol->value.integer.value[i] ? 0 : - WM_VOL_MUTE; - for (dac = 0; dac < ice->num_total_dacs; dac += 2) - wm_set_vol(ice, WM_DAC_ATTEN + dac + i, - spec->vol[dac + i], - spec->master[i]); - change = 1; - } - } - snd_ice1712_restore_gpio_status(ice); - - return change; -} - -/* digital master volume */ -#define PCM_0dB 0xff -#define PCM_RES 128 /* -64dB */ -#define PCM_MIN (PCM_0dB - PCM_RES) -static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; /* mute (-64dB) */ - uinfo->value.integer.max = PCM_RES; /* 0dB */ - return 0; -} - -static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val; - - mutex_lock(&ice->gpio_mutex); - val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; - val = val > PCM_MIN ? (val - PCM_MIN) : 0; - ucontrol->value.integer.value[0] = val; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int change = 0; - - nvol = ucontrol->value.integer.value[0]; - if (nvol > PCM_RES) - return -EINVAL; - snd_ice1712_save_gpio_status(ice); - nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; - ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; - if (ovol != nvol) { - wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */ - /* update */ - wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); - change = 1; - } - snd_ice1712_restore_gpio_status(ice); - return change; -} - -/* - * Deemphasis - */ -#define phase28_deemp_info snd_ctl_boolean_mono_info - -static int phase28_deemp_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == - 0xf; - return 0; -} - -static int phase28_deemp_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int temp, temp2; - temp = wm_get(ice, WM_DAC_CTRL2); - temp2 = temp; - if (ucontrol->value.integer.value[0]) - temp |= 0xf; - else - temp &= ~0xf; - if (temp != temp2) { - wm_put(ice, WM_DAC_CTRL2, temp); - return 1; - } - return 0; -} - -/* - * ADC Oversampling - */ -static int phase28_oversampling_info(struct snd_kcontrol *k, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { "128x", "64x" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int phase28_oversampling_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == - 0x8; - return 0; -} - -static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int temp, temp2; - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - temp = wm_get(ice, WM_MASTER); - temp2 = temp; - - if (ucontrol->value.enumerated.item[0]) - temp |= 0x8; - else - temp &= ~0x8; - - if (temp != temp2) { - wm_put(ice, WM_MASTER, temp); - return 1; - } - return 0; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); -static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); - -static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = wm_master_mute_info, - .get = wm_master_mute_get, - .put = wm_master_mute_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Master Playback Volume", - .info = wm_master_vol_info, - .get = wm_master_vol_get, - .put = wm_master_vol_put, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Front Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 0 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Front Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 0, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Rear Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 2 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Rear Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 2, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Center Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (1 << 8) | 4 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Center Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (1 << 8) | 4, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "LFE Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (1 << 8) | 5 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "LFE Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (1 << 8) | 5, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Side Playback Switch", - .info = wm_mute_info, - .get = wm_mute_get, - .put = wm_mute_put, - .private_value = (2 << 8) | 6 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Side Playback Volume", - .info = wm_vol_info, - .get = wm_vol_get, - .put = wm_vol_put, - .private_value = (2 << 8) | 6, - .tlv = { .p = db_scale_wm_dac } - } -}; - -static struct snd_kcontrol_new wm_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .info = wm_pcm_mute_info, - .get = wm_pcm_mute_get, - .put = wm_pcm_mute_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "PCM Playback Volume", - .info = wm_pcm_vol_info, - .get = wm_pcm_vol_get, - .put = wm_pcm_vol_put, - .tlv = { .p = db_scale_wm_pcm } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Deemphasis Switch", - .info = phase28_deemp_info, - .get = phase28_deemp_get, - .put = phase28_deemp_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Oversampling", - .info = phase28_oversampling_info, - .get = phase28_oversampling_get, - .put = phase28_oversampling_put - } -}; - -static int __devinit phase28_add_controls(struct snd_ice1712 *ice) -{ - unsigned int i, counts; - int err; - - counts = ARRAY_SIZE(phase28_dac_controls); - for (i = 0; i < counts; i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&phase28_dac_controls[i], - ice)); - if (err < 0) - return err; - } - - for (i = 0; i < ARRAY_SIZE(wm_controls); i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&wm_controls[i], ice)); - if (err < 0) - return err; - } - - return 0; -} - -struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_PHASE22, - .name = "Terratec PHASE 22", - .model = "phase22", - .chip_init = phase22_init, - .build_controls = phase22_add_controls, - .eeprom_size = sizeof(phase22_eeprom), - .eeprom_data = phase22_eeprom, - }, - { - .subvendor = VT1724_SUBDEVICE_PHASE28, - .name = "Terratec PHASE 28", - .model = "phase28", - .chip_init = phase28_init, - .build_controls = phase28_add_controls, - .eeprom_size = sizeof(phase28_eeprom), - .eeprom_data = phase28_eeprom, - }, - { - .subvendor = VT1724_SUBDEVICE_TS22, - .name = "Terrasoniq TS22 PCI", - .model = "TS22", - .chip_init = phase22_init, - .build_controls = phase22_add_controls, - .eeprom_size = sizeof(phase22_eeprom), - .eeprom_data = phase22_eeprom, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/phase.h b/ANDROID_3.4.5/sound/pci/ice1712/phase.h deleted file mode 100644 index 7fc22d9d..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/phase.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __SOUND_PHASE_H -#define __SOUND_PHASE_H - -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for Terratec PHASE 22 - * - * Copyright (c) 2005 Misha Zhilin - * - * 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 - * - */ - -#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\ - "{Terratec,Phase 28},"\ - "{Terrasoniq,TS22}," - -#define VT1724_SUBDEVICE_PHASE22 0x3b155011 -#define VT1724_SUBDEVICE_PHASE28 0x3b154911 -#define VT1724_SUBDEVICE_TS22 0x3b157b11 - -/* entry point */ -extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; - -/* PHASE28 GPIO bits */ -#define PHASE28_SPI_MISO (1 << 21) -#define PHASE28_WM_RESET (1 << 20) -#define PHASE28_SPI_CLK (1 << 19) -#define PHASE28_SPI_MOSI (1 << 18) -#define PHASE28_WM_RW (1 << 17) -#define PHASE28_AC97_RESET (1 << 16) -#define PHASE28_DIGITAL_SEL1 (1 << 15) -#define PHASE28_HP_SEL (1 << 14) -#define PHASE28_WM_CS (1 << 12) -#define PHASE28_AC97_COMMIT (1 << 11) -#define PHASE28_AC97_ADDR (1 << 10) -#define PHASE28_AC97_DATA_LOW (1 << 9) -#define PHASE28_AC97_DATA_HIGH (1 << 8) -#define PHASE28_AC97_DATA_MASK 0xFF -#endif /* __SOUND_PHASE */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/pontis.c b/ANDROID_3.4.5/sound/pci/ice1712/pontis.c deleted file mode 100644 index 92c1160d..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/pontis.c +++ /dev/null @@ -1,836 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for Pontis MS300 - * - * Copyright (c) 2004 Takashi Iwai - * - * 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 - -#include "ice1712.h" -#include "envy24ht.h" -#include "pontis.h" - -/* I2C addresses */ -#define WM_DEV 0x34 -#define CS_DEV 0x20 - -/* WM8776 registers */ -#define WM_HP_ATTEN_L 0x00 /* headphone left attenuation */ -#define WM_HP_ATTEN_R 0x01 /* headphone left attenuation */ -#define WM_HP_MASTER 0x02 /* headphone master (both channels) */ - /* override LLR */ -#define WM_DAC_ATTEN_L 0x03 /* digital left attenuation */ -#define WM_DAC_ATTEN_R 0x04 -#define WM_DAC_MASTER 0x05 -#define WM_PHASE_SWAP 0x06 /* DAC phase swap */ -#define WM_DAC_CTRL1 0x07 -#define WM_DAC_MUTE 0x08 -#define WM_DAC_CTRL2 0x09 -#define WM_DAC_INT 0x0a -#define WM_ADC_INT 0x0b -#define WM_MASTER_CTRL 0x0c -#define WM_POWERDOWN 0x0d -#define WM_ADC_ATTEN_L 0x0e -#define WM_ADC_ATTEN_R 0x0f -#define WM_ALC_CTRL1 0x10 -#define WM_ALC_CTRL2 0x11 -#define WM_ALC_CTRL3 0x12 -#define WM_NOISE_GATE 0x13 -#define WM_LIMITER 0x14 -#define WM_ADC_MUX 0x15 -#define WM_OUT_MUX 0x16 -#define WM_RESET 0x17 - -/* - * GPIO - */ -#define PONTIS_CS_CS (1<<4) /* CS */ -#define PONTIS_CS_CLK (1<<5) /* CLK */ -#define PONTIS_CS_RDATA (1<<6) /* CS8416 -> VT1720 */ -#define PONTIS_CS_WDATA (1<<7) /* VT1720 -> CS8416 */ - - -/* - * get the current register value of WM codec - */ -static unsigned short wm_get(struct snd_ice1712 *ice, int reg) -{ - reg <<= 1; - return ((unsigned short)ice->akm[0].images[reg] << 8) | - ice->akm[0].images[reg + 1]; -} - -/* - * set the register value of WM codec and remember it - */ -static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - unsigned short cval; - cval = (reg << 9) | val; - snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff); -} - -static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - wm_put_nocache(ice, reg, val); - reg <<= 1; - ice->akm[0].images[reg] = val >> 8; - ice->akm[0].images[reg + 1] = val; -} - -/* - * DAC volume attenuation mixer control (-64dB to 0dB) - */ - -#define DAC_0dB 0xff -#define DAC_RES 128 -#define DAC_MIN (DAC_0dB - DAC_RES) - -static int wm_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* mute */ - uinfo->value.integer.max = DAC_RES; /* 0dB, 0.5dB step */ - return 0; -} - -static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val; - int i; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff; - val = val > DAC_MIN ? (val - DAC_MIN) : 0; - ucontrol->value.integer.value[i] = val; - } - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short oval, nval; - int i, idx, change = 0; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - nval = ucontrol->value.integer.value[i]; - nval = (nval ? (nval + DAC_MIN) : 0) & 0xff; - idx = WM_DAC_ATTEN_L + i; - oval = wm_get(ice, idx) & 0xff; - if (oval != nval) { - wm_put(ice, idx, nval); - wm_put_nocache(ice, idx, nval | 0x100); - change = 1; - } - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* - * ADC gain mixer control (-64dB to 0dB) - */ - -#define ADC_0dB 0xcf -#define ADC_RES 128 -#define ADC_MIN (ADC_0dB - ADC_RES) - -static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* mute (-64dB) */ - uinfo->value.integer.max = ADC_RES; /* 0dB, 0.5dB step */ - return 0; -} - -static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val; - int i; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff; - val = val > ADC_MIN ? (val - ADC_MIN) : 0; - ucontrol->value.integer.value[i] = val; - } - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int i, idx, change = 0; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - nvol = ucontrol->value.integer.value[i]; - nvol = nvol ? (nvol + ADC_MIN) : 0; - idx = WM_ADC_ATTEN_L + i; - ovol = wm_get(ice, idx) & 0xff; - if (ovol != nvol) { - wm_put(ice, idx, nvol); - change = 1; - } - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* - * ADC input mux mixer control - */ -#define wm_adc_mux_info snd_ctl_boolean_mono_info - -static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int bit = kcontrol->private_value; - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int bit = kcontrol->private_value; - unsigned short oval, nval; - int change; - - mutex_lock(&ice->gpio_mutex); - nval = oval = wm_get(ice, WM_ADC_MUX); - if (ucontrol->value.integer.value[0]) - nval |= (1 << bit); - else - nval &= ~(1 << bit); - change = nval != oval; - if (change) { - wm_put(ice, WM_ADC_MUX, nval); - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* - * Analog bypass (In -> Out) - */ -#define wm_bypass_info snd_ctl_boolean_mono_info - -static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val, oval; - int change = 0; - - mutex_lock(&ice->gpio_mutex); - val = oval = wm_get(ice, WM_OUT_MUX); - if (ucontrol->value.integer.value[0]) - val |= 0x04; - else - val &= ~0x04; - if (val != oval) { - wm_put(ice, WM_OUT_MUX, val); - change = 1; - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* - * Left/Right swap - */ -#define wm_chswap_info snd_ctl_boolean_mono_info - -static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val, oval; - int change = 0; - - mutex_lock(&ice->gpio_mutex); - oval = wm_get(ice, WM_DAC_CTRL1); - val = oval & 0x0f; - if (ucontrol->value.integer.value[0]) - val |= 0x60; - else - val |= 0x90; - if (val != oval) { - wm_put(ice, WM_DAC_CTRL1, val); - wm_put_nocache(ice, WM_DAC_CTRL1, val); - change = 1; - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* - * write data in the SPI mode - */ -static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val) -{ - unsigned int tmp = snd_ice1712_gpio_read(ice); - if (val) - tmp |= bit; - else - tmp &= ~bit; - snd_ice1712_gpio_write(ice, tmp); -} - -static void spi_send_byte(struct snd_ice1712 *ice, unsigned char data) -{ - int i; - for (i = 0; i < 8; i++) { - set_gpio_bit(ice, PONTIS_CS_CLK, 0); - udelay(1); - set_gpio_bit(ice, PONTIS_CS_WDATA, data & 0x80); - udelay(1); - set_gpio_bit(ice, PONTIS_CS_CLK, 1); - udelay(1); - data <<= 1; - } -} - -static unsigned int spi_read_byte(struct snd_ice1712 *ice) -{ - int i; - unsigned int val = 0; - - for (i = 0; i < 8; i++) { - val <<= 1; - set_gpio_bit(ice, PONTIS_CS_CLK, 0); - udelay(1); - if (snd_ice1712_gpio_read(ice) & PONTIS_CS_RDATA) - val |= 1; - udelay(1); - set_gpio_bit(ice, PONTIS_CS_CLK, 1); - udelay(1); - } - return val; -} - - -static void spi_write(struct snd_ice1712 *ice, unsigned int dev, unsigned int reg, unsigned int data) -{ - snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK); - snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK)); - set_gpio_bit(ice, PONTIS_CS_CS, 0); - spi_send_byte(ice, dev & ~1); /* WRITE */ - spi_send_byte(ice, reg); /* MAP */ - spi_send_byte(ice, data); /* DATA */ - /* trigger */ - set_gpio_bit(ice, PONTIS_CS_CS, 1); - udelay(1); - /* restore */ - snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); -} - -static unsigned int spi_read(struct snd_ice1712 *ice, unsigned int dev, unsigned int reg) -{ - unsigned int val; - snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK); - snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK)); - set_gpio_bit(ice, PONTIS_CS_CS, 0); - spi_send_byte(ice, dev & ~1); /* WRITE */ - spi_send_byte(ice, reg); /* MAP */ - /* trigger */ - set_gpio_bit(ice, PONTIS_CS_CS, 1); - udelay(1); - set_gpio_bit(ice, PONTIS_CS_CS, 0); - spi_send_byte(ice, dev | 1); /* READ */ - val = spi_read_byte(ice); - /* trigger */ - set_gpio_bit(ice, PONTIS_CS_CS, 1); - udelay(1); - /* restore */ - snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); - return val; -} - - -/* - * SPDIF input source - */ -static int cs_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char * const texts[] = { - "Coax", /* RXP0 */ - "Optical", /* RXP1 */ - "CD", /* RXP2 */ - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int cs_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.enumerated.item[0] = ice->gpio.saved[0]; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val; - int change = 0; - - mutex_lock(&ice->gpio_mutex); - if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) { - ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3; - val = 0x80 | (ice->gpio.saved[0] << 3); - spi_write(ice, CS_DEV, 0x04, val); - change = 1; - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - - -/* - * GPIO controls - */ -static int pontis_gpio_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xffff; /* 16bit */ - return 0; -} - -static int pontis_gpio_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); - /* 4-7 reserved */ - ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int pontis_gpio_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val; - int changed; - mutex_lock(&ice->gpio_mutex); - /* 4-7 reserved */ - val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0; - changed = val != ice->gpio.write_mask; - ice->gpio.write_mask = val; - mutex_unlock(&ice->gpio_mutex); - return changed; -} - -static int pontis_gpio_dir_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); - /* 4-7 reserved */ - ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int pontis_gpio_dir_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val; - int changed; - mutex_lock(&ice->gpio_mutex); - /* 4-7 reserved */ - val = ucontrol->value.integer.value[0] & 0xff0f; - changed = (val != ice->gpio.direction); - ice->gpio.direction = val; - mutex_unlock(&ice->gpio_mutex); - return changed; -} - -static int pontis_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - mutex_lock(&ice->gpio_mutex); - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); - snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); - ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val, nval; - int changed = 0; - mutex_lock(&ice->gpio_mutex); - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); - snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); - val = snd_ice1712_gpio_read(ice) & 0xffff; - nval = ucontrol->value.integer.value[0] & 0xffff; - if (val != nval) { - snd_ice1712_gpio_write(ice, nval); - changed = 1; - } - mutex_unlock(&ice->gpio_mutex); - return changed; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1); - -/* - * mixers - */ - -static struct snd_kcontrol_new pontis_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "PCM Playback Volume", - .info = wm_dac_vol_info, - .get = wm_dac_vol_get, - .put = wm_dac_vol_put, - .tlv = { .p = db_scale_volume }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Capture Volume", - .info = wm_adc_vol_info, - .get = wm_adc_vol_get, - .put = wm_adc_vol_put, - .tlv = { .p = db_scale_volume }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "CD Capture Switch", - .info = wm_adc_mux_info, - .get = wm_adc_mux_get, - .put = wm_adc_mux_put, - .private_value = 0, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Capture Switch", - .info = wm_adc_mux_info, - .get = wm_adc_mux_get, - .put = wm_adc_mux_put, - .private_value = 1, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Bypass Switch", - .info = wm_bypass_info, - .get = wm_bypass_get, - .put = wm_bypass_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Swap Output Channels", - .info = wm_chswap_info, - .get = wm_chswap_get, - .put = wm_chswap_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Input Source", - .info = cs_source_info, - .get = cs_source_get, - .put = cs_source_put, - }, - /* FIXME: which interface? */ - { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "GPIO Mask", - .info = pontis_gpio_mask_info, - .get = pontis_gpio_mask_get, - .put = pontis_gpio_mask_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "GPIO Direction", - .info = pontis_gpio_mask_info, - .get = pontis_gpio_dir_get, - .put = pontis_gpio_dir_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "GPIO Data", - .info = pontis_gpio_mask_info, - .get = pontis_gpio_data_get, - .put = pontis_gpio_data_put, - }, -}; - - -/* - * WM codec registers - */ -static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - char line[64]; - unsigned int reg, val; - mutex_lock(&ice->gpio_mutex); - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x", ®, &val) != 2) - continue; - if (reg <= 0x17 && val <= 0xffff) - wm_put(ice, reg, val); - } - mutex_unlock(&ice->gpio_mutex); -} - -static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - int reg, val; - - mutex_lock(&ice->gpio_mutex); - for (reg = 0; reg <= 0x17; reg++) { - val = wm_get(ice, reg); - snd_iprintf(buffer, "%02x = %04x\n", reg, val); - } - mutex_unlock(&ice->gpio_mutex); -} - -static void wm_proc_init(struct snd_ice1712 *ice) -{ - struct snd_info_entry *entry; - if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) { - snd_info_set_text_ops(entry, ice, wm_proc_regs_read); - entry->mode |= S_IWUSR; - entry->c.text.write = wm_proc_regs_write; - } -} - -static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - int reg, val; - - mutex_lock(&ice->gpio_mutex); - for (reg = 0; reg <= 0x26; reg++) { - val = spi_read(ice, CS_DEV, reg); - snd_iprintf(buffer, "%02x = %02x\n", reg, val); - } - val = spi_read(ice, CS_DEV, 0x7f); - snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val); - mutex_unlock(&ice->gpio_mutex); -} - -static void cs_proc_init(struct snd_ice1712 *ice) -{ - struct snd_info_entry *entry; - if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) - snd_info_set_text_ops(entry, ice, cs_proc_regs_read); -} - - -static int __devinit pontis_add_controls(struct snd_ice1712 *ice) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(pontis_controls); i++) { - err = snd_ctl_add(ice->card, snd_ctl_new1(&pontis_controls[i], ice)); - if (err < 0) - return err; - } - - wm_proc_init(ice); - cs_proc_init(ice); - - return 0; -} - - -/* - * initialize the chip - */ -static int __devinit pontis_init(struct snd_ice1712 *ice) -{ - static const unsigned short wm_inits[] = { - /* These come first to reduce init pop noise */ - WM_ADC_MUX, 0x00c0, /* ADC mute */ - WM_DAC_MUTE, 0x0001, /* DAC softmute */ - WM_DAC_CTRL1, 0x0000, /* DAC mute */ - - WM_POWERDOWN, 0x0008, /* All power-up except HP */ - WM_RESET, 0x0000, /* reset */ - }; - static const unsigned short wm_inits2[] = { - WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */ - WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */ - WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */ - WM_DAC_CTRL1, 0x0090, /* DAC L/R */ - WM_OUT_MUX, 0x0001, /* OUT DAC */ - WM_HP_ATTEN_L, 0x0179, /* HP 0dB */ - WM_HP_ATTEN_R, 0x0179, /* HP 0dB */ - WM_DAC_ATTEN_L, 0x0000, /* DAC 0dB */ - WM_DAC_ATTEN_L, 0x0100, /* DAC 0dB */ - WM_DAC_ATTEN_R, 0x0000, /* DAC 0dB */ - WM_DAC_ATTEN_R, 0x0100, /* DAC 0dB */ - /* WM_DAC_MASTER, 0x0100, */ /* DAC master muted */ - WM_PHASE_SWAP, 0x0000, /* phase normal */ - WM_DAC_CTRL2, 0x0000, /* no deemphasis, no ZFLG */ - WM_ADC_ATTEN_L, 0x0000, /* ADC muted */ - WM_ADC_ATTEN_R, 0x0000, /* ADC muted */ -#if 0 - WM_ALC_CTRL1, 0x007b, /* */ - WM_ALC_CTRL2, 0x0000, /* */ - WM_ALC_CTRL3, 0x0000, /* */ - WM_NOISE_GATE, 0x0000, /* */ -#endif - WM_DAC_MUTE, 0x0000, /* DAC unmute */ - WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */ - }; - static const unsigned char cs_inits[] = { - 0x04, 0x80, /* RUN, RXP0 */ - 0x05, 0x05, /* slave, 24bit */ - 0x01, 0x00, - 0x02, 0x00, - 0x03, 0x00, - }; - unsigned int i; - - ice->vt1720 = 1; - ice->num_total_dacs = 2; - ice->num_total_adcs = 2; - - /* to remember the register values */ - ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (! ice->akm) - return -ENOMEM; - ice->akm_codecs = 1; - - /* HACK - use this as the SPDIF source. - * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten - */ - ice->gpio.saved[0] = 0; - - /* initialize WM8776 codec */ - for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) - wm_put(ice, wm_inits[i], wm_inits[i+1]); - schedule_timeout_uninterruptible(1); - for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2) - wm_put(ice, wm_inits2[i], wm_inits2[i+1]); - - /* initialize CS8416 codec */ - /* assert PRST#; MT05 bit 7 */ - outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); - mdelay(5); - /* deassert PRST# */ - outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); - - for (i = 0; i < ARRAY_SIZE(cs_inits); i += 2) - spi_write(ice, CS_DEV, cs_inits[i], cs_inits[i+1]); - - return 0; -} - - -/* - * Pontis boards don't provide the EEPROM data at all. - * hence the driver needs to sets up it properly. - */ - -static unsigned char pontis_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x08, /* clock 256, mpu401, spdif-in/ADC, 1DAC */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0x07, - [ICE_EEP2_GPIO_DIR1] = 0x00, - [ICE_EEP2_GPIO_DIR2] = 0x00, /* ignored */ - [ICE_EEP2_GPIO_MASK] = 0x0f, /* 4-7 reserved for CS8416 */ - [ICE_EEP2_GPIO_MASK1] = 0xff, - [ICE_EEP2_GPIO_MASK2] = 0x00, /* ignored */ - [ICE_EEP2_GPIO_STATE] = 0x06, /* 0-low, 1-high, 2-high */ - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, /* ignored */ -}; - -/* entry point */ -struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = { - { - .subvendor = VT1720_SUBDEVICE_PONTIS_MS300, - .name = "Pontis MS300", - .model = "ms300", - .chip_init = pontis_init, - .build_controls = pontis_add_controls, - .eeprom_size = sizeof(pontis_eeprom), - .eeprom_data = pontis_eeprom, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/pontis.h b/ANDROID_3.4.5/sound/pci/ice1712/pontis.h deleted file mode 100644 index d0d1378b..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/pontis.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __SOUND_PONTIS_H -#define __SOUND_PONTIS_H - -/* - * ALSA driver for VIA VT1724 (Envy24HT) - * - * Lowlevel functions for Pontis MS300 boards - * - * Copyright (c) 2004 Takashi Iwai - * - * 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 - * - */ - -#define PONTIS_DEVICE_DESC "{Pontis,MS300}," - -#define VT1720_SUBDEVICE_PONTIS_MS300 0x00020002 /* a dummy id for MS300 */ - -extern struct snd_ice1712_card_info snd_vt1720_pontis_cards[]; - -#endif /* __SOUND_PONTIS_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/prodigy192.c b/ANDROID_3.4.5/sound/pci/ice1712/prodigy192.c deleted file mode 100644 index e36ddb94..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/prodigy192.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for AudioTrak Prodigy 192 cards - * Supported IEC958 input from optional MI/ODI/O add-on card. - * - * Specifics (SW, HW): - * ------------------- - * * 49.5MHz crystal - * * SPDIF-OUT on the card: - * - coax (through isolation transformer)/toslink supplied by - * 74HC04 gates - 3 in parallel - * - output switched between on-board CD drive dig-out connector - * and ice1724 SPDTX pin, using 74HC02 NOR gates, controlled - * by GPIO20 (0 = CD dig-out, 1 = SPDTX) - * * SPDTX goes straight to MI/ODI/O card's SPDIF-OUT coax - * - * * MI/ODI/O card: AK4114 based, used for iec958 input only - * - toslink input -> RX0 - * - coax input -> RX1 - * - 4wire protocol: - * AK4114 ICE1724 - * ------------------------------ - * CDTO (pin 32) -- GPIO11 pin 86 - * CDTI (pin 33) -- GPIO10 pin 77 - * CCLK (pin 34) -- GPIO9 pin 76 - * CSN (pin 35) -- GPIO8 pin 75 - * - output data Mode 7 (24bit, I2S, slave) - * - both MCKO1 and MCKO2 of ak4114 are fed to FPGA, which - * outputs master clock to SPMCLKIN of ice1724. - * Experimentally I found out that only a combination of - * OCKS0=1, OCKS1=1 (128fs, 64fs output) and ice1724 - - * VT1724_MT_I2S_MCLK_128X=0 (256fs input) yields correct - * sampling rate. That means the the FPGA doubles the - * MCK01 rate. - * - * Copyright (c) 2003 Takashi Iwai - * Copyright (c) 2003 Dimitromanolakis Apostolos - * Copyright (c) 2004 Kouichi ONO - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include "prodigy192.h" -#include "stac946x.h" -#include - -struct prodigy192_spec { - struct ak4114 *ak4114; - /* rate change needs atomic mute/unmute of all dacs*/ - struct mutex mute_mutex; -}; - -static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) -{ - snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val); -} - -static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) -{ - return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg); -} - -/* - * DAC mute control - */ - -/* - * idx = STAC9460 volume register number, mute: 0 = mute, 1 = unmute - */ -static int stac9460_dac_mute(struct snd_ice1712 *ice, int idx, - unsigned char mute) -{ - unsigned char new, old; - int change; - old = stac9460_get(ice, idx); - new = (~mute << 7 & 0x80) | (old & ~0x80); - change = (new != old); - if (change) - /*printk ("Volume register 0x%02x: 0x%02x\n", idx, new);*/ - stac9460_put(ice, idx, new); - return change; -} - -#define stac9460_dac_mute_info snd_ctl_boolean_mono_info - -static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val; - int idx; - - if (kcontrol->private_value) - idx = STAC946X_MASTER_VOLUME; - else - idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; - val = stac9460_get(ice, idx); - ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; - return 0; -} - -static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy192_spec *spec = ice->spec; - int idx, change; - - if (kcontrol->private_value) - idx = STAC946X_MASTER_VOLUME; - else - idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; - /* due to possible conflicts with stac9460_set_rate_val, mutexing */ - mutex_lock(&spec->mute_mutex); - /* - printk(KERN_DEBUG "Mute put: reg 0x%02x, ctrl value: 0x%02x\n", idx, - ucontrol->value.integer.value[0]); - */ - change = stac9460_dac_mute(ice, idx, ucontrol->value.integer.value[0]); - mutex_unlock(&spec->mute_mutex); - return change; -} - -/* - * DAC volume attenuation mixer control - */ -static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; /* mute */ - uinfo->value.integer.max = 0x7f; /* 0dB */ - return 0; -} - -static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx; - unsigned char vol; - - if (kcontrol->private_value) - idx = STAC946X_MASTER_VOLUME; - else - idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; - vol = stac9460_get(ice, idx) & 0x7f; - ucontrol->value.integer.value[0] = 0x7f - vol; - - return 0; -} - -static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx; - unsigned char tmp, ovol, nvol; - int change; - - if (kcontrol->private_value) - idx = STAC946X_MASTER_VOLUME; - else - idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME; - nvol = ucontrol->value.integer.value[0]; - tmp = stac9460_get(ice, idx); - ovol = 0x7f - (tmp & 0x7f); - change = (ovol != nvol); - if (change) { - ovol = (0x7f - nvol) | (tmp & 0x80); - /* - printk(KERN_DEBUG "DAC Volume: reg 0x%02x: 0x%02x\n", - idx, ovol); - */ - stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); - } - return change; -} - -/* - * ADC mute control - */ -#define stac9460_adc_mute_info snd_ctl_boolean_stereo_info - -static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val; - int i; - - for (i = 0; i < 2; ++i) { - val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i); - ucontrol->value.integer.value[i] = ~val>>7 & 0x1; - } - - return 0; -} - -static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char new, old; - int i, reg; - int change; - - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - old = stac9460_get(ice, reg); - new = (~ucontrol->value.integer.value[i]<<7&0x80) | (old&~0x80); - change = (new != old); - if (change) - stac9460_put(ice, reg, new); - } - - return change; -} - -/* - * ADC gain mixer control - */ -static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* 0dB */ - uinfo->value.integer.max = 0x0f; /* 22.5dB */ - return 0; -} - -static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int i, reg; - unsigned char vol; - - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - vol = stac9460_get(ice, reg) & 0x0f; - ucontrol->value.integer.value[i] = 0x0f - vol; - } - - return 0; -} - -static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int i, reg; - unsigned char ovol, nvol; - int change; - - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - nvol = ucontrol->value.integer.value[i] & 0x0f; - ovol = 0x0f - stac9460_get(ice, reg); - change = ((ovol & 0x0f) != nvol); - if (change) - stac9460_put(ice, reg, (0x0f - nvol) | (ovol & ~0x0f)); - } - - return change; -} - -static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { "Line In", "Mic" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - - return 0; -} - - -static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val; - - val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); - ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1; - return 0; -} - -static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char new, old; - int change; - old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); - new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80); - change = (new != old); - if (change) - stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); - return change; -} -/* - * Handler for setting correct codec rate - called when rate change is detected - */ -static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate) -{ - unsigned char old, new; - int idx; - unsigned char changed[7]; - struct prodigy192_spec *spec = ice->spec; - - if (rate == 0) /* no hint - S/PDIF input is master, simply return */ - return; - else if (rate <= 48000) - new = 0x08; /* 256x, base rate mode */ - else if (rate <= 96000) - new = 0x11; /* 256x, mid rate mode */ - else - new = 0x12; /* 128x, high rate mode */ - old = stac9460_get(ice, STAC946X_MASTER_CLOCKING); - if (old == new) - return; - /* change detected, setting master clock, muting first */ - /* due to possible conflicts with mute controls - mutexing */ - mutex_lock(&spec->mute_mutex); - /* we have to remember current mute status for each DAC */ - for (idx = 0; idx < 7 ; ++idx) - changed[idx] = stac9460_dac_mute(ice, - STAC946X_MASTER_VOLUME + idx, 0); - /*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/ - stac9460_put(ice, STAC946X_MASTER_CLOCKING, new); - udelay(10); - /* unmuting - only originally unmuted dacs - - * i.e. those changed when muting */ - for (idx = 0; idx < 7 ; ++idx) { - if (changed[idx]) - stac9460_dac_mute(ice, STAC946X_MASTER_VOLUME + idx, 1); - } - mutex_unlock(&spec->mute_mutex); -} - - -static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); - -/* - * mixers - */ - -static struct snd_kcontrol_new stac_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = stac9460_dac_mute_info, - .get = stac9460_dac_mute_get, - .put = stac9460_dac_mute_put, - .private_value = 1, - .tlv = { .p = db_scale_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Master Playback Volume", - .info = stac9460_dac_vol_info, - .get = stac9460_dac_vol_get, - .put = stac9460_dac_vol_put, - .private_value = 1, - .tlv = { .p = db_scale_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Switch", - .count = 6, - .info = stac9460_dac_mute_info, - .get = stac9460_dac_mute_get, - .put = stac9460_dac_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "DAC Volume", - .count = 6, - .info = stac9460_dac_vol_info, - .get = stac9460_dac_vol_get, - .put = stac9460_dac_vol_put, - .tlv = { .p = db_scale_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Capture Switch", - .count = 1, - .info = stac9460_adc_mute_info, - .get = stac9460_adc_mute_get, - .put = stac9460_adc_mute_put, - - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "ADC Capture Volume", - .count = 1, - .info = stac9460_adc_vol_info, - .get = stac9460_adc_vol_get, - .put = stac9460_adc_vol_put, - .tlv = { .p = db_scale_adc } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Capture Input", - .info = stac9460_mic_sw_info, - .get = stac9460_mic_sw_get, - .put = stac9460_mic_sw_put, - - }, -}; - -/* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */ -/* CDTO (pin 32) -- GPIO11 pin 86 - * CDTI (pin 33) -- GPIO10 pin 77 - * CCLK (pin 34) -- GPIO9 pin 76 - * CSN (pin 35) -- GPIO8 pin 75 - */ -#define AK4114_ADDR 0x00 /* C1-C0: Chip Address - * (According to datasheet fixed to “00”) - */ - -/* - * 4wire ak4114 protocol - writing data - */ -static void write_data(struct snd_ice1712 *ice, unsigned int gpio, - unsigned int data, int idx) -{ - for (; idx >= 0; idx--) { - /* drop clock */ - gpio &= ~VT1724_PRODIGY192_CCLK; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - /* set data */ - if (data & (1 << idx)) - gpio |= VT1724_PRODIGY192_CDOUT; - else - gpio &= ~VT1724_PRODIGY192_CDOUT; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - /* raise clock */ - gpio |= VT1724_PRODIGY192_CCLK; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - } -} - -/* - * 4wire ak4114 protocol - reading data - */ -static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio, - int idx) -{ - unsigned char data = 0; - - for (; idx >= 0; idx--) { - /* drop clock */ - gpio &= ~VT1724_PRODIGY192_CCLK; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - /* read data */ - if (snd_ice1712_gpio_read(ice) & VT1724_PRODIGY192_CDIN) - data |= (1 << idx); - udelay(1); - /* raise clock */ - gpio |= VT1724_PRODIGY192_CCLK; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - } - return data; -} -/* - * 4wire ak4114 protocol - starting sequence - */ -static unsigned int prodigy192_4wire_start(struct snd_ice1712 *ice) -{ - unsigned int tmp; - - snd_ice1712_save_gpio_status(ice); - tmp = snd_ice1712_gpio_read(ice); - - tmp |= VT1724_PRODIGY192_CCLK; /* high at init */ - tmp &= ~VT1724_PRODIGY192_CS; /* drop chip select */ - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - return tmp; -} - -/* - * 4wire ak4114 protocol - final sequence - */ -static void prodigy192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp) -{ - tmp |= VT1724_PRODIGY192_CS; /* raise chip select */ - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - snd_ice1712_restore_gpio_status(ice); -} - -/* - * Write data to addr register of ak4114 - */ -static void prodigy192_ak4114_write(void *private_data, unsigned char addr, - unsigned char data) -{ - struct snd_ice1712 *ice = private_data; - unsigned int tmp, addrdata; - tmp = prodigy192_4wire_start(ice); - addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f); - addrdata = (addrdata << 8) | data; - write_data(ice, tmp, addrdata, 15); - prodigy192_4wire_finish(ice, tmp); -} - -/* - * Read data from addr register of ak4114 - */ -static unsigned char prodigy192_ak4114_read(void *private_data, - unsigned char addr) -{ - struct snd_ice1712 *ice = private_data; - unsigned int tmp; - unsigned char data; - - tmp = prodigy192_4wire_start(ice); - write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7); - data = read_data(ice, tmp, 7); - prodigy192_4wire_finish(ice, tmp); - return data; -} - - -static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { "Toslink", "Coax" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - - -static int ak4114_input_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val; - - val = prodigy192_ak4114_read(ice, AK4114_REG_IO1); - /* AK4114_IPS0 bit = 0 -> RX0 = Toslink - * AK4114_IPS0 bit = 1 -> RX1 = Coax - */ - ucontrol->value.enumerated.item[0] = (val & AK4114_IPS0) ? 1 : 0; - return 0; -} - -static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char new, old, itemvalue; - int change; - - old = prodigy192_ak4114_read(ice, AK4114_REG_IO1); - /* AK4114_IPS0 could be any bit */ - itemvalue = (ucontrol->value.enumerated.item[0]) ? 0xff : 0x00; - - new = (itemvalue & AK4114_IPS0) | (old & ~AK4114_IPS0); - change = (new != old); - if (change) - prodigy192_ak4114_write(ice, AK4114_REG_IO1, new); - return change; -} - - -static struct snd_kcontrol_new ak4114_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "MIODIO IEC958 Capture Input", - .info = ak4114_input_sw_info, - .get = ak4114_input_sw_get, - .put = ak4114_input_sw_put, - - } -}; - - -static int prodigy192_ak4114_init(struct snd_ice1712 *ice) -{ - static const unsigned char ak4114_init_vals[] = { - AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1, - /* ice1724 expects I2S and provides clock, - * DEM0 disables the deemphasis filter - */ - AK4114_DIF_I24I2S | AK4114_DEM0 , - AK4114_TX1E, - AK4114_EFH_1024 | AK4114_DIT, /* default input RX0 */ - 0, - 0 - }; - static const unsigned char ak4114_init_txcsb[] = { - 0x41, 0x02, 0x2c, 0x00, 0x00 - }; - struct prodigy192_spec *spec = ice->spec; - int err; - - err = snd_ak4114_create(ice->card, - prodigy192_ak4114_read, - prodigy192_ak4114_write, - ak4114_init_vals, ak4114_init_txcsb, - ice, &spec->ak4114); - if (err < 0) - return err; - /* AK4114 in Prodigy192 cannot detect external rate correctly. - * No reason to stop capture stream due to incorrect checks */ - spec->ak4114->check_flags = AK4114_CHECK_NO_RATE; - return 0; -} - -static void stac9460_proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - int reg, val; - /* registers 0x0 - 0x14 */ - for (reg = 0; reg <= 0x15; reg++) { - val = stac9460_get(ice, reg); - snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val); - } -} - - -static void stac9460_proc_init(struct snd_ice1712 *ice) -{ - struct snd_info_entry *entry; - if (!snd_card_proc_new(ice->card, "stac9460_codec", &entry)) - snd_info_set_text_ops(entry, ice, stac9460_proc_regs_read); -} - - -static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice) -{ - struct prodigy192_spec *spec = ice->spec; - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(stac_controls); i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&stac_controls[i], ice)); - if (err < 0) - return err; - } - if (spec->ak4114) { - /* ak4114 is connected */ - for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&ak4114_controls[i], - ice)); - if (err < 0) - return err; - } - err = snd_ak4114_build(spec->ak4114, - NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */ - ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); - if (err < 0) - return err; - } - stac9460_proc_init(ice); - return 0; -} - -/* - * check for presence of MI/ODI/O add-on card with digital inputs - */ -static int prodigy192_miodio_exists(struct snd_ice1712 *ice) -{ - - unsigned char orig_value; - const unsigned char test_data = 0xd1; /* random value */ - unsigned char addr = AK4114_REG_INT0_MASK; /* random SAFE address */ - int exists = 0; - - orig_value = prodigy192_ak4114_read(ice, addr); - prodigy192_ak4114_write(ice, addr, test_data); - if (prodigy192_ak4114_read(ice, addr) == test_data) { - /* ak4114 seems to communicate, apparently exists */ - /* writing back original value */ - prodigy192_ak4114_write(ice, addr, orig_value); - exists = 1; - } - return exists; -} - -/* - * initialize the chip - */ -static int __devinit prodigy192_init(struct snd_ice1712 *ice) -{ - static const unsigned short stac_inits_prodigy[] = { - STAC946X_RESET, 0, - STAC946X_MASTER_CLOCKING, 0x11, -/* STAC946X_MASTER_VOLUME, 0, - STAC946X_LF_VOLUME, 0, - STAC946X_RF_VOLUME, 0, - STAC946X_LR_VOLUME, 0, - STAC946X_RR_VOLUME, 0, - STAC946X_CENTER_VOLUME, 0, - STAC946X_LFE_VOLUME, 0,*/ - (unsigned short)-1 - }; - const unsigned short *p; - int err = 0; - struct prodigy192_spec *spec; - - /* prodigy 192 */ - ice->num_total_dacs = 6; - ice->num_total_adcs = 2; - ice->vt1720 = 0; /* ice1724, e.g. 23 GPIOs */ - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - mutex_init(&spec->mute_mutex); - - /* initialize codec */ - p = stac_inits_prodigy; - for (; *p != (unsigned short)-1; p += 2) - stac9460_put(ice, p[0], p[1]); - ice->gpio.set_pro_rate = stac9460_set_rate_val; - - /* MI/ODI/O add on card with AK4114 */ - if (prodigy192_miodio_exists(ice)) { - err = prodigy192_ak4114_init(ice); - /* from this moment if err = 0 then - * spec->ak4114 should not be null - */ - snd_printdd("AK4114 initialized with status %d\n", err); - } else - snd_printdd("AK4114 not found\n"); - if (err < 0) - return err; - - return 0; -} - - -/* - * Aureon boards don't provide the EEPROM data except for the vendor IDs. - * hence the driver needs to sets up it properly. - */ - -static unsigned char prodigy71_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x6a, /* 49MHz crystal, mpu401, - * spdif-in+ 1 stereo ADC, - * 3 stereo DACs - */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = ~(VT1724_PRODIGY192_CDIN >> 8) , - [ICE_EEP2_GPIO_DIR2] = 0xbf, - [ICE_EEP2_GPIO_MASK] = 0x00, - [ICE_EEP2_GPIO_MASK1] = 0x00, - [ICE_EEP2_GPIO_MASK2] = 0x00, - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x10, /* GPIO20: 0 = CD drive dig. input - * passthrough, - * 1 = SPDIF-OUT from ice1724 - */ -}; - - -/* entry point */ -struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_PRODIGY192VE, - .name = "Audiotrak Prodigy 192", - .model = "prodigy192", - .chip_init = prodigy192_init, - .build_controls = prodigy192_add_controls, - .eeprom_size = sizeof(prodigy71_eeprom), - .eeprom_data = prodigy71_eeprom, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/prodigy192.h b/ANDROID_3.4.5/sound/pci/ice1712/prodigy192.h deleted file mode 100644 index 16a53b45..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/prodigy192.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __SOUND_PRODIGY192_H -#define __SOUND_PRODIGY192_H - -#define PRODIGY192_DEVICE_DESC "{AudioTrak,Prodigy 192}," -#define PRODIGY192_STAC9460_ADDR 0x54 - -#define VT1724_SUBDEVICE_PRODIGY192VE 0x34495345 /* PRODIGY 192 VE */ -/* - * AudioTrak Prodigy192 GPIO definitions for MI/ODI/O card with - * AK4114 (SPDIF-IN) - */ -#define VT1724_PRODIGY192_CS (1 << 8) /* GPIO8, pin 75 */ -#define VT1724_PRODIGY192_CCLK (1 << 9) /* GPIO9, pin 76 */ -#define VT1724_PRODIGY192_CDOUT (1 << 10) /* GPIO10, pin 77 */ -#define VT1724_PRODIGY192_CDIN (1 << 11) /* GPIO11, pin 86 */ - -extern struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[]; - -#endif /* __SOUND_PRODIGY192_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.c b/ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.c deleted file mode 100644 index 764cc93d..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.c +++ /dev/null @@ -1,1236 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for Audiotrak Prodigy 7.1 Hifi - * based on pontis.c - * - * Copyright (c) 2007 Julian Scheel - * Copyright (c) 2007 allank - * Copyright (c) 2004 Takashi Iwai - * - * 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 - -#include "ice1712.h" -#include "envy24ht.h" -#include "prodigy_hifi.h" - -struct prodigy_hifi_spec { - unsigned short master[2]; - unsigned short vol[8]; -}; - -/* I2C addresses */ -#define WM_DEV 0x34 - -/* WM8776 registers */ -#define WM_HP_ATTEN_L 0x00 /* headphone left attenuation */ -#define WM_HP_ATTEN_R 0x01 /* headphone left attenuation */ -#define WM_HP_MASTER 0x02 /* headphone master (both channels), - override LLR */ -#define WM_DAC_ATTEN_L 0x03 /* digital left attenuation */ -#define WM_DAC_ATTEN_R 0x04 -#define WM_DAC_MASTER 0x05 -#define WM_PHASE_SWAP 0x06 /* DAC phase swap */ -#define WM_DAC_CTRL1 0x07 -#define WM_DAC_MUTE 0x08 -#define WM_DAC_CTRL2 0x09 -#define WM_DAC_INT 0x0a -#define WM_ADC_INT 0x0b -#define WM_MASTER_CTRL 0x0c -#define WM_POWERDOWN 0x0d -#define WM_ADC_ATTEN_L 0x0e -#define WM_ADC_ATTEN_R 0x0f -#define WM_ALC_CTRL1 0x10 -#define WM_ALC_CTRL2 0x11 -#define WM_ALC_CTRL3 0x12 -#define WM_NOISE_GATE 0x13 -#define WM_LIMITER 0x14 -#define WM_ADC_MUX 0x15 -#define WM_OUT_MUX 0x16 -#define WM_RESET 0x17 - -/* Analog Recording Source :- Mic, LineIn, CD/Video, */ - -/* implement capture source select control for WM8776 */ - -#define WM_AIN1 "AIN1" -#define WM_AIN2 "AIN2" -#define WM_AIN3 "AIN3" -#define WM_AIN4 "AIN4" -#define WM_AIN5 "AIN5" - -/* GPIO pins of envy24ht connected to wm8766 */ -#define WM8766_SPI_CLK (1<<17) /* CLK, Pin97 on ICE1724 */ -#define WM8766_SPI_MD (1<<16) /* DATA VT1724 -> WM8766, Pin96 */ -#define WM8766_SPI_ML (1<<18) /* Latch, Pin98 */ - -/* WM8766 registers */ -#define WM8766_DAC_CTRL 0x02 /* DAC Control */ -#define WM8766_INT_CTRL 0x03 /* Interface Control */ -#define WM8766_DAC_CTRL2 0x09 -#define WM8766_DAC_CTRL3 0x0a -#define WM8766_RESET 0x1f -#define WM8766_LDA1 0x00 -#define WM8766_LDA2 0x04 -#define WM8766_LDA3 0x06 -#define WM8766_RDA1 0x01 -#define WM8766_RDA2 0x05 -#define WM8766_RDA3 0x07 -#define WM8766_MUTE1 0x0C -#define WM8766_MUTE2 0x0F - - -/* - * Prodigy HD2 - */ -#define AK4396_ADDR 0x00 -#define AK4396_CSN (1 << 8) /* CSN->GPIO8, pin 75 */ -#define AK4396_CCLK (1 << 9) /* CCLK->GPIO9, pin 76 */ -#define AK4396_CDTI (1 << 10) /* CDTI->GPIO10, pin 77 */ - -/* ak4396 registers */ -#define AK4396_CTRL1 0x00 -#define AK4396_CTRL2 0x01 -#define AK4396_CTRL3 0x02 -#define AK4396_LCH_ATT 0x03 -#define AK4396_RCH_ATT 0x04 - - -/* - * get the current register value of WM codec - */ -static unsigned short wm_get(struct snd_ice1712 *ice, int reg) -{ - reg <<= 1; - return ((unsigned short)ice->akm[0].images[reg] << 8) | - ice->akm[0].images[reg + 1]; -} - -/* - * set the register value of WM codec and remember it - */ -static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - unsigned short cval; - cval = (reg << 9) | val; - snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff); -} - -static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val) -{ - wm_put_nocache(ice, reg, val); - reg <<= 1; - ice->akm[0].images[reg] = val >> 8; - ice->akm[0].images[reg + 1] = val; -} - -/* - * write data in the SPI mode - */ - -static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val) -{ - unsigned int tmp = snd_ice1712_gpio_read(ice); - if (val) - tmp |= bit; - else - tmp &= ~bit; - snd_ice1712_gpio_write(ice, tmp); -} - -/* - * SPI implementation for WM8766 codec - only writing supported, no readback - */ - -static void wm8766_spi_send_word(struct snd_ice1712 *ice, unsigned int data) -{ - int i; - for (i = 0; i < 16; i++) { - set_gpio_bit(ice, WM8766_SPI_CLK, 0); - udelay(1); - set_gpio_bit(ice, WM8766_SPI_MD, data & 0x8000); - udelay(1); - set_gpio_bit(ice, WM8766_SPI_CLK, 1); - udelay(1); - data <<= 1; - } -} - -static void wm8766_spi_write(struct snd_ice1712 *ice, unsigned int reg, - unsigned int data) -{ - unsigned int block; - - snd_ice1712_gpio_set_dir(ice, WM8766_SPI_MD| - WM8766_SPI_CLK|WM8766_SPI_ML); - snd_ice1712_gpio_set_mask(ice, ~(WM8766_SPI_MD| - WM8766_SPI_CLK|WM8766_SPI_ML)); - /* latch must be low when writing */ - set_gpio_bit(ice, WM8766_SPI_ML, 0); - block = (reg << 9) | (data & 0x1ff); - wm8766_spi_send_word(ice, block); /* REGISTER ADDRESS */ - /* release latch */ - set_gpio_bit(ice, WM8766_SPI_ML, 1); - udelay(1); - /* restore */ - snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); -} - - -/* - * serial interface for ak4396 - only writing supported, no readback - */ - -static void ak4396_send_word(struct snd_ice1712 *ice, unsigned int data) -{ - int i; - for (i = 0; i < 16; i++) { - set_gpio_bit(ice, AK4396_CCLK, 0); - udelay(1); - set_gpio_bit(ice, AK4396_CDTI, data & 0x8000); - udelay(1); - set_gpio_bit(ice, AK4396_CCLK, 1); - udelay(1); - data <<= 1; - } -} - -static void ak4396_write(struct snd_ice1712 *ice, unsigned int reg, - unsigned int data) -{ - unsigned int block; - - snd_ice1712_gpio_set_dir(ice, AK4396_CSN|AK4396_CCLK|AK4396_CDTI); - snd_ice1712_gpio_set_mask(ice, ~(AK4396_CSN|AK4396_CCLK|AK4396_CDTI)); - /* latch must be low when writing */ - set_gpio_bit(ice, AK4396_CSN, 0); - block = ((AK4396_ADDR & 0x03) << 14) | (1 << 13) | - ((reg & 0x1f) << 8) | (data & 0xff); - ak4396_send_word(ice, block); /* REGISTER ADDRESS */ - /* release latch */ - set_gpio_bit(ice, AK4396_CSN, 1); - udelay(1); - /* restore */ - snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask); - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); -} - - -/* - * ak4396 mixers - */ - - - -/* - * DAC volume attenuation mixer control (-64dB to 0dB) - */ - -static int ak4396_dac_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* mute */ - uinfo->value.integer.max = 0xFF; /* linear */ - return 0; -} - -static int ak4396_dac_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy_hifi_spec *spec = ice->spec; - int i; - - for (i = 0; i < 2; i++) - ucontrol->value.integer.value[i] = spec->vol[i]; - - return 0; -} - -static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy_hifi_spec *spec = ice->spec; - int i; - int change = 0; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - if (ucontrol->value.integer.value[i] != spec->vol[i]) { - spec->vol[i] = ucontrol->value.integer.value[i]; - ak4396_write(ice, AK4396_LCH_ATT + i, - spec->vol[i] & 0xff); - change = 1; - } - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); - -static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Front Playback Volume", - .info = ak4396_dac_vol_info, - .get = ak4396_dac_vol_get, - .put = ak4396_dac_vol_put, - .tlv = { .p = db_scale_wm_dac }, - }, -}; - - -/* --------------- */ - -/* - * Logarithmic volume values for WM87*6 - * Computed as 20 * Log10(255 / x) - */ -static const unsigned char wm_vol[256] = { - 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, - 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, - 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, - 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 -}; - -#define WM_VOL_MAX (sizeof(wm_vol) - 1) -#define WM_VOL_MUTE 0x8000 - - -#define DAC_0dB 0xff -#define DAC_RES 128 -#define DAC_MIN (DAC_0dB - DAC_RES) - - -static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, - unsigned short vol, unsigned short master) -{ - unsigned char nvol; - - if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) - nvol = 0; - else { - nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128) - & WM_VOL_MAX; - nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff; - } - - wm_put(ice, index, nvol); - wm_put_nocache(ice, index, 0x100 | nvol); -} - -static void wm8766_set_vol(struct snd_ice1712 *ice, unsigned int index, - unsigned short vol, unsigned short master) -{ - unsigned char nvol; - - if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) - nvol = 0; - else { - nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128) - & WM_VOL_MAX; - nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff; - } - - wm8766_spi_write(ice, index, (0x0100 | nvol)); -} - - -/* - * DAC volume attenuation mixer control (-64dB to 0dB) - */ - -static int wm_dac_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* mute */ - uinfo->value.integer.max = DAC_RES; /* 0dB, 0.5dB step */ - return 0; -} - -static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy_hifi_spec *spec = ice->spec; - int i; - - for (i = 0; i < 2; i++) - ucontrol->value.integer.value[i] = - spec->vol[2 + i] & ~WM_VOL_MUTE; - return 0; -} - -static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy_hifi_spec *spec = ice->spec; - int i, idx, change = 0; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - if (ucontrol->value.integer.value[i] != spec->vol[2 + i]) { - idx = WM_DAC_ATTEN_L + i; - spec->vol[2 + i] &= WM_VOL_MUTE; - spec->vol[2 + i] |= ucontrol->value.integer.value[i]; - wm_set_vol(ice, idx, spec->vol[2 + i], spec->master[i]); - change = 1; - } - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - - -/* - * WM8766 DAC volume attenuation mixer control - */ -static int wm8766_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int voices = kcontrol->private_value >> 8; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = voices; - uinfo->value.integer.min = 0; /* mute */ - uinfo->value.integer.max = DAC_RES; /* 0dB */ - return 0; -} - -static int wm8766_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy_hifi_spec *spec = ice->spec; - int i, ofs, voices; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xff; - for (i = 0; i < voices; i++) - ucontrol->value.integer.value[i] = spec->vol[ofs + i]; - return 0; -} - -static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy_hifi_spec *spec = ice->spec; - int i, idx, ofs, voices; - int change = 0; - - voices = kcontrol->private_value >> 8; - ofs = kcontrol->private_value & 0xff; - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < voices; i++) { - if (ucontrol->value.integer.value[i] != spec->vol[ofs + i]) { - idx = WM8766_LDA1 + ofs + i; - spec->vol[ofs + i] &= WM_VOL_MUTE; - spec->vol[ofs + i] |= ucontrol->value.integer.value[i]; - wm8766_set_vol(ice, idx, - spec->vol[ofs + i], spec->master[i]); - change = 1; - } - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* - * Master volume attenuation mixer control / applied to WM8776+WM8766 - */ -static int wm_master_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = DAC_RES; - return 0; -} - -static int wm_master_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy_hifi_spec *spec = ice->spec; - int i; - for (i = 0; i < 2; i++) - ucontrol->value.integer.value[i] = spec->master[i]; - return 0; -} - -static int wm_master_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - struct prodigy_hifi_spec *spec = ice->spec; - int ch, change = 0; - - mutex_lock(&ice->gpio_mutex); - for (ch = 0; ch < 2; ch++) { - if (ucontrol->value.integer.value[ch] != spec->master[ch]) { - spec->master[ch] = ucontrol->value.integer.value[ch]; - - /* Apply to front DAC */ - wm_set_vol(ice, WM_DAC_ATTEN_L + ch, - spec->vol[2 + ch], spec->master[ch]); - - wm8766_set_vol(ice, WM8766_LDA1 + ch, - spec->vol[0 + ch], spec->master[ch]); - - wm8766_set_vol(ice, WM8766_LDA2 + ch, - spec->vol[4 + ch], spec->master[ch]); - - wm8766_set_vol(ice, WM8766_LDA3 + ch, - spec->vol[6 + ch], spec->master[ch]); - change = 1; - } - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - - -/* KONSTI */ - -static int wm_adc_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char* texts[32] = { - "NULL", WM_AIN1, WM_AIN2, WM_AIN1 "+" WM_AIN2, - WM_AIN3, WM_AIN1 "+" WM_AIN3, WM_AIN2 "+" WM_AIN3, - WM_AIN1 "+" WM_AIN2 "+" WM_AIN3, - WM_AIN4, WM_AIN1 "+" WM_AIN4, WM_AIN2 "+" WM_AIN4, - WM_AIN1 "+" WM_AIN2 "+" WM_AIN4, - WM_AIN3 "+" WM_AIN4, WM_AIN1 "+" WM_AIN3 "+" WM_AIN4, - WM_AIN2 "+" WM_AIN3 "+" WM_AIN4, - WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4, - WM_AIN5, WM_AIN1 "+" WM_AIN5, WM_AIN2 "+" WM_AIN5, - WM_AIN1 "+" WM_AIN2 "+" WM_AIN5, - WM_AIN3 "+" WM_AIN5, WM_AIN1 "+" WM_AIN3 "+" WM_AIN5, - WM_AIN2 "+" WM_AIN3 "+" WM_AIN5, - WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN5, - WM_AIN4 "+" WM_AIN5, WM_AIN1 "+" WM_AIN4 "+" WM_AIN5, - WM_AIN2 "+" WM_AIN4 "+" WM_AIN5, - WM_AIN1 "+" WM_AIN2 "+" WM_AIN4 "+" WM_AIN5, - WM_AIN3 "+" WM_AIN4 "+" WM_AIN5, - WM_AIN1 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5, - WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5, - WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5 - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 32; - if (uinfo->value.enumerated.item > 31) - uinfo->value.enumerated.item = 31; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = wm_get(ice, WM_ADC_MUX) & 0x1f; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short oval, nval; - int change = 0; - - mutex_lock(&ice->gpio_mutex); - oval = wm_get(ice, WM_ADC_MUX); - nval = (oval & 0xe0) | ucontrol->value.integer.value[0]; - if (nval != oval) { - wm_put(ice, WM_ADC_MUX, nval); - change = 1; - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* KONSTI */ - -/* - * ADC gain mixer control (-64dB to 0dB) - */ - -#define ADC_0dB 0xcf -#define ADC_RES 128 -#define ADC_MIN (ADC_0dB - ADC_RES) - -static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* mute (-64dB) */ - uinfo->value.integer.max = ADC_RES; /* 0dB, 0.5dB step */ - return 0; -} - -static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val; - int i; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff; - val = val > ADC_MIN ? (val - ADC_MIN) : 0; - ucontrol->value.integer.value[i] = val; - } - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short ovol, nvol; - int i, idx, change = 0; - - mutex_lock(&ice->gpio_mutex); - for (i = 0; i < 2; i++) { - nvol = ucontrol->value.integer.value[i]; - nvol = nvol ? (nvol + ADC_MIN) : 0; - idx = WM_ADC_ATTEN_L + i; - ovol = wm_get(ice, idx) & 0xff; - if (ovol != nvol) { - wm_put(ice, idx, nvol); - change = 1; - } - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* - * ADC input mux mixer control - */ -#define wm_adc_mux_info snd_ctl_boolean_mono_info - -static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int bit = kcontrol->private_value; - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = - (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int bit = kcontrol->private_value; - unsigned short oval, nval; - int change; - - mutex_lock(&ice->gpio_mutex); - nval = oval = wm_get(ice, WM_ADC_MUX); - if (ucontrol->value.integer.value[0]) - nval |= (1 << bit); - else - nval &= ~(1 << bit); - change = nval != oval; - if (change) { - wm_put(ice, WM_ADC_MUX, nval); - } - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -/* - * Analog bypass (In -> Out) - */ -#define wm_bypass_info snd_ctl_boolean_mono_info - -static int wm_bypass_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = - (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_bypass_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val, oval; - int change = 0; - - mutex_lock(&ice->gpio_mutex); - val = oval = wm_get(ice, WM_OUT_MUX); - if (ucontrol->value.integer.value[0]) - val |= 0x04; - else - val &= ~0x04; - if (val != oval) { - wm_put(ice, WM_OUT_MUX, val); - change = 1; - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - -/* - * Left/Right swap - */ -#define wm_chswap_info snd_ctl_boolean_mono_info - -static int wm_chswap_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - - mutex_lock(&ice->gpio_mutex); - ucontrol->value.integer.value[0] = - (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90; - mutex_unlock(&ice->gpio_mutex); - return 0; -} - -static int wm_chswap_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned short val, oval; - int change = 0; - - mutex_lock(&ice->gpio_mutex); - oval = wm_get(ice, WM_DAC_CTRL1); - val = oval & 0x0f; - if (ucontrol->value.integer.value[0]) - val |= 0x60; - else - val |= 0x90; - if (val != oval) { - wm_put(ice, WM_DAC_CTRL1, val); - wm_put_nocache(ice, WM_DAC_CTRL1, val); - change = 1; - } - mutex_unlock(&ice->gpio_mutex); - return change; -} - - -/* - * mixers - */ - -static struct snd_kcontrol_new prodigy_hifi_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Master Playback Volume", - .info = wm_master_vol_info, - .get = wm_master_vol_get, - .put = wm_master_vol_put, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Front Playback Volume", - .info = wm_dac_vol_info, - .get = wm_dac_vol_get, - .put = wm_dac_vol_put, - .tlv = { .p = db_scale_wm_dac }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Rear Playback Volume", - .info = wm8766_vol_info, - .get = wm8766_vol_get, - .put = wm8766_vol_put, - .private_value = (2 << 8) | 0, - .tlv = { .p = db_scale_wm_dac }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Center Playback Volume", - .info = wm8766_vol_info, - .get = wm8766_vol_get, - .put = wm8766_vol_put, - .private_value = (1 << 8) | 4, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "LFE Playback Volume", - .info = wm8766_vol_info, - .get = wm8766_vol_get, - .put = wm8766_vol_put, - .private_value = (1 << 8) | 5, - .tlv = { .p = db_scale_wm_dac } - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Side Playback Volume", - .info = wm8766_vol_info, - .get = wm8766_vol_get, - .put = wm8766_vol_put, - .private_value = (2 << 8) | 6, - .tlv = { .p = db_scale_wm_dac }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Capture Volume", - .info = wm_adc_vol_info, - .get = wm_adc_vol_get, - .put = wm_adc_vol_put, - .tlv = { .p = db_scale_wm_dac }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "CD Capture Switch", - .info = wm_adc_mux_info, - .get = wm_adc_mux_get, - .put = wm_adc_mux_put, - .private_value = 0, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Capture Switch", - .info = wm_adc_mux_info, - .get = wm_adc_mux_get, - .put = wm_adc_mux_put, - .private_value = 1, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Bypass Switch", - .info = wm_bypass_info, - .get = wm_bypass_get, - .put = wm_bypass_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Swap Output Channels", - .info = wm_chswap_info, - .get = wm_chswap_get, - .put = wm_chswap_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Capture Source", - .info = wm_adc_mux_enum_info, - .get = wm_adc_mux_enum_get, - .put = wm_adc_mux_enum_put, - }, -}; - -/* - * WM codec registers - */ -static void wm_proc_regs_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - char line[64]; - unsigned int reg, val; - mutex_lock(&ice->gpio_mutex); - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x", ®, &val) != 2) - continue; - if (reg <= 0x17 && val <= 0xffff) - wm_put(ice, reg, val); - } - mutex_unlock(&ice->gpio_mutex); -} - -static void wm_proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - int reg, val; - - mutex_lock(&ice->gpio_mutex); - for (reg = 0; reg <= 0x17; reg++) { - val = wm_get(ice, reg); - snd_iprintf(buffer, "%02x = %04x\n", reg, val); - } - mutex_unlock(&ice->gpio_mutex); -} - -static void wm_proc_init(struct snd_ice1712 *ice) -{ - struct snd_info_entry *entry; - if (!snd_card_proc_new(ice->card, "wm_codec", &entry)) { - snd_info_set_text_ops(entry, ice, wm_proc_regs_read); - entry->mode |= S_IWUSR; - entry->c.text.write = wm_proc_regs_write; - } -} - -static int __devinit prodigy_hifi_add_controls(struct snd_ice1712 *ice) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(prodigy_hifi_controls); i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&prodigy_hifi_controls[i], ice)); - if (err < 0) - return err; - } - - wm_proc_init(ice); - - return 0; -} - -static int __devinit prodigy_hd2_add_controls(struct snd_ice1712 *ice) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(prodigy_hd2_controls); i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&prodigy_hd2_controls[i], ice)); - if (err < 0) - return err; - } - - wm_proc_init(ice); - - return 0; -} - - -/* - * initialize the chip - */ -static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice) -{ - static unsigned short wm_inits[] = { - /* These come first to reduce init pop noise */ - WM_ADC_MUX, 0x0003, /* ADC mute */ - /* 0x00c0 replaced by 0x0003 */ - - WM_DAC_MUTE, 0x0001, /* DAC softmute */ - WM_DAC_CTRL1, 0x0000, /* DAC mute */ - - WM_POWERDOWN, 0x0008, /* All power-up except HP */ - WM_RESET, 0x0000, /* reset */ - }; - static unsigned short wm_inits2[] = { - WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */ - WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */ - WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */ - WM_DAC_CTRL1, 0x0090, /* DAC L/R */ - WM_OUT_MUX, 0x0001, /* OUT DAC */ - WM_HP_ATTEN_L, 0x0179, /* HP 0dB */ - WM_HP_ATTEN_R, 0x0179, /* HP 0dB */ - WM_DAC_ATTEN_L, 0x0000, /* DAC 0dB */ - WM_DAC_ATTEN_L, 0x0100, /* DAC 0dB */ - WM_DAC_ATTEN_R, 0x0000, /* DAC 0dB */ - WM_DAC_ATTEN_R, 0x0100, /* DAC 0dB */ - WM_PHASE_SWAP, 0x0000, /* phase normal */ -#if 0 - WM_DAC_MASTER, 0x0100, /* DAC master muted */ -#endif - WM_DAC_CTRL2, 0x0000, /* no deemphasis, no ZFLG */ - WM_ADC_ATTEN_L, 0x0000, /* ADC muted */ - WM_ADC_ATTEN_R, 0x0000, /* ADC muted */ -#if 1 - WM_ALC_CTRL1, 0x007b, /* */ - WM_ALC_CTRL2, 0x0000, /* */ - WM_ALC_CTRL3, 0x0000, /* */ - WM_NOISE_GATE, 0x0000, /* */ -#endif - WM_DAC_MUTE, 0x0000, /* DAC unmute */ - WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */ - }; - static unsigned short wm8766_inits[] = { - WM8766_RESET, 0x0000, - WM8766_DAC_CTRL, 0x0120, - WM8766_INT_CTRL, 0x0022, /* I2S Normal Mode, 24 bit */ - WM8766_DAC_CTRL2, 0x0001, - WM8766_DAC_CTRL3, 0x0080, - WM8766_LDA1, 0x0100, - WM8766_LDA2, 0x0100, - WM8766_LDA3, 0x0100, - WM8766_RDA1, 0x0100, - WM8766_RDA2, 0x0100, - WM8766_RDA3, 0x0100, - WM8766_MUTE1, 0x0000, - WM8766_MUTE2, 0x0000, - }; - - struct prodigy_hifi_spec *spec; - unsigned int i; - - ice->vt1720 = 0; - ice->vt1724 = 1; - - ice->num_total_dacs = 8; - ice->num_total_adcs = 1; - - /* HACK - use this as the SPDIF source. - * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten - */ - ice->gpio.saved[0] = 0; - /* to remember the register values */ - - ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (! ice->akm) - return -ENOMEM; - ice->akm_codecs = 1; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - /* initialize WM8776 codec */ - for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) - wm_put(ice, wm_inits[i], wm_inits[i+1]); - schedule_timeout_uninterruptible(1); - for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2) - wm_put(ice, wm_inits2[i], wm_inits2[i+1]); - - /* initialize WM8766 codec */ - for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2) - wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i+1]); - - - return 0; -} - - -/* - * initialize the chip - */ -static void ak4396_init(struct snd_ice1712 *ice) -{ - static unsigned short ak4396_inits[] = { - AK4396_CTRL1, 0x87, /* I2S Normal Mode, 24 bit */ - AK4396_CTRL2, 0x02, - AK4396_CTRL3, 0x00, - AK4396_LCH_ATT, 0x00, - AK4396_RCH_ATT, 0x00, - }; - - unsigned int i; - - /* initialize ak4396 codec */ - /* reset codec */ - ak4396_write(ice, AK4396_CTRL1, 0x86); - msleep(100); - ak4396_write(ice, AK4396_CTRL1, 0x87); - - for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2) - ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]); -} - -#ifdef CONFIG_PM -static int prodigy_hd2_resume(struct snd_ice1712 *ice) -{ - /* initialize ak4396 codec and restore previous mixer volumes */ - struct prodigy_hifi_spec *spec = ice->spec; - int i; - mutex_lock(&ice->gpio_mutex); - ak4396_init(ice); - for (i = 0; i < 2; i++) - ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff); - mutex_unlock(&ice->gpio_mutex); - return 0; -} -#endif - -static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice) -{ - struct prodigy_hifi_spec *spec; - - ice->vt1720 = 0; - ice->vt1724 = 1; - - ice->num_total_dacs = 1; - ice->num_total_adcs = 1; - - /* HACK - use this as the SPDIF source. - * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten - */ - ice->gpio.saved[0] = 0; - /* to remember the register values */ - - ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (! ice->akm) - return -ENOMEM; - ice->akm_codecs = 1; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - -#ifdef CONFIG_PM - ice->pm_resume = &prodigy_hd2_resume; - ice->pm_suspend_enabled = 1; -#endif - - ak4396_init(ice); - - return 0; -} - - -static unsigned char prodigy71hifi_eeprom[] __devinitdata = { - 0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ - 0x80, /* ACLINK: I2S */ - 0xfc, /* I2S: vol, 96k, 24bit, 192k */ - 0xc3, /* SPDIF: out-en, out-int, spdif-in */ - 0xff, /* GPIO_DIR */ - 0xff, /* GPIO_DIR1 */ - 0x5f, /* GPIO_DIR2 */ - 0x00, /* GPIO_MASK */ - 0x00, /* GPIO_MASK1 */ - 0x00, /* GPIO_MASK2 */ - 0x00, /* GPIO_STATE */ - 0x00, /* GPIO_STATE1 */ - 0x00, /* GPIO_STATE2 */ -}; - -static unsigned char prodigyhd2_eeprom[] __devinitdata = { - 0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ - 0x80, /* ACLINK: I2S */ - 0xfc, /* I2S: vol, 96k, 24bit, 192k */ - 0xc3, /* SPDIF: out-en, out-int, spdif-in */ - 0xff, /* GPIO_DIR */ - 0xff, /* GPIO_DIR1 */ - 0x5f, /* GPIO_DIR2 */ - 0x00, /* GPIO_MASK */ - 0x00, /* GPIO_MASK1 */ - 0x00, /* GPIO_MASK2 */ - 0x00, /* GPIO_STATE */ - 0x00, /* GPIO_STATE1 */ - 0x00, /* GPIO_STATE2 */ -}; - -static unsigned char fortissimo4_eeprom[] __devinitdata = { - 0x43, /* SYSCONF: clock 512, ADC, 4DACs */ - 0x80, /* ACLINK: I2S */ - 0xfc, /* I2S: vol, 96k, 24bit, 192k */ - 0xc1, /* SPDIF: out-en, out-int */ - 0xff, /* GPIO_DIR */ - 0xff, /* GPIO_DIR1 */ - 0x5f, /* GPIO_DIR2 */ - 0x00, /* GPIO_MASK */ - 0x00, /* GPIO_MASK1 */ - 0x00, /* GPIO_MASK2 */ - 0x00, /* GPIO_STATE */ - 0x00, /* GPIO_STATE1 */ - 0x00, /* GPIO_STATE2 */ -}; - -/* entry point */ -struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI, - .name = "Audiotrak Prodigy 7.1 HiFi", - .model = "prodigy71hifi", - .chip_init = prodigy_hifi_init, - .build_controls = prodigy_hifi_add_controls, - .eeprom_size = sizeof(prodigy71hifi_eeprom), - .eeprom_data = prodigy71hifi_eeprom, - .driver = "Prodigy71HIFI", - }, - { - .subvendor = VT1724_SUBDEVICE_PRODIGY_HD2, - .name = "Audiotrak Prodigy HD2", - .model = "prodigyhd2", - .chip_init = prodigy_hd2_init, - .build_controls = prodigy_hd2_add_controls, - .eeprom_size = sizeof(prodigyhd2_eeprom), - .eeprom_data = prodigyhd2_eeprom, - .driver = "Prodigy71HD2", - }, - { - .subvendor = VT1724_SUBDEVICE_FORTISSIMO4, - .name = "Hercules Fortissimo IV", - .model = "fortissimo4", - .chip_init = prodigy_hifi_init, - .build_controls = prodigy_hifi_add_controls, - .eeprom_size = sizeof(fortissimo4_eeprom), - .eeprom_data = fortissimo4_eeprom, - .driver = "Fortissimo4", - }, - { } /* terminator */ -}; - diff --git a/ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.h b/ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.h deleted file mode 100644 index a4415d45..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/prodigy_hifi.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __SOUND_PRODIGY_HIFI_H -#define __SOUND_PRODIGY_HIFI_H - -/* - * ALSA driver for VIA VT1724 (Envy24HT) - * - * Lowlevel functions for Audiotrak Prodigy Hifi - * - * Copyright (c) 2004 Takashi Iwai - * - * 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 - * - */ - -#define PRODIGY_HIFI_DEVICE_DESC "{Audiotrak,Prodigy 7.1 HIFI},"\ - "{Audiotrak Prodigy HD2},"\ - "{Hercules Fortissimo IV}," - -#define VT1724_SUBDEVICE_PRODIGY_HIFI 0x38315441 /* PRODIGY 7.1 HIFI */ -#define VT1724_SUBDEVICE_PRODIGY_HD2 0x37315441 /* PRODIGY HD2 */ -#define VT1724_SUBDEVICE_FORTISSIMO4 0x81160100 /* Fortissimo IV */ - - -extern struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[]; - -#endif /* __SOUND_PRODIGY_HIFI_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/quartet.c b/ANDROID_3.4.5/sound/pci/ice1712/quartet.c deleted file mode 100644 index 19486327..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/quartet.c +++ /dev/null @@ -1,1130 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for Infrasonic Quartet - * - * Copyright (c) 2009 Pavel Hofman - * - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include -#include "quartet.h" - -struct qtet_spec { - struct ak4113 *ak4113; - unsigned int scr; /* system control register */ - unsigned int mcr; /* monitoring control register */ - unsigned int cpld; /* cpld register */ -}; - -struct qtet_kcontrol_private { - unsigned int bit; - void (*set_register)(struct snd_ice1712 *ice, unsigned int val); - unsigned int (*get_register)(struct snd_ice1712 *ice); - unsigned char *texts[2]; -}; - -enum { - IN12_SEL = 0, - IN34_SEL, - AIN34_SEL, - COAX_OUT, - IN12_MON12, - IN12_MON34, - IN34_MON12, - IN34_MON34, - OUT12_MON34, - OUT34_MON12, -}; - -static char *ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS", - "Word Clock 256xFS"}; - -/* chip address on I2C bus */ -#define AK4113_ADDR 0x26 /* S/PDIF receiver */ - -/* chip address on SPI bus */ -#define AK4620_ADDR 0x02 /* ADC/DAC */ - - -/* - * GPIO pins - */ - -/* GPIO0 - O - DATA0, def. 0 */ -#define GPIO_D0 (1<<0) -/* GPIO1 - I/O - DATA1, Jack Detect Input0 (0:present, 1:missing), def. 1 */ -#define GPIO_D1_JACKDTC0 (1<<1) -/* GPIO2 - I/O - DATA2, Jack Detect Input1 (0:present, 1:missing), def. 1 */ -#define GPIO_D2_JACKDTC1 (1<<2) -/* GPIO3 - I/O - DATA3, def. 1 */ -#define GPIO_D3 (1<<3) -/* GPIO4 - I/O - DATA4, SPI CDTO, def. 1 */ -#define GPIO_D4_SPI_CDTO (1<<4) -/* GPIO5 - I/O - DATA5, SPI CCLK, def. 1 */ -#define GPIO_D5_SPI_CCLK (1<<5) -/* GPIO6 - I/O - DATA6, Cable Detect Input (0:detected, 1:not detected */ -#define GPIO_D6_CD (1<<6) -/* GPIO7 - I/O - DATA7, Device Detect Input (0:detected, 1:not detected */ -#define GPIO_D7_DD (1<<7) -/* GPIO8 - O - CPLD Chip Select, def. 1 */ -#define GPIO_CPLD_CSN (1<<8) -/* GPIO9 - O - CPLD register read/write (0:write, 1:read), def. 0 */ -#define GPIO_CPLD_RW (1<<9) -/* GPIO10 - O - SPI Chip Select for CODEC#0, def. 1 */ -#define GPIO_SPI_CSN0 (1<<10) -/* GPIO11 - O - SPI Chip Select for CODEC#1, def. 1 */ -#define GPIO_SPI_CSN1 (1<<11) -/* GPIO12 - O - Ex. Register Output Enable (0:enable, 1:disable), def. 1, - * init 0 */ -#define GPIO_EX_GPIOE (1<<12) -/* GPIO13 - O - Ex. Register0 Chip Select for System Control Register, - * def. 1 */ -#define GPIO_SCR (1<<13) -/* GPIO14 - O - Ex. Register1 Chip Select for Monitor Control Register, - * def. 1 */ -#define GPIO_MCR (1<<14) - -#define GPIO_SPI_ALL (GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK |\ - GPIO_SPI_CSN0 | GPIO_SPI_CSN1) - -#define GPIO_DATA_MASK (GPIO_D0 | GPIO_D1_JACKDTC0 | \ - GPIO_D2_JACKDTC1 | GPIO_D3 | \ - GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK | \ - GPIO_D6_CD | GPIO_D7_DD) - -/* System Control Register GPIO_SCR data bits */ -/* Mic/Line select relay (0:line, 1:mic) */ -#define SCR_RELAY GPIO_D0 -/* Phantom power drive control (0:5V, 1:48V) */ -#define SCR_PHP_V GPIO_D1_JACKDTC0 -/* H/W mute control (0:Normal, 1:Mute) */ -#define SCR_MUTE GPIO_D2_JACKDTC1 -/* Phantom power control (0:Phantom on, 1:off) */ -#define SCR_PHP GPIO_D3 -/* Analog input 1/2 Source Select */ -#define SCR_AIN12_SEL0 GPIO_D4_SPI_CDTO -#define SCR_AIN12_SEL1 GPIO_D5_SPI_CCLK -/* Analog input 3/4 Source Select (0:line, 1:hi-z) */ -#define SCR_AIN34_SEL GPIO_D6_CD -/* Codec Power Down (0:power down, 1:normal) */ -#define SCR_CODEC_PDN GPIO_D7_DD - -#define SCR_AIN12_LINE (0) -#define SCR_AIN12_MIC (SCR_AIN12_SEL0) -#define SCR_AIN12_LOWCUT (SCR_AIN12_SEL1 | SCR_AIN12_SEL0) - -/* Monitor Control Register GPIO_MCR data bits */ -/* Input 1/2 to Monitor 1/2 (0:off, 1:on) */ -#define MCR_IN12_MON12 GPIO_D0 -/* Input 1/2 to Monitor 3/4 (0:off, 1:on) */ -#define MCR_IN12_MON34 GPIO_D1_JACKDTC0 -/* Input 3/4 to Monitor 1/2 (0:off, 1:on) */ -#define MCR_IN34_MON12 GPIO_D2_JACKDTC1 -/* Input 3/4 to Monitor 3/4 (0:off, 1:on) */ -#define MCR_IN34_MON34 GPIO_D3 -/* Output to Monitor 1/2 (0:off, 1:on) */ -#define MCR_OUT34_MON12 GPIO_D4_SPI_CDTO -/* Output to Monitor 3/4 (0:off, 1:on) */ -#define MCR_OUT12_MON34 GPIO_D5_SPI_CCLK - -/* CPLD Register DATA bits */ -/* Clock Rate Select */ -#define CPLD_CKS0 GPIO_D0 -#define CPLD_CKS1 GPIO_D1_JACKDTC0 -#define CPLD_CKS2 GPIO_D2_JACKDTC1 -/* Sync Source Select (0:Internal, 1:External) */ -#define CPLD_SYNC_SEL GPIO_D3 -/* Word Clock FS Select (0:FS, 1:256FS) */ -#define CPLD_WORD_SEL GPIO_D4_SPI_CDTO -/* Coaxial Output Source (IS-Link) (0:SPDIF, 1:I2S) */ -#define CPLD_COAX_OUT GPIO_D5_SPI_CCLK -/* Input 1/2 Source Select (0:Analog12, 1:An34) */ -#define CPLD_IN12_SEL GPIO_D6_CD -/* Input 3/4 Source Select (0:Analog34, 1:Digital In) */ -#define CPLD_IN34_SEL GPIO_D7_DD - -/* internal clock (CPLD_SYNC_SEL = 0) options */ -#define CPLD_CKS_44100HZ (0) -#define CPLD_CKS_48000HZ (CPLD_CKS0) -#define CPLD_CKS_88200HZ (CPLD_CKS1) -#define CPLD_CKS_96000HZ (CPLD_CKS1 | CPLD_CKS0) -#define CPLD_CKS_176400HZ (CPLD_CKS2) -#define CPLD_CKS_192000HZ (CPLD_CKS2 | CPLD_CKS0) - -#define CPLD_CKS_MASK (CPLD_CKS0 | CPLD_CKS1 | CPLD_CKS2) - -/* external clock (CPLD_SYNC_SEL = 1) options */ -/* external clock - SPDIF */ -#define CPLD_EXT_SPDIF (0 | CPLD_SYNC_SEL) -/* external clock - WordClock 1xfs */ -#define CPLD_EXT_WORDCLOCK_1FS (CPLD_CKS1 | CPLD_SYNC_SEL) -/* external clock - WordClock 256xfs */ -#define CPLD_EXT_WORDCLOCK_256FS (CPLD_CKS1 | CPLD_WORD_SEL |\ - CPLD_SYNC_SEL) - -#define EXT_SPDIF_TYPE 0 -#define EXT_WORDCLOCK_1FS_TYPE 1 -#define EXT_WORDCLOCK_256FS_TYPE 2 - -#define AK4620_DFS0 (1<<0) -#define AK4620_DFS1 (1<<1) -#define AK4620_CKS0 (1<<2) -#define AK4620_CKS1 (1<<3) -/* Clock and Format Control register */ -#define AK4620_DFS_REG 0x02 - -/* Deem and Volume Control register */ -#define AK4620_DEEMVOL_REG 0x03 -#define AK4620_SMUTE (1<<7) - -/* - * Conversion from int value to its binary form. Used for debugging. - * The output buffer must be allocated prior to calling the function. - */ -static char *get_binary(char *buffer, int value) -{ - int i, j, pos; - pos = 0; - for (i = 0; i < 4; ++i) { - for (j = 0; j < 8; ++j) { - if (value & (1 << (31-(i*8 + j)))) - buffer[pos] = '1'; - else - buffer[pos] = '0'; - pos++; - } - if (i < 3) { - buffer[pos] = ' '; - pos++; - } - } - buffer[pos] = '\0'; - return buffer; -} - -/* - * Initial setup of the conversion array GPIO <-> rate - */ -static unsigned int qtet_rates[] = { - 44100, 48000, 88200, - 96000, 176400, 192000, -}; - -static unsigned int cks_vals[] = { - CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ, - CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ, -}; - -static struct snd_pcm_hw_constraint_list qtet_rates_info = { - .count = ARRAY_SIZE(qtet_rates), - .list = qtet_rates, - .mask = 0, -}; - -static void qtet_ak4113_write(void *private_data, unsigned char reg, - unsigned char val) -{ - snd_vt1724_write_i2c((struct snd_ice1712 *)private_data, AK4113_ADDR, - reg, val); -} - -static unsigned char qtet_ak4113_read(void *private_data, unsigned char reg) -{ - return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, - AK4113_ADDR, reg); -} - - -/* - * AK4620 section - */ - -/* - * Write data to addr register of ak4620 - */ -static void qtet_akm_write(struct snd_akm4xxx *ak, int chip, - unsigned char addr, unsigned char data) -{ - unsigned int tmp, orig_dir; - int idx; - unsigned int addrdata; - struct snd_ice1712 *ice = ak->private_data[0]; - - if (snd_BUG_ON(chip < 0 || chip >= 4)) - return; - /*printk(KERN_DEBUG "Writing to AK4620: chip=%d, addr=0x%x, - data=0x%x\n", chip, addr, data);*/ - orig_dir = ice->gpio.get_dir(ice); - ice->gpio.set_dir(ice, orig_dir | GPIO_SPI_ALL); - /* set mask - only SPI bits */ - ice->gpio.set_mask(ice, ~GPIO_SPI_ALL); - - tmp = ice->gpio.get_data(ice); - /* high all */ - tmp |= GPIO_SPI_ALL; - ice->gpio.set_data(ice, tmp); - udelay(100); - /* drop chip select */ - if (chip) - /* CODEC 1 */ - tmp &= ~GPIO_SPI_CSN1; - else - tmp &= ~GPIO_SPI_CSN0; - ice->gpio.set_data(ice, tmp); - udelay(100); - - /* build I2C address + data byte */ - addrdata = (AK4620_ADDR << 6) | 0x20 | (addr & 0x1f); - addrdata = (addrdata << 8) | data; - for (idx = 15; idx >= 0; idx--) { - /* drop clock */ - tmp &= ~GPIO_D5_SPI_CCLK; - ice->gpio.set_data(ice, tmp); - udelay(100); - /* set data */ - if (addrdata & (1 << idx)) - tmp |= GPIO_D4_SPI_CDTO; - else - tmp &= ~GPIO_D4_SPI_CDTO; - ice->gpio.set_data(ice, tmp); - udelay(100); - /* raise clock */ - tmp |= GPIO_D5_SPI_CCLK; - ice->gpio.set_data(ice, tmp); - udelay(100); - } - /* all back to 1 */ - tmp |= GPIO_SPI_ALL; - ice->gpio.set_data(ice, tmp); - udelay(100); - - /* return all gpios to non-writable */ - ice->gpio.set_mask(ice, 0xffffff); - /* restore GPIOs direction */ - ice->gpio.set_dir(ice, orig_dir); -} - -static void qtet_akm_set_regs(struct snd_akm4xxx *ak, unsigned char addr, - unsigned char mask, unsigned char value) -{ - unsigned char tmp; - int chip; - for (chip = 0; chip < ak->num_chips; chip++) { - tmp = snd_akm4xxx_get(ak, chip, addr); - /* clear the bits */ - tmp &= ~mask; - /* set the new bits */ - tmp |= value; - snd_akm4xxx_write(ak, chip, addr, tmp); - } -} - -/* - * change the rate of AK4620 - */ -static void qtet_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) -{ - unsigned char ak4620_dfs; - - if (rate == 0) /* no hint - S/PDIF input is master or the new spdif - input rate undetected, simply return */ - return; - - /* adjust DFS on codecs - see datasheet */ - if (rate > 108000) - ak4620_dfs = AK4620_DFS1 | AK4620_CKS1; - else if (rate > 54000) - ak4620_dfs = AK4620_DFS0 | AK4620_CKS0; - else - ak4620_dfs = 0; - - /* set new value */ - qtet_akm_set_regs(ak, AK4620_DFS_REG, AK4620_DFS0 | AK4620_DFS1 | - AK4620_CKS0 | AK4620_CKS1, ak4620_dfs); -} - -#define AK_CONTROL(xname, xch) { .name = xname, .num_channels = xch } - -#define PCM_12_PLAYBACK_VOLUME "PCM 1/2 Playback Volume" -#define PCM_34_PLAYBACK_VOLUME "PCM 3/4 Playback Volume" -#define PCM_12_CAPTURE_VOLUME "PCM 1/2 Capture Volume" -#define PCM_34_CAPTURE_VOLUME "PCM 3/4 Capture Volume" - -static const struct snd_akm4xxx_dac_channel qtet_dac[] = { - AK_CONTROL(PCM_12_PLAYBACK_VOLUME, 2), - AK_CONTROL(PCM_34_PLAYBACK_VOLUME, 2), -}; - -static const struct snd_akm4xxx_adc_channel qtet_adc[] = { - AK_CONTROL(PCM_12_CAPTURE_VOLUME, 2), - AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2), -}; - -static struct snd_akm4xxx akm_qtet_dac __devinitdata = { - .type = SND_AK4620, - .num_dacs = 4, /* DAC1 - Output 12 - */ - .num_adcs = 4, /* ADC1 - Input 12 - */ - .ops = { - .write = qtet_akm_write, - .set_rate_val = qtet_akm_set_rate_val, - }, - .dac_info = qtet_dac, - .adc_info = qtet_adc, -}; - -/* Communication routines with the CPLD */ - - -/* Writes data to external register reg, both reg and data are - * GPIO representations */ -static void reg_write(struct snd_ice1712 *ice, unsigned int reg, - unsigned int data) -{ - unsigned int tmp; - - mutex_lock(&ice->gpio_mutex); - /* set direction of used GPIOs*/ - /* all outputs */ - tmp = 0x00ffff; - ice->gpio.set_dir(ice, tmp); - /* mask - writable bits */ - ice->gpio.set_mask(ice, ~(tmp)); - /* write the data */ - tmp = ice->gpio.get_data(ice); - tmp &= ~GPIO_DATA_MASK; - tmp |= data; - ice->gpio.set_data(ice, tmp); - udelay(100); - /* drop output enable */ - tmp &= ~GPIO_EX_GPIOE; - ice->gpio.set_data(ice, tmp); - udelay(100); - /* drop the register gpio */ - tmp &= ~reg; - ice->gpio.set_data(ice, tmp); - udelay(100); - /* raise the register GPIO */ - tmp |= reg; - ice->gpio.set_data(ice, tmp); - udelay(100); - - /* raise all data gpios */ - tmp |= GPIO_DATA_MASK; - ice->gpio.set_data(ice, tmp); - /* mask - immutable bits */ - ice->gpio.set_mask(ice, 0xffffff); - /* outputs only 8-15 */ - ice->gpio.set_dir(ice, 0x00ff00); - mutex_unlock(&ice->gpio_mutex); -} - -static unsigned int get_scr(struct snd_ice1712 *ice) -{ - struct qtet_spec *spec = ice->spec; - return spec->scr; -} - -static unsigned int get_mcr(struct snd_ice1712 *ice) -{ - struct qtet_spec *spec = ice->spec; - return spec->mcr; -} - -static unsigned int get_cpld(struct snd_ice1712 *ice) -{ - struct qtet_spec *spec = ice->spec; - return spec->cpld; -} - -static void set_scr(struct snd_ice1712 *ice, unsigned int val) -{ - struct qtet_spec *spec = ice->spec; - reg_write(ice, GPIO_SCR, val); - spec->scr = val; -} - -static void set_mcr(struct snd_ice1712 *ice, unsigned int val) -{ - struct qtet_spec *spec = ice->spec; - reg_write(ice, GPIO_MCR, val); - spec->mcr = val; -} - -static void set_cpld(struct snd_ice1712 *ice, unsigned int val) -{ - struct qtet_spec *spec = ice->spec; - reg_write(ice, GPIO_CPLD_CSN, val); - spec->cpld = val; -} -#ifdef CONFIG_PROC_FS -static void proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ice1712 *ice = entry->private_data; - char bin_buffer[36]; - - snd_iprintf(buffer, "SCR: %s\n", get_binary(bin_buffer, - get_scr(ice))); - snd_iprintf(buffer, "MCR: %s\n", get_binary(bin_buffer, - get_mcr(ice))); - snd_iprintf(buffer, "CPLD: %s\n", get_binary(bin_buffer, - get_cpld(ice))); -} - -static void proc_init(struct snd_ice1712 *ice) -{ - struct snd_info_entry *entry; - if (!snd_card_proc_new(ice->card, "quartet", &entry)) - snd_info_set_text_ops(entry, ice, proc_regs_read); -} -#else /* !CONFIG_PROC_FS */ -static void proc_init(struct snd_ice1712 *ice) {} -#endif - -static int qtet_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val; - val = get_scr(ice) & SCR_MUTE; - ucontrol->value.integer.value[0] = (val) ? 0 : 1; - return 0; -} - -static int qtet_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int old, new, smute; - old = get_scr(ice) & SCR_MUTE; - if (ucontrol->value.integer.value[0]) { - /* unmute */ - new = 0; - /* un-smuting DAC */ - smute = 0; - } else { - /* mute */ - new = SCR_MUTE; - /* smuting DAC */ - smute = AK4620_SMUTE; - } - if (old != new) { - struct snd_akm4xxx *ak = ice->akm; - set_scr(ice, (get_scr(ice) & ~SCR_MUTE) | new); - /* set smute */ - qtet_akm_set_regs(ak, AK4620_DEEMVOL_REG, AK4620_SMUTE, smute); - return 1; - } - /* no change */ - return 0; -} - -static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = {"Line In 1/2", "Mic", "Mic + Low-cut"}; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = ARRAY_SIZE(texts); - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int qtet_ain12_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val, result; - val = get_scr(ice) & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); - switch (val) { - case SCR_AIN12_LINE: - result = 0; - break; - case SCR_AIN12_MIC: - result = 1; - break; - case SCR_AIN12_LOWCUT: - result = 2; - break; - default: - /* BUG - no other combinations allowed */ - snd_BUG(); - result = 0; - } - ucontrol->value.integer.value[0] = result; - return 0; -} - -static int qtet_ain12_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int old, new, tmp, masked_old; - old = new = get_scr(ice); - masked_old = old & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); - tmp = ucontrol->value.integer.value[0]; - if (tmp == 2) - tmp = 3; /* binary 10 is not supported */ - tmp <<= 4; /* shifting to SCR_AIN12_SEL0 */ - if (tmp != masked_old) { - /* change requested */ - switch (tmp) { - case SCR_AIN12_LINE: - new = old & ~(SCR_AIN12_SEL1 | SCR_AIN12_SEL0); - set_scr(ice, new); - /* turn off relay */ - new &= ~SCR_RELAY; - set_scr(ice, new); - break; - case SCR_AIN12_MIC: - /* turn on relay */ - new = old | SCR_RELAY; - set_scr(ice, new); - new = (new & ~SCR_AIN12_SEL1) | SCR_AIN12_SEL0; - set_scr(ice, new); - break; - case SCR_AIN12_LOWCUT: - /* turn on relay */ - new = old | SCR_RELAY; - set_scr(ice, new); - new |= SCR_AIN12_SEL1 | SCR_AIN12_SEL0; - set_scr(ice, new); - break; - default: - snd_BUG(); - } - return 1; - } - /* no change */ - return 0; -} - -static int qtet_php_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int val; - /* if phantom voltage =48V, phantom on */ - val = get_scr(ice) & SCR_PHP_V; - ucontrol->value.integer.value[0] = val ? 1 : 0; - return 0; -} - -static int qtet_php_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int old, new; - old = new = get_scr(ice); - if (ucontrol->value.integer.value[0] /* phantom on requested */ - && (~old & SCR_PHP_V)) /* 0 = voltage 5V */ { - /* is off, turn on */ - /* turn voltage on first, = 1 */ - new = old | SCR_PHP_V; - set_scr(ice, new); - /* turn phantom on, = 0 */ - new &= ~SCR_PHP; - set_scr(ice, new); - } else if (!ucontrol->value.integer.value[0] && (old & SCR_PHP_V)) { - /* phantom off requested and 1 = voltage 48V */ - /* is on, turn off */ - /* turn voltage off first, = 0 */ - new = old & ~SCR_PHP_V; - set_scr(ice, new); - /* turn phantom off, = 1 */ - new |= SCR_PHP; - set_scr(ice, new); - } - if (old != new) - return 1; - /* no change */ - return 0; -} - -#define PRIV_SW(xid, xbit, xreg) [xid] = {.bit = xbit,\ - .set_register = set_##xreg,\ - .get_register = get_##xreg, } - - -#define PRIV_ENUM2(xid, xbit, xreg, xtext1, xtext2) [xid] = {.bit = xbit,\ - .set_register = set_##xreg,\ - .get_register = get_##xreg,\ - .texts = {xtext1, xtext2} } - -static struct qtet_kcontrol_private qtet_privates[] = { - PRIV_ENUM2(IN12_SEL, CPLD_IN12_SEL, cpld, "An In 1/2", "An In 3/4"), - PRIV_ENUM2(IN34_SEL, CPLD_IN34_SEL, cpld, "An In 3/4", "IEC958 In"), - PRIV_ENUM2(AIN34_SEL, SCR_AIN34_SEL, scr, "Line In 3/4", "Hi-Z"), - PRIV_ENUM2(COAX_OUT, CPLD_COAX_OUT, cpld, "IEC958", "I2S"), - PRIV_SW(IN12_MON12, MCR_IN12_MON12, mcr), - PRIV_SW(IN12_MON34, MCR_IN12_MON34, mcr), - PRIV_SW(IN34_MON12, MCR_IN34_MON12, mcr), - PRIV_SW(IN34_MON34, MCR_IN34_MON34, mcr), - PRIV_SW(OUT12_MON34, MCR_OUT12_MON34, mcr), - PRIV_SW(OUT34_MON12, MCR_OUT34_MON12, mcr), -}; - -static int qtet_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct qtet_kcontrol_private private = - qtet_privates[kcontrol->private_value]; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = ARRAY_SIZE(private.texts); - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - private.texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int qtet_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct qtet_kcontrol_private private = - qtet_privates[kcontrol->private_value]; - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = - (private.get_register(ice) & private.bit) ? 1 : 0; - return 0; -} - -static int qtet_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct qtet_kcontrol_private private = - qtet_privates[kcontrol->private_value]; - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned int old, new; - old = private.get_register(ice); - if (ucontrol->value.integer.value[0]) - new = old | private.bit; - else - new = old & ~private.bit; - if (old != new) { - private.set_register(ice, new); - return 1; - } - /* no change */ - return 0; -} - -#define qtet_sw_info snd_ctl_boolean_mono_info - -#define QTET_CONTROL(xname, xtype, xpriv) \ - {.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname,\ - .info = qtet_##xtype##_info,\ - .get = qtet_sw_get,\ - .put = qtet_sw_put,\ - .private_value = xpriv } - -static struct snd_kcontrol_new qtet_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = qtet_sw_info, - .get = qtet_mute_get, - .put = qtet_mute_put, - .private_value = 0 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Phantom Power", - .info = qtet_sw_info, - .get = qtet_php_get, - .put = qtet_php_put, - .private_value = 0 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog In 1/2 Capture Switch", - .info = qtet_ain12_enum_info, - .get = qtet_ain12_sw_get, - .put = qtet_ain12_sw_put, - .private_value = 0 - }, - QTET_CONTROL("Analog In 3/4 Capture Switch", enum, AIN34_SEL), - QTET_CONTROL("PCM In 1/2 Capture Switch", enum, IN12_SEL), - QTET_CONTROL("PCM In 3/4 Capture Switch", enum, IN34_SEL), - QTET_CONTROL("Coax Output Source", enum, COAX_OUT), - QTET_CONTROL("Analog In 1/2 to Monitor 1/2", sw, IN12_MON12), - QTET_CONTROL("Analog In 1/2 to Monitor 3/4", sw, IN12_MON34), - QTET_CONTROL("Analog In 3/4 to Monitor 1/2", sw, IN34_MON12), - QTET_CONTROL("Analog In 3/4 to Monitor 3/4", sw, IN34_MON34), - QTET_CONTROL("Output 1/2 to Monitor 3/4", sw, OUT12_MON34), - QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12), -}; - -static char *slave_vols[] __devinitdata = { - PCM_12_PLAYBACK_VOLUME, - PCM_34_PLAYBACK_VOLUME, - NULL -}; - -static __devinitdata -DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1); - -static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, - const char *name) -{ - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - /* FIXME: strcpy is bad. */ - strcpy(sid.name, name); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_find_id(card, &sid); -} - -static void __devinit add_slaves(struct snd_card *card, - struct snd_kcontrol *master, char **list) -{ - for (; *list; list++) { - struct snd_kcontrol *slave = ctl_find(card, *list); - if (slave) - snd_ctl_add_slave(master, slave); - } -} - -static int __devinit qtet_add_controls(struct snd_ice1712 *ice) -{ - struct qtet_spec *spec = ice->spec; - int err, i; - struct snd_kcontrol *vmaster; - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - for (i = 0; i < ARRAY_SIZE(qtet_controls); i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&qtet_controls[i], ice)); - if (err < 0) - return err; - } - - /* Create virtual master control */ - vmaster = snd_ctl_make_virtual_master("Master Playback Volume", - qtet_master_db_scale); - if (!vmaster) - return -ENOMEM; - add_slaves(ice->card, vmaster, slave_vols); - err = snd_ctl_add(ice->card, vmaster); - if (err < 0) - return err; - /* only capture SPDIF over AK4113 */ - err = snd_ak4113_build(spec->ak4113, - ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); - if (err < 0) - return err; - return 0; -} - -static inline int qtet_is_spdif_master(struct snd_ice1712 *ice) -{ - /* CPLD_SYNC_SEL: 0 = internal, 1 = external (i.e. spdif master) */ - return (get_cpld(ice) & CPLD_SYNC_SEL) ? 1 : 0; -} - -static unsigned int qtet_get_rate(struct snd_ice1712 *ice) -{ - int i; - unsigned char result; - - result = get_cpld(ice) & CPLD_CKS_MASK; - for (i = 0; i < ARRAY_SIZE(cks_vals); i++) - if (cks_vals[i] == result) - return qtet_rates[i]; - return 0; -} - -static int get_cks_val(int rate) -{ - int i; - for (i = 0; i < ARRAY_SIZE(qtet_rates); i++) - if (qtet_rates[i] == rate) - return cks_vals[i]; - return 0; -} - -/* setting new rate */ -static void qtet_set_rate(struct snd_ice1712 *ice, unsigned int rate) -{ - unsigned int new; - unsigned char val; - /* switching ice1724 to external clock - supplied by ext. circuits */ - val = inb(ICEMT1724(ice, RATE)); - outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); - - new = (get_cpld(ice) & ~CPLD_CKS_MASK) | get_cks_val(rate); - /* switch to internal clock, drop CPLD_SYNC_SEL */ - new &= ~CPLD_SYNC_SEL; - /* printk(KERN_DEBUG "QT - set_rate: old %x, new %x\n", - get_cpld(ice), new); */ - set_cpld(ice, new); -} - -static inline unsigned char qtet_set_mclk(struct snd_ice1712 *ice, - unsigned int rate) -{ - /* no change in master clock */ - return 0; -} - -/* setting clock to external - SPDIF */ -static int qtet_set_spdif_clock(struct snd_ice1712 *ice, int type) -{ - unsigned int old, new; - - old = new = get_cpld(ice); - new &= ~(CPLD_CKS_MASK | CPLD_WORD_SEL); - switch (type) { - case EXT_SPDIF_TYPE: - new |= CPLD_EXT_SPDIF; - break; - case EXT_WORDCLOCK_1FS_TYPE: - new |= CPLD_EXT_WORDCLOCK_1FS; - break; - case EXT_WORDCLOCK_256FS_TYPE: - new |= CPLD_EXT_WORDCLOCK_256FS; - break; - default: - snd_BUG(); - } - if (old != new) { - set_cpld(ice, new); - /* changed */ - return 1; - } - return 0; -} - -static int qtet_get_spdif_master_type(struct snd_ice1712 *ice) -{ - unsigned int val; - int result; - val = get_cpld(ice); - /* checking only rate/clock-related bits */ - val &= (CPLD_CKS_MASK | CPLD_WORD_SEL | CPLD_SYNC_SEL); - if (!(val & CPLD_SYNC_SEL)) { - /* switched to internal clock, is not any external type */ - result = -1; - } else { - switch (val) { - case (CPLD_EXT_SPDIF): - result = EXT_SPDIF_TYPE; - break; - case (CPLD_EXT_WORDCLOCK_1FS): - result = EXT_WORDCLOCK_1FS_TYPE; - break; - case (CPLD_EXT_WORDCLOCK_256FS): - result = EXT_WORDCLOCK_256FS_TYPE; - break; - default: - /* undefined combination of external clock setup */ - snd_BUG(); - result = 0; - } - } - return result; -} - -/* Called when ak4113 detects change in the input SPDIF stream */ -static void qtet_ak4113_change(struct ak4113 *ak4113, unsigned char c0, - unsigned char c1) -{ - struct snd_ice1712 *ice = ak4113->change_callback_private; - int rate; - if ((qtet_get_spdif_master_type(ice) == EXT_SPDIF_TYPE) && - c1) { - /* only for SPDIF master mode, rate was changed */ - rate = snd_ak4113_external_rate(ak4113); - /* printk(KERN_DEBUG "ak4113 - input rate changed to %d\n", - rate); */ - qtet_akm_set_rate_val(ice->akm, rate); - } -} - -/* - * If clock slaved to SPDIF-IN, setting runtime rate - * to the detected external rate - */ -static void qtet_spdif_in_open(struct snd_ice1712 *ice, - struct snd_pcm_substream *substream) -{ - struct qtet_spec *spec = ice->spec; - struct snd_pcm_runtime *runtime = substream->runtime; - int rate; - - if (qtet_get_spdif_master_type(ice) != EXT_SPDIF_TYPE) - /* not external SPDIF, no rate limitation */ - return; - /* only external SPDIF can detect incoming sample rate */ - rate = snd_ak4113_external_rate(spec->ak4113); - if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) { - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } -} - -/* - * initialize the chip - */ -static int __devinit qtet_init(struct snd_ice1712 *ice) -{ - static const unsigned char ak4113_init_vals[] = { - /* AK4113_REG_PWRDN */ AK4113_RST | AK4113_PWN | - AK4113_OCKS0 | AK4113_OCKS1, - /* AK4113_REQ_FORMAT */ AK4113_DIF_I24I2S | AK4113_VTX | - AK4113_DEM_OFF | AK4113_DEAU, - /* AK4113_REG_IO0 */ AK4113_OPS2 | AK4113_TXE | - AK4113_XTL_24_576M, - /* AK4113_REG_IO1 */ AK4113_EFH_1024LRCLK | AK4113_IPS(0), - /* AK4113_REG_INT0_MASK */ 0, - /* AK4113_REG_INT1_MASK */ 0, - /* AK4113_REG_DATDTS */ 0, - }; - int err; - struct qtet_spec *spec; - struct snd_akm4xxx *ak; - unsigned char val; - - /* switching ice1724 to external clock - supplied by ext. circuits */ - val = inb(ICEMT1724(ice, RATE)); - outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - /* qtet is clocked by Xilinx array */ - ice->hw_rates = &qtet_rates_info; - ice->is_spdif_master = qtet_is_spdif_master; - ice->get_rate = qtet_get_rate; - ice->set_rate = qtet_set_rate; - ice->set_mclk = qtet_set_mclk; - ice->set_spdif_clock = qtet_set_spdif_clock; - ice->get_spdif_master_type = qtet_get_spdif_master_type; - ice->ext_clock_names = ext_clock_names; - ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); - /* since Qtet can detect correct SPDIF-in rate, all streams can be - * limited to this specific rate */ - ice->spdif.ops.open = ice->pro_open = qtet_spdif_in_open; - ice->spec = spec; - - /* Mute Off */ - /* SCR Initialize*/ - /* keep codec power down first */ - set_scr(ice, SCR_PHP); - udelay(1); - /* codec power up */ - set_scr(ice, SCR_PHP | SCR_CODEC_PDN); - - /* MCR Initialize */ - set_mcr(ice, 0); - - /* CPLD Initialize */ - set_cpld(ice, 0); - - - ice->num_total_dacs = 2; - ice->num_total_adcs = 2; - - ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL); - ak = ice->akm; - if (!ak) - return -ENOMEM; - /* only one codec with two chips */ - ice->akm_codecs = 1; - err = snd_ice1712_akm4xxx_init(ak, &akm_qtet_dac, NULL, ice); - if (err < 0) - return err; - err = snd_ak4113_create(ice->card, - qtet_ak4113_read, - qtet_ak4113_write, - ak4113_init_vals, - ice, &spec->ak4113); - if (err < 0) - return err; - /* callback for codecs rate setting */ - spec->ak4113->change_callback = qtet_ak4113_change; - spec->ak4113->change_callback_private = ice; - /* AK41143 in Quartet can detect external rate correctly - * (i.e. check_flags = 0) */ - spec->ak4113->check_flags = 0; - - proc_init(ice); - - qtet_set_rate(ice, 44100); - return 0; -} - -static unsigned char qtet_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x28, /* clock 256(24MHz), mpu401, 1xADC, - 1xDACs, SPDIF in */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0x78, /* 96k, 24bit, 192k */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, in, out-ext */ - [ICE_EEP2_GPIO_DIR] = 0x00, /* 0-7 inputs, switched to output - only during output operations */ - [ICE_EEP2_GPIO_DIR1] = 0xff, /* 8-15 outputs */ - [ICE_EEP2_GPIO_DIR2] = 0x00, - [ICE_EEP2_GPIO_MASK] = 0xff, /* changed only for OUT operations */ - [ICE_EEP2_GPIO_MASK1] = 0x00, - [ICE_EEP2_GPIO_MASK2] = 0xff, - - [ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */ - [ICE_EEP2_GPIO_STATE1] = 0x7d, /* all 1, but GPIO_CPLD_RW - and GPIO15 always zero */ - [ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */ -}; - -/* entry point */ -struct snd_ice1712_card_info snd_vt1724_qtet_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_QTET, - .name = "Infrasonic Quartet", - .model = "quartet", - .chip_init = qtet_init, - .build_controls = qtet_add_controls, - .eeprom_size = sizeof(qtet_eeprom), - .eeprom_data = qtet_eeprom, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/quartet.h b/ANDROID_3.4.5/sound/pci/ice1712/quartet.h deleted file mode 100644 index 80809b72..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/quartet.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __SOUND_QTET_H -#define __SOUND_QTET_H - -#define QTET_DEVICE_DESC "{Infrasonic,Quartet}," - -#define VT1724_SUBDEVICE_QTET 0x30305349 /* Infrasonic Quartet */ - -extern struct snd_ice1712_card_info snd_vt1724_qtet_cards[]; - -#endif /* __SOUND_QTET_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/revo.c b/ANDROID_3.4.5/sound/pci/ice1712/revo.c deleted file mode 100644 index b508bb36..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/revo.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for M-Audio Audiophile 192, Revolution 7.1 and 5.1 - * - * Copyright (c) 2003 Takashi Iwai - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include "revo.h" - -/* a non-standard I2C device for revo51 */ -struct revo51_spec { - struct snd_i2c_device *dev; - struct snd_pt2258 *pt2258; -}; - -static void revo_i2s_mclk_changed(struct snd_ice1712 *ice) -{ - /* assert PRST# to converters; MT05 bit 7 */ - outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); - mdelay(5); - /* deassert PRST# */ - outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); -} - -/* - * change the rate of Envy24HT, AK4355 and AK4381 - */ -static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) -{ - unsigned char old, tmp, dfs; - int reg, shift; - - if (rate == 0) /* no hint - S/PDIF input is master, simply return */ - return; - - /* adjust DFS on codecs */ - if (rate > 96000) - dfs = 2; - else if (rate > 48000) - dfs = 1; - else - dfs = 0; - - if (ak->type == SND_AK4355 || ak->type == SND_AK4358) { - reg = 2; - shift = 4; - } else { - reg = 1; - shift = 3; - } - tmp = snd_akm4xxx_get(ak, 0, reg); - old = (tmp >> shift) & 0x03; - if (old == dfs) - return; - - /* reset DFS */ - snd_akm4xxx_reset(ak, 1); - tmp = snd_akm4xxx_get(ak, 0, reg); - tmp &= ~(0x03 << shift); - tmp |= dfs << shift; - /* snd_akm4xxx_write(ak, 0, reg, tmp); */ - snd_akm4xxx_set(ak, 0, reg, tmp); /* value is written in reset(0) */ - snd_akm4xxx_reset(ak, 0); -} - -/* - * I2C access to the PT2258 volume controller on GPIO 6/7 (Revolution 5.1) - */ - -static void revo_i2c_start(struct snd_i2c_bus *bus) -{ - struct snd_ice1712 *ice = bus->private_data; - snd_ice1712_save_gpio_status(ice); -} - -static void revo_i2c_stop(struct snd_i2c_bus *bus) -{ - struct snd_ice1712 *ice = bus->private_data; - snd_ice1712_restore_gpio_status(ice); -} - -static void revo_i2c_direction(struct snd_i2c_bus *bus, int clock, int data) -{ - struct snd_ice1712 *ice = bus->private_data; - unsigned int mask, val; - - val = 0; - if (clock) - val |= VT1724_REVO_I2C_CLOCK; /* write SCL */ - if (data) - val |= VT1724_REVO_I2C_DATA; /* write SDA */ - mask = VT1724_REVO_I2C_CLOCK | VT1724_REVO_I2C_DATA; - ice->gpio.direction &= ~mask; - ice->gpio.direction |= val; - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction); - snd_ice1712_gpio_set_mask(ice, ~mask); -} - -static void revo_i2c_setlines(struct snd_i2c_bus *bus, int clk, int data) -{ - struct snd_ice1712 *ice = bus->private_data; - unsigned int val = 0; - - if (clk) - val |= VT1724_REVO_I2C_CLOCK; - if (data) - val |= VT1724_REVO_I2C_DATA; - snd_ice1712_gpio_write_bits(ice, - VT1724_REVO_I2C_DATA | - VT1724_REVO_I2C_CLOCK, val); - udelay(5); -} - -static int revo_i2c_getdata(struct snd_i2c_bus *bus, int ack) -{ - struct snd_ice1712 *ice = bus->private_data; - int bit; - - if (ack) - udelay(5); - bit = snd_ice1712_gpio_read_bits(ice, VT1724_REVO_I2C_DATA) ? 1 : 0; - return bit; -} - -static struct snd_i2c_bit_ops revo51_bit_ops = { - .start = revo_i2c_start, - .stop = revo_i2c_stop, - .direction = revo_i2c_direction, - .setlines = revo_i2c_setlines, - .getdata = revo_i2c_getdata, -}; - -static int revo51_i2c_init(struct snd_ice1712 *ice, - struct snd_pt2258 *pt) -{ - struct revo51_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - /* create the I2C bus */ - err = snd_i2c_bus_create(ice->card, "ICE1724 GPIO6", NULL, &ice->i2c); - if (err < 0) - return err; - - ice->i2c->private_data = ice; - ice->i2c->hw_ops.bit = &revo51_bit_ops; - - /* create the I2C device */ - err = snd_i2c_device_create(ice->i2c, "PT2258", 0x40, &spec->dev); - if (err < 0) - return err; - - pt->card = ice->card; - pt->i2c_bus = ice->i2c; - pt->i2c_dev = spec->dev; - spec->pt2258 = pt; - - snd_pt2258_reset(pt); - - return 0; -} - -/* - * initialize the chips on M-Audio Revolution cards - */ - -#define AK_DAC(xname,xch) { .name = xname, .num_channels = xch } - -static const struct snd_akm4xxx_dac_channel revo71_front[] = { - { - .name = "PCM Playback Volume", - .num_channels = 2, - /* front channels DAC supports muting */ - .switch_name = "PCM Playback Switch", - }, -}; - -static const struct snd_akm4xxx_dac_channel revo71_surround[] = { - AK_DAC("PCM Center Playback Volume", 1), - AK_DAC("PCM LFE Playback Volume", 1), - AK_DAC("PCM Side Playback Volume", 2), - AK_DAC("PCM Rear Playback Volume", 2), -}; - -static const struct snd_akm4xxx_dac_channel revo51_dac[] = { - AK_DAC("PCM Playback Volume", 2), - AK_DAC("PCM Center Playback Volume", 1), - AK_DAC("PCM LFE Playback Volume", 1), - AK_DAC("PCM Rear Playback Volume", 2), - AK_DAC("PCM Headphone Volume", 2), -}; - -static const char *revo51_adc_input_names[] = { - "Mic", - "Line", - "CD", - NULL -}; - -static const struct snd_akm4xxx_adc_channel revo51_adc[] = { - { - .name = "PCM Capture Volume", - .switch_name = "PCM Capture Switch", - .num_channels = 2, - .input_names = revo51_adc_input_names - }, -}; - -static struct snd_akm4xxx akm_revo_front __devinitdata = { - .type = SND_AK4381, - .num_dacs = 2, - .ops = { - .set_rate_val = revo_set_rate_val - }, - .dac_info = revo71_front, -}; - -static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { - .caddr = 1, - .cif = 0, - .data_mask = VT1724_REVO_CDOUT, - .clk_mask = VT1724_REVO_CCLK, - .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, - .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS2, - .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, - .add_flags = VT1724_REVO_CCLK, /* high at init */ - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_revo_surround __devinitdata = { - .type = SND_AK4355, - .idx_offset = 1, - .num_dacs = 6, - .ops = { - .set_rate_val = revo_set_rate_val - }, - .dac_info = revo71_surround, -}; - -static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { - .caddr = 3, - .cif = 0, - .data_mask = VT1724_REVO_CDOUT, - .clk_mask = VT1724_REVO_CCLK, - .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, - .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS1, - .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, - .add_flags = VT1724_REVO_CCLK, /* high at init */ - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_revo51 __devinitdata = { - .type = SND_AK4358, - .num_dacs = 8, - .ops = { - .set_rate_val = revo_set_rate_val - }, - .dac_info = revo51_dac, -}; - -static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { - .caddr = 2, - .cif = 0, - .data_mask = VT1724_REVO_CDOUT, - .clk_mask = VT1724_REVO_CCLK, - .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1, - .cs_addr = VT1724_REVO_CS1, - .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1, - .add_flags = VT1724_REVO_CCLK, /* high at init */ - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_revo51_adc __devinitdata = { - .type = SND_AK5365, - .num_adcs = 2, - .adc_info = revo51_adc, -}; - -static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = { - .caddr = 2, - .cif = 0, - .data_mask = VT1724_REVO_CDOUT, - .clk_mask = VT1724_REVO_CCLK, - .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1, - .cs_addr = VT1724_REVO_CS0, - .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1, - .add_flags = VT1724_REVO_CCLK, /* high at init */ - .mask_flags = 0, -}; - -static struct snd_pt2258 ptc_revo51_volume; - -/* AK4358 for AP192 DAC, AK5385A for ADC */ -static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) -{ - struct snd_ice1712 *ice = ak->private_data[0]; - int dfs; - - revo_set_rate_val(ak, rate); - - /* reset CKS */ - snd_ice1712_gpio_write_bits(ice, 1 << 8, rate > 96000 ? 1 << 8 : 0); - /* reset DFS pins of AK5385A for ADC, too */ - if (rate > 96000) - dfs = 2; - else if (rate > 48000) - dfs = 1; - else - dfs = 0; - snd_ice1712_gpio_write_bits(ice, 3 << 9, dfs << 9); - /* reset ADC */ - snd_ice1712_gpio_write_bits(ice, 1 << 11, 0); - snd_ice1712_gpio_write_bits(ice, 1 << 11, 1 << 11); -} - -static const struct snd_akm4xxx_dac_channel ap192_dac[] = { - AK_DAC("PCM Playback Volume", 2) -}; - -static struct snd_akm4xxx akm_ap192 __devinitdata = { - .type = SND_AK4358, - .num_dacs = 2, - .ops = { - .set_rate_val = ap192_set_rate_val - }, - .dac_info = ap192_dac, -}; - -static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = { - .caddr = 2, - .cif = 0, - .data_mask = VT1724_REVO_CDOUT, - .clk_mask = VT1724_REVO_CCLK, - .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1, - .cs_addr = VT1724_REVO_CS1, - .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1, - .add_flags = VT1724_REVO_CCLK, /* high at init */ - .mask_flags = 0, -}; - -/* AK4114 support on Audiophile 192 */ -/* CDTO (pin 32) -- GPIO2 pin 52 - * CDTI (pin 33) -- GPIO3 pin 53 (shared with AK4358) - * CCLK (pin 34) -- GPIO1 pin 51 (shared with AK4358) - * CSN (pin 35) -- GPIO7 pin 59 - */ -#define AK4114_ADDR 0x02 - -static void write_data(struct snd_ice1712 *ice, unsigned int gpio, - unsigned int data, int idx) -{ - for (; idx >= 0; idx--) { - /* drop clock */ - gpio &= ~VT1724_REVO_CCLK; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - /* set data */ - if (data & (1 << idx)) - gpio |= VT1724_REVO_CDOUT; - else - gpio &= ~VT1724_REVO_CDOUT; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - /* raise clock */ - gpio |= VT1724_REVO_CCLK; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - } -} - -static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio, - int idx) -{ - unsigned char data = 0; - - for (; idx >= 0; idx--) { - /* drop clock */ - gpio &= ~VT1724_REVO_CCLK; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - /* read data */ - if (snd_ice1712_gpio_read(ice) & VT1724_REVO_CDIN) - data |= (1 << idx); - udelay(1); - /* raise clock */ - gpio |= VT1724_REVO_CCLK; - snd_ice1712_gpio_write(ice, gpio); - udelay(1); - } - return data; -} - -static unsigned int ap192_4wire_start(struct snd_ice1712 *ice) -{ - unsigned int tmp; - - snd_ice1712_save_gpio_status(ice); - tmp = snd_ice1712_gpio_read(ice); - tmp |= VT1724_REVO_CCLK; /* high at init */ - tmp |= VT1724_REVO_CS0; - tmp &= ~VT1724_REVO_CS1; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - return tmp; -} - -static void ap192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp) -{ - tmp |= VT1724_REVO_CS1; - tmp |= VT1724_REVO_CS0; - snd_ice1712_gpio_write(ice, tmp); - udelay(1); - snd_ice1712_restore_gpio_status(ice); -} - -static void ap192_ak4114_write(void *private_data, unsigned char addr, - unsigned char data) -{ - struct snd_ice1712 *ice = private_data; - unsigned int tmp, addrdata; - - tmp = ap192_4wire_start(ice); - addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f); - addrdata = (addrdata << 8) | data; - write_data(ice, tmp, addrdata, 15); - ap192_4wire_finish(ice, tmp); -} - -static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr) -{ - struct snd_ice1712 *ice = private_data; - unsigned int tmp; - unsigned char data; - - tmp = ap192_4wire_start(ice); - write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7); - data = read_data(ice, tmp, 7); - ap192_4wire_finish(ice, tmp); - return data; -} - -static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice) -{ - static const unsigned char ak4114_init_vals[] = { - AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1, - AK4114_DIF_I24I2S, - AK4114_TX1E, - AK4114_EFH_1024 | AK4114_DIT | AK4114_IPS(1), - 0, - 0 - }; - static const unsigned char ak4114_init_txcsb[] = { - 0x41, 0x02, 0x2c, 0x00, 0x00 - }; - struct ak4114 *ak; - int err; - - err = snd_ak4114_create(ice->card, - ap192_ak4114_read, - ap192_ak4114_write, - ak4114_init_vals, ak4114_init_txcsb, - ice, &ak); - /* AK4114 in Revo cannot detect external rate correctly. - * No reason to stop capture stream due to incorrect checks */ - ak->check_flags = AK4114_CHECK_NO_RATE; - - return 0; /* error ignored; it's no fatal error */ -} - -static int __devinit revo_init(struct snd_ice1712 *ice) -{ - struct snd_akm4xxx *ak; - int err; - - /* determine I2C, DACs and ADCs */ - switch (ice->eeprom.subvendor) { - case VT1724_SUBDEVICE_REVOLUTION71: - ice->num_total_dacs = 8; - ice->num_total_adcs = 2; - ice->gpio.i2s_mclk_changed = revo_i2s_mclk_changed; - break; - case VT1724_SUBDEVICE_REVOLUTION51: - ice->num_total_dacs = 8; - ice->num_total_adcs = 2; - break; - case VT1724_SUBDEVICE_AUDIOPHILE192: - ice->num_total_dacs = 2; - ice->num_total_adcs = 2; - break; - default: - snd_BUG(); - return -EINVAL; - } - - /* second stage of initialization, analog parts and others */ - ak = ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL); - if (! ak) - return -ENOMEM; - switch (ice->eeprom.subvendor) { - case VT1724_SUBDEVICE_REVOLUTION71: - ice->akm_codecs = 2; - err = snd_ice1712_akm4xxx_init(ak, &akm_revo_front, - &akm_revo_front_priv, ice); - if (err < 0) - return err; - err = snd_ice1712_akm4xxx_init(ak+1, &akm_revo_surround, - &akm_revo_surround_priv, ice); - if (err < 0) - return err; - /* unmute all codecs */ - snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, - VT1724_REVO_MUTE); - break; - case VT1724_SUBDEVICE_REVOLUTION51: - ice->akm_codecs = 2; - err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, - &akm_revo51_priv, ice); - if (err < 0) - return err; - err = snd_ice1712_akm4xxx_init(ak+1, &akm_revo51_adc, - &akm_revo51_adc_priv, ice); - if (err < 0) - return err; - err = revo51_i2c_init(ice, &ptc_revo51_volume); - if (err < 0) - return err; - /* unmute all codecs */ - snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, - VT1724_REVO_MUTE); - break; - case VT1724_SUBDEVICE_AUDIOPHILE192: - ice->akm_codecs = 1; - err = snd_ice1712_akm4xxx_init(ak, &akm_ap192, &akm_ap192_priv, - ice); - if (err < 0) - return err; - - /* unmute all codecs */ - snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, - VT1724_REVO_MUTE); - break; - } - - return 0; -} - - -static int __devinit revo_add_controls(struct snd_ice1712 *ice) -{ - struct revo51_spec *spec; - int err; - - switch (ice->eeprom.subvendor) { - case VT1724_SUBDEVICE_REVOLUTION71: - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - break; - case VT1724_SUBDEVICE_REVOLUTION51: - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - spec = ice->spec; - err = snd_pt2258_build_controls(spec->pt2258); - if (err < 0) - return err; - break; - case VT1724_SUBDEVICE_AUDIOPHILE192: - err = snd_ice1712_akm4xxx_build_controls(ice); - if (err < 0) - return err; - err = ap192_ak4114_init(ice); - if (err < 0) - return err; - break; - } - return 0; -} - -/* entry point */ -struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_REVOLUTION71, - .name = "M Audio Revolution-7.1", - .model = "revo71", - .chip_init = revo_init, - .build_controls = revo_add_controls, - }, - { - .subvendor = VT1724_SUBDEVICE_REVOLUTION51, - .name = "M Audio Revolution-5.1", - .model = "revo51", - .chip_init = revo_init, - .build_controls = revo_add_controls, - }, - { - .subvendor = VT1724_SUBDEVICE_AUDIOPHILE192, - .name = "M Audio Audiophile192", - .model = "ap192", - .chip_init = revo_init, - .build_controls = revo_add_controls, - }, - { } /* terminator */ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/revo.h b/ANDROID_3.4.5/sound/pci/ice1712/revo.h deleted file mode 100644 index a3ba4259..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/revo.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __SOUND_REVO_H -#define __SOUND_REVO_H - -/* - * ALSA driver for ICEnsemble ICE1712 (Envy24) - * - * Lowlevel functions for M-Audio Revolution 7.1 - * - * Copyright (c) 2003 Takashi Iwai - * - * 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 - * - */ - -#define REVO_DEVICE_DESC \ - "{MidiMan M Audio,Revolution 7.1},"\ - "{MidiMan M Audio,Revolution 5.1},"\ - "{MidiMan M Audio,Audiophile 192}," - -#define VT1724_SUBDEVICE_REVOLUTION71 0x12143036 -#define VT1724_SUBDEVICE_REVOLUTION51 0x12143136 -#define VT1724_SUBDEVICE_AUDIOPHILE192 0x12143236 - -/* entry point */ -extern struct snd_ice1712_card_info snd_vt1724_revo_cards[]; - - -/* - * MidiMan M-Audio Revolution GPIO definitions - */ - -#define VT1724_REVO_CCLK 0x02 -#define VT1724_REVO_CDIN 0x04 /* not used */ -#define VT1724_REVO_CDOUT 0x08 -#define VT1724_REVO_CS0 0x10 /* AK5365 chipselect for (revo51) */ -#define VT1724_REVO_CS1 0x20 /* front AKM4381 chipselect */ -#define VT1724_REVO_CS2 0x40 /* surround AKM4355 CS (revo71) */ -#define VT1724_REVO_I2C_DATA 0x40 /* I2C: PT 2258 SDA (on revo51) */ -#define VT1724_REVO_I2C_CLOCK 0x80 /* I2C: PT 2258 SCL (on revo51) */ -#define VT1724_REVO_CS3 0x80 /* AK4114 for AP192 */ -#define VT1724_REVO_MUTE (1<<22) /* 0 = all mute, 1 = normal operation */ - -#endif /* __SOUND_REVO_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/se.c b/ANDROID_3.4.5/sound/pci/ice1712/se.c deleted file mode 100644 index 69673b95..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/se.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for ONKYO WAVIO SE-90PCI and SE-200PCI - * - * Copyright (c) 2007 Shin-ya Okada sh_okada(at)d4.dion.ne.jp - * (at) -> @ - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include "se.h" - -struct se_spec { - struct { - unsigned char ch1, ch2; - } vol[8]; -}; - -/****************************************************************************/ -/* ONKYO WAVIO SE-200PCI */ -/****************************************************************************/ -/* - * system configuration ICE_EEP2_SYSCONF=0x4b - * XIN1 49.152MHz - * not have UART - * one stereo ADC and a S/PDIF receiver connected - * four stereo DACs connected - * - * AC-Link configuration ICE_EEP2_ACLINK=0x80 - * use I2C, not use AC97 - * - * I2S converters feature ICE_EEP2_I2S=0x78 - * I2S codec has no volume/mute control feature - * I2S codec supports 96KHz and 192KHz - * I2S codec 24bits - * - * S/PDIF configuration ICE_EEP2_SPDIF=0xc3 - * Enable integrated S/PDIF transmitter - * internal S/PDIF out implemented - * S/PDIF is stereo - * External S/PDIF out implemented - * - * - * ** connected chips ** - * - * WM8740 - * A 2ch-DAC of main outputs. - * It setuped as I2S mode by wire, so no way to setup from software. - * The sample-rate are automatically changed. - * ML/I2S (28pin) --------+ - * MC/DM1 (27pin) -- 5V | - * MD/DM0 (26pin) -- GND | - * MUTEB (25pin) -- NC | - * MODE (24pin) -- GND | - * CSBIW (23pin) --------+ - * | - * RSTB (22pin) --R(1K)-+ - * Probably it reduce the noise from the control line. - * - * WM8766 - * A 6ch-DAC for surrounds. - * It's control wire was connected to GPIOxx (3-wire serial interface) - * ML/I2S (11pin) -- GPIO18 - * MC/IWL (12pin) -- GPIO17 - * MD/DM (13pin) -- GPIO16 - * MUTE (14pin) -- GPIO01 - * - * WM8776 - * A 2ch-ADC(with 10ch-selector) plus 2ch-DAC. - * It's control wire was connected to SDA/SCLK (2-wire serial interface) - * MODE (16pin) -- R(1K) -- GND - * CE (17pin) -- R(1K) -- GND 2-wire mode (address=0x34) - * DI (18pin) -- SDA - * CL (19pin) -- SCLK - * - * - * ** output pins and device names ** - * - * 7.1ch name -- output connector color -- device (-D option) - * - * FRONT 2ch -- green -- plughw:0,0 - * CENTER(Lch) SUBWOOFER(Rch) -- black -- plughw:0,2,0 - * SURROUND 2ch -- orange -- plughw:0,2,1 - * SURROUND BACK 2ch -- white -- plughw:0,2,2 - * - */ - - -/****************************************************************************/ -/* WM8740 interface */ -/****************************************************************************/ - -static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice) -{ - /* nothing to do */ -} - - -static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice, - unsigned int rate) -{ - /* nothing to do */ -} - - -/****************************************************************************/ -/* WM8766 interface */ -/****************************************************************************/ - -static void se200pci_WM8766_write(struct snd_ice1712 *ice, - unsigned int addr, unsigned int data) -{ - unsigned int st; - unsigned int bits; - int i; - const unsigned int DATA = 0x010000; - const unsigned int CLOCK = 0x020000; - const unsigned int LOAD = 0x040000; - const unsigned int ALL_MASK = (DATA | CLOCK | LOAD); - - snd_ice1712_save_gpio_status(ice); - - st = ((addr & 0x7f) << 9) | (data & 0x1ff); - snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK); - snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK); - bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK; - - snd_ice1712_gpio_write(ice, bits); - for (i = 0; i < 16; i++) { - udelay(1); - bits &= ~CLOCK; - st = (st << 1); - if (st & 0x10000) - bits |= DATA; - else - bits &= ~DATA; - - snd_ice1712_gpio_write(ice, bits); - - udelay(1); - bits |= CLOCK; - snd_ice1712_gpio_write(ice, bits); - } - - udelay(1); - bits |= LOAD; - snd_ice1712_gpio_write(ice, bits); - - udelay(1); - bits |= (DATA | CLOCK); - snd_ice1712_gpio_write(ice, bits); - - snd_ice1712_restore_gpio_status(ice); -} - -static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch, - unsigned int vol1, unsigned int vol2) -{ - switch (ch) { - case 0: - se200pci_WM8766_write(ice, 0x000, vol1); - se200pci_WM8766_write(ice, 0x001, vol2 | 0x100); - break; - case 1: - se200pci_WM8766_write(ice, 0x004, vol1); - se200pci_WM8766_write(ice, 0x005, vol2 | 0x100); - break; - case 2: - se200pci_WM8766_write(ice, 0x006, vol1); - se200pci_WM8766_write(ice, 0x007, vol2 | 0x100); - break; - } -} - -static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice) -{ - se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */ - udelay(10); - - se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */ - se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */ - se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */ - - se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */ - se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */ - se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */ - se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */ - se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */ - - se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */ - se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */ -} - -static void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice, - unsigned int rate) -{ - if (rate > 96000) - se200pci_WM8766_write(ice, 0x0a, 0x000); /* MCLK=128fs */ - else - se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */ -} - - -/****************************************************************************/ -/* WM8776 interface */ -/****************************************************************************/ - -static void se200pci_WM8776_write(struct snd_ice1712 *ice, - unsigned int addr, unsigned int data) -{ - unsigned int val; - - val = (addr << 9) | data; - snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff); -} - - -static void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice, - unsigned int vol1, unsigned int vol2) -{ - se200pci_WM8776_write(ice, 0x03, vol1); - se200pci_WM8776_write(ice, 0x04, vol2 | 0x100); -} - -static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice, - unsigned int vol1, unsigned int vol2) -{ - se200pci_WM8776_write(ice, 0x0e, vol1); - se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100); -} - -static const char *se200pci_sel[] = { - "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL -}; - -static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice, - unsigned int sel) -{ - static unsigned char vals[] = { - /* LINE, CD, MIC, ALL, GND */ - 0x10, 0x04, 0x08, 0x1c, 0x03 - }; - if (sel > 4) - sel = 4; - se200pci_WM8776_write(ice, 0x15, vals[sel]); -} - -static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl) -{ - /* AFL -- After Fader Listening */ - if (afl) - se200pci_WM8776_write(ice, 0x16, 0x005); - else - se200pci_WM8776_write(ice, 0x16, 0x001); -} - -static const char *se200pci_agc[] = { - "Off", "LimiterMode", "ALCMode", NULL -}; - -static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc) -{ - /* AGC -- Auto Gain Control of the input */ - switch (agc) { - case 0: - se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */ - break; - case 1: - se200pci_WM8776_write(ice, 0x10, 0x07b); - se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */ - break; - case 2: - se200pci_WM8776_write(ice, 0x10, 0x1fb); - se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */ - break; - } -} - -static void __devinit se200pci_WM8776_init(struct snd_ice1712 *ice) -{ - int i; - static unsigned short __devinitdata default_values[] = { - 0x100, 0x100, 0x100, - 0x100, 0x100, 0x100, - 0x000, 0x090, 0x000, 0x000, - 0x022, 0x022, 0x022, - 0x008, 0x0cf, 0x0cf, 0x07b, 0x000, - 0x032, 0x000, 0x0a6, 0x001, 0x001 - }; - - se200pci_WM8776_write(ice, 0x17, 0x000); /* reset all */ - /* ADC and DAC interface is I2S 24bits mode */ - /* The sample-rate are automatically changed */ - udelay(10); - /* BUT my board can not do reset all, so I load all by manually. */ - for (i = 0; i < ARRAY_SIZE(default_values); i++) - se200pci_WM8776_write(ice, i, default_values[i]); - - se200pci_WM8776_set_input_selector(ice, 0); - se200pci_WM8776_set_afl(ice, 0); - se200pci_WM8776_set_agc(ice, 0); - se200pci_WM8776_set_input_volume(ice, 0, 0); - se200pci_WM8776_set_output_volume(ice, 0, 0); - - /* head phone mute and power down */ - se200pci_WM8776_write(ice, 0x00, 0); - se200pci_WM8776_write(ice, 0x01, 0); - se200pci_WM8776_write(ice, 0x02, 0x100); - se200pci_WM8776_write(ice, 0x0d, 0x080); -} - -static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice, - unsigned int rate) -{ - /* nothing to do */ -} - - -/****************************************************************************/ -/* runtime interface */ -/****************************************************************************/ - -static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate) -{ - se200pci_WM8740_set_pro_rate(ice, rate); - se200pci_WM8766_set_pro_rate(ice, rate); - se200pci_WM8776_set_pro_rate(ice, rate); -} - -struct se200pci_control { - char *name; - enum { - WM8766, - WM8776in, - WM8776out, - WM8776sel, - WM8776agc, - WM8776afl - } target; - enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type; - int ch; - const char **member; - const char *comment; -}; - -static const struct se200pci_control se200pci_cont[] = { - { - .name = "Front Playback Volume", - .target = WM8776out, - .type = VOLUME1, - .comment = "Front(green)" - }, - { - .name = "Side Playback Volume", - .target = WM8766, - .type = VOLUME1, - .ch = 1, - .comment = "Surround(orange)" - }, - { - .name = "Surround Playback Volume", - .target = WM8766, - .type = VOLUME1, - .ch = 2, - .comment = "SurroundBack(white)" - }, - { - .name = "CLFE Playback Volume", - .target = WM8766, - .type = VOLUME1, - .ch = 0, - .comment = "Center(Lch)&SubWoofer(Rch)(black)" - }, - { - .name = "Capture Volume", - .target = WM8776in, - .type = VOLUME2 - }, - { - .name = "Capture Select", - .target = WM8776sel, - .type = ENUM, - .member = se200pci_sel - }, - { - .name = "AGC Capture Mode", - .target = WM8776agc, - .type = ENUM, - .member = se200pci_agc - }, - { - .name = "AFL Bypass Playback Switch", - .target = WM8776afl, - .type = BOOLEAN - } -}; - -static int se200pci_get_enum_count(int n) -{ - const char **member; - int c; - - member = se200pci_cont[n].member; - if (!member) - return 0; - for (c = 0; member[c]; c++) - ; - return c; -} - -static int se200pci_cont_volume_info(struct snd_kcontrol *kc, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* mute */ - uinfo->value.integer.max = 0xff; /* 0dB */ - return 0; -} - -#define se200pci_cont_boolean_info snd_ctl_boolean_mono_info - -static int se200pci_cont_enum_info(struct snd_kcontrol *kc, - struct snd_ctl_elem_info *uinfo) -{ - int n, c; - - n = kc->private_value; - c = se200pci_get_enum_count(n); - if (!c) - return -EINVAL; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = c; - if (uinfo->value.enumerated.item >= c) - uinfo->value.enumerated.item = c - 1; - strcpy(uinfo->value.enumerated.name, - se200pci_cont[n].member[uinfo->value.enumerated.item]); - return 0; -} - -static int se200pci_cont_volume_get(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *uc) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kc); - struct se_spec *spec = ice->spec; - int n = kc->private_value; - uc->value.integer.value[0] = spec->vol[n].ch1; - uc->value.integer.value[1] = spec->vol[n].ch2; - return 0; -} - -static int se200pci_cont_boolean_get(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *uc) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kc); - struct se_spec *spec = ice->spec; - int n = kc->private_value; - uc->value.integer.value[0] = spec->vol[n].ch1; - return 0; -} - -static int se200pci_cont_enum_get(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *uc) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kc); - struct se_spec *spec = ice->spec; - int n = kc->private_value; - uc->value.enumerated.item[0] = spec->vol[n].ch1; - return 0; -} - -static void se200pci_cont_update(struct snd_ice1712 *ice, int n) -{ - struct se_spec *spec = ice->spec; - switch (se200pci_cont[n].target) { - case WM8766: - se200pci_WM8766_set_volume(ice, - se200pci_cont[n].ch, - spec->vol[n].ch1, - spec->vol[n].ch2); - break; - - case WM8776in: - se200pci_WM8776_set_input_volume(ice, - spec->vol[n].ch1, - spec->vol[n].ch2); - break; - - case WM8776out: - se200pci_WM8776_set_output_volume(ice, - spec->vol[n].ch1, - spec->vol[n].ch2); - break; - - case WM8776sel: - se200pci_WM8776_set_input_selector(ice, - spec->vol[n].ch1); - break; - - case WM8776agc: - se200pci_WM8776_set_agc(ice, spec->vol[n].ch1); - break; - - case WM8776afl: - se200pci_WM8776_set_afl(ice, spec->vol[n].ch1); - break; - - default: - break; - } -} - -static int se200pci_cont_volume_put(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *uc) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kc); - struct se_spec *spec = ice->spec; - int n = kc->private_value; - unsigned int vol1, vol2; - int changed; - - changed = 0; - vol1 = uc->value.integer.value[0] & 0xff; - vol2 = uc->value.integer.value[1] & 0xff; - if (spec->vol[n].ch1 != vol1) { - spec->vol[n].ch1 = vol1; - changed = 1; - } - if (spec->vol[n].ch2 != vol2) { - spec->vol[n].ch2 = vol2; - changed = 1; - } - if (changed) - se200pci_cont_update(ice, n); - - return changed; -} - -static int se200pci_cont_boolean_put(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *uc) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kc); - struct se_spec *spec = ice->spec; - int n = kc->private_value; - unsigned int vol1; - - vol1 = !!uc->value.integer.value[0]; - if (spec->vol[n].ch1 != vol1) { - spec->vol[n].ch1 = vol1; - se200pci_cont_update(ice, n); - return 1; - } - return 0; -} - -static int se200pci_cont_enum_put(struct snd_kcontrol *kc, - struct snd_ctl_elem_value *uc) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kc); - struct se_spec *spec = ice->spec; - int n = kc->private_value; - unsigned int vol1; - - vol1 = uc->value.enumerated.item[0]; - if (vol1 >= se200pci_get_enum_count(n)) - return -EINVAL; - if (spec->vol[n].ch1 != vol1) { - spec->vol[n].ch1 = vol1; - se200pci_cont_update(ice, n); - return 1; - } - return 0; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1); - -static int __devinit se200pci_add_controls(struct snd_ice1712 *ice) -{ - int i; - struct snd_kcontrol_new cont; - int err; - - memset(&cont, 0, sizeof(cont)); - cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) { - cont.private_value = i; - cont.name = se200pci_cont[i].name; - cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; - cont.tlv.p = NULL; - switch (se200pci_cont[i].type) { - case VOLUME1: - case VOLUME2: - cont.info = se200pci_cont_volume_info; - cont.get = se200pci_cont_volume_get; - cont.put = se200pci_cont_volume_put; - cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - if (se200pci_cont[i].type == VOLUME1) - cont.tlv.p = db_scale_gain1; - else - cont.tlv.p = db_scale_gain2; - break; - case BOOLEAN: - cont.info = se200pci_cont_boolean_info; - cont.get = se200pci_cont_boolean_get; - cont.put = se200pci_cont_boolean_put; - break; - case ENUM: - cont.info = se200pci_cont_enum_info; - cont.get = se200pci_cont_enum_get; - cont.put = se200pci_cont_enum_put; - break; - default: - snd_BUG(); - return -EINVAL; - } - err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice)); - if (err < 0) - return err; - } - - return 0; -} - - -/****************************************************************************/ -/* ONKYO WAVIO SE-90PCI */ -/****************************************************************************/ -/* - * system configuration ICE_EEP2_SYSCONF=0x4b - * AC-Link configuration ICE_EEP2_ACLINK=0x80 - * I2S converters feature ICE_EEP2_I2S=0x78 - * S/PDIF configuration ICE_EEP2_SPDIF=0xc3 - * - * ** connected chip ** - * - * WM8716 - * A 2ch-DAC of main outputs. - * It setuped as I2S mode by wire, so no way to setup from software. - * ML/I2S (28pin) -- +5V - * MC/DM1 (27pin) -- GND - * MC/DM0 (26pin) -- GND - * MUTEB (25pin) -- open (internal pull-up) - * MODE (24pin) -- GND - * CSBIWO (23pin) -- +5V - * - */ - - /* Nothing to do for this chip. */ - - -/****************************************************************************/ -/* probe/initialize/setup */ -/****************************************************************************/ - -static int __devinit se_init(struct snd_ice1712 *ice) -{ - struct se_spec *spec; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) - return -ENOMEM; - ice->spec = spec; - - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) { - ice->num_total_dacs = 2; - ice->num_total_adcs = 0; - ice->vt1720 = 1; - return 0; - - } else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) { - ice->num_total_dacs = 8; - ice->num_total_adcs = 2; - se200pci_WM8740_init(ice); - se200pci_WM8766_init(ice); - se200pci_WM8776_init(ice); - ice->gpio.set_pro_rate = se200pci_set_pro_rate; - return 0; - } - - return -ENOENT; -} - -static int __devinit se_add_controls(struct snd_ice1712 *ice) -{ - int err; - - err = 0; - /* nothing to do for VT1724_SUBDEVICE_SE90PCI */ - if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) - err = se200pci_add_controls(ice); - - return err; -} - - -/****************************************************************************/ -/* entry point */ -/****************************************************************************/ - -static unsigned char se200pci_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - - [ICE_EEP2_GPIO_DIR] = 0x02, /* WM8766 mute 1=output */ - [ICE_EEP2_GPIO_DIR1] = 0x00, /* not used */ - [ICE_EEP2_GPIO_DIR2] = 0x07, /* WM8766 ML/MC/MD 1=output */ - - [ICE_EEP2_GPIO_MASK] = 0x00, /* 0=writable */ - [ICE_EEP2_GPIO_MASK1] = 0x00, /* 0=writable */ - [ICE_EEP2_GPIO_MASK2] = 0x00, /* 0=writable */ - - [ICE_EEP2_GPIO_STATE] = 0x00, /* WM8766 mute=0 */ - [ICE_EEP2_GPIO_STATE1] = 0x00, /* not used */ - [ICE_EEP2_GPIO_STATE2] = 0x07, /* WM8766 ML/MC/MD */ -}; - -static unsigned char se90pci_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */ - [ICE_EEP2_ACLINK] = 0x80, /* I2S */ - [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */ - [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ - - /* ALL GPIO bits are in input mode */ -}; - -struct snd_ice1712_card_info snd_vt1724_se_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_SE200PCI, - .name = "ONKYO SE200PCI", - .model = "se200pci", - .chip_init = se_init, - .build_controls = se_add_controls, - .eeprom_size = sizeof(se200pci_eeprom), - .eeprom_data = se200pci_eeprom, - }, - { - .subvendor = VT1724_SUBDEVICE_SE90PCI, - .name = "ONKYO SE90PCI", - .model = "se90pci", - .chip_init = se_init, - .build_controls = se_add_controls, - .eeprom_size = sizeof(se90pci_eeprom), - .eeprom_data = se90pci_eeprom, - }, - {} /*terminator*/ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/se.h b/ANDROID_3.4.5/sound/pci/ice1712/se.h deleted file mode 100644 index 0b0a9dab..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/se.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __SOUND_SE_H -#define __SOUND_SE_H - -/* ID */ -#define SE_DEVICE_DESC \ - "{ONKYO INC,SE-90PCI},"\ - "{ONKYO INC,SE-200PCI}," - -#define VT1724_SUBDEVICE_SE90PCI 0xb161000 -#define VT1724_SUBDEVICE_SE200PCI 0xb160100 - -/* entry struct */ -extern struct snd_ice1712_card_info snd_vt1724_se_cards[]; - -#endif /* __SOUND_SE_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/stac946x.h b/ANDROID_3.4.5/sound/pci/ice1712/stac946x.h deleted file mode 100644 index 5b390952..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/stac946x.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __SOUND_STAC946X_H -#define __SOUND_STAC946X_H - -#define STAC946X_RESET 0x00 -#define STAC946X_STATUS 0x01 -#define STAC946X_MASTER_VOLUME 0x02 -#define STAC946X_LF_VOLUME 0x03 -#define STAC946X_RF_VOLUME 0x04 -#define STAC946X_LR_VOLUME 0x05 -#define STAC946X_RR_VOLUME 0x06 -#define STAC946X_CENTER_VOLUME 0x07 -#define STAC946X_LFE_VOLUME 0x08 -#define STAC946X_MIC_L_VOLUME 0x09 -#define STAC946X_MIC_R_VOLUME 0x0a -#define STAC946X_DEEMPHASIS 0x0c -#define STAC946X_GENERAL_PURPOSE 0x0d -#define STAC946X_AUDIO_PORT_CONTROL 0x0e -#define STAC946X_MASTER_CLOCKING 0x0f -#define STAC946X_POWERDOWN_CTRL1 0x10 -#define STAC946X_POWERDOWN_CTRL2 0x11 -#define STAC946X_REVISION_CODE 0x12 -#define STAC946X_ADDRESS_CONTROL 0x13 -#define STAC946X_ADDRESS 0x14 - -#endif /* __SOUND_STAC946X_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.c b/ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.c deleted file mode 100644 index 4c551e14..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT) - * - * Lowlevel functions for VT1720-based motherboards - * - * Copyright (c) 2004 Takashi Iwai - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include "vt1720_mobo.h" - - -static int __devinit k8x800_init(struct snd_ice1712 *ice) -{ - ice->vt1720 = 1; - - /* VT1616 codec */ - ice->num_total_dacs = 6; - ice->num_total_adcs = 2; - - /* WM8728 codec */ - /* FIXME: TODO */ - - return 0; -} - -static int __devinit k8x800_add_controls(struct snd_ice1712 *ice) -{ - /* FIXME: needs some quirks for VT1616? */ - return 0; -} - -/* EEPROM image */ - -static unsigned char k8x800_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x01, /* clock 256, 1ADC, 2DACs */ - [ICE_EEP2_ACLINK] = 0x02, /* ACLINK, packed */ - [ICE_EEP2_I2S] = 0x00, /* - */ - [ICE_EEP2_SPDIF] = 0x00, /* - */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0x00, /* - */ - [ICE_EEP2_GPIO_MASK] = 0xff, - [ICE_EEP2_GPIO_MASK1] = 0xff, - [ICE_EEP2_GPIO_MASK2] = 0x00, /* - */ - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, /* - */ -}; - -static unsigned char sn25p_eeprom[] __devinitdata = { - [ICE_EEP2_SYSCONF] = 0x01, /* clock 256, 1ADC, 2DACs */ - [ICE_EEP2_ACLINK] = 0x02, /* ACLINK, packed */ - [ICE_EEP2_I2S] = 0x00, /* - */ - [ICE_EEP2_SPDIF] = 0x41, /* - */ - [ICE_EEP2_GPIO_DIR] = 0xff, - [ICE_EEP2_GPIO_DIR1] = 0xff, - [ICE_EEP2_GPIO_DIR2] = 0x00, /* - */ - [ICE_EEP2_GPIO_MASK] = 0xff, - [ICE_EEP2_GPIO_MASK1] = 0xff, - [ICE_EEP2_GPIO_MASK2] = 0x00, /* - */ - [ICE_EEP2_GPIO_STATE] = 0x00, - [ICE_EEP2_GPIO_STATE1] = 0x00, - [ICE_EEP2_GPIO_STATE2] = 0x00, /* - */ -}; - - -/* entry point */ -struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { - { - .subvendor = VT1720_SUBDEVICE_K8X800, - .name = "Albatron K8X800 Pro II", - .model = "k8x800", - .chip_init = k8x800_init, - .build_controls = k8x800_add_controls, - .eeprom_size = sizeof(k8x800_eeprom), - .eeprom_data = k8x800_eeprom, - }, - { - .subvendor = VT1720_SUBDEVICE_ZNF3_150, - .name = "Chaintech ZNF3-150", - /* identical with k8x800 */ - .chip_init = k8x800_init, - .build_controls = k8x800_add_controls, - .eeprom_size = sizeof(k8x800_eeprom), - .eeprom_data = k8x800_eeprom, - }, - { - .subvendor = VT1720_SUBDEVICE_ZNF3_250, - .name = "Chaintech ZNF3-250", - /* identical with k8x800 */ - .chip_init = k8x800_init, - .build_controls = k8x800_add_controls, - .eeprom_size = sizeof(k8x800_eeprom), - .eeprom_data = k8x800_eeprom, - }, - { - .subvendor = VT1720_SUBDEVICE_9CJS, - .name = "Chaintech 9CJS", - /* identical with k8x800 */ - .chip_init = k8x800_init, - .build_controls = k8x800_add_controls, - .eeprom_size = sizeof(k8x800_eeprom), - .eeprom_data = k8x800_eeprom, - }, - { - .subvendor = VT1720_SUBDEVICE_SN25P, - .name = "Shuttle SN25P", - .model = "sn25p", - .chip_init = k8x800_init, - .build_controls = k8x800_add_controls, - .eeprom_size = sizeof(k8x800_eeprom), - .eeprom_data = sn25p_eeprom, - }, - { } /* terminator */ -}; - diff --git a/ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.h b/ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.h deleted file mode 100644 index 0b1b0ee1..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/vt1720_mobo.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __SOUND_VT1720_MOBO_H -#define __SOUND_VT1720_MOBO_H - -/* - * ALSA driver for VT1720/VT1724 (Envy24PT/Envy24HT) - * - * Lowlevel functions for VT1720-based motherboards - * - * Copyright (c) 2004 Takashi Iwai - * - * 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 - * - */ - -#define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\ - "{Chaintech,ZNF3-150},"\ - "{Chaintech,ZNF3-250},"\ - "{Chaintech,9CJS},"\ - "{Shuttle,SN25P}," - -#define VT1720_SUBDEVICE_K8X800 0xf217052c -#define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6 -#define VT1720_SUBDEVICE_ZNF3_250 0x0f2745f6 -#define VT1720_SUBDEVICE_9CJS 0x0f272327 -#define VT1720_SUBDEVICE_SN25P 0x97123650 - -extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; - -#endif /* __SOUND_VT1720_MOBO_H */ diff --git a/ANDROID_3.4.5/sound/pci/ice1712/wtm.c b/ANDROID_3.4.5/sound/pci/ice1712/wtm.c deleted file mode 100644 index e618f789..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/wtm.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * ALSA driver for ICEnsemble VT1724 (Envy24HT) - * - * Lowlevel functions for Ego Sys Waveterminal 192M - * - * Copyright (c) 2006 Guedez Clement - * Some functions are taken from the Prodigy192 driver - * source - * - * 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 "ice1712.h" -#include "envy24ht.h" -#include "wtm.h" -#include "stac946x.h" - - -/* - * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus - */ -static inline void stac9460_put(struct snd_ice1712 *ice, int reg, - unsigned char val) -{ - snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val); -} - -static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg) -{ - return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg); -} - -/* - * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus - */ -static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg, - unsigned char val) -{ - snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val); -} - -static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg) -{ - return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg); -} - - -/* - * DAC mute control - */ -#define stac9460_dac_mute_info snd_ctl_boolean_mono_info - -static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val; - int idx, id; - - if (kcontrol->private_value) { - idx = STAC946X_MASTER_VOLUME; - id = 0; - } else { - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - idx = id + STAC946X_LF_VOLUME; - } - if (id < 6) - val = stac9460_get(ice, idx); - else - val = stac9460_2_get(ice, idx - 6); - ucontrol->value.integer.value[0] = (~val >> 7) & 0x1; - return 0; -} - -static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char new, old; - int id, idx; - int change; - - if (kcontrol->private_value) { - idx = STAC946X_MASTER_VOLUME; - old = stac9460_get(ice, idx); - new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | - (old & ~0x80); - change = (new != old); - if (change) { - stac9460_put(ice, idx, new); - stac9460_2_put(ice, idx, new); - } - } else { - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - idx = id + STAC946X_LF_VOLUME; - if (id < 6) - old = stac9460_get(ice, idx); - else - old = stac9460_2_get(ice, idx - 6); - new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | - (old & ~0x80); - change = (new != old); - if (change) { - if (id < 6) - stac9460_put(ice, idx, new); - else - stac9460_2_put(ice, idx - 6, new); - } - } - return change; -} - -/* - * DAC volume attenuation mixer control - */ -static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; /* mute */ - uinfo->value.integer.max = 0x7f; /* 0dB */ - return 0; -} - -static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx, id; - unsigned char vol; - - if (kcontrol->private_value) { - idx = STAC946X_MASTER_VOLUME; - id = 0; - } else { - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - idx = id + STAC946X_LF_VOLUME; - } - if (id < 6) - vol = stac9460_get(ice, idx) & 0x7f; - else - vol = stac9460_2_get(ice, idx - 6) & 0x7f; - ucontrol->value.integer.value[0] = 0x7f - vol; - return 0; -} - -static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int idx, id; - unsigned char tmp, ovol, nvol; - int change; - - if (kcontrol->private_value) { - idx = STAC946X_MASTER_VOLUME; - nvol = ucontrol->value.integer.value[0] & 0x7f; - tmp = stac9460_get(ice, idx); - ovol = 0x7f - (tmp & 0x7f); - change = (ovol != nvol); - if (change) { - stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); - stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80)); - } - } else { - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - idx = id + STAC946X_LF_VOLUME; - nvol = ucontrol->value.integer.value[0] & 0x7f; - if (id < 6) - tmp = stac9460_get(ice, idx); - else - tmp = stac9460_2_get(ice, idx - 6); - ovol = 0x7f - (tmp & 0x7f); - change = (ovol != nvol); - if (change) { - if (id < 6) - stac9460_put(ice, idx, (0x7f - nvol) | - (tmp & 0x80)); - else - stac9460_2_put(ice, idx-6, (0x7f - nvol) | - (tmp & 0x80)); - } - } - return change; -} - -/* - * ADC mute control - */ -#define stac9460_adc_mute_info snd_ctl_boolean_stereo_info - -static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val; - int i, id; - - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - if (id == 0) { - for (i = 0; i < 2; ++i) { - val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i); - ucontrol->value.integer.value[i] = ~val>>7 & 0x1; - } - } else { - for (i = 0; i < 2; ++i) { - val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i); - ucontrol->value.integer.value[i] = ~val>>7 & 0x1; - } - } - return 0; -} - -static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char new, old; - int i, reg, id; - int change; - - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - if (id == 0) { - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - old = stac9460_get(ice, reg); - new = (~ucontrol->value.integer.value[i]<<7&0x80) | - (old&~0x80); - change = (new != old); - if (change) - stac9460_put(ice, reg, new); - } - } else { - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - old = stac9460_2_get(ice, reg); - new = (~ucontrol->value.integer.value[i]<<7&0x80) | - (old&~0x80); - change = (new != old); - if (change) - stac9460_2_put(ice, reg, new); - } - } - return change; -} - -/* - *ADC gain mixer control - */ -static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; /* 0dB */ - uinfo->value.integer.max = 0x0f; /* 22.5dB */ - return 0; -} - -static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int i, reg, id; - unsigned char vol; - - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - if (id == 0) { - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - vol = stac9460_get(ice, reg) & 0x0f; - ucontrol->value.integer.value[i] = 0x0f - vol; - } - } else { - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - vol = stac9460_2_get(ice, reg) & 0x0f; - ucontrol->value.integer.value[i] = 0x0f - vol; - } - } - return 0; -} - -static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - int i, reg, id; - unsigned char ovol, nvol; - int change; - - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - if (id == 0) { - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - nvol = ucontrol->value.integer.value[i] & 0x0f; - ovol = 0x0f - stac9460_get(ice, reg); - change = ((ovol & 0x0f) != nvol); - if (change) - stac9460_put(ice, reg, (0x0f - nvol) | - (ovol & ~0x0f)); - } - } else { - for (i = 0; i < 2; ++i) { - reg = STAC946X_MIC_L_VOLUME + i; - nvol = ucontrol->value.integer.value[i] & 0x0f; - ovol = 0x0f - stac9460_2_get(ice, reg); - change = ((ovol & 0x0f) != nvol); - if (change) - stac9460_2_put(ice, reg, (0x0f - nvol) | - (ovol & ~0x0f)); - } - } - return change; -} - -/* - * MIC / LINE switch fonction - */ - -#define stac9460_mic_sw_info snd_ctl_boolean_mono_info - -static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char val; - int id; - - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - if (id == 0) - val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); - else - val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); - ucontrol->value.integer.value[0] = ~val>>7 & 0x1; - return 0; -} - -static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); - unsigned char new, old; - int change, id; - - id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - if (id == 0) - old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE); - else - old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE); - new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | (old & ~0x80); - change = (new != old); - if (change) { - if (id == 0) - stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new); - else - stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new); - } - return change; -} - -/* - * Control tabs - */ -static struct snd_kcontrol_new stac9640_controls[] __devinitdata = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = stac9460_dac_mute_info, - .get = stac9460_dac_mute_get, - .put = stac9460_dac_mute_put, - .private_value = 1 - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = stac9460_dac_vol_info, - .get = stac9460_dac_vol_get, - .put = stac9460_dac_vol_put, - .private_value = 1, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "MIC/Line switch", - .count = 2, - .info = stac9460_mic_sw_info, - .get = stac9460_mic_sw_get, - .put = stac9460_mic_sw_put, - - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Switch", - .count = 8, - .info = stac9460_dac_mute_info, - .get = stac9460_dac_mute_get, - .put = stac9460_dac_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Volume", - .count = 8, - .info = stac9460_dac_vol_info, - .get = stac9460_dac_vol_get, - .put = stac9460_dac_vol_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Switch", - .count = 2, - .info = stac9460_adc_mute_info, - .get = stac9460_adc_mute_get, - .put = stac9460_adc_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Volume", - .count = 2, - .info = stac9460_adc_vol_info, - .get = stac9460_adc_vol_get, - .put = stac9460_adc_vol_put, - - } -}; - - - -/*INIT*/ -static int __devinit wtm_add_controls(struct snd_ice1712 *ice) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) { - err = snd_ctl_add(ice->card, - snd_ctl_new1(&stac9640_controls[i], ice)); - if (err < 0) - return err; - } - return 0; -} - -static int __devinit wtm_init(struct snd_ice1712 *ice) -{ - static unsigned short stac_inits_prodigy[] = { - STAC946X_RESET, 0, - (unsigned short)-1 - }; - unsigned short *p; - - /*WTM 192M*/ - ice->num_total_dacs = 8; - ice->num_total_adcs = 4; - ice->force_rdma1 = 1; - - /*initialize codec*/ - p = stac_inits_prodigy; - for (; *p != (unsigned short)-1; p += 2) { - stac9460_put(ice, p[0], p[1]); - stac9460_2_put(ice, p[0], p[1]); - } - return 0; -} - - -static unsigned char wtm_eeprom[] __devinitdata = { - 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */ - 0x80, /* ACLINK : I2S */ - 0xf8, /* I2S: vol; 96k, 24bit, 192k */ - 0xc1 /*SPDIF: out-en, spidf ext out*/, - 0x9f, /* GPIO_DIR */ - 0xff, /* GPIO_DIR1 */ - 0x7f, /* GPIO_DIR2 */ - 0x9f, /* GPIO_MASK */ - 0xff, /* GPIO_MASK1 */ - 0x7f, /* GPIO_MASK2 */ - 0x16, /* GPIO_STATE */ - 0x80, /* GPIO_STATE1 */ - 0x00, /* GPIO_STATE2 */ -}; - - -/*entry point*/ -struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = { - { - .subvendor = VT1724_SUBDEVICE_WTM, - .name = "ESI Waveterminal 192M", - .model = "WT192M", - .chip_init = wtm_init, - .build_controls = wtm_add_controls, - .eeprom_size = sizeof(wtm_eeprom), - .eeprom_data = wtm_eeprom, - }, - {} /*terminator*/ -}; diff --git a/ANDROID_3.4.5/sound/pci/ice1712/wtm.h b/ANDROID_3.4.5/sound/pci/ice1712/wtm.h deleted file mode 100644 index 423c1a20..00000000 --- a/ANDROID_3.4.5/sound/pci/ice1712/wtm.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __SOUND_WTM_H -#define __SOUND_WTM_H - -/* ID */ -#define WTM_DEVICE_DESC "{EGO SYS INC,WaveTerminal 192M}," -#define VT1724_SUBDEVICE_WTM 0x36495345 /* WT192M ver1.0 */ - -/* - *chip addresses on I2C bus - */ - -#define AK4114_ADDR 0x20 /*S/PDIF receiver*/ -#define STAC9460_I2C_ADDR 0x54 /* ADC*2 | DAC*6 */ -#define STAC9460_2_I2C_ADDR 0x56 /* ADC|DAC *2 */ - - -extern struct snd_ice1712_card_info snd_vt1724_wtm_cards[]; - -#endif /* __SOUND_WTM_H */ - diff --git a/ANDROID_3.4.5/sound/pci/intel8x0.c b/ANDROID_3.4.5/sound/pci/intel8x0.c deleted file mode 100644 index e0a4263b..00000000 --- a/ANDROID_3.4.5/sound/pci/intel8x0.c +++ /dev/null @@ -1,3364 +0,0 @@ -/* - * ALSA driver for Intel ICH (i8x0) chipsets - * - * Copyright (c) 2000 Jaroslav Kysela - * - * - * This code also contains alpha support for SiS 735 chipsets provided - * by Mike Pieper . We have no datasheet - * for SiS735, so the code is not fully functional. - * - * - * 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 -#include -#include -#include -/* for 440MX workaround */ -#include -#include - -#ifdef CONFIG_KVM_GUEST -#include -#else -#define kvm_para_available() (0) -#endif - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," - "{Intel,82901AB-ICH0}," - "{Intel,82801BA-ICH2}," - "{Intel,82801CA-ICH3}," - "{Intel,82801DB-ICH4}," - "{Intel,ICH5}," - "{Intel,ICH6}," - "{Intel,ICH7}," - "{Intel,6300ESB}," - "{Intel,ESB2}," - "{Intel,MX440}," - "{SiS,SI7012}," - "{NVidia,nForce Audio}," - "{NVidia,nForce2 Audio}," - "{NVidia,nForce3 Audio}," - "{NVidia,MCP04}," - "{NVidia,MCP501}," - "{NVidia,CK804}," - "{NVidia,CK8}," - "{NVidia,CK8S}," - "{AMD,AMD768}," - "{AMD,AMD8111}," - "{ALI,M5455}}"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int ac97_clock; -static char *ac97_quirk; -static bool buggy_semaphore; -static int buggy_irq = -1; /* auto-check */ -static bool xbox; -static int spdif_aclink = -1; -static int inside_vm = -1; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard."); -module_param(ac97_clock, int, 0444); -MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = whitelist + auto-detect, 1 = force autodetect)."); -module_param(ac97_quirk, charp, 0444); -MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); -module_param(buggy_semaphore, bool, 0444); -MODULE_PARM_DESC(buggy_semaphore, "Enable workaround for hardwares with problematic codec semaphores."); -module_param(buggy_irq, bint, 0444); -MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); -module_param(xbox, bool, 0444); -MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); -module_param(spdif_aclink, int, 0444); -MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); -module_param(inside_vm, bint, 0444); -MODULE_PARM_DESC(inside_vm, "KVM/Parallels optimization."); - -/* just for backward compatibility */ -static bool enable; -module_param(enable, bool, 0444); -static int joystick; -module_param(joystick, int, 0444); - -/* - * Direct registers - */ -enum { DEVICE_INTEL, DEVICE_INTEL_ICH4, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE }; - -#define ICHREG(x) ICH_REG_##x - -#define DEFINE_REGSET(name,base) \ -enum { \ - ICH_REG_##name##_BDBAR = base + 0x0, /* dword - buffer descriptor list base address */ \ - ICH_REG_##name##_CIV = base + 0x04, /* byte - current index value */ \ - ICH_REG_##name##_LVI = base + 0x05, /* byte - last valid index */ \ - ICH_REG_##name##_SR = base + 0x06, /* byte - status register */ \ - ICH_REG_##name##_PICB = base + 0x08, /* word - position in current buffer */ \ - ICH_REG_##name##_PIV = base + 0x0a, /* byte - prefetched index value */ \ - ICH_REG_##name##_CR = base + 0x0b, /* byte - control register */ \ -}; - -/* busmaster blocks */ -DEFINE_REGSET(OFF, 0); /* offset */ -DEFINE_REGSET(PI, 0x00); /* PCM in */ -DEFINE_REGSET(PO, 0x10); /* PCM out */ -DEFINE_REGSET(MC, 0x20); /* Mic in */ - -/* ICH4 busmaster blocks */ -DEFINE_REGSET(MC2, 0x40); /* Mic in 2 */ -DEFINE_REGSET(PI2, 0x50); /* PCM in 2 */ -DEFINE_REGSET(SP, 0x60); /* SPDIF out */ - -/* values for each busmaster block */ - -/* LVI */ -#define ICH_REG_LVI_MASK 0x1f - -/* SR */ -#define ICH_FIFOE 0x10 /* FIFO error */ -#define ICH_BCIS 0x08 /* buffer completion interrupt status */ -#define ICH_LVBCI 0x04 /* last valid buffer completion interrupt */ -#define ICH_CELV 0x02 /* current equals last valid */ -#define ICH_DCH 0x01 /* DMA controller halted */ - -/* PIV */ -#define ICH_REG_PIV_MASK 0x1f /* mask */ - -/* CR */ -#define ICH_IOCE 0x10 /* interrupt on completion enable */ -#define ICH_FEIE 0x08 /* fifo error interrupt enable */ -#define ICH_LVBIE 0x04 /* last valid buffer interrupt enable */ -#define ICH_RESETREGS 0x02 /* reset busmaster registers */ -#define ICH_STARTBM 0x01 /* start busmaster operation */ - - -/* global block */ -#define ICH_REG_GLOB_CNT 0x2c /* dword - global control */ -#define ICH_PCM_SPDIF_MASK 0xc0000000 /* s/pdif pcm slot mask (ICH4) */ -#define ICH_PCM_SPDIF_NONE 0x00000000 /* reserved - undefined */ -#define ICH_PCM_SPDIF_78 0x40000000 /* s/pdif pcm on slots 7&8 */ -#define ICH_PCM_SPDIF_69 0x80000000 /* s/pdif pcm on slots 6&9 */ -#define ICH_PCM_SPDIF_1011 0xc0000000 /* s/pdif pcm on slots 10&11 */ -#define ICH_PCM_20BIT 0x00400000 /* 20-bit samples (ICH4) */ -#define ICH_PCM_246_MASK 0x00300000 /* chan mask (not all chips) */ -#define ICH_PCM_8 0x00300000 /* 8 channels (not all chips) */ -#define ICH_PCM_6 0x00200000 /* 6 channels (not all chips) */ -#define ICH_PCM_4 0x00100000 /* 4 channels (not all chips) */ -#define ICH_PCM_2 0x00000000 /* 2 channels (stereo) */ -#define ICH_SIS_PCM_246_MASK 0x000000c0 /* 6 channels (SIS7012) */ -#define ICH_SIS_PCM_6 0x00000080 /* 6 channels (SIS7012) */ -#define ICH_SIS_PCM_4 0x00000040 /* 4 channels (SIS7012) */ -#define ICH_SIS_PCM_2 0x00000000 /* 2 channels (SIS7012) */ -#define ICH_TRIE 0x00000040 /* tertiary resume interrupt enable */ -#define ICH_SRIE 0x00000020 /* secondary resume interrupt enable */ -#define ICH_PRIE 0x00000010 /* primary resume interrupt enable */ -#define ICH_ACLINK 0x00000008 /* AClink shut off */ -#define ICH_AC97WARM 0x00000004 /* AC'97 warm reset */ -#define ICH_AC97COLD 0x00000002 /* AC'97 cold reset */ -#define ICH_GIE 0x00000001 /* GPI interrupt enable */ -#define ICH_REG_GLOB_STA 0x30 /* dword - global status */ -#define ICH_TRI 0x20000000 /* ICH4: tertiary (AC_SDIN2) resume interrupt */ -#define ICH_TCR 0x10000000 /* ICH4: tertiary (AC_SDIN2) codec ready */ -#define ICH_BCS 0x08000000 /* ICH4: bit clock stopped */ -#define ICH_SPINT 0x04000000 /* ICH4: S/PDIF interrupt */ -#define ICH_P2INT 0x02000000 /* ICH4: PCM2-In interrupt */ -#define ICH_M2INT 0x01000000 /* ICH4: Mic2-In interrupt */ -#define ICH_SAMPLE_CAP 0x00c00000 /* ICH4: sample capability bits (RO) */ -#define ICH_SAMPLE_16_20 0x00400000 /* ICH4: 16- and 20-bit samples */ -#define ICH_MULTICHAN_CAP 0x00300000 /* ICH4: multi-channel capability bits (RO) */ -#define ICH_SIS_TRI 0x00080000 /* SIS: tertiary resume irq */ -#define ICH_SIS_TCR 0x00040000 /* SIS: tertiary codec ready */ -#define ICH_MD3 0x00020000 /* modem power down semaphore */ -#define ICH_AD3 0x00010000 /* audio power down semaphore */ -#define ICH_RCS 0x00008000 /* read completion status */ -#define ICH_BIT3 0x00004000 /* bit 3 slot 12 */ -#define ICH_BIT2 0x00002000 /* bit 2 slot 12 */ -#define ICH_BIT1 0x00001000 /* bit 1 slot 12 */ -#define ICH_SRI 0x00000800 /* secondary (AC_SDIN1) resume interrupt */ -#define ICH_PRI 0x00000400 /* primary (AC_SDIN0) resume interrupt */ -#define ICH_SCR 0x00000200 /* secondary (AC_SDIN1) codec ready */ -#define ICH_PCR 0x00000100 /* primary (AC_SDIN0) codec ready */ -#define ICH_MCINT 0x00000080 /* MIC capture interrupt */ -#define ICH_POINT 0x00000040 /* playback interrupt */ -#define ICH_PIINT 0x00000020 /* capture interrupt */ -#define ICH_NVSPINT 0x00000010 /* nforce spdif interrupt */ -#define ICH_MOINT 0x00000004 /* modem playback interrupt */ -#define ICH_MIINT 0x00000002 /* modem capture interrupt */ -#define ICH_GSCI 0x00000001 /* GPI status change interrupt */ -#define ICH_REG_ACC_SEMA 0x34 /* byte - codec write semaphore */ -#define ICH_CAS 0x01 /* codec access semaphore */ -#define ICH_REG_SDM 0x80 -#define ICH_DI2L_MASK 0x000000c0 /* PCM In 2, Mic In 2 data in line */ -#define ICH_DI2L_SHIFT 6 -#define ICH_DI1L_MASK 0x00000030 /* PCM In 1, Mic In 1 data in line */ -#define ICH_DI1L_SHIFT 4 -#define ICH_SE 0x00000008 /* steer enable */ -#define ICH_LDI_MASK 0x00000003 /* last codec read data input */ - -#define ICH_MAX_FRAGS 32 /* max hw frags */ - - -/* - * registers for Ali5455 - */ - -/* ALi 5455 busmaster blocks */ -DEFINE_REGSET(AL_PI, 0x40); /* ALi PCM in */ -DEFINE_REGSET(AL_PO, 0x50); /* Ali PCM out */ -DEFINE_REGSET(AL_MC, 0x60); /* Ali Mic in */ -DEFINE_REGSET(AL_CDC_SPO, 0x70); /* Ali Codec SPDIF out */ -DEFINE_REGSET(AL_CENTER, 0x80); /* Ali center out */ -DEFINE_REGSET(AL_LFE, 0x90); /* Ali center out */ -DEFINE_REGSET(AL_CLR_SPI, 0xa0); /* Ali Controller SPDIF in */ -DEFINE_REGSET(AL_CLR_SPO, 0xb0); /* Ali Controller SPDIF out */ -DEFINE_REGSET(AL_I2S, 0xc0); /* Ali I2S in */ -DEFINE_REGSET(AL_PI2, 0xd0); /* Ali PCM2 in */ -DEFINE_REGSET(AL_MC2, 0xe0); /* Ali Mic2 in */ - -enum { - ICH_REG_ALI_SCR = 0x00, /* System Control Register */ - ICH_REG_ALI_SSR = 0x04, /* System Status Register */ - ICH_REG_ALI_DMACR = 0x08, /* DMA Control Register */ - ICH_REG_ALI_FIFOCR1 = 0x0c, /* FIFO Control Register 1 */ - ICH_REG_ALI_INTERFACECR = 0x10, /* Interface Control Register */ - ICH_REG_ALI_INTERRUPTCR = 0x14, /* Interrupt control Register */ - ICH_REG_ALI_INTERRUPTSR = 0x18, /* Interrupt Status Register */ - ICH_REG_ALI_FIFOCR2 = 0x1c, /* FIFO Control Register 2 */ - ICH_REG_ALI_CPR = 0x20, /* Command Port Register */ - ICH_REG_ALI_CPR_ADDR = 0x22, /* ac97 addr write */ - ICH_REG_ALI_SPR = 0x24, /* Status Port Register */ - ICH_REG_ALI_SPR_ADDR = 0x26, /* ac97 addr read */ - ICH_REG_ALI_FIFOCR3 = 0x2c, /* FIFO Control Register 3 */ - ICH_REG_ALI_TTSR = 0x30, /* Transmit Tag Slot Register */ - ICH_REG_ALI_RTSR = 0x34, /* Receive Tag Slot Register */ - ICH_REG_ALI_CSPSR = 0x38, /* Command/Status Port Status Register */ - ICH_REG_ALI_CAS = 0x3c, /* Codec Write Semaphore Register */ - ICH_REG_ALI_HWVOL = 0xf0, /* hardware volume control/status */ - ICH_REG_ALI_I2SCR = 0xf4, /* I2S control/status */ - ICH_REG_ALI_SPDIFCSR = 0xf8, /* spdif channel status register */ - ICH_REG_ALI_SPDIFICS = 0xfc, /* spdif interface control/status */ -}; - -#define ALI_CAS_SEM_BUSY 0x80000000 -#define ALI_CPR_ADDR_SECONDARY 0x100 -#define ALI_CPR_ADDR_READ 0x80 -#define ALI_CSPSR_CODEC_READY 0x08 -#define ALI_CSPSR_READ_OK 0x02 -#define ALI_CSPSR_WRITE_OK 0x01 - -/* interrupts for the whole chip by interrupt status register finish */ - -#define ALI_INT_MICIN2 (1<<26) -#define ALI_INT_PCMIN2 (1<<25) -#define ALI_INT_I2SIN (1<<24) -#define ALI_INT_SPDIFOUT (1<<23) /* controller spdif out INTERRUPT */ -#define ALI_INT_SPDIFIN (1<<22) -#define ALI_INT_LFEOUT (1<<21) -#define ALI_INT_CENTEROUT (1<<20) -#define ALI_INT_CODECSPDIFOUT (1<<19) -#define ALI_INT_MICIN (1<<18) -#define ALI_INT_PCMOUT (1<<17) -#define ALI_INT_PCMIN (1<<16) -#define ALI_INT_CPRAIS (1<<7) /* command port available */ -#define ALI_INT_SPRAIS (1<<5) /* status port available */ -#define ALI_INT_GPIO (1<<1) -#define ALI_INT_MASK (ALI_INT_SPDIFOUT|ALI_INT_CODECSPDIFOUT|\ - ALI_INT_MICIN|ALI_INT_PCMOUT|ALI_INT_PCMIN) - -#define ICH_ALI_SC_RESET (1<<31) /* master reset */ -#define ICH_ALI_SC_AC97_DBL (1<<30) -#define ICH_ALI_SC_CODEC_SPDF (3<<20) /* 1=7/8, 2=6/9, 3=10/11 */ -#define ICH_ALI_SC_IN_BITS (3<<18) -#define ICH_ALI_SC_OUT_BITS (3<<16) -#define ICH_ALI_SC_6CH_CFG (3<<14) -#define ICH_ALI_SC_PCM_4 (1<<8) -#define ICH_ALI_SC_PCM_6 (2<<8) -#define ICH_ALI_SC_PCM_246_MASK (3<<8) - -#define ICH_ALI_SS_SEC_ID (3<<5) -#define ICH_ALI_SS_PRI_ID (3<<3) - -#define ICH_ALI_IF_AC97SP (1<<21) -#define ICH_ALI_IF_MC (1<<20) -#define ICH_ALI_IF_PI (1<<19) -#define ICH_ALI_IF_MC2 (1<<18) -#define ICH_ALI_IF_PI2 (1<<17) -#define ICH_ALI_IF_LINE_SRC (1<<15) /* 0/1 = slot 3/6 */ -#define ICH_ALI_IF_MIC_SRC (1<<14) /* 0/1 = slot 3/6 */ -#define ICH_ALI_IF_SPDF_SRC (3<<12) /* 00 = PCM, 01 = AC97-in, 10 = spdif-in, 11 = i2s */ -#define ICH_ALI_IF_AC97_OUT (3<<8) /* 00 = PCM, 10 = spdif-in, 11 = i2s */ -#define ICH_ALI_IF_PO_SPDF (1<<3) -#define ICH_ALI_IF_PO (1<<1) - -/* - * - */ - -enum { - ICHD_PCMIN, - ICHD_PCMOUT, - ICHD_MIC, - ICHD_MIC2, - ICHD_PCM2IN, - ICHD_SPBAR, - ICHD_LAST = ICHD_SPBAR -}; -enum { - NVD_PCMIN, - NVD_PCMOUT, - NVD_MIC, - NVD_SPBAR, - NVD_LAST = NVD_SPBAR -}; -enum { - ALID_PCMIN, - ALID_PCMOUT, - ALID_MIC, - ALID_AC97SPDIFOUT, - ALID_SPDIFIN, - ALID_SPDIFOUT, - ALID_LAST = ALID_SPDIFOUT -}; - -#define get_ichdev(substream) (substream->runtime->private_data) - -struct ichdev { - unsigned int ichd; /* ich device number */ - unsigned long reg_offset; /* offset to bmaddr */ - u32 *bdbar; /* CPU address (32bit) */ - unsigned int bdbar_addr; /* PCI bus address (32bit) */ - struct snd_pcm_substream *substream; - unsigned int physbuf; /* physical address (32bit) */ - unsigned int size; - unsigned int fragsize; - unsigned int fragsize1; - unsigned int position; - unsigned int pos_shift; - unsigned int last_pos; - int frags; - int lvi; - int lvi_frag; - int civ; - int ack; - int ack_reload; - unsigned int ack_bit; - unsigned int roff_sr; - unsigned int roff_picb; - unsigned int int_sta_mask; /* interrupt status mask */ - unsigned int ali_slot; /* ALI DMA slot */ - struct ac97_pcm *pcm; - int pcm_open_flag; - unsigned int page_attr_changed: 1; - unsigned int suspended: 1; -}; - -struct intel8x0 { - unsigned int device_type; - - int irq; - - void __iomem *addr; - void __iomem *bmaddr; - - struct pci_dev *pci; - struct snd_card *card; - - int pcm_devs; - struct snd_pcm *pcm[6]; - struct ichdev ichd[6]; - - unsigned multi4: 1, - multi6: 1, - multi8 :1, - dra: 1, - smp20bit: 1; - unsigned in_ac97_init: 1, - in_sdin_init: 1; - unsigned in_measurement: 1; /* during ac97 clock measurement */ - unsigned fix_nocache: 1; /* workaround for 440MX */ - unsigned buggy_irq: 1; /* workaround for buggy mobos */ - unsigned xbox: 1; /* workaround for Xbox AC'97 detection */ - unsigned buggy_semaphore: 1; /* workaround for buggy codec semaphore */ - unsigned inside_vm: 1; /* enable VM optimization */ - - int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */ - unsigned int sdm_saved; /* SDM reg value */ - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97[3]; - unsigned int ac97_sdin[3]; - unsigned int max_codecs, ncodecs; - unsigned int *codec_bit; - unsigned int codec_isr_bits; - unsigned int codec_ready_bits; - - spinlock_t reg_lock; - - u32 bdbars_count; - struct snd_dma_buffer bdbars; - u32 int_sta_reg; /* interrupt status register */ - u32 int_sta_mask; /* interrupt status mask */ -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0_ids) = { - { PCI_VDEVICE(INTEL, 0x2415), DEVICE_INTEL }, /* 82801AA */ - { PCI_VDEVICE(INTEL, 0x2425), DEVICE_INTEL }, /* 82901AB */ - { PCI_VDEVICE(INTEL, 0x2445), DEVICE_INTEL }, /* 82801BA */ - { PCI_VDEVICE(INTEL, 0x2485), DEVICE_INTEL }, /* ICH3 */ - { PCI_VDEVICE(INTEL, 0x24c5), DEVICE_INTEL_ICH4 }, /* ICH4 */ - { PCI_VDEVICE(INTEL, 0x24d5), DEVICE_INTEL_ICH4 }, /* ICH5 */ - { PCI_VDEVICE(INTEL, 0x25a6), DEVICE_INTEL_ICH4 }, /* ESB */ - { PCI_VDEVICE(INTEL, 0x266e), DEVICE_INTEL_ICH4 }, /* ICH6 */ - { PCI_VDEVICE(INTEL, 0x27de), DEVICE_INTEL_ICH4 }, /* ICH7 */ - { PCI_VDEVICE(INTEL, 0x2698), DEVICE_INTEL_ICH4 }, /* ESB2 */ - { PCI_VDEVICE(INTEL, 0x7195), DEVICE_INTEL }, /* 440MX */ - { PCI_VDEVICE(SI, 0x7012), DEVICE_SIS }, /* SI7012 */ - { PCI_VDEVICE(NVIDIA, 0x01b1), DEVICE_NFORCE }, /* NFORCE */ - { PCI_VDEVICE(NVIDIA, 0x003a), DEVICE_NFORCE }, /* MCP04 */ - { PCI_VDEVICE(NVIDIA, 0x006a), DEVICE_NFORCE }, /* NFORCE2 */ - { PCI_VDEVICE(NVIDIA, 0x0059), DEVICE_NFORCE }, /* CK804 */ - { PCI_VDEVICE(NVIDIA, 0x008a), DEVICE_NFORCE }, /* CK8 */ - { PCI_VDEVICE(NVIDIA, 0x00da), DEVICE_NFORCE }, /* NFORCE3 */ - { PCI_VDEVICE(NVIDIA, 0x00ea), DEVICE_NFORCE }, /* CK8S */ - { PCI_VDEVICE(NVIDIA, 0x026b), DEVICE_NFORCE }, /* MCP51 */ - { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */ - { PCI_VDEVICE(AMD, 0x7445), DEVICE_INTEL }, /* AMD768 */ - { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_intel8x0_ids); - -/* - * Lowlevel I/O - busmaster - */ - -static inline u8 igetbyte(struct intel8x0 *chip, u32 offset) -{ - return ioread8(chip->bmaddr + offset); -} - -static inline u16 igetword(struct intel8x0 *chip, u32 offset) -{ - return ioread16(chip->bmaddr + offset); -} - -static inline u32 igetdword(struct intel8x0 *chip, u32 offset) -{ - return ioread32(chip->bmaddr + offset); -} - -static inline void iputbyte(struct intel8x0 *chip, u32 offset, u8 val) -{ - iowrite8(val, chip->bmaddr + offset); -} - -static inline void iputword(struct intel8x0 *chip, u32 offset, u16 val) -{ - iowrite16(val, chip->bmaddr + offset); -} - -static inline void iputdword(struct intel8x0 *chip, u32 offset, u32 val) -{ - iowrite32(val, chip->bmaddr + offset); -} - -/* - * Lowlevel I/O - AC'97 registers - */ - -static inline u16 iagetword(struct intel8x0 *chip, u32 offset) -{ - return ioread16(chip->addr + offset); -} - -static inline void iaputword(struct intel8x0 *chip, u32 offset, u16 val) -{ - iowrite16(val, chip->addr + offset); -} - -/* - * Basic I/O - */ - -/* - * access to AC97 codec via normal i/o (for ICH and SIS7012) - */ - -static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int codec) -{ - int time; - - if (codec > 2) - return -EIO; - if (chip->in_sdin_init) { - /* we don't know the ready bit assignment at the moment */ - /* so we check any */ - codec = chip->codec_isr_bits; - } else { - codec = chip->codec_bit[chip->ac97_sdin[codec]]; - } - - /* codec ready ? */ - if ((igetdword(chip, ICHREG(GLOB_STA)) & codec) == 0) - return -EIO; - - if (chip->buggy_semaphore) - return 0; /* just ignore ... */ - - /* Anyone holding a semaphore for 1 msec should be shot... */ - time = 100; - do { - if (!(igetbyte(chip, ICHREG(ACC_SEMA)) & ICH_CAS)) - return 0; - udelay(10); - } while (time--); - - /* access to some forbidden (non existent) ac97 registers will not - * reset the semaphore. So even if you don't get the semaphore, still - * continue the access. We don't need the semaphore anyway. */ - snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", - igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA))); - iagetword(chip, 0); /* clear semaphore flag */ - /* I don't care about the semaphore */ - return -EBUSY; -} - -static void snd_intel8x0_codec_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct intel8x0 *chip = ac97->private_data; - - if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { - if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); - } - iaputword(chip, reg + ac97->num * 0x80, val); -} - -static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct intel8x0 *chip = ac97->private_data; - unsigned short res; - unsigned int tmp; - - if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { - if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); - res = 0xffff; - } else { - res = iagetword(chip, reg + ac97->num * 0x80); - if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { - /* reset RCS and preserve other R/WC bits */ - iputdword(chip, ICHREG(GLOB_STA), tmp & - ~(chip->codec_ready_bits | ICH_GSCI)); - if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); - res = 0xffff; - } - } - return res; -} - -static void __devinit snd_intel8x0_codec_read_test(struct intel8x0 *chip, - unsigned int codec) -{ - unsigned int tmp; - - if (snd_intel8x0_codec_semaphore(chip, codec) >= 0) { - iagetword(chip, codec * 0x80); - if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { - /* reset RCS and preserve other R/WC bits */ - iputdword(chip, ICHREG(GLOB_STA), tmp & - ~(chip->codec_ready_bits | ICH_GSCI)); - } - } -} - -/* - * access to AC97 for Ali5455 - */ -static int snd_intel8x0_ali_codec_ready(struct intel8x0 *chip, int mask) -{ - int count = 0; - for (count = 0; count < 0x7f; count++) { - int val = igetbyte(chip, ICHREG(ALI_CSPSR)); - if (val & mask) - return 0; - } - if (! chip->in_ac97_init) - snd_printd(KERN_WARNING "intel8x0: AC97 codec ready timeout.\n"); - return -EBUSY; -} - -static int snd_intel8x0_ali_codec_semaphore(struct intel8x0 *chip) -{ - int time = 100; - if (chip->buggy_semaphore) - return 0; /* just ignore ... */ - while (--time && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY)) - udelay(1); - if (! time && ! chip->in_ac97_init) - snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n"); - return snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_CODEC_READY); -} - -static unsigned short snd_intel8x0_ali_codec_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct intel8x0 *chip = ac97->private_data; - unsigned short data = 0xffff; - - if (snd_intel8x0_ali_codec_semaphore(chip)) - goto __err; - reg |= ALI_CPR_ADDR_READ; - if (ac97->num) - reg |= ALI_CPR_ADDR_SECONDARY; - iputword(chip, ICHREG(ALI_CPR_ADDR), reg); - if (snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_READ_OK)) - goto __err; - data = igetword(chip, ICHREG(ALI_SPR)); - __err: - return data; -} - -static void snd_intel8x0_ali_codec_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct intel8x0 *chip = ac97->private_data; - - if (snd_intel8x0_ali_codec_semaphore(chip)) - return; - iputword(chip, ICHREG(ALI_CPR), val); - if (ac97->num) - reg |= ALI_CPR_ADDR_SECONDARY; - iputword(chip, ICHREG(ALI_CPR_ADDR), reg); - snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_WRITE_OK); -} - - -/* - * DMA I/O - */ -static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ichdev) -{ - int idx; - u32 *bdbar = ichdev->bdbar; - unsigned long port = ichdev->reg_offset; - - iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr); - if (ichdev->size == ichdev->fragsize) { - ichdev->ack_reload = ichdev->ack = 2; - ichdev->fragsize1 = ichdev->fragsize >> 1; - for (idx = 0; idx < (ICH_REG_LVI_MASK + 1) * 2; idx += 4) { - bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf); - bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ - ichdev->fragsize1 >> ichdev->pos_shift); - bdbar[idx + 2] = cpu_to_le32(ichdev->physbuf + (ichdev->size >> 1)); - bdbar[idx + 3] = cpu_to_le32(0x80000000 | /* interrupt on completion */ - ichdev->fragsize1 >> ichdev->pos_shift); - } - ichdev->frags = 2; - } else { - ichdev->ack_reload = ichdev->ack = 1; - ichdev->fragsize1 = ichdev->fragsize; - for (idx = 0; idx < (ICH_REG_LVI_MASK + 1) * 2; idx += 2) { - bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf + - (((idx >> 1) * ichdev->fragsize) % - ichdev->size)); - bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ - ichdev->fragsize >> ichdev->pos_shift); -#if 0 - printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", - idx + 0, bdbar[idx + 0], bdbar[idx + 1]); -#endif - } - ichdev->frags = ichdev->size / ichdev->fragsize; - } - iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi = ICH_REG_LVI_MASK); - ichdev->civ = 0; - iputbyte(chip, port + ICH_REG_OFF_CIV, 0); - ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; - ichdev->position = 0; -#if 0 - printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " - "period_size1 = 0x%x\n", - ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, - ichdev->fragsize1); -#endif - /* clear interrupts */ - iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); -} - -#ifdef __i386__ -/* - * Intel 82443MX running a 100MHz processor system bus has a hardware bug, - * which aborts PCI busmaster for audio transfer. A workaround is to set - * the pages as non-cached. For details, see the errata in - * http://download.intel.com/design/chipsets/specupdt/24505108.pdf - */ -static void fill_nocache(void *buf, int size, int nocache) -{ - size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; - if (nocache) - set_pages_uc(virt_to_page(buf), size); - else - set_pages_wb(virt_to_page(buf), size); -} -#else -#define fill_nocache(buf, size, nocache) do { ; } while (0) -#endif - -/* - * Interrupt handler - */ - -static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ichdev) -{ - unsigned long port = ichdev->reg_offset; - unsigned long flags; - int status, civ, i, step; - int ack = 0; - - spin_lock_irqsave(&chip->reg_lock, flags); - status = igetbyte(chip, port + ichdev->roff_sr); - civ = igetbyte(chip, port + ICH_REG_OFF_CIV); - if (!(status & ICH_BCIS)) { - step = 0; - } else if (civ == ichdev->civ) { - // snd_printd("civ same %d\n", civ); - step = 1; - ichdev->civ++; - ichdev->civ &= ICH_REG_LVI_MASK; - } else { - step = civ - ichdev->civ; - if (step < 0) - step += ICH_REG_LVI_MASK + 1; - // if (step != 1) - // snd_printd("step = %d, %d -> %d\n", step, ichdev->civ, civ); - ichdev->civ = civ; - } - - ichdev->position += step * ichdev->fragsize1; - if (! chip->in_measurement) - ichdev->position %= ichdev->size; - ichdev->lvi += step; - ichdev->lvi &= ICH_REG_LVI_MASK; - iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi); - for (i = 0; i < step; i++) { - ichdev->lvi_frag++; - ichdev->lvi_frag %= ichdev->frags; - ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); -#if 0 - printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, " - "all = 0x%x, 0x%x\n", - ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], - ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), - inl(port + 4), inb(port + ICH_REG_OFF_CR)); -#endif - if (--ichdev->ack == 0) { - ichdev->ack = ichdev->ack_reload; - ack = 1; - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (ack && ichdev->substream) { - snd_pcm_period_elapsed(ichdev->substream); - } - iputbyte(chip, port + ichdev->roff_sr, - status & (ICH_FIFOE | ICH_BCIS | ICH_LVBCI)); -} - -static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id) -{ - struct intel8x0 *chip = dev_id; - struct ichdev *ichdev; - unsigned int status; - unsigned int i; - - status = igetdword(chip, chip->int_sta_reg); - if (status == 0xffffffff) /* we are not yet resumed */ - return IRQ_NONE; - - if ((status & chip->int_sta_mask) == 0) { - if (status) { - /* ack */ - iputdword(chip, chip->int_sta_reg, status); - if (! chip->buggy_irq) - status = 0; - } - return IRQ_RETVAL(status); - } - - for (i = 0; i < chip->bdbars_count; i++) { - ichdev = &chip->ichd[i]; - if (status & ichdev->int_sta_mask) - snd_intel8x0_update(chip, ichdev); - } - - /* ack them */ - iputdword(chip, chip->int_sta_reg, status & chip->int_sta_mask); - - return IRQ_HANDLED; -} - -/* - * PCM part - */ - -static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - struct ichdev *ichdev = get_ichdev(substream); - unsigned char val = 0; - unsigned long port = ichdev->reg_offset; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - 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; - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - ichdev->suspended = 1; - /* fallthru */ - case SNDRV_PCM_TRIGGER_STOP: - val = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - val = ICH_IOCE; - break; - default: - return -EINVAL; - } - iputbyte(chip, port + ICH_REG_OFF_CR, val); - if (cmd == SNDRV_PCM_TRIGGER_STOP) { - /* wait until DMA stopped */ - while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH)) ; - /* reset whole DMA things */ - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); - } - return 0; -} - -static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - struct ichdev *ichdev = get_ichdev(substream); - unsigned long port = ichdev->reg_offset; - static int fiforeg[] = { - ICHREG(ALI_FIFOCR1), ICHREG(ALI_FIFOCR2), ICHREG(ALI_FIFOCR3) - }; - unsigned int val, fifo; - - val = igetdword(chip, ICHREG(ALI_DMACR)); - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - ichdev->suspended = 0; - /* fallthru */ - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* clear FIFO for synchronization of channels */ - fifo = igetdword(chip, fiforeg[ichdev->ali_slot / 4]); - fifo &= ~(0xff << (ichdev->ali_slot % 4)); - fifo |= 0x83 << (ichdev->ali_slot % 4); - iputdword(chip, fiforeg[ichdev->ali_slot / 4], fifo); - } - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); - val &= ~(1 << (ichdev->ali_slot + 16)); /* clear PAUSE flag */ - /* start DMA */ - iputdword(chip, ICHREG(ALI_DMACR), val | (1 << ichdev->ali_slot)); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - ichdev->suspended = 1; - /* fallthru */ - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - /* pause */ - iputdword(chip, ICHREG(ALI_DMACR), val | (1 << (ichdev->ali_slot + 16))); - iputbyte(chip, port + ICH_REG_OFF_CR, 0); - while (igetbyte(chip, port + ICH_REG_OFF_CR)) - ; - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) - break; - /* reset whole DMA things */ - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); - /* clear interrupts */ - iputbyte(chip, port + ICH_REG_OFF_SR, - igetbyte(chip, port + ICH_REG_OFF_SR) | 0x1e); - iputdword(chip, ICHREG(ALI_INTERRUPTSR), - igetdword(chip, ICHREG(ALI_INTERRUPTSR)) & ichdev->int_sta_mask); - break; - default: - return -EINVAL; - } - return 0; -} - -static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - struct ichdev *ichdev = get_ichdev(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int dbl = params_rate(hw_params) > 48000; - int err; - - if (chip->fix_nocache && ichdev->page_attr_changed) { - fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); /* clear */ - ichdev->page_attr_changed = 0; - } - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) - return err; - if (chip->fix_nocache) { - if (runtime->dma_area && ! ichdev->page_attr_changed) { - fill_nocache(runtime->dma_area, runtime->dma_bytes, 1); - ichdev->page_attr_changed = 1; - } - } - if (ichdev->pcm_open_flag) { - snd_ac97_pcm_close(ichdev->pcm); - ichdev->pcm_open_flag = 0; - } - err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params), - params_channels(hw_params), - ichdev->pcm->r[dbl].slots); - if (err >= 0) { - ichdev->pcm_open_flag = 1; - /* Force SPDIF setting */ - if (ichdev->ichd == ICHD_PCMOUT && chip->spdif_idx < 0) - snd_ac97_set_rate(ichdev->pcm->r[0].codec[0], AC97_SPDIF, - params_rate(hw_params)); - } - return err; -} - -static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - struct ichdev *ichdev = get_ichdev(substream); - - if (ichdev->pcm_open_flag) { - snd_ac97_pcm_close(ichdev->pcm); - ichdev->pcm_open_flag = 0; - } - if (chip->fix_nocache && ichdev->page_attr_changed) { - fill_nocache(substream->runtime->dma_area, substream->runtime->dma_bytes, 0); - ichdev->page_attr_changed = 0; - } - return snd_pcm_lib_free_pages(substream); -} - -static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip, - struct snd_pcm_runtime *runtime) -{ - unsigned int cnt; - int dbl = runtime->rate > 48000; - - spin_lock_irq(&chip->reg_lock); - switch (chip->device_type) { - case DEVICE_ALI: - cnt = igetdword(chip, ICHREG(ALI_SCR)); - cnt &= ~ICH_ALI_SC_PCM_246_MASK; - if (runtime->channels == 4 || dbl) - cnt |= ICH_ALI_SC_PCM_4; - else if (runtime->channels == 6) - cnt |= ICH_ALI_SC_PCM_6; - iputdword(chip, ICHREG(ALI_SCR), cnt); - break; - case DEVICE_SIS: - cnt = igetdword(chip, ICHREG(GLOB_CNT)); - cnt &= ~ICH_SIS_PCM_246_MASK; - if (runtime->channels == 4 || dbl) - cnt |= ICH_SIS_PCM_4; - else if (runtime->channels == 6) - cnt |= ICH_SIS_PCM_6; - iputdword(chip, ICHREG(GLOB_CNT), cnt); - break; - default: - cnt = igetdword(chip, ICHREG(GLOB_CNT)); - cnt &= ~(ICH_PCM_246_MASK | ICH_PCM_20BIT); - if (runtime->channels == 4 || dbl) - cnt |= ICH_PCM_4; - else if (runtime->channels == 6) - cnt |= ICH_PCM_6; - else if (runtime->channels == 8) - cnt |= ICH_PCM_8; - if (chip->device_type == DEVICE_NFORCE) { - /* reset to 2ch once to keep the 6 channel data in alignment, - * to start from Front Left always - */ - if (cnt & ICH_PCM_246_MASK) { - iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_PCM_246_MASK); - spin_unlock_irq(&chip->reg_lock); - msleep(50); /* grrr... */ - spin_lock_irq(&chip->reg_lock); - } - } else if (chip->device_type == DEVICE_INTEL_ICH4) { - if (runtime->sample_bits > 16) - cnt |= ICH_PCM_20BIT; - } - iputdword(chip, ICHREG(GLOB_CNT), cnt); - break; - } - spin_unlock_irq(&chip->reg_lock); -} - -static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ichdev *ichdev = get_ichdev(substream); - - ichdev->physbuf = runtime->dma_addr; - ichdev->size = snd_pcm_lib_buffer_bytes(substream); - ichdev->fragsize = snd_pcm_lib_period_bytes(substream); - if (ichdev->ichd == ICHD_PCMOUT) { - snd_intel8x0_setup_pcm_out(chip, runtime); - if (chip->device_type == DEVICE_INTEL_ICH4) - ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1; - } - snd_intel8x0_setup_periods(chip, ichdev); - return 0; -} - -static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - struct ichdev *ichdev = get_ichdev(substream); - size_t ptr1, ptr; - int civ, timeout = 10; - unsigned int position; - - spin_lock(&chip->reg_lock); - do { - civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV); - ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb); - position = ichdev->position; - if (ptr1 == 0) { - udelay(10); - continue; - } - if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV)) - continue; - - /* IO read operation is very expensive inside virtual machine - * as it is emulated. The probability that subsequent PICB read - * will return different result is high enough to loop till - * timeout here. - * Same CIV is strict enough condition to be sure that PICB - * is valid inside VM on emulated card. */ - if (chip->inside_vm) - break; - if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) - break; - } while (timeout--); - ptr = ichdev->last_pos; - if (ptr1 != 0) { - ptr1 <<= ichdev->pos_shift; - ptr = ichdev->fragsize1 - ptr1; - ptr += position; - if (ptr < ichdev->last_pos) { - unsigned int pos_base, last_base; - pos_base = position / ichdev->fragsize1; - last_base = ichdev->last_pos / ichdev->fragsize1; - /* another sanity check; ptr1 can go back to full - * before the base position is updated - */ - if (pos_base == last_base) - ptr = ichdev->last_pos; - } - } - ichdev->last_pos = ptr; - spin_unlock(&chip->reg_lock); - if (ptr >= ichdev->size) - return 0; - return bytes_to_frames(substream->runtime, ptr); -} - -static struct snd_pcm_hardware snd_intel8x0_stream = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 128 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 128 * 1024, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static unsigned int channels4[] = { - 2, 4, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_channels4 = { - .count = ARRAY_SIZE(channels4), - .list = channels4, - .mask = 0, -}; - -static unsigned int channels6[] = { - 2, 4, 6, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = { - .count = ARRAY_SIZE(channels6), - .list = channels6, - .mask = 0, -}; - -static unsigned int channels8[] = { - 2, 4, 6, 8, -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = { - .count = ARRAY_SIZE(channels8), - .list = channels8, - .mask = 0, -}; - -static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - ichdev->substream = substream; - runtime->hw = snd_intel8x0_stream; - runtime->hw.rates = ichdev->pcm->rates; - snd_pcm_limit_hw_rates(runtime); - if (chip->device_type == DEVICE_SIS) { - runtime->hw.buffer_bytes_max = 64*1024; - runtime->hw.period_bytes_max = 64*1024; - } - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - runtime->private_data = ichdev; - return 0; -} - -static int snd_intel8x0_playback_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - err = snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_PCMOUT]); - if (err < 0) - return err; - - if (chip->multi8) { - runtime->hw.channels_max = 8; - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &hw_constraints_channels8); - } else if (chip->multi6) { - runtime->hw.channels_max = 6; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &hw_constraints_channels6); - } else if (chip->multi4) { - runtime->hw.channels_max = 4; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &hw_constraints_channels4); - } - if (chip->dra) { - snd_ac97_pcm_double_rate_rules(runtime); - } - if (chip->smp20bit) { - runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20); - } - return 0; -} - -static int snd_intel8x0_playback_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ICHD_PCMOUT].substream = NULL; - return 0; -} - -static int snd_intel8x0_capture_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - return snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_PCMIN]); -} - -static int snd_intel8x0_capture_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ICHD_PCMIN].substream = NULL; - return 0; -} - -static int snd_intel8x0_mic_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - return snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_MIC]); -} - -static int snd_intel8x0_mic_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ICHD_MIC].substream = NULL; - return 0; -} - -static int snd_intel8x0_mic2_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - return snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_MIC2]); -} - -static int snd_intel8x0_mic2_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ICHD_MIC2].substream = NULL; - return 0; -} - -static int snd_intel8x0_capture2_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - return snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_PCM2IN]); -} - -static int snd_intel8x0_capture2_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ICHD_PCM2IN].substream = NULL; - return 0; -} - -static int snd_intel8x0_spdif_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - int idx = chip->device_type == DEVICE_NFORCE ? NVD_SPBAR : ICHD_SPBAR; - - return snd_intel8x0_pcm_open(substream, &chip->ichd[idx]); -} - -static int snd_intel8x0_spdif_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - int idx = chip->device_type == DEVICE_NFORCE ? NVD_SPBAR : ICHD_SPBAR; - - chip->ichd[idx].substream = NULL; - return 0; -} - -static int snd_intel8x0_ali_ac97spdifout_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - unsigned int val; - - spin_lock_irq(&chip->reg_lock); - val = igetdword(chip, ICHREG(ALI_INTERFACECR)); - val |= ICH_ALI_IF_AC97SP; - iputdword(chip, ICHREG(ALI_INTERFACECR), val); - /* also needs to set ALI_SC_CODEC_SPDF correctly */ - spin_unlock_irq(&chip->reg_lock); - - return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_AC97SPDIFOUT]); -} - -static int snd_intel8x0_ali_ac97spdifout_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - unsigned int val; - - chip->ichd[ALID_AC97SPDIFOUT].substream = NULL; - spin_lock_irq(&chip->reg_lock); - val = igetdword(chip, ICHREG(ALI_INTERFACECR)); - val &= ~ICH_ALI_IF_AC97SP; - iputdword(chip, ICHREG(ALI_INTERFACECR), val); - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - -#if 0 // NYI -static int snd_intel8x0_ali_spdifin_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_SPDIFIN]); -} - -static int snd_intel8x0_ali_spdifin_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ALID_SPDIFIN].substream = NULL; - return 0; -} - -static int snd_intel8x0_ali_spdifout_open(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_SPDIFOUT]); -} - -static int snd_intel8x0_ali_spdifout_close(struct snd_pcm_substream *substream) -{ - struct intel8x0 *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ALID_SPDIFOUT].substream = NULL; - return 0; -} -#endif - -static struct snd_pcm_ops snd_intel8x0_playback_ops = { - .open = snd_intel8x0_playback_open, - .close = snd_intel8x0_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_capture_ops = { - .open = snd_intel8x0_capture_open, - .close = snd_intel8x0_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_capture_mic_ops = { - .open = snd_intel8x0_mic_open, - .close = snd_intel8x0_mic_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_capture_mic2_ops = { - .open = snd_intel8x0_mic2_open, - .close = snd_intel8x0_mic2_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_capture2_ops = { - .open = snd_intel8x0_capture2_open, - .close = snd_intel8x0_capture2_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_spdif_ops = { - .open = snd_intel8x0_spdif_open, - .close = snd_intel8x0_spdif_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_ali_playback_ops = { - .open = snd_intel8x0_playback_open, - .close = snd_intel8x0_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_ali_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_ali_capture_ops = { - .open = snd_intel8x0_capture_open, - .close = snd_intel8x0_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_ali_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_ali_capture_mic_ops = { - .open = snd_intel8x0_mic_open, - .close = snd_intel8x0_mic_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_ali_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = { - .open = snd_intel8x0_ali_ac97spdifout_open, - .close = snd_intel8x0_ali_ac97spdifout_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_ali_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -#if 0 // NYI -static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = { - .open = snd_intel8x0_ali_spdifin_open, - .close = snd_intel8x0_ali_spdifin_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = { - .open = snd_intel8x0_ali_spdifout_open, - .close = snd_intel8x0_ali_spdifout_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0_hw_params, - .hw_free = snd_intel8x0_hw_free, - .prepare = snd_intel8x0_pcm_prepare, - .trigger = snd_intel8x0_pcm_trigger, - .pointer = snd_intel8x0_pcm_pointer, -}; -#endif // NYI - -struct ich_pcm_table { - char *suffix; - struct snd_pcm_ops *playback_ops; - struct snd_pcm_ops *capture_ops; - size_t prealloc_size; - size_t prealloc_max_size; - int ac97_idx; -}; - -static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device, - struct ich_pcm_table *rec) -{ - struct snd_pcm *pcm; - int err; - char name[32]; - - if (rec->suffix) - sprintf(name, "Intel ICH - %s", rec->suffix); - else - strcpy(name, "Intel ICH"); - err = snd_pcm_new(chip->card, name, device, - rec->playback_ops ? 1 : 0, - rec->capture_ops ? 1 : 0, &pcm); - if (err < 0) - return err; - - if (rec->playback_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, rec->playback_ops); - if (rec->capture_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, rec->capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - if (rec->suffix) - sprintf(pcm->name, "%s - %s", chip->card->shortname, rec->suffix); - else - strcpy(pcm->name, chip->card->shortname); - chip->pcm[device] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - rec->prealloc_size, rec->prealloc_max_size); - - return 0; -} - -static struct ich_pcm_table intel_pcms[] __devinitdata = { - { - .playback_ops = &snd_intel8x0_playback_ops, - .capture_ops = &snd_intel8x0_capture_ops, - .prealloc_size = 64 * 1024, - .prealloc_max_size = 128 * 1024, - }, - { - .suffix = "MIC ADC", - .capture_ops = &snd_intel8x0_capture_mic_ops, - .prealloc_size = 0, - .prealloc_max_size = 128 * 1024, - .ac97_idx = ICHD_MIC, - }, - { - .suffix = "MIC2 ADC", - .capture_ops = &snd_intel8x0_capture_mic2_ops, - .prealloc_size = 0, - .prealloc_max_size = 128 * 1024, - .ac97_idx = ICHD_MIC2, - }, - { - .suffix = "ADC2", - .capture_ops = &snd_intel8x0_capture2_ops, - .prealloc_size = 0, - .prealloc_max_size = 128 * 1024, - .ac97_idx = ICHD_PCM2IN, - }, - { - .suffix = "IEC958", - .playback_ops = &snd_intel8x0_spdif_ops, - .prealloc_size = 64 * 1024, - .prealloc_max_size = 128 * 1024, - .ac97_idx = ICHD_SPBAR, - }, -}; - -static struct ich_pcm_table nforce_pcms[] __devinitdata = { - { - .playback_ops = &snd_intel8x0_playback_ops, - .capture_ops = &snd_intel8x0_capture_ops, - .prealloc_size = 64 * 1024, - .prealloc_max_size = 128 * 1024, - }, - { - .suffix = "MIC ADC", - .capture_ops = &snd_intel8x0_capture_mic_ops, - .prealloc_size = 0, - .prealloc_max_size = 128 * 1024, - .ac97_idx = NVD_MIC, - }, - { - .suffix = "IEC958", - .playback_ops = &snd_intel8x0_spdif_ops, - .prealloc_size = 64 * 1024, - .prealloc_max_size = 128 * 1024, - .ac97_idx = NVD_SPBAR, - }, -}; - -static struct ich_pcm_table ali_pcms[] __devinitdata = { - { - .playback_ops = &snd_intel8x0_ali_playback_ops, - .capture_ops = &snd_intel8x0_ali_capture_ops, - .prealloc_size = 64 * 1024, - .prealloc_max_size = 128 * 1024, - }, - { - .suffix = "MIC ADC", - .capture_ops = &snd_intel8x0_ali_capture_mic_ops, - .prealloc_size = 0, - .prealloc_max_size = 128 * 1024, - .ac97_idx = ALID_MIC, - }, - { - .suffix = "IEC958", - .playback_ops = &snd_intel8x0_ali_ac97spdifout_ops, - /* .capture_ops = &snd_intel8x0_ali_spdifin_ops, */ - .prealloc_size = 64 * 1024, - .prealloc_max_size = 128 * 1024, - .ac97_idx = ALID_AC97SPDIFOUT, - }, -#if 0 // NYI - { - .suffix = "HW IEC958", - .playback_ops = &snd_intel8x0_ali_spdifout_ops, - .prealloc_size = 64 * 1024, - .prealloc_max_size = 128 * 1024, - }, -#endif -}; - -static int __devinit snd_intel8x0_pcm(struct intel8x0 *chip) -{ - int i, tblsize, device, err; - struct ich_pcm_table *tbl, *rec; - - switch (chip->device_type) { - case DEVICE_INTEL_ICH4: - tbl = intel_pcms; - tblsize = ARRAY_SIZE(intel_pcms); - if (spdif_aclink) - tblsize--; - break; - case DEVICE_NFORCE: - tbl = nforce_pcms; - tblsize = ARRAY_SIZE(nforce_pcms); - if (spdif_aclink) - tblsize--; - break; - case DEVICE_ALI: - tbl = ali_pcms; - tblsize = ARRAY_SIZE(ali_pcms); - break; - default: - tbl = intel_pcms; - tblsize = 2; - break; - } - - device = 0; - for (i = 0; i < tblsize; i++) { - rec = tbl + i; - if (i > 0 && rec->ac97_idx) { - /* activate PCM only when associated AC'97 codec */ - if (! chip->ichd[rec->ac97_idx].pcm) - continue; - } - err = snd_intel8x0_pcm1(chip, device, rec); - if (err < 0) - return err; - device++; - } - - chip->pcm_devs = device; - return 0; -} - - -/* - * Mixer part - */ - -static void snd_intel8x0_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct intel8x0 *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct intel8x0 *chip = ac97->private_data; - chip->ac97[ac97->num] = NULL; -} - -static struct ac97_pcm ac97_pcm_defs[] __devinitdata = { - /* front PCM */ - { - .exclusive = 1, - .r = { { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) | - (1 << AC97_SLOT_PCM_CENTER) | - (1 << AC97_SLOT_PCM_SLEFT) | - (1 << AC97_SLOT_PCM_SRIGHT) | - (1 << AC97_SLOT_LFE) - }, - { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) | - (1 << AC97_SLOT_PCM_LEFT_0) | - (1 << AC97_SLOT_PCM_RIGHT_0) - } - } - }, - /* PCM IN #1 */ - { - .stream = 1, - .exclusive = 1, - .r = { { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) - } - } - }, - /* MIC IN #1 */ - { - .stream = 1, - .exclusive = 1, - .r = { { - .slots = (1 << AC97_SLOT_MIC) - } - } - }, - /* S/PDIF PCM */ - { - .exclusive = 1, - .spdif = 1, - .r = { { - .slots = (1 << AC97_SLOT_SPDIF_LEFT2) | - (1 << AC97_SLOT_SPDIF_RIGHT2) - } - } - }, - /* PCM IN #2 */ - { - .stream = 1, - .exclusive = 1, - .r = { { - .slots = (1 << AC97_SLOT_PCM_LEFT) | - (1 << AC97_SLOT_PCM_RIGHT) - } - } - }, - /* MIC IN #2 */ - { - .stream = 1, - .exclusive = 1, - .r = { { - .slots = (1 << AC97_SLOT_MIC) - } - } - }, -}; - -static struct ac97_quirk ac97_quirks[] __devinitdata = { - { - .subvendor = 0x0e11, - .subdevice = 0x000e, - .name = "Compaq Deskpro EN", /* AD1885 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x0e11, - .subdevice = 0x008a, - .name = "Compaq Evo W4000", /* AD1885 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x0e11, - .subdevice = 0x00b8, - .name = "Compaq Evo D510C", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x0e11, - .subdevice = 0x0860, - .name = "HP/Compaq nx7010", - .type = AC97_TUNE_MUTE_LED - }, - { - .subvendor = 0x1014, - .subdevice = 0x0534, - .name = "ThinkPad X31", - .type = AC97_TUNE_INV_EAPD - }, - { - .subvendor = 0x1014, - .subdevice = 0x1f00, - .name = "MS-9128", - .type = AC97_TUNE_ALC_JACK - }, - { - .subvendor = 0x1014, - .subdevice = 0x0267, - .name = "IBM NetVista A30p", /* AD1981B */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1025, - .subdevice = 0x0082, - .name = "Acer Travelmate 2310", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1025, - .subdevice = 0x0083, - .name = "Acer Aspire 3003LCi", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x00d8, - .name = "Dell Precision 530", /* AD1885 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x010d, - .name = "Dell", /* which model? AD1885 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x0126, - .name = "Dell Optiplex GX260", /* AD1981A */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x012c, - .name = "Dell Precision 650", /* AD1981A */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x012d, - .name = "Dell Precision 450", /* AD1981B*/ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x0147, - .name = "Dell", /* which model? AD1981B*/ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x0151, - .name = "Dell Optiplex GX270", /* AD1981B */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x014e, - .name = "Dell D800", /* STAC9750/51 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x0163, - .name = "Dell Unknown", /* STAC9750/51 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x016a, - .name = "Dell Inspiron 8600", /* STAC9750/51 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x0182, - .name = "Dell Latitude D610", /* STAC9750/51 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1028, - .subdevice = 0x0186, - .name = "Dell Latitude D810", /* cf. Malone #41015 */ - .type = AC97_TUNE_HP_MUTE_LED - }, - { - .subvendor = 0x1028, - .subdevice = 0x0188, - .name = "Dell Inspiron 6000", - .type = AC97_TUNE_HP_MUTE_LED /* cf. Malone #41015 */ - }, - { - .subvendor = 0x1028, - .subdevice = 0x0189, - .name = "Dell Inspiron 9300", - .type = AC97_TUNE_HP_MUTE_LED - }, - { - .subvendor = 0x1028, - .subdevice = 0x0191, - .name = "Dell Inspiron 8600", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x103c, - .subdevice = 0x006d, - .name = "HP zv5000", - .type = AC97_TUNE_MUTE_LED /*AD1981B*/ - }, - { /* FIXME: which codec? */ - .subvendor = 0x103c, - .subdevice = 0x00c3, - .name = "HP xw6000", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x103c, - .subdevice = 0x088c, - .name = "HP nc8000", - .type = AC97_TUNE_HP_MUTE_LED - }, - { - .subvendor = 0x103c, - .subdevice = 0x0890, - .name = "HP nc6000", - .type = AC97_TUNE_MUTE_LED - }, - { - .subvendor = 0x103c, - .subdevice = 0x129d, - .name = "HP xw8000", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x103c, - .subdevice = 0x0938, - .name = "HP nc4200", - .type = AC97_TUNE_HP_MUTE_LED - }, - { - .subvendor = 0x103c, - .subdevice = 0x099c, - .name = "HP nx6110/nc6120", - .type = AC97_TUNE_HP_MUTE_LED - }, - { - .subvendor = 0x103c, - .subdevice = 0x0944, - .name = "HP nc6220", - .type = AC97_TUNE_HP_MUTE_LED - }, - { - .subvendor = 0x103c, - .subdevice = 0x0934, - .name = "HP nc8220", - .type = AC97_TUNE_HP_MUTE_LED - }, - { - .subvendor = 0x103c, - .subdevice = 0x12f1, - .name = "HP xw8200", /* AD1981B*/ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x103c, - .subdevice = 0x12f2, - .name = "HP xw6200", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x103c, - .subdevice = 0x3008, - .name = "HP xw4200", /* AD1981B*/ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x104d, - .subdevice = 0x8144, - .name = "Sony", - .type = AC97_TUNE_INV_EAPD - }, - { - .subvendor = 0x104d, - .subdevice = 0x8197, - .name = "Sony S1XP", - .type = AC97_TUNE_INV_EAPD - }, - { - .subvendor = 0x104d, - .subdevice = 0x81c0, - .name = "Sony VAIO VGN-T350P", /*AD1981B*/ - .type = AC97_TUNE_INV_EAPD - }, - { - .subvendor = 0x104d, - .subdevice = 0x81c5, - .name = "Sony VAIO VGN-B1VP", /*AD1981B*/ - .type = AC97_TUNE_INV_EAPD - }, - { - .subvendor = 0x1043, - .subdevice = 0x80f3, - .name = "ASUS ICH5/AD1985", - .type = AC97_TUNE_AD_SHARING - }, - { - .subvendor = 0x10cf, - .subdevice = 0x11c3, - .name = "Fujitsu-Siemens E4010", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10cf, - .subdevice = 0x1225, - .name = "Fujitsu-Siemens T3010", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10cf, - .subdevice = 0x1253, - .name = "Fujitsu S6210", /* STAC9750/51 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10cf, - .subdevice = 0x127d, - .name = "Fujitsu Lifebook P7010", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10cf, - .subdevice = 0x127e, - .name = "Fujitsu Lifebook C1211D", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10cf, - .subdevice = 0x12ec, - .name = "Fujitsu-Siemens 4010", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10cf, - .subdevice = 0x12f2, - .name = "Fujitsu-Siemens Celsius H320", - .type = AC97_TUNE_SWAP_HP - }, - { - .subvendor = 0x10f1, - .subdevice = 0x2665, - .name = "Fujitsu-Siemens Celsius", /* AD1981? */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10f1, - .subdevice = 0x2885, - .name = "AMD64 Mobo", /* ALC650 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10f1, - .subdevice = 0x2895, - .name = "Tyan Thunder K8WE", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x10f7, - .subdevice = 0x834c, - .name = "Panasonic CF-R4", - .type = AC97_TUNE_HP_ONLY, - }, - { - .subvendor = 0x110a, - .subdevice = 0x0056, - .name = "Fujitsu-Siemens Scenic", /* AD1981? */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x11d4, - .subdevice = 0x5375, - .name = "ADI AD1985 (discrete)", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1462, - .subdevice = 0x5470, - .name = "MSI P4 ATX 645 Ultra", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x161f, - .subdevice = 0x202f, - .name = "Gateway M520", - .type = AC97_TUNE_INV_EAPD - }, - { - .subvendor = 0x161f, - .subdevice = 0x203a, - .name = "Gateway 4525GZ", /* AD1981B */ - .type = AC97_TUNE_INV_EAPD - }, - { - .subvendor = 0x1734, - .subdevice = 0x0088, - .name = "Fujitsu-Siemens D1522", /* AD1981 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x8086, - .subdevice = 0x2000, - .mask = 0xfff0, - .name = "Intel ICH5/AD1985", - .type = AC97_TUNE_AD_SHARING - }, - { - .subvendor = 0x8086, - .subdevice = 0x4000, - .mask = 0xfff0, - .name = "Intel ICH5/AD1985", - .type = AC97_TUNE_AD_SHARING - }, - { - .subvendor = 0x8086, - .subdevice = 0x4856, - .name = "Intel D845WN (82801BA)", - .type = AC97_TUNE_SWAP_HP - }, - { - .subvendor = 0x8086, - .subdevice = 0x4d44, - .name = "Intel D850EMV2", /* AD1885 */ - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x8086, - .subdevice = 0x4d56, - .name = "Intel ICH/AD1885", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x8086, - .subdevice = 0x6000, - .mask = 0xfff0, - .name = "Intel ICH5/AD1985", - .type = AC97_TUNE_AD_SHARING - }, - { - .subvendor = 0x8086, - .subdevice = 0xe000, - .mask = 0xfff0, - .name = "Intel ICH5/AD1985", - .type = AC97_TUNE_AD_SHARING - }, -#if 0 /* FIXME: this seems wrong on most boards */ - { - .subvendor = 0x8086, - .subdevice = 0xa000, - .mask = 0xfff0, - .name = "Intel ICH5/AD1985", - .type = AC97_TUNE_HP_ONLY - }, -#endif - { } /* terminator */ -}; - -static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, - const char *quirk_override) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err; - unsigned int i, codecs; - unsigned int glob_sta = 0; - struct snd_ac97_bus_ops *ops; - static struct snd_ac97_bus_ops standard_bus_ops = { - .write = snd_intel8x0_codec_write, - .read = snd_intel8x0_codec_read, - }; - static struct snd_ac97_bus_ops ali_bus_ops = { - .write = snd_intel8x0_ali_codec_write, - .read = snd_intel8x0_ali_codec_read, - }; - - chip->spdif_idx = -1; /* use PCMOUT (or disabled) */ - if (!spdif_aclink) { - switch (chip->device_type) { - case DEVICE_NFORCE: - chip->spdif_idx = NVD_SPBAR; - break; - case DEVICE_ALI: - chip->spdif_idx = ALID_AC97SPDIFOUT; - break; - case DEVICE_INTEL_ICH4: - chip->spdif_idx = ICHD_SPBAR; - break; - }; - } - - chip->in_ac97_init = 1; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_intel8x0_mixer_free_ac97; - ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE; - if (chip->xbox) - ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR; - if (chip->device_type != DEVICE_ALI) { - glob_sta = igetdword(chip, ICHREG(GLOB_STA)); - ops = &standard_bus_ops; - chip->in_sdin_init = 1; - codecs = 0; - for (i = 0; i < chip->max_codecs; i++) { - if (! (glob_sta & chip->codec_bit[i])) - continue; - if (chip->device_type == DEVICE_INTEL_ICH4) { - snd_intel8x0_codec_read_test(chip, codecs); - chip->ac97_sdin[codecs] = - igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; - if (snd_BUG_ON(chip->ac97_sdin[codecs] >= 3)) - chip->ac97_sdin[codecs] = 0; - } else - chip->ac97_sdin[codecs] = i; - codecs++; - } - chip->in_sdin_init = 0; - if (! codecs) - codecs = 1; - } else { - ops = &ali_bus_ops; - codecs = 1; - /* detect the secondary codec */ - for (i = 0; i < 100; i++) { - unsigned int reg = igetdword(chip, ICHREG(ALI_RTSR)); - if (reg & 0x40) { - codecs = 2; - break; - } - iputdword(chip, ICHREG(ALI_RTSR), reg | 0x40); - udelay(1); - } - } - if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0) - goto __err; - pbus->private_free = snd_intel8x0_mixer_free_ac97_bus; - if (ac97_clock >= 8000 && ac97_clock <= 48000) - pbus->clock = ac97_clock; - /* FIXME: my test board doesn't work well with VRA... */ - if (chip->device_type == DEVICE_ALI) - pbus->no_vra = 1; - else - pbus->dra = 1; - chip->ac97_bus = pbus; - chip->ncodecs = codecs; - - ac97.pci = chip->pci; - for (i = 0; i < codecs; i++) { - ac97.num = i; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { - if (err != -EACCES) - snd_printk(KERN_ERR "Unable to initialize codec #%d\n", i); - if (i == 0) - goto __err; - } - } - /* tune up the primary codec */ - snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override); - /* enable separate SDINs for ICH4 */ - if (chip->device_type == DEVICE_INTEL_ICH4) - pbus->isdin = 1; - /* find the available PCM streams */ - i = ARRAY_SIZE(ac97_pcm_defs); - if (chip->device_type != DEVICE_INTEL_ICH4) - i -= 2; /* do not allocate PCM2IN and MIC2 */ - if (chip->spdif_idx < 0) - i--; /* do not allocate S/PDIF */ - err = snd_ac97_pcm_assign(pbus, i, ac97_pcm_defs); - if (err < 0) - goto __err; - chip->ichd[ICHD_PCMOUT].pcm = &pbus->pcms[0]; - chip->ichd[ICHD_PCMIN].pcm = &pbus->pcms[1]; - chip->ichd[ICHD_MIC].pcm = &pbus->pcms[2]; - if (chip->spdif_idx >= 0) - chip->ichd[chip->spdif_idx].pcm = &pbus->pcms[3]; - if (chip->device_type == DEVICE_INTEL_ICH4) { - chip->ichd[ICHD_PCM2IN].pcm = &pbus->pcms[4]; - chip->ichd[ICHD_MIC2].pcm = &pbus->pcms[5]; - } - /* enable separate SDINs for ICH4 */ - if (chip->device_type == DEVICE_INTEL_ICH4) { - struct ac97_pcm *pcm = chip->ichd[ICHD_PCM2IN].pcm; - u8 tmp = igetbyte(chip, ICHREG(SDM)); - tmp &= ~(ICH_DI2L_MASK|ICH_DI1L_MASK); - if (pcm) { - tmp |= ICH_SE; /* steer enable for multiple SDINs */ - tmp |= chip->ac97_sdin[0] << ICH_DI1L_SHIFT; - for (i = 1; i < 4; i++) { - if (pcm->r[0].codec[i]) { - tmp |= chip->ac97_sdin[pcm->r[0].codec[1]->num] << ICH_DI2L_SHIFT; - break; - } - } - } else { - tmp &= ~ICH_SE; /* steer disable */ - } - iputbyte(chip, ICHREG(SDM), tmp); - } - if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) { - chip->multi4 = 1; - if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) { - chip->multi6 = 1; - if (chip->ac97[0]->flags & AC97_HAS_8CH) - chip->multi8 = 1; - } - } - if (pbus->pcms[0].r[1].rslots[0]) { - chip->dra = 1; - } - if (chip->device_type == DEVICE_INTEL_ICH4) { - if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20) - chip->smp20bit = 1; - } - if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) { - /* 48kHz only */ - chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000; - } - if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) { - /* use slot 10/11 for SPDIF */ - u32 val; - val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK; - val |= ICH_PCM_SPDIF_1011; - iputdword(chip, ICHREG(GLOB_CNT), val); - snd_ac97_update_bits(chip->ac97[0], AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4); - } - chip->in_ac97_init = 0; - return 0; - - __err: - /* clear the cold-reset bit for the next chance */ - if (chip->device_type != DEVICE_ALI) - iputdword(chip, ICHREG(GLOB_CNT), - igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD); - return err; -} - - -/* - * - */ - -static void do_ali_reset(struct intel8x0 *chip) -{ - iputdword(chip, ICHREG(ALI_SCR), ICH_ALI_SC_RESET); - iputdword(chip, ICHREG(ALI_FIFOCR1), 0x83838383); - iputdword(chip, ICHREG(ALI_FIFOCR2), 0x83838383); - iputdword(chip, ICHREG(ALI_FIFOCR3), 0x83838383); - iputdword(chip, ICHREG(ALI_INTERFACECR), - ICH_ALI_IF_PI|ICH_ALI_IF_PO); - iputdword(chip, ICHREG(ALI_INTERRUPTCR), 0x00000000); - iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000); -} - -#ifdef CONFIG_SND_AC97_POWER_SAVE -static struct snd_pci_quirk ich_chip_reset_mode[] = { - SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1), - { } /* end */ -}; - -static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip) -{ - unsigned int cnt; - /* ACLink on, 2 channels */ - - if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) - return -EIO; - - cnt = igetdword(chip, ICHREG(GLOB_CNT)); - cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); - - /* do cold reset - the full ac97 powerdown may leave the controller - * in a warm state but actually it cannot communicate with the codec. - */ - iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_AC97COLD); - cnt = igetdword(chip, ICHREG(GLOB_CNT)); - udelay(10); - iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); - msleep(1); - return 0; -} -#define snd_intel8x0_ich_chip_can_cold_reset(chip) \ - (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) -#else -#define snd_intel8x0_ich_chip_cold_reset(chip) 0 -#define snd_intel8x0_ich_chip_can_cold_reset(chip) (0) -#endif - -static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip) -{ - unsigned long end_time; - unsigned int cnt; - /* ACLink on, 2 channels */ - cnt = igetdword(chip, ICHREG(GLOB_CNT)); - cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); - /* finish cold or do warm reset */ - cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; - iputdword(chip, ICHREG(GLOB_CNT), cnt); - end_time = (jiffies + (HZ / 4)) + 1; - do { - if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) - return 0; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", - igetdword(chip, ICHREG(GLOB_CNT))); - return -EIO; -} - -static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) -{ - unsigned long end_time; - unsigned int status, nstatus; - unsigned int cnt; - int err; - - /* put logic to right state */ - /* first clear status bits */ - status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; - if (chip->device_type == DEVICE_NFORCE) - status |= ICH_NVSPINT; - cnt = igetdword(chip, ICHREG(GLOB_STA)); - iputdword(chip, ICHREG(GLOB_STA), cnt & status); - - if (snd_intel8x0_ich_chip_can_cold_reset(chip)) - err = snd_intel8x0_ich_chip_cold_reset(chip); - else - err = snd_intel8x0_ich_chip_reset(chip); - if (err < 0) - return err; - - if (probing) { - /* wait for any codec ready status. - * Once it becomes ready it should remain ready - * as long as we do not disable the ac97 link. - */ - end_time = jiffies + HZ; - do { - status = igetdword(chip, ICHREG(GLOB_STA)) & - chip->codec_isr_bits; - if (status) - break; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - if (! status) { - /* no codec is found */ - snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", - igetdword(chip, ICHREG(GLOB_STA))); - return -EIO; - } - - /* wait for other codecs ready status. */ - end_time = jiffies + HZ / 4; - while (status != chip->codec_isr_bits && - time_after_eq(end_time, jiffies)) { - schedule_timeout_uninterruptible(1); - status |= igetdword(chip, ICHREG(GLOB_STA)) & - chip->codec_isr_bits; - } - - } else { - /* resume phase */ - int i; - status = 0; - for (i = 0; i < chip->ncodecs; i++) - if (chip->ac97[i]) - status |= chip->codec_bit[chip->ac97_sdin[i]]; - /* wait until all the probed codecs are ready */ - end_time = jiffies + HZ; - do { - nstatus = igetdword(chip, ICHREG(GLOB_STA)) & - chip->codec_isr_bits; - if (status == nstatus) - break; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - } - - if (chip->device_type == DEVICE_SIS) { - /* unmute the output on SIS7012 */ - iputword(chip, 0x4c, igetword(chip, 0x4c) | 1); - } - if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) { - /* enable SPDIF interrupt */ - unsigned int val; - pci_read_config_dword(chip->pci, 0x4c, &val); - val |= 0x1000000; - pci_write_config_dword(chip->pci, 0x4c, val); - } - return 0; -} - -static int snd_intel8x0_ali_chip_init(struct intel8x0 *chip, int probing) -{ - u32 reg; - int i = 0; - - reg = igetdword(chip, ICHREG(ALI_SCR)); - if ((reg & 2) == 0) /* Cold required */ - reg |= 2; - else - reg |= 1; /* Warm */ - reg &= ~0x80000000; /* ACLink on */ - iputdword(chip, ICHREG(ALI_SCR), reg); - - for (i = 0; i < HZ / 2; i++) { - if (! (igetdword(chip, ICHREG(ALI_INTERRUPTSR)) & ALI_INT_GPIO)) - goto __ok; - schedule_timeout_uninterruptible(1); - } - snd_printk(KERN_ERR "AC'97 reset failed.\n"); - if (probing) - return -EIO; - - __ok: - for (i = 0; i < HZ / 2; i++) { - reg = igetdword(chip, ICHREG(ALI_RTSR)); - if (reg & 0x80) /* primary codec */ - break; - iputdword(chip, ICHREG(ALI_RTSR), reg | 0x80); - schedule_timeout_uninterruptible(1); - } - - do_ali_reset(chip); - return 0; -} - -static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) -{ - unsigned int i, timeout; - int err; - - if (chip->device_type != DEVICE_ALI) { - if ((err = snd_intel8x0_ich_chip_init(chip, probing)) < 0) - return err; - iagetword(chip, 0); /* clear semaphore flag */ - } else { - if ((err = snd_intel8x0_ali_chip_init(chip, probing)) < 0) - return err; - } - - /* disable interrupts */ - for (i = 0; i < chip->bdbars_count; i++) - iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, 0x00); - /* reset channels */ - for (i = 0; i < chip->bdbars_count; i++) - iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); - for (i = 0; i < chip->bdbars_count; i++) { - timeout = 100000; - while (--timeout != 0) { - if ((igetbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset) & ICH_RESETREGS) == 0) - break; - } - if (timeout == 0) - printk(KERN_ERR "intel8x0: reset of registers failed?\n"); - } - /* initialize Buffer Descriptor Lists */ - for (i = 0; i < chip->bdbars_count; i++) - iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, - chip->ichd[i].bdbar_addr); - return 0; -} - -static int snd_intel8x0_free(struct intel8x0 *chip) -{ - unsigned int i; - - if (chip->irq < 0) - goto __hw_end; - /* disable interrupts */ - for (i = 0; i < chip->bdbars_count; i++) - iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, 0x00); - /* reset channels */ - for (i = 0; i < chip->bdbars_count; i++) - iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); - if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) { - /* stop the spdif interrupt */ - unsigned int val; - pci_read_config_dword(chip->pci, 0x4c, &val); - val &= ~0x1000000; - pci_write_config_dword(chip->pci, 0x4c, val); - } - /* --- */ - - __hw_end: - if (chip->irq >= 0) - free_irq(chip->irq, chip); - if (chip->bdbars.area) { - if (chip->fix_nocache) - fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0); - snd_dma_free_pages(&chip->bdbars); - } - if (chip->addr) - pci_iounmap(chip->pci, chip->addr); - if (chip->bmaddr) - pci_iounmap(chip->pci, chip->bmaddr); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -#ifdef CONFIG_PM -/* - * power management - */ -static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct intel8x0 *chip = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < chip->pcm_devs; i++) - snd_pcm_suspend_all(chip->pcm[i]); - /* clear nocache */ - if (chip->fix_nocache) { - for (i = 0; i < chip->bdbars_count; i++) { - struct ichdev *ichdev = &chip->ichd[i]; - if (ichdev->substream && ichdev->page_attr_changed) { - struct snd_pcm_runtime *runtime = ichdev->substream->runtime; - if (runtime->dma_area) - fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); - } - } - } - for (i = 0; i < chip->ncodecs; i++) - snd_ac97_suspend(chip->ac97[i]); - if (chip->device_type == DEVICE_INTEL_ICH4) - chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); - - if (chip->irq >= 0) { - free_irq(chip->irq, chip); - chip->irq = -1; - } - pci_disable_device(pci); - pci_save_state(pci); - /* The call below may disable built-in speaker on some laptops - * after S2RAM. So, don't touch it. - */ - /* pci_set_power_state(pci, pci_choose_state(pci, state)); */ - return 0; -} - -static int intel8x0_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct intel8x0 *chip = card->private_data; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "intel8x0: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - snd_intel8x0_chip_init(chip, 0); - if (request_irq(pci->irq, snd_intel8x0_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "intel8x0: unable to grab IRQ %d, " - "disabling device\n", pci->irq); - snd_card_disconnect(card); - return -EIO; - } - chip->irq = pci->irq; - synchronize_irq(chip->irq); - - /* re-initialize mixer stuff */ - if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) { - /* enable separate SDINs for ICH4 */ - iputbyte(chip, ICHREG(SDM), chip->sdm_saved); - /* use slot 10/11 for SPDIF */ - iputdword(chip, ICHREG(GLOB_CNT), - (igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK) | - ICH_PCM_SPDIF_1011); - } - - /* refill nocache */ - if (chip->fix_nocache) - fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); - - for (i = 0; i < chip->ncodecs; i++) - snd_ac97_resume(chip->ac97[i]); - - /* refill nocache */ - if (chip->fix_nocache) { - for (i = 0; i < chip->bdbars_count; i++) { - struct ichdev *ichdev = &chip->ichd[i]; - if (ichdev->substream && ichdev->page_attr_changed) { - struct snd_pcm_runtime *runtime = ichdev->substream->runtime; - if (runtime->dma_area) - fill_nocache(runtime->dma_area, runtime->dma_bytes, 1); - } - } - } - - /* resume status */ - for (i = 0; i < chip->bdbars_count; i++) { - struct ichdev *ichdev = &chip->ichd[i]; - unsigned long port = ichdev->reg_offset; - if (! ichdev->substream || ! ichdev->suspended) - continue; - if (ichdev->ichd == ICHD_PCMOUT) - snd_intel8x0_setup_pcm_out(chip, ichdev->substream->runtime); - iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr); - iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi); - iputbyte(chip, port + ICH_REG_OFF_CIV, ichdev->civ); - iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); - } - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -#define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */ - -static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) -{ - struct snd_pcm_substream *subs; - struct ichdev *ichdev; - unsigned long port; - unsigned long pos, pos1, t; - 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"); - return; - } - ichdev = &chip->ichd[ICHD_PCMOUT]; - ichdev->physbuf = subs->dma_buffer.addr; - ichdev->size = ichdev->fragsize = INTEL8X0_TESTBUF_SIZE; - ichdev->substream = NULL; /* don't process interrupts */ - - /* set rate */ - if (snd_ac97_set_rate(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 48000) < 0) { - snd_printk(KERN_ERR "cannot set ac97 rate: clock = %d\n", chip->ac97_bus->clock); - return; - } - snd_intel8x0_setup_periods(chip, ichdev); - port = ichdev->reg_offset; - spin_lock_irq(&chip->reg_lock); - chip->in_measurement = 1; - /* trigger */ - if (chip->device_type != DEVICE_ALI) - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM); - else { - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); - iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot); - } - 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--); - 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 */ - if (chip->device_type == DEVICE_ALI) { - iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); - iputbyte(chip, port + ICH_REG_OFF_CR, 0); - while (igetbyte(chip, port + ICH_REG_OFF_CR)) - ; - } else { - iputbyte(chip, port + ICH_REG_OFF_CR, 0); - while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH)) - ; - } - 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"); - __retry: - if (attempt < 3) { - msleep(300); - attempt++; - goto __again; - } - goto __end; - } - - pos /= 4; - t = stop_time.tv_sec - start_time.tv_sec; - t *= 1000000; - 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 "intel8x0: ?? calculation error..\n"); - goto __retry; - } - 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); - goto __retry; - } 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; - __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); -} - -static struct snd_pci_quirk intel8x0_clock_list[] __devinitdata = { - SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000), - SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100), - SND_PCI_QUIRK(0x1028, 0x0177, "AD1980", 48000), - SND_PCI_QUIRK(0x1028, 0x01ad, "AD1981B", 48000), - SND_PCI_QUIRK(0x1043, 0x80f3, "AD1985", 48000), - { } /* terminator */ -}; - -static int __devinit intel8x0_in_clock_list(struct intel8x0 *chip) -{ - struct pci_dev *pci = chip->pci; - const struct snd_pci_quirk *wl; - - wl = snd_pci_quirk_lookup(pci, intel8x0_clock_list); - if (!wl) - return 0; - printk(KERN_INFO "intel8x0: white list rate for %04x:%04x is %i\n", - pci->subsystem_vendor, pci->subsystem_device, wl->value); - chip->ac97_bus->clock = wl->value; - return 1; -} - -#ifdef CONFIG_PROC_FS -static void snd_intel8x0_proc_read(struct snd_info_entry * entry, - struct snd_info_buffer *buffer) -{ - struct intel8x0 *chip = entry->private_data; - unsigned int tmp; - - snd_iprintf(buffer, "Intel8x0\n\n"); - if (chip->device_type == DEVICE_ALI) - return; - tmp = igetdword(chip, ICHREG(GLOB_STA)); - snd_iprintf(buffer, "Global control : 0x%08x\n", igetdword(chip, ICHREG(GLOB_CNT))); - snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); - if (chip->device_type == DEVICE_INTEL_ICH4) - snd_iprintf(buffer, "SDM : 0x%08x\n", igetdword(chip, ICHREG(SDM))); - snd_iprintf(buffer, "AC'97 codecs ready :"); - if (tmp & chip->codec_isr_bits) { - int i; - static const char *codecs[3] = { - "primary", "secondary", "tertiary" - }; - for (i = 0; i < chip->max_codecs; i++) - if (tmp & chip->codec_bit[i]) - snd_iprintf(buffer, " %s", codecs[i]); - } else - snd_iprintf(buffer, " none"); - snd_iprintf(buffer, "\n"); - if (chip->device_type == DEVICE_INTEL_ICH4 || - chip->device_type == DEVICE_SIS) - snd_iprintf(buffer, "AC'97 codecs SDIN : %i %i %i\n", - chip->ac97_sdin[0], - chip->ac97_sdin[1], - chip->ac97_sdin[2]); -} - -static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "intel8x0", &entry)) - snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read); -} -#else -#define snd_intel8x0_proc_init(x) -#endif - -static int snd_intel8x0_dev_free(struct snd_device *device) -{ - struct intel8x0 *chip = device->device_data; - return snd_intel8x0_free(chip); -} - -struct ich_reg_info { - unsigned int int_sta_mask; - unsigned int offset; -}; - -static unsigned int ich_codec_bits[3] = { - ICH_PCR, ICH_SCR, ICH_TCR -}; -static unsigned int sis_codec_bits[3] = { - ICH_PCR, ICH_SCR, ICH_SIS_TCR -}; - -static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci) -{ - int result = inside_vm; - char *msg = NULL; - - /* check module parameter first (override detection) */ - if (result >= 0) { - msg = result ? "enable (forced) VM" : "disable (forced) VM"; - goto fini; - } - - /* detect KVM and Parallels virtual environments */ - result = kvm_para_available(); -#ifdef X86_FEATURE_HYPERVISOR - result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR); -#endif - if (!result) - goto fini; - - /* check for known (emulated) devices */ - if (pci->subsystem_vendor == 0x1af4 && - pci->subsystem_device == 0x1100) { - /* KVM emulated sound, PCI SSID: 1af4:1100 */ - msg = "enable KVM"; - } else if (pci->subsystem_vendor == 0x1ab8) { - /* Parallels VM emulated sound, PCI SSID: 1ab8:xxxx */ - msg = "enable Parallels VM"; - } else { - msg = "disable (unknown or VT-d) VM"; - result = 0; - } - -fini: - if (msg != NULL) - printk(KERN_INFO "intel8x0: %s optimization\n", msg); - - return result; -} - -static int __devinit snd_intel8x0_create(struct snd_card *card, - struct pci_dev *pci, - unsigned long device_type, - struct intel8x0 ** r_intel8x0) -{ - struct intel8x0 *chip; - int err; - unsigned int i; - unsigned int int_sta_masks; - struct ichdev *ichdev; - static struct snd_device_ops ops = { - .dev_free = snd_intel8x0_dev_free, - }; - - static unsigned int bdbars[] = { - 3, /* DEVICE_INTEL */ - 6, /* DEVICE_INTEL_ICH4 */ - 3, /* DEVICE_SIS */ - 6, /* DEVICE_ALI */ - 4, /* DEVICE_NFORCE */ - }; - static struct ich_reg_info intel_regs[6] = { - { ICH_PIINT, 0 }, - { ICH_POINT, 0x10 }, - { ICH_MCINT, 0x20 }, - { ICH_M2INT, 0x40 }, - { ICH_P2INT, 0x50 }, - { ICH_SPINT, 0x60 }, - }; - static struct ich_reg_info nforce_regs[4] = { - { ICH_PIINT, 0 }, - { ICH_POINT, 0x10 }, - { ICH_MCINT, 0x20 }, - { ICH_NVSPINT, 0x70 }, - }; - static struct ich_reg_info ali_regs[6] = { - { ALI_INT_PCMIN, 0x40 }, - { ALI_INT_PCMOUT, 0x50 }, - { ALI_INT_MICIN, 0x60 }, - { ALI_INT_CODECSPDIFOUT, 0x70 }, - { ALI_INT_SPDIFIN, 0xa0 }, - { ALI_INT_SPDIFOUT, 0xb0 }, - }; - struct ich_reg_info *tbl; - - *r_intel8x0 = NULL; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&chip->reg_lock); - chip->device_type = device_type; - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - /* module parameters */ - chip->buggy_irq = buggy_irq; - chip->buggy_semaphore = buggy_semaphore; - if (xbox) - chip->xbox = 1; - - chip->inside_vm = snd_intel8x0_inside_vm(pci); - - if (pci->vendor == PCI_VENDOR_ID_INTEL && - pci->device == PCI_DEVICE_ID_INTEL_440MX) - chip->fix_nocache = 1; /* enable workaround */ - - if ((err = pci_request_regions(pci, card->shortname)) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - - if (device_type == DEVICE_ALI) { - /* ALI5455 has no ac97 region */ - chip->bmaddr = pci_iomap(pci, 0, 0); - goto port_inited; - } - - if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */ - chip->addr = pci_iomap(pci, 2, 0); - else - chip->addr = pci_iomap(pci, 0, 0); - if (!chip->addr) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); - snd_intel8x0_free(chip); - return -EIO; - } - if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */ - chip->bmaddr = pci_iomap(pci, 3, 0); - else - chip->bmaddr = pci_iomap(pci, 1, 0); - if (!chip->bmaddr) { - snd_printk(KERN_ERR "Controller space ioremap problem\n"); - snd_intel8x0_free(chip); - return -EIO; - } - - port_inited: - chip->bdbars_count = bdbars[device_type]; - - /* initialize offsets */ - switch (device_type) { - case DEVICE_NFORCE: - tbl = nforce_regs; - break; - case DEVICE_ALI: - tbl = ali_regs; - break; - default: - tbl = intel_regs; - break; - } - for (i = 0; i < chip->bdbars_count; i++) { - ichdev = &chip->ichd[i]; - ichdev->ichd = i; - ichdev->reg_offset = tbl[i].offset; - ichdev->int_sta_mask = tbl[i].int_sta_mask; - if (device_type == DEVICE_SIS) { - /* SiS 7012 swaps the registers */ - ichdev->roff_sr = ICH_REG_OFF_PICB; - ichdev->roff_picb = ICH_REG_OFF_SR; - } else { - ichdev->roff_sr = ICH_REG_OFF_SR; - ichdev->roff_picb = ICH_REG_OFF_PICB; - } - if (device_type == DEVICE_ALI) - ichdev->ali_slot = (ichdev->reg_offset - 0x40) / 0x10; - /* SIS7012 handles the pcm data in bytes, others are in samples */ - ichdev->pos_shift = (device_type == DEVICE_SIS) ? 0 : 1; - } - - /* allocate buffer descriptor lists */ - /* the start of each lists must be aligned to 8 bytes */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, - &chip->bdbars) < 0) { - snd_intel8x0_free(chip); - snd_printk(KERN_ERR "intel8x0: cannot allocate buffer descriptors\n"); - return -ENOMEM; - } - /* tables must be aligned to 8 bytes here, but the kernel pages - are much bigger, so we don't care (on i386) */ - /* workaround for 440MX */ - if (chip->fix_nocache) - fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); - int_sta_masks = 0; - for (i = 0; i < chip->bdbars_count; i++) { - ichdev = &chip->ichd[i]; - ichdev->bdbar = ((u32 *)chip->bdbars.area) + - (i * ICH_MAX_FRAGS * 2); - ichdev->bdbar_addr = chip->bdbars.addr + - (i * sizeof(u32) * ICH_MAX_FRAGS * 2); - int_sta_masks |= ichdev->int_sta_mask; - } - chip->int_sta_reg = device_type == DEVICE_ALI ? - ICH_REG_ALI_INTERRUPTSR : ICH_REG_GLOB_STA; - chip->int_sta_mask = int_sta_masks; - - pci_set_master(pci); - - switch(chip->device_type) { - case DEVICE_INTEL_ICH4: - /* ICH4 can have three codecs */ - chip->max_codecs = 3; - chip->codec_bit = ich_codec_bits; - chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_TRI; - break; - case DEVICE_SIS: - /* recent SIS7012 can have three codecs */ - chip->max_codecs = 3; - chip->codec_bit = sis_codec_bits; - chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_SIS_TRI; - break; - default: - /* others up to two codecs */ - chip->max_codecs = 2; - chip->codec_bit = ich_codec_bits; - chip->codec_ready_bits = ICH_PRI | ICH_SRI; - break; - } - for (i = 0; i < chip->max_codecs; i++) - chip->codec_isr_bits |= chip->codec_bit[i]; - - if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { - snd_intel8x0_free(chip); - return err; - } - - /* request irq after initializaing int_sta_mask, etc */ - if (request_irq(pci->irq, snd_intel8x0_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_intel8x0_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_intel8x0_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *r_intel8x0 = chip; - return 0; -} - -static struct shortname_table { - unsigned int id; - const char *s; -} shortnames[] __devinitdata = { - { PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" }, - { PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" }, - { PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" }, - { PCI_DEVICE_ID_INTEL_440MX, "Intel 440MX" }, - { PCI_DEVICE_ID_INTEL_82801CA_5, "Intel 82801CA-ICH3" }, - { PCI_DEVICE_ID_INTEL_82801DB_5, "Intel 82801DB-ICH4" }, - { PCI_DEVICE_ID_INTEL_82801EB_5, "Intel ICH5" }, - { PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" }, - { PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" }, - { PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" }, - { PCI_DEVICE_ID_INTEL_ESB2_14, "Intel ESB2" }, - { PCI_DEVICE_ID_SI_7012, "SiS SI7012" }, - { PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, "NVidia nForce" }, - { PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" }, - { PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" }, - { PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" }, - { PCI_DEVICE_ID_NVIDIA_CK804_AUDIO, "NVidia CK804" }, - { PCI_DEVICE_ID_NVIDIA_CK8_AUDIO, "NVidia CK8" }, - { 0x003a, "NVidia MCP04" }, - { 0x746d, "AMD AMD8111" }, - { 0x7445, "AMD AMD768" }, - { 0x5455, "ALi M5455" }, - { 0, NULL }, -}; - -static struct snd_pci_quirk spdif_aclink_defaults[] __devinitdata = { - SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1), - { } /* end */ -}; - -/* look up white/black list for SPDIF over ac-link */ -static int __devinit check_default_spdif_aclink(struct pci_dev *pci) -{ - const struct snd_pci_quirk *w; - - w = snd_pci_quirk_lookup(pci, spdif_aclink_defaults); - if (w) { - if (w->value) - snd_printdd(KERN_INFO "intel8x0: Using SPDIF over " - "AC-Link for %s\n", w->name); - else - snd_printdd(KERN_INFO "intel8x0: Using integrated " - "SPDIF DMA for %s\n", w->name); - return w->value; - } - return 0; -} - -static int __devinit snd_intel8x0_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct intel8x0 *chip; - int err; - struct shortname_table *name; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if (spdif_aclink < 0) - spdif_aclink = check_default_spdif_aclink(pci); - - strcpy(card->driver, "ICH"); - if (!spdif_aclink) { - switch (pci_id->driver_data) { - case DEVICE_NFORCE: - strcpy(card->driver, "NFORCE"); - break; - case DEVICE_INTEL_ICH4: - strcpy(card->driver, "ICH4"); - } - } - - strcpy(card->shortname, "Intel ICH"); - for (name = shortnames; name->id; name++) { - if (pci->device == name->id) { - strcpy(card->shortname, name->s); - break; - } - } - - if (buggy_irq < 0) { - /* some Nforce[2] and ICH boards have problems with IRQ handling. - * Needs to return IRQ_HANDLED for unknown irqs. - */ - if (pci_id->driver_data == DEVICE_NFORCE) - buggy_irq = 1; - else - buggy_irq = 0; - } - - if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, - &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - if ((err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_intel8x0_pcm(chip)) < 0) { - snd_card_free(card); - return err; - } - - snd_intel8x0_proc_init(chip); - - snprintf(card->longname, sizeof(card->longname), - "%s with %s at irq %i", card->shortname, - snd_ac97_get_short_name(chip->ac97[0]), chip->irq); - - if (ac97_clock == 0 || ac97_clock == 1) { - if (ac97_clock == 0) { - if (intel8x0_in_clock_list(chip) == 0) - intel8x0_measure_ac97_clock(chip); - } else { - intel8x0_measure_ac97_clock(chip); - } - } - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - return 0; -} - -static void __devexit snd_intel8x0_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_intel8x0_ids, - .probe = snd_intel8x0_probe, - .remove = __devexit_p(snd_intel8x0_remove), -#ifdef CONFIG_PM - .suspend = intel8x0_suspend, - .resume = intel8x0_resume, -#endif -}; - - -static int __init alsa_card_intel8x0_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_intel8x0_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_intel8x0_init) -module_exit(alsa_card_intel8x0_exit) diff --git a/ANDROID_3.4.5/sound/pci/intel8x0m.c b/ANDROID_3.4.5/sound/pci/intel8x0m.c deleted file mode 100644 index d689913a..00000000 --- a/ANDROID_3.4.5/sound/pci/intel8x0m.c +++ /dev/null @@ -1,1350 +0,0 @@ -/* - * ALSA modem driver for Intel ICH (i8x0) chipsets - * - * Copyright (c) 2000 Jaroslav Kysela - * - * This is modified (by Sasha Khapyorsky ) version - * of ALSA ICH sound driver intel8x0.c . - * - * - * 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 -#include -#include -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; " - "SiS 7013; NVidia MCP/2/2S/3 modems"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," - "{Intel,82901AB-ICH0}," - "{Intel,82801BA-ICH2}," - "{Intel,82801CA-ICH3}," - "{Intel,82801DB-ICH4}," - "{Intel,ICH5}," - "{Intel,ICH6}," - "{Intel,ICH7}," - "{Intel,MX440}," - "{SiS,7013}," - "{NVidia,NForce Modem}," - "{NVidia,NForce2 Modem}," - "{NVidia,NForce2s Modem}," - "{NVidia,NForce3 Modem}," - "{AMD,AMD768}}"); - -static int index = -2; /* Exclude the first card */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int ac97_clock; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for Intel i8x0 modemcard."); -module_param(ac97_clock, int, 0444); -MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); - -/* just for backward compatibility */ -static bool enable; -module_param(enable, bool, 0444); - -/* - * Direct registers - */ -enum { DEVICE_INTEL, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE }; - -#define ICHREG(x) ICH_REG_##x - -#define DEFINE_REGSET(name,base) \ -enum { \ - ICH_REG_##name##_BDBAR = base + 0x0, /* dword - buffer descriptor list base address */ \ - ICH_REG_##name##_CIV = base + 0x04, /* byte - current index value */ \ - ICH_REG_##name##_LVI = base + 0x05, /* byte - last valid index */ \ - ICH_REG_##name##_SR = base + 0x06, /* byte - status register */ \ - ICH_REG_##name##_PICB = base + 0x08, /* word - position in current buffer */ \ - ICH_REG_##name##_PIV = base + 0x0a, /* byte - prefetched index value */ \ - ICH_REG_##name##_CR = base + 0x0b, /* byte - control register */ \ -}; - -/* busmaster blocks */ -DEFINE_REGSET(OFF, 0); /* offset */ - -/* values for each busmaster block */ - -/* LVI */ -#define ICH_REG_LVI_MASK 0x1f - -/* SR */ -#define ICH_FIFOE 0x10 /* FIFO error */ -#define ICH_BCIS 0x08 /* buffer completion interrupt status */ -#define ICH_LVBCI 0x04 /* last valid buffer completion interrupt */ -#define ICH_CELV 0x02 /* current equals last valid */ -#define ICH_DCH 0x01 /* DMA controller halted */ - -/* PIV */ -#define ICH_REG_PIV_MASK 0x1f /* mask */ - -/* CR */ -#define ICH_IOCE 0x10 /* interrupt on completion enable */ -#define ICH_FEIE 0x08 /* fifo error interrupt enable */ -#define ICH_LVBIE 0x04 /* last valid buffer interrupt enable */ -#define ICH_RESETREGS 0x02 /* reset busmaster registers */ -#define ICH_STARTBM 0x01 /* start busmaster operation */ - - -/* global block */ -#define ICH_REG_GLOB_CNT 0x3c /* dword - global control */ -#define ICH_TRIE 0x00000040 /* tertiary resume interrupt enable */ -#define ICH_SRIE 0x00000020 /* secondary resume interrupt enable */ -#define ICH_PRIE 0x00000010 /* primary resume interrupt enable */ -#define ICH_ACLINK 0x00000008 /* AClink shut off */ -#define ICH_AC97WARM 0x00000004 /* AC'97 warm reset */ -#define ICH_AC97COLD 0x00000002 /* AC'97 cold reset */ -#define ICH_GIE 0x00000001 /* GPI interrupt enable */ -#define ICH_REG_GLOB_STA 0x40 /* dword - global status */ -#define ICH_TRI 0x20000000 /* ICH4: tertiary (AC_SDIN2) resume interrupt */ -#define ICH_TCR 0x10000000 /* ICH4: tertiary (AC_SDIN2) codec ready */ -#define ICH_BCS 0x08000000 /* ICH4: bit clock stopped */ -#define ICH_SPINT 0x04000000 /* ICH4: S/PDIF interrupt */ -#define ICH_P2INT 0x02000000 /* ICH4: PCM2-In interrupt */ -#define ICH_M2INT 0x01000000 /* ICH4: Mic2-In interrupt */ -#define ICH_SAMPLE_CAP 0x00c00000 /* ICH4: sample capability bits (RO) */ -#define ICH_MULTICHAN_CAP 0x00300000 /* ICH4: multi-channel capability bits (RO) */ -#define ICH_MD3 0x00020000 /* modem power down semaphore */ -#define ICH_AD3 0x00010000 /* audio power down semaphore */ -#define ICH_RCS 0x00008000 /* read completion status */ -#define ICH_BIT3 0x00004000 /* bit 3 slot 12 */ -#define ICH_BIT2 0x00002000 /* bit 2 slot 12 */ -#define ICH_BIT1 0x00001000 /* bit 1 slot 12 */ -#define ICH_SRI 0x00000800 /* secondary (AC_SDIN1) resume interrupt */ -#define ICH_PRI 0x00000400 /* primary (AC_SDIN0) resume interrupt */ -#define ICH_SCR 0x00000200 /* secondary (AC_SDIN1) codec ready */ -#define ICH_PCR 0x00000100 /* primary (AC_SDIN0) codec ready */ -#define ICH_MCINT 0x00000080 /* MIC capture interrupt */ -#define ICH_POINT 0x00000040 /* playback interrupt */ -#define ICH_PIINT 0x00000020 /* capture interrupt */ -#define ICH_NVSPINT 0x00000010 /* nforce spdif interrupt */ -#define ICH_MOINT 0x00000004 /* modem playback interrupt */ -#define ICH_MIINT 0x00000002 /* modem capture interrupt */ -#define ICH_GSCI 0x00000001 /* GPI status change interrupt */ -#define ICH_REG_ACC_SEMA 0x44 /* byte - codec write semaphore */ -#define ICH_CAS 0x01 /* codec access semaphore */ - -#define ICH_MAX_FRAGS 32 /* max hw frags */ - - -/* - * - */ - -enum { ICHD_MDMIN, ICHD_MDMOUT, ICHD_MDMLAST = ICHD_MDMOUT }; -enum { ALID_MDMIN, ALID_MDMOUT, ALID_MDMLAST = ALID_MDMOUT }; - -#define get_ichdev(substream) (substream->runtime->private_data) - -struct ichdev { - unsigned int ichd; /* ich device number */ - unsigned long reg_offset; /* offset to bmaddr */ - u32 *bdbar; /* CPU address (32bit) */ - unsigned int bdbar_addr; /* PCI bus address (32bit) */ - struct snd_pcm_substream *substream; - unsigned int physbuf; /* physical address (32bit) */ - unsigned int size; - unsigned int fragsize; - unsigned int fragsize1; - unsigned int position; - int frags; - int lvi; - int lvi_frag; - int civ; - int ack; - int ack_reload; - unsigned int ack_bit; - unsigned int roff_sr; - unsigned int roff_picb; - unsigned int int_sta_mask; /* interrupt status mask */ - unsigned int ali_slot; /* ALI DMA slot */ - struct snd_ac97 *ac97; -}; - -struct intel8x0m { - unsigned int device_type; - - int irq; - - void __iomem *addr; - void __iomem *bmaddr; - - struct pci_dev *pci; - struct snd_card *card; - - int pcm_devs; - struct snd_pcm *pcm[2]; - struct ichdev ichd[2]; - - unsigned int in_ac97_init: 1; - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97; - - spinlock_t reg_lock; - - struct snd_dma_buffer bdbars; - u32 bdbars_count; - u32 int_sta_reg; /* interrupt status register */ - u32 int_sta_mask; /* interrupt status mask */ - unsigned int pcm_pos_shift; -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0m_ids) = { - { PCI_VDEVICE(INTEL, 0x2416), DEVICE_INTEL }, /* 82801AA */ - { PCI_VDEVICE(INTEL, 0x2426), DEVICE_INTEL }, /* 82901AB */ - { PCI_VDEVICE(INTEL, 0x2446), DEVICE_INTEL }, /* 82801BA */ - { PCI_VDEVICE(INTEL, 0x2486), DEVICE_INTEL }, /* ICH3 */ - { PCI_VDEVICE(INTEL, 0x24c6), DEVICE_INTEL }, /* ICH4 */ - { PCI_VDEVICE(INTEL, 0x24d6), DEVICE_INTEL }, /* ICH5 */ - { PCI_VDEVICE(INTEL, 0x266d), DEVICE_INTEL }, /* ICH6 */ - { PCI_VDEVICE(INTEL, 0x27dd), DEVICE_INTEL }, /* ICH7 */ - { PCI_VDEVICE(INTEL, 0x7196), DEVICE_INTEL }, /* 440MX */ - { PCI_VDEVICE(AMD, 0x7446), DEVICE_INTEL }, /* AMD768 */ - { PCI_VDEVICE(SI, 0x7013), DEVICE_SIS }, /* SI7013 */ - { PCI_VDEVICE(NVIDIA, 0x01c1), DEVICE_NFORCE }, /* NFORCE */ - { PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */ - { PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */ - { PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */ - { PCI_VDEVICE(AMD, 0x746e), DEVICE_INTEL }, /* AMD8111 */ -#if 0 - { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ -#endif - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids); - -/* - * Lowlevel I/O - busmaster - */ - -static inline u8 igetbyte(struct intel8x0m *chip, u32 offset) -{ - return ioread8(chip->bmaddr + offset); -} - -static inline u16 igetword(struct intel8x0m *chip, u32 offset) -{ - return ioread16(chip->bmaddr + offset); -} - -static inline u32 igetdword(struct intel8x0m *chip, u32 offset) -{ - return ioread32(chip->bmaddr + offset); -} - -static inline void iputbyte(struct intel8x0m *chip, u32 offset, u8 val) -{ - iowrite8(val, chip->bmaddr + offset); -} - -static inline void iputword(struct intel8x0m *chip, u32 offset, u16 val) -{ - iowrite16(val, chip->bmaddr + offset); -} - -static inline void iputdword(struct intel8x0m *chip, u32 offset, u32 val) -{ - iowrite32(val, chip->bmaddr + offset); -} - -/* - * Lowlevel I/O - AC'97 registers - */ - -static inline u16 iagetword(struct intel8x0m *chip, u32 offset) -{ - return ioread16(chip->addr + offset); -} - -static inline void iaputword(struct intel8x0m *chip, u32 offset, u16 val) -{ - iowrite16(val, chip->addr + offset); -} - -/* - * Basic I/O - */ - -/* - * access to AC97 codec via normal i/o (for ICH and SIS7013) - */ - -/* return the GLOB_STA bit for the corresponding codec */ -static unsigned int get_ich_codec_bit(struct intel8x0m *chip, unsigned int codec) -{ - static unsigned int codec_bit[3] = { - ICH_PCR, ICH_SCR, ICH_TCR - }; - if (snd_BUG_ON(codec >= 3)) - return ICH_PCR; - return codec_bit[codec]; -} - -static int snd_intel8x0m_codec_semaphore(struct intel8x0m *chip, unsigned int codec) -{ - int time; - - if (codec > 1) - return -EIO; - codec = get_ich_codec_bit(chip, codec); - - /* codec ready ? */ - if ((igetdword(chip, ICHREG(GLOB_STA)) & codec) == 0) - return -EIO; - - /* Anyone holding a semaphore for 1 msec should be shot... */ - time = 100; - do { - if (!(igetbyte(chip, ICHREG(ACC_SEMA)) & ICH_CAS)) - return 0; - udelay(10); - } while (time--); - - /* access to some forbidden (non existent) ac97 registers will not - * reset the semaphore. So even if you don't get the semaphore, still - * continue the access. We don't need the semaphore anyway. */ - snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", - igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA))); - iagetword(chip, 0); /* clear semaphore flag */ - /* I don't care about the semaphore */ - return -EBUSY; -} - -static void snd_intel8x0m_codec_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct intel8x0m *chip = ac97->private_data; - - if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) { - if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); - } - iaputword(chip, reg + ac97->num * 0x80, val); -} - -static unsigned short snd_intel8x0m_codec_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct intel8x0m *chip = ac97->private_data; - unsigned short res; - unsigned int tmp; - - if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) { - if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); - res = 0xffff; - } else { - res = iagetword(chip, reg + ac97->num * 0x80); - if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { - /* reset RCS and preserve other R/WC bits */ - iputdword(chip, ICHREG(GLOB_STA), - tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); - if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); - res = 0xffff; - } - } - if (reg == AC97_GPIO_STATUS) - iagetword(chip, 0); /* clear semaphore */ - return res; -} - - -/* - * DMA I/O - */ -static void snd_intel8x0m_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev) -{ - int idx; - u32 *bdbar = ichdev->bdbar; - unsigned long port = ichdev->reg_offset; - - iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr); - if (ichdev->size == ichdev->fragsize) { - ichdev->ack_reload = ichdev->ack = 2; - ichdev->fragsize1 = ichdev->fragsize >> 1; - for (idx = 0; idx < (ICH_REG_LVI_MASK + 1) * 2; idx += 4) { - bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf); - bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ - ichdev->fragsize1 >> chip->pcm_pos_shift); - bdbar[idx + 2] = cpu_to_le32(ichdev->physbuf + (ichdev->size >> 1)); - bdbar[idx + 3] = cpu_to_le32(0x80000000 | /* interrupt on completion */ - ichdev->fragsize1 >> chip->pcm_pos_shift); - } - ichdev->frags = 2; - } else { - ichdev->ack_reload = ichdev->ack = 1; - ichdev->fragsize1 = ichdev->fragsize; - for (idx = 0; idx < (ICH_REG_LVI_MASK + 1) * 2; idx += 2) { - bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf + (((idx >> 1) * ichdev->fragsize) % ichdev->size)); - bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ - ichdev->fragsize >> chip->pcm_pos_shift); - /* - printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", - idx + 0, bdbar[idx + 0], bdbar[idx + 1]); - */ - } - ichdev->frags = ichdev->size / ichdev->fragsize; - } - iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi = ICH_REG_LVI_MASK); - ichdev->civ = 0; - iputbyte(chip, port + ICH_REG_OFF_CIV, 0); - ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; - ichdev->position = 0; -#if 0 - printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " - "period_size1 = 0x%x\n", - ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, - ichdev->fragsize1); -#endif - /* clear interrupts */ - iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); -} - -/* - * Interrupt handler - */ - -static inline void snd_intel8x0m_update(struct intel8x0m *chip, struct ichdev *ichdev) -{ - unsigned long port = ichdev->reg_offset; - int civ, i, step; - int ack = 0; - - civ = igetbyte(chip, port + ICH_REG_OFF_CIV); - if (civ == ichdev->civ) { - // snd_printd("civ same %d\n", civ); - step = 1; - ichdev->civ++; - ichdev->civ &= ICH_REG_LVI_MASK; - } else { - step = civ - ichdev->civ; - if (step < 0) - step += ICH_REG_LVI_MASK + 1; - // if (step != 1) - // snd_printd("step = %d, %d -> %d\n", step, ichdev->civ, civ); - ichdev->civ = civ; - } - - ichdev->position += step * ichdev->fragsize1; - ichdev->position %= ichdev->size; - ichdev->lvi += step; - ichdev->lvi &= ICH_REG_LVI_MASK; - iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi); - for (i = 0; i < step; i++) { - ichdev->lvi_frag++; - ichdev->lvi_frag %= ichdev->frags; - ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + - ichdev->lvi_frag * - ichdev->fragsize1); -#if 0 - printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], " - "prefetch = %i, all = 0x%x, 0x%x\n", - ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], - ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), - inl(port + 4), inb(port + ICH_REG_OFF_CR)); -#endif - if (--ichdev->ack == 0) { - ichdev->ack = ichdev->ack_reload; - ack = 1; - } - } - if (ack && ichdev->substream) { - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(ichdev->substream); - spin_lock(&chip->reg_lock); - } - iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); -} - -static irqreturn_t snd_intel8x0m_interrupt(int irq, void *dev_id) -{ - struct intel8x0m *chip = dev_id; - struct ichdev *ichdev; - unsigned int status; - unsigned int i; - - spin_lock(&chip->reg_lock); - status = igetdword(chip, chip->int_sta_reg); - if (status == 0xffffffff) { /* we are not yet resumed */ - spin_unlock(&chip->reg_lock); - return IRQ_NONE; - } - if ((status & chip->int_sta_mask) == 0) { - if (status) - iputdword(chip, chip->int_sta_reg, status); - spin_unlock(&chip->reg_lock); - return IRQ_NONE; - } - - for (i = 0; i < chip->bdbars_count; i++) { - ichdev = &chip->ichd[i]; - if (status & ichdev->int_sta_mask) - snd_intel8x0m_update(chip, ichdev); - } - - /* ack them */ - iputdword(chip, chip->int_sta_reg, status & chip->int_sta_mask); - spin_unlock(&chip->reg_lock); - - return IRQ_HANDLED; -} - -/* - * PCM part - */ - -static int snd_intel8x0m_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct intel8x0m *chip = snd_pcm_substream_chip(substream); - struct ichdev *ichdev = get_ichdev(substream); - unsigned char val = 0; - unsigned long port = ichdev->reg_offset; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - val = ICH_IOCE | ICH_STARTBM; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - val = 0; - break; - 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; - } - iputbyte(chip, port + ICH_REG_OFF_CR, val); - if (cmd == SNDRV_PCM_TRIGGER_STOP) { - /* wait until DMA stopped */ - while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH)) ; - /* reset whole DMA things */ - iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); - } - return 0; -} - -static int snd_intel8x0m_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_intel8x0m_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static snd_pcm_uframes_t snd_intel8x0m_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct intel8x0m *chip = snd_pcm_substream_chip(substream); - struct ichdev *ichdev = get_ichdev(substream); - size_t ptr1, ptr; - - ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << chip->pcm_pos_shift; - if (ptr1 != 0) - ptr = ichdev->fragsize1 - ptr1; - else - ptr = 0; - ptr += ichdev->position; - if (ptr >= ichdev->size) - return 0; - return bytes_to_frames(substream->runtime, ptr); -} - -static int snd_intel8x0m_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct intel8x0m *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct ichdev *ichdev = get_ichdev(substream); - - ichdev->physbuf = runtime->dma_addr; - ichdev->size = snd_pcm_lib_buffer_bytes(substream); - ichdev->fragsize = snd_pcm_lib_period_bytes(substream); - snd_ac97_write(ichdev->ac97, AC97_LINE1_RATE, runtime->rate); - snd_ac97_write(ichdev->ac97, AC97_LINE1_LEVEL, 0); - snd_intel8x0m_setup_periods(chip, ichdev); - return 0; -} - -static struct snd_pcm_hardware snd_intel8x0m_stream = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_KNOT, - .rate_min = 8000, - .rate_max = 16000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = 64 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 64 * 1024, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - - -static int snd_intel8x0m_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev) -{ - static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - ichdev->substream = substream; - runtime->hw = snd_intel8x0m_stream; - err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates); - if ( err < 0 ) - return err; - runtime->private_data = ichdev; - return 0; -} - -static int snd_intel8x0m_playback_open(struct snd_pcm_substream *substream) -{ - struct intel8x0m *chip = snd_pcm_substream_chip(substream); - - return snd_intel8x0m_pcm_open(substream, &chip->ichd[ICHD_MDMOUT]); -} - -static int snd_intel8x0m_playback_close(struct snd_pcm_substream *substream) -{ - struct intel8x0m *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ICHD_MDMOUT].substream = NULL; - return 0; -} - -static int snd_intel8x0m_capture_open(struct snd_pcm_substream *substream) -{ - struct intel8x0m *chip = snd_pcm_substream_chip(substream); - - return snd_intel8x0m_pcm_open(substream, &chip->ichd[ICHD_MDMIN]); -} - -static int snd_intel8x0m_capture_close(struct snd_pcm_substream *substream) -{ - struct intel8x0m *chip = snd_pcm_substream_chip(substream); - - chip->ichd[ICHD_MDMIN].substream = NULL; - return 0; -} - - -static struct snd_pcm_ops snd_intel8x0m_playback_ops = { - .open = snd_intel8x0m_playback_open, - .close = snd_intel8x0m_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0m_hw_params, - .hw_free = snd_intel8x0m_hw_free, - .prepare = snd_intel8x0m_pcm_prepare, - .trigger = snd_intel8x0m_pcm_trigger, - .pointer = snd_intel8x0m_pcm_pointer, -}; - -static struct snd_pcm_ops snd_intel8x0m_capture_ops = { - .open = snd_intel8x0m_capture_open, - .close = snd_intel8x0m_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_intel8x0m_hw_params, - .hw_free = snd_intel8x0m_hw_free, - .prepare = snd_intel8x0m_pcm_prepare, - .trigger = snd_intel8x0m_pcm_trigger, - .pointer = snd_intel8x0m_pcm_pointer, -}; - - -struct ich_pcm_table { - char *suffix; - struct snd_pcm_ops *playback_ops; - struct snd_pcm_ops *capture_ops; - size_t prealloc_size; - size_t prealloc_max_size; - int ac97_idx; -}; - -static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device, - struct ich_pcm_table *rec) -{ - struct snd_pcm *pcm; - int err; - char name[32]; - - if (rec->suffix) - sprintf(name, "Intel ICH - %s", rec->suffix); - else - strcpy(name, "Intel ICH"); - err = snd_pcm_new(chip->card, name, device, - rec->playback_ops ? 1 : 0, - rec->capture_ops ? 1 : 0, &pcm); - if (err < 0) - return err; - - if (rec->playback_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, rec->playback_ops); - if (rec->capture_ops) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, rec->capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - pcm->dev_class = SNDRV_PCM_CLASS_MODEM; - if (rec->suffix) - sprintf(pcm->name, "%s - %s", chip->card->shortname, rec->suffix); - else - strcpy(pcm->name, chip->card->shortname); - chip->pcm[device] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - rec->prealloc_size, - rec->prealloc_max_size); - - return 0; -} - -static struct ich_pcm_table intel_pcms[] __devinitdata = { - { - .suffix = "Modem", - .playback_ops = &snd_intel8x0m_playback_ops, - .capture_ops = &snd_intel8x0m_capture_ops, - .prealloc_size = 32 * 1024, - .prealloc_max_size = 64 * 1024, - }, -}; - -static int __devinit snd_intel8x0m_pcm(struct intel8x0m *chip) -{ - int i, tblsize, device, err; - struct ich_pcm_table *tbl, *rec; - -#if 1 - tbl = intel_pcms; - tblsize = 1; -#else - switch (chip->device_type) { - case DEVICE_NFORCE: - tbl = nforce_pcms; - tblsize = ARRAY_SIZE(nforce_pcms); - break; - case DEVICE_ALI: - tbl = ali_pcms; - tblsize = ARRAY_SIZE(ali_pcms); - break; - default: - tbl = intel_pcms; - tblsize = 2; - break; - } -#endif - device = 0; - for (i = 0; i < tblsize; i++) { - rec = tbl + i; - if (i > 0 && rec->ac97_idx) { - /* activate PCM only when associated AC'97 codec */ - if (! chip->ichd[rec->ac97_idx].ac97) - continue; - } - err = snd_intel8x0m_pcm1(chip, device, rec); - if (err < 0) - return err; - device++; - } - - chip->pcm_devs = device; - return 0; -} - - -/* - * Mixer part - */ - -static void snd_intel8x0m_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct intel8x0m *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void snd_intel8x0m_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct intel8x0m *chip = ac97->private_data; - chip->ac97 = NULL; -} - - -static int __devinit snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - struct snd_ac97 *x97; - int err; - unsigned int glob_sta = 0; - static struct snd_ac97_bus_ops ops = { - .write = snd_intel8x0m_codec_write, - .read = snd_intel8x0m_codec_read, - }; - - chip->in_ac97_init = 1; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_intel8x0m_mixer_free_ac97; - ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; - - glob_sta = igetdword(chip, ICHREG(GLOB_STA)); - - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) - goto __err; - pbus->private_free = snd_intel8x0m_mixer_free_ac97_bus; - if (ac97_clock >= 8000 && ac97_clock <= 48000) - pbus->clock = ac97_clock; - chip->ac97_bus = pbus; - - ac97.pci = chip->pci; - ac97.num = glob_sta & ICH_SCR ? 1 : 0; - if ((err = snd_ac97_mixer(pbus, &ac97, &x97)) < 0) { - snd_printk(KERN_ERR "Unable to initialize codec #%d\n", ac97.num); - if (ac97.num == 0) - goto __err; - return err; - } - chip->ac97 = x97; - if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97) { - chip->ichd[ICHD_MDMIN].ac97 = x97; - chip->ichd[ICHD_MDMOUT].ac97 = x97; - } - - chip->in_ac97_init = 0; - return 0; - - __err: - /* clear the cold-reset bit for the next chance */ - if (chip->device_type != DEVICE_ALI) - iputdword(chip, ICHREG(GLOB_CNT), - igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD); - return err; -} - - -/* - * - */ - -static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing) -{ - unsigned long end_time; - unsigned int cnt, status, nstatus; - - /* put logic to right state */ - /* first clear status bits */ - status = ICH_RCS | ICH_MIINT | ICH_MOINT; - cnt = igetdword(chip, ICHREG(GLOB_STA)); - iputdword(chip, ICHREG(GLOB_STA), cnt & status); - - /* ACLink on, 2 channels */ - cnt = igetdword(chip, ICHREG(GLOB_CNT)); - cnt &= ~(ICH_ACLINK); - /* finish cold or do warm reset */ - cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; - iputdword(chip, ICHREG(GLOB_CNT), cnt); - usleep_range(500, 1000); /* give warm reset some time */ - end_time = jiffies + HZ / 4; - do { - if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) - goto __ok; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", - igetdword(chip, ICHREG(GLOB_CNT))); - return -EIO; - - __ok: - if (probing) { - /* wait for any codec ready status. - * Once it becomes ready it should remain ready - * as long as we do not disable the ac97 link. - */ - end_time = jiffies + HZ; - do { - status = igetdword(chip, ICHREG(GLOB_STA)) & - (ICH_PCR | ICH_SCR | ICH_TCR); - if (status) - break; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - if (! status) { - /* no codec is found */ - snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", - igetdword(chip, ICHREG(GLOB_STA))); - return -EIO; - } - - /* up to two codecs (modem cannot be tertiary with ICH4) */ - nstatus = ICH_PCR | ICH_SCR; - - /* wait for other codecs ready status. */ - end_time = jiffies + HZ / 4; - while (status != nstatus && time_after_eq(end_time, jiffies)) { - schedule_timeout_uninterruptible(1); - status |= igetdword(chip, ICHREG(GLOB_STA)) & nstatus; - } - - } else { - /* resume phase */ - status = 0; - if (chip->ac97) - status |= get_ich_codec_bit(chip, chip->ac97->num); - /* wait until all the probed codecs are ready */ - end_time = jiffies + HZ; - do { - nstatus = igetdword(chip, ICHREG(GLOB_STA)) & - (ICH_PCR | ICH_SCR | ICH_TCR); - if (status == nstatus) - break; - schedule_timeout_uninterruptible(1); - } while (time_after_eq(end_time, jiffies)); - } - - if (chip->device_type == DEVICE_SIS) { - /* unmute the output on SIS7012 */ - iputword(chip, 0x4c, igetword(chip, 0x4c) | 1); - } - - return 0; -} - -static int snd_intel8x0m_chip_init(struct intel8x0m *chip, int probing) -{ - unsigned int i; - int err; - - if ((err = snd_intel8x0m_ich_chip_init(chip, probing)) < 0) - return err; - iagetword(chip, 0); /* clear semaphore flag */ - - /* disable interrupts */ - for (i = 0; i < chip->bdbars_count; i++) - iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, 0x00); - /* reset channels */ - for (i = 0; i < chip->bdbars_count; i++) - iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); - /* initialize Buffer Descriptor Lists */ - for (i = 0; i < chip->bdbars_count; i++) - iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, chip->ichd[i].bdbar_addr); - return 0; -} - -static int snd_intel8x0m_free(struct intel8x0m *chip) -{ - unsigned int i; - - if (chip->irq < 0) - goto __hw_end; - /* disable interrupts */ - for (i = 0; i < chip->bdbars_count; i++) - iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, 0x00); - /* reset channels */ - for (i = 0; i < chip->bdbars_count; i++) - iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); - __hw_end: - if (chip->irq >= 0) - free_irq(chip->irq, chip); - if (chip->bdbars.area) - snd_dma_free_pages(&chip->bdbars); - if (chip->addr) - pci_iounmap(chip->pci, chip->addr); - if (chip->bmaddr) - pci_iounmap(chip->pci, chip->bmaddr); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -#ifdef CONFIG_PM -/* - * power management - */ -static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct intel8x0m *chip = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < chip->pcm_devs; i++) - snd_pcm_suspend_all(chip->pcm[i]); - snd_ac97_suspend(chip->ac97); - if (chip->irq >= 0) { - free_irq(chip->irq, chip); - chip->irq = -1; - } - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int intel8x0m_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct intel8x0m *chip = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "intel8x0m: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - if (request_irq(pci->irq, snd_intel8x0m_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, " - "disabling device\n", pci->irq); - snd_card_disconnect(card); - return -EIO; - } - chip->irq = pci->irq; - snd_intel8x0m_chip_init(chip, 0); - snd_ac97_resume(chip->ac97); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -#ifdef CONFIG_PROC_FS -static void snd_intel8x0m_proc_read(struct snd_info_entry * entry, - struct snd_info_buffer *buffer) -{ - struct intel8x0m *chip = entry->private_data; - unsigned int tmp; - - snd_iprintf(buffer, "Intel8x0m\n\n"); - if (chip->device_type == DEVICE_ALI) - return; - tmp = igetdword(chip, ICHREG(GLOB_STA)); - snd_iprintf(buffer, "Global control : 0x%08x\n", - igetdword(chip, ICHREG(GLOB_CNT))); - snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); - snd_iprintf(buffer, "AC'97 codecs ready :%s%s%s%s\n", - tmp & ICH_PCR ? " primary" : "", - tmp & ICH_SCR ? " secondary" : "", - tmp & ICH_TCR ? " tertiary" : "", - (tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : ""); -} - -static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "intel8x0m", &entry)) - snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read); -} -#else /* !CONFIG_PROC_FS */ -#define snd_intel8x0m_proc_init(chip) -#endif /* CONFIG_PROC_FS */ - - -static int snd_intel8x0m_dev_free(struct snd_device *device) -{ - struct intel8x0m *chip = device->device_data; - return snd_intel8x0m_free(chip); -} - -struct ich_reg_info { - unsigned int int_sta_mask; - unsigned int offset; -}; - -static int __devinit snd_intel8x0m_create(struct snd_card *card, - struct pci_dev *pci, - unsigned long device_type, - struct intel8x0m **r_intel8x0m) -{ - struct intel8x0m *chip; - int err; - unsigned int i; - unsigned int int_sta_masks; - struct ichdev *ichdev; - static struct snd_device_ops ops = { - .dev_free = snd_intel8x0m_dev_free, - }; - static struct ich_reg_info intel_regs[2] = { - { ICH_MIINT, 0 }, - { ICH_MOINT, 0x10 }, - }; - struct ich_reg_info *tbl; - - *r_intel8x0m = NULL; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&chip->reg_lock); - chip->device_type = device_type; - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - if ((err = pci_request_regions(pci, card->shortname)) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - - if (device_type == DEVICE_ALI) { - /* ALI5455 has no ac97 region */ - chip->bmaddr = pci_iomap(pci, 0, 0); - goto port_inited; - } - - if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */ - chip->addr = pci_iomap(pci, 2, 0); - else - chip->addr = pci_iomap(pci, 0, 0); - if (!chip->addr) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); - snd_intel8x0m_free(chip); - return -EIO; - } - if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */ - chip->bmaddr = pci_iomap(pci, 3, 0); - else - chip->bmaddr = pci_iomap(pci, 1, 0); - if (!chip->bmaddr) { - snd_printk(KERN_ERR "Controller space ioremap problem\n"); - snd_intel8x0m_free(chip); - return -EIO; - } - - port_inited: - if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_intel8x0m_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - pci_set_master(pci); - synchronize_irq(chip->irq); - - /* initialize offsets */ - chip->bdbars_count = 2; - tbl = intel_regs; - - for (i = 0; i < chip->bdbars_count; i++) { - ichdev = &chip->ichd[i]; - ichdev->ichd = i; - ichdev->reg_offset = tbl[i].offset; - ichdev->int_sta_mask = tbl[i].int_sta_mask; - if (device_type == DEVICE_SIS) { - /* SiS 7013 swaps the registers */ - ichdev->roff_sr = ICH_REG_OFF_PICB; - ichdev->roff_picb = ICH_REG_OFF_SR; - } else { - ichdev->roff_sr = ICH_REG_OFF_SR; - ichdev->roff_picb = ICH_REG_OFF_PICB; - } - if (device_type == DEVICE_ALI) - ichdev->ali_slot = (ichdev->reg_offset - 0x40) / 0x10; - } - /* SIS7013 handles the pcm data in bytes, others are in words */ - chip->pcm_pos_shift = (device_type == DEVICE_SIS) ? 0 : 1; - - /* allocate buffer descriptor lists */ - /* the start of each lists must be aligned to 8 bytes */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, - &chip->bdbars) < 0) { - snd_intel8x0m_free(chip); - return -ENOMEM; - } - /* tables must be aligned to 8 bytes here, but the kernel pages - are much bigger, so we don't care (on i386) */ - int_sta_masks = 0; - for (i = 0; i < chip->bdbars_count; i++) { - ichdev = &chip->ichd[i]; - ichdev->bdbar = ((u32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2); - ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2); - int_sta_masks |= ichdev->int_sta_mask; - } - chip->int_sta_reg = ICH_REG_GLOB_STA; - chip->int_sta_mask = int_sta_masks; - - if ((err = snd_intel8x0m_chip_init(chip, 1)) < 0) { - snd_intel8x0m_free(chip); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_intel8x0m_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *r_intel8x0m = chip; - return 0; -} - -static struct shortname_table { - unsigned int id; - const char *s; -} shortnames[] __devinitdata = { - { PCI_DEVICE_ID_INTEL_82801AA_6, "Intel 82801AA-ICH" }, - { PCI_DEVICE_ID_INTEL_82801AB_6, "Intel 82901AB-ICH0" }, - { PCI_DEVICE_ID_INTEL_82801BA_6, "Intel 82801BA-ICH2" }, - { PCI_DEVICE_ID_INTEL_440MX_6, "Intel 440MX" }, - { PCI_DEVICE_ID_INTEL_82801CA_6, "Intel 82801CA-ICH3" }, - { PCI_DEVICE_ID_INTEL_82801DB_6, "Intel 82801DB-ICH4" }, - { PCI_DEVICE_ID_INTEL_82801EB_6, "Intel ICH5" }, - { PCI_DEVICE_ID_INTEL_ICH6_17, "Intel ICH6" }, - { PCI_DEVICE_ID_INTEL_ICH7_19, "Intel ICH7" }, - { 0x7446, "AMD AMD768" }, - { PCI_DEVICE_ID_SI_7013, "SiS SI7013" }, - { PCI_DEVICE_ID_NVIDIA_MCP1_MODEM, "NVidia nForce" }, - { PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" }, - { PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" }, - { PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" }, - { 0x746e, "AMD AMD8111" }, -#if 0 - { 0x5455, "ALi M5455" }, -#endif - { 0 }, -}; - -static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct intel8x0m *chip; - int err; - struct shortname_table *name; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - strcpy(card->driver, "ICH-MODEM"); - strcpy(card->shortname, "Intel ICH"); - for (name = shortnames; name->id; name++) { - if (pci->device == name->id) { - strcpy(card->shortname, name->s); - break; - } - } - strcat(card->shortname," Modem"); - - if ((err = snd_intel8x0m_create(card, pci, pci_id->driver_data, &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - if ((err = snd_intel8x0m_mixer(chip, ac97_clock)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_intel8x0m_pcm(chip)) < 0) { - snd_card_free(card); - return err; - } - - snd_intel8x0m_proc_init(chip); - - sprintf(card->longname, "%s at irq %i", - card->shortname, chip->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - return 0; -} - -static void __devexit snd_intel8x0m_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_intel8x0m_ids, - .probe = snd_intel8x0m_probe, - .remove = __devexit_p(snd_intel8x0m_remove), -#ifdef CONFIG_PM - .suspend = intel8x0m_suspend, - .resume = intel8x0m_resume, -#endif -}; - - -static int __init alsa_card_intel8x0m_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_intel8x0m_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_intel8x0m_init) -module_exit(alsa_card_intel8x0m_exit) diff --git a/ANDROID_3.4.5/sound/pci/korg1212/Makefile b/ANDROID_3.4.5/sound/pci/korg1212/Makefile deleted file mode 100644 index f11ce1b1..00000000 --- a/ANDROID_3.4.5/sound/pci/korg1212/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-korg1212-objs := korg1212.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_KORG1212) += snd-korg1212.o diff --git a/ANDROID_3.4.5/sound/pci/korg1212/korg1212.c b/ANDROID_3.4.5/sound/pci/korg1212/korg1212.c deleted file mode 100644 index 8fea45ab..00000000 --- a/ANDROID_3.4.5/sound/pci/korg1212/korg1212.c +++ /dev/null @@ -1,2497 +0,0 @@ -/* - * Driver for the Korg 1212 IO PCI card - * - * Copyright (c) 2001 Haroldo Gamal - * - * 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 - -#include -#include -#include -#include -#include -#include - -#include - -// ---------------------------------------------------------------------------- -// Debug Stuff -// ---------------------------------------------------------------------------- -#define K1212_DEBUG_LEVEL 0 -#if K1212_DEBUG_LEVEL > 0 -#define K1212_DEBUG_PRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args) -#else -#define K1212_DEBUG_PRINTK(fmt,...) -#endif -#if K1212_DEBUG_LEVEL > 1 -#define K1212_DEBUG_PRINTK_VERBOSE(fmt,args...) printk(KERN_DEBUG fmt,##args) -#else -#define K1212_DEBUG_PRINTK_VERBOSE(fmt,...) -#endif - -// ---------------------------------------------------------------------------- -// Record/Play Buffer Allocation Method. If K1212_LARGEALLOC is defined all -// buffers are alocated as a large piece inside KorgSharedBuffer. -// ---------------------------------------------------------------------------- -//#define K1212_LARGEALLOC 1 - -// ---------------------------------------------------------------------------- -// Valid states of the Korg 1212 I/O card. -// ---------------------------------------------------------------------------- -enum CardState { - K1212_STATE_NONEXISTENT, // there is no card here - K1212_STATE_UNINITIALIZED, // the card is awaiting DSP download - K1212_STATE_DSP_IN_PROCESS, // the card is currently downloading its DSP code - K1212_STATE_DSP_COMPLETE, // the card has finished the DSP download - K1212_STATE_READY, // the card can be opened by an application. Any application - // requests prior to this state should fail. Only an open - // request can be made at this state. - K1212_STATE_OPEN, // an application has opened the card - K1212_STATE_SETUP, // the card has been setup for play - K1212_STATE_PLAYING, // the card is playing - K1212_STATE_MONITOR, // the card is in the monitor mode - K1212_STATE_CALIBRATING, // the card is currently calibrating - K1212_STATE_ERRORSTOP, // the card has stopped itself because of an error and we - // are in the process of cleaning things up. - K1212_STATE_MAX_STATE // state values of this and beyond are invalid -}; - -// ---------------------------------------------------------------------------- -// The following enumeration defines the constants written to the card's -// host-to-card doorbell to initiate a command. -// ---------------------------------------------------------------------------- -enum korg1212_dbcnst { - K1212_DB_RequestForData = 0, // sent by the card to request a buffer fill. - K1212_DB_TriggerPlay = 1, // starts playback/record on the card. - K1212_DB_SelectPlayMode = 2, // select monitor, playback setup, or stop. - K1212_DB_ConfigureBufferMemory = 3, // tells card where the host audio buffers are. - K1212_DB_RequestAdatTimecode = 4, // asks the card for the latest ADAT timecode value. - K1212_DB_SetClockSourceRate = 5, // sets the clock source and rate for the card. - K1212_DB_ConfigureMiscMemory = 6, // tells card where other buffers are. - K1212_DB_TriggerFromAdat = 7, // tells card to trigger from Adat at a specific - // timecode value. - K1212_DB_DMAERROR = 0x80, // DMA Error - the PCI bus is congestioned. - K1212_DB_CARDSTOPPED = 0x81, // Card has stopped by user request. - K1212_DB_RebootCard = 0xA0, // instructs the card to reboot. - K1212_DB_BootFromDSPPage4 = 0xA4, // instructs the card to boot from the DSP microcode - // on page 4 (local page to card). - K1212_DB_DSPDownloadDone = 0xAE, // sent by the card to indicate the download has - // completed. - K1212_DB_StartDSPDownload = 0xAF // tells the card to download its DSP firmware. -}; - - -// ---------------------------------------------------------------------------- -// The following enumeration defines return codes -// to the Korg 1212 I/O driver. -// ---------------------------------------------------------------------------- -enum snd_korg1212rc { - K1212_CMDRET_Success = 0, // command was successfully placed - K1212_CMDRET_DIOCFailure, // the DeviceIoControl call failed - K1212_CMDRET_PMFailure, // the protected mode call failed - K1212_CMDRET_FailUnspecified, // unspecified failure - K1212_CMDRET_FailBadState, // the specified command can not be given in - // the card's current state. (or the wave device's - // state) - K1212_CMDRET_CardUninitialized, // the card is uninitialized and cannot be used - K1212_CMDRET_BadIndex, // an out of range card index was specified - K1212_CMDRET_BadHandle, // an invalid card handle was specified - K1212_CMDRET_NoFillRoutine, // a play request has been made before a fill routine set - K1212_CMDRET_FillRoutineInUse, // can't set a new fill routine while one is in use - K1212_CMDRET_NoAckFromCard, // the card never acknowledged a command - K1212_CMDRET_BadParams, // bad parameters were provided by the caller - - K1212_CMDRET_BadDevice, // the specified wave device was out of range - K1212_CMDRET_BadFormat // the specified wave format is unsupported -}; - -// ---------------------------------------------------------------------------- -// The following enumeration defines the constants used to select the play -// mode for the card in the SelectPlayMode command. -// ---------------------------------------------------------------------------- -enum PlayModeSelector { - K1212_MODE_SetupPlay = 0x00000001, // provides card with pre-play information - K1212_MODE_MonitorOn = 0x00000002, // tells card to turn on monitor mode - K1212_MODE_MonitorOff = 0x00000004, // tells card to turn off monitor mode - K1212_MODE_StopPlay = 0x00000008 // stops playback on the card -}; - -// ---------------------------------------------------------------------------- -// The following enumeration defines the constants used to select the monitor -// mode for the card in the SetMonitorMode command. -// ---------------------------------------------------------------------------- -enum MonitorModeSelector { - K1212_MONMODE_Off = 0, // tells card to turn off monitor mode - K1212_MONMODE_On // tells card to turn on monitor mode -}; - -#define MAILBOX0_OFFSET 0x40 // location of mailbox 0 relative to base address -#define MAILBOX1_OFFSET 0x44 // location of mailbox 1 relative to base address -#define MAILBOX2_OFFSET 0x48 // location of mailbox 2 relative to base address -#define MAILBOX3_OFFSET 0x4c // location of mailbox 3 relative to base address -#define OUT_DOORBELL_OFFSET 0x60 // location of PCI to local doorbell -#define IN_DOORBELL_OFFSET 0x64 // location of local to PCI doorbell -#define STATUS_REG_OFFSET 0x68 // location of interrupt control/status register -#define PCI_CONTROL_OFFSET 0x6c // location of the EEPROM, PCI, User I/O, init control - // register -#define SENS_CONTROL_OFFSET 0x6e // location of the input sensitivity setting register. - // this is the upper word of the PCI control reg. -#define DEV_VEND_ID_OFFSET 0x70 // location of the device and vendor ID register - -#define MAX_COMMAND_RETRIES 5 // maximum number of times the driver will attempt - // to send a command before giving up. -#define COMMAND_ACK_MASK 0x8000 // the MSB is set in the command acknowledgment from - // the card. -#define DOORBELL_VAL_MASK 0x00FF // the doorbell value is one byte - -#define CARD_BOOT_DELAY_IN_MS 10 -#define CARD_BOOT_TIMEOUT 10 -#define DSP_BOOT_DELAY_IN_MS 200 - -#define kNumBuffers 8 -#define k1212MaxCards 4 -#define k1212NumWaveDevices 6 -#define k16BitChannels 10 -#define k32BitChannels 2 -#define kAudioChannels (k16BitChannels + k32BitChannels) -#define kPlayBufferFrames 1024 - -#define K1212_ANALOG_CHANNELS 2 -#define K1212_SPDIF_CHANNELS 2 -#define K1212_ADAT_CHANNELS 8 -#define K1212_CHANNELS (K1212_ADAT_CHANNELS + K1212_ANALOG_CHANNELS) -#define K1212_MIN_CHANNELS 1 -#define K1212_MAX_CHANNELS K1212_CHANNELS -#define K1212_FRAME_SIZE (sizeof(struct KorgAudioFrame)) -#define K1212_MAX_SAMPLES (kPlayBufferFrames*kNumBuffers) -#define K1212_PERIODS (kNumBuffers) -#define K1212_PERIOD_BYTES (K1212_FRAME_SIZE*kPlayBufferFrames) -#define K1212_BUF_SIZE (K1212_PERIOD_BYTES*kNumBuffers) -#define K1212_ANALOG_BUF_SIZE (K1212_ANALOG_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers) -#define K1212_SPDIF_BUF_SIZE (K1212_SPDIF_CHANNELS * 3 * kPlayBufferFrames * kNumBuffers) -#define K1212_ADAT_BUF_SIZE (K1212_ADAT_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers) -#define K1212_MAX_BUF_SIZE (K1212_ANALOG_BUF_SIZE + K1212_ADAT_BUF_SIZE) - -#define k1212MinADCSens 0x7f -#define k1212MaxADCSens 0x00 -#define k1212MaxVolume 0x7fff -#define k1212MaxWaveVolume 0xffff -#define k1212MinVolume 0x0000 -#define k1212MaxVolInverted 0x8000 - -// ----------------------------------------------------------------- -// the following bits are used for controlling interrupts in the -// interrupt control/status reg -// ----------------------------------------------------------------- -#define PCI_INT_ENABLE_BIT 0x00000100 -#define PCI_DOORBELL_INT_ENABLE_BIT 0x00000200 -#define LOCAL_INT_ENABLE_BIT 0x00010000 -#define LOCAL_DOORBELL_INT_ENABLE_BIT 0x00020000 -#define LOCAL_DMA1_INT_ENABLE_BIT 0x00080000 - -// ----------------------------------------------------------------- -// the following bits are defined for the PCI command register -// ----------------------------------------------------------------- -#define PCI_CMD_MEM_SPACE_ENABLE_BIT 0x0002 -#define PCI_CMD_IO_SPACE_ENABLE_BIT 0x0001 -#define PCI_CMD_BUS_MASTER_ENABLE_BIT 0x0004 - -// ----------------------------------------------------------------- -// the following bits are defined for the PCI status register -// ----------------------------------------------------------------- -#define PCI_STAT_PARITY_ERROR_BIT 0x8000 -#define PCI_STAT_SYSTEM_ERROR_BIT 0x4000 -#define PCI_STAT_MASTER_ABORT_RCVD_BIT 0x2000 -#define PCI_STAT_TARGET_ABORT_RCVD_BIT 0x1000 -#define PCI_STAT_TARGET_ABORT_SENT_BIT 0x0800 - -// ------------------------------------------------------------------------ -// the following constants are used in setting the 1212 I/O card's input -// sensitivity. -// ------------------------------------------------------------------------ -#define SET_SENS_LOCALINIT_BITPOS 15 -#define SET_SENS_DATA_BITPOS 10 -#define SET_SENS_CLOCK_BITPOS 8 -#define SET_SENS_LOADSHIFT_BITPOS 0 - -#define SET_SENS_LEFTCHANID 0x00 -#define SET_SENS_RIGHTCHANID 0x01 - -#define K1212SENSUPDATE_DELAY_IN_MS 50 - -// -------------------------------------------------------------------------- -// WaitRTCTicks -// -// This function waits the specified number of real time clock ticks. -// According to the DDK, each tick is ~0.8 microseconds. -// The defines following the function declaration can be used for the -// numTicksToWait parameter. -// -------------------------------------------------------------------------- -#define ONE_RTC_TICK 1 -#define SENSCLKPULSE_WIDTH 4 -#define LOADSHIFT_DELAY 4 -#define INTERCOMMAND_DELAY 40 -#define STOPCARD_DELAY 300 // max # RTC ticks for the card to stop once we write - // the command register. (could be up to 180 us) -#define COMMAND_ACK_DELAY 13 // number of RTC ticks to wait for an acknowledgement - // from the card after sending a command. - -enum ClockSourceIndex { - K1212_CLKIDX_AdatAt44_1K = 0, // selects source as ADAT at 44.1 kHz - K1212_CLKIDX_AdatAt48K, // selects source as ADAT at 48 kHz - K1212_CLKIDX_WordAt44_1K, // selects source as S/PDIF at 44.1 kHz - K1212_CLKIDX_WordAt48K, // selects source as S/PDIF at 48 kHz - K1212_CLKIDX_LocalAt44_1K, // selects source as local clock at 44.1 kHz - K1212_CLKIDX_LocalAt48K, // selects source as local clock at 48 kHz - K1212_CLKIDX_Invalid // used to check validity of the index -}; - -enum ClockSourceType { - K1212_CLKIDX_Adat = 0, // selects source as ADAT - K1212_CLKIDX_Word, // selects source as S/PDIF - K1212_CLKIDX_Local // selects source as local clock -}; - -struct KorgAudioFrame { - u16 frameData16[k16BitChannels]; /* channels 0-9 use 16 bit samples */ - u32 frameData32[k32BitChannels]; /* channels 10-11 use 32 bits - only 20 are sent across S/PDIF */ - u32 timeCodeVal; /* holds the ADAT timecode value */ -}; - -struct KorgAudioBuffer { - struct KorgAudioFrame bufferData[kPlayBufferFrames]; /* buffer definition */ -}; - -struct KorgSharedBuffer { -#ifdef K1212_LARGEALLOC - struct KorgAudioBuffer playDataBufs[kNumBuffers]; - struct KorgAudioBuffer recordDataBufs[kNumBuffers]; -#endif - short volumeData[kAudioChannels]; - u32 cardCommand; - u16 routeData [kAudioChannels]; - u32 AdatTimeCode; // ADAT timecode value -}; - -struct SensBits { - union { - struct { - unsigned int leftChanVal:8; - unsigned int leftChanId:8; - } v; - u16 leftSensBits; - } l; - union { - struct { - unsigned int rightChanVal:8; - unsigned int rightChanId:8; - } v; - u16 rightSensBits; - } r; -}; - -struct snd_korg1212 { - struct snd_card *card; - struct pci_dev *pci; - struct snd_pcm *pcm; - int irq; - - spinlock_t lock; - struct mutex open_mutex; - - struct timer_list timer; /* timer callback for checking ack of stop request */ - int stop_pending_cnt; /* counter for stop pending check */ - - wait_queue_head_t wait; - - unsigned long iomem; - unsigned long ioport; - unsigned long iomem2; - unsigned long irqcount; - unsigned long inIRQ; - void __iomem *iobase; - - struct snd_dma_buffer dma_dsp; - struct snd_dma_buffer dma_play; - struct snd_dma_buffer dma_rec; - struct snd_dma_buffer dma_shared; - - u32 DataBufsSize; - - struct KorgAudioBuffer * playDataBufsPtr; - struct KorgAudioBuffer * recordDataBufsPtr; - - struct KorgSharedBuffer * sharedBufferPtr; - - u32 RecDataPhy; - u32 PlayDataPhy; - unsigned long sharedBufferPhy; - u32 VolumeTablePhy; - u32 RoutingTablePhy; - u32 AdatTimeCodePhy; - - u32 __iomem * statusRegPtr; // address of the interrupt status/control register - u32 __iomem * outDoorbellPtr; // address of the host->card doorbell register - u32 __iomem * inDoorbellPtr; // address of the card->host doorbell register - u32 __iomem * mailbox0Ptr; // address of mailbox 0 on the card - u32 __iomem * mailbox1Ptr; // address of mailbox 1 on the card - u32 __iomem * mailbox2Ptr; // address of mailbox 2 on the card - u32 __iomem * mailbox3Ptr; // address of mailbox 3 on the card - u32 __iomem * controlRegPtr; // address of the EEPROM, PCI, I/O, Init ctrl reg - u16 __iomem * sensRegPtr; // address of the sensitivity setting register - u32 __iomem * idRegPtr; // address of the device and vendor ID registers - - size_t periodsize; - int channels; - int currentBuffer; - - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - - pid_t capture_pid; - pid_t playback_pid; - - enum CardState cardState; - int running; - int idleMonitorOn; // indicates whether the card is in idle monitor mode. - u32 cmdRetryCount; // tracks how many times we have retried sending to the card. - - enum ClockSourceIndex clkSrcRate; // sample rate and clock source - - enum ClockSourceType clkSource; // clock source - int clkRate; // clock rate - - int volumePhase[kAudioChannels]; - - u16 leftADCInSens; // ADC left channel input sensitivity - u16 rightADCInSens; // ADC right channel input sensitivity - - int opencnt; // Open/Close count - int setcnt; // SetupForPlay count - int playcnt; // TriggerPlay count - int errorcnt; // Error Count - unsigned long totalerrorcnt; // Total Error Count - - int dsp_is_loaded; - int dsp_stop_is_processed; - -}; - -MODULE_DESCRIPTION("korg1212"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{KORG,korg1212}}"); -MODULE_FIRMWARE("korg/k1212.dsp"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Korg 1212 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Korg 1212 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard."); -MODULE_AUTHOR("Haroldo Gamal "); - -static DEFINE_PCI_DEVICE_TABLE(snd_korg1212_ids) = { - { - .vendor = 0x10b5, - .device = 0x906d, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, snd_korg1212_ids); - -static char *stateName[] = { - "Non-existent", - "Uninitialized", - "DSP download in process", - "DSP download complete", - "Ready", - "Open", - "Setup for play", - "Playing", - "Monitor mode on", - "Calibrating", - "Invalid" -}; - -static char *clockSourceTypeName[] = { "ADAT", "S/PDIF", "local" }; - -static char *clockSourceName[] = { - "ADAT at 44.1 kHz", - "ADAT at 48 kHz", - "S/PDIF at 44.1 kHz", - "S/PDIF at 48 kHz", - "local clock at 44.1 kHz", - "local clock at 48 kHz" -}; - -static char *channelName[] = { - "ADAT-1", - "ADAT-2", - "ADAT-3", - "ADAT-4", - "ADAT-5", - "ADAT-6", - "ADAT-7", - "ADAT-8", - "Analog-L", - "Analog-R", - "SPDIF-L", - "SPDIF-R", -}; - -static u16 ClockSourceSelector[] = { - 0x8000, // selects source as ADAT at 44.1 kHz - 0x0000, // selects source as ADAT at 48 kHz - 0x8001, // selects source as S/PDIF at 44.1 kHz - 0x0001, // selects source as S/PDIF at 48 kHz - 0x8002, // selects source as local clock at 44.1 kHz - 0x0002 // selects source as local clock at 48 kHz -}; - -union swap_u32 { unsigned char c[4]; u32 i; }; - -#ifdef SNDRV_BIG_ENDIAN -static u32 LowerWordSwap(u32 swappee) -#else -static u32 UpperWordSwap(u32 swappee) -#endif -{ - union swap_u32 retVal, swapper; - - swapper.i = swappee; - retVal.c[2] = swapper.c[3]; - retVal.c[3] = swapper.c[2]; - retVal.c[1] = swapper.c[1]; - retVal.c[0] = swapper.c[0]; - - return retVal.i; -} - -#ifdef SNDRV_BIG_ENDIAN -static u32 UpperWordSwap(u32 swappee) -#else -static u32 LowerWordSwap(u32 swappee) -#endif -{ - union swap_u32 retVal, swapper; - - swapper.i = swappee; - retVal.c[2] = swapper.c[2]; - retVal.c[3] = swapper.c[3]; - retVal.c[1] = swapper.c[0]; - retVal.c[0] = swapper.c[1]; - - return retVal.i; -} - -#define SetBitInWord(theWord,bitPosition) (*theWord) |= (0x0001 << bitPosition) -#define SetBitInDWord(theWord,bitPosition) (*theWord) |= (0x00000001 << bitPosition) -#define ClearBitInWord(theWord,bitPosition) (*theWord) &= ~(0x0001 << bitPosition) -#define ClearBitInDWord(theWord,bitPosition) (*theWord) &= ~(0x00000001 << bitPosition) - -static int snd_korg1212_Send1212Command(struct snd_korg1212 *korg1212, - enum korg1212_dbcnst doorbellVal, - u32 mailBox0Val, u32 mailBox1Val, - u32 mailBox2Val, u32 mailBox3Val) -{ - u32 retryCount; - u16 mailBox3Lo; - int rc = K1212_CMDRET_Success; - - if (!korg1212->outDoorbellPtr) { - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: CardUninitialized\n"); - return K1212_CMDRET_CardUninitialized; - } - - K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- 0x%08x 0x%08x [%s]\n", - doorbellVal, mailBox0Val, stateName[korg1212->cardState]); - for (retryCount = 0; retryCount < MAX_COMMAND_RETRIES; retryCount++) { - writel(mailBox3Val, korg1212->mailbox3Ptr); - writel(mailBox2Val, korg1212->mailbox2Ptr); - writel(mailBox1Val, korg1212->mailbox1Ptr); - writel(mailBox0Val, korg1212->mailbox0Ptr); - writel(doorbellVal, korg1212->outDoorbellPtr); // interrupt the card - - // -------------------------------------------------------------- - // the reboot command will not give an acknowledgement. - // -------------------------------------------------------------- - if ( doorbellVal == K1212_DB_RebootCard || - doorbellVal == K1212_DB_BootFromDSPPage4 || - doorbellVal == K1212_DB_StartDSPDownload ) { - rc = K1212_CMDRET_Success; - break; - } - - // -------------------------------------------------------------- - // See if the card acknowledged the command. Wait a bit, then - // read in the low word of mailbox3. If the MSB is set and the - // low byte is equal to the doorbell value, then it ack'd. - // -------------------------------------------------------------- - udelay(COMMAND_ACK_DELAY); - mailBox3Lo = readl(korg1212->mailbox3Ptr); - if (mailBox3Lo & COMMAND_ACK_MASK) { - if ((mailBox3Lo & DOORBELL_VAL_MASK) == (doorbellVal & DOORBELL_VAL_MASK)) { - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Card <- Success\n"); - rc = K1212_CMDRET_Success; - break; - } - } - } - korg1212->cmdRetryCount += retryCount; - - if (retryCount >= MAX_COMMAND_RETRIES) { - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Card <- NoAckFromCard\n"); - rc = K1212_CMDRET_NoAckFromCard; - } - - return rc; -} - -/* spinlock already held */ -static void snd_korg1212_SendStop(struct snd_korg1212 *korg1212) -{ - if (! korg1212->stop_pending_cnt) { - korg1212->sharedBufferPtr->cardCommand = 0xffffffff; - /* program the timer */ - korg1212->stop_pending_cnt = HZ; - korg1212->timer.expires = jiffies + 1; - add_timer(&korg1212->timer); - } -} - -static void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212) -{ - unsigned long flags; - spin_lock_irqsave(&korg1212->lock, flags); - korg1212->dsp_stop_is_processed = 0; - snd_korg1212_SendStop(korg1212); - spin_unlock_irqrestore(&korg1212->lock, flags); - wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2); -} - -/* timer callback for checking the ack of stop request */ -static void snd_korg1212_timer_func(unsigned long data) -{ - struct snd_korg1212 *korg1212 = (struct snd_korg1212 *) data; - unsigned long flags; - - spin_lock_irqsave(&korg1212->lock, flags); - if (korg1212->sharedBufferPtr->cardCommand == 0) { - /* ack'ed */ - korg1212->stop_pending_cnt = 0; - korg1212->dsp_stop_is_processed = 1; - wake_up(&korg1212->wait); - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Stop ack'ed [%s]\n", - stateName[korg1212->cardState]); - } else { - if (--korg1212->stop_pending_cnt > 0) { - /* reprogram timer */ - korg1212->timer.expires = jiffies + 1; - add_timer(&korg1212->timer); - } else { - snd_printd("korg1212_timer_func timeout\n"); - korg1212->sharedBufferPtr->cardCommand = 0; - korg1212->dsp_stop_is_processed = 1; - wake_up(&korg1212->wait); - K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n", - stateName[korg1212->cardState]); - } - } - spin_unlock_irqrestore(&korg1212->lock, flags); -} - -static int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212) -{ - unsigned long flags; - int rc; - - udelay(INTERCOMMAND_DELAY); - spin_lock_irqsave(&korg1212->lock, flags); - korg1212->idleMonitorOn = 1; - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, - K1212_MODE_MonitorOn, 0, 0, 0); - spin_unlock_irqrestore(&korg1212->lock, flags); - return rc; -} - -static void snd_korg1212_TurnOffIdleMonitor(struct snd_korg1212 *korg1212) -{ - if (korg1212->idleMonitorOn) { - snd_korg1212_SendStopAndWait(korg1212); - korg1212->idleMonitorOn = 0; - } -} - -static inline void snd_korg1212_setCardState(struct snd_korg1212 * korg1212, enum CardState csState) -{ - korg1212->cardState = csState; -} - -static int snd_korg1212_OpenCard(struct snd_korg1212 * korg1212) -{ - K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", - stateName[korg1212->cardState], korg1212->opencnt); - mutex_lock(&korg1212->open_mutex); - if (korg1212->opencnt++ == 0) { - snd_korg1212_TurnOffIdleMonitor(korg1212); - snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); - } - - mutex_unlock(&korg1212->open_mutex); - return 1; -} - -static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) -{ - K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", - stateName[korg1212->cardState], korg1212->opencnt); - - mutex_lock(&korg1212->open_mutex); - if (--(korg1212->opencnt)) { - mutex_unlock(&korg1212->open_mutex); - return 0; - } - - if (korg1212->cardState == K1212_STATE_SETUP) { - int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, - K1212_MODE_StopPlay, 0, 0, 0); - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - if (rc != K1212_CMDRET_Success) { - mutex_unlock(&korg1212->open_mutex); - return 0; - } - } else if (korg1212->cardState > K1212_STATE_SETUP) { - snd_korg1212_SendStopAndWait(korg1212); - } - - if (korg1212->cardState > K1212_STATE_READY) { - snd_korg1212_TurnOnIdleMonitor(korg1212); - snd_korg1212_setCardState(korg1212, K1212_STATE_READY); - } - - mutex_unlock(&korg1212->open_mutex); - return 0; -} - -/* spinlock already held */ -static int snd_korg1212_SetupForPlay(struct snd_korg1212 * korg1212) -{ - int rc; - - K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay [%s] %d\n", - stateName[korg1212->cardState], korg1212->setcnt); - - if (korg1212->setcnt++) - return 0; - - snd_korg1212_setCardState(korg1212, K1212_STATE_SETUP); - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, - K1212_MODE_SetupPlay, 0, 0, 0); - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - if (rc != K1212_CMDRET_Success) { - return 1; - } - return 0; -} - -/* spinlock already held */ -static int snd_korg1212_TriggerPlay(struct snd_korg1212 * korg1212) -{ - int rc; - - K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay [%s] %d\n", - stateName[korg1212->cardState], korg1212->playcnt); - - if (korg1212->playcnt++) - return 0; - - snd_korg1212_setCardState(korg1212, K1212_STATE_PLAYING); - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_TriggerPlay, 0, 0, 0, 0); - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - if (rc != K1212_CMDRET_Success) { - return 1; - } - return 0; -} - -/* spinlock already held */ -static int snd_korg1212_StopPlay(struct snd_korg1212 * korg1212) -{ - K1212_DEBUG_PRINTK("K1212_DEBUG: StopPlay [%s] %d\n", - stateName[korg1212->cardState], korg1212->playcnt); - - if (--(korg1212->playcnt)) - return 0; - - korg1212->setcnt = 0; - - if (korg1212->cardState != K1212_STATE_ERRORSTOP) - snd_korg1212_SendStop(korg1212); - - snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); - return 0; -} - -static void snd_korg1212_EnableCardInterrupts(struct snd_korg1212 * korg1212) -{ - writel(PCI_INT_ENABLE_BIT | - PCI_DOORBELL_INT_ENABLE_BIT | - LOCAL_INT_ENABLE_BIT | - LOCAL_DOORBELL_INT_ENABLE_BIT | - LOCAL_DMA1_INT_ENABLE_BIT, - korg1212->statusRegPtr); -} - -#if 0 /* not used */ - -static int snd_korg1212_SetMonitorMode(struct snd_korg1212 *korg1212, - enum MonitorModeSelector mode) -{ - K1212_DEBUG_PRINTK("K1212_DEBUG: SetMonitorMode [%s]\n", - stateName[korg1212->cardState]); - - switch (mode) { - case K1212_MONMODE_Off: - if (korg1212->cardState != K1212_STATE_MONITOR) - return 0; - else { - snd_korg1212_SendStopAndWait(korg1212); - snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); - } - break; - - case K1212_MONMODE_On: - if (korg1212->cardState != K1212_STATE_OPEN) - return 0; - else { - int rc; - snd_korg1212_setCardState(korg1212, K1212_STATE_MONITOR); - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, - K1212_MODE_MonitorOn, 0, 0, 0); - if (rc != K1212_CMDRET_Success) - return 0; - } - break; - - default: - return 0; - } - - return 1; -} - -#endif /* not used */ - -static inline int snd_korg1212_use_is_exclusive(struct snd_korg1212 *korg1212) -{ - if (korg1212->playback_pid != korg1212->capture_pid && - korg1212->playback_pid >= 0 && korg1212->capture_pid >= 0) - return 0; - - return 1; -} - -static int snd_korg1212_SetRate(struct snd_korg1212 *korg1212, int rate) -{ - static enum ClockSourceIndex s44[] = { - K1212_CLKIDX_AdatAt44_1K, - K1212_CLKIDX_WordAt44_1K, - K1212_CLKIDX_LocalAt44_1K - }; - static enum ClockSourceIndex s48[] = { - K1212_CLKIDX_AdatAt48K, - K1212_CLKIDX_WordAt48K, - K1212_CLKIDX_LocalAt48K - }; - int parm, rc; - - if (!snd_korg1212_use_is_exclusive (korg1212)) - return -EBUSY; - - switch (rate) { - case 44100: - parm = s44[korg1212->clkSource]; - break; - - case 48000: - parm = s48[korg1212->clkSource]; - break; - - default: - return -EINVAL; - } - - korg1212->clkSrcRate = parm; - korg1212->clkRate = rate; - - udelay(INTERCOMMAND_DELAY); - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SetClockSourceRate, - ClockSourceSelector[korg1212->clkSrcRate], - 0, 0, 0); - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - - return 0; -} - -static int snd_korg1212_SetClockSource(struct snd_korg1212 *korg1212, int source) -{ - - if (source < 0 || source > 2) - return -EINVAL; - - korg1212->clkSource = source; - - snd_korg1212_SetRate(korg1212, korg1212->clkRate); - - return 0; -} - -static void snd_korg1212_DisableCardInterrupts(struct snd_korg1212 *korg1212) -{ - writel(0, korg1212->statusRegPtr); -} - -static int snd_korg1212_WriteADCSensitivity(struct snd_korg1212 *korg1212) -{ - struct SensBits sensVals; - int bitPosition; - int channel; - int clkIs48K; - int monModeSet; - u16 controlValue; // this keeps the current value to be written to - // the card's eeprom control register. - u16 count; - unsigned long flags; - - K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity [%s]\n", - stateName[korg1212->cardState]); - - // ---------------------------------------------------------------------------- - // initialize things. The local init bit is always set when writing to the - // card's control register. - // ---------------------------------------------------------------------------- - controlValue = 0; - SetBitInWord(&controlValue, SET_SENS_LOCALINIT_BITPOS); // init the control value - - // ---------------------------------------------------------------------------- - // make sure the card is not in monitor mode when we do this update. - // ---------------------------------------------------------------------------- - if (korg1212->cardState == K1212_STATE_MONITOR || korg1212->idleMonitorOn) { - monModeSet = 1; - snd_korg1212_SendStopAndWait(korg1212); - } else - monModeSet = 0; - - spin_lock_irqsave(&korg1212->lock, flags); - - // ---------------------------------------------------------------------------- - // we are about to send new values to the card, so clear the new values queued - // flag. Also, clear out mailbox 3, so we don't lockup. - // ---------------------------------------------------------------------------- - writel(0, korg1212->mailbox3Ptr); - udelay(LOADSHIFT_DELAY); - - // ---------------------------------------------------------------------------- - // determine whether we are running a 48K or 44.1K clock. This info is used - // later when setting the SPDIF FF after the volume has been shifted in. - // ---------------------------------------------------------------------------- - switch (korg1212->clkSrcRate) { - case K1212_CLKIDX_AdatAt44_1K: - case K1212_CLKIDX_WordAt44_1K: - case K1212_CLKIDX_LocalAt44_1K: - clkIs48K = 0; - break; - - case K1212_CLKIDX_WordAt48K: - case K1212_CLKIDX_AdatAt48K: - case K1212_CLKIDX_LocalAt48K: - default: - clkIs48K = 1; - break; - } - - // ---------------------------------------------------------------------------- - // start the update. Setup the bit structure and then shift the bits. - // ---------------------------------------------------------------------------- - sensVals.l.v.leftChanId = SET_SENS_LEFTCHANID; - sensVals.r.v.rightChanId = SET_SENS_RIGHTCHANID; - sensVals.l.v.leftChanVal = korg1212->leftADCInSens; - sensVals.r.v.rightChanVal = korg1212->rightADCInSens; - - // ---------------------------------------------------------------------------- - // now start shifting the bits in. Start with the left channel then the right. - // ---------------------------------------------------------------------------- - for (channel = 0; channel < 2; channel++) { - - // ---------------------------------------------------------------------------- - // Bring the load/shift line low, then wait - the spec says >150ns from load/ - // shift low to the first rising edge of the clock. - // ---------------------------------------------------------------------------- - ClearBitInWord(&controlValue, SET_SENS_LOADSHIFT_BITPOS); - ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); - writew(controlValue, korg1212->sensRegPtr); // load/shift goes low - udelay(LOADSHIFT_DELAY); - - for (bitPosition = 15; bitPosition >= 0; bitPosition--) { // for all the bits - if (channel == 0) { - if (sensVals.l.leftSensBits & (0x0001 << bitPosition)) - SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high - else - ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low - } else { - if (sensVals.r.rightSensBits & (0x0001 << bitPosition)) - SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high - else - ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low - } - - ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); - writew(controlValue, korg1212->sensRegPtr); // clock goes low - udelay(SENSCLKPULSE_WIDTH); - SetBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); - writew(controlValue, korg1212->sensRegPtr); // clock goes high - udelay(SENSCLKPULSE_WIDTH); - } - - // ---------------------------------------------------------------------------- - // finish up SPDIF for left. Bring the load/shift line high, then write a one - // bit if the clock rate is 48K otherwise write 0. - // ---------------------------------------------------------------------------- - ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); - ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); - SetBitInWord(&controlValue, SET_SENS_LOADSHIFT_BITPOS); - writew(controlValue, korg1212->sensRegPtr); // load shift goes high - clk low - udelay(SENSCLKPULSE_WIDTH); - - if (clkIs48K) - SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); - - writew(controlValue, korg1212->sensRegPtr); // set/clear data bit - udelay(ONE_RTC_TICK); - SetBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); - writew(controlValue, korg1212->sensRegPtr); // clock goes high - udelay(SENSCLKPULSE_WIDTH); - ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); - writew(controlValue, korg1212->sensRegPtr); // clock goes low - udelay(SENSCLKPULSE_WIDTH); - } - - // ---------------------------------------------------------------------------- - // The update is complete. Set a timeout. This is the inter-update delay. - // Also, if the card was in monitor mode, restore it. - // ---------------------------------------------------------------------------- - for (count = 0; count < 10; count++) - udelay(SENSCLKPULSE_WIDTH); - - if (monModeSet) { - int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, - K1212_MODE_MonitorOn, 0, 0, 0); - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - } - - spin_unlock_irqrestore(&korg1212->lock, flags); - - return 1; -} - -static void snd_korg1212_OnDSPDownloadComplete(struct snd_korg1212 *korg1212) -{ - int channel, rc; - - K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is complete. [%s]\n", - stateName[korg1212->cardState]); - - // ---------------------------------------------------- - // tell the card to boot - // ---------------------------------------------------- - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_BootFromDSPPage4, 0, 0, 0, 0); - - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: Boot from Page 4 - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - msleep(DSP_BOOT_DELAY_IN_MS); - - // -------------------------------------------------------------------------------- - // Let the card know where all the buffers are. - // -------------------------------------------------------------------------------- - rc = snd_korg1212_Send1212Command(korg1212, - K1212_DB_ConfigureBufferMemory, - LowerWordSwap(korg1212->PlayDataPhy), - LowerWordSwap(korg1212->RecDataPhy), - ((kNumBuffers * kPlayBufferFrames) / 2), // size given to the card - // is based on 2 buffers - 0 - ); - - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Buffer Memory - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - - udelay(INTERCOMMAND_DELAY); - - rc = snd_korg1212_Send1212Command(korg1212, - K1212_DB_ConfigureMiscMemory, - LowerWordSwap(korg1212->VolumeTablePhy), - LowerWordSwap(korg1212->RoutingTablePhy), - LowerWordSwap(korg1212->AdatTimeCodePhy), - 0 - ); - - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Misc Memory - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - - // -------------------------------------------------------------------------------- - // Initialize the routing and volume tables, then update the card's state. - // -------------------------------------------------------------------------------- - udelay(INTERCOMMAND_DELAY); - - for (channel = 0; channel < kAudioChannels; channel++) { - korg1212->sharedBufferPtr->volumeData[channel] = k1212MaxVolume; - //korg1212->sharedBufferPtr->routeData[channel] = channel; - korg1212->sharedBufferPtr->routeData[channel] = 8 + (channel & 1); - } - - snd_korg1212_WriteADCSensitivity(korg1212); - - udelay(INTERCOMMAND_DELAY); - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SetClockSourceRate, - ClockSourceSelector[korg1212->clkSrcRate], - 0, 0, 0); - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - - rc = snd_korg1212_TurnOnIdleMonitor(korg1212); - snd_korg1212_setCardState(korg1212, K1212_STATE_READY); - - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: Set Monitor On - RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - - snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_COMPLETE); -} - -static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id) -{ - u32 doorbellValue; - struct snd_korg1212 *korg1212 = dev_id; - - doorbellValue = readl(korg1212->inDoorbellPtr); - - if (!doorbellValue) - return IRQ_NONE; - - spin_lock(&korg1212->lock); - - writel(doorbellValue, korg1212->inDoorbellPtr); - - korg1212->irqcount++; - - korg1212->inIRQ++; - - switch (doorbellValue) { - case K1212_DB_DSPDownloadDone: - K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n", - korg1212->irqcount, doorbellValue, - stateName[korg1212->cardState]); - if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) { - korg1212->dsp_is_loaded = 1; - wake_up(&korg1212->wait); - } - break; - - // ------------------------------------------------------------------------ - // an error occurred - stop the card - // ------------------------------------------------------------------------ - case K1212_DB_DMAERROR: - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n", - korg1212->irqcount, doorbellValue, - stateName[korg1212->cardState]); - snd_printk(KERN_ERR "korg1212: DMA Error\n"); - korg1212->errorcnt++; - korg1212->totalerrorcnt++; - korg1212->sharedBufferPtr->cardCommand = 0; - snd_korg1212_setCardState(korg1212, K1212_STATE_ERRORSTOP); - break; - - // ------------------------------------------------------------------------ - // the card has stopped by our request. Clear the command word and signal - // the semaphore in case someone is waiting for this. - // ------------------------------------------------------------------------ - case K1212_DB_CARDSTOPPED: - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].\n", - korg1212->irqcount, doorbellValue, - stateName[korg1212->cardState]); - korg1212->sharedBufferPtr->cardCommand = 0; - break; - - default: - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DFLT count - %ld, %x, cpos=%d [%s].\n", - korg1212->irqcount, doorbellValue, - korg1212->currentBuffer, stateName[korg1212->cardState]); - if ((korg1212->cardState > K1212_STATE_SETUP) || korg1212->idleMonitorOn) { - korg1212->currentBuffer++; - - if (korg1212->currentBuffer >= kNumBuffers) - korg1212->currentBuffer = 0; - - if (!korg1212->running) - break; - - if (korg1212->capture_substream) { - spin_unlock(&korg1212->lock); - snd_pcm_period_elapsed(korg1212->capture_substream); - spin_lock(&korg1212->lock); - } - - if (korg1212->playback_substream) { - spin_unlock(&korg1212->lock); - snd_pcm_period_elapsed(korg1212->playback_substream); - spin_lock(&korg1212->lock); - } - } - break; - } - - korg1212->inIRQ--; - - spin_unlock(&korg1212->lock); - - return IRQ_HANDLED; -} - -static int snd_korg1212_downloadDSPCode(struct snd_korg1212 *korg1212) -{ - int rc; - - K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is starting... [%s]\n", - stateName[korg1212->cardState]); - - // --------------------------------------------------------------- - // verify the state of the card before proceeding. - // --------------------------------------------------------------- - if (korg1212->cardState >= K1212_STATE_DSP_IN_PROCESS) - return 1; - - snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS); - - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload, - UpperWordSwap(korg1212->dma_dsp.addr), - 0, 0, 0); - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", - rc, stateName[korg1212->cardState]); - - korg1212->dsp_is_loaded = 0; - wait_event_timeout(korg1212->wait, korg1212->dsp_is_loaded, HZ * CARD_BOOT_TIMEOUT); - if (! korg1212->dsp_is_loaded ) - return -EBUSY; /* timeout */ - - snd_korg1212_OnDSPDownloadComplete(korg1212); - - return 0; -} - -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_BATCH), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 44100, - .rate_max = 48000, - .channels_min = K1212_MIN_CHANNELS, - .channels_max = K1212_MAX_CHANNELS, - .buffer_bytes_max = K1212_MAX_BUF_SIZE, - .period_bytes_min = K1212_MIN_CHANNELS * 2 * kPlayBufferFrames, - .period_bytes_max = K1212_MAX_CHANNELS * 2 * kPlayBufferFrames, - .periods_min = K1212_PERIODS, - .periods_max = K1212_PERIODS, - .fifo_size = 0, -}; - -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_BATCH), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 44100, - .rate_max = 48000, - .channels_min = K1212_MIN_CHANNELS, - .channels_max = K1212_MAX_CHANNELS, - .buffer_bytes_max = K1212_MAX_BUF_SIZE, - .period_bytes_min = K1212_MIN_CHANNELS * 2 * kPlayBufferFrames, - .period_bytes_max = K1212_MAX_CHANNELS * 2 * kPlayBufferFrames, - .periods_min = K1212_PERIODS, - .periods_max = K1212_PERIODS, - .fifo_size = 0, -}; - -static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int count, int offset, int size) -{ - struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos; - int i; - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_silence pos=%d offset=%d size=%d count=%d\n", - pos, offset, size, count); - if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) - return -EINVAL; - - for (i=0; i < count; i++) { -#if K1212_DEBUG_LEVEL > 0 - if ( (void *) dst < (void *) korg1212->playDataBufsPtr || - (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { - printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_silence KERNEL EFAULT dst=%p iter=%d\n", - dst, i); - return -EFAULT; - } -#endif - memset((void*) dst + offset, 0, size); - dst++; - } - - return 0; -} - -static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, int pos, int count, int offset, int size) -{ - struct KorgAudioFrame * src = korg1212->recordDataBufsPtr[0].bufferData + pos; - int i, rc; - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d\n", - pos, offset, size); - if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) - return -EINVAL; - - for (i=0; i < count; i++) { -#if K1212_DEBUG_LEVEL > 0 - if ( (void *) src < (void *) korg1212->recordDataBufsPtr || - (void *) src > (void *) korg1212->recordDataBufsPtr[8].bufferData ) { - printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i); - return -EFAULT; - } -#endif - rc = copy_to_user(dst + offset, src, size); - if (rc) { - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i); - return -EFAULT; - } - src++; - dst += size; - } - - return 0; -} - -static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *src, int pos, int count, int offset, int size) -{ - struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos; - int i, rc; - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d\n", - pos, offset, size, count); - - if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) - return -EINVAL; - - for (i=0; i < count; i++) { -#if K1212_DEBUG_LEVEL > 0 - if ( (void *) dst < (void *) korg1212->playDataBufsPtr || - (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { - printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i); - return -EFAULT; - } -#endif - rc = copy_from_user((void*) dst + offset, src, size); - if (rc) { - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i); - return -EFAULT; - } - dst++; - src += size; - } - - return 0; -} - -static void snd_korg1212_free_pcm(struct snd_pcm *pcm) -{ - struct snd_korg1212 *korg1212 = pcm->private_data; - - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_free_pcm [%s]\n", - stateName[korg1212->cardState]); - - korg1212->pcm = NULL; -} - -static int snd_korg1212_playback_open(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", - stateName[korg1212->cardState]); - - snd_korg1212_OpenCard(korg1212); - - runtime->hw = snd_korg1212_playback_info; - snd_pcm_set_runtime_buffer(substream, &korg1212->dma_play); - - spin_lock_irqsave(&korg1212->lock, flags); - - korg1212->playback_substream = substream; - korg1212->playback_pid = current->pid; - korg1212->periodsize = K1212_PERIODS; - korg1212->channels = K1212_CHANNELS; - korg1212->errorcnt = 0; - - spin_unlock_irqrestore(&korg1212->lock, flags); - - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, kPlayBufferFrames, kPlayBufferFrames); - return 0; -} - - -static int snd_korg1212_capture_open(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", - stateName[korg1212->cardState]); - - snd_korg1212_OpenCard(korg1212); - - runtime->hw = snd_korg1212_capture_info; - snd_pcm_set_runtime_buffer(substream, &korg1212->dma_rec); - - spin_lock_irqsave(&korg1212->lock, flags); - - korg1212->capture_substream = substream; - korg1212->capture_pid = current->pid; - korg1212->periodsize = K1212_PERIODS; - korg1212->channels = K1212_CHANNELS; - - spin_unlock_irqrestore(&korg1212->lock, flags); - - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - kPlayBufferFrames, kPlayBufferFrames); - return 0; -} - -static int snd_korg1212_playback_close(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n", - stateName[korg1212->cardState]); - - snd_korg1212_silence(korg1212, 0, K1212_MAX_SAMPLES, 0, korg1212->channels * 2); - - spin_lock_irqsave(&korg1212->lock, flags); - - korg1212->playback_pid = -1; - korg1212->playback_substream = NULL; - korg1212->periodsize = 0; - - spin_unlock_irqrestore(&korg1212->lock, flags); - - snd_korg1212_CloseCard(korg1212); - return 0; -} - -static int snd_korg1212_capture_close(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_close [%s]\n", - stateName[korg1212->cardState]); - - spin_lock_irqsave(&korg1212->lock, flags); - - korg1212->capture_pid = -1; - korg1212->capture_substream = NULL; - korg1212->periodsize = 0; - - spin_unlock_irqrestore(&korg1212->lock, flags); - - snd_korg1212_CloseCard(korg1212); - return 0; -} - -static int snd_korg1212_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_ioctl: cmd=%d\n", cmd); - - if (cmd == SNDRV_PCM_IOCTL1_CHANNEL_INFO ) { - struct snd_pcm_channel_info *info = arg; - info->offset = 0; - info->first = info->channel * 16; - info->step = 256; - K1212_DEBUG_PRINTK("K1212_DEBUG: channel_info %d:, offset=%ld, first=%d, step=%d\n", info->channel, info->offset, info->first, info->step); - return 0; - } - - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static int snd_korg1212_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - unsigned long flags; - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - int err; - pid_t this_pid; - pid_t other_pid; - - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_hw_params [%s]\n", - stateName[korg1212->cardState]); - - spin_lock_irqsave(&korg1212->lock, flags); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { - this_pid = korg1212->playback_pid; - other_pid = korg1212->capture_pid; - } else { - this_pid = korg1212->capture_pid; - other_pid = korg1212->playback_pid; - } - - if ((other_pid > 0) && (this_pid != other_pid)) { - - /* The other stream is open, and not by the same - task as this one. Make sure that the parameters - that matter are the same. - */ - - if ((int)params_rate(params) != korg1212->clkRate) { - spin_unlock_irqrestore(&korg1212->lock, flags); - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); - return -EBUSY; - } - - spin_unlock_irqrestore(&korg1212->lock, flags); - return 0; - } - - if ((err = snd_korg1212_SetRate(korg1212, params_rate(params))) < 0) { - spin_unlock_irqrestore(&korg1212->lock, flags); - return err; - } - - korg1212->channels = params_channels(params); - korg1212->periodsize = K1212_PERIOD_BYTES; - - spin_unlock_irqrestore(&korg1212->lock, flags); - - return 0; -} - -static int snd_korg1212_prepare(struct snd_pcm_substream *substream) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - int rc; - - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n", - stateName[korg1212->cardState]); - - spin_lock_irq(&korg1212->lock); - - /* FIXME: we should wait for ack! */ - if (korg1212->stop_pending_cnt > 0) { - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is pending... [%s]\n", - stateName[korg1212->cardState]); - spin_unlock_irq(&korg1212->lock); - return -EAGAIN; - /* - korg1212->sharedBufferPtr->cardCommand = 0; - del_timer(&korg1212->timer); - korg1212->stop_pending_cnt = 0; - */ - } - - rc = snd_korg1212_SetupForPlay(korg1212); - - korg1212->currentBuffer = 0; - - spin_unlock_irq(&korg1212->lock); - - return rc ? -EINVAL : 0; -} - -static int snd_korg1212_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - int rc; - - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger [%s] cmd=%d\n", - stateName[korg1212->cardState], cmd); - - spin_lock(&korg1212->lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: -/* - if (korg1212->running) { - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_trigger: Already running?\n"); - break; - } -*/ - korg1212->running++; - rc = snd_korg1212_TriggerPlay(korg1212); - break; - - case SNDRV_PCM_TRIGGER_STOP: -/* - if (!korg1212->running) { - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_trigger: Already stopped?\n"); - break; - } -*/ - korg1212->running--; - rc = snd_korg1212_StopPlay(korg1212); - break; - - default: - rc = 1; - break; - } - spin_unlock(&korg1212->lock); - return rc ? -EINVAL : 0; -} - -static snd_pcm_uframes_t snd_korg1212_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - snd_pcm_uframes_t pos; - - pos = korg1212->currentBuffer * kPlayBufferFrames; - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_pointer [%s] %ld\n", - stateName[korg1212->cardState], pos); - - return pos; -} - -static snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - snd_pcm_uframes_t pos; - - pos = korg1212->currentBuffer * kPlayBufferFrames; - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_pointer [%s] %ld\n", - stateName[korg1212->cardState], pos); - - return pos; -} - -static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n", - stateName[korg1212->cardState], pos, count); - - return snd_korg1212_copy_from(korg1212, src, pos, count, 0, korg1212->channels * 2); - -} - -static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n", - stateName[korg1212->cardState]); - - return snd_korg1212_silence(korg1212, pos, count, 0, korg1212->channels * 2); -} - -static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) -{ - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n", - stateName[korg1212->cardState], pos, count); - - return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2); -} - -static struct snd_pcm_ops snd_korg1212_playback_ops = { - .open = snd_korg1212_playback_open, - .close = snd_korg1212_playback_close, - .ioctl = snd_korg1212_ioctl, - .hw_params = snd_korg1212_hw_params, - .prepare = snd_korg1212_prepare, - .trigger = snd_korg1212_trigger, - .pointer = snd_korg1212_playback_pointer, - .copy = snd_korg1212_playback_copy, - .silence = snd_korg1212_playback_silence, -}; - -static struct snd_pcm_ops snd_korg1212_capture_ops = { - .open = snd_korg1212_capture_open, - .close = snd_korg1212_capture_close, - .ioctl = snd_korg1212_ioctl, - .hw_params = snd_korg1212_hw_params, - .prepare = snd_korg1212_prepare, - .trigger = snd_korg1212_trigger, - .pointer = snd_korg1212_capture_pointer, - .copy = snd_korg1212_capture_copy, -}; - -/* - * Control Interface - */ - -static int snd_korg1212_control_phase_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1; - return 0; -} - -static int snd_korg1212_control_phase_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *u) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - int i = kcontrol->private_value; - - spin_lock_irq(&korg1212->lock); - - u->value.integer.value[0] = korg1212->volumePhase[i]; - - if (i >= 8) - u->value.integer.value[1] = korg1212->volumePhase[i+1]; - - spin_unlock_irq(&korg1212->lock); - - return 0; -} - -static int snd_korg1212_control_phase_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *u) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - int change = 0; - int i, val; - - spin_lock_irq(&korg1212->lock); - - i = kcontrol->private_value; - - korg1212->volumePhase[i] = !!u->value.integer.value[0]; - - val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value]; - - if ((u->value.integer.value[0] != 0) != (val < 0)) { - val = abs(val) * (korg1212->volumePhase[i] > 0 ? -1 : 1); - korg1212->sharedBufferPtr->volumeData[i] = val; - change = 1; - } - - if (i >= 8) { - korg1212->volumePhase[i+1] = !!u->value.integer.value[1]; - - val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value+1]; - - if ((u->value.integer.value[1] != 0) != (val < 0)) { - val = abs(val) * (korg1212->volumePhase[i+1] > 0 ? -1 : 1); - korg1212->sharedBufferPtr->volumeData[i+1] = val; - change = 1; - } - } - - spin_unlock_irq(&korg1212->lock); - - return change; -} - -static int snd_korg1212_control_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1; - uinfo->value.integer.min = k1212MinVolume; - uinfo->value.integer.max = k1212MaxVolume; - return 0; -} - -static int snd_korg1212_control_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *u) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - int i; - - spin_lock_irq(&korg1212->lock); - - i = kcontrol->private_value; - u->value.integer.value[0] = abs(korg1212->sharedBufferPtr->volumeData[i]); - - if (i >= 8) - u->value.integer.value[1] = abs(korg1212->sharedBufferPtr->volumeData[i+1]); - - spin_unlock_irq(&korg1212->lock); - - return 0; -} - -static int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *u) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - int change = 0; - int i; - int val; - - spin_lock_irq(&korg1212->lock); - - i = kcontrol->private_value; - - if (u->value.integer.value[0] >= k1212MinVolume && - u->value.integer.value[0] >= k1212MaxVolume && - u->value.integer.value[0] != - abs(korg1212->sharedBufferPtr->volumeData[i])) { - val = korg1212->volumePhase[i] > 0 ? -1 : 1; - val *= u->value.integer.value[0]; - korg1212->sharedBufferPtr->volumeData[i] = val; - change = 1; - } - - if (i >= 8) { - if (u->value.integer.value[1] >= k1212MinVolume && - u->value.integer.value[1] >= k1212MaxVolume && - u->value.integer.value[1] != - abs(korg1212->sharedBufferPtr->volumeData[i+1])) { - val = korg1212->volumePhase[i+1] > 0 ? -1 : 1; - val *= u->value.integer.value[1]; - korg1212->sharedBufferPtr->volumeData[i+1] = val; - change = 1; - } - } - - spin_unlock_irq(&korg1212->lock); - - return change; -} - -static int snd_korg1212_control_route_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1; - uinfo->value.enumerated.items = kAudioChannels; - if (uinfo->value.enumerated.item > kAudioChannels-1) { - uinfo->value.enumerated.item = kAudioChannels-1; - } - strcpy(uinfo->value.enumerated.name, channelName[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_korg1212_control_route_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *u) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - int i; - - spin_lock_irq(&korg1212->lock); - - i = kcontrol->private_value; - u->value.enumerated.item[0] = korg1212->sharedBufferPtr->routeData[i]; - - if (i >= 8) - u->value.enumerated.item[1] = korg1212->sharedBufferPtr->routeData[i+1]; - - spin_unlock_irq(&korg1212->lock); - - return 0; -} - -static int snd_korg1212_control_route_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *u) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - int change = 0, i; - - spin_lock_irq(&korg1212->lock); - - i = kcontrol->private_value; - - if (u->value.enumerated.item[0] < kAudioChannels && - u->value.enumerated.item[0] != - (unsigned) korg1212->sharedBufferPtr->volumeData[i]) { - korg1212->sharedBufferPtr->routeData[i] = u->value.enumerated.item[0]; - change = 1; - } - - if (i >= 8) { - if (u->value.enumerated.item[1] < kAudioChannels && - u->value.enumerated.item[1] != - (unsigned) korg1212->sharedBufferPtr->volumeData[i+1]) { - korg1212->sharedBufferPtr->routeData[i+1] = u->value.enumerated.item[1]; - change = 1; - } - } - - spin_unlock_irq(&korg1212->lock); - - return change; -} - -static int snd_korg1212_control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = k1212MaxADCSens; - uinfo->value.integer.max = k1212MinADCSens; - return 0; -} - -static int snd_korg1212_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *u) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&korg1212->lock); - - u->value.integer.value[0] = korg1212->leftADCInSens; - u->value.integer.value[1] = korg1212->rightADCInSens; - - spin_unlock_irq(&korg1212->lock); - - return 0; -} - -static int snd_korg1212_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *u) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - int change = 0; - - spin_lock_irq(&korg1212->lock); - - if (u->value.integer.value[0] >= k1212MinADCSens && - u->value.integer.value[0] <= k1212MaxADCSens && - u->value.integer.value[0] != korg1212->leftADCInSens) { - korg1212->leftADCInSens = u->value.integer.value[0]; - change = 1; - } - if (u->value.integer.value[1] >= k1212MinADCSens && - u->value.integer.value[1] <= k1212MaxADCSens && - u->value.integer.value[1] != korg1212->rightADCInSens) { - korg1212->rightADCInSens = u->value.integer.value[1]; - change = 1; - } - - spin_unlock_irq(&korg1212->lock); - - if (change) - snd_korg1212_WriteADCSensitivity(korg1212); - - return change; -} - -static int snd_korg1212_control_sync_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) { - uinfo->value.enumerated.item = 2; - } - strcpy(uinfo->value.enumerated.name, clockSourceTypeName[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_korg1212_control_sync_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&korg1212->lock); - - ucontrol->value.enumerated.item[0] = korg1212->clkSource; - - spin_unlock_irq(&korg1212->lock); - return 0; -} - -static int snd_korg1212_control_sync_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&korg1212->lock); - change = val != korg1212->clkSource; - snd_korg1212_SetClockSource(korg1212, val); - spin_unlock_irq(&korg1212->lock); - return change; -} - -#define MON_MIXER(ord,c_name) \ - { \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = c_name " Monitor Volume", \ - .info = snd_korg1212_control_volume_info, \ - .get = snd_korg1212_control_volume_get, \ - .put = snd_korg1212_control_volume_put, \ - .private_value = ord, \ - }, \ - { \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = c_name " Monitor Route", \ - .info = snd_korg1212_control_route_info, \ - .get = snd_korg1212_control_route_get, \ - .put = snd_korg1212_control_route_put, \ - .private_value = ord, \ - }, \ - { \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = c_name " Monitor Phase Invert", \ - .info = snd_korg1212_control_phase_info, \ - .get = snd_korg1212_control_phase_get, \ - .put = snd_korg1212_control_phase_put, \ - .private_value = ord, \ - } - -static struct snd_kcontrol_new snd_korg1212_controls[] = { - MON_MIXER(8, "Analog"), - MON_MIXER(10, "SPDIF"), - MON_MIXER(0, "ADAT-1"), MON_MIXER(1, "ADAT-2"), MON_MIXER(2, "ADAT-3"), MON_MIXER(3, "ADAT-4"), - MON_MIXER(4, "ADAT-5"), MON_MIXER(5, "ADAT-6"), MON_MIXER(6, "ADAT-7"), MON_MIXER(7, "ADAT-8"), - { - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Sync Source", - .info = snd_korg1212_control_sync_info, - .get = snd_korg1212_control_sync_get, - .put = snd_korg1212_control_sync_put, - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Attenuation", - .info = snd_korg1212_control_info, - .get = snd_korg1212_control_get, - .put = snd_korg1212_control_put, - } -}; - -/* - * proc interface - */ - -static void snd_korg1212_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - int n; - struct snd_korg1212 *korg1212 = entry->private_data; - - snd_iprintf(buffer, korg1212->card->longname); - snd_iprintf(buffer, " (index #%d)\n", korg1212->card->number + 1); - snd_iprintf(buffer, "\nGeneral settings\n"); - snd_iprintf(buffer, " period size: %Zd bytes\n", K1212_PERIOD_BYTES); - snd_iprintf(buffer, " clock mode: %s\n", clockSourceName[korg1212->clkSrcRate] ); - snd_iprintf(buffer, " left ADC Sens: %d\n", korg1212->leftADCInSens ); - snd_iprintf(buffer, " right ADC Sens: %d\n", korg1212->rightADCInSens ); - snd_iprintf(buffer, " Volume Info:\n"); - for (n=0; n %s [%d]\n", n, - channelName[n], - channelName[korg1212->sharedBufferPtr->routeData[n]], - korg1212->sharedBufferPtr->volumeData[n]); - snd_iprintf(buffer, "\nGeneral status\n"); - snd_iprintf(buffer, " ADAT Time Code: %d\n", korg1212->sharedBufferPtr->AdatTimeCode); - snd_iprintf(buffer, " Card State: %s\n", stateName[korg1212->cardState]); - snd_iprintf(buffer, "Idle mon. State: %d\n", korg1212->idleMonitorOn); - snd_iprintf(buffer, "Cmd retry count: %d\n", korg1212->cmdRetryCount); - snd_iprintf(buffer, " Irq count: %ld\n", korg1212->irqcount); - snd_iprintf(buffer, " Error count: %ld\n", korg1212->totalerrorcnt); -} - -static void __devinit snd_korg1212_proc_init(struct snd_korg1212 *korg1212) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(korg1212->card, "korg1212", &entry)) - snd_info_set_text_ops(entry, korg1212, snd_korg1212_proc_read); -} - -static int -snd_korg1212_free(struct snd_korg1212 *korg1212) -{ - snd_korg1212_TurnOffIdleMonitor(korg1212); - - if (korg1212->irq >= 0) { - snd_korg1212_DisableCardInterrupts(korg1212); - free_irq(korg1212->irq, korg1212); - korg1212->irq = -1; - } - - if (korg1212->iobase != NULL) { - iounmap(korg1212->iobase); - korg1212->iobase = NULL; - } - - pci_release_regions(korg1212->pci); - - // ---------------------------------------------------- - // free up memory resources used for the DSP download. - // ---------------------------------------------------- - if (korg1212->dma_dsp.area) { - snd_dma_free_pages(&korg1212->dma_dsp); - korg1212->dma_dsp.area = NULL; - } - -#ifndef K1212_LARGEALLOC - - // ------------------------------------------------------ - // free up memory resources used for the Play/Rec Buffers - // ------------------------------------------------------ - if (korg1212->dma_play.area) { - snd_dma_free_pages(&korg1212->dma_play); - korg1212->dma_play.area = NULL; - } - - if (korg1212->dma_rec.area) { - snd_dma_free_pages(&korg1212->dma_rec); - korg1212->dma_rec.area = NULL; - } - -#endif - - // ---------------------------------------------------- - // free up memory resources used for the Shared Buffers - // ---------------------------------------------------- - if (korg1212->dma_shared.area) { - snd_dma_free_pages(&korg1212->dma_shared); - korg1212->dma_shared.area = NULL; - } - - pci_disable_device(korg1212->pci); - kfree(korg1212); - return 0; -} - -static int snd_korg1212_dev_free(struct snd_device *device) -{ - struct snd_korg1212 *korg1212 = device->device_data; - K1212_DEBUG_PRINTK("K1212_DEBUG: Freeing device\n"); - return snd_korg1212_free(korg1212); -} - -static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, - struct snd_korg1212 ** rchip) - -{ - int err, rc; - unsigned int i; - unsigned ioport_size, iomem_size, iomem2_size; - struct snd_korg1212 * korg1212; - const struct firmware *dsp_code; - - static struct snd_device_ops ops = { - .dev_free = snd_korg1212_dev_free, - }; - - * rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) - return err; - - korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL); - if (korg1212 == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - korg1212->card = card; - korg1212->pci = pci; - - init_waitqueue_head(&korg1212->wait); - spin_lock_init(&korg1212->lock); - mutex_init(&korg1212->open_mutex); - init_timer(&korg1212->timer); - korg1212->timer.function = snd_korg1212_timer_func; - korg1212->timer.data = (unsigned long)korg1212; - - korg1212->irq = -1; - korg1212->clkSource = K1212_CLKIDX_Local; - korg1212->clkRate = 44100; - korg1212->inIRQ = 0; - korg1212->running = 0; - korg1212->opencnt = 0; - korg1212->playcnt = 0; - korg1212->setcnt = 0; - korg1212->totalerrorcnt = 0; - korg1212->playback_pid = -1; - korg1212->capture_pid = -1; - snd_korg1212_setCardState(korg1212, K1212_STATE_UNINITIALIZED); - korg1212->idleMonitorOn = 0; - korg1212->clkSrcRate = K1212_CLKIDX_LocalAt44_1K; - korg1212->leftADCInSens = k1212MaxADCSens; - korg1212->rightADCInSens = k1212MaxADCSens; - - for (i=0; ivolumePhase[i] = 0; - - if ((err = pci_request_regions(pci, "korg1212")) < 0) { - kfree(korg1212); - pci_disable_device(pci); - return err; - } - - korg1212->iomem = pci_resource_start(korg1212->pci, 0); - korg1212->ioport = pci_resource_start(korg1212->pci, 1); - korg1212->iomem2 = pci_resource_start(korg1212->pci, 2); - - iomem_size = pci_resource_len(korg1212->pci, 0); - ioport_size = pci_resource_len(korg1212->pci, 1); - iomem2_size = pci_resource_len(korg1212->pci, 2); - - K1212_DEBUG_PRINTK("K1212_DEBUG: resources:\n" - " iomem = 0x%lx (%d)\n" - " ioport = 0x%lx (%d)\n" - " iomem = 0x%lx (%d)\n" - " [%s]\n", - korg1212->iomem, iomem_size, - korg1212->ioport, ioport_size, - korg1212->iomem2, iomem2_size, - stateName[korg1212->cardState]); - - if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) { - snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem, - korg1212->iomem + iomem_size - 1); - snd_korg1212_free(korg1212); - return -EBUSY; - } - - err = request_irq(pci->irq, snd_korg1212_interrupt, - IRQF_SHARED, - KBUILD_MODNAME, korg1212); - - if (err) { - snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq); - snd_korg1212_free(korg1212); - return -EBUSY; - } - - korg1212->irq = pci->irq; - - pci_set_master(korg1212->pci); - - korg1212->statusRegPtr = (u32 __iomem *) (korg1212->iobase + STATUS_REG_OFFSET); - korg1212->outDoorbellPtr = (u32 __iomem *) (korg1212->iobase + OUT_DOORBELL_OFFSET); - korg1212->inDoorbellPtr = (u32 __iomem *) (korg1212->iobase + IN_DOORBELL_OFFSET); - korg1212->mailbox0Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX0_OFFSET); - korg1212->mailbox1Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX1_OFFSET); - korg1212->mailbox2Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX2_OFFSET); - korg1212->mailbox3Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX3_OFFSET); - korg1212->controlRegPtr = (u32 __iomem *) (korg1212->iobase + PCI_CONTROL_OFFSET); - korg1212->sensRegPtr = (u16 __iomem *) (korg1212->iobase + SENS_CONTROL_OFFSET); - korg1212->idRegPtr = (u32 __iomem *) (korg1212->iobase + DEV_VEND_ID_OFFSET); - - K1212_DEBUG_PRINTK("K1212_DEBUG: card registers:\n" - " Status register = 0x%p\n" - " OutDoorbell = 0x%p\n" - " InDoorbell = 0x%p\n" - " Mailbox0 = 0x%p\n" - " Mailbox1 = 0x%p\n" - " Mailbox2 = 0x%p\n" - " Mailbox3 = 0x%p\n" - " ControlReg = 0x%p\n" - " SensReg = 0x%p\n" - " IDReg = 0x%p\n" - " [%s]\n", - korg1212->statusRegPtr, - korg1212->outDoorbellPtr, - korg1212->inDoorbellPtr, - korg1212->mailbox0Ptr, - korg1212->mailbox1Ptr, - korg1212->mailbox2Ptr, - korg1212->mailbox3Ptr, - korg1212->controlRegPtr, - korg1212->sensRegPtr, - korg1212->idRegPtr, - stateName[korg1212->cardState]); - - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - sizeof(struct KorgSharedBuffer), &korg1212->dma_shared) < 0) { - snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%Zd bytes)\n", sizeof(struct KorgSharedBuffer)); - snd_korg1212_free(korg1212); - return -ENOMEM; - } - korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared.area; - korg1212->sharedBufferPhy = korg1212->dma_shared.addr; - - K1212_DEBUG_PRINTK("K1212_DEBUG: Shared Buffer Area = 0x%p (0x%08lx), %d bytes\n", korg1212->sharedBufferPtr, korg1212->sharedBufferPhy, sizeof(struct KorgSharedBuffer)); - -#ifndef K1212_LARGEALLOC - - korg1212->DataBufsSize = sizeof(struct KorgAudioBuffer) * kNumBuffers; - - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - korg1212->DataBufsSize, &korg1212->dma_play) < 0) { - snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize); - snd_korg1212_free(korg1212); - return -ENOMEM; - } - korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play.area; - korg1212->PlayDataPhy = korg1212->dma_play.addr; - - K1212_DEBUG_PRINTK("K1212_DEBUG: Play Data Area = 0x%p (0x%08x), %d bytes\n", - korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize); - - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - korg1212->DataBufsSize, &korg1212->dma_rec) < 0) { - snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize); - snd_korg1212_free(korg1212); - return -ENOMEM; - } - korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec.area; - korg1212->RecDataPhy = korg1212->dma_rec.addr; - - K1212_DEBUG_PRINTK("K1212_DEBUG: Record Data Area = 0x%p (0x%08x), %d bytes\n", - korg1212->recordDataBufsPtr, korg1212->RecDataPhy, korg1212->DataBufsSize); - -#else // K1212_LARGEALLOC - - korg1212->recordDataBufsPtr = korg1212->sharedBufferPtr->recordDataBufs; - korg1212->playDataBufsPtr = korg1212->sharedBufferPtr->playDataBufs; - korg1212->PlayDataPhy = (u32) &((struct KorgSharedBuffer *) korg1212->sharedBufferPhy)->playDataBufs; - korg1212->RecDataPhy = (u32) &((struct KorgSharedBuffer *) korg1212->sharedBufferPhy)->recordDataBufs; - -#endif // K1212_LARGEALLOC - - korg1212->VolumeTablePhy = korg1212->sharedBufferPhy + - offsetof(struct KorgSharedBuffer, volumeData); - korg1212->RoutingTablePhy = korg1212->sharedBufferPhy + - offsetof(struct KorgSharedBuffer, routeData); - korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy + - offsetof(struct KorgSharedBuffer, AdatTimeCode); - - err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev); - if (err < 0) { - release_firmware(dsp_code); - snd_printk(KERN_ERR "firmware not available\n"); - snd_korg1212_free(korg1212); - return err; - } - - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - dsp_code->size, &korg1212->dma_dsp) < 0) { - snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size); - snd_korg1212_free(korg1212); - release_firmware(dsp_code); - return -ENOMEM; - } - - K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n", - korg1212->dma_dsp.area, korg1212->dma_dsp.addr, dsp_code->size, - stateName[korg1212->cardState]); - - memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size); - - release_firmware(dsp_code); - - rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0); - - if (rc) - K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, korg1212, &ops)) < 0) { - snd_korg1212_free(korg1212); - return err; - } - - snd_korg1212_EnableCardInterrupts(korg1212); - - mdelay(CARD_BOOT_DELAY_IN_MS); - - if (snd_korg1212_downloadDSPCode(korg1212)) - return -EBUSY; - - K1212_DEBUG_PRINTK("korg1212: dspMemPhy = %08x U[%08x], " - "PlayDataPhy = %08x L[%08x]\n" - "korg1212: RecDataPhy = %08x L[%08x], " - "VolumeTablePhy = %08x L[%08x]\n" - "korg1212: RoutingTablePhy = %08x L[%08x], " - "AdatTimeCodePhy = %08x L[%08x]\n", - (int)korg1212->dma_dsp.addr, UpperWordSwap(korg1212->dma_dsp.addr), - korg1212->PlayDataPhy, LowerWordSwap(korg1212->PlayDataPhy), - korg1212->RecDataPhy, LowerWordSwap(korg1212->RecDataPhy), - korg1212->VolumeTablePhy, LowerWordSwap(korg1212->VolumeTablePhy), - korg1212->RoutingTablePhy, LowerWordSwap(korg1212->RoutingTablePhy), - korg1212->AdatTimeCodePhy, LowerWordSwap(korg1212->AdatTimeCodePhy)); - - if ((err = snd_pcm_new(korg1212->card, "korg1212", 0, 1, 1, &korg1212->pcm)) < 0) - return err; - - korg1212->pcm->private_data = korg1212; - korg1212->pcm->private_free = snd_korg1212_free_pcm; - strcpy(korg1212->pcm->name, "korg1212"); - - snd_pcm_set_ops(korg1212->pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_korg1212_playback_ops); - - snd_pcm_set_ops(korg1212->pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_korg1212_capture_ops); - - korg1212->pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - - for (i = 0; i < ARRAY_SIZE(snd_korg1212_controls); i++) { - err = snd_ctl_add(korg1212->card, snd_ctl_new1(&snd_korg1212_controls[i], korg1212)); - if (err < 0) - return err; - } - - snd_korg1212_proc_init(korg1212); - - snd_card_set_dev(card, &pci->dev); - - * rchip = korg1212; - return 0; - -} - -/* - * Card initialisation - */ - -static int __devinit -snd_korg1212_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_korg1212 *korg1212; - struct snd_card *card; - int err; - - if (dev >= SNDRV_CARDS) { - return -ENODEV; - } - if (!enable[dev]) { - dev++; - return -ENOENT; - } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_korg1212_create(card, pci, &korg1212)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "korg1212"); - strcpy(card->shortname, "korg1212"); - sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, - korg1212->iomem, korg1212->irq); - - K1212_DEBUG_PRINTK("K1212_DEBUG: %s\n", card->longname); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_korg1212_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_korg1212_ids, - .probe = snd_korg1212_probe, - .remove = __devexit_p(snd_korg1212_remove), -}; - -static int __init alsa_card_korg1212_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_korg1212_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_korg1212_init) -module_exit(alsa_card_korg1212_exit) diff --git a/ANDROID_3.4.5/sound/pci/lola/Makefile b/ANDROID_3.4.5/sound/pci/lola/Makefile deleted file mode 100644 index 8178a2a5..00000000 --- a/ANDROID_3.4.5/sound/pci/lola/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -snd-lola-y := lola.o lola_pcm.o lola_clock.o lola_mixer.o -snd-lola-$(CONFIG_SND_DEBUG) += lola_proc.o - -obj-$(CONFIG_SND_LOLA) += snd-lola.o diff --git a/ANDROID_3.4.5/sound/pci/lola/lola.c b/ANDROID_3.4.5/sound/pci/lola/lola.c deleted file mode 100644 index 37598273..00000000 --- a/ANDROID_3.4.5/sound/pci/lola/lola.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * Support for Digigram Lola PCI-e boards - * - * Copyright (c) 2011 Takashi Iwai - * - * 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 -#include -#include -#include -#include "lola.h" - -/* Standard options */ -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Digigram Lola driver."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Digigram Lola driver."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Digigram Lola driver."); - -/* Lola-specific options */ - -/* for instance use always max granularity which is compatible - * with all sample rates - */ -static int granularity[SNDRV_CARDS] = { - [0 ... (SNDRV_CARDS - 1)] = LOLA_GRANULARITY_MAX -}; - -/* below a sample_rate of 16kHz the analogue audio quality is NOT excellent */ -static int sample_rate_min[SNDRV_CARDS] = { - [0 ... (SNDRV_CARDS - 1) ] = 16000 -}; - -module_param_array(granularity, int, NULL, 0444); -MODULE_PARM_DESC(granularity, "Granularity value"); -module_param_array(sample_rate_min, int, NULL, 0444); -MODULE_PARM_DESC(sample_rate_min, "Minimal sample rate"); - -/* - */ - -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Digigram, Lola}}"); -MODULE_DESCRIPTION("Digigram Lola driver"); -MODULE_AUTHOR("Takashi Iwai "); - -#ifdef CONFIG_SND_DEBUG_VERBOSE -static int debug; -module_param(debug, int, 0644); -#define verbose_debug(fmt, args...) \ - do { if (debug > 1) printk(KERN_DEBUG SFX fmt, ##args); } while (0) -#else -#define verbose_debug(fmt, args...) -#endif - -/* - * pseudo-codec read/write via CORB/RIRB - */ - -static int corb_send_verb(struct lola *chip, unsigned int nid, - unsigned int verb, unsigned int data, - unsigned int extdata) -{ - unsigned long flags; - int ret = -EIO; - - chip->last_cmd_nid = nid; - chip->last_verb = verb; - chip->last_data = data; - chip->last_extdata = extdata; - data |= (nid << 20) | (verb << 8); - - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->rirb.cmds < LOLA_CORB_ENTRIES - 1) { - unsigned int wp = chip->corb.wp + 1; - wp %= LOLA_CORB_ENTRIES; - chip->corb.wp = wp; - chip->corb.buf[wp * 2] = cpu_to_le32(data); - chip->corb.buf[wp * 2 + 1] = cpu_to_le32(extdata); - lola_writew(chip, BAR0, CORBWP, wp); - chip->rirb.cmds++; - smp_wmb(); - ret = 0; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return ret; -} - -static void lola_queue_unsol_event(struct lola *chip, unsigned int res, - unsigned int res_ex) -{ - lola_update_ext_clock_freq(chip, res); -} - -/* retrieve RIRB entry - called from interrupt handler */ -static void lola_update_rirb(struct lola *chip) -{ - unsigned int rp, wp; - u32 res, res_ex; - - wp = lola_readw(chip, BAR0, RIRBWP); - if (wp == chip->rirb.wp) - return; - chip->rirb.wp = wp; - - while (chip->rirb.rp != wp) { - chip->rirb.rp++; - chip->rirb.rp %= LOLA_CORB_ENTRIES; - - rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ - res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); - res = le32_to_cpu(chip->rirb.buf[rp]); - if (res_ex & LOLA_RIRB_EX_UNSOL_EV) - lola_queue_unsol_event(chip, res, res_ex); - else if (chip->rirb.cmds) { - chip->res = res; - chip->res_ex = res_ex; - smp_wmb(); - chip->rirb.cmds--; - } - } -} - -static int rirb_get_response(struct lola *chip, unsigned int *val, - unsigned int *extval) -{ - unsigned long timeout; - - again: - timeout = jiffies + msecs_to_jiffies(1000); - for (;;) { - if (chip->polling_mode) { - spin_lock_irq(&chip->reg_lock); - lola_update_rirb(chip); - spin_unlock_irq(&chip->reg_lock); - } - if (!chip->rirb.cmds) { - *val = chip->res; - if (extval) - *extval = chip->res_ex; - verbose_debug("get_response: %x, %x\n", - chip->res, chip->res_ex); - if (chip->res_ex & LOLA_RIRB_EX_ERROR) { - printk(KERN_WARNING SFX "RIRB ERROR: " - "NID=%x, verb=%x, data=%x, ext=%x\n", - chip->last_cmd_nid, - chip->last_verb, chip->last_data, - chip->last_extdata); - return -EIO; - } - return 0; - } - if (time_after(jiffies, timeout)) - break; - udelay(20); - cond_resched(); - } - printk(KERN_WARNING SFX "RIRB response error\n"); - if (!chip->polling_mode) { - printk(KERN_WARNING SFX "switching to polling mode\n"); - chip->polling_mode = 1; - goto again; - } - return -EIO; -} - -/* aynchronous write of a codec verb with data */ -int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb, - unsigned int data, unsigned int extdata) -{ - verbose_debug("codec_write NID=%x, verb=%x, data=%x, ext=%x\n", - nid, verb, data, extdata); - return corb_send_verb(chip, nid, verb, data, extdata); -} - -/* write a codec verb with data and read the returned status */ -int lola_codec_read(struct lola *chip, unsigned int nid, unsigned int verb, - unsigned int data, unsigned int extdata, - unsigned int *val, unsigned int *extval) -{ - int err; - - verbose_debug("codec_read NID=%x, verb=%x, data=%x, ext=%x\n", - nid, verb, data, extdata); - err = corb_send_verb(chip, nid, verb, data, extdata); - if (err < 0) - return err; - err = rirb_get_response(chip, val, extval); - return err; -} - -/* flush all pending codec writes */ -int lola_codec_flush(struct lola *chip) -{ - unsigned int tmp; - return rirb_get_response(chip, &tmp, NULL); -} - -/* - * interrupt handler - */ -static irqreturn_t lola_interrupt(int irq, void *dev_id) -{ - struct lola *chip = dev_id; - unsigned int notify_ins, notify_outs, error_ins, error_outs; - int handled = 0; - int i; - - notify_ins = notify_outs = error_ins = error_outs = 0; - spin_lock(&chip->reg_lock); - for (;;) { - unsigned int status, in_sts, out_sts; - unsigned int reg; - - status = lola_readl(chip, BAR1, DINTSTS); - if (!status || status == -1) - break; - - in_sts = lola_readl(chip, BAR1, DIINTSTS); - out_sts = lola_readl(chip, BAR1, DOINTSTS); - - /* clear Input Interrupts */ - for (i = 0; in_sts && i < chip->pcm[CAPT].num_streams; i++) { - if (!(in_sts & (1 << i))) - continue; - in_sts &= ~(1 << i); - reg = lola_dsd_read(chip, i, STS); - if (reg & LOLA_DSD_STS_DESE) /* error */ - error_ins |= (1 << i); - if (reg & LOLA_DSD_STS_BCIS) /* notify */ - notify_ins |= (1 << i); - /* clear */ - lola_dsd_write(chip, i, STS, reg); - } - - /* clear Output Interrupts */ - for (i = 0; out_sts && i < chip->pcm[PLAY].num_streams; i++) { - if (!(out_sts & (1 << i))) - continue; - out_sts &= ~(1 << i); - reg = lola_dsd_read(chip, i + MAX_STREAM_IN_COUNT, STS); - if (reg & LOLA_DSD_STS_DESE) /* error */ - error_outs |= (1 << i); - if (reg & LOLA_DSD_STS_BCIS) /* notify */ - notify_outs |= (1 << i); - lola_dsd_write(chip, i + MAX_STREAM_IN_COUNT, STS, reg); - } - - if (status & LOLA_DINT_CTRL) { - unsigned char rbsts; /* ring status is byte access */ - rbsts = lola_readb(chip, BAR0, RIRBSTS); - rbsts &= LOLA_RIRB_INT_MASK; - if (rbsts) - lola_writeb(chip, BAR0, RIRBSTS, rbsts); - rbsts = lola_readb(chip, BAR0, CORBSTS); - rbsts &= LOLA_CORB_INT_MASK; - if (rbsts) - lola_writeb(chip, BAR0, CORBSTS, rbsts); - - lola_update_rirb(chip); - } - - if (status & (LOLA_DINT_FIFOERR | LOLA_DINT_MUERR)) { - /* clear global fifo error interrupt */ - lola_writel(chip, BAR1, DINTSTS, - (status & (LOLA_DINT_FIFOERR | LOLA_DINT_MUERR))); - } - handled = 1; - } - spin_unlock(&chip->reg_lock); - - lola_pcm_update(chip, &chip->pcm[CAPT], notify_ins); - lola_pcm_update(chip, &chip->pcm[PLAY], notify_outs); - - return IRQ_RETVAL(handled); -} - - -/* - * controller - */ -static int reset_controller(struct lola *chip) -{ - unsigned int gctl = lola_readl(chip, BAR0, GCTL); - unsigned long end_time; - - if (gctl) { - /* to be sure */ - lola_writel(chip, BAR1, BOARD_MODE, 0); - return 0; - } - - chip->cold_reset = 1; - lola_writel(chip, BAR0, GCTL, LOLA_GCTL_RESET); - end_time = jiffies + msecs_to_jiffies(200); - do { - msleep(1); - gctl = lola_readl(chip, BAR0, GCTL); - if (gctl) - break; - } while (time_before(jiffies, end_time)); - if (!gctl) { - printk(KERN_ERR SFX "cannot reset controller\n"); - return -EIO; - } - return 0; -} - -static void lola_irq_enable(struct lola *chip) -{ - unsigned int val; - - /* enalbe all I/O streams */ - val = (1 << chip->pcm[PLAY].num_streams) - 1; - lola_writel(chip, BAR1, DOINTCTL, val); - val = (1 << chip->pcm[CAPT].num_streams) - 1; - lola_writel(chip, BAR1, DIINTCTL, val); - - /* enable global irqs */ - val = LOLA_DINT_GLOBAL | LOLA_DINT_CTRL | LOLA_DINT_FIFOERR | - LOLA_DINT_MUERR; - lola_writel(chip, BAR1, DINTCTL, val); -} - -static void lola_irq_disable(struct lola *chip) -{ - lola_writel(chip, BAR1, DINTCTL, 0); - lola_writel(chip, BAR1, DIINTCTL, 0); - lola_writel(chip, BAR1, DOINTCTL, 0); -} - -static int setup_corb_rirb(struct lola *chip) -{ - int err; - unsigned char tmp; - unsigned long end_time; - - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - PAGE_SIZE, &chip->rb); - if (err < 0) - return err; - - chip->corb.addr = chip->rb.addr; - chip->corb.buf = (u32 *)chip->rb.area; - chip->rirb.addr = chip->rb.addr + 2048; - chip->rirb.buf = (u32 *)(chip->rb.area + 2048); - - /* disable ringbuffer DMAs */ - lola_writeb(chip, BAR0, RIRBCTL, 0); - lola_writeb(chip, BAR0, CORBCTL, 0); - - end_time = jiffies + msecs_to_jiffies(200); - do { - if (!lola_readb(chip, BAR0, RIRBCTL) && - !lola_readb(chip, BAR0, CORBCTL)) - break; - msleep(1); - } while (time_before(jiffies, end_time)); - - /* CORB set up */ - lola_writel(chip, BAR0, CORBLBASE, (u32)chip->corb.addr); - lola_writel(chip, BAR0, CORBUBASE, upper_32_bits(chip->corb.addr)); - /* set the corb size to 256 entries */ - lola_writeb(chip, BAR0, CORBSIZE, 0x02); - /* set the corb write pointer to 0 */ - lola_writew(chip, BAR0, CORBWP, 0); - /* reset the corb hw read pointer */ - lola_writew(chip, BAR0, CORBRP, LOLA_RBRWP_CLR); - /* enable corb dma */ - lola_writeb(chip, BAR0, CORBCTL, LOLA_RBCTL_DMA_EN); - /* clear flags if set */ - tmp = lola_readb(chip, BAR0, CORBSTS) & LOLA_CORB_INT_MASK; - if (tmp) - lola_writeb(chip, BAR0, CORBSTS, tmp); - chip->corb.wp = 0; - - /* RIRB set up */ - lola_writel(chip, BAR0, RIRBLBASE, (u32)chip->rirb.addr); - lola_writel(chip, BAR0, RIRBUBASE, upper_32_bits(chip->rirb.addr)); - /* set the rirb size to 256 entries */ - lola_writeb(chip, BAR0, RIRBSIZE, 0x02); - /* reset the rirb hw write pointer */ - lola_writew(chip, BAR0, RIRBWP, LOLA_RBRWP_CLR); - /* set N=1, get RIRB response interrupt for new entry */ - lola_writew(chip, BAR0, RINTCNT, 1); - /* enable rirb dma and response irq */ - lola_writeb(chip, BAR0, RIRBCTL, LOLA_RBCTL_DMA_EN | LOLA_RBCTL_IRQ_EN); - /* clear flags if set */ - tmp = lola_readb(chip, BAR0, RIRBSTS) & LOLA_RIRB_INT_MASK; - if (tmp) - lola_writeb(chip, BAR0, RIRBSTS, tmp); - chip->rirb.rp = chip->rirb.cmds = 0; - - return 0; -} - -static void stop_corb_rirb(struct lola *chip) -{ - /* disable ringbuffer DMAs */ - lola_writeb(chip, BAR0, RIRBCTL, 0); - lola_writeb(chip, BAR0, CORBCTL, 0); -} - -static void lola_reset_setups(struct lola *chip) -{ - /* update the granularity */ - lola_set_granularity(chip, chip->granularity, true); - /* update the sample clock */ - lola_set_clock_index(chip, chip->clock.cur_index); - /* enable unsolicited events of the clock widget */ - lola_enable_clock_events(chip); - /* update the analog gains */ - lola_setup_all_analog_gains(chip, CAPT, false); /* input, update */ - /* update SRC configuration if applicable */ - lola_set_src_config(chip, chip->input_src_mask, false); - /* update the analog outputs */ - lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */ -} - -static int __devinit lola_parse_tree(struct lola *chip) -{ - unsigned int val; - int nid, err; - - err = lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read VENDOR_ID\n"); - return err; - } - val >>= 16; - if (val != 0x1369) { - printk(KERN_ERR SFX "Unknown codec vendor 0x%x\n", val); - return -EINVAL; - } - - err = lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read FUNCTION_TYPE for 0x%x\n", nid); - return err; - } - if (val != 1) { - printk(KERN_ERR SFX "Unknown function type %d\n", val); - return -EINVAL; - } - - err = lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read SPECCAPS\n"); - return err; - } - chip->lola_caps = val; - chip->pin[CAPT].num_pins = LOLA_AFG_INPUT_PIN_COUNT(chip->lola_caps); - chip->pin[PLAY].num_pins = LOLA_AFG_OUTPUT_PIN_COUNT(chip->lola_caps); - snd_printdd(SFX "speccaps=0x%x, pins in=%d, out=%d\n", - chip->lola_caps, - chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins); - - if (chip->pin[CAPT].num_pins > MAX_AUDIO_INOUT_COUNT || - chip->pin[PLAY].num_pins > MAX_AUDIO_INOUT_COUNT) { - printk(KERN_ERR SFX "Invalid Lola-spec caps 0x%x\n", val); - return -EINVAL; - } - - nid = 0x02; - err = lola_init_pcm(chip, CAPT, &nid); - if (err < 0) - return err; - err = lola_init_pcm(chip, PLAY, &nid); - if (err < 0) - return err; - - err = lola_init_pins(chip, CAPT, &nid); - if (err < 0) - return err; - err = lola_init_pins(chip, PLAY, &nid); - if (err < 0) - return err; - - if (LOLA_AFG_CLOCK_WIDGET_PRESENT(chip->lola_caps)) { - err = lola_init_clock_widget(chip, nid); - if (err < 0) - return err; - nid++; - } - if (LOLA_AFG_MIXER_WIDGET_PRESENT(chip->lola_caps)) { - err = lola_init_mixer_widget(chip, nid); - if (err < 0) - return err; - nid++; - } - - /* enable unsolicited events of the clock widget */ - err = lola_enable_clock_events(chip); - if (err < 0) - return err; - - /* if last ResetController was not a ColdReset, we don't know - * the state of the card; initialize here again - */ - if (!chip->cold_reset) { - lola_reset_setups(chip); - chip->cold_reset = 1; - } else { - /* set the granularity if it is not the default */ - if (chip->granularity != LOLA_GRANULARITY_MIN) - lola_set_granularity(chip, chip->granularity, true); - } - - return 0; -} - -static void lola_stop_hw(struct lola *chip) -{ - stop_corb_rirb(chip); - lola_irq_disable(chip); -} - -static void lola_free(struct lola *chip) -{ - if (chip->initialized) - lola_stop_hw(chip); - lola_free_pcm(chip); - lola_free_mixer(chip); - if (chip->irq >= 0) - free_irq(chip->irq, (void *)chip); - if (chip->bar[0].remap_addr) - iounmap(chip->bar[0].remap_addr); - if (chip->bar[1].remap_addr) - iounmap(chip->bar[1].remap_addr); - if (chip->rb.area) - snd_dma_free_pages(&chip->rb); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); -} - -static int lola_dev_free(struct snd_device *device) -{ - lola_free(device->device_data); - return 0; -} - -static int __devinit lola_create(struct snd_card *card, struct pci_dev *pci, - int dev, struct lola **rchip) -{ - struct lola *chip; - int err; - unsigned int dever; - static struct snd_device_ops ops = { - .dev_free = lola_dev_free, - }; - - *rchip = NULL; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) { - snd_printk(KERN_ERR SFX "cannot allocate chip\n"); - pci_disable_device(pci); - return -ENOMEM; - } - - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->open_mutex); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - chip->granularity = granularity[dev]; - switch (chip->granularity) { - case 8: - chip->sample_rate_max = 48000; - break; - case 16: - chip->sample_rate_max = 96000; - break; - case 32: - chip->sample_rate_max = 192000; - break; - default: - snd_printk(KERN_WARNING SFX - "Invalid granularity %d, reset to %d\n", - chip->granularity, LOLA_GRANULARITY_MAX); - chip->granularity = LOLA_GRANULARITY_MAX; - chip->sample_rate_max = 192000; - break; - } - chip->sample_rate_min = sample_rate_min[dev]; - if (chip->sample_rate_min > chip->sample_rate_max) { - snd_printk(KERN_WARNING SFX - "Invalid sample_rate_min %d, reset to 16000\n", - chip->sample_rate_min); - chip->sample_rate_min = 16000; - } - - err = pci_request_regions(pci, DRVNAME); - if (err < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - - chip->bar[0].addr = pci_resource_start(pci, 0); - chip->bar[0].remap_addr = pci_ioremap_bar(pci, 0); - chip->bar[1].addr = pci_resource_start(pci, 2); - chip->bar[1].remap_addr = pci_ioremap_bar(pci, 2); - if (!chip->bar[0].remap_addr || !chip->bar[1].remap_addr) { - snd_printk(KERN_ERR SFX "ioremap error\n"); - err = -ENXIO; - goto errout; - } - - pci_set_master(pci); - - err = reset_controller(chip); - if (err < 0) - goto errout; - - if (request_irq(pci->irq, lola_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); - err = -EBUSY; - goto errout; - } - chip->irq = pci->irq; - synchronize_irq(chip->irq); - - dever = lola_readl(chip, BAR1, DEVER); - chip->pcm[CAPT].num_streams = (dever >> 0) & 0x3ff; - chip->pcm[PLAY].num_streams = (dever >> 10) & 0x3ff; - chip->version = (dever >> 24) & 0xff; - snd_printdd(SFX "streams in=%d, out=%d, version=0x%x\n", - chip->pcm[CAPT].num_streams, chip->pcm[PLAY].num_streams, - chip->version); - - /* Test LOLA_BAR1_DEVER */ - if (chip->pcm[CAPT].num_streams > MAX_STREAM_IN_COUNT || - chip->pcm[PLAY].num_streams > MAX_STREAM_OUT_COUNT || - (!chip->pcm[CAPT].num_streams && - !chip->pcm[PLAY].num_streams)) { - printk(KERN_ERR SFX "invalid DEVER = %x\n", dever); - err = -EINVAL; - goto errout; - } - - err = setup_corb_rirb(chip); - if (err < 0) - goto errout; - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); - goto errout; - } - - strcpy(card->driver, "Lola"); - strlcpy(card->shortname, "Digigram Lola", sizeof(card->shortname)); - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%lx irq %i", - card->shortname, chip->bar[0].addr, chip->irq); - strcpy(card->mixername, card->shortname); - - lola_irq_enable(chip); - - chip->initialized = 1; - *rchip = chip; - return 0; - - errout: - lola_free(chip); - return err; -} - -static int __devinit lola_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct lola *chip; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printk(KERN_ERR SFX "Error creating card!\n"); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - err = lola_create(card, pci, dev, &chip); - if (err < 0) - goto out_free; - card->private_data = chip; - - err = lola_parse_tree(chip); - if (err < 0) - goto out_free; - - err = lola_create_pcm(chip); - if (err < 0) - goto out_free; - - err = lola_create_mixer(chip); - if (err < 0) - goto out_free; - - lola_proc_debug_new(chip); - - err = snd_card_register(card); - if (err < 0) - goto out_free; - - pci_set_drvdata(pci, card); - dev++; - return err; -out_free: - snd_card_free(card); - return err; -} - -static void __devexit lola_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -/* PCI IDs */ -static DEFINE_PCI_DEVICE_TABLE(lola_ids) = { - { PCI_VDEVICE(DIGIGRAM, 0x0001) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, lola_ids); - -/* pci_driver definition */ -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = lola_ids, - .probe = lola_probe, - .remove = __devexit_p(lola_remove), -}; - -static int __init alsa_card_lola_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_lola_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_lola_init) -module_exit(alsa_card_lola_exit) diff --git a/ANDROID_3.4.5/sound/pci/lola/lola.h b/ANDROID_3.4.5/sound/pci/lola/lola.h deleted file mode 100644 index f0b10005..00000000 --- a/ANDROID_3.4.5/sound/pci/lola/lola.h +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Support for Digigram Lola PCI-e boards - * - * Copyright (c) 2011 Takashi Iwai - * - * 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. - */ - -#ifndef _LOLA_H -#define _LOLA_H - -#define DRVNAME "snd-lola" -#define SFX DRVNAME ": " - -/* - * Lola HD Audio Registers BAR0 - */ -#define LOLA_BAR0_GCAP 0x00 -#define LOLA_BAR0_VMIN 0x02 -#define LOLA_BAR0_VMAJ 0x03 -#define LOLA_BAR0_OUTPAY 0x04 -#define LOLA_BAR0_INPAY 0x06 -#define LOLA_BAR0_GCTL 0x08 -#define LOLA_BAR0_WAKEEN 0x0c -#define LOLA_BAR0_STATESTS 0x0e -#define LOLA_BAR0_GSTS 0x10 -#define LOLA_BAR0_OUTSTRMPAY 0x18 -#define LOLA_BAR0_INSTRMPAY 0x1a -#define LOLA_BAR0_INTCTL 0x20 -#define LOLA_BAR0_INTSTS 0x24 -#define LOLA_BAR0_WALCLK 0x30 -#define LOLA_BAR0_SSYNC 0x38 - -#define LOLA_BAR0_CORBLBASE 0x40 -#define LOLA_BAR0_CORBUBASE 0x44 -#define LOLA_BAR0_CORBWP 0x48 /* no ULONG access */ -#define LOLA_BAR0_CORBRP 0x4a /* no ULONG access */ -#define LOLA_BAR0_CORBCTL 0x4c /* no ULONG access */ -#define LOLA_BAR0_CORBSTS 0x4d /* UCHAR access only */ -#define LOLA_BAR0_CORBSIZE 0x4e /* no ULONG access */ - -#define LOLA_BAR0_RIRBLBASE 0x50 -#define LOLA_BAR0_RIRBUBASE 0x54 -#define LOLA_BAR0_RIRBWP 0x58 -#define LOLA_BAR0_RINTCNT 0x5a /* no ULONG access */ -#define LOLA_BAR0_RIRBCTL 0x5c -#define LOLA_BAR0_RIRBSTS 0x5d /* UCHAR access only */ -#define LOLA_BAR0_RIRBSIZE 0x5e /* no ULONG access */ - -#define LOLA_BAR0_ICW 0x60 -#define LOLA_BAR0_IRR 0x64 -#define LOLA_BAR0_ICS 0x68 -#define LOLA_BAR0_DPLBASE 0x70 -#define LOLA_BAR0_DPUBASE 0x74 - -/* stream register offsets from stream base 0x80 */ -#define LOLA_BAR0_SD0_OFFSET 0x80 -#define LOLA_REG0_SD_CTL 0x00 -#define LOLA_REG0_SD_STS 0x03 -#define LOLA_REG0_SD_LPIB 0x04 -#define LOLA_REG0_SD_CBL 0x08 -#define LOLA_REG0_SD_LVI 0x0c -#define LOLA_REG0_SD_FIFOW 0x0e -#define LOLA_REG0_SD_FIFOSIZE 0x10 -#define LOLA_REG0_SD_FORMAT 0x12 -#define LOLA_REG0_SD_BDLPL 0x18 -#define LOLA_REG0_SD_BDLPU 0x1c - -/* - * Lola Digigram Registers BAR1 - */ -#define LOLA_BAR1_FPGAVER 0x00 -#define LOLA_BAR1_DEVER 0x04 -#define LOLA_BAR1_UCBMV 0x08 -#define LOLA_BAR1_JTAG 0x0c -#define LOLA_BAR1_UARTRX 0x10 -#define LOLA_BAR1_UARTTX 0x14 -#define LOLA_BAR1_UARTCR 0x18 -#define LOLA_BAR1_NVRAMVER 0x1c -#define LOLA_BAR1_CTRLSPI 0x20 -#define LOLA_BAR1_DSPI 0x24 -#define LOLA_BAR1_AISPI 0x28 -#define LOLA_BAR1_GRAN 0x2c - -#define LOLA_BAR1_DINTCTL 0x80 -#define LOLA_BAR1_DIINTCTL 0x84 -#define LOLA_BAR1_DOINTCTL 0x88 -#define LOLA_BAR1_LRC 0x90 -#define LOLA_BAR1_DINTSTS 0x94 -#define LOLA_BAR1_DIINTSTS 0x98 -#define LOLA_BAR1_DOINTSTS 0x9c - -#define LOLA_BAR1_DSD0_OFFSET 0xa0 -#define LOLA_BAR1_DSD_SIZE 0x18 - -#define LOLA_BAR1_DSDnSTS 0x00 -#define LOLA_BAR1_DSDnLPIB 0x04 -#define LOLA_BAR1_DSDnCTL 0x08 -#define LOLA_BAR1_DSDnLVI 0x0c -#define LOLA_BAR1_DSDnBDPL 0x10 -#define LOLA_BAR1_DSDnBDPU 0x14 - -#define LOLA_BAR1_SSYNC 0x03e8 - -#define LOLA_BAR1_BOARD_CTRL 0x0f00 -#define LOLA_BAR1_BOARD_MODE 0x0f02 - -#define LOLA_BAR1_SOURCE_GAIN_ENABLE 0x1000 -#define LOLA_BAR1_DEST00_MIX_GAIN_ENABLE 0x1004 -#define LOLA_BAR1_DEST31_MIX_GAIN_ENABLE 0x1080 -#define LOLA_BAR1_SOURCE00_01_GAIN 0x1084 -#define LOLA_BAR1_SOURCE30_31_GAIN 0x10c0 -#define LOLA_BAR1_SOURCE_GAIN(src) \ - (LOLA_BAR1_SOURCE00_01_GAIN + (src) * 2) -#define LOLA_BAR1_DEST00_MIX00_01_GAIN 0x10c4 -#define LOLA_BAR1_DEST00_MIX30_31_GAIN 0x1100 -#define LOLA_BAR1_DEST01_MIX00_01_GAIN 0x1104 -#define LOLA_BAR1_DEST01_MIX30_31_GAIN 0x1140 -#define LOLA_BAR1_DEST31_MIX00_01_GAIN 0x1884 -#define LOLA_BAR1_DEST31_MIX30_31_GAIN 0x18c0 -#define LOLA_BAR1_MIX_GAIN(dest, mix) \ - (LOLA_BAR1_DEST00_MIX00_01_GAIN + (dest) * 0x40 + (mix) * 2) -#define LOLA_BAR1_ANALOG_CLIP_IN 0x18c4 -#define LOLA_BAR1_PEAKMETERS_SOURCE00_01 0x18c8 -#define LOLA_BAR1_PEAKMETERS_SOURCE30_31 0x1904 -#define LOLA_BAR1_PEAKMETERS_SOURCE(src) \ - (LOLA_BAR1_PEAKMETERS_SOURCE00_01 + (src) * 2) -#define LOLA_BAR1_PEAKMETERS_DEST00_01 0x1908 -#define LOLA_BAR1_PEAKMETERS_DEST30_31 0x1944 -#define LOLA_BAR1_PEAKMETERS_DEST(dest) \ - (LOLA_BAR1_PEAKMETERS_DEST00_01 + (dest) * 2) -#define LOLA_BAR1_PEAKMETERS_AGC00_01 0x1948 -#define LOLA_BAR1_PEAKMETERS_AGC14_15 0x1964 -#define LOLA_BAR1_PEAKMETERS_AGC(x) \ - (LOLA_BAR1_PEAKMETERS_AGC00_01 + (x) * 2) - -/* GCTL reset bit */ -#define LOLA_GCTL_RESET (1 << 0) -/* GCTL unsolicited response enable bit */ -#define LOLA_GCTL_UREN (1 << 8) - -/* CORB/RIRB control, read/write pointer */ -#define LOLA_RBCTL_DMA_EN 0x02 /* enable DMA */ -#define LOLA_RBCTL_IRQ_EN 0x01 /* enable IRQ */ -#define LOLA_RBRWP_CLR 0x8000 /* read/write pointer clear */ - -#define LOLA_RIRB_EX_UNSOL_EV 0x40000000 -#define LOLA_RIRB_EX_ERROR 0x80000000 - -/* CORB int mask: CMEI[0] */ -#define LOLA_CORB_INT_CMEI 0x01 -#define LOLA_CORB_INT_MASK LOLA_CORB_INT_CMEI - -/* RIRB int mask: overrun[2], response[0] */ -#define LOLA_RIRB_INT_RESPONSE 0x01 -#define LOLA_RIRB_INT_OVERRUN 0x04 -#define LOLA_RIRB_INT_MASK (LOLA_RIRB_INT_RESPONSE | LOLA_RIRB_INT_OVERRUN) - -/* DINTCTL and DINTSTS */ -#define LOLA_DINT_GLOBAL 0x80000000 /* global interrupt enable bit */ -#define LOLA_DINT_CTRL 0x40000000 /* controller interrupt enable bit */ -#define LOLA_DINT_FIFOERR 0x20000000 /* global fifo error enable bit */ -#define LOLA_DINT_MUERR 0x10000000 /* global microcontroller underrun error */ - -/* DSDnCTL bits */ -#define LOLA_DSD_CTL_SRST 0x01 /* stream reset bit */ -#define LOLA_DSD_CTL_SRUN 0x02 /* stream DMA start bit */ -#define LOLA_DSD_CTL_IOCE 0x04 /* interrupt on completion enable */ -#define LOLA_DSD_CTL_DEIE 0x10 /* descriptor error interrupt enable */ -#define LOLA_DSD_CTL_VLRCV 0x20 /* valid LRCountValue information in bits 8..31 */ -#define LOLA_LRC_MASK 0xffffff00 - -/* DSDnSTS */ -#define LOLA_DSD_STS_BCIS 0x04 /* buffer completion interrupt status */ -#define LOLA_DSD_STS_DESE 0x10 /* descriptor error interrupt */ -#define LOLA_DSD_STS_FIFORDY 0x20 /* fifo ready */ - -#define LOLA_CORB_ENTRIES 256 - -#define MAX_STREAM_IN_COUNT 16 -#define MAX_STREAM_OUT_COUNT 16 -#define MAX_STREAM_COUNT 16 -#define MAX_PINS MAX_STREAM_COUNT -#define MAX_STREAM_BUFFER_COUNT 16 -#define MAX_AUDIO_INOUT_COUNT 16 - -#define LOLA_CLOCK_TYPE_INTERNAL 0 -#define LOLA_CLOCK_TYPE_AES 1 -#define LOLA_CLOCK_TYPE_AES_SYNC 2 -#define LOLA_CLOCK_TYPE_WORDCLOCK 3 -#define LOLA_CLOCK_TYPE_ETHERSOUND 4 -#define LOLA_CLOCK_TYPE_VIDEO 5 - -#define LOLA_CLOCK_FORMAT_NONE 0 -#define LOLA_CLOCK_FORMAT_NTSC 1 -#define LOLA_CLOCK_FORMAT_PAL 2 - -#define MAX_SAMPLE_CLOCK_COUNT 48 - -/* parameters used with mixer widget's mixer capabilities */ -#define LOLA_PEAK_METER_CAN_AGC_MASK 1 -#define LOLA_PEAK_METER_CAN_ANALOG_CLIP_MASK 2 - -struct lola_bar { - unsigned long addr; - void __iomem *remap_addr; -}; - -/* CORB/RIRB */ -struct lola_rb { - u32 *buf; /* CORB/RIRB buffer, 8 byte per each entry */ - dma_addr_t addr; /* physical address of CORB/RIRB buffer */ - unsigned short rp, wp; /* read/write pointers */ - int cmds; /* number of pending requests */ -}; - -/* Pin widget setup */ -struct lola_pin { - unsigned int nid; - bool is_analog; - unsigned int amp_mute; - unsigned int amp_step_size; - unsigned int amp_num_steps; - unsigned int amp_offset; - unsigned int max_level; - unsigned int config_default_reg; - unsigned int fixed_gain_list_len; - unsigned int cur_gain_step; -}; - -struct lola_pin_array { - unsigned int num_pins; - unsigned int num_analog_pins; - struct lola_pin pins[MAX_PINS]; -}; - -/* Clock widget setup */ -struct lola_sample_clock { - unsigned int type; - unsigned int format; - unsigned int freq; -}; - -struct lola_clock_widget { - unsigned int nid; - unsigned int items; - unsigned int cur_index; - unsigned int cur_freq; - bool cur_valid; - struct lola_sample_clock sample_clock[MAX_SAMPLE_CLOCK_COUNT]; - unsigned int idx_lookup[MAX_SAMPLE_CLOCK_COUNT]; -}; - -#define LOLA_MIXER_DIM 32 -struct lola_mixer_array { - u32 src_gain_enable; - u32 dest_mix_gain_enable[LOLA_MIXER_DIM]; - u16 src_gain[LOLA_MIXER_DIM]; - u16 dest_mix_gain[LOLA_MIXER_DIM][LOLA_MIXER_DIM]; -}; - -/* Mixer widget setup */ -struct lola_mixer_widget { - unsigned int nid; - unsigned int caps; - struct lola_mixer_array __user *array; - struct lola_mixer_array *array_saved; - unsigned int src_stream_outs; - unsigned int src_phys_ins; - unsigned int dest_stream_ins; - unsigned int dest_phys_outs; - unsigned int src_stream_out_ofs; - unsigned int dest_phys_out_ofs; - unsigned int src_mask; - unsigned int dest_mask; -}; - -/* Audio stream */ -struct lola_stream { - unsigned int nid; /* audio widget NID */ - unsigned int index; /* array index */ - unsigned int dsd; /* DSD index */ - bool can_float; - struct snd_pcm_substream *substream; /* assigned PCM substream */ - struct lola_stream *master; /* master stream (for multi-channel) */ - - /* buffer setup */ - unsigned int bufsize; - unsigned int period_bytes; - unsigned int frags; - - /* format + channel setup */ - unsigned int format_verb; - - /* flags */ - unsigned int opened:1; - unsigned int prepared:1; - unsigned int paused:1; - unsigned int running:1; -}; - -#define PLAY SNDRV_PCM_STREAM_PLAYBACK -#define CAPT SNDRV_PCM_STREAM_CAPTURE - -struct lola_pcm { - unsigned int num_streams; - struct snd_dma_buffer bdl; /* BDL buffer */ - struct lola_stream streams[MAX_STREAM_COUNT]; -}; - -/* card instance */ -struct lola { - struct snd_card *card; - struct pci_dev *pci; - - /* pci resources */ - struct lola_bar bar[2]; - int irq; - - /* locks */ - spinlock_t reg_lock; - struct mutex open_mutex; - - /* CORB/RIRB */ - struct lola_rb corb; - struct lola_rb rirb; - unsigned int res, res_ex; /* last read values */ - /* last command (for debugging) */ - unsigned int last_cmd_nid, last_verb, last_data, last_extdata; - - /* CORB/RIRB buffers */ - struct snd_dma_buffer rb; - - /* unsolicited events */ - unsigned int last_unsol_res; - - /* streams */ - struct lola_pcm pcm[2]; - - /* input src */ - unsigned int input_src_caps_mask; - unsigned int input_src_mask; - - /* pins */ - struct lola_pin_array pin[2]; - - /* clock */ - struct lola_clock_widget clock; - int ref_count_rate; - unsigned int sample_rate; - - /* mixer */ - struct lola_mixer_widget mixer; - - /* hw info */ - unsigned int version; - unsigned int lola_caps; - - /* parameters */ - unsigned int granularity; - unsigned int sample_rate_min; - unsigned int sample_rate_max; - - /* flags */ - unsigned int initialized:1; - unsigned int cold_reset:1; - unsigned int polling_mode:1; - - /* for debugging */ - unsigned int debug_res; - unsigned int debug_res_ex; -}; - -#define BAR0 0 -#define BAR1 1 - -/* Helper macros */ -#define lola_readl(chip, idx, name) \ - readl((chip)->bar[idx].remap_addr + LOLA_##idx##_##name) -#define lola_readw(chip, idx, name) \ - readw((chip)->bar[idx].remap_addr + LOLA_##idx##_##name) -#define lola_readb(chip, idx, name) \ - readb((chip)->bar[idx].remap_addr + LOLA_##idx##_##name) -#define lola_writel(chip, idx, name, val) \ - writel((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name) -#define lola_writew(chip, idx, name, val) \ - writew((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name) -#define lola_writeb(chip, idx, name, val) \ - writeb((val), (chip)->bar[idx].remap_addr + LOLA_##idx##_##name) - -#define lola_dsd_read(chip, dsd, name) \ - readl((chip)->bar[BAR1].remap_addr + LOLA_BAR1_DSD0_OFFSET + \ - (LOLA_BAR1_DSD_SIZE * (dsd)) + LOLA_BAR1_DSDn##name) -#define lola_dsd_write(chip, dsd, name, val) \ - writel((val), (chip)->bar[BAR1].remap_addr + LOLA_BAR1_DSD0_OFFSET + \ - (LOLA_BAR1_DSD_SIZE * (dsd)) + LOLA_BAR1_DSDn##name) - -/* GET verbs HDAudio */ -#define LOLA_VERB_GET_STREAM_FORMAT 0xa00 -#define LOLA_VERB_GET_AMP_GAIN_MUTE 0xb00 -#define LOLA_VERB_PARAMETERS 0xf00 -#define LOLA_VERB_GET_POWER_STATE 0xf05 -#define LOLA_VERB_GET_CONV 0xf06 -#define LOLA_VERB_GET_UNSOLICITED_RESPONSE 0xf08 -#define LOLA_VERB_GET_DIGI_CONVERT_1 0xf0d -#define LOLA_VERB_GET_CONFIG_DEFAULT 0xf1c -#define LOLA_VERB_GET_SUBSYSTEM_ID 0xf20 -/* GET verbs Digigram */ -#define LOLA_VERB_GET_FIXED_GAIN 0xfc0 -#define LOLA_VERB_GET_GAIN_SELECT 0xfc1 -#define LOLA_VERB_GET_MAX_LEVEL 0xfc2 -#define LOLA_VERB_GET_CLOCK_LIST 0xfc3 -#define LOLA_VERB_GET_CLOCK_SELECT 0xfc4 -#define LOLA_VERB_GET_CLOCK_STATUS 0xfc5 - -/* SET verbs HDAudio */ -#define LOLA_VERB_SET_STREAM_FORMAT 0x200 -#define LOLA_VERB_SET_AMP_GAIN_MUTE 0x300 -#define LOLA_VERB_SET_POWER_STATE 0x705 -#define LOLA_VERB_SET_CHANNEL_STREAMID 0x706 -#define LOLA_VERB_SET_UNSOLICITED_ENABLE 0x708 -#define LOLA_VERB_SET_DIGI_CONVERT_1 0x70d -/* SET verbs Digigram */ -#define LOLA_VERB_SET_GAIN_SELECT 0xf81 -#define LOLA_VERB_SET_CLOCK_SELECT 0xf84 -#define LOLA_VERB_SET_GRANULARITY_STEPS 0xf86 -#define LOLA_VERB_SET_SOURCE_GAIN 0xf87 -#define LOLA_VERB_SET_MIX_GAIN 0xf88 -#define LOLA_VERB_SET_DESTINATION_GAIN 0xf89 -#define LOLA_VERB_SET_SRC 0xf8a - -/* Parameter IDs used with LOLA_VERB_PARAMETERS */ -#define LOLA_PAR_VENDOR_ID 0x00 -#define LOLA_PAR_FUNCTION_TYPE 0x05 -#define LOLA_PAR_AUDIO_WIDGET_CAP 0x09 -#define LOLA_PAR_PCM 0x0a -#define LOLA_PAR_STREAM_FORMATS 0x0b -#define LOLA_PAR_PIN_CAP 0x0c -#define LOLA_PAR_AMP_IN_CAP 0x0d -#define LOLA_PAR_CONNLIST_LEN 0x0e -#define LOLA_PAR_POWER_STATE 0x0f -#define LOLA_PAR_GPIO_CAP 0x11 -#define LOLA_PAR_AMP_OUT_CAP 0x12 -#define LOLA_PAR_SPECIFIC_CAPS 0x80 -#define LOLA_PAR_FIXED_GAIN_LIST 0x81 - -/* extract results of LOLA_PAR_SPECIFIC_CAPS */ -#define LOLA_AFG_MIXER_WIDGET_PRESENT(res) ((res & (1 << 21)) != 0) -#define LOLA_AFG_CLOCK_WIDGET_PRESENT(res) ((res & (1 << 20)) != 0) -#define LOLA_AFG_INPUT_PIN_COUNT(res) ((res >> 10) & 0x2ff) -#define LOLA_AFG_OUTPUT_PIN_COUNT(res) ((res) & 0x2ff) - -/* extract results of LOLA_PAR_AMP_IN_CAP / LOLA_PAR_AMP_OUT_CAP */ -#define LOLA_AMP_MUTE_CAPABLE(res) ((res & (1 << 31)) != 0) -#define LOLA_AMP_STEP_SIZE(res) ((res >> 24) & 0x7f) -#define LOLA_AMP_NUM_STEPS(res) ((res >> 12) & 0x3ff) -#define LOLA_AMP_OFFSET(res) ((res) & 0x3ff) - -#define LOLA_GRANULARITY_MIN 8 -#define LOLA_GRANULARITY_MAX 32 -#define LOLA_GRANULARITY_STEP 8 - -/* parameters used with unsolicited command/response */ -#define LOLA_UNSOLICITED_TAG_MASK 0x3f -#define LOLA_UNSOLICITED_TAG 0x1a -#define LOLA_UNSOLICITED_ENABLE 0x80 -#define LOLA_UNSOL_RESP_TAG_OFFSET 26 - -/* count values in the Vendor Specific Mixer Widget's Audio Widget Capabilities */ -#define LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(res) ((res >> 2) & 0x1f) -#define LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(res) ((res >> 7) & 0x1f) - -int lola_codec_write(struct lola *chip, unsigned int nid, unsigned int verb, - unsigned int data, unsigned int extdata); -int lola_codec_read(struct lola *chip, unsigned int nid, unsigned int verb, - unsigned int data, unsigned int extdata, - unsigned int *val, unsigned int *extval); -int lola_codec_flush(struct lola *chip); -#define lola_read_param(chip, nid, param, val) \ - lola_codec_read(chip, nid, LOLA_VERB_PARAMETERS, param, 0, val, NULL) - -/* PCM */ -int lola_create_pcm(struct lola *chip); -void lola_free_pcm(struct lola *chip); -int lola_init_pcm(struct lola *chip, int dir, int *nidp); -void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits); - -/* clock */ -int lola_init_clock_widget(struct lola *chip, int nid); -int lola_set_granularity(struct lola *chip, unsigned int val, bool force); -int lola_enable_clock_events(struct lola *chip); -int lola_set_clock_index(struct lola *chip, unsigned int idx); -int lola_set_clock(struct lola *chip, int idx); -int lola_set_sample_rate(struct lola *chip, int rate); -bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val); -unsigned int lola_sample_rate_convert(unsigned int coded); - -/* mixer */ -int lola_init_pins(struct lola *chip, int dir, int *nidp); -int lola_init_mixer_widget(struct lola *chip, int nid); -void lola_free_mixer(struct lola *chip); -int lola_create_mixer(struct lola *chip); -int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute); -void lola_save_mixer(struct lola *chip); -void lola_restore_mixer(struct lola *chip); -int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update); - -/* proc */ -#ifdef CONFIG_SND_DEBUG -void lola_proc_debug_new(struct lola *chip); -#else -#define lola_proc_debug_new(chip) -#endif - -#endif /* _LOLA_H */ diff --git a/ANDROID_3.4.5/sound/pci/lola/lola_clock.c b/ANDROID_3.4.5/sound/pci/lola/lola_clock.c deleted file mode 100644 index 72f8ef0a..00000000 --- a/ANDROID_3.4.5/sound/pci/lola/lola_clock.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Support for Digigram Lola PCI-e boards - * - * Copyright (c) 2011 Takashi Iwai - * - * 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 "lola.h" - -unsigned int lola_sample_rate_convert(unsigned int coded) -{ - unsigned int freq; - - /* base frequency */ - switch (coded & 0x3) { - case 0: freq = 48000; break; - case 1: freq = 44100; break; - case 2: freq = 32000; break; - default: return 0; /* error */ - } - - /* multiplier / devisor */ - switch (coded & 0x1c) { - case (0 << 2): break; - case (4 << 2): break; - case (1 << 2): freq *= 2; break; - case (2 << 2): freq *= 4; break; - case (5 << 2): freq /= 2; break; - case (6 << 2): freq /= 4; break; - default: return 0; /* error */ - } - - /* ajustement */ - switch (coded & 0x60) { - case (0 << 5): break; - case (1 << 5): freq = (freq * 999) / 1000; break; - case (2 << 5): freq = (freq * 1001) / 1000; break; - default: return 0; /* error */ - } - return freq; -} - -/* - * Granualrity - */ - -#define LOLA_MAXFREQ_AT_GRANULARITY_MIN 48000 -#define LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX 96000 - -static bool check_gran_clock_compatibility(struct lola *chip, - unsigned int val, - unsigned int freq) -{ - if (!chip->granularity) - return true; - - if (val < LOLA_GRANULARITY_MIN || val > LOLA_GRANULARITY_MAX || - (val % LOLA_GRANULARITY_STEP) != 0) - return false; - - if (val == LOLA_GRANULARITY_MIN) { - if (freq > LOLA_MAXFREQ_AT_GRANULARITY_MIN) - return false; - } else if (val < LOLA_GRANULARITY_MAX) { - if (freq > LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX) - return false; - } - return true; -} - -int lola_set_granularity(struct lola *chip, unsigned int val, bool force) -{ - int err; - - if (!force) { - if (val == chip->granularity) - return 0; -#if 0 - /* change Gran only if there are no streams allocated ! */ - if (chip->audio_in_alloc_mask || chip->audio_out_alloc_mask) - return -EBUSY; -#endif - if (!check_gran_clock_compatibility(chip, val, - chip->clock.cur_freq)) - return -EINVAL; - } - - chip->granularity = val; - val /= LOLA_GRANULARITY_STEP; - - /* audio function group */ - err = lola_codec_write(chip, 1, LOLA_VERB_SET_GRANULARITY_STEPS, - val, 0); - if (err < 0) - return err; - /* this can be a very slow function !!! */ - usleep_range(400 * val, 20000); - return lola_codec_flush(chip); -} - -/* - * Clock widget handling - */ - -int __devinit lola_init_clock_widget(struct lola *chip, int nid) -{ - unsigned int val; - int i, j, nitems, nb_verbs, idx, idx_list; - int err; - - err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); - return err; - } - - if ((val & 0xfff00000) != 0x01f00000) { /* test SubType and Type */ - snd_printdd("No valid clock widget\n"); - return 0; - } - - chip->clock.nid = nid; - chip->clock.items = val & 0xff; - snd_printdd("clock_list nid=%x, entries=%d\n", nid, - chip->clock.items); - if (chip->clock.items > MAX_SAMPLE_CLOCK_COUNT) { - printk(KERN_ERR SFX "CLOCK_LIST too big: %d\n", - chip->clock.items); - return -EINVAL; - } - - nitems = chip->clock.items; - nb_verbs = (nitems + 3) / 4; - idx = 0; - idx_list = 0; - for (i = 0; i < nb_verbs; i++) { - unsigned int res_ex; - unsigned short items[4]; - - err = lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST, - idx, 0, &val, &res_ex); - if (err < 0) { - printk(KERN_ERR SFX "Can't read CLOCK_LIST\n"); - return -EINVAL; - } - - items[0] = val & 0xfff; - items[1] = (val >> 16) & 0xfff; - items[2] = res_ex & 0xfff; - items[3] = (res_ex >> 16) & 0xfff; - - for (j = 0; j < 4; j++) { - unsigned char type = items[j] >> 8; - unsigned int freq = items[j] & 0xff; - int format = LOLA_CLOCK_FORMAT_NONE; - bool add_clock = true; - if (type == LOLA_CLOCK_TYPE_INTERNAL) { - freq = lola_sample_rate_convert(freq); - if (freq < chip->sample_rate_min) - add_clock = false; - else if (freq == 48000) { - chip->clock.cur_index = idx_list; - chip->clock.cur_freq = 48000; - chip->clock.cur_valid = true; - } - } else if (type == LOLA_CLOCK_TYPE_VIDEO) { - freq = lola_sample_rate_convert(freq); - if (freq < chip->sample_rate_min) - add_clock = false; - /* video clock has a format (0:NTSC, 1:PAL)*/ - if (items[j] & 0x80) - format = LOLA_CLOCK_FORMAT_NTSC; - else - format = LOLA_CLOCK_FORMAT_PAL; - } - if (add_clock) { - struct lola_sample_clock *sc; - sc = &chip->clock.sample_clock[idx_list]; - sc->type = type; - sc->format = format; - sc->freq = freq; - /* keep the index used with the board */ - chip->clock.idx_lookup[idx_list] = idx; - idx_list++; - } else { - chip->clock.items--; - } - if (++idx >= nitems) - break; - } - } - return 0; -} - -/* enable unsolicited events of the clock widget */ -int lola_enable_clock_events(struct lola *chip) -{ - unsigned int res; - int err; - - err = lola_codec_read(chip, chip->clock.nid, - LOLA_VERB_SET_UNSOLICITED_ENABLE, - LOLA_UNSOLICITED_ENABLE | LOLA_UNSOLICITED_TAG, - 0, &res, NULL); - if (err < 0) - return err; - if (res) { - printk(KERN_WARNING SFX "error in enable_clock_events %d\n", - res); - return -EINVAL; - } - return 0; -} - -int lola_set_clock_index(struct lola *chip, unsigned int idx) -{ - unsigned int res; - int err; - - err = lola_codec_read(chip, chip->clock.nid, - LOLA_VERB_SET_CLOCK_SELECT, - chip->clock.idx_lookup[idx], - 0, &res, NULL); - if (err < 0) - return err; - if (res) { - printk(KERN_WARNING SFX "error in set_clock %d\n", res); - return -EINVAL; - } - return 0; -} - -bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val) -{ - unsigned int tag; - - /* the current EXTERNAL clock information gets updated by interrupt - * with an unsolicited response - */ - if (!val) - return false; - tag = (val >> LOLA_UNSOL_RESP_TAG_OFFSET) & LOLA_UNSOLICITED_TAG_MASK; - if (tag != LOLA_UNSOLICITED_TAG) - return false; - - /* only for current = external clocks */ - if (chip->clock.sample_clock[chip->clock.cur_index].type != - LOLA_CLOCK_TYPE_INTERNAL) { - chip->clock.cur_freq = lola_sample_rate_convert(val & 0x7f); - chip->clock.cur_valid = (val & 0x100) != 0; - } - return true; -} - -int lola_set_clock(struct lola *chip, int idx) -{ - int freq = 0; - bool valid = false; - - if (idx == chip->clock.cur_index) { - /* current clock is allowed */ - freq = chip->clock.cur_freq; - valid = chip->clock.cur_valid; - } else if (chip->clock.sample_clock[idx].type == - LOLA_CLOCK_TYPE_INTERNAL) { - /* internal clocks allowed */ - freq = chip->clock.sample_clock[idx].freq; - valid = true; - } - - if (!freq || !valid) - return -EINVAL; - - if (!check_gran_clock_compatibility(chip, chip->granularity, freq)) - return -EINVAL; - - if (idx != chip->clock.cur_index) { - int err = lola_set_clock_index(chip, idx); - if (err < 0) - return err; - /* update new settings */ - chip->clock.cur_index = idx; - chip->clock.cur_freq = freq; - chip->clock.cur_valid = true; - } - return 0; -} - -int lola_set_sample_rate(struct lola *chip, int rate) -{ - int i; - - if (chip->clock.cur_freq == rate && chip->clock.cur_valid) - return 0; - /* search for new dwClockIndex */ - for (i = 0; i < chip->clock.items; i++) { - if (chip->clock.sample_clock[i].type == LOLA_CLOCK_TYPE_INTERNAL && - chip->clock.sample_clock[i].freq == rate) - break; - } - if (i >= chip->clock.items) - return -EINVAL; - return lola_set_clock(chip, i); -} - diff --git a/ANDROID_3.4.5/sound/pci/lola/lola_mixer.c b/ANDROID_3.4.5/sound/pci/lola/lola_mixer.c deleted file mode 100644 index 6b8d6481..00000000 --- a/ANDROID_3.4.5/sound/pci/lola/lola_mixer.c +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Support for Digigram Lola PCI-e boards - * - * Copyright (c) 2011 Takashi Iwai - * - * 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 "lola.h" - -static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin, - int dir, int nid) -{ - unsigned int val; - int err; - - pin->nid = nid; - err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); - return err; - } - val &= 0x00f00fff; /* test TYPE and bits 0..11 */ - if (val == 0x00400200) /* Type = 4, Digital = 1 */ - pin->is_analog = false; - else if (val == 0x0040000a && dir == CAPT) /* Dig=0, InAmp/ovrd */ - pin->is_analog = true; - else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */ - pin->is_analog = true; - else { - printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", val, nid); - return -EINVAL; - } - - /* analog parameters only following, so continue in case of Digital pin - */ - if (!pin->is_analog) - return 0; - - if (dir == PLAY) - err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val); - else - err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read AMP-caps for 0x%x\n", nid); - return err; - } - - pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val); - pin->amp_step_size = LOLA_AMP_STEP_SIZE(val); - pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val); - if (pin->amp_num_steps) { - /* zero as mute state */ - pin->amp_num_steps++; - pin->amp_step_size++; - } - pin->amp_offset = LOLA_AMP_OFFSET(val); - - err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val, - NULL); - if (err < 0) { - printk(KERN_ERR SFX "Can't get MAX_LEVEL 0x%x\n", nid); - return err; - } - pin->max_level = val & 0x3ff; /* 10 bits */ - - pin->config_default_reg = 0; - pin->fixed_gain_list_len = 0; - pin->cur_gain_step = 0; - - return 0; -} - -int __devinit lola_init_pins(struct lola *chip, int dir, int *nidp) -{ - int i, err, nid; - nid = *nidp; - for (i = 0; i < chip->pin[dir].num_pins; i++, nid++) { - err = lola_init_pin(chip, &chip->pin[dir].pins[i], dir, nid); - if (err < 0) - return err; - if (chip->pin[dir].pins[i].is_analog) - chip->pin[dir].num_analog_pins++; - } - *nidp = nid; - return 0; -} - -void lola_free_mixer(struct lola *chip) -{ - if (chip->mixer.array_saved) - vfree(chip->mixer.array_saved); -} - -int __devinit lola_init_mixer_widget(struct lola *chip, int nid) -{ - unsigned int val; - int err; - - err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); - return err; - } - - if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */ - snd_printdd("No valid mixer widget\n"); - return 0; - } - - chip->mixer.nid = nid; - chip->mixer.caps = val; - chip->mixer.array = (struct lola_mixer_array __iomem *) - (chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE); - - /* reserve memory to copy mixer data for sleep mode transitions */ - chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array)); - - /* mixer matrix sources are physical input data and play streams */ - chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams; - chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins; - - /* mixer matrix destinations are record streams and physical output */ - chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams; - chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins; - - /* mixer matrix may have unused areas between PhysIn and - * Play or Record and PhysOut zones - */ - chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins + - LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val); - chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins + - LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(val); - - /* example : MixerMatrix of LoLa881 (LoLa16161 uses unused zones) - * +-+ 0-------8------16-------8------16 - * | | | | | | | - * |s| | INPUT | | INPUT | | - * | |->| -> |unused | -> |unused | - * |r| |CAPTURE| | OUTPUT| | - * | | | MIX | | MIX | | - * |c| 8-------------------------------- - * | | | | | | | - * | | | | | | | - * |g| |unused |unused |unused |unused | - * | | | | | | | - * |a| | | | | | - * | | 16------------------------------- - * |i| | | | | | - * | | | PLAYBK| | PLAYBK| | - * |n|->| -> |unused | -> |unused | - * | | |CAPTURE| | OUTPUT| | - * | | | MIX | | MIX | | - * |a| 8-------------------------------- - * |r| | | | | | - * |r| | | | | | - * |a| |unused |unused |unused |unused | - * |y| | | | | | - * | | | | | | | - * +++ 16--|---------------|------------ - * +---V---------------V-----------+ - * | dest_mix_gain_enable array | - * +-------------------------------+ - */ - /* example : MixerMatrix of LoLa280 - * +-+ 0-------8-2 - * | | | | | - * |s| | INPUT | | INPUT - * |r|->| -> | | -> - * |c| |CAPTURE| | <- OUTPUT - * | | | MIX | | MIX - * |g| 8---------- - * |a| | | | - * |i| | PLAYBK| | PLAYBACK - * |n|->| -> | | -> - * | | |CAPTURE| | <- OUTPUT - * |a| | MIX | | MIX - * |r| 8---|----|- - * |r| +---V----V-------------------+ - * |a| | dest_mix_gain_enable array | - * |y| +----------------------------+ - */ - if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT || - chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) { - printk(KERN_ERR SFX "Invalid mixer widget size\n"); - return -EINVAL; - } - - chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) | - (((1U << chip->mixer.src_stream_outs) - 1) - << chip->mixer.src_stream_out_ofs); - chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) | - (((1U << chip->mixer.dest_phys_outs) - 1) - << chip->mixer.dest_phys_out_ofs); - - snd_printdd("Mixer src_mask=%x, dest_mask=%x\n", - chip->mixer.src_mask, chip->mixer.dest_mask); - - return 0; -} - -static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id, - unsigned short gain, bool on) -{ - unsigned int oldval, val; - - if (!(chip->mixer.src_mask & (1 << id))) - return -EINVAL; - oldval = val = readl(&chip->mixer.array->src_gain_enable); - if (on) - val |= (1 << id); - else - val &= ~(1 << id); - /* test if values unchanged */ - if ((val == oldval) && - (gain == readw(&chip->mixer.array->src_gain[id]))) - return 0; - - snd_printdd("lola_mixer_set_src_gain (id=%d, gain=%d) enable=%x\n", - id, gain, val); - writew(gain, &chip->mixer.array->src_gain[id]); - writel(val, &chip->mixer.array->src_gain_enable); - lola_codec_flush(chip); - /* inform micro-controller about the new source gain */ - return lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_SOURCE_GAIN, id, 0); -} - -#if 0 /* not used */ -static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask, - unsigned short *gains) -{ - int i; - - if ((chip->mixer.src_mask & mask) != mask) - return -EINVAL; - for (i = 0; i < LOLA_MIXER_DIM; i++) { - if (mask & (1 << i)) { - writew(*gains, &chip->mixer.array->src_gain[i]); - gains++; - } - } - writel(mask, &chip->mixer.array->src_gain_enable); - lola_codec_flush(chip); - if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) { - /* update for all srcs at once */ - return lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0); - } - /* update manually */ - for (i = 0; i < LOLA_MIXER_DIM; i++) { - if (mask & (1 << i)) { - lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_SOURCE_GAIN, i, 0); - } - } - return 0; -} -#endif /* not used */ - -static int lola_mixer_set_mapping_gain(struct lola *chip, - unsigned int src, unsigned int dest, - unsigned short gain, bool on) -{ - unsigned int val; - - if (!(chip->mixer.src_mask & (1 << src)) || - !(chip->mixer.dest_mask & (1 << dest))) - return -EINVAL; - if (on) - writew(gain, &chip->mixer.array->dest_mix_gain[dest][src]); - val = readl(&chip->mixer.array->dest_mix_gain_enable[dest]); - if (on) - val |= (1 << src); - else - val &= ~(1 << src); - writel(val, &chip->mixer.array->dest_mix_gain_enable[dest]); - lola_codec_flush(chip); - return lola_codec_write(chip, chip->mixer.nid, LOLA_VERB_SET_MIX_GAIN, - src, dest); -} - -#if 0 /* not used */ -static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id, - unsigned int mask, unsigned short *gains) -{ - int i; - - if (!(chip->mixer.dest_mask & (1 << id)) || - (chip->mixer.src_mask & mask) != mask) - return -EINVAL; - for (i = 0; i < LOLA_MIXER_DIM; i++) { - if (mask & (1 << i)) { - writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]); - gains++; - } - } - writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]); - lola_codec_flush(chip); - /* update for all dests at once */ - return lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_DESTINATION_GAIN, id, 0); -} -#endif /* not used */ - -/* - */ - -static int set_analog_volume(struct lola *chip, int dir, - unsigned int idx, unsigned int val, - bool external_call); - -int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute) -{ - struct lola_pin *pin; - int idx, max_idx; - - pin = chip->pin[dir].pins; - max_idx = chip->pin[dir].num_pins; - for (idx = 0; idx < max_idx; idx++) { - if (pin[idx].is_analog) { - unsigned int val = mute ? 0 : pin[idx].cur_gain_step; - /* set volume and do not save the value */ - set_analog_volume(chip, dir, idx, val, false); - } - } - return lola_codec_flush(chip); -} - -void lola_save_mixer(struct lola *chip) -{ - /* mute analog output */ - if (chip->mixer.array_saved) { - /* store contents of mixer array */ - memcpy_fromio(chip->mixer.array_saved, chip->mixer.array, - sizeof(*chip->mixer.array)); - } - lola_setup_all_analog_gains(chip, PLAY, true); /* output mute */ -} - -void lola_restore_mixer(struct lola *chip) -{ - int i; - - /*lola_reset_setups(chip);*/ - if (chip->mixer.array_saved) { - /* restore contents of mixer array */ - memcpy_toio(chip->mixer.array, chip->mixer.array_saved, - sizeof(*chip->mixer.array)); - /* inform micro-controller about all restored values - * and ignore return values - */ - for (i = 0; i < chip->mixer.src_phys_ins; i++) - lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_SOURCE_GAIN, - i, 0); - for (i = 0; i < chip->mixer.src_stream_outs; i++) - lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_SOURCE_GAIN, - chip->mixer.src_stream_out_ofs + i, 0); - for (i = 0; i < chip->mixer.dest_stream_ins; i++) - lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_DESTINATION_GAIN, - i, 0); - for (i = 0; i < chip->mixer.dest_phys_outs; i++) - lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_DESTINATION_GAIN, - chip->mixer.dest_phys_out_ofs + i, 0); - lola_codec_flush(chip); - } -} - -/* - */ - -static int set_analog_volume(struct lola *chip, int dir, - unsigned int idx, unsigned int val, - bool external_call) -{ - struct lola_pin *pin; - int err; - - if (idx >= chip->pin[dir].num_pins) - return -EINVAL; - pin = &chip->pin[dir].pins[idx]; - if (!pin->is_analog || pin->amp_num_steps <= val) - return -EINVAL; - if (external_call && pin->cur_gain_step == val) - return 0; - if (external_call) - lola_codec_flush(chip); - snd_printdd("set_analog_volume (dir=%d idx=%d, volume=%d)\n", - dir, idx, val); - err = lola_codec_write(chip, pin->nid, - LOLA_VERB_SET_AMP_GAIN_MUTE, val, 0); - if (err < 0) - return err; - if (external_call) - pin->cur_gain_step = val; - return 0; -} - -int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update) -{ - int ret = 0; - int success = 0; - int n, err; - - /* SRC can be activated and the dwInputSRCMask is valid? */ - if ((chip->input_src_caps_mask & src_mask) != src_mask) - return -EINVAL; - /* handle all even Inputs - SRC is a stereo setting !!! */ - for (n = 0; n < chip->pin[CAPT].num_pins; n += 2) { - unsigned int mask = 3U << n; /* handle the stereo case */ - unsigned int new_src, src_state; - if (!(chip->input_src_caps_mask & mask)) - continue; - /* if one IO needs SRC, both stereo IO will get SRC */ - new_src = (src_mask & mask) != 0; - if (update) { - src_state = (chip->input_src_mask & mask) != 0; - if (src_state == new_src) - continue; /* nothing to change for this IO */ - } - err = lola_codec_write(chip, chip->pcm[CAPT].streams[n].nid, - LOLA_VERB_SET_SRC, new_src, 0); - if (!err) - success++; - else - ret = err; - } - if (success) - ret = lola_codec_flush(chip); - if (!ret) - chip->input_src_mask = src_mask; - return ret; -} - -/* - */ -static int init_mixer_values(struct lola *chip) -{ - int i; - - /* all sample rate converters on */ - lola_set_src_config(chip, (1 << chip->pin[CAPT].num_pins) - 1, false); - - /* clear all mixer matrix settings */ - memset_io(chip->mixer.array, 0, sizeof(*chip->mixer.array)); - /* inform firmware about all updated matrix columns - capture part */ - for (i = 0; i < chip->mixer.dest_stream_ins; i++) - lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_DESTINATION_GAIN, - i, 0); - /* inform firmware about all updated matrix columns - output part */ - for (i = 0; i < chip->mixer.dest_phys_outs; i++) - lola_codec_write(chip, chip->mixer.nid, - LOLA_VERB_SET_DESTINATION_GAIN, - chip->mixer.dest_phys_out_ofs + i, 0); - - /* set all digital input source (master) gains to 0dB */ - for (i = 0; i < chip->mixer.src_phys_ins; i++) - lola_mixer_set_src_gain(chip, i, 336, true); /* 0dB */ - - /* set all digital playback source (master) gains to 0dB */ - for (i = 0; i < chip->mixer.src_stream_outs; i++) - lola_mixer_set_src_gain(chip, - i + chip->mixer.src_stream_out_ofs, - 336, true); /* 0dB */ - /* set gain value 0dB diagonally in matrix - part INPUT -> CAPTURE */ - for (i = 0; i < chip->mixer.dest_stream_ins; i++) { - int src = i % chip->mixer.src_phys_ins; - lola_mixer_set_mapping_gain(chip, src, i, 336, true); - } - /* set gain value 0dB diagonally in matrix , part PLAYBACK -> OUTPUT - * (LoLa280 : playback channel 0,2,4,6 linked to output channel 0) - * (LoLa280 : playback channel 1,3,5,7 linked to output channel 1) - */ - for (i = 0; i < chip->mixer.src_stream_outs; i++) { - int src = chip->mixer.src_stream_out_ofs + i; - int dst = chip->mixer.dest_phys_out_ofs + - i % chip->mixer.dest_phys_outs; - lola_mixer_set_mapping_gain(chip, src, dst, 336, true); - } - return 0; -} - -/* - * analog mixer control element - */ -static int lola_analog_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - int dir = kcontrol->private_value; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = chip->pin[dir].num_pins; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = chip->pin[dir].pins[0].amp_num_steps; - return 0; -} - -static int lola_analog_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - int dir = kcontrol->private_value; - int i; - - for (i = 0; i < chip->pin[dir].num_pins; i++) - ucontrol->value.integer.value[i] = - chip->pin[dir].pins[i].cur_gain_step; - return 0; -} - -static int lola_analog_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - int dir = kcontrol->private_value; - int i, err; - - for (i = 0; i < chip->pin[dir].num_pins; i++) { - err = set_analog_volume(chip, dir, i, - ucontrol->value.integer.value[i], - true); - if (err < 0) - return err; - } - return 0; -} - -static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - int dir = kcontrol->private_value; - unsigned int val1, val2; - struct lola_pin *pin; - - if (size < 4 * sizeof(unsigned int)) - return -ENOMEM; - pin = &chip->pin[dir].pins[0]; - - val2 = pin->amp_step_size * 25; - val1 = -1 * (int)pin->amp_offset * (int)val2; -#ifdef TLV_DB_SCALE_MUTE - val2 |= TLV_DB_SCALE_MUTE; -#endif - if (put_user(SNDRV_CTL_TLVT_DB_SCALE, tlv)) - return -EFAULT; - if (put_user(2 * sizeof(unsigned int), tlv + 1)) - return -EFAULT; - if (put_user(val1, tlv + 2)) - return -EFAULT; - if (put_user(val2, tlv + 3)) - return -EFAULT; - return 0; -} - -static struct snd_kcontrol_new lola_analog_mixer __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), - .info = lola_analog_vol_info, - .get = lola_analog_vol_get, - .put = lola_analog_vol_put, - .tlv.c = lola_analog_vol_tlv, -}; - -static int __devinit create_analog_mixer(struct lola *chip, int dir, char *name) -{ - if (!chip->pin[dir].num_pins) - return 0; - /* no analog volumes on digital only adapters */ - if (chip->pin[dir].num_pins != chip->pin[dir].num_analog_pins) - return 0; - lola_analog_mixer.name = name; - lola_analog_mixer.private_value = dir; - return snd_ctl_add(chip->card, - snd_ctl_new1(&lola_analog_mixer, chip)); -} - -/* - * Hardware sample rate converter on digital input - */ -static int lola_input_src_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = chip->pin[CAPT].num_pins; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int lola_input_src_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - int i; - - for (i = 0; i < chip->pin[CAPT].num_pins; i++) - ucontrol->value.integer.value[i] = - !!(chip->input_src_mask & (1 << i)); - return 0; -} - -static int lola_input_src_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - int i; - unsigned int mask; - - mask = 0; - for (i = 0; i < chip->pin[CAPT].num_pins; i++) - if (ucontrol->value.integer.value[i]) - mask |= 1 << i; - return lola_set_src_config(chip, mask, true); -} - -static struct snd_kcontrol_new lola_input_src_mixer __devinitdata = { - .name = "Digital SRC Capture Switch", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = lola_input_src_info, - .get = lola_input_src_get, - .put = lola_input_src_put, -}; - -/* - * Lola16161 or Lola881 can have Hardware sample rate converters - * on its digital input pins - */ -static int __devinit create_input_src_mixer(struct lola *chip) -{ - if (!chip->input_src_caps_mask) - return 0; - - return snd_ctl_add(chip->card, - snd_ctl_new1(&lola_input_src_mixer, chip)); -} - -/* - * src gain mixer - */ -static int lola_src_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - unsigned int count = (kcontrol->private_value >> 8) & 0xff; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = count; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 409; - return 0; -} - -static int lola_src_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - unsigned int ofs = kcontrol->private_value & 0xff; - unsigned int count = (kcontrol->private_value >> 8) & 0xff; - unsigned int mask, i; - - mask = readl(&chip->mixer.array->src_gain_enable); - for (i = 0; i < count; i++) { - unsigned int idx = ofs + i; - unsigned short val; - if (!(chip->mixer.src_mask & (1 << idx))) - return -EINVAL; - if (mask & (1 << idx)) - val = readw(&chip->mixer.array->src_gain[idx]) + 1; - else - val = 0; - ucontrol->value.integer.value[i] = val; - } - return 0; -} - -static int lola_src_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - unsigned int ofs = kcontrol->private_value & 0xff; - unsigned int count = (kcontrol->private_value >> 8) & 0xff; - int i, err; - - for (i = 0; i < count; i++) { - unsigned int idx = ofs + i; - unsigned short val = ucontrol->value.integer.value[i]; - if (val) - val--; - err = lola_mixer_set_src_gain(chip, idx, val, !!val); - if (err < 0) - return err; - } - return 0; -} - -/* raw value: 0 = -84dB, 336 = 0dB, 408=18dB, incremented 1 for mute */ -static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1); - -static struct snd_kcontrol_new lola_src_gain_mixer __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .info = lola_src_gain_info, - .get = lola_src_gain_get, - .put = lola_src_gain_put, - .tlv.p = lola_src_gain_tlv, -}; - -static int __devinit create_src_gain_mixer(struct lola *chip, - int num, int ofs, char *name) -{ - lola_src_gain_mixer.name = name; - lola_src_gain_mixer.private_value = ofs + (num << 8); - return snd_ctl_add(chip->card, - snd_ctl_new1(&lola_src_gain_mixer, chip)); -} - -#if 0 /* not used */ -/* - * destination gain (matrix-like) mixer - */ -static int lola_dest_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = src_num; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 433; - return 0; -} - -static int lola_dest_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - unsigned int src_ofs = kcontrol->private_value & 0xff; - unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; - unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff; - unsigned int dst, mask, i; - - dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs; - mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]); - for (i = 0; i < src_num; i++) { - unsigned int src = src_ofs + i; - unsigned short val; - if (!(chip->mixer.src_mask & (1 << src))) - return -EINVAL; - if (mask & (1 << dst)) - val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1; - else - val = 0; - ucontrol->value.integer.value[i] = val; - } - return 0; -} - -static int lola_dest_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lola *chip = snd_kcontrol_chip(kcontrol); - unsigned int src_ofs = kcontrol->private_value & 0xff; - unsigned int src_num = (kcontrol->private_value >> 8) & 0xff; - unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff; - unsigned int dst, mask; - unsigned short gains[MAX_STREAM_COUNT]; - int i, num; - - mask = 0; - num = 0; - for (i = 0; i < src_num; i++) { - unsigned short val = ucontrol->value.integer.value[i]; - if (val) { - gains[num++] = val - 1; - mask |= 1 << i; - } - } - mask <<= src_ofs; - dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs; - return lola_mixer_set_dest_gains(chip, dst, mask, gains); -} - -static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1); - -static struct snd_kcontrol_new lola_dest_gain_mixer __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .info = lola_dest_gain_info, - .get = lola_dest_gain_get, - .put = lola_dest_gain_put, - .tlv.p = lola_dest_gain_tlv, -}; - -static int __devinit create_dest_gain_mixer(struct lola *chip, - int src_num, int src_ofs, - int num, int ofs, char *name) -{ - lola_dest_gain_mixer.count = num; - lola_dest_gain_mixer.name = name; - lola_dest_gain_mixer.private_value = - src_ofs + (src_num << 8) + (ofs << 16) + (num << 24); - return snd_ctl_add(chip->card, - snd_ctl_new1(&lola_dest_gain_mixer, chip)); -} -#endif /* not used */ - -/* - */ -int __devinit lola_create_mixer(struct lola *chip) -{ - int err; - - err = create_analog_mixer(chip, PLAY, "Analog Playback Volume"); - if (err < 0) - return err; - err = create_analog_mixer(chip, CAPT, "Analog Capture Volume"); - if (err < 0) - return err; - err = create_input_src_mixer(chip); - if (err < 0) - return err; - err = create_src_gain_mixer(chip, chip->mixer.src_phys_ins, 0, - "Digital Capture Volume"); - if (err < 0) - return err; - err = create_src_gain_mixer(chip, chip->mixer.src_stream_outs, - chip->mixer.src_stream_out_ofs, - "Digital Playback Volume"); - if (err < 0) - return err; -#if 0 -/* FIXME: buggy mixer matrix handling */ - err = create_dest_gain_mixer(chip, - chip->mixer.src_phys_ins, 0, - chip->mixer.dest_stream_ins, 0, - "Line Capture Volume"); - if (err < 0) - return err; - err = create_dest_gain_mixer(chip, - chip->mixer.src_stream_outs, - chip->mixer.src_stream_out_ofs, - chip->mixer.dest_stream_ins, 0, - "Stream-Loopback Capture Volume"); - if (err < 0) - return err; - err = create_dest_gain_mixer(chip, - chip->mixer.src_phys_ins, 0, - chip->mixer.dest_phys_outs, - chip->mixer.dest_phys_out_ofs, - "Line-Loopback Playback Volume"); - if (err < 0) - return err; - err = create_dest_gain_mixer(chip, - chip->mixer.src_stream_outs, - chip->mixer.src_stream_out_ofs, - chip->mixer.dest_phys_outs, - chip->mixer.dest_phys_out_ofs, - "Stream Playback Volume"); - if (err < 0) - return err; -#endif /* FIXME */ - return init_mixer_values(chip); -} diff --git a/ANDROID_3.4.5/sound/pci/lola/lola_pcm.c b/ANDROID_3.4.5/sound/pci/lola/lola_pcm.c deleted file mode 100644 index c44db68e..00000000 --- a/ANDROID_3.4.5/sound/pci/lola/lola_pcm.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Support for Digigram Lola PCI-e boards - * - * Copyright (c) 2011 Takashi Iwai - * - * 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 "lola.h" - -#define LOLA_MAX_BDL_ENTRIES 8 -#define LOLA_MAX_BUF_SIZE (1024*1024*1024) -#define LOLA_BDL_ENTRY_SIZE (16 * 16) - -static struct lola_pcm *lola_get_pcm(struct snd_pcm_substream *substream) -{ - struct lola *chip = snd_pcm_substream_chip(substream); - return &chip->pcm[substream->stream]; -} - -static struct lola_stream *lola_get_stream(struct snd_pcm_substream *substream) -{ - struct lola_pcm *pcm = lola_get_pcm(substream); - unsigned int idx = substream->number; - return &pcm->streams[idx]; -} - -static unsigned int lola_get_lrc(struct lola *chip) -{ - return lola_readl(chip, BAR1, LRC); -} - -static unsigned int lola_get_tstamp(struct lola *chip, bool quick_no_sync) -{ - unsigned int tstamp = lola_get_lrc(chip) >> 8; - if (chip->granularity) { - unsigned int wait_banks = quick_no_sync ? 0 : 8; - tstamp += (wait_banks + 1) * chip->granularity - 1; - tstamp -= tstamp % chip->granularity; - } - return tstamp << 8; -} - -/* clear any pending interrupt status */ -static void lola_stream_clear_pending_irq(struct lola *chip, - struct lola_stream *str) -{ - unsigned int val = lola_dsd_read(chip, str->dsd, STS); - val &= LOLA_DSD_STS_DESE | LOLA_DSD_STS_BCIS; - if (val) - lola_dsd_write(chip, str->dsd, STS, val); -} - -static void lola_stream_start(struct lola *chip, struct lola_stream *str, - unsigned int tstamp) -{ - lola_stream_clear_pending_irq(chip, str); - lola_dsd_write(chip, str->dsd, CTL, - LOLA_DSD_CTL_SRUN | - LOLA_DSD_CTL_IOCE | - LOLA_DSD_CTL_DEIE | - LOLA_DSD_CTL_VLRCV | - tstamp); -} - -static void lola_stream_stop(struct lola *chip, struct lola_stream *str, - unsigned int tstamp) -{ - lola_dsd_write(chip, str->dsd, CTL, - LOLA_DSD_CTL_IOCE | - LOLA_DSD_CTL_DEIE | - LOLA_DSD_CTL_VLRCV | - tstamp); - lola_stream_clear_pending_irq(chip, str); -} - -static void wait_for_srst_clear(struct lola *chip, struct lola_stream *str) -{ - unsigned long end_time = jiffies + msecs_to_jiffies(200); - while (time_before(jiffies, end_time)) { - unsigned int val; - val = lola_dsd_read(chip, str->dsd, CTL); - if (!(val & LOLA_DSD_CTL_SRST)) - return; - msleep(1); - } - printk(KERN_WARNING SFX "SRST not clear (stream %d)\n", str->dsd); -} - -static int lola_stream_wait_for_fifo(struct lola *chip, - struct lola_stream *str, - bool ready) -{ - unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0; - unsigned long end_time = jiffies + msecs_to_jiffies(200); - while (time_before(jiffies, end_time)) { - unsigned int reg = lola_dsd_read(chip, str->dsd, STS); - if ((reg & LOLA_DSD_STS_FIFORDY) == val) - return 0; - msleep(1); - } - printk(KERN_WARNING SFX "FIFO not ready (stream %d)\n", str->dsd); - return -EIO; -} - -/* sync for FIFO ready/empty for all linked streams; - * clear paused flag when FIFO gets ready again - */ -static int lola_sync_wait_for_fifo(struct lola *chip, - struct snd_pcm_substream *substream, - bool ready) -{ - unsigned int val = ready ? LOLA_DSD_STS_FIFORDY : 0; - unsigned long end_time = jiffies + msecs_to_jiffies(200); - struct snd_pcm_substream *s; - int pending = 0; - - while (time_before(jiffies, end_time)) { - pending = 0; - snd_pcm_group_for_each_entry(s, substream) { - struct lola_stream *str; - if (s->pcm->card != substream->pcm->card) - continue; - str = lola_get_stream(s); - if (str->prepared && str->paused) { - unsigned int reg; - reg = lola_dsd_read(chip, str->dsd, STS); - if ((reg & LOLA_DSD_STS_FIFORDY) != val) { - pending = str->dsd + 1; - break; - } - if (ready) - str->paused = 0; - } - } - if (!pending) - return 0; - msleep(1); - } - printk(KERN_WARNING SFX "FIFO not ready (pending %d)\n", pending - 1); - return -EIO; -} - -/* finish pause - prepare for a new resume */ -static void lola_sync_pause(struct lola *chip, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_substream *s; - - lola_sync_wait_for_fifo(chip, substream, false); - snd_pcm_group_for_each_entry(s, substream) { - struct lola_stream *str; - if (s->pcm->card != substream->pcm->card) - continue; - str = lola_get_stream(s); - if (str->paused && str->prepared) - lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRUN | - LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); - } - lola_sync_wait_for_fifo(chip, substream, true); -} - -static void lola_stream_reset(struct lola *chip, struct lola_stream *str) -{ - if (str->prepared) { - if (str->paused) - lola_sync_pause(chip, str->substream); - str->prepared = 0; - lola_dsd_write(chip, str->dsd, CTL, - LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE); - lola_stream_wait_for_fifo(chip, str, false); - lola_stream_clear_pending_irq(chip, str); - lola_dsd_write(chip, str->dsd, CTL, LOLA_DSD_CTL_SRST); - lola_dsd_write(chip, str->dsd, LVI, 0); - lola_dsd_write(chip, str->dsd, BDPU, 0); - lola_dsd_write(chip, str->dsd, BDPL, 0); - wait_for_srst_clear(chip, str); - } -} - -static struct snd_pcm_hardware lola_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_FLOAT_LE), - .rates = SNDRV_PCM_RATE_8000_192000, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = LOLA_MAX_BUF_SIZE, - .period_bytes_min = 128, - .period_bytes_max = LOLA_MAX_BUF_SIZE / 2, - .periods_min = 2, - .periods_max = LOLA_MAX_BDL_ENTRIES, - .fifo_size = 0, -}; - -static int lola_pcm_open(struct snd_pcm_substream *substream) -{ - struct lola *chip = snd_pcm_substream_chip(substream); - struct lola_pcm *pcm = lola_get_pcm(substream); - struct lola_stream *str = lola_get_stream(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - mutex_lock(&chip->open_mutex); - if (str->opened) { - mutex_unlock(&chip->open_mutex); - return -EBUSY; - } - str->substream = substream; - str->master = NULL; - str->opened = 1; - runtime->hw = lola_pcm_hw; - runtime->hw.channels_max = pcm->num_streams - str->index; - if (chip->sample_rate) { - /* sample rate is locked */ - runtime->hw.rate_min = chip->sample_rate; - runtime->hw.rate_max = chip->sample_rate; - } else { - runtime->hw.rate_min = chip->sample_rate_min; - runtime->hw.rate_max = chip->sample_rate_max; - } - chip->ref_count_rate++; - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - /* period size = multiple of chip->granularity (8, 16 or 32 frames)*/ - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - chip->granularity); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - chip->granularity); - mutex_unlock(&chip->open_mutex); - return 0; -} - -static void lola_cleanup_slave_streams(struct lola_pcm *pcm, - struct lola_stream *str) -{ - int i; - for (i = str->index + 1; i < pcm->num_streams; i++) { - struct lola_stream *s = &pcm->streams[i]; - if (s->master != str) - break; - s->master = NULL; - s->opened = 0; - } -} - -static int lola_pcm_close(struct snd_pcm_substream *substream) -{ - struct lola *chip = snd_pcm_substream_chip(substream); - struct lola_stream *str = lola_get_stream(substream); - - mutex_lock(&chip->open_mutex); - if (str->substream == substream) { - str->substream = NULL; - str->opened = 0; - } - if (--chip->ref_count_rate == 0) { - /* release sample rate */ - chip->sample_rate = 0; - } - mutex_unlock(&chip->open_mutex); - return 0; -} - -static int lola_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct lola_stream *str = lola_get_stream(substream); - - str->bufsize = 0; - str->period_bytes = 0; - str->format_verb = 0; - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int lola_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct lola *chip = snd_pcm_substream_chip(substream); - struct lola_pcm *pcm = lola_get_pcm(substream); - struct lola_stream *str = lola_get_stream(substream); - - mutex_lock(&chip->open_mutex); - lola_stream_reset(chip, str); - lola_cleanup_slave_streams(pcm, str); - mutex_unlock(&chip->open_mutex); - return snd_pcm_lib_free_pages(substream); -} - -/* - * set up a BDL entry - */ -static int setup_bdle(struct snd_pcm_substream *substream, - struct lola_stream *str, u32 **bdlp, - int ofs, int size) -{ - u32 *bdl = *bdlp; - - while (size > 0) { - dma_addr_t addr; - int chunk; - - if (str->frags >= LOLA_MAX_BDL_ENTRIES) - return -EINVAL; - - addr = snd_pcm_sgbuf_get_addr(substream, ofs); - /* program the address field of the BDL entry */ - bdl[0] = cpu_to_le32((u32)addr); - bdl[1] = cpu_to_le32(upper_32_bits(addr)); - /* program the size field of the BDL entry */ - chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size); - bdl[2] = cpu_to_le32(chunk); - /* program the IOC to enable interrupt - * only when the whole fragment is processed - */ - size -= chunk; - bdl[3] = size ? 0 : cpu_to_le32(0x01); - bdl += 4; - str->frags++; - ofs += chunk; - } - *bdlp = bdl; - return ofs; -} - -/* - * set up BDL entries - */ -static int lola_setup_periods(struct lola *chip, struct lola_pcm *pcm, - struct snd_pcm_substream *substream, - struct lola_stream *str) -{ - u32 *bdl; - int i, ofs, periods, period_bytes; - - period_bytes = str->period_bytes; - periods = str->bufsize / period_bytes; - - /* program the initial BDL entries */ - bdl = (u32 *)(pcm->bdl.area + LOLA_BDL_ENTRY_SIZE * str->index); - ofs = 0; - str->frags = 0; - for (i = 0; i < periods; i++) { - ofs = setup_bdle(substream, str, &bdl, ofs, period_bytes); - if (ofs < 0) - goto error; - } - return 0; - - error: - snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n", - str->bufsize, period_bytes); - return -EINVAL; -} - -static unsigned int lola_get_format_verb(struct snd_pcm_substream *substream) -{ - unsigned int verb; - - switch (substream->runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - verb = 0x00000000; - break; - case SNDRV_PCM_FORMAT_S24_LE: - verb = 0x00000200; - break; - case SNDRV_PCM_FORMAT_S32_LE: - verb = 0x00000300; - break; - case SNDRV_PCM_FORMAT_FLOAT_LE: - verb = 0x00001300; - break; - default: - return 0; - } - verb |= substream->runtime->channels; - return verb; -} - -static int lola_set_stream_config(struct lola *chip, - struct lola_stream *str, - int channels) -{ - int i, err; - unsigned int verb, val; - - /* set format info for all channels - * (with only one command for the first channel) - */ - err = lola_codec_read(chip, str->nid, LOLA_VERB_SET_STREAM_FORMAT, - str->format_verb, 0, &val, NULL); - if (err < 0) { - printk(KERN_ERR SFX "Cannot set stream format 0x%x\n", - str->format_verb); - return err; - } - - /* update stream - channel config */ - for (i = 0; i < channels; i++) { - verb = (str->index << 6) | i; - err = lola_codec_read(chip, str[i].nid, - LOLA_VERB_SET_CHANNEL_STREAMID, 0, verb, - &val, NULL); - if (err < 0) { - printk(KERN_ERR SFX "Cannot set stream channel %d\n", i); - return err; - } - } - return 0; -} - -/* - * set up the SD for streaming - */ -static int lola_setup_controller(struct lola *chip, struct lola_pcm *pcm, - struct lola_stream *str) -{ - dma_addr_t bdl; - - if (str->prepared) - return -EINVAL; - - /* set up BDL */ - bdl = pcm->bdl.addr + LOLA_BDL_ENTRY_SIZE * str->index; - lola_dsd_write(chip, str->dsd, BDPL, (u32)bdl); - lola_dsd_write(chip, str->dsd, BDPU, upper_32_bits(bdl)); - /* program the stream LVI (last valid index) of the BDL */ - lola_dsd_write(chip, str->dsd, LVI, str->frags - 1); - lola_stream_clear_pending_irq(chip, str); - - lola_dsd_write(chip, str->dsd, CTL, - LOLA_DSD_CTL_IOCE | LOLA_DSD_CTL_DEIE | LOLA_DSD_CTL_SRUN); - - str->prepared = 1; - - return lola_stream_wait_for_fifo(chip, str, true); -} - -static int lola_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct lola *chip = snd_pcm_substream_chip(substream); - struct lola_pcm *pcm = lola_get_pcm(substream); - struct lola_stream *str = lola_get_stream(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int bufsize, period_bytes, format_verb; - int i, err; - - mutex_lock(&chip->open_mutex); - lola_stream_reset(chip, str); - lola_cleanup_slave_streams(pcm, str); - if (str->index + runtime->channels > pcm->num_streams) { - mutex_unlock(&chip->open_mutex); - return -EINVAL; - } - for (i = 1; i < runtime->channels; i++) { - str[i].master = str; - str[i].opened = 1; - } - mutex_unlock(&chip->open_mutex); - - bufsize = snd_pcm_lib_buffer_bytes(substream); - period_bytes = snd_pcm_lib_period_bytes(substream); - format_verb = lola_get_format_verb(substream); - - str->bufsize = bufsize; - str->period_bytes = period_bytes; - str->format_verb = format_verb; - - err = lola_setup_periods(chip, pcm, substream, str); - if (err < 0) - return err; - - err = lola_set_sample_rate(chip, runtime->rate); - if (err < 0) - return err; - chip->sample_rate = runtime->rate; /* sample rate gets locked */ - - err = lola_set_stream_config(chip, str, runtime->channels); - if (err < 0) - return err; - - err = lola_setup_controller(chip, pcm, str); - if (err < 0) { - lola_stream_reset(chip, str); - return err; - } - - return 0; -} - -static int lola_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct lola *chip = snd_pcm_substream_chip(substream); - struct lola_stream *str; - struct snd_pcm_substream *s; - unsigned int start; - unsigned int tstamp; - bool sync_streams; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - start = 1; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - start = 0; - break; - default: - return -EINVAL; - } - - /* - * sample correct synchronization is only needed starting several - * streams. On stop or if only one stream do as quick as possible - */ - sync_streams = (start && snd_pcm_stream_linked(substream)); - tstamp = lola_get_tstamp(chip, !sync_streams); - spin_lock(&chip->reg_lock); - snd_pcm_group_for_each_entry(s, substream) { - if (s->pcm->card != substream->pcm->card) - continue; - str = lola_get_stream(s); - if (start) - lola_stream_start(chip, str, tstamp); - else - lola_stream_stop(chip, str, tstamp); - str->running = start; - str->paused = !start; - snd_pcm_trigger_done(s, substream); - } - spin_unlock(&chip->reg_lock); - return 0; -} - -static snd_pcm_uframes_t lola_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct lola *chip = snd_pcm_substream_chip(substream); - struct lola_stream *str = lola_get_stream(substream); - unsigned int pos = lola_dsd_read(chip, str->dsd, LPIB); - - if (pos >= str->bufsize) - pos = 0; - return bytes_to_frames(substream->runtime, pos); -} - -void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits) -{ - int i; - - for (i = 0; bits && i < pcm->num_streams; i++) { - if (bits & (1 << i)) { - struct lola_stream *str = &pcm->streams[i]; - if (str->substream && str->running) - snd_pcm_period_elapsed(str->substream); - bits &= ~(1 << i); - } - } -} - -static struct snd_pcm_ops lola_pcm_ops = { - .open = lola_pcm_open, - .close = lola_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = lola_pcm_hw_params, - .hw_free = lola_pcm_hw_free, - .prepare = lola_pcm_prepare, - .trigger = lola_pcm_trigger, - .pointer = lola_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -int __devinit lola_create_pcm(struct lola *chip) -{ - struct snd_pcm *pcm; - int i, err; - - for (i = 0; i < 2; i++) { - err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - PAGE_SIZE, &chip->pcm[i].bdl); - if (err < 0) - return err; - } - - err = snd_pcm_new(chip->card, "Digigram Lola", 0, - chip->pcm[SNDRV_PCM_STREAM_PLAYBACK].num_streams, - chip->pcm[SNDRV_PCM_STREAM_CAPTURE].num_streams, - &pcm); - if (err < 0) - return err; - strlcpy(pcm->name, "Digigram Lola", sizeof(pcm->name)); - pcm->private_data = chip; - for (i = 0; i < 2; i++) { - if (chip->pcm[i].num_streams) - snd_pcm_set_ops(pcm, i, &lola_pcm_ops); - } - /* buffer pre-allocation */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 1024 * 64, 32 * 1024 * 1024); - return 0; -} - -void lola_free_pcm(struct lola *chip) -{ - snd_dma_free_pages(&chip->pcm[0].bdl); - snd_dma_free_pages(&chip->pcm[1].bdl); -} - -/* - */ - -static int lola_init_stream(struct lola *chip, struct lola_stream *str, - int idx, int nid, int dir) -{ - unsigned int val; - int err; - - str->nid = nid; - str->index = idx; - str->dsd = idx; - if (dir == PLAY) - str->dsd += MAX_STREAM_IN_COUNT; - err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); - return err; - } - if (dir == PLAY) { - /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) */ - if ((val & 0x00f00dff) != 0x00000010) { - printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", - val, nid); - return -EINVAL; - } - } else { - /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) - * (bug : ignore bit8: Conn list = 0/1) - */ - if ((val & 0x00f00cff) != 0x00100010) { - printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", - val, nid); - return -EINVAL; - } - /* test bit9:DIGITAL and bit12:SRC_PRESENT*/ - if ((val & 0x00001200) == 0x00001200) - chip->input_src_caps_mask |= (1 << idx); - } - - err = lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val); - if (err < 0) { - printk(KERN_ERR SFX "Can't read FORMATS 0x%x\n", nid); - return err; - } - val &= 3; - if (val == 3) - str->can_float = true; - if (!(val & 1)) { - printk(KERN_ERR SFX "Invalid formats 0x%x for 0x%x", val, nid); - return -EINVAL; - } - return 0; -} - -int __devinit lola_init_pcm(struct lola *chip, int dir, int *nidp) -{ - struct lola_pcm *pcm = &chip->pcm[dir]; - int i, nid, err; - - nid = *nidp; - for (i = 0; i < pcm->num_streams; i++, nid++) { - err = lola_init_stream(chip, &pcm->streams[i], i, nid, dir); - if (err < 0) - return err; - } - *nidp = nid; - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/lola/lola_proc.c b/ANDROID_3.4.5/sound/pci/lola/lola_proc.c deleted file mode 100644 index 9d7daf89..00000000 --- a/ANDROID_3.4.5/sound/pci/lola/lola_proc.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Support for Digigram Lola PCI-e boards - * - * Copyright (c) 2011 Takashi Iwai - * - * 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 "lola.h" - -static void print_audio_widget(struct snd_info_buffer *buffer, - struct lola *chip, int nid, const char *name) -{ - unsigned int val; - - lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); - snd_iprintf(buffer, "Node 0x%02x %s wcaps 0x%x\n", nid, name, val); - lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val); - snd_iprintf(buffer, " Formats: 0x%x\n", val); -} - -static void print_pin_widget(struct snd_info_buffer *buffer, - struct lola *chip, int nid, unsigned int ampcap, - const char *name) -{ - unsigned int val; - - lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); - snd_iprintf(buffer, "Node 0x%02x %s wcaps 0x%x\n", nid, name, val); - if (val == 0x00400200) - return; - lola_read_param(chip, nid, ampcap, &val); - snd_iprintf(buffer, " Amp-Caps: 0x%x\n", val); - snd_iprintf(buffer, " mute=%d, step-size=%d, steps=%d, ofs=%d\n", - LOLA_AMP_MUTE_CAPABLE(val), - LOLA_AMP_STEP_SIZE(val), - LOLA_AMP_NUM_STEPS(val), - LOLA_AMP_OFFSET(val)); - lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val, NULL); - snd_iprintf(buffer, " Max-level: 0x%x\n", val); -} - -static void print_clock_widget(struct snd_info_buffer *buffer, - struct lola *chip, int nid) -{ - int i, j, num_clocks; - unsigned int val; - - lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); - snd_iprintf(buffer, "Node 0x%02x [Clock] wcaps 0x%x\n", nid, val); - num_clocks = val & 0xff; - for (i = 0; i < num_clocks; i += 4) { - unsigned int res_ex; - unsigned short items[4]; - const char *name; - - lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST, - i, 0, &val, &res_ex); - items[0] = val & 0xfff; - items[1] = (val >> 16) & 0xfff; - items[2] = res_ex & 0xfff; - items[3] = (res_ex >> 16) & 0xfff; - for (j = 0; j < 4; j++) { - unsigned char type = items[j] >> 8; - unsigned int freq = items[j] & 0xff; - if (i + j >= num_clocks) - break; - if (type == LOLA_CLOCK_TYPE_INTERNAL) { - name = "Internal"; - freq = lola_sample_rate_convert(freq); - } else if (type == LOLA_CLOCK_TYPE_VIDEO) { - name = "Video"; - freq = lola_sample_rate_convert(freq); - } else { - name = "Other"; - } - snd_iprintf(buffer, " Clock %d: Type %d:%s, freq=%d\n", - i + j, type, name, freq); - } - } -} - -static void print_mixer_widget(struct snd_info_buffer *buffer, - struct lola *chip, int nid) -{ - unsigned int val; - - lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); - snd_iprintf(buffer, "Node 0x%02x [Mixer] wcaps 0x%x\n", nid, val); -} - -static void lola_proc_codec_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct lola *chip = entry->private_data; - unsigned int val; - int i, nid; - - lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val); - snd_iprintf(buffer, "Vendor: 0x%08x\n", val); - lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val); - snd_iprintf(buffer, "Function Type: %d\n", val); - lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val); - snd_iprintf(buffer, "Specific-Caps: 0x%08x\n", val); - snd_iprintf(buffer, " Pins-In %d, Pins-Out %d\n", - chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins); - nid = 2; - for (i = 0; i < chip->pcm[CAPT].num_streams; i++, nid++) - print_audio_widget(buffer, chip, nid, "[Audio-In]"); - for (i = 0; i < chip->pcm[PLAY].num_streams; i++, nid++) - print_audio_widget(buffer, chip, nid, "[Audio-Out]"); - for (i = 0; i < chip->pin[CAPT].num_pins; i++, nid++) - print_pin_widget(buffer, chip, nid, LOLA_PAR_AMP_IN_CAP, - "[Pin-In]"); - for (i = 0; i < chip->pin[PLAY].num_pins; i++, nid++) - print_pin_widget(buffer, chip, nid, LOLA_PAR_AMP_OUT_CAP, - "[Pin-Out]"); - if (LOLA_AFG_CLOCK_WIDGET_PRESENT(chip->lola_caps)) { - print_clock_widget(buffer, chip, nid); - nid++; - } - if (LOLA_AFG_MIXER_WIDGET_PRESENT(chip->lola_caps)) { - print_mixer_widget(buffer, chip, nid); - nid++; - } -} - -/* direct codec access for debugging */ -static void lola_proc_codec_rw_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct lola *chip = entry->private_data; - char line[64]; - unsigned int id, verb, data, extdata; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%i %i %i %i", &id, &verb, &data, &extdata) != 4) - continue; - lola_codec_read(chip, id, verb, data, extdata, - &chip->debug_res, - &chip->debug_res_ex); - } -} - -static void lola_proc_codec_rw_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct lola *chip = entry->private_data; - snd_iprintf(buffer, "0x%x 0x%x\n", chip->debug_res, chip->debug_res_ex); -} - -/* - * dump some registers - */ -static void lola_proc_regs_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct lola *chip = entry->private_data; - int i; - - for (i = 0; i < 0x40; i += 4) { - snd_iprintf(buffer, "BAR0 %02x: %08x\n", i, - readl(chip->bar[BAR0].remap_addr + i)); - } - snd_iprintf(buffer, "\n"); - for (i = 0; i < 0x30; i += 4) { - snd_iprintf(buffer, "BAR1 %02x: %08x\n", i, - readl(chip->bar[BAR1].remap_addr + i)); - } - snd_iprintf(buffer, "\n"); - for (i = 0x80; i < 0xa0; i += 4) { - snd_iprintf(buffer, "BAR1 %02x: %08x\n", i, - readl(chip->bar[BAR1].remap_addr + i)); - } - snd_iprintf(buffer, "\n"); - for (i = 0; i < 32; i++) { - snd_iprintf(buffer, "DSD %02x STS %08x\n", i, - lola_dsd_read(chip, i, STS)); - snd_iprintf(buffer, "DSD %02x LPIB %08x\n", i, - lola_dsd_read(chip, i, LPIB)); - snd_iprintf(buffer, "DSD %02x CTL %08x\n", i, - lola_dsd_read(chip, i, CTL)); - snd_iprintf(buffer, "DSD %02x LVIL %08x\n", i, - lola_dsd_read(chip, i, LVI)); - snd_iprintf(buffer, "DSD %02x BDPL %08x\n", i, - lola_dsd_read(chip, i, BDPL)); - snd_iprintf(buffer, "DSD %02x BDPU %08x\n", i, - lola_dsd_read(chip, i, BDPU)); - } -} - -void __devinit lola_proc_debug_new(struct lola *chip) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(chip->card, "codec", &entry)) - snd_info_set_text_ops(entry, chip, lola_proc_codec_read); - if (!snd_card_proc_new(chip->card, "codec_rw", &entry)) { - snd_info_set_text_ops(entry, chip, lola_proc_codec_rw_read); - entry->mode |= S_IWUSR; - entry->c.text.write = lola_proc_codec_rw_write; - } - if (!snd_card_proc_new(chip->card, "regs", &entry)) - snd_info_set_text_ops(entry, chip, lola_proc_regs_read); -} diff --git a/ANDROID_3.4.5/sound/pci/lx6464es/Makefile b/ANDROID_3.4.5/sound/pci/lx6464es/Makefile deleted file mode 100644 index eb04a6c7..00000000 --- a/ANDROID_3.4.5/sound/pci/lx6464es/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -snd-lx6464es-objs := lx6464es.o lx_core.o -obj-$(CONFIG_SND_LX6464ES) += snd-lx6464es.o diff --git a/ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.c b/ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.c deleted file mode 100644 index d94c0c29..00000000 --- a/ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* -*- linux-c -*- * - * - * ALSA driver for the digigram lx6464es interface - * - * Copyright (c) 2008, 2009 Tim Blechmann - * - * - * 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; see the file COPYING. 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 "lx6464es.h" - -MODULE_AUTHOR("Tim Blechmann"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("digigram lx6464es"); -MODULE_SUPPORTED_DEVICE("{digigram lx6464es{}}"); - - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Digigram LX6464ES interface."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Digigram LX6464ES interface."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable/disable specific Digigram LX6464ES soundcards."); - -static const char card_name[] = "LX6464ES"; - - -#define PCI_DEVICE_ID_PLX_LX6464ES PCI_DEVICE_ID_PLX_9056 - -static DEFINE_PCI_DEVICE_TABLE(snd_lx6464es_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES), - .subvendor = PCI_VENDOR_ID_DIGIGRAM, - .subdevice = PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_SERIAL_SUBSYSTEM - }, /* LX6464ES */ - { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_LX6464ES), - .subvendor = PCI_VENDOR_ID_DIGIGRAM, - .subdevice = PCI_SUBDEVICE_ID_DIGIGRAM_LX6464ES_CAE_SERIAL_SUBSYSTEM - }, /* LX6464ES-CAE */ - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, snd_lx6464es_ids); - - - -/* PGO pour USERo dans le registre pci_0x06/loc_0xEC */ -#define CHIPSC_RESET_XILINX (1L<<16) - - -/* alsa callbacks */ -static struct snd_pcm_hardware lx_caps = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S24_3BE), - .rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_192000), - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 64, - .buffer_bytes_max = 64*2*3*MICROBLAZE_IBL_MAX*MAX_STREAM_BUFFER, - .period_bytes_min = (2*2*MICROBLAZE_IBL_MIN*2), - .period_bytes_max = (4*64*MICROBLAZE_IBL_MAX*MAX_STREAM_BUFFER), - .periods_min = 2, - .periods_max = MAX_STREAM_BUFFER, -}; - -static int lx_set_granularity(struct lx6464es *chip, u32 gran); - - -static int lx_hardware_open(struct lx6464es *chip, - struct snd_pcm_substream *substream) -{ - int err = 0; - struct snd_pcm_runtime *runtime = substream->runtime; - int channels = runtime->channels; - int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - - snd_pcm_uframes_t period_size = runtime->period_size; - - snd_printd(LXP "allocating pipe for %d channels\n", channels); - err = lx_pipe_allocate(chip, 0, is_capture, channels); - if (err < 0) { - snd_printk(KERN_ERR LXP "allocating pipe failed\n"); - return err; - } - - err = lx_set_granularity(chip, period_size); - if (err < 0) { - snd_printk(KERN_ERR LXP "setting granularity to %ld failed\n", - period_size); - return err; - } - - return 0; -} - -static int lx_hardware_start(struct lx6464es *chip, - struct snd_pcm_substream *substream) -{ - int err = 0; - struct snd_pcm_runtime *runtime = substream->runtime; - int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - - snd_printd(LXP "setting stream format\n"); - err = lx_stream_set_format(chip, runtime, 0, is_capture); - if (err < 0) { - snd_printk(KERN_ERR LXP "setting stream format failed\n"); - return err; - } - - snd_printd(LXP "starting pipe\n"); - err = lx_pipe_start(chip, 0, is_capture); - if (err < 0) { - snd_printk(KERN_ERR LXP "starting pipe failed\n"); - return err; - } - - snd_printd(LXP "waiting for pipe to start\n"); - err = lx_pipe_wait_for_start(chip, 0, is_capture); - if (err < 0) { - snd_printk(KERN_ERR LXP "waiting for pipe failed\n"); - return err; - } - - return err; -} - - -static int lx_hardware_stop(struct lx6464es *chip, - struct snd_pcm_substream *substream) -{ - int err = 0; - int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - - snd_printd(LXP "pausing pipe\n"); - err = lx_pipe_pause(chip, 0, is_capture); - if (err < 0) { - snd_printk(KERN_ERR LXP "pausing pipe failed\n"); - return err; - } - - snd_printd(LXP "waiting for pipe to become idle\n"); - err = lx_pipe_wait_for_idle(chip, 0, is_capture); - if (err < 0) { - snd_printk(KERN_ERR LXP "waiting for pipe failed\n"); - return err; - } - - snd_printd(LXP "stopping pipe\n"); - err = lx_pipe_stop(chip, 0, is_capture); - if (err < 0) { - snd_printk(LXP "stopping pipe failed\n"); - return err; - } - - return err; -} - - -static int lx_hardware_close(struct lx6464es *chip, - struct snd_pcm_substream *substream) -{ - int err = 0; - int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - - snd_printd(LXP "releasing pipe\n"); - err = lx_pipe_release(chip, 0, is_capture); - if (err < 0) { - snd_printk(LXP "releasing pipe failed\n"); - return err; - } - - return err; -} - - -static int lx_pcm_open(struct snd_pcm_substream *substream) -{ - struct lx6464es *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err = 0; - int board_rate; - - snd_printdd("->lx_pcm_open\n"); - mutex_lock(&chip->setup_mutex); - - /* copy the struct snd_pcm_hardware struct */ - runtime->hw = lx_caps; - -#if 0 - /* buffer-size should better be multiple of period-size */ - err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - snd_printk(KERN_WARNING LXP "could not constrain periods\n"); - goto exit; - } -#endif - - /* the clock rate cannot be changed */ - board_rate = chip->board_sample_rate; - err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, - board_rate, board_rate); - - if (err < 0) { - snd_printk(KERN_WARNING LXP "could not constrain periods\n"); - goto exit; - } - - /* constrain period size */ - err = snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - MICROBLAZE_IBL_MIN, - MICROBLAZE_IBL_MAX); - if (err < 0) { - snd_printk(KERN_WARNING LXP - "could not constrain period size\n"); - goto exit; - } - - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32); - - snd_pcm_set_sync(substream); - err = 0; - -exit: - runtime->private_data = chip; - - mutex_unlock(&chip->setup_mutex); - snd_printdd("<-lx_pcm_open, %d\n", err); - return err; -} - -static int lx_pcm_close(struct snd_pcm_substream *substream) -{ - int err = 0; - snd_printdd("->lx_pcm_close\n"); - return err; -} - -static snd_pcm_uframes_t lx_pcm_stream_pointer(struct snd_pcm_substream - *substream) -{ - struct lx6464es *chip = snd_pcm_substream_chip(substream); - snd_pcm_uframes_t pos; - unsigned long flags; - int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - - struct lx_stream *lx_stream = is_capture ? &chip->capture_stream : - &chip->playback_stream; - - snd_printdd("->lx_pcm_stream_pointer\n"); - - spin_lock_irqsave(&chip->lock, flags); - pos = lx_stream->frame_pos * substream->runtime->period_size; - spin_unlock_irqrestore(&chip->lock, flags); - - snd_printdd(LXP "stream_pointer at %ld\n", pos); - return pos; -} - -static int lx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct lx6464es *chip = snd_pcm_substream_chip(substream); - int err = 0; - const int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - - snd_printdd("->lx_pcm_prepare\n"); - - mutex_lock(&chip->setup_mutex); - - if (chip->hardware_running[is_capture]) { - err = lx_hardware_stop(chip, substream); - if (err < 0) { - snd_printk(KERN_ERR LXP "failed to stop hardware. " - "Error code %d\n", err); - goto exit; - } - - err = lx_hardware_close(chip, substream); - if (err < 0) { - snd_printk(KERN_ERR LXP "failed to close hardware. " - "Error code %d\n", err); - goto exit; - } - } - - snd_printd(LXP "opening hardware\n"); - err = lx_hardware_open(chip, substream); - if (err < 0) { - snd_printk(KERN_ERR LXP "failed to open hardware. " - "Error code %d\n", err); - goto exit; - } - - err = lx_hardware_start(chip, substream); - if (err < 0) { - snd_printk(KERN_ERR LXP "failed to start hardware. " - "Error code %d\n", err); - goto exit; - } - - chip->hardware_running[is_capture] = 1; - - if (chip->board_sample_rate != substream->runtime->rate) { - if (!err) - chip->board_sample_rate = substream->runtime->rate; - } - -exit: - mutex_unlock(&chip->setup_mutex); - return err; -} - -static int lx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params, int is_capture) -{ - struct lx6464es *chip = snd_pcm_substream_chip(substream); - int err = 0; - - snd_printdd("->lx_pcm_hw_params\n"); - - mutex_lock(&chip->setup_mutex); - - /* set dma buffer */ - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - - if (is_capture) - chip->capture_stream.stream = substream; - else - chip->playback_stream.stream = substream; - - mutex_unlock(&chip->setup_mutex); - return err; -} - -static int lx_pcm_hw_params_playback(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return lx_pcm_hw_params(substream, hw_params, 0); -} - -static int lx_pcm_hw_params_capture(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return lx_pcm_hw_params(substream, hw_params, 1); -} - -static int lx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct lx6464es *chip = snd_pcm_substream_chip(substream); - int err = 0; - int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - - snd_printdd("->lx_pcm_hw_free\n"); - mutex_lock(&chip->setup_mutex); - - if (chip->hardware_running[is_capture]) { - err = lx_hardware_stop(chip, substream); - if (err < 0) { - snd_printk(KERN_ERR LXP "failed to stop hardware. " - "Error code %d\n", err); - goto exit; - } - - err = lx_hardware_close(chip, substream); - if (err < 0) { - snd_printk(KERN_ERR LXP "failed to close hardware. " - "Error code %d\n", err); - goto exit; - } - - chip->hardware_running[is_capture] = 0; - } - - err = snd_pcm_lib_free_pages(substream); - - if (is_capture) - chip->capture_stream.stream = 0; - else - chip->playback_stream.stream = 0; - -exit: - mutex_unlock(&chip->setup_mutex); - return err; -} - -static void lx_trigger_start(struct lx6464es *chip, struct lx_stream *lx_stream) -{ - struct snd_pcm_substream *substream = lx_stream->stream; - const unsigned int is_capture = lx_stream->is_capture; - - int err; - - const u32 channels = substream->runtime->channels; - const u32 bytes_per_frame = channels * 3; - const u32 period_size = substream->runtime->period_size; - const u32 periods = substream->runtime->periods; - const u32 period_bytes = period_size * bytes_per_frame; - - dma_addr_t buf = substream->dma_buffer.addr; - int i; - - u32 needed, freed; - u32 size_array[5]; - - for (i = 0; i != periods; ++i) { - u32 buffer_index = 0; - - err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, - size_array); - snd_printdd(LXP "starting: needed %d, freed %d\n", - needed, freed); - - err = lx_buffer_give(chip, 0, is_capture, period_bytes, - lower_32_bits(buf), upper_32_bits(buf), - &buffer_index); - - snd_printdd(LXP "starting: buffer index %x on %p (%d bytes)\n", - buffer_index, (void *)buf, period_bytes); - buf += period_bytes; - } - - err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array); - snd_printdd(LXP "starting: needed %d, freed %d\n", needed, freed); - - snd_printd(LXP "starting: starting stream\n"); - err = lx_stream_start(chip, 0, is_capture); - if (err < 0) - snd_printk(KERN_ERR LXP "couldn't start stream\n"); - else - lx_stream->status = LX_STREAM_STATUS_RUNNING; - - lx_stream->frame_pos = 0; -} - -static void lx_trigger_stop(struct lx6464es *chip, struct lx_stream *lx_stream) -{ - const unsigned int is_capture = lx_stream->is_capture; - int err; - - snd_printd(LXP "stopping: stopping stream\n"); - err = lx_stream_stop(chip, 0, is_capture); - if (err < 0) - snd_printk(KERN_ERR LXP "couldn't stop stream\n"); - else - lx_stream->status = LX_STREAM_STATUS_FREE; - -} - -static void lx_trigger_tasklet_dispatch_stream(struct lx6464es *chip, - struct lx_stream *lx_stream) -{ - switch (lx_stream->status) { - case LX_STREAM_STATUS_SCHEDULE_RUN: - lx_trigger_start(chip, lx_stream); - break; - - case LX_STREAM_STATUS_SCHEDULE_STOP: - lx_trigger_stop(chip, lx_stream); - break; - - default: - break; - } -} - -static void lx_trigger_tasklet(unsigned long data) -{ - struct lx6464es *chip = (struct lx6464es *)data; - unsigned long flags; - - snd_printdd("->lx_trigger_tasklet\n"); - - spin_lock_irqsave(&chip->lock, flags); - lx_trigger_tasklet_dispatch_stream(chip, &chip->capture_stream); - lx_trigger_tasklet_dispatch_stream(chip, &chip->playback_stream); - spin_unlock_irqrestore(&chip->lock, flags); -} - -static int lx_pcm_trigger_dispatch(struct lx6464es *chip, - struct lx_stream *lx_stream, int cmd) -{ - int err = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - lx_stream->status = LX_STREAM_STATUS_SCHEDULE_RUN; - break; - - case SNDRV_PCM_TRIGGER_STOP: - lx_stream->status = LX_STREAM_STATUS_SCHEDULE_STOP; - break; - - default: - err = -EINVAL; - goto exit; - } - tasklet_schedule(&chip->trigger_tasklet); - -exit: - return err; -} - - -static int lx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct lx6464es *chip = snd_pcm_substream_chip(substream); - const int is_capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - struct lx_stream *stream = is_capture ? &chip->capture_stream : - &chip->playback_stream; - - snd_printdd("->lx_pcm_trigger\n"); - - return lx_pcm_trigger_dispatch(chip, stream, cmd); -} - -static int snd_lx6464es_free(struct lx6464es *chip) -{ - snd_printdd("->snd_lx6464es_free\n"); - - lx_irq_disable(chip); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - iounmap(chip->port_dsp_bar); - ioport_unmap(chip->port_plx_remapped); - - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - - kfree(chip); - - return 0; -} - -static int snd_lx6464es_dev_free(struct snd_device *device) -{ - return snd_lx6464es_free(device->device_data); -} - -/* reset the dsp during initialization */ -static int __devinit lx_init_xilinx_reset(struct lx6464es *chip) -{ - int i; - u32 plx_reg = lx_plx_reg_read(chip, ePLX_CHIPSC); - - snd_printdd("->lx_init_xilinx_reset\n"); - - /* activate reset of xilinx */ - plx_reg &= ~CHIPSC_RESET_XILINX; - - lx_plx_reg_write(chip, ePLX_CHIPSC, plx_reg); - msleep(1); - - lx_plx_reg_write(chip, ePLX_MBOX3, 0); - msleep(1); - - plx_reg |= CHIPSC_RESET_XILINX; - lx_plx_reg_write(chip, ePLX_CHIPSC, plx_reg); - - /* deactivate reset of xilinx */ - for (i = 0; i != 100; ++i) { - u32 reg_mbox3; - msleep(10); - reg_mbox3 = lx_plx_reg_read(chip, ePLX_MBOX3); - if (reg_mbox3) { - snd_printd(LXP "xilinx reset done\n"); - snd_printdd(LXP "xilinx took %d loops\n", i); - break; - } - } - - /* todo: add some error handling? */ - - /* clear mr */ - lx_dsp_reg_write(chip, eReg_CSM, 0); - - /* le xilinx ES peut ne pas etre encore pret, on attend. */ - msleep(600); - - return 0; -} - -static int __devinit lx_init_xilinx_test(struct lx6464es *chip) -{ - u32 reg; - - snd_printdd("->lx_init_xilinx_test\n"); - - /* TEST if we have access to Xilinx/MicroBlaze */ - lx_dsp_reg_write(chip, eReg_CSM, 0); - - reg = lx_dsp_reg_read(chip, eReg_CSM); - - if (reg) { - snd_printk(KERN_ERR LXP "Problem: Reg_CSM %x.\n", reg); - - /* PCI9056_SPACE0_REMAP */ - lx_plx_reg_write(chip, ePLX_PCICR, 1); - - reg = lx_dsp_reg_read(chip, eReg_CSM); - if (reg) { - snd_printk(KERN_ERR LXP "Error: Reg_CSM %x.\n", reg); - return -EAGAIN; /* seems to be appropriate */ - } - } - - snd_printd(LXP "Xilinx/MicroBlaze access test successful\n"); - - return 0; -} - -/* initialize ethersound */ -static int __devinit lx_init_ethersound_config(struct lx6464es *chip) -{ - int i; - u32 orig_conf_es = lx_dsp_reg_read(chip, eReg_CONFES); - - /* configure 64 io channels */ - u32 conf_es = (orig_conf_es & CONFES_READ_PART_MASK) | - (64 << IOCR_INPUTS_OFFSET) | - (64 << IOCR_OUTPUTS_OFFSET) | - (FREQ_RATIO_SINGLE_MODE << FREQ_RATIO_OFFSET); - - snd_printdd("->lx_init_ethersound\n"); - - chip->freq_ratio = FREQ_RATIO_SINGLE_MODE; - - /* - * write it to the card ! - * this actually kicks the ES xilinx, the first time since poweron. - * the MAC address in the Reg_ADMACESMSB Reg_ADMACESLSB registers - * is not ready before this is done, and the bit 2 in Reg_CSES is set. - * */ - lx_dsp_reg_write(chip, eReg_CONFES, conf_es); - - for (i = 0; i != 1000; ++i) { - if (lx_dsp_reg_read(chip, eReg_CSES) & 4) { - snd_printd(LXP "ethersound initialized after %dms\n", - i); - goto ethersound_initialized; - } - msleep(1); - } - snd_printk(KERN_WARNING LXP - "ethersound could not be initialized after %dms\n", i); - return -ETIMEDOUT; - - ethersound_initialized: - snd_printd(LXP "ethersound initialized\n"); - return 0; -} - -static int __devinit lx_init_get_version_features(struct lx6464es *chip) -{ - u32 dsp_version; - - int err; - - snd_printdd("->lx_init_get_version_features\n"); - - err = lx_dsp_get_version(chip, &dsp_version); - - if (err == 0) { - u32 freq; - - snd_printk(LXP "DSP version: V%02d.%02d #%d\n", - (dsp_version>>16) & 0xff, (dsp_version>>8) & 0xff, - dsp_version & 0xff); - - /* later: what firmware version do we expect? */ - - /* retrieve Play/Rec features */ - /* done here because we may have to handle alternate - * DSP files. */ - /* later */ - - /* init the EtherSound sample rate */ - err = lx_dsp_get_clock_frequency(chip, &freq); - if (err == 0) - chip->board_sample_rate = freq; - snd_printd(LXP "actual clock frequency %d\n", freq); - } else { - snd_printk(KERN_ERR LXP "DSP corrupted \n"); - err = -EAGAIN; - } - - return err; -} - -static int lx_set_granularity(struct lx6464es *chip, u32 gran) -{ - int err = 0; - u32 snapped_gran = MICROBLAZE_IBL_MIN; - - snd_printdd("->lx_set_granularity\n"); - - /* blocksize is a power of 2 */ - while ((snapped_gran < gran) && - (snapped_gran < MICROBLAZE_IBL_MAX)) { - snapped_gran *= 2; - } - - if (snapped_gran == chip->pcm_granularity) - return 0; - - err = lx_dsp_set_granularity(chip, snapped_gran); - if (err < 0) { - snd_printk(KERN_WARNING LXP "could not set granularity\n"); - err = -EAGAIN; - } - - if (snapped_gran != gran) - snd_printk(LXP "snapped blocksize to %d\n", snapped_gran); - - snd_printd(LXP "set blocksize on board %d\n", snapped_gran); - chip->pcm_granularity = snapped_gran; - - return err; -} - -/* initialize and test the xilinx dsp chip */ -static int __devinit lx_init_dsp(struct lx6464es *chip) -{ - int err; - int i; - - snd_printdd("->lx_init_dsp\n"); - - snd_printd(LXP "initialize board\n"); - err = lx_init_xilinx_reset(chip); - if (err) - return err; - - snd_printd(LXP "testing board\n"); - err = lx_init_xilinx_test(chip); - if (err) - return err; - - snd_printd(LXP "initialize ethersound configuration\n"); - err = lx_init_ethersound_config(chip); - if (err) - return err; - - lx_irq_enable(chip); - - /** \todo the mac address should be ready by not, but it isn't, - * so we wait for it */ - for (i = 0; i != 1000; ++i) { - err = lx_dsp_get_mac(chip); - if (err) - return err; - if (chip->mac_address[0] || chip->mac_address[1] || chip->mac_address[2] || - chip->mac_address[3] || chip->mac_address[4] || chip->mac_address[5]) - goto mac_ready; - msleep(1); - } - return -ETIMEDOUT; - -mac_ready: - snd_printd(LXP "mac address ready read after: %dms\n", i); - snd_printk(LXP "mac address: %02X.%02X.%02X.%02X.%02X.%02X\n", - chip->mac_address[0], chip->mac_address[1], chip->mac_address[2], - chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); - - err = lx_init_get_version_features(chip); - if (err) - return err; - - lx_set_granularity(chip, MICROBLAZE_IBL_DEFAULT); - - chip->playback_mute = 0; - - return err; -} - -static struct snd_pcm_ops lx_ops_playback = { - .open = lx_pcm_open, - .close = lx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = lx_pcm_prepare, - .hw_params = lx_pcm_hw_params_playback, - .hw_free = lx_pcm_hw_free, - .trigger = lx_pcm_trigger, - .pointer = lx_pcm_stream_pointer, -}; - -static struct snd_pcm_ops lx_ops_capture = { - .open = lx_pcm_open, - .close = lx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = lx_pcm_prepare, - .hw_params = lx_pcm_hw_params_capture, - .hw_free = lx_pcm_hw_free, - .trigger = lx_pcm_trigger, - .pointer = lx_pcm_stream_pointer, -}; - -static int __devinit lx_pcm_create(struct lx6464es *chip) -{ - int err; - struct snd_pcm *pcm; - - u32 size = 64 * /* channels */ - 3 * /* 24 bit samples */ - MAX_STREAM_BUFFER * /* periods */ - MICROBLAZE_IBL_MAX * /* frames per period */ - 2; /* duplex */ - - size = PAGE_ALIGN(size); - - /* hardcoded device name & channel count */ - err = snd_pcm_new(chip->card, (char *)card_name, 0, - 1, 1, &pcm); - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &lx_ops_playback); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &lx_ops_capture); - - pcm->info_flags = 0; - strcpy(pcm->name, card_name); - - err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - size, size); - if (err < 0) - return err; - - chip->pcm = pcm; - chip->capture_stream.is_capture = 1; - - return 0; -} - -static int lx_control_playback_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int lx_control_playback_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lx6464es *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->playback_mute; - return 0; -} - -static int lx_control_playback_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct lx6464es *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int current_value = chip->playback_mute; - - if (current_value != ucontrol->value.integer.value[0]) { - lx_level_unmute(chip, 0, !current_value); - chip->playback_mute = !current_value; - changed = 1; - } - return changed; -} - -static struct snd_kcontrol_new lx_control_playback_switch __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = lx_control_playback_info, - .get = lx_control_playback_get, - .put = lx_control_playback_put -}; - - - -static void lx_proc_levels_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - u32 levels[64]; - int err; - int i, j; - struct lx6464es *chip = entry->private_data; - - snd_iprintf(buffer, "capture levels:\n"); - err = lx_level_peaks(chip, 1, 64, levels); - if (err < 0) - return; - - for (i = 0; i != 8; ++i) { - for (j = 0; j != 8; ++j) - snd_iprintf(buffer, "%08x ", levels[i*8+j]); - snd_iprintf(buffer, "\n"); - } - - snd_iprintf(buffer, "\nplayback levels:\n"); - - err = lx_level_peaks(chip, 0, 64, levels); - if (err < 0) - return; - - for (i = 0; i != 8; ++i) { - for (j = 0; j != 8; ++j) - snd_iprintf(buffer, "%08x ", levels[i*8+j]); - snd_iprintf(buffer, "\n"); - } - - snd_iprintf(buffer, "\n"); -} - -static int __devinit lx_proc_create(struct snd_card *card, struct lx6464es *chip) -{ - struct snd_info_entry *entry; - int err = snd_card_proc_new(card, "levels", &entry); - if (err < 0) - return err; - - snd_info_set_text_ops(entry, chip, lx_proc_levels_read); - return 0; -} - - -static int __devinit snd_lx6464es_create(struct snd_card *card, - struct pci_dev *pci, - struct lx6464es **rchip) -{ - struct lx6464es *chip; - int err; - - static struct snd_device_ops ops = { - .dev_free = snd_lx6464es_dev_free, - }; - - snd_printdd("->snd_lx6464es_create\n"); - - *rchip = NULL; - - /* enable PCI device */ - err = pci_enable_device(pci); - if (err < 0) - return err; - - pci_set_master(pci); - - /* check if we can restrict PCI DMA transfers to 32 bits */ - err = pci_set_dma_mask(pci, DMA_BIT_MASK(32)); - if (err < 0) { - snd_printk(KERN_ERR "architecture does not support " - "32bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - err = -ENOMEM; - goto alloc_failed; - } - - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - /* initialize synchronization structs */ - spin_lock_init(&chip->lock); - spin_lock_init(&chip->msg_lock); - mutex_init(&chip->setup_mutex); - tasklet_init(&chip->trigger_tasklet, lx_trigger_tasklet, - (unsigned long)chip); - tasklet_init(&chip->tasklet_capture, lx_tasklet_capture, - (unsigned long)chip); - tasklet_init(&chip->tasklet_playback, lx_tasklet_playback, - (unsigned long)chip); - - /* request resources */ - err = pci_request_regions(pci, card_name); - if (err < 0) - goto request_regions_failed; - - /* plx port */ - chip->port_plx = pci_resource_start(pci, 1); - chip->port_plx_remapped = ioport_map(chip->port_plx, - pci_resource_len(pci, 1)); - - /* dsp port */ - chip->port_dsp_bar = pci_ioremap_bar(pci, 2); - - err = request_irq(pci->irq, lx_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip); - if (err) { - snd_printk(KERN_ERR LXP "unable to grab IRQ %d\n", pci->irq); - goto request_irq_failed; - } - chip->irq = pci->irq; - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) - goto device_new_failed; - - err = lx_init_dsp(chip); - if (err < 0) { - snd_printk(KERN_ERR LXP "error during DSP initialization\n"); - return err; - } - - err = lx_pcm_create(chip); - if (err < 0) - return err; - - err = lx_proc_create(card, chip); - if (err < 0) - return err; - - err = snd_ctl_add(card, snd_ctl_new1(&lx_control_playback_switch, - chip)); - if (err < 0) - return err; - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - return 0; - -device_new_failed: - free_irq(pci->irq, chip); - -request_irq_failed: - pci_release_regions(pci); - -request_regions_failed: - kfree(chip); - -alloc_failed: - pci_disable_device(pci); - - return err; -} - -static int __devinit snd_lx6464es_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct lx6464es *chip; - int err; - - snd_printdd("->snd_lx6464es_probe\n"); - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - err = snd_lx6464es_create(card, pci, &chip); - if (err < 0) { - snd_printk(KERN_ERR LXP "error during snd_lx6464es_create\n"); - goto out_free; - } - - strcpy(card->driver, "LX6464ES"); - sprintf(card->id, "LX6464ES_%02X%02X%02X", - chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); - - sprintf(card->shortname, "LX6464ES %02X.%02X.%02X.%02X.%02X.%02X", - chip->mac_address[0], chip->mac_address[1], chip->mac_address[2], - chip->mac_address[3], chip->mac_address[4], chip->mac_address[5]); - - sprintf(card->longname, "%s at 0x%lx, 0x%p, irq %i", - card->shortname, chip->port_plx, - chip->port_dsp_bar, chip->irq); - - err = snd_card_register(card); - if (err < 0) - goto out_free; - - snd_printdd(LXP "initialization successful\n"); - pci_set_drvdata(pci, card); - dev++; - return 0; - -out_free: - snd_card_free(card); - return err; - -} - -static void __devexit snd_lx6464es_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_lx6464es_ids, - .probe = snd_lx6464es_probe, - .remove = __devexit_p(snd_lx6464es_remove), -}; - - -/* module initialization */ -static int __init mod_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit mod_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(mod_init); -module_exit(mod_exit); diff --git a/ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.h b/ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.h deleted file mode 100644 index 6792eda9..00000000 --- a/ANDROID_3.4.5/sound/pci/lx6464es/lx6464es.h +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- linux-c -*- * - * - * ALSA driver for the digigram lx6464es interface - * - * Copyright (c) 2009 Tim Blechmann - * - * - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef LX6464ES_H -#define LX6464ES_H - -#include -#include - -#include -#include - -#include "lx_core.h" - -#define LXP "LX6464ES: " - -enum { - ES_cmd_free = 0, /* no command executing */ - ES_cmd_processing = 1, /* execution of a read/write command */ - ES_read_pending = 2, /* a asynchron read command is pending */ - ES_read_finishing = 3, /* a read command has finished waiting (set by - * Interrupt or CancelIrp) */ -}; - -enum lx_stream_status { - LX_STREAM_STATUS_FREE, -/* LX_STREAM_STATUS_OPEN, */ - LX_STREAM_STATUS_SCHEDULE_RUN, -/* LX_STREAM_STATUS_STARTED, */ - LX_STREAM_STATUS_RUNNING, - LX_STREAM_STATUS_SCHEDULE_STOP, -/* LX_STREAM_STATUS_STOPPED, */ -/* LX_STREAM_STATUS_PAUSED */ -}; - - -struct lx_stream { - struct snd_pcm_substream *stream; - snd_pcm_uframes_t frame_pos; - enum lx_stream_status status; /* free, open, running, draining - * pause */ - unsigned int is_capture:1; -}; - - -struct lx6464es { - struct snd_card *card; - struct pci_dev *pci; - int irq; - - u8 mac_address[6]; - - spinlock_t lock; /* interrupt spinlock */ - struct mutex setup_mutex; /* mutex used in hw_params, open - * and close */ - - struct tasklet_struct trigger_tasklet; /* trigger tasklet */ - struct tasklet_struct tasklet_capture; - struct tasklet_struct tasklet_playback; - - /* ports */ - unsigned long port_plx; /* io port (size=256) */ - void __iomem *port_plx_remapped; /* remapped plx port */ - void __iomem *port_dsp_bar; /* memory port (32-bit, - * non-prefetchable, - * size=8K) */ - - /* messaging */ - spinlock_t msg_lock; /* message spinlock */ - struct lx_rmh rmh; - - /* configuration */ - uint freq_ratio : 2; - uint playback_mute : 1; - uint hardware_running[2]; - u32 board_sample_rate; /* sample rate read from - * board */ - u16 pcm_granularity; /* board blocksize */ - - /* dma */ - struct snd_dma_buffer capture_dma_buf; - struct snd_dma_buffer playback_dma_buf; - - /* pcm */ - struct snd_pcm *pcm; - - /* streams */ - struct lx_stream capture_stream; - struct lx_stream playback_stream; -}; - - -#endif /* LX6464ES_H */ diff --git a/ANDROID_3.4.5/sound/pci/lx6464es/lx_core.c b/ANDROID_3.4.5/sound/pci/lx6464es/lx_core.c deleted file mode 100644 index 8c3e7fce..00000000 --- a/ANDROID_3.4.5/sound/pci/lx6464es/lx_core.c +++ /dev/null @@ -1,1357 +0,0 @@ -/* -*- linux-c -*- * - * - * ALSA driver for the digigram lx6464es interface - * low-level interface - * - * Copyright (c) 2009 Tim Blechmann - * - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -/* #define RMH_DEBUG 1 */ - -#include -#include -#include - -#include "lx6464es.h" -#include "lx_core.h" - -/* low-level register access */ - -static const unsigned long dsp_port_offsets[] = { - 0, - 0x400, - 0x401, - 0x402, - 0x403, - 0x404, - 0x405, - 0x406, - 0x407, - 0x408, - 0x409, - 0x40a, - 0x40b, - 0x40c, - - 0x410, - 0x411, - 0x412, - 0x413, - 0x414, - 0x415, - 0x416, - - 0x420, - 0x430, - 0x431, - 0x432, - 0x433, - 0x434, - 0x440 -}; - -static void __iomem *lx_dsp_register(struct lx6464es *chip, int port) -{ - void __iomem *base_address = chip->port_dsp_bar; - return base_address + dsp_port_offsets[port]*4; -} - -unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port) -{ - void __iomem *address = lx_dsp_register(chip, port); - return ioread32(address); -} - -static void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, - u32 len) -{ - u32 __iomem *address = lx_dsp_register(chip, port); - int i; - - /* we cannot use memcpy_fromio */ - for (i = 0; i != len; ++i) - data[i] = ioread32(address + i); -} - - -void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data) -{ - void __iomem *address = lx_dsp_register(chip, port); - iowrite32(data, address); -} - -static void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, - const u32 *data, u32 len) -{ - u32 __iomem *address = lx_dsp_register(chip, port); - int i; - - /* we cannot use memcpy_to */ - for (i = 0; i != len; ++i) - iowrite32(data[i], address + i); -} - - -static const unsigned long plx_port_offsets[] = { - 0x04, - 0x40, - 0x44, - 0x48, - 0x4c, - 0x50, - 0x54, - 0x58, - 0x5c, - 0x64, - 0x68, - 0x6C -}; - -static void __iomem *lx_plx_register(struct lx6464es *chip, int port) -{ - void __iomem *base_address = chip->port_plx_remapped; - return base_address + plx_port_offsets[port]; -} - -unsigned long lx_plx_reg_read(struct lx6464es *chip, int port) -{ - void __iomem *address = lx_plx_register(chip, port); - return ioread32(address); -} - -void lx_plx_reg_write(struct lx6464es *chip, int port, u32 data) -{ - void __iomem *address = lx_plx_register(chip, port); - iowrite32(data, address); -} - -u32 lx_plx_mbox_read(struct lx6464es *chip, int mbox_nr) -{ - int index; - - switch (mbox_nr) { - case 1: - index = ePLX_MBOX1; break; - case 2: - index = ePLX_MBOX2; break; - case 3: - index = ePLX_MBOX3; break; - case 4: - index = ePLX_MBOX4; break; - case 5: - index = ePLX_MBOX5; break; - case 6: - index = ePLX_MBOX6; break; - case 7: - index = ePLX_MBOX7; break; - case 0: /* reserved for HF flags */ - snd_BUG(); - default: - return 0xdeadbeef; - } - - return lx_plx_reg_read(chip, index); -} - -int lx_plx_mbox_write(struct lx6464es *chip, int mbox_nr, u32 value) -{ - int index = -1; - - switch (mbox_nr) { - case 1: - index = ePLX_MBOX1; break; - case 3: - index = ePLX_MBOX3; break; - case 4: - index = ePLX_MBOX4; break; - case 5: - index = ePLX_MBOX5; break; - case 6: - index = ePLX_MBOX6; break; - case 7: - index = ePLX_MBOX7; break; - case 0: /* reserved for HF flags */ - case 2: /* reserved for Pipe States - * the DSP keeps an image of it */ - snd_BUG(); - return -EBADRQC; - } - - lx_plx_reg_write(chip, index, value); - return 0; -} - - -/* rmh */ - -#ifdef CONFIG_SND_DEBUG -#define CMD_NAME(a) a -#else -#define CMD_NAME(a) NULL -#endif - -#define Reg_CSM_MR 0x00000002 -#define Reg_CSM_MC 0x00000001 - -struct dsp_cmd_info { - u32 dcCodeOp; /* Op Code of the command (usually 1st 24-bits - * word).*/ - u16 dcCmdLength; /* Command length in words of 24 bits.*/ - u16 dcStatusType; /* Status type: 0 for fixed length, 1 for - * random. */ - u16 dcStatusLength; /* Status length (if fixed).*/ - char *dcOpName; -}; - -/* - Initialization and control data for the Microblaze interface - - OpCode: - the opcode field of the command set at the proper offset - - CmdLength - the number of command words - - StatusType - offset in the status registers: 0 means that the return value may be - different from 0, and must be read - - StatusLength - the number of status words (in addition to the return value) -*/ - -static struct dsp_cmd_info dsp_commands[] = -{ - { (CMD_00_INFO_DEBUG << OPCODE_OFFSET) , 1 /*custom*/ - , 1 , 0 /**/ , CMD_NAME("INFO_DEBUG") }, - { (CMD_01_GET_SYS_CFG << OPCODE_OFFSET) , 1 /**/ - , 1 , 2 /**/ , CMD_NAME("GET_SYS_CFG") }, - { (CMD_02_SET_GRANULARITY << OPCODE_OFFSET) , 1 /**/ - , 1 , 0 /**/ , CMD_NAME("SET_GRANULARITY") }, - { (CMD_03_SET_TIMER_IRQ << OPCODE_OFFSET) , 1 /**/ - , 1 , 0 /**/ , CMD_NAME("SET_TIMER_IRQ") }, - { (CMD_04_GET_EVENT << OPCODE_OFFSET) , 1 /**/ - , 1 , 0 /*up to 10*/ , CMD_NAME("GET_EVENT") }, - { (CMD_05_GET_PIPES << OPCODE_OFFSET) , 1 /**/ - , 1 , 2 /*up to 4*/ , CMD_NAME("GET_PIPES") }, - { (CMD_06_ALLOCATE_PIPE << OPCODE_OFFSET) , 1 /**/ - , 0 , 0 /**/ , CMD_NAME("ALLOCATE_PIPE") }, - { (CMD_07_RELEASE_PIPE << OPCODE_OFFSET) , 1 /**/ - , 0 , 0 /**/ , CMD_NAME("RELEASE_PIPE") }, - { (CMD_08_ASK_BUFFERS << OPCODE_OFFSET) , 1 /**/ - , 1 , MAX_STREAM_BUFFER , CMD_NAME("ASK_BUFFERS") }, - { (CMD_09_STOP_PIPE << OPCODE_OFFSET) , 1 /**/ - , 0 , 0 /*up to 2*/ , CMD_NAME("STOP_PIPE") }, - { (CMD_0A_GET_PIPE_SPL_COUNT << OPCODE_OFFSET) , 1 /**/ - , 1 , 1 /*up to 2*/ , CMD_NAME("GET_PIPE_SPL_COUNT") }, - { (CMD_0B_TOGGLE_PIPE_STATE << OPCODE_OFFSET) , 1 /*up to 5*/ - , 1 , 0 /**/ , CMD_NAME("TOGGLE_PIPE_STATE") }, - { (CMD_0C_DEF_STREAM << OPCODE_OFFSET) , 1 /*up to 4*/ - , 1 , 0 /**/ , CMD_NAME("DEF_STREAM") }, - { (CMD_0D_SET_MUTE << OPCODE_OFFSET) , 3 /**/ - , 1 , 0 /**/ , CMD_NAME("SET_MUTE") }, - { (CMD_0E_GET_STREAM_SPL_COUNT << OPCODE_OFFSET) , 1/**/ - , 1 , 2 /**/ , CMD_NAME("GET_STREAM_SPL_COUNT") }, - { (CMD_0F_UPDATE_BUFFER << OPCODE_OFFSET) , 3 /*up to 4*/ - , 0 , 1 /**/ , CMD_NAME("UPDATE_BUFFER") }, - { (CMD_10_GET_BUFFER << OPCODE_OFFSET) , 1 /**/ - , 1 , 4 /**/ , CMD_NAME("GET_BUFFER") }, - { (CMD_11_CANCEL_BUFFER << OPCODE_OFFSET) , 1 /**/ - , 1 , 1 /*up to 4*/ , CMD_NAME("CANCEL_BUFFER") }, - { (CMD_12_GET_PEAK << OPCODE_OFFSET) , 1 /**/ - , 1 , 1 /**/ , CMD_NAME("GET_PEAK") }, - { (CMD_13_SET_STREAM_STATE << OPCODE_OFFSET) , 1 /**/ - , 1 , 0 /**/ , CMD_NAME("SET_STREAM_STATE") }, -}; - -static void lx_message_init(struct lx_rmh *rmh, enum cmd_mb_opcodes cmd) -{ - snd_BUG_ON(cmd >= CMD_14_INVALID); - - rmh->cmd[0] = dsp_commands[cmd].dcCodeOp; - rmh->cmd_len = dsp_commands[cmd].dcCmdLength; - rmh->stat_len = dsp_commands[cmd].dcStatusLength; - rmh->dsp_stat = dsp_commands[cmd].dcStatusType; - rmh->cmd_idx = cmd; - memset(&rmh->cmd[1], 0, (REG_CRM_NUMBER - 1) * sizeof(u32)); - -#ifdef CONFIG_SND_DEBUG - memset(rmh->stat, 0, REG_CRM_NUMBER * sizeof(u32)); -#endif -#ifdef RMH_DEBUG - rmh->cmd_idx = cmd; -#endif -} - -#ifdef RMH_DEBUG -#define LXRMH "lx6464es rmh: " -static void lx_message_dump(struct lx_rmh *rmh) -{ - u8 idx = rmh->cmd_idx; - int i; - - snd_printk(LXRMH "command %s\n", dsp_commands[idx].dcOpName); - - for (i = 0; i != rmh->cmd_len; ++i) - snd_printk(LXRMH "\tcmd[%d] %08x\n", i, rmh->cmd[i]); - - for (i = 0; i != rmh->stat_len; ++i) - snd_printk(LXRMH "\tstat[%d]: %08x\n", i, rmh->stat[i]); - snd_printk("\n"); -} -#else -static inline void lx_message_dump(struct lx_rmh *rmh) -{} -#endif - - - -/* sleep 500 - 100 = 400 times 100us -> the timeout is >= 40 ms */ -#define XILINX_TIMEOUT_MS 40 -#define XILINX_POLL_NO_SLEEP 100 -#define XILINX_POLL_ITERATIONS 150 - - -static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh) -{ - u32 reg = ED_DSP_TIMED_OUT; - int dwloop; - - if (lx_dsp_reg_read(chip, eReg_CSM) & (Reg_CSM_MC | Reg_CSM_MR)) { - snd_printk(KERN_ERR LXP "PIOSendMessage eReg_CSM %x\n", reg); - return -EBUSY; - } - - /* write command */ - lx_dsp_reg_writebuf(chip, eReg_CRM1, rmh->cmd, rmh->cmd_len); - - /* MicoBlaze gogogo */ - lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC); - - /* wait for device to answer */ - for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS * 1000; ++dwloop) { - if (lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR) { - if (rmh->dsp_stat == 0) - reg = lx_dsp_reg_read(chip, eReg_CRM1); - else - reg = 0; - goto polling_successful; - } else - udelay(1); - } - snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send_atomic! " - "polling failed\n"); - -polling_successful: - if ((reg & ERROR_VALUE) == 0) { - /* read response */ - if (rmh->stat_len) { - snd_BUG_ON(rmh->stat_len >= (REG_CRM_NUMBER-1)); - lx_dsp_reg_readbuf(chip, eReg_CRM2, rmh->stat, - rmh->stat_len); - } - } else - snd_printk(LXP "rmh error: %08x\n", reg); - - /* clear Reg_CSM_MR */ - lx_dsp_reg_write(chip, eReg_CSM, 0); - - switch (reg) { - case ED_DSP_TIMED_OUT: - snd_printk(KERN_WARNING LXP "lx_message_send: dsp timeout\n"); - return -ETIMEDOUT; - - case ED_DSP_CRASHED: - snd_printk(KERN_WARNING LXP "lx_message_send: dsp crashed\n"); - return -EAGAIN; - } - - lx_message_dump(rmh); - - return reg; -} - - -/* low-level dsp access */ -int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version) -{ - u16 ret; - unsigned long flags; - - spin_lock_irqsave(&chip->msg_lock, flags); - - lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG); - ret = lx_message_send_atomic(chip, &chip->rmh); - - *rdsp_version = chip->rmh.stat[1]; - spin_unlock_irqrestore(&chip->msg_lock, flags); - return ret; -} - -int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq) -{ - u16 ret = 0; - unsigned long flags; - u32 freq_raw = 0; - u32 freq = 0; - u32 frequency = 0; - - spin_lock_irqsave(&chip->msg_lock, flags); - - lx_message_init(&chip->rmh, CMD_01_GET_SYS_CFG); - ret = lx_message_send_atomic(chip, &chip->rmh); - - if (ret == 0) { - freq_raw = chip->rmh.stat[0] >> FREQ_FIELD_OFFSET; - freq = freq_raw & XES_FREQ_COUNT8_MASK; - - if ((freq < XES_FREQ_COUNT8_48_MAX) || - (freq > XES_FREQ_COUNT8_44_MIN)) - frequency = 0; /* unknown */ - else if (freq >= XES_FREQ_COUNT8_44_MAX) - frequency = 44100; - else - frequency = 48000; - } - - spin_unlock_irqrestore(&chip->msg_lock, flags); - - *rfreq = frequency * chip->freq_ratio; - - return ret; -} - -int lx_dsp_get_mac(struct lx6464es *chip) -{ - u32 macmsb, maclsb; - - macmsb = lx_dsp_reg_read(chip, eReg_ADMACESMSB) & 0x00FFFFFF; - maclsb = lx_dsp_reg_read(chip, eReg_ADMACESLSB) & 0x00FFFFFF; - - /* todo: endianess handling */ - chip->mac_address[5] = ((u8 *)(&maclsb))[0]; - chip->mac_address[4] = ((u8 *)(&maclsb))[1]; - chip->mac_address[3] = ((u8 *)(&maclsb))[2]; - chip->mac_address[2] = ((u8 *)(&macmsb))[0]; - chip->mac_address[1] = ((u8 *)(&macmsb))[1]; - chip->mac_address[0] = ((u8 *)(&macmsb))[2]; - - return 0; -} - - -int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&chip->msg_lock, flags); - - lx_message_init(&chip->rmh, CMD_02_SET_GRANULARITY); - chip->rmh.cmd[0] |= gran; - - ret = lx_message_send_atomic(chip, &chip->rmh); - spin_unlock_irqrestore(&chip->msg_lock, flags); - return ret; -} - -int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&chip->msg_lock, flags); - - lx_message_init(&chip->rmh, CMD_04_GET_EVENT); - chip->rmh.stat_len = 9; /* we don't necessarily need the full length */ - - ret = lx_message_send_atomic(chip, &chip->rmh); - - if (!ret) - memcpy(data, chip->rmh.stat, chip->rmh.stat_len * sizeof(u32)); - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return ret; -} - -#define CSES_TIMEOUT 100 /* microseconds */ -#define CSES_CE 0x0001 -#define CSES_BROADCAST 0x0002 -#define CSES_UPDATE_LDSV 0x0004 - -int lx_dsp_es_check_pipeline(struct lx6464es *chip) -{ - int i; - - for (i = 0; i != CSES_TIMEOUT; ++i) { - /* - * le bit CSES_UPDATE_LDSV est à 1 dés que le macprog - * est pret. il re-passe à 0 lorsque le premier read a - * été fait. pour l'instant on retire le test car ce bit - * passe a 1 environ 200 à 400 ms aprés que le registre - * confES à été écrit (kick du xilinx ES). - * - * On ne teste que le bit CE. - * */ - - u32 cses = lx_dsp_reg_read(chip, eReg_CSES); - - if ((cses & CSES_CE) == 0) - return 0; - - udelay(1); - } - - return -ETIMEDOUT; -} - - -#define PIPE_INFO_TO_CMD(capture, pipe) \ - ((u32)((u32)(pipe) | ((capture) ? ID_IS_CAPTURE : 0L)) << ID_OFFSET) - - - -/* low-level pipe handling */ -int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture, - int channels) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_06_ALLOCATE_PIPE); - - chip->rmh.cmd[0] |= pipe_cmd; - chip->rmh.cmd[0] |= channels; - - err = lx_message_send_atomic(chip, &chip->rmh); - spin_unlock_irqrestore(&chip->msg_lock, flags); - - if (err != 0) - snd_printk(KERN_ERR "lx6464es: could not allocate pipe\n"); - - return err; -} - -int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_07_RELEASE_PIPE); - - chip->rmh.cmd[0] |= pipe_cmd; - - err = lx_message_send_atomic(chip, &chip->rmh); - spin_unlock_irqrestore(&chip->msg_lock, flags); - - return err; -} - -int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, - u32 *r_needed, u32 *r_freed, u32 *size_array) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - -#ifdef CONFIG_SND_DEBUG - if (size_array) - memset(size_array, 0, sizeof(u32)*MAX_STREAM_BUFFER); -#endif - - *r_needed = 0; - *r_freed = 0; - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_08_ASK_BUFFERS); - - chip->rmh.cmd[0] |= pipe_cmd; - - err = lx_message_send_atomic(chip, &chip->rmh); - - if (!err) { - int i; - for (i = 0; i < MAX_STREAM_BUFFER; ++i) { - u32 stat = chip->rmh.stat[i]; - if (stat & (BF_EOB << BUFF_FLAGS_OFFSET)) { - /* finished */ - *r_freed += 1; - if (size_array) - size_array[i] = stat & MASK_DATA_SIZE; - } else if ((stat & (BF_VALID << BUFF_FLAGS_OFFSET)) - == 0) - /* free */ - *r_needed += 1; - } - -#if 0 - snd_printdd(LXP "CMD_08_ASK_BUFFERS: needed %d, freed %d\n", - *r_needed, *r_freed); - for (i = 0; i < MAX_STREAM_BUFFER; ++i) { - for (i = 0; i != chip->rmh.stat_len; ++i) - snd_printdd(" stat[%d]: %x, %x\n", i, - chip->rmh.stat[i], - chip->rmh.stat[i] & MASK_DATA_SIZE); - } -#endif - } - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - - -int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_09_STOP_PIPE); - - chip->rmh.cmd[0] |= pipe_cmd; - - err = lx_message_send_atomic(chip, &chip->rmh); - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -static int lx_pipe_toggle_state(struct lx6464es *chip, u32 pipe, int is_capture) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_0B_TOGGLE_PIPE_STATE); - - chip->rmh.cmd[0] |= pipe_cmd; - - err = lx_message_send_atomic(chip, &chip->rmh); - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - - -int lx_pipe_start(struct lx6464es *chip, u32 pipe, int is_capture) -{ - int err; - - err = lx_pipe_wait_for_idle(chip, pipe, is_capture); - if (err < 0) - return err; - - err = lx_pipe_toggle_state(chip, pipe, is_capture); - - return err; -} - -int lx_pipe_pause(struct lx6464es *chip, u32 pipe, int is_capture) -{ - int err = 0; - - err = lx_pipe_wait_for_start(chip, pipe, is_capture); - if (err < 0) - return err; - - err = lx_pipe_toggle_state(chip, pipe, is_capture); - - return err; -} - - -int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture, - u64 *rsample_count) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT); - - chip->rmh.cmd[0] |= pipe_cmd; - chip->rmh.stat_len = 2; /* need all words here! */ - - err = lx_message_send_atomic(chip, &chip->rmh); /* don't sleep! */ - - if (err != 0) - snd_printk(KERN_ERR - "lx6464es: could not query pipe's sample count\n"); - else { - *rsample_count = ((u64)(chip->rmh.stat[0] & MASK_SPL_COUNT_HI) - << 24) /* hi part */ - + chip->rmh.stat[1]; /* lo part */ - } - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_0A_GET_PIPE_SPL_COUNT); - - chip->rmh.cmd[0] |= pipe_cmd; - - err = lx_message_send_atomic(chip, &chip->rmh); - - if (err != 0) - snd_printk(KERN_ERR "lx6464es: could not query pipe's state\n"); - else - *rstate = (chip->rmh.stat[0] >> PSTATE_OFFSET) & 0x0F; - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -static int lx_pipe_wait_for_state(struct lx6464es *chip, u32 pipe, - int is_capture, u16 state) -{ - int i; - - /* max 2*PCMOnlyGranularity = 2*1024 at 44100 = < 50 ms: - * timeout 50 ms */ - for (i = 0; i != 50; ++i) { - u16 current_state; - int err = lx_pipe_state(chip, pipe, is_capture, ¤t_state); - - if (err < 0) - return err; - - if (current_state == state) - return 0; - - mdelay(1); - } - - return -ETIMEDOUT; -} - -int lx_pipe_wait_for_start(struct lx6464es *chip, u32 pipe, int is_capture) -{ - return lx_pipe_wait_for_state(chip, pipe, is_capture, PSTATE_RUN); -} - -int lx_pipe_wait_for_idle(struct lx6464es *chip, u32 pipe, int is_capture) -{ - return lx_pipe_wait_for_state(chip, pipe, is_capture, PSTATE_IDLE); -} - -/* low-level stream handling */ -int lx_stream_set_state(struct lx6464es *chip, u32 pipe, - int is_capture, enum stream_state_t state) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_13_SET_STREAM_STATE); - - chip->rmh.cmd[0] |= pipe_cmd; - chip->rmh.cmd[0] |= state; - - err = lx_message_send_atomic(chip, &chip->rmh); - spin_unlock_irqrestore(&chip->msg_lock, flags); - - return err; -} - -int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime, - u32 pipe, int is_capture) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - u32 channels = runtime->channels; - - if (runtime->channels != channels) - snd_printk(KERN_ERR LXP "channel count mismatch: %d vs %d", - runtime->channels, channels); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_0C_DEF_STREAM); - - chip->rmh.cmd[0] |= pipe_cmd; - - if (runtime->sample_bits == 16) - /* 16 bit format */ - chip->rmh.cmd[0] |= (STREAM_FMT_16b << STREAM_FMT_OFFSET); - - if (snd_pcm_format_little_endian(runtime->format)) - /* little endian/intel format */ - chip->rmh.cmd[0] |= (STREAM_FMT_intel << STREAM_FMT_OFFSET); - - chip->rmh.cmd[0] |= channels-1; - - err = lx_message_send_atomic(chip, &chip->rmh); - spin_unlock_irqrestore(&chip->msg_lock, flags); - - return err; -} - -int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture, - int *rstate) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT); - - chip->rmh.cmd[0] |= pipe_cmd; - - err = lx_message_send_atomic(chip, &chip->rmh); - - *rstate = (chip->rmh.stat[0] & SF_START) ? START_STATE : PAUSE_STATE; - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture, - u64 *r_bytepos) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_0E_GET_STREAM_SPL_COUNT); - - chip->rmh.cmd[0] |= pipe_cmd; - - err = lx_message_send_atomic(chip, &chip->rmh); - - *r_bytepos = ((u64) (chip->rmh.stat[0] & MASK_SPL_COUNT_HI) - << 32) /* hi part */ - + chip->rmh.stat[1]; /* lo part */ - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -/* low-level buffer handling */ -int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture, - u32 buffer_size, u32 buf_address_lo, u32 buf_address_hi, - u32 *r_buffer_index) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_0F_UPDATE_BUFFER); - - chip->rmh.cmd[0] |= pipe_cmd; - chip->rmh.cmd[0] |= BF_NOTIFY_EOB; /* request interrupt notification */ - - /* todo: pause request, circular buffer */ - - chip->rmh.cmd[1] = buffer_size & MASK_DATA_SIZE; - chip->rmh.cmd[2] = buf_address_lo; - - if (buf_address_hi) { - chip->rmh.cmd_len = 4; - chip->rmh.cmd[3] = buf_address_hi; - chip->rmh.cmd[0] |= BF_64BITS_ADR; - } - - err = lx_message_send_atomic(chip, &chip->rmh); - - if (err == 0) { - *r_buffer_index = chip->rmh.stat[0]; - goto done; - } - - if (err == EB_RBUFFERS_TABLE_OVERFLOW) - snd_printk(LXP "lx_buffer_give EB_RBUFFERS_TABLE_OVERFLOW\n"); - - if (err == EB_INVALID_STREAM) - snd_printk(LXP "lx_buffer_give EB_INVALID_STREAM\n"); - - if (err == EB_CMD_REFUSED) - snd_printk(LXP "lx_buffer_give EB_CMD_REFUSED\n"); - - done: - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture, - u32 *r_buffer_size) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER); - - chip->rmh.cmd[0] |= pipe_cmd; - chip->rmh.cmd[0] |= MASK_BUFFER_ID; /* ask for the current buffer: the - * microblaze will seek for it */ - - err = lx_message_send_atomic(chip, &chip->rmh); - - if (err == 0) - *r_buffer_size = chip->rmh.stat[0] & MASK_DATA_SIZE; - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture, - u32 buffer_index) -{ - int err; - unsigned long flags; - - u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_11_CANCEL_BUFFER); - - chip->rmh.cmd[0] |= pipe_cmd; - chip->rmh.cmd[0] |= buffer_index; - - err = lx_message_send_atomic(chip, &chip->rmh); - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - - -/* low-level gain/peak handling - * - * \todo: can we unmute capture/playback channels independently? - * - * */ -int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute) -{ - int err; - unsigned long flags; - - /* bit set to 1: channel muted */ - u64 mute_mask = unmute ? 0 : 0xFFFFFFFFFFFFFFFFLLU; - - spin_lock_irqsave(&chip->msg_lock, flags); - lx_message_init(&chip->rmh, CMD_0D_SET_MUTE); - - chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, 0); - - chip->rmh.cmd[1] = (u32)(mute_mask >> (u64)32); /* hi part */ - chip->rmh.cmd[2] = (u32)(mute_mask & (u64)0xFFFFFFFF); /* lo part */ - - snd_printk("mute %x %x %x\n", chip->rmh.cmd[0], chip->rmh.cmd[1], - chip->rmh.cmd[2]); - - err = lx_message_send_atomic(chip, &chip->rmh); - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -static u32 peak_map[] = { - 0x00000109, /* -90.308dB */ - 0x0000083B, /* -72.247dB */ - 0x000020C4, /* -60.205dB */ - 0x00008273, /* -48.030dB */ - 0x00020756, /* -36.005dB */ - 0x00040C37, /* -30.001dB */ - 0x00081385, /* -24.002dB */ - 0x00101D3F, /* -18.000dB */ - 0x0016C310, /* -15.000dB */ - 0x002026F2, /* -12.001dB */ - 0x002D6A86, /* -9.000dB */ - 0x004026E6, /* -6.004dB */ - 0x005A9DF6, /* -3.000dB */ - 0x0065AC8B, /* -2.000dB */ - 0x00721481, /* -1.000dB */ - 0x007FFFFF, /* FS */ -}; - -int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels, - u32 *r_levels) -{ - int err = 0; - unsigned long flags; - int i; - spin_lock_irqsave(&chip->msg_lock, flags); - - for (i = 0; i < channels; i += 4) { - u32 s0, s1, s2, s3; - - lx_message_init(&chip->rmh, CMD_12_GET_PEAK); - chip->rmh.cmd[0] |= PIPE_INFO_TO_CMD(is_capture, i); - - err = lx_message_send_atomic(chip, &chip->rmh); - - if (err == 0) { - s0 = peak_map[chip->rmh.stat[0] & 0x0F]; - s1 = peak_map[(chip->rmh.stat[0] >> 4) & 0xf]; - s2 = peak_map[(chip->rmh.stat[0] >> 8) & 0xf]; - s3 = peak_map[(chip->rmh.stat[0] >> 12) & 0xf]; - } else - s0 = s1 = s2 = s3 = 0; - - r_levels[0] = s0; - r_levels[1] = s1; - r_levels[2] = s2; - r_levels[3] = s3; - - r_levels += 4; - } - - spin_unlock_irqrestore(&chip->msg_lock, flags); - return err; -} - -/* interrupt handling */ -#define PCX_IRQ_NONE 0 -#define IRQCS_ACTIVE_PCIDB 0x00002000L /* Bit nø 13 */ -#define IRQCS_ENABLE_PCIIRQ 0x00000100L /* Bit nø 08 */ -#define IRQCS_ENABLE_PCIDB 0x00000200L /* Bit nø 09 */ - -static u32 lx_interrupt_test_ack(struct lx6464es *chip) -{ - u32 irqcs = lx_plx_reg_read(chip, ePLX_IRQCS); - - /* Test if PCI Doorbell interrupt is active */ - if (irqcs & IRQCS_ACTIVE_PCIDB) { - u32 temp; - irqcs = PCX_IRQ_NONE; - - while ((temp = lx_plx_reg_read(chip, ePLX_L2PCIDB))) { - /* RAZ interrupt */ - irqcs |= temp; - lx_plx_reg_write(chip, ePLX_L2PCIDB, temp); - } - - return irqcs; - } - return PCX_IRQ_NONE; -} - -static int lx_interrupt_ack(struct lx6464es *chip, u32 *r_irqsrc, - int *r_async_pending, int *r_async_escmd) -{ - u32 irq_async; - u32 irqsrc = lx_interrupt_test_ack(chip); - - if (irqsrc == PCX_IRQ_NONE) - return 0; - - *r_irqsrc = irqsrc; - - irq_async = irqsrc & MASK_SYS_ASYNC_EVENTS; /* + EtherSound response - * (set by xilinx) + EOB */ - - if (irq_async & MASK_SYS_STATUS_ESA) { - irq_async &= ~MASK_SYS_STATUS_ESA; - *r_async_escmd = 1; - } - - if (irq_async) { - /* snd_printd("interrupt: async event pending\n"); */ - *r_async_pending = 1; - } - - return 1; -} - -static int lx_interrupt_handle_async_events(struct lx6464es *chip, u32 irqsrc, - int *r_freq_changed, - u64 *r_notified_in_pipe_mask, - u64 *r_notified_out_pipe_mask) -{ - int err; - u32 stat[9]; /* answer from CMD_04_GET_EVENT */ - - /* On peut optimiser pour ne pas lire les evenements vides - * les mots de réponse sont dans l'ordre suivant : - * Stat[0] mot de status général - * Stat[1] fin de buffer OUT pF - * Stat[2] fin de buffer OUT pf - * Stat[3] fin de buffer IN pF - * Stat[4] fin de buffer IN pf - * Stat[5] underrun poid fort - * Stat[6] underrun poid faible - * Stat[7] overrun poid fort - * Stat[8] overrun poid faible - * */ - - u64 orun_mask; - u64 urun_mask; -#if 0 - int has_underrun = (irqsrc & MASK_SYS_STATUS_URUN) ? 1 : 0; - int has_overrun = (irqsrc & MASK_SYS_STATUS_ORUN) ? 1 : 0; -#endif - int eb_pending_out = (irqsrc & MASK_SYS_STATUS_EOBO) ? 1 : 0; - int eb_pending_in = (irqsrc & MASK_SYS_STATUS_EOBI) ? 1 : 0; - - *r_freq_changed = (irqsrc & MASK_SYS_STATUS_FREQ) ? 1 : 0; - - err = lx_dsp_read_async_events(chip, stat); - if (err < 0) - return err; - - if (eb_pending_in) { - *r_notified_in_pipe_mask = ((u64)stat[3] << 32) - + stat[4]; - snd_printdd(LXP "interrupt: EOBI pending %llx\n", - *r_notified_in_pipe_mask); - } - if (eb_pending_out) { - *r_notified_out_pipe_mask = ((u64)stat[1] << 32) - + stat[2]; - snd_printdd(LXP "interrupt: EOBO pending %llx\n", - *r_notified_out_pipe_mask); - } - - orun_mask = ((u64)stat[7] << 32) + stat[8]; - urun_mask = ((u64)stat[5] << 32) + stat[6]; - - /* todo: handle xrun notification */ - - return err; -} - -static int lx_interrupt_request_new_buffer(struct lx6464es *chip, - struct lx_stream *lx_stream) -{ - struct snd_pcm_substream *substream = lx_stream->stream; - const unsigned int is_capture = lx_stream->is_capture; - int err; - unsigned long flags; - - const u32 channels = substream->runtime->channels; - const u32 bytes_per_frame = channels * 3; - const u32 period_size = substream->runtime->period_size; - const u32 period_bytes = period_size * bytes_per_frame; - const u32 pos = lx_stream->frame_pos; - const u32 next_pos = ((pos+1) == substream->runtime->periods) ? - 0 : pos + 1; - - dma_addr_t buf = substream->dma_buffer.addr + pos * period_bytes; - u32 buf_hi = 0; - u32 buf_lo = 0; - u32 buffer_index = 0; - - u32 needed, freed; - u32 size_array[MAX_STREAM_BUFFER]; - - snd_printdd("->lx_interrupt_request_new_buffer\n"); - - spin_lock_irqsave(&chip->lock, flags); - - err = lx_buffer_ask(chip, 0, is_capture, &needed, &freed, size_array); - snd_printdd(LXP "interrupt: needed %d, freed %d\n", needed, freed); - - unpack_pointer(buf, &buf_lo, &buf_hi); - err = lx_buffer_give(chip, 0, is_capture, period_bytes, buf_lo, buf_hi, - &buffer_index); - snd_printdd(LXP "interrupt: gave buffer index %x on %p (%d bytes)\n", - buffer_index, (void *)buf, period_bytes); - - lx_stream->frame_pos = next_pos; - spin_unlock_irqrestore(&chip->lock, flags); - - return err; -} - -void lx_tasklet_playback(unsigned long data) -{ - struct lx6464es *chip = (struct lx6464es *)data; - struct lx_stream *lx_stream = &chip->playback_stream; - int err; - - snd_printdd("->lx_tasklet_playback\n"); - - err = lx_interrupt_request_new_buffer(chip, lx_stream); - if (err < 0) - snd_printk(KERN_ERR LXP - "cannot request new buffer for playback\n"); - - snd_pcm_period_elapsed(lx_stream->stream); -} - -void lx_tasklet_capture(unsigned long data) -{ - struct lx6464es *chip = (struct lx6464es *)data; - struct lx_stream *lx_stream = &chip->capture_stream; - int err; - - snd_printdd("->lx_tasklet_capture\n"); - err = lx_interrupt_request_new_buffer(chip, lx_stream); - if (err < 0) - snd_printk(KERN_ERR LXP - "cannot request new buffer for capture\n"); - - snd_pcm_period_elapsed(lx_stream->stream); -} - - - -static int lx_interrupt_handle_audio_transfer(struct lx6464es *chip, - u64 notified_in_pipe_mask, - u64 notified_out_pipe_mask) -{ - int err = 0; - - if (notified_in_pipe_mask) { - snd_printdd(LXP "requesting audio transfer for capture\n"); - tasklet_hi_schedule(&chip->tasklet_capture); - } - - if (notified_out_pipe_mask) { - snd_printdd(LXP "requesting audio transfer for playback\n"); - tasklet_hi_schedule(&chip->tasklet_playback); - } - - return err; -} - - -irqreturn_t lx_interrupt(int irq, void *dev_id) -{ - struct lx6464es *chip = dev_id; - int async_pending, async_escmd; - u32 irqsrc; - - spin_lock(&chip->lock); - - snd_printdd("**************************************************\n"); - - if (!lx_interrupt_ack(chip, &irqsrc, &async_pending, &async_escmd)) { - spin_unlock(&chip->lock); - snd_printdd("IRQ_NONE\n"); - return IRQ_NONE; /* this device did not cause the interrupt */ - } - - if (irqsrc & MASK_SYS_STATUS_CMD_DONE) - goto exit; - -#if 0 - if (irqsrc & MASK_SYS_STATUS_EOBI) - snd_printdd(LXP "interrupt: EOBI\n"); - - if (irqsrc & MASK_SYS_STATUS_EOBO) - snd_printdd(LXP "interrupt: EOBO\n"); - - if (irqsrc & MASK_SYS_STATUS_URUN) - snd_printdd(LXP "interrupt: URUN\n"); - - if (irqsrc & MASK_SYS_STATUS_ORUN) - snd_printdd(LXP "interrupt: ORUN\n"); -#endif - - if (async_pending) { - u64 notified_in_pipe_mask = 0; - u64 notified_out_pipe_mask = 0; - int freq_changed; - int err; - - /* handle async events */ - err = lx_interrupt_handle_async_events(chip, irqsrc, - &freq_changed, - ¬ified_in_pipe_mask, - ¬ified_out_pipe_mask); - if (err) - snd_printk(KERN_ERR LXP - "error handling async events\n"); - - err = lx_interrupt_handle_audio_transfer(chip, - notified_in_pipe_mask, - notified_out_pipe_mask - ); - if (err) - snd_printk(KERN_ERR LXP - "error during audio transfer\n"); - } - - if (async_escmd) { -#if 0 - /* backdoor for ethersound commands - * - * for now, we do not need this - * - * */ - - snd_printdd("lx6464es: interrupt requests escmd handling\n"); -#endif - } - -exit: - spin_unlock(&chip->lock); - return IRQ_HANDLED; /* this device caused the interrupt */ -} - - -static void lx_irq_set(struct lx6464es *chip, int enable) -{ - u32 reg = lx_plx_reg_read(chip, ePLX_IRQCS); - - /* enable/disable interrupts - * - * Set the Doorbell and PCI interrupt enable bits - * - * */ - if (enable) - reg |= (IRQCS_ENABLE_PCIIRQ | IRQCS_ENABLE_PCIDB); - else - reg &= ~(IRQCS_ENABLE_PCIIRQ | IRQCS_ENABLE_PCIDB); - lx_plx_reg_write(chip, ePLX_IRQCS, reg); -} - -void lx_irq_enable(struct lx6464es *chip) -{ - snd_printdd("->lx_irq_enable\n"); - lx_irq_set(chip, 1); -} - -void lx_irq_disable(struct lx6464es *chip) -{ - snd_printdd("->lx_irq_disable\n"); - lx_irq_set(chip, 0); -} diff --git a/ANDROID_3.4.5/sound/pci/lx6464es/lx_core.h b/ANDROID_3.4.5/sound/pci/lx6464es/lx_core.h deleted file mode 100644 index 4d7ff797..00000000 --- a/ANDROID_3.4.5/sound/pci/lx6464es/lx_core.h +++ /dev/null @@ -1,239 +0,0 @@ -/* -*- linux-c -*- * - * - * ALSA driver for the digigram lx6464es interface - * low-level interface - * - * Copyright (c) 2009 Tim Blechmann - * - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef LX_CORE_H -#define LX_CORE_H - -#include - -#include "lx_defs.h" - -#define REG_CRM_NUMBER 12 - -struct lx6464es; - -/* low-level register access */ - -/* dsp register access */ -enum { - eReg_BASE, - eReg_CSM, - eReg_CRM1, - eReg_CRM2, - eReg_CRM3, - eReg_CRM4, - eReg_CRM5, - eReg_CRM6, - eReg_CRM7, - eReg_CRM8, - eReg_CRM9, - eReg_CRM10, - eReg_CRM11, - eReg_CRM12, - - eReg_ICR, - eReg_CVR, - eReg_ISR, - eReg_RXHTXH, - eReg_RXMTXM, - eReg_RHLTXL, - eReg_RESETDSP, - - eReg_CSUF, - eReg_CSES, - eReg_CRESMSB, - eReg_CRESLSB, - eReg_ADMACESMSB, - eReg_ADMACESLSB, - eReg_CONFES, - - eMaxPortLx -}; - -unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port); -void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data); - -/* plx register access */ -enum { - ePLX_PCICR, - - ePLX_MBOX0, - ePLX_MBOX1, - ePLX_MBOX2, - ePLX_MBOX3, - ePLX_MBOX4, - ePLX_MBOX5, - ePLX_MBOX6, - ePLX_MBOX7, - - ePLX_L2PCIDB, - ePLX_IRQCS, - ePLX_CHIPSC, - - eMaxPort -}; - -unsigned long lx_plx_reg_read(struct lx6464es *chip, int port); -void lx_plx_reg_write(struct lx6464es *chip, int port, u32 data); - -/* rhm */ -struct lx_rmh { - u16 cmd_len; /* length of the command to send (WORDs) */ - u16 stat_len; /* length of the status received (WORDs) */ - u16 dsp_stat; /* status type, RMP_SSIZE_XXX */ - u16 cmd_idx; /* index of the command */ - u32 cmd[REG_CRM_NUMBER]; - u32 stat[REG_CRM_NUMBER]; -}; - - -/* low-level dsp access */ -int __devinit lx_dsp_get_version(struct lx6464es *chip, u32 *rdsp_version); -int lx_dsp_get_clock_frequency(struct lx6464es *chip, u32 *rfreq); -int lx_dsp_set_granularity(struct lx6464es *chip, u32 gran); -int lx_dsp_read_async_events(struct lx6464es *chip, u32 *data); -int lx_dsp_get_mac(struct lx6464es *chip); - - -/* low-level pipe handling */ -int lx_pipe_allocate(struct lx6464es *chip, u32 pipe, int is_capture, - int channels); -int lx_pipe_release(struct lx6464es *chip, u32 pipe, int is_capture); -int lx_pipe_sample_count(struct lx6464es *chip, u32 pipe, int is_capture, - u64 *rsample_count); -int lx_pipe_state(struct lx6464es *chip, u32 pipe, int is_capture, u16 *rstate); -int lx_pipe_stop(struct lx6464es *chip, u32 pipe, int is_capture); -int lx_pipe_start(struct lx6464es *chip, u32 pipe, int is_capture); -int lx_pipe_pause(struct lx6464es *chip, u32 pipe, int is_capture); - -int lx_pipe_wait_for_start(struct lx6464es *chip, u32 pipe, int is_capture); -int lx_pipe_wait_for_idle(struct lx6464es *chip, u32 pipe, int is_capture); - -/* low-level stream handling */ -int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime, - u32 pipe, int is_capture); -int lx_stream_state(struct lx6464es *chip, u32 pipe, int is_capture, - int *rstate); -int lx_stream_sample_position(struct lx6464es *chip, u32 pipe, int is_capture, - u64 *r_bytepos); - -int lx_stream_set_state(struct lx6464es *chip, u32 pipe, - int is_capture, enum stream_state_t state); - -static inline int lx_stream_start(struct lx6464es *chip, u32 pipe, - int is_capture) -{ - snd_printdd("->lx_stream_start\n"); - return lx_stream_set_state(chip, pipe, is_capture, SSTATE_RUN); -} - -static inline int lx_stream_pause(struct lx6464es *chip, u32 pipe, - int is_capture) -{ - snd_printdd("->lx_stream_pause\n"); - return lx_stream_set_state(chip, pipe, is_capture, SSTATE_PAUSE); -} - -static inline int lx_stream_stop(struct lx6464es *chip, u32 pipe, - int is_capture) -{ - snd_printdd("->lx_stream_stop\n"); - return lx_stream_set_state(chip, pipe, is_capture, SSTATE_STOP); -} - -/* low-level buffer handling */ -int lx_buffer_ask(struct lx6464es *chip, u32 pipe, int is_capture, - u32 *r_needed, u32 *r_freed, u32 *size_array); -int lx_buffer_give(struct lx6464es *chip, u32 pipe, int is_capture, - u32 buffer_size, u32 buf_address_lo, u32 buf_address_hi, - u32 *r_buffer_index); -int lx_buffer_free(struct lx6464es *chip, u32 pipe, int is_capture, - u32 *r_buffer_size); -int lx_buffer_cancel(struct lx6464es *chip, u32 pipe, int is_capture, - u32 buffer_index); - -/* low-level gain/peak handling */ -int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute); -int lx_level_peaks(struct lx6464es *chip, int is_capture, int channels, - u32 *r_levels); - - -/* interrupt handling */ -irqreturn_t lx_interrupt(int irq, void *dev_id); -void lx_irq_enable(struct lx6464es *chip); -void lx_irq_disable(struct lx6464es *chip); - -void lx_tasklet_capture(unsigned long data); -void lx_tasklet_playback(unsigned long data); - - -/* Stream Format Header Defines (for LIN and IEEE754) */ -#define HEADER_FMT_BASE HEADER_FMT_BASE_LIN -#define HEADER_FMT_BASE_LIN 0xFED00000 -#define HEADER_FMT_BASE_FLOAT 0xFAD00000 -#define HEADER_FMT_MONO 0x00000080 /* bit 23 in header_lo. WARNING: old - * bit 22 is ignored in float - * format */ -#define HEADER_FMT_INTEL 0x00008000 -#define HEADER_FMT_16BITS 0x00002000 -#define HEADER_FMT_24BITS 0x00004000 -#define HEADER_FMT_UPTO11 0x00000200 /* frequency is less or equ. to 11k. - * */ -#define HEADER_FMT_UPTO32 0x00000100 /* frequency is over 11k and less - * then 32k.*/ - - -#define BIT_FMP_HEADER 23 -#define BIT_FMP_SD 22 -#define BIT_FMP_MULTICHANNEL 19 - -#define START_STATE 1 -#define PAUSE_STATE 0 - - - - - -/* from PcxAll_e.h */ -/* Start/Pause condition for pipes (PCXStartPipe, PCXPausePipe) */ -#define START_PAUSE_IMMEDIATE 0 -#define START_PAUSE_ON_SYNCHRO 1 -#define START_PAUSE_ON_TIME_CODE 2 - - -/* Pipe / Stream state */ -#define START_STATE 1 -#define PAUSE_STATE 0 - -static inline void unpack_pointer(dma_addr_t ptr, u32 *r_low, u32 *r_high) -{ - *r_low = (u32)(ptr & 0xffffffff); -#if BITS_PER_LONG == 32 - *r_high = 0; -#else - *r_high = (u32)((u64)ptr>>32); -#endif -} - -#endif /* LX_CORE_H */ diff --git a/ANDROID_3.4.5/sound/pci/lx6464es/lx_defs.h b/ANDROID_3.4.5/sound/pci/lx6464es/lx_defs.h deleted file mode 100644 index 49d36bdd..00000000 --- a/ANDROID_3.4.5/sound/pci/lx6464es/lx_defs.h +++ /dev/null @@ -1,376 +0,0 @@ -/* -*- linux-c -*- * - * - * ALSA driver for the digigram lx6464es interface - * adapted upstream headers - * - * Copyright (c) 2009 Tim Blechmann - * - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef LX_DEFS_H -#define LX_DEFS_H - -/* code adapted from ethersound.h */ -#define XES_FREQ_COUNT8_MASK 0x00001FFF /* compteur 25MHz entre 8 ech. */ -#define XES_FREQ_COUNT8_44_MIN 0x00001288 /* 25M / - * [ 44k - ( 44.1k + 48k ) / 2 ] - * * 8 */ -#define XES_FREQ_COUNT8_44_MAX 0x000010F0 /* 25M / [ ( 44.1k + 48k ) / 2 ] - * * 8 */ -#define XES_FREQ_COUNT8_48_MAX 0x00000F08 /* 25M / - * [ 48k + ( 44.1k + 48k ) / 2 ] - * * 8 */ - -/* code adapted from LXES_registers.h */ - -#define IOCR_OUTPUTS_OFFSET 0 /* (rw) offset for the number of OUTs in the - * ConfES register. */ -#define IOCR_INPUTS_OFFSET 8 /* (rw) offset for the number of INs in the - * ConfES register. */ -#define FREQ_RATIO_OFFSET 19 /* (rw) offset for frequency ratio in the - * ConfES register. */ -#define FREQ_RATIO_SINGLE_MODE 0x01 /* value for single mode frequency ratio: - * sample rate = frequency rate. */ - -#define CONFES_READ_PART_MASK 0x00070000 -#define CONFES_WRITE_PART_MASK 0x00F80000 - -/* code adapted from if_drv_mb.h */ - -#define MASK_SYS_STATUS_ERROR (1L << 31) /* events that lead to a PCI irq if - * not yet pending */ -#define MASK_SYS_STATUS_URUN (1L << 30) -#define MASK_SYS_STATUS_ORUN (1L << 29) -#define MASK_SYS_STATUS_EOBO (1L << 28) -#define MASK_SYS_STATUS_EOBI (1L << 27) -#define MASK_SYS_STATUS_FREQ (1L << 26) -#define MASK_SYS_STATUS_ESA (1L << 25) /* reserved, this is set by the - * XES */ -#define MASK_SYS_STATUS_TIMER (1L << 24) - -#define MASK_SYS_ASYNC_EVENTS (MASK_SYS_STATUS_ERROR | \ - MASK_SYS_STATUS_URUN | \ - MASK_SYS_STATUS_ORUN | \ - MASK_SYS_STATUS_EOBO | \ - MASK_SYS_STATUS_EOBI | \ - MASK_SYS_STATUS_FREQ | \ - MASK_SYS_STATUS_ESA) - -#define MASK_SYS_PCI_EVENTS (MASK_SYS_ASYNC_EVENTS | \ - MASK_SYS_STATUS_TIMER) - -#define MASK_SYS_TIMER_COUNT 0x0000FFFF - -#define MASK_SYS_STATUS_EOT_PLX (1L << 22) /* event that remains - * internal: reserved fo end - * of plx dma */ -#define MASK_SYS_STATUS_XES (1L << 21) /* event that remains - * internal: pending XES - * IRQ */ -#define MASK_SYS_STATUS_CMD_DONE (1L << 20) /* alternate command - * management: notify driver - * instead of polling */ - - -#define MAX_STREAM_BUFFER 5 /* max amount of stream buffers. */ - -#define MICROBLAZE_IBL_MIN 32 -#define MICROBLAZE_IBL_DEFAULT 128 -#define MICROBLAZE_IBL_MAX 512 -/* #define MASK_GRANULARITY (2*MICROBLAZE_IBL_MAX-1) */ - - - -/* command opcodes, see reference for details */ - -/* - the capture bit position in the object_id field in driver commands - depends upon the number of managed channels. For now, 64 IN + 64 OUT are - supported. HOwever, the communication protocol forsees 1024 channels, hence - bit 10 indicates a capture (input) object). -*/ -#define ID_IS_CAPTURE (1L << 10) -#define ID_OFFSET 13 /* object ID is at the 13th bit in the - * 1st command word.*/ -#define ID_CH_MASK 0x3F -#define OPCODE_OFFSET 24 /* offset of the command opcode in the first - * command word.*/ - -enum cmd_mb_opcodes { - CMD_00_INFO_DEBUG = 0x00, - CMD_01_GET_SYS_CFG = 0x01, - CMD_02_SET_GRANULARITY = 0x02, - CMD_03_SET_TIMER_IRQ = 0x03, - CMD_04_GET_EVENT = 0x04, - CMD_05_GET_PIPES = 0x05, - - CMD_06_ALLOCATE_PIPE = 0x06, - CMD_07_RELEASE_PIPE = 0x07, - CMD_08_ASK_BUFFERS = 0x08, - CMD_09_STOP_PIPE = 0x09, - CMD_0A_GET_PIPE_SPL_COUNT = 0x0a, - CMD_0B_TOGGLE_PIPE_STATE = 0x0b, - - CMD_0C_DEF_STREAM = 0x0c, - CMD_0D_SET_MUTE = 0x0d, - CMD_0E_GET_STREAM_SPL_COUNT = 0x0e, - CMD_0F_UPDATE_BUFFER = 0x0f, - CMD_10_GET_BUFFER = 0x10, - CMD_11_CANCEL_BUFFER = 0x11, - CMD_12_GET_PEAK = 0x12, - CMD_13_SET_STREAM_STATE = 0x13, - CMD_14_INVALID = 0x14, -}; - -/* pipe states */ -enum pipe_state_t { - PSTATE_IDLE = 0, /* the pipe is not processed in the XES_IRQ - * (free or stopped, or paused). */ - PSTATE_RUN = 1, /* sustained play/record state. */ - PSTATE_PURGE = 2, /* the ES channels are now off, render pipes do - * not DMA, record pipe do a last DMA. */ - PSTATE_ACQUIRE = 3, /* the ES channels are now on, render pipes do - * not yet increase their sample count, record - * pipes do not DMA. */ - PSTATE_CLOSING = 4, /* the pipe is releasing, and may not yet - * receive an "alloc" command. */ -}; - -/* stream states */ -enum stream_state_t { - SSTATE_STOP = 0x00, /* setting to stop resets the stream spl - * count.*/ - SSTATE_RUN = (0x01 << 0), /* start DMA and spl count handling. */ - SSTATE_PAUSE = (0x01 << 1), /* pause DMA and spl count handling. */ -}; - -/* buffer flags */ -enum buffer_flags { - BF_VALID = 0x80, /* set if the buffer is valid, clear if free.*/ - BF_CURRENT = 0x40, /* set if this is the current buffer (there is - * always a current buffer).*/ - BF_NOTIFY_EOB = 0x20, /* set if this buffer must cause a PCI event - * when finished.*/ - BF_CIRCULAR = 0x10, /* set if buffer[1] must be copied to buffer[0] - * by the end of this buffer.*/ - BF_64BITS_ADR = 0x08, /* set if the hi part of the address is valid.*/ - BF_xx = 0x04, /* future extension.*/ - BF_EOB = 0x02, /* set if finished, but not yet free.*/ - BF_PAUSE = 0x01, /* pause stream at buffer end.*/ - BF_ZERO = 0x00, /* no flags (init).*/ -}; - -/** -* Stream Flags definitions -*/ -enum stream_flags { - SF_ZERO = 0x00000000, /* no flags (stream invalid). */ - SF_VALID = 0x10000000, /* the stream has a valid DMA_conf - * info (setstreamformat). */ - SF_XRUN = 0x20000000, /* the stream is un x-run state. */ - SF_START = 0x40000000, /* the DMA is running.*/ - SF_ASIO = 0x80000000, /* ASIO.*/ -}; - - -#define MASK_SPL_COUNT_HI 0x00FFFFFF /* 4 MSBits are status bits */ -#define PSTATE_OFFSET 28 /* 4 MSBits are status bits */ - - -#define MASK_STREAM_HAS_MAPPING (1L << 12) -#define MASK_STREAM_IS_ASIO (1L << 9) -#define STREAM_FMT_OFFSET 10 /* the stream fmt bits start at the 10th - * bit in the command word. */ - -#define STREAM_FMT_16b 0x02 -#define STREAM_FMT_intel 0x01 - -#define FREQ_FIELD_OFFSET 15 /* offset of the freq field in the response - * word */ - -#define BUFF_FLAGS_OFFSET 24 /* offset of the buffer flags in the - * response word. */ -#define MASK_DATA_SIZE 0x00FFFFFF /* this must match the field size of - * datasize in the buffer_t structure. */ - -#define MASK_BUFFER_ID 0xFF /* the cancel command awaits a buffer ID, - * may be 0xFF for "current". */ - - -/* code adapted from PcxErr_e.h */ - -/* Bits masks */ - -#define ERROR_MASK 0x8000 - -#define SOURCE_MASK 0x7800 - -#define E_SOURCE_BOARD 0x4000 /* 8 >> 1 */ -#define E_SOURCE_DRV 0x2000 /* 4 >> 1 */ -#define E_SOURCE_API 0x1000 /* 2 >> 1 */ -/* Error tools */ -#define E_SOURCE_TOOLS 0x0800 /* 1 >> 1 */ -/* Error pcxaudio */ -#define E_SOURCE_AUDIO 0x1800 /* 3 >> 1 */ -/* Error virtual pcx */ -#define E_SOURCE_VPCX 0x2800 /* 5 >> 1 */ -/* Error dispatcher */ -#define E_SOURCE_DISPATCHER 0x3000 /* 6 >> 1 */ -/* Error from CobraNet firmware */ -#define E_SOURCE_COBRANET 0x3800 /* 7 >> 1 */ - -#define E_SOURCE_USER 0x7800 - -#define CLASS_MASK 0x0700 - -#define CODE_MASK 0x00FF - -/* Bits values */ - -/* Values for the error/warning bit */ -#define ERROR_VALUE 0x8000 -#define WARNING_VALUE 0x0000 - -/* Class values */ -#define E_CLASS_GENERAL 0x0000 -#define E_CLASS_INVALID_CMD 0x0100 -#define E_CLASS_INVALID_STD_OBJECT 0x0200 -#define E_CLASS_RSRC_IMPOSSIBLE 0x0300 -#define E_CLASS_WRONG_CONTEXT 0x0400 -#define E_CLASS_BAD_SPECIFIC_PARAMETER 0x0500 -#define E_CLASS_REAL_TIME_ERROR 0x0600 -#define E_CLASS_DIRECTSHOW 0x0700 -#define E_CLASS_FREE 0x0700 - - -/* Complete DRV error code for the general class */ -#define ED_GN (ERROR_VALUE | E_SOURCE_DRV | E_CLASS_GENERAL) -#define ED_CONCURRENCY (ED_GN | 0x01) -#define ED_DSP_CRASHED (ED_GN | 0x02) -#define ED_UNKNOWN_BOARD (ED_GN | 0x03) -#define ED_NOT_INSTALLED (ED_GN | 0x04) -#define ED_CANNOT_OPEN_SVC_MANAGER (ED_GN | 0x05) -#define ED_CANNOT_READ_REGISTRY (ED_GN | 0x06) -#define ED_DSP_VERSION_MISMATCH (ED_GN | 0x07) -#define ED_UNAVAILABLE_FEATURE (ED_GN | 0x08) -#define ED_CANCELLED (ED_GN | 0x09) -#define ED_NO_RESPONSE_AT_IRQA (ED_GN | 0x10) -#define ED_INVALID_ADDRESS (ED_GN | 0x11) -#define ED_DSP_CORRUPTED (ED_GN | 0x12) -#define ED_PENDING_OPERATION (ED_GN | 0x13) -#define ED_NET_ALLOCATE_MEMORY_IMPOSSIBLE (ED_GN | 0x14) -#define ED_NET_REGISTER_ERROR (ED_GN | 0x15) -#define ED_NET_THREAD_ERROR (ED_GN | 0x16) -#define ED_NET_OPEN_ERROR (ED_GN | 0x17) -#define ED_NET_CLOSE_ERROR (ED_GN | 0x18) -#define ED_NET_NO_MORE_PACKET (ED_GN | 0x19) -#define ED_NET_NO_MORE_BUFFER (ED_GN | 0x1A) -#define ED_NET_SEND_ERROR (ED_GN | 0x1B) -#define ED_NET_RECEIVE_ERROR (ED_GN | 0x1C) -#define ED_NET_WRONG_MSG_SIZE (ED_GN | 0x1D) -#define ED_NET_WAIT_ERROR (ED_GN | 0x1E) -#define ED_NET_EEPROM_ERROR (ED_GN | 0x1F) -#define ED_INVALID_RS232_COM_NUMBER (ED_GN | 0x20) -#define ED_INVALID_RS232_INIT (ED_GN | 0x21) -#define ED_FILE_ERROR (ED_GN | 0x22) -#define ED_INVALID_GPIO_CMD (ED_GN | 0x23) -#define ED_RS232_ALREADY_OPENED (ED_GN | 0x24) -#define ED_RS232_NOT_OPENED (ED_GN | 0x25) -#define ED_GPIO_ALREADY_OPENED (ED_GN | 0x26) -#define ED_GPIO_NOT_OPENED (ED_GN | 0x27) -#define ED_REGISTRY_ERROR (ED_GN | 0x28) /* <- NCX */ -#define ED_INVALID_SERVICE (ED_GN | 0x29) /* <- NCX */ - -#define ED_READ_FILE_ALREADY_OPENED (ED_GN | 0x2a) /* <- Decalage - * pour RCX - * (old 0x28) - * */ -#define ED_READ_FILE_INVALID_COMMAND (ED_GN | 0x2b) /* ~ */ -#define ED_READ_FILE_INVALID_PARAMETER (ED_GN | 0x2c) /* ~ */ -#define ED_READ_FILE_ALREADY_CLOSED (ED_GN | 0x2d) /* ~ */ -#define ED_READ_FILE_NO_INFORMATION (ED_GN | 0x2e) /* ~ */ -#define ED_READ_FILE_INVALID_HANDLE (ED_GN | 0x2f) /* ~ */ -#define ED_READ_FILE_END_OF_FILE (ED_GN | 0x30) /* ~ */ -#define ED_READ_FILE_ERROR (ED_GN | 0x31) /* ~ */ - -#define ED_DSP_CRASHED_EXC_DSPSTACK_OVERFLOW (ED_GN | 0x32) /* <- Decalage pour - * PCX (old 0x14) */ -#define ED_DSP_CRASHED_EXC_SYSSTACK_OVERFLOW (ED_GN | 0x33) /* ~ */ -#define ED_DSP_CRASHED_EXC_ILLEGAL (ED_GN | 0x34) /* ~ */ -#define ED_DSP_CRASHED_EXC_TIMER_REENTRY (ED_GN | 0x35) /* ~ */ -#define ED_DSP_CRASHED_EXC_FATAL_ERROR (ED_GN | 0x36) /* ~ */ - -#define ED_FLASH_PCCARD_NOT_PRESENT (ED_GN | 0x37) - -#define ED_NO_CURRENT_CLOCK (ED_GN | 0x38) - -/* Complete DRV error code for real time class */ -#define ED_RT (ERROR_VALUE | E_SOURCE_DRV | E_CLASS_REAL_TIME_ERROR) -#define ED_DSP_TIMED_OUT (ED_RT | 0x01) -#define ED_DSP_CHK_TIMED_OUT (ED_RT | 0x02) -#define ED_STREAM_OVERRUN (ED_RT | 0x03) -#define ED_DSP_BUSY (ED_RT | 0x04) -#define ED_DSP_SEMAPHORE_TIME_OUT (ED_RT | 0x05) -#define ED_BOARD_TIME_OUT (ED_RT | 0x06) -#define ED_XILINX_ERROR (ED_RT | 0x07) -#define ED_COBRANET_ITF_NOT_RESPONDING (ED_RT | 0x08) - -/* Complete BOARD error code for the invaid standard object class */ -#define EB_ISO (ERROR_VALUE | E_SOURCE_BOARD | \ - E_CLASS_INVALID_STD_OBJECT) -#define EB_INVALID_EFFECT (EB_ISO | 0x00) -#define EB_INVALID_PIPE (EB_ISO | 0x40) -#define EB_INVALID_STREAM (EB_ISO | 0x80) -#define EB_INVALID_AUDIO (EB_ISO | 0xC0) - -/* Complete BOARD error code for impossible resource allocation class */ -#define EB_RI (ERROR_VALUE | E_SOURCE_BOARD | E_CLASS_RSRC_IMPOSSIBLE) -#define EB_ALLOCATE_ALL_STREAM_TRANSFERT_BUFFERS_IMPOSSIBLE (EB_RI | 0x01) -#define EB_ALLOCATE_PIPE_SAMPLE_BUFFER_IMPOSSIBLE (EB_RI | 0x02) - -#define EB_ALLOCATE_MEM_STREAM_IMPOSSIBLE \ - EB_ALLOCATE_ALL_STREAM_TRANSFERT_BUFFERS_IMPOSSIBLE -#define EB_ALLOCATE_MEM_PIPE_IMPOSSIBLE \ - EB_ALLOCATE_PIPE_SAMPLE_BUFFER_IMPOSSIBLE - -#define EB_ALLOCATE_DIFFERED_CMD_IMPOSSIBLE (EB_RI | 0x03) -#define EB_TOO_MANY_DIFFERED_CMD (EB_RI | 0x04) -#define EB_RBUFFERS_TABLE_OVERFLOW (EB_RI | 0x05) -#define EB_ALLOCATE_EFFECTS_IMPOSSIBLE (EB_RI | 0x08) -#define EB_ALLOCATE_EFFECT_POS_IMPOSSIBLE (EB_RI | 0x09) -#define EB_RBUFFER_NOT_AVAILABLE (EB_RI | 0x0A) -#define EB_ALLOCATE_CONTEXT_LIII_IMPOSSIBLE (EB_RI | 0x0B) -#define EB_STATUS_DIALOG_IMPOSSIBLE (EB_RI | 0x1D) -#define EB_CONTROL_CMD_IMPOSSIBLE (EB_RI | 0x1E) -#define EB_STATUS_SEND_IMPOSSIBLE (EB_RI | 0x1F) -#define EB_ALLOCATE_PIPE_IMPOSSIBLE (EB_RI | 0x40) -#define EB_ALLOCATE_STREAM_IMPOSSIBLE (EB_RI | 0x80) -#define EB_ALLOCATE_AUDIO_IMPOSSIBLE (EB_RI | 0xC0) - -/* Complete BOARD error code for wrong call context class */ -#define EB_WCC (ERROR_VALUE | E_SOURCE_BOARD | E_CLASS_WRONG_CONTEXT) -#define EB_CMD_REFUSED (EB_WCC | 0x00) -#define EB_START_STREAM_REFUSED (EB_WCC | 0xFC) -#define EB_SPC_REFUSED (EB_WCC | 0xFD) -#define EB_CSN_REFUSED (EB_WCC | 0xFE) -#define EB_CSE_REFUSED (EB_WCC | 0xFF) - - - - -#endif /* LX_DEFS_H */ diff --git a/ANDROID_3.4.5/sound/pci/maestro3.c b/ANDROID_3.4.5/sound/pci/maestro3.c deleted file mode 100644 index 78229b0d..00000000 --- a/ANDROID_3.4.5/sound/pci/maestro3.c +++ /dev/null @@ -1,2862 +0,0 @@ -/* - * Driver for ESS Maestro3/Allegro (ES1988) soundcards. - * Copyright (c) 2000 by Zach Brown - * Takashi Iwai - * - * Most of the hardware init stuffs are based on maestro3 driver for - * OSS/Free by Zach Brown. Many thanks to Zach! - * - * 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 - * - * - * ChangeLog: - * Aug. 27, 2001 - * - Fixed deadlock on capture - * - Added Canyon3D-2 support by Rob Riggs - * - */ - -#define CARD_NAME "ESS Maestro3/Allegro/Canyon3D-2" -#define DRIVER_NAME "Maestro3" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Zach Brown , Takashi Iwai "); -MODULE_DESCRIPTION("ESS Maestro3 PCI"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESS,Maestro3 PCI}," - "{ESS,ES1988}," - "{ESS,Allegro PCI}," - "{ESS,Allegro-1 PCI}," - "{ESS,Canyon3D-2/LE PCI}}"); -MODULE_FIRMWARE("ess/maestro3_assp_kernel.fw"); -MODULE_FIRMWARE("ess/maestro3_assp_minisrc.fw"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* all enabled */ -static bool external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -static int amp_gpio[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable this soundcard."); -module_param_array(external_amp, bool, NULL, 0444); -MODULE_PARM_DESC(external_amp, "Enable external amp for " CARD_NAME " soundcard."); -module_param_array(amp_gpio, int, NULL, 0444); -MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)"); - -#define MAX_PLAYBACKS 2 -#define MAX_CAPTURES 1 -#define NR_DSPS (MAX_PLAYBACKS + MAX_CAPTURES) - - -/* - * maestro3 registers - */ - -/* Allegro PCI configuration registers */ -#define PCI_LEGACY_AUDIO_CTRL 0x40 -#define SOUND_BLASTER_ENABLE 0x00000001 -#define FM_SYNTHESIS_ENABLE 0x00000002 -#define GAME_PORT_ENABLE 0x00000004 -#define MPU401_IO_ENABLE 0x00000008 -#define MPU401_IRQ_ENABLE 0x00000010 -#define ALIAS_10BIT_IO 0x00000020 -#define SB_DMA_MASK 0x000000C0 -#define SB_DMA_0 0x00000040 -#define SB_DMA_1 0x00000040 -#define SB_DMA_R 0x00000080 -#define SB_DMA_3 0x000000C0 -#define SB_IRQ_MASK 0x00000700 -#define SB_IRQ_5 0x00000000 -#define SB_IRQ_7 0x00000100 -#define SB_IRQ_9 0x00000200 -#define SB_IRQ_10 0x00000300 -#define MIDI_IRQ_MASK 0x00003800 -#define SERIAL_IRQ_ENABLE 0x00004000 -#define DISABLE_LEGACY 0x00008000 - -#define PCI_ALLEGRO_CONFIG 0x50 -#define SB_ADDR_240 0x00000004 -#define MPU_ADDR_MASK 0x00000018 -#define MPU_ADDR_330 0x00000000 -#define MPU_ADDR_300 0x00000008 -#define MPU_ADDR_320 0x00000010 -#define MPU_ADDR_340 0x00000018 -#define USE_PCI_TIMING 0x00000040 -#define POSTED_WRITE_ENABLE 0x00000080 -#define DMA_POLICY_MASK 0x00000700 -#define DMA_DDMA 0x00000000 -#define DMA_TDMA 0x00000100 -#define DMA_PCPCI 0x00000200 -#define DMA_WBDMA16 0x00000400 -#define DMA_WBDMA4 0x00000500 -#define DMA_WBDMA2 0x00000600 -#define DMA_WBDMA1 0x00000700 -#define DMA_SAFE_GUARD 0x00000800 -#define HI_PERF_GP_ENABLE 0x00001000 -#define PIC_SNOOP_MODE_0 0x00002000 -#define PIC_SNOOP_MODE_1 0x00004000 -#define SOUNDBLASTER_IRQ_MASK 0x00008000 -#define RING_IN_ENABLE 0x00010000 -#define SPDIF_TEST_MODE 0x00020000 -#define CLK_MULT_MODE_SELECT_2 0x00040000 -#define EEPROM_WRITE_ENABLE 0x00080000 -#define CODEC_DIR_IN 0x00100000 -#define HV_BUTTON_FROM_GD 0x00200000 -#define REDUCED_DEBOUNCE 0x00400000 -#define HV_CTRL_ENABLE 0x00800000 -#define SPDIF_ENABLE 0x01000000 -#define CLK_DIV_SELECT 0x06000000 -#define CLK_DIV_BY_48 0x00000000 -#define CLK_DIV_BY_49 0x02000000 -#define CLK_DIV_BY_50 0x04000000 -#define CLK_DIV_RESERVED 0x06000000 -#define PM_CTRL_ENABLE 0x08000000 -#define CLK_MULT_MODE_SELECT 0x30000000 -#define CLK_MULT_MODE_SHIFT 28 -#define CLK_MULT_MODE_0 0x00000000 -#define CLK_MULT_MODE_1 0x10000000 -#define CLK_MULT_MODE_2 0x20000000 -#define CLK_MULT_MODE_3 0x30000000 -#define INT_CLK_SELECT 0x40000000 -#define INT_CLK_MULT_RESET 0x80000000 - -/* M3 */ -#define INT_CLK_SRC_NOT_PCI 0x00100000 -#define INT_CLK_MULT_ENABLE 0x80000000 - -#define PCI_ACPI_CONTROL 0x54 -#define PCI_ACPI_D0 0x00000000 -#define PCI_ACPI_D1 0xB4F70000 -#define PCI_ACPI_D2 0xB4F7B4F7 - -#define PCI_USER_CONFIG 0x58 -#define EXT_PCI_MASTER_ENABLE 0x00000001 -#define SPDIF_OUT_SELECT 0x00000002 -#define TEST_PIN_DIR_CTRL 0x00000004 -#define AC97_CODEC_TEST 0x00000020 -#define TRI_STATE_BUFFER 0x00000080 -#define IN_CLK_12MHZ_SELECT 0x00000100 -#define MULTI_FUNC_DISABLE 0x00000200 -#define EXT_MASTER_PAIR_SEL 0x00000400 -#define PCI_MASTER_SUPPORT 0x00000800 -#define STOP_CLOCK_ENABLE 0x00001000 -#define EAPD_DRIVE_ENABLE 0x00002000 -#define REQ_TRI_STATE_ENABLE 0x00004000 -#define REQ_LOW_ENABLE 0x00008000 -#define MIDI_1_ENABLE 0x00010000 -#define MIDI_2_ENABLE 0x00020000 -#define SB_AUDIO_SYNC 0x00040000 -#define HV_CTRL_TEST 0x00100000 -#define SOUNDBLASTER_TEST 0x00400000 - -#define PCI_USER_CONFIG_C 0x5C - -#define PCI_DDMA_CTRL 0x60 -#define DDMA_ENABLE 0x00000001 - - -/* Allegro registers */ -#define HOST_INT_CTRL 0x18 -#define SB_INT_ENABLE 0x0001 -#define MPU401_INT_ENABLE 0x0002 -#define ASSP_INT_ENABLE 0x0010 -#define RING_INT_ENABLE 0x0020 -#define HV_INT_ENABLE 0x0040 -#define CLKRUN_GEN_ENABLE 0x0100 -#define HV_CTRL_TO_PME 0x0400 -#define SOFTWARE_RESET_ENABLE 0x8000 - -/* - * should be using the above defines, probably. - */ -#define REGB_ENABLE_RESET 0x01 -#define REGB_STOP_CLOCK 0x10 - -#define HOST_INT_STATUS 0x1A -#define SB_INT_PENDING 0x01 -#define MPU401_INT_PENDING 0x02 -#define ASSP_INT_PENDING 0x10 -#define RING_INT_PENDING 0x20 -#define HV_INT_PENDING 0x40 - -#define HARDWARE_VOL_CTRL 0x1B -#define SHADOW_MIX_REG_VOICE 0x1C -#define HW_VOL_COUNTER_VOICE 0x1D -#define SHADOW_MIX_REG_MASTER 0x1E -#define HW_VOL_COUNTER_MASTER 0x1F - -#define CODEC_COMMAND 0x30 -#define CODEC_READ_B 0x80 - -#define CODEC_STATUS 0x30 -#define CODEC_BUSY_B 0x01 - -#define CODEC_DATA 0x32 - -#define RING_BUS_CTRL_A 0x36 -#define RAC_PME_ENABLE 0x0100 -#define RAC_SDFS_ENABLE 0x0200 -#define LAC_PME_ENABLE 0x0400 -#define LAC_SDFS_ENABLE 0x0800 -#define SERIAL_AC_LINK_ENABLE 0x1000 -#define IO_SRAM_ENABLE 0x2000 -#define IIS_INPUT_ENABLE 0x8000 - -#define RING_BUS_CTRL_B 0x38 -#define SECOND_CODEC_ID_MASK 0x0003 -#define SPDIF_FUNC_ENABLE 0x0010 -#define SECOND_AC_ENABLE 0x0020 -#define SB_MODULE_INTF_ENABLE 0x0040 -#define SSPE_ENABLE 0x0040 -#define M3I_DOCK_ENABLE 0x0080 - -#define SDO_OUT_DEST_CTRL 0x3A -#define COMMAND_ADDR_OUT 0x0003 -#define PCM_LR_OUT_LOCAL 0x0000 -#define PCM_LR_OUT_REMOTE 0x0004 -#define PCM_LR_OUT_MUTE 0x0008 -#define PCM_LR_OUT_BOTH 0x000C -#define LINE1_DAC_OUT_LOCAL 0x0000 -#define LINE1_DAC_OUT_REMOTE 0x0010 -#define LINE1_DAC_OUT_MUTE 0x0020 -#define LINE1_DAC_OUT_BOTH 0x0030 -#define PCM_CLS_OUT_LOCAL 0x0000 -#define PCM_CLS_OUT_REMOTE 0x0040 -#define PCM_CLS_OUT_MUTE 0x0080 -#define PCM_CLS_OUT_BOTH 0x00C0 -#define PCM_RLF_OUT_LOCAL 0x0000 -#define PCM_RLF_OUT_REMOTE 0x0100 -#define PCM_RLF_OUT_MUTE 0x0200 -#define PCM_RLF_OUT_BOTH 0x0300 -#define LINE2_DAC_OUT_LOCAL 0x0000 -#define LINE2_DAC_OUT_REMOTE 0x0400 -#define LINE2_DAC_OUT_MUTE 0x0800 -#define LINE2_DAC_OUT_BOTH 0x0C00 -#define HANDSET_OUT_LOCAL 0x0000 -#define HANDSET_OUT_REMOTE 0x1000 -#define HANDSET_OUT_MUTE 0x2000 -#define HANDSET_OUT_BOTH 0x3000 -#define IO_CTRL_OUT_LOCAL 0x0000 -#define IO_CTRL_OUT_REMOTE 0x4000 -#define IO_CTRL_OUT_MUTE 0x8000 -#define IO_CTRL_OUT_BOTH 0xC000 - -#define SDO_IN_DEST_CTRL 0x3C -#define STATUS_ADDR_IN 0x0003 -#define PCM_LR_IN_LOCAL 0x0000 -#define PCM_LR_IN_REMOTE 0x0004 -#define PCM_LR_RESERVED 0x0008 -#define PCM_LR_IN_BOTH 0x000C -#define LINE1_ADC_IN_LOCAL 0x0000 -#define LINE1_ADC_IN_REMOTE 0x0010 -#define LINE1_ADC_IN_MUTE 0x0020 -#define MIC_ADC_IN_LOCAL 0x0000 -#define MIC_ADC_IN_REMOTE 0x0040 -#define MIC_ADC_IN_MUTE 0x0080 -#define LINE2_DAC_IN_LOCAL 0x0000 -#define LINE2_DAC_IN_REMOTE 0x0400 -#define LINE2_DAC_IN_MUTE 0x0800 -#define HANDSET_IN_LOCAL 0x0000 -#define HANDSET_IN_REMOTE 0x1000 -#define HANDSET_IN_MUTE 0x2000 -#define IO_STATUS_IN_LOCAL 0x0000 -#define IO_STATUS_IN_REMOTE 0x4000 - -#define SPDIF_IN_CTRL 0x3E -#define SPDIF_IN_ENABLE 0x0001 - -#define GPIO_DATA 0x60 -#define GPIO_DATA_MASK 0x0FFF -#define GPIO_HV_STATUS 0x3000 -#define GPIO_PME_STATUS 0x4000 - -#define GPIO_MASK 0x64 -#define GPIO_DIRECTION 0x68 -#define GPO_PRIMARY_AC97 0x0001 -#define GPI_LINEOUT_SENSE 0x0004 -#define GPO_SECONDARY_AC97 0x0008 -#define GPI_VOL_DOWN 0x0010 -#define GPI_VOL_UP 0x0020 -#define GPI_IIS_CLK 0x0040 -#define GPI_IIS_LRCLK 0x0080 -#define GPI_IIS_DATA 0x0100 -#define GPI_DOCKING_STATUS 0x0100 -#define GPI_HEADPHONE_SENSE 0x0200 -#define GPO_EXT_AMP_SHUTDOWN 0x1000 - -#define GPO_EXT_AMP_M3 1 /* default m3 amp */ -#define GPO_EXT_AMP_ALLEGRO 8 /* default allegro amp */ - -/* M3 */ -#define GPO_M3_EXT_AMP_SHUTDN 0x0002 - -#define ASSP_INDEX_PORT 0x80 -#define ASSP_MEMORY_PORT 0x82 -#define ASSP_DATA_PORT 0x84 - -#define MPU401_DATA_PORT 0x98 -#define MPU401_STATUS_PORT 0x99 - -#define CLK_MULT_DATA_PORT 0x9C - -#define ASSP_CONTROL_A 0xA2 -#define ASSP_0_WS_ENABLE 0x01 -#define ASSP_CTRL_A_RESERVED1 0x02 -#define ASSP_CTRL_A_RESERVED2 0x04 -#define ASSP_CLK_49MHZ_SELECT 0x08 -#define FAST_PLU_ENABLE 0x10 -#define ASSP_CTRL_A_RESERVED3 0x20 -#define DSP_CLK_36MHZ_SELECT 0x40 - -#define ASSP_CONTROL_B 0xA4 -#define RESET_ASSP 0x00 -#define RUN_ASSP 0x01 -#define ENABLE_ASSP_CLOCK 0x00 -#define STOP_ASSP_CLOCK 0x10 -#define RESET_TOGGLE 0x40 - -#define ASSP_CONTROL_C 0xA6 -#define ASSP_HOST_INT_ENABLE 0x01 -#define FM_ADDR_REMAP_DISABLE 0x02 -#define HOST_WRITE_PORT_ENABLE 0x08 - -#define ASSP_HOST_INT_STATUS 0xAC -#define DSP2HOST_REQ_PIORECORD 0x01 -#define DSP2HOST_REQ_I2SRATE 0x02 -#define DSP2HOST_REQ_TIMER 0x04 - -/* AC97 registers */ -/* XXX fix this crap up */ -/*#define AC97_RESET 0x00*/ - -#define AC97_VOL_MUTE_B 0x8000 -#define AC97_VOL_M 0x1F -#define AC97_LEFT_VOL_S 8 - -#define AC97_MASTER_VOL 0x02 -#define AC97_LINE_LEVEL_VOL 0x04 -#define AC97_MASTER_MONO_VOL 0x06 -#define AC97_PC_BEEP_VOL 0x0A -#define AC97_PC_BEEP_VOL_M 0x0F -#define AC97_SROUND_MASTER_VOL 0x38 -#define AC97_PC_BEEP_VOL_S 1 - -/*#define AC97_PHONE_VOL 0x0C -#define AC97_MIC_VOL 0x0E*/ -#define AC97_MIC_20DB_ENABLE 0x40 - -/*#define AC97_LINEIN_VOL 0x10 -#define AC97_CD_VOL 0x12 -#define AC97_VIDEO_VOL 0x14 -#define AC97_AUX_VOL 0x16*/ -#define AC97_PCM_OUT_VOL 0x18 -/*#define AC97_RECORD_SELECT 0x1A*/ -#define AC97_RECORD_MIC 0x00 -#define AC97_RECORD_CD 0x01 -#define AC97_RECORD_VIDEO 0x02 -#define AC97_RECORD_AUX 0x03 -#define AC97_RECORD_MONO_MUX 0x02 -#define AC97_RECORD_DIGITAL 0x03 -#define AC97_RECORD_LINE 0x04 -#define AC97_RECORD_STEREO 0x05 -#define AC97_RECORD_MONO 0x06 -#define AC97_RECORD_PHONE 0x07 - -/*#define AC97_RECORD_GAIN 0x1C*/ -#define AC97_RECORD_VOL_M 0x0F - -/*#define AC97_GENERAL_PURPOSE 0x20*/ -#define AC97_POWER_DOWN_CTRL 0x26 -#define AC97_ADC_READY 0x0001 -#define AC97_DAC_READY 0x0002 -#define AC97_ANALOG_READY 0x0004 -#define AC97_VREF_ON 0x0008 -#define AC97_PR0 0x0100 -#define AC97_PR1 0x0200 -#define AC97_PR2 0x0400 -#define AC97_PR3 0x0800 -#define AC97_PR4 0x1000 - -#define AC97_RESERVED1 0x28 - -#define AC97_VENDOR_TEST 0x5A - -#define AC97_CLOCK_DELAY 0x5C -#define AC97_LINEOUT_MUX_SEL 0x0001 -#define AC97_MONO_MUX_SEL 0x0002 -#define AC97_CLOCK_DELAY_SEL 0x1F -#define AC97_DAC_CDS_SHIFT 6 -#define AC97_ADC_CDS_SHIFT 11 - -#define AC97_MULTI_CHANNEL_SEL 0x74 - -/*#define AC97_VENDOR_ID1 0x7C -#define AC97_VENDOR_ID2 0x7E*/ - -/* - * ASSP control regs - */ -#define DSP_PORT_TIMER_COUNT 0x06 - -#define DSP_PORT_MEMORY_INDEX 0x80 - -#define DSP_PORT_MEMORY_TYPE 0x82 -#define MEMTYPE_INTERNAL_CODE 0x0002 -#define MEMTYPE_INTERNAL_DATA 0x0003 -#define MEMTYPE_MASK 0x0003 - -#define DSP_PORT_MEMORY_DATA 0x84 - -#define DSP_PORT_CONTROL_REG_A 0xA2 -#define DSP_PORT_CONTROL_REG_B 0xA4 -#define DSP_PORT_CONTROL_REG_C 0xA6 - -#define REV_A_CODE_MEMORY_BEGIN 0x0000 -#define REV_A_CODE_MEMORY_END 0x0FFF -#define REV_A_CODE_MEMORY_UNIT_LENGTH 0x0040 -#define REV_A_CODE_MEMORY_LENGTH (REV_A_CODE_MEMORY_END - REV_A_CODE_MEMORY_BEGIN + 1) - -#define REV_B_CODE_MEMORY_BEGIN 0x0000 -#define REV_B_CODE_MEMORY_END 0x0BFF -#define REV_B_CODE_MEMORY_UNIT_LENGTH 0x0040 -#define REV_B_CODE_MEMORY_LENGTH (REV_B_CODE_MEMORY_END - REV_B_CODE_MEMORY_BEGIN + 1) - -#define REV_A_DATA_MEMORY_BEGIN 0x1000 -#define REV_A_DATA_MEMORY_END 0x2FFF -#define REV_A_DATA_MEMORY_UNIT_LENGTH 0x0080 -#define REV_A_DATA_MEMORY_LENGTH (REV_A_DATA_MEMORY_END - REV_A_DATA_MEMORY_BEGIN + 1) - -#define REV_B_DATA_MEMORY_BEGIN 0x1000 -#define REV_B_DATA_MEMORY_END 0x2BFF -#define REV_B_DATA_MEMORY_UNIT_LENGTH 0x0080 -#define REV_B_DATA_MEMORY_LENGTH (REV_B_DATA_MEMORY_END - REV_B_DATA_MEMORY_BEGIN + 1) - - -#define NUM_UNITS_KERNEL_CODE 16 -#define NUM_UNITS_KERNEL_DATA 2 - -#define NUM_UNITS_KERNEL_CODE_WITH_HSP 16 -#define NUM_UNITS_KERNEL_DATA_WITH_HSP 5 - -/* - * Kernel data layout - */ - -#define DP_SHIFT_COUNT 7 - -#define KDATA_BASE_ADDR 0x1000 -#define KDATA_BASE_ADDR2 0x1080 - -#define KDATA_TASK0 (KDATA_BASE_ADDR + 0x0000) -#define KDATA_TASK1 (KDATA_BASE_ADDR + 0x0001) -#define KDATA_TASK2 (KDATA_BASE_ADDR + 0x0002) -#define KDATA_TASK3 (KDATA_BASE_ADDR + 0x0003) -#define KDATA_TASK4 (KDATA_BASE_ADDR + 0x0004) -#define KDATA_TASK5 (KDATA_BASE_ADDR + 0x0005) -#define KDATA_TASK6 (KDATA_BASE_ADDR + 0x0006) -#define KDATA_TASK7 (KDATA_BASE_ADDR + 0x0007) -#define KDATA_TASK_ENDMARK (KDATA_BASE_ADDR + 0x0008) - -#define KDATA_CURRENT_TASK (KDATA_BASE_ADDR + 0x0009) -#define KDATA_TASK_SWITCH (KDATA_BASE_ADDR + 0x000A) - -#define KDATA_INSTANCE0_POS3D (KDATA_BASE_ADDR + 0x000B) -#define KDATA_INSTANCE1_POS3D (KDATA_BASE_ADDR + 0x000C) -#define KDATA_INSTANCE2_POS3D (KDATA_BASE_ADDR + 0x000D) -#define KDATA_INSTANCE3_POS3D (KDATA_BASE_ADDR + 0x000E) -#define KDATA_INSTANCE4_POS3D (KDATA_BASE_ADDR + 0x000F) -#define KDATA_INSTANCE5_POS3D (KDATA_BASE_ADDR + 0x0010) -#define KDATA_INSTANCE6_POS3D (KDATA_BASE_ADDR + 0x0011) -#define KDATA_INSTANCE7_POS3D (KDATA_BASE_ADDR + 0x0012) -#define KDATA_INSTANCE8_POS3D (KDATA_BASE_ADDR + 0x0013) -#define KDATA_INSTANCE_POS3D_ENDMARK (KDATA_BASE_ADDR + 0x0014) - -#define KDATA_INSTANCE0_SPKVIRT (KDATA_BASE_ADDR + 0x0015) -#define KDATA_INSTANCE_SPKVIRT_ENDMARK (KDATA_BASE_ADDR + 0x0016) - -#define KDATA_INSTANCE0_SPDIF (KDATA_BASE_ADDR + 0x0017) -#define KDATA_INSTANCE_SPDIF_ENDMARK (KDATA_BASE_ADDR + 0x0018) - -#define KDATA_INSTANCE0_MODEM (KDATA_BASE_ADDR + 0x0019) -#define KDATA_INSTANCE_MODEM_ENDMARK (KDATA_BASE_ADDR + 0x001A) - -#define KDATA_INSTANCE0_SRC (KDATA_BASE_ADDR + 0x001B) -#define KDATA_INSTANCE1_SRC (KDATA_BASE_ADDR + 0x001C) -#define KDATA_INSTANCE_SRC_ENDMARK (KDATA_BASE_ADDR + 0x001D) - -#define KDATA_INSTANCE0_MINISRC (KDATA_BASE_ADDR + 0x001E) -#define KDATA_INSTANCE1_MINISRC (KDATA_BASE_ADDR + 0x001F) -#define KDATA_INSTANCE2_MINISRC (KDATA_BASE_ADDR + 0x0020) -#define KDATA_INSTANCE3_MINISRC (KDATA_BASE_ADDR + 0x0021) -#define KDATA_INSTANCE_MINISRC_ENDMARK (KDATA_BASE_ADDR + 0x0022) - -#define KDATA_INSTANCE0_CPYTHRU (KDATA_BASE_ADDR + 0x0023) -#define KDATA_INSTANCE1_CPYTHRU (KDATA_BASE_ADDR + 0x0024) -#define KDATA_INSTANCE_CPYTHRU_ENDMARK (KDATA_BASE_ADDR + 0x0025) - -#define KDATA_CURRENT_DMA (KDATA_BASE_ADDR + 0x0026) -#define KDATA_DMA_SWITCH (KDATA_BASE_ADDR + 0x0027) -#define KDATA_DMA_ACTIVE (KDATA_BASE_ADDR + 0x0028) - -#define KDATA_DMA_XFER0 (KDATA_BASE_ADDR + 0x0029) -#define KDATA_DMA_XFER1 (KDATA_BASE_ADDR + 0x002A) -#define KDATA_DMA_XFER2 (KDATA_BASE_ADDR + 0x002B) -#define KDATA_DMA_XFER3 (KDATA_BASE_ADDR + 0x002C) -#define KDATA_DMA_XFER4 (KDATA_BASE_ADDR + 0x002D) -#define KDATA_DMA_XFER5 (KDATA_BASE_ADDR + 0x002E) -#define KDATA_DMA_XFER6 (KDATA_BASE_ADDR + 0x002F) -#define KDATA_DMA_XFER7 (KDATA_BASE_ADDR + 0x0030) -#define KDATA_DMA_XFER8 (KDATA_BASE_ADDR + 0x0031) -#define KDATA_DMA_XFER_ENDMARK (KDATA_BASE_ADDR + 0x0032) - -#define KDATA_I2S_SAMPLE_COUNT (KDATA_BASE_ADDR + 0x0033) -#define KDATA_I2S_INT_METER (KDATA_BASE_ADDR + 0x0034) -#define KDATA_I2S_ACTIVE (KDATA_BASE_ADDR + 0x0035) - -#define KDATA_TIMER_COUNT_RELOAD (KDATA_BASE_ADDR + 0x0036) -#define KDATA_TIMER_COUNT_CURRENT (KDATA_BASE_ADDR + 0x0037) - -#define KDATA_HALT_SYNCH_CLIENT (KDATA_BASE_ADDR + 0x0038) -#define KDATA_HALT_SYNCH_DMA (KDATA_BASE_ADDR + 0x0039) -#define KDATA_HALT_ACKNOWLEDGE (KDATA_BASE_ADDR + 0x003A) - -#define KDATA_ADC1_XFER0 (KDATA_BASE_ADDR + 0x003B) -#define KDATA_ADC1_XFER_ENDMARK (KDATA_BASE_ADDR + 0x003C) -#define KDATA_ADC1_LEFT_VOLUME (KDATA_BASE_ADDR + 0x003D) -#define KDATA_ADC1_RIGHT_VOLUME (KDATA_BASE_ADDR + 0x003E) -#define KDATA_ADC1_LEFT_SUR_VOL (KDATA_BASE_ADDR + 0x003F) -#define KDATA_ADC1_RIGHT_SUR_VOL (KDATA_BASE_ADDR + 0x0040) - -#define KDATA_ADC2_XFER0 (KDATA_BASE_ADDR + 0x0041) -#define KDATA_ADC2_XFER_ENDMARK (KDATA_BASE_ADDR + 0x0042) -#define KDATA_ADC2_LEFT_VOLUME (KDATA_BASE_ADDR + 0x0043) -#define KDATA_ADC2_RIGHT_VOLUME (KDATA_BASE_ADDR + 0x0044) -#define KDATA_ADC2_LEFT_SUR_VOL (KDATA_BASE_ADDR + 0x0045) -#define KDATA_ADC2_RIGHT_SUR_VOL (KDATA_BASE_ADDR + 0x0046) - -#define KDATA_CD_XFER0 (KDATA_BASE_ADDR + 0x0047) -#define KDATA_CD_XFER_ENDMARK (KDATA_BASE_ADDR + 0x0048) -#define KDATA_CD_LEFT_VOLUME (KDATA_BASE_ADDR + 0x0049) -#define KDATA_CD_RIGHT_VOLUME (KDATA_BASE_ADDR + 0x004A) -#define KDATA_CD_LEFT_SUR_VOL (KDATA_BASE_ADDR + 0x004B) -#define KDATA_CD_RIGHT_SUR_VOL (KDATA_BASE_ADDR + 0x004C) - -#define KDATA_MIC_XFER0 (KDATA_BASE_ADDR + 0x004D) -#define KDATA_MIC_XFER_ENDMARK (KDATA_BASE_ADDR + 0x004E) -#define KDATA_MIC_VOLUME (KDATA_BASE_ADDR + 0x004F) -#define KDATA_MIC_SUR_VOL (KDATA_BASE_ADDR + 0x0050) - -#define KDATA_I2S_XFER0 (KDATA_BASE_ADDR + 0x0051) -#define KDATA_I2S_XFER_ENDMARK (KDATA_BASE_ADDR + 0x0052) - -#define KDATA_CHI_XFER0 (KDATA_BASE_ADDR + 0x0053) -#define KDATA_CHI_XFER_ENDMARK (KDATA_BASE_ADDR + 0x0054) - -#define KDATA_SPDIF_XFER (KDATA_BASE_ADDR + 0x0055) -#define KDATA_SPDIF_CURRENT_FRAME (KDATA_BASE_ADDR + 0x0056) -#define KDATA_SPDIF_FRAME0 (KDATA_BASE_ADDR + 0x0057) -#define KDATA_SPDIF_FRAME1 (KDATA_BASE_ADDR + 0x0058) -#define KDATA_SPDIF_FRAME2 (KDATA_BASE_ADDR + 0x0059) - -#define KDATA_SPDIF_REQUEST (KDATA_BASE_ADDR + 0x005A) -#define KDATA_SPDIF_TEMP (KDATA_BASE_ADDR + 0x005B) - -#define KDATA_SPDIFIN_XFER0 (KDATA_BASE_ADDR + 0x005C) -#define KDATA_SPDIFIN_XFER_ENDMARK (KDATA_BASE_ADDR + 0x005D) -#define KDATA_SPDIFIN_INT_METER (KDATA_BASE_ADDR + 0x005E) - -#define KDATA_DSP_RESET_COUNT (KDATA_BASE_ADDR + 0x005F) -#define KDATA_DEBUG_OUTPUT (KDATA_BASE_ADDR + 0x0060) - -#define KDATA_KERNEL_ISR_LIST (KDATA_BASE_ADDR + 0x0061) - -#define KDATA_KERNEL_ISR_CBSR1 (KDATA_BASE_ADDR + 0x0062) -#define KDATA_KERNEL_ISR_CBER1 (KDATA_BASE_ADDR + 0x0063) -#define KDATA_KERNEL_ISR_CBCR (KDATA_BASE_ADDR + 0x0064) -#define KDATA_KERNEL_ISR_AR0 (KDATA_BASE_ADDR + 0x0065) -#define KDATA_KERNEL_ISR_AR1 (KDATA_BASE_ADDR + 0x0066) -#define KDATA_KERNEL_ISR_AR2 (KDATA_BASE_ADDR + 0x0067) -#define KDATA_KERNEL_ISR_AR3 (KDATA_BASE_ADDR + 0x0068) -#define KDATA_KERNEL_ISR_AR4 (KDATA_BASE_ADDR + 0x0069) -#define KDATA_KERNEL_ISR_AR5 (KDATA_BASE_ADDR + 0x006A) -#define KDATA_KERNEL_ISR_BRCR (KDATA_BASE_ADDR + 0x006B) -#define KDATA_KERNEL_ISR_PASR (KDATA_BASE_ADDR + 0x006C) -#define KDATA_KERNEL_ISR_PAER (KDATA_BASE_ADDR + 0x006D) - -#define KDATA_CLIENT_SCRATCH0 (KDATA_BASE_ADDR + 0x006E) -#define KDATA_CLIENT_SCRATCH1 (KDATA_BASE_ADDR + 0x006F) -#define KDATA_KERNEL_SCRATCH (KDATA_BASE_ADDR + 0x0070) -#define KDATA_KERNEL_ISR_SCRATCH (KDATA_BASE_ADDR + 0x0071) - -#define KDATA_OUEUE_LEFT (KDATA_BASE_ADDR + 0x0072) -#define KDATA_QUEUE_RIGHT (KDATA_BASE_ADDR + 0x0073) - -#define KDATA_ADC1_REQUEST (KDATA_BASE_ADDR + 0x0074) -#define KDATA_ADC2_REQUEST (KDATA_BASE_ADDR + 0x0075) -#define KDATA_CD_REQUEST (KDATA_BASE_ADDR + 0x0076) -#define KDATA_MIC_REQUEST (KDATA_BASE_ADDR + 0x0077) - -#define KDATA_ADC1_MIXER_REQUEST (KDATA_BASE_ADDR + 0x0078) -#define KDATA_ADC2_MIXER_REQUEST (KDATA_BASE_ADDR + 0x0079) -#define KDATA_CD_MIXER_REQUEST (KDATA_BASE_ADDR + 0x007A) -#define KDATA_MIC_MIXER_REQUEST (KDATA_BASE_ADDR + 0x007B) -#define KDATA_MIC_SYNC_COUNTER (KDATA_BASE_ADDR + 0x007C) - -/* - * second 'segment' (?) reserved for mixer - * buffers.. - */ - -#define KDATA_MIXER_WORD0 (KDATA_BASE_ADDR2 + 0x0000) -#define KDATA_MIXER_WORD1 (KDATA_BASE_ADDR2 + 0x0001) -#define KDATA_MIXER_WORD2 (KDATA_BASE_ADDR2 + 0x0002) -#define KDATA_MIXER_WORD3 (KDATA_BASE_ADDR2 + 0x0003) -#define KDATA_MIXER_WORD4 (KDATA_BASE_ADDR2 + 0x0004) -#define KDATA_MIXER_WORD5 (KDATA_BASE_ADDR2 + 0x0005) -#define KDATA_MIXER_WORD6 (KDATA_BASE_ADDR2 + 0x0006) -#define KDATA_MIXER_WORD7 (KDATA_BASE_ADDR2 + 0x0007) -#define KDATA_MIXER_WORD8 (KDATA_BASE_ADDR2 + 0x0008) -#define KDATA_MIXER_WORD9 (KDATA_BASE_ADDR2 + 0x0009) -#define KDATA_MIXER_WORDA (KDATA_BASE_ADDR2 + 0x000A) -#define KDATA_MIXER_WORDB (KDATA_BASE_ADDR2 + 0x000B) -#define KDATA_MIXER_WORDC (KDATA_BASE_ADDR2 + 0x000C) -#define KDATA_MIXER_WORDD (KDATA_BASE_ADDR2 + 0x000D) -#define KDATA_MIXER_WORDE (KDATA_BASE_ADDR2 + 0x000E) -#define KDATA_MIXER_WORDF (KDATA_BASE_ADDR2 + 0x000F) - -#define KDATA_MIXER_XFER0 (KDATA_BASE_ADDR2 + 0x0010) -#define KDATA_MIXER_XFER1 (KDATA_BASE_ADDR2 + 0x0011) -#define KDATA_MIXER_XFER2 (KDATA_BASE_ADDR2 + 0x0012) -#define KDATA_MIXER_XFER3 (KDATA_BASE_ADDR2 + 0x0013) -#define KDATA_MIXER_XFER4 (KDATA_BASE_ADDR2 + 0x0014) -#define KDATA_MIXER_XFER5 (KDATA_BASE_ADDR2 + 0x0015) -#define KDATA_MIXER_XFER6 (KDATA_BASE_ADDR2 + 0x0016) -#define KDATA_MIXER_XFER7 (KDATA_BASE_ADDR2 + 0x0017) -#define KDATA_MIXER_XFER8 (KDATA_BASE_ADDR2 + 0x0018) -#define KDATA_MIXER_XFER9 (KDATA_BASE_ADDR2 + 0x0019) -#define KDATA_MIXER_XFER_ENDMARK (KDATA_BASE_ADDR2 + 0x001A) - -#define KDATA_MIXER_TASK_NUMBER (KDATA_BASE_ADDR2 + 0x001B) -#define KDATA_CURRENT_MIXER (KDATA_BASE_ADDR2 + 0x001C) -#define KDATA_MIXER_ACTIVE (KDATA_BASE_ADDR2 + 0x001D) -#define KDATA_MIXER_BANK_STATUS (KDATA_BASE_ADDR2 + 0x001E) -#define KDATA_DAC_LEFT_VOLUME (KDATA_BASE_ADDR2 + 0x001F) -#define KDATA_DAC_RIGHT_VOLUME (KDATA_BASE_ADDR2 + 0x0020) - -#define MAX_INSTANCE_MINISRC (KDATA_INSTANCE_MINISRC_ENDMARK - KDATA_INSTANCE0_MINISRC) -#define MAX_VIRTUAL_DMA_CHANNELS (KDATA_DMA_XFER_ENDMARK - KDATA_DMA_XFER0) -#define MAX_VIRTUAL_MIXER_CHANNELS (KDATA_MIXER_XFER_ENDMARK - KDATA_MIXER_XFER0) -#define MAX_VIRTUAL_ADC1_CHANNELS (KDATA_ADC1_XFER_ENDMARK - KDATA_ADC1_XFER0) - -/* - * client data area offsets - */ -#define CDATA_INSTANCE_READY 0x00 - -#define CDATA_HOST_SRC_ADDRL 0x01 -#define CDATA_HOST_SRC_ADDRH 0x02 -#define CDATA_HOST_SRC_END_PLUS_1L 0x03 -#define CDATA_HOST_SRC_END_PLUS_1H 0x04 -#define CDATA_HOST_SRC_CURRENTL 0x05 -#define CDATA_HOST_SRC_CURRENTH 0x06 - -#define CDATA_IN_BUF_CONNECT 0x07 -#define CDATA_OUT_BUF_CONNECT 0x08 - -#define CDATA_IN_BUF_BEGIN 0x09 -#define CDATA_IN_BUF_END_PLUS_1 0x0A -#define CDATA_IN_BUF_HEAD 0x0B -#define CDATA_IN_BUF_TAIL 0x0C -#define CDATA_OUT_BUF_BEGIN 0x0D -#define CDATA_OUT_BUF_END_PLUS_1 0x0E -#define CDATA_OUT_BUF_HEAD 0x0F -#define CDATA_OUT_BUF_TAIL 0x10 - -#define CDATA_DMA_CONTROL 0x11 -#define CDATA_RESERVED 0x12 - -#define CDATA_FREQUENCY 0x13 -#define CDATA_LEFT_VOLUME 0x14 -#define CDATA_RIGHT_VOLUME 0x15 -#define CDATA_LEFT_SUR_VOL 0x16 -#define CDATA_RIGHT_SUR_VOL 0x17 - -#define CDATA_HEADER_LEN 0x18 - -#define SRC3_DIRECTION_OFFSET CDATA_HEADER_LEN -#define SRC3_MODE_OFFSET (CDATA_HEADER_LEN + 1) -#define SRC3_WORD_LENGTH_OFFSET (CDATA_HEADER_LEN + 2) -#define SRC3_PARAMETER_OFFSET (CDATA_HEADER_LEN + 3) -#define SRC3_COEFF_ADDR_OFFSET (CDATA_HEADER_LEN + 8) -#define SRC3_FILTAP_ADDR_OFFSET (CDATA_HEADER_LEN + 10) -#define SRC3_TEMP_INBUF_ADDR_OFFSET (CDATA_HEADER_LEN + 16) -#define SRC3_TEMP_OUTBUF_ADDR_OFFSET (CDATA_HEADER_LEN + 17) - -#define MINISRC_IN_BUFFER_SIZE ( 0x50 * 2 ) -#define MINISRC_OUT_BUFFER_SIZE ( 0x50 * 2 * 2) -#define MINISRC_TMP_BUFFER_SIZE ( 112 + ( MINISRC_BIQUAD_STAGE * 3 + 4 ) * 2 * 2 ) -#define MINISRC_BIQUAD_STAGE 2 -#define MINISRC_COEF_LOC 0x175 - -#define DMACONTROL_BLOCK_MASK 0x000F -#define DMAC_BLOCK0_SELECTOR 0x0000 -#define DMAC_BLOCK1_SELECTOR 0x0001 -#define DMAC_BLOCK2_SELECTOR 0x0002 -#define DMAC_BLOCK3_SELECTOR 0x0003 -#define DMAC_BLOCK4_SELECTOR 0x0004 -#define DMAC_BLOCK5_SELECTOR 0x0005 -#define DMAC_BLOCK6_SELECTOR 0x0006 -#define DMAC_BLOCK7_SELECTOR 0x0007 -#define DMAC_BLOCK8_SELECTOR 0x0008 -#define DMAC_BLOCK9_SELECTOR 0x0009 -#define DMAC_BLOCKA_SELECTOR 0x000A -#define DMAC_BLOCKB_SELECTOR 0x000B -#define DMAC_BLOCKC_SELECTOR 0x000C -#define DMAC_BLOCKD_SELECTOR 0x000D -#define DMAC_BLOCKE_SELECTOR 0x000E -#define DMAC_BLOCKF_SELECTOR 0x000F -#define DMACONTROL_PAGE_MASK 0x00F0 -#define DMAC_PAGE0_SELECTOR 0x0030 -#define DMAC_PAGE1_SELECTOR 0x0020 -#define DMAC_PAGE2_SELECTOR 0x0010 -#define DMAC_PAGE3_SELECTOR 0x0000 -#define DMACONTROL_AUTOREPEAT 0x1000 -#define DMACONTROL_STOPPED 0x2000 -#define DMACONTROL_DIRECTION 0x0100 - -/* - * an arbitrary volume we set the internal - * volume settings to so that the ac97 volume - * range is a little less insane. 0x7fff is - * max. - */ -#define ARB_VOLUME ( 0x6800 ) - -/* - */ - -struct m3_list { - int curlen; - int mem_addr; - int max; -}; - -struct m3_dma { - - int number; - struct snd_pcm_substream *substream; - - struct assp_instance { - unsigned short code, data; - } inst; - - int running; - int opened; - - unsigned long buffer_addr; - int dma_size; - int period_size; - unsigned int hwptr; - int count; - - int index[3]; - struct m3_list *index_list[3]; - - int in_lists; - - struct list_head list; - -}; - -struct snd_m3 { - - struct snd_card *card; - - unsigned long iobase; - - int irq; - unsigned int allegro_flag : 1; - - struct snd_ac97 *ac97; - - struct snd_pcm *pcm; - - struct pci_dev *pci; - - int dacs_active; - int timer_users; - - struct m3_list msrc_list; - struct m3_list mixer_list; - struct m3_list adc1_list; - struct m3_list dma_list; - - /* for storing reset state..*/ - u8 reset_state; - - int external_amp; - int amp_gpio; /* gpio pin # for external amp, -1 = default */ - unsigned int hv_config; /* hardware-volume config bits */ - unsigned irda_workaround :1; /* avoid to touch 0x10 on GPIO_DIRECTION - (e.g. for IrDA on Dell Inspirons) */ - unsigned is_omnibook :1; /* Do HP OmniBook GPIO magic? */ - - /* midi */ - struct snd_rawmidi *rmidi; - - /* pcm streams */ - int num_substreams; - struct m3_dma *substreams; - - spinlock_t reg_lock; - -#ifdef CONFIG_SND_MAESTRO3_INPUT - struct input_dev *input_dev; - char phys[64]; /* physical device path */ -#else - struct snd_kcontrol *master_switch; - struct snd_kcontrol *master_volume; -#endif - struct work_struct hwvol_work; - - unsigned int in_suspend; - -#ifdef CONFIG_PM - u16 *suspend_mem; -#endif - - const struct firmware *assp_kernel_image; - const struct firmware *assp_minisrc_image; -}; - -/* - * pci ids - */ -static DEFINE_PCI_DEVICE_TABLE(snd_m3_ids) = { - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2LE, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_1, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_HW, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_2, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, snd_m3_ids); - -static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = { - SND_PCI_QUIRK(0x0E11, 0x0094, "Compaq Evo N600c", 0x0c), - SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d), - SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d), - SND_PCI_QUIRK(0x1033, 0x80f1, "NEC LM800J/7", 0x03), - SND_PCI_QUIRK(0x1509, 0x1740, "LEGEND ZhaoYang 3100CF", 0x03), - { } /* END */ -}; - -static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = { - SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1), - SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1), - SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1), - { } /* END */ -}; - -/* hardware volume quirks */ -static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = { - /* Allegro chips */ - SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x0E11, 0xB112, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x0E11, 0xB114, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x103C, 0x0012, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x103C, 0x0018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x103C, 0x001C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x103C, 0x001D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x103C, 0x001E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x107B, 0x3350, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x10F7, 0x8338, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x10F7, 0x833C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x10F7, 0x833D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x10F7, 0x833E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x10F7, 0x833F, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x13BD, 0x1018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x13BD, 0x1019, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x13BD, 0x101A, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x14FF, 0x0F03, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x14FF, 0x0F04, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x14FF, 0x0F05, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x156D, 0xB400, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x156D, 0xB795, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x156D, 0xB797, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x156D, 0xC700, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD), - SND_PCI_QUIRK(0x1033, 0x80F1, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x103C, 0x001A, NULL, /* HP OmniBook 6100 */ - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x107B, 0x340A, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x107B, 0x3450, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x109F, 0x3134, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x109F, 0x3161, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x144D, 0x3280, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x144D, 0x3281, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x144D, 0xC002, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x144D, 0xC003, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x1509, 0x1740, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x1610, 0x0010, NULL, - HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x1042, 0x1042, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x107B, 0x9500, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x14FF, 0x0F06, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x1558, 0x8586, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x161F, 0x2011, NULL, HV_CTRL_ENABLE), - /* Maestro3 chips */ - SND_PCI_QUIRK(0x103C, 0x000E, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x103C, 0x0010, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x103C, 0x0011, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x103C, 0x001B, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x104D, 0x80A6, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x104D, 0x80AA, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x107B, 0x5300, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x110A, 0x1998, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x13BD, 0x1015, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x13BD, 0x101C, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x13BD, 0x1802, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x1599, 0x0715, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x5643, 0x5643, NULL, HV_CTRL_ENABLE), - SND_PCI_QUIRK(0x144D, 0x3260, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x144D, 0x3261, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x144D, 0xC000, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE), - SND_PCI_QUIRK(0x144D, 0xC001, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE), - { } /* END */ -}; - -/* HP Omnibook quirks */ -static struct snd_pci_quirk m3_omnibook_quirk_list[] __devinitdata = { - SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */ - SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */ - { } /* END */ -}; - -/* - * lowlevel functions - */ - -static inline void snd_m3_outw(struct snd_m3 *chip, u16 value, unsigned long reg) -{ - outw(value, chip->iobase + reg); -} - -static inline u16 snd_m3_inw(struct snd_m3 *chip, unsigned long reg) -{ - return inw(chip->iobase + reg); -} - -static inline void snd_m3_outb(struct snd_m3 *chip, u8 value, unsigned long reg) -{ - outb(value, chip->iobase + reg); -} - -static inline u8 snd_m3_inb(struct snd_m3 *chip, unsigned long reg) -{ - return inb(chip->iobase + reg); -} - -/* - * access 16bit words to the code or data regions of the dsp's memory. - * index addresses 16bit words. - */ -static u16 snd_m3_assp_read(struct snd_m3 *chip, u16 region, u16 index) -{ - snd_m3_outw(chip, region & MEMTYPE_MASK, DSP_PORT_MEMORY_TYPE); - snd_m3_outw(chip, index, DSP_PORT_MEMORY_INDEX); - return snd_m3_inw(chip, DSP_PORT_MEMORY_DATA); -} - -static void snd_m3_assp_write(struct snd_m3 *chip, u16 region, u16 index, u16 data) -{ - snd_m3_outw(chip, region & MEMTYPE_MASK, DSP_PORT_MEMORY_TYPE); - snd_m3_outw(chip, index, DSP_PORT_MEMORY_INDEX); - snd_m3_outw(chip, data, DSP_PORT_MEMORY_DATA); -} - -static void snd_m3_assp_halt(struct snd_m3 *chip) -{ - chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK; - msleep(10); - snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B); -} - -static void snd_m3_assp_continue(struct snd_m3 *chip) -{ - snd_m3_outb(chip, chip->reset_state | REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B); -} - - -/* - * This makes me sad. the maestro3 has lists - * internally that must be packed.. 0 terminates, - * apparently, or maybe all unused entries have - * to be 0, the lists have static lengths set - * by the binary code images. - */ - -static int snd_m3_add_list(struct snd_m3 *chip, struct m3_list *list, u16 val) -{ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - list->mem_addr + list->curlen, - val); - return list->curlen++; -} - -static void snd_m3_remove_list(struct snd_m3 *chip, struct m3_list *list, int index) -{ - u16 val; - int lastindex = list->curlen - 1; - - if (index != lastindex) { - val = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, - list->mem_addr + lastindex); - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - list->mem_addr + index, - val); - } - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - list->mem_addr + lastindex, - 0); - - list->curlen--; -} - -static void snd_m3_inc_timer_users(struct snd_m3 *chip) -{ - chip->timer_users++; - if (chip->timer_users != 1) - return; - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_TIMER_COUNT_RELOAD, - 240); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_TIMER_COUNT_CURRENT, - 240); - - snd_m3_outw(chip, - snd_m3_inw(chip, HOST_INT_CTRL) | CLKRUN_GEN_ENABLE, - HOST_INT_CTRL); -} - -static void snd_m3_dec_timer_users(struct snd_m3 *chip) -{ - chip->timer_users--; - if (chip->timer_users > 0) - return; - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_TIMER_COUNT_RELOAD, - 0); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_TIMER_COUNT_CURRENT, - 0); - - snd_m3_outw(chip, - snd_m3_inw(chip, HOST_INT_CTRL) & ~CLKRUN_GEN_ENABLE, - HOST_INT_CTRL); -} - -/* - * start/stop - */ - -/* spinlock held! */ -static int snd_m3_pcm_start(struct snd_m3 *chip, struct m3_dma *s, - struct snd_pcm_substream *subs) -{ - if (! s || ! subs) - return -EINVAL; - - snd_m3_inc_timer_users(chip); - switch (subs->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - chip->dacs_active++; - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_INSTANCE_READY, 1); - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_MIXER_TASK_NUMBER, - chip->dacs_active); - break; - case SNDRV_PCM_STREAM_CAPTURE: - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_ADC1_REQUEST, 1); - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_INSTANCE_READY, 1); - break; - } - return 0; -} - -/* spinlock held! */ -static int snd_m3_pcm_stop(struct snd_m3 *chip, struct m3_dma *s, - struct snd_pcm_substream *subs) -{ - if (! s || ! subs) - return -EINVAL; - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_INSTANCE_READY, 0); - snd_m3_dec_timer_users(chip); - switch (subs->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - chip->dacs_active--; - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_MIXER_TASK_NUMBER, - chip->dacs_active); - break; - case SNDRV_PCM_STREAM_CAPTURE: - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_ADC1_REQUEST, 0); - break; - } - return 0; -} - -static int -snd_m3_pcm_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct snd_m3 *chip = snd_pcm_substream_chip(subs); - struct m3_dma *s = subs->runtime->private_data; - int err = -EINVAL; - - if (snd_BUG_ON(!s)) - return -ENXIO; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (s->running) - err = -EBUSY; - else { - s->running = 1; - err = snd_m3_pcm_start(chip, s, subs); - } - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (! s->running) - err = 0; /* should return error? */ - else { - s->running = 0; - err = snd_m3_pcm_stop(chip, s, subs); - } - break; - } - spin_unlock(&chip->reg_lock); - return err; -} - -/* - * setup - */ -static void -snd_m3_pcm_setup1(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs) -{ - int dsp_in_size, dsp_out_size, dsp_in_buffer, dsp_out_buffer; - struct snd_pcm_runtime *runtime = subs->runtime; - - if (subs->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2); - dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2); - } else { - dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x10 * 2); - dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2); - } - dsp_in_buffer = s->inst.data + (MINISRC_TMP_BUFFER_SIZE / 2); - dsp_out_buffer = dsp_in_buffer + (dsp_in_size / 2) + 1; - - s->dma_size = frames_to_bytes(runtime, runtime->buffer_size); - s->period_size = frames_to_bytes(runtime, runtime->period_size); - s->hwptr = 0; - s->count = 0; - -#define LO(x) ((x) & 0xffff) -#define HI(x) LO((x) >> 16) - - /* host dma buffer pointers */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_ADDRL, - LO(s->buffer_addr)); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_ADDRH, - HI(s->buffer_addr)); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_END_PLUS_1L, - LO(s->buffer_addr + s->dma_size)); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_END_PLUS_1H, - HI(s->buffer_addr + s->dma_size)); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_CURRENTL, - LO(s->buffer_addr)); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_CURRENTH, - HI(s->buffer_addr)); -#undef LO -#undef HI - - /* dsp buffers */ - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_IN_BUF_BEGIN, - dsp_in_buffer); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_IN_BUF_END_PLUS_1, - dsp_in_buffer + (dsp_in_size / 2)); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_IN_BUF_HEAD, - dsp_in_buffer); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_IN_BUF_TAIL, - dsp_in_buffer); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_OUT_BUF_BEGIN, - dsp_out_buffer); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_OUT_BUF_END_PLUS_1, - dsp_out_buffer + (dsp_out_size / 2)); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_OUT_BUF_HEAD, - dsp_out_buffer); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_OUT_BUF_TAIL, - dsp_out_buffer); -} - -static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s, - struct snd_pcm_runtime *runtime) -{ - u32 freq; - - /* - * put us in the lists if we're not already there - */ - if (! s->in_lists) { - s->index[0] = snd_m3_add_list(chip, s->index_list[0], - s->inst.data >> DP_SHIFT_COUNT); - s->index[1] = snd_m3_add_list(chip, s->index_list[1], - s->inst.data >> DP_SHIFT_COUNT); - s->index[2] = snd_m3_add_list(chip, s->index_list[2], - s->inst.data >> DP_SHIFT_COUNT); - s->in_lists = 1; - } - - /* write to 'mono' word */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + SRC3_DIRECTION_OFFSET + 1, - runtime->channels == 2 ? 0 : 1); - /* write to '8bit' word */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + SRC3_DIRECTION_OFFSET + 2, - snd_pcm_format_width(runtime->format) == 16 ? 0 : 1); - - /* set up dac/adc rate */ - freq = ((runtime->rate << 15) + 24000 ) / 48000; - if (freq) - freq--; - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_FREQUENCY, - freq); -} - - -static const struct play_vals { - u16 addr, val; -} pv[] = { - {CDATA_LEFT_VOLUME, ARB_VOLUME}, - {CDATA_RIGHT_VOLUME, ARB_VOLUME}, - {SRC3_DIRECTION_OFFSET, 0} , - /* +1, +2 are stereo/16 bit */ - {SRC3_DIRECTION_OFFSET + 3, 0x0000}, /* fraction? */ - {SRC3_DIRECTION_OFFSET + 4, 0}, /* first l */ - {SRC3_DIRECTION_OFFSET + 5, 0}, /* first r */ - {SRC3_DIRECTION_OFFSET + 6, 0}, /* second l */ - {SRC3_DIRECTION_OFFSET + 7, 0}, /* second r */ - {SRC3_DIRECTION_OFFSET + 8, 0}, /* delta l */ - {SRC3_DIRECTION_OFFSET + 9, 0}, /* delta r */ - {SRC3_DIRECTION_OFFSET + 10, 0x8000}, /* round */ - {SRC3_DIRECTION_OFFSET + 11, 0xFF00}, /* higher bute mark */ - {SRC3_DIRECTION_OFFSET + 13, 0}, /* temp0 */ - {SRC3_DIRECTION_OFFSET + 14, 0}, /* c fraction */ - {SRC3_DIRECTION_OFFSET + 15, 0}, /* counter */ - {SRC3_DIRECTION_OFFSET + 16, 8}, /* numin */ - {SRC3_DIRECTION_OFFSET + 17, 50*2}, /* numout */ - {SRC3_DIRECTION_OFFSET + 18, MINISRC_BIQUAD_STAGE - 1}, /* numstage */ - {SRC3_DIRECTION_OFFSET + 20, 0}, /* filtertap */ - {SRC3_DIRECTION_OFFSET + 21, 0} /* booster */ -}; - - -/* the mode passed should be already shifted and masked */ -static void -snd_m3_playback_setup(struct snd_m3 *chip, struct m3_dma *s, - struct snd_pcm_substream *subs) -{ - unsigned int i; - - /* - * some per client initializers - */ - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + SRC3_DIRECTION_OFFSET + 12, - s->inst.data + 40 + 8); - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + SRC3_DIRECTION_OFFSET + 19, - s->inst.code + MINISRC_COEF_LOC); - - /* enable or disable low pass filter? */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + SRC3_DIRECTION_OFFSET + 22, - subs->runtime->rate > 45000 ? 0xff : 0); - - /* tell it which way dma is going? */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_DMA_CONTROL, - DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR); - - /* - * set an armload of static initializers - */ - for (i = 0; i < ARRAY_SIZE(pv); i++) - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + pv[i].addr, pv[i].val); -} - -/* - * Native record driver - */ -static const struct rec_vals { - u16 addr, val; -} rv[] = { - {CDATA_LEFT_VOLUME, ARB_VOLUME}, - {CDATA_RIGHT_VOLUME, ARB_VOLUME}, - {SRC3_DIRECTION_OFFSET, 1} , - /* +1, +2 are stereo/16 bit */ - {SRC3_DIRECTION_OFFSET + 3, 0x0000}, /* fraction? */ - {SRC3_DIRECTION_OFFSET + 4, 0}, /* first l */ - {SRC3_DIRECTION_OFFSET + 5, 0}, /* first r */ - {SRC3_DIRECTION_OFFSET + 6, 0}, /* second l */ - {SRC3_DIRECTION_OFFSET + 7, 0}, /* second r */ - {SRC3_DIRECTION_OFFSET + 8, 0}, /* delta l */ - {SRC3_DIRECTION_OFFSET + 9, 0}, /* delta r */ - {SRC3_DIRECTION_OFFSET + 10, 0x8000}, /* round */ - {SRC3_DIRECTION_OFFSET + 11, 0xFF00}, /* higher bute mark */ - {SRC3_DIRECTION_OFFSET + 13, 0}, /* temp0 */ - {SRC3_DIRECTION_OFFSET + 14, 0}, /* c fraction */ - {SRC3_DIRECTION_OFFSET + 15, 0}, /* counter */ - {SRC3_DIRECTION_OFFSET + 16, 50},/* numin */ - {SRC3_DIRECTION_OFFSET + 17, 8}, /* numout */ - {SRC3_DIRECTION_OFFSET + 18, 0}, /* numstage */ - {SRC3_DIRECTION_OFFSET + 19, 0}, /* coef */ - {SRC3_DIRECTION_OFFSET + 20, 0}, /* filtertap */ - {SRC3_DIRECTION_OFFSET + 21, 0}, /* booster */ - {SRC3_DIRECTION_OFFSET + 22, 0xff} /* skip lpf */ -}; - -static void -snd_m3_capture_setup(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs) -{ - unsigned int i; - - /* - * some per client initializers - */ - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + SRC3_DIRECTION_OFFSET + 12, - s->inst.data + 40 + 8); - - /* tell it which way dma is going? */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_DMA_CONTROL, - DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT + - DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR); - - /* - * set an armload of static initializers - */ - for (i = 0; i < ARRAY_SIZE(rv); i++) - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + rv[i].addr, rv[i].val); -} - -static int snd_m3_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct m3_dma *s = substream->runtime->private_data; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - /* set buffer address */ - s->buffer_addr = substream->runtime->dma_addr; - if (s->buffer_addr & 0x3) { - snd_printk(KERN_ERR "oh my, not aligned\n"); - s->buffer_addr = s->buffer_addr & ~0x3; - } - return 0; -} - -static int snd_m3_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct m3_dma *s; - - if (substream->runtime->private_data == NULL) - return 0; - s = substream->runtime->private_data; - snd_pcm_lib_free_pages(substream); - s->buffer_addr = 0; - return 0; -} - -static int -snd_m3_pcm_prepare(struct snd_pcm_substream *subs) -{ - struct snd_m3 *chip = snd_pcm_substream_chip(subs); - struct snd_pcm_runtime *runtime = subs->runtime; - struct m3_dma *s = runtime->private_data; - - if (snd_BUG_ON(!s)) - return -ENXIO; - - if (runtime->format != SNDRV_PCM_FORMAT_U8 && - runtime->format != SNDRV_PCM_FORMAT_S16_LE) - return -EINVAL; - if (runtime->rate > 48000 || - runtime->rate < 8000) - return -EINVAL; - - spin_lock_irq(&chip->reg_lock); - - snd_m3_pcm_setup1(chip, s, subs); - - if (subs->stream == SNDRV_PCM_STREAM_PLAYBACK) - snd_m3_playback_setup(chip, s, subs); - else - snd_m3_capture_setup(chip, s, subs); - - snd_m3_pcm_setup2(chip, s, runtime); - - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - -/* - * get current pointer - */ -static unsigned int -snd_m3_get_pointer(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs) -{ - u16 hi = 0, lo = 0; - int retry = 10; - u32 addr; - - /* - * try and get a valid answer - */ - while (retry--) { - hi = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_CURRENTH); - - lo = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_CURRENTL); - - if (hi == snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, - s->inst.data + CDATA_HOST_SRC_CURRENTH)) - break; - } - addr = lo | ((u32)hi<<16); - return (unsigned int)(addr - s->buffer_addr); -} - -static snd_pcm_uframes_t -snd_m3_pcm_pointer(struct snd_pcm_substream *subs) -{ - struct snd_m3 *chip = snd_pcm_substream_chip(subs); - unsigned int ptr; - struct m3_dma *s = subs->runtime->private_data; - - if (snd_BUG_ON(!s)) - return 0; - - spin_lock(&chip->reg_lock); - ptr = snd_m3_get_pointer(chip, s, subs); - spin_unlock(&chip->reg_lock); - return bytes_to_frames(subs->runtime, ptr); -} - - -/* update pointer */ -/* spinlock held! */ -static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s) -{ - struct snd_pcm_substream *subs = s->substream; - unsigned int hwptr; - int diff; - - if (! s->running) - return; - - hwptr = snd_m3_get_pointer(chip, s, subs); - - /* try to avoid expensive modulo divisions */ - if (hwptr >= s->dma_size) - hwptr %= s->dma_size; - - diff = s->dma_size + hwptr - s->hwptr; - if (diff >= s->dma_size) - diff %= s->dma_size; - - s->hwptr = hwptr; - s->count += diff; - - if (s->count >= (signed)s->period_size) { - - if (s->count < 2 * (signed)s->period_size) - s->count -= (signed)s->period_size; - else - s->count %= s->period_size; - - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(subs); - spin_lock(&chip->reg_lock); - } -} - -/* The m3's hardware volume works by incrementing / decrementing 2 counters - (without wrap around) in response to volume button presses and then - generating an interrupt. The pair of counters is stored in bits 1-3 and 5-7 - of a byte wide register. The meaning of bits 0 and 4 is unknown. */ -static void snd_m3_update_hw_volume(struct work_struct *work) -{ - struct snd_m3 *chip = container_of(work, struct snd_m3, hwvol_work); - int x, val; - - /* Figure out which volume control button was pushed, - based on differences from the default register - values. */ - x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee; - - /* Reset the volume counters to 4. Tests on the allegro integrated - into a Compaq N600C laptop, have revealed that: - 1) Writing any value will result in the 2 counters being reset to - 4 so writing 0x88 is not strictly necessary - 2) Writing to any of the 4 involved registers will reset all 4 - of them (and reading them always returns the same value for all - of them) - It could be that a maestro deviates from this, so leave the code - as is. */ - outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE); - outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE); - outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER); - outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER); - - /* Ignore spurious HV interrupts during suspend / resume, this avoids - mistaking them for a mute button press. */ - if (chip->in_suspend) - return; - -#ifndef CONFIG_SND_MAESTRO3_INPUT - if (!chip->master_switch || !chip->master_volume) - return; - - val = snd_ac97_read(chip->ac97, AC97_MASTER); - switch (x) { - case 0x88: - /* The counters have not changed, yet we've received a HV - interrupt. According to tests run by various people this - happens when pressing the mute button. */ - val ^= 0x8000; - break; - case 0xaa: - /* counters increased by 1 -> volume up */ - if ((val & 0x7f) > 0) - val--; - if ((val & 0x7f00) > 0) - val -= 0x0100; - break; - case 0x66: - /* counters decreased by 1 -> volume down */ - if ((val & 0x7f) < 0x1f) - val++; - if ((val & 0x7f00) < 0x1f00) - val += 0x0100; - break; - } - if (snd_ac97_update(chip->ac97, AC97_MASTER, val)) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_switch->id); -#else - if (!chip->input_dev) - return; - - val = 0; - switch (x) { - case 0x88: - /* The counters have not changed, yet we've received a HV - interrupt. According to tests run by various people this - happens when pressing the mute button. */ - val = KEY_MUTE; - break; - case 0xaa: - /* counters increased by 1 -> volume up */ - val = KEY_VOLUMEUP; - break; - case 0x66: - /* counters decreased by 1 -> volume down */ - val = KEY_VOLUMEDOWN; - break; - } - - if (val) { - input_report_key(chip->input_dev, val, 1); - input_sync(chip->input_dev); - input_report_key(chip->input_dev, val, 0); - input_sync(chip->input_dev); - } -#endif -} - -static irqreturn_t snd_m3_interrupt(int irq, void *dev_id) -{ - struct snd_m3 *chip = dev_id; - u8 status; - int i; - - status = inb(chip->iobase + HOST_INT_STATUS); - - if (status == 0xff) - return IRQ_NONE; - - if (status & HV_INT_PENDING) - schedule_work(&chip->hwvol_work); - - /* - * ack an assp int if its running - * and has an int pending - */ - if (status & ASSP_INT_PENDING) { - u8 ctl = inb(chip->iobase + ASSP_CONTROL_B); - if (!(ctl & STOP_ASSP_CLOCK)) { - ctl = inb(chip->iobase + ASSP_HOST_INT_STATUS); - if (ctl & DSP2HOST_REQ_TIMER) { - outb(DSP2HOST_REQ_TIMER, chip->iobase + ASSP_HOST_INT_STATUS); - /* update adc/dac info if it was a timer int */ - spin_lock(&chip->reg_lock); - for (i = 0; i < chip->num_substreams; i++) { - struct m3_dma *s = &chip->substreams[i]; - if (s->running) - snd_m3_update_ptr(chip, s); - } - spin_unlock(&chip->reg_lock); - } - } - } - -#if 0 /* TODO: not supported yet */ - if ((status & MPU401_INT_PENDING) && chip->rmidi) - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); -#endif - - /* ack ints */ - outb(status, chip->iobase + HOST_INT_STATUS); - - return IRQ_HANDLED; -} - - -/* - */ - -static struct snd_pcm_hardware snd_m3_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - /*SNDRV_PCM_INFO_PAUSE |*/ - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (512*1024), - .period_bytes_min = 64, - .period_bytes_max = (512*1024), - .periods_min = 1, - .periods_max = 1024, -}; - -static struct snd_pcm_hardware snd_m3_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - /*SNDRV_PCM_INFO_PAUSE |*/ - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (512*1024), - .period_bytes_min = 64, - .period_bytes_max = (512*1024), - .periods_min = 1, - .periods_max = 1024, -}; - - -/* - */ - -static int -snd_m3_substream_open(struct snd_m3 *chip, struct snd_pcm_substream *subs) -{ - int i; - struct m3_dma *s; - - spin_lock_irq(&chip->reg_lock); - for (i = 0; i < chip->num_substreams; i++) { - s = &chip->substreams[i]; - if (! s->opened) - goto __found; - } - spin_unlock_irq(&chip->reg_lock); - return -ENOMEM; -__found: - s->opened = 1; - s->running = 0; - spin_unlock_irq(&chip->reg_lock); - - subs->runtime->private_data = s; - s->substream = subs; - - /* set list owners */ - if (subs->stream == SNDRV_PCM_STREAM_PLAYBACK) { - s->index_list[0] = &chip->mixer_list; - } else - s->index_list[0] = &chip->adc1_list; - s->index_list[1] = &chip->msrc_list; - s->index_list[2] = &chip->dma_list; - - return 0; -} - -static void -snd_m3_substream_close(struct snd_m3 *chip, struct snd_pcm_substream *subs) -{ - struct m3_dma *s = subs->runtime->private_data; - - if (s == NULL) - return; /* not opened properly */ - - spin_lock_irq(&chip->reg_lock); - if (s->substream && s->running) - snd_m3_pcm_stop(chip, s, s->substream); /* does this happen? */ - if (s->in_lists) { - snd_m3_remove_list(chip, s->index_list[0], s->index[0]); - snd_m3_remove_list(chip, s->index_list[1], s->index[1]); - snd_m3_remove_list(chip, s->index_list[2], s->index[2]); - s->in_lists = 0; - } - s->running = 0; - s->opened = 0; - spin_unlock_irq(&chip->reg_lock); -} - -static int -snd_m3_playback_open(struct snd_pcm_substream *subs) -{ - struct snd_m3 *chip = snd_pcm_substream_chip(subs); - struct snd_pcm_runtime *runtime = subs->runtime; - int err; - - if ((err = snd_m3_substream_open(chip, subs)) < 0) - return err; - - runtime->hw = snd_m3_playback; - - return 0; -} - -static int -snd_m3_playback_close(struct snd_pcm_substream *subs) -{ - struct snd_m3 *chip = snd_pcm_substream_chip(subs); - - snd_m3_substream_close(chip, subs); - return 0; -} - -static int -snd_m3_capture_open(struct snd_pcm_substream *subs) -{ - struct snd_m3 *chip = snd_pcm_substream_chip(subs); - struct snd_pcm_runtime *runtime = subs->runtime; - int err; - - if ((err = snd_m3_substream_open(chip, subs)) < 0) - return err; - - runtime->hw = snd_m3_capture; - - return 0; -} - -static int -snd_m3_capture_close(struct snd_pcm_substream *subs) -{ - struct snd_m3 *chip = snd_pcm_substream_chip(subs); - - snd_m3_substream_close(chip, subs); - return 0; -} - -/* - * create pcm instance - */ - -static struct snd_pcm_ops snd_m3_playback_ops = { - .open = snd_m3_playback_open, - .close = snd_m3_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_m3_pcm_hw_params, - .hw_free = snd_m3_pcm_hw_free, - .prepare = snd_m3_pcm_prepare, - .trigger = snd_m3_pcm_trigger, - .pointer = snd_m3_pcm_pointer, -}; - -static struct snd_pcm_ops snd_m3_capture_ops = { - .open = snd_m3_capture_open, - .close = snd_m3_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_m3_pcm_hw_params, - .hw_free = snd_m3_pcm_hw_free, - .prepare = snd_m3_pcm_prepare, - .trigger = snd_m3_pcm_trigger, - .pointer = snd_m3_pcm_pointer, -}; - -static int __devinit -snd_m3_pcm(struct snd_m3 * chip, int device) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(chip->card, chip->card->driver, device, - MAX_PLAYBACKS, MAX_CAPTURES, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_m3_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_m3_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->driver); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 64*1024); - - return 0; -} - - -/* - * ac97 interface - */ - -/* - * Wait for the ac97 serial bus to be free. - * return nonzero if the bus is still busy. - */ -static int snd_m3_ac97_wait(struct snd_m3 *chip) -{ - int i = 10000; - - do { - if (! (snd_m3_inb(chip, 0x30) & 1)) - return 0; - cpu_relax(); - } while (i-- > 0); - - snd_printk(KERN_ERR "ac97 serial bus busy\n"); - return 1; -} - -static unsigned short -snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_m3 *chip = ac97->private_data; - unsigned short data = 0xffff; - - if (snd_m3_ac97_wait(chip)) - goto fail; - snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); - if (snd_m3_ac97_wait(chip)) - goto fail; - data = snd_m3_inw(chip, CODEC_DATA); -fail: - return data; -} - -static void -snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) -{ - struct snd_m3 *chip = ac97->private_data; - - if (snd_m3_ac97_wait(chip)) - return; - snd_m3_outw(chip, val, CODEC_DATA); - snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); -} - - -static void snd_m3_remote_codec_config(int io, int isremote) -{ - isremote = isremote ? 1 : 0; - - outw((inw(io + RING_BUS_CTRL_B) & ~SECOND_CODEC_ID_MASK) | isremote, - io + RING_BUS_CTRL_B); - outw((inw(io + SDO_OUT_DEST_CTRL) & ~COMMAND_ADDR_OUT) | isremote, - io + SDO_OUT_DEST_CTRL); - outw((inw(io + SDO_IN_DEST_CTRL) & ~STATUS_ADDR_IN) | isremote, - io + SDO_IN_DEST_CTRL); -} - -/* - * hack, returns non zero on err - */ -static int snd_m3_try_read_vendor(struct snd_m3 *chip) -{ - u16 ret; - - if (snd_m3_ac97_wait(chip)) - return 1; - - snd_m3_outb(chip, 0x80 | (AC97_VENDOR_ID1 & 0x7f), 0x30); - - if (snd_m3_ac97_wait(chip)) - return 1; - - ret = snd_m3_inw(chip, 0x32); - - return (ret == 0) || (ret == 0xffff); -} - -static void snd_m3_ac97_reset(struct snd_m3 *chip) -{ - u16 dir; - int delay1 = 0, delay2 = 0, i; - int io = chip->iobase; - - if (chip->allegro_flag) { - /* - * the onboard codec on the allegro seems - * to want to wait a very long time before - * coming back to life - */ - delay1 = 50; - delay2 = 800; - } else { - /* maestro3 */ - delay1 = 20; - delay2 = 500; - } - - for (i = 0; i < 5; i++) { - dir = inw(io + GPIO_DIRECTION); - if (!chip->irda_workaround) - dir |= 0x10; /* assuming pci bus master? */ - - snd_m3_remote_codec_config(io, 0); - - outw(IO_SRAM_ENABLE, io + RING_BUS_CTRL_A); - udelay(20); - - outw(dir & ~GPO_PRIMARY_AC97 , io + GPIO_DIRECTION); - outw(~GPO_PRIMARY_AC97 , io + GPIO_MASK); - outw(0, io + GPIO_DATA); - outw(dir | GPO_PRIMARY_AC97, io + GPIO_DIRECTION); - - schedule_timeout_uninterruptible(msecs_to_jiffies(delay1)); - - outw(GPO_PRIMARY_AC97, io + GPIO_DATA); - udelay(5); - /* ok, bring back the ac-link */ - outw(IO_SRAM_ENABLE | SERIAL_AC_LINK_ENABLE, io + RING_BUS_CTRL_A); - outw(~0, io + GPIO_MASK); - - schedule_timeout_uninterruptible(msecs_to_jiffies(delay2)); - - if (! snd_m3_try_read_vendor(chip)) - break; - - delay1 += 10; - delay2 += 100; - - snd_printd("maestro3: retrying codec reset with delays of %d and %d ms\n", - delay1, delay2); - } - -#if 0 - /* more gung-ho reset that doesn't - * seem to work anywhere :) - */ - tmp = inw(io + RING_BUS_CTRL_A); - outw(RAC_SDFS_ENABLE|LAC_SDFS_ENABLE, io + RING_BUS_CTRL_A); - msleep(20); - outw(tmp, io + RING_BUS_CTRL_A); - msleep(50); -#endif -} - -static int __devinit snd_m3_mixer(struct snd_m3 *chip) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; -#ifndef CONFIG_SND_MAESTRO3_INPUT - struct snd_ctl_elem_id elem_id; -#endif - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_m3_ac97_write, - .read = snd_m3_ac97_read, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) - return err; - - /* seems ac97 PCM needs initialization.. hack hack.. */ - snd_ac97_write(chip->ac97, AC97_PCM, 0x8000 | (15 << 8) | 15); - schedule_timeout_uninterruptible(msecs_to_jiffies(100)); - snd_ac97_write(chip->ac97, AC97_PCM, 0); - -#ifndef CONFIG_SND_MAESTRO3_INPUT - memset(&elem_id, 0, sizeof(elem_id)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(elem_id.name, "Master Playback Switch"); - chip->master_switch = snd_ctl_find_id(chip->card, &elem_id); - memset(&elem_id, 0, sizeof(elem_id)); - elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(elem_id.name, "Master Playback Volume"); - chip->master_volume = snd_ctl_find_id(chip->card, &elem_id); -#endif - - return 0; -} - - -/* - * initialize ASSP - */ - -#define MINISRC_LPF_LEN 10 -static const u16 minisrc_lpf[MINISRC_LPF_LEN] = { - 0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C, - 0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F -}; - -static void snd_m3_assp_init(struct snd_m3 *chip) -{ - unsigned int i; - const u16 *data; - - /* zero kernel data */ - for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++) - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_BASE_ADDR + i, 0); - - /* zero mixer data? */ - for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++) - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_BASE_ADDR2 + i, 0); - - /* init dma pointer */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_CURRENT_DMA, - KDATA_DMA_XFER0); - - /* write kernel into code memory.. */ - data = (const u16 *)chip->assp_kernel_image->data; - for (i = 0 ; i * 2 < chip->assp_kernel_image->size; i++) { - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, - REV_B_CODE_MEMORY_BEGIN + i, - le16_to_cpu(data[i])); - } - - /* - * We only have this one client and we know that 0x400 - * is free in our kernel's mem map, so lets just - * drop it there. It seems that the minisrc doesn't - * need vectors, so we won't bother with them.. - */ - data = (const u16 *)chip->assp_minisrc_image->data; - for (i = 0; i * 2 < chip->assp_minisrc_image->size; i++) { - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, - 0x400 + i, le16_to_cpu(data[i])); - } - - /* - * write the coefficients for the low pass filter? - */ - for (i = 0; i < MINISRC_LPF_LEN ; i++) { - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, - 0x400 + MINISRC_COEF_LOC + i, - minisrc_lpf[i]); - } - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, - 0x400 + MINISRC_COEF_LOC + MINISRC_LPF_LEN, - 0x8000); - - /* - * the minisrc is the only thing on - * our task list.. - */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_TASK0, - 0x400); - - /* - * init the mixer number.. - */ - - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_MIXER_TASK_NUMBER,0); - - /* - * EXTREME KERNEL MASTER VOLUME - */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_DAC_LEFT_VOLUME, ARB_VOLUME); - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_DAC_RIGHT_VOLUME, ARB_VOLUME); - - chip->mixer_list.curlen = 0; - chip->mixer_list.mem_addr = KDATA_MIXER_XFER0; - chip->mixer_list.max = MAX_VIRTUAL_MIXER_CHANNELS; - chip->adc1_list.curlen = 0; - chip->adc1_list.mem_addr = KDATA_ADC1_XFER0; - chip->adc1_list.max = MAX_VIRTUAL_ADC1_CHANNELS; - chip->dma_list.curlen = 0; - chip->dma_list.mem_addr = KDATA_DMA_XFER0; - chip->dma_list.max = MAX_VIRTUAL_DMA_CHANNELS; - chip->msrc_list.curlen = 0; - chip->msrc_list.mem_addr = KDATA_INSTANCE0_MINISRC; - chip->msrc_list.max = MAX_INSTANCE_MINISRC; -} - - -static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int index) -{ - int data_bytes = 2 * ( MINISRC_TMP_BUFFER_SIZE / 2 + - MINISRC_IN_BUFFER_SIZE / 2 + - 1 + MINISRC_OUT_BUFFER_SIZE / 2 + 1 ); - int address, i; - - /* - * the revb memory map has 0x1100 through 0x1c00 - * free. - */ - - /* - * align instance address to 256 bytes so that its - * shifted list address is aligned. - * list address = (mem address >> 1) >> 7; - */ - data_bytes = ALIGN(data_bytes, 256); - address = 0x1100 + ((data_bytes/2) * index); - - if ((address + (data_bytes/2)) >= 0x1c00) { - snd_printk(KERN_ERR "no memory for %d bytes at ind %d (addr 0x%x)\n", - data_bytes, index, address); - return -ENOMEM; - } - - s->number = index; - s->inst.code = 0x400; - s->inst.data = address; - - for (i = data_bytes / 2; i > 0; address++, i--) { - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - address, 0); - } - - return 0; -} - - -/* - * this works for the reference board, have to find - * out about others - * - * this needs more magic for 4 speaker, but.. - */ -static void -snd_m3_amp_enable(struct snd_m3 *chip, int enable) -{ - int io = chip->iobase; - u16 gpo, polarity; - - if (! chip->external_amp) - return; - - polarity = enable ? 0 : 1; - polarity = polarity << chip->amp_gpio; - gpo = 1 << chip->amp_gpio; - - outw(~gpo, io + GPIO_MASK); - - outw(inw(io + GPIO_DIRECTION) | gpo, - io + GPIO_DIRECTION); - - outw((GPO_SECONDARY_AC97 | GPO_PRIMARY_AC97 | polarity), - io + GPIO_DATA); - - outw(0xffff, io + GPIO_MASK); -} - -static void -snd_m3_hv_init(struct snd_m3 *chip) -{ - unsigned long io = chip->iobase; - u16 val = GPI_VOL_DOWN | GPI_VOL_UP; - - if (!chip->is_omnibook) - return; - - /* - * Volume buttons on some HP OmniBook laptops - * require some GPIO magic to work correctly. - */ - outw(0xffff, io + GPIO_MASK); - outw(0x0000, io + GPIO_DATA); - - outw(~val, io + GPIO_MASK); - outw(inw(io + GPIO_DIRECTION) & ~val, io + GPIO_DIRECTION); - outw(val, io + GPIO_MASK); - - outw(0xffff, io + GPIO_MASK); -} - -static int -snd_m3_chip_init(struct snd_m3 *chip) -{ - struct pci_dev *pcidev = chip->pci; - unsigned long io = chip->iobase; - u32 n; - u16 w; - u8 t; /* makes as much sense as 'n', no? */ - - pci_read_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, &w); - w &= ~(SOUND_BLASTER_ENABLE|FM_SYNTHESIS_ENABLE| - MPU401_IO_ENABLE|MPU401_IRQ_ENABLE|ALIAS_10BIT_IO| - DISABLE_LEGACY); - pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); - - pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); - n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD); - n |= chip->hv_config; - /* For some reason we must always use reduced debounce. */ - n |= REDUCED_DEBOUNCE; - n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; - pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n); - - outb(RESET_ASSP, chip->iobase + ASSP_CONTROL_B); - pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); - n &= ~INT_CLK_SELECT; - if (!chip->allegro_flag) { - n &= ~INT_CLK_MULT_ENABLE; - n |= INT_CLK_SRC_NOT_PCI; - } - n &= ~( CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2 ); - pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n); - - if (chip->allegro_flag) { - pci_read_config_dword(pcidev, PCI_USER_CONFIG, &n); - n |= IN_CLK_12MHZ_SELECT; - pci_write_config_dword(pcidev, PCI_USER_CONFIG, n); - } - - t = inb(chip->iobase + ASSP_CONTROL_A); - t &= ~( DSP_CLK_36MHZ_SELECT | ASSP_CLK_49MHZ_SELECT); - t |= ASSP_CLK_49MHZ_SELECT; - t |= ASSP_0_WS_ENABLE; - outb(t, chip->iobase + ASSP_CONTROL_A); - - snd_m3_assp_init(chip); /* download DSP code before starting ASSP below */ - outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); - - outb(0x00, io + HARDWARE_VOL_CTRL); - outb(0x88, io + SHADOW_MIX_REG_VOICE); - outb(0x88, io + HW_VOL_COUNTER_VOICE); - outb(0x88, io + SHADOW_MIX_REG_MASTER); - outb(0x88, io + HW_VOL_COUNTER_MASTER); - - return 0; -} - -static void -snd_m3_enable_ints(struct snd_m3 *chip) -{ - unsigned long io = chip->iobase; - unsigned short val; - - /* TODO: MPU401 not supported yet */ - val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/; - if (chip->hv_config & HV_CTRL_ENABLE) - val |= HV_INT_ENABLE; - outb(val, chip->iobase + HOST_INT_STATUS); - outw(val, io + HOST_INT_CTRL); - outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, - io + ASSP_CONTROL_C); -} - - -/* - */ - -static int snd_m3_free(struct snd_m3 *chip) -{ - struct m3_dma *s; - int i; - - cancel_work_sync(&chip->hwvol_work); -#ifdef CONFIG_SND_MAESTRO3_INPUT - if (chip->input_dev) - input_unregister_device(chip->input_dev); -#endif - - if (chip->substreams) { - spin_lock_irq(&chip->reg_lock); - for (i = 0; i < chip->num_substreams; i++) { - s = &chip->substreams[i]; - /* check surviving pcms; this should not happen though.. */ - if (s->substream && s->running) - snd_m3_pcm_stop(chip, s, s->substream); - } - spin_unlock_irq(&chip->reg_lock); - kfree(chip->substreams); - } - if (chip->iobase) { - outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */ - } - -#ifdef CONFIG_PM - vfree(chip->suspend_mem); -#endif - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - if (chip->iobase) - pci_release_regions(chip->pci); - - release_firmware(chip->assp_kernel_image); - release_firmware(chip->assp_minisrc_image); - - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - - -/* - * APM support - */ -#ifdef CONFIG_PM -static int m3_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_m3 *chip = card->private_data; - int i, dsp_index; - - if (chip->suspend_mem == NULL) - return 0; - - chip->in_suspend = 1; - cancel_work_sync(&chip->hwvol_work); - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_ac97_suspend(chip->ac97); - - msleep(10); /* give the assp a chance to idle.. */ - - snd_m3_assp_halt(chip); - - /* save dsp image */ - dsp_index = 0; - for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++) - chip->suspend_mem[dsp_index++] = - snd_m3_assp_read(chip, MEMTYPE_INTERNAL_CODE, i); - for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++) - chip->suspend_mem[dsp_index++] = - snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int m3_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_m3 *chip = card->private_data; - int i, dsp_index; - - if (chip->suspend_mem == NULL) - return 0; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "maestor3: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - /* first lets just bring everything back. .*/ - snd_m3_outw(chip, 0, 0x54); - snd_m3_outw(chip, 0, 0x56); - - snd_m3_chip_init(chip); - snd_m3_assp_halt(chip); - snd_m3_ac97_reset(chip); - - /* restore dsp image */ - dsp_index = 0; - for (i = REV_B_CODE_MEMORY_BEGIN; i <= REV_B_CODE_MEMORY_END; i++) - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, i, - chip->suspend_mem[dsp_index++]); - for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++) - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, i, - chip->suspend_mem[dsp_index++]); - - /* tell the dma engine to restart itself */ - snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA, - KDATA_DMA_ACTIVE, 0); - - /* restore ac97 registers */ - snd_ac97_resume(chip->ac97); - - snd_m3_assp_continue(chip); - snd_m3_enable_ints(chip); - snd_m3_amp_enable(chip, 1); - - snd_m3_hv_init(chip); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - chip->in_suspend = 0; - return 0; -} -#endif /* CONFIG_PM */ - -#ifdef CONFIG_SND_MAESTRO3_INPUT -static int __devinit snd_m3_input_register(struct snd_m3 *chip) -{ - struct input_dev *input_dev; - int err; - - input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - - snprintf(chip->phys, sizeof(chip->phys), "pci-%s/input0", - pci_name(chip->pci)); - - input_dev->name = chip->card->driver; - input_dev->phys = chip->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.vendor = chip->pci->vendor; - input_dev->id.product = chip->pci->device; - input_dev->dev.parent = &chip->pci->dev; - - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(KEY_MUTE, input_dev->keybit); - __set_bit(KEY_VOLUMEDOWN, input_dev->keybit); - __set_bit(KEY_VOLUMEUP, input_dev->keybit); - - err = input_register_device(input_dev); - if (err) { - input_free_device(input_dev); - return err; - } - - chip->input_dev = input_dev; - return 0; -} -#endif /* CONFIG_INPUT */ - -/* - */ - -static int snd_m3_dev_free(struct snd_device *device) -{ - struct snd_m3 *chip = device->device_data; - return snd_m3_free(chip); -} - -static int __devinit -snd_m3_create(struct snd_card *card, struct pci_dev *pci, - int enable_amp, - int amp_gpio, - struct snd_m3 **chip_ret) -{ - struct snd_m3 *chip; - int i, err; - const struct snd_pci_quirk *quirk; - static struct snd_device_ops ops = { - .dev_free = snd_m3_dev_free, - }; - - *chip_ret = NULL; - - if (pci_enable_device(pci)) - return -EIO; - - /* check, if we can restrict PCI DMA transfers to 28 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "architecture does not support 28bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - spin_lock_init(&chip->reg_lock); - - switch (pci->device) { - case PCI_DEVICE_ID_ESS_ALLEGRO: - case PCI_DEVICE_ID_ESS_ALLEGRO_1: - case PCI_DEVICE_ID_ESS_CANYON3D_2LE: - case PCI_DEVICE_ID_ESS_CANYON3D_2: - chip->allegro_flag = 1; - break; - } - - chip->card = card; - chip->pci = pci; - chip->irq = -1; - INIT_WORK(&chip->hwvol_work, snd_m3_update_hw_volume); - - chip->external_amp = enable_amp; - if (amp_gpio >= 0 && amp_gpio <= 0x0f) - chip->amp_gpio = amp_gpio; - else { - quirk = snd_pci_quirk_lookup(pci, m3_amp_quirk_list); - if (quirk) { - snd_printdd(KERN_INFO "maestro3: set amp-gpio " - "for '%s'\n", quirk->name); - chip->amp_gpio = quirk->value; - } else if (chip->allegro_flag) - chip->amp_gpio = GPO_EXT_AMP_ALLEGRO; - else /* presumably this is for all 'maestro3's.. */ - chip->amp_gpio = GPO_EXT_AMP_M3; - } - - quirk = snd_pci_quirk_lookup(pci, m3_irda_quirk_list); - if (quirk) { - snd_printdd(KERN_INFO "maestro3: enabled irda workaround " - "for '%s'\n", quirk->name); - chip->irda_workaround = 1; - } - quirk = snd_pci_quirk_lookup(pci, m3_hv_quirk_list); - if (quirk) - chip->hv_config = quirk->value; - if (snd_pci_quirk_lookup(pci, m3_omnibook_quirk_list)) - chip->is_omnibook = 1; - - chip->num_substreams = NR_DSPS; - chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma), - GFP_KERNEL); - if (chip->substreams == NULL) { - kfree(chip); - pci_disable_device(pci); - return -ENOMEM; - } - - err = request_firmware(&chip->assp_kernel_image, - "ess/maestro3_assp_kernel.fw", &pci->dev); - if (err < 0) { - snd_m3_free(chip); - return err; - } - - err = request_firmware(&chip->assp_minisrc_image, - "ess/maestro3_assp_minisrc.fw", &pci->dev); - if (err < 0) { - snd_m3_free(chip); - return err; - } - - if ((err = pci_request_regions(pci, card->driver)) < 0) { - snd_m3_free(chip); - return err; - } - chip->iobase = pci_resource_start(pci, 0); - - /* just to be sure */ - pci_set_master(pci); - - snd_m3_chip_init(chip); - snd_m3_assp_halt(chip); - - snd_m3_ac97_reset(chip); - - snd_m3_amp_enable(chip, 1); - - snd_m3_hv_init(chip); - - if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_m3_free(chip); - return -ENOMEM; - } - chip->irq = pci->irq; - -#ifdef CONFIG_PM - chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH)); - if (chip->suspend_mem == NULL) - snd_printk(KERN_WARNING "can't allocate apm buffer\n"); -#endif - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_m3_free(chip); - return err; - } - - if ((err = snd_m3_mixer(chip)) < 0) - return err; - - for (i = 0; i < chip->num_substreams; i++) { - struct m3_dma *s = &chip->substreams[i]; - if ((err = snd_m3_assp_client_init(chip, s, i)) < 0) - return err; - } - - if ((err = snd_m3_pcm(chip, 0)) < 0) - return err; - -#ifdef CONFIG_SND_MAESTRO3_INPUT - if (chip->hv_config & HV_CTRL_ENABLE) { - err = snd_m3_input_register(chip); - if (err) - snd_printk(KERN_WARNING "Input device registration " - "failed with error %i", err); - } -#endif - - snd_m3_enable_ints(chip); - snd_m3_assp_continue(chip); - - snd_card_set_dev(card, &pci->dev); - - *chip_ret = chip; - - return 0; -} - -/* - */ -static int __devinit -snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_m3 *chip; - int err; - - /* don't pick up modems */ - if (((pci->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO) - return -ENODEV; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - switch (pci->device) { - case PCI_DEVICE_ID_ESS_ALLEGRO: - case PCI_DEVICE_ID_ESS_ALLEGRO_1: - strcpy(card->driver, "Allegro"); - break; - case PCI_DEVICE_ID_ESS_CANYON3D_2LE: - case PCI_DEVICE_ID_ESS_CANYON3D_2: - strcpy(card->driver, "Canyon3D-2"); - break; - default: - strcpy(card->driver, "Maestro3"); - break; - } - - if ((err = snd_m3_create(card, pci, - external_amp[dev], - amp_gpio[dev], - &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - sprintf(card->shortname, "ESS %s PCI", card->driver); - sprintf(card->longname, "%s at 0x%lx, irq %d", - card->shortname, chip->iobase, chip->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - -#if 0 /* TODO: not supported yet */ - /* TODO enable MIDI IRQ and I/O */ - err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, - chip->iobase + MPU401_DATA_PORT, - MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi); - if (err < 0) - printk(KERN_WARNING "maestro3: no MIDI support.\n"); -#endif - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_m3_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_m3_ids, - .probe = snd_m3_probe, - .remove = __devexit_p(snd_m3_remove), -#ifdef CONFIG_PM - .suspend = m3_suspend, - .resume = m3_resume, -#endif -}; - -static int __init alsa_card_m3_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_m3_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_m3_init) -module_exit(alsa_card_m3_exit) diff --git a/ANDROID_3.4.5/sound/pci/mixart/Makefile b/ANDROID_3.4.5/sound/pci/mixart/Makefile deleted file mode 100644 index cce159ec..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-mixart-objs := mixart.o mixart_core.o mixart_hwdep.o mixart_mixer.o - -obj-$(CONFIG_SND_MIXART) += snd-mixart.o diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart.c b/ANDROID_3.4.5/sound/pci/mixart/mixart.c deleted file mode 100644 index 487837c0..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart.c +++ /dev/null @@ -1,1401 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * main file with alsa callbacks - * - * Copyright (c) 2003 by Digigram - * - * 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 -#include -#include -#include -#include -#include "mixart.h" -#include "mixart_hwdep.h" -#include "mixart_core.h" -#include "mixart_mixer.h" - -#define CARD_NAME "miXart" - -MODULE_AUTHOR("Digigram "); -MODULE_DESCRIPTION("Digigram " CARD_NAME); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); - -/* - */ - -static DEFINE_PCI_DEVICE_TABLE(snd_mixart_ids) = { - { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_mixart_ids); - - -static int mixart_set_pipe_state(struct mixart_mgr *mgr, - struct mixart_pipe *pipe, int start) -{ - struct mixart_group_state_req group_state; - struct mixart_group_state_resp group_state_resp; - struct mixart_msg request; - int err; - u32 system_msg_uid; - - switch(pipe->status) { - case PIPE_RUNNING: - case PIPE_CLOCK_SET: - if(start) return 0; /* already started */ - break; - case PIPE_STOPPED: - if(!start) return 0; /* already stopped */ - break; - default: - snd_printk(KERN_ERR "error mixart_set_pipe_state called with wrong pipe->status!\n"); - return -EINVAL; /* function called with wrong pipe status */ - } - - system_msg_uid = 0x12345678; /* the event ! (take care: the MSB and two LSB's have to be 0) */ - - /* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */ - - request.message_id = MSG_SYSTEM_WAIT_SYNCHRO_CMD; - request.uid = (struct mixart_uid){0,0}; - request.data = &system_msg_uid; - request.size = sizeof(system_msg_uid); - - err = snd_mixart_send_msg_wait_notif(mgr, &request, system_msg_uid); - if(err) { - snd_printk(KERN_ERR "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n"); - return err; - } - - /* start or stop the pipe (1 pipe) */ - - memset(&group_state, 0, sizeof(group_state)); - group_state.pipe_count = 1; - group_state.pipe_uid[0] = pipe->group_uid; - - if(start) - request.message_id = MSG_STREAM_START_STREAM_GRP_PACKET; - else - request.message_id = MSG_STREAM_STOP_STREAM_GRP_PACKET; - - request.uid = pipe->group_uid; /*(struct mixart_uid){0,0};*/ - request.data = &group_state; - request.size = sizeof(group_state); - - err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp); - if (err < 0 || group_state_resp.txx_status != 0) { - snd_printk(KERN_ERR "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n", err, group_state_resp.txx_status); - return -EINVAL; - } - - if(start) { - u32 stat; - - group_state.pipe_count = 0; /* in case of start same command once again with pipe_count=0 */ - - err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp); - if (err < 0 || group_state_resp.txx_status != 0) { - snd_printk(KERN_ERR "error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n", err, group_state_resp.txx_status); - return -EINVAL; - } - - /* in case of start send a synchro top */ - - request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD; - request.uid = (struct mixart_uid){0,0}; - request.data = NULL; - request.size = 0; - - err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat); - if (err < 0 || stat != 0) { - snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n", err, stat); - return -EINVAL; - } - - pipe->status = PIPE_RUNNING; - } - else /* !start */ - pipe->status = PIPE_STOPPED; - - return 0; -} - - -static int mixart_set_clock(struct mixart_mgr *mgr, - struct mixart_pipe *pipe, unsigned int rate) -{ - struct mixart_msg request; - struct mixart_clock_properties clock_properties; - struct mixart_clock_properties_resp clock_prop_resp; - int err; - - switch(pipe->status) { - case PIPE_CLOCK_SET: - break; - case PIPE_RUNNING: - if(rate != 0) - break; - default: - if(rate == 0) - return 0; /* nothing to do */ - else { - snd_printk(KERN_ERR "error mixart_set_clock(%d) called with wrong pipe->status !\n", rate); - return -EINVAL; - } - } - - memset(&clock_properties, 0, sizeof(clock_properties)); - clock_properties.clock_generic_type = (rate != 0) ? CGT_INTERNAL_CLOCK : CGT_NO_CLOCK; - clock_properties.clock_mode = CM_STANDALONE; - clock_properties.frequency = rate; - clock_properties.nb_callers = 1; /* only one entry in uid_caller ! */ - clock_properties.uid_caller[0] = pipe->group_uid; - - snd_printdd("mixart_set_clock to %d kHz\n", rate); - - request.message_id = MSG_CLOCK_SET_PROPERTIES; - request.uid = mgr->uid_console_manager; - request.data = &clock_properties; - request.size = sizeof(clock_properties); - - err = snd_mixart_send_msg(mgr, &request, sizeof(clock_prop_resp), &clock_prop_resp); - if (err < 0 || clock_prop_resp.status != 0 || clock_prop_resp.clock_mode != CM_STANDALONE) { - snd_printk(KERN_ERR "error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x mod=%x !\n", err, clock_prop_resp.status, clock_prop_resp.clock_mode); - return -EINVAL; - } - - if(rate) pipe->status = PIPE_CLOCK_SET; - else pipe->status = PIPE_RUNNING; - - return 0; -} - - -/* - * Allocate or reference output pipe for analog IOs (pcmp0/1) - */ -struct mixart_pipe * -snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture, - int monitoring) -{ - int stream_count; - struct mixart_pipe *pipe; - struct mixart_msg request; - - if(capture) { - if (pcm_number == MIXART_PCM_ANALOG) { - pipe = &(chip->pipe_in_ana); /* analog inputs */ - } else { - pipe = &(chip->pipe_in_dig); /* digital inputs */ - } - request.message_id = MSG_STREAM_ADD_OUTPUT_GROUP; - stream_count = MIXART_CAPTURE_STREAMS; - } else { - if (pcm_number == MIXART_PCM_ANALOG) { - pipe = &(chip->pipe_out_ana); /* analog outputs */ - } else { - pipe = &(chip->pipe_out_dig); /* digital outputs */ - } - request.message_id = MSG_STREAM_ADD_INPUT_GROUP; - stream_count = MIXART_PLAYBACK_STREAMS; - } - - /* a new stream is opened and there are already all streams in use */ - if( (monitoring == 0) && (pipe->references >= stream_count) ) { - return NULL; - } - - /* pipe is not yet defined */ - if( pipe->status == PIPE_UNDEFINED ) { - int err, i; - struct { - struct mixart_streaming_group_req sgroup_req; - struct mixart_streaming_group sgroup_resp; - } *buf; - - snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number); - - buf = kmalloc(sizeof(*buf), GFP_KERNEL); - if (!buf) - return NULL; - - request.uid = (struct mixart_uid){0,0}; /* should be StreamManagerUID, but zero is OK if there is only one ! */ - request.data = &buf->sgroup_req; - request.size = sizeof(buf->sgroup_req); - - memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req)); - - buf->sgroup_req.stream_count = stream_count; - buf->sgroup_req.channel_count = 2; - buf->sgroup_req.latency = 256; - buf->sgroup_req.connector = pipe->uid_left_connector; /* the left connector */ - - for (i=0; isgroup_req.stream_info[i].size_max_byte_frame = 1024; - buf->sgroup_req.stream_info[i].size_max_sample_frame = 256; - buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */ - - /* find the right bufferinfo_array */ - j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i; - if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */ - - buf->sgroup_req.flow_entry[i] = j; - - flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area; - flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(struct mixart_bufferinfo)); - flowinfo[j].bufferinfo_count = 1; /* 1 will set the miXart to ring-buffer mode ! */ - - bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area; - bufferinfo[j].buffer_address = 0; /* buffer is not yet allocated */ - bufferinfo[j].available_length = 0; /* buffer is not yet allocated */ - - /* construct the identifier of the stream buffer received in the interrupts ! */ - bufferinfo[j].buffer_id = (chip->chip_idx << MIXART_NOTIFY_CARD_OFFSET) + (pcm_number << MIXART_NOTIFY_PCM_OFFSET ) + i; - if(capture) { - bufferinfo[j].buffer_id |= MIXART_NOTIFY_CAPT_MASK; - } - } - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp); - if((err < 0) || (buf->sgroup_resp.status != 0)) { - snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, buf->sgroup_resp.status); - kfree(buf); - return NULL; - } - - pipe->group_uid = buf->sgroup_resp.group; /* id of the pipe, as returned by embedded */ - pipe->stream_count = buf->sgroup_resp.stream_count; - /* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */ - - pipe->status = PIPE_STOPPED; - kfree(buf); - } - - if(monitoring) pipe->monitoring = 1; - else pipe->references++; - - return pipe; -} - - -int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr, - struct mixart_pipe *pipe, int monitoring) -{ - int err = 0; - - if(pipe->status == PIPE_UNDEFINED) - return 0; - - if(monitoring) - pipe->monitoring = 0; - else - pipe->references--; - - if((pipe->references <= 0) && (pipe->monitoring == 0)) { - - struct mixart_msg request; - struct mixart_delete_group_resp delete_resp; - - /* release the clock */ - err = mixart_set_clock( mgr, pipe, 0); - if( err < 0 ) { - snd_printk(KERN_ERR "mixart_set_clock(0) return error!\n"); - } - - /* stop the pipe */ - err = mixart_set_pipe_state(mgr, pipe, 0); - if( err < 0 ) { - snd_printk(KERN_ERR "error stopping pipe!\n"); - } - - request.message_id = MSG_STREAM_DELETE_GROUP; - request.uid = (struct mixart_uid){0,0}; - request.data = &pipe->group_uid; /* the streaming group ! */ - request.size = sizeof(pipe->group_uid); - - /* delete the pipe */ - err = snd_mixart_send_msg(mgr, &request, sizeof(delete_resp), &delete_resp); - if ((err < 0) || (delete_resp.status != 0)) { - snd_printk(KERN_ERR "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n", err, delete_resp.status); - } - - pipe->group_uid = (struct mixart_uid){0,0}; - pipe->stream_count = 0; - pipe->status = PIPE_UNDEFINED; - } - - return err; -} - -static int mixart_set_stream_state(struct mixart_stream *stream, int start) -{ - struct snd_mixart *chip; - struct mixart_stream_state_req stream_state_req; - struct mixart_msg request; - - if(!stream->substream) - return -EINVAL; - - memset(&stream_state_req, 0, sizeof(stream_state_req)); - stream_state_req.stream_count = 1; - stream_state_req.stream_info.stream_desc.uid_pipe = stream->pipe->group_uid; - stream_state_req.stream_info.stream_desc.stream_idx = stream->substream->number; - - if (stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - request.message_id = start ? MSG_STREAM_START_INPUT_STAGE_PACKET : MSG_STREAM_STOP_INPUT_STAGE_PACKET; - else - request.message_id = start ? MSG_STREAM_START_OUTPUT_STAGE_PACKET : MSG_STREAM_STOP_OUTPUT_STAGE_PACKET; - - request.uid = (struct mixart_uid){0,0}; - request.data = &stream_state_req; - request.size = sizeof(stream_state_req); - - stream->abs_period_elapsed = 0; /* reset stream pos */ - stream->buf_periods = 0; - stream->buf_period_frag = 0; - - chip = snd_pcm_substream_chip(stream->substream); - - return snd_mixart_send_msg_nonblock(chip->mgr, &request); -} - -/* - * Trigger callback - */ - -static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct mixart_stream *stream = subs->runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - - snd_printdd("SNDRV_PCM_TRIGGER_START\n"); - - /* START_STREAM */ - if( mixart_set_stream_state(stream, 1) ) - return -EINVAL; - - stream->status = MIXART_STREAM_STATUS_RUNNING; - - break; - case SNDRV_PCM_TRIGGER_STOP: - - /* STOP_STREAM */ - if( mixart_set_stream_state(stream, 0) ) - return -EINVAL; - - stream->status = MIXART_STREAM_STATUS_OPEN; - - snd_printdd("SNDRV_PCM_TRIGGER_STOP\n"); - - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - /* TODO */ - stream->status = MIXART_STREAM_STATUS_PAUSE; - snd_printdd("SNDRV_PCM_PAUSE_PUSH\n"); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - /* TODO */ - stream->status = MIXART_STREAM_STATUS_RUNNING; - snd_printdd("SNDRV_PCM_PAUSE_RELEASE\n"); - break; - default: - return -EINVAL; - } - return 0; -} - -static int mixart_sync_nonblock_events(struct mixart_mgr *mgr) -{ - unsigned long timeout = jiffies + HZ; - while (atomic_read(&mgr->msg_processed) > 0) { - if (time_after(jiffies, timeout)) { - snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n"); - return -EBUSY; - } - schedule_timeout_uninterruptible(1); - } - return 0; -} - -/* - * prepare callback for all pcms - */ -static int snd_mixart_prepare(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_stream *stream = subs->runtime->private_data; - - /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */ - - snd_printdd("snd_mixart_prepare\n"); - - mixart_sync_nonblock_events(chip->mgr); - - /* only the first stream can choose the sample rate */ - /* the further opened streams will be limited to its frequency (see open) */ - if(chip->mgr->ref_count_rate == 1) - chip->mgr->sample_rate = subs->runtime->rate; - - /* set the clock only once (first stream) on the same pipe */ - if(stream->pipe->references == 1) { - if( mixart_set_clock(chip->mgr, stream->pipe, subs->runtime->rate) ) - return -EINVAL; - } - - return 0; -} - - -static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t format) -{ - int err; - struct snd_mixart *chip; - struct mixart_msg request; - struct mixart_stream_param_desc stream_param; - struct mixart_return_uid resp; - - chip = snd_pcm_substream_chip(stream->substream); - - memset(&stream_param, 0, sizeof(stream_param)); - - stream_param.coding_type = CT_LINEAR; - stream_param.number_of_channel = stream->channels; - - stream_param.sampling_freq = chip->mgr->sample_rate; - if(stream_param.sampling_freq == 0) - stream_param.sampling_freq = 44100; /* if frequency not yet defined, use some default */ - - switch(format){ - case SNDRV_PCM_FORMAT_U8: - stream_param.sample_type = ST_INTEGER_8; - stream_param.sample_size = 8; - break; - case SNDRV_PCM_FORMAT_S16_LE: - stream_param.sample_type = ST_INTEGER_16LE; - stream_param.sample_size = 16; - break; - case SNDRV_PCM_FORMAT_S16_BE: - stream_param.sample_type = ST_INTEGER_16BE; - stream_param.sample_size = 16; - break; - case SNDRV_PCM_FORMAT_S24_3LE: - stream_param.sample_type = ST_INTEGER_24LE; - stream_param.sample_size = 24; - break; - case SNDRV_PCM_FORMAT_S24_3BE: - stream_param.sample_type = ST_INTEGER_24BE; - stream_param.sample_size = 24; - break; - case SNDRV_PCM_FORMAT_FLOAT_LE: - stream_param.sample_type = ST_FLOATING_POINT_32LE; - stream_param.sample_size = 32; - break; - case SNDRV_PCM_FORMAT_FLOAT_BE: - stream_param.sample_type = ST_FLOATING_POINT_32BE; - stream_param.sample_size = 32; - break; - default: - snd_printk(KERN_ERR "error mixart_set_format() : unknown format\n"); - return -EINVAL; - } - - snd_printdd("set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n", - stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels); - - /* TODO: what else to configure ? */ - /* stream_param.samples_per_frame = 2; */ - /* stream_param.bytes_per_frame = 4; */ - /* stream_param.bytes_per_sample = 2; */ - - stream_param.pipe_count = 1; /* set to 1 */ - stream_param.stream_count = 1; /* set to 1 */ - stream_param.stream_desc[0].uid_pipe = stream->pipe->group_uid; - stream_param.stream_desc[0].stream_idx = stream->substream->number; - - request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM; - request.uid = (struct mixart_uid){0,0}; - request.data = &stream_param; - request.size = sizeof(stream_param); - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); - if((err < 0) || resp.error_code) { - snd_printk(KERN_ERR "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n", err, resp.error_code); - return -EINVAL; - } - return 0; -} - - -/* - * HW_PARAMS callback for all pcms - */ -static int snd_mixart_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_mgr *mgr = chip->mgr; - struct mixart_stream *stream = subs->runtime->private_data; - snd_pcm_format_t format; - int err; - int channels; - - /* set up channels */ - channels = params_channels(hw); - - /* set up format for the stream */ - format = params_format(hw); - - mutex_lock(&mgr->setup_mutex); - - /* update the stream levels */ - if( stream->pcm_number <= MIXART_PCM_DIGITAL ) { - int is_aes = stream->pcm_number > MIXART_PCM_ANALOG; - if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) - mixart_update_playback_stream_level(chip, is_aes, subs->number); - else - mixart_update_capture_stream_level( chip, is_aes); - } - - stream->channels = channels; - - /* set the format to the board */ - err = mixart_set_format(stream, format); - if(err < 0) { - mutex_unlock(&mgr->setup_mutex); - return err; - } - - /* allocate buffer */ - err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw)); - - if (err > 0) { - struct mixart_bufferinfo *bufferinfo; - int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number; - if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) { - i += MIXART_PLAYBACK_STREAMS; /* in array capture is behind playback */ - } - - bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area; - bufferinfo[i].buffer_address = subs->runtime->dma_addr; - bufferinfo[i].available_length = subs->runtime->dma_bytes; - /* bufferinfo[i].buffer_id is already defined */ - - snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i, - bufferinfo[i].buffer_address, - bufferinfo[i].available_length, - subs->number); - } - mutex_unlock(&mgr->setup_mutex); - - return err; -} - -static int snd_mixart_hw_free(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - snd_pcm_lib_free_pages(subs); - mixart_sync_nonblock_events(chip->mgr); - return 0; -} - - - -/* - * TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max - */ -static struct snd_pcm_hardware snd_mixart_analog_caps = -{ - .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = ( SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | - SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 256, /* 256 frames U8 mono*/ - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = (32*1024/256), -}; - -static struct snd_pcm_hardware snd_mixart_digital_caps = -{ - .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE), - .formats = ( SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | - SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ), - .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 32000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 256, /* 256 frames U8 mono*/ - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = (32*1024/256), -}; - - -static int snd_mixart_playback_open(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_mgr *mgr = chip->mgr; - struct snd_pcm_runtime *runtime = subs->runtime; - struct snd_pcm *pcm = subs->pcm; - struct mixart_stream *stream; - struct mixart_pipe *pipe; - int err = 0; - int pcm_number; - - mutex_lock(&mgr->setup_mutex); - - if ( pcm == chip->pcm ) { - pcm_number = MIXART_PCM_ANALOG; - runtime->hw = snd_mixart_analog_caps; - } else { - snd_BUG_ON(pcm != chip->pcm_dig); - pcm_number = MIXART_PCM_DIGITAL; - runtime->hw = snd_mixart_digital_caps; - } - snd_printdd("snd_mixart_playback_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number); - - /* get stream info */ - stream = &(chip->playback_stream[pcm_number][subs->number]); - - if (stream->status != MIXART_STREAM_STATUS_FREE){ - /* streams in use */ - snd_printk(KERN_ERR "snd_mixart_playback_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number); - err = -EBUSY; - goto _exit_open; - } - - /* get pipe pointer (out pipe) */ - pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0); - - if (pipe == NULL) { - err = -EINVAL; - goto _exit_open; - } - - /* start the pipe if necessary */ - err = mixart_set_pipe_state(chip->mgr, pipe, 1); - if( err < 0 ) { - snd_printk(KERN_ERR "error starting pipe!\n"); - snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0); - err = -EINVAL; - goto _exit_open; - } - - stream->pipe = pipe; - stream->pcm_number = pcm_number; - stream->status = MIXART_STREAM_STATUS_OPEN; - stream->substream = subs; - stream->channels = 0; /* not configured yet */ - - runtime->private_data = stream; - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64); - - /* if a sample rate is already used, another stream cannot change */ - if(mgr->ref_count_rate++) { - if(mgr->sample_rate) { - runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate; - } - } - - _exit_open: - mutex_unlock(&mgr->setup_mutex); - - return err; -} - - -static int snd_mixart_capture_open(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_mgr *mgr = chip->mgr; - struct snd_pcm_runtime *runtime = subs->runtime; - struct snd_pcm *pcm = subs->pcm; - struct mixart_stream *stream; - struct mixart_pipe *pipe; - int err = 0; - int pcm_number; - - mutex_lock(&mgr->setup_mutex); - - if ( pcm == chip->pcm ) { - pcm_number = MIXART_PCM_ANALOG; - runtime->hw = snd_mixart_analog_caps; - } else { - snd_BUG_ON(pcm != chip->pcm_dig); - pcm_number = MIXART_PCM_DIGITAL; - runtime->hw = snd_mixart_digital_caps; - } - - runtime->hw.channels_min = 2; /* for instance, no mono */ - - snd_printdd("snd_mixart_capture_open C%d/P%d/Sub%d\n", chip->chip_idx, pcm_number, subs->number); - - /* get stream info */ - stream = &(chip->capture_stream[pcm_number]); - - if (stream->status != MIXART_STREAM_STATUS_FREE){ - /* streams in use */ - snd_printk(KERN_ERR "snd_mixart_capture_open C%d/P%d/Sub%d in use\n", chip->chip_idx, pcm_number, subs->number); - err = -EBUSY; - goto _exit_open; - } - - /* get pipe pointer (in pipe) */ - pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0); - - if (pipe == NULL) { - err = -EINVAL; - goto _exit_open; - } - - /* start the pipe if necessary */ - err = mixart_set_pipe_state(chip->mgr, pipe, 1); - if( err < 0 ) { - snd_printk(KERN_ERR "error starting pipe!\n"); - snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0); - err = -EINVAL; - goto _exit_open; - } - - stream->pipe = pipe; - stream->pcm_number = pcm_number; - stream->status = MIXART_STREAM_STATUS_OPEN; - stream->substream = subs; - stream->channels = 0; /* not configured yet */ - - runtime->private_data = stream; - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64); - - /* if a sample rate is already used, another stream cannot change */ - if(mgr->ref_count_rate++) { - if(mgr->sample_rate) { - runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate; - } - } - - _exit_open: - mutex_unlock(&mgr->setup_mutex); - - return err; -} - - - -static int snd_mixart_close(struct snd_pcm_substream *subs) -{ - struct snd_mixart *chip = snd_pcm_substream_chip(subs); - struct mixart_mgr *mgr = chip->mgr; - struct mixart_stream *stream = subs->runtime->private_data; - - mutex_lock(&mgr->setup_mutex); - - snd_printdd("snd_mixart_close C%d/P%d/Sub%d\n", chip->chip_idx, stream->pcm_number, subs->number); - - /* sample rate released */ - if(--mgr->ref_count_rate == 0) { - mgr->sample_rate = 0; - } - - /* delete pipe */ - if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) { - - snd_printk(KERN_ERR "error snd_mixart_kill_ref_pipe C%dP%d\n", chip->chip_idx, stream->pcm_number); - } - - stream->pipe = NULL; - stream->status = MIXART_STREAM_STATUS_FREE; - stream->substream = NULL; - - mutex_unlock(&mgr->setup_mutex); - return 0; -} - - -static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct mixart_stream *stream = runtime->private_data; - - return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag); -} - - - -static struct snd_pcm_ops snd_mixart_playback_ops = { - .open = snd_mixart_playback_open, - .close = snd_mixart_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = snd_mixart_prepare, - .hw_params = snd_mixart_hw_params, - .hw_free = snd_mixart_hw_free, - .trigger = snd_mixart_trigger, - .pointer = snd_mixart_stream_pointer, -}; - -static struct snd_pcm_ops snd_mixart_capture_ops = { - .open = snd_mixart_capture_open, - .close = snd_mixart_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = snd_mixart_prepare, - .hw_params = snd_mixart_hw_params, - .hw_free = snd_mixart_hw_free, - .trigger = snd_mixart_trigger, - .pointer = snd_mixart_stream_pointer, -}; - -static void preallocate_buffers(struct snd_mixart *chip, struct snd_pcm *pcm) -{ -#if 0 - struct snd_pcm_substream *subs; - int stream; - - for (stream = 0; stream < 2; stream++) { - int idx = 0; - for (subs = pcm->streams[stream].substream; subs; subs = subs->next, idx++) - /* set up the unique device id with the chip index */ - subs->dma_device.id = subs->pcm->device << 16 | - subs->stream << 8 | (subs->number + 1) | - (chip->chip_idx + 1) << 24; - } -#endif - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->mgr->pci), 32*1024, 32*1024); -} - -/* - */ -static int snd_mixart_pcm_analog(struct snd_mixart *chip) -{ - int err; - struct snd_pcm *pcm; - char name[32]; - - sprintf(name, "miXart analog %d", chip->chip_idx); - if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG, - MIXART_PLAYBACK_STREAMS, - MIXART_CAPTURE_STREAMS, &pcm)) < 0) { - snd_printk(KERN_ERR "cannot create the analog pcm %d\n", chip->chip_idx); - return err; - } - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, name); - - preallocate_buffers(chip, pcm); - - chip->pcm = pcm; - return 0; -} - - -/* - */ -static int snd_mixart_pcm_digital(struct snd_mixart *chip) -{ - int err; - struct snd_pcm *pcm; - char name[32]; - - sprintf(name, "miXart AES/EBU %d", chip->chip_idx); - if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL, - MIXART_PLAYBACK_STREAMS, - MIXART_CAPTURE_STREAMS, &pcm)) < 0) { - snd_printk(KERN_ERR "cannot create the digital pcm %d\n", chip->chip_idx); - return err; - } - - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, name); - - preallocate_buffers(chip, pcm); - - chip->pcm_dig = pcm; - return 0; -} - -static int snd_mixart_chip_free(struct snd_mixart *chip) -{ - kfree(chip); - return 0; -} - -static int snd_mixart_chip_dev_free(struct snd_device *device) -{ - struct snd_mixart *chip = device->device_data; - return snd_mixart_chip_free(chip); -} - - -/* - */ -static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx) -{ - int err; - struct snd_mixart *chip; - static struct snd_device_ops ops = { - .dev_free = snd_mixart_chip_dev_free, - }; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (! chip) { - snd_printk(KERN_ERR "cannot allocate chip\n"); - return -ENOMEM; - } - - chip->card = card; - chip->chip_idx = idx; - chip->mgr = mgr; - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_mixart_chip_free(chip); - return err; - } - - mgr->chip[idx] = chip; - snd_card_set_dev(card, &mgr->pci->dev); - - return 0; -} - -int snd_mixart_create_pcm(struct snd_mixart* chip) -{ - int err; - - err = snd_mixart_pcm_analog(chip); - if (err < 0) - return err; - - if(chip->mgr->board_type == MIXART_DAUGHTER_TYPE_AES) { - - err = snd_mixart_pcm_digital(chip); - if (err < 0) - return err; - } - return err; -} - - -/* - * release all the cards assigned to a manager instance - */ -static int snd_mixart_free(struct mixart_mgr *mgr) -{ - unsigned int i; - - for (i = 0; i < mgr->num_cards; i++) { - if (mgr->chip[i]) - snd_card_free(mgr->chip[i]->card); - } - - /* stop mailbox */ - snd_mixart_exit_mailbox(mgr); - - /* release irq */ - if (mgr->irq >= 0) - free_irq(mgr->irq, mgr); - - /* reset board if some firmware was loaded */ - if(mgr->dsp_loaded) { - snd_mixart_reset_board(mgr); - snd_printdd("reset miXart !\n"); - } - - /* release the i/o ports */ - for (i = 0; i < 2; i++) { - if (mgr->mem[i].virt) - iounmap(mgr->mem[i].virt); - } - pci_release_regions(mgr->pci); - - /* free flowarray */ - if(mgr->flowinfo.area) { - snd_dma_free_pages(&mgr->flowinfo); - mgr->flowinfo.area = NULL; - } - /* free bufferarray */ - if(mgr->bufferinfo.area) { - snd_dma_free_pages(&mgr->bufferinfo); - mgr->bufferinfo.area = NULL; - } - - pci_disable_device(mgr->pci); - kfree(mgr); - return 0; -} - -/* - * proc interface - */ - -/* - mixart_BA0 proc interface for BAR 0 - read callback - */ -static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct mixart_mgr *mgr = entry->private_data; - - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ - if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) - return -EFAULT; - return count; -} - -/* - mixart_BA1 proc interface for BAR 1 - read callback - */ -static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct mixart_mgr *mgr = entry->private_data; - - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ - if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) - return -EFAULT; - return count; -} - -static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = { - .read = snd_mixart_BA0_read, -}; - -static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = { - .read = snd_mixart_BA1_read, -}; - - -static void snd_mixart_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_mixart *chip = entry->private_data; - u32 ref; - - snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx); - - /* stats available when embedded OS is running */ - if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) { - snd_iprintf(buffer, "- hardware -\n"); - switch (chip->mgr->board_type ) { - case MIXART_DAUGHTER_TYPE_NONE : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break; - case MIXART_DAUGHTER_TYPE_AES : snd_iprintf(buffer, "\tmiXart8 AES/EBU\n\n"); break; - case MIXART_DAUGHTER_TYPE_COBRANET : snd_iprintf(buffer, "\tmiXart8 Cobranet\n\n"); break; - default: snd_iprintf(buffer, "\tUNKNOWN!\n\n"); break; - } - - snd_iprintf(buffer, "- system load -\n"); - - /* get perf reference */ - - ref = readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET)); - - if (ref) { - u32 mailbox = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET)) / ref; - u32 streaming = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET)) / ref; - u32 interr = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET)) / ref; - - snd_iprintf(buffer, "\tstreaming : %d\n", streaming); - snd_iprintf(buffer, "\tmailbox : %d\n", mailbox); - snd_iprintf(buffer, "\tinterrups handling : %d\n\n", interr); - } - } /* endif elf loaded */ -} - -static void __devinit snd_mixart_proc_init(struct snd_mixart *chip) -{ - struct snd_info_entry *entry; - - /* text interface to read perf and temp meters */ - if (! snd_card_proc_new(chip->card, "board_info", &entry)) { - entry->private_data = chip; - entry->c.text.read = snd_mixart_proc_read; - } - - if (! snd_card_proc_new(chip->card, "mixart_BA0", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = chip->mgr; - entry->c.ops = &snd_mixart_proc_ops_BA0; - entry->size = MIXART_BA0_SIZE; - } - if (! snd_card_proc_new(chip->card, "mixart_BA1", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = chip->mgr; - entry->c.ops = &snd_mixart_proc_ops_BA1; - entry->size = MIXART_BA1_SIZE; - } -} -/* end of proc interface */ - - -/* - * probe function - creates the card manager - */ -static int __devinit snd_mixart_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct mixart_mgr *mgr; - unsigned int i; - int err; - size_t size; - - /* - */ - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (! enable[dev]) { - dev++; - return -ENOENT; - } - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - pci_set_master(pci); - - /* check if we can restrict PCI DMA transfers to 32 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - /* - */ - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - if (! mgr) { - pci_disable_device(pci); - return -ENOMEM; - } - - mgr->pci = pci; - mgr->irq = -1; - - /* resource assignment */ - if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { - kfree(mgr); - pci_disable_device(pci); - return err; - } - for (i = 0; i < 2; i++) { - mgr->mem[i].phys = pci_resource_start(pci, i); - mgr->mem[i].virt = pci_ioremap_bar(pci, i); - if (!mgr->mem[i].virt) { - printk(KERN_ERR "unable to remap resource 0x%lx\n", - mgr->mem[i].phys); - snd_mixart_free(mgr); - return -EBUSY; - } - } - - if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, - KBUILD_MODNAME, mgr)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_mixart_free(mgr); - return -EBUSY; - } - mgr->irq = pci->irq; - - sprintf(mgr->shortname, "Digigram miXart"); - sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq); - - /* ISR spinlock */ - spin_lock_init(&mgr->lock); - - /* init mailbox */ - mgr->msg_fifo_readptr = 0; - mgr->msg_fifo_writeptr = 0; - - spin_lock_init(&mgr->msg_lock); - mutex_init(&mgr->msg_mutex); - init_waitqueue_head(&mgr->msg_sleep); - atomic_set(&mgr->msg_processed, 0); - - /* init setup mutex*/ - mutex_init(&mgr->setup_mutex); - - /* init message taslket */ - tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr); - - /* card assignment */ - mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */ - for (i = 0; i < mgr->num_cards; i++) { - struct snd_card *card; - char tmpid[16]; - int idx; - - if (index[dev] < 0) - idx = index[dev]; - else - idx = index[dev] + i; - snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); - err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); - - if (err < 0) { - snd_printk(KERN_ERR "cannot allocate the card %d\n", i); - snd_mixart_free(mgr); - return err; - } - - strcpy(card->driver, CARD_NAME); - sprintf(card->shortname, "%s [PCM #%d]", mgr->shortname, i); - sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); - - if ((err = snd_mixart_create(mgr, card, i)) < 0) { - snd_card_free(card); - snd_mixart_free(mgr); - return err; - } - - if(i==0) { - /* init proc interface only for chip0 */ - snd_mixart_proc_init(mgr->chip[i]); - } - - if ((err = snd_card_register(card)) < 0) { - snd_mixart_free(mgr); - return err; - } - } - - /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */ - mgr->board_type = MIXART_DAUGHTER_TYPE_NONE; - - /* create array of streaminfo */ - size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * - sizeof(struct mixart_flowinfo)) ); - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, &mgr->flowinfo) < 0) { - snd_mixart_free(mgr); - return -ENOMEM; - } - /* init streaminfo_array */ - memset(mgr->flowinfo.area, 0, size); - - /* create array of bufferinfo */ - size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * - sizeof(struct mixart_bufferinfo)) ); - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, &mgr->bufferinfo) < 0) { - snd_mixart_free(mgr); - return -ENOMEM; - } - /* init bufferinfo_array */ - memset(mgr->bufferinfo.area, 0, size); - - /* set up firmware */ - err = snd_mixart_setup_firmware(mgr); - if (err < 0) { - snd_mixart_free(mgr); - return err; - } - - pci_set_drvdata(pci, mgr); - dev++; - return 0; -} - -static void __devexit snd_mixart_remove(struct pci_dev *pci) -{ - snd_mixart_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_mixart_ids, - .probe = snd_mixart_probe, - .remove = __devexit_p(snd_mixart_remove), -}; - -static int __init alsa_card_mixart_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_mixart_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_mixart_init) -module_exit(alsa_card_mixart_exit) diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart.h b/ANDROID_3.4.5/sound/pci/mixart/mixart.h deleted file mode 100644 index 561634d5..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * main header file - * - * Copyright (c) 2003 by Digigram - * - * 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 - */ - -#ifndef __SOUND_MIXART_H -#define __SOUND_MIXART_H - -#include -#include -#include - -#define MIXART_DRIVER_VERSION 0x000100 /* 0.1.0 */ - - -/* - */ - -struct mixart_uid { - u32 object_id; - u32 desc; -}; - -struct mem_area { - unsigned long phys; - void __iomem *virt; - struct resource *res; -}; - - -struct mixart_route { - unsigned char connected; - unsigned char phase_inv; - int volume; -}; - - -/* firmware status codes */ -#define MIXART_MOTHERBOARD_XLX_INDEX 0 -#define MIXART_MOTHERBOARD_ELF_INDEX 1 -#define MIXART_AESEBUBOARD_XLX_INDEX 2 -#define MIXART_HARDW_FILES_MAX_INDEX 3 /* xilinx, elf, AESEBU xilinx */ - -#define MIXART_MAX_CARDS 4 -#define MSG_FIFO_SIZE 16 - -#define MIXART_MAX_PHYS_CONNECTORS (MIXART_MAX_CARDS * 2 * 2) /* 4 * stereo * (analog+digital) */ - -struct mixart_mgr { - unsigned int num_cards; - struct snd_mixart *chip[MIXART_MAX_CARDS]; - - struct pci_dev *pci; - - int irq; - - /* memory-maps */ - struct mem_area mem[2]; - - /* share the name */ - char shortname[32]; /* short name of this soundcard */ - char longname[80]; /* name of this soundcard */ - - /* message tasklet */ - struct tasklet_struct msg_taskq; - - /* one and only blocking message or notification may be pending */ - u32 pending_event; - wait_queue_head_t msg_sleep; - - /* messages stored for tasklet */ - u32 msg_fifo[MSG_FIFO_SIZE]; - int msg_fifo_readptr; - int msg_fifo_writeptr; - atomic_t msg_processed; /* number of messages to be processed in takslet */ - - spinlock_t lock; /* interrupt spinlock */ - spinlock_t msg_lock; /* mailbox spinlock */ - struct mutex msg_mutex; /* mutex for blocking_requests */ - - struct mutex setup_mutex; /* mutex used in hw_params, open and close */ - - /* hardware interface */ - unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ - unsigned int board_type; /* read from embedded once elf file is loaded, 250 = miXart8, 251 = with AES, 252 = with Cobranet */ - - struct snd_dma_buffer flowinfo; - struct snd_dma_buffer bufferinfo; - - struct mixart_uid uid_console_manager; - int sample_rate; - int ref_count_rate; - - struct mutex mixer_mutex; /* mutex for mixer */ - -}; - - -#define MIXART_STREAM_STATUS_FREE 0 -#define MIXART_STREAM_STATUS_OPEN 1 -#define MIXART_STREAM_STATUS_RUNNING 2 -#define MIXART_STREAM_STATUS_DRAINING 3 -#define MIXART_STREAM_STATUS_PAUSE 4 - -#define MIXART_PLAYBACK_STREAMS 4 -#define MIXART_CAPTURE_STREAMS 1 - -#define MIXART_PCM_ANALOG 0 -#define MIXART_PCM_DIGITAL 1 -#define MIXART_PCM_TOTAL 2 - -#define MIXART_MAX_STREAM_PER_CARD (MIXART_PCM_TOTAL * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS) ) - - -#define MIXART_NOTIFY_CARD_MASK 0xF000 -#define MIXART_NOTIFY_CARD_OFFSET 12 -#define MIXART_NOTIFY_PCM_MASK 0x0F00 -#define MIXART_NOTIFY_PCM_OFFSET 8 -#define MIXART_NOTIFY_CAPT_MASK 0x0080 -#define MIXART_NOTIFY_SUBS_MASK 0x007F - - -struct mixart_stream { - struct snd_pcm_substream *substream; - struct mixart_pipe *pipe; - int pcm_number; - - int status; /* nothing, running, draining */ - - u64 abs_period_elapsed; /* last absolute stream position where period_elapsed was called (multiple of runtime->period_size) */ - u32 buf_periods; /* periods counter in the buffer (< runtime->periods) */ - u32 buf_period_frag; /* defines with buf_period_pos the exact position in the buffer (< runtime->period_size) */ - - int channels; -}; - - -enum mixart_pipe_status { - PIPE_UNDEFINED, - PIPE_STOPPED, - PIPE_RUNNING, - PIPE_CLOCK_SET -}; - -struct mixart_pipe { - struct mixart_uid group_uid; /* id of the pipe, as returned by embedded */ - int stream_count; - struct mixart_uid uid_left_connector; /* UID's for the audio connectors */ - struct mixart_uid uid_right_connector; - enum mixart_pipe_status status; - int references; /* number of subs openned */ - int monitoring; /* pipe used for monitoring issue */ -}; - - -struct snd_mixart { - struct snd_card *card; - struct mixart_mgr *mgr; - int chip_idx; /* zero based */ - struct snd_hwdep *hwdep; /* DSP loader, only for the first card */ - - struct snd_pcm *pcm; /* PCM analog i/o */ - struct snd_pcm *pcm_dig; /* PCM digital i/o */ - - /* allocate stereo pipe for instance */ - struct mixart_pipe pipe_in_ana; - struct mixart_pipe pipe_out_ana; - - /* if AES/EBU daughter board is available, additional pipes possible on pcm_dig */ - struct mixart_pipe pipe_in_dig; - struct mixart_pipe pipe_out_dig; - - struct mixart_stream playback_stream[MIXART_PCM_TOTAL][MIXART_PLAYBACK_STREAMS]; /* 0 = pcm, 1 = pcm_dig */ - struct mixart_stream capture_stream[MIXART_PCM_TOTAL]; /* 0 = pcm, 1 = pcm_dig */ - - /* UID's for the physical io's */ - struct mixart_uid uid_out_analog_physio; - struct mixart_uid uid_in_analog_physio; - - int analog_playback_active[2]; /* Mixer : Master Playback active (!mute) */ - int analog_playback_volume[2]; /* Mixer : Master Playback Volume */ - int analog_capture_volume[2]; /* Mixer : Master Capture Volume */ - int digital_playback_active[2*MIXART_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Active [(analog+AES output)*streams][stereo]*/ - int digital_playback_volume[2*MIXART_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Volume [(analog+AES output)*streams][stereo]*/ - int digital_capture_volume[2][2]; /* Mixer : Digital Capture Volume [analog+AES output][stereo] */ - int monitoring_active[2]; /* Mixer : Monitoring Active */ - int monitoring_volume[2]; /* Mixer : Monitoring Volume */ -}; - -struct mixart_bufferinfo -{ - u32 buffer_address; - u32 reserved[5]; - u32 available_length; - u32 buffer_id; -}; - -struct mixart_flowinfo -{ - u32 bufferinfo_array_phy_address; - u32 reserved[11]; - u32 bufferinfo_count; - u32 capture; -}; - -/* exported */ -int snd_mixart_create_pcm(struct snd_mixart * chip); -struct mixart_pipe *snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture, int monitoring); -int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr, struct mixart_pipe *pipe, int monitoring); - -#endif /* __SOUND_MIXART_H */ diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_core.c b/ANDROID_3.4.5/sound/pci/mixart/mixart_core.c deleted file mode 100644 index 3df0f530..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_core.c +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * low level interface with interrupt handling and mail box implementation - * - * Copyright (c) 2003 by Digigram - * - * 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 "mixart.h" -#include "mixart_hwdep.h" -#include "mixart_core.h" - - -#define MSG_TIMEOUT_JIFFIES (400 * HZ) / 1000 /* 400 ms */ - -#define MSG_DESCRIPTOR_SIZE 0x24 -#define MSG_HEADER_SIZE (MSG_DESCRIPTOR_SIZE + 4) - -#define MSG_DEFAULT_SIZE 512 - -#define MSG_TYPE_MASK 0x00000003 /* mask for following types */ -#define MSG_TYPE_NOTIFY 0 /* embedded -> driver (only notification, do not get_msg() !) */ -#define MSG_TYPE_COMMAND 1 /* driver <-> embedded (a command has no answer) */ -#define MSG_TYPE_REQUEST 2 /* driver -> embedded (request will get an answer back) */ -#define MSG_TYPE_ANSWER 3 /* embedded -> driver */ -#define MSG_CANCEL_NOTIFY_MASK 0x80000000 /* this bit is set for a notification that has been canceled */ - - -static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame) -{ - /* read the message frame fifo */ - u32 headptr, tailptr; - - tailptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL)); - headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_HEAD)); - - if (tailptr == headptr) - return 0; /* no message posted */ - - if (tailptr < MSG_OUTBOUND_POST_STACK) - return 0; /* error */ - if (tailptr >= MSG_OUTBOUND_POST_STACK + MSG_BOUND_STACK_SIZE) - return 0; /* error */ - - *msg_frame = readl_be(MIXART_MEM(mgr, tailptr)); - - /* increment the tail index */ - tailptr += 4; - if( tailptr >= (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) ) - tailptr = MSG_OUTBOUND_POST_STACK; - writel_be(tailptr, MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL)); - - return 1; -} - -static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, - u32 msg_frame_address ) -{ - unsigned long flags; - u32 headptr; - u32 size; - int err; -#ifndef __BIG_ENDIAN - unsigned int i; -#endif - - spin_lock_irqsave(&mgr->msg_lock, flags); - err = 0; - - /* copy message descriptor from miXart to driver */ - size = readl_be(MIXART_MEM(mgr, msg_frame_address)); /* size of descriptor + response */ - resp->message_id = readl_be(MIXART_MEM(mgr, msg_frame_address + 4)); /* dwMessageID */ - resp->uid.object_id = readl_be(MIXART_MEM(mgr, msg_frame_address + 8)); /* uidDest */ - resp->uid.desc = readl_be(MIXART_MEM(mgr, msg_frame_address + 12)); /* */ - - if( (size < MSG_DESCRIPTOR_SIZE) || (resp->size < (size - MSG_DESCRIPTOR_SIZE))) { - err = -EINVAL; - snd_printk(KERN_ERR "problem with response size = %d\n", size); - goto _clean_exit; - } - size -= MSG_DESCRIPTOR_SIZE; - - memcpy_fromio(resp->data, MIXART_MEM(mgr, msg_frame_address + MSG_HEADER_SIZE ), size); - resp->size = size; - - /* swap if necessary */ -#ifndef __BIG_ENDIAN - size /= 4; /* u32 size */ - for(i=0; i < size; i++) { - ((u32*)resp->data)[i] = be32_to_cpu(((u32*)resp->data)[i]); - } -#endif - - /* - * free message frame address - */ - headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); - - if( (headptr < MSG_OUTBOUND_FREE_STACK) || ( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) { - err = -EINVAL; - goto _clean_exit; - } - - /* give address back to outbound fifo */ - writel_be(msg_frame_address, MIXART_MEM(mgr, headptr)); - - /* increment the outbound free head */ - headptr += 4; - if( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) ) - headptr = MSG_OUTBOUND_FREE_STACK; - - writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); - - _clean_exit: - spin_unlock_irqrestore(&mgr->msg_lock, flags); - - return err; -} - - -/* - * send a message to miXart. return: the msg_frame used for this message - */ -/* call with mgr->msg_lock held! */ -static int send_msg( struct mixart_mgr *mgr, - struct mixart_msg *msg, - int max_answersize, - int mark_pending, - u32 *msg_event) -{ - u32 headptr, tailptr; - u32 msg_frame_address; - int err, i; - - if (snd_BUG_ON(msg->size % 4)) - return -EINVAL; - - err = 0; - - /* get message frame address */ - tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); - headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD)); - - if (tailptr == headptr) { - snd_printk(KERN_ERR "error: no message frame available\n"); - return -EBUSY; - } - - if( (tailptr < MSG_INBOUND_FREE_STACK) || (tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) { - return -EINVAL; - } - - msg_frame_address = readl_be(MIXART_MEM(mgr, tailptr)); - writel(0, MIXART_MEM(mgr, tailptr)); /* set address to zero on this fifo position */ - - /* increment the inbound free tail */ - tailptr += 4; - if( tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) ) - tailptr = MSG_INBOUND_FREE_STACK; - - writel_be(tailptr, MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL)); - - /* TODO : use memcpy_toio() with intermediate buffer to copy the message */ - - /* copy message descriptor to card memory */ - writel_be( msg->size + MSG_DESCRIPTOR_SIZE, MIXART_MEM(mgr, msg_frame_address) ); /* size of descriptor + request */ - writel_be( msg->message_id , MIXART_MEM(mgr, msg_frame_address + 4) ); /* dwMessageID */ - writel_be( msg->uid.object_id, MIXART_MEM(mgr, msg_frame_address + 8) ); /* uidDest */ - writel_be( msg->uid.desc, MIXART_MEM(mgr, msg_frame_address + 12) ); /* */ - writel_be( MSG_DESCRIPTOR_SIZE, MIXART_MEM(mgr, msg_frame_address + 16) ); /* SizeHeader */ - writel_be( MSG_DESCRIPTOR_SIZE, MIXART_MEM(mgr, msg_frame_address + 20) ); /* OffsetDLL_T16 */ - writel_be( msg->size, MIXART_MEM(mgr, msg_frame_address + 24) ); /* SizeDLL_T16 */ - writel_be( MSG_DESCRIPTOR_SIZE, MIXART_MEM(mgr, msg_frame_address + 28) ); /* OffsetDLL_DRV */ - writel_be( 0, MIXART_MEM(mgr, msg_frame_address + 32) ); /* SizeDLL_DRV */ - writel_be( MSG_DESCRIPTOR_SIZE + max_answersize, MIXART_MEM(mgr, msg_frame_address + 36) ); /* dwExpectedAnswerSize */ - - /* copy message data to card memory */ - for( i=0; i < msg->size; i+=4 ) { - writel_be( *(u32*)(msg->data + i), MIXART_MEM(mgr, MSG_HEADER_SIZE + msg_frame_address + i) ); - } - - if( mark_pending ) { - if( *msg_event ) { - /* the pending event is the notification we wait for ! */ - mgr->pending_event = *msg_event; - } - else { - /* the pending event is the answer we wait for (same address than the request)! */ - mgr->pending_event = msg_frame_address; - - /* copy address back to caller */ - *msg_event = msg_frame_address; - } - } - - /* mark the frame as a request (will have an answer) */ - msg_frame_address |= MSG_TYPE_REQUEST; - - /* post the frame */ - headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD)); - - if( (headptr < MSG_INBOUND_POST_STACK) || (headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE))) { - return -EINVAL; - } - - writel_be(msg_frame_address, MIXART_MEM(mgr, headptr)); - - /* increment the inbound post head */ - headptr += 4; - if( headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) ) - headptr = MSG_INBOUND_POST_STACK; - - writel_be(headptr, MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD)); - - return 0; -} - - -int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data) -{ - struct mixart_msg resp; - u32 msg_frame = 0; /* set to 0, so it's no notification to wait for, but the answer */ - int err; - wait_queue_t wait; - long timeout; - - mutex_lock(&mgr->msg_mutex); - - init_waitqueue_entry(&wait, current); - - spin_lock_irq(&mgr->msg_lock); - /* send the message */ - err = send_msg(mgr, request, max_resp_size, 1, &msg_frame); /* send and mark the answer pending */ - if (err) { - spin_unlock_irq(&mgr->msg_lock); - mutex_unlock(&mgr->msg_mutex); - return err; - } - - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&mgr->msg_sleep, &wait); - spin_unlock_irq(&mgr->msg_lock); - timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); - remove_wait_queue(&mgr->msg_sleep, &wait); - - if (! timeout) { - /* error - no ack */ - mutex_unlock(&mgr->msg_mutex); - snd_printk(KERN_ERR "error: no response on msg %x\n", msg_frame); - return -EIO; - } - - /* retrieve the answer into the same struct mixart_msg */ - resp.message_id = 0; - resp.uid = (struct mixart_uid){0,0}; - resp.data = resp_data; - resp.size = max_resp_size; - - err = get_msg(mgr, &resp, msg_frame); - - if( request->message_id != resp.message_id ) - snd_printk(KERN_ERR "RESPONSE ERROR!\n"); - - mutex_unlock(&mgr->msg_mutex); - return err; -} - - -int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, - struct mixart_msg *request, u32 notif_event) -{ - int err; - wait_queue_t wait; - long timeout; - - if (snd_BUG_ON(!notif_event)) - return -EINVAL; - if (snd_BUG_ON((notif_event & MSG_TYPE_MASK) != MSG_TYPE_NOTIFY)) - return -EINVAL; - if (snd_BUG_ON(notif_event & MSG_CANCEL_NOTIFY_MASK)) - return -EINVAL; - - mutex_lock(&mgr->msg_mutex); - - init_waitqueue_entry(&wait, current); - - spin_lock_irq(&mgr->msg_lock); - /* send the message */ - err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, ¬if_event); /* send and mark the notification event pending */ - if(err) { - spin_unlock_irq(&mgr->msg_lock); - mutex_unlock(&mgr->msg_mutex); - return err; - } - - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&mgr->msg_sleep, &wait); - spin_unlock_irq(&mgr->msg_lock); - timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES); - remove_wait_queue(&mgr->msg_sleep, &wait); - - if (! timeout) { - /* error - no ack */ - mutex_unlock(&mgr->msg_mutex); - snd_printk(KERN_ERR "error: notification %x not received\n", notif_event); - return -EIO; - } - - mutex_unlock(&mgr->msg_mutex); - return 0; -} - - -int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request) -{ - u32 message_frame; - unsigned long flags; - int err; - - /* just send the message (do not mark it as a pending one) */ - spin_lock_irqsave(&mgr->msg_lock, flags); - err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame); - spin_unlock_irqrestore(&mgr->msg_lock, flags); - - /* the answer will be handled by snd_struct mixart_msgasklet() */ - atomic_inc(&mgr->msg_processed); - - return err; -} - - -/* common buffer of tasklet and interrupt to send/receive messages */ -static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4]; - - -void snd_mixart_msg_tasklet(unsigned long arg) -{ - struct mixart_mgr *mgr = ( struct mixart_mgr*)(arg); - struct mixart_msg resp; - u32 msg, addr, type; - int err; - - spin_lock(&mgr->lock); - - while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) { - msg = mgr->msg_fifo[mgr->msg_fifo_readptr]; - mgr->msg_fifo_readptr++; - mgr->msg_fifo_readptr %= MSG_FIFO_SIZE; - - /* process the message ... */ - addr = msg & ~MSG_TYPE_MASK; - type = msg & MSG_TYPE_MASK; - - switch (type) { - case MSG_TYPE_ANSWER: - /* answer to a message on that we did not wait for (send_msg_nonblock) */ - resp.message_id = 0; - resp.data = mixart_msg_data; - resp.size = sizeof(mixart_msg_data); - err = get_msg(mgr, &resp, addr); - if( err < 0 ) { - snd_printk(KERN_ERR "tasklet: error(%d) reading mf %x\n", err, msg); - break; - } - - switch(resp.message_id) { - case MSG_STREAM_START_INPUT_STAGE_PACKET: - case MSG_STREAM_START_OUTPUT_STAGE_PACKET: - case MSG_STREAM_STOP_INPUT_STAGE_PACKET: - case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET: - if(mixart_msg_data[0]) - snd_printk(KERN_ERR "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", mixart_msg_data[0]); - break; - default: - snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n", - msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size); - break; - } - break; - case MSG_TYPE_NOTIFY: - /* msg contains no address ! do not get_msg() ! */ - case MSG_TYPE_COMMAND: - /* get_msg() necessary */ - default: - snd_printk(KERN_ERR "tasklet doesn't know what to do with message %x\n", msg); - } /* switch type */ - - /* decrement counter */ - atomic_dec(&mgr->msg_processed); - - } /* while there is a msg in fifo */ - - spin_unlock(&mgr->lock); -} - - -irqreturn_t snd_mixart_interrupt(int irq, void *dev_id) -{ - struct mixart_mgr *mgr = dev_id; - int err; - struct mixart_msg resp; - - u32 msg; - u32 it_reg; - - spin_lock(&mgr->lock); - - it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET)); - if( !(it_reg & MIXART_OIDI) ) { - /* this device did not cause the interrupt */ - spin_unlock(&mgr->lock); - return IRQ_NONE; - } - - /* mask all interrupts */ - writel_le(MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG(mgr, MIXART_PCI_OMIMR_OFFSET)); - - /* outdoorbell register clear */ - it_reg = readl(MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET)); - writel(it_reg, MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET)); - - /* clear interrupt */ - writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) ); - - /* process interrupt */ - while (retrieve_msg_frame(mgr, &msg)) { - - switch (msg & MSG_TYPE_MASK) { - case MSG_TYPE_COMMAND: - resp.message_id = 0; - resp.data = mixart_msg_data; - resp.size = sizeof(mixart_msg_data); - err = get_msg(mgr, &resp, msg & ~MSG_TYPE_MASK); - if( err < 0 ) { - snd_printk(KERN_ERR "interrupt: error(%d) reading mf %x\n", err, msg); - break; - } - - if(resp.message_id == MSG_SERVICES_TIMER_NOTIFY) { - int i; - struct mixart_timer_notify *notify; - notify = (struct mixart_timer_notify *)mixart_msg_data; - - for(i=0; istream_count; i++) { - - u32 buffer_id = notify->streams[i].buffer_id; - unsigned int chip_number = (buffer_id & MIXART_NOTIFY_CARD_MASK) >> MIXART_NOTIFY_CARD_OFFSET; /* card0 to 3 */ - unsigned int pcm_number = (buffer_id & MIXART_NOTIFY_PCM_MASK ) >> MIXART_NOTIFY_PCM_OFFSET; /* pcm0 to 3 */ - unsigned int sub_number = buffer_id & MIXART_NOTIFY_SUBS_MASK; /* 0 to MIXART_PLAYBACK_STREAMS */ - unsigned int is_capture = ((buffer_id & MIXART_NOTIFY_CAPT_MASK) != 0); /* playback == 0 / capture == 1 */ - - struct snd_mixart *chip = mgr->chip[chip_number]; - struct mixart_stream *stream; - - if ((chip_number >= mgr->num_cards) || (pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) { - snd_printk(KERN_ERR "error MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n", - buffer_id, notify->streams[i].sample_pos_low_part); - break; - } - - if (is_capture) - stream = &chip->capture_stream[pcm_number]; - else - stream = &chip->playback_stream[pcm_number][sub_number]; - - if (stream->substream && (stream->status == MIXART_STREAM_STATUS_RUNNING)) { - struct snd_pcm_runtime *runtime = stream->substream->runtime; - int elapsed = 0; - u64 sample_count = ((u64)notify->streams[i].sample_pos_high_part) << 32; - sample_count |= notify->streams[i].sample_pos_low_part; - - while (1) { - u64 new_elapse_pos = stream->abs_period_elapsed + runtime->period_size; - - if (new_elapse_pos > sample_count) { - break; /* while */ - } - else { - elapsed = 1; - stream->buf_periods++; - if (stream->buf_periods >= runtime->periods) - stream->buf_periods = 0; - - stream->abs_period_elapsed = new_elapse_pos; - } - } - stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed ); - - if(elapsed) { - spin_unlock(&mgr->lock); - snd_pcm_period_elapsed(stream->substream); - spin_lock(&mgr->lock); - } - } - } - break; - } - if(resp.message_id == MSG_SERVICES_REPORT_TRACES) { - if(resp.size > 1) { -#ifndef __BIG_ENDIAN - /* Traces are text: the swapped msg_data has to be swapped back ! */ - int i; - for(i=0; i<(resp.size/4); i++) { - (mixart_msg_data)[i] = cpu_to_be32((mixart_msg_data)[i]); - } -#endif - ((char*)mixart_msg_data)[resp.size - 1] = 0; - snd_printdd("MIXART TRACE : %s\n", (char*)mixart_msg_data); - } - break; - } - - snd_printdd("command %x not handled\n", resp.message_id); - break; - - case MSG_TYPE_NOTIFY: - if(msg & MSG_CANCEL_NOTIFY_MASK) { - msg &= ~MSG_CANCEL_NOTIFY_MASK; - snd_printk(KERN_ERR "canceled notification %x !\n", msg); - } - /* no break, continue ! */ - case MSG_TYPE_ANSWER: - /* answer or notification to a message we are waiting for*/ - spin_lock(&mgr->msg_lock); - if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) { - wake_up(&mgr->msg_sleep); - mgr->pending_event = 0; - } - /* answer to a message we did't want to wait for */ - else { - mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg; - mgr->msg_fifo_writeptr++; - mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE; - tasklet_schedule(&mgr->msg_taskq); - } - spin_unlock(&mgr->msg_lock); - break; - case MSG_TYPE_REQUEST: - default: - snd_printdd("interrupt received request %x\n", msg); - /* TODO : are there things to do here ? */ - break; - } /* switch on msg type */ - } /* while there are msgs */ - - /* allow interrupt again */ - writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); - - spin_unlock(&mgr->lock); - - return IRQ_HANDLED; -} - - -void snd_mixart_init_mailbox(struct mixart_mgr *mgr) -{ - writel( 0, MIXART_MEM( mgr, MSG_HOST_RSC_PROTECTION ) ); - writel( 0, MIXART_MEM( mgr, MSG_AGENT_RSC_PROTECTION ) ); - - /* allow outbound messagebox to generate interrupts */ - if(mgr->irq >= 0) { - writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); - } - return; -} - -void snd_mixart_exit_mailbox(struct mixart_mgr *mgr) -{ - /* no more interrupts on outbound messagebox */ - writel_le( MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET)); - return; -} - -void snd_mixart_reset_board(struct mixart_mgr *mgr) -{ - /* reset miXart */ - writel_be( 1, MIXART_REG(mgr, MIXART_BA1_BRUTAL_RESET_OFFSET) ); - return; -} diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_core.h b/ANDROID_3.4.5/sound/pci/mixart/mixart_core.h deleted file mode 100644 index c919b734..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_core.h +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * low level interface with interrupt handling and mail box implementation - * - * Copyright (c) 2003 by Digigram - * - * 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 - */ - -#ifndef __SOUND_MIXART_CORE_H -#define __SOUND_MIXART_CORE_H - - -enum mixart_message_id { - MSG_CONNECTOR_GET_AUDIO_INFO = 0x050008, - MSG_CONNECTOR_GET_OUT_AUDIO_LEVEL = 0x050009, - MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL = 0x05000A, - - MSG_CONSOLE_MANAGER = 0x070000, - MSG_CONSOLE_GET_CLOCK_UID = 0x070003, - - MSG_PHYSICALIO_SET_LEVEL = 0x0F0008, - - MSG_STREAM_ADD_INPUT_GROUP = 0x130000, - MSG_STREAM_ADD_OUTPUT_GROUP = 0x130001, - MSG_STREAM_DELETE_GROUP = 0x130004, - MSG_STREAM_START_STREAM_GRP_PACKET = 0x130006, - MSG_STREAM_START_INPUT_STAGE_PACKET = 0x130007, - MSG_STREAM_START_OUTPUT_STAGE_PACKET = 0x130008, - MSG_STREAM_STOP_STREAM_GRP_PACKET = 0x130009, - MSG_STREAM_STOP_INPUT_STAGE_PACKET = 0x13000A, - MSG_STREAM_STOP_OUTPUT_STAGE_PACKET = 0x13000B, - MSG_STREAM_SET_INPUT_STAGE_PARAM = 0x13000F, - MSG_STREAM_SET_OUTPUT_STAGE_PARAM = 0x130010, - MSG_STREAM_SET_IN_AUDIO_LEVEL = 0x130015, - MSG_STREAM_SET_OUT_STREAM_LEVEL = 0x130017, - - MSG_SYSTEM_FIRST_ID = 0x160000, - MSG_SYSTEM_ENUM_PHYSICAL_IO = 0x16000E, - MSG_SYSTEM_ENUM_PLAY_CONNECTOR = 0x160017, - MSG_SYSTEM_ENUM_RECORD_CONNECTOR = 0x160018, - MSG_SYSTEM_WAIT_SYNCHRO_CMD = 0x16002C, - MSG_SYSTEM_SEND_SYNCHRO_CMD = 0x16002D, - - MSG_SERVICES_TIMER_NOTIFY = 0x1D0404, - MSG_SERVICES_REPORT_TRACES = 0x1D0700, - - MSG_CLOCK_CHECK_PROPERTIES = 0x200001, - MSG_CLOCK_SET_PROPERTIES = 0x200002, -}; - - -struct mixart_msg -{ - u32 message_id; - struct mixart_uid uid; - void* data; - size_t size; -}; - -/* structs used to communicate with miXart */ - -struct mixart_enum_connector_resp -{ - u32 error_code; - u32 first_uid_offset; - u32 uid_count; - u32 current_uid_index; - struct mixart_uid uid[MIXART_MAX_PHYS_CONNECTORS]; -} __attribute__((packed)); - - -/* used for following struct */ -#define MIXART_FLOAT_P_22_0_TO_HEX 0x41b00000 /* 22.0f */ -#define MIXART_FLOAT_M_20_0_TO_HEX 0xc1a00000 /* -20.0f */ -#define MIXART_FLOAT____0_0_TO_HEX 0x00000000 /* 0.0f */ - -struct mixart_audio_info_req -{ - u32 line_max_level; /* float */ - u32 micro_max_level; /* float */ - u32 cd_max_level; /* float */ -} __attribute__((packed)); - -struct mixart_analog_hw_info -{ - u32 is_present; - u32 hw_connection_type; - u32 max_level; /* float */ - u32 min_var_level; /* float */ - u32 max_var_level; /* float */ - u32 step_var_level; /* float */ - u32 fix_gain; /* float */ - u32 zero_var; /* float */ -} __attribute__((packed)); - -struct mixart_digital_hw_info -{ - u32 hw_connection_type; - u32 presence; - u32 clock; - u32 reserved; -} __attribute__((packed)); - -struct mixart_analog_info -{ - u32 type_mask; - struct mixart_analog_hw_info micro_info; - struct mixart_analog_hw_info line_info; - struct mixart_analog_hw_info cd_info; - u32 analog_level_present; -} __attribute__((packed)); - -struct mixart_digital_info -{ - u32 type_mask; - struct mixart_digital_hw_info aes_info; - struct mixart_digital_hw_info adat_info; -} __attribute__((packed)); - -struct mixart_audio_info -{ - u32 clock_type_mask; - struct mixart_analog_info analog_info; - struct mixart_digital_info digital_info; -} __attribute__((packed)); - -struct mixart_audio_info_resp -{ - u32 txx_status; - struct mixart_audio_info info; -} __attribute__((packed)); - - -/* used for nb_bytes_max_per_sample */ -#define MIXART_FLOAT_P__4_0_TO_HEX 0x40800000 /* +4.0f */ -#define MIXART_FLOAT_P__8_0_TO_HEX 0x41000000 /* +8.0f */ - -struct mixart_stream_info -{ - u32 size_max_byte_frame; - u32 size_max_sample_frame; - u32 nb_bytes_max_per_sample; /* float */ -} __attribute__((packed)); - -/* MSG_STREAM_ADD_INPUT_GROUP */ -/* MSG_STREAM_ADD_OUTPUT_GROUP */ - -struct mixart_streaming_group_req -{ - u32 stream_count; - u32 channel_count; - u32 user_grp_number; - u32 first_phys_audio; - u32 latency; - struct mixart_stream_info stream_info[32]; - struct mixart_uid connector; - u32 flow_entry[32]; -} __attribute__((packed)); - -struct mixart_stream_desc -{ - struct mixart_uid stream_uid; - u32 stream_desc; -} __attribute__((packed)); - -struct mixart_streaming_group -{ - u32 status; - struct mixart_uid group; - u32 pipe_desc; - u32 stream_count; - struct mixart_stream_desc stream[32]; -} __attribute__((packed)); - -/* MSG_STREAM_DELETE_GROUP */ - -/* request : mixart_uid_t group */ - -struct mixart_delete_group_resp -{ - u32 status; - u32 unused[2]; -} __attribute__((packed)); - - -/* MSG_STREAM_START_INPUT_STAGE_PACKET = 0x130000 + 7, - MSG_STREAM_START_OUTPUT_STAGE_PACKET = 0x130000 + 8, - MSG_STREAM_STOP_INPUT_STAGE_PACKET = 0x130000 + 10, - MSG_STREAM_STOP_OUTPUT_STAGE_PACKET = 0x130000 + 11, - */ - -struct mixart_fx_couple_uid -{ - struct mixart_uid uid_fx_code; - struct mixart_uid uid_fx_data; -} __attribute__((packed)); - -struct mixart_txx_stream_desc -{ - struct mixart_uid uid_pipe; - u32 stream_idx; - u32 fx_number; - struct mixart_fx_couple_uid uid_fx[4]; -} __attribute__((packed)); - -struct mixart_flow_info -{ - struct mixart_txx_stream_desc stream_desc; - u32 flow_entry; - u32 flow_phy_addr; -} __attribute__((packed)); - -struct mixart_stream_state_req -{ - u32 delayed; - u64 scheduler; - u32 reserved4np[3]; - u32 stream_count; /* set to 1 for instance */ - struct mixart_flow_info stream_info; /* could be an array[stream_count] */ -} __attribute__((packed)); - -/* MSG_STREAM_START_STREAM_GRP_PACKET = 0x130000 + 6 - MSG_STREAM_STOP_STREAM_GRP_PACKET = 0x130000 + 9 - */ - -struct mixart_group_state_req -{ - u32 delayed; - u64 scheduler; - u32 reserved4np[2]; - u32 pipe_count; /* set to 1 for instance */ - struct mixart_uid pipe_uid[1]; /* could be an array[pipe_count] */ -} __attribute__((packed)); - -struct mixart_group_state_resp -{ - u32 txx_status; - u64 scheduler; -} __attribute__((packed)); - - - -/* Structures used by the MSG_SERVICES_TIMER_NOTIFY command */ - -struct mixart_sample_pos -{ - u32 buffer_id; - u32 validity; - u32 sample_pos_high_part; - u32 sample_pos_low_part; -} __attribute__((packed)); - -struct mixart_timer_notify -{ - u32 stream_count; - struct mixart_sample_pos streams[MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS]; -} __attribute__((packed)); - - -/* MSG_CONSOLE_GET_CLOCK_UID = 0x070003, - */ - -/* request is a uid with desc = MSG_CONSOLE_MANAGER | cardindex */ - -struct mixart_return_uid -{ - u32 error_code; - struct mixart_uid uid; -} __attribute__((packed)); - -/* MSG_CLOCK_CHECK_PROPERTIES = 0x200001, - MSG_CLOCK_SET_PROPERTIES = 0x200002, -*/ - -enum mixart_clock_generic_type { - CGT_NO_CLOCK, - CGT_INTERNAL_CLOCK, - CGT_PROGRAMMABLE_CLOCK, - CGT_INTERNAL_ENSLAVED_CLOCK, - CGT_EXTERNAL_CLOCK, - CGT_CURRENT_CLOCK -}; - -enum mixart_clock_mode { - CM_UNDEFINED, - CM_MASTER, - CM_SLAVE, - CM_STANDALONE, - CM_NOT_CONCERNED -}; - - -struct mixart_clock_properties -{ - u32 error_code; - u32 validation_mask; - u32 frequency; - u32 reference_frequency; - u32 clock_generic_type; - u32 clock_mode; - struct mixart_uid uid_clock_source; - struct mixart_uid uid_event_source; - u32 event_mode; - u32 synchro_signal_presence; - u32 format; - u32 board_mask; - u32 nb_callers; /* set to 1 (see below) */ - struct mixart_uid uid_caller[1]; -} __attribute__((packed)); - -struct mixart_clock_properties_resp -{ - u32 status; - u32 clock_mode; -} __attribute__((packed)); - - -/* MSG_STREAM_SET_INPUT_STAGE_PARAM = 0x13000F */ -/* MSG_STREAM_SET_OUTPUT_STAGE_PARAM = 0x130010 */ - -enum mixart_coding_type { - CT_NOT_DEFINED, - CT_LINEAR, - CT_MPEG_L1, - CT_MPEG_L2, - CT_MPEG_L3, - CT_MPEG_L3_LSF, - CT_GSM -}; -enum mixart_sample_type { - ST_NOT_DEFINED, - ST_FLOATING_POINT_32BE, - ST_FLOATING_POINT_32LE, - ST_FLOATING_POINT_64BE, - ST_FLOATING_POINT_64LE, - ST_FIXED_POINT_8, - ST_FIXED_POINT_16BE, - ST_FIXED_POINT_16LE, - ST_FIXED_POINT_24BE, - ST_FIXED_POINT_24LE, - ST_FIXED_POINT_32BE, - ST_FIXED_POINT_32LE, - ST_INTEGER_8, - ST_INTEGER_16BE, - ST_INTEGER_16LE, - ST_INTEGER_24BE, - ST_INTEGER_24LE, - ST_INTEGER_32BE, - ST_INTEGER_32LE -}; - -struct mixart_stream_param_desc -{ - u32 coding_type; /* use enum mixart_coding_type */ - u32 sample_type; /* use enum mixart_sample_type */ - - union { - struct { - u32 linear_endian_ness; - u32 linear_bits; - u32 is_signed; - u32 is_float; - } linear_format_info; - - struct { - u32 mpeg_layer; - u32 mpeg_mode; - u32 mpeg_mode_extension; - u32 mpeg_pre_emphasis; - u32 mpeg_has_padding_bit; - u32 mpeg_has_crc; - u32 mpeg_has_extension; - u32 mpeg_is_original; - u32 mpeg_has_copyright; - } mpeg_format_info; - } format_info; - - u32 delayed; - u64 scheduler; - u32 sample_size; - u32 has_header; - u32 has_suffix; - u32 has_bitrate; - u32 samples_per_frame; - u32 bytes_per_frame; - u32 bytes_per_sample; - u32 sampling_freq; - u32 number_of_channel; - u32 stream_number; - u32 buffer_size; - u32 differed_time; - u32 reserved4np[3]; - u32 pipe_count; /* set to 1 (array size !) */ - u32 stream_count; /* set to 1 (array size !) */ - struct mixart_txx_stream_desc stream_desc[1]; /* only one stream per command, but this could be an array */ - -} __attribute__((packed)); - - -/* MSG_CONNECTOR_GET_OUT_AUDIO_LEVEL = 0x050009, - */ - - -struct mixart_get_out_audio_level -{ - u32 txx_status; - u32 digital_level; /* float */ - u32 analog_level; /* float */ - u32 monitor_level; /* float */ - u32 mute; - u32 monitor_mute1; - u32 monitor_mute2; -} __attribute__((packed)); - - -/* MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL = 0x05000A, - */ - -/* used for valid_mask below */ -#define MIXART_AUDIO_LEVEL_ANALOG_MASK 0x01 -#define MIXART_AUDIO_LEVEL_DIGITAL_MASK 0x02 -#define MIXART_AUDIO_LEVEL_MONITOR_MASK 0x04 -#define MIXART_AUDIO_LEVEL_MUTE_MASK 0x08 -#define MIXART_AUDIO_LEVEL_MUTE_M1_MASK 0x10 -#define MIXART_AUDIO_LEVEL_MUTE_M2_MASK 0x20 - -struct mixart_set_out_audio_level -{ - u32 delayed; - u64 scheduler; - u32 valid_mask1; - u32 valid_mask2; - u32 digital_level; /* float */ - u32 analog_level; /* float */ - u32 monitor_level; /* float */ - u32 mute; - u32 monitor_mute1; - u32 monitor_mute2; - u32 reserved4np; -} __attribute__((packed)); - - -/* MSG_SYSTEM_ENUM_PHYSICAL_IO = 0x16000E, - */ - -#define MIXART_MAX_PHYS_IO (MIXART_MAX_CARDS * 2 * 2) /* 4 * (analog+digital) * (playback+capture) */ - -struct mixart_uid_enumeration -{ - u32 error_code; - u32 first_uid_offset; - u32 nb_uid; - u32 current_uid_index; - struct mixart_uid uid[MIXART_MAX_PHYS_IO]; -} __attribute__((packed)); - - -/* MSG_PHYSICALIO_SET_LEVEL = 0x0F0008, - MSG_PHYSICALIO_GET_LEVEL = 0x0F000C, -*/ - -struct mixart_io_channel_level -{ - u32 analog_level; /* float */ - u32 unused[2]; -} __attribute__((packed)); - -struct mixart_io_level -{ - s32 channel; /* 0=left, 1=right, -1=both, -2=both same */ - struct mixart_io_channel_level level[2]; -} __attribute__((packed)); - - -/* MSG_STREAM_SET_IN_AUDIO_LEVEL = 0x130015, - */ - -struct mixart_in_audio_level_info -{ - struct mixart_uid connector; - u32 valid_mask1; - u32 valid_mask2; - u32 digital_level; - u32 analog_level; -} __attribute__((packed)); - -struct mixart_set_in_audio_level_req -{ - u32 delayed; - u64 scheduler; - u32 audio_count; /* set to <= 2 */ - u32 reserved4np; - struct mixart_in_audio_level_info level[2]; -} __attribute__((packed)); - -/* response is a 32 bit status */ - - -/* MSG_STREAM_SET_OUT_STREAM_LEVEL = 0x130017, - */ - -/* defines used for valid_mask1 */ -#define MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO1 0x01 -#define MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO2 0x02 -#define MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO1 0x04 -#define MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO2 0x08 -#define MIXART_OUT_STREAM_SET_LEVEL_STREAM_1 0x10 -#define MIXART_OUT_STREAM_SET_LEVEL_STREAM_2 0x20 -#define MIXART_OUT_STREAM_SET_LEVEL_MUTE_1 0x40 -#define MIXART_OUT_STREAM_SET_LEVEL_MUTE_2 0x80 - -struct mixart_out_stream_level_info -{ - u32 valid_mask1; - u32 valid_mask2; - u32 left_to_out1_level; - u32 left_to_out2_level; - u32 right_to_out1_level; - u32 right_to_out2_level; - u32 digital_level1; - u32 digital_level2; - u32 mute1; - u32 mute2; -} __attribute__((packed)); - -struct mixart_set_out_stream_level -{ - struct mixart_txx_stream_desc desc; - struct mixart_out_stream_level_info out_level; -} __attribute__((packed)); - -struct mixart_set_out_stream_level_req -{ - u32 delayed; - u64 scheduler; - u32 reserved4np[2]; - u32 nb_of_stream; /* set to 1 */ - struct mixart_set_out_stream_level stream_level; /* could be an array */ -} __attribute__((packed)); - -/* response to this request is a u32 status value */ - - -/* exported */ -void snd_mixart_init_mailbox(struct mixart_mgr *mgr); -void snd_mixart_exit_mailbox(struct mixart_mgr *mgr); - -int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data); -int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *request, u32 notif_event); -int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request); - -irqreturn_t snd_mixart_interrupt(int irq, void *dev_id); -void snd_mixart_msg_tasklet(unsigned long arg); - -void snd_mixart_reset_board(struct mixart_mgr *mgr); - -#endif /* __SOUND_MIXART_CORE_H */ diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c b/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c deleted file mode 100644 index bfbdc91e..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * DSP firmware management - * - * Copyright (c) 2003 by Digigram - * - * 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 "mixart.h" -#include "mixart_mixer.h" -#include "mixart_core.h" -#include "mixart_hwdep.h" - - -/** - * wait for a value on a peudo register, exit with a timeout - * - * @param mgr pointer to miXart manager structure - * @param offset unsigned pseudo_register base + offset of value - * @param value value - * @param timeout timeout in centisenconds - */ -static int mixart_wait_nice_for_register_value(struct mixart_mgr *mgr, - u32 offset, int is_egal, - u32 value, unsigned long timeout) -{ - unsigned long end_time = jiffies + (timeout * HZ / 100); - u32 read; - - do { /* we may take too long time in this loop. - * so give controls back to kernel if needed. - */ - cond_resched(); - - read = readl_be( MIXART_MEM( mgr, offset )); - if(is_egal) { - if(read == value) return 0; - } - else { /* wait for different value */ - if(read != value) return 0; - } - } while ( time_after_eq(end_time, jiffies) ); - - return -EBUSY; -} - - -/* - structures needed to upload elf code packets - */ -struct snd_mixart_elf32_ehdr { - u8 e_ident[16]; - u16 e_type; - u16 e_machine; - u32 e_version; - u32 e_entry; - u32 e_phoff; - u32 e_shoff; - u32 e_flags; - u16 e_ehsize; - u16 e_phentsize; - u16 e_phnum; - u16 e_shentsize; - u16 e_shnum; - u16 e_shstrndx; -}; - -struct snd_mixart_elf32_phdr { - u32 p_type; - u32 p_offset; - u32 p_vaddr; - u32 p_paddr; - u32 p_filesz; - u32 p_memsz; - u32 p_flags; - u32 p_align; -}; - -static int mixart_load_elf(struct mixart_mgr *mgr, const struct firmware *dsp ) -{ - char elf32_magic_number[4] = {0x7f,'E','L','F'}; - struct snd_mixart_elf32_ehdr *elf_header; - int i; - - elf_header = (struct snd_mixart_elf32_ehdr *)dsp->data; - for( i=0; i<4; i++ ) - if ( elf32_magic_number[i] != elf_header->e_ident[i] ) - return -EINVAL; - - if( elf_header->e_phoff != 0 ) { - struct snd_mixart_elf32_phdr elf_programheader; - - for( i=0; i < be16_to_cpu(elf_header->e_phnum); i++ ) { - u32 pos = be32_to_cpu(elf_header->e_phoff) + (u32)(i * be16_to_cpu(elf_header->e_phentsize)); - - memcpy( &elf_programheader, dsp->data + pos, sizeof(elf_programheader) ); - - if(elf_programheader.p_type != 0) { - if( elf_programheader.p_filesz != 0 ) { - memcpy_toio( MIXART_MEM( mgr, be32_to_cpu(elf_programheader.p_vaddr)), - dsp->data + be32_to_cpu( elf_programheader.p_offset ), - be32_to_cpu( elf_programheader.p_filesz )); - } - } - } - } - return 0; -} - -/* - * get basic information and init miXart - */ - -/* audio IDs for request to the board */ -#define MIXART_FIRST_ANA_AUDIO_ID 0 -#define MIXART_FIRST_DIG_AUDIO_ID 8 - -static int mixart_enum_connectors(struct mixart_mgr *mgr) -{ - u32 k; - int err; - struct mixart_msg request; - struct mixart_enum_connector_resp *connector; - struct mixart_audio_info_req *audio_info_req; - struct mixart_audio_info_resp *audio_info; - - connector = kmalloc(sizeof(*connector), GFP_KERNEL); - audio_info_req = kmalloc(sizeof(*audio_info_req), GFP_KERNEL); - audio_info = kmalloc(sizeof(*audio_info), GFP_KERNEL); - if (! connector || ! audio_info_req || ! audio_info) { - err = -ENOMEM; - goto __error; - } - - audio_info_req->line_max_level = MIXART_FLOAT_P_22_0_TO_HEX; - audio_info_req->micro_max_level = MIXART_FLOAT_M_20_0_TO_HEX; - audio_info_req->cd_max_level = MIXART_FLOAT____0_0_TO_HEX; - - request.message_id = MSG_SYSTEM_ENUM_PLAY_CONNECTOR; - request.uid = (struct mixart_uid){0,0}; /* board num = 0 */ - request.data = NULL; - request.size = 0; - - err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector); - if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PLAY_CONNECTOR\n"); - err = -EINVAL; - goto __error; - } - - for(k=0; k < connector->uid_count; k++) { - struct mixart_pipe *pipe; - - if(k < MIXART_FIRST_DIG_AUDIO_ID) { - pipe = &mgr->chip[k/2]->pipe_out_ana; - } else { - pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_out_dig; - } - if(k & 1) { - pipe->uid_right_connector = connector->uid[k]; /* odd */ - } else { - pipe->uid_left_connector = connector->uid[k]; /* even */ - } - - /* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ - - /* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */ - request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO; - request.uid = connector->uid[k]; - request.data = audio_info_req; - request.size = sizeof(*audio_info_req); - - err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info); - if( err < 0 ) { - snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); - goto __error; - } - /*snd_printk(KERN_DEBUG "play analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ - } - - request.message_id = MSG_SYSTEM_ENUM_RECORD_CONNECTOR; - request.uid = (struct mixart_uid){0,0}; /* board num = 0 */ - request.data = NULL; - request.size = 0; - - err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector); - if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_RECORD_CONNECTOR\n"); - err = -EINVAL; - goto __error; - } - - for(k=0; k < connector->uid_count; k++) { - struct mixart_pipe *pipe; - - if(k < MIXART_FIRST_DIG_AUDIO_ID) { - pipe = &mgr->chip[k/2]->pipe_in_ana; - } else { - pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_in_dig; - } - if(k & 1) { - pipe->uid_right_connector = connector->uid[k]; /* odd */ - } else { - pipe->uid_left_connector = connector->uid[k]; /* even */ - } - - /* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ - - /* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */ - request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO; - request.uid = connector->uid[k]; - request.data = audio_info_req; - request.size = sizeof(*audio_info_req); - - err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info); - if( err < 0 ) { - snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); - goto __error; - } - /*snd_printk(KERN_DEBUG "rec analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ - } - err = 0; - - __error: - kfree(connector); - kfree(audio_info_req); - kfree(audio_info); - - return err; -} - -static int mixart_enum_physio(struct mixart_mgr *mgr) -{ - u32 k; - int err; - struct mixart_msg request; - struct mixart_uid get_console_mgr; - struct mixart_return_uid console_mgr; - struct mixart_uid_enumeration phys_io; - - /* get the uid for the console manager */ - get_console_mgr.object_id = 0; - get_console_mgr.desc = MSG_CONSOLE_MANAGER | 0; /* cardindex = 0 */ - - request.message_id = MSG_CONSOLE_GET_CLOCK_UID; - request.uid = get_console_mgr; - request.data = &get_console_mgr; - request.size = sizeof(get_console_mgr); - - err = snd_mixart_send_msg(mgr, &request, sizeof(console_mgr), &console_mgr); - - if( (err < 0) || (console_mgr.error_code != 0) ) { - snd_printk(KERN_DEBUG "error MSG_CONSOLE_GET_CLOCK_UID : err=%x\n", console_mgr.error_code); - return -EINVAL; - } - - /* used later for clock issues ! */ - mgr->uid_console_manager = console_mgr.uid; - - request.message_id = MSG_SYSTEM_ENUM_PHYSICAL_IO; - request.uid = (struct mixart_uid){0,0}; - request.data = &console_mgr.uid; - request.size = sizeof(console_mgr.uid); - - err = snd_mixart_send_msg(mgr, &request, sizeof(phys_io), &phys_io); - if( (err < 0) || ( phys_io.error_code != 0 ) ) { - snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PHYSICAL_IO err(%x) error_code(%x)\n", err, phys_io.error_code ); - return -EINVAL; - } - - /* min 2 phys io per card (analog in + analog out) */ - if (phys_io.nb_uid < MIXART_MAX_CARDS * 2) - return -EINVAL; - - for(k=0; knum_cards; k++) { - mgr->chip[k]->uid_in_analog_physio = phys_io.uid[k]; - mgr->chip[k]->uid_out_analog_physio = phys_io.uid[phys_io.nb_uid/2 + k]; - } - - return 0; -} - - -static int mixart_first_init(struct mixart_mgr *mgr) -{ - u32 k; - int err; - struct mixart_msg request; - - if((err = mixart_enum_connectors(mgr)) < 0) return err; - - if((err = mixart_enum_physio(mgr)) < 0) return err; - - /* send a synchro command to card (necessary to do this before first MSG_STREAM_START_STREAM_GRP_PACKET) */ - /* though why not here */ - request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD; - request.uid = (struct mixart_uid){0,0}; - request.data = NULL; - request.size = 0; - /* this command has no data. response is a 32 bit status */ - err = snd_mixart_send_msg(mgr, &request, sizeof(k), &k); - if( (err < 0) || (k != 0) ) { - snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD\n"); - return err == 0 ? -EINVAL : err; - } - - return 0; -} - - -/* firmware base addresses (when hard coded) */ -#define MIXART_MOTHERBOARD_XLX_BASE_ADDRESS 0x00600000 - -static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmware *dsp) -{ - int err, card_index; - u32 status_xilinx, status_elf, status_daught; - u32 val; - - /* read motherboard xilinx status */ - status_xilinx = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); - /* read elf status */ - status_elf = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); - /* read daughterboard xilinx status */ - status_daught = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); - - /* motherboard xilinx status 5 will say that the board is performing a reset */ - if (status_xilinx == 5) { - snd_printk(KERN_ERR "miXart is resetting !\n"); - return -EAGAIN; /* try again later */ - } - - switch (index) { - case MIXART_MOTHERBOARD_XLX_INDEX: - - /* xilinx already loaded ? */ - if (status_xilinx == 4) { - snd_printk(KERN_DEBUG "xilinx is already loaded !\n"); - return 0; - } - /* the status should be 0 == "idle" */ - if (status_xilinx != 0) { - snd_printk(KERN_ERR "xilinx load error ! status = %d\n", - status_xilinx); - return -EIO; /* modprob -r may help ? */ - } - - /* check xilinx validity */ - if (((u32*)(dsp->data))[0] == 0xffffffff) - return -EINVAL; - if (dsp->size % 4) - return -EINVAL; - - /* set xilinx status to copying */ - writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); - - /* setup xilinx base address */ - writel_be( MIXART_MOTHERBOARD_XLX_BASE_ADDRESS, MIXART_MEM( mgr,MIXART_PSEUDOREG_MXLX_BASE_ADDR_OFFSET )); - /* setup code size for xilinx file */ - writel_be( dsp->size, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_SIZE_OFFSET )); - - /* copy xilinx code */ - memcpy_toio( MIXART_MEM( mgr, MIXART_MOTHERBOARD_XLX_BASE_ADDRESS), dsp->data, dsp->size); - - /* set xilinx status to copy finished */ - writel_be( 2, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); - - /* return, because no further processing needed */ - return 0; - - case MIXART_MOTHERBOARD_ELF_INDEX: - - if (status_elf == 4) { - snd_printk(KERN_DEBUG "elf file already loaded !\n"); - return 0; - } - - /* the status should be 0 == "idle" */ - if (status_elf != 0) { - snd_printk(KERN_ERR "elf load error ! status = %d\n", - status_elf); - return -EIO; /* modprob -r may help ? */ - } - - /* wait for xilinx status == 4 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */ - if (err < 0) { - snd_printk(KERN_ERR "xilinx was not loaded or " - "could not be started\n"); - return err; - } - - /* init some data on the card */ - writel_be( 0, MIXART_MEM( mgr, MIXART_PSEUDOREG_BOARDNUMBER ) ); /* set miXart boardnumber to 0 */ - writel_be( 0, MIXART_MEM( mgr, MIXART_FLOWTABLE_PTR ) ); /* reset pointer to flow table on miXart */ - - /* set elf status to copying */ - writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); - - /* process the copying of the elf packets */ - err = mixart_load_elf( mgr, dsp ); - if (err < 0) return err; - - /* set elf status to copy finished */ - writel_be( 2, MIXART_MEM( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); - - /* wait for elf status == 4 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */ - if (err < 0) { - snd_printk(KERN_ERR "elf could not be started\n"); - return err; - } - - /* miXart waits at this point on the pointer to the flow table */ - writel_be( (u32)mgr->flowinfo.addr, MIXART_MEM( mgr, MIXART_FLOWTABLE_PTR ) ); /* give pointer of flow table to miXart */ - - return 0; /* return, another xilinx file has to be loaded before */ - - case MIXART_AESEBUBOARD_XLX_INDEX: - default: - - /* elf and xilinx should be loaded */ - if (status_elf != 4 || status_xilinx != 4) { - printk(KERN_ERR "xilinx or elf not " - "successfully loaded\n"); - return -EIO; /* modprob -r may help ? */ - } - - /* wait for daughter detection != 0 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */ - if (err < 0) { - snd_printk(KERN_ERR "error starting elf file\n"); - return err; - } - - /* the board type can now be retrieved */ - mgr->board_type = (DAUGHTER_TYPE_MASK & readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DBRD_TYPE_OFFSET))); - - if (mgr->board_type == MIXART_DAUGHTER_TYPE_NONE) - break; /* no daughter board; the file does not have to be loaded, continue after the switch */ - - /* only if aesebu daughter board presence (elf code must run) */ - if (mgr->board_type != MIXART_DAUGHTER_TYPE_AES ) - return -EINVAL; - - /* daughter should be idle */ - if (status_daught != 0) { - printk(KERN_ERR "daughter load error ! status = %d\n", - status_daught); - return -EIO; /* modprob -r may help ? */ - } - - /* check daughterboard xilinx validity */ - if (((u32*)(dsp->data))[0] == 0xffffffff) - return -EINVAL; - if (dsp->size % 4) - return -EINVAL; - - /* inform mixart about the size of the file */ - writel_be( dsp->size, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_SIZE_OFFSET )); - - /* set daughterboard status to 1 */ - writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); - - /* wait for status == 2 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */ - if (err < 0) { - snd_printk(KERN_ERR "daughter board load error\n"); - return err; - } - - /* get the address where to write the file */ - val = readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_BASE_ADDR_OFFSET )); - if (!val) - return -EINVAL; - - /* copy daughterboard xilinx code */ - memcpy_toio( MIXART_MEM( mgr, val), dsp->data, dsp->size); - - /* set daughterboard status to 4 */ - writel_be( 4, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); - - /* continue with init */ - break; - } /* end of switch file index*/ - - /* wait for daughter status == 3 */ - err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */ - if (err < 0) { - snd_printk(KERN_ERR - "daughter board could not be initialised\n"); - return err; - } - - /* init mailbox (communication with embedded) */ - snd_mixart_init_mailbox(mgr); - - /* first communication with embedded */ - err = mixart_first_init(mgr); - if (err < 0) { - snd_printk(KERN_ERR "miXart could not be set up\n"); - return err; - } - - /* create devices and mixer in accordance with HW options*/ - for (card_index = 0; card_index < mgr->num_cards; card_index++) { - struct snd_mixart *chip = mgr->chip[card_index]; - - if ((err = snd_mixart_create_pcm(chip)) < 0) - return err; - - if (card_index == 0) { - if ((err = snd_mixart_create_mixer(chip->mgr)) < 0) - return err; - } - - if ((err = snd_card_register(chip->card)) < 0) - return err; - }; - - snd_printdd("miXart firmware downloaded and successfully set up\n"); - - return 0; -} - - -#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) -#if !defined(CONFIG_USE_MIXARTLOADER) && !defined(CONFIG_SND_MIXART) /* built-in kernel */ -#define SND_MIXART_FW_LOADER /* use the standard firmware loader */ -#endif -#endif - -#ifdef SND_MIXART_FW_LOADER - -int snd_mixart_setup_firmware(struct mixart_mgr *mgr) -{ - static char *fw_files[3] = { - "miXart8.xlx", "miXart8.elf", "miXart8AES.xlx" - }; - char path[32]; - - const struct firmware *fw_entry; - int i, err; - - for (i = 0; i < 3; i++) { - sprintf(path, "mixart/%s", fw_files[i]); - if (request_firmware(&fw_entry, path, &mgr->pci->dev)) { - snd_printk(KERN_ERR "miXart: can't load firmware %s\n", path); - return -ENOENT; - } - /* fake hwdep dsp record */ - err = mixart_dsp_load(mgr, i, fw_entry); - release_firmware(fw_entry); - if (err < 0) - return err; - mgr->dsp_loaded |= 1 << i; - } - return 0; -} - -MODULE_FIRMWARE("mixart/miXart8.xlx"); -MODULE_FIRMWARE("mixart/miXart8.elf"); -MODULE_FIRMWARE("mixart/miXart8AES.xlx"); - -#else /* old style firmware loading */ - -/* miXart hwdep interface id string */ -#define SND_MIXART_HWDEP_ID "miXart Loader" - -static int mixart_hwdep_dsp_status(struct snd_hwdep *hw, - struct snd_hwdep_dsp_status *info) -{ - struct mixart_mgr *mgr = hw->private_data; - - strcpy(info->id, "miXart"); - info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX; - - if (mgr->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX)) - info->chip_ready = 1; - - info->version = MIXART_DRIVER_VERSION; - return 0; -} - -static int mixart_hwdep_dsp_load(struct snd_hwdep *hw, - struct snd_hwdep_dsp_image *dsp) -{ - struct mixart_mgr* mgr = hw->private_data; - struct firmware fw; - int err; - - fw.size = dsp->length; - fw.data = vmalloc(dsp->length); - if (! fw.data) { - snd_printk(KERN_ERR "miXart: cannot allocate image size %d\n", - (int)dsp->length); - return -ENOMEM; - } - if (copy_from_user((void *) fw.data, dsp->image, dsp->length)) { - vfree(fw.data); - return -EFAULT; - } - err = mixart_dsp_load(mgr, dsp->index, &fw); - vfree(fw.data); - if (err < 0) - return err; - mgr->dsp_loaded |= 1 << dsp->index; - return err; -} - -int snd_mixart_setup_firmware(struct mixart_mgr *mgr) -{ - int err; - struct snd_hwdep *hw; - - /* only create hwdep interface for first cardX (see "index" module parameter)*/ - if ((err = snd_hwdep_new(mgr->chip[0]->card, SND_MIXART_HWDEP_ID, 0, &hw)) < 0) - return err; - - hw->iface = SNDRV_HWDEP_IFACE_MIXART; - hw->private_data = mgr; - hw->ops.dsp_status = mixart_hwdep_dsp_status; - hw->ops.dsp_load = mixart_hwdep_dsp_load; - hw->exclusive = 1; - sprintf(hw->name, SND_MIXART_HWDEP_ID); - mgr->dsp_loaded = 0; - - return snd_card_register(mgr->chip[0]->card); -} - -#endif /* SND_MIXART_FW_LOADER */ diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h b/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h deleted file mode 100644 index 812e288e..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_hwdep.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * definitions and makros for basic card access - * - * Copyright (c) 2003 by Digigram - * - * 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 - */ - -#ifndef __SOUND_MIXART_HWDEP_H -#define __SOUND_MIXART_HWDEP_H - -#include - -#ifndef readl_be -#define readl_be(x) be32_to_cpu(__raw_readl(x)) -#endif - -#ifndef writel_be -#define writel_be(data,addr) __raw_writel(cpu_to_be32(data),addr) -#endif - -#ifndef readl_le -#define readl_le(x) le32_to_cpu(__raw_readl(x)) -#endif - -#ifndef writel_le -#define writel_le(data,addr) __raw_writel(cpu_to_le32(data),addr) -#endif - -#define MIXART_MEM(mgr,x) ((mgr)->mem[0].virt + (x)) -#define MIXART_REG(mgr,x) ((mgr)->mem[1].virt + (x)) - - -/* Daughter board Type */ -#define DAUGHTER_TYPE_MASK 0x0F -#define DAUGHTER_VER_MASK 0xF0 -#define DAUGHTER_TYPEVER_MASK (DAUGHTER_TYPE_MASK|DAUGHTER_VER_MASK) - -#define MIXART_DAUGHTER_TYPE_NONE 0x00 -#define MIXART_DAUGHTER_TYPE_COBRANET 0x08 -#define MIXART_DAUGHTER_TYPE_AES 0x0E - - - -#define MIXART_BA0_SIZE (16 * 1024 * 1024) /* 16M */ -#define MIXART_BA1_SIZE (4 * 1024) /* 4k */ - -/* - * -----------BAR 0 -------------------------------------------------------------------------------------------------------- - */ -#define MIXART_PSEUDOREG 0x2000 /* base address for pseudoregister */ - -#define MIXART_PSEUDOREG_BOARDNUMBER MIXART_PSEUDOREG+0 /* board number */ - -/* perfmeter (available when elf loaded)*/ -#define MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET MIXART_PSEUDOREG+0x70 /* streaming load */ -#define MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET MIXART_PSEUDOREG+0x78 /* system load (reference)*/ -#define MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET MIXART_PSEUDOREG+0x7C /* mailbox load */ -#define MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET MIXART_PSEUDOREG+0x74 /* interrupt handling load */ - -/* motherboard xilinx loader info */ -#define MIXART_PSEUDOREG_MXLX_BASE_ADDR_OFFSET MIXART_PSEUDOREG+0x9C /* 0x00600000 */ -#define MIXART_PSEUDOREG_MXLX_SIZE_OFFSET MIXART_PSEUDOREG+0xA0 /* xilinx size in bytes */ -#define MIXART_PSEUDOREG_MXLX_STATUS_OFFSET MIXART_PSEUDOREG+0xA4 /* status = EMBEBBED_STAT_XXX */ - -/* elf loader info */ -#define MIXART_PSEUDOREG_ELF_STATUS_OFFSET MIXART_PSEUDOREG+0xB0 /* status = EMBEBBED_STAT_XXX */ - -/* -* after the elf code is loaded, and the flowtable info was passed to it, -* the driver polls on this address, until it shows 1 (presence) or 2 (absence) -* once it is non-zero, the daughter board type may be read -*/ -#define MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET MIXART_PSEUDOREG+0x990 - -/* Global info structure */ -#define MIXART_PSEUDOREG_DBRD_TYPE_OFFSET MIXART_PSEUDOREG+0x994 /* Type and version of daughterboard */ - - -/* daughterboard xilinx loader info */ -#define MIXART_PSEUDOREG_DXLX_BASE_ADDR_OFFSET MIXART_PSEUDOREG+0x998 /* get the address here where to write the file */ -#define MIXART_PSEUDOREG_DXLX_SIZE_OFFSET MIXART_PSEUDOREG+0x99C /* xilinx size in bytes */ -#define MIXART_PSEUDOREG_DXLX_STATUS_OFFSET MIXART_PSEUDOREG+0x9A0 /* status = EMBEBBED_STAT_XXX */ - -/* */ -#define MIXART_FLOWTABLE_PTR 0x3000 /* pointer to flow table */ - -/* mailbox addresses */ - -/* message DRV -> EMB */ -#define MSG_INBOUND_POST_HEAD 0x010008 /* DRV posts MF + increment4 */ -#define MSG_INBOUND_POST_TAIL 0x01000C /* EMB gets MF + increment4 */ -/* message EMB -> DRV */ -#define MSG_OUTBOUND_POST_TAIL 0x01001C /* DRV gets MF + increment4 */ -#define MSG_OUTBOUND_POST_HEAD 0x010018 /* EMB posts MF + increment4 */ -/* Get Free Frames */ -#define MSG_INBOUND_FREE_TAIL 0x010004 /* DRV gets MFA + increment4 */ -#define MSG_OUTBOUND_FREE_TAIL 0x010014 /* EMB gets MFA + increment4 */ -/* Put Free Frames */ -#define MSG_OUTBOUND_FREE_HEAD 0x010010 /* DRV puts MFA + increment4 */ -#define MSG_INBOUND_FREE_HEAD 0x010000 /* EMB puts MFA + increment4 */ - -/* firmware addresses of the message fifos */ -#define MSG_BOUND_STACK_SIZE 0x004000 /* size of each following stack */ -/* posted messages */ -#define MSG_OUTBOUND_POST_STACK 0x108000 /* stack of messages to the DRV */ -#define MSG_INBOUND_POST_STACK 0x104000 /* stack of messages to the EMB */ -/* available empty messages */ -#define MSG_OUTBOUND_FREE_STACK 0x10C000 /* stack of free enveloped for EMB */ -#define MSG_INBOUND_FREE_STACK 0x100000 /* stack of free enveloped for DRV */ - - -/* defines for mailbox message frames */ -#define MSG_FRAME_OFFSET 0x64 -#define MSG_FRAME_SIZE 0x6400 -#define MSG_FRAME_NUMBER 32 -#define MSG_FROM_AGENT_ITMF_OFFSET (MSG_FRAME_OFFSET + (MSG_FRAME_SIZE * MSG_FRAME_NUMBER)) -#define MSG_TO_AGENT_ITMF_OFFSET (MSG_FROM_AGENT_ITMF_OFFSET + MSG_FRAME_SIZE) -#define MSG_HOST_RSC_PROTECTION (MSG_TO_AGENT_ITMF_OFFSET + MSG_FRAME_SIZE) -#define MSG_AGENT_RSC_PROTECTION (MSG_HOST_RSC_PROTECTION + 4) - - -/* - * -----------BAR 1 -------------------------------------------------------------------------------------------------------- - */ - -/* interrupt addresses and constants */ -#define MIXART_PCI_OMIMR_OFFSET 0x34 /* outbound message interrupt mask register */ -#define MIXART_PCI_OMISR_OFFSET 0x30 /* outbound message interrupt status register */ -#define MIXART_PCI_ODBR_OFFSET 0x60 /* outbound doorbell register */ - -#define MIXART_BA1_BRUTAL_RESET_OFFSET 0x68 /* write 1 in LSBit to reset board */ - -#define MIXART_HOST_ALL_INTERRUPT_MASKED 0x02B /* 0000 0010 1011 */ -#define MIXART_ALLOW_OUTBOUND_DOORBELL 0x023 /* 0000 0010 0011 */ -#define MIXART_OIDI 0x008 /* 0000 0000 1000 */ - - -int snd_mixart_setup_firmware(struct mixart_mgr *mgr); - -#endif /* __SOUND_MIXART_HWDEP_H */ diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c b/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c deleted file mode 100644 index 3ba6174c..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * mixer callbacks - * - * Copyright (c) 2003 by Digigram - * - * 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 "mixart.h" -#include "mixart_core.h" -#include "mixart_hwdep.h" -#include -#include -#include "mixart_mixer.h" - -static u32 mixart_analog_level[256] = { - 0xc2c00000, /* [000] -96.0 dB */ - 0xc2bf0000, /* [001] -95.5 dB */ - 0xc2be0000, /* [002] -95.0 dB */ - 0xc2bd0000, /* [003] -94.5 dB */ - 0xc2bc0000, /* [004] -94.0 dB */ - 0xc2bb0000, /* [005] -93.5 dB */ - 0xc2ba0000, /* [006] -93.0 dB */ - 0xc2b90000, /* [007] -92.5 dB */ - 0xc2b80000, /* [008] -92.0 dB */ - 0xc2b70000, /* [009] -91.5 dB */ - 0xc2b60000, /* [010] -91.0 dB */ - 0xc2b50000, /* [011] -90.5 dB */ - 0xc2b40000, /* [012] -90.0 dB */ - 0xc2b30000, /* [013] -89.5 dB */ - 0xc2b20000, /* [014] -89.0 dB */ - 0xc2b10000, /* [015] -88.5 dB */ - 0xc2b00000, /* [016] -88.0 dB */ - 0xc2af0000, /* [017] -87.5 dB */ - 0xc2ae0000, /* [018] -87.0 dB */ - 0xc2ad0000, /* [019] -86.5 dB */ - 0xc2ac0000, /* [020] -86.0 dB */ - 0xc2ab0000, /* [021] -85.5 dB */ - 0xc2aa0000, /* [022] -85.0 dB */ - 0xc2a90000, /* [023] -84.5 dB */ - 0xc2a80000, /* [024] -84.0 dB */ - 0xc2a70000, /* [025] -83.5 dB */ - 0xc2a60000, /* [026] -83.0 dB */ - 0xc2a50000, /* [027] -82.5 dB */ - 0xc2a40000, /* [028] -82.0 dB */ - 0xc2a30000, /* [029] -81.5 dB */ - 0xc2a20000, /* [030] -81.0 dB */ - 0xc2a10000, /* [031] -80.5 dB */ - 0xc2a00000, /* [032] -80.0 dB */ - 0xc29f0000, /* [033] -79.5 dB */ - 0xc29e0000, /* [034] -79.0 dB */ - 0xc29d0000, /* [035] -78.5 dB */ - 0xc29c0000, /* [036] -78.0 dB */ - 0xc29b0000, /* [037] -77.5 dB */ - 0xc29a0000, /* [038] -77.0 dB */ - 0xc2990000, /* [039] -76.5 dB */ - 0xc2980000, /* [040] -76.0 dB */ - 0xc2970000, /* [041] -75.5 dB */ - 0xc2960000, /* [042] -75.0 dB */ - 0xc2950000, /* [043] -74.5 dB */ - 0xc2940000, /* [044] -74.0 dB */ - 0xc2930000, /* [045] -73.5 dB */ - 0xc2920000, /* [046] -73.0 dB */ - 0xc2910000, /* [047] -72.5 dB */ - 0xc2900000, /* [048] -72.0 dB */ - 0xc28f0000, /* [049] -71.5 dB */ - 0xc28e0000, /* [050] -71.0 dB */ - 0xc28d0000, /* [051] -70.5 dB */ - 0xc28c0000, /* [052] -70.0 dB */ - 0xc28b0000, /* [053] -69.5 dB */ - 0xc28a0000, /* [054] -69.0 dB */ - 0xc2890000, /* [055] -68.5 dB */ - 0xc2880000, /* [056] -68.0 dB */ - 0xc2870000, /* [057] -67.5 dB */ - 0xc2860000, /* [058] -67.0 dB */ - 0xc2850000, /* [059] -66.5 dB */ - 0xc2840000, /* [060] -66.0 dB */ - 0xc2830000, /* [061] -65.5 dB */ - 0xc2820000, /* [062] -65.0 dB */ - 0xc2810000, /* [063] -64.5 dB */ - 0xc2800000, /* [064] -64.0 dB */ - 0xc27e0000, /* [065] -63.5 dB */ - 0xc27c0000, /* [066] -63.0 dB */ - 0xc27a0000, /* [067] -62.5 dB */ - 0xc2780000, /* [068] -62.0 dB */ - 0xc2760000, /* [069] -61.5 dB */ - 0xc2740000, /* [070] -61.0 dB */ - 0xc2720000, /* [071] -60.5 dB */ - 0xc2700000, /* [072] -60.0 dB */ - 0xc26e0000, /* [073] -59.5 dB */ - 0xc26c0000, /* [074] -59.0 dB */ - 0xc26a0000, /* [075] -58.5 dB */ - 0xc2680000, /* [076] -58.0 dB */ - 0xc2660000, /* [077] -57.5 dB */ - 0xc2640000, /* [078] -57.0 dB */ - 0xc2620000, /* [079] -56.5 dB */ - 0xc2600000, /* [080] -56.0 dB */ - 0xc25e0000, /* [081] -55.5 dB */ - 0xc25c0000, /* [082] -55.0 dB */ - 0xc25a0000, /* [083] -54.5 dB */ - 0xc2580000, /* [084] -54.0 dB */ - 0xc2560000, /* [085] -53.5 dB */ - 0xc2540000, /* [086] -53.0 dB */ - 0xc2520000, /* [087] -52.5 dB */ - 0xc2500000, /* [088] -52.0 dB */ - 0xc24e0000, /* [089] -51.5 dB */ - 0xc24c0000, /* [090] -51.0 dB */ - 0xc24a0000, /* [091] -50.5 dB */ - 0xc2480000, /* [092] -50.0 dB */ - 0xc2460000, /* [093] -49.5 dB */ - 0xc2440000, /* [094] -49.0 dB */ - 0xc2420000, /* [095] -48.5 dB */ - 0xc2400000, /* [096] -48.0 dB */ - 0xc23e0000, /* [097] -47.5 dB */ - 0xc23c0000, /* [098] -47.0 dB */ - 0xc23a0000, /* [099] -46.5 dB */ - 0xc2380000, /* [100] -46.0 dB */ - 0xc2360000, /* [101] -45.5 dB */ - 0xc2340000, /* [102] -45.0 dB */ - 0xc2320000, /* [103] -44.5 dB */ - 0xc2300000, /* [104] -44.0 dB */ - 0xc22e0000, /* [105] -43.5 dB */ - 0xc22c0000, /* [106] -43.0 dB */ - 0xc22a0000, /* [107] -42.5 dB */ - 0xc2280000, /* [108] -42.0 dB */ - 0xc2260000, /* [109] -41.5 dB */ - 0xc2240000, /* [110] -41.0 dB */ - 0xc2220000, /* [111] -40.5 dB */ - 0xc2200000, /* [112] -40.0 dB */ - 0xc21e0000, /* [113] -39.5 dB */ - 0xc21c0000, /* [114] -39.0 dB */ - 0xc21a0000, /* [115] -38.5 dB */ - 0xc2180000, /* [116] -38.0 dB */ - 0xc2160000, /* [117] -37.5 dB */ - 0xc2140000, /* [118] -37.0 dB */ - 0xc2120000, /* [119] -36.5 dB */ - 0xc2100000, /* [120] -36.0 dB */ - 0xc20e0000, /* [121] -35.5 dB */ - 0xc20c0000, /* [122] -35.0 dB */ - 0xc20a0000, /* [123] -34.5 dB */ - 0xc2080000, /* [124] -34.0 dB */ - 0xc2060000, /* [125] -33.5 dB */ - 0xc2040000, /* [126] -33.0 dB */ - 0xc2020000, /* [127] -32.5 dB */ - 0xc2000000, /* [128] -32.0 dB */ - 0xc1fc0000, /* [129] -31.5 dB */ - 0xc1f80000, /* [130] -31.0 dB */ - 0xc1f40000, /* [131] -30.5 dB */ - 0xc1f00000, /* [132] -30.0 dB */ - 0xc1ec0000, /* [133] -29.5 dB */ - 0xc1e80000, /* [134] -29.0 dB */ - 0xc1e40000, /* [135] -28.5 dB */ - 0xc1e00000, /* [136] -28.0 dB */ - 0xc1dc0000, /* [137] -27.5 dB */ - 0xc1d80000, /* [138] -27.0 dB */ - 0xc1d40000, /* [139] -26.5 dB */ - 0xc1d00000, /* [140] -26.0 dB */ - 0xc1cc0000, /* [141] -25.5 dB */ - 0xc1c80000, /* [142] -25.0 dB */ - 0xc1c40000, /* [143] -24.5 dB */ - 0xc1c00000, /* [144] -24.0 dB */ - 0xc1bc0000, /* [145] -23.5 dB */ - 0xc1b80000, /* [146] -23.0 dB */ - 0xc1b40000, /* [147] -22.5 dB */ - 0xc1b00000, /* [148] -22.0 dB */ - 0xc1ac0000, /* [149] -21.5 dB */ - 0xc1a80000, /* [150] -21.0 dB */ - 0xc1a40000, /* [151] -20.5 dB */ - 0xc1a00000, /* [152] -20.0 dB */ - 0xc19c0000, /* [153] -19.5 dB */ - 0xc1980000, /* [154] -19.0 dB */ - 0xc1940000, /* [155] -18.5 dB */ - 0xc1900000, /* [156] -18.0 dB */ - 0xc18c0000, /* [157] -17.5 dB */ - 0xc1880000, /* [158] -17.0 dB */ - 0xc1840000, /* [159] -16.5 dB */ - 0xc1800000, /* [160] -16.0 dB */ - 0xc1780000, /* [161] -15.5 dB */ - 0xc1700000, /* [162] -15.0 dB */ - 0xc1680000, /* [163] -14.5 dB */ - 0xc1600000, /* [164] -14.0 dB */ - 0xc1580000, /* [165] -13.5 dB */ - 0xc1500000, /* [166] -13.0 dB */ - 0xc1480000, /* [167] -12.5 dB */ - 0xc1400000, /* [168] -12.0 dB */ - 0xc1380000, /* [169] -11.5 dB */ - 0xc1300000, /* [170] -11.0 dB */ - 0xc1280000, /* [171] -10.5 dB */ - 0xc1200000, /* [172] -10.0 dB */ - 0xc1180000, /* [173] -9.5 dB */ - 0xc1100000, /* [174] -9.0 dB */ - 0xc1080000, /* [175] -8.5 dB */ - 0xc1000000, /* [176] -8.0 dB */ - 0xc0f00000, /* [177] -7.5 dB */ - 0xc0e00000, /* [178] -7.0 dB */ - 0xc0d00000, /* [179] -6.5 dB */ - 0xc0c00000, /* [180] -6.0 dB */ - 0xc0b00000, /* [181] -5.5 dB */ - 0xc0a00000, /* [182] -5.0 dB */ - 0xc0900000, /* [183] -4.5 dB */ - 0xc0800000, /* [184] -4.0 dB */ - 0xc0600000, /* [185] -3.5 dB */ - 0xc0400000, /* [186] -3.0 dB */ - 0xc0200000, /* [187] -2.5 dB */ - 0xc0000000, /* [188] -2.0 dB */ - 0xbfc00000, /* [189] -1.5 dB */ - 0xbf800000, /* [190] -1.0 dB */ - 0xbf000000, /* [191] -0.5 dB */ - 0x00000000, /* [192] 0.0 dB */ - 0x3f000000, /* [193] 0.5 dB */ - 0x3f800000, /* [194] 1.0 dB */ - 0x3fc00000, /* [195] 1.5 dB */ - 0x40000000, /* [196] 2.0 dB */ - 0x40200000, /* [197] 2.5 dB */ - 0x40400000, /* [198] 3.0 dB */ - 0x40600000, /* [199] 3.5 dB */ - 0x40800000, /* [200] 4.0 dB */ - 0x40900000, /* [201] 4.5 dB */ - 0x40a00000, /* [202] 5.0 dB */ - 0x40b00000, /* [203] 5.5 dB */ - 0x40c00000, /* [204] 6.0 dB */ - 0x40d00000, /* [205] 6.5 dB */ - 0x40e00000, /* [206] 7.0 dB */ - 0x40f00000, /* [207] 7.5 dB */ - 0x41000000, /* [208] 8.0 dB */ - 0x41080000, /* [209] 8.5 dB */ - 0x41100000, /* [210] 9.0 dB */ - 0x41180000, /* [211] 9.5 dB */ - 0x41200000, /* [212] 10.0 dB */ - 0x41280000, /* [213] 10.5 dB */ - 0x41300000, /* [214] 11.0 dB */ - 0x41380000, /* [215] 11.5 dB */ - 0x41400000, /* [216] 12.0 dB */ - 0x41480000, /* [217] 12.5 dB */ - 0x41500000, /* [218] 13.0 dB */ - 0x41580000, /* [219] 13.5 dB */ - 0x41600000, /* [220] 14.0 dB */ - 0x41680000, /* [221] 14.5 dB */ - 0x41700000, /* [222] 15.0 dB */ - 0x41780000, /* [223] 15.5 dB */ - 0x41800000, /* [224] 16.0 dB */ - 0x41840000, /* [225] 16.5 dB */ - 0x41880000, /* [226] 17.0 dB */ - 0x418c0000, /* [227] 17.5 dB */ - 0x41900000, /* [228] 18.0 dB */ - 0x41940000, /* [229] 18.5 dB */ - 0x41980000, /* [230] 19.0 dB */ - 0x419c0000, /* [231] 19.5 dB */ - 0x41a00000, /* [232] 20.0 dB */ - 0x41a40000, /* [233] 20.5 dB */ - 0x41a80000, /* [234] 21.0 dB */ - 0x41ac0000, /* [235] 21.5 dB */ - 0x41b00000, /* [236] 22.0 dB */ - 0x41b40000, /* [237] 22.5 dB */ - 0x41b80000, /* [238] 23.0 dB */ - 0x41bc0000, /* [239] 23.5 dB */ - 0x41c00000, /* [240] 24.0 dB */ - 0x41c40000, /* [241] 24.5 dB */ - 0x41c80000, /* [242] 25.0 dB */ - 0x41cc0000, /* [243] 25.5 dB */ - 0x41d00000, /* [244] 26.0 dB */ - 0x41d40000, /* [245] 26.5 dB */ - 0x41d80000, /* [246] 27.0 dB */ - 0x41dc0000, /* [247] 27.5 dB */ - 0x41e00000, /* [248] 28.0 dB */ - 0x41e40000, /* [249] 28.5 dB */ - 0x41e80000, /* [250] 29.0 dB */ - 0x41ec0000, /* [251] 29.5 dB */ - 0x41f00000, /* [252] 30.0 dB */ - 0x41f40000, /* [253] 30.5 dB */ - 0x41f80000, /* [254] 31.0 dB */ - 0x41fc0000, /* [255] 31.5 dB */ -}; - -#define MIXART_ANALOG_CAPTURE_LEVEL_MIN 0 /* -96.0 dB + 8.0 dB = -88.0 dB */ -#define MIXART_ANALOG_CAPTURE_LEVEL_MAX 255 /* 31.5 dB + 8.0 dB = 39.5 dB */ -#define MIXART_ANALOG_CAPTURE_ZERO_LEVEL 176 /* -8.0 dB + 8.0 dB = 0.0 dB */ - -#define MIXART_ANALOG_PLAYBACK_LEVEL_MIN 0 /* -96.0 dB + 1.5 dB = -94.5 dB (possible is down to (-114.0+1.5)dB) */ -#define MIXART_ANALOG_PLAYBACK_LEVEL_MAX 192 /* 0.0 dB + 1.5 dB = 1.5 dB */ -#define MIXART_ANALOG_PLAYBACK_ZERO_LEVEL 189 /* -1.5 dB + 1.5 dB = 0.0 dB */ - -static int mixart_update_analog_audio_level(struct snd_mixart* chip, int is_capture) -{ - int i, err; - struct mixart_msg request; - struct mixart_io_level io_level; - struct mixart_return_uid resp; - - memset(&io_level, 0, sizeof(io_level)); - io_level.channel = -1; /* left and right */ - - for(i=0; i<2; i++) { - if(is_capture) { - io_level.level[i].analog_level = mixart_analog_level[chip->analog_capture_volume[i]]; - } else { - if(chip->analog_playback_active[i]) - io_level.level[i].analog_level = mixart_analog_level[chip->analog_playback_volume[i]]; - else - io_level.level[i].analog_level = mixart_analog_level[MIXART_ANALOG_PLAYBACK_LEVEL_MIN]; - } - } - - if(is_capture) request.uid = chip->uid_in_analog_physio; - else request.uid = chip->uid_out_analog_physio; - request.message_id = MSG_PHYSICALIO_SET_LEVEL; - request.data = &io_level; - request.size = sizeof(io_level); - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); - if((err<0) || (resp.error_code)) { - snd_printk(KERN_DEBUG "error MSG_PHYSICALIO_SET_LEVEL card(%d) is_capture(%d) error_code(%x)\n", chip->chip_idx, is_capture, resp.error_code); - return -EINVAL; - } - return 0; -} - -/* - * analog level control - */ -static int mixart_analog_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - if(kcontrol->private_value == 0) { /* playback */ - uinfo->value.integer.min = MIXART_ANALOG_PLAYBACK_LEVEL_MIN; /* -96 dB */ - uinfo->value.integer.max = MIXART_ANALOG_PLAYBACK_LEVEL_MAX; /* 0 dB */ - } else { /* capture */ - uinfo->value.integer.min = MIXART_ANALOG_CAPTURE_LEVEL_MIN; /* -96 dB */ - uinfo->value.integer.max = MIXART_ANALOG_CAPTURE_LEVEL_MAX; /* 31.5 dB */ - } - return 0; -} - -static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - if(kcontrol->private_value == 0) { /* playback */ - ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; - ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; - } else { /* capture */ - ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; - ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; - } - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int is_capture, i; - - mutex_lock(&chip->mgr->mixer_mutex); - is_capture = (kcontrol->private_value != 0); - for (i = 0; i < 2; i++) { - int new_volume = ucontrol->value.integer.value[i]; - int *stored_volume = is_capture ? - &chip->analog_capture_volume[i] : - &chip->analog_playback_volume[i]; - if (is_capture) { - if (new_volume < MIXART_ANALOG_CAPTURE_LEVEL_MIN || - new_volume > MIXART_ANALOG_CAPTURE_LEVEL_MAX) - continue; - } else { - if (new_volume < MIXART_ANALOG_PLAYBACK_LEVEL_MIN || - new_volume > MIXART_ANALOG_PLAYBACK_LEVEL_MAX) - continue; - } - if (*stored_volume != new_volume) { - *stored_volume = new_volume; - changed = 1; - } - } - if (changed) - mixart_update_analog_audio_level(chip, is_capture); - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0); - -static struct snd_kcontrol_new mixart_control_analog_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - /* name will be filled later */ - .info = mixart_analog_vol_info, - .get = mixart_analog_vol_get, - .put = mixart_analog_vol_put, - .tlv = { .p = db_scale_analog }, -}; - -/* shared */ -#define mixart_sw_info snd_ctl_boolean_stereo_info - -static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; - ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int i, changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 2; i++) { - if (chip->analog_playback_active[i] != - ucontrol->value.integer.value[i]) { - chip->analog_playback_active[i] = - !!ucontrol->value.integer.value[i]; - changed = 1; - } - } - if (changed) /* update playback levels */ - mixart_update_analog_audio_level(chip, 0); - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new mixart_control_output_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = mixart_sw_info, /* shared */ - .get = mixart_audio_sw_get, - .put = mixart_audio_sw_put -}; - -static u32 mixart_digital_level[256] = { - 0x00000000, /* [000] = 0.00e+000 = mute if <= -109.5dB */ - 0x366e1c7a, /* [001] = 3.55e-006 = pow(10.0, 0.05 * -109.0dB) */ - 0x367c3860, /* [002] = 3.76e-006 = pow(10.0, 0.05 * -108.5dB) */ - 0x36859525, /* [003] = 3.98e-006 = pow(10.0, 0.05 * -108.0dB) */ - 0x368d7f74, /* [004] = 4.22e-006 = pow(10.0, 0.05 * -107.5dB) */ - 0x3695e1d4, /* [005] = 4.47e-006 = pow(10.0, 0.05 * -107.0dB) */ - 0x369ec362, /* [006] = 4.73e-006 = pow(10.0, 0.05 * -106.5dB) */ - 0x36a82ba8, /* [007] = 5.01e-006 = pow(10.0, 0.05 * -106.0dB) */ - 0x36b222a0, /* [008] = 5.31e-006 = pow(10.0, 0.05 * -105.5dB) */ - 0x36bcb0c1, /* [009] = 5.62e-006 = pow(10.0, 0.05 * -105.0dB) */ - 0x36c7defd, /* [010] = 5.96e-006 = pow(10.0, 0.05 * -104.5dB) */ - 0x36d3b6d3, /* [011] = 6.31e-006 = pow(10.0, 0.05 * -104.0dB) */ - 0x36e0424e, /* [012] = 6.68e-006 = pow(10.0, 0.05 * -103.5dB) */ - 0x36ed8c14, /* [013] = 7.08e-006 = pow(10.0, 0.05 * -103.0dB) */ - 0x36fb9f6c, /* [014] = 7.50e-006 = pow(10.0, 0.05 * -102.5dB) */ - 0x37054423, /* [015] = 7.94e-006 = pow(10.0, 0.05 * -102.0dB) */ - 0x370d29a5, /* [016] = 8.41e-006 = pow(10.0, 0.05 * -101.5dB) */ - 0x371586f0, /* [017] = 8.91e-006 = pow(10.0, 0.05 * -101.0dB) */ - 0x371e631b, /* [018] = 9.44e-006 = pow(10.0, 0.05 * -100.5dB) */ - 0x3727c5ac, /* [019] = 1.00e-005 = pow(10.0, 0.05 * -100.0dB) */ - 0x3731b69a, /* [020] = 1.06e-005 = pow(10.0, 0.05 * -99.5dB) */ - 0x373c3e53, /* [021] = 1.12e-005 = pow(10.0, 0.05 * -99.0dB) */ - 0x374765c8, /* [022] = 1.19e-005 = pow(10.0, 0.05 * -98.5dB) */ - 0x3753366f, /* [023] = 1.26e-005 = pow(10.0, 0.05 * -98.0dB) */ - 0x375fba4f, /* [024] = 1.33e-005 = pow(10.0, 0.05 * -97.5dB) */ - 0x376cfc07, /* [025] = 1.41e-005 = pow(10.0, 0.05 * -97.0dB) */ - 0x377b06d5, /* [026] = 1.50e-005 = pow(10.0, 0.05 * -96.5dB) */ - 0x3784f352, /* [027] = 1.58e-005 = pow(10.0, 0.05 * -96.0dB) */ - 0x378cd40b, /* [028] = 1.68e-005 = pow(10.0, 0.05 * -95.5dB) */ - 0x37952c42, /* [029] = 1.78e-005 = pow(10.0, 0.05 * -95.0dB) */ - 0x379e030e, /* [030] = 1.88e-005 = pow(10.0, 0.05 * -94.5dB) */ - 0x37a75fef, /* [031] = 2.00e-005 = pow(10.0, 0.05 * -94.0dB) */ - 0x37b14ad5, /* [032] = 2.11e-005 = pow(10.0, 0.05 * -93.5dB) */ - 0x37bbcc2c, /* [033] = 2.24e-005 = pow(10.0, 0.05 * -93.0dB) */ - 0x37c6ecdd, /* [034] = 2.37e-005 = pow(10.0, 0.05 * -92.5dB) */ - 0x37d2b65a, /* [035] = 2.51e-005 = pow(10.0, 0.05 * -92.0dB) */ - 0x37df32a3, /* [036] = 2.66e-005 = pow(10.0, 0.05 * -91.5dB) */ - 0x37ec6c50, /* [037] = 2.82e-005 = pow(10.0, 0.05 * -91.0dB) */ - 0x37fa6e9b, /* [038] = 2.99e-005 = pow(10.0, 0.05 * -90.5dB) */ - 0x3804a2b3, /* [039] = 3.16e-005 = pow(10.0, 0.05 * -90.0dB) */ - 0x380c7ea4, /* [040] = 3.35e-005 = pow(10.0, 0.05 * -89.5dB) */ - 0x3814d1cc, /* [041] = 3.55e-005 = pow(10.0, 0.05 * -89.0dB) */ - 0x381da33c, /* [042] = 3.76e-005 = pow(10.0, 0.05 * -88.5dB) */ - 0x3826fa6f, /* [043] = 3.98e-005 = pow(10.0, 0.05 * -88.0dB) */ - 0x3830df51, /* [044] = 4.22e-005 = pow(10.0, 0.05 * -87.5dB) */ - 0x383b5a49, /* [045] = 4.47e-005 = pow(10.0, 0.05 * -87.0dB) */ - 0x3846743b, /* [046] = 4.73e-005 = pow(10.0, 0.05 * -86.5dB) */ - 0x38523692, /* [047] = 5.01e-005 = pow(10.0, 0.05 * -86.0dB) */ - 0x385eab48, /* [048] = 5.31e-005 = pow(10.0, 0.05 * -85.5dB) */ - 0x386bdcf1, /* [049] = 5.62e-005 = pow(10.0, 0.05 * -85.0dB) */ - 0x3879d6bc, /* [050] = 5.96e-005 = pow(10.0, 0.05 * -84.5dB) */ - 0x38845244, /* [051] = 6.31e-005 = pow(10.0, 0.05 * -84.0dB) */ - 0x388c2971, /* [052] = 6.68e-005 = pow(10.0, 0.05 * -83.5dB) */ - 0x3894778d, /* [053] = 7.08e-005 = pow(10.0, 0.05 * -83.0dB) */ - 0x389d43a4, /* [054] = 7.50e-005 = pow(10.0, 0.05 * -82.5dB) */ - 0x38a6952c, /* [055] = 7.94e-005 = pow(10.0, 0.05 * -82.0dB) */ - 0x38b0740f, /* [056] = 8.41e-005 = pow(10.0, 0.05 * -81.5dB) */ - 0x38bae8ac, /* [057] = 8.91e-005 = pow(10.0, 0.05 * -81.0dB) */ - 0x38c5fbe2, /* [058] = 9.44e-005 = pow(10.0, 0.05 * -80.5dB) */ - 0x38d1b717, /* [059] = 1.00e-004 = pow(10.0, 0.05 * -80.0dB) */ - 0x38de2440, /* [060] = 1.06e-004 = pow(10.0, 0.05 * -79.5dB) */ - 0x38eb4de8, /* [061] = 1.12e-004 = pow(10.0, 0.05 * -79.0dB) */ - 0x38f93f3a, /* [062] = 1.19e-004 = pow(10.0, 0.05 * -78.5dB) */ - 0x39040206, /* [063] = 1.26e-004 = pow(10.0, 0.05 * -78.0dB) */ - 0x390bd472, /* [064] = 1.33e-004 = pow(10.0, 0.05 * -77.5dB) */ - 0x39141d84, /* [065] = 1.41e-004 = pow(10.0, 0.05 * -77.0dB) */ - 0x391ce445, /* [066] = 1.50e-004 = pow(10.0, 0.05 * -76.5dB) */ - 0x39263027, /* [067] = 1.58e-004 = pow(10.0, 0.05 * -76.0dB) */ - 0x3930090d, /* [068] = 1.68e-004 = pow(10.0, 0.05 * -75.5dB) */ - 0x393a7753, /* [069] = 1.78e-004 = pow(10.0, 0.05 * -75.0dB) */ - 0x394583d2, /* [070] = 1.88e-004 = pow(10.0, 0.05 * -74.5dB) */ - 0x395137ea, /* [071] = 2.00e-004 = pow(10.0, 0.05 * -74.0dB) */ - 0x395d9d8a, /* [072] = 2.11e-004 = pow(10.0, 0.05 * -73.5dB) */ - 0x396abf37, /* [073] = 2.24e-004 = pow(10.0, 0.05 * -73.0dB) */ - 0x3978a814, /* [074] = 2.37e-004 = pow(10.0, 0.05 * -72.5dB) */ - 0x3983b1f8, /* [075] = 2.51e-004 = pow(10.0, 0.05 * -72.0dB) */ - 0x398b7fa6, /* [076] = 2.66e-004 = pow(10.0, 0.05 * -71.5dB) */ - 0x3993c3b2, /* [077] = 2.82e-004 = pow(10.0, 0.05 * -71.0dB) */ - 0x399c8521, /* [078] = 2.99e-004 = pow(10.0, 0.05 * -70.5dB) */ - 0x39a5cb5f, /* [079] = 3.16e-004 = pow(10.0, 0.05 * -70.0dB) */ - 0x39af9e4d, /* [080] = 3.35e-004 = pow(10.0, 0.05 * -69.5dB) */ - 0x39ba063f, /* [081] = 3.55e-004 = pow(10.0, 0.05 * -69.0dB) */ - 0x39c50c0b, /* [082] = 3.76e-004 = pow(10.0, 0.05 * -68.5dB) */ - 0x39d0b90a, /* [083] = 3.98e-004 = pow(10.0, 0.05 * -68.0dB) */ - 0x39dd1726, /* [084] = 4.22e-004 = pow(10.0, 0.05 * -67.5dB) */ - 0x39ea30db, /* [085] = 4.47e-004 = pow(10.0, 0.05 * -67.0dB) */ - 0x39f81149, /* [086] = 4.73e-004 = pow(10.0, 0.05 * -66.5dB) */ - 0x3a03621b, /* [087] = 5.01e-004 = pow(10.0, 0.05 * -66.0dB) */ - 0x3a0b2b0d, /* [088] = 5.31e-004 = pow(10.0, 0.05 * -65.5dB) */ - 0x3a136a16, /* [089] = 5.62e-004 = pow(10.0, 0.05 * -65.0dB) */ - 0x3a1c2636, /* [090] = 5.96e-004 = pow(10.0, 0.05 * -64.5dB) */ - 0x3a2566d5, /* [091] = 6.31e-004 = pow(10.0, 0.05 * -64.0dB) */ - 0x3a2f33cd, /* [092] = 6.68e-004 = pow(10.0, 0.05 * -63.5dB) */ - 0x3a399570, /* [093] = 7.08e-004 = pow(10.0, 0.05 * -63.0dB) */ - 0x3a44948c, /* [094] = 7.50e-004 = pow(10.0, 0.05 * -62.5dB) */ - 0x3a503a77, /* [095] = 7.94e-004 = pow(10.0, 0.05 * -62.0dB) */ - 0x3a5c9112, /* [096] = 8.41e-004 = pow(10.0, 0.05 * -61.5dB) */ - 0x3a69a2d7, /* [097] = 8.91e-004 = pow(10.0, 0.05 * -61.0dB) */ - 0x3a777ada, /* [098] = 9.44e-004 = pow(10.0, 0.05 * -60.5dB) */ - 0x3a83126f, /* [099] = 1.00e-003 = pow(10.0, 0.05 * -60.0dB) */ - 0x3a8ad6a8, /* [100] = 1.06e-003 = pow(10.0, 0.05 * -59.5dB) */ - 0x3a9310b1, /* [101] = 1.12e-003 = pow(10.0, 0.05 * -59.0dB) */ - 0x3a9bc784, /* [102] = 1.19e-003 = pow(10.0, 0.05 * -58.5dB) */ - 0x3aa50287, /* [103] = 1.26e-003 = pow(10.0, 0.05 * -58.0dB) */ - 0x3aaec98e, /* [104] = 1.33e-003 = pow(10.0, 0.05 * -57.5dB) */ - 0x3ab924e5, /* [105] = 1.41e-003 = pow(10.0, 0.05 * -57.0dB) */ - 0x3ac41d56, /* [106] = 1.50e-003 = pow(10.0, 0.05 * -56.5dB) */ - 0x3acfbc31, /* [107] = 1.58e-003 = pow(10.0, 0.05 * -56.0dB) */ - 0x3adc0b51, /* [108] = 1.68e-003 = pow(10.0, 0.05 * -55.5dB) */ - 0x3ae91528, /* [109] = 1.78e-003 = pow(10.0, 0.05 * -55.0dB) */ - 0x3af6e4c6, /* [110] = 1.88e-003 = pow(10.0, 0.05 * -54.5dB) */ - 0x3b02c2f2, /* [111] = 2.00e-003 = pow(10.0, 0.05 * -54.0dB) */ - 0x3b0a8276, /* [112] = 2.11e-003 = pow(10.0, 0.05 * -53.5dB) */ - 0x3b12b782, /* [113] = 2.24e-003 = pow(10.0, 0.05 * -53.0dB) */ - 0x3b1b690d, /* [114] = 2.37e-003 = pow(10.0, 0.05 * -52.5dB) */ - 0x3b249e76, /* [115] = 2.51e-003 = pow(10.0, 0.05 * -52.0dB) */ - 0x3b2e5f8f, /* [116] = 2.66e-003 = pow(10.0, 0.05 * -51.5dB) */ - 0x3b38b49f, /* [117] = 2.82e-003 = pow(10.0, 0.05 * -51.0dB) */ - 0x3b43a669, /* [118] = 2.99e-003 = pow(10.0, 0.05 * -50.5dB) */ - 0x3b4f3e37, /* [119] = 3.16e-003 = pow(10.0, 0.05 * -50.0dB) */ - 0x3b5b85e0, /* [120] = 3.35e-003 = pow(10.0, 0.05 * -49.5dB) */ - 0x3b6887cf, /* [121] = 3.55e-003 = pow(10.0, 0.05 * -49.0dB) */ - 0x3b764f0e, /* [122] = 3.76e-003 = pow(10.0, 0.05 * -48.5dB) */ - 0x3b8273a6, /* [123] = 3.98e-003 = pow(10.0, 0.05 * -48.0dB) */ - 0x3b8a2e77, /* [124] = 4.22e-003 = pow(10.0, 0.05 * -47.5dB) */ - 0x3b925e89, /* [125] = 4.47e-003 = pow(10.0, 0.05 * -47.0dB) */ - 0x3b9b0ace, /* [126] = 4.73e-003 = pow(10.0, 0.05 * -46.5dB) */ - 0x3ba43aa2, /* [127] = 5.01e-003 = pow(10.0, 0.05 * -46.0dB) */ - 0x3badf5d1, /* [128] = 5.31e-003 = pow(10.0, 0.05 * -45.5dB) */ - 0x3bb8449c, /* [129] = 5.62e-003 = pow(10.0, 0.05 * -45.0dB) */ - 0x3bc32fc3, /* [130] = 5.96e-003 = pow(10.0, 0.05 * -44.5dB) */ - 0x3bcec08a, /* [131] = 6.31e-003 = pow(10.0, 0.05 * -44.0dB) */ - 0x3bdb00c0, /* [132] = 6.68e-003 = pow(10.0, 0.05 * -43.5dB) */ - 0x3be7facc, /* [133] = 7.08e-003 = pow(10.0, 0.05 * -43.0dB) */ - 0x3bf5b9b0, /* [134] = 7.50e-003 = pow(10.0, 0.05 * -42.5dB) */ - 0x3c02248a, /* [135] = 7.94e-003 = pow(10.0, 0.05 * -42.0dB) */ - 0x3c09daac, /* [136] = 8.41e-003 = pow(10.0, 0.05 * -41.5dB) */ - 0x3c1205c6, /* [137] = 8.91e-003 = pow(10.0, 0.05 * -41.0dB) */ - 0x3c1aacc8, /* [138] = 9.44e-003 = pow(10.0, 0.05 * -40.5dB) */ - 0x3c23d70a, /* [139] = 1.00e-002 = pow(10.0, 0.05 * -40.0dB) */ - 0x3c2d8c52, /* [140] = 1.06e-002 = pow(10.0, 0.05 * -39.5dB) */ - 0x3c37d4dd, /* [141] = 1.12e-002 = pow(10.0, 0.05 * -39.0dB) */ - 0x3c42b965, /* [142] = 1.19e-002 = pow(10.0, 0.05 * -38.5dB) */ - 0x3c4e4329, /* [143] = 1.26e-002 = pow(10.0, 0.05 * -38.0dB) */ - 0x3c5a7bf1, /* [144] = 1.33e-002 = pow(10.0, 0.05 * -37.5dB) */ - 0x3c676e1e, /* [145] = 1.41e-002 = pow(10.0, 0.05 * -37.0dB) */ - 0x3c7524ac, /* [146] = 1.50e-002 = pow(10.0, 0.05 * -36.5dB) */ - 0x3c81d59f, /* [147] = 1.58e-002 = pow(10.0, 0.05 * -36.0dB) */ - 0x3c898712, /* [148] = 1.68e-002 = pow(10.0, 0.05 * -35.5dB) */ - 0x3c91ad39, /* [149] = 1.78e-002 = pow(10.0, 0.05 * -35.0dB) */ - 0x3c9a4efc, /* [150] = 1.88e-002 = pow(10.0, 0.05 * -34.5dB) */ - 0x3ca373af, /* [151] = 2.00e-002 = pow(10.0, 0.05 * -34.0dB) */ - 0x3cad2314, /* [152] = 2.11e-002 = pow(10.0, 0.05 * -33.5dB) */ - 0x3cb76563, /* [153] = 2.24e-002 = pow(10.0, 0.05 * -33.0dB) */ - 0x3cc24350, /* [154] = 2.37e-002 = pow(10.0, 0.05 * -32.5dB) */ - 0x3ccdc614, /* [155] = 2.51e-002 = pow(10.0, 0.05 * -32.0dB) */ - 0x3cd9f773, /* [156] = 2.66e-002 = pow(10.0, 0.05 * -31.5dB) */ - 0x3ce6e1c6, /* [157] = 2.82e-002 = pow(10.0, 0.05 * -31.0dB) */ - 0x3cf49003, /* [158] = 2.99e-002 = pow(10.0, 0.05 * -30.5dB) */ - 0x3d0186e2, /* [159] = 3.16e-002 = pow(10.0, 0.05 * -30.0dB) */ - 0x3d0933ac, /* [160] = 3.35e-002 = pow(10.0, 0.05 * -29.5dB) */ - 0x3d1154e1, /* [161] = 3.55e-002 = pow(10.0, 0.05 * -29.0dB) */ - 0x3d19f169, /* [162] = 3.76e-002 = pow(10.0, 0.05 * -28.5dB) */ - 0x3d231090, /* [163] = 3.98e-002 = pow(10.0, 0.05 * -28.0dB) */ - 0x3d2cba15, /* [164] = 4.22e-002 = pow(10.0, 0.05 * -27.5dB) */ - 0x3d36f62b, /* [165] = 4.47e-002 = pow(10.0, 0.05 * -27.0dB) */ - 0x3d41cd81, /* [166] = 4.73e-002 = pow(10.0, 0.05 * -26.5dB) */ - 0x3d4d494a, /* [167] = 5.01e-002 = pow(10.0, 0.05 * -26.0dB) */ - 0x3d597345, /* [168] = 5.31e-002 = pow(10.0, 0.05 * -25.5dB) */ - 0x3d6655c3, /* [169] = 5.62e-002 = pow(10.0, 0.05 * -25.0dB) */ - 0x3d73fbb4, /* [170] = 5.96e-002 = pow(10.0, 0.05 * -24.5dB) */ - 0x3d813856, /* [171] = 6.31e-002 = pow(10.0, 0.05 * -24.0dB) */ - 0x3d88e078, /* [172] = 6.68e-002 = pow(10.0, 0.05 * -23.5dB) */ - 0x3d90fcbf, /* [173] = 7.08e-002 = pow(10.0, 0.05 * -23.0dB) */ - 0x3d99940e, /* [174] = 7.50e-002 = pow(10.0, 0.05 * -22.5dB) */ - 0x3da2adad, /* [175] = 7.94e-002 = pow(10.0, 0.05 * -22.0dB) */ - 0x3dac5156, /* [176] = 8.41e-002 = pow(10.0, 0.05 * -21.5dB) */ - 0x3db68738, /* [177] = 8.91e-002 = pow(10.0, 0.05 * -21.0dB) */ - 0x3dc157fb, /* [178] = 9.44e-002 = pow(10.0, 0.05 * -20.5dB) */ - 0x3dcccccd, /* [179] = 1.00e-001 = pow(10.0, 0.05 * -20.0dB) */ - 0x3dd8ef67, /* [180] = 1.06e-001 = pow(10.0, 0.05 * -19.5dB) */ - 0x3de5ca15, /* [181] = 1.12e-001 = pow(10.0, 0.05 * -19.0dB) */ - 0x3df367bf, /* [182] = 1.19e-001 = pow(10.0, 0.05 * -18.5dB) */ - 0x3e00e9f9, /* [183] = 1.26e-001 = pow(10.0, 0.05 * -18.0dB) */ - 0x3e088d77, /* [184] = 1.33e-001 = pow(10.0, 0.05 * -17.5dB) */ - 0x3e10a4d3, /* [185] = 1.41e-001 = pow(10.0, 0.05 * -17.0dB) */ - 0x3e1936ec, /* [186] = 1.50e-001 = pow(10.0, 0.05 * -16.5dB) */ - 0x3e224b06, /* [187] = 1.58e-001 = pow(10.0, 0.05 * -16.0dB) */ - 0x3e2be8d7, /* [188] = 1.68e-001 = pow(10.0, 0.05 * -15.5dB) */ - 0x3e361887, /* [189] = 1.78e-001 = pow(10.0, 0.05 * -15.0dB) */ - 0x3e40e2bb, /* [190] = 1.88e-001 = pow(10.0, 0.05 * -14.5dB) */ - 0x3e4c509b, /* [191] = 2.00e-001 = pow(10.0, 0.05 * -14.0dB) */ - 0x3e586bd9, /* [192] = 2.11e-001 = pow(10.0, 0.05 * -13.5dB) */ - 0x3e653ebb, /* [193] = 2.24e-001 = pow(10.0, 0.05 * -13.0dB) */ - 0x3e72d424, /* [194] = 2.37e-001 = pow(10.0, 0.05 * -12.5dB) */ - 0x3e809bcc, /* [195] = 2.51e-001 = pow(10.0, 0.05 * -12.0dB) */ - 0x3e883aa8, /* [196] = 2.66e-001 = pow(10.0, 0.05 * -11.5dB) */ - 0x3e904d1c, /* [197] = 2.82e-001 = pow(10.0, 0.05 * -11.0dB) */ - 0x3e98da02, /* [198] = 2.99e-001 = pow(10.0, 0.05 * -10.5dB) */ - 0x3ea1e89b, /* [199] = 3.16e-001 = pow(10.0, 0.05 * -10.0dB) */ - 0x3eab8097, /* [200] = 3.35e-001 = pow(10.0, 0.05 * -9.5dB) */ - 0x3eb5aa1a, /* [201] = 3.55e-001 = pow(10.0, 0.05 * -9.0dB) */ - 0x3ec06dc3, /* [202] = 3.76e-001 = pow(10.0, 0.05 * -8.5dB) */ - 0x3ecbd4b4, /* [203] = 3.98e-001 = pow(10.0, 0.05 * -8.0dB) */ - 0x3ed7e89b, /* [204] = 4.22e-001 = pow(10.0, 0.05 * -7.5dB) */ - 0x3ee4b3b6, /* [205] = 4.47e-001 = pow(10.0, 0.05 * -7.0dB) */ - 0x3ef240e2, /* [206] = 4.73e-001 = pow(10.0, 0.05 * -6.5dB) */ - 0x3f004dce, /* [207] = 5.01e-001 = pow(10.0, 0.05 * -6.0dB) */ - 0x3f07e80b, /* [208] = 5.31e-001 = pow(10.0, 0.05 * -5.5dB) */ - 0x3f0ff59a, /* [209] = 5.62e-001 = pow(10.0, 0.05 * -5.0dB) */ - 0x3f187d50, /* [210] = 5.96e-001 = pow(10.0, 0.05 * -4.5dB) */ - 0x3f21866c, /* [211] = 6.31e-001 = pow(10.0, 0.05 * -4.0dB) */ - 0x3f2b1896, /* [212] = 6.68e-001 = pow(10.0, 0.05 * -3.5dB) */ - 0x3f353bef, /* [213] = 7.08e-001 = pow(10.0, 0.05 * -3.0dB) */ - 0x3f3ff911, /* [214] = 7.50e-001 = pow(10.0, 0.05 * -2.5dB) */ - 0x3f4b5918, /* [215] = 7.94e-001 = pow(10.0, 0.05 * -2.0dB) */ - 0x3f5765ac, /* [216] = 8.41e-001 = pow(10.0, 0.05 * -1.5dB) */ - 0x3f642905, /* [217] = 8.91e-001 = pow(10.0, 0.05 * -1.0dB) */ - 0x3f71adf9, /* [218] = 9.44e-001 = pow(10.0, 0.05 * -0.5dB) */ - 0x3f800000, /* [219] = 1.00e+000 = pow(10.0, 0.05 * 0.0dB) */ - 0x3f8795a0, /* [220] = 1.06e+000 = pow(10.0, 0.05 * 0.5dB) */ - 0x3f8f9e4d, /* [221] = 1.12e+000 = pow(10.0, 0.05 * 1.0dB) */ - 0x3f9820d7, /* [222] = 1.19e+000 = pow(10.0, 0.05 * 1.5dB) */ - 0x3fa12478, /* [223] = 1.26e+000 = pow(10.0, 0.05 * 2.0dB) */ - 0x3faab0d5, /* [224] = 1.33e+000 = pow(10.0, 0.05 * 2.5dB) */ - 0x3fb4ce08, /* [225] = 1.41e+000 = pow(10.0, 0.05 * 3.0dB) */ - 0x3fbf84a6, /* [226] = 1.50e+000 = pow(10.0, 0.05 * 3.5dB) */ - 0x3fcaddc8, /* [227] = 1.58e+000 = pow(10.0, 0.05 * 4.0dB) */ - 0x3fd6e30d, /* [228] = 1.68e+000 = pow(10.0, 0.05 * 4.5dB) */ - 0x3fe39ea9, /* [229] = 1.78e+000 = pow(10.0, 0.05 * 5.0dB) */ - 0x3ff11b6a, /* [230] = 1.88e+000 = pow(10.0, 0.05 * 5.5dB) */ - 0x3fff64c1, /* [231] = 2.00e+000 = pow(10.0, 0.05 * 6.0dB) */ - 0x40074368, /* [232] = 2.11e+000 = pow(10.0, 0.05 * 6.5dB) */ - 0x400f4735, /* [233] = 2.24e+000 = pow(10.0, 0.05 * 7.0dB) */ - 0x4017c496, /* [234] = 2.37e+000 = pow(10.0, 0.05 * 7.5dB) */ - 0x4020c2bf, /* [235] = 2.51e+000 = pow(10.0, 0.05 * 8.0dB) */ - 0x402a4952, /* [236] = 2.66e+000 = pow(10.0, 0.05 * 8.5dB) */ - 0x40346063, /* [237] = 2.82e+000 = pow(10.0, 0.05 * 9.0dB) */ - 0x403f1082, /* [238] = 2.99e+000 = pow(10.0, 0.05 * 9.5dB) */ - 0x404a62c2, /* [239] = 3.16e+000 = pow(10.0, 0.05 * 10.0dB) */ - 0x405660bd, /* [240] = 3.35e+000 = pow(10.0, 0.05 * 10.5dB) */ - 0x406314a0, /* [241] = 3.55e+000 = pow(10.0, 0.05 * 11.0dB) */ - 0x40708933, /* [242] = 3.76e+000 = pow(10.0, 0.05 * 11.5dB) */ - 0x407ec9e1, /* [243] = 3.98e+000 = pow(10.0, 0.05 * 12.0dB) */ - 0x4086f161, /* [244] = 4.22e+000 = pow(10.0, 0.05 * 12.5dB) */ - 0x408ef052, /* [245] = 4.47e+000 = pow(10.0, 0.05 * 13.0dB) */ - 0x4097688d, /* [246] = 4.73e+000 = pow(10.0, 0.05 * 13.5dB) */ - 0x40a06142, /* [247] = 5.01e+000 = pow(10.0, 0.05 * 14.0dB) */ - 0x40a9e20e, /* [248] = 5.31e+000 = pow(10.0, 0.05 * 14.5dB) */ - 0x40b3f300, /* [249] = 5.62e+000 = pow(10.0, 0.05 * 15.0dB) */ - 0x40be9ca5, /* [250] = 5.96e+000 = pow(10.0, 0.05 * 15.5dB) */ - 0x40c9e807, /* [251] = 6.31e+000 = pow(10.0, 0.05 * 16.0dB) */ - 0x40d5debc, /* [252] = 6.68e+000 = pow(10.0, 0.05 * 16.5dB) */ - 0x40e28aeb, /* [253] = 7.08e+000 = pow(10.0, 0.05 * 17.0dB) */ - 0x40eff755, /* [254] = 7.50e+000 = pow(10.0, 0.05 * 17.5dB) */ - 0x40fe2f5e, /* [255] = 7.94e+000 = pow(10.0, 0.05 * 18.0dB) */ -}; - -#define MIXART_DIGITAL_LEVEL_MIN 0 /* -109.5 dB */ -#define MIXART_DIGITAL_LEVEL_MAX 255 /* 18.0 dB */ -#define MIXART_DIGITAL_ZERO_LEVEL 219 /* 0.0 dB */ - - -int mixart_update_playback_stream_level(struct snd_mixart* chip, int is_aes, int idx) -{ - int err, i; - int volume[2]; - struct mixart_msg request; - struct mixart_set_out_stream_level_req set_level; - u32 status; - struct mixart_pipe *pipe; - - memset(&set_level, 0, sizeof(set_level)); - set_level.nb_of_stream = 1; - set_level.stream_level.desc.stream_idx = idx; - - if(is_aes) { - pipe = &chip->pipe_out_dig; /* AES playback */ - idx += MIXART_PLAYBACK_STREAMS; - } else { - pipe = &chip->pipe_out_ana; /* analog playback */ - } - - /* only when pipe exists ! */ - if(pipe->status == PIPE_UNDEFINED) - return 0; - - set_level.stream_level.desc.uid_pipe = pipe->group_uid; - - for(i=0; i<2; i++) { - if(chip->digital_playback_active[idx][i]) - volume[i] = chip->digital_playback_volume[idx][i]; - else - volume[i] = MIXART_DIGITAL_LEVEL_MIN; - } - - set_level.stream_level.out_level.valid_mask1 = MIXART_OUT_STREAM_SET_LEVEL_LEFT_AUDIO1 | MIXART_OUT_STREAM_SET_LEVEL_RIGHT_AUDIO2; - set_level.stream_level.out_level.left_to_out1_level = mixart_digital_level[volume[0]]; - set_level.stream_level.out_level.right_to_out2_level = mixart_digital_level[volume[1]]; - - request.message_id = MSG_STREAM_SET_OUT_STREAM_LEVEL; - request.uid = (struct mixart_uid){0,0}; - request.data = &set_level; - request.size = sizeof(set_level); - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(status), &status); - if((err<0) || status) { - snd_printk(KERN_DEBUG "error MSG_STREAM_SET_OUT_STREAM_LEVEL card(%d) status(%x)\n", chip->chip_idx, status); - return -EINVAL; - } - return 0; -} - -int mixart_update_capture_stream_level(struct snd_mixart* chip, int is_aes) -{ - int err, i, idx; - struct mixart_pipe *pipe; - struct mixart_msg request; - struct mixart_set_in_audio_level_req set_level; - u32 status; - - if(is_aes) { - idx = 1; - pipe = &chip->pipe_in_dig; - } else { - idx = 0; - pipe = &chip->pipe_in_ana; - } - - /* only when pipe exists ! */ - if(pipe->status == PIPE_UNDEFINED) - return 0; - - memset(&set_level, 0, sizeof(set_level)); - set_level.audio_count = 2; - set_level.level[0].connector = pipe->uid_left_connector; - set_level.level[1].connector = pipe->uid_right_connector; - - for(i=0; i<2; i++) { - set_level.level[i].valid_mask1 = MIXART_AUDIO_LEVEL_DIGITAL_MASK; - set_level.level[i].digital_level = mixart_digital_level[chip->digital_capture_volume[idx][i]]; - } - - request.message_id = MSG_STREAM_SET_IN_AUDIO_LEVEL; - request.uid = (struct mixart_uid){0,0}; - request.data = &set_level; - request.size = sizeof(set_level); - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(status), &status); - if((err<0) || status) { - snd_printk(KERN_DEBUG "error MSG_STREAM_SET_IN_AUDIO_LEVEL card(%d) status(%x)\n", chip->chip_idx, status); - return -EINVAL; - } - return 0; -} - - -/* shared */ -static int mixart_digital_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = MIXART_DIGITAL_LEVEL_MIN; /* -109.5 dB */ - uinfo->value.integer.max = MIXART_DIGITAL_LEVEL_MAX; /* 18.0 dB */ - return 0; -} - -#define MIXART_VOL_REC_MASK 1 -#define MIXART_VOL_AES_MASK 2 - -static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int *stored_volume; - int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; - int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; - mutex_lock(&chip->mgr->mixer_mutex); - if(is_capture) { - if(is_aes) stored_volume = chip->digital_capture_volume[1]; /* AES capture */ - else stored_volume = chip->digital_capture_volume[0]; /* analog capture */ - } else { - snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - if(is_aes) stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; /* AES playback */ - else stored_volume = chip->digital_playback_volume[idx]; /* analog playback */ - } - ucontrol->value.integer.value[0] = stored_volume[0]; - ucontrol->value.integer.value[1] = stored_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int changed = 0; - int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK; - int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; - int* stored_volume; - int i; - mutex_lock(&chip->mgr->mixer_mutex); - if (is_capture) { - if (is_aes) /* AES capture */ - stored_volume = chip->digital_capture_volume[1]; - else /* analog capture */ - stored_volume = chip->digital_capture_volume[0]; - } else { - snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - if (is_aes) /* AES playback */ - stored_volume = chip->digital_playback_volume[MIXART_PLAYBACK_STREAMS + idx]; - else /* analog playback */ - stored_volume = chip->digital_playback_volume[idx]; - } - for (i = 0; i < 2; i++) { - int vol = ucontrol->value.integer.value[i]; - if (vol < MIXART_DIGITAL_LEVEL_MIN || - vol > MIXART_DIGITAL_LEVEL_MAX) - continue; - if (stored_volume[i] != vol) { - stored_volume[i] = vol; - changed = 1; - } - } - if (changed) { - if (is_capture) - mixart_update_capture_stream_level(chip, is_aes); - else - mixart_update_playback_stream_level(chip, is_aes, idx); - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); - -static struct snd_kcontrol_new snd_mixart_pcm_vol = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - /* name will be filled later */ - /* count will be filled later */ - .info = mixart_digital_vol_info, /* shared */ - .get = mixart_pcm_vol_get, - .put = mixart_pcm_vol_put, - .tlv = { .p = db_scale_digital }, -}; - - -static int mixart_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - mutex_lock(&chip->mgr->mixer_mutex); - if(kcontrol->private_value & MIXART_VOL_AES_MASK) /* AES playback */ - idx += MIXART_PLAYBACK_STREAMS; - ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; - ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK; - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int i, j; - snd_BUG_ON(idx >= MIXART_PLAYBACK_STREAMS); - mutex_lock(&chip->mgr->mixer_mutex); - j = idx; - if (is_aes) - j += MIXART_PLAYBACK_STREAMS; - for (i = 0; i < 2; i++) { - if (chip->digital_playback_active[j][i] != - ucontrol->value.integer.value[i]) { - chip->digital_playback_active[j][i] = - !!ucontrol->value.integer.value[i]; - changed = 1; - } - } - if (changed) - mixart_update_playback_stream_level(chip, is_aes, idx); - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new mixart_control_pcm_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* name will be filled later */ - .count = MIXART_PLAYBACK_STREAMS, - .info = mixart_sw_info, /* shared */ - .get = mixart_pcm_sw_get, - .put = mixart_pcm_sw_put -}; - -static int mixart_update_monitoring(struct snd_mixart* chip, int channel) -{ - int err; - struct mixart_msg request; - struct mixart_set_out_audio_level audio_level; - u32 resp; - - if(chip->pipe_out_ana.status == PIPE_UNDEFINED) - return -EINVAL; /* no pipe defined */ - - if(!channel) request.uid = chip->pipe_out_ana.uid_left_connector; - else request.uid = chip->pipe_out_ana.uid_right_connector; - request.message_id = MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL; - request.data = &audio_level; - request.size = sizeof(audio_level); - - memset(&audio_level, 0, sizeof(audio_level)); - audio_level.valid_mask1 = MIXART_AUDIO_LEVEL_MONITOR_MASK | MIXART_AUDIO_LEVEL_MUTE_M1_MASK; - audio_level.monitor_level = mixart_digital_level[chip->monitoring_volume[channel!=0]]; - audio_level.monitor_mute1 = !chip->monitoring_active[channel!=0]; - - err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp); - if((err<0) || resp) { - snd_printk(KERN_DEBUG "error MSG_CONNECTOR_SET_OUT_AUDIO_LEVEL card(%d) resp(%x)\n", chip->chip_idx, resp); - return -EINVAL; - } - return 0; -} - -/* - * monitoring level control - */ - -static int mixart_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; - ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int i; - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 2; i++) { - if (chip->monitoring_volume[i] != - ucontrol->value.integer.value[i]) { - chip->monitoring_volume[i] = - !!ucontrol->value.integer.value[i]; - mixart_update_monitoring(chip, i); - changed = 1; - } - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new mixart_control_monitor_vol = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Monitoring Volume", - .info = mixart_digital_vol_info, /* shared */ - .get = mixart_monitor_vol_get, - .put = mixart_monitor_vol_put, - .tlv = { .p = db_scale_digital }, -}; - -/* - * monitoring switch control - */ - -static int mixart_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->monitoring_active[0]; - ucontrol->value.integer.value[1] = chip->monitoring_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_mixart *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int i; - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 2; i++) { - if (chip->monitoring_active[i] != - ucontrol->value.integer.value[i]) { - chip->monitoring_active[i] = - !!ucontrol->value.integer.value[i]; - changed |= (1<monitoring_active[0] || - chip->monitoring_active[1]; - if (allocate) { - /* allocate the playback pipe for monitoring */ - snd_mixart_add_ref_pipe(chip, MIXART_PCM_ANALOG, 0, 1); - /* allocate the capture pipe for monitoring */ - snd_mixart_add_ref_pipe(chip, MIXART_PCM_ANALOG, 1, 1); - } - if (changed & 0x01) - mixart_update_monitoring(chip, 0); - if (changed & 0x02) - mixart_update_monitoring(chip, 1); - if (!allocate) { - /* release the capture pipe for monitoring */ - snd_mixart_kill_ref_pipe(chip->mgr, - &chip->pipe_in_ana, 1); - /* release the playback pipe for monitoring */ - snd_mixart_kill_ref_pipe(chip->mgr, - &chip->pipe_out_ana, 1); - } - } - - mutex_unlock(&chip->mgr->mixer_mutex); - return (changed != 0); -} - -static struct snd_kcontrol_new mixart_control_monitor_sw = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitoring Switch", - .info = mixart_sw_info, /* shared */ - .get = mixart_monitor_sw_get, - .put = mixart_monitor_sw_put -}; - - -static void mixart_reset_audio_levels(struct snd_mixart *chip) -{ - /* analog volumes can be set even if there is no pipe */ - mixart_update_analog_audio_level(chip, 0); - /* analog levels for capture only on the first two chips */ - if(chip->chip_idx < 2) { - mixart_update_analog_audio_level(chip, 1); - } - return; -} - - -int snd_mixart_create_mixer(struct mixart_mgr *mgr) -{ - struct snd_mixart *chip; - int err, i; - - mutex_init(&mgr->mixer_mutex); /* can be in another place */ - - for(i=0; inum_cards; i++) { - struct snd_kcontrol_new temp; - chip = mgr->chip[i]; - - /* analog output level control */ - temp = mixart_control_analog_level; - temp.name = "Master Playback Volume"; - temp.private_value = 0; /* playback */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - /* output mute controls */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_output_switch, chip))) < 0) - return err; - - /* analog input level control only on first two chips !*/ - if(i<2) { - temp = mixart_control_analog_level; - temp.name = "Master Capture Volume"; - temp.private_value = 1; /* capture */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - - temp = snd_mixart_pcm_vol; - temp.name = "PCM Playback Volume"; - temp.count = MIXART_PLAYBACK_STREAMS; - temp.private_value = 0; /* playback analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - - temp.name = "PCM Capture Volume"; - temp.count = 1; - temp.private_value = MIXART_VOL_REC_MASK; /* capture analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - - if(mgr->board_type == MIXART_DAUGHTER_TYPE_AES) { - temp.name = "AES Playback Volume"; - temp.count = MIXART_PLAYBACK_STREAMS; - temp.private_value = MIXART_VOL_AES_MASK; /* playback AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - - temp.name = "AES Capture Volume"; - temp.count = 0; - temp.private_value = MIXART_VOL_REC_MASK | MIXART_VOL_AES_MASK; /* capture AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - temp = mixart_control_pcm_switch; - temp.name = "PCM Playback Switch"; - temp.private_value = 0; /* playback analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - - if(mgr->board_type == MIXART_DAUGHTER_TYPE_AES) { - temp.name = "AES Playback Switch"; - temp.private_value = MIXART_VOL_AES_MASK; /* playback AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) - return err; - } - - /* monitoring */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_vol, chip))) < 0) - return err; - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_sw, chip))) < 0) - return err; - - /* init all mixer data and program the master volumes/switches */ - mixart_reset_audio_levels(chip); - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h b/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h deleted file mode 100644 index 04aa24e3..00000000 --- a/ANDROID_3.4.5/sound/pci/mixart/mixart_mixer.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Driver for Digigram miXart soundcards - * - * include file for mixer - * - * Copyright (c) 2003 by Digigram - * - * 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 - */ - -#ifndef __SOUND_MIXART_MIXER_H -#define __SOUND_MIXART_MIXER_H - -/* exported */ -int mixart_update_playback_stream_level(struct snd_mixart* chip, int is_aes, int idx); -int mixart_update_capture_stream_level(struct snd_mixart* chip, int is_aes); -int snd_mixart_create_mixer(struct mixart_mgr* mgr); - -#endif /* __SOUND_MIXART_MIXER_H */ diff --git a/ANDROID_3.4.5/sound/pci/nm256/Makefile b/ANDROID_3.4.5/sound/pci/nm256/Makefile deleted file mode 100644 index a1bd44ff..00000000 --- a/ANDROID_3.4.5/sound/pci/nm256/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-nm256-objs := nm256.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_NM256) += snd-nm256.o diff --git a/ANDROID_3.4.5/sound/pci/nm256/nm256.c b/ANDROID_3.4.5/sound/pci/nm256/nm256.c deleted file mode 100644 index ade2c64b..00000000 --- a/ANDROID_3.4.5/sound/pci/nm256/nm256.c +++ /dev/null @@ -1,1768 +0,0 @@ -/* - * Driver for NeoMagic 256AV and 256ZX chipsets. - * Copyright (c) 2000 by Takashi Iwai - * - * Based on nm256_audio.c OSS driver in linux kernel. - * The original author of OSS nm256 driver wishes to remain anonymous, - * so I just put my acknoledgment to him/her here. - * The original author's web page is found at - * http://www.uglx.org/sony.html - * - * - * 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 -#include -#include -#include -#include -#include - -#define CARD_NAME "NeoMagic 256AV/ZX" -#define DRIVER_NAME "NM256" - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("NeoMagic NM256AV/ZX"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{NeoMagic,NM256AV}," - "{NeoMagic,NM256ZX}}"); - -/* - * some compile conditions. - */ - -static int index = SNDRV_DEFAULT_IDX1; /* Index */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int playback_bufsize = 16; -static int capture_bufsize = 16; -static bool force_ac97; /* disabled as default */ -static int buffer_top; /* not specified */ -static bool use_cache; /* disabled */ -static bool vaio_hack; /* disabled */ -static bool reset_workaround; -static bool reset_workaround_2; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param(playback_bufsize, int, 0444); -MODULE_PARM_DESC(playback_bufsize, "DAC frame size in kB for " CARD_NAME " soundcard."); -module_param(capture_bufsize, int, 0444); -MODULE_PARM_DESC(capture_bufsize, "ADC frame size in kB for " CARD_NAME " soundcard."); -module_param(force_ac97, bool, 0444); -MODULE_PARM_DESC(force_ac97, "Force to use AC97 codec for " CARD_NAME " soundcard."); -module_param(buffer_top, int, 0444); -MODULE_PARM_DESC(buffer_top, "Set the top address of audio buffer for " CARD_NAME " soundcard."); -module_param(use_cache, bool, 0444); -MODULE_PARM_DESC(use_cache, "Enable the cache for coefficient table access."); -module_param(vaio_hack, bool, 0444); -MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks."); -module_param(reset_workaround, bool, 0444); -MODULE_PARM_DESC(reset_workaround, "Enable AC97 RESET workaround for some laptops."); -module_param(reset_workaround_2, bool, 0444); -MODULE_PARM_DESC(reset_workaround_2, "Enable extended AC97 RESET workaround for some other laptops."); - -/* just for backward compatibility */ -static bool enable; -module_param(enable, bool, 0444); - - - -/* - * hw definitions - */ - -/* The BIOS signature. */ -#define NM_SIGNATURE 0x4e4d0000 -/* Signature mask. */ -#define NM_SIG_MASK 0xffff0000 - -/* Size of the second memory area. */ -#define NM_PORT2_SIZE 4096 - -/* The base offset of the mixer in the second memory area. */ -#define NM_MIXER_OFFSET 0x600 - -/* The maximum size of a coefficient entry. */ -#define NM_MAX_PLAYBACK_COEF_SIZE 0x5000 -#define NM_MAX_RECORD_COEF_SIZE 0x1260 - -/* The interrupt register. */ -#define NM_INT_REG 0xa04 -/* And its bits. */ -#define NM_PLAYBACK_INT 0x40 -#define NM_RECORD_INT 0x100 -#define NM_MISC_INT_1 0x4000 -#define NM_MISC_INT_2 0x1 -#define NM_ACK_INT(chip, X) snd_nm256_writew(chip, NM_INT_REG, (X) << 1) - -/* The AV's "mixer ready" status bit and location. */ -#define NM_MIXER_STATUS_OFFSET 0xa04 -#define NM_MIXER_READY_MASK 0x0800 -#define NM_MIXER_PRESENCE 0xa06 -#define NM_PRESENCE_MASK 0x0050 -#define NM_PRESENCE_VALUE 0x0040 - -/* - * For the ZX. It uses the same interrupt register, but it holds 32 - * bits instead of 16. - */ -#define NM2_PLAYBACK_INT 0x10000 -#define NM2_RECORD_INT 0x80000 -#define NM2_MISC_INT_1 0x8 -#define NM2_MISC_INT_2 0x2 -#define NM2_ACK_INT(chip, X) snd_nm256_writel(chip, NM_INT_REG, (X)) - -/* The ZX's "mixer ready" status bit and location. */ -#define NM2_MIXER_STATUS_OFFSET 0xa06 -#define NM2_MIXER_READY_MASK 0x0800 - -/* The playback registers start from here. */ -#define NM_PLAYBACK_REG_OFFSET 0x0 -/* The record registers start from here. */ -#define NM_RECORD_REG_OFFSET 0x200 - -/* The rate register is located 2 bytes from the start of the register area. */ -#define NM_RATE_REG_OFFSET 2 - -/* Mono/stereo flag, number of bits on playback, and rate mask. */ -#define NM_RATE_STEREO 1 -#define NM_RATE_BITS_16 2 -#define NM_RATE_MASK 0xf0 - -/* Playback enable register. */ -#define NM_PLAYBACK_ENABLE_REG (NM_PLAYBACK_REG_OFFSET + 0x1) -#define NM_PLAYBACK_ENABLE_FLAG 1 -#define NM_PLAYBACK_ONESHOT 2 -#define NM_PLAYBACK_FREERUN 4 - -/* Mutes the audio output. */ -#define NM_AUDIO_MUTE_REG (NM_PLAYBACK_REG_OFFSET + 0x18) -#define NM_AUDIO_MUTE_LEFT 0x8000 -#define NM_AUDIO_MUTE_RIGHT 0x0080 - -/* Recording enable register. */ -#define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0) -#define NM_RECORD_ENABLE_FLAG 1 -#define NM_RECORD_FREERUN 2 - -/* coefficient buffer pointer */ -#define NM_COEFF_START_OFFSET 0x1c -#define NM_COEFF_END_OFFSET 0x20 - -/* DMA buffer offsets */ -#define NM_RBUFFER_START (NM_RECORD_REG_OFFSET + 0x4) -#define NM_RBUFFER_END (NM_RECORD_REG_OFFSET + 0x10) -#define NM_RBUFFER_WMARK (NM_RECORD_REG_OFFSET + 0xc) -#define NM_RBUFFER_CURRP (NM_RECORD_REG_OFFSET + 0x8) - -#define NM_PBUFFER_START (NM_PLAYBACK_REG_OFFSET + 0x4) -#define NM_PBUFFER_END (NM_PLAYBACK_REG_OFFSET + 0x14) -#define NM_PBUFFER_WMARK (NM_PLAYBACK_REG_OFFSET + 0xc) -#define NM_PBUFFER_CURRP (NM_PLAYBACK_REG_OFFSET + 0x8) - -struct nm256_stream { - - struct nm256 *chip; - struct snd_pcm_substream *substream; - int running; - int suspended; - - u32 buf; /* offset from chip->buffer */ - int bufsize; /* buffer size in bytes */ - void __iomem *bufptr; /* mapped pointer */ - unsigned long bufptr_addr; /* physical address of the mapped pointer */ - - int dma_size; /* buffer size of the substream in bytes */ - int period_size; /* period size in bytes */ - int periods; /* # of periods */ - int shift; /* bit shifts */ - int cur_period; /* current period # */ - -}; - -struct nm256 { - - struct snd_card *card; - - void __iomem *cport; /* control port */ - struct resource *res_cport; /* its resource */ - unsigned long cport_addr; /* physical address */ - - void __iomem *buffer; /* buffer */ - struct resource *res_buffer; /* its resource */ - unsigned long buffer_addr; /* buffer phyiscal address */ - - u32 buffer_start; /* start offset from pci resource 0 */ - u32 buffer_end; /* end offset */ - u32 buffer_size; /* total buffer size */ - - u32 all_coeff_buf; /* coefficient buffer */ - u32 coeff_buf[2]; /* coefficient buffer for each stream */ - - unsigned int coeffs_current: 1; /* coeff. table is loaded? */ - unsigned int use_cache: 1; /* use one big coef. table */ - unsigned int reset_workaround: 1; /* Workaround for some laptops to avoid freeze */ - unsigned int reset_workaround_2: 1; /* Extended workaround for some other laptops to avoid freeze */ - unsigned int in_resume: 1; - - int mixer_base; /* register offset of ac97 mixer */ - int mixer_status_offset; /* offset of mixer status reg. */ - int mixer_status_mask; /* bit mask to test the mixer status */ - - int irq; - int irq_acks; - irq_handler_t interrupt; - int badintrcount; /* counter to check bogus interrupts */ - struct mutex irq_mutex; - - struct nm256_stream streams[2]; - - struct snd_ac97 *ac97; - unsigned short *ac97_regs; /* register caches, only for valid regs */ - - struct snd_pcm *pcm; - - struct pci_dev *pci; - - spinlock_t reg_lock; - -}; - - -/* - * include coefficient table - */ -#include "nm256_coef.c" - - -/* - * PCI ids - */ -static DEFINE_PCI_DEVICE_TABLE(snd_nm256_ids) = { - {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO), 0}, - {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO), 0}, - {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO), 0}, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, snd_nm256_ids); - - -/* - * lowlvel stuffs - */ - -static inline u8 -snd_nm256_readb(struct nm256 *chip, int offset) -{ - return readb(chip->cport + offset); -} - -static inline u16 -snd_nm256_readw(struct nm256 *chip, int offset) -{ - return readw(chip->cport + offset); -} - -static inline u32 -snd_nm256_readl(struct nm256 *chip, int offset) -{ - return readl(chip->cport + offset); -} - -static inline void -snd_nm256_writeb(struct nm256 *chip, int offset, u8 val) -{ - writeb(val, chip->cport + offset); -} - -static inline void -snd_nm256_writew(struct nm256 *chip, int offset, u16 val) -{ - writew(val, chip->cport + offset); -} - -static inline void -snd_nm256_writel(struct nm256 *chip, int offset, u32 val) -{ - writel(val, chip->cport + offset); -} - -static inline void -snd_nm256_write_buffer(struct nm256 *chip, void *src, int offset, int size) -{ - offset -= chip->buffer_start; -#ifdef CONFIG_SND_DEBUG - if (offset < 0 || offset >= chip->buffer_size) { - snd_printk(KERN_ERR "write_buffer invalid offset = %d size = %d\n", - offset, size); - return; - } -#endif - memcpy_toio(chip->buffer + offset, src, size); -} - -/* - * coefficient handlers -- what a magic! - */ - -static u16 -snd_nm256_get_start_offset(int which) -{ - u16 offset = 0; - while (which-- > 0) - offset += coefficient_sizes[which]; - return offset; -} - -static void -snd_nm256_load_one_coefficient(struct nm256 *chip, int stream, u32 port, int which) -{ - u32 coeff_buf = chip->coeff_buf[stream]; - u16 offset = snd_nm256_get_start_offset(which); - u16 size = coefficient_sizes[which]; - - snd_nm256_write_buffer(chip, coefficients + offset, coeff_buf, size); - snd_nm256_writel(chip, port, coeff_buf); - /* ??? Record seems to behave differently than playback. */ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - size--; - snd_nm256_writel(chip, port + 4, coeff_buf + size); -} - -static void -snd_nm256_load_coefficient(struct nm256 *chip, int stream, int number) -{ - /* The enable register for the specified engine. */ - u32 poffset = (stream == SNDRV_PCM_STREAM_CAPTURE ? - NM_RECORD_ENABLE_REG : NM_PLAYBACK_ENABLE_REG); - u32 addr = NM_COEFF_START_OFFSET; - - addr += (stream == SNDRV_PCM_STREAM_CAPTURE ? - NM_RECORD_REG_OFFSET : NM_PLAYBACK_REG_OFFSET); - - if (snd_nm256_readb(chip, poffset) & 1) { - snd_printd("NM256: Engine was enabled while loading coefficients!\n"); - return; - } - - /* The recording engine uses coefficient values 8-15. */ - number &= 7; - if (stream == SNDRV_PCM_STREAM_CAPTURE) - number += 8; - - if (! chip->use_cache) { - snd_nm256_load_one_coefficient(chip, stream, addr, number); - return; - } - if (! chip->coeffs_current) { - snd_nm256_write_buffer(chip, coefficients, chip->all_coeff_buf, - NM_TOTAL_COEFF_COUNT * 4); - chip->coeffs_current = 1; - } else { - u32 base = chip->all_coeff_buf; - u32 offset = snd_nm256_get_start_offset(number); - u32 end_offset = offset + coefficient_sizes[number]; - snd_nm256_writel(chip, addr, base + offset); - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - end_offset--; - snd_nm256_writel(chip, addr + 4, base + end_offset); - } -} - - -/* The actual rates supported by the card. */ -static unsigned int samplerates[8] = { - 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, -}; -static struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(samplerates), - .list = samplerates, - .mask = 0, -}; - -/* - * return the index of the target rate - */ -static int -snd_nm256_fixed_rate(unsigned int rate) -{ - unsigned int i; - for (i = 0; i < ARRAY_SIZE(samplerates); i++) { - if (rate == samplerates[i]) - return i; - } - snd_BUG(); - return 0; -} - -/* - * set sample rate and format - */ -static void -snd_nm256_set_format(struct nm256 *chip, struct nm256_stream *s, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int rate_index = snd_nm256_fixed_rate(runtime->rate); - unsigned char ratebits = (rate_index << 4) & NM_RATE_MASK; - - s->shift = 0; - if (snd_pcm_format_width(runtime->format) == 16) { - ratebits |= NM_RATE_BITS_16; - s->shift++; - } - if (runtime->channels > 1) { - ratebits |= NM_RATE_STEREO; - s->shift++; - } - - runtime->rate = samplerates[rate_index]; - - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - snd_nm256_load_coefficient(chip, 0, rate_index); /* 0 = playback */ - snd_nm256_writeb(chip, - NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET, - ratebits); - break; - case SNDRV_PCM_STREAM_CAPTURE: - snd_nm256_load_coefficient(chip, 1, rate_index); /* 1 = record */ - snd_nm256_writeb(chip, - NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET, - ratebits); - break; - } -} - -/* acquire interrupt */ -static int snd_nm256_acquire_irq(struct nm256 *chip) -{ - mutex_lock(&chip->irq_mutex); - if (chip->irq < 0) { - if (request_irq(chip->pci->irq, chip->interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); - mutex_unlock(&chip->irq_mutex); - return -EBUSY; - } - chip->irq = chip->pci->irq; - } - chip->irq_acks++; - mutex_unlock(&chip->irq_mutex); - return 0; -} - -/* release interrupt */ -static void snd_nm256_release_irq(struct nm256 *chip) -{ - mutex_lock(&chip->irq_mutex); - if (chip->irq_acks > 0) - chip->irq_acks--; - if (chip->irq_acks == 0 && chip->irq >= 0) { - free_irq(chip->irq, chip); - chip->irq = -1; - } - mutex_unlock(&chip->irq_mutex); -} - -/* - * start / stop - */ - -/* update the watermark (current period) */ -static void snd_nm256_pcm_mark(struct nm256 *chip, struct nm256_stream *s, int reg) -{ - s->cur_period++; - s->cur_period %= s->periods; - snd_nm256_writel(chip, reg, s->buf + s->cur_period * s->period_size); -} - -#define snd_nm256_playback_mark(chip, s) snd_nm256_pcm_mark(chip, s, NM_PBUFFER_WMARK) -#define snd_nm256_capture_mark(chip, s) snd_nm256_pcm_mark(chip, s, NM_RBUFFER_WMARK) - -static void -snd_nm256_playback_start(struct nm256 *chip, struct nm256_stream *s, - struct snd_pcm_substream *substream) -{ - /* program buffer pointers */ - snd_nm256_writel(chip, NM_PBUFFER_START, s->buf); - snd_nm256_writel(chip, NM_PBUFFER_END, s->buf + s->dma_size - (1 << s->shift)); - snd_nm256_writel(chip, NM_PBUFFER_CURRP, s->buf); - snd_nm256_playback_mark(chip, s); - - /* Enable playback engine and interrupts. */ - snd_nm256_writeb(chip, NM_PLAYBACK_ENABLE_REG, - NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN); - /* Enable both channels. */ - snd_nm256_writew(chip, NM_AUDIO_MUTE_REG, 0x0); -} - -static void -snd_nm256_capture_start(struct nm256 *chip, struct nm256_stream *s, - struct snd_pcm_substream *substream) -{ - /* program buffer pointers */ - snd_nm256_writel(chip, NM_RBUFFER_START, s->buf); - snd_nm256_writel(chip, NM_RBUFFER_END, s->buf + s->dma_size); - snd_nm256_writel(chip, NM_RBUFFER_CURRP, s->buf); - snd_nm256_capture_mark(chip, s); - - /* Enable playback engine and interrupts. */ - snd_nm256_writeb(chip, NM_RECORD_ENABLE_REG, - NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN); -} - -/* Stop the play engine. */ -static void -snd_nm256_playback_stop(struct nm256 *chip) -{ - /* Shut off sound from both channels. */ - snd_nm256_writew(chip, NM_AUDIO_MUTE_REG, - NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT); - /* Disable play engine. */ - snd_nm256_writeb(chip, NM_PLAYBACK_ENABLE_REG, 0); -} - -static void -snd_nm256_capture_stop(struct nm256 *chip) -{ - /* Disable recording engine. */ - snd_nm256_writeb(chip, NM_RECORD_ENABLE_REG, 0); -} - -static int -snd_nm256_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - struct nm256_stream *s = substream->runtime->private_data; - int err = 0; - - if (snd_BUG_ON(!s)) - return -ENXIO; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - s->suspended = 0; - /* fallthru */ - case SNDRV_PCM_TRIGGER_START: - if (! s->running) { - snd_nm256_playback_start(chip, s, substream); - s->running = 1; - } - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - s->suspended = 1; - /* fallthru */ - case SNDRV_PCM_TRIGGER_STOP: - if (s->running) { - snd_nm256_playback_stop(chip); - s->running = 0; - } - break; - default: - err = -EINVAL; - break; - } - spin_unlock(&chip->reg_lock); - return err; -} - -static int -snd_nm256_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - struct nm256_stream *s = substream->runtime->private_data; - int err = 0; - - if (snd_BUG_ON(!s)) - return -ENXIO; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (! s->running) { - snd_nm256_capture_start(chip, s, substream); - s->running = 1; - } - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (s->running) { - snd_nm256_capture_stop(chip); - s->running = 0; - } - break; - default: - err = -EINVAL; - break; - } - spin_unlock(&chip->reg_lock); - return err; -} - - -/* - * prepare playback/capture channel - */ -static int snd_nm256_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct nm256_stream *s = runtime->private_data; - - if (snd_BUG_ON(!s)) - return -ENXIO; - s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size); - s->period_size = frames_to_bytes(runtime, substream->runtime->period_size); - s->periods = substream->runtime->periods; - s->cur_period = 0; - - spin_lock_irq(&chip->reg_lock); - s->running = 0; - snd_nm256_set_format(chip, s, substream); - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - - -/* - * get the current pointer - */ -static snd_pcm_uframes_t -snd_nm256_playback_pointer(struct snd_pcm_substream *substream) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - struct nm256_stream *s = substream->runtime->private_data; - unsigned long curp; - - if (snd_BUG_ON(!s)) - return 0; - curp = snd_nm256_readl(chip, NM_PBUFFER_CURRP) - (unsigned long)s->buf; - curp %= s->dma_size; - return bytes_to_frames(substream->runtime, curp); -} - -static snd_pcm_uframes_t -snd_nm256_capture_pointer(struct snd_pcm_substream *substream) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - struct nm256_stream *s = substream->runtime->private_data; - unsigned long curp; - - if (snd_BUG_ON(!s)) - return 0; - curp = snd_nm256_readl(chip, NM_RBUFFER_CURRP) - (unsigned long)s->buf; - curp %= s->dma_size; - return bytes_to_frames(substream->runtime, curp); -} - -/* Remapped I/O space can be accessible as pointer on i386 */ -/* This might be changed in the future */ -#ifndef __i386__ -/* - * silence / copy for playback - */ -static int -snd_nm256_playback_silence(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nm256_stream *s = runtime->private_data; - count = frames_to_bytes(runtime, count); - pos = frames_to_bytes(runtime, pos); - memset_io(s->bufptr + pos, 0, count); - return 0; -} - -static int -snd_nm256_playback_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nm256_stream *s = runtime->private_data; - count = frames_to_bytes(runtime, count); - pos = frames_to_bytes(runtime, pos); - if (copy_from_user_toio(s->bufptr + pos, src, count)) - return -EFAULT; - return 0; -} - -/* - * copy to user - */ -static int -snd_nm256_capture_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nm256_stream *s = runtime->private_data; - count = frames_to_bytes(runtime, count); - pos = frames_to_bytes(runtime, pos); - if (copy_to_user_fromio(dst, s->bufptr + pos, count)) - return -EFAULT; - return 0; -} - -#endif /* !__i386__ */ - - -/* - * update playback/capture watermarks - */ - -/* spinlock held! */ -static void -snd_nm256_playback_update(struct nm256 *chip) -{ - struct nm256_stream *s; - - s = &chip->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (s->running && s->substream) { - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(s->substream); - spin_lock(&chip->reg_lock); - snd_nm256_playback_mark(chip, s); - } -} - -/* spinlock held! */ -static void -snd_nm256_capture_update(struct nm256 *chip) -{ - struct nm256_stream *s; - - s = &chip->streams[SNDRV_PCM_STREAM_CAPTURE]; - if (s->running && s->substream) { - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(s->substream); - spin_lock(&chip->reg_lock); - snd_nm256_capture_mark(chip, s); - } -} - -/* - * hardware info - */ -static struct snd_pcm_hardware snd_nm256_playback = -{ - .info = SNDRV_PCM_INFO_MMAP_IOMEM |SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - /*SNDRV_PCM_INFO_PAUSE |*/ - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_KNOT/*24k*/ | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .periods_min = 2, - .periods_max = 1024, - .buffer_bytes_max = 128 * 1024, - .period_bytes_min = 256, - .period_bytes_max = 128 * 1024, -}; - -static struct snd_pcm_hardware snd_nm256_capture = -{ - .info = SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - /*SNDRV_PCM_INFO_PAUSE |*/ - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_KNOT/*24k*/ | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .periods_min = 2, - .periods_max = 1024, - .buffer_bytes_max = 128 * 1024, - .period_bytes_min = 256, - .period_bytes_max = 128 * 1024, -}; - - -/* set dma transfer size */ -static int snd_nm256_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - /* area and addr are already set and unchanged */ - substream->runtime->dma_bytes = params_buffer_bytes(hw_params); - return 0; -} - -/* - * open - */ -static void snd_nm256_setup_stream(struct nm256 *chip, struct nm256_stream *s, - struct snd_pcm_substream *substream, - struct snd_pcm_hardware *hw_ptr) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - s->running = 0; - runtime->hw = *hw_ptr; - runtime->hw.buffer_bytes_max = s->bufsize; - runtime->hw.period_bytes_max = s->bufsize / 2; - runtime->dma_area = (void __force *) s->bufptr; - runtime->dma_addr = s->bufptr_addr; - runtime->dma_bytes = s->bufsize; - runtime->private_data = s; - s->substream = substream; - - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); -} - -static int -snd_nm256_playback_open(struct snd_pcm_substream *substream) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - - if (snd_nm256_acquire_irq(chip) < 0) - return -EBUSY; - snd_nm256_setup_stream(chip, &chip->streams[SNDRV_PCM_STREAM_PLAYBACK], - substream, &snd_nm256_playback); - return 0; -} - -static int -snd_nm256_capture_open(struct snd_pcm_substream *substream) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - - if (snd_nm256_acquire_irq(chip) < 0) - return -EBUSY; - snd_nm256_setup_stream(chip, &chip->streams[SNDRV_PCM_STREAM_CAPTURE], - substream, &snd_nm256_capture); - return 0; -} - -/* - * close - we don't have to do special.. - */ -static int -snd_nm256_playback_close(struct snd_pcm_substream *substream) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - - snd_nm256_release_irq(chip); - return 0; -} - - -static int -snd_nm256_capture_close(struct snd_pcm_substream *substream) -{ - struct nm256 *chip = snd_pcm_substream_chip(substream); - - snd_nm256_release_irq(chip); - return 0; -} - -/* - * create a pcm instance - */ -static struct snd_pcm_ops snd_nm256_playback_ops = { - .open = snd_nm256_playback_open, - .close = snd_nm256_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_nm256_pcm_hw_params, - .prepare = snd_nm256_pcm_prepare, - .trigger = snd_nm256_playback_trigger, - .pointer = snd_nm256_playback_pointer, -#ifndef __i386__ - .copy = snd_nm256_playback_copy, - .silence = snd_nm256_playback_silence, -#endif - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static struct snd_pcm_ops snd_nm256_capture_ops = { - .open = snd_nm256_capture_open, - .close = snd_nm256_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_nm256_pcm_hw_params, - .prepare = snd_nm256_pcm_prepare, - .trigger = snd_nm256_capture_trigger, - .pointer = snd_nm256_capture_pointer, -#ifndef __i386__ - .copy = snd_nm256_capture_copy, -#endif - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static int __devinit -snd_nm256_pcm(struct nm256 *chip, int device) -{ - struct snd_pcm *pcm; - int i, err; - - for (i = 0; i < 2; i++) { - struct nm256_stream *s = &chip->streams[i]; - s->bufptr = chip->buffer + (s->buf - chip->buffer_start); - s->bufptr_addr = chip->buffer_addr + (s->buf - chip->buffer_start); - } - - err = snd_pcm_new(chip->card, chip->card->driver, device, - 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_nm256_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_nm256_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - chip->pcm = pcm; - - return 0; -} - - -/* - * Initialize the hardware. - */ -static void -snd_nm256_init_chip(struct nm256 *chip) -{ - /* Reset everything. */ - snd_nm256_writeb(chip, 0x0, 0x11); - snd_nm256_writew(chip, 0x214, 0); - /* stop sounds.. */ - //snd_nm256_playback_stop(chip); - //snd_nm256_capture_stop(chip); -} - - -static irqreturn_t -snd_nm256_intr_check(struct nm256 *chip) -{ - if (chip->badintrcount++ > 1000) { - /* - * I'm not sure if the best thing is to stop the card from - * playing or just release the interrupt (after all, we're in - * a bad situation, so doing fancy stuff may not be such a good - * idea). - * - * I worry about the card engine continuing to play noise - * over and over, however--that could become a very - * obnoxious problem. And we know that when this usually - * happens things are fairly safe, it just means the user's - * inserted a PCMCIA card and someone's spamming us with IRQ 9s. - */ - if (chip->streams[SNDRV_PCM_STREAM_PLAYBACK].running) - snd_nm256_playback_stop(chip); - if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running) - snd_nm256_capture_stop(chip); - chip->badintrcount = 0; - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/* - * Handle a potential interrupt for the device referred to by DEV_ID. - * - * I don't like the cut-n-paste job here either between the two routines, - * but there are sufficient differences between the two interrupt handlers - * that parameterizing it isn't all that great either. (Could use a macro, - * I suppose...yucky bleah.) - */ - -static irqreturn_t -snd_nm256_interrupt(int irq, void *dev_id) -{ - struct nm256 *chip = dev_id; - u16 status; - u8 cbyte; - - status = snd_nm256_readw(chip, NM_INT_REG); - - /* Not ours. */ - if (status == 0) - return snd_nm256_intr_check(chip); - - chip->badintrcount = 0; - - /* Rather boring; check for individual interrupts and process them. */ - - spin_lock(&chip->reg_lock); - if (status & NM_PLAYBACK_INT) { - status &= ~NM_PLAYBACK_INT; - NM_ACK_INT(chip, NM_PLAYBACK_INT); - snd_nm256_playback_update(chip); - } - - if (status & NM_RECORD_INT) { - status &= ~NM_RECORD_INT; - NM_ACK_INT(chip, NM_RECORD_INT); - snd_nm256_capture_update(chip); - } - - if (status & NM_MISC_INT_1) { - status &= ~NM_MISC_INT_1; - NM_ACK_INT(chip, NM_MISC_INT_1); - snd_printd("NM256: Got misc interrupt #1\n"); - snd_nm256_writew(chip, NM_INT_REG, 0x8000); - cbyte = snd_nm256_readb(chip, 0x400); - snd_nm256_writeb(chip, 0x400, cbyte | 2); - } - - if (status & NM_MISC_INT_2) { - status &= ~NM_MISC_INT_2; - NM_ACK_INT(chip, NM_MISC_INT_2); - snd_printd("NM256: Got misc interrupt #2\n"); - cbyte = snd_nm256_readb(chip, 0x400); - snd_nm256_writeb(chip, 0x400, cbyte & ~2); - } - - /* Unknown interrupt. */ - if (status) { - snd_printd("NM256: Fire in the hole! Unknown status 0x%x\n", - status); - /* Pray. */ - NM_ACK_INT(chip, status); - } - - spin_unlock(&chip->reg_lock); - return IRQ_HANDLED; -} - -/* - * Handle a potential interrupt for the device referred to by DEV_ID. - * This handler is for the 256ZX, and is very similar to the non-ZX - * routine. - */ - -static irqreturn_t -snd_nm256_interrupt_zx(int irq, void *dev_id) -{ - struct nm256 *chip = dev_id; - u32 status; - u8 cbyte; - - status = snd_nm256_readl(chip, NM_INT_REG); - - /* Not ours. */ - if (status == 0) - return snd_nm256_intr_check(chip); - - chip->badintrcount = 0; - - /* Rather boring; check for individual interrupts and process them. */ - - spin_lock(&chip->reg_lock); - if (status & NM2_PLAYBACK_INT) { - status &= ~NM2_PLAYBACK_INT; - NM2_ACK_INT(chip, NM2_PLAYBACK_INT); - snd_nm256_playback_update(chip); - } - - if (status & NM2_RECORD_INT) { - status &= ~NM2_RECORD_INT; - NM2_ACK_INT(chip, NM2_RECORD_INT); - snd_nm256_capture_update(chip); - } - - if (status & NM2_MISC_INT_1) { - status &= ~NM2_MISC_INT_1; - NM2_ACK_INT(chip, NM2_MISC_INT_1); - snd_printd("NM256: Got misc interrupt #1\n"); - cbyte = snd_nm256_readb(chip, 0x400); - snd_nm256_writeb(chip, 0x400, cbyte | 2); - } - - if (status & NM2_MISC_INT_2) { - status &= ~NM2_MISC_INT_2; - NM2_ACK_INT(chip, NM2_MISC_INT_2); - snd_printd("NM256: Got misc interrupt #2\n"); - cbyte = snd_nm256_readb(chip, 0x400); - snd_nm256_writeb(chip, 0x400, cbyte & ~2); - } - - /* Unknown interrupt. */ - if (status) { - snd_printd("NM256: Fire in the hole! Unknown status 0x%x\n", - status); - /* Pray. */ - NM2_ACK_INT(chip, status); - } - - spin_unlock(&chip->reg_lock); - return IRQ_HANDLED; -} - -/* - * AC97 interface - */ - -/* - * Waits for the mixer to become ready to be written; returns a zero value - * if it timed out. - */ -static int -snd_nm256_ac97_ready(struct nm256 *chip) -{ - int timeout = 10; - u32 testaddr; - u16 testb; - - testaddr = chip->mixer_status_offset; - testb = chip->mixer_status_mask; - - /* - * Loop around waiting for the mixer to become ready. - */ - while (timeout-- > 0) { - if ((snd_nm256_readw(chip, testaddr) & testb) == 0) - return 1; - udelay(100); - } - return 0; -} - -/* - * Initial register values to be written to the AC97 mixer. - * While most of these are identical to the reset values, we do this - * so that we have most of the register contents cached--this avoids - * reading from the mixer directly (which seems to be problematic, - * probably due to ignorance). - */ - -struct initialValues { - unsigned short reg; - unsigned short value; -}; - -static struct initialValues nm256_ac97_init_val[] = -{ - { AC97_MASTER, 0x8000 }, - { AC97_HEADPHONE, 0x8000 }, - { AC97_MASTER_MONO, 0x8000 }, - { AC97_PC_BEEP, 0x8000 }, - { AC97_PHONE, 0x8008 }, - { AC97_MIC, 0x8000 }, - { AC97_LINE, 0x8808 }, - { AC97_CD, 0x8808 }, - { AC97_VIDEO, 0x8808 }, - { AC97_AUX, 0x8808 }, - { AC97_PCM, 0x8808 }, - { AC97_REC_SEL, 0x0000 }, - { AC97_REC_GAIN, 0x0B0B }, - { AC97_GENERAL_PURPOSE, 0x0000 }, - { AC97_3D_CONTROL, 0x8000 }, - { AC97_VENDOR_ID1, 0x8384 }, - { AC97_VENDOR_ID2, 0x7609 }, -}; - -static int nm256_ac97_idx(unsigned short reg) -{ - int i; - for (i = 0; i < ARRAY_SIZE(nm256_ac97_init_val); i++) - if (nm256_ac97_init_val[i].reg == reg) - return i; - return -1; -} - -/* - * some nm256 easily crash when reading from mixer registers - * thus we're treating it as a write-only mixer and cache the - * written values - */ -static unsigned short -snd_nm256_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct nm256 *chip = ac97->private_data; - int idx = nm256_ac97_idx(reg); - - if (idx < 0) - return 0; - return chip->ac97_regs[idx]; -} - -/* - */ -static void -snd_nm256_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - struct nm256 *chip = ac97->private_data; - int tries = 2; - int idx = nm256_ac97_idx(reg); - u32 base; - - if (idx < 0) - return; - - base = chip->mixer_base; - - snd_nm256_ac97_ready(chip); - - /* Wait for the write to take, too. */ - while (tries-- > 0) { - snd_nm256_writew(chip, base + reg, val); - msleep(1); /* a little delay here seems better.. */ - if (snd_nm256_ac97_ready(chip)) { - /* successful write: set cache */ - chip->ac97_regs[idx] = val; - return; - } - } - snd_printd("nm256: ac97 codec not ready..\n"); -} - -/* static resolution table */ -static struct snd_ac97_res_table nm256_res_table[] = { - { AC97_MASTER, 0x1f1f }, - { AC97_HEADPHONE, 0x1f1f }, - { AC97_MASTER_MONO, 0x001f }, - { AC97_PC_BEEP, 0x001f }, - { AC97_PHONE, 0x001f }, - { AC97_MIC, 0x001f }, - { AC97_LINE, 0x1f1f }, - { AC97_CD, 0x1f1f }, - { AC97_VIDEO, 0x1f1f }, - { AC97_AUX, 0x1f1f }, - { AC97_PCM, 0x1f1f }, - { AC97_REC_GAIN, 0x0f0f }, - { } /* terminator */ -}; - -/* initialize the ac97 into a known state */ -static void -snd_nm256_ac97_reset(struct snd_ac97 *ac97) -{ - struct nm256 *chip = ac97->private_data; - - /* Reset the mixer. 'Tis magic! */ - snd_nm256_writeb(chip, 0x6c0, 1); - if (! chip->reset_workaround) { - /* Dell latitude LS will lock up by this */ - snd_nm256_writeb(chip, 0x6cc, 0x87); - } - if (! chip->reset_workaround_2) { - /* Dell latitude CSx will lock up by this */ - snd_nm256_writeb(chip, 0x6cc, 0x80); - snd_nm256_writeb(chip, 0x6cc, 0x0); - } - if (! chip->in_resume) { - int i; - for (i = 0; i < ARRAY_SIZE(nm256_ac97_init_val); i++) { - /* preload the cache, so as to avoid even a single - * read of the mixer regs - */ - snd_nm256_ac97_write(ac97, nm256_ac97_init_val[i].reg, - nm256_ac97_init_val[i].value); - } - } -} - -/* create an ac97 mixer interface */ -static int __devinit -snd_nm256_mixer(struct nm256 *chip) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .reset = snd_nm256_ac97_reset, - .write = snd_nm256_ac97_write, - .read = snd_nm256_ac97_read, - }; - - chip->ac97_regs = kcalloc(ARRAY_SIZE(nm256_ac97_init_val), - sizeof(short), GFP_KERNEL); - if (! chip->ac97_regs) - return -ENOMEM; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) - return err; - - memset(&ac97, 0, sizeof(ac97)); - ac97.scaps = AC97_SCAP_AUDIO; /* we support audio! */ - ac97.private_data = chip; - ac97.res_table = nm256_res_table; - pbus->no_vra = 1; - err = snd_ac97_mixer(pbus, &ac97, &chip->ac97); - if (err < 0) - return err; - if (! (chip->ac97->id & (0xf0000000))) { - /* looks like an invalid id */ - sprintf(chip->card->mixername, "%s AC97", chip->card->driver); - } - return 0; -} - -/* - * See if the signature left by the NM256 BIOS is intact; if so, we use - * the associated address as the end of our audio buffer in the video - * RAM. - */ - -static int __devinit -snd_nm256_peek_for_sig(struct nm256 *chip) -{ - /* The signature is located 1K below the end of video RAM. */ - void __iomem *temp; - /* Default buffer end is 5120 bytes below the top of RAM. */ - unsigned long pointer_found = chip->buffer_end - 0x1400; - u32 sig; - - temp = ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16); - if (temp == NULL) { - snd_printk(KERN_ERR "Unable to scan for card signature in video RAM\n"); - return -EBUSY; - } - - sig = readl(temp); - if ((sig & NM_SIG_MASK) == NM_SIGNATURE) { - u32 pointer = readl(temp + 4); - - /* - * If it's obviously invalid, don't use it - */ - if (pointer == 0xffffffff || - pointer < chip->buffer_size || - pointer > chip->buffer_end) { - snd_printk(KERN_ERR "invalid signature found: 0x%x\n", pointer); - iounmap(temp); - return -ENODEV; - } else { - pointer_found = pointer; - printk(KERN_INFO "nm256: found card signature in video RAM: 0x%x\n", - pointer); - } - } - - iounmap(temp); - chip->buffer_end = pointer_found; - - return 0; -} - -#ifdef CONFIG_PM -/* - * APM event handler, so the card is properly reinitialized after a power - * event. - */ -static int nm256_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct nm256 *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_ac97_suspend(chip->ac97); - chip->coeffs_current = 0; - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int nm256_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct nm256 *chip = card->private_data; - int i; - - /* Perform a full reset on the hardware */ - chip->in_resume = 1; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "nm256: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_nm256_init_chip(chip); - - /* restore ac97 */ - snd_ac97_resume(chip->ac97); - - for (i = 0; i < 2; i++) { - struct nm256_stream *s = &chip->streams[i]; - if (s->substream && s->suspended) { - spin_lock_irq(&chip->reg_lock); - snd_nm256_set_format(chip, s, s->substream); - spin_unlock_irq(&chip->reg_lock); - } - } - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - chip->in_resume = 0; - return 0; -} -#endif /* CONFIG_PM */ - -static int snd_nm256_free(struct nm256 *chip) -{ - if (chip->streams[SNDRV_PCM_STREAM_PLAYBACK].running) - snd_nm256_playback_stop(chip); - if (chip->streams[SNDRV_PCM_STREAM_CAPTURE].running) - snd_nm256_capture_stop(chip); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - if (chip->cport) - iounmap(chip->cport); - if (chip->buffer) - iounmap(chip->buffer); - release_and_free_resource(chip->res_cport); - release_and_free_resource(chip->res_buffer); - - pci_disable_device(chip->pci); - kfree(chip->ac97_regs); - kfree(chip); - return 0; -} - -static int snd_nm256_dev_free(struct snd_device *device) -{ - struct nm256 *chip = device->device_data; - return snd_nm256_free(chip); -} - -static int __devinit -snd_nm256_create(struct snd_card *card, struct pci_dev *pci, - struct nm256 **chip_ret) -{ - struct nm256 *chip; - int err, pval; - static struct snd_device_ops ops = { - .dev_free = snd_nm256_dev_free, - }; - u32 addr; - - *chip_ret = NULL; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - chip->pci = pci; - chip->use_cache = use_cache; - spin_lock_init(&chip->reg_lock); - chip->irq = -1; - mutex_init(&chip->irq_mutex); - - /* store buffer sizes in bytes */ - chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize = playback_bufsize * 1024; - chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize = capture_bufsize * 1024; - - /* - * The NM256 has two memory ports. The first port is nothing - * more than a chunk of video RAM, which is used as the I/O ring - * buffer. The second port has the actual juicy stuff (like the - * mixer and the playback engine control registers). - */ - - chip->buffer_addr = pci_resource_start(pci, 0); - chip->cport_addr = pci_resource_start(pci, 1); - - /* Init the memory port info. */ - /* remap control port (#2) */ - chip->res_cport = request_mem_region(chip->cport_addr, NM_PORT2_SIZE, - card->driver); - if (chip->res_cport == NULL) { - snd_printk(KERN_ERR "memory region 0x%lx (size 0x%x) busy\n", - chip->cport_addr, NM_PORT2_SIZE); - err = -EBUSY; - goto __error; - } - chip->cport = ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE); - if (chip->cport == NULL) { - snd_printk(KERN_ERR "unable to map control port %lx\n", chip->cport_addr); - err = -ENOMEM; - goto __error; - } - - if (!strcmp(card->driver, "NM256AV")) { - /* Ok, try to see if this is a non-AC97 version of the hardware. */ - pval = snd_nm256_readw(chip, NM_MIXER_PRESENCE); - if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) { - if (! force_ac97) { - printk(KERN_ERR "nm256: no ac97 is found!\n"); - printk(KERN_ERR " force the driver to load by " - "passing in the module parameter\n"); - printk(KERN_ERR " force_ac97=1\n"); - printk(KERN_ERR " or try sb16, opl3sa2, or " - "cs423x drivers instead.\n"); - err = -ENXIO; - goto __error; - } - } - chip->buffer_end = 2560 * 1024; - chip->interrupt = snd_nm256_interrupt; - chip->mixer_status_offset = NM_MIXER_STATUS_OFFSET; - chip->mixer_status_mask = NM_MIXER_READY_MASK; - } else { - /* Not sure if there is any relevant detect for the ZX or not. */ - if (snd_nm256_readb(chip, 0xa0b) != 0) - chip->buffer_end = 6144 * 1024; - else - chip->buffer_end = 4096 * 1024; - - chip->interrupt = snd_nm256_interrupt_zx; - chip->mixer_status_offset = NM2_MIXER_STATUS_OFFSET; - chip->mixer_status_mask = NM2_MIXER_READY_MASK; - } - - chip->buffer_size = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize + - chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize; - if (chip->use_cache) - chip->buffer_size += NM_TOTAL_COEFF_COUNT * 4; - else - chip->buffer_size += NM_MAX_PLAYBACK_COEF_SIZE + NM_MAX_RECORD_COEF_SIZE; - - if (buffer_top >= chip->buffer_size && buffer_top < chip->buffer_end) - chip->buffer_end = buffer_top; - else { - /* get buffer end pointer from signature */ - if ((err = snd_nm256_peek_for_sig(chip)) < 0) - goto __error; - } - - chip->buffer_start = chip->buffer_end - chip->buffer_size; - chip->buffer_addr += chip->buffer_start; - - printk(KERN_INFO "nm256: Mapping port 1 from 0x%x - 0x%x\n", - chip->buffer_start, chip->buffer_end); - - chip->res_buffer = request_mem_region(chip->buffer_addr, - chip->buffer_size, - card->driver); - if (chip->res_buffer == NULL) { - snd_printk(KERN_ERR "nm256: buffer 0x%lx (size 0x%x) busy\n", - chip->buffer_addr, chip->buffer_size); - err = -EBUSY; - goto __error; - } - chip->buffer = ioremap_nocache(chip->buffer_addr, chip->buffer_size); - if (chip->buffer == NULL) { - err = -ENOMEM; - snd_printk(KERN_ERR "unable to map ring buffer at %lx\n", chip->buffer_addr); - goto __error; - } - - /* set offsets */ - addr = chip->buffer_start; - chip->streams[SNDRV_PCM_STREAM_PLAYBACK].buf = addr; - addr += chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize; - chip->streams[SNDRV_PCM_STREAM_CAPTURE].buf = addr; - addr += chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize; - if (chip->use_cache) { - chip->all_coeff_buf = addr; - } else { - chip->coeff_buf[SNDRV_PCM_STREAM_PLAYBACK] = addr; - addr += NM_MAX_PLAYBACK_COEF_SIZE; - chip->coeff_buf[SNDRV_PCM_STREAM_CAPTURE] = addr; - } - - /* Fixed setting. */ - chip->mixer_base = NM_MIXER_OFFSET; - - chip->coeffs_current = 0; - - snd_nm256_init_chip(chip); - - // pci_set_master(pci); /* needed? */ - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) - goto __error; - - snd_card_set_dev(card, &pci->dev); - - *chip_ret = chip; - return 0; - -__error: - snd_nm256_free(chip); - return err; -} - - -enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 }; - -static struct snd_pci_quirk nm256_quirks[] __devinitdata = { - /* HP omnibook 4150 has cs4232 codec internally */ - SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_BLACKLISTED), - /* Reset workarounds to avoid lock-ups */ - SND_PCI_QUIRK(0x104d, 0x8041, "Sony PCG-F305", NM_RESET_WORKAROUND), - SND_PCI_QUIRK(0x1028, 0x0080, "Dell Latitude LS", NM_RESET_WORKAROUND), - SND_PCI_QUIRK(0x1028, 0x0091, "Dell Latitude CSx", NM_RESET_WORKAROUND_2), - { } /* terminator */ -}; - - -static int __devinit snd_nm256_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct nm256 *chip; - int err; - const struct snd_pci_quirk *q; - - q = snd_pci_quirk_lookup(pci, nm256_quirks); - if (q) { - snd_printdd(KERN_INFO "nm256: Enabled quirk for %s.\n", q->name); - switch (q->value) { - case NM_BLACKLISTED: - printk(KERN_INFO "nm256: The device is blacklisted. " - "Loading stopped\n"); - return -ENODEV; - case NM_RESET_WORKAROUND_2: - reset_workaround_2 = 1; - /* Fall-through */ - case NM_RESET_WORKAROUND: - reset_workaround = 1; - break; - } - } - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - switch (pci->device) { - case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO: - strcpy(card->driver, "NM256AV"); - break; - case PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO: - strcpy(card->driver, "NM256ZX"); - break; - case PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO: - strcpy(card->driver, "NM256XL+"); - break; - default: - snd_printk(KERN_ERR "invalid device id 0x%x\n", pci->device); - snd_card_free(card); - return -EINVAL; - } - - if (vaio_hack) - buffer_top = 0x25a800; /* this avoids conflicts with XFree86 server */ - - if (playback_bufsize < 4) - playback_bufsize = 4; - if (playback_bufsize > 128) - playback_bufsize = 128; - if (capture_bufsize < 4) - capture_bufsize = 4; - if (capture_bufsize > 128) - capture_bufsize = 128; - if ((err = snd_nm256_create(card, pci, &chip)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = chip; - - if (reset_workaround) { - snd_printdd(KERN_INFO "nm256: reset_workaround activated\n"); - chip->reset_workaround = 1; - } - - if (reset_workaround_2) { - snd_printdd(KERN_INFO "nm256: reset_workaround_2 activated\n"); - chip->reset_workaround_2 = 1; - } - - if ((err = snd_nm256_pcm(chip, 0)) < 0 || - (err = snd_nm256_mixer(chip)) < 0) { - snd_card_free(card); - return err; - } - - sprintf(card->shortname, "NeoMagic %s", card->driver); - sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d", - card->shortname, - chip->buffer_addr, chip->cport_addr, chip->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - return 0; -} - -static void __devexit snd_nm256_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_nm256_ids, - .probe = snd_nm256_probe, - .remove = __devexit_p(snd_nm256_remove), -#ifdef CONFIG_PM - .suspend = nm256_suspend, - .resume = nm256_resume, -#endif -}; - - -static int __init alsa_card_nm256_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_nm256_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_nm256_init) -module_exit(alsa_card_nm256_exit) diff --git a/ANDROID_3.4.5/sound/pci/nm256/nm256_coef.c b/ANDROID_3.4.5/sound/pci/nm256/nm256_coef.c deleted file mode 100644 index 747d5d6c..00000000 --- a/ANDROID_3.4.5/sound/pci/nm256/nm256_coef.c +++ /dev/null @@ -1,4607 +0,0 @@ -#define NM_TOTAL_COEFF_COUNT 0x3158 - -static char coefficients[NM_TOTAL_COEFF_COUNT * 4] = { - 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA5, 0x01, 0xEF, 0xFC, 0x21, - 0x05, 0x87, 0xF7, 0x62, 0x11, 0xE9, 0x45, 0x5E, 0xF9, 0xB5, 0x01, - 0xDE, 0xFF, 0xA4, 0xFF, 0x60, 0x00, 0xCA, 0xFF, 0x0D, 0x00, 0xFD, - 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06, - 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1, - 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFD, 0xFF, - 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, - 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, - 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x02, 0x00, 0x05, - 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3, - 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6, - 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF, - 0x60, 0x00, 0xA4, 0xFF, 0xDE, 0xFF, 0xB5, 0x01, 0x5E, 0xF9, 0xE9, - 0x45, 0x62, 0x11, 0x87, 0xF7, 0x21, 0x05, 0xEF, 0xFC, 0xA5, 0x01, - 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, - 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, - 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, - 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, - 0xCA, 0x01, 0x95, 0xFC, 0xEA, 0x05, 0xBB, 0xF5, 0x25, 0x17, 0x3C, - 0x43, 0x8D, 0xF6, 0x43, 0x03, 0xF5, 0xFE, 0x26, 0x00, 0x20, 0x00, - 0xE2, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5, - 0x01, 0x4C, 0xFC, 0x26, 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33, - 0x8F, 0xF1, 0xCA, 0x06, 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24, - 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD5, 0xFF, 0xBC, 0x00, - 0xF0, 0xFD, 0xEC, 0x04, 0xD9, 0xF3, 0xB1, 0x3E, 0xCD, 0x1E, 0xC1, - 0xF3, 0xAF, 0x06, 0x49, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, - 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38, - 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA, - 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0x98, 0x01, 0x0D, 0xFD, - 0xE0, 0x04, 0x14, 0xF8, 0xC3, 0x0F, 0x89, 0x46, 0x4C, 0xFA, 0x38, - 0x01, 0x25, 0x00, 0x7D, 0xFF, 0x73, 0x00, 0xC2, 0xFF, 0x0F, 0x00, - 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F, - 0x07, 0x84, 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05, - 0x41, 0xFD, 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0x15, 0x00, 0x97, 0xFF, 0x37, 0x01, 0x22, 0xFD, 0x23, 0x06, - 0x2F, 0xF2, 0x11, 0x39, 0x7B, 0x26, 0x50, 0xF2, 0x1B, 0x07, 0x32, - 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, - 0xC8, 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, - 0xF9, 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, - 0xA2, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, - 0x00, 0x6A, 0xFF, 0x53, 0x01, 0xA6, 0xFD, 0xA6, 0x03, 0xA1, 0xFA, - 0xDE, 0x08, 0x76, 0x48, 0x0C, 0xFF, 0xDE, 0xFE, 0x73, 0x01, 0xC9, - 0xFE, 0xCA, 0x00, 0xA0, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, - 0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78, - 0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00, - 0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x68, - 0xFF, 0x93, 0x01, 0x92, 0xFC, 0xE2, 0x06, 0x83, 0xF1, 0x8C, 0x32, - 0xED, 0x2D, 0x90, 0xF1, 0x1E, 0x07, 0x57, 0xFC, 0xBD, 0x01, 0x51, - 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00, - 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76, - 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, - 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF, 0x03, 0x01, 0x53, - 0xFE, 0x53, 0x02, 0x39, 0xFD, 0xA9, 0x02, 0xF2, 0x48, 0xB9, 0x04, - 0x54, 0xFC, 0xCA, 0x02, 0x16, 0xFE, 0x20, 0x01, 0x7F, 0xFF, 0x20, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC3, 0x01, - 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7, 0x43, 0x20, - 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00, 0xDD, 0xFF, - 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCD, 0x01, 0x43, - 0xFC, 0x2A, 0x07, 0xBC, 0xF1, 0x64, 0x2B, 0xE3, 0x34, 0xA3, 0xF1, - 0xAE, 0x06, 0xBD, 0xFC, 0x77, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, - 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8, 0xFD, - 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3, 0xC8, - 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, - 0x14, 0x00, 0xAC, 0xFF, 0xAC, 0x00, 0x08, 0xFF, 0xFD, 0x00, 0xB5, - 0xFF, 0x4B, 0xFD, 0xF4, 0x47, 0x30, 0x0B, 0xBC, 0xF9, 0x17, 0x04, - 0x6E, 0xFD, 0x6D, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01, 0x26, 0xFD, 0xAD, 0x04, - 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C, 0xFB, 0xD4, 0x00, 0x5D, - 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF, 0x10, 0x00, 0xFD, 0xFF, - 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0x01, 0x07, 0xBE, - 0xF2, 0xD6, 0x23, 0x1F, 0x3B, 0xA5, 0xF2, 0xC5, 0x05, 0x62, 0xFD, - 0x10, 0x01, 0xAB, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19, - 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD, 0x4D, 0x06, 0x00, 0xF2, - 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23, 0x07, 0x34, 0xFC, 0xDD, - 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF, - 0x56, 0x00, 0xB9, 0xFF, 0xB8, 0xFF, 0xF7, 0x01, 0xE2, 0xF8, 0x8D, - 0x45, 0x46, 0x12, 0x3C, 0xF7, 0x43, 0x05, 0xDF, 0xFC, 0xAC, 0x01, - 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, - 0xFF, 0x46, 0x01, 0xC3, 0xFD, 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07, - 0xA6, 0x48, 0xF8, 0xFF, 0x70, 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9, - 0x00, 0x9A, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, - 0xDE, 0x01, 0x5D, 0xFC, 0x74, 0x06, 0x63, 0xF4, 0x23, 0x1C, 0x66, - 0x40, 0xAA, 0xF4, 0x65, 0x04, 0x44, 0xFE, 0x8B, 0x00, 0xEE, 0xFF, - 0xF5, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, - 0x01, 0x80, 0xFC, 0xF7, 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, - 0x83, 0xF1, 0x13, 0x07, 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, - 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xED, 0xFF, 0x05, 0x00, 0x5D, 0x00, - 0x95, 0xFE, 0xE2, 0x03, 0x7F, 0xF5, 0xCC, 0x41, 0xC7, 0x19, 0xFF, - 0xF4, 0x37, 0x06, 0x75, 0xFC, 0xD6, 0x01, 0x39, 0xFF, 0x35, 0x00, - 0xFE, 0xFF, 0x1B, 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18, - 0x02, 0xAA, 0xFD, 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB, - 0x05, 0x03, 0xF7, 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBB, 0x01, 0xBA, 0xFC, - 0x95, 0x05, 0x83, 0xF6, 0x8C, 0x14, 0x87, 0x44, 0xBB, 0xF7, 0x98, - 0x02, 0x5A, 0xFF, 0xEE, 0xFF, 0x3C, 0x00, 0xD8, 0xFF, 0x0A, 0x00, - 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, - 0x07, 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, - 0xD5, 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01, - 0x00, 0x07, 0x00, 0xBE, 0xFF, 0xEA, 0x00, 0xA2, 0xFD, 0x65, 0x05, - 0x28, 0xF3, 0xDB, 0x3C, 0x78, 0x21, 0x30, 0xF3, 0xDF, 0x06, 0x3A, - 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, - 0xB2, 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76, - 0xFC, 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD, - 0x79, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, - 0x00, 0x58, 0xFF, 0x82, 0x01, 0x3F, 0xFD, 0x78, 0x04, 0xF2, 0xF8, - 0x50, 0x0D, 0x5E, 0x47, 0xD5, 0xFB, 0x6F, 0x00, 0x96, 0x00, 0x40, - 0xFF, 0x91, 0x00, 0xB7, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, - 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81, - 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00, - 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x85, - 0xFF, 0x5B, 0x01, 0xE9, 0xFC, 0x73, 0x06, 0xD8, 0xF1, 0xE5, 0x36, - 0x19, 0x29, 0xF8, 0xF1, 0x29, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x42, - 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3, 0xFF, 0x47, 0x00, - 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44, 0x8D, - 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45, 0xFF, - 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x75, 0xFF, 0x39, - 0x01, 0xE0, 0xFD, 0x33, 0x03, 0x87, 0xFB, 0xA2, 0x06, 0xCB, 0x48, - 0xEA, 0x00, 0x01, 0xFE, 0xE9, 0x01, 0x8A, 0xFE, 0xE8, 0x00, 0x95, - 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF, 0xDA, 0x01, - 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32, 0x41, 0x1F, - 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF, 0xF0, 0xFF, - 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5B, 0xFF, 0xAB, 0x01, 0x6F, - 0xFC, 0x08, 0x07, 0x7E, 0xF1, 0x21, 0x30, 0x67, 0x30, 0x7D, 0xF1, - 0x05, 0x07, 0x73, 0xFC, 0xA8, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, - 0xFF, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0x67, 0xFE, - 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B, 0xA6, 0xF4, 0x5A, - 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, - 0x1A, 0x00, 0x96, 0xFF, 0xE5, 0x00, 0x91, 0xFE, 0xDC, 0x01, 0x1A, - 0xFE, 0xB3, 0x00, 0xC3, 0x48, 0xE1, 0x06, 0x6E, 0xFB, 0x40, 0x03, - 0xDA, 0xFD, 0x3C, 0x01, 0x74, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05, - 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E, - 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, - 0x33, 0x00, 0x41, 0xFF, 0xD9, 0x01, 0x36, 0xFC, 0x28, 0x07, 0x01, - 0xF2, 0xCE, 0x28, 0x23, 0x37, 0xE0, 0xF1, 0x6B, 0x06, 0xEF, 0xFC, - 0x57, 0x01, 0x87, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B, - 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E, 0xFD, 0x9C, 0x05, 0xDC, 0xF2, - 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2, 0xF3, 0x06, 0x35, 0xFC, 0xE6, - 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xB8, 0xFF, - 0x8E, 0x00, 0x46, 0xFF, 0x8A, 0x00, 0x86, 0x00, 0xA7, 0xFB, 0x48, - 0x47, 0x95, 0x0D, 0xD9, 0xF8, 0x84, 0x04, 0x39, 0xFD, 0x85, 0x01, - 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D, - 0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C, - 0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0, - 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, - 0xE6, 0x01, 0x3B, 0xFC, 0xDA, 0x06, 0x3F, 0xF3, 0x2C, 0x21, 0x11, - 0x3D, 0x3A, 0xF3, 0x58, 0x05, 0xAA, 0xFD, 0xE5, 0x00, 0xC1, 0xFF, - 0x06, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B, - 0x01, 0xCF, 0xFC, 0x96, 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A, - 0xD4, 0xF1, 0x2B, 0x07, 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32, - 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD9, 0xFF, 0x39, 0x00, 0xF4, 0xFF, - 0x4E, 0xFF, 0xAC, 0x02, 0x98, 0xF7, 0x65, 0x44, 0xD6, 0x14, 0x6C, - 0xF6, 0x9F, 0x05, 0xB6, 0xFC, 0xBD, 0x01, 0x42, 0xFF, 0x32, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE, - 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01, - 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C, - 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD5, 0x01, 0x78, 0xFC, - 0x2F, 0x06, 0x13, 0xF5, 0x7C, 0x19, 0xF7, 0x41, 0x9B, 0xF5, 0xD1, - 0x03, 0x9F, 0xFE, 0x57, 0x00, 0x08, 0x00, 0xEC, 0xFF, 0x06, 0x00, - 0xFD, 0xFF, 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16, - 0x07, 0x85, 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06, - 0x84, 0xFC, 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04, - 0x00, 0xF6, 0xFF, 0xEB, 0xFF, 0x91, 0x00, 0x3B, 0xFE, 0x75, 0x04, - 0x92, 0xF4, 0x36, 0x40, 0x6E, 0x1C, 0x50, 0xF4, 0x7B, 0x06, 0x5B, - 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, - 0x9C, 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, - 0xFF, 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, - 0x49, 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, - 0x00, 0x49, 0xFF, 0xAA, 0x01, 0xE4, 0xFC, 0x38, 0x05, 0x54, 0xF7, - 0xFE, 0x11, 0xAA, 0x45, 0x09, 0xF9, 0xE2, 0x01, 0xC4, 0xFF, 0xB3, - 0xFF, 0x59, 0x00, 0xCD, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, - 0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80, - 0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01, - 0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA9, - 0xFF, 0x15, 0x01, 0x5B, 0xFD, 0xD0, 0x05, 0x97, 0xF2, 0xE6, 0x3A, - 0x21, 0x24, 0xB1, 0xF2, 0x04, 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x39, - 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00, - 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD, - 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF, - 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x6A, - 0x01, 0x74, 0xFD, 0x0A, 0x04, 0xD5, 0xF9, 0xED, 0x0A, 0x03, 0x48, - 0x7C, 0xFD, 0x9E, 0xFF, 0x0A, 0x01, 0x01, 0xFF, 0xAF, 0x00, 0xAB, - 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, - 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE, 0x3D, 0x91, - 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF, 0x02, 0x00, - 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x75, 0xFF, 0x7A, 0x01, 0xB8, - 0xFC, 0xB4, 0x06, 0x9E, 0xF1, 0xA2, 0x34, 0xAD, 0x2B, 0xB6, 0xF1, - 0x29, 0x07, 0x45, 0xFC, 0xCB, 0x01, 0x49, 0xFF, 0x31, 0x00, 0xFD, - 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B, 0xFF, - 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6, 0xCA, - 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x20, 0x00, 0x80, 0xFF, 0x1C, 0x01, 0x1C, 0xFE, 0xBD, - 0x02, 0x6E, 0xFC, 0x7D, 0x04, 0xF3, 0x48, 0xE2, 0x02, 0x1F, 0xFD, - 0x60, 0x02, 0x4C, 0xFE, 0x06, 0x01, 0x89, 0xFF, 0x1D, 0x00, 0xFE, - 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01, 0x88, 0xFC, 0x09, 0x06, - 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20, 0xF6, 0x83, 0x03, 0xCF, - 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF, - 0x2E, 0x00, 0x50, 0xFF, 0xBF, 0x01, 0x54, 0xFC, 0x20, 0x07, 0x94, - 0xF1, 0xA6, 0x2D, 0xD0, 0x32, 0x85, 0xF1, 0xDD, 0x06, 0x96, 0xFC, - 0x90, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB, - 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE, 0xB9, 0x04, 0x27, 0xF4, - 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99, 0x06, 0x50, 0xFC, 0xE2, - 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA2, 0xFF, - 0xC7, 0x00, 0xD0, 0xFE, 0x65, 0x01, 0xF6, 0xFE, 0xD9, 0xFE, 0x6A, - 0x48, 0x1F, 0x09, 0x87, 0xFA, 0xB3, 0x03, 0xA0, 0xFD, 0x56, 0x01, - 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4D, - 0xFF, 0xA0, 0x01, 0xFB, 0xFC, 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10, - 0x2B, 0x46, 0xBB, 0xF9, 0x83, 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68, - 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, - 0xE1, 0x01, 0x31, 0xFC, 0x19, 0x07, 0x5B, 0xF2, 0x30, 0x26, 0x4B, - 0x39, 0x3B, 0xF2, 0x1A, 0x06, 0x29, 0xFD, 0x33, 0x01, 0x99, 0xFF, - 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, - 0x01, 0x3A, 0xFD, 0x00, 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, - 0x79, 0xF2, 0x12, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, - 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC4, 0xFF, 0x70, 0x00, 0x84, 0xFF, - 0x19, 0x00, 0x4D, 0x01, 0x22, 0xFA, 0x70, 0x46, 0x0A, 0x10, 0xFC, - 0xF7, 0xEB, 0x04, 0x08, 0xFD, 0x9A, 0x01, 0x4F, 0xFF, 0x2E, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90, - 0xFD, 0xD2, 0x03, 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE, - 0x33, 0xFF, 0x45, 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16, - 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4B, 0xFC, - 0xA9, 0x06, 0xD2, 0xF3, 0x81, 0x1E, 0xE4, 0x3E, 0xEF, 0xF3, 0xDE, - 0x04, 0xF9, 0xFD, 0xB7, 0x00, 0xD8, 0xFF, 0xFD, 0xFF, 0x03, 0x00, - 0xFD, 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, - 0x06, 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, - 0x4E, 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08, - 0x00, 0xE4, 0xFF, 0x1D, 0x00, 0x2D, 0x00, 0xEA, 0xFE, 0x56, 0x03, - 0x6D, 0xF6, 0x17, 0x43, 0x70, 0x17, 0xA6, 0xF5, 0xF3, 0x05, 0x91, - 0xFC, 0xCC, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00, - 0x86, 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73, - 0x03, 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE, - 0x14, 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, - 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x99, 0xFC, 0xE1, 0x05, 0xD1, 0xF5, - 0xDC, 0x16, 0x65, 0x43, 0xAD, 0xF6, 0x31, 0x03, 0x00, 0xFF, 0x20, - 0x00, 0x23, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, - 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62, - 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01, - 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0xFF, 0xFF, 0xD3, - 0xFF, 0xC1, 0x00, 0xE7, 0xFD, 0xFA, 0x04, 0xC4, 0xF3, 0x7E, 0x3E, - 0x19, 0x1F, 0xB0, 0xF3, 0xB5, 0x06, 0x47, 0xFC, 0xE4, 0x01, 0x36, - 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8, 0x00, - 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48, 0x47, - 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64, 0xFF, - 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x96, - 0x01, 0x13, 0xFD, 0xD5, 0x04, 0x2C, 0xF8, 0x7D, 0x0F, 0xA3, 0x46, - 0x76, 0xFA, 0x22, 0x01, 0x32, 0x00, 0x76, 0xFF, 0x76, 0x00, 0xC1, - 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF, 0xE4, 0x01, - 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54, 0x3A, 0x74, - 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF, 0x11, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x95, 0xFF, 0x3B, 0x01, 0x1B, - 0xFD, 0x2D, 0x06, 0x24, 0xF2, 0xD3, 0x38, 0xC6, 0x26, 0x45, 0xF2, - 0x1D, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD, - 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2, 0xFF, 0xE2, 0xFF, - 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11, 0x8F, 0xF7, 0x1D, - 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x51, 0x01, 0xAC, 0xFD, 0x9A, - 0x03, 0xBA, 0xFA, 0x9E, 0x08, 0x81, 0x48, 0x40, 0xFF, 0xC6, 0xFE, - 0x80, 0x01, 0xC2, 0xFE, 0xCE, 0x00, 0x9F, 0xFF, 0x17, 0x00, 0xFE, - 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06, - 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23, - 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFD, 0xFF, - 0x27, 0x00, 0x66, 0xFF, 0x96, 0x01, 0x8E, 0xFC, 0xE7, 0x06, 0x81, - 0xF1, 0x48, 0x32, 0x34, 0x2E, 0x8D, 0xF1, 0x1C, 0x07, 0x5A, 0xFC, - 0xBB, 0x01, 0x53, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9, - 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9, 0xFE, 0xA6, 0x03, 0xE4, 0xF5, - 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5, 0x1A, 0x06, 0x81, 0xFC, 0xD2, - 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8B, 0xFF, - 0xFF, 0x00, 0x5A, 0xFE, 0x46, 0x02, 0x52, 0xFD, 0x70, 0x02, 0xED, - 0x48, 0xF5, 0x04, 0x3B, 0xFC, 0xD7, 0x02, 0x0F, 0xFE, 0x23, 0x01, - 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, - 0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15, - 0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31, - 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF, - 0xCE, 0x01, 0x41, 0xFC, 0x2A, 0x07, 0xC2, 0xF1, 0x1B, 0x2B, 0x25, - 0x35, 0xA8, 0xF1, 0xA7, 0x06, 0xC2, 0xFC, 0x74, 0x01, 0x78, 0xFF, - 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9, - 0x00, 0xBF, 0xFD, 0x38, 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20, - 0x66, 0xF3, 0xCE, 0x06, 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, - 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAE, 0xFF, 0xA9, 0x00, 0x0F, 0xFF, - 0xF0, 0x00, 0xCD, 0xFF, 0x1B, 0xFD, 0xE4, 0x47, 0x73, 0x0B, 0xA2, - 0xF9, 0x23, 0x04, 0x68, 0xFD, 0x70, 0x01, 0x5F, 0xFF, 0x29, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B, - 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB, - 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10, - 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, - 0xFD, 0x06, 0xCB, 0xF2, 0x8A, 0x23, 0x58, 0x3B, 0xB4, 0xF2, 0xBA, - 0x05, 0x6A, 0xFD, 0x0B, 0x01, 0xAE, 0xFF, 0x0D, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56, - 0x06, 0xF7, 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07, - 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, - 0x00, 0xCF, 0xFF, 0x52, 0x00, 0xC0, 0xFF, 0xAC, 0xFF, 0x0C, 0x02, - 0xBC, 0xF8, 0x6D, 0x45, 0x8E, 0x12, 0x24, 0xF7, 0x4D, 0x05, 0xDB, - 0xFC, 0xAE, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x24, 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, - 0xFB, 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, - 0xA3, 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, - 0x00, 0x37, 0xFF, 0xDD, 0x01, 0x60, 0xFC, 0x6D, 0x06, 0x76, 0xF4, - 0xD8, 0x1B, 0x95, 0x40, 0xC3, 0xF4, 0x56, 0x04, 0x4E, 0xFE, 0x85, - 0x00, 0xF1, 0xFF, 0xF4, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x29, 0x00, - 0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15, - 0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01, - 0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x02, - 0x00, 0x63, 0x00, 0x8A, 0xFE, 0xF3, 0x03, 0x63, 0xF5, 0xA1, 0x41, - 0x12, 0x1A, 0xEB, 0xF4, 0x3F, 0x06, 0x72, 0xFC, 0xD7, 0x01, 0x39, - 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00, - 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07, - 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF, - 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x43, 0xFF, 0xBA, - 0x01, 0xBF, 0xFC, 0x8B, 0x05, 0x99, 0xF6, 0x43, 0x14, 0xA9, 0x44, - 0xDE, 0xF7, 0x85, 0x02, 0x65, 0xFF, 0xE7, 0xFF, 0x3F, 0x00, 0xD6, - 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD5, 0x01, - 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46, 0x36, 0xC5, - 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF, 0x1E, 0x00, - 0xFE, 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBC, 0xFF, 0xEF, 0x00, 0x9A, - 0xFD, 0x72, 0x05, 0x16, 0xF3, 0xA5, 0x3C, 0xC4, 0x21, 0x21, 0xF3, - 0xE4, 0x06, 0x39, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, - 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6, 0x00, - 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9, 0x5A, - 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x80, 0x01, 0x45, 0xFD, 0x6C, - 0x04, 0x0B, 0xF9, 0x0B, 0x0D, 0x73, 0x47, 0x02, 0xFC, 0x58, 0x00, - 0xA3, 0x00, 0x39, 0xFF, 0x94, 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD, - 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37, 0xFC, 0xEB, 0x06, - 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD, 0xF2, 0x84, 0x05, 0x8D, - 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF, - 0x1D, 0x00, 0x83, 0xFF, 0x5E, 0x01, 0xE3, 0xFC, 0x7B, 0x06, 0xD0, - 0xF1, 0xA5, 0x36, 0x62, 0x29, 0xEF, 0xF1, 0x29, 0x07, 0x39, 0xFC, - 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5, - 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF, 0x67, 0x02, 0x14, 0xF8, - 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C, 0x05, 0xC5, 0xFC, 0xB7, - 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, - 0x76, 0xFF, 0x35, 0x01, 0xE7, 0xFD, 0x26, 0x03, 0xA1, 0xFB, 0x64, - 0x06, 0xD2, 0x48, 0x21, 0x01, 0xE8, 0xFD, 0xF7, 0x01, 0x83, 0xFE, - 0xEC, 0x00, 0x93, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, - 0xFF, 0xD9, 0x01, 0x6D, 0xFC, 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A, - 0x5F, 0x41, 0x3A, 0xF5, 0x0C, 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE, - 0xFF, 0xEF, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF, - 0xAD, 0x01, 0x6C, 0xFC, 0x0C, 0x07, 0x7F, 0xF1, 0xDC, 0x2F, 0xAD, - 0x30, 0x7D, 0xF1, 0x01, 0x07, 0x76, 0xFC, 0xA6, 0x01, 0x5E, 0xFF, - 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, - 0x00, 0x5D, 0xFE, 0x3E, 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, - 0x93, 0xF4, 0x62, 0x06, 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, - 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x97, 0xFF, 0xE2, 0x00, 0x98, 0xFE, - 0xCF, 0x01, 0x33, 0xFE, 0x7D, 0x00, 0xBB, 0x48, 0x1F, 0x07, 0x54, - 0xFB, 0x4C, 0x03, 0xD3, 0xFD, 0x3F, 0x01, 0x73, 0xFF, 0x23, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3, - 0xFC, 0x5D, 0x05, 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8, - 0x2A, 0x02, 0x9A, 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C, - 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDA, 0x01, 0x35, 0xFC, - 0x27, 0x07, 0x09, 0xF2, 0x85, 0x28, 0x63, 0x37, 0xE9, 0xF1, 0x63, - 0x06, 0xF5, 0xFC, 0x53, 0x01, 0x89, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, - 0x00, 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, - 0x05, 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, - 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, - 0x00, 0xB9, 0xFF, 0x8A, 0x00, 0x4D, 0xFF, 0x7D, 0x00, 0x9C, 0x00, - 0x7B, 0xFB, 0x31, 0x47, 0xD9, 0x0D, 0xC0, 0xF8, 0x8F, 0x04, 0x34, - 0xFD, 0x87, 0x01, 0x56, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x29, 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C, - 0xF9, 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00, - 0x19, 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, - 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD5, 0x06, 0x4F, 0xF3, - 0xE0, 0x20, 0x45, 0x3D, 0x4D, 0xF3, 0x4B, 0x05, 0xB3, 0xFD, 0xE0, - 0x00, 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, - 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86, - 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01, - 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xDA, 0xFF, 0x36, - 0x00, 0xFA, 0xFF, 0x43, 0xFF, 0xBF, 0x02, 0x75, 0xF7, 0x42, 0x44, - 0x20, 0x15, 0x55, 0xF6, 0xA9, 0x05, 0xB2, 0xFC, 0xBF, 0x01, 0x41, - 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF, - 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05, 0xEA, - 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA, 0x00, - 0x8D, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD4, - 0x01, 0x7C, 0xFC, 0x27, 0x06, 0x28, 0xF5, 0x31, 0x19, 0x21, 0x42, - 0xB8, 0xF5, 0xC0, 0x03, 0xAA, 0xFE, 0x51, 0x00, 0x0B, 0x00, 0xEA, - 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF, 0xB7, 0x01, - 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3, 0x31, 0x7E, - 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF, 0x28, 0x00, - 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xE8, 0xFF, 0x96, 0x00, 0x31, - 0xFE, 0x84, 0x04, 0x79, 0xF4, 0x07, 0x40, 0xBA, 0x1C, 0x3E, 0xF4, - 0x82, 0x06, 0x58, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, - 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8, 0xFE, 0x93, 0x01, - 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08, 0xE1, 0xFA, 0x86, - 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA8, 0x01, 0xE9, 0xFC, 0x2D, - 0x05, 0x6B, 0xF7, 0xB6, 0x11, 0xC8, 0x45, 0x30, 0xF9, 0xCD, 0x01, - 0xD0, 0xFF, 0xAC, 0xFF, 0x5C, 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD, - 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07, - 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11, - 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x10, 0x00, 0xA7, 0xFF, 0x19, 0x01, 0x53, 0xFD, 0xDB, 0x05, 0x88, - 0xF2, 0xAD, 0x3A, 0x6D, 0x24, 0xA4, 0xF2, 0x08, 0x07, 0x32, 0xFC, - 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBF, - 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44, 0x00, 0x01, 0x01, 0xB6, 0xFA, - 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8, 0xC4, 0x04, 0x1B, 0xFD, 0x92, - 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, - 0x63, 0xFF, 0x67, 0x01, 0x7A, 0xFD, 0xFE, 0x03, 0xEE, 0xF9, 0xAA, - 0x0A, 0x16, 0x48, 0xAC, 0xFD, 0x86, 0xFF, 0x17, 0x01, 0xFA, 0xFE, - 0xB3, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, - 0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F, - 0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF, - 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x73, 0xFF, - 0x7D, 0x01, 0xB3, 0xFC, 0xBB, 0x06, 0x9A, 0xF1, 0x60, 0x34, 0xF5, - 0x2B, 0xB0, 0xF1, 0x28, 0x07, 0x47, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, - 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17, - 0x00, 0x10, 0xFF, 0x15, 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16, - 0xF1, 0xF5, 0xD3, 0x05, 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x19, 0x01, - 0x23, 0xFE, 0xB0, 0x02, 0x87, 0xFC, 0x41, 0x04, 0xF4, 0x48, 0x1C, - 0x03, 0x06, 0xFD, 0x6E, 0x02, 0x45, 0xFE, 0x09, 0x01, 0x88, 0xFF, - 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C, - 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6, - 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07, - 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4F, 0xFF, 0xC1, 0x01, 0x52, 0xFC, - 0x22, 0x07, 0x98, 0xF1, 0x5E, 0x2D, 0x13, 0x33, 0x87, 0xF1, 0xD8, - 0x06, 0x9B, 0xFC, 0x8D, 0x01, 0x6B, 0xFF, 0x25, 0x00, 0xFD, 0xFF, - 0x03, 0x00, 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8, - 0x04, 0x10, 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06, - 0x4E, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, - 0x00, 0xA3, 0xFF, 0xC3, 0x00, 0xD7, 0xFE, 0x58, 0x01, 0x0F, 0xFF, - 0xA6, 0xFE, 0x5D, 0x48, 0x61, 0x09, 0x6E, 0xFA, 0xC0, 0x03, 0x99, - 0xFD, 0x59, 0x01, 0x68, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x2E, 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, - 0xF7, 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, - 0x8E, 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, - 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x16, 0x07, 0x67, 0xF2, - 0xE5, 0x25, 0x87, 0x39, 0x47, 0xF2, 0x10, 0x06, 0x30, 0xFD, 0x2F, - 0x01, 0x9C, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x00, - 0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5, - 0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01, - 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC5, 0xFF, 0x6D, - 0x00, 0x8B, 0xFF, 0x0D, 0x00, 0x63, 0x01, 0xF9, 0xF9, 0x55, 0x46, - 0x51, 0x10, 0xE3, 0xF7, 0xF7, 0x04, 0x03, 0xFD, 0x9D, 0x01, 0x4E, - 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, - 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57, - 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00, - 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, - 0x01, 0x4D, 0xFC, 0xA3, 0x06, 0xE4, 0xF3, 0x36, 0x1E, 0x16, 0x3F, - 0x05, 0xF4, 0xCF, 0x04, 0x02, 0xFE, 0xB2, 0x00, 0xDB, 0xFF, 0xFC, - 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF, 0x8B, 0x01, - 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A, 0x2D, 0x9A, - 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF, 0x2F, 0x00, - 0xFD, 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x1A, 0x00, 0x33, 0x00, 0xDF, - 0xFE, 0x68, 0x03, 0x4E, 0xF6, 0xEE, 0x42, 0xBB, 0x17, 0x90, 0xF5, - 0xFC, 0x05, 0x8E, 0xFC, 0xCD, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, - 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74, 0x02, - 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC, 0xA9, - 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC7, 0x01, 0x9D, 0xFC, 0xD8, - 0x05, 0xE7, 0xF5, 0x91, 0x16, 0x89, 0x43, 0xCD, 0xF6, 0x1E, 0x03, - 0x0B, 0xFF, 0x1A, 0x00, 0x26, 0x00, 0xE0, 0xFF, 0x08, 0x00, 0xFD, - 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01, 0x48, 0xFC, 0x28, 0x07, - 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97, 0xF1, 0xBE, 0x06, 0xB0, - 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x02, 0x00, - 0x00, 0x00, 0xD0, 0xFF, 0xC7, 0x00, 0xDE, 0xFD, 0x08, 0x05, 0xB0, - 0xF3, 0x4A, 0x3E, 0x64, 0x1F, 0xA0, 0xF3, 0xBB, 0x06, 0x45, 0xFC, - 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xA9, - 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01, 0x7A, 0xFF, 0xC5, 0xFD, - 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8, 0x03, 0x7D, 0xFD, 0x66, - 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, - 0x52, 0xFF, 0x93, 0x01, 0x18, 0xFD, 0xC9, 0x04, 0x45, 0xF8, 0x36, - 0x0F, 0xBB, 0x46, 0xA1, 0xFA, 0x0C, 0x01, 0x3E, 0x00, 0x70, 0xFF, - 0x7A, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, - 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24, - 0x8F, 0x3A, 0x82, 0xF2, 0xE1, 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6, - 0xFF, 0x10, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x17, 0x00, 0x93, 0xFF, - 0x3F, 0x01, 0x15, 0xFD, 0x36, 0x06, 0x19, 0xF2, 0x97, 0x38, 0x11, - 0x27, 0x3B, 0xF2, 0x1F, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF, - 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, - 0xFF, 0xD6, 0xFF, 0xC3, 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, - 0x77, 0xF7, 0x28, 0x05, 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6D, 0xFF, 0x4E, 0x01, - 0xB3, 0xFD, 0x8D, 0x03, 0xD4, 0xFA, 0x5D, 0x08, 0x8D, 0x48, 0x74, - 0xFF, 0xAE, 0xFE, 0x8D, 0x01, 0xBB, 0xFE, 0xD1, 0x00, 0x9E, 0xFF, - 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57, - 0xFC, 0x85, 0x06, 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4, - 0x8C, 0x04, 0x2C, 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04, - 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x65, 0xFF, 0x98, 0x01, 0x8A, 0xFC, - 0xEC, 0x06, 0x7F, 0xF1, 0x04, 0x32, 0x7B, 0x2E, 0x8A, 0xF1, 0x1A, - 0x07, 0x5D, 0xFC, 0xB8, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, - 0x06, 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, - 0x03, 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, - 0x7D, 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, - 0x00, 0x8D, 0xFF, 0xFC, 0x00, 0x61, 0xFE, 0x39, 0x02, 0x6B, 0xFD, - 0x37, 0x02, 0xEB, 0x48, 0x31, 0x05, 0x21, 0xFC, 0xE4, 0x02, 0x08, - 0xFE, 0x26, 0x01, 0x7C, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x32, 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A, - 0xF6, 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF, - 0xFE, 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x32, - 0x00, 0x47, 0xFF, 0xD0, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xCA, 0xF1, - 0xD1, 0x2A, 0x65, 0x35, 0xAE, 0xF1, 0xA0, 0x06, 0xC7, 0xFC, 0x70, - 0x01, 0x7A, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00, - 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61, - 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01, - 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA5, - 0x00, 0x16, 0xFF, 0xE3, 0x00, 0xE4, 0xFF, 0xEB, 0xFC, 0xD2, 0x47, - 0xB6, 0x0B, 0x89, 0xF9, 0x2F, 0x04, 0x62, 0xFD, 0x72, 0x01, 0x5E, - 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x56, 0xFF, - 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D, 0x26, - 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89, 0x00, - 0xBA, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, - 0x01, 0x34, 0xFC, 0xF9, 0x06, 0xD9, 0xF2, 0x3F, 0x23, 0x90, 0x3B, - 0xC4, 0xF2, 0xAE, 0x05, 0x72, 0xFD, 0x07, 0x01, 0xB0, 0xFF, 0x0C, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF, 0x51, 0x01, - 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60, 0x28, 0x0E, - 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF, 0x34, 0x00, - 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x4F, 0x00, 0xC7, 0xFF, 0xA0, - 0xFF, 0x20, 0x02, 0x96, 0xF8, 0x4E, 0x45, 0xD7, 0x12, 0x0D, 0xF7, - 0x58, 0x05, 0xD6, 0xFC, 0xB0, 0x01, 0x47, 0xFF, 0x30, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40, 0x01, 0xD0, 0xFD, - 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48, 0x62, 0x00, 0x3F, - 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98, 0xFF, 0x19, 0x00, - 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x63, 0xFC, 0x66, - 0x06, 0x89, 0xF4, 0x8C, 0x1B, 0xC3, 0x40, 0xDD, 0xF4, 0x46, 0x04, - 0x58, 0xFE, 0x80, 0x00, 0xF4, 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD, - 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06, - 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A, - 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, - 0xEF, 0xFF, 0xFF, 0xFF, 0x69, 0x00, 0x80, 0xFE, 0x04, 0x04, 0x48, - 0xF5, 0x74, 0x41, 0x5D, 0x1A, 0xD7, 0xF4, 0x47, 0x06, 0x6F, 0xFC, - 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x93, - 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD, 0x01, 0xDC, 0xFD, 0x3C, 0x01, - 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB, 0x1F, 0x03, 0xEA, 0xFD, 0x34, - 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, - 0x44, 0xFF, 0xB8, 0x01, 0xC3, 0xFC, 0x81, 0x05, 0xB0, 0xF6, 0xFA, - 0x13, 0xCC, 0x44, 0x02, 0xF8, 0x71, 0x02, 0x71, 0xFF, 0xE1, 0xFF, - 0x42, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43, - 0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29, - 0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82, - 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x09, 0x00, 0xBA, 0xFF, - 0xF4, 0x00, 0x91, 0xFD, 0x7E, 0x05, 0x05, 0xF3, 0x6E, 0x3C, 0x10, - 0x22, 0x12, 0xF3, 0xE9, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, - 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35, - 0xFF, 0xA9, 0x00, 0x4D, 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C, - 0x18, 0xF9, 0x66, 0x04, 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5A, 0xFF, 0x7D, 0x01, - 0x4B, 0xFD, 0x60, 0x04, 0x24, 0xF9, 0xC6, 0x0C, 0x86, 0x47, 0x30, - 0xFC, 0x41, 0x00, 0xB0, 0x00, 0x32, 0xFF, 0x98, 0x00, 0xB4, 0xFF, - 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38, - 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3, - 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01, - 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x81, 0xFF, 0x62, 0x01, 0xDD, 0xFC, - 0x83, 0x06, 0xC9, 0xF1, 0x66, 0x36, 0xAC, 0x29, 0xE7, 0xF1, 0x2A, - 0x07, 0x3A, 0xFC, 0xD5, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, - 0x0B, 0x00, 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B, - 0x02, 0xF0, 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05, - 0xC1, 0xFC, 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x22, 0x00, 0x77, 0xFF, 0x32, 0x01, 0xED, 0xFD, 0x19, 0x03, - 0xBB, 0xFB, 0x26, 0x06, 0xD7, 0x48, 0x58, 0x01, 0xCF, 0xFD, 0x04, - 0x02, 0x7D, 0xFE, 0xEF, 0x00, 0x92, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, - 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, - 0xF4, 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, - 0x66, 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2B, - 0x00, 0x59, 0xFF, 0xB0, 0x01, 0x69, 0xFC, 0x0F, 0x07, 0x80, 0xF1, - 0x96, 0x2F, 0xF2, 0x30, 0x7C, 0xF1, 0xFD, 0x06, 0x7A, 0xFC, 0xA3, - 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF4, 0xFF, - 0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB, - 0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01, - 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x98, 0xFF, 0xDE, - 0x00, 0x9F, 0xFE, 0xC2, 0x01, 0x4B, 0xFE, 0x48, 0x00, 0xB3, 0x48, - 0x5E, 0x07, 0x3B, 0xFB, 0x59, 0x03, 0xCD, 0xFD, 0x42, 0x01, 0x71, - 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF, - 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C, - 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00, - 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x40, 0xFF, 0xDB, - 0x01, 0x35, 0xFC, 0x25, 0x07, 0x13, 0xF2, 0x3A, 0x28, 0xA0, 0x37, - 0xF2, 0xF1, 0x5A, 0x06, 0xFB, 0xFC, 0x4F, 0x01, 0x8B, 0xFF, 0x1A, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF, 0x09, 0x01, - 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64, 0x23, 0xD2, - 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, - 0xFD, 0xFF, 0x11, 0x00, 0xBB, 0xFF, 0x87, 0x00, 0x54, 0xFF, 0x70, - 0x00, 0xB3, 0x00, 0x4E, 0xFB, 0x1A, 0x47, 0x1F, 0x0E, 0xA8, 0xF8, - 0x9B, 0x04, 0x2E, 0xFD, 0x8A, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65, 0xFD, - 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD, 0xD9, - 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14, 0x00, - 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD0, - 0x06, 0x5E, 0xF3, 0x94, 0x20, 0x7B, 0x3D, 0x60, 0xF3, 0x3E, 0x05, - 0xBB, 0xFD, 0xDB, 0x00, 0xC6, 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE, - 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01, 0xC4, 0xFC, 0xA4, 0x06, - 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6, 0xF1, 0x2A, 0x07, 0x40, - 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, - 0xDB, 0xFF, 0x33, 0x00, 0x01, 0x00, 0x38, 0xFF, 0xD3, 0x02, 0x53, - 0xF7, 0x1F, 0x44, 0x69, 0x15, 0x3F, 0xF6, 0xB2, 0x05, 0xAD, 0xFC, - 0xC1, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, - 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE, 0xDE, 0x02, 0x2E, 0xFC, - 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E, 0xFD, 0x3F, 0x02, 0x5D, - 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, - 0x3B, 0xFF, 0xD3, 0x01, 0x7F, 0xFC, 0x1F, 0x06, 0x3C, 0xF5, 0xE6, - 0x18, 0x4D, 0x42, 0xD5, 0xF5, 0xAF, 0x03, 0xB4, 0xFE, 0x4B, 0x00, - 0x0E, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53, - 0xFF, 0xBA, 0x01, 0x5B, 0xFC, 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E, - 0x26, 0x32, 0x80, 0xF1, 0xEA, 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66, - 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8, 0xFF, 0xE6, 0xFF, - 0x9C, 0x00, 0x27, 0xFE, 0x94, 0x04, 0x61, 0xF4, 0xD7, 0x3F, 0x06, - 0x1D, 0x2B, 0xF4, 0x89, 0x06, 0x56, 0xFC, 0xE0, 0x01, 0x37, 0xFF, - 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, - 0xFE, 0x86, 0x01, 0xBA, 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, - 0xC7, 0xFA, 0x93, 0x03, 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA6, 0x01, - 0xEE, 0xFC, 0x23, 0x05, 0x83, 0xF7, 0x6E, 0x11, 0xE5, 0x45, 0x57, - 0xF9, 0xB8, 0x01, 0xDC, 0xFF, 0xA5, 0xFF, 0x5F, 0x00, 0xCA, 0xFF, - 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32, - 0xFC, 0x1E, 0x07, 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2, - 0x32, 0x06, 0x18, 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA4, 0xFF, 0x1D, 0x01, 0x4C, 0xFD, - 0xE6, 0x05, 0x7B, 0xF2, 0x71, 0x3A, 0xB8, 0x24, 0x97, 0xF2, 0x0B, - 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, - 0x0F, 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, - 0x01, 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, - 0x15, 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x28, 0x00, 0x64, 0xFF, 0x65, 0x01, 0x81, 0xFD, 0xF2, 0x03, - 0x08, 0xFA, 0x68, 0x0A, 0x25, 0x48, 0xDE, 0xFD, 0x6E, 0xFF, 0x24, - 0x01, 0xF3, 0xFE, 0xB6, 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF, - 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8, - 0xF3, 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD, - 0xC4, 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x23, - 0x00, 0x71, 0xFF, 0x81, 0x01, 0xAE, 0xFC, 0xC1, 0x06, 0x95, 0xF1, - 0x1E, 0x34, 0x3E, 0x2C, 0xAB, 0xF1, 0x27, 0x07, 0x49, 0xFC, 0xC8, - 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF, - 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77, - 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01, - 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, - 0xFF, 0x16, 0x01, 0x2A, 0xFE, 0xA3, 0x02, 0xA1, 0xFC, 0x06, 0x04, - 0xF5, 0x48, 0x56, 0x03, 0xED, 0xFC, 0x7B, 0x02, 0x3E, 0xFE, 0x0C, - 0x01, 0x86, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, - 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17, 0x02, - 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B, 0x00, - 0xE4, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, - 0x01, 0x4F, 0xFC, 0x24, 0x07, 0x9C, 0xF1, 0x17, 0x2D, 0x57, 0x33, - 0x8A, 0xF1, 0xD3, 0x06, 0x9F, 0xFC, 0x8A, 0x01, 0x6D, 0xFF, 0x25, - 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF, 0xB4, 0x00, - 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B, 0x1E, 0xDB, - 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, - 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC0, 0x00, 0xDE, 0xFE, 0x4B, - 0x01, 0x27, 0xFF, 0x73, 0xFE, 0x4F, 0x48, 0xA2, 0x09, 0x54, 0xFA, - 0xCC, 0x03, 0x93, 0xFD, 0x5C, 0x01, 0x67, 0xFF, 0x27, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C, 0x01, 0x05, 0xFD, - 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46, 0x0D, 0xFA, 0x58, - 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4, 0xFF, 0x0E, 0x00, - 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x14, - 0x07, 0x73, 0xF2, 0x99, 0x25, 0xC2, 0x39, 0x54, 0xF2, 0x05, 0x06, - 0x37, 0xFD, 0x2B, 0x01, 0x9E, 0xFF, 0x13, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06, - 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31, - 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, - 0xC6, 0xFF, 0x69, 0x00, 0x91, 0xFF, 0x00, 0x00, 0x78, 0x01, 0xD0, - 0xF9, 0x39, 0x46, 0x98, 0x10, 0xCB, 0xF7, 0x02, 0x05, 0xFE, 0xFC, - 0x9F, 0x01, 0x4D, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, - 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D, 0xFD, 0xB9, 0x03, 0x7B, 0xFA, - 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE, 0x03, 0xFF, 0x5F, 0x01, 0xD4, - 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, - 0x36, 0xFF, 0xE2, 0x01, 0x4F, 0xFC, 0x9C, 0x06, 0xF5, 0xF3, 0xEA, - 0x1D, 0x47, 0x3F, 0x1B, 0xF4, 0xC1, 0x04, 0x0B, 0xFE, 0xAC, 0x00, - 0xDE, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A, - 0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32, - 0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50, - 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE6, 0xFF, 0x17, 0x00, - 0x39, 0x00, 0xD4, 0xFE, 0x7A, 0x03, 0x2F, 0xF6, 0xC7, 0x42, 0x06, - 0x18, 0x7B, 0xF5, 0x05, 0x06, 0x8A, 0xFC, 0xCF, 0x01, 0x3C, 0xFF, - 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49, - 0xFE, 0x67, 0x02, 0x13, 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04, - 0x7A, 0xFC, 0xB6, 0x02, 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01, - 0xA1, 0xFC, 0xCF, 0x05, 0xFC, 0xF5, 0x47, 0x16, 0xB0, 0x43, 0xEE, - 0xF6, 0x0C, 0x03, 0x16, 0xFF, 0x14, 0x00, 0x29, 0x00, 0xDF, 0xFF, - 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46, - 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1, - 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE, - 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCE, 0xFF, 0xCC, 0x00, 0xD5, 0xFD, - 0x16, 0x05, 0x9B, 0xF3, 0x18, 0x3E, 0xB1, 0x1F, 0x8F, 0xF3, 0xC0, - 0x06, 0x43, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, - 0x15, 0x00, 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92, - 0xFF, 0x94, 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04, - 0x77, 0xFD, 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x91, 0x01, 0x1E, 0xFD, 0xBE, 0x04, - 0x5E, 0xF8, 0xF0, 0x0E, 0xD3, 0x46, 0xCB, 0xFA, 0xF6, 0x00, 0x4B, - 0x00, 0x69, 0xFF, 0x7D, 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF, - 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, - 0xF2, 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, - 0x17, 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, - 0x00, 0x91, 0xFF, 0x43, 0x01, 0x0E, 0xFD, 0x40, 0x06, 0x0F, 0xF2, - 0x5B, 0x38, 0x5C, 0x27, 0x30, 0xF2, 0x21, 0x07, 0x33, 0xFC, 0xDE, - 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCC, 0xFF, - 0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8, - 0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01, - 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6E, - 0xFF, 0x4B, 0x01, 0xB9, 0xFD, 0x80, 0x03, 0xEE, 0xFA, 0x1D, 0x08, - 0x98, 0x48, 0xA8, 0xFF, 0x95, 0xFE, 0x9A, 0x01, 0xB4, 0xFE, 0xD4, - 0x00, 0x9C, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, - 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F, - 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF, - 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9B, - 0x01, 0x86, 0xFC, 0xF1, 0x06, 0x7E, 0xF1, 0xC0, 0x31, 0xC2, 0x2E, - 0x87, 0xF1, 0x17, 0x07, 0x5F, 0xFC, 0xB6, 0x01, 0x55, 0xFF, 0x2D, - 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00, 0x54, 0x00, - 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56, 0x19, 0x1E, - 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF, 0x35, 0x00, - 0xFE, 0xFF, 0x1C, 0x00, 0x8E, 0xFF, 0xF9, 0x00, 0x68, 0xFE, 0x2C, - 0x02, 0x84, 0xFD, 0xFF, 0x01, 0xE6, 0x48, 0x6E, 0x05, 0x07, 0xFC, - 0xF1, 0x02, 0x01, 0xFE, 0x29, 0x01, 0x7B, 0xFF, 0x21, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4, 0xFC, - 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7, 0xB6, - 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A, 0x00, - 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3E, 0xFC, 0x2B, - 0x07, 0xD0, 0xF1, 0x89, 0x2A, 0xA6, 0x35, 0xB4, 0xF1, 0x99, 0x06, - 0xCD, 0xFC, 0x6D, 0x01, 0x7C, 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01, - 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00, 0xAE, 0xFD, 0x52, 0x05, - 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47, 0xF3, 0xD8, 0x06, 0x3C, - 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, - 0xB0, 0xFF, 0xA2, 0x00, 0x1D, 0xFF, 0xD6, 0x00, 0xFC, 0xFF, 0xBC, - 0xFC, 0xC0, 0x47, 0xFA, 0x0B, 0x70, 0xF9, 0x3C, 0x04, 0x5C, 0xFD, - 0x75, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, - 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD, 0x89, 0x04, 0xCD, 0xF8, - 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91, 0x00, 0x83, 0x00, 0x4A, - 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, - 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF5, 0x06, 0xE7, 0xF2, 0xF2, - 0x22, 0xC7, 0x3B, 0xD4, 0xF2, 0xA2, 0x05, 0x7A, 0xFD, 0x02, 0x01, - 0xB2, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88, - 0xFF, 0x55, 0x01, 0xF2, 0xFC, 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37, - 0xAA, 0x28, 0x05, 0xF2, 0x27, 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41, - 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD2, 0xFF, 0x4C, 0x00, - 0xCD, 0xFF, 0x94, 0xFF, 0x34, 0x02, 0x70, 0xF8, 0x2E, 0x45, 0x20, - 0x13, 0xF6, 0xF6, 0x62, 0x05, 0xD1, 0xFC, 0xB2, 0x01, 0x46, 0xFF, - 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, - 0x01, 0xD6, 0xFD, 0x46, 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, - 0x98, 0x00, 0x26, 0xFE, 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, - 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01, - 0x66, 0xFC, 0x5E, 0x06, 0x9C, 0xF4, 0x40, 0x1B, 0xEF, 0x40, 0xF7, - 0xF4, 0x35, 0x04, 0x62, 0xFE, 0x7A, 0x00, 0xF7, 0xFF, 0xF2, 0xFF, - 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75, - 0xFC, 0x03, 0x07, 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1, - 0x0A, 0x07, 0x6E, 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD, - 0xFF, 0x05, 0x00, 0xF0, 0xFF, 0xFC, 0xFF, 0x6E, 0x00, 0x76, 0xFE, - 0x15, 0x04, 0x2C, 0xF5, 0x49, 0x41, 0xA9, 0x1A, 0xC3, 0xF4, 0x4F, - 0x06, 0x6C, 0xFC, 0xD9, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, - 0x1A, 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, - 0xFD, 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, - 0xE4, 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB6, 0x01, 0xC8, 0xFC, 0x77, 0x05, - 0xC7, 0xF6, 0xB1, 0x13, 0xED, 0x44, 0x26, 0xF8, 0x5D, 0x02, 0x7D, - 0xFF, 0xDA, 0xFF, 0x46, 0x00, 0xD4, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, - 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3, - 0xF1, 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC, - 0x5C, 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A, - 0x00, 0xB7, 0xFF, 0xF9, 0x00, 0x89, 0xFD, 0x8A, 0x05, 0xF4, 0xF2, - 0x37, 0x3C, 0x5B, 0x22, 0x03, 0xF3, 0xED, 0x06, 0x37, 0xFC, 0xE6, - 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB6, 0xFF, - 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69, - 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01, - 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B, - 0xFF, 0x7A, 0x01, 0x50, 0xFD, 0x54, 0x04, 0x3D, 0xF9, 0x82, 0x0C, - 0x9A, 0x47, 0x5E, 0xFC, 0x2A, 0x00, 0xBD, 0x00, 0x2B, 0xFF, 0x9B, - 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, - 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21, 0xC0, - 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD, 0xFF, - 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x80, 0xFF, 0x66, - 0x01, 0xD8, 0xFC, 0x8B, 0x06, 0xC1, 0xF1, 0x27, 0x36, 0xF6, 0x29, - 0xDF, 0xF1, 0x2A, 0x07, 0x3B, 0xFC, 0xD4, 0x01, 0x44, 0xFF, 0x32, - 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00, 0xEA, 0xFF, - 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68, 0x14, 0x8E, - 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF, 0x32, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x79, 0xFF, 0x2F, 0x01, 0xF4, - 0xFD, 0x0C, 0x03, 0xD4, 0xFB, 0xE9, 0x05, 0xDE, 0x48, 0x8F, 0x01, - 0xB6, 0xFD, 0x11, 0x02, 0x76, 0xFE, 0xF2, 0x00, 0x91, 0xFF, 0x1B, - 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7, 0x01, 0x73, 0xFC, - 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41, 0x71, 0xF5, 0xEB, - 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED, 0xFF, 0x06, 0x00, - 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB2, 0x01, 0x65, 0xFC, 0x12, - 0x07, 0x82, 0xF1, 0x50, 0x2F, 0x38, 0x31, 0x7C, 0xF1, 0xF9, 0x06, - 0x7E, 0xFC, 0xA1, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04, - 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04, - 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F, - 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, - 0x9A, 0xFF, 0xDB, 0x00, 0xA6, 0xFE, 0xB4, 0x01, 0x64, 0xFE, 0x12, - 0x00, 0xAA, 0x48, 0x9E, 0x07, 0x21, 0xFB, 0x66, 0x03, 0xC6, 0xFD, - 0x45, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, - 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD, 0xFC, 0x48, 0x05, 0x30, 0xF7, - 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8, 0x01, 0x02, 0xB2, 0xFF, 0xBD, - 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, - 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x24, 0x07, 0x1C, 0xF2, 0xF0, - 0x27, 0xDF, 0x37, 0xFB, 0xF1, 0x51, 0x06, 0x01, 0xFD, 0x4B, 0x01, - 0x8D, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC, - 0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B, - 0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38, - 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBC, 0xFF, 0x84, 0x00, - 0x5B, 0xFF, 0x64, 0x00, 0xC9, 0x00, 0x22, 0xFB, 0x02, 0x47, 0x64, - 0x0E, 0x8F, 0xF8, 0xA7, 0x04, 0x29, 0xFD, 0x8C, 0x01, 0x54, 0xFF, - 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E, - 0x01, 0x6B, 0xFD, 0x1D, 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47, - 0x33, 0xFD, 0xC1, 0xFF, 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD, - 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, - 0x40, 0xFC, 0xCB, 0x06, 0x6E, 0xF3, 0x49, 0x20, 0xB0, 0x3D, 0x73, - 0xF3, 0x31, 0x05, 0xC4, 0xFD, 0xD6, 0x00, 0xC8, 0xFF, 0x03, 0x00, - 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF, - 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1, - 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, - 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x2F, 0x00, 0x07, 0x00, 0x2C, 0xFF, - 0xE6, 0x02, 0x31, 0xF7, 0xFA, 0x43, 0xB3, 0x15, 0x29, 0xF6, 0xBC, - 0x05, 0xA9, 0xFC, 0xC2, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1, - 0x02, 0x47, 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD, - 0x4D, 0x02, 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFE, - 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01, 0x83, 0xFC, 0x16, 0x06, - 0x51, 0xF5, 0x9B, 0x18, 0x75, 0x42, 0xF3, 0xF5, 0x9D, 0x03, 0xBF, - 0xFE, 0x45, 0x00, 0x11, 0x00, 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF, - 0x2E, 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, - 0xF1, 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, - 0x94, 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF9, - 0xFF, 0xE3, 0xFF, 0xA1, 0x00, 0x1E, 0xFE, 0xA3, 0x04, 0x49, 0xF4, - 0xA8, 0x3F, 0x52, 0x1D, 0x19, 0xF4, 0x90, 0x06, 0x53, 0xFC, 0xE1, - 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF, - 0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C, - 0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01, - 0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, - 0xFF, 0xA3, 0x01, 0xF3, 0xFC, 0x18, 0x05, 0x9B, 0xF7, 0x27, 0x11, - 0x02, 0x46, 0x7F, 0xF9, 0xA3, 0x01, 0xE8, 0xFF, 0x9F, 0xFF, 0x63, - 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, - 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2, - 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF, - 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00, 0xA2, 0xFF, 0x22, - 0x01, 0x45, 0xFD, 0xF1, 0x05, 0x6D, 0xF2, 0x38, 0x3A, 0x03, 0x25, - 0x8B, 0xF2, 0x0E, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x3A, 0xFF, 0x36, - 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00, 0x7A, 0xFF, - 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0, 0x0F, 0x20, - 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF, 0x2E, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x62, 0x01, 0x87, - 0xFD, 0xE5, 0x03, 0x21, 0xFA, 0x25, 0x0A, 0x33, 0x48, 0x0F, 0xFE, - 0x57, 0xFF, 0x31, 0x01, 0xEC, 0xFE, 0xB9, 0x00, 0xA7, 0xFF, 0x15, - 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48, 0xFC, - 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3, 0xF3, - 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03, 0x00, - 0xFE, 0xFF, 0x23, 0x00, 0x70, 0xFF, 0x84, 0x01, 0xA9, 0xFC, 0xC7, - 0x06, 0x91, 0xF1, 0xDC, 0x33, 0x87, 0x2C, 0xA5, 0xF1, 0x26, 0x07, - 0x4B, 0xFC, 0xC6, 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, - 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00, 0xFA, 0xFE, 0x3A, 0x03, - 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6, 0xF5, 0xE6, 0x05, 0x97, - 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00, - 0x1E, 0x00, 0x84, 0xFF, 0x13, 0x01, 0x31, 0xFE, 0x95, 0x02, 0xBA, - 0xFC, 0xCB, 0x03, 0xF7, 0x48, 0x91, 0x03, 0xD3, 0xFC, 0x88, 0x02, - 0x38, 0xFE, 0x10, 0x01, 0x85, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, - 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC, 0xEF, 0x05, 0xB0, 0xF5, - 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D, 0x03, 0xEF, 0xFE, 0x2A, - 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00, 0xFD, 0xFF, 0x2F, 0x00, - 0x4D, 0xFF, 0xC4, 0x01, 0x4D, 0xFC, 0x25, 0x07, 0xA1, 0xF1, 0xCE, - 0x2C, 0x99, 0x33, 0x8E, 0xF1, 0xCD, 0x06, 0xA4, 0xFC, 0x87, 0x01, - 0x6E, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xD7, - 0xFF, 0xBA, 0x00, 0xF4, 0xFD, 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E, - 0xA7, 0x1E, 0xCA, 0xF3, 0xAC, 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36, - 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA6, 0xFF, 0xBD, 0x00, - 0xE5, 0xFE, 0x3E, 0x01, 0x3F, 0xFF, 0x41, 0xFE, 0x41, 0x48, 0xE4, - 0x09, 0x3B, 0xFA, 0xD9, 0x03, 0x8D, 0xFD, 0x5F, 0x01, 0x66, 0xFF, - 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, - 0x01, 0x0B, 0xFD, 0xE6, 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, - 0x37, 0xFA, 0x42, 0x01, 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, - 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, - 0x31, 0xFC, 0x11, 0x07, 0x7F, 0xF2, 0x4E, 0x25, 0xFD, 0x39, 0x60, - 0xF2, 0xFB, 0x05, 0x3E, 0xFD, 0x26, 0x01, 0xA0, 0xFF, 0x12, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25, - 0xFD, 0x1E, 0x06, 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2, - 0x1A, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, - 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x66, 0x00, 0x98, 0xFF, 0xF4, 0xFF, - 0x8E, 0x01, 0xA7, 0xF9, 0x1D, 0x46, 0xDF, 0x10, 0xB3, 0xF7, 0x0D, - 0x05, 0xF8, 0xFC, 0xA1, 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, - 0x03, 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, - 0x6C, 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFE, - 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x51, 0xFC, 0x96, 0x06, - 0x07, 0xF4, 0x9E, 0x1D, 0x77, 0x3F, 0x32, 0xF4, 0xB2, 0x04, 0x15, - 0xFE, 0xA7, 0x00, 0xE0, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0xFD, 0xFF, - 0x26, 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84, - 0xF1, 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC, - 0xBE, 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE7, - 0xFF, 0x14, 0x00, 0x3F, 0x00, 0xC9, 0xFE, 0x8C, 0x03, 0x11, 0xF6, - 0x9E, 0x42, 0x50, 0x18, 0x66, 0xF5, 0x0D, 0x06, 0x86, 0xFC, 0xD0, - 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x8A, 0xFF, - 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2, - 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01, - 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, - 0xFF, 0xC4, 0x01, 0xA5, 0xFC, 0xC5, 0x05, 0x13, 0xF6, 0xFD, 0x15, - 0xD4, 0x43, 0x0F, 0xF7, 0xF9, 0x02, 0x21, 0xFF, 0x0D, 0x00, 0x2C, - 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49, 0xFF, - 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B, 0xC3, - 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76, 0xFF, - 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00, 0xCB, 0xFF, 0xD1, - 0x00, 0xCC, 0xFD, 0x24, 0x05, 0x87, 0xF3, 0xE4, 0x3D, 0xFD, 0x1F, - 0x7F, 0xF3, 0xC6, 0x06, 0x41, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, - 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00, 0x05, 0xFF, - 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E, 0x0B, 0xC8, - 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF, 0x28, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x8F, 0x01, 0x23, - 0xFD, 0xB2, 0x04, 0x76, 0xF8, 0xAA, 0x0E, 0xED, 0x46, 0xF7, 0xFA, - 0xDF, 0x00, 0x57, 0x00, 0x62, 0xFF, 0x80, 0x00, 0xBD, 0xFF, 0x10, - 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x33, 0xFC, - 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B, 0x9E, 0xF2, 0xCB, - 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x18, 0x00, 0x8F, 0xFF, 0x47, 0x01, 0x08, 0xFD, 0x49, - 0x06, 0x05, 0xF2, 0x1D, 0x38, 0xA6, 0x27, 0x26, 0xF2, 0x23, 0x07, - 0x33, 0xFC, 0xDD, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, - 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01, - 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2, - 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x24, 0x00, 0x6F, 0xFF, 0x48, 0x01, 0xC0, 0xFD, 0x73, 0x03, 0x07, - 0xFB, 0xDD, 0x07, 0xA1, 0x48, 0xDD, 0xFF, 0x7D, 0xFE, 0xA7, 0x01, - 0xAD, 0xFE, 0xD8, 0x00, 0x9B, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36, - 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C, 0xFC, 0x78, 0x06, 0x5A, 0xF4, - 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4, 0x6D, 0x04, 0x3F, 0xFE, 0x8E, - 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00, - 0x62, 0xFF, 0x9E, 0x01, 0x82, 0xFC, 0xF5, 0x06, 0x7D, 0xF1, 0x7B, - 0x31, 0x09, 0x2F, 0x84, 0xF1, 0x15, 0x07, 0x62, 0xFC, 0xB4, 0x01, - 0x56, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06, - 0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41, - 0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A, - 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x8F, 0xFF, 0xF5, 0x00, - 0x6F, 0xFE, 0x1E, 0x02, 0x9D, 0xFD, 0xC7, 0x01, 0xE1, 0x48, 0xAB, - 0x05, 0xEE, 0xFB, 0xFE, 0x02, 0xFB, 0xFD, 0x2C, 0x01, 0x7A, 0xFF, - 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC, - 0x01, 0xB8, 0xFC, 0x9A, 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44, - 0xA9, 0xF7, 0xA2, 0x02, 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8, - 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD3, 0x01, - 0x3C, 0xFC, 0x2A, 0x07, 0xD8, 0xF1, 0x3F, 0x2A, 0xE6, 0x35, 0xBB, - 0xF1, 0x92, 0x06, 0xD2, 0xFC, 0x69, 0x01, 0x7E, 0xFF, 0x1F, 0x00, - 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6, - 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3, - 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, - 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0x9F, 0x00, 0x24, 0xFF, 0xC9, 0x00, - 0x13, 0x00, 0x8D, 0xFC, 0xAE, 0x47, 0x3E, 0x0C, 0x56, 0xF9, 0x48, - 0x04, 0x56, 0xFD, 0x78, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E, - 0x04, 0xE6, 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00, - 0x90, 0x00, 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFD, - 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xF1, 0x06, - 0xF5, 0xF2, 0xA7, 0x22, 0xFF, 0x3B, 0xE4, 0xF2, 0x96, 0x05, 0x81, - 0xFD, 0xFD, 0x00, 0xB5, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0xFE, 0xFF, - 0x1C, 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, - 0xF1, 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, - 0xD8, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD3, - 0xFF, 0x49, 0x00, 0xD4, 0xFF, 0x88, 0xFF, 0x49, 0x02, 0x4B, 0xF8, - 0x0D, 0x45, 0x68, 0x13, 0xDF, 0xF6, 0x6C, 0x05, 0xCC, 0xFC, 0xB4, - 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, - 0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1, - 0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE, - 0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, - 0xFF, 0xDA, 0x01, 0x69, 0xFC, 0x57, 0x06, 0xAF, 0xF4, 0xF5, 0x1A, - 0x1D, 0x41, 0x11, 0xF5, 0x25, 0x04, 0x6C, 0xFE, 0x74, 0x00, 0xF9, - 0xFF, 0xF1, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF, - 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44, - 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF, - 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF1, 0xFF, 0xF9, 0xFF, 0x74, - 0x00, 0x6C, 0xFE, 0x25, 0x04, 0x11, 0xF5, 0x1D, 0x41, 0xF5, 0x1A, - 0xAF, 0xF4, 0x57, 0x06, 0x69, 0xFC, 0xDA, 0x01, 0x38, 0xFF, 0x36, - 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00, 0x8E, 0xFE, - 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1, 0x06, 0x7B, - 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF, 0x23, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF, 0xB4, 0x01, 0xCC, - 0xFC, 0x6C, 0x05, 0xDF, 0xF6, 0x68, 0x13, 0x0D, 0x45, 0x4B, 0xF8, - 0x49, 0x02, 0x88, 0xFF, 0xD4, 0xFF, 0x49, 0x00, 0xD3, 0xFF, 0x0B, - 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37, 0xFC, - 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1, 0x6F, - 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, - 0x01, 0x00, 0x0B, 0x00, 0xB5, 0xFF, 0xFD, 0x00, 0x81, 0xFD, 0x96, - 0x05, 0xE4, 0xF2, 0xFF, 0x3B, 0xA7, 0x22, 0xF5, 0xF2, 0xF1, 0x06, - 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, - 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF, 0x90, 0x00, 0x7A, 0x00, - 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6, 0xF8, 0x7E, 0x04, 0x3C, - 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x5C, 0xFF, 0x78, 0x01, 0x56, 0xFD, 0x48, 0x04, 0x56, - 0xF9, 0x3E, 0x0C, 0xAE, 0x47, 0x8D, 0xFC, 0x13, 0x00, 0xC9, 0x00, - 0x24, 0xFF, 0x9F, 0x00, 0xB1, 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, - 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC, 0xDD, 0x06, 0x37, 0xF3, - 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F, 0x05, 0xA6, 0xFD, 0xE8, - 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1F, 0x00, - 0x7E, 0xFF, 0x69, 0x01, 0xD2, 0xFC, 0x92, 0x06, 0xBB, 0xF1, 0xE6, - 0x35, 0x3F, 0x2A, 0xD8, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01, - 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD8, 0xFF, 0x3A, - 0x00, 0xF1, 0xFF, 0x54, 0xFF, 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44, - 0xB1, 0x14, 0x77, 0xF6, 0x9A, 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42, - 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF, - 0x2C, 0x01, 0xFB, 0xFD, 0xFE, 0x02, 0xEE, 0xFB, 0xAB, 0x05, 0xE1, - 0x48, 0xC7, 0x01, 0x9D, 0xFD, 0x1E, 0x02, 0x6F, 0xFE, 0xF5, 0x00, - 0x8F, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, - 0x01, 0x77, 0xFC, 0x33, 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, - 0x8D, 0xF5, 0xDA, 0x03, 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, - 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x56, 0xFF, 0xB4, 0x01, - 0x62, 0xFC, 0x15, 0x07, 0x84, 0xF1, 0x09, 0x2F, 0x7B, 0x31, 0x7D, - 0xF1, 0xF5, 0x06, 0x82, 0xFC, 0x9E, 0x01, 0x62, 0xFF, 0x28, 0x00, - 0xFD, 0xFF, 0x04, 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F, - 0xFE, 0x6D, 0x04, 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4, - 0x78, 0x06, 0x5C, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, - 0xFF, 0x18, 0x00, 0x9B, 0xFF, 0xD8, 0x00, 0xAD, 0xFE, 0xA7, 0x01, - 0x7D, 0xFE, 0xDD, 0xFF, 0xA1, 0x48, 0xDD, 0x07, 0x07, 0xFB, 0x73, - 0x03, 0xC0, 0xFD, 0x48, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, - 0x05, 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, - 0xBE, 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0xFD, - 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDD, 0x01, 0x33, 0xFC, 0x23, 0x07, - 0x26, 0xF2, 0xA6, 0x27, 0x1D, 0x38, 0x05, 0xF2, 0x49, 0x06, 0x08, - 0xFD, 0x47, 0x01, 0x8F, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x0E, 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E, - 0xF2, 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC, - 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBD, - 0xFF, 0x80, 0x00, 0x62, 0xFF, 0x57, 0x00, 0xDF, 0x00, 0xF7, 0xFA, - 0xED, 0x46, 0xAA, 0x0E, 0x76, 0xF8, 0xB2, 0x04, 0x23, 0xFD, 0x8F, - 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, - 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E, - 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF, - 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, - 0xFF, 0xE5, 0x01, 0x41, 0xFC, 0xC6, 0x06, 0x7F, 0xF3, 0xFD, 0x1F, - 0xE4, 0x3D, 0x87, 0xF3, 0x24, 0x05, 0xCC, 0xFD, 0xD1, 0x00, 0xCB, - 0xFF, 0x02, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76, 0xFF, - 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34, 0x89, - 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49, 0xFF, - 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2C, 0x00, 0x0D, - 0x00, 0x21, 0xFF, 0xF9, 0x02, 0x0F, 0xF7, 0xD4, 0x43, 0xFD, 0x15, - 0x13, 0xF6, 0xC5, 0x05, 0xA5, 0xFC, 0xC4, 0x01, 0x40, 0xFF, 0x33, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF, 0x1E, 0x01, - 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2, 0x48, 0xC6, - 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01, 0x8A, 0xFF, - 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD0, 0x01, 0x86, - 0xFC, 0x0D, 0x06, 0x66, 0xF5, 0x50, 0x18, 0x9E, 0x42, 0x11, 0xF6, - 0x8C, 0x03, 0xC9, 0xFE, 0x3F, 0x00, 0x14, 0x00, 0xE7, 0xFF, 0x07, - 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE, 0x01, 0x56, 0xFC, - 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32, 0x84, 0xF1, 0xE0, - 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26, 0x00, 0xFD, 0xFF, - 0x03, 0x00, 0xFA, 0xFF, 0xE0, 0xFF, 0xA7, 0x00, 0x15, 0xFE, 0xB2, - 0x04, 0x32, 0xF4, 0x77, 0x3F, 0x9E, 0x1D, 0x07, 0xF4, 0x96, 0x06, - 0x51, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, - 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE, - 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3, - 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x2F, 0x00, 0x4C, 0xFF, 0xA1, 0x01, 0xF8, 0xFC, 0x0D, 0x05, 0xB3, - 0xF7, 0xDF, 0x10, 0x1D, 0x46, 0xA7, 0xF9, 0x8E, 0x01, 0xF4, 0xFF, - 0x98, 0xFF, 0x66, 0x00, 0xC7, 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, - 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31, 0xFC, 0x1A, 0x07, 0x56, 0xF2, - 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2, 0x1E, 0x06, 0x25, 0xFD, 0x35, - 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x12, 0x00, - 0xA0, 0xFF, 0x26, 0x01, 0x3E, 0xFD, 0xFB, 0x05, 0x60, 0xF2, 0xFD, - 0x39, 0x4E, 0x25, 0x7F, 0xF2, 0x11, 0x07, 0x31, 0xFC, 0xE3, 0x01, - 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71, - 0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46, - 0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F, - 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x66, 0xFF, - 0x5F, 0x01, 0x8D, 0xFD, 0xD9, 0x03, 0x3B, 0xFA, 0xE4, 0x09, 0x41, - 0x48, 0x41, 0xFE, 0x3F, 0xFF, 0x3E, 0x01, 0xE5, 0xFE, 0xBD, 0x00, - 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, - 0x01, 0x4A, 0xFC, 0xAC, 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E, - 0xE4, 0xF3, 0xE5, 0x04, 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE, - 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6E, 0xFF, 0x87, 0x01, - 0xA4, 0xFC, 0xCD, 0x06, 0x8E, 0xF1, 0x99, 0x33, 0xCE, 0x2C, 0xA1, - 0xF1, 0x25, 0x07, 0x4D, 0xFC, 0xC4, 0x01, 0x4D, 0xFF, 0x2F, 0x00, - 0xFD, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF, - 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5, - 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, - 0xFF, 0x1E, 0x00, 0x85, 0xFF, 0x10, 0x01, 0x38, 0xFE, 0x88, 0x02, - 0xD3, 0xFC, 0x91, 0x03, 0xF7, 0x48, 0xCB, 0x03, 0xBA, 0xFC, 0x95, - 0x02, 0x31, 0xFE, 0x13, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00, 0x00, - 0xFE, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6, - 0x05, 0xC6, 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03, - 0xFA, 0xFE, 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0xFD, - 0xFF, 0x30, 0x00, 0x4C, 0xFF, 0xC6, 0x01, 0x4B, 0xFC, 0x26, 0x07, - 0xA5, 0xF1, 0x87, 0x2C, 0xDC, 0x33, 0x91, 0xF1, 0xC7, 0x06, 0xA9, - 0xFC, 0x84, 0x01, 0x70, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x03, 0x00, - 0xFF, 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, - 0xF3, 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, - 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA7, - 0xFF, 0xB9, 0x00, 0xEC, 0xFE, 0x31, 0x01, 0x57, 0xFF, 0x0F, 0xFE, - 0x33, 0x48, 0x25, 0x0A, 0x21, 0xFA, 0xE5, 0x03, 0x87, 0xFD, 0x62, - 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, - 0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0, - 0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF, - 0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, - 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0E, 0x07, 0x8B, 0xF2, 0x03, 0x25, - 0x38, 0x3A, 0x6D, 0xF2, 0xF1, 0x05, 0x45, 0xFD, 0x22, 0x01, 0xA2, - 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF, - 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0, - 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF, - 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xC9, 0xFF, 0x63, 0x00, 0x9F, - 0xFF, 0xE8, 0xFF, 0xA3, 0x01, 0x7F, 0xF9, 0x02, 0x46, 0x27, 0x11, - 0x9B, 0xF7, 0x18, 0x05, 0xF3, 0xFC, 0xA3, 0x01, 0x4C, 0xFF, 0x2F, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF, 0x52, 0x01, - 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C, 0x48, 0x26, - 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00, 0xA0, 0xFF, - 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE1, 0x01, 0x53, - 0xFC, 0x90, 0x06, 0x19, 0xF4, 0x52, 0x1D, 0xA8, 0x3F, 0x49, 0xF4, - 0xA3, 0x04, 0x1E, 0xFE, 0xA1, 0x00, 0xE3, 0xFF, 0xF9, 0xFF, 0x04, - 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90, 0xFC, - 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1, 0x1D, - 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, - 0x07, 0x00, 0xE8, 0xFF, 0x11, 0x00, 0x45, 0x00, 0xBF, 0xFE, 0x9D, - 0x03, 0xF3, 0xF5, 0x75, 0x42, 0x9B, 0x18, 0x51, 0xF5, 0x16, 0x06, - 0x83, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, - 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE, 0x4D, 0x02, 0x45, 0xFD, - 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47, 0xFC, 0xD1, 0x02, 0x12, - 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x33, 0x00, 0x40, 0xFF, 0xC2, 0x01, 0xA9, 0xFC, 0xBC, 0x05, 0x29, - 0xF6, 0xB3, 0x15, 0xFA, 0x43, 0x31, 0xF7, 0xE6, 0x02, 0x2C, 0xFF, - 0x07, 0x00, 0x2F, 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, - 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC, 0x2A, 0x07, 0xBF, 0xF1, - 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB, 0x06, 0xBF, 0xFC, 0x75, - 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00, - 0xC8, 0xFF, 0xD6, 0x00, 0xC4, 0xFD, 0x31, 0x05, 0x73, 0xF3, 0xB0, - 0x3D, 0x49, 0x20, 0x6E, 0xF3, 0xCB, 0x06, 0x40, 0xFC, 0xE6, 0x01, - 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA, - 0x00, 0x0C, 0xFF, 0xF7, 0x00, 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47, - 0x51, 0x0B, 0xAF, 0xF9, 0x1D, 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60, - 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF, - 0x8C, 0x01, 0x29, 0xFD, 0xA7, 0x04, 0x8F, 0xF8, 0x64, 0x0E, 0x02, - 0x47, 0x22, 0xFB, 0xC9, 0x00, 0x64, 0x00, 0x5B, 0xFF, 0x84, 0x00, - 0xBC, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, - 0x01, 0x33, 0xFC, 0xFF, 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, - 0xAD, 0xF2, 0xBF, 0x05, 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8D, 0xFF, 0x4B, 0x01, - 0x01, 0xFD, 0x51, 0x06, 0xFB, 0xF1, 0xDF, 0x37, 0xF0, 0x27, 0x1C, - 0xF2, 0x24, 0x07, 0x34, 0xFC, 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, - 0xFD, 0xFF, 0x0C, 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2, - 0xFF, 0x01, 0x02, 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7, - 0x48, 0x05, 0xDD, 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x45, 0x01, 0xC6, 0xFD, - 0x66, 0x03, 0x21, 0xFB, 0x9E, 0x07, 0xAA, 0x48, 0x12, 0x00, 0x64, - 0xFE, 0xB4, 0x01, 0xA6, 0xFE, 0xDB, 0x00, 0x9A, 0xFF, 0x19, 0x00, - 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, - 0x06, 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, - 0x49, 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFD, - 0xFF, 0x29, 0x00, 0x61, 0xFF, 0xA1, 0x01, 0x7E, 0xFC, 0xF9, 0x06, - 0x7C, 0xF1, 0x38, 0x31, 0x50, 0x2F, 0x82, 0xF1, 0x12, 0x07, 0x65, - 0xFC, 0xB2, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x06, 0x00, - 0xED, 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71, - 0xF5, 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC, - 0xD7, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x91, - 0xFF, 0xF2, 0x00, 0x76, 0xFE, 0x11, 0x02, 0xB6, 0xFD, 0x8F, 0x01, - 0xDE, 0x48, 0xE9, 0x05, 0xD4, 0xFB, 0x0C, 0x03, 0xF4, 0xFD, 0x2F, - 0x01, 0x79, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, - 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68, - 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF, - 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, - 0xFF, 0xD4, 0x01, 0x3B, 0xFC, 0x2A, 0x07, 0xDF, 0xF1, 0xF6, 0x29, - 0x27, 0x36, 0xC1, 0xF1, 0x8B, 0x06, 0xD8, 0xFC, 0x66, 0x01, 0x80, - 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xBD, 0xFF, - 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C, 0x9E, - 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37, 0xFF, - 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x9B, 0x00, 0x2B, - 0xFF, 0xBD, 0x00, 0x2A, 0x00, 0x5E, 0xFC, 0x9A, 0x47, 0x82, 0x0C, - 0x3D, 0xF9, 0x54, 0x04, 0x50, 0xFD, 0x7A, 0x01, 0x5B, 0xFF, 0x2A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, 0x81, 0x01, - 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69, 0x47, 0xEB, - 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00, 0xB6, 0xFF, - 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x37, - 0xFC, 0xED, 0x06, 0x03, 0xF3, 0x5B, 0x22, 0x37, 0x3C, 0xF4, 0xF2, - 0x8A, 0x05, 0x89, 0xFD, 0xF9, 0x00, 0xB7, 0xFF, 0x0A, 0x00, 0x01, - 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C, 0x01, 0xE6, 0xFC, - 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29, 0xF3, 0xF1, 0x29, - 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33, 0x00, 0xFD, 0xFF, - 0x0B, 0x00, 0xD4, 0xFF, 0x46, 0x00, 0xDA, 0xFF, 0x7D, 0xFF, 0x5D, - 0x02, 0x26, 0xF8, 0xED, 0x44, 0xB1, 0x13, 0xC7, 0xF6, 0x77, 0x05, - 0xC8, 0xFC, 0xB6, 0x01, 0x45, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03, - 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0, - 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, - 0x35, 0x00, 0x38, 0xFF, 0xD9, 0x01, 0x6C, 0xFC, 0x4F, 0x06, 0xC3, - 0xF4, 0xA9, 0x1A, 0x49, 0x41, 0x2C, 0xF5, 0x15, 0x04, 0x76, 0xFE, - 0x6E, 0x00, 0xFC, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2B, - 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E, 0xFC, 0x0A, 0x07, 0x7E, 0xF1, - 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1, 0x03, 0x07, 0x75, 0xFC, 0xA7, - 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF2, 0xFF, - 0xF7, 0xFF, 0x7A, 0x00, 0x62, 0xFE, 0x35, 0x04, 0xF7, 0xF4, 0xEF, - 0x40, 0x40, 0x1B, 0x9C, 0xF4, 0x5E, 0x06, 0x66, 0xFC, 0xDB, 0x01, - 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3, - 0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48, - 0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73, - 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, - 0xB2, 0x01, 0xD1, 0xFC, 0x62, 0x05, 0xF6, 0xF6, 0x20, 0x13, 0x2E, - 0x45, 0x70, 0xF8, 0x34, 0x02, 0x94, 0xFF, 0xCD, 0xFF, 0x4C, 0x00, - 0xD2, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA, - 0x01, 0x36, 0xFC, 0x27, 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37, - 0xE4, 0xF1, 0x67, 0x06, 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B, - 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0B, 0x00, 0xB2, 0xFF, 0x02, 0x01, - 0x7A, 0xFD, 0xA2, 0x05, 0xD4, 0xF2, 0xC7, 0x3B, 0xF2, 0x22, 0xE7, - 0xF2, 0xF5, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, - 0xFD, 0xFF, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83, - 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8, - 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x75, 0x01, 0x5C, 0xFD, - 0x3C, 0x04, 0x70, 0xF9, 0xFA, 0x0B, 0xC0, 0x47, 0xBC, 0xFC, 0xFC, - 0xFF, 0xD6, 0x00, 0x1D, 0xFF, 0xA2, 0x00, 0xB0, 0xFF, 0x13, 0x00, - 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8, - 0x06, 0x47, 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05, - 0xAE, 0xFD, 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0xFE, - 0xFF, 0x1F, 0x00, 0x7C, 0xFF, 0x6D, 0x01, 0xCD, 0xFC, 0x99, 0x06, - 0xB4, 0xF1, 0xA6, 0x35, 0x89, 0x2A, 0xD0, 0xF1, 0x2B, 0x07, 0x3E, - 0xFC, 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, - 0xD9, 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, - 0xF7, 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, - 0xBE, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, - 0x00, 0x7B, 0xFF, 0x29, 0x01, 0x01, 0xFE, 0xF1, 0x02, 0x07, 0xFC, - 0x6E, 0x05, 0xE6, 0x48, 0xFF, 0x01, 0x84, 0xFD, 0x2C, 0x02, 0x68, - 0xFE, 0xF9, 0x00, 0x8E, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, - 0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56, - 0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00, - 0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x55, - 0xFF, 0xB6, 0x01, 0x5F, 0xFC, 0x17, 0x07, 0x87, 0xF1, 0xC2, 0x2E, - 0xC0, 0x31, 0x7E, 0xF1, 0xF1, 0x06, 0x86, 0xFC, 0x9B, 0x01, 0x63, - 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF, - 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94, - 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF, - 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9C, 0xFF, 0xD4, 0x00, 0xB4, - 0xFE, 0x9A, 0x01, 0x95, 0xFE, 0xA8, 0xFF, 0x98, 0x48, 0x1D, 0x08, - 0xEE, 0xFA, 0x80, 0x03, 0xB9, 0xFD, 0x4B, 0x01, 0x6E, 0xFF, 0x25, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xA9, 0x01, - 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8, 0x45, 0x1C, - 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00, 0xCC, 0xFF, - 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDE, 0x01, 0x33, - 0xFC, 0x21, 0x07, 0x30, 0xF2, 0x5C, 0x27, 0x5B, 0x38, 0x0F, 0xF2, - 0x40, 0x06, 0x0E, 0xFD, 0x43, 0x01, 0x91, 0xFF, 0x18, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57, 0xFD, - 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2, 0x06, - 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, - 0x10, 0x00, 0xBE, 0xFF, 0x7D, 0x00, 0x69, 0xFF, 0x4B, 0x00, 0xF6, - 0x00, 0xCB, 0xFA, 0xD3, 0x46, 0xF0, 0x0E, 0x5E, 0xF8, 0xBE, 0x04, - 0x1E, 0xFD, 0x91, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01, 0x77, 0xFD, 0x04, 0x04, - 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94, 0xFD, 0x92, 0xFF, 0x10, - 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF, 0x15, 0x00, 0xFD, 0xFF, - 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x43, 0xFC, 0xC0, 0x06, 0x8F, - 0xF3, 0xB1, 0x1F, 0x18, 0x3E, 0x9B, 0xF3, 0x16, 0x05, 0xD5, 0xFD, - 0xCC, 0x00, 0xCE, 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x22, - 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC, 0xB8, 0x06, 0x9C, 0xF1, - 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29, 0x07, 0x46, 0xFC, 0xCA, - 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDF, 0xFF, - 0x29, 0x00, 0x14, 0x00, 0x16, 0xFF, 0x0C, 0x03, 0xEE, 0xF6, 0xB0, - 0x43, 0x47, 0x16, 0xFC, 0xF5, 0xCF, 0x05, 0xA1, 0xFC, 0xC6, 0x01, - 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, - 0xFF, 0x1B, 0x01, 0x20, 0xFE, 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04, - 0xF4, 0x48, 0xFF, 0x02, 0x13, 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07, - 0x01, 0x88, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, - 0xCF, 0x01, 0x8A, 0xFC, 0x05, 0x06, 0x7B, 0xF5, 0x06, 0x18, 0xC7, - 0x42, 0x2F, 0xF6, 0x7A, 0x03, 0xD4, 0xFE, 0x39, 0x00, 0x17, 0x00, - 0xE6, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, - 0x01, 0x53, 0xFC, 0x21, 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, - 0x86, 0xF1, 0xDB, 0x06, 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, - 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDE, 0xFF, 0xAC, 0x00, - 0x0B, 0xFE, 0xC1, 0x04, 0x1B, 0xF4, 0x47, 0x3F, 0xEA, 0x1D, 0xF5, - 0xF3, 0x9C, 0x06, 0x4F, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, - 0xFE, 0xFF, 0x16, 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F, - 0x01, 0x03, 0xFF, 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA, - 0xB9, 0x03, 0x9D, 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4D, 0xFF, 0x9F, 0x01, 0xFE, 0xFC, - 0x02, 0x05, 0xCB, 0xF7, 0x98, 0x10, 0x39, 0x46, 0xD0, 0xF9, 0x78, - 0x01, 0x00, 0x00, 0x91, 0xFF, 0x69, 0x00, 0xC6, 0xFF, 0x0E, 0x00, - 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, - 0x07, 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, - 0x2C, 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0x13, 0x00, 0x9E, 0xFF, 0x2B, 0x01, 0x37, 0xFD, 0x05, 0x06, - 0x54, 0xF2, 0xC2, 0x39, 0x99, 0x25, 0x73, 0xF2, 0x14, 0x07, 0x31, - 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, - 0xC4, 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D, - 0xFA, 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD, - 0x9C, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, - 0x00, 0x67, 0xFF, 0x5C, 0x01, 0x93, 0xFD, 0xCC, 0x03, 0x54, 0xFA, - 0xA2, 0x09, 0x4F, 0x48, 0x73, 0xFE, 0x27, 0xFF, 0x4B, 0x01, 0xDE, - 0xFE, 0xC0, 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, - 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B, - 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00, - 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6D, - 0xFF, 0x8A, 0x01, 0x9F, 0xFC, 0xD3, 0x06, 0x8A, 0xF1, 0x57, 0x33, - 0x17, 0x2D, 0x9C, 0xF1, 0x24, 0x07, 0x4F, 0xFC, 0xC3, 0x01, 0x4E, - 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE4, 0xFF, 0x1B, 0x00, - 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43, 0x96, - 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D, 0xFF, - 0x34, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x86, 0xFF, 0x0C, 0x01, 0x3E, - 0xFE, 0x7B, 0x02, 0xED, 0xFC, 0x56, 0x03, 0xF5, 0x48, 0x06, 0x04, - 0xA1, 0xFC, 0xA3, 0x02, 0x2A, 0xFE, 0x16, 0x01, 0x83, 0xFF, 0x1F, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, 0xC8, 0x01, - 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77, 0x43, 0xBD, - 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00, 0xE1, 0xFF, - 0x08, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC8, 0x01, 0x49, - 0xFC, 0x27, 0x07, 0xAB, 0xF1, 0x3E, 0x2C, 0x1E, 0x34, 0x95, 0xF1, - 0xC1, 0x06, 0xAE, 0xFC, 0x81, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE, - 0xFF, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4, 0x00, 0xE2, 0xFD, - 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F, 0xA8, 0xF3, 0xB8, - 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, - 0x15, 0x00, 0xA8, 0xFF, 0xB6, 0x00, 0xF3, 0xFE, 0x24, 0x01, 0x6E, - 0xFF, 0xDE, 0xFD, 0x25, 0x48, 0x68, 0x0A, 0x08, 0xFA, 0xF2, 0x03, - 0x81, 0xFD, 0x65, 0x01, 0x64, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04, - 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38, - 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, - 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0B, 0x07, 0x97, - 0xF2, 0xB8, 0x24, 0x71, 0x3A, 0x7B, 0xF2, 0xE6, 0x05, 0x4C, 0xFD, - 0x1D, 0x01, 0xA4, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x16, - 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18, 0xFD, 0x32, 0x06, 0x1F, 0xF2, - 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2, 0x1E, 0x07, 0x32, 0xFC, 0xDF, - 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0D, 0x00, 0xCA, 0xFF, - 0x5F, 0x00, 0xA5, 0xFF, 0xDC, 0xFF, 0xB8, 0x01, 0x57, 0xF9, 0xE5, - 0x45, 0x6E, 0x11, 0x83, 0xF7, 0x23, 0x05, 0xEE, 0xFC, 0xA6, 0x01, - 0x4B, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C, - 0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08, - 0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF, - 0x00, 0x9E, 0xFF, 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, - 0xE0, 0x01, 0x56, 0xFC, 0x89, 0x06, 0x2B, 0xF4, 0x06, 0x1D, 0xD7, - 0x3F, 0x61, 0xF4, 0x94, 0x04, 0x27, 0xFE, 0x9C, 0x00, 0xE6, 0xFF, - 0xF8, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97, - 0x01, 0x8C, 0xFC, 0xEA, 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E, - 0x8B, 0xF1, 0x1B, 0x07, 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D, - 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE9, 0xFF, 0x0E, 0x00, 0x4B, 0x00, - 0xB4, 0xFE, 0xAF, 0x03, 0xD5, 0xF5, 0x4D, 0x42, 0xE6, 0x18, 0x3C, - 0xF5, 0x1F, 0x06, 0x7F, 0xFC, 0xD3, 0x01, 0x3B, 0xFF, 0x35, 0x00, - 0xFE, 0xFF, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F, - 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC, - 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xC1, 0x01, 0xAD, 0xFC, - 0xB2, 0x05, 0x3F, 0xF6, 0x69, 0x15, 0x1F, 0x44, 0x53, 0xF7, 0xD3, - 0x02, 0x38, 0xFF, 0x01, 0x00, 0x33, 0x00, 0xDB, 0xFF, 0x09, 0x00, - 0xFD, 0xFF, 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A, - 0x07, 0xC6, 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06, - 0xC4, 0xFC, 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x02, - 0x00, 0x04, 0x00, 0xC6, 0xFF, 0xDB, 0x00, 0xBB, 0xFD, 0x3E, 0x05, - 0x60, 0xF3, 0x7B, 0x3D, 0x94, 0x20, 0x5E, 0xF3, 0xD0, 0x06, 0x3E, - 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, - 0xAE, 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, - 0xFD, 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, - 0x71, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2C, - 0x00, 0x55, 0xFF, 0x8A, 0x01, 0x2E, 0xFD, 0x9B, 0x04, 0xA8, 0xF8, - 0x1F, 0x0E, 0x1A, 0x47, 0x4E, 0xFB, 0xB3, 0x00, 0x70, 0x00, 0x54, - 0xFF, 0x87, 0x00, 0xBB, 0xFF, 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, - 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64, - 0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01, - 0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8B, - 0xFF, 0x4F, 0x01, 0xFB, 0xFC, 0x5A, 0x06, 0xF2, 0xF1, 0xA0, 0x37, - 0x3A, 0x28, 0x13, 0xF2, 0x25, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, - 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00, - 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2, - 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF, - 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x42, - 0x01, 0xCD, 0xFD, 0x59, 0x03, 0x3B, 0xFB, 0x5E, 0x07, 0xB3, 0x48, - 0x48, 0x00, 0x4B, 0xFE, 0xC2, 0x01, 0x9F, 0xFE, 0xDE, 0x00, 0x98, - 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDD, 0x01, - 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB, 0x40, 0xD0, - 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF, 0xF4, 0xFF, - 0x05, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA3, 0x01, 0x7A, - 0xFC, 0xFD, 0x06, 0x7C, 0xF1, 0xF2, 0x30, 0x96, 0x2F, 0x80, 0xF1, - 0x0F, 0x07, 0x69, 0xFC, 0xB0, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0xFD, - 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85, 0xFE, - 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4, 0x43, - 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, - 0x1B, 0x00, 0x92, 0xFF, 0xEF, 0x00, 0x7D, 0xFE, 0x04, 0x02, 0xCF, - 0xFD, 0x58, 0x01, 0xD7, 0x48, 0x26, 0x06, 0xBB, 0xFB, 0x19, 0x03, - 0xED, 0xFD, 0x32, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFF, - 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01, 0xC1, 0xFC, 0x86, 0x05, - 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0, 0xF7, 0x7B, 0x02, 0x6B, - 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, - 0x33, 0x00, 0x43, 0xFF, 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE7, - 0xF1, 0xAC, 0x29, 0x66, 0x36, 0xC9, 0xF1, 0x83, 0x06, 0xDD, 0xFC, - 0x62, 0x01, 0x81, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x08, - 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD, 0x78, 0x05, 0x0E, 0xF3, - 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6, 0x06, 0x38, 0xFC, 0xE6, - 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, 0x00, 0xB4, 0xFF, - 0x98, 0x00, 0x32, 0xFF, 0xB0, 0x00, 0x41, 0x00, 0x30, 0xFC, 0x86, - 0x47, 0xC6, 0x0C, 0x24, 0xF9, 0x60, 0x04, 0x4B, 0xFD, 0x7D, 0x01, - 0x5A, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x5A, - 0xFF, 0x7E, 0x01, 0x48, 0xFD, 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C, - 0x7C, 0x47, 0x19, 0xFC, 0x4D, 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96, - 0x00, 0xB5, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, - 0xE6, 0x01, 0x38, 0xFC, 0xE9, 0x06, 0x12, 0xF3, 0x10, 0x22, 0x6E, - 0x3C, 0x05, 0xF3, 0x7E, 0x05, 0x91, 0xFD, 0xF4, 0x00, 0xBA, 0xFF, - 0x09, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, - 0x01, 0xE0, 0xFC, 0x7F, 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, - 0xEB, 0xF1, 0x2A, 0x07, 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, - 0x00, 0xFD, 0xFF, 0x0B, 0x00, 0xD5, 0xFF, 0x42, 0x00, 0xE1, 0xFF, - 0x71, 0xFF, 0x71, 0x02, 0x02, 0xF8, 0xCC, 0x44, 0xFA, 0x13, 0xB0, - 0xF6, 0x81, 0x05, 0xC3, 0xFC, 0xB8, 0x01, 0x44, 0xFF, 0x31, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA, - 0xFD, 0x1F, 0x03, 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01, - 0xDC, 0xFD, 0xFD, 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B, - 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x6F, 0xFC, - 0x47, 0x06, 0xD7, 0xF4, 0x5D, 0x1A, 0x74, 0x41, 0x48, 0xF5, 0x04, - 0x04, 0x80, 0xFE, 0x69, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0x05, 0x00, - 0xFD, 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, - 0x07, 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, - 0x78, 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x05, - 0x00, 0xF3, 0xFF, 0xF4, 0xFF, 0x80, 0x00, 0x58, 0xFE, 0x46, 0x04, - 0xDD, 0xF4, 0xC3, 0x40, 0x8C, 0x1B, 0x89, 0xF4, 0x66, 0x06, 0x63, - 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, - 0x98, 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62, - 0x00, 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD, - 0x40, 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, - 0x00, 0x47, 0xFF, 0xB0, 0x01, 0xD6, 0xFC, 0x58, 0x05, 0x0D, 0xF7, - 0xD7, 0x12, 0x4E, 0x45, 0x96, 0xF8, 0x20, 0x02, 0xA0, 0xFF, 0xC7, - 0xFF, 0x4F, 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, - 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60, - 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01, - 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, 0xB0, - 0xFF, 0x07, 0x01, 0x72, 0xFD, 0xAE, 0x05, 0xC4, 0xF2, 0x90, 0x3B, - 0x3F, 0x23, 0xD9, 0xF2, 0xF9, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, - 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89, 0x00, - 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47, 0xFC, - 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56, 0xFF, - 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5E, 0xFF, 0x72, - 0x01, 0x62, 0xFD, 0x2F, 0x04, 0x89, 0xF9, 0xB6, 0x0B, 0xD2, 0x47, - 0xEB, 0xFC, 0xE4, 0xFF, 0xE3, 0x00, 0x16, 0xFF, 0xA5, 0x00, 0xAF, - 0xFF, 0x13, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, - 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61, 0x3D, 0x56, - 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF, 0x05, 0x00, - 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x7A, 0xFF, 0x70, 0x01, 0xC7, - 0xFC, 0xA0, 0x06, 0xAE, 0xF1, 0x65, 0x35, 0xD1, 0x2A, 0xCA, 0xF1, - 0x2A, 0x07, 0x40, 0xFC, 0xD0, 0x01, 0x47, 0xFF, 0x32, 0x00, 0xFD, - 0xFF, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x3D, 0xFF, - 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15, 0x4A, 0xF6, 0xAD, - 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x21, 0x00, 0x7C, 0xFF, 0x26, 0x01, 0x08, 0xFE, 0xE4, - 0x02, 0x21, 0xFC, 0x31, 0x05, 0xEB, 0x48, 0x37, 0x02, 0x6B, 0xFD, - 0x39, 0x02, 0x61, 0xFE, 0xFC, 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFE, - 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06, - 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF, - 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFD, 0xFF, - 0x2D, 0x00, 0x54, 0xFF, 0xB8, 0x01, 0x5D, 0xFC, 0x1A, 0x07, 0x8A, - 0xF1, 0x7B, 0x2E, 0x04, 0x32, 0x7F, 0xF1, 0xEC, 0x06, 0x8A, 0xFC, - 0x98, 0x01, 0x65, 0xFF, 0x27, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF8, - 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C, 0xFE, 0x8C, 0x04, 0x6D, 0xF4, - 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4, 0x85, 0x06, 0x57, 0xFC, 0xE0, - 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x18, 0x00, 0x9E, 0xFF, - 0xD1, 0x00, 0xBB, 0xFE, 0x8D, 0x01, 0xAE, 0xFE, 0x74, 0xFF, 0x8D, - 0x48, 0x5D, 0x08, 0xD4, 0xFA, 0x8D, 0x03, 0xB3, 0xFD, 0x4E, 0x01, - 0x6D, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A, - 0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11, - 0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E, - 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3D, 0xFF, - 0xDF, 0x01, 0x32, 0xFC, 0x1F, 0x07, 0x3B, 0xF2, 0x11, 0x27, 0x97, - 0x38, 0x19, 0xF2, 0x36, 0x06, 0x15, 0xFD, 0x3F, 0x01, 0x93, 0xFF, - 0x17, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B, - 0x01, 0x50, 0xFD, 0xE1, 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24, - 0x9D, 0xF2, 0x09, 0x07, 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, - 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x7A, 0x00, 0x70, 0xFF, - 0x3E, 0x00, 0x0C, 0x01, 0xA1, 0xFA, 0xBB, 0x46, 0x36, 0x0F, 0x45, - 0xF8, 0xC9, 0x04, 0x18, 0xFD, 0x93, 0x01, 0x52, 0xFF, 0x2D, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D, - 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD, - 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15, - 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x45, 0xFC, - 0xBB, 0x06, 0xA0, 0xF3, 0x64, 0x1F, 0x4A, 0x3E, 0xB0, 0xF3, 0x08, - 0x05, 0xDE, 0xFD, 0xC7, 0x00, 0xD0, 0xFF, 0x00, 0x00, 0x02, 0x00, - 0xFE, 0xFF, 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE, - 0x06, 0x97, 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07, - 0x48, 0xFC, 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, - 0x00, 0xE0, 0xFF, 0x26, 0x00, 0x1A, 0x00, 0x0B, 0xFF, 0x1E, 0x03, - 0xCD, 0xF6, 0x89, 0x43, 0x91, 0x16, 0xE7, 0xF5, 0xD8, 0x05, 0x9D, - 0xFC, 0xC7, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x1F, 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, - 0xFC, 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, - 0x42, 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x34, - 0x00, 0x3C, 0xFF, 0xCD, 0x01, 0x8E, 0xFC, 0xFC, 0x05, 0x90, 0xF5, - 0xBB, 0x17, 0xEE, 0x42, 0x4E, 0xF6, 0x68, 0x03, 0xDF, 0xFE, 0x33, - 0x00, 0x1A, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2F, 0x00, - 0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A, - 0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01, - 0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFC, 0xFF, 0xDB, - 0xFF, 0xB2, 0x00, 0x02, 0xFE, 0xCF, 0x04, 0x05, 0xF4, 0x16, 0x3F, - 0x36, 0x1E, 0xE4, 0xF3, 0xA3, 0x06, 0x4D, 0xFC, 0xE3, 0x01, 0x36, - 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00, - 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81, - 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF, - 0x26, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9D, - 0x01, 0x03, 0xFD, 0xF7, 0x04, 0xE3, 0xF7, 0x51, 0x10, 0x55, 0x46, - 0xF9, 0xF9, 0x63, 0x01, 0x0D, 0x00, 0x8B, 0xFF, 0x6D, 0x00, 0xC5, - 0xFF, 0x0E, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, - 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5, 0x39, 0x4D, - 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF, 0x13, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0x9C, 0xFF, 0x2F, 0x01, 0x30, - 0xFD, 0x10, 0x06, 0x47, 0xF2, 0x87, 0x39, 0xE5, 0x25, 0x67, 0xF2, - 0x16, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, - 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06, 0x00, - 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7, 0xFC, - 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x59, 0x01, 0x99, 0xFD, 0xC0, - 0x03, 0x6E, 0xFA, 0x61, 0x09, 0x5D, 0x48, 0xA6, 0xFE, 0x0F, 0xFF, - 0x58, 0x01, 0xD7, 0xFE, 0xC3, 0x00, 0xA3, 0xFF, 0x16, 0x00, 0xFE, - 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4E, 0xFC, 0xA0, 0x06, - 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10, 0xF4, 0xC8, 0x04, 0x07, - 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF, 0x03, 0x00, 0xFD, 0xFF, - 0x25, 0x00, 0x6B, 0xFF, 0x8D, 0x01, 0x9B, 0xFC, 0xD8, 0x06, 0x87, - 0xF1, 0x13, 0x33, 0x5E, 0x2D, 0x98, 0xF1, 0x22, 0x07, 0x52, 0xFC, - 0xC1, 0x01, 0x4F, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x07, 0x00, 0xE5, - 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE, 0x71, 0x03, 0x3F, 0xF6, - 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00, 0x06, 0x8C, 0xFC, 0xCE, - 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, 0x00, 0x88, 0xFF, - 0x09, 0x01, 0x45, 0xFE, 0x6E, 0x02, 0x06, 0xFD, 0x1C, 0x03, 0xF4, - 0x48, 0x41, 0x04, 0x87, 0xFC, 0xB0, 0x02, 0x23, 0xFE, 0x19, 0x01, - 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, - 0xFF, 0xC6, 0x01, 0x9F, 0xFC, 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16, - 0x9E, 0x43, 0xDD, 0xF6, 0x15, 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28, - 0x00, 0xDF, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF, - 0xCA, 0x01, 0x47, 0xFC, 0x28, 0x07, 0xB0, 0xF1, 0xF5, 0x2B, 0x60, - 0x34, 0x9A, 0xF1, 0xBB, 0x06, 0xB3, 0xFC, 0x7D, 0x01, 0x73, 0xFF, - 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, - 0x00, 0xDA, 0xFD, 0x0F, 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, - 0x97, 0xF3, 0xBD, 0x06, 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, - 0x00, 0xFD, 0xFF, 0x15, 0x00, 0xAA, 0xFF, 0xB3, 0x00, 0xFA, 0xFE, - 0x17, 0x01, 0x86, 0xFF, 0xAC, 0xFD, 0x16, 0x48, 0xAA, 0x0A, 0xEE, - 0xF9, 0xFE, 0x03, 0x7A, 0xFD, 0x67, 0x01, 0x63, 0xFF, 0x28, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B, - 0xFD, 0xC4, 0x04, 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA, - 0x01, 0x01, 0x44, 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10, - 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, - 0x08, 0x07, 0xA4, 0xF2, 0x6D, 0x24, 0xAD, 0x3A, 0x88, 0xF2, 0xDB, - 0x05, 0x53, 0xFD, 0x19, 0x01, 0xA7, 0xFF, 0x10, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, - 0x06, 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, - 0x33, 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0D, - 0x00, 0xCB, 0xFF, 0x5C, 0x00, 0xAC, 0xFF, 0xD0, 0xFF, 0xCD, 0x01, - 0x30, 0xF9, 0xC8, 0x45, 0xB6, 0x11, 0x6B, 0xF7, 0x2D, 0x05, 0xE9, - 0xFC, 0xA8, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x25, 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1, - 0xFA, 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01, - 0xB8, 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFE, 0xFF, 0x36, - 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x58, 0xFC, 0x82, 0x06, 0x3E, 0xF4, - 0xBA, 0x1C, 0x07, 0x40, 0x79, 0xF4, 0x84, 0x04, 0x31, 0xFE, 0x96, - 0x00, 0xE8, 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0xFD, 0xFF, 0x28, 0x00, - 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3, - 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01, - 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00, 0xEA, 0xFF, 0x0B, - 0x00, 0x51, 0x00, 0xAA, 0xFE, 0xC0, 0x03, 0xB8, 0xF5, 0x21, 0x42, - 0x31, 0x19, 0x28, 0xF5, 0x27, 0x06, 0x7C, 0xFC, 0xD4, 0x01, 0x3A, - 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA, 0x00, - 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48, 0x50, - 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C, 0xFF, - 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x41, 0xFF, 0xBF, - 0x01, 0xB2, 0xFC, 0xA9, 0x05, 0x55, 0xF6, 0x20, 0x15, 0x42, 0x44, - 0x75, 0xF7, 0xBF, 0x02, 0x43, 0xFF, 0xFA, 0xFF, 0x36, 0x00, 0xDA, - 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, 0xD1, 0x01, - 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86, 0x35, 0xB1, - 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF, 0x20, 0x00, - 0xFE, 0xFF, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE0, 0x00, 0xB3, - 0xFD, 0x4B, 0x05, 0x4D, 0xF3, 0x45, 0x3D, 0xE0, 0x20, 0x4F, 0xF3, - 0xD5, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, - 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19, 0xFF, 0xDD, 0x00, - 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B, 0x7C, 0xF9, 0x35, - 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x2C, 0x00, 0x56, 0xFF, 0x87, 0x01, 0x34, 0xFD, 0x8F, - 0x04, 0xC0, 0xF8, 0xD9, 0x0D, 0x31, 0x47, 0x7B, 0xFB, 0x9C, 0x00, - 0x7D, 0x00, 0x4D, 0xFF, 0x8A, 0x00, 0xB9, 0xFF, 0x11, 0x00, 0xFD, - 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06, - 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76, - 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF, - 0x1A, 0x00, 0x89, 0xFF, 0x53, 0x01, 0xF5, 0xFC, 0x63, 0x06, 0xE9, - 0xF1, 0x63, 0x37, 0x85, 0x28, 0x09, 0xF2, 0x27, 0x07, 0x35, 0xFC, - 0xDA, 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x0C, 0x00, 0xD1, - 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A, 0xFF, 0x2A, 0x02, 0x83, 0xF8, - 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7, 0x5D, 0x05, 0xD3, 0xFC, 0xB1, - 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x23, 0x00, - 0x73, 0xFF, 0x3F, 0x01, 0xD3, 0xFD, 0x4C, 0x03, 0x54, 0xFB, 0x1F, - 0x07, 0xBB, 0x48, 0x7D, 0x00, 0x33, 0xFE, 0xCF, 0x01, 0x98, 0xFE, - 0xE2, 0x00, 0x97, 0xFF, 0x19, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, - 0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B, - 0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5, - 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5E, 0xFF, - 0xA6, 0x01, 0x76, 0xFC, 0x01, 0x07, 0x7D, 0xF1, 0xAD, 0x30, 0xDC, - 0x2F, 0x7F, 0xF1, 0x0C, 0x07, 0x6C, 0xFC, 0xAD, 0x01, 0x5A, 0xFF, - 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C, - 0x00, 0x7B, 0xFE, 0x0C, 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A, - 0xCD, 0xF4, 0x4B, 0x06, 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35, - 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x93, 0xFF, 0xEC, 0x00, 0x83, 0xFE, - 0xF7, 0x01, 0xE8, 0xFD, 0x21, 0x01, 0xD2, 0x48, 0x64, 0x06, 0xA1, - 0xFB, 0x26, 0x03, 0xE7, 0xFD, 0x35, 0x01, 0x76, 0xFF, 0x22, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5, - 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8, - 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B, - 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x39, 0xFC, - 0x29, 0x07, 0xEF, 0xF1, 0x62, 0x29, 0xA5, 0x36, 0xD0, 0xF1, 0x7B, - 0x06, 0xE3, 0xFC, 0x5E, 0x01, 0x83, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, - 0x01, 0x00, 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84, - 0x05, 0xFD, 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06, - 0x37, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x12, - 0x00, 0xB5, 0xFF, 0x94, 0x00, 0x39, 0xFF, 0xA3, 0x00, 0x58, 0x00, - 0x02, 0xFC, 0x73, 0x47, 0x0B, 0x0D, 0x0B, 0xF9, 0x6C, 0x04, 0x45, - 0xFD, 0x80, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2A, 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, - 0xF9, 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, - 0x2E, 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFD, 0xFF, 0x36, - 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x39, 0xFC, 0xE4, 0x06, 0x21, 0xF3, - 0xC4, 0x21, 0xA5, 0x3C, 0x16, 0xF3, 0x72, 0x05, 0x9A, 0xFD, 0xEF, - 0x00, 0xBC, 0xFF, 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x1E, 0x00, - 0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46, - 0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01, - 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, 0xD6, 0xFF, 0x3F, - 0x00, 0xE7, 0xFF, 0x65, 0xFF, 0x85, 0x02, 0xDE, 0xF7, 0xA9, 0x44, - 0x43, 0x14, 0x99, 0xF6, 0x8B, 0x05, 0xBF, 0xFC, 0xBA, 0x01, 0x43, - 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF, - 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB, - 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00, - 0x91, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7, - 0x01, 0x72, 0xFC, 0x3F, 0x06, 0xEB, 0xF4, 0x12, 0x1A, 0xA1, 0x41, - 0x63, 0xF5, 0xF3, 0x03, 0x8A, 0xFE, 0x63, 0x00, 0x02, 0x00, 0xEE, - 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF, 0xB1, 0x01, - 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15, 0x31, 0x7C, - 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF, 0x29, 0x00, - 0xFD, 0xFF, 0x04, 0x00, 0xF4, 0xFF, 0xF1, 0xFF, 0x85, 0x00, 0x4E, - 0xFE, 0x56, 0x04, 0xC3, 0xF4, 0x95, 0x40, 0xD8, 0x1B, 0x76, 0xF4, - 0x6D, 0x06, 0x60, 0xFC, 0xDD, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, - 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB, 0x01, - 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB, 0x60, - 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAE, 0x01, 0xDB, 0xFC, 0x4D, - 0x05, 0x24, 0xF7, 0x8E, 0x12, 0x6D, 0x45, 0xBC, 0xF8, 0x0C, 0x02, - 0xAC, 0xFF, 0xC0, 0xFF, 0x52, 0x00, 0xCF, 0xFF, 0x0C, 0x00, 0xFD, - 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01, 0x34, 0xFC, 0x25, 0x07, - 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7, 0xF1, 0x56, 0x06, 0xFE, - 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x0D, 0x00, 0xAE, 0xFF, 0x0B, 0x01, 0x6A, 0xFD, 0xBA, 0x05, 0xB4, - 0xF2, 0x58, 0x3B, 0x8A, 0x23, 0xCB, 0xF2, 0xFD, 0x06, 0x34, 0xFC, - 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x10, 0x00, 0xBB, - 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00, 0xBE, 0x00, 0x38, 0xFB, - 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1, 0x04, 0x2B, 0xFD, 0x8B, - 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x29, 0x00, - 0x5F, 0xFF, 0x70, 0x01, 0x68, 0xFD, 0x23, 0x04, 0xA2, 0xF9, 0x73, - 0x0B, 0xE4, 0x47, 0x1B, 0xFD, 0xCD, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, - 0xA9, 0x00, 0xAE, 0xFF, 0x14, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, - 0xFF, 0xE6, 0x01, 0x3F, 0xFC, 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20, - 0x96, 0x3D, 0x69, 0xF3, 0x38, 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7, - 0xFF, 0x04, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x78, 0xFF, - 0x74, 0x01, 0xC2, 0xFC, 0xA7, 0x06, 0xA8, 0xF1, 0x25, 0x35, 0x1B, - 0x2B, 0xC2, 0xF1, 0x2A, 0x07, 0x41, 0xFC, 0xCE, 0x01, 0x47, 0xFF, - 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, - 0x00, 0x32, 0xFF, 0xDC, 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, - 0x34, 0xF6, 0xB7, 0x05, 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7E, 0xFF, 0x23, 0x01, - 0x0F, 0xFE, 0xD7, 0x02, 0x3B, 0xFC, 0xF5, 0x04, 0xED, 0x48, 0x70, - 0x02, 0x52, 0xFD, 0x46, 0x02, 0x5A, 0xFE, 0xFF, 0x00, 0x8B, 0xFF, - 0x1C, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81, - 0xFC, 0x1A, 0x06, 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5, - 0xA6, 0x03, 0xB9, 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07, - 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x53, 0xFF, 0xBB, 0x01, 0x5A, 0xFC, - 0x1C, 0x07, 0x8D, 0xF1, 0x34, 0x2E, 0x48, 0x32, 0x81, 0xF1, 0xE7, - 0x06, 0x8E, 0xFC, 0x96, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF, - 0x04, 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, - 0x04, 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, - 0x55, 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x17, - 0x00, 0x9F, 0xFF, 0xCE, 0x00, 0xC2, 0xFE, 0x80, 0x01, 0xC6, 0xFE, - 0x40, 0xFF, 0x81, 0x48, 0x9E, 0x08, 0xBA, 0xFA, 0x9A, 0x03, 0xAC, - 0xFD, 0x51, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x2F, 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F, - 0xF7, 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF, - 0xA2, 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0xFD, 0xFF, 0x35, - 0x00, 0x3D, 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1D, 0x07, 0x45, 0xF2, - 0xC6, 0x26, 0xD3, 0x38, 0x24, 0xF2, 0x2D, 0x06, 0x1B, 0xFD, 0x3B, - 0x01, 0x95, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x11, 0x00, - 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54, - 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01, - 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x0F, 0x00, 0xC1, 0xFF, 0x76, - 0x00, 0x76, 0xFF, 0x32, 0x00, 0x22, 0x01, 0x76, 0xFA, 0xA3, 0x46, - 0x7D, 0x0F, 0x2C, 0xF8, 0xD5, 0x04, 0x13, 0xFD, 0x96, 0x01, 0x51, - 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64, 0xFF, - 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A, 0x2C, - 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8, 0x00, - 0xA8, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, - 0x01, 0x47, 0xFC, 0xB5, 0x06, 0xB0, 0xF3, 0x19, 0x1F, 0x7E, 0x3E, - 0xC4, 0xF3, 0xFA, 0x04, 0xE7, 0xFD, 0xC1, 0x00, 0xD3, 0xFF, 0xFF, - 0xFF, 0x02, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF, 0x82, 0x01, - 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62, 0x2C, 0xA8, - 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF, 0x30, 0x00, - 0xFD, 0xFF, 0x08, 0x00, 0xE1, 0xFF, 0x23, 0x00, 0x20, 0x00, 0x00, - 0xFF, 0x31, 0x03, 0xAD, 0xF6, 0x65, 0x43, 0xDC, 0x16, 0xD1, 0xF5, - 0xE1, 0x05, 0x99, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14, 0x01, 0x2D, 0xFE, - 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48, 0x73, 0x03, 0xE0, - 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86, 0xFF, 0x1E, 0x00, - 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCC, 0x01, 0x91, 0xFC, 0xF3, - 0x05, 0xA6, 0xF5, 0x70, 0x17, 0x17, 0x43, 0x6D, 0xF6, 0x56, 0x03, - 0xEA, 0xFE, 0x2D, 0x00, 0x1D, 0x00, 0xE4, 0xFF, 0x08, 0x00, 0xFD, - 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07, - 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2, - 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x03, 0x00, - 0xFD, 0xFF, 0xD8, 0xFF, 0xB7, 0x00, 0xF9, 0xFD, 0xDE, 0x04, 0xEF, - 0xF3, 0xE4, 0x3E, 0x81, 0x1E, 0xD2, 0xF3, 0xA9, 0x06, 0x4B, 0xFC, - 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x16, 0x00, 0xA5, - 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45, 0x01, 0x33, 0xFF, 0x5A, 0xFE, - 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA, 0xD2, 0x03, 0x90, 0xFD, 0x5E, - 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2E, 0x00, - 0x4F, 0xFF, 0x9A, 0x01, 0x08, 0xFD, 0xEB, 0x04, 0xFC, 0xF7, 0x0A, - 0x10, 0x70, 0x46, 0x22, 0xFA, 0x4D, 0x01, 0x19, 0x00, 0x84, 0xFF, - 0x70, 0x00, 0xC4, 0xFF, 0x0F, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, - 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25, - 0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F, - 0xFF, 0x13, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x15, 0x00, 0x99, 0xFF, - 0x33, 0x01, 0x29, 0xFD, 0x1A, 0x06, 0x3B, 0xF2, 0x4B, 0x39, 0x30, - 0x26, 0x5B, 0xF2, 0x19, 0x07, 0x31, 0xFC, 0xE1, 0x01, 0x3C, 0xFF, - 0x35, 0x00, 0xFD, 0xFF, 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95, - 0xFF, 0xFA, 0xFF, 0x83, 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10, - 0xBF, 0xF7, 0x07, 0x05, 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x56, 0x01, - 0xA0, 0xFD, 0xB3, 0x03, 0x87, 0xFA, 0x1F, 0x09, 0x6A, 0x48, 0xD9, - 0xFE, 0xF6, 0xFE, 0x65, 0x01, 0xD0, 0xFE, 0xC7, 0x00, 0xA2, 0xFF, - 0x17, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50, - 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4, - 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03, - 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x69, 0xFF, 0x90, 0x01, 0x96, 0xFC, - 0xDD, 0x06, 0x85, 0xF1, 0xD0, 0x32, 0xA6, 0x2D, 0x94, 0xF1, 0x20, - 0x07, 0x54, 0xFC, 0xBF, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, - 0x07, 0x00, 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83, - 0x03, 0x20, 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06, - 0x88, 0xFC, 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0x1D, - 0x00, 0x89, 0xFF, 0x06, 0x01, 0x4C, 0xFE, 0x60, 0x02, 0x1F, 0xFD, - 0xE2, 0x02, 0xF3, 0x48, 0x7D, 0x04, 0x6E, 0xFC, 0xBD, 0x02, 0x1C, - 0xFE, 0x1C, 0x01, 0x80, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x33, 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, - 0xF6, 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, - 0x11, 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0xFD, 0xFF, 0x31, - 0x00, 0x49, 0xFF, 0xCB, 0x01, 0x45, 0xFC, 0x29, 0x07, 0xB6, 0xF1, - 0xAD, 0x2B, 0xA2, 0x34, 0x9E, 0xF1, 0xB4, 0x06, 0xB8, 0xFC, 0x7A, - 0x01, 0x75, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x02, 0x00, - 0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE, - 0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01, - 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x14, 0x00, 0xAB, 0xFF, 0xAF, - 0x00, 0x01, 0xFF, 0x0A, 0x01, 0x9E, 0xFF, 0x7C, 0xFD, 0x03, 0x48, - 0xED, 0x0A, 0xD5, 0xF9, 0x0A, 0x04, 0x74, 0xFD, 0x6A, 0x01, 0x62, - 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, - 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1, - 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00, - 0xBE, 0xFF, 0x10, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, - 0x01, 0x33, 0xFC, 0x04, 0x07, 0xB1, 0xF2, 0x21, 0x24, 0xE6, 0x3A, - 0x97, 0xF2, 0xD0, 0x05, 0x5B, 0xFD, 0x15, 0x01, 0xA9, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF, 0x45, 0x01, - 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80, 0x27, 0x2B, - 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF, 0x34, 0x00, - 0xFD, 0xFF, 0x0D, 0x00, 0xCD, 0xFF, 0x59, 0x00, 0xB3, 0xFF, 0xC4, - 0xFF, 0xE2, 0x01, 0x09, 0xF9, 0xAA, 0x45, 0xFE, 0x11, 0x54, 0xF7, - 0x38, 0x05, 0xE4, 0xFC, 0xAA, 0x01, 0x49, 0xFF, 0x30, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC, 0xFD, - 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF, 0x89, - 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18, 0x00, - 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5B, 0xFC, 0x7B, - 0x06, 0x50, 0xF4, 0x6E, 0x1C, 0x36, 0x40, 0x92, 0xF4, 0x75, 0x04, - 0x3B, 0xFE, 0x91, 0x00, 0xEB, 0xFF, 0xF6, 0xFF, 0x04, 0x00, 0xFD, - 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01, 0x84, 0xFC, 0xF3, 0x06, - 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85, 0xF1, 0x16, 0x07, 0x61, - 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x06, 0x00, - 0xEC, 0xFF, 0x08, 0x00, 0x57, 0x00, 0x9F, 0xFE, 0xD1, 0x03, 0x9B, - 0xF5, 0xF7, 0x41, 0x7C, 0x19, 0x13, 0xF5, 0x2F, 0x06, 0x78, 0xFC, - 0xD5, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x8F, - 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02, 0x91, 0xFD, 0xE3, 0x01, - 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8, 0x02, 0xFE, 0xFD, 0x2B, - 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x00, - 0x42, 0xFF, 0xBD, 0x01, 0xB6, 0xFC, 0x9F, 0x05, 0x6C, 0xF6, 0xD6, - 0x14, 0x65, 0x44, 0x98, 0xF7, 0xAC, 0x02, 0x4E, 0xFF, 0xF4, 0xFF, - 0x39, 0x00, 0xD9, 0xFF, 0x0A, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, - 0xFF, 0xD2, 0x01, 0x3D, 0xFC, 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A, - 0xC6, 0x35, 0xB7, 0xF1, 0x96, 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D, - 0xFF, 0x1F, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x06, 0x00, 0xC1, 0xFF, - 0xE5, 0x00, 0xAA, 0xFD, 0x58, 0x05, 0x3A, 0xF3, 0x11, 0x3D, 0x2C, - 0x21, 0x3F, 0xF3, 0xDA, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF, - 0x36, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, - 0xFF, 0xD0, 0x00, 0x07, 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, - 0x63, 0xF9, 0x42, 0x04, 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x85, 0x01, - 0x39, 0xFD, 0x84, 0x04, 0xD9, 0xF8, 0x95, 0x0D, 0x48, 0x47, 0xA7, - 0xFB, 0x86, 0x00, 0x8A, 0x00, 0x46, 0xFF, 0x8E, 0x00, 0xB8, 0xFF, - 0x11, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35, - 0xFC, 0xF3, 0x06, 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2, - 0x9C, 0x05, 0x7E, 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01, - 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x87, 0xFF, 0x57, 0x01, 0xEF, 0xFC, - 0x6B, 0x06, 0xE0, 0xF1, 0x23, 0x37, 0xCE, 0x28, 0x01, 0xF2, 0x28, - 0x07, 0x36, 0xFC, 0xD9, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, - 0x0B, 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, - 0x02, 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, - 0xCF, 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x23, 0x00, 0x74, 0xFF, 0x3C, 0x01, 0xDA, 0xFD, 0x40, 0x03, - 0x6E, 0xFB, 0xE1, 0x06, 0xC3, 0x48, 0xB3, 0x00, 0x1A, 0xFE, 0xDC, - 0x01, 0x91, 0xFE, 0xE5, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFE, 0xFF, - 0x36, 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6, - 0xF4, 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE, - 0x77, 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0xFD, 0xFF, 0x2A, - 0x00, 0x5C, 0xFF, 0xA8, 0x01, 0x73, 0xFC, 0x05, 0x07, 0x7D, 0xF1, - 0x67, 0x30, 0x21, 0x30, 0x7E, 0xF1, 0x08, 0x07, 0x6F, 0xFC, 0xAB, - 0x01, 0x5B, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x05, 0x00, 0xF0, 0xFF, - 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32, - 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01, - 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE8, - 0x00, 0x8A, 0xFE, 0xE9, 0x01, 0x01, 0xFE, 0xEA, 0x00, 0xCB, 0x48, - 0xA2, 0x06, 0x87, 0xFB, 0x33, 0x03, 0xE0, 0xFD, 0x39, 0x01, 0x75, - 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x45, 0xFF, - 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13, 0xFD, - 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47, 0x00, - 0xD3, 0xFF, 0x0B, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x42, 0xFF, 0xD8, - 0x01, 0x37, 0xFC, 0x29, 0x07, 0xF8, 0xF1, 0x19, 0x29, 0xE5, 0x36, - 0xD8, 0xF1, 0x73, 0x06, 0xE9, 0xFC, 0x5B, 0x01, 0x85, 0xFF, 0x1C, - 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF, 0xFB, 0x00, - 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81, 0x22, 0xFC, - 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, - 0xFD, 0xFF, 0x12, 0x00, 0xB7, 0xFF, 0x91, 0x00, 0x40, 0xFF, 0x96, - 0x00, 0x6F, 0x00, 0xD5, 0xFB, 0x5E, 0x47, 0x50, 0x0D, 0xF2, 0xF8, - 0x78, 0x04, 0x3F, 0xFD, 0x82, 0x01, 0x58, 0xFF, 0x2B, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79, 0x01, 0x53, 0xFD, - 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47, 0x76, 0xFC, 0x1F, - 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2, 0xFF, 0x13, 0x00, - 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xDF, - 0x06, 0x30, 0xF3, 0x78, 0x21, 0xDB, 0x3C, 0x28, 0xF3, 0x65, 0x05, - 0xA2, 0xFD, 0xEA, 0x00, 0xBE, 0xFF, 0x07, 0x00, 0x01, 0x00, 0xFE, - 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06, - 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C, - 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x0A, 0x00, - 0xD8, 0xFF, 0x3C, 0x00, 0xEE, 0xFF, 0x5A, 0xFF, 0x98, 0x02, 0xBB, - 0xF7, 0x87, 0x44, 0x8C, 0x14, 0x83, 0xF6, 0x95, 0x05, 0xBA, 0xFC, - 0xBB, 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x21, - 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7, 0xFD, 0x05, 0x03, 0xE1, 0xFB, - 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01, 0xAA, 0xFD, 0x18, 0x02, 0x72, - 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x35, 0x00, - 0x39, 0xFF, 0xD6, 0x01, 0x75, 0xFC, 0x37, 0x06, 0xFF, 0xF4, 0xC7, - 0x19, 0xCC, 0x41, 0x7F, 0xF5, 0xE2, 0x03, 0x95, 0xFE, 0x5D, 0x00, - 0x05, 0x00, 0xED, 0xFF, 0x06, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57, - 0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F, - 0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61, - 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x04, 0x00, 0xF5, 0xFF, 0xEE, 0xFF, - 0x8B, 0x00, 0x44, 0xFE, 0x65, 0x04, 0xAA, 0xF4, 0x66, 0x40, 0x23, - 0x1C, 0x63, 0xF4, 0x74, 0x06, 0x5D, 0xFC, 0xDE, 0x01, 0x37, 0xFF, - 0x36, 0x00, 0xFE, 0xFF, 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA, - 0xFE, 0xAE, 0x01, 0x70, 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07, - 0x14, 0xFB, 0x6D, 0x03, 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24, - 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAC, 0x01, - 0xDF, 0xFC, 0x43, 0x05, 0x3C, 0xF7, 0x46, 0x12, 0x8D, 0x45, 0xE2, - 0xF8, 0xF7, 0x01, 0xB8, 0xFF, 0xB9, 0xFF, 0x56, 0x00, 0xCE, 0xFF, - 0x0C, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34, - 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2, - 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF, - 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAB, 0xFF, 0x10, 0x01, 0x62, 0xFD, - 0xC5, 0x05, 0xA5, 0xF2, 0x1F, 0x3B, 0xD6, 0x23, 0xBE, 0xF2, 0x01, - 0x07, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, - 0x10, 0x00, 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4, - 0x00, 0x0C, 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04, - 0x26, 0xFD, 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6D, 0x01, 0x6E, 0xFD, 0x17, 0x04, - 0xBC, 0xF9, 0x30, 0x0B, 0xF4, 0x47, 0x4B, 0xFD, 0xB5, 0xFF, 0xFD, - 0x00, 0x08, 0xFF, 0xAC, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFD, 0xFF, - 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, - 0xF3, 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, - 0xD4, 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x21, - 0x00, 0x77, 0xFF, 0x77, 0x01, 0xBD, 0xFC, 0xAE, 0x06, 0xA3, 0xF1, - 0xE3, 0x34, 0x64, 0x2B, 0xBC, 0xF1, 0x2A, 0x07, 0x43, 0xFC, 0xCD, - 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x09, 0x00, 0xDD, 0xFF, - 0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7, - 0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01, - 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, - 0xFF, 0x20, 0x01, 0x16, 0xFE, 0xCA, 0x02, 0x54, 0xFC, 0xB9, 0x04, - 0xF2, 0x48, 0xA9, 0x02, 0x39, 0xFD, 0x53, 0x02, 0x53, 0xFE, 0x03, - 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, - 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89, - 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00, - 0xE8, 0xFF, 0x07, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBD, - 0x01, 0x57, 0xFC, 0x1E, 0x07, 0x90, 0xF1, 0xED, 0x2D, 0x8C, 0x32, - 0x83, 0xF1, 0xE2, 0x06, 0x92, 0xFC, 0x93, 0x01, 0x68, 0xFF, 0x26, - 0x00, 0xFD, 0xFF, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF, 0xA4, 0x00, - 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78, 0x1D, 0x10, - 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF, 0x36, 0x00, - 0xFE, 0xFF, 0x17, 0x00, 0xA0, 0xFF, 0xCA, 0x00, 0xC9, 0xFE, 0x73, - 0x01, 0xDE, 0xFE, 0x0C, 0xFF, 0x76, 0x48, 0xDE, 0x08, 0xA1, 0xFA, - 0xA6, 0x03, 0xA6, 0xFD, 0x53, 0x01, 0x6A, 0xFF, 0x26, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6, 0xFC, - 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9, 0x98, - 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E, 0x00, - 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x32, 0xFC, 0x1B, - 0x07, 0x50, 0xF2, 0x7B, 0x26, 0x11, 0x39, 0x2F, 0xF2, 0x23, 0x06, - 0x22, 0xFD, 0x37, 0x01, 0x97, 0xFF, 0x15, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01, 0x41, 0xFD, 0xF6, 0x05, - 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84, 0xF2, 0x0F, 0x07, 0x31, - 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x0F, 0x00, - 0xC2, 0xFF, 0x73, 0x00, 0x7D, 0xFF, 0x25, 0x00, 0x38, 0x01, 0x4C, - 0xFA, 0x89, 0x46, 0xC3, 0x0F, 0x14, 0xF8, 0xE0, 0x04, 0x0D, 0xFD, - 0x98, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x27, - 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD, 0xDF, 0x03, 0x2E, 0xFA, - 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B, 0xFF, 0x38, 0x01, 0xE9, - 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00, 0xFE, 0xFF, 0x36, 0x00, - 0x36, 0xFF, 0xE4, 0x01, 0x49, 0xFC, 0xAF, 0x06, 0xC1, 0xF3, 0xCD, - 0x1E, 0xB1, 0x3E, 0xD9, 0xF3, 0xEC, 0x04, 0xF0, 0xFD, 0xBC, 0x00, - 0xD5, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F, - 0xFF, 0x85, 0x01, 0xA6, 0xFC, 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33, - 0xAB, 0x2C, 0xA3, 0xF1, 0x26, 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D, - 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x08, 0x00, 0xE2, 0xFF, 0x20, 0x00, - 0x26, 0x00, 0xF5, 0xFE, 0x43, 0x03, 0x8D, 0xF6, 0x3C, 0x43, 0x25, - 0x17, 0xBB, 0xF5, 0xEA, 0x05, 0x95, 0xFC, 0xCA, 0x01, 0x3D, 0xFF, - 0x34, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, - 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, - 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, - 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, - 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED, 0x20, 0x3D, 0x3D, 0x4A, - 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00, 0xC3, 0xFF, 0x05, 0x00, - 0x02, 0x00, 0x02, 0x00, 0x05, 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, - 0xFD, 0x4E, 0x05, 0x4A, 0xF3, 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, - 0xD6, 0x06, 0x3D, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, - 0xFF, 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, - 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, - 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, - 0xFD, 0xFF, 0x30, 0x00, 0x4D, 0xFF, 0xC5, 0x01, 0x4C, 0xFC, 0x26, - 0x07, 0xA3, 0xF1, 0xAB, 0x2C, 0xBB, 0x33, 0x8F, 0xF1, 0xCA, 0x06, - 0xA6, 0xFC, 0x85, 0x01, 0x6F, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0x16, - 0x00, 0xA6, 0xFF, 0xBB, 0x00, 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF, - 0x28, 0xFE, 0x3A, 0x48, 0x04, 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A, - 0xFD, 0x60, 0x01, 0x65, 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF, - 0x35, 0x00, 0x3A, 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x0F, 0x07, 0x84, - 0xF2, 0x29, 0x25, 0x1A, 0x3A, 0x67, 0xF2, 0xF6, 0x05, 0x41, 0xFD, - 0x24, 0x01, 0xA1, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8, - 0xFF, 0x64, 0x00, 0x9B, 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9, - 0x10, 0x46, 0x03, 0x11, 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2, - 0x01, 0x4C, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, - 0x36, 0xFF, 0xE1, 0x01, 0x52, 0xFC, 0x93, 0x06, 0x10, 0xF4, 0x78, - 0x1D, 0x90, 0x3F, 0x3E, 0xF4, 0xAA, 0x04, 0x19, 0xFE, 0xA4, 0x00, - 0xE2, 0xFF, 0xFA, 0xFF, 0x03, 0x00, 0x07, 0x00, 0xE8, 0xFF, 0x12, - 0x00, 0x42, 0x00, 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, - 0x76, 0x18, 0x5C, 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, - 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, - 0xC3, 0x01, 0xA7, 0xFC, 0xC0, 0x05, 0x1E, 0xF6, 0xD8, 0x15, 0xE7, - 0x43, 0x20, 0xF7, 0xEF, 0x02, 0x27, 0xFF, 0x0A, 0x00, 0x2E, 0x00, - 0xDD, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, - 0x00, 0xC8, 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, - 0x76, 0xF3, 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, - 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x54, 0xFF, 0x8D, 0x01, - 0x26, 0xFD, 0xAD, 0x04, 0x82, 0xF8, 0x87, 0x0E, 0xF9, 0x46, 0x0C, - 0xFB, 0xD4, 0x00, 0x5D, 0x00, 0x5E, 0xFF, 0x82, 0x00, 0xBD, 0xFF, - 0x10, 0x00, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, - 0xFD, 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, - 0x23, 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, - 0xFF, 0x00, 0x00, 0x24, 0x00, 0x70, 0xFF, 0x46, 0x01, 0xC3, 0xFD, - 0x6D, 0x03, 0x14, 0xFB, 0xBE, 0x07, 0xA6, 0x48, 0xF8, 0xFF, 0x70, - 0xFE, 0xAE, 0x01, 0xAA, 0xFE, 0xD9, 0x00, 0x9A, 0xFF, 0x19, 0x00, - 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7, - 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07, - 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B, - 0x00, 0x90, 0xFF, 0xF4, 0x00, 0x72, 0xFE, 0x18, 0x02, 0xAA, 0xFD, - 0xAB, 0x01, 0xDF, 0x48, 0xCA, 0x05, 0xE1, 0xFB, 0x05, 0x03, 0xF7, - 0xFD, 0x2E, 0x01, 0x79, 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF, - 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07, 0xDC, - 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5, 0xFC, - 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xB2, - 0xFF, 0x9D, 0x00, 0x27, 0xFF, 0xC3, 0x00, 0x1F, 0x00, 0x76, 0xFC, - 0xA3, 0x47, 0x60, 0x0C, 0x4A, 0xF9, 0x4E, 0x04, 0x53, 0xFD, 0x79, - 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, - 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, 0xF2, 0x81, - 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, 0xFB, 0x00, - 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xD3, 0xFF, 0x47, - 0x00, 0xD7, 0xFF, 0x82, 0xFF, 0x53, 0x02, 0x39, 0xF8, 0xFD, 0x44, - 0x8D, 0x13, 0xD3, 0xF6, 0x72, 0x05, 0xCA, 0xFC, 0xB5, 0x01, 0x45, - 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x38, 0xFF, - 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, 0xCE, 0x1A, 0x32, - 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, 0x00, 0xFB, 0xFF, - 0xF0, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF2, 0xFF, 0xF8, 0xFF, 0x77, - 0x00, 0x67, 0xFE, 0x2D, 0x04, 0x04, 0xF5, 0x07, 0x41, 0x1B, 0x1B, - 0xA6, 0xF4, 0x5A, 0x06, 0x67, 0xFC, 0xDB, 0x01, 0x38, 0xFF, 0x36, - 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB3, 0x01, - 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44, 0x13, 0x1E, 0x45, 0x5E, - 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF, 0x4A, 0x00, 0xD2, 0xFF, - 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00, 0xB4, 0xFF, 0x00, 0x01, 0x7E, - 0xFD, 0x9C, 0x05, 0xDC, 0xF2, 0xE4, 0x3B, 0xCD, 0x22, 0xEE, 0xF2, - 0xF3, 0x06, 0x35, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, - 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5D, 0xFF, 0x76, 0x01, 0x59, 0xFD, - 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C, 0xB6, 0x47, 0xA4, 0xFC, 0x07, - 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0, 0x00, 0xB1, 0xFF, 0x13, 0x00, - 0xFE, 0xFF, 0x1F, 0x00, 0x7D, 0xFF, 0x6B, 0x01, 0xCF, 0xFC, 0x96, - 0x06, 0xB7, 0xF1, 0xC6, 0x35, 0x64, 0x2A, 0xD4, 0xF1, 0x2B, 0x07, - 0x3D, 0xFC, 0xD2, 0x01, 0x45, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, - 0x00, 0x21, 0x00, 0x7A, 0xFF, 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02, - 0xFB, 0xFB, 0x8D, 0x05, 0xE5, 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25, - 0x02, 0x6B, 0xFE, 0xF7, 0x00, 0x8F, 0xFF, 0x1C, 0x00, 0xFD, 0xFF, - 0x2D, 0x00, 0x55, 0xFF, 0xB5, 0x01, 0x61, 0xFC, 0x16, 0x07, 0x85, - 0xF1, 0xE6, 0x2E, 0x9E, 0x31, 0x7D, 0xF1, 0xF3, 0x06, 0x84, 0xFC, - 0x9D, 0x01, 0x63, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9C, - 0xFF, 0xD6, 0x00, 0xB1, 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF, - 0x9C, 0x48, 0xFD, 0x07, 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49, - 0x01, 0x6E, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, - 0x3E, 0xFF, 0xDE, 0x01, 0x33, 0xFC, 0x22, 0x07, 0x2B, 0xF2, 0x80, - 0x27, 0x3B, 0x38, 0x0A, 0xF2, 0x44, 0x06, 0x0B, 0xFD, 0x45, 0x01, - 0x90, 0xFF, 0x18, 0x00, 0xFF, 0xFF, 0x10, 0x00, 0xBE, 0xFF, 0x7F, - 0x00, 0x65, 0xFF, 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, - 0xCD, 0x0E, 0x6A, 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, - 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, - 0xE5, 0x01, 0x42, 0xFC, 0xC3, 0x06, 0x87, 0xF3, 0xD7, 0x1F, 0xFE, - 0x3D, 0x91, 0xF3, 0x1D, 0x05, 0xD1, 0xFD, 0xCE, 0x00, 0xCC, 0xFF, - 0x02, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, - 0x00, 0x1B, 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, - 0x07, 0xF6, 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, - 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCF, 0x01, - 0x88, 0xFC, 0x09, 0x06, 0x71, 0xF5, 0x2B, 0x18, 0xB2, 0x42, 0x20, - 0xF6, 0x83, 0x03, 0xCF, 0xFE, 0x3C, 0x00, 0x15, 0x00, 0xE6, 0xFF, - 0x07, 0x00, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, - 0xFE, 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, - 0x99, 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, - 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4D, 0xFF, 0xA0, 0x01, 0xFB, 0xFC, - 0x07, 0x05, 0xBF, 0xF7, 0xBB, 0x10, 0x2B, 0x46, 0xBB, 0xF9, 0x83, - 0x01, 0xFA, 0xFF, 0x95, 0xFF, 0x68, 0x00, 0xC7, 0xFF, 0x0E, 0x00, - 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00, - 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07, - 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, - 0x00, 0x27, 0x00, 0x66, 0xFF, 0x5E, 0x01, 0x90, 0xFD, 0xD2, 0x03, - 0x47, 0xFA, 0xC3, 0x09, 0x48, 0x48, 0x5A, 0xFE, 0x33, 0xFF, 0x45, - 0x01, 0xE2, 0xFE, 0xBE, 0x00, 0xA5, 0xFF, 0x16, 0x00, 0xFD, 0xFF, - 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06, 0x8C, - 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E, 0xFC, - 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x86, - 0xFF, 0x0E, 0x01, 0x3B, 0xFE, 0x82, 0x02, 0xE0, 0xFC, 0x73, 0x03, - 0xF6, 0x48, 0xE9, 0x03, 0xAD, 0xFC, 0x9C, 0x02, 0x2D, 0xFE, 0x14, - 0x01, 0x83, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00, - 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, 0xF1, 0x62, - 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, 0x82, 0x01, - 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0x15, 0x00, 0xA8, 0xFF, 0xB8, - 0x00, 0xF0, 0xFE, 0x2B, 0x01, 0x63, 0xFF, 0xF6, 0xFD, 0x2C, 0x48, - 0x47, 0x0A, 0x14, 0xFA, 0xEB, 0x03, 0x84, 0xFD, 0x63, 0x01, 0x64, - 0xFF, 0x27, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x3A, 0xFF, - 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, 0xDD, 0x24, 0x54, - 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, 0x01, 0xA3, 0xFF, - 0x11, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xC9, 0xFF, 0x61, 0x00, 0xA2, - 0xFF, 0xE2, 0xFF, 0xAE, 0x01, 0x6B, 0xF9, 0xF2, 0x45, 0x4A, 0x11, - 0x8F, 0xF7, 0x1D, 0x05, 0xF1, 0xFC, 0xA4, 0x01, 0x4B, 0xFF, 0x2F, - 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE1, 0x01, - 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C, 0x1D, 0xC0, 0x3F, 0x55, - 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00, 0xE4, 0xFF, 0xF9, 0xFF, - 0x04, 0x00, 0x07, 0x00, 0xE9, 0xFF, 0x0F, 0x00, 0x48, 0x00, 0xB9, - 0xFE, 0xA6, 0x03, 0xE4, 0xF5, 0x60, 0x42, 0xC1, 0x18, 0x47, 0xF5, - 0x1A, 0x06, 0x81, 0xFC, 0xD2, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFE, - 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x40, 0xFF, 0xC1, 0x01, 0xAB, 0xFC, - 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15, 0x0B, 0x44, 0x42, 0xF7, 0xDC, - 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31, 0x00, 0xDC, 0xFF, 0x09, 0x00, - 0x02, 0x00, 0x04, 0x00, 0xC7, 0xFF, 0xD9, 0x00, 0xBF, 0xFD, 0x38, - 0x05, 0x69, 0xF3, 0x96, 0x3D, 0x6F, 0x20, 0x66, 0xF3, 0xCE, 0x06, - 0x3F, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, - 0xFF, 0x2C, 0x00, 0x55, 0xFF, 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04, - 0x9B, 0xF8, 0x42, 0x0E, 0x0F, 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A, - 0x00, 0x58, 0xFF, 0x85, 0x00, 0xBB, 0xFF, 0x10, 0x00, 0xFF, 0xFF, - 0x19, 0x00, 0x8C, 0xFF, 0x4D, 0x01, 0xFE, 0xFC, 0x56, 0x06, 0xF7, - 0xF1, 0xBF, 0x37, 0x15, 0x28, 0x18, 0xF2, 0x25, 0x07, 0x34, 0xFC, - 0xDC, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24, - 0x00, 0x71, 0xFF, 0x43, 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB, - 0x7E, 0x07, 0xAF, 0x48, 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3, - 0xFE, 0xDD, 0x00, 0x99, 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00, - 0x60, 0xFF, 0xA2, 0x01, 0x7C, 0xFC, 0xFB, 0x06, 0x7C, 0xF1, 0x15, - 0x31, 0x73, 0x2F, 0x81, 0xF1, 0x10, 0x07, 0x67, 0xFC, 0xB1, 0x01, - 0x58, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0x1B, 0x00, 0x91, 0xFF, 0xF1, - 0x00, 0x79, 0xFE, 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, - 0x07, 0x06, 0xC7, 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, - 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x44, 0xFF, - 0xD5, 0x01, 0x3A, 0xFC, 0x2A, 0x07, 0xE3, 0xF1, 0xD1, 0x29, 0x46, - 0x36, 0xC5, 0xF1, 0x87, 0x06, 0xDA, 0xFC, 0x64, 0x01, 0x80, 0xFF, - 0x1E, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, - 0xFF, 0xB6, 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, - 0x31, 0xF9, 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, - 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, - 0x37, 0xFC, 0xEB, 0x06, 0x0B, 0xF3, 0x35, 0x22, 0x52, 0x3C, 0xFD, - 0xF2, 0x84, 0x05, 0x8D, 0xFD, 0xF6, 0x00, 0xB8, 0xFF, 0x09, 0x00, - 0x01, 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, - 0xFF, 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, - 0x7C, 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, - 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD9, 0x01, 0x6D, 0xFC, - 0x4B, 0x06, 0xCD, 0xF4, 0x83, 0x1A, 0x5F, 0x41, 0x3A, 0xF5, 0x0C, - 0x04, 0x7B, 0xFE, 0x6C, 0x00, 0xFE, 0xFF, 0xEF, 0xFF, 0x05, 0x00, - 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E, - 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06, - 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, - 0xFF, 0x31, 0x00, 0x46, 0xFF, 0xB1, 0x01, 0xD3, 0xFC, 0x5D, 0x05, - 0x01, 0xF7, 0xFB, 0x12, 0x3F, 0x45, 0x83, 0xF8, 0x2A, 0x02, 0x9A, - 0xFF, 0xCA, 0xFF, 0x4E, 0x00, 0xD1, 0xFF, 0x0C, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05, 0xCC, - 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35, 0xFC, - 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29, - 0x00, 0x5E, 0xFF, 0x74, 0x01, 0x5F, 0xFD, 0x35, 0x04, 0x7C, 0xF9, - 0xD8, 0x0B, 0xC9, 0x47, 0xD4, 0xFC, 0xF0, 0xFF, 0xDD, 0x00, 0x19, - 0xFF, 0xA4, 0x00, 0xAF, 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x20, 0x00, - 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, 0xF1, 0x86, - 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, 0xD1, 0x01, - 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x7C, - 0xFF, 0x27, 0x01, 0x05, 0xFE, 0xEB, 0x02, 0x14, 0xFC, 0x50, 0x05, - 0xEA, 0x48, 0x1B, 0x02, 0x78, 0xFD, 0x32, 0x02, 0x64, 0xFE, 0xFA, - 0x00, 0x8D, 0xFF, 0x1C, 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x54, 0xFF, - 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, 0x9F, 0x2E, 0xE3, - 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, 0x01, 0x64, 0xFF, - 0x28, 0x00, 0xFD, 0xFF, 0x18, 0x00, 0x9D, 0xFF, 0xD3, 0x00, 0xB8, - 0xFE, 0x93, 0x01, 0xA1, 0xFE, 0x8E, 0xFF, 0x92, 0x48, 0x3D, 0x08, - 0xE1, 0xFA, 0x86, 0x03, 0xB6, 0xFD, 0x4C, 0x01, 0x6D, 0xFF, 0x25, - 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3E, 0xFF, 0xDF, 0x01, - 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36, 0x27, 0x78, 0x38, 0x14, - 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01, 0x92, 0xFF, 0x17, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0xBF, 0xFF, 0x7B, 0x00, 0x6C, 0xFF, 0x44, - 0x00, 0x01, 0x01, 0xB6, 0xFA, 0xC8, 0x46, 0x13, 0x0F, 0x51, 0xF8, - 0xC4, 0x04, 0x1B, 0xFD, 0x92, 0x01, 0x52, 0xFF, 0x2D, 0x00, 0xFF, - 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x44, 0xFC, - 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F, 0x31, 0x3E, 0xA5, 0xF3, 0x0F, - 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF, 0xFF, 0x01, 0x00, 0x02, 0x00, - 0x09, 0x00, 0xDF, 0xFF, 0x28, 0x00, 0x17, 0x00, 0x10, 0xFF, 0x15, - 0x03, 0xDD, 0xF6, 0x9E, 0x43, 0x6C, 0x16, 0xF1, 0xF5, 0xD3, 0x05, - 0x9F, 0xFC, 0xC6, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, - 0xFF, 0x34, 0x00, 0x3C, 0xFF, 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06, - 0x86, 0xF5, 0xE0, 0x17, 0xDB, 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9, - 0xFE, 0x36, 0x00, 0x18, 0x00, 0xE5, 0xFF, 0x07, 0x00, 0x03, 0x00, - 0xFC, 0xFF, 0xDC, 0xFF, 0xAF, 0x00, 0x07, 0xFE, 0xC8, 0x04, 0x10, - 0xF4, 0x2D, 0x3F, 0x0F, 0x1E, 0xED, 0xF3, 0xA0, 0x06, 0x4E, 0xFC, - 0xE3, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, - 0x00, 0x4E, 0xFF, 0x9E, 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7, - 0x75, 0x10, 0x48, 0x46, 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E, - 0xFF, 0x6B, 0x00, 0xC6, 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x13, 0x00, - 0x9D, 0xFF, 0x2D, 0x01, 0x33, 0xFD, 0x0B, 0x06, 0x4D, 0xF2, 0xA5, - 0x39, 0xBF, 0x25, 0x6D, 0xF2, 0x15, 0x07, 0x31, 0xFC, 0xE2, 0x01, - 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x68, - 0xFF, 0x5B, 0x01, 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, - 0x57, 0x48, 0x8D, 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, - 0x00, 0xA4, 0xFF, 0x16, 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6C, 0xFF, - 0x8B, 0x01, 0x9D, 0xFC, 0xD5, 0x06, 0x89, 0xF1, 0x35, 0x33, 0x3A, - 0x2D, 0x9A, 0xF1, 0x23, 0x07, 0x51, 0xFC, 0xC2, 0x01, 0x4F, 0xFF, - 0x2F, 0x00, 0xFD, 0xFF, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, - 0xFE, 0x74, 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, - 0x94, 0xFC, 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, - 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x30, 0x00, 0x4B, 0xFF, 0xC9, 0x01, - 0x48, 0xFC, 0x28, 0x07, 0xAD, 0xF1, 0x19, 0x2C, 0x3F, 0x34, 0x97, - 0xF1, 0xBE, 0x06, 0xB0, 0xFC, 0x7F, 0x01, 0x72, 0xFF, 0x23, 0x00, - 0xFE, 0xFF, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, - 0x01, 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, - 0xF8, 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, - 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE4, 0x01, 0x32, 0xFC, - 0x09, 0x07, 0x9D, 0xF2, 0x92, 0x24, 0x8F, 0x3A, 0x82, 0xF2, 0xE1, - 0x05, 0x50, 0xFD, 0x1B, 0x01, 0xA6, 0xFF, 0x10, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3, - 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05, - 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE, - 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE0, 0x01, 0x57, 0xFC, 0x85, 0x06, - 0x34, 0xF4, 0xE0, 0x1C, 0xF0, 0x3F, 0x6D, 0xF4, 0x8C, 0x04, 0x2C, - 0xFE, 0x99, 0x00, 0xE7, 0xFF, 0xF8, 0xFF, 0x04, 0x00, 0x06, 0x00, - 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03, 0xC7, - 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D, 0xFC, - 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, - 0x00, 0x41, 0xFF, 0xC0, 0x01, 0xAF, 0xFC, 0xAD, 0x05, 0x4A, 0xF6, - 0x44, 0x15, 0x2F, 0x44, 0x64, 0xF7, 0xC9, 0x02, 0x3D, 0xFF, 0xFE, - 0xFF, 0x34, 0x00, 0xDB, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x05, 0x00, - 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, 0xF3, 0x61, - 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, 0xE6, 0x01, - 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x56, - 0xFF, 0x88, 0x01, 0x31, 0xFD, 0x95, 0x04, 0xB4, 0xF8, 0xFC, 0x0D, - 0x26, 0x47, 0x64, 0xFB, 0xA7, 0x00, 0x77, 0x00, 0x51, 0xFF, 0x89, - 0x00, 0xBA, 0xFF, 0x11, 0x00, 0xFF, 0xFF, 0x1A, 0x00, 0x8A, 0xFF, - 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, 0x82, 0x37, 0x60, - 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, 0x01, 0x40, 0xFF, - 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00, 0x72, 0xFF, 0x40, - 0x01, 0xD0, 0xFD, 0x53, 0x03, 0x47, 0xFB, 0x3F, 0x07, 0xB8, 0x48, - 0x62, 0x00, 0x3F, 0xFE, 0xC8, 0x01, 0x9C, 0xFE, 0xE0, 0x00, 0x98, - 0xFF, 0x19, 0x00, 0xFD, 0xFF, 0x29, 0x00, 0x5F, 0xFF, 0xA5, 0x01, - 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF, 0x30, 0xB8, 0x2F, 0x80, - 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01, 0x59, 0xFF, 0x2B, 0x00, - 0xFD, 0xFF, 0x1B, 0x00, 0x93, 0xFF, 0xED, 0x00, 0x80, 0xFE, 0xFD, - 0x01, 0xDC, 0xFD, 0x3C, 0x01, 0xD5, 0x48, 0x45, 0x06, 0xAE, 0xFB, - 0x1F, 0x03, 0xEA, 0xFD, 0x34, 0x01, 0x77, 0xFF, 0x22, 0x00, 0x00, - 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x43, 0xFF, 0xD6, 0x01, 0x39, 0xFC, - 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29, 0x85, 0x36, 0xCC, 0xF1, 0x7F, - 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82, 0xFF, 0x1D, 0x00, 0xFE, 0xFF, - 0x12, 0x00, 0xB5, 0xFF, 0x96, 0x00, 0x35, 0xFF, 0xA9, 0x00, 0x4D, - 0x00, 0x19, 0xFC, 0x7C, 0x47, 0xE8, 0x0C, 0x18, 0xF9, 0x66, 0x04, - 0x48, 0xFD, 0x7E, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, - 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06, - 0x19, 0xF3, 0xEA, 0x21, 0x8A, 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96, - 0xFD, 0xF1, 0x00, 0xBB, 0xFF, 0x08, 0x00, 0x01, 0x00, 0x0B, 0x00, - 0xD6, 0xFF, 0x41, 0x00, 0xE4, 0xFF, 0x6B, 0xFF, 0x7B, 0x02, 0xF0, - 0xF7, 0xBA, 0x44, 0x1E, 0x14, 0xA5, 0xF6, 0x86, 0x05, 0xC1, 0xFC, - 0xB9, 0x01, 0x44, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, - 0x00, 0x39, 0xFF, 0xD8, 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4, - 0x38, 0x1A, 0x8C, 0x41, 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66, - 0x00, 0x01, 0x00, 0xEE, 0xFF, 0x06, 0x00, 0x05, 0x00, 0xF4, 0xFF, - 0xF2, 0xFF, 0x83, 0x00, 0x53, 0xFE, 0x4E, 0x04, 0xD0, 0xF4, 0xAB, - 0x40, 0xB2, 0x1B, 0x7F, 0xF4, 0x69, 0x06, 0x62, 0xFC, 0xDD, 0x01, - 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x47, - 0xFF, 0xAF, 0x01, 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, - 0x5C, 0x45, 0xA9, 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, - 0x00, 0xD0, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xAF, 0xFF, - 0x09, 0x01, 0x6E, 0xFD, 0xB4, 0x05, 0xBC, 0xF2, 0x73, 0x3B, 0x64, - 0x23, 0xD2, 0xF2, 0xFB, 0x06, 0x34, 0xFC, 0xE6, 0x01, 0x38, 0xFF, - 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, - 0x01, 0x65, 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, - 0x03, 0xFD, 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, - 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x20, 0x00, 0x79, 0xFF, 0x72, 0x01, - 0xC4, 0xFC, 0xA4, 0x06, 0xAB, 0xF1, 0x46, 0x35, 0xF7, 0x2A, 0xC6, - 0xF1, 0x2A, 0x07, 0x40, 0xFC, 0xCF, 0x01, 0x47, 0xFF, 0x31, 0x00, - 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, - 0xFE, 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, - 0x5E, 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, - 0x00, 0xFD, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0xBA, 0x01, 0x5B, 0xFC, - 0x1B, 0x07, 0x8B, 0xF1, 0x58, 0x2E, 0x26, 0x32, 0x80, 0xF1, 0xEA, - 0x06, 0x8C, 0xFC, 0x97, 0x01, 0x66, 0xFF, 0x27, 0x00, 0xFD, 0xFF, - 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA, - 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03, - 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD, - 0xFF, 0x35, 0x00, 0x3D, 0xFF, 0xDF, 0x01, 0x32, 0xFC, 0x1E, 0x07, - 0x40, 0xF2, 0xEB, 0x26, 0xB5, 0x38, 0x1F, 0xF2, 0x32, 0x06, 0x18, - 0xFD, 0x3D, 0x01, 0x94, 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00, - 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01, 0x8B, - 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15, 0xFD, - 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, - 0x00, 0x36, 0xFF, 0xE5, 0x01, 0x46, 0xFC, 0xB8, 0x06, 0xA8, 0xF3, - 0x3F, 0x1F, 0x64, 0x3E, 0xBA, 0xF3, 0x01, 0x05, 0xE2, 0xFD, 0xC4, - 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0xE1, 0xFF, - 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, 0xF6, 0x77, - 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, 0xC8, 0x01, - 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D, - 0xFF, 0xCC, 0x01, 0x8F, 0xFC, 0xF8, 0x05, 0x9B, 0xF5, 0x96, 0x17, - 0x02, 0x43, 0x5E, 0xF6, 0x5F, 0x03, 0xE4, 0xFE, 0x30, 0x00, 0x1B, - 0x00, 0xE4, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFD, 0xFF, 0xD9, 0xFF, - 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, 0xFC, 0x3E, 0x5B, - 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, 0x01, 0x36, 0xFF, - 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9C, - 0x01, 0x05, 0xFD, 0xF1, 0x04, 0xF0, 0xF7, 0x2D, 0x10, 0x61, 0x46, - 0x0D, 0xFA, 0x58, 0x01, 0x13, 0x00, 0x87, 0xFF, 0x6E, 0x00, 0xC4, - 0xFF, 0x0E, 0x00, 0xFF, 0xFF, 0x14, 0x00, 0x9B, 0xFF, 0x31, 0x01, - 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A, 0x39, 0x0A, 0x26, 0x61, - 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01, 0x3B, 0xFF, 0x35, 0x00, - 0xFD, 0xFF, 0x00, 0x00, 0x26, 0x00, 0x69, 0xFF, 0x58, 0x01, 0x9D, - 0xFD, 0xB9, 0x03, 0x7B, 0xFA, 0x40, 0x09, 0x63, 0x48, 0xBF, 0xFE, - 0x03, 0xFF, 0x5F, 0x01, 0xD4, 0xFE, 0xC5, 0x00, 0xA2, 0xFF, 0x16, - 0x00, 0xFD, 0xFF, 0x25, 0x00, 0x6A, 0xFF, 0x8E, 0x01, 0x99, 0xFC, - 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32, 0x82, 0x2D, 0x96, 0xF1, 0x21, - 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, - 0x1D, 0x00, 0x88, 0xFF, 0x07, 0x01, 0x49, 0xFE, 0x67, 0x02, 0x13, - 0xFD, 0xFF, 0x02, 0xF4, 0x48, 0x5F, 0x04, 0x7A, 0xFC, 0xB6, 0x02, - 0x20, 0xFE, 0x1B, 0x01, 0x81, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFD, - 0xFF, 0x30, 0x00, 0x4A, 0xFF, 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07, - 0xB3, 0xF1, 0xD1, 0x2B, 0x81, 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5, - 0xFC, 0x7C, 0x01, 0x74, 0xFF, 0x22, 0x00, 0xFE, 0xFF, 0x15, 0x00, - 0xAA, 0xFF, 0xB1, 0x00, 0xFE, 0xFE, 0x10, 0x01, 0x92, 0xFF, 0x94, - 0xFD, 0x0D, 0x48, 0xCB, 0x0A, 0xE2, 0xF9, 0x04, 0x04, 0x77, 0xFD, - 0x69, 0x01, 0x62, 0xFF, 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, - 0x00, 0x39, 0xFF, 0xE5, 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2, - 0x46, 0x24, 0xC8, 0x3A, 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17, - 0x01, 0xA8, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0xCC, 0xFF, - 0x5A, 0x00, 0xAF, 0xFF, 0xCA, 0xFF, 0xD8, 0x01, 0x1C, 0xF9, 0xB8, - 0x45, 0xDA, 0x11, 0x60, 0xF7, 0x33, 0x05, 0xE7, 0xFC, 0xA9, 0x01, - 0x4A, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, - 0xFF, 0xDF, 0x01, 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, - 0x1F, 0x40, 0x85, 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, - 0xFF, 0xF7, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xEB, 0xFF, 0x09, 0x00, - 0x54, 0x00, 0xA4, 0xFE, 0xC9, 0x03, 0xAA, 0xF5, 0x0C, 0x42, 0x56, - 0x19, 0x1E, 0xF5, 0x2B, 0x06, 0x7A, 0xFC, 0xD4, 0x01, 0x3A, 0xFF, - 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, - 0x01, 0xB4, 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, - 0x86, 0xF7, 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, - 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x06, 0x00, 0xC2, 0xFF, 0xE3, 0x00, - 0xAE, 0xFD, 0x52, 0x05, 0x44, 0xF3, 0x2A, 0x3D, 0x06, 0x21, 0x47, - 0xF3, 0xD8, 0x06, 0x3C, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, - 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, - 0xFD, 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, - 0x91, 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, - 0x00, 0xFE, 0xFF, 0x1B, 0x00, 0x88, 0xFF, 0x55, 0x01, 0xF2, 0xFC, - 0x67, 0x06, 0xE4, 0xF1, 0x44, 0x37, 0xAA, 0x28, 0x05, 0xF2, 0x27, - 0x07, 0x36, 0xFC, 0xDA, 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, - 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46, - 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE, - 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0xFD, - 0xFF, 0x2A, 0x00, 0x5D, 0xFF, 0xA7, 0x01, 0x75, 0xFC, 0x03, 0x07, - 0x7D, 0xF1, 0x8A, 0x30, 0xFF, 0x2F, 0x7E, 0xF1, 0x0A, 0x07, 0x6E, - 0xFC, 0xAC, 0x01, 0x5A, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0x1A, 0x00, - 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD, 0x05, - 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4, 0xFD, - 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33, - 0x00, 0x42, 0xFF, 0xD7, 0x01, 0x38, 0xFC, 0x29, 0x07, 0xF3, 0xF1, - 0x3E, 0x29, 0xC6, 0x36, 0xD4, 0xF1, 0x77, 0x06, 0xE6, 0xFC, 0x5C, - 0x01, 0x84, 0xFF, 0x1C, 0x00, 0xFE, 0xFF, 0x12, 0x00, 0xB6, 0xFF, - 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, 0xFB, 0x69, - 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, 0x81, 0x01, - 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x37, - 0xFF, 0xE6, 0x01, 0x3A, 0xFC, 0xE2, 0x06, 0x28, 0xF3, 0x9E, 0x21, - 0xC0, 0x3C, 0x1F, 0xF3, 0x6C, 0x05, 0x9E, 0xFD, 0xED, 0x00, 0xBD, - 0xFF, 0x07, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD7, 0xFF, 0x3E, 0x00, - 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, 0x99, 0x44, 0x68, - 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, 0x01, 0x43, 0xFF, - 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD7, - 0x01, 0x73, 0xFC, 0x3B, 0x06, 0xF5, 0xF4, 0xED, 0x19, 0xB7, 0x41, - 0x71, 0xF5, 0xEB, 0x03, 0x90, 0xFE, 0x60, 0x00, 0x04, 0x00, 0xED, - 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF5, 0xFF, 0xEF, 0xFF, 0x88, 0x00, - 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D, 0x40, 0xFD, 0x1B, 0x6C, - 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01, 0x37, 0xFF, 0x36, 0x00, - 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x48, 0xFF, 0xAD, 0x01, 0xDD, - 0xFC, 0x48, 0x05, 0x30, 0xF7, 0x6B, 0x12, 0x7D, 0x45, 0xCF, 0xF8, - 0x01, 0x02, 0xB2, 0xFF, 0xBD, 0xFF, 0x54, 0x00, 0xCE, 0xFF, 0x0C, - 0x00, 0x00, 0x00, 0x0E, 0x00, 0xAC, 0xFF, 0x0E, 0x01, 0x66, 0xFD, - 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B, 0xB0, 0x23, 0xC4, 0xF2, 0xFF, - 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, - 0x00, 0x00, 0x29, 0x00, 0x60, 0xFF, 0x6E, 0x01, 0x6B, 0xFD, 0x1D, - 0x04, 0xAF, 0xF9, 0x51, 0x0B, 0xEC, 0x47, 0x33, 0xFD, 0xC1, 0xFF, - 0xF7, 0x00, 0x0C, 0xFF, 0xAA, 0x00, 0xAD, 0xFF, 0x14, 0x00, 0xFE, - 0xFF, 0x21, 0x00, 0x77, 0xFF, 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06, - 0xA6, 0xF1, 0x05, 0x35, 0x40, 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42, - 0xFC, 0xCE, 0x01, 0x48, 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00, - 0x20, 0x00, 0x7E, 0xFF, 0x21, 0x01, 0x12, 0xFE, 0xD1, 0x02, 0x47, - 0xFC, 0xD7, 0x04, 0xF0, 0x48, 0x8D, 0x02, 0x45, 0xFD, 0x4D, 0x02, - 0x56, 0xFE, 0x01, 0x01, 0x8B, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E, - 0x00, 0x52, 0xFF, 0xBC, 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1, - 0x11, 0x2E, 0x6B, 0x32, 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94, - 0x01, 0x67, 0xFF, 0x26, 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA0, 0xFF, - 0xCC, 0x00, 0xC6, 0xFE, 0x79, 0x01, 0xD2, 0xFE, 0x26, 0xFF, 0x7C, - 0x48, 0xBE, 0x08, 0xAE, 0xFA, 0xA0, 0x03, 0xA9, 0xFD, 0x52, 0x01, - 0x6B, 0xFF, 0x25, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, - 0xFF, 0xE0, 0x01, 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, - 0xF2, 0x38, 0x2A, 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, - 0xFF, 0x16, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xC2, 0xFF, 0x75, 0x00, - 0x7A, 0xFF, 0x2B, 0x00, 0x2D, 0x01, 0x61, 0xFA, 0x97, 0x46, 0xA0, - 0x0F, 0x20, 0xF8, 0xDA, 0x04, 0x10, 0xFD, 0x97, 0x01, 0x50, 0xFF, - 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, - 0x01, 0x48, 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, - 0xCF, 0xF3, 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, - 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE2, 0xFF, 0x21, 0x00, 0x23, 0x00, - 0xFA, 0xFE, 0x3A, 0x03, 0x9D, 0xF6, 0x50, 0x43, 0x00, 0x17, 0xC6, - 0xF5, 0xE6, 0x05, 0x97, 0xFC, 0xC9, 0x01, 0x3E, 0xFF, 0x34, 0x00, - 0xFE, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, - 0xFC, 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, - 0x4D, 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, - 0x00, 0x03, 0x00, 0xFE, 0xFF, 0xD7, 0xFF, 0xBA, 0x00, 0xF4, 0xFD, - 0xE5, 0x04, 0xE4, 0xF3, 0xCA, 0x3E, 0xA7, 0x1E, 0xCA, 0xF3, 0xAC, - 0x06, 0x4A, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, - 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6, - 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01, - 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0xFF, - 0xFF, 0x15, 0x00, 0x98, 0xFF, 0x35, 0x01, 0x25, 0xFD, 0x1E, 0x06, - 0x35, 0xF2, 0x2E, 0x39, 0x55, 0x26, 0x56, 0xF2, 0x1A, 0x07, 0x31, - 0xFC, 0xE1, 0x01, 0x3C, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, - 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03, 0x94, - 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C, 0x01, - 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26, - 0x00, 0x69, 0xFF, 0x91, 0x01, 0x94, 0xFC, 0xE0, 0x06, 0x84, 0xF1, - 0xAF, 0x32, 0xCA, 0x2D, 0x92, 0xF1, 0x1F, 0x07, 0x56, 0xFC, 0xBE, - 0x01, 0x51, 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8A, 0xFF, - 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, 0x02, 0xF2, - 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, 0x1E, 0x01, - 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x49, - 0xFF, 0xCC, 0x01, 0x44, 0xFC, 0x29, 0x07, 0xB9, 0xF1, 0x89, 0x2B, - 0xC3, 0x34, 0xA0, 0xF1, 0xB1, 0x06, 0xBA, 0xFC, 0x79, 0x01, 0x76, - 0xFF, 0x21, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAC, 0xFF, 0xAE, 0x00, - 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, 0xFD, 0x47, 0x0E, - 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, 0x01, 0x61, 0xFF, - 0x28, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, - 0x01, 0x33, 0xFC, 0x03, 0x07, 0xB7, 0xF2, 0xFC, 0x23, 0x03, 0x3B, - 0x9E, 0xF2, 0xCB, 0x05, 0x5F, 0xFD, 0x12, 0x01, 0xAA, 0xFF, 0x0E, - 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF, 0x57, 0x00, 0xB6, 0xFF, - 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B, 0x45, 0x22, 0x12, 0x48, - 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01, 0x49, 0xFF, 0x30, 0x00, - 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, 0x5C, - 0xFC, 0x78, 0x06, 0x5A, 0xF4, 0x49, 0x1C, 0x4E, 0x40, 0x9E, 0xF4, - 0x6D, 0x04, 0x3F, 0xFE, 0x8E, 0x00, 0xED, 0xFF, 0xF6, 0xFF, 0x04, - 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x5A, 0x00, 0x9A, 0xFE, - 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41, 0xA1, 0x19, 0x09, 0xF5, 0x33, - 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, - 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBC, 0x01, 0xB8, 0xFC, 0x9A, - 0x05, 0x77, 0xF6, 0xB1, 0x14, 0x77, 0x44, 0xA9, 0xF7, 0xA2, 0x02, - 0x54, 0xFF, 0xF1, 0xFF, 0x3A, 0x00, 0xD8, 0xFF, 0x0A, 0x00, 0x01, - 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05, - 0x31, 0xF3, 0xF6, 0x3C, 0x52, 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B, - 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, - 0x2B, 0x00, 0x58, 0xFF, 0x83, 0x01, 0x3C, 0xFD, 0x7E, 0x04, 0xE6, - 0xF8, 0x72, 0x0D, 0x52, 0x47, 0xBE, 0xFB, 0x7A, 0x00, 0x90, 0x00, - 0x43, 0xFF, 0x8F, 0x00, 0xB7, 0xFF, 0x11, 0x00, 0xFE, 0xFF, 0x1C, - 0x00, 0x86, 0xFF, 0x59, 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1, - 0x04, 0x37, 0xF3, 0x28, 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8, - 0x01, 0x41, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x23, 0x00, - 0x74, 0xFF, 0x3A, 0x01, 0xDD, 0xFD, 0x39, 0x03, 0x7B, 0xFB, 0xC1, - 0x06, 0xC7, 0x48, 0xCF, 0x00, 0x0D, 0xFE, 0xE3, 0x01, 0x8E, 0xFE, - 0xE7, 0x00, 0x95, 0xFF, 0x1A, 0x00, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, - 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, - 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, - 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x1A, 0x00, 0x95, 0xFF, 0xE7, 0x00, - 0x8E, 0xFE, 0xE3, 0x01, 0x0D, 0xFE, 0xCF, 0x00, 0xC7, 0x48, 0xC1, - 0x06, 0x7B, 0xFB, 0x39, 0x03, 0xDD, 0xFD, 0x3A, 0x01, 0x74, 0xFF, - 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, - 0x01, 0x37, 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, - 0xDC, 0xF1, 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, - 0x00, 0xFE, 0xFF, 0x11, 0x00, 0xB7, 0xFF, 0x8F, 0x00, 0x43, 0xFF, - 0x90, 0x00, 0x7A, 0x00, 0xBE, 0xFB, 0x52, 0x47, 0x72, 0x0D, 0xE6, - 0xF8, 0x7E, 0x04, 0x3C, 0xFD, 0x83, 0x01, 0x58, 0xFF, 0x2B, 0x00, - 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, - 0xFC, 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, - 0x5F, 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, - 0x00, 0x0A, 0x00, 0xD8, 0xFF, 0x3A, 0x00, 0xF1, 0xFF, 0x54, 0xFF, - 0xA2, 0x02, 0xA9, 0xF7, 0x77, 0x44, 0xB1, 0x14, 0x77, 0xF6, 0x9A, - 0x05, 0xB8, 0xFC, 0xBC, 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, - 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33, - 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03, - 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0x04, - 0x00, 0xF6, 0xFF, 0xED, 0xFF, 0x8E, 0x00, 0x3F, 0xFE, 0x6D, 0x04, - 0x9E, 0xF4, 0x4E, 0x40, 0x49, 0x1C, 0x5A, 0xF4, 0x78, 0x06, 0x5C, - 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, - 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05, 0x48, - 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE, 0xFF, - 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x0E, - 0x00, 0xAA, 0xFF, 0x12, 0x01, 0x5F, 0xFD, 0xCB, 0x05, 0x9E, 0xF2, - 0x03, 0x3B, 0xFC, 0x23, 0xB7, 0xF2, 0x03, 0x07, 0x33, 0xFC, 0xE5, - 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00, - 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, 0xF9, 0x0E, - 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, 0x05, 0xFF, - 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0xFE, 0xFF, 0x21, 0x00, 0x76, - 0xFF, 0x79, 0x01, 0xBA, 0xFC, 0xB1, 0x06, 0xA0, 0xF1, 0xC3, 0x34, - 0x89, 0x2B, 0xB9, 0xF1, 0x29, 0x07, 0x44, 0xFC, 0xCC, 0x01, 0x49, - 0xFF, 0x31, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x20, 0x00, 0x7F, 0xFF, - 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, 0x9B, 0x04, 0xF2, - 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, 0xFE, 0x04, 0x01, - 0x8A, 0xFF, 0x1D, 0x00, 0xFD, 0xFF, 0x2E, 0x00, 0x51, 0xFF, 0xBE, - 0x01, 0x56, 0xFC, 0x1F, 0x07, 0x92, 0xF1, 0xCA, 0x2D, 0xAF, 0x32, - 0x84, 0xF1, 0xE0, 0x06, 0x94, 0xFC, 0x91, 0x01, 0x69, 0xFF, 0x26, - 0x00, 0xFD, 0xFF, 0x17, 0x00, 0xA1, 0xFF, 0xC9, 0x00, 0xCD, 0xFE, - 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70, 0x48, 0xFF, 0x08, 0x94, - 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01, 0x6A, 0xFF, 0x26, 0x00, - 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE1, 0x01, 0x31, - 0xFC, 0x1A, 0x07, 0x56, 0xF2, 0x55, 0x26, 0x2E, 0x39, 0x35, 0xF2, - 0x1E, 0x06, 0x25, 0xFD, 0x35, 0x01, 0x98, 0xFF, 0x15, 0x00, 0xFF, - 0xFF, 0x0F, 0x00, 0xC3, 0xFF, 0x71, 0x00, 0x81, 0xFF, 0x1F, 0x00, - 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46, 0xE7, 0x0F, 0x08, 0xF8, 0xE6, - 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, - 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x4A, 0xFC, 0xAC, - 0x06, 0xCA, 0xF3, 0xA7, 0x1E, 0xCA, 0x3E, 0xE4, 0xF3, 0xE5, 0x04, - 0xF4, 0xFD, 0xBA, 0x00, 0xD7, 0xFF, 0xFE, 0xFF, 0x03, 0x00, 0x08, - 0x00, 0xE3, 0xFF, 0x1E, 0x00, 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03, - 0x7D, 0xF6, 0x2A, 0x43, 0x4B, 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93, - 0xFC, 0xCB, 0x01, 0x3D, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFE, 0xFF, - 0x34, 0x00, 0x3E, 0xFF, 0xC9, 0x01, 0x97, 0xFC, 0xE6, 0x05, 0xC6, - 0xF5, 0x00, 0x17, 0x50, 0x43, 0x9D, 0xF6, 0x3A, 0x03, 0xFA, 0xFE, - 0x23, 0x00, 0x21, 0x00, 0xE2, 0xFF, 0x08, 0x00, 0x03, 0x00, 0xFF, - 0xFF, 0xD4, 0xFF, 0xBF, 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3, - 0x98, 0x3E, 0xF3, 0x1E, 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4, - 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2E, 0x00, - 0x50, 0xFF, 0x97, 0x01, 0x10, 0xFD, 0xDA, 0x04, 0x20, 0xF8, 0xA0, - 0x0F, 0x97, 0x46, 0x61, 0xFA, 0x2D, 0x01, 0x2B, 0x00, 0x7A, 0xFF, - 0x75, 0x00, 0xC2, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x96, - 0xFF, 0x39, 0x01, 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, - 0xA0, 0x26, 0x4B, 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, - 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6B, 0xFF, - 0x52, 0x01, 0xA9, 0xFD, 0xA0, 0x03, 0xAE, 0xFA, 0xBE, 0x08, 0x7C, - 0x48, 0x26, 0xFF, 0xD2, 0xFE, 0x79, 0x01, 0xC6, 0xFE, 0xCC, 0x00, - 0xA0, 0xFF, 0x17, 0x00, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, - 0x01, 0x90, 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, - 0x8E, 0xF1, 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, - 0x00, 0xFD, 0xFF, 0x1D, 0x00, 0x8B, 0xFF, 0x01, 0x01, 0x56, 0xFE, - 0x4D, 0x02, 0x45, 0xFD, 0x8D, 0x02, 0xF0, 0x48, 0xD7, 0x04, 0x47, - 0xFC, 0xD1, 0x02, 0x12, 0xFE, 0x21, 0x01, 0x7E, 0xFF, 0x20, 0x00, - 0x00, 0x00, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, - 0xFC, 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, - 0xAB, 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, - 0xFF, 0x14, 0x00, 0xAD, 0xFF, 0xAA, 0x00, 0x0C, 0xFF, 0xF7, 0x00, - 0xC1, 0xFF, 0x33, 0xFD, 0xEC, 0x47, 0x51, 0x0B, 0xAF, 0xF9, 0x1D, - 0x04, 0x6B, 0xFD, 0x6E, 0x01, 0x60, 0xFF, 0x29, 0x00, 0x00, 0x00, - 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF, - 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05, - 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x0C, - 0x00, 0xCE, 0xFF, 0x54, 0x00, 0xBD, 0xFF, 0xB2, 0xFF, 0x01, 0x02, - 0xCF, 0xF8, 0x7D, 0x45, 0x6B, 0x12, 0x30, 0xF7, 0x48, 0x05, 0xDD, - 0xFC, 0xAD, 0x01, 0x48, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, - 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06, 0x6C, - 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49, 0xFE, - 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0x06, 0x00, 0xED, - 0xFF, 0x04, 0x00, 0x60, 0x00, 0x90, 0xFE, 0xEB, 0x03, 0x71, 0xF5, - 0xB7, 0x41, 0xED, 0x19, 0xF5, 0xF4, 0x3B, 0x06, 0x73, 0xFC, 0xD7, - 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, - 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, 0xF6, 0x68, - 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, 0xEA, 0xFF, - 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0x07, 0x00, 0xBD, - 0xFF, 0xED, 0x00, 0x9E, 0xFD, 0x6C, 0x05, 0x1F, 0xF3, 0xC0, 0x3C, - 0x9E, 0x21, 0x28, 0xF3, 0xE2, 0x06, 0x3A, 0xFC, 0xE6, 0x01, 0x37, - 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x59, 0xFF, - 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, 0x2D, 0x0D, 0x69, - 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, 0xFF, 0x93, 0x00, - 0xB6, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1C, 0x00, 0x84, 0xFF, 0x5C, - 0x01, 0xE6, 0xFC, 0x77, 0x06, 0xD4, 0xF1, 0xC6, 0x36, 0x3E, 0x29, - 0xF3, 0xF1, 0x29, 0x07, 0x38, 0xFC, 0xD7, 0x01, 0x42, 0xFF, 0x33, - 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x76, 0xFF, 0x37, 0x01, - 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83, 0x06, 0xCE, 0x48, 0x05, - 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE, 0xEA, 0x00, 0x94, 0xFF, - 0x1A, 0x00, 0xFD, 0xFF, 0x2B, 0x00, 0x5A, 0xFF, 0xAC, 0x01, 0x6E, - 0xFC, 0x0A, 0x07, 0x7E, 0xF1, 0xFF, 0x2F, 0x8A, 0x30, 0x7D, 0xF1, - 0x03, 0x07, 0x75, 0xFC, 0xA7, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0xFD, - 0xFF, 0x1A, 0x00, 0x96, 0xFF, 0xE3, 0x00, 0x95, 0xFE, 0xD5, 0x01, - 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48, 0x00, 0x07, 0x61, 0xFB, 0x46, - 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73, 0xFF, 0x23, 0x00, 0x00, 0x00, - 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xDA, 0x01, 0x36, 0xFC, 0x27, - 0x07, 0x05, 0xF2, 0xAA, 0x28, 0x44, 0x37, 0xE4, 0xF1, 0x67, 0x06, - 0xF2, 0xFC, 0x55, 0x01, 0x88, 0xFF, 0x1B, 0x00, 0xFE, 0xFF, 0x11, - 0x00, 0xB9, 0xFF, 0x8C, 0x00, 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00, - 0x91, 0xFB, 0x3D, 0x47, 0xB7, 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36, - 0xFD, 0x86, 0x01, 0x57, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0xFD, 0xFF, - 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3C, 0xFC, 0xD8, 0x06, 0x47, - 0xF3, 0x06, 0x21, 0x2A, 0x3D, 0x44, 0xF3, 0x52, 0x05, 0xAE, 0xFD, - 0xE3, 0x00, 0xC2, 0xFF, 0x06, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xD9, - 0xFF, 0x37, 0x00, 0xF7, 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7, - 0x53, 0x44, 0xFB, 0x14, 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE, - 0x01, 0x42, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, - 0x3A, 0xFF, 0xD4, 0x01, 0x7A, 0xFC, 0x2B, 0x06, 0x1E, 0xF5, 0x56, - 0x19, 0x0C, 0x42, 0xAA, 0xF5, 0xC9, 0x03, 0xA4, 0xFE, 0x54, 0x00, - 0x09, 0x00, 0xEB, 0xFF, 0x06, 0x00, 0x04, 0x00, 0xF7, 0xFF, 0xEA, - 0xFF, 0x93, 0x00, 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, - 0x94, 0x1C, 0x47, 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, - 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x30, 0x00, 0x4A, 0xFF, - 0xA9, 0x01, 0xE7, 0xFC, 0x33, 0x05, 0x60, 0xF7, 0xDA, 0x11, 0xB8, - 0x45, 0x1C, 0xF9, 0xD8, 0x01, 0xCA, 0xFF, 0xAF, 0xFF, 0x5A, 0x00, - 0xCC, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, - 0x01, 0x57, 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, - 0xAA, 0xF2, 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, - 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x28, 0x00, 0x62, 0xFF, 0x69, 0x01, - 0x77, 0xFD, 0x04, 0x04, 0xE2, 0xF9, 0xCB, 0x0A, 0x0D, 0x48, 0x94, - 0xFD, 0x92, 0xFF, 0x10, 0x01, 0xFE, 0xFE, 0xB1, 0x00, 0xAA, 0xFF, - 0x15, 0x00, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, - 0xFC, 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, - 0x29, 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, - 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x81, 0xFF, 0x1B, 0x01, 0x20, 0xFE, - 0xB6, 0x02, 0x7A, 0xFC, 0x5F, 0x04, 0xF4, 0x48, 0xFF, 0x02, 0x13, - 0xFD, 0x67, 0x02, 0x49, 0xFE, 0x07, 0x01, 0x88, 0xFF, 0x1D, 0x00, - 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21, - 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06, - 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16, - 0x00, 0xA2, 0xFF, 0xC5, 0x00, 0xD4, 0xFE, 0x5F, 0x01, 0x03, 0xFF, - 0xBF, 0xFE, 0x63, 0x48, 0x40, 0x09, 0x7B, 0xFA, 0xB9, 0x03, 0x9D, - 0xFD, 0x58, 0x01, 0x69, 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF, - 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07, 0x61, - 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C, 0xFD, - 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC4, - 0xFF, 0x6E, 0x00, 0x87, 0xFF, 0x13, 0x00, 0x58, 0x01, 0x0D, 0xFA, - 0x61, 0x46, 0x2D, 0x10, 0xF0, 0xF7, 0xF1, 0x04, 0x05, 0xFD, 0x9C, - 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, - 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, 0xF3, 0x5B, - 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, 0xB4, 0x00, - 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0x08, 0x00, 0xE4, 0xFF, 0x1B, - 0x00, 0x30, 0x00, 0xE4, 0xFE, 0x5F, 0x03, 0x5E, 0xF6, 0x02, 0x43, - 0x96, 0x17, 0x9B, 0xF5, 0xF8, 0x05, 0x8F, 0xFC, 0xCC, 0x01, 0x3D, - 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3E, 0xFF, - 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, 0xB6, 0x16, 0x77, - 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, 0x00, 0x25, 0x00, - 0xE1, 0xFF, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0xC4, - 0x00, 0xE2, 0xFD, 0x01, 0x05, 0xBA, 0xF3, 0x64, 0x3E, 0x3F, 0x1F, - 0xA8, 0xF3, 0xB8, 0x06, 0x46, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, - 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x51, 0xFF, 0x95, 0x01, - 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59, 0x0F, 0xAF, 0x46, 0x8B, - 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF, 0x78, 0x00, 0xC0, 0xFF, - 0x0F, 0x00, 0xFF, 0xFF, 0x16, 0x00, 0x94, 0xFF, 0x3D, 0x01, 0x18, - 0xFD, 0x32, 0x06, 0x1F, 0xF2, 0xB5, 0x38, 0xEB, 0x26, 0x40, 0xF2, - 0x1E, 0x07, 0x32, 0xFC, 0xDF, 0x01, 0x3D, 0xFF, 0x35, 0x00, 0xFD, - 0xFF, 0x00, 0x00, 0x25, 0x00, 0x6C, 0xFF, 0x4F, 0x01, 0xB0, 0xFD, - 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08, 0x86, 0x48, 0x5A, 0xFF, 0xBA, - 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF, 0x00, 0x9E, 0xFF, 0x17, 0x00, - 0xFD, 0xFF, 0x27, 0x00, 0x66, 0xFF, 0x97, 0x01, 0x8C, 0xFC, 0xEA, - 0x06, 0x80, 0xF1, 0x26, 0x32, 0x58, 0x2E, 0x8B, 0xF1, 0x1B, 0x07, - 0x5B, 0xFC, 0xBA, 0x01, 0x53, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C, - 0x00, 0x8C, 0xFF, 0xFE, 0x00, 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD, - 0x54, 0x02, 0xEC, 0x48, 0x13, 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C, - 0xFE, 0x24, 0x01, 0x7D, 0xFF, 0x20, 0x00, 0x00, 0x00, 0xFD, 0xFF, - 0x31, 0x00, 0x47, 0xFF, 0xCF, 0x01, 0x40, 0xFC, 0x2A, 0x07, 0xC6, - 0xF1, 0xF7, 0x2A, 0x46, 0x35, 0xAB, 0xF1, 0xA4, 0x06, 0xC4, 0xFC, - 0x72, 0x01, 0x79, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0x14, 0x00, 0xAE, - 0xFF, 0xA7, 0x00, 0x12, 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD, - 0xDC, 0x47, 0x95, 0x0B, 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71, - 0x01, 0x5F, 0xFF, 0x29, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, - 0x38, 0xFF, 0xE6, 0x01, 0x34, 0xFC, 0xFB, 0x06, 0xD2, 0xF2, 0x64, - 0x23, 0x73, 0x3B, 0xBC, 0xF2, 0xB4, 0x05, 0x6E, 0xFD, 0x09, 0x01, - 0xAF, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51, - 0x00, 0xC3, 0xFF, 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, - 0xB2, 0x12, 0x19, 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, - 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, - 0xDD, 0x01, 0x62, 0xFC, 0x69, 0x06, 0x7F, 0xF4, 0xB2, 0x1B, 0xAB, - 0x40, 0xD0, 0xF4, 0x4E, 0x04, 0x53, 0xFE, 0x83, 0x00, 0xF2, 0xFF, - 0xF4, 0xFF, 0x05, 0x00, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, - 0x00, 0x85, 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, - 0xE1, 0xF4, 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, - 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xB9, 0x01, - 0xC1, 0xFC, 0x86, 0x05, 0xA5, 0xF6, 0x1E, 0x14, 0xBA, 0x44, 0xF0, - 0xF7, 0x7B, 0x02, 0x6B, 0xFF, 0xE4, 0xFF, 0x41, 0x00, 0xD6, 0xFF, - 0x0B, 0x00, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, - 0xFD, 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, - 0xE6, 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, - 0xFF, 0x00, 0x00, 0x2B, 0x00, 0x5A, 0xFF, 0x7E, 0x01, 0x48, 0xFD, - 0x66, 0x04, 0x18, 0xF9, 0xE8, 0x0C, 0x7C, 0x47, 0x19, 0xFC, 0x4D, - 0x00, 0xA9, 0x00, 0x35, 0xFF, 0x96, 0x00, 0xB5, 0xFF, 0x12, 0x00, - 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F, - 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07, - 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0x00, - 0x00, 0x22, 0x00, 0x77, 0xFF, 0x34, 0x01, 0xEA, 0xFD, 0x1F, 0x03, - 0xAE, 0xFB, 0x45, 0x06, 0xD5, 0x48, 0x3C, 0x01, 0xDC, 0xFD, 0xFD, - 0x01, 0x80, 0xFE, 0xED, 0x00, 0x93, 0xFF, 0x1B, 0x00, 0xFD, 0xFF, - 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07, 0x80, - 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78, 0xFC, - 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x98, - 0xFF, 0xE0, 0x00, 0x9C, 0xFE, 0xC8, 0x01, 0x3F, 0xFE, 0x62, 0x00, - 0xB8, 0x48, 0x3F, 0x07, 0x47, 0xFB, 0x53, 0x03, 0xD0, 0xFD, 0x40, - 0x01, 0x72, 0xFF, 0x23, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, - 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, 0xF2, 0x60, - 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, 0x51, 0x01, - 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0x11, 0x00, 0xBA, 0xFF, 0x89, - 0x00, 0x51, 0xFF, 0x77, 0x00, 0xA7, 0x00, 0x64, 0xFB, 0x26, 0x47, - 0xFC, 0x0D, 0xB4, 0xF8, 0x95, 0x04, 0x31, 0xFD, 0x88, 0x01, 0x56, - 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, - 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, 0xBA, 0x20, 0x61, - 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, 0x00, 0xC5, 0xFF, - 0x05, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDB, 0xFF, 0x34, 0x00, 0xFE, - 0xFF, 0x3D, 0xFF, 0xC9, 0x02, 0x64, 0xF7, 0x2F, 0x44, 0x44, 0x15, - 0x4A, 0xF6, 0xAD, 0x05, 0xAF, 0xFC, 0xC0, 0x01, 0x41, 0xFF, 0x32, - 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD3, 0x01, - 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C, 0x19, 0x38, 0x42, 0xC7, - 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00, 0x0C, 0x00, 0xEA, 0xFF, - 0x06, 0x00, 0x04, 0x00, 0xF8, 0xFF, 0xE7, 0xFF, 0x99, 0x00, 0x2C, - 0xFE, 0x8C, 0x04, 0x6D, 0xF4, 0xF0, 0x3F, 0xE0, 0x1C, 0x34, 0xF4, - 0x85, 0x06, 0x57, 0xFC, 0xE0, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, - 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4A, 0xFF, 0xA7, 0x01, 0xEC, 0xFC, - 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11, 0xD7, 0x45, 0x43, 0xF9, 0xC3, - 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E, 0x00, 0xCB, 0xFF, 0x0D, 0x00, - 0x00, 0x00, 0x10, 0x00, 0xA6, 0xFF, 0x1B, 0x01, 0x50, 0xFD, 0xE1, - 0x05, 0x82, 0xF2, 0x8F, 0x3A, 0x92, 0x24, 0x9D, 0xF2, 0x09, 0x07, - 0x32, 0xFC, 0xE4, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, - 0x00, 0x28, 0x00, 0x63, 0xFF, 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03, - 0xFB, 0xF9, 0x89, 0x0A, 0x1D, 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D, - 0x01, 0xF7, 0xFE, 0xB4, 0x00, 0xA9, 0xFF, 0x15, 0x00, 0xFE, 0xFF, - 0x23, 0x00, 0x72, 0xFF, 0x7F, 0x01, 0xB0, 0xFC, 0xBE, 0x06, 0x97, - 0xF1, 0x3F, 0x34, 0x19, 0x2C, 0xAD, 0xF1, 0x28, 0x07, 0x48, 0xFC, - 0xC9, 0x01, 0x4B, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F, - 0x00, 0x82, 0xFF, 0x18, 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC, - 0x24, 0x04, 0xF5, 0x48, 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42, - 0xFE, 0x0B, 0x01, 0x87, 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00, - 0x4F, 0xFF, 0xC2, 0x01, 0x51, 0xFC, 0x23, 0x07, 0x9A, 0xF1, 0x3A, - 0x2D, 0x35, 0x33, 0x89, 0xF1, 0xD5, 0x06, 0x9D, 0xFC, 0x8B, 0x01, - 0x6C, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0x16, 0x00, 0xA4, 0xFF, 0xC2, - 0x00, 0xDB, 0xFE, 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, - 0x81, 0x09, 0x61, 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, - 0xFF, 0x26, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, - 0xE2, 0x01, 0x31, 0xFC, 0x15, 0x07, 0x6D, 0xF2, 0xBF, 0x25, 0xA5, - 0x39, 0x4D, 0xF2, 0x0B, 0x06, 0x33, 0xFD, 0x2D, 0x01, 0x9D, 0xFF, - 0x13, 0x00, 0xFF, 0xFF, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, - 0xFF, 0x06, 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, - 0xD7, 0xF7, 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, - 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, - 0x4E, 0xFC, 0xA0, 0x06, 0xED, 0xF3, 0x0F, 0x1E, 0x2D, 0x3F, 0x10, - 0xF4, 0xC8, 0x04, 0x07, 0xFE, 0xAF, 0x00, 0xDC, 0xFF, 0xFC, 0xFF, - 0x03, 0x00, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, - 0xFE, 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, - 0x00, 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, - 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC6, 0x01, 0x9F, 0xFC, - 0xD3, 0x05, 0xF1, 0xF5, 0x6C, 0x16, 0x9E, 0x43, 0xDD, 0xF6, 0x15, - 0x03, 0x10, 0xFF, 0x17, 0x00, 0x28, 0x00, 0xDF, 0xFF, 0x09, 0x00, - 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F, - 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06, - 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, - 0xFF, 0x2D, 0x00, 0x52, 0xFF, 0x92, 0x01, 0x1B, 0xFD, 0xC4, 0x04, - 0x51, 0xF8, 0x13, 0x0F, 0xC8, 0x46, 0xB6, 0xFA, 0x01, 0x01, 0x44, - 0x00, 0x6C, 0xFF, 0x7B, 0x00, 0xBF, 0xFF, 0x10, 0x00, 0xFF, 0xFF, - 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06, 0x14, - 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33, 0xFC, - 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x25, - 0x00, 0x6D, 0xFF, 0x4C, 0x01, 0xB6, 0xFD, 0x86, 0x03, 0xE1, 0xFA, - 0x3D, 0x08, 0x92, 0x48, 0x8E, 0xFF, 0xA1, 0xFE, 0x93, 0x01, 0xB8, - 0xFE, 0xD3, 0x00, 0x9D, 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00, - 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, 0xF1, 0xE3, - 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, 0xB7, 0x01, - 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0x1C, 0x00, 0x8D, 0xFF, 0xFA, - 0x00, 0x64, 0xFE, 0x32, 0x02, 0x78, 0xFD, 0x1B, 0x02, 0xEA, 0x48, - 0x50, 0x05, 0x14, 0xFC, 0xEB, 0x02, 0x05, 0xFE, 0x27, 0x01, 0x7C, - 0xFF, 0x21, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x46, 0xFF, - 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, 0xAE, 0x2A, 0x86, - 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, 0x01, 0x7B, 0xFF, - 0x20, 0x00, 0xFE, 0xFF, 0x13, 0x00, 0xAF, 0xFF, 0xA4, 0x00, 0x19, - 0xFF, 0xDD, 0x00, 0xF0, 0xFF, 0xD4, 0xFC, 0xC9, 0x47, 0xD8, 0x0B, - 0x7C, 0xF9, 0x35, 0x04, 0x5F, 0xFD, 0x74, 0x01, 0x5E, 0xFF, 0x29, - 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE6, 0x01, - 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18, 0x23, 0xAB, 0x3B, 0xCC, - 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01, 0xB1, 0xFF, 0x0C, 0x00, - 0x00, 0x00, 0x0C, 0x00, 0xD1, 0xFF, 0x4E, 0x00, 0xCA, 0xFF, 0x9A, - 0xFF, 0x2A, 0x02, 0x83, 0xF8, 0x3F, 0x45, 0xFB, 0x12, 0x01, 0xF7, - 0x5D, 0x05, 0xD3, 0xFC, 0xB1, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, - 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xDC, 0x01, 0x64, 0xFC, - 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B, 0xD9, 0x40, 0xEA, 0xF4, 0x3E, - 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5, 0xFF, 0xF3, 0xFF, 0x05, 0x00, - 0x05, 0x00, 0xEF, 0xFF, 0xFE, 0xFF, 0x6C, 0x00, 0x7B, 0xFE, 0x0C, - 0x04, 0x3A, 0xF5, 0x5F, 0x41, 0x83, 0x1A, 0xCD, 0xF4, 0x4B, 0x06, - 0x6D, 0xFC, 0xD9, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, - 0xFF, 0x31, 0x00, 0x44, 0xFF, 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05, - 0xBC, 0xF6, 0xD5, 0x13, 0xDC, 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77, - 0xFF, 0xDD, 0xFF, 0x44, 0x00, 0xD5, 0xFF, 0x0B, 0x00, 0x01, 0x00, - 0x09, 0x00, 0xB8, 0xFF, 0xF6, 0x00, 0x8D, 0xFD, 0x84, 0x05, 0xFD, - 0xF2, 0x52, 0x3C, 0x35, 0x22, 0x0B, 0xF3, 0xEB, 0x06, 0x37, 0xFC, - 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A, - 0x00, 0x5B, 0xFF, 0x7C, 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9, - 0xA4, 0x0C, 0x90, 0x47, 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E, - 0xFF, 0x99, 0x00, 0xB3, 0xFF, 0x12, 0x00, 0xFE, 0xFF, 0x1E, 0x00, - 0x80, 0xFF, 0x64, 0x01, 0xDA, 0xFC, 0x87, 0x06, 0xC5, 0xF1, 0x46, - 0x36, 0xD1, 0x29, 0xE3, 0xF1, 0x2A, 0x07, 0x3A, 0xFC, 0xD5, 0x01, - 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x22, 0x00, 0x78, - 0xFF, 0x31, 0x01, 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, - 0xDB, 0x48, 0x73, 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, - 0x00, 0x91, 0xFF, 0x1B, 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x58, 0xFF, - 0xB1, 0x01, 0x67, 0xFC, 0x10, 0x07, 0x81, 0xF1, 0x73, 0x2F, 0x15, - 0x31, 0x7C, 0xF1, 0xFB, 0x06, 0x7C, 0xFC, 0xA2, 0x01, 0x60, 0xFF, - 0x29, 0x00, 0xFD, 0xFF, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, - 0xFE, 0xBB, 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, - 0x2E, 0xFB, 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, - 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDC, 0x01, - 0x34, 0xFC, 0x25, 0x07, 0x18, 0xF2, 0x15, 0x28, 0xBF, 0x37, 0xF7, - 0xF1, 0x56, 0x06, 0xFE, 0xFC, 0x4D, 0x01, 0x8C, 0xFF, 0x19, 0x00, - 0xFF, 0xFF, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, - 0x00, 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, - 0xA1, 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, - 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3F, 0xFC, - 0xCE, 0x06, 0x66, 0xF3, 0x6F, 0x20, 0x96, 0x3D, 0x69, 0xF3, 0x38, - 0x05, 0xBF, 0xFD, 0xD9, 0x00, 0xC7, 0xFF, 0x04, 0x00, 0x02, 0x00, - 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC, - 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05, - 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, - 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xD2, 0x01, 0x81, 0xFC, 0x1A, 0x06, - 0x47, 0xF5, 0xC1, 0x18, 0x60, 0x42, 0xE4, 0xF5, 0xA6, 0x03, 0xB9, - 0xFE, 0x48, 0x00, 0x0F, 0x00, 0xE9, 0xFF, 0x07, 0x00, 0x04, 0x00, - 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04, 0x55, - 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55, 0xFC, - 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F, - 0x00, 0x4B, 0xFF, 0xA4, 0x01, 0xF1, 0xFC, 0x1D, 0x05, 0x8F, 0xF7, - 0x4A, 0x11, 0xF2, 0x45, 0x6B, 0xF9, 0xAE, 0x01, 0xE2, 0xFF, 0xA2, - 0xFF, 0x61, 0x00, 0xC9, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, - 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, 0xF2, 0x54, - 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, 0xE4, 0x01, - 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x64, - 0xFF, 0x63, 0x01, 0x84, 0xFD, 0xEB, 0x03, 0x14, 0xFA, 0x47, 0x0A, - 0x2C, 0x48, 0xF6, 0xFD, 0x63, 0xFF, 0x2B, 0x01, 0xF0, 0xFE, 0xB8, - 0x00, 0xA8, 0xFF, 0x15, 0x00, 0xFE, 0xFF, 0x23, 0x00, 0x71, 0xFF, - 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, 0xFD, 0x33, 0x62, - 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, 0x01, 0x4C, 0xFF, - 0x30, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x1F, 0x00, 0x83, 0xFF, 0x14, - 0x01, 0x2D, 0xFE, 0x9C, 0x02, 0xAD, 0xFC, 0xE9, 0x03, 0xF6, 0x48, - 0x73, 0x03, 0xE0, 0xFC, 0x82, 0x02, 0x3B, 0xFE, 0x0E, 0x01, 0x86, - 0xFF, 0x1E, 0x00, 0xFD, 0xFF, 0x2F, 0x00, 0x4E, 0xFF, 0xC3, 0x01, - 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2, 0x2C, 0x78, 0x33, 0x8C, - 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01, 0x6D, 0xFF, 0x24, 0x00, - 0xFD, 0xFF, 0x16, 0x00, 0xA5, 0xFF, 0xBE, 0x00, 0xE2, 0xFE, 0x45, - 0x01, 0x33, 0xFF, 0x5A, 0xFE, 0x48, 0x48, 0xC3, 0x09, 0x47, 0xFA, - 0xD2, 0x03, 0x90, 0xFD, 0x5E, 0x01, 0x66, 0xFF, 0x27, 0x00, 0x00, - 0x00, 0xFD, 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE3, 0x01, 0x31, 0xFC, - 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25, 0xDF, 0x39, 0x5A, 0xF2, 0x00, - 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F, 0xFF, 0x13, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0xC7, 0xFF, 0x68, 0x00, 0x95, 0xFF, 0xFA, 0xFF, 0x83, - 0x01, 0xBB, 0xF9, 0x2B, 0x46, 0xBB, 0x10, 0xBF, 0xF7, 0x07, 0x05, - 0xFB, 0xFC, 0xA0, 0x01, 0x4D, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0xFE, - 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06, - 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10, - 0xFE, 0xA9, 0x00, 0xDF, 0xFF, 0xFB, 0xFF, 0x03, 0x00, 0x07, 0x00, - 0xE6, 0xFF, 0x15, 0x00, 0x3C, 0x00, 0xCF, 0xFE, 0x83, 0x03, 0x20, - 0xF6, 0xB2, 0x42, 0x2B, 0x18, 0x71, 0xF5, 0x09, 0x06, 0x88, 0xFC, - 0xCF, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x33, - 0x00, 0x3F, 0xFF, 0xC5, 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6, - 0x22, 0x16, 0xC3, 0x43, 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11, - 0x00, 0x2B, 0x00, 0xDE, 0xFF, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, - 0xCC, 0xFF, 0xCE, 0x00, 0xD1, 0xFD, 0x1D, 0x05, 0x91, 0xF3, 0xFE, - 0x3D, 0xD7, 0x1F, 0x87, 0xF3, 0xC3, 0x06, 0x42, 0xFC, 0xE5, 0x01, - 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x53, - 0xFF, 0x90, 0x01, 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, - 0xE1, 0x46, 0xE1, 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, - 0x00, 0xBE, 0xFF, 0x10, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x90, 0xFF, - 0x45, 0x01, 0x0B, 0xFD, 0x44, 0x06, 0x0A, 0xF2, 0x3B, 0x38, 0x80, - 0x27, 0x2B, 0xF2, 0x22, 0x07, 0x33, 0xFC, 0xDE, 0x01, 0x3E, 0xFF, - 0x34, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, - 0x01, 0xBC, 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, - 0xC3, 0xFF, 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, - 0xFF, 0x18, 0x00, 0xFD, 0xFF, 0x28, 0x00, 0x63, 0xFF, 0x9D, 0x01, - 0x84, 0xFC, 0xF3, 0x06, 0x7D, 0xF1, 0x9E, 0x31, 0xE6, 0x2E, 0x85, - 0xF1, 0x16, 0x07, 0x61, 0xFC, 0xB5, 0x01, 0x55, 0xFF, 0x2D, 0x00, - 0xFD, 0xFF, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, - 0x02, 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, - 0xF8, 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, - 0x00, 0xFD, 0xFF, 0x32, 0x00, 0x45, 0xFF, 0xD2, 0x01, 0x3D, 0xFC, - 0x2B, 0x07, 0xD4, 0xF1, 0x64, 0x2A, 0xC6, 0x35, 0xB7, 0xF1, 0x96, - 0x06, 0xCF, 0xFC, 0x6B, 0x01, 0x7D, 0xFF, 0x1F, 0x00, 0xFE, 0xFF, - 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07, - 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04, - 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0xFD, - 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF3, 0x06, - 0xEE, 0xF2, 0xCD, 0x22, 0xE4, 0x3B, 0xDC, 0xF2, 0x9C, 0x05, 0x7E, - 0xFD, 0x00, 0x01, 0xB4, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0B, 0x00, - 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02, 0x5E, - 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF, 0xFC, - 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x36, - 0x00, 0x38, 0xFF, 0xDB, 0x01, 0x67, 0xFC, 0x5A, 0x06, 0xA6, 0xF4, - 0x1B, 0x1B, 0x07, 0x41, 0x04, 0xF5, 0x2D, 0x04, 0x67, 0xFE, 0x77, - 0x00, 0xF8, 0xFF, 0xF2, 0xFF, 0x05, 0x00, 0x05, 0x00, 0xF0, 0xFF, - 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, 0xF5, 0x32, - 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, 0xDA, 0x01, - 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x31, 0x00, 0x45, - 0xFF, 0xB5, 0x01, 0xCA, 0xFC, 0x72, 0x05, 0xD3, 0xF6, 0x8D, 0x13, - 0xFD, 0x44, 0x39, 0xF8, 0x53, 0x02, 0x82, 0xFF, 0xD7, 0xFF, 0x47, - 0x00, 0xD3, 0xFF, 0x0B, 0x00, 0x01, 0x00, 0x0A, 0x00, 0xB6, 0xFF, - 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, 0x1C, 0x3C, 0x81, - 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, 0x01, 0x37, 0xFF, - 0x36, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x2A, 0x00, 0x5C, 0xFF, 0x79, - 0x01, 0x53, 0xFD, 0x4E, 0x04, 0x4A, 0xF9, 0x60, 0x0C, 0xA3, 0x47, - 0x76, 0xFC, 0x1F, 0x00, 0xC3, 0x00, 0x27, 0xFF, 0x9D, 0x00, 0xB2, - 0xFF, 0x13, 0x00, 0xFE, 0xFF, 0x1E, 0x00, 0x7F, 0xFF, 0x67, 0x01, - 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06, 0x36, 0x1A, 0x2A, 0xDC, - 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01, 0x44, 0xFF, 0x32, 0x00, - 0xFD, 0xFF, 0x00, 0x00, 0x21, 0x00, 0x79, 0xFF, 0x2E, 0x01, 0xF7, - 0xFD, 0x05, 0x03, 0xE1, 0xFB, 0xCA, 0x05, 0xDF, 0x48, 0xAB, 0x01, - 0xAA, 0xFD, 0x18, 0x02, 0x72, 0xFE, 0xF4, 0x00, 0x90, 0xFF, 0x1B, - 0x00, 0xFD, 0xFF, 0x2C, 0x00, 0x57, 0xFF, 0xB3, 0x01, 0x64, 0xFC, - 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F, 0x5A, 0x31, 0x7D, 0xF1, 0xF7, - 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61, 0xFF, 0x29, 0x00, 0xFD, 0xFF, - 0x19, 0x00, 0x9A, 0xFF, 0xD9, 0x00, 0xAA, 0xFE, 0xAE, 0x01, 0x70, - 0xFE, 0xF8, 0xFF, 0xA6, 0x48, 0xBE, 0x07, 0x14, 0xFB, 0x6D, 0x03, - 0xC3, 0xFD, 0x46, 0x01, 0x70, 0xFF, 0x24, 0x00, 0x00, 0x00, 0xFD, - 0xFF, 0x34, 0x00, 0x3F, 0xFF, 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07, - 0x21, 0xF2, 0xCB, 0x27, 0xFE, 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04, - 0xFD, 0x49, 0x01, 0x8E, 0xFF, 0x19, 0x00, 0xFF, 0xFF, 0x10, 0x00, - 0xBD, 0xFF, 0x82, 0x00, 0x5E, 0xFF, 0x5D, 0x00, 0xD4, 0x00, 0x0C, - 0xFB, 0xF9, 0x46, 0x87, 0x0E, 0x82, 0xF8, 0xAD, 0x04, 0x26, 0xFD, - 0x8D, 0x01, 0x54, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, - 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3, - 0x22, 0x20, 0xCA, 0x3D, 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4, - 0x00, 0xCA, 0xFF, 0x03, 0x00, 0x02, 0x00, 0x09, 0x00, 0xDD, 0xFF, - 0x2E, 0x00, 0x0A, 0x00, 0x27, 0xFF, 0xEF, 0x02, 0x20, 0xF7, 0xE7, - 0x43, 0xD8, 0x15, 0x1E, 0xF6, 0xC0, 0x05, 0xA7, 0xFC, 0xC3, 0x01, - 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, 0x34, 0x00, 0x3B, - 0xFF, 0xD1, 0x01, 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, - 0x89, 0x42, 0x02, 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, - 0x00, 0xE8, 0xFF, 0x07, 0x00, 0x03, 0x00, 0xFA, 0xFF, 0xE2, 0xFF, - 0xA4, 0x00, 0x19, 0xFE, 0xAA, 0x04, 0x3E, 0xF4, 0x90, 0x3F, 0x78, - 0x1D, 0x10, 0xF4, 0x93, 0x06, 0x52, 0xFC, 0xE1, 0x01, 0x36, 0xFF, - 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, - 0x01, 0xF6, 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, - 0x93, 0xF9, 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, - 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA1, 0xFF, 0x24, 0x01, - 0x41, 0xFD, 0xF6, 0x05, 0x67, 0xF2, 0x1A, 0x3A, 0x29, 0x25, 0x84, - 0xF2, 0x0F, 0x07, 0x31, 0xFC, 0xE3, 0x01, 0x3A, 0xFF, 0x35, 0x00, - 0xFD, 0xFF, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, - 0xFD, 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, - 0x4B, 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, - 0x00, 0xFD, 0xFF, 0x24, 0x00, 0x6F, 0xFF, 0x85, 0x01, 0xA6, 0xFC, - 0xCA, 0x06, 0x8F, 0xF1, 0xBB, 0x33, 0xAB, 0x2C, 0xA3, 0xF1, 0x26, - 0x07, 0x4C, 0xFC, 0xC5, 0x01, 0x4D, 0xFF, 0x30, 0x00, 0xFD, 0xFF, - 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, - 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, - 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0xFD, - 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, 0x71, 0xFC, 0x07, 0x07, - 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, 0xF1, 0x07, 0x07, 0x71, - 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, 0xFD, 0xFF, 0x00, 0x00, - 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, - 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, - 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x02, 0x00, 0x05, - 0x00, 0xC3, 0xFF, 0xE1, 0x00, 0xB1, 0xFD, 0x4E, 0x05, 0x4A, 0xF3, - 0x3D, 0x3D, 0xED, 0x20, 0x4C, 0xF3, 0xD6, 0x06, 0x3D, 0xFC, 0xE6, - 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x36, 0x00, - 0x36, 0xFF, 0xE6, 0x01, 0x3D, 0xFC, 0xD6, 0x06, 0x4C, 0xF3, 0xED, - 0x20, 0x3D, 0x3D, 0x4A, 0xF3, 0x4E, 0x05, 0xB1, 0xFD, 0xE1, 0x00, - 0xC3, 0xFF, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x84, - 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, 0x02, 0xC7, 0xFC, 0xAE, 0x03, - 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, 0x8F, 0x02, 0x34, 0xFE, 0x11, - 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA6, 0xFF, 0xBB, 0x00, - 0xE9, 0xFE, 0x38, 0x01, 0x4B, 0xFF, 0x28, 0xFE, 0x3A, 0x48, 0x04, - 0x0A, 0x2E, 0xFA, 0xDF, 0x03, 0x8A, 0xFD, 0x60, 0x01, 0x65, 0xFF, - 0x27, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC8, 0xFF, 0x64, 0x00, 0x9B, - 0xFF, 0xEE, 0xFF, 0x98, 0x01, 0x93, 0xF9, 0x10, 0x46, 0x03, 0x11, - 0xA7, 0xF7, 0x12, 0x05, 0xF6, 0xFC, 0xA2, 0x01, 0x4C, 0xFF, 0x2F, - 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xE8, 0xFF, 0x12, 0x00, 0x42, 0x00, - 0xC4, 0xFE, 0x94, 0x03, 0x02, 0xF6, 0x89, 0x42, 0x76, 0x18, 0x5C, - 0xF5, 0x12, 0x06, 0x84, 0xFC, 0xD1, 0x01, 0x3B, 0xFF, 0x34, 0x00, - 0xFE, 0xFF, 0x02, 0x00, 0x03, 0x00, 0xCA, 0xFF, 0xD4, 0x00, 0xC8, - 0xFD, 0x2A, 0x05, 0x7D, 0xF3, 0xCA, 0x3D, 0x22, 0x20, 0x76, 0xF3, - 0xC8, 0x06, 0x41, 0xFC, 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, - 0xFF, 0xFF, 0xFF, 0x19, 0x00, 0x8E, 0xFF, 0x49, 0x01, 0x04, 0xFD, - 0x4D, 0x06, 0x00, 0xF2, 0xFE, 0x37, 0xCB, 0x27, 0x21, 0xF2, 0x23, - 0x07, 0x34, 0xFC, 0xDD, 0x01, 0x3F, 0xFF, 0x34, 0x00, 0xFD, 0xFF, - 0xFD, 0xFF, 0x29, 0x00, 0x61, 0xFF, 0x9F, 0x01, 0x80, 0xFC, 0xF7, - 0x06, 0x7D, 0xF1, 0x5A, 0x31, 0x2C, 0x2F, 0x83, 0xF1, 0x13, 0x07, - 0x64, 0xFC, 0xB3, 0x01, 0x57, 0xFF, 0x2C, 0x00, 0xFD, 0xFF, 0xFD, - 0xFF, 0x32, 0x00, 0x44, 0xFF, 0xD3, 0x01, 0x3C, 0xFC, 0x2A, 0x07, - 0xDC, 0xF1, 0x1A, 0x2A, 0x06, 0x36, 0xBE, 0xF1, 0x8E, 0x06, 0xD5, - 0xFC, 0x67, 0x01, 0x7F, 0xFF, 0x1E, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, - 0x36, 0x00, 0x37, 0xFF, 0xE6, 0x01, 0x36, 0xFC, 0xEF, 0x06, 0xFC, - 0xF2, 0x81, 0x22, 0x1C, 0x3C, 0xEC, 0xF2, 0x90, 0x05, 0x85, 0xFD, - 0xFB, 0x00, 0xB6, 0xFF, 0x0A, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35, - 0x00, 0x38, 0xFF, 0xDA, 0x01, 0x6A, 0xFC, 0x53, 0x06, 0xBA, 0xF4, - 0xCE, 0x1A, 0x32, 0x41, 0x1F, 0xF5, 0x1D, 0x04, 0x71, 0xFE, 0x71, - 0x00, 0xFB, 0xFF, 0xF0, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00, - 0x46, 0xFF, 0xB3, 0x01, 0xCF, 0xFC, 0x67, 0x05, 0xEA, 0xF6, 0x44, - 0x13, 0x1E, 0x45, 0x5E, 0xF8, 0x3F, 0x02, 0x8E, 0xFF, 0xD0, 0xFF, - 0x4A, 0x00, 0xD2, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5D, - 0xFF, 0x76, 0x01, 0x59, 0xFD, 0x42, 0x04, 0x63, 0xF9, 0x1C, 0x0C, - 0xB6, 0x47, 0xA4, 0xFC, 0x07, 0x00, 0xD0, 0x00, 0x20, 0xFF, 0xA0, - 0x00, 0xB1, 0xFF, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x7A, 0xFF, - 0x2B, 0x01, 0xFE, 0xFD, 0xF8, 0x02, 0xFB, 0xFB, 0x8D, 0x05, 0xE5, - 0x48, 0xE3, 0x01, 0x91, 0xFD, 0x25, 0x02, 0x6B, 0xFE, 0xF7, 0x00, - 0x8F, 0xFF, 0x1C, 0x00, 0x18, 0x00, 0x9C, 0xFF, 0xD6, 0x00, 0xB1, - 0xFE, 0xA1, 0x01, 0x89, 0xFE, 0xC3, 0xFF, 0x9C, 0x48, 0xFD, 0x07, - 0xFA, 0xFA, 0x7A, 0x03, 0xBC, 0xFD, 0x49, 0x01, 0x6E, 0xFF, 0x24, - 0x00, 0x00, 0x00, 0x10, 0x00, 0xBE, 0xFF, 0x7F, 0x00, 0x65, 0xFF, - 0x51, 0x00, 0xEB, 0x00, 0xE1, 0xFA, 0xE1, 0x46, 0xCD, 0x0E, 0x6A, - 0xF8, 0xB8, 0x04, 0x20, 0xFD, 0x90, 0x01, 0x53, 0xFF, 0x2D, 0x00, - 0xFF, 0xFF, 0x09, 0x00, 0xDE, 0xFF, 0x2B, 0x00, 0x11, 0x00, 0x1B, - 0xFF, 0x02, 0x03, 0xFE, 0xF6, 0xC3, 0x43, 0x22, 0x16, 0x07, 0xF6, - 0xCA, 0x05, 0xA3, 0xFC, 0xC5, 0x01, 0x3F, 0xFF, 0x33, 0x00, 0xFF, - 0xFF, 0x03, 0x00, 0xFB, 0xFF, 0xDF, 0xFF, 0xA9, 0x00, 0x10, 0xFE, - 0xB9, 0x04, 0x27, 0xF4, 0x5E, 0x3F, 0xC3, 0x1D, 0xFE, 0xF3, 0x99, - 0x06, 0x50, 0xFC, 0xE2, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, - 0x00, 0x00, 0x13, 0x00, 0x9F, 0xFF, 0x28, 0x01, 0x3A, 0xFD, 0x00, - 0x06, 0x5A, 0xF2, 0xDF, 0x39, 0x73, 0x25, 0x79, 0xF2, 0x12, 0x07, - 0x31, 0xFC, 0xE3, 0x01, 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD, - 0xFF, 0x24, 0x00, 0x6D, 0xFF, 0x88, 0x01, 0xA2, 0xFC, 0xD0, 0x06, - 0x8C, 0xF1, 0x78, 0x33, 0xF2, 0x2C, 0x9E, 0xF1, 0x24, 0x07, 0x4E, - 0xFC, 0xC3, 0x01, 0x4E, 0xFF, 0x2F, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, - 0x30, 0x00, 0x4C, 0xFF, 0xC7, 0x01, 0x4A, 0xFC, 0x27, 0x07, 0xA8, - 0xF1, 0x62, 0x2C, 0xFD, 0x33, 0x93, 0xF1, 0xC4, 0x06, 0xAB, 0xFC, - 0x82, 0x01, 0x71, 0xFF, 0x23, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, - 0x00, 0x3A, 0xFF, 0xE4, 0x01, 0x32, 0xFC, 0x0C, 0x07, 0x91, 0xF2, - 0xDD, 0x24, 0x54, 0x3A, 0x74, 0xF2, 0xEB, 0x05, 0x49, 0xFD, 0x20, - 0x01, 0xA3, 0xFF, 0x11, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, - 0x37, 0xFF, 0xE1, 0x01, 0x55, 0xFC, 0x8C, 0x06, 0x22, 0xF4, 0x2C, - 0x1D, 0xC0, 0x3F, 0x55, 0xF4, 0x9B, 0x04, 0x23, 0xFE, 0x9F, 0x00, - 0xE4, 0xFF, 0xF9, 0xFF, 0x04, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x40, - 0xFF, 0xC1, 0x01, 0xAB, 0xFC, 0xB7, 0x05, 0x34, 0xF6, 0x8E, 0x15, - 0x0B, 0x44, 0x42, 0xF7, 0xDC, 0x02, 0x32, 0xFF, 0x04, 0x00, 0x31, - 0x00, 0xDC, 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2C, 0x00, 0x55, 0xFF, - 0x8B, 0x01, 0x2B, 0xFD, 0xA1, 0x04, 0x9B, 0xF8, 0x42, 0x0E, 0x0F, - 0x47, 0x38, 0xFB, 0xBE, 0x00, 0x6A, 0x00, 0x58, 0xFF, 0x85, 0x00, - 0xBB, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x71, 0xFF, 0x43, - 0x01, 0xC9, 0xFD, 0x60, 0x03, 0x2E, 0xFB, 0x7E, 0x07, 0xAF, 0x48, - 0x2D, 0x00, 0x58, 0xFE, 0xBB, 0x01, 0xA3, 0xFE, 0xDD, 0x00, 0x99, - 0xFF, 0x19, 0x00, 0x1B, 0x00, 0x91, 0xFF, 0xF1, 0x00, 0x79, 0xFE, - 0x0A, 0x02, 0xC3, 0xFD, 0x73, 0x01, 0xDB, 0x48, 0x07, 0x06, 0xC7, - 0xFB, 0x12, 0x03, 0xF1, 0xFD, 0x31, 0x01, 0x78, 0xFF, 0x22, 0x00, - 0x00, 0x00, 0x12, 0x00, 0xB3, 0xFF, 0x99, 0x00, 0x2E, 0xFF, 0xB6, - 0x00, 0x36, 0x00, 0x47, 0xFC, 0x90, 0x47, 0xA4, 0x0C, 0x31, 0xF9, - 0x5A, 0x04, 0x4E, 0xFD, 0x7C, 0x01, 0x5B, 0xFF, 0x2A, 0x00, 0x00, - 0x00, 0x0B, 0x00, 0xD5, 0xFF, 0x44, 0x00, 0xDD, 0xFF, 0x77, 0xFF, - 0x67, 0x02, 0x14, 0xF8, 0xDC, 0x44, 0xD5, 0x13, 0xBC, 0xF6, 0x7C, - 0x05, 0xC5, 0xFC, 0xB7, 0x01, 0x44, 0xFF, 0x31, 0x00, 0xFF, 0xFF, - 0x05, 0x00, 0xF3, 0xFF, 0xF5, 0xFF, 0x7D, 0x00, 0x5D, 0xFE, 0x3E, - 0x04, 0xEA, 0xF4, 0xD9, 0x40, 0x66, 0x1B, 0x93, 0xF4, 0x62, 0x06, - 0x64, 0xFC, 0xDC, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, - 0x00, 0x0C, 0x00, 0xB1, 0xFF, 0x04, 0x01, 0x76, 0xFD, 0xA8, 0x05, - 0xCC, 0xF2, 0xAB, 0x3B, 0x18, 0x23, 0xE0, 0xF2, 0xF7, 0x06, 0x35, - 0xFC, 0xE6, 0x01, 0x38, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, - 0x20, 0x00, 0x7B, 0xFF, 0x6E, 0x01, 0xCA, 0xFC, 0x9D, 0x06, 0xB1, - 0xF1, 0x86, 0x35, 0xAE, 0x2A, 0xCD, 0xF1, 0x2B, 0x07, 0x3F, 0xFC, - 0xD1, 0x01, 0x46, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2D, - 0x00, 0x54, 0xFF, 0xB7, 0x01, 0x5E, 0xFC, 0x19, 0x07, 0x88, 0xF1, - 0x9F, 0x2E, 0xE3, 0x31, 0x7E, 0xF1, 0xEE, 0x06, 0x88, 0xFC, 0x9A, - 0x01, 0x64, 0xFF, 0x28, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00, - 0x3E, 0xFF, 0xDF, 0x01, 0x33, 0xFC, 0x20, 0x07, 0x35, 0xF2, 0x36, - 0x27, 0x78, 0x38, 0x14, 0xF2, 0x3B, 0x06, 0x11, 0xFD, 0x41, 0x01, - 0x92, 0xFF, 0x17, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, - 0xFF, 0xE5, 0x01, 0x44, 0xFC, 0xBD, 0x06, 0x97, 0xF3, 0x8A, 0x1F, - 0x31, 0x3E, 0xA5, 0xF3, 0x0F, 0x05, 0xDA, 0xFD, 0xC9, 0x00, 0xCF, - 0xFF, 0x01, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3C, 0xFF, - 0xCE, 0x01, 0x8C, 0xFC, 0x00, 0x06, 0x86, 0xF5, 0xE0, 0x17, 0xDB, - 0x42, 0x3F, 0xF6, 0x71, 0x03, 0xD9, 0xFE, 0x36, 0x00, 0x18, 0x00, - 0xE5, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x2E, 0x00, 0x4E, 0xFF, 0x9E, - 0x01, 0x00, 0xFD, 0xFC, 0x04, 0xD7, 0xF7, 0x75, 0x10, 0x48, 0x46, - 0xE4, 0xF9, 0x6E, 0x01, 0x06, 0x00, 0x8E, 0xFF, 0x6B, 0x00, 0xC6, - 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x68, 0xFF, 0x5B, 0x01, - 0x96, 0xFD, 0xC6, 0x03, 0x61, 0xFA, 0x81, 0x09, 0x57, 0x48, 0x8D, - 0xFE, 0x1B, 0xFF, 0x52, 0x01, 0xDB, 0xFE, 0xC2, 0x00, 0xA4, 0xFF, - 0x16, 0x00, 0x1E, 0x00, 0x87, 0xFF, 0x0B, 0x01, 0x42, 0xFE, 0x74, - 0x02, 0xF9, 0xFC, 0x39, 0x03, 0xF5, 0x48, 0x24, 0x04, 0x94, 0xFC, - 0xA9, 0x02, 0x27, 0xFE, 0x18, 0x01, 0x82, 0xFF, 0x1F, 0x00, 0x00, - 0x00, 0x15, 0x00, 0xA9, 0xFF, 0xB4, 0x00, 0xF7, 0xFE, 0x1D, 0x01, - 0x7A, 0xFF, 0xC5, 0xFD, 0x1D, 0x48, 0x89, 0x0A, 0xFB, 0xF9, 0xF8, - 0x03, 0x7D, 0xFD, 0x66, 0x01, 0x63, 0xFF, 0x28, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0xCB, 0xFF, 0x5E, 0x00, 0xA9, 0xFF, 0xD6, 0xFF, 0xC3, - 0x01, 0x43, 0xF9, 0xD7, 0x45, 0x92, 0x11, 0x77, 0xF7, 0x28, 0x05, - 0xEC, 0xFC, 0xA7, 0x01, 0x4A, 0xFF, 0x2F, 0x00, 0xFF, 0xFF, 0x06, - 0x00, 0xEA, 0xFF, 0x0C, 0x00, 0x4E, 0x00, 0xAF, 0xFE, 0xB8, 0x03, - 0xC7, 0xF5, 0x38, 0x42, 0x0C, 0x19, 0x32, 0xF5, 0x23, 0x06, 0x7D, - 0xFC, 0xD3, 0x01, 0x3A, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x02, 0x00, - 0x05, 0x00, 0xC5, 0xFF, 0xDE, 0x00, 0xB7, 0xFD, 0x45, 0x05, 0x56, - 0xF3, 0x61, 0x3D, 0xBA, 0x20, 0x56, 0xF3, 0xD3, 0x06, 0x3E, 0xFC, - 0xE6, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x1A, - 0x00, 0x8A, 0xFF, 0x51, 0x01, 0xF8, 0xFC, 0x5E, 0x06, 0xED, 0xF1, - 0x82, 0x37, 0x60, 0x28, 0x0E, 0xF2, 0x26, 0x07, 0x35, 0xFC, 0xDB, - 0x01, 0x40, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x29, 0x00, - 0x5F, 0xFF, 0xA5, 0x01, 0x78, 0xFC, 0xFF, 0x06, 0x7D, 0xF1, 0xCF, - 0x30, 0xB8, 0x2F, 0x80, 0xF1, 0x0D, 0x07, 0x6A, 0xFC, 0xAE, 0x01, - 0x59, 0xFF, 0x2B, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x43, - 0xFF, 0xD6, 0x01, 0x39, 0xFC, 0x2A, 0x07, 0xEB, 0xF1, 0x87, 0x29, - 0x85, 0x36, 0xCC, 0xF1, 0x7F, 0x06, 0xE0, 0xFC, 0x60, 0x01, 0x82, - 0xFF, 0x1D, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x37, 0xFF, - 0xE6, 0x01, 0x38, 0xFC, 0xE6, 0x06, 0x19, 0xF3, 0xEA, 0x21, 0x8A, - 0x3C, 0x0E, 0xF3, 0x78, 0x05, 0x96, 0xFD, 0xF1, 0x00, 0xBB, 0xFF, - 0x08, 0x00, 0x01, 0x00, 0xFE, 0xFF, 0x35, 0x00, 0x39, 0xFF, 0xD8, - 0x01, 0x70, 0xFC, 0x43, 0x06, 0xE1, 0xF4, 0x38, 0x1A, 0x8C, 0x41, - 0x55, 0xF5, 0xFC, 0x03, 0x85, 0xFE, 0x66, 0x00, 0x01, 0x00, 0xEE, - 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x30, 0x00, 0x47, 0xFF, 0xAF, 0x01, - 0xD8, 0xFC, 0x52, 0x05, 0x19, 0xF7, 0xB2, 0x12, 0x5C, 0x45, 0xA9, - 0xF8, 0x16, 0x02, 0xA6, 0xFF, 0xC3, 0xFF, 0x51, 0x00, 0xD0, 0xFF, - 0x0C, 0x00, 0x00, 0x00, 0x29, 0x00, 0x5F, 0xFF, 0x71, 0x01, 0x65, - 0xFD, 0x29, 0x04, 0x96, 0xF9, 0x95, 0x0B, 0xDC, 0x47, 0x03, 0xFD, - 0xD9, 0xFF, 0xEA, 0x00, 0x12, 0xFF, 0xA7, 0x00, 0xAE, 0xFF, 0x14, - 0x00, 0x00, 0x00, 0x20, 0x00, 0x7D, 0xFF, 0x24, 0x01, 0x0C, 0xFE, - 0xDE, 0x02, 0x2E, 0xFC, 0x13, 0x05, 0xEC, 0x48, 0x54, 0x02, 0x5E, - 0xFD, 0x3F, 0x02, 0x5D, 0xFE, 0xFE, 0x00, 0x8C, 0xFF, 0x1C, 0x00, - 0x17, 0x00, 0x9E, 0xFF, 0xCF, 0x00, 0xBF, 0xFE, 0x86, 0x01, 0xBA, - 0xFE, 0x5A, 0xFF, 0x86, 0x48, 0x7D, 0x08, 0xC7, 0xFA, 0x93, 0x03, - 0xB0, 0xFD, 0x4F, 0x01, 0x6C, 0xFF, 0x25, 0x00, 0x00, 0x00, 0x0F, - 0x00, 0xC0, 0xFF, 0x78, 0x00, 0x73, 0xFF, 0x38, 0x00, 0x17, 0x01, - 0x8B, 0xFA, 0xAF, 0x46, 0x59, 0x0F, 0x39, 0xF8, 0xCF, 0x04, 0x15, - 0xFD, 0x95, 0x01, 0x51, 0xFF, 0x2D, 0x00, 0xFF, 0xFF, 0x08, 0x00, - 0xE1, 0xFF, 0x25, 0x00, 0x1D, 0x00, 0x05, 0xFF, 0x28, 0x03, 0xBD, - 0xF6, 0x77, 0x43, 0xB6, 0x16, 0xDC, 0xF5, 0xDD, 0x05, 0x9B, 0xFC, - 0xC8, 0x01, 0x3E, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFD, - 0xFF, 0xD9, 0xFF, 0xB4, 0x00, 0xFD, 0xFD, 0xD7, 0x04, 0xFA, 0xF3, - 0xFC, 0x3E, 0x5B, 0x1E, 0xDB, 0xF3, 0xA6, 0x06, 0x4C, 0xFC, 0xE3, - 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x14, 0x00, - 0x9B, 0xFF, 0x31, 0x01, 0x2C, 0xFD, 0x15, 0x06, 0x41, 0xF2, 0x6A, - 0x39, 0x0A, 0x26, 0x61, 0xF2, 0x17, 0x07, 0x31, 0xFC, 0xE2, 0x01, - 0x3B, 0xFF, 0x35, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x25, 0x00, 0x6A, - 0xFF, 0x8E, 0x01, 0x99, 0xFC, 0xDB, 0x06, 0x86, 0xF1, 0xF2, 0x32, - 0x82, 0x2D, 0x96, 0xF1, 0x21, 0x07, 0x53, 0xFC, 0xC0, 0x01, 0x50, - 0xFF, 0x2E, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x30, 0x00, 0x4A, 0xFF, - 0xCA, 0x01, 0x46, 0xFC, 0x29, 0x07, 0xB3, 0xF1, 0xD1, 0x2B, 0x81, - 0x34, 0x9C, 0xF1, 0xB8, 0x06, 0xB5, 0xFC, 0x7C, 0x01, 0x74, 0xFF, - 0x22, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x39, 0xFF, 0xE5, - 0x01, 0x32, 0xFC, 0x06, 0x07, 0xAA, 0xF2, 0x46, 0x24, 0xC8, 0x3A, - 0x90, 0xF2, 0xD6, 0x05, 0x57, 0xFD, 0x17, 0x01, 0xA8, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDF, 0x01, - 0x5A, 0xFC, 0x7E, 0x06, 0x47, 0xF4, 0x94, 0x1C, 0x1F, 0x40, 0x85, - 0xF4, 0x7D, 0x04, 0x36, 0xFE, 0x93, 0x00, 0xEA, 0xFF, 0xF7, 0xFF, - 0x04, 0x00, 0xFF, 0xFF, 0x32, 0x00, 0x42, 0xFF, 0xBE, 0x01, 0xB4, - 0xFC, 0xA4, 0x05, 0x61, 0xF6, 0xFB, 0x14, 0x53, 0x44, 0x86, 0xF7, - 0xB6, 0x02, 0x49, 0xFF, 0xF7, 0xFF, 0x37, 0x00, 0xD9, 0xFF, 0x0A, - 0x00, 0x00, 0x00, 0x2B, 0x00, 0x57, 0xFF, 0x86, 0x01, 0x36, 0xFD, - 0x89, 0x04, 0xCD, 0xF8, 0xB7, 0x0D, 0x3D, 0x47, 0x91, 0xFB, 0x91, - 0x00, 0x83, 0x00, 0x4A, 0xFF, 0x8C, 0x00, 0xB9, 0xFF, 0x11, 0x00, - 0x00, 0x00, 0x23, 0x00, 0x73, 0xFF, 0x3D, 0x01, 0xD6, 0xFD, 0x46, - 0x03, 0x61, 0xFB, 0x00, 0x07, 0xBF, 0x48, 0x98, 0x00, 0x26, 0xFE, - 0xD5, 0x01, 0x95, 0xFE, 0xE3, 0x00, 0x96, 0xFF, 0x1A, 0x00, 0x1A, - 0x00, 0x94, 0xFF, 0xEA, 0x00, 0x87, 0xFE, 0xF0, 0x01, 0xF5, 0xFD, - 0x05, 0x01, 0xCE, 0x48, 0x83, 0x06, 0x94, 0xFB, 0x2C, 0x03, 0xE4, - 0xFD, 0x37, 0x01, 0x76, 0xFF, 0x22, 0x00, 0x00, 0x00, 0x12, 0x00, - 0xB6, 0xFF, 0x93, 0x00, 0x3C, 0xFF, 0x9D, 0x00, 0x63, 0x00, 0xEB, - 0xFB, 0x69, 0x47, 0x2D, 0x0D, 0xFF, 0xF8, 0x72, 0x04, 0x42, 0xFD, - 0x81, 0x01, 0x59, 0xFF, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD7, - 0xFF, 0x3E, 0x00, 0xEA, 0xFF, 0x60, 0xFF, 0x8F, 0x02, 0xCD, 0xF7, - 0x99, 0x44, 0x68, 0x14, 0x8E, 0xF6, 0x90, 0x05, 0xBC, 0xFC, 0xBA, - 0x01, 0x43, 0xFF, 0x32, 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF5, 0xFF, - 0xEF, 0xFF, 0x88, 0x00, 0x49, 0xFE, 0x5D, 0x04, 0xB7, 0xF4, 0x7D, - 0x40, 0xFD, 0x1B, 0x6C, 0xF4, 0x70, 0x06, 0x5F, 0xFC, 0xDE, 0x01, - 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x0E, 0x00, 0xAC, - 0xFF, 0x0E, 0x01, 0x66, 0xFD, 0xBF, 0x05, 0xAD, 0xF2, 0x3B, 0x3B, - 0xB0, 0x23, 0xC4, 0xF2, 0xFF, 0x06, 0x33, 0xFC, 0xE5, 0x01, 0x38, - 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x21, 0x00, 0x77, 0xFF, - 0x75, 0x01, 0xBF, 0xFC, 0xAB, 0x06, 0xA6, 0xF1, 0x05, 0x35, 0x40, - 0x2B, 0xBF, 0xF1, 0x2A, 0x07, 0x42, 0xFC, 0xCE, 0x01, 0x48, 0xFF, - 0x31, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2E, 0x00, 0x52, 0xFF, 0xBC, - 0x01, 0x58, 0xFC, 0x1D, 0x07, 0x8E, 0xF1, 0x11, 0x2E, 0x6B, 0x32, - 0x81, 0xF1, 0xE5, 0x06, 0x90, 0xFC, 0x94, 0x01, 0x67, 0xFF, 0x26, - 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3C, 0xFF, 0xE0, 0x01, - 0x32, 0xFC, 0x1C, 0x07, 0x4B, 0xF2, 0xA0, 0x26, 0xF2, 0x38, 0x2A, - 0xF2, 0x28, 0x06, 0x1F, 0xFD, 0x39, 0x01, 0x96, 0xFF, 0x16, 0x00, - 0xFF, 0xFF, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE4, 0x01, 0x48, - 0xFC, 0xB2, 0x06, 0xB9, 0xF3, 0xF3, 0x1E, 0x98, 0x3E, 0xCF, 0xF3, - 0xF3, 0x04, 0xEB, 0xFD, 0xBF, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0x03, - 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3D, 0xFF, 0xCB, 0x01, 0x93, 0xFC, - 0xEF, 0x05, 0xB0, 0xF5, 0x4B, 0x17, 0x2A, 0x43, 0x7D, 0xF6, 0x4D, - 0x03, 0xEF, 0xFE, 0x2A, 0x00, 0x1E, 0x00, 0xE3, 0xFF, 0x08, 0x00, - 0xFF, 0xFF, 0x2E, 0x00, 0x4F, 0xFF, 0x99, 0x01, 0x0B, 0xFD, 0xE6, - 0x04, 0x08, 0xF8, 0xE7, 0x0F, 0x7C, 0x46, 0x37, 0xFA, 0x42, 0x01, - 0x1F, 0x00, 0x81, 0xFF, 0x71, 0x00, 0xC3, 0xFF, 0x0F, 0x00, 0x00, - 0x00, 0x26, 0x00, 0x6A, 0xFF, 0x55, 0x01, 0xA3, 0xFD, 0xAD, 0x03, - 0x94, 0xFA, 0xFF, 0x08, 0x70, 0x48, 0xF3, 0xFE, 0xEA, 0xFE, 0x6C, - 0x01, 0xCD, 0xFE, 0xC9, 0x00, 0xA1, 0xFF, 0x17, 0x00, 0x1D, 0x00, - 0x8A, 0xFF, 0x04, 0x01, 0x50, 0xFE, 0x5A, 0x02, 0x2C, 0xFD, 0xC6, - 0x02, 0xF2, 0x48, 0x9B, 0x04, 0x61, 0xFC, 0xC3, 0x02, 0x19, 0xFE, - 0x1E, 0x01, 0x7F, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAC, - 0xFF, 0xAE, 0x00, 0x05, 0xFF, 0x03, 0x01, 0xAA, 0xFF, 0x63, 0xFD, - 0xFD, 0x47, 0x0E, 0x0B, 0xC8, 0xF9, 0x11, 0x04, 0x71, 0xFD, 0x6C, - 0x01, 0x61, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xCD, 0xFF, - 0x57, 0x00, 0xB6, 0xFF, 0xBE, 0xFF, 0xED, 0x01, 0xF5, 0xF8, 0x9B, - 0x45, 0x22, 0x12, 0x48, 0xF7, 0x3D, 0x05, 0xE2, 0xFC, 0xAB, 0x01, - 0x49, 0xFF, 0x30, 0x00, 0xFF, 0xFF, 0x06, 0x00, 0xEC, 0xFF, 0x06, - 0x00, 0x5A, 0x00, 0x9A, 0xFE, 0xDA, 0x03, 0x8D, 0xF5, 0xE1, 0x41, - 0xA1, 0x19, 0x09, 0xF5, 0x33, 0x06, 0x77, 0xFC, 0xD6, 0x01, 0x3A, - 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, - 0xE8, 0x00, 0xA6, 0xFD, 0x5F, 0x05, 0x31, 0xF3, 0xF6, 0x3C, 0x52, - 0x21, 0x37, 0xF3, 0xDD, 0x06, 0x3B, 0xFC, 0xE6, 0x01, 0x36, 0xFF, - 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1C, 0x00, 0x86, 0xFF, 0x59, - 0x01, 0xEC, 0xFC, 0x6F, 0x06, 0xDC, 0xF1, 0x04, 0x37, 0xF3, 0x28, - 0xFC, 0xF1, 0x28, 0x07, 0x37, 0xFC, 0xD8, 0x01, 0x41, 0xFF, 0x33, - 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2A, 0x00, 0x5C, 0xFF, 0xAA, 0x01, - 0x71, 0xFC, 0x07, 0x07, 0x7E, 0xF1, 0x44, 0x30, 0x44, 0x30, 0x7E, - 0xF1, 0x07, 0x07, 0x71, 0xFC, 0xAA, 0x01, 0x5C, 0xFF, 0x2A, 0x00, - 0xFD, 0xFF, 0xFD, 0xFF, 0x33, 0x00, 0x41, 0xFF, 0xD8, 0x01, 0x37, - 0xFC, 0x28, 0x07, 0xFC, 0xF1, 0xF3, 0x28, 0x04, 0x37, 0xDC, 0xF1, - 0x6F, 0x06, 0xEC, 0xFC, 0x59, 0x01, 0x86, 0xFF, 0x1C, 0x00, 0xFE, - 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3B, 0xFC, - 0xDD, 0x06, 0x37, 0xF3, 0x52, 0x21, 0xF6, 0x3C, 0x31, 0xF3, 0x5F, - 0x05, 0xA6, 0xFD, 0xE8, 0x00, 0xC0, 0xFF, 0x07, 0x00, 0x01, 0x00, - 0xFE, 0xFF, 0x35, 0x00, 0x3A, 0xFF, 0xD6, 0x01, 0x77, 0xFC, 0x33, - 0x06, 0x09, 0xF5, 0xA1, 0x19, 0xE1, 0x41, 0x8D, 0xF5, 0xDA, 0x03, - 0x9A, 0xFE, 0x5A, 0x00, 0x06, 0x00, 0xEC, 0xFF, 0x06, 0x00, 0xFF, - 0xFF, 0x30, 0x00, 0x49, 0xFF, 0xAB, 0x01, 0xE2, 0xFC, 0x3D, 0x05, - 0x48, 0xF7, 0x22, 0x12, 0x9B, 0x45, 0xF5, 0xF8, 0xED, 0x01, 0xBE, - 0xFF, 0xB6, 0xFF, 0x57, 0x00, 0xCD, 0xFF, 0x0C, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x61, 0xFF, 0x6C, 0x01, 0x71, 0xFD, 0x11, 0x04, 0xC8, - 0xF9, 0x0E, 0x0B, 0xFD, 0x47, 0x63, 0xFD, 0xAA, 0xFF, 0x03, 0x01, - 0x05, 0xFF, 0xAE, 0x00, 0xAC, 0xFF, 0x14, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x7F, 0xFF, 0x1E, 0x01, 0x19, 0xFE, 0xC3, 0x02, 0x61, 0xFC, - 0x9B, 0x04, 0xF2, 0x48, 0xC6, 0x02, 0x2C, 0xFD, 0x5A, 0x02, 0x50, - 0xFE, 0x04, 0x01, 0x8A, 0xFF, 0x1D, 0x00, 0x17, 0x00, 0xA1, 0xFF, - 0xC9, 0x00, 0xCD, 0xFE, 0x6C, 0x01, 0xEA, 0xFE, 0xF3, 0xFE, 0x70, - 0x48, 0xFF, 0x08, 0x94, 0xFA, 0xAD, 0x03, 0xA3, 0xFD, 0x55, 0x01, - 0x6A, 0xFF, 0x26, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xC3, 0xFF, 0x71, - 0x00, 0x81, 0xFF, 0x1F, 0x00, 0x42, 0x01, 0x37, 0xFA, 0x7C, 0x46, - 0xE7, 0x0F, 0x08, 0xF8, 0xE6, 0x04, 0x0B, 0xFD, 0x99, 0x01, 0x4F, - 0xFF, 0x2E, 0x00, 0xFF, 0xFF, 0x08, 0x00, 0xE3, 0xFF, 0x1E, 0x00, - 0x2A, 0x00, 0xEF, 0xFE, 0x4D, 0x03, 0x7D, 0xF6, 0x2A, 0x43, 0x4B, - 0x17, 0xB0, 0xF5, 0xEF, 0x05, 0x93, 0xFC, 0xCB, 0x01, 0x3D, 0xFF, - 0x34, 0x00, 0xFE, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xD4, 0xFF, 0xBF, - 0x00, 0xEB, 0xFD, 0xF3, 0x04, 0xCF, 0xF3, 0x98, 0x3E, 0xF3, 0x1E, - 0xB9, 0xF3, 0xB2, 0x06, 0x48, 0xFC, 0xE4, 0x01, 0x36, 0xFF, 0x36, - 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x16, 0x00, 0x96, 0xFF, 0x39, 0x01, - 0x1F, 0xFD, 0x28, 0x06, 0x2A, 0xF2, 0xF2, 0x38, 0xA0, 0x26, 0x4B, - 0xF2, 0x1C, 0x07, 0x32, 0xFC, 0xE0, 0x01, 0x3C, 0xFF, 0x35, 0x00, - 0xFD, 0xFF, 0xFD, 0xFF, 0x26, 0x00, 0x67, 0xFF, 0x94, 0x01, 0x90, - 0xFC, 0xE5, 0x06, 0x81, 0xF1, 0x6B, 0x32, 0x11, 0x2E, 0x8E, 0xF1, - 0x1D, 0x07, 0x58, 0xFC, 0xBC, 0x01, 0x52, 0xFF, 0x2E, 0x00, 0xFD, - 0xFF, 0xFD, 0xFF, 0x31, 0x00, 0x48, 0xFF, 0xCE, 0x01, 0x42, 0xFC, - 0x2A, 0x07, 0xBF, 0xF1, 0x40, 0x2B, 0x05, 0x35, 0xA6, 0xF1, 0xAB, - 0x06, 0xBF, 0xFC, 0x75, 0x01, 0x77, 0xFF, 0x21, 0x00, 0xFE, 0xFF, - 0xFD, 0xFF, 0x36, 0x00, 0x38, 0xFF, 0xE5, 0x01, 0x33, 0xFC, 0xFF, - 0x06, 0xC4, 0xF2, 0xB0, 0x23, 0x3B, 0x3B, 0xAD, 0xF2, 0xBF, 0x05, - 0x66, 0xFD, 0x0E, 0x01, 0xAC, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFE, - 0xFF, 0x36, 0x00, 0x37, 0xFF, 0xDE, 0x01, 0x5F, 0xFC, 0x70, 0x06, - 0x6C, 0xF4, 0xFD, 0x1B, 0x7D, 0x40, 0xB7, 0xF4, 0x5D, 0x04, 0x49, - 0xFE, 0x88, 0x00, 0xEF, 0xFF, 0xF5, 0xFF, 0x04, 0x00, 0xFF, 0xFF, - 0x32, 0x00, 0x43, 0xFF, 0xBA, 0x01, 0xBC, 0xFC, 0x90, 0x05, 0x8E, - 0xF6, 0x68, 0x14, 0x99, 0x44, 0xCD, 0xF7, 0x8F, 0x02, 0x60, 0xFF, - 0xEA, 0xFF, 0x3E, 0x00, 0xD7, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x2B, - 0x00, 0x59, 0xFF, 0x81, 0x01, 0x42, 0xFD, 0x72, 0x04, 0xFF, 0xF8, - 0x2D, 0x0D, 0x69, 0x47, 0xEB, 0xFB, 0x63, 0x00, 0x9D, 0x00, 0x3C, - 0xFF, 0x93, 0x00, 0xB6, 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00, - 0x76, 0xFF, 0x37, 0x01, 0xE4, 0xFD, 0x2C, 0x03, 0x94, 0xFB, 0x83, - 0x06, 0xCE, 0x48, 0x05, 0x01, 0xF5, 0xFD, 0xF0, 0x01, 0x87, 0xFE, - 0xEA, 0x00, 0x94, 0xFF, 0x1A, 0x00, 0x1A, 0x00, 0x96, 0xFF, 0xE3, - 0x00, 0x95, 0xFE, 0xD5, 0x01, 0x26, 0xFE, 0x98, 0x00, 0xBF, 0x48, - 0x00, 0x07, 0x61, 0xFB, 0x46, 0x03, 0xD6, 0xFD, 0x3D, 0x01, 0x73, - 0xFF, 0x23, 0x00, 0x00, 0x00, 0x11, 0x00, 0xB9, 0xFF, 0x8C, 0x00, - 0x4A, 0xFF, 0x83, 0x00, 0x91, 0x00, 0x91, 0xFB, 0x3D, 0x47, 0xB7, - 0x0D, 0xCD, 0xF8, 0x89, 0x04, 0x36, 0xFD, 0x86, 0x01, 0x57, 0xFF, - 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xD9, 0xFF, 0x37, 0x00, 0xF7, - 0xFF, 0x49, 0xFF, 0xB6, 0x02, 0x86, 0xF7, 0x53, 0x44, 0xFB, 0x14, - 0x61, 0xF6, 0xA4, 0x05, 0xB4, 0xFC, 0xBE, 0x01, 0x42, 0xFF, 0x32, - 0x00, 0xFF, 0xFF, 0x04, 0x00, 0xF7, 0xFF, 0xEA, 0xFF, 0x93, 0x00, - 0x36, 0xFE, 0x7D, 0x04, 0x85, 0xF4, 0x1F, 0x40, 0x94, 0x1C, 0x47, - 0xF4, 0x7E, 0x06, 0x5A, 0xFC, 0xDF, 0x01, 0x37, 0xFF, 0x36, 0x00, - 0xFE, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0xA8, 0xFF, 0x17, 0x01, 0x57, - 0xFD, 0xD6, 0x05, 0x90, 0xF2, 0xC8, 0x3A, 0x46, 0x24, 0xAA, 0xF2, - 0x06, 0x07, 0x32, 0xFC, 0xE5, 0x01, 0x39, 0xFF, 0x36, 0x00, 0xFD, - 0xFF, 0xFE, 0xFF, 0x22, 0x00, 0x74, 0xFF, 0x7C, 0x01, 0xB5, 0xFC, - 0xB8, 0x06, 0x9C, 0xF1, 0x81, 0x34, 0xD1, 0x2B, 0xB3, 0xF1, 0x29, - 0x07, 0x46, 0xFC, 0xCA, 0x01, 0x4A, 0xFF, 0x30, 0x00, 0xFD, 0xFF, - 0xFD, 0xFF, 0x2E, 0x00, 0x50, 0xFF, 0xC0, 0x01, 0x53, 0xFC, 0x21, - 0x07, 0x96, 0xF1, 0x82, 0x2D, 0xF2, 0x32, 0x86, 0xF1, 0xDB, 0x06, - 0x99, 0xFC, 0x8E, 0x01, 0x6A, 0xFF, 0x25, 0x00, 0xFD, 0xFF, 0xFD, - 0xFF, 0x35, 0x00, 0x3B, 0xFF, 0xE2, 0x01, 0x31, 0xFC, 0x17, 0x07, - 0x61, 0xF2, 0x0A, 0x26, 0x6A, 0x39, 0x41, 0xF2, 0x15, 0x06, 0x2C, - 0xFD, 0x31, 0x01, 0x9B, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFE, 0xFF, - 0x36, 0x00, 0x36, 0xFF, 0xE3, 0x01, 0x4C, 0xFC, 0xA6, 0x06, 0xDB, - 0xF3, 0x5B, 0x1E, 0xFC, 0x3E, 0xFA, 0xF3, 0xD7, 0x04, 0xFD, 0xFD, - 0xB4, 0x00, 0xD9, 0xFF, 0xFD, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33, - 0x00, 0x3E, 0xFF, 0xC8, 0x01, 0x9B, 0xFC, 0xDD, 0x05, 0xDC, 0xF5, - 0xB6, 0x16, 0x77, 0x43, 0xBD, 0xF6, 0x28, 0x03, 0x05, 0xFF, 0x1D, - 0x00, 0x25, 0x00, 0xE1, 0xFF, 0x08, 0x00, 0xFF, 0xFF, 0x2D, 0x00, - 0x51, 0xFF, 0x95, 0x01, 0x15, 0xFD, 0xCF, 0x04, 0x39, 0xF8, 0x59, - 0x0F, 0xAF, 0x46, 0x8B, 0xFA, 0x17, 0x01, 0x38, 0x00, 0x73, 0xFF, - 0x78, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x25, 0x00, 0x6C, - 0xFF, 0x4F, 0x01, 0xB0, 0xFD, 0x93, 0x03, 0xC7, 0xFA, 0x7D, 0x08, - 0x86, 0x48, 0x5A, 0xFF, 0xBA, 0xFE, 0x86, 0x01, 0xBF, 0xFE, 0xCF, - 0x00, 0x9E, 0xFF, 0x17, 0x00, 0x1C, 0x00, 0x8C, 0xFF, 0xFE, 0x00, - 0x5D, 0xFE, 0x3F, 0x02, 0x5E, 0xFD, 0x54, 0x02, 0xEC, 0x48, 0x13, - 0x05, 0x2E, 0xFC, 0xDE, 0x02, 0x0C, 0xFE, 0x24, 0x01, 0x7D, 0xFF, - 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0xAE, 0xFF, 0xA7, 0x00, 0x12, - 0xFF, 0xEA, 0x00, 0xD9, 0xFF, 0x03, 0xFD, 0xDC, 0x47, 0x95, 0x0B, - 0x96, 0xF9, 0x29, 0x04, 0x65, 0xFD, 0x71, 0x01, 0x5F, 0xFF, 0x29, - 0x00, 0x00, 0x00, 0x0C, 0x00, 0xD0, 0xFF, 0x51, 0x00, 0xC3, 0xFF, - 0xA6, 0xFF, 0x16, 0x02, 0xA9, 0xF8, 0x5C, 0x45, 0xB2, 0x12, 0x19, - 0xF7, 0x52, 0x05, 0xD8, 0xFC, 0xAF, 0x01, 0x47, 0xFF, 0x30, 0x00, - 0xFF, 0xFF, 0x06, 0x00, 0xEE, 0xFF, 0x01, 0x00, 0x66, 0x00, 0x85, - 0xFE, 0xFC, 0x03, 0x55, 0xF5, 0x8C, 0x41, 0x38, 0x1A, 0xE1, 0xF4, - 0x43, 0x06, 0x70, 0xFC, 0xD8, 0x01, 0x39, 0xFF, 0x35, 0x00, 0xFE, - 0xFF, 0x01, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0xF1, 0x00, 0x96, 0xFD, - 0x78, 0x05, 0x0E, 0xF3, 0x8A, 0x3C, 0xEA, 0x21, 0x19, 0xF3, 0xE6, - 0x06, 0x38, 0xFC, 0xE6, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, - 0xFE, 0xFF, 0x1D, 0x00, 0x82, 0xFF, 0x60, 0x01, 0xE0, 0xFC, 0x7F, - 0x06, 0xCC, 0xF1, 0x85, 0x36, 0x87, 0x29, 0xEB, 0xF1, 0x2A, 0x07, - 0x39, 0xFC, 0xD6, 0x01, 0x43, 0xFF, 0x33, 0x00, 0xFD, 0xFF, 0xFD, - 0xFF, 0x2B, 0x00, 0x59, 0xFF, 0xAE, 0x01, 0x6A, 0xFC, 0x0D, 0x07, - 0x80, 0xF1, 0xB8, 0x2F, 0xCF, 0x30, 0x7D, 0xF1, 0xFF, 0x06, 0x78, - 0xFC, 0xA5, 0x01, 0x5F, 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, - 0x34, 0x00, 0x40, 0xFF, 0xDB, 0x01, 0x35, 0xFC, 0x26, 0x07, 0x0E, - 0xF2, 0x60, 0x28, 0x82, 0x37, 0xED, 0xF1, 0x5E, 0x06, 0xF8, 0xFC, - 0x51, 0x01, 0x8A, 0xFF, 0x1A, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, - 0x00, 0x36, 0xFF, 0xE6, 0x01, 0x3E, 0xFC, 0xD3, 0x06, 0x56, 0xF3, - 0xBA, 0x20, 0x61, 0x3D, 0x56, 0xF3, 0x45, 0x05, 0xB7, 0xFD, 0xDE, - 0x00, 0xC5, 0xFF, 0x05, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x35, 0x00, - 0x3A, 0xFF, 0xD3, 0x01, 0x7D, 0xFC, 0x23, 0x06, 0x32, 0xF5, 0x0C, - 0x19, 0x38, 0x42, 0xC7, 0xF5, 0xB8, 0x03, 0xAF, 0xFE, 0x4E, 0x00, - 0x0C, 0x00, 0xEA, 0xFF, 0x06, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4A, - 0xFF, 0xA7, 0x01, 0xEC, 0xFC, 0x28, 0x05, 0x77, 0xF7, 0x92, 0x11, - 0xD7, 0x45, 0x43, 0xF9, 0xC3, 0x01, 0xD6, 0xFF, 0xA9, 0xFF, 0x5E, - 0x00, 0xCB, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x28, 0x00, 0x63, 0xFF, - 0x66, 0x01, 0x7D, 0xFD, 0xF8, 0x03, 0xFB, 0xF9, 0x89, 0x0A, 0x1D, - 0x48, 0xC5, 0xFD, 0x7A, 0xFF, 0x1D, 0x01, 0xF7, 0xFE, 0xB4, 0x00, - 0xA9, 0xFF, 0x15, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x82, 0xFF, 0x18, - 0x01, 0x27, 0xFE, 0xA9, 0x02, 0x94, 0xFC, 0x24, 0x04, 0xF5, 0x48, - 0x39, 0x03, 0xF9, 0xFC, 0x74, 0x02, 0x42, 0xFE, 0x0B, 0x01, 0x87, - 0xFF, 0x1E, 0x00, 0x16, 0x00, 0xA4, 0xFF, 0xC2, 0x00, 0xDB, 0xFE, - 0x52, 0x01, 0x1B, 0xFF, 0x8D, 0xFE, 0x57, 0x48, 0x81, 0x09, 0x61, - 0xFA, 0xC6, 0x03, 0x96, 0xFD, 0x5B, 0x01, 0x68, 0xFF, 0x26, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0xC6, 0xFF, 0x6B, 0x00, 0x8E, 0xFF, 0x06, - 0x00, 0x6E, 0x01, 0xE4, 0xF9, 0x48, 0x46, 0x75, 0x10, 0xD7, 0xF7, - 0xFC, 0x04, 0x00, 0xFD, 0x9E, 0x01, 0x4E, 0xFF, 0x2E, 0x00, 0xFF, - 0xFF, 0x07, 0x00, 0xE5, 0xFF, 0x18, 0x00, 0x36, 0x00, 0xD9, 0xFE, - 0x71, 0x03, 0x3F, 0xF6, 0xDB, 0x42, 0xE0, 0x17, 0x86, 0xF5, 0x00, - 0x06, 0x8C, 0xFC, 0xCE, 0x01, 0x3C, 0xFF, 0x34, 0x00, 0xFE, 0xFF, - 0x02, 0x00, 0x01, 0x00, 0xCF, 0xFF, 0xC9, 0x00, 0xDA, 0xFD, 0x0F, - 0x05, 0xA5, 0xF3, 0x31, 0x3E, 0x8A, 0x1F, 0x97, 0xF3, 0xBD, 0x06, - 0x44, 0xFC, 0xE5, 0x01, 0x36, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFF, - 0xFF, 0x17, 0x00, 0x92, 0xFF, 0x41, 0x01, 0x11, 0xFD, 0x3B, 0x06, - 0x14, 0xF2, 0x78, 0x38, 0x36, 0x27, 0x35, 0xF2, 0x20, 0x07, 0x33, - 0xFC, 0xDF, 0x01, 0x3E, 0xFF, 0x34, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, - 0x28, 0x00, 0x64, 0xFF, 0x9A, 0x01, 0x88, 0xFC, 0xEE, 0x06, 0x7E, - 0xF1, 0xE3, 0x31, 0x9F, 0x2E, 0x88, 0xF1, 0x19, 0x07, 0x5E, 0xFC, - 0xB7, 0x01, 0x54, 0xFF, 0x2D, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x32, - 0x00, 0x46, 0xFF, 0xD1, 0x01, 0x3F, 0xFC, 0x2B, 0x07, 0xCD, 0xF1, - 0xAE, 0x2A, 0x86, 0x35, 0xB1, 0xF1, 0x9D, 0x06, 0xCA, 0xFC, 0x6E, - 0x01, 0x7B, 0xFF, 0x20, 0x00, 0xFE, 0xFF, 0xFD, 0xFF, 0x36, 0x00, - 0x38, 0xFF, 0xE6, 0x01, 0x35, 0xFC, 0xF7, 0x06, 0xE0, 0xF2, 0x18, - 0x23, 0xAB, 0x3B, 0xCC, 0xF2, 0xA8, 0x05, 0x76, 0xFD, 0x04, 0x01, - 0xB1, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x38, - 0xFF, 0xDC, 0x01, 0x64, 0xFC, 0x62, 0x06, 0x93, 0xF4, 0x66, 0x1B, - 0xD9, 0x40, 0xEA, 0xF4, 0x3E, 0x04, 0x5D, 0xFE, 0x7D, 0x00, 0xF5, - 0xFF, 0xF3, 0xFF, 0x05, 0x00, 0xFF, 0xFF, 0x31, 0x00, 0x44, 0xFF, - 0xB7, 0x01, 0xC5, 0xFC, 0x7C, 0x05, 0xBC, 0xF6, 0xD5, 0x13, 0xDC, - 0x44, 0x14, 0xF8, 0x67, 0x02, 0x77, 0xFF, 0xDD, 0xFF, 0x44, 0x00, - 0xD5, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x5B, 0xFF, 0x7C, - 0x01, 0x4E, 0xFD, 0x5A, 0x04, 0x31, 0xF9, 0xA4, 0x0C, 0x90, 0x47, - 0x47, 0xFC, 0x36, 0x00, 0xB6, 0x00, 0x2E, 0xFF, 0x99, 0x00, 0xB3, - 0xFF, 0x12, 0x00, 0x00, 0x00, 0x22, 0x00, 0x78, 0xFF, 0x31, 0x01, - 0xF1, 0xFD, 0x12, 0x03, 0xC7, 0xFB, 0x07, 0x06, 0xDB, 0x48, 0x73, - 0x01, 0xC3, 0xFD, 0x0A, 0x02, 0x79, 0xFE, 0xF1, 0x00, 0x91, 0xFF, - 0x1B, 0x00, 0x19, 0x00, 0x99, 0xFF, 0xDD, 0x00, 0xA3, 0xFE, 0xBB, - 0x01, 0x58, 0xFE, 0x2D, 0x00, 0xAF, 0x48, 0x7E, 0x07, 0x2E, 0xFB, - 0x60, 0x03, 0xC9, 0xFD, 0x43, 0x01, 0x71, 0xFF, 0x24, 0x00, 0x00, - 0x00, 0x10, 0x00, 0xBB, 0xFF, 0x85, 0x00, 0x58, 0xFF, 0x6A, 0x00, - 0xBE, 0x00, 0x38, 0xFB, 0x0F, 0x47, 0x42, 0x0E, 0x9B, 0xF8, 0xA1, - 0x04, 0x2B, 0xFD, 0x8B, 0x01, 0x55, 0xFF, 0x2C, 0x00, 0xFF, 0xFF, - 0x09, 0x00, 0xDC, 0xFF, 0x31, 0x00, 0x04, 0x00, 0x32, 0xFF, 0xDC, - 0x02, 0x42, 0xF7, 0x0B, 0x44, 0x8E, 0x15, 0x34, 0xF6, 0xB7, 0x05, - 0xAB, 0xFC, 0xC1, 0x01, 0x40, 0xFF, 0x33, 0x00, 0xFF, 0xFF, 0x04, - 0x00, 0xF9, 0xFF, 0xE4, 0xFF, 0x9F, 0x00, 0x23, 0xFE, 0x9B, 0x04, - 0x55, 0xF4, 0xC0, 0x3F, 0x2C, 0x1D, 0x22, 0xF4, 0x8C, 0x06, 0x55, - 0xFC, 0xE1, 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFE, 0xFF, 0x00, 0x00, - 0x11, 0x00, 0xA3, 0xFF, 0x20, 0x01, 0x49, 0xFD, 0xEB, 0x05, 0x74, - 0xF2, 0x54, 0x3A, 0xDD, 0x24, 0x91, 0xF2, 0x0C, 0x07, 0x32, 0xFC, - 0xE4, 0x01, 0x3A, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x23, - 0x00, 0x71, 0xFF, 0x82, 0x01, 0xAB, 0xFC, 0xC4, 0x06, 0x93, 0xF1, - 0xFD, 0x33, 0x62, 0x2C, 0xA8, 0xF1, 0x27, 0x07, 0x4A, 0xFC, 0xC7, - 0x01, 0x4C, 0xFF, 0x30, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2F, 0x00, - 0x4E, 0xFF, 0xC3, 0x01, 0x4E, 0xFC, 0x24, 0x07, 0x9E, 0xF1, 0xF2, - 0x2C, 0x78, 0x33, 0x8C, 0xF1, 0xD0, 0x06, 0xA2, 0xFC, 0x88, 0x01, - 0x6D, 0xFF, 0x24, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x35, 0x00, 0x3B, - 0xFF, 0xE3, 0x01, 0x31, 0xFC, 0x12, 0x07, 0x79, 0xF2, 0x73, 0x25, - 0xDF, 0x39, 0x5A, 0xF2, 0x00, 0x06, 0x3A, 0xFD, 0x28, 0x01, 0x9F, - 0xFF, 0x13, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x36, 0x00, 0x36, 0xFF, - 0xE2, 0x01, 0x50, 0xFC, 0x99, 0x06, 0xFE, 0xF3, 0xC3, 0x1D, 0x5E, - 0x3F, 0x27, 0xF4, 0xB9, 0x04, 0x10, 0xFE, 0xA9, 0x00, 0xDF, 0xFF, - 0xFB, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x33, 0x00, 0x3F, 0xFF, 0xC5, - 0x01, 0xA3, 0xFC, 0xCA, 0x05, 0x07, 0xF6, 0x22, 0x16, 0xC3, 0x43, - 0xFE, 0xF6, 0x02, 0x03, 0x1B, 0xFF, 0x11, 0x00, 0x2B, 0x00, 0xDE, - 0xFF, 0x09, 0x00, 0xFF, 0xFF, 0x2D, 0x00, 0x53, 0xFF, 0x90, 0x01, - 0x20, 0xFD, 0xB8, 0x04, 0x6A, 0xF8, 0xCD, 0x0E, 0xE1, 0x46, 0xE1, - 0xFA, 0xEB, 0x00, 0x51, 0x00, 0x65, 0xFF, 0x7F, 0x00, 0xBE, 0xFF, - 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x6E, 0xFF, 0x49, 0x01, 0xBC, - 0xFD, 0x7A, 0x03, 0xFA, 0xFA, 0xFD, 0x07, 0x9C, 0x48, 0xC3, 0xFF, - 0x89, 0xFE, 0xA1, 0x01, 0xB1, 0xFE, 0xD6, 0x00, 0x9C, 0xFF, 0x18, - 0x00, 0x1C, 0x00, 0x8F, 0xFF, 0xF7, 0x00, 0x6B, 0xFE, 0x25, 0x02, - 0x91, 0xFD, 0xE3, 0x01, 0xE5, 0x48, 0x8D, 0x05, 0xFB, 0xFB, 0xF8, - 0x02, 0xFE, 0xFD, 0x2B, 0x01, 0x7A, 0xFF, 0x21, 0x00, 0x00, 0x00, - 0x13, 0x00, 0xB1, 0xFF, 0xA0, 0x00, 0x20, 0xFF, 0xD0, 0x00, 0x07, - 0x00, 0xA4, 0xFC, 0xB6, 0x47, 0x1C, 0x0C, 0x63, 0xF9, 0x42, 0x04, - 0x59, 0xFD, 0x76, 0x01, 0x5D, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x0B, - 0x00, 0xD2, 0xFF, 0x4A, 0x00, 0xD0, 0xFF, 0x8E, 0xFF, 0x3F, 0x02, - 0x5E, 0xF8, 0x1E, 0x45, 0x44, 0x13, 0xEA, 0xF6, 0x67, 0x05, 0xCF, - 0xFC, 0xB3, 0x01, 0x46, 0xFF, 0x31, 0x00, 0xFF, 0xFF, 0x05, 0x00, - 0xF0, 0xFF, 0xFB, 0xFF, 0x71, 0x00, 0x71, 0xFE, 0x1D, 0x04, 0x1F, - 0xF5, 0x32, 0x41, 0xCE, 0x1A, 0xBA, 0xF4, 0x53, 0x06, 0x6A, 0xFC, - 0xDA, 0x01, 0x38, 0xFF, 0x35, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0x0A, - 0x00, 0xB6, 0xFF, 0xFB, 0x00, 0x85, 0xFD, 0x90, 0x05, 0xEC, 0xF2, - 0x1C, 0x3C, 0x81, 0x22, 0xFC, 0xF2, 0xEF, 0x06, 0x36, 0xFC, 0xE6, - 0x01, 0x37, 0xFF, 0x36, 0x00, 0xFD, 0xFF, 0xFE, 0xFF, 0x1E, 0x00, - 0x7F, 0xFF, 0x67, 0x01, 0xD5, 0xFC, 0x8E, 0x06, 0xBE, 0xF1, 0x06, - 0x36, 0x1A, 0x2A, 0xDC, 0xF1, 0x2A, 0x07, 0x3C, 0xFC, 0xD3, 0x01, - 0x44, 0xFF, 0x32, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x2C, 0x00, 0x57, - 0xFF, 0xB3, 0x01, 0x64, 0xFC, 0x13, 0x07, 0x83, 0xF1, 0x2C, 0x2F, - 0x5A, 0x31, 0x7D, 0xF1, 0xF7, 0x06, 0x80, 0xFC, 0x9F, 0x01, 0x61, - 0xFF, 0x29, 0x00, 0xFD, 0xFF, 0xFD, 0xFF, 0x34, 0x00, 0x3F, 0xFF, - 0xDD, 0x01, 0x34, 0xFC, 0x23, 0x07, 0x21, 0xF2, 0xCB, 0x27, 0xFE, - 0x37, 0x00, 0xF2, 0x4D, 0x06, 0x04, 0xFD, 0x49, 0x01, 0x8E, 0xFF, - 0x19, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0x36, 0x00, 0x36, 0xFF, 0xE6, - 0x01, 0x41, 0xFC, 0xC8, 0x06, 0x76, 0xF3, 0x22, 0x20, 0xCA, 0x3D, - 0x7D, 0xF3, 0x2A, 0x05, 0xC8, 0xFD, 0xD4, 0x00, 0xCA, 0xFF, 0x03, - 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x34, 0x00, 0x3B, 0xFF, 0xD1, 0x01, - 0x84, 0xFC, 0x12, 0x06, 0x5C, 0xF5, 0x76, 0x18, 0x89, 0x42, 0x02, - 0xF6, 0x94, 0x03, 0xC4, 0xFE, 0x42, 0x00, 0x12, 0x00, 0xE8, 0xFF, - 0x07, 0x00, 0xFF, 0xFF, 0x2F, 0x00, 0x4C, 0xFF, 0xA2, 0x01, 0xF6, - 0xFC, 0x12, 0x05, 0xA7, 0xF7, 0x03, 0x11, 0x10, 0x46, 0x93, 0xF9, - 0x98, 0x01, 0xEE, 0xFF, 0x9B, 0xFF, 0x64, 0x00, 0xC8, 0xFF, 0x0E, - 0x00, 0x00, 0x00, 0x27, 0x00, 0x65, 0xFF, 0x60, 0x01, 0x8A, 0xFD, - 0xDF, 0x03, 0x2E, 0xFA, 0x04, 0x0A, 0x3A, 0x48, 0x28, 0xFE, 0x4B, - 0xFF, 0x38, 0x01, 0xE9, 0xFE, 0xBB, 0x00, 0xA6, 0xFF, 0x16, 0x00, - 0x00, 0x00, 0x1E, 0x00, 0x84, 0xFF, 0x11, 0x01, 0x34, 0xFE, 0x8F, - 0x02, 0xC7, 0xFC, 0xAE, 0x03, 0xF7, 0x48, 0xAE, 0x03, 0xC7, 0xFC, - 0x8F, 0x02, 0x34, 0xFE, 0x11, 0x01, 0x84, 0xFF, 0x1E, 0x00, 0x00, - 0x00, 0xF4, 0xFF, 0x1A, 0x00, 0xFF, 0x00, 0x07, 0x03, 0x16, 0x06, - 0x7C, 0x09, 0x2A, 0x0C, 0x2E, 0x0D, 0x2A, 0x0C, 0x7C, 0x09, 0x16, - 0x06, 0x07, 0x03, 0xFF, 0x00, 0x1A, 0x00, 0xF4, 0xFF, 0xF2, 0xFF, - 0xA0, 0xFF, 0x71, 0xFF, 0x71, 0x00, 0x86, 0x03, 0x73, 0x08, 0x88, - 0x0D, 0x78, 0x10, 0xC9, 0x0F, 0xD5, 0x0B, 0x8B, 0x06, 0x28, 0x02, - 0xDF, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDC, - 0xFF, 0x80, 0xFF, 0x9A, 0xFF, 0x46, 0x01, 0x1E, 0x05, 0x5A, 0x0A, - 0xED, 0x0E, 0xAA, 0x10, 0xAF, 0x0E, 0xFD, 0x09, 0xCB, 0x04, 0x18, - 0x01, 0x8E, 0xFF, 0x85, 0xFF, 0xE1, 0xFF, 0xFC, 0xFF, 0xBD, 0xFF, - 0x6D, 0xFF, 0xF6, 0xFF, 0x65, 0x02, 0xE5, 0x06, 0x2B, 0x0C, 0xF3, - 0x0F, 0x60, 0x10, 0x3B, 0x0D, 0x16, 0x08, 0x3F, 0x03, 0x50, 0x00, - 0x6E, 0xFF, 0xA7, 0xFF, 0xF5, 0xFF, 0xEF, 0xFF, 0x9A, 0xFF, 0x75, - 0xFF, 0x91, 0x00, 0xC9, 0x03, 0xC8, 0x08, 0xCC, 0x0D, 0x89, 0x10, - 0x9F, 0x0F, 0x85, 0x0B, 0x3B, 0x06, 0xF4, 0x01, 0xCD, 0xFF, 0x72, - 0xFF, 0xC9, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD7, 0xFF, 0x7B, 0xFF, - 0xA5, 0xFF, 0x73, 0x01, 0x6A, 0x05, 0xAD, 0x0A, 0x21, 0x0F, 0xA6, - 0x10, 0x74, 0x0E, 0xA9, 0x09, 0x83, 0x04, 0xF0, 0x00, 0x85, 0xFF, - 0x8B, 0xFF, 0xE5, 0xFF, 0xFA, 0xFF, 0xB7, 0xFF, 0x6C, 0xFF, 0x0C, - 0x00, 0x9D, 0x02, 0x37, 0x07, 0x78, 0x0C, 0x15, 0x10, 0x47, 0x10, - 0xF3, 0x0C, 0xC2, 0x07, 0x01, 0x03, 0x35, 0x00, 0x6D, 0xFF, 0xAD, - 0xFF, 0xF7, 0xFF, 0xEB, 0xFF, 0x94, 0xFF, 0x7A, 0xFF, 0xB3, 0x00, - 0x0D, 0x04, 0x1C, 0x09, 0x0D, 0x0E, 0x97, 0x10, 0x73, 0x0F, 0x35, - 0x0B, 0xEB, 0x05, 0xC1, 0x01, 0xBD, 0xFF, 0x75, 0xFF, 0xCE, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x77, 0xFF, 0xB3, 0xFF, 0xA1, - 0x01, 0xB7, 0x05, 0xFF, 0x0A, 0x53, 0x0F, 0x9E, 0x10, 0x37, 0x0E, - 0x55, 0x09, 0x3B, 0x04, 0xCB, 0x00, 0x7E, 0xFF, 0x90, 0xFF, 0xE9, - 0xFF, 0xF8, 0xFF, 0xB1, 0xFF, 0x6C, 0xFF, 0x24, 0x00, 0xD8, 0x02, - 0x8A, 0x07, 0xC2, 0x0C, 0x34, 0x10, 0x2A, 0x10, 0xAA, 0x0C, 0x6F, - 0x07, 0xC4, 0x02, 0x1C, 0x00, 0x6C, 0xFF, 0xB3, 0xFF, 0xF9, 0xFF, - 0xE8, 0xFF, 0x8E, 0xFF, 0x80, 0xFF, 0xD7, 0x00, 0x53, 0x04, 0x71, - 0x09, 0x4C, 0x0E, 0xA1, 0x10, 0x43, 0x0F, 0xE3, 0x0A, 0x9D, 0x05, - 0x91, 0x01, 0xAE, 0xFF, 0x79, 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF, - 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC2, 0xFF, 0xD2, 0x01, 0x06, 0x06, - 0x50, 0x0B, 0x82, 0x0F, 0x93, 0x10, 0xF8, 0x0D, 0x00, 0x09, 0xF6, - 0x03, 0xA7, 0x00, 0x78, 0xFF, 0x96, 0xFF, 0xEC, 0xFF, 0xF6, 0xFF, - 0xAB, 0xFF, 0x6D, 0xFF, 0x3E, 0x00, 0x15, 0x03, 0xDE, 0x07, 0x0B, - 0x0D, 0x50, 0x10, 0x0A, 0x10, 0x5E, 0x0C, 0x1C, 0x07, 0x8A, 0x02, - 0x04, 0x00, 0x6C, 0xFF, 0xB9, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF, 0x89, - 0xFF, 0x88, 0xFF, 0xFD, 0x00, 0x9B, 0x04, 0xC5, 0x09, 0x88, 0x0E, - 0xA8, 0x10, 0x10, 0x0F, 0x91, 0x0A, 0x50, 0x05, 0x64, 0x01, 0xA1, - 0xFF, 0x7D, 0xFF, 0xD9, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF, - 0x71, 0xFF, 0xD3, 0xFF, 0x05, 0x02, 0x55, 0x06, 0xA0, 0x0B, 0xAD, - 0x0F, 0x84, 0x10, 0xB6, 0x0D, 0xAC, 0x08, 0xB3, 0x03, 0x86, 0x00, - 0x74, 0xFF, 0x9C, 0xFF, 0xF0, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF, 0x6F, - 0xFF, 0x5A, 0x00, 0x54, 0x03, 0x32, 0x08, 0x52, 0x0D, 0x68, 0x10, - 0xE6, 0x0F, 0x11, 0x0C, 0xCA, 0x06, 0x52, 0x02, 0xEF, 0xFF, 0x6E, - 0xFF, 0xBF, 0xFF, 0xFC, 0xFF, 0xDF, 0xFF, 0x84, 0xFF, 0x91, 0xFF, - 0x25, 0x01, 0xE4, 0x04, 0x19, 0x0A, 0xC2, 0x0E, 0xAA, 0x10, 0xDA, - 0x0E, 0x3E, 0x0A, 0x05, 0x05, 0x38, 0x01, 0x96, 0xFF, 0x81, 0xFF, - 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE6, - 0xFF, 0x3A, 0x02, 0xA6, 0x06, 0xEF, 0x0B, 0xD6, 0x0F, 0x71, 0x10, - 0x71, 0x0D, 0x57, 0x08, 0x71, 0x03, 0x67, 0x00, 0x70, 0xFF, 0xA2, - 0xFF, 0xF3, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x78, 0x00, - 0x95, 0x03, 0x86, 0x08, 0x98, 0x0D, 0x7C, 0x10, 0xC0, 0x0F, 0xC3, - 0x0B, 0x79, 0x06, 0x1C, 0x02, 0xDB, 0xFF, 0x70, 0xFF, 0xC5, 0xFF, - 0xFE, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9C, 0xFF, 0x50, - 0x01, 0x2F, 0x05, 0x6C, 0x0A, 0xF9, 0x0E, 0xA9, 0x10, 0xA2, 0x0E, - 0xEA, 0x09, 0xBB, 0x04, 0x0F, 0x01, 0x8C, 0xFF, 0x87, 0xFF, 0xE2, - 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xFA, 0xFF, 0x71, 0x02, - 0xF7, 0x06, 0x3C, 0x0C, 0xFB, 0x0F, 0x5B, 0x10, 0x2B, 0x0D, 0x03, - 0x08, 0x31, 0x03, 0x4A, 0x00, 0x6E, 0xFF, 0xA8, 0xFF, 0xF5, 0xFF, - 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x98, 0x00, 0xD8, 0x03, 0xDB, - 0x08, 0xDB, 0x0D, 0x8D, 0x10, 0x96, 0x0F, 0x73, 0x0B, 0x29, 0x06, - 0xE8, 0x01, 0xC9, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF, 0x00, - 0x00, 0xD6, 0xFF, 0x7A, 0xFF, 0xA8, 0xFF, 0x7D, 0x01, 0x7B, 0x05, - 0xBF, 0x0A, 0x2D, 0x0F, 0xA5, 0x10, 0x67, 0x0E, 0x96, 0x09, 0x73, - 0x04, 0xE7, 0x00, 0x84, 0xFF, 0x8C, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF, - 0xB6, 0xFF, 0x6C, 0xFF, 0x11, 0x00, 0xAA, 0x02, 0x4A, 0x07, 0x88, - 0x0C, 0x1C, 0x10, 0x41, 0x10, 0xE3, 0x0C, 0xAF, 0x07, 0xF3, 0x02, - 0x2F, 0x00, 0x6C, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEA, 0xFF, 0x93, - 0xFF, 0x7B, 0xFF, 0xBB, 0x00, 0x1C, 0x04, 0x2F, 0x09, 0x1B, 0x0E, - 0x9A, 0x10, 0x68, 0x0F, 0x23, 0x0B, 0xDA, 0x05, 0xB7, 0x01, 0xB9, - 0xFF, 0x76, 0xFF, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1, 0xFF, - 0x76, 0xFF, 0xB6, 0xFF, 0xAC, 0x01, 0xC8, 0x05, 0x11, 0x0B, 0x5E, - 0x0F, 0x9C, 0x10, 0x29, 0x0E, 0x42, 0x09, 0x2C, 0x04, 0xC2, 0x00, - 0x7D, 0xFF, 0x92, 0xFF, 0xEA, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF, 0x6C, - 0xFF, 0x29, 0x00, 0xE6, 0x02, 0x9D, 0x07, 0xD3, 0x0C, 0x3B, 0x10, - 0x23, 0x10, 0x99, 0x0C, 0x5C, 0x07, 0xB7, 0x02, 0x16, 0x00, 0x6C, - 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8D, 0xFF, 0x82, 0xFF, - 0xDF, 0x00, 0x63, 0x04, 0x84, 0x09, 0x59, 0x0E, 0xA3, 0x10, 0x38, - 0x0F, 0xD1, 0x0A, 0x8C, 0x05, 0x87, 0x01, 0xAB, 0xFF, 0x79, 0xFF, - 0xD5, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC6, - 0xFF, 0xDD, 0x01, 0x17, 0x06, 0x62, 0x0B, 0x8C, 0x0F, 0x90, 0x10, - 0xE9, 0x0D, 0xED, 0x08, 0xE7, 0x03, 0xA0, 0x00, 0x77, 0xFF, 0x97, - 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xA9, 0xFF, 0x6D, 0xFF, 0x44, 0x00, - 0x23, 0x03, 0xF1, 0x07, 0x1B, 0x0D, 0x55, 0x10, 0x02, 0x10, 0x4D, - 0x0C, 0x0A, 0x07, 0x7E, 0x02, 0xFF, 0xFF, 0x6D, 0xFF, 0xBA, 0xFF, - 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x8A, 0xFF, 0x06, 0x01, 0xAB, - 0x04, 0xD8, 0x09, 0x95, 0x0E, 0xA9, 0x10, 0x05, 0x0F, 0x7F, 0x0A, - 0x40, 0x05, 0x5A, 0x01, 0x9F, 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00, - 0x00, 0xFE, 0xFF, 0xC6, 0xFF, 0x70, 0xFF, 0xD7, 0xFF, 0x10, 0x02, - 0x67, 0x06, 0xB1, 0x0B, 0xB7, 0x0F, 0x80, 0x10, 0xA7, 0x0D, 0x99, - 0x08, 0xA4, 0x03, 0x7F, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0, 0xFF, - 0xF3, 0xFF, 0xA3, 0xFF, 0x70, 0xFF, 0x60, 0x00, 0x62, 0x03, 0x45, - 0x08, 0x62, 0x0D, 0x6C, 0x10, 0xDE, 0x0F, 0x00, 0x0C, 0xB8, 0x06, - 0x46, 0x02, 0xEA, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFD, 0xFF, 0x00, - 0x00, 0xDE, 0xFF, 0x83, 0xFF, 0x94, 0xFF, 0x2F, 0x01, 0xF4, 0x04, - 0x2B, 0x0A, 0xCE, 0x0E, 0xAA, 0x10, 0xCE, 0x0E, 0x2B, 0x0A, 0xF4, - 0x04, 0x2F, 0x01, 0x94, 0xFF, 0x83, 0xFF, 0xDE, 0xFF, 0xFD, 0xFF, - 0xC0, 0xFF, 0x6E, 0xFF, 0xEA, 0xFF, 0x46, 0x02, 0xB8, 0x06, 0x00, - 0x0C, 0xDE, 0x0F, 0x6C, 0x10, 0x62, 0x0D, 0x45, 0x08, 0x62, 0x03, - 0x60, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D, - 0xFF, 0x73, 0xFF, 0x7F, 0x00, 0xA4, 0x03, 0x99, 0x08, 0xA7, 0x0D, - 0x80, 0x10, 0xB7, 0x0F, 0xB1, 0x0B, 0x67, 0x06, 0x10, 0x02, 0xD7, - 0xFF, 0x70, 0xFF, 0xC6, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA, 0xFF, - 0x7E, 0xFF, 0x9F, 0xFF, 0x5A, 0x01, 0x40, 0x05, 0x7F, 0x0A, 0x05, - 0x0F, 0xA9, 0x10, 0x95, 0x0E, 0xD8, 0x09, 0xAB, 0x04, 0x06, 0x01, - 0x8A, 0xFF, 0x88, 0xFF, 0xE3, 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D, - 0xFF, 0xFF, 0xFF, 0x7E, 0x02, 0x0A, 0x07, 0x4D, 0x0C, 0x02, 0x10, - 0x55, 0x10, 0x1B, 0x0D, 0xF1, 0x07, 0x23, 0x03, 0x44, 0x00, 0x6D, - 0xFF, 0xA9, 0xFF, 0xF6, 0xFF, 0xED, 0xFF, 0x97, 0xFF, 0x77, 0xFF, - 0xA0, 0x00, 0xE7, 0x03, 0xED, 0x08, 0xE9, 0x0D, 0x90, 0x10, 0x8C, - 0x0F, 0x62, 0x0B, 0x17, 0x06, 0xDD, 0x01, 0xC6, 0xFF, 0x73, 0xFF, - 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x79, 0xFF, 0xAB, - 0xFF, 0x87, 0x01, 0x8C, 0x05, 0xD1, 0x0A, 0x38, 0x0F, 0xA3, 0x10, - 0x59, 0x0E, 0x84, 0x09, 0x63, 0x04, 0xDF, 0x00, 0x82, 0xFF, 0x8D, - 0xFF, 0xE7, 0xFF, 0xF9, 0xFF, 0xB4, 0xFF, 0x6C, 0xFF, 0x16, 0x00, - 0xB7, 0x02, 0x5C, 0x07, 0x99, 0x0C, 0x23, 0x10, 0x3B, 0x10, 0xD3, - 0x0C, 0x9D, 0x07, 0xE6, 0x02, 0x29, 0x00, 0x6C, 0xFF, 0xB0, 0xFF, - 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7D, 0xFF, 0xC2, 0x00, 0x2C, - 0x04, 0x42, 0x09, 0x29, 0x0E, 0x9C, 0x10, 0x5E, 0x0F, 0x11, 0x0B, - 0xC8, 0x05, 0xAC, 0x01, 0xB6, 0xFF, 0x76, 0xFF, 0xD1, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB9, 0xFF, 0xB7, 0x01, - 0xDA, 0x05, 0x23, 0x0B, 0x68, 0x0F, 0x9A, 0x10, 0x1B, 0x0E, 0x2F, - 0x09, 0x1C, 0x04, 0xBB, 0x00, 0x7B, 0xFF, 0x93, 0xFF, 0xEA, 0xFF, - 0xF7, 0xFF, 0xAE, 0xFF, 0x6C, 0xFF, 0x2F, 0x00, 0xF3, 0x02, 0xAF, - 0x07, 0xE3, 0x0C, 0x41, 0x10, 0x1C, 0x10, 0x88, 0x0C, 0x4A, 0x07, - 0xAA, 0x02, 0x11, 0x00, 0x6C, 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE6, - 0xFF, 0x8C, 0xFF, 0x84, 0xFF, 0xE7, 0x00, 0x73, 0x04, 0x96, 0x09, - 0x67, 0x0E, 0xA5, 0x10, 0x2D, 0x0F, 0xBF, 0x0A, 0x7B, 0x05, 0x7D, - 0x01, 0xA8, 0xFF, 0x7A, 0xFF, 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF, - 0xCA, 0xFF, 0x72, 0xFF, 0xC9, 0xFF, 0xE8, 0x01, 0x29, 0x06, 0x73, - 0x0B, 0x96, 0x0F, 0x8D, 0x10, 0xDB, 0x0D, 0xDB, 0x08, 0xD8, 0x03, - 0x98, 0x00, 0x76, 0xFF, 0x99, 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA8, - 0xFF, 0x6E, 0xFF, 0x4A, 0x00, 0x31, 0x03, 0x03, 0x08, 0x2B, 0x0D, - 0x5B, 0x10, 0xFB, 0x0F, 0x3C, 0x0C, 0xF7, 0x06, 0x71, 0x02, 0xFA, - 0xFF, 0x6D, 0xFF, 0xBC, 0xFF, 0xFC, 0xFF, 0xE2, 0xFF, 0x87, 0xFF, - 0x8C, 0xFF, 0x0F, 0x01, 0xBB, 0x04, 0xEA, 0x09, 0xA2, 0x0E, 0xA9, - 0x10, 0xF9, 0x0E, 0x6C, 0x0A, 0x2F, 0x05, 0x50, 0x01, 0x9C, 0xFF, - 0x7F, 0xFF, 0xDB, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF, 0x70, - 0xFF, 0xDB, 0xFF, 0x1C, 0x02, 0x79, 0x06, 0xC3, 0x0B, 0xC0, 0x0F, - 0x7C, 0x10, 0x98, 0x0D, 0x86, 0x08, 0x95, 0x03, 0x78, 0x00, 0x72, - 0xFF, 0x9F, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA2, 0xFF, 0x70, 0xFF, - 0x67, 0x00, 0x71, 0x03, 0x57, 0x08, 0x71, 0x0D, 0x71, 0x10, 0xD6, - 0x0F, 0xEF, 0x0B, 0xA6, 0x06, 0x3A, 0x02, 0xE6, 0xFF, 0x6E, 0xFF, - 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x96, - 0xFF, 0x38, 0x01, 0x05, 0x05, 0x3E, 0x0A, 0xDA, 0x0E, 0xAA, 0x10, - 0xC2, 0x0E, 0x19, 0x0A, 0xE4, 0x04, 0x25, 0x01, 0x91, 0xFF, 0x84, - 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xBF, 0xFF, 0x6E, 0xFF, 0xEF, 0xFF, - 0x52, 0x02, 0xCA, 0x06, 0x11, 0x0C, 0xE6, 0x0F, 0x68, 0x10, 0x52, - 0x0D, 0x32, 0x08, 0x54, 0x03, 0x5A, 0x00, 0x6F, 0xFF, 0xA5, 0xFF, - 0xF4, 0xFF, 0xF0, 0xFF, 0x9C, 0xFF, 0x74, 0xFF, 0x86, 0x00, 0xB3, - 0x03, 0xAC, 0x08, 0xB6, 0x0D, 0x84, 0x10, 0xAD, 0x0F, 0xA0, 0x0B, - 0x55, 0x06, 0x05, 0x02, 0xD3, 0xFF, 0x71, 0xFF, 0xC7, 0xFF, 0xFE, - 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA1, 0xFF, 0x64, 0x01, - 0x50, 0x05, 0x91, 0x0A, 0x10, 0x0F, 0xA8, 0x10, 0x88, 0x0E, 0xC5, - 0x09, 0x9B, 0x04, 0xFD, 0x00, 0x88, 0xFF, 0x89, 0xFF, 0xE4, 0xFF, - 0xFB, 0xFF, 0xB9, 0xFF, 0x6C, 0xFF, 0x04, 0x00, 0x8A, 0x02, 0x1C, - 0x07, 0x5E, 0x0C, 0x0A, 0x10, 0x50, 0x10, 0x0B, 0x0D, 0xDE, 0x07, - 0x15, 0x03, 0x3E, 0x00, 0x6D, 0xFF, 0xAB, 0xFF, 0xF6, 0xFF, 0xEC, - 0xFF, 0x96, 0xFF, 0x78, 0xFF, 0xA7, 0x00, 0xF6, 0x03, 0x00, 0x09, - 0xF8, 0x0D, 0x93, 0x10, 0x82, 0x0F, 0x50, 0x0B, 0x06, 0x06, 0xD2, - 0x01, 0xC2, 0xFF, 0x74, 0xFF, 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0xD4, 0xFF, 0x79, 0xFF, 0xAE, 0xFF, 0x91, 0x01, 0x9D, 0x05, 0xE3, - 0x0A, 0x43, 0x0F, 0xA1, 0x10, 0x4C, 0x0E, 0x71, 0x09, 0x53, 0x04, - 0xD7, 0x00, 0x80, 0xFF, 0x8E, 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB3, - 0xFF, 0x6C, 0xFF, 0x1C, 0x00, 0xC4, 0x02, 0x6F, 0x07, 0xAA, 0x0C, - 0x2A, 0x10, 0x34, 0x10, 0xC2, 0x0C, 0x8A, 0x07, 0xD8, 0x02, 0x24, - 0x00, 0x6C, 0xFF, 0xB1, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x90, 0xFF, - 0x7E, 0xFF, 0xCB, 0x00, 0x3B, 0x04, 0x55, 0x09, 0x37, 0x0E, 0x9E, - 0x10, 0x53, 0x0F, 0xFF, 0x0A, 0xB7, 0x05, 0xA1, 0x01, 0xB3, 0xFF, - 0x77, 0xFF, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x75, - 0xFF, 0xBD, 0xFF, 0xC1, 0x01, 0xEB, 0x05, 0x35, 0x0B, 0x73, 0x0F, - 0x97, 0x10, 0x0D, 0x0E, 0x1C, 0x09, 0x0D, 0x04, 0xB3, 0x00, 0x7A, - 0xFF, 0x94, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAD, 0xFF, 0x6D, 0xFF, - 0x35, 0x00, 0x01, 0x03, 0xC2, 0x07, 0xF3, 0x0C, 0x47, 0x10, 0x15, - 0x10, 0x78, 0x0C, 0x37, 0x07, 0x9D, 0x02, 0x0C, 0x00, 0x6C, 0xFF, - 0xB7, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF, 0xF0, - 0x00, 0x83, 0x04, 0xA9, 0x09, 0x74, 0x0E, 0xA6, 0x10, 0x21, 0x0F, - 0xAD, 0x0A, 0x6A, 0x05, 0x73, 0x01, 0xA5, 0xFF, 0x7B, 0xFF, 0xD7, - 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC9, 0xFF, 0x72, 0xFF, 0xCD, 0xFF, - 0xF4, 0x01, 0x3B, 0x06, 0x85, 0x0B, 0x9F, 0x0F, 0x89, 0x10, 0xCC, - 0x0D, 0xC8, 0x08, 0xC9, 0x03, 0x91, 0x00, 0x75, 0xFF, 0x9A, 0xFF, - 0xEF, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x50, 0x00, 0x3F, - 0x03, 0x16, 0x08, 0x3B, 0x0D, 0x60, 0x10, 0xF3, 0x0F, 0x2B, 0x0C, - 0xE5, 0x06, 0x65, 0x02, 0xF6, 0xFF, 0x6D, 0xFF, 0xBD, 0xFF, 0xFC, - 0xFF, 0xE1, 0xFF, 0x85, 0xFF, 0x8E, 0xFF, 0x18, 0x01, 0xCB, 0x04, - 0xFD, 0x09, 0xAF, 0x0E, 0xAA, 0x10, 0xED, 0x0E, 0x5A, 0x0A, 0x1E, - 0x05, 0x46, 0x01, 0x9A, 0xFF, 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00, - 0xFD, 0xFF, 0xC3, 0xFF, 0x6F, 0xFF, 0xDF, 0xFF, 0x28, 0x02, 0x8B, - 0x06, 0xD5, 0x0B, 0xC9, 0x0F, 0x78, 0x10, 0x88, 0x0D, 0x73, 0x08, - 0x86, 0x03, 0x71, 0x00, 0x71, 0xFF, 0xA0, 0xFF, 0xF2, 0xFF, 0xF2, - 0xFF, 0xA1, 0xFF, 0x71, 0xFF, 0x6E, 0x00, 0x7F, 0x03, 0x6A, 0x08, - 0x81, 0x0D, 0x76, 0x10, 0xCD, 0x0F, 0xDD, 0x0B, 0x94, 0x06, 0x2E, - 0x02, 0xE1, 0xFF, 0x6F, 0xFF, 0xC3, 0xFF, 0xFD, 0xFF, 0x00, 0x00, - 0xDC, 0xFF, 0x80, 0xFF, 0x98, 0xFF, 0x42, 0x01, 0x16, 0x05, 0x50, - 0x0A, 0xE7, 0x0E, 0xAA, 0x10, 0xB5, 0x0E, 0x06, 0x0A, 0xD3, 0x04, - 0x1C, 0x01, 0x8F, 0xFF, 0x85, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF, 0xBE, - 0xFF, 0x6D, 0xFF, 0xF3, 0xFF, 0x5E, 0x02, 0xDC, 0x06, 0x23, 0x0C, - 0xEF, 0x0F, 0x63, 0x10, 0x43, 0x0D, 0x1F, 0x08, 0x46, 0x03, 0x53, - 0x00, 0x6E, 0xFF, 0xA6, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B, 0xFF, - 0x75, 0xFF, 0x8D, 0x00, 0xC1, 0x03, 0xBE, 0x08, 0xC4, 0x0D, 0x88, - 0x10, 0xA4, 0x0F, 0x8E, 0x0B, 0x43, 0x06, 0xF9, 0x01, 0xCF, 0xFF, - 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF, 0x7C, - 0xFF, 0xA4, 0xFF, 0x6E, 0x01, 0x61, 0x05, 0xA3, 0x0A, 0x1C, 0x0F, - 0xA7, 0x10, 0x7B, 0x0E, 0xB2, 0x09, 0x8B, 0x04, 0xF4, 0x00, 0x86, - 0xFF, 0x8A, 0xFF, 0xE4, 0xFF, 0xFA, 0xFF, 0xB8, 0xFF, 0x6C, 0xFF, - 0x09, 0x00, 0x97, 0x02, 0x2E, 0x07, 0x6F, 0x0C, 0x11, 0x10, 0x4A, - 0x10, 0xFB, 0x0C, 0xCB, 0x07, 0x07, 0x03, 0x38, 0x00, 0x6D, 0xFF, - 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF, 0xAF, - 0x00, 0x05, 0x04, 0x13, 0x09, 0x06, 0x0E, 0x96, 0x10, 0x78, 0x0F, - 0x3E, 0x0B, 0xF4, 0x05, 0xC7, 0x01, 0xBF, 0xFF, 0x74, 0xFF, 0xCE, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xFF, 0x78, 0xFF, 0xB1, 0xFF, - 0x9C, 0x01, 0xAE, 0x05, 0xF6, 0x0A, 0x4E, 0x0F, 0x9F, 0x10, 0x3E, - 0x0E, 0x5E, 0x09, 0x43, 0x04, 0xCF, 0x00, 0x7F, 0xFF, 0x90, 0xFF, - 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x21, 0x00, 0xD2, - 0x02, 0x81, 0x07, 0xBA, 0x0C, 0x31, 0x10, 0x2E, 0x10, 0xB2, 0x0C, - 0x78, 0x07, 0xCB, 0x02, 0x1E, 0x00, 0x6C, 0xFF, 0xB2, 0xFF, 0xF9, - 0xFF, 0xE8, 0xFF, 0x8F, 0xFF, 0x80, 0xFF, 0xD3, 0x00, 0x4B, 0x04, - 0x67, 0x09, 0x45, 0x0E, 0xA0, 0x10, 0x48, 0x0F, 0xEC, 0x0A, 0xA6, - 0x05, 0x97, 0x01, 0xB0, 0xFF, 0x78, 0xFF, 0xD3, 0xFF, 0x00, 0x00, - 0xFF, 0xFF, 0xCD, 0xFF, 0x74, 0xFF, 0xC0, 0xFF, 0xCC, 0x01, 0xFD, - 0x05, 0x47, 0x0B, 0x7D, 0x0F, 0x94, 0x10, 0xFF, 0x0D, 0x0A, 0x09, - 0xFE, 0x03, 0xAB, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF, 0xF7, - 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x3B, 0x00, 0x0E, 0x03, 0xD5, 0x07, - 0x03, 0x0D, 0x4D, 0x10, 0x0E, 0x10, 0x67, 0x0C, 0x25, 0x07, 0x91, - 0x02, 0x07, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFB, 0xFF, 0xE4, 0xFF, - 0x89, 0xFF, 0x87, 0xFF, 0xF9, 0x00, 0x93, 0x04, 0xBC, 0x09, 0x82, - 0x0E, 0xA7, 0x10, 0x16, 0x0F, 0x9A, 0x0A, 0x59, 0x05, 0x69, 0x01, - 0xA3, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC8, - 0xFF, 0x71, 0xFF, 0xD1, 0xFF, 0xFF, 0x01, 0x4C, 0x06, 0x97, 0x0B, - 0xA9, 0x0F, 0x86, 0x10, 0xBD, 0x0D, 0xB5, 0x08, 0xBA, 0x03, 0x8A, - 0x00, 0x74, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA5, 0xFF, - 0x6F, 0xFF, 0x57, 0x00, 0x4D, 0x03, 0x29, 0x08, 0x4B, 0x0D, 0x65, - 0x10, 0xEB, 0x0F, 0x1A, 0x0C, 0xD3, 0x06, 0x58, 0x02, 0xF1, 0xFF, - 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x84, 0xFF, 0x90, - 0xFF, 0x21, 0x01, 0xDC, 0x04, 0x10, 0x0A, 0xBB, 0x0E, 0xAA, 0x10, - 0xE1, 0x0E, 0x47, 0x0A, 0x0D, 0x05, 0x3D, 0x01, 0x97, 0xFF, 0x81, - 0xFF, 0xDD, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC2, 0xFF, 0x6F, 0xFF, - 0xE4, 0xFF, 0x34, 0x02, 0x9D, 0x06, 0xE6, 0x0B, 0xD1, 0x0F, 0x73, - 0x10, 0x79, 0x0D, 0x61, 0x08, 0x78, 0x03, 0x6A, 0x00, 0x70, 0xFF, - 0xA1, 0xFF, 0xF2, 0xFF, 0xF1, 0xFF, 0x9F, 0xFF, 0x72, 0xFF, 0x74, - 0x00, 0x8E, 0x03, 0x7D, 0x08, 0x90, 0x0D, 0x7A, 0x10, 0xC4, 0x0F, - 0xCC, 0x0B, 0x82, 0x06, 0x22, 0x02, 0xDD, 0xFF, 0x6F, 0xFF, 0xC4, - 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDB, 0xFF, 0x7F, 0xFF, 0x9B, 0xFF, - 0x4B, 0x01, 0x26, 0x05, 0x63, 0x0A, 0xF3, 0x0E, 0xAA, 0x10, 0xA8, - 0x0E, 0xF4, 0x09, 0xC3, 0x04, 0x13, 0x01, 0x8D, 0xFF, 0x86, 0xFF, - 0xE1, 0xFF, 0xFC, 0xFF, 0xBC, 0xFF, 0x6D, 0xFF, 0xF8, 0xFF, 0x6B, - 0x02, 0xEE, 0x06, 0x34, 0x0C, 0xF7, 0x0F, 0x5D, 0x10, 0x33, 0x0D, - 0x0D, 0x08, 0x38, 0x03, 0x4D, 0x00, 0x6E, 0xFF, 0xA7, 0xFF, 0xF5, - 0xFF, 0xEE, 0xFF, 0x99, 0xFF, 0x76, 0xFF, 0x94, 0x00, 0xD0, 0x03, - 0xD1, 0x08, 0xD3, 0x0D, 0x8B, 0x10, 0x9A, 0x0F, 0x7C, 0x0B, 0x32, - 0x06, 0xEE, 0x01, 0xCB, 0xFF, 0x72, 0xFF, 0xCA, 0xFF, 0xFE, 0xFF, - 0x00, 0x00, 0xD6, 0xFF, 0x7B, 0xFF, 0xA7, 0xFF, 0x78, 0x01, 0x72, - 0x05, 0xB6, 0x0A, 0x27, 0x0F, 0xA5, 0x10, 0x6E, 0x0E, 0xA0, 0x09, - 0x7B, 0x04, 0xEC, 0x00, 0x85, 0xFF, 0x8B, 0xFF, 0xE5, 0xFF, 0xFA, - 0xFF, 0xB6, 0xFF, 0x6C, 0xFF, 0x0E, 0x00, 0xA4, 0x02, 0x41, 0x07, - 0x80, 0x0C, 0x19, 0x10, 0x44, 0x10, 0xEB, 0x0C, 0xB9, 0x07, 0xFA, - 0x02, 0x32, 0x00, 0x6D, 0xFF, 0xAE, 0xFF, 0xF7, 0xFF, 0xEB, 0xFF, - 0x93, 0xFF, 0x7B, 0xFF, 0xB7, 0x00, 0x15, 0x04, 0x26, 0x09, 0x14, - 0x0E, 0x98, 0x10, 0x6D, 0x0F, 0x2C, 0x0B, 0xE3, 0x05, 0xBC, 0x01, - 0xBB, 0xFF, 0x75, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD1, - 0xFF, 0x77, 0xFF, 0xB5, 0xFF, 0xA6, 0x01, 0xC0, 0x05, 0x08, 0x0B, - 0x58, 0x0F, 0x9D, 0x10, 0x30, 0x0E, 0x4B, 0x09, 0x34, 0x04, 0xC6, - 0x00, 0x7D, 0xFF, 0x91, 0xFF, 0xE9, 0xFF, 0xF8, 0xFF, 0xB0, 0xFF, - 0x6C, 0xFF, 0x27, 0x00, 0xDF, 0x02, 0x94, 0x07, 0xCA, 0x0C, 0x37, - 0x10, 0x27, 0x10, 0xA1, 0x0C, 0x65, 0x07, 0xBE, 0x02, 0x19, 0x00, - 0x6C, 0xFF, 0xB4, 0xFF, 0xF9, 0xFF, 0xE7, 0xFF, 0x8E, 0xFF, 0x81, - 0xFF, 0xDB, 0x00, 0x5B, 0x04, 0x7A, 0x09, 0x53, 0x0E, 0xA2, 0x10, - 0x3D, 0x0F, 0xDA, 0x0A, 0x95, 0x05, 0x8C, 0x01, 0xAD, 0xFF, 0x79, - 0xFF, 0xD4, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xCC, 0xFF, 0x73, 0xFF, - 0xC4, 0xFF, 0xD7, 0x01, 0x0E, 0x06, 0x59, 0x0B, 0x87, 0x0F, 0x91, - 0x10, 0xF0, 0x0D, 0xF7, 0x08, 0xEF, 0x03, 0xA3, 0x00, 0x78, 0xFF, - 0x97, 0xFF, 0xED, 0xFF, 0xF6, 0xFF, 0xAA, 0xFF, 0x6D, 0xFF, 0x41, - 0x00, 0x1C, 0x03, 0xE7, 0x07, 0x13, 0x0D, 0x52, 0x10, 0x06, 0x10, - 0x56, 0x0C, 0x13, 0x07, 0x84, 0x02, 0x02, 0x00, 0x6D, 0xFF, 0xBA, - 0xFF, 0xFB, 0xFF, 0xE3, 0xFF, 0x88, 0xFF, 0x89, 0xFF, 0x01, 0x01, - 0xA3, 0x04, 0xCE, 0x09, 0x8F, 0x0E, 0xA8, 0x10, 0x0A, 0x0F, 0x88, - 0x0A, 0x48, 0x05, 0x5F, 0x01, 0xA0, 0xFF, 0x7D, 0xFF, 0xD9, 0xFF, - 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0xFF, 0x70, 0xFF, 0xD5, 0xFF, 0x0B, - 0x02, 0x5E, 0x06, 0xA9, 0x0B, 0xB2, 0x0F, 0x82, 0x10, 0xAE, 0x0D, - 0xA2, 0x08, 0xAB, 0x03, 0x82, 0x00, 0x73, 0xFF, 0x9D, 0xFF, 0xF0, - 0xFF, 0xF3, 0xFF, 0xA4, 0xFF, 0x6F, 0xFF, 0x5D, 0x00, 0x5B, 0x03, - 0x3B, 0x08, 0x5A, 0x0D, 0x6A, 0x10, 0xE2, 0x0F, 0x09, 0x0C, 0xC1, - 0x06, 0x4C, 0x02, 0xEC, 0xFF, 0x6E, 0xFF, 0xC0, 0xFF, 0xFC, 0xFF, - 0xDF, 0xFF, 0x83, 0xFF, 0x93, 0xFF, 0x2A, 0x01, 0xEC, 0x04, 0x22, - 0x0A, 0xC8, 0x0E, 0xAB, 0x10, 0xD4, 0x0E, 0x35, 0x0A, 0xFD, 0x04, - 0x33, 0x01, 0x95, 0xFF, 0x82, 0xFF, 0xDE, 0xFF, 0x00, 0x00, 0xFD, - 0xFF, 0xC1, 0xFF, 0x6E, 0xFF, 0xE8, 0xFF, 0x40, 0x02, 0xAF, 0x06, - 0xF7, 0x0B, 0xDA, 0x0F, 0x6F, 0x10, 0x6A, 0x0D, 0x4E, 0x08, 0x6A, - 0x03, 0x64, 0x00, 0x70, 0xFF, 0xA3, 0xFF, 0xF3, 0xFF, 0xF1, 0xFF, - 0x9E, 0xFF, 0x72, 0xFF, 0x7B, 0x00, 0x9C, 0x03, 0x90, 0x08, 0x9F, - 0x0D, 0x7E, 0x10, 0xBB, 0x0F, 0xBA, 0x0B, 0x70, 0x06, 0x16, 0x02, - 0xD9, 0xFF, 0x70, 0xFF, 0xC5, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xDA, - 0xFF, 0x7E, 0xFF, 0x9D, 0xFF, 0x55, 0x01, 0x37, 0x05, 0x75, 0x0A, - 0xFF, 0x0E, 0xA9, 0x10, 0x9C, 0x0E, 0xE1, 0x09, 0xB3, 0x04, 0x0A, - 0x01, 0x8B, 0xFF, 0x87, 0xFF, 0xE2, 0xFF, 0xFB, 0xFF, 0xBB, 0xFF, - 0x6D, 0xFF, 0xFD, 0xFF, 0x77, 0x02, 0x01, 0x07, 0x45, 0x0C, 0xFF, - 0x0F, 0x58, 0x10, 0x23, 0x0D, 0xFA, 0x07, 0x2A, 0x03, 0x47, 0x00, - 0x6E, 0xFF, 0xA9, 0xFF, 0xF5, 0xFF, 0xED, 0xFF, 0x98, 0xFF, 0x77, - 0xFF, 0x9C, 0x00, 0xDF, 0x03, 0xE4, 0x08, 0xE2, 0x0D, 0x8E, 0x10, - 0x91, 0x0F, 0x6B, 0x0B, 0x20, 0x06, 0xE3, 0x01, 0xC8, 0xFF, 0x73, - 0xFF, 0xCB, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD5, 0xFF, 0x7A, 0xFF, - 0xAA, 0xFF, 0x82, 0x01, 0x83, 0x05, 0xC8, 0x0A, 0x32, 0x0F, 0xA4, - 0x10, 0x60, 0x0E, 0x8D, 0x09, 0x6B, 0x04, 0xE3, 0x00, 0x83, 0xFF, - 0x8D, 0xFF, 0xE6, 0xFF, 0xFA, 0xFF, 0xB5, 0xFF, 0x6C, 0xFF, 0x14, - 0x00, 0xB1, 0x02, 0x53, 0x07, 0x91, 0x0C, 0x20, 0x10, 0x3E, 0x10, - 0xDB, 0x0C, 0xA6, 0x07, 0xEC, 0x02, 0x2C, 0x00, 0x6C, 0xFF, 0xAF, - 0xFF, 0xF8, 0xFF, 0xEA, 0xFF, 0x92, 0xFF, 0x7C, 0xFF, 0xBE, 0x00, - 0x24, 0x04, 0x38, 0x09, 0x22, 0x0E, 0x9B, 0x10, 0x63, 0x0F, 0x1A, - 0x0B, 0xD1, 0x05, 0xB1, 0x01, 0xB8, 0xFF, 0x76, 0xFF, 0xD0, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xFF, 0x76, 0xFF, 0xB8, 0xFF, 0xB1, - 0x01, 0xD1, 0x05, 0x1A, 0x0B, 0x63, 0x0F, 0x9B, 0x10, 0x22, 0x0E, - 0x38, 0x09, 0x24, 0x04, 0xBE, 0x00, 0x7C, 0xFF, 0x92, 0xFF, 0xEA, - 0xFF, 0xF8, 0xFF, 0xAF, 0xFF, 0x6C, 0xFF, 0x2C, 0x00, 0xEC, 0x02, - 0xA6, 0x07, 0xDB, 0x0C, 0x3E, 0x10, 0x20, 0x10, 0x91, 0x0C, 0x53, - 0x07, 0xB1, 0x02, 0x14, 0x00, 0x6C, 0xFF, 0xB5, 0xFF, 0xFA, 0xFF, - 0xE6, 0xFF, 0x8D, 0xFF, 0x83, 0xFF, 0xE3, 0x00, 0x6B, 0x04, 0x8D, - 0x09, 0x60, 0x0E, 0xA4, 0x10, 0x32, 0x0F, 0xC8, 0x0A, 0x83, 0x05, - 0x82, 0x01, 0xAA, 0xFF, 0x7A, 0xFF, 0xD5, 0xFF, 0x00, 0x00, 0xFF, - 0xFF, 0xCB, 0xFF, 0x73, 0xFF, 0xC8, 0xFF, 0xE3, 0x01, 0x20, 0x06, - 0x6B, 0x0B, 0x91, 0x0F, 0x8E, 0x10, 0xE2, 0x0D, 0xE4, 0x08, 0xDF, - 0x03, 0x9C, 0x00, 0x77, 0xFF, 0x98, 0xFF, 0xED, 0xFF, 0xF5, 0xFF, - 0xA9, 0xFF, 0x6E, 0xFF, 0x47, 0x00, 0x2A, 0x03, 0xFA, 0x07, 0x23, - 0x0D, 0x58, 0x10, 0xFF, 0x0F, 0x45, 0x0C, 0x01, 0x07, 0x77, 0x02, - 0xFD, 0xFF, 0x6D, 0xFF, 0xBB, 0xFF, 0xFB, 0xFF, 0xE2, 0xFF, 0x87, - 0xFF, 0x8B, 0xFF, 0x0A, 0x01, 0xB3, 0x04, 0xE1, 0x09, 0x9C, 0x0E, - 0xA9, 0x10, 0xFF, 0x0E, 0x75, 0x0A, 0x37, 0x05, 0x55, 0x01, 0x9D, - 0xFF, 0x7E, 0xFF, 0xDA, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xC5, 0xFF, - 0x70, 0xFF, 0xD9, 0xFF, 0x16, 0x02, 0x70, 0x06, 0xBA, 0x0B, 0xBB, - 0x0F, 0x7E, 0x10, 0x9F, 0x0D, 0x90, 0x08, 0x9C, 0x03, 0x7B, 0x00, - 0x72, 0xFF, 0x9E, 0xFF, 0xF1, 0xFF, 0xF3, 0xFF, 0xA3, 0xFF, 0x70, - 0xFF, 0x64, 0x00, 0x6A, 0x03, 0x4E, 0x08, 0x6A, 0x0D, 0x6F, 0x10, - 0xDA, 0x0F, 0xF7, 0x0B, 0xAF, 0x06, 0x40, 0x02, 0xE8, 0xFF, 0x6E, - 0xFF, 0xC1, 0xFF, 0xFD, 0xFF, 0x00, 0x00, 0xDE, 0xFF, 0x82, 0xFF, - 0x95, 0xFF, 0x33, 0x01, 0xFD, 0x04, 0x35, 0x0A, 0xD4, 0x0E, 0xAB, - 0x10, 0xC8, 0x0E, 0x22, 0x0A, 0xEC, 0x04, 0x2A, 0x01, 0x93, 0xFF, - 0x83, 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xC0, 0xFF, 0x6E, 0xFF, 0xEC, - 0xFF, 0x4C, 0x02, 0xC1, 0x06, 0x09, 0x0C, 0xE2, 0x0F, 0x6A, 0x10, - 0x5A, 0x0D, 0x3B, 0x08, 0x5B, 0x03, 0x5D, 0x00, 0x6F, 0xFF, 0xA4, - 0xFF, 0xF3, 0xFF, 0xF0, 0xFF, 0x9D, 0xFF, 0x73, 0xFF, 0x82, 0x00, - 0xAB, 0x03, 0xA2, 0x08, 0xAE, 0x0D, 0x82, 0x10, 0xB2, 0x0F, 0xA9, - 0x0B, 0x5E, 0x06, 0x0B, 0x02, 0xD5, 0xFF, 0x70, 0xFF, 0xC7, 0xFF, - 0xFE, 0xFF, 0x00, 0x00, 0xD9, 0xFF, 0x7D, 0xFF, 0xA0, 0xFF, 0x5F, - 0x01, 0x48, 0x05, 0x88, 0x0A, 0x0A, 0x0F, 0xA8, 0x10, 0x8F, 0x0E, - 0xCE, 0x09, 0xA3, 0x04, 0x01, 0x01, 0x89, 0xFF, 0x88, 0xFF, 0xE3, - 0xFF, 0xFB, 0xFF, 0xBA, 0xFF, 0x6D, 0xFF, 0x02, 0x00, 0x84, 0x02, - 0x13, 0x07, 0x56, 0x0C, 0x06, 0x10, 0x52, 0x10, 0x13, 0x0D, 0xE7, - 0x07, 0x1C, 0x03, 0x41, 0x00, 0x6D, 0xFF, 0xAA, 0xFF, 0xF6, 0xFF, - 0xED, 0xFF, 0x97, 0xFF, 0x78, 0xFF, 0xA3, 0x00, 0xEF, 0x03, 0xF7, - 0x08, 0xF0, 0x0D, 0x91, 0x10, 0x87, 0x0F, 0x59, 0x0B, 0x0E, 0x06, - 0xD7, 0x01, 0xC4, 0xFF, 0x73, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0xD4, 0xFF, 0x79, 0xFF, 0xAD, 0xFF, 0x8C, 0x01, 0x95, 0x05, - 0xDA, 0x0A, 0x3D, 0x0F, 0xA2, 0x10, 0x53, 0x0E, 0x7A, 0x09, 0x5B, - 0x04, 0xDB, 0x00, 0x81, 0xFF, 0x8E, 0xFF, 0xE7, 0xFF, 0xF9, 0xFF, - 0xB4, 0xFF, 0x6C, 0xFF, 0x19, 0x00, 0xBE, 0x02, 0x65, 0x07, 0xA1, - 0x0C, 0x27, 0x10, 0x37, 0x10, 0xCA, 0x0C, 0x94, 0x07, 0xDF, 0x02, - 0x27, 0x00, 0x6C, 0xFF, 0xB0, 0xFF, 0xF8, 0xFF, 0xE9, 0xFF, 0x91, - 0xFF, 0x7D, 0xFF, 0xC6, 0x00, 0x34, 0x04, 0x4B, 0x09, 0x30, 0x0E, - 0x9D, 0x10, 0x58, 0x0F, 0x08, 0x0B, 0xC0, 0x05, 0xA6, 0x01, 0xB5, - 0xFF, 0x77, 0xFF, 0xD1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, - 0x75, 0xFF, 0xBB, 0xFF, 0xBC, 0x01, 0xE3, 0x05, 0x2C, 0x0B, 0x6D, - 0x0F, 0x98, 0x10, 0x14, 0x0E, 0x26, 0x09, 0x15, 0x04, 0xB7, 0x00, - 0x7B, 0xFF, 0x93, 0xFF, 0xEB, 0xFF, 0xF7, 0xFF, 0xAE, 0xFF, 0x6D, - 0xFF, 0x32, 0x00, 0xFA, 0x02, 0xB9, 0x07, 0xEB, 0x0C, 0x44, 0x10, - 0x19, 0x10, 0x80, 0x0C, 0x41, 0x07, 0xA4, 0x02, 0x0E, 0x00, 0x6C, - 0xFF, 0xB6, 0xFF, 0xFA, 0xFF, 0xE5, 0xFF, 0x8B, 0xFF, 0x85, 0xFF, - 0xEC, 0x00, 0x7B, 0x04, 0xA0, 0x09, 0x6E, 0x0E, 0xA5, 0x10, 0x27, - 0x0F, 0xB6, 0x0A, 0x72, 0x05, 0x78, 0x01, 0xA7, 0xFF, 0x7B, 0xFF, - 0xD6, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xCA, 0xFF, 0x72, 0xFF, 0xCB, - 0xFF, 0xEE, 0x01, 0x32, 0x06, 0x7C, 0x0B, 0x9A, 0x0F, 0x8B, 0x10, - 0xD3, 0x0D, 0xD1, 0x08, 0xD0, 0x03, 0x94, 0x00, 0x76, 0xFF, 0x99, - 0xFF, 0xEE, 0xFF, 0xF5, 0xFF, 0xA7, 0xFF, 0x6E, 0xFF, 0x4D, 0x00, - 0x38, 0x03, 0x0D, 0x08, 0x33, 0x0D, 0x5D, 0x10, 0xF7, 0x0F, 0x34, - 0x0C, 0xEE, 0x06, 0x6B, 0x02, 0xF8, 0xFF, 0x6D, 0xFF, 0xBC, 0xFF, - 0xFC, 0xFF, 0xE1, 0xFF, 0x86, 0xFF, 0x8D, 0xFF, 0x13, 0x01, 0xC3, - 0x04, 0xF4, 0x09, 0xA8, 0x0E, 0xAA, 0x10, 0xF3, 0x0E, 0x63, 0x0A, - 0x26, 0x05, 0x4B, 0x01, 0x9B, 0xFF, 0x7F, 0xFF, 0xDB, 0xFF, 0x00, - 0x00, 0xFD, 0xFF, 0xC4, 0xFF, 0x6F, 0xFF, 0xDD, 0xFF, 0x22, 0x02, - 0x82, 0x06, 0xCC, 0x0B, 0xC4, 0x0F, 0x7A, 0x10, 0x90, 0x0D, 0x7D, - 0x08, 0x8E, 0x03, 0x74, 0x00, 0x72, 0xFF, 0x9F, 0xFF, 0xF1, 0xFF, - 0xF2, 0xFF, 0xA1, 0xFF, 0x70, 0xFF, 0x6A, 0x00, 0x78, 0x03, 0x61, - 0x08, 0x79, 0x0D, 0x73, 0x10, 0xD1, 0x0F, 0xE6, 0x0B, 0x9D, 0x06, - 0x34, 0x02, 0xE4, 0xFF, 0x6F, 0xFF, 0xC2, 0xFF, 0xFD, 0xFF, 0x00, - 0x00, 0xDD, 0xFF, 0x81, 0xFF, 0x97, 0xFF, 0x3D, 0x01, 0x0D, 0x05, - 0x47, 0x0A, 0xE1, 0x0E, 0xAA, 0x10, 0xBB, 0x0E, 0x10, 0x0A, 0xDC, - 0x04, 0x21, 0x01, 0x90, 0xFF, 0x84, 0xFF, 0xE0, 0xFF, 0xFC, 0xFF, - 0xBE, 0xFF, 0x6D, 0xFF, 0xF1, 0xFF, 0x58, 0x02, 0xD3, 0x06, 0x1A, - 0x0C, 0xEB, 0x0F, 0x65, 0x10, 0x4B, 0x0D, 0x29, 0x08, 0x4D, 0x03, - 0x57, 0x00, 0x6F, 0xFF, 0xA5, 0xFF, 0xF4, 0xFF, 0xEF, 0xFF, 0x9B, - 0xFF, 0x74, 0xFF, 0x8A, 0x00, 0xBA, 0x03, 0xB5, 0x08, 0xBD, 0x0D, - 0x86, 0x10, 0xA9, 0x0F, 0x97, 0x0B, 0x4C, 0x06, 0xFF, 0x01, 0xD1, - 0xFF, 0x71, 0xFF, 0xC8, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0xD8, 0xFF, - 0x7C, 0xFF, 0xA3, 0xFF, 0x69, 0x01, 0x59, 0x05, 0x9A, 0x0A, 0x16, - 0x0F, 0xA7, 0x10, 0x82, 0x0E, 0xBC, 0x09, 0x93, 0x04, 0xF9, 0x00, - 0x87, 0xFF, 0x89, 0xFF, 0xE4, 0xFF, 0xFB, 0xFF, 0xB8, 0xFF, 0x6C, - 0xFF, 0x07, 0x00, 0x91, 0x02, 0x25, 0x07, 0x67, 0x0C, 0x0E, 0x10, - 0x4D, 0x10, 0x03, 0x0D, 0xD5, 0x07, 0x0E, 0x03, 0x3B, 0x00, 0x6D, - 0xFF, 0xAC, 0xFF, 0xF7, 0xFF, 0xEC, 0xFF, 0x95, 0xFF, 0x79, 0xFF, - 0xAB, 0x00, 0xFE, 0x03, 0x0A, 0x09, 0xFF, 0x0D, 0x94, 0x10, 0x7D, - 0x0F, 0x47, 0x0B, 0xFD, 0x05, 0xCC, 0x01, 0xC0, 0xFF, 0x74, 0xFF, - 0xCD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD3, 0xFF, 0x78, 0xFF, 0xB0, - 0xFF, 0x97, 0x01, 0xA6, 0x05, 0xEC, 0x0A, 0x48, 0x0F, 0xA0, 0x10, - 0x45, 0x0E, 0x67, 0x09, 0x4B, 0x04, 0xD3, 0x00, 0x80, 0xFF, 0x8F, - 0xFF, 0xE8, 0xFF, 0xF9, 0xFF, 0xB2, 0xFF, 0x6C, 0xFF, 0x1E, 0x00, - 0xCB, 0x02, 0x78, 0x07, 0xB2, 0x0C, 0x2E, 0x10, 0x31, 0x10, 0xBA, - 0x0C, 0x81, 0x07, 0xD2, 0x02, 0x21, 0x00, 0x6C, 0xFF, 0xB2, 0xFF, - 0xF9, 0xFF, 0xE8, 0xFF, 0x90, 0xFF, 0x7F, 0xFF, 0xCF, 0x00, 0x43, - 0x04, 0x5E, 0x09, 0x3E, 0x0E, 0x9F, 0x10, 0x4E, 0x0F, 0xF6, 0x0A, - 0xAE, 0x05, 0x9C, 0x01, 0xB1, 0xFF, 0x78, 0xFF, 0xD2, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0x74, 0xFF, 0xBF, 0xFF, 0xC7, 0x01, - 0xF4, 0x05, 0x3E, 0x0B, 0x78, 0x0F, 0x96, 0x10, 0x06, 0x0E, 0x13, - 0x09, 0x05, 0x04, 0xAF, 0x00, 0x79, 0xFF, 0x95, 0xFF, 0xEC, 0xFF, - 0xF7, 0xFF, 0xAC, 0xFF, 0x6D, 0xFF, 0x38, 0x00, 0x07, 0x03, 0xCB, - 0x07, 0xFB, 0x0C, 0x4A, 0x10, 0x11, 0x10, 0x6F, 0x0C, 0x2E, 0x07, - 0x97, 0x02, 0x09, 0x00, 0x6C, 0xFF, 0xB8, 0xFF, 0xFA, 0xFF, 0xE4, - 0xFF, 0x8A, 0xFF, 0x86, 0xFF, 0xF4, 0x00, 0x8B, 0x04, 0xB2, 0x09, - 0x7B, 0x0E, 0xA7, 0x10, 0x1C, 0x0F, 0xA3, 0x0A, 0x61, 0x05, 0x6E, - 0x01, 0xA4, 0xFF, 0x7C, 0xFF, 0xD8, 0xFF, 0x00, 0x00, 0xFE, 0xFF, - 0xC8, 0xFF, 0x71, 0xFF, 0xCF, 0xFF, 0xF9, 0x01, 0x43, 0x06, 0x8E, - 0x0B, 0xA4, 0x0F, 0x88, 0x10, 0xC4, 0x0D, 0xBE, 0x08, 0xC1, 0x03, - 0x8D, 0x00, 0x75, 0xFF, 0x9B, 0xFF, 0xEF, 0xFF, 0xF4, 0xFF, 0xA6, - 0xFF, 0x6E, 0xFF, 0x53, 0x00, 0x46, 0x03, 0x1F, 0x08, 0x43, 0x0D, - 0x63, 0x10, 0xEF, 0x0F, 0x23, 0x0C, 0xDC, 0x06, 0x5E, 0x02, 0xF3, - 0xFF, 0x6D, 0xFF, 0xBE, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, 0x85, 0xFF, - 0x8F, 0xFF, 0x1C, 0x01, 0xD3, 0x04, 0x06, 0x0A, 0xB5, 0x0E, 0xAA, - 0x10, 0xE7, 0x0E, 0x50, 0x0A, 0x16, 0x05, 0x42, 0x01, 0x98, 0xFF, - 0x80, 0xFF, 0xDC, 0xFF, 0x00, 0x00, 0xFD, 0xFF, 0xC3, 0xFF, 0x6F, - 0xFF, 0xE1, 0xFF, 0x2E, 0x02, 0x94, 0x06, 0xDD, 0x0B, 0xCD, 0x0F, - 0x76, 0x10, 0x81, 0x0D, 0x6A, 0x08, 0x7F, 0x03, 0x6E, 0x00, 0x71, - 0xFF, 0xA1, 0xFF, 0xF2, 0xFF, 0x00, 0x00, 0x15, 0x00, 0xD1, 0xFF, - 0x8B, 0xFE, 0xBC, 0xFD, 0xE1, 0x00, 0x84, 0x09, 0xB0, 0x13, 0x47, - 0x18, 0xB0, 0x13, 0x84, 0x09, 0xE1, 0x00, 0xBC, 0xFD, 0x8B, 0xFE, - 0xD1, 0xFF, 0x15, 0x00, 0xFD, 0xFF, 0x13, 0x00, 0xDA, 0x00, 0x30, - 0x00, 0x5D, 0xFC, 0xB3, 0xFC, 0x35, 0x0A, 0xC2, 0x1C, 0x24, 0x20, - 0x48, 0x10, 0x5D, 0xFF, 0x74, 0xFB, 0x3A, 0xFF, 0xFB, 0x00, 0x42, - 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2C, 0x00, 0xF3, 0x00, 0xAD, 0xFF, - 0xC5, 0xFB, 0x11, 0xFE, 0xAF, 0x0D, 0xEF, 0x1E, 0x68, 0x1E, 0xBC, - 0x0C, 0xA7, 0xFD, 0xEA, 0xFB, 0xD3, 0xFF, 0xEE, 0x00, 0x24, 0x00, - 0xFA, 0xFF, 0xF7, 0xFF, 0x4C, 0x00, 0xFB, 0x00, 0x0C, 0xFF, 0x5F, - 0xFB, 0xE8, 0xFF, 0x3D, 0x11, 0x7E, 0x20, 0x13, 0x1C, 0x4C, 0x09, - 0x6A, 0xFC, 0x8C, 0xFC, 0x4E, 0x00, 0xD1, 0x00, 0x0E, 0x00, 0xFD, - 0xFF, 0xF7, 0xFF, 0x72, 0x00, 0xEC, 0x00, 0x55, 0xFE, 0x3D, 0xFB, - 0x37, 0x02, 0xBE, 0x14, 0x5D, 0x21, 0x40, 0x19, 0x18, 0x06, 0xA2, - 0xFB, 0x47, 0xFD, 0xA7, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFC, 0xFF, 0x9B, 0x00, 0xC0, 0x00, 0x92, 0xFD, 0x73, - 0xFB, 0xF2, 0x04, 0x0E, 0x18, 0x81, 0x21, 0x0C, 0x16, 0x37, 0x03, - 0x47, 0xFB, 0x0B, 0xFE, 0xDF, 0x00, 0x82, 0x00, 0xF9, 0xFF, 0xFE, - 0xFF, 0x08, 0x00, 0xC3, 0x00, 0x74, 0x00, 0xD2, 0xFC, 0x10, 0xFC, - 0x08, 0x08, 0x0A, 0x1B, 0xE9, 0x20, 0x9A, 0x12, 0xBE, 0x00, 0x49, - 0xFB, 0xC8, 0xFE, 0xF9, 0x00, 0x5A, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, - 0x1B, 0x00, 0xE4, 0x00, 0x06, 0x00, 0x24, 0xFC, 0x1E, 0xFD, 0x65, - 0x0B, 0x94, 0x1D, 0x9D, 0x1F, 0x0D, 0x0F, 0xB8, 0xFE, 0x96, 0xFB, - 0x72, 0xFF, 0xF9, 0x00, 0x37, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x36, - 0x00, 0xF8, 0x00, 0x78, 0xFF, 0x9B, 0xFB, 0xA6, 0xFE, 0xE9, 0x0E, - 0x8D, 0x1F, 0xAA, 0x1D, 0x87, 0x0B, 0x2B, 0xFD, 0x1E, 0xFC, 0x02, - 0x00, 0xE5, 0x00, 0x1C, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x58, 0x00, - 0xF9, 0x00, 0xCF, 0xFE, 0x4A, 0xFB, 0xA7, 0x00, 0x77, 0x12, 0xE0, - 0x20, 0x26, 0x1B, 0x28, 0x08, 0x18, 0xFC, 0xCB, 0xFC, 0x71, 0x00, - 0xC5, 0x00, 0x08, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x80, 0x00, 0xE1, - 0x00, 0x13, 0xFE, 0x45, 0xFB, 0x1D, 0x03, 0xEB, 0x15, 0x7F, 0x21, - 0x2D, 0x18, 0x0E, 0x05, 0x77, 0xFB, 0x8B, 0xFD, 0xBE, 0x00, 0x9D, - 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA9, 0x00, - 0xAA, 0x00, 0x4F, 0xFD, 0x9D, 0xFB, 0xFA, 0x05, 0x22, 0x19, 0x62, - 0x21, 0xE0, 0x14, 0x50, 0x02, 0x3E, 0xFB, 0x4E, 0xFE, 0xEB, 0x00, - 0x73, 0x00, 0xF7, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xD0, 0x00, 0x52, - 0x00, 0x93, 0xFC, 0x60, 0xFC, 0x2C, 0x09, 0xFA, 0x1B, 0x8A, 0x20, - 0x60, 0x11, 0xFD, 0xFF, 0x5C, 0xFB, 0x06, 0xFF, 0xFB, 0x00, 0x4D, - 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x23, 0x00, 0xED, 0x00, 0xD9, 0xFF, - 0xEF, 0xFB, 0x98, 0xFD, 0x99, 0x0C, 0x54, 0x1E, 0x02, 0x1F, 0xD2, - 0x0D, 0x20, 0xFE, 0xC0, 0xFB, 0xA7, 0xFF, 0xF4, 0x00, 0x2D, 0x00, - 0xF9, 0xFF, 0xF8, 0xFF, 0x41, 0x00, 0xFB, 0x00, 0x41, 0xFF, 0x78, - 0xFB, 0x4A, 0xFF, 0x25, 0x10, 0x16, 0x20, 0xDA, 0x1C, 0x56, 0x0A, - 0xBE, 0xFC, 0x56, 0xFC, 0x2C, 0x00, 0xDB, 0x00, 0x14, 0x00, 0xFD, - 0xFF, 0xF7, 0xFF, 0x66, 0x00, 0xF4, 0x00, 0x8F, 0xFE, 0x3F, 0xFB, - 0x75, 0x01, 0xAE, 0x13, 0x2C, 0x21, 0x2A, 0x1A, 0x0D, 0x07, 0xD4, - 0xFB, 0x0C, 0xFD, 0x8F, 0x00, 0xB7, 0x00, 0x03, 0x00, 0xFF, 0xFF, - 0x00, 0x00, 0xFA, 0xFF, 0x8E, 0x00, 0xD1, 0x00, 0xCF, 0xFD, 0x58, - 0xFB, 0x10, 0x04, 0x10, 0x17, 0x8A, 0x21, 0x10, 0x17, 0x10, 0x04, - 0x58, 0xFB, 0xCF, 0xFD, 0xD1, 0x00, 0x8E, 0x00, 0xFA, 0xFF, 0xFF, - 0xFF, 0x03, 0x00, 0xB7, 0x00, 0x8F, 0x00, 0x0C, 0xFD, 0xD4, 0xFB, - 0x0D, 0x07, 0x2A, 0x1A, 0x2C, 0x21, 0xAE, 0x13, 0x75, 0x01, 0x3F, - 0xFB, 0x8F, 0xFE, 0xF4, 0x00, 0x66, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, - 0x14, 0x00, 0xDB, 0x00, 0x2C, 0x00, 0x56, 0xFC, 0xBE, 0xFC, 0x56, - 0x0A, 0xDA, 0x1C, 0x16, 0x20, 0x25, 0x10, 0x4A, 0xFF, 0x78, 0xFB, - 0x41, 0xFF, 0xFB, 0x00, 0x41, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2D, - 0x00, 0xF4, 0x00, 0xA7, 0xFF, 0xC0, 0xFB, 0x20, 0xFE, 0xD2, 0x0D, - 0x02, 0x1F, 0x54, 0x1E, 0x99, 0x0C, 0x98, 0xFD, 0xEF, 0xFB, 0xD9, - 0xFF, 0xED, 0x00, 0x23, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4D, 0x00, - 0xFB, 0x00, 0x06, 0xFF, 0x5C, 0xFB, 0xFD, 0xFF, 0x60, 0x11, 0x8A, - 0x20, 0xFA, 0x1B, 0x2C, 0x09, 0x60, 0xFC, 0x93, 0xFC, 0x52, 0x00, - 0xD0, 0x00, 0x0D, 0x00, 0xFE, 0xFF, 0xF7, 0xFF, 0x73, 0x00, 0xEB, - 0x00, 0x4E, 0xFE, 0x3E, 0xFB, 0x50, 0x02, 0xE0, 0x14, 0x62, 0x21, - 0x22, 0x19, 0xFA, 0x05, 0x9D, 0xFB, 0x4F, 0xFD, 0xAA, 0x00, 0xA9, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0x9D, 0x00, - 0xBE, 0x00, 0x8B, 0xFD, 0x77, 0xFB, 0x0E, 0x05, 0x2D, 0x18, 0x7F, - 0x21, 0xEB, 0x15, 0x1D, 0x03, 0x45, 0xFB, 0x13, 0xFE, 0xE1, 0x00, - 0x80, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x08, 0x00, 0xC5, 0x00, 0x71, - 0x00, 0xCB, 0xFC, 0x18, 0xFC, 0x28, 0x08, 0x26, 0x1B, 0xE0, 0x20, - 0x77, 0x12, 0xA7, 0x00, 0x4A, 0xFB, 0xCF, 0xFE, 0xF9, 0x00, 0x58, - 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1C, 0x00, 0xE5, 0x00, 0x02, 0x00, - 0x1E, 0xFC, 0x2B, 0xFD, 0x87, 0x0B, 0xAA, 0x1D, 0x8D, 0x1F, 0xE9, - 0x0E, 0xA6, 0xFE, 0x9B, 0xFB, 0x78, 0xFF, 0xF8, 0x00, 0x36, 0x00, - 0xF9, 0xFF, 0xF8, 0xFF, 0x37, 0x00, 0xF9, 0x00, 0x72, 0xFF, 0x96, - 0xFB, 0xB8, 0xFE, 0x0D, 0x0F, 0x9D, 0x1F, 0x94, 0x1D, 0x65, 0x0B, - 0x1E, 0xFD, 0x24, 0xFC, 0x06, 0x00, 0xE4, 0x00, 0x1B, 0x00, 0xFC, - 0xFF, 0xF7, 0xFF, 0x5A, 0x00, 0xF9, 0x00, 0xC8, 0xFE, 0x49, 0xFB, - 0xBE, 0x00, 0x9A, 0x12, 0xE9, 0x20, 0x0A, 0x1B, 0x08, 0x08, 0x10, - 0xFC, 0xD2, 0xFC, 0x74, 0x00, 0xC3, 0x00, 0x08, 0x00, 0xFE, 0xFF, - 0xF9, 0xFF, 0x82, 0x00, 0xDF, 0x00, 0x0B, 0xFE, 0x47, 0xFB, 0x37, - 0x03, 0x0C, 0x16, 0x81, 0x21, 0x0E, 0x18, 0xF2, 0x04, 0x73, 0xFB, - 0x92, 0xFD, 0xC0, 0x00, 0x9B, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xAB, 0x00, 0xA7, 0x00, 0x47, 0xFD, 0xA2, 0xFB, - 0x18, 0x06, 0x40, 0x19, 0x5D, 0x21, 0xBE, 0x14, 0x37, 0x02, 0x3D, - 0xFB, 0x55, 0xFE, 0xEC, 0x00, 0x72, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, - 0x0E, 0x00, 0xD1, 0x00, 0x4E, 0x00, 0x8C, 0xFC, 0x6A, 0xFC, 0x4C, - 0x09, 0x13, 0x1C, 0x7E, 0x20, 0x3D, 0x11, 0xE8, 0xFF, 0x5F, 0xFB, - 0x0C, 0xFF, 0xFB, 0x00, 0x4C, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x24, - 0x00, 0xEE, 0x00, 0xD3, 0xFF, 0xEA, 0xFB, 0xA7, 0xFD, 0xBC, 0x0C, - 0x68, 0x1E, 0xEF, 0x1E, 0xAF, 0x0D, 0x11, 0xFE, 0xC5, 0xFB, 0xAD, - 0xFF, 0xF3, 0x00, 0x2C, 0x00, 0xFA, 0xFF, 0xF8, 0xFF, 0x42, 0x00, - 0xFB, 0x00, 0x3A, 0xFF, 0x74, 0xFB, 0x5D, 0xFF, 0x48, 0x10, 0x24, - 0x20, 0xC2, 0x1C, 0x35, 0x0A, 0xB3, 0xFC, 0x5D, 0xFC, 0x30, 0x00, - 0xDA, 0x00, 0x13, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x67, 0x00, 0xF3, - 0x00, 0x88, 0xFE, 0x3E, 0xFB, 0x8C, 0x01, 0xD0, 0x13, 0x33, 0x21, - 0x0D, 0x1A, 0xEE, 0x06, 0xCD, 0xFB, 0x13, 0xFD, 0x92, 0x00, 0xB6, - 0x00, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFA, 0xFF, 0x90, 0x00, - 0xCF, 0x00, 0xC7, 0xFD, 0x5B, 0xFB, 0x2B, 0x04, 0x31, 0x17, 0x8A, - 0x21, 0xF0, 0x16, 0xF4, 0x03, 0x56, 0xFB, 0xD6, 0xFD, 0xD3, 0x00, - 0x8D, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0xB9, 0x00, 0x8C, - 0x00, 0x05, 0xFD, 0xDB, 0xFB, 0x2C, 0x07, 0x47, 0x1A, 0x25, 0x21, - 0x8B, 0x13, 0x5D, 0x01, 0x40, 0xFB, 0x97, 0xFE, 0xF5, 0x00, 0x64, - 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x15, 0x00, 0xDC, 0x00, 0x27, 0x00, - 0x50, 0xFC, 0xCA, 0xFC, 0x78, 0x0A, 0xF2, 0x1C, 0x07, 0x20, 0x02, - 0x10, 0x37, 0xFF, 0x7B, 0xFB, 0x47, 0xFF, 0xFB, 0x00, 0x40, 0x00, - 0xF8, 0xFF, 0xF9, 0xFF, 0x2E, 0x00, 0xF5, 0x00, 0xA2, 0xFF, 0xBB, - 0xFB, 0x31, 0xFE, 0xF5, 0x0D, 0x14, 0x1F, 0x3F, 0x1E, 0x77, 0x0C, - 0x8A, 0xFD, 0xF5, 0xFB, 0xDE, 0xFF, 0xEC, 0x00, 0x22, 0x00, 0xFB, - 0xFF, 0xF7, 0xFF, 0x4E, 0x00, 0xFB, 0x00, 0xFF, 0xFE, 0x59, 0xFB, - 0x11, 0x00, 0x83, 0x11, 0x96, 0x20, 0xE0, 0x1B, 0x0B, 0x09, 0x56, - 0xFC, 0x99, 0xFC, 0x56, 0x00, 0xCE, 0x00, 0x0D, 0x00, 0xFE, 0xFF, - 0xF8, 0xFF, 0x75, 0x00, 0xEA, 0x00, 0x47, 0xFE, 0x3E, 0xFB, 0x69, - 0x02, 0x02, 0x15, 0x66, 0x21, 0x04, 0x19, 0xDC, 0x05, 0x98, 0xFB, - 0x56, 0xFD, 0xAD, 0x00, 0xA8, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0xFD, 0xFF, 0x9E, 0x00, 0xBC, 0x00, 0x83, 0xFD, 0x7B, 0xFB, - 0x2B, 0x05, 0x4C, 0x18, 0x7C, 0x21, 0xCA, 0x15, 0x03, 0x03, 0x44, - 0xFB, 0x1A, 0xFE, 0xE2, 0x00, 0x7E, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, - 0x09, 0x00, 0xC6, 0x00, 0x6D, 0x00, 0xC3, 0xFC, 0x20, 0xFC, 0x49, - 0x08, 0x41, 0x1B, 0xD6, 0x20, 0x54, 0x12, 0x92, 0x00, 0x4C, 0xFB, - 0xD6, 0xFE, 0xFA, 0x00, 0x57, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1D, - 0x00, 0xE6, 0x00, 0xFD, 0xFF, 0x18, 0xFC, 0x38, 0xFD, 0xA9, 0x0B, - 0xC0, 0x1D, 0x7C, 0x1F, 0xC6, 0x0E, 0x95, 0xFE, 0x9F, 0xFB, 0x7E, - 0xFF, 0xF8, 0x00, 0x35, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x38, 0x00, - 0xF9, 0x00, 0x6C, 0xFF, 0x92, 0xFB, 0xC9, 0xFE, 0x2F, 0x0F, 0xAD, - 0x1F, 0x7D, 0x1D, 0x42, 0x0B, 0x12, 0xFD, 0x2A, 0xFC, 0x0B, 0x00, - 0xE3, 0x00, 0x1A, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5B, 0x00, 0xF8, - 0x00, 0xC1, 0xFE, 0x47, 0xFB, 0xD4, 0x00, 0xBC, 0x12, 0xF3, 0x20, - 0xEF, 0x1A, 0xE9, 0x07, 0x08, 0xFC, 0xD9, 0xFC, 0x78, 0x00, 0xC2, - 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x83, 0x00, 0xDD, 0x00, - 0x04, 0xFE, 0x49, 0xFB, 0x52, 0x03, 0x2D, 0x16, 0x83, 0x21, 0xEF, - 0x17, 0xD5, 0x04, 0x6F, 0xFB, 0x9A, 0xFD, 0xC3, 0x00, 0x9A, 0x00, - 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xAD, 0x00, 0xA4, - 0x00, 0x40, 0xFD, 0xA8, 0xFB, 0x36, 0x06, 0x5E, 0x19, 0x58, 0x21, - 0x9C, 0x14, 0x1E, 0x02, 0x3D, 0xFB, 0x5D, 0xFE, 0xED, 0x00, 0x70, - 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F, 0x00, 0xD2, 0x00, 0x4A, 0x00, - 0x85, 0xFC, 0x74, 0xFC, 0x6D, 0x09, 0x2D, 0x1C, 0x72, 0x20, 0x1A, - 0x11, 0xD4, 0xFF, 0x61, 0xFB, 0x13, 0xFF, 0xFC, 0x00, 0x4A, 0x00, - 0xF7, 0xFF, 0xFA, 0xFF, 0x25, 0x00, 0xEF, 0x00, 0xCE, 0xFF, 0xE4, - 0xFB, 0xB5, 0xFD, 0xDE, 0x0C, 0x7C, 0x1E, 0xDD, 0x1E, 0x8C, 0x0D, - 0x01, 0xFE, 0xCA, 0xFB, 0xB3, 0xFF, 0xF3, 0x00, 0x2B, 0x00, 0xFA, - 0xFF, 0xF8, 0xFF, 0x44, 0x00, 0xFB, 0x00, 0x34, 0xFF, 0x71, 0xFB, - 0x71, 0xFF, 0x6B, 0x10, 0x32, 0x20, 0xA9, 0x1C, 0x13, 0x0A, 0xA8, - 0xFC, 0x63, 0xFC, 0x35, 0x00, 0xD9, 0x00, 0x12, 0x00, 0xFD, 0xFF, - 0xF7, 0xFF, 0x69, 0x00, 0xF2, 0x00, 0x81, 0xFE, 0x3E, 0xFB, 0xA4, - 0x01, 0xF2, 0x13, 0x3A, 0x21, 0xF0, 0x19, 0xCF, 0x06, 0xC7, 0xFB, - 0x1B, 0xFD, 0x96, 0x00, 0xB4, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00, - 0x00, 0xFB, 0xFF, 0x92, 0x00, 0xCD, 0x00, 0xC0, 0xFD, 0x5E, 0xFB, - 0x47, 0x04, 0x51, 0x17, 0x8A, 0x21, 0xD0, 0x16, 0xD9, 0x03, 0x53, - 0xFB, 0xDE, 0xFD, 0xD5, 0x00, 0x8B, 0x00, 0xFA, 0xFF, 0xFF, 0xFF, - 0x04, 0x00, 0xBA, 0x00, 0x89, 0x00, 0xFD, 0xFC, 0xE2, 0xFB, 0x4B, - 0x07, 0x63, 0x1A, 0x1D, 0x21, 0x69, 0x13, 0x46, 0x01, 0x41, 0xFB, - 0x9E, 0xFE, 0xF5, 0x00, 0x63, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x16, - 0x00, 0xDD, 0x00, 0x23, 0x00, 0x49, 0xFC, 0xD5, 0xFC, 0x99, 0x0A, - 0x09, 0x1D, 0xF9, 0x1F, 0xDF, 0x0F, 0x24, 0xFF, 0x7F, 0xFB, 0x4D, - 0xFF, 0xFB, 0x00, 0x3F, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x2F, 0x00, - 0xF5, 0x00, 0x9C, 0xFF, 0xB6, 0xFB, 0x41, 0xFE, 0x17, 0x0E, 0x26, - 0x1F, 0x2B, 0x1E, 0x54, 0x0C, 0x7C, 0xFD, 0xFA, 0xFB, 0xE3, 0xFF, - 0xEB, 0x00, 0x21, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x50, 0x00, 0xFB, - 0x00, 0xF8, 0xFE, 0x57, 0xFB, 0x26, 0x00, 0xA6, 0x11, 0xA1, 0x20, - 0xC6, 0x1B, 0xEA, 0x08, 0x4D, 0xFC, 0xA0, 0xFC, 0x5A, 0x00, 0xCD, - 0x00, 0x0C, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x77, 0x00, 0xE9, 0x00, - 0x3F, 0xFE, 0x3F, 0xFB, 0x82, 0x02, 0x23, 0x15, 0x6B, 0x21, 0xE5, - 0x18, 0xBE, 0x05, 0x93, 0xFB, 0x5E, 0xFD, 0xAF, 0x00, 0xA6, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xA0, 0x00, 0xB9, - 0x00, 0x7C, 0xFD, 0x80, 0xFB, 0x48, 0x05, 0x6B, 0x18, 0x79, 0x21, - 0xA9, 0x15, 0xE9, 0x02, 0x43, 0xFB, 0x21, 0xFE, 0xE3, 0x00, 0x7D, - 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x09, 0x00, 0xC7, 0x00, 0x69, 0x00, - 0xBC, 0xFC, 0x29, 0xFC, 0x69, 0x08, 0x5C, 0x1B, 0xCC, 0x20, 0x32, - 0x12, 0x7C, 0x00, 0x4E, 0xFB, 0xDD, 0xFE, 0xFA, 0x00, 0x56, 0x00, - 0xF7, 0xFF, 0xFB, 0xFF, 0x1D, 0x00, 0xE7, 0x00, 0xF8, 0xFF, 0x12, - 0xFC, 0x45, 0xFD, 0xCB, 0x0B, 0xD6, 0x1D, 0x6C, 0x1F, 0xA3, 0x0E, - 0x84, 0xFE, 0xA4, 0xFB, 0x84, 0xFF, 0xF7, 0x00, 0x34, 0x00, 0xF9, - 0xFF, 0xF8, 0xFF, 0x3A, 0x00, 0xFA, 0x00, 0x66, 0xFF, 0x8E, 0xFB, - 0xDB, 0xFE, 0x53, 0x0F, 0xBD, 0x1F, 0x66, 0x1D, 0x21, 0x0B, 0x05, - 0xFD, 0x30, 0xFC, 0x10, 0x00, 0xE2, 0x00, 0x19, 0x00, 0xFC, 0xFF, - 0xF7, 0xFF, 0x5D, 0x00, 0xF8, 0x00, 0xBA, 0xFE, 0x46, 0xFB, 0xEA, - 0x00, 0xDF, 0x12, 0xFC, 0x20, 0xD3, 0x1A, 0xC9, 0x07, 0x00, 0xFC, - 0xE0, 0xFC, 0x7B, 0x00, 0xC0, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xF9, - 0xFF, 0x85, 0x00, 0xDC, 0x00, 0xFC, 0xFD, 0x4A, 0xFB, 0x6C, 0x03, - 0x4E, 0x16, 0x85, 0x21, 0xCF, 0x17, 0xB8, 0x04, 0x6C, 0xFB, 0xA2, - 0xFD, 0xC5, 0x00, 0x98, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFF, 0xFF, - 0x01, 0x00, 0xAE, 0x00, 0xA1, 0x00, 0x38, 0xFD, 0xAE, 0xFB, 0x54, - 0x06, 0x7C, 0x19, 0x53, 0x21, 0x7B, 0x14, 0x05, 0x02, 0x3D, 0xFB, - 0x64, 0xFE, 0xEE, 0x00, 0x6F, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x0F, - 0x00, 0xD4, 0x00, 0x46, 0x00, 0x7E, 0xFC, 0x7E, 0xFC, 0x8E, 0x09, - 0x46, 0x1C, 0x66, 0x20, 0xF7, 0x10, 0xC0, 0xFF, 0x64, 0xFB, 0x1A, - 0xFF, 0xFC, 0x00, 0x49, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x26, 0x00, - 0xF0, 0x00, 0xC9, 0xFF, 0xDF, 0xFB, 0xC4, 0xFD, 0x01, 0x0D, 0x90, - 0x1E, 0xCA, 0x1E, 0x69, 0x0D, 0xF1, 0xFD, 0xCF, 0xFB, 0xB8, 0xFF, - 0xF2, 0x00, 0x29, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x45, 0x00, 0xFC, - 0x00, 0x2D, 0xFF, 0x6D, 0xFB, 0x84, 0xFF, 0x8E, 0x10, 0x3F, 0x20, - 0x91, 0x1C, 0xF2, 0x09, 0x9D, 0xFC, 0x6A, 0xFC, 0x39, 0x00, 0xD7, - 0x00, 0x12, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6A, 0x00, 0xF1, 0x00, - 0x7A, 0xFE, 0x3D, 0xFB, 0xBC, 0x01, 0x14, 0x14, 0x41, 0x21, 0xD4, - 0x19, 0xB0, 0x06, 0xC0, 0xFB, 0x22, 0xFD, 0x99, 0x00, 0xB3, 0x00, - 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x93, 0x00, 0xCB, - 0x00, 0xB8, 0xFD, 0x61, 0xFB, 0x63, 0x04, 0x71, 0x17, 0x89, 0x21, - 0xB0, 0x16, 0xBD, 0x03, 0x51, 0xFB, 0xE6, 0xFD, 0xD7, 0x00, 0x8A, - 0x00, 0xFA, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0xBC, 0x00, 0x86, 0x00, - 0xF6, 0xFC, 0xE9, 0xFB, 0x6A, 0x07, 0x80, 0x1A, 0x15, 0x21, 0x47, - 0x13, 0x2F, 0x01, 0x42, 0xFB, 0xA5, 0xFE, 0xF6, 0x00, 0x61, 0x00, - 0xF7, 0xFF, 0xFC, 0xFF, 0x16, 0x00, 0xDF, 0x00, 0x1E, 0x00, 0x43, - 0xFC, 0xE1, 0xFC, 0xBB, 0x0A, 0x21, 0x1D, 0xEA, 0x1F, 0xBC, 0x0F, - 0x12, 0xFF, 0x82, 0xFB, 0x54, 0xFF, 0xFA, 0x00, 0x3D, 0x00, 0xF8, - 0xFF, 0xF9, 0xFF, 0x30, 0x00, 0xF6, 0x00, 0x96, 0xFF, 0xB1, 0xFB, - 0x51, 0xFE, 0x3A, 0x0E, 0x38, 0x1F, 0x16, 0x1E, 0x32, 0x0C, 0x6E, - 0xFD, 0x00, 0xFC, 0xE8, 0xFF, 0xEA, 0x00, 0x20, 0x00, 0xFB, 0xFF, - 0xF7, 0xFF, 0x51, 0x00, 0xFB, 0x00, 0xF1, 0xFE, 0x54, 0xFB, 0x3B, - 0x00, 0xC9, 0x11, 0xAD, 0x20, 0xAC, 0x1B, 0xCA, 0x08, 0x44, 0xFC, - 0xA7, 0xFC, 0x5E, 0x00, 0xCC, 0x00, 0x0B, 0x00, 0xFE, 0xFF, 0xF8, - 0xFF, 0x78, 0x00, 0xE7, 0x00, 0x38, 0xFE, 0x40, 0xFB, 0x9B, 0x02, - 0x45, 0x15, 0x6F, 0x21, 0xC7, 0x18, 0xA1, 0x05, 0x8E, 0xFB, 0x65, - 0xFD, 0xB2, 0x00, 0xA5, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0xFF, 0xA2, 0x00, 0xB7, 0x00, 0x74, 0xFD, 0x84, 0xFB, 0x66, - 0x05, 0x8A, 0x18, 0x76, 0x21, 0x87, 0x15, 0xCF, 0x02, 0x41, 0xFB, - 0x29, 0xFE, 0xE5, 0x00, 0x7B, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0A, - 0x00, 0xC9, 0x00, 0x66, 0x00, 0xB5, 0xFC, 0x32, 0xFC, 0x89, 0x08, - 0x77, 0x1B, 0xC2, 0x20, 0x0F, 0x12, 0x66, 0x00, 0x50, 0xFB, 0xE4, - 0xFE, 0xFA, 0x00, 0x54, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x1E, 0x00, - 0xE8, 0x00, 0xF3, 0xFF, 0x0C, 0xFC, 0x53, 0xFD, 0xED, 0x0B, 0xEB, - 0x1D, 0x5A, 0x1F, 0x80, 0x0E, 0x73, 0xFE, 0xA8, 0xFB, 0x8A, 0xFF, - 0xF7, 0x00, 0x32, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3B, 0x00, 0xFA, - 0x00, 0x60, 0xFF, 0x8A, 0xFB, 0xED, 0xFE, 0x76, 0x0F, 0xCC, 0x1F, - 0x4F, 0x1D, 0xFF, 0x0A, 0xF9, 0xFC, 0x36, 0xFC, 0x15, 0x00, 0xE1, - 0x00, 0x18, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x5E, 0x00, 0xF7, 0x00, - 0xB3, 0xFE, 0x44, 0xFB, 0x01, 0x01, 0x02, 0x13, 0x04, 0x21, 0xB8, - 0x1A, 0xA9, 0x07, 0xF8, 0xFB, 0xE7, 0xFC, 0x7F, 0x00, 0xBF, 0x00, - 0x06, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, 0x86, 0x00, 0xDA, 0x00, 0xF5, - 0xFD, 0x4C, 0xFB, 0x87, 0x03, 0x6E, 0x16, 0x86, 0x21, 0xB0, 0x17, - 0x9C, 0x04, 0x68, 0xFB, 0xA9, 0xFD, 0xC7, 0x00, 0x96, 0x00, 0xFB, - 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xB0, 0x00, 0x9F, 0x00, - 0x31, 0xFD, 0xB4, 0xFB, 0x73, 0x06, 0x99, 0x19, 0x4D, 0x21, 0x59, - 0x14, 0xED, 0x01, 0x3D, 0xFB, 0x6B, 0xFE, 0xEF, 0x00, 0x6D, 0x00, - 0xF7, 0xFF, 0xFD, 0xFF, 0x10, 0x00, 0xD5, 0x00, 0x42, 0x00, 0x77, - 0xFC, 0x88, 0xFC, 0xAF, 0x09, 0x5F, 0x1C, 0x59, 0x20, 0xD4, 0x10, - 0xAC, 0xFF, 0x67, 0xFB, 0x20, 0xFF, 0xFC, 0x00, 0x48, 0x00, 0xF7, - 0xFF, 0xFA, 0xFF, 0x27, 0x00, 0xF0, 0x00, 0xC3, 0xFF, 0xD9, 0xFB, - 0xD3, 0xFD, 0x24, 0x0D, 0xA3, 0x1E, 0xB7, 0x1E, 0x46, 0x0D, 0xE2, - 0xFD, 0xD4, 0xFB, 0xBE, 0xFF, 0xF1, 0x00, 0x28, 0x00, 0xFA, 0xFF, - 0xF7, 0xFF, 0x46, 0x00, 0xFC, 0x00, 0x27, 0xFF, 0x6A, 0xFB, 0x98, - 0xFF, 0xB1, 0x10, 0x4C, 0x20, 0x78, 0x1C, 0xD1, 0x09, 0x93, 0xFC, - 0x71, 0xFC, 0x3D, 0x00, 0xD6, 0x00, 0x11, 0x00, 0xFD, 0xFF, 0xF7, - 0xFF, 0x6C, 0x00, 0xF0, 0x00, 0x72, 0xFE, 0x3D, 0xFB, 0xD4, 0x01, - 0x36, 0x14, 0x47, 0x21, 0xB6, 0x19, 0x91, 0x06, 0xBA, 0xFB, 0x29, - 0xFD, 0x9C, 0x00, 0xB1, 0x00, 0x02, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0xFB, 0xFF, 0x95, 0x00, 0xC9, 0x00, 0xB1, 0xFD, 0x65, 0xFB, 0x80, - 0x04, 0x90, 0x17, 0x88, 0x21, 0x8F, 0x16, 0xA2, 0x03, 0x4E, 0xFB, - 0xED, 0xFD, 0xD9, 0x00, 0x88, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x05, - 0x00, 0xBD, 0x00, 0x82, 0x00, 0xEF, 0xFC, 0xF0, 0xFB, 0x8A, 0x07, - 0x9C, 0x1A, 0x0D, 0x21, 0x24, 0x13, 0x18, 0x01, 0x43, 0xFB, 0xAC, - 0xFE, 0xF7, 0x00, 0x60, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x17, 0x00, - 0xE0, 0x00, 0x1A, 0x00, 0x3D, 0xFC, 0xED, 0xFC, 0xDD, 0x0A, 0x38, - 0x1D, 0xDB, 0x1F, 0x99, 0x0F, 0xFF, 0xFE, 0x86, 0xFB, 0x5A, 0xFF, - 0xFA, 0x00, 0x3C, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x31, 0x00, 0xF6, - 0x00, 0x90, 0xFF, 0xAD, 0xFB, 0x62, 0xFE, 0x5D, 0x0E, 0x49, 0x1F, - 0x01, 0x1E, 0x10, 0x0C, 0x60, 0xFD, 0x06, 0xFC, 0xEE, 0xFF, 0xE9, - 0x00, 0x1F, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x53, 0x00, 0xFB, 0x00, - 0xEB, 0xFE, 0x52, 0xFB, 0x51, 0x00, 0xEC, 0x11, 0xB7, 0x20, 0x91, - 0x1B, 0xA9, 0x08, 0x3B, 0xFC, 0xAE, 0xFC, 0x62, 0x00, 0xCA, 0x00, - 0x0B, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7A, 0x00, 0xE6, 0x00, 0x30, - 0xFE, 0x40, 0xFB, 0xB5, 0x02, 0x66, 0x15, 0x73, 0x21, 0xA9, 0x18, - 0x83, 0x05, 0x89, 0xFB, 0x6D, 0xFD, 0xB4, 0x00, 0xA3, 0x00, 0xFE, - 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xA3, 0x00, 0xB4, 0x00, - 0x6D, 0xFD, 0x89, 0xFB, 0x83, 0x05, 0xA9, 0x18, 0x73, 0x21, 0x66, - 0x15, 0xB5, 0x02, 0x40, 0xFB, 0x30, 0xFE, 0xE6, 0x00, 0x7A, 0x00, - 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00, 0xCA, 0x00, 0x62, 0x00, 0xAE, - 0xFC, 0x3B, 0xFC, 0xA9, 0x08, 0x91, 0x1B, 0xB7, 0x20, 0xEC, 0x11, - 0x51, 0x00, 0x52, 0xFB, 0xEB, 0xFE, 0xFB, 0x00, 0x53, 0x00, 0xF7, - 0xFF, 0xFB, 0xFF, 0x1F, 0x00, 0xE9, 0x00, 0xEE, 0xFF, 0x06, 0xFC, - 0x60, 0xFD, 0x10, 0x0C, 0x01, 0x1E, 0x49, 0x1F, 0x5D, 0x0E, 0x62, - 0xFE, 0xAD, 0xFB, 0x90, 0xFF, 0xF6, 0x00, 0x31, 0x00, 0xF9, 0xFF, - 0xF8, 0xFF, 0x3C, 0x00, 0xFA, 0x00, 0x5A, 0xFF, 0x86, 0xFB, 0xFF, - 0xFE, 0x99, 0x0F, 0xDB, 0x1F, 0x38, 0x1D, 0xDD, 0x0A, 0xED, 0xFC, - 0x3D, 0xFC, 0x1A, 0x00, 0xE0, 0x00, 0x17, 0x00, 0xFC, 0xFF, 0xF7, - 0xFF, 0x60, 0x00, 0xF7, 0x00, 0xAC, 0xFE, 0x43, 0xFB, 0x18, 0x01, - 0x24, 0x13, 0x0D, 0x21, 0x9C, 0x1A, 0x8A, 0x07, 0xF0, 0xFB, 0xEF, - 0xFC, 0x82, 0x00, 0xBD, 0x00, 0x05, 0x00, 0xFF, 0xFF, 0xF9, 0xFF, - 0x88, 0x00, 0xD9, 0x00, 0xED, 0xFD, 0x4E, 0xFB, 0xA2, 0x03, 0x8F, - 0x16, 0x88, 0x21, 0x90, 0x17, 0x80, 0x04, 0x65, 0xFB, 0xB1, 0xFD, - 0xC9, 0x00, 0x95, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02, - 0x00, 0xB1, 0x00, 0x9C, 0x00, 0x29, 0xFD, 0xBA, 0xFB, 0x91, 0x06, - 0xB6, 0x19, 0x47, 0x21, 0x36, 0x14, 0xD4, 0x01, 0x3D, 0xFB, 0x72, - 0xFE, 0xF0, 0x00, 0x6C, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x11, 0x00, - 0xD6, 0x00, 0x3D, 0x00, 0x71, 0xFC, 0x93, 0xFC, 0xD1, 0x09, 0x78, - 0x1C, 0x4C, 0x20, 0xB1, 0x10, 0x98, 0xFF, 0x6A, 0xFB, 0x27, 0xFF, - 0xFC, 0x00, 0x46, 0x00, 0xF7, 0xFF, 0xFA, 0xFF, 0x28, 0x00, 0xF1, - 0x00, 0xBE, 0xFF, 0xD4, 0xFB, 0xE2, 0xFD, 0x46, 0x0D, 0xB7, 0x1E, - 0xA3, 0x1E, 0x24, 0x0D, 0xD3, 0xFD, 0xD9, 0xFB, 0xC3, 0xFF, 0xF0, - 0x00, 0x27, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x48, 0x00, 0xFC, 0x00, - 0x20, 0xFF, 0x67, 0xFB, 0xAC, 0xFF, 0xD4, 0x10, 0x59, 0x20, 0x5F, - 0x1C, 0xAF, 0x09, 0x88, 0xFC, 0x77, 0xFC, 0x42, 0x00, 0xD5, 0x00, - 0x10, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x6D, 0x00, 0xEF, 0x00, 0x6B, - 0xFE, 0x3D, 0xFB, 0xED, 0x01, 0x59, 0x14, 0x4D, 0x21, 0x99, 0x19, - 0x73, 0x06, 0xB4, 0xFB, 0x31, 0xFD, 0x9F, 0x00, 0xB0, 0x00, 0x01, - 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFB, 0xFF, 0x96, 0x00, 0xC7, 0x00, - 0xA9, 0xFD, 0x68, 0xFB, 0x9C, 0x04, 0xB0, 0x17, 0x86, 0x21, 0x6E, - 0x16, 0x87, 0x03, 0x4C, 0xFB, 0xF5, 0xFD, 0xDA, 0x00, 0x86, 0x00, - 0xF9, 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0xBF, 0x00, 0x7F, 0x00, 0xE7, - 0xFC, 0xF8, 0xFB, 0xA9, 0x07, 0xB8, 0x1A, 0x04, 0x21, 0x02, 0x13, - 0x01, 0x01, 0x44, 0xFB, 0xB3, 0xFE, 0xF7, 0x00, 0x5E, 0x00, 0xF7, - 0xFF, 0xFC, 0xFF, 0x18, 0x00, 0xE1, 0x00, 0x15, 0x00, 0x36, 0xFC, - 0xF9, 0xFC, 0xFF, 0x0A, 0x4F, 0x1D, 0xCC, 0x1F, 0x76, 0x0F, 0xED, - 0xFE, 0x8A, 0xFB, 0x60, 0xFF, 0xFA, 0x00, 0x3B, 0x00, 0xF8, 0xFF, - 0xF9, 0xFF, 0x32, 0x00, 0xF7, 0x00, 0x8A, 0xFF, 0xA8, 0xFB, 0x73, - 0xFE, 0x80, 0x0E, 0x5A, 0x1F, 0xEB, 0x1D, 0xED, 0x0B, 0x53, 0xFD, - 0x0C, 0xFC, 0xF3, 0xFF, 0xE8, 0x00, 0x1E, 0x00, 0xFB, 0xFF, 0xF7, - 0xFF, 0x54, 0x00, 0xFA, 0x00, 0xE4, 0xFE, 0x50, 0xFB, 0x66, 0x00, - 0x0F, 0x12, 0xC2, 0x20, 0x77, 0x1B, 0x89, 0x08, 0x32, 0xFC, 0xB5, - 0xFC, 0x66, 0x00, 0xC9, 0x00, 0x0A, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, - 0x7B, 0x00, 0xE5, 0x00, 0x29, 0xFE, 0x41, 0xFB, 0xCF, 0x02, 0x87, - 0x15, 0x76, 0x21, 0x8A, 0x18, 0x66, 0x05, 0x84, 0xFB, 0x74, 0xFD, - 0xB7, 0x00, 0xA2, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFE, - 0xFF, 0xA5, 0x00, 0xB2, 0x00, 0x65, 0xFD, 0x8E, 0xFB, 0xA1, 0x05, - 0xC7, 0x18, 0x6F, 0x21, 0x45, 0x15, 0x9B, 0x02, 0x40, 0xFB, 0x38, - 0xFE, 0xE7, 0x00, 0x78, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0B, 0x00, - 0xCC, 0x00, 0x5E, 0x00, 0xA7, 0xFC, 0x44, 0xFC, 0xCA, 0x08, 0xAC, - 0x1B, 0xAD, 0x20, 0xC9, 0x11, 0x3B, 0x00, 0x54, 0xFB, 0xF1, 0xFE, - 0xFB, 0x00, 0x51, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x20, 0x00, 0xEA, - 0x00, 0xE8, 0xFF, 0x00, 0xFC, 0x6E, 0xFD, 0x32, 0x0C, 0x16, 0x1E, - 0x38, 0x1F, 0x3A, 0x0E, 0x51, 0xFE, 0xB1, 0xFB, 0x96, 0xFF, 0xF6, - 0x00, 0x30, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x3D, 0x00, 0xFA, 0x00, - 0x54, 0xFF, 0x82, 0xFB, 0x12, 0xFF, 0xBC, 0x0F, 0xEA, 0x1F, 0x21, - 0x1D, 0xBB, 0x0A, 0xE1, 0xFC, 0x43, 0xFC, 0x1E, 0x00, 0xDF, 0x00, - 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x61, 0x00, 0xF6, 0x00, 0xA5, - 0xFE, 0x42, 0xFB, 0x2F, 0x01, 0x47, 0x13, 0x15, 0x21, 0x80, 0x1A, - 0x6A, 0x07, 0xE9, 0xFB, 0xF6, 0xFC, 0x86, 0x00, 0xBC, 0x00, 0x05, - 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8A, 0x00, 0xD7, 0x00, 0xE6, 0xFD, - 0x51, 0xFB, 0xBD, 0x03, 0xB0, 0x16, 0x89, 0x21, 0x71, 0x17, 0x63, - 0x04, 0x61, 0xFB, 0xB8, 0xFD, 0xCB, 0x00, 0x93, 0x00, 0xFB, 0xFF, - 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, 0xB3, 0x00, 0x99, 0x00, 0x22, - 0xFD, 0xC0, 0xFB, 0xB0, 0x06, 0xD4, 0x19, 0x41, 0x21, 0x14, 0x14, - 0xBC, 0x01, 0x3D, 0xFB, 0x7A, 0xFE, 0xF1, 0x00, 0x6A, 0x00, 0xF7, - 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD7, 0x00, 0x39, 0x00, 0x6A, 0xFC, - 0x9D, 0xFC, 0xF2, 0x09, 0x91, 0x1C, 0x3F, 0x20, 0x8E, 0x10, 0x84, - 0xFF, 0x6D, 0xFB, 0x2D, 0xFF, 0xFC, 0x00, 0x45, 0x00, 0xF7, 0xFF, - 0xFA, 0xFF, 0x29, 0x00, 0xF2, 0x00, 0xB8, 0xFF, 0xCF, 0xFB, 0xF1, - 0xFD, 0x69, 0x0D, 0xCA, 0x1E, 0x90, 0x1E, 0x01, 0x0D, 0xC4, 0xFD, - 0xDF, 0xFB, 0xC9, 0xFF, 0xF0, 0x00, 0x26, 0x00, 0xFA, 0xFF, 0xF7, - 0xFF, 0x49, 0x00, 0xFC, 0x00, 0x1A, 0xFF, 0x64, 0xFB, 0xC0, 0xFF, - 0xF7, 0x10, 0x66, 0x20, 0x46, 0x1C, 0x8E, 0x09, 0x7E, 0xFC, 0x7E, - 0xFC, 0x46, 0x00, 0xD4, 0x00, 0x0F, 0x00, 0xFD, 0xFF, 0xF7, 0xFF, - 0x6F, 0x00, 0xEE, 0x00, 0x64, 0xFE, 0x3D, 0xFB, 0x05, 0x02, 0x7B, - 0x14, 0x53, 0x21, 0x7C, 0x19, 0x54, 0x06, 0xAE, 0xFB, 0x38, 0xFD, - 0xA1, 0x00, 0xAE, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFC, - 0xFF, 0x98, 0x00, 0xC5, 0x00, 0xA2, 0xFD, 0x6C, 0xFB, 0xB8, 0x04, - 0xCF, 0x17, 0x85, 0x21, 0x4E, 0x16, 0x6C, 0x03, 0x4A, 0xFB, 0xFC, - 0xFD, 0xDC, 0x00, 0x85, 0x00, 0xF9, 0xFF, 0xFF, 0xFF, 0x07, 0x00, - 0xC0, 0x00, 0x7B, 0x00, 0xE0, 0xFC, 0x00, 0xFC, 0xC9, 0x07, 0xD3, - 0x1A, 0xFC, 0x20, 0xDF, 0x12, 0xEA, 0x00, 0x46, 0xFB, 0xBA, 0xFE, - 0xF8, 0x00, 0x5D, 0x00, 0xF7, 0xFF, 0xFC, 0xFF, 0x19, 0x00, 0xE2, - 0x00, 0x10, 0x00, 0x30, 0xFC, 0x05, 0xFD, 0x21, 0x0B, 0x66, 0x1D, - 0xBD, 0x1F, 0x53, 0x0F, 0xDB, 0xFE, 0x8E, 0xFB, 0x66, 0xFF, 0xFA, - 0x00, 0x3A, 0x00, 0xF8, 0xFF, 0xF9, 0xFF, 0x34, 0x00, 0xF7, 0x00, - 0x84, 0xFF, 0xA4, 0xFB, 0x84, 0xFE, 0xA3, 0x0E, 0x6C, 0x1F, 0xD6, - 0x1D, 0xCB, 0x0B, 0x45, 0xFD, 0x12, 0xFC, 0xF8, 0xFF, 0xE7, 0x00, - 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, 0x56, 0x00, 0xFA, 0x00, 0xDD, - 0xFE, 0x4E, 0xFB, 0x7C, 0x00, 0x32, 0x12, 0xCC, 0x20, 0x5C, 0x1B, - 0x69, 0x08, 0x29, 0xFC, 0xBC, 0xFC, 0x69, 0x00, 0xC7, 0x00, 0x09, - 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7D, 0x00, 0xE3, 0x00, 0x21, 0xFE, - 0x43, 0xFB, 0xE9, 0x02, 0xA9, 0x15, 0x79, 0x21, 0x6B, 0x18, 0x48, - 0x05, 0x80, 0xFB, 0x7C, 0xFD, 0xB9, 0x00, 0xA0, 0x00, 0xFD, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x00, 0xAF, 0x00, 0x5E, - 0xFD, 0x93, 0xFB, 0xBE, 0x05, 0xE5, 0x18, 0x6B, 0x21, 0x23, 0x15, - 0x82, 0x02, 0x3F, 0xFB, 0x3F, 0xFE, 0xE9, 0x00, 0x77, 0x00, 0xF8, - 0xFF, 0xFE, 0xFF, 0x0C, 0x00, 0xCD, 0x00, 0x5A, 0x00, 0xA0, 0xFC, - 0x4D, 0xFC, 0xEA, 0x08, 0xC6, 0x1B, 0xA1, 0x20, 0xA6, 0x11, 0x26, - 0x00, 0x57, 0xFB, 0xF8, 0xFE, 0xFB, 0x00, 0x50, 0x00, 0xF7, 0xFF, - 0xFB, 0xFF, 0x21, 0x00, 0xEB, 0x00, 0xE3, 0xFF, 0xFA, 0xFB, 0x7C, - 0xFD, 0x54, 0x0C, 0x2B, 0x1E, 0x26, 0x1F, 0x17, 0x0E, 0x41, 0xFE, - 0xB6, 0xFB, 0x9C, 0xFF, 0xF5, 0x00, 0x2F, 0x00, 0xF9, 0xFF, 0xF8, - 0xFF, 0x3F, 0x00, 0xFB, 0x00, 0x4D, 0xFF, 0x7F, 0xFB, 0x24, 0xFF, - 0xDF, 0x0F, 0xF9, 0x1F, 0x09, 0x1D, 0x99, 0x0A, 0xD5, 0xFC, 0x49, - 0xFC, 0x23, 0x00, 0xDD, 0x00, 0x16, 0x00, 0xFC, 0xFF, 0xF7, 0xFF, - 0x63, 0x00, 0xF5, 0x00, 0x9E, 0xFE, 0x41, 0xFB, 0x46, 0x01, 0x69, - 0x13, 0x1D, 0x21, 0x63, 0x1A, 0x4B, 0x07, 0xE2, 0xFB, 0xFD, 0xFC, - 0x89, 0x00, 0xBA, 0x00, 0x04, 0x00, 0xFF, 0xFF, 0xFA, 0xFF, 0x8B, - 0x00, 0xD5, 0x00, 0xDE, 0xFD, 0x53, 0xFB, 0xD9, 0x03, 0xD0, 0x16, - 0x8A, 0x21, 0x51, 0x17, 0x47, 0x04, 0x5E, 0xFB, 0xC0, 0xFD, 0xCD, - 0x00, 0x92, 0x00, 0xFB, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, - 0xB4, 0x00, 0x96, 0x00, 0x1B, 0xFD, 0xC7, 0xFB, 0xCF, 0x06, 0xF0, - 0x19, 0x3A, 0x21, 0xF2, 0x13, 0xA4, 0x01, 0x3E, 0xFB, 0x81, 0xFE, - 0xF2, 0x00, 0x69, 0x00, 0xF7, 0xFF, 0xFD, 0xFF, 0x12, 0x00, 0xD9, - 0x00, 0x35, 0x00, 0x63, 0xFC, 0xA8, 0xFC, 0x13, 0x0A, 0xA9, 0x1C, - 0x32, 0x20, 0x6B, 0x10, 0x71, 0xFF, 0x71, 0xFB, 0x34, 0xFF, 0xFB, - 0x00, 0x44, 0x00, 0xF8, 0xFF, 0xFA, 0xFF, 0x2B, 0x00, 0xF3, 0x00, - 0xB3, 0xFF, 0xCA, 0xFB, 0x01, 0xFE, 0x8C, 0x0D, 0xDD, 0x1E, 0x7C, - 0x1E, 0xDE, 0x0C, 0xB5, 0xFD, 0xE4, 0xFB, 0xCE, 0xFF, 0xEF, 0x00, - 0x25, 0x00, 0xFA, 0xFF, 0xF7, 0xFF, 0x4A, 0x00, 0xFC, 0x00, 0x13, - 0xFF, 0x61, 0xFB, 0xD4, 0xFF, 0x1A, 0x11, 0x72, 0x20, 0x2D, 0x1C, - 0x6D, 0x09, 0x74, 0xFC, 0x85, 0xFC, 0x4A, 0x00, 0xD2, 0x00, 0x0F, - 0x00, 0xFD, 0xFF, 0xF7, 0xFF, 0x70, 0x00, 0xED, 0x00, 0x5D, 0xFE, - 0x3D, 0xFB, 0x1E, 0x02, 0x9C, 0x14, 0x58, 0x21, 0x5E, 0x19, 0x36, - 0x06, 0xA8, 0xFB, 0x40, 0xFD, 0xA4, 0x00, 0xAD, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x00, 0x00, 0xFC, 0xFF, 0x9A, 0x00, 0xC3, 0x00, 0x9A, - 0xFD, 0x6F, 0xFB, 0xD5, 0x04, 0xEF, 0x17, 0x83, 0x21, 0x2D, 0x16, - 0x52, 0x03, 0x49, 0xFB, 0x04, 0xFE, 0xDD, 0x00, 0x83, 0x00, 0xF9, - 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xC2, 0x00, 0x78, 0x00, 0xD9, 0xFC, - 0x08, 0xFC, 0xE9, 0x07, 0xEF, 0x1A, 0xF3, 0x20, 0xBC, 0x12, 0xD4, - 0x00, 0x47, 0xFB, 0xC1, 0xFE, 0xF8, 0x00, 0x5B, 0x00, 0xF7, 0xFF, - 0xFC, 0xFF, 0x1A, 0x00, 0xE3, 0x00, 0x0B, 0x00, 0x2A, 0xFC, 0x12, - 0xFD, 0x42, 0x0B, 0x7D, 0x1D, 0xAD, 0x1F, 0x2F, 0x0F, 0xC9, 0xFE, - 0x92, 0xFB, 0x6C, 0xFF, 0xF9, 0x00, 0x38, 0x00, 0xF8, 0xFF, 0xF9, - 0xFF, 0x35, 0x00, 0xF8, 0x00, 0x7E, 0xFF, 0x9F, 0xFB, 0x95, 0xFE, - 0xC6, 0x0E, 0x7C, 0x1F, 0xC0, 0x1D, 0xA9, 0x0B, 0x38, 0xFD, 0x18, - 0xFC, 0xFD, 0xFF, 0xE6, 0x00, 0x1D, 0x00, 0xFB, 0xFF, 0xF7, 0xFF, - 0x57, 0x00, 0xFA, 0x00, 0xD6, 0xFE, 0x4C, 0xFB, 0x92, 0x00, 0x54, - 0x12, 0xD6, 0x20, 0x41, 0x1B, 0x49, 0x08, 0x20, 0xFC, 0xC3, 0xFC, - 0x6D, 0x00, 0xC6, 0x00, 0x09, 0x00, 0xFE, 0xFF, 0xF8, 0xFF, 0x7E, - 0x00, 0xE2, 0x00, 0x1A, 0xFE, 0x44, 0xFB, 0x03, 0x03, 0xCA, 0x15, - 0x7C, 0x21, 0x4C, 0x18, 0x2B, 0x05, 0x7B, 0xFB, 0x83, 0xFD, 0xBC, - 0x00, 0x9E, 0x00, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xA8, 0x00, 0xAD, 0x00, 0x56, 0xFD, 0x98, 0xFB, 0xDC, 0x05, 0x04, - 0x19, 0x66, 0x21, 0x02, 0x15, 0x69, 0x02, 0x3E, 0xFB, 0x47, 0xFE, - 0xEA, 0x00, 0x75, 0x00, 0xF8, 0xFF, 0xFE, 0xFF, 0x0D, 0x00, 0xCE, - 0x00, 0x56, 0x00, 0x99, 0xFC, 0x56, 0xFC, 0x0B, 0x09, 0xE0, 0x1B, - 0x96, 0x20, 0x83, 0x11, 0x11, 0x00, 0x59, 0xFB, 0xFF, 0xFE, 0xFB, - 0x00, 0x4E, 0x00, 0xF7, 0xFF, 0xFB, 0xFF, 0x22, 0x00, 0xEC, 0x00, - 0xDE, 0xFF, 0xF5, 0xFB, 0x8A, 0xFD, 0x77, 0x0C, 0x3F, 0x1E, 0x14, - 0x1F, 0xF5, 0x0D, 0x31, 0xFE, 0xBB, 0xFB, 0xA2, 0xFF, 0xF5, 0x00, - 0x2E, 0x00, 0xF9, 0xFF, 0xF8, 0xFF, 0x40, 0x00, 0xFB, 0x00, 0x47, - 0xFF, 0x7B, 0xFB, 0x37, 0xFF, 0x02, 0x10, 0x07, 0x20, 0xF2, 0x1C, - 0x78, 0x0A, 0xCA, 0xFC, 0x50, 0xFC, 0x27, 0x00, 0xDC, 0x00, 0x15, - 0x00, 0xFC, 0xFF, 0xF7, 0xFF, 0x64, 0x00, 0xF5, 0x00, 0x97, 0xFE, - 0x40, 0xFB, 0x5D, 0x01, 0x8B, 0x13, 0x25, 0x21, 0x47, 0x1A, 0x2C, - 0x07, 0xDB, 0xFB, 0x05, 0xFD, 0x8C, 0x00, 0xB9, 0x00, 0x04, 0x00, - 0xFF, 0xFF, 0xFA, 0xFF, 0x8D, 0x00, 0xD3, 0x00, 0xD6, 0xFD, 0x56, - 0xFB, 0xF4, 0x03, 0xF0, 0x16, 0x8A, 0x21, 0x31, 0x17, 0x2B, 0x04, - 0x5B, 0xFB, 0xC7, 0xFD, 0xCF, 0x00, 0x90, 0x00, 0xFA, 0xFF, 0x00, - 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xB6, 0x00, 0x92, 0x00, 0x13, 0xFD, - 0xCD, 0xFB, 0xEE, 0x06, 0x0D, 0x1A, 0x33, 0x21, 0xD0, 0x13, 0x8C, - 0x01, 0x3E, 0xFB, 0x88, 0xFE, 0xF3, 0x00, 0x67, 0x00, 0xF7, 0xFF, - 0x06, 0x00, 0x1D, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0xA1, 0x02, 0xA6, - 0xF8, 0x56, 0x02, 0xA5, 0x28, 0xA5, 0x28, 0x56, 0x02, 0xA6, 0xF8, - 0xA1, 0x02, 0xFE, 0x00, 0x03, 0xFF, 0x1D, 0x00, 0x06, 0x00, 0x00, - 0x00, 0x21, 0x00, 0xA6, 0xFF, 0x3F, 0xFF, 0x0B, 0x03, 0x42, 0xFE, - 0x3E, 0xF8, 0x7F, 0x15, 0xAC, 0x30, 0x7F, 0x15, 0x3E, 0xF8, 0x42, - 0xFE, 0x0B, 0x03, 0x3F, 0xFF, 0xA6, 0xFF, 0x21, 0x00, 0x00, 0x00, - 0xFA, 0xFF, 0xCE, 0xFF, 0x14, 0x01, 0x00, 0xFD, 0x35, 0x06, 0xD5, - 0xF4, 0xDA, 0x15, 0x92, 0x40, 0xAE, 0xFE, 0xF3, 0xFC, 0x68, 0x03, - 0x86, 0xFD, 0x51, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEC, - 0xFF, 0xF9, 0xFF, 0xC6, 0x00, 0x55, 0xFD, 0x35, 0x06, 0x90, 0xF3, - 0xE5, 0x1C, 0x6B, 0x3D, 0x71, 0xFA, 0x34, 0xFF, 0x46, 0x02, 0xFF, - 0xFD, 0x2D, 0x01, 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDB, 0xFF, - 0x2D, 0x00, 0x60, 0x00, 0xE1, 0xFD, 0xCE, 0x05, 0xED, 0xF2, 0xF3, - 0x23, 0x20, 0x39, 0x22, 0xF7, 0x44, 0x01, 0x1F, 0x01, 0x89, 0xFE, - 0xFB, 0x00, 0x9C, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC9, 0xFF, 0x68, - 0x00, 0xE5, 0xFF, 0xA0, 0xFE, 0xFB, 0x04, 0x0C, 0xF3, 0xC5, 0x2A, - 0xD8, 0x33, 0xC9, 0xF4, 0x0B, 0x03, 0x05, 0x00, 0x1A, 0xFF, 0xC1, - 0x00, 0xAD, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB5, 0xFF, 0xA5, 0x00, - 0x5C, 0xFF, 0x8C, 0xFF, 0xBF, 0x03, 0x06, 0xF4, 0x22, 0x31, 0xC8, - 0x2D, 0x63, 0xF3, 0x76, 0x04, 0x08, 0xFF, 0xA7, 0xFF, 0x84, 0x00, - 0xC0, 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA4, 0xFF, 0xE1, 0x00, 0xCB, - 0xFE, 0x9B, 0x00, 0x21, 0x02, 0xEE, 0xF5, 0xCD, 0x36, 0x24, 0x27, - 0xE1, 0xF2, 0x7A, 0x05, 0x33, 0xFE, 0x2A, 0x00, 0x47, 0x00, 0xD3, - 0xFF, 0x04, 0x00, 0x0F, 0x00, 0x95, 0xFF, 0x17, 0x01, 0x3D, 0xFE, - 0xBD, 0x01, 0x30, 0x00, 0xCC, 0xF8, 0x92, 0x3B, 0x2A, 0x20, 0x2E, - 0xF3, 0x12, 0x06, 0x8F, 0xFD, 0x9A, 0x00, 0x10, 0x00, 0xE5, 0xFF, - 0x02, 0x00, 0x10, 0x00, 0x8C, 0xFF, 0x42, 0x01, 0xBB, 0xFD, 0xE4, - 0x02, 0x01, 0xFE, 0x9C, 0xFC, 0x45, 0x3F, 0x16, 0x19, 0x2D, 0xF4, - 0x41, 0x06, 0x21, 0xFD, 0xF3, 0x00, 0xE0, 0xFF, 0xF4, 0xFF, 0x01, - 0x00, 0x10, 0x00, 0x8B, 0xFF, 0x5D, 0x01, 0x4F, 0xFD, 0xFB, 0x03, - 0xB2, 0xFB, 0x53, 0x01, 0xC2, 0x41, 0x24, 0x12, 0xBA, 0xF5, 0x0F, - 0x06, 0xE9, 0xFC, 0x33, 0x01, 0xBB, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x93, 0xFF, 0x63, 0x01, 0x04, 0xFD, 0xEF, 0x04, 0x62, - 0xF9, 0xD7, 0x06, 0xF2, 0x42, 0x8D, 0x0B, 0xB0, 0xF7, 0x87, 0x05, - 0xE6, 0xFC, 0x58, 0x01, 0xA0, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0x00, 0xA5, 0xFF, 0x52, 0x01, 0xE2, 0xFC, 0xAD, 0x05, - 0x35, 0xF7, 0x08, 0x0D, 0xCB, 0x42, 0x81, 0x05, 0xE8, 0xF9, 0xBB, - 0x04, 0x12, 0xFD, 0x64, 0x01, 0x90, 0xFF, 0x0E, 0x00, 0x00, 0x00, - 0xFE, 0xFF, 0xC2, 0xFF, 0x27, 0x01, 0xF1, 0xFC, 0x22, 0x06, 0x54, - 0xF5, 0xB8, 0x13, 0x4A, 0x41, 0x29, 0x00, 0x3C, 0xFC, 0xBD, 0x03, - 0x66, 0xFD, 0x58, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF1, - 0xFF, 0xEB, 0xFF, 0xE1, 0x00, 0x35, 0xFD, 0x40, 0x06, 0xE4, 0xF3, - 0xB7, 0x1A, 0x85, 0x3E, 0xA6, 0xFB, 0x86, 0xFE, 0xA0, 0x02, 0xD7, - 0xFD, 0x39, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xE1, 0xFF, - 0x1C, 0x00, 0x82, 0x00, 0xB0, 0xFD, 0xF9, 0x05, 0x0C, 0xF3, 0xCB, - 0x21, 0x8F, 0x3A, 0x0D, 0xF8, 0xA9, 0x00, 0x79, 0x01, 0x5D, 0xFE, - 0x0B, 0x01, 0x98, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCE, 0xFF, 0x55, - 0x00, 0x0D, 0x00, 0x60, 0xFE, 0x48, 0x05, 0xEC, 0xF2, 0xB6, 0x28, - 0x91, 0x35, 0x68, 0xF5, 0x88, 0x02, 0x5A, 0x00, 0xED, 0xFE, 0xD4, - 0x00, 0xA8, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBB, 0xFF, 0x92, 0x00, - 0x87, 0xFF, 0x3F, 0xFF, 0x2B, 0x04, 0xA1, 0xF3, 0x3D, 0x2F, 0xB8, - 0x2F, 0xB8, 0xF3, 0x11, 0x04, 0x52, 0xFF, 0x7C, 0xFF, 0x97, 0x00, - 0xBA, 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA9, 0xFF, 0xCF, 0x00, 0xF8, - 0xFE, 0x44, 0x00, 0xAA, 0x02, 0x3E, 0xF5, 0x24, 0x35, 0x3B, 0x29, - 0xF2, 0xF2, 0x35, 0x05, 0x70, 0xFE, 0x03, 0x00, 0x5A, 0x00, 0xCD, - 0xFF, 0x05, 0x00, 0x0E, 0x00, 0x99, 0xFF, 0x07, 0x01, 0x68, 0xFE, - 0x63, 0x01, 0xD0, 0x00, 0xD0, 0xF7, 0x35, 0x3A, 0x55, 0x22, 0x02, - 0xF3, 0xEF, 0x05, 0xBC, 0xFD, 0x7A, 0x00, 0x20, 0x00, 0xDF, 0xFF, - 0x03, 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x36, 0x01, 0xE1, 0xFD, 0x8A, - 0x02, 0xB2, 0xFE, 0x56, 0xFB, 0x40, 0x3E, 0x42, 0x1B, 0xCE, 0xF3, - 0x3E, 0x06, 0x3D, 0xFD, 0xDB, 0x00, 0xEE, 0xFF, 0xF0, 0xFF, 0x01, - 0x00, 0x11, 0x00, 0x8A, 0xFF, 0x57, 0x01, 0x6D, 0xFD, 0xA8, 0x03, - 0x69, 0xFC, 0xC8, 0xFF, 0x20, 0x41, 0x40, 0x14, 0x33, 0xF5, 0x28, - 0x06, 0xF5, 0xFC, 0x22, 0x01, 0xC5, 0xFF, 0xFD, 0xFF, 0x00, 0x00, - 0x0F, 0x00, 0x8F, 0xFF, 0x64, 0x01, 0x17, 0xFD, 0xA9, 0x04, 0x16, - 0xFA, 0x10, 0x05, 0xB8, 0x42, 0x87, 0x0D, 0x0D, 0xF7, 0xB9, 0x05, - 0xE2, 0xFC, 0x50, 0x01, 0xA7, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0A, 0x00, 0x9E, 0xFF, 0x5A, 0x01, 0xE8, 0xFC, 0x7A, 0x05, - 0xDA, 0xF7, 0x10, 0x0B, 0xFB, 0x42, 0x4B, 0x07, 0x35, 0xF9, 0x00, - 0x05, 0x00, 0xFD, 0x63, 0x01, 0x94, 0xFF, 0x0D, 0x00, 0x00, 0x00, - 0x01, 0x00, 0xB8, 0xFF, 0x37, 0x01, 0xE7, 0xFC, 0x07, 0x06, 0xDE, - 0xF5, 0x9F, 0x11, 0xE4, 0x41, 0xB8, 0x01, 0x84, 0xFB, 0x0F, 0x04, - 0x48, 0xFD, 0x5E, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF5, - 0xFF, 0xDD, 0xFF, 0xF9, 0x00, 0x1B, 0xFD, 0x41, 0x06, 0x47, 0xF4, - 0x8B, 0x18, 0x81, 0x3F, 0xF1, 0xFC, 0xD5, 0xFD, 0xFA, 0x02, 0xB2, - 0xFD, 0x45, 0x01, 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE6, 0xFF, - 0x0C, 0x00, 0xA2, 0x00, 0x85, 0xFD, 0x1A, 0x06, 0x3C, 0xF3, 0x9F, - 0x1F, 0xE6, 0x3B, 0x0E, 0xF9, 0x07, 0x00, 0xD4, 0x01, 0x33, 0xFE, - 0x1B, 0x01, 0x94, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x43, - 0x00, 0x33, 0x00, 0x25, 0xFE, 0x89, 0x05, 0xE0, 0xF2, 0x9C, 0x26, - 0x33, 0x37, 0x1E, 0xF6, 0xFD, 0x01, 0xB0, 0x00, 0xC0, 0xFE, 0xE6, - 0x00, 0xA2, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC1, 0xFF, 0x7F, 0x00, - 0xB2, 0xFF, 0xF6, 0xFE, 0x8E, 0x04, 0x51, 0xF3, 0x49, 0x2D, 0x98, - 0x31, 0x23, 0xF4, 0xA2, 0x03, 0xA0, 0xFF, 0x51, 0xFF, 0xAA, 0x00, - 0xB4, 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAE, 0xFF, 0xBD, 0x00, 0x25, - 0xFF, 0xF1, 0xFF, 0x2B, 0x03, 0xA5, 0xF4, 0x68, 0x33, 0x48, 0x2B, - 0x17, 0xF3, 0xE7, 0x04, 0xB1, 0xFE, 0xDB, 0xFF, 0x6C, 0x00, 0xC7, - 0xFF, 0x06, 0x00, 0x0D, 0x00, 0x9E, 0xFF, 0xF7, 0x00, 0x94, 0xFE, - 0x09, 0x01, 0x6A, 0x01, 0xEB, 0xF6, 0xC1, 0x38, 0x7D, 0x24, 0xE8, - 0xF2, 0xC1, 0x05, 0xEE, 0xFD, 0x57, 0x00, 0x31, 0x00, 0xDA, 0xFF, - 0x03, 0x00, 0x10, 0x00, 0x91, 0xFF, 0x29, 0x01, 0x09, 0xFE, 0x2F, - 0x02, 0x5F, 0xFF, 0x27, 0xFA, 0x20, 0x3D, 0x70, 0x1D, 0x7D, 0xF3, - 0x31, 0x06, 0x5E, 0xFD, 0xBF, 0x00, 0xFD, 0xFF, 0xEB, 0xFF, 0x02, - 0x00, 0x11, 0x00, 0x8B, 0xFF, 0x4E, 0x01, 0x8E, 0xFD, 0x52, 0x03, - 0x20, 0xFD, 0x52, 0xFE, 0x60, 0x40, 0x63, 0x16, 0xB7, 0xF4, 0x39, - 0x06, 0x05, 0xFD, 0x0F, 0x01, 0xD1, 0xFF, 0xF9, 0xFF, 0x00, 0x00, - 0x10, 0x00, 0x8D, 0xFF, 0x62, 0x01, 0x2E, 0xFD, 0x5E, 0x04, 0xCC, - 0xFA, 0x5B, 0x03, 0x5E, 0x42, 0x8E, 0x0F, 0x71, 0xF6, 0xE4, 0x05, - 0xE2, 0xFC, 0x45, 0x01, 0xAF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0B, 0x00, 0x99, 0xFF, 0x60, 0x01, 0xF2, 0xFC, 0x40, 0x05, - 0x85, 0xF8, 0x26, 0x09, 0x0C, 0x43, 0x26, 0x09, 0x85, 0xF8, 0x40, - 0x05, 0xF2, 0xFC, 0x60, 0x01, 0x99, 0xFF, 0x0B, 0x00, 0x00, 0x00, - 0x04, 0x00, 0xAF, 0xFF, 0x45, 0x01, 0xE2, 0xFC, 0xE4, 0x05, 0x71, - 0xF6, 0x8E, 0x0F, 0x5E, 0x42, 0x5B, 0x03, 0xCC, 0xFA, 0x5E, 0x04, - 0x2E, 0xFD, 0x62, 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x00, 0x00, 0xF9, - 0xFF, 0xD1, 0xFF, 0x0F, 0x01, 0x05, 0xFD, 0x39, 0x06, 0xB7, 0xF4, - 0x63, 0x16, 0x60, 0x40, 0x52, 0xFE, 0x20, 0xFD, 0x52, 0x03, 0x8E, - 0xFD, 0x4E, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEB, 0xFF, - 0xFD, 0xFF, 0xBF, 0x00, 0x5E, 0xFD, 0x31, 0x06, 0x7D, 0xF3, 0x70, - 0x1D, 0x20, 0x3D, 0x27, 0xFA, 0x5F, 0xFF, 0x2F, 0x02, 0x09, 0xFE, - 0x29, 0x01, 0x91, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDA, 0xFF, 0x31, - 0x00, 0x57, 0x00, 0xEE, 0xFD, 0xC1, 0x05, 0xE8, 0xF2, 0x7D, 0x24, - 0xC1, 0x38, 0xEB, 0xF6, 0x6A, 0x01, 0x09, 0x01, 0x94, 0xFE, 0xF7, - 0x00, 0x9E, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC7, 0xFF, 0x6C, 0x00, - 0xDB, 0xFF, 0xB1, 0xFE, 0xE7, 0x04, 0x17, 0xF3, 0x48, 0x2B, 0x68, - 0x33, 0xA5, 0xF4, 0x2B, 0x03, 0xF1, 0xFF, 0x25, 0xFF, 0xBD, 0x00, - 0xAE, 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB4, 0xFF, 0xAA, 0x00, 0x51, - 0xFF, 0xA0, 0xFF, 0xA2, 0x03, 0x23, 0xF4, 0x98, 0x31, 0x49, 0x2D, - 0x51, 0xF3, 0x8E, 0x04, 0xF6, 0xFE, 0xB2, 0xFF, 0x7F, 0x00, 0xC1, - 0xFF, 0x07, 0x00, 0x0C, 0x00, 0xA2, 0xFF, 0xE6, 0x00, 0xC0, 0xFE, - 0xB0, 0x00, 0xFD, 0x01, 0x1E, 0xF6, 0x33, 0x37, 0x9C, 0x26, 0xE0, - 0xF2, 0x89, 0x05, 0x25, 0xFE, 0x33, 0x00, 0x43, 0x00, 0xD4, 0xFF, - 0x04, 0x00, 0x0F, 0x00, 0x94, 0xFF, 0x1B, 0x01, 0x33, 0xFE, 0xD4, - 0x01, 0x07, 0x00, 0x0E, 0xF9, 0xE6, 0x3B, 0x9F, 0x1F, 0x3C, 0xF3, - 0x1A, 0x06, 0x85, 0xFD, 0xA2, 0x00, 0x0C, 0x00, 0xE6, 0xFF, 0x02, - 0x00, 0x11, 0x00, 0x8C, 0xFF, 0x45, 0x01, 0xB2, 0xFD, 0xFA, 0x02, - 0xD5, 0xFD, 0xF1, 0xFC, 0x81, 0x3F, 0x8B, 0x18, 0x47, 0xF4, 0x41, - 0x06, 0x1B, 0xFD, 0xF9, 0x00, 0xDD, 0xFF, 0xF5, 0xFF, 0x01, 0x00, - 0x10, 0x00, 0x8B, 0xFF, 0x5E, 0x01, 0x48, 0xFD, 0x0F, 0x04, 0x84, - 0xFB, 0xB8, 0x01, 0xE4, 0x41, 0x9F, 0x11, 0xDE, 0xF5, 0x07, 0x06, - 0xE7, 0xFC, 0x37, 0x01, 0xB8, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x0D, - 0x00, 0x94, 0xFF, 0x63, 0x01, 0x00, 0xFD, 0x00, 0x05, 0x35, 0xF9, - 0x4B, 0x07, 0xFB, 0x42, 0x10, 0x0B, 0xDA, 0xF7, 0x7A, 0x05, 0xE8, - 0xFC, 0x5A, 0x01, 0x9E, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0xA7, 0xFF, 0x50, 0x01, 0xE2, 0xFC, 0xB9, 0x05, 0x0D, - 0xF7, 0x87, 0x0D, 0xB8, 0x42, 0x10, 0x05, 0x16, 0xFA, 0xA9, 0x04, - 0x17, 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFD, - 0xFF, 0xC5, 0xFF, 0x22, 0x01, 0xF5, 0xFC, 0x28, 0x06, 0x33, 0xF5, - 0x40, 0x14, 0x20, 0x41, 0xC8, 0xFF, 0x69, 0xFC, 0xA8, 0x03, 0x6D, - 0xFD, 0x57, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xF0, 0xFF, - 0xEE, 0xFF, 0xDB, 0x00, 0x3D, 0xFD, 0x3E, 0x06, 0xCE, 0xF3, 0x42, - 0x1B, 0x40, 0x3E, 0x56, 0xFB, 0xB2, 0xFE, 0x8A, 0x02, 0xE1, 0xFD, - 0x36, 0x01, 0x8E, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDF, 0xFF, 0x20, - 0x00, 0x7A, 0x00, 0xBC, 0xFD, 0xEF, 0x05, 0x02, 0xF3, 0x55, 0x22, - 0x35, 0x3A, 0xD0, 0xF7, 0xD0, 0x00, 0x63, 0x01, 0x68, 0xFE, 0x07, - 0x01, 0x99, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCD, 0xFF, 0x5A, 0x00, - 0x03, 0x00, 0x70, 0xFE, 0x35, 0x05, 0xF2, 0xF2, 0x3B, 0x29, 0x24, - 0x35, 0x3E, 0xF5, 0xAA, 0x02, 0x44, 0x00, 0xF8, 0xFE, 0xCF, 0x00, - 0xA9, 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xBA, 0xFF, 0x97, 0x00, 0x7C, - 0xFF, 0x52, 0xFF, 0x11, 0x04, 0xB8, 0xF3, 0xB8, 0x2F, 0x3D, 0x2F, - 0xA1, 0xF3, 0x2B, 0x04, 0x3F, 0xFF, 0x87, 0xFF, 0x92, 0x00, 0xBB, - 0xFF, 0x08, 0x00, 0x0B, 0x00, 0xA8, 0xFF, 0xD4, 0x00, 0xED, 0xFE, - 0x5A, 0x00, 0x88, 0x02, 0x68, 0xF5, 0x91, 0x35, 0xB6, 0x28, 0xEC, - 0xF2, 0x48, 0x05, 0x60, 0xFE, 0x0D, 0x00, 0x55, 0x00, 0xCE, 0xFF, - 0x05, 0x00, 0x0E, 0x00, 0x98, 0xFF, 0x0B, 0x01, 0x5D, 0xFE, 0x79, - 0x01, 0xA9, 0x00, 0x0D, 0xF8, 0x8F, 0x3A, 0xCB, 0x21, 0x0C, 0xF3, - 0xF9, 0x05, 0xB0, 0xFD, 0x82, 0x00, 0x1C, 0x00, 0xE1, 0xFF, 0x03, - 0x00, 0x10, 0x00, 0x8E, 0xFF, 0x39, 0x01, 0xD7, 0xFD, 0xA0, 0x02, - 0x86, 0xFE, 0xA6, 0xFB, 0x85, 0x3E, 0xB7, 0x1A, 0xE4, 0xF3, 0x40, - 0x06, 0x35, 0xFD, 0xE1, 0x00, 0xEB, 0xFF, 0xF1, 0xFF, 0x01, 0x00, - 0x11, 0x00, 0x8A, 0xFF, 0x58, 0x01, 0x66, 0xFD, 0xBD, 0x03, 0x3C, - 0xFC, 0x29, 0x00, 0x4A, 0x41, 0xB8, 0x13, 0x54, 0xF5, 0x22, 0x06, - 0xF1, 0xFC, 0x27, 0x01, 0xC2, 0xFF, 0xFE, 0xFF, 0x00, 0x00, 0x0E, - 0x00, 0x90, 0xFF, 0x64, 0x01, 0x12, 0xFD, 0xBB, 0x04, 0xE8, 0xF9, - 0x81, 0x05, 0xCB, 0x42, 0x08, 0x0D, 0x35, 0xF7, 0xAD, 0x05, 0xE2, - 0xFC, 0x52, 0x01, 0xA5, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0xA0, 0xFF, 0x58, 0x01, 0xE6, 0xFC, 0x87, 0x05, 0xB0, - 0xF7, 0x8D, 0x0B, 0xF2, 0x42, 0xD7, 0x06, 0x62, 0xF9, 0xEF, 0x04, - 0x04, 0xFD, 0x63, 0x01, 0x93, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xBB, 0xFF, 0x33, 0x01, 0xE9, 0xFC, 0x0F, 0x06, 0xBA, 0xF5, - 0x24, 0x12, 0xC2, 0x41, 0x53, 0x01, 0xB2, 0xFB, 0xFB, 0x03, 0x4F, - 0xFD, 0x5D, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF4, 0xFF, - 0xE0, 0xFF, 0xF3, 0x00, 0x21, 0xFD, 0x41, 0x06, 0x2D, 0xF4, 0x16, - 0x19, 0x45, 0x3F, 0x9C, 0xFC, 0x01, 0xFE, 0xE4, 0x02, 0xBB, 0xFD, - 0x42, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE5, 0xFF, 0x10, - 0x00, 0x9A, 0x00, 0x8F, 0xFD, 0x12, 0x06, 0x2E, 0xF3, 0x2A, 0x20, - 0x92, 0x3B, 0xCC, 0xF8, 0x30, 0x00, 0xBD, 0x01, 0x3D, 0xFE, 0x17, - 0x01, 0x95, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x47, 0x00, - 0x2A, 0x00, 0x33, 0xFE, 0x7A, 0x05, 0xE1, 0xF2, 0x24, 0x27, 0xCD, - 0x36, 0xEE, 0xF5, 0x21, 0x02, 0x9B, 0x00, 0xCB, 0xFE, 0xE1, 0x00, - 0xA4, 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0x84, 0x00, 0xA7, - 0xFF, 0x08, 0xFF, 0x76, 0x04, 0x63, 0xF3, 0xC8, 0x2D, 0x22, 0x31, - 0x06, 0xF4, 0xBF, 0x03, 0x8C, 0xFF, 0x5C, 0xFF, 0xA5, 0x00, 0xB5, - 0xFF, 0x09, 0x00, 0x0A, 0x00, 0xAD, 0xFF, 0xC1, 0x00, 0x1A, 0xFF, - 0x05, 0x00, 0x0B, 0x03, 0xC9, 0xF4, 0xD8, 0x33, 0xC5, 0x2A, 0x0C, - 0xF3, 0xFB, 0x04, 0xA0, 0xFE, 0xE5, 0xFF, 0x68, 0x00, 0xC9, 0xFF, - 0x06, 0x00, 0x0D, 0x00, 0x9C, 0xFF, 0xFB, 0x00, 0x89, 0xFE, 0x1F, - 0x01, 0x44, 0x01, 0x22, 0xF7, 0x20, 0x39, 0xF3, 0x23, 0xED, 0xF2, - 0xCE, 0x05, 0xE1, 0xFD, 0x60, 0x00, 0x2D, 0x00, 0xDB, 0xFF, 0x03, - 0x00, 0x10, 0x00, 0x90, 0xFF, 0x2D, 0x01, 0xFF, 0xFD, 0x46, 0x02, - 0x34, 0xFF, 0x71, 0xFA, 0x6B, 0x3D, 0xE5, 0x1C, 0x90, 0xF3, 0x35, - 0x06, 0x55, 0xFD, 0xC6, 0x00, 0xF9, 0xFF, 0xEC, 0xFF, 0x01, 0x00, - 0x11, 0x00, 0x8B, 0xFF, 0x51, 0x01, 0x86, 0xFD, 0x68, 0x03, 0xF3, - 0xFC, 0xAE, 0xFE, 0x92, 0x40, 0xDA, 0x15, 0xD5, 0xF4, 0x35, 0x06, - 0x00, 0xFD, 0x14, 0x01, 0xCE, 0xFF, 0xFA, 0xFF, 0x00, 0x00, 0x0F, - 0x00, 0x8D, 0xFF, 0x63, 0x01, 0x28, 0xFD, 0x71, 0x04, 0x9E, 0xFA, - 0xC7, 0x03, 0x79, 0x42, 0x0B, 0x0F, 0x97, 0xF6, 0xDA, 0x05, 0xE2, - 0xFC, 0x48, 0x01, 0xAD, 0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x9A, 0xFF, 0x5F, 0x01, 0xEF, 0xFC, 0x4F, 0x05, 0x5A, - 0xF8, 0x9F, 0x09, 0x0A, 0x43, 0xAE, 0x08, 0xB1, 0xF8, 0x30, 0x05, - 0xF5, 0xFC, 0x61, 0x01, 0x97, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03, - 0x00, 0xB1, 0xFF, 0x41, 0x01, 0xE3, 0xFC, 0xED, 0x05, 0x4C, 0xF6, - 0x11, 0x10, 0x42, 0x42, 0xF1, 0x02, 0xFA, 0xFA, 0x4B, 0x04, 0x34, - 0xFD, 0x61, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF8, 0xFF, - 0xD4, 0xFF, 0x0A, 0x01, 0x0A, 0xFD, 0x3C, 0x06, 0x9A, 0xF4, 0xED, - 0x16, 0x2A, 0x40, 0xF8, 0xFD, 0x4D, 0xFD, 0x3C, 0x03, 0x97, 0xFD, - 0x4C, 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xEA, 0xFF, 0x00, - 0x00, 0xB8, 0x00, 0x67, 0xFD, 0x2C, 0x06, 0x6B, 0xF3, 0xFC, 0x1D, - 0xD3, 0x3C, 0xDF, 0xF9, 0x89, 0xFF, 0x18, 0x02, 0x13, 0xFE, 0x26, - 0x01, 0x92, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD9, 0xFF, 0x36, 0x00, - 0x4E, 0x00, 0xFB, 0xFD, 0xB4, 0x05, 0xE4, 0xF2, 0x04, 0x25, 0x5F, - 0x38, 0xB6, 0xF6, 0x90, 0x01, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00, - 0x9F, 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC6, 0xFF, 0x71, 0x00, 0xD1, - 0xFF, 0xC2, 0xFE, 0xD1, 0x04, 0x23, 0xF3, 0xC9, 0x2B, 0xF5, 0x32, - 0x83, 0xF4, 0x49, 0x03, 0xDC, 0xFF, 0x30, 0xFF, 0xB8, 0x00, 0xB0, - 0xFF, 0x0A, 0x00, 0x09, 0x00, 0xB3, 0xFF, 0xAE, 0x00, 0x46, 0xFF, - 0xB4, 0xFF, 0x85, 0x03, 0x42, 0xF4, 0x0E, 0x32, 0xCA, 0x2C, 0x41, - 0xF3, 0xA5, 0x04, 0xE4, 0xFE, 0xBC, 0xFF, 0x7A, 0x00, 0xC3, 0xFF, - 0x07, 0x00, 0x0D, 0x00, 0xA1, 0xFF, 0xEA, 0x00, 0xB5, 0xFE, 0xC6, - 0x00, 0xD9, 0x01, 0x4F, 0xF6, 0x99, 0x37, 0x16, 0x26, 0xE0, 0xF2, - 0x98, 0x05, 0x16, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0xD6, 0xFF, 0x04, - 0x00, 0x0F, 0x00, 0x93, 0xFF, 0x1F, 0x01, 0x28, 0xFE, 0xEB, 0x01, - 0xDD, 0xFF, 0x52, 0xF9, 0x36, 0x3C, 0x13, 0x1F, 0x4B, 0xF3, 0x20, - 0x06, 0x7B, 0xFD, 0xA9, 0x00, 0x08, 0x00, 0xE7, 0xFF, 0x02, 0x00, - 0x11, 0x00, 0x8C, 0xFF, 0x47, 0x01, 0xA9, 0xFD, 0x10, 0x03, 0xA8, - 0xFD, 0x47, 0xFD, 0xBB, 0x3F, 0x01, 0x18, 0x62, 0xF4, 0x40, 0x06, - 0x15, 0xFD, 0xFF, 0x00, 0xDA, 0xFF, 0xF6, 0xFF, 0x01, 0x00, 0x10, - 0x00, 0x8B, 0xFF, 0x5F, 0x01, 0x41, 0xFD, 0x23, 0x04, 0x56, 0xFB, - 0x1F, 0x02, 0x06, 0x42, 0x19, 0x11, 0x02, 0xF6, 0xFF, 0x05, 0xE5, - 0xFC, 0x3B, 0x01, 0xB6, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, - 0x95, 0xFF, 0x62, 0x01, 0xFC, 0xFC, 0x10, 0x05, 0x09, 0xF9, 0xC1, - 0x07, 0x03, 0x43, 0x94, 0x0A, 0x05, 0xF8, 0x6C, 0x05, 0xEA, 0xFC, - 0x5C, 0x01, 0x9D, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, - 0x00, 0xA9, 0xFF, 0x4D, 0x01, 0xE1, 0xFC, 0xC4, 0x05, 0xE6, 0xF6, - 0x08, 0x0E, 0xA5, 0x42, 0xA1, 0x04, 0x43, 0xFA, 0x97, 0x04, 0x1D, - 0xFD, 0x64, 0x01, 0x8F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFC, 0xFF, - 0xC8, 0xFF, 0x1E, 0x01, 0xF8, 0xFC, 0x2D, 0x06, 0x13, 0xF5, 0xC8, - 0x14, 0xF2, 0x40, 0x69, 0xFF, 0x97, 0xFC, 0x92, 0x03, 0x75, 0xFD, - 0x55, 0x01, 0x8A, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xEF, 0xFF, 0xF2, - 0xFF, 0xD4, 0x00, 0x45, 0xFD, 0x3B, 0x06, 0xB8, 0xF3, 0xCE, 0x1B, - 0xFB, 0x3D, 0x08, 0xFB, 0xDE, 0xFE, 0x73, 0x02, 0xEB, 0xFD, 0x33, - 0x01, 0x8F, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDE, 0xFF, 0x25, 0x00, - 0x71, 0x00, 0xC8, 0xFD, 0xE5, 0x05, 0xFA, 0xF2, 0xDF, 0x22, 0xDB, - 0x39, 0x94, 0xF7, 0xF7, 0x00, 0x4C, 0x01, 0x73, 0xFE, 0x03, 0x01, - 0x9A, 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xCC, 0xFF, 0x5E, 0x00, 0xF9, - 0xFF, 0x80, 0xFE, 0x23, 0x05, 0xF9, 0xF2, 0xC0, 0x29, 0xB8, 0x34, - 0x16, 0xF5, 0xCB, 0x02, 0x2F, 0x00, 0x03, 0xFF, 0xCA, 0x00, 0xAA, - 0xFF, 0x0B, 0x00, 0x08, 0x00, 0xB8, 0xFF, 0x9B, 0x00, 0x72, 0xFF, - 0x65, 0xFF, 0xF6, 0x03, 0xD1, 0xF3, 0x31, 0x30, 0xC1, 0x2E, 0x8B, - 0xF3, 0x45, 0x04, 0x2D, 0xFF, 0x92, 0xFF, 0x8D, 0x00, 0xBD, 0xFF, - 0x08, 0x00, 0x0C, 0x00, 0xA6, 0xFF, 0xD8, 0x00, 0xE2, 0xFE, 0x6F, - 0x00, 0x66, 0x02, 0x93, 0xF5, 0xFB, 0x35, 0x31, 0x28, 0xE7, 0xF2, - 0x59, 0x05, 0x51, 0xFE, 0x17, 0x00, 0x50, 0x00, 0xD0, 0xFF, 0x05, - 0x00, 0x0E, 0x00, 0x97, 0xFF, 0x0F, 0x01, 0x53, 0xFE, 0x90, 0x01, - 0x81, 0x00, 0x4B, 0xF8, 0xE6, 0x3A, 0x3F, 0x21, 0x16, 0xF3, 0x02, - 0x06, 0xA5, 0xFD, 0x8A, 0x00, 0x18, 0x00, 0xE2, 0xFF, 0x02, 0x00, - 0x10, 0x00, 0x8D, 0xFF, 0x3C, 0x01, 0xCE, 0xFD, 0xB7, 0x02, 0x5A, - 0xFE, 0xF7, 0xFB, 0xC6, 0x3E, 0x2C, 0x1A, 0xFC, 0xF3, 0x41, 0x06, - 0x2E, 0xFD, 0xE7, 0x00, 0xE7, 0xFF, 0xF2, 0xFF, 0x01, 0x00, 0x10, - 0x00, 0x8B, 0xFF, 0x5A, 0x01, 0x5E, 0xFD, 0xD2, 0x03, 0x0E, 0xFC, - 0x8B, 0x00, 0x75, 0x41, 0x32, 0x13, 0x75, 0xF5, 0x1C, 0x06, 0xEE, - 0xFC, 0x2B, 0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0E, 0x00, - 0x91, 0xFF, 0x64, 0x01, 0x0D, 0xFD, 0xCD, 0x04, 0xBB, 0xF9, 0xF2, - 0x05, 0xD9, 0x42, 0x88, 0x0C, 0x5E, 0xF7, 0xA1, 0x05, 0xE3, 0xFC, - 0x54, 0x01, 0xA3, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x00, 0xA2, 0xFF, 0x56, 0x01, 0xE5, 0xFC, 0x94, 0x05, 0x87, 0xF7, - 0x0A, 0x0C, 0xE6, 0x42, 0x64, 0x06, 0x8E, 0xF9, 0xDE, 0x04, 0x09, - 0xFD, 0x64, 0x01, 0x92, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xBD, 0xFF, 0x2F, 0x01, 0xEC, 0xFC, 0x16, 0x06, 0x98, 0xF5, 0xAB, - 0x12, 0x9C, 0x41, 0xEE, 0x00, 0xE0, 0xFB, 0xE6, 0x03, 0x57, 0xFD, - 0x5B, 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF3, 0xFF, 0xE4, - 0xFF, 0xED, 0x00, 0x27, 0xFD, 0x41, 0x06, 0x14, 0xF4, 0xA1, 0x19, - 0x06, 0x3F, 0x49, 0xFC, 0x2E, 0xFE, 0xCD, 0x02, 0xC4, 0xFD, 0x3F, - 0x01, 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE3, 0xFF, 0x14, 0x00, - 0x92, 0x00, 0x9A, 0xFD, 0x0A, 0x06, 0x22, 0xF3, 0xB4, 0x20, 0x3C, - 0x3B, 0x8B, 0xF8, 0x58, 0x00, 0xA7, 0x01, 0x48, 0xFE, 0x13, 0x01, - 0x96, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x4C, 0x00, 0x20, - 0x00, 0x42, 0xFE, 0x6A, 0x05, 0xE3, 0xF2, 0xAB, 0x27, 0x66, 0x36, - 0xC0, 0xF5, 0x44, 0x02, 0x85, 0x00, 0xD7, 0xFE, 0xDD, 0x00, 0xA5, - 0xFF, 0x0C, 0x00, 0x07, 0x00, 0xBE, 0xFF, 0x89, 0x00, 0x9D, 0xFF, - 0x1A, 0xFF, 0x5E, 0x04, 0x76, 0xF3, 0x45, 0x2E, 0xAA, 0x30, 0xEB, - 0xF3, 0xDB, 0x03, 0x79, 0xFF, 0x67, 0xFF, 0xA0, 0x00, 0xB7, 0xFF, - 0x09, 0x00, 0x0B, 0x00, 0xAC, 0xFF, 0xC6, 0x00, 0x0E, 0xFF, 0x1A, - 0x00, 0xEB, 0x02, 0xEF, 0xF4, 0x49, 0x34, 0x43, 0x2A, 0x02, 0xF3, - 0x0F, 0x05, 0x90, 0xFE, 0xEF, 0xFF, 0x63, 0x00, 0xCA, 0xFF, 0x06, - 0x00, 0x0E, 0x00, 0x9B, 0xFF, 0xFF, 0x00, 0x7E, 0xFE, 0x36, 0x01, - 0x1E, 0x01, 0x5B, 0xF7, 0x7E, 0x39, 0x69, 0x23, 0xF3, 0xF2, 0xD9, - 0x05, 0xD4, 0xFD, 0x69, 0x00, 0x29, 0x00, 0xDD, 0xFF, 0x03, 0x00, - 0x10, 0x00, 0x90, 0xFF, 0x30, 0x01, 0xF5, 0xFD, 0x5C, 0x02, 0x09, - 0xFF, 0xBC, 0xFA, 0xB5, 0x3D, 0x5A, 0x1C, 0xA3, 0xF3, 0x38, 0x06, - 0x4D, 0xFD, 0xCD, 0x00, 0xF5, 0xFF, 0xED, 0xFF, 0x01, 0x00, 0x11, - 0x00, 0x8B, 0xFF, 0x53, 0x01, 0x7E, 0xFD, 0x7D, 0x03, 0xC5, 0xFC, - 0x0B, 0xFF, 0xC3, 0x40, 0x51, 0x15, 0xF4, 0xF4, 0x31, 0x06, 0xFC, - 0xFC, 0x19, 0x01, 0xCB, 0xFF, 0xFB, 0xFF, 0x00, 0x00, 0x0F, 0x00, - 0x8E, 0xFF, 0x63, 0x01, 0x22, 0xFD, 0x84, 0x04, 0x71, 0xFA, 0x34, - 0x04, 0x90, 0x42, 0x89, 0x0E, 0xBE, 0xF6, 0xCF, 0x05, 0xE1, 0xFC, - 0x4A, 0x01, 0xAB, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, - 0x00, 0x9B, 0xFF, 0x5D, 0x01, 0xEC, 0xFC, 0x5D, 0x05, 0x2F, 0xF8, - 0x19, 0x0A, 0x07, 0x43, 0x37, 0x08, 0xDD, 0xF8, 0x21, 0x05, 0xF8, - 0xFC, 0x62, 0x01, 0x96, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, - 0xB4, 0xFF, 0x3E, 0x01, 0xE4, 0xFC, 0xF6, 0x05, 0x26, 0xF6, 0x95, - 0x10, 0x26, 0x42, 0x87, 0x02, 0x28, 0xFB, 0x37, 0x04, 0x3B, 0xFD, - 0x60, 0x01, 0x8C, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF7, 0xFF, 0xD7, - 0xFF, 0x04, 0x01, 0x0F, 0xFD, 0x3E, 0x06, 0x7D, 0xF4, 0x76, 0x17, - 0xF4, 0x3F, 0x9F, 0xFD, 0x7B, 0xFD, 0x26, 0x03, 0xA0, 0xFD, 0x4A, - 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE9, 0xFF, 0x04, 0x00, - 0xB1, 0x00, 0x71, 0xFD, 0x26, 0x06, 0x5A, 0xF3, 0x88, 0x1E, 0x87, - 0x3C, 0x98, 0xF9, 0xB3, 0xFF, 0x02, 0x02, 0x1E, 0xFE, 0x22, 0x01, - 0x93, 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD7, 0xFF, 0x3A, 0x00, 0x45, - 0x00, 0x09, 0xFE, 0xA7, 0x05, 0xE1, 0xF2, 0x8D, 0x25, 0xFD, 0x37, - 0x82, 0xF6, 0xB5, 0x01, 0xDC, 0x00, 0xAA, 0xFE, 0xEE, 0x00, 0xA0, - 0xFF, 0x0D, 0x00, 0x06, 0x00, 0xC4, 0xFF, 0x76, 0x00, 0xC7, 0xFF, - 0xD3, 0xFE, 0xBC, 0x04, 0x31, 0xF3, 0x4A, 0x2C, 0x83, 0x32, 0x61, - 0xF4, 0x68, 0x03, 0xC8, 0xFF, 0x3B, 0xFF, 0xB3, 0x00, 0xB1, 0xFF, - 0x0A, 0x00, 0x0A, 0x00, 0xB1, 0xFF, 0xB3, 0x00, 0x3B, 0xFF, 0xC8, - 0xFF, 0x68, 0x03, 0x61, 0xF4, 0x83, 0x32, 0x4A, 0x2C, 0x31, 0xF3, - 0xBC, 0x04, 0xD3, 0xFE, 0xC7, 0xFF, 0x76, 0x00, 0xC4, 0xFF, 0x06, - 0x00, 0x0D, 0x00, 0xA0, 0xFF, 0xEE, 0x00, 0xAA, 0xFE, 0xDC, 0x00, - 0xB5, 0x01, 0x82, 0xF6, 0xFD, 0x37, 0x8D, 0x25, 0xE1, 0xF2, 0xA7, - 0x05, 0x09, 0xFE, 0x45, 0x00, 0x3A, 0x00, 0xD7, 0xFF, 0x04, 0x00, - 0x0F, 0x00, 0x93, 0xFF, 0x22, 0x01, 0x1E, 0xFE, 0x02, 0x02, 0xB3, - 0xFF, 0x98, 0xF9, 0x87, 0x3C, 0x88, 0x1E, 0x5A, 0xF3, 0x26, 0x06, - 0x71, 0xFD, 0xB1, 0x00, 0x04, 0x00, 0xE9, 0xFF, 0x02, 0x00, 0x11, - 0x00, 0x8B, 0xFF, 0x4A, 0x01, 0xA0, 0xFD, 0x26, 0x03, 0x7B, 0xFD, - 0x9F, 0xFD, 0xF4, 0x3F, 0x76, 0x17, 0x7D, 0xF4, 0x3E, 0x06, 0x0F, - 0xFD, 0x04, 0x01, 0xD7, 0xFF, 0xF7, 0xFF, 0x01, 0x00, 0x10, 0x00, - 0x8C, 0xFF, 0x60, 0x01, 0x3B, 0xFD, 0x37, 0x04, 0x28, 0xFB, 0x87, - 0x02, 0x26, 0x42, 0x95, 0x10, 0x26, 0xF6, 0xF6, 0x05, 0xE4, 0xFC, - 0x3E, 0x01, 0xB4, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x96, - 0xFF, 0x62, 0x01, 0xF8, 0xFC, 0x21, 0x05, 0xDD, 0xF8, 0x37, 0x08, - 0x07, 0x43, 0x19, 0x0A, 0x2F, 0xF8, 0x5D, 0x05, 0xEC, 0xFC, 0x5D, - 0x01, 0x9B, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, - 0xAB, 0xFF, 0x4A, 0x01, 0xE1, 0xFC, 0xCF, 0x05, 0xBE, 0xF6, 0x89, - 0x0E, 0x90, 0x42, 0x34, 0x04, 0x71, 0xFA, 0x84, 0x04, 0x22, 0xFD, - 0x63, 0x01, 0x8E, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0xCB, - 0xFF, 0x19, 0x01, 0xFC, 0xFC, 0x31, 0x06, 0xF4, 0xF4, 0x51, 0x15, - 0xC3, 0x40, 0x0B, 0xFF, 0xC5, 0xFC, 0x7D, 0x03, 0x7E, 0xFD, 0x53, - 0x01, 0x8B, 0xFF, 0x11, 0x00, 0x01, 0x00, 0xED, 0xFF, 0xF5, 0xFF, - 0xCD, 0x00, 0x4D, 0xFD, 0x38, 0x06, 0xA3, 0xF3, 0x5A, 0x1C, 0xB5, - 0x3D, 0xBC, 0xFA, 0x09, 0xFF, 0x5C, 0x02, 0xF5, 0xFD, 0x30, 0x01, - 0x90, 0xFF, 0x10, 0x00, 0x03, 0x00, 0xDD, 0xFF, 0x29, 0x00, 0x69, - 0x00, 0xD4, 0xFD, 0xD9, 0x05, 0xF3, 0xF2, 0x69, 0x23, 0x7E, 0x39, - 0x5B, 0xF7, 0x1E, 0x01, 0x36, 0x01, 0x7E, 0xFE, 0xFF, 0x00, 0x9B, - 0xFF, 0x0E, 0x00, 0x06, 0x00, 0xCA, 0xFF, 0x63, 0x00, 0xEF, 0xFF, - 0x90, 0xFE, 0x0F, 0x05, 0x02, 0xF3, 0x43, 0x2A, 0x49, 0x34, 0xEF, - 0xF4, 0xEB, 0x02, 0x1A, 0x00, 0x0E, 0xFF, 0xC6, 0x00, 0xAC, 0xFF, - 0x0B, 0x00, 0x09, 0x00, 0xB7, 0xFF, 0xA0, 0x00, 0x67, 0xFF, 0x79, - 0xFF, 0xDB, 0x03, 0xEB, 0xF3, 0xAA, 0x30, 0x45, 0x2E, 0x76, 0xF3, - 0x5E, 0x04, 0x1A, 0xFF, 0x9D, 0xFF, 0x89, 0x00, 0xBE, 0xFF, 0x07, - 0x00, 0x0C, 0x00, 0xA5, 0xFF, 0xDD, 0x00, 0xD7, 0xFE, 0x85, 0x00, - 0x44, 0x02, 0xC0, 0xF5, 0x66, 0x36, 0xAB, 0x27, 0xE3, 0xF2, 0x6A, - 0x05, 0x42, 0xFE, 0x20, 0x00, 0x4C, 0x00, 0xD1, 0xFF, 0x04, 0x00, - 0x0F, 0x00, 0x96, 0xFF, 0x13, 0x01, 0x48, 0xFE, 0xA7, 0x01, 0x58, - 0x00, 0x8B, 0xF8, 0x3C, 0x3B, 0xB4, 0x20, 0x22, 0xF3, 0x0A, 0x06, - 0x9A, 0xFD, 0x92, 0x00, 0x14, 0x00, 0xE3, 0xFF, 0x02, 0x00, 0x10, - 0x00, 0x8D, 0xFF, 0x3F, 0x01, 0xC4, 0xFD, 0xCD, 0x02, 0x2E, 0xFE, - 0x49, 0xFC, 0x06, 0x3F, 0xA1, 0x19, 0x14, 0xF4, 0x41, 0x06, 0x27, - 0xFD, 0xED, 0x00, 0xE4, 0xFF, 0xF3, 0xFF, 0x01, 0x00, 0x10, 0x00, - 0x8B, 0xFF, 0x5B, 0x01, 0x57, 0xFD, 0xE6, 0x03, 0xE0, 0xFB, 0xEE, - 0x00, 0x9C, 0x41, 0xAB, 0x12, 0x98, 0xF5, 0x16, 0x06, 0xEC, 0xFC, - 0x2F, 0x01, 0xBD, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x92, - 0xFF, 0x64, 0x01, 0x09, 0xFD, 0xDE, 0x04, 0x8E, 0xF9, 0x64, 0x06, - 0xE6, 0x42, 0x0A, 0x0C, 0x87, 0xF7, 0x94, 0x05, 0xE5, 0xFC, 0x56, - 0x01, 0xA2, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, - 0xA3, 0xFF, 0x54, 0x01, 0xE3, 0xFC, 0xA1, 0x05, 0x5E, 0xF7, 0x88, - 0x0C, 0xD9, 0x42, 0xF2, 0x05, 0xBB, 0xF9, 0xCD, 0x04, 0x0D, 0xFD, - 0x64, 0x01, 0x91, 0xFF, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, - 0xFF, 0x2B, 0x01, 0xEE, 0xFC, 0x1C, 0x06, 0x75, 0xF5, 0x32, 0x13, - 0x75, 0x41, 0x8B, 0x00, 0x0E, 0xFC, 0xD2, 0x03, 0x5E, 0xFD, 0x5A, - 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF2, 0xFF, 0xE7, 0xFF, - 0xE7, 0x00, 0x2E, 0xFD, 0x41, 0x06, 0xFC, 0xF3, 0x2C, 0x1A, 0xC6, - 0x3E, 0xF7, 0xFB, 0x5A, 0xFE, 0xB7, 0x02, 0xCE, 0xFD, 0x3C, 0x01, - 0x8D, 0xFF, 0x10, 0x00, 0x02, 0x00, 0xE2, 0xFF, 0x18, 0x00, 0x8A, - 0x00, 0xA5, 0xFD, 0x02, 0x06, 0x16, 0xF3, 0x3F, 0x21, 0xE6, 0x3A, - 0x4B, 0xF8, 0x81, 0x00, 0x90, 0x01, 0x53, 0xFE, 0x0F, 0x01, 0x97, - 0xFF, 0x0E, 0x00, 0x05, 0x00, 0xD0, 0xFF, 0x50, 0x00, 0x17, 0x00, - 0x51, 0xFE, 0x59, 0x05, 0xE7, 0xF2, 0x31, 0x28, 0xFB, 0x35, 0x93, - 0xF5, 0x66, 0x02, 0x6F, 0x00, 0xE2, 0xFE, 0xD8, 0x00, 0xA6, 0xFF, - 0x0C, 0x00, 0x08, 0x00, 0xBD, 0xFF, 0x8D, 0x00, 0x92, 0xFF, 0x2D, - 0xFF, 0x45, 0x04, 0x8B, 0xF3, 0xC1, 0x2E, 0x31, 0x30, 0xD1, 0xF3, - 0xF6, 0x03, 0x65, 0xFF, 0x72, 0xFF, 0x9B, 0x00, 0xB8, 0xFF, 0x08, - 0x00, 0x0B, 0x00, 0xAA, 0xFF, 0xCA, 0x00, 0x03, 0xFF, 0x2F, 0x00, - 0xCB, 0x02, 0x16, 0xF5, 0xB8, 0x34, 0xC0, 0x29, 0xF9, 0xF2, 0x23, - 0x05, 0x80, 0xFE, 0xF9, 0xFF, 0x5E, 0x00, 0xCC, 0xFF, 0x05, 0x00, - 0x0E, 0x00, 0x9A, 0xFF, 0x03, 0x01, 0x73, 0xFE, 0x4C, 0x01, 0xF7, - 0x00, 0x94, 0xF7, 0xDB, 0x39, 0xDF, 0x22, 0xFA, 0xF2, 0xE5, 0x05, - 0xC8, 0xFD, 0x71, 0x00, 0x25, 0x00, 0xDE, 0xFF, 0x03, 0x00, 0x10, - 0x00, 0x8F, 0xFF, 0x33, 0x01, 0xEB, 0xFD, 0x73, 0x02, 0xDE, 0xFE, - 0x08, 0xFB, 0xFB, 0x3D, 0xCE, 0x1B, 0xB8, 0xF3, 0x3B, 0x06, 0x45, - 0xFD, 0xD4, 0x00, 0xF2, 0xFF, 0xEF, 0xFF, 0x01, 0x00, 0x11, 0x00, - 0x8A, 0xFF, 0x55, 0x01, 0x75, 0xFD, 0x92, 0x03, 0x97, 0xFC, 0x69, - 0xFF, 0xF2, 0x40, 0xC8, 0x14, 0x13, 0xF5, 0x2D, 0x06, 0xF8, 0xFC, - 0x1E, 0x01, 0xC8, 0xFF, 0xFC, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x8F, - 0xFF, 0x64, 0x01, 0x1D, 0xFD, 0x97, 0x04, 0x43, 0xFA, 0xA1, 0x04, - 0xA5, 0x42, 0x08, 0x0E, 0xE6, 0xF6, 0xC4, 0x05, 0xE1, 0xFC, 0x4D, - 0x01, 0xA9, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, - 0x9D, 0xFF, 0x5C, 0x01, 0xEA, 0xFC, 0x6C, 0x05, 0x05, 0xF8, 0x94, - 0x0A, 0x03, 0x43, 0xC1, 0x07, 0x09, 0xF9, 0x10, 0x05, 0xFC, 0xFC, - 0x62, 0x01, 0x95, 0xFF, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x00, 0xB6, - 0xFF, 0x3B, 0x01, 0xE5, 0xFC, 0xFF, 0x05, 0x02, 0xF6, 0x19, 0x11, - 0x06, 0x42, 0x1F, 0x02, 0x56, 0xFB, 0x23, 0x04, 0x41, 0xFD, 0x5F, - 0x01, 0x8B, 0xFF, 0x10, 0x00, 0x01, 0x00, 0xF6, 0xFF, 0xDA, 0xFF, - 0xFF, 0x00, 0x15, 0xFD, 0x40, 0x06, 0x62, 0xF4, 0x01, 0x18, 0xBB, - 0x3F, 0x47, 0xFD, 0xA8, 0xFD, 0x10, 0x03, 0xA9, 0xFD, 0x47, 0x01, - 0x8C, 0xFF, 0x11, 0x00, 0x02, 0x00, 0xE7, 0xFF, 0x08, 0x00, 0xA9, - 0x00, 0x7B, 0xFD, 0x20, 0x06, 0x4B, 0xF3, 0x13, 0x1F, 0x36, 0x3C, - 0x52, 0xF9, 0xDD, 0xFF, 0xEB, 0x01, 0x28, 0xFE, 0x1F, 0x01, 0x93, - 0xFF, 0x0F, 0x00, 0x04, 0x00, 0xD6, 0xFF, 0x3F, 0x00, 0x3C, 0x00, - 0x16, 0xFE, 0x98, 0x05, 0xE0, 0xF2, 0x16, 0x26, 0x99, 0x37, 0x4F, - 0xF6, 0xD9, 0x01, 0xC6, 0x00, 0xB5, 0xFE, 0xEA, 0x00, 0xA1, 0xFF, - 0x0D, 0x00, 0x07, 0x00, 0xC3, 0xFF, 0x7A, 0x00, 0xBC, 0xFF, 0xE4, - 0xFE, 0xA5, 0x04, 0x41, 0xF3, 0xCA, 0x2C, 0x0E, 0x32, 0x42, 0xF4, - 0x85, 0x03, 0xB4, 0xFF, 0x46, 0xFF, 0xAE, 0x00, 0xB3, 0xFF, 0x09, - 0x00, 0x0A, 0x00, 0xB0, 0xFF, 0xB8, 0x00, 0x30, 0xFF, 0xDC, 0xFF, - 0x49, 0x03, 0x83, 0xF4, 0xF5, 0x32, 0xC9, 0x2B, 0x23, 0xF3, 0xD1, - 0x04, 0xC2, 0xFE, 0xD1, 0xFF, 0x71, 0x00, 0xC6, 0xFF, 0x06, 0x00, - 0x0D, 0x00, 0x9F, 0xFF, 0xF3, 0x00, 0x9F, 0xFE, 0xF3, 0x00, 0x90, - 0x01, 0xB6, 0xF6, 0x5F, 0x38, 0x04, 0x25, 0xE4, 0xF2, 0xB4, 0x05, - 0xFB, 0xFD, 0x4E, 0x00, 0x36, 0x00, 0xD9, 0xFF, 0x04, 0x00, 0x0F, - 0x00, 0x92, 0xFF, 0x26, 0x01, 0x13, 0xFE, 0x18, 0x02, 0x89, 0xFF, - 0xDF, 0xF9, 0xD3, 0x3C, 0xFC, 0x1D, 0x6B, 0xF3, 0x2C, 0x06, 0x67, - 0xFD, 0xB8, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0x02, 0x00, 0x11, 0x00, - 0x8B, 0xFF, 0x4C, 0x01, 0x97, 0xFD, 0x3C, 0x03, 0x4D, 0xFD, 0xF8, - 0xFD, 0x2A, 0x40, 0xED, 0x16, 0x9A, 0xF4, 0x3C, 0x06, 0x0A, 0xFD, - 0x0A, 0x01, 0xD4, 0xFF, 0xF8, 0xFF, 0x01, 0x00, 0x10, 0x00, 0x8C, - 0xFF, 0x61, 0x01, 0x34, 0xFD, 0x4B, 0x04, 0xFA, 0xFA, 0xF1, 0x02, - 0x42, 0x42, 0x11, 0x10, 0x4C, 0xF6, 0xED, 0x05, 0xE3, 0xFC, 0x41, - 0x01, 0xB1, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x97, 0xFF, - 0x61, 0x01, 0xF5, 0xFC, 0x30, 0x05, 0xB1, 0xF8, 0xAE, 0x08, 0x0A, - 0x43, 0x9F, 0x09, 0x5A, 0xF8, 0x4F, 0x05, 0xEF, 0xFC, 0x5F, 0x01, - 0x9A, 0xFF, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xAD, - 0xFF, 0x48, 0x01, 0xE2, 0xFC, 0xDA, 0x05, 0x97, 0xF6, 0x0B, 0x0F, - 0x79, 0x42, 0xC7, 0x03, 0x9E, 0xFA, 0x71, 0x04, 0x28, 0xFD, 0x63, - 0x01, 0x8D, 0xFF, 0x0F, 0x00 -}; - -static u16 -coefficient_sizes[8 * 2] = { - /* Playback */ - 0x00C0, 0x5000, 0x0060, 0x2800, 0x0040, 0x0060, 0x1400, 0x0000, - /* capture */ - 0x0020, 0x1260, 0x0020, 0x1260, 0x0000, 0x0040, 0x1260, 0x0000, -}; - diff --git a/ANDROID_3.4.5/sound/pci/oxygen/Makefile b/ANDROID_3.4.5/sound/pci/oxygen/Makefile deleted file mode 100644 index 0f872655..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o -snd-oxygen-objs := oxygen.o xonar_dg.o -snd-virtuoso-objs := virtuoso.o xonar_lib.o \ - xonar_pcm179x.o xonar_cs43xx.o xonar_wm87x6.o xonar_hdmi.o - -obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o -obj-$(CONFIG_SND_OXYGEN) += snd-oxygen.o -obj-$(CONFIG_SND_VIRTUOSO) += snd-virtuoso.o diff --git a/ANDROID_3.4.5/sound/pci/oxygen/ak4396.h b/ANDROID_3.4.5/sound/pci/oxygen/ak4396.h deleted file mode 100644 index 551c1cf8..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/ak4396.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef AK4396_H_INCLUDED -#define AK4396_H_INCLUDED - -#define AK4396_WRITE 0x2000 - -#define AK4396_CONTROL_1 0 -#define AK4396_CONTROL_2 1 -#define AK4396_CONTROL_3 2 -#define AK4396_LCH_ATT 3 -#define AK4396_RCH_ATT 4 - -/* control 1 */ -#define AK4396_RSTN 0x01 -#define AK4396_DIF_MASK 0x0e -#define AK4396_DIF_16_LSB 0x00 -#define AK4396_DIF_20_LSB 0x02 -#define AK4396_DIF_24_MSB 0x04 -#define AK4396_DIF_24_I2S 0x06 -#define AK4396_DIF_24_LSB 0x08 -#define AK4396_ACKS 0x80 -/* control 2 */ -#define AK4396_SMUTE 0x01 -#define AK4396_DEM_MASK 0x06 -#define AK4396_DEM_441 0x00 -#define AK4396_DEM_OFF 0x02 -#define AK4396_DEM_48 0x04 -#define AK4396_DEM_32 0x06 -#define AK4396_DFS_MASK 0x18 -#define AK4396_DFS_NORMAL 0x00 -#define AK4396_DFS_DOUBLE 0x08 -#define AK4396_DFS_QUAD 0x10 -#define AK4396_SLOW 0x20 -#define AK4396_DZFM 0x40 -#define AK4396_DZFE 0x80 -/* control 3 */ -#define AK4396_DZFB 0x04 -#define AK4396_DCKB 0x10 -#define AK4396_DCKS 0x20 -#define AK4396_DSDM 0x40 -#define AK4396_D_P_MASK 0x80 -#define AK4396_PCM 0x00 -#define AK4396_DSD 0x80 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cm9780.h b/ANDROID_3.4.5/sound/pci/oxygen/cm9780.h deleted file mode 100644 index 14459679..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cm9780.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef CM9780_H_INCLUDED -#define CM9780_H_INCLUDED - -#define CM9780_JACK 0x62 -#define CM9780_MIXER 0x64 -#define CM9780_GPIO_SETUP 0x70 -#define CM9780_GPIO_STATUS 0x72 - -/* jack control */ -#define CM9780_RSOE 0x0001 -#define CM9780_CBOE 0x0002 -#define CM9780_SSOE 0x0004 -#define CM9780_FROE 0x0008 -#define CM9780_HP2FMICOE 0x0010 -#define CM9780_CB2MICOE 0x0020 -#define CM9780_FMIC2LI 0x0040 -#define CM9780_FMIC2MIC 0x0080 -#define CM9780_HP2LI 0x0100 -#define CM9780_HP2MIC 0x0200 -#define CM9780_MIC2LI 0x0400 -#define CM9780_MIC2MIC 0x0800 -#define CM9780_LI2LI 0x1000 -#define CM9780_LI2MIC 0x2000 -#define CM9780_LO2LI 0x4000 -#define CM9780_LO2MIC 0x8000 - -/* mixer control */ -#define CM9780_BSTSEL 0x0001 -#define CM9780_STRO_MIC 0x0002 -#define CM9780_SPDI_FREX 0x0004 -#define CM9780_SPDI_SSEX 0x0008 -#define CM9780_SPDI_CBEX 0x0010 -#define CM9780_SPDI_RSEX 0x0020 -#define CM9780_MIX2FR 0x0040 -#define CM9780_MIX2SS 0x0080 -#define CM9780_MIX2CB 0x0100 -#define CM9780_MIX2RS 0x0200 -#define CM9780_MIX2FR_EX 0x0400 -#define CM9780_MIX2SS_EX 0x0800 -#define CM9780_MIX2CB_EX 0x1000 -#define CM9780_MIX2RS_EX 0x2000 -#define CM9780_P47_IO 0x4000 -#define CM9780_PCBSW 0x8000 - -/* GPIO setup */ -#define CM9780_GPI0EN 0x0001 -#define CM9780_GPI1EN 0x0002 -#define CM9780_SENSE_P 0x0004 -#define CM9780_LOCK_P 0x0008 -#define CM9780_GPIO0P 0x0010 -#define CM9780_GPIO1P 0x0020 -#define CM9780_GPIO0IO 0x0100 -#define CM9780_GPIO1IO 0x0200 - -/* GPIO status */ -#define CM9780_GPO0 0x0001 -#define CM9780_GPO1 0x0002 -#define CM9780_GPIO0S 0x0010 -#define CM9780_GPIO1S 0x0020 -#define CM9780_GPII0S 0x0100 -#define CM9780_GPII1S 0x0200 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cs2000.h b/ANDROID_3.4.5/sound/pci/oxygen/cs2000.h deleted file mode 100644 index c3501bdb..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cs2000.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef CS2000_H_INCLUDED -#define CS2000_H_INCLUDED - -#define CS2000_DEV_ID 0x01 -#define CS2000_DEV_CTRL 0x02 -#define CS2000_DEV_CFG_1 0x03 -#define CS2000_DEV_CFG_2 0x04 -#define CS2000_GLOBAL_CFG 0x05 -#define CS2000_RATIO_0 0x06 /* 32 bits, big endian */ -#define CS2000_RATIO_1 0x0a -#define CS2000_RATIO_2 0x0e -#define CS2000_RATIO_3 0x12 -#define CS2000_FUN_CFG_1 0x16 -#define CS2000_FUN_CFG_2 0x17 -#define CS2000_FUN_CFG_3 0x1e - -/* DEV_ID */ -#define CS2000_DEVICE_MASK 0xf8 -#define CS2000_REVISION_MASK 0x07 - -/* DEV_CTRL */ -#define CS2000_UNLOCK 0x80 -#define CS2000_AUX_OUT_DIS 0x02 -#define CS2000_CLK_OUT_DIS 0x01 - -/* DEV_CFG_1 */ -#define CS2000_R_MOD_SEL_MASK 0xe0 -#define CS2000_R_MOD_SEL_1 0x00 -#define CS2000_R_MOD_SEL_2 0x20 -#define CS2000_R_MOD_SEL_4 0x40 -#define CS2000_R_MOD_SEL_8 0x60 -#define CS2000_R_MOD_SEL_1_2 0x80 -#define CS2000_R_MOD_SEL_1_4 0xa0 -#define CS2000_R_MOD_SEL_1_8 0xc0 -#define CS2000_R_MOD_SEL_1_16 0xe0 -#define CS2000_R_SEL_MASK 0x18 -#define CS2000_R_SEL_SHIFT 3 -#define CS2000_AUX_OUT_SRC_MASK 0x06 -#define CS2000_AUX_OUT_SRC_REF_CLK 0x00 -#define CS2000_AUX_OUT_SRC_CLK_IN 0x02 -#define CS2000_AUX_OUT_SRC_CLK_OUT 0x04 -#define CS2000_AUX_OUT_SRC_PLL_LOCK 0x06 -#define CS2000_EN_DEV_CFG_1 0x01 - -/* DEV_CFG_2 */ -#define CS2000_LOCK_CLK_MASK 0x06 -#define CS2000_LOCK_CLK_SHIFT 1 -#define CS2000_FRAC_N_SRC_MASK 0x01 -#define CS2000_FRAC_N_SRC_STATIC 0x00 -#define CS2000_FRAC_N_SRC_DYNAMIC 0x01 - -/* GLOBAL_CFG */ -#define CS2000_FREEZE 0x08 -#define CS2000_EN_DEV_CFG_2 0x01 - -/* FUN_CFG_1 */ -#define CS2000_CLK_SKIP_EN 0x80 -#define CS2000_AUX_LOCK_CFG_MASK 0x40 -#define CS2000_AUX_LOCK_CFG_PP_HIGH 0x00 -#define CS2000_AUX_LOCK_CFG_OD_LOW 0x40 -#define CS2000_REF_CLK_DIV_MASK 0x18 -#define CS2000_REF_CLK_DIV_4 0x00 -#define CS2000_REF_CLK_DIV_2 0x08 -#define CS2000_REF_CLK_DIV_1 0x10 - -/* FUN_CFG_2 */ -#define CS2000_CLK_OUT_UNL 0x10 -#define CS2000_L_F_RATIO_CFG_MASK 0x08 -#define CS2000_L_F_RATIO_CFG_20_12 0x00 -#define CS2000_L_F_RATIO_CFG_12_20 0x08 - -/* FUN_CFG_3 */ -#define CS2000_CLK_IN_BW_MASK 0x70 -#define CS2000_CLK_IN_BW_1 0x00 -#define CS2000_CLK_IN_BW_2 0x10 -#define CS2000_CLK_IN_BW_4 0x20 -#define CS2000_CLK_IN_BW_8 0x30 -#define CS2000_CLK_IN_BW_16 0x40 -#define CS2000_CLK_IN_BW_32 0x50 -#define CS2000_CLK_IN_BW_64 0x60 -#define CS2000_CLK_IN_BW_128 0x70 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cs4245.h b/ANDROID_3.4.5/sound/pci/oxygen/cs4245.h deleted file mode 100644 index 5e0197e0..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cs4245.h +++ /dev/null @@ -1,107 +0,0 @@ -#define CS4245_CHIP_ID 0x01 -#define CS4245_POWER_CTRL 0x02 -#define CS4245_DAC_CTRL_1 0x03 -#define CS4245_ADC_CTRL 0x04 -#define CS4245_MCLK_FREQ 0x05 -#define CS4245_SIGNAL_SEL 0x06 -#define CS4245_PGA_B_CTRL 0x07 -#define CS4245_PGA_A_CTRL 0x08 -#define CS4245_ANALOG_IN 0x09 -#define CS4245_DAC_A_CTRL 0x0a -#define CS4245_DAC_B_CTRL 0x0b -#define CS4245_DAC_CTRL_2 0x0c -#define CS4245_INT_STATUS 0x0d -#define CS4245_INT_MASK 0x0e -#define CS4245_INT_MODE_MSB 0x0f -#define CS4245_INT_MODE_LSB 0x10 - -/* Chip ID */ -#define CS4245_CHIP_PART_MASK 0xf0 -#define CS4245_CHIP_REV_MASK 0x0f - -/* Power Control */ -#define CS4245_FREEZE 0x80 -#define CS4245_PDN_MIC 0x08 -#define CS4245_PDN_ADC 0x04 -#define CS4245_PDN_DAC 0x02 -#define CS4245_PDN 0x01 - -/* DAC Control */ -#define CS4245_DAC_FM_MASK 0xc0 -#define CS4245_DAC_FM_SINGLE 0x00 -#define CS4245_DAC_FM_DOUBLE 0x40 -#define CS4245_DAC_FM_QUAD 0x80 -#define CS4245_DAC_DIF_MASK 0x30 -#define CS4245_DAC_DIF_LJUST 0x00 -#define CS4245_DAC_DIF_I2S 0x10 -#define CS4245_DAC_DIF_RJUST_16 0x20 -#define CS4245_DAC_DIF_RJUST_24 0x30 -#define CS4245_RESERVED_1 0x08 -#define CS4245_MUTE_DAC 0x04 -#define CS4245_DEEMPH 0x02 -#define CS4245_DAC_MASTER 0x01 - -/* ADC Control */ -#define CS4245_ADC_FM_MASK 0xc0 -#define CS4245_ADC_FM_SINGLE 0x00 -#define CS4245_ADC_FM_DOUBLE 0x40 -#define CS4245_ADC_FM_QUAD 0x80 -#define CS4245_ADC_DIF_MASK 0x10 -#define CS4245_ADC_DIF_LJUST 0x00 -#define CS4245_ADC_DIF_I2S 0x10 -#define CS4245_MUTE_ADC 0x04 -#define CS4245_HPF_FREEZE 0x02 -#define CS4245_ADC_MASTER 0x01 - -/* MCLK Frequency */ -#define CS4245_MCLK1_MASK 0x70 -#define CS4245_MCLK1_SHIFT 4 -#define CS4245_MCLK2_MASK 0x07 -#define CS4245_MCLK2_SHIFT 0 -#define CS4245_MCLK_1 0 -#define CS4245_MCLK_1_5 1 -#define CS4245_MCLK_2 2 -#define CS4245_MCLK_3 3 -#define CS4245_MCLK_4 4 - -/* Signal Selection */ -#define CS4245_A_OUT_SEL_MASK 0x60 -#define CS4245_A_OUT_SEL_HIZ 0x00 -#define CS4245_A_OUT_SEL_DAC 0x20 -#define CS4245_A_OUT_SEL_PGA 0x40 -#define CS4245_LOOP 0x02 -#define CS4245_ASYNCH 0x01 - -/* Channel B/A PGA Control */ -#define CS4245_PGA_GAIN_MASK 0x3f - -/* ADC Input Control */ -#define CS4245_PGA_SOFT 0x10 -#define CS4245_PGA_ZERO 0x08 -#define CS4245_SEL_MASK 0x07 -#define CS4245_SEL_MIC 0x00 -#define CS4245_SEL_INPUT_1 0x01 -#define CS4245_SEL_INPUT_2 0x02 -#define CS4245_SEL_INPUT_3 0x03 -#define CS4245_SEL_INPUT_4 0x04 -#define CS4245_SEL_INPUT_5 0x05 -#define CS4245_SEL_INPUT_6 0x06 - -/* DAC Channel A/B Volume Control */ -#define CS4245_VOL_MASK 0xff - -/* DAC Control 2 */ -#define CS4245_DAC_SOFT 0x80 -#define CS4245_DAC_ZERO 0x40 -#define CS4245_INVERT_DAC 0x20 -#define CS4245_INT_ACTIVE_HIGH 0x01 - -/* Interrupt Status/Mask/Mode */ -#define CS4245_ADC_CLK_ERR 0x08 -#define CS4245_DAC_CLK_ERR 0x04 -#define CS4245_ADC_OVFL 0x02 -#define CS4245_ADC_UNDRFL 0x01 - - -#define CS4245_SPI_ADDRESS (0x9e << 16) -#define CS4245_SPI_WRITE (0 << 16) diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cs4362a.h b/ANDROID_3.4.5/sound/pci/oxygen/cs4362a.h deleted file mode 100644 index 6a4fedf5..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cs4362a.h +++ /dev/null @@ -1,69 +0,0 @@ -/* register 01h */ -#define CS4362A_PDN 0x01 -#define CS4362A_DAC1_DIS 0x02 -#define CS4362A_DAC2_DIS 0x04 -#define CS4362A_DAC3_DIS 0x08 -#define CS4362A_MCLKDIV 0x20 -#define CS4362A_FREEZE 0x40 -#define CS4362A_CPEN 0x80 -/* register 02h */ -#define CS4362A_DIF_MASK 0x70 -#define CS4362A_DIF_LJUST 0x00 -#define CS4362A_DIF_I2S 0x10 -#define CS4362A_DIF_RJUST_16 0x20 -#define CS4362A_DIF_RJUST_24 0x30 -#define CS4362A_DIF_RJUST_20 0x40 -#define CS4362A_DIF_RJUST_18 0x50 -/* register 03h */ -#define CS4362A_MUTEC_MASK 0x03 -#define CS4362A_MUTEC_6 0x00 -#define CS4362A_MUTEC_1 0x01 -#define CS4362A_MUTEC_3 0x03 -#define CS4362A_AMUTE 0x04 -#define CS4362A_MUTEC_POL 0x08 -#define CS4362A_RMP_UP 0x10 -#define CS4362A_SNGLVOL 0x20 -#define CS4362A_ZERO_CROSS 0x40 -#define CS4362A_SOFT_RAMP 0x80 -/* register 04h */ -#define CS4362A_RMP_DN 0x01 -#define CS4362A_DEM_MASK 0x06 -#define CS4362A_DEM_NONE 0x00 -#define CS4362A_DEM_44100 0x02 -#define CS4362A_DEM_48000 0x04 -#define CS4362A_DEM_32000 0x06 -#define CS4362A_FILT_SEL 0x10 -/* register 05h */ -#define CS4362A_INV_A1 0x01 -#define CS4362A_INV_B1 0x02 -#define CS4362A_INV_A2 0x04 -#define CS4362A_INV_B2 0x08 -#define CS4362A_INV_A3 0x10 -#define CS4362A_INV_B3 0x20 -/* register 06h */ -#define CS4362A_FM_MASK 0x03 -#define CS4362A_FM_SINGLE 0x00 -#define CS4362A_FM_DOUBLE 0x01 -#define CS4362A_FM_QUAD 0x02 -#define CS4362A_FM_DSD 0x03 -#define CS4362A_ATAPI_MASK 0x7c -#define CS4362A_ATAPI_B_MUTE 0x00 -#define CS4362A_ATAPI_B_R 0x04 -#define CS4362A_ATAPI_B_L 0x08 -#define CS4362A_ATAPI_B_LR 0x0c -#define CS4362A_ATAPI_A_MUTE 0x00 -#define CS4362A_ATAPI_A_R 0x10 -#define CS4362A_ATAPI_A_L 0x20 -#define CS4362A_ATAPI_A_LR 0x30 -#define CS4362A_ATAPI_MIX_LR_VOL 0x40 -#define CS4362A_A_EQ_B 0x80 -/* register 07h */ -#define CS4362A_VOL_MASK 0x7f -#define CS4362A_MUTE 0x80 -/* register 08h: like 07h */ -/* registers 09h..0Bh: like 06h..08h */ -/* registers 0Ch..0Eh: like 06h..08h */ -/* register 12h */ -#define CS4362A_REV_MASK 0x07 -#define CS4362A_PART_MASK 0xf8 -#define CS4362A_PART_CS4362A 0x50 diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cs4398.h b/ANDROID_3.4.5/sound/pci/oxygen/cs4398.h deleted file mode 100644 index 5faf5efc..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cs4398.h +++ /dev/null @@ -1,69 +0,0 @@ -/* register 1 */ -#define CS4398_REV_MASK 0x07 -#define CS4398_PART_MASK 0xf8 -#define CS4398_PART_CS4398 0x70 -/* register 2 */ -#define CS4398_FM_MASK 0x03 -#define CS4398_FM_SINGLE 0x00 -#define CS4398_FM_DOUBLE 0x01 -#define CS4398_FM_QUAD 0x02 -#define CS4398_FM_DSD 0x03 -#define CS4398_DEM_MASK 0x0c -#define CS4398_DEM_NONE 0x00 -#define CS4398_DEM_44100 0x04 -#define CS4398_DEM_48000 0x08 -#define CS4398_DEM_32000 0x0c -#define CS4398_DIF_MASK 0x70 -#define CS4398_DIF_LJUST 0x00 -#define CS4398_DIF_I2S 0x10 -#define CS4398_DIF_RJUST_16 0x20 -#define CS4398_DIF_RJUST_24 0x30 -#define CS4398_DIF_RJUST_20 0x40 -#define CS4398_DIF_RJUST_18 0x50 -#define CS4398_DSD_SRC 0x80 -/* register 3 */ -#define CS4398_ATAPI_MASK 0x1f -#define CS4398_ATAPI_B_MUTE 0x00 -#define CS4398_ATAPI_B_R 0x01 -#define CS4398_ATAPI_B_L 0x02 -#define CS4398_ATAPI_B_LR 0x03 -#define CS4398_ATAPI_A_MUTE 0x00 -#define CS4398_ATAPI_A_R 0x04 -#define CS4398_ATAPI_A_L 0x08 -#define CS4398_ATAPI_A_LR 0x0c -#define CS4398_ATAPI_MIX_LR_VOL 0x10 -#define CS4398_INVERT_B 0x20 -#define CS4398_INVERT_A 0x40 -#define CS4398_VOL_B_EQ_A 0x80 -/* register 4 */ -#define CS4398_MUTEP_MASK 0x03 -#define CS4398_MUTEP_AUTO 0x00 -#define CS4398_MUTEP_LOW 0x02 -#define CS4398_MUTEP_HIGH 0x03 -#define CS4398_MUTE_B 0x08 -#define CS4398_MUTE_A 0x10 -#define CS4398_MUTEC_A_EQ_B 0x20 -#define CS4398_DAMUTE 0x40 -#define CS4398_PAMUTE 0x80 -/* register 5 */ -#define CS4398_VOL_A_MASK 0xff -/* register 6 */ -#define CS4398_VOL_B_MASK 0xff -/* register 7 */ -#define CS4398_DIR_DSD 0x01 -#define CS4398_FILT_SEL 0x04 -#define CS4398_RMP_DN 0x10 -#define CS4398_RMP_UP 0x20 -#define CS4398_ZERO_CROSS 0x40 -#define CS4398_SOFT_RAMP 0x80 -/* register 8 */ -#define CS4398_MCLKDIV3 0x08 -#define CS4398_MCLKDIV2 0x10 -#define CS4398_FREEZE 0x20 -#define CS4398_CPEN 0x40 -#define CS4398_PDN 0x80 -/* register 9 */ -#define CS4398_DSD_PM_EN 0x01 -#define CS4398_DSD_PM_MODE 0x02 -#define CS4398_INVALID_DSD 0x04 -#define CS4398_STATIC_DSD 0x08 diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen.c deleted file mode 100644 index eab663ee..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen.c +++ /dev/null @@ -1,884 +0,0 @@ -/* - * C-Media CMI8788 driver for C-Media's reference design and similar models - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * CMI8788: - * - * SPI 0 -> 1st AK4396 (front) - * SPI 1 -> 2nd AK4396 (surround) - * SPI 2 -> 3rd AK4396 (center/LFE) - * SPI 3 -> WM8785 - * SPI 4 -> 4th AK4396 (back) - * - * GPIO 0 -> DFS0 of AK5385 - * GPIO 1 -> DFS1 of AK5385 - * - * X-Meridian models: - * GPIO 4 -> enable extension S/PDIF input - * GPIO 6 -> enable on-board S/PDIF input - * - * Claro models: - * GPIO 6 -> S/PDIF from optical (0) or coaxial (1) input - * GPIO 8 -> enable headphone amplifier - * - * CM9780: - * - * LINE_OUT -> input of ADC - * - * AUX_IN <- aux - * CD_IN <- CD - * MIC_IN <- mic - * - * GPO 0 -> route line-in (0) or AC97 output (1) to ADC input - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "oxygen.h" -#include "xonar_dg.h" -#include "ak4396.h" -#include "wm8785.h" - -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_DESCRIPTION("C-Media CMI8788 driver"); -MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8786}" - ",{C-Media,CMI8787}" - ",{C-Media,CMI8788}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "card index"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string"); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "enable card"); - -enum { - MODEL_CMEDIA_REF, - MODEL_MERIDIAN, - MODEL_MERIDIAN_2G, - MODEL_CLARO, - MODEL_CLARO_HALO, - MODEL_FANTASIA, - MODEL_SERENADE, - MODEL_2CH_OUTPUT, - MODEL_HG2PCI, - MODEL_XONAR_DG, -}; - -static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = { - /* C-Media's reference design */ - { OXYGEN_PCI_SUBID(0x10b0, 0x0216), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x10b0, 0x0217), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x10b0, 0x0218), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x10b0, 0x0219), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, - /* Asus Xonar DG */ - { OXYGEN_PCI_SUBID(0x1043, 0x8467), .driver_data = MODEL_XONAR_DG }, - /* PCI 2.0 HD Audio */ - { OXYGEN_PCI_SUBID(0x13f6, 0x8782), .driver_data = MODEL_2CH_OUTPUT }, - /* Kuroutoshikou CMI8787-HG2PCI */ - { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_HG2PCI }, - /* TempoTec HiFier Fantasia */ - { OXYGEN_PCI_SUBID(0x14c3, 0x1710), .driver_data = MODEL_FANTASIA }, - /* TempoTec HiFier Serenade */ - { OXYGEN_PCI_SUBID(0x14c3, 0x1711), .driver_data = MODEL_SERENADE }, - /* AuzenTech X-Meridian */ - { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, - /* AuzenTech X-Meridian 2G */ - { OXYGEN_PCI_SUBID(0x5431, 0x017a), .driver_data = MODEL_MERIDIAN_2G }, - /* HT-Omega Claro */ - { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, - /* HT-Omega Claro halo */ - { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, - { } -}; -MODULE_DEVICE_TABLE(pci, oxygen_ids); - - -#define GPIO_AK5385_DFS_MASK 0x0003 -#define GPIO_AK5385_DFS_NORMAL 0x0000 -#define GPIO_AK5385_DFS_DOUBLE 0x0001 -#define GPIO_AK5385_DFS_QUAD 0x0002 - -#define GPIO_MERIDIAN_DIG_MASK 0x0050 -#define GPIO_MERIDIAN_DIG_EXT 0x0010 -#define GPIO_MERIDIAN_DIG_BOARD 0x0040 - -#define GPIO_CLARO_DIG_COAX 0x0040 -#define GPIO_CLARO_HP 0x0100 - -struct generic_data { - unsigned int dacs; - u8 ak4396_regs[4][5]; - u16 wm8785_regs[3]; -}; - -static void ak4396_write(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - /* maps ALSA channel pair number to SPI output */ - static const u8 codec_spi_map[4] = { - 0, 1, 2, 4 - }; - struct generic_data *data = chip->model_data; - - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_HI, - AK4396_WRITE | (reg << 8) | value); - data->ak4396_regs[codec][reg] = value; -} - -static void ak4396_write_cached(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - struct generic_data *data = chip->model_data; - - if (value != data->ak4396_regs[codec][reg]) - ak4396_write(chip, codec, reg, value); -} - -static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value) -{ - struct generic_data *data = chip->model_data; - - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (3 << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_LO, - (reg << 9) | value); - if (reg < ARRAY_SIZE(data->wm8785_regs)) - data->wm8785_regs[reg] = value; -} - -static void ak4396_registers_init(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - - for (i = 0; i < data->dacs; ++i) { - ak4396_write(chip, i, AK4396_CONTROL_1, - AK4396_DIF_24_MSB | AK4396_RSTN); - ak4396_write(chip, i, AK4396_CONTROL_2, - data->ak4396_regs[0][AK4396_CONTROL_2]); - ak4396_write(chip, i, AK4396_CONTROL_3, - AK4396_PCM); - ak4396_write(chip, i, AK4396_LCH_ATT, - chip->dac_volume[i * 2]); - ak4396_write(chip, i, AK4396_RCH_ATT, - chip->dac_volume[i * 2 + 1]); - } -} - -static void ak4396_init(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - - data->dacs = chip->model.dac_channels_pcm / 2; - data->ak4396_regs[0][AK4396_CONTROL_2] = - AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; - ak4396_registers_init(chip); - snd_component_add(chip->card, "AK4396"); -} - -static void ak5385_init(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_AK5385_DFS_MASK); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_AK5385_DFS_MASK); - snd_component_add(chip->card, "AK5385"); -} - -static void wm8785_registers_init(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - - wm8785_write(chip, WM8785_R7, 0); - wm8785_write(chip, WM8785_R0, data->wm8785_regs[0]); - wm8785_write(chip, WM8785_R2, data->wm8785_regs[2]); -} - -static void wm8785_init(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - - data->wm8785_regs[0] = - WM8785_MCR_SLAVE | WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST; - data->wm8785_regs[2] = WM8785_HPFR | WM8785_HPFL; - wm8785_registers_init(chip); - snd_component_add(chip->card, "WM8785"); -} - -static void generic_init(struct oxygen *chip) -{ - ak4396_init(chip); - wm8785_init(chip); -} - -static void meridian_init(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_MERIDIAN_DIG_MASK); - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - GPIO_MERIDIAN_DIG_BOARD, GPIO_MERIDIAN_DIG_MASK); - ak4396_init(chip); - ak5385_init(chip); -} - -static void claro_enable_hp(struct oxygen *chip) -{ - msleep(300); - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_HP); - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); -} - -static void claro_init(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); - ak4396_init(chip); - wm8785_init(chip); - claro_enable_hp(chip); -} - -static void claro_halo_init(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); - ak4396_init(chip); - ak5385_init(chip); - claro_enable_hp(chip); -} - -static void fantasia_init(struct oxygen *chip) -{ - ak4396_init(chip); - snd_component_add(chip->card, "CS5340"); -} - -static void stereo_output_init(struct oxygen *chip) -{ - ak4396_init(chip); -} - -static void generic_cleanup(struct oxygen *chip) -{ -} - -static void claro_disable_hp(struct oxygen *chip) -{ - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); -} - -static void claro_cleanup(struct oxygen *chip) -{ - claro_disable_hp(chip); -} - -static void claro_suspend(struct oxygen *chip) -{ - claro_disable_hp(chip); -} - -static void generic_resume(struct oxygen *chip) -{ - ak4396_registers_init(chip); - wm8785_registers_init(chip); -} - -static void meridian_resume(struct oxygen *chip) -{ - ak4396_registers_init(chip); -} - -static void claro_resume(struct oxygen *chip) -{ - ak4396_registers_init(chip); - claro_enable_hp(chip); -} - -static void stereo_resume(struct oxygen *chip) -{ - ak4396_registers_init(chip); -} - -static void set_ak4396_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - u8 value; - - value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_DFS_MASK; - if (params_rate(params) <= 54000) - value |= AK4396_DFS_NORMAL; - else if (params_rate(params) <= 108000) - value |= AK4396_DFS_DOUBLE; - else - value |= AK4396_DFS_QUAD; - - msleep(1); /* wait for the new MCLK to become stable */ - - if (value != data->ak4396_regs[0][AK4396_CONTROL_2]) { - for (i = 0; i < data->dacs; ++i) { - ak4396_write(chip, i, AK4396_CONTROL_1, - AK4396_DIF_24_MSB); - ak4396_write(chip, i, AK4396_CONTROL_2, value); - ak4396_write(chip, i, AK4396_CONTROL_1, - AK4396_DIF_24_MSB | AK4396_RSTN); - } - } -} - -static void update_ak4396_volume(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - - for (i = 0; i < data->dacs; ++i) { - ak4396_write_cached(chip, i, AK4396_LCH_ATT, - chip->dac_volume[i * 2]); - ak4396_write_cached(chip, i, AK4396_RCH_ATT, - chip->dac_volume[i * 2 + 1]); - } -} - -static void update_ak4396_mute(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - u8 value; - - value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE; - if (chip->dac_mute) - value |= AK4396_SMUTE; - for (i = 0; i < data->dacs; ++i) - ak4396_write_cached(chip, i, AK4396_CONTROL_2, value); -} - -static void set_wm8785_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct generic_data *data = chip->model_data; - unsigned int value; - - value = WM8785_MCR_SLAVE | WM8785_FORMAT_LJUST; - if (params_rate(params) <= 48000) - value |= WM8785_OSR_SINGLE; - else if (params_rate(params) <= 96000) - value |= WM8785_OSR_DOUBLE; - else - value |= WM8785_OSR_QUAD; - if (value != data->wm8785_regs[0]) { - wm8785_write(chip, WM8785_R7, 0); - wm8785_write(chip, WM8785_R0, value); - wm8785_write(chip, WM8785_R2, data->wm8785_regs[2]); - } -} - -static void set_ak5385_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - unsigned int value; - - if (params_rate(params) <= 54000) - value = GPIO_AK5385_DFS_NORMAL; - else if (params_rate(params) <= 108000) - value = GPIO_AK5385_DFS_DOUBLE; - else - value = GPIO_AK5385_DFS_QUAD; - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - value, GPIO_AK5385_DFS_MASK); -} - -static void set_no_params(struct oxygen *chip, struct snd_pcm_hw_params *params) -{ -} - -static int rolloff_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "Sharp Roll-off", "Slow Roll-off" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int rolloff_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct generic_data *data = chip->model_data; - - value->value.enumerated.item[0] = - (data->ak4396_regs[0][AK4396_CONTROL_2] & AK4396_SLOW) != 0; - return 0; -} - -static int rolloff_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct generic_data *data = chip->model_data; - unsigned int i; - int changed; - u8 reg; - - mutex_lock(&chip->mutex); - reg = data->ak4396_regs[0][AK4396_CONTROL_2]; - if (value->value.enumerated.item[0]) - reg |= AK4396_SLOW; - else - reg &= ~AK4396_SLOW; - changed = reg != data->ak4396_regs[0][AK4396_CONTROL_2]; - if (changed) { - for (i = 0; i < data->dacs; ++i) - ak4396_write(chip, i, AK4396_CONTROL_2, reg); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new rolloff_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Filter Playback Enum", - .info = rolloff_info, - .get = rolloff_get, - .put = rolloff_put, -}; - -static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "None", "High-pass Filter" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct generic_data *data = chip->model_data; - - value->value.enumerated.item[0] = - (data->wm8785_regs[WM8785_R2] & WM8785_HPFR) != 0; - return 0; -} - -static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct generic_data *data = chip->model_data; - unsigned int reg; - int changed; - - mutex_lock(&chip->mutex); - reg = data->wm8785_regs[WM8785_R2] & ~(WM8785_HPFR | WM8785_HPFL); - if (value->value.enumerated.item[0]) - reg |= WM8785_HPFR | WM8785_HPFL; - changed = reg != data->wm8785_regs[WM8785_R2]; - if (changed) - wm8785_write(chip, WM8785_R2, reg); - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new hpf_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Filter Capture Enum", - .info = hpf_info, - .get = hpf_get, - .put = hpf_put, -}; - -static int meridian_dig_source_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { "On-board", "Extension" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int claro_dig_source_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { "Optical", "Coaxial" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int meridian_dig_source_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - value->value.enumerated.item[0] = - !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & - GPIO_MERIDIAN_DIG_EXT); - return 0; -} - -static int claro_dig_source_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - value->value.enumerated.item[0] = - !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & - GPIO_CLARO_DIG_COAX); - return 0; -} - -static int meridian_dig_source_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 old_reg, new_reg; - int changed; - - mutex_lock(&chip->mutex); - old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); - new_reg = old_reg & ~GPIO_MERIDIAN_DIG_MASK; - if (value->value.enumerated.item[0] == 0) - new_reg |= GPIO_MERIDIAN_DIG_BOARD; - else - new_reg |= GPIO_MERIDIAN_DIG_EXT; - changed = new_reg != old_reg; - if (changed) - oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); - mutex_unlock(&chip->mutex); - return changed; -} - -static int claro_dig_source_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 old_reg, new_reg; - int changed; - - mutex_lock(&chip->mutex); - old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); - new_reg = old_reg & ~GPIO_CLARO_DIG_COAX; - if (value->value.enumerated.item[0]) - new_reg |= GPIO_CLARO_DIG_COAX; - changed = new_reg != old_reg; - if (changed) - oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new meridian_dig_source_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Source Capture Enum", - .info = meridian_dig_source_info, - .get = meridian_dig_source_get, - .put = meridian_dig_source_put, -}; - -static const struct snd_kcontrol_new claro_dig_source_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Source Capture Enum", - .info = claro_dig_source_info, - .get = claro_dig_source_get, - .put = claro_dig_source_put, -}; - -static int generic_mixer_init(struct oxygen *chip) -{ - return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); -} - -static int generic_wm8785_mixer_init(struct oxygen *chip) -{ - int err; - - err = generic_mixer_init(chip); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, snd_ctl_new1(&hpf_control, chip)); - if (err < 0) - return err; - return 0; -} - -static int meridian_mixer_init(struct oxygen *chip) -{ - int err; - - err = generic_mixer_init(chip); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&meridian_dig_source_control, chip)); - if (err < 0) - return err; - return 0; -} - -static int claro_mixer_init(struct oxygen *chip) -{ - int err; - - err = generic_wm8785_mixer_init(chip); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&claro_dig_source_control, chip)); - if (err < 0) - return err; - return 0; -} - -static int claro_halo_mixer_init(struct oxygen *chip) -{ - int err; - - err = generic_mixer_init(chip); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&claro_dig_source_control, chip)); - if (err < 0) - return err; - return 0; -} - -static void dump_ak4396_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct generic_data *data = chip->model_data; - unsigned int dac, i; - - for (dac = 0; dac < data->dacs; ++dac) { - snd_iprintf(buffer, "\nAK4396 %u:", dac + 1); - for (i = 0; i < 5; ++i) - snd_iprintf(buffer, " %02x", data->ak4396_regs[dac][i]); - } - snd_iprintf(buffer, "\n"); -} - -static void dump_wm8785_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - - snd_iprintf(buffer, "\nWM8785:"); - for (i = 0; i < 3; ++i) - snd_iprintf(buffer, " %03x", data->wm8785_regs[i]); - snd_iprintf(buffer, "\n"); -} - -static void dump_oxygen_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - dump_ak4396_registers(chip, buffer); - dump_wm8785_registers(chip, buffer); -} - -static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); - -static const struct oxygen_model model_generic = { - .shortname = "C-Media CMI8788", - .longname = "C-Media Oxygen HD Audio", - .chip = "CMI8788", - .init = generic_init, - .mixer_init = generic_wm8785_mixer_init, - .cleanup = generic_cleanup, - .resume = generic_resume, - .set_dac_params = set_ak4396_params, - .set_adc_params = set_wm8785_params, - .update_dac_volume = update_ak4396_volume, - .update_dac_mute = update_ak4396_mute, - .dump_registers = dump_oxygen_registers, - .dac_tlv = ak4396_db_scale, - .model_data_size = sizeof(struct generic_data), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - PLAYBACK_2_TO_AC97_1 | - CAPTURE_0_FROM_I2S_1 | - CAPTURE_1_FROM_SPDIF | - CAPTURE_2_FROM_AC97_1 | - AC97_CD_INPUT, - .dac_channels_pcm = 8, - .dac_channels_mixer = 8, - .dac_volume_min = 0, - .dac_volume_max = 255, - .function_flags = OXYGEN_FUNCTION_SPI | - OXYGEN_FUNCTION_ENABLE_SPI_4_5, - .dac_mclks = OXYGEN_MCLKS(256, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 256, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -static int __devinit get_oxygen_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - static const char *const names[] = { - [MODEL_MERIDIAN] = "AuzenTech X-Meridian", - [MODEL_MERIDIAN_2G] = "AuzenTech X-Meridian 2G", - [MODEL_CLARO] = "HT-Omega Claro", - [MODEL_CLARO_HALO] = "HT-Omega Claro halo", - [MODEL_FANTASIA] = "TempoTec HiFier Fantasia", - [MODEL_SERENADE] = "TempoTec HiFier Serenade", - [MODEL_HG2PCI] = "CMI8787-HG2PCI", - }; - - chip->model = model_generic; - switch (id->driver_data) { - case MODEL_MERIDIAN: - case MODEL_MERIDIAN_2G: - chip->model.init = meridian_init; - chip->model.mixer_init = meridian_mixer_init; - chip->model.resume = meridian_resume; - chip->model.set_adc_params = set_ak5385_params; - chip->model.dump_registers = dump_ak4396_registers; - chip->model.device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF; - if (id->driver_data == MODEL_MERIDIAN) - chip->model.device_config |= AC97_CD_INPUT; - break; - case MODEL_CLARO: - chip->model.init = claro_init; - chip->model.mixer_init = claro_mixer_init; - chip->model.cleanup = claro_cleanup; - chip->model.suspend = claro_suspend; - chip->model.resume = claro_resume; - break; - case MODEL_CLARO_HALO: - chip->model.init = claro_halo_init; - chip->model.mixer_init = claro_halo_mixer_init; - chip->model.cleanup = claro_cleanup; - chip->model.suspend = claro_suspend; - chip->model.resume = claro_resume; - chip->model.set_adc_params = set_ak5385_params; - chip->model.dump_registers = dump_ak4396_registers; - chip->model.device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF; - break; - case MODEL_FANTASIA: - case MODEL_SERENADE: - case MODEL_2CH_OUTPUT: - case MODEL_HG2PCI: - chip->model.shortname = "C-Media CMI8787"; - chip->model.chip = "CMI8787"; - if (id->driver_data == MODEL_FANTASIA) - chip->model.init = fantasia_init; - else - chip->model.init = stereo_output_init; - chip->model.resume = stereo_resume; - chip->model.mixer_init = generic_mixer_init; - chip->model.set_adc_params = set_no_params; - chip->model.dump_registers = dump_ak4396_registers; - chip->model.device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF; - if (id->driver_data == MODEL_FANTASIA) { - chip->model.device_config |= CAPTURE_0_FROM_I2S_1; - chip->model.adc_mclks = OXYGEN_MCLKS(256, 128, 128); - } - chip->model.dac_channels_pcm = 2; - chip->model.dac_channels_mixer = 2; - break; - case MODEL_XONAR_DG: - chip->model = model_xonar_dg; - break; - } - if (id->driver_data == MODEL_MERIDIAN || - id->driver_data == MODEL_MERIDIAN_2G || - id->driver_data == MODEL_CLARO_HALO) { - chip->model.misc_flags = OXYGEN_MISC_MIDI; - chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; - } - if (id->driver_data < ARRAY_SIZE(names) && names[id->driver_data]) - chip->model.shortname = names[id->driver_data]; - return 0; -} - -static int __devinit generic_oxygen_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - ++dev; - return -ENOENT; - } - err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, - oxygen_ids, get_oxygen_model); - if (err >= 0) - ++dev; - return err; -} - -static struct pci_driver oxygen_driver = { - .name = KBUILD_MODNAME, - .id_table = oxygen_ids, - .probe = generic_oxygen_probe, - .remove = __devexit_p(oxygen_pci_remove), -#ifdef CONFIG_PM - .suspend = oxygen_pci_suspend, - .resume = oxygen_pci_resume, -#endif -}; - -static int __init alsa_card_oxygen_init(void) -{ - return pci_register_driver(&oxygen_driver); -} - -static void __exit alsa_card_oxygen_exit(void) -{ - pci_unregister_driver(&oxygen_driver); -} - -module_init(alsa_card_oxygen_init) -module_exit(alsa_card_oxygen_exit) diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen.h b/ANDROID_3.4.5/sound/pci/oxygen/oxygen.h deleted file mode 100644 index f53897a7..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen.h +++ /dev/null @@ -1,260 +0,0 @@ -#ifndef OXYGEN_H_INCLUDED -#define OXYGEN_H_INCLUDED - -#include -#include -#include -#include -#include "oxygen_regs.h" - -/* 1 << PCM_x == OXYGEN_CHANNEL_x */ -#define PCM_A 0 -#define PCM_B 1 -#define PCM_C 2 -#define PCM_SPDIF 3 -#define PCM_MULTICH 4 -#define PCM_AC97 5 -#define PCM_COUNT 6 - -#define OXYGEN_MCLKS(f_single, f_double, f_quad) ((MCLK_##f_single << 0) | \ - (MCLK_##f_double << 2) | \ - (MCLK_##f_quad << 4)) - -#define OXYGEN_IO_SIZE 0x100 - -#define OXYGEN_EEPROM_ID 0x434d /* "CM" */ - -/* model-specific configuration of outputs/inputs */ -#define PLAYBACK_0_TO_I2S 0x0001 - /* PLAYBACK_0_TO_AC97_0 not implemented */ -#define PLAYBACK_1_TO_SPDIF 0x0004 -#define PLAYBACK_2_TO_AC97_1 0x0008 -#define CAPTURE_0_FROM_I2S_1 0x0010 -#define CAPTURE_0_FROM_I2S_2 0x0020 - /* CAPTURE_0_FROM_AC97_0 not implemented */ -#define CAPTURE_1_FROM_SPDIF 0x0080 -#define CAPTURE_2_FROM_I2S_2 0x0100 -#define CAPTURE_2_FROM_AC97_1 0x0200 - /* CAPTURE_3_FROM_I2S_3 not implemented */ -#define MIDI_OUTPUT 0x0800 -#define MIDI_INPUT 0x1000 -#define AC97_CD_INPUT 0x2000 -#define AC97_FMIC_SWITCH 0x4000 - -enum { - CONTROL_SPDIF_PCM, - CONTROL_SPDIF_INPUT_BITS, - CONTROL_MIC_CAPTURE_SWITCH, - CONTROL_LINE_CAPTURE_SWITCH, - CONTROL_CD_CAPTURE_SWITCH, - CONTROL_AUX_CAPTURE_SWITCH, - CONTROL_COUNT -}; - -#define OXYGEN_PCI_SUBID(sv, sd) \ - .vendor = PCI_VENDOR_ID_CMEDIA, \ - .device = 0x8788, \ - .subvendor = sv, \ - .subdevice = sd - -#define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1) -#define OXYGEN_PCI_SUBID_BROKEN_EEPROM \ - OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \ - .driver_data = BROKEN_EEPROM_DRIVER_DATA - -struct pci_dev; -struct pci_device_id; -struct snd_card; -struct snd_pcm_substream; -struct snd_pcm_hardware; -struct snd_pcm_hw_params; -struct snd_kcontrol_new; -struct snd_rawmidi; -struct snd_info_buffer; -struct oxygen; - -struct oxygen_model { - const char *shortname; - const char *longname; - const char *chip; - void (*init)(struct oxygen *chip); - int (*control_filter)(struct snd_kcontrol_new *template); - int (*mixer_init)(struct oxygen *chip); - void (*cleanup)(struct oxygen *chip); - void (*suspend)(struct oxygen *chip); - void (*resume)(struct oxygen *chip); - void (*pcm_hardware_filter)(unsigned int channel, - struct snd_pcm_hardware *hardware); - void (*set_dac_params)(struct oxygen *chip, - struct snd_pcm_hw_params *params); - void (*set_adc_params)(struct oxygen *chip, - struct snd_pcm_hw_params *params); - void (*update_dac_volume)(struct oxygen *chip); - void (*update_dac_mute)(struct oxygen *chip); - void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed); - unsigned int (*adjust_dac_routing)(struct oxygen *chip, - unsigned int play_routing); - void (*gpio_changed)(struct oxygen *chip); - void (*uart_input)(struct oxygen *chip); - void (*ac97_switch)(struct oxygen *chip, - unsigned int reg, unsigned int mute); - void (*dump_registers)(struct oxygen *chip, - struct snd_info_buffer *buffer); - const unsigned int *dac_tlv; - size_t model_data_size; - unsigned int device_config; - u8 dac_channels_pcm; - u8 dac_channels_mixer; - u8 dac_volume_min; - u8 dac_volume_max; - u8 misc_flags; - u8 function_flags; - u8 dac_mclks; - u8 adc_mclks; - u16 dac_i2s_format; - u16 adc_i2s_format; -}; - -struct oxygen { - unsigned long addr; - spinlock_t reg_lock; - struct mutex mutex; - struct snd_card *card; - struct pci_dev *pci; - struct snd_rawmidi *midi; - int irq; - void *model_data; - unsigned int interrupt_mask; - u8 dac_volume[8]; - u8 dac_mute; - u8 pcm_active; - u8 pcm_running; - u8 dac_routing; - u8 spdif_playback_enable; - u8 has_ac97_0; - u8 has_ac97_1; - u32 spdif_bits; - u32 spdif_pcm_bits; - struct snd_pcm_substream *streams[PCM_COUNT]; - struct snd_kcontrol *controls[CONTROL_COUNT]; - struct work_struct spdif_input_bits_work; - struct work_struct gpio_work; - wait_queue_head_t ac97_waitqueue; - union { - u8 _8[OXYGEN_IO_SIZE]; - __le16 _16[OXYGEN_IO_SIZE / 2]; - __le32 _32[OXYGEN_IO_SIZE / 4]; - } saved_registers; - u16 saved_ac97_registers[2][0x40]; - unsigned int uart_input_count; - u8 uart_input[32]; - struct oxygen_model model; -}; - -/* oxygen_lib.c */ - -int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, - struct module *owner, - const struct pci_device_id *ids, - int (*get_model)(struct oxygen *chip, - const struct pci_device_id *id - ) - ); -void oxygen_pci_remove(struct pci_dev *pci); -#ifdef CONFIG_PM -int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); -int oxygen_pci_resume(struct pci_dev *pci); -#endif -void oxygen_pci_shutdown(struct pci_dev *pci); - -/* oxygen_mixer.c */ - -int oxygen_mixer_init(struct oxygen *chip); -void oxygen_update_dac_routing(struct oxygen *chip); -void oxygen_update_spdif_source(struct oxygen *chip); - -/* oxygen_pcm.c */ - -int oxygen_pcm_init(struct oxygen *chip); - -/* oxygen_io.c */ - -u8 oxygen_read8(struct oxygen *chip, unsigned int reg); -u16 oxygen_read16(struct oxygen *chip, unsigned int reg); -u32 oxygen_read32(struct oxygen *chip, unsigned int reg); -void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value); -void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value); -void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value); -void oxygen_write8_masked(struct oxygen *chip, unsigned int reg, - u8 value, u8 mask); -void oxygen_write16_masked(struct oxygen *chip, unsigned int reg, - u16 value, u16 mask); -void oxygen_write32_masked(struct oxygen *chip, unsigned int reg, - u32 value, u32 mask); - -u16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec, - unsigned int index); -void oxygen_write_ac97(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 data); -void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 data, u16 mask); - -void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data); -void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); - -void oxygen_reset_uart(struct oxygen *chip); -void oxygen_write_uart(struct oxygen *chip, u8 data); - -u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); -void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value); - -static inline void oxygen_set_bits8(struct oxygen *chip, - unsigned int reg, u8 value) -{ - oxygen_write8_masked(chip, reg, value, value); -} - -static inline void oxygen_set_bits16(struct oxygen *chip, - unsigned int reg, u16 value) -{ - oxygen_write16_masked(chip, reg, value, value); -} - -static inline void oxygen_set_bits32(struct oxygen *chip, - unsigned int reg, u32 value) -{ - oxygen_write32_masked(chip, reg, value, value); -} - -static inline void oxygen_clear_bits8(struct oxygen *chip, - unsigned int reg, u8 value) -{ - oxygen_write8_masked(chip, reg, 0, value); -} - -static inline void oxygen_clear_bits16(struct oxygen *chip, - unsigned int reg, u16 value) -{ - oxygen_write16_masked(chip, reg, 0, value); -} - -static inline void oxygen_clear_bits32(struct oxygen *chip, - unsigned int reg, u32 value) -{ - oxygen_write32_masked(chip, reg, 0, value); -} - -static inline void oxygen_ac97_set_bits(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 value) -{ - oxygen_write_ac97_masked(chip, codec, index, value, value); -} - -static inline void oxygen_ac97_clear_bits(struct oxygen *chip, - unsigned int codec, - unsigned int index, u16 value) -{ - oxygen_write_ac97_masked(chip, codec, index, 0, value); -} - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_io.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_io.c deleted file mode 100644 index 521eae45..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_io.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * C-Media CMI8788 driver - helper functions - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; 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 "oxygen.h" - -u8 oxygen_read8(struct oxygen *chip, unsigned int reg) -{ - return inb(chip->addr + reg); -} -EXPORT_SYMBOL(oxygen_read8); - -u16 oxygen_read16(struct oxygen *chip, unsigned int reg) -{ - return inw(chip->addr + reg); -} -EXPORT_SYMBOL(oxygen_read16); - -u32 oxygen_read32(struct oxygen *chip, unsigned int reg) -{ - return inl(chip->addr + reg); -} -EXPORT_SYMBOL(oxygen_read32); - -void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value) -{ - outb(value, chip->addr + reg); - chip->saved_registers._8[reg] = value; -} -EXPORT_SYMBOL(oxygen_write8); - -void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value) -{ - outw(value, chip->addr + reg); - chip->saved_registers._16[reg / 2] = cpu_to_le16(value); -} -EXPORT_SYMBOL(oxygen_write16); - -void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value) -{ - outl(value, chip->addr + reg); - chip->saved_registers._32[reg / 4] = cpu_to_le32(value); -} -EXPORT_SYMBOL(oxygen_write32); - -void oxygen_write8_masked(struct oxygen *chip, unsigned int reg, - u8 value, u8 mask) -{ - u8 tmp = inb(chip->addr + reg); - tmp &= ~mask; - tmp |= value & mask; - outb(tmp, chip->addr + reg); - chip->saved_registers._8[reg] = tmp; -} -EXPORT_SYMBOL(oxygen_write8_masked); - -void oxygen_write16_masked(struct oxygen *chip, unsigned int reg, - u16 value, u16 mask) -{ - u16 tmp = inw(chip->addr + reg); - tmp &= ~mask; - tmp |= value & mask; - outw(tmp, chip->addr + reg); - chip->saved_registers._16[reg / 2] = cpu_to_le16(tmp); -} -EXPORT_SYMBOL(oxygen_write16_masked); - -void oxygen_write32_masked(struct oxygen *chip, unsigned int reg, - u32 value, u32 mask) -{ - u32 tmp = inl(chip->addr + reg); - tmp &= ~mask; - tmp |= value & mask; - outl(tmp, chip->addr + reg); - chip->saved_registers._32[reg / 4] = cpu_to_le32(tmp); -} -EXPORT_SYMBOL(oxygen_write32_masked); - -static int oxygen_ac97_wait(struct oxygen *chip, unsigned int mask) -{ - u8 status = 0; - - /* - * Reading the status register also clears the bits, so we have to save - * the read bits in status. - */ - wait_event_timeout(chip->ac97_waitqueue, - ({ status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS); - status & mask; }), - msecs_to_jiffies(1) + 1); - /* - * Check even after a timeout because this function should not require - * the AC'97 interrupt to be enabled. - */ - status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS); - return status & mask ? 0 : -EIO; -} - -/* - * About 10% of AC'97 register reads or writes fail to complete, but even those - * where the controller indicates completion aren't guaranteed to have actually - * happened. - * - * It's hard to assign blame to either the controller or the codec because both - * were made by C-Media ... - */ - -void oxygen_write_ac97(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 data) -{ - unsigned int count, succeeded; - u32 reg; - - reg = data; - reg |= index << OXYGEN_AC97_REG_ADDR_SHIFT; - reg |= OXYGEN_AC97_REG_DIR_WRITE; - reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT; - succeeded = 0; - for (count = 5; count > 0; --count) { - udelay(5); - oxygen_write32(chip, OXYGEN_AC97_REGS, reg); - /* require two "completed" writes, just to be sure */ - if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_WRITE_DONE) >= 0 && - ++succeeded >= 2) { - chip->saved_ac97_registers[codec][index / 2] = data; - return; - } - } - snd_printk(KERN_ERR "AC'97 write timeout\n"); -} -EXPORT_SYMBOL(oxygen_write_ac97); - -u16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec, - unsigned int index) -{ - unsigned int count; - unsigned int last_read = UINT_MAX; - u32 reg; - - reg = index << OXYGEN_AC97_REG_ADDR_SHIFT; - reg |= OXYGEN_AC97_REG_DIR_READ; - reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT; - for (count = 5; count > 0; --count) { - udelay(5); - oxygen_write32(chip, OXYGEN_AC97_REGS, reg); - udelay(10); - if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_READ_DONE) >= 0) { - u16 value = oxygen_read16(chip, OXYGEN_AC97_REGS); - /* we require two consecutive reads of the same value */ - if (value == last_read) - return value; - last_read = value; - /* - * Invert the register value bits to make sure that two - * consecutive unsuccessful reads do not return the same - * value. - */ - reg ^= 0xffff; - } - } - snd_printk(KERN_ERR "AC'97 read timeout on codec %u\n", codec); - return 0; -} -EXPORT_SYMBOL(oxygen_read_ac97); - -void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 data, u16 mask) -{ - u16 value = oxygen_read_ac97(chip, codec, index); - value &= ~mask; - value |= data & mask; - oxygen_write_ac97(chip, codec, index, value); -} -EXPORT_SYMBOL(oxygen_write_ac97_masked); - -void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data) -{ - unsigned int count; - - /* should not need more than 30.72 us (24 * 1.28 us) */ - count = 10; - while ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & OXYGEN_SPI_BUSY) - && count > 0) { - udelay(4); - --count; - } - - oxygen_write8(chip, OXYGEN_SPI_DATA1, data); - oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8); - if (control & OXYGEN_SPI_DATA_LENGTH_3) - oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16); - oxygen_write8(chip, OXYGEN_SPI_CONTROL, control); -} -EXPORT_SYMBOL(oxygen_write_spi); - -void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data) -{ - /* should not need more than about 300 us */ - msleep(1); - - oxygen_write8(chip, OXYGEN_2WIRE_MAP, map); - oxygen_write8(chip, OXYGEN_2WIRE_DATA, data); - oxygen_write8(chip, OXYGEN_2WIRE_CONTROL, - device | OXYGEN_2WIRE_DIR_WRITE); -} -EXPORT_SYMBOL(oxygen_write_i2c); - -static void _write_uart(struct oxygen *chip, unsigned int port, u8 data) -{ - if (oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_TX_FULL) - msleep(1); - oxygen_write8(chip, OXYGEN_MPU401 + port, data); -} - -void oxygen_reset_uart(struct oxygen *chip) -{ - _write_uart(chip, 1, MPU401_RESET); - msleep(1); /* wait for ACK */ - _write_uart(chip, 1, MPU401_ENTER_UART); -} -EXPORT_SYMBOL(oxygen_reset_uart); - -void oxygen_write_uart(struct oxygen *chip, u8 data) -{ - _write_uart(chip, 0, data); -} -EXPORT_SYMBOL(oxygen_write_uart); - -u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index) -{ - unsigned int timeout; - - oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, - index | OXYGEN_EEPROM_DIR_READ); - for (timeout = 0; timeout < 100; ++timeout) { - udelay(1); - if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) - & OXYGEN_EEPROM_BUSY)) - break; - } - return oxygen_read16(chip, OXYGEN_EEPROM_DATA); -} - -void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value) -{ - unsigned int timeout; - - oxygen_write16(chip, OXYGEN_EEPROM_DATA, value); - oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, - index | OXYGEN_EEPROM_DIR_WRITE); - for (timeout = 0; timeout < 10; ++timeout) { - msleep(1); - if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) - & OXYGEN_EEPROM_BUSY)) - return; - } - snd_printk(KERN_ERR "EEPROM write timeout\n"); -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_lib.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_lib.c deleted file mode 100644 index 92e2d67f..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_lib.c +++ /dev/null @@ -1,834 +0,0 @@ -/* - * C-Media CMI8788 driver - main driver module - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; 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 -#include -#include -#include -#include "oxygen.h" -#include "cm9780.h" - -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_DESCRIPTION("C-Media CMI8788 helper library"); -MODULE_LICENSE("GPL v2"); - -#define DRIVER "oxygen" - -static inline int oxygen_uart_input_ready(struct oxygen *chip) -{ - return !(oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_RX_EMPTY); -} - -static void oxygen_read_uart(struct oxygen *chip) -{ - if (unlikely(!oxygen_uart_input_ready(chip))) { - /* no data, but read it anyway to clear the interrupt */ - oxygen_read8(chip, OXYGEN_MPU401); - return; - } - do { - u8 data = oxygen_read8(chip, OXYGEN_MPU401); - if (data == MPU401_ACK) - continue; - if (chip->uart_input_count >= ARRAY_SIZE(chip->uart_input)) - chip->uart_input_count = 0; - chip->uart_input[chip->uart_input_count++] = data; - } while (oxygen_uart_input_ready(chip)); - if (chip->model.uart_input) - chip->model.uart_input(chip); -} - -static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) -{ - struct oxygen *chip = dev_id; - unsigned int status, clear, elapsed_streams, i; - - status = oxygen_read16(chip, OXYGEN_INTERRUPT_STATUS); - if (!status) - return IRQ_NONE; - - spin_lock(&chip->reg_lock); - - clear = status & (OXYGEN_CHANNEL_A | - OXYGEN_CHANNEL_B | - OXYGEN_CHANNEL_C | - OXYGEN_CHANNEL_SPDIF | - OXYGEN_CHANNEL_MULTICH | - OXYGEN_CHANNEL_AC97 | - OXYGEN_INT_SPDIF_IN_DETECT | - OXYGEN_INT_GPIO | - OXYGEN_INT_AC97); - if (clear) { - if (clear & OXYGEN_INT_SPDIF_IN_DETECT) - chip->interrupt_mask &= ~OXYGEN_INT_SPDIF_IN_DETECT; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask & ~clear); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask); - } - - elapsed_streams = status & chip->pcm_running; - - spin_unlock(&chip->reg_lock); - - for (i = 0; i < PCM_COUNT; ++i) - if ((elapsed_streams & (1 << i)) && chip->streams[i]) - snd_pcm_period_elapsed(chip->streams[i]); - - if (status & OXYGEN_INT_SPDIF_IN_DETECT) { - spin_lock(&chip->reg_lock); - i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if (i & (OXYGEN_SPDIF_SENSE_INT | OXYGEN_SPDIF_LOCK_INT | - OXYGEN_SPDIF_RATE_INT)) { - /* write the interrupt bit(s) to clear */ - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i); - schedule_work(&chip->spdif_input_bits_work); - } - spin_unlock(&chip->reg_lock); - } - - if (status & OXYGEN_INT_GPIO) - schedule_work(&chip->gpio_work); - - if (status & OXYGEN_INT_MIDI) { - if (chip->midi) - snd_mpu401_uart_interrupt(0, chip->midi->private_data); - else - oxygen_read_uart(chip); - } - - if (status & OXYGEN_INT_AC97) - wake_up(&chip->ac97_waitqueue); - - return IRQ_HANDLED; -} - -static void oxygen_spdif_input_bits_changed(struct work_struct *work) -{ - struct oxygen *chip = container_of(work, struct oxygen, - spdif_input_bits_work); - u32 reg; - - /* - * This function gets called when there is new activity on the SPDIF - * input, or when we lose lock on the input signal, or when the rate - * changes. - */ - msleep(1); - spin_lock_irq(&chip->reg_lock); - reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | - OXYGEN_SPDIF_LOCK_STATUS)) - == OXYGEN_SPDIF_SENSE_STATUS) { - /* - * If we detect activity on the SPDIF input but cannot lock to - * a signal, the clock bit is likely to be wrong. - */ - reg ^= OXYGEN_SPDIF_IN_CLOCK_MASK; - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); - spin_unlock_irq(&chip->reg_lock); - msleep(1); - spin_lock_irq(&chip->reg_lock); - reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | - OXYGEN_SPDIF_LOCK_STATUS)) - == OXYGEN_SPDIF_SENSE_STATUS) { - /* nothing detected with either clock; give up */ - if ((reg & OXYGEN_SPDIF_IN_CLOCK_MASK) - == OXYGEN_SPDIF_IN_CLOCK_192) { - /* - * Reset clock to <= 96 kHz because this is - * more likely to be received next time. - */ - reg &= ~OXYGEN_SPDIF_IN_CLOCK_MASK; - reg |= OXYGEN_SPDIF_IN_CLOCK_96; - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); - } - } - } - spin_unlock_irq(&chip->reg_lock); - - if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) { - spin_lock_irq(&chip->reg_lock); - chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); - - /* - * We don't actually know that any channel status bits have - * changed, but let's send a notification just to be sure. - */ - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->controls[CONTROL_SPDIF_INPUT_BITS]->id); - } -} - -static void oxygen_gpio_changed(struct work_struct *work) -{ - struct oxygen *chip = container_of(work, struct oxygen, gpio_work); - - if (chip->model.gpio_changed) - chip->model.gpio_changed(chip); -} - -#ifdef CONFIG_PROC_FS -static void oxygen_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct oxygen *chip = entry->private_data; - int i, j; - - switch (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_PACKAGE_ID_MASK) { - case OXYGEN_PACKAGE_ID_8786: i = '6'; break; - case OXYGEN_PACKAGE_ID_8787: i = '7'; break; - case OXYGEN_PACKAGE_ID_8788: i = '8'; break; - default: i = '?'; break; - } - snd_iprintf(buffer, "CMI878%c:\n", i); - for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) { - snd_iprintf(buffer, "%02x:", i); - for (j = 0; j < 0x10; ++j) - snd_iprintf(buffer, " %02x", oxygen_read8(chip, i + j)); - snd_iprintf(buffer, "\n"); - } - if (mutex_lock_interruptible(&chip->mutex) < 0) - return; - if (chip->has_ac97_0) { - snd_iprintf(buffer, "\nAC97:\n"); - for (i = 0; i < 0x80; i += 0x10) { - snd_iprintf(buffer, "%02x:", i); - for (j = 0; j < 0x10; j += 2) - snd_iprintf(buffer, " %04x", - oxygen_read_ac97(chip, 0, i + j)); - snd_iprintf(buffer, "\n"); - } - } - if (chip->has_ac97_1) { - snd_iprintf(buffer, "\nAC97 2:\n"); - for (i = 0; i < 0x80; i += 0x10) { - snd_iprintf(buffer, "%02x:", i); - for (j = 0; j < 0x10; j += 2) - snd_iprintf(buffer, " %04x", - oxygen_read_ac97(chip, 1, i + j)); - snd_iprintf(buffer, "\n"); - } - } - mutex_unlock(&chip->mutex); - if (chip->model.dump_registers) - chip->model.dump_registers(chip, buffer); -} - -static void oxygen_proc_init(struct oxygen *chip) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(chip->card, "oxygen", &entry)) - snd_info_set_text_ops(entry, chip, oxygen_proc_read); -} -#else -#define oxygen_proc_init(chip) -#endif - -static const struct pci_device_id * -oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) -{ - u16 subdevice; - - /* - * Make sure the EEPROM pins are available, i.e., not used for SPI. - * (This function is called before we initialize or use SPI.) - */ - oxygen_clear_bits8(chip, OXYGEN_FUNCTION, - OXYGEN_FUNCTION_ENABLE_SPI_4_5); - /* - * Read the subsystem device ID directly from the EEPROM, because the - * chip didn't if the first EEPROM word was overwritten. - */ - subdevice = oxygen_read_eeprom(chip, 2); - /* use default ID if EEPROM is missing */ - if (subdevice == 0xffff && oxygen_read_eeprom(chip, 1) == 0xffff) - subdevice = 0x8788; - /* - * We use only the subsystem device ID for searching because it is - * unique even without the subsystem vendor ID, which may have been - * overwritten in the EEPROM. - */ - for (; ids->vendor; ++ids) - if (ids->subdevice == subdevice && - ids->driver_data != BROKEN_EEPROM_DRIVER_DATA) - return ids; - return NULL; -} - -static void oxygen_restore_eeprom(struct oxygen *chip, - const struct pci_device_id *id) -{ - u16 eeprom_id; - - eeprom_id = oxygen_read_eeprom(chip, 0); - if (eeprom_id != OXYGEN_EEPROM_ID && - (eeprom_id != 0xffff || id->subdevice != 0x8788)) { - /* - * This function gets called only when a known card model has - * been detected, i.e., we know there is a valid subsystem - * product ID at index 2 in the EEPROM. Therefore, we have - * been able to deduce the correct subsystem vendor ID, and - * this is enough information to restore the original EEPROM - * contents. - */ - oxygen_write_eeprom(chip, 1, id->subvendor); - oxygen_write_eeprom(chip, 0, OXYGEN_EEPROM_ID); - - oxygen_set_bits8(chip, OXYGEN_MISC, - OXYGEN_MISC_WRITE_PCI_SUBID); - pci_write_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, - id->subvendor); - pci_write_config_word(chip->pci, PCI_SUBSYSTEM_ID, - id->subdevice); - oxygen_clear_bits8(chip, OXYGEN_MISC, - OXYGEN_MISC_WRITE_PCI_SUBID); - - snd_printk(KERN_INFO "EEPROM ID restored\n"); - } -} - -static void configure_pcie_bridge(struct pci_dev *pci) -{ - enum { PEX811X, PI7C9X110 }; - static const struct pci_device_id bridge_ids[] = { - { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X }, - { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X }, - { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 }, - { } - }; - struct pci_dev *bridge; - const struct pci_device_id *id; - u32 tmp; - - if (!pci->bus || !pci->bus->self) - return; - bridge = pci->bus->self; - - id = pci_match_id(bridge_ids, bridge); - if (!id) - return; - - switch (id->driver_data) { - case PEX811X: /* PLX PEX8111/PEX8112 PCIe/PCI bridge */ - pci_read_config_dword(bridge, 0x48, &tmp); - tmp |= 1; /* enable blind prefetching */ - tmp |= 1 << 11; /* enable beacon generation */ - pci_write_config_dword(bridge, 0x48, tmp); - - pci_write_config_dword(bridge, 0x84, 0x0c); - pci_read_config_dword(bridge, 0x88, &tmp); - tmp &= ~(7 << 27); - tmp |= 2 << 27; /* set prefetch size to 128 bytes */ - pci_write_config_dword(bridge, 0x88, tmp); - break; - - case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */ - pci_read_config_dword(bridge, 0x40, &tmp); - tmp |= 1; /* park the PCI arbiter to the sound chip */ - pci_write_config_dword(bridge, 0x40, tmp); - break; - } -} - -static void oxygen_init(struct oxygen *chip) -{ - unsigned int i; - - chip->dac_routing = 1; - for (i = 0; i < 8; ++i) - chip->dac_volume[i] = chip->model.dac_volume_min; - chip->dac_mute = 1; - chip->spdif_playback_enable = 1; - chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL | - (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT); - chip->spdif_pcm_bits = chip->spdif_bits; - - if (!(oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2)) - oxygen_set_bits8(chip, OXYGEN_MISC, - OXYGEN_MISC_PCI_MEM_W_1_CLOCK); - - i = oxygen_read16(chip, OXYGEN_AC97_CONTROL); - chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0; - chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0; - - oxygen_write8_masked(chip, OXYGEN_FUNCTION, - OXYGEN_FUNCTION_RESET_CODEC | - chip->model.function_flags, - OXYGEN_FUNCTION_RESET_CODEC | - OXYGEN_FUNCTION_2WIRE_SPI_MASK | - OXYGEN_FUNCTION_ENABLE_SPI_4_5); - oxygen_write8(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0); - oxygen_write8(chip, OXYGEN_PLAY_CHANNELS, - OXYGEN_PLAY_CHANNELS_2 | - OXYGEN_DMA_A_BURST_8 | - OXYGEN_DMA_MULTICH_BURST_8); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - oxygen_write8_masked(chip, OXYGEN_MISC, - chip->model.misc_flags, - OXYGEN_MISC_WRITE_PCI_SUBID | - OXYGEN_MISC_REC_C_FROM_SPDIF | - OXYGEN_MISC_REC_B_FROM_AC97 | - OXYGEN_MISC_REC_A_FROM_MULTICH | - OXYGEN_MISC_MIDI); - oxygen_write8(chip, OXYGEN_REC_FORMAT, - (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) | - (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) | - (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_C_SHIFT)); - oxygen_write8(chip, OXYGEN_PLAY_FORMAT, - (OXYGEN_FORMAT_16 << OXYGEN_SPDIF_FORMAT_SHIFT) | - (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); - oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); - oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, - OXYGEN_RATE_48000 | - chip->model.dac_i2s_format | - OXYGEN_I2S_MCLK(chip->model.dac_mclks) | - OXYGEN_I2S_BITS_16 | - OXYGEN_I2S_MASTER | - OXYGEN_I2S_BCLK_64); - if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) - oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, - OXYGEN_RATE_48000 | - chip->model.adc_i2s_format | - OXYGEN_I2S_MCLK(chip->model.adc_mclks) | - OXYGEN_I2S_BITS_16 | - OXYGEN_I2S_MASTER | - OXYGEN_I2S_BCLK_64); - else - oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, - OXYGEN_I2S_MASTER | - OXYGEN_I2S_MUTE_MCLK); - if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 | - CAPTURE_2_FROM_I2S_2)) - oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, - OXYGEN_RATE_48000 | - chip->model.adc_i2s_format | - OXYGEN_I2S_MCLK(chip->model.adc_mclks) | - OXYGEN_I2S_BITS_16 | - OXYGEN_I2S_MASTER | - OXYGEN_I2S_BCLK_64); - else - oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, - OXYGEN_I2S_MASTER | - OXYGEN_I2S_MUTE_MCLK); - oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, - OXYGEN_I2S_MASTER | - OXYGEN_I2S_MUTE_MCLK); - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_OUT_ENABLE | - OXYGEN_SPDIF_LOOPBACK); - if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) - oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_SENSE_MASK | - OXYGEN_SPDIF_LOCK_MASK | - OXYGEN_SPDIF_RATE_MASK | - OXYGEN_SPDIF_LOCK_PAR | - OXYGEN_SPDIF_IN_CLOCK_96, - OXYGEN_SPDIF_SENSE_MASK | - OXYGEN_SPDIF_LOCK_MASK | - OXYGEN_SPDIF_RATE_MASK | - OXYGEN_SPDIF_SENSE_PAR | - OXYGEN_SPDIF_LOCK_PAR | - OXYGEN_SPDIF_IN_CLOCK_MASK); - else - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_SENSE_MASK | - OXYGEN_SPDIF_LOCK_MASK | - OXYGEN_SPDIF_RATE_MASK); - oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits); - oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, - OXYGEN_2WIRE_LENGTH_8 | - OXYGEN_2WIRE_INTERRUPT_MASK | - OXYGEN_2WIRE_SPEED_STANDARD); - oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK); - oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0); - oxygen_write16(chip, OXYGEN_GPIO_INTERRUPT_MASK, 0); - oxygen_write16(chip, OXYGEN_PLAY_ROUTING, - OXYGEN_PLAY_MULTICH_I2S_DAC | - OXYGEN_PLAY_SPDIF_SPDIF | - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT)); - oxygen_write8(chip, OXYGEN_REC_ROUTING, - OXYGEN_REC_A_ROUTE_I2S_ADC_1 | - OXYGEN_REC_B_ROUTE_I2S_ADC_2 | - OXYGEN_REC_C_ROUTE_SPDIF); - oxygen_write8(chip, OXYGEN_ADC_MONITOR, 0); - oxygen_write8(chip, OXYGEN_A_MONITOR_ROUTING, - (0 << OXYGEN_A_MONITOR_ROUTE_0_SHIFT) | - (1 << OXYGEN_A_MONITOR_ROUTE_1_SHIFT) | - (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) | - (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT)); - - if (chip->has_ac97_0 | chip->has_ac97_1) - oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, - OXYGEN_AC97_INT_READ_DONE | - OXYGEN_AC97_INT_WRITE_DONE); - else - oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0); - oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0); - oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0); - if (!(chip->has_ac97_0 | chip->has_ac97_1)) - oxygen_set_bits16(chip, OXYGEN_AC97_CONTROL, - OXYGEN_AC97_CLOCK_DISABLE); - if (!chip->has_ac97_0) { - oxygen_set_bits16(chip, OXYGEN_AC97_CONTROL, - OXYGEN_AC97_NO_CODEC_0); - } else { - oxygen_write_ac97(chip, 0, AC97_RESET, 0); - msleep(1); - oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_SETUP, - CM9780_GPIO0IO | CM9780_GPIO1IO); - oxygen_ac97_set_bits(chip, 0, CM9780_MIXER, - CM9780_BSTSEL | CM9780_STRO_MIC | - CM9780_MIX2FR | CM9780_PCBSW); - oxygen_ac97_set_bits(chip, 0, CM9780_JACK, - CM9780_RSOE | CM9780_CBOE | - CM9780_SSOE | CM9780_FROE | - CM9780_MIC2MIC | CM9780_LI2LI); - oxygen_write_ac97(chip, 0, AC97_MASTER, 0x0000); - oxygen_write_ac97(chip, 0, AC97_PC_BEEP, 0x8000); - oxygen_write_ac97(chip, 0, AC97_MIC, 0x8808); - oxygen_write_ac97(chip, 0, AC97_LINE, 0x0808); - oxygen_write_ac97(chip, 0, AC97_CD, 0x8808); - oxygen_write_ac97(chip, 0, AC97_VIDEO, 0x8808); - oxygen_write_ac97(chip, 0, AC97_AUX, 0x8808); - oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000); - oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080); - oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080); - oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, - CM9780_GPO0); - /* power down unused ADCs and DACs */ - oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN, - AC97_PD_PR0 | AC97_PD_PR1); - oxygen_ac97_set_bits(chip, 0, AC97_EXTENDED_STATUS, - AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK); - } - if (chip->has_ac97_1) { - oxygen_set_bits32(chip, OXYGEN_AC97_OUT_CONFIG, - OXYGEN_AC97_CODEC1_SLOT3 | - OXYGEN_AC97_CODEC1_SLOT4); - oxygen_write_ac97(chip, 1, AC97_RESET, 0); - msleep(1); - oxygen_write_ac97(chip, 1, AC97_MASTER, 0x0000); - oxygen_write_ac97(chip, 1, AC97_HEADPHONE, 0x8000); - oxygen_write_ac97(chip, 1, AC97_PC_BEEP, 0x8000); - oxygen_write_ac97(chip, 1, AC97_MIC, 0x8808); - oxygen_write_ac97(chip, 1, AC97_LINE, 0x8808); - oxygen_write_ac97(chip, 1, AC97_CD, 0x8808); - oxygen_write_ac97(chip, 1, AC97_VIDEO, 0x8808); - oxygen_write_ac97(chip, 1, AC97_AUX, 0x8808); - oxygen_write_ac97(chip, 1, AC97_PCM, 0x0808); - oxygen_write_ac97(chip, 1, AC97_REC_SEL, 0x0000); - oxygen_write_ac97(chip, 1, AC97_REC_GAIN, 0x0000); - oxygen_ac97_set_bits(chip, 1, 0x6a, 0x0040); - } -} - -static void oxygen_shutdown(struct oxygen *chip) -{ - spin_lock_irq(&chip->reg_lock); - chip->interrupt_mask = 0; - chip->pcm_running = 0; - oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - spin_unlock_irq(&chip->reg_lock); -} - -static void oxygen_card_free(struct snd_card *card) -{ - struct oxygen *chip = card->private_data; - - oxygen_shutdown(chip); - if (chip->irq >= 0) - free_irq(chip->irq, chip); - flush_work_sync(&chip->spdif_input_bits_work); - flush_work_sync(&chip->gpio_work); - chip->model.cleanup(chip); - kfree(chip->model_data); - mutex_destroy(&chip->mutex); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); -} - -int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, - struct module *owner, - const struct pci_device_id *ids, - int (*get_model)(struct oxygen *chip, - const struct pci_device_id *id - ) - ) -{ - struct snd_card *card; - struct oxygen *chip; - const struct pci_device_id *pci_id; - int err; - - err = snd_card_create(index, id, owner, sizeof(*chip), &card); - if (err < 0) - return err; - - chip = card->private_data; - chip->card = card; - chip->pci = pci; - chip->irq = -1; - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->mutex); - INIT_WORK(&chip->spdif_input_bits_work, - oxygen_spdif_input_bits_changed); - INIT_WORK(&chip->gpio_work, oxygen_gpio_changed); - init_waitqueue_head(&chip->ac97_waitqueue); - - err = pci_enable_device(pci); - if (err < 0) - goto err_card; - - err = pci_request_regions(pci, DRIVER); - if (err < 0) { - snd_printk(KERN_ERR "cannot reserve PCI resources\n"); - goto err_pci_enable; - } - - if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) || - pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) { - snd_printk(KERN_ERR "invalid PCI I/O range\n"); - err = -ENXIO; - goto err_pci_regions; - } - chip->addr = pci_resource_start(pci, 0); - - pci_id = oxygen_search_pci_id(chip, ids); - if (!pci_id) { - err = -ENODEV; - goto err_pci_regions; - } - oxygen_restore_eeprom(chip, pci_id); - err = get_model(chip, pci_id); - if (err < 0) - goto err_pci_regions; - - if (chip->model.model_data_size) { - chip->model_data = kzalloc(chip->model.model_data_size, - GFP_KERNEL); - if (!chip->model_data) { - err = -ENOMEM; - goto err_pci_regions; - } - } - - pci_set_master(pci); - snd_card_set_dev(card, &pci->dev); - card->private_free = oxygen_card_free; - - configure_pcie_bridge(pci); - oxygen_init(chip); - chip->model.init(chip); - - err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip); - if (err < 0) { - snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); - goto err_card; - } - chip->irq = pci->irq; - - strcpy(card->driver, chip->model.chip); - strcpy(card->shortname, chip->model.shortname); - sprintf(card->longname, "%s at %#lx, irq %i", - chip->model.longname, chip->addr, chip->irq); - strcpy(card->mixername, chip->model.chip); - snd_component_add(card, chip->model.chip); - - err = oxygen_pcm_init(chip); - if (err < 0) - goto err_card; - - err = oxygen_mixer_init(chip); - if (err < 0) - goto err_card; - - if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) { - unsigned int info_flags = - MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK; - if (chip->model.device_config & MIDI_OUTPUT) - info_flags |= MPU401_INFO_OUTPUT; - if (chip->model.device_config & MIDI_INPUT) - info_flags |= MPU401_INFO_INPUT; - err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, - chip->addr + OXYGEN_MPU401, - info_flags, -1, &chip->midi); - if (err < 0) - goto err_card; - } - - oxygen_proc_init(chip); - - spin_lock_irq(&chip->reg_lock); - if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) - chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; - if (chip->has_ac97_0 | chip->has_ac97_1) - chip->interrupt_mask |= OXYGEN_INT_AC97; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); - - err = snd_card_register(card); - if (err < 0) - goto err_card; - - pci_set_drvdata(pci, card); - return 0; - -err_pci_regions: - pci_release_regions(pci); -err_pci_enable: - pci_disable_device(pci); -err_card: - snd_card_free(card); - return err; -} -EXPORT_SYMBOL(oxygen_pci_probe); - -void oxygen_pci_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} -EXPORT_SYMBOL(oxygen_pci_remove); - -#ifdef CONFIG_PM -int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct oxygen *chip = card->private_data; - unsigned int i, saved_interrupt_mask; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - for (i = 0; i < PCM_COUNT; ++i) - if (chip->streams[i]) - snd_pcm_suspend(chip->streams[i]); - - if (chip->model.suspend) - chip->model.suspend(chip); - - spin_lock_irq(&chip->reg_lock); - saved_interrupt_mask = chip->interrupt_mask; - chip->interrupt_mask = 0; - oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - spin_unlock_irq(&chip->reg_lock); - - synchronize_irq(chip->irq); - flush_work_sync(&chip->spdif_input_bits_work); - flush_work_sync(&chip->gpio_work); - chip->interrupt_mask = saved_interrupt_mask; - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} -EXPORT_SYMBOL(oxygen_pci_suspend); - -static const u32 registers_to_restore[OXYGEN_IO_SIZE / 32] = { - 0xffffffff, 0x00ff077f, 0x00011d08, 0x007f00ff, - 0x00300000, 0x00000fe4, 0x0ff7001f, 0x00000000 -}; -static const u32 ac97_registers_to_restore[2][0x40 / 32] = { - { 0x18284fa2, 0x03060000 }, - { 0x00007fa6, 0x00200000 } -}; - -static inline int is_bit_set(const u32 *bitmap, unsigned int bit) -{ - return bitmap[bit / 32] & (1 << (bit & 31)); -} - -static void oxygen_restore_ac97(struct oxygen *chip, unsigned int codec) -{ - unsigned int i; - - oxygen_write_ac97(chip, codec, AC97_RESET, 0); - msleep(1); - for (i = 1; i < 0x40; ++i) - if (is_bit_set(ac97_registers_to_restore[codec], i)) - oxygen_write_ac97(chip, codec, i * 2, - chip->saved_ac97_registers[codec][i]); -} - -int oxygen_pci_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct oxygen *chip = card->private_data; - unsigned int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - snd_printk(KERN_ERR "cannot reenable device"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - for (i = 0; i < OXYGEN_IO_SIZE; ++i) - if (is_bit_set(registers_to_restore, i)) - oxygen_write8(chip, i, chip->saved_registers._8[i]); - if (chip->has_ac97_0) - oxygen_restore_ac97(chip, 0); - if (chip->has_ac97_1) - oxygen_restore_ac97(chip, 1); - - if (chip->model.resume) - chip->model.resume(chip); - - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -EXPORT_SYMBOL(oxygen_pci_resume); -#endif /* CONFIG_PM */ - -void oxygen_pci_shutdown(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct oxygen *chip = card->private_data; - - oxygen_shutdown(chip); - chip->model.cleanup(chip); -} -EXPORT_SYMBOL(oxygen_pci_shutdown); diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_mixer.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_mixer.c deleted file mode 100644 index c0dbb52d..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_mixer.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * C-Media CMI8788 driver - mixer code - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; 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 "oxygen.h" -#include "cm9780.h" - -static int dac_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - struct oxygen *chip = ctl->private_data; - - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = chip->model.dac_channels_mixer; - info->value.integer.min = chip->model.dac_volume_min; - info->value.integer.max = chip->model.dac_volume_max; - return 0; -} - -static int dac_volume_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int i; - - mutex_lock(&chip->mutex); - for (i = 0; i < chip->model.dac_channels_mixer; ++i) - value->value.integer.value[i] = chip->dac_volume[i]; - mutex_unlock(&chip->mutex); - return 0; -} - -static int dac_volume_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int i; - int changed; - - changed = 0; - mutex_lock(&chip->mutex); - for (i = 0; i < chip->model.dac_channels_mixer; ++i) - if (value->value.integer.value[i] != chip->dac_volume[i]) { - chip->dac_volume[i] = value->value.integer.value[i]; - changed = 1; - } - if (changed) - chip->model.update_dac_volume(chip); - mutex_unlock(&chip->mutex); - return changed; -} - -static int dac_mute_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = !chip->dac_mute; - mutex_unlock(&chip->mutex); - return 0; -} - -static int dac_mute_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - int changed; - - mutex_lock(&chip->mutex); - changed = !value->value.integer.value[0] != chip->dac_mute; - if (changed) { - chip->dac_mute = !value->value.integer.value[0]; - chip->model.update_dac_mute(chip); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static unsigned int upmix_item_count(struct oxygen *chip) -{ - if (chip->model.dac_channels_pcm < 8) - return 2; - else if (chip->model.update_center_lfe_mix) - return 5; - else - return 3; -} - -static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - static const char *const names[5] = { - "Front", - "Front+Surround", - "Front+Surround+Back", - "Front+Surround+Center/LFE", - "Front+Surround+Center/LFE+Back", - }; - struct oxygen *chip = ctl->private_data; - unsigned int count = upmix_item_count(chip); - - return snd_ctl_enum_info(info, 1, count, names); -} - -static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - value->value.enumerated.item[0] = chip->dac_routing; - mutex_unlock(&chip->mutex); - return 0; -} - -void oxygen_update_dac_routing(struct oxygen *chip) -{ - /* DAC 0: front, DAC 1: surround, DAC 2: center/LFE, DAC 3: back */ - static const unsigned int reg_values[5] = { - /* stereo -> front */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - /* stereo -> front+surround */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - /* stereo -> front+surround+back */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - /* stereo -> front+surround+center/LFE */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - /* stereo -> front+surround+center/LFE+back */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - }; - u8 channels; - unsigned int reg_value; - - channels = oxygen_read8(chip, OXYGEN_PLAY_CHANNELS) & - OXYGEN_PLAY_CHANNELS_MASK; - if (channels == OXYGEN_PLAY_CHANNELS_2) - reg_value = reg_values[chip->dac_routing]; - else if (channels == OXYGEN_PLAY_CHANNELS_8) - /* in 7.1 mode, "rear" channels go to the "back" jack */ - reg_value = (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (1 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); - else - reg_value = (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); - if (chip->model.adjust_dac_routing) - reg_value = chip->model.adjust_dac_routing(chip, reg_value); - oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value, - OXYGEN_PLAY_DAC0_SOURCE_MASK | - OXYGEN_PLAY_DAC1_SOURCE_MASK | - OXYGEN_PLAY_DAC2_SOURCE_MASK | - OXYGEN_PLAY_DAC3_SOURCE_MASK); - if (chip->model.update_center_lfe_mix) - chip->model.update_center_lfe_mix(chip, chip->dac_routing > 2); -} - -static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int count = upmix_item_count(chip); - int changed; - - if (value->value.enumerated.item[0] >= count) - return -EINVAL; - mutex_lock(&chip->mutex); - changed = value->value.enumerated.item[0] != chip->dac_routing; - if (changed) { - chip->dac_routing = value->value.enumerated.item[0]; - oxygen_update_dac_routing(chip); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int spdif_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = chip->spdif_playback_enable; - mutex_unlock(&chip->mutex); - return 0; -} - -static unsigned int oxygen_spdif_rate(unsigned int oxygen_rate) -{ - switch (oxygen_rate) { - case OXYGEN_RATE_32000: - return IEC958_AES3_CON_FS_32000 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_44100: - return IEC958_AES3_CON_FS_44100 << OXYGEN_SPDIF_CS_RATE_SHIFT; - default: /* OXYGEN_RATE_48000 */ - return IEC958_AES3_CON_FS_48000 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_64000: - return 0xb << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_88200: - return IEC958_AES3_CON_FS_88200 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_96000: - return IEC958_AES3_CON_FS_96000 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_176400: - return IEC958_AES3_CON_FS_176400 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_192000: - return IEC958_AES3_CON_FS_192000 << OXYGEN_SPDIF_CS_RATE_SHIFT; - } -} - -void oxygen_update_spdif_source(struct oxygen *chip) -{ - u32 old_control, new_control; - u16 old_routing, new_routing; - unsigned int oxygen_rate; - - old_control = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - old_routing = oxygen_read16(chip, OXYGEN_PLAY_ROUTING); - if (chip->pcm_active & (1 << PCM_SPDIF)) { - new_control = old_control | OXYGEN_SPDIF_OUT_ENABLE; - new_routing = (old_routing & ~OXYGEN_PLAY_SPDIF_MASK) - | OXYGEN_PLAY_SPDIF_SPDIF; - oxygen_rate = (old_control >> OXYGEN_SPDIF_OUT_RATE_SHIFT) - & OXYGEN_I2S_RATE_MASK; - /* S/PDIF rate was already set by the caller */ - } else if ((chip->pcm_active & (1 << PCM_MULTICH)) && - chip->spdif_playback_enable) { - new_routing = (old_routing & ~OXYGEN_PLAY_SPDIF_MASK) - | OXYGEN_PLAY_SPDIF_MULTICH_01; - oxygen_rate = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT) - & OXYGEN_I2S_RATE_MASK; - new_control = (old_control & ~OXYGEN_SPDIF_OUT_RATE_MASK) | - (oxygen_rate << OXYGEN_SPDIF_OUT_RATE_SHIFT) | - OXYGEN_SPDIF_OUT_ENABLE; - } else { - new_control = old_control & ~OXYGEN_SPDIF_OUT_ENABLE; - new_routing = old_routing; - oxygen_rate = OXYGEN_RATE_44100; - } - if (old_routing != new_routing) { - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, - new_control & ~OXYGEN_SPDIF_OUT_ENABLE); - oxygen_write16(chip, OXYGEN_PLAY_ROUTING, new_routing); - } - if (new_control & OXYGEN_SPDIF_OUT_ENABLE) - oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, - oxygen_spdif_rate(oxygen_rate) | - ((chip->pcm_active & (1 << PCM_SPDIF)) ? - chip->spdif_pcm_bits : chip->spdif_bits)); - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, new_control); -} - -static int spdif_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - int changed; - - mutex_lock(&chip->mutex); - changed = value->value.integer.value[0] != chip->spdif_playback_enable; - if (changed) { - chip->spdif_playback_enable = !!value->value.integer.value[0]; - spin_lock_irq(&chip->reg_lock); - oxygen_update_spdif_source(chip); - spin_unlock_irq(&chip->reg_lock); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int spdif_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_IEC958; - info->count = 1; - return 0; -} - -static void oxygen_to_iec958(u32 bits, struct snd_ctl_elem_value *value) -{ - value->value.iec958.status[0] = - bits & (OXYGEN_SPDIF_NONAUDIO | OXYGEN_SPDIF_C | - OXYGEN_SPDIF_PREEMPHASIS); - value->value.iec958.status[1] = /* category and original */ - bits >> OXYGEN_SPDIF_CATEGORY_SHIFT; -} - -static u32 iec958_to_oxygen(struct snd_ctl_elem_value *value) -{ - u32 bits; - - bits = value->value.iec958.status[0] & - (OXYGEN_SPDIF_NONAUDIO | OXYGEN_SPDIF_C | - OXYGEN_SPDIF_PREEMPHASIS); - bits |= value->value.iec958.status[1] << OXYGEN_SPDIF_CATEGORY_SHIFT; - if (bits & OXYGEN_SPDIF_NONAUDIO) - bits |= OXYGEN_SPDIF_V; - return bits; -} - -static inline void write_spdif_bits(struct oxygen *chip, u32 bits) -{ - oxygen_write32_masked(chip, OXYGEN_SPDIF_OUTPUT_BITS, bits, - OXYGEN_SPDIF_NONAUDIO | - OXYGEN_SPDIF_C | - OXYGEN_SPDIF_PREEMPHASIS | - OXYGEN_SPDIF_CATEGORY_MASK | - OXYGEN_SPDIF_ORIGINAL | - OXYGEN_SPDIF_V); -} - -static int spdif_default_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - oxygen_to_iec958(chip->spdif_bits, value); - mutex_unlock(&chip->mutex); - return 0; -} - -static int spdif_default_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 new_bits; - int changed; - - new_bits = iec958_to_oxygen(value); - mutex_lock(&chip->mutex); - changed = new_bits != chip->spdif_bits; - if (changed) { - chip->spdif_bits = new_bits; - if (!(chip->pcm_active & (1 << PCM_SPDIF))) - write_spdif_bits(chip, new_bits); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int spdif_mask_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - value->value.iec958.status[0] = IEC958_AES0_NONAUDIO | - IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS; - value->value.iec958.status[1] = - IEC958_AES1_CON_CATEGORY | IEC958_AES1_CON_ORIGINAL; - return 0; -} - -static int spdif_pcm_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - oxygen_to_iec958(chip->spdif_pcm_bits, value); - mutex_unlock(&chip->mutex); - return 0; -} - -static int spdif_pcm_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 new_bits; - int changed; - - new_bits = iec958_to_oxygen(value); - mutex_lock(&chip->mutex); - changed = new_bits != chip->spdif_pcm_bits; - if (changed) { - chip->spdif_pcm_bits = new_bits; - if (chip->pcm_active & (1 << PCM_SPDIF)) - write_spdif_bits(chip, new_bits); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int spdif_input_mask_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - value->value.iec958.status[0] = 0xff; - value->value.iec958.status[1] = 0xff; - value->value.iec958.status[2] = 0xff; - value->value.iec958.status[3] = 0xff; - return 0; -} - -static int spdif_input_default_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 bits; - - bits = oxygen_read32(chip, OXYGEN_SPDIF_INPUT_BITS); - value->value.iec958.status[0] = bits; - value->value.iec958.status[1] = bits >> 8; - value->value.iec958.status[2] = bits >> 16; - value->value.iec958.status[3] = bits >> 24; - return 0; -} - -static int spdif_bit_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 bit = ctl->private_value; - - value->value.integer.value[0] = - !!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) & bit); - return 0; -} - -static int spdif_bit_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 bit = ctl->private_value; - u32 oldreg, newreg; - int changed; - - spin_lock_irq(&chip->reg_lock); - oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if (value->value.integer.value[0]) - newreg = oldreg | bit; - else - newreg = oldreg & ~bit; - changed = newreg != oldreg; - if (changed) - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg); - spin_unlock_irq(&chip->reg_lock); - return changed; -} - -static int monitor_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; - info->value.integer.min = 0; - info->value.integer.max = 1; - return 0; -} - -static int monitor_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u8 bit = ctl->private_value; - int invert = ctl->private_value & (1 << 8); - - value->value.integer.value[0] = - !!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit); - return 0; -} - -static int monitor_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u8 bit = ctl->private_value; - int invert = ctl->private_value & (1 << 8); - u8 oldreg, newreg; - int changed; - - spin_lock_irq(&chip->reg_lock); - oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR); - if ((!!value->value.integer.value[0] ^ !!invert) != 0) - newreg = oldreg | bit; - else - newreg = oldreg & ~bit; - changed = newreg != oldreg; - if (changed) - oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg); - spin_unlock_irq(&chip->reg_lock); - return changed; -} - -static int ac97_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int codec = (ctl->private_value >> 24) & 1; - unsigned int index = ctl->private_value & 0xff; - unsigned int bitnr = (ctl->private_value >> 8) & 0xff; - int invert = ctl->private_value & (1 << 16); - u16 reg; - - mutex_lock(&chip->mutex); - reg = oxygen_read_ac97(chip, codec, index); - mutex_unlock(&chip->mutex); - if (!(reg & (1 << bitnr)) ^ !invert) - value->value.integer.value[0] = 1; - else - value->value.integer.value[0] = 0; - return 0; -} - -static void mute_ac97_ctl(struct oxygen *chip, unsigned int control) -{ - unsigned int priv_idx; - u16 value; - - if (!chip->controls[control]) - return; - priv_idx = chip->controls[control]->private_value & 0xff; - value = oxygen_read_ac97(chip, 0, priv_idx); - if (!(value & 0x8000)) { - oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000); - if (chip->model.ac97_switch) - chip->model.ac97_switch(chip, priv_idx, 0x8000); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->controls[control]->id); - } -} - -static int ac97_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int codec = (ctl->private_value >> 24) & 1; - unsigned int index = ctl->private_value & 0xff; - unsigned int bitnr = (ctl->private_value >> 8) & 0xff; - int invert = ctl->private_value & (1 << 16); - u16 oldreg, newreg; - int change; - - mutex_lock(&chip->mutex); - oldreg = oxygen_read_ac97(chip, codec, index); - newreg = oldreg; - if (!value->value.integer.value[0] ^ !invert) - newreg |= 1 << bitnr; - else - newreg &= ~(1 << bitnr); - change = newreg != oldreg; - if (change) { - oxygen_write_ac97(chip, codec, index, newreg); - if (codec == 0 && chip->model.ac97_switch) - chip->model.ac97_switch(chip, index, newreg & 0x8000); - if (index == AC97_LINE) { - oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS, - newreg & 0x8000 ? - CM9780_GPO0 : 0, CM9780_GPO0); - if (!(newreg & 0x8000)) { - mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH); - mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH); - mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH); - } - } else if ((index == AC97_MIC || index == AC97_CD || - index == AC97_VIDEO || index == AC97_AUX) && - bitnr == 15 && !(newreg & 0x8000)) { - mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH); - oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS, - CM9780_GPO0, CM9780_GPO0); - } - } - mutex_unlock(&chip->mutex); - return change; -} - -static int ac97_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - int stereo = (ctl->private_value >> 16) & 1; - - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = stereo ? 2 : 1; - info->value.integer.min = 0; - info->value.integer.max = 0x1f; - return 0; -} - -static int ac97_volume_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int codec = (ctl->private_value >> 24) & 1; - int stereo = (ctl->private_value >> 16) & 1; - unsigned int index = ctl->private_value & 0xff; - u16 reg; - - mutex_lock(&chip->mutex); - reg = oxygen_read_ac97(chip, codec, index); - mutex_unlock(&chip->mutex); - if (!stereo) { - value->value.integer.value[0] = 31 - (reg & 0x1f); - } else { - value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f); - value->value.integer.value[1] = 31 - (reg & 0x1f); - } - return 0; -} - -static int ac97_volume_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int codec = (ctl->private_value >> 24) & 1; - int stereo = (ctl->private_value >> 16) & 1; - unsigned int index = ctl->private_value & 0xff; - u16 oldreg, newreg; - int change; - - mutex_lock(&chip->mutex); - oldreg = oxygen_read_ac97(chip, codec, index); - if (!stereo) { - newreg = oldreg & ~0x1f; - newreg |= 31 - (value->value.integer.value[0] & 0x1f); - } else { - newreg = oldreg & ~0x1f1f; - newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8; - newreg |= 31 - (value->value.integer.value[1] & 0x1f); - } - change = newreg != oldreg; - if (change) - oxygen_write_ac97(chip, codec, index, newreg); - mutex_unlock(&chip->mutex); - return change; -} - -static int mic_fmic_source_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[] = { "Mic Jack", "Front Panel" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int mic_fmic_source_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - value->value.enumerated.item[0] = - !!(oxygen_read_ac97(chip, 0, CM9780_JACK) & CM9780_FMIC2MIC); - mutex_unlock(&chip->mutex); - return 0; -} - -static int mic_fmic_source_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 oldreg, newreg; - int change; - - mutex_lock(&chip->mutex); - oldreg = oxygen_read_ac97(chip, 0, CM9780_JACK); - if (value->value.enumerated.item[0]) - newreg = oldreg | CM9780_FMIC2MIC; - else - newreg = oldreg & ~CM9780_FMIC2MIC; - change = newreg != oldreg; - if (change) - oxygen_write_ac97(chip, 0, CM9780_JACK, newreg); - mutex_unlock(&chip->mutex); - return change; -} - -static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0; - info->value.integer.max = 7; - return 0; -} - -static int ac97_fp_rec_volume_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 reg; - - mutex_lock(&chip->mutex); - reg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN); - mutex_unlock(&chip->mutex); - value->value.integer.value[0] = reg & 7; - value->value.integer.value[1] = (reg >> 8) & 7; - return 0; -} - -static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 oldreg, newreg; - int change; - - mutex_lock(&chip->mutex); - oldreg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN); - newreg = oldreg & ~0x0707; - newreg = newreg | (value->value.integer.value[0] & 7); - newreg = newreg | ((value->value.integer.value[0] & 7) << 8); - change = newreg != oldreg; - if (change) - oxygen_write_ac97(chip, 1, AC97_REC_GAIN, newreg); - mutex_unlock(&chip->mutex); - return change; -} - -#define AC97_SWITCH(xname, codec, index, bitnr, invert) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .info = snd_ctl_boolean_mono_info, \ - .get = ac97_switch_get, \ - .put = ac97_switch_put, \ - .private_value = ((codec) << 24) | ((invert) << 16) | \ - ((bitnr) << 8) | (index), \ - } -#define AC97_VOLUME(xname, codec, index, stereo) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = ac97_volume_info, \ - .get = ac97_volume_get, \ - .put = ac97_volume_put, \ - .tlv = { .p = ac97_db_scale, }, \ - .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \ - } - -static DECLARE_TLV_DB_SCALE(monitor_db_scale, -600, 600, 0); -static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); -static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); - -static const struct snd_kcontrol_new controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = dac_volume_info, - .get = dac_volume_get, - .put = dac_volume_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = dac_mute_get, - .put = dac_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Stereo Upmixing", - .info = upmix_info, - .get = upmix_get, - .put = upmix_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), - .info = snd_ctl_boolean_mono_info, - .get = spdif_switch_get, - .put = spdif_switch_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = spdif_info, - .get = spdif_default_get, - .put = spdif_default_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = spdif_info, - .get = spdif_mask_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .info = spdif_info, - .get = spdif_pcm_get, - .put = spdif_pcm_put, - }, -}; - -static const struct snd_kcontrol_new spdif_input_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = spdif_info, - .get = spdif_input_mask_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = spdif_info, - .get = spdif_input_default_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Loopback ", NONE, SWITCH), - .info = snd_ctl_boolean_mono_info, - .get = spdif_bit_switch_get, - .put = spdif_bit_switch_put, - .private_value = OXYGEN_SPDIF_LOOPBACK, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Validity Check ",CAPTURE,SWITCH), - .info = snd_ctl_boolean_mono_info, - .get = spdif_bit_switch_get, - .put = spdif_bit_switch_put, - .private_value = OXYGEN_SPDIF_SPDVALID, - }, -}; - -static const struct { - unsigned int pcm_dev; - struct snd_kcontrol_new controls[2]; -} monitor_controls[] = { - { - .pcm_dev = CAPTURE_0_FROM_I2S_1, - .controls = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_A, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = monitor_volume_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL - | (1 << 8), - .tlv = { .p = monitor_db_scale, }, - }, - }, - }, - { - .pcm_dev = CAPTURE_0_FROM_I2S_2, - .controls = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_B, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = monitor_volume_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL - | (1 << 8), - .tlv = { .p = monitor_db_scale, }, - }, - }, - }, - { - .pcm_dev = CAPTURE_2_FROM_I2S_2, - .controls = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Switch", - .index = 1, - .info = snd_ctl_boolean_mono_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_B, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Volume", - .index = 1, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = monitor_volume_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL - | (1 << 8), - .tlv = { .p = monitor_db_scale, }, - }, - }, - }, - { - .pcm_dev = CAPTURE_1_FROM_SPDIF, - .controls = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Input Monitor Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_C, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Input Monitor Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = monitor_volume_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL - | (1 << 8), - .tlv = { .p = monitor_db_scale, }, - }, - }, - }, -}; - -static const struct snd_kcontrol_new ac97_controls[] = { - AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0), - AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), - AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Source Capture Enum", - .info = mic_fmic_source_info, - .get = mic_fmic_source_get, - .put = mic_fmic_source_put, - }, - AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), - AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1), - AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), - AC97_VOLUME("Aux Capture Volume", 0, AC97_AUX, 1), - AC97_SWITCH("Aux Capture Switch", 0, AC97_AUX, 15, 1), -}; - -static const struct snd_kcontrol_new ac97_fp_controls[] = { - AC97_VOLUME("Front Panel Playback Volume", 1, AC97_HEADPHONE, 1), - AC97_SWITCH("Front Panel Playback Switch", 1, AC97_HEADPHONE, 15, 1), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Front Panel Capture Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = ac97_fp_rec_volume_info, - .get = ac97_fp_rec_volume_get, - .put = ac97_fp_rec_volume_put, - .tlv = { .p = ac97_rec_db_scale, }, - }, - AC97_SWITCH("Front Panel Capture Switch", 1, AC97_REC_GAIN, 15, 1), -}; - -static void oxygen_any_ctl_free(struct snd_kcontrol *ctl) -{ - struct oxygen *chip = ctl->private_data; - unsigned int i; - - /* I'm too lazy to write a function for each control :-) */ - for (i = 0; i < ARRAY_SIZE(chip->controls); ++i) - chip->controls[i] = NULL; -} - -static int add_controls(struct oxygen *chip, - const struct snd_kcontrol_new controls[], - unsigned int count) -{ - static const char *const known_ctl_names[CONTROL_COUNT] = { - [CONTROL_SPDIF_PCM] = - SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), - [CONTROL_SPDIF_INPUT_BITS] = - SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), - [CONTROL_MIC_CAPTURE_SWITCH] = "Mic Capture Switch", - [CONTROL_LINE_CAPTURE_SWITCH] = "Line Capture Switch", - [CONTROL_CD_CAPTURE_SWITCH] = "CD Capture Switch", - [CONTROL_AUX_CAPTURE_SWITCH] = "Aux Capture Switch", - }; - unsigned int i, j; - struct snd_kcontrol_new template; - struct snd_kcontrol *ctl; - int err; - - for (i = 0; i < count; ++i) { - template = controls[i]; - if (chip->model.control_filter) { - err = chip->model.control_filter(&template); - if (err < 0) - return err; - if (err == 1) - continue; - } - if (!strcmp(template.name, "Stereo Upmixing") && - chip->model.dac_channels_pcm == 2) - continue; - if (!strcmp(template.name, "Mic Source Capture Enum") && - !(chip->model.device_config & AC97_FMIC_SWITCH)) - continue; - if (!strncmp(template.name, "CD Capture ", 11) && - !(chip->model.device_config & AC97_CD_INPUT)) - continue; - if (!strcmp(template.name, "Master Playback Volume") && - chip->model.dac_tlv) { - template.tlv.p = chip->model.dac_tlv; - template.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - } - ctl = snd_ctl_new1(&template, chip); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(chip->card, ctl); - if (err < 0) - return err; - for (j = 0; j < CONTROL_COUNT; ++j) - if (!strcmp(ctl->id.name, known_ctl_names[j])) { - chip->controls[j] = ctl; - ctl->private_free = oxygen_any_ctl_free; - } - } - return 0; -} - -int oxygen_mixer_init(struct oxygen *chip) -{ - unsigned int i; - int err; - - err = add_controls(chip, controls, ARRAY_SIZE(controls)); - if (err < 0) - return err; - if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) { - err = add_controls(chip, spdif_input_controls, - ARRAY_SIZE(spdif_input_controls)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) { - if (!(chip->model.device_config & monitor_controls[i].pcm_dev)) - continue; - err = add_controls(chip, monitor_controls[i].controls, - ARRAY_SIZE(monitor_controls[i].controls)); - if (err < 0) - return err; - } - if (chip->has_ac97_0) { - err = add_controls(chip, ac97_controls, - ARRAY_SIZE(ac97_controls)); - if (err < 0) - return err; - } - if (chip->has_ac97_1) { - err = add_controls(chip, ac97_fp_controls, - ARRAY_SIZE(ac97_fp_controls)); - if (err < 0) - return err; - } - return chip->model.mixer_init ? chip->model.mixer_init(chip) : 0; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_pcm.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_pcm.c deleted file mode 100644 index cc0bcd9f..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_pcm.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * C-Media CMI8788 driver - PCM code - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; 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 "oxygen.h" - -/* most DMA channels have a 16-bit counter for 32-bit words */ -#define BUFFER_BYTES_MAX ((1 << 16) * 4) -/* the multichannel DMA channel has a 24-bit counter */ -#define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4) - -#define PERIOD_BYTES_MIN 64 - -#define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2) -#define DEFAULT_BUFFER_BYTES_MULTICH (1024 * 1024) - -static const struct snd_pcm_hardware oxygen_stereo_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .rate_min = 32000, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = BUFFER_BYTES_MAX, - .period_bytes_min = PERIOD_BYTES_MIN, - .period_bytes_max = BUFFER_BYTES_MAX, - .periods_min = 1, - .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, -}; -static const struct snd_pcm_hardware oxygen_multichannel_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .rate_min = 32000, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 8, - .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH, - .period_bytes_min = PERIOD_BYTES_MIN, - .period_bytes_max = BUFFER_BYTES_MAX_MULTICH, - .periods_min = 1, - .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, -}; -static const struct snd_pcm_hardware oxygen_ac97_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = BUFFER_BYTES_MAX, - .period_bytes_min = PERIOD_BYTES_MIN, - .period_bytes_max = BUFFER_BYTES_MAX, - .periods_min = 1, - .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, -}; - -static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = { - [PCM_A] = &oxygen_stereo_hardware, - [PCM_B] = &oxygen_stereo_hardware, - [PCM_C] = &oxygen_stereo_hardware, - [PCM_SPDIF] = &oxygen_stereo_hardware, - [PCM_MULTICH] = &oxygen_multichannel_hardware, - [PCM_AC97] = &oxygen_ac97_hardware, -}; - -static inline unsigned int -oxygen_substream_channel(struct snd_pcm_substream *substream) -{ - return (unsigned int)(uintptr_t)substream->runtime->private_data; -} - -static int oxygen_open(struct snd_pcm_substream *substream, - unsigned int channel) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - runtime->private_data = (void *)(uintptr_t)channel; - if (channel == PCM_B && chip->has_ac97_1 && - (chip->model.device_config & CAPTURE_2_FROM_AC97_1)) - runtime->hw = oxygen_ac97_hardware; - else - runtime->hw = *oxygen_hardware[channel]; - switch (channel) { - case PCM_C: - runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_64000); - runtime->hw.rate_min = 44100; - break; - case PCM_MULTICH: - runtime->hw.channels_max = chip->model.dac_channels_pcm; - break; - } - if (chip->model.pcm_hardware_filter) - chip->model.pcm_hardware_filter(channel, &runtime->hw); - err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); - if (err < 0) - return err; - err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); - if (err < 0) - return err; - if (runtime->hw.formats & SNDRV_PCM_FMTBIT_S32_LE) { - err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - if (err < 0) - return err; - } - if (runtime->hw.channels_max > 2) { - err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - 2); - if (err < 0) - return err; - } - snd_pcm_set_sync(substream); - chip->streams[channel] = substream; - - mutex_lock(&chip->mutex); - chip->pcm_active |= 1 << channel; - if (channel == PCM_SPDIF) { - chip->spdif_pcm_bits = chip->spdif_bits; - chip->controls[CONTROL_SPDIF_PCM]->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - &chip->controls[CONTROL_SPDIF_PCM]->id); - } - mutex_unlock(&chip->mutex); - - return 0; -} - -static int oxygen_rec_a_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_A); -} - -static int oxygen_rec_b_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_B); -} - -static int oxygen_rec_c_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_C); -} - -static int oxygen_spdif_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_SPDIF); -} - -static int oxygen_multich_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_MULTICH); -} - -static int oxygen_ac97_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_AC97); -} - -static int oxygen_close(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - unsigned int channel = oxygen_substream_channel(substream); - - mutex_lock(&chip->mutex); - chip->pcm_active &= ~(1 << channel); - if (channel == PCM_SPDIF) { - chip->controls[CONTROL_SPDIF_PCM]->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - &chip->controls[CONTROL_SPDIF_PCM]->id); - } - if (channel == PCM_SPDIF || channel == PCM_MULTICH) - oxygen_update_spdif_source(chip); - mutex_unlock(&chip->mutex); - - chip->streams[channel] = NULL; - return 0; -} - -static unsigned int oxygen_format(struct snd_pcm_hw_params *hw_params) -{ - if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE) - return OXYGEN_FORMAT_24; - else - return OXYGEN_FORMAT_16; -} - -static unsigned int oxygen_rate(struct snd_pcm_hw_params *hw_params) -{ - switch (params_rate(hw_params)) { - case 32000: - return OXYGEN_RATE_32000; - case 44100: - return OXYGEN_RATE_44100; - default: /* 48000 */ - return OXYGEN_RATE_48000; - case 64000: - return OXYGEN_RATE_64000; - case 88200: - return OXYGEN_RATE_88200; - case 96000: - return OXYGEN_RATE_96000; - case 176400: - return OXYGEN_RATE_176400; - case 192000: - return OXYGEN_RATE_192000; - } -} - -static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params) -{ - if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE) - return OXYGEN_I2S_BITS_24; - else - return OXYGEN_I2S_BITS_16; -} - -static unsigned int oxygen_play_channels(struct snd_pcm_hw_params *hw_params) -{ - switch (params_channels(hw_params)) { - default: /* 2 */ - return OXYGEN_PLAY_CHANNELS_2; - case 4: - return OXYGEN_PLAY_CHANNELS_4; - case 6: - return OXYGEN_PLAY_CHANNELS_6; - case 8: - return OXYGEN_PLAY_CHANNELS_8; - } -} - -static const unsigned int channel_base_registers[PCM_COUNT] = { - [PCM_A] = OXYGEN_DMA_A_ADDRESS, - [PCM_B] = OXYGEN_DMA_B_ADDRESS, - [PCM_C] = OXYGEN_DMA_C_ADDRESS, - [PCM_SPDIF] = OXYGEN_DMA_SPDIF_ADDRESS, - [PCM_MULTICH] = OXYGEN_DMA_MULTICH_ADDRESS, - [PCM_AC97] = OXYGEN_DMA_AC97_ADDRESS, -}; - -static int oxygen_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - unsigned int channel = oxygen_substream_channel(substream); - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - oxygen_write32(chip, channel_base_registers[channel], - (u32)substream->runtime->dma_addr); - if (channel == PCM_MULTICH) { - oxygen_write32(chip, OXYGEN_DMA_MULTICH_COUNT, - params_buffer_bytes(hw_params) / 4 - 1); - oxygen_write32(chip, OXYGEN_DMA_MULTICH_TCOUNT, - params_period_bytes(hw_params) / 4 - 1); - } else { - oxygen_write16(chip, channel_base_registers[channel] + 4, - params_buffer_bytes(hw_params) / 4 - 1); - oxygen_write16(chip, channel_base_registers[channel] + 6, - params_period_bytes(hw_params) / 4 - 1); - } - return 0; -} - -static u16 get_mclk(struct oxygen *chip, unsigned int channel, - struct snd_pcm_hw_params *params) -{ - unsigned int mclks, shift; - - if (channel == PCM_MULTICH) - mclks = chip->model.dac_mclks; - else - mclks = chip->model.adc_mclks; - - if (params_rate(params) <= 48000) - shift = 0; - else if (params_rate(params) <= 96000) - shift = 2; - else - shift = 4; - - return OXYGEN_I2S_MCLK(mclks >> shift); -} - -static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_A_SHIFT, - OXYGEN_REC_FORMAT_A_MASK); - oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, - oxygen_rate(hw_params) | - chip->model.adc_i2s_format | - get_mclk(chip, PCM_A, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - spin_unlock_irq(&chip->reg_lock); - - mutex_lock(&chip->mutex); - chip->model.set_adc_params(chip, hw_params); - mutex_unlock(&chip->mutex); - return 0; -} - -static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int is_ac97; - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - is_ac97 = chip->has_ac97_1 && - (chip->model.device_config & CAPTURE_2_FROM_AC97_1); - - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_B_SHIFT, - OXYGEN_REC_FORMAT_B_MASK); - if (!is_ac97) - oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, - oxygen_rate(hw_params) | - chip->model.adc_i2s_format | - get_mclk(chip, PCM_B, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - spin_unlock_irq(&chip->reg_lock); - - if (!is_ac97) { - mutex_lock(&chip->mutex); - chip->model.set_adc_params(chip, hw_params); - mutex_unlock(&chip->mutex); - } - return 0; -} - -static int oxygen_rec_c_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT, - OXYGEN_REC_FORMAT_C_MASK); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - mutex_lock(&chip->mutex); - spin_lock_irq(&chip->reg_lock); - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_OUT_ENABLE); - oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, - oxygen_format(hw_params) << OXYGEN_SPDIF_FORMAT_SHIFT, - OXYGEN_SPDIF_FORMAT_MASK); - oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, - oxygen_rate(hw_params) << OXYGEN_SPDIF_OUT_RATE_SHIFT, - OXYGEN_SPDIF_OUT_RATE_MASK); - oxygen_update_spdif_source(chip); - spin_unlock_irq(&chip->reg_lock); - mutex_unlock(&chip->mutex); - return 0; -} - -static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - mutex_lock(&chip->mutex); - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, - oxygen_play_channels(hw_params), - OXYGEN_PLAY_CHANNELS_MASK); - oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, - oxygen_format(hw_params) << OXYGEN_MULTICH_FORMAT_SHIFT, - OXYGEN_MULTICH_FORMAT_MASK); - oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, - oxygen_rate(hw_params) | - chip->model.dac_i2s_format | - get_mclk(chip, PCM_MULTICH, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - oxygen_update_spdif_source(chip); - spin_unlock_irq(&chip->reg_lock); - - chip->model.set_dac_params(chip, hw_params); - oxygen_update_dac_routing(chip); - mutex_unlock(&chip->mutex); - return 0; -} - -static int oxygen_hw_free(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - unsigned int channel = oxygen_substream_channel(substream); - unsigned int channel_mask = 1 << channel; - - spin_lock_irq(&chip->reg_lock); - chip->interrupt_mask &= ~channel_mask; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - - oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - spin_unlock_irq(&chip->reg_lock); - - return snd_pcm_lib_free_pages(substream); -} - -static int oxygen_spdif_hw_free(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_OUT_ENABLE); - spin_unlock_irq(&chip->reg_lock); - return oxygen_hw_free(substream); -} - -static int oxygen_prepare(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - unsigned int channel = oxygen_substream_channel(substream); - unsigned int channel_mask = 1 << channel; - - spin_lock_irq(&chip->reg_lock); - oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - - if (substream->runtime->no_period_wakeup) - chip->interrupt_mask &= ~channel_mask; - else - chip->interrupt_mask |= channel_mask; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int oxygen_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *s; - unsigned int mask = 0; - int pausing; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_SUSPEND: - pausing = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - pausing = 1; - break; - default: - return -EINVAL; - } - - snd_pcm_group_for_each_entry(s, substream) { - if (snd_pcm_substream_chip(s) == chip) { - mask |= 1 << oxygen_substream_channel(s); - snd_pcm_trigger_done(s, substream); - } - } - - spin_lock(&chip->reg_lock); - if (!pausing) { - if (cmd == SNDRV_PCM_TRIGGER_START) - chip->pcm_running |= mask; - else - chip->pcm_running &= ~mask; - oxygen_write8(chip, OXYGEN_DMA_STATUS, chip->pcm_running); - } else { - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) - oxygen_set_bits8(chip, OXYGEN_DMA_PAUSE, mask); - else - oxygen_clear_bits8(chip, OXYGEN_DMA_PAUSE, mask); - } - spin_unlock(&chip->reg_lock); - return 0; -} - -static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int channel = oxygen_substream_channel(substream); - u32 curr_addr; - - /* no spinlock, this read should be atomic */ - curr_addr = oxygen_read32(chip, channel_base_registers[channel]); - return bytes_to_frames(runtime, curr_addr - (u32)runtime->dma_addr); -} - -static struct snd_pcm_ops oxygen_rec_a_ops = { - .open = oxygen_rec_a_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_rec_a_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_rec_b_ops = { - .open = oxygen_rec_b_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_rec_b_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_rec_c_ops = { - .open = oxygen_rec_c_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_rec_c_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_spdif_ops = { - .open = oxygen_spdif_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_spdif_hw_params, - .hw_free = oxygen_spdif_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_multich_ops = { - .open = oxygen_multich_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_multich_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_ac97_ops = { - .open = oxygen_ac97_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static void oxygen_pcm_free(struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -int oxygen_pcm_init(struct oxygen *chip) -{ - struct snd_pcm *pcm; - int outs, ins; - int err; - - outs = !!(chip->model.device_config & PLAYBACK_0_TO_I2S); - ins = !!(chip->model.device_config & (CAPTURE_0_FROM_I2S_1 | - CAPTURE_0_FROM_I2S_2)); - if (outs | ins) { - err = snd_pcm_new(chip->card, "Multichannel", - 0, outs, ins, &pcm); - if (err < 0) - return err; - if (outs) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &oxygen_multich_ops); - if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &oxygen_rec_a_ops); - else if (chip->model.device_config & CAPTURE_0_FROM_I2S_2) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &oxygen_rec_b_ops); - pcm->private_data = chip; - pcm->private_free = oxygen_pcm_free; - strcpy(pcm->name, "Multichannel"); - if (outs) - snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - DEFAULT_BUFFER_BYTES_MULTICH, - BUFFER_BYTES_MAX_MULTICH); - if (ins) - snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - DEFAULT_BUFFER_BYTES, - BUFFER_BYTES_MAX); - } - - outs = !!(chip->model.device_config & PLAYBACK_1_TO_SPDIF); - ins = !!(chip->model.device_config & CAPTURE_1_FROM_SPDIF); - if (outs | ins) { - err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm); - if (err < 0) - return err; - if (outs) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &oxygen_spdif_ops); - if (ins) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &oxygen_rec_c_ops); - pcm->private_data = chip; - pcm->private_free = oxygen_pcm_free; - strcpy(pcm->name, "Digital"); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - DEFAULT_BUFFER_BYTES, - BUFFER_BYTES_MAX); - } - - if (chip->has_ac97_1) { - outs = !!(chip->model.device_config & PLAYBACK_2_TO_AC97_1); - ins = !!(chip->model.device_config & CAPTURE_2_FROM_AC97_1); - } else { - outs = 0; - ins = !!(chip->model.device_config & CAPTURE_2_FROM_I2S_2); - } - if (outs | ins) { - err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2", - 2, outs, ins, &pcm); - if (err < 0) - return err; - if (outs) { - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &oxygen_ac97_ops); - oxygen_write8_masked(chip, OXYGEN_REC_ROUTING, - OXYGEN_REC_B_ROUTE_AC97_1, - OXYGEN_REC_B_ROUTE_MASK); - } - if (ins) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &oxygen_rec_b_ops); - pcm->private_data = chip; - pcm->private_free = oxygen_pcm_free; - strcpy(pcm->name, outs ? "Front Panel" : "Analog 2"); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - DEFAULT_BUFFER_BYTES, - BUFFER_BYTES_MAX); - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_regs.h b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_regs.h deleted file mode 100644 index 63dc7a0a..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_regs.h +++ /dev/null @@ -1,457 +0,0 @@ -#ifndef OXYGEN_REGS_H_INCLUDED -#define OXYGEN_REGS_H_INCLUDED - -/* recording channel A */ -#define OXYGEN_DMA_A_ADDRESS 0x00 /* 32-bit base address */ -#define OXYGEN_DMA_A_COUNT 0x04 /* buffer counter (dwords) */ -#define OXYGEN_DMA_A_TCOUNT 0x06 /* interrupt counter (dwords) */ - -/* recording channel B */ -#define OXYGEN_DMA_B_ADDRESS 0x08 -#define OXYGEN_DMA_B_COUNT 0x0c -#define OXYGEN_DMA_B_TCOUNT 0x0e - -/* recording channel C */ -#define OXYGEN_DMA_C_ADDRESS 0x10 -#define OXYGEN_DMA_C_COUNT 0x14 -#define OXYGEN_DMA_C_TCOUNT 0x16 - -/* SPDIF playback channel */ -#define OXYGEN_DMA_SPDIF_ADDRESS 0x18 -#define OXYGEN_DMA_SPDIF_COUNT 0x1c -#define OXYGEN_DMA_SPDIF_TCOUNT 0x1e - -/* multichannel playback channel */ -#define OXYGEN_DMA_MULTICH_ADDRESS 0x20 -#define OXYGEN_DMA_MULTICH_COUNT 0x24 /* 24 bits */ -#define OXYGEN_DMA_MULTICH_TCOUNT 0x28 /* 24 bits */ - -/* AC'97 (front panel) playback channel */ -#define OXYGEN_DMA_AC97_ADDRESS 0x30 -#define OXYGEN_DMA_AC97_COUNT 0x34 -#define OXYGEN_DMA_AC97_TCOUNT 0x36 - -/* all registers 0x00..0x36 return current position on read */ - -#define OXYGEN_DMA_STATUS 0x40 /* 1 = running, 0 = stop */ -#define OXYGEN_CHANNEL_A 0x01 -#define OXYGEN_CHANNEL_B 0x02 -#define OXYGEN_CHANNEL_C 0x04 -#define OXYGEN_CHANNEL_SPDIF 0x08 -#define OXYGEN_CHANNEL_MULTICH 0x10 -#define OXYGEN_CHANNEL_AC97 0x20 - -#define OXYGEN_DMA_PAUSE 0x41 /* 1 = pause */ -/* OXYGEN_CHANNEL_* */ - -#define OXYGEN_DMA_RESET 0x42 -/* OXYGEN_CHANNEL_* */ - -#define OXYGEN_PLAY_CHANNELS 0x43 -#define OXYGEN_PLAY_CHANNELS_MASK 0x03 -#define OXYGEN_PLAY_CHANNELS_2 0x00 -#define OXYGEN_PLAY_CHANNELS_4 0x01 -#define OXYGEN_PLAY_CHANNELS_6 0x02 -#define OXYGEN_PLAY_CHANNELS_8 0x03 -#define OXYGEN_DMA_A_BURST_MASK 0x04 -#define OXYGEN_DMA_A_BURST_8 0x00 /* dwords */ -#define OXYGEN_DMA_A_BURST_16 0x04 -#define OXYGEN_DMA_MULTICH_BURST_MASK 0x08 -#define OXYGEN_DMA_MULTICH_BURST_8 0x00 -#define OXYGEN_DMA_MULTICH_BURST_16 0x08 - -#define OXYGEN_INTERRUPT_MASK 0x44 -/* OXYGEN_CHANNEL_* */ -#define OXYGEN_INT_SPDIF_IN_DETECT 0x0100 -#define OXYGEN_INT_MCU 0x0200 -#define OXYGEN_INT_2WIRE 0x0400 -#define OXYGEN_INT_GPIO 0x0800 -#define OXYGEN_INT_MCB 0x2000 -#define OXYGEN_INT_AC97 0x4000 - -#define OXYGEN_INTERRUPT_STATUS 0x46 -/* OXYGEN_CHANNEL_* amd OXYGEN_INT_* */ -#define OXYGEN_INT_MIDI 0x1000 - -#define OXYGEN_MISC 0x48 -#define OXYGEN_MISC_WRITE_PCI_SUBID 0x01 -#define OXYGEN_MISC_LATENCY_3F 0x02 -#define OXYGEN_MISC_REC_C_FROM_SPDIF 0x04 -#define OXYGEN_MISC_REC_B_FROM_AC97 0x08 -#define OXYGEN_MISC_REC_A_FROM_MULTICH 0x10 -#define OXYGEN_MISC_PCI_MEM_W_1_CLOCK 0x20 -#define OXYGEN_MISC_MIDI 0x40 -#define OXYGEN_MISC_CRYSTAL_MASK 0x80 -#define OXYGEN_MISC_CRYSTAL_24576 0x00 -#define OXYGEN_MISC_CRYSTAL_27 0x80 /* MHz */ - -#define OXYGEN_REC_FORMAT 0x4a -#define OXYGEN_REC_FORMAT_A_MASK 0x03 -#define OXYGEN_REC_FORMAT_A_SHIFT 0 -#define OXYGEN_REC_FORMAT_B_MASK 0x0c -#define OXYGEN_REC_FORMAT_B_SHIFT 2 -#define OXYGEN_REC_FORMAT_C_MASK 0x30 -#define OXYGEN_REC_FORMAT_C_SHIFT 4 -#define OXYGEN_FORMAT_16 0x00 -#define OXYGEN_FORMAT_24 0x01 -#define OXYGEN_FORMAT_32 0x02 - -#define OXYGEN_PLAY_FORMAT 0x4b -#define OXYGEN_SPDIF_FORMAT_MASK 0x03 -#define OXYGEN_SPDIF_FORMAT_SHIFT 0 -#define OXYGEN_MULTICH_FORMAT_MASK 0x0c -#define OXYGEN_MULTICH_FORMAT_SHIFT 2 -/* OXYGEN_FORMAT_* */ - -#define OXYGEN_REC_CHANNELS 0x4c -#define OXYGEN_REC_CHANNELS_MASK 0x07 -#define OXYGEN_REC_CHANNELS_2_2_2 0x00 /* DMA A, B, C */ -#define OXYGEN_REC_CHANNELS_4_2_2 0x01 -#define OXYGEN_REC_CHANNELS_6_0_2 0x02 -#define OXYGEN_REC_CHANNELS_6_2_0 0x03 -#define OXYGEN_REC_CHANNELS_8_0_0 0x04 - -#define OXYGEN_FUNCTION 0x50 -#define OXYGEN_FUNCTION_CLOCK_MASK 0x01 -#define OXYGEN_FUNCTION_CLOCK_PLL 0x00 -#define OXYGEN_FUNCTION_CLOCK_CRYSTAL 0x01 -#define OXYGEN_FUNCTION_RESET_CODEC 0x02 -#define OXYGEN_FUNCTION_RESET_POL 0x04 -#define OXYGEN_FUNCTION_PWDN 0x08 -#define OXYGEN_FUNCTION_PWDN_EN 0x10 -#define OXYGEN_FUNCTION_PWDN_POL 0x20 -#define OXYGEN_FUNCTION_2WIRE_SPI_MASK 0x40 -#define OXYGEN_FUNCTION_SPI 0x00 -#define OXYGEN_FUNCTION_2WIRE 0x40 -#define OXYGEN_FUNCTION_ENABLE_SPI_4_5 0x80 /* 0 = EEPROM */ - -#define OXYGEN_I2S_MULTICH_FORMAT 0x60 -#define OXYGEN_I2S_RATE_MASK 0x0007 /* LRCK */ -#define OXYGEN_RATE_32000 0x0000 -#define OXYGEN_RATE_44100 0x0001 -#define OXYGEN_RATE_48000 0x0002 -#define OXYGEN_RATE_64000 0x0003 -#define OXYGEN_RATE_88200 0x0004 -#define OXYGEN_RATE_96000 0x0005 -#define OXYGEN_RATE_176400 0x0006 -#define OXYGEN_RATE_192000 0x0007 -#define OXYGEN_I2S_FORMAT_MASK 0x0008 -#define OXYGEN_I2S_FORMAT_I2S 0x0000 -#define OXYGEN_I2S_FORMAT_LJUST 0x0008 -#define OXYGEN_I2S_MCLK_MASK 0x0030 /* MCLK/LRCK */ -#define OXYGEN_I2S_MCLK_SHIFT 4 -#define MCLK_128 0 -#define MCLK_256 1 -#define MCLK_512 2 -#define OXYGEN_I2S_MCLK(f) (((f) & 3) << OXYGEN_I2S_MCLK_SHIFT) -#define OXYGEN_I2S_BITS_MASK 0x00c0 -#define OXYGEN_I2S_BITS_16 0x0000 -#define OXYGEN_I2S_BITS_20 0x0040 -#define OXYGEN_I2S_BITS_24 0x0080 -#define OXYGEN_I2S_BITS_32 0x00c0 -#define OXYGEN_I2S_MASTER 0x0100 -#define OXYGEN_I2S_BCLK_MASK 0x0600 /* BCLK/LRCK */ -#define OXYGEN_I2S_BCLK_64 0x0000 -#define OXYGEN_I2S_BCLK_128 0x0200 -#define OXYGEN_I2S_BCLK_256 0x0400 -#define OXYGEN_I2S_MUTE_MCLK 0x0800 - -#define OXYGEN_I2S_A_FORMAT 0x62 -#define OXYGEN_I2S_B_FORMAT 0x64 -#define OXYGEN_I2S_C_FORMAT 0x66 -/* like OXYGEN_I2S_MULTICH_FORMAT */ - -#define OXYGEN_SPDIF_CONTROL 0x70 -#define OXYGEN_SPDIF_OUT_ENABLE 0x00000002 -#define OXYGEN_SPDIF_LOOPBACK 0x00000004 /* in to out */ -#define OXYGEN_SPDIF_SENSE_MASK 0x00000008 -#define OXYGEN_SPDIF_LOCK_MASK 0x00000010 -#define OXYGEN_SPDIF_RATE_MASK 0x00000020 -#define OXYGEN_SPDIF_SPDVALID 0x00000040 -#define OXYGEN_SPDIF_SENSE_PAR 0x00000200 -#define OXYGEN_SPDIF_LOCK_PAR 0x00000400 -#define OXYGEN_SPDIF_SENSE_STATUS 0x00000800 -#define OXYGEN_SPDIF_LOCK_STATUS 0x00001000 -#define OXYGEN_SPDIF_SENSE_INT 0x00002000 /* r/wc */ -#define OXYGEN_SPDIF_LOCK_INT 0x00004000 /* r/wc */ -#define OXYGEN_SPDIF_RATE_INT 0x00008000 /* r/wc */ -#define OXYGEN_SPDIF_IN_CLOCK_MASK 0x00010000 -#define OXYGEN_SPDIF_IN_CLOCK_96 0x00000000 /* <= 96 kHz */ -#define OXYGEN_SPDIF_IN_CLOCK_192 0x00010000 /* > 96 kHz */ -#define OXYGEN_SPDIF_OUT_RATE_MASK 0x07000000 -#define OXYGEN_SPDIF_OUT_RATE_SHIFT 24 -/* OXYGEN_RATE_* << OXYGEN_SPDIF_OUT_RATE_SHIFT */ - -#define OXYGEN_SPDIF_OUTPUT_BITS 0x74 -#define OXYGEN_SPDIF_NONAUDIO 0x00000002 -#define OXYGEN_SPDIF_C 0x00000004 -#define OXYGEN_SPDIF_PREEMPHASIS 0x00000008 -#define OXYGEN_SPDIF_CATEGORY_MASK 0x000007f0 -#define OXYGEN_SPDIF_CATEGORY_SHIFT 4 -#define OXYGEN_SPDIF_ORIGINAL 0x00000800 -#define OXYGEN_SPDIF_CS_RATE_MASK 0x0000f000 -#define OXYGEN_SPDIF_CS_RATE_SHIFT 12 -#define OXYGEN_SPDIF_V 0x00010000 /* 0 = valid */ - -#define OXYGEN_SPDIF_INPUT_BITS 0x78 -/* 32 bits, IEC958_AES_* */ - -#define OXYGEN_EEPROM_CONTROL 0x80 -#define OXYGEN_EEPROM_ADDRESS_MASK 0x7f -#define OXYGEN_EEPROM_DIR_MASK 0x80 -#define OXYGEN_EEPROM_DIR_READ 0x00 -#define OXYGEN_EEPROM_DIR_WRITE 0x80 - -#define OXYGEN_EEPROM_STATUS 0x81 -#define OXYGEN_EEPROM_VALID 0x40 -#define OXYGEN_EEPROM_BUSY 0x80 - -#define OXYGEN_EEPROM_DATA 0x82 /* 16 bits */ - -#define OXYGEN_2WIRE_CONTROL 0x90 -#define OXYGEN_2WIRE_DIR_MASK 0x01 -#define OXYGEN_2WIRE_DIR_WRITE 0x00 -#define OXYGEN_2WIRE_DIR_READ 0x01 -#define OXYGEN_2WIRE_ADDRESS_MASK 0xfe /* slave device address */ -#define OXYGEN_2WIRE_ADDRESS_SHIFT 1 - -#define OXYGEN_2WIRE_MAP 0x91 /* address, 8 bits */ -#define OXYGEN_2WIRE_DATA 0x92 /* data, 16 bits */ - -#define OXYGEN_2WIRE_BUS_STATUS 0x94 -#define OXYGEN_2WIRE_BUSY 0x0001 -#define OXYGEN_2WIRE_LENGTH_MASK 0x0002 -#define OXYGEN_2WIRE_LENGTH_8 0x0000 -#define OXYGEN_2WIRE_LENGTH_16 0x0002 -#define OXYGEN_2WIRE_MANUAL_READ 0x0004 /* 0 = auto read */ -#define OXYGEN_2WIRE_WRITE_MAP_ONLY 0x0008 -#define OXYGEN_2WIRE_SLAVE_AD_MASK 0x0030 /* AD0, AD1 */ -#define OXYGEN_2WIRE_INTERRUPT_MASK 0x0040 /* 0 = int. if not responding */ -#define OXYGEN_2WIRE_SLAVE_NO_RESPONSE 0x0080 -#define OXYGEN_2WIRE_SPEED_MASK 0x0100 -#define OXYGEN_2WIRE_SPEED_STANDARD 0x0000 -#define OXYGEN_2WIRE_SPEED_FAST 0x0100 -#define OXYGEN_2WIRE_CLOCK_SYNC 0x0200 -#define OXYGEN_2WIRE_BUS_RESET 0x0400 - -#define OXYGEN_SPI_CONTROL 0x98 -#define OXYGEN_SPI_BUSY 0x01 /* read */ -#define OXYGEN_SPI_TRIGGER 0x01 /* write */ -#define OXYGEN_SPI_DATA_LENGTH_MASK 0x02 -#define OXYGEN_SPI_DATA_LENGTH_2 0x00 -#define OXYGEN_SPI_DATA_LENGTH_3 0x02 -#define OXYGEN_SPI_CLOCK_MASK 0x0c -#define OXYGEN_SPI_CLOCK_160 0x00 /* ns */ -#define OXYGEN_SPI_CLOCK_320 0x04 -#define OXYGEN_SPI_CLOCK_640 0x08 -#define OXYGEN_SPI_CLOCK_1280 0x0c -#define OXYGEN_SPI_CODEC_MASK 0x70 /* 0..5 */ -#define OXYGEN_SPI_CODEC_SHIFT 4 -#define OXYGEN_SPI_CEN_MASK 0x80 -#define OXYGEN_SPI_CEN_LATCH_CLOCK_LO 0x00 -#define OXYGEN_SPI_CEN_LATCH_CLOCK_HI 0x80 - -#define OXYGEN_SPI_DATA1 0x99 -#define OXYGEN_SPI_DATA2 0x9a -#define OXYGEN_SPI_DATA3 0x9b - -#define OXYGEN_MPU401 0xa0 - -#define OXYGEN_MPU401_CONTROL 0xa2 -#define OXYGEN_MPU401_LOOPBACK 0x01 /* TXD to RXD */ - -#define OXYGEN_GPI_DATA 0xa4 -/* bits 0..5 = pin XGPI0..XGPI5 */ - -#define OXYGEN_GPI_INTERRUPT_MASK 0xa5 -/* bits 0..5, 1 = enable */ - -#define OXYGEN_GPIO_DATA 0xa6 -/* bits 0..9 */ - -#define OXYGEN_GPIO_CONTROL 0xa8 -/* bits 0..9, 0 = input, 1 = output */ -#define OXYGEN_GPIO1_XSLAVE_RDY 0x8000 - -#define OXYGEN_GPIO_INTERRUPT_MASK 0xaa -/* bits 0..9, 1 = enable */ - -#define OXYGEN_DEVICE_SENSE 0xac -#define OXYGEN_HEAD_PHONE_DETECT 0x01 -#define OXYGEN_HEAD_PHONE_MASK 0x06 -#define OXYGEN_HEAD_PHONE_PASSIVE_SPK 0x00 -#define OXYGEN_HEAD_PHONE_HP 0x02 -#define OXYGEN_HEAD_PHONE_ACTIVE_SPK 0x04 - -#define OXYGEN_MCU_2WIRE_DATA 0xb0 - -#define OXYGEN_MCU_2WIRE_MAP 0xb2 - -#define OXYGEN_MCU_2WIRE_STATUS 0xb3 -#define OXYGEN_MCU_2WIRE_BUSY 0x01 -#define OXYGEN_MCU_2WIRE_LENGTH_MASK 0x06 -#define OXYGEN_MCU_2WIRE_LENGTH_1 0x00 -#define OXYGEN_MCU_2WIRE_LENGTH_2 0x02 -#define OXYGEN_MCU_2WIRE_LENGTH_3 0x04 -#define OXYGEN_MCU_2WIRE_WRITE 0x08 /* r/wc */ -#define OXYGEN_MCU_2WIRE_READ 0x10 /* r/wc */ -#define OXYGEN_MCU_2WIRE_DRV_XACT_FAIL 0x20 /* r/wc */ -#define OXYGEN_MCU_2WIRE_RESET 0x40 - -#define OXYGEN_MCU_2WIRE_CONTROL 0xb4 -#define OXYGEN_MCU_2WIRE_DRV_ACK 0x01 -#define OXYGEN_MCU_2WIRE_DRV_XACT 0x02 -#define OXYGEN_MCU_2WIRE_INT_MASK 0x04 -#define OXYGEN_MCU_2WIRE_SYNC_MASK 0x08 -#define OXYGEN_MCU_2WIRE_SYNC_RDY_PIN 0x00 -#define OXYGEN_MCU_2WIRE_SYNC_DATA 0x08 -#define OXYGEN_MCU_2WIRE_ADDRESS_MASK 0x30 -#define OXYGEN_MCU_2WIRE_ADDRESS_10 0x00 -#define OXYGEN_MCU_2WIRE_ADDRESS_12 0x10 -#define OXYGEN_MCU_2WIRE_ADDRESS_14 0x20 -#define OXYGEN_MCU_2WIRE_ADDRESS_16 0x30 -#define OXYGEN_MCU_2WIRE_INT_POL 0x40 -#define OXYGEN_MCU_2WIRE_SYNC_ENABLE 0x80 - -#define OXYGEN_PLAY_ROUTING 0xc0 -#define OXYGEN_PLAY_MUTE01 0x0001 -#define OXYGEN_PLAY_MUTE23 0x0002 -#define OXYGEN_PLAY_MUTE45 0x0004 -#define OXYGEN_PLAY_MUTE67 0x0008 -#define OXYGEN_PLAY_MULTICH_MASK 0x0010 -#define OXYGEN_PLAY_MULTICH_I2S_DAC 0x0000 -#define OXYGEN_PLAY_MULTICH_AC97 0x0010 -#define OXYGEN_PLAY_SPDIF_MASK 0x00e0 -#define OXYGEN_PLAY_SPDIF_SPDIF 0x0000 -#define OXYGEN_PLAY_SPDIF_MULTICH_01 0x0020 -#define OXYGEN_PLAY_SPDIF_MULTICH_23 0x0040 -#define OXYGEN_PLAY_SPDIF_MULTICH_45 0x0060 -#define OXYGEN_PLAY_SPDIF_MULTICH_67 0x0080 -#define OXYGEN_PLAY_SPDIF_REC_A 0x00a0 -#define OXYGEN_PLAY_SPDIF_REC_B 0x00c0 -#define OXYGEN_PLAY_SPDIF_I2S_ADC_3 0x00e0 -#define OXYGEN_PLAY_DAC0_SOURCE_MASK 0x0300 -#define OXYGEN_PLAY_DAC0_SOURCE_SHIFT 8 -#define OXYGEN_PLAY_DAC1_SOURCE_MASK 0x0c00 -#define OXYGEN_PLAY_DAC1_SOURCE_SHIFT 10 -#define OXYGEN_PLAY_DAC2_SOURCE_MASK 0x3000 -#define OXYGEN_PLAY_DAC2_SOURCE_SHIFT 12 -#define OXYGEN_PLAY_DAC3_SOURCE_MASK 0xc000 -#define OXYGEN_PLAY_DAC3_SOURCE_SHIFT 14 - -#define OXYGEN_REC_ROUTING 0xc2 -#define OXYGEN_MUTE_I2S_ADC_1 0x01 -#define OXYGEN_MUTE_I2S_ADC_2 0x02 -#define OXYGEN_MUTE_I2S_ADC_3 0x04 -#define OXYGEN_REC_A_ROUTE_MASK 0x08 -#define OXYGEN_REC_A_ROUTE_I2S_ADC_1 0x00 -#define OXYGEN_REC_A_ROUTE_AC97_0 0x08 -#define OXYGEN_REC_B_ROUTE_MASK 0x10 -#define OXYGEN_REC_B_ROUTE_I2S_ADC_2 0x00 -#define OXYGEN_REC_B_ROUTE_AC97_1 0x10 -#define OXYGEN_REC_C_ROUTE_MASK 0x20 -#define OXYGEN_REC_C_ROUTE_SPDIF 0x00 -#define OXYGEN_REC_C_ROUTE_I2S_ADC_3 0x20 - -#define OXYGEN_ADC_MONITOR 0xc3 -#define OXYGEN_ADC_MONITOR_A 0x01 -#define OXYGEN_ADC_MONITOR_A_HALF_VOL 0x02 -#define OXYGEN_ADC_MONITOR_B 0x04 -#define OXYGEN_ADC_MONITOR_B_HALF_VOL 0x08 -#define OXYGEN_ADC_MONITOR_C 0x10 -#define OXYGEN_ADC_MONITOR_C_HALF_VOL 0x20 - -#define OXYGEN_A_MONITOR_ROUTING 0xc4 -#define OXYGEN_A_MONITOR_ROUTE_0_MASK 0x03 -#define OXYGEN_A_MONITOR_ROUTE_0_SHIFT 0 -#define OXYGEN_A_MONITOR_ROUTE_1_MASK 0x0c -#define OXYGEN_A_MONITOR_ROUTE_1_SHIFT 2 -#define OXYGEN_A_MONITOR_ROUTE_2_MASK 0x30 -#define OXYGEN_A_MONITOR_ROUTE_2_SHIFT 4 -#define OXYGEN_A_MONITOR_ROUTE_3_MASK 0xc0 -#define OXYGEN_A_MONITOR_ROUTE_3_SHIFT 6 - -#define OXYGEN_AC97_CONTROL 0xd0 -#define OXYGEN_AC97_COLD_RESET 0x0001 -#define OXYGEN_AC97_SUSPENDED 0x0002 /* read */ -#define OXYGEN_AC97_RESUME 0x0002 /* write */ -#define OXYGEN_AC97_CLOCK_DISABLE 0x0004 -#define OXYGEN_AC97_NO_CODEC_0 0x0008 -#define OXYGEN_AC97_CODEC_0 0x0010 -#define OXYGEN_AC97_CODEC_1 0x0020 - -#define OXYGEN_AC97_INTERRUPT_MASK 0xd2 -#define OXYGEN_AC97_INT_READ_DONE 0x01 -#define OXYGEN_AC97_INT_WRITE_DONE 0x02 -#define OXYGEN_AC97_INT_CODEC_0 0x10 -#define OXYGEN_AC97_INT_CODEC_1 0x20 - -#define OXYGEN_AC97_INTERRUPT_STATUS 0xd3 -/* OXYGEN_AC97_INT_* */ - -#define OXYGEN_AC97_OUT_CONFIG 0xd4 -#define OXYGEN_AC97_CODEC1_SLOT3 0x00000001 -#define OXYGEN_AC97_CODEC1_SLOT3_VSR 0x00000002 -#define OXYGEN_AC97_CODEC1_SLOT4 0x00000010 -#define OXYGEN_AC97_CODEC1_SLOT4_VSR 0x00000020 -#define OXYGEN_AC97_CODEC0_FRONTL 0x00000100 -#define OXYGEN_AC97_CODEC0_FRONTR 0x00000200 -#define OXYGEN_AC97_CODEC0_SIDEL 0x00000400 -#define OXYGEN_AC97_CODEC0_SIDER 0x00000800 -#define OXYGEN_AC97_CODEC0_CENTER 0x00001000 -#define OXYGEN_AC97_CODEC0_BASE 0x00002000 -#define OXYGEN_AC97_CODEC0_REARL 0x00004000 -#define OXYGEN_AC97_CODEC0_REARR 0x00008000 - -#define OXYGEN_AC97_IN_CONFIG 0xd8 -#define OXYGEN_AC97_CODEC1_LINEL 0x00000001 -#define OXYGEN_AC97_CODEC1_LINEL_VSR 0x00000002 -#define OXYGEN_AC97_CODEC1_LINEL_16 0x00000000 -#define OXYGEN_AC97_CODEC1_LINEL_18 0x00000004 -#define OXYGEN_AC97_CODEC1_LINEL_20 0x00000008 -#define OXYGEN_AC97_CODEC1_LINER 0x00000010 -#define OXYGEN_AC97_CODEC1_LINER_VSR 0x00000020 -#define OXYGEN_AC97_CODEC1_LINER_16 0x00000000 -#define OXYGEN_AC97_CODEC1_LINER_18 0x00000040 -#define OXYGEN_AC97_CODEC1_LINER_20 0x00000080 -#define OXYGEN_AC97_CODEC0_LINEL 0x00000100 -#define OXYGEN_AC97_CODEC0_LINER 0x00000200 - -#define OXYGEN_AC97_REGS 0xdc -#define OXYGEN_AC97_REG_DATA_MASK 0x0000ffff -#define OXYGEN_AC97_REG_ADDR_MASK 0x007f0000 -#define OXYGEN_AC97_REG_ADDR_SHIFT 16 -#define OXYGEN_AC97_REG_DIR_MASK 0x00800000 -#define OXYGEN_AC97_REG_DIR_WRITE 0x00000000 -#define OXYGEN_AC97_REG_DIR_READ 0x00800000 -#define OXYGEN_AC97_REG_CODEC_MASK 0x01000000 -#define OXYGEN_AC97_REG_CODEC_SHIFT 24 - -#define OXYGEN_TEST 0xe0 -#define OXYGEN_TEST_RAM_SUCCEEDED 0x01 -#define OXYGEN_TEST_PLAYBACK_RAM 0x02 -#define OXYGEN_TEST_RECORD_RAM 0x04 -#define OXYGEN_TEST_PLL 0x08 -#define OXYGEN_TEST_2WIRE_LOOPBACK 0x10 - -#define OXYGEN_DMA_FLUSH 0xe1 -/* OXYGEN_CHANNEL_* */ - -#define OXYGEN_CODEC_VERSION 0xe4 -#define OXYGEN_CODEC_ID_MASK 0x07 - -#define OXYGEN_REVISION 0xe6 -#define OXYGEN_PACKAGE_ID_MASK 0x0007 -#define OXYGEN_PACKAGE_ID_8786 0x0004 -#define OXYGEN_PACKAGE_ID_8787 0x0006 -#define OXYGEN_PACKAGE_ID_8788 0x0007 -#define OXYGEN_REVISION_MASK 0xfff8 -#define OXYGEN_REVISION_2 0x0008 - -#define OXYGEN_OFFSIN_48K 0xe8 -#define OXYGEN_OFFSBASE_48K 0xe9 -#define OXYGEN_OFFSBASE_MASK 0x0fff -#define OXYGEN_OFFSIN_44K 0xec -#define OXYGEN_OFFSBASE_44K 0xed - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/pcm1796.h b/ANDROID_3.4.5/sound/pci/oxygen/pcm1796.h deleted file mode 100644 index 698bf46c..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/pcm1796.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef PCM1796_H_INCLUDED -#define PCM1796_H_INCLUDED - -/* register 16 */ -#define PCM1796_ATL_MASK 0xff -/* register 17 */ -#define PCM1796_ATR_MASK 0xff -/* register 18 */ -#define PCM1796_MUTE 0x01 -#define PCM1796_DME 0x02 -#define PCM1796_DMF_MASK 0x0c -#define PCM1796_DMF_DISABLED 0x00 -#define PCM1796_DMF_48 0x04 -#define PCM1796_DMF_441 0x08 -#define PCM1796_DMF_32 0x0c -#define PCM1796_FMT_MASK 0x70 -#define PCM1796_FMT_16_RJUST 0x00 -#define PCM1796_FMT_20_RJUST 0x10 -#define PCM1796_FMT_24_RJUST 0x20 -#define PCM1796_FMT_24_LJUST 0x30 -#define PCM1796_FMT_16_I2S 0x40 -#define PCM1796_FMT_24_I2S 0x50 -#define PCM1796_ATLD 0x80 -/* register 19 */ -#define PCM1796_INZD 0x01 -#define PCM1796_FLT_MASK 0x02 -#define PCM1796_FLT_SHARP 0x00 -#define PCM1796_FLT_SLOW 0x02 -#define PCM1796_DFMS 0x04 -#define PCM1796_OPE 0x10 -#define PCM1796_ATS_MASK 0x60 -#define PCM1796_ATS_1 0x00 -#define PCM1796_ATS_2 0x20 -#define PCM1796_ATS_4 0x40 -#define PCM1796_ATS_8 0x60 -#define PCM1796_REV 0x80 -/* register 20 */ -#define PCM1796_OS_MASK 0x03 -#define PCM1796_OS_64 0x00 -#define PCM1796_OS_32 0x01 -#define PCM1796_OS_128 0x02 -#define PCM1796_CHSL_MASK 0x04 -#define PCM1796_CHSL_LEFT 0x00 -#define PCM1796_CHSL_RIGHT 0x04 -#define PCM1796_MONO 0x08 -#define PCM1796_DFTH 0x10 -#define PCM1796_DSD 0x20 -#define PCM1796_SRST 0x40 -/* register 21 */ -#define PCM1796_PCMZ 0x01 -#define PCM1796_DZ_MASK 0x06 -/* register 22 */ -#define PCM1796_ZFGL 0x01 -#define PCM1796_ZFGR 0x02 -/* register 23 */ -#define PCM1796_ID_MASK 0x1f - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/virtuoso.c b/ANDROID_3.4.5/sound/pci/oxygen/virtuoso.c deleted file mode 100644 index 3fdee495..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/virtuoso.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * C-Media CMI8788 driver for Asus Xonar cards - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; 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 "xonar.h" - -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_DESCRIPTION("Asus Virtuoso driver"); -MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{Asus,AV66},{Asus,AV100},{Asus,AV200}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "card index"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string"); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "enable card"); - -static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { - { OXYGEN_PCI_SUBID(0x1043, 0x8269) }, - { OXYGEN_PCI_SUBID(0x1043, 0x8275) }, - { OXYGEN_PCI_SUBID(0x1043, 0x82b7) }, - { OXYGEN_PCI_SUBID(0x1043, 0x8314) }, - { OXYGEN_PCI_SUBID(0x1043, 0x8327) }, - { OXYGEN_PCI_SUBID(0x1043, 0x834f) }, - { OXYGEN_PCI_SUBID(0x1043, 0x835c) }, - { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, - { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, - { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, - { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, - { } -}; -MODULE_DEVICE_TABLE(pci, xonar_ids); - -static int __devinit get_xonar_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - if (get_xonar_pcm179x_model(chip, id) >= 0) - return 0; - if (get_xonar_cs43xx_model(chip, id) >= 0) - return 0; - if (get_xonar_wm87x6_model(chip, id) >= 0) - return 0; - return -EINVAL; -} - -static int __devinit xonar_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - ++dev; - return -ENOENT; - } - err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, - xonar_ids, get_xonar_model); - if (err >= 0) - ++dev; - return err; -} - -static struct pci_driver xonar_driver = { - .name = KBUILD_MODNAME, - .id_table = xonar_ids, - .probe = xonar_probe, - .remove = __devexit_p(oxygen_pci_remove), -#ifdef CONFIG_PM - .suspend = oxygen_pci_suspend, - .resume = oxygen_pci_resume, -#endif - .shutdown = oxygen_pci_shutdown, -}; - -static int __init alsa_card_xonar_init(void) -{ - return pci_register_driver(&xonar_driver); -} - -static void __exit alsa_card_xonar_exit(void) -{ - pci_unregister_driver(&xonar_driver); -} - -module_init(alsa_card_xonar_init) -module_exit(alsa_card_xonar_exit) diff --git a/ANDROID_3.4.5/sound/pci/oxygen/wm8766.h b/ANDROID_3.4.5/sound/pci/oxygen/wm8766.h deleted file mode 100644 index e0e849a7..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/wm8766.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef WM8766_H_INCLUDED -#define WM8766_H_INCLUDED - -#define WM8766_LDA1 0x00 -#define WM8766_RDA1 0x01 -#define WM8766_DAC_CTRL 0x02 -#define WM8766_INT_CTRL 0x03 -#define WM8766_LDA2 0x04 -#define WM8766_RDA2 0x05 -#define WM8766_LDA3 0x06 -#define WM8766_RDA3 0x07 -#define WM8766_MASTDA 0x08 -#define WM8766_DAC_CTRL2 0x09 -#define WM8766_DAC_CTRL3 0x0a -#define WM8766_MUTE1 0x0c -#define WM8766_MUTE2 0x0f -#define WM8766_RESET 0x1f - -/* LDAx/RDAx/MASTDA */ -#define WM8766_ATT_MASK 0x0ff -#define WM8766_UPDATE 0x100 -/* DAC_CTRL */ -#define WM8766_MUTEALL 0x001 -#define WM8766_DEEMPALL 0x002 -#define WM8766_PWDN 0x004 -#define WM8766_ATC 0x008 -#define WM8766_IZD 0x010 -#define WM8766_PL_LEFT_MASK 0x060 -#define WM8766_PL_LEFT_MUTE 0x000 -#define WM8766_PL_LEFT_LEFT 0x020 -#define WM8766_PL_LEFT_RIGHT 0x040 -#define WM8766_PL_LEFT_LRMIX 0x060 -#define WM8766_PL_RIGHT_MASK 0x180 -#define WM8766_PL_RIGHT_MUTE 0x000 -#define WM8766_PL_RIGHT_LEFT 0x080 -#define WM8766_PL_RIGHT_RIGHT 0x100 -#define WM8766_PL_RIGHT_LRMIX 0x180 -/* INT_CTRL */ -#define WM8766_FMT_MASK 0x003 -#define WM8766_FMT_RJUST 0x000 -#define WM8766_FMT_LJUST 0x001 -#define WM8766_FMT_I2S 0x002 -#define WM8766_FMT_DSP 0x003 -#define WM8766_LRP 0x004 -#define WM8766_BCP 0x008 -#define WM8766_IWL_MASK 0x030 -#define WM8766_IWL_16 0x000 -#define WM8766_IWL_20 0x010 -#define WM8766_IWL_24 0x020 -#define WM8766_IWL_32 0x030 -#define WM8766_PHASE_MASK 0x1c0 -/* DAC_CTRL2 */ -#define WM8766_ZCD 0x001 -#define WM8766_DZFM_MASK 0x006 -#define WM8766_DMUTE_MASK 0x038 -#define WM8766_DEEMP_MASK 0x1c0 -/* DAC_CTRL3 */ -#define WM8766_DACPD_MASK 0x00e -#define WM8766_PWRDNALL 0x010 -#define WM8766_MS 0x020 -#define WM8766_RATE_MASK 0x1c0 -#define WM8766_RATE_128 0x000 -#define WM8766_RATE_192 0x040 -#define WM8766_RATE_256 0x080 -#define WM8766_RATE_384 0x0c0 -#define WM8766_RATE_512 0x100 -#define WM8766_RATE_768 0x140 -/* MUTE1 */ -#define WM8766_MPD1 0x040 -/* MUTE2 */ -#define WM8766_MPD2 0x020 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/wm8776.h b/ANDROID_3.4.5/sound/pci/oxygen/wm8776.h deleted file mode 100644 index 1a96f561..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/wm8776.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef WM8776_H_INCLUDED -#define WM8776_H_INCLUDED - -/* - * the following register names are from: - * wm8776.h -- WM8776 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define WM8776_HPLVOL 0x00 -#define WM8776_HPRVOL 0x01 -#define WM8776_HPMASTER 0x02 -#define WM8776_DACLVOL 0x03 -#define WM8776_DACRVOL 0x04 -#define WM8776_DACMASTER 0x05 -#define WM8776_PHASESWAP 0x06 -#define WM8776_DACCTRL1 0x07 -#define WM8776_DACMUTE 0x08 -#define WM8776_DACCTRL2 0x09 -#define WM8776_DACIFCTRL 0x0a -#define WM8776_ADCIFCTRL 0x0b -#define WM8776_MSTRCTRL 0x0c -#define WM8776_PWRDOWN 0x0d -#define WM8776_ADCLVOL 0x0e -#define WM8776_ADCRVOL 0x0f -#define WM8776_ALCCTRL1 0x10 -#define WM8776_ALCCTRL2 0x11 -#define WM8776_ALCCTRL3 0x12 -#define WM8776_NOISEGATE 0x13 -#define WM8776_LIMITER 0x14 -#define WM8776_ADCMUX 0x15 -#define WM8776_OUTMUX 0x16 -#define WM8776_RESET 0x17 - - -/* HPLVOL/HPRVOL/HPMASTER */ -#define WM8776_HPATT_MASK 0x07f -#define WM8776_HPZCEN 0x080 -#define WM8776_UPDATE 0x100 - -/* DACLVOL/DACRVOL/DACMASTER */ -#define WM8776_DATT_MASK 0x0ff -/*#define WM8776_UPDATE 0x100*/ - -/* PHASESWAP */ -#define WM8776_PH_MASK 0x003 - -/* DACCTRL1 */ -#define WM8776_DZCEN 0x001 -#define WM8776_ATC 0x002 -#define WM8776_IZD 0x004 -#define WM8776_TOD 0x008 -#define WM8776_PL_LEFT_MASK 0x030 -#define WM8776_PL_LEFT_MUTE 0x000 -#define WM8776_PL_LEFT_LEFT 0x010 -#define WM8776_PL_LEFT_RIGHT 0x020 -#define WM8776_PL_LEFT_LRMIX 0x030 -#define WM8776_PL_RIGHT_MASK 0x0c0 -#define WM8776_PL_RIGHT_MUTE 0x000 -#define WM8776_PL_RIGHT_LEFT 0x040 -#define WM8776_PL_RIGHT_RIGHT 0x080 -#define WM8776_PL_RIGHT_LRMIX 0x0c0 - -/* DACMUTE */ -#define WM8776_DMUTE 0x001 - -/* DACCTRL2 */ -#define WM8776_DEEMPH 0x001 -#define WM8776_DZFM_MASK 0x006 -#define WM8776_DZFM_NONE 0x000 -#define WM8776_DZFM_LR 0x002 -#define WM8776_DZFM_BOTH 0x004 -#define WM8776_DZFM_EITHER 0x006 - -/* DACIFCTRL */ -#define WM8776_DACFMT_MASK 0x003 -#define WM8776_DACFMT_RJUST 0x000 -#define WM8776_DACFMT_LJUST 0x001 -#define WM8776_DACFMT_I2S 0x002 -#define WM8776_DACFMT_DSP 0x003 -#define WM8776_DACLRP 0x004 -#define WM8776_DACBCP 0x008 -#define WM8776_DACWL_MASK 0x030 -#define WM8776_DACWL_16 0x000 -#define WM8776_DACWL_20 0x010 -#define WM8776_DACWL_24 0x020 -#define WM8776_DACWL_32 0x030 - -/* ADCIFCTRL */ -#define WM8776_ADCFMT_MASK 0x003 -#define WM8776_ADCFMT_RJUST 0x000 -#define WM8776_ADCFMT_LJUST 0x001 -#define WM8776_ADCFMT_I2S 0x002 -#define WM8776_ADCFMT_DSP 0x003 -#define WM8776_ADCLRP 0x004 -#define WM8776_ADCBCP 0x008 -#define WM8776_ADCWL_MASK 0x030 -#define WM8776_ADCWL_16 0x000 -#define WM8776_ADCWL_20 0x010 -#define WM8776_ADCWL_24 0x020 -#define WM8776_ADCWL_32 0x030 -#define WM8776_ADCMCLK 0x040 -#define WM8776_ADCHPD 0x100 - -/* MSTRCTRL */ -#define WM8776_ADCRATE_MASK 0x007 -#define WM8776_ADCRATE_256 0x002 -#define WM8776_ADCRATE_384 0x003 -#define WM8776_ADCRATE_512 0x004 -#define WM8776_ADCRATE_768 0x005 -#define WM8776_ADCOSR 0x008 -#define WM8776_DACRATE_MASK 0x070 -#define WM8776_DACRATE_128 0x000 -#define WM8776_DACRATE_192 0x010 -#define WM8776_DACRATE_256 0x020 -#define WM8776_DACRATE_384 0x030 -#define WM8776_DACRATE_512 0x040 -#define WM8776_DACRATE_768 0x050 -#define WM8776_DACMS 0x080 -#define WM8776_ADCMS 0x100 - -/* PWRDOWN */ -#define WM8776_PDWN 0x001 -#define WM8776_ADCPD 0x002 -#define WM8776_DACPD 0x004 -#define WM8776_HPPD 0x008 -#define WM8776_AINPD 0x040 - -/* ADCLVOL/ADCRVOL */ -#define WM8776_AGMASK 0x0ff -#define WM8776_ZCA 0x100 - -/* ALCCTRL1 */ -#define WM8776_LCT_MASK 0x00f -#define WM8776_MAXGAIN_MASK 0x070 -#define WM8776_LCSEL_MASK 0x180 -#define WM8776_LCSEL_LIMITER 0x000 -#define WM8776_LCSEL_ALC_RIGHT 0x080 -#define WM8776_LCSEL_ALC_LEFT 0x100 -#define WM8776_LCSEL_ALC_STEREO 0x180 - -/* ALCCTRL2 */ -#define WM8776_HLD_MASK 0x00f -#define WM8776_ALCZC 0x080 -#define WM8776_LCEN 0x100 - -/* ALCCTRL3 */ -#define WM8776_ATK_MASK 0x00f -#define WM8776_DCY_MASK 0x0f0 - -/* NOISEGATE */ -#define WM8776_NGAT 0x001 -#define WM8776_NGTH_MASK 0x01c - -/* LIMITER */ -#define WM8776_MAXATTEN_MASK 0x00f -#define WM8776_TRANWIN_MASK 0x070 - -/* ADCMUX */ -#define WM8776_AMX_MASK 0x01f -#define WM8776_MUTERA 0x040 -#define WM8776_MUTELA 0x080 -#define WM8776_LRBOTH 0x100 - -/* OUTMUX */ -#define WM8776_MX_DAC 0x001 -#define WM8776_MX_AUX 0x002 -#define WM8776_MX_BYPASS 0x004 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/wm8785.h b/ANDROID_3.4.5/sound/pci/oxygen/wm8785.h deleted file mode 100644 index 8c23e315..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/wm8785.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef WM8785_H_INCLUDED -#define WM8785_H_INCLUDED - -#define WM8785_R0 0 -#define WM8785_R1 1 -#define WM8785_R2 2 -#define WM8785_R7 7 - -/* R0 */ -#define WM8785_MCR_MASK 0x007 -#define WM8785_MCR_SLAVE 0x000 -#define WM8785_MCR_MASTER_128 0x001 -#define WM8785_MCR_MASTER_192 0x002 -#define WM8785_MCR_MASTER_256 0x003 -#define WM8785_MCR_MASTER_384 0x004 -#define WM8785_MCR_MASTER_512 0x005 -#define WM8785_MCR_MASTER_768 0x006 -#define WM8785_OSR_MASK 0x018 -#define WM8785_OSR_SINGLE 0x000 -#define WM8785_OSR_DOUBLE 0x008 -#define WM8785_OSR_QUAD 0x010 -#define WM8785_FORMAT_MASK 0x060 -#define WM8785_FORMAT_RJUST 0x000 -#define WM8785_FORMAT_LJUST 0x020 -#define WM8785_FORMAT_I2S 0x040 -#define WM8785_FORMAT_DSP 0x060 -/* R1 */ -#define WM8785_WL_MASK 0x003 -#define WM8785_WL_16 0x000 -#define WM8785_WL_20 0x001 -#define WM8785_WL_24 0x002 -#define WM8785_WL_32 0x003 -#define WM8785_LRP 0x004 -#define WM8785_BCLKINV 0x008 -#define WM8785_LRSWAP 0x010 -#define WM8785_DEVNO_MASK 0x0e0 -/* R2 */ -#define WM8785_HPFR 0x001 -#define WM8785_HPFL 0x002 -#define WM8785_SDODIS 0x004 -#define WM8785_PWRDNR 0x008 -#define WM8785_PWRDNL 0x010 -#define WM8785_TDM_MASK 0x1c0 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar.h b/ANDROID_3.4.5/sound/pci/oxygen/xonar.h deleted file mode 100644 index 0434c207..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef XONAR_H_INCLUDED -#define XONAR_H_INCLUDED - -#include "oxygen.h" - -struct xonar_generic { - unsigned int anti_pop_delay; - u16 output_enable_bit; - u8 ext_power_reg; - u8 ext_power_int_reg; - u8 ext_power_bit; - u8 has_power; -}; - -struct xonar_hdmi { - u8 params[5]; -}; - -/* generic helper functions */ - -void xonar_enable_output(struct oxygen *chip); -void xonar_disable_output(struct oxygen *chip); -void xonar_init_ext_power(struct oxygen *chip); -void xonar_init_cs53x1(struct oxygen *chip); -void xonar_set_cs53x1_params(struct oxygen *chip, - struct snd_pcm_hw_params *params); - -#define XONAR_GPIO_BIT_INVERT (1 << 16) -int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value); -int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value); - -/* model-specific card drivers */ - -int get_xonar_pcm179x_model(struct oxygen *chip, - const struct pci_device_id *id); -int get_xonar_cs43xx_model(struct oxygen *chip, - const struct pci_device_id *id); -int get_xonar_wm87x6_model(struct oxygen *chip, - const struct pci_device_id *id); - -/* HDMI helper functions */ - -void xonar_hdmi_init(struct oxygen *chip, struct xonar_hdmi *data); -void xonar_hdmi_cleanup(struct oxygen *chip); -void xonar_hdmi_resume(struct oxygen *chip, struct xonar_hdmi *hdmi); -void xonar_hdmi_pcm_hardware_filter(unsigned int channel, - struct snd_pcm_hardware *hardware); -void xonar_set_hdmi_params(struct oxygen *chip, struct xonar_hdmi *hdmi, - struct snd_pcm_hw_params *params); -void xonar_hdmi_uart_input(struct oxygen *chip); - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_cs43xx.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_cs43xx.c deleted file mode 100644 index c8febf4b..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_cs43xx.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * card driver for models with CS4398/CS4362A DACs (Xonar D1/DX) - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; if not, see . - */ - -/* - * Xonar D1/DX - * ----------- - * - * CMI8788: - * - * I²C <-> CS4398 (addr 1001111) (front) - * <-> CS4362A (addr 0011000) (surround, center/LFE, back) - * - * GPI 0 <- external power present (DX only) - * - * GPIO 0 -> enable output to speakers - * GPIO 1 -> route output to front panel - * GPIO 2 -> M0 of CS5361 - * GPIO 3 -> M1 of CS5361 - * GPIO 6 -> ? - * GPIO 7 -> ? - * GPIO 8 -> route input jack to line-in (0) or mic-in (1) - * - * CM9780: - * - * LINE_OUT -> input of ADC - * - * AUX_IN <- aux - * MIC_IN <- mic - * FMIC_IN <- front mic - * - * GPO 0 -> route line-in (0) or AC97 output (1) to CS5361 input - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "xonar.h" -#include "cm9780.h" -#include "cs4398.h" -#include "cs4362a.h" - -#define GPI_EXT_POWER 0x01 -#define GPIO_D1_OUTPUT_ENABLE 0x0001 -#define GPIO_D1_FRONT_PANEL 0x0002 -#define GPIO_D1_MAGIC 0x00c0 -#define GPIO_D1_INPUT_ROUTE 0x0100 - -#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ -#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ - -struct xonar_cs43xx { - struct xonar_generic generic; - u8 cs4398_regs[8]; - u8 cs4362a_regs[15]; -}; - -static void cs4398_write(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_cs43xx *data = chip->model_data; - - oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value); - if (reg < ARRAY_SIZE(data->cs4398_regs)) - data->cs4398_regs[reg] = value; -} - -static void cs4398_write_cached(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_cs43xx *data = chip->model_data; - - if (value != data->cs4398_regs[reg]) - cs4398_write(chip, reg, value); -} - -static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_cs43xx *data = chip->model_data; - - oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value); - if (reg < ARRAY_SIZE(data->cs4362a_regs)) - data->cs4362a_regs[reg] = value; -} - -static void cs4362a_write_cached(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_cs43xx *data = chip->model_data; - - if (value != data->cs4362a_regs[reg]) - cs4362a_write(chip, reg, value); -} - -static void cs43xx_registers_init(struct oxygen *chip) -{ - struct xonar_cs43xx *data = chip->model_data; - unsigned int i; - - /* set CPEN (control port mode) and power down */ - cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN); - cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN); - /* configure */ - cs4398_write(chip, 2, data->cs4398_regs[2]); - cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L); - cs4398_write(chip, 4, data->cs4398_regs[4]); - cs4398_write(chip, 5, data->cs4398_regs[5]); - cs4398_write(chip, 6, data->cs4398_regs[6]); - cs4398_write(chip, 7, data->cs4398_regs[7]); - cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST); - cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE | - CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP); - cs4362a_write(chip, 0x04, data->cs4362a_regs[0x04]); - cs4362a_write(chip, 0x05, 0); - for (i = 6; i <= 14; ++i) - cs4362a_write(chip, i, data->cs4362a_regs[i]); - /* clear power down */ - cs4398_write(chip, 8, CS4398_CPEN); - cs4362a_write(chip, 0x01, CS4362A_CPEN); -} - -static void xonar_d1_init(struct oxygen *chip) -{ - struct xonar_cs43xx *data = chip->model_data; - - data->generic.anti_pop_delay = 800; - data->generic.output_enable_bit = GPIO_D1_OUTPUT_ENABLE; - data->cs4398_regs[2] = - CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; - data->cs4398_regs[4] = CS4398_MUTEP_LOW | - CS4398_MUTE_B | CS4398_MUTE_A | CS4398_PAMUTE; - data->cs4398_regs[5] = 60 * 2; - data->cs4398_regs[6] = 60 * 2; - data->cs4398_regs[7] = CS4398_RMP_DN | CS4398_RMP_UP | - CS4398_ZERO_CROSS | CS4398_SOFT_RAMP; - data->cs4362a_regs[4] = CS4362A_RMP_DN | CS4362A_DEM_NONE; - data->cs4362a_regs[6] = CS4362A_FM_SINGLE | - CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; - data->cs4362a_regs[7] = 60 | CS4362A_MUTE; - data->cs4362a_regs[8] = 60 | CS4362A_MUTE; - data->cs4362a_regs[9] = data->cs4362a_regs[6]; - data->cs4362a_regs[10] = 60 | CS4362A_MUTE; - data->cs4362a_regs[11] = 60 | CS4362A_MUTE; - data->cs4362a_regs[12] = data->cs4362a_regs[6]; - data->cs4362a_regs[13] = 60 | CS4362A_MUTE; - data->cs4362a_regs[14] = 60 | CS4362A_MUTE; - - oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, - OXYGEN_2WIRE_LENGTH_8 | - OXYGEN_2WIRE_INTERRUPT_MASK | - OXYGEN_2WIRE_SPEED_FAST); - - cs43xx_registers_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_D1_FRONT_PANEL | - GPIO_D1_MAGIC | - GPIO_D1_INPUT_ROUTE); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, - GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE); - - xonar_init_cs53x1(chip); - xonar_enable_output(chip); - - snd_component_add(chip->card, "CS4398"); - snd_component_add(chip->card, "CS4362A"); - snd_component_add(chip->card, "CS5361"); -} - -static void xonar_dx_init(struct oxygen *chip) -{ - struct xonar_cs43xx *data = chip->model_data; - - data->generic.ext_power_reg = OXYGEN_GPI_DATA; - data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; - data->generic.ext_power_bit = GPI_EXT_POWER; - xonar_init_ext_power(chip); - xonar_d1_init(chip); -} - -static void xonar_d1_cleanup(struct oxygen *chip) -{ - xonar_disable_output(chip); - cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN); - oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC); -} - -static void xonar_d1_suspend(struct oxygen *chip) -{ - xonar_d1_cleanup(chip); -} - -static void xonar_d1_resume(struct oxygen *chip) -{ - oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC); - msleep(1); - cs43xx_registers_init(chip); - xonar_enable_output(chip); -} - -static void set_cs43xx_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct xonar_cs43xx *data = chip->model_data; - u8 cs4398_fm, cs4362a_fm; - - if (params_rate(params) <= 50000) { - cs4398_fm = CS4398_FM_SINGLE; - cs4362a_fm = CS4362A_FM_SINGLE; - } else if (params_rate(params) <= 100000) { - cs4398_fm = CS4398_FM_DOUBLE; - cs4362a_fm = CS4362A_FM_DOUBLE; - } else { - cs4398_fm = CS4398_FM_QUAD; - cs4362a_fm = CS4362A_FM_QUAD; - } - cs4398_fm |= CS4398_DEM_NONE | CS4398_DIF_LJUST; - cs4398_write_cached(chip, 2, cs4398_fm); - cs4362a_fm |= data->cs4362a_regs[6] & ~CS4362A_FM_MASK; - cs4362a_write_cached(chip, 6, cs4362a_fm); - cs4362a_write_cached(chip, 12, cs4362a_fm); - cs4362a_fm &= CS4362A_FM_MASK; - cs4362a_fm |= data->cs4362a_regs[9] & ~CS4362A_FM_MASK; - cs4362a_write_cached(chip, 9, cs4362a_fm); -} - -static void update_cs4362a_volumes(struct oxygen *chip) -{ - unsigned int i; - u8 mute; - - mute = chip->dac_mute ? CS4362A_MUTE : 0; - for (i = 0; i < 6; ++i) - cs4362a_write_cached(chip, 7 + i + i / 2, - (127 - chip->dac_volume[2 + i]) | mute); -} - -static void update_cs43xx_volume(struct oxygen *chip) -{ - cs4398_write_cached(chip, 5, (127 - chip->dac_volume[0]) * 2); - cs4398_write_cached(chip, 6, (127 - chip->dac_volume[1]) * 2); - update_cs4362a_volumes(chip); -} - -static void update_cs43xx_mute(struct oxygen *chip) -{ - u8 reg; - - reg = CS4398_MUTEP_LOW | CS4398_PAMUTE; - if (chip->dac_mute) - reg |= CS4398_MUTE_B | CS4398_MUTE_A; - cs4398_write_cached(chip, 4, reg); - update_cs4362a_volumes(chip); -} - -static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed) -{ - struct xonar_cs43xx *data = chip->model_data; - u8 reg; - - reg = data->cs4362a_regs[9] & ~CS4362A_ATAPI_MASK; - if (mixed) - reg |= CS4362A_ATAPI_B_LR | CS4362A_ATAPI_A_LR; - else - reg |= CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; - cs4362a_write_cached(chip, 9, reg); -} - -static const struct snd_kcontrol_new front_panel_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Front Panel Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = xonar_gpio_bit_switch_get, - .put = xonar_gpio_bit_switch_put, - .private_value = GPIO_D1_FRONT_PANEL, -}; - -static int rolloff_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "Fast Roll-off", "Slow Roll-off" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int rolloff_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_cs43xx *data = chip->model_data; - - value->value.enumerated.item[0] = - (data->cs4398_regs[7] & CS4398_FILT_SEL) != 0; - return 0; -} - -static int rolloff_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_cs43xx *data = chip->model_data; - int changed; - u8 reg; - - mutex_lock(&chip->mutex); - reg = data->cs4398_regs[7]; - if (value->value.enumerated.item[0]) - reg |= CS4398_FILT_SEL; - else - reg &= ~CS4398_FILT_SEL; - changed = reg != data->cs4398_regs[7]; - if (changed) { - cs4398_write(chip, 7, reg); - if (reg & CS4398_FILT_SEL) - reg = data->cs4362a_regs[0x04] | CS4362A_FILT_SEL; - else - reg = data->cs4362a_regs[0x04] & ~CS4362A_FILT_SEL; - cs4362a_write(chip, 0x04, reg); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new rolloff_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Filter Playback Enum", - .info = rolloff_info, - .get = rolloff_get, - .put = rolloff_put, -}; - -static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip, - unsigned int reg, unsigned int mute) -{ - if (reg == AC97_LINE) { - spin_lock_irq(&chip->reg_lock); - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - mute ? GPIO_D1_INPUT_ROUTE : 0, - GPIO_D1_INPUT_ROUTE); - spin_unlock_irq(&chip->reg_lock); - } -} - -static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); - -static int xonar_d1_mixer_init(struct oxygen *chip) -{ - int err; - - err = snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); - if (err < 0) - return err; - return 0; -} - -static void dump_cs4362a_registers(struct xonar_cs43xx *data, - struct snd_info_buffer *buffer) -{ - unsigned int i; - - snd_iprintf(buffer, "\nCS4362A:"); - for (i = 1; i <= 14; ++i) - snd_iprintf(buffer, " %02x", data->cs4362a_regs[i]); - snd_iprintf(buffer, "\n"); -} - -static void dump_d1_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_cs43xx *data = chip->model_data; - unsigned int i; - - snd_iprintf(buffer, "\nCS4398: 7?"); - for (i = 2; i < 8; ++i) - snd_iprintf(buffer, " %02x", data->cs4398_regs[i]); - snd_iprintf(buffer, "\n"); - dump_cs4362a_registers(data, buffer); -} - -static const struct oxygen_model model_xonar_d1 = { - .longname = "Asus Virtuoso 100", - .chip = "AV200", - .init = xonar_d1_init, - .mixer_init = xonar_d1_mixer_init, - .cleanup = xonar_d1_cleanup, - .suspend = xonar_d1_suspend, - .resume = xonar_d1_resume, - .set_dac_params = set_cs43xx_params, - .set_adc_params = xonar_set_cs53x1_params, - .update_dac_volume = update_cs43xx_volume, - .update_dac_mute = update_cs43xx_mute, - .update_center_lfe_mix = update_cs43xx_center_lfe_mix, - .ac97_switch = xonar_d1_line_mic_ac97_switch, - .dump_registers = dump_d1_registers, - .dac_tlv = cs4362a_db_scale, - .model_data_size = sizeof(struct xonar_cs43xx), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF | - AC97_FMIC_SWITCH, - .dac_channels_pcm = 8, - .dac_channels_mixer = 8, - .dac_volume_min = 127 - 60, - .dac_volume_max = 127, - .function_flags = OXYGEN_FUNCTION_2WIRE, - .dac_mclks = OXYGEN_MCLKS(256, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -int __devinit get_xonar_cs43xx_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - switch (id->subdevice) { - case 0x834f: - chip->model = model_xonar_d1; - chip->model.shortname = "Xonar D1"; - break; - case 0x8275: - case 0x8327: - chip->model = model_xonar_d1; - chip->model.shortname = "Xonar DX"; - chip->model.init = xonar_dx_init; - break; - default: - return -EINVAL; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.c deleted file mode 100644 index 793bdf03..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * card driver for the Xonar DG - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; if not, see . - */ - -/* - * Xonar DG - * -------- - * - * CMI8788: - * - * SPI 0 -> CS4245 - * - * I²S 1 -> CS4245 - * I²S 2 -> CS4361 (center/LFE) - * I²S 3 -> CS4361 (surround) - * I²S 4 -> CS4361 (front) - * - * GPIO 3 <- ? - * GPIO 4 <- headphone detect - * GPIO 5 -> route input jack to line-in (0) or mic-in (1) - * GPIO 6 -> route input jack to line-in (0) or mic-in (1) - * GPIO 7 -> enable rear headphone amp - * GPIO 8 -> enable output to speakers - * - * CS4245: - * - * input 1 <- aux - * input 2 <- front mic - * input 4 <- line/mic - * DAC out -> headphones - * aux out -> front panel headphones - */ - -#include -#include -#include -#include -#include -#include -#include -#include "oxygen.h" -#include "xonar_dg.h" -#include "cs4245.h" - -#define GPIO_MAGIC 0x0008 -#define GPIO_HP_DETECT 0x0010 -#define GPIO_INPUT_ROUTE 0x0060 -#define GPIO_HP_REAR 0x0080 -#define GPIO_OUTPUT_ENABLE 0x0100 - -struct dg { - unsigned int output_sel; - s8 input_vol[4][2]; - unsigned int input_sel; - u8 hp_vol_att; - u8 cs4245_regs[0x11]; -}; - -static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value) -{ - struct dg *data = chip->model_data; - - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_3 | - OXYGEN_SPI_CLOCK_1280 | - (0 << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_HI, - CS4245_SPI_ADDRESS | - CS4245_SPI_WRITE | - (reg << 8) | value); - data->cs4245_regs[reg] = value; -} - -static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value) -{ - struct dg *data = chip->model_data; - - if (value != data->cs4245_regs[reg]) - cs4245_write(chip, reg, value); -} - -static void cs4245_registers_init(struct oxygen *chip) -{ - struct dg *data = chip->model_data; - - cs4245_write(chip, CS4245_POWER_CTRL, CS4245_PDN); - cs4245_write(chip, CS4245_DAC_CTRL_1, - data->cs4245_regs[CS4245_DAC_CTRL_1]); - cs4245_write(chip, CS4245_ADC_CTRL, - data->cs4245_regs[CS4245_ADC_CTRL]); - cs4245_write(chip, CS4245_SIGNAL_SEL, - data->cs4245_regs[CS4245_SIGNAL_SEL]); - cs4245_write(chip, CS4245_PGA_B_CTRL, - data->cs4245_regs[CS4245_PGA_B_CTRL]); - cs4245_write(chip, CS4245_PGA_A_CTRL, - data->cs4245_regs[CS4245_PGA_A_CTRL]); - cs4245_write(chip, CS4245_ANALOG_IN, - data->cs4245_regs[CS4245_ANALOG_IN]); - cs4245_write(chip, CS4245_DAC_A_CTRL, - data->cs4245_regs[CS4245_DAC_A_CTRL]); - cs4245_write(chip, CS4245_DAC_B_CTRL, - data->cs4245_regs[CS4245_DAC_B_CTRL]); - cs4245_write(chip, CS4245_DAC_CTRL_2, - CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC); - cs4245_write(chip, CS4245_INT_MASK, 0); - cs4245_write(chip, CS4245_POWER_CTRL, 0); -} - -static void cs4245_init(struct oxygen *chip) -{ - struct dg *data = chip->model_data; - - data->cs4245_regs[CS4245_DAC_CTRL_1] = - CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST; - data->cs4245_regs[CS4245_ADC_CTRL] = - CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST; - data->cs4245_regs[CS4245_SIGNAL_SEL] = - CS4245_A_OUT_SEL_HIZ | CS4245_ASYNCH; - data->cs4245_regs[CS4245_PGA_B_CTRL] = 0; - data->cs4245_regs[CS4245_PGA_A_CTRL] = 0; - data->cs4245_regs[CS4245_ANALOG_IN] = - CS4245_PGA_SOFT | CS4245_PGA_ZERO | CS4245_SEL_INPUT_4; - data->cs4245_regs[CS4245_DAC_A_CTRL] = 0; - data->cs4245_regs[CS4245_DAC_B_CTRL] = 0; - cs4245_registers_init(chip); - snd_component_add(chip->card, "CS4245"); -} - -static void dg_output_enable(struct oxygen *chip) -{ - msleep(2500); - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); -} - -static void dg_init(struct oxygen *chip) -{ - struct dg *data = chip->model_data; - - data->output_sel = 0; - data->input_sel = 3; - data->hp_vol_att = 2 * 16; - - cs4245_init(chip); - - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_MAGIC | GPIO_HP_DETECT); - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_INPUT_ROUTE | GPIO_HP_REAR | GPIO_OUTPUT_ENABLE); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, - GPIO_INPUT_ROUTE | GPIO_HP_REAR); - dg_output_enable(chip); -} - -static void dg_cleanup(struct oxygen *chip) -{ - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); -} - -static void dg_suspend(struct oxygen *chip) -{ - dg_cleanup(chip); -} - -static void dg_resume(struct oxygen *chip) -{ - cs4245_registers_init(chip); - dg_output_enable(chip); -} - -static void set_cs4245_dac_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct dg *data = chip->model_data; - u8 value; - - value = data->cs4245_regs[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK; - if (params_rate(params) <= 50000) - value |= CS4245_DAC_FM_SINGLE; - else if (params_rate(params) <= 100000) - value |= CS4245_DAC_FM_DOUBLE; - else - value |= CS4245_DAC_FM_QUAD; - cs4245_write_cached(chip, CS4245_DAC_CTRL_1, value); -} - -static void set_cs4245_adc_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct dg *data = chip->model_data; - u8 value; - - value = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK; - if (params_rate(params) <= 50000) - value |= CS4245_ADC_FM_SINGLE; - else if (params_rate(params) <= 100000) - value |= CS4245_ADC_FM_DOUBLE; - else - value |= CS4245_ADC_FM_QUAD; - cs4245_write_cached(chip, CS4245_ADC_CTRL, value); -} - -static inline unsigned int shift_bits(unsigned int value, - unsigned int shift_from, - unsigned int shift_to, - unsigned int mask) -{ - if (shift_from < shift_to) - return (value << (shift_to - shift_from)) & mask; - else - return (value >> (shift_from - shift_to)) & mask; -} - -static unsigned int adjust_dg_dac_routing(struct oxygen *chip, - unsigned int play_routing) -{ - return (play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC2_SOURCE_SHIFT, - OXYGEN_PLAY_DAC1_SOURCE_SHIFT, - OXYGEN_PLAY_DAC1_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC1_SOURCE_SHIFT, - OXYGEN_PLAY_DAC2_SOURCE_SHIFT, - OXYGEN_PLAY_DAC2_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC0_SOURCE_SHIFT, - OXYGEN_PLAY_DAC3_SOURCE_SHIFT, - OXYGEN_PLAY_DAC3_SOURCE_MASK); -} - -static int output_switch_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "Speakers", "Headphones", "FP Headphones" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int output_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - - mutex_lock(&chip->mutex); - value->value.enumerated.item[0] = data->output_sel; - mutex_unlock(&chip->mutex); - return 0; -} - -static int output_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - u8 reg; - int changed; - - if (value->value.enumerated.item[0] > 2) - return -EINVAL; - - mutex_lock(&chip->mutex); - changed = value->value.enumerated.item[0] != data->output_sel; - if (changed) { - data->output_sel = value->value.enumerated.item[0]; - - reg = data->cs4245_regs[CS4245_SIGNAL_SEL] & - ~CS4245_A_OUT_SEL_MASK; - reg |= data->output_sel == 2 ? - CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; - cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg); - - cs4245_write_cached(chip, CS4245_DAC_A_CTRL, - data->output_sel ? data->hp_vol_att : 0); - cs4245_write_cached(chip, CS4245_DAC_B_CTRL, - data->output_sel ? data->hp_vol_att : 0); - - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - data->output_sel == 1 ? GPIO_HP_REAR : 0, - GPIO_HP_REAR); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int hp_volume_offset_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "< 64 ohms", "64-150 ohms", "150-300 ohms" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int hp_volume_offset_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - - mutex_lock(&chip->mutex); - if (data->hp_vol_att > 2 * 7) - value->value.enumerated.item[0] = 0; - else if (data->hp_vol_att > 0) - value->value.enumerated.item[0] = 1; - else - value->value.enumerated.item[0] = 2; - mutex_unlock(&chip->mutex); - return 0; -} - -static int hp_volume_offset_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - static const s8 atts[3] = { 2 * 16, 2 * 7, 0 }; - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - s8 att; - int changed; - - if (value->value.enumerated.item[0] > 2) - return -EINVAL; - att = atts[value->value.enumerated.item[0]]; - mutex_lock(&chip->mutex); - changed = att != data->hp_vol_att; - if (changed) { - data->hp_vol_att = att; - if (data->output_sel) { - cs4245_write_cached(chip, CS4245_DAC_A_CTRL, att); - cs4245_write_cached(chip, CS4245_DAC_B_CTRL, att); - } - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int input_vol_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 2 * -12; - info->value.integer.max = 2 * 12; - return 0; -} - -static int input_vol_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - unsigned int idx = ctl->private_value; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = data->input_vol[idx][0]; - value->value.integer.value[1] = data->input_vol[idx][1]; - mutex_unlock(&chip->mutex); - return 0; -} - -static int input_vol_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - unsigned int idx = ctl->private_value; - int changed = 0; - - if (value->value.integer.value[0] < 2 * -12 || - value->value.integer.value[0] > 2 * 12 || - value->value.integer.value[1] < 2 * -12 || - value->value.integer.value[1] > 2 * 12) - return -EINVAL; - mutex_lock(&chip->mutex); - changed = data->input_vol[idx][0] != value->value.integer.value[0] || - data->input_vol[idx][1] != value->value.integer.value[1]; - if (changed) { - data->input_vol[idx][0] = value->value.integer.value[0]; - data->input_vol[idx][1] = value->value.integer.value[1]; - if (idx == data->input_sel) { - cs4245_write_cached(chip, CS4245_PGA_A_CTRL, - data->input_vol[idx][0]); - cs4245_write_cached(chip, CS4245_PGA_B_CTRL, - data->input_vol[idx][1]); - } - } - mutex_unlock(&chip->mutex); - return changed; -} - -static DECLARE_TLV_DB_SCALE(cs4245_pga_db_scale, -1200, 50, 0); - -static int input_sel_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[4] = { - "Mic", "Aux", "Front Mic", "Line" - }; - - return snd_ctl_enum_info(info, 1, 4, names); -} - -static int input_sel_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - - mutex_lock(&chip->mutex); - value->value.enumerated.item[0] = data->input_sel; - mutex_unlock(&chip->mutex); - return 0; -} - -static int input_sel_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - static const u8 sel_values[4] = { - CS4245_SEL_MIC, - CS4245_SEL_INPUT_1, - CS4245_SEL_INPUT_2, - CS4245_SEL_INPUT_4 - }; - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - int changed; - - if (value->value.enumerated.item[0] > 3) - return -EINVAL; - - mutex_lock(&chip->mutex); - changed = value->value.enumerated.item[0] != data->input_sel; - if (changed) { - data->input_sel = value->value.enumerated.item[0]; - - cs4245_write(chip, CS4245_ANALOG_IN, - (data->cs4245_regs[CS4245_ANALOG_IN] & - ~CS4245_SEL_MASK) | - sel_values[data->input_sel]); - - cs4245_write_cached(chip, CS4245_PGA_A_CTRL, - data->input_vol[data->input_sel][0]); - cs4245_write_cached(chip, CS4245_PGA_B_CTRL, - data->input_vol[data->input_sel][1]); - - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - data->input_sel ? 0 : GPIO_INPUT_ROUTE, - GPIO_INPUT_ROUTE); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { "Active", "Frozen" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - - value->value.enumerated.item[0] = - !!(data->cs4245_regs[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE); - return 0; -} - -static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - u8 reg; - int changed; - - mutex_lock(&chip->mutex); - reg = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; - if (value->value.enumerated.item[0]) - reg |= CS4245_HPF_FREEZE; - changed = reg != data->cs4245_regs[CS4245_ADC_CTRL]; - if (changed) - cs4245_write(chip, CS4245_ADC_CTRL, reg); - mutex_unlock(&chip->mutex); - return changed; -} - -#define INPUT_VOLUME(xname, index) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .info = input_vol_info, \ - .get = input_vol_get, \ - .put = input_vol_put, \ - .tlv = { .p = cs4245_pga_db_scale }, \ - .private_value = index, \ -} -static const struct snd_kcontrol_new dg_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Output Playback Enum", - .info = output_switch_info, - .get = output_switch_get, - .put = output_switch_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphones Impedance Playback Enum", - .info = hp_volume_offset_info, - .get = hp_volume_offset_get, - .put = hp_volume_offset_put, - }, - INPUT_VOLUME("Mic Capture Volume", 0), - INPUT_VOLUME("Aux Capture Volume", 1), - INPUT_VOLUME("Front Mic Capture Volume", 2), - INPUT_VOLUME("Line Capture Volume", 3), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = input_sel_info, - .get = input_sel_get, - .put = input_sel_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC High-pass Filter Capture Enum", - .info = hpf_info, - .get = hpf_get, - .put = hpf_put, - }, -}; - -static int dg_control_filter(struct snd_kcontrol_new *template) -{ - if (!strncmp(template->name, "Master Playback ", 16)) - return 1; - return 0; -} - -static int dg_mixer_init(struct oxygen *chip) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(dg_controls); ++i) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&dg_controls[i], chip)); - if (err < 0) - return err; - } - return 0; -} - -static void dump_cs4245_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct dg *data = chip->model_data; - unsigned int i; - - snd_iprintf(buffer, "\nCS4245:"); - for (i = 1; i <= 0x10; ++i) - snd_iprintf(buffer, " %02x", data->cs4245_regs[i]); - snd_iprintf(buffer, "\n"); -} - -struct oxygen_model model_xonar_dg = { - .shortname = "Xonar DG", - .longname = "C-Media Oxygen HD Audio", - .chip = "CMI8786", - .init = dg_init, - .control_filter = dg_control_filter, - .mixer_init = dg_mixer_init, - .cleanup = dg_cleanup, - .suspend = dg_suspend, - .resume = dg_resume, - .set_dac_params = set_cs4245_dac_params, - .set_adc_params = set_cs4245_adc_params, - .adjust_dac_routing = adjust_dg_dac_routing, - .dump_registers = dump_cs4245_registers, - .model_data_size = sizeof(struct dg), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF, - .dac_channels_pcm = 6, - .dac_channels_mixer = 0, - .function_flags = OXYGEN_FUNCTION_SPI, - .dac_mclks = OXYGEN_MCLKS(256, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.h b/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.h deleted file mode 100644 index 5688d786..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef XONAR_DG_H_INCLUDED -#define XONAR_DG_H_INCLUDED - -#include "oxygen.h" - -extern struct oxygen_model model_xonar_dg; - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_hdmi.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_hdmi.c deleted file mode 100644 index 136dac6a..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_hdmi.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * helper functions for HDMI models (Xonar HDAV1.3/HDAV1.3 Slim) - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; if not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "xonar.h" - -static void hdmi_write_command(struct oxygen *chip, u8 command, - unsigned int count, const u8 *params) -{ - unsigned int i; - u8 checksum; - - oxygen_write_uart(chip, 0xfb); - oxygen_write_uart(chip, 0xef); - oxygen_write_uart(chip, command); - oxygen_write_uart(chip, count); - for (i = 0; i < count; ++i) - oxygen_write_uart(chip, params[i]); - checksum = 0xfb + 0xef + command + count; - for (i = 0; i < count; ++i) - checksum += params[i]; - oxygen_write_uart(chip, checksum); -} - -static void xonar_hdmi_init_commands(struct oxygen *chip, - struct xonar_hdmi *hdmi) -{ - u8 param; - - oxygen_reset_uart(chip); - param = 0; - hdmi_write_command(chip, 0x61, 1, ¶m); - param = 1; - hdmi_write_command(chip, 0x74, 1, ¶m); - hdmi_write_command(chip, 0x54, 5, hdmi->params); -} - -void xonar_hdmi_init(struct oxygen *chip, struct xonar_hdmi *hdmi) -{ - hdmi->params[1] = IEC958_AES3_CON_FS_48000; - hdmi->params[4] = 1; - xonar_hdmi_init_commands(chip, hdmi); -} - -void xonar_hdmi_cleanup(struct oxygen *chip) -{ - u8 param = 0; - - hdmi_write_command(chip, 0x74, 1, ¶m); -} - -void xonar_hdmi_resume(struct oxygen *chip, struct xonar_hdmi *hdmi) -{ - xonar_hdmi_init_commands(chip, hdmi); -} - -void xonar_hdmi_pcm_hardware_filter(unsigned int channel, - struct snd_pcm_hardware *hardware) -{ - if (channel == PCM_MULTICH) { - hardware->rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000; - hardware->rate_min = 44100; - } -} - -void xonar_set_hdmi_params(struct oxygen *chip, struct xonar_hdmi *hdmi, - struct snd_pcm_hw_params *params) -{ - hdmi->params[0] = 0; /* 1 = non-audio */ - switch (params_rate(params)) { - case 44100: - hdmi->params[1] = IEC958_AES3_CON_FS_44100; - break; - case 48000: - hdmi->params[1] = IEC958_AES3_CON_FS_48000; - break; - default: /* 96000 */ - hdmi->params[1] = IEC958_AES3_CON_FS_96000; - break; - case 192000: - hdmi->params[1] = IEC958_AES3_CON_FS_192000; - break; - } - hdmi->params[2] = params_channels(params) / 2 - 1; - if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) - hdmi->params[3] = 0; - else - hdmi->params[3] = 0xc0; - hdmi->params[4] = 1; /* ? */ - hdmi_write_command(chip, 0x54, 5, hdmi->params); -} - -void xonar_hdmi_uart_input(struct oxygen *chip) -{ - if (chip->uart_input_count >= 2 && - chip->uart_input[chip->uart_input_count - 2] == 'O' && - chip->uart_input[chip->uart_input_count - 1] == 'K') { - printk(KERN_DEBUG "message from HDMI chip received:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - chip->uart_input, chip->uart_input_count); - chip->uart_input_count = 0; - } -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_lib.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_lib.c deleted file mode 100644 index 0ebe7f59..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_lib.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * helper functions for Asus Xonar cards - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; if not, see . - */ - -#include -#include -#include -#include -#include -#include "xonar.h" - - -#define GPIO_CS53x1_M_MASK 0x000c -#define GPIO_CS53x1_M_SINGLE 0x0000 -#define GPIO_CS53x1_M_DOUBLE 0x0004 -#define GPIO_CS53x1_M_QUAD 0x0008 - - -void xonar_enable_output(struct oxygen *chip) -{ - struct xonar_generic *data = chip->model_data; - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit); - msleep(data->anti_pop_delay); - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit); -} - -void xonar_disable_output(struct oxygen *chip) -{ - struct xonar_generic *data = chip->model_data; - - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit); -} - -static void xonar_ext_power_gpio_changed(struct oxygen *chip) -{ - struct xonar_generic *data = chip->model_data; - u8 has_power; - - has_power = !!(oxygen_read8(chip, data->ext_power_reg) - & data->ext_power_bit); - if (has_power != data->has_power) { - data->has_power = has_power; - if (has_power) { - snd_printk(KERN_NOTICE "power restored\n"); - } else { - snd_printk(KERN_CRIT - "Hey! Don't unplug the power cable!\n"); - /* TODO: stop PCMs */ - } - } -} - -void xonar_init_ext_power(struct oxygen *chip) -{ - struct xonar_generic *data = chip->model_data; - - oxygen_set_bits8(chip, data->ext_power_int_reg, - data->ext_power_bit); - chip->interrupt_mask |= OXYGEN_INT_GPIO; - chip->model.gpio_changed = xonar_ext_power_gpio_changed; - data->has_power = !!(oxygen_read8(chip, data->ext_power_reg) - & data->ext_power_bit); -} - -void xonar_init_cs53x1(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK); - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK); -} - -void xonar_set_cs53x1_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - unsigned int value; - - if (params_rate(params) <= 54000) - value = GPIO_CS53x1_M_SINGLE; - else if (params_rate(params) <= 108000) - value = GPIO_CS53x1_M_DOUBLE; - else - value = GPIO_CS53x1_M_QUAD; - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - value, GPIO_CS53x1_M_MASK); -} - -int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 bit = ctl->private_value; - bool invert = ctl->private_value & XONAR_GPIO_BIT_INVERT; - - value->value.integer.value[0] = - !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & bit) ^ invert; - return 0; -} - -int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 bit = ctl->private_value; - bool invert = ctl->private_value & XONAR_GPIO_BIT_INVERT; - u16 old_bits, new_bits; - int changed; - - spin_lock_irq(&chip->reg_lock); - old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); - if (!!value->value.integer.value[0] ^ invert) - new_bits = old_bits | bit; - else - new_bits = old_bits & ~bit; - changed = new_bits != old_bits; - if (changed) - oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits); - spin_unlock_irq(&chip->reg_lock); - return changed; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_pcm179x.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_pcm179x.c deleted file mode 100644 index 8433aa7c..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_pcm179x.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * card driver for models with PCM1796 DACs (Xonar D2/D2X/HDAV1.3/ST/STX) - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; if not, see . - */ - -/* - * Xonar D2/D2X - * ------------ - * - * CMI8788: - * - * SPI 0 -> 1st PCM1796 (front) - * SPI 1 -> 2nd PCM1796 (surround) - * SPI 2 -> 3rd PCM1796 (center/LFE) - * SPI 4 -> 4th PCM1796 (back) - * - * GPIO 2 -> M0 of CS5381 - * GPIO 3 -> M1 of CS5381 - * GPIO 5 <- external power present (D2X only) - * GPIO 7 -> ALT - * GPIO 8 -> enable output to speakers - * - * CM9780: - * - * LINE_OUT -> input of ADC - * - * AUX_IN <- aux - * VIDEO_IN <- CD - * FMIC_IN <- mic - * - * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input - */ - -/* - * Xonar HDAV1.3 (Deluxe) - * ---------------------- - * - * CMI8788: - * - * I²C <-> PCM1796 (addr 1001100) (front) - * - * GPI 0 <- external power present - * - * GPIO 0 -> enable HDMI (0) or speaker (1) output - * GPIO 2 -> M0 of CS5381 - * GPIO 3 -> M1 of CS5381 - * GPIO 4 <- daughterboard detection - * GPIO 5 <- daughterboard detection - * GPIO 6 -> ? - * GPIO 7 -> ? - * GPIO 8 -> route input jack to line-in (0) or mic-in (1) - * - * UART <-> HDMI controller - * - * CM9780: - * - * LINE_OUT -> input of ADC - * - * AUX_IN <- aux - * CD_IN <- CD - * MIC_IN <- mic - * - * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input - * - * no daughterboard - * ---------------- - * - * GPIO 4 <- 1 - * - * H6 daughterboard - * ---------------- - * - * GPIO 4 <- 0 - * GPIO 5 <- 0 - * - * I²C <-> PCM1796 (addr 1001101) (surround) - * <-> PCM1796 (addr 1001110) (center/LFE) - * <-> PCM1796 (addr 1001111) (back) - * - * unknown daughterboard - * --------------------- - * - * GPIO 4 <- 0 - * GPIO 5 <- 1 - * - * I²C <-> CS4362A (addr 0011000) (surround, center/LFE, back) - */ - -/* - * Xonar Essence ST (Deluxe)/STX - * ----------------------------- - * - * CMI8788: - * - * I²C <-> PCM1792A (addr 1001100) - * <-> CS2000 (addr 1001110) (ST only) - * - * ADC1 MCLK -> REF_CLK of CS2000 (ST only) - * - * GPI 0 <- external power present (STX only) - * - * GPIO 0 -> enable output to speakers - * GPIO 1 -> route HP to front panel (0) or rear jack (1) - * GPIO 2 -> M0 of CS5381 - * GPIO 3 -> M1 of CS5381 - * GPIO 4 <- daughterboard detection - * GPIO 5 <- daughterboard detection - * GPIO 6 -> ? - * GPIO 7 -> route output to speaker jacks (0) or HP (1) - * GPIO 8 -> route input jack to line-in (0) or mic-in (1) - * - * PCM1792A: - * - * SCK <- CLK_OUT of CS2000 (ST only) - * - * CM9780: - * - * LINE_OUT -> input of ADC - * - * AUX_IN <- aux - * MIC_IN <- mic - * - * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input - * - * H6 daughterboard - * ---------------- - * - * GPIO 4 <- 0 - * GPIO 5 <- 0 - */ - -/* - * Xonar Xense - * ----------- - * - * CMI8788: - * - * I²C <-> PCM1796 (addr 1001100) (front) - * <-> CS4362A (addr 0011000) (surround, center/LFE, back) - * <-> CS2000 (addr 1001110) - * - * ADC1 MCLK -> REF_CLK of CS2000 - * - * GPI 0 <- external power present - * - * GPIO 0 -> enable output - * GPIO 1 -> route HP to front panel (0) or rear jack (1) - * GPIO 2 -> M0 of CS5381 - * GPIO 3 -> M1 of CS5381 - * GPIO 4 -> enable output - * GPIO 5 -> enable output - * GPIO 6 -> ? - * GPIO 7 -> route output to HP (0) or speaker (1) - * GPIO 8 -> route input jack to mic-in (0) or line-in (1) - * - * CM9780: - * - * LINE_OUT -> input of ADC - * - * AUX_IN <- aux - * VIDEO_IN <- ? - * FMIC_IN <- mic - * - * GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input - * GPO 1 -> route mic-in from input jack (0) or front panel header (1) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "xonar.h" -#include "cm9780.h" -#include "pcm1796.h" -#include "cs2000.h" - - -#define GPIO_D2X_EXT_POWER 0x0020 -#define GPIO_D2_ALT 0x0080 -#define GPIO_D2_OUTPUT_ENABLE 0x0100 - -#define GPI_EXT_POWER 0x01 -#define GPIO_INPUT_ROUTE 0x0100 - -#define GPIO_HDAV_OUTPUT_ENABLE 0x0001 -#define GPIO_HDAV_MAGIC 0x00c0 - -#define GPIO_DB_MASK 0x0030 -#define GPIO_DB_H6 0x0000 - -#define GPIO_ST_OUTPUT_ENABLE 0x0001 -#define GPIO_ST_HP_REAR 0x0002 -#define GPIO_ST_MAGIC 0x0040 -#define GPIO_ST_HP 0x0080 - -#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ -#define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ - -#define PCM1796_REG_BASE 16 - - -struct xonar_pcm179x { - struct xonar_generic generic; - unsigned int dacs; - u8 pcm1796_regs[4][5]; - unsigned int current_rate; - bool h6; - bool hp_active; - s8 hp_gain_offset; - bool has_cs2000; - u8 cs2000_regs[0x1f]; - bool broken_i2c; -}; - -struct xonar_hdav { - struct xonar_pcm179x pcm179x; - struct xonar_hdmi hdmi; -}; - - -static inline void pcm1796_write_spi(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - /* maps ALSA channel pair number to SPI output */ - static const u8 codec_map[4] = { - 0, 1, 2, 4 - }; - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (codec_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_HI, - (reg << 8) | value); -} - -static inline void pcm1796_write_i2c(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - oxygen_write_i2c(chip, I2C_DEVICE_PCM1796(codec), reg, value); -} - -static void pcm1796_write(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - struct xonar_pcm179x *data = chip->model_data; - - if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) == - OXYGEN_FUNCTION_SPI) - pcm1796_write_spi(chip, codec, reg, value); - else - pcm1796_write_i2c(chip, codec, reg, value); - if ((unsigned int)(reg - PCM1796_REG_BASE) - < ARRAY_SIZE(data->pcm1796_regs[codec])) - data->pcm1796_regs[codec][reg - PCM1796_REG_BASE] = value; -} - -static void pcm1796_write_cached(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - struct xonar_pcm179x *data = chip->model_data; - - if (value != data->pcm1796_regs[codec][reg - PCM1796_REG_BASE]) - pcm1796_write(chip, codec, reg, value); -} - -static void cs2000_write(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_pcm179x *data = chip->model_data; - - oxygen_write_i2c(chip, I2C_DEVICE_CS2000, reg, value); - data->cs2000_regs[reg] = value; -} - -static void cs2000_write_cached(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_pcm179x *data = chip->model_data; - - if (value != data->cs2000_regs[reg]) - cs2000_write(chip, reg, value); -} - -static void pcm1796_registers_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - s8 gain_offset; - - msleep(1); - gain_offset = data->hp_active ? data->hp_gain_offset : 0; - for (i = 0; i < data->dacs; ++i) { - /* set ATLD before ATL/ATR */ - pcm1796_write(chip, i, 18, - data->pcm1796_regs[0][18 - PCM1796_REG_BASE]); - pcm1796_write(chip, i, 16, chip->dac_volume[i * 2] - + gain_offset); - pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1] - + gain_offset); - pcm1796_write(chip, i, 19, - data->pcm1796_regs[0][19 - PCM1796_REG_BASE]); - pcm1796_write(chip, i, 20, - data->pcm1796_regs[0][20 - PCM1796_REG_BASE]); - pcm1796_write(chip, i, 21, 0); - gain_offset = 0; - } -} - -static void pcm1796_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = - PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD; - if (!data->broken_i2c) - data->pcm1796_regs[0][18 - PCM1796_REG_BASE] |= PCM1796_MUTE; - data->pcm1796_regs[0][19 - PCM1796_REG_BASE] = - PCM1796_FLT_SHARP | PCM1796_ATS_1; - data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = - data->h6 ? PCM1796_OS_64 : PCM1796_OS_128; - pcm1796_registers_init(chip); - data->current_rate = 48000; -} - -static void xonar_d2_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->generic.anti_pop_delay = 300; - data->generic.output_enable_bit = GPIO_D2_OUTPUT_ENABLE; - data->dacs = 4; - - pcm1796_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT); - - oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); - - xonar_init_cs53x1(chip); - xonar_enable_output(chip); - - snd_component_add(chip->card, "PCM1796"); - snd_component_add(chip->card, "CS5381"); -} - -static void xonar_d2x_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->generic.ext_power_reg = OXYGEN_GPIO_DATA; - data->generic.ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK; - data->generic.ext_power_bit = GPIO_D2X_EXT_POWER; - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER); - xonar_init_ext_power(chip); - xonar_d2_init(chip); -} - -static void xonar_hdav_init(struct oxygen *chip) -{ - struct xonar_hdav *data = chip->model_data; - - oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, - OXYGEN_2WIRE_LENGTH_8 | - OXYGEN_2WIRE_INTERRUPT_MASK | - OXYGEN_2WIRE_SPEED_STANDARD); - - data->pcm179x.generic.anti_pop_delay = 100; - data->pcm179x.generic.output_enable_bit = GPIO_HDAV_OUTPUT_ENABLE; - data->pcm179x.generic.ext_power_reg = OXYGEN_GPI_DATA; - data->pcm179x.generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; - data->pcm179x.generic.ext_power_bit = GPI_EXT_POWER; - data->pcm179x.dacs = chip->model.dac_channels_mixer / 2; - data->pcm179x.h6 = chip->model.dac_channels_mixer > 2; - - pcm1796_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_HDAV_MAGIC | GPIO_INPUT_ROUTE); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_INPUT_ROUTE); - - xonar_init_cs53x1(chip); - xonar_init_ext_power(chip); - xonar_hdmi_init(chip, &data->hdmi); - xonar_enable_output(chip); - - snd_component_add(chip->card, "PCM1796"); - snd_component_add(chip->card, "CS5381"); -} - -static void xonar_st_init_i2c(struct oxygen *chip) -{ - oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, - OXYGEN_2WIRE_LENGTH_8 | - OXYGEN_2WIRE_INTERRUPT_MASK | - OXYGEN_2WIRE_SPEED_STANDARD); -} - -static void xonar_st_init_common(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; - data->dacs = chip->model.dac_channels_mixer / 2; - data->hp_gain_offset = 2*-18; - - pcm1796_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | - GPIO_ST_MAGIC | GPIO_ST_HP); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, - GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); - - xonar_init_cs53x1(chip); - xonar_enable_output(chip); - - snd_component_add(chip->card, "PCM1792A"); - snd_component_add(chip->card, "CS5381"); -} - -static void cs2000_registers_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_FREEZE); - cs2000_write(chip, CS2000_DEV_CTRL, 0); - cs2000_write(chip, CS2000_DEV_CFG_1, - CS2000_R_MOD_SEL_1 | - (0 << CS2000_R_SEL_SHIFT) | - CS2000_AUX_OUT_SRC_REF_CLK | - CS2000_EN_DEV_CFG_1); - cs2000_write(chip, CS2000_DEV_CFG_2, - (0 << CS2000_LOCK_CLK_SHIFT) | - CS2000_FRAC_N_SRC_STATIC); - cs2000_write(chip, CS2000_RATIO_0 + 0, 0x00); /* 1.0 */ - cs2000_write(chip, CS2000_RATIO_0 + 1, 0x10); - cs2000_write(chip, CS2000_RATIO_0 + 2, 0x00); - cs2000_write(chip, CS2000_RATIO_0 + 3, 0x00); - cs2000_write(chip, CS2000_FUN_CFG_1, - data->cs2000_regs[CS2000_FUN_CFG_1]); - cs2000_write(chip, CS2000_FUN_CFG_2, 0); - cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_EN_DEV_CFG_2); - msleep(3); /* PLL lock delay */ -} - -static void xonar_st_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->generic.anti_pop_delay = 100; - data->h6 = chip->model.dac_channels_mixer > 2; - data->has_cs2000 = 1; - data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; - data->broken_i2c = true; - - oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, - OXYGEN_RATE_48000 | - OXYGEN_I2S_FORMAT_I2S | - OXYGEN_I2S_MCLK(data->h6 ? MCLK_256 : MCLK_512) | - OXYGEN_I2S_BITS_16 | - OXYGEN_I2S_MASTER | - OXYGEN_I2S_BCLK_64); - - xonar_st_init_i2c(chip); - cs2000_registers_init(chip); - xonar_st_init_common(chip); - - snd_component_add(chip->card, "CS2000"); -} - -static void xonar_stx_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - xonar_st_init_i2c(chip); - data->generic.anti_pop_delay = 800; - data->generic.ext_power_reg = OXYGEN_GPI_DATA; - data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; - data->generic.ext_power_bit = GPI_EXT_POWER; - xonar_init_ext_power(chip); - xonar_st_init_common(chip); -} - -static void xonar_d2_cleanup(struct oxygen *chip) -{ - xonar_disable_output(chip); -} - -static void xonar_hdav_cleanup(struct oxygen *chip) -{ - xonar_hdmi_cleanup(chip); - xonar_disable_output(chip); - msleep(2); -} - -static void xonar_st_cleanup(struct oxygen *chip) -{ - xonar_disable_output(chip); -} - -static void xonar_d2_suspend(struct oxygen *chip) -{ - xonar_d2_cleanup(chip); -} - -static void xonar_hdav_suspend(struct oxygen *chip) -{ - xonar_hdav_cleanup(chip); -} - -static void xonar_st_suspend(struct oxygen *chip) -{ - xonar_st_cleanup(chip); -} - -static void xonar_d2_resume(struct oxygen *chip) -{ - pcm1796_registers_init(chip); - xonar_enable_output(chip); -} - -static void xonar_hdav_resume(struct oxygen *chip) -{ - struct xonar_hdav *data = chip->model_data; - - pcm1796_registers_init(chip); - xonar_hdmi_resume(chip, &data->hdmi); - xonar_enable_output(chip); -} - -static void xonar_stx_resume(struct oxygen *chip) -{ - pcm1796_registers_init(chip); - xonar_enable_output(chip); -} - -static void xonar_st_resume(struct oxygen *chip) -{ - cs2000_registers_init(chip); - xonar_stx_resume(chip); -} - -static void update_pcm1796_oversampling(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - u8 reg; - - if (data->current_rate <= 48000 && !data->h6) - reg = PCM1796_OS_128; - else - reg = PCM1796_OS_64; - for (i = 0; i < data->dacs; ++i) - pcm1796_write_cached(chip, i, 20, reg); -} - -static void set_pcm1796_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct xonar_pcm179x *data = chip->model_data; - - msleep(1); - data->current_rate = params_rate(params); - update_pcm1796_oversampling(chip); -} - -static void update_pcm1796_volume(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - s8 gain_offset; - - gain_offset = data->hp_active ? data->hp_gain_offset : 0; - for (i = 0; i < data->dacs; ++i) { - pcm1796_write_cached(chip, i, 16, chip->dac_volume[i * 2] - + gain_offset); - pcm1796_write_cached(chip, i, 17, chip->dac_volume[i * 2 + 1] - + gain_offset); - gain_offset = 0; - } -} - -static void update_pcm1796_mute(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - u8 value; - - value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD; - if (chip->dac_mute) - value |= PCM1796_MUTE; - for (i = 0; i < data->dacs; ++i) - pcm1796_write_cached(chip, i, 18, value); -} - -static void update_cs2000_rate(struct oxygen *chip, unsigned int rate) -{ - struct xonar_pcm179x *data = chip->model_data; - u8 rate_mclk, reg; - - switch (rate) { - case 32000: - case 64000: - rate_mclk = OXYGEN_RATE_32000; - break; - case 44100: - case 88200: - case 176400: - rate_mclk = OXYGEN_RATE_44100; - break; - default: - case 48000: - case 96000: - case 192000: - rate_mclk = OXYGEN_RATE_48000; - break; - } - - if (rate <= 96000 && (rate > 48000 || data->h6)) { - rate_mclk |= OXYGEN_I2S_MCLK(MCLK_256); - reg = CS2000_REF_CLK_DIV_1; - } else { - rate_mclk |= OXYGEN_I2S_MCLK(MCLK_512); - reg = CS2000_REF_CLK_DIV_2; - } - - oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, - OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); - cs2000_write_cached(chip, CS2000_FUN_CFG_1, reg); - msleep(3); /* PLL lock delay */ -} - -static void set_st_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - update_cs2000_rate(chip, params_rate(params)); - set_pcm1796_params(chip, params); -} - -static void set_hdav_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct xonar_hdav *data = chip->model_data; - - set_pcm1796_params(chip, params); - xonar_set_hdmi_params(chip, &data->hdmi, params); -} - -static const struct snd_kcontrol_new alt_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Loopback Switch", - .info = snd_ctl_boolean_mono_info, - .get = xonar_gpio_bit_switch_get, - .put = xonar_gpio_bit_switch_put, - .private_value = GPIO_D2_ALT, -}; - -static int rolloff_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "Sharp Roll-off", "Slow Roll-off" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int rolloff_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - - value->value.enumerated.item[0] = - (data->pcm1796_regs[0][19 - PCM1796_REG_BASE] & - PCM1796_FLT_MASK) != PCM1796_FLT_SHARP; - return 0; -} - -static int rolloff_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - int changed; - u8 reg; - - mutex_lock(&chip->mutex); - reg = data->pcm1796_regs[0][19 - PCM1796_REG_BASE]; - reg &= ~PCM1796_FLT_MASK; - if (!value->value.enumerated.item[0]) - reg |= PCM1796_FLT_SHARP; - else - reg |= PCM1796_FLT_SLOW; - changed = reg != data->pcm1796_regs[0][19 - PCM1796_REG_BASE]; - if (changed) { - for (i = 0; i < data->dacs; ++i) - pcm1796_write(chip, i, 19, reg); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new rolloff_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Filter Playback Enum", - .info = rolloff_info, - .get = rolloff_get, - .put = rolloff_put, -}; - -static const struct snd_kcontrol_new hdav_hdmi_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HDMI Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = xonar_gpio_bit_switch_get, - .put = xonar_gpio_bit_switch_put, - .private_value = GPIO_HDAV_OUTPUT_ENABLE | XONAR_GPIO_BIT_INVERT, -}; - -static int st_output_switch_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "Speakers", "Headphones", "FP Headphones" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int st_output_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 gpio; - - gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA); - if (!(gpio & GPIO_ST_HP)) - value->value.enumerated.item[0] = 0; - else if (gpio & GPIO_ST_HP_REAR) - value->value.enumerated.item[0] = 1; - else - value->value.enumerated.item[0] = 2; - return 0; -} - - -static int st_output_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - u16 gpio_old, gpio; - - mutex_lock(&chip->mutex); - gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); - gpio = gpio_old; - switch (value->value.enumerated.item[0]) { - case 0: - gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR); - break; - case 1: - gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR; - break; - case 2: - gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR; - break; - } - oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); - data->hp_active = gpio & GPIO_ST_HP; - update_pcm1796_volume(chip); - mutex_unlock(&chip->mutex); - return gpio != gpio_old; -} - -static int st_hp_volume_offset_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "< 64 ohms", "64-300 ohms", "300-600 ohms" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - - mutex_lock(&chip->mutex); - if (data->hp_gain_offset < 2*-6) - value->value.enumerated.item[0] = 0; - else if (data->hp_gain_offset < 0) - value->value.enumerated.item[0] = 1; - else - value->value.enumerated.item[0] = 2; - mutex_unlock(&chip->mutex); - return 0; -} - - -static int st_hp_volume_offset_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - static const s8 offsets[] = { 2*-18, 2*-6, 0 }; - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - s8 offset; - int changed; - - if (value->value.enumerated.item[0] > 2) - return -EINVAL; - offset = offsets[value->value.enumerated.item[0]]; - mutex_lock(&chip->mutex); - changed = offset != data->hp_gain_offset; - if (changed) { - data->hp_gain_offset = offset; - update_pcm1796_volume(chip); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new st_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Output", - .info = st_output_switch_info, - .get = st_output_switch_get, - .put = st_output_switch_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphones Impedance Playback Enum", - .info = st_hp_volume_offset_info, - .get = st_hp_volume_offset_get, - .put = st_hp_volume_offset_put, - }, -}; - -static void xonar_line_mic_ac97_switch(struct oxygen *chip, - unsigned int reg, unsigned int mute) -{ - if (reg == AC97_LINE) { - spin_lock_irq(&chip->reg_lock); - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - mute ? GPIO_INPUT_ROUTE : 0, - GPIO_INPUT_ROUTE); - spin_unlock_irq(&chip->reg_lock); - } -} - -static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -6000, 50, 0); - -static int xonar_d2_control_filter(struct snd_kcontrol_new *template) -{ - if (!strncmp(template->name, "CD Capture ", 11)) - /* CD in is actually connected to the video in pin */ - template->private_value ^= AC97_CD ^ AC97_VIDEO; - return 0; -} - -static int xonar_st_h6_control_filter(struct snd_kcontrol_new *template) -{ - if (!strncmp(template->name, "Master Playback ", 16)) - /* no volume/mute, as I²C to the third DAC does not work */ - return 1; - return 0; -} - -static int add_pcm1796_controls(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - int err; - - if (!data->broken_i2c) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&rolloff_control, chip)); - if (err < 0) - return err; - } - return 0; -} - -static int xonar_d2_mixer_init(struct oxygen *chip) -{ - int err; - - err = snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); - if (err < 0) - return err; - err = add_pcm1796_controls(chip); - if (err < 0) - return err; - return 0; -} - -static int xonar_hdav_mixer_init(struct oxygen *chip) -{ - int err; - - err = snd_ctl_add(chip->card, snd_ctl_new1(&hdav_hdmi_control, chip)); - if (err < 0) - return err; - err = add_pcm1796_controls(chip); - if (err < 0) - return err; - return 0; -} - -static int xonar_st_mixer_init(struct oxygen *chip) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(st_controls); ++i) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&st_controls[i], chip)); - if (err < 0) - return err; - } - err = add_pcm1796_controls(chip); - if (err < 0) - return err; - return 0; -} - -static void dump_pcm1796_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int dac, i; - - for (dac = 0; dac < data->dacs; ++dac) { - snd_iprintf(buffer, "\nPCM1796 %u:", dac + 1); - for (i = 0; i < 5; ++i) - snd_iprintf(buffer, " %02x", - data->pcm1796_regs[dac][i]); - } - snd_iprintf(buffer, "\n"); -} - -static void dump_cs2000_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - - if (data->has_cs2000) { - snd_iprintf(buffer, "\nCS2000:\n00: "); - for (i = 1; i < 0x10; ++i) - snd_iprintf(buffer, " %02x", data->cs2000_regs[i]); - snd_iprintf(buffer, "\n10:"); - for (i = 0x10; i < 0x1f; ++i) - snd_iprintf(buffer, " %02x", data->cs2000_regs[i]); - snd_iprintf(buffer, "\n"); - } -} - -static void dump_st_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - dump_pcm1796_registers(chip, buffer); - dump_cs2000_registers(chip, buffer); -} - -static const struct oxygen_model model_xonar_d2 = { - .longname = "Asus Virtuoso 200", - .chip = "AV200", - .init = xonar_d2_init, - .control_filter = xonar_d2_control_filter, - .mixer_init = xonar_d2_mixer_init, - .cleanup = xonar_d2_cleanup, - .suspend = xonar_d2_suspend, - .resume = xonar_d2_resume, - .set_dac_params = set_pcm1796_params, - .set_adc_params = xonar_set_cs53x1_params, - .update_dac_volume = update_pcm1796_volume, - .update_dac_mute = update_pcm1796_mute, - .dump_registers = dump_pcm1796_registers, - .dac_tlv = pcm1796_db_scale, - .model_data_size = sizeof(struct xonar_pcm179x), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF | - MIDI_OUTPUT | - MIDI_INPUT | - AC97_CD_INPUT, - .dac_channels_pcm = 8, - .dac_channels_mixer = 8, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .misc_flags = OXYGEN_MISC_MIDI, - .function_flags = OXYGEN_FUNCTION_SPI | - OXYGEN_FUNCTION_ENABLE_SPI_4_5, - .dac_mclks = OXYGEN_MCLKS(512, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -static const struct oxygen_model model_xonar_hdav = { - .longname = "Asus Virtuoso 200", - .chip = "AV200", - .init = xonar_hdav_init, - .mixer_init = xonar_hdav_mixer_init, - .cleanup = xonar_hdav_cleanup, - .suspend = xonar_hdav_suspend, - .resume = xonar_hdav_resume, - .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter, - .set_dac_params = set_hdav_params, - .set_adc_params = xonar_set_cs53x1_params, - .update_dac_volume = update_pcm1796_volume, - .update_dac_mute = update_pcm1796_mute, - .uart_input = xonar_hdmi_uart_input, - .ac97_switch = xonar_line_mic_ac97_switch, - .dump_registers = dump_pcm1796_registers, - .dac_tlv = pcm1796_db_scale, - .model_data_size = sizeof(struct xonar_hdav), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF, - .dac_channels_pcm = 8, - .dac_channels_mixer = 2, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .misc_flags = OXYGEN_MISC_MIDI, - .function_flags = OXYGEN_FUNCTION_2WIRE, - .dac_mclks = OXYGEN_MCLKS(512, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -static const struct oxygen_model model_xonar_st = { - .longname = "Asus Virtuoso 100", - .chip = "AV200", - .init = xonar_st_init, - .mixer_init = xonar_st_mixer_init, - .cleanup = xonar_st_cleanup, - .suspend = xonar_st_suspend, - .resume = xonar_st_resume, - .set_dac_params = set_st_params, - .set_adc_params = xonar_set_cs53x1_params, - .update_dac_volume = update_pcm1796_volume, - .update_dac_mute = update_pcm1796_mute, - .ac97_switch = xonar_line_mic_ac97_switch, - .dump_registers = dump_st_registers, - .dac_tlv = pcm1796_db_scale, - .model_data_size = sizeof(struct xonar_pcm179x), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF | - AC97_FMIC_SWITCH, - .dac_channels_pcm = 2, - .dac_channels_mixer = 2, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .function_flags = OXYGEN_FUNCTION_2WIRE, - .dac_mclks = OXYGEN_MCLKS(512, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -int __devinit get_xonar_pcm179x_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - switch (id->subdevice) { - case 0x8269: - chip->model = model_xonar_d2; - chip->model.shortname = "Xonar D2"; - break; - case 0x82b7: - chip->model = model_xonar_d2; - chip->model.shortname = "Xonar D2X"; - chip->model.init = xonar_d2x_init; - break; - case 0x8314: - chip->model = model_xonar_hdav; - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK); - switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) { - default: - chip->model.shortname = "Xonar HDAV1.3"; - break; - case GPIO_DB_H6: - chip->model.shortname = "Xonar HDAV1.3+H6"; - chip->model.dac_channels_mixer = 8; - chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); - break; - } - break; - case 0x835d: - chip->model = model_xonar_st; - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK); - switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) { - default: - chip->model.shortname = "Xonar ST"; - break; - case GPIO_DB_H6: - chip->model.shortname = "Xonar ST+H6"; - chip->model.control_filter = xonar_st_h6_control_filter; - chip->model.dac_channels_pcm = 8; - chip->model.dac_channels_mixer = 8; - chip->model.dac_volume_min = 255; - chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); - break; - } - break; - case 0x835c: - chip->model = model_xonar_st; - chip->model.shortname = "Xonar STX"; - chip->model.init = xonar_stx_init; - chip->model.resume = xonar_stx_resume; - chip->model.set_dac_params = set_pcm1796_params; - break; - default: - return -EINVAL; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_wm87x6.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_wm87x6.c deleted file mode 100644 index 63cff907..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_wm87x6.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* - * card driver for models with WM8776/WM8766 DACs (Xonar DS/HDAV1.3 Slim) - * - * Copyright (c) Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2. - * - * This driver 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 driver; if not, see . - */ - -/* - * Xonar DS - * -------- - * - * CMI8788: - * - * SPI 0 -> WM8766 (surround, center/LFE, back) - * SPI 1 -> WM8776 (front, input) - * - * GPIO 4 <- headphone detect, 0 = plugged - * GPIO 6 -> route input jack to mic-in (0) or line-in (1) - * GPIO 7 -> enable output to front L/R speaker channels - * GPIO 8 -> enable output to other speaker channels and front panel headphone - * - * WM8776: - * - * input 1 <- line - * input 2 <- mic - * input 3 <- front mic - * input 4 <- aux - */ - -/* - * Xonar HDAV1.3 Slim - * ------------------ - * - * CMI8788: - * - * I²C <-> WM8776 (addr 0011010) - * - * GPIO 0 -> disable HDMI output - * GPIO 1 -> enable HP output - * GPIO 6 -> firmware EEPROM I²C clock - * GPIO 7 <-> firmware EEPROM I²C data - * - * UART <-> HDMI controller - * - * WM8776: - * - * input 1 <- mic - * input 2 <- aux - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "xonar.h" -#include "wm8776.h" -#include "wm8766.h" - -#define GPIO_DS_HP_DETECT 0x0010 -#define GPIO_DS_INPUT_ROUTE 0x0040 -#define GPIO_DS_OUTPUT_FRONTLR 0x0080 -#define GPIO_DS_OUTPUT_ENABLE 0x0100 - -#define GPIO_SLIM_HDMI_DISABLE 0x0001 -#define GPIO_SLIM_OUTPUT_ENABLE 0x0002 -#define GPIO_SLIM_FIRMWARE_CLK 0x0040 -#define GPIO_SLIM_FIRMWARE_DATA 0x0080 - -#define I2C_DEVICE_WM8776 0x34 /* 001101, 0, /W=0 */ - -#define LC_CONTROL_LIMITER 0x40000000 -#define LC_CONTROL_ALC 0x20000000 - -struct xonar_wm87x6 { - struct xonar_generic generic; - u16 wm8776_regs[0x17]; - u16 wm8766_regs[0x10]; - struct snd_kcontrol *line_adcmux_control; - struct snd_kcontrol *mic_adcmux_control; - struct snd_kcontrol *lc_controls[13]; - struct snd_jack *hp_jack; - struct xonar_hdmi hdmi; -}; - -static void wm8776_write_spi(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (1 << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_LO, - (reg << 9) | value); -} - -static void wm8776_write_i2c(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - oxygen_write_i2c(chip, I2C_DEVICE_WM8776, - (reg << 1) | (value >> 8), value); -} - -static void wm8776_write(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - struct xonar_wm87x6 *data = chip->model_data; - - if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) == - OXYGEN_FUNCTION_SPI) - wm8776_write_spi(chip, reg, value); - else - wm8776_write_i2c(chip, reg, value); - if (reg < ARRAY_SIZE(data->wm8776_regs)) { - if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) - value &= ~WM8776_UPDATE; - data->wm8776_regs[reg] = value; - } -} - -static void wm8776_write_cached(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - struct xonar_wm87x6 *data = chip->model_data; - - if (reg >= ARRAY_SIZE(data->wm8776_regs) || - value != data->wm8776_regs[reg]) - wm8776_write(chip, reg, value); -} - -static void wm8766_write(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - struct xonar_wm87x6 *data = chip->model_data; - - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (0 << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_LO, - (reg << 9) | value); - if (reg < ARRAY_SIZE(data->wm8766_regs)) { - if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) || - (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA)) - value &= ~WM8766_UPDATE; - data->wm8766_regs[reg] = value; - } -} - -static void wm8766_write_cached(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - struct xonar_wm87x6 *data = chip->model_data; - - if (reg >= ARRAY_SIZE(data->wm8766_regs) || - value != data->wm8766_regs[reg]) - wm8766_write(chip, reg, value); -} - -static void wm8776_registers_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - wm8776_write(chip, WM8776_RESET, 0); - wm8776_write(chip, WM8776_PHASESWAP, WM8776_PH_MASK); - wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN | - WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT); - wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0); - wm8776_write(chip, WM8776_DACIFCTRL, - WM8776_DACFMT_LJUST | WM8776_DACWL_24); - wm8776_write(chip, WM8776_ADCIFCTRL, - data->wm8776_regs[WM8776_ADCIFCTRL]); - wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]); - wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]); - wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]); - wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] | - WM8776_UPDATE); - wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]); - wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]); - wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]); - wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]); - wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE); -} - -static void wm8766_registers_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - wm8766_write(chip, WM8766_RESET, 0); - wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]); - wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); - wm8766_write(chip, WM8766_DAC_CTRL2, - WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); - wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]); - wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]); - wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]); - wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]); - wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]); - wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE); -} - -static void wm8776_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN; - data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN; - data->wm8776_regs[WM8776_ADCIFCTRL] = - WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK; - data->wm8776_regs[WM8776_MSTRCTRL] = - WM8776_ADCRATE_256 | WM8776_DACRATE_256; - data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD; - data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA; - data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA; - data->wm8776_regs[WM8776_ADCMUX] = 0x001; - wm8776_registers_init(chip); -} - -static void wm8766_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - data->wm8766_regs[WM8766_DAC_CTRL] = - WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; - wm8766_registers_init(chip); -} - -static void xonar_ds_handle_hp_jack(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - bool hp_plugged; - unsigned int reg; - - mutex_lock(&chip->mutex); - - hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) & - GPIO_DS_HP_DETECT); - - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR, - GPIO_DS_OUTPUT_FRONTLR); - - reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL; - if (hp_plugged) - reg |= WM8766_MUTEALL; - wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); - - snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0); - - mutex_unlock(&chip->mutex); -} - -static void xonar_ds_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - data->generic.anti_pop_delay = 300; - data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; - - wm8776_init(chip); - wm8766_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR); - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_DS_HP_DETECT); - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); - oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); - chip->interrupt_mask |= OXYGEN_INT_GPIO; - - xonar_enable_output(chip); - - snd_jack_new(chip->card, "Headphone", - SND_JACK_HEADPHONE, &data->hp_jack); - xonar_ds_handle_hp_jack(chip); - - snd_component_add(chip->card, "WM8776"); - snd_component_add(chip->card, "WM8766"); -} - -static void xonar_hdav_slim_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - data->generic.anti_pop_delay = 300; - data->generic.output_enable_bit = GPIO_SLIM_OUTPUT_ENABLE; - - wm8776_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_SLIM_HDMI_DISABLE | - GPIO_SLIM_FIRMWARE_CLK | - GPIO_SLIM_FIRMWARE_DATA); - - xonar_hdmi_init(chip, &data->hdmi); - xonar_enable_output(chip); - - snd_component_add(chip->card, "WM8776"); -} - -static void xonar_ds_cleanup(struct oxygen *chip) -{ - xonar_disable_output(chip); - wm8776_write(chip, WM8776_RESET, 0); -} - -static void xonar_hdav_slim_cleanup(struct oxygen *chip) -{ - xonar_hdmi_cleanup(chip); - xonar_disable_output(chip); - wm8776_write(chip, WM8776_RESET, 0); - msleep(2); -} - -static void xonar_ds_suspend(struct oxygen *chip) -{ - xonar_ds_cleanup(chip); -} - -static void xonar_hdav_slim_suspend(struct oxygen *chip) -{ - xonar_hdav_slim_cleanup(chip); -} - -static void xonar_ds_resume(struct oxygen *chip) -{ - wm8776_registers_init(chip); - wm8766_registers_init(chip); - xonar_enable_output(chip); - xonar_ds_handle_hp_jack(chip); -} - -static void xonar_hdav_slim_resume(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - wm8776_registers_init(chip); - xonar_hdmi_resume(chip, &data->hdmi); - xonar_enable_output(chip); -} - -static void wm8776_adc_hardware_filter(unsigned int channel, - struct snd_pcm_hardware *hardware) -{ - if (channel == PCM_A) { - hardware->rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000; - hardware->rate_max = 96000; - } -} - -static void xonar_hdav_slim_hardware_filter(unsigned int channel, - struct snd_pcm_hardware *hardware) -{ - wm8776_adc_hardware_filter(channel, hardware); - xonar_hdmi_pcm_hardware_filter(channel, hardware); -} - -static void set_wm87x6_dac_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ -} - -static void set_wm8776_adc_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - u16 reg; - - reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256; - if (params_rate(params) > 48000) - reg |= WM8776_ADCOSR; - wm8776_write_cached(chip, WM8776_MSTRCTRL, reg); -} - -static void set_hdav_slim_dac_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct xonar_wm87x6 *data = chip->model_data; - - xonar_set_hdmi_params(chip, &data->hdmi, params); -} - -static void update_wm8776_volume(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - u8 to_change; - - if (chip->dac_volume[0] == chip->dac_volume[1]) { - if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] || - chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) { - wm8776_write(chip, WM8776_DACMASTER, - chip->dac_volume[0] | WM8776_UPDATE); - data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0]; - data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0]; - } - } else { - to_change = (chip->dac_volume[0] != - data->wm8776_regs[WM8776_DACLVOL]) << 0; - to_change |= (chip->dac_volume[1] != - data->wm8776_regs[WM8776_DACLVOL]) << 1; - if (to_change & 1) - wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] | - ((to_change & 2) ? 0 : WM8776_UPDATE)); - if (to_change & 2) - wm8776_write(chip, WM8776_DACRVOL, - chip->dac_volume[1] | WM8776_UPDATE); - } -} - -static void update_wm87x6_volume(struct oxygen *chip) -{ - static const u8 wm8766_regs[6] = { - WM8766_LDA1, WM8766_RDA1, - WM8766_LDA2, WM8766_RDA2, - WM8766_LDA3, WM8766_RDA3, - }; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - u8 to_change; - - update_wm8776_volume(chip); - if (chip->dac_volume[2] == chip->dac_volume[3] && - chip->dac_volume[2] == chip->dac_volume[4] && - chip->dac_volume[2] == chip->dac_volume[5] && - chip->dac_volume[2] == chip->dac_volume[6] && - chip->dac_volume[2] == chip->dac_volume[7]) { - to_change = 0; - for (i = 0; i < 6; ++i) - if (chip->dac_volume[2] != - data->wm8766_regs[wm8766_regs[i]]) - to_change = 1; - if (to_change) { - wm8766_write(chip, WM8766_MASTDA, - chip->dac_volume[2] | WM8766_UPDATE); - for (i = 0; i < 6; ++i) - data->wm8766_regs[wm8766_regs[i]] = - chip->dac_volume[2]; - } - } else { - to_change = 0; - for (i = 0; i < 6; ++i) - to_change |= (chip->dac_volume[2 + i] != - data->wm8766_regs[wm8766_regs[i]]) << i; - for (i = 0; i < 6; ++i) - if (to_change & (1 << i)) - wm8766_write(chip, wm8766_regs[i], - chip->dac_volume[2 + i] | - ((to_change & (0x3e << i)) - ? 0 : WM8766_UPDATE)); - } -} - -static void update_wm8776_mute(struct oxygen *chip) -{ - wm8776_write_cached(chip, WM8776_DACMUTE, - chip->dac_mute ? WM8776_DMUTE : 0); -} - -static void update_wm87x6_mute(struct oxygen *chip) -{ - update_wm8776_mute(chip); - wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD | - (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); -} - -static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int reg; - - /* - * The WM8766 can mix left and right channels, but this setting - * applies to all three stereo pairs. - */ - reg = data->wm8766_regs[WM8766_DAC_CTRL] & - ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK); - if (mixed) - reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX; - else - reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; - wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); -} - -static void xonar_ds_gpio_changed(struct oxygen *chip) -{ - xonar_ds_handle_hp_jack(chip); -} - -static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - u16 bit = ctl->private_value & 0xffff; - unsigned int reg_index = (ctl->private_value >> 16) & 0xff; - bool invert = (ctl->private_value >> 24) & 1; - - value->value.integer.value[0] = - ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert; - return 0; -} - -static int wm8776_bit_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - u16 bit = ctl->private_value & 0xffff; - u16 reg_value; - unsigned int reg_index = (ctl->private_value >> 16) & 0xff; - bool invert = (ctl->private_value >> 24) & 1; - int changed; - - mutex_lock(&chip->mutex); - reg_value = data->wm8776_regs[reg_index] & ~bit; - if (value->value.integer.value[0] ^ invert) - reg_value |= bit; - changed = reg_value != data->wm8776_regs[reg_index]; - if (changed) - wm8776_write(chip, reg_index, reg_value); - mutex_unlock(&chip->mutex); - return changed; -} - -static int wm8776_field_enum_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const hld[16] = { - "0 ms", "2.67 ms", "5.33 ms", "10.6 ms", - "21.3 ms", "42.7 ms", "85.3 ms", "171 ms", - "341 ms", "683 ms", "1.37 s", "2.73 s", - "5.46 s", "10.9 s", "21.8 s", "43.7 s", - }; - static const char *const atk_lim[11] = { - "0.25 ms", "0.5 ms", "1 ms", "2 ms", - "4 ms", "8 ms", "16 ms", "32 ms", - "64 ms", "128 ms", "256 ms", - }; - static const char *const atk_alc[11] = { - "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms", - "134 ms", "269 ms", "538 ms", "1.08 s", - "2.15 s", "4.3 s", "8.6 s", - }; - static const char *const dcy_lim[11] = { - "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms", - "19.2 ms", "38.4 ms", "76.8 ms", "154 ms", - "307 ms", "614 ms", "1.23 s", - }; - static const char *const dcy_alc[11] = { - "33.5 ms", "67.0 ms", "134 ms", "268 ms", - "536 ms", "1.07 s", "2.14 s", "4.29 s", - "8.58 s", "17.2 s", "34.3 s", - }; - static const char *const tranwin[8] = { - "0 us", "62.5 us", "125 us", "250 us", - "500 us", "1 ms", "2 ms", "4 ms", - }; - u8 max; - const char *const *names; - - max = (ctl->private_value >> 12) & 0xf; - switch ((ctl->private_value >> 24) & 0x1f) { - case WM8776_ALCCTRL2: - names = hld; - break; - case WM8776_ALCCTRL3: - if (((ctl->private_value >> 20) & 0xf) == 0) { - if (ctl->private_value & LC_CONTROL_LIMITER) - names = atk_lim; - else - names = atk_alc; - } else { - if (ctl->private_value & LC_CONTROL_LIMITER) - names = dcy_lim; - else - names = dcy_alc; - } - break; - case WM8776_LIMITER: - names = tranwin; - break; - default: - return -ENXIO; - } - return snd_ctl_enum_info(info, 1, max + 1, names); -} - -static int wm8776_field_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; - info->value.integer.min = (ctl->private_value >> 8) & 0xf; - info->value.integer.max = (ctl->private_value >> 12) & 0xf; - return 0; -} - -static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int value, reg_index, mode; - u8 min, max, shift; - u16 mask, reg_value; - bool invert; - - if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) == - WM8776_LCSEL_LIMITER) - mode = LC_CONTROL_LIMITER; - else - mode = LC_CONTROL_ALC; - if (!(ctl->private_value & mode)) - return; - - value = ctl->private_value & 0xf; - min = (ctl->private_value >> 8) & 0xf; - max = (ctl->private_value >> 12) & 0xf; - mask = (ctl->private_value >> 16) & 0xf; - shift = (ctl->private_value >> 20) & 0xf; - reg_index = (ctl->private_value >> 24) & 0x1f; - invert = (ctl->private_value >> 29) & 0x1; - - if (invert) - value = max - (value - min); - reg_value = data->wm8776_regs[reg_index]; - reg_value &= ~(mask << shift); - reg_value |= value << shift; - wm8776_write_cached(chip, reg_index, reg_value); -} - -static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value) -{ - struct oxygen *chip = ctl->private_data; - u8 min, max; - int changed; - - min = (ctl->private_value >> 8) & 0xf; - max = (ctl->private_value >> 12) & 0xf; - if (value < min || value > max) - return -EINVAL; - mutex_lock(&chip->mutex); - changed = value != (ctl->private_value & 0xf); - if (changed) { - ctl->private_value = (ctl->private_value & ~0xf) | value; - wm8776_field_set_from_ctl(ctl); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int wm8776_field_enum_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - value->value.enumerated.item[0] = ctl->private_value & 0xf; - return 0; -} - -static int wm8776_field_volume_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - value->value.integer.value[0] = ctl->private_value & 0xf; - return 0; -} - -static int wm8776_field_enum_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - return wm8776_field_set(ctl, value->value.enumerated.item[0]); -} - -static int wm8776_field_volume_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - return wm8776_field_set(ctl, value->value.integer.value[0]); -} - -static int wm8776_hp_vol_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0x79 - 60; - info->value.integer.max = 0x7f; - return 0; -} - -static int wm8776_hp_vol_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = - data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK; - value->value.integer.value[1] = - data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK; - mutex_unlock(&chip->mutex); - return 0; -} - -static int wm8776_hp_vol_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - u8 to_update; - - mutex_lock(&chip->mutex); - to_update = (value->value.integer.value[0] != - (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK)) - << 0; - to_update |= (value->value.integer.value[1] != - (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK)) - << 1; - if (value->value.integer.value[0] == value->value.integer.value[1]) { - if (to_update) { - wm8776_write(chip, WM8776_HPMASTER, - value->value.integer.value[0] | - WM8776_HPZCEN | WM8776_UPDATE); - data->wm8776_regs[WM8776_HPLVOL] = - value->value.integer.value[0] | WM8776_HPZCEN; - data->wm8776_regs[WM8776_HPRVOL] = - value->value.integer.value[0] | WM8776_HPZCEN; - } - } else { - if (to_update & 1) - wm8776_write(chip, WM8776_HPLVOL, - value->value.integer.value[0] | - WM8776_HPZCEN | - ((to_update & 2) ? 0 : WM8776_UPDATE)); - if (to_update & 2) - wm8776_write(chip, WM8776_HPRVOL, - value->value.integer.value[1] | - WM8776_HPZCEN | WM8776_UPDATE); - } - mutex_unlock(&chip->mutex); - return to_update != 0; -} - -static int wm8776_input_mux_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int mux_bit = ctl->private_value; - - value->value.integer.value[0] = - !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit); - return 0; -} - -static int wm8776_input_mux_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - struct snd_kcontrol *other_ctl; - unsigned int mux_bit = ctl->private_value; - u16 reg; - int changed; - - mutex_lock(&chip->mutex); - reg = data->wm8776_regs[WM8776_ADCMUX]; - if (value->value.integer.value[0]) { - reg |= mux_bit; - /* line-in and mic-in are exclusive */ - mux_bit ^= 3; - if (reg & mux_bit) { - reg &= ~mux_bit; - if (mux_bit == 1) - other_ctl = data->line_adcmux_control; - else - other_ctl = data->mic_adcmux_control; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &other_ctl->id); - } - } else - reg &= ~mux_bit; - changed = reg != data->wm8776_regs[WM8776_ADCMUX]; - if (changed) { - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - reg & 1 ? GPIO_DS_INPUT_ROUTE : 0, - GPIO_DS_INPUT_ROUTE); - wm8776_write(chip, WM8776_ADCMUX, reg); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int wm8776_input_vol_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0xa5; - info->value.integer.max = 0xff; - return 0; -} - -static int wm8776_input_vol_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = - data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK; - value->value.integer.value[1] = - data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK; - mutex_unlock(&chip->mutex); - return 0; -} - -static int wm8776_input_vol_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - int changed = 0; - - mutex_lock(&chip->mutex); - changed = (value->value.integer.value[0] != - (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) || - (value->value.integer.value[1] != - (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK)); - wm8776_write_cached(chip, WM8776_ADCLVOL, - value->value.integer.value[0] | WM8776_ZCA); - wm8776_write_cached(chip, WM8776_ADCRVOL, - value->value.integer.value[1] | WM8776_ZCA); - mutex_unlock(&chip->mutex); - return changed; -} - -static int wm8776_level_control_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "None", "Peak Limiter", "Automatic Level Control" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int wm8776_level_control_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - - if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN)) - value->value.enumerated.item[0] = 0; - else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) == - WM8776_LCSEL_LIMITER) - value->value.enumerated.item[0] = 1; - else - value->value.enumerated.item[0] = 2; - return 0; -} - -static void activate_control(struct oxygen *chip, - struct snd_kcontrol *ctl, unsigned int mode) -{ - unsigned int access; - - if (ctl->private_value & mode) - access = 0; - else - access = SNDRV_CTL_ELEM_ACCESS_INACTIVE; - if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) { - ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); - } -} - -static int wm8776_level_control_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int mode = 0, i; - u16 ctrl1, ctrl2; - int changed; - - if (value->value.enumerated.item[0] >= 3) - return -EINVAL; - mutex_lock(&chip->mutex); - changed = value->value.enumerated.item[0] != ctl->private_value; - if (changed) { - ctl->private_value = value->value.enumerated.item[0]; - ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1]; - ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2]; - switch (value->value.enumerated.item[0]) { - default: - wm8776_write_cached(chip, WM8776_ALCCTRL2, - ctrl2 & ~WM8776_LCEN); - break; - case 1: - wm8776_write_cached(chip, WM8776_ALCCTRL1, - (ctrl1 & ~WM8776_LCSEL_MASK) | - WM8776_LCSEL_LIMITER); - wm8776_write_cached(chip, WM8776_ALCCTRL2, - ctrl2 | WM8776_LCEN); - mode = LC_CONTROL_LIMITER; - break; - case 2: - wm8776_write_cached(chip, WM8776_ALCCTRL1, - (ctrl1 & ~WM8776_LCSEL_MASK) | - WM8776_LCSEL_ALC_STEREO); - wm8776_write_cached(chip, WM8776_ALCCTRL2, - ctrl2 | WM8776_LCEN); - mode = LC_CONTROL_ALC; - break; - } - for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i) - activate_control(chip, data->lc_controls[i], mode); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "None", "High-pass Filter" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - - value->value.enumerated.item[0] = - !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD); - return 0; -} - -static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int reg; - int changed; - - mutex_lock(&chip->mutex); - reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD; - if (!value->value.enumerated.item[0]) - reg |= WM8776_ADCHPD; - changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL]; - if (changed) - wm8776_write(chip, WM8776_ADCIFCTRL, reg); - mutex_unlock(&chip->mutex); - return changed; -} - -#define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .info = snd_ctl_boolean_mono_info, \ - .get = wm8776_bit_switch_get, \ - .put = wm8776_bit_switch_put, \ - .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \ -} -#define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .private_value = (initval) | ((min) << 8) | ((max) << 12) | \ - ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags) -#define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\ - _WM8776_FIELD_CTL(xname " Capture Enum", \ - reg, shift, init, min, max, mask, flags), \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_INACTIVE, \ - .info = wm8776_field_enum_info, \ - .get = wm8776_field_enum_get, \ - .put = wm8776_field_enum_put, \ -} -#define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \ - _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_INACTIVE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = wm8776_field_volume_info, \ - .get = wm8776_field_volume_get, \ - .put = wm8776_field_volume_put, \ - .tlv = { .p = tlv_p }, \ -} - -static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0); - -static const struct snd_kcontrol_new ds_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Volume", - .info = wm8776_hp_vol_info, - .get = wm8776_hp_vol_get, - .put = wm8776_hp_vol_put, - .tlv = { .p = wm8776_hp_db_scale }, - }, - WM8776_BIT_SWITCH("Headphone Playback Switch", - WM8776_PWRDOWN, WM8776_HPPD, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Capture Volume", - .info = wm8776_input_vol_info, - .get = wm8776_input_vol_get, - .put = wm8776_input_vol_put, - .tlv = { .p = wm8776_adc_db_scale }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Capture Switch", - .info = snd_ctl_boolean_mono_info, - .get = wm8776_input_mux_get, - .put = wm8776_input_mux_put, - .private_value = 1 << 0, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Capture Switch", - .info = snd_ctl_boolean_mono_info, - .get = wm8776_input_mux_get, - .put = wm8776_input_mux_put, - .private_value = 1 << 1, - }, - WM8776_BIT_SWITCH("Front Mic Capture Switch", - WM8776_ADCMUX, 1 << 2, 0, 0), - WM8776_BIT_SWITCH("Aux Capture Switch", - WM8776_ADCMUX, 1 << 3, 0, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Filter Capture Enum", - .info = hpf_info, - .get = hpf_get, - .put = hpf_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Level Control Capture Enum", - .info = wm8776_level_control_info, - .get = wm8776_level_control_get, - .put = wm8776_level_control_put, - .private_value = 0, - }, -}; -static const struct snd_kcontrol_new hdav_slim_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HDMI Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = xonar_gpio_bit_switch_get, - .put = xonar_gpio_bit_switch_put, - .private_value = GPIO_SLIM_HDMI_DISABLE | XONAR_GPIO_BIT_INVERT, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Volume", - .info = wm8776_hp_vol_info, - .get = wm8776_hp_vol_get, - .put = wm8776_hp_vol_put, - .tlv = { .p = wm8776_hp_db_scale }, - }, - WM8776_BIT_SWITCH("Headphone Playback Switch", - WM8776_PWRDOWN, WM8776_HPPD, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Capture Volume", - .info = wm8776_input_vol_info, - .get = wm8776_input_vol_get, - .put = wm8776_input_vol_put, - .tlv = { .p = wm8776_adc_db_scale }, - }, - WM8776_BIT_SWITCH("Mic Capture Switch", - WM8776_ADCMUX, 1 << 0, 0, 0), - WM8776_BIT_SWITCH("Aux Capture Switch", - WM8776_ADCMUX, 1 << 1, 0, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Filter Capture Enum", - .info = hpf_info, - .get = hpf_get, - .put = hpf_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Level Control Capture Enum", - .info = wm8776_level_control_info, - .get = wm8776_level_control_get, - .put = wm8776_level_control_put, - .private_value = 0, - }, -}; -static const struct snd_kcontrol_new lc_controls[] = { - WM8776_FIELD_CTL_VOLUME("Limiter Threshold", - WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf, - LC_CONTROL_LIMITER, wm8776_lct_db_scale), - WM8776_FIELD_CTL_ENUM("Limiter Attack Time", - WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf, - LC_CONTROL_LIMITER), - WM8776_FIELD_CTL_ENUM("Limiter Decay Time", - WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf, - LC_CONTROL_LIMITER), - WM8776_FIELD_CTL_ENUM("Limiter Transient Window", - WM8776_LIMITER, 4, 2, 0, 7, 0x7, - LC_CONTROL_LIMITER), - WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation", - WM8776_LIMITER, 0, 6, 3, 12, 0xf, - LC_CONTROL_LIMITER, - wm8776_maxatten_lim_db_scale), - WM8776_FIELD_CTL_VOLUME("ALC Target Level", - WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf, - LC_CONTROL_ALC, wm8776_lct_db_scale), - WM8776_FIELD_CTL_ENUM("ALC Attack Time", - WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf, - LC_CONTROL_ALC), - WM8776_FIELD_CTL_ENUM("ALC Decay Time", - WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf, - LC_CONTROL_ALC), - WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain", - WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7, - LC_CONTROL_ALC, wm8776_maxgain_db_scale), - WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation", - WM8776_LIMITER, 0, 10, 10, 15, 0xf, - LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale), - WM8776_FIELD_CTL_ENUM("ALC Hold Time", - WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf, - LC_CONTROL_ALC), - WM8776_BIT_SWITCH("Noise Gate Capture Switch", - WM8776_NOISEGATE, WM8776_NGAT, 0, - LC_CONTROL_ALC), - WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold", - WM8776_NOISEGATE, 2, 0, 0, 7, 0x7, - LC_CONTROL_ALC, wm8776_ngth_db_scale), -}; - -static int add_lc_controls(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - struct snd_kcontrol *ctl; - int err; - - BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); - for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { - ctl = snd_ctl_new1(&lc_controls[i], chip); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(chip->card, ctl); - if (err < 0) - return err; - data->lc_controls[i] = ctl; - } - return 0; -} - -static int xonar_ds_mixer_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - struct snd_kcontrol *ctl; - int err; - - for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) { - ctl = snd_ctl_new1(&ds_controls[i], chip); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(chip->card, ctl); - if (err < 0) - return err; - if (!strcmp(ctl->id.name, "Line Capture Switch")) - data->line_adcmux_control = ctl; - else if (!strcmp(ctl->id.name, "Mic Capture Switch")) - data->mic_adcmux_control = ctl; - } - if (!data->line_adcmux_control || !data->mic_adcmux_control) - return -ENXIO; - - return add_lc_controls(chip); -} - -static int xonar_hdav_slim_mixer_init(struct oxygen *chip) -{ - unsigned int i; - struct snd_kcontrol *ctl; - int err; - - for (i = 0; i < ARRAY_SIZE(hdav_slim_controls); ++i) { - ctl = snd_ctl_new1(&hdav_slim_controls[i], chip); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(chip->card, ctl); - if (err < 0) - return err; - } - - return add_lc_controls(chip); -} - -static void dump_wm8776_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - - snd_iprintf(buffer, "\nWM8776:\n00:"); - for (i = 0; i < 0x10; ++i) - snd_iprintf(buffer, " %03x", data->wm8776_regs[i]); - snd_iprintf(buffer, "\n10:"); - for (i = 0x10; i < 0x17; ++i) - snd_iprintf(buffer, " %03x", data->wm8776_regs[i]); - snd_iprintf(buffer, "\n"); -} - -static void dump_wm87x6_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - - dump_wm8776_registers(chip, buffer); - snd_iprintf(buffer, "\nWM8766:\n00:"); - for (i = 0; i < 0x10; ++i) - snd_iprintf(buffer, " %03x", data->wm8766_regs[i]); - snd_iprintf(buffer, "\n"); -} - -static const struct oxygen_model model_xonar_ds = { - .shortname = "Xonar DS", - .longname = "Asus Virtuoso 66", - .chip = "AV200", - .init = xonar_ds_init, - .mixer_init = xonar_ds_mixer_init, - .cleanup = xonar_ds_cleanup, - .suspend = xonar_ds_suspend, - .resume = xonar_ds_resume, - .pcm_hardware_filter = wm8776_adc_hardware_filter, - .set_dac_params = set_wm87x6_dac_params, - .set_adc_params = set_wm8776_adc_params, - .update_dac_volume = update_wm87x6_volume, - .update_dac_mute = update_wm87x6_mute, - .update_center_lfe_mix = update_wm8766_center_lfe_mix, - .gpio_changed = xonar_ds_gpio_changed, - .dump_registers = dump_wm87x6_registers, - .dac_tlv = wm87x6_dac_db_scale, - .model_data_size = sizeof(struct xonar_wm87x6), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_1 | - CAPTURE_1_FROM_SPDIF, - .dac_channels_pcm = 8, - .dac_channels_mixer = 8, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .function_flags = OXYGEN_FUNCTION_SPI, - .dac_mclks = OXYGEN_MCLKS(256, 256, 128), - .adc_mclks = OXYGEN_MCLKS(256, 256, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -static const struct oxygen_model model_xonar_hdav_slim = { - .shortname = "Xonar HDAV1.3 Slim", - .longname = "Asus Virtuoso 200", - .chip = "AV200", - .init = xonar_hdav_slim_init, - .mixer_init = xonar_hdav_slim_mixer_init, - .cleanup = xonar_hdav_slim_cleanup, - .suspend = xonar_hdav_slim_suspend, - .resume = xonar_hdav_slim_resume, - .pcm_hardware_filter = xonar_hdav_slim_hardware_filter, - .set_dac_params = set_hdav_slim_dac_params, - .set_adc_params = set_wm8776_adc_params, - .update_dac_volume = update_wm8776_volume, - .update_dac_mute = update_wm8776_mute, - .uart_input = xonar_hdmi_uart_input, - .dump_registers = dump_wm8776_registers, - .dac_tlv = wm87x6_dac_db_scale, - .model_data_size = sizeof(struct xonar_wm87x6), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_1 | - CAPTURE_1_FROM_SPDIF, - .dac_channels_pcm = 8, - .dac_channels_mixer = 2, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .function_flags = OXYGEN_FUNCTION_2WIRE, - .dac_mclks = OXYGEN_MCLKS(256, 256, 128), - .adc_mclks = OXYGEN_MCLKS(256, 256, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -int __devinit get_xonar_wm87x6_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - switch (id->subdevice) { - case 0x838e: - chip->model = model_xonar_ds; - break; - case 0x835e: - chip->model = model_xonar_hdav_slim; - break; - default: - return -EINVAL; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/Makefile b/ANDROID_3.4.5/sound/pci/pcxhr/Makefile deleted file mode 100644 index b06128e9..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -snd-pcxhr-objs := pcxhr.o pcxhr_hwdep.o pcxhr_mixer.o pcxhr_core.o pcxhr_mix22.o -obj-$(CONFIG_SND_PCXHR) += snd-pcxhr.o diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.c b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.c deleted file mode 100644 index fd1809ab..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.c +++ /dev/null @@ -1,1628 +0,0 @@ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * main file with alsa callbacks - * - * Copyright (c) 2004 by Digigram - * - * 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 -#include -#include -#include -#include -#include -#include "pcxhr.h" -#include "pcxhr_mixer.h" -#include "pcxhr_hwdep.h" -#include "pcxhr_core.h" -#include "pcxhr_mix22.h" - -#define DRIVER_NAME "pcxhr" - -MODULE_AUTHOR("Markus Bollinger , " - "Marc Titinger "); -MODULE_DESCRIPTION("Digigram " DRIVER_NAME " " PCXHR_DRIVER_VERSION_STRING); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Digigram," DRIVER_NAME "}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ -static bool mono[SNDRV_CARDS]; /* capture mono only */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Digigram " DRIVER_NAME " soundcard"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Digigram " DRIVER_NAME " soundcard"); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Digigram " DRIVER_NAME " soundcard"); -module_param_array(mono, bool, NULL, 0444); -MODULE_PARM_DESC(mono, "Mono capture mode (default is stereo)"); - -enum { - PCI_ID_VX882HR, - PCI_ID_PCX882HR, - PCI_ID_VX881HR, - PCI_ID_PCX881HR, - PCI_ID_VX882E, - PCI_ID_PCX882E, - PCI_ID_VX881E, - PCI_ID_PCX881E, - PCI_ID_VX1222HR, - PCI_ID_PCX1222HR, - PCI_ID_VX1221HR, - PCI_ID_PCX1221HR, - PCI_ID_VX1222E, - PCI_ID_PCX1222E, - PCI_ID_VX1221E, - PCI_ID_PCX1221E, - PCI_ID_VX222HR, - PCI_ID_VX222E, - PCI_ID_PCX22HR, - PCI_ID_PCX22E, - PCI_ID_VX222HRMIC, - PCI_ID_VX222E_MIC, - PCI_ID_PCX924HR, - PCI_ID_PCX924E, - PCI_ID_PCX924HRMIC, - PCI_ID_PCX924E_MIC, - PCI_ID_LAST -}; - -static DEFINE_PCI_DEVICE_TABLE(pcxhr_ids) = { - { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, }, - { 0x10b5, 0x9056, 0x1369, 0xb021, 0, 0, PCI_ID_VX882E, }, - { 0x10b5, 0x9056, 0x1369, 0xb121, 0, 0, PCI_ID_PCX882E, }, - { 0x10b5, 0x9056, 0x1369, 0xb221, 0, 0, PCI_ID_VX881E, }, - { 0x10b5, 0x9056, 0x1369, 0xb321, 0, 0, PCI_ID_PCX881E, }, - { 0x10b5, 0x9656, 0x1369, 0xb401, 0, 0, PCI_ID_VX1222HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb601, 0, 0, PCI_ID_VX1221HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, }, - { 0x10b5, 0x9056, 0x1369, 0xb421, 0, 0, PCI_ID_VX1222E, }, - { 0x10b5, 0x9056, 0x1369, 0xb521, 0, 0, PCI_ID_PCX1222E, }, - { 0x10b5, 0x9056, 0x1369, 0xb621, 0, 0, PCI_ID_VX1221E, }, - { 0x10b5, 0x9056, 0x1369, 0xb721, 0, 0, PCI_ID_PCX1221E, }, - { 0x10b5, 0x9056, 0x1369, 0xba01, 0, 0, PCI_ID_VX222HR, }, - { 0x10b5, 0x9056, 0x1369, 0xba21, 0, 0, PCI_ID_VX222E, }, - { 0x10b5, 0x9056, 0x1369, 0xbd01, 0, 0, PCI_ID_PCX22HR, }, - { 0x10b5, 0x9056, 0x1369, 0xbd21, 0, 0, PCI_ID_PCX22E, }, - { 0x10b5, 0x9056, 0x1369, 0xbc01, 0, 0, PCI_ID_VX222HRMIC, }, - { 0x10b5, 0x9056, 0x1369, 0xbc21, 0, 0, PCI_ID_VX222E_MIC, }, - { 0x10b5, 0x9056, 0x1369, 0xbb01, 0, 0, PCI_ID_PCX924HR, }, - { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, }, - { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, }, - { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, pcxhr_ids); - -struct board_parameters { - char* board_name; - short playback_chips; - short capture_chips; - short fw_file_set; - short firmware_num; -}; -static struct board_parameters pcxhr_board_params[] = { -[PCI_ID_VX882HR] = { "VX882HR", 4, 4, 0, 41 }, -[PCI_ID_PCX882HR] = { "PCX882HR", 4, 4, 0, 41 }, -[PCI_ID_VX881HR] = { "VX881HR", 4, 4, 0, 41 }, -[PCI_ID_PCX881HR] = { "PCX881HR", 4, 4, 0, 41 }, -[PCI_ID_VX882E] = { "VX882e", 4, 4, 1, 41 }, -[PCI_ID_PCX882E] = { "PCX882e", 4, 4, 1, 41 }, -[PCI_ID_VX881E] = { "VX881e", 4, 4, 1, 41 }, -[PCI_ID_PCX881E] = { "PCX881e", 4, 4, 1, 41 }, -[PCI_ID_VX1222HR] = { "VX1222HR", 6, 1, 2, 42 }, -[PCI_ID_PCX1222HR] = { "PCX1222HR", 6, 1, 2, 42 }, -[PCI_ID_VX1221HR] = { "VX1221HR", 6, 1, 2, 42 }, -[PCI_ID_PCX1221HR] = { "PCX1221HR", 6, 1, 2, 42 }, -[PCI_ID_VX1222E] = { "VX1222e", 6, 1, 3, 42 }, -[PCI_ID_PCX1222E] = { "PCX1222e", 6, 1, 3, 42 }, -[PCI_ID_VX1221E] = { "VX1221e", 6, 1, 3, 42 }, -[PCI_ID_PCX1221E] = { "PCX1221e", 6, 1, 3, 42 }, -[PCI_ID_VX222HR] = { "VX222HR", 1, 1, 4, 44 }, -[PCI_ID_VX222E] = { "VX222e", 1, 1, 4, 44 }, -[PCI_ID_PCX22HR] = { "PCX22HR", 1, 0, 4, 44 }, -[PCI_ID_PCX22E] = { "PCX22e", 1, 0, 4, 44 }, -[PCI_ID_VX222HRMIC] = { "VX222HR-Mic", 1, 1, 5, 44 }, -[PCI_ID_VX222E_MIC] = { "VX222e-Mic", 1, 1, 5, 44 }, -[PCI_ID_PCX924HR] = { "PCX924HR", 1, 1, 5, 44 }, -[PCI_ID_PCX924E] = { "PCX924e", 1, 1, 5, 44 }, -[PCI_ID_PCX924HRMIC] = { "PCX924HR-Mic", 1, 1, 5, 44 }, -[PCI_ID_PCX924E_MIC] = { "PCX924e-Mic", 1, 1, 5, 44 }, -}; - -/* boards without hw AES1 and SRC onboard are all using fw_file_set==4 */ -/* VX222HR, VX222e, PCX22HR and PCX22e */ -#define PCXHR_BOARD_HAS_AES1(x) (x->fw_file_set != 4) -/* some boards do not support 192kHz on digital AES input plugs */ -#define PCXHR_BOARD_AESIN_NO_192K(x) ((x->capture_chips == 0) || \ - (x->fw_file_set == 0) || \ - (x->fw_file_set == 2)) - -static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg, - unsigned int* realfreq) -{ - unsigned int reg; - - if (freq < 6900 || freq > 110000) - return -EINVAL; - reg = (28224000 * 2) / freq; - reg = (reg - 1) / 2; - if (reg < 0x200) - *pllreg = reg + 0x800; - else if (reg < 0x400) - *pllreg = reg & 0x1ff; - else if (reg < 0x800) { - *pllreg = ((reg >> 1) & 0x1ff) + 0x200; - reg &= ~1; - } else { - *pllreg = ((reg >> 2) & 0x1ff) + 0x400; - reg &= ~3; - } - if (realfreq) - *realfreq = (28224000 / (reg + 1)); - return 0; -} - - -#define PCXHR_FREQ_REG_MASK 0x1f -#define PCXHR_FREQ_QUARTZ_48000 0x00 -#define PCXHR_FREQ_QUARTZ_24000 0x01 -#define PCXHR_FREQ_QUARTZ_12000 0x09 -#define PCXHR_FREQ_QUARTZ_32000 0x08 -#define PCXHR_FREQ_QUARTZ_16000 0x04 -#define PCXHR_FREQ_QUARTZ_8000 0x0c -#define PCXHR_FREQ_QUARTZ_44100 0x02 -#define PCXHR_FREQ_QUARTZ_22050 0x0a -#define PCXHR_FREQ_QUARTZ_11025 0x06 -#define PCXHR_FREQ_PLL 0x05 -#define PCXHR_FREQ_QUARTZ_192000 0x10 -#define PCXHR_FREQ_QUARTZ_96000 0x18 -#define PCXHR_FREQ_QUARTZ_176400 0x14 -#define PCXHR_FREQ_QUARTZ_88200 0x1c -#define PCXHR_FREQ_QUARTZ_128000 0x12 -#define PCXHR_FREQ_QUARTZ_64000 0x1a - -#define PCXHR_FREQ_WORD_CLOCK 0x0f -#define PCXHR_FREQ_SYNC_AES 0x0e -#define PCXHR_FREQ_AES_1 0x07 -#define PCXHR_FREQ_AES_2 0x0b -#define PCXHR_FREQ_AES_3 0x03 -#define PCXHR_FREQ_AES_4 0x0d - -static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate, - unsigned int *reg, unsigned int *freq) -{ - unsigned int val, realfreq, pllreg; - struct pcxhr_rmh rmh; - int err; - - realfreq = rate; - switch (mgr->use_clock_type) { - case PCXHR_CLOCK_TYPE_INTERNAL : /* clock by quartz or pll */ - switch (rate) { - case 48000 : val = PCXHR_FREQ_QUARTZ_48000; break; - case 24000 : val = PCXHR_FREQ_QUARTZ_24000; break; - case 12000 : val = PCXHR_FREQ_QUARTZ_12000; break; - case 32000 : val = PCXHR_FREQ_QUARTZ_32000; break; - case 16000 : val = PCXHR_FREQ_QUARTZ_16000; break; - case 8000 : val = PCXHR_FREQ_QUARTZ_8000; break; - case 44100 : val = PCXHR_FREQ_QUARTZ_44100; break; - case 22050 : val = PCXHR_FREQ_QUARTZ_22050; break; - case 11025 : val = PCXHR_FREQ_QUARTZ_11025; break; - case 192000 : val = PCXHR_FREQ_QUARTZ_192000; break; - case 96000 : val = PCXHR_FREQ_QUARTZ_96000; break; - case 176400 : val = PCXHR_FREQ_QUARTZ_176400; break; - case 88200 : val = PCXHR_FREQ_QUARTZ_88200; break; - case 128000 : val = PCXHR_FREQ_QUARTZ_128000; break; - case 64000 : val = PCXHR_FREQ_QUARTZ_64000; break; - default : - val = PCXHR_FREQ_PLL; - /* get the value for the pll register */ - err = pcxhr_pll_freq_register(rate, &pllreg, &realfreq); - if (err) - return err; - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); - rmh.cmd[0] |= IO_NUM_REG_GENCLK; - rmh.cmd[1] = pllreg & MASK_DSP_WORD; - rmh.cmd[2] = pllreg >> 24; - rmh.cmd_len = 3; - err = pcxhr_send_msg(mgr, &rmh); - if (err < 0) { - snd_printk(KERN_ERR - "error CMD_ACCESS_IO_WRITE " - "for PLL register : %x!\n", err); - return err; - } - } - break; - case PCXHR_CLOCK_TYPE_WORD_CLOCK: - val = PCXHR_FREQ_WORD_CLOCK; - break; - case PCXHR_CLOCK_TYPE_AES_SYNC: - val = PCXHR_FREQ_SYNC_AES; - break; - case PCXHR_CLOCK_TYPE_AES_1: - val = PCXHR_FREQ_AES_1; - break; - case PCXHR_CLOCK_TYPE_AES_2: - val = PCXHR_FREQ_AES_2; - break; - case PCXHR_CLOCK_TYPE_AES_3: - val = PCXHR_FREQ_AES_3; - break; - case PCXHR_CLOCK_TYPE_AES_4: - val = PCXHR_FREQ_AES_4; - break; - default: - return -EINVAL; - } - *reg = val; - *freq = realfreq; - return 0; -} - - -static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr, - unsigned int rate, - int *changed) -{ - unsigned int val, realfreq, speed; - struct pcxhr_rmh rmh; - int err; - - err = pcxhr_get_clock_reg(mgr, rate, &val, &realfreq); - if (err) - return err; - - /* codec speed modes */ - if (rate < 55000) - speed = 0; /* single speed */ - else if (rate < 100000) - speed = 1; /* dual speed */ - else - speed = 2; /* quad speed */ - if (mgr->codec_speed != speed) { - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* mute outputs */ - rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT; - if (DSP_EXT_CMD_SET(mgr)) { - rmh.cmd[1] = 1; - rmh.cmd_len = 2; - } - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set speed ratio */ - rmh.cmd[0] |= IO_NUM_SPEED_RATIO; - rmh.cmd[1] = speed; - rmh.cmd_len = 2; - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - } - /* set the new frequency */ - snd_printdd("clock register : set %x\n", val); - err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK, - val, changed); - if (err) - return err; - - mgr->sample_rate_real = realfreq; - mgr->cur_clock_type = mgr->use_clock_type; - - /* unmute after codec speed modes */ - if (mgr->codec_speed != speed) { - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* unmute outputs */ - rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT; - if (DSP_EXT_CMD_SET(mgr)) { - rmh.cmd[1] = 1; - rmh.cmd_len = 2; - } - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - mgr->codec_speed = speed; /* save new codec speed */ - } - - snd_printdd("pcxhr_sub_set_clock to %dHz (realfreq=%d)\n", - rate, realfreq); - return 0; -} - -#define PCXHR_MODIFY_CLOCK_S_BIT 0x04 - -#define PCXHR_IRQ_TIMER_FREQ 92000 -#define PCXHR_IRQ_TIMER_PERIOD 48 - -int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate) -{ - struct pcxhr_rmh rmh; - int err, changed; - - if (rate == 0) - return 0; /* nothing to do */ - - if (mgr->is_hr_stereo) - err = hr222_sub_set_clock(mgr, rate, &changed); - else - err = pcxhr_sub_set_clock(mgr, rate, &changed); - - if (err) - return err; - - if (changed) { - pcxhr_init_rmh(&rmh, CMD_MODIFY_CLOCK); - rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT; /* resync fifos */ - if (rate < PCXHR_IRQ_TIMER_FREQ) - rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD; - else - rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD * 2; - rmh.cmd[2] = rate; - rmh.cmd_len = 3; - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - } - return 0; -} - - -static int pcxhr_sub_get_external_clock(struct pcxhr_mgr *mgr, - enum pcxhr_clock_type clock_type, - int *sample_rate) -{ - struct pcxhr_rmh rmh; - unsigned char reg; - int err, rate; - - switch (clock_type) { - case PCXHR_CLOCK_TYPE_WORD_CLOCK: - reg = REG_STATUS_WORD_CLOCK; - break; - case PCXHR_CLOCK_TYPE_AES_SYNC: - reg = REG_STATUS_AES_SYNC; - break; - case PCXHR_CLOCK_TYPE_AES_1: - reg = REG_STATUS_AES_1; - break; - case PCXHR_CLOCK_TYPE_AES_2: - reg = REG_STATUS_AES_2; - break; - case PCXHR_CLOCK_TYPE_AES_3: - reg = REG_STATUS_AES_3; - break; - case PCXHR_CLOCK_TYPE_AES_4: - reg = REG_STATUS_AES_4; - break; - default: - return -EINVAL; - } - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); - rmh.cmd_len = 2; - rmh.cmd[0] |= IO_NUM_REG_STATUS; - if (mgr->last_reg_stat != reg) { - rmh.cmd[1] = reg; - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - udelay(100); /* wait minimum 2 sample_frames at 32kHz ! */ - mgr->last_reg_stat = reg; - } - rmh.cmd[1] = REG_STATUS_CURRENT; - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - switch (rmh.stat[1] & 0x0f) { - case REG_STATUS_SYNC_32000 : rate = 32000; break; - case REG_STATUS_SYNC_44100 : rate = 44100; break; - case REG_STATUS_SYNC_48000 : rate = 48000; break; - case REG_STATUS_SYNC_64000 : rate = 64000; break; - case REG_STATUS_SYNC_88200 : rate = 88200; break; - case REG_STATUS_SYNC_96000 : rate = 96000; break; - case REG_STATUS_SYNC_128000 : rate = 128000; break; - case REG_STATUS_SYNC_176400 : rate = 176400; break; - case REG_STATUS_SYNC_192000 : rate = 192000; break; - default: rate = 0; - } - snd_printdd("External clock is at %d Hz\n", rate); - *sample_rate = rate; - return 0; -} - - -int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, - enum pcxhr_clock_type clock_type, - int *sample_rate) -{ - if (mgr->is_hr_stereo) - return hr222_get_external_clock(mgr, clock_type, - sample_rate); - else - return pcxhr_sub_get_external_clock(mgr, clock_type, - sample_rate); -} - -/* - * start or stop playback/capture substream - */ -static int pcxhr_set_stream_state(struct pcxhr_stream *stream) -{ - int err; - struct snd_pcxhr *chip; - struct pcxhr_rmh rmh; - int stream_mask, start; - - if (stream->status == PCXHR_STREAM_STATUS_SCHEDULE_RUN) - start = 1; - else { - if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) { - snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state " - "CANNOT be stopped\n"); - return -EINVAL; - } - start = 0; - } - if (!stream->substream) - return -EINVAL; - - stream->timer_abs_periods = 0; - stream->timer_period_frag = 0; /* reset theoretical stream pos */ - stream->timer_buf_periods = 0; - stream->timer_is_synced = 0; - - stream_mask = - stream->pipe->is_capture ? 1 : 1<substream->number; - - pcxhr_init_rmh(&rmh, start ? CMD_START_STREAM : CMD_STOP_STREAM); - pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture, - stream->pipe->first_audio, 0, stream_mask); - - chip = snd_pcm_substream_chip(stream->substream); - - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err) - snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n", - err); - stream->status = - start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED; - return err; -} - -#define HEADER_FMT_BASE_LIN 0xfed00000 -#define HEADER_FMT_BASE_FLOAT 0xfad00000 -#define HEADER_FMT_INTEL 0x00008000 -#define HEADER_FMT_24BITS 0x00004000 -#define HEADER_FMT_16BITS 0x00002000 -#define HEADER_FMT_UPTO11 0x00000200 -#define HEADER_FMT_UPTO32 0x00000100 -#define HEADER_FMT_MONO 0x00000080 - -static int pcxhr_set_format(struct pcxhr_stream *stream) -{ - int err, is_capture, sample_rate, stream_num; - struct snd_pcxhr *chip; - struct pcxhr_rmh rmh; - unsigned int header; - - switch (stream->format) { - case SNDRV_PCM_FORMAT_U8: - header = HEADER_FMT_BASE_LIN; - break; - case SNDRV_PCM_FORMAT_S16_LE: - header = HEADER_FMT_BASE_LIN | - HEADER_FMT_16BITS | HEADER_FMT_INTEL; - break; - case SNDRV_PCM_FORMAT_S16_BE: - header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS; - break; - case SNDRV_PCM_FORMAT_S24_3LE: - header = HEADER_FMT_BASE_LIN | - HEADER_FMT_24BITS | HEADER_FMT_INTEL; - break; - case SNDRV_PCM_FORMAT_S24_3BE: - header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS; - break; - case SNDRV_PCM_FORMAT_FLOAT_LE: - header = HEADER_FMT_BASE_FLOAT | HEADER_FMT_INTEL; - break; - default: - snd_printk(KERN_ERR - "error pcxhr_set_format() : unknown format\n"); - return -EINVAL; - } - chip = snd_pcm_substream_chip(stream->substream); - - sample_rate = chip->mgr->sample_rate; - if (sample_rate <= 32000 && sample_rate !=0) { - if (sample_rate <= 11025) - header |= HEADER_FMT_UPTO11; - else - header |= HEADER_FMT_UPTO32; - } - if (stream->channels == 1) - header |= HEADER_FMT_MONO; - - is_capture = stream->pipe->is_capture; - stream_num = is_capture ? 0 : stream->substream->number; - - pcxhr_init_rmh(&rmh, is_capture ? - CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT); - pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, - stream_num, 0); - if (is_capture) { - /* bug with old dsp versions: */ - /* bit 12 also sets the format of the playback stream */ - if (DSP_EXT_CMD_SET(chip->mgr)) - rmh.cmd[0] |= 1<<10; - else - rmh.cmd[0] |= 1<<12; - } - rmh.cmd[1] = 0; - rmh.cmd_len = 2; - if (DSP_EXT_CMD_SET(chip->mgr)) { - /* add channels and set bit 19 if channels>2 */ - rmh.cmd[1] = stream->channels; - if (!is_capture) { - /* playback : add channel mask to command */ - rmh.cmd[2] = (stream->channels == 1) ? 0x01 : 0x03; - rmh.cmd_len = 3; - } - } - rmh.cmd[rmh.cmd_len++] = header >> 8; - rmh.cmd[rmh.cmd_len++] = (header & 0xff) << 16; - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err) - snd_printk(KERN_ERR "ERROR pcxhr_set_format err=%x;\n", err); - return err; -} - -static int pcxhr_update_r_buffer(struct pcxhr_stream *stream) -{ - int err, is_capture, stream_num; - struct pcxhr_rmh rmh; - struct snd_pcm_substream *subs = stream->substream; - struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); - - is_capture = (subs->stream == SNDRV_PCM_STREAM_CAPTURE); - stream_num = is_capture ? 0 : subs->number; - - snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : " - "addr(%p) bytes(%zx) subs(%d)\n", - is_capture ? 'c' : 'p', - chip->chip_idx, (void *)(long)subs->runtime->dma_addr, - subs->runtime->dma_bytes, subs->number); - - pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS); - pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, - stream_num, 0); - - /* max buffer size is 2 MByte */ - snd_BUG_ON(subs->runtime->dma_bytes >= 0x200000); - /* size in bits */ - rmh.cmd[1] = subs->runtime->dma_bytes * 8; - /* most significant byte */ - rmh.cmd[2] = subs->runtime->dma_addr >> 24; - /* this is a circular buffer */ - rmh.cmd[2] |= 1<<19; - /* least 3 significant bytes */ - rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD; - rmh.cmd_len = 4; - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err) - snd_printk(KERN_ERR - "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err); - return err; -} - - -#if 0 -static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream, - snd_pcm_uframes_t *sample_count) -{ - struct pcxhr_rmh rmh; - int err; - pcxhr_t *chip = snd_pcm_substream_chip(stream->substream); - pcxhr_init_rmh(&rmh, CMD_PIPE_SAMPLE_COUNT); - pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture, 0, 0, - 1<pipe->first_audio); - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err == 0) { - *sample_count = ((snd_pcm_uframes_t)rmh.stat[0]) << 24; - *sample_count += (snd_pcm_uframes_t)rmh.stat[1]; - } - snd_printdd("PIPE_SAMPLE_COUNT = %lx\n", *sample_count); - return err; -} -#endif - -static inline int pcxhr_stream_scheduled_get_pipe(struct pcxhr_stream *stream, - struct pcxhr_pipe **pipe) -{ - if (stream->status == PCXHR_STREAM_STATUS_SCHEDULE_RUN) { - *pipe = stream->pipe; - return 1; - } - return 0; -} - -static void pcxhr_trigger_tasklet(unsigned long arg) -{ - unsigned long flags; - int i, j, err; - struct pcxhr_pipe *pipe; - struct snd_pcxhr *chip; - struct pcxhr_mgr *mgr = (struct pcxhr_mgr*)(arg); - int capture_mask = 0; - int playback_mask = 0; - -#ifdef CONFIG_SND_DEBUG_VERBOSE - struct timeval my_tv1, my_tv2; - do_gettimeofday(&my_tv1); -#endif - mutex_lock(&mgr->setup_mutex); - - /* check the pipes concerned and build pipe_array */ - for (i = 0; i < mgr->num_cards; i++) { - chip = mgr->chip[i]; - for (j = 0; j < chip->nb_streams_capt; j++) { - if (pcxhr_stream_scheduled_get_pipe(&chip->capture_stream[j], &pipe)) - capture_mask |= (1 << pipe->first_audio); - } - for (j = 0; j < chip->nb_streams_play; j++) { - if (pcxhr_stream_scheduled_get_pipe(&chip->playback_stream[j], &pipe)) { - playback_mask |= (1 << pipe->first_audio); - break; /* add only once, as all playback - * streams of one chip use the same pipe - */ - } - } - } - if (capture_mask == 0 && playback_mask == 0) { - mutex_unlock(&mgr->setup_mutex); - snd_printk(KERN_ERR "pcxhr_trigger_tasklet : no pipes\n"); - return; - } - - snd_printdd("pcxhr_trigger_tasklet : " - "playback_mask=%x capture_mask=%x\n", - playback_mask, capture_mask); - - /* synchronous stop of all the pipes concerned */ - err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); - if (err) { - mutex_unlock(&mgr->setup_mutex); - snd_printk(KERN_ERR "pcxhr_trigger_tasklet : " - "error stop pipes (P%x C%x)\n", - playback_mask, capture_mask); - return; - } - - /* the dsp lost format and buffer info with the stop pipe */ - for (i = 0; i < mgr->num_cards; i++) { - struct pcxhr_stream *stream; - chip = mgr->chip[i]; - for (j = 0; j < chip->nb_streams_capt; j++) { - stream = &chip->capture_stream[j]; - if (pcxhr_stream_scheduled_get_pipe(stream, &pipe)) { - err = pcxhr_set_format(stream); - err = pcxhr_update_r_buffer(stream); - } - } - for (j = 0; j < chip->nb_streams_play; j++) { - stream = &chip->playback_stream[j]; - if (pcxhr_stream_scheduled_get_pipe(stream, &pipe)) { - err = pcxhr_set_format(stream); - err = pcxhr_update_r_buffer(stream); - } - } - } - /* start all the streams */ - for (i = 0; i < mgr->num_cards; i++) { - struct pcxhr_stream *stream; - chip = mgr->chip[i]; - for (j = 0; j < chip->nb_streams_capt; j++) { - stream = &chip->capture_stream[j]; - if (pcxhr_stream_scheduled_get_pipe(stream, &pipe)) - err = pcxhr_set_stream_state(stream); - } - for (j = 0; j < chip->nb_streams_play; j++) { - stream = &chip->playback_stream[j]; - if (pcxhr_stream_scheduled_get_pipe(stream, &pipe)) - err = pcxhr_set_stream_state(stream); - } - } - - /* synchronous start of all the pipes concerned */ - err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); - if (err) { - mutex_unlock(&mgr->setup_mutex); - snd_printk(KERN_ERR "pcxhr_trigger_tasklet : " - "error start pipes (P%x C%x)\n", - playback_mask, capture_mask); - return; - } - - /* put the streams into the running state now - * (increment pointer by interrupt) - */ - spin_lock_irqsave(&mgr->lock, flags); - for ( i =0; i < mgr->num_cards; i++) { - struct pcxhr_stream *stream; - chip = mgr->chip[i]; - for(j = 0; j < chip->nb_streams_capt; j++) { - stream = &chip->capture_stream[j]; - if(stream->status == PCXHR_STREAM_STATUS_STARTED) - stream->status = PCXHR_STREAM_STATUS_RUNNING; - } - for (j = 0; j < chip->nb_streams_play; j++) { - stream = &chip->playback_stream[j]; - if (stream->status == PCXHR_STREAM_STATUS_STARTED) { - /* playback will already have advanced ! */ - stream->timer_period_frag += mgr->granularity; - stream->status = PCXHR_STREAM_STATUS_RUNNING; - } - } - } - spin_unlock_irqrestore(&mgr->lock, flags); - - mutex_unlock(&mgr->setup_mutex); - -#ifdef CONFIG_SND_DEBUG_VERBOSE - do_gettimeofday(&my_tv2); - snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n", - (long)(my_tv2.tv_usec - my_tv1.tv_usec), err); -#endif -} - - -/* - * trigger callback - */ -static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct pcxhr_stream *stream; - struct snd_pcm_substream *s; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_printdd("SNDRV_PCM_TRIGGER_START\n"); - if (snd_pcm_stream_linked(subs)) { - struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); - snd_pcm_group_for_each_entry(s, subs) { - if (snd_pcm_substream_chip(s) != chip) - continue; - stream = s->runtime->private_data; - stream->status = - PCXHR_STREAM_STATUS_SCHEDULE_RUN; - snd_pcm_trigger_done(s, subs); - } - tasklet_schedule(&chip->mgr->trigger_taskq); - } else { - stream = subs->runtime->private_data; - snd_printdd("Only one Substream %c %d\n", - stream->pipe->is_capture ? 'C' : 'P', - stream->pipe->first_audio); - if (pcxhr_set_format(stream)) - return -EINVAL; - if (pcxhr_update_r_buffer(stream)) - return -EINVAL; - - stream->status = PCXHR_STREAM_STATUS_SCHEDULE_RUN; - if (pcxhr_set_stream_state(stream)) - return -EINVAL; - stream->status = PCXHR_STREAM_STATUS_RUNNING; - } - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_printdd("SNDRV_PCM_TRIGGER_STOP\n"); - snd_pcm_group_for_each_entry(s, subs) { - stream = s->runtime->private_data; - stream->status = PCXHR_STREAM_STATUS_SCHEDULE_STOP; - if (pcxhr_set_stream_state(stream)) - return -EINVAL; - snd_pcm_trigger_done(s, subs); - } - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - /* TODO */ - default: - return -EINVAL; - } - return 0; -} - - -static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start) -{ - struct pcxhr_rmh rmh; - int err; - - pcxhr_init_rmh(&rmh, CMD_SET_TIMER_INTERRUPT); - if (start) { - /* last dsp time invalid */ - mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; - rmh.cmd[0] |= mgr->granularity; - } - err = pcxhr_send_msg(mgr, &rmh); - if (err < 0) - snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n", - err); - return err; -} - -/* - * prepare callback for all pcms - */ -static int pcxhr_prepare(struct snd_pcm_substream *subs) -{ - struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); - struct pcxhr_mgr *mgr = chip->mgr; - int err = 0; - - snd_printdd("pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n", - subs->runtime->period_size, subs->runtime->periods, - subs->runtime->buffer_size); - - mutex_lock(&mgr->setup_mutex); - - do { - /* only the first stream can choose the sample rate */ - /* set the clock only once (first stream) */ - if (mgr->sample_rate != subs->runtime->rate) { - err = pcxhr_set_clock(mgr, subs->runtime->rate); - if (err) - break; - if (mgr->sample_rate == 0) - /* start the DSP-timer */ - err = pcxhr_hardware_timer(mgr, 1); - mgr->sample_rate = subs->runtime->rate; - } - } while(0); /* do only once (so we can use break instead of goto) */ - - mutex_unlock(&mgr->setup_mutex); - - return err; -} - - -/* - * HW_PARAMS callback for all pcms - */ -static int pcxhr_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw) -{ - struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); - struct pcxhr_mgr *mgr = chip->mgr; - struct pcxhr_stream *stream = subs->runtime->private_data; - snd_pcm_format_t format; - int err; - int channels; - - /* set up channels */ - channels = params_channels(hw); - - /* set up format for the stream */ - format = params_format(hw); - - mutex_lock(&mgr->setup_mutex); - - stream->channels = channels; - stream->format = format; - - /* allocate buffer */ - err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw)); - - mutex_unlock(&mgr->setup_mutex); - - return err; -} - -static int pcxhr_hw_free(struct snd_pcm_substream *subs) -{ - snd_pcm_lib_free_pages(subs); - return 0; -} - - -/* - * CONFIGURATION SPACE for all pcms, mono pcm must update channels_max - */ -static struct snd_pcm_hardware pcxhr_caps = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S24_3BE | - SNDRV_PCM_FMTBIT_FLOAT_LE), - .rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_192000), - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - /* 1 byte == 1 frame U8 mono (PCXHR_GRANULARITY is frames!) */ - .period_bytes_min = (2*PCXHR_GRANULARITY), - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = (32*1024/PCXHR_GRANULARITY), -}; - - -static int pcxhr_open(struct snd_pcm_substream *subs) -{ - struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); - struct pcxhr_mgr *mgr = chip->mgr; - struct snd_pcm_runtime *runtime = subs->runtime; - struct pcxhr_stream *stream; - int err; - - mutex_lock(&mgr->setup_mutex); - - /* copy the struct snd_pcm_hardware struct */ - runtime->hw = pcxhr_caps; - - if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) { - snd_printdd("pcxhr_open playback chip%d subs%d\n", - chip->chip_idx, subs->number); - stream = &chip->playback_stream[subs->number]; - } else { - snd_printdd("pcxhr_open capture chip%d subs%d\n", - chip->chip_idx, subs->number); - if (mgr->mono_capture) - runtime->hw.channels_max = 1; - else - runtime->hw.channels_min = 2; - stream = &chip->capture_stream[subs->number]; - } - if (stream->status != PCXHR_STREAM_STATUS_FREE){ - /* streams in use */ - snd_printk(KERN_ERR "pcxhr_open chip%d subs%d in use\n", - chip->chip_idx, subs->number); - mutex_unlock(&mgr->setup_mutex); - return -EBUSY; - } - - /* float format support is in some cases buggy on stereo cards */ - if (mgr->is_hr_stereo) - runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_FLOAT_LE; - - /* buffer-size should better be multiple of period-size */ - err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - mutex_unlock(&mgr->setup_mutex); - return err; - } - - /* if a sample rate is already used or fixed by external clock, - * the stream cannot change - */ - if (mgr->sample_rate) - runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate; - else { - if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) { - int external_rate; - if (pcxhr_get_external_clock(mgr, mgr->use_clock_type, - &external_rate) || - external_rate == 0) { - /* cannot detect the external clock rate */ - mutex_unlock(&mgr->setup_mutex); - return -EBUSY; - } - runtime->hw.rate_min = external_rate; - runtime->hw.rate_max = external_rate; - } - } - - stream->status = PCXHR_STREAM_STATUS_OPEN; - stream->substream = subs; - stream->channels = 0; /* not configured yet */ - - runtime->private_data = stream; - - /* better get a divisor of granularity values (96 or 192) */ - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32); - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32); - snd_pcm_set_sync(subs); - - mgr->ref_count_rate++; - - mutex_unlock(&mgr->setup_mutex); - return 0; -} - - -static int pcxhr_close(struct snd_pcm_substream *subs) -{ - struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); - struct pcxhr_mgr *mgr = chip->mgr; - struct pcxhr_stream *stream = subs->runtime->private_data; - - mutex_lock(&mgr->setup_mutex); - - snd_printdd("pcxhr_close chip%d subs%d\n", - chip->chip_idx, subs->number); - - /* sample rate released */ - if (--mgr->ref_count_rate == 0) { - mgr->sample_rate = 0; /* the sample rate is no more locked */ - pcxhr_hardware_timer(mgr, 0); /* stop the DSP-timer */ - } - - stream->status = PCXHR_STREAM_STATUS_FREE; - stream->substream = NULL; - - mutex_unlock(&mgr->setup_mutex); - - return 0; -} - - -static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs) -{ - unsigned long flags; - u_int32_t timer_period_frag; - int timer_buf_periods; - struct snd_pcxhr *chip = snd_pcm_substream_chip(subs); - struct snd_pcm_runtime *runtime = subs->runtime; - struct pcxhr_stream *stream = runtime->private_data; - - spin_lock_irqsave(&chip->mgr->lock, flags); - - /* get the period fragment and the nb of periods in the buffer */ - timer_period_frag = stream->timer_period_frag; - timer_buf_periods = stream->timer_buf_periods; - - spin_unlock_irqrestore(&chip->mgr->lock, flags); - - return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) + - timer_period_frag); -} - - -static struct snd_pcm_ops pcxhr_ops = { - .open = pcxhr_open, - .close = pcxhr_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = pcxhr_prepare, - .hw_params = pcxhr_hw_params, - .hw_free = pcxhr_hw_free, - .trigger = pcxhr_trigger, - .pointer = pcxhr_stream_pointer, -}; - -/* - */ -int pcxhr_create_pcm(struct snd_pcxhr *chip) -{ - int err; - struct snd_pcm *pcm; - char name[32]; - - sprintf(name, "pcxhr %d", chip->chip_idx); - if ((err = snd_pcm_new(chip->card, name, 0, - chip->nb_streams_play, - chip->nb_streams_capt, &pcm)) < 0) { - snd_printk(KERN_ERR "cannot create pcm %s\n", name); - return err; - } - pcm->private_data = chip; - - if (chip->nb_streams_play) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcxhr_ops); - if (chip->nb_streams_capt) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, name); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->mgr->pci), - 32*1024, 32*1024); - chip->pcm = pcm; - return 0; -} - -static int pcxhr_chip_free(struct snd_pcxhr *chip) -{ - kfree(chip); - return 0; -} - -static int pcxhr_chip_dev_free(struct snd_device *device) -{ - struct snd_pcxhr *chip = device->device_data; - return pcxhr_chip_free(chip); -} - - -/* - */ -static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, - struct snd_card *card, int idx) -{ - int err; - struct snd_pcxhr *chip; - static struct snd_device_ops ops = { - .dev_free = pcxhr_chip_dev_free, - }; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (! chip) { - snd_printk(KERN_ERR "cannot allocate chip\n"); - return -ENOMEM; - } - - chip->card = card; - chip->chip_idx = idx; - chip->mgr = mgr; - - if (idx < mgr->playback_chips) - /* stereo or mono streams */ - chip->nb_streams_play = PCXHR_PLAYBACK_STREAMS; - - if (idx < mgr->capture_chips) { - if (mgr->mono_capture) - chip->nb_streams_capt = 2; /* 2 mono streams */ - else - chip->nb_streams_capt = 1; /* or 1 stereo stream */ - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - pcxhr_chip_free(chip); - return err; - } - - mgr->chip[idx] = chip; - snd_card_set_dev(card, &mgr->pci->dev); - - return 0; -} - -/* proc interface */ -static void pcxhr_proc_info(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcxhr *chip = entry->private_data; - struct pcxhr_mgr *mgr = chip->mgr; - - snd_iprintf(buffer, "\n%s\n", mgr->longname); - - /* stats available when embedded DSP is running */ - if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) { - struct pcxhr_rmh rmh; - short ver_maj = (mgr->dsp_version >> 16) & 0xff; - short ver_min = (mgr->dsp_version >> 8) & 0xff; - short ver_build = mgr->dsp_version & 0xff; - snd_iprintf(buffer, "module version %s\n", - PCXHR_DRIVER_VERSION_STRING); - snd_iprintf(buffer, "dsp version %d.%d.%d\n", - ver_maj, ver_min, ver_build); - if (mgr->board_has_analog) - snd_iprintf(buffer, "analog io available\n"); - else - snd_iprintf(buffer, "digital only board\n"); - - /* calc cpu load of the dsp */ - pcxhr_init_rmh(&rmh, CMD_GET_DSP_RESOURCES); - if( ! pcxhr_send_msg(mgr, &rmh) ) { - int cur = rmh.stat[0]; - int ref = rmh.stat[1]; - if (ref > 0) { - if (mgr->sample_rate_real != 0 && - mgr->sample_rate_real != 48000) { - ref = (ref * 48000) / - mgr->sample_rate_real; - if (mgr->sample_rate_real >= - PCXHR_IRQ_TIMER_FREQ) - ref *= 2; - } - cur = 100 - (100 * cur) / ref; - snd_iprintf(buffer, "cpu load %d%%\n", cur); - snd_iprintf(buffer, "buffer pool %d/%d\n", - rmh.stat[2], rmh.stat[3]); - } - } - snd_iprintf(buffer, "dma granularity : %d\n", - mgr->granularity); - snd_iprintf(buffer, "dsp time errors : %d\n", - mgr->dsp_time_err); - snd_iprintf(buffer, "dsp async pipe xrun errors : %d\n", - mgr->async_err_pipe_xrun); - snd_iprintf(buffer, "dsp async stream xrun errors : %d\n", - mgr->async_err_stream_xrun); - snd_iprintf(buffer, "dsp async last other error : %x\n", - mgr->async_err_other_last); - /* debug zone dsp */ - rmh.cmd[0] = 0x4200 + PCXHR_SIZE_MAX_STATUS; - rmh.cmd_len = 1; - rmh.stat_len = PCXHR_SIZE_MAX_STATUS; - rmh.dsp_stat = 0; - rmh.cmd_idx = CMD_LAST_INDEX; - if( ! pcxhr_send_msg(mgr, &rmh) ) { - int i; - if (rmh.stat_len > 8) - rmh.stat_len = 8; - for (i = 0; i < rmh.stat_len; i++) - snd_iprintf(buffer, "debug[%02d] = %06x\n", - i, rmh.stat[i]); - } - } else - snd_iprintf(buffer, "no firmware loaded\n"); - snd_iprintf(buffer, "\n"); -} -static void pcxhr_proc_sync(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcxhr *chip = entry->private_data; - struct pcxhr_mgr *mgr = chip->mgr; - static const char *textsHR22[3] = { - "Internal", "AES Sync", "AES 1" - }; - static const char *textsPCXHR[7] = { - "Internal", "Word", "AES Sync", - "AES 1", "AES 2", "AES 3", "AES 4" - }; - const char **texts; - int max_clock; - if (mgr->is_hr_stereo) { - texts = textsHR22; - max_clock = HR22_CLOCK_TYPE_MAX; - } else { - texts = textsPCXHR; - max_clock = PCXHR_CLOCK_TYPE_MAX; - } - - snd_iprintf(buffer, "\n%s\n", mgr->longname); - snd_iprintf(buffer, "Current Sample Clock\t: %s\n", - texts[mgr->cur_clock_type]); - snd_iprintf(buffer, "Current Sample Rate\t= %d\n", - mgr->sample_rate_real); - /* commands available when embedded DSP is running */ - if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) { - int i, err, sample_rate; - for (i = 1; i <= max_clock; i++) { - err = pcxhr_get_external_clock(mgr, i, &sample_rate); - if (err) - break; - snd_iprintf(buffer, "%s Clock\t\t= %d\n", - texts[i], sample_rate); - } - } else - snd_iprintf(buffer, "no firmware loaded\n"); - snd_iprintf(buffer, "\n"); -} - -static void pcxhr_proc_gpio_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcxhr *chip = entry->private_data; - struct pcxhr_mgr *mgr = chip->mgr; - /* commands available when embedded DSP is running */ - if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) { - /* gpio ports on stereo boards only available */ - int value = 0; - hr222_read_gpio(mgr, 1, &value); /* GPI */ - snd_iprintf(buffer, "GPI: 0x%x\n", value); - hr222_read_gpio(mgr, 0, &value); /* GP0 */ - snd_iprintf(buffer, "GPO: 0x%x\n", value); - } else - snd_iprintf(buffer, "no firmware loaded\n"); - snd_iprintf(buffer, "\n"); -} -static void pcxhr_proc_gpo_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_pcxhr *chip = entry->private_data; - struct pcxhr_mgr *mgr = chip->mgr; - char line[64]; - int value; - /* commands available when embedded DSP is running */ - if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))) - return; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "GPO: 0x%x", &value) != 1) - continue; - hr222_write_gpo(mgr, value); /* GP0 */ - } -} - -static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "info", &entry)) - snd_info_set_text_ops(entry, chip, pcxhr_proc_info); - if (! snd_card_proc_new(chip->card, "sync", &entry)) - snd_info_set_text_ops(entry, chip, pcxhr_proc_sync); - /* gpio available on stereo sound cards only */ - if (chip->mgr->is_hr_stereo && - !snd_card_proc_new(chip->card, "gpio", &entry)) { - snd_info_set_text_ops(entry, chip, pcxhr_proc_gpio_read); - entry->c.text.write = pcxhr_proc_gpo_write; - entry->mode |= S_IWUSR; - } -} -/* end of proc interface */ - -/* - * release all the cards assigned to a manager instance - */ -static int pcxhr_free(struct pcxhr_mgr *mgr) -{ - unsigned int i; - - for (i = 0; i < mgr->num_cards; i++) { - if (mgr->chip[i]) - snd_card_free(mgr->chip[i]->card); - } - - /* reset board if some firmware was loaded */ - if(mgr->dsp_loaded) { - pcxhr_reset_board(mgr); - snd_printdd("reset pcxhr !\n"); - } - - /* release irq */ - if (mgr->irq >= 0) - free_irq(mgr->irq, mgr); - - pci_release_regions(mgr->pci); - - /* free hostport purgebuffer */ - if (mgr->hostport.area) { - snd_dma_free_pages(&mgr->hostport); - mgr->hostport.area = NULL; - } - - kfree(mgr->prmh); - - pci_disable_device(mgr->pci); - kfree(mgr); - return 0; -} - -/* - * probe function - creates the card manager - */ -static int __devinit pcxhr_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct pcxhr_mgr *mgr; - unsigned int i; - int err; - size_t size; - char *card_name; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (! enable[dev]) { - dev++; - return -ENOENT; - } - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - pci_set_master(pci); - - /* check if we can restrict PCI DMA transfers to 32 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(32)) < 0) { - snd_printk(KERN_ERR "architecture does not support " - "32bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - /* alloc card manager */ - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - if (! mgr) { - pci_disable_device(pci); - return -ENOMEM; - } - - if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST)) { - kfree(mgr); - pci_disable_device(pci); - return -ENODEV; - } - card_name = - pcxhr_board_params[pci_id->driver_data].board_name; - mgr->playback_chips = - pcxhr_board_params[pci_id->driver_data].playback_chips; - mgr->capture_chips = - pcxhr_board_params[pci_id->driver_data].capture_chips; - mgr->fw_file_set = - pcxhr_board_params[pci_id->driver_data].fw_file_set; - mgr->firmware_num = - pcxhr_board_params[pci_id->driver_data].firmware_num; - mgr->mono_capture = mono[dev]; - mgr->is_hr_stereo = (mgr->playback_chips == 1); - mgr->board_has_aes1 = PCXHR_BOARD_HAS_AES1(mgr); - mgr->board_aes_in_192k = !PCXHR_BOARD_AESIN_NO_192K(mgr); - - if (mgr->is_hr_stereo) - mgr->granularity = PCXHR_GRANULARITY_HR22; - else - mgr->granularity = PCXHR_GRANULARITY; - - /* resource assignment */ - if ((err = pci_request_regions(pci, card_name)) < 0) { - kfree(mgr); - pci_disable_device(pci); - return err; - } - for (i = 0; i < 3; i++) - mgr->port[i] = pci_resource_start(pci, i); - - mgr->pci = pci; - mgr->irq = -1; - - if (request_irq(pci->irq, pcxhr_interrupt, IRQF_SHARED, - KBUILD_MODNAME, mgr)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - pcxhr_free(mgr); - return -EBUSY; - } - mgr->irq = pci->irq; - - sprintf(mgr->shortname, "Digigram %s", card_name); - sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i", - mgr->shortname, - mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq); - - /* ISR spinlock */ - spin_lock_init(&mgr->lock); - spin_lock_init(&mgr->msg_lock); - - /* init setup mutex*/ - mutex_init(&mgr->setup_mutex); - - /* init taslket */ - tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, - (unsigned long) mgr); - tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet, - (unsigned long) mgr); - - mgr->prmh = kmalloc(sizeof(*mgr->prmh) + - sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - - PCXHR_SIZE_MAX_STATUS), - GFP_KERNEL); - if (! mgr->prmh) { - pcxhr_free(mgr); - return -ENOMEM; - } - - for (i=0; i < PCXHR_MAX_CARDS; i++) { - struct snd_card *card; - char tmpid[16]; - int idx; - - if (i >= max(mgr->playback_chips, mgr->capture_chips)) - break; - mgr->num_cards++; - - if (index[dev] < 0) - idx = index[dev]; - else - idx = index[dev] + i; - - snprintf(tmpid, sizeof(tmpid), "%s-%d", - id[dev] ? id[dev] : card_name, i); - err = snd_card_create(idx, tmpid, THIS_MODULE, 0, &card); - - if (err < 0) { - snd_printk(KERN_ERR "cannot allocate the card %d\n", i); - pcxhr_free(mgr); - return err; - } - - strcpy(card->driver, DRIVER_NAME); - sprintf(card->shortname, "%s [PCM #%d]", mgr->shortname, i); - sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); - - if ((err = pcxhr_create(mgr, card, i)) < 0) { - snd_card_free(card); - pcxhr_free(mgr); - return err; - } - - if (i == 0) - /* init proc interface only for chip0 */ - pcxhr_proc_init(mgr->chip[i]); - - if ((err = snd_card_register(card)) < 0) { - pcxhr_free(mgr); - return err; - } - } - - /* create hostport purgebuffer */ - size = PAGE_ALIGN(sizeof(struct pcxhr_hostport)); - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, &mgr->hostport) < 0) { - pcxhr_free(mgr); - return -ENOMEM; - } - /* init purgebuffer */ - memset(mgr->hostport.area, 0, size); - - /* create a DSP loader */ - err = pcxhr_setup_firmware(mgr); - if (err < 0) { - pcxhr_free(mgr); - return err; - } - - pci_set_drvdata(pci, mgr); - dev++; - return 0; -} - -static void __devexit pcxhr_remove(struct pci_dev *pci) -{ - pcxhr_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = pcxhr_ids, - .probe = pcxhr_probe, - .remove = __devexit_p(pcxhr_remove), -}; - -static int __init pcxhr_module_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit pcxhr_module_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(pcxhr_module_init) -module_exit(pcxhr_module_exit) diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.h b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.h deleted file mode 100644 index bda776c4..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Driver for Digigram pcxhr soundcards - * - * main header file - * - * Copyright (c) 2004 by Digigram - * - * 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 - */ - -#ifndef __SOUND_PCXHR_H -#define __SOUND_PCXHR_H - -#include -#include -#include - -#define PCXHR_DRIVER_VERSION 0x000906 /* 0.9.6 */ -#define PCXHR_DRIVER_VERSION_STRING "0.9.6" /* 0.9.6 */ - - -#define PCXHR_MAX_CARDS 6 -#define PCXHR_PLAYBACK_STREAMS 4 - -#define PCXHR_GRANULARITY 96 /* min 96 and multiple of 48 */ -/* transfer granularity of pipes and the dsp time (MBOX4) */ -#define PCXHR_GRANULARITY_MIN 96 -/* TODO : granularity could be 64 or 128 */ -#define PCXHR_GRANULARITY_HR22 192 /* granularity for stereo cards */ - -struct snd_pcxhr; -struct pcxhr_mgr; - -struct pcxhr_stream; -struct pcxhr_pipe; - -enum pcxhr_clock_type { - PCXHR_CLOCK_TYPE_INTERNAL = 0, - PCXHR_CLOCK_TYPE_WORD_CLOCK, - PCXHR_CLOCK_TYPE_AES_SYNC, - PCXHR_CLOCK_TYPE_AES_1, - PCXHR_CLOCK_TYPE_AES_2, - PCXHR_CLOCK_TYPE_AES_3, - PCXHR_CLOCK_TYPE_AES_4, - PCXHR_CLOCK_TYPE_MAX = PCXHR_CLOCK_TYPE_AES_4, - HR22_CLOCK_TYPE_INTERNAL = PCXHR_CLOCK_TYPE_INTERNAL, - HR22_CLOCK_TYPE_AES_SYNC, - HR22_CLOCK_TYPE_AES_1, - HR22_CLOCK_TYPE_MAX = HR22_CLOCK_TYPE_AES_1, -}; - -struct pcxhr_mgr { - unsigned int num_cards; - struct snd_pcxhr *chip[PCXHR_MAX_CARDS]; - - struct pci_dev *pci; - - int irq; - - int granularity; - - /* card access with 1 mem bar and 2 io bar's */ - unsigned long port[3]; - - /* share the name */ - char shortname[32]; /* short name of this soundcard */ - char longname[96]; /* name of this soundcard */ - - /* message tasklet */ - struct tasklet_struct msg_taskq; - struct pcxhr_rmh *prmh; - /* trigger tasklet */ - struct tasklet_struct trigger_taskq; - - spinlock_t lock; /* interrupt spinlock */ - spinlock_t msg_lock; /* message spinlock */ - - struct mutex setup_mutex; /* mutex used in hw_params, open and close */ - struct mutex mixer_mutex; /* mutex for mixer */ - - /* hardware interface */ - unsigned int dsp_loaded; /* bit flags of loaded dsp indices */ - unsigned int dsp_version; /* read from embedded once firmware is loaded */ - int playback_chips; - int capture_chips; - int fw_file_set; - int firmware_num; - unsigned int is_hr_stereo:1; - unsigned int board_has_aes1:1; /* if 1 board has AES1 plug and SRC */ - unsigned int board_has_analog:1; /* if 0 the board is digital only */ - unsigned int board_has_mic:1; /* if 1 the board has microphone input */ - unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */ - unsigned int mono_capture:1; /* if 1 the board does mono capture */ - - struct snd_dma_buffer hostport; - - enum pcxhr_clock_type use_clock_type; /* clock type selected by mixer */ - enum pcxhr_clock_type cur_clock_type; /* current clock type synced */ - int sample_rate; - int ref_count_rate; - int timer_toggle; /* timer interrupt toggles between the two values 0x200 and 0x300 */ - int dsp_time_last; /* the last dsp time (read by interrupt) */ - int dsp_time_err; /* dsp time errors */ - unsigned int src_it_dsp; /* dsp interrupt source */ - unsigned int io_num_reg_cont; /* backup of IO_NUM_REG_CONT */ - unsigned int codec_speed; /* speed mode of the codecs */ - unsigned int sample_rate_real; /* current real sample rate */ - int last_reg_stat; - int async_err_stream_xrun; - int async_err_pipe_xrun; - int async_err_other_last; - - unsigned char xlx_cfg; /* copy of PCXHR_XLX_CFG register */ - unsigned char xlx_selmic; /* copy of PCXHR_XLX_SELMIC register */ - unsigned char dsp_reset; /* copy of PCXHR_DSP_RESET register */ -}; - - -enum pcxhr_stream_status { - PCXHR_STREAM_STATUS_FREE, - PCXHR_STREAM_STATUS_OPEN, - PCXHR_STREAM_STATUS_SCHEDULE_RUN, - PCXHR_STREAM_STATUS_STARTED, - PCXHR_STREAM_STATUS_RUNNING, - PCXHR_STREAM_STATUS_SCHEDULE_STOP, - PCXHR_STREAM_STATUS_STOPPED, - PCXHR_STREAM_STATUS_PAUSED -}; - -struct pcxhr_stream { - struct snd_pcm_substream *substream; - snd_pcm_format_t format; - struct pcxhr_pipe *pipe; - - enum pcxhr_stream_status status; /* free, open, running, draining, pause */ - - u_int64_t timer_abs_periods; /* timer: samples elapsed since TRIGGER_START (multiple of period_size) */ - u_int32_t timer_period_frag; /* timer: samples elapsed since last call to snd_pcm_period_elapsed (0..period_size) */ - u_int32_t timer_buf_periods; /* nb of periods in the buffer that have already elapsed */ - int timer_is_synced; /* if(0) : timer needs to be resynced with real hardware pointer */ - - int channels; -}; - - -enum pcxhr_pipe_status { - PCXHR_PIPE_UNDEFINED, - PCXHR_PIPE_DEFINED -}; - -struct pcxhr_pipe { - enum pcxhr_pipe_status status; - int is_capture; /* this is a capture pipe */ - int first_audio; /* first audio num */ -}; - - -struct snd_pcxhr { - struct snd_card *card; - struct pcxhr_mgr *mgr; - int chip_idx; /* zero based */ - - struct snd_pcm *pcm; /* PCM */ - - struct pcxhr_pipe playback_pipe; /* 1 stereo pipe only */ - struct pcxhr_pipe capture_pipe[2]; /* 1 stereo or 2 mono pipes */ - - struct pcxhr_stream playback_stream[PCXHR_PLAYBACK_STREAMS]; - struct pcxhr_stream capture_stream[2]; /* 1 stereo or 2 mono streams */ - int nb_streams_play; - int nb_streams_capt; - - int analog_playback_active[2]; /* Mixer : Master Playback !mute */ - int analog_playback_volume[2]; /* Mixer : Master Playback Volume */ - int analog_capture_volume[2]; /* Mixer : Master Capture Volume */ - int digital_playback_active[PCXHR_PLAYBACK_STREAMS][2]; - int digital_playback_volume[PCXHR_PLAYBACK_STREAMS][2]; - int digital_capture_volume[2]; /* Mixer : Digital Capture Volume */ - int monitoring_active[2]; /* Mixer : Monitoring Active */ - int monitoring_volume[2]; /* Mixer : Monitoring Volume */ - int audio_capture_source; /* Mixer : Audio Capture Source */ - int mic_volume; /* used by cards with MIC only */ - int mic_boost; /* used by cards with MIC only */ - int mic_active; /* used by cards with MIC only */ - int analog_capture_active; /* used by cards with MIC only */ - int phantom_power; /* used by cards with MIC only */ - - unsigned char aes_bits[5]; /* Mixer : IEC958_AES bits */ -}; - -struct pcxhr_hostport -{ - char purgebuffer[6]; - char reserved[2]; -}; - -/* exported */ -int pcxhr_create_pcm(struct snd_pcxhr *chip); -int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate); -int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, - enum pcxhr_clock_type clock_type, - int *sample_rate); - -#endif /* __SOUND_PCXHR_H */ diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.c b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.c deleted file mode 100644 index 304411c1..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.c +++ /dev/null @@ -1,1305 +0,0 @@ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * low level interface with interrupt and message handling implementation - * - * Copyright (c) 2004 by Digigram - * - * 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 "pcxhr.h" -#include "pcxhr_mixer.h" -#include "pcxhr_hwdep.h" -#include "pcxhr_core.h" - - -/* registers used on the PLX (port 1) */ -#define PCXHR_PLX_OFFSET_MIN 0x40 -#define PCXHR_PLX_MBOX0 0x40 -#define PCXHR_PLX_MBOX1 0x44 -#define PCXHR_PLX_MBOX2 0x48 -#define PCXHR_PLX_MBOX3 0x4C -#define PCXHR_PLX_MBOX4 0x50 -#define PCXHR_PLX_MBOX5 0x54 -#define PCXHR_PLX_MBOX6 0x58 -#define PCXHR_PLX_MBOX7 0x5C -#define PCXHR_PLX_L2PCIDB 0x64 -#define PCXHR_PLX_IRQCS 0x68 -#define PCXHR_PLX_CHIPSC 0x6C - -/* registers used on the DSP (port 2) */ -#define PCXHR_DSP_ICR 0x00 -#define PCXHR_DSP_CVR 0x04 -#define PCXHR_DSP_ISR 0x08 -#define PCXHR_DSP_IVR 0x0C -#define PCXHR_DSP_RXH 0x14 -#define PCXHR_DSP_TXH 0x14 -#define PCXHR_DSP_RXM 0x18 -#define PCXHR_DSP_TXM 0x18 -#define PCXHR_DSP_RXL 0x1C -#define PCXHR_DSP_TXL 0x1C -#define PCXHR_DSP_RESET 0x20 -#define PCXHR_DSP_OFFSET_MAX 0x20 - -/* access to the card */ -#define PCXHR_PLX 1 -#define PCXHR_DSP 2 - -#if (PCXHR_DSP_OFFSET_MAX > PCXHR_PLX_OFFSET_MIN) -#undef PCXHR_REG_TO_PORT(x) -#else -#define PCXHR_REG_TO_PORT(x) ((x)>PCXHR_DSP_OFFSET_MAX ? PCXHR_PLX : PCXHR_DSP) -#endif -#define PCXHR_INPB(mgr,x) inb((mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) -#define PCXHR_INPL(mgr,x) inl((mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) -#define PCXHR_OUTPB(mgr,x,data) outb((data), (mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) -#define PCXHR_OUTPL(mgr,x,data) outl((data), (mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) -/* attention : access the PCXHR_DSP_* registers with inb and outb only ! */ - -/* params used with PCXHR_PLX_MBOX0 */ -#define PCXHR_MBOX0_HF5 (1 << 0) -#define PCXHR_MBOX0_HF4 (1 << 1) -#define PCXHR_MBOX0_BOOT_HERE (1 << 23) -/* params used with PCXHR_PLX_IRQCS */ -#define PCXHR_IRQCS_ENABLE_PCIIRQ (1 << 8) -#define PCXHR_IRQCS_ENABLE_PCIDB (1 << 9) -#define PCXHR_IRQCS_ACTIVE_PCIDB (1 << 13) -/* params used with PCXHR_PLX_CHIPSC */ -#define PCXHR_CHIPSC_INIT_VALUE 0x100D767E -#define PCXHR_CHIPSC_RESET_XILINX (1 << 16) -#define PCXHR_CHIPSC_GPI_USERI (1 << 17) -#define PCXHR_CHIPSC_DATA_CLK (1 << 24) -#define PCXHR_CHIPSC_DATA_IN (1 << 26) - -/* params used with PCXHR_DSP_ICR */ -#define PCXHR_ICR_HI08_RREQ 0x01 -#define PCXHR_ICR_HI08_TREQ 0x02 -#define PCXHR_ICR_HI08_HDRQ 0x04 -#define PCXHR_ICR_HI08_HF0 0x08 -#define PCXHR_ICR_HI08_HF1 0x10 -#define PCXHR_ICR_HI08_HLEND 0x20 -#define PCXHR_ICR_HI08_INIT 0x80 -/* params used with PCXHR_DSP_CVR */ -#define PCXHR_CVR_HI08_HC 0x80 -/* params used with PCXHR_DSP_ISR */ -#define PCXHR_ISR_HI08_RXDF 0x01 -#define PCXHR_ISR_HI08_TXDE 0x02 -#define PCXHR_ISR_HI08_TRDY 0x04 -#define PCXHR_ISR_HI08_ERR 0x08 -#define PCXHR_ISR_HI08_CHK 0x10 -#define PCXHR_ISR_HI08_HREQ 0x80 - - -/* constants used for delay in msec */ -#define PCXHR_WAIT_DEFAULT 2 -#define PCXHR_WAIT_IT 25 -#define PCXHR_WAIT_IT_EXTRA 65 - -/* - * pcxhr_check_reg_bit - wait for the specified bit is set/reset on a register - * @reg: register to check - * @mask: bit mask - * @bit: resultant bit to be checked - * @time: time-out of loop in msec - * - * returns zero if a bit matches, or a negative error code. - */ -static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg, - unsigned char mask, unsigned char bit, int time, - unsigned char* read) -{ - int i = 0; - unsigned long end_time = jiffies + (time * HZ + 999) / 1000; - do { - *read = PCXHR_INPB(mgr, reg); - if ((*read & mask) == bit) { - if (i > 100) - snd_printdd("ATTENTION! check_reg(%x) " - "loopcount=%d\n", - reg, i); - return 0; - } - i++; - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR - "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=%x\n", - reg, mask, *read); - return -EIO; -} - -/* constants used with pcxhr_check_reg_bit() */ -#define PCXHR_TIMEOUT_DSP 200 - - -#define PCXHR_MASK_EXTRA_INFO 0x0000FE -#define PCXHR_MASK_IT_HF0 0x000100 -#define PCXHR_MASK_IT_HF1 0x000200 -#define PCXHR_MASK_IT_NO_HF0_HF1 0x000400 -#define PCXHR_MASK_IT_MANAGE_HF5 0x000800 -#define PCXHR_MASK_IT_WAIT 0x010000 -#define PCXHR_MASK_IT_WAIT_EXTRA 0x020000 - -#define PCXHR_IT_SEND_BYTE_XILINX (0x0000003C | PCXHR_MASK_IT_HF0) -#define PCXHR_IT_TEST_XILINX (0x0000003C | PCXHR_MASK_IT_HF1 | \ - PCXHR_MASK_IT_MANAGE_HF5) -#define PCXHR_IT_DOWNLOAD_BOOT (0x0000000C | PCXHR_MASK_IT_HF1 | \ - PCXHR_MASK_IT_MANAGE_HF5 | \ - PCXHR_MASK_IT_WAIT) -#define PCXHR_IT_RESET_BOARD_FUNC (0x0000000C | PCXHR_MASK_IT_HF0 | \ - PCXHR_MASK_IT_MANAGE_HF5 | \ - PCXHR_MASK_IT_WAIT_EXTRA) -#define PCXHR_IT_DOWNLOAD_DSP (0x0000000C | \ - PCXHR_MASK_IT_MANAGE_HF5 | \ - PCXHR_MASK_IT_WAIT) -#define PCXHR_IT_DEBUG (0x0000005A | PCXHR_MASK_IT_NO_HF0_HF1) -#define PCXHR_IT_RESET_SEMAPHORE (0x0000005C | PCXHR_MASK_IT_NO_HF0_HF1) -#define PCXHR_IT_MESSAGE (0x00000074 | PCXHR_MASK_IT_NO_HF0_HF1) -#define PCXHR_IT_RESET_CHK (0x00000076 | PCXHR_MASK_IT_NO_HF0_HF1) -#define PCXHR_IT_UPDATE_RBUFFER (0x00000078 | PCXHR_MASK_IT_NO_HF0_HF1) - -static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, - unsigned int itdsp, int atomic) -{ - int err; - unsigned char reg; - - if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) { - /* clear hf5 bit */ - PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, - PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & - ~PCXHR_MBOX0_HF5); - } - if ((itdsp & PCXHR_MASK_IT_NO_HF0_HF1) == 0) { - reg = (PCXHR_ICR_HI08_RREQ | - PCXHR_ICR_HI08_TREQ | - PCXHR_ICR_HI08_HDRQ); - if (itdsp & PCXHR_MASK_IT_HF0) - reg |= PCXHR_ICR_HI08_HF0; - if (itdsp & PCXHR_MASK_IT_HF1) - reg |= PCXHR_ICR_HI08_HF1; - PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); - } - reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) | - PCXHR_CVR_HI08_HC); - PCXHR_OUTPB(mgr, PCXHR_DSP_CVR, reg); - if (itdsp & PCXHR_MASK_IT_WAIT) { - if (atomic) - mdelay(PCXHR_WAIT_IT); - else - msleep(PCXHR_WAIT_IT); - } - if (itdsp & PCXHR_MASK_IT_WAIT_EXTRA) { - if (atomic) - mdelay(PCXHR_WAIT_IT_EXTRA); - else - msleep(PCXHR_WAIT_IT); - } - /* wait for CVR_HI08_HC == 0 */ - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_CVR, PCXHR_CVR_HI08_HC, 0, - PCXHR_TIMEOUT_DSP, ®); - if (err) { - snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT CVR\n"); - return err; - } - if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) { - /* wait for hf5 bit */ - err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, - PCXHR_MBOX0_HF5, - PCXHR_MBOX0_HF5, - PCXHR_TIMEOUT_DSP, - ®); - if (err) { - snd_printk(KERN_ERR - "pcxhr_send_it_dsp : TIMEOUT HF5\n"); - return err; - } - } - return 0; /* retry not handled here */ -} - -void pcxhr_reset_xilinx_com(struct pcxhr_mgr *mgr) -{ - /* reset second xilinx */ - PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, - PCXHR_CHIPSC_INIT_VALUE & ~PCXHR_CHIPSC_RESET_XILINX); -} - -static void pcxhr_enable_irq(struct pcxhr_mgr *mgr, int enable) -{ - unsigned int reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); - /* enable/disable interrupts */ - if (enable) - reg |= (PCXHR_IRQCS_ENABLE_PCIIRQ | PCXHR_IRQCS_ENABLE_PCIDB); - else - reg &= ~(PCXHR_IRQCS_ENABLE_PCIIRQ | PCXHR_IRQCS_ENABLE_PCIDB); - PCXHR_OUTPL(mgr, PCXHR_PLX_IRQCS, reg); -} - -void pcxhr_reset_dsp(struct pcxhr_mgr *mgr) -{ - /* disable interrupts */ - pcxhr_enable_irq(mgr, 0); - - /* let's reset the DSP */ - PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 0); - msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ - PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 3); - msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ - - /* reset mailbox */ - PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, 0); -} - -void pcxhr_enable_dsp(struct pcxhr_mgr *mgr) -{ - /* enable interrupts */ - pcxhr_enable_irq(mgr, 1); -} - -/* - * load the xilinx image - */ -int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, - const struct firmware *xilinx, int second) -{ - unsigned int i; - unsigned int chipsc; - unsigned char data; - unsigned char mask; - const unsigned char *image; - - /* test first xilinx */ - chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC); - /* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */ - /* this bit will always be 1; - * no possibility to test presence of first xilinx - */ - if(second) { - if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) { - snd_printk(KERN_ERR "error loading first xilinx\n"); - return -EINVAL; - } - /* activate second xilinx */ - chipsc |= PCXHR_CHIPSC_RESET_XILINX; - PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); - msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ - } - image = xilinx->data; - for (i = 0; i < xilinx->size; i++, image++) { - data = *image; - mask = 0x80; - while (mask) { - chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | - PCXHR_CHIPSC_DATA_IN); - if (data & mask) - chipsc |= PCXHR_CHIPSC_DATA_IN; - PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); - chipsc |= PCXHR_CHIPSC_DATA_CLK; - PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); - mask >>= 1; - } - /* don't take too much time in this loop... */ - cond_resched(); - } - chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN); - PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); - /* wait 2 msec (time to boot the xilinx before any access) */ - msleep( PCXHR_WAIT_DEFAULT ); - return 0; -} - -/* - * send an executable file to the DSP - */ -static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp) -{ - int err; - unsigned int i; - unsigned int len; - const unsigned char *data; - unsigned char dummy; - /* check the length of boot image */ - if (dsp->size <= 0) - return -EINVAL; - if (dsp->size % 3) - return -EINVAL; - if (snd_BUG_ON(!dsp->data)) - return -EINVAL; - /* transfert data buffer from PC to DSP */ - for (i = 0; i < dsp->size; i += 3) { - data = dsp->data + i; - if (i == 0) { - /* test data header consistency */ - len = (unsigned int)((data[0]<<16) + - (data[1]<<8) + - data[2]); - if (len && (dsp->size != (len + 2) * 3)) - return -EINVAL; - } - /* wait DSP ready for new transfer */ - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, - PCXHR_ISR_HI08_TRDY, - PCXHR_ISR_HI08_TRDY, - PCXHR_TIMEOUT_DSP, &dummy); - if (err) { - snd_printk(KERN_ERR - "dsp loading error at position %d\n", i); - return err; - } - /* send host data */ - PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, data[0]); - PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, data[1]); - PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, data[2]); - - /* don't take too much time in this loop... */ - cond_resched(); - } - /* give some time to boot the DSP */ - msleep(PCXHR_WAIT_DEFAULT); - return 0; -} - -/* - * load the eeprom image - */ -int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, - const struct firmware *eeprom) -{ - int err; - unsigned char reg; - - /* init value of the ICR register */ - reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ; - if (PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & PCXHR_MBOX0_BOOT_HERE) { - /* no need to load the eeprom binary, - * but init the HI08 interface - */ - PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg | PCXHR_ICR_HI08_INIT); - msleep(PCXHR_WAIT_DEFAULT); - PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); - msleep(PCXHR_WAIT_DEFAULT); - snd_printdd("no need to load eeprom boot\n"); - return 0; - } - PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); - - err = pcxhr_download_dsp(mgr, eeprom); - if (err) - return err; - /* wait for chk bit */ - return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, - PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); -} - -/* - * load the boot image - */ -int pcxhr_load_boot_binary(struct pcxhr_mgr *mgr, const struct firmware *boot) -{ - int err; - unsigned int physaddr = mgr->hostport.addr; - unsigned char dummy; - - /* send the hostport address to the DSP (only the upper 24 bit !) */ - if (snd_BUG_ON(physaddr & 0xff)) - return -EINVAL; - PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX1, (physaddr >> 8)); - - err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_BOOT, 0); - if (err) - return err; - /* clear hf5 bit */ - PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, - PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5); - - err = pcxhr_download_dsp(mgr, boot); - if (err) - return err; - /* wait for hf5 bit */ - return pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5, - PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &dummy); -} - -/* - * load the final dsp image - */ -int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp) -{ - int err; - unsigned char dummy; - err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_BOARD_FUNC, 0); - if (err) - return err; - err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_DSP, 0); - if (err) - return err; - err = pcxhr_download_dsp(mgr, dsp); - if (err) - return err; - /* wait for chk bit */ - return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, - PCXHR_ISR_HI08_CHK, - PCXHR_ISR_HI08_CHK, - PCXHR_TIMEOUT_DSP, &dummy); -} - - -struct pcxhr_cmd_info { - u32 opcode; /* command word */ - u16 st_length; /* status length */ - u16 st_type; /* status type (RMH_SSIZE_XXX) */ -}; - -/* RMH status type */ -enum { - RMH_SSIZE_FIXED = 0, /* status size fix (st_length = 0..x) */ - RMH_SSIZE_ARG = 1, /* status size given in the LSB byte */ - RMH_SSIZE_MASK = 2, /* status size given in bitmask */ -}; - -/* - * Array of DSP commands - */ -static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { -[CMD_VERSION] = { 0x010000, 1, RMH_SSIZE_FIXED }, -[CMD_SUPPORTED] = { 0x020000, 4, RMH_SSIZE_FIXED }, -[CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED }, -[CMD_SEND_IRQA] = { 0x070001, 0, RMH_SSIZE_FIXED }, -[CMD_ACCESS_IO_WRITE] = { 0x090000, 1, RMH_SSIZE_ARG }, -[CMD_ACCESS_IO_READ] = { 0x094000, 1, RMH_SSIZE_ARG }, -[CMD_ASYNC] = { 0x0a0000, 1, RMH_SSIZE_ARG }, -[CMD_MODIFY_CLOCK] = { 0x0d0000, 0, RMH_SSIZE_FIXED }, -[CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 0, RMH_SSIZE_FIXED }, -[CMD_GET_DSP_RESOURCES] = { 0x100000, 4, RMH_SSIZE_FIXED }, -[CMD_SET_TIMER_INTERRUPT] = { 0x110000, 0, RMH_SSIZE_FIXED }, -[CMD_RES_PIPE] = { 0x400000, 0, RMH_SSIZE_FIXED }, -[CMD_FREE_PIPE] = { 0x410000, 0, RMH_SSIZE_FIXED }, -[CMD_CONF_PIPE] = { 0x422101, 0, RMH_SSIZE_FIXED }, -[CMD_STOP_PIPE] = { 0x470004, 0, RMH_SSIZE_FIXED }, -[CMD_PIPE_SAMPLE_COUNT] = { 0x49a000, 2, RMH_SSIZE_FIXED }, -[CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED }, -[CMD_START_STREAM] = { 0x802000, 0, RMH_SSIZE_FIXED }, -[CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x822000, 0, RMH_SSIZE_FIXED }, -[CMD_STOP_STREAM] = { 0x832000, 0, RMH_SSIZE_FIXED }, -[CMD_UPDATE_R_BUFFERS] = { 0x840000, 0, RMH_SSIZE_FIXED }, -[CMD_FORMAT_STREAM_OUT] = { 0x860000, 0, RMH_SSIZE_FIXED }, -[CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, -[CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, -[CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, -}; - -#ifdef CONFIG_SND_DEBUG_VERBOSE -static char* cmd_names[] = { -[CMD_VERSION] = "CMD_VERSION", -[CMD_SUPPORTED] = "CMD_SUPPORTED", -[CMD_TEST_IT] = "CMD_TEST_IT", -[CMD_SEND_IRQA] = "CMD_SEND_IRQA", -[CMD_ACCESS_IO_WRITE] = "CMD_ACCESS_IO_WRITE", -[CMD_ACCESS_IO_READ] = "CMD_ACCESS_IO_READ", -[CMD_ASYNC] = "CMD_ASYNC", -[CMD_MODIFY_CLOCK] = "CMD_MODIFY_CLOCK", -[CMD_RESYNC_AUDIO_INPUTS] = "CMD_RESYNC_AUDIO_INPUTS", -[CMD_GET_DSP_RESOURCES] = "CMD_GET_DSP_RESOURCES", -[CMD_SET_TIMER_INTERRUPT] = "CMD_SET_TIMER_INTERRUPT", -[CMD_RES_PIPE] = "CMD_RES_PIPE", -[CMD_FREE_PIPE] = "CMD_FREE_PIPE", -[CMD_CONF_PIPE] = "CMD_CONF_PIPE", -[CMD_STOP_PIPE] = "CMD_STOP_PIPE", -[CMD_PIPE_SAMPLE_COUNT] = "CMD_PIPE_SAMPLE_COUNT", -[CMD_CAN_START_PIPE] = "CMD_CAN_START_PIPE", -[CMD_START_STREAM] = "CMD_START_STREAM", -[CMD_STREAM_OUT_LEVEL_ADJUST] = "CMD_STREAM_OUT_LEVEL_ADJUST", -[CMD_STOP_STREAM] = "CMD_STOP_STREAM", -[CMD_UPDATE_R_BUFFERS] = "CMD_UPDATE_R_BUFFERS", -[CMD_FORMAT_STREAM_OUT] = "CMD_FORMAT_STREAM_OUT", -[CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", -[CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", -[CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", -}; -#endif - - -static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) -{ - int err; - int i; - u32 data; - u32 size_mask; - unsigned char reg; - int max_stat_len; - - if (rmh->stat_len < PCXHR_SIZE_MAX_STATUS) - max_stat_len = PCXHR_SIZE_MAX_STATUS; - else max_stat_len = rmh->stat_len; - - for (i = 0; i < rmh->stat_len; i++) { - /* wait for receiver full */ - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, - PCXHR_ISR_HI08_RXDF, - PCXHR_ISR_HI08_RXDF, - PCXHR_TIMEOUT_DSP, ®); - if (err) { - snd_printk(KERN_ERR "ERROR RMH stat: " - "ISR:RXDF=1 (ISR = %x; i=%d )\n", - reg, i); - return err; - } - /* read data */ - data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16; - data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8; - data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL); - - /* need to update rmh->stat_len on the fly ?? */ - if (!i) { - if (rmh->dsp_stat != RMH_SSIZE_FIXED) { - if (rmh->dsp_stat == RMH_SSIZE_ARG) { - rmh->stat_len = (data & 0x0000ff) + 1; - data &= 0xffff00; - } else { - /* rmh->dsp_stat == RMH_SSIZE_MASK */ - rmh->stat_len = 1; - size_mask = data; - while (size_mask) { - if (size_mask & 1) - rmh->stat_len++; - size_mask >>= 1; - } - } - } - } -#ifdef CONFIG_SND_DEBUG_VERBOSE - if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd(" stat[%d]=%x\n", i, data); -#endif - if (i < max_stat_len) - rmh->stat[i] = data; - } - if (rmh->stat_len > max_stat_len) { - snd_printdd("PCXHR : rmh->stat_len=%x too big\n", - rmh->stat_len); - rmh->stat_len = max_stat_len; - } - return 0; -} - -static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) -{ - int err; - int i; - u32 data; - unsigned char reg; - - if (snd_BUG_ON(rmh->cmd_len >= PCXHR_SIZE_MAX_CMD)) - return -EINVAL; - err = pcxhr_send_it_dsp(mgr, PCXHR_IT_MESSAGE, 1); - if (err) { - snd_printk(KERN_ERR "pcxhr_send_message : ED_DSP_CRASHED\n"); - return err; - } - /* wait for chk bit */ - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, - PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); - if (err) - return err; - /* reset irq chk */ - err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_CHK, 1); - if (err) - return err; - /* wait for chk bit == 0*/ - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 0, - PCXHR_TIMEOUT_DSP, ®); - if (err) - return err; - - data = rmh->cmd[0]; - - if (rmh->cmd_len > 1) - data |= 0x008000; /* MASK_MORE_THAN_1_WORD_COMMAND */ - else - data &= 0xff7fff; /* MASK_1_WORD_COMMAND */ -#ifdef CONFIG_SND_DEBUG_VERBOSE - if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd("MSG cmd[0]=%x (%s)\n", - data, cmd_names[rmh->cmd_idx]); -#endif - - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY, - PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, ®); - if (err) - return err; - PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); - PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); - PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); - - if (rmh->cmd_len > 1) { - /* send length */ - data = rmh->cmd_len - 1; - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, - PCXHR_ISR_HI08_TRDY, - PCXHR_ISR_HI08_TRDY, - PCXHR_TIMEOUT_DSP, ®); - if (err) - return err; - PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); - PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); - PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); - - for (i=1; i < rmh->cmd_len; i++) { - /* send other words */ - data = rmh->cmd[i]; -#ifdef CONFIG_SND_DEBUG_VERBOSE - if (rmh->cmd_idx < CMD_LAST_INDEX) - snd_printdd(" cmd[%d]=%x\n", i, data); -#endif - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, - PCXHR_ISR_HI08_TRDY, - PCXHR_ISR_HI08_TRDY, - PCXHR_TIMEOUT_DSP, ®); - if (err) - return err; - PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); - PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); - PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); - } - } - /* wait for chk bit */ - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, - PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); - if (err) - return err; - /* test status ISR */ - if (reg & PCXHR_ISR_HI08_ERR) { - /* ERROR, wait for receiver full */ - err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, - PCXHR_ISR_HI08_RXDF, - PCXHR_ISR_HI08_RXDF, - PCXHR_TIMEOUT_DSP, ®); - if (err) { - snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg); - return err; - } - /* read error code */ - data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16; - data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8; - data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL); - snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", - rmh->cmd_idx, data); - err = -EINVAL; - } else { - /* read the response data */ - err = pcxhr_read_rmh_status(mgr, rmh); - } - /* reset semaphore */ - if (pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_SEMAPHORE, 1) < 0) - return -EIO; - return err; -} - - -/** - * pcxhr_init_rmh - initialize the RMH instance - * @rmh: the rmh pointer to be initialized - * @cmd: the rmh command to be set - */ -void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd) -{ - if (snd_BUG_ON(cmd >= CMD_LAST_INDEX)) - return; - rmh->cmd[0] = pcxhr_dsp_cmds[cmd].opcode; - rmh->cmd_len = 1; - rmh->stat_len = pcxhr_dsp_cmds[cmd].st_length; - rmh->dsp_stat = pcxhr_dsp_cmds[cmd].st_type; - rmh->cmd_idx = cmd; -} - - -void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture, - unsigned int param1, unsigned int param2, - unsigned int param3) -{ - snd_BUG_ON(param1 > MASK_FIRST_FIELD); - if (capture) - rmh->cmd[0] |= 0x800; /* COMMAND_RECORD_MASK */ - if (param1) - rmh->cmd[0] |= (param1 << FIELD_SIZE); - if (param2) { - snd_BUG_ON(param2 > MASK_FIRST_FIELD); - rmh->cmd[0] |= param2; - } - if(param3) { - snd_BUG_ON(param3 > MASK_DSP_WORD); - rmh->cmd[1] = param3; - rmh->cmd_len = 2; - } -} - -/* - * pcxhr_send_msg - send a DSP message with spinlock - * @rmh: the rmh record to send and receive - * - * returns 0 if successful, or a negative error code. - */ -int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) -{ - unsigned long flags; - int err; - spin_lock_irqsave(&mgr->msg_lock, flags); - err = pcxhr_send_msg_nolock(mgr, rmh); - spin_unlock_irqrestore(&mgr->msg_lock, flags); - return err; -} - -static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr) -{ - int start_mask = PCXHR_INPL(mgr, PCXHR_PLX_MBOX2); - /* least segnificant 12 bits are the pipe states - * for the playback audios - * next 12 bits are the pipe states for the capture audios - * (PCXHR_PIPE_STATE_CAPTURE_OFFSET) - */ - start_mask &= 0xffffff; - snd_printdd("CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask); - return start_mask; -} - -#define PCXHR_PIPE_STATE_CAPTURE_OFFSET 12 -#define MAX_WAIT_FOR_DSP 20 - -static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, - int audio_mask, int *retry) -{ - struct pcxhr_rmh rmh; - int err; - int audio = 0; - - *retry = 0; - while (audio_mask) { - if (audio_mask & 1) { - pcxhr_init_rmh(&rmh, CMD_CAN_START_PIPE); - if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) { - /* can start playback pipe */ - pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0); - } else { - /* can start capture pipe */ - pcxhr_set_pipe_cmd_params(&rmh, 1, audio - - PCXHR_PIPE_STATE_CAPTURE_OFFSET, - 0, 0); - } - err = pcxhr_send_msg(mgr, &rmh); - if (err) { - snd_printk(KERN_ERR - "error pipe start " - "(CMD_CAN_START_PIPE) err=%x!\n", - err); - return err; - } - /* if the pipe couldn't be prepaired for start, - * retry it later - */ - if (rmh.stat[0] == 0) - *retry |= (1<>=1; - audio++; - } - return 0; -} - -static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask) -{ - struct pcxhr_rmh rmh; - int err; - int audio = 0; - - while (audio_mask) { - if (audio_mask & 1) { - pcxhr_init_rmh(&rmh, CMD_STOP_PIPE); - if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) { - /* stop playback pipe */ - pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0); - } else { - /* stop capture pipe */ - pcxhr_set_pipe_cmd_params(&rmh, 1, audio - - PCXHR_PIPE_STATE_CAPTURE_OFFSET, - 0, 0); - } - err = pcxhr_send_msg(mgr, &rmh); - if (err) { - snd_printk(KERN_ERR - "error pipe stop " - "(CMD_STOP_PIPE) err=%x!\n", err); - return err; - } - } - audio_mask>>=1; - audio++; - } - return 0; -} - -static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask) -{ - struct pcxhr_rmh rmh; - int err; - int audio = 0; - - while (audio_mask) { - if (audio_mask & 1) { - pcxhr_init_rmh(&rmh, CMD_CONF_PIPE); - if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) - pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0, - 1 << audio); - else - pcxhr_set_pipe_cmd_params(&rmh, 1, 0, 0, - 1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET)); - err = pcxhr_send_msg(mgr, &rmh); - if (err) { - snd_printk(KERN_ERR - "error pipe start " - "(CMD_CONF_PIPE) err=%x!\n", err); - return err; - } - } - audio_mask>>=1; - audio++; - } - /* now fire the interrupt on the card */ - pcxhr_init_rmh(&rmh, CMD_SEND_IRQA); - err = pcxhr_send_msg(mgr, &rmh); - if (err) { - snd_printk(KERN_ERR - "error pipe start (CMD_SEND_IRQA) err=%x!\n", - err); - return err; - } - return 0; -} - - - -int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, - int capture_mask, int start) -{ - int state, i, err; - int audio_mask; - -#ifdef CONFIG_SND_DEBUG_VERBOSE - struct timeval my_tv1, my_tv2; - do_gettimeofday(&my_tv1); -#endif - audio_mask = (playback_mask | - (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET)); - /* current pipe state (playback + record) */ - state = pcxhr_pipes_running(mgr); - snd_printdd("pcxhr_set_pipe_state %s (mask %x current %x)\n", - start ? "START" : "STOP", audio_mask, state); - if (start) { - /* start only pipes that are not yet started */ - audio_mask &= ~state; - state = audio_mask; - for (i = 0; i < MAX_WAIT_FOR_DSP; i++) { - err = pcxhr_prepair_pipe_start(mgr, state, &state); - if (err) - return err; - if (state == 0) - break; /* success, all pipes prepaired */ - mdelay(1); /* wait 1 millisecond and retry */ - } - } else { - audio_mask &= state; /* stop only pipes that are started */ - } - if (audio_mask == 0) - return 0; - - err = pcxhr_toggle_pipes(mgr, audio_mask); - if (err) - return err; - - i = 0; - while (1) { - state = pcxhr_pipes_running(mgr); - /* have all pipes the new state ? */ - if ((state & audio_mask) == (start ? audio_mask : 0)) - break; - if (++i >= MAX_WAIT_FOR_DSP * 100) { - snd_printk(KERN_ERR "error pipe start/stop\n"); - return -EBUSY; - } - udelay(10); /* wait 10 microseconds */ - } - if (!start) { - err = pcxhr_stop_pipes(mgr, audio_mask); - if (err) - return err; - } -#ifdef CONFIG_SND_DEBUG_VERBOSE - do_gettimeofday(&my_tv2); - snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n", - (long)(my_tv2.tv_usec - my_tv1.tv_usec), err); -#endif - return 0; -} - -int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, - unsigned int value, int *changed) -{ - struct pcxhr_rmh rmh; - unsigned long flags; - int err; - - spin_lock_irqsave(&mgr->msg_lock, flags); - if ((mgr->io_num_reg_cont & mask) == value) { - snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n", - mask, value); - if (changed) - *changed = 0; - spin_unlock_irqrestore(&mgr->msg_lock, flags); - return 0; /* already programmed */ - } - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); - rmh.cmd[0] |= IO_NUM_REG_CONT; - rmh.cmd[1] = mask; - rmh.cmd[2] = value; - rmh.cmd_len = 3; - err = pcxhr_send_msg_nolock(mgr, &rmh); - if (err == 0) { - mgr->io_num_reg_cont &= ~mask; - mgr->io_num_reg_cont |= value; - if (changed) - *changed = 1; - } - spin_unlock_irqrestore(&mgr->msg_lock, flags); - return err; -} - -#define PCXHR_IRQ_TIMER 0x000300 -#define PCXHR_IRQ_FREQ_CHANGE 0x000800 -#define PCXHR_IRQ_TIME_CODE 0x001000 -#define PCXHR_IRQ_NOTIFY 0x002000 -#define PCXHR_IRQ_ASYNC 0x008000 -#define PCXHR_IRQ_MASK 0x00bb00 -#define PCXHR_FATAL_DSP_ERR 0xff0000 - -enum pcxhr_async_err_src { - PCXHR_ERR_PIPE, - PCXHR_ERR_STREAM, - PCXHR_ERR_AUDIO -}; - -static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err, - enum pcxhr_async_err_src err_src, int pipe, - int is_capture) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - static char* err_src_name[] = { - [PCXHR_ERR_PIPE] = "Pipe", - [PCXHR_ERR_STREAM] = "Stream", - [PCXHR_ERR_AUDIO] = "Audio" - }; -#endif - if (err & 0xfff) - err &= 0xfff; - else - err = ((err >> 12) & 0xfff); - if (!err) - return 0; - snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n", - err_src_name[err_src], - is_capture ? "Record" : "Play", pipe, err); - if (err == 0xe01) - mgr->async_err_stream_xrun++; - else if (err == 0xe10) - mgr->async_err_pipe_xrun++; - else - mgr->async_err_other_last = (int)err; - return 1; -} - - -void pcxhr_msg_tasklet(unsigned long arg) -{ - struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg); - struct pcxhr_rmh *prmh = mgr->prmh; - int err; - int i, j; - - if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) - snd_printdd("TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); - if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) - snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); - if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) - snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occurred\n"); - if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) { - /* clear events FREQ_CHANGE and TIME_CODE */ - pcxhr_init_rmh(prmh, CMD_TEST_IT); - err = pcxhr_send_msg(mgr, prmh); - snd_printdd("CMD_TEST_IT : err=%x, stat=%x\n", - err, prmh->stat[0]); - } - if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { - snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); - - pcxhr_init_rmh(prmh, CMD_ASYNC); - prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ - /* this is the only one extra long response command */ - prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; - err = pcxhr_send_msg(mgr, prmh); - if (err) - snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n", - err); - i = 1; - while (i < prmh->stat_len) { - int nb_audio = ((prmh->stat[i] >> FIELD_SIZE) & - MASK_FIRST_FIELD); - int nb_stream = ((prmh->stat[i] >> (2*FIELD_SIZE)) & - MASK_FIRST_FIELD); - int pipe = prmh->stat[i] & MASK_FIRST_FIELD; - int is_capture = prmh->stat[i] & 0x400000; - u32 err2; - - if (prmh->stat[i] & 0x800000) { /* if BIT_END */ - snd_printdd("TASKLET : End%sPipe %d\n", - is_capture ? "Record" : "Play", - pipe); - } - i++; - err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1]; - if (err2) - pcxhr_handle_async_err(mgr, err2, - PCXHR_ERR_PIPE, - pipe, is_capture); - i += 2; - for (j = 0; j < nb_stream; j++) { - err2 = prmh->stat[i] ? - prmh->stat[i] : prmh->stat[i+1]; - if (err2) - pcxhr_handle_async_err(mgr, err2, - PCXHR_ERR_STREAM, - pipe, - is_capture); - i += 2; - } - for (j = 0; j < nb_audio; j++) { - err2 = prmh->stat[i] ? - prmh->stat[i] : prmh->stat[i+1]; - if (err2) - pcxhr_handle_async_err(mgr, err2, - PCXHR_ERR_AUDIO, - pipe, - is_capture); - i += 2; - } - } - } -} - -static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, - struct pcxhr_stream *stream) -{ - u_int64_t hw_sample_count; - struct pcxhr_rmh rmh; - int err, stream_mask; - - stream_mask = stream->pipe->is_capture ? 1 : 1<substream->number; - - /* get sample count for one stream */ - pcxhr_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT); - pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture, - stream->pipe->first_audio, 0, stream_mask); - /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */ - - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return 0; - - hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; - hw_sample_count += (u_int64_t)rmh.stat[1]; - - snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n", - stream->pipe->is_capture ? 'C' : 'P', - stream->substream->number, - (long unsigned int)hw_sample_count, - (long unsigned int)(stream->timer_abs_periods + - stream->timer_period_frag + - mgr->granularity)); - return hw_sample_count; -} - -static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr, - struct pcxhr_stream *stream, - int samples_to_add) -{ - if (stream->substream && - (stream->status == PCXHR_STREAM_STATUS_RUNNING)) { - u_int64_t new_sample_count; - int elapsed = 0; - int hardware_read = 0; - struct snd_pcm_runtime *runtime = stream->substream->runtime; - - if (samples_to_add < 0) { - stream->timer_is_synced = 0; - /* add default if no hardware_read possible */ - samples_to_add = mgr->granularity; - } - - if (!stream->timer_is_synced) { - if ((stream->timer_abs_periods != 0) || - ((stream->timer_period_frag + samples_to_add) >= - runtime->period_size)) { - new_sample_count = - pcxhr_stream_read_position(mgr, stream); - hardware_read = 1; - if (new_sample_count >= mgr->granularity) { - /* sub security offset because of - * jitter and finer granularity of - * dsp time (MBOX4) - */ - new_sample_count -= mgr->granularity; - stream->timer_is_synced = 1; - } - } - } - if (!hardware_read) { - /* if we didn't try to sync the position, increment it - * by PCXHR_GRANULARITY every timer interrupt - */ - new_sample_count = stream->timer_abs_periods + - stream->timer_period_frag + samples_to_add; - } - while (1) { - u_int64_t new_elapse_pos = stream->timer_abs_periods + - runtime->period_size; - if (new_elapse_pos > new_sample_count) - break; - elapsed = 1; - stream->timer_buf_periods++; - if (stream->timer_buf_periods >= runtime->periods) - stream->timer_buf_periods = 0; - stream->timer_abs_periods = new_elapse_pos; - } - if (new_sample_count >= stream->timer_abs_periods) { - stream->timer_period_frag = - (u_int32_t)(new_sample_count - - stream->timer_abs_periods); - } else { - snd_printk(KERN_ERR - "ERROR new_sample_count too small ??? %ld\n", - (long unsigned int)new_sample_count); - } - - if (elapsed) { - spin_unlock(&mgr->lock); - snd_pcm_period_elapsed(stream->substream); - spin_lock(&mgr->lock); - } - } -} - -irqreturn_t pcxhr_interrupt(int irq, void *dev_id) -{ - struct pcxhr_mgr *mgr = dev_id; - unsigned int reg; - int i, j; - struct snd_pcxhr *chip; - - spin_lock(&mgr->lock); - - reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); - if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) { - spin_unlock(&mgr->lock); - /* this device did not cause the interrupt */ - return IRQ_NONE; - } - - /* clear interrupt */ - reg = PCXHR_INPL(mgr, PCXHR_PLX_L2PCIDB); - PCXHR_OUTPL(mgr, PCXHR_PLX_L2PCIDB, reg); - - /* timer irq occurred */ - if (reg & PCXHR_IRQ_TIMER) { - int timer_toggle = reg & PCXHR_IRQ_TIMER; - /* is a 24 bit counter */ - int dsp_time_new = - PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK; - int dsp_time_diff = dsp_time_new - mgr->dsp_time_last; - - if ((dsp_time_diff < 0) && - (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { - snd_printdd("ERROR DSP TIME old(%d) new(%d) -> " - "resynchronize all streams\n", - mgr->dsp_time_last, dsp_time_new); - mgr->dsp_time_err++; - } -#ifdef CONFIG_SND_DEBUG_VERBOSE - if (dsp_time_diff == 0) - snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", - dsp_time_new); - else if (dsp_time_diff >= (2*mgr->granularity)) - snd_printdd("ERROR DSP TIME TOO BIG old(%d) add(%d)\n", - mgr->dsp_time_last, - dsp_time_new - mgr->dsp_time_last); - else if (dsp_time_diff % mgr->granularity) - snd_printdd("ERROR DSP TIME increased by %d\n", - dsp_time_diff); -#endif - mgr->dsp_time_last = dsp_time_new; - - if (timer_toggle == mgr->timer_toggle) { - snd_printdd("ERROR TIMER TOGGLE\n"); - mgr->dsp_time_err++; - } - mgr->timer_toggle = timer_toggle; - - reg &= ~PCXHR_IRQ_TIMER; - for (i = 0; i < mgr->num_cards; i++) { - chip = mgr->chip[i]; - for (j = 0; j < chip->nb_streams_capt; j++) - pcxhr_update_timer_pos(mgr, - &chip->capture_stream[j], - dsp_time_diff); - } - for (i = 0; i < mgr->num_cards; i++) { - chip = mgr->chip[i]; - for (j = 0; j < chip->nb_streams_play; j++) - pcxhr_update_timer_pos(mgr, - &chip->playback_stream[j], - dsp_time_diff); - } - } - /* other irq's handled in the tasklet */ - if (reg & PCXHR_IRQ_MASK) { - if (reg & PCXHR_IRQ_ASYNC) { - /* as we didn't request any async notifications, - * some kind of xrun error will probably occurred - */ - /* better resynchronize all streams next interrupt : */ - mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; - } - mgr->src_it_dsp = reg; - tasklet_schedule(&mgr->msg_taskq); - } -#ifdef CONFIG_SND_DEBUG_VERBOSE - if (reg & PCXHR_FATAL_DSP_ERR) - snd_printdd("FATAL DSP ERROR : %x\n", reg); -#endif - spin_unlock(&mgr->lock); - return IRQ_HANDLED; /* this device caused the interrupt */ -} diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.h b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.h deleted file mode 100644 index be017379..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_core.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * low level interface with interrupt and message handling - * - * Copyright (c) 2004 by Digigram - * - * 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 - */ - -#ifndef __SOUND_PCXHR_CORE_H -#define __SOUND_PCXHR_CORE_H - -struct firmware; -struct pcxhr_mgr; - -/* init and firmware download commands */ -void pcxhr_reset_xilinx_com(struct pcxhr_mgr *mgr); -void pcxhr_reset_dsp(struct pcxhr_mgr *mgr); -void pcxhr_enable_dsp(struct pcxhr_mgr *mgr); -int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilinx, int second); -int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, const struct firmware *eeprom); -int pcxhr_load_boot_binary(struct pcxhr_mgr *mgr, const struct firmware *boot); -int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp); - -/* DSP time available on MailBox4 register : 24 bit time samples() */ -#define PCXHR_DSP_TIME_MASK 0x00ffffff -#define PCXHR_DSP_TIME_INVALID 0x10000000 - - -#define PCXHR_SIZE_MAX_CMD 8 -#define PCXHR_SIZE_MAX_STATUS 16 -#define PCXHR_SIZE_MAX_LONG_STATUS 256 - -struct pcxhr_rmh { - u16 cmd_len; /* length of the command to send (WORDs) */ - u16 stat_len; /* length of the status received (WORDs) */ - u16 dsp_stat; /* status type, RMP_SSIZE_XXX */ - u16 cmd_idx; /* index of the command */ - u32 cmd[PCXHR_SIZE_MAX_CMD]; - u32 stat[PCXHR_SIZE_MAX_STATUS]; -}; - -enum { - CMD_VERSION, /* cmd_len = 2 stat_len = 1 */ - CMD_SUPPORTED, /* cmd_len = 1 stat_len = 4 */ - CMD_TEST_IT, /* cmd_len = 1 stat_len = 1 */ - CMD_SEND_IRQA, /* cmd_len = 1 stat_len = 0 */ - CMD_ACCESS_IO_WRITE, /* cmd_len >= 1 stat_len >= 1 */ - CMD_ACCESS_IO_READ, /* cmd_len >= 1 stat_len >= 1 */ - CMD_ASYNC, /* cmd_len = 1 stat_len = 1 */ - CMD_MODIFY_CLOCK, /* cmd_len = 3 stat_len = 0 */ - CMD_RESYNC_AUDIO_INPUTS, /* cmd_len = 1 stat_len = 0 */ - CMD_GET_DSP_RESOURCES, /* cmd_len = 1 stat_len = 4 */ - CMD_SET_TIMER_INTERRUPT, /* cmd_len = 1 stat_len = 0 */ - CMD_RES_PIPE, /* cmd_len >=2 stat_len = 0 */ - CMD_FREE_PIPE, /* cmd_len = 1 stat_len = 0 */ - CMD_CONF_PIPE, /* cmd_len = 2 stat_len = 0 */ - CMD_STOP_PIPE, /* cmd_len = 1 stat_len = 0 */ - CMD_PIPE_SAMPLE_COUNT, /* cmd_len = 2 stat_len = 2 */ - CMD_CAN_START_PIPE, /* cmd_len >= 1 stat_len = 1 */ - CMD_START_STREAM, /* cmd_len = 2 stat_len = 0 */ - CMD_STREAM_OUT_LEVEL_ADJUST, /* cmd_len >= 1 stat_len = 0 */ - CMD_STOP_STREAM, /* cmd_len = 2 stat_len = 0 */ - CMD_UPDATE_R_BUFFERS, /* cmd_len = 4 stat_len = 0 */ - CMD_FORMAT_STREAM_OUT, /* cmd_len >= 2 stat_len = 0 */ - CMD_FORMAT_STREAM_IN, /* cmd_len >= 4 stat_len = 0 */ - CMD_STREAM_SAMPLE_COUNT, /* cmd_len = 2 stat_len = (2 * nb_stream) */ - CMD_AUDIO_LEVEL_ADJUST, /* cmd_len = 3 stat_len = 0 */ - CMD_LAST_INDEX -}; - -#define MASK_DSP_WORD 0x00ffffff -#define MASK_ALL_STREAM 0x00ffffff -#define MASK_DSP_WORD_LEVEL 0x000001ff -#define MASK_FIRST_FIELD 0x0000001f -#define FIELD_SIZE 5 - -/* - init the rmh struct; by default cmd_len is set to 1 - */ -void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd); - -void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh* rmh, int capture, unsigned int param1, - unsigned int param2, unsigned int param3); - -#define DSP_EXT_CMD_SET(x) (x->dsp_version > 0x012800) - -/* - send the rmh - */ -int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh); - - -/* values used for CMD_ACCESS_IO_WRITE and CMD_ACCESS_IO_READ */ -#define IO_NUM_REG_CONT 0 -#define IO_NUM_REG_GENCLK 1 -#define IO_NUM_REG_MUTE_OUT 2 -#define IO_NUM_SPEED_RATIO 4 -#define IO_NUM_REG_STATUS 5 -#define IO_NUM_REG_CUER 10 -#define IO_NUM_UER_CHIP_REG 11 -#define IO_NUM_REG_CONFIG_SRC 12 -#define IO_NUM_REG_OUT_ANA_LEVEL 20 -#define IO_NUM_REG_IN_ANA_LEVEL 21 - - -#define REG_CONT_UNMUTE_INPUTS 0x020000 - -/* parameters used with register IO_NUM_REG_STATUS */ -#define REG_STATUS_OPTIONS 0 -#define REG_STATUS_AES_SYNC 8 -#define REG_STATUS_AES_1 9 -#define REG_STATUS_AES_2 10 -#define REG_STATUS_AES_3 11 -#define REG_STATUS_AES_4 12 -#define REG_STATUS_WORD_CLOCK 13 -#define REG_STATUS_INTER_SYNC 14 -#define REG_STATUS_CURRENT 0x80 -/* results */ -#define REG_STATUS_OPT_NO_VIDEO_SIGNAL 0x01 -#define REG_STATUS_OPT_DAUGHTER_MASK 0x1c -#define REG_STATUS_OPT_ANALOG_BOARD 0x00 -#define REG_STATUS_OPT_NO_DAUGHTER 0x1c -#define REG_STATUS_OPT_COMPANION_MASK 0xe0 -#define REG_STATUS_OPT_NO_COMPANION 0xe0 -#define REG_STATUS_SYNC_32000 0x00 -#define REG_STATUS_SYNC_44100 0x01 -#define REG_STATUS_SYNC_48000 0x02 -#define REG_STATUS_SYNC_64000 0x03 -#define REG_STATUS_SYNC_88200 0x04 -#define REG_STATUS_SYNC_96000 0x05 -#define REG_STATUS_SYNC_128000 0x06 -#define REG_STATUS_SYNC_176400 0x07 -#define REG_STATUS_SYNC_192000 0x08 - -int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_mask, int start); - -int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, - unsigned int value, int *changed); - -/* codec parameters */ -#define CS8416_RUN 0x200401 -#define CS8416_FORMAT_DETECT 0x200b00 -#define CS8416_CSB0 0x201900 -#define CS8416_CSB1 0x201a00 -#define CS8416_CSB2 0x201b00 -#define CS8416_CSB3 0x201c00 -#define CS8416_CSB4 0x201d00 -#define CS8416_VERSION 0x207f00 - -#define CS8420_DATA_FLOW_CTL 0x200301 -#define CS8420_CLOCK_SRC_CTL 0x200401 -#define CS8420_RECEIVER_ERRORS 0x201000 -#define CS8420_SRC_RATIO 0x201e00 -#define CS8420_CSB0 0x202000 -#define CS8420_CSB1 0x202100 -#define CS8420_CSB2 0x202200 -#define CS8420_CSB3 0x202300 -#define CS8420_CSB4 0x202400 -#define CS8420_VERSION 0x207f00 - -#define CS4271_MODE_CTL_1 0x200101 -#define CS4271_DAC_CTL 0x200201 -#define CS4271_VOLMIX 0x200301 -#define CS4271_VOLMUTE_LEFT 0x200401 -#define CS4271_VOLMUTE_RIGHT 0x200501 -#define CS4271_ADC_CTL 0x200601 -#define CS4271_MODE_CTL_2 0x200701 - -#define CHIP_SIG_AND_MAP_SPI 0xff7f00 - -/* codec selection */ -#define CS4271_01_CS 0x160018 -#define CS4271_23_CS 0x160019 -#define CS4271_45_CS 0x16001a -#define CS4271_67_CS 0x16001b -#define CS4271_89_CS 0x16001c -#define CS4271_AB_CS 0x16001d -#define CS8420_01_CS 0x080090 -#define CS8420_23_CS 0x080092 -#define CS8420_45_CS 0x080094 -#define CS8420_67_CS 0x080096 -#define CS8416_01_CS 0x080098 - - -/* interrupt handling */ -irqreturn_t pcxhr_interrupt(int irq, void *dev_id); -void pcxhr_msg_tasklet(unsigned long arg); - -#endif /* __SOUND_PCXHR_CORE_H */ diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.c b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.c deleted file mode 100644 index ec1587cd..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * hwdep device manager - * - * Copyright (c) 2004 by Digigram - * - * 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 "pcxhr.h" -#include "pcxhr_mixer.h" -#include "pcxhr_hwdep.h" -#include "pcxhr_core.h" -#include "pcxhr_mix22.h" - - -#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) -#if !defined(CONFIG_USE_PCXHRLOADER) && !defined(CONFIG_SND_PCXHR) /* built-in kernel */ -#define SND_PCXHR_FW_LOADER /* use the standard firmware loader */ -#endif -#endif - - -static int pcxhr_sub_init(struct pcxhr_mgr *mgr); -/* - * get basic information and init pcxhr card - */ -static int pcxhr_init_board(struct pcxhr_mgr *mgr) -{ - int err; - struct pcxhr_rmh rmh; - int card_streams; - - /* calc the number of all streams used */ - if (mgr->mono_capture) - card_streams = mgr->capture_chips * 2; - else - card_streams = mgr->capture_chips; - card_streams += mgr->playback_chips * PCXHR_PLAYBACK_STREAMS; - - /* enable interrupts */ - pcxhr_enable_dsp(mgr); - - pcxhr_init_rmh(&rmh, CMD_SUPPORTED); - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - /* test 8 or 12 phys out */ - if ((rmh.stat[0] & MASK_FIRST_FIELD) != mgr->playback_chips * 2) - return -EINVAL; - /* test 8 or 2 phys in */ - if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) < - mgr->capture_chips * 2) - return -EINVAL; - /* test max nb substream per board */ - if ((rmh.stat[1] & 0x5F) < card_streams) - return -EINVAL; - /* test max nb substream per pipe */ - if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS) - return -EINVAL; - snd_printdd("supported formats : playback=%x capture=%x\n", - rmh.stat[2], rmh.stat[3]); - - pcxhr_init_rmh(&rmh, CMD_VERSION); - /* firmware num for DSP */ - rmh.cmd[0] |= mgr->firmware_num; - /* transfer granularity in samples (should be multiple of 48) */ - rmh.cmd[1] = (1<<23) + mgr->granularity; - rmh.cmd_len = 2; - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - snd_printdd("PCXHR DSP version is %d.%d.%d\n", (rmh.stat[0]>>16)&0xff, - (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff); - mgr->dsp_version = rmh.stat[0]; - - if (mgr->is_hr_stereo) - err = hr222_sub_init(mgr); - else - err = pcxhr_sub_init(mgr); - return err; -} - -static int pcxhr_sub_init(struct pcxhr_mgr *mgr) -{ - int err; - struct pcxhr_rmh rmh; - - /* get options */ - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); - rmh.cmd[0] |= IO_NUM_REG_STATUS; - rmh.cmd[1] = REG_STATUS_OPTIONS; - rmh.cmd_len = 2; - err = pcxhr_send_msg(mgr, &rmh); - if (err) - return err; - - if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) == - REG_STATUS_OPT_ANALOG_BOARD) - mgr->board_has_analog = 1; /* analog addon board found */ - - /* unmute inputs */ - err = pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS, - REG_CONT_UNMUTE_INPUTS, NULL); - if (err) - return err; - /* unmute outputs (a write to IO_NUM_REG_MUTE_OUT mutes!) */ - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); - rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT; - if (DSP_EXT_CMD_SET(mgr)) { - rmh.cmd[1] = 1; /* unmute digital plugs */ - rmh.cmd_len = 2; - } - err = pcxhr_send_msg(mgr, &rmh); - return err; -} - -void pcxhr_reset_board(struct pcxhr_mgr *mgr) -{ - struct pcxhr_rmh rmh; - - if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) { - /* mute outputs */ - if (!mgr->is_hr_stereo) { - /* a read to IO_NUM_REG_MUTE_OUT register unmutes! */ - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); - rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT; - pcxhr_send_msg(mgr, &rmh); - /* mute inputs */ - pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS, - 0, NULL); - } - /* stereo cards mute with reset of dsp */ - } - /* reset pcxhr dsp */ - if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX)) - pcxhr_reset_dsp(mgr); - /* reset second xilinx */ - if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_XLX_COM_INDEX)) { - pcxhr_reset_xilinx_com(mgr); - mgr->dsp_loaded = 1; - } - return; -} - - -/* - * allocate a playback/capture pipe (pcmp0/pcmc0) - */ -static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr, - struct pcxhr_pipe *pipe, - int is_capture, int pin) -{ - int stream_count, audio_count; - int err; - struct pcxhr_rmh rmh; - - if (is_capture) { - stream_count = 1; - if (mgr->mono_capture) - audio_count = 1; - else - audio_count = 2; - } else { - stream_count = PCXHR_PLAYBACK_STREAMS; - audio_count = 2; /* always stereo */ - } - snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n", - pin, is_capture ? 'c' : 'p'); - pipe->is_capture = is_capture; - pipe->first_audio = pin; - /* define pipe (P_PCM_ONLY_MASK (0x020000) is not necessary) */ - pcxhr_init_rmh(&rmh, CMD_RES_PIPE); - pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin, - audio_count, stream_count); - rmh.cmd[1] |= 0x020000; /* add P_PCM_ONLY_MASK */ - if (DSP_EXT_CMD_SET(mgr)) { - /* add channel mask to command */ - rmh.cmd[rmh.cmd_len++] = (audio_count == 1) ? 0x01 : 0x03; - } - err = pcxhr_send_msg(mgr, &rmh); - if (err < 0) { - snd_printk(KERN_ERR "error pipe allocation " - "(CMD_RES_PIPE) err=%x!\n", err); - return err; - } - pipe->status = PCXHR_PIPE_DEFINED; - - return 0; -} - -/* - * free playback/capture pipe (pcmp0/pcmc0) - */ -#if 0 -static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe) -{ - struct pcxhr_rmh rmh; - int capture_mask = 0; - int playback_mask = 0; - int err = 0; - - if (pipe->is_capture) - capture_mask = (1 << pipe->first_audio); - else - playback_mask = (1 << pipe->first_audio); - - /* stop one pipe */ - err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); - if (err < 0) - snd_printk(KERN_ERR "error stopping pipe!\n"); - /* release the pipe */ - pcxhr_init_rmh(&rmh, CMD_FREE_PIPE); - pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio, - 0, 0); - err = pcxhr_send_msg(mgr, &rmh); - if (err < 0) - snd_printk(KERN_ERR "error pipe release " - "(CMD_FREE_PIPE) err(%x)\n", err); - pipe->status = PCXHR_PIPE_UNDEFINED; - return err; -} -#endif - - -static int pcxhr_config_pipes(struct pcxhr_mgr *mgr) -{ - int err, i, j; - struct snd_pcxhr *chip; - struct pcxhr_pipe *pipe; - - /* allocate the pipes on the dsp */ - for (i = 0; i < mgr->num_cards; i++) { - chip = mgr->chip[i]; - if (chip->nb_streams_play) { - pipe = &chip->playback_pipe; - err = pcxhr_dsp_allocate_pipe( mgr, pipe, 0, i*2); - if (err) - return err; - for(j = 0; j < chip->nb_streams_play; j++) - chip->playback_stream[j].pipe = pipe; - } - for (j = 0; j < chip->nb_streams_capt; j++) { - pipe = &chip->capture_pipe[j]; - err = pcxhr_dsp_allocate_pipe(mgr, pipe, 1, i*2 + j); - if (err) - return err; - chip->capture_stream[j].pipe = pipe; - } - } - return 0; -} - -static int pcxhr_start_pipes(struct pcxhr_mgr *mgr) -{ - int i, j; - struct snd_pcxhr *chip; - int playback_mask = 0; - int capture_mask = 0; - - /* start all the pipes on the dsp */ - for (i = 0; i < mgr->num_cards; i++) { - chip = mgr->chip[i]; - if (chip->nb_streams_play) - playback_mask |= 1 << chip->playback_pipe.first_audio; - for (j = 0; j < chip->nb_streams_capt; j++) - capture_mask |= 1 << chip->capture_pipe[j].first_audio; - } - return pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); -} - - -static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, - const struct firmware *dsp) -{ - int err, card_index; - - snd_printdd("loading dsp [%d] size = %Zd\n", index, dsp->size); - - switch (index) { - case PCXHR_FIRMWARE_XLX_INT_INDEX: - pcxhr_reset_xilinx_com(mgr); - return pcxhr_load_xilinx_binary(mgr, dsp, 0); - - case PCXHR_FIRMWARE_XLX_COM_INDEX: - pcxhr_reset_xilinx_com(mgr); - return pcxhr_load_xilinx_binary(mgr, dsp, 1); - - case PCXHR_FIRMWARE_DSP_EPRM_INDEX: - pcxhr_reset_dsp(mgr); - return pcxhr_load_eeprom_binary(mgr, dsp); - - case PCXHR_FIRMWARE_DSP_BOOT_INDEX: - return pcxhr_load_boot_binary(mgr, dsp); - - case PCXHR_FIRMWARE_DSP_MAIN_INDEX: - err = pcxhr_load_dsp_binary(mgr, dsp); - if (err) - return err; - break; /* continue with first init */ - default: - snd_printk(KERN_ERR "wrong file index\n"); - return -EFAULT; - } /* end of switch file index*/ - - /* first communication with embedded */ - err = pcxhr_init_board(mgr); - if (err < 0) { - snd_printk(KERN_ERR "pcxhr could not be set up\n"); - return err; - } - err = pcxhr_config_pipes(mgr); - if (err < 0) { - snd_printk(KERN_ERR "pcxhr pipes could not be set up\n"); - return err; - } - /* create devices and mixer in accordance with HW options*/ - for (card_index = 0; card_index < mgr->num_cards; card_index++) { - struct snd_pcxhr *chip = mgr->chip[card_index]; - - if ((err = pcxhr_create_pcm(chip)) < 0) - return err; - - if (card_index == 0) { - if ((err = pcxhr_create_mixer(chip->mgr)) < 0) - return err; - } - if ((err = snd_card_register(chip->card)) < 0) - return err; - } - err = pcxhr_start_pipes(mgr); - if (err < 0) { - snd_printk(KERN_ERR "pcxhr pipes could not be started\n"); - return err; - } - snd_printdd("pcxhr firmware downloaded and successfully set up\n"); - - return 0; -} - -/* - * fw loader entry - */ -#ifdef SND_PCXHR_FW_LOADER - -int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) -{ - static char *fw_files[][5] = { - [0] = { "xlxint.dat", "xlxc882hr.dat", - "dspe882.e56", "dspb882hr.b56", "dspd882.d56" }, - [1] = { "xlxint.dat", "xlxc882e.dat", - "dspe882.e56", "dspb882e.b56", "dspd882.d56" }, - [2] = { "xlxint.dat", "xlxc1222hr.dat", - "dspe882.e56", "dspb1222hr.b56", "dspd1222.d56" }, - [3] = { "xlxint.dat", "xlxc1222e.dat", - "dspe882.e56", "dspb1222e.b56", "dspd1222.d56" }, - [4] = { NULL, "xlxc222.dat", - "dspe924.e56", "dspb924.b56", "dspd222.d56" }, - [5] = { NULL, "xlxc924.dat", - "dspe924.e56", "dspb924.b56", "dspd222.d56" }, - }; - char path[32]; - - const struct firmware *fw_entry; - int i, err; - int fw_set = mgr->fw_file_set; - - for (i = 0; i < 5; i++) { - if (!fw_files[fw_set][i]) - continue; - sprintf(path, "pcxhr/%s", fw_files[fw_set][i]); - if (request_firmware(&fw_entry, path, &mgr->pci->dev)) { - snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n", - path); - return -ENOENT; - } - /* fake hwdep dsp record */ - err = pcxhr_dsp_load(mgr, i, fw_entry); - release_firmware(fw_entry); - if (err < 0) - return err; - mgr->dsp_loaded |= 1 << i; - } - return 0; -} - -MODULE_FIRMWARE("pcxhr/xlxint.dat"); -MODULE_FIRMWARE("pcxhr/xlxc882hr.dat"); -MODULE_FIRMWARE("pcxhr/xlxc882e.dat"); -MODULE_FIRMWARE("pcxhr/dspe882.e56"); -MODULE_FIRMWARE("pcxhr/dspb882hr.b56"); -MODULE_FIRMWARE("pcxhr/dspb882e.b56"); -MODULE_FIRMWARE("pcxhr/dspd882.d56"); - -MODULE_FIRMWARE("pcxhr/xlxc1222hr.dat"); -MODULE_FIRMWARE("pcxhr/xlxc1222e.dat"); -MODULE_FIRMWARE("pcxhr/dspb1222hr.b56"); -MODULE_FIRMWARE("pcxhr/dspb1222e.b56"); -MODULE_FIRMWARE("pcxhr/dspd1222.d56"); - -MODULE_FIRMWARE("pcxhr/xlxc222.dat"); -MODULE_FIRMWARE("pcxhr/xlxc924.dat"); -MODULE_FIRMWARE("pcxhr/dspe924.e56"); -MODULE_FIRMWARE("pcxhr/dspb924.b56"); -MODULE_FIRMWARE("pcxhr/dspd222.d56"); - - -#else /* old style firmware loading */ - -/* pcxhr hwdep interface id string */ -#define PCXHR_HWDEP_ID "pcxhr loader" - - -static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw, - struct snd_hwdep_dsp_status *info) -{ - struct pcxhr_mgr *mgr = hw->private_data; - sprintf(info->id, "pcxhr%d", mgr->fw_file_set); - info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX; - - if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) - info->chip_ready = 1; - - info->version = PCXHR_DRIVER_VERSION; - return 0; -} - -static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw, - struct snd_hwdep_dsp_image *dsp) -{ - struct pcxhr_mgr *mgr = hw->private_data; - int err; - struct firmware fw; - - fw.size = dsp->length; - fw.data = vmalloc(fw.size); - if (! fw.data) { - snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image " - "(%lu bytes)\n", (unsigned long)fw.size); - return -ENOMEM; - } - if (copy_from_user((void *)fw.data, dsp->image, dsp->length)) { - vfree(fw.data); - return -EFAULT; - } - err = pcxhr_dsp_load(mgr, dsp->index, &fw); - vfree(fw.data); - if (err < 0) - return err; - mgr->dsp_loaded |= 1 << dsp->index; - return 0; -} - -int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) -{ - int err; - struct snd_hwdep *hw; - - /* only create hwdep interface for first cardX - * (see "index" module parameter) - */ - err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw); - if (err < 0) - return err; - - hw->iface = SNDRV_HWDEP_IFACE_PCXHR; - hw->private_data = mgr; - hw->ops.dsp_status = pcxhr_hwdep_dsp_status; - hw->ops.dsp_load = pcxhr_hwdep_dsp_load; - hw->exclusive = 1; - /* stereo cards don't need fw_file_0 -> dsp_loaded = 1 */ - hw->dsp_loaded = mgr->is_hr_stereo ? 1 : 0; - mgr->dsp_loaded = 0; - sprintf(hw->name, PCXHR_HWDEP_ID); - - err = snd_card_register(mgr->chip[0]->card); - if (err < 0) - return err; - return 0; -} - -#endif /* SND_PCXHR_FW_LOADER */ diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.h b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.h deleted file mode 100644 index f561909d..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_hwdep.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * definitions and makros for basic card access - * - * Copyright (c) 2004 by Digigram - * - * 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 - */ - -#ifndef __SOUND_PCXHR_HWDEP_H -#define __SOUND_PCXHR_HWDEP_H - - -/* firmware status codes */ -#define PCXHR_FIRMWARE_XLX_INT_INDEX 0 -#define PCXHR_FIRMWARE_XLX_COM_INDEX 1 -#define PCXHR_FIRMWARE_DSP_EPRM_INDEX 2 -#define PCXHR_FIRMWARE_DSP_BOOT_INDEX 3 -#define PCXHR_FIRMWARE_DSP_MAIN_INDEX 4 -#define PCXHR_FIRMWARE_FILES_MAX_INDEX 5 - - -/* exported */ -int pcxhr_setup_firmware(struct pcxhr_mgr *mgr); -void pcxhr_reset_board(struct pcxhr_mgr *mgr); - -#endif /* __SOUND_PCXHR_HWDEP_H */ diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.c b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.c deleted file mode 100644 index 1cb82c0a..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.c +++ /dev/null @@ -1,852 +0,0 @@ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * mixer interface for stereo cards - * - * Copyright (c) 2004 by Digigram - * - * 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 "pcxhr.h" -#include "pcxhr_core.h" -#include "pcxhr_mix22.h" - - -/* registers used on the DSP and Xilinx (port 2) : HR stereo cards only */ -#define PCXHR_DSP_RESET 0x20 -#define PCXHR_XLX_CFG 0x24 -#define PCXHR_XLX_RUER 0x28 -#define PCXHR_XLX_DATA 0x2C -#define PCXHR_XLX_STATUS 0x30 -#define PCXHR_XLX_LOFREQ 0x34 -#define PCXHR_XLX_HIFREQ 0x38 -#define PCXHR_XLX_CSUER 0x3C -#define PCXHR_XLX_SELMIC 0x40 - -#define PCXHR_DSP 2 - -/* byte access only ! */ -#define PCXHR_INPB(mgr, x) inb((mgr)->port[PCXHR_DSP] + (x)) -#define PCXHR_OUTPB(mgr, x, data) outb((data), (mgr)->port[PCXHR_DSP] + (x)) - - -/* values for PCHR_DSP_RESET register */ -#define PCXHR_DSP_RESET_DSP 0x01 -#define PCXHR_DSP_RESET_MUTE 0x02 -#define PCXHR_DSP_RESET_CODEC 0x08 -#define PCXHR_DSP_RESET_GPO_OFFSET 5 -#define PCXHR_DSP_RESET_GPO_MASK 0x60 - -/* values for PCHR_XLX_CFG register */ -#define PCXHR_CFG_SYNCDSP_MASK 0x80 -#define PCXHR_CFG_DEPENDENCY_MASK 0x60 -#define PCXHR_CFG_INDEPENDANT_SEL 0x00 -#define PCXHR_CFG_MASTER_SEL 0x40 -#define PCXHR_CFG_SLAVE_SEL 0x20 -#define PCXHR_CFG_DATA_UER1_SEL_MASK 0x10 /* 0 (UER0), 1(UER1) */ -#define PCXHR_CFG_DATAIN_SEL_MASK 0x08 /* 0 (ana), 1 (UER) */ -#define PCXHR_CFG_SRC_MASK 0x04 /* 0 (Bypass), 1 (SRC Actif) */ -#define PCXHR_CFG_CLOCK_UER1_SEL_MASK 0x02 /* 0 (UER0), 1(UER1) */ -#define PCXHR_CFG_CLOCKIN_SEL_MASK 0x01 /* 0 (internal), 1 (AES/EBU) */ - -/* values for PCHR_XLX_DATA register */ -#define PCXHR_DATA_CODEC 0x80 -#define AKM_POWER_CONTROL_CMD 0xA007 -#define AKM_RESET_ON_CMD 0xA100 -#define AKM_RESET_OFF_CMD 0xA103 -#define AKM_CLOCK_INF_55K_CMD 0xA240 -#define AKM_CLOCK_SUP_55K_CMD 0xA24D -#define AKM_MUTE_CMD 0xA38D -#define AKM_UNMUTE_CMD 0xA30D -#define AKM_LEFT_LEVEL_CMD 0xA600 -#define AKM_RIGHT_LEVEL_CMD 0xA700 - -/* values for PCHR_XLX_STATUS register - READ */ -#define PCXHR_STAT_SRC_LOCK 0x01 -#define PCXHR_STAT_LEVEL_IN 0x02 -#define PCXHR_STAT_GPI_OFFSET 2 -#define PCXHR_STAT_GPI_MASK 0x0C -#define PCXHR_STAT_MIC_CAPS 0x10 -/* values for PCHR_XLX_STATUS register - WRITE */ -#define PCXHR_STAT_FREQ_SYNC_MASK 0x01 -#define PCXHR_STAT_FREQ_UER1_MASK 0x02 -#define PCXHR_STAT_FREQ_SAVE_MASK 0x80 - -/* values for PCHR_XLX_CSUER register */ -#define PCXHR_SUER1_BIT_U_READ_MASK 0x80 -#define PCXHR_SUER1_BIT_C_READ_MASK 0x40 -#define PCXHR_SUER1_DATA_PRESENT_MASK 0x20 -#define PCXHR_SUER1_CLOCK_PRESENT_MASK 0x10 -#define PCXHR_SUER_BIT_U_READ_MASK 0x08 -#define PCXHR_SUER_BIT_C_READ_MASK 0x04 -#define PCXHR_SUER_DATA_PRESENT_MASK 0x02 -#define PCXHR_SUER_CLOCK_PRESENT_MASK 0x01 - -#define PCXHR_SUER_BIT_U_WRITE_MASK 0x02 -#define PCXHR_SUER_BIT_C_WRITE_MASK 0x01 - -/* values for PCXHR_XLX_SELMIC register - WRITE */ -#define PCXHR_SELMIC_PREAMPLI_OFFSET 2 -#define PCXHR_SELMIC_PREAMPLI_MASK 0x0C -#define PCXHR_SELMIC_PHANTOM_ALIM 0x80 - - -static const unsigned char g_hr222_p_level[] = { - 0x00, /* [000] -49.5 dB: AKM[000] = -1.#INF dB (mute) */ - 0x01, /* [001] -49.0 dB: AKM[001] = -48.131 dB (diff=0.86920 dB) */ - 0x01, /* [002] -48.5 dB: AKM[001] = -48.131 dB (diff=0.36920 dB) */ - 0x01, /* [003] -48.0 dB: AKM[001] = -48.131 dB (diff=0.13080 dB) */ - 0x01, /* [004] -47.5 dB: AKM[001] = -48.131 dB (diff=0.63080 dB) */ - 0x01, /* [005] -46.5 dB: AKM[001] = -48.131 dB (diff=1.63080 dB) */ - 0x01, /* [006] -47.0 dB: AKM[001] = -48.131 dB (diff=1.13080 dB) */ - 0x01, /* [007] -46.0 dB: AKM[001] = -48.131 dB (diff=2.13080 dB) */ - 0x01, /* [008] -45.5 dB: AKM[001] = -48.131 dB (diff=2.63080 dB) */ - 0x02, /* [009] -45.0 dB: AKM[002] = -42.110 dB (diff=2.88980 dB) */ - 0x02, /* [010] -44.5 dB: AKM[002] = -42.110 dB (diff=2.38980 dB) */ - 0x02, /* [011] -44.0 dB: AKM[002] = -42.110 dB (diff=1.88980 dB) */ - 0x02, /* [012] -43.5 dB: AKM[002] = -42.110 dB (diff=1.38980 dB) */ - 0x02, /* [013] -43.0 dB: AKM[002] = -42.110 dB (diff=0.88980 dB) */ - 0x02, /* [014] -42.5 dB: AKM[002] = -42.110 dB (diff=0.38980 dB) */ - 0x02, /* [015] -42.0 dB: AKM[002] = -42.110 dB (diff=0.11020 dB) */ - 0x02, /* [016] -41.5 dB: AKM[002] = -42.110 dB (diff=0.61020 dB) */ - 0x02, /* [017] -41.0 dB: AKM[002] = -42.110 dB (diff=1.11020 dB) */ - 0x02, /* [018] -40.5 dB: AKM[002] = -42.110 dB (diff=1.61020 dB) */ - 0x03, /* [019] -40.0 dB: AKM[003] = -38.588 dB (diff=1.41162 dB) */ - 0x03, /* [020] -39.5 dB: AKM[003] = -38.588 dB (diff=0.91162 dB) */ - 0x03, /* [021] -39.0 dB: AKM[003] = -38.588 dB (diff=0.41162 dB) */ - 0x03, /* [022] -38.5 dB: AKM[003] = -38.588 dB (diff=0.08838 dB) */ - 0x03, /* [023] -38.0 dB: AKM[003] = -38.588 dB (diff=0.58838 dB) */ - 0x03, /* [024] -37.5 dB: AKM[003] = -38.588 dB (diff=1.08838 dB) */ - 0x04, /* [025] -37.0 dB: AKM[004] = -36.090 dB (diff=0.91040 dB) */ - 0x04, /* [026] -36.5 dB: AKM[004] = -36.090 dB (diff=0.41040 dB) */ - 0x04, /* [027] -36.0 dB: AKM[004] = -36.090 dB (diff=0.08960 dB) */ - 0x04, /* [028] -35.5 dB: AKM[004] = -36.090 dB (diff=0.58960 dB) */ - 0x05, /* [029] -35.0 dB: AKM[005] = -34.151 dB (diff=0.84860 dB) */ - 0x05, /* [030] -34.5 dB: AKM[005] = -34.151 dB (diff=0.34860 dB) */ - 0x05, /* [031] -34.0 dB: AKM[005] = -34.151 dB (diff=0.15140 dB) */ - 0x05, /* [032] -33.5 dB: AKM[005] = -34.151 dB (diff=0.65140 dB) */ - 0x06, /* [033] -33.0 dB: AKM[006] = -32.568 dB (diff=0.43222 dB) */ - 0x06, /* [034] -32.5 dB: AKM[006] = -32.568 dB (diff=0.06778 dB) */ - 0x06, /* [035] -32.0 dB: AKM[006] = -32.568 dB (diff=0.56778 dB) */ - 0x07, /* [036] -31.5 dB: AKM[007] = -31.229 dB (diff=0.27116 dB) */ - 0x07, /* [037] -31.0 dB: AKM[007] = -31.229 dB (diff=0.22884 dB) */ - 0x08, /* [038] -30.5 dB: AKM[008] = -30.069 dB (diff=0.43100 dB) */ - 0x08, /* [039] -30.0 dB: AKM[008] = -30.069 dB (diff=0.06900 dB) */ - 0x09, /* [040] -29.5 dB: AKM[009] = -29.046 dB (diff=0.45405 dB) */ - 0x09, /* [041] -29.0 dB: AKM[009] = -29.046 dB (diff=0.04595 dB) */ - 0x0a, /* [042] -28.5 dB: AKM[010] = -28.131 dB (diff=0.36920 dB) */ - 0x0a, /* [043] -28.0 dB: AKM[010] = -28.131 dB (diff=0.13080 dB) */ - 0x0b, /* [044] -27.5 dB: AKM[011] = -27.303 dB (diff=0.19705 dB) */ - 0x0b, /* [045] -27.0 dB: AKM[011] = -27.303 dB (diff=0.30295 dB) */ - 0x0c, /* [046] -26.5 dB: AKM[012] = -26.547 dB (diff=0.04718 dB) */ - 0x0d, /* [047] -26.0 dB: AKM[013] = -25.852 dB (diff=0.14806 dB) */ - 0x0e, /* [048] -25.5 dB: AKM[014] = -25.208 dB (diff=0.29176 dB) */ - 0x0e, /* [049] -25.0 dB: AKM[014] = -25.208 dB (diff=0.20824 dB) */ - 0x0f, /* [050] -24.5 dB: AKM[015] = -24.609 dB (diff=0.10898 dB) */ - 0x10, /* [051] -24.0 dB: AKM[016] = -24.048 dB (diff=0.04840 dB) */ - 0x11, /* [052] -23.5 dB: AKM[017] = -23.522 dB (diff=0.02183 dB) */ - 0x12, /* [053] -23.0 dB: AKM[018] = -23.025 dB (diff=0.02535 dB) */ - 0x13, /* [054] -22.5 dB: AKM[019] = -22.556 dB (diff=0.05573 dB) */ - 0x14, /* [055] -22.0 dB: AKM[020] = -22.110 dB (diff=0.11020 dB) */ - 0x15, /* [056] -21.5 dB: AKM[021] = -21.686 dB (diff=0.18642 dB) */ - 0x17, /* [057] -21.0 dB: AKM[023] = -20.896 dB (diff=0.10375 dB) */ - 0x18, /* [058] -20.5 dB: AKM[024] = -20.527 dB (diff=0.02658 dB) */ - 0x1a, /* [059] -20.0 dB: AKM[026] = -19.831 dB (diff=0.16866 dB) */ - 0x1b, /* [060] -19.5 dB: AKM[027] = -19.504 dB (diff=0.00353 dB) */ - 0x1d, /* [061] -19.0 dB: AKM[029] = -18.883 dB (diff=0.11716 dB) */ - 0x1e, /* [062] -18.5 dB: AKM[030] = -18.588 dB (diff=0.08838 dB) */ - 0x20, /* [063] -18.0 dB: AKM[032] = -18.028 dB (diff=0.02780 dB) */ - 0x22, /* [064] -17.5 dB: AKM[034] = -17.501 dB (diff=0.00123 dB) */ - 0x24, /* [065] -17.0 dB: AKM[036] = -17.005 dB (diff=0.00475 dB) */ - 0x26, /* [066] -16.5 dB: AKM[038] = -16.535 dB (diff=0.03513 dB) */ - 0x28, /* [067] -16.0 dB: AKM[040] = -16.090 dB (diff=0.08960 dB) */ - 0x2b, /* [068] -15.5 dB: AKM[043] = -15.461 dB (diff=0.03857 dB) */ - 0x2d, /* [069] -15.0 dB: AKM[045] = -15.067 dB (diff=0.06655 dB) */ - 0x30, /* [070] -14.5 dB: AKM[048] = -14.506 dB (diff=0.00598 dB) */ - 0x33, /* [071] -14.0 dB: AKM[051] = -13.979 dB (diff=0.02060 dB) */ - 0x36, /* [072] -13.5 dB: AKM[054] = -13.483 dB (diff=0.01707 dB) */ - 0x39, /* [073] -13.0 dB: AKM[057] = -13.013 dB (diff=0.01331 dB) */ - 0x3c, /* [074] -12.5 dB: AKM[060] = -12.568 dB (diff=0.06778 dB) */ - 0x40, /* [075] -12.0 dB: AKM[064] = -12.007 dB (diff=0.00720 dB) */ - 0x44, /* [076] -11.5 dB: AKM[068] = -11.481 dB (diff=0.01937 dB) */ - 0x48, /* [077] -11.0 dB: AKM[072] = -10.984 dB (diff=0.01585 dB) */ - 0x4c, /* [078] -10.5 dB: AKM[076] = -10.515 dB (diff=0.01453 dB) */ - 0x51, /* [079] -10.0 dB: AKM[081] = -9.961 dB (diff=0.03890 dB) */ - 0x55, /* [080] -9.5 dB: AKM[085] = -9.542 dB (diff=0.04243 dB) */ - 0x5a, /* [081] -9.0 dB: AKM[090] = -9.046 dB (diff=0.04595 dB) */ - 0x60, /* [082] -8.5 dB: AKM[096] = -8.485 dB (diff=0.01462 dB) */ - 0x66, /* [083] -8.0 dB: AKM[102] = -7.959 dB (diff=0.04120 dB) */ - 0x6c, /* [084] -7.5 dB: AKM[108] = -7.462 dB (diff=0.03767 dB) */ - 0x72, /* [085] -7.0 dB: AKM[114] = -6.993 dB (diff=0.00729 dB) */ - 0x79, /* [086] -6.5 dB: AKM[121] = -6.475 dB (diff=0.02490 dB) */ - 0x80, /* [087] -6.0 dB: AKM[128] = -5.987 dB (diff=0.01340 dB) */ - 0x87, /* [088] -5.5 dB: AKM[135] = -5.524 dB (diff=0.02413 dB) */ - 0x8f, /* [089] -5.0 dB: AKM[143] = -5.024 dB (diff=0.02408 dB) */ - 0x98, /* [090] -4.5 dB: AKM[152] = -4.494 dB (diff=0.00607 dB) */ - 0xa1, /* [091] -4.0 dB: AKM[161] = -3.994 dB (diff=0.00571 dB) */ - 0xaa, /* [092] -3.5 dB: AKM[170] = -3.522 dB (diff=0.02183 dB) */ - 0xb5, /* [093] -3.0 dB: AKM[181] = -2.977 dB (diff=0.02277 dB) */ - 0xbf, /* [094] -2.5 dB: AKM[191] = -2.510 dB (diff=0.01014 dB) */ - 0xcb, /* [095] -2.0 dB: AKM[203] = -1.981 dB (diff=0.01912 dB) */ - 0xd7, /* [096] -1.5 dB: AKM[215] = -1.482 dB (diff=0.01797 dB) */ - 0xe3, /* [097] -1.0 dB: AKM[227] = -1.010 dB (diff=0.01029 dB) */ - 0xf1, /* [098] -0.5 dB: AKM[241] = -0.490 dB (diff=0.00954 dB) */ - 0xff, /* [099] +0.0 dB: AKM[255] = +0.000 dB (diff=0.00000 dB) */ -}; - - -static void hr222_config_akm(struct pcxhr_mgr *mgr, unsigned short data) -{ - unsigned short mask = 0x8000; - /* activate access to codec registers */ - PCXHR_INPB(mgr, PCXHR_XLX_HIFREQ); - - while (mask) { - PCXHR_OUTPB(mgr, PCXHR_XLX_DATA, - data & mask ? PCXHR_DATA_CODEC : 0); - mask >>= 1; - } - /* termiate access to codec registers */ - PCXHR_INPB(mgr, PCXHR_XLX_RUER); -} - - -static int hr222_set_hw_playback_level(struct pcxhr_mgr *mgr, - int idx, int level) -{ - unsigned short cmd; - if (idx > 1 || - level < 0 || - level >= ARRAY_SIZE(g_hr222_p_level)) - return -EINVAL; - - if (idx == 0) - cmd = AKM_LEFT_LEVEL_CMD; - else - cmd = AKM_RIGHT_LEVEL_CMD; - - /* conversion from PmBoardCodedLevel to AKM nonlinear programming */ - cmd += g_hr222_p_level[level]; - - hr222_config_akm(mgr, cmd); - return 0; -} - - -static int hr222_set_hw_capture_level(struct pcxhr_mgr *mgr, - int level_l, int level_r, int level_mic) -{ - /* program all input levels at the same time */ - unsigned int data; - int i; - - if (!mgr->capture_chips) - return -EINVAL; /* no PCX22 */ - - data = ((level_mic & 0xff) << 24); /* micro is mono, but apply */ - data |= ((level_mic & 0xff) << 16); /* level on both channels */ - data |= ((level_r & 0xff) << 8); /* line input right channel */ - data |= (level_l & 0xff); /* line input left channel */ - - PCXHR_INPB(mgr, PCXHR_XLX_DATA); /* activate input codec */ - /* send 32 bits (4 x 8 bits) */ - for (i = 0; i < 32; i++, data <<= 1) { - PCXHR_OUTPB(mgr, PCXHR_XLX_DATA, - (data & 0x80000000) ? PCXHR_DATA_CODEC : 0); - } - PCXHR_INPB(mgr, PCXHR_XLX_RUER); /* close input level codec */ - return 0; -} - -static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level); - -int hr222_sub_init(struct pcxhr_mgr *mgr) -{ - unsigned char reg; - - mgr->board_has_analog = 1; /* analog always available */ - mgr->xlx_cfg = PCXHR_CFG_SYNCDSP_MASK; - - reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS); - if (reg & PCXHR_STAT_MIC_CAPS) - mgr->board_has_mic = 1; /* microphone available */ - snd_printdd("MIC input available = %d\n", mgr->board_has_mic); - - /* reset codec */ - PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, - PCXHR_DSP_RESET_DSP); - msleep(5); - mgr->dsp_reset = PCXHR_DSP_RESET_DSP | - PCXHR_DSP_RESET_MUTE | - PCXHR_DSP_RESET_CODEC; - PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, mgr->dsp_reset); - /* hr222_write_gpo(mgr, 0); does the same */ - msleep(5); - - /* config AKM */ - hr222_config_akm(mgr, AKM_POWER_CONTROL_CMD); - hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD); - hr222_config_akm(mgr, AKM_UNMUTE_CMD); - hr222_config_akm(mgr, AKM_RESET_OFF_CMD); - - /* init micro boost */ - hr222_micro_boost(mgr, 0); - - return 0; -} - - -/* calc PLL register */ -/* TODO : there is a very similar fct in pcxhr.c */ -static int hr222_pll_freq_register(unsigned int freq, - unsigned int *pllreg, - unsigned int *realfreq) -{ - unsigned int reg; - - if (freq < 6900 || freq > 219000) - return -EINVAL; - reg = (28224000 * 2) / freq; - reg = (reg - 1) / 2; - if (reg < 0x100) - *pllreg = reg + 0xC00; - else if (reg < 0x200) - *pllreg = reg + 0x800; - else if (reg < 0x400) - *pllreg = reg & 0x1ff; - else if (reg < 0x800) { - *pllreg = ((reg >> 1) & 0x1ff) + 0x200; - reg &= ~1; - } else { - *pllreg = ((reg >> 2) & 0x1ff) + 0x400; - reg &= ~3; - } - if (realfreq) - *realfreq = (28224000 / (reg + 1)); - return 0; -} - -int hr222_sub_set_clock(struct pcxhr_mgr *mgr, - unsigned int rate, - int *changed) -{ - unsigned int speed, pllreg = 0; - int err; - unsigned realfreq = rate; - - switch (mgr->use_clock_type) { - case HR22_CLOCK_TYPE_INTERNAL: - err = hr222_pll_freq_register(rate, &pllreg, &realfreq); - if (err) - return err; - - mgr->xlx_cfg &= ~(PCXHR_CFG_CLOCKIN_SEL_MASK | - PCXHR_CFG_CLOCK_UER1_SEL_MASK); - break; - case HR22_CLOCK_TYPE_AES_SYNC: - mgr->xlx_cfg |= PCXHR_CFG_CLOCKIN_SEL_MASK; - mgr->xlx_cfg &= ~PCXHR_CFG_CLOCK_UER1_SEL_MASK; - break; - case HR22_CLOCK_TYPE_AES_1: - if (!mgr->board_has_aes1) - return -EINVAL; - - mgr->xlx_cfg |= (PCXHR_CFG_CLOCKIN_SEL_MASK | - PCXHR_CFG_CLOCK_UER1_SEL_MASK); - break; - default: - return -EINVAL; - } - hr222_config_akm(mgr, AKM_MUTE_CMD); - - if (mgr->use_clock_type == HR22_CLOCK_TYPE_INTERNAL) { - PCXHR_OUTPB(mgr, PCXHR_XLX_HIFREQ, pllreg >> 8); - PCXHR_OUTPB(mgr, PCXHR_XLX_LOFREQ, pllreg & 0xff); - } - - /* set clock source */ - PCXHR_OUTPB(mgr, PCXHR_XLX_CFG, mgr->xlx_cfg); - - /* codec speed modes */ - speed = rate < 55000 ? 0 : 1; - if (mgr->codec_speed != speed) { - mgr->codec_speed = speed; - if (speed == 0) - hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD); - else - hr222_config_akm(mgr, AKM_CLOCK_SUP_55K_CMD); - } - - mgr->sample_rate_real = realfreq; - mgr->cur_clock_type = mgr->use_clock_type; - - if (changed) - *changed = 1; - - hr222_config_akm(mgr, AKM_UNMUTE_CMD); - - snd_printdd("set_clock to %dHz (realfreq=%d pllreg=%x)\n", - rate, realfreq, pllreg); - return 0; -} - -int hr222_get_external_clock(struct pcxhr_mgr *mgr, - enum pcxhr_clock_type clock_type, - int *sample_rate) -{ - int rate, calc_rate = 0; - unsigned int ticks; - unsigned char mask, reg; - - if (clock_type == HR22_CLOCK_TYPE_AES_SYNC) { - - mask = (PCXHR_SUER_CLOCK_PRESENT_MASK | - PCXHR_SUER_DATA_PRESENT_MASK); - reg = PCXHR_STAT_FREQ_SYNC_MASK; - - } else if (clock_type == HR22_CLOCK_TYPE_AES_1 && mgr->board_has_aes1) { - - mask = (PCXHR_SUER1_CLOCK_PRESENT_MASK | - PCXHR_SUER1_DATA_PRESENT_MASK); - reg = PCXHR_STAT_FREQ_UER1_MASK; - - } else { - snd_printdd("get_external_clock : type %d not supported\n", - clock_type); - return -EINVAL; /* other clocks not supported */ - } - - if ((PCXHR_INPB(mgr, PCXHR_XLX_CSUER) & mask) != mask) { - snd_printdd("get_external_clock(%d) = 0 Hz\n", clock_type); - *sample_rate = 0; - return 0; /* no external clock locked */ - } - - PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg); /* calculate freq */ - - /* save the measured clock frequency */ - reg |= PCXHR_STAT_FREQ_SAVE_MASK; - - if (mgr->last_reg_stat != reg) { - udelay(500); /* wait min 2 cycles of lowest freq (8000) */ - mgr->last_reg_stat = reg; - } - - PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg); /* save */ - - /* get the frequency */ - ticks = (unsigned int)PCXHR_INPB(mgr, PCXHR_XLX_CFG); - ticks = (ticks & 0x03) << 8; - ticks |= (unsigned int)PCXHR_INPB(mgr, PCXHR_DSP_RESET); - - if (ticks != 0) - calc_rate = 28224000 / ticks; - /* rounding */ - if (calc_rate > 184200) - rate = 192000; - else if (calc_rate > 152200) - rate = 176400; - else if (calc_rate > 112000) - rate = 128000; - else if (calc_rate > 92100) - rate = 96000; - else if (calc_rate > 76100) - rate = 88200; - else if (calc_rate > 56000) - rate = 64000; - else if (calc_rate > 46050) - rate = 48000; - else if (calc_rate > 38050) - rate = 44100; - else if (calc_rate > 28000) - rate = 32000; - else if (calc_rate > 23025) - rate = 24000; - else if (calc_rate > 19025) - rate = 22050; - else if (calc_rate > 14000) - rate = 16000; - else if (calc_rate > 11512) - rate = 12000; - else if (calc_rate > 9512) - rate = 11025; - else if (calc_rate > 7000) - rate = 8000; - else - rate = 0; - - snd_printdd("External clock is at %d Hz (measured %d Hz)\n", - rate, calc_rate); - *sample_rate = rate; - return 0; -} - - -int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value) -{ - if (is_gpi) { - unsigned char reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS); - *value = (int)(reg & PCXHR_STAT_GPI_MASK) >> - PCXHR_STAT_GPI_OFFSET; - } else { - *value = (int)(mgr->dsp_reset & PCXHR_DSP_RESET_GPO_MASK) >> - PCXHR_DSP_RESET_GPO_OFFSET; - } - return 0; -} - - -int hr222_write_gpo(struct pcxhr_mgr *mgr, int value) -{ - unsigned char reg = mgr->dsp_reset & ~PCXHR_DSP_RESET_GPO_MASK; - - reg |= (unsigned char)(value << PCXHR_DSP_RESET_GPO_OFFSET) & - PCXHR_DSP_RESET_GPO_MASK; - - PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, reg); - mgr->dsp_reset = reg; - return 0; -} - - -int hr222_update_analog_audio_level(struct snd_pcxhr *chip, - int is_capture, int channel) -{ - snd_printdd("hr222_update_analog_audio_level(%s chan=%d)\n", - is_capture ? "capture" : "playback", channel); - if (is_capture) { - int level_l, level_r, level_mic; - /* we have to update all levels */ - if (chip->analog_capture_active) { - level_l = chip->analog_capture_volume[0]; - level_r = chip->analog_capture_volume[1]; - } else { - level_l = HR222_LINE_CAPTURE_LEVEL_MIN; - level_r = HR222_LINE_CAPTURE_LEVEL_MIN; - } - if (chip->mic_active) - level_mic = chip->mic_volume; - else - level_mic = HR222_MICRO_CAPTURE_LEVEL_MIN; - return hr222_set_hw_capture_level(chip->mgr, - level_l, level_r, level_mic); - } else { - int vol; - if (chip->analog_playback_active[channel]) - vol = chip->analog_playback_volume[channel]; - else - vol = HR222_LINE_PLAYBACK_LEVEL_MIN; - return hr222_set_hw_playback_level(chip->mgr, channel, vol); - } -} - - -/*texts[5] = {"Line", "Digital", "Digi+SRC", "Mic", "Line+Mic"}*/ -#define SOURCE_LINE 0 -#define SOURCE_DIGITAL 1 -#define SOURCE_DIGISRC 2 -#define SOURCE_MIC 3 -#define SOURCE_LINEMIC 4 - -int hr222_set_audio_source(struct snd_pcxhr *chip) -{ - int digital = 0; - /* default analog source */ - chip->mgr->xlx_cfg &= ~(PCXHR_CFG_SRC_MASK | - PCXHR_CFG_DATAIN_SEL_MASK | - PCXHR_CFG_DATA_UER1_SEL_MASK); - - if (chip->audio_capture_source == SOURCE_DIGISRC) { - chip->mgr->xlx_cfg |= PCXHR_CFG_SRC_MASK; - digital = 1; - } else { - if (chip->audio_capture_source == SOURCE_DIGITAL) - digital = 1; - } - if (digital) { - chip->mgr->xlx_cfg |= PCXHR_CFG_DATAIN_SEL_MASK; - if (chip->mgr->board_has_aes1) { - /* get data from the AES1 plug */ - chip->mgr->xlx_cfg |= PCXHR_CFG_DATA_UER1_SEL_MASK; - } - /* chip->mic_active = 0; */ - /* chip->analog_capture_active = 0; */ - } else { - int update_lvl = 0; - chip->analog_capture_active = 0; - chip->mic_active = 0; - if (chip->audio_capture_source == SOURCE_LINE || - chip->audio_capture_source == SOURCE_LINEMIC) { - if (chip->analog_capture_active == 0) - update_lvl = 1; - chip->analog_capture_active = 1; - } - if (chip->audio_capture_source == SOURCE_MIC || - chip->audio_capture_source == SOURCE_LINEMIC) { - if (chip->mic_active == 0) - update_lvl = 1; - chip->mic_active = 1; - } - if (update_lvl) { - /* capture: update all 3 mutes/unmutes with one call */ - hr222_update_analog_audio_level(chip, 1, 0); - } - } - /* set the source infos (max 3 bits modified) */ - PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CFG, chip->mgr->xlx_cfg); - return 0; -} - - -int hr222_iec958_capture_byte(struct snd_pcxhr *chip, - int aes_idx, unsigned char *aes_bits) -{ - unsigned char idx = (unsigned char)(aes_idx * 8); - unsigned char temp = 0; - unsigned char mask = chip->mgr->board_has_aes1 ? - PCXHR_SUER1_BIT_C_READ_MASK : PCXHR_SUER_BIT_C_READ_MASK; - int i; - for (i = 0; i < 8; i++) { - PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx++); /* idx < 192 */ - temp <<= 1; - if (PCXHR_INPB(chip->mgr, PCXHR_XLX_CSUER) & mask) - temp |= 1; - } - snd_printdd("read iec958 AES %d byte %d = 0x%x\n", - chip->chip_idx, aes_idx, temp); - *aes_bits = temp; - return 0; -} - - -int hr222_iec958_update_byte(struct snd_pcxhr *chip, - int aes_idx, unsigned char aes_bits) -{ - int i; - unsigned char new_bits = aes_bits; - unsigned char old_bits = chip->aes_bits[aes_idx]; - unsigned char idx = (unsigned char)(aes_idx * 8); - for (i = 0; i < 8; i++) { - if ((old_bits & 0x01) != (new_bits & 0x01)) { - /* idx < 192 */ - PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx); - /* write C and U bit */ - PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CSUER, new_bits&0x01 ? - PCXHR_SUER_BIT_C_WRITE_MASK : 0); - } - idx++; - old_bits >>= 1; - new_bits >>= 1; - } - chip->aes_bits[aes_idx] = aes_bits; - return 0; -} - -static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level) -{ - unsigned char boost_mask; - boost_mask = (unsigned char) (level << PCXHR_SELMIC_PREAMPLI_OFFSET); - if (boost_mask & (~PCXHR_SELMIC_PREAMPLI_MASK)) - return; /* only values form 0 to 3 accepted */ - - mgr->xlx_selmic &= ~PCXHR_SELMIC_PREAMPLI_MASK; - mgr->xlx_selmic |= boost_mask; - - PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic); - - snd_printdd("hr222_micro_boost : set %x\n", boost_mask); -} - -static void hr222_phantom_power(struct pcxhr_mgr *mgr, int power) -{ - if (power) - mgr->xlx_selmic |= PCXHR_SELMIC_PHANTOM_ALIM; - else - mgr->xlx_selmic &= ~PCXHR_SELMIC_PHANTOM_ALIM; - - PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic); - - snd_printdd("hr222_phantom_power : set %d\n", power); -} - - -/* mic level */ -static const DECLARE_TLV_DB_SCALE(db_scale_mic_hr222, -9850, 50, 650); - -static int hr222_mic_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = HR222_MICRO_CAPTURE_LEVEL_MIN; /* -98 dB */ - /* gains from 9 dB to 31.5 dB not recommended; use micboost instead */ - uinfo->value.integer.max = HR222_MICRO_CAPTURE_LEVEL_MAX; /* +7 dB */ - return 0; -} - -static int hr222_mic_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->mic_volume; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int hr222_mic_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); - if (chip->mic_volume != ucontrol->value.integer.value[0]) { - changed = 1; - chip->mic_volume = ucontrol->value.integer.value[0]; - hr222_update_analog_audio_level(chip, 1, 0); - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new hr222_control_mic_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Mic Capture Volume", - .info = hr222_mic_vol_info, - .get = hr222_mic_vol_get, - .put = hr222_mic_vol_put, - .tlv = { .p = db_scale_mic_hr222 }, -}; - - -/* mic boost level */ -static const DECLARE_TLV_DB_SCALE(db_scale_micboost_hr222, 0, 1800, 5400); - -static int hr222_mic_boost_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; /* 0 dB */ - uinfo->value.integer.max = 3; /* 54 dB */ - return 0; -} - -static int hr222_mic_boost_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->mic_boost; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int hr222_mic_boost_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); - if (chip->mic_boost != ucontrol->value.integer.value[0]) { - changed = 1; - chip->mic_boost = ucontrol->value.integer.value[0]; - hr222_micro_boost(chip->mgr, chip->mic_boost); - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new hr222_control_mic_boost = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "MicBoost Capture Volume", - .info = hr222_mic_boost_info, - .get = hr222_mic_boost_get, - .put = hr222_mic_boost_put, - .tlv = { .p = db_scale_micboost_hr222 }, -}; - - -/******************* Phantom power switch *******************/ -#define hr222_phantom_power_info snd_ctl_boolean_mono_info - -static int hr222_phantom_power_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->phantom_power; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int hr222_phantom_power_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int power, changed = 0; - - mutex_lock(&chip->mgr->mixer_mutex); - power = !!ucontrol->value.integer.value[0]; - if (chip->phantom_power != power) { - hr222_phantom_power(chip->mgr, power); - chip->phantom_power = power; - changed = 1; - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new hr222_phantom_power_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Phantom Power Switch", - .info = hr222_phantom_power_info, - .get = hr222_phantom_power_get, - .put = hr222_phantom_power_put, -}; - - -int hr222_add_mic_controls(struct snd_pcxhr *chip) -{ - int err; - if (!chip->mgr->board_has_mic) - return 0; - - /* controls */ - err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_level, - chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_boost, - chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_phantom_power_switch, - chip)); - return err; -} diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.h b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.h deleted file mode 100644 index 5a37a000..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mix22.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * low level interface with interrupt ans message handling - * - * Copyright (c) 2004 by Digigram - * - * 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 - */ - -#ifndef __SOUND_PCXHR_MIX22_H -#define __SOUND_PCXHR_MIX22_H - -struct pcxhr_mgr; - -int hr222_sub_init(struct pcxhr_mgr *mgr); -int hr222_sub_set_clock(struct pcxhr_mgr *mgr, unsigned int rate, - int *changed); -int hr222_get_external_clock(struct pcxhr_mgr *mgr, - enum pcxhr_clock_type clock_type, - int *sample_rate); - -int hr222_read_gpio(struct pcxhr_mgr *mgr, int is_gpi, int *value); -int hr222_write_gpo(struct pcxhr_mgr *mgr, int value); - -#define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */ -#define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */ -#define HR222_LINE_PLAYBACK_LEVEL_MAX 99 /* +24.0 dB */ - -#define HR222_LINE_CAPTURE_LEVEL_MIN 0 /* -111.5 dB */ -#define HR222_LINE_CAPTURE_ZERO_LEVEL 223 /* 0.0 dB */ -#define HR222_LINE_CAPTURE_LEVEL_MAX 255 /* +16 dB */ -#define HR222_MICRO_CAPTURE_LEVEL_MIN 0 /* -98.5 dB */ -#define HR222_MICRO_CAPTURE_LEVEL_MAX 210 /* +6.5 dB */ - -int hr222_update_analog_audio_level(struct snd_pcxhr *chip, - int is_capture, - int channel); -int hr222_set_audio_source(struct snd_pcxhr *chip); -int hr222_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, - unsigned char *aes_bits); -int hr222_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, - unsigned char aes_bits); - -int hr222_add_mic_controls(struct snd_pcxhr *chip); - -#endif /* __SOUND_PCXHR_MIX22_H */ diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.c b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.c deleted file mode 100644 index fec04934..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.c +++ /dev/null @@ -1,1270 +0,0 @@ -#define __NO_VERSION__ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * mixer callbacks - * - * Copyright (c) 2004 by Digigram - * - * 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 "pcxhr.h" -#include "pcxhr_hwdep.h" -#include "pcxhr_core.h" -#include -#include -#include -#include "pcxhr_mixer.h" -#include "pcxhr_mix22.h" - -#define PCXHR_LINE_CAPTURE_LEVEL_MIN 0 /* -112.0 dB */ -#define PCXHR_LINE_CAPTURE_LEVEL_MAX 255 /* +15.5 dB */ -#define PCXHR_LINE_CAPTURE_ZERO_LEVEL 224 /* 0.0 dB ( 0 dBu -> 0 dBFS ) */ - -#define PCXHR_LINE_PLAYBACK_LEVEL_MIN 0 /* -104.0 dB */ -#define PCXHR_LINE_PLAYBACK_LEVEL_MAX 128 /* +24.0 dB */ -#define PCXHR_LINE_PLAYBACK_ZERO_LEVEL 104 /* 0.0 dB ( 0 dBFS -> 0 dBu ) */ - -static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -11200, 50, 1550); -static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400); - -static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_capture, -11150, 50, 1600); -static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_playback, -2550, 50, 2400); - -static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, - int is_capture, int channel) -{ - int err, vol; - struct pcxhr_rmh rmh; - - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); - if (is_capture) { - rmh.cmd[0] |= IO_NUM_REG_IN_ANA_LEVEL; - rmh.cmd[2] = chip->analog_capture_volume[channel]; - } else { - rmh.cmd[0] |= IO_NUM_REG_OUT_ANA_LEVEL; - if (chip->analog_playback_active[channel]) - vol = chip->analog_playback_volume[channel]; - else - vol = PCXHR_LINE_PLAYBACK_LEVEL_MIN; - /* playback analog levels are inversed */ - rmh.cmd[2] = PCXHR_LINE_PLAYBACK_LEVEL_MAX - vol; - } - rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */ - rmh.cmd_len = 3; - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err < 0) { - snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d)" - " is_capture(%d) err(%x)\n", - chip->chip_idx, is_capture, err); - return -EINVAL; - } - return 0; -} - -/* - * analog level control - */ -static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - if (kcontrol->private_value == 0) { /* playback */ - if (chip->mgr->is_hr_stereo) { - uinfo->value.integer.min = - HR222_LINE_PLAYBACK_LEVEL_MIN; /* -25 dB */ - uinfo->value.integer.max = - HR222_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */ - } else { - uinfo->value.integer.min = - PCXHR_LINE_PLAYBACK_LEVEL_MIN; /*-104 dB */ - uinfo->value.integer.max = - PCXHR_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */ - } - } else { /* capture */ - if (chip->mgr->is_hr_stereo) { - uinfo->value.integer.min = - HR222_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */ - uinfo->value.integer.max = - HR222_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */ - } else { - uinfo->value.integer.min = - PCXHR_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */ - uinfo->value.integer.max = - PCXHR_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */ - } - } - return 0; -} - -static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - if (kcontrol->private_value == 0) { /* playback */ - ucontrol->value.integer.value[0] = chip->analog_playback_volume[0]; - ucontrol->value.integer.value[1] = chip->analog_playback_volume[1]; - } else { /* capture */ - ucontrol->value.integer.value[0] = chip->analog_capture_volume[0]; - ucontrol->value.integer.value[1] = chip->analog_capture_volume[1]; - } - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int is_capture, i; - - mutex_lock(&chip->mgr->mixer_mutex); - is_capture = (kcontrol->private_value != 0); - for (i = 0; i < 2; i++) { - int new_volume = ucontrol->value.integer.value[i]; - int *stored_volume = is_capture ? - &chip->analog_capture_volume[i] : - &chip->analog_playback_volume[i]; - if (is_capture) { - if (chip->mgr->is_hr_stereo) { - if (new_volume < HR222_LINE_CAPTURE_LEVEL_MIN || - new_volume > HR222_LINE_CAPTURE_LEVEL_MAX) - continue; - } else { - if (new_volume < PCXHR_LINE_CAPTURE_LEVEL_MIN || - new_volume > PCXHR_LINE_CAPTURE_LEVEL_MAX) - continue; - } - } else { - if (chip->mgr->is_hr_stereo) { - if (new_volume < HR222_LINE_PLAYBACK_LEVEL_MIN || - new_volume > HR222_LINE_PLAYBACK_LEVEL_MAX) - continue; - } else { - if (new_volume < PCXHR_LINE_PLAYBACK_LEVEL_MIN || - new_volume > PCXHR_LINE_PLAYBACK_LEVEL_MAX) - continue; - } - } - if (*stored_volume != new_volume) { - *stored_volume = new_volume; - changed = 1; - if (chip->mgr->is_hr_stereo) - hr222_update_analog_audio_level(chip, - is_capture, i); - else - pcxhr_update_analog_audio_level(chip, - is_capture, i); - } - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new pcxhr_control_analog_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - /* name will be filled later */ - .info = pcxhr_analog_vol_info, - .get = pcxhr_analog_vol_get, - .put = pcxhr_analog_vol_put, - /* tlv will be filled later */ -}; - -/* shared */ - -#define pcxhr_sw_info snd_ctl_boolean_stereo_info - -static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->analog_playback_active[0]; - ucontrol->value.integer.value[1] = chip->analog_playback_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int i, changed = 0; - mutex_lock(&chip->mgr->mixer_mutex); - for(i = 0; i < 2; i++) { - if (chip->analog_playback_active[i] != - ucontrol->value.integer.value[i]) { - chip->analog_playback_active[i] = - !!ucontrol->value.integer.value[i]; - changed = 1; - /* update playback levels */ - if (chip->mgr->is_hr_stereo) - hr222_update_analog_audio_level(chip, 0, i); - else - pcxhr_update_analog_audio_level(chip, 0, i); - } - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new pcxhr_control_output_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = pcxhr_sw_info, /* shared */ - .get = pcxhr_audio_sw_get, - .put = pcxhr_audio_sw_put -}; - - -#define PCXHR_DIGITAL_LEVEL_MIN 0x000 /* -110 dB */ -#define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ -#define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ - -static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10975, 25, 1800); - -#define MORE_THAN_ONE_STREAM_LEVEL 0x000001 -#define VALID_STREAM_PAN_LEVEL_MASK 0x800000 -#define VALID_STREAM_LEVEL_MASK 0x400000 -#define VALID_STREAM_LEVEL_1_MASK 0x200000 -#define VALID_STREAM_LEVEL_2_MASK 0x100000 - -static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx) -{ - int err; - struct pcxhr_rmh rmh; - struct pcxhr_pipe *pipe = &chip->playback_pipe; - int left, right; - - if (chip->digital_playback_active[idx][0]) - left = chip->digital_playback_volume[idx][0]; - else - left = PCXHR_DIGITAL_LEVEL_MIN; - if (chip->digital_playback_active[idx][1]) - right = chip->digital_playback_volume[idx][1]; - else - right = PCXHR_DIGITAL_LEVEL_MIN; - - pcxhr_init_rmh(&rmh, CMD_STREAM_OUT_LEVEL_ADJUST); - /* add pipe and stream mask */ - pcxhr_set_pipe_cmd_params(&rmh, 0, pipe->first_audio, 0, 1<left / right->right panoramic level */ - rmh.cmd[0] |= MORE_THAN_ONE_STREAM_LEVEL; - rmh.cmd[2] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_1_MASK; - rmh.cmd[2] |= (left << 10); - rmh.cmd[3] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_2_MASK; - rmh.cmd[3] |= right; - rmh.cmd_len = 4; - - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err < 0) { - snd_printk(KERN_DEBUG "error update_playback_stream_level " - "card(%d) err(%x)\n", chip->chip_idx, err); - return -EINVAL; - } - return 0; -} - -#define AUDIO_IO_HAS_MUTE_LEVEL 0x400000 -#define AUDIO_IO_HAS_MUTE_MONITOR_1 0x200000 -#define VALID_AUDIO_IO_DIGITAL_LEVEL 0x000001 -#define VALID_AUDIO_IO_MONITOR_LEVEL 0x000002 -#define VALID_AUDIO_IO_MUTE_LEVEL 0x000004 -#define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008 - -static int pcxhr_update_audio_pipe_level(struct snd_pcxhr *chip, - int capture, int channel) -{ - int err; - struct pcxhr_rmh rmh; - struct pcxhr_pipe *pipe; - - if (capture) - pipe = &chip->capture_pipe[0]; - else - pipe = &chip->playback_pipe; - - pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST); - /* add channel mask */ - pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, - 1 << (channel + pipe->first_audio)); - /* TODO : if mask (3 << pipe->first_audio) is used, left and right - * channel will be programmed to the same params */ - if (capture) { - rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL; - /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled - * (capture pipe level) */ - rmh.cmd[2] = chip->digital_capture_volume[channel]; - } else { - rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | - VALID_AUDIO_IO_MUTE_MONITOR_1; - /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL - * not yet handled (playback pipe level) - */ - rmh.cmd[2] = chip->monitoring_volume[channel] << 10; - if (chip->monitoring_active[channel] == 0) - rmh.cmd[2] |= AUDIO_IO_HAS_MUTE_MONITOR_1; - } - rmh.cmd_len = 3; - - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err < 0) { - snd_printk(KERN_DEBUG "error update_audio_level(%d) err=%x\n", - chip->chip_idx, err); - return -EINVAL; - } - return 0; -} - - -/* shared */ -static int pcxhr_digital_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = PCXHR_DIGITAL_LEVEL_MIN; /* -109.5 dB */ - uinfo->value.integer.max = PCXHR_DIGITAL_LEVEL_MAX; /* 18.0 dB */ - return 0; -} - - -static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int *stored_volume; - int is_capture = kcontrol->private_value; - - mutex_lock(&chip->mgr->mixer_mutex); - if (is_capture) /* digital capture */ - stored_volume = chip->digital_capture_volume; - else /* digital playback */ - stored_volume = chip->digital_playback_volume[idx]; - ucontrol->value.integer.value[0] = stored_volume[0]; - ucontrol->value.integer.value[1] = stored_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int changed = 0; - int is_capture = kcontrol->private_value; - int *stored_volume; - int i; - - mutex_lock(&chip->mgr->mixer_mutex); - if (is_capture) /* digital capture */ - stored_volume = chip->digital_capture_volume; - else /* digital playback */ - stored_volume = chip->digital_playback_volume[idx]; - for (i = 0; i < 2; i++) { - int vol = ucontrol->value.integer.value[i]; - if (vol < PCXHR_DIGITAL_LEVEL_MIN || - vol > PCXHR_DIGITAL_LEVEL_MAX) - continue; - if (stored_volume[i] != vol) { - stored_volume[i] = vol; - changed = 1; - if (is_capture) /* update capture volume */ - pcxhr_update_audio_pipe_level(chip, 1, i); - } - } - if (!is_capture && changed) /* update playback volume */ - pcxhr_update_playback_stream_level(chip, idx); - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new snd_pcxhr_pcm_vol = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - /* name will be filled later */ - /* count will be filled later */ - .info = pcxhr_digital_vol_info, /* shared */ - .get = pcxhr_pcm_vol_get, - .put = pcxhr_pcm_vol_put, - .tlv = { .p = db_scale_digital }, -}; - - -static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0]; - ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */ - int i, j; - - mutex_lock(&chip->mgr->mixer_mutex); - j = idx; - for (i = 0; i < 2; i++) { - if (chip->digital_playback_active[j][i] != - ucontrol->value.integer.value[i]) { - chip->digital_playback_active[j][i] = - !!ucontrol->value.integer.value[i]; - changed = 1; - } - } - if (changed) - pcxhr_update_playback_stream_level(chip, idx); - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new pcxhr_control_pcm_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .count = PCXHR_PLAYBACK_STREAMS, - .info = pcxhr_sw_info, /* shared */ - .get = pcxhr_pcm_sw_get, - .put = pcxhr_pcm_sw_put -}; - - -/* - * monitoring level control - */ - -static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->monitoring_volume[0]; - ucontrol->value.integer.value[1] = chip->monitoring_volume[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int i; - - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 2; i++) { - if (chip->monitoring_volume[i] != - ucontrol->value.integer.value[i]) { - chip->monitoring_volume[i] = - ucontrol->value.integer.value[i]; - if (chip->monitoring_active[i]) - /* update monitoring volume and mute */ - /* do only when monitoring is unmuted */ - pcxhr_update_audio_pipe_level(chip, 0, i); - changed = 1; - } - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new pcxhr_control_monitor_vol = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Monitoring Playback Volume", - .info = pcxhr_digital_vol_info, /* shared */ - .get = pcxhr_monitor_vol_get, - .put = pcxhr_monitor_vol_put, - .tlv = { .p = db_scale_digital }, -}; - -/* - * monitoring switch control - */ - -static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - mutex_lock(&chip->mgr->mixer_mutex); - ucontrol->value.integer.value[0] = chip->monitoring_active[0]; - ucontrol->value.integer.value[1] = chip->monitoring_active[1]; - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int i; - - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 2; i++) { - if (chip->monitoring_active[i] != - ucontrol->value.integer.value[i]) { - chip->monitoring_active[i] = - !!ucontrol->value.integer.value[i]; - changed |= (1<mgr->mixer_mutex); - return (changed != 0); -} - -static struct snd_kcontrol_new pcxhr_control_monitor_sw = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitoring Playback Switch", - .info = pcxhr_sw_info, /* shared */ - .get = pcxhr_monitor_sw_get, - .put = pcxhr_monitor_sw_put -}; - - - -/* - * audio source select - */ -#define PCXHR_SOURCE_AUDIO01_UER 0x000100 -#define PCXHR_SOURCE_AUDIO01_SYNC 0x000200 -#define PCXHR_SOURCE_AUDIO23_UER 0x000400 -#define PCXHR_SOURCE_AUDIO45_UER 0x001000 -#define PCXHR_SOURCE_AUDIO67_UER 0x040000 - -static int pcxhr_set_audio_source(struct snd_pcxhr* chip) -{ - struct pcxhr_rmh rmh; - unsigned int mask, reg; - unsigned int codec; - int err, changed; - - switch (chip->chip_idx) { - case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break; - case 1 : mask = PCXHR_SOURCE_AUDIO23_UER; codec = CS8420_23_CS; break; - case 2 : mask = PCXHR_SOURCE_AUDIO45_UER; codec = CS8420_45_CS; break; - case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break; - default: return -EINVAL; - } - if (chip->audio_capture_source != 0) { - reg = mask; /* audio source from digital plug */ - } else { - reg = 0; /* audio source from analog plug */ - } - /* set the input source */ - pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed); - /* resync them (otherwise channel inversion possible) */ - if (changed) { - pcxhr_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS); - rmh.cmd[0] |= (1 << chip->chip_idx); - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err) - return err; - } - if (chip->mgr->board_aes_in_192k) { - int i; - unsigned int src_config = 0xC0; - /* update all src configs with one call */ - for (i = 0; (i < 4) && (i < chip->mgr->capture_chips); i++) { - if (chip->mgr->chip[i]->audio_capture_source == 2) - src_config |= (1 << (3 - i)); - } - /* set codec SRC on off */ - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); - rmh.cmd_len = 2; - rmh.cmd[0] |= IO_NUM_REG_CONFIG_SRC; - rmh.cmd[1] = src_config; - err = pcxhr_send_msg(chip->mgr, &rmh); - } else { - int use_src = 0; - if (chip->audio_capture_source == 2) - use_src = 1; - /* set codec SRC on off */ - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); - rmh.cmd_len = 3; - rmh.cmd[0] |= IO_NUM_UER_CHIP_REG; - rmh.cmd[1] = codec; - rmh.cmd[2] = ((CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | - (use_src ? 0x41 : 0x54)); - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err) - return err; - rmh.cmd[2] = ((CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | - (use_src ? 0x41 : 0x49)); - err = pcxhr_send_msg(chip->mgr, &rmh); - } - return err; -} - -static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[5] = { - "Line", "Digital", "Digi+SRC", "Mic", "Line+Mic" - }; - int i; - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - - i = 2; /* no SRC, no Mic available */ - if (chip->mgr->board_has_aes1) { - i = 3; /* SRC available */ - if (chip->mgr->board_has_mic) - i = 5; /* Mic and MicroMix available */ - } - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = i; - if (uinfo->value.enumerated.item > (i-1)) - uinfo->value.enumerated.item = i-1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int pcxhr_audio_src_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = chip->audio_capture_source; - return 0; -} - -static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int ret = 0; - int i = 2; /* no SRC, no Mic available */ - if (chip->mgr->board_has_aes1) { - i = 3; /* SRC available */ - if (chip->mgr->board_has_mic) - i = 5; /* Mic and MicroMix available */ - } - if (ucontrol->value.enumerated.item[0] >= i) - return -EINVAL; - mutex_lock(&chip->mgr->mixer_mutex); - if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) { - chip->audio_capture_source = ucontrol->value.enumerated.item[0]; - if (chip->mgr->is_hr_stereo) - hr222_set_audio_source(chip); - else - pcxhr_set_audio_source(chip); - ret = 1; - } - mutex_unlock(&chip->mgr->mixer_mutex); - return ret; -} - -static struct snd_kcontrol_new pcxhr_control_audio_src = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = pcxhr_audio_src_info, - .get = pcxhr_audio_src_get, - .put = pcxhr_audio_src_put, -}; - - -/* - * clock type selection - * enum pcxhr_clock_type { - * PCXHR_CLOCK_TYPE_INTERNAL = 0, - * PCXHR_CLOCK_TYPE_WORD_CLOCK, - * PCXHR_CLOCK_TYPE_AES_SYNC, - * PCXHR_CLOCK_TYPE_AES_1, - * PCXHR_CLOCK_TYPE_AES_2, - * PCXHR_CLOCK_TYPE_AES_3, - * PCXHR_CLOCK_TYPE_AES_4, - * PCXHR_CLOCK_TYPE_MAX = PCXHR_CLOCK_TYPE_AES_4, - * HR22_CLOCK_TYPE_INTERNAL = PCXHR_CLOCK_TYPE_INTERNAL, - * HR22_CLOCK_TYPE_AES_SYNC, - * HR22_CLOCK_TYPE_AES_1, - * HR22_CLOCK_TYPE_MAX = HR22_CLOCK_TYPE_AES_1, - * }; - */ - -static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char *textsPCXHR[7] = { - "Internal", "WordClock", "AES Sync", - "AES 1", "AES 2", "AES 3", "AES 4" - }; - static const char *textsHR22[3] = { - "Internal", "AES Sync", "AES 1" - }; - const char **texts; - struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); - int clock_items = 2; /* at least Internal and AES Sync clock */ - if (mgr->board_has_aes1) { - clock_items += mgr->capture_chips; /* add AES x */ - if (!mgr->is_hr_stereo) - clock_items += 1; /* add word clock */ - } - if (mgr->is_hr_stereo) { - texts = textsHR22; - snd_BUG_ON(clock_items > (HR22_CLOCK_TYPE_MAX+1)); - } else { - texts = textsPCXHR; - snd_BUG_ON(clock_items > (PCXHR_CLOCK_TYPE_MAX+1)); - } - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = clock_items; - if (uinfo->value.enumerated.item >= clock_items) - uinfo->value.enumerated.item = clock_items-1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int pcxhr_clock_type_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = mgr->use_clock_type; - return 0; -} - -static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); - int rate, ret = 0; - unsigned int clock_items = 2; /* at least Internal and AES Sync clock */ - if (mgr->board_has_aes1) { - clock_items += mgr->capture_chips; /* add AES x */ - if (!mgr->is_hr_stereo) - clock_items += 1; /* add word clock */ - } - if (ucontrol->value.enumerated.item[0] >= clock_items) - return -EINVAL; - mutex_lock(&mgr->mixer_mutex); - if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) { - mutex_lock(&mgr->setup_mutex); - mgr->use_clock_type = ucontrol->value.enumerated.item[0]; - rate = 0; - if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) { - pcxhr_get_external_clock(mgr, mgr->use_clock_type, - &rate); - } else { - rate = mgr->sample_rate; - if (!rate) - rate = 48000; - } - if (rate) { - pcxhr_set_clock(mgr, rate); - if (mgr->sample_rate) - mgr->sample_rate = rate; - } - mutex_unlock(&mgr->setup_mutex); - ret = 1; /* return 1 even if the set was not done. ok ? */ - } - mutex_unlock(&mgr->mixer_mutex); - return ret; -} - -static struct snd_kcontrol_new pcxhr_control_clock_type = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Clock Mode", - .info = pcxhr_clock_type_info, - .get = pcxhr_clock_type_get, - .put = pcxhr_clock_type_put, -}; - -/* - * clock rate control - * specific control that scans the sample rates on the external plugs - */ -static int pcxhr_clock_rate_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 3 + mgr->capture_chips; - uinfo->value.integer.min = 0; /* clock not present */ - uinfo->value.integer.max = 192000; /* max sample rate 192 kHz */ - return 0; -} - -static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); - int i, err, rate; - - mutex_lock(&mgr->mixer_mutex); - for(i = 0; i < 3 + mgr->capture_chips; i++) { - if (i == PCXHR_CLOCK_TYPE_INTERNAL) - rate = mgr->sample_rate_real; - else { - err = pcxhr_get_external_clock(mgr, i, &rate); - if (err) - break; - } - ucontrol->value.integer.value[i] = rate; - } - mutex_unlock(&mgr->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new pcxhr_control_clock_rate = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "Clock Rates", - .info = pcxhr_clock_rate_info, - .get = pcxhr_clock_rate_get, -}; - -/* - * IEC958 status bits - */ -static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, - int aes_idx, unsigned char *aes_bits) -{ - int i, err; - unsigned char temp; - struct pcxhr_rmh rmh; - - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); - rmh.cmd[0] |= IO_NUM_UER_CHIP_REG; - switch (chip->chip_idx) { - /* instead of CS8420_01_CS use CS8416_01_CS for AES SYNC plug */ - case 0: rmh.cmd[1] = CS8420_01_CS; break; - case 1: rmh.cmd[1] = CS8420_23_CS; break; - case 2: rmh.cmd[1] = CS8420_45_CS; break; - case 3: rmh.cmd[1] = CS8420_67_CS; break; - default: return -EINVAL; - } - if (chip->mgr->board_aes_in_192k) { - switch (aes_idx) { - case 0: rmh.cmd[2] = CS8416_CSB0; break; - case 1: rmh.cmd[2] = CS8416_CSB1; break; - case 2: rmh.cmd[2] = CS8416_CSB2; break; - case 3: rmh.cmd[2] = CS8416_CSB3; break; - case 4: rmh.cmd[2] = CS8416_CSB4; break; - default: return -EINVAL; - } - } else { - switch (aes_idx) { - /* instead of CS8420_CSB0 use CS8416_CSBx for AES SYNC plug */ - case 0: rmh.cmd[2] = CS8420_CSB0; break; - case 1: rmh.cmd[2] = CS8420_CSB1; break; - case 2: rmh.cmd[2] = CS8420_CSB2; break; - case 3: rmh.cmd[2] = CS8420_CSB3; break; - case 4: rmh.cmd[2] = CS8420_CSB4; break; - default: return -EINVAL; - } - } - /* size and code the chip id for the fpga */ - rmh.cmd[1] &= 0x0fffff; - /* chip signature + map for spi read */ - rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; - rmh.cmd_len = 3; - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err) - return err; - - if (chip->mgr->board_aes_in_192k) { - temp = (unsigned char)rmh.stat[1]; - } else { - temp = 0; - /* reversed bit order (not with CS8416_01_CS) */ - for (i = 0; i < 8; i++) { - temp <<= 1; - if (rmh.stat[1] & (1 << i)) - temp |= 1; - } - } - snd_printdd("read iec958 AES %d byte %d = 0x%x\n", - chip->chip_idx, aes_idx, temp); - *aes_bits = temp; - return 0; -} - -static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - unsigned char aes_bits; - int i, err; - - mutex_lock(&chip->mgr->mixer_mutex); - for(i = 0; i < 5; i++) { - if (kcontrol->private_value == 0) /* playback */ - aes_bits = chip->aes_bits[i]; - else { /* capture */ - if (chip->mgr->is_hr_stereo) - err = hr222_iec958_capture_byte(chip, i, - &aes_bits); - else - err = pcxhr_iec958_capture_byte(chip, i, - &aes_bits); - if (err) - break; - } - ucontrol->value.iec958.status[i] = aes_bits; - } - mutex_unlock(&chip->mgr->mixer_mutex); - return 0; -} - -static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int i; - for (i = 0; i < 5; i++) - ucontrol->value.iec958.status[i] = 0xff; - return 0; -} - -static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, - int aes_idx, unsigned char aes_bits) -{ - int i, err, cmd; - unsigned char new_bits = aes_bits; - unsigned char old_bits = chip->aes_bits[aes_idx]; - struct pcxhr_rmh rmh; - - for (i = 0; i < 8; i++) { - if ((old_bits & 0x01) != (new_bits & 0x01)) { - cmd = chip->chip_idx & 0x03; /* chip index 0..3 */ - if (chip->chip_idx > 3) - /* new bit used if chip_idx>3 (PCX1222HR) */ - cmd |= 1 << 22; - cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */ - cmd |= (new_bits & 0x01) << 23; /* add bit value */ - pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); - rmh.cmd[0] |= IO_NUM_REG_CUER; - rmh.cmd[1] = cmd; - rmh.cmd_len = 2; - snd_printdd("write iec958 AES %d byte %d bit %d (cmd %x)\n", - chip->chip_idx, aes_idx, i, cmd); - err = pcxhr_send_msg(chip->mgr, &rmh); - if (err) - return err; - } - old_bits >>= 1; - new_bits >>= 1; - } - chip->aes_bits[aes_idx] = aes_bits; - return 0; -} - -static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); - int i, changed = 0; - - /* playback */ - mutex_lock(&chip->mgr->mixer_mutex); - for (i = 0; i < 5; i++) { - if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) { - if (chip->mgr->is_hr_stereo) - hr222_iec958_update_byte(chip, i, - ucontrol->value.iec958.status[i]); - else - pcxhr_iec958_update_byte(chip, i, - ucontrol->value.iec958.status[i]); - changed = 1; - } - } - mutex_unlock(&chip->mgr->mixer_mutex); - return changed; -} - -static struct snd_kcontrol_new pcxhr_control_playback_iec958_mask = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .info = pcxhr_iec958_info, - .get = pcxhr_iec958_mask_get -}; -static struct snd_kcontrol_new pcxhr_control_playback_iec958 = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = pcxhr_iec958_info, - .get = pcxhr_iec958_get, - .put = pcxhr_iec958_put, - .private_value = 0 /* playback */ -}; - -static struct snd_kcontrol_new pcxhr_control_capture_iec958_mask = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK), - .info = pcxhr_iec958_info, - .get = pcxhr_iec958_mask_get -}; -static struct snd_kcontrol_new pcxhr_control_capture_iec958 = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), - .info = pcxhr_iec958_info, - .get = pcxhr_iec958_get, - .private_value = 1 /* capture */ -}; - -static void pcxhr_init_audio_levels(struct snd_pcxhr *chip) -{ - int i; - - for (i = 0; i < 2; i++) { - if (chip->nb_streams_play) { - int j; - /* at boot time the digital volumes are unmuted 0dB */ - for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) { - chip->digital_playback_active[j][i] = 1; - chip->digital_playback_volume[j][i] = - PCXHR_DIGITAL_ZERO_LEVEL; - } - /* after boot, only two bits are set on the uer - * interface - */ - chip->aes_bits[0] = (IEC958_AES0_PROFESSIONAL | - IEC958_AES0_PRO_FS_48000); -#ifdef CONFIG_SND_DEBUG - /* analog volumes for playback - * (is LEVEL_MIN after boot) - */ - chip->analog_playback_active[i] = 1; - if (chip->mgr->is_hr_stereo) - chip->analog_playback_volume[i] = - HR222_LINE_PLAYBACK_ZERO_LEVEL; - else { - chip->analog_playback_volume[i] = - PCXHR_LINE_PLAYBACK_ZERO_LEVEL; - pcxhr_update_analog_audio_level(chip, 0, i); - } -#endif - /* stereo cards need to be initialised after boot */ - if (chip->mgr->is_hr_stereo) - hr222_update_analog_audio_level(chip, 0, i); - } - if (chip->nb_streams_capt) { - /* at boot time the digital volumes are unmuted 0dB */ - chip->digital_capture_volume[i] = - PCXHR_DIGITAL_ZERO_LEVEL; - chip->analog_capture_active = 1; -#ifdef CONFIG_SND_DEBUG - /* analog volumes for playback - * (is LEVEL_MIN after boot) - */ - if (chip->mgr->is_hr_stereo) - chip->analog_capture_volume[i] = - HR222_LINE_CAPTURE_ZERO_LEVEL; - else { - chip->analog_capture_volume[i] = - PCXHR_LINE_CAPTURE_ZERO_LEVEL; - pcxhr_update_analog_audio_level(chip, 1, i); - } -#endif - /* stereo cards need to be initialised after boot */ - if (chip->mgr->is_hr_stereo) - hr222_update_analog_audio_level(chip, 1, i); - } - } - - return; -} - - -int pcxhr_create_mixer(struct pcxhr_mgr *mgr) -{ - struct snd_pcxhr *chip; - int err, i; - - mutex_init(&mgr->mixer_mutex); /* can be in another place */ - - for (i = 0; i < mgr->num_cards; i++) { - struct snd_kcontrol_new temp; - chip = mgr->chip[i]; - - if (chip->nb_streams_play) { - /* analog output level control */ - temp = pcxhr_control_analog_level; - temp.name = "Master Playback Volume"; - temp.private_value = 0; /* playback */ - if (mgr->is_hr_stereo) - temp.tlv.p = db_scale_a_hr222_playback; - else - temp.tlv.p = db_scale_analog_playback; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&temp, chip)); - if (err < 0) - return err; - - /* output mute controls */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_output_switch, - chip)); - if (err < 0) - return err; - - temp = snd_pcxhr_pcm_vol; - temp.name = "PCM Playback Volume"; - temp.count = PCXHR_PLAYBACK_STREAMS; - temp.private_value = 0; /* playback */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&temp, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_pcm_switch, chip)); - if (err < 0) - return err; - - /* IEC958 controls */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_playback_iec958_mask, - chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_playback_iec958, - chip)); - if (err < 0) - return err; - } - if (chip->nb_streams_capt) { - /* analog input level control */ - temp = pcxhr_control_analog_level; - temp.name = "Line Capture Volume"; - temp.private_value = 1; /* capture */ - if (mgr->is_hr_stereo) - temp.tlv.p = db_scale_a_hr222_capture; - else - temp.tlv.p = db_scale_analog_capture; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&temp, chip)); - if (err < 0) - return err; - - temp = snd_pcxhr_pcm_vol; - temp.name = "PCM Capture Volume"; - temp.count = 1; - temp.private_value = 1; /* capture */ - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&temp, chip)); - if (err < 0) - return err; - - /* Audio source */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_audio_src, chip)); - if (err < 0) - return err; - - /* IEC958 controls */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_capture_iec958_mask, - chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_capture_iec958, - chip)); - if (err < 0) - return err; - - if (mgr->is_hr_stereo) { - err = hr222_add_mic_controls(chip); - if (err < 0) - return err; - } - } - /* monitoring only if playback and capture device available */ - if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) { - /* monitoring */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_monitor_vol, chip)); - if (err < 0) - return err; - - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_monitor_sw, chip)); - if (err < 0) - return err; - } - - if (i == 0) { - /* clock mode only one control per pcxhr */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_clock_type, mgr)); - if (err < 0) - return err; - /* non standard control used to scan - * the external clock presence/frequencies - */ - err = snd_ctl_add(chip->card, - snd_ctl_new1(&pcxhr_control_clock_rate, mgr)); - if (err < 0) - return err; - } - - /* init values for the mixer data */ - pcxhr_init_audio_levels(chip); - } - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.h b/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.h deleted file mode 100644 index 4348d0e5..00000000 --- a/ANDROID_3.4.5/sound/pci/pcxhr/pcxhr_mixer.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Driver for Digigram pcxhr compatible soundcards - * - * include file for mixer - * - * Copyright (c) 2004 by Digigram - * - * 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 - */ - -#ifndef __SOUND_PCXHR_MIXER_H -#define __SOUND_PCXHR_MIXER_H - -/* exported */ -int pcxhr_create_mixer(struct pcxhr_mgr *mgr); - -#endif /* __SOUND_PCXHR_MIXER_H */ diff --git a/ANDROID_3.4.5/sound/pci/riptide/Makefile b/ANDROID_3.4.5/sound/pci/riptide/Makefile deleted file mode 100644 index dcd2e64e..00000000 --- a/ANDROID_3.4.5/sound/pci/riptide/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -snd-riptide-objs := riptide.o - -obj-$(CONFIG_SND_RIPTIDE) += snd-riptide.o diff --git a/ANDROID_3.4.5/sound/pci/riptide/riptide.c b/ANDROID_3.4.5/sound/pci/riptide/riptide.c deleted file mode 100644 index 0481d94a..00000000 --- a/ANDROID_3.4.5/sound/pci/riptide/riptide.c +++ /dev/null @@ -1,2223 +0,0 @@ -/* - * Driver for the Conexant Riptide Soundchip - * - * Copyright (c) 2004 Peter Gruber - * - * 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 - * - */ -/* - History: - - 02/15/2004 first release - - This Driver is based on the OSS Driver version from Linuxant (riptide-0.6lnxtbeta03111100) - credits from the original files: - - MODULE NAME: cnxt_rt.h - AUTHOR: K. Lazarev (Transcribed by KNL) - HISTORY: Major Revision Date By - ----------------------------- -------- ----- - Created 02/1/2000 KNL - - MODULE NAME: int_mdl.c - AUTHOR: Konstantin Lazarev (Transcribed by KNL) - HISTORY: Major Revision Date By - ----------------------------- -------- ----- - Created 10/01/99 KNL - - MODULE NAME: riptide.h - AUTHOR: O. Druzhinin (Transcribed by OLD) - HISTORY: Major Revision Date By - ----------------------------- -------- ----- - Created 10/16/97 OLD - - MODULE NAME: Rp_Cmdif.cpp - AUTHOR: O. Druzhinin (Transcribed by OLD) - K. Lazarev (Transcribed by KNL) - HISTORY: Major Revision Date By - ----------------------------- -------- ----- - Adopted from NT4 driver 6/22/99 OLD - Ported to Linux 9/01/99 KNL - - MODULE NAME: rt_hw.c - AUTHOR: O. Druzhinin (Transcribed by OLD) - C. Lazarev (Transcribed by CNL) - HISTORY: Major Revision Date By - ----------------------------- -------- ----- - Created 11/18/97 OLD - Hardware functions for RipTide 11/24/97 CNL - (ES1) are coded - Hardware functions for RipTide 12/24/97 CNL - (A0) are coded - Hardware functions for RipTide 03/20/98 CNL - (A1) are coded - Boot loader is included 05/07/98 CNL - Redesigned for WDM 07/27/98 CNL - Redesigned for Linux 09/01/99 CNL - - MODULE NAME: rt_hw.h - AUTHOR: C. Lazarev (Transcribed by CNL) - HISTORY: Major Revision Date By - ----------------------------- -------- ----- - Created 11/18/97 CNL - - MODULE NAME: rt_mdl.c - AUTHOR: Konstantin Lazarev (Transcribed by KNL) - HISTORY: Major Revision Date By - ----------------------------- -------- ----- - Created 10/01/99 KNL - - MODULE NAME: mixer.h - AUTHOR: K. Kenney - HISTORY: Major Revision Date By - ----------------------------- -------- ----- - Created from MS W95 Sample 11/28/95 KRS - RipTide 10/15/97 KRS - Adopted for Windows NT driver 01/20/98 CNL -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - -MODULE_AUTHOR("Peter Gruber "); -MODULE_DESCRIPTION("riptide"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Conexant,Riptide}}"); -MODULE_FIRMWARE("riptide.hex"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; - -#ifdef SUPPORT_JOYSTICK -static int joystick_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x200 }; -#endif -static int mpu_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x330 }; -static int opl3_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x388 }; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Riptide soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Riptide soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Riptide soundcard."); -#ifdef SUPPORT_JOYSTICK -module_param_array(joystick_port, int, NULL, 0444); -MODULE_PARM_DESC(joystick_port, "Joystick port # for Riptide soundcard."); -#endif -module_param_array(mpu_port, int, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU401 port # for Riptide driver."); -module_param_array(opl3_port, int, NULL, 0444); -MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver."); - -/* - */ - -#define MPU401_HW_RIPTIDE MPU401_HW_MPU401 -#define OPL3_HW_RIPTIDE OPL3_HW_OPL3 - -#define PCI_EXT_CapId 0x40 -#define PCI_EXT_NextCapPrt 0x41 -#define PCI_EXT_PWMC 0x42 -#define PCI_EXT_PWSCR 0x44 -#define PCI_EXT_Data00 0x46 -#define PCI_EXT_PMSCR_BSE 0x47 -#define PCI_EXT_SB_Base 0x48 -#define PCI_EXT_FM_Base 0x4a -#define PCI_EXT_MPU_Base 0x4C -#define PCI_EXT_Game_Base 0x4E -#define PCI_EXT_Legacy_Mask 0x50 -#define PCI_EXT_AsicRev 0x52 -#define PCI_EXT_Reserved3 0x53 - -#define LEGACY_ENABLE_ALL 0x8000 /* legacy device options */ -#define LEGACY_ENABLE_SB 0x4000 -#define LEGACY_ENABLE_FM 0x2000 -#define LEGACY_ENABLE_MPU_INT 0x1000 -#define LEGACY_ENABLE_MPU 0x0800 -#define LEGACY_ENABLE_GAMEPORT 0x0400 - -#define MAX_WRITE_RETRY 10 /* cmd interface limits */ -#define MAX_ERROR_COUNT 10 -#define CMDIF_TIMEOUT 50000 -#define RESET_TRIES 5 - -#define READ_PORT_ULONG(p) inl((unsigned long)&(p)) -#define WRITE_PORT_ULONG(p,x) outl(x,(unsigned long)&(p)) - -#define READ_AUDIO_CONTROL(p) READ_PORT_ULONG(p->audio_control) -#define WRITE_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,x) -#define UMASK_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)|x) -#define MASK_AUDIO_CONTROL(p,x) WRITE_PORT_ULONG(p->audio_control,READ_PORT_ULONG(p->audio_control)&x) -#define READ_AUDIO_STATUS(p) READ_PORT_ULONG(p->audio_status) - -#define SET_GRESET(p) UMASK_AUDIO_CONTROL(p,0x0001) /* global reset switch */ -#define UNSET_GRESET(p) MASK_AUDIO_CONTROL(p,~0x0001) -#define SET_AIE(p) UMASK_AUDIO_CONTROL(p,0x0004) /* interrupt enable */ -#define UNSET_AIE(p) MASK_AUDIO_CONTROL(p,~0x0004) -#define SET_AIACK(p) UMASK_AUDIO_CONTROL(p,0x0008) /* interrupt acknowledge */ -#define UNSET_AIACKT(p) MASKAUDIO_CONTROL(p,~0x0008) -#define SET_ECMDAE(p) UMASK_AUDIO_CONTROL(p,0x0010) -#define UNSET_ECMDAE(p) MASK_AUDIO_CONTROL(p,~0x0010) -#define SET_ECMDBE(p) UMASK_AUDIO_CONTROL(p,0x0020) -#define UNSET_ECMDBE(p) MASK_AUDIO_CONTROL(p,~0x0020) -#define SET_EDATAF(p) UMASK_AUDIO_CONTROL(p,0x0040) -#define UNSET_EDATAF(p) MASK_AUDIO_CONTROL(p,~0x0040) -#define SET_EDATBF(p) UMASK_AUDIO_CONTROL(p,0x0080) -#define UNSET_EDATBF(p) MASK_AUDIO_CONTROL(p,~0x0080) -#define SET_ESBIRQON(p) UMASK_AUDIO_CONTROL(p,0x0100) -#define UNSET_ESBIRQON(p) MASK_AUDIO_CONTROL(p,~0x0100) -#define SET_EMPUIRQ(p) UMASK_AUDIO_CONTROL(p,0x0200) -#define UNSET_EMPUIRQ(p) MASK_AUDIO_CONTROL(p,~0x0200) -#define IS_CMDE(a) (READ_PORT_ULONG(a->stat)&0x1) /* cmd empty */ -#define IS_DATF(a) (READ_PORT_ULONG(a->stat)&0x2) /* data filled */ -#define IS_READY(p) (READ_AUDIO_STATUS(p)&0x0001) -#define IS_DLREADY(p) (READ_AUDIO_STATUS(p)&0x0002) -#define IS_DLERR(p) (READ_AUDIO_STATUS(p)&0x0004) -#define IS_GERR(p) (READ_AUDIO_STATUS(p)&0x0008) /* error ! */ -#define IS_CMDAEIRQ(p) (READ_AUDIO_STATUS(p)&0x0010) -#define IS_CMDBEIRQ(p) (READ_AUDIO_STATUS(p)&0x0020) -#define IS_DATAFIRQ(p) (READ_AUDIO_STATUS(p)&0x0040) -#define IS_DATBFIRQ(p) (READ_AUDIO_STATUS(p)&0x0080) -#define IS_EOBIRQ(p) (READ_AUDIO_STATUS(p)&0x0100) /* interrupt status */ -#define IS_EOSIRQ(p) (READ_AUDIO_STATUS(p)&0x0200) -#define IS_EOCIRQ(p) (READ_AUDIO_STATUS(p)&0x0400) -#define IS_UNSLIRQ(p) (READ_AUDIO_STATUS(p)&0x0800) -#define IS_SBIRQ(p) (READ_AUDIO_STATUS(p)&0x1000) -#define IS_MPUIRQ(p) (READ_AUDIO_STATUS(p)&0x2000) - -#define RESP 0x00000001 /* command flags */ -#define PARM 0x00000002 -#define CMDA 0x00000004 -#define CMDB 0x00000008 -#define NILL 0x00000000 - -#define LONG0(a) ((u32)a) /* shifts and masks */ -#define BYTE0(a) (LONG0(a)&0xff) -#define BYTE1(a) (BYTE0(a)<<8) -#define BYTE2(a) (BYTE0(a)<<16) -#define BYTE3(a) (BYTE0(a)<<24) -#define WORD0(a) (LONG0(a)&0xffff) -#define WORD1(a) (WORD0(a)<<8) -#define WORD2(a) (WORD0(a)<<16) -#define TRINIB0(a) (LONG0(a)&0xffffff) -#define TRINIB1(a) (TRINIB0(a)<<8) - -#define RET(a) ((union cmdret *)(a)) - -#define SEND_GETV(p,b) sendcmd(p,RESP,GETV,0,RET(b)) /* get version */ -#define SEND_GETC(p,b,c) sendcmd(p,PARM|RESP,GETC,c,RET(b)) -#define SEND_GUNS(p,b) sendcmd(p,RESP,GUNS,0,RET(b)) -#define SEND_SCID(p,b) sendcmd(p,RESP,SCID,0,RET(b)) -#define SEND_RMEM(p,b,c,d) sendcmd(p,PARM|RESP,RMEM|BYTE1(b),LONG0(c),RET(d)) /* memory access for firmware write */ -#define SEND_SMEM(p,b,c) sendcmd(p,PARM,SMEM|BYTE1(b),LONG0(c),RET(0)) /* memory access for firmware write */ -#define SEND_WMEM(p,b,c) sendcmd(p,PARM,WMEM|BYTE1(b),LONG0(c),RET(0)) /* memory access for firmware write */ -#define SEND_SDTM(p,b,c) sendcmd(p,PARM|RESP,SDTM|TRINIB1(b),0,RET(c)) /* memory access for firmware write */ -#define SEND_GOTO(p,b) sendcmd(p,PARM,GOTO,LONG0(b),RET(0)) /* memory access for firmware write */ -#define SEND_SETDPLL(p) sendcmd(p,0,ARM_SETDPLL,0,RET(0)) -#define SEND_SSTR(p,b,c) sendcmd(p,PARM,SSTR|BYTE3(b),LONG0(c),RET(0)) /* start stream */ -#define SEND_PSTR(p,b) sendcmd(p,PARM,PSTR,BYTE3(b),RET(0)) /* pause stream */ -#define SEND_KSTR(p,b) sendcmd(p,PARM,KSTR,BYTE3(b),RET(0)) /* stop stream */ -#define SEND_KDMA(p) sendcmd(p,0,KDMA,0,RET(0)) /* stop all dma */ -#define SEND_GPOS(p,b,c,d) sendcmd(p,PARM|RESP,GPOS,BYTE3(c)|BYTE2(b),RET(d)) /* get position in dma */ -#define SEND_SETF(p,b,c,d,e,f,g) sendcmd(p,PARM,SETF|WORD1(b)|BYTE3(c),d|BYTE1(e)|BYTE2(f)|BYTE3(g),RET(0)) /* set sample format at mixer */ -#define SEND_GSTS(p,b,c,d) sendcmd(p,PARM|RESP,GSTS,BYTE3(c)|BYTE2(b),RET(d)) -#define SEND_NGPOS(p,b,c,d) sendcmd(p,PARM|RESP,NGPOS,BYTE3(c)|BYTE2(b),RET(d)) -#define SEND_PSEL(p,b,c) sendcmd(p,PARM,PSEL,BYTE2(b)|BYTE3(c),RET(0)) /* activate lbus path */ -#define SEND_PCLR(p,b,c) sendcmd(p,PARM,PCLR,BYTE2(b)|BYTE3(c),RET(0)) /* deactivate lbus path */ -#define SEND_PLST(p,b) sendcmd(p,PARM,PLST,BYTE3(b),RET(0)) -#define SEND_RSSV(p,b,c,d) sendcmd(p,PARM|RESP,RSSV,BYTE2(b)|BYTE3(c),RET(d)) -#define SEND_LSEL(p,b,c,d,e,f,g,h) sendcmd(p,PARM,LSEL|BYTE1(b)|BYTE2(c)|BYTE3(d),BYTE0(e)|BYTE1(f)|BYTE2(g)|BYTE3(h),RET(0)) /* select paths for internal connections */ -#define SEND_SSRC(p,b,c,d,e) sendcmd(p,PARM,SSRC|BYTE1(b)|WORD2(c),WORD0(d)|WORD2(e),RET(0)) /* configure source */ -#define SEND_SLST(p,b) sendcmd(p,PARM,SLST,BYTE3(b),RET(0)) -#define SEND_RSRC(p,b,c) sendcmd(p,RESP,RSRC|BYTE1(b),0,RET(c)) /* read source config */ -#define SEND_SSRB(p,b,c) sendcmd(p,PARM,SSRB|BYTE1(b),WORD2(c),RET(0)) -#define SEND_SDGV(p,b,c,d,e) sendcmd(p,PARM,SDGV|BYTE2(b)|BYTE3(c),WORD0(d)|WORD2(e),RET(0)) /* set digital mixer */ -#define SEND_RDGV(p,b,c,d) sendcmd(p,PARM|RESP,RDGV|BYTE2(b)|BYTE3(c),0,RET(d)) /* read digital mixer */ -#define SEND_DLST(p,b) sendcmd(p,PARM,DLST,BYTE3(b),RET(0)) -#define SEND_SACR(p,b,c) sendcmd(p,PARM,SACR,WORD0(b)|WORD2(c),RET(0)) /* set AC97 register */ -#define SEND_RACR(p,b,c) sendcmd(p,PARM|RESP,RACR,WORD2(b),RET(c)) /* get AC97 register */ -#define SEND_ALST(p,b) sendcmd(p,PARM,ALST,BYTE3(b),RET(0)) -#define SEND_TXAC(p,b,c,d,e,f) sendcmd(p,PARM,TXAC|BYTE1(b)|WORD2(c),WORD0(d)|BYTE2(e)|BYTE3(f),RET(0)) -#define SEND_RXAC(p,b,c,d) sendcmd(p,PARM|RESP,RXAC,BYTE2(b)|BYTE3(c),RET(d)) -#define SEND_SI2S(p,b) sendcmd(p,PARM,SI2S,WORD2(b),RET(0)) - -#define EOB_STATUS 0x80000000 /* status flags : block boundary */ -#define EOS_STATUS 0x40000000 /* : stoppped */ -#define EOC_STATUS 0x20000000 /* : stream end */ -#define ERR_STATUS 0x10000000 -#define EMPTY_STATUS 0x08000000 - -#define IEOB_ENABLE 0x1 /* enable interrupts for status notification above */ -#define IEOS_ENABLE 0x2 -#define IEOC_ENABLE 0x4 -#define RDONCE 0x8 -#define DESC_MAX_MASK 0xff - -#define ST_PLAY 0x1 /* stream states */ -#define ST_STOP 0x2 -#define ST_PAUSE 0x4 - -#define I2S_INTDEC 3 /* config for I2S link */ -#define I2S_MERGER 0 -#define I2S_SPLITTER 0 -#define I2S_MIXER 7 -#define I2S_RATE 44100 - -#define MODEM_INTDEC 4 /* config for modem link */ -#define MODEM_MERGER 3 -#define MODEM_SPLITTER 0 -#define MODEM_MIXER 11 - -#define FM_INTDEC 3 /* config for FM/OPL3 link */ -#define FM_MERGER 0 -#define FM_SPLITTER 0 -#define FM_MIXER 9 - -#define SPLIT_PATH 0x80 /* path splitting flag */ - -enum FIRMWARE { - DATA_REC = 0, EXT_END_OF_FILE, EXT_SEG_ADDR_REC, EXT_GOTO_CMD_REC, - EXT_LIN_ADDR_REC, -}; - -enum CMDS { - GETV = 0x00, GETC, GUNS, SCID, RMEM = - 0x10, SMEM, WMEM, SDTM, GOTO, SSTR = - 0x20, PSTR, KSTR, KDMA, GPOS, SETF, GSTS, NGPOS, PSEL = - 0x30, PCLR, PLST, RSSV, LSEL, SSRC = 0x40, SLST, RSRC, SSRB, SDGV = - 0x50, RDGV, DLST, SACR = 0x60, RACR, ALST, TXAC, RXAC, SI2S = - 0x70, ARM_SETDPLL = 0x72, -}; - -enum E1SOURCE { - ARM2LBUS_FIFO0 = 0, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2, ARM2LBUS_FIFO3, - ARM2LBUS_FIFO4, ARM2LBUS_FIFO5, ARM2LBUS_FIFO6, ARM2LBUS_FIFO7, - ARM2LBUS_FIFO8, ARM2LBUS_FIFO9, ARM2LBUS_FIFO10, ARM2LBUS_FIFO11, - ARM2LBUS_FIFO12, ARM2LBUS_FIFO13, ARM2LBUS_FIFO14, ARM2LBUS_FIFO15, - INTER0_OUT, INTER1_OUT, INTER2_OUT, INTER3_OUT, INTER4_OUT, - INTERM0_OUT, INTERM1_OUT, INTERM2_OUT, INTERM3_OUT, INTERM4_OUT, - INTERM5_OUT, INTERM6_OUT, DECIMM0_OUT, DECIMM1_OUT, DECIMM2_OUT, - DECIMM3_OUT, DECIM0_OUT, SR3_4_OUT, OPL3_SAMPLE, ASRC0, ASRC1, - ACLNK2PADC, ACLNK2MODEM0RX, ACLNK2MIC, ACLNK2MODEM1RX, ACLNK2HNDMIC, - DIGITAL_MIXER_OUT0, GAINFUNC0_OUT, GAINFUNC1_OUT, GAINFUNC2_OUT, - GAINFUNC3_OUT, GAINFUNC4_OUT, SOFTMODEMTX, SPLITTER0_OUTL, - SPLITTER0_OUTR, SPLITTER1_OUTL, SPLITTER1_OUTR, SPLITTER2_OUTL, - SPLITTER2_OUTR, SPLITTER3_OUTL, SPLITTER3_OUTR, MERGER0_OUT, - MERGER1_OUT, MERGER2_OUT, MERGER3_OUT, ARM2LBUS_FIFO_DIRECT, NO_OUT -}; - -enum E2SINK { - LBUS2ARM_FIFO0 = 0, LBUS2ARM_FIFO1, LBUS2ARM_FIFO2, LBUS2ARM_FIFO3, - LBUS2ARM_FIFO4, LBUS2ARM_FIFO5, LBUS2ARM_FIFO6, LBUS2ARM_FIFO7, - INTER0_IN, INTER1_IN, INTER2_IN, INTER3_IN, INTER4_IN, INTERM0_IN, - INTERM1_IN, INTERM2_IN, INTERM3_IN, INTERM4_IN, INTERM5_IN, INTERM6_IN, - DECIMM0_IN, DECIMM1_IN, DECIMM2_IN, DECIMM3_IN, DECIM0_IN, SR3_4_IN, - PDAC2ACLNK, MODEM0TX2ACLNK, MODEM1TX2ACLNK, HNDSPK2ACLNK, - DIGITAL_MIXER_IN0, DIGITAL_MIXER_IN1, DIGITAL_MIXER_IN2, - DIGITAL_MIXER_IN3, DIGITAL_MIXER_IN4, DIGITAL_MIXER_IN5, - DIGITAL_MIXER_IN6, DIGITAL_MIXER_IN7, DIGITAL_MIXER_IN8, - DIGITAL_MIXER_IN9, DIGITAL_MIXER_IN10, DIGITAL_MIXER_IN11, - GAINFUNC0_IN, GAINFUNC1_IN, GAINFUNC2_IN, GAINFUNC3_IN, GAINFUNC4_IN, - SOFTMODEMRX, SPLITTER0_IN, SPLITTER1_IN, SPLITTER2_IN, SPLITTER3_IN, - MERGER0_INL, MERGER0_INR, MERGER1_INL, MERGER1_INR, MERGER2_INL, - MERGER2_INR, MERGER3_INL, MERGER3_INR, E2SINK_MAX -}; - -enum LBUS_SINK { - LS_SRC_INTERPOLATOR = 0, LS_SRC_INTERPOLATORM, LS_SRC_DECIMATOR, - LS_SRC_DECIMATORM, LS_MIXER_IN, LS_MIXER_GAIN_FUNCTION, - LS_SRC_SPLITTER, LS_SRC_MERGER, LS_NONE1, LS_NONE2, -}; - -enum RT_CHANNEL_IDS { - M0TX = 0, M1TX, TAMTX, HSSPKR, PDAC, DSNDTX0, DSNDTX1, DSNDTX2, - DSNDTX3, DSNDTX4, DSNDTX5, DSNDTX6, DSNDTX7, WVSTRTX, COP3DTX, SPARE, - M0RX, HSMIC, M1RX, CLEANRX, MICADC, PADC, COPRX1, COPRX2, - CHANNEL_ID_COUNTER -}; - -enum { SB_CMD = 0, MODEM_CMD, I2S_CMD0, I2S_CMD1, FM_CMD, MAX_CMD }; - -struct lbuspath { - unsigned char *noconv; - unsigned char *stereo; - unsigned char *mono; -}; - -struct cmdport { - u32 data1; /* cmd,param */ - u32 data2; /* param */ - u32 stat; /* status */ - u32 pad[5]; -}; - -struct riptideport { - u32 audio_control; /* status registers */ - u32 audio_status; - u32 pad[2]; - struct cmdport port[2]; /* command ports */ -}; - -struct cmdif { - struct riptideport *hwport; - spinlock_t lock; - unsigned int cmdcnt; /* cmd statistics */ - unsigned int cmdtime; - unsigned int cmdtimemax; - unsigned int cmdtimemin; - unsigned int errcnt; - int is_reset; -}; - -struct riptide_firmware { - u16 ASIC; - u16 CODEC; - u16 AUXDSP; - u16 PROG; -}; - -union cmdret { - u8 retbytes[8]; - u16 retwords[4]; - u32 retlongs[2]; -}; - -union firmware_version { - union cmdret ret; - struct riptide_firmware firmware; -}; - -#define get_pcmhwdev(substream) (struct pcmhw *)(substream->runtime->private_data) - -#define PLAYBACK_SUBSTREAMS 3 -struct snd_riptide { - struct snd_card *card; - struct pci_dev *pci; - const struct firmware *fw_entry; - - struct cmdif *cif; - - struct snd_pcm *pcm; - struct snd_pcm *pcm_i2s; - struct snd_rawmidi *rmidi; - struct snd_opl3 *opl3; - struct snd_ac97 *ac97; - struct snd_ac97_bus *ac97_bus; - - struct snd_pcm_substream *playback_substream[PLAYBACK_SUBSTREAMS]; - struct snd_pcm_substream *capture_substream; - - int openstreams; - - int irq; - unsigned long port; - unsigned short mpuaddr; - unsigned short opladdr; -#ifdef SUPPORT_JOYSTICK - unsigned short gameaddr; -#endif - struct resource *res_port; - - unsigned short device_id; - - union firmware_version firmware; - - spinlock_t lock; - struct tasklet_struct riptide_tq; - struct snd_info_entry *proc_entry; - - unsigned long received_irqs; - unsigned long handled_irqs; -#ifdef CONFIG_PM - int in_suspend; -#endif -}; - -struct sgd { /* scatter gather desriptor */ - u32 dwNextLink; - u32 dwSegPtrPhys; - u32 dwSegLen; - u32 dwStat_Ctl; -}; - -struct pcmhw { /* pcm descriptor */ - struct lbuspath paths; - unsigned char *lbuspath; - unsigned char source; - unsigned char intdec[2]; - unsigned char mixer; - unsigned char id; - unsigned char state; - unsigned int rate; - unsigned int channels; - snd_pcm_format_t format; - struct snd_dma_buffer sgdlist; - struct sgd *sgdbuf; - unsigned int size; - unsigned int pages; - unsigned int oldpos; - unsigned int pointer; -}; - -#define CMDRET_ZERO (union cmdret){{(u32)0, (u32) 0}} - -static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, - union cmdret *ret); -static int getsourcesink(struct cmdif *cif, unsigned char source, - unsigned char sink, unsigned char *a, - unsigned char *b); -static int snd_riptide_initialize(struct snd_riptide *chip); -static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip); - -/* - */ - -static DEFINE_PCI_DEVICE_TABLE(snd_riptide_ids) = { - { PCI_DEVICE(0x127a, 0x4310) }, - { PCI_DEVICE(0x127a, 0x4320) }, - { PCI_DEVICE(0x127a, 0x4330) }, - { PCI_DEVICE(0x127a, 0x4340) }, - {0,}, -}; - -#ifdef SUPPORT_JOYSTICK -static DEFINE_PCI_DEVICE_TABLE(snd_riptide_joystick_ids) = { - { PCI_DEVICE(0x127a, 0x4312) }, - { PCI_DEVICE(0x127a, 0x4322) }, - { PCI_DEVICE(0x127a, 0x4332) }, - { PCI_DEVICE(0x127a, 0x4342) }, - {0,}, -}; -#endif - -MODULE_DEVICE_TABLE(pci, snd_riptide_ids); - -/* - */ - -static unsigned char lbusin2out[E2SINK_MAX + 1][2] = { - {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT, - LS_NONE2}, - {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT, - LS_NONE2}, - {INTER0_OUT, LS_SRC_INTERPOLATOR}, {INTER1_OUT, LS_SRC_INTERPOLATOR}, - {INTER2_OUT, LS_SRC_INTERPOLATOR}, {INTER3_OUT, LS_SRC_INTERPOLATOR}, - {INTER4_OUT, LS_SRC_INTERPOLATOR}, {INTERM0_OUT, LS_SRC_INTERPOLATORM}, - {INTERM1_OUT, LS_SRC_INTERPOLATORM}, {INTERM2_OUT, - LS_SRC_INTERPOLATORM}, - {INTERM3_OUT, LS_SRC_INTERPOLATORM}, {INTERM4_OUT, - LS_SRC_INTERPOLATORM}, - {INTERM5_OUT, LS_SRC_INTERPOLATORM}, {INTERM6_OUT, - LS_SRC_INTERPOLATORM}, - {DECIMM0_OUT, LS_SRC_DECIMATORM}, {DECIMM1_OUT, LS_SRC_DECIMATORM}, - {DECIMM2_OUT, LS_SRC_DECIMATORM}, {DECIMM3_OUT, LS_SRC_DECIMATORM}, - {DECIM0_OUT, LS_SRC_DECIMATOR}, {SR3_4_OUT, LS_NONE1}, {NO_OUT, - LS_NONE2}, - {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, - {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, - {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, - {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, - {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, - {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, - {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, {DIGITAL_MIXER_OUT0, LS_MIXER_IN}, - {GAINFUNC0_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC1_OUT, - LS_MIXER_GAIN_FUNCTION}, - {GAINFUNC2_OUT, LS_MIXER_GAIN_FUNCTION}, {GAINFUNC3_OUT, - LS_MIXER_GAIN_FUNCTION}, - {GAINFUNC4_OUT, LS_MIXER_GAIN_FUNCTION}, {SOFTMODEMTX, LS_NONE1}, - {SPLITTER0_OUTL, LS_SRC_SPLITTER}, {SPLITTER1_OUTL, LS_SRC_SPLITTER}, - {SPLITTER2_OUTL, LS_SRC_SPLITTER}, {SPLITTER3_OUTL, LS_SRC_SPLITTER}, - {MERGER0_OUT, LS_SRC_MERGER}, {MERGER0_OUT, LS_SRC_MERGER}, - {MERGER1_OUT, LS_SRC_MERGER}, - {MERGER1_OUT, LS_SRC_MERGER}, {MERGER2_OUT, LS_SRC_MERGER}, - {MERGER2_OUT, LS_SRC_MERGER}, - {MERGER3_OUT, LS_SRC_MERGER}, {MERGER3_OUT, LS_SRC_MERGER}, {NO_OUT, - LS_NONE2}, -}; - -static unsigned char lbus_play_opl3[] = { - DIGITAL_MIXER_IN0 + FM_MIXER, 0xff -}; -static unsigned char lbus_play_modem[] = { - DIGITAL_MIXER_IN0 + MODEM_MIXER, 0xff -}; -static unsigned char lbus_play_i2s[] = { - INTER0_IN + I2S_INTDEC, DIGITAL_MIXER_IN0 + I2S_MIXER, 0xff -}; -static unsigned char lbus_play_out[] = { - PDAC2ACLNK, 0xff -}; -static unsigned char lbus_play_outhp[] = { - HNDSPK2ACLNK, 0xff -}; -static unsigned char lbus_play_noconv1[] = { - DIGITAL_MIXER_IN0, 0xff -}; -static unsigned char lbus_play_stereo1[] = { - INTER0_IN, DIGITAL_MIXER_IN0, 0xff -}; -static unsigned char lbus_play_mono1[] = { - INTERM0_IN, DIGITAL_MIXER_IN0, 0xff -}; -static unsigned char lbus_play_noconv2[] = { - DIGITAL_MIXER_IN1, 0xff -}; -static unsigned char lbus_play_stereo2[] = { - INTER1_IN, DIGITAL_MIXER_IN1, 0xff -}; -static unsigned char lbus_play_mono2[] = { - INTERM1_IN, DIGITAL_MIXER_IN1, 0xff -}; -static unsigned char lbus_play_noconv3[] = { - DIGITAL_MIXER_IN2, 0xff -}; -static unsigned char lbus_play_stereo3[] = { - INTER2_IN, DIGITAL_MIXER_IN2, 0xff -}; -static unsigned char lbus_play_mono3[] = { - INTERM2_IN, DIGITAL_MIXER_IN2, 0xff -}; -static unsigned char lbus_rec_noconv1[] = { - LBUS2ARM_FIFO5, 0xff -}; -static unsigned char lbus_rec_stereo1[] = { - DECIM0_IN, LBUS2ARM_FIFO5, 0xff -}; -static unsigned char lbus_rec_mono1[] = { - DECIMM3_IN, LBUS2ARM_FIFO5, 0xff -}; - -static unsigned char play_ids[] = { 4, 1, 2, }; -static unsigned char play_sources[] = { - ARM2LBUS_FIFO4, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2, -}; -static struct lbuspath lbus_play_paths[] = { - { - .noconv = lbus_play_noconv1, - .stereo = lbus_play_stereo1, - .mono = lbus_play_mono1, - }, - { - .noconv = lbus_play_noconv2, - .stereo = lbus_play_stereo2, - .mono = lbus_play_mono2, - }, - { - .noconv = lbus_play_noconv3, - .stereo = lbus_play_stereo3, - .mono = lbus_play_mono3, - }, -}; -static struct lbuspath lbus_rec_path = { - .noconv = lbus_rec_noconv1, - .stereo = lbus_rec_stereo1, - .mono = lbus_rec_mono1, -}; - -#define FIRMWARE_VERSIONS 1 -static union firmware_version firmware_versions[] = { - { - .firmware = { - .ASIC = 3, - .CODEC = 2, - .AUXDSP = 3, - .PROG = 773, - }, - }, -}; - -static u32 atoh(const unsigned char *in, unsigned int len) -{ - u32 sum = 0; - unsigned int mult = 1; - unsigned char c; - - while (len) { - int value; - - c = in[len - 1]; - value = hex_to_bin(c); - if (value >= 0) - sum += mult * value; - mult *= 16; - --len; - } - return sum; -} - -static int senddata(struct cmdif *cif, const unsigned char *in, u32 offset) -{ - u32 addr; - u32 data; - u32 i; - const unsigned char *p; - - i = atoh(&in[1], 2); - addr = offset + atoh(&in[3], 4); - if (SEND_SMEM(cif, 0, addr) != 0) - return -EACCES; - p = in + 9; - while (i) { - data = atoh(p, 8); - if (SEND_WMEM(cif, 2, - ((data & 0x0f0f0f0f) << 4) | ((data & 0xf0f0f0f0) - >> 4))) - return -EACCES; - i -= 4; - p += 8; - } - return 0; -} - -static int loadfirmware(struct cmdif *cif, const unsigned char *img, - unsigned int size) -{ - const unsigned char *in; - u32 laddr, saddr, t, val; - int err = 0; - - laddr = saddr = 0; - while (size > 0 && err == 0) { - in = img; - if (in[0] == ':') { - t = atoh(&in[7], 2); - switch (t) { - case DATA_REC: - err = senddata(cif, in, laddr + saddr); - break; - case EXT_SEG_ADDR_REC: - saddr = atoh(&in[9], 4) << 4; - break; - case EXT_LIN_ADDR_REC: - laddr = atoh(&in[9], 4) << 16; - break; - case EXT_GOTO_CMD_REC: - val = atoh(&in[9], 8); - if (SEND_GOTO(cif, val) != 0) - err = -EACCES; - break; - case EXT_END_OF_FILE: - size = 0; - break; - default: - break; - } - while (size > 0) { - size--; - if (*img++ == '\n') - break; - } - } - } - snd_printdd("load firmware return %d\n", err); - return err; -} - -static void -alloclbuspath(struct cmdif *cif, unsigned char source, - unsigned char *path, unsigned char *mixer, unsigned char *s) -{ - while (*path != 0xff) { - unsigned char sink, type; - - sink = *path & (~SPLIT_PATH); - if (sink != E2SINK_MAX) { - snd_printdd("alloc path 0x%x->0x%x\n", source, sink); - SEND_PSEL(cif, source, sink); - source = lbusin2out[sink][0]; - type = lbusin2out[sink][1]; - if (type == LS_MIXER_IN) { - if (mixer) - *mixer = sink - DIGITAL_MIXER_IN0; - } - if (type == LS_SRC_DECIMATORM || - type == LS_SRC_DECIMATOR || - type == LS_SRC_INTERPOLATORM || - type == LS_SRC_INTERPOLATOR) { - if (s) { - if (s[0] != 0xff) - s[1] = sink; - else - s[0] = sink; - } - } - } - if (*path++ & SPLIT_PATH) { - unsigned char *npath = path; - - while (*npath != 0xff) - npath++; - alloclbuspath(cif, source + 1, ++npath, mixer, s); - } - } -} - -static void -freelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path) -{ - while (*path != 0xff) { - unsigned char sink; - - sink = *path & (~SPLIT_PATH); - if (sink != E2SINK_MAX) { - snd_printdd("free path 0x%x->0x%x\n", source, sink); - SEND_PCLR(cif, source, sink); - source = lbusin2out[sink][0]; - } - if (*path++ & SPLIT_PATH) { - unsigned char *npath = path; - - while (*npath != 0xff) - npath++; - freelbuspath(cif, source + 1, ++npath); - } - } -} - -static int writearm(struct cmdif *cif, u32 addr, u32 data, u32 mask) -{ - union cmdret rptr = CMDRET_ZERO; - unsigned int i = MAX_WRITE_RETRY; - int flag = 1; - - SEND_RMEM(cif, 0x02, addr, &rptr); - rptr.retlongs[0] &= (~mask); - - while (--i) { - SEND_SMEM(cif, 0x01, addr); - SEND_WMEM(cif, 0x02, (rptr.retlongs[0] | data)); - SEND_RMEM(cif, 0x02, addr, &rptr); - if ((rptr.retlongs[0] & data) == data) { - flag = 0; - break; - } else - rptr.retlongs[0] &= ~mask; - } - snd_printdd("send arm 0x%x 0x%x 0x%x return %d\n", addr, data, mask, - flag); - return flag; -} - -static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm, - union cmdret *ret) -{ - int i, j; - int err; - unsigned int time = 0; - unsigned long irqflags; - struct riptideport *hwport; - struct cmdport *cmdport = NULL; - - if (snd_BUG_ON(!cif)) - return -EINVAL; - - hwport = cif->hwport; - if (cif->errcnt > MAX_ERROR_COUNT) { - if (cif->is_reset) { - snd_printk(KERN_ERR - "Riptide: Too many failed cmds, reinitializing\n"); - if (riptide_reset(cif, NULL) == 0) { - cif->errcnt = 0; - return -EIO; - } - } - snd_printk(KERN_ERR "Riptide: Initialization failed.\n"); - return -EINVAL; - } - if (ret) { - ret->retlongs[0] = 0; - ret->retlongs[1] = 0; - } - i = 0; - spin_lock_irqsave(&cif->lock, irqflags); - while (i++ < CMDIF_TIMEOUT && !IS_READY(cif->hwport)) - udelay(10); - if (i > CMDIF_TIMEOUT) { - err = -EBUSY; - goto errout; - } - - err = 0; - for (j = 0, time = 0; time < CMDIF_TIMEOUT; j++, time += 2) { - cmdport = &(hwport->port[j % 2]); - if (IS_DATF(cmdport)) { /* free pending data */ - READ_PORT_ULONG(cmdport->data1); - READ_PORT_ULONG(cmdport->data2); - } - if (IS_CMDE(cmdport)) { - if (flags & PARM) /* put data */ - WRITE_PORT_ULONG(cmdport->data2, parm); - WRITE_PORT_ULONG(cmdport->data1, cmd); /* write cmd */ - if ((flags & RESP) && ret) { - while (!IS_DATF(cmdport) && - time < CMDIF_TIMEOUT) { - udelay(10); - time++; - } - if (time < CMDIF_TIMEOUT) { /* read response */ - ret->retlongs[0] = - READ_PORT_ULONG(cmdport->data1); - ret->retlongs[1] = - READ_PORT_ULONG(cmdport->data2); - } else { - err = -ENOSYS; - goto errout; - } - } - break; - } - udelay(20); - } - if (time == CMDIF_TIMEOUT) { - err = -ENODATA; - goto errout; - } - spin_unlock_irqrestore(&cif->lock, irqflags); - - cif->cmdcnt++; /* update command statistics */ - cif->cmdtime += time; - if (time > cif->cmdtimemax) - cif->cmdtimemax = time; - if (time < cif->cmdtimemin) - cif->cmdtimemin = time; - if ((cif->cmdcnt) % 1000 == 0) - snd_printdd - ("send cmd %d time: %d mintime: %d maxtime %d err: %d\n", - cif->cmdcnt, cif->cmdtime, cif->cmdtimemin, - cif->cmdtimemax, cif->errcnt); - return 0; - - errout: - cif->errcnt++; - spin_unlock_irqrestore(&cif->lock, irqflags); - snd_printdd - ("send cmd %d hw: 0x%x flag: 0x%x cmd: 0x%x parm: 0x%x ret: 0x%x 0x%x CMDE: %d DATF: %d failed %d\n", - cif->cmdcnt, (int)((void *)&(cmdport->stat) - (void *)hwport), - flags, cmd, parm, ret ? ret->retlongs[0] : 0, - ret ? ret->retlongs[1] : 0, IS_CMDE(cmdport), IS_DATF(cmdport), - err); - return err; -} - -static int -setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval) -{ - union cmdret rptr = CMDRET_ZERO; - int i = 0; - - snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval); - do { - SEND_SDGV(cif, num, num, rval, lval); - SEND_RDGV(cif, num, num, &rptr); - if (rptr.retwords[0] == lval && rptr.retwords[1] == rval) - return 0; - } while (i++ < MAX_WRITE_RETRY); - snd_printdd("sent mixer failed\n"); - return -EIO; -} - -static int getpaths(struct cmdif *cif, unsigned char *o) -{ - unsigned char src[E2SINK_MAX]; - unsigned char sink[E2SINK_MAX]; - int i, j = 0; - - for (i = 0; i < E2SINK_MAX; i++) { - getsourcesink(cif, i, i, &src[i], &sink[i]); - if (sink[i] < E2SINK_MAX) { - o[j++] = sink[i]; - o[j++] = i; - } - } - return j; -} - -static int -getsourcesink(struct cmdif *cif, unsigned char source, unsigned char sink, - unsigned char *a, unsigned char *b) -{ - union cmdret rptr = CMDRET_ZERO; - - if (SEND_RSSV(cif, source, sink, &rptr) && - SEND_RSSV(cif, source, sink, &rptr)) - return -EIO; - *a = rptr.retbytes[0]; - *b = rptr.retbytes[1]; - snd_printdd("getsourcesink 0x%x 0x%x\n", *a, *b); - return 0; -} - -static int -getsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int *rate) -{ - unsigned char *s; - unsigned int p[2] = { 0, 0 }; - int i; - union cmdret rptr = CMDRET_ZERO; - - s = intdec; - for (i = 0; i < 2; i++) { - if (*s != 0xff) { - if (SEND_RSRC(cif, *s, &rptr) && - SEND_RSRC(cif, *s, &rptr)) - return -EIO; - p[i] += rptr.retwords[1]; - p[i] *= rptr.retwords[2]; - p[i] += rptr.retwords[3]; - p[i] /= 65536; - } - s++; - } - if (p[0]) { - if (p[1] != p[0]) - snd_printdd("rates differ %d %d\n", p[0], p[1]); - *rate = (unsigned int)p[0]; - } else - *rate = (unsigned int)p[1]; - snd_printdd("getsampleformat %d %d %d\n", intdec[0], intdec[1], *rate); - return 0; -} - -static int -setsampleformat(struct cmdif *cif, - unsigned char mixer, unsigned char id, - unsigned char channels, unsigned char format) -{ - unsigned char w, ch, sig, order; - - snd_printdd - ("setsampleformat mixer: %d id: %d channels: %d format: %d\n", - mixer, id, channels, format); - ch = channels == 1; - w = snd_pcm_format_width(format) == 8; - sig = snd_pcm_format_unsigned(format) != 0; - order = snd_pcm_format_big_endian(format) != 0; - - if (SEND_SETF(cif, mixer, w, ch, order, sig, id) && - SEND_SETF(cif, mixer, w, ch, order, sig, id)) { - snd_printdd("setsampleformat failed\n"); - return -EIO; - } - return 0; -} - -static int -setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate) -{ - u32 D, M, N; - union cmdret rptr = CMDRET_ZERO; - int i; - - snd_printdd("setsamplerate intdec: %d,%d rate: %d\n", intdec[0], - intdec[1], rate); - D = 48000; - M = ((rate == 48000) ? 47999 : rate) * 65536; - N = M % D; - M /= D; - for (i = 0; i < 2; i++) { - if (*intdec != 0xff) { - do { - SEND_SSRC(cif, *intdec, D, M, N); - SEND_RSRC(cif, *intdec, &rptr); - } while (rptr.retwords[1] != D && - rptr.retwords[2] != M && - rptr.retwords[3] != N && - i++ < MAX_WRITE_RETRY); - if (i > MAX_WRITE_RETRY) { - snd_printdd("sent samplerate %d: %d failed\n", - *intdec, rate); - return -EIO; - } - } - intdec++; - } - return 0; -} - -static int -getmixer(struct cmdif *cif, short num, unsigned short *rval, - unsigned short *lval) -{ - union cmdret rptr = CMDRET_ZERO; - - if (SEND_RDGV(cif, num, num, &rptr) && SEND_RDGV(cif, num, num, &rptr)) - return -EIO; - *rval = rptr.retwords[0]; - *lval = rptr.retwords[1]; - snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval); - return 0; -} - -static void riptide_handleirq(unsigned long dev_id) -{ - struct snd_riptide *chip = (void *)dev_id; - struct cmdif *cif = chip->cif; - struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1]; - struct snd_pcm_runtime *runtime; - struct pcmhw *data = NULL; - unsigned int pos, period_bytes; - struct sgd *c; - int i, j; - unsigned int flag; - - if (!cif) - return; - - for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) - substream[i] = chip->playback_substream[i]; - substream[i] = chip->capture_substream; - for (i = 0; i < PLAYBACK_SUBSTREAMS + 1; i++) { - if (substream[i] && - (runtime = substream[i]->runtime) && - (data = runtime->private_data) && data->state != ST_STOP) { - pos = 0; - for (j = 0; j < data->pages; j++) { - c = &data->sgdbuf[j]; - flag = le32_to_cpu(c->dwStat_Ctl); - if (flag & EOB_STATUS) - pos += le32_to_cpu(c->dwSegLen); - if (flag & EOC_STATUS) - pos += le32_to_cpu(c->dwSegLen); - if ((flag & EOS_STATUS) - && (data->state == ST_PLAY)) { - data->state = ST_STOP; - snd_printk(KERN_ERR - "Riptide: DMA stopped unexpectedly\n"); - } - c->dwStat_Ctl = - cpu_to_le32(flag & - ~(EOS_STATUS | EOB_STATUS | - EOC_STATUS)); - } - data->pointer += pos; - pos += data->oldpos; - if (data->state != ST_STOP) { - period_bytes = - frames_to_bytes(runtime, - runtime->period_size); - snd_printdd - ("interrupt 0x%x after 0x%lx of 0x%lx frames in period\n", - READ_AUDIO_STATUS(cif->hwport), - bytes_to_frames(runtime, pos), - runtime->period_size); - j = 0; - if (pos >= period_bytes) { - j++; - while (pos >= period_bytes) - pos -= period_bytes; - } - data->oldpos = pos; - if (j > 0) - snd_pcm_period_elapsed(substream[i]); - } - } - } -} - -#ifdef CONFIG_PM -static int riptide_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_riptide *chip = card->private_data; - - chip->in_suspend = 1; - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_ac97_suspend(chip->ac97); - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int riptide_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_riptide *chip = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "riptide: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - snd_riptide_initialize(chip); - snd_ac97_resume(chip->ac97); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - chip->in_suspend = 0; - return 0; -} -#endif - -static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) -{ - union firmware_version firmware = { .ret = CMDRET_ZERO }; - int i, timeout, err; - - for (i = 0; i < 2; i++) { - WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0); - WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0); - } - SET_GRESET(cif->hwport); - udelay(100); - UNSET_GRESET(cif->hwport); - udelay(100); - - for (timeout = 100000; --timeout; udelay(10)) { - if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport)) - break; - } - if (!timeout) { - snd_printk(KERN_ERR - "Riptide: device not ready, audio status: 0x%x " - "ready: %d gerr: %d\n", - READ_AUDIO_STATUS(cif->hwport), - IS_READY(cif->hwport), IS_GERR(cif->hwport)); - return -EIO; - } else { - snd_printdd - ("Riptide: audio status: 0x%x ready: %d gerr: %d\n", - READ_AUDIO_STATUS(cif->hwport), - IS_READY(cif->hwport), IS_GERR(cif->hwport)); - } - - SEND_GETV(cif, &firmware.ret); - snd_printdd("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n", - firmware.firmware.ASIC, firmware.firmware.CODEC, - firmware.firmware.AUXDSP, firmware.firmware.PROG); - - if (!chip) - return 1; - - for (i = 0; i < FIRMWARE_VERSIONS; i++) { - if (!memcmp(&firmware_versions[i], &firmware, sizeof(firmware))) - return 1; /* OK */ - - } - - snd_printdd("Writing Firmware\n"); - if (!chip->fw_entry) { - err = request_firmware(&chip->fw_entry, "riptide.hex", - &chip->pci->dev); - if (err) { - snd_printk(KERN_ERR - "Riptide: Firmware not available %d\n", err); - return -EIO; - } - } - err = loadfirmware(cif, chip->fw_entry->data, chip->fw_entry->size); - if (err) { - snd_printk(KERN_ERR - "Riptide: Could not load firmware %d\n", err); - return err; - } - - chip->firmware = firmware; - - return 1; /* OK */ -} - -static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip) -{ - union cmdret rptr = CMDRET_ZERO; - int err, tries; - - if (!cif) - return -EINVAL; - - cif->cmdcnt = 0; - cif->cmdtime = 0; - cif->cmdtimemax = 0; - cif->cmdtimemin = 0xffffffff; - cif->errcnt = 0; - cif->is_reset = 0; - - tries = RESET_TRIES; - do { - err = try_to_load_firmware(cif, chip); - if (err < 0) - return err; - } while (!err && --tries); - - SEND_SACR(cif, 0, AC97_RESET); - SEND_RACR(cif, AC97_RESET, &rptr); - snd_printdd("AC97: 0x%x 0x%x\n", rptr.retlongs[0], rptr.retlongs[1]); - - SEND_PLST(cif, 0); - SEND_SLST(cif, 0); - SEND_DLST(cif, 0); - SEND_ALST(cif, 0); - SEND_KDMA(cif); - - writearm(cif, 0x301F8, 1, 1); - writearm(cif, 0x301F4, 1, 1); - - SEND_LSEL(cif, MODEM_CMD, 0, 0, MODEM_INTDEC, MODEM_MERGER, - MODEM_SPLITTER, MODEM_MIXER); - setmixer(cif, MODEM_MIXER, 0x7fff, 0x7fff); - alloclbuspath(cif, ARM2LBUS_FIFO13, lbus_play_modem, NULL, NULL); - - SEND_LSEL(cif, FM_CMD, 0, 0, FM_INTDEC, FM_MERGER, FM_SPLITTER, - FM_MIXER); - setmixer(cif, FM_MIXER, 0x7fff, 0x7fff); - writearm(cif, 0x30648 + FM_MIXER * 4, 0x01, 0x00000005); - writearm(cif, 0x301A8, 0x02, 0x00000002); - writearm(cif, 0x30264, 0x08, 0xffffffff); - alloclbuspath(cif, OPL3_SAMPLE, lbus_play_opl3, NULL, NULL); - - SEND_SSRC(cif, I2S_INTDEC, 48000, - ((u32) I2S_RATE * 65536) / 48000, - ((u32) I2S_RATE * 65536) % 48000); - SEND_LSEL(cif, I2S_CMD0, 0, 0, I2S_INTDEC, I2S_MERGER, I2S_SPLITTER, - I2S_MIXER); - SEND_SI2S(cif, 1); - alloclbuspath(cif, ARM2LBUS_FIFO0, lbus_play_i2s, NULL, NULL); - alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_out, NULL, NULL); - alloclbuspath(cif, DIGITAL_MIXER_OUT0, lbus_play_outhp, NULL, NULL); - - SET_AIACK(cif->hwport); - SET_AIE(cif->hwport); - SET_AIACK(cif->hwport); - cif->is_reset = 1; - - return 0; -} - -static struct snd_pcm_hardware snd_riptide_playback = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID), - .formats = - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 - | SNDRV_PCM_FMTBIT_U16_LE, - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5500, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (64 * 1024), - .period_bytes_min = PAGE_SIZE >> 1, - .period_bytes_max = PAGE_SIZE << 8, - .periods_min = 2, - .periods_max = 64, - .fifo_size = 0, -}; -static struct snd_pcm_hardware snd_riptide_capture = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID), - .formats = - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 - | SNDRV_PCM_FMTBIT_U16_LE, - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5500, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (64 * 1024), - .period_bytes_min = PAGE_SIZE >> 1, - .period_bytes_max = PAGE_SIZE << 3, - .periods_min = 2, - .periods_max = 64, - .fifo_size = 0, -}; - -static snd_pcm_uframes_t snd_riptide_pointer(struct snd_pcm_substream - *substream) -{ - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct pcmhw *data = get_pcmhwdev(substream); - struct cmdif *cif = chip->cif; - union cmdret rptr = CMDRET_ZERO; - snd_pcm_uframes_t ret; - - SEND_GPOS(cif, 0, data->id, &rptr); - if (data->size && runtime->period_size) { - snd_printdd - ("pointer stream %d position 0x%x(0x%x in buffer) bytes 0x%lx(0x%lx in period) frames\n", - data->id, rptr.retlongs[1], rptr.retlongs[1] % data->size, - bytes_to_frames(runtime, rptr.retlongs[1]), - bytes_to_frames(runtime, - rptr.retlongs[1]) % runtime->period_size); - if (rptr.retlongs[1] > data->pointer) - ret = - bytes_to_frames(runtime, - rptr.retlongs[1] % data->size); - else - ret = - bytes_to_frames(runtime, - data->pointer % data->size); - } else { - snd_printdd("stream not started or strange parms (%d %ld)\n", - data->size, runtime->period_size); - ret = bytes_to_frames(runtime, 0); - } - return ret; -} - -static int snd_riptide_trigger(struct snd_pcm_substream *substream, int cmd) -{ - int i, j; - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct pcmhw *data = get_pcmhwdev(substream); - struct cmdif *cif = chip->cif; - union cmdret rptr = CMDRET_ZERO; - - spin_lock(&chip->lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (!(data->state & ST_PLAY)) { - SEND_SSTR(cif, data->id, data->sgdlist.addr); - SET_AIE(cif->hwport); - data->state = ST_PLAY; - if (data->mixer != 0xff) - setmixer(cif, data->mixer, 0x7fff, 0x7fff); - chip->openstreams++; - data->oldpos = 0; - data->pointer = 0; - } - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (data->mixer != 0xff) - setmixer(cif, data->mixer, 0, 0); - setmixer(cif, data->mixer, 0, 0); - SEND_KSTR(cif, data->id); - data->state = ST_STOP; - chip->openstreams--; - j = 0; - do { - i = rptr.retlongs[1]; - SEND_GPOS(cif, 0, data->id, &rptr); - udelay(1); - } while (i != rptr.retlongs[1] && j++ < MAX_WRITE_RETRY); - if (j > MAX_WRITE_RETRY) - snd_printk(KERN_ERR "Riptide: Could not stop stream!"); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (!(data->state & ST_PAUSE)) { - SEND_PSTR(cif, data->id); - data->state |= ST_PAUSE; - chip->openstreams--; - } - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (data->state & ST_PAUSE) { - SEND_SSTR(cif, data->id, data->sgdlist.addr); - data->state &= ~ST_PAUSE; - chip->openstreams++; - } - break; - default: - spin_unlock(&chip->lock); - return -EINVAL; - } - spin_unlock(&chip->lock); - return 0; -} - -static int snd_riptide_prepare(struct snd_pcm_substream *substream) -{ - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct pcmhw *data = get_pcmhwdev(substream); - struct cmdif *cif = chip->cif; - unsigned char *lbuspath = NULL; - unsigned int rate, channels; - int err = 0; - snd_pcm_format_t format; - - if (snd_BUG_ON(!cif || !data)) - return -EINVAL; - - snd_printdd("prepare id %d ch: %d f:0x%x r:%d\n", data->id, - runtime->channels, runtime->format, runtime->rate); - - spin_lock_irq(&chip->lock); - channels = runtime->channels; - format = runtime->format; - rate = runtime->rate; - switch (channels) { - case 1: - if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE) - lbuspath = data->paths.noconv; - else - lbuspath = data->paths.mono; - break; - case 2: - if (rate == 48000 && format == SNDRV_PCM_FORMAT_S16_LE) - lbuspath = data->paths.noconv; - else - lbuspath = data->paths.stereo; - break; - } - snd_printdd("use sgdlist at 0x%p\n", - data->sgdlist.area); - if (data->sgdlist.area) { - unsigned int i, j, size, pages, f, pt, period; - struct sgd *c, *p = NULL; - - size = frames_to_bytes(runtime, runtime->buffer_size); - period = frames_to_bytes(runtime, runtime->period_size); - f = PAGE_SIZE; - while ((size + (f >> 1) - 1) <= (f << 7) && (f << 1) > period) - f = f >> 1; - pages = (size + f - 1) / f; - data->size = size; - data->pages = pages; - snd_printdd - ("create sgd size: 0x%x pages %d of size 0x%x for period 0x%x\n", - size, pages, f, period); - pt = 0; - j = 0; - for (i = 0; i < pages; i++) { - unsigned int ofs, addr; - c = &data->sgdbuf[i]; - if (p) - p->dwNextLink = cpu_to_le32(data->sgdlist.addr + - (i * - sizeof(struct - sgd))); - c->dwNextLink = cpu_to_le32(data->sgdlist.addr); - ofs = j << PAGE_SHIFT; - addr = snd_pcm_sgbuf_get_addr(substream, ofs) + pt; - c->dwSegPtrPhys = cpu_to_le32(addr); - pt = (pt + f) % PAGE_SIZE; - if (pt == 0) - j++; - c->dwSegLen = cpu_to_le32(f); - c->dwStat_Ctl = - cpu_to_le32(IEOB_ENABLE | IEOS_ENABLE | - IEOC_ENABLE); - p = c; - size -= f; - } - data->sgdbuf[i].dwSegLen = cpu_to_le32(size); - } - if (lbuspath && lbuspath != data->lbuspath) { - if (data->lbuspath) - freelbuspath(cif, data->source, data->lbuspath); - alloclbuspath(cif, data->source, lbuspath, - &data->mixer, data->intdec); - data->lbuspath = lbuspath; - data->rate = 0; - } - if (data->rate != rate || data->format != format || - data->channels != channels) { - data->rate = rate; - data->format = format; - data->channels = channels; - if (setsampleformat - (cif, data->mixer, data->id, channels, format) - || setsamplerate(cif, data->intdec, rate)) - err = -EIO; - } - spin_unlock_irq(&chip->lock); - return err; -} - -static int -snd_riptide_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct pcmhw *data = get_pcmhwdev(substream); - struct snd_dma_buffer *sgdlist = &data->sgdlist; - int err; - - snd_printdd("hw params id %d (sgdlist: 0x%p 0x%lx %d)\n", data->id, - sgdlist->area, (unsigned long)sgdlist->addr, - (int)sgdlist->bytes); - if (sgdlist->area) - snd_dma_free_pages(sgdlist); - if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - sizeof(struct sgd) * (DESC_MAX_MASK + 1), - sgdlist)) < 0) { - snd_printk(KERN_ERR "Riptide: failed to alloc %d dma bytes\n", - (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1)); - return err; - } - data->sgdbuf = (struct sgd *)sgdlist->area; - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int snd_riptide_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct pcmhw *data = get_pcmhwdev(substream); - struct cmdif *cif = chip->cif; - - if (cif && data) { - if (data->lbuspath) - freelbuspath(cif, data->source, data->lbuspath); - data->lbuspath = NULL; - data->source = 0xff; - data->intdec[0] = 0xff; - data->intdec[1] = 0xff; - - if (data->sgdlist.area) { - snd_dma_free_pages(&data->sgdlist); - data->sgdlist.area = NULL; - } - } - return snd_pcm_lib_free_pages(substream); -} - -static int snd_riptide_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct pcmhw *data; - int sub_num = substream->number; - - chip->playback_substream[sub_num] = substream; - runtime->hw = snd_riptide_playback; - - data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - data->paths = lbus_play_paths[sub_num]; - data->id = play_ids[sub_num]; - data->source = play_sources[sub_num]; - data->intdec[0] = 0xff; - data->intdec[1] = 0xff; - data->state = ST_STOP; - runtime->private_data = data; - return snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); -} - -static int snd_riptide_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct pcmhw *data; - - chip->capture_substream = substream; - runtime->hw = snd_riptide_capture; - - data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - data->paths = lbus_rec_path; - data->id = PADC; - data->source = ACLNK2PADC; - data->intdec[0] = 0xff; - data->intdec[1] = 0xff; - data->state = ST_STOP; - runtime->private_data = data; - return snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); -} - -static int snd_riptide_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct pcmhw *data = get_pcmhwdev(substream); - int sub_num = substream->number; - - substream->runtime->private_data = NULL; - chip->playback_substream[sub_num] = NULL; - kfree(data); - return 0; -} - -static int snd_riptide_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_riptide *chip = snd_pcm_substream_chip(substream); - struct pcmhw *data = get_pcmhwdev(substream); - - substream->runtime->private_data = NULL; - chip->capture_substream = NULL; - kfree(data); - return 0; -} - -static struct snd_pcm_ops snd_riptide_playback_ops = { - .open = snd_riptide_playback_open, - .close = snd_riptide_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_riptide_hw_params, - .hw_free = snd_riptide_hw_free, - .prepare = snd_riptide_prepare, - .page = snd_pcm_sgbuf_ops_page, - .trigger = snd_riptide_trigger, - .pointer = snd_riptide_pointer, -}; -static struct snd_pcm_ops snd_riptide_capture_ops = { - .open = snd_riptide_capture_open, - .close = snd_riptide_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_riptide_hw_params, - .hw_free = snd_riptide_hw_free, - .prepare = snd_riptide_prepare, - .page = snd_pcm_sgbuf_ops_page, - .trigger = snd_riptide_trigger, - .pointer = snd_riptide_pointer, -}; - -static int __devinit -snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = - snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1, - &pcm)) < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_riptide_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_riptide_capture_ops); - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, "RIPTIDE"); - chip->pcm = pcm; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 64 * 1024, 128 * 1024); - if (rpcm) - *rpcm = pcm; - return 0; -} - -static irqreturn_t -snd_riptide_interrupt(int irq, void *dev_id) -{ - struct snd_riptide *chip = dev_id; - struct cmdif *cif = chip->cif; - - if (cif) { - chip->received_irqs++; - if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) || - IS_EOCIRQ(cif->hwport)) { - chip->handled_irqs++; - tasklet_schedule(&chip->riptide_tq); - } - if (chip->rmidi && IS_MPUIRQ(cif->hwport)) { - chip->handled_irqs++; - snd_mpu401_uart_interrupt(irq, - chip->rmidi->private_data); - } - SET_AIACK(cif->hwport); - } - return IRQ_HANDLED; -} - -static void -snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct snd_riptide *chip = ac97->private_data; - struct cmdif *cif = chip->cif; - union cmdret rptr = CMDRET_ZERO; - int i = 0; - - if (snd_BUG_ON(!cif)) - return; - - snd_printdd("Write AC97 reg 0x%x 0x%x\n", reg, val); - do { - SEND_SACR(cif, val, reg); - SEND_RACR(cif, reg, &rptr); - } while (rptr.retwords[1] != val && i++ < MAX_WRITE_RETRY); - if (i > MAX_WRITE_RETRY) - snd_printdd("Write AC97 reg failed\n"); -} - -static unsigned short snd_riptide_codec_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct snd_riptide *chip = ac97->private_data; - struct cmdif *cif = chip->cif; - union cmdret rptr = CMDRET_ZERO; - - if (snd_BUG_ON(!cif)) - return 0; - - if (SEND_RACR(cif, reg, &rptr) != 0) - SEND_RACR(cif, reg, &rptr); - snd_printdd("Read AC97 reg 0x%x got 0x%x\n", reg, rptr.retwords[1]); - return rptr.retwords[1]; -} - -static int snd_riptide_initialize(struct snd_riptide *chip) -{ - struct cmdif *cif; - unsigned int device_id; - int err; - - if (snd_BUG_ON(!chip)) - return -EINVAL; - - cif = chip->cif; - if (!cif) { - if ((cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL)) == NULL) - return -ENOMEM; - cif->hwport = (struct riptideport *)chip->port; - spin_lock_init(&cif->lock); - chip->cif = cif; - } - cif->is_reset = 0; - if ((err = riptide_reset(cif, chip)) != 0) - return err; - device_id = chip->device_id; - switch (device_id) { - case 0x4310: - case 0x4320: - case 0x4330: - snd_printdd("Modem enable?\n"); - SEND_SETDPLL(cif); - break; - } - snd_printdd("Enabling MPU IRQs\n"); - if (chip->rmidi) - SET_EMPUIRQ(cif->hwport); - return err; -} - -static int snd_riptide_free(struct snd_riptide *chip) -{ - struct cmdif *cif; - - if (!chip) - return 0; - - if ((cif = chip->cif)) { - SET_GRESET(cif->hwport); - udelay(100); - UNSET_GRESET(cif->hwport); - kfree(chip->cif); - } - if (chip->irq >= 0) - free_irq(chip->irq, chip); - if (chip->fw_entry) - release_firmware(chip->fw_entry); - release_and_free_resource(chip->res_port); - kfree(chip); - return 0; -} - -static int snd_riptide_dev_free(struct snd_device *device) -{ - struct snd_riptide *chip = device->device_data; - - return snd_riptide_free(chip); -} - -static int __devinit -snd_riptide_create(struct snd_card *card, struct pci_dev *pci, - struct snd_riptide **rchip) -{ - struct snd_riptide *chip; - struct riptideport *hwport; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_riptide_dev_free, - }; - - *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) - return err; - if (!(chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL))) - return -ENOMEM; - - spin_lock_init(&chip->lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - chip->openstreams = 0; - chip->port = pci_resource_start(pci, 0); - chip->received_irqs = 0; - chip->handled_irqs = 0; - chip->cif = NULL; - tasklet_init(&chip->riptide_tq, riptide_handleirq, (unsigned long)chip); - - if ((chip->res_port = - request_region(chip->port, 64, "RIPTIDE")) == NULL) { - snd_printk(KERN_ERR - "Riptide: unable to grab region 0x%lx-0x%lx\n", - chip->port, chip->port + 64 - 1); - snd_riptide_free(chip); - return -EBUSY; - } - hwport = (struct riptideport *)chip->port; - UNSET_AIE(hwport); - - if (request_irq(pci->irq, snd_riptide_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n", - pci->irq); - snd_riptide_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - chip->device_id = pci->device; - pci_set_master(pci); - if ((err = snd_riptide_initialize(chip)) < 0) { - snd_riptide_free(chip); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_riptide_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - return 0; -} - -static void -snd_riptide_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_riptide *chip = entry->private_data; - struct pcmhw *data; - int i; - struct cmdif *cif = NULL; - unsigned char p[256]; - unsigned short rval = 0, lval = 0; - unsigned int rate; - - if (!chip) - return; - - snd_iprintf(buffer, "%s\n\n", chip->card->longname); - snd_iprintf(buffer, "Device ID: 0x%x\nReceived IRQs: (%ld)%ld\nPorts:", - chip->device_id, chip->handled_irqs, chip->received_irqs); - for (i = 0; i < 64; i += 4) - snd_iprintf(buffer, "%c%02x: %08x", - (i % 16) ? ' ' : '\n', i, inl(chip->port + i)); - if ((cif = chip->cif)) { - snd_iprintf(buffer, - "\nVersion: ASIC: %d CODEC: %d AUXDSP: %d PROG: %d", - chip->firmware.firmware.ASIC, - chip->firmware.firmware.CODEC, - chip->firmware.firmware.AUXDSP, - chip->firmware.firmware.PROG); - snd_iprintf(buffer, "\nDigital mixer:"); - for (i = 0; i < 12; i++) { - getmixer(cif, i, &rval, &lval); - snd_iprintf(buffer, "\n %d: %d %d", i, rval, lval); - } - snd_iprintf(buffer, - "\nARM Commands num: %d failed: %d time: %d max: %d min: %d", - cif->cmdcnt, cif->errcnt, - cif->cmdtime, cif->cmdtimemax, cif->cmdtimemin); - } - snd_iprintf(buffer, "\nOpen streams %d:\n", chip->openstreams); - for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) { - if (chip->playback_substream[i] - && chip->playback_substream[i]->runtime - && (data = - chip->playback_substream[i]->runtime->private_data)) { - snd_iprintf(buffer, - "stream: %d mixer: %d source: %d (%d,%d)\n", - data->id, data->mixer, data->source, - data->intdec[0], data->intdec[1]); - if (!(getsamplerate(cif, data->intdec, &rate))) - snd_iprintf(buffer, "rate: %d\n", rate); - } - } - if (chip->capture_substream - && chip->capture_substream->runtime - && (data = chip->capture_substream->runtime->private_data)) { - snd_iprintf(buffer, - "stream: %d mixer: %d source: %d (%d,%d)\n", - data->id, data->mixer, - data->source, data->intdec[0], data->intdec[1]); - if (!(getsamplerate(cif, data->intdec, &rate))) - snd_iprintf(buffer, "rate: %d\n", rate); - } - snd_iprintf(buffer, "Paths:\n"); - i = getpaths(cif, p); - while (i >= 2) { - i -= 2; - snd_iprintf(buffer, "%x->%x ", p[i], p[i + 1]); - } - snd_iprintf(buffer, "\n"); -} - -static void __devinit snd_riptide_proc_init(struct snd_riptide *chip) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(chip->card, "riptide", &entry)) - snd_info_set_text_ops(entry, chip, snd_riptide_proc_read); -} - -static int __devinit snd_riptide_mixer(struct snd_riptide *chip) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err = 0; - static struct snd_ac97_bus_ops ops = { - .write = snd_riptide_codec_write, - .read = snd_riptide_codec_read, - }; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.scaps = AC97_SCAP_SKIP_MODEM; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) - return err; - - chip->ac97_bus = pbus; - ac97.pci = chip->pci; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) - return err; - return err; -} - -#ifdef SUPPORT_JOYSTICK - -static int __devinit -snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id) -{ - static int dev; - struct gameport *gameport; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - if (!joystick_port[dev++]) - return 0; - - gameport = gameport_allocate_port(); - if (!gameport) - return -ENOMEM; - if (!request_region(joystick_port[dev], 8, "Riptide gameport")) { - snd_printk(KERN_WARNING - "Riptide: cannot grab gameport 0x%x\n", - joystick_port[dev]); - gameport_free_port(gameport); - return -EBUSY; - } - - gameport->io = joystick_port[dev]; - gameport_register_port(gameport); - pci_set_drvdata(pci, gameport); - return 0; -} - -static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci) -{ - struct gameport *gameport = pci_get_drvdata(pci); - if (gameport) { - release_region(gameport->io, 8); - gameport_unregister_port(gameport); - pci_set_drvdata(pci, NULL); - } -} -#endif - -static int __devinit -snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_riptide *chip; - unsigned short val; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - err = snd_riptide_create(card, pci, &chip); - if (err < 0) - goto error; - card->private_data = chip; - err = snd_riptide_pcm(chip, 0, NULL); - if (err < 0) - goto error; - err = snd_riptide_mixer(chip); - if (err < 0) - goto error; - - val = LEGACY_ENABLE_ALL; - if (opl3_port[dev]) - val |= LEGACY_ENABLE_FM; -#ifdef SUPPORT_JOYSTICK - if (joystick_port[dev]) - val |= LEGACY_ENABLE_GAMEPORT; -#endif - if (mpu_port[dev]) - val |= LEGACY_ENABLE_MPU_INT | LEGACY_ENABLE_MPU; - val |= (chip->irq << 4) & 0xf0; - pci_write_config_word(chip->pci, PCI_EXT_Legacy_Mask, val); - if (mpu_port[dev]) { - val = mpu_port[dev]; - pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, val); - err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE, - val, MPU401_INFO_IRQ_HOOK, -1, - &chip->rmidi); - if (err < 0) - snd_printk(KERN_WARNING - "Riptide: Can't Allocate MPU at 0x%x\n", - val); - else - chip->mpuaddr = val; - } - if (opl3_port[dev]) { - val = opl3_port[dev]; - pci_write_config_word(chip->pci, PCI_EXT_FM_Base, val); - err = snd_opl3_create(card, val, val + 2, - OPL3_HW_RIPTIDE, 0, &chip->opl3); - if (err < 0) - snd_printk(KERN_WARNING - "Riptide: Can't Allocate OPL3 at 0x%x\n", - val); - else { - chip->opladdr = val; - err = snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL); - if (err < 0) - snd_printk(KERN_WARNING - "Riptide: Can't Allocate OPL3-HWDEP\n"); - } - } -#ifdef SUPPORT_JOYSTICK - if (joystick_port[dev]) { - val = joystick_port[dev]; - pci_write_config_word(chip->pci, PCI_EXT_Game_Base, val); - chip->gameaddr = val; - } -#endif - - strcpy(card->driver, "RIPTIDE"); - strcpy(card->shortname, "Riptide"); -#ifdef SUPPORT_JOYSTICK - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x gameport 0x%x", - card->shortname, chip->port, chip->irq, chip->mpuaddr, - chip->opladdr, chip->gameaddr); -#else - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%lx, irq %i mpu 0x%x opl3 0x%x", - card->shortname, chip->port, chip->irq, chip->mpuaddr, - chip->opladdr); -#endif - snd_riptide_proc_init(chip); - err = snd_card_register(card); - if (err < 0) - goto error; - pci_set_drvdata(pci, card); - dev++; - return 0; - - error: - snd_card_free(card); - return err; -} - -static void __devexit snd_card_riptide_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_riptide_ids, - .probe = snd_card_riptide_probe, - .remove = __devexit_p(snd_card_riptide_remove), -#ifdef CONFIG_PM - .suspend = riptide_suspend, - .resume = riptide_resume, -#endif -}; - -#ifdef SUPPORT_JOYSTICK -static struct pci_driver joystick_driver = { - .name = KBUILD_MODNAME "-joystick", - .id_table = snd_riptide_joystick_ids, - .probe = snd_riptide_joystick_probe, - .remove = __devexit_p(snd_riptide_joystick_remove), -}; -#endif - -static int __init alsa_card_riptide_init(void) -{ - int err; - err = pci_register_driver(&driver); - if (err < 0) - return err; -#if defined(SUPPORT_JOYSTICK) - err = pci_register_driver(&joystick_driver); - /* On failure unregister formerly registered audio driver */ - if (err < 0) - pci_unregister_driver(&driver); -#endif - return err; -} - -static void __exit alsa_card_riptide_exit(void) -{ - pci_unregister_driver(&driver); -#if defined(SUPPORT_JOYSTICK) - pci_unregister_driver(&joystick_driver); -#endif -} - -module_init(alsa_card_riptide_init); -module_exit(alsa_card_riptide_exit); diff --git a/ANDROID_3.4.5/sound/pci/rme32.c b/ANDROID_3.4.5/sound/pci/rme32.c deleted file mode 100644 index b4819d5e..00000000 --- a/ANDROID_3.4.5/sound/pci/rme32.c +++ /dev/null @@ -1,2005 +0,0 @@ -/* - * ALSA driver for RME Digi32, Digi32/8 and Digi32 PRO audio interfaces - * - * Copyright (c) 2002-2004 Martin Langer , - * Pilo Chambert - * - * Thanks to : Anders Torger , - * Henk Hesselink - * for writing the digi96-driver - * and RME for all informations. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * **************************************************************************** - * - * Note #1 "Sek'd models" ................................... martin 2002-12-07 - * - * Identical soundcards by Sek'd were labeled: - * RME Digi 32 = Sek'd Prodif 32 - * RME Digi 32 Pro = Sek'd Prodif 96 - * RME Digi 32/8 = Sek'd Prodif Gold - * - * **************************************************************************** - * - * Note #2 "full duplex mode" ............................... martin 2002-12-07 - * - * Full duplex doesn't work. All cards (32, 32/8, 32Pro) are working identical - * in this mode. Rec data and play data are using the same buffer therefore. At - * first you have got the playing bits in the buffer and then (after playing - * them) they were overwitten by the captured sound of the CS8412/14. Both - * modes (play/record) are running harmonically hand in hand in the same buffer - * and you have only one start bit plus one interrupt bit to control this - * paired action. - * This is opposite to the latter rme96 where playing and capturing is totally - * separated and so their full duplex mode is supported by alsa (using two - * start bits and two interrupts for two different buffers). - * But due to the wrong sequence of playing and capturing ALSA shows no solved - * full duplex support for the rme32 at the moment. That's bad, but I'm not - * able to solve it. Are you motivated enough to solve this problem now? Your - * patch would be welcome! - * - * **************************************************************************** - * - * "The story after the long seeking" -- tiwai - * - * Ok, the situation regarding the full duplex is now improved a bit. - * In the fullduplex mode (given by the module parameter), the hardware buffer - * is split to halves for read and write directions at the DMA pointer. - * That is, the half above the current DMA pointer is used for write, and - * the half below is used for read. To mangle this strange behavior, an - * software intermediate buffer is introduced. This is, of course, not good - * from the viewpoint of the data transfer efficiency. However, this allows - * you to use arbitrary buffer sizes, instead of the fixed I/O buffer size. - * - * **************************************************************************** - */ - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static bool fullduplex[SNDRV_CARDS]; // = {[0 ... (SNDRV_CARDS - 1)] = 1}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for RME Digi32 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for RME Digi32 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable RME Digi32 soundcard."); -module_param_array(fullduplex, bool, NULL, 0444); -MODULE_PARM_DESC(fullduplex, "Support full-duplex mode."); -MODULE_AUTHOR("Martin Langer , Pilo Chambert "); -MODULE_DESCRIPTION("RME Digi32, Digi32/8, Digi32 PRO"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}"); - -/* Defines for RME Digi32 series */ -#define RME32_SPDIF_NCHANNELS 2 - -/* Playback and capture buffer size */ -#define RME32_BUFFER_SIZE 0x20000 - -/* IO area size */ -#define RME32_IO_SIZE 0x30000 - -/* IO area offsets */ -#define RME32_IO_DATA_BUFFER 0x0 -#define RME32_IO_CONTROL_REGISTER 0x20000 -#define RME32_IO_GET_POS 0x20000 -#define RME32_IO_CONFIRM_ACTION_IRQ 0x20004 -#define RME32_IO_RESET_POS 0x20100 - -/* Write control register bits */ -#define RME32_WCR_START (1 << 0) /* startbit */ -#define RME32_WCR_MONO (1 << 1) /* 0=stereo, 1=mono - Setting the whole card to mono - doesn't seem to be very useful. - A software-solution can handle - full-duplex with one direction in - stereo and the other way in mono. - So, the hardware should work all - the time in stereo! */ -#define RME32_WCR_MODE24 (1 << 2) /* 0=16bit, 1=32bit */ -#define RME32_WCR_SEL (1 << 3) /* 0=input on output, 1=normal playback/capture */ -#define RME32_WCR_FREQ_0 (1 << 4) /* frequency (play) */ -#define RME32_WCR_FREQ_1 (1 << 5) -#define RME32_WCR_INP_0 (1 << 6) /* input switch */ -#define RME32_WCR_INP_1 (1 << 7) -#define RME32_WCR_RESET (1 << 8) /* Reset address */ -#define RME32_WCR_MUTE (1 << 9) /* digital mute for output */ -#define RME32_WCR_PRO (1 << 10) /* 1=professional, 0=consumer */ -#define RME32_WCR_DS_BM (1 << 11) /* 1=DoubleSpeed (only PRO-Version); 1=BlockMode (only Adat-Version) */ -#define RME32_WCR_ADAT (1 << 12) /* Adat Mode (only Adat-Version) */ -#define RME32_WCR_AUTOSYNC (1 << 13) /* AutoSync */ -#define RME32_WCR_PD (1 << 14) /* DAC Reset (only PRO-Version) */ -#define RME32_WCR_EMP (1 << 15) /* 1=Emphasis on (only PRO-Version) */ - -#define RME32_WCR_BITPOS_FREQ_0 4 -#define RME32_WCR_BITPOS_FREQ_1 5 -#define RME32_WCR_BITPOS_INP_0 6 -#define RME32_WCR_BITPOS_INP_1 7 - -/* Read control register bits */ -#define RME32_RCR_AUDIO_ADDR_MASK 0x1ffff -#define RME32_RCR_LOCK (1 << 23) /* 1=locked, 0=not locked */ -#define RME32_RCR_ERF (1 << 26) /* 1=Error, 0=no Error */ -#define RME32_RCR_FREQ_0 (1 << 27) /* CS841x frequency (record) */ -#define RME32_RCR_FREQ_1 (1 << 28) -#define RME32_RCR_FREQ_2 (1 << 29) -#define RME32_RCR_KMODE (1 << 30) /* card mode: 1=PLL, 0=quartz */ -#define RME32_RCR_IRQ (1 << 31) /* interrupt */ - -#define RME32_RCR_BITPOS_F0 27 -#define RME32_RCR_BITPOS_F1 28 -#define RME32_RCR_BITPOS_F2 29 - -/* Input types */ -#define RME32_INPUT_OPTICAL 0 -#define RME32_INPUT_COAXIAL 1 -#define RME32_INPUT_INTERNAL 2 -#define RME32_INPUT_XLR 3 - -/* Clock modes */ -#define RME32_CLOCKMODE_SLAVE 0 -#define RME32_CLOCKMODE_MASTER_32 1 -#define RME32_CLOCKMODE_MASTER_44 2 -#define RME32_CLOCKMODE_MASTER_48 3 - -/* Block sizes in bytes */ -#define RME32_BLOCK_SIZE 8192 - -/* Software intermediate buffer (max) size */ -#define RME32_MID_BUFFER_SIZE (1024*1024) - -/* Hardware revisions */ -#define RME32_32_REVISION 192 -#define RME32_328_REVISION_OLD 100 -#define RME32_328_REVISION_NEW 101 -#define RME32_PRO_REVISION_WITH_8412 192 -#define RME32_PRO_REVISION_WITH_8414 150 - - -struct rme32 { - spinlock_t lock; - int irq; - unsigned long port; - void __iomem *iobase; - - u32 wcreg; /* cached write control register value */ - u32 wcreg_spdif; /* S/PDIF setup */ - u32 wcreg_spdif_stream; /* S/PDIF setup (temporary) */ - u32 rcreg; /* cached read control register value */ - - u8 rev; /* card revision number */ - - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - - int playback_frlog; /* log2 of framesize */ - int capture_frlog; - - size_t playback_periodsize; /* in bytes, zero if not used */ - size_t capture_periodsize; /* in bytes, zero if not used */ - - unsigned int fullduplex_mode; - int running; - - struct snd_pcm_indirect playback_pcm; - struct snd_pcm_indirect capture_pcm; - - struct snd_card *card; - struct snd_pcm *spdif_pcm; - struct snd_pcm *adat_pcm; - struct pci_dev *pci; - struct snd_kcontrol *spdif_ctl; -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_rme32_ids) = { - {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32), 0,}, - {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8), 0,}, - {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO), 0,}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, snd_rme32_ids); - -#define RME32_ISWORKING(rme32) ((rme32)->wcreg & RME32_WCR_START) -#define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414) - -static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream); - -static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream); - -static int snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd); - -static void snd_rme32_proc_init(struct rme32 * rme32); - -static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32); - -static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32) -{ - return (readl(rme32->iobase + RME32_IO_GET_POS) - & RME32_RCR_AUDIO_ADDR_MASK); -} - -/* silence callback for halfduplex mode */ -static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - count <<= rme32->playback_frlog; - pos <<= rme32->playback_frlog; - memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count); - return 0; -} - -/* copy callback for halfduplex mode */ -static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, snd_pcm_uframes_t count) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - count <<= rme32->playback_frlog; - pos <<= rme32->playback_frlog; - if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, - src, count)) - return -EFAULT; - return 0; -} - -/* copy callback for halfduplex mode */ -static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, snd_pcm_uframes_t count) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - count <<= rme32->capture_frlog; - pos <<= rme32->capture_frlog; - if (copy_to_user_fromio(dst, - rme32->iobase + RME32_IO_DATA_BUFFER + pos, - count)) - return -EFAULT; - return 0; -} - -/* - * SPDIF I/O capabilities (half-duplex mode) - */ -static struct snd_pcm_hardware snd_rme32_spdif_info = { - .info = (SNDRV_PCM_INFO_MMAP_IOMEM | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE), - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 32000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = RME32_BUFFER_SIZE, - .period_bytes_min = RME32_BLOCK_SIZE, - .period_bytes_max = RME32_BLOCK_SIZE, - .periods_min = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE, - .periods_max = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE, - .fifo_size = 0, -}; - -/* - * ADAT I/O capabilities (half-duplex mode) - */ -static struct snd_pcm_hardware snd_rme32_adat_info = -{ - .info = (SNDRV_PCM_INFO_MMAP_IOMEM | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START), - .formats= SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 8, - .channels_max = 8, - .buffer_bytes_max = RME32_BUFFER_SIZE, - .period_bytes_min = RME32_BLOCK_SIZE, - .period_bytes_max = RME32_BLOCK_SIZE, - .periods_min = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE, - .periods_max = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE, - .fifo_size = 0, -}; - -/* - * SPDIF I/O capabilities (full-duplex mode) - */ -static struct snd_pcm_hardware snd_rme32_spdif_fd_info = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE), - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 32000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = RME32_MID_BUFFER_SIZE, - .period_bytes_min = RME32_BLOCK_SIZE, - .period_bytes_max = RME32_BLOCK_SIZE, - .periods_min = 2, - .periods_max = RME32_MID_BUFFER_SIZE / RME32_BLOCK_SIZE, - .fifo_size = 0, -}; - -/* - * ADAT I/O capabilities (full-duplex mode) - */ -static struct snd_pcm_hardware snd_rme32_adat_fd_info = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START), - .formats= SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 8, - .channels_max = 8, - .buffer_bytes_max = RME32_MID_BUFFER_SIZE, - .period_bytes_min = RME32_BLOCK_SIZE, - .period_bytes_max = RME32_BLOCK_SIZE, - .periods_min = 2, - .periods_max = RME32_MID_BUFFER_SIZE / RME32_BLOCK_SIZE, - .fifo_size = 0, -}; - -static void snd_rme32_reset_dac(struct rme32 *rme32) -{ - writel(rme32->wcreg | RME32_WCR_PD, - rme32->iobase + RME32_IO_CONTROL_REGISTER); - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); -} - -static int snd_rme32_playback_getrate(struct rme32 * rme32) -{ - int rate; - - rate = ((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_0) & 1) + - (((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_1) & 1) << 1); - switch (rate) { - case 1: - rate = 32000; - break; - case 2: - rate = 44100; - break; - case 3: - rate = 48000; - break; - default: - return -1; - } - return (rme32->wcreg & RME32_WCR_DS_BM) ? rate << 1 : rate; -} - -static int snd_rme32_capture_getrate(struct rme32 * rme32, int *is_adat) -{ - int n; - - *is_adat = 0; - if (rme32->rcreg & RME32_RCR_LOCK) { - /* ADAT rate */ - *is_adat = 1; - } - if (rme32->rcreg & RME32_RCR_ERF) { - return -1; - } - - /* S/PDIF rate */ - n = ((rme32->rcreg >> RME32_RCR_BITPOS_F0) & 1) + - (((rme32->rcreg >> RME32_RCR_BITPOS_F1) & 1) << 1) + - (((rme32->rcreg >> RME32_RCR_BITPOS_F2) & 1) << 2); - - if (RME32_PRO_WITH_8414(rme32)) - switch (n) { /* supporting the CS8414 */ - case 0: - case 1: - case 2: - return -1; - case 3: - return 96000; - case 4: - return 88200; - case 5: - return 48000; - case 6: - return 44100; - case 7: - return 32000; - default: - return -1; - break; - } - else - switch (n) { /* supporting the CS8412 */ - case 0: - return -1; - case 1: - return 48000; - case 2: - return 44100; - case 3: - return 32000; - case 4: - return 48000; - case 5: - return 44100; - case 6: - return 44056; - case 7: - return 32000; - default: - break; - } - return -1; -} - -static int snd_rme32_playback_setrate(struct rme32 * rme32, int rate) -{ - int ds; - - ds = rme32->wcreg & RME32_WCR_DS_BM; - switch (rate) { - case 32000: - rme32->wcreg &= ~RME32_WCR_DS_BM; - rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & - ~RME32_WCR_FREQ_1; - break; - case 44100: - rme32->wcreg &= ~RME32_WCR_DS_BM; - rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & - ~RME32_WCR_FREQ_0; - break; - case 48000: - rme32->wcreg &= ~RME32_WCR_DS_BM; - rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | - RME32_WCR_FREQ_1; - break; - case 64000: - if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) - return -EINVAL; - rme32->wcreg |= RME32_WCR_DS_BM; - rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & - ~RME32_WCR_FREQ_1; - break; - case 88200: - if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) - return -EINVAL; - rme32->wcreg |= RME32_WCR_DS_BM; - rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & - ~RME32_WCR_FREQ_0; - break; - case 96000: - if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) - return -EINVAL; - rme32->wcreg |= RME32_WCR_DS_BM; - rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | - RME32_WCR_FREQ_1; - break; - default: - return -EINVAL; - } - if ((!ds && rme32->wcreg & RME32_WCR_DS_BM) || - (ds && !(rme32->wcreg & RME32_WCR_DS_BM))) - { - /* change to/from double-speed: reset the DAC (if available) */ - snd_rme32_reset_dac(rme32); - } else { - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - } - return 0; -} - -static int snd_rme32_setclockmode(struct rme32 * rme32, int mode) -{ - switch (mode) { - case RME32_CLOCKMODE_SLAVE: - /* AutoSync */ - rme32->wcreg = (rme32->wcreg & ~RME32_WCR_FREQ_0) & - ~RME32_WCR_FREQ_1; - break; - case RME32_CLOCKMODE_MASTER_32: - /* Internal 32.0kHz */ - rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & - ~RME32_WCR_FREQ_1; - break; - case RME32_CLOCKMODE_MASTER_44: - /* Internal 44.1kHz */ - rme32->wcreg = (rme32->wcreg & ~RME32_WCR_FREQ_0) | - RME32_WCR_FREQ_1; - break; - case RME32_CLOCKMODE_MASTER_48: - /* Internal 48.0kHz */ - rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | - RME32_WCR_FREQ_1; - break; - default: - return -EINVAL; - } - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - return 0; -} - -static int snd_rme32_getclockmode(struct rme32 * rme32) -{ - return ((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_0) & 1) + - (((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_1) & 1) << 1); -} - -static int snd_rme32_setinputtype(struct rme32 * rme32, int type) -{ - switch (type) { - case RME32_INPUT_OPTICAL: - rme32->wcreg = (rme32->wcreg & ~RME32_WCR_INP_0) & - ~RME32_WCR_INP_1; - break; - case RME32_INPUT_COAXIAL: - rme32->wcreg = (rme32->wcreg | RME32_WCR_INP_0) & - ~RME32_WCR_INP_1; - break; - case RME32_INPUT_INTERNAL: - rme32->wcreg = (rme32->wcreg & ~RME32_WCR_INP_0) | - RME32_WCR_INP_1; - break; - case RME32_INPUT_XLR: - rme32->wcreg = (rme32->wcreg | RME32_WCR_INP_0) | - RME32_WCR_INP_1; - break; - default: - return -EINVAL; - } - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - return 0; -} - -static int snd_rme32_getinputtype(struct rme32 * rme32) -{ - return ((rme32->wcreg >> RME32_WCR_BITPOS_INP_0) & 1) + - (((rme32->wcreg >> RME32_WCR_BITPOS_INP_1) & 1) << 1); -} - -static void -snd_rme32_setframelog(struct rme32 * rme32, int n_channels, int is_playback) -{ - int frlog; - - if (n_channels == 2) { - frlog = 1; - } else { - /* assume 8 channels */ - frlog = 3; - } - if (is_playback) { - frlog += (rme32->wcreg & RME32_WCR_MODE24) ? 2 : 1; - rme32->playback_frlog = frlog; - } else { - frlog += (rme32->wcreg & RME32_WCR_MODE24) ? 2 : 1; - rme32->capture_frlog = frlog; - } -} - -static int snd_rme32_setformat(struct rme32 * rme32, int format) -{ - switch (format) { - case SNDRV_PCM_FORMAT_S16_LE: - rme32->wcreg &= ~RME32_WCR_MODE24; - break; - case SNDRV_PCM_FORMAT_S32_LE: - rme32->wcreg |= RME32_WCR_MODE24; - break; - default: - return -EINVAL; - } - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - return 0; -} - -static int -snd_rme32_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - int err, rate, dummy; - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (rme32->fullduplex_mode) { - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (err < 0) - return err; - } else { - runtime->dma_area = (void __force *)(rme32->iobase + - RME32_IO_DATA_BUFFER); - runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER; - runtime->dma_bytes = RME32_BUFFER_SIZE; - } - - spin_lock_irq(&rme32->lock); - if ((rme32->rcreg & RME32_RCR_KMODE) && - (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { - /* AutoSync */ - if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme32->lock); - return -EIO; - } - } else if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) { - spin_unlock_irq(&rme32->lock); - return err; - } - if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) { - spin_unlock_irq(&rme32->lock); - return err; - } - - snd_rme32_setframelog(rme32, params_channels(params), 1); - if (rme32->capture_periodsize != 0) { - if (params_period_size(params) << rme32->playback_frlog != rme32->capture_periodsize) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - } - rme32->playback_periodsize = params_period_size(params) << rme32->playback_frlog; - /* S/PDIF setup */ - if ((rme32->wcreg & RME32_WCR_ADAT) == 0) { - rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP); - rme32->wcreg |= rme32->wcreg_spdif_stream; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - } - spin_unlock_irq(&rme32->lock); - - return 0; -} - -static int -snd_rme32_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - int err, isadat, rate; - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (rme32->fullduplex_mode) { - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (err < 0) - return err; - } else { - runtime->dma_area = (void __force *)rme32->iobase + - RME32_IO_DATA_BUFFER; - runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER; - runtime->dma_bytes = RME32_BUFFER_SIZE; - } - - spin_lock_irq(&rme32->lock); - /* enable AutoSync for record-preparing */ - rme32->wcreg |= RME32_WCR_AUTOSYNC; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - - if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) { - spin_unlock_irq(&rme32->lock); - return err; - } - if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) { - spin_unlock_irq(&rme32->lock); - return err; - } - if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { - if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme32->lock); - return -EIO; - } - if ((isadat && runtime->hw.channels_min == 2) || - (!isadat && runtime->hw.channels_min == 8)) { - spin_unlock_irq(&rme32->lock); - return -EIO; - } - } - /* AutoSync off for recording */ - rme32->wcreg &= ~RME32_WCR_AUTOSYNC; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - - snd_rme32_setframelog(rme32, params_channels(params), 0); - if (rme32->playback_periodsize != 0) { - if (params_period_size(params) << rme32->capture_frlog != - rme32->playback_periodsize) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - } - rme32->capture_periodsize = - params_period_size(params) << rme32->capture_frlog; - spin_unlock_irq(&rme32->lock); - - return 0; -} - -static int snd_rme32_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - if (! rme32->fullduplex_mode) - return 0; - return snd_pcm_lib_free_pages(substream); -} - -static void snd_rme32_pcm_start(struct rme32 * rme32, int from_pause) -{ - if (!from_pause) { - writel(0, rme32->iobase + RME32_IO_RESET_POS); - } - - rme32->wcreg |= RME32_WCR_START; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); -} - -static void snd_rme32_pcm_stop(struct rme32 * rme32, int to_pause) -{ - /* - * Check if there is an unconfirmed IRQ, if so confirm it, or else - * the hardware will not stop generating interrupts - */ - rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER); - if (rme32->rcreg & RME32_RCR_IRQ) { - writel(0, rme32->iobase + RME32_IO_CONFIRM_ACTION_IRQ); - } - rme32->wcreg &= ~RME32_WCR_START; - if (rme32->wcreg & RME32_WCR_SEL) - rme32->wcreg |= RME32_WCR_MUTE; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - if (! to_pause) - writel(0, rme32->iobase + RME32_IO_RESET_POS); -} - -static irqreturn_t snd_rme32_interrupt(int irq, void *dev_id) -{ - struct rme32 *rme32 = (struct rme32 *) dev_id; - - rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER); - if (!(rme32->rcreg & RME32_RCR_IRQ)) { - return IRQ_NONE; - } else { - if (rme32->capture_substream) { - snd_pcm_period_elapsed(rme32->capture_substream); - } - if (rme32->playback_substream) { - snd_pcm_period_elapsed(rme32->playback_substream); - } - writel(0, rme32->iobase + RME32_IO_CONFIRM_ACTION_IRQ); - } - return IRQ_HANDLED; -} - -static unsigned int period_bytes[] = { RME32_BLOCK_SIZE }; - - -static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { - .count = ARRAY_SIZE(period_bytes), - .list = period_bytes, - .mask = 0 -}; - -static void snd_rme32_set_buffer_constraint(struct rme32 *rme32, struct snd_pcm_runtime *runtime) -{ - if (! rme32->fullduplex_mode) { - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - RME32_BUFFER_SIZE, RME32_BUFFER_SIZE); - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - &hw_constraints_period_bytes); - } -} - -static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream) -{ - int rate, dummy; - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_pcm_set_sync(substream); - - spin_lock_irq(&rme32->lock); - if (rme32->playback_substream != NULL) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - rme32->wcreg &= ~RME32_WCR_ADAT; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - rme32->playback_substream = substream; - spin_unlock_irq(&rme32->lock); - - if (rme32->fullduplex_mode) - runtime->hw = snd_rme32_spdif_fd_info; - else - runtime->hw = snd_rme32_spdif_info; - if (rme32->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO) { - runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; - runtime->hw.rate_max = 96000; - } - if ((rme32->rcreg & RME32_RCR_KMODE) && - (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { - /* AutoSync */ - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - - snd_rme32_set_buffer_constraint(rme32, runtime); - - rme32->wcreg_spdif_stream = rme32->wcreg_spdif; - rme32->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(rme32->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &rme32->spdif_ctl->id); - return 0; -} - -static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream) -{ - int isadat, rate; - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_pcm_set_sync(substream); - - spin_lock_irq(&rme32->lock); - if (rme32->capture_substream != NULL) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - rme32->capture_substream = substream; - spin_unlock_irq(&rme32->lock); - - if (rme32->fullduplex_mode) - runtime->hw = snd_rme32_spdif_fd_info; - else - runtime->hw = snd_rme32_spdif_info; - if (RME32_PRO_WITH_8414(rme32)) { - runtime->hw.rates |= SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; - runtime->hw.rate_max = 96000; - } - if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { - if (isadat) { - return -EIO; - } - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - - snd_rme32_set_buffer_constraint(rme32, runtime); - - return 0; -} - -static int -snd_rme32_playback_adat_open(struct snd_pcm_substream *substream) -{ - int rate, dummy; - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_pcm_set_sync(substream); - - spin_lock_irq(&rme32->lock); - if (rme32->playback_substream != NULL) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - rme32->wcreg |= RME32_WCR_ADAT; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - rme32->playback_substream = substream; - spin_unlock_irq(&rme32->lock); - - if (rme32->fullduplex_mode) - runtime->hw = snd_rme32_adat_fd_info; - else - runtime->hw = snd_rme32_adat_info; - if ((rme32->rcreg & RME32_RCR_KMODE) && - (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { - /* AutoSync */ - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - - snd_rme32_set_buffer_constraint(rme32, runtime); - return 0; -} - -static int -snd_rme32_capture_adat_open(struct snd_pcm_substream *substream) -{ - int isadat, rate; - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (rme32->fullduplex_mode) - runtime->hw = snd_rme32_adat_fd_info; - else - runtime->hw = snd_rme32_adat_info; - if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { - if (!isadat) { - return -EIO; - } - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - - snd_pcm_set_sync(substream); - - spin_lock_irq(&rme32->lock); - if (rme32->capture_substream != NULL) { - spin_unlock_irq(&rme32->lock); - return -EBUSY; - } - rme32->capture_substream = substream; - spin_unlock_irq(&rme32->lock); - - snd_rme32_set_buffer_constraint(rme32, runtime); - return 0; -} - -static int snd_rme32_playback_close(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - int spdif = 0; - - spin_lock_irq(&rme32->lock); - rme32->playback_substream = NULL; - rme32->playback_periodsize = 0; - spdif = (rme32->wcreg & RME32_WCR_ADAT) == 0; - spin_unlock_irq(&rme32->lock); - if (spdif) { - rme32->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(rme32->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - &rme32->spdif_ctl->id); - } - return 0; -} - -static int snd_rme32_capture_close(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - - spin_lock_irq(&rme32->lock); - rme32->capture_substream = NULL; - rme32->capture_periodsize = 0; - spin_unlock(&rme32->lock); - return 0; -} - -static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - - spin_lock_irq(&rme32->lock); - if (rme32->fullduplex_mode) { - memset(&rme32->playback_pcm, 0, sizeof(rme32->playback_pcm)); - rme32->playback_pcm.hw_buffer_size = RME32_BUFFER_SIZE; - rme32->playback_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - } else { - writel(0, rme32->iobase + RME32_IO_RESET_POS); - } - if (rme32->wcreg & RME32_WCR_SEL) - rme32->wcreg &= ~RME32_WCR_MUTE; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme32->lock); - return 0; -} - -static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - - spin_lock_irq(&rme32->lock); - if (rme32->fullduplex_mode) { - memset(&rme32->capture_pcm, 0, sizeof(rme32->capture_pcm)); - rme32->capture_pcm.hw_buffer_size = RME32_BUFFER_SIZE; - rme32->capture_pcm.hw_queue_size = RME32_BUFFER_SIZE / 2; - rme32->capture_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - } else { - writel(0, rme32->iobase + RME32_IO_RESET_POS); - } - spin_unlock_irq(&rme32->lock); - return 0; -} - -static int -snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *s; - - spin_lock(&rme32->lock); - snd_pcm_group_for_each_entry(s, substream) { - if (s != rme32->playback_substream && - s != rme32->capture_substream) - continue; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - rme32->running |= (1 << s->stream); - if (rme32->fullduplex_mode) { - /* remember the current DMA position */ - if (s == rme32->playback_substream) { - rme32->playback_pcm.hw_io = - rme32->playback_pcm.hw_data = snd_rme32_pcm_byteptr(rme32); - } else { - rme32->capture_pcm.hw_io = - rme32->capture_pcm.hw_data = snd_rme32_pcm_byteptr(rme32); - } - } - break; - case SNDRV_PCM_TRIGGER_STOP: - rme32->running &= ~(1 << s->stream); - break; - } - snd_pcm_trigger_done(s, substream); - } - - /* prefill playback buffer */ - if (cmd == SNDRV_PCM_TRIGGER_START && rme32->fullduplex_mode) { - snd_pcm_group_for_each_entry(s, substream) { - if (s == rme32->playback_substream) { - s->ops->ack(s); - break; - } - } - } - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (rme32->running && ! RME32_ISWORKING(rme32)) - snd_rme32_pcm_start(rme32, 0); - break; - case SNDRV_PCM_TRIGGER_STOP: - if (! rme32->running && RME32_ISWORKING(rme32)) - snd_rme32_pcm_stop(rme32, 0); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (rme32->running && RME32_ISWORKING(rme32)) - snd_rme32_pcm_stop(rme32, 1); - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (rme32->running && ! RME32_ISWORKING(rme32)) - snd_rme32_pcm_start(rme32, 1); - break; - } - spin_unlock(&rme32->lock); - return 0; -} - -/* pointer callback for halfduplex mode */ -static snd_pcm_uframes_t -snd_rme32_playback_pointer(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - return snd_rme32_pcm_byteptr(rme32) >> rme32->playback_frlog; -} - -static snd_pcm_uframes_t -snd_rme32_capture_pointer(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - return snd_rme32_pcm_byteptr(rme32) >> rme32->capture_frlog; -} - - -/* ack and pointer callbacks for fullduplex mode */ -static void snd_rme32_pb_trans_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data, - substream->runtime->dma_area + rec->sw_data, bytes); -} - -static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - struct snd_pcm_indirect *rec, *cprec; - - rec = &rme32->playback_pcm; - cprec = &rme32->capture_pcm; - spin_lock(&rme32->lock); - rec->hw_queue_size = RME32_BUFFER_SIZE; - if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) - rec->hw_queue_size -= cprec->hw_ready; - spin_unlock(&rme32->lock); - snd_pcm_indirect_playback_transfer(substream, rec, - snd_rme32_pb_trans_copy); - return 0; -} - -static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - memcpy_fromio(substream->runtime->dma_area + rec->sw_data, - rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data, - bytes); -} - -static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm, - snd_rme32_cp_trans_copy); - return 0; -} - -static snd_pcm_uframes_t -snd_rme32_playback_fd_pointer(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - return snd_pcm_indirect_playback_pointer(substream, &rme32->playback_pcm, - snd_rme32_pcm_byteptr(rme32)); -} - -static snd_pcm_uframes_t -snd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream) -{ - struct rme32 *rme32 = snd_pcm_substream_chip(substream); - return snd_pcm_indirect_capture_pointer(substream, &rme32->capture_pcm, - snd_rme32_pcm_byteptr(rme32)); -} - -/* for halfduplex mode */ -static struct snd_pcm_ops snd_rme32_playback_spdif_ops = { - .open = snd_rme32_playback_spdif_open, - .close = snd_rme32_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme32_playback_hw_params, - .hw_free = snd_rme32_pcm_hw_free, - .prepare = snd_rme32_playback_prepare, - .trigger = snd_rme32_pcm_trigger, - .pointer = snd_rme32_playback_pointer, - .copy = snd_rme32_playback_copy, - .silence = snd_rme32_playback_silence, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static struct snd_pcm_ops snd_rme32_capture_spdif_ops = { - .open = snd_rme32_capture_spdif_open, - .close = snd_rme32_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme32_capture_hw_params, - .hw_free = snd_rme32_pcm_hw_free, - .prepare = snd_rme32_capture_prepare, - .trigger = snd_rme32_pcm_trigger, - .pointer = snd_rme32_capture_pointer, - .copy = snd_rme32_capture_copy, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static struct snd_pcm_ops snd_rme32_playback_adat_ops = { - .open = snd_rme32_playback_adat_open, - .close = snd_rme32_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme32_playback_hw_params, - .prepare = snd_rme32_playback_prepare, - .trigger = snd_rme32_pcm_trigger, - .pointer = snd_rme32_playback_pointer, - .copy = snd_rme32_playback_copy, - .silence = snd_rme32_playback_silence, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static struct snd_pcm_ops snd_rme32_capture_adat_ops = { - .open = snd_rme32_capture_adat_open, - .close = snd_rme32_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme32_capture_hw_params, - .prepare = snd_rme32_capture_prepare, - .trigger = snd_rme32_pcm_trigger, - .pointer = snd_rme32_capture_pointer, - .copy = snd_rme32_capture_copy, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -/* for fullduplex mode */ -static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = { - .open = snd_rme32_playback_spdif_open, - .close = snd_rme32_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme32_playback_hw_params, - .hw_free = snd_rme32_pcm_hw_free, - .prepare = snd_rme32_playback_prepare, - .trigger = snd_rme32_pcm_trigger, - .pointer = snd_rme32_playback_fd_pointer, - .ack = snd_rme32_playback_fd_ack, -}; - -static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = { - .open = snd_rme32_capture_spdif_open, - .close = snd_rme32_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme32_capture_hw_params, - .hw_free = snd_rme32_pcm_hw_free, - .prepare = snd_rme32_capture_prepare, - .trigger = snd_rme32_pcm_trigger, - .pointer = snd_rme32_capture_fd_pointer, - .ack = snd_rme32_capture_fd_ack, -}; - -static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = { - .open = snd_rme32_playback_adat_open, - .close = snd_rme32_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme32_playback_hw_params, - .prepare = snd_rme32_playback_prepare, - .trigger = snd_rme32_pcm_trigger, - .pointer = snd_rme32_playback_fd_pointer, - .ack = snd_rme32_playback_fd_ack, -}; - -static struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = { - .open = snd_rme32_capture_adat_open, - .close = snd_rme32_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme32_capture_hw_params, - .prepare = snd_rme32_capture_prepare, - .trigger = snd_rme32_pcm_trigger, - .pointer = snd_rme32_capture_fd_pointer, - .ack = snd_rme32_capture_fd_ack, -}; - -static void snd_rme32_free(void *private_data) -{ - struct rme32 *rme32 = (struct rme32 *) private_data; - - if (rme32 == NULL) { - return; - } - if (rme32->irq >= 0) { - snd_rme32_pcm_stop(rme32, 0); - free_irq(rme32->irq, (void *) rme32); - rme32->irq = -1; - } - if (rme32->iobase) { - iounmap(rme32->iobase); - rme32->iobase = NULL; - } - if (rme32->port) { - pci_release_regions(rme32->pci); - rme32->port = 0; - } - pci_disable_device(rme32->pci); -} - -static void snd_rme32_free_spdif_pcm(struct snd_pcm *pcm) -{ - struct rme32 *rme32 = (struct rme32 *) pcm->private_data; - rme32->spdif_pcm = NULL; -} - -static void -snd_rme32_free_adat_pcm(struct snd_pcm *pcm) -{ - struct rme32 *rme32 = (struct rme32 *) pcm->private_data; - rme32->adat_pcm = NULL; -} - -static int __devinit snd_rme32_create(struct rme32 * rme32) -{ - struct pci_dev *pci = rme32->pci; - int err; - - rme32->irq = -1; - spin_lock_init(&rme32->lock); - - if ((err = pci_enable_device(pci)) < 0) - return err; - - if ((err = pci_request_regions(pci, "RME32")) < 0) - return err; - rme32->port = pci_resource_start(rme32->pci, 0); - - rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE); - if (!rme32->iobase) { - snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", - rme32->port, rme32->port + RME32_IO_SIZE - 1); - return -ENOMEM; - } - - if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED, - KBUILD_MODNAME, rme32)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - return -EBUSY; - } - rme32->irq = pci->irq; - - /* read the card's revision number */ - pci_read_config_byte(pci, 8, &rme32->rev); - - /* set up ALSA pcm device for S/PDIF */ - if ((err = snd_pcm_new(rme32->card, "Digi32 IEC958", 0, 1, 1, &rme32->spdif_pcm)) < 0) { - return err; - } - rme32->spdif_pcm->private_data = rme32; - rme32->spdif_pcm->private_free = snd_rme32_free_spdif_pcm; - strcpy(rme32->spdif_pcm->name, "Digi32 IEC958"); - if (rme32->fullduplex_mode) { - snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_rme32_playback_spdif_fd_ops); - snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_rme32_capture_spdif_fd_ops); - snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 0, RME32_MID_BUFFER_SIZE); - rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - } else { - snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_rme32_playback_spdif_ops); - snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_rme32_capture_spdif_ops); - rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - } - - /* set up ALSA pcm device for ADAT */ - if ((pci->device == PCI_DEVICE_ID_RME_DIGI32) || - (pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO)) { - /* ADAT is not available on DIGI32 and DIGI32 Pro */ - rme32->adat_pcm = NULL; - } - else { - if ((err = snd_pcm_new(rme32->card, "Digi32 ADAT", 1, - 1, 1, &rme32->adat_pcm)) < 0) - { - return err; - } - rme32->adat_pcm->private_data = rme32; - rme32->adat_pcm->private_free = snd_rme32_free_adat_pcm; - strcpy(rme32->adat_pcm->name, "Digi32 ADAT"); - if (rme32->fullduplex_mode) { - snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_rme32_playback_adat_fd_ops); - snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_rme32_capture_adat_fd_ops); - snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 0, RME32_MID_BUFFER_SIZE); - rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - } else { - snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_rme32_playback_adat_ops); - snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_rme32_capture_adat_ops); - rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - } - } - - - rme32->playback_periodsize = 0; - rme32->capture_periodsize = 0; - - /* make sure playback/capture is stopped, if by some reason active */ - snd_rme32_pcm_stop(rme32, 0); - - /* reset DAC */ - snd_rme32_reset_dac(rme32); - - /* reset buffer pointer */ - writel(0, rme32->iobase + RME32_IO_RESET_POS); - - /* set default values in registers */ - rme32->wcreg = RME32_WCR_SEL | /* normal playback */ - RME32_WCR_INP_0 | /* input select */ - RME32_WCR_MUTE; /* muting on */ - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - - - /* init switch interface */ - if ((err = snd_rme32_create_switches(rme32->card, rme32)) < 0) { - return err; - } - - /* init proc interface */ - snd_rme32_proc_init(rme32); - - rme32->capture_substream = NULL; - rme32->playback_substream = NULL; - - return 0; -} - -/* - * proc interface - */ - -static void -snd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer) -{ - int n; - struct rme32 *rme32 = (struct rme32 *) entry->private_data; - - rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER); - - snd_iprintf(buffer, rme32->card->longname); - snd_iprintf(buffer, " (index #%d)\n", rme32->card->number + 1); - - snd_iprintf(buffer, "\nGeneral settings\n"); - if (rme32->fullduplex_mode) - snd_iprintf(buffer, " Full-duplex mode\n"); - else - snd_iprintf(buffer, " Half-duplex mode\n"); - if (RME32_PRO_WITH_8414(rme32)) { - snd_iprintf(buffer, " receiver: CS8414\n"); - } else { - snd_iprintf(buffer, " receiver: CS8412\n"); - } - if (rme32->wcreg & RME32_WCR_MODE24) { - snd_iprintf(buffer, " format: 24 bit"); - } else { - snd_iprintf(buffer, " format: 16 bit"); - } - if (rme32->wcreg & RME32_WCR_MONO) { - snd_iprintf(buffer, ", Mono\n"); - } else { - snd_iprintf(buffer, ", Stereo\n"); - } - - snd_iprintf(buffer, "\nInput settings\n"); - switch (snd_rme32_getinputtype(rme32)) { - case RME32_INPUT_OPTICAL: - snd_iprintf(buffer, " input: optical"); - break; - case RME32_INPUT_COAXIAL: - snd_iprintf(buffer, " input: coaxial"); - break; - case RME32_INPUT_INTERNAL: - snd_iprintf(buffer, " input: internal"); - break; - case RME32_INPUT_XLR: - snd_iprintf(buffer, " input: XLR"); - break; - } - if (snd_rme32_capture_getrate(rme32, &n) < 0) { - snd_iprintf(buffer, "\n sample rate: no valid signal\n"); - } else { - if (n) { - snd_iprintf(buffer, " (8 channels)\n"); - } else { - snd_iprintf(buffer, " (2 channels)\n"); - } - snd_iprintf(buffer, " sample rate: %d Hz\n", - snd_rme32_capture_getrate(rme32, &n)); - } - - snd_iprintf(buffer, "\nOutput settings\n"); - if (rme32->wcreg & RME32_WCR_SEL) { - snd_iprintf(buffer, " output signal: normal playback"); - } else { - snd_iprintf(buffer, " output signal: same as input"); - } - if (rme32->wcreg & RME32_WCR_MUTE) { - snd_iprintf(buffer, " (muted)\n"); - } else { - snd_iprintf(buffer, "\n"); - } - - /* master output frequency */ - if (! - ((!(rme32->wcreg & RME32_WCR_FREQ_0)) - && (!(rme32->wcreg & RME32_WCR_FREQ_1)))) { - snd_iprintf(buffer, " sample rate: %d Hz\n", - snd_rme32_playback_getrate(rme32)); - } - if (rme32->rcreg & RME32_RCR_KMODE) { - snd_iprintf(buffer, " sample clock source: AutoSync\n"); - } else { - snd_iprintf(buffer, " sample clock source: Internal\n"); - } - if (rme32->wcreg & RME32_WCR_PRO) { - snd_iprintf(buffer, " format: AES/EBU (professional)\n"); - } else { - snd_iprintf(buffer, " format: IEC958 (consumer)\n"); - } - if (rme32->wcreg & RME32_WCR_EMP) { - snd_iprintf(buffer, " emphasis: on\n"); - } else { - snd_iprintf(buffer, " emphasis: off\n"); - } -} - -static void __devinit snd_rme32_proc_init(struct rme32 * rme32) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(rme32->card, "rme32", &entry)) - snd_info_set_text_ops(entry, rme32, snd_rme32_proc_read); -} - -/* - * control interface - */ - -#define snd_rme32_info_loopback_control snd_ctl_boolean_mono_info - -static int -snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme32->lock); - ucontrol->value.integer.value[0] = - rme32->wcreg & RME32_WCR_SEL ? 0 : 1; - spin_unlock_irq(&rme32->lock); - return 0; -} -static int -snd_rme32_put_loopback_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ucontrol->value.integer.value[0] ? 0 : RME32_WCR_SEL; - spin_lock_irq(&rme32->lock); - val = (rme32->wcreg & ~RME32_WCR_SEL) | val; - change = val != rme32->wcreg; - if (ucontrol->value.integer.value[0]) - val &= ~RME32_WCR_MUTE; - else - val |= RME32_WCR_MUTE; - rme32->wcreg = val; - writel(val, rme32->iobase + RME32_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme32->lock); - return change; -} - -static int -snd_rme32_info_inputtype_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - static char *texts[4] = { "Optical", "Coaxial", "Internal", "XLR" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - switch (rme32->pci->device) { - case PCI_DEVICE_ID_RME_DIGI32: - case PCI_DEVICE_ID_RME_DIGI32_8: - uinfo->value.enumerated.items = 3; - break; - case PCI_DEVICE_ID_RME_DIGI32_PRO: - uinfo->value.enumerated.items = 4; - break; - default: - snd_BUG(); - break; - } - if (uinfo->value.enumerated.item > - uinfo->value.enumerated.items - 1) { - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - } - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} -static int -snd_rme32_get_inputtype_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - unsigned int items = 3; - - spin_lock_irq(&rme32->lock); - ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32); - - switch (rme32->pci->device) { - case PCI_DEVICE_ID_RME_DIGI32: - case PCI_DEVICE_ID_RME_DIGI32_8: - items = 3; - break; - case PCI_DEVICE_ID_RME_DIGI32_PRO: - items = 4; - break; - default: - snd_BUG(); - break; - } - if (ucontrol->value.enumerated.item[0] >= items) { - ucontrol->value.enumerated.item[0] = items - 1; - } - - spin_unlock_irq(&rme32->lock); - return 0; -} -static int -snd_rme32_put_inputtype_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change, items = 3; - - switch (rme32->pci->device) { - case PCI_DEVICE_ID_RME_DIGI32: - case PCI_DEVICE_ID_RME_DIGI32_8: - items = 3; - break; - case PCI_DEVICE_ID_RME_DIGI32_PRO: - items = 4; - break; - default: - snd_BUG(); - break; - } - val = ucontrol->value.enumerated.item[0] % items; - - spin_lock_irq(&rme32->lock); - change = val != (unsigned int)snd_rme32_getinputtype(rme32); - snd_rme32_setinputtype(rme32, val); - spin_unlock_irq(&rme32->lock); - return change; -} - -static int -snd_rme32_info_clockmode_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { "AutoSync", - "Internal 32.0kHz", - "Internal 44.1kHz", - "Internal 48.0kHz" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) { - uinfo->value.enumerated.item = 3; - } - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} -static int -snd_rme32_get_clockmode_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme32->lock); - ucontrol->value.enumerated.item[0] = snd_rme32_getclockmode(rme32); - spin_unlock_irq(&rme32->lock); - return 0; -} -static int -snd_rme32_put_clockmode_control(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&rme32->lock); - change = val != (unsigned int)snd_rme32_getclockmode(rme32); - snd_rme32_setclockmode(rme32, val); - spin_unlock_irq(&rme32->lock); - return change; -} - -static u32 snd_rme32_convert_from_aes(struct snd_aes_iec958 * aes) -{ - u32 val = 0; - val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME32_WCR_PRO : 0; - if (val & RME32_WCR_PRO) - val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME32_WCR_EMP : 0; - else - val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME32_WCR_EMP : 0; - return val; -} - -static void snd_rme32_convert_to_aes(struct snd_aes_iec958 * aes, u32 val) -{ - aes->status[0] = ((val & RME32_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0); - if (val & RME32_WCR_PRO) - aes->status[0] |= (val & RME32_WCR_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; - else - aes->status[0] |= (val & RME32_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; -} - -static int snd_rme32_control_spdif_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme32_control_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - - snd_rme32_convert_to_aes(&ucontrol->value.iec958, - rme32->wcreg_spdif); - return 0; -} - -static int snd_rme32_control_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - int change; - u32 val; - - val = snd_rme32_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme32->lock); - change = val != rme32->wcreg_spdif; - rme32->wcreg_spdif = val; - spin_unlock_irq(&rme32->lock); - return change; -} - -static int snd_rme32_control_spdif_stream_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme32_control_spdif_stream_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value * - ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - - snd_rme32_convert_to_aes(&ucontrol->value.iec958, - rme32->wcreg_spdif_stream); - return 0; -} - -static int snd_rme32_control_spdif_stream_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value * - ucontrol) -{ - struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); - int change; - u32 val; - - val = snd_rme32_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme32->lock); - change = val != rme32->wcreg_spdif_stream; - rme32->wcreg_spdif_stream = val; - rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP); - rme32->wcreg |= val; - writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme32->lock); - return change; -} - -static int snd_rme32_control_spdif_mask_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme32_control_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value * - ucontrol) -{ - ucontrol->value.iec958.status[0] = kcontrol->private_value; - return 0; -} - -static struct snd_kcontrol_new snd_rme32_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = snd_rme32_control_spdif_info, - .get = snd_rme32_control_spdif_get, - .put = snd_rme32_control_spdif_put - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), - .info = snd_rme32_control_spdif_stream_info, - .get = snd_rme32_control_spdif_stream_get, - .put = snd_rme32_control_spdif_stream_put - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), - .info = snd_rme32_control_spdif_mask_info, - .get = snd_rme32_control_spdif_mask_get, - .private_value = IEC958_AES0_PROFESSIONAL | IEC958_AES0_CON_EMPHASIS - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), - .info = snd_rme32_control_spdif_mask_info, - .get = snd_rme32_control_spdif_mask_get, - .private_value = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_EMPHASIS - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Connector", - .info = snd_rme32_info_inputtype_control, - .get = snd_rme32_get_inputtype_control, - .put = snd_rme32_put_inputtype_control - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Loopback Input", - .info = snd_rme32_info_loopback_control, - .get = snd_rme32_get_loopback_control, - .put = snd_rme32_put_loopback_control - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Sample Clock Source", - .info = snd_rme32_info_clockmode_control, - .get = snd_rme32_get_clockmode_control, - .put = snd_rme32_put_clockmode_control - } -}; - -static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32) -{ - int idx, err; - struct snd_kcontrol *kctl; - - for (idx = 0; idx < (int)ARRAY_SIZE(snd_rme32_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme32_controls[idx], rme32))) < 0) - return err; - if (idx == 1) /* IEC958 (S/PDIF) Stream */ - rme32->spdif_ctl = kctl; - } - - return 0; -} - -/* - * Card initialisation - */ - -static void snd_rme32_card_free(struct snd_card *card) -{ - snd_rme32_free(card->private_data); -} - -static int __devinit -snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) -{ - static int dev; - struct rme32 *rme32; - struct snd_card *card; - int err; - - if (dev >= SNDRV_CARDS) { - return -ENODEV; - } - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme32), &card); - if (err < 0) - return err; - card->private_free = snd_rme32_card_free; - rme32 = (struct rme32 *) card->private_data; - rme32->card = card; - rme32->pci = pci; - snd_card_set_dev(card, &pci->dev); - if (fullduplex[dev]) - rme32->fullduplex_mode = 1; - if ((err = snd_rme32_create(rme32)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "Digi32"); - switch (rme32->pci->device) { - case PCI_DEVICE_ID_RME_DIGI32: - strcpy(card->shortname, "RME Digi32"); - break; - case PCI_DEVICE_ID_RME_DIGI32_8: - strcpy(card->shortname, "RME Digi32/8"); - break; - case PCI_DEVICE_ID_RME_DIGI32_PRO: - strcpy(card->shortname, "RME Digi32 PRO"); - break; - } - sprintf(card->longname, "%s (Rev. %d) at 0x%lx, irq %d", - card->shortname, rme32->rev, rme32->port, rme32->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_rme32_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_rme32_ids, - .probe = snd_rme32_probe, - .remove = __devexit_p(snd_rme32_remove), -}; - -static int __init alsa_card_rme32_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_rme32_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_rme32_init) -module_exit(alsa_card_rme32_exit) diff --git a/ANDROID_3.4.5/sound/pci/rme96.c b/ANDROID_3.4.5/sound/pci/rme96.c deleted file mode 100644 index ba894158..00000000 --- a/ANDROID_3.4.5/sound/pci/rme96.c +++ /dev/null @@ -1,2416 +0,0 @@ -/* - * ALSA driver for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST audio - * interfaces - * - * Copyright (c) 2000, 2001 Anders Torger - * - * Thanks to Henk Hesselink for the analog volume control - * code. - * - * 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 -#include -#include -#include - -#include - -/* note, two last pcis should be equal, it is not a bug */ - -MODULE_AUTHOR("Anders Torger "); -MODULE_DESCRIPTION("RME Digi96, Digi96/8, Digi96/8 PRO, Digi96/8 PST, " - "Digi96/8 PAD"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{RME,Digi96}," - "{RME,Digi96/8}," - "{RME,Digi96/8 PRO}," - "{RME,Digi96/8 PST}," - "{RME,Digi96/8 PAD}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for RME Digi96 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for RME Digi96 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard."); - -/* - * Defines for RME Digi96 series, from internal RME reference documents - * dated 12.01.00 - */ - -#define RME96_SPDIF_NCHANNELS 2 - -/* Playback and capture buffer size */ -#define RME96_BUFFER_SIZE 0x10000 - -/* IO area size */ -#define RME96_IO_SIZE 0x60000 - -/* IO area offsets */ -#define RME96_IO_PLAY_BUFFER 0x0 -#define RME96_IO_REC_BUFFER 0x10000 -#define RME96_IO_CONTROL_REGISTER 0x20000 -#define RME96_IO_ADDITIONAL_REG 0x20004 -#define RME96_IO_CONFIRM_PLAY_IRQ 0x20008 -#define RME96_IO_CONFIRM_REC_IRQ 0x2000C -#define RME96_IO_SET_PLAY_POS 0x40000 -#define RME96_IO_RESET_PLAY_POS 0x4FFFC -#define RME96_IO_SET_REC_POS 0x50000 -#define RME96_IO_RESET_REC_POS 0x5FFFC -#define RME96_IO_GET_PLAY_POS 0x20000 -#define RME96_IO_GET_REC_POS 0x30000 - -/* Write control register bits */ -#define RME96_WCR_START (1 << 0) -#define RME96_WCR_START_2 (1 << 1) -#define RME96_WCR_GAIN_0 (1 << 2) -#define RME96_WCR_GAIN_1 (1 << 3) -#define RME96_WCR_MODE24 (1 << 4) -#define RME96_WCR_MODE24_2 (1 << 5) -#define RME96_WCR_BM (1 << 6) -#define RME96_WCR_BM_2 (1 << 7) -#define RME96_WCR_ADAT (1 << 8) -#define RME96_WCR_FREQ_0 (1 << 9) -#define RME96_WCR_FREQ_1 (1 << 10) -#define RME96_WCR_DS (1 << 11) -#define RME96_WCR_PRO (1 << 12) -#define RME96_WCR_EMP (1 << 13) -#define RME96_WCR_SEL (1 << 14) -#define RME96_WCR_MASTER (1 << 15) -#define RME96_WCR_PD (1 << 16) -#define RME96_WCR_INP_0 (1 << 17) -#define RME96_WCR_INP_1 (1 << 18) -#define RME96_WCR_THRU_0 (1 << 19) -#define RME96_WCR_THRU_1 (1 << 20) -#define RME96_WCR_THRU_2 (1 << 21) -#define RME96_WCR_THRU_3 (1 << 22) -#define RME96_WCR_THRU_4 (1 << 23) -#define RME96_WCR_THRU_5 (1 << 24) -#define RME96_WCR_THRU_6 (1 << 25) -#define RME96_WCR_THRU_7 (1 << 26) -#define RME96_WCR_DOLBY (1 << 27) -#define RME96_WCR_MONITOR_0 (1 << 28) -#define RME96_WCR_MONITOR_1 (1 << 29) -#define RME96_WCR_ISEL (1 << 30) -#define RME96_WCR_IDIS (1 << 31) - -#define RME96_WCR_BITPOS_GAIN_0 2 -#define RME96_WCR_BITPOS_GAIN_1 3 -#define RME96_WCR_BITPOS_FREQ_0 9 -#define RME96_WCR_BITPOS_FREQ_1 10 -#define RME96_WCR_BITPOS_INP_0 17 -#define RME96_WCR_BITPOS_INP_1 18 -#define RME96_WCR_BITPOS_MONITOR_0 28 -#define RME96_WCR_BITPOS_MONITOR_1 29 - -/* Read control register bits */ -#define RME96_RCR_AUDIO_ADDR_MASK 0xFFFF -#define RME96_RCR_IRQ_2 (1 << 16) -#define RME96_RCR_T_OUT (1 << 17) -#define RME96_RCR_DEV_ID_0 (1 << 21) -#define RME96_RCR_DEV_ID_1 (1 << 22) -#define RME96_RCR_LOCK (1 << 23) -#define RME96_RCR_VERF (1 << 26) -#define RME96_RCR_F0 (1 << 27) -#define RME96_RCR_F1 (1 << 28) -#define RME96_RCR_F2 (1 << 29) -#define RME96_RCR_AUTOSYNC (1 << 30) -#define RME96_RCR_IRQ (1 << 31) - -#define RME96_RCR_BITPOS_F0 27 -#define RME96_RCR_BITPOS_F1 28 -#define RME96_RCR_BITPOS_F2 29 - -/* Additional register bits */ -#define RME96_AR_WSEL (1 << 0) -#define RME96_AR_ANALOG (1 << 1) -#define RME96_AR_FREQPAD_0 (1 << 2) -#define RME96_AR_FREQPAD_1 (1 << 3) -#define RME96_AR_FREQPAD_2 (1 << 4) -#define RME96_AR_PD2 (1 << 5) -#define RME96_AR_DAC_EN (1 << 6) -#define RME96_AR_CLATCH (1 << 7) -#define RME96_AR_CCLK (1 << 8) -#define RME96_AR_CDATA (1 << 9) - -#define RME96_AR_BITPOS_F0 2 -#define RME96_AR_BITPOS_F1 3 -#define RME96_AR_BITPOS_F2 4 - -/* Monitor tracks */ -#define RME96_MONITOR_TRACKS_1_2 0 -#define RME96_MONITOR_TRACKS_3_4 1 -#define RME96_MONITOR_TRACKS_5_6 2 -#define RME96_MONITOR_TRACKS_7_8 3 - -/* Attenuation */ -#define RME96_ATTENUATION_0 0 -#define RME96_ATTENUATION_6 1 -#define RME96_ATTENUATION_12 2 -#define RME96_ATTENUATION_18 3 - -/* Input types */ -#define RME96_INPUT_OPTICAL 0 -#define RME96_INPUT_COAXIAL 1 -#define RME96_INPUT_INTERNAL 2 -#define RME96_INPUT_XLR 3 -#define RME96_INPUT_ANALOG 4 - -/* Clock modes */ -#define RME96_CLOCKMODE_SLAVE 0 -#define RME96_CLOCKMODE_MASTER 1 -#define RME96_CLOCKMODE_WORDCLOCK 2 - -/* Block sizes in bytes */ -#define RME96_SMALL_BLOCK_SIZE 2048 -#define RME96_LARGE_BLOCK_SIZE 8192 - -/* Volume control */ -#define RME96_AD1852_VOL_BITS 14 -#define RME96_AD1855_VOL_BITS 10 - - -struct rme96 { - spinlock_t lock; - int irq; - unsigned long port; - void __iomem *iobase; - - u32 wcreg; /* cached write control register value */ - u32 wcreg_spdif; /* S/PDIF setup */ - u32 wcreg_spdif_stream; /* S/PDIF setup (temporary) */ - u32 rcreg; /* cached read control register value */ - u32 areg; /* cached additional register value */ - u16 vol[2]; /* cached volume of analog output */ - - u8 rev; /* card revision number */ - - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - - int playback_frlog; /* log2 of framesize */ - int capture_frlog; - - size_t playback_periodsize; /* in bytes, zero if not used */ - size_t capture_periodsize; /* in bytes, zero if not used */ - - struct snd_card *card; - struct snd_pcm *spdif_pcm; - struct snd_pcm *adat_pcm; - struct pci_dev *pci; - struct snd_kcontrol *spdif_ctl; -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_rme96_ids) = { - { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96), 0, }, - { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8), 0, }, - { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO), 0, }, - { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST), 0, }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_rme96_ids); - -#define RME96_ISPLAYING(rme96) ((rme96)->wcreg & RME96_WCR_START) -#define RME96_ISRECORDING(rme96) ((rme96)->wcreg & RME96_WCR_START_2) -#define RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) -#define RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO || \ - (rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) -#define RME96_DAC_IS_1852(rme96) (RME96_HAS_ANALOG_OUT(rme96) && (rme96)->rev >= 4) -#define RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \ - ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO && (rme96)->rev == 2)) -#define RME96_185X_MAX_OUT(rme96) ((1 << (RME96_DAC_IS_1852(rme96) ? RME96_AD1852_VOL_BITS : RME96_AD1855_VOL_BITS)) - 1) - -static int -snd_rme96_playback_prepare(struct snd_pcm_substream *substream); - -static int -snd_rme96_capture_prepare(struct snd_pcm_substream *substream); - -static int -snd_rme96_playback_trigger(struct snd_pcm_substream *substream, - int cmd); - -static int -snd_rme96_capture_trigger(struct snd_pcm_substream *substream, - int cmd); - -static snd_pcm_uframes_t -snd_rme96_playback_pointer(struct snd_pcm_substream *substream); - -static snd_pcm_uframes_t -snd_rme96_capture_pointer(struct snd_pcm_substream *substream); - -static void __devinit -snd_rme96_proc_init(struct rme96 *rme96); - -static int -snd_rme96_create_switches(struct snd_card *card, - struct rme96 *rme96); - -static int -snd_rme96_getinputtype(struct rme96 *rme96); - -static inline unsigned int -snd_rme96_playback_ptr(struct rme96 *rme96) -{ - return (readl(rme96->iobase + RME96_IO_GET_PLAY_POS) - & RME96_RCR_AUDIO_ADDR_MASK) >> rme96->playback_frlog; -} - -static inline unsigned int -snd_rme96_capture_ptr(struct rme96 *rme96) -{ - return (readl(rme96->iobase + RME96_IO_GET_REC_POS) - & RME96_RCR_AUDIO_ADDR_MASK) >> rme96->capture_frlog; -} - -static int -snd_rme96_playback_silence(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - count <<= rme96->playback_frlog; - pos <<= rme96->playback_frlog; - memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, - 0, count); - return 0; -} - -static int -snd_rme96_playback_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - count <<= rme96->playback_frlog; - pos <<= rme96->playback_frlog; - copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, - count); - return 0; -} - -static int -snd_rme96_capture_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - count <<= rme96->capture_frlog; - pos <<= rme96->capture_frlog; - copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, - count); - return 0; -} - -/* - * Digital output capabilities (S/PDIF) - */ -static struct snd_pcm_hardware snd_rme96_playback_spdif_info = -{ - .info = (SNDRV_PCM_INFO_MMAP_IOMEM | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE), - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000), - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = RME96_BUFFER_SIZE, - .period_bytes_min = RME96_SMALL_BLOCK_SIZE, - .period_bytes_max = RME96_LARGE_BLOCK_SIZE, - .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, - .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, - .fifo_size = 0, -}; - -/* - * Digital input capabilities (S/PDIF) - */ -static struct snd_pcm_hardware snd_rme96_capture_spdif_info = -{ - .info = (SNDRV_PCM_INFO_MMAP_IOMEM | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE), - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000), - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = RME96_BUFFER_SIZE, - .period_bytes_min = RME96_SMALL_BLOCK_SIZE, - .period_bytes_max = RME96_LARGE_BLOCK_SIZE, - .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, - .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, - .fifo_size = 0, -}; - -/* - * Digital output capabilities (ADAT) - */ -static struct snd_pcm_hardware snd_rme96_playback_adat_info = -{ - .info = (SNDRV_PCM_INFO_MMAP_IOMEM | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE), - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 8, - .channels_max = 8, - .buffer_bytes_max = RME96_BUFFER_SIZE, - .period_bytes_min = RME96_SMALL_BLOCK_SIZE, - .period_bytes_max = RME96_LARGE_BLOCK_SIZE, - .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, - .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, - .fifo_size = 0, -}; - -/* - * Digital input capabilities (ADAT) - */ -static struct snd_pcm_hardware snd_rme96_capture_adat_info = -{ - .info = (SNDRV_PCM_INFO_MMAP_IOMEM | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE), - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 8, - .channels_max = 8, - .buffer_bytes_max = RME96_BUFFER_SIZE, - .period_bytes_min = RME96_SMALL_BLOCK_SIZE, - .period_bytes_max = RME96_LARGE_BLOCK_SIZE, - .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, - .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, - .fifo_size = 0, -}; - -/* - * The CDATA, CCLK and CLATCH bits can be used to write to the SPI interface - * of the AD1852 or AD1852 D/A converter on the board. CDATA must be set up - * on the falling edge of CCLK and be stable on the rising edge. The rising - * edge of CLATCH after the last data bit clocks in the whole data word. - * A fast processor could probably drive the SPI interface faster than the - * DAC can handle (3MHz for the 1855, unknown for the 1852). The udelay(1) - * limits the data rate to 500KHz and only causes a delay of 33 microsecs. - * - * NOTE: increased delay from 1 to 10, since there where problems setting - * the volume. - */ -static void -snd_rme96_write_SPI(struct rme96 *rme96, u16 val) -{ - int i; - - for (i = 0; i < 16; i++) { - if (val & 0x8000) { - rme96->areg |= RME96_AR_CDATA; - } else { - rme96->areg &= ~RME96_AR_CDATA; - } - rme96->areg &= ~(RME96_AR_CCLK | RME96_AR_CLATCH); - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - udelay(10); - rme96->areg |= RME96_AR_CCLK; - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - udelay(10); - val <<= 1; - } - rme96->areg &= ~(RME96_AR_CCLK | RME96_AR_CDATA); - rme96->areg |= RME96_AR_CLATCH; - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - udelay(10); - rme96->areg &= ~RME96_AR_CLATCH; - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); -} - -static void -snd_rme96_apply_dac_volume(struct rme96 *rme96) -{ - if (RME96_DAC_IS_1852(rme96)) { - snd_rme96_write_SPI(rme96, (rme96->vol[0] << 2) | 0x0); - snd_rme96_write_SPI(rme96, (rme96->vol[1] << 2) | 0x2); - } else if (RME96_DAC_IS_1855(rme96)) { - snd_rme96_write_SPI(rme96, (rme96->vol[0] & 0x3FF) | 0x000); - snd_rme96_write_SPI(rme96, (rme96->vol[1] & 0x3FF) | 0x400); - } -} - -static void -snd_rme96_reset_dac(struct rme96 *rme96) -{ - writel(rme96->wcreg | RME96_WCR_PD, - rme96->iobase + RME96_IO_CONTROL_REGISTER); - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} - -static int -snd_rme96_getmontracks(struct rme96 *rme96) -{ - return ((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_0) & 1) + - (((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_1) & 1) << 1); -} - -static int -snd_rme96_setmontracks(struct rme96 *rme96, - int montracks) -{ - if (montracks & 1) { - rme96->wcreg |= RME96_WCR_MONITOR_0; - } else { - rme96->wcreg &= ~RME96_WCR_MONITOR_0; - } - if (montracks & 2) { - rme96->wcreg |= RME96_WCR_MONITOR_1; - } else { - rme96->wcreg &= ~RME96_WCR_MONITOR_1; - } - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - return 0; -} - -static int -snd_rme96_getattenuation(struct rme96 *rme96) -{ - return ((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_0) & 1) + - (((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_1) & 1) << 1); -} - -static int -snd_rme96_setattenuation(struct rme96 *rme96, - int attenuation) -{ - switch (attenuation) { - case 0: - rme96->wcreg = (rme96->wcreg & ~RME96_WCR_GAIN_0) & - ~RME96_WCR_GAIN_1; - break; - case 1: - rme96->wcreg = (rme96->wcreg | RME96_WCR_GAIN_0) & - ~RME96_WCR_GAIN_1; - break; - case 2: - rme96->wcreg = (rme96->wcreg & ~RME96_WCR_GAIN_0) | - RME96_WCR_GAIN_1; - break; - case 3: - rme96->wcreg = (rme96->wcreg | RME96_WCR_GAIN_0) | - RME96_WCR_GAIN_1; - break; - default: - return -EINVAL; - } - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - return 0; -} - -static int -snd_rme96_capture_getrate(struct rme96 *rme96, - int *is_adat) -{ - int n, rate; - - *is_adat = 0; - if (rme96->areg & RME96_AR_ANALOG) { - /* Analog input, overrides S/PDIF setting */ - n = ((rme96->areg >> RME96_AR_BITPOS_F0) & 1) + - (((rme96->areg >> RME96_AR_BITPOS_F1) & 1) << 1); - switch (n) { - case 1: - rate = 32000; - break; - case 2: - rate = 44100; - break; - case 3: - rate = 48000; - break; - default: - return -1; - } - return (rme96->areg & RME96_AR_BITPOS_F2) ? rate << 1 : rate; - } - - rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); - if (rme96->rcreg & RME96_RCR_LOCK) { - /* ADAT rate */ - *is_adat = 1; - if (rme96->rcreg & RME96_RCR_T_OUT) { - return 48000; - } - return 44100; - } - - if (rme96->rcreg & RME96_RCR_VERF) { - return -1; - } - - /* S/PDIF rate */ - n = ((rme96->rcreg >> RME96_RCR_BITPOS_F0) & 1) + - (((rme96->rcreg >> RME96_RCR_BITPOS_F1) & 1) << 1) + - (((rme96->rcreg >> RME96_RCR_BITPOS_F2) & 1) << 2); - - switch (n) { - case 0: - if (rme96->rcreg & RME96_RCR_T_OUT) { - return 64000; - } - return -1; - case 3: return 96000; - case 4: return 88200; - case 5: return 48000; - case 6: return 44100; - case 7: return 32000; - default: - break; - } - return -1; -} - -static int -snd_rme96_playback_getrate(struct rme96 *rme96) -{ - int rate, dummy; - - if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) - { - /* slave clock */ - return rate; - } - rate = ((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_0) & 1) + - (((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_1) & 1) << 1); - switch (rate) { - case 1: - rate = 32000; - break; - case 2: - rate = 44100; - break; - case 3: - rate = 48000; - break; - default: - return -1; - } - return (rme96->wcreg & RME96_WCR_DS) ? rate << 1 : rate; -} - -static int -snd_rme96_playback_setrate(struct rme96 *rme96, - int rate) -{ - int ds; - - ds = rme96->wcreg & RME96_WCR_DS; - switch (rate) { - case 32000: - rme96->wcreg &= ~RME96_WCR_DS; - rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) & - ~RME96_WCR_FREQ_1; - break; - case 44100: - rme96->wcreg &= ~RME96_WCR_DS; - rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_1) & - ~RME96_WCR_FREQ_0; - break; - case 48000: - rme96->wcreg &= ~RME96_WCR_DS; - rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) | - RME96_WCR_FREQ_1; - break; - case 64000: - rme96->wcreg |= RME96_WCR_DS; - rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) & - ~RME96_WCR_FREQ_1; - break; - case 88200: - rme96->wcreg |= RME96_WCR_DS; - rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_1) & - ~RME96_WCR_FREQ_0; - break; - case 96000: - rme96->wcreg |= RME96_WCR_DS; - rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) | - RME96_WCR_FREQ_1; - break; - default: - return -EINVAL; - } - if ((!ds && rme96->wcreg & RME96_WCR_DS) || - (ds && !(rme96->wcreg & RME96_WCR_DS))) - { - /* change to/from double-speed: reset the DAC (if available) */ - snd_rme96_reset_dac(rme96); - } else { - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - } - return 0; -} - -static int -snd_rme96_capture_analog_setrate(struct rme96 *rme96, - int rate) -{ - switch (rate) { - case 32000: - rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) & - ~RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2; - break; - case 44100: - rme96->areg = ((rme96->areg & ~RME96_AR_FREQPAD_0) | - RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2; - break; - case 48000: - rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) | - RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2; - break; - case 64000: - if (rme96->rev < 4) { - return -EINVAL; - } - rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) & - ~RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; - break; - case 88200: - if (rme96->rev < 4) { - return -EINVAL; - } - rme96->areg = ((rme96->areg & ~RME96_AR_FREQPAD_0) | - RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; - break; - case 96000: - rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) | - RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; - break; - default: - return -EINVAL; - } - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - return 0; -} - -static int -snd_rme96_setclockmode(struct rme96 *rme96, - int mode) -{ - switch (mode) { - case RME96_CLOCKMODE_SLAVE: - /* AutoSync */ - rme96->wcreg &= ~RME96_WCR_MASTER; - rme96->areg &= ~RME96_AR_WSEL; - break; - case RME96_CLOCKMODE_MASTER: - /* Internal */ - rme96->wcreg |= RME96_WCR_MASTER; - rme96->areg &= ~RME96_AR_WSEL; - break; - case RME96_CLOCKMODE_WORDCLOCK: - /* Word clock is a master mode */ - rme96->wcreg |= RME96_WCR_MASTER; - rme96->areg |= RME96_AR_WSEL; - break; - default: - return -EINVAL; - } - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - return 0; -} - -static int -snd_rme96_getclockmode(struct rme96 *rme96) -{ - if (rme96->areg & RME96_AR_WSEL) { - return RME96_CLOCKMODE_WORDCLOCK; - } - return (rme96->wcreg & RME96_WCR_MASTER) ? RME96_CLOCKMODE_MASTER : - RME96_CLOCKMODE_SLAVE; -} - -static int -snd_rme96_setinputtype(struct rme96 *rme96, - int type) -{ - int n; - - switch (type) { - case RME96_INPUT_OPTICAL: - rme96->wcreg = (rme96->wcreg & ~RME96_WCR_INP_0) & - ~RME96_WCR_INP_1; - break; - case RME96_INPUT_COAXIAL: - rme96->wcreg = (rme96->wcreg | RME96_WCR_INP_0) & - ~RME96_WCR_INP_1; - break; - case RME96_INPUT_INTERNAL: - rme96->wcreg = (rme96->wcreg & ~RME96_WCR_INP_0) | - RME96_WCR_INP_1; - break; - case RME96_INPUT_XLR: - if ((rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && - rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PRO) || - (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && - rme96->rev > 4)) - { - /* Only Digi96/8 PRO and Digi96/8 PAD supports XLR */ - return -EINVAL; - } - rme96->wcreg = (rme96->wcreg | RME96_WCR_INP_0) | - RME96_WCR_INP_1; - break; - case RME96_INPUT_ANALOG: - if (!RME96_HAS_ANALOG_IN(rme96)) { - return -EINVAL; - } - rme96->areg |= RME96_AR_ANALOG; - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - if (rme96->rev < 4) { - /* - * Revision less than 004 does not support 64 and - * 88.2 kHz - */ - if (snd_rme96_capture_getrate(rme96, &n) == 88200) { - snd_rme96_capture_analog_setrate(rme96, 44100); - } - if (snd_rme96_capture_getrate(rme96, &n) == 64000) { - snd_rme96_capture_analog_setrate(rme96, 32000); - } - } - return 0; - default: - return -EINVAL; - } - if (type != RME96_INPUT_ANALOG && RME96_HAS_ANALOG_IN(rme96)) { - rme96->areg &= ~RME96_AR_ANALOG; - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - } - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - return 0; -} - -static int -snd_rme96_getinputtype(struct rme96 *rme96) -{ - if (rme96->areg & RME96_AR_ANALOG) { - return RME96_INPUT_ANALOG; - } - return ((rme96->wcreg >> RME96_WCR_BITPOS_INP_0) & 1) + - (((rme96->wcreg >> RME96_WCR_BITPOS_INP_1) & 1) << 1); -} - -static void -snd_rme96_setframelog(struct rme96 *rme96, - int n_channels, - int is_playback) -{ - int frlog; - - if (n_channels == 2) { - frlog = 1; - } else { - /* assume 8 channels */ - frlog = 3; - } - if (is_playback) { - frlog += (rme96->wcreg & RME96_WCR_MODE24) ? 2 : 1; - rme96->playback_frlog = frlog; - } else { - frlog += (rme96->wcreg & RME96_WCR_MODE24_2) ? 2 : 1; - rme96->capture_frlog = frlog; - } -} - -static int -snd_rme96_playback_setformat(struct rme96 *rme96, - int format) -{ - switch (format) { - case SNDRV_PCM_FORMAT_S16_LE: - rme96->wcreg &= ~RME96_WCR_MODE24; - break; - case SNDRV_PCM_FORMAT_S32_LE: - rme96->wcreg |= RME96_WCR_MODE24; - break; - default: - return -EINVAL; - } - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - return 0; -} - -static int -snd_rme96_capture_setformat(struct rme96 *rme96, - int format) -{ - switch (format) { - case SNDRV_PCM_FORMAT_S16_LE: - rme96->wcreg &= ~RME96_WCR_MODE24_2; - break; - case SNDRV_PCM_FORMAT_S32_LE: - rme96->wcreg |= RME96_WCR_MODE24_2; - break; - default: - return -EINVAL; - } - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - return 0; -} - -static void -snd_rme96_set_period_properties(struct rme96 *rme96, - size_t period_bytes) -{ - switch (period_bytes) { - case RME96_LARGE_BLOCK_SIZE: - rme96->wcreg &= ~RME96_WCR_ISEL; - break; - case RME96_SMALL_BLOCK_SIZE: - rme96->wcreg |= RME96_WCR_ISEL; - break; - default: - snd_BUG(); - break; - } - rme96->wcreg &= ~RME96_WCR_IDIS; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} - -static int -snd_rme96_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err, rate, dummy; - - runtime->dma_area = (void __force *)(rme96->iobase + - RME96_IO_PLAY_BUFFER); - runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER; - runtime->dma_bytes = RME96_BUFFER_SIZE; - - spin_lock_irq(&rme96->lock); - if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) - { - /* slave clock */ - if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme96->lock); - return -EIO; - } - } else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) { - spin_unlock_irq(&rme96->lock); - return err; - } - if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) { - spin_unlock_irq(&rme96->lock); - return err; - } - snd_rme96_setframelog(rme96, params_channels(params), 1); - if (rme96->capture_periodsize != 0) { - if (params_period_size(params) << rme96->playback_frlog != - rme96->capture_periodsize) - { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - } - rme96->playback_periodsize = - params_period_size(params) << rme96->playback_frlog; - snd_rme96_set_period_properties(rme96, rme96->playback_periodsize); - /* S/PDIF setup */ - if ((rme96->wcreg & RME96_WCR_ADAT) == 0) { - rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); - writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER); - } - spin_unlock_irq(&rme96->lock); - - return 0; -} - -static int -snd_rme96_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err, isadat, rate; - - runtime->dma_area = (void __force *)(rme96->iobase + - RME96_IO_REC_BUFFER); - runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER; - runtime->dma_bytes = RME96_BUFFER_SIZE; - - spin_lock_irq(&rme96->lock); - if ((err = snd_rme96_capture_setformat(rme96, params_format(params))) < 0) { - spin_unlock_irq(&rme96->lock); - return err; - } - if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { - if ((err = snd_rme96_capture_analog_setrate(rme96, - params_rate(params))) < 0) - { - spin_unlock_irq(&rme96->lock); - return err; - } - } else if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) { - if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme96->lock); - return -EIO; - } - if ((isadat && runtime->hw.channels_min == 2) || - (!isadat && runtime->hw.channels_min == 8)) - { - spin_unlock_irq(&rme96->lock); - return -EIO; - } - } - snd_rme96_setframelog(rme96, params_channels(params), 0); - if (rme96->playback_periodsize != 0) { - if (params_period_size(params) << rme96->capture_frlog != - rme96->playback_periodsize) - { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - } - rme96->capture_periodsize = - params_period_size(params) << rme96->capture_frlog; - snd_rme96_set_period_properties(rme96, rme96->capture_periodsize); - spin_unlock_irq(&rme96->lock); - - return 0; -} - -static void -snd_rme96_playback_start(struct rme96 *rme96, - int from_pause) -{ - if (!from_pause) { - writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); - } - - rme96->wcreg |= RME96_WCR_START; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} - -static void -snd_rme96_capture_start(struct rme96 *rme96, - int from_pause) -{ - if (!from_pause) { - writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); - } - - rme96->wcreg |= RME96_WCR_START_2; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} - -static void -snd_rme96_playback_stop(struct rme96 *rme96) -{ - /* - * Check if there is an unconfirmed IRQ, if so confirm it, or else - * the hardware will not stop generating interrupts - */ - rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); - if (rme96->rcreg & RME96_RCR_IRQ) { - writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); - } - rme96->wcreg &= ~RME96_WCR_START; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} - -static void -snd_rme96_capture_stop(struct rme96 *rme96) -{ - rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); - if (rme96->rcreg & RME96_RCR_IRQ_2) { - writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); - } - rme96->wcreg &= ~RME96_WCR_START_2; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); -} - -static irqreturn_t -snd_rme96_interrupt(int irq, - void *dev_id) -{ - struct rme96 *rme96 = (struct rme96 *)dev_id; - - rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); - /* fastpath out, to ease interrupt sharing */ - if (!((rme96->rcreg & RME96_RCR_IRQ) || - (rme96->rcreg & RME96_RCR_IRQ_2))) - { - return IRQ_NONE; - } - - if (rme96->rcreg & RME96_RCR_IRQ) { - /* playback */ - snd_pcm_period_elapsed(rme96->playback_substream); - writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); - } - if (rme96->rcreg & RME96_RCR_IRQ_2) { - /* capture */ - snd_pcm_period_elapsed(rme96->capture_substream); - writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); - } - return IRQ_HANDLED; -} - -static unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE }; - -static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { - .count = ARRAY_SIZE(period_bytes), - .list = period_bytes, - .mask = 0 -}; - -static void -rme96_set_buffer_size_constraint(struct rme96 *rme96, - struct snd_pcm_runtime *runtime) -{ - unsigned int size; - - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); - if ((size = rme96->playback_periodsize) != 0 || - (size = rme96->capture_periodsize) != 0) - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - size, size); - else - snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - &hw_constraints_period_bytes); -} - -static int -snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) -{ - int rate, dummy; - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irq(&rme96->lock); - if (rme96->playback_substream != NULL) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - rme96->wcreg &= ~RME96_WCR_ADAT; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - rme96->playback_substream = substream; - spin_unlock_irq(&rme96->lock); - - runtime->hw = snd_rme96_playback_spdif_info; - if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) - { - /* slave clock */ - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - rme96_set_buffer_size_constraint(rme96, runtime); - - rme96->wcreg_spdif_stream = rme96->wcreg_spdif; - rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &rme96->spdif_ctl->id); - return 0; -} - -static int -snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) -{ - int isadat, rate; - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_rme96_capture_spdif_info; - if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) - { - if (isadat) { - return -EIO; - } - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - - spin_lock_irq(&rme96->lock); - if (rme96->capture_substream != NULL) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - rme96->capture_substream = substream; - spin_unlock_irq(&rme96->lock); - - rme96_set_buffer_size_constraint(rme96, runtime); - return 0; -} - -static int -snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) -{ - int rate, dummy; - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irq(&rme96->lock); - if (rme96->playback_substream != NULL) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - rme96->wcreg |= RME96_WCR_ADAT; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - rme96->playback_substream = substream; - spin_unlock_irq(&rme96->lock); - - runtime->hw = snd_rme96_playback_adat_info; - if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) - { - /* slave clock */ - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - rme96_set_buffer_size_constraint(rme96, runtime); - return 0; -} - -static int -snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) -{ - int isadat, rate; - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_rme96_capture_adat_info; - if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { - /* makes no sense to use analog input. Note that analog - expension cards AEB4/8-I are RME96_INPUT_INTERNAL */ - return -EIO; - } - if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) { - if (!isadat) { - return -EIO; - } - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } - - spin_lock_irq(&rme96->lock); - if (rme96->capture_substream != NULL) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; - } - rme96->capture_substream = substream; - spin_unlock_irq(&rme96->lock); - - rme96_set_buffer_size_constraint(rme96, runtime); - return 0; -} - -static int -snd_rme96_playback_close(struct snd_pcm_substream *substream) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - int spdif = 0; - - spin_lock_irq(&rme96->lock); - if (RME96_ISPLAYING(rme96)) { - snd_rme96_playback_stop(rme96); - } - rme96->playback_substream = NULL; - rme96->playback_periodsize = 0; - spdif = (rme96->wcreg & RME96_WCR_ADAT) == 0; - spin_unlock_irq(&rme96->lock); - if (spdif) { - rme96->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &rme96->spdif_ctl->id); - } - return 0; -} - -static int -snd_rme96_capture_close(struct snd_pcm_substream *substream) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - - spin_lock_irq(&rme96->lock); - if (RME96_ISRECORDING(rme96)) { - snd_rme96_capture_stop(rme96); - } - rme96->capture_substream = NULL; - rme96->capture_periodsize = 0; - spin_unlock_irq(&rme96->lock); - return 0; -} - -static int -snd_rme96_playback_prepare(struct snd_pcm_substream *substream) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - - spin_lock_irq(&rme96->lock); - if (RME96_ISPLAYING(rme96)) { - snd_rme96_playback_stop(rme96); - } - writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); - spin_unlock_irq(&rme96->lock); - return 0; -} - -static int -snd_rme96_capture_prepare(struct snd_pcm_substream *substream) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - - spin_lock_irq(&rme96->lock); - if (RME96_ISRECORDING(rme96)) { - snd_rme96_capture_stop(rme96); - } - writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); - spin_unlock_irq(&rme96->lock); - return 0; -} - -static int -snd_rme96_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (!RME96_ISPLAYING(rme96)) { - if (substream != rme96->playback_substream) { - return -EBUSY; - } - snd_rme96_playback_start(rme96, 0); - } - break; - - case SNDRV_PCM_TRIGGER_STOP: - if (RME96_ISPLAYING(rme96)) { - if (substream != rme96->playback_substream) { - return -EBUSY; - } - snd_rme96_playback_stop(rme96); - } - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (RME96_ISPLAYING(rme96)) { - snd_rme96_playback_stop(rme96); - } - break; - - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!RME96_ISPLAYING(rme96)) { - snd_rme96_playback_start(rme96, 1); - } - break; - - default: - return -EINVAL; - } - return 0; -} - -static int -snd_rme96_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (!RME96_ISRECORDING(rme96)) { - if (substream != rme96->capture_substream) { - return -EBUSY; - } - snd_rme96_capture_start(rme96, 0); - } - break; - - case SNDRV_PCM_TRIGGER_STOP: - if (RME96_ISRECORDING(rme96)) { - if (substream != rme96->capture_substream) { - return -EBUSY; - } - snd_rme96_capture_stop(rme96); - } - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (RME96_ISRECORDING(rme96)) { - snd_rme96_capture_stop(rme96); - } - break; - - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!RME96_ISRECORDING(rme96)) { - snd_rme96_capture_start(rme96, 1); - } - break; - - default: - return -EINVAL; - } - - return 0; -} - -static snd_pcm_uframes_t -snd_rme96_playback_pointer(struct snd_pcm_substream *substream) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - return snd_rme96_playback_ptr(rme96); -} - -static snd_pcm_uframes_t -snd_rme96_capture_pointer(struct snd_pcm_substream *substream) -{ - struct rme96 *rme96 = snd_pcm_substream_chip(substream); - return snd_rme96_capture_ptr(rme96); -} - -static struct snd_pcm_ops snd_rme96_playback_spdif_ops = { - .open = snd_rme96_playback_spdif_open, - .close = snd_rme96_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme96_playback_hw_params, - .prepare = snd_rme96_playback_prepare, - .trigger = snd_rme96_playback_trigger, - .pointer = snd_rme96_playback_pointer, - .copy = snd_rme96_playback_copy, - .silence = snd_rme96_playback_silence, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static struct snd_pcm_ops snd_rme96_capture_spdif_ops = { - .open = snd_rme96_capture_spdif_open, - .close = snd_rme96_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme96_capture_hw_params, - .prepare = snd_rme96_capture_prepare, - .trigger = snd_rme96_capture_trigger, - .pointer = snd_rme96_capture_pointer, - .copy = snd_rme96_capture_copy, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static struct snd_pcm_ops snd_rme96_playback_adat_ops = { - .open = snd_rme96_playback_adat_open, - .close = snd_rme96_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme96_playback_hw_params, - .prepare = snd_rme96_playback_prepare, - .trigger = snd_rme96_playback_trigger, - .pointer = snd_rme96_playback_pointer, - .copy = snd_rme96_playback_copy, - .silence = snd_rme96_playback_silence, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static struct snd_pcm_ops snd_rme96_capture_adat_ops = { - .open = snd_rme96_capture_adat_open, - .close = snd_rme96_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_rme96_capture_hw_params, - .prepare = snd_rme96_capture_prepare, - .trigger = snd_rme96_capture_trigger, - .pointer = snd_rme96_capture_pointer, - .copy = snd_rme96_capture_copy, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static void -snd_rme96_free(void *private_data) -{ - struct rme96 *rme96 = (struct rme96 *)private_data; - - if (rme96 == NULL) { - return; - } - if (rme96->irq >= 0) { - snd_rme96_playback_stop(rme96); - snd_rme96_capture_stop(rme96); - rme96->areg &= ~RME96_AR_DAC_EN; - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - free_irq(rme96->irq, (void *)rme96); - rme96->irq = -1; - } - if (rme96->iobase) { - iounmap(rme96->iobase); - rme96->iobase = NULL; - } - if (rme96->port) { - pci_release_regions(rme96->pci); - rme96->port = 0; - } - pci_disable_device(rme96->pci); -} - -static void -snd_rme96_free_spdif_pcm(struct snd_pcm *pcm) -{ - struct rme96 *rme96 = pcm->private_data; - rme96->spdif_pcm = NULL; -} - -static void -snd_rme96_free_adat_pcm(struct snd_pcm *pcm) -{ - struct rme96 *rme96 = pcm->private_data; - rme96->adat_pcm = NULL; -} - -static int __devinit -snd_rme96_create(struct rme96 *rme96) -{ - struct pci_dev *pci = rme96->pci; - int err; - - rme96->irq = -1; - spin_lock_init(&rme96->lock); - - if ((err = pci_enable_device(pci)) < 0) - return err; - - if ((err = pci_request_regions(pci, "RME96")) < 0) - return err; - rme96->port = pci_resource_start(rme96->pci, 0); - - rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE); - if (!rme96->iobase) { - snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); - return -ENOMEM; - } - - if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_SHARED, - KBUILD_MODNAME, rme96)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - return -EBUSY; - } - rme96->irq = pci->irq; - - /* read the card's revision number */ - pci_read_config_byte(pci, 8, &rme96->rev); - - /* set up ALSA pcm device for S/PDIF */ - if ((err = snd_pcm_new(rme96->card, "Digi96 IEC958", 0, - 1, 1, &rme96->spdif_pcm)) < 0) - { - return err; - } - rme96->spdif_pcm->private_data = rme96; - rme96->spdif_pcm->private_free = snd_rme96_free_spdif_pcm; - strcpy(rme96->spdif_pcm->name, "Digi96 IEC958"); - snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_spdif_ops); - snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_spdif_ops); - - rme96->spdif_pcm->info_flags = 0; - - /* set up ALSA pcm device for ADAT */ - if (pci->device == PCI_DEVICE_ID_RME_DIGI96) { - /* ADAT is not available on the base model */ - rme96->adat_pcm = NULL; - } else { - if ((err = snd_pcm_new(rme96->card, "Digi96 ADAT", 1, - 1, 1, &rme96->adat_pcm)) < 0) - { - return err; - } - rme96->adat_pcm->private_data = rme96; - rme96->adat_pcm->private_free = snd_rme96_free_adat_pcm; - strcpy(rme96->adat_pcm->name, "Digi96 ADAT"); - snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_adat_ops); - snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_adat_ops); - - rme96->adat_pcm->info_flags = 0; - } - - rme96->playback_periodsize = 0; - rme96->capture_periodsize = 0; - - /* make sure playback/capture is stopped, if by some reason active */ - snd_rme96_playback_stop(rme96); - snd_rme96_capture_stop(rme96); - - /* set default values in registers */ - rme96->wcreg = - RME96_WCR_FREQ_1 | /* set 44.1 kHz playback */ - RME96_WCR_SEL | /* normal playback */ - RME96_WCR_MASTER | /* set to master clock mode */ - RME96_WCR_INP_0; /* set coaxial input */ - - rme96->areg = RME96_AR_FREQPAD_1; /* set 44.1 kHz analog capture */ - - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - - /* reset the ADC */ - writel(rme96->areg | RME96_AR_PD2, - rme96->iobase + RME96_IO_ADDITIONAL_REG); - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - - /* reset and enable the DAC (order is important). */ - snd_rme96_reset_dac(rme96); - rme96->areg |= RME96_AR_DAC_EN; - writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); - - /* reset playback and record buffer pointers */ - writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); - writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); - - /* reset volume */ - rme96->vol[0] = rme96->vol[1] = 0; - if (RME96_HAS_ANALOG_OUT(rme96)) { - snd_rme96_apply_dac_volume(rme96); - } - - /* init switch interface */ - if ((err = snd_rme96_create_switches(rme96->card, rme96)) < 0) { - return err; - } - - /* init proc interface */ - snd_rme96_proc_init(rme96); - - return 0; -} - -/* - * proc interface - */ - -static void -snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - int n; - struct rme96 *rme96 = entry->private_data; - - rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); - - snd_iprintf(buffer, rme96->card->longname); - snd_iprintf(buffer, " (index #%d)\n", rme96->card->number + 1); - - snd_iprintf(buffer, "\nGeneral settings\n"); - if (rme96->wcreg & RME96_WCR_IDIS) { - snd_iprintf(buffer, " period size: N/A (interrupts " - "disabled)\n"); - } else if (rme96->wcreg & RME96_WCR_ISEL) { - snd_iprintf(buffer, " period size: 2048 bytes\n"); - } else { - snd_iprintf(buffer, " period size: 8192 bytes\n"); - } - snd_iprintf(buffer, "\nInput settings\n"); - switch (snd_rme96_getinputtype(rme96)) { - case RME96_INPUT_OPTICAL: - snd_iprintf(buffer, " input: optical"); - break; - case RME96_INPUT_COAXIAL: - snd_iprintf(buffer, " input: coaxial"); - break; - case RME96_INPUT_INTERNAL: - snd_iprintf(buffer, " input: internal"); - break; - case RME96_INPUT_XLR: - snd_iprintf(buffer, " input: XLR"); - break; - case RME96_INPUT_ANALOG: - snd_iprintf(buffer, " input: analog"); - break; - } - if (snd_rme96_capture_getrate(rme96, &n) < 0) { - snd_iprintf(buffer, "\n sample rate: no valid signal\n"); - } else { - if (n) { - snd_iprintf(buffer, " (8 channels)\n"); - } else { - snd_iprintf(buffer, " (2 channels)\n"); - } - snd_iprintf(buffer, " sample rate: %d Hz\n", - snd_rme96_capture_getrate(rme96, &n)); - } - if (rme96->wcreg & RME96_WCR_MODE24_2) { - snd_iprintf(buffer, " sample format: 24 bit\n"); - } else { - snd_iprintf(buffer, " sample format: 16 bit\n"); - } - - snd_iprintf(buffer, "\nOutput settings\n"); - if (rme96->wcreg & RME96_WCR_SEL) { - snd_iprintf(buffer, " output signal: normal playback\n"); - } else { - snd_iprintf(buffer, " output signal: same as input\n"); - } - snd_iprintf(buffer, " sample rate: %d Hz\n", - snd_rme96_playback_getrate(rme96)); - if (rme96->wcreg & RME96_WCR_MODE24) { - snd_iprintf(buffer, " sample format: 24 bit\n"); - } else { - snd_iprintf(buffer, " sample format: 16 bit\n"); - } - if (rme96->areg & RME96_AR_WSEL) { - snd_iprintf(buffer, " sample clock source: word clock\n"); - } else if (rme96->wcreg & RME96_WCR_MASTER) { - snd_iprintf(buffer, " sample clock source: internal\n"); - } else if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { - snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to analog input setting)\n"); - } else if (snd_rme96_capture_getrate(rme96, &n) < 0) { - snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to no valid signal)\n"); - } else { - snd_iprintf(buffer, " sample clock source: autosync\n"); - } - if (rme96->wcreg & RME96_WCR_PRO) { - snd_iprintf(buffer, " format: AES/EBU (professional)\n"); - } else { - snd_iprintf(buffer, " format: IEC958 (consumer)\n"); - } - if (rme96->wcreg & RME96_WCR_EMP) { - snd_iprintf(buffer, " emphasis: on\n"); - } else { - snd_iprintf(buffer, " emphasis: off\n"); - } - if (rme96->wcreg & RME96_WCR_DOLBY) { - snd_iprintf(buffer, " non-audio (dolby): on\n"); - } else { - snd_iprintf(buffer, " non-audio (dolby): off\n"); - } - if (RME96_HAS_ANALOG_IN(rme96)) { - snd_iprintf(buffer, "\nAnalog output settings\n"); - switch (snd_rme96_getmontracks(rme96)) { - case RME96_MONITOR_TRACKS_1_2: - snd_iprintf(buffer, " monitored ADAT tracks: 1+2\n"); - break; - case RME96_MONITOR_TRACKS_3_4: - snd_iprintf(buffer, " monitored ADAT tracks: 3+4\n"); - break; - case RME96_MONITOR_TRACKS_5_6: - snd_iprintf(buffer, " monitored ADAT tracks: 5+6\n"); - break; - case RME96_MONITOR_TRACKS_7_8: - snd_iprintf(buffer, " monitored ADAT tracks: 7+8\n"); - break; - } - switch (snd_rme96_getattenuation(rme96)) { - case RME96_ATTENUATION_0: - snd_iprintf(buffer, " attenuation: 0 dB\n"); - break; - case RME96_ATTENUATION_6: - snd_iprintf(buffer, " attenuation: -6 dB\n"); - break; - case RME96_ATTENUATION_12: - snd_iprintf(buffer, " attenuation: -12 dB\n"); - break; - case RME96_ATTENUATION_18: - snd_iprintf(buffer, " attenuation: -18 dB\n"); - break; - } - snd_iprintf(buffer, " volume left: %u\n", rme96->vol[0]); - snd_iprintf(buffer, " volume right: %u\n", rme96->vol[1]); - } -} - -static void __devinit -snd_rme96_proc_init(struct rme96 *rme96) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(rme96->card, "rme96", &entry)) - snd_info_set_text_ops(entry, rme96, snd_rme96_proc_read); -} - -/* - * control interface - */ - -#define snd_rme96_info_loopback_control snd_ctl_boolean_mono_info - -static int -snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme96->lock); - ucontrol->value.integer.value[0] = rme96->wcreg & RME96_WCR_SEL ? 0 : 1; - spin_unlock_irq(&rme96->lock); - return 0; -} -static int -snd_rme96_put_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ucontrol->value.integer.value[0] ? 0 : RME96_WCR_SEL; - spin_lock_irq(&rme96->lock); - val = (rme96->wcreg & ~RME96_WCR_SEL) | val; - change = val != rme96->wcreg; - rme96->wcreg = val; - writel(val, rme96->iobase + RME96_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme96->lock); - return change; -} - -static int -snd_rme96_info_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *_texts[5] = { "Optical", "Coaxial", "Internal", "XLR", "Analog" }; - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - char *texts[5] = { _texts[0], _texts[1], _texts[2], _texts[3], _texts[4] }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - switch (rme96->pci->device) { - case PCI_DEVICE_ID_RME_DIGI96: - case PCI_DEVICE_ID_RME_DIGI96_8: - uinfo->value.enumerated.items = 3; - break; - case PCI_DEVICE_ID_RME_DIGI96_8_PRO: - uinfo->value.enumerated.items = 4; - break; - case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: - if (rme96->rev > 4) { - /* PST */ - uinfo->value.enumerated.items = 4; - texts[3] = _texts[4]; /* Analog instead of XLR */ - } else { - /* PAD */ - uinfo->value.enumerated.items = 5; - } - break; - default: - snd_BUG(); - break; - } - if (uinfo->value.enumerated.item > uinfo->value.enumerated.items - 1) { - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - } - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} -static int -snd_rme96_get_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - unsigned int items = 3; - - spin_lock_irq(&rme96->lock); - ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96); - - switch (rme96->pci->device) { - case PCI_DEVICE_ID_RME_DIGI96: - case PCI_DEVICE_ID_RME_DIGI96_8: - items = 3; - break; - case PCI_DEVICE_ID_RME_DIGI96_8_PRO: - items = 4; - break; - case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: - if (rme96->rev > 4) { - /* for handling PST case, (INPUT_ANALOG is moved to INPUT_XLR */ - if (ucontrol->value.enumerated.item[0] == RME96_INPUT_ANALOG) { - ucontrol->value.enumerated.item[0] = RME96_INPUT_XLR; - } - items = 4; - } else { - items = 5; - } - break; - default: - snd_BUG(); - break; - } - if (ucontrol->value.enumerated.item[0] >= items) { - ucontrol->value.enumerated.item[0] = items - 1; - } - - spin_unlock_irq(&rme96->lock); - return 0; -} -static int -snd_rme96_put_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change, items = 3; - - switch (rme96->pci->device) { - case PCI_DEVICE_ID_RME_DIGI96: - case PCI_DEVICE_ID_RME_DIGI96_8: - items = 3; - break; - case PCI_DEVICE_ID_RME_DIGI96_8_PRO: - items = 4; - break; - case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: - if (rme96->rev > 4) { - items = 4; - } else { - items = 5; - } - break; - default: - snd_BUG(); - break; - } - val = ucontrol->value.enumerated.item[0] % items; - - /* special case for PST */ - if (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && rme96->rev > 4) { - if (val == RME96_INPUT_XLR) { - val = RME96_INPUT_ANALOG; - } - } - - spin_lock_irq(&rme96->lock); - change = (int)val != snd_rme96_getinputtype(rme96); - snd_rme96_setinputtype(rme96, val); - spin_unlock_irq(&rme96->lock); - return change; -} - -static int -snd_rme96_info_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { "AutoSync", "Internal", "Word" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) { - uinfo->value.enumerated.item = 2; - } - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} -static int -snd_rme96_get_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme96->lock); - ucontrol->value.enumerated.item[0] = snd_rme96_getclockmode(rme96); - spin_unlock_irq(&rme96->lock); - return 0; -} -static int -snd_rme96_put_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&rme96->lock); - change = (int)val != snd_rme96_getclockmode(rme96); - snd_rme96_setclockmode(rme96, val); - spin_unlock_irq(&rme96->lock); - return change; -} - -static int -snd_rme96_info_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { "0 dB", "-6 dB", "-12 dB", "-18 dB" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) { - uinfo->value.enumerated.item = 3; - } - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} -static int -snd_rme96_get_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme96->lock); - ucontrol->value.enumerated.item[0] = snd_rme96_getattenuation(rme96); - spin_unlock_irq(&rme96->lock); - return 0; -} -static int -snd_rme96_put_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ucontrol->value.enumerated.item[0] % 4; - spin_lock_irq(&rme96->lock); - - change = (int)val != snd_rme96_getattenuation(rme96); - snd_rme96_setattenuation(rme96, val); - spin_unlock_irq(&rme96->lock); - return change; -} - -static int -snd_rme96_info_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { "1+2", "3+4", "5+6", "7+8" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) { - uinfo->value.enumerated.item = 3; - } - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} -static int -snd_rme96_get_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme96->lock); - ucontrol->value.enumerated.item[0] = snd_rme96_getmontracks(rme96); - spin_unlock_irq(&rme96->lock); - return 0; -} -static int -snd_rme96_put_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ucontrol->value.enumerated.item[0] % 4; - spin_lock_irq(&rme96->lock); - change = (int)val != snd_rme96_getmontracks(rme96); - snd_rme96_setmontracks(rme96, val); - spin_unlock_irq(&rme96->lock); - return change; -} - -static u32 snd_rme96_convert_from_aes(struct snd_aes_iec958 *aes) -{ - u32 val = 0; - val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME96_WCR_PRO : 0; - val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? RME96_WCR_DOLBY : 0; - if (val & RME96_WCR_PRO) - val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME96_WCR_EMP : 0; - else - val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME96_WCR_EMP : 0; - return val; -} - -static void snd_rme96_convert_to_aes(struct snd_aes_iec958 *aes, u32 val) -{ - aes->status[0] = ((val & RME96_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0) | - ((val & RME96_WCR_DOLBY) ? IEC958_AES0_NONAUDIO : 0); - if (val & RME96_WCR_PRO) - aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; - else - aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; -} - -static int snd_rme96_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme96_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - - snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif); - return 0; -} - -static int snd_rme96_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - int change; - u32 val; - - val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme96->lock); - change = val != rme96->wcreg_spdif; - rme96->wcreg_spdif = val; - spin_unlock_irq(&rme96->lock); - return change; -} - -static int snd_rme96_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme96_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - - snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif_stream); - return 0; -} - -static int snd_rme96_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - int change; - u32 val; - - val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme96->lock); - change = val != rme96->wcreg_spdif_stream; - rme96->wcreg_spdif_stream = val; - rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); - rme96->wcreg |= val; - writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); - spin_unlock_irq(&rme96->lock); - return change; -} - -static int snd_rme96_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme96_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = kcontrol->private_value; - return 0; -} - -static int -snd_rme96_dac_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = RME96_185X_MAX_OUT(rme96); - return 0; -} - -static int -snd_rme96_dac_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme96->lock); - u->value.integer.value[0] = rme96->vol[0]; - u->value.integer.value[1] = rme96->vol[1]; - spin_unlock_irq(&rme96->lock); - - return 0; -} - -static int -snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u) -{ - struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); - int change = 0; - unsigned int vol, maxvol; - - - if (!RME96_HAS_ANALOG_OUT(rme96)) - return -EINVAL; - maxvol = RME96_185X_MAX_OUT(rme96); - spin_lock_irq(&rme96->lock); - vol = u->value.integer.value[0]; - if (vol != rme96->vol[0] && vol <= maxvol) { - rme96->vol[0] = vol; - change = 1; - } - vol = u->value.integer.value[1]; - if (vol != rme96->vol[1] && vol <= maxvol) { - rme96->vol[1] = vol; - change = 1; - } - if (change) - snd_rme96_apply_dac_volume(rme96); - spin_unlock_irq(&rme96->lock); - - return change; -} - -static struct snd_kcontrol_new snd_rme96_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_rme96_control_spdif_info, - .get = snd_rme96_control_spdif_get, - .put = snd_rme96_control_spdif_put -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_rme96_control_spdif_stream_info, - .get = snd_rme96_control_spdif_stream_get, - .put = snd_rme96_control_spdif_stream_put -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), - .info = snd_rme96_control_spdif_mask_info, - .get = snd_rme96_control_spdif_mask_get, - .private_value = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_CON_EMPHASIS -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), - .info = snd_rme96_control_spdif_mask_info, - .get = snd_rme96_control_spdif_mask_get, - .private_value = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_PRO_EMPHASIS -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Connector", - .info = snd_rme96_info_inputtype_control, - .get = snd_rme96_get_inputtype_control, - .put = snd_rme96_put_inputtype_control -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Loopback Input", - .info = snd_rme96_info_loopback_control, - .get = snd_rme96_get_loopback_control, - .put = snd_rme96_put_loopback_control -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Sample Clock Source", - .info = snd_rme96_info_clockmode_control, - .get = snd_rme96_get_clockmode_control, - .put = snd_rme96_put_clockmode_control -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Monitor Tracks", - .info = snd_rme96_info_montracks_control, - .get = snd_rme96_get_montracks_control, - .put = snd_rme96_put_montracks_control -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Attenuation", - .info = snd_rme96_info_attenuation_control, - .get = snd_rme96_get_attenuation_control, - .put = snd_rme96_put_attenuation_control -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Playback Volume", - .info = snd_rme96_dac_volume_info, - .get = snd_rme96_dac_volume_get, - .put = snd_rme96_dac_volume_put -} -}; - -static int -snd_rme96_create_switches(struct snd_card *card, - struct rme96 *rme96) -{ - int idx, err; - struct snd_kcontrol *kctl; - - for (idx = 0; idx < 7; idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme96_controls[idx], rme96))) < 0) - return err; - if (idx == 1) /* IEC958 (S/PDIF) Stream */ - rme96->spdif_ctl = kctl; - } - - if (RME96_HAS_ANALOG_OUT(rme96)) { - for (idx = 7; idx < 10; idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_rme96_controls[idx], rme96))) < 0) - return err; - } - - return 0; -} - -/* - * Card initialisation - */ - -static void snd_rme96_card_free(struct snd_card *card) -{ - snd_rme96_free(card->private_data); -} - -static int __devinit -snd_rme96_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct rme96 *rme96; - struct snd_card *card; - int err; - u8 val; - - if (dev >= SNDRV_CARDS) { - return -ENODEV; - } - if (!enable[dev]) { - dev++; - return -ENOENT; - } - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct rme96), &card); - if (err < 0) - return err; - card->private_free = snd_rme96_card_free; - rme96 = card->private_data; - rme96->card = card; - rme96->pci = pci; - snd_card_set_dev(card, &pci->dev); - if ((err = snd_rme96_create(rme96)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "Digi96"); - switch (rme96->pci->device) { - case PCI_DEVICE_ID_RME_DIGI96: - strcpy(card->shortname, "RME Digi96"); - break; - case PCI_DEVICE_ID_RME_DIGI96_8: - strcpy(card->shortname, "RME Digi96/8"); - break; - case PCI_DEVICE_ID_RME_DIGI96_8_PRO: - strcpy(card->shortname, "RME Digi96/8 PRO"); - break; - case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: - pci_read_config_byte(rme96->pci, 8, &val); - if (val < 5) { - strcpy(card->shortname, "RME Digi96/8 PAD"); - } else { - strcpy(card->shortname, "RME Digi96/8 PST"); - } - break; - } - sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, - rme96->port, rme96->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_rme96_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_rme96_ids, - .probe = snd_rme96_probe, - .remove = __devexit_p(snd_rme96_remove), -}; - -static int __init alsa_card_rme96_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_rme96_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_rme96_init) -module_exit(alsa_card_rme96_exit) diff --git a/ANDROID_3.4.5/sound/pci/rme9652/Makefile b/ANDROID_3.4.5/sound/pci/rme9652/Makefile deleted file mode 100644 index dcba5604..00000000 --- a/ANDROID_3.4.5/sound/pci/rme9652/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-rme9652-objs := rme9652.o -snd-hdsp-objs := hdsp.o -snd-hdspm-objs := hdspm.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_RME9652) += snd-rme9652.o -obj-$(CONFIG_SND_HDSP) += snd-hdsp.o -obj-$(CONFIG_SND_HDSPM) +=snd-hdspm.o diff --git a/ANDROID_3.4.5/sound/pci/rme9652/hdsp.c b/ANDROID_3.4.5/sound/pci/rme9652/hdsp.c deleted file mode 100644 index 0b2aea2c..00000000 --- a/ANDROID_3.4.5/sound/pci/rme9652/hdsp.c +++ /dev/null @@ -1,5657 +0,0 @@ -/* - * ALSA driver for RME Hammerfall DSP audio interface(s) - * - * Copyright (c) 2002 Paul Davis - * Marcus Andersson - * Thomas Charbonnel - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards."); -MODULE_AUTHOR("Paul Davis , Marcus Andersson, Thomas Charbonnel "); -MODULE_DESCRIPTION("RME Hammerfall DSP"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," - "{RME HDSP-9652}," - "{RME HDSP-9632}}"); -#ifdef HDSP_FW_LOADER -MODULE_FIRMWARE("rpm_firmware.bin"); -MODULE_FIRMWARE("multiface_firmware.bin"); -MODULE_FIRMWARE("multiface_firmware_rev11.bin"); -MODULE_FIRMWARE("digiface_firmware.bin"); -MODULE_FIRMWARE("digiface_firmware_rev11.bin"); -#endif - -#define HDSP_MAX_CHANNELS 26 -#define HDSP_MAX_DS_CHANNELS 14 -#define HDSP_MAX_QS_CHANNELS 8 -#define DIGIFACE_SS_CHANNELS 26 -#define DIGIFACE_DS_CHANNELS 14 -#define MULTIFACE_SS_CHANNELS 18 -#define MULTIFACE_DS_CHANNELS 14 -#define H9652_SS_CHANNELS 26 -#define H9652_DS_CHANNELS 14 -/* This does not include possible Analog Extension Boards - AEBs are detected at card initialization -*/ -#define H9632_SS_CHANNELS 12 -#define H9632_DS_CHANNELS 8 -#define H9632_QS_CHANNELS 4 -#define RPM_CHANNELS 6 - -/* Write registers. These are defined as byte-offsets from the iobase value. - */ -#define HDSP_resetPointer 0 -#define HDSP_freqReg 0 -#define HDSP_outputBufferAddress 32 -#define HDSP_inputBufferAddress 36 -#define HDSP_controlRegister 64 -#define HDSP_interruptConfirmation 96 -#define HDSP_outputEnable 128 -#define HDSP_control2Reg 256 -#define HDSP_midiDataOut0 352 -#define HDSP_midiDataOut1 356 -#define HDSP_fifoData 368 -#define HDSP_inputEnable 384 - -/* Read registers. These are defined as byte-offsets from the iobase value - */ - -#define HDSP_statusRegister 0 -#define HDSP_timecode 128 -#define HDSP_status2Register 192 -#define HDSP_midiDataIn0 360 -#define HDSP_midiDataIn1 364 -#define HDSP_midiStatusOut0 384 -#define HDSP_midiStatusOut1 388 -#define HDSP_midiStatusIn0 392 -#define HDSP_midiStatusIn1 396 -#define HDSP_fifoStatus 400 - -/* the meters are regular i/o-mapped registers, but offset - considerably from the rest. the peak registers are reset - when read; the least-significant 4 bits are full-scale counters; - the actual peak value is in the most-significant 24 bits. -*/ - -#define HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */ -#define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */ -#define HDSP_outputPeakLevel 4352 /* (26+2) * 32 bit values */ -#define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */ -#define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */ - - -/* This is for H9652 cards - Peak values are read downward from the base - Rms values are read upward - There are rms values for the outputs too - 26*3 values are read in ss mode - 14*3 in ds mode, with no gap between values -*/ -#define HDSP_9652_peakBase 7164 -#define HDSP_9652_rmsBase 4096 - -/* c.f. the hdsp_9632_meters_t struct */ -#define HDSP_9632_metersBase 4096 - -#define HDSP_IO_EXTENT 7168 - -/* control2 register bits */ - -#define HDSP_TMS 0x01 -#define HDSP_TCK 0x02 -#define HDSP_TDI 0x04 -#define HDSP_JTAG 0x08 -#define HDSP_PWDN 0x10 -#define HDSP_PROGRAM 0x020 -#define HDSP_CONFIG_MODE_0 0x040 -#define HDSP_CONFIG_MODE_1 0x080 -#define HDSP_VERSION_BIT (0x100 | HDSP_S_LOAD) -#define HDSP_BIGENDIAN_MODE 0x200 -#define HDSP_RD_MULTIPLE 0x400 -#define HDSP_9652_ENABLE_MIXER 0x800 -#define HDSP_TDO 0x10000000 - -#define HDSP_S_PROGRAM (HDSP_PROGRAM|HDSP_CONFIG_MODE_0) -#define HDSP_S_LOAD (HDSP_PROGRAM|HDSP_CONFIG_MODE_1) - -/* Control Register bits */ - -#define HDSP_Start (1<<0) /* start engine */ -#define HDSP_Latency0 (1<<1) /* buffer size = 2^n where n is defined by Latency{2,1,0} */ -#define HDSP_Latency1 (1<<2) /* [ see above ] */ -#define HDSP_Latency2 (1<<3) /* [ see above ] */ -#define HDSP_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */ -#define HDSP_AudioInterruptEnable (1<<5) /* what do you think ? */ -#define HDSP_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz/176.4kHz 1=48kHz/96kHz/192kHz */ -#define HDSP_Frequency1 (1<<7) /* 0=32kHz/64kHz/128kHz */ -#define HDSP_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */ -#define HDSP_SPDIFProfessional (1<<9) /* 0=consumer, 1=professional */ -#define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */ -#define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */ -#define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */ -#define HDSP_SyncRef2 (1<<13) -#define HDSP_SPDIFInputSelect0 (1<<14) -#define HDSP_SPDIFInputSelect1 (1<<15) -#define HDSP_SyncRef0 (1<<16) -#define HDSP_SyncRef1 (1<<17) -#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */ -#define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */ -#define HDSP_Midi0InterruptEnable (1<<22) -#define HDSP_Midi1InterruptEnable (1<<23) -#define HDSP_LineOut (1<<24) -#define HDSP_ADGain0 (1<<25) /* From here : H9632 specific */ -#define HDSP_ADGain1 (1<<26) -#define HDSP_DAGain0 (1<<27) -#define HDSP_DAGain1 (1<<28) -#define HDSP_PhoneGain0 (1<<29) -#define HDSP_PhoneGain1 (1<<30) -#define HDSP_QuadSpeed (1<<31) - -/* RPM uses some of the registers for special purposes */ -#define HDSP_RPM_Inp12 0x04A00 -#define HDSP_RPM_Inp12_Phon_6dB 0x00800 /* Dolby */ -#define HDSP_RPM_Inp12_Phon_0dB 0x00000 /* .. */ -#define HDSP_RPM_Inp12_Phon_n6dB 0x04000 /* inp_0 */ -#define HDSP_RPM_Inp12_Line_0dB 0x04200 /* Dolby+PRO */ -#define HDSP_RPM_Inp12_Line_n6dB 0x00200 /* PRO */ - -#define HDSP_RPM_Inp34 0x32000 -#define HDSP_RPM_Inp34_Phon_6dB 0x20000 /* SyncRef1 */ -#define HDSP_RPM_Inp34_Phon_0dB 0x00000 /* .. */ -#define HDSP_RPM_Inp34_Phon_n6dB 0x02000 /* SyncRef2 */ -#define HDSP_RPM_Inp34_Line_0dB 0x30000 /* SyncRef1+SyncRef0 */ -#define HDSP_RPM_Inp34_Line_n6dB 0x10000 /* SyncRef0 */ - -#define HDSP_RPM_Bypass 0x01000 - -#define HDSP_RPM_Disconnect 0x00001 - -#define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1) -#define HDSP_ADGainMinus10dBV HDSP_ADGainMask -#define HDSP_ADGainPlus4dBu (HDSP_ADGain0) -#define HDSP_ADGainLowGain 0 - -#define HDSP_DAGainMask (HDSP_DAGain0|HDSP_DAGain1) -#define HDSP_DAGainHighGain HDSP_DAGainMask -#define HDSP_DAGainPlus4dBu (HDSP_DAGain0) -#define HDSP_DAGainMinus10dBV 0 - -#define HDSP_PhoneGainMask (HDSP_PhoneGain0|HDSP_PhoneGain1) -#define HDSP_PhoneGain0dB HDSP_PhoneGainMask -#define HDSP_PhoneGainMinus6dB (HDSP_PhoneGain0) -#define HDSP_PhoneGainMinus12dB 0 - -#define HDSP_LatencyMask (HDSP_Latency0|HDSP_Latency1|HDSP_Latency2) -#define HDSP_FrequencyMask (HDSP_Frequency0|HDSP_Frequency1|HDSP_DoubleSpeed|HDSP_QuadSpeed) - -#define HDSP_SPDIFInputMask (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1) -#define HDSP_SPDIFInputADAT1 0 -#define HDSP_SPDIFInputCoaxial (HDSP_SPDIFInputSelect0) -#define HDSP_SPDIFInputCdrom (HDSP_SPDIFInputSelect1) -#define HDSP_SPDIFInputAES (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1) - -#define HDSP_SyncRefMask (HDSP_SyncRef0|HDSP_SyncRef1|HDSP_SyncRef2) -#define HDSP_SyncRef_ADAT1 0 -#define HDSP_SyncRef_ADAT2 (HDSP_SyncRef0) -#define HDSP_SyncRef_ADAT3 (HDSP_SyncRef1) -#define HDSP_SyncRef_SPDIF (HDSP_SyncRef0|HDSP_SyncRef1) -#define HDSP_SyncRef_WORD (HDSP_SyncRef2) -#define HDSP_SyncRef_ADAT_SYNC (HDSP_SyncRef0|HDSP_SyncRef2) - -/* Sample Clock Sources */ - -#define HDSP_CLOCK_SOURCE_AUTOSYNC 0 -#define HDSP_CLOCK_SOURCE_INTERNAL_32KHZ 1 -#define HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ 2 -#define HDSP_CLOCK_SOURCE_INTERNAL_48KHZ 3 -#define HDSP_CLOCK_SOURCE_INTERNAL_64KHZ 4 -#define HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ 5 -#define HDSP_CLOCK_SOURCE_INTERNAL_96KHZ 6 -#define HDSP_CLOCK_SOURCE_INTERNAL_128KHZ 7 -#define HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ 8 -#define HDSP_CLOCK_SOURCE_INTERNAL_192KHZ 9 - -/* Preferred sync reference choices - used by "pref_sync_ref" control switch */ - -#define HDSP_SYNC_FROM_WORD 0 -#define HDSP_SYNC_FROM_SPDIF 1 -#define HDSP_SYNC_FROM_ADAT1 2 -#define HDSP_SYNC_FROM_ADAT_SYNC 3 -#define HDSP_SYNC_FROM_ADAT2 4 -#define HDSP_SYNC_FROM_ADAT3 5 - -/* SyncCheck status */ - -#define HDSP_SYNC_CHECK_NO_LOCK 0 -#define HDSP_SYNC_CHECK_LOCK 1 -#define HDSP_SYNC_CHECK_SYNC 2 - -/* AutoSync references - used by "autosync_ref" control switch */ - -#define HDSP_AUTOSYNC_FROM_WORD 0 -#define HDSP_AUTOSYNC_FROM_ADAT_SYNC 1 -#define HDSP_AUTOSYNC_FROM_SPDIF 2 -#define HDSP_AUTOSYNC_FROM_NONE 3 -#define HDSP_AUTOSYNC_FROM_ADAT1 4 -#define HDSP_AUTOSYNC_FROM_ADAT2 5 -#define HDSP_AUTOSYNC_FROM_ADAT3 6 - -/* Possible sources of S/PDIF input */ - -#define HDSP_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */ -#define HDSP_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */ -#define HDSP_SPDIFIN_INTERNAL 2 /* internal (CDROM) */ -#define HDSP_SPDIFIN_AES 3 /* xlr for H9632 (AES)*/ - -#define HDSP_Frequency32KHz HDSP_Frequency0 -#define HDSP_Frequency44_1KHz HDSP_Frequency1 -#define HDSP_Frequency48KHz (HDSP_Frequency1|HDSP_Frequency0) -#define HDSP_Frequency64KHz (HDSP_DoubleSpeed|HDSP_Frequency0) -#define HDSP_Frequency88_2KHz (HDSP_DoubleSpeed|HDSP_Frequency1) -#define HDSP_Frequency96KHz (HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) -/* For H9632 cards */ -#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0) -#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1) -#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) -/* RME says n = 104857600000000, but in the windows MADI driver, I see: - return 104857600000000 / rate; // 100 MHz - return 110100480000000 / rate; // 105 MHz -*/ -#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */ - -#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask) -#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1) - -#define hdsp_encode_spdif_in(x) (((x)&0x3)<<14) -#define hdsp_decode_spdif_in(x) (((x)>>14)&0x3) - -/* Status Register bits */ - -#define HDSP_audioIRQPending (1<<0) -#define HDSP_Lock2 (1<<1) /* this is for Digiface and H9652 */ -#define HDSP_spdifFrequency3 HDSP_Lock2 /* this is for H9632 only */ -#define HDSP_Lock1 (1<<2) -#define HDSP_Lock0 (1<<3) -#define HDSP_SPDIFSync (1<<4) -#define HDSP_TimecodeLock (1<<5) -#define HDSP_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ -#define HDSP_Sync2 (1<<16) -#define HDSP_Sync1 (1<<17) -#define HDSP_Sync0 (1<<18) -#define HDSP_DoubleSpeedStatus (1<<19) -#define HDSP_ConfigError (1<<20) -#define HDSP_DllError (1<<21) -#define HDSP_spdifFrequency0 (1<<22) -#define HDSP_spdifFrequency1 (1<<23) -#define HDSP_spdifFrequency2 (1<<24) -#define HDSP_SPDIFErrorFlag (1<<25) -#define HDSP_BufferID (1<<26) -#define HDSP_TimecodeSync (1<<27) -#define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */ -#define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */ -#define HDSP_midi0IRQPending (1<<30) -#define HDSP_midi1IRQPending (1<<31) - -#define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2) -#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\ - HDSP_spdifFrequency1|\ - HDSP_spdifFrequency2|\ - HDSP_spdifFrequency3) - -#define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0) -#define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1) -#define HDSP_spdifFrequency48KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency1) - -#define HDSP_spdifFrequency64KHz (HDSP_spdifFrequency2) -#define HDSP_spdifFrequency88_2KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency2) -#define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1) - -/* This is for H9632 cards */ -#define HDSP_spdifFrequency128KHz (HDSP_spdifFrequency0|\ - HDSP_spdifFrequency1|\ - HDSP_spdifFrequency2) -#define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3 -#define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0) - -/* Status2 Register bits */ - -#define HDSP_version0 (1<<0) -#define HDSP_version1 (1<<1) -#define HDSP_version2 (1<<2) -#define HDSP_wc_lock (1<<3) -#define HDSP_wc_sync (1<<4) -#define HDSP_inp_freq0 (1<<5) -#define HDSP_inp_freq1 (1<<6) -#define HDSP_inp_freq2 (1<<7) -#define HDSP_SelSyncRef0 (1<<8) -#define HDSP_SelSyncRef1 (1<<9) -#define HDSP_SelSyncRef2 (1<<10) - -#define HDSP_wc_valid (HDSP_wc_lock|HDSP_wc_sync) - -#define HDSP_systemFrequencyMask (HDSP_inp_freq0|HDSP_inp_freq1|HDSP_inp_freq2) -#define HDSP_systemFrequency32 (HDSP_inp_freq0) -#define HDSP_systemFrequency44_1 (HDSP_inp_freq1) -#define HDSP_systemFrequency48 (HDSP_inp_freq0|HDSP_inp_freq1) -#define HDSP_systemFrequency64 (HDSP_inp_freq2) -#define HDSP_systemFrequency88_2 (HDSP_inp_freq0|HDSP_inp_freq2) -#define HDSP_systemFrequency96 (HDSP_inp_freq1|HDSP_inp_freq2) -/* FIXME : more values for 9632 cards ? */ - -#define HDSP_SelSyncRefMask (HDSP_SelSyncRef0|HDSP_SelSyncRef1|HDSP_SelSyncRef2) -#define HDSP_SelSyncRef_ADAT1 0 -#define HDSP_SelSyncRef_ADAT2 (HDSP_SelSyncRef0) -#define HDSP_SelSyncRef_ADAT3 (HDSP_SelSyncRef1) -#define HDSP_SelSyncRef_SPDIF (HDSP_SelSyncRef0|HDSP_SelSyncRef1) -#define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2) -#define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2) - -/* Card state flags */ - -#define HDSP_InitializationComplete (1<<0) -#define HDSP_FirmwareLoaded (1<<1) -#define HDSP_FirmwareCached (1<<2) - -/* FIFO wait times, defined in terms of 1/10ths of msecs */ - -#define HDSP_LONG_WAIT 5000 -#define HDSP_SHORT_WAIT 30 - -#define UNITY_GAIN 32768 -#define MINUS_INFINITY_GAIN 0 - -/* the size of a substream (1 mono data stream) */ - -#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024) -#define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES) - -/* the size of the area we need to allocate for DMA transfers. the - size is the same regardless of the number of channels - the - Multiface still uses the same memory area. - - Note that we allocate 1 more channel than is apparently needed - because the h/w seems to write 1 byte beyond the end of the last - page. Sigh. -*/ - -#define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES) -#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024) - -/* use hotplug firmware loader? */ -#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) -#if !defined(HDSP_USE_HWDEP_LOADER) -#define HDSP_FW_LOADER -#endif -#endif - -struct hdsp_9632_meters { - u32 input_peak[16]; - u32 playback_peak[16]; - u32 output_peak[16]; - u32 xxx_peak[16]; - u32 padding[64]; - u32 input_rms_low[16]; - u32 playback_rms_low[16]; - u32 output_rms_low[16]; - u32 xxx_rms_low[16]; - u32 input_rms_high[16]; - u32 playback_rms_high[16]; - u32 output_rms_high[16]; - u32 xxx_rms_high[16]; -}; - -struct hdsp_midi { - struct hdsp *hdsp; - int id; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *input; - struct snd_rawmidi_substream *output; - char istimer; /* timer in use */ - struct timer_list timer; - spinlock_t lock; - int pending; -}; - -struct hdsp { - spinlock_t lock; - struct snd_pcm_substream *capture_substream; - struct snd_pcm_substream *playback_substream; - struct hdsp_midi midi[2]; - struct tasklet_struct midi_tasklet; - int use_midi_tasklet; - int precise_ptr; - u32 control_register; /* cached value */ - u32 control2_register; /* cached value */ - u32 creg_spdif; - u32 creg_spdif_stream; - int clock_source_locked; - char *card_name; /* digiface/multiface/rpm */ - enum HDSP_IO_Type io_type; /* ditto, but for code use */ - unsigned short firmware_rev; - unsigned short state; /* stores state bits */ - u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */ - size_t period_bytes; /* guess what this is */ - unsigned char max_channels; - unsigned char qs_in_channels; /* quad speed mode for H9632 */ - unsigned char ds_in_channels; - unsigned char ss_in_channels; /* different for multiface/digiface */ - unsigned char qs_out_channels; - unsigned char ds_out_channels; - unsigned char ss_out_channels; - - struct snd_dma_buffer capture_dma_buf; - struct snd_dma_buffer playback_dma_buf; - unsigned char *capture_buffer; /* suitably aligned address */ - unsigned char *playback_buffer; /* suitably aligned address */ - - pid_t capture_pid; - pid_t playback_pid; - int running; - int system_sample_rate; - char *channel_map; - int dev; - int irq; - unsigned long port; - void __iomem *iobase; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_hwdep *hwdep; - struct pci_dev *pci; - struct snd_kcontrol *spdif_ctl; - unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE]; - unsigned int dds_value; /* last value written to freq register */ -}; - -/* These tables map the ALSA channels 1..N to the channels that we - need to use in order to find the relevant channel buffer. RME - refer to this kind of mapping as between "the ADAT channel and - the DMA channel." We index it using the logical audio channel, - and the value is the DMA channel (i.e. channel buffer number) - where the data for that channel can be read/written from/to. -*/ - -static char channel_map_df_ss[HDSP_MAX_CHANNELS] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25 -}; - -static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */ - /* Analog */ - 0, 1, 2, 3, 4, 5, 6, 7, - /* ADAT 2 */ - 16, 17, 18, 19, 20, 21, 22, 23, - /* SPDIF */ - 24, 25, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_ds[HDSP_MAX_CHANNELS] = { - /* ADAT channels are remapped */ - 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, - /* channels 12 and 13 are S/PDIF */ - 24, 25, - /* others don't exist */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { - /* ADAT channels */ - 0, 1, 2, 3, 4, 5, 6, 7, - /* SPDIF */ - 8, 9, - /* Analog */ - 10, 11, - /* AO4S-192 and AI4S-192 extension boards */ - 12, 13, 14, 15, - /* others don't exist */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1 -}; - -static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { - /* ADAT */ - 1, 3, 5, 7, - /* SPDIF */ - 8, 9, - /* Analog */ - 10, 11, - /* AO4S-192 and AI4S-192 extension boards */ - 12, 13, 14, 15, - /* others don't exist */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = { - /* ADAT is disabled in this mode */ - /* SPDIF */ - 8, 9, - /* Analog */ - 10, 11, - /* AO4S-192 and AI4S-192 extension boards */ - 12, 13, 14, 15, - /* others don't exist */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1 -}; - -static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size) -{ - dmab->dev.type = SNDRV_DMA_TYPE_DEV; - dmab->dev.dev = snd_dma_pci_data(pci); - if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { - if (dmab->bytes >= size) - return 0; - } - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, dmab) < 0) - return -ENOMEM; - return 0; -} - -static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) -{ - if (dmab->area) { - dmab->dev.dev = NULL; /* make it anonymous */ - snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); - } -} - - -static DEFINE_PCI_DEVICE_TABLE(snd_hdsp_ids) = { - { - .vendor = PCI_VENDOR_ID_XILINX, - .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, /* RME Hammerfall-DSP */ - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, snd_hdsp_ids); - -/* prototypes */ -static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp); -static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp); -static int snd_hdsp_enable_io (struct hdsp *hdsp); -static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp); -static void snd_hdsp_initialize_channels (struct hdsp *hdsp); -static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout); -static int hdsp_autosync_ref(struct hdsp *hdsp); -static int snd_hdsp_set_defaults(struct hdsp *hdsp); -static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp); - -static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out) -{ - switch (hdsp->io_type) { - case Multiface: - case Digiface: - case RPM: - default: - if (hdsp->firmware_rev == 0xa) - return (64 * out) + (32 + (in)); - else - return (52 * out) + (26 + (in)); - case H9632: - return (32 * out) + (16 + (in)); - case H9652: - return (52 * out) + (26 + (in)); - } -} - -static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out) -{ - switch (hdsp->io_type) { - case Multiface: - case Digiface: - case RPM: - default: - if (hdsp->firmware_rev == 0xa) - return (64 * out) + in; - else - return (52 * out) + in; - case H9632: - return (32 * out) + in; - case H9652: - return (52 * out) + in; - } -} - -static void hdsp_write(struct hdsp *hdsp, int reg, int val) -{ - writel(val, hdsp->iobase + reg); -} - -static unsigned int hdsp_read(struct hdsp *hdsp, int reg) -{ - return readl (hdsp->iobase + reg); -} - -static int hdsp_check_for_iobox (struct hdsp *hdsp) -{ - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; - if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) { - snd_printk("Hammerfall-DSP: no IO box connected!\n"); - hdsp->state &= ~HDSP_FirmwareLoaded; - return -EIO; - } - return 0; -} - -static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops, - unsigned int delay) -{ - unsigned int i; - - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) - return 0; - - for (i = 0; i != loops; ++i) { - if (hdsp_read(hdsp, HDSP_statusRegister) & HDSP_ConfigError) - msleep(delay); - else { - snd_printd("Hammerfall-DSP: iobox found after %ums!\n", - i * delay); - return 0; - } - } - - snd_printk("Hammerfall-DSP: no IO box connected!\n"); - hdsp->state &= ~HDSP_FirmwareLoaded; - return -EIO; -} - -static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) { - - int i; - unsigned long flags; - - if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - - snd_printk ("Hammerfall-DSP: loading firmware\n"); - - hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM); - hdsp_write (hdsp, HDSP_fifoData, 0); - - if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n"); - return -EIO; - } - - hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); - - for (i = 0; i < 24413; ++i) { - hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); - if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { - snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); - return -EIO; - } - } - - ssleep(3); - - if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { - snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n"); - return -EIO; - } - -#ifdef SNDRV_BIG_ENDIAN - hdsp->control2_register = HDSP_BIGENDIAN_MODE; -#else - hdsp->control2_register = 0; -#endif - hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); - snd_printk ("Hammerfall-DSP: finished firmware loading\n"); - - } - if (hdsp->state & HDSP_InitializationComplete) { - snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); - spin_lock_irqsave(&hdsp->lock, flags); - snd_hdsp_set_defaults(hdsp); - spin_unlock_irqrestore(&hdsp->lock, flags); - } - - hdsp->state |= HDSP_FirmwareLoaded; - - return 0; -} - -static int hdsp_get_iobox_version (struct hdsp *hdsp) -{ - if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - - hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM); - hdsp_write (hdsp, HDSP_fifoData, 0); - if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) - return -EIO; - - hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); - hdsp_write (hdsp, HDSP_fifoData, 0); - - if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT)) { - hdsp_write(hdsp, HDSP_control2Reg, HDSP_VERSION_BIT); - hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD); - if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT)) - hdsp->io_type = RPM; - else - hdsp->io_type = Multiface; - } else { - hdsp->io_type = Digiface; - } - } else { - /* firmware was already loaded, get iobox type */ - if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2) - hdsp->io_type = RPM; - else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) - hdsp->io_type = Multiface; - else - hdsp->io_type = Digiface; - } - return 0; -} - - -#ifdef HDSP_FW_LOADER -static int hdsp_request_fw_loader(struct hdsp *hdsp); -#endif - -static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) -{ - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) - return 0; - if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - hdsp->state &= ~HDSP_FirmwareLoaded; - if (! load_on_demand) - return -EIO; - snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); - /* try to load firmware */ - if (! (hdsp->state & HDSP_FirmwareCached)) { -#ifdef HDSP_FW_LOADER - if (! hdsp_request_fw_loader(hdsp)) - return 0; -#endif - snd_printk(KERN_ERR - "Hammerfall-DSP: No firmware loaded nor " - "cached, please upload firmware.\n"); - return -EIO; - } - if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk(KERN_ERR - "Hammerfall-DSP: Firmware loading from " - "cache failed, please upload manually.\n"); - return -EIO; - } - } - return 0; -} - - -static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout) -{ - int i; - - /* the fifoStatus registers reports on how many words - are available in the command FIFO. - */ - - for (i = 0; i < timeout; i++) { - - if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count) - return 0; - - /* not very friendly, but we only do this during a firmware - load and changing the mixer, so we just put up with it. - */ - - udelay (100); - } - - snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n", - count, timeout); - return -1; -} - -static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr) -{ - if (addr >= HDSP_MATRIX_MIXER_SIZE) - return 0; - - return hdsp->mixer_matrix[addr]; -} - -static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data) -{ - unsigned int ad; - - if (addr >= HDSP_MATRIX_MIXER_SIZE) - return -1; - - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) { - - /* from martin bjornsen: - - "You can only write dwords to the - mixer memory which contain two - mixer values in the low and high - word. So if you want to change - value 0 you have to read value 1 - from the cache and write both to - the first dword in the mixer - memory." - */ - - if (hdsp->io_type == H9632 && addr >= 512) - return 0; - - if (hdsp->io_type == H9652 && addr >= 1352) - return 0; - - hdsp->mixer_matrix[addr] = data; - - - /* `addr' addresses a 16-bit wide address, but - the address space accessed via hdsp_write - uses byte offsets. put another way, addr - varies from 0 to 1351, but to access the - corresponding memory location, we need - to access 0 to 2703 ... - */ - ad = addr/2; - - hdsp_write (hdsp, 4096 + (ad*4), - (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) + - hdsp->mixer_matrix[addr&0x7fe]); - - return 0; - - } else { - - ad = (addr << 16) + data; - - if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) - return -1; - - hdsp_write (hdsp, HDSP_fifoData, ad); - hdsp->mixer_matrix[addr] = data; - - } - - return 0; -} - -static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp) -{ - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&hdsp->lock, flags); - if ((hdsp->playback_pid != hdsp->capture_pid) && - (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0)) - ret = 0; - spin_unlock_irqrestore(&hdsp->lock, flags); - return ret; -} - -static int hdsp_spdif_sample_rate(struct hdsp *hdsp) -{ - unsigned int status = hdsp_read(hdsp, HDSP_statusRegister); - unsigned int rate_bits = (status & HDSP_spdifFrequencyMask); - - /* For the 9632, the mask is different */ - if (hdsp->io_type == H9632) - rate_bits = (status & HDSP_spdifFrequencyMask_9632); - - if (status & HDSP_SPDIFErrorFlag) - return 0; - - switch (rate_bits) { - case HDSP_spdifFrequency32KHz: return 32000; - case HDSP_spdifFrequency44_1KHz: return 44100; - case HDSP_spdifFrequency48KHz: return 48000; - case HDSP_spdifFrequency64KHz: return 64000; - case HDSP_spdifFrequency88_2KHz: return 88200; - case HDSP_spdifFrequency96KHz: return 96000; - case HDSP_spdifFrequency128KHz: - if (hdsp->io_type == H9632) return 128000; - break; - case HDSP_spdifFrequency176_4KHz: - if (hdsp->io_type == H9632) return 176400; - break; - case HDSP_spdifFrequency192KHz: - if (hdsp->io_type == H9632) return 192000; - break; - default: - break; - } - snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status); - return 0; -} - -static int hdsp_external_sample_rate(struct hdsp *hdsp) -{ - unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register); - unsigned int rate_bits = status2 & HDSP_systemFrequencyMask; - - /* For the 9632 card, there seems to be no bit for indicating external - * sample rate greater than 96kHz. The card reports the corresponding - * single speed. So the best means seems to get spdif rate when - * autosync reference is spdif */ - if (hdsp->io_type == H9632 && - hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF) - return hdsp_spdif_sample_rate(hdsp); - - switch (rate_bits) { - case HDSP_systemFrequency32: return 32000; - case HDSP_systemFrequency44_1: return 44100; - case HDSP_systemFrequency48: return 48000; - case HDSP_systemFrequency64: return 64000; - case HDSP_systemFrequency88_2: return 88200; - case HDSP_systemFrequency96: return 96000; - default: - return 0; - } -} - -static void hdsp_compute_period_size(struct hdsp *hdsp) -{ - hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8)); -} - -static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp) -{ - int position; - - position = hdsp_read(hdsp, HDSP_statusRegister); - - if (!hdsp->precise_ptr) - return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0; - - position &= HDSP_BufferPositionMask; - position /= 4; - position &= (hdsp->period_bytes/2) - 1; - return position; -} - -static void hdsp_reset_hw_pointer(struct hdsp *hdsp) -{ - hdsp_write (hdsp, HDSP_resetPointer, 0); - if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152) - /* HDSP_resetPointer = HDSP_freqReg, which is strange and - * requires (?) to write again DDS value after a reset pointer - * (at least, it works like this) */ - hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value); -} - -static void hdsp_start_audio(struct hdsp *s) -{ - s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start); - hdsp_write(s, HDSP_controlRegister, s->control_register); -} - -static void hdsp_stop_audio(struct hdsp *s) -{ - s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable); - hdsp_write(s, HDSP_controlRegister, s->control_register); -} - -static void hdsp_silence_playback(struct hdsp *hdsp) -{ - memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES); -} - -static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames) -{ - int n; - - spin_lock_irq(&s->lock); - - frames >>= 7; - n = 0; - while (frames) { - n++; - frames >>= 1; - } - - s->control_register &= ~HDSP_LatencyMask; - s->control_register |= hdsp_encode_latency(n); - - hdsp_write(s, HDSP_controlRegister, s->control_register); - - hdsp_compute_period_size(s); - - spin_unlock_irq(&s->lock); - - return 0; -} - -static void hdsp_set_dds_value(struct hdsp *hdsp, int rate) -{ - u64 n; - - if (rate >= 112000) - rate /= 4; - else if (rate >= 56000) - rate /= 2; - - n = DDS_NUMERATOR; - n = div_u64(n, rate); - /* n should be less than 2^32 for being written to FREQ register */ - snd_BUG_ON(n >> 32); - /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS - value to write it after a reset */ - hdsp->dds_value = n; - hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value); -} - -static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) -{ - int reject_if_open = 0; - int current_rate; - int rate_bits; - - /* ASSUMPTION: hdsp->lock is either held, or - there is no need for it (e.g. during module - initialization). - */ - - if (!(hdsp->control_register & HDSP_ClockModeMaster)) { - if (called_internally) { - /* request from ctl or card initialization */ - snd_printk(KERN_ERR "Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); - return -1; - } else { - /* hw_param request while in AutoSync mode */ - int external_freq = hdsp_external_sample_rate(hdsp); - int spdif_freq = hdsp_spdif_sample_rate(hdsp); - - if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) - snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n"); - else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) - snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n"); - else if (rate != external_freq) { - snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n"); - return -1; - } - } - } - - current_rate = hdsp->system_sample_rate; - - /* Changing from a "single speed" to a "double speed" rate is - not allowed if any substreams are open. This is because - such a change causes a shift in the location of - the DMA buffers and a reduction in the number of available - buffers. - - Note that a similar but essentially insoluble problem - exists for externally-driven rate changes. All we can do - is to flag rate changes in the read/write routines. */ - - if (rate > 96000 && hdsp->io_type != H9632) - return -EINVAL; - - switch (rate) { - case 32000: - if (current_rate > 48000) - reject_if_open = 1; - rate_bits = HDSP_Frequency32KHz; - break; - case 44100: - if (current_rate > 48000) - reject_if_open = 1; - rate_bits = HDSP_Frequency44_1KHz; - break; - case 48000: - if (current_rate > 48000) - reject_if_open = 1; - rate_bits = HDSP_Frequency48KHz; - break; - case 64000: - if (current_rate <= 48000 || current_rate > 96000) - reject_if_open = 1; - rate_bits = HDSP_Frequency64KHz; - break; - case 88200: - if (current_rate <= 48000 || current_rate > 96000) - reject_if_open = 1; - rate_bits = HDSP_Frequency88_2KHz; - break; - case 96000: - if (current_rate <= 48000 || current_rate > 96000) - reject_if_open = 1; - rate_bits = HDSP_Frequency96KHz; - break; - case 128000: - if (current_rate < 128000) - reject_if_open = 1; - rate_bits = HDSP_Frequency128KHz; - break; - case 176400: - if (current_rate < 128000) - reject_if_open = 1; - rate_bits = HDSP_Frequency176_4KHz; - break; - case 192000: - if (current_rate < 128000) - reject_if_open = 1; - rate_bits = HDSP_Frequency192KHz; - break; - default: - return -EINVAL; - } - - if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) { - snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n", - hdsp->capture_pid, - hdsp->playback_pid); - return -EBUSY; - } - - hdsp->control_register &= ~HDSP_FrequencyMask; - hdsp->control_register |= rate_bits; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - - /* For HDSP9632 rev 152, need to set DDS value in FREQ register */ - if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152) - hdsp_set_dds_value(hdsp, rate); - - if (rate >= 128000) { - hdsp->channel_map = channel_map_H9632_qs; - } else if (rate > 48000) { - if (hdsp->io_type == H9632) - hdsp->channel_map = channel_map_H9632_ds; - else - hdsp->channel_map = channel_map_ds; - } else { - switch (hdsp->io_type) { - case RPM: - case Multiface: - hdsp->channel_map = channel_map_mf_ss; - break; - case Digiface: - case H9652: - hdsp->channel_map = channel_map_df_ss; - break; - case H9632: - hdsp->channel_map = channel_map_H9632_ss; - break; - default: - /* should never happen */ - break; - } - } - - hdsp->system_sample_rate = rate; - - return 0; -} - -/*---------------------------------------------------------------------------- - MIDI - ----------------------------------------------------------------------------*/ - -static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id) -{ - /* the hardware already does the relevant bit-mask with 0xff */ - if (id) - return hdsp_read(hdsp, HDSP_midiDataIn1); - else - return hdsp_read(hdsp, HDSP_midiDataIn0); -} - -static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val) -{ - /* the hardware already does the relevant bit-mask with 0xff */ - if (id) - hdsp_write(hdsp, HDSP_midiDataOut1, val); - else - hdsp_write(hdsp, HDSP_midiDataOut0, val); -} - -static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id) -{ - if (id) - return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff); - else - return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff); -} - -static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id) -{ - int fifo_bytes_used; - - if (id) - fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff; - else - fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff; - - if (fifo_bytes_used < 128) - return 128 - fifo_bytes_used; - else - return 0; -} - -static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id) -{ - while (snd_hdsp_midi_input_available (hdsp, id)) - snd_hdsp_midi_read_byte (hdsp, id); -} - -static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) -{ - unsigned long flags; - int n_pending; - int to_write; - int i; - unsigned char buf[128]; - - /* Output is not interrupt driven */ - - spin_lock_irqsave (&hmidi->lock, flags); - if (hmidi->output) { - if (!snd_rawmidi_transmit_empty (hmidi->output)) { - if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) { - if (n_pending > (int)sizeof (buf)) - n_pending = sizeof (buf); - - if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { - for (i = 0; i < to_write; ++i) - snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]); - } - } - } - } - spin_unlock_irqrestore (&hmidi->lock, flags); - return 0; -} - -static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi) -{ - unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */ - unsigned long flags; - int n_pending; - int i; - - spin_lock_irqsave (&hmidi->lock, flags); - if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) { - if (hmidi->input) { - if (n_pending > (int)sizeof (buf)) - n_pending = sizeof (buf); - for (i = 0; i < n_pending; ++i) - buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id); - if (n_pending) - snd_rawmidi_receive (hmidi->input, buf, n_pending); - } else { - /* flush the MIDI input FIFO */ - while (--n_pending) - snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id); - } - } - hmidi->pending = 0; - if (hmidi->id) - hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable; - else - hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable; - hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register); - spin_unlock_irqrestore (&hmidi->lock, flags); - return snd_hdsp_midi_output_write (hmidi); -} - -static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct hdsp *hdsp; - struct hdsp_midi *hmidi; - unsigned long flags; - u32 ie; - - hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - hdsp = hmidi->hdsp; - ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable; - spin_lock_irqsave (&hdsp->lock, flags); - if (up) { - if (!(hdsp->control_register & ie)) { - snd_hdsp_flush_midi_input (hdsp, hmidi->id); - hdsp->control_register |= ie; - } - } else { - hdsp->control_register &= ~ie; - tasklet_kill(&hdsp->midi_tasklet); - } - - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - spin_unlock_irqrestore (&hdsp->lock, flags); -} - -static void snd_hdsp_midi_output_timer(unsigned long data) -{ - struct hdsp_midi *hmidi = (struct hdsp_midi *) data; - unsigned long flags; - - snd_hdsp_midi_output_write(hmidi); - spin_lock_irqsave (&hmidi->lock, flags); - - /* this does not bump hmidi->istimer, because the - kernel automatically removed the timer when it - expired, and we are now adding it back, thus - leaving istimer wherever it was set before. - */ - - if (hmidi->istimer) { - hmidi->timer.expires = 1 + jiffies; - add_timer(&hmidi->timer); - } - - spin_unlock_irqrestore (&hmidi->lock, flags); -} - -static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct hdsp_midi *hmidi; - unsigned long flags; - - hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irqsave (&hmidi->lock, flags); - if (up) { - if (!hmidi->istimer) { - init_timer(&hmidi->timer); - hmidi->timer.function = snd_hdsp_midi_output_timer; - hmidi->timer.data = (unsigned long) hmidi; - hmidi->timer.expires = 1 + jiffies; - add_timer(&hmidi->timer); - hmidi->istimer++; - } - } else { - if (hmidi->istimer && --hmidi->istimer <= 0) - del_timer (&hmidi->timer); - } - spin_unlock_irqrestore (&hmidi->lock, flags); - if (up) - snd_hdsp_midi_output_write(hmidi); -} - -static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct hdsp_midi *hmidi; - - hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id); - hmidi->input = substream; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct hdsp_midi *hmidi; - - hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->output = substream; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct hdsp_midi *hmidi; - - snd_hdsp_midi_input_trigger (substream, 0); - - hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->input = NULL; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct hdsp_midi *hmidi; - - snd_hdsp_midi_output_trigger (substream, 0); - - hmidi = (struct hdsp_midi *) substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->output = NULL; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static struct snd_rawmidi_ops snd_hdsp_midi_output = -{ - .open = snd_hdsp_midi_output_open, - .close = snd_hdsp_midi_output_close, - .trigger = snd_hdsp_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_hdsp_midi_input = -{ - .open = snd_hdsp_midi_input_open, - .close = snd_hdsp_midi_input_close, - .trigger = snd_hdsp_midi_input_trigger, -}; - -static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id) -{ - char buf[32]; - - hdsp->midi[id].id = id; - hdsp->midi[id].rmidi = NULL; - hdsp->midi[id].input = NULL; - hdsp->midi[id].output = NULL; - hdsp->midi[id].hdsp = hdsp; - hdsp->midi[id].istimer = 0; - hdsp->midi[id].pending = 0; - spin_lock_init (&hdsp->midi[id].lock); - - sprintf (buf, "%s MIDI %d", card->shortname, id+1); - if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0) - return -1; - - sprintf(hdsp->midi[id].rmidi->name, "HDSP MIDI %d", id+1); - hdsp->midi[id].rmidi->private_data = &hdsp->midi[id]; - - snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output); - snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input); - - hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - return 0; -} - -/*----------------------------------------------------------------------------- - Control Interface - ----------------------------------------------------------------------------*/ - -static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes) -{ - u32 val = 0; - val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0; - val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0; - if (val & HDSP_SPDIFProfessional) - val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0; - else - val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0; - return val; -} - -static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val) -{ - aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) | - ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0); - if (val & HDSP_SPDIFProfessional) - aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; - else - aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; -} - -static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif); - return 0; -} - -static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - u32 val; - - val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&hdsp->lock); - change = val != hdsp->creg_spdif; - hdsp->creg_spdif = val; - spin_unlock_irq(&hdsp->lock); - return change; -} - -static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream); - return 0; -} - -static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - u32 val; - - val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&hdsp->lock); - change = val != hdsp->creg_spdif_stream; - hdsp->creg_spdif_stream = val; - hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis); - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = kcontrol->private_value; - return 0; -} - -#define HDSP_SPDIF_IN(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_spdif_in, \ - .get = snd_hdsp_get_spdif_in, \ - .put = snd_hdsp_put_spdif_in } - -static unsigned int hdsp_spdif_in(struct hdsp *hdsp) -{ - return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask); -} - -static int hdsp_set_spdif_input(struct hdsp *hdsp, int in) -{ - hdsp->control_register &= ~HDSP_SPDIFInputMask; - hdsp->control_register |= hdsp_encode_spdif_in(in); - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"}; - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3); - if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2)) - uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2); - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp); - return 0; -} - -static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3); - spin_lock_irq(&hdsp->lock); - change = val != hdsp_spdif_in(hdsp); - if (change) - hdsp_set_spdif_input(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_SPDIF_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_hdsp_info_spdif_bits, \ - .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out } - -static int hdsp_spdif_out(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0; -} - -static int hdsp_set_spdif_output(struct hdsp *hdsp, int out) -{ - if (out) - hdsp->control_register |= HDSP_SPDIFOpticalOut; - else - hdsp->control_register &= ~HDSP_SPDIFOpticalOut; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -#define snd_hdsp_info_spdif_bits snd_ctl_boolean_mono_info - -static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp); - return 0; -} - -static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_spdif_out(hdsp); - hdsp_set_spdif_output(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_hdsp_info_spdif_bits, \ - .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional } - -static int hdsp_spdif_professional(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0; -} - -static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val) -{ - if (val) - hdsp->control_register |= HDSP_SPDIFProfessional; - else - hdsp->control_register &= ~HDSP_SPDIFProfessional; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp); - return 0; -} - -static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_spdif_professional(hdsp); - hdsp_set_spdif_professional(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_SPDIF_EMPHASIS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_hdsp_info_spdif_bits, \ - .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis } - -static int hdsp_spdif_emphasis(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0; -} - -static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val) -{ - if (val) - hdsp->control_register |= HDSP_SPDIFEmphasis; - else - hdsp->control_register &= ~HDSP_SPDIFEmphasis; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp); - return 0; -} - -static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_spdif_emphasis(hdsp); - hdsp_set_spdif_emphasis(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_hdsp_info_spdif_bits, \ - .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio } - -static int hdsp_spdif_nonaudio(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0; -} - -static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val) -{ - if (val) - hdsp->control_register |= HDSP_SPDIFNonAudio; - else - hdsp->control_register &= ~HDSP_SPDIFNonAudio; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp); - return 0; -} - -static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_spdif_nonaudio(hdsp); - hdsp_set_spdif_nonaudio(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdsp_info_spdif_sample_rate, \ - .get = snd_hdsp_get_spdif_sample_rate \ -} - -static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - switch (hdsp_spdif_sample_rate(hdsp)) { - case 32000: - ucontrol->value.enumerated.item[0] = 0; - break; - case 44100: - ucontrol->value.enumerated.item[0] = 1; - break; - case 48000: - ucontrol->value.enumerated.item[0] = 2; - break; - case 64000: - ucontrol->value.enumerated.item[0] = 3; - break; - case 88200: - ucontrol->value.enumerated.item[0] = 4; - break; - case 96000: - ucontrol->value.enumerated.item[0] = 5; - break; - case 128000: - ucontrol->value.enumerated.item[0] = 7; - break; - case 176400: - ucontrol->value.enumerated.item[0] = 8; - break; - case 192000: - ucontrol->value.enumerated.item[0] = 9; - break; - default: - ucontrol->value.enumerated.item[0] = 6; - } - return 0; -} - -#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdsp_info_system_sample_rate, \ - .get = snd_hdsp_get_system_sample_rate \ -} - -static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - return 0; -} - -static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate; - return 0; -} - -#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdsp_info_autosync_sample_rate, \ - .get = snd_hdsp_get_autosync_sample_rate \ -} - -static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - switch (hdsp_external_sample_rate(hdsp)) { - case 32000: - ucontrol->value.enumerated.item[0] = 0; - break; - case 44100: - ucontrol->value.enumerated.item[0] = 1; - break; - case 48000: - ucontrol->value.enumerated.item[0] = 2; - break; - case 64000: - ucontrol->value.enumerated.item[0] = 3; - break; - case 88200: - ucontrol->value.enumerated.item[0] = 4; - break; - case 96000: - ucontrol->value.enumerated.item[0] = 5; - break; - case 128000: - ucontrol->value.enumerated.item[0] = 7; - break; - case 176400: - ucontrol->value.enumerated.item[0] = 8; - break; - case 192000: - ucontrol->value.enumerated.item[0] = 9; - break; - default: - ucontrol->value.enumerated.item[0] = 6; - } - return 0; -} - -#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdsp_info_system_clock_mode, \ - .get = snd_hdsp_get_system_clock_mode \ -} - -static int hdsp_system_clock_mode(struct hdsp *hdsp) -{ - if (hdsp->control_register & HDSP_ClockModeMaster) - return 0; - else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate) - return 0; - return 1; -} - -static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"Master", "Slave" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp); - return 0; -} - -#define HDSP_CLOCK_SOURCE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_clock_source, \ - .get = snd_hdsp_get_clock_source, \ - .put = snd_hdsp_put_clock_source \ -} - -static int hdsp_clock_source(struct hdsp *hdsp) -{ - if (hdsp->control_register & HDSP_ClockModeMaster) { - switch (hdsp->system_sample_rate) { - case 32000: - return 1; - case 44100: - return 2; - case 48000: - return 3; - case 64000: - return 4; - case 88200: - return 5; - case 96000: - return 6; - case 128000: - return 7; - case 176400: - return 8; - case 192000: - return 9; - default: - return 3; - } - } else { - return 0; - } -} - -static int hdsp_set_clock_source(struct hdsp *hdsp, int mode) -{ - int rate; - switch (mode) { - case HDSP_CLOCK_SOURCE_AUTOSYNC: - if (hdsp_external_sample_rate(hdsp) != 0) { - if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) { - hdsp->control_register &= ~HDSP_ClockModeMaster; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; - } - } - return -1; - case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ: - rate = 32000; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ: - rate = 44100; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ: - rate = 48000; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ: - rate = 64000; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ: - rate = 88200; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ: - rate = 96000; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ: - rate = 128000; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ: - rate = 176400; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ: - rate = 192000; - break; - default: - rate = 48000; - } - hdsp->control_register |= HDSP_ClockModeMaster; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp_set_rate(hdsp, rate, 1); - return 0; -} - -static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" }; - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - if (hdsp->io_type == H9632) - uinfo->value.enumerated.items = 10; - else - uinfo->value.enumerated.items = 7; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp); - return 0; -} - -static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - if (val < 0) val = 0; - if (hdsp->io_type == H9632) { - if (val > 9) - val = 9; - } else { - if (val > 6) - val = 6; - } - spin_lock_irq(&hdsp->lock); - if (val != hdsp_clock_source(hdsp)) - change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info - -static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp->clock_source_locked; - return 0; -} - -static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - - change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked; - if (change) - hdsp->clock_source_locked = !!ucontrol->value.integer.value[0]; - return change; -} - -#define HDSP_DA_GAIN(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_da_gain, \ - .get = snd_hdsp_get_da_gain, \ - .put = snd_hdsp_put_da_gain \ -} - -static int hdsp_da_gain(struct hdsp *hdsp) -{ - switch (hdsp->control_register & HDSP_DAGainMask) { - case HDSP_DAGainHighGain: - return 0; - case HDSP_DAGainPlus4dBu: - return 1; - case HDSP_DAGainMinus10dBV: - return 2; - default: - return 1; - } -} - -static int hdsp_set_da_gain(struct hdsp *hdsp, int mode) -{ - hdsp->control_register &= ~HDSP_DAGainMask; - switch (mode) { - case 0: - hdsp->control_register |= HDSP_DAGainHighGain; - break; - case 1: - hdsp->control_register |= HDSP_DAGainPlus4dBu; - break; - case 2: - hdsp->control_register |= HDSP_DAGainMinus10dBV; - break; - default: - return -1; - - } - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp); - return 0; -} - -static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - if (val < 0) val = 0; - if (val > 2) val = 2; - spin_lock_irq(&hdsp->lock); - if (val != hdsp_da_gain(hdsp)) - change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_AD_GAIN(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_ad_gain, \ - .get = snd_hdsp_get_ad_gain, \ - .put = snd_hdsp_put_ad_gain \ -} - -static int hdsp_ad_gain(struct hdsp *hdsp) -{ - switch (hdsp->control_register & HDSP_ADGainMask) { - case HDSP_ADGainMinus10dBV: - return 0; - case HDSP_ADGainPlus4dBu: - return 1; - case HDSP_ADGainLowGain: - return 2; - default: - return 1; - } -} - -static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode) -{ - hdsp->control_register &= ~HDSP_ADGainMask; - switch (mode) { - case 0: - hdsp->control_register |= HDSP_ADGainMinus10dBV; - break; - case 1: - hdsp->control_register |= HDSP_ADGainPlus4dBu; - break; - case 2: - hdsp->control_register |= HDSP_ADGainLowGain; - break; - default: - return -1; - - } - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp); - return 0; -} - -static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - if (val < 0) val = 0; - if (val > 2) val = 2; - spin_lock_irq(&hdsp->lock); - if (val != hdsp_ad_gain(hdsp)) - change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_PHONE_GAIN(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_phone_gain, \ - .get = snd_hdsp_get_phone_gain, \ - .put = snd_hdsp_put_phone_gain \ -} - -static int hdsp_phone_gain(struct hdsp *hdsp) -{ - switch (hdsp->control_register & HDSP_PhoneGainMask) { - case HDSP_PhoneGain0dB: - return 0; - case HDSP_PhoneGainMinus6dB: - return 1; - case HDSP_PhoneGainMinus12dB: - return 2; - default: - return 0; - } -} - -static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode) -{ - hdsp->control_register &= ~HDSP_PhoneGainMask; - switch (mode) { - case 0: - hdsp->control_register |= HDSP_PhoneGain0dB; - break; - case 1: - hdsp->control_register |= HDSP_PhoneGainMinus6dB; - break; - case 2: - hdsp->control_register |= HDSP_PhoneGainMinus12dB; - break; - default: - return -1; - - } - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"0 dB", "-6 dB", "-12 dB"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp); - return 0; -} - -static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - if (val < 0) val = 0; - if (val > 2) val = 2; - spin_lock_irq(&hdsp->lock); - if (val != hdsp_phone_gain(hdsp)) - change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_xlr_breakout_cable, \ - .get = snd_hdsp_get_xlr_breakout_cable, \ - .put = snd_hdsp_put_xlr_breakout_cable \ -} - -static int hdsp_xlr_breakout_cable(struct hdsp *hdsp) -{ - if (hdsp->control_register & HDSP_XLRBreakoutCable) - return 1; - return 0; -} - -static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode) -{ - if (mode) - hdsp->control_register |= HDSP_XLRBreakoutCable; - else - hdsp->control_register &= ~HDSP_XLRBreakoutCable; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -#define snd_hdsp_info_xlr_breakout_cable snd_ctl_boolean_mono_info - -static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp); - return 0; -} - -static int snd_hdsp_put_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_xlr_breakout_cable(hdsp); - hdsp_set_xlr_breakout_cable(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -/* (De)activates old RME Analog Extension Board - These are connected to the internal ADAT connector - Switching this on desactivates external ADAT -*/ -#define HDSP_AEB(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_aeb, \ - .get = snd_hdsp_get_aeb, \ - .put = snd_hdsp_put_aeb \ -} - -static int hdsp_aeb(struct hdsp *hdsp) -{ - if (hdsp->control_register & HDSP_AnalogExtensionBoard) - return 1; - return 0; -} - -static int hdsp_set_aeb(struct hdsp *hdsp, int mode) -{ - if (mode) - hdsp->control_register |= HDSP_AnalogExtensionBoard; - else - hdsp->control_register &= ~HDSP_AnalogExtensionBoard; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -#define snd_hdsp_info_aeb snd_ctl_boolean_mono_info - -static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp); - return 0; -} - -static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_aeb(hdsp); - hdsp_set_aeb(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_PREF_SYNC_REF(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_pref_sync_ref, \ - .get = snd_hdsp_get_pref_sync_ref, \ - .put = snd_hdsp_put_pref_sync_ref \ -} - -static int hdsp_pref_sync_ref(struct hdsp *hdsp) -{ - /* Notice that this looks at the requested sync source, - not the one actually in use. - */ - - switch (hdsp->control_register & HDSP_SyncRefMask) { - case HDSP_SyncRef_ADAT1: - return HDSP_SYNC_FROM_ADAT1; - case HDSP_SyncRef_ADAT2: - return HDSP_SYNC_FROM_ADAT2; - case HDSP_SyncRef_ADAT3: - return HDSP_SYNC_FROM_ADAT3; - case HDSP_SyncRef_SPDIF: - return HDSP_SYNC_FROM_SPDIF; - case HDSP_SyncRef_WORD: - return HDSP_SYNC_FROM_WORD; - case HDSP_SyncRef_ADAT_SYNC: - return HDSP_SYNC_FROM_ADAT_SYNC; - default: - return HDSP_SYNC_FROM_WORD; - } - return 0; -} - -static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref) -{ - hdsp->control_register &= ~HDSP_SyncRefMask; - switch (pref) { - case HDSP_SYNC_FROM_ADAT1: - hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */ - break; - case HDSP_SYNC_FROM_ADAT2: - hdsp->control_register |= HDSP_SyncRef_ADAT2; - break; - case HDSP_SYNC_FROM_ADAT3: - hdsp->control_register |= HDSP_SyncRef_ADAT3; - break; - case HDSP_SYNC_FROM_SPDIF: - hdsp->control_register |= HDSP_SyncRef_SPDIF; - break; - case HDSP_SYNC_FROM_WORD: - hdsp->control_register |= HDSP_SyncRef_WORD; - break; - case HDSP_SYNC_FROM_ADAT_SYNC: - hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC; - break; - default: - return -1; - } - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" }; - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - - switch (hdsp->io_type) { - case Digiface: - case H9652: - uinfo->value.enumerated.items = 6; - break; - case Multiface: - uinfo->value.enumerated.items = 4; - break; - case H9632: - uinfo->value.enumerated.items = 3; - break; - default: - return -EINVAL; - } - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp); - return 0; -} - -static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change, max; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - - switch (hdsp->io_type) { - case Digiface: - case H9652: - max = 6; - break; - case Multiface: - max = 4; - break; - case H9632: - max = 3; - break; - default: - return -EIO; - } - - val = ucontrol->value.enumerated.item[0] % max; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_pref_sync_ref(hdsp); - hdsp_set_pref_sync_ref(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_AUTOSYNC_REF(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdsp_info_autosync_ref, \ - .get = snd_hdsp_get_autosync_ref, \ -} - -static int hdsp_autosync_ref(struct hdsp *hdsp) -{ - /* This looks at the autosync selected sync reference */ - unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register); - - switch (status2 & HDSP_SelSyncRefMask) { - case HDSP_SelSyncRef_WORD: - return HDSP_AUTOSYNC_FROM_WORD; - case HDSP_SelSyncRef_ADAT_SYNC: - return HDSP_AUTOSYNC_FROM_ADAT_SYNC; - case HDSP_SelSyncRef_SPDIF: - return HDSP_AUTOSYNC_FROM_SPDIF; - case HDSP_SelSyncRefMask: - return HDSP_AUTOSYNC_FROM_NONE; - case HDSP_SelSyncRef_ADAT1: - return HDSP_AUTOSYNC_FROM_ADAT1; - case HDSP_SelSyncRef_ADAT2: - return HDSP_AUTOSYNC_FROM_ADAT2; - case HDSP_SelSyncRef_ADAT3: - return HDSP_AUTOSYNC_FROM_ADAT3; - default: - return HDSP_AUTOSYNC_FROM_WORD; - } - return 0; -} - -static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 7; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp); - return 0; -} - -#define HDSP_LINE_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_line_out, \ - .get = snd_hdsp_get_line_out, \ - .put = snd_hdsp_put_line_out \ -} - -static int hdsp_line_out(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_LineOut) ? 1 : 0; -} - -static int hdsp_set_line_output(struct hdsp *hdsp, int out) -{ - if (out) - hdsp->control_register |= HDSP_LineOut; - else - hdsp->control_register &= ~HDSP_LineOut; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - -#define snd_hdsp_info_line_out snd_ctl_boolean_mono_info - -static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[0] = hdsp_line_out(hdsp); - spin_unlock_irq(&hdsp->lock); - return 0; -} - -static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_line_out(hdsp); - hdsp_set_line_output(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_PRECISE_POINTER(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_precise_pointer, \ - .get = snd_hdsp_get_precise_pointer, \ - .put = snd_hdsp_put_precise_pointer \ -} - -static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise) -{ - if (precise) - hdsp->precise_ptr = 1; - else - hdsp->precise_ptr = 0; - return 0; -} - -#define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info - -static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[0] = hdsp->precise_ptr; - spin_unlock_irq(&hdsp->lock); - return 0; -} - -static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp->precise_ptr; - hdsp_set_precise_pointer(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_USE_MIDI_TASKLET(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_use_midi_tasklet, \ - .get = snd_hdsp_get_use_midi_tasklet, \ - .put = snd_hdsp_put_use_midi_tasklet \ -} - -static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet) -{ - if (use_tasklet) - hdsp->use_midi_tasklet = 1; - else - hdsp->use_midi_tasklet = 0; - return 0; -} - -#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info - -static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet; - spin_unlock_irq(&hdsp->lock); - return 0; -} - -static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp->use_midi_tasklet; - hdsp_set_use_midi_tasklet(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_MIXER(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .device = 0, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdsp_info_mixer, \ - .get = snd_hdsp_get_mixer, \ - .put = snd_hdsp_put_mixer \ -} - -static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 3; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 65536; - uinfo->value.integer.step = 1; - return 0; -} - -static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int source; - int destination; - int addr; - - source = ucontrol->value.integer.value[0]; - destination = ucontrol->value.integer.value[1]; - - if (source >= hdsp->max_channels) - addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination); - else - addr = hdsp_input_to_output_key(hdsp,source, destination); - - spin_lock_irq(&hdsp->lock); - ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr); - spin_unlock_irq(&hdsp->lock); - return 0; -} - -static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int source; - int destination; - int gain; - int addr; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - - source = ucontrol->value.integer.value[0]; - destination = ucontrol->value.integer.value[1]; - - if (source >= hdsp->max_channels) - addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination); - else - addr = hdsp_input_to_output_key(hdsp,source, destination); - - gain = ucontrol->value.integer.value[2]; - - spin_lock_irq(&hdsp->lock); - change = gain != hdsp_read_gain(hdsp, addr); - if (change) - hdsp_write_gain(hdsp, addr, gain); - spin_unlock_irq(&hdsp->lock); - return change; -} - -#define HDSP_WC_SYNC_CHECK(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdsp_info_sync_check, \ - .get = snd_hdsp_get_wc_sync_check \ -} - -static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"No Lock", "Lock", "Sync" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int hdsp_wc_sync_check(struct hdsp *hdsp) -{ - int status2 = hdsp_read(hdsp, HDSP_status2Register); - if (status2 & HDSP_wc_lock) { - if (status2 & HDSP_wc_sync) - return 2; - else - return 1; - } else - return 0; - return 0; -} - -static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp); - return 0; -} - -#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdsp_info_sync_check, \ - .get = snd_hdsp_get_spdif_sync_check \ -} - -static int hdsp_spdif_sync_check(struct hdsp *hdsp) -{ - int status = hdsp_read(hdsp, HDSP_statusRegister); - if (status & HDSP_SPDIFErrorFlag) - return 0; - else { - if (status & HDSP_SPDIFSync) - return 2; - else - return 1; - } - return 0; -} - -static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp); - return 0; -} - -#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdsp_info_sync_check, \ - .get = snd_hdsp_get_adatsync_sync_check \ -} - -static int hdsp_adatsync_sync_check(struct hdsp *hdsp) -{ - int status = hdsp_read(hdsp, HDSP_statusRegister); - if (status & HDSP_TimecodeLock) { - if (status & HDSP_TimecodeSync) - return 2; - else - return 1; - } else - return 0; -} - -static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp); - return 0; -} - -#define HDSP_ADAT_SYNC_CHECK \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdsp_info_sync_check, \ - .get = snd_hdsp_get_adat_sync_check \ -} - -static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx) -{ - int status = hdsp_read(hdsp, HDSP_statusRegister); - - if (status & (HDSP_Lock0>>idx)) { - if (status & (HDSP_Sync0>>idx)) - return 2; - else - return 1; - } else - return 0; -} - -static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - int offset; - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - offset = ucontrol->id.index - 1; - snd_BUG_ON(offset < 0); - - switch (hdsp->io_type) { - case Digiface: - case H9652: - if (offset >= 3) - return -EINVAL; - break; - case Multiface: - case H9632: - if (offset >= 1) - return -EINVAL; - break; - default: - return -EIO; - } - - ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset); - return 0; -} - -#define HDSP_DDS_OFFSET(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdsp_info_dds_offset, \ - .get = snd_hdsp_get_dds_offset, \ - .put = snd_hdsp_put_dds_offset \ -} - -static int hdsp_dds_offset(struct hdsp *hdsp) -{ - u64 n; - unsigned int dds_value = hdsp->dds_value; - int system_sample_rate = hdsp->system_sample_rate; - - if (!dds_value) - return 0; - - n = DDS_NUMERATOR; - /* - * dds_value = n / rate - * rate = n / dds_value - */ - n = div_u64(n, dds_value); - if (system_sample_rate >= 112000) - n *= 4; - else if (system_sample_rate >= 56000) - n *= 2; - return ((int)n) - system_sample_rate; -} - -static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz) -{ - int rate = hdsp->system_sample_rate + offset_hz; - hdsp_set_dds_value(hdsp, rate); - return 0; -} - -static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = -5000; - uinfo->value.integer.max = 5000; - return 0; -} - -static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp); - return 0; -} - -static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - spin_lock_irq(&hdsp->lock); - if (val != hdsp_dds_offset(hdsp)) - change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdsp->lock); - return change; -} - -static struct snd_kcontrol_new snd_hdsp_9632_controls[] = { -HDSP_DA_GAIN("DA Gain", 0), -HDSP_AD_GAIN("AD Gain", 0), -HDSP_PHONE_GAIN("Phones Gain", 0), -HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0), -HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0) -}; - -static struct snd_kcontrol_new snd_hdsp_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_hdsp_control_spdif_info, - .get = snd_hdsp_control_spdif_get, - .put = snd_hdsp_control_spdif_put, -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_hdsp_control_spdif_stream_info, - .get = snd_hdsp_control_spdif_stream_get, - .put = snd_hdsp_control_spdif_stream_put, -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), - .info = snd_hdsp_control_spdif_mask_info, - .get = snd_hdsp_control_spdif_mask_get, - .private_value = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_CON_EMPHASIS, -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), - .info = snd_hdsp_control_spdif_mask_info, - .get = snd_hdsp_control_spdif_mask_get, - .private_value = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_PRO_EMPHASIS, -}, -HDSP_MIXER("Mixer", 0), -HDSP_SPDIF_IN("IEC958 Input Connector", 0), -HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0), -HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0), -HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0), -HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), -/* 'Sample Clock Source' complies with the alsa control naming scheme */ -HDSP_CLOCK_SOURCE("Sample Clock Source", 0), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Sample Clock Source Locking", - .info = snd_hdsp_info_clock_source_lock, - .get = snd_hdsp_get_clock_source_lock, - .put = snd_hdsp_put_clock_source_lock, -}, -HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0), -HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0), -HDSP_AUTOSYNC_REF("AutoSync Reference", 0), -HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0), -HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), -/* 'External Rate' complies with the alsa control naming scheme */ -HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0), -HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0), -HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0), -HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0), -HDSP_LINE_OUT("Line Out", 0), -HDSP_PRECISE_POINTER("Precise Pointer", 0), -HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0), -}; - - -static int hdsp_rpm_input12(struct hdsp *hdsp) -{ - switch (hdsp->control_register & HDSP_RPM_Inp12) { - case HDSP_RPM_Inp12_Phon_6dB: - return 0; - case HDSP_RPM_Inp12_Phon_n6dB: - return 2; - case HDSP_RPM_Inp12_Line_0dB: - return 3; - case HDSP_RPM_Inp12_Line_n6dB: - return 4; - } - return 1; -} - - -static int snd_hdsp_get_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_rpm_input12(hdsp); - return 0; -} - - -static int hdsp_set_rpm_input12(struct hdsp *hdsp, int mode) -{ - hdsp->control_register &= ~HDSP_RPM_Inp12; - switch (mode) { - case 0: - hdsp->control_register |= HDSP_RPM_Inp12_Phon_6dB; - break; - case 1: - break; - case 2: - hdsp->control_register |= HDSP_RPM_Inp12_Phon_n6dB; - break; - case 3: - hdsp->control_register |= HDSP_RPM_Inp12_Line_0dB; - break; - case 4: - hdsp->control_register |= HDSP_RPM_Inp12_Line_n6dB; - break; - default: - return -1; - } - - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - - -static int snd_hdsp_put_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - if (val < 0) - val = 0; - if (val > 4) - val = 4; - spin_lock_irq(&hdsp->lock); - if (val != hdsp_rpm_input12(hdsp)) - change = (hdsp_set_rpm_input12(hdsp, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdsp->lock); - return change; -} - - -static int snd_hdsp_info_rpm_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"Phono +6dB", "Phono 0dB", "Phono -6dB", "Line 0dB", "Line -6dB"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - - -static int hdsp_rpm_input34(struct hdsp *hdsp) -{ - switch (hdsp->control_register & HDSP_RPM_Inp34) { - case HDSP_RPM_Inp34_Phon_6dB: - return 0; - case HDSP_RPM_Inp34_Phon_n6dB: - return 2; - case HDSP_RPM_Inp34_Line_0dB: - return 3; - case HDSP_RPM_Inp34_Line_n6dB: - return 4; - } - return 1; -} - - -static int snd_hdsp_get_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdsp_rpm_input34(hdsp); - return 0; -} - - -static int hdsp_set_rpm_input34(struct hdsp *hdsp, int mode) -{ - hdsp->control_register &= ~HDSP_RPM_Inp34; - switch (mode) { - case 0: - hdsp->control_register |= HDSP_RPM_Inp34_Phon_6dB; - break; - case 1: - break; - case 2: - hdsp->control_register |= HDSP_RPM_Inp34_Phon_n6dB; - break; - case 3: - hdsp->control_register |= HDSP_RPM_Inp34_Line_0dB; - break; - case 4: - hdsp->control_register |= HDSP_RPM_Inp34_Line_n6dB; - break; - default: - return -1; - } - - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - - -static int snd_hdsp_put_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - if (val < 0) - val = 0; - if (val > 4) - val = 4; - spin_lock_irq(&hdsp->lock); - if (val != hdsp_rpm_input34(hdsp)) - change = (hdsp_set_rpm_input34(hdsp, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdsp->lock); - return change; -} - - -/* RPM Bypass switch */ -static int hdsp_rpm_bypass(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_RPM_Bypass) ? 1 : 0; -} - - -static int snd_hdsp_get_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_rpm_bypass(hdsp); - return 0; -} - - -static int hdsp_set_rpm_bypass(struct hdsp *hdsp, int on) -{ - if (on) - hdsp->control_register |= HDSP_RPM_Bypass; - else - hdsp->control_register &= ~HDSP_RPM_Bypass; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - - -static int snd_hdsp_put_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_rpm_bypass(hdsp); - hdsp_set_rpm_bypass(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - - -static int snd_hdsp_info_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"On", "Off"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - - -/* RPM Disconnect switch */ -static int hdsp_rpm_disconnect(struct hdsp *hdsp) -{ - return (hdsp->control_register & HDSP_RPM_Disconnect) ? 1 : 0; -} - - -static int snd_hdsp_get_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdsp_rpm_disconnect(hdsp); - return 0; -} - - -static int hdsp_set_rpm_disconnect(struct hdsp *hdsp, int on) -{ - if (on) - hdsp->control_register |= HDSP_RPM_Disconnect; - else - hdsp->control_register &= ~HDSP_RPM_Disconnect; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - return 0; -} - - -static int snd_hdsp_put_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct hdsp *hdsp = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdsp_use_is_exclusive(hdsp)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdsp->lock); - change = (int)val != hdsp_rpm_disconnect(hdsp); - hdsp_set_rpm_disconnect(hdsp, val); - spin_unlock_irq(&hdsp->lock); - return change; -} - -static int snd_hdsp_info_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"On", "Off"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static struct snd_kcontrol_new snd_hdsp_rpm_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "RPM Bypass", - .get = snd_hdsp_get_rpm_bypass, - .put = snd_hdsp_put_rpm_bypass, - .info = snd_hdsp_info_rpm_bypass - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "RPM Disconnect", - .get = snd_hdsp_get_rpm_disconnect, - .put = snd_hdsp_put_rpm_disconnect, - .info = snd_hdsp_info_rpm_disconnect - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input 1/2", - .get = snd_hdsp_get_rpm_input12, - .put = snd_hdsp_put_rpm_input12, - .info = snd_hdsp_info_rpm_input - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input 3/4", - .get = snd_hdsp_get_rpm_input34, - .put = snd_hdsp_put_rpm_input34, - .info = snd_hdsp_info_rpm_input - }, - HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), - HDSP_MIXER("Mixer", 0) -}; - -static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0); -static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK; - -static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) -{ - unsigned int idx; - int err; - struct snd_kcontrol *kctl; - - if (hdsp->io_type == RPM) { - /* RPM Bypass, Disconnect and Input switches */ - for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_rpm_controls); idx++) { - err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_rpm_controls[idx], hdsp)); - if (err < 0) - return err; - } - return 0; - } - - for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) - return err; - if (idx == 1) /* IEC958 (S/PDIF) Stream */ - hdsp->spdif_ctl = kctl; - } - - /* ADAT SyncCheck status */ - snd_hdsp_adat_sync_check.name = "ADAT Lock Status"; - snd_hdsp_adat_sync_check.index = 1; - if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) - return err; - if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { - for (idx = 1; idx < 3; ++idx) { - snd_hdsp_adat_sync_check.index = idx+1; - if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) - return err; - } - } - - /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */ - if (hdsp->io_type == H9632) { - for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0) - return err; - } - } - - /* AEB control for H96xx card */ - if (hdsp->io_type == H9632 || hdsp->io_type == H9652) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0) - return err; - } - - return 0; -} - -/*------------------------------------------------------------ - /proc interface - ------------------------------------------------------------*/ - -static void -snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct hdsp *hdsp = entry->private_data; - unsigned int status; - unsigned int status2; - char *pref_sync_ref; - char *autosync_ref; - char *system_clock_mode; - char *clock_source; - int x; - - status = hdsp_read(hdsp, HDSP_statusRegister); - status2 = hdsp_read(hdsp, HDSP_status2Register); - - snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, - hdsp->card->number + 1); - snd_iprintf(buffer, "Buffers: capture %p playback %p\n", - hdsp->capture_buffer, hdsp->playback_buffer); - snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", - hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase); - snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register); - snd_iprintf(buffer, "Control2 register: 0x%x\n", - hdsp->control2_register); - snd_iprintf(buffer, "Status register: 0x%x\n", status); - snd_iprintf(buffer, "Status2 register: 0x%x\n", status2); - - if (hdsp_check_for_iobox(hdsp)) { - snd_iprintf(buffer, "No I/O box connected.\n" - "Please connect one and upload firmware.\n"); - return; - } - - if (hdsp_check_for_firmware(hdsp, 0)) { - if (hdsp->state & HDSP_FirmwareCached) { - if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_iprintf(buffer, "Firmware loading from " - "cache failed, " - "please upload manually.\n"); - return; - } - } else { - int err = -EINVAL; -#ifdef HDSP_FW_LOADER - err = hdsp_request_fw_loader(hdsp); -#endif - if (err < 0) { - snd_iprintf(buffer, - "No firmware loaded nor cached, " - "please upload firmware.\n"); - return; - } - } - } - - snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff); - snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0)); - snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0)); - snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1)); - snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1)); - snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off"); - - snd_iprintf(buffer, "\n"); - - x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask)); - - snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes); - snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp)); - snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off"); - snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off"); - - snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2); - - snd_iprintf(buffer, "\n"); - - switch (hdsp_clock_source(hdsp)) { - case HDSP_CLOCK_SOURCE_AUTOSYNC: - clock_source = "AutoSync"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ: - clock_source = "Internal 32 kHz"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ: - clock_source = "Internal 44.1 kHz"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ: - clock_source = "Internal 48 kHz"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ: - clock_source = "Internal 64 kHz"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ: - clock_source = "Internal 88.2 kHz"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ: - clock_source = "Internal 96 kHz"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ: - clock_source = "Internal 128 kHz"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ: - clock_source = "Internal 176.4 kHz"; - break; - case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ: - clock_source = "Internal 192 kHz"; - break; - default: - clock_source = "Error"; - } - snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source); - - if (hdsp_system_clock_mode(hdsp)) - system_clock_mode = "Slave"; - else - system_clock_mode = "Master"; - - switch (hdsp_pref_sync_ref (hdsp)) { - case HDSP_SYNC_FROM_WORD: - pref_sync_ref = "Word Clock"; - break; - case HDSP_SYNC_FROM_ADAT_SYNC: - pref_sync_ref = "ADAT Sync"; - break; - case HDSP_SYNC_FROM_SPDIF: - pref_sync_ref = "SPDIF"; - break; - case HDSP_SYNC_FROM_ADAT1: - pref_sync_ref = "ADAT1"; - break; - case HDSP_SYNC_FROM_ADAT2: - pref_sync_ref = "ADAT2"; - break; - case HDSP_SYNC_FROM_ADAT3: - pref_sync_ref = "ADAT3"; - break; - default: - pref_sync_ref = "Word Clock"; - break; - } - snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref); - - switch (hdsp_autosync_ref (hdsp)) { - case HDSP_AUTOSYNC_FROM_WORD: - autosync_ref = "Word Clock"; - break; - case HDSP_AUTOSYNC_FROM_ADAT_SYNC: - autosync_ref = "ADAT Sync"; - break; - case HDSP_AUTOSYNC_FROM_SPDIF: - autosync_ref = "SPDIF"; - break; - case HDSP_AUTOSYNC_FROM_NONE: - autosync_ref = "None"; - break; - case HDSP_AUTOSYNC_FROM_ADAT1: - autosync_ref = "ADAT1"; - break; - case HDSP_AUTOSYNC_FROM_ADAT2: - autosync_ref = "ADAT2"; - break; - case HDSP_AUTOSYNC_FROM_ADAT3: - autosync_ref = "ADAT3"; - break; - default: - autosync_ref = "---"; - break; - } - snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref); - - snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp)); - - snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); - - snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); - snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No"); - - snd_iprintf(buffer, "\n"); - - if (hdsp->io_type != RPM) { - switch (hdsp_spdif_in(hdsp)) { - case HDSP_SPDIFIN_OPTICAL: - snd_iprintf(buffer, "IEC958 input: Optical\n"); - break; - case HDSP_SPDIFIN_COAXIAL: - snd_iprintf(buffer, "IEC958 input: Coaxial\n"); - break; - case HDSP_SPDIFIN_INTERNAL: - snd_iprintf(buffer, "IEC958 input: Internal\n"); - break; - case HDSP_SPDIFIN_AES: - snd_iprintf(buffer, "IEC958 input: AES\n"); - break; - default: - snd_iprintf(buffer, "IEC958 input: ???\n"); - break; - } - } - - if (RPM == hdsp->io_type) { - if (hdsp->control_register & HDSP_RPM_Bypass) - snd_iprintf(buffer, "RPM Bypass: disabled\n"); - else - snd_iprintf(buffer, "RPM Bypass: enabled\n"); - if (hdsp->control_register & HDSP_RPM_Disconnect) - snd_iprintf(buffer, "RPM disconnected\n"); - else - snd_iprintf(buffer, "RPM connected\n"); - - switch (hdsp->control_register & HDSP_RPM_Inp12) { - case HDSP_RPM_Inp12_Phon_6dB: - snd_iprintf(buffer, "Input 1/2: Phono, 6dB\n"); - break; - case HDSP_RPM_Inp12_Phon_0dB: - snd_iprintf(buffer, "Input 1/2: Phono, 0dB\n"); - break; - case HDSP_RPM_Inp12_Phon_n6dB: - snd_iprintf(buffer, "Input 1/2: Phono, -6dB\n"); - break; - case HDSP_RPM_Inp12_Line_0dB: - snd_iprintf(buffer, "Input 1/2: Line, 0dB\n"); - break; - case HDSP_RPM_Inp12_Line_n6dB: - snd_iprintf(buffer, "Input 1/2: Line, -6dB\n"); - break; - default: - snd_iprintf(buffer, "Input 1/2: ???\n"); - } - - switch (hdsp->control_register & HDSP_RPM_Inp34) { - case HDSP_RPM_Inp34_Phon_6dB: - snd_iprintf(buffer, "Input 3/4: Phono, 6dB\n"); - break; - case HDSP_RPM_Inp34_Phon_0dB: - snd_iprintf(buffer, "Input 3/4: Phono, 0dB\n"); - break; - case HDSP_RPM_Inp34_Phon_n6dB: - snd_iprintf(buffer, "Input 3/4: Phono, -6dB\n"); - break; - case HDSP_RPM_Inp34_Line_0dB: - snd_iprintf(buffer, "Input 3/4: Line, 0dB\n"); - break; - case HDSP_RPM_Inp34_Line_n6dB: - snd_iprintf(buffer, "Input 3/4: Line, -6dB\n"); - break; - default: - snd_iprintf(buffer, "Input 3/4: ???\n"); - } - - } else { - if (hdsp->control_register & HDSP_SPDIFOpticalOut) - snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); - else - snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); - - if (hdsp->control_register & HDSP_SPDIFProfessional) - snd_iprintf(buffer, "IEC958 quality: Professional\n"); - else - snd_iprintf(buffer, "IEC958 quality: Consumer\n"); - - if (hdsp->control_register & HDSP_SPDIFEmphasis) - snd_iprintf(buffer, "IEC958 emphasis: on\n"); - else - snd_iprintf(buffer, "IEC958 emphasis: off\n"); - - if (hdsp->control_register & HDSP_SPDIFNonAudio) - snd_iprintf(buffer, "IEC958 NonAudio: on\n"); - else - snd_iprintf(buffer, "IEC958 NonAudio: off\n"); - x = hdsp_spdif_sample_rate(hdsp); - if (x != 0) - snd_iprintf(buffer, "IEC958 sample rate: %d\n", x); - else - snd_iprintf(buffer, "IEC958 sample rate: Error flag set\n"); - } - snd_iprintf(buffer, "\n"); - - /* Sync Check */ - x = status & HDSP_Sync0; - if (status & HDSP_Lock0) - snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock"); - else - snd_iprintf(buffer, "ADAT1: No Lock\n"); - - switch (hdsp->io_type) { - case Digiface: - case H9652: - x = status & HDSP_Sync1; - if (status & HDSP_Lock1) - snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock"); - else - snd_iprintf(buffer, "ADAT2: No Lock\n"); - x = status & HDSP_Sync2; - if (status & HDSP_Lock2) - snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock"); - else - snd_iprintf(buffer, "ADAT3: No Lock\n"); - break; - default: - /* relax */ - break; - } - - x = status & HDSP_SPDIFSync; - if (status & HDSP_SPDIFErrorFlag) - snd_iprintf (buffer, "SPDIF: No Lock\n"); - else - snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock"); - - x = status2 & HDSP_wc_sync; - if (status2 & HDSP_wc_lock) - snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock"); - else - snd_iprintf (buffer, "Word Clock: No Lock\n"); - - x = status & HDSP_TimecodeSync; - if (status & HDSP_TimecodeLock) - snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock"); - else - snd_iprintf(buffer, "ADAT Sync: No Lock\n"); - - snd_iprintf(buffer, "\n"); - - /* Informations about H9632 specific controls */ - if (hdsp->io_type == H9632) { - char *tmp; - - switch (hdsp_ad_gain(hdsp)) { - case 0: - tmp = "-10 dBV"; - break; - case 1: - tmp = "+4 dBu"; - break; - default: - tmp = "Lo Gain"; - break; - } - snd_iprintf(buffer, "AD Gain : %s\n", tmp); - - switch (hdsp_da_gain(hdsp)) { - case 0: - tmp = "Hi Gain"; - break; - case 1: - tmp = "+4 dBu"; - break; - default: - tmp = "-10 dBV"; - break; - } - snd_iprintf(buffer, "DA Gain : %s\n", tmp); - - switch (hdsp_phone_gain(hdsp)) { - case 0: - tmp = "0 dB"; - break; - case 1: - tmp = "-6 dB"; - break; - default: - tmp = "-12 dB"; - break; - } - snd_iprintf(buffer, "Phones Gain : %s\n", tmp); - - snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no"); - - if (hdsp->control_register & HDSP_AnalogExtensionBoard) - snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n"); - else - snd_iprintf(buffer, "AEB : off (ADAT1 external)\n"); - snd_iprintf(buffer, "\n"); - } - -} - -static void snd_hdsp_proc_init(struct hdsp *hdsp) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(hdsp->card, "hdsp", &entry)) - snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read); -} - -static void snd_hdsp_free_buffers(struct hdsp *hdsp) -{ - snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci); - snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci); -} - -static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp) -{ - unsigned long pb_bus, cb_bus; - - if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 || - snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) { - if (hdsp->capture_dma_buf.area) - snd_dma_free_pages(&hdsp->capture_dma_buf); - printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name); - return -ENOMEM; - } - - /* Align to bus-space 64K boundary */ - - cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul); - pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul); - - /* Tell the card where it is */ - - hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus); - hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus); - - hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr); - hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr); - - return 0; -} - -static int snd_hdsp_set_defaults(struct hdsp *hdsp) -{ - unsigned int i; - - /* ASSUMPTION: hdsp->lock is either held, or - there is no need to hold it (e.g. during module - initialization). - */ - - /* set defaults: - - SPDIF Input via Coax - Master clock mode - maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer, - which implies 2 4096 sample, 32Kbyte periods). - Enable line out. - */ - - hdsp->control_register = HDSP_ClockModeMaster | - HDSP_SPDIFInputCoaxial | - hdsp_encode_latency(7) | - HDSP_LineOut; - - - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - -#ifdef SNDRV_BIG_ENDIAN - hdsp->control2_register = HDSP_BIGENDIAN_MODE; -#else - hdsp->control2_register = 0; -#endif - if (hdsp->io_type == H9652) - snd_hdsp_9652_enable_mixer (hdsp); - else - hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); - - hdsp_reset_hw_pointer(hdsp); - hdsp_compute_period_size(hdsp); - - /* silence everything */ - - for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i) - hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN; - - for (i = 0; i < ((hdsp->io_type == H9652 || hdsp->io_type == H9632) ? 1352 : HDSP_MATRIX_MIXER_SIZE); ++i) { - if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN)) - return -EIO; - } - - /* H9632 specific defaults */ - if (hdsp->io_type == H9632) { - hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB); - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - } - - /* set a default rate so that the channel map is set up. - */ - - hdsp_set_rate(hdsp, 48000, 1); - - return 0; -} - -static void hdsp_midi_tasklet(unsigned long arg) -{ - struct hdsp *hdsp = (struct hdsp *)arg; - - if (hdsp->midi[0].pending) - snd_hdsp_midi_input_read (&hdsp->midi[0]); - if (hdsp->midi[1].pending) - snd_hdsp_midi_input_read (&hdsp->midi[1]); -} - -static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id) -{ - struct hdsp *hdsp = (struct hdsp *) dev_id; - unsigned int status; - int audio; - int midi0; - int midi1; - unsigned int midi0status; - unsigned int midi1status; - int schedule = 0; - - status = hdsp_read(hdsp, HDSP_statusRegister); - - audio = status & HDSP_audioIRQPending; - midi0 = status & HDSP_midi0IRQPending; - midi1 = status & HDSP_midi1IRQPending; - - if (!audio && !midi0 && !midi1) - return IRQ_NONE; - - hdsp_write(hdsp, HDSP_interruptConfirmation, 0); - - midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff; - midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff; - - if (!(hdsp->state & HDSP_InitializationComplete)) - return IRQ_HANDLED; - - if (audio) { - if (hdsp->capture_substream) - snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); - - if (hdsp->playback_substream) - snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); - } - - if (midi0 && midi0status) { - if (hdsp->use_midi_tasklet) { - /* we disable interrupts for this input until processing is done */ - hdsp->control_register &= ~HDSP_Midi0InterruptEnable; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp->midi[0].pending = 1; - schedule = 1; - } else { - snd_hdsp_midi_input_read (&hdsp->midi[0]); - } - } - if (hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632 && midi1 && midi1status) { - if (hdsp->use_midi_tasklet) { - /* we disable interrupts for this input until processing is done */ - hdsp->control_register &= ~HDSP_Midi1InterruptEnable; - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); - hdsp->midi[1].pending = 1; - schedule = 1; - } else { - snd_hdsp_midi_input_read (&hdsp->midi[1]); - } - } - if (hdsp->use_midi_tasklet && schedule) - tasklet_schedule(&hdsp->midi_tasklet); - return IRQ_HANDLED; -} - -static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - return hdsp_hw_pointer(hdsp); -} - -static char *hdsp_channel_buffer_location(struct hdsp *hdsp, - int stream, - int channel) - -{ - int mapped_channel; - - if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels)) - return NULL; - - if ((mapped_channel = hdsp->channel_map[channel]) < 0) - return NULL; - - if (stream == SNDRV_PCM_STREAM_CAPTURE) - return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); - else - return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); -} - -static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; - - if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) - return -EINVAL; - - channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - if (copy_from_user(channel_buf + pos * 4, src, count * 4)) - return -EFAULT; - return count; -} - -static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; - - if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) - return -EINVAL; - - channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) - return -EFAULT; - return count; -} - -static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, snd_pcm_uframes_t count) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - char *channel_buf; - - channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - memset(channel_buf + pos * 4, 0, count * 4); - return count; -} - -static int snd_hdsp_reset(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *other; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - other = hdsp->capture_substream; - else - other = hdsp->playback_substream; - if (hdsp->running) - runtime->status->hw_ptr = hdsp_hw_pointer(hdsp); - else - runtime->status->hw_ptr = 0; - if (other) { - struct snd_pcm_substream *s; - struct snd_pcm_runtime *oruntime = other->runtime; - snd_pcm_group_for_each_entry(s, substream) { - if (s == other) { - oruntime->status->hw_ptr = runtime->status->hw_ptr; - break; - } - } - } - return 0; -} - -static int snd_hdsp_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - int err; - pid_t this_pid; - pid_t other_pid; - - if (hdsp_check_for_iobox (hdsp)) - return -EIO; - - if (hdsp_check_for_firmware(hdsp, 1)) - return -EIO; - - spin_lock_irq(&hdsp->lock); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { - hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis); - hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream); - this_pid = hdsp->playback_pid; - other_pid = hdsp->capture_pid; - } else { - this_pid = hdsp->capture_pid; - other_pid = hdsp->playback_pid; - } - - if ((other_pid > 0) && (this_pid != other_pid)) { - - /* The other stream is open, and not by the same - task as this one. Make sure that the parameters - that matter are the same. - */ - - if (params_rate(params) != hdsp->system_sample_rate) { - spin_unlock_irq(&hdsp->lock); - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); - return -EBUSY; - } - - if (params_period_size(params) != hdsp->period_bytes / 4) { - spin_unlock_irq(&hdsp->lock); - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return -EBUSY; - } - - /* We're fine. */ - - spin_unlock_irq(&hdsp->lock); - return 0; - - } else { - spin_unlock_irq(&hdsp->lock); - } - - /* how to make sure that the rate matches an externally-set one ? - */ - - spin_lock_irq(&hdsp->lock); - if (! hdsp->clock_source_locked) { - if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) { - spin_unlock_irq(&hdsp->lock); - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); - return err; - } - } - spin_unlock_irq(&hdsp->lock); - - if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) { - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return err; - } - - return 0; -} - -static int snd_hdsp_channel_info(struct snd_pcm_substream *substream, - struct snd_pcm_channel_info *info) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - int mapped_channel; - - if (snd_BUG_ON(info->channel >= hdsp->max_channels)) - return -EINVAL; - - if ((mapped_channel = hdsp->channel_map[info->channel]) < 0) - return -EINVAL; - - info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES; - info->first = 0; - info->step = 32; - return 0; -} - -static int snd_hdsp_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - switch (cmd) { - case SNDRV_PCM_IOCTL1_RESET: - return snd_hdsp_reset(substream); - case SNDRV_PCM_IOCTL1_CHANNEL_INFO: - return snd_hdsp_channel_info(substream, arg); - default: - break; - } - - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *other; - int running; - - if (hdsp_check_for_iobox (hdsp)) - return -EIO; - - if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */ - return -EIO; - - spin_lock(&hdsp->lock); - running = hdsp->running; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - running |= 1 << substream->stream; - break; - case SNDRV_PCM_TRIGGER_STOP: - running &= ~(1 << substream->stream); - break; - default: - snd_BUG(); - spin_unlock(&hdsp->lock); - return -EINVAL; - } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - other = hdsp->capture_substream; - else - other = hdsp->playback_substream; - - if (other) { - struct snd_pcm_substream *s; - snd_pcm_group_for_each_entry(s, substream) { - if (s == other) { - snd_pcm_trigger_done(s, substream); - if (cmd == SNDRV_PCM_TRIGGER_START) - running |= 1 << s->stream; - else - running &= ~(1 << s->stream); - goto _ok; - } - } - if (cmd == SNDRV_PCM_TRIGGER_START) { - if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) && - substream->stream == SNDRV_PCM_STREAM_CAPTURE) - hdsp_silence_playback(hdsp); - } else { - if (running && - substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - hdsp_silence_playback(hdsp); - } - } else { - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - hdsp_silence_playback(hdsp); - } - _ok: - snd_pcm_trigger_done(substream, substream); - if (!hdsp->running && running) - hdsp_start_audio(hdsp); - else if (hdsp->running && !running) - hdsp_stop_audio(hdsp); - hdsp->running = running; - spin_unlock(&hdsp->lock); - - return 0; -} - -static int snd_hdsp_prepare(struct snd_pcm_substream *substream) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - int result = 0; - - if (hdsp_check_for_iobox (hdsp)) - return -EIO; - - if (hdsp_check_for_firmware(hdsp, 1)) - return -EIO; - - spin_lock_irq(&hdsp->lock); - if (!hdsp->running) - hdsp_reset_hw_pointer(hdsp); - spin_unlock_irq(&hdsp->lock); - return result; -} - -static struct snd_pcm_hardware snd_hdsp_playback_subinfo = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_DOUBLE), -#ifdef SNDRV_BIG_ENDIAN - .formats = SNDRV_PCM_FMTBIT_S32_BE, -#else - .formats = SNDRV_PCM_FMTBIT_S32_LE, -#endif - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000), - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 6, - .channels_max = HDSP_MAX_CHANNELS, - .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, - .period_bytes_min = (64 * 4) * 10, - .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS, - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0 -}; - -static struct snd_pcm_hardware snd_hdsp_capture_subinfo = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_SYNC_START), -#ifdef SNDRV_BIG_ENDIAN - .formats = SNDRV_PCM_FMTBIT_S32_BE, -#else - .formats = SNDRV_PCM_FMTBIT_S32_LE, -#endif - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000), - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 5, - .channels_max = HDSP_MAX_CHANNELS, - .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, - .period_bytes_min = (64 * 4) * 10, - .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS, - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0 -}; - -static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; - -static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = { - .count = ARRAY_SIZE(hdsp_period_sizes), - .list = hdsp_period_sizes, - .mask = 0 -}; - -static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; - -static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = { - .count = ARRAY_SIZE(hdsp_9632_sample_rates), - .list = hdsp_9632_sample_rates, - .mask = 0 -}; - -static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct hdsp *hdsp = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - if (hdsp->io_type == H9632) { - unsigned int list[3]; - list[0] = hdsp->qs_in_channels; - list[1] = hdsp->ds_in_channels; - list[2] = hdsp->ss_in_channels; - return snd_interval_list(c, 3, list, 0); - } else { - unsigned int list[2]; - list[0] = hdsp->ds_in_channels; - list[1] = hdsp->ss_in_channels; - return snd_interval_list(c, 2, list, 0); - } -} - -static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - unsigned int list[3]; - struct hdsp *hdsp = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - if (hdsp->io_type == H9632) { - list[0] = hdsp->qs_out_channels; - list[1] = hdsp->ds_out_channels; - list[2] = hdsp->ss_out_channels; - return snd_interval_list(c, 3, list, 0); - } else { - list[0] = hdsp->ds_out_channels; - list[1] = hdsp->ss_out_channels; - } - return snd_interval_list(c, 2, list, 0); -} - -static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct hdsp *hdsp = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (r->min > 96000 && hdsp->io_type == H9632) { - struct snd_interval t = { - .min = hdsp->qs_in_channels, - .max = hdsp->qs_in_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->min > 48000 && r->max <= 96000) { - struct snd_interval t = { - .min = hdsp->ds_in_channels, - .max = hdsp->ds_in_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->max < 64000) { - struct snd_interval t = { - .min = hdsp->ss_in_channels, - .max = hdsp->ss_in_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } - return 0; -} - -static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct hdsp *hdsp = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (r->min > 96000 && hdsp->io_type == H9632) { - struct snd_interval t = { - .min = hdsp->qs_out_channels, - .max = hdsp->qs_out_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->min > 48000 && r->max <= 96000) { - struct snd_interval t = { - .min = hdsp->ds_out_channels, - .max = hdsp->ds_out_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->max < 64000) { - struct snd_interval t = { - .min = hdsp->ss_out_channels, - .max = hdsp->ss_out_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } - return 0; -} - -static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct hdsp *hdsp = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (c->min >= hdsp->ss_out_channels) { - struct snd_interval t = { - .min = 32000, - .max = 48000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) { - struct snd_interval t = { - .min = 128000, - .max = 192000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= hdsp->ds_out_channels) { - struct snd_interval t = { - .min = 64000, - .max = 96000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } - return 0; -} - -static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct hdsp *hdsp = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (c->min >= hdsp->ss_in_channels) { - struct snd_interval t = { - .min = 32000, - .max = 48000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) { - struct snd_interval t = { - .min = 128000, - .max = 192000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= hdsp->ds_in_channels) { - struct snd_interval t = { - .min = 64000, - .max = 96000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } - return 0; -} - -static int snd_hdsp_playback_open(struct snd_pcm_substream *substream) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (hdsp_check_for_iobox (hdsp)) - return -EIO; - - if (hdsp_check_for_firmware(hdsp, 1)) - return -EIO; - - spin_lock_irq(&hdsp->lock); - - snd_pcm_set_sync(substream); - - runtime->hw = snd_hdsp_playback_subinfo; - runtime->dma_area = hdsp->playback_buffer; - runtime->dma_bytes = HDSP_DMA_AREA_BYTES; - - hdsp->playback_pid = current->pid; - hdsp->playback_substream = substream; - - spin_unlock_irq(&hdsp->lock); - - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); - if (hdsp->clock_source_locked) { - runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate; - } else if (hdsp->io_type == H9632) { - runtime->hw.rate_max = 192000; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates); - } - if (hdsp->io_type == H9632) { - runtime->hw.channels_min = hdsp->qs_out_channels; - runtime->hw.channels_max = hdsp->ss_out_channels; - } - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdsp_hw_rule_out_channels, hdsp, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdsp_hw_rule_out_channels_rate, hdsp, - SNDRV_PCM_HW_PARAM_RATE, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_hdsp_hw_rule_rate_out_channels, hdsp, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - - if (RPM != hdsp->io_type) { - hdsp->creg_spdif_stream = hdsp->creg_spdif; - hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); - } - return 0; -} - -static int snd_hdsp_playback_release(struct snd_pcm_substream *substream) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - - spin_lock_irq(&hdsp->lock); - - hdsp->playback_pid = -1; - hdsp->playback_substream = NULL; - - spin_unlock_irq(&hdsp->lock); - - if (RPM != hdsp->io_type) { - hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); - } - return 0; -} - - -static int snd_hdsp_capture_open(struct snd_pcm_substream *substream) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (hdsp_check_for_iobox (hdsp)) - return -EIO; - - if (hdsp_check_for_firmware(hdsp, 1)) - return -EIO; - - spin_lock_irq(&hdsp->lock); - - snd_pcm_set_sync(substream); - - runtime->hw = snd_hdsp_capture_subinfo; - runtime->dma_area = hdsp->capture_buffer; - runtime->dma_bytes = HDSP_DMA_AREA_BYTES; - - hdsp->capture_pid = current->pid; - hdsp->capture_substream = substream; - - spin_unlock_irq(&hdsp->lock); - - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); - if (hdsp->io_type == H9632) { - runtime->hw.channels_min = hdsp->qs_in_channels; - runtime->hw.channels_max = hdsp->ss_in_channels; - runtime->hw.rate_max = 192000; - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates); - } - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdsp_hw_rule_in_channels, hdsp, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdsp_hw_rule_in_channels_rate, hdsp, - SNDRV_PCM_HW_PARAM_RATE, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_hdsp_hw_rule_rate_in_channels, hdsp, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - return 0; -} - -static int snd_hdsp_capture_release(struct snd_pcm_substream *substream) -{ - struct hdsp *hdsp = snd_pcm_substream_chip(substream); - - spin_lock_irq(&hdsp->lock); - - hdsp->capture_pid = -1; - hdsp->capture_substream = NULL; - - spin_unlock_irq(&hdsp->lock); - return 0; -} - -/* helper functions for copying meter values */ -static inline int copy_u32_le(void __user *dest, void __iomem *src) -{ - u32 val = readl(src); - return copy_to_user(dest, &val, 4); -} - -static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high) -{ - u32 rms_low, rms_high; - u64 rms; - rms_low = readl(src_low); - rms_high = readl(src_high); - rms = ((u64)rms_high << 32) | rms_low; - return copy_to_user(dest, &rms, 8); -} - -static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high) -{ - u32 rms_low, rms_high; - u64 rms; - rms_low = readl(src_low) & 0xffffff00; - rms_high = readl(src_high) & 0xffffff00; - rms = ((u64)rms_high << 32) | rms_low; - return copy_to_user(dest, &rms, 8); -} - -static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms) -{ - int doublespeed = 0; - int i, j, channels, ofs; - - if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus) - doublespeed = 1; - channels = doublespeed ? 14 : 26; - for (i = 0, j = 0; i < 26; ++i) { - if (doublespeed && (i & 4)) - continue; - ofs = HDSP_9652_peakBase - j * 4; - if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs)) - return -EFAULT; - ofs -= channels * 4; - if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs)) - return -EFAULT; - ofs -= channels * 4; - if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs)) - return -EFAULT; - ofs = HDSP_9652_rmsBase + j * 8; - if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs, - hdsp->iobase + ofs + 4)) - return -EFAULT; - ofs += channels * 8; - if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs, - hdsp->iobase + ofs + 4)) - return -EFAULT; - ofs += channels * 8; - if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs, - hdsp->iobase + ofs + 4)) - return -EFAULT; - j++; - } - return 0; -} - -static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms) -{ - int i, j; - struct hdsp_9632_meters __iomem *m; - int doublespeed = 0; - - if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus) - doublespeed = 1; - m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase); - for (i = 0, j = 0; i < 16; ++i, ++j) { - if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j])) - return -EFAULT; - if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j])) - return -EFAULT; - if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j])) - return -EFAULT; - if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j], - &m->input_rms_high[j])) - return -EFAULT; - if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j], - &m->playback_rms_high[j])) - return -EFAULT; - if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j], - &m->output_rms_high[j])) - return -EFAULT; - if (doublespeed && i == 3) i += 4; - } - return 0; -} - -static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms) -{ - int i; - - for (i = 0; i < 26; i++) { - if (copy_u32_le(&peak_rms->playback_peaks[i], - hdsp->iobase + HDSP_playbackPeakLevel + i * 4)) - return -EFAULT; - if (copy_u32_le(&peak_rms->input_peaks[i], - hdsp->iobase + HDSP_inputPeakLevel + i * 4)) - return -EFAULT; - } - for (i = 0; i < 28; i++) { - if (copy_u32_le(&peak_rms->output_peaks[i], - hdsp->iobase + HDSP_outputPeakLevel + i * 4)) - return -EFAULT; - } - for (i = 0; i < 26; ++i) { - if (copy_u64_le(&peak_rms->playback_rms[i], - hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4, - hdsp->iobase + HDSP_playbackRmsLevel + i * 8)) - return -EFAULT; - if (copy_u64_le(&peak_rms->input_rms[i], - hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4, - hdsp->iobase + HDSP_inputRmsLevel + i * 8)) - return -EFAULT; - } - return 0; -} - -static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct hdsp *hdsp = hw->private_data; - void __user *argp = (void __user *)arg; - int err; - - switch (cmd) { - case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: { - struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg; - - err = hdsp_check_for_iobox(hdsp); - if (err < 0) - return err; - - err = hdsp_check_for_firmware(hdsp, 1); - if (err < 0) - return err; - - if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n"); - return -EINVAL; - } - - switch (hdsp->io_type) { - case H9652: - return hdsp_9652_get_peak(hdsp, peak_rms); - case H9632: - return hdsp_9632_get_peak(hdsp, peak_rms); - default: - return hdsp_get_peak(hdsp, peak_rms); - } - } - case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: { - struct hdsp_config_info info; - unsigned long flags; - int i; - - err = hdsp_check_for_iobox(hdsp); - if (err < 0) - return err; - - err = hdsp_check_for_firmware(hdsp, 1); - if (err < 0) - return err; - - memset(&info, 0, sizeof(info)); - spin_lock_irqsave(&hdsp->lock, flags); - info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); - info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); - if (hdsp->io_type != H9632) - info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp); - info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp); - for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632) ? 3 : 1); ++i) - info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i); - info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp); - info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp); - info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp); - info.spdif_emphasis = (unsigned char)hdsp_spdif_emphasis(hdsp); - info.spdif_nonaudio = (unsigned char)hdsp_spdif_nonaudio(hdsp); - info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp); - info.system_sample_rate = hdsp->system_sample_rate; - info.autosync_sample_rate = hdsp_external_sample_rate(hdsp); - info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp); - info.clock_source = (unsigned char)hdsp_clock_source(hdsp); - info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp); - info.line_out = (unsigned char)hdsp_line_out(hdsp); - if (hdsp->io_type == H9632) { - info.da_gain = (unsigned char)hdsp_da_gain(hdsp); - info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); - info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); - info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp); - - } else if (hdsp->io_type == RPM) { - info.da_gain = (unsigned char) hdsp_rpm_input12(hdsp); - info.ad_gain = (unsigned char) hdsp_rpm_input34(hdsp); - } - if (hdsp->io_type == H9632 || hdsp->io_type == H9652) - info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp); - spin_unlock_irqrestore(&hdsp->lock, flags); - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - break; - } - case SNDRV_HDSP_IOCTL_GET_9632_AEB: { - struct hdsp_9632_aeb h9632_aeb; - - if (hdsp->io_type != H9632) return -EINVAL; - h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS; - h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS; - if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb))) - return -EFAULT; - break; - } - case SNDRV_HDSP_IOCTL_GET_VERSION: { - struct hdsp_version hdsp_version; - int err; - - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; - if (hdsp->io_type == Undefined) { - if ((err = hdsp_get_iobox_version(hdsp)) < 0) - return err; - } - hdsp_version.io_type = hdsp->io_type; - hdsp_version.firmware_rev = hdsp->firmware_rev; - if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version)))) - return -EFAULT; - break; - } - case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: { - struct hdsp_firmware __user *firmware; - u32 __user *firmware_data; - int err; - - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; - /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */ - if (hdsp->io_type == Undefined) return -EINVAL; - - if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded)) - return -EBUSY; - - snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n"); - firmware = (struct hdsp_firmware __user *)argp; - - if (get_user(firmware_data, &firmware->firmware_data)) - return -EFAULT; - - if (hdsp_check_for_iobox (hdsp)) - return -EIO; - - if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) - return -EFAULT; - - hdsp->state |= HDSP_FirmwareCached; - - if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) - return err; - - if (!(hdsp->state & HDSP_InitializationComplete)) { - if ((err = snd_hdsp_enable_io(hdsp)) < 0) - return err; - - snd_hdsp_initialize_channels(hdsp); - snd_hdsp_initialize_midi_flush(hdsp); - - if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); - return err; - } - } - break; - } - case SNDRV_HDSP_IOCTL_GET_MIXER: { - struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp; - if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE)) - return -EFAULT; - break; - } - default: - return -EINVAL; - } - return 0; -} - -static struct snd_pcm_ops snd_hdsp_playback_ops = { - .open = snd_hdsp_playback_open, - .close = snd_hdsp_playback_release, - .ioctl = snd_hdsp_ioctl, - .hw_params = snd_hdsp_hw_params, - .prepare = snd_hdsp_prepare, - .trigger = snd_hdsp_trigger, - .pointer = snd_hdsp_hw_pointer, - .copy = snd_hdsp_playback_copy, - .silence = snd_hdsp_hw_silence, -}; - -static struct snd_pcm_ops snd_hdsp_capture_ops = { - .open = snd_hdsp_capture_open, - .close = snd_hdsp_capture_release, - .ioctl = snd_hdsp_ioctl, - .hw_params = snd_hdsp_hw_params, - .prepare = snd_hdsp_prepare, - .trigger = snd_hdsp_trigger, - .pointer = snd_hdsp_hw_pointer, - .copy = snd_hdsp_capture_copy, -}; - -static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) -{ - struct snd_hwdep *hw; - int err; - - if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0) - return err; - - hdsp->hwdep = hw; - hw->private_data = hdsp; - strcpy(hw->name, "HDSP hwdep interface"); - - hw->ops.ioctl = snd_hdsp_hwdep_ioctl; - hw->ops.ioctl_compat = snd_hdsp_hwdep_ioctl; - - return 0; -} - -static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp) -{ - struct snd_pcm *pcm; - int err; - - if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0) - return err; - - hdsp->pcm = pcm; - pcm->private_data = hdsp; - strcpy(pcm->name, hdsp->card_name); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops); - - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - - return 0; -} - -static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp) -{ - hdsp->control2_register |= HDSP_9652_ENABLE_MIXER; - hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); -} - -static int snd_hdsp_enable_io (struct hdsp *hdsp) -{ - int i; - - if (hdsp_fifo_wait (hdsp, 0, 100)) { - snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n"); - return -EIO; - } - - for (i = 0; i < hdsp->max_channels; ++i) { - hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1); - hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1); - } - - return 0; -} - -static void snd_hdsp_initialize_channels(struct hdsp *hdsp) -{ - int status, aebi_channels, aebo_channels; - - switch (hdsp->io_type) { - case Digiface: - hdsp->card_name = "RME Hammerfall DSP + Digiface"; - hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS; - hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS; - break; - - case H9652: - hdsp->card_name = "RME Hammerfall HDSP 9652"; - hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS; - hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS; - break; - - case H9632: - status = hdsp_read(hdsp, HDSP_statusRegister); - /* HDSP_AEBx bits are low when AEB are connected */ - aebi_channels = (status & HDSP_AEBI) ? 0 : 4; - aebo_channels = (status & HDSP_AEBO) ? 0 : 4; - hdsp->card_name = "RME Hammerfall HDSP 9632"; - hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels; - hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels; - hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels; - hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels; - hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels; - hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels; - break; - - case Multiface: - hdsp->card_name = "RME Hammerfall DSP + Multiface"; - hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS; - hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS; - break; - - case RPM: - hdsp->card_name = "RME Hammerfall DSP + RPM"; - hdsp->ss_in_channels = RPM_CHANNELS-1; - hdsp->ss_out_channels = RPM_CHANNELS; - hdsp->ds_in_channels = RPM_CHANNELS-1; - hdsp->ds_out_channels = RPM_CHANNELS; - break; - - default: - /* should never get here */ - break; - } -} - -static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp) -{ - snd_hdsp_flush_midi_input (hdsp, 0); - snd_hdsp_flush_midi_input (hdsp, 1); -} - -static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp) -{ - int err; - - if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n"); - return err; - } - - - if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n"); - return err; - } - - if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { - if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n"); - return err; - } - } - - if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n"); - return err; - } - - snd_hdsp_proc_init(hdsp); - - hdsp->system_sample_rate = -1; - hdsp->playback_pid = -1; - hdsp->capture_pid = -1; - hdsp->capture_substream = NULL; - hdsp->playback_substream = NULL; - - if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n"); - return err; - } - - if (!(hdsp->state & HDSP_InitializationComplete)) { - strcpy(card->shortname, "Hammerfall DSP"); - sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, - hdsp->port, hdsp->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n"); - return err; - } - hdsp->state |= HDSP_InitializationComplete; - } - - return 0; -} - -#ifdef HDSP_FW_LOADER -/* load firmware via hotplug fw loader */ -static int hdsp_request_fw_loader(struct hdsp *hdsp) -{ - const char *fwfile; - const struct firmware *fw; - int err; - - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) - return 0; - if (hdsp->io_type == Undefined) { - if ((err = hdsp_get_iobox_version(hdsp)) < 0) - return err; - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) - return 0; - } - - /* caution: max length of firmware filename is 30! */ - switch (hdsp->io_type) { - case RPM: - fwfile = "rpm_firmware.bin"; - break; - case Multiface: - if (hdsp->firmware_rev == 0xa) - fwfile = "multiface_firmware.bin"; - else - fwfile = "multiface_firmware_rev11.bin"; - break; - case Digiface: - if (hdsp->firmware_rev == 0xa) - fwfile = "digiface_firmware.bin"; - else - fwfile = "digiface_firmware_rev11.bin"; - break; - default: - snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type); - return -EINVAL; - } - - if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) { - snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); - return -ENOENT; - } - if (fw->size < sizeof(hdsp->firmware_cache)) { - snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", - (int)fw->size, (int)sizeof(hdsp->firmware_cache)); - release_firmware(fw); - return -EINVAL; - } - - memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); - - release_firmware(fw); - - hdsp->state |= HDSP_FirmwareCached; - - if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) - return err; - - if (!(hdsp->state & HDSP_InitializationComplete)) { - if ((err = snd_hdsp_enable_io(hdsp)) < 0) - return err; - - if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n"); - return err; - } - snd_hdsp_initialize_channels(hdsp); - snd_hdsp_initialize_midi_flush(hdsp); - if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { - snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n"); - return err; - } - } - return 0; -} -#endif - -static int __devinit snd_hdsp_create(struct snd_card *card, - struct hdsp *hdsp) -{ - struct pci_dev *pci = hdsp->pci; - int err; - int is_9652 = 0; - int is_9632 = 0; - - hdsp->irq = -1; - hdsp->state = 0; - hdsp->midi[0].rmidi = NULL; - hdsp->midi[1].rmidi = NULL; - hdsp->midi[0].input = NULL; - hdsp->midi[1].input = NULL; - hdsp->midi[0].output = NULL; - hdsp->midi[1].output = NULL; - hdsp->midi[0].pending = 0; - hdsp->midi[1].pending = 0; - spin_lock_init(&hdsp->midi[0].lock); - spin_lock_init(&hdsp->midi[1].lock); - hdsp->iobase = NULL; - hdsp->control_register = 0; - hdsp->control2_register = 0; - hdsp->io_type = Undefined; - hdsp->max_channels = 26; - - hdsp->card = card; - - spin_lock_init(&hdsp->lock); - - tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp); - - pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); - hdsp->firmware_rev &= 0xff; - - /* From Martin Bjoernsen : - "It is important that the card's latency timer register in - the PCI configuration space is set to a value much larger - than 0 by the computer's BIOS or the driver. - The windows driver always sets this 8 bit register [...] - to its maximum 255 to avoid problems with some computers." - */ - pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF); - - strcpy(card->driver, "H-DSP"); - strcpy(card->mixername, "Xilinx FPGA"); - - if (hdsp->firmware_rev < 0xa) - return -ENODEV; - else if (hdsp->firmware_rev < 0x64) - hdsp->card_name = "RME Hammerfall DSP"; - else if (hdsp->firmware_rev < 0x96) { - hdsp->card_name = "RME HDSP 9652"; - is_9652 = 1; - } else { - hdsp->card_name = "RME HDSP 9632"; - hdsp->max_channels = 16; - is_9632 = 1; - } - - if ((err = pci_enable_device(pci)) < 0) - return err; - - pci_set_master(hdsp->pci); - - if ((err = pci_request_regions(pci, "hdsp")) < 0) - return err; - hdsp->port = pci_resource_start(pci, 0); - if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) { - snd_printk(KERN_ERR "Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); - return -EBUSY; - } - - if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED, - KBUILD_MODNAME, hdsp)) { - snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); - return -EBUSY; - } - - hdsp->irq = pci->irq; - hdsp->precise_ptr = 0; - hdsp->use_midi_tasklet = 1; - hdsp->dds_value = 0; - - if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) - return err; - - if (!is_9652 && !is_9632) { - /* we wait a maximum of 10 seconds to let freshly - * inserted cardbus cards do their hardware init */ - err = hdsp_wait_for_iobox(hdsp, 1000, 10); - - if (err < 0) - return err; - - if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { -#ifdef HDSP_FW_LOADER - if ((err = hdsp_request_fw_loader(hdsp)) < 0) - /* we don't fail as this can happen - if userspace is not ready for - firmware upload - */ - snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n"); - else - /* init is complete, we return */ - return 0; -#endif - /* we defer initialization */ - snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n"); - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) - return err; - return 0; - } else { - snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n"); - if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2) - hdsp->io_type = RPM; - else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) - hdsp->io_type = Multiface; - else - hdsp->io_type = Digiface; - } - } - - if ((err = snd_hdsp_enable_io(hdsp)) != 0) - return err; - - if (is_9652) - hdsp->io_type = H9652; - - if (is_9632) - hdsp->io_type = H9632; - - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) - return err; - - snd_hdsp_initialize_channels(hdsp); - snd_hdsp_initialize_midi_flush(hdsp); - - hdsp->state |= HDSP_FirmwareLoaded; - - if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) - return err; - - return 0; -} - -static int snd_hdsp_free(struct hdsp *hdsp) -{ - if (hdsp->port) { - /* stop the audio, and cancel all interrupts */ - tasklet_kill(&hdsp->midi_tasklet); - hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable); - hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register); - } - - if (hdsp->irq >= 0) - free_irq(hdsp->irq, (void *)hdsp); - - snd_hdsp_free_buffers(hdsp); - - if (hdsp->iobase) - iounmap(hdsp->iobase); - - if (hdsp->port) - pci_release_regions(hdsp->pci); - - pci_disable_device(hdsp->pci); - return 0; -} - -static void snd_hdsp_card_free(struct snd_card *card) -{ - struct hdsp *hdsp = card->private_data; - - if (hdsp) - snd_hdsp_free(hdsp); -} - -static int __devinit snd_hdsp_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct hdsp *hdsp; - struct snd_card *card; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct hdsp), &card); - if (err < 0) - return err; - - hdsp = card->private_data; - card->private_free = snd_hdsp_card_free; - hdsp->dev = dev; - hdsp->pci = pci; - snd_card_set_dev(card, &pci->dev); - - if ((err = snd_hdsp_create(card, hdsp)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->shortname, "Hammerfall DSP"); - sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, - hdsp->port, hdsp->irq); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_hdsp_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_hdsp_ids, - .probe = snd_hdsp_probe, - .remove = __devexit_p(snd_hdsp_remove), -}; - -static int __init alsa_card_hdsp_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_hdsp_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_hdsp_init) -module_exit(alsa_card_hdsp_exit) diff --git a/ANDROID_3.4.5/sound/pci/rme9652/hdspm.c b/ANDROID_3.4.5/sound/pci/rme9652/hdspm.c deleted file mode 100644 index bc030a20..00000000 --- a/ANDROID_3.4.5/sound/pci/rme9652/hdspm.c +++ /dev/null @@ -1,6940 +0,0 @@ -/* - * ALSA driver for RME Hammerfall DSP MADI audio interface(s) - * - * Copyright (c) 2003 Winfried Ritsch (IEM) - * code based on hdsp.c Paul Davis - * Marcus Andersson - * Thomas Charbonnel - * Modified 2006-06-01 for AES32 support by Remy Bruno - * - * - * Modified 2009-04-13 for proper metering by Florian Faber - * - * - * Modified 2009-04-14 for native float support by Florian Faber - * - * - * Modified 2009-04-26 fixed bug in rms metering by Florian Faber - * - * - * Modified 2009-04-30 added hw serial number support by Florian Faber - * - * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth - * - * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for RME HDSPM interface."); - -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for RME HDSPM interface."); - -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards."); - - -MODULE_AUTHOR -( - "Winfried Ritsch , " - "Paul Davis , " - "Marcus Andersson, Thomas Charbonnel , " - "Remy Bruno , " - "Florian Faber , " - "Adrian Knoth " -); -MODULE_DESCRIPTION("RME HDSPM"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); - -/* --- Write registers. --- - These are defined as byte-offsets from the iobase value. */ - -#define HDSPM_WR_SETTINGS 0 -#define HDSPM_outputBufferAddress 32 -#define HDSPM_inputBufferAddress 36 -#define HDSPM_controlRegister 64 -#define HDSPM_interruptConfirmation 96 -#define HDSPM_control2Reg 256 /* not in specs ???????? */ -#define HDSPM_freqReg 256 /* for AES32 */ -#define HDSPM_midiDataOut0 352 /* just believe in old code */ -#define HDSPM_midiDataOut1 356 -#define HDSPM_eeprom_wr 384 /* for AES32 */ - -/* DMA enable for 64 channels, only Bit 0 is relevant */ -#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ -#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */ - -/* 16 page addresses for each of the 64 channels DMA buffer in and out - (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */ -#define HDSPM_pageAddressBufferOut 8192 -#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4) - -#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */ - -#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */ - -/* --- Read registers. --- - These are defined as byte-offsets from the iobase value */ -#define HDSPM_statusRegister 0 -/*#define HDSPM_statusRegister2 96 */ -/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at - * offset 192, for AES32 *and* MADI - * => need to check that offset 192 is working on MADI */ -#define HDSPM_statusRegister2 192 -#define HDSPM_timecodeRegister 128 - -/* AIO, RayDAT */ -#define HDSPM_RD_STATUS_0 0 -#define HDSPM_RD_STATUS_1 64 -#define HDSPM_RD_STATUS_2 128 -#define HDSPM_RD_STATUS_3 192 - -#define HDSPM_RD_TCO 256 -#define HDSPM_RD_PLL_FREQ 512 -#define HDSPM_WR_TCO 128 - -#define HDSPM_TCO1_TCO_lock 0x00000001 -#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002 -#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004 -#define HDSPM_TCO1_LTC_Input_valid 0x00000008 -#define HDSPM_TCO1_WCK_Input_valid 0x00000010 -#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020 -#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040 - -#define HDSPM_TCO1_set_TC 0x00000100 -#define HDSPM_TCO1_set_drop_frame_flag 0x00000200 -#define HDSPM_TCO1_LTC_Format_LSB 0x00000400 -#define HDSPM_TCO1_LTC_Format_MSB 0x00000800 - -#define HDSPM_TCO2_TC_run 0x00010000 -#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000 -#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000 -#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000 -#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000 -#define HDSPM_TCO2_set_jam_sync 0x00200000 -#define HDSPM_TCO2_set_flywheel 0x00400000 - -#define HDSPM_TCO2_set_01_4 0x01000000 -#define HDSPM_TCO2_set_pull_down 0x02000000 -#define HDSPM_TCO2_set_pull_up 0x04000000 -#define HDSPM_TCO2_set_freq 0x08000000 -#define HDSPM_TCO2_set_term_75R 0x10000000 -#define HDSPM_TCO2_set_input_LSB 0x20000000 -#define HDSPM_TCO2_set_input_MSB 0x40000000 -#define HDSPM_TCO2_set_freq_from_app 0x80000000 - - -#define HDSPM_midiDataOut0 352 -#define HDSPM_midiDataOut1 356 -#define HDSPM_midiDataOut2 368 - -#define HDSPM_midiDataIn0 360 -#define HDSPM_midiDataIn1 364 -#define HDSPM_midiDataIn2 372 -#define HDSPM_midiDataIn3 376 - -/* status is data bytes in MIDI-FIFO (0-128) */ -#define HDSPM_midiStatusOut0 384 -#define HDSPM_midiStatusOut1 388 -#define HDSPM_midiStatusOut2 400 - -#define HDSPM_midiStatusIn0 392 -#define HDSPM_midiStatusIn1 396 -#define HDSPM_midiStatusIn2 404 -#define HDSPM_midiStatusIn3 408 - - -/* the meters are regular i/o-mapped registers, but offset - considerably from the rest. the peak registers are reset - when read; the least-significant 4 bits are full-scale counters; - the actual peak value is in the most-significant 24 bits. -*/ - -#define HDSPM_MADI_INPUT_PEAK 4096 -#define HDSPM_MADI_PLAYBACK_PEAK 4352 -#define HDSPM_MADI_OUTPUT_PEAK 4608 - -#define HDSPM_MADI_INPUT_RMS_L 6144 -#define HDSPM_MADI_PLAYBACK_RMS_L 6400 -#define HDSPM_MADI_OUTPUT_RMS_L 6656 - -#define HDSPM_MADI_INPUT_RMS_H 7168 -#define HDSPM_MADI_PLAYBACK_RMS_H 7424 -#define HDSPM_MADI_OUTPUT_RMS_H 7680 - -/* --- Control Register bits --------- */ -#define HDSPM_Start (1<<0) /* start engine */ - -#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */ -#define HDSPM_Latency1 (1<<2) /* where n is defined */ -#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */ - -#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */ -#define HDSPM_c0Master 0x1 /* Master clock bit in settings - register [RayDAT, AIO] */ - -#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */ - -#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */ -#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */ -#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */ -#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */ - -#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */ -#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1, - 56channelMODE=0 */ /* MADI ONLY*/ -#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */ - -#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, - 0=off, 1=on */ /* MADI ONLY */ -#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ - -#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax - * -- MADI ONLY - */ -#define HDSPM_InputSelect1 (1<<15) /* should be 0 */ - -#define HDSPM_SyncRef2 (1<<13) -#define HDSPM_SyncRef3 (1<<25) - -#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */ -#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use - AES additional bits in - lower 5 Audiodatabits ??? */ -#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */ -#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */ - -#define HDSPM_Midi0InterruptEnable 0x0400000 -#define HDSPM_Midi1InterruptEnable 0x0800000 -#define HDSPM_Midi2InterruptEnable 0x0200000 -#define HDSPM_Midi3InterruptEnable 0x4000000 - -#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ -#define HDSPe_FLOAT_FORMAT 0x2000000 - -#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */ -#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */ -#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */ - -#define HDSPM_wclk_sel (1<<30) - -/* --- bit helper defines */ -#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) -#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\ - HDSPM_DoubleSpeed|HDSPM_QuadSpeed) -#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) -#define HDSPM_InputOptical 0 -#define HDSPM_InputCoaxial (HDSPM_InputSelect0) -#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\ - HDSPM_SyncRef2|HDSPM_SyncRef3) - -#define HDSPM_c0_SyncRef0 0x2 -#define HDSPM_c0_SyncRef1 0x4 -#define HDSPM_c0_SyncRef2 0x8 -#define HDSPM_c0_SyncRef3 0x10 -#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\ - HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3) - -#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */ -#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */ -#define HDSPM_SYNC_FROM_TCO 2 -#define HDSPM_SYNC_FROM_SYNC_IN 3 - -#define HDSPM_Frequency32KHz HDSPM_Frequency0 -#define HDSPM_Frequency44_1KHz HDSPM_Frequency1 -#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0) -#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) -#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) -#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\ - HDSPM_Frequency0) -#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0) -#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1) -#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\ - HDSPM_Frequency0) - - -/* Synccheck Status */ -#define HDSPM_SYNC_CHECK_NO_LOCK 0 -#define HDSPM_SYNC_CHECK_LOCK 1 -#define HDSPM_SYNC_CHECK_SYNC 2 - -/* AutoSync References - used by "autosync_ref" control switch */ -#define HDSPM_AUTOSYNC_FROM_WORD 0 -#define HDSPM_AUTOSYNC_FROM_MADI 1 -#define HDSPM_AUTOSYNC_FROM_TCO 2 -#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3 -#define HDSPM_AUTOSYNC_FROM_NONE 4 - -/* Possible sources of MADI input */ -#define HDSPM_OPTICAL 0 /* optical */ -#define HDSPM_COAXIAL 1 /* BNC */ - -#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask) -#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1)) - -#define hdspm_encode_in(x) (((x)&0x3)<<14) -#define hdspm_decode_in(x) (((x)>>14)&0x3) - -/* --- control2 register bits --- */ -#define HDSPM_TMS (1<<0) -#define HDSPM_TCK (1<<1) -#define HDSPM_TDI (1<<2) -#define HDSPM_JTAG (1<<3) -#define HDSPM_PWDN (1<<4) -#define HDSPM_PROGRAM (1<<5) -#define HDSPM_CONFIG_MODE_0 (1<<6) -#define HDSPM_CONFIG_MODE_1 (1<<7) -/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/ -#define HDSPM_BIGENDIAN_MODE (1<<9) -#define HDSPM_RD_MULTIPLE (1<<10) - -/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and - that do not conflict with specific bits for AES32 seem to be valid also - for the AES32 - */ -#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ -#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */ -#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 - * (like inp0) - */ - -#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ -#define HDSPM_madiSync (1<<18) /* MADI is in sync */ - -#define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */ -#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */ - -#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */ -#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */ - -#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ - /* since 64byte accurate, last 6 bits are not used */ - - - -#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */ - -#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */ -#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */ -#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */ -#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */ - -#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with - * Interrupt - */ -#define HDSPM_tco_detect 0x08000000 -#define HDSPM_tco_lock 0x20000000 - -#define HDSPM_s2_tco_detect 0x00000040 -#define HDSPM_s2_AEBO_D 0x00000080 -#define HDSPM_s2_AEBI_D 0x00000100 - - -#define HDSPM_midi0IRQPending 0x40000000 -#define HDSPM_midi1IRQPending 0x80000000 -#define HDSPM_midi2IRQPending 0x20000000 -#define HDSPM_midi2IRQPendingAES 0x00000020 -#define HDSPM_midi3IRQPending 0x00200000 - -/* --- status bit helpers */ -#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\ - HDSPM_madiFreq2|HDSPM_madiFreq3) -#define HDSPM_madiFreq32 (HDSPM_madiFreq0) -#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1) -#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1) -#define HDSPM_madiFreq64 (HDSPM_madiFreq2) -#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2) -#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2) -#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2) -#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3) -#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0) - -/* Status2 Register bits */ /* MADI ONLY */ - -#define HDSPM_version0 (1<<0) /* not really defined but I guess */ -#define HDSPM_version1 (1<<1) /* in former cards it was ??? */ -#define HDSPM_version2 (1<<2) - -#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */ -#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */ - -#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */ -#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */ -#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */ -/* missing Bit for 111=128, 1000=176.4, 1001=192 */ - -#define HDSPM_SyncRef0 0x10000 /* Sync Reference */ -#define HDSPM_SyncRef1 0x20000 - -#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */ -#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */ -#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */ - -#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync) - -#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2) -#define HDSPM_wcFreq32 (HDSPM_wc_freq0) -#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1) -#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1) -#define HDSPM_wcFreq64 (HDSPM_wc_freq2) -#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) -#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) - -#define HDSPM_status1_F_0 0x0400000 -#define HDSPM_status1_F_1 0x0800000 -#define HDSPM_status1_F_2 0x1000000 -#define HDSPM_status1_F_3 0x2000000 -#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3) - - -#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ - HDSPM_SelSyncRef2) -#define HDSPM_SelSyncRef_WORD 0 -#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) -#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1) -#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1) -#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ - HDSPM_SelSyncRef2) - -/* - For AES32, bits for status, status2 and timecode are different -*/ -/* status */ -#define HDSPM_AES32_wcLock 0x0200000 -#define HDSPM_AES32_wcFreq_bit 22 -/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function - HDSPM_bit2freq */ -#define HDSPM_AES32_syncref_bit 16 -/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */ - -#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0 -#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1 -#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2 -#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3 -#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4 -#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5 -#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6 -#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7 -#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8 -#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9 - -/* status2 */ -/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */ -#define HDSPM_LockAES 0x80 -#define HDSPM_LockAES1 0x80 -#define HDSPM_LockAES2 0x40 -#define HDSPM_LockAES3 0x20 -#define HDSPM_LockAES4 0x10 -#define HDSPM_LockAES5 0x8 -#define HDSPM_LockAES6 0x4 -#define HDSPM_LockAES7 0x2 -#define HDSPM_LockAES8 0x1 -/* - Timecode - After windows driver sources, bits 4*i to 4*i+3 give the input frequency on - AES i+1 - bits 3210 - 0001 32kHz - 0010 44.1kHz - 0011 48kHz - 0100 64kHz - 0101 88.2kHz - 0110 96kHz - 0111 128kHz - 1000 176.4kHz - 1001 192kHz - NB: Timecode register doesn't seem to work on AES32 card revision 230 -*/ - -/* Mixer Values */ -#define UNITY_GAIN 32768 /* = 65536/2 */ -#define MINUS_INFINITY_GAIN 0 - -/* Number of channels for different Speed Modes */ -#define MADI_SS_CHANNELS 64 -#define MADI_DS_CHANNELS 32 -#define MADI_QS_CHANNELS 16 - -#define RAYDAT_SS_CHANNELS 36 -#define RAYDAT_DS_CHANNELS 20 -#define RAYDAT_QS_CHANNELS 12 - -#define AIO_IN_SS_CHANNELS 14 -#define AIO_IN_DS_CHANNELS 10 -#define AIO_IN_QS_CHANNELS 8 -#define AIO_OUT_SS_CHANNELS 16 -#define AIO_OUT_DS_CHANNELS 12 -#define AIO_OUT_QS_CHANNELS 10 - -#define AES32_CHANNELS 16 - -/* the size of a substream (1 mono data stream) */ -#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024) -#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES) - -/* the size of the area we need to allocate for DMA transfers. the - size is the same regardless of the number of channels, and - also the latency to use. - for one direction !!! -*/ -#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) -#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) - -#define HDSPM_RAYDAT_REV 211 -#define HDSPM_AIO_REV 212 -#define HDSPM_MADIFACE_REV 213 - -/* speed factor modes */ -#define HDSPM_SPEED_SINGLE 0 -#define HDSPM_SPEED_DOUBLE 1 -#define HDSPM_SPEED_QUAD 2 - -/* names for speed modes */ -static char *hdspm_speed_names[] = { "single", "double", "quad" }; - -static char *texts_autosync_aes_tco[] = { "Word Clock", - "AES1", "AES2", "AES3", "AES4", - "AES5", "AES6", "AES7", "AES8", - "TCO" }; -static char *texts_autosync_aes[] = { "Word Clock", - "AES1", "AES2", "AES3", "AES4", - "AES5", "AES6", "AES7", "AES8" }; -static char *texts_autosync_madi_tco[] = { "Word Clock", - "MADI", "TCO", "Sync In" }; -static char *texts_autosync_madi[] = { "Word Clock", - "MADI", "Sync In" }; - -static char *texts_autosync_raydat_tco[] = { - "Word Clock", - "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4", - "AES", "SPDIF", "TCO", "Sync In" -}; -static char *texts_autosync_raydat[] = { - "Word Clock", - "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4", - "AES", "SPDIF", "Sync In" -}; -static char *texts_autosync_aio_tco[] = { - "Word Clock", - "ADAT", "AES", "SPDIF", "TCO", "Sync In" -}; -static char *texts_autosync_aio[] = { "Word Clock", - "ADAT", "AES", "SPDIF", "Sync In" }; - -static char *texts_freq[] = { - "No Lock", - "32 kHz", - "44.1 kHz", - "48 kHz", - "64 kHz", - "88.2 kHz", - "96 kHz", - "128 kHz", - "176.4 kHz", - "192 kHz" -}; - -static char *texts_ports_madi[] = { - "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6", - "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12", - "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18", - "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24", - "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30", - "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36", - "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42", - "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48", - "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54", - "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60", - "MADI.61", "MADI.62", "MADI.63", "MADI.64", -}; - - -static char *texts_ports_raydat_ss[] = { - "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6", - "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", - "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2", - "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8", - "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6", - "ADAT4.7", "ADAT4.8", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R" -}; - -static char *texts_ports_raydat_ds[] = { - "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", - "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", - "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4", - "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R" -}; - -static char *texts_ports_raydat_qs[] = { - "ADAT1.1", "ADAT1.2", - "ADAT2.1", "ADAT2.2", - "ADAT3.1", "ADAT3.2", - "ADAT4.1", "ADAT4.2", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R" -}; - - -static char *texts_ports_aio_in_ss[] = { - "Analogue.L", "Analogue.R", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R", - "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6", - "ADAT.7", "ADAT.8" -}; - -static char *texts_ports_aio_out_ss[] = { - "Analogue.L", "Analogue.R", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R", - "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6", - "ADAT.7", "ADAT.8", - "Phone.L", "Phone.R" -}; - -static char *texts_ports_aio_in_ds[] = { - "Analogue.L", "Analogue.R", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R", - "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4" -}; - -static char *texts_ports_aio_out_ds[] = { - "Analogue.L", "Analogue.R", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R", - "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", - "Phone.L", "Phone.R" -}; - -static char *texts_ports_aio_in_qs[] = { - "Analogue.L", "Analogue.R", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R", - "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4" -}; - -static char *texts_ports_aio_out_qs[] = { - "Analogue.L", "Analogue.R", - "AES.L", "AES.R", - "SPDIF.L", "SPDIF.R", - "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", - "Phone.L", "Phone.R" -}; - -static char *texts_ports_aes32[] = { - "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7", - "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14", - "AES.15", "AES.16" -}; - -/* These tables map the ALSA channels 1..N to the channels that we - need to use in order to find the relevant channel buffer. RME - refers to this kind of mapping as between "the ADAT channel and - the DMA channel." We index it using the logical audio channel, - and the value is the DMA channel (i.e. channel buffer number) - where the data for that channel can be read/written from/to. -*/ - -static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63 -}; - -static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = { - 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */ - 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */ - 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */ - 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */ - 0, 1, /* AES */ - 2, 3, /* SPDIF */ - -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -}; - -static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = { - 4, 5, 6, 7, /* ADAT 1 */ - 8, 9, 10, 11, /* ADAT 2 */ - 12, 13, 14, 15, /* ADAT 3 */ - 16, 17, 18, 19, /* ADAT 4 */ - 0, 1, /* AES */ - 2, 3, /* SPDIF */ - -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -}; - -static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = { - 4, 5, /* ADAT 1 */ - 6, 7, /* ADAT 2 */ - 8, 9, /* ADAT 3 */ - 10, 11, /* ADAT 4 */ - 0, 1, /* AES */ - 2, 3, /* SPDIF */ - -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -}; - -static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = { - 0, 1, /* line in */ - 8, 9, /* aes in, */ - 10, 11, /* spdif in */ - 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */ - -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -}; - -static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = { - 0, 1, /* line out */ - 8, 9, /* aes out */ - 10, 11, /* spdif out */ - 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */ - 6, 7, /* phone out */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -}; - -static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = { - 0, 1, /* line in */ - 8, 9, /* aes in */ - 10, 11, /* spdif in */ - 12, 14, 16, 18, /* adat in */ - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = { - 0, 1, /* line out */ - 8, 9, /* aes out */ - 10, 11, /* spdif out */ - 12, 14, 16, 18, /* adat out */ - 6, 7, /* phone out */ - -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = { - 0, 1, /* line in */ - 8, 9, /* aes in */ - 10, 11, /* spdif in */ - 12, 16, /* adat in */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = { - 0, 1, /* line out */ - 8, 9, /* aes out */ - 10, 11, /* spdif out */ - 12, 16, /* adat out */ - 6, 7, /* phone out */ - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_aes32[HDSPM_MAX_CHANNELS] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -struct hdspm_midi { - struct hdspm *hdspm; - int id; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *input; - struct snd_rawmidi_substream *output; - char istimer; /* timer in use */ - struct timer_list timer; - spinlock_t lock; - int pending; - int dataIn; - int statusIn; - int dataOut; - int statusOut; - int ie; - int irq; -}; - -struct hdspm_tco { - int input; - int framerate; - int wordclock; - int samplerate; - int pull; - int term; /* 0 = off, 1 = on */ -}; - -struct hdspm { - spinlock_t lock; - /* only one playback and/or capture stream */ - struct snd_pcm_substream *capture_substream; - struct snd_pcm_substream *playback_substream; - - char *card_name; /* for procinfo */ - unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ - - uint8_t io_type; - - int monitor_outs; /* set up monitoring outs init flag */ - - u32 control_register; /* cached value */ - u32 control2_register; /* cached value */ - u32 settings_register; - - struct hdspm_midi midi[4]; - struct tasklet_struct midi_tasklet; - - size_t period_bytes; - unsigned char ss_in_channels; - unsigned char ds_in_channels; - unsigned char qs_in_channels; - unsigned char ss_out_channels; - unsigned char ds_out_channels; - unsigned char qs_out_channels; - - unsigned char max_channels_in; - unsigned char max_channels_out; - - signed char *channel_map_in; - signed char *channel_map_out; - - signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; - signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; - - char **port_names_in; - char **port_names_out; - - char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs; - char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs; - - unsigned char *playback_buffer; /* suitably aligned address */ - unsigned char *capture_buffer; /* suitably aligned address */ - - pid_t capture_pid; /* process id which uses capture */ - pid_t playback_pid; /* process id which uses capture */ - int running; /* running status */ - - int last_external_sample_rate; /* samplerate mystic ... */ - int last_internal_sample_rate; - int system_sample_rate; - - int dev; /* Hardware vars... */ - int irq; - unsigned long port; - void __iomem *iobase; - - int irq_count; /* for debug */ - int midiPorts; - - struct snd_card *card; /* one card */ - struct snd_pcm *pcm; /* has one pcm */ - struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */ - struct pci_dev *pci; /* and an pci info */ - - /* Mixer vars */ - /* fast alsa mixer */ - struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; - /* but input to much, so not used */ - struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; - /* full mixer accessible over mixer ioctl or hwdep-device */ - struct hdspm_mixer *mixer; - - struct hdspm_tco *tco; /* NULL if no TCO detected */ - - char **texts_autosync; - int texts_autosync_items; - - cycles_t last_interrupt; - - unsigned int serial; - - struct hdspm_peak_rms peak_rms; -}; - - -static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = { - { - .vendor = PCI_VENDOR_ID_XILINX, - .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .class = 0, - .class_mask = 0, - .driver_data = 0}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci, snd_hdspm_ids); - -/* prototypes */ -static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, - struct hdspm * hdspm); -static int __devinit snd_hdspm_create_pcm(struct snd_card *card, - struct hdspm * hdspm); - -static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); -static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); -static int hdspm_autosync_ref(struct hdspm *hdspm); -static int snd_hdspm_set_defaults(struct hdspm *hdspm); -static void hdspm_set_sgbuf(struct hdspm *hdspm, - struct snd_pcm_substream *substream, - unsigned int reg, int channels); - -static inline int HDSPM_bit2freq(int n) -{ - static const int bit2freq_tab[] = { - 0, 32000, 44100, 48000, 64000, 88200, - 96000, 128000, 176400, 192000 }; - if (n < 1 || n > 9) - return 0; - return bit2freq_tab[n]; -} - -/* Write/read to/from HDSPM with Adresses in Bytes - not words but only 32Bit writes are allowed */ - -static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg, - unsigned int val) -{ - writel(val, hdspm->iobase + reg); -} - -static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg) -{ - return readl(hdspm->iobase + reg); -} - -/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader - mixer is write only on hardware so we have to cache him for read - each fader is a u32, but uses only the first 16 bit */ - -static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan, - unsigned int in) -{ - if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS) - return 0; - - return hdspm->mixer->ch[chan].in[in]; -} - -static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan, - unsigned int pb) -{ - if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS) - return 0; - return hdspm->mixer->ch[chan].pb[pb]; -} - -static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan, - unsigned int in, unsigned short data) -{ - if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS) - return -1; - - hdspm_write(hdspm, - HDSPM_MADI_mixerBase + - ((in + 128 * chan) * sizeof(u32)), - (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF)); - return 0; -} - -static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan, - unsigned int pb, unsigned short data) -{ - if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS) - return -1; - - hdspm_write(hdspm, - HDSPM_MADI_mixerBase + - ((64 + pb + 128 * chan) * sizeof(u32)), - (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF)); - return 0; -} - - -/* enable DMA for specific channels, now available for DSP-MADI */ -static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v) -{ - hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v); -} - -static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v) -{ - hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v); -} - -/* check if same process is writing and reading */ -static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm) -{ - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&hdspm->lock, flags); - if ((hdspm->playback_pid != hdspm->capture_pid) && - (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) { - ret = 0; - } - spin_unlock_irqrestore(&hdspm->lock, flags); - return ret; -} - -/* check for external sample rate */ -static int hdspm_external_sample_rate(struct hdspm *hdspm) -{ - unsigned int status, status2, timecode; - int syncref, rate = 0, rate_bits; - - switch (hdspm->io_type) { - case AES32: - status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - status = hdspm_read(hdspm, HDSPM_statusRegister); - timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); - - syncref = hdspm_autosync_ref(hdspm); - - if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && - status & HDSPM_AES32_wcLock) - return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF); - - if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && - syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && - status2 & (HDSPM_LockAES >> - (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))) - return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF); - return 0; - break; - - case MADIface: - status = hdspm_read(hdspm, HDSPM_statusRegister); - - if (!(status & HDSPM_madiLock)) { - rate = 0; /* no lock */ - } else { - switch (status & (HDSPM_status1_freqMask)) { - case HDSPM_status1_F_0*1: - rate = 32000; break; - case HDSPM_status1_F_0*2: - rate = 44100; break; - case HDSPM_status1_F_0*3: - rate = 48000; break; - case HDSPM_status1_F_0*4: - rate = 64000; break; - case HDSPM_status1_F_0*5: - rate = 88200; break; - case HDSPM_status1_F_0*6: - rate = 96000; break; - case HDSPM_status1_F_0*7: - rate = 128000; break; - case HDSPM_status1_F_0*8: - rate = 176400; break; - case HDSPM_status1_F_0*9: - rate = 192000; break; - default: - rate = 0; break; - } - } - - break; - - case MADI: - case AIO: - case RayDAT: - status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - status = hdspm_read(hdspm, HDSPM_statusRegister); - rate = 0; - - /* if wordclock has synced freq and wordclock is valid */ - if ((status2 & HDSPM_wcLock) != 0 && - (status2 & HDSPM_SelSyncRef0) == 0) { - - rate_bits = status2 & HDSPM_wcFreqMask; - - - switch (rate_bits) { - case HDSPM_wcFreq32: - rate = 32000; - break; - case HDSPM_wcFreq44_1: - rate = 44100; - break; - case HDSPM_wcFreq48: - rate = 48000; - break; - case HDSPM_wcFreq64: - rate = 64000; - break; - case HDSPM_wcFreq88_2: - rate = 88200; - break; - case HDSPM_wcFreq96: - rate = 96000; - break; - default: - rate = 0; - break; - } - } - - /* if rate detected and Syncref is Word than have it, - * word has priority to MADI - */ - if (rate != 0 && - (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) - return rate; - - /* maybe a madi input (which is taken if sel sync is madi) */ - if (status & HDSPM_madiLock) { - rate_bits = status & HDSPM_madiFreqMask; - - switch (rate_bits) { - case HDSPM_madiFreq32: - rate = 32000; - break; - case HDSPM_madiFreq44_1: - rate = 44100; - break; - case HDSPM_madiFreq48: - rate = 48000; - break; - case HDSPM_madiFreq64: - rate = 64000; - break; - case HDSPM_madiFreq88_2: - rate = 88200; - break; - case HDSPM_madiFreq96: - rate = 96000; - break; - case HDSPM_madiFreq128: - rate = 128000; - break; - case HDSPM_madiFreq176_4: - rate = 176400; - break; - case HDSPM_madiFreq192: - rate = 192000; - break; - default: - rate = 0; - break; - } - - /* QS and DS rates normally can not be detected - * automatically by the card. Only exception is MADI - * in 96k frame mode. - * - * So if we read SS values (32 .. 48k), check for - * user-provided DS/QS bits in the control register - * and multiply the base frequency accordingly. - */ - if (rate <= 48000) { - if (hdspm->control_register & HDSPM_QuadSpeed) - rate *= 4; - else if (hdspm->control_register & - HDSPM_DoubleSpeed) - rate *= 2; - } - } - break; - } - - return rate; -} - -/* return latency in samples per period */ -static int hdspm_get_latency(struct hdspm *hdspm) -{ - int n; - - n = hdspm_decode_latency(hdspm->control_register); - - /* Special case for new RME cards with 32 samples period size. - * The three latency bits in the control register - * (HDSP_LatencyMask) encode latency values of 64 samples as - * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7 - * denotes 8192 samples, but on new cards like RayDAT or AIO, - * it corresponds to 32 samples. - */ - if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type)) - n = -1; - - return 1 << (n + 6); -} - -/* Latency function */ -static inline void hdspm_compute_period_size(struct hdspm *hdspm) -{ - hdspm->period_bytes = 4 * hdspm_get_latency(hdspm); -} - - -static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm) -{ - int position; - - position = hdspm_read(hdspm, HDSPM_statusRegister); - - switch (hdspm->io_type) { - case RayDAT: - case AIO: - position &= HDSPM_BufferPositionMask; - position /= 4; /* Bytes per sample */ - break; - default: - position = (position & HDSPM_BufferID) ? - (hdspm->period_bytes / 4) : 0; - } - - return position; -} - - -static inline void hdspm_start_audio(struct hdspm * s) -{ - s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start); - hdspm_write(s, HDSPM_controlRegister, s->control_register); -} - -static inline void hdspm_stop_audio(struct hdspm * s) -{ - s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable); - hdspm_write(s, HDSPM_controlRegister, s->control_register); -} - -/* should I silence all or only opened ones ? doit all for first even is 4MB*/ -static void hdspm_silence_playback(struct hdspm *hdspm) -{ - int i; - int n = hdspm->period_bytes; - void *buf = hdspm->playback_buffer; - - if (buf == NULL) - return; - - for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { - memset(buf, 0, n); - buf += HDSPM_CHANNEL_BUFFER_BYTES; - } -} - -static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames) -{ - int n; - - spin_lock_irq(&s->lock); - - if (32 == frames) { - /* Special case for new RME cards like RayDAT/AIO which - * support period sizes of 32 samples. Since latency is - * encoded in the three bits of HDSP_LatencyMask, we can only - * have values from 0 .. 7. While 0 still means 64 samples and - * 6 represents 4096 samples on all cards, 7 represents 8192 - * on older cards and 32 samples on new cards. - * - * In other words, period size in samples is calculated by - * 2^(n+6) with n ranging from 0 .. 7. - */ - n = 7; - } else { - frames >>= 7; - n = 0; - while (frames) { - n++; - frames >>= 1; - } - } - - s->control_register &= ~HDSPM_LatencyMask; - s->control_register |= hdspm_encode_latency(n); - - hdspm_write(s, HDSPM_controlRegister, s->control_register); - - hdspm_compute_period_size(s); - - spin_unlock_irq(&s->lock); - - return 0; -} - -static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period) -{ - u64 freq_const; - - if (period == 0) - return 0; - - switch (hdspm->io_type) { - case MADI: - case AES32: - freq_const = 110069313433624ULL; - break; - case RayDAT: - case AIO: - freq_const = 104857600000000ULL; - break; - case MADIface: - freq_const = 131072000000000ULL; - break; - default: - snd_BUG(); - return 0; - } - - return div_u64(freq_const, period); -} - - -static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) -{ - u64 n; - - if (rate >= 112000) - rate /= 4; - else if (rate >= 56000) - rate /= 2; - - switch (hdspm->io_type) { - case MADIface: - n = 131072000000000ULL; /* 125 MHz */ - break; - case MADI: - case AES32: - n = 110069313433624ULL; /* 105 MHz */ - break; - case RayDAT: - case AIO: - n = 104857600000000ULL; /* 100 MHz */ - break; - default: - snd_BUG(); - return; - } - - n = div_u64(n, rate); - /* n should be less than 2^32 for being written to FREQ register */ - snd_BUG_ON(n >> 32); - hdspm_write(hdspm, HDSPM_freqReg, (u32)n); -} - -/* dummy set rate lets see what happens */ -static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) -{ - int current_rate; - int rate_bits; - int not_set = 0; - int current_speed, target_speed; - - /* ASSUMPTION: hdspm->lock is either set, or there is no need for - it (e.g. during module initialization). - */ - - if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { - - /* SLAVE --- */ - if (called_internally) { - - /* request from ctl or card initialization - just make a warning an remember setting - for future master mode switching */ - - snd_printk(KERN_WARNING "HDSPM: " - "Warning: device is not running " - "as a clock master.\n"); - not_set = 1; - } else { - - /* hw_param request while in AutoSync mode */ - int external_freq = - hdspm_external_sample_rate(hdspm); - - if (hdspm_autosync_ref(hdspm) == - HDSPM_AUTOSYNC_FROM_NONE) { - - snd_printk(KERN_WARNING "HDSPM: " - "Detected no Externel Sync \n"); - not_set = 1; - - } else if (rate != external_freq) { - - snd_printk(KERN_WARNING "HDSPM: " - "Warning: No AutoSync source for " - "requested rate\n"); - not_set = 1; - } - } - } - - current_rate = hdspm->system_sample_rate; - - /* Changing between Singe, Double and Quad speed is not - allowed if any substreams are open. This is because such a change - causes a shift in the location of the DMA buffers and a reduction - in the number of available buffers. - - Note that a similar but essentially insoluble problem exists for - externally-driven rate changes. All we can do is to flag rate - changes in the read/write routines. - */ - - if (current_rate <= 48000) - current_speed = HDSPM_SPEED_SINGLE; - else if (current_rate <= 96000) - current_speed = HDSPM_SPEED_DOUBLE; - else - current_speed = HDSPM_SPEED_QUAD; - - if (rate <= 48000) - target_speed = HDSPM_SPEED_SINGLE; - else if (rate <= 96000) - target_speed = HDSPM_SPEED_DOUBLE; - else - target_speed = HDSPM_SPEED_QUAD; - - switch (rate) { - case 32000: - rate_bits = HDSPM_Frequency32KHz; - break; - case 44100: - rate_bits = HDSPM_Frequency44_1KHz; - break; - case 48000: - rate_bits = HDSPM_Frequency48KHz; - break; - case 64000: - rate_bits = HDSPM_Frequency64KHz; - break; - case 88200: - rate_bits = HDSPM_Frequency88_2KHz; - break; - case 96000: - rate_bits = HDSPM_Frequency96KHz; - break; - case 128000: - rate_bits = HDSPM_Frequency128KHz; - break; - case 176400: - rate_bits = HDSPM_Frequency176_4KHz; - break; - case 192000: - rate_bits = HDSPM_Frequency192KHz; - break; - default: - return -EINVAL; - } - - if (current_speed != target_speed - && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) { - snd_printk - (KERN_ERR "HDSPM: " - "cannot change from %s speed to %s speed mode " - "(capture PID = %d, playback PID = %d)\n", - hdspm_speed_names[current_speed], - hdspm_speed_names[target_speed], - hdspm->capture_pid, hdspm->playback_pid); - return -EBUSY; - } - - hdspm->control_register &= ~HDSPM_FrequencyMask; - hdspm->control_register |= rate_bits; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - /* For AES32, need to set DDS value in FREQ register - For MADI, also apparently */ - hdspm_set_dds_value(hdspm, rate); - - if (AES32 == hdspm->io_type && rate != current_rate) - hdspm_write(hdspm, HDSPM_eeprom_wr, 0); - - hdspm->system_sample_rate = rate; - - if (rate <= 48000) { - hdspm->channel_map_in = hdspm->channel_map_in_ss; - hdspm->channel_map_out = hdspm->channel_map_out_ss; - hdspm->max_channels_in = hdspm->ss_in_channels; - hdspm->max_channels_out = hdspm->ss_out_channels; - hdspm->port_names_in = hdspm->port_names_in_ss; - hdspm->port_names_out = hdspm->port_names_out_ss; - } else if (rate <= 96000) { - hdspm->channel_map_in = hdspm->channel_map_in_ds; - hdspm->channel_map_out = hdspm->channel_map_out_ds; - hdspm->max_channels_in = hdspm->ds_in_channels; - hdspm->max_channels_out = hdspm->ds_out_channels; - hdspm->port_names_in = hdspm->port_names_in_ds; - hdspm->port_names_out = hdspm->port_names_out_ds; - } else { - hdspm->channel_map_in = hdspm->channel_map_in_qs; - hdspm->channel_map_out = hdspm->channel_map_out_qs; - hdspm->max_channels_in = hdspm->qs_in_channels; - hdspm->max_channels_out = hdspm->qs_out_channels; - hdspm->port_names_in = hdspm->port_names_in_qs; - hdspm->port_names_out = hdspm->port_names_out_qs; - } - - if (not_set != 0) - return -1; - - return 0; -} - -/* mainly for init to 0 on load */ -static void all_in_all_mixer(struct hdspm * hdspm, int sgain) -{ - int i, j; - unsigned int gain; - - if (sgain > UNITY_GAIN) - gain = UNITY_GAIN; - else if (sgain < 0) - gain = 0; - else - gain = sgain; - - for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) - for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) { - hdspm_write_in_gain(hdspm, i, j, gain); - hdspm_write_pb_gain(hdspm, i, j, gain); - } -} - -/*---------------------------------------------------------------------------- - MIDI - ----------------------------------------------------------------------------*/ - -static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, - int id) -{ - /* the hardware already does the relevant bit-mask with 0xff */ - return hdspm_read(hdspm, hdspm->midi[id].dataIn); -} - -static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, - int val) -{ - /* the hardware already does the relevant bit-mask with 0xff */ - return hdspm_write(hdspm, hdspm->midi[id].dataOut, val); -} - -static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id) -{ - return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF; -} - -static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) -{ - int fifo_bytes_used; - - fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF; - - if (fifo_bytes_used < 128) - return 128 - fifo_bytes_used; - else - return 0; -} - -static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id) -{ - while (snd_hdspm_midi_input_available (hdspm, id)) - snd_hdspm_midi_read_byte (hdspm, id); -} - -static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) -{ - unsigned long flags; - int n_pending; - int to_write; - int i; - unsigned char buf[128]; - - /* Output is not interrupt driven */ - - spin_lock_irqsave (&hmidi->lock, flags); - if (hmidi->output && - !snd_rawmidi_transmit_empty (hmidi->output)) { - n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, - hmidi->id); - if (n_pending > 0) { - if (n_pending > (int)sizeof (buf)) - n_pending = sizeof (buf); - - to_write = snd_rawmidi_transmit (hmidi->output, buf, - n_pending); - if (to_write > 0) { - for (i = 0; i < to_write; ++i) - snd_hdspm_midi_write_byte (hmidi->hdspm, - hmidi->id, - buf[i]); - } - } - } - spin_unlock_irqrestore (&hmidi->lock, flags); - return 0; -} - -static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) -{ - unsigned char buf[128]; /* this buffer is designed to match the MIDI - * input FIFO size - */ - unsigned long flags; - int n_pending; - int i; - - spin_lock_irqsave (&hmidi->lock, flags); - n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id); - if (n_pending > 0) { - if (hmidi->input) { - if (n_pending > (int)sizeof (buf)) - n_pending = sizeof (buf); - for (i = 0; i < n_pending; ++i) - buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, - hmidi->id); - if (n_pending) - snd_rawmidi_receive (hmidi->input, buf, - n_pending); - } else { - /* flush the MIDI input FIFO */ - while (n_pending--) - snd_hdspm_midi_read_byte (hmidi->hdspm, - hmidi->id); - } - } - hmidi->pending = 0; - spin_unlock_irqrestore(&hmidi->lock, flags); - - spin_lock_irqsave(&hmidi->hdspm->lock, flags); - hmidi->hdspm->control_register |= hmidi->ie; - hdspm_write(hmidi->hdspm, HDSPM_controlRegister, - hmidi->hdspm->control_register); - spin_unlock_irqrestore(&hmidi->hdspm->lock, flags); - - return snd_hdspm_midi_output_write (hmidi); -} - -static void -snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct hdspm *hdspm; - struct hdspm_midi *hmidi; - unsigned long flags; - - hmidi = substream->rmidi->private_data; - hdspm = hmidi->hdspm; - - spin_lock_irqsave (&hdspm->lock, flags); - if (up) { - if (!(hdspm->control_register & hmidi->ie)) { - snd_hdspm_flush_midi_input (hdspm, hmidi->id); - hdspm->control_register |= hmidi->ie; - } - } else { - hdspm->control_register &= ~hmidi->ie; - } - - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - spin_unlock_irqrestore (&hdspm->lock, flags); -} - -static void snd_hdspm_midi_output_timer(unsigned long data) -{ - struct hdspm_midi *hmidi = (struct hdspm_midi *) data; - unsigned long flags; - - snd_hdspm_midi_output_write(hmidi); - spin_lock_irqsave (&hmidi->lock, flags); - - /* this does not bump hmidi->istimer, because the - kernel automatically removed the timer when it - expired, and we are now adding it back, thus - leaving istimer wherever it was set before. - */ - - if (hmidi->istimer) { - hmidi->timer.expires = 1 + jiffies; - add_timer(&hmidi->timer); - } - - spin_unlock_irqrestore (&hmidi->lock, flags); -} - -static void -snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct hdspm_midi *hmidi; - unsigned long flags; - - hmidi = substream->rmidi->private_data; - spin_lock_irqsave (&hmidi->lock, flags); - if (up) { - if (!hmidi->istimer) { - init_timer(&hmidi->timer); - hmidi->timer.function = snd_hdspm_midi_output_timer; - hmidi->timer.data = (unsigned long) hmidi; - hmidi->timer.expires = 1 + jiffies; - add_timer(&hmidi->timer); - hmidi->istimer++; - } - } else { - if (hmidi->istimer && --hmidi->istimer <= 0) - del_timer (&hmidi->timer); - } - spin_unlock_irqrestore (&hmidi->lock, flags); - if (up) - snd_hdspm_midi_output_write(hmidi); -} - -static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct hdspm_midi *hmidi; - - hmidi = substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id); - hmidi->input = substream; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct hdspm_midi *hmidi; - - hmidi = substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->output = substream; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct hdspm_midi *hmidi; - - snd_hdspm_midi_input_trigger (substream, 0); - - hmidi = substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->input = NULL; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct hdspm_midi *hmidi; - - snd_hdspm_midi_output_trigger (substream, 0); - - hmidi = substream->rmidi->private_data; - spin_lock_irq (&hmidi->lock); - hmidi->output = NULL; - spin_unlock_irq (&hmidi->lock); - - return 0; -} - -static struct snd_rawmidi_ops snd_hdspm_midi_output = -{ - .open = snd_hdspm_midi_output_open, - .close = snd_hdspm_midi_output_close, - .trigger = snd_hdspm_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_hdspm_midi_input = -{ - .open = snd_hdspm_midi_input_open, - .close = snd_hdspm_midi_input_close, - .trigger = snd_hdspm_midi_input_trigger, -}; - -static int __devinit snd_hdspm_create_midi (struct snd_card *card, - struct hdspm *hdspm, int id) -{ - int err; - char buf[32]; - - hdspm->midi[id].id = id; - hdspm->midi[id].hdspm = hdspm; - spin_lock_init (&hdspm->midi[id].lock); - - if (0 == id) { - if (MADIface == hdspm->io_type) { - /* MIDI-over-MADI on HDSPe MADIface */ - hdspm->midi[0].dataIn = HDSPM_midiDataIn2; - hdspm->midi[0].statusIn = HDSPM_midiStatusIn2; - hdspm->midi[0].dataOut = HDSPM_midiDataOut2; - hdspm->midi[0].statusOut = HDSPM_midiStatusOut2; - hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable; - hdspm->midi[0].irq = HDSPM_midi2IRQPending; - } else { - hdspm->midi[0].dataIn = HDSPM_midiDataIn0; - hdspm->midi[0].statusIn = HDSPM_midiStatusIn0; - hdspm->midi[0].dataOut = HDSPM_midiDataOut0; - hdspm->midi[0].statusOut = HDSPM_midiStatusOut0; - hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable; - hdspm->midi[0].irq = HDSPM_midi0IRQPending; - } - } else if (1 == id) { - hdspm->midi[1].dataIn = HDSPM_midiDataIn1; - hdspm->midi[1].statusIn = HDSPM_midiStatusIn1; - hdspm->midi[1].dataOut = HDSPM_midiDataOut1; - hdspm->midi[1].statusOut = HDSPM_midiStatusOut1; - hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable; - hdspm->midi[1].irq = HDSPM_midi1IRQPending; - } else if ((2 == id) && (MADI == hdspm->io_type)) { - /* MIDI-over-MADI on HDSPe MADI */ - hdspm->midi[2].dataIn = HDSPM_midiDataIn2; - hdspm->midi[2].statusIn = HDSPM_midiStatusIn2; - hdspm->midi[2].dataOut = HDSPM_midiDataOut2; - hdspm->midi[2].statusOut = HDSPM_midiStatusOut2; - hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable; - hdspm->midi[2].irq = HDSPM_midi2IRQPending; - } else if (2 == id) { - /* TCO MTC, read only */ - hdspm->midi[2].dataIn = HDSPM_midiDataIn2; - hdspm->midi[2].statusIn = HDSPM_midiStatusIn2; - hdspm->midi[2].dataOut = -1; - hdspm->midi[2].statusOut = -1; - hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable; - hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES; - } else if (3 == id) { - /* TCO MTC on HDSPe MADI */ - hdspm->midi[3].dataIn = HDSPM_midiDataIn3; - hdspm->midi[3].statusIn = HDSPM_midiStatusIn3; - hdspm->midi[3].dataOut = -1; - hdspm->midi[3].statusOut = -1; - hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable; - hdspm->midi[3].irq = HDSPM_midi3IRQPending; - } - - if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) || - (MADIface == hdspm->io_type)))) { - if ((id == 0) && (MADIface == hdspm->io_type)) { - sprintf(buf, "%s MIDIoverMADI", card->shortname); - } else if ((id == 2) && (MADI == hdspm->io_type)) { - sprintf(buf, "%s MIDIoverMADI", card->shortname); - } else { - sprintf(buf, "%s MIDI %d", card->shortname, id+1); - } - err = snd_rawmidi_new(card, buf, id, 1, 1, - &hdspm->midi[id].rmidi); - if (err < 0) - return err; - - sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d", - card->id, id+1); - hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; - - snd_rawmidi_set_ops(hdspm->midi[id].rmidi, - SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_hdspm_midi_output); - snd_rawmidi_set_ops(hdspm->midi[id].rmidi, - SNDRV_RAWMIDI_STREAM_INPUT, - &snd_hdspm_midi_input); - - hdspm->midi[id].rmidi->info_flags |= - SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - } else { - /* TCO MTC, read only */ - sprintf(buf, "%s MTC %d", card->shortname, id+1); - err = snd_rawmidi_new(card, buf, id, 1, 1, - &hdspm->midi[id].rmidi); - if (err < 0) - return err; - - sprintf(hdspm->midi[id].rmidi->name, - "%s MTC %d", card->id, id+1); - hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; - - snd_rawmidi_set_ops(hdspm->midi[id].rmidi, - SNDRV_RAWMIDI_STREAM_INPUT, - &snd_hdspm_midi_input); - - hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; - } - - return 0; -} - - -static void hdspm_midi_tasklet(unsigned long arg) -{ - struct hdspm *hdspm = (struct hdspm *)arg; - int i = 0; - - while (i < hdspm->midiPorts) { - if (hdspm->midi[i].pending) - snd_hdspm_midi_input_read(&hdspm->midi[i]); - - i++; - } -} - - -/*----------------------------------------------------------------------------- - Status Interface - ----------------------------------------------------------------------------*/ - -/* get the system sample rate which is set */ - - -/** - * Calculate the real sample rate from the - * current DDS value. - **/ -static int hdspm_get_system_sample_rate(struct hdspm *hdspm) -{ - unsigned int period, rate; - - period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); - rate = hdspm_calc_dds_value(hdspm, period); - - return rate; -} - - -#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_system_sample_rate, \ - .get = snd_hdspm_get_system_sample_rate \ -} - -static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 27000; - uinfo->value.integer.max = 207000; - uinfo->value.integer.step = 1; - return 0; -} - - -static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value * - ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm); - return 0; -} - - -/** - * Returns the WordClock sample rate class for the given card. - **/ -static int hdspm_get_wc_sample_rate(struct hdspm *hdspm) -{ - int status; - - switch (hdspm->io_type) { - case RayDAT: - case AIO: - status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); - return (status >> 16) & 0xF; - break; - default: - break; - } - - - return 0; -} - - -/** - * Returns the TCO sample rate class for the given card. - **/ -static int hdspm_get_tco_sample_rate(struct hdspm *hdspm) -{ - int status; - - if (hdspm->tco) { - switch (hdspm->io_type) { - case RayDAT: - case AIO: - status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); - return (status >> 20) & 0xF; - break; - default: - break; - } - } - - return 0; -} - - -/** - * Returns the SYNC_IN sample rate class for the given card. - **/ -static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm) -{ - int status; - - if (hdspm->tco) { - switch (hdspm->io_type) { - case RayDAT: - case AIO: - status = hdspm_read(hdspm, HDSPM_RD_STATUS_2); - return (status >> 12) & 0xF; - break; - default: - break; - } - } - - return 0; -} - - -/** - * Returns the sample rate class for input source for - * 'new style' cards like the AIO and RayDAT. - **/ -static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) -{ - int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2); - - return (status >> (idx*4)) & 0xF; -} - - - -#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .private_value = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_autosync_sample_rate, \ - .get = snd_hdspm_get_autosync_sample_rate \ -} - - -static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 10; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts_freq[uinfo->value.enumerated.item]); - return 0; -} - - -static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value * - ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - switch (hdspm->io_type) { - case RayDAT: - switch (kcontrol->private_value) { - case 0: - ucontrol->value.enumerated.item[0] = - hdspm_get_wc_sample_rate(hdspm); - break; - case 7: - ucontrol->value.enumerated.item[0] = - hdspm_get_tco_sample_rate(hdspm); - break; - case 8: - ucontrol->value.enumerated.item[0] = - hdspm_get_sync_in_sample_rate(hdspm); - break; - default: - ucontrol->value.enumerated.item[0] = - hdspm_get_s1_sample_rate(hdspm, - kcontrol->private_value-1); - } - - case AIO: - switch (kcontrol->private_value) { - case 0: /* WC */ - ucontrol->value.enumerated.item[0] = - hdspm_get_wc_sample_rate(hdspm); - break; - case 4: /* TCO */ - ucontrol->value.enumerated.item[0] = - hdspm_get_tco_sample_rate(hdspm); - break; - case 5: /* SYNC_IN */ - ucontrol->value.enumerated.item[0] = - hdspm_get_sync_in_sample_rate(hdspm); - break; - default: - ucontrol->value.enumerated.item[0] = - hdspm_get_s1_sample_rate(hdspm, - ucontrol->id.index-1); - } - - case AES32: - - switch (kcontrol->private_value) { - case 0: /* WC */ - ucontrol->value.enumerated.item[0] = - hdspm_get_wc_sample_rate(hdspm); - break; - case 9: /* TCO */ - ucontrol->value.enumerated.item[0] = - hdspm_get_tco_sample_rate(hdspm); - break; - case 10: /* SYNC_IN */ - ucontrol->value.enumerated.item[0] = - hdspm_get_sync_in_sample_rate(hdspm); - break; - default: /* AES1 to AES8 */ - ucontrol->value.enumerated.item[0] = - hdspm_get_s1_sample_rate(hdspm, - kcontrol->private_value-1); - break; - - } - default: - break; - } - - return 0; -} - - -#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_system_clock_mode, \ - .get = snd_hdspm_get_system_clock_mode, \ - .put = snd_hdspm_put_system_clock_mode, \ -} - - -/** - * Returns the system clock mode for the given card. - * @returns 0 - master, 1 - slave - **/ -static int hdspm_system_clock_mode(struct hdspm *hdspm) -{ - switch (hdspm->io_type) { - case AIO: - case RayDAT: - if (hdspm->settings_register & HDSPM_c0Master) - return 0; - break; - - default: - if (hdspm->control_register & HDSPM_ClockModeMaster) - return 0; - } - - return 1; -} - - -/** - * Sets the system clock mode. - * @param mode 0 - master, 1 - slave - **/ -static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode) -{ - switch (hdspm->io_type) { - case AIO: - case RayDAT: - if (0 == mode) - hdspm->settings_register |= HDSPM_c0Master; - else - hdspm->settings_register &= ~HDSPM_c0Master; - - hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); - break; - - default: - if (0 == mode) - hdspm->control_register |= HDSPM_ClockModeMaster; - else - hdspm->control_register &= ~HDSPM_ClockModeMaster; - - hdspm_write(hdspm, HDSPM_controlRegister, - hdspm->control_register); - } -} - - -static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "Master", "AutoSync" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm); - return 0; -} - -static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - - val = ucontrol->value.enumerated.item[0]; - if (val < 0) - val = 0; - else if (val > 1) - val = 1; - - hdspm_set_system_clock_mode(hdspm, val); - - return 0; -} - - -#define HDSPM_INTERNAL_CLOCK(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_clock_source, \ - .get = snd_hdspm_get_clock_source, \ - .put = snd_hdspm_put_clock_source \ -} - - -static int hdspm_clock_source(struct hdspm * hdspm) -{ - switch (hdspm->system_sample_rate) { - case 32000: return 0; - case 44100: return 1; - case 48000: return 2; - case 64000: return 3; - case 88200: return 4; - case 96000: return 5; - case 128000: return 6; - case 176400: return 7; - case 192000: return 8; - } - - return -1; -} - -static int hdspm_set_clock_source(struct hdspm * hdspm, int mode) -{ - int rate; - switch (mode) { - case 0: - rate = 32000; break; - case 1: - rate = 44100; break; - case 2: - rate = 48000; break; - case 3: - rate = 64000; break; - case 4: - rate = 88200; break; - case 5: - rate = 96000; break; - case 6: - rate = 128000; break; - case 7: - rate = 176400; break; - case 8: - rate = 192000; break; - default: - rate = 48000; - } - hdspm_set_rate(hdspm, rate, 1); - return 0; -} - -static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 9; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts_freq[uinfo->value.enumerated.item+1]); - - return 0; -} - -static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm); - return 0; -} - -static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0]; - if (val < 0) - val = 0; - if (val > 9) - val = 9; - spin_lock_irq(&hdspm->lock); - if (val != hdspm_clock_source(hdspm)) - change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; - else - change = 0; - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_PREF_SYNC_REF(xname, xindex) \ -{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_pref_sync_ref, \ - .get = snd_hdspm_get_pref_sync_ref, \ - .put = snd_hdspm_put_pref_sync_ref \ -} - - -/** - * Returns the current preferred sync reference setting. - * The semantics of the return value are depending on the - * card, please see the comments for clarification. - **/ -static int hdspm_pref_sync_ref(struct hdspm * hdspm) -{ - switch (hdspm->io_type) { - case AES32: - switch (hdspm->control_register & HDSPM_SyncRefMask) { - case 0: return 0; /* WC */ - case HDSPM_SyncRef0: return 1; /* AES 1 */ - case HDSPM_SyncRef1: return 2; /* AES 2 */ - case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */ - case HDSPM_SyncRef2: return 4; /* AES 4 */ - case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */ - case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */ - case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: - return 7; /* AES 7 */ - case HDSPM_SyncRef3: return 8; /* AES 8 */ - case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */ - } - break; - - case MADI: - case MADIface: - if (hdspm->tco) { - switch (hdspm->control_register & HDSPM_SyncRefMask) { - case 0: return 0; /* WC */ - case HDSPM_SyncRef0: return 1; /* MADI */ - case HDSPM_SyncRef1: return 2; /* TCO */ - case HDSPM_SyncRef1+HDSPM_SyncRef0: - return 3; /* SYNC_IN */ - } - } else { - switch (hdspm->control_register & HDSPM_SyncRefMask) { - case 0: return 0; /* WC */ - case HDSPM_SyncRef0: return 1; /* MADI */ - case HDSPM_SyncRef1+HDSPM_SyncRef0: - return 2; /* SYNC_IN */ - } - } - break; - - case RayDAT: - if (hdspm->tco) { - switch ((hdspm->settings_register & - HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { - case 0: return 0; /* WC */ - case 3: return 1; /* ADAT 1 */ - case 4: return 2; /* ADAT 2 */ - case 5: return 3; /* ADAT 3 */ - case 6: return 4; /* ADAT 4 */ - case 1: return 5; /* AES */ - case 2: return 6; /* SPDIF */ - case 9: return 7; /* TCO */ - case 10: return 8; /* SYNC_IN */ - } - } else { - switch ((hdspm->settings_register & - HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { - case 0: return 0; /* WC */ - case 3: return 1; /* ADAT 1 */ - case 4: return 2; /* ADAT 2 */ - case 5: return 3; /* ADAT 3 */ - case 6: return 4; /* ADAT 4 */ - case 1: return 5; /* AES */ - case 2: return 6; /* SPDIF */ - case 10: return 7; /* SYNC_IN */ - } - } - - break; - - case AIO: - if (hdspm->tco) { - switch ((hdspm->settings_register & - HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { - case 0: return 0; /* WC */ - case 3: return 1; /* ADAT */ - case 1: return 2; /* AES */ - case 2: return 3; /* SPDIF */ - case 9: return 4; /* TCO */ - case 10: return 5; /* SYNC_IN */ - } - } else { - switch ((hdspm->settings_register & - HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { - case 0: return 0; /* WC */ - case 3: return 1; /* ADAT */ - case 1: return 2; /* AES */ - case 2: return 3; /* SPDIF */ - case 10: return 4; /* SYNC_IN */ - } - } - - break; - } - - return -1; -} - - -/** - * Set the preferred sync reference to . The semantics - * of are depending on the card type, see the comments - * for clarification. - **/ -static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) -{ - int p = 0; - - switch (hdspm->io_type) { - case AES32: - hdspm->control_register &= ~HDSPM_SyncRefMask; - switch (pref) { - case 0: /* WC */ - break; - case 1: /* AES 1 */ - hdspm->control_register |= HDSPM_SyncRef0; - break; - case 2: /* AES 2 */ - hdspm->control_register |= HDSPM_SyncRef1; - break; - case 3: /* AES 3 */ - hdspm->control_register |= - HDSPM_SyncRef1+HDSPM_SyncRef0; - break; - case 4: /* AES 4 */ - hdspm->control_register |= HDSPM_SyncRef2; - break; - case 5: /* AES 5 */ - hdspm->control_register |= - HDSPM_SyncRef2+HDSPM_SyncRef0; - break; - case 6: /* AES 6 */ - hdspm->control_register |= - HDSPM_SyncRef2+HDSPM_SyncRef1; - break; - case 7: /* AES 7 */ - hdspm->control_register |= - HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; - break; - case 8: /* AES 8 */ - hdspm->control_register |= HDSPM_SyncRef3; - break; - case 9: /* TCO */ - hdspm->control_register |= - HDSPM_SyncRef3+HDSPM_SyncRef0; - break; - default: - return -1; - } - - break; - - case MADI: - case MADIface: - hdspm->control_register &= ~HDSPM_SyncRefMask; - if (hdspm->tco) { - switch (pref) { - case 0: /* WC */ - break; - case 1: /* MADI */ - hdspm->control_register |= HDSPM_SyncRef0; - break; - case 2: /* TCO */ - hdspm->control_register |= HDSPM_SyncRef1; - break; - case 3: /* SYNC_IN */ - hdspm->control_register |= - HDSPM_SyncRef0+HDSPM_SyncRef1; - break; - default: - return -1; - } - } else { - switch (pref) { - case 0: /* WC */ - break; - case 1: /* MADI */ - hdspm->control_register |= HDSPM_SyncRef0; - break; - case 2: /* SYNC_IN */ - hdspm->control_register |= - HDSPM_SyncRef0+HDSPM_SyncRef1; - break; - default: - return -1; - } - } - - break; - - case RayDAT: - if (hdspm->tco) { - switch (pref) { - case 0: p = 0; break; /* WC */ - case 1: p = 3; break; /* ADAT 1 */ - case 2: p = 4; break; /* ADAT 2 */ - case 3: p = 5; break; /* ADAT 3 */ - case 4: p = 6; break; /* ADAT 4 */ - case 5: p = 1; break; /* AES */ - case 6: p = 2; break; /* SPDIF */ - case 7: p = 9; break; /* TCO */ - case 8: p = 10; break; /* SYNC_IN */ - default: return -1; - } - } else { - switch (pref) { - case 0: p = 0; break; /* WC */ - case 1: p = 3; break; /* ADAT 1 */ - case 2: p = 4; break; /* ADAT 2 */ - case 3: p = 5; break; /* ADAT 3 */ - case 4: p = 6; break; /* ADAT 4 */ - case 5: p = 1; break; /* AES */ - case 6: p = 2; break; /* SPDIF */ - case 7: p = 10; break; /* SYNC_IN */ - default: return -1; - } - } - break; - - case AIO: - if (hdspm->tco) { - switch (pref) { - case 0: p = 0; break; /* WC */ - case 1: p = 3; break; /* ADAT */ - case 2: p = 1; break; /* AES */ - case 3: p = 2; break; /* SPDIF */ - case 4: p = 9; break; /* TCO */ - case 5: p = 10; break; /* SYNC_IN */ - default: return -1; - } - } else { - switch (pref) { - case 0: p = 0; break; /* WC */ - case 1: p = 3; break; /* ADAT */ - case 2: p = 1; break; /* AES */ - case 3: p = 2; break; /* SPDIF */ - case 4: p = 10; break; /* SYNC_IN */ - default: return -1; - } - } - break; - } - - switch (hdspm->io_type) { - case RayDAT: - case AIO: - hdspm->settings_register &= ~HDSPM_c0_SyncRefMask; - hdspm->settings_register |= HDSPM_c0_SyncRef0 * p; - hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); - break; - - case MADI: - case MADIface: - case AES32: - hdspm_write(hdspm, HDSPM_controlRegister, - hdspm->control_register); - } - - return 0; -} - - -static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = hdspm->texts_autosync_items; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - hdspm->texts_autosync[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int psf = hdspm_pref_sync_ref(hdspm); - - if (psf >= 0) { - ucontrol->value.enumerated.item[0] = psf; - return 0; - } - - return -1; -} - -static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int val, change = 0; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - - val = ucontrol->value.enumerated.item[0]; - - if (val < 0) - val = 0; - else if (val >= hdspm->texts_autosync_items) - val = hdspm->texts_autosync_items-1; - - spin_lock_irq(&hdspm->lock); - if (val != hdspm_pref_sync_ref(hdspm)) - change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0; - - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_AUTOSYNC_REF(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_autosync_ref, \ - .get = snd_hdspm_get_autosync_ref, \ -} - -static int hdspm_autosync_ref(struct hdspm *hdspm) -{ - if (AES32 == hdspm->io_type) { - unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); - unsigned int syncref = - (status >> HDSPM_AES32_syncref_bit) & 0xF; - if (syncref == 0) - return HDSPM_AES32_AUTOSYNC_FROM_WORD; - if (syncref <= 8) - return syncref; - return HDSPM_AES32_AUTOSYNC_FROM_NONE; - } else if (MADI == hdspm->io_type) { - /* This looks at the autosync selected sync reference */ - unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - - switch (status2 & HDSPM_SelSyncRefMask) { - case HDSPM_SelSyncRef_WORD: - return HDSPM_AUTOSYNC_FROM_WORD; - case HDSPM_SelSyncRef_MADI: - return HDSPM_AUTOSYNC_FROM_MADI; - case HDSPM_SelSyncRef_TCO: - return HDSPM_AUTOSYNC_FROM_TCO; - case HDSPM_SelSyncRef_SyncIn: - return HDSPM_AUTOSYNC_FROM_SYNC_IN; - case HDSPM_SelSyncRef_NVALID: - return HDSPM_AUTOSYNC_FROM_NONE; - default: - return 0; - } - - } - return 0; -} - - -static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - if (AES32 == hdspm->io_type) { - static char *texts[] = { "WordClock", "AES1", "AES2", "AES3", - "AES4", "AES5", "AES6", "AES7", "AES8", "None"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 10; - if (uinfo->value.enumerated.item >= - uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - } else if (MADI == hdspm->io_type) { - static char *texts[] = {"Word Clock", "MADI", "TCO", - "Sync In", "None" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item >= - uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - } - return 0; -} - -static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm); - return 0; -} - - -#define HDSPM_LINE_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_line_out, \ - .get = snd_hdspm_get_line_out, \ - .put = snd_hdspm_put_line_out \ -} - -static int hdspm_line_out(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0; -} - - -static int hdspm_set_line_output(struct hdspm * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_LineOut; - else - hdspm->control_register &= ~HDSPM_LineOut; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info - -static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = hdspm_line_out(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_line_out(hdspm); - hdspm_set_line_output(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_TX_64(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_tx_64, \ - .get = snd_hdspm_get_tx_64, \ - .put = snd_hdspm_put_tx_64 \ -} - -static int hdspm_tx_64(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0; -} - -static int hdspm_set_tx_64(struct hdspm * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_TX_64ch; - else - hdspm->control_register &= ~HDSPM_TX_64ch; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info - -static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_tx_64(hdspm); - hdspm_set_tx_64(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_C_TMS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_c_tms, \ - .get = snd_hdspm_get_c_tms, \ - .put = snd_hdspm_put_c_tms \ -} - -static int hdspm_c_tms(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0; -} - -static int hdspm_set_c_tms(struct hdspm * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_clr_tms; - else - hdspm->control_register &= ~HDSPM_clr_tms; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info - -static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_c_tms(hdspm); - hdspm_set_c_tms(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_SAFE_MODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_safe_mode, \ - .get = snd_hdspm_get_safe_mode, \ - .put = snd_hdspm_put_safe_mode \ -} - -static int hdspm_safe_mode(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0; -} - -static int hdspm_set_safe_mode(struct hdspm * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_AutoInp; - else - hdspm->control_register &= ~HDSPM_AutoInp; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info - -static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_safe_mode(hdspm); - hdspm_set_safe_mode(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_EMPHASIS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_emphasis, \ - .get = snd_hdspm_get_emphasis, \ - .put = snd_hdspm_put_emphasis \ -} - -static int hdspm_emphasis(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0; -} - -static int hdspm_set_emphasis(struct hdspm * hdspm, int emp) -{ - if (emp) - hdspm->control_register |= HDSPM_Emphasis; - else - hdspm->control_register &= ~HDSPM_Emphasis; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info - -static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_emphasis(hdspm); - hdspm_set_emphasis(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_DOLBY(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_dolby, \ - .get = snd_hdspm_get_dolby, \ - .put = snd_hdspm_put_dolby \ -} - -static int hdspm_dolby(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0; -} - -static int hdspm_set_dolby(struct hdspm * hdspm, int dol) -{ - if (dol) - hdspm->control_register |= HDSPM_Dolby; - else - hdspm->control_register &= ~HDSPM_Dolby; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info - -static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_dolby(hdspm); - hdspm_set_dolby(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_PROFESSIONAL(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_professional, \ - .get = snd_hdspm_get_professional, \ - .put = snd_hdspm_put_professional \ -} - -static int hdspm_professional(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_Professional) ? 1 : 0; -} - -static int hdspm_set_professional(struct hdspm * hdspm, int dol) -{ - if (dol) - hdspm->control_register |= HDSPM_Professional; - else - hdspm->control_register &= ~HDSPM_Professional; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -#define snd_hdspm_info_professional snd_ctl_boolean_mono_info - -static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_professional(hdspm); - hdspm_set_professional(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_INPUT_SELECT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_input_select, \ - .get = snd_hdspm_get_input_select, \ - .put = snd_hdspm_put_input_select \ -} - -static int hdspm_input_select(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0; -} - -static int hdspm_set_input_select(struct hdspm * hdspm, int out) -{ - if (out) - hdspm->control_register |= HDSPM_InputSelect0; - else - hdspm->control_register &= ~HDSPM_InputSelect0; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "optical", "coaxial" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_input_select(hdspm); - hdspm_set_input_select(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_DS_WIRE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_ds_wire, \ - .get = snd_hdspm_get_ds_wire, \ - .put = snd_hdspm_put_ds_wire \ -} - -static int hdspm_ds_wire(struct hdspm * hdspm) -{ - return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0; -} - -static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds) -{ - if (ds) - hdspm->control_register |= HDSPM_DS_DoubleWire; - else - hdspm->control_register &= ~HDSPM_DS_DoubleWire; - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "Single", "Double" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&hdspm->lock); - change = (int) val != hdspm_ds_wire(hdspm); - hdspm_set_ds_wire(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - - -#define HDSPM_QS_WIRE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_qs_wire, \ - .get = snd_hdspm_get_qs_wire, \ - .put = snd_hdspm_put_qs_wire \ -} - -static int hdspm_qs_wire(struct hdspm * hdspm) -{ - if (hdspm->control_register & HDSPM_QS_DoubleWire) - return 1; - if (hdspm->control_register & HDSPM_QS_QuadWire) - return 2; - return 0; -} - -static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode) -{ - hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire); - switch (mode) { - case 0: - break; - case 1: - hdspm->control_register |= HDSPM_QS_DoubleWire; - break; - case 2: - hdspm->control_register |= HDSPM_QS_QuadWire; - break; - } - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "Single", "Double", "Quad" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0]; - if (val < 0) - val = 0; - if (val > 2) - val = 2; - spin_lock_irq(&hdspm->lock); - change = val != hdspm_qs_wire(hdspm); - hdspm_set_qs_wire(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_MADI_SPEEDMODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_madi_speedmode, \ - .get = snd_hdspm_get_madi_speedmode, \ - .put = snd_hdspm_put_madi_speedmode \ -} - -static int hdspm_madi_speedmode(struct hdspm *hdspm) -{ - if (hdspm->control_register & HDSPM_QuadSpeed) - return 2; - if (hdspm->control_register & HDSPM_DoubleSpeed) - return 1; - return 0; -} - -static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode) -{ - hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed); - switch (mode) { - case 0: - break; - case 1: - hdspm->control_register |= HDSPM_DoubleSpeed; - break; - case 2: - hdspm->control_register |= HDSPM_QuadSpeed; - break; - } - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "Single", "Double", "Quad" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&hdspm->lock); - ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm); - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - int val; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - val = ucontrol->value.integer.value[0]; - if (val < 0) - val = 0; - if (val > 2) - val = 2; - spin_lock_irq(&hdspm->lock); - change = val != hdspm_madi_speedmode(hdspm); - hdspm_set_madi_speedmode(hdspm, val); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_MIXER(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .device = 0, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_mixer, \ - .get = snd_hdspm_get_mixer, \ - .put = snd_hdspm_put_mixer \ -} - -static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 3; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 65535; - uinfo->value.integer.step = 1; - return 0; -} - -static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int source; - int destination; - - source = ucontrol->value.integer.value[0]; - if (source < 0) - source = 0; - else if (source >= 2 * HDSPM_MAX_CHANNELS) - source = 2 * HDSPM_MAX_CHANNELS - 1; - - destination = ucontrol->value.integer.value[1]; - if (destination < 0) - destination = 0; - else if (destination >= HDSPM_MAX_CHANNELS) - destination = HDSPM_MAX_CHANNELS - 1; - - spin_lock_irq(&hdspm->lock); - if (source >= HDSPM_MAX_CHANNELS) - ucontrol->value.integer.value[2] = - hdspm_read_pb_gain(hdspm, destination, - source - HDSPM_MAX_CHANNELS); - else - ucontrol->value.integer.value[2] = - hdspm_read_in_gain(hdspm, destination, source); - - spin_unlock_irq(&hdspm->lock); - - return 0; -} - -static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - int source; - int destination; - int gain; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - - source = ucontrol->value.integer.value[0]; - destination = ucontrol->value.integer.value[1]; - - if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS) - return -1; - if (destination < 0 || destination >= HDSPM_MAX_CHANNELS) - return -1; - - gain = ucontrol->value.integer.value[2]; - - spin_lock_irq(&hdspm->lock); - - if (source >= HDSPM_MAX_CHANNELS) - change = gain != hdspm_read_pb_gain(hdspm, destination, - source - - HDSPM_MAX_CHANNELS); - else - change = gain != hdspm_read_in_gain(hdspm, destination, - source); - - if (change) { - if (source >= HDSPM_MAX_CHANNELS) - hdspm_write_pb_gain(hdspm, destination, - source - HDSPM_MAX_CHANNELS, - gain); - else - hdspm_write_in_gain(hdspm, destination, source, - gain); - } - spin_unlock_irq(&hdspm->lock); - - return change; -} - -/* The simple mixer control(s) provide gain control for the - basic 1:1 mappings of playback streams to output - streams. -*/ - -#define HDSPM_PLAYBACK_MIXER \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_playback_mixer, \ - .get = snd_hdspm_get_playback_mixer, \ - .put = snd_hdspm_put_playback_mixer \ -} - -static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 64; - uinfo->value.integer.step = 1; - return 0; -} - -static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int channel; - - channel = ucontrol->id.index - 1; - - if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) - return -EINVAL; - - spin_lock_irq(&hdspm->lock); - ucontrol->value.integer.value[0] = - (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN; - spin_unlock_irq(&hdspm->lock); - - return 0; -} - -static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int change; - int channel; - int gain; - - if (!snd_hdspm_use_is_exclusive(hdspm)) - return -EBUSY; - - channel = ucontrol->id.index - 1; - - if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) - return -EINVAL; - - gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64; - - spin_lock_irq(&hdspm->lock); - change = - gain != hdspm_read_pb_gain(hdspm, channel, - channel); - if (change) - hdspm_write_pb_gain(hdspm, channel, channel, - gain); - spin_unlock_irq(&hdspm->lock); - return change; -} - -#define HDSPM_SYNC_CHECK(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .private_value = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_sync_check, \ - .get = snd_hdspm_get_sync_check \ -} - - -static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int hdspm_wc_sync_check(struct hdspm *hdspm) -{ - int status, status2; - - switch (hdspm->io_type) { - case AES32: - status = hdspm_read(hdspm, HDSPM_statusRegister); - if (status & HDSPM_wcSync) - return 2; - else if (status & HDSPM_wcLock) - return 1; - return 0; - break; - - case MADI: - status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - if (status2 & HDSPM_wcLock) { - if (status2 & HDSPM_wcSync) - return 2; - else - return 1; - } - return 0; - break; - - case RayDAT: - case AIO: - status = hdspm_read(hdspm, HDSPM_statusRegister); - - if (status & 0x2000000) - return 2; - else if (status & 0x1000000) - return 1; - return 0; - - break; - - case MADIface: - break; - } - - - return 3; -} - - -static int hdspm_madi_sync_check(struct hdspm *hdspm) -{ - int status = hdspm_read(hdspm, HDSPM_statusRegister); - if (status & HDSPM_madiLock) { - if (status & HDSPM_madiSync) - return 2; - else - return 1; - } - return 0; -} - - -static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx) -{ - int status, lock, sync; - - status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); - - lock = (status & (0x1<io_type) { - case RayDAT: - case AIO: - status = hdspm_read(hdspm, HDSPM_RD_STATUS_3); - lock = (status & 0x400) ? 1 : 0; - sync = (status & 0x800) ? 1 : 0; - break; - - case MADI: - case AES32: - status = hdspm_read(hdspm, HDSPM_statusRegister2); - lock = (status & HDSPM_syncInLock) ? 1 : 0; - sync = (status & HDSPM_syncInSync) ? 1 : 0; - break; - - case MADIface: - break; - } - - if (lock && sync) - return 2; - else if (lock) - return 1; - - return 0; -} - -static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx) -{ - int status2, lock, sync; - status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - - lock = (status2 & (0x0080 >> idx)) ? 1 : 0; - sync = (status2 & (0x8000 >> idx)) ? 1 : 0; - - if (sync) - return 2; - else if (lock) - return 1; - return 0; -} - - -static int hdspm_tco_sync_check(struct hdspm *hdspm) -{ - int status; - - if (hdspm->tco) { - switch (hdspm->io_type) { - case MADI: - case AES32: - status = hdspm_read(hdspm, HDSPM_statusRegister); - if (status & HDSPM_tcoLock) { - if (status & HDSPM_tcoSync) - return 2; - else - return 1; - } - return 0; - - break; - - case RayDAT: - case AIO: - status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); - - if (status & 0x8000000) - return 2; /* Sync */ - if (status & 0x4000000) - return 1; /* Lock */ - return 0; /* No signal */ - break; - - default: - break; - } - } - - return 3; /* N/A */ -} - - -static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - int val = -1; - - switch (hdspm->io_type) { - case RayDAT: - switch (kcontrol->private_value) { - case 0: /* WC */ - val = hdspm_wc_sync_check(hdspm); break; - case 7: /* TCO */ - val = hdspm_tco_sync_check(hdspm); break; - case 8: /* SYNC IN */ - val = hdspm_sync_in_sync_check(hdspm); break; - default: - val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); - } - - case AIO: - switch (kcontrol->private_value) { - case 0: /* WC */ - val = hdspm_wc_sync_check(hdspm); break; - case 4: /* TCO */ - val = hdspm_tco_sync_check(hdspm); break; - case 5: /* SYNC IN */ - val = hdspm_sync_in_sync_check(hdspm); break; - default: - val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); - } - - case MADI: - switch (kcontrol->private_value) { - case 0: /* WC */ - val = hdspm_wc_sync_check(hdspm); break; - case 1: /* MADI */ - val = hdspm_madi_sync_check(hdspm); break; - case 2: /* TCO */ - val = hdspm_tco_sync_check(hdspm); break; - case 3: /* SYNC_IN */ - val = hdspm_sync_in_sync_check(hdspm); break; - } - - case MADIface: - val = hdspm_madi_sync_check(hdspm); /* MADI */ - break; - - case AES32: - switch (kcontrol->private_value) { - case 0: /* WC */ - val = hdspm_wc_sync_check(hdspm); break; - case 9: /* TCO */ - val = hdspm_tco_sync_check(hdspm); break; - case 10 /* SYNC IN */: - val = hdspm_sync_in_sync_check(hdspm); break; - default: /* AES1 to AES8 */ - val = hdspm_aes_sync_check(hdspm, - kcontrol->private_value-1); - } - - } - - if (-1 == val) - val = 3; - - ucontrol->value.enumerated.item[0] = val; - return 0; -} - - - -/** - * TCO controls - **/ -static void hdspm_tco_write(struct hdspm *hdspm) -{ - unsigned int tc[4] = { 0, 0, 0, 0}; - - switch (hdspm->tco->input) { - case 0: - tc[2] |= HDSPM_TCO2_set_input_MSB; - break; - case 1: - tc[2] |= HDSPM_TCO2_set_input_LSB; - break; - default: - break; - } - - switch (hdspm->tco->framerate) { - case 1: - tc[1] |= HDSPM_TCO1_LTC_Format_LSB; - break; - case 2: - tc[1] |= HDSPM_TCO1_LTC_Format_MSB; - break; - case 3: - tc[1] |= HDSPM_TCO1_LTC_Format_MSB + - HDSPM_TCO1_set_drop_frame_flag; - break; - case 4: - tc[1] |= HDSPM_TCO1_LTC_Format_LSB + - HDSPM_TCO1_LTC_Format_MSB; - break; - case 5: - tc[1] |= HDSPM_TCO1_LTC_Format_LSB + - HDSPM_TCO1_LTC_Format_MSB + - HDSPM_TCO1_set_drop_frame_flag; - break; - default: - break; - } - - switch (hdspm->tco->wordclock) { - case 1: - tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB; - break; - case 2: - tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB; - break; - default: - break; - } - - switch (hdspm->tco->samplerate) { - case 1: - tc[2] |= HDSPM_TCO2_set_freq; - break; - case 2: - tc[2] |= HDSPM_TCO2_set_freq_from_app; - break; - default: - break; - } - - switch (hdspm->tco->pull) { - case 1: - tc[2] |= HDSPM_TCO2_set_pull_up; - break; - case 2: - tc[2] |= HDSPM_TCO2_set_pull_down; - break; - case 3: - tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4; - break; - case 4: - tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4; - break; - default: - break; - } - - if (1 == hdspm->tco->term) { - tc[2] |= HDSPM_TCO2_set_term_75R; - } - - hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]); - hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]); - hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]); - hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]); -} - - -#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_tco_sample_rate, \ - .get = snd_hdspm_get_tco_sample_rate, \ - .put = snd_hdspm_put_tco_sample_rate \ -} - -static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "44.1 kHz", "48 kHz" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate; - - return 0; -} - -static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) { - hdspm->tco->samplerate = ucontrol->value.enumerated.item[0]; - - hdspm_tco_write(hdspm); - - return 1; - } - - return 0; -} - - -#define HDSPM_TCO_PULL(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_tco_pull, \ - .get = snd_hdspm_get_tco_pull, \ - .put = snd_hdspm_put_tco_pull \ -} - -static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm->tco->pull; - - return 0; -} - -static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) { - hdspm->tco->pull = ucontrol->value.enumerated.item[0]; - - hdspm_tco_write(hdspm); - - return 1; - } - - return 0; -} - -#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_tco_wck_conversion, \ - .get = snd_hdspm_get_tco_wck_conversion, \ - .put = snd_hdspm_put_tco_wck_conversion \ -} - -static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock; - - return 0; -} - -static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) { - hdspm->tco->wordclock = ucontrol->value.enumerated.item[0]; - - hdspm_tco_write(hdspm); - - return 1; - } - - return 0; -} - - -#define HDSPM_TCO_FRAME_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_tco_frame_rate, \ - .get = snd_hdspm_get_tco_frame_rate, \ - .put = snd_hdspm_put_tco_frame_rate \ -} - -static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "24 fps", "25 fps", "29.97fps", - "29.97 dfps", "30 fps", "30 dfps" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 6; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm->tco->framerate; - - return 0; -} - -static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) { - hdspm->tco->framerate = ucontrol->value.enumerated.item[0]; - - hdspm_tco_write(hdspm); - - return 1; - } - - return 0; -} - - -#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_tco_sync_source, \ - .get = snd_hdspm_get_tco_sync_source, \ - .put = snd_hdspm_put_tco_sync_source \ -} - -static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = { "LTC", "Video", "WCK" }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm->tco->input; - - return 0; -} - -static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) { - hdspm->tco->input = ucontrol->value.enumerated.item[0]; - - hdspm_tco_write(hdspm); - - return 1; - } - - return 0; -} - - -#define HDSPM_TCO_WORD_TERM(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_tco_word_term, \ - .get = snd_hdspm_get_tco_word_term, \ - .put = snd_hdspm_put_tco_word_term \ -} - -static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - - return 0; -} - - -static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = hdspm->tco->term; - - return 0; -} - - -static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); - - if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) { - hdspm->tco->term = ucontrol->value.enumerated.item[0]; - - hdspm_tco_write(hdspm); - - return 1; - } - - return 0; -} - - - - -static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { - HDSPM_MIXER("Mixer", 0), - HDSPM_INTERNAL_CLOCK("Internal Clock", 0), - HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), - HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), - HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), - HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), - HDSPM_SYNC_CHECK("WC SyncCheck", 0), - HDSPM_SYNC_CHECK("MADI SyncCheck", 1), - HDSPM_SYNC_CHECK("TCO SyncCHeck", 2), - HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), - HDSPM_LINE_OUT("Line Out", 0), - HDSPM_TX_64("TX 64 channels mode", 0), - HDSPM_C_TMS("Clear Track Marker", 0), - HDSPM_SAFE_MODE("Safe Mode", 0), - HDSPM_INPUT_SELECT("Input Select", 0), - HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0) -}; - - -static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { - HDSPM_MIXER("Mixer", 0), - HDSPM_INTERNAL_CLOCK("Internal Clock", 0), - HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), - HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), - HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), - HDSPM_SYNC_CHECK("MADI SyncCheck", 0), - HDSPM_TX_64("TX 64 channels mode", 0), - HDSPM_C_TMS("Clear Track Marker", 0), - HDSPM_SAFE_MODE("Safe Mode", 0), - HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0) -}; - -static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { - HDSPM_MIXER("Mixer", 0), - HDSPM_INTERNAL_CLOCK("Internal Clock", 0), - HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), - HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), - HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), - HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), - HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), - HDSPM_SYNC_CHECK("WC SyncCheck", 0), - HDSPM_SYNC_CHECK("AES SyncCheck", 1), - HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2), - HDSPM_SYNC_CHECK("ADAT SyncCheck", 3), - HDSPM_SYNC_CHECK("TCO SyncCheck", 4), - HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5), - HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1), - HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2), - HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3), - HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4), - HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5) - - /* - HDSPM_INPUT_SELECT("Input Select", 0), - HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0), - HDSPM_PROFESSIONAL("SPDIF Out Professional", 0); - HDSPM_SPDIF_IN("SPDIF In", 0); - HDSPM_BREAKOUT_CABLE("Breakout Cable", 0); - HDSPM_INPUT_LEVEL("Input Level", 0); - HDSPM_OUTPUT_LEVEL("Output Level", 0); - HDSPM_PHONES("Phones", 0); - */ -}; - -static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = { - HDSPM_MIXER("Mixer", 0), - HDSPM_INTERNAL_CLOCK("Internal Clock", 0), - HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0), - HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0), - HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), - HDSPM_SYNC_CHECK("WC SyncCheck", 0), - HDSPM_SYNC_CHECK("AES SyncCheck", 1), - HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2), - HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3), - HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4), - HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5), - HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6), - HDSPM_SYNC_CHECK("TCO SyncCheck", 7), - HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8), - HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1), - HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2), - HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3), - HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4), - HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5), - HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6), - HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7), - HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8) -}; - -static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { - HDSPM_MIXER("Mixer", 0), - HDSPM_INTERNAL_CLOCK("Internal Clock", 0), - HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), - HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), - HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), - HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), - HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), - HDSPM_SYNC_CHECK("WC Sync Check", 0), - HDSPM_SYNC_CHECK("AES1 Sync Check", 1), - HDSPM_SYNC_CHECK("AES2 Sync Check", 2), - HDSPM_SYNC_CHECK("AES3 Sync Check", 3), - HDSPM_SYNC_CHECK("AES4 Sync Check", 4), - HDSPM_SYNC_CHECK("AES5 Sync Check", 5), - HDSPM_SYNC_CHECK("AES6 Sync Check", 6), - HDSPM_SYNC_CHECK("AES7 Sync Check", 7), - HDSPM_SYNC_CHECK("AES8 Sync Check", 8), - HDSPM_SYNC_CHECK("TCO Sync Check", 9), - HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10), - HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7), - HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8), - HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9), - HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10), - HDSPM_LINE_OUT("Line Out", 0), - HDSPM_EMPHASIS("Emphasis", 0), - HDSPM_DOLBY("Non Audio", 0), - HDSPM_PROFESSIONAL("Professional", 0), - HDSPM_C_TMS("Clear Track Marker", 0), - HDSPM_DS_WIRE("Double Speed Wire Mode", 0), - HDSPM_QS_WIRE("Quad Speed Wire Mode", 0), -}; - - - -/* Control elements for the optional TCO module */ -static struct snd_kcontrol_new snd_hdspm_controls_tco[] = { - HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0), - HDSPM_TCO_PULL("TCO Pull", 0), - HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), - HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0), - HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0), - HDSPM_TCO_WORD_TERM("TCO Word Term", 0) -}; - - -static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; - - -static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm) -{ - int i; - - for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) { - if (hdspm->system_sample_rate > 48000) { - hdspm->playback_mixer_ctls[i]->vd[0].access = - SNDRV_CTL_ELEM_ACCESS_INACTIVE | - SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_VOLATILE; - } else { - hdspm->playback_mixer_ctls[i]->vd[0].access = - SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_VOLATILE; - } - snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - &hdspm->playback_mixer_ctls[i]->id); - } - - return 0; -} - - -static int snd_hdspm_create_controls(struct snd_card *card, - struct hdspm *hdspm) -{ - unsigned int idx, limit; - int err; - struct snd_kcontrol *kctl; - struct snd_kcontrol_new *list = NULL; - - switch (hdspm->io_type) { - case MADI: - list = snd_hdspm_controls_madi; - limit = ARRAY_SIZE(snd_hdspm_controls_madi); - break; - case MADIface: - list = snd_hdspm_controls_madiface; - limit = ARRAY_SIZE(snd_hdspm_controls_madiface); - break; - case AIO: - list = snd_hdspm_controls_aio; - limit = ARRAY_SIZE(snd_hdspm_controls_aio); - break; - case RayDAT: - list = snd_hdspm_controls_raydat; - limit = ARRAY_SIZE(snd_hdspm_controls_raydat); - break; - case AES32: - list = snd_hdspm_controls_aes32; - limit = ARRAY_SIZE(snd_hdspm_controls_aes32); - break; - } - - if (NULL != list) { - for (idx = 0; idx < limit; idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&list[idx], hdspm)); - if (err < 0) - return err; - } - } - - - /* create simple 1:1 playback mixer controls */ - snd_hdspm_playback_mixer.name = "Chn"; - if (hdspm->system_sample_rate >= 128000) { - limit = hdspm->qs_out_channels; - } else if (hdspm->system_sample_rate >= 64000) { - limit = hdspm->ds_out_channels; - } else { - limit = hdspm->ss_out_channels; - } - for (idx = 0; idx < limit; ++idx) { - snd_hdspm_playback_mixer.index = idx + 1; - kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm); - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; - hdspm->playback_mixer_ctls[idx] = kctl; - } - - - if (hdspm->tco) { - /* add tco control elements */ - list = snd_hdspm_controls_tco; - limit = ARRAY_SIZE(snd_hdspm_controls_tco); - for (idx = 0; idx < limit; idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&list[idx], hdspm)); - if (err < 0) - return err; - } - } - - return 0; -} - -/*------------------------------------------------------------ - /proc interface - ------------------------------------------------------------*/ - -static void -snd_hdspm_proc_read_madi(struct snd_info_entry * entry, - struct snd_info_buffer *buffer) -{ - struct hdspm *hdspm = entry->private_data; - unsigned int status, status2, control, freq; - - char *pref_sync_ref; - char *autosync_ref; - char *system_clock_mode; - char *insel; - int x, x2; - - /* TCO stuff */ - int a, ltc, frames, seconds, minutes, hours; - unsigned int period; - u64 freq_const = 0; - u32 rate; - - status = hdspm_read(hdspm, HDSPM_statusRegister); - status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - control = hdspm->control_register; - freq = hdspm_read(hdspm, HDSPM_timecodeRegister); - - snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n", - hdspm->card_name, hdspm->card->number + 1, - hdspm->firmware_rev, - (status2 & HDSPM_version0) | - (status2 & HDSPM_version1) | (status2 & - HDSPM_version2)); - - snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n", - (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF, - hdspm->serial); - - snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", - hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); - - snd_iprintf(buffer, "--- System ---\n"); - - snd_iprintf(buffer, - "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", - status & HDSPM_audioIRQPending, - (status & HDSPM_midi0IRQPending) ? 1 : 0, - (status & HDSPM_midi1IRQPending) ? 1 : 0, - hdspm->irq_count); - snd_iprintf(buffer, - "HW pointer: id = %d, rawptr = %d (%d->%d) " - "estimated= %ld (bytes)\n", - ((status & HDSPM_BufferID) ? 1 : 0), - (status & HDSPM_BufferPositionMask), - (status & HDSPM_BufferPositionMask) % - (2 * (int)hdspm->period_bytes), - ((status & HDSPM_BufferPositionMask) - 64) % - (2 * (int)hdspm->period_bytes), - (long) hdspm_hw_pointer(hdspm) * 4); - - snd_iprintf(buffer, - "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", - hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); - snd_iprintf(buffer, - "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n", - hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF); - snd_iprintf(buffer, - "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " - "status2=0x%x\n", - hdspm->control_register, hdspm->control2_register, - status, status2); - if (status & HDSPM_tco_detect) { - snd_iprintf(buffer, "TCO module detected.\n"); - a = hdspm_read(hdspm, HDSPM_RD_TCO+4); - if (a & HDSPM_TCO1_LTC_Input_valid) { - snd_iprintf(buffer, " LTC valid, "); - switch (a & (HDSPM_TCO1_LTC_Format_LSB | - HDSPM_TCO1_LTC_Format_MSB)) { - case 0: - snd_iprintf(buffer, "24 fps, "); - break; - case HDSPM_TCO1_LTC_Format_LSB: - snd_iprintf(buffer, "25 fps, "); - break; - case HDSPM_TCO1_LTC_Format_MSB: - snd_iprintf(buffer, "29.97 fps, "); - break; - default: - snd_iprintf(buffer, "30 fps, "); - break; - } - if (a & HDSPM_TCO1_set_drop_frame_flag) { - snd_iprintf(buffer, "drop frame\n"); - } else { - snd_iprintf(buffer, "full frame\n"); - } - } else { - snd_iprintf(buffer, " no LTC\n"); - } - if (a & HDSPM_TCO1_Video_Input_Format_NTSC) { - snd_iprintf(buffer, " Video: NTSC\n"); - } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) { - snd_iprintf(buffer, " Video: PAL\n"); - } else { - snd_iprintf(buffer, " No video\n"); - } - if (a & HDSPM_TCO1_TCO_lock) { - snd_iprintf(buffer, " Sync: lock\n"); - } else { - snd_iprintf(buffer, " Sync: no lock\n"); - } - - switch (hdspm->io_type) { - case MADI: - case AES32: - freq_const = 110069313433624ULL; - break; - case RayDAT: - case AIO: - freq_const = 104857600000000ULL; - break; - case MADIface: - break; /* no TCO possible */ - } - - period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); - snd_iprintf(buffer, " period: %u\n", period); - - - /* rate = freq_const/period; */ - rate = div_u64(freq_const, period); - - if (control & HDSPM_QuadSpeed) { - rate *= 4; - } else if (control & HDSPM_DoubleSpeed) { - rate *= 2; - } - - snd_iprintf(buffer, " Frequency: %u Hz\n", - (unsigned int) rate); - - ltc = hdspm_read(hdspm, HDSPM_RD_TCO); - frames = ltc & 0xF; - ltc >>= 4; - frames += (ltc & 0x3) * 10; - ltc >>= 4; - seconds = ltc & 0xF; - ltc >>= 4; - seconds += (ltc & 0x7) * 10; - ltc >>= 4; - minutes = ltc & 0xF; - ltc >>= 4; - minutes += (ltc & 0x7) * 10; - ltc >>= 4; - hours = ltc & 0xF; - ltc >>= 4; - hours += (ltc & 0x3) * 10; - snd_iprintf(buffer, - " LTC In: %02d:%02d:%02d:%02d\n", - hours, minutes, seconds, frames); - - } else { - snd_iprintf(buffer, "No TCO module detected.\n"); - } - - snd_iprintf(buffer, "--- Settings ---\n"); - - x = hdspm_get_latency(hdspm); - - snd_iprintf(buffer, - "Size (Latency): %d samples (2 periods of %lu bytes)\n", - x, (unsigned long) hdspm->period_bytes); - - snd_iprintf(buffer, "Line out: %s\n", - (hdspm->control_register & HDSPM_LineOut) ? "on " : "off"); - - switch (hdspm->control_register & HDSPM_InputMask) { - case HDSPM_InputOptical: - insel = "Optical"; - break; - case HDSPM_InputCoaxial: - insel = "Coaxial"; - break; - default: - insel = "Unkown"; - } - - snd_iprintf(buffer, - "ClearTrackMarker = %s, Transmit in %s Channel Mode, " - "Auto Input %s\n", - (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off", - (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56", - (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off"); - - - if (!(hdspm->control_register & HDSPM_ClockModeMaster)) - system_clock_mode = "AutoSync"; - else - system_clock_mode = "Master"; - snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode); - - switch (hdspm_pref_sync_ref(hdspm)) { - case HDSPM_SYNC_FROM_WORD: - pref_sync_ref = "Word Clock"; - break; - case HDSPM_SYNC_FROM_MADI: - pref_sync_ref = "MADI Sync"; - break; - case HDSPM_SYNC_FROM_TCO: - pref_sync_ref = "TCO"; - break; - case HDSPM_SYNC_FROM_SYNC_IN: - pref_sync_ref = "Sync In"; - break; - default: - pref_sync_ref = "XXXX Clock"; - break; - } - snd_iprintf(buffer, "Preferred Sync Reference: %s\n", - pref_sync_ref); - - snd_iprintf(buffer, "System Clock Frequency: %d\n", - hdspm->system_sample_rate); - - - snd_iprintf(buffer, "--- Status:\n"); - - x = status & HDSPM_madiSync; - x2 = status2 & HDSPM_wcSync; - - snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n", - (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") : - "NoLock", - (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") : - "NoLock"); - - switch (hdspm_autosync_ref(hdspm)) { - case HDSPM_AUTOSYNC_FROM_SYNC_IN: - autosync_ref = "Sync In"; - break; - case HDSPM_AUTOSYNC_FROM_TCO: - autosync_ref = "TCO"; - break; - case HDSPM_AUTOSYNC_FROM_WORD: - autosync_ref = "Word Clock"; - break; - case HDSPM_AUTOSYNC_FROM_MADI: - autosync_ref = "MADI Sync"; - break; - case HDSPM_AUTOSYNC_FROM_NONE: - autosync_ref = "Input not valid"; - break; - default: - autosync_ref = "---"; - break; - } - snd_iprintf(buffer, - "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n", - autosync_ref, hdspm_external_sample_rate(hdspm), - (status & HDSPM_madiFreqMask) >> 22, - (status2 & HDSPM_wcFreqMask) >> 5); - - snd_iprintf(buffer, "Input: %s, Mode=%s\n", - (status & HDSPM_AB_int) ? "Coax" : "Optical", - (status & HDSPM_RX_64ch) ? "64 channels" : - "56 channels"); - - snd_iprintf(buffer, "\n"); -} - -static void -snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, - struct snd_info_buffer *buffer) -{ - struct hdspm *hdspm = entry->private_data; - unsigned int status; - unsigned int status2; - unsigned int timecode; - int pref_syncref; - char *autosync_ref; - int x; - - status = hdspm_read(hdspm, HDSPM_statusRegister); - status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); - - snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n", - hdspm->card_name, hdspm->card->number + 1, - hdspm->firmware_rev); - - snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", - hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); - - snd_iprintf(buffer, "--- System ---\n"); - - snd_iprintf(buffer, - "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", - status & HDSPM_audioIRQPending, - (status & HDSPM_midi0IRQPending) ? 1 : 0, - (status & HDSPM_midi1IRQPending) ? 1 : 0, - hdspm->irq_count); - snd_iprintf(buffer, - "HW pointer: id = %d, rawptr = %d (%d->%d) " - "estimated= %ld (bytes)\n", - ((status & HDSPM_BufferID) ? 1 : 0), - (status & HDSPM_BufferPositionMask), - (status & HDSPM_BufferPositionMask) % - (2 * (int)hdspm->period_bytes), - ((status & HDSPM_BufferPositionMask) - 64) % - (2 * (int)hdspm->period_bytes), - (long) hdspm_hw_pointer(hdspm) * 4); - - snd_iprintf(buffer, - "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", - hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); - snd_iprintf(buffer, - "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n", - hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF, - hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF); - snd_iprintf(buffer, - "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " - "status2=0x%x\n", - hdspm->control_register, hdspm->control2_register, - status, status2); - - snd_iprintf(buffer, "--- Settings ---\n"); - - x = hdspm_get_latency(hdspm); - - snd_iprintf(buffer, - "Size (Latency): %d samples (2 periods of %lu bytes)\n", - x, (unsigned long) hdspm->period_bytes); - - snd_iprintf(buffer, "Line out: %s\n", - (hdspm-> - control_register & HDSPM_LineOut) ? "on " : "off"); - - snd_iprintf(buffer, - "ClearTrackMarker %s, Emphasis %s, Dolby %s\n", - (hdspm-> - control_register & HDSPM_clr_tms) ? "on" : "off", - (hdspm-> - control_register & HDSPM_Emphasis) ? "on" : "off", - (hdspm-> - control_register & HDSPM_Dolby) ? "on" : "off"); - - - pref_syncref = hdspm_pref_sync_ref(hdspm); - if (pref_syncref == 0) - snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n"); - else - snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n", - pref_syncref); - - snd_iprintf(buffer, "System Clock Frequency: %d\n", - hdspm->system_sample_rate); - - snd_iprintf(buffer, "Double speed: %s\n", - hdspm->control_register & HDSPM_DS_DoubleWire? - "Double wire" : "Single wire"); - snd_iprintf(buffer, "Quad speed: %s\n", - hdspm->control_register & HDSPM_QS_DoubleWire? - "Double wire" : - hdspm->control_register & HDSPM_QS_QuadWire? - "Quad wire" : "Single wire"); - - snd_iprintf(buffer, "--- Status:\n"); - - snd_iprintf(buffer, "Word: %s Frequency: %d\n", - (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock", - HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); - - for (x = 0; x < 8; x++) { - snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", - x+1, - (status2 & (HDSPM_LockAES >> x)) ? - "Sync " : "No Lock", - HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); - } - - switch (hdspm_autosync_ref(hdspm)) { - case HDSPM_AES32_AUTOSYNC_FROM_NONE: - autosync_ref = "None"; break; - case HDSPM_AES32_AUTOSYNC_FROM_WORD: - autosync_ref = "Word Clock"; break; - case HDSPM_AES32_AUTOSYNC_FROM_AES1: - autosync_ref = "AES1"; break; - case HDSPM_AES32_AUTOSYNC_FROM_AES2: - autosync_ref = "AES2"; break; - case HDSPM_AES32_AUTOSYNC_FROM_AES3: - autosync_ref = "AES3"; break; - case HDSPM_AES32_AUTOSYNC_FROM_AES4: - autosync_ref = "AES4"; break; - case HDSPM_AES32_AUTOSYNC_FROM_AES5: - autosync_ref = "AES5"; break; - case HDSPM_AES32_AUTOSYNC_FROM_AES6: - autosync_ref = "AES6"; break; - case HDSPM_AES32_AUTOSYNC_FROM_AES7: - autosync_ref = "AES7"; break; - case HDSPM_AES32_AUTOSYNC_FROM_AES8: - autosync_ref = "AES8"; break; - default: - autosync_ref = "---"; break; - } - snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref); - - snd_iprintf(buffer, "\n"); -} - -static void -snd_hdspm_proc_read_raydat(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct hdspm *hdspm = entry->private_data; - unsigned int status1, status2, status3, control, i; - unsigned int lock, sync; - - status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */ - status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */ - status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */ - - control = hdspm->control_register; - - snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1); - snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2); - snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3); - - - snd_iprintf(buffer, "\n*** CLOCK MODE\n\n"); - - snd_iprintf(buffer, "Clock mode : %s\n", - (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave"); - snd_iprintf(buffer, "System frequency: %d Hz\n", - hdspm_get_system_sample_rate(hdspm)); - - snd_iprintf(buffer, "\n*** INPUT STATUS\n\n"); - - lock = 0x1; - sync = 0x100; - - for (i = 0; i < 8; i++) { - snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n", - i, - (status1 & lock) ? 1 : 0, - (status1 & sync) ? 1 : 0, - texts_freq[(status2 >> (i * 4)) & 0xF]); - - lock = lock<<1; - sync = sync<<1; - } - - snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n", - (status1 & 0x1000000) ? 1 : 0, - (status1 & 0x2000000) ? 1 : 0, - texts_freq[(status1 >> 16) & 0xF]); - - snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n", - (status1 & 0x4000000) ? 1 : 0, - (status1 & 0x8000000) ? 1 : 0, - texts_freq[(status1 >> 20) & 0xF]); - - snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n", - (status3 & 0x400) ? 1 : 0, - (status3 & 0x800) ? 1 : 0, - texts_freq[(status2 >> 12) & 0xF]); - -} - -#ifdef CONFIG_SND_DEBUG -static void -snd_hdspm_proc_read_debug(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct hdspm *hdspm = entry->private_data; - - int j,i; - - for (i = 0; i < 256 /* 1024*64 */; i += j) { - snd_iprintf(buffer, "0x%08X: ", i); - for (j = 0; j < 16; j += 4) - snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j)); - snd_iprintf(buffer, "\n"); - } -} -#endif - - -static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct hdspm *hdspm = entry->private_data; - int i; - - snd_iprintf(buffer, "# generated by hdspm\n"); - - for (i = 0; i < hdspm->max_channels_in; i++) { - snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]); - } -} - -static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct hdspm *hdspm = entry->private_data; - int i; - - snd_iprintf(buffer, "# generated by hdspm\n"); - - for (i = 0; i < hdspm->max_channels_out; i++) { - snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]); - } -} - - -static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) { - switch (hdspm->io_type) { - case AES32: - snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_aes32); - break; - case MADI: - snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_madi); - break; - case MADIface: - /* snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_madiface); */ - break; - case RayDAT: - snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_raydat); - break; - case AIO: - break; - } - } - - if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) { - snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in); - } - - if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) { - snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out); - } - -#ifdef CONFIG_SND_DEBUG - /* debug file to read all hdspm registers */ - if (!snd_card_proc_new(hdspm->card, "debug", &entry)) - snd_info_set_text_ops(entry, hdspm, - snd_hdspm_proc_read_debug); -#endif -} - -/*------------------------------------------------------------ - hdspm intitialize - ------------------------------------------------------------*/ - -static int snd_hdspm_set_defaults(struct hdspm * hdspm) -{ - /* ASSUMPTION: hdspm->lock is either held, or there is no need to - hold it (e.g. during module initialization). - */ - - /* set defaults: */ - - hdspm->settings_register = 0; - - switch (hdspm->io_type) { - case MADI: - case MADIface: - hdspm->control_register = - 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000; - break; - - case RayDAT: - case AIO: - hdspm->settings_register = 0x1 + 0x1000; - /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0, - * line_out */ - hdspm->control_register = - 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000; - break; - - case AES32: - hdspm->control_register = - HDSPM_ClockModeMaster | /* Master Cloack Mode on */ - hdspm_encode_latency(7) | /* latency max=8192samples */ - HDSPM_SyncRef0 | /* AES1 is syncclock */ - HDSPM_LineOut | /* Analog output in */ - HDSPM_Professional; /* Professional mode */ - break; - } - - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - if (AES32 == hdspm->io_type) { - /* No control2 register for AES32 */ -#ifdef SNDRV_BIG_ENDIAN - hdspm->control2_register = HDSPM_BIGENDIAN_MODE; -#else - hdspm->control2_register = 0; -#endif - - hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register); - } - hdspm_compute_period_size(hdspm); - - /* silence everything */ - - all_in_all_mixer(hdspm, 0 * UNITY_GAIN); - - if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) { - hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); - } - - /* set a default rate so that the channel map is set up. */ - hdspm_set_rate(hdspm, 48000, 1); - - return 0; -} - - -/*------------------------------------------------------------ - interrupt - ------------------------------------------------------------*/ - -static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) -{ - struct hdspm *hdspm = (struct hdspm *) dev_id; - unsigned int status; - int i, audio, midi, schedule = 0; - /* cycles_t now; */ - - status = hdspm_read(hdspm, HDSPM_statusRegister); - - audio = status & HDSPM_audioIRQPending; - midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending | - HDSPM_midi2IRQPending | HDSPM_midi3IRQPending); - - /* now = get_cycles(); */ - /** - * LAT_2..LAT_0 period counter (win) counter (mac) - * 6 4096 ~256053425 ~514672358 - * 5 2048 ~128024983 ~257373821 - * 4 1024 ~64023706 ~128718089 - * 3 512 ~32005945 ~64385999 - * 2 256 ~16003039 ~32260176 - * 1 128 ~7998738 ~16194507 - * 0 64 ~3998231 ~8191558 - **/ - /* - snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n", - now-hdspm->last_interrupt, status & 0xFFC0); - hdspm->last_interrupt = now; - */ - - if (!audio && !midi) - return IRQ_NONE; - - hdspm_write(hdspm, HDSPM_interruptConfirmation, 0); - hdspm->irq_count++; - - - if (audio) { - if (hdspm->capture_substream) - snd_pcm_period_elapsed(hdspm->capture_substream); - - if (hdspm->playback_substream) - snd_pcm_period_elapsed(hdspm->playback_substream); - } - - if (midi) { - i = 0; - while (i < hdspm->midiPorts) { - if ((hdspm_read(hdspm, - hdspm->midi[i].statusIn) & 0xff) && - (status & hdspm->midi[i].irq)) { - /* we disable interrupts for this input until - * processing is done - */ - hdspm->control_register &= ~hdspm->midi[i].ie; - hdspm_write(hdspm, HDSPM_controlRegister, - hdspm->control_register); - hdspm->midi[i].pending = 1; - schedule = 1; - } - - i++; - } - - if (schedule) - tasklet_hi_schedule(&hdspm->midi_tasklet); - } - - return IRQ_HANDLED; -} - -/*------------------------------------------------------------ - pcm interface - ------------------------------------------------------------*/ - - -static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream - *substream) -{ - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - return hdspm_hw_pointer(hdspm); -} - - -static int snd_hdspm_reset(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *other; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - other = hdspm->capture_substream; - else - other = hdspm->playback_substream; - - if (hdspm->running) - runtime->status->hw_ptr = hdspm_hw_pointer(hdspm); - else - runtime->status->hw_ptr = 0; - if (other) { - struct snd_pcm_substream *s; - struct snd_pcm_runtime *oruntime = other->runtime; - snd_pcm_group_for_each_entry(s, substream) { - if (s == other) { - oruntime->status->hw_ptr = - runtime->status->hw_ptr; - break; - } - } - } - return 0; -} - -static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - int err; - int i; - pid_t this_pid; - pid_t other_pid; - - spin_lock_irq(&hdspm->lock); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { - this_pid = hdspm->playback_pid; - other_pid = hdspm->capture_pid; - } else { - this_pid = hdspm->capture_pid; - other_pid = hdspm->playback_pid; - } - - if (other_pid > 0 && this_pid != other_pid) { - - /* The other stream is open, and not by the same - task as this one. Make sure that the parameters - that matter are the same. - */ - - if (params_rate(params) != hdspm->system_sample_rate) { - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_RATE); - return -EBUSY; - } - - if (params_period_size(params) != hdspm->period_bytes / 4) { - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return -EBUSY; - } - - } - /* We're fine. */ - spin_unlock_irq(&hdspm->lock); - - /* how to make sure that the rate matches an externally-set one ? */ - - spin_lock_irq(&hdspm->lock); - err = hdspm_set_rate(hdspm, params_rate(params), 0); - if (err < 0) { - snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err); - spin_unlock_irq(&hdspm->lock); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_RATE); - return err; - } - spin_unlock_irq(&hdspm->lock); - - err = hdspm_set_interrupt_interval(hdspm, - params_period_size(params)); - if (err < 0) { - snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err); - _snd_pcm_hw_param_setempty(params, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return err; - } - - /* Memory allocation, takashi's method, dont know if we should - * spinlock - */ - /* malloc all buffer even if not enabled to get sure */ - /* Update for MADI rev 204: we need to allocate for all channels, - * otherwise it doesn't work at 96kHz */ - - err = - snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES); - if (err < 0) { - snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err); - return err; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - - hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut, - params_channels(params)); - - for (i = 0; i < params_channels(params); ++i) - snd_hdspm_enable_out(hdspm, i, 1); - - hdspm->playback_buffer = - (unsigned char *) substream->runtime->dma_area; - snd_printdd("Allocated sample buffer for playback at %p\n", - hdspm->playback_buffer); - } else { - hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn, - params_channels(params)); - - for (i = 0; i < params_channels(params); ++i) - snd_hdspm_enable_in(hdspm, i, 1); - - hdspm->capture_buffer = - (unsigned char *) substream->runtime->dma_area; - snd_printdd("Allocated sample buffer for capture at %p\n", - hdspm->capture_buffer); - } - - /* - snd_printdd("Allocated sample buffer for %s at 0x%08X\n", - substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - "playback" : "capture", - snd_pcm_sgbuf_get_addr(substream, 0)); - */ - /* - snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n", - substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - "playback" : "capture", - params_rate(params), params_channels(params), - params_buffer_size(params)); - */ - - - /* Switch to native float format if requested */ - if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) { - if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT)) - snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n"); - - hdspm->control_register |= HDSPe_FLOAT_FORMAT; - } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) { - if (hdspm->control_register & HDSPe_FLOAT_FORMAT) - snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n"); - - hdspm->control_register &= ~HDSPe_FLOAT_FORMAT; - } - hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); - - return 0; -} - -static int snd_hdspm_hw_free(struct snd_pcm_substream *substream) -{ - int i; - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - - /* params_channels(params) should be enough, - but to get sure in case of error */ - for (i = 0; i < hdspm->max_channels_out; ++i) - snd_hdspm_enable_out(hdspm, i, 0); - - hdspm->playback_buffer = NULL; - } else { - for (i = 0; i < hdspm->max_channels_in; ++i) - snd_hdspm_enable_in(hdspm, i, 0); - - hdspm->capture_buffer = NULL; - - } - - snd_pcm_lib_free_pages(substream); - - return 0; -} - - -static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, - struct snd_pcm_channel_info *info) -{ - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) { - snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel); - return -EINVAL; - } - - if (hdspm->channel_map_out[info->channel] < 0) { - snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel); - return -EINVAL; - } - - info->offset = hdspm->channel_map_out[info->channel] * - HDSPM_CHANNEL_BUFFER_BYTES; - } else { - if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) { - snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel); - return -EINVAL; - } - - if (hdspm->channel_map_in[info->channel] < 0) { - snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel); - return -EINVAL; - } - - info->offset = hdspm->channel_map_in[info->channel] * - HDSPM_CHANNEL_BUFFER_BYTES; - } - - info->first = 0; - info->step = 32; - return 0; -} - - -static int snd_hdspm_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - switch (cmd) { - case SNDRV_PCM_IOCTL1_RESET: - return snd_hdspm_reset(substream); - - case SNDRV_PCM_IOCTL1_CHANNEL_INFO: - { - struct snd_pcm_channel_info *info = arg; - return snd_hdspm_channel_info(substream, info); - } - default: - break; - } - - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *other; - int running; - - spin_lock(&hdspm->lock); - running = hdspm->running; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - running |= 1 << substream->stream; - break; - case SNDRV_PCM_TRIGGER_STOP: - running &= ~(1 << substream->stream); - break; - default: - snd_BUG(); - spin_unlock(&hdspm->lock); - return -EINVAL; - } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - other = hdspm->capture_substream; - else - other = hdspm->playback_substream; - - if (other) { - struct snd_pcm_substream *s; - snd_pcm_group_for_each_entry(s, substream) { - if (s == other) { - snd_pcm_trigger_done(s, substream); - if (cmd == SNDRV_PCM_TRIGGER_START) - running |= 1 << s->stream; - else - running &= ~(1 << s->stream); - goto _ok; - } - } - if (cmd == SNDRV_PCM_TRIGGER_START) { - if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) - && substream->stream == - SNDRV_PCM_STREAM_CAPTURE) - hdspm_silence_playback(hdspm); - } else { - if (running && - substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - hdspm_silence_playback(hdspm); - } - } else { - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - hdspm_silence_playback(hdspm); - } -_ok: - snd_pcm_trigger_done(substream, substream); - if (!hdspm->running && running) - hdspm_start_audio(hdspm); - else if (hdspm->running && !running) - hdspm_stop_audio(hdspm); - hdspm->running = running; - spin_unlock(&hdspm->lock); - - return 0; -} - -static int snd_hdspm_prepare(struct snd_pcm_substream *substream) -{ - return 0; -} - -static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ), - .rate_min = 32000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = HDSPM_MAX_CHANNELS, - .buffer_bytes_max = - HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, - .period_bytes_min = (32 * 4), - .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, - .periods_min = 2, - .periods_max = 512, - .fifo_size = 0 -}; - -static struct snd_pcm_hardware snd_hdspm_capture_subinfo = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000), - .rate_min = 32000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = HDSPM_MAX_CHANNELS, - .buffer_bytes_max = - HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, - .period_bytes_min = (32 * 4), - .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, - .periods_min = 2, - .periods_max = 512, - .fifo_size = 0 -}; - -static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct hdspm *hdspm = rule->private; - struct snd_interval *c = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - - if (r->min > 96000 && r->max <= 192000) { - struct snd_interval t = { - .min = hdspm->qs_in_channels, - .max = hdspm->qs_in_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->min > 48000 && r->max <= 96000) { - struct snd_interval t = { - .min = hdspm->ds_in_channels, - .max = hdspm->ds_in_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->max < 64000) { - struct snd_interval t = { - .min = hdspm->ss_in_channels, - .max = hdspm->ss_in_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } - - return 0; -} - -static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule * rule) -{ - struct hdspm *hdspm = rule->private; - struct snd_interval *c = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - - if (r->min > 96000 && r->max <= 192000) { - struct snd_interval t = { - .min = hdspm->qs_out_channels, - .max = hdspm->qs_out_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->min > 48000 && r->max <= 96000) { - struct snd_interval t = { - .min = hdspm->ds_out_channels, - .max = hdspm->ds_out_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->max < 64000) { - struct snd_interval t = { - .min = hdspm->ss_out_channels, - .max = hdspm->ss_out_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else { - } - return 0; -} - -static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule * rule) -{ - struct hdspm *hdspm = rule->private; - struct snd_interval *c = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - - if (c->min >= hdspm->ss_in_channels) { - struct snd_interval t = { - .min = 32000, - .max = 48000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= hdspm->qs_in_channels) { - struct snd_interval t = { - .min = 128000, - .max = 192000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= hdspm->ds_in_channels) { - struct snd_interval t = { - .min = 64000, - .max = 96000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } - - return 0; -} -static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct hdspm *hdspm = rule->private; - struct snd_interval *c = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - - if (c->min >= hdspm->ss_out_channels) { - struct snd_interval t = { - .min = 32000, - .max = 48000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= hdspm->qs_out_channels) { - struct snd_interval t = { - .min = 128000, - .max = 192000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= hdspm->ds_out_channels) { - struct snd_interval t = { - .min = 64000, - .max = 96000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } - - return 0; -} - -static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - unsigned int list[3]; - struct hdspm *hdspm = rule->private; - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - list[0] = hdspm->qs_in_channels; - list[1] = hdspm->ds_in_channels; - list[2] = hdspm->ss_in_channels; - return snd_interval_list(c, 3, list, 0); -} - -static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - unsigned int list[3]; - struct hdspm *hdspm = rule->private; - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - list[0] = hdspm->qs_out_channels; - list[1] = hdspm->ds_out_channels; - list[2] = hdspm->ss_out_channels; - return snd_interval_list(c, 3, list, 0); -} - - -static unsigned int hdspm_aes32_sample_rates[] = { - 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 -}; - -static struct snd_pcm_hw_constraint_list -hdspm_hw_constraints_aes32_sample_rates = { - .count = ARRAY_SIZE(hdspm_aes32_sample_rates), - .list = hdspm_aes32_sample_rates, - .mask = 0 -}; - -static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) -{ - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irq(&hdspm->lock); - - snd_pcm_set_sync(substream); - - - runtime->hw = snd_hdspm_playback_subinfo; - - if (hdspm->capture_substream == NULL) - hdspm_stop_audio(hdspm); - - hdspm->playback_pid = current->pid; - hdspm->playback_substream = substream; - - spin_unlock_irq(&hdspm->lock); - - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - - switch (hdspm->io_type) { - case AIO: - case RayDAT: - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 32, 4096); - /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */ - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - 16384, 16384); - break; - - default: - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 64, 8192); - break; - } - - if (AES32 == hdspm->io_type) { - runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hdspm_hw_constraints_aes32_sample_rates); - } else { - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_hdspm_hw_rule_rate_out_channels, hdspm, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - } - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdspm_hw_rule_out_channels, hdspm, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdspm_hw_rule_out_channels_rate, hdspm, - SNDRV_PCM_HW_PARAM_RATE, -1); - - return 0; -} - -static int snd_hdspm_playback_release(struct snd_pcm_substream *substream) -{ - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - - spin_lock_irq(&hdspm->lock); - - hdspm->playback_pid = -1; - hdspm->playback_substream = NULL; - - spin_unlock_irq(&hdspm->lock); - - return 0; -} - - -static int snd_hdspm_capture_open(struct snd_pcm_substream *substream) -{ - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irq(&hdspm->lock); - snd_pcm_set_sync(substream); - runtime->hw = snd_hdspm_capture_subinfo; - - if (hdspm->playback_substream == NULL) - hdspm_stop_audio(hdspm); - - hdspm->capture_pid = current->pid; - hdspm->capture_substream = substream; - - spin_unlock_irq(&hdspm->lock); - - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - - switch (hdspm->io_type) { - case AIO: - case RayDAT: - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 32, 4096); - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - 16384, 16384); - break; - - default: - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 64, 8192); - break; - } - - if (AES32 == hdspm->io_type) { - runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hdspm_hw_constraints_aes32_sample_rates); - } else { - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_hdspm_hw_rule_rate_in_channels, hdspm, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - } - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdspm_hw_rule_in_channels, hdspm, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hdspm_hw_rule_in_channels_rate, hdspm, - SNDRV_PCM_HW_PARAM_RATE, -1); - - return 0; -} - -static int snd_hdspm_capture_release(struct snd_pcm_substream *substream) -{ - struct hdspm *hdspm = snd_pcm_substream_chip(substream); - - spin_lock_irq(&hdspm->lock); - - hdspm->capture_pid = -1; - hdspm->capture_substream = NULL; - - spin_unlock_irq(&hdspm->lock); - return 0; -} - -static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file) -{ - /* we have nothing to initialize but the call is required */ - return 0; -} - -static inline int copy_u32_le(void __user *dest, void __iomem *src) -{ - u32 val = readl(src); - return copy_to_user(dest, &val, 4); -} - -static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, - unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - struct hdspm *hdspm = hw->private_data; - struct hdspm_mixer_ioctl mixer; - struct hdspm_config info; - struct hdspm_status status; - struct hdspm_version hdspm_version; - struct hdspm_peak_rms *levels; - struct hdspm_ltc ltc; - unsigned int statusregister; - long unsigned int s; - int i = 0; - - switch (cmd) { - - case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: - levels = &hdspm->peak_rms; - for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { - levels->input_peaks[i] = - readl(hdspm->iobase + - HDSPM_MADI_INPUT_PEAK + i*4); - levels->playback_peaks[i] = - readl(hdspm->iobase + - HDSPM_MADI_PLAYBACK_PEAK + i*4); - levels->output_peaks[i] = - readl(hdspm->iobase + - HDSPM_MADI_OUTPUT_PEAK + i*4); - - levels->input_rms[i] = - ((uint64_t) readl(hdspm->iobase + - HDSPM_MADI_INPUT_RMS_H + i*4) << 32) | - (uint64_t) readl(hdspm->iobase + - HDSPM_MADI_INPUT_RMS_L + i*4); - levels->playback_rms[i] = - ((uint64_t)readl(hdspm->iobase + - HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) | - (uint64_t)readl(hdspm->iobase + - HDSPM_MADI_PLAYBACK_RMS_L + i*4); - levels->output_rms[i] = - ((uint64_t)readl(hdspm->iobase + - HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) | - (uint64_t)readl(hdspm->iobase + - HDSPM_MADI_OUTPUT_RMS_L + i*4); - } - - if (hdspm->system_sample_rate > 96000) { - levels->speed = qs; - } else if (hdspm->system_sample_rate > 48000) { - levels->speed = ds; - } else { - levels->speed = ss; - } - levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2); - - s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms)); - if (0 != s) { - /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu - [Levels]\n", sizeof(struct hdspm_peak_rms), s); - */ - return -EFAULT; - } - break; - - case SNDRV_HDSPM_IOCTL_GET_LTC: - ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO); - i = hdspm_read(hdspm, HDSPM_RD_TCO + 4); - if (i & HDSPM_TCO1_LTC_Input_valid) { - switch (i & (HDSPM_TCO1_LTC_Format_LSB | - HDSPM_TCO1_LTC_Format_MSB)) { - case 0: - ltc.format = fps_24; - break; - case HDSPM_TCO1_LTC_Format_LSB: - ltc.format = fps_25; - break; - case HDSPM_TCO1_LTC_Format_MSB: - ltc.format = fps_2997; - break; - default: - ltc.format = 30; - break; - } - if (i & HDSPM_TCO1_set_drop_frame_flag) { - ltc.frame = drop_frame; - } else { - ltc.frame = full_frame; - } - } else { - ltc.format = format_invalid; - ltc.frame = frame_invalid; - } - if (i & HDSPM_TCO1_Video_Input_Format_NTSC) { - ltc.input_format = ntsc; - } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) { - ltc.input_format = pal; - } else { - ltc.input_format = no_video; - } - - s = copy_to_user(argp, <c, sizeof(struct hdspm_ltc)); - if (0 != s) { - /* - snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */ - return -EFAULT; - } - - break; - - case SNDRV_HDSPM_IOCTL_GET_CONFIG: - - memset(&info, 0, sizeof(info)); - spin_lock_irq(&hdspm->lock); - info.pref_sync_ref = hdspm_pref_sync_ref(hdspm); - info.wordclock_sync_check = hdspm_wc_sync_check(hdspm); - - info.system_sample_rate = hdspm->system_sample_rate; - info.autosync_sample_rate = - hdspm_external_sample_rate(hdspm); - info.system_clock_mode = hdspm_system_clock_mode(hdspm); - info.clock_source = hdspm_clock_source(hdspm); - info.autosync_ref = hdspm_autosync_ref(hdspm); - info.line_out = hdspm_line_out(hdspm); - info.passthru = 0; - spin_unlock_irq(&hdspm->lock); - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - break; - - case SNDRV_HDSPM_IOCTL_GET_STATUS: - memset(&status, 0, sizeof(status)); - - status.card_type = hdspm->io_type; - - status.autosync_source = hdspm_autosync_ref(hdspm); - - status.card_clock = 110069313433624ULL; - status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); - - switch (hdspm->io_type) { - case MADI: - case MADIface: - status.card_specific.madi.sync_wc = - hdspm_wc_sync_check(hdspm); - status.card_specific.madi.sync_madi = - hdspm_madi_sync_check(hdspm); - status.card_specific.madi.sync_tco = - hdspm_tco_sync_check(hdspm); - status.card_specific.madi.sync_in = - hdspm_sync_in_sync_check(hdspm); - - statusregister = - hdspm_read(hdspm, HDSPM_statusRegister); - status.card_specific.madi.madi_input = - (statusregister & HDSPM_AB_int) ? 1 : 0; - status.card_specific.madi.channel_format = - (statusregister & HDSPM_RX_64ch) ? 1 : 0; - /* TODO: Mac driver sets it when f_s>48kHz */ - status.card_specific.madi.frame_format = 0; - - default: - break; - } - - if (copy_to_user(argp, &status, sizeof(status))) - return -EFAULT; - - - break; - - case SNDRV_HDSPM_IOCTL_GET_VERSION: - memset(&hdspm_version, 0, sizeof(hdspm_version)); - - hdspm_version.card_type = hdspm->io_type; - strncpy(hdspm_version.cardname, hdspm->card_name, - sizeof(hdspm_version.cardname)); - hdspm_version.serial = hdspm->serial; - hdspm_version.firmware_rev = hdspm->firmware_rev; - hdspm_version.addons = 0; - if (hdspm->tco) - hdspm_version.addons |= HDSPM_ADDON_TCO; - - if (copy_to_user(argp, &hdspm_version, - sizeof(hdspm_version))) - return -EFAULT; - break; - - case SNDRV_HDSPM_IOCTL_GET_MIXER: - if (copy_from_user(&mixer, argp, sizeof(mixer))) - return -EFAULT; - if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer, - sizeof(struct hdspm_mixer))) - return -EFAULT; - break; - - default: - return -EINVAL; - } - return 0; -} - -static struct snd_pcm_ops snd_hdspm_playback_ops = { - .open = snd_hdspm_playback_open, - .close = snd_hdspm_playback_release, - .ioctl = snd_hdspm_ioctl, - .hw_params = snd_hdspm_hw_params, - .hw_free = snd_hdspm_hw_free, - .prepare = snd_hdspm_prepare, - .trigger = snd_hdspm_trigger, - .pointer = snd_hdspm_hw_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -static struct snd_pcm_ops snd_hdspm_capture_ops = { - .open = snd_hdspm_capture_open, - .close = snd_hdspm_capture_release, - .ioctl = snd_hdspm_ioctl, - .hw_params = snd_hdspm_hw_params, - .hw_free = snd_hdspm_hw_free, - .prepare = snd_hdspm_prepare, - .trigger = snd_hdspm_trigger, - .pointer = snd_hdspm_hw_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -static int __devinit snd_hdspm_create_hwdep(struct snd_card *card, - struct hdspm * hdspm) -{ - struct snd_hwdep *hw; - int err; - - err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw); - if (err < 0) - return err; - - hdspm->hwdep = hw; - hw->private_data = hdspm; - strcpy(hw->name, "HDSPM hwdep interface"); - - hw->ops.open = snd_hdspm_hwdep_dummy_op; - hw->ops.ioctl = snd_hdspm_hwdep_ioctl; - hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl; - hw->ops.release = snd_hdspm_hwdep_dummy_op; - - return 0; -} - - -/*------------------------------------------------------------ - memory interface - ------------------------------------------------------------*/ -static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm) -{ - int err; - struct snd_pcm *pcm; - size_t wanted; - - pcm = hdspm->pcm; - - wanted = HDSPM_DMA_AREA_BYTES; - - err = - snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(hdspm->pci), - wanted, - wanted); - if (err < 0) { - snd_printdd("Could not preallocate %zd Bytes\n", wanted); - - return err; - } else - snd_printdd(" Preallocated %zd Bytes\n", wanted); - - return 0; -} - - -static void hdspm_set_sgbuf(struct hdspm *hdspm, - struct snd_pcm_substream *substream, - unsigned int reg, int channels) -{ - int i; - - /* continuous memory segment */ - for (i = 0; i < (channels * 16); i++) - hdspm_write(hdspm, reg + 4 * i, - snd_pcm_sgbuf_get_addr(substream, 4096 * i)); -} - - -/* ------------- ALSA Devices ---------------------------- */ -static int __devinit snd_hdspm_create_pcm(struct snd_card *card, - struct hdspm *hdspm) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm); - if (err < 0) - return err; - - hdspm->pcm = pcm; - pcm->private_data = hdspm; - strcpy(pcm->name, hdspm->card_name); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_hdspm_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_hdspm_capture_ops); - - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - - err = snd_hdspm_preallocate_memory(hdspm); - if (err < 0) - return err; - - return 0; -} - -static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm) -{ - int i; - - for (i = 0; i < hdspm->midiPorts; i++) - snd_hdspm_flush_midi_input(hdspm, i); -} - -static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, - struct hdspm * hdspm) -{ - int err, i; - - snd_printdd("Create card...\n"); - err = snd_hdspm_create_pcm(card, hdspm); - if (err < 0) - return err; - - i = 0; - while (i < hdspm->midiPorts) { - err = snd_hdspm_create_midi(card, hdspm, i); - if (err < 0) { - return err; - } - i++; - } - - err = snd_hdspm_create_controls(card, hdspm); - if (err < 0) - return err; - - err = snd_hdspm_create_hwdep(card, hdspm); - if (err < 0) - return err; - - snd_printdd("proc init...\n"); - snd_hdspm_proc_init(hdspm); - - hdspm->system_sample_rate = -1; - hdspm->last_external_sample_rate = -1; - hdspm->last_internal_sample_rate = -1; - hdspm->playback_pid = -1; - hdspm->capture_pid = -1; - hdspm->capture_substream = NULL; - hdspm->playback_substream = NULL; - - snd_printdd("Set defaults...\n"); - err = snd_hdspm_set_defaults(hdspm); - if (err < 0) - return err; - - snd_printdd("Update mixer controls...\n"); - hdspm_update_simple_mixer_controls(hdspm); - - snd_printdd("Initializeing complete ???\n"); - - err = snd_card_register(card); - if (err < 0) { - snd_printk(KERN_ERR "HDSPM: error registering card\n"); - return err; - } - - snd_printdd("... yes now\n"); - - return 0; -} - -static int __devinit snd_hdspm_create(struct snd_card *card, - struct hdspm *hdspm) { - - struct pci_dev *pci = hdspm->pci; - int err; - unsigned long io_extent; - - hdspm->irq = -1; - hdspm->card = card; - - spin_lock_init(&hdspm->lock); - - pci_read_config_word(hdspm->pci, - PCI_CLASS_REVISION, &hdspm->firmware_rev); - - strcpy(card->mixername, "Xilinx FPGA"); - strcpy(card->driver, "HDSPM"); - - switch (hdspm->firmware_rev) { - case HDSPM_RAYDAT_REV: - hdspm->io_type = RayDAT; - hdspm->card_name = "RME RayDAT"; - hdspm->midiPorts = 2; - break; - case HDSPM_AIO_REV: - hdspm->io_type = AIO; - hdspm->card_name = "RME AIO"; - hdspm->midiPorts = 1; - break; - case HDSPM_MADIFACE_REV: - hdspm->io_type = MADIface; - hdspm->card_name = "RME MADIface"; - hdspm->midiPorts = 1; - break; - default: - if ((hdspm->firmware_rev == 0xf0) || - ((hdspm->firmware_rev >= 0xe6) && - (hdspm->firmware_rev <= 0xea))) { - hdspm->io_type = AES32; - hdspm->card_name = "RME AES32"; - hdspm->midiPorts = 2; - } else if ((hdspm->firmware_rev == 0xd2) || - ((hdspm->firmware_rev >= 0xc8) && - (hdspm->firmware_rev <= 0xcf))) { - hdspm->io_type = MADI; - hdspm->card_name = "RME MADI"; - hdspm->midiPorts = 3; - } else { - snd_printk(KERN_ERR - "HDSPM: unknown firmware revision %x\n", - hdspm->firmware_rev); - return -ENODEV; - } - } - - err = pci_enable_device(pci); - if (err < 0) - return err; - - pci_set_master(hdspm->pci); - - err = pci_request_regions(pci, "hdspm"); - if (err < 0) - return err; - - hdspm->port = pci_resource_start(pci, 0); - io_extent = pci_resource_len(pci, 0); - - snd_printdd("grabbed memory region 0x%lx-0x%lx\n", - hdspm->port, hdspm->port + io_extent - 1); - - hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); - if (!hdspm->iobase) { - snd_printk(KERN_ERR "HDSPM: " - "unable to remap region 0x%lx-0x%lx\n", - hdspm->port, hdspm->port + io_extent - 1); - return -EBUSY; - } - snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n", - (unsigned long)hdspm->iobase, hdspm->port, - hdspm->port + io_extent - 1); - - if (request_irq(pci->irq, snd_hdspm_interrupt, - IRQF_SHARED, KBUILD_MODNAME, hdspm)) { - snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); - return -EBUSY; - } - - snd_printdd("use IRQ %d\n", pci->irq); - - hdspm->irq = pci->irq; - - snd_printdd("kmalloc Mixer memory of %zd Bytes\n", - sizeof(struct hdspm_mixer)); - hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL); - if (!hdspm->mixer) { - snd_printk(KERN_ERR "HDSPM: " - "unable to kmalloc Mixer memory of %d Bytes\n", - (int)sizeof(struct hdspm_mixer)); - return err; - } - - hdspm->port_names_in = NULL; - hdspm->port_names_out = NULL; - - switch (hdspm->io_type) { - case AES32: - hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS; - hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS; - hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS; - - hdspm->channel_map_in_ss = hdspm->channel_map_out_ss = - channel_map_aes32; - hdspm->channel_map_in_ds = hdspm->channel_map_out_ds = - channel_map_aes32; - hdspm->channel_map_in_qs = hdspm->channel_map_out_qs = - channel_map_aes32; - hdspm->port_names_in_ss = hdspm->port_names_out_ss = - texts_ports_aes32; - hdspm->port_names_in_ds = hdspm->port_names_out_ds = - texts_ports_aes32; - hdspm->port_names_in_qs = hdspm->port_names_out_qs = - texts_ports_aes32; - - hdspm->max_channels_out = hdspm->max_channels_in = - AES32_CHANNELS; - hdspm->port_names_in = hdspm->port_names_out = - texts_ports_aes32; - hdspm->channel_map_in = hdspm->channel_map_out = - channel_map_aes32; - - break; - - case MADI: - case MADIface: - hdspm->ss_in_channels = hdspm->ss_out_channels = - MADI_SS_CHANNELS; - hdspm->ds_in_channels = hdspm->ds_out_channels = - MADI_DS_CHANNELS; - hdspm->qs_in_channels = hdspm->qs_out_channels = - MADI_QS_CHANNELS; - - hdspm->channel_map_in_ss = hdspm->channel_map_out_ss = - channel_map_unity_ss; - hdspm->channel_map_in_ds = hdspm->channel_map_out_ds = - channel_map_unity_ss; - hdspm->channel_map_in_qs = hdspm->channel_map_out_qs = - channel_map_unity_ss; - - hdspm->port_names_in_ss = hdspm->port_names_out_ss = - texts_ports_madi; - hdspm->port_names_in_ds = hdspm->port_names_out_ds = - texts_ports_madi; - hdspm->port_names_in_qs = hdspm->port_names_out_qs = - texts_ports_madi; - break; - - case AIO: - if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) { - snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n"); - } - - hdspm->ss_in_channels = AIO_IN_SS_CHANNELS; - hdspm->ds_in_channels = AIO_IN_DS_CHANNELS; - hdspm->qs_in_channels = AIO_IN_QS_CHANNELS; - hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS; - hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS; - hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS; - - hdspm->channel_map_out_ss = channel_map_aio_out_ss; - hdspm->channel_map_out_ds = channel_map_aio_out_ds; - hdspm->channel_map_out_qs = channel_map_aio_out_qs; - - hdspm->channel_map_in_ss = channel_map_aio_in_ss; - hdspm->channel_map_in_ds = channel_map_aio_in_ds; - hdspm->channel_map_in_qs = channel_map_aio_in_qs; - - hdspm->port_names_in_ss = texts_ports_aio_in_ss; - hdspm->port_names_out_ss = texts_ports_aio_out_ss; - hdspm->port_names_in_ds = texts_ports_aio_in_ds; - hdspm->port_names_out_ds = texts_ports_aio_out_ds; - hdspm->port_names_in_qs = texts_ports_aio_in_qs; - hdspm->port_names_out_qs = texts_ports_aio_out_qs; - - break; - - case RayDAT: - hdspm->ss_in_channels = hdspm->ss_out_channels = - RAYDAT_SS_CHANNELS; - hdspm->ds_in_channels = hdspm->ds_out_channels = - RAYDAT_DS_CHANNELS; - hdspm->qs_in_channels = hdspm->qs_out_channels = - RAYDAT_QS_CHANNELS; - - hdspm->max_channels_in = RAYDAT_SS_CHANNELS; - hdspm->max_channels_out = RAYDAT_SS_CHANNELS; - - hdspm->channel_map_in_ss = hdspm->channel_map_out_ss = - channel_map_raydat_ss; - hdspm->channel_map_in_ds = hdspm->channel_map_out_ds = - channel_map_raydat_ds; - hdspm->channel_map_in_qs = hdspm->channel_map_out_qs = - channel_map_raydat_qs; - hdspm->channel_map_in = hdspm->channel_map_out = - channel_map_raydat_ss; - - hdspm->port_names_in_ss = hdspm->port_names_out_ss = - texts_ports_raydat_ss; - hdspm->port_names_in_ds = hdspm->port_names_out_ds = - texts_ports_raydat_ds; - hdspm->port_names_in_qs = hdspm->port_names_out_qs = - texts_ports_raydat_qs; - - - break; - - } - - /* TCO detection */ - switch (hdspm->io_type) { - case AIO: - case RayDAT: - if (hdspm_read(hdspm, HDSPM_statusRegister2) & - HDSPM_s2_tco_detect) { - hdspm->midiPorts++; - hdspm->tco = kzalloc(sizeof(struct hdspm_tco), - GFP_KERNEL); - if (NULL != hdspm->tco) { - hdspm_tco_write(hdspm); - } - snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n"); - } else { - hdspm->tco = NULL; - } - break; - - case MADI: - if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) { - hdspm->midiPorts++; - hdspm->tco = kzalloc(sizeof(struct hdspm_tco), - GFP_KERNEL); - if (NULL != hdspm->tco) { - hdspm_tco_write(hdspm); - } - snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n"); - } else { - hdspm->tco = NULL; - } - break; - - default: - hdspm->tco = NULL; - } - - /* texts */ - switch (hdspm->io_type) { - case AES32: - if (hdspm->tco) { - hdspm->texts_autosync = texts_autosync_aes_tco; - hdspm->texts_autosync_items = 10; - } else { - hdspm->texts_autosync = texts_autosync_aes; - hdspm->texts_autosync_items = 9; - } - break; - - case MADI: - if (hdspm->tco) { - hdspm->texts_autosync = texts_autosync_madi_tco; - hdspm->texts_autosync_items = 4; - } else { - hdspm->texts_autosync = texts_autosync_madi; - hdspm->texts_autosync_items = 3; - } - break; - - case MADIface: - - break; - - case RayDAT: - if (hdspm->tco) { - hdspm->texts_autosync = texts_autosync_raydat_tco; - hdspm->texts_autosync_items = 9; - } else { - hdspm->texts_autosync = texts_autosync_raydat; - hdspm->texts_autosync_items = 8; - } - break; - - case AIO: - if (hdspm->tco) { - hdspm->texts_autosync = texts_autosync_aio_tco; - hdspm->texts_autosync_items = 6; - } else { - hdspm->texts_autosync = texts_autosync_aio; - hdspm->texts_autosync_items = 5; - } - break; - - } - - tasklet_init(&hdspm->midi_tasklet, - hdspm_midi_tasklet, (unsigned long) hdspm); - - - if (hdspm->io_type != MADIface) { - hdspm->serial = (hdspm_read(hdspm, - HDSPM_midiStatusIn0)>>8) & 0xFFFFFF; - /* id contains either a user-provided value or the default - * NULL. If it's the default, we're safe to - * fill card->id with the serial number. - * - * If the serial number is 0xFFFFFF, then we're dealing with - * an old PCI revision that comes without a sane number. In - * this case, we don't set card->id to avoid collisions - * when running with multiple cards. - */ - if (NULL == id[hdspm->dev] && hdspm->serial != 0xFFFFFF) { - sprintf(card->id, "HDSPMx%06x", hdspm->serial); - snd_card_set_id(card, card->id); - } - } - - snd_printdd("create alsa devices.\n"); - err = snd_hdspm_create_alsa_devices(card, hdspm); - if (err < 0) - return err; - - snd_hdspm_initialize_midi_flush(hdspm); - - return 0; -} - - -static int snd_hdspm_free(struct hdspm * hdspm) -{ - - if (hdspm->port) { - - /* stop th audio, and cancel all interrupts */ - hdspm->control_register &= - ~(HDSPM_Start | HDSPM_AudioInterruptEnable | - HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable | - HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable); - hdspm_write(hdspm, HDSPM_controlRegister, - hdspm->control_register); - } - - if (hdspm->irq >= 0) - free_irq(hdspm->irq, (void *) hdspm); - - kfree(hdspm->mixer); - - if (hdspm->iobase) - iounmap(hdspm->iobase); - - if (hdspm->port) - pci_release_regions(hdspm->pci); - - pci_disable_device(hdspm->pci); - return 0; -} - - -static void snd_hdspm_card_free(struct snd_card *card) -{ - struct hdspm *hdspm = card->private_data; - - if (hdspm) - snd_hdspm_free(hdspm); -} - - -static int __devinit snd_hdspm_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct hdspm *hdspm; - struct snd_card *card; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], - THIS_MODULE, sizeof(struct hdspm), &card); - if (err < 0) - return err; - - hdspm = card->private_data; - card->private_free = snd_hdspm_card_free; - hdspm->dev = dev; - hdspm->pci = pci; - - snd_card_set_dev(card, &pci->dev); - - err = snd_hdspm_create(card, hdspm); - if (err < 0) { - snd_card_free(card); - return err; - } - - if (hdspm->io_type != MADIface) { - sprintf(card->shortname, "%s_%x", - hdspm->card_name, - hdspm->serial); - sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d", - hdspm->card_name, - hdspm->serial, - hdspm->port, hdspm->irq); - } else { - sprintf(card->shortname, "%s", hdspm->card_name); - sprintf(card->longname, "%s at 0x%lx, irq %d", - hdspm->card_name, hdspm->port, hdspm->irq); - } - - err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - - dev++; - return 0; -} - -static void __devexit snd_hdspm_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_hdspm_ids, - .probe = snd_hdspm_probe, - .remove = __devexit_p(snd_hdspm_remove), -}; - - -static int __init alsa_card_hdspm_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_hdspm_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_hdspm_init) -module_exit(alsa_card_hdspm_exit) diff --git a/ANDROID_3.4.5/sound/pci/rme9652/rme9652.c b/ANDROID_3.4.5/sound/pci/rme9652/rme9652.c deleted file mode 100644 index b737d161..00000000 --- a/ANDROID_3.4.5/sound/pci/rme9652/rme9652.c +++ /dev/null @@ -1,2652 +0,0 @@ -/* - * ALSA driver for RME Digi9652 audio interfaces - * - * Copyright (c) 1999 IEM - Winfried Ritsch - * Copyright (c) 1999-2001 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 - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static bool precise_ptr[SNDRV_CARDS]; /* Enable precise pointer */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for RME Digi9652 (Hammerfall) soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable/disable specific RME96{52,36} soundcards."); -module_param_array(precise_ptr, bool, NULL, 0444); -MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably)."); -MODULE_AUTHOR("Paul Davis , Winfried Ritsch"); -MODULE_DESCRIPTION("RME Digi9652/Digi9636"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{RME,Hammerfall}," - "{RME,Hammerfall-Light}}"); - -/* The Hammerfall has two sets of 24 ADAT + 2 S/PDIF channels, one for - capture, one for playback. Both the ADAT and S/PDIF channels appear - to the host CPU in the same block of memory. There is no functional - difference between them in terms of access. - - The Hammerfall Light is identical to the Hammerfall, except that it - has 2 sets 18 channels (16 ADAT + 2 S/PDIF) for capture and playback. -*/ - -#define RME9652_NCHANNELS 26 -#define RME9636_NCHANNELS 18 - -/* Preferred sync source choices - used by "sync_pref" control switch */ - -#define RME9652_SYNC_FROM_SPDIF 0 -#define RME9652_SYNC_FROM_ADAT1 1 -#define RME9652_SYNC_FROM_ADAT2 2 -#define RME9652_SYNC_FROM_ADAT3 3 - -/* Possible sources of S/PDIF input */ - -#define RME9652_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */ -#define RME9652_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */ -#define RME9652_SPDIFIN_INTERN 2 /* internal (CDROM) */ - -/* ------------- Status-Register bits --------------------- */ - -#define RME9652_IRQ (1<<0) /* IRQ is High if not reset by irq_clear */ -#define RME9652_lock_2 (1<<1) /* ADAT 3-PLL: 1=locked, 0=unlocked */ -#define RME9652_lock_1 (1<<2) /* ADAT 2-PLL: 1=locked, 0=unlocked */ -#define RME9652_lock_0 (1<<3) /* ADAT 1-PLL: 1=locked, 0=unlocked */ -#define RME9652_fs48 (1<<4) /* sample rate is 0=44.1/88.2,1=48/96 Khz */ -#define RME9652_wsel_rd (1<<5) /* if Word-Clock is used and valid then 1 */ - /* bits 6-15 encode h/w buffer pointer position */ -#define RME9652_sync_2 (1<<16) /* if ADAT-IN 3 in sync to system clock */ -#define RME9652_sync_1 (1<<17) /* if ADAT-IN 2 in sync to system clock */ -#define RME9652_sync_0 (1<<18) /* if ADAT-IN 1 in sync to system clock */ -#define RME9652_DS_rd (1<<19) /* 1=Double Speed Mode, 0=Normal Speed */ -#define RME9652_tc_busy (1<<20) /* 1=time-code copy in progress (960ms) */ -#define RME9652_tc_out (1<<21) /* time-code out bit */ -#define RME9652_F_0 (1<<22) /* 000=64kHz, 100=88.2kHz, 011=96kHz */ -#define RME9652_F_1 (1<<23) /* 111=32kHz, 110=44.1kHz, 101=48kHz, */ -#define RME9652_F_2 (1<<24) /* external Crystal Chip if ERF=1 */ -#define RME9652_ERF (1<<25) /* Error-Flag of SDPIF Receiver (1=No Lock) */ -#define RME9652_buffer_id (1<<26) /* toggles by each interrupt on rec/play */ -#define RME9652_tc_valid (1<<27) /* 1 = a signal is detected on time-code input */ -#define RME9652_SPDIF_READ (1<<28) /* byte available from Rev 1.5+ S/PDIF interface */ - -#define RME9652_sync (RME9652_sync_0|RME9652_sync_1|RME9652_sync_2) -#define RME9652_lock (RME9652_lock_0|RME9652_lock_1|RME9652_lock_2) -#define RME9652_F (RME9652_F_0|RME9652_F_1|RME9652_F_2) -#define rme9652_decode_spdif_rate(x) ((x)>>22) - -/* Bit 6..15 : h/w buffer pointer */ - -#define RME9652_buf_pos 0x000FFC0 - -/* Bits 31,30,29 are bits 5,4,3 of h/w pointer position on later - Rev G EEPROMS and Rev 1.5 cards or later. -*/ - -#define RME9652_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME9652_buf_pos)) - -/* amount of io space we remap for register access. i'm not sure we - even need this much, but 1K is nice round number :) -*/ - -#define RME9652_IO_EXTENT 1024 - -#define RME9652_init_buffer 0 -#define RME9652_play_buffer 32 /* holds ptr to 26x64kBit host RAM */ -#define RME9652_rec_buffer 36 /* holds ptr to 26x64kBit host RAM */ -#define RME9652_control_register 64 -#define RME9652_irq_clear 96 -#define RME9652_time_code 100 /* useful if used with alesis adat */ -#define RME9652_thru_base 128 /* 132...228 Thru for 26 channels */ - -/* Read-only registers */ - -/* Writing to any of the register locations writes to the status - register. We'll use the first location as our point of access. -*/ - -#define RME9652_status_register 0 - -/* --------- Control-Register Bits ---------------- */ - - -#define RME9652_start_bit (1<<0) /* start record/play */ - /* bits 1-3 encode buffersize/latency */ -#define RME9652_Master (1<<4) /* Clock Mode Master=1,Slave/Auto=0 */ -#define RME9652_IE (1<<5) /* Interrupt Enable */ -#define RME9652_freq (1<<6) /* samplerate 0=44.1/88.2, 1=48/96 kHz */ -#define RME9652_freq1 (1<<7) /* if 0, 32kHz, else always 1 */ -#define RME9652_DS (1<<8) /* Doule Speed 0=44.1/48, 1=88.2/96 Khz */ -#define RME9652_PRO (1<<9) /* S/PDIF out: 0=consumer, 1=professional */ -#define RME9652_EMP (1<<10) /* Emphasis 0=None, 1=ON */ -#define RME9652_Dolby (1<<11) /* Non-audio bit 1=set, 0=unset */ -#define RME9652_opt_out (1<<12) /* Use 1st optical OUT as SPDIF: 1=yes,0=no */ -#define RME9652_wsel (1<<13) /* use Wordclock as sync (overwrites master) */ -#define RME9652_inp_0 (1<<14) /* SPDIF-IN: 00=optical (ADAT1), */ -#define RME9652_inp_1 (1<<15) /* 01=koaxial (Cinch), 10=Internal CDROM */ -#define RME9652_SyncPref_ADAT2 (1<<16) -#define RME9652_SyncPref_ADAT3 (1<<17) -#define RME9652_SPDIF_RESET (1<<18) /* Rev 1.5+: h/w S/PDIF receiver */ -#define RME9652_SPDIF_SELECT (1<<19) -#define RME9652_SPDIF_CLOCK (1<<20) -#define RME9652_SPDIF_WRITE (1<<21) -#define RME9652_ADAT1_INTERNAL (1<<22) /* Rev 1.5+: if set, internal CD connector carries ADAT */ - -/* buffersize = 512Bytes * 2^n, where n is made from Bit2 ... Bit0 */ - -#define RME9652_latency 0x0e -#define rme9652_encode_latency(x) (((x)&0x7)<<1) -#define rme9652_decode_latency(x) (((x)>>1)&0x7) -#define rme9652_running_double_speed(s) ((s)->control_register & RME9652_DS) -#define RME9652_inp (RME9652_inp_0|RME9652_inp_1) -#define rme9652_encode_spdif_in(x) (((x)&0x3)<<14) -#define rme9652_decode_spdif_in(x) (((x)>>14)&0x3) - -#define RME9652_SyncPref_Mask (RME9652_SyncPref_ADAT2|RME9652_SyncPref_ADAT3) -#define RME9652_SyncPref_ADAT1 0 -#define RME9652_SyncPref_SPDIF (RME9652_SyncPref_ADAT2|RME9652_SyncPref_ADAT3) - -/* the size of a substream (1 mono data stream) */ - -#define RME9652_CHANNEL_BUFFER_SAMPLES (16*1024) -#define RME9652_CHANNEL_BUFFER_BYTES (4*RME9652_CHANNEL_BUFFER_SAMPLES) - -/* the size of the area we need to allocate for DMA transfers. the - size is the same regardless of the number of channels - the - 9636 still uses the same memory area. - - Note that we allocate 1 more channel than is apparently needed - because the h/w seems to write 1 byte beyond the end of the last - page. Sigh. -*/ - -#define RME9652_DMA_AREA_BYTES ((RME9652_NCHANNELS+1) * RME9652_CHANNEL_BUFFER_BYTES) -#define RME9652_DMA_AREA_KILOBYTES (RME9652_DMA_AREA_BYTES/1024) - -struct snd_rme9652 { - int dev; - - spinlock_t lock; - int irq; - unsigned long port; - void __iomem *iobase; - - int precise_ptr; - - u32 control_register; /* cached value */ - u32 thru_bits; /* thru 1=on, 0=off channel 1=Bit1... channel 26= Bit26 */ - - u32 creg_spdif; - u32 creg_spdif_stream; - - char *card_name; /* hammerfall or hammerfall light names */ - - size_t hw_offsetmask; /* &-with status register to get real hw_offset */ - size_t prev_hw_offset; /* previous hw offset */ - size_t max_jitter; /* maximum jitter in frames for - hw pointer */ - size_t period_bytes; /* guess what this is */ - - unsigned char ds_channels; - unsigned char ss_channels; /* different for hammerfall/hammerfall-light */ - - struct snd_dma_buffer playback_dma_buf; - struct snd_dma_buffer capture_dma_buf; - - unsigned char *capture_buffer; /* suitably aligned address */ - unsigned char *playback_buffer; /* suitably aligned address */ - - pid_t capture_pid; - pid_t playback_pid; - - struct snd_pcm_substream *capture_substream; - struct snd_pcm_substream *playback_substream; - int running; - - int passthru; /* non-zero if doing pass-thru */ - int hw_rev; /* h/w rev * 10 (i.e. 1.5 has hw_rev = 15) */ - - int last_spdif_sample_rate; /* so that we can catch externally ... */ - int last_adat_sample_rate; /* ... induced rate changes */ - - char *channel_map; - - struct snd_card *card; - struct snd_pcm *pcm; - struct pci_dev *pci; - struct snd_kcontrol *spdif_ctl; - -}; - -/* These tables map the ALSA channels 1..N to the channels that we - need to use in order to find the relevant channel buffer. RME - refer to this kind of mapping as between "the ADAT channel and - the DMA channel." We index it using the logical audio channel, - and the value is the DMA channel (i.e. channel buffer number) - where the data for that channel can be read/written from/to. -*/ - -static char channel_map_9652_ss[26] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25 -}; - -static char channel_map_9636_ss[26] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - /* channels 16 and 17 are S/PDIF */ - 24, 25, - /* channels 18-25 don't exist */ - -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_9652_ds[26] = { - /* ADAT channels are remapped */ - 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, - /* channels 12 and 13 are S/PDIF */ - 24, 25, - /* others don't exist */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char channel_map_9636_ds[26] = { - /* ADAT channels are remapped */ - 1, 3, 5, 7, 9, 11, 13, 15, - /* channels 8 and 9 are S/PDIF */ - 24, 25 - /* others don't exist */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size) -{ - dmab->dev.type = SNDRV_DMA_TYPE_DEV; - dmab->dev.dev = snd_dma_pci_data(pci); - if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { - if (dmab->bytes >= size) - return 0; - } - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - size, dmab) < 0) - return -ENOMEM; - return 0; -} - -static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) -{ - if (dmab->area) { - dmab->dev.dev = NULL; /* make it anonymous */ - snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); - } -} - - -static DEFINE_PCI_DEVICE_TABLE(snd_rme9652_ids) = { - { - .vendor = 0x10ee, - .device = 0x3fc4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, /* RME Digi9652 */ - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, snd_rme9652_ids); - -static inline void rme9652_write(struct snd_rme9652 *rme9652, int reg, int val) -{ - writel(val, rme9652->iobase + reg); -} - -static inline unsigned int rme9652_read(struct snd_rme9652 *rme9652, int reg) -{ - return readl(rme9652->iobase + reg); -} - -static inline int snd_rme9652_use_is_exclusive(struct snd_rme9652 *rme9652) -{ - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&rme9652->lock, flags); - if ((rme9652->playback_pid != rme9652->capture_pid) && - (rme9652->playback_pid >= 0) && (rme9652->capture_pid >= 0)) { - ret = 0; - } - spin_unlock_irqrestore(&rme9652->lock, flags); - return ret; -} - -static inline int rme9652_adat_sample_rate(struct snd_rme9652 *rme9652) -{ - if (rme9652_running_double_speed(rme9652)) { - return (rme9652_read(rme9652, RME9652_status_register) & - RME9652_fs48) ? 96000 : 88200; - } else { - return (rme9652_read(rme9652, RME9652_status_register) & - RME9652_fs48) ? 48000 : 44100; - } -} - -static inline void rme9652_compute_period_size(struct snd_rme9652 *rme9652) -{ - unsigned int i; - - i = rme9652->control_register & RME9652_latency; - rme9652->period_bytes = 1 << ((rme9652_decode_latency(i) + 8)); - rme9652->hw_offsetmask = - (rme9652->period_bytes * 2 - 1) & RME9652_buf_pos; - rme9652->max_jitter = 80; -} - -static snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652) -{ - int status; - unsigned int offset, frag; - snd_pcm_uframes_t period_size = rme9652->period_bytes / 4; - snd_pcm_sframes_t delta; - - status = rme9652_read(rme9652, RME9652_status_register); - if (!rme9652->precise_ptr) - return (status & RME9652_buffer_id) ? period_size : 0; - offset = status & RME9652_buf_pos; - - /* The hardware may give a backward movement for up to 80 frames - Martin Kirst knows the details. - */ - - delta = rme9652->prev_hw_offset - offset; - delta &= 0xffff; - if (delta <= (snd_pcm_sframes_t)rme9652->max_jitter * 4) - offset = rme9652->prev_hw_offset; - else - rme9652->prev_hw_offset = offset; - offset &= rme9652->hw_offsetmask; - offset /= 4; - frag = status & RME9652_buffer_id; - - if (offset < period_size) { - if (offset > rme9652->max_jitter) { - if (frag) - printk(KERN_ERR "Unexpected hw_pointer position (bufid == 0): status: %x offset: %d\n", status, offset); - } else if (!frag) - return 0; - offset -= rme9652->max_jitter; - if ((int)offset < 0) - offset += period_size * 2; - } else { - if (offset > period_size + rme9652->max_jitter) { - if (!frag) - printk(KERN_ERR "Unexpected hw_pointer position (bufid == 1): status: %x offset: %d\n", status, offset); - } else if (frag) - return period_size; - offset -= rme9652->max_jitter; - } - - return offset; -} - -static inline void rme9652_reset_hw_pointer(struct snd_rme9652 *rme9652) -{ - int i; - - /* reset the FIFO pointer to zero. We do this by writing to 8 - registers, each of which is a 32bit wide register, and set - them all to zero. Note that s->iobase is a pointer to - int32, not pointer to char. - */ - - for (i = 0; i < 8; i++) { - rme9652_write(rme9652, i * 4, 0); - udelay(10); - } - rme9652->prev_hw_offset = 0; -} - -static inline void rme9652_start(struct snd_rme9652 *s) -{ - s->control_register |= (RME9652_IE | RME9652_start_bit); - rme9652_write(s, RME9652_control_register, s->control_register); -} - -static inline void rme9652_stop(struct snd_rme9652 *s) -{ - s->control_register &= ~(RME9652_start_bit | RME9652_IE); - rme9652_write(s, RME9652_control_register, s->control_register); -} - -static int rme9652_set_interrupt_interval(struct snd_rme9652 *s, - unsigned int frames) -{ - int restart = 0; - int n; - - spin_lock_irq(&s->lock); - - if ((restart = s->running)) { - rme9652_stop(s); - } - - frames >>= 7; - n = 0; - while (frames) { - n++; - frames >>= 1; - } - - s->control_register &= ~RME9652_latency; - s->control_register |= rme9652_encode_latency(n); - - rme9652_write(s, RME9652_control_register, s->control_register); - - rme9652_compute_period_size(s); - - if (restart) - rme9652_start(s); - - spin_unlock_irq(&s->lock); - - return 0; -} - -static int rme9652_set_rate(struct snd_rme9652 *rme9652, int rate) -{ - int restart; - int reject_if_open = 0; - int xrate; - - if (!snd_rme9652_use_is_exclusive (rme9652)) { - return -EBUSY; - } - - /* Changing from a "single speed" to a "double speed" rate is - not allowed if any substreams are open. This is because - such a change causes a shift in the location of - the DMA buffers and a reduction in the number of available - buffers. - - Note that a similar but essentially insoluble problem - exists for externally-driven rate changes. All we can do - is to flag rate changes in the read/write routines. - */ - - spin_lock_irq(&rme9652->lock); - xrate = rme9652_adat_sample_rate(rme9652); - - switch (rate) { - case 44100: - if (xrate > 48000) { - reject_if_open = 1; - } - rate = 0; - break; - case 48000: - if (xrate > 48000) { - reject_if_open = 1; - } - rate = RME9652_freq; - break; - case 88200: - if (xrate < 48000) { - reject_if_open = 1; - } - rate = RME9652_DS; - break; - case 96000: - if (xrate < 48000) { - reject_if_open = 1; - } - rate = RME9652_DS | RME9652_freq; - break; - default: - spin_unlock_irq(&rme9652->lock); - return -EINVAL; - } - - if (reject_if_open && (rme9652->capture_pid >= 0 || rme9652->playback_pid >= 0)) { - spin_unlock_irq(&rme9652->lock); - return -EBUSY; - } - - if ((restart = rme9652->running)) { - rme9652_stop(rme9652); - } - rme9652->control_register &= ~(RME9652_freq | RME9652_DS); - rme9652->control_register |= rate; - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - - if (restart) { - rme9652_start(rme9652); - } - - if (rate & RME9652_DS) { - if (rme9652->ss_channels == RME9652_NCHANNELS) { - rme9652->channel_map = channel_map_9652_ds; - } else { - rme9652->channel_map = channel_map_9636_ds; - } - } else { - if (rme9652->ss_channels == RME9652_NCHANNELS) { - rme9652->channel_map = channel_map_9652_ss; - } else { - rme9652->channel_map = channel_map_9636_ss; - } - } - - spin_unlock_irq(&rme9652->lock); - return 0; -} - -static void rme9652_set_thru(struct snd_rme9652 *rme9652, int channel, int enable) -{ - int i; - - rme9652->passthru = 0; - - if (channel < 0) { - - /* set thru for all channels */ - - if (enable) { - for (i = 0; i < RME9652_NCHANNELS; i++) { - rme9652->thru_bits |= (1 << i); - rme9652_write(rme9652, RME9652_thru_base + i * 4, 1); - } - } else { - for (i = 0; i < RME9652_NCHANNELS; i++) { - rme9652->thru_bits &= ~(1 << i); - rme9652_write(rme9652, RME9652_thru_base + i * 4, 0); - } - } - - } else { - int mapped_channel; - - mapped_channel = rme9652->channel_map[channel]; - - if (enable) { - rme9652->thru_bits |= (1 << mapped_channel); - } else { - rme9652->thru_bits &= ~(1 << mapped_channel); - } - - rme9652_write(rme9652, - RME9652_thru_base + mapped_channel * 4, - enable ? 1 : 0); - } -} - -static int rme9652_set_passthru(struct snd_rme9652 *rme9652, int onoff) -{ - if (onoff) { - rme9652_set_thru(rme9652, -1, 1); - - /* we don't want interrupts, so do a - custom version of rme9652_start(). - */ - - rme9652->control_register = - RME9652_inp_0 | - rme9652_encode_latency(7) | - RME9652_start_bit; - - rme9652_reset_hw_pointer(rme9652); - - rme9652_write(rme9652, RME9652_control_register, - rme9652->control_register); - rme9652->passthru = 1; - } else { - rme9652_set_thru(rme9652, -1, 0); - rme9652_stop(rme9652); - rme9652->passthru = 0; - } - - return 0; -} - -static void rme9652_spdif_set_bit (struct snd_rme9652 *rme9652, int mask, int onoff) -{ - if (onoff) - rme9652->control_register |= mask; - else - rme9652->control_register &= ~mask; - - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); -} - -static void rme9652_spdif_write_byte (struct snd_rme9652 *rme9652, const int val) -{ - long mask; - long i; - - for (i = 0, mask = 0x80; i < 8; i++, mask >>= 1) { - if (val & mask) - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_WRITE, 1); - else - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_WRITE, 0); - - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 1); - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 0); - } -} - -static int rme9652_spdif_read_byte (struct snd_rme9652 *rme9652) -{ - long mask; - long val; - long i; - - val = 0; - - for (i = 0, mask = 0x80; i < 8; i++, mask >>= 1) { - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 1); - if (rme9652_read (rme9652, RME9652_status_register) & RME9652_SPDIF_READ) - val |= mask; - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 0); - } - - return val; -} - -static void rme9652_write_spdif_codec (struct snd_rme9652 *rme9652, const int address, const int data) -{ - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1); - rme9652_spdif_write_byte (rme9652, 0x20); - rme9652_spdif_write_byte (rme9652, address); - rme9652_spdif_write_byte (rme9652, data); - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0); -} - - -static int rme9652_spdif_read_codec (struct snd_rme9652 *rme9652, const int address) -{ - int ret; - - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1); - rme9652_spdif_write_byte (rme9652, 0x20); - rme9652_spdif_write_byte (rme9652, address); - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0); - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1); - - rme9652_spdif_write_byte (rme9652, 0x21); - ret = rme9652_spdif_read_byte (rme9652); - rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0); - - return ret; -} - -static void rme9652_initialize_spdif_receiver (struct snd_rme9652 *rme9652) -{ - /* XXX what unsets this ? */ - - rme9652->control_register |= RME9652_SPDIF_RESET; - - rme9652_write_spdif_codec (rme9652, 4, 0x40); - rme9652_write_spdif_codec (rme9652, 17, 0x13); - rme9652_write_spdif_codec (rme9652, 6, 0x02); -} - -static inline int rme9652_spdif_sample_rate(struct snd_rme9652 *s) -{ - unsigned int rate_bits; - - if (rme9652_read(s, RME9652_status_register) & RME9652_ERF) { - return -1; /* error condition */ - } - - if (s->hw_rev == 15) { - - int x, y, ret; - - x = rme9652_spdif_read_codec (s, 30); - - if (x != 0) - y = 48000 * 64 / x; - else - y = 0; - - if (y > 30400 && y < 33600) ret = 32000; - else if (y > 41900 && y < 46000) ret = 44100; - else if (y > 46000 && y < 50400) ret = 48000; - else if (y > 60800 && y < 67200) ret = 64000; - else if (y > 83700 && y < 92000) ret = 88200; - else if (y > 92000 && y < 100000) ret = 96000; - else ret = 0; - return ret; - } - - rate_bits = rme9652_read(s, RME9652_status_register) & RME9652_F; - - switch (rme9652_decode_spdif_rate(rate_bits)) { - case 0x7: - return 32000; - break; - - case 0x6: - return 44100; - break; - - case 0x5: - return 48000; - break; - - case 0x4: - return 88200; - break; - - case 0x3: - return 96000; - break; - - case 0x0: - return 64000; - break; - - default: - snd_printk(KERN_ERR "%s: unknown S/PDIF input rate (bits = 0x%x)\n", - s->card_name, rate_bits); - return 0; - break; - } -} - -/*----------------------------------------------------------------------------- - Control Interface - ----------------------------------------------------------------------------*/ - -static u32 snd_rme9652_convert_from_aes(struct snd_aes_iec958 *aes) -{ - u32 val = 0; - val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME9652_PRO : 0; - val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? RME9652_Dolby : 0; - if (val & RME9652_PRO) - val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME9652_EMP : 0; - else - val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME9652_EMP : 0; - return val; -} - -static void snd_rme9652_convert_to_aes(struct snd_aes_iec958 *aes, u32 val) -{ - aes->status[0] = ((val & RME9652_PRO) ? IEC958_AES0_PROFESSIONAL : 0) | - ((val & RME9652_Dolby) ? IEC958_AES0_NONAUDIO : 0); - if (val & RME9652_PRO) - aes->status[0] |= (val & RME9652_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; - else - aes->status[0] |= (val & RME9652_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; -} - -static int snd_rme9652_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme9652_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif); - return 0; -} - -static int snd_rme9652_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change; - u32 val; - - val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme9652->lock); - change = val != rme9652->creg_spdif; - rme9652->creg_spdif = val; - spin_unlock_irq(&rme9652->lock); - return change; -} - -static int snd_rme9652_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme9652_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif_stream); - return 0; -} - -static int snd_rme9652_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change; - u32 val; - - val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958); - spin_lock_irq(&rme9652->lock); - change = val != rme9652->creg_spdif_stream; - rme9652->creg_spdif_stream = val; - rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP); - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= val); - spin_unlock_irq(&rme9652->lock); - return change; -} - -static int snd_rme9652_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_rme9652_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = kcontrol->private_value; - return 0; -} - -#define RME9652_ADAT1_IN(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_rme9652_info_adat1_in, \ - .get = snd_rme9652_get_adat1_in, \ - .put = snd_rme9652_put_adat1_in } - -static unsigned int rme9652_adat1_in(struct snd_rme9652 *rme9652) -{ - if (rme9652->control_register & RME9652_ADAT1_INTERNAL) - return 1; - return 0; -} - -static int rme9652_set_adat1_input(struct snd_rme9652 *rme9652, int internal) -{ - int restart = 0; - - if (internal) { - rme9652->control_register |= RME9652_ADAT1_INTERNAL; - } else { - rme9652->control_register &= ~RME9652_ADAT1_INTERNAL; - } - - /* XXX do we actually need to stop the card when we do this ? */ - - if ((restart = rme9652->running)) { - rme9652_stop(rme9652); - } - - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - - if (restart) { - rme9652_start(rme9652); - } - - return 0; -} - -static int snd_rme9652_info_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = {"ADAT1", "Internal"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_rme9652_get_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme9652->lock); - ucontrol->value.enumerated.item[0] = rme9652_adat1_in(rme9652); - spin_unlock_irq(&rme9652->lock); - return 0; -} - -static int snd_rme9652_put_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_rme9652_use_is_exclusive(rme9652)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0] % 2; - spin_lock_irq(&rme9652->lock); - change = val != rme9652_adat1_in(rme9652); - if (change) - rme9652_set_adat1_input(rme9652, val); - spin_unlock_irq(&rme9652->lock); - return change; -} - -#define RME9652_SPDIF_IN(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_rme9652_info_spdif_in, \ - .get = snd_rme9652_get_spdif_in, .put = snd_rme9652_put_spdif_in } - -static unsigned int rme9652_spdif_in(struct snd_rme9652 *rme9652) -{ - return rme9652_decode_spdif_in(rme9652->control_register & - RME9652_inp); -} - -static int rme9652_set_spdif_input(struct snd_rme9652 *rme9652, int in) -{ - int restart = 0; - - rme9652->control_register &= ~RME9652_inp; - rme9652->control_register |= rme9652_encode_spdif_in(in); - - if ((restart = rme9652->running)) { - rme9652_stop(rme9652); - } - - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - - if (restart) { - rme9652_start(rme9652); - } - - return 0; -} - -static int snd_rme9652_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = {"ADAT1", "Coaxial", "Internal"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_rme9652_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme9652->lock); - ucontrol->value.enumerated.item[0] = rme9652_spdif_in(rme9652); - spin_unlock_irq(&rme9652->lock); - return 0; -} - -static int snd_rme9652_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_rme9652_use_is_exclusive(rme9652)) - return -EBUSY; - val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&rme9652->lock); - change = val != rme9652_spdif_in(rme9652); - if (change) - rme9652_set_spdif_input(rme9652, val); - spin_unlock_irq(&rme9652->lock); - return change; -} - -#define RME9652_SPDIF_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_rme9652_info_spdif_out, \ - .get = snd_rme9652_get_spdif_out, .put = snd_rme9652_put_spdif_out } - -static int rme9652_spdif_out(struct snd_rme9652 *rme9652) -{ - return (rme9652->control_register & RME9652_opt_out) ? 1 : 0; -} - -static int rme9652_set_spdif_output(struct snd_rme9652 *rme9652, int out) -{ - int restart = 0; - - if (out) { - rme9652->control_register |= RME9652_opt_out; - } else { - rme9652->control_register &= ~RME9652_opt_out; - } - - if ((restart = rme9652->running)) { - rme9652_stop(rme9652); - } - - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - - if (restart) { - rme9652_start(rme9652); - } - - return 0; -} - -#define snd_rme9652_info_spdif_out snd_ctl_boolean_mono_info - -static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme9652->lock); - ucontrol->value.integer.value[0] = rme9652_spdif_out(rme9652); - spin_unlock_irq(&rme9652->lock); - return 0; -} - -static int snd_rme9652_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - if (!snd_rme9652_use_is_exclusive(rme9652)) - return -EBUSY; - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&rme9652->lock); - change = (int)val != rme9652_spdif_out(rme9652); - rme9652_set_spdif_output(rme9652, val); - spin_unlock_irq(&rme9652->lock); - return change; -} - -#define RME9652_SYNC_MODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_rme9652_info_sync_mode, \ - .get = snd_rme9652_get_sync_mode, .put = snd_rme9652_put_sync_mode } - -static int rme9652_sync_mode(struct snd_rme9652 *rme9652) -{ - if (rme9652->control_register & RME9652_wsel) { - return 2; - } else if (rme9652->control_register & RME9652_Master) { - return 1; - } else { - return 0; - } -} - -static int rme9652_set_sync_mode(struct snd_rme9652 *rme9652, int mode) -{ - int restart = 0; - - switch (mode) { - case 0: - rme9652->control_register &= - ~(RME9652_Master | RME9652_wsel); - break; - case 1: - rme9652->control_register = - (rme9652->control_register & ~RME9652_wsel) | RME9652_Master; - break; - case 2: - rme9652->control_register |= - (RME9652_Master | RME9652_wsel); - break; - } - - if ((restart = rme9652->running)) { - rme9652_stop(rme9652); - } - - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - - if (restart) { - rme9652_start(rme9652); - } - - return 0; -} - -static int snd_rme9652_info_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = {"AutoSync", "Master", "Word Clock"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_rme9652_get_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme9652->lock); - ucontrol->value.enumerated.item[0] = rme9652_sync_mode(rme9652); - spin_unlock_irq(&rme9652->lock); - return 0; -} - -static int snd_rme9652_put_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - - val = ucontrol->value.enumerated.item[0] % 3; - spin_lock_irq(&rme9652->lock); - change = (int)val != rme9652_sync_mode(rme9652); - rme9652_set_sync_mode(rme9652, val); - spin_unlock_irq(&rme9652->lock); - return change; -} - -#define RME9652_SYNC_PREF(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_rme9652_info_sync_pref, \ - .get = snd_rme9652_get_sync_pref, .put = snd_rme9652_put_sync_pref } - -static int rme9652_sync_pref(struct snd_rme9652 *rme9652) -{ - switch (rme9652->control_register & RME9652_SyncPref_Mask) { - case RME9652_SyncPref_ADAT1: - return RME9652_SYNC_FROM_ADAT1; - case RME9652_SyncPref_ADAT2: - return RME9652_SYNC_FROM_ADAT2; - case RME9652_SyncPref_ADAT3: - return RME9652_SYNC_FROM_ADAT3; - case RME9652_SyncPref_SPDIF: - return RME9652_SYNC_FROM_SPDIF; - } - /* Not reachable */ - return 0; -} - -static int rme9652_set_sync_pref(struct snd_rme9652 *rme9652, int pref) -{ - int restart; - - rme9652->control_register &= ~RME9652_SyncPref_Mask; - switch (pref) { - case RME9652_SYNC_FROM_ADAT1: - rme9652->control_register |= RME9652_SyncPref_ADAT1; - break; - case RME9652_SYNC_FROM_ADAT2: - rme9652->control_register |= RME9652_SyncPref_ADAT2; - break; - case RME9652_SYNC_FROM_ADAT3: - rme9652->control_register |= RME9652_SyncPref_ADAT3; - break; - case RME9652_SYNC_FROM_SPDIF: - rme9652->control_register |= RME9652_SyncPref_SPDIF; - break; - } - - if ((restart = rme9652->running)) { - rme9652_stop(rme9652); - } - - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - - if (restart) { - rme9652_start(rme9652); - } - - return 0; -} - -static int snd_rme9652_info_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = {"IEC958 In", "ADAT1 In", "ADAT2 In", "ADAT3 In"}; - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_rme9652_get_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme9652->lock); - ucontrol->value.enumerated.item[0] = rme9652_sync_pref(rme9652); - spin_unlock_irq(&rme9652->lock); - return 0; -} - -static int snd_rme9652_put_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change, max; - unsigned int val; - - if (!snd_rme9652_use_is_exclusive(rme9652)) - return -EBUSY; - max = rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3; - val = ucontrol->value.enumerated.item[0] % max; - spin_lock_irq(&rme9652->lock); - change = (int)val != rme9652_sync_pref(rme9652); - rme9652_set_sync_pref(rme9652, val); - spin_unlock_irq(&rme9652->lock); - return change; -} - -static int snd_rme9652_info_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = rme9652->ss_channels; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_rme9652_get_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - unsigned int k; - u32 thru_bits = rme9652->thru_bits; - - for (k = 0; k < rme9652->ss_channels; ++k) { - ucontrol->value.integer.value[k] = !!(thru_bits & (1 << k)); - } - return 0; -} - -static int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change; - unsigned int chn; - u32 thru_bits = 0; - - if (!snd_rme9652_use_is_exclusive(rme9652)) - return -EBUSY; - - for (chn = 0; chn < rme9652->ss_channels; ++chn) { - if (ucontrol->value.integer.value[chn]) - thru_bits |= 1 << chn; - } - - spin_lock_irq(&rme9652->lock); - change = thru_bits ^ rme9652->thru_bits; - if (change) { - for (chn = 0; chn < rme9652->ss_channels; ++chn) { - if (!(change & (1 << chn))) - continue; - rme9652_set_thru(rme9652,chn,thru_bits&(1<lock); - return !!change; -} - -#define RME9652_PASSTHRU(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_rme9652_info_passthru, \ - .put = snd_rme9652_put_passthru, \ - .get = snd_rme9652_get_passthru } - -#define snd_rme9652_info_passthru snd_ctl_boolean_mono_info - -static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme9652->lock); - ucontrol->value.integer.value[0] = rme9652->passthru; - spin_unlock_irq(&rme9652->lock); - return 0; -} - -static int snd_rme9652_put_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - int change; - unsigned int val; - int err = 0; - - if (!snd_rme9652_use_is_exclusive(rme9652)) - return -EBUSY; - - val = ucontrol->value.integer.value[0] & 1; - spin_lock_irq(&rme9652->lock); - change = (ucontrol->value.integer.value[0] != rme9652->passthru); - if (change) - err = rme9652_set_passthru(rme9652, val); - spin_unlock_irq(&rme9652->lock); - return err ? err : change; -} - -/* Read-only switches */ - -#define RME9652_SPDIF_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_rme9652_info_spdif_rate, \ - .get = snd_rme9652_get_spdif_rate } - -static int snd_rme9652_info_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 96000; - return 0; -} - -static int snd_rme9652_get_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&rme9652->lock); - ucontrol->value.integer.value[0] = rme9652_spdif_sample_rate(rme9652); - spin_unlock_irq(&rme9652->lock); - return 0; -} - -#define RME9652_ADAT_SYNC(xname, xindex, xidx) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_rme9652_info_adat_sync, \ - .get = snd_rme9652_get_adat_sync, .private_value = xidx } - -static int snd_rme9652_info_adat_sync(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = {"No Lock", "Lock", "No Lock Sync", "Lock Sync"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_rme9652_get_adat_sync(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - unsigned int mask1, mask2, val; - - switch (kcontrol->private_value) { - case 0: mask1 = RME9652_lock_0; mask2 = RME9652_sync_0; break; - case 1: mask1 = RME9652_lock_1; mask2 = RME9652_sync_1; break; - case 2: mask1 = RME9652_lock_2; mask2 = RME9652_sync_2; break; - default: return -EINVAL; - } - val = rme9652_read(rme9652, RME9652_status_register); - ucontrol->value.enumerated.item[0] = (val & mask1) ? 1 : 0; - ucontrol->value.enumerated.item[0] |= (val & mask2) ? 2 : 0; - return 0; -} - -#define RME9652_TC_VALID(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_rme9652_info_tc_valid, \ - .get = snd_rme9652_get_tc_valid } - -#define snd_rme9652_info_tc_valid snd_ctl_boolean_mono_info - -static int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = - (rme9652_read(rme9652, RME9652_status_register) & RME9652_tc_valid) ? 1 : 0; - return 0; -} - -#ifdef ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE - -/* FIXME: this routine needs a port to the new control API --jk */ - -static int snd_rme9652_get_tc_value(void *private_data, - snd_kswitch_t *kswitch, - snd_switch_t *uswitch) -{ - struct snd_rme9652 *s = (struct snd_rme9652 *) private_data; - u32 value; - int i; - - uswitch->type = SNDRV_SW_TYPE_DWORD; - - if ((rme9652_read(s, RME9652_status_register) & - RME9652_tc_valid) == 0) { - uswitch->value.data32[0] = 0; - return 0; - } - - /* timecode request */ - - rme9652_write(s, RME9652_time_code, 0); - - /* XXX bug alert: loop-based timing !!!! */ - - for (i = 0; i < 50; i++) { - if (!(rme9652_read(s, i * 4) & RME9652_tc_busy)) - break; - } - - if (!(rme9652_read(s, i * 4) & RME9652_tc_busy)) { - return -EIO; - } - - value = 0; - - for (i = 0; i < 32; i++) { - value >>= 1; - - if (rme9652_read(s, i * 4) & RME9652_tc_out) - value |= 0x80000000; - } - - if (value > 2 * 60 * 48000) { - value -= 2 * 60 * 48000; - } else { - value = 0; - } - - uswitch->value.data32[0] = value; - - return 0; -} - -#endif /* ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE */ - -static struct snd_kcontrol_new snd_rme9652_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_rme9652_control_spdif_info, - .get = snd_rme9652_control_spdif_get, - .put = snd_rme9652_control_spdif_put, -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_rme9652_control_spdif_stream_info, - .get = snd_rme9652_control_spdif_stream_get, - .put = snd_rme9652_control_spdif_stream_put, -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), - .info = snd_rme9652_control_spdif_mask_info, - .get = snd_rme9652_control_spdif_mask_get, - .private_value = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_CON_EMPHASIS, -}, -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), - .info = snd_rme9652_control_spdif_mask_info, - .get = snd_rme9652_control_spdif_mask_get, - .private_value = IEC958_AES0_NONAUDIO | - IEC958_AES0_PROFESSIONAL | - IEC958_AES0_PRO_EMPHASIS, -}, -RME9652_SPDIF_IN("IEC958 Input Connector", 0), -RME9652_SPDIF_OUT("IEC958 Output also on ADAT1", 0), -RME9652_SYNC_MODE("Sync Mode", 0), -RME9652_SYNC_PREF("Preferred Sync Source", 0), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channels Thru", - .index = 0, - .info = snd_rme9652_info_thru, - .get = snd_rme9652_get_thru, - .put = snd_rme9652_put_thru, -}, -RME9652_SPDIF_RATE("IEC958 Sample Rate", 0), -RME9652_ADAT_SYNC("ADAT1 Sync Check", 0, 0), -RME9652_ADAT_SYNC("ADAT2 Sync Check", 0, 1), -RME9652_TC_VALID("Timecode Valid", 0), -RME9652_PASSTHRU("Passthru", 0) -}; - -static struct snd_kcontrol_new snd_rme9652_adat3_check = -RME9652_ADAT_SYNC("ADAT3 Sync Check", 0, 2); - -static struct snd_kcontrol_new snd_rme9652_adat1_input = -RME9652_ADAT1_IN("ADAT1 Input Source", 0); - -static int snd_rme9652_create_controls(struct snd_card *card, struct snd_rme9652 *rme9652) -{ - unsigned int idx; - int err; - struct snd_kcontrol *kctl; - - for (idx = 0; idx < ARRAY_SIZE(snd_rme9652_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_controls[idx], rme9652))) < 0) - return err; - if (idx == 1) /* IEC958 (S/PDIF) Stream */ - rme9652->spdif_ctl = kctl; - } - - if (rme9652->ss_channels == RME9652_NCHANNELS) - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_adat3_check, rme9652))) < 0) - return err; - - if (rme9652->hw_rev >= 15) - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_adat1_input, rme9652))) < 0) - return err; - - return 0; -} - -/*------------------------------------------------------------ - /proc interface - ------------------------------------------------------------*/ - -static void -snd_rme9652_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) entry->private_data; - u32 thru_bits = rme9652->thru_bits; - int show_auto_sync_source = 0; - int i; - unsigned int status; - int x; - - status = rme9652_read(rme9652, RME9652_status_register); - - snd_iprintf(buffer, "%s (Card #%d)\n", rme9652->card_name, rme9652->card->number + 1); - snd_iprintf(buffer, "Buffers: capture %p playback %p\n", - rme9652->capture_buffer, rme9652->playback_buffer); - snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", - rme9652->irq, rme9652->port, (unsigned long)rme9652->iobase); - snd_iprintf(buffer, "Control register: %x\n", rme9652->control_register); - - snd_iprintf(buffer, "\n"); - - x = 1 << (6 + rme9652_decode_latency(rme9652->control_register & - RME9652_latency)); - - snd_iprintf(buffer, "Latency: %d samples (2 periods of %lu bytes)\n", - x, (unsigned long) rme9652->period_bytes); - snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", - rme9652_hw_pointer(rme9652)); - snd_iprintf(buffer, "Passthru: %s\n", - rme9652->passthru ? "yes" : "no"); - - if ((rme9652->control_register & (RME9652_Master | RME9652_wsel)) == 0) { - snd_iprintf(buffer, "Clock mode: autosync\n"); - show_auto_sync_source = 1; - } else if (rme9652->control_register & RME9652_wsel) { - if (status & RME9652_wsel_rd) { - snd_iprintf(buffer, "Clock mode: word clock\n"); - } else { - snd_iprintf(buffer, "Clock mode: word clock (no signal)\n"); - } - } else { - snd_iprintf(buffer, "Clock mode: master\n"); - } - - if (show_auto_sync_source) { - switch (rme9652->control_register & RME9652_SyncPref_Mask) { - case RME9652_SyncPref_ADAT1: - snd_iprintf(buffer, "Pref. sync source: ADAT1\n"); - break; - case RME9652_SyncPref_ADAT2: - snd_iprintf(buffer, "Pref. sync source: ADAT2\n"); - break; - case RME9652_SyncPref_ADAT3: - snd_iprintf(buffer, "Pref. sync source: ADAT3\n"); - break; - case RME9652_SyncPref_SPDIF: - snd_iprintf(buffer, "Pref. sync source: IEC958\n"); - break; - default: - snd_iprintf(buffer, "Pref. sync source: ???\n"); - } - } - - if (rme9652->hw_rev >= 15) - snd_iprintf(buffer, "\nADAT1 Input source: %s\n", - (rme9652->control_register & RME9652_ADAT1_INTERNAL) ? - "Internal" : "ADAT1 optical"); - - snd_iprintf(buffer, "\n"); - - switch (rme9652_decode_spdif_in(rme9652->control_register & - RME9652_inp)) { - case RME9652_SPDIFIN_OPTICAL: - snd_iprintf(buffer, "IEC958 input: ADAT1\n"); - break; - case RME9652_SPDIFIN_COAXIAL: - snd_iprintf(buffer, "IEC958 input: Coaxial\n"); - break; - case RME9652_SPDIFIN_INTERN: - snd_iprintf(buffer, "IEC958 input: Internal\n"); - break; - default: - snd_iprintf(buffer, "IEC958 input: ???\n"); - break; - } - - if (rme9652->control_register & RME9652_opt_out) { - snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); - } else { - snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); - } - - if (rme9652->control_register & RME9652_PRO) { - snd_iprintf(buffer, "IEC958 quality: Professional\n"); - } else { - snd_iprintf(buffer, "IEC958 quality: Consumer\n"); - } - - if (rme9652->control_register & RME9652_EMP) { - snd_iprintf(buffer, "IEC958 emphasis: on\n"); - } else { - snd_iprintf(buffer, "IEC958 emphasis: off\n"); - } - - if (rme9652->control_register & RME9652_Dolby) { - snd_iprintf(buffer, "IEC958 Dolby: on\n"); - } else { - snd_iprintf(buffer, "IEC958 Dolby: off\n"); - } - - i = rme9652_spdif_sample_rate(rme9652); - - if (i < 0) { - snd_iprintf(buffer, - "IEC958 sample rate: error flag set\n"); - } else if (i == 0) { - snd_iprintf(buffer, "IEC958 sample rate: undetermined\n"); - } else { - snd_iprintf(buffer, "IEC958 sample rate: %d\n", i); - } - - snd_iprintf(buffer, "\n"); - - snd_iprintf(buffer, "ADAT Sample rate: %dHz\n", - rme9652_adat_sample_rate(rme9652)); - - /* Sync Check */ - - x = status & RME9652_sync_0; - if (status & RME9652_lock_0) { - snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock"); - } else { - snd_iprintf(buffer, "ADAT1: No Lock\n"); - } - - x = status & RME9652_sync_1; - if (status & RME9652_lock_1) { - snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock"); - } else { - snd_iprintf(buffer, "ADAT2: No Lock\n"); - } - - x = status & RME9652_sync_2; - if (status & RME9652_lock_2) { - snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock"); - } else { - snd_iprintf(buffer, "ADAT3: No Lock\n"); - } - - snd_iprintf(buffer, "\n"); - - snd_iprintf(buffer, "Timecode signal: %s\n", - (status & RME9652_tc_valid) ? "yes" : "no"); - - /* thru modes */ - - snd_iprintf(buffer, "Punch Status:\n\n"); - - for (i = 0; i < rme9652->ss_channels; i++) { - if (thru_bits & (1 << i)) { - snd_iprintf(buffer, "%2d: on ", i + 1); - } else { - snd_iprintf(buffer, "%2d: off ", i + 1); - } - - if (((i + 1) % 8) == 0) { - snd_iprintf(buffer, "\n"); - } - } - - snd_iprintf(buffer, "\n"); -} - -static void __devinit snd_rme9652_proc_init(struct snd_rme9652 *rme9652) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(rme9652->card, "rme9652", &entry)) - snd_info_set_text_ops(entry, rme9652, snd_rme9652_proc_read); -} - -static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652) -{ - snd_hammerfall_free_buffer(&rme9652->capture_dma_buf, rme9652->pci); - snd_hammerfall_free_buffer(&rme9652->playback_dma_buf, rme9652->pci); -} - -static int snd_rme9652_free(struct snd_rme9652 *rme9652) -{ - if (rme9652->irq >= 0) - rme9652_stop(rme9652); - snd_rme9652_free_buffers(rme9652); - - if (rme9652->irq >= 0) - free_irq(rme9652->irq, (void *)rme9652); - if (rme9652->iobase) - iounmap(rme9652->iobase); - if (rme9652->port) - pci_release_regions(rme9652->pci); - - pci_disable_device(rme9652->pci); - return 0; -} - -static int __devinit snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652) -{ - unsigned long pb_bus, cb_bus; - - if (snd_hammerfall_get_buffer(rme9652->pci, &rme9652->capture_dma_buf, RME9652_DMA_AREA_BYTES) < 0 || - snd_hammerfall_get_buffer(rme9652->pci, &rme9652->playback_dma_buf, RME9652_DMA_AREA_BYTES) < 0) { - if (rme9652->capture_dma_buf.area) - snd_dma_free_pages(&rme9652->capture_dma_buf); - printk(KERN_ERR "%s: no buffers available\n", rme9652->card_name); - return -ENOMEM; - } - - /* Align to bus-space 64K boundary */ - - cb_bus = ALIGN(rme9652->capture_dma_buf.addr, 0x10000ul); - pb_bus = ALIGN(rme9652->playback_dma_buf.addr, 0x10000ul); - - /* Tell the card where it is */ - - rme9652_write(rme9652, RME9652_rec_buffer, cb_bus); - rme9652_write(rme9652, RME9652_play_buffer, pb_bus); - - rme9652->capture_buffer = rme9652->capture_dma_buf.area + (cb_bus - rme9652->capture_dma_buf.addr); - rme9652->playback_buffer = rme9652->playback_dma_buf.area + (pb_bus - rme9652->playback_dma_buf.addr); - - return 0; -} - -static void snd_rme9652_set_defaults(struct snd_rme9652 *rme9652) -{ - unsigned int k; - - /* ASSUMPTION: rme9652->lock is either held, or - there is no need to hold it (e.g. during module - initialization). - */ - - /* set defaults: - - SPDIF Input via Coax - autosync clock mode - maximum latency (7 = 8192 samples, 64Kbyte buffer, - which implies 2 4096 sample, 32Kbyte periods). - - if rev 1.5, initialize the S/PDIF receiver. - - */ - - rme9652->control_register = - RME9652_inp_0 | rme9652_encode_latency(7); - - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - - rme9652_reset_hw_pointer(rme9652); - rme9652_compute_period_size(rme9652); - - /* default: thru off for all channels */ - - for (k = 0; k < RME9652_NCHANNELS; ++k) - rme9652_write(rme9652, RME9652_thru_base + k * 4, 0); - - rme9652->thru_bits = 0; - rme9652->passthru = 0; - - /* set a default rate so that the channel map is set up */ - - rme9652_set_rate(rme9652, 48000); -} - -static irqreturn_t snd_rme9652_interrupt(int irq, void *dev_id) -{ - struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) dev_id; - - if (!(rme9652_read(rme9652, RME9652_status_register) & RME9652_IRQ)) { - return IRQ_NONE; - } - - rme9652_write(rme9652, RME9652_irq_clear, 0); - - if (rme9652->capture_substream) { - snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); - } - - if (rme9652->playback_substream) { - snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); - } - return IRQ_HANDLED; -} - -static snd_pcm_uframes_t snd_rme9652_hw_pointer(struct snd_pcm_substream *substream) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - return rme9652_hw_pointer(rme9652); -} - -static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, - int stream, - int channel) - -{ - int mapped_channel; - - if (snd_BUG_ON(channel < 0 || channel >= RME9652_NCHANNELS)) - return NULL; - - if ((mapped_channel = rme9652->channel_map[channel]) < 0) { - return NULL; - } - - if (stream == SNDRV_PCM_STREAM_CAPTURE) { - return rme9652->capture_buffer + - (mapped_channel * RME9652_CHANNEL_BUFFER_BYTES); - } else { - return rme9652->playback_buffer + - (mapped_channel * RME9652_CHANNEL_BUFFER_BYTES); - } -} - -static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; - - if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4)) - return -EINVAL; - - channel_buf = rme9652_channel_buffer_location (rme9652, - substream->pstr->stream, - channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - if (copy_from_user(channel_buf + pos * 4, src, count * 4)) - return -EFAULT; - return count; -} - -static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; - - if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4)) - return -EINVAL; - - channel_buf = rme9652_channel_buffer_location (rme9652, - substream->pstr->stream, - channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) - return -EFAULT; - return count; -} - -static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, snd_pcm_uframes_t count) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - char *channel_buf; - - channel_buf = rme9652_channel_buffer_location (rme9652, - substream->pstr->stream, - channel); - if (snd_BUG_ON(!channel_buf)) - return -EIO; - memset(channel_buf + pos * 4, 0, count * 4); - return count; -} - -static int snd_rme9652_reset(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *other; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - other = rme9652->capture_substream; - else - other = rme9652->playback_substream; - if (rme9652->running) - runtime->status->hw_ptr = rme9652_hw_pointer(rme9652); - else - runtime->status->hw_ptr = 0; - if (other) { - struct snd_pcm_substream *s; - struct snd_pcm_runtime *oruntime = other->runtime; - snd_pcm_group_for_each_entry(s, substream) { - if (s == other) { - oruntime->status->hw_ptr = runtime->status->hw_ptr; - break; - } - } - } - return 0; -} - -static int snd_rme9652_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - int err; - pid_t this_pid; - pid_t other_pid; - - spin_lock_irq(&rme9652->lock); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { - rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP); - rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= rme9652->creg_spdif_stream); - this_pid = rme9652->playback_pid; - other_pid = rme9652->capture_pid; - } else { - this_pid = rme9652->capture_pid; - other_pid = rme9652->playback_pid; - } - - if ((other_pid > 0) && (this_pid != other_pid)) { - - /* The other stream is open, and not by the same - task as this one. Make sure that the parameters - that matter are the same. - */ - - if ((int)params_rate(params) != - rme9652_adat_sample_rate(rme9652)) { - spin_unlock_irq(&rme9652->lock); - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); - return -EBUSY; - } - - if (params_period_size(params) != rme9652->period_bytes / 4) { - spin_unlock_irq(&rme9652->lock); - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return -EBUSY; - } - - /* We're fine. */ - - spin_unlock_irq(&rme9652->lock); - return 0; - - } else { - spin_unlock_irq(&rme9652->lock); - } - - /* how to make sure that the rate matches an externally-set one ? - */ - - if ((err = rme9652_set_rate(rme9652, params_rate(params))) < 0) { - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); - return err; - } - - if ((err = rme9652_set_interrupt_interval(rme9652, params_period_size(params))) < 0) { - _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); - return err; - } - - return 0; -} - -static int snd_rme9652_channel_info(struct snd_pcm_substream *substream, - struct snd_pcm_channel_info *info) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - int chn; - - if (snd_BUG_ON(info->channel >= RME9652_NCHANNELS)) - return -EINVAL; - - if ((chn = rme9652->channel_map[info->channel]) < 0) { - return -EINVAL; - } - - info->offset = chn * RME9652_CHANNEL_BUFFER_BYTES; - info->first = 0; - info->step = 32; - return 0; -} - -static int snd_rme9652_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - switch (cmd) { - case SNDRV_PCM_IOCTL1_RESET: - { - return snd_rme9652_reset(substream); - } - case SNDRV_PCM_IOCTL1_CHANNEL_INFO: - { - struct snd_pcm_channel_info *info = arg; - return snd_rme9652_channel_info(substream, info); - } - default: - break; - } - - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static void rme9652_silence_playback(struct snd_rme9652 *rme9652) -{ - memset(rme9652->playback_buffer, 0, RME9652_DMA_AREA_BYTES); -} - -static int snd_rme9652_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *other; - int running; - spin_lock(&rme9652->lock); - running = rme9652->running; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - running |= 1 << substream->stream; - break; - case SNDRV_PCM_TRIGGER_STOP: - running &= ~(1 << substream->stream); - break; - default: - snd_BUG(); - spin_unlock(&rme9652->lock); - return -EINVAL; - } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - other = rme9652->capture_substream; - else - other = rme9652->playback_substream; - - if (other) { - struct snd_pcm_substream *s; - snd_pcm_group_for_each_entry(s, substream) { - if (s == other) { - snd_pcm_trigger_done(s, substream); - if (cmd == SNDRV_PCM_TRIGGER_START) - running |= 1 << s->stream; - else - running &= ~(1 << s->stream); - goto _ok; - } - } - if (cmd == SNDRV_PCM_TRIGGER_START) { - if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) && - substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rme9652_silence_playback(rme9652); - } else { - if (running && - substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - rme9652_silence_playback(rme9652); - } - } else { - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - rme9652_silence_playback(rme9652); - } - _ok: - snd_pcm_trigger_done(substream, substream); - if (!rme9652->running && running) - rme9652_start(rme9652); - else if (rme9652->running && !running) - rme9652_stop(rme9652); - rme9652->running = running; - spin_unlock(&rme9652->lock); - - return 0; -} - -static int snd_rme9652_prepare(struct snd_pcm_substream *substream) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - unsigned long flags; - int result = 0; - - spin_lock_irqsave(&rme9652->lock, flags); - if (!rme9652->running) - rme9652_reset_hw_pointer(rme9652); - spin_unlock_irqrestore(&rme9652->lock, flags); - return result; -} - -static struct snd_pcm_hardware snd_rme9652_playback_subinfo = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_DOUBLE), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000), - .rate_min = 44100, - .rate_max = 96000, - .channels_min = 10, - .channels_max = 26, - .buffer_bytes_max = RME9652_CHANNEL_BUFFER_BYTES * 26, - .period_bytes_min = (64 * 4) * 10, - .period_bytes_max = (8192 * 4) * 26, - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_rme9652_capture_subinfo = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_SYNC_START), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000), - .rate_min = 44100, - .rate_max = 96000, - .channels_min = 10, - .channels_max = 26, - .buffer_bytes_max = RME9652_CHANNEL_BUFFER_BYTES *26, - .period_bytes_min = (64 * 4) * 10, - .period_bytes_max = (8192 * 4) * 26, - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; - -static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { - .count = ARRAY_SIZE(period_sizes), - .list = period_sizes, - .mask = 0 -}; - -static int snd_rme9652_hw_rule_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_rme9652 *rme9652 = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - unsigned int list[2] = { rme9652->ds_channels, rme9652->ss_channels }; - return snd_interval_list(c, 2, list, 0); -} - -static int snd_rme9652_hw_rule_channels_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_rme9652 *rme9652 = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (r->min > 48000) { - struct snd_interval t = { - .min = rme9652->ds_channels, - .max = rme9652->ds_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } else if (r->max < 88200) { - struct snd_interval t = { - .min = rme9652->ss_channels, - .max = rme9652->ss_channels, - .integer = 1, - }; - return snd_interval_refine(c, &t); - } - return 0; -} - -static int snd_rme9652_hw_rule_rate_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_rme9652 *rme9652 = rule->private; - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (c->min >= rme9652->ss_channels) { - struct snd_interval t = { - .min = 44100, - .max = 48000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } else if (c->max <= rme9652->ds_channels) { - struct snd_interval t = { - .min = 88200, - .max = 96000, - .integer = 1, - }; - return snd_interval_refine(r, &t); - } - return 0; -} - -static int snd_rme9652_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irq(&rme9652->lock); - - snd_pcm_set_sync(substream); - - runtime->hw = snd_rme9652_playback_subinfo; - runtime->dma_area = rme9652->playback_buffer; - runtime->dma_bytes = RME9652_DMA_AREA_BYTES; - - if (rme9652->capture_substream == NULL) { - rme9652_stop(rme9652); - rme9652_set_thru(rme9652, -1, 0); - } - - rme9652->playback_pid = current->pid; - rme9652->playback_substream = substream; - - spin_unlock_irq(&rme9652->lock); - - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_rme9652_hw_rule_channels, rme9652, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_rme9652_hw_rule_channels_rate, rme9652, - SNDRV_PCM_HW_PARAM_RATE, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_rme9652_hw_rule_rate_channels, rme9652, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - - rme9652->creg_spdif_stream = rme9652->creg_spdif; - rme9652->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &rme9652->spdif_ctl->id); - return 0; -} - -static int snd_rme9652_playback_release(struct snd_pcm_substream *substream) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - - spin_lock_irq(&rme9652->lock); - - rme9652->playback_pid = -1; - rme9652->playback_substream = NULL; - - spin_unlock_irq(&rme9652->lock); - - rme9652->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &rme9652->spdif_ctl->id); - return 0; -} - - -static int snd_rme9652_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irq(&rme9652->lock); - - snd_pcm_set_sync(substream); - - runtime->hw = snd_rme9652_capture_subinfo; - runtime->dma_area = rme9652->capture_buffer; - runtime->dma_bytes = RME9652_DMA_AREA_BYTES; - - if (rme9652->playback_substream == NULL) { - rme9652_stop(rme9652); - rme9652_set_thru(rme9652, -1, 0); - } - - rme9652->capture_pid = current->pid; - rme9652->capture_substream = substream; - - spin_unlock_irq(&rme9652->lock); - - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_rme9652_hw_rule_channels, rme9652, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_rme9652_hw_rule_channels_rate, rme9652, - SNDRV_PCM_HW_PARAM_RATE, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_rme9652_hw_rule_rate_channels, rme9652, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - return 0; -} - -static int snd_rme9652_capture_release(struct snd_pcm_substream *substream) -{ - struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); - - spin_lock_irq(&rme9652->lock); - - rme9652->capture_pid = -1; - rme9652->capture_substream = NULL; - - spin_unlock_irq(&rme9652->lock); - return 0; -} - -static struct snd_pcm_ops snd_rme9652_playback_ops = { - .open = snd_rme9652_playback_open, - .close = snd_rme9652_playback_release, - .ioctl = snd_rme9652_ioctl, - .hw_params = snd_rme9652_hw_params, - .prepare = snd_rme9652_prepare, - .trigger = snd_rme9652_trigger, - .pointer = snd_rme9652_hw_pointer, - .copy = snd_rme9652_playback_copy, - .silence = snd_rme9652_hw_silence, -}; - -static struct snd_pcm_ops snd_rme9652_capture_ops = { - .open = snd_rme9652_capture_open, - .close = snd_rme9652_capture_release, - .ioctl = snd_rme9652_ioctl, - .hw_params = snd_rme9652_hw_params, - .prepare = snd_rme9652_prepare, - .trigger = snd_rme9652_trigger, - .pointer = snd_rme9652_hw_pointer, - .copy = snd_rme9652_capture_copy, -}; - -static int __devinit snd_rme9652_create_pcm(struct snd_card *card, - struct snd_rme9652 *rme9652) -{ - struct snd_pcm *pcm; - int err; - - if ((err = snd_pcm_new(card, - rme9652->card_name, - 0, 1, 1, &pcm)) < 0) { - return err; - } - - rme9652->pcm = pcm; - pcm->private_data = rme9652; - strcpy(pcm->name, rme9652->card_name); - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme9652_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme9652_capture_ops); - - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - - return 0; -} - -static int __devinit snd_rme9652_create(struct snd_card *card, - struct snd_rme9652 *rme9652, - int precise_ptr) -{ - struct pci_dev *pci = rme9652->pci; - int err; - int status; - unsigned short rev; - - rme9652->irq = -1; - rme9652->card = card; - - pci_read_config_word(rme9652->pci, PCI_CLASS_REVISION, &rev); - - switch (rev & 0xff) { - case 3: - case 4: - case 8: - case 9: - break; - - default: - /* who knows? */ - return -ENODEV; - } - - if ((err = pci_enable_device(pci)) < 0) - return err; - - spin_lock_init(&rme9652->lock); - - if ((err = pci_request_regions(pci, "rme9652")) < 0) - return err; - rme9652->port = pci_resource_start(pci, 0); - rme9652->iobase = ioremap_nocache(rme9652->port, RME9652_IO_EXTENT); - if (rme9652->iobase == NULL) { - snd_printk(KERN_ERR "unable to remap region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1); - return -EBUSY; - } - - if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_SHARED, - KBUILD_MODNAME, rme9652)) { - snd_printk(KERN_ERR "unable to request IRQ %d\n", pci->irq); - return -EBUSY; - } - rme9652->irq = pci->irq; - rme9652->precise_ptr = precise_ptr; - - /* Determine the h/w rev level of the card. This seems like - a particularly kludgy way to encode it, but its what RME - chose to do, so we follow them ... - */ - - status = rme9652_read(rme9652, RME9652_status_register); - if (rme9652_decode_spdif_rate(status&RME9652_F) == 1) { - rme9652->hw_rev = 15; - } else { - rme9652->hw_rev = 11; - } - - /* Differentiate between the standard Hammerfall, and the - "Light", which does not have the expansion board. This - method comes from information received from Mathhias - Clausen at RME. Display the EEPROM and h/w revID where - relevant. - */ - - switch (rev) { - case 8: /* original eprom */ - strcpy(card->driver, "RME9636"); - if (rme9652->hw_rev == 15) { - rme9652->card_name = "RME Digi9636 (Rev 1.5)"; - } else { - rme9652->card_name = "RME Digi9636"; - } - rme9652->ss_channels = RME9636_NCHANNELS; - break; - case 9: /* W36_G EPROM */ - strcpy(card->driver, "RME9636"); - rme9652->card_name = "RME Digi9636 (Rev G)"; - rme9652->ss_channels = RME9636_NCHANNELS; - break; - case 4: /* W52_G EPROM */ - strcpy(card->driver, "RME9652"); - rme9652->card_name = "RME Digi9652 (Rev G)"; - rme9652->ss_channels = RME9652_NCHANNELS; - break; - case 3: /* original eprom */ - strcpy(card->driver, "RME9652"); - if (rme9652->hw_rev == 15) { - rme9652->card_name = "RME Digi9652 (Rev 1.5)"; - } else { - rme9652->card_name = "RME Digi9652"; - } - rme9652->ss_channels = RME9652_NCHANNELS; - break; - } - - rme9652->ds_channels = (rme9652->ss_channels - 2) / 2 + 2; - - pci_set_master(rme9652->pci); - - if ((err = snd_rme9652_initialize_memory(rme9652)) < 0) { - return err; - } - - if ((err = snd_rme9652_create_pcm(card, rme9652)) < 0) { - return err; - } - - if ((err = snd_rme9652_create_controls(card, rme9652)) < 0) { - return err; - } - - snd_rme9652_proc_init(rme9652); - - rme9652->last_spdif_sample_rate = -1; - rme9652->last_adat_sample_rate = -1; - rme9652->playback_pid = -1; - rme9652->capture_pid = -1; - rme9652->capture_substream = NULL; - rme9652->playback_substream = NULL; - - snd_rme9652_set_defaults(rme9652); - - if (rme9652->hw_rev == 15) { - rme9652_initialize_spdif_receiver (rme9652); - } - - return 0; -} - -static void snd_rme9652_card_free(struct snd_card *card) -{ - struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data; - - if (rme9652) - snd_rme9652_free(rme9652); -} - -static int __devinit snd_rme9652_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_rme9652 *rme9652; - struct snd_card *card; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_rme9652), &card); - - if (err < 0) - return err; - - rme9652 = (struct snd_rme9652 *) card->private_data; - card->private_free = snd_rme9652_card_free; - rme9652->dev = dev; - rme9652->pci = pci; - snd_card_set_dev(card, &pci->dev); - - if ((err = snd_rme9652_create(card, rme9652, precise_ptr[dev])) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->shortname, rme9652->card_name); - - sprintf(card->longname, "%s at 0x%lx, irq %d", - card->shortname, rme9652->port, rme9652->irq); - - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_rme9652_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_rme9652_ids, - .probe = snd_rme9652_probe, - .remove = __devexit_p(snd_rme9652_remove), -}; - -static int __init alsa_card_hammerfall_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_hammerfall_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_hammerfall_init) -module_exit(alsa_card_hammerfall_exit) diff --git a/ANDROID_3.4.5/sound/pci/sis7019.c b/ANDROID_3.4.5/sound/pci/sis7019.c deleted file mode 100644 index ff500a87..00000000 --- a/ANDROID_3.4.5/sound/pci/sis7019.c +++ /dev/null @@ -1,1502 +0,0 @@ -/* - * Driver for SiS7019 Audio Accelerator - * - * Copyright (C) 2004-2007, David Dillow - * Written by David Dillow - * Inspired by the Trident 4D-WaveDX/NX driver. - * - * All rights reserved. - * - * 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, version 2. - * - * 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 -#include -#include "sis7019.h" - -MODULE_AUTHOR("David Dillow "); -MODULE_DESCRIPTION("SiS7019"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static bool enable = 1; -static int codecs = 1; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); -module_param(enable, bool, 0444); -MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); -module_param(codecs, int, 0444); -MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)"); - -static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_sis7019_ids); - -/* There are three timing modes for the voices. - * - * For both playback and capture, when the buffer is one or two periods long, - * we use the hardware's built-in Mid-Loop Interrupt and End-Loop Interrupt - * to let us know when the periods have ended. - * - * When performing playback with more than two periods per buffer, we set - * the "Stop Sample Offset" and tell the hardware to interrupt us when we - * reach it. We then update the offset and continue on until we are - * interrupted for the next period. - * - * Capture channels do not have a SSO, so we allocate a playback channel to - * use as a timer for the capture periods. We use the SSO on the playback - * channel to clock out virtual periods, and adjust the virtual period length - * to maintain synchronization. This algorithm came from the Trident driver. - * - * FIXME: It'd be nice to make use of some of the synth features in the - * hardware, but a woeful lack of documentation is a significant roadblock. - */ -struct voice { - u16 flags; -#define VOICE_IN_USE 1 -#define VOICE_CAPTURE 2 -#define VOICE_SSO_TIMING 4 -#define VOICE_SYNC_TIMING 8 - u16 sync_cso; - u16 period_size; - u16 buffer_size; - u16 sync_period_size; - u16 sync_buffer_size; - u32 sso; - u32 vperiod; - struct snd_pcm_substream *substream; - struct voice *timing; - void __iomem *ctrl_base; - void __iomem *wave_base; - void __iomem *sync_base; - int num; -}; - -/* We need four pages to store our wave parameters during a suspend. If - * we're not doing power management, we still need to allocate a page - * for the silence buffer. - */ -#ifdef CONFIG_PM -#define SIS_SUSPEND_PAGES 4 -#else -#define SIS_SUSPEND_PAGES 1 -#endif - -struct sis7019 { - unsigned long ioport; - void __iomem *ioaddr; - int irq; - int codecs_present; - - struct pci_dev *pci; - struct snd_pcm *pcm; - struct snd_card *card; - struct snd_ac97 *ac97[3]; - - /* Protect against more than one thread hitting the AC97 - * registers (in a more polite manner than pounding the hardware - * semaphore) - */ - struct mutex ac97_mutex; - - /* voice_lock protects allocation/freeing of the voice descriptions - */ - spinlock_t voice_lock; - - struct voice voices[64]; - struct voice capture_voice; - - /* Allocate pages to store the internal wave state during - * suspends. When we're operating, this can be used as a silence - * buffer for a timing channel. - */ - void *suspend_state[SIS_SUSPEND_PAGES]; - - int silence_users; - dma_addr_t silence_dma_addr; -}; - -/* These values are also used by the module param 'codecs' to indicate - * which codecs should be present. - */ -#define SIS_PRIMARY_CODEC_PRESENT 0x0001 -#define SIS_SECONDARY_CODEC_PRESENT 0x0002 -#define SIS_TERTIARY_CODEC_PRESENT 0x0004 - -/* The HW offset parameters (Loop End, Stop Sample, End Sample) have a - * documented range of 8-0xfff8 samples. Given that they are 0-based, - * that places our period/buffer range at 9-0xfff9 samples. That makes the - * max buffer size 0xfff9 samples * 2 channels * 2 bytes per sample, and - * max samples / min samples gives us the max periods in a buffer. - * - * We'll add a constraint upon open that limits the period and buffer sample - * size to values that are legal for the hardware. - */ -static struct snd_pcm_hardware sis_playback_hw_info = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_RESUME), - .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (0xfff9 * 4), - .period_bytes_min = 9, - .period_bytes_max = (0xfff9 * 4), - .periods_min = 1, - .periods_max = (0xfff9 / 9), -}; - -static struct snd_pcm_hardware sis_capture_hw_info = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_RESUME), - .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (0xfff9 * 4), - .period_bytes_min = 9, - .period_bytes_max = (0xfff9 * 4), - .periods_min = 1, - .periods_max = (0xfff9 / 9), -}; - -static void sis_update_sso(struct voice *voice, u16 period) -{ - void __iomem *base = voice->ctrl_base; - - voice->sso += period; - if (voice->sso >= voice->buffer_size) - voice->sso -= voice->buffer_size; - - /* Enforce the documented hardware minimum offset */ - if (voice->sso < 8) - voice->sso = 8; - - /* The SSO is in the upper 16 bits of the register. */ - writew(voice->sso & 0xffff, base + SIS_PLAY_DMA_SSO_ESO + 2); -} - -static void sis_update_voice(struct voice *voice) -{ - if (voice->flags & VOICE_SSO_TIMING) { - sis_update_sso(voice, voice->period_size); - } else if (voice->flags & VOICE_SYNC_TIMING) { - int sync; - - /* If we've not hit the end of the virtual period, update - * our records and keep going. - */ - if (voice->vperiod > voice->period_size) { - voice->vperiod -= voice->period_size; - if (voice->vperiod < voice->period_size) - sis_update_sso(voice, voice->vperiod); - else - sis_update_sso(voice, voice->period_size); - return; - } - - /* Calculate our relative offset between the target and - * the actual CSO value. Since we're operating in a loop, - * if the value is more than half way around, we can - * consider ourselves wrapped. - */ - sync = voice->sync_cso; - sync -= readw(voice->sync_base + SIS_CAPTURE_DMA_FORMAT_CSO); - if (sync > (voice->sync_buffer_size / 2)) - sync -= voice->sync_buffer_size; - - /* If sync is positive, then we interrupted too early, and - * we'll need to come back in a few samples and try again. - * There's a minimum wait, as it takes some time for the DMA - * engine to startup, etc... - */ - if (sync > 0) { - if (sync < 16) - sync = 16; - sis_update_sso(voice, sync); - return; - } - - /* Ok, we interrupted right on time, or (hopefully) just - * a bit late. We'll adjst our next waiting period based - * on how close we got. - * - * We need to stay just behind the actual channel to ensure - * it really is past a period when we get our interrupt -- - * otherwise we'll fall into the early code above and have - * a minimum wait time, which makes us quite late here, - * eating into the user's time to refresh the buffer, esp. - * if using small periods. - * - * If we're less than 9 samples behind, we're on target. - * Otherwise, shorten the next vperiod by the amount we've - * been delayed. - */ - if (sync > -9) - voice->vperiod = voice->sync_period_size + 1; - else - voice->vperiod = voice->sync_period_size + sync + 10; - - if (voice->vperiod < voice->buffer_size) { - sis_update_sso(voice, voice->vperiod); - voice->vperiod = 0; - } else - sis_update_sso(voice, voice->period_size); - - sync = voice->sync_cso + voice->sync_period_size; - if (sync >= voice->sync_buffer_size) - sync -= voice->sync_buffer_size; - voice->sync_cso = sync; - } - - snd_pcm_period_elapsed(voice->substream); -} - -static void sis_voice_irq(u32 status, struct voice *voice) -{ - int bit; - - while (status) { - bit = __ffs(status); - status >>= bit + 1; - voice += bit; - sis_update_voice(voice); - voice++; - } -} - -static irqreturn_t sis_interrupt(int irq, void *dev) -{ - struct sis7019 *sis = dev; - unsigned long io = sis->ioport; - struct voice *voice; - u32 intr, status; - - /* We only use the DMA interrupts, and we don't enable any other - * source of interrupts. But, it is possible to see an interrupt - * status that didn't actually interrupt us, so eliminate anything - * we're not expecting to avoid falsely claiming an IRQ, and an - * ensuing endless loop. - */ - intr = inl(io + SIS_GISR); - intr &= SIS_GISR_AUDIO_PLAY_DMA_IRQ_STATUS | - SIS_GISR_AUDIO_RECORD_DMA_IRQ_STATUS; - if (!intr) - return IRQ_NONE; - - do { - status = inl(io + SIS_PISR_A); - if (status) { - sis_voice_irq(status, sis->voices); - outl(status, io + SIS_PISR_A); - } - - status = inl(io + SIS_PISR_B); - if (status) { - sis_voice_irq(status, &sis->voices[32]); - outl(status, io + SIS_PISR_B); - } - - status = inl(io + SIS_RISR); - if (status) { - voice = &sis->capture_voice; - if (!voice->timing) - snd_pcm_period_elapsed(voice->substream); - - outl(status, io + SIS_RISR); - } - - outl(intr, io + SIS_GISR); - intr = inl(io + SIS_GISR); - intr &= SIS_GISR_AUDIO_PLAY_DMA_IRQ_STATUS | - SIS_GISR_AUDIO_RECORD_DMA_IRQ_STATUS; - } while (intr); - - return IRQ_HANDLED; -} - -static u32 sis_rate_to_delta(unsigned int rate) -{ - u32 delta; - - /* This was copied from the trident driver, but it seems its gotten - * around a bit... nevertheless, it works well. - * - * We special case 44100 and 8000 since rounding with the equation - * does not give us an accurate enough value. For 11025 and 22050 - * the equation gives us the best answer. All other frequencies will - * also use the equation. JDW - */ - if (rate == 44100) - delta = 0xeb3; - else if (rate == 8000) - delta = 0x2ab; - else if (rate == 48000) - delta = 0x1000; - else - delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff; - return delta; -} - -static void __sis_map_silence(struct sis7019 *sis) -{ - /* Helper function: must hold sis->voice_lock on entry */ - if (!sis->silence_users) - sis->silence_dma_addr = pci_map_single(sis->pci, - sis->suspend_state[0], - 4096, PCI_DMA_TODEVICE); - sis->silence_users++; -} - -static void __sis_unmap_silence(struct sis7019 *sis) -{ - /* Helper function: must hold sis->voice_lock on entry */ - sis->silence_users--; - if (!sis->silence_users) - pci_unmap_single(sis->pci, sis->silence_dma_addr, 4096, - PCI_DMA_TODEVICE); -} - -static void sis_free_voice(struct sis7019 *sis, struct voice *voice) -{ - unsigned long flags; - - spin_lock_irqsave(&sis->voice_lock, flags); - if (voice->timing) { - __sis_unmap_silence(sis); - voice->timing->flags &= ~(VOICE_IN_USE | VOICE_SSO_TIMING | - VOICE_SYNC_TIMING); - voice->timing = NULL; - } - voice->flags &= ~(VOICE_IN_USE | VOICE_SSO_TIMING | VOICE_SYNC_TIMING); - spin_unlock_irqrestore(&sis->voice_lock, flags); -} - -static struct voice *__sis_alloc_playback_voice(struct sis7019 *sis) -{ - /* Must hold the voice_lock on entry */ - struct voice *voice; - int i; - - for (i = 0; i < 64; i++) { - voice = &sis->voices[i]; - if (voice->flags & VOICE_IN_USE) - continue; - voice->flags |= VOICE_IN_USE; - goto found_one; - } - voice = NULL; - -found_one: - return voice; -} - -static struct voice *sis_alloc_playback_voice(struct sis7019 *sis) -{ - struct voice *voice; - unsigned long flags; - - spin_lock_irqsave(&sis->voice_lock, flags); - voice = __sis_alloc_playback_voice(sis); - spin_unlock_irqrestore(&sis->voice_lock, flags); - - return voice; -} - -static int sis_alloc_timing_voice(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct sis7019 *sis = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct voice *voice = runtime->private_data; - unsigned int period_size, buffer_size; - unsigned long flags; - int needed; - - /* If there are one or two periods per buffer, we don't need a - * timing voice, as we can use the capture channel's interrupts - * to clock out the periods. - */ - period_size = params_period_size(hw_params); - buffer_size = params_buffer_size(hw_params); - needed = (period_size != buffer_size && - period_size != (buffer_size / 2)); - - if (needed && !voice->timing) { - spin_lock_irqsave(&sis->voice_lock, flags); - voice->timing = __sis_alloc_playback_voice(sis); - if (voice->timing) - __sis_map_silence(sis); - spin_unlock_irqrestore(&sis->voice_lock, flags); - if (!voice->timing) - return -ENOMEM; - voice->timing->substream = substream; - } else if (!needed && voice->timing) { - sis_free_voice(sis, voice); - voice->timing = NULL; - } - - return 0; -} - -static int sis_playback_open(struct snd_pcm_substream *substream) -{ - struct sis7019 *sis = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct voice *voice; - - voice = sis_alloc_playback_voice(sis); - if (!voice) - return -EAGAIN; - - voice->substream = substream; - runtime->private_data = voice; - runtime->hw = sis_playback_hw_info; - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 9, 0xfff9); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - 9, 0xfff9); - snd_pcm_set_sync(substream); - return 0; -} - -static int sis_substream_close(struct snd_pcm_substream *substream) -{ - struct sis7019 *sis = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct voice *voice = runtime->private_data; - - sis_free_voice(sis, voice); - return 0; -} - -static int sis_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int sis_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int sis_pcm_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct voice *voice = runtime->private_data; - void __iomem *ctrl_base = voice->ctrl_base; - void __iomem *wave_base = voice->wave_base; - u32 format, dma_addr, control, sso_eso, delta, reg; - u16 leo; - - /* We rely on the PCM core to ensure that the parameters for this - * substream do not change on us while we're programming the HW. - */ - format = 0; - if (snd_pcm_format_width(runtime->format) == 8) - format |= SIS_PLAY_DMA_FORMAT_8BIT; - if (!snd_pcm_format_signed(runtime->format)) - format |= SIS_PLAY_DMA_FORMAT_UNSIGNED; - if (runtime->channels == 1) - format |= SIS_PLAY_DMA_FORMAT_MONO; - - /* The baseline setup is for a single period per buffer, and - * we add bells and whistles as needed from there. - */ - dma_addr = runtime->dma_addr; - leo = runtime->buffer_size - 1; - control = leo | SIS_PLAY_DMA_LOOP | SIS_PLAY_DMA_INTR_AT_LEO; - sso_eso = leo; - - if (runtime->period_size == (runtime->buffer_size / 2)) { - control |= SIS_PLAY_DMA_INTR_AT_MLP; - } else if (runtime->period_size != runtime->buffer_size) { - voice->flags |= VOICE_SSO_TIMING; - voice->sso = runtime->period_size - 1; - voice->period_size = runtime->period_size; - voice->buffer_size = runtime->buffer_size; - - control &= ~SIS_PLAY_DMA_INTR_AT_LEO; - control |= SIS_PLAY_DMA_INTR_AT_SSO; - sso_eso |= (runtime->period_size - 1) << 16; - } - - delta = sis_rate_to_delta(runtime->rate); - - /* Ok, we're ready to go, set up the channel. - */ - writel(format, ctrl_base + SIS_PLAY_DMA_FORMAT_CSO); - writel(dma_addr, ctrl_base + SIS_PLAY_DMA_BASE); - writel(control, ctrl_base + SIS_PLAY_DMA_CONTROL); - writel(sso_eso, ctrl_base + SIS_PLAY_DMA_SSO_ESO); - - for (reg = 0; reg < SIS_WAVE_SIZE; reg += 4) - writel(0, wave_base + reg); - - writel(SIS_WAVE_GENERAL_WAVE_VOLUME, wave_base + SIS_WAVE_GENERAL); - writel(delta << 16, wave_base + SIS_WAVE_GENERAL_ARTICULATION); - writel(SIS_WAVE_CHANNEL_CONTROL_FIRST_SAMPLE | - SIS_WAVE_CHANNEL_CONTROL_AMP_ENABLE | - SIS_WAVE_CHANNEL_CONTROL_INTERPOLATE_ENABLE, - wave_base + SIS_WAVE_CHANNEL_CONTROL); - - /* Force PCI writes to post. */ - readl(ctrl_base); - - return 0; -} - -static int sis_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct sis7019 *sis = snd_pcm_substream_chip(substream); - unsigned long io = sis->ioport; - struct snd_pcm_substream *s; - struct voice *voice; - void *chip; - int starting; - u32 record = 0; - u32 play[2] = { 0, 0 }; - - /* No locks needed, as the PCM core will hold the locks on the - * substreams, and the HW will only start/stop the indicated voices - * without changing the state of the others. - */ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - starting = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - starting = 0; - break; - default: - return -EINVAL; - } - - snd_pcm_group_for_each_entry(s, substream) { - /* Make sure it is for us... */ - chip = snd_pcm_substream_chip(s); - if (chip != sis) - continue; - - voice = s->runtime->private_data; - if (voice->flags & VOICE_CAPTURE) { - record |= 1 << voice->num; - voice = voice->timing; - } - - /* voice could be NULL if this a recording stream, and it - * doesn't have an external timing channel. - */ - if (voice) - play[voice->num / 32] |= 1 << (voice->num & 0x1f); - - snd_pcm_trigger_done(s, substream); - } - - if (starting) { - if (record) - outl(record, io + SIS_RECORD_START_REG); - if (play[0]) - outl(play[0], io + SIS_PLAY_START_A_REG); - if (play[1]) - outl(play[1], io + SIS_PLAY_START_B_REG); - } else { - if (record) - outl(record, io + SIS_RECORD_STOP_REG); - if (play[0]) - outl(play[0], io + SIS_PLAY_STOP_A_REG); - if (play[1]) - outl(play[1], io + SIS_PLAY_STOP_B_REG); - } - return 0; -} - -static snd_pcm_uframes_t sis_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct voice *voice = runtime->private_data; - u32 cso; - - cso = readl(voice->ctrl_base + SIS_PLAY_DMA_FORMAT_CSO); - cso &= 0xffff; - return cso; -} - -static int sis_capture_open(struct snd_pcm_substream *substream) -{ - struct sis7019 *sis = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct voice *voice = &sis->capture_voice; - unsigned long flags; - - /* FIXME: The driver only supports recording from one channel - * at the moment, but it could support more. - */ - spin_lock_irqsave(&sis->voice_lock, flags); - if (voice->flags & VOICE_IN_USE) - voice = NULL; - else - voice->flags |= VOICE_IN_USE; - spin_unlock_irqrestore(&sis->voice_lock, flags); - - if (!voice) - return -EAGAIN; - - voice->substream = substream; - runtime->private_data = voice; - runtime->hw = sis_capture_hw_info; - runtime->hw.rates = sis->ac97[0]->rates[AC97_RATES_ADC]; - snd_pcm_limit_hw_rates(runtime); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 9, 0xfff9); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - 9, 0xfff9); - snd_pcm_set_sync(substream); - return 0; -} - -static int sis_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct sis7019 *sis = snd_pcm_substream_chip(substream); - int rc; - - rc = snd_ac97_set_rate(sis->ac97[0], AC97_PCM_LR_ADC_RATE, - params_rate(hw_params)); - if (rc) - goto out; - - rc = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (rc < 0) - goto out; - - rc = sis_alloc_timing_voice(substream, hw_params); - -out: - return rc; -} - -static void sis_prepare_timing_voice(struct voice *voice, - struct snd_pcm_substream *substream) -{ - struct sis7019 *sis = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct voice *timing = voice->timing; - void __iomem *play_base = timing->ctrl_base; - void __iomem *wave_base = timing->wave_base; - u16 buffer_size, period_size; - u32 format, control, sso_eso, delta; - u32 vperiod, sso, reg; - - /* Set our initial buffer and period as large as we can given a - * single page of silence. - */ - buffer_size = 4096 / runtime->channels; - buffer_size /= snd_pcm_format_size(runtime->format, 1); - period_size = buffer_size; - - /* Initially, we want to interrupt just a bit behind the end of - * the period we're clocking out. 12 samples seems to give a good - * delay. - * - * We want to spread our interrupts throughout the virtual period, - * so that we don't end up with two interrupts back to back at the - * end -- this helps minimize the effects of any jitter. Adjust our - * clocking period size so that the last period is at least a fourth - * of a full period. - * - * This is all moot if we don't need to use virtual periods. - */ - vperiod = runtime->period_size + 12; - if (vperiod > period_size) { - u16 tail = vperiod % period_size; - u16 quarter_period = period_size / 4; - - if (tail && tail < quarter_period) { - u16 loops = vperiod / period_size; - - tail = quarter_period - tail; - tail += loops - 1; - tail /= loops; - period_size -= tail; - } - - sso = period_size - 1; - } else { - /* The initial period will fit inside the buffer, so we - * don't need to use virtual periods -- disable them. - */ - period_size = runtime->period_size; - sso = vperiod - 1; - vperiod = 0; - } - - /* The interrupt handler implements the timing synchronization, so - * setup its state. - */ - timing->flags |= VOICE_SYNC_TIMING; - timing->sync_base = voice->ctrl_base; - timing->sync_cso = runtime->period_size; - timing->sync_period_size = runtime->period_size; - timing->sync_buffer_size = runtime->buffer_size; - timing->period_size = period_size; - timing->buffer_size = buffer_size; - timing->sso = sso; - timing->vperiod = vperiod; - - /* Using unsigned samples with the all-zero silence buffer - * forces the output to the lower rail, killing playback. - * So ignore unsigned vs signed -- it doesn't change the timing. - */ - format = 0; - if (snd_pcm_format_width(runtime->format) == 8) - format = SIS_CAPTURE_DMA_FORMAT_8BIT; - if (runtime->channels == 1) - format |= SIS_CAPTURE_DMA_FORMAT_MONO; - - control = timing->buffer_size - 1; - control |= SIS_PLAY_DMA_LOOP | SIS_PLAY_DMA_INTR_AT_SSO; - sso_eso = timing->buffer_size - 1; - sso_eso |= timing->sso << 16; - - delta = sis_rate_to_delta(runtime->rate); - - /* We've done the math, now configure the channel. - */ - writel(format, play_base + SIS_PLAY_DMA_FORMAT_CSO); - writel(sis->silence_dma_addr, play_base + SIS_PLAY_DMA_BASE); - writel(control, play_base + SIS_PLAY_DMA_CONTROL); - writel(sso_eso, play_base + SIS_PLAY_DMA_SSO_ESO); - - for (reg = 0; reg < SIS_WAVE_SIZE; reg += 4) - writel(0, wave_base + reg); - - writel(SIS_WAVE_GENERAL_WAVE_VOLUME, wave_base + SIS_WAVE_GENERAL); - writel(delta << 16, wave_base + SIS_WAVE_GENERAL_ARTICULATION); - writel(SIS_WAVE_CHANNEL_CONTROL_FIRST_SAMPLE | - SIS_WAVE_CHANNEL_CONTROL_AMP_ENABLE | - SIS_WAVE_CHANNEL_CONTROL_INTERPOLATE_ENABLE, - wave_base + SIS_WAVE_CHANNEL_CONTROL); -} - -static int sis_pcm_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct voice *voice = runtime->private_data; - void __iomem *rec_base = voice->ctrl_base; - u32 format, dma_addr, control; - u16 leo; - - /* We rely on the PCM core to ensure that the parameters for this - * substream do not change on us while we're programming the HW. - */ - format = 0; - if (snd_pcm_format_width(runtime->format) == 8) - format = SIS_CAPTURE_DMA_FORMAT_8BIT; - if (!snd_pcm_format_signed(runtime->format)) - format |= SIS_CAPTURE_DMA_FORMAT_UNSIGNED; - if (runtime->channels == 1) - format |= SIS_CAPTURE_DMA_FORMAT_MONO; - - dma_addr = runtime->dma_addr; - leo = runtime->buffer_size - 1; - control = leo | SIS_CAPTURE_DMA_LOOP; - - /* If we've got more than two periods per buffer, then we have - * use a timing voice to clock out the periods. Otherwise, we can - * use the capture channel's interrupts. - */ - if (voice->timing) { - sis_prepare_timing_voice(voice, substream); - } else { - control |= SIS_CAPTURE_DMA_INTR_AT_LEO; - if (runtime->period_size != runtime->buffer_size) - control |= SIS_CAPTURE_DMA_INTR_AT_MLP; - } - - writel(format, rec_base + SIS_CAPTURE_DMA_FORMAT_CSO); - writel(dma_addr, rec_base + SIS_CAPTURE_DMA_BASE); - writel(control, rec_base + SIS_CAPTURE_DMA_CONTROL); - - /* Force the writes to post. */ - readl(rec_base); - - return 0; -} - -static struct snd_pcm_ops sis_playback_ops = { - .open = sis_playback_open, - .close = sis_substream_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = sis_playback_hw_params, - .hw_free = sis_hw_free, - .prepare = sis_pcm_playback_prepare, - .trigger = sis_pcm_trigger, - .pointer = sis_pcm_pointer, -}; - -static struct snd_pcm_ops sis_capture_ops = { - .open = sis_capture_open, - .close = sis_substream_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = sis_capture_hw_params, - .hw_free = sis_hw_free, - .prepare = sis_pcm_capture_prepare, - .trigger = sis_pcm_trigger, - .pointer = sis_pcm_pointer, -}; - -static int __devinit sis_pcm_create(struct sis7019 *sis) -{ - struct snd_pcm *pcm; - int rc; - - /* We have 64 voices, and the driver currently records from - * only one channel, though that could change in the future. - */ - rc = snd_pcm_new(sis->card, "SiS7019", 0, 64, 1, &pcm); - if (rc) - return rc; - - pcm->private_data = sis; - strcpy(pcm->name, "SiS7019"); - sis->pcm = pcm; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &sis_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &sis_capture_ops); - - /* Try to preallocate some memory, but it's not the end of the - * world if this fails. - */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(sis->pci), 64*1024, 128*1024); - - return 0; -} - -static unsigned short sis_ac97_rw(struct sis7019 *sis, int codec, u32 cmd) -{ - unsigned long io = sis->ioport; - unsigned short val = 0xffff; - u16 status; - u16 rdy; - int count; - static const u16 codec_ready[3] = { - SIS_AC97_STATUS_CODEC_READY, - SIS_AC97_STATUS_CODEC2_READY, - SIS_AC97_STATUS_CODEC3_READY, - }; - - rdy = codec_ready[codec]; - - - /* Get the AC97 semaphore -- software first, so we don't spin - * pounding out IO reads on the hardware semaphore... - */ - mutex_lock(&sis->ac97_mutex); - - count = 0xffff; - while ((inw(io + SIS_AC97_SEMA) & SIS_AC97_SEMA_BUSY) && --count) - udelay(1); - - if (!count) - goto timeout; - - /* ... and wait for any outstanding commands to complete ... - */ - count = 0xffff; - do { - status = inw(io + SIS_AC97_STATUS); - if ((status & rdy) && !(status & SIS_AC97_STATUS_BUSY)) - break; - - udelay(1); - } while (--count); - - if (!count) - goto timeout_sema; - - /* ... before sending our command and waiting for it to finish ... - */ - outl(cmd, io + SIS_AC97_CMD); - udelay(10); - - count = 0xffff; - while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) - udelay(1); - - /* ... and reading the results (if any). - */ - val = inl(io + SIS_AC97_CMD) >> 16; - -timeout_sema: - outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); -timeout: - mutex_unlock(&sis->ac97_mutex); - - if (!count) { - dev_err(&sis->pci->dev, "ac97 codec %d timeout cmd 0x%08x\n", - codec, cmd); - } - - return val; -} - -static void sis_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - static const u32 cmd[3] = { - SIS_AC97_CMD_CODEC_WRITE, - SIS_AC97_CMD_CODEC2_WRITE, - SIS_AC97_CMD_CODEC3_WRITE, - }; - sis_ac97_rw(ac97->private_data, ac97->num, - (val << 16) | (reg << 8) | cmd[ac97->num]); -} - -static unsigned short sis_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - static const u32 cmd[3] = { - SIS_AC97_CMD_CODEC_READ, - SIS_AC97_CMD_CODEC2_READ, - SIS_AC97_CMD_CODEC3_READ, - }; - return sis_ac97_rw(ac97->private_data, ac97->num, - (reg << 8) | cmd[ac97->num]); -} - -static int __devinit sis_mixer_create(struct sis7019 *sis) -{ - struct snd_ac97_bus *bus; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = sis_ac97_write, - .read = sis_ac97_read, - }; - int rc; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = sis; - - rc = snd_ac97_bus(sis->card, 0, &ops, NULL, &bus); - if (!rc && sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT) - rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[0]); - ac97.num = 1; - if (!rc && (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT)) - rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[1]); - ac97.num = 2; - if (!rc && (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT)) - rc = snd_ac97_mixer(bus, &ac97, &sis->ac97[2]); - - /* If we return an error here, then snd_card_free() should - * free up any ac97 codecs that got created, as well as the bus. - */ - return rc; -} - -static void sis_free_suspend(struct sis7019 *sis) -{ - int i; - - for (i = 0; i < SIS_SUSPEND_PAGES; i++) - kfree(sis->suspend_state[i]); -} - -static int sis_chip_free(struct sis7019 *sis) -{ - /* Reset the chip, and disable all interrputs. - */ - outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR); - udelay(25); - outl(0, sis->ioport + SIS_GCR); - outl(0, sis->ioport + SIS_GIER); - - /* Now, free everything we allocated. - */ - if (sis->irq >= 0) - free_irq(sis->irq, sis); - - if (sis->ioaddr) - iounmap(sis->ioaddr); - - pci_release_regions(sis->pci); - pci_disable_device(sis->pci); - - sis_free_suspend(sis); - return 0; -} - -static int sis_dev_free(struct snd_device *dev) -{ - struct sis7019 *sis = dev->device_data; - return sis_chip_free(sis); -} - -static int sis_chip_init(struct sis7019 *sis) -{ - unsigned long io = sis->ioport; - void __iomem *ioaddr = sis->ioaddr; - unsigned long timeout; - u16 status; - int count; - int i; - - /* Reset the audio controller - */ - outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR); - udelay(25); - outl(0, io + SIS_GCR); - - /* Get the AC-link semaphore, and reset the codecs - */ - count = 0xffff; - while ((inw(io + SIS_AC97_SEMA) & SIS_AC97_SEMA_BUSY) && --count) - udelay(1); - - if (!count) - return -EIO; - - outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD); - udelay(250); - - count = 0xffff; - while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) - udelay(1); - - /* Command complete, we can let go of the semaphore now. - */ - outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); - if (!count) - return -EIO; - - /* Now that we've finished the reset, find out what's attached. - * There are some codec/board combinations that take an extremely - * long time to come up. 350+ ms has been observed in the field, - * so we'll give them up to 500ms. - */ - sis->codecs_present = 0; - timeout = msecs_to_jiffies(500) + jiffies; - while (time_before_eq(jiffies, timeout)) { - status = inl(io + SIS_AC97_STATUS); - if (status & SIS_AC97_STATUS_CODEC_READY) - sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; - if (status & SIS_AC97_STATUS_CODEC2_READY) - sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; - if (status & SIS_AC97_STATUS_CODEC3_READY) - sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; - - if (sis->codecs_present == codecs) - break; - - msleep(1); - } - - /* All done, check for errors. - */ - if (!sis->codecs_present) { - dev_err(&sis->pci->dev, "could not find any codecs\n"); - return -EIO; - } - - if (sis->codecs_present != codecs) { - dev_warn(&sis->pci->dev, "missing codecs, found %0x, expected %0x\n", - sis->codecs_present, codecs); - } - - /* Let the hardware know that the audio driver is alive, - * and enable PCM slots on the AC-link for L/R playback (3 & 4) and - * record channels. We're going to want to use Variable Rate Audio - * for recording, to avoid needlessly resampling from 48kHZ. - */ - outl(SIS_AC97_CONF_AUDIO_ALIVE, io + SIS_AC97_CONF); - outl(SIS_AC97_CONF_AUDIO_ALIVE | SIS_AC97_CONF_PCM_LR_ENABLE | - SIS_AC97_CONF_PCM_CAP_MIC_ENABLE | - SIS_AC97_CONF_PCM_CAP_LR_ENABLE | - SIS_AC97_CONF_CODEC_VRA_ENABLE, io + SIS_AC97_CONF); - - /* All AC97 PCM slots should be sourced from sub-mixer 0. - */ - outl(0, io + SIS_AC97_PSR); - - /* There is only one valid DMA setup for a PCI environment. - */ - outl(SIS_DMA_CSR_PCI_SETTINGS, io + SIS_DMA_CSR); - - /* Reset the synchronization groups for all of the channels - * to be asyncronous. If we start doing SPDIF or 5.1 sound, etc. - * we'll need to change how we handle these. Until then, we just - * assign sub-mixer 0 to all playback channels, and avoid any - * attenuation on the audio. - */ - outl(0, io + SIS_PLAY_SYNC_GROUP_A); - outl(0, io + SIS_PLAY_SYNC_GROUP_B); - outl(0, io + SIS_PLAY_SYNC_GROUP_C); - outl(0, io + SIS_PLAY_SYNC_GROUP_D); - outl(0, io + SIS_MIXER_SYNC_GROUP); - - for (i = 0; i < 64; i++) { - writel(i, SIS_MIXER_START_ADDR(ioaddr, i)); - writel(SIS_MIXER_RIGHT_NO_ATTEN | SIS_MIXER_LEFT_NO_ATTEN | - SIS_MIXER_DEST_0, SIS_MIXER_ADDR(ioaddr, i)); - } - - /* Don't attenuate any audio set for the wave amplifier. - * - * FIXME: Maximum attenuation is set for the music amp, which will - * need to change if we start using the synth engine. - */ - outl(0xffff0000, io + SIS_WEVCR); - - /* Ensure that the wave engine is in normal operating mode. - */ - outl(0, io + SIS_WECCR); - - /* Go ahead and enable the DMA interrupts. They won't go live - * until we start a channel. - */ - outl(SIS_GIER_AUDIO_PLAY_DMA_IRQ_ENABLE | - SIS_GIER_AUDIO_RECORD_DMA_IRQ_ENABLE, io + SIS_GIER); - - return 0; -} - -#ifdef CONFIG_PM -static int sis_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct sis7019 *sis = card->private_data; - void __iomem *ioaddr = sis->ioaddr; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(sis->pcm); - if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT) - snd_ac97_suspend(sis->ac97[0]); - if (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT) - snd_ac97_suspend(sis->ac97[1]); - if (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT) - snd_ac97_suspend(sis->ac97[2]); - - /* snd_pcm_suspend_all() stopped all channels, so we're quiescent. - */ - if (sis->irq >= 0) { - free_irq(sis->irq, sis); - sis->irq = -1; - } - - /* Save the internal state away - */ - for (i = 0; i < 4; i++) { - memcpy_fromio(sis->suspend_state[i], ioaddr, 4096); - ioaddr += 4096; - } - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int sis_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct sis7019 *sis = card->private_data; - void __iomem *ioaddr = sis->ioaddr; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - - if (pci_enable_device(pci) < 0) { - dev_err(&pci->dev, "unable to re-enable device\n"); - goto error; - } - - if (sis_chip_init(sis)) { - dev_err(&pci->dev, "unable to re-init controller\n"); - goto error; - } - - if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, - KBUILD_MODNAME, sis)) { - dev_err(&pci->dev, "unable to regain IRQ %d\n", pci->irq); - goto error; - } - - /* Restore saved state, then clear out the page we use for the - * silence buffer. - */ - for (i = 0; i < 4; i++) { - memcpy_toio(ioaddr, sis->suspend_state[i], 4096); - ioaddr += 4096; - } - - memset(sis->suspend_state[0], 0, 4096); - - sis->irq = pci->irq; - pci_set_master(pci); - - if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT) - snd_ac97_resume(sis->ac97[0]); - if (sis->codecs_present & SIS_SECONDARY_CODEC_PRESENT) - snd_ac97_resume(sis->ac97[1]); - if (sis->codecs_present & SIS_TERTIARY_CODEC_PRESENT) - snd_ac97_resume(sis->ac97[2]); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; - -error: - snd_card_disconnect(card); - return -EIO; -} -#endif /* CONFIG_PM */ - -static int sis_alloc_suspend(struct sis7019 *sis) -{ - int i; - - /* We need 16K to store the internal wave engine state during a - * suspend, but we don't need it to be contiguous, so play nice - * with the memory system. We'll also use this area for a silence - * buffer. - */ - for (i = 0; i < SIS_SUSPEND_PAGES; i++) { - sis->suspend_state[i] = kmalloc(4096, GFP_KERNEL); - if (!sis->suspend_state[i]) - return -ENOMEM; - } - memset(sis->suspend_state[0], 0, 4096); - - return 0; -} - -static int __devinit sis_chip_create(struct snd_card *card, - struct pci_dev *pci) -{ - struct sis7019 *sis = card->private_data; - struct voice *voice; - static struct snd_device_ops ops = { - .dev_free = sis_dev_free, - }; - int rc; - int i; - - rc = pci_enable_device(pci); - if (rc) - goto error_out; - - if (pci_set_dma_mask(pci, DMA_BIT_MASK(30)) < 0) { - dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA"); - goto error_out_enabled; - } - - memset(sis, 0, sizeof(*sis)); - mutex_init(&sis->ac97_mutex); - spin_lock_init(&sis->voice_lock); - sis->card = card; - sis->pci = pci; - sis->irq = -1; - sis->ioport = pci_resource_start(pci, 0); - - rc = pci_request_regions(pci, "SiS7019"); - if (rc) { - dev_err(&pci->dev, "unable request regions\n"); - goto error_out_enabled; - } - - rc = -EIO; - sis->ioaddr = ioremap_nocache(pci_resource_start(pci, 1), 0x4000); - if (!sis->ioaddr) { - dev_err(&pci->dev, "unable to remap MMIO, aborting\n"); - goto error_out_cleanup; - } - - rc = sis_alloc_suspend(sis); - if (rc < 0) { - dev_err(&pci->dev, "unable to allocate state storage\n"); - goto error_out_cleanup; - } - - rc = sis_chip_init(sis); - if (rc) - goto error_out_cleanup; - - if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME, - sis)) { - dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq); - goto error_out_cleanup; - } - - sis->irq = pci->irq; - pci_set_master(pci); - - for (i = 0; i < 64; i++) { - voice = &sis->voices[i]; - voice->num = i; - voice->ctrl_base = SIS_PLAY_DMA_ADDR(sis->ioaddr, i); - voice->wave_base = SIS_WAVE_ADDR(sis->ioaddr, i); - } - - voice = &sis->capture_voice; - voice->flags = VOICE_CAPTURE; - voice->num = SIS_CAPTURE_CHAN_AC97_PCM_IN; - voice->ctrl_base = SIS_CAPTURE_DMA_ADDR(sis->ioaddr, voice->num); - - rc = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sis, &ops); - if (rc) - goto error_out_cleanup; - - snd_card_set_dev(card, &pci->dev); - - return 0; - -error_out_cleanup: - sis_chip_free(sis); - -error_out_enabled: - pci_disable_device(pci); - -error_out: - return rc; -} - -static int __devinit snd_sis7019_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct sis7019 *sis; - int rc; - - rc = -ENOENT; - if (!enable) - goto error_out; - - /* The user can specify which codecs should be present so that we - * can wait for them to show up if they are slow to recover from - * the AC97 cold reset. We default to a single codec, the primary. - * - * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2. - */ - codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT | - SIS_TERTIARY_CODEC_PRESENT; - if (!codecs) - codecs = SIS_PRIMARY_CODEC_PRESENT; - - rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); - if (rc < 0) - goto error_out; - - strcpy(card->driver, "SiS7019"); - strcpy(card->shortname, "SiS7019"); - rc = sis_chip_create(card, pci); - if (rc) - goto card_error_out; - - sis = card->private_data; - - rc = sis_mixer_create(sis); - if (rc) - goto card_error_out; - - rc = sis_pcm_create(sis); - if (rc) - goto card_error_out; - - snprintf(card->longname, sizeof(card->longname), - "%s Audio Accelerator with %s at 0x%lx, irq %d", - card->shortname, snd_ac97_get_short_name(sis->ac97[0]), - sis->ioport, sis->irq); - - rc = snd_card_register(card); - if (rc) - goto card_error_out; - - pci_set_drvdata(pci, card); - return 0; - -card_error_out: - snd_card_free(card); - -error_out: - return rc; -} - -static void __devexit snd_sis7019_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver sis7019_driver = { - .name = KBUILD_MODNAME, - .id_table = snd_sis7019_ids, - .probe = snd_sis7019_probe, - .remove = __devexit_p(snd_sis7019_remove), - -#ifdef CONFIG_PM - .suspend = sis_suspend, - .resume = sis_resume, -#endif -}; - -static int __init sis7019_init(void) -{ - return pci_register_driver(&sis7019_driver); -} - -static void __exit sis7019_exit(void) -{ - pci_unregister_driver(&sis7019_driver); -} - -module_init(sis7019_init); -module_exit(sis7019_exit); diff --git a/ANDROID_3.4.5/sound/pci/sis7019.h b/ANDROID_3.4.5/sound/pci/sis7019.h deleted file mode 100644 index bc8c7681..00000000 --- a/ANDROID_3.4.5/sound/pci/sis7019.h +++ /dev/null @@ -1,342 +0,0 @@ -#ifndef __sis7019_h__ -#define __sis7019_h__ - -/* - * Definitions for SiS7019 Audio Accelerator - * - * Copyright (C) 2004-2007, David Dillow - * Written by David Dillow - * Inspired by the Trident 4D-WaveDX/NX driver. - * - * All rights reserved. - * - * 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, version 2. - * - * 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 - */ - - -/* General Control Register */ -#define SIS_GCR 0x00 -#define SIS_GCR_MACRO_POWER_DOWN 0x80000000 -#define SIS_GCR_MODEM_ENABLE 0x00010000 -#define SIS_GCR_SOFTWARE_RESET 0x00000001 - -/* General Interrupt Enable Register */ -#define SIS_GIER 0x04 -#define SIS_GIER_MODEM_TIMER_IRQ_ENABLE 0x00100000 -#define SIS_GIER_MODEM_RX_DMA_IRQ_ENABLE 0x00080000 -#define SIS_GIER_MODEM_TX_DMA_IRQ_ENABLE 0x00040000 -#define SIS_GIER_AC97_GPIO1_IRQ_ENABLE 0x00020000 -#define SIS_GIER_AC97_GPIO0_IRQ_ENABLE 0x00010000 -#define SIS_GIER_AC97_SAMPLE_TIMER_IRQ_ENABLE 0x00000010 -#define SIS_GIER_AUDIO_GLOBAL_TIMER_IRQ_ENABLE 0x00000008 -#define SIS_GIER_AUDIO_RECORD_DMA_IRQ_ENABLE 0x00000004 -#define SIS_GIER_AUDIO_PLAY_DMA_IRQ_ENABLE 0x00000002 -#define SIS_GIER_AUDIO_WAVE_ENGINE_IRQ_ENABLE 0x00000001 - -/* General Interrupt Status Register */ -#define SIS_GISR 0x08 -#define SIS_GISR_MODEM_TIMER_IRQ_STATUS 0x00100000 -#define SIS_GISR_MODEM_RX_DMA_IRQ_STATUS 0x00080000 -#define SIS_GISR_MODEM_TX_DMA_IRQ_STATUS 0x00040000 -#define SIS_GISR_AC97_GPIO1_IRQ_STATUS 0x00020000 -#define SIS_GISR_AC97_GPIO0_IRQ_STATUS 0x00010000 -#define SIS_GISR_AC97_SAMPLE_TIMER_IRQ_STATUS 0x00000010 -#define SIS_GISR_AUDIO_GLOBAL_TIMER_IRQ_STATUS 0x00000008 -#define SIS_GISR_AUDIO_RECORD_DMA_IRQ_STATUS 0x00000004 -#define SIS_GISR_AUDIO_PLAY_DMA_IRQ_STATUS 0x00000002 -#define SIS_GISR_AUDIO_WAVE_ENGINE_IRQ_STATUS 0x00000001 - -/* DMA Control Register */ -#define SIS_DMA_CSR 0x10 -#define SIS_DMA_CSR_PCI_SETTINGS 0x0000001d -#define SIS_DMA_CSR_CONCURRENT_ENABLE 0x00000200 -#define SIS_DMA_CSR_PIPELINE_ENABLE 0x00000100 -#define SIS_DMA_CSR_RX_DRAIN_ENABLE 0x00000010 -#define SIS_DMA_CSR_RX_FILL_ENABLE 0x00000008 -#define SIS_DMA_CSR_TX_DRAIN_ENABLE 0x00000004 -#define SIS_DMA_CSR_TX_LOWPRI_FILL_ENABLE 0x00000002 -#define SIS_DMA_CSR_TX_HIPRI_FILL_ENABLE 0x00000001 - -/* Playback Channel Start Registers */ -#define SIS_PLAY_START_A_REG 0x14 -#define SIS_PLAY_START_B_REG 0x18 - -/* Playback Channel Stop Registers */ -#define SIS_PLAY_STOP_A_REG 0x1c -#define SIS_PLAY_STOP_B_REG 0x20 - -/* Recording Channel Start Register */ -#define SIS_RECORD_START_REG 0x24 - -/* Recording Channel Stop Register */ -#define SIS_RECORD_STOP_REG 0x28 - -/* Playback Interrupt Status Registers */ -#define SIS_PISR_A 0x2c -#define SIS_PISR_B 0x30 - -/* Recording Interrupt Status Register */ -#define SIS_RISR 0x34 - -/* AC97 AC-link Playback Source Register */ -#define SIS_AC97_PSR 0x40 -#define SIS_AC97_PSR_MODEM_HEADSET_SRC_MIXER 0x0f000000 -#define SIS_AC97_PSR_MODEM_LINE2_SRC_MIXER 0x00f00000 -#define SIS_AC97_PSR_MODEM_LINE1_SRC_MIXER 0x000f0000 -#define SIS_AC97_PSR_PCM_LFR_SRC_MIXER 0x0000f000 -#define SIS_AC97_PSR_PCM_SURROUND_SRC_MIXER 0x00000f00 -#define SIS_AC97_PSR_PCM_CENTER_SRC_MIXER 0x000000f0 -#define SIS_AC97_PSR_PCM_LR_SRC_MIXER 0x0000000f - -/* AC97 AC-link Command Register */ -#define SIS_AC97_CMD 0x50 -#define SIS_AC97_CMD_DATA_MASK 0xffff0000 -#define SIS_AC97_CMD_REG_MASK 0x0000ff00 -#define SIS_AC97_CMD_CODEC3_READ 0x0000000d -#define SIS_AC97_CMD_CODEC3_WRITE 0x0000000c -#define SIS_AC97_CMD_CODEC2_READ 0x0000000b -#define SIS_AC97_CMD_CODEC2_WRITE 0x0000000a -#define SIS_AC97_CMD_CODEC_READ 0x00000009 -#define SIS_AC97_CMD_CODEC_WRITE 0x00000008 -#define SIS_AC97_CMD_CODEC_WARM_RESET 0x00000005 -#define SIS_AC97_CMD_CODEC_COLD_RESET 0x00000004 -#define SIS_AC97_CMD_DONE 0x00000000 - -/* AC97 AC-link Semaphore Register */ -#define SIS_AC97_SEMA 0x54 -#define SIS_AC97_SEMA_BUSY 0x00000001 -#define SIS_AC97_SEMA_RELEASE 0x00000000 - -/* AC97 AC-link Status Register */ -#define SIS_AC97_STATUS 0x58 -#define SIS_AC97_STATUS_AUDIO_D2_INACT_SECS 0x03f00000 -#define SIS_AC97_STATUS_MODEM_ALIVE 0x00002000 -#define SIS_AC97_STATUS_AUDIO_ALIVE 0x00001000 -#define SIS_AC97_STATUS_CODEC3_READY 0x00000400 -#define SIS_AC97_STATUS_CODEC2_READY 0x00000200 -#define SIS_AC97_STATUS_CODEC_READY 0x00000100 -#define SIS_AC97_STATUS_WARM_RESET 0x00000080 -#define SIS_AC97_STATUS_COLD_RESET 0x00000040 -#define SIS_AC97_STATUS_POWERED_DOWN 0x00000020 -#define SIS_AC97_STATUS_NORMAL 0x00000010 -#define SIS_AC97_STATUS_READ_EXPIRED 0x00000004 -#define SIS_AC97_STATUS_SEMAPHORE 0x00000002 -#define SIS_AC97_STATUS_BUSY 0x00000001 - -/* AC97 AC-link Audio Configuration Register */ -#define SIS_AC97_CONF 0x5c -#define SIS_AC97_CONF_AUDIO_ALIVE 0x80000000 -#define SIS_AC97_CONF_WARM_RESET_ENABLE 0x40000000 -#define SIS_AC97_CONF_PR6_ENABLE 0x20000000 -#define SIS_AC97_CONF_PR5_ENABLE 0x10000000 -#define SIS_AC97_CONF_PR4_ENABLE 0x08000000 -#define SIS_AC97_CONF_PR3_ENABLE 0x04000000 -#define SIS_AC97_CONF_PR2_PR7_ENABLE 0x02000000 -#define SIS_AC97_CONF_PR0_PR1_ENABLE 0x01000000 -#define SIS_AC97_CONF_AUTO_PM_ENABLE 0x00800000 -#define SIS_AC97_CONF_PCM_LFE_ENABLE 0x00080000 -#define SIS_AC97_CONF_PCM_SURROUND_ENABLE 0x00040000 -#define SIS_AC97_CONF_PCM_CENTER_ENABLE 0x00020000 -#define SIS_AC97_CONF_PCM_LR_ENABLE 0x00010000 -#define SIS_AC97_CONF_PCM_CAP_MIC_ENABLE 0x00002000 -#define SIS_AC97_CONF_PCM_CAP_LR_ENABLE 0x00001000 -#define SIS_AC97_CONF_PCM_CAP_MIC_FROM_CODEC3 0x00000200 -#define SIS_AC97_CONF_PCM_CAP_LR_FROM_CODEC3 0x00000100 -#define SIS_AC97_CONF_CODEC3_PM_VRM 0x00000080 -#define SIS_AC97_CONF_CODEC_PM_VRM 0x00000040 -#define SIS_AC97_CONF_CODEC3_VRA_ENABLE 0x00000020 -#define SIS_AC97_CONF_CODEC_VRA_ENABLE 0x00000010 -#define SIS_AC97_CONF_CODEC3_PM_EAC 0x00000008 -#define SIS_AC97_CONF_CODEC_PM_EAC 0x00000004 -#define SIS_AC97_CONF_CODEC3_EXISTS 0x00000002 -#define SIS_AC97_CONF_CODEC_EXISTS 0x00000001 - -/* Playback Channel Sync Group registers */ -#define SIS_PLAY_SYNC_GROUP_A 0x80 -#define SIS_PLAY_SYNC_GROUP_B 0x84 -#define SIS_PLAY_SYNC_GROUP_C 0x88 -#define SIS_PLAY_SYNC_GROUP_D 0x8c -#define SIS_MIXER_SYNC_GROUP 0x90 - -/* Wave Engine Config and Control Register */ -#define SIS_WECCR 0xa0 -#define SIS_WECCR_TESTMODE_MASK 0x00300000 -#define SIS_WECCR_TESTMODE_NORMAL 0x00000000 -#define SIS_WECCR_TESTMODE_BYPASS_NSO_ALPHA 0x00100000 -#define SIS_WECCR_TESTMODE_BYPASS_FC 0x00200000 -#define SIS_WECCR_TESTMODE_BYPASS_WOL 0x00300000 -#define SIS_WECCR_RESONANCE_DELAY_MASK 0x00060000 -#define SIS_WECCR_RESONANCE_DELAY_NONE 0x00000000 -#define SIS_WECCR_RESONANCE_DELAY_FC_1F00 0x00020000 -#define SIS_WECCR_RESONANCE_DELAY_FC_1E00 0x00040000 -#define SIS_WECCR_RESONANCE_DELAY_FC_1C00 0x00060000 -#define SIS_WECCR_IGNORE_CHANNEL_PARMS 0x00010000 -#define SIS_WECCR_COMMAND_CHANNEL_ID_MASK 0x0003ff00 -#define SIS_WECCR_COMMAND_MASK 0x00000007 -#define SIS_WECCR_COMMAND_NONE 0x00000000 -#define SIS_WECCR_COMMAND_DONE 0x00000000 -#define SIS_WECCR_COMMAND_PAUSE 0x00000001 -#define SIS_WECCR_COMMAND_TOGGLE_VEG 0x00000002 -#define SIS_WECCR_COMMAND_TOGGLE_MEG 0x00000003 -#define SIS_WECCR_COMMAND_TOGGLE_VEG_MEG 0x00000004 - -/* Wave Engine Volume Control Register */ -#define SIS_WEVCR 0xa4 -#define SIS_WEVCR_LEFT_MUSIC_ATTENUATION_MASK 0xff000000 -#define SIS_WEVCR_RIGHT_MUSIC_ATTENUATION_MASK 0x00ff0000 -#define SIS_WEVCR_LEFT_WAVE_ATTENUATION_MASK 0x0000ff00 -#define SIS_WEVCR_RIGHT_WAVE_ATTENUATION_MASK 0x000000ff - -/* Wave Engine Interrupt Status Registers */ -#define SIS_WEISR_A 0xa8 -#define SIS_WEISR_B 0xac - - -/* Playback DMA parameters (parameter RAM) */ -#define SIS_PLAY_DMA_OFFSET 0x0000 -#define SIS_PLAY_DMA_SIZE 0x10 -#define SIS_PLAY_DMA_ADDR(addr, num) \ - ((num * SIS_PLAY_DMA_SIZE) + (addr) + SIS_PLAY_DMA_OFFSET) - -#define SIS_PLAY_DMA_FORMAT_CSO 0x00 -#define SIS_PLAY_DMA_FORMAT_UNSIGNED 0x00080000 -#define SIS_PLAY_DMA_FORMAT_8BIT 0x00040000 -#define SIS_PLAY_DMA_FORMAT_MONO 0x00020000 -#define SIS_PLAY_DMA_CSO_MASK 0x0000ffff -#define SIS_PLAY_DMA_BASE 0x04 -#define SIS_PLAY_DMA_CONTROL 0x08 -#define SIS_PLAY_DMA_STOP_AT_SSO 0x04000000 -#define SIS_PLAY_DMA_RELEASE 0x02000000 -#define SIS_PLAY_DMA_LOOP 0x01000000 -#define SIS_PLAY_DMA_INTR_AT_SSO 0x00080000 -#define SIS_PLAY_DMA_INTR_AT_ESO 0x00040000 -#define SIS_PLAY_DMA_INTR_AT_LEO 0x00020000 -#define SIS_PLAY_DMA_INTR_AT_MLP 0x00010000 -#define SIS_PLAY_DMA_LEO_MASK 0x0000ffff -#define SIS_PLAY_DMA_SSO_ESO 0x0c -#define SIS_PLAY_DMA_SSO_MASK 0xffff0000 -#define SIS_PLAY_DMA_ESO_MASK 0x0000ffff - -/* Capture DMA parameters (parameter RAM) */ -#define SIS_CAPTURE_DMA_OFFSET 0x0800 -#define SIS_CAPTURE_DMA_SIZE 0x10 -#define SIS_CAPTURE_DMA_ADDR(addr, num) \ - ((num * SIS_CAPTURE_DMA_SIZE) + (addr) + SIS_CAPTURE_DMA_OFFSET) - -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_0 0 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_1 1 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_2 2 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_3 3 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_4 4 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_5 5 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_6 6 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_7 7 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_8 8 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_9 9 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_10 10 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_11 11 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_12 12 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_13 13 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_14 14 -#define SIS_CAPTURE_CHAN_MIXER_ROUTE_BACK_15 15 -#define SIS_CAPTURE_CHAN_AC97_PCM_IN 16 -#define SIS_CAPTURE_CHAN_AC97_MIC_IN 17 -#define SIS_CAPTURE_CHAN_AC97_LINE1_IN 18 -#define SIS_CAPTURE_CHAN_AC97_LINE2_IN 19 -#define SIS_CAPTURE_CHAN_AC97_HANDSE_IN 20 - -#define SIS_CAPTURE_DMA_FORMAT_CSO 0x00 -#define SIS_CAPTURE_DMA_MONO_MODE_MASK 0xc0000000 -#define SIS_CAPTURE_DMA_MONO_MODE_AVG 0x00000000 -#define SIS_CAPTURE_DMA_MONO_MODE_LEFT 0x40000000 -#define SIS_CAPTURE_DMA_MONO_MODE_RIGHT 0x80000000 -#define SIS_CAPTURE_DMA_FORMAT_UNSIGNED 0x00080000 -#define SIS_CAPTURE_DMA_FORMAT_8BIT 0x00040000 -#define SIS_CAPTURE_DMA_FORMAT_MONO 0x00020000 -#define SIS_CAPTURE_DMA_CSO_MASK 0x0000ffff -#define SIS_CAPTURE_DMA_BASE 0x04 -#define SIS_CAPTURE_DMA_CONTROL 0x08 -#define SIS_CAPTURE_DMA_STOP_AT_SSO 0x04000000 -#define SIS_CAPTURE_DMA_RELEASE 0x02000000 -#define SIS_CAPTURE_DMA_LOOP 0x01000000 -#define SIS_CAPTURE_DMA_INTR_AT_LEO 0x00020000 -#define SIS_CAPTURE_DMA_INTR_AT_MLP 0x00010000 -#define SIS_CAPTURE_DMA_LEO_MASK 0x0000ffff -#define SIS_CAPTURE_DMA_RESERVED 0x0c - - -/* Mixer routing list start pointer (parameter RAM) */ -#define SIS_MIXER_START_OFFSET 0x1000 -#define SIS_MIXER_START_SIZE 0x04 -#define SIS_MIXER_START_ADDR(addr, num) \ - ((num * SIS_MIXER_START_SIZE) + (addr) + SIS_MIXER_START_OFFSET) - -#define SIS_MIXER_START_MASK 0x0000007f - -/* Mixer routing table (parameter RAM) */ -#define SIS_MIXER_OFFSET 0x1400 -#define SIS_MIXER_SIZE 0x04 -#define SIS_MIXER_ADDR(addr, num) \ - ((num * SIS_MIXER_SIZE) + (addr) + SIS_MIXER_OFFSET) - -#define SIS_MIXER_RIGHT_ATTENUTATION_MASK 0xff000000 -#define SIS_MIXER_RIGHT_NO_ATTEN 0xff000000 -#define SIS_MIXER_LEFT_ATTENUTATION_MASK 0x00ff0000 -#define SIS_MIXER_LEFT_NO_ATTEN 0x00ff0000 -#define SIS_MIXER_NEXT_ENTRY_MASK 0x00007f00 -#define SIS_MIXER_NEXT_ENTRY_NONE 0x00000000 -#define SIS_MIXER_DEST_MASK 0x0000007f -#define SIS_MIXER_DEST_0 0x00000020 -#define SIS_MIXER_DEST_1 0x00000021 -#define SIS_MIXER_DEST_2 0x00000022 -#define SIS_MIXER_DEST_3 0x00000023 -#define SIS_MIXER_DEST_4 0x00000024 -#define SIS_MIXER_DEST_5 0x00000025 -#define SIS_MIXER_DEST_6 0x00000026 -#define SIS_MIXER_DEST_7 0x00000027 -#define SIS_MIXER_DEST_8 0x00000028 -#define SIS_MIXER_DEST_9 0x00000029 -#define SIS_MIXER_DEST_10 0x0000002a -#define SIS_MIXER_DEST_11 0x0000002b -#define SIS_MIXER_DEST_12 0x0000002c -#define SIS_MIXER_DEST_13 0x0000002d -#define SIS_MIXER_DEST_14 0x0000002e -#define SIS_MIXER_DEST_15 0x0000002f - -/* Wave Engine Control Parameters (parameter RAM) */ -#define SIS_WAVE_OFFSET 0x2000 -#define SIS_WAVE_SIZE 0x40 -#define SIS_WAVE_ADDR(addr, num) \ - ((num * SIS_WAVE_SIZE) + (addr) + SIS_WAVE_OFFSET) - -#define SIS_WAVE_GENERAL 0x00 -#define SIS_WAVE_GENERAL_WAVE_VOLUME 0x80000000 -#define SIS_WAVE_GENERAL_MUSIC_VOLUME 0x00000000 -#define SIS_WAVE_GENERAL_VOLUME_MASK 0x7f000000 -#define SIS_WAVE_GENERAL_ARTICULATION 0x04 -#define SIS_WAVE_GENERAL_ARTICULATION_DELTA_MASK 0x3fff0000 -#define SIS_WAVE_ARTICULATION 0x08 -#define SIS_WAVE_TIMER 0x0c -#define SIS_WAVE_GENERATOR 0x10 -#define SIS_WAVE_CHANNEL_CONTROL 0x14 -#define SIS_WAVE_CHANNEL_CONTROL_FIRST_SAMPLE 0x80000000 -#define SIS_WAVE_CHANNEL_CONTROL_AMP_ENABLE 0x40000000 -#define SIS_WAVE_CHANNEL_CONTROL_FILTER_ENABLE 0x20000000 -#define SIS_WAVE_CHANNEL_CONTROL_INTERPOLATE_ENABLE 0x10000000 -#define SIS_WAVE_LFO_EG_CONTROL 0x18 -#define SIS_WAVE_LFO_EG_CONTROL_2 0x1c -#define SIS_WAVE_LFO_EG_CONTROL_3 0x20 -#define SIS_WAVE_LFO_EG_CONTROL_4 0x24 - -#endif /* __sis7019_h__ */ diff --git a/ANDROID_3.4.5/sound/pci/sonicvibes.c b/ANDROID_3.4.5/sound/pci/sonicvibes.c deleted file mode 100644 index 54cc8020..00000000 --- a/ANDROID_3.4.5/sound/pci/sonicvibes.c +++ /dev/null @@ -1,1551 +0,0 @@ -/* - * Driver for S3 SonicVibes soundcard - * Copyright (c) by Jaroslav Kysela - * - * BUGS: - * It looks like 86c617 rev 3 doesn't supports DDMA buffers above 16MB? - * Driver sometimes hangs... Nobody knows why at this moment... - * - * 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 -#include -#include -#include -#include -#include -#include - -#include - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("S3 SonicVibes PCI"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static bool reverb[SNDRV_CARDS]; -static bool mge[SNDRV_CARDS]; -static unsigned int dmaio = 0x7a00; /* DDMA i/o address */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for S3 SonicVibes soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for S3 SonicVibes soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable S3 SonicVibes soundcard."); -module_param_array(reverb, bool, NULL, 0444); -MODULE_PARM_DESC(reverb, "Enable reverb (SRAM is present) for S3 SonicVibes soundcard."); -module_param_array(mge, bool, NULL, 0444); -MODULE_PARM_DESC(mge, "MIC Gain Enable for S3 SonicVibes soundcard."); -module_param(dmaio, uint, 0444); -MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard."); - -/* - * Enhanced port direct registers - */ - -#define SV_REG(sonic, x) ((sonic)->enh_port + SV_REG_##x) - -#define SV_REG_CONTROL 0x00 /* R/W: CODEC/Mixer control register */ -#define SV_ENHANCED 0x01 /* audio mode select - enhanced mode */ -#define SV_TEST 0x02 /* test bit */ -#define SV_REVERB 0x04 /* reverb enable */ -#define SV_WAVETABLE 0x08 /* wavetable active / FM active if not set */ -#define SV_INTA 0x20 /* INTA driving - should be always 1 */ -#define SV_RESET 0x80 /* reset chip */ -#define SV_REG_IRQMASK 0x01 /* R/W: CODEC/Mixer interrupt mask register */ -#define SV_DMAA_MASK 0x01 /* mask DMA-A interrupt */ -#define SV_DMAC_MASK 0x04 /* mask DMA-C interrupt */ -#define SV_SPEC_MASK 0x08 /* special interrupt mask - should be always masked */ -#define SV_UD_MASK 0x40 /* Up/Down button interrupt mask */ -#define SV_MIDI_MASK 0x80 /* mask MIDI interrupt */ -#define SV_REG_STATUS 0x02 /* R/O: CODEC/Mixer status register */ -#define SV_DMAA_IRQ 0x01 /* DMA-A interrupt */ -#define SV_DMAC_IRQ 0x04 /* DMA-C interrupt */ -#define SV_SPEC_IRQ 0x08 /* special interrupt */ -#define SV_UD_IRQ 0x40 /* Up/Down interrupt */ -#define SV_MIDI_IRQ 0x80 /* MIDI interrupt */ -#define SV_REG_INDEX 0x04 /* R/W: CODEC/Mixer index address register */ -#define SV_MCE 0x40 /* mode change enable */ -#define SV_TRD 0x80 /* DMA transfer request disabled */ -#define SV_REG_DATA 0x05 /* R/W: CODEC/Mixer index data register */ - -/* - * Enhanced port indirect registers - */ - -#define SV_IREG_LEFT_ADC 0x00 /* Left ADC Input Control */ -#define SV_IREG_RIGHT_ADC 0x01 /* Right ADC Input Control */ -#define SV_IREG_LEFT_AUX1 0x02 /* Left AUX1 Input Control */ -#define SV_IREG_RIGHT_AUX1 0x03 /* Right AUX1 Input Control */ -#define SV_IREG_LEFT_CD 0x04 /* Left CD Input Control */ -#define SV_IREG_RIGHT_CD 0x05 /* Right CD Input Control */ -#define SV_IREG_LEFT_LINE 0x06 /* Left Line Input Control */ -#define SV_IREG_RIGHT_LINE 0x07 /* Right Line Input Control */ -#define SV_IREG_MIC 0x08 /* MIC Input Control */ -#define SV_IREG_GAME_PORT 0x09 /* Game Port Control */ -#define SV_IREG_LEFT_SYNTH 0x0a /* Left Synth Input Control */ -#define SV_IREG_RIGHT_SYNTH 0x0b /* Right Synth Input Control */ -#define SV_IREG_LEFT_AUX2 0x0c /* Left AUX2 Input Control */ -#define SV_IREG_RIGHT_AUX2 0x0d /* Right AUX2 Input Control */ -#define SV_IREG_LEFT_ANALOG 0x0e /* Left Analog Mixer Output Control */ -#define SV_IREG_RIGHT_ANALOG 0x0f /* Right Analog Mixer Output Control */ -#define SV_IREG_LEFT_PCM 0x10 /* Left PCM Input Control */ -#define SV_IREG_RIGHT_PCM 0x11 /* Right PCM Input Control */ -#define SV_IREG_DMA_DATA_FMT 0x12 /* DMA Data Format */ -#define SV_IREG_PC_ENABLE 0x13 /* Playback/Capture Enable Register */ -#define SV_IREG_UD_BUTTON 0x14 /* Up/Down Button Register */ -#define SV_IREG_REVISION 0x15 /* Revision */ -#define SV_IREG_ADC_OUTPUT_CTRL 0x16 /* ADC Output Control */ -#define SV_IREG_DMA_A_UPPER 0x18 /* DMA A Upper Base Count */ -#define SV_IREG_DMA_A_LOWER 0x19 /* DMA A Lower Base Count */ -#define SV_IREG_DMA_C_UPPER 0x1c /* DMA C Upper Base Count */ -#define SV_IREG_DMA_C_LOWER 0x1d /* DMA C Lower Base Count */ -#define SV_IREG_PCM_RATE_LOW 0x1e /* PCM Sampling Rate Low Byte */ -#define SV_IREG_PCM_RATE_HIGH 0x1f /* PCM Sampling Rate High Byte */ -#define SV_IREG_SYNTH_RATE_LOW 0x20 /* Synthesizer Sampling Rate Low Byte */ -#define SV_IREG_SYNTH_RATE_HIGH 0x21 /* Synthesizer Sampling Rate High Byte */ -#define SV_IREG_ADC_CLOCK 0x22 /* ADC Clock Source Selection */ -#define SV_IREG_ADC_ALT_RATE 0x23 /* ADC Alternative Sampling Rate Selection */ -#define SV_IREG_ADC_PLL_M 0x24 /* ADC PLL M Register */ -#define SV_IREG_ADC_PLL_N 0x25 /* ADC PLL N Register */ -#define SV_IREG_SYNTH_PLL_M 0x26 /* Synthesizer PLL M Register */ -#define SV_IREG_SYNTH_PLL_N 0x27 /* Synthesizer PLL N Register */ -#define SV_IREG_MPU401 0x2a /* MPU-401 UART Operation */ -#define SV_IREG_DRIVE_CTRL 0x2b /* Drive Control */ -#define SV_IREG_SRS_SPACE 0x2c /* SRS Space Control */ -#define SV_IREG_SRS_CENTER 0x2d /* SRS Center Control */ -#define SV_IREG_WAVE_SOURCE 0x2e /* Wavetable Sample Source Select */ -#define SV_IREG_ANALOG_POWER 0x30 /* Analog Power Down Control */ -#define SV_IREG_DIGITAL_POWER 0x31 /* Digital Power Down Control */ - -#define SV_IREG_ADC_PLL SV_IREG_ADC_PLL_M -#define SV_IREG_SYNTH_PLL SV_IREG_SYNTH_PLL_M - -/* - * DMA registers - */ - -#define SV_DMA_ADDR0 0x00 -#define SV_DMA_ADDR1 0x01 -#define SV_DMA_ADDR2 0x02 -#define SV_DMA_ADDR3 0x03 -#define SV_DMA_COUNT0 0x04 -#define SV_DMA_COUNT1 0x05 -#define SV_DMA_COUNT2 0x06 -#define SV_DMA_MODE 0x0b -#define SV_DMA_RESET 0x0d -#define SV_DMA_MASK 0x0f - -/* - * Record sources - */ - -#define SV_RECSRC_RESERVED (0x00<<5) -#define SV_RECSRC_CD (0x01<<5) -#define SV_RECSRC_DAC (0x02<<5) -#define SV_RECSRC_AUX2 (0x03<<5) -#define SV_RECSRC_LINE (0x04<<5) -#define SV_RECSRC_AUX1 (0x05<<5) -#define SV_RECSRC_MIC (0x06<<5) -#define SV_RECSRC_OUT (0x07<<5) - -/* - * constants - */ - -#define SV_FULLRATE 48000 -#define SV_REFFREQUENCY 24576000 -#define SV_ADCMULT 512 - -#define SV_MODE_PLAY 1 -#define SV_MODE_CAPTURE 2 - -/* - - */ - -struct sonicvibes { - unsigned long dma1size; - unsigned long dma2size; - int irq; - - unsigned long sb_port; - unsigned long enh_port; - unsigned long synth_port; - unsigned long midi_port; - unsigned long game_port; - unsigned int dmaa_port; - struct resource *res_dmaa; - unsigned int dmac_port; - struct resource *res_dmac; - - unsigned char enable; - unsigned char irqmask; - unsigned char revision; - unsigned char format; - unsigned char srs_space; - unsigned char srs_center; - unsigned char mpu_switch; - unsigned char wave_source; - - unsigned int mode; - - struct pci_dev *pci; - struct snd_card *card; - struct snd_pcm *pcm; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - struct snd_rawmidi *rmidi; - struct snd_hwdep *fmsynth; /* S3FM */ - - spinlock_t reg_lock; - - unsigned int p_dma_size; - unsigned int c_dma_size; - - struct snd_kcontrol *master_mute; - struct snd_kcontrol *master_volume; - -#ifdef SUPPORT_JOYSTICK - struct gameport *gameport; -#endif -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_sonic_ids) = { - { PCI_VDEVICE(S3, 0xca00), 0, }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_sonic_ids); - -static struct snd_ratden sonicvibes_adc_clock = { - .num_min = 4000 * 65536, - .num_max = 48000UL * 65536, - .num_step = 1, - .den = 65536, -}; -static struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = { - .nrats = 1, - .rats = &sonicvibes_adc_clock, -}; - -/* - * common I/O routines - */ - -static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic, - unsigned int addr, - unsigned int count) -{ - count--; - outl(addr, sonic->dmaa_port + SV_DMA_ADDR0); - outl(count, sonic->dmaa_port + SV_DMA_COUNT0); - outb(0x18, sonic->dmaa_port + SV_DMA_MODE); -#if 0 - printk(KERN_DEBUG "program dmaa: addr = 0x%x, paddr = 0x%x\n", - addr, inl(sonic->dmaa_port + SV_DMA_ADDR0)); -#endif -} - -static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic, - unsigned int addr, - unsigned int count) -{ - /* note: dmac is working in word mode!!! */ - count >>= 1; - count--; - outl(addr, sonic->dmac_port + SV_DMA_ADDR0); - outl(count, sonic->dmac_port + SV_DMA_COUNT0); - outb(0x14, sonic->dmac_port + SV_DMA_MODE); -#if 0 - printk(KERN_DEBUG "program dmac: addr = 0x%x, paddr = 0x%x\n", - addr, inl(sonic->dmac_port + SV_DMA_ADDR0)); -#endif -} - -static inline unsigned int snd_sonicvibes_getdmaa(struct sonicvibes * sonic) -{ - return (inl(sonic->dmaa_port + SV_DMA_COUNT0) & 0xffffff) + 1; -} - -static inline unsigned int snd_sonicvibes_getdmac(struct sonicvibes * sonic) -{ - /* note: dmac is working in word mode!!! */ - return ((inl(sonic->dmac_port + SV_DMA_COUNT0) & 0xffffff) + 1) << 1; -} - -static void snd_sonicvibes_out1(struct sonicvibes * sonic, - unsigned char reg, - unsigned char value) -{ - outb(reg, SV_REG(sonic, INDEX)); - udelay(10); - outb(value, SV_REG(sonic, DATA)); - udelay(10); -} - -static void snd_sonicvibes_out(struct sonicvibes * sonic, - unsigned char reg, - unsigned char value) -{ - unsigned long flags; - - spin_lock_irqsave(&sonic->reg_lock, flags); - outb(reg, SV_REG(sonic, INDEX)); - udelay(10); - outb(value, SV_REG(sonic, DATA)); - udelay(10); - spin_unlock_irqrestore(&sonic->reg_lock, flags); -} - -static unsigned char snd_sonicvibes_in1(struct sonicvibes * sonic, unsigned char reg) -{ - unsigned char value; - - outb(reg, SV_REG(sonic, INDEX)); - udelay(10); - value = inb(SV_REG(sonic, DATA)); - udelay(10); - return value; -} - -static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char reg) -{ - unsigned long flags; - unsigned char value; - - spin_lock_irqsave(&sonic->reg_lock, flags); - outb(reg, SV_REG(sonic, INDEX)); - udelay(10); - value = inb(SV_REG(sonic, DATA)); - udelay(10); - spin_unlock_irqrestore(&sonic->reg_lock, flags); - return value; -} - -#if 0 -static void snd_sonicvibes_debug(struct sonicvibes * sonic) -{ - printk(KERN_DEBUG - "SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX))); - printk(" STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS))); - printk(KERN_DEBUG - " 0x00: left input = 0x%02x ", snd_sonicvibes_in(sonic, 0x00)); - printk(" 0x20: synth rate low = 0x%02x\n", snd_sonicvibes_in(sonic, 0x20)); - printk(KERN_DEBUG - " 0x01: right input = 0x%02x ", snd_sonicvibes_in(sonic, 0x01)); - printk(" 0x21: synth rate high = 0x%02x\n", snd_sonicvibes_in(sonic, 0x21)); - printk(KERN_DEBUG - " 0x02: left AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x02)); - printk(" 0x22: ADC clock = 0x%02x\n", snd_sonicvibes_in(sonic, 0x22)); - printk(KERN_DEBUG - " 0x03: right AUX1 = 0x%02x ", snd_sonicvibes_in(sonic, 0x03)); - printk(" 0x23: ADC alt rate = 0x%02x\n", snd_sonicvibes_in(sonic, 0x23)); - printk(KERN_DEBUG - " 0x04: left CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x04)); - printk(" 0x24: ADC pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x24)); - printk(KERN_DEBUG - " 0x05: right CD = 0x%02x ", snd_sonicvibes_in(sonic, 0x05)); - printk(" 0x25: ADC pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x25)); - printk(KERN_DEBUG - " 0x06: left line = 0x%02x ", snd_sonicvibes_in(sonic, 0x06)); - printk(" 0x26: Synth pll M = 0x%02x\n", snd_sonicvibes_in(sonic, 0x26)); - printk(KERN_DEBUG - " 0x07: right line = 0x%02x ", snd_sonicvibes_in(sonic, 0x07)); - printk(" 0x27: Synth pll N = 0x%02x\n", snd_sonicvibes_in(sonic, 0x27)); - printk(KERN_DEBUG - " 0x08: MIC = 0x%02x ", snd_sonicvibes_in(sonic, 0x08)); - printk(" 0x28: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x28)); - printk(KERN_DEBUG - " 0x09: Game port = 0x%02x ", snd_sonicvibes_in(sonic, 0x09)); - printk(" 0x29: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x29)); - printk(KERN_DEBUG - " 0x0a: left synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0a)); - printk(" 0x2a: MPU401 = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2a)); - printk(KERN_DEBUG - " 0x0b: right synth = 0x%02x ", snd_sonicvibes_in(sonic, 0x0b)); - printk(" 0x2b: drive ctrl = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2b)); - printk(KERN_DEBUG - " 0x0c: left AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0c)); - printk(" 0x2c: SRS space = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2c)); - printk(KERN_DEBUG - " 0x0d: right AUX2 = 0x%02x ", snd_sonicvibes_in(sonic, 0x0d)); - printk(" 0x2d: SRS center = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2d)); - printk(KERN_DEBUG - " 0x0e: left analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0e)); - printk(" 0x2e: wave source = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2e)); - printk(KERN_DEBUG - " 0x0f: right analog = 0x%02x ", snd_sonicvibes_in(sonic, 0x0f)); - printk(" 0x2f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x2f)); - printk(KERN_DEBUG - " 0x10: left PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x10)); - printk(" 0x30: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x30)); - printk(KERN_DEBUG - " 0x11: right PCM = 0x%02x ", snd_sonicvibes_in(sonic, 0x11)); - printk(" 0x31: analog power = 0x%02x\n", snd_sonicvibes_in(sonic, 0x31)); - printk(KERN_DEBUG - " 0x12: DMA data format = 0x%02x ", snd_sonicvibes_in(sonic, 0x12)); - printk(" 0x32: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x32)); - printk(KERN_DEBUG - " 0x13: P/C enable = 0x%02x ", snd_sonicvibes_in(sonic, 0x13)); - printk(" 0x33: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x33)); - printk(KERN_DEBUG - " 0x14: U/D button = 0x%02x ", snd_sonicvibes_in(sonic, 0x14)); - printk(" 0x34: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x34)); - printk(KERN_DEBUG - " 0x15: revision = 0x%02x ", snd_sonicvibes_in(sonic, 0x15)); - printk(" 0x35: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x35)); - printk(KERN_DEBUG - " 0x16: ADC output ctrl = 0x%02x ", snd_sonicvibes_in(sonic, 0x16)); - printk(" 0x36: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x36)); - printk(KERN_DEBUG - " 0x17: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x17)); - printk(" 0x37: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x37)); - printk(KERN_DEBUG - " 0x18: DMA A upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x18)); - printk(" 0x38: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x38)); - printk(KERN_DEBUG - " 0x19: DMA A lower cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x19)); - printk(" 0x39: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x39)); - printk(KERN_DEBUG - " 0x1a: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1a)); - printk(" 0x3a: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3a)); - printk(KERN_DEBUG - " 0x1b: --- = 0x%02x ", snd_sonicvibes_in(sonic, 0x1b)); - printk(" 0x3b: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3b)); - printk(KERN_DEBUG - " 0x1c: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1c)); - printk(" 0x3c: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3c)); - printk(KERN_DEBUG - " 0x1d: DMA C upper cnt = 0x%02x ", snd_sonicvibes_in(sonic, 0x1d)); - printk(" 0x3d: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3d)); - printk(KERN_DEBUG - " 0x1e: PCM rate low = 0x%02x ", snd_sonicvibes_in(sonic, 0x1e)); - printk(" 0x3e: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3e)); - printk(KERN_DEBUG - " 0x1f: PCM rate high = 0x%02x ", snd_sonicvibes_in(sonic, 0x1f)); - printk(" 0x3f: --- = 0x%02x\n", snd_sonicvibes_in(sonic, 0x3f)); -} - -#endif - -static void snd_sonicvibes_setfmt(struct sonicvibes * sonic, - unsigned char mask, - unsigned char value) -{ - unsigned long flags; - - spin_lock_irqsave(&sonic->reg_lock, flags); - outb(SV_MCE | SV_IREG_DMA_DATA_FMT, SV_REG(sonic, INDEX)); - if (mask) { - sonic->format = inb(SV_REG(sonic, DATA)); - udelay(10); - } - sonic->format = (sonic->format & mask) | value; - outb(sonic->format, SV_REG(sonic, DATA)); - udelay(10); - outb(0, SV_REG(sonic, INDEX)); - udelay(10); - spin_unlock_irqrestore(&sonic->reg_lock, flags); -} - -static void snd_sonicvibes_pll(unsigned int rate, - unsigned int *res_r, - unsigned int *res_m, - unsigned int *res_n) -{ - unsigned int r, m = 0, n = 0; - unsigned int xm, xn, xr, xd, metric = ~0U; - - if (rate < 625000 / SV_ADCMULT) - rate = 625000 / SV_ADCMULT; - if (rate > 150000000 / SV_ADCMULT) - rate = 150000000 / SV_ADCMULT; - /* slight violation of specs, needed for continuous sampling rates */ - for (r = 0; rate < 75000000 / SV_ADCMULT; r += 0x20, rate <<= 1); - for (xn = 3; xn < 33; xn++) /* 35 */ - for (xm = 3; xm < 257; xm++) { - xr = ((SV_REFFREQUENCY / SV_ADCMULT) * xm) / xn; - if (xr >= rate) - xd = xr - rate; - else - xd = rate - xr; - if (xd < metric) { - metric = xd; - m = xm - 2; - n = xn - 2; - } - } - *res_r = r; - *res_m = m; - *res_n = n; -#if 0 - printk(KERN_DEBUG "metric = %i, xm = %i, xn = %i\n", metric, xm, xn); - printk(KERN_DEBUG "pll: m = 0x%x, r = 0x%x, n = 0x%x\n", reg, m, r, n); -#endif -} - -static void snd_sonicvibes_setpll(struct sonicvibes * sonic, - unsigned char reg, - unsigned int rate) -{ - unsigned long flags; - unsigned int r, m, n; - - snd_sonicvibes_pll(rate, &r, &m, &n); - if (sonic != NULL) { - spin_lock_irqsave(&sonic->reg_lock, flags); - snd_sonicvibes_out1(sonic, reg, m); - snd_sonicvibes_out1(sonic, reg + 1, r | n); - spin_unlock_irqrestore(&sonic->reg_lock, flags); - } -} - -static void snd_sonicvibes_set_adc_rate(struct sonicvibes * sonic, unsigned int rate) -{ - unsigned long flags; - unsigned int div; - unsigned char clock; - - div = 48000 / rate; - if (div > 8) - div = 8; - if ((48000 / div) == rate) { /* use the alternate clock */ - clock = 0x10; - } else { /* use the PLL source */ - clock = 0x00; - snd_sonicvibes_setpll(sonic, SV_IREG_ADC_PLL, rate); - } - spin_lock_irqsave(&sonic->reg_lock, flags); - snd_sonicvibes_out1(sonic, SV_IREG_ADC_ALT_RATE, (div - 1) << 4); - snd_sonicvibes_out1(sonic, SV_IREG_ADC_CLOCK, clock); - spin_unlock_irqrestore(&sonic->reg_lock, flags); -} - -static int snd_sonicvibes_hw_constraint_dac_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - unsigned int rate, div, r, m, n; - - if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min == - hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max) { - rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min; - div = 48000 / rate; - if (div > 8) - div = 8; - if ((48000 / div) == rate) { - params->rate_num = rate; - params->rate_den = 1; - } else { - snd_sonicvibes_pll(rate, &r, &m, &n); - snd_BUG_ON(SV_REFFREQUENCY % 16); - snd_BUG_ON(SV_ADCMULT % 512); - params->rate_num = (SV_REFFREQUENCY/16) * (n+2) * r; - params->rate_den = (SV_ADCMULT/512) * (m+2); - } - } - return 0; -} - -static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int rate) -{ - unsigned int div; - unsigned long flags; - - div = (rate * 65536 + SV_FULLRATE / 2) / SV_FULLRATE; - if (div > 65535) - div = 65535; - spin_lock_irqsave(&sonic->reg_lock, flags); - snd_sonicvibes_out1(sonic, SV_IREG_PCM_RATE_HIGH, div >> 8); - snd_sonicvibes_out1(sonic, SV_IREG_PCM_RATE_LOW, div); - spin_unlock_irqrestore(&sonic->reg_lock, flags); -} - -static int snd_sonicvibes_trigger(struct sonicvibes * sonic, int what, int cmd) -{ - int result = 0; - - spin_lock(&sonic->reg_lock); - if (cmd == SNDRV_PCM_TRIGGER_START) { - if (!(sonic->enable & what)) { - sonic->enable |= what; - snd_sonicvibes_out1(sonic, SV_IREG_PC_ENABLE, sonic->enable); - } - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - if (sonic->enable & what) { - sonic->enable &= ~what; - snd_sonicvibes_out1(sonic, SV_IREG_PC_ENABLE, sonic->enable); - } - } else { - result = -EINVAL; - } - spin_unlock(&sonic->reg_lock); - return result; -} - -static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id) -{ - struct sonicvibes *sonic = dev_id; - unsigned char status; - - status = inb(SV_REG(sonic, STATUS)); - if (!(status & (SV_DMAA_IRQ | SV_DMAC_IRQ | SV_MIDI_IRQ))) - return IRQ_NONE; - if (status == 0xff) { /* failure */ - outb(sonic->irqmask = ~0, SV_REG(sonic, IRQMASK)); - snd_printk(KERN_ERR "IRQ failure - interrupts disabled!!\n"); - return IRQ_HANDLED; - } - if (sonic->pcm) { - if (status & SV_DMAA_IRQ) - snd_pcm_period_elapsed(sonic->playback_substream); - if (status & SV_DMAC_IRQ) - snd_pcm_period_elapsed(sonic->capture_substream); - } - if (sonic->rmidi) { - if (status & SV_MIDI_IRQ) - snd_mpu401_uart_interrupt(irq, sonic->rmidi->private_data); - } - if (status & SV_UD_IRQ) { - unsigned char udreg; - int vol, oleft, oright, mleft, mright; - - spin_lock(&sonic->reg_lock); - udreg = snd_sonicvibes_in1(sonic, SV_IREG_UD_BUTTON); - vol = udreg & 0x3f; - if (!(udreg & 0x40)) - vol = -vol; - oleft = mleft = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ANALOG); - oright = mright = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ANALOG); - oleft &= 0x1f; - oright &= 0x1f; - oleft += vol; - if (oleft < 0) - oleft = 0; - if (oleft > 0x1f) - oleft = 0x1f; - oright += vol; - if (oright < 0) - oright = 0; - if (oright > 0x1f) - oright = 0x1f; - if (udreg & 0x80) { - mleft ^= 0x80; - mright ^= 0x80; - } - oleft |= mleft & 0x80; - oright |= mright & 0x80; - snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ANALOG, oleft); - snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ANALOG, oright); - spin_unlock(&sonic->reg_lock); - snd_ctl_notify(sonic->card, SNDRV_CTL_EVENT_MASK_VALUE, &sonic->master_mute->id); - snd_ctl_notify(sonic->card, SNDRV_CTL_EVENT_MASK_VALUE, &sonic->master_volume->id); - } - return IRQ_HANDLED; -} - -/* - * PCM part - */ - -static int snd_sonicvibes_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - return snd_sonicvibes_trigger(sonic, 1, cmd); -} - -static int snd_sonicvibes_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - return snd_sonicvibes_trigger(sonic, 2, cmd); -} - -static int snd_sonicvibes_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_sonicvibes_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_sonicvibes_playback_prepare(struct snd_pcm_substream *substream) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned char fmt = 0; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - sonic->p_dma_size = size; - count--; - if (runtime->channels > 1) - fmt |= 1; - if (snd_pcm_format_width(runtime->format) == 16) - fmt |= 2; - snd_sonicvibes_setfmt(sonic, ~3, fmt); - snd_sonicvibes_set_dac_rate(sonic, runtime->rate); - spin_lock_irq(&sonic->reg_lock); - snd_sonicvibes_setdmaa(sonic, runtime->dma_addr, size); - snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_UPPER, count >> 8); - snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_LOWER, count); - spin_unlock_irq(&sonic->reg_lock); - return 0; -} - -static int snd_sonicvibes_capture_prepare(struct snd_pcm_substream *substream) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned char fmt = 0; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - sonic->c_dma_size = size; - count >>= 1; - count--; - if (runtime->channels > 1) - fmt |= 0x10; - if (snd_pcm_format_width(runtime->format) == 16) - fmt |= 0x20; - snd_sonicvibes_setfmt(sonic, ~0x30, fmt); - snd_sonicvibes_set_adc_rate(sonic, runtime->rate); - spin_lock_irq(&sonic->reg_lock); - snd_sonicvibes_setdmac(sonic, runtime->dma_addr, size); - snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_UPPER, count >> 8); - snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_LOWER, count); - spin_unlock_irq(&sonic->reg_lock); - return 0; -} - -static snd_pcm_uframes_t snd_sonicvibes_playback_pointer(struct snd_pcm_substream *substream) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(sonic->enable & 1)) - return 0; - ptr = sonic->p_dma_size - snd_sonicvibes_getdmaa(sonic); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_sonicvibes_capture_pointer(struct snd_pcm_substream *substream) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - size_t ptr; - if (!(sonic->enable & 2)) - return 0; - ptr = sonic->c_dma_size - snd_sonicvibes_getdmac(sonic); - return bytes_to_frames(substream->runtime, ptr); -} - -static struct snd_pcm_hardware snd_sonicvibes_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 32, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_sonicvibes_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 32, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_sonicvibes_playback_open(struct snd_pcm_substream *substream) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - sonic->mode |= SV_MODE_PLAY; - sonic->playback_substream = substream; - runtime->hw = snd_sonicvibes_playback; - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, snd_sonicvibes_hw_constraint_dac_rate, NULL, SNDRV_PCM_HW_PARAM_RATE, -1); - return 0; -} - -static int snd_sonicvibes_capture_open(struct snd_pcm_substream *substream) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - sonic->mode |= SV_MODE_CAPTURE; - sonic->capture_substream = substream; - runtime->hw = snd_sonicvibes_capture; - snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &snd_sonicvibes_hw_constraints_adc_clock); - return 0; -} - -static int snd_sonicvibes_playback_close(struct snd_pcm_substream *substream) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - - sonic->playback_substream = NULL; - sonic->mode &= ~SV_MODE_PLAY; - return 0; -} - -static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream) -{ - struct sonicvibes *sonic = snd_pcm_substream_chip(substream); - - sonic->capture_substream = NULL; - sonic->mode &= ~SV_MODE_CAPTURE; - return 0; -} - -static struct snd_pcm_ops snd_sonicvibes_playback_ops = { - .open = snd_sonicvibes_playback_open, - .close = snd_sonicvibes_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sonicvibes_hw_params, - .hw_free = snd_sonicvibes_hw_free, - .prepare = snd_sonicvibes_playback_prepare, - .trigger = snd_sonicvibes_playback_trigger, - .pointer = snd_sonicvibes_playback_pointer, -}; - -static struct snd_pcm_ops snd_sonicvibes_capture_ops = { - .open = snd_sonicvibes_capture_open, - .close = snd_sonicvibes_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sonicvibes_hw_params, - .hw_free = snd_sonicvibes_hw_free, - .prepare = snd_sonicvibes_capture_prepare, - .trigger = snd_sonicvibes_capture_trigger, - .pointer = snd_sonicvibes_capture_pointer, -}; - -static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if ((err = snd_pcm_new(sonic->card, "s3_86c617", device, 1, 1, &pcm)) < 0) - return err; - if (snd_BUG_ON(!pcm)) - return -EINVAL; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sonicvibes_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sonicvibes_capture_ops); - - pcm->private_data = sonic; - pcm->info_flags = 0; - strcpy(pcm->name, "S3 SonicVibes"); - sonic->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(sonic->pci), 64*1024, 128*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* - * Mixer part - */ - -#define SONICVIBES_MUX(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_sonicvibes_info_mux, \ - .get = snd_sonicvibes_get_mux, .put = snd_sonicvibes_put_mux } - -static int snd_sonicvibes_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[7] = { - "CD", "PCM", "Aux1", "Line", "Aux0", "Mic", "Mix" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - uinfo->value.enumerated.items = 7; - if (uinfo->value.enumerated.item >= 7) - uinfo->value.enumerated.item = 6; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_sonicvibes_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&sonic->reg_lock); - ucontrol->value.enumerated.item[0] = ((snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC) & SV_RECSRC_OUT) >> 5) - 1; - ucontrol->value.enumerated.item[1] = ((snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC) & SV_RECSRC_OUT) >> 5) - 1; - spin_unlock_irq(&sonic->reg_lock); - return 0; -} - -static int snd_sonicvibes_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol); - unsigned short left, right, oval1, oval2; - int change; - - if (ucontrol->value.enumerated.item[0] >= 7 || - ucontrol->value.enumerated.item[1] >= 7) - return -EINVAL; - left = (ucontrol->value.enumerated.item[0] + 1) << 5; - right = (ucontrol->value.enumerated.item[1] + 1) << 5; - spin_lock_irq(&sonic->reg_lock); - oval1 = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC); - oval2 = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC); - left = (oval1 & ~SV_RECSRC_OUT) | left; - right = (oval2 & ~SV_RECSRC_OUT) | right; - change = left != oval1 || right != oval2; - snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ADC, left); - snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ADC, right); - spin_unlock_irq(&sonic->reg_lock); - return change; -} - -#define SONICVIBES_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_sonicvibes_info_single, \ - .get = snd_sonicvibes_get_single, .put = snd_sonicvibes_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_sonicvibes_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_sonicvibes_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irq(&sonic->reg_lock); - ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, reg)>> shift) & mask; - spin_unlock_irq(&sonic->reg_lock); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_sonicvibes_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val, oval; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irq(&sonic->reg_lock); - oval = snd_sonicvibes_in1(sonic, reg); - val = (oval & ~(mask << shift)) | val; - change = val != oval; - snd_sonicvibes_out1(sonic, reg, val); - spin_unlock_irq(&sonic->reg_lock); - return change; -} - -#define SONICVIBES_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_sonicvibes_info_double, \ - .get = snd_sonicvibes_get_double, .put = snd_sonicvibes_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -static int snd_sonicvibes_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_sonicvibes_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irq(&sonic->reg_lock); - ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, left_reg) >> shift_left) & mask; - ucontrol->value.integer.value[1] = (snd_sonicvibes_in1(sonic, right_reg) >> shift_right) & mask; - spin_unlock_irq(&sonic->reg_lock); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2, oval1, oval2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irq(&sonic->reg_lock); - oval1 = snd_sonicvibes_in1(sonic, left_reg); - oval2 = snd_sonicvibes_in1(sonic, right_reg); - val1 = (oval1 & ~(mask << shift_left)) | val1; - val2 = (oval2 & ~(mask << shift_right)) | val2; - change = val1 != oval1 || val2 != oval2; - snd_sonicvibes_out1(sonic, left_reg, val1); - snd_sonicvibes_out1(sonic, right_reg, val2); - spin_unlock_irq(&sonic->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_sonicvibes_controls[] __devinitdata = { -SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0), -SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1), -SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1), -SONICVIBES_DOUBLE("CD Playback Switch", 0, SV_IREG_LEFT_CD, SV_IREG_RIGHT_CD, 7, 7, 1, 1), -SONICVIBES_DOUBLE("CD Playback Volume", 0, SV_IREG_LEFT_CD, SV_IREG_RIGHT_CD, 0, 0, 31, 1), -SONICVIBES_DOUBLE("Line Playback Switch", 0, SV_IREG_LEFT_LINE, SV_IREG_RIGHT_LINE, 7, 7, 1, 1), -SONICVIBES_DOUBLE("Line Playback Volume", 0, SV_IREG_LEFT_LINE, SV_IREG_RIGHT_LINE, 0, 0, 31, 1), -SONICVIBES_SINGLE("Mic Playback Switch", 0, SV_IREG_MIC, 7, 1, 1), -SONICVIBES_SINGLE("Mic Playback Volume", 0, SV_IREG_MIC, 0, 15, 1), -SONICVIBES_SINGLE("Mic Boost", 0, SV_IREG_LEFT_ADC, 4, 1, 0), -SONICVIBES_DOUBLE("Synth Playback Switch", 0, SV_IREG_LEFT_SYNTH, SV_IREG_RIGHT_SYNTH, 7, 7, 1, 1), -SONICVIBES_DOUBLE("Synth Playback Volume", 0, SV_IREG_LEFT_SYNTH, SV_IREG_RIGHT_SYNTH, 0, 0, 31, 1), -SONICVIBES_DOUBLE("Aux Playback Switch", 1, SV_IREG_LEFT_AUX2, SV_IREG_RIGHT_AUX2, 7, 7, 1, 1), -SONICVIBES_DOUBLE("Aux Playback Volume", 1, SV_IREG_LEFT_AUX2, SV_IREG_RIGHT_AUX2, 0, 0, 31, 1), -SONICVIBES_DOUBLE("Master Playback Switch", 0, SV_IREG_LEFT_ANALOG, SV_IREG_RIGHT_ANALOG, 7, 7, 1, 1), -SONICVIBES_DOUBLE("Master Playback Volume", 0, SV_IREG_LEFT_ANALOG, SV_IREG_RIGHT_ANALOG, 0, 0, 31, 1), -SONICVIBES_DOUBLE("PCM Playback Switch", 0, SV_IREG_LEFT_PCM, SV_IREG_RIGHT_PCM, 7, 7, 1, 1), -SONICVIBES_DOUBLE("PCM Playback Volume", 0, SV_IREG_LEFT_PCM, SV_IREG_RIGHT_PCM, 0, 0, 63, 1), -SONICVIBES_SINGLE("Loopback Capture Switch", 0, SV_IREG_ADC_OUTPUT_CTRL, 0, 1, 0), -SONICVIBES_SINGLE("Loopback Capture Volume", 0, SV_IREG_ADC_OUTPUT_CTRL, 2, 63, 1), -SONICVIBES_MUX("Capture Source", 0) -}; - -static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol) -{ - struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol); - sonic->master_mute = NULL; - sonic->master_volume = NULL; -} - -static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic) -{ - struct snd_card *card; - struct snd_kcontrol *kctl; - unsigned int idx; - int err; - - if (snd_BUG_ON(!sonic || !sonic->card)) - return -EINVAL; - card = sonic->card; - strcpy(card->mixername, "S3 SonicVibes"); - - for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic))) < 0) - return err; - switch (idx) { - case 0: - case 1: kctl->private_free = snd_sonicvibes_master_free; break; - } - } - return 0; -} - -/* - - */ - -static void snd_sonicvibes_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct sonicvibes *sonic = entry->private_data; - unsigned char tmp; - - tmp = sonic->srs_space & 0x0f; - snd_iprintf(buffer, "SRS 3D : %s\n", - sonic->srs_space & 0x80 ? "off" : "on"); - snd_iprintf(buffer, "SRS Space : %s\n", - tmp == 0x00 ? "100%" : - tmp == 0x01 ? "75%" : - tmp == 0x02 ? "50%" : - tmp == 0x03 ? "25%" : "0%"); - tmp = sonic->srs_center & 0x0f; - snd_iprintf(buffer, "SRS Center : %s\n", - tmp == 0x00 ? "100%" : - tmp == 0x01 ? "75%" : - tmp == 0x02 ? "50%" : - tmp == 0x03 ? "25%" : "0%"); - tmp = sonic->wave_source & 0x03; - snd_iprintf(buffer, "WaveTable Source : %s\n", - tmp == 0x00 ? "on-board ROM" : - tmp == 0x01 ? "PCI bus" : "on-board ROM + PCI bus"); - tmp = sonic->mpu_switch; - snd_iprintf(buffer, "Onboard synth : %s\n", tmp & 0x01 ? "on" : "off"); - snd_iprintf(buffer, "Ext. Rx to synth : %s\n", tmp & 0x02 ? "on" : "off"); - snd_iprintf(buffer, "MIDI to ext. Tx : %s\n", tmp & 0x04 ? "on" : "off"); -} - -static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry)) - snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read); -} - -/* - - */ - -#ifdef SUPPORT_JOYSTICK -static struct snd_kcontrol_new snd_sonicvibes_game_control __devinitdata = -SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0); - -static int __devinit snd_sonicvibes_create_gameport(struct sonicvibes *sonic) -{ - struct gameport *gp; - - sonic->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n"); - return -ENOMEM; - } - - gameport_set_name(gp, "SonicVibes Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci)); - gameport_set_dev_parent(gp, &sonic->pci->dev); - gp->io = sonic->game_port; - - gameport_register_port(gp); - - snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic)); - - return 0; -} - -static void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) -{ - if (sonic->gameport) { - gameport_unregister_port(sonic->gameport); - sonic->gameport = NULL; - } -} -#else -static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { return -ENOSYS; } -static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { } -#endif - -static int snd_sonicvibes_free(struct sonicvibes *sonic) -{ - snd_sonicvibes_free_gameport(sonic); - pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port); - pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port); - if (sonic->irq >= 0) - free_irq(sonic->irq, sonic); - release_and_free_resource(sonic->res_dmaa); - release_and_free_resource(sonic->res_dmac); - pci_release_regions(sonic->pci); - pci_disable_device(sonic->pci); - kfree(sonic); - return 0; -} - -static int snd_sonicvibes_dev_free(struct snd_device *device) -{ - struct sonicvibes *sonic = device->device_data; - return snd_sonicvibes_free(sonic); -} - -static int __devinit snd_sonicvibes_create(struct snd_card *card, - struct pci_dev *pci, - int reverb, - int mge, - struct sonicvibes ** rsonic) -{ - struct sonicvibes *sonic; - unsigned int dmaa, dmac; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_sonicvibes_dev_free, - }; - - *rsonic = NULL; - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - /* check, if we can restrict PCI DMA transfers to 24 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(24)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(24)) < 0) { - snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - sonic = kzalloc(sizeof(*sonic), GFP_KERNEL); - if (sonic == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - spin_lock_init(&sonic->reg_lock); - sonic->card = card; - sonic->pci = pci; - sonic->irq = -1; - - if ((err = pci_request_regions(pci, "S3 SonicVibes")) < 0) { - kfree(sonic); - pci_disable_device(pci); - return err; - } - - sonic->sb_port = pci_resource_start(pci, 0); - sonic->enh_port = pci_resource_start(pci, 1); - sonic->synth_port = pci_resource_start(pci, 2); - sonic->midi_port = pci_resource_start(pci, 3); - sonic->game_port = pci_resource_start(pci, 4); - - if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED, - KBUILD_MODNAME, sonic)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_sonicvibes_free(sonic); - return -EBUSY; - } - sonic->irq = pci->irq; - - pci_read_config_dword(pci, 0x40, &dmaa); - pci_read_config_dword(pci, 0x48, &dmac); - dmaio &= ~0x0f; - dmaa &= ~0x0f; - dmac &= ~0x0f; - if (!dmaa) { - dmaa = dmaio; - dmaio += 0x10; - snd_printk(KERN_INFO "BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa); - } - if (!dmac) { - dmac = dmaio; - dmaio += 0x10; - snd_printk(KERN_INFO "BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac); - } - pci_write_config_dword(pci, 0x40, dmaa); - pci_write_config_dword(pci, 0x48, dmac); - - if ((sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A")) == NULL) { - snd_sonicvibes_free(sonic); - snd_printk(KERN_ERR "unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1); - return -EBUSY; - } - if ((sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C")) == NULL) { - snd_sonicvibes_free(sonic); - snd_printk(KERN_ERR "unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1); - return -EBUSY; - } - - pci_read_config_dword(pci, 0x40, &sonic->dmaa_port); - pci_read_config_dword(pci, 0x48, &sonic->dmac_port); - sonic->dmaa_port &= ~0x0f; - sonic->dmac_port &= ~0x0f; - pci_write_config_dword(pci, 0x40, sonic->dmaa_port | 9); /* enable + enhanced */ - pci_write_config_dword(pci, 0x48, sonic->dmac_port | 9); /* enable */ - /* ok.. initialize S3 SonicVibes chip */ - outb(SV_RESET, SV_REG(sonic, CONTROL)); /* reset chip */ - udelay(100); - outb(0, SV_REG(sonic, CONTROL)); /* release reset */ - udelay(100); - outb(SV_ENHANCED | SV_INTA | (reverb ? SV_REVERB : 0), SV_REG(sonic, CONTROL)); - inb(SV_REG(sonic, STATUS)); /* clear IRQs */ -#if 1 - snd_sonicvibes_out(sonic, SV_IREG_DRIVE_CTRL, 0); /* drive current 16mA */ -#else - snd_sonicvibes_out(sonic, SV_IREG_DRIVE_CTRL, 0x40); /* drive current 8mA */ -#endif - snd_sonicvibes_out(sonic, SV_IREG_PC_ENABLE, sonic->enable = 0); /* disable playback & capture */ - outb(sonic->irqmask = ~(SV_DMAA_MASK | SV_DMAC_MASK | SV_UD_MASK), SV_REG(sonic, IRQMASK)); - inb(SV_REG(sonic, STATUS)); /* clear IRQs */ - snd_sonicvibes_out(sonic, SV_IREG_ADC_CLOCK, 0); /* use PLL as clock source */ - snd_sonicvibes_out(sonic, SV_IREG_ANALOG_POWER, 0); /* power up analog parts */ - snd_sonicvibes_out(sonic, SV_IREG_DIGITAL_POWER, 0); /* power up digital parts */ - snd_sonicvibes_setpll(sonic, SV_IREG_ADC_PLL, 8000); - snd_sonicvibes_out(sonic, SV_IREG_SRS_SPACE, sonic->srs_space = 0x80); /* SRS space off */ - snd_sonicvibes_out(sonic, SV_IREG_SRS_CENTER, sonic->srs_center = 0x00);/* SRS center off */ - snd_sonicvibes_out(sonic, SV_IREG_MPU401, sonic->mpu_switch = 0x05); /* MPU-401 switch */ - snd_sonicvibes_out(sonic, SV_IREG_WAVE_SOURCE, sonic->wave_source = 0x00); /* onboard ROM */ - snd_sonicvibes_out(sonic, SV_IREG_PCM_RATE_LOW, (8000 * 65536 / SV_FULLRATE) & 0xff); - snd_sonicvibes_out(sonic, SV_IREG_PCM_RATE_HIGH, ((8000 * 65536 / SV_FULLRATE) >> 8) & 0xff); - snd_sonicvibes_out(sonic, SV_IREG_LEFT_ADC, mge ? 0xd0 : 0xc0); - snd_sonicvibes_out(sonic, SV_IREG_RIGHT_ADC, 0xc0); - snd_sonicvibes_out(sonic, SV_IREG_LEFT_AUX1, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_RIGHT_AUX1, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_LEFT_CD, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_RIGHT_CD, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_LEFT_LINE, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_RIGHT_LINE, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_MIC, 0x8f); - snd_sonicvibes_out(sonic, SV_IREG_LEFT_SYNTH, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_RIGHT_SYNTH, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_LEFT_AUX2, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_RIGHT_AUX2, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_LEFT_ANALOG, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_RIGHT_ANALOG, 0x9f); - snd_sonicvibes_out(sonic, SV_IREG_LEFT_PCM, 0xbf); - snd_sonicvibes_out(sonic, SV_IREG_RIGHT_PCM, 0xbf); - snd_sonicvibes_out(sonic, SV_IREG_ADC_OUTPUT_CTRL, 0xfc); -#if 0 - snd_sonicvibes_debug(sonic); -#endif - sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) { - snd_sonicvibes_free(sonic); - return err; - } - - snd_sonicvibes_proc_init(sonic); - - snd_card_set_dev(card, &pci->dev); - - *rsonic = sonic; - return 0; -} - -/* - * MIDI section - */ - -static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = { -SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0), -SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0), -SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0), -SONICVIBES_SINGLE("SonicVibes External Rx to Synth", 0, SV_IREG_MPU401, 1, 1, 0), -SONICVIBES_SINGLE("SonicVibes External Tx", 0, SV_IREG_MPU401, 2, 1, 0) -}; - -static int snd_sonicvibes_midi_input_open(struct snd_mpu401 * mpu) -{ - struct sonicvibes *sonic = mpu->private_data; - outb(sonic->irqmask &= ~SV_MIDI_MASK, SV_REG(sonic, IRQMASK)); - return 0; -} - -static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu) -{ - struct sonicvibes *sonic = mpu->private_data; - outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK)); -} - -static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic, - struct snd_rawmidi *rmidi) -{ - struct snd_mpu401 * mpu = rmidi->private_data; - struct snd_card *card = sonic->card; - struct snd_rawmidi_str *dir; - unsigned int idx; - int err; - - mpu->private_data = sonic; - mpu->open_input = snd_sonicvibes_midi_input_open; - mpu->close_input = snd_sonicvibes_midi_input_close; - dir = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]; - for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic))) < 0) - return err; - return 0; -} - -static int __devinit snd_sonic_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct sonicvibes *sonic; - struct snd_rawmidi *midi_uart; - struct snd_opl3 *opl3; - int idx, err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - for (idx = 0; idx < 5; idx++) { - if (pci_resource_start(pci, idx) == 0 || - !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) { - snd_card_free(card); - return -ENODEV; - } - } - if ((err = snd_sonicvibes_create(card, pci, - reverb[dev] ? 1 : 0, - mge[dev] ? 1 : 0, - &sonic)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "SonicVibes"); - strcpy(card->shortname, "S3 SonicVibes"); - sprintf(card->longname, "%s rev %i at 0x%llx, irq %i", - card->shortname, - sonic->revision, - (unsigned long long)pci_resource_start(pci, 1), - sonic->irq); - - if ((err = snd_sonicvibes_pcm(sonic, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_sonicvibes_mixer(sonic)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, - sonic->midi_port, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &midi_uart)) < 0) { - snd_card_free(card); - return err; - } - snd_sonicvibes_midi(sonic, midi_uart); - if ((err = snd_opl3_create(card, sonic->synth_port, - sonic->synth_port + 2, - OPL3_HW_OPL3_SV, 1, &opl3)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - - snd_sonicvibes_create_gameport(sonic); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_sonic_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_sonic_ids, - .probe = snd_sonic_probe, - .remove = __devexit_p(snd_sonic_remove), -}; - -static int __init alsa_card_sonicvibes_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_sonicvibes_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_sonicvibes_init) -module_exit(alsa_card_sonicvibes_exit) diff --git a/ANDROID_3.4.5/sound/pci/trident/Makefile b/ANDROID_3.4.5/sound/pci/trident/Makefile deleted file mode 100644 index 88676b50..00000000 --- a/ANDROID_3.4.5/sound/pci/trident/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-trident-objs := trident.o trident_main.o trident_memory.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_TRIDENT) += snd-trident.o diff --git a/ANDROID_3.4.5/sound/pci/trident/trident.c b/ANDROID_3.4.5/sound/pci/trident/trident.c deleted file mode 100644 index 5f1def7f..00000000 --- a/ANDROID_3.4.5/sound/pci/trident/trident.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Driver for Trident 4DWave DX/NX & SiS SI7018 Audio PCI soundcard - * - * Driver was originated by Trident - * Fri Feb 19 15:55:28 MST 1999 - * - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela , "); -MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX}," - "{Trident,4DWave NX}," - "{SiS,SI7018 PCI Audio}," - "{Best Union,Miss Melody 4DWave PCI}," - "{HIS,4DWave PCI}," - "{Warpspeed,ONSpeed 4DWave PCI}," - "{Aztech Systems,PCI 64-Q3D}," - "{Addonics,SV 750}," - "{CHIC,True Sound 4Dwave}," - "{Shark,Predator4D-PCI}," - "{Jaton,SonicWave 4D}," - "{Hoontech,SoundTrack Digital 4DWave NX}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 32}; -static int wavetable_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8192}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Trident 4DWave PCI soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Trident 4DWave PCI soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Trident 4DWave PCI soundcard."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM."); -module_param_array(wavetable_size, int, NULL, 0444); -MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth."); - -static DEFINE_PCI_DEVICE_TABLE(snd_trident_ids) = { - {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), - 0, 0, 0}, - {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, 0}, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_trident_ids); - -static int __devinit snd_trident_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_trident *trident; - const char *str; - int err, pcm_dev = 0; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_trident_create(card, pci, - pcm_channels[dev], - ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2, - wavetable_size[dev], - &trident)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = trident; - - switch (trident->device) { - case TRIDENT_DEVICE_ID_DX: - str = "TRID4DWAVEDX"; - break; - case TRIDENT_DEVICE_ID_NX: - str = "TRID4DWAVENX"; - break; - case TRIDENT_DEVICE_ID_SI7018: - str = "SI7018"; - break; - default: - str = "Unknown"; - } - strcpy(card->driver, str); - if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - strcpy(card->shortname, "SiS "); - } else { - strcpy(card->shortname, "Trident "); - } - strcat(card->shortname, card->driver); - sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d", - card->shortname, trident->port, trident->irq); - - if ((err = snd_trident_pcm(trident, pcm_dev++, NULL)) < 0) { - snd_card_free(card); - return err; - } - switch (trident->device) { - case TRIDENT_DEVICE_ID_DX: - case TRIDENT_DEVICE_ID_NX: - if ((err = snd_trident_foldback_pcm(trident, pcm_dev++, NULL)) < 0) { - snd_card_free(card); - return err; - } - break; - } - if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) { - if ((err = snd_trident_spdif_pcm(trident, pcm_dev++, NULL)) < 0) { - snd_card_free(card); - return err; - } - } - if (trident->device != TRIDENT_DEVICE_ID_SI7018 && - (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, - trident->midi_port, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &trident->rmidi)) < 0) { - snd_card_free(card); - return err; - } - - snd_trident_create_gameport(trident); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_trident_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_trident_ids, - .probe = snd_trident_probe, - .remove = __devexit_p(snd_trident_remove), -#ifdef CONFIG_PM - .suspend = snd_trident_suspend, - .resume = snd_trident_resume, -#endif -}; - -static int __init alsa_card_trident_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_trident_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_trident_init) -module_exit(alsa_card_trident_exit) diff --git a/ANDROID_3.4.5/sound/pci/trident/trident_main.c b/ANDROID_3.4.5/sound/pci/trident/trident_main.c deleted file mode 100644 index 61d3c0e8..00000000 --- a/ANDROID_3.4.5/sound/pci/trident/trident_main.c +++ /dev/null @@ -1,3982 +0,0 @@ -/* - * Maintained by Jaroslav Kysela - * Originated by audio@tridentmicro.com - * Fri Feb 19 15:55:28 MST 1999 - * Routines for control of Trident 4DWave (DX and NX) chip - * - * BUGS: - * - * TODO: - * --- - * - * 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 - * - * - * SiS7018 S/PDIF support by Thomas Winischhofer - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -static int snd_trident_pcm_mixer_build(struct snd_trident *trident, - struct snd_trident_voice * voice, - struct snd_pcm_substream *substream); -static int snd_trident_pcm_mixer_free(struct snd_trident *trident, - struct snd_trident_voice * voice, - struct snd_pcm_substream *substream); -static irqreturn_t snd_trident_interrupt(int irq, void *dev_id); -static int snd_trident_sis_reset(struct snd_trident *trident); - -static void snd_trident_clear_voices(struct snd_trident * trident, - unsigned short v_min, unsigned short v_max); -static int snd_trident_free(struct snd_trident *trident); - -/* - * common I/O routines - */ - - -#if 0 -static void snd_trident_print_voice_regs(struct snd_trident *trident, int voice) -{ - unsigned int val, tmp; - - printk(KERN_DEBUG "Trident voice %i:\n", voice); - outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR)); - val = inl(TRID_REG(trident, CH_LBA)); - printk(KERN_DEBUG "LBA: 0x%x\n", val); - val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); - printk(KERN_DEBUG "GVSel: %i\n", val >> 31); - printk(KERN_DEBUG "Pan: 0x%x\n", (val >> 24) & 0x7f); - printk(KERN_DEBUG "Vol: 0x%x\n", (val >> 16) & 0xff); - printk(KERN_DEBUG "CTRL: 0x%x\n", (val >> 12) & 0x0f); - printk(KERN_DEBUG "EC: 0x%x\n", val & 0x0fff); - if (trident->device != TRIDENT_DEVICE_ID_NX) { - val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS)); - printk(KERN_DEBUG "CSO: 0x%x\n", val >> 16); - printk("Alpha: 0x%x\n", (val >> 4) & 0x0fff); - printk(KERN_DEBUG "FMS: 0x%x\n", val & 0x0f); - val = inl(TRID_REG(trident, CH_DX_ESO_DELTA)); - printk(KERN_DEBUG "ESO: 0x%x\n", val >> 16); - printk(KERN_DEBUG "Delta: 0x%x\n", val & 0xffff); - val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL)); - } else { // TRIDENT_DEVICE_ID_NX - val = inl(TRID_REG(trident, CH_NX_DELTA_CSO)); - tmp = (val >> 24) & 0xff; - printk(KERN_DEBUG "CSO: 0x%x\n", val & 0x00ffffff); - val = inl(TRID_REG(trident, CH_NX_DELTA_ESO)); - tmp |= (val >> 16) & 0xff00; - printk(KERN_DEBUG "Delta: 0x%x\n", tmp); - printk(KERN_DEBUG "ESO: 0x%x\n", val & 0x00ffffff); - val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL)); - printk(KERN_DEBUG "Alpha: 0x%x\n", val >> 20); - printk(KERN_DEBUG "FMS: 0x%x\n", (val >> 16) & 0x0f); - } - printk(KERN_DEBUG "FMC: 0x%x\n", (val >> 14) & 3); - printk(KERN_DEBUG "RVol: 0x%x\n", (val >> 7) & 0x7f); - printk(KERN_DEBUG "CVol: 0x%x\n", val & 0x7f); -} -#endif - -/*--------------------------------------------------------------------------- - unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg) - - Description: This routine will do all of the reading from the external - CODEC (AC97). - - Parameters: ac97 - ac97 codec structure - reg - CODEC register index, from AC97 Hal. - - returns: 16 bit value read from the AC97. - - ---------------------------------------------------------------------------*/ -static unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg) -{ - unsigned int data = 0, treg; - unsigned short count = 0xffff; - unsigned long flags; - struct snd_trident *trident = ac97->private_data; - - spin_lock_irqsave(&trident->reg_lock, flags); - if (trident->device == TRIDENT_DEVICE_ID_DX) { - data = (DX_AC97_BUSY_READ | (reg & 0x000000ff)); - outl(data, TRID_REG(trident, DX_ACR1_AC97_R)); - do { - data = inl(TRID_REG(trident, DX_ACR1_AC97_R)); - if ((data & DX_AC97_BUSY_READ) == 0) - break; - } while (--count); - } else if (trident->device == TRIDENT_DEVICE_ID_NX) { - data = (NX_AC97_BUSY_READ | (reg & 0x000000ff)); - treg = ac97->num == 0 ? NX_ACR2_AC97_R_PRIMARY : NX_ACR3_AC97_R_SECONDARY; - outl(data, TRID_REG(trident, treg)); - do { - data = inl(TRID_REG(trident, treg)); - if ((data & 0x00000C00) == 0) - break; - } while (--count); - } else if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - data = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff); - if (ac97->num == 1) - data |= SI_AC97_SECONDARY; - outl(data, TRID_REG(trident, SI_AC97_READ)); - do { - data = inl(TRID_REG(trident, SI_AC97_READ)); - if ((data & (SI_AC97_BUSY_READ)) == 0) - break; - } while (--count); - } - - if (count == 0 && !trident->ac97_detect) { - snd_printk(KERN_ERR "ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n", - reg, data); - data = 0; - } - - spin_unlock_irqrestore(&trident->reg_lock, flags); - return ((unsigned short) (data >> 16)); -} - -/*--------------------------------------------------------------------------- - void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short wdata) - - Description: This routine will do all of the writing to the external - CODEC (AC97). - - Parameters: ac97 - ac97 codec structure - reg - CODEC register index, from AC97 Hal. - data - Lower 16 bits are the data to write to CODEC. - - returns: TRUE if everything went ok, else FALSE. - - ---------------------------------------------------------------------------*/ -static void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short wdata) -{ - unsigned int address, data; - unsigned short count = 0xffff; - unsigned long flags; - struct snd_trident *trident = ac97->private_data; - - data = ((unsigned long) wdata) << 16; - - spin_lock_irqsave(&trident->reg_lock, flags); - if (trident->device == TRIDENT_DEVICE_ID_DX) { - address = DX_ACR0_AC97_W; - - /* read AC-97 write register status */ - do { - if ((inw(TRID_REG(trident, address)) & DX_AC97_BUSY_WRITE) == 0) - break; - } while (--count); - - data |= (DX_AC97_BUSY_WRITE | (reg & 0x000000ff)); - } else if (trident->device == TRIDENT_DEVICE_ID_NX) { - address = NX_ACR1_AC97_W; - - /* read AC-97 write register status */ - do { - if ((inw(TRID_REG(trident, address)) & NX_AC97_BUSY_WRITE) == 0) - break; - } while (--count); - - data |= (NX_AC97_BUSY_WRITE | (ac97->num << 8) | (reg & 0x000000ff)); - } else if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - address = SI_AC97_WRITE; - - /* read AC-97 write register status */ - do { - if ((inw(TRID_REG(trident, address)) & (SI_AC97_BUSY_WRITE)) == 0) - break; - } while (--count); - - data |= SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff); - if (ac97->num == 1) - data |= SI_AC97_SECONDARY; - } else { - address = 0; /* keep GCC happy */ - count = 0; /* return */ - } - - if (count == 0) { - spin_unlock_irqrestore(&trident->reg_lock, flags); - return; - } - outl(data, TRID_REG(trident, address)); - spin_unlock_irqrestore(&trident->reg_lock, flags); -} - -/*--------------------------------------------------------------------------- - void snd_trident_enable_eso(struct snd_trident *trident) - - Description: This routine will enable end of loop interrupts. - End of loop interrupts will occur when a running - channel reaches ESO. - Also enables middle of loop interrupts. - - Parameters: trident - pointer to target device class for 4DWave. - - ---------------------------------------------------------------------------*/ - -static void snd_trident_enable_eso(struct snd_trident * trident) -{ - unsigned int val; - - val = inl(TRID_REG(trident, T4D_LFO_GC_CIR)); - val |= ENDLP_IE; - val |= MIDLP_IE; - if (trident->device == TRIDENT_DEVICE_ID_SI7018) - val |= BANK_B_EN; - outl(val, TRID_REG(trident, T4D_LFO_GC_CIR)); -} - -/*--------------------------------------------------------------------------- - void snd_trident_disable_eso(struct snd_trident *trident) - - Description: This routine will disable end of loop interrupts. - End of loop interrupts will occur when a running - channel reaches ESO. - Also disables middle of loop interrupts. - - Parameters: - trident - pointer to target device class for 4DWave. - - returns: TRUE if everything went ok, else FALSE. - - ---------------------------------------------------------------------------*/ - -static void snd_trident_disable_eso(struct snd_trident * trident) -{ - unsigned int tmp; - - tmp = inl(TRID_REG(trident, T4D_LFO_GC_CIR)); - tmp &= ~ENDLP_IE; - tmp &= ~MIDLP_IE; - outl(tmp, TRID_REG(trident, T4D_LFO_GC_CIR)); -} - -/*--------------------------------------------------------------------------- - void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice) - - Description: Start a voice, any channel 0 thru 63. - This routine automatically handles the fact that there are - more than 32 channels available. - - Parameters : voice - Voice number 0 thru n. - trident - pointer to target device class for 4DWave. - - Return Value: None. - - ---------------------------------------------------------------------------*/ - -void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice) -{ - unsigned int mask = 1 << (voice & 0x1f); - unsigned int reg = (voice & 0x20) ? T4D_START_B : T4D_START_A; - - outl(mask, TRID_REG(trident, reg)); -} - -EXPORT_SYMBOL(snd_trident_start_voice); - -/*--------------------------------------------------------------------------- - void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice) - - Description: Stop a voice, any channel 0 thru 63. - This routine automatically handles the fact that there are - more than 32 channels available. - - Parameters : voice - Voice number 0 thru n. - trident - pointer to target device class for 4DWave. - - Return Value: None. - - ---------------------------------------------------------------------------*/ - -void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice) -{ - unsigned int mask = 1 << (voice & 0x1f); - unsigned int reg = (voice & 0x20) ? T4D_STOP_B : T4D_STOP_A; - - outl(mask, TRID_REG(trident, reg)); -} - -EXPORT_SYMBOL(snd_trident_stop_voice); - -/*--------------------------------------------------------------------------- - int snd_trident_allocate_pcm_channel(struct snd_trident *trident) - - Description: Allocate hardware channel in Bank B (32-63). - - Parameters : trident - pointer to target device class for 4DWave. - - Return Value: hardware channel - 32-63 or -1 when no channel is available - - ---------------------------------------------------------------------------*/ - -static int snd_trident_allocate_pcm_channel(struct snd_trident * trident) -{ - int idx; - - if (trident->ChanPCMcnt >= trident->ChanPCM) - return -1; - for (idx = 31; idx >= 0; idx--) { - if (!(trident->ChanMap[T4D_BANK_B] & (1 << idx))) { - trident->ChanMap[T4D_BANK_B] |= 1 << idx; - trident->ChanPCMcnt++; - return idx + 32; - } - } - return -1; -} - -/*--------------------------------------------------------------------------- - void snd_trident_free_pcm_channel(int channel) - - Description: Free hardware channel in Bank B (32-63) - - Parameters : trident - pointer to target device class for 4DWave. - channel - hardware channel number 0-63 - - Return Value: none - - ---------------------------------------------------------------------------*/ - -static void snd_trident_free_pcm_channel(struct snd_trident *trident, int channel) -{ - if (channel < 32 || channel > 63) - return; - channel &= 0x1f; - if (trident->ChanMap[T4D_BANK_B] & (1 << channel)) { - trident->ChanMap[T4D_BANK_B] &= ~(1 << channel); - trident->ChanPCMcnt--; - } -} - -/*--------------------------------------------------------------------------- - unsigned int snd_trident_allocate_synth_channel(void) - - Description: Allocate hardware channel in Bank A (0-31). - - Parameters : trident - pointer to target device class for 4DWave. - - Return Value: hardware channel - 0-31 or -1 when no channel is available - - ---------------------------------------------------------------------------*/ - -static int snd_trident_allocate_synth_channel(struct snd_trident * trident) -{ - int idx; - - for (idx = 31; idx >= 0; idx--) { - if (!(trident->ChanMap[T4D_BANK_A] & (1 << idx))) { - trident->ChanMap[T4D_BANK_A] |= 1 << idx; - trident->synth.ChanSynthCount++; - return idx; - } - } - return -1; -} - -/*--------------------------------------------------------------------------- - void snd_trident_free_synth_channel( int channel ) - - Description: Free hardware channel in Bank B (0-31). - - Parameters : trident - pointer to target device class for 4DWave. - channel - hardware channel number 0-63 - - Return Value: none - - ---------------------------------------------------------------------------*/ - -static void snd_trident_free_synth_channel(struct snd_trident *trident, int channel) -{ - if (channel < 0 || channel > 31) - return; - channel &= 0x1f; - if (trident->ChanMap[T4D_BANK_A] & (1 << channel)) { - trident->ChanMap[T4D_BANK_A] &= ~(1 << channel); - trident->synth.ChanSynthCount--; - } -} - -/*--------------------------------------------------------------------------- - snd_trident_write_voice_regs - - Description: This routine will complete and write the 5 hardware channel - registers to hardware. - - Parameters: trident - pointer to target device class for 4DWave. - voice - synthesizer voice structure - Each register field. - - ---------------------------------------------------------------------------*/ - -void snd_trident_write_voice_regs(struct snd_trident * trident, - struct snd_trident_voice * voice) -{ - unsigned int FmcRvolCvol; - unsigned int regs[5]; - - regs[1] = voice->LBA; - regs[4] = (voice->GVSel << 31) | - ((voice->Pan & 0x0000007f) << 24) | - ((voice->CTRL & 0x0000000f) << 12); - FmcRvolCvol = ((voice->FMC & 3) << 14) | - ((voice->RVol & 0x7f) << 7) | - (voice->CVol & 0x7f); - - switch (trident->device) { - case TRIDENT_DEVICE_ID_SI7018: - regs[4] |= voice->number > 31 ? - (voice->Vol & 0x000003ff) : - ((voice->Vol & 0x00003fc) << (16-2)) | - (voice->EC & 0x00000fff); - regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | - (voice->FMS & 0x0000000f); - regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff); - regs[3] = (voice->Attribute << 16) | FmcRvolCvol; - break; - case TRIDENT_DEVICE_ID_DX: - regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) | - (voice->EC & 0x00000fff); - regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | - (voice->FMS & 0x0000000f); - regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff); - regs[3] = FmcRvolCvol; - break; - case TRIDENT_DEVICE_ID_NX: - regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) | - (voice->EC & 0x00000fff); - regs[0] = (voice->Delta << 24) | (voice->CSO & 0x00ffffff); - regs[2] = ((voice->Delta << 16) & 0xff000000) | - (voice->ESO & 0x00ffffff); - regs[3] = (voice->Alpha << 20) | - ((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol; - break; - default: - snd_BUG(); - return; - } - - outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); - outl(regs[0], TRID_REG(trident, CH_START + 0)); - outl(regs[1], TRID_REG(trident, CH_START + 4)); - outl(regs[2], TRID_REG(trident, CH_START + 8)); - outl(regs[3], TRID_REG(trident, CH_START + 12)); - outl(regs[4], TRID_REG(trident, CH_START + 16)); - -#if 0 - printk(KERN_DEBUG "written %i channel:\n", voice->number); - printk(KERN_DEBUG " regs[0] = 0x%x/0x%x\n", - regs[0], inl(TRID_REG(trident, CH_START + 0))); - printk(KERN_DEBUG " regs[1] = 0x%x/0x%x\n", - regs[1], inl(TRID_REG(trident, CH_START + 4))); - printk(KERN_DEBUG " regs[2] = 0x%x/0x%x\n", - regs[2], inl(TRID_REG(trident, CH_START + 8))); - printk(KERN_DEBUG " regs[3] = 0x%x/0x%x\n", - regs[3], inl(TRID_REG(trident, CH_START + 12))); - printk(KERN_DEBUG " regs[4] = 0x%x/0x%x\n", - regs[4], inl(TRID_REG(trident, CH_START + 16))); -#endif -} - -EXPORT_SYMBOL(snd_trident_write_voice_regs); - -/*--------------------------------------------------------------------------- - snd_trident_write_cso_reg - - Description: This routine will write the new CSO offset - register to hardware. - - Parameters: trident - pointer to target device class for 4DWave. - voice - synthesizer voice structure - CSO - new CSO value - - ---------------------------------------------------------------------------*/ - -static void snd_trident_write_cso_reg(struct snd_trident * trident, - struct snd_trident_voice * voice, - unsigned int CSO) -{ - voice->CSO = CSO; - outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); - if (trident->device != TRIDENT_DEVICE_ID_NX) { - outw(voice->CSO, TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2); - } else { - outl((voice->Delta << 24) | - (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO)); - } -} - -/*--------------------------------------------------------------------------- - snd_trident_write_eso_reg - - Description: This routine will write the new ESO offset - register to hardware. - - Parameters: trident - pointer to target device class for 4DWave. - voice - synthesizer voice structure - ESO - new ESO value - - ---------------------------------------------------------------------------*/ - -static void snd_trident_write_eso_reg(struct snd_trident * trident, - struct snd_trident_voice * voice, - unsigned int ESO) -{ - voice->ESO = ESO; - outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); - if (trident->device != TRIDENT_DEVICE_ID_NX) { - outw(voice->ESO, TRID_REG(trident, CH_DX_ESO_DELTA) + 2); - } else { - outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff), - TRID_REG(trident, CH_NX_DELTA_ESO)); - } -} - -/*--------------------------------------------------------------------------- - snd_trident_write_vol_reg - - Description: This routine will write the new voice volume - register to hardware. - - Parameters: trident - pointer to target device class for 4DWave. - voice - synthesizer voice structure - Vol - new voice volume - - ---------------------------------------------------------------------------*/ - -static void snd_trident_write_vol_reg(struct snd_trident * trident, - struct snd_trident_voice * voice, - unsigned int Vol) -{ - voice->Vol = Vol; - outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); - switch (trident->device) { - case TRIDENT_DEVICE_ID_DX: - case TRIDENT_DEVICE_ID_NX: - outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2)); - break; - case TRIDENT_DEVICE_ID_SI7018: - /* printk(KERN_DEBUG "voice->Vol = 0x%x\n", voice->Vol); */ - outw((voice->CTRL << 12) | voice->Vol, - TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); - break; - } -} - -/*--------------------------------------------------------------------------- - snd_trident_write_pan_reg - - Description: This routine will write the new voice pan - register to hardware. - - Parameters: trident - pointer to target device class for 4DWave. - voice - synthesizer voice structure - Pan - new pan value - - ---------------------------------------------------------------------------*/ - -static void snd_trident_write_pan_reg(struct snd_trident * trident, - struct snd_trident_voice * voice, - unsigned int Pan) -{ - voice->Pan = Pan; - outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); - outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f), - TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3)); -} - -/*--------------------------------------------------------------------------- - snd_trident_write_rvol_reg - - Description: This routine will write the new reverb volume - register to hardware. - - Parameters: trident - pointer to target device class for 4DWave. - voice - synthesizer voice structure - RVol - new reverb volume - - ---------------------------------------------------------------------------*/ - -static void snd_trident_write_rvol_reg(struct snd_trident * trident, - struct snd_trident_voice * voice, - unsigned int RVol) -{ - voice->RVol = RVol; - outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); - outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | - (voice->CVol & 0x007f), - TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? - CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL)); -} - -/*--------------------------------------------------------------------------- - snd_trident_write_cvol_reg - - Description: This routine will write the new chorus volume - register to hardware. - - Parameters: trident - pointer to target device class for 4DWave. - voice - synthesizer voice structure - CVol - new chorus volume - - ---------------------------------------------------------------------------*/ - -static void snd_trident_write_cvol_reg(struct snd_trident * trident, - struct snd_trident_voice * voice, - unsigned int CVol) -{ - voice->CVol = CVol; - outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); - outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | - (voice->CVol & 0x007f), - TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? - CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL)); -} - -/*--------------------------------------------------------------------------- - snd_trident_convert_rate - - Description: This routine converts rate in HZ to hardware delta value. - - Parameters: trident - pointer to target device class for 4DWave. - rate - Real or Virtual channel number. - - Returns: Delta value. - - ---------------------------------------------------------------------------*/ -static unsigned int snd_trident_convert_rate(unsigned int rate) -{ - unsigned int delta; - - // We special case 44100 and 8000 since rounding with the equation - // does not give us an accurate enough value. For 11025 and 22050 - // the equation gives us the best answer. All other frequencies will - // also use the equation. JDW - if (rate == 44100) - delta = 0xeb3; - else if (rate == 8000) - delta = 0x2ab; - else if (rate == 48000) - delta = 0x1000; - else - delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff; - return delta; -} - -/*--------------------------------------------------------------------------- - snd_trident_convert_adc_rate - - Description: This routine converts rate in HZ to hardware delta value. - - Parameters: trident - pointer to target device class for 4DWave. - rate - Real or Virtual channel number. - - Returns: Delta value. - - ---------------------------------------------------------------------------*/ -static unsigned int snd_trident_convert_adc_rate(unsigned int rate) -{ - unsigned int delta; - - // We special case 44100 and 8000 since rounding with the equation - // does not give us an accurate enough value. For 11025 and 22050 - // the equation gives us the best answer. All other frequencies will - // also use the equation. JDW - if (rate == 44100) - delta = 0x116a; - else if (rate == 8000) - delta = 0x6000; - else if (rate == 48000) - delta = 0x1000; - else - delta = ((48000 << 12) / rate) & 0x0000ffff; - return delta; -} - -/*--------------------------------------------------------------------------- - snd_trident_spurious_threshold - - Description: This routine converts rate in HZ to spurious threshold. - - Parameters: trident - pointer to target device class for 4DWave. - rate - Real or Virtual channel number. - - Returns: Delta value. - - ---------------------------------------------------------------------------*/ -static unsigned int snd_trident_spurious_threshold(unsigned int rate, - unsigned int period_size) -{ - unsigned int res = (rate * period_size) / 48000; - if (res < 64) - res = res / 2; - else - res -= 32; - return res; -} - -/*--------------------------------------------------------------------------- - snd_trident_control_mode - - Description: This routine returns a control mode for a PCM channel. - - Parameters: trident - pointer to target device class for 4DWave. - substream - PCM substream - - Returns: Control value. - - ---------------------------------------------------------------------------*/ -static unsigned int snd_trident_control_mode(struct snd_pcm_substream *substream) -{ - unsigned int CTRL; - struct snd_pcm_runtime *runtime = substream->runtime; - - /* set ctrl mode - CTRL default: 8-bit (unsigned) mono, loop mode enabled - */ - CTRL = 0x00000001; - if (snd_pcm_format_width(runtime->format) == 16) - CTRL |= 0x00000008; // 16-bit data - if (snd_pcm_format_signed(runtime->format)) - CTRL |= 0x00000002; // signed data - if (runtime->channels > 1) - CTRL |= 0x00000004; // stereo data - return CTRL; -} - -/* - * PCM part - */ - -/*--------------------------------------------------------------------------- - snd_trident_ioctl - - Description: Device I/O control handler for playback/capture parameters. - - Parameters: substream - PCM substream class - cmd - what ioctl message to process - arg - additional message infoarg - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, - void *arg) -{ - /* FIXME: it seems that with small periods the behaviour of - trident hardware is unpredictable and interrupt generator - is broken */ - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -/*--------------------------------------------------------------------------- - snd_trident_allocate_pcm_mem - - Description: Allocate PCM ring buffer for given substream - - Parameters: substream - PCM substream class - hw_params - hardware parameters - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_allocate_pcm_mem(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - if (trident->tlb.entries) { - if (err > 0) { /* change */ - if (voice->memblk) - snd_trident_free_pages(trident, voice->memblk); - voice->memblk = snd_trident_alloc_pages(trident, substream); - if (voice->memblk == NULL) - return -ENOMEM; - } - } - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_allocate_evoice - - Description: Allocate extra voice as interrupt generator - - Parameters: substream - PCM substream class - hw_params - hardware parameters - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_allocate_evoice(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - struct snd_trident_voice *evoice = voice->extra; - - /* voice management */ - - if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) { - if (evoice == NULL) { - evoice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0); - if (evoice == NULL) - return -ENOMEM; - voice->extra = evoice; - evoice->substream = substream; - } - } else { - if (evoice != NULL) { - snd_trident_free_voice(trident, evoice); - voice->extra = evoice = NULL; - } - } - - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_hw_params - - Description: Set the hardware parameters for the playback device. - - Parameters: substream - PCM substream class - hw_params - hardware parameters - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int err; - - err = snd_trident_allocate_pcm_mem(substream, hw_params); - if (err >= 0) - err = snd_trident_allocate_evoice(substream, hw_params); - return err; -} - -/*--------------------------------------------------------------------------- - snd_trident_playback_hw_free - - Description: Release the hardware resources for the playback device. - - Parameters: substream - PCM substream class - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - struct snd_trident_voice *evoice = voice ? voice->extra : NULL; - - if (trident->tlb.entries) { - if (voice && voice->memblk) { - snd_trident_free_pages(trident, voice->memblk); - voice->memblk = NULL; - } - } - snd_pcm_lib_free_pages(substream); - if (evoice != NULL) { - snd_trident_free_voice(trident, evoice); - voice->extra = NULL; - } - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_playback_prepare - - Description: Prepare playback device for playback. - - Parameters: substream - PCM substream class - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - struct snd_trident_voice *evoice = voice->extra; - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number]; - - spin_lock_irq(&trident->reg_lock); - - /* set delta (rate) value */ - voice->Delta = snd_trident_convert_rate(runtime->rate); - voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size); - - /* set Loop Begin Address */ - if (voice->memblk) - voice->LBA = voice->memblk->offset; - else - voice->LBA = runtime->dma_addr; - - voice->CSO = 0; - voice->ESO = runtime->buffer_size - 1; /* in samples */ - voice->CTRL = snd_trident_control_mode(substream); - voice->FMC = 3; - voice->GVSel = 1; - voice->EC = 0; - voice->Alpha = 0; - voice->FMS = 0; - voice->Vol = mix->vol; - voice->RVol = mix->rvol; - voice->CVol = mix->cvol; - voice->Pan = mix->pan; - voice->Attribute = 0; -#if 0 - voice->Attribute = (1<<(30-16))|(2<<(26-16))| - (0<<(24-16))|(0x1f<<(19-16)); -#else - voice->Attribute = 0; -#endif - - snd_trident_write_voice_regs(trident, voice); - - if (evoice != NULL) { - evoice->Delta = voice->Delta; - evoice->spurious_threshold = voice->spurious_threshold; - evoice->LBA = voice->LBA; - evoice->CSO = 0; - evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */ - evoice->CTRL = voice->CTRL; - evoice->FMC = 3; - evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1; - evoice->EC = 0; - evoice->Alpha = 0; - evoice->FMS = 0; - evoice->Vol = 0x3ff; /* mute */ - evoice->RVol = evoice->CVol = 0x7f; /* mute */ - evoice->Pan = 0x7f; /* mute */ -#if 0 - evoice->Attribute = (1<<(30-16))|(2<<(26-16))| - (0<<(24-16))|(0x1f<<(19-16)); -#else - evoice->Attribute = 0; -#endif - snd_trident_write_voice_regs(trident, evoice); - evoice->isync2 = 1; - evoice->isync_mark = runtime->period_size; - evoice->ESO = (runtime->period_size * 2) - 1; - } - - spin_unlock_irq(&trident->reg_lock); - - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_capture_hw_params - - Description: Set the hardware parameters for the capture device. - - Parameters: substream - PCM substream class - hw_params - hardware parameters - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_trident_allocate_pcm_mem(substream, hw_params); -} - -/*--------------------------------------------------------------------------- - snd_trident_capture_prepare - - Description: Prepare capture device for playback. - - Parameters: substream - PCM substream class - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - unsigned int val, ESO_bytes; - - spin_lock_irq(&trident->reg_lock); - - // Initialize the channel and set channel Mode - outb(0, TRID_REG(trident, LEGACY_DMAR15)); - - // Set DMA channel operation mode register - outb(0x54, TRID_REG(trident, LEGACY_DMAR11)); - - // Set channel buffer Address, DMAR0 expects contiguous PCI memory area - voice->LBA = runtime->dma_addr; - outl(voice->LBA, TRID_REG(trident, LEGACY_DMAR0)); - if (voice->memblk) - voice->LBA = voice->memblk->offset; - - // set ESO - ESO_bytes = snd_pcm_lib_buffer_bytes(substream) - 1; - outb((ESO_bytes & 0x00ff0000) >> 16, TRID_REG(trident, LEGACY_DMAR6)); - outw((ESO_bytes & 0x0000ffff), TRID_REG(trident, LEGACY_DMAR4)); - ESO_bytes++; - - // Set channel sample rate, 4.12 format - val = (((unsigned int) 48000L << 12) + (runtime->rate/2)) / runtime->rate; - outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R)); - - // Set channel interrupt blk length - if (snd_pcm_format_width(runtime->format) == 16) { - val = (unsigned short) ((ESO_bytes >> 1) - 1); - } else { - val = (unsigned short) (ESO_bytes - 1); - } - - outl((val << 16) | val, TRID_REG(trident, T4D_SBBL_SBCL)); - - // Right now, set format and start to run captureing, - // continuous run loop enable. - trident->bDMAStart = 0x19; // 0001 1001b - - if (snd_pcm_format_width(runtime->format) == 16) - trident->bDMAStart |= 0x80; - if (snd_pcm_format_signed(runtime->format)) - trident->bDMAStart |= 0x20; - if (runtime->channels > 1) - trident->bDMAStart |= 0x40; - - // Prepare capture intr channel - - voice->Delta = snd_trident_convert_rate(runtime->rate); - voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size); - voice->isync = 1; - voice->isync_mark = runtime->period_size; - voice->isync_max = runtime->buffer_size; - - // Set voice parameters - voice->CSO = 0; - voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1; - voice->CTRL = snd_trident_control_mode(substream); - voice->FMC = 3; - voice->RVol = 0x7f; - voice->CVol = 0x7f; - voice->GVSel = 1; - voice->Pan = 0x7f; /* mute */ - voice->Vol = 0x3ff; /* mute */ - voice->EC = 0; - voice->Alpha = 0; - voice->FMS = 0; - voice->Attribute = 0; - - snd_trident_write_voice_regs(trident, voice); - - spin_unlock_irq(&trident->reg_lock); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_si7018_capture_hw_params - - Description: Set the hardware parameters for the capture device. - - Parameters: substream - PCM substream class - hw_params - hardware parameters - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_si7018_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - - return snd_trident_allocate_evoice(substream, hw_params); -} - -/*--------------------------------------------------------------------------- - snd_trident_si7018_capture_hw_free - - Description: Release the hardware resources for the capture device. - - Parameters: substream - PCM substream class - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_si7018_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - struct snd_trident_voice *evoice = voice ? voice->extra : NULL; - - snd_pcm_lib_free_pages(substream); - if (evoice != NULL) { - snd_trident_free_voice(trident, evoice); - voice->extra = NULL; - } - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_si7018_capture_prepare - - Description: Prepare capture device for playback. - - Parameters: substream - PCM substream class - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_si7018_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - struct snd_trident_voice *evoice = voice->extra; - - spin_lock_irq(&trident->reg_lock); - - voice->LBA = runtime->dma_addr; - voice->Delta = snd_trident_convert_adc_rate(runtime->rate); - voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size); - - // Set voice parameters - voice->CSO = 0; - voice->ESO = runtime->buffer_size - 1; /* in samples */ - voice->CTRL = snd_trident_control_mode(substream); - voice->FMC = 0; - voice->RVol = 0; - voice->CVol = 0; - voice->GVSel = 1; - voice->Pan = T4D_DEFAULT_PCM_PAN; - voice->Vol = 0; - voice->EC = 0; - voice->Alpha = 0; - voice->FMS = 0; - - voice->Attribute = (2 << (30-16)) | - (2 << (26-16)) | - (2 << (24-16)) | - (1 << (23-16)); - - snd_trident_write_voice_regs(trident, voice); - - if (evoice != NULL) { - evoice->Delta = snd_trident_convert_rate(runtime->rate); - evoice->spurious_threshold = voice->spurious_threshold; - evoice->LBA = voice->LBA; - evoice->CSO = 0; - evoice->ESO = (runtime->period_size * 2) + 20 - 1; /* in samples, 20 means correction */ - evoice->CTRL = voice->CTRL; - evoice->FMC = 3; - evoice->GVSel = 0; - evoice->EC = 0; - evoice->Alpha = 0; - evoice->FMS = 0; - evoice->Vol = 0x3ff; /* mute */ - evoice->RVol = evoice->CVol = 0x7f; /* mute */ - evoice->Pan = 0x7f; /* mute */ - evoice->Attribute = 0; - snd_trident_write_voice_regs(trident, evoice); - evoice->isync2 = 1; - evoice->isync_mark = runtime->period_size; - evoice->ESO = (runtime->period_size * 2) - 1; - } - - spin_unlock_irq(&trident->reg_lock); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_foldback_prepare - - Description: Prepare foldback capture device for playback. - - Parameters: substream - PCM substream class - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_foldback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - struct snd_trident_voice *evoice = voice->extra; - - spin_lock_irq(&trident->reg_lock); - - /* Set channel buffer Address */ - if (voice->memblk) - voice->LBA = voice->memblk->offset; - else - voice->LBA = runtime->dma_addr; - - /* set target ESO for channel */ - voice->ESO = runtime->buffer_size - 1; /* in samples */ - - /* set sample rate */ - voice->Delta = 0x1000; - voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size); - - voice->CSO = 0; - voice->CTRL = snd_trident_control_mode(substream); - voice->FMC = 3; - voice->RVol = 0x7f; - voice->CVol = 0x7f; - voice->GVSel = 1; - voice->Pan = 0x7f; /* mute */ - voice->Vol = 0x3ff; /* mute */ - voice->EC = 0; - voice->Alpha = 0; - voice->FMS = 0; - voice->Attribute = 0; - - /* set up capture channel */ - outb(((voice->number & 0x3f) | 0x80), TRID_REG(trident, T4D_RCI + voice->foldback_chan)); - - snd_trident_write_voice_regs(trident, voice); - - if (evoice != NULL) { - evoice->Delta = voice->Delta; - evoice->spurious_threshold = voice->spurious_threshold; - evoice->LBA = voice->LBA; - evoice->CSO = 0; - evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */ - evoice->CTRL = voice->CTRL; - evoice->FMC = 3; - evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1; - evoice->EC = 0; - evoice->Alpha = 0; - evoice->FMS = 0; - evoice->Vol = 0x3ff; /* mute */ - evoice->RVol = evoice->CVol = 0x7f; /* mute */ - evoice->Pan = 0x7f; /* mute */ - evoice->Attribute = 0; - snd_trident_write_voice_regs(trident, evoice); - evoice->isync2 = 1; - evoice->isync_mark = runtime->period_size; - evoice->ESO = (runtime->period_size * 2) - 1; - } - - spin_unlock_irq(&trident->reg_lock); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_spdif_hw_params - - Description: Set the hardware parameters for the spdif device. - - Parameters: substream - PCM substream class - hw_params - hardware parameters - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_spdif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - unsigned int old_bits = 0, change = 0; - int err; - - err = snd_trident_allocate_pcm_mem(substream, hw_params); - if (err < 0) - return err; - - if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - err = snd_trident_allocate_evoice(substream, hw_params); - if (err < 0) - return err; - } - - /* prepare SPDIF channel */ - spin_lock_irq(&trident->reg_lock); - old_bits = trident->spdif_pcm_bits; - if (old_bits & IEC958_AES0_PROFESSIONAL) - trident->spdif_pcm_bits &= ~IEC958_AES0_PRO_FS; - else - trident->spdif_pcm_bits &= ~(IEC958_AES3_CON_FS << 24); - if (params_rate(hw_params) >= 48000) { - trident->spdif_pcm_ctrl = 0x3c; // 48000 Hz - trident->spdif_pcm_bits |= - trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? - IEC958_AES0_PRO_FS_48000 : - (IEC958_AES3_CON_FS_48000 << 24); - } - else if (params_rate(hw_params) >= 44100) { - trident->spdif_pcm_ctrl = 0x3e; // 44100 Hz - trident->spdif_pcm_bits |= - trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? - IEC958_AES0_PRO_FS_44100 : - (IEC958_AES3_CON_FS_44100 << 24); - } - else { - trident->spdif_pcm_ctrl = 0x3d; // 32000 Hz - trident->spdif_pcm_bits |= - trident->spdif_bits & IEC958_AES0_PROFESSIONAL ? - IEC958_AES0_PRO_FS_32000 : - (IEC958_AES3_CON_FS_32000 << 24); - } - change = old_bits != trident->spdif_pcm_bits; - spin_unlock_irq(&trident->reg_lock); - - if (change) - snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE, &trident->spdif_pcm_ctl->id); - - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_spdif_prepare - - Description: Prepare SPDIF device for playback. - - Parameters: substream - PCM substream class - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_spdif_prepare(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - struct snd_trident_voice *evoice = voice->extra; - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number]; - unsigned int RESO, LBAO; - unsigned int temp; - - spin_lock_irq(&trident->reg_lock); - - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - - /* set delta (rate) value */ - voice->Delta = snd_trident_convert_rate(runtime->rate); - voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size); - - /* set Loop Back Address */ - LBAO = runtime->dma_addr; - if (voice->memblk) - voice->LBA = voice->memblk->offset; - else - voice->LBA = LBAO; - - voice->isync = 1; - voice->isync3 = 1; - voice->isync_mark = runtime->period_size; - voice->isync_max = runtime->buffer_size; - - /* set target ESO for channel */ - RESO = runtime->buffer_size - 1; - voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1; - - /* set ctrl mode */ - voice->CTRL = snd_trident_control_mode(substream); - - voice->FMC = 3; - voice->RVol = 0x7f; - voice->CVol = 0x7f; - voice->GVSel = 1; - voice->Pan = 0x7f; - voice->Vol = 0x3ff; - voice->EC = 0; - voice->CSO = 0; - voice->Alpha = 0; - voice->FMS = 0; - voice->Attribute = 0; - - /* prepare surrogate IRQ channel */ - snd_trident_write_voice_regs(trident, voice); - - outw((RESO & 0xffff), TRID_REG(trident, NX_SPESO)); - outb((RESO >> 16), TRID_REG(trident, NX_SPESO + 2)); - outl((LBAO & 0xfffffffc), TRID_REG(trident, NX_SPLBA)); - outw((voice->CSO & 0xffff), TRID_REG(trident, NX_SPCTRL_SPCSO)); - outb((voice->CSO >> 16), TRID_REG(trident, NX_SPCTRL_SPCSO + 2)); - - /* set SPDIF setting */ - outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3)); - outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS)); - - } else { /* SiS */ - - /* set delta (rate) value */ - voice->Delta = 0x800; - voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size); - - /* set Loop Begin Address */ - if (voice->memblk) - voice->LBA = voice->memblk->offset; - else - voice->LBA = runtime->dma_addr; - - voice->CSO = 0; - voice->ESO = runtime->buffer_size - 1; /* in samples */ - voice->CTRL = snd_trident_control_mode(substream); - voice->FMC = 3; - voice->GVSel = 1; - voice->EC = 0; - voice->Alpha = 0; - voice->FMS = 0; - voice->Vol = mix->vol; - voice->RVol = mix->rvol; - voice->CVol = mix->cvol; - voice->Pan = mix->pan; - voice->Attribute = (1<<(30-16))|(7<<(26-16))| - (0<<(24-16))|(0<<(19-16)); - - snd_trident_write_voice_regs(trident, voice); - - if (evoice != NULL) { - evoice->Delta = voice->Delta; - evoice->spurious_threshold = voice->spurious_threshold; - evoice->LBA = voice->LBA; - evoice->CSO = 0; - evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */ - evoice->CTRL = voice->CTRL; - evoice->FMC = 3; - evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1; - evoice->EC = 0; - evoice->Alpha = 0; - evoice->FMS = 0; - evoice->Vol = 0x3ff; /* mute */ - evoice->RVol = evoice->CVol = 0x7f; /* mute */ - evoice->Pan = 0x7f; /* mute */ - evoice->Attribute = 0; - snd_trident_write_voice_regs(trident, evoice); - evoice->isync2 = 1; - evoice->isync_mark = runtime->period_size; - evoice->ESO = (runtime->period_size * 2) - 1; - } - - outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS)); - temp = inl(TRID_REG(trident, T4D_LFO_GC_CIR)); - temp &= ~(1<<19); - outl(temp, TRID_REG(trident, T4D_LFO_GC_CIR)); - temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - temp |= SPDIF_EN; - outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - } - - spin_unlock_irq(&trident->reg_lock); - - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_trigger - - Description: Start/stop devices - - Parameters: substream - PCM substream class - cmd - trigger command (STOP, GO) - - Returns: Error status - - ---------------------------------------------------------------------------*/ - -static int snd_trident_trigger(struct snd_pcm_substream *substream, - int cmd) - -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *s; - unsigned int what, whati, capture_flag, spdif_flag; - struct snd_trident_voice *voice, *evoice; - unsigned int val, go; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - go = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - go = 0; - break; - default: - return -EINVAL; - } - what = whati = capture_flag = spdif_flag = 0; - spin_lock(&trident->reg_lock); - val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff; - snd_pcm_group_for_each_entry(s, substream) { - if ((struct snd_trident *) snd_pcm_substream_chip(s) == trident) { - voice = s->runtime->private_data; - evoice = voice->extra; - what |= 1 << (voice->number & 0x1f); - if (evoice == NULL) { - whati |= 1 << (voice->number & 0x1f); - } else { - what |= 1 << (evoice->number & 0x1f); - whati |= 1 << (evoice->number & 0x1f); - if (go) - evoice->stimer = val; - } - if (go) { - voice->running = 1; - voice->stimer = val; - } else { - voice->running = 0; - } - snd_pcm_trigger_done(s, substream); - if (voice->capture) - capture_flag = 1; - if (voice->spdif) - spdif_flag = 1; - } - } - if (spdif_flag) { - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS)); - val = trident->spdif_pcm_ctrl; - if (!go) - val &= ~(0x28); - outb(val, TRID_REG(trident, NX_SPCTRL_SPCSO + 3)); - } else { - outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS)); - val = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) | SPDIF_EN; - outl(val, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - } - } - if (!go) - outl(what, TRID_REG(trident, T4D_STOP_B)); - val = inl(TRID_REG(trident, T4D_AINTEN_B)); - if (go) { - val |= whati; - } else { - val &= ~whati; - } - outl(val, TRID_REG(trident, T4D_AINTEN_B)); - if (go) { - outl(what, TRID_REG(trident, T4D_START_B)); - - if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018) - outb(trident->bDMAStart, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD)); - } else { - if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018) - outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD)); - } - spin_unlock(&trident->reg_lock); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_playback_pointer - - Description: This routine return the playback position - - Parameters: substream - PCM substream class - - Returns: position of buffer - - ---------------------------------------------------------------------------*/ - -static snd_pcm_uframes_t snd_trident_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - unsigned int cso; - - if (!voice->running) - return 0; - - spin_lock(&trident->reg_lock); - - outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); - - if (trident->device != TRIDENT_DEVICE_ID_NX) { - cso = inw(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2)); - } else { // ID_4DWAVE_NX - cso = (unsigned int) inl(TRID_REG(trident, CH_NX_DELTA_CSO)) & 0x00ffffff; - } - - spin_unlock(&trident->reg_lock); - - if (cso >= runtime->buffer_size) - cso = 0; - - return cso; -} - -/*--------------------------------------------------------------------------- - snd_trident_capture_pointer - - Description: This routine return the capture position - - Parameters: pcm1 - PCM device class - - Returns: position of buffer - - ---------------------------------------------------------------------------*/ - -static snd_pcm_uframes_t snd_trident_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - unsigned int result; - - if (!voice->running) - return 0; - - result = inw(TRID_REG(trident, T4D_SBBL_SBCL)); - if (runtime->channels > 1) - result >>= 1; - if (result > 0) - result = runtime->buffer_size - result; - - return result; -} - -/*--------------------------------------------------------------------------- - snd_trident_spdif_pointer - - Description: This routine return the SPDIF playback position - - Parameters: substream - PCM substream class - - Returns: position of buffer - - ---------------------------------------------------------------------------*/ - -static snd_pcm_uframes_t snd_trident_spdif_pointer(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - unsigned int result; - - if (!voice->running) - return 0; - - result = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff; - - return result; -} - -/* - * Playback support device description - */ - -static struct snd_pcm_hardware snd_trident_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (256*1024), - .period_bytes_min = 64, - .period_bytes_max = (256*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * Capture support device description - */ - -static struct snd_pcm_hardware snd_trident_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * Foldback capture support device description - */ - -static struct snd_pcm_hardware snd_trident_foldback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * SPDIF playback support device description - */ - -static struct snd_pcm_hardware snd_trident_spdif = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = 32000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_trident_spdif_7018 = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static void snd_trident_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - struct snd_trident_voice *voice = runtime->private_data; - struct snd_trident *trident; - - if (voice) { - trident = voice->trident; - snd_trident_free_voice(trident, voice); - } -} - -static int snd_trident_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice; - - voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0); - if (voice == NULL) - return -EAGAIN; - snd_trident_pcm_mixer_build(trident, voice, substream); - voice->substream = substream; - runtime->private_data = voice; - runtime->private_free = snd_trident_pcm_free_substream; - runtime->hw = snd_trident_playback; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_playback_close - - Description: This routine will close the 4DWave playback device. For now - we will simply free the dma transfer buffer. - - Parameters: substream - PCM substream class - - ---------------------------------------------------------------------------*/ -static int snd_trident_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_trident_voice *voice = runtime->private_data; - - snd_trident_pcm_mixer_free(trident, voice, substream); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_spdif_open - - Description: This routine will open the 4DWave SPDIF device. - - Parameters: substream - PCM substream class - - Returns: status - success or failure flag - - ---------------------------------------------------------------------------*/ - -static int snd_trident_spdif_open(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_trident_voice *voice; - struct snd_pcm_runtime *runtime = substream->runtime; - - voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0); - if (voice == NULL) - return -EAGAIN; - voice->spdif = 1; - voice->substream = substream; - spin_lock_irq(&trident->reg_lock); - trident->spdif_pcm_bits = trident->spdif_bits; - spin_unlock_irq(&trident->reg_lock); - - runtime->private_data = voice; - runtime->private_free = snd_trident_pcm_free_substream; - if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - runtime->hw = snd_trident_spdif; - } else { - runtime->hw = snd_trident_spdif_7018; - } - - trident->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id); - - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); - return 0; -} - - -/*--------------------------------------------------------------------------- - snd_trident_spdif_close - - Description: This routine will close the 4DWave SPDIF device. - - Parameters: substream - PCM substream class - - ---------------------------------------------------------------------------*/ - -static int snd_trident_spdif_close(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - unsigned int temp; - - spin_lock_irq(&trident->reg_lock); - // restore default SPDIF setting - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3)); - outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS)); - } else { - outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); - temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - if (trident->spdif_ctrl) { - temp |= SPDIF_EN; - } else { - temp &= ~SPDIF_EN; - } - outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - } - spin_unlock_irq(&trident->reg_lock); - trident->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_capture_open - - Description: This routine will open the 4DWave capture device. - - Parameters: substream - PCM substream class - - Returns: status - success or failure flag - - ---------------------------------------------------------------------------*/ - -static int snd_trident_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_trident_voice *voice; - struct snd_pcm_runtime *runtime = substream->runtime; - - voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0); - if (voice == NULL) - return -EAGAIN; - voice->capture = 1; - voice->substream = substream; - runtime->private_data = voice; - runtime->private_free = snd_trident_pcm_free_substream; - runtime->hw = snd_trident_capture; - snd_pcm_set_sync(substream); - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_capture_close - - Description: This routine will close the 4DWave capture device. For now - we will simply free the dma transfer buffer. - - Parameters: substream - PCM substream class - - ---------------------------------------------------------------------------*/ -static int snd_trident_capture_close(struct snd_pcm_substream *substream) -{ - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_foldback_open - - Description: This routine will open the 4DWave foldback capture device. - - Parameters: substream - PCM substream class - - Returns: status - success or failure flag - - ---------------------------------------------------------------------------*/ - -static int snd_trident_foldback_open(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_trident_voice *voice; - struct snd_pcm_runtime *runtime = substream->runtime; - - voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0); - if (voice == NULL) - return -EAGAIN; - voice->foldback_chan = substream->number; - voice->substream = substream; - runtime->private_data = voice; - runtime->private_free = snd_trident_pcm_free_substream; - runtime->hw = snd_trident_foldback; - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_foldback_close - - Description: This routine will close the 4DWave foldback capture device. - For now we will simply free the dma transfer buffer. - - Parameters: substream - PCM substream class - - ---------------------------------------------------------------------------*/ -static int snd_trident_foldback_close(struct snd_pcm_substream *substream) -{ - struct snd_trident *trident = snd_pcm_substream_chip(substream); - struct snd_trident_voice *voice; - struct snd_pcm_runtime *runtime = substream->runtime; - voice = runtime->private_data; - - /* stop capture channel */ - spin_lock_irq(&trident->reg_lock); - outb(0x00, TRID_REG(trident, T4D_RCI + voice->foldback_chan)); - spin_unlock_irq(&trident->reg_lock); - return 0; -} - -/*--------------------------------------------------------------------------- - PCM operations - ---------------------------------------------------------------------------*/ - -static struct snd_pcm_ops snd_trident_playback_ops = { - .open = snd_trident_playback_open, - .close = snd_trident_playback_close, - .ioctl = snd_trident_ioctl, - .hw_params = snd_trident_hw_params, - .hw_free = snd_trident_hw_free, - .prepare = snd_trident_playback_prepare, - .trigger = snd_trident_trigger, - .pointer = snd_trident_playback_pointer, -}; - -static struct snd_pcm_ops snd_trident_nx_playback_ops = { - .open = snd_trident_playback_open, - .close = snd_trident_playback_close, - .ioctl = snd_trident_ioctl, - .hw_params = snd_trident_hw_params, - .hw_free = snd_trident_hw_free, - .prepare = snd_trident_playback_prepare, - .trigger = snd_trident_trigger, - .pointer = snd_trident_playback_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -static struct snd_pcm_ops snd_trident_capture_ops = { - .open = snd_trident_capture_open, - .close = snd_trident_capture_close, - .ioctl = snd_trident_ioctl, - .hw_params = snd_trident_capture_hw_params, - .hw_free = snd_trident_hw_free, - .prepare = snd_trident_capture_prepare, - .trigger = snd_trident_trigger, - .pointer = snd_trident_capture_pointer, -}; - -static struct snd_pcm_ops snd_trident_si7018_capture_ops = { - .open = snd_trident_capture_open, - .close = snd_trident_capture_close, - .ioctl = snd_trident_ioctl, - .hw_params = snd_trident_si7018_capture_hw_params, - .hw_free = snd_trident_si7018_capture_hw_free, - .prepare = snd_trident_si7018_capture_prepare, - .trigger = snd_trident_trigger, - .pointer = snd_trident_playback_pointer, -}; - -static struct snd_pcm_ops snd_trident_foldback_ops = { - .open = snd_trident_foldback_open, - .close = snd_trident_foldback_close, - .ioctl = snd_trident_ioctl, - .hw_params = snd_trident_hw_params, - .hw_free = snd_trident_hw_free, - .prepare = snd_trident_foldback_prepare, - .trigger = snd_trident_trigger, - .pointer = snd_trident_playback_pointer, -}; - -static struct snd_pcm_ops snd_trident_nx_foldback_ops = { - .open = snd_trident_foldback_open, - .close = snd_trident_foldback_close, - .ioctl = snd_trident_ioctl, - .hw_params = snd_trident_hw_params, - .hw_free = snd_trident_hw_free, - .prepare = snd_trident_foldback_prepare, - .trigger = snd_trident_trigger, - .pointer = snd_trident_playback_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -static struct snd_pcm_ops snd_trident_spdif_ops = { - .open = snd_trident_spdif_open, - .close = snd_trident_spdif_close, - .ioctl = snd_trident_ioctl, - .hw_params = snd_trident_spdif_hw_params, - .hw_free = snd_trident_hw_free, - .prepare = snd_trident_spdif_prepare, - .trigger = snd_trident_trigger, - .pointer = snd_trident_spdif_pointer, -}; - -static struct snd_pcm_ops snd_trident_spdif_7018_ops = { - .open = snd_trident_spdif_open, - .close = snd_trident_spdif_close, - .ioctl = snd_trident_ioctl, - .hw_params = snd_trident_spdif_hw_params, - .hw_free = snd_trident_hw_free, - .prepare = snd_trident_spdif_prepare, - .trigger = snd_trident_trigger, - .pointer = snd_trident_playback_pointer, -}; - -/*--------------------------------------------------------------------------- - snd_trident_pcm - - Description: This routine registers the 4DWave device for PCM support. - - Parameters: trident - pointer to target device class for 4DWave. - - Returns: None - - ---------------------------------------------------------------------------*/ - -int __devinit snd_trident_pcm(struct snd_trident * trident, - int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm)) < 0) - return err; - - pcm->private_data = trident; - - if (trident->tlb.entries) { - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_nx_playback_ops); - } else { - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_playback_ops); - } - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - trident->device != TRIDENT_DEVICE_ID_SI7018 ? - &snd_trident_capture_ops : - &snd_trident_si7018_capture_ops); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, "Trident 4DWave"); - trident->pcm = pcm; - - if (trident->tlb.entries) { - struct snd_pcm_substream *substream; - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) - snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(trident->pci), - 64*1024, 128*1024); - snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, - SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), - 64*1024, 128*1024); - } else { - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(trident->pci), 64*1024, 128*1024); - } - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_foldback_pcm - - Description: This routine registers the 4DWave device for foldback PCM support. - - Parameters: trident - pointer to target device class for 4DWave. - - Returns: None - - ---------------------------------------------------------------------------*/ - -int __devinit snd_trident_foldback_pcm(struct snd_trident * trident, - int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *foldback; - int err; - int num_chan = 3; - struct snd_pcm_substream *substream; - - if (rpcm) - *rpcm = NULL; - if (trident->device == TRIDENT_DEVICE_ID_NX) - num_chan = 4; - if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0) - return err; - - foldback->private_data = trident; - if (trident->tlb.entries) - snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_nx_foldback_ops); - else - snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_foldback_ops); - foldback->info_flags = 0; - strcpy(foldback->name, "Trident 4DWave"); - substream = foldback->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - strcpy(substream->name, "Front Mixer"); - substream = substream->next; - strcpy(substream->name, "Reverb Mixer"); - substream = substream->next; - strcpy(substream->name, "Chorus Mixer"); - if (num_chan == 4) { - substream = substream->next; - strcpy(substream->name, "Second AC'97 ADC"); - } - trident->foldback = foldback; - - if (trident->tlb.entries) - snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(trident->pci), 0, 128*1024); - else - snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(trident->pci), 64*1024, 128*1024); - - if (rpcm) - *rpcm = foldback; - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_spdif - - Description: This routine registers the 4DWave-NX device for SPDIF support. - - Parameters: trident - pointer to target device class for 4DWave-NX. - - Returns: None - - ---------------------------------------------------------------------------*/ - -int __devinit snd_trident_spdif_pcm(struct snd_trident * trident, - int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *spdif; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0) - return err; - - spdif->private_data = trident; - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_ops); - } else { - snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_7018_ops); - } - spdif->info_flags = 0; - strcpy(spdif->name, "Trident 4DWave IEC958"); - trident->spdif = spdif; - - snd_pcm_lib_preallocate_pages_for_all(spdif, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), 64*1024, 128*1024); - - if (rpcm) - *rpcm = spdif; - return 0; -} - -/* - * Mixer part - */ - - -/*--------------------------------------------------------------------------- - snd_trident_spdif_control - - Description: enable/disable S/PDIF out from ac97 mixer - ---------------------------------------------------------------------------*/ - -#define snd_trident_spdif_control_info snd_ctl_boolean_mono_info - -static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - unsigned char val; - - spin_lock_irq(&trident->reg_lock); - val = trident->spdif_ctrl; - ucontrol->value.integer.value[0] = val == kcontrol->private_value; - spin_unlock_irq(&trident->reg_lock); - return 0; -} - -static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - unsigned char val; - int change; - - val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00; - spin_lock_irq(&trident->reg_lock); - /* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */ - change = trident->spdif_ctrl != val; - trident->spdif_ctrl = val; - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0) { - outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS)); - outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3)); - } - } else { - if (trident->spdif == NULL) { - unsigned int temp; - outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); - temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & ~SPDIF_EN; - if (val) - temp |= SPDIF_EN; - outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - } - } - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_trident_spdif_control __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), - .info = snd_trident_spdif_control_info, - .get = snd_trident_spdif_control_get, - .put = snd_trident_spdif_control_put, - .private_value = 0x28, -}; - -/*--------------------------------------------------------------------------- - snd_trident_spdif_default - - Description: put/get the S/PDIF default settings - ---------------------------------------------------------------------------*/ - -static int snd_trident_spdif_default_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_trident_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&trident->reg_lock); - ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff; - spin_unlock_irq(&trident->reg_lock); - return 0; -} - -static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - spin_lock_irq(&trident->reg_lock); - change = trident->spdif_bits != val; - trident->spdif_bits = val; - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0) - outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS)); - } else { - if (trident->spdif == NULL) - outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); - } - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_trident_spdif_default __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_trident_spdif_default_info, - .get = snd_trident_spdif_default_get, - .put = snd_trident_spdif_default_put -}; - -/*--------------------------------------------------------------------------- - snd_trident_spdif_mask - - Description: put/get the S/PDIF mask - ---------------------------------------------------------------------------*/ - -static int snd_trident_spdif_mask_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_trident_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static struct snd_kcontrol_new snd_trident_spdif_mask __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .info = snd_trident_spdif_mask_info, - .get = snd_trident_spdif_mask_get, -}; - -/*--------------------------------------------------------------------------- - snd_trident_spdif_stream - - Description: put/get the S/PDIF stream settings - ---------------------------------------------------------------------------*/ - -static int snd_trident_spdif_stream_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_trident_spdif_stream_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&trident->reg_lock); - ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff; - spin_unlock_irq(&trident->reg_lock); - return 0; -} - -static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - spin_lock_irq(&trident->reg_lock); - change = trident->spdif_pcm_bits != val; - trident->spdif_pcm_bits = val; - if (trident->spdif != NULL) { - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS)); - } else { - outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); - } - } - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_trident_spdif_stream_info, - .get = snd_trident_spdif_stream_get, - .put = snd_trident_spdif_stream_put -}; - -/*--------------------------------------------------------------------------- - snd_trident_ac97_control - - Description: enable/disable rear path for ac97 - ---------------------------------------------------------------------------*/ - -#define snd_trident_ac97_control_info snd_ctl_boolean_mono_info - -static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - unsigned char val; - - spin_lock_irq(&trident->reg_lock); - val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); - ucontrol->value.integer.value[0] = (val & (1 << kcontrol->private_value)) ? 1 : 0; - spin_unlock_irq(&trident->reg_lock); - return 0; -} - -static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - unsigned char val; - int change = 0; - - spin_lock_irq(&trident->reg_lock); - val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); - val &= ~(1 << kcontrol->private_value); - if (ucontrol->value.integer.value[0]) - val |= 1 << kcontrol->private_value; - change = val != trident->ac97_ctrl; - trident->ac97_ctrl = val; - outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_trident_ac97_rear_control __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Rear Path", - .info = snd_trident_ac97_control_info, - .get = snd_trident_ac97_control_get, - .put = snd_trident_ac97_control_put, - .private_value = 4, -}; - -/*--------------------------------------------------------------------------- - snd_trident_vol_control - - Description: wave & music volume control - ---------------------------------------------------------------------------*/ - -static int snd_trident_vol_control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - unsigned int val; - - val = trident->musicvol_wavevol; - ucontrol->value.integer.value[0] = 255 - ((val >> kcontrol->private_value) & 0xff); - ucontrol->value.integer.value[1] = 255 - ((val >> (kcontrol->private_value + 8)) & 0xff); - return 0; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0); - -static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - spin_lock_irq(&trident->reg_lock); - val = trident->musicvol_wavevol; - val &= ~(0xffff << kcontrol->private_value); - val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) | - ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value; - change = val != trident->musicvol_wavevol; - outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL)); - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Music Playback Volume", - .info = snd_trident_vol_control_info, - .get = snd_trident_vol_control_get, - .put = snd_trident_vol_control_put, - .private_value = 16, - .tlv = { .p = db_scale_gvol }, -}; - -static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Wave Playback Volume", - .info = snd_trident_vol_control_info, - .get = snd_trident_vol_control_get, - .put = snd_trident_vol_control_put, - .private_value = 0, - .tlv = { .p = db_scale_gvol }, -}; - -/*--------------------------------------------------------------------------- - snd_trident_pcm_vol_control - - Description: PCM front volume control - ---------------------------------------------------------------------------*/ - -static int snd_trident_pcm_vol_control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - if (trident->device == TRIDENT_DEVICE_ID_SI7018) - uinfo->value.integer.max = 1023; - return 0; -} - -static int snd_trident_pcm_vol_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)]; - - if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - ucontrol->value.integer.value[0] = 1023 - mix->vol; - } else { - ucontrol->value.integer.value[0] = 255 - (mix->vol>>2); - } - return 0; -} - -static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)]; - unsigned int val; - int change = 0; - - if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - val = 1023 - (ucontrol->value.integer.value[0] & 1023); - } else { - val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2; - } - spin_lock_irq(&trident->reg_lock); - change = val != mix->vol; - mix->vol = val; - if (mix->voice != NULL) - snd_trident_write_vol_reg(trident, mix->voice, val); - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Front Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .count = 32, - .info = snd_trident_pcm_vol_control_info, - .get = snd_trident_pcm_vol_control_get, - .put = snd_trident_pcm_vol_control_put, - /* FIXME: no tlv yet */ -}; - -/*--------------------------------------------------------------------------- - snd_trident_pcm_pan_control - - Description: PCM front pan control - ---------------------------------------------------------------------------*/ - -static int snd_trident_pcm_pan_control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 127; - return 0; -} - -static int snd_trident_pcm_pan_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)]; - - ucontrol->value.integer.value[0] = mix->pan; - if (ucontrol->value.integer.value[0] & 0x40) { - ucontrol->value.integer.value[0] = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)); - } else { - ucontrol->value.integer.value[0] |= 0x40; - } - return 0; -} - -static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)]; - unsigned char val; - int change = 0; - - if (ucontrol->value.integer.value[0] & 0x40) - val = ucontrol->value.integer.value[0] & 0x3f; - else - val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40; - spin_lock_irq(&trident->reg_lock); - change = val != mix->pan; - mix->pan = val; - if (mix->voice != NULL) - snd_trident_write_pan_reg(trident, mix->voice, val); - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_trident_pcm_pan_control __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Pan Playback Control", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .count = 32, - .info = snd_trident_pcm_pan_control_info, - .get = snd_trident_pcm_pan_control_get, - .put = snd_trident_pcm_pan_control_put, -}; - -/*--------------------------------------------------------------------------- - snd_trident_pcm_rvol_control - - Description: PCM reverb volume control - ---------------------------------------------------------------------------*/ - -static int snd_trident_pcm_rvol_control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 127; - return 0; -} - -static int snd_trident_pcm_rvol_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)]; - - ucontrol->value.integer.value[0] = 127 - mix->rvol; - return 0; -} - -static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)]; - unsigned short val; - int change = 0; - - val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f); - spin_lock_irq(&trident->reg_lock); - change = val != mix->rvol; - mix->rvol = val; - if (mix->voice != NULL) - snd_trident_write_rvol_reg(trident, mix->voice, val); - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1); - -static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Reverb Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .count = 32, - .info = snd_trident_pcm_rvol_control_info, - .get = snd_trident_pcm_rvol_control_get, - .put = snd_trident_pcm_rvol_control_put, - .tlv = { .p = db_scale_crvol }, -}; - -/*--------------------------------------------------------------------------- - snd_trident_pcm_cvol_control - - Description: PCM chorus volume control - ---------------------------------------------------------------------------*/ - -static int snd_trident_pcm_cvol_control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 127; - return 0; -} - -static int snd_trident_pcm_cvol_control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)]; - - ucontrol->value.integer.value[0] = 127 - mix->cvol; - return 0; -} - -static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_trident *trident = snd_kcontrol_chip(kcontrol); - struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)]; - unsigned short val; - int change = 0; - - val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f); - spin_lock_irq(&trident->reg_lock); - change = val != mix->cvol; - mix->cvol = val; - if (mix->voice != NULL) - snd_trident_write_cvol_reg(trident, mix->voice, val); - spin_unlock_irq(&trident->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Chorus Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .count = 32, - .info = snd_trident_pcm_cvol_control_info, - .get = snd_trident_pcm_cvol_control_get, - .put = snd_trident_pcm_cvol_control_put, - .tlv = { .p = db_scale_crvol }, -}; - -static void snd_trident_notify_pcm_change1(struct snd_card *card, - struct snd_kcontrol *kctl, - int num, int activate) -{ - struct snd_ctl_elem_id id; - - if (! kctl) - return; - if (activate) - kctl->vd[num].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - else - kctl->vd[num].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - snd_ctl_build_ioff(&id, kctl, num)); -} - -static void snd_trident_notify_pcm_change(struct snd_trident *trident, - struct snd_trident_pcm_mixer *tmix, - int num, int activate) -{ - snd_trident_notify_pcm_change1(trident->card, trident->ctl_vol, num, activate); - snd_trident_notify_pcm_change1(trident->card, trident->ctl_pan, num, activate); - snd_trident_notify_pcm_change1(trident->card, trident->ctl_rvol, num, activate); - snd_trident_notify_pcm_change1(trident->card, trident->ctl_cvol, num, activate); -} - -static int snd_trident_pcm_mixer_build(struct snd_trident *trident, - struct snd_trident_voice *voice, - struct snd_pcm_substream *substream) -{ - struct snd_trident_pcm_mixer *tmix; - - if (snd_BUG_ON(!trident || !voice || !substream)) - return -EINVAL; - tmix = &trident->pcm_mixer[substream->number]; - tmix->voice = voice; - tmix->vol = T4D_DEFAULT_PCM_VOL; - tmix->pan = T4D_DEFAULT_PCM_PAN; - tmix->rvol = T4D_DEFAULT_PCM_RVOL; - tmix->cvol = T4D_DEFAULT_PCM_CVOL; - snd_trident_notify_pcm_change(trident, tmix, substream->number, 1); - return 0; -} - -static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_trident_voice *voice, struct snd_pcm_substream *substream) -{ - struct snd_trident_pcm_mixer *tmix; - - if (snd_BUG_ON(!trident || !substream)) - return -EINVAL; - tmix = &trident->pcm_mixer[substream->number]; - tmix->voice = NULL; - snd_trident_notify_pcm_change(trident, tmix, substream->number, 0); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_mixer - - Description: This routine registers the 4DWave device for mixer support. - - Parameters: trident - pointer to target device class for 4DWave. - - Returns: None - - ---------------------------------------------------------------------------*/ - -static int __devinit snd_trident_mixer(struct snd_trident * trident, int pcm_spdif_device) -{ - struct snd_ac97_template _ac97; - struct snd_card *card = trident->card; - struct snd_kcontrol *kctl; - struct snd_ctl_elem_value *uctl; - int idx, err, retries = 2; - static struct snd_ac97_bus_ops ops = { - .write = snd_trident_codec_write, - .read = snd_trident_codec_read, - }; - - uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); - if (!uctl) - return -ENOMEM; - - if ((err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus)) < 0) - goto __out; - - memset(&_ac97, 0, sizeof(_ac97)); - _ac97.private_data = trident; - trident->ac97_detect = 1; - - __again: - if ((err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97)) < 0) { - if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - if ((err = snd_trident_sis_reset(trident)) < 0) - goto __out; - if (retries-- > 0) - goto __again; - err = -EIO; - } - goto __out; - } - - /* secondary codec? */ - if (trident->device == TRIDENT_DEVICE_ID_SI7018 && - (inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0) { - _ac97.num = 1; - err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97_sec); - if (err < 0) - snd_printk(KERN_ERR "SI7018: the secondary codec - invalid access\n"); -#if 0 // only for my testing purpose --jk - { - struct snd_ac97 *mc97; - err = snd_ac97_modem(trident->card, &_ac97, &mc97); - if (err < 0) - snd_printk(KERN_ERR "snd_ac97_modem returned error %i\n", err); - } -#endif - } - - trident->ac97_detect = 0; - - if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident))) < 0) - goto __out; - kctl->put(kctl, uctl); - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident))) < 0) - goto __out; - kctl->put(kctl, uctl); - outl(trident->musicvol_wavevol = 0x00000000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL)); - } else { - outl(trident->musicvol_wavevol = 0xffff0000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL)); - } - - for (idx = 0; idx < 32; idx++) { - struct snd_trident_pcm_mixer *tmix; - - tmix = &trident->pcm_mixer[idx]; - tmix->voice = NULL; - } - if ((trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident)) == NULL) - goto __nomem; - if ((err = snd_ctl_add(card, trident->ctl_vol))) - goto __out; - - if ((trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident)) == NULL) - goto __nomem; - if ((err = snd_ctl_add(card, trident->ctl_pan))) - goto __out; - - if ((trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident)) == NULL) - goto __nomem; - if ((err = snd_ctl_add(card, trident->ctl_rvol))) - goto __out; - - if ((trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident)) == NULL) - goto __nomem; - if ((err = snd_ctl_add(card, trident->ctl_cvol))) - goto __out; - - if (trident->device == TRIDENT_DEVICE_ID_NX) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident))) < 0) - goto __out; - kctl->put(kctl, uctl); - } - if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) { - - kctl = snd_ctl_new1(&snd_trident_spdif_control, trident); - if (kctl == NULL) { - err = -ENOMEM; - goto __out; - } - if (trident->ac97->ext_id & AC97_EI_SPDIF) - kctl->id.index++; - if (trident->ac97_sec && (trident->ac97_sec->ext_id & AC97_EI_SPDIF)) - kctl->id.index++; - idx = kctl->id.index; - if ((err = snd_ctl_add(card, kctl)) < 0) - goto __out; - kctl->put(kctl, uctl); - - kctl = snd_ctl_new1(&snd_trident_spdif_default, trident); - if (kctl == NULL) { - err = -ENOMEM; - goto __out; - } - kctl->id.index = idx; - kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl)) < 0) - goto __out; - - kctl = snd_ctl_new1(&snd_trident_spdif_mask, trident); - if (kctl == NULL) { - err = -ENOMEM; - goto __out; - } - kctl->id.index = idx; - kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl)) < 0) - goto __out; - - kctl = snd_ctl_new1(&snd_trident_spdif_stream, trident); - if (kctl == NULL) { - err = -ENOMEM; - goto __out; - } - kctl->id.index = idx; - kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl)) < 0) - goto __out; - trident->spdif_pcm_ctl = kctl; - } - - err = 0; - goto __out; - - __nomem: - err = -ENOMEM; - - __out: - kfree(uctl); - - return err; -} - -/* - * gameport interface - */ - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) - -static unsigned char snd_trident_gameport_read(struct gameport *gameport) -{ - struct snd_trident *chip = gameport_get_port_data(gameport); - - if (snd_BUG_ON(!chip)) - return 0; - return inb(TRID_REG(chip, GAMEPORT_LEGACY)); -} - -static void snd_trident_gameport_trigger(struct gameport *gameport) -{ - struct snd_trident *chip = gameport_get_port_data(gameport); - - if (snd_BUG_ON(!chip)) - return; - outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY)); -} - -static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) -{ - struct snd_trident *chip = gameport_get_port_data(gameport); - int i; - - if (snd_BUG_ON(!chip)) - return 0; - - *buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf; - - for (i = 0; i < 4; i++) { - axes[i] = inw(TRID_REG(chip, GAMEPORT_AXES + i * 2)); - if (axes[i] == 0xffff) axes[i] = -1; - } - - return 0; -} - -static int snd_trident_gameport_open(struct gameport *gameport, int mode) -{ - struct snd_trident *chip = gameport_get_port_data(gameport); - - if (snd_BUG_ON(!chip)) - return 0; - - switch (mode) { - case GAMEPORT_MODE_COOKED: - outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR)); - msleep(20); - return 0; - case GAMEPORT_MODE_RAW: - outb(0, TRID_REG(chip, GAMEPORT_GCR)); - return 0; - default: - return -1; - } -} - -int __devinit snd_trident_create_gameport(struct snd_trident *chip) -{ - struct gameport *gp; - - chip->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "trident: cannot allocate memory for gameport\n"); - return -ENOMEM; - } - - gameport_set_name(gp, "Trident 4DWave"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); - gameport_set_dev_parent(gp, &chip->pci->dev); - - gameport_set_port_data(gp, chip); - gp->fuzz = 64; - gp->read = snd_trident_gameport_read; - gp->trigger = snd_trident_gameport_trigger; - gp->cooked_read = snd_trident_gameport_cooked_read; - gp->open = snd_trident_gameport_open; - - gameport_register_port(gp); - - return 0; -} - -static inline void snd_trident_free_gameport(struct snd_trident *chip) -{ - if (chip->gameport) { - gameport_unregister_port(chip->gameport); - chip->gameport = NULL; - } -} -#else -int __devinit snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; } -static inline void snd_trident_free_gameport(struct snd_trident *chip) { } -#endif /* CONFIG_GAMEPORT */ - -/* - * delay for 1 tick - */ -static inline void do_delay(struct snd_trident *chip) -{ - schedule_timeout_uninterruptible(1); -} - -/* - * SiS reset routine - */ - -static int snd_trident_sis_reset(struct snd_trident *trident) -{ - unsigned long end_time; - unsigned int i; - int r; - - r = trident->in_suspend ? 0 : 2; /* count of retries */ - __si7018_retry: - pci_write_config_byte(trident->pci, 0x46, 0x04); /* SOFTWARE RESET */ - udelay(100); - pci_write_config_byte(trident->pci, 0x46, 0x00); - udelay(100); - /* disable AC97 GPIO interrupt */ - outb(0x00, TRID_REG(trident, SI_AC97_GPIO)); - /* initialize serial interface, force cold reset */ - i = PCMOUT|SURROUT|CENTEROUT|LFEOUT|SECONDARY_ID|COLD_RESET; - outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - udelay(1000); - /* remove cold reset */ - i &= ~COLD_RESET; - outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - udelay(2000); - /* wait, until the codec is ready */ - end_time = (jiffies + (HZ * 3) / 4) + 1; - do { - if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0) - goto __si7018_ok; - do_delay(trident); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL))); - if (r-- > 0) { - end_time = jiffies + HZ; - do { - do_delay(trident); - } while (time_after_eq(end_time, jiffies)); - goto __si7018_retry; - } - __si7018_ok: - /* wait for the second codec */ - do { - if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_SECONDARY_READY) != 0) - break; - do_delay(trident); - } while (time_after_eq(end_time, jiffies)); - /* enable 64 channel mode */ - outl(BANK_B_EN, TRID_REG(trident, T4D_LFO_GC_CIR)); - return 0; -} - -/* - * /proc interface - */ - -static void snd_trident_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_trident *trident = entry->private_data; - char *s; - - switch (trident->device) { - case TRIDENT_DEVICE_ID_SI7018: - s = "SiS 7018 Audio"; - break; - case TRIDENT_DEVICE_ID_DX: - s = "Trident 4DWave PCI DX"; - break; - case TRIDENT_DEVICE_ID_NX: - s = "Trident 4DWave PCI NX"; - break; - default: - s = "???"; - } - snd_iprintf(buffer, "%s\n\n", s); - snd_iprintf(buffer, "Spurious IRQs : %d\n", trident->spurious_irq_count); - snd_iprintf(buffer, "Spurious IRQ dlta: %d\n", trident->spurious_irq_max_delta); - if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) - snd_iprintf(buffer, "IEC958 Mixer Out : %s\n", trident->spdif_ctrl == 0x28 ? "on" : "off"); - if (trident->device == TRIDENT_DEVICE_ID_NX) { - snd_iprintf(buffer, "Rear Speakers : %s\n", trident->ac97_ctrl & 0x00000010 ? "on" : "off"); - if (trident->tlb.entries) { - snd_iprintf(buffer,"\nVirtual Memory\n"); - snd_iprintf(buffer, "Memory Maximum : %d\n", trident->tlb.memhdr->size); - snd_iprintf(buffer, "Memory Used : %d\n", trident->tlb.memhdr->used); - snd_iprintf(buffer, "Memory Free : %d\n", snd_util_mem_avail(trident->tlb.memhdr)); - } - } -} - -static void __devinit snd_trident_proc_init(struct snd_trident * trident) -{ - struct snd_info_entry *entry; - const char *s = "trident"; - - if (trident->device == TRIDENT_DEVICE_ID_SI7018) - s = "sis7018"; - if (! snd_card_proc_new(trident->card, s, &entry)) - snd_info_set_text_ops(entry, trident, snd_trident_proc_read); -} - -static int snd_trident_dev_free(struct snd_device *device) -{ - struct snd_trident *trident = device->device_data; - return snd_trident_free(trident); -} - -/*--------------------------------------------------------------------------- - snd_trident_tlb_alloc - - Description: Allocate and set up the TLB page table on 4D NX. - Each entry has 4 bytes (physical PCI address). - - Parameters: trident - pointer to target device class for 4DWave. - - Returns: 0 or negative error code - - ---------------------------------------------------------------------------*/ - -static int __devinit snd_trident_tlb_alloc(struct snd_trident *trident) -{ - int i; - - /* TLB array must be aligned to 16kB !!! so we allocate - 32kB region and correct offset when necessary */ - - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), - 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) { - snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n"); - return -ENOMEM; - } - trident->tlb.entries = (unsigned int*)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4); - trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4); - /* allocate shadow TLB page table (virtual addresses) */ - trident->tlb.shadow_entries = vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long)); - if (trident->tlb.shadow_entries == NULL) { - snd_printk(KERN_ERR "trident: unable to allocate shadow TLB entries\n"); - return -ENOMEM; - } - /* allocate and setup silent page and initialise TLB entries */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), - SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) { - snd_printk(KERN_ERR "trident: unable to allocate silent page\n"); - return -ENOMEM; - } - memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE); - for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) { - trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1)); - trident->tlb.shadow_entries[i] = (unsigned long)trident->tlb.silent_page.area; - } - - /* use emu memory block manager code to manage tlb page allocation */ - trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES); - if (trident->tlb.memhdr == NULL) - return -ENOMEM; - - trident->tlb.memhdr->block_extra_size = sizeof(struct snd_trident_memblk_arg); - return 0; -} - -/* - * initialize 4D DX chip - */ - -static void snd_trident_stop_all_voices(struct snd_trident *trident) -{ - outl(0xffffffff, TRID_REG(trident, T4D_STOP_A)); - outl(0xffffffff, TRID_REG(trident, T4D_STOP_B)); - outl(0, TRID_REG(trident, T4D_AINTEN_A)); - outl(0, TRID_REG(trident, T4D_AINTEN_B)); -} - -static int snd_trident_4d_dx_init(struct snd_trident *trident) -{ - struct pci_dev *pci = trident->pci; - unsigned long end_time; - - /* reset the legacy configuration and whole audio/wavetable block */ - pci_write_config_dword(pci, 0x40, 0); /* DDMA */ - pci_write_config_byte(pci, 0x44, 0); /* ports */ - pci_write_config_byte(pci, 0x45, 0); /* Legacy DMA */ - pci_write_config_byte(pci, 0x46, 4); /* reset */ - udelay(100); - pci_write_config_byte(pci, 0x46, 0); /* release reset */ - udelay(100); - - /* warm reset of the AC'97 codec */ - outl(0x00000001, TRID_REG(trident, DX_ACR2_AC97_COM_STAT)); - udelay(100); - outl(0x00000000, TRID_REG(trident, DX_ACR2_AC97_COM_STAT)); - /* DAC on, disable SB IRQ and try to force ADC valid signal */ - trident->ac97_ctrl = 0x0000004a; - outl(trident->ac97_ctrl, TRID_REG(trident, DX_ACR2_AC97_COM_STAT)); - /* wait, until the codec is ready */ - end_time = (jiffies + (HZ * 3) / 4) + 1; - do { - if ((inl(TRID_REG(trident, DX_ACR2_AC97_COM_STAT)) & 0x0010) != 0) - goto __dx_ok; - do_delay(trident); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 codec ready error\n"); - return -EIO; - - __dx_ok: - snd_trident_stop_all_voices(trident); - - return 0; -} - -/* - * initialize 4D NX chip - */ -static int snd_trident_4d_nx_init(struct snd_trident *trident) -{ - struct pci_dev *pci = trident->pci; - unsigned long end_time; - - /* reset the legacy configuration and whole audio/wavetable block */ - pci_write_config_dword(pci, 0x40, 0); /* DDMA */ - pci_write_config_byte(pci, 0x44, 0); /* ports */ - pci_write_config_byte(pci, 0x45, 0); /* Legacy DMA */ - - pci_write_config_byte(pci, 0x46, 1); /* reset */ - udelay(100); - pci_write_config_byte(pci, 0x46, 0); /* release reset */ - udelay(100); - - /* warm reset of the AC'97 codec */ - outl(0x00000001, TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); - udelay(100); - outl(0x00000000, TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); - /* wait, until the codec is ready */ - end_time = (jiffies + (HZ * 3) / 4) + 1; - do { - if ((inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)) & 0x0008) != 0) - goto __nx_ok; - do_delay(trident); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT))); - return -EIO; - - __nx_ok: - /* DAC on */ - trident->ac97_ctrl = 0x00000002; - outl(trident->ac97_ctrl, TRID_REG(trident, NX_ACR0_AC97_COM_STAT)); - /* disable SB IRQ */ - outl(NX_SB_IRQ_DISABLE, TRID_REG(trident, T4D_MISCINT)); - - snd_trident_stop_all_voices(trident); - - if (trident->tlb.entries != NULL) { - unsigned int i; - /* enable virtual addressing via TLB */ - i = trident->tlb.entries_dmaaddr; - i |= 0x00000001; - outl(i, TRID_REG(trident, NX_TLBC)); - } else { - outl(0, TRID_REG(trident, NX_TLBC)); - } - /* initialize S/PDIF */ - outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS)); - outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3)); - - return 0; -} - -/* - * initialize sis7018 chip - */ -static int snd_trident_sis_init(struct snd_trident *trident) -{ - int err; - - if ((err = snd_trident_sis_reset(trident)) < 0) - return err; - - snd_trident_stop_all_voices(trident); - - /* initialize S/PDIF */ - outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS)); - - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_create - - Description: This routine will create the device specific class for - the 4DWave card. It will also perform basic initialization. - - Parameters: card - which card to create - pci - interface to PCI bus resource info - dma1ptr - playback dma buffer - dma2ptr - capture dma buffer - irqptr - interrupt resource info - - Returns: 4DWave device class private data - - ---------------------------------------------------------------------------*/ - -int __devinit snd_trident_create(struct snd_card *card, - struct pci_dev *pci, - int pcm_streams, - int pcm_spdif_device, - int max_wavetable_size, - struct snd_trident ** rtrident) -{ - struct snd_trident *trident; - int i, err; - struct snd_trident_voice *voice; - struct snd_trident_pcm_mixer *tmix; - static struct snd_device_ops ops = { - .dev_free = snd_trident_dev_free, - }; - - *rtrident = NULL; - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - /* check, if we can restrict PCI DMA transfers to 30 bits */ - if (pci_set_dma_mask(pci, DMA_BIT_MASK(30)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(30)) < 0) { - snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - trident = kzalloc(sizeof(*trident), GFP_KERNEL); - if (trident == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - trident->device = (pci->vendor << 16) | pci->device; - trident->card = card; - trident->pci = pci; - spin_lock_init(&trident->reg_lock); - spin_lock_init(&trident->event_lock); - spin_lock_init(&trident->voice_alloc); - if (pcm_streams < 1) - pcm_streams = 1; - if (pcm_streams > 32) - pcm_streams = 32; - trident->ChanPCM = pcm_streams; - if (max_wavetable_size < 0 ) - max_wavetable_size = 0; - trident->synth.max_size = max_wavetable_size * 1024; - trident->irq = -1; - - trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE); - pci_set_master(pci); - - if ((err = pci_request_regions(pci, "Trident Audio")) < 0) { - kfree(trident); - pci_disable_device(pci); - return err; - } - trident->port = pci_resource_start(pci, 0); - - if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED, - KBUILD_MODNAME, trident)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_trident_free(trident); - return -EBUSY; - } - trident->irq = pci->irq; - - /* allocate 16k-aligned TLB for NX cards */ - trident->tlb.entries = NULL; - trident->tlb.buffer.area = NULL; - if (trident->device == TRIDENT_DEVICE_ID_NX) { - if ((err = snd_trident_tlb_alloc(trident)) < 0) { - snd_trident_free(trident); - return err; - } - } - - trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF; - - /* initialize chip */ - switch (trident->device) { - case TRIDENT_DEVICE_ID_DX: - err = snd_trident_4d_dx_init(trident); - break; - case TRIDENT_DEVICE_ID_NX: - err = snd_trident_4d_nx_init(trident); - break; - case TRIDENT_DEVICE_ID_SI7018: - err = snd_trident_sis_init(trident); - break; - default: - snd_BUG(); - break; - } - if (err < 0) { - snd_trident_free(trident); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops)) < 0) { - snd_trident_free(trident); - return err; - } - - if ((err = snd_trident_mixer(trident, pcm_spdif_device)) < 0) - return err; - - /* initialise synth voices */ - for (i = 0; i < 64; i++) { - voice = &trident->synth.voices[i]; - voice->number = i; - voice->trident = trident; - } - /* initialize pcm mixer entries */ - for (i = 0; i < 32; i++) { - tmix = &trident->pcm_mixer[i]; - tmix->vol = T4D_DEFAULT_PCM_VOL; - tmix->pan = T4D_DEFAULT_PCM_PAN; - tmix->rvol = T4D_DEFAULT_PCM_RVOL; - tmix->cvol = T4D_DEFAULT_PCM_CVOL; - } - - snd_trident_enable_eso(trident); - - snd_trident_proc_init(trident); - snd_card_set_dev(card, &pci->dev); - *rtrident = trident; - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_free - - Description: This routine will free the device specific class for - the 4DWave card. - - Parameters: trident - device specific private data for 4DWave card - - Returns: None. - - ---------------------------------------------------------------------------*/ - -static int snd_trident_free(struct snd_trident *trident) -{ - snd_trident_free_gameport(trident); - snd_trident_disable_eso(trident); - // Disable S/PDIF out - if (trident->device == TRIDENT_DEVICE_ID_NX) - outb(0x00, TRID_REG(trident, NX_SPCTRL_SPCSO + 3)); - else if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); - } - if (trident->irq >= 0) - free_irq(trident->irq, trident); - if (trident->tlb.buffer.area) { - outl(0, TRID_REG(trident, NX_TLBC)); - if (trident->tlb.memhdr) - snd_util_memhdr_free(trident->tlb.memhdr); - if (trident->tlb.silent_page.area) - snd_dma_free_pages(&trident->tlb.silent_page); - vfree(trident->tlb.shadow_entries); - snd_dma_free_pages(&trident->tlb.buffer); - } - pci_release_regions(trident->pci); - pci_disable_device(trident->pci); - kfree(trident); - return 0; -} - -/*--------------------------------------------------------------------------- - snd_trident_interrupt - - Description: ISR for Trident 4DWave device - - Parameters: trident - device specific private data for 4DWave card - - Problems: It seems that Trident chips generates interrupts more than - one time in special cases. The spurious interrupts are - detected via sample timer (T4D_STIMER) and computing - corresponding delta value. The limits are detected with - the method try & fail so it is possible that it won't - work on all computers. [jaroslav] - - Returns: None. - - ---------------------------------------------------------------------------*/ - -static irqreturn_t snd_trident_interrupt(int irq, void *dev_id) -{ - struct snd_trident *trident = dev_id; - unsigned int audio_int, chn_int, stimer, channel, mask, tmp; - int delta; - struct snd_trident_voice *voice; - - audio_int = inl(TRID_REG(trident, T4D_MISCINT)); - if ((audio_int & (ADDRESS_IRQ|MPU401_IRQ)) == 0) - return IRQ_NONE; - if (audio_int & ADDRESS_IRQ) { - // get interrupt status for all channels - spin_lock(&trident->reg_lock); - stimer = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff; - chn_int = inl(TRID_REG(trident, T4D_AINT_A)); - if (chn_int == 0) - goto __skip1; - outl(chn_int, TRID_REG(trident, T4D_AINT_A)); /* ack */ - __skip1: - chn_int = inl(TRID_REG(trident, T4D_AINT_B)); - if (chn_int == 0) - goto __skip2; - for (channel = 63; channel >= 32; channel--) { - mask = 1 << (channel&0x1f); - if ((chn_int & mask) == 0) - continue; - voice = &trident->synth.voices[channel]; - if (!voice->pcm || voice->substream == NULL) { - outl(mask, TRID_REG(trident, T4D_STOP_B)); - continue; - } - delta = (int)stimer - (int)voice->stimer; - if (delta < 0) - delta = -delta; - if ((unsigned int)delta < voice->spurious_threshold) { - /* do some statistics here */ - trident->spurious_irq_count++; - if (trident->spurious_irq_max_delta < (unsigned int)delta) - trident->spurious_irq_max_delta = delta; - continue; - } - voice->stimer = stimer; - if (voice->isync) { - if (!voice->isync3) { - tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL)); - if (trident->bDMAStart & 0x40) - tmp >>= 1; - if (tmp > 0) - tmp = voice->isync_max - tmp; - } else { - tmp = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff; - } - if (tmp < voice->isync_mark) { - if (tmp > 0x10) - tmp = voice->isync_ESO - 7; - else - tmp = voice->isync_ESO + 2; - /* update ESO for IRQ voice to preserve sync */ - snd_trident_stop_voice(trident, voice->number); - snd_trident_write_eso_reg(trident, voice, tmp); - snd_trident_start_voice(trident, voice->number); - } - } else if (voice->isync2) { - voice->isync2 = 0; - /* write original ESO and update CSO for IRQ voice to preserve sync */ - snd_trident_stop_voice(trident, voice->number); - snd_trident_write_cso_reg(trident, voice, voice->isync_mark); - snd_trident_write_eso_reg(trident, voice, voice->ESO); - snd_trident_start_voice(trident, voice->number); - } -#if 0 - if (voice->extra) { - /* update CSO for extra voice to preserve sync */ - snd_trident_stop_voice(trident, voice->extra->number); - snd_trident_write_cso_reg(trident, voice->extra, 0); - snd_trident_start_voice(trident, voice->extra->number); - } -#endif - spin_unlock(&trident->reg_lock); - snd_pcm_period_elapsed(voice->substream); - spin_lock(&trident->reg_lock); - } - outl(chn_int, TRID_REG(trident, T4D_AINT_B)); /* ack */ - __skip2: - spin_unlock(&trident->reg_lock); - } - if (audio_int & MPU401_IRQ) { - if (trident->rmidi) { - snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data); - } else { - inb(TRID_REG(trident, T4D_MPUR0)); - } - } - // outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), TRID_REG(trident, T4D_MISCINT)); - return IRQ_HANDLED; -} - -struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port) -{ - struct snd_trident_voice *pvoice; - unsigned long flags; - int idx; - - spin_lock_irqsave(&trident->voice_alloc, flags); - if (type == SNDRV_TRIDENT_VOICE_TYPE_PCM) { - idx = snd_trident_allocate_pcm_channel(trident); - if(idx < 0) { - spin_unlock_irqrestore(&trident->voice_alloc, flags); - return NULL; - } - pvoice = &trident->synth.voices[idx]; - pvoice->use = 1; - pvoice->pcm = 1; - pvoice->capture = 0; - pvoice->spdif = 0; - pvoice->memblk = NULL; - pvoice->substream = NULL; - spin_unlock_irqrestore(&trident->voice_alloc, flags); - return pvoice; - } - if (type == SNDRV_TRIDENT_VOICE_TYPE_SYNTH) { - idx = snd_trident_allocate_synth_channel(trident); - if(idx < 0) { - spin_unlock_irqrestore(&trident->voice_alloc, flags); - return NULL; - } - pvoice = &trident->synth.voices[idx]; - pvoice->use = 1; - pvoice->synth = 1; - pvoice->client = client; - pvoice->port = port; - pvoice->memblk = NULL; - spin_unlock_irqrestore(&trident->voice_alloc, flags); - return pvoice; - } - if (type == SNDRV_TRIDENT_VOICE_TYPE_MIDI) { - } - spin_unlock_irqrestore(&trident->voice_alloc, flags); - return NULL; -} - -EXPORT_SYMBOL(snd_trident_alloc_voice); - -void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice) -{ - unsigned long flags; - void (*private_free)(struct snd_trident_voice *); - void *private_data; - - if (voice == NULL || !voice->use) - return; - snd_trident_clear_voices(trident, voice->number, voice->number); - spin_lock_irqsave(&trident->voice_alloc, flags); - private_free = voice->private_free; - private_data = voice->private_data; - voice->private_free = NULL; - voice->private_data = NULL; - if (voice->pcm) - snd_trident_free_pcm_channel(trident, voice->number); - if (voice->synth) - snd_trident_free_synth_channel(trident, voice->number); - voice->use = voice->pcm = voice->synth = voice->midi = 0; - voice->capture = voice->spdif = 0; - voice->sample_ops = NULL; - voice->substream = NULL; - voice->extra = NULL; - spin_unlock_irqrestore(&trident->voice_alloc, flags); - if (private_free) - private_free(voice); -} - -EXPORT_SYMBOL(snd_trident_free_voice); - -static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max) -{ - unsigned int i, val, mask[2] = { 0, 0 }; - - if (snd_BUG_ON(v_min > 63 || v_max > 63)) - return; - for (i = v_min; i <= v_max; i++) - mask[i >> 5] |= 1 << (i & 0x1f); - if (mask[0]) { - outl(mask[0], TRID_REG(trident, T4D_STOP_A)); - val = inl(TRID_REG(trident, T4D_AINTEN_A)); - outl(val & ~mask[0], TRID_REG(trident, T4D_AINTEN_A)); - } - if (mask[1]) { - outl(mask[1], TRID_REG(trident, T4D_STOP_B)); - val = inl(TRID_REG(trident, T4D_AINTEN_B)); - outl(val & ~mask[1], TRID_REG(trident, T4D_AINTEN_B)); - } -} - -#ifdef CONFIG_PM -int snd_trident_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_trident *trident = card->private_data; - - trident->in_suspend = 1; - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(trident->pcm); - snd_pcm_suspend_all(trident->foldback); - snd_pcm_suspend_all(trident->spdif); - - snd_ac97_suspend(trident->ac97); - snd_ac97_suspend(trident->ac97_sec); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -int snd_trident_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_trident *trident = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "trident: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - switch (trident->device) { - case TRIDENT_DEVICE_ID_DX: - snd_trident_4d_dx_init(trident); - break; - case TRIDENT_DEVICE_ID_NX: - snd_trident_4d_nx_init(trident); - break; - case TRIDENT_DEVICE_ID_SI7018: - snd_trident_sis_init(trident); - break; - } - - snd_ac97_resume(trident->ac97); - snd_ac97_resume(trident->ac97_sec); - - /* restore some registers */ - outl(trident->musicvol_wavevol, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL)); - - snd_trident_enable_eso(trident); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - trident->in_suspend = 0; - return 0; -} -#endif /* CONFIG_PM */ diff --git a/ANDROID_3.4.5/sound/pci/trident/trident_memory.c b/ANDROID_3.4.5/sound/pci/trident/trident_memory.c deleted file mode 100644 index f9779e23..00000000 --- a/ANDROID_3.4.5/sound/pci/trident/trident_memory.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Copyright (c) by Takashi Iwai - * Copyright (c) by Scott McNab - * - * Trident 4DWave-NX memory page allocation (TLB area) - * Trident chip can handle only 16MByte of the memory at the same time. - * - * - * 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 - -/* page arguments of these two macros are Trident page (4096 bytes), not like - * aligned pages in others - */ -#define __set_tlb_bus(trident,page,ptr,addr) \ - do { (trident)->tlb.entries[page] = cpu_to_le32((addr) & ~(SNDRV_TRIDENT_PAGE_SIZE-1)); \ - (trident)->tlb.shadow_entries[page] = (ptr); } while (0) -#define __tlb_to_ptr(trident,page) \ - (void*)((trident)->tlb.shadow_entries[page]) -#define __tlb_to_addr(trident,page) \ - (dma_addr_t)le32_to_cpu((trident->tlb.entries[page]) & ~(SNDRV_TRIDENT_PAGE_SIZE - 1)) - -#if PAGE_SIZE == 4096 -/* page size == SNDRV_TRIDENT_PAGE_SIZE */ -#define ALIGN_PAGE_SIZE PAGE_SIZE /* minimum page size for allocation */ -#define MAX_ALIGN_PAGES SNDRV_TRIDENT_MAX_PAGES /* maxmium aligned pages */ -/* fill TLB entrie(s) corresponding to page with ptr */ -#define set_tlb_bus(trident,page,ptr,addr) __set_tlb_bus(trident,page,ptr,addr) -/* fill TLB entrie(s) corresponding to page with silence pointer */ -#define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr) -/* get aligned page from offset address */ -#define get_aligned_page(offset) ((offset) >> 12) -/* get offset address from aligned page */ -#define aligned_page_offset(page) ((page) << 12) -/* get buffer address from aligned page */ -#define page_to_ptr(trident,page) __tlb_to_ptr(trident, page) -/* get PCI physical address from aligned page */ -#define page_to_addr(trident,page) __tlb_to_addr(trident, page) - -#elif PAGE_SIZE == 8192 -/* page size == SNDRV_TRIDENT_PAGE_SIZE x 2*/ -#define ALIGN_PAGE_SIZE PAGE_SIZE -#define MAX_ALIGN_PAGES (SNDRV_TRIDENT_MAX_PAGES / 2) -#define get_aligned_page(offset) ((offset) >> 13) -#define aligned_page_offset(page) ((page) << 13) -#define page_to_ptr(trident,page) __tlb_to_ptr(trident, (page) << 1) -#define page_to_addr(trident,page) __tlb_to_addr(trident, (page) << 1) - -/* fill TLB entries -- we need to fill two entries */ -static inline void set_tlb_bus(struct snd_trident *trident, int page, - unsigned long ptr, dma_addr_t addr) -{ - page <<= 1; - __set_tlb_bus(trident, page, ptr, addr); - __set_tlb_bus(trident, page+1, ptr + SNDRV_TRIDENT_PAGE_SIZE, addr + SNDRV_TRIDENT_PAGE_SIZE); -} -static inline void set_silent_tlb(struct snd_trident *trident, int page) -{ - page <<= 1; - __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr); - __set_tlb_bus(trident, page+1, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr); -} - -#else -/* arbitrary size */ -#define UNIT_PAGES (PAGE_SIZE / SNDRV_TRIDENT_PAGE_SIZE) -#define ALIGN_PAGE_SIZE (SNDRV_TRIDENT_PAGE_SIZE * UNIT_PAGES) -#define MAX_ALIGN_PAGES (SNDRV_TRIDENT_MAX_PAGES / UNIT_PAGES) -/* Note: if alignment doesn't match to the maximum size, the last few blocks - * become unusable. To use such blocks, you'll need to check the validity - * of accessing page in set_tlb_bus and set_silent_tlb. search_empty() - * should also check it, too. - */ -#define get_aligned_page(offset) ((offset) / ALIGN_PAGE_SIZE) -#define aligned_page_offset(page) ((page) * ALIGN_PAGE_SIZE) -#define page_to_ptr(trident,page) __tlb_to_ptr(trident, (page) * UNIT_PAGES) -#define page_to_addr(trident,page) __tlb_to_addr(trident, (page) * UNIT_PAGES) - -/* fill TLB entries -- UNIT_PAGES entries must be filled */ -static inline void set_tlb_bus(struct snd_trident *trident, int page, - unsigned long ptr, dma_addr_t addr) -{ - int i; - page *= UNIT_PAGES; - for (i = 0; i < UNIT_PAGES; i++, page++) { - __set_tlb_bus(trident, page, ptr, addr); - ptr += SNDRV_TRIDENT_PAGE_SIZE; - addr += SNDRV_TRIDENT_PAGE_SIZE; - } -} -static inline void set_silent_tlb(struct snd_trident *trident, int page) -{ - int i; - page *= UNIT_PAGES; - for (i = 0; i < UNIT_PAGES; i++, page++) - __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr); -} - -#endif /* PAGE_SIZE */ - -/* calculate buffer pointer from offset address */ -static inline void *offset_ptr(struct snd_trident *trident, int offset) -{ - char *ptr; - ptr = page_to_ptr(trident, get_aligned_page(offset)); - ptr += offset % ALIGN_PAGE_SIZE; - return (void*)ptr; -} - -/* first and last (aligned) pages of memory block */ -#define firstpg(blk) (((struct snd_trident_memblk_arg *)snd_util_memblk_argptr(blk))->first_page) -#define lastpg(blk) (((struct snd_trident_memblk_arg *)snd_util_memblk_argptr(blk))->last_page) - -/* - * search empty pages which may contain given size - */ -static struct snd_util_memblk * -search_empty(struct snd_util_memhdr *hdr, int size) -{ - struct snd_util_memblk *blk, *prev; - int page, psize; - struct list_head *p; - - psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1); - prev = NULL; - page = 0; - list_for_each(p, &hdr->block) { - blk = list_entry(p, struct snd_util_memblk, list); - if (page + psize <= firstpg(blk)) - goto __found_pages; - page = lastpg(blk) + 1; - } - if (page + psize > MAX_ALIGN_PAGES) - return NULL; - -__found_pages: - /* create a new memory block */ - blk = __snd_util_memblk_new(hdr, psize * ALIGN_PAGE_SIZE, p->prev); - if (blk == NULL) - return NULL; - blk->offset = aligned_page_offset(page); /* set aligned offset */ - firstpg(blk) = page; - lastpg(blk) = page + psize - 1; - return blk; -} - - -/* - * check if the given pointer is valid for pages - */ -static int is_valid_page(unsigned long ptr) -{ - if (ptr & ~0x3fffffffUL) { - snd_printk(KERN_ERR "max memory size is 1GB!!\n"); - return 0; - } - if (ptr & (SNDRV_TRIDENT_PAGE_SIZE-1)) { - snd_printk(KERN_ERR "page is not aligned\n"); - return 0; - } - return 1; -} - -/* - * page allocation for DMA (Scatter-Gather version) - */ -static struct snd_util_memblk * -snd_trident_alloc_sg_pages(struct snd_trident *trident, - struct snd_pcm_substream *substream) -{ - struct snd_util_memhdr *hdr; - struct snd_util_memblk *blk; - struct snd_pcm_runtime *runtime = substream->runtime; - int idx, page; - - if (snd_BUG_ON(runtime->dma_bytes <= 0 || - runtime->dma_bytes > SNDRV_TRIDENT_MAX_PAGES * - SNDRV_TRIDENT_PAGE_SIZE)) - return NULL; - hdr = trident->tlb.memhdr; - if (snd_BUG_ON(!hdr)) - return NULL; - - - - mutex_lock(&hdr->block_mutex); - blk = search_empty(hdr, runtime->dma_bytes); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); - return NULL; - } - - /* set TLB entries */ - idx = 0; - for (page = firstpg(blk); page <= lastpg(blk); page++, idx++) { - unsigned long ofs = idx << PAGE_SHIFT; - dma_addr_t addr = snd_pcm_sgbuf_get_addr(substream, ofs); - unsigned long ptr = (unsigned long) - snd_pcm_sgbuf_get_ptr(substream, ofs); - if (! is_valid_page(addr)) { - __snd_util_mem_free(hdr, blk); - mutex_unlock(&hdr->block_mutex); - return NULL; - } - set_tlb_bus(trident, page, ptr, addr); - } - mutex_unlock(&hdr->block_mutex); - return blk; -} - -/* - * page allocation for DMA (contiguous version) - */ -static struct snd_util_memblk * -snd_trident_alloc_cont_pages(struct snd_trident *trident, - struct snd_pcm_substream *substream) -{ - struct snd_util_memhdr *hdr; - struct snd_util_memblk *blk; - int page; - struct snd_pcm_runtime *runtime = substream->runtime; - dma_addr_t addr; - unsigned long ptr; - - if (snd_BUG_ON(runtime->dma_bytes <= 0 || - runtime->dma_bytes > SNDRV_TRIDENT_MAX_PAGES * - SNDRV_TRIDENT_PAGE_SIZE)) - return NULL; - hdr = trident->tlb.memhdr; - if (snd_BUG_ON(!hdr)) - return NULL; - - mutex_lock(&hdr->block_mutex); - blk = search_empty(hdr, runtime->dma_bytes); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); - return NULL; - } - - /* set TLB entries */ - addr = runtime->dma_addr; - ptr = (unsigned long)runtime->dma_area; - for (page = firstpg(blk); page <= lastpg(blk); page++, - ptr += SNDRV_TRIDENT_PAGE_SIZE, addr += SNDRV_TRIDENT_PAGE_SIZE) { - if (! is_valid_page(addr)) { - __snd_util_mem_free(hdr, blk); - mutex_unlock(&hdr->block_mutex); - return NULL; - } - set_tlb_bus(trident, page, ptr, addr); - } - mutex_unlock(&hdr->block_mutex); - return blk; -} - -/* - * page allocation for DMA - */ -struct snd_util_memblk * -snd_trident_alloc_pages(struct snd_trident *trident, - struct snd_pcm_substream *substream) -{ - if (snd_BUG_ON(!trident || !substream)) - return NULL; - if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_SG) - return snd_trident_alloc_sg_pages(trident, substream); - else - return snd_trident_alloc_cont_pages(trident, substream); -} - - -/* - * release DMA buffer from page table - */ -int snd_trident_free_pages(struct snd_trident *trident, - struct snd_util_memblk *blk) -{ - struct snd_util_memhdr *hdr; - int page; - - if (snd_BUG_ON(!trident || !blk)) - return -EINVAL; - - hdr = trident->tlb.memhdr; - mutex_lock(&hdr->block_mutex); - /* reset TLB entries */ - for (page = firstpg(blk); page <= lastpg(blk); page++) - set_silent_tlb(trident, page); - /* free memory block */ - __snd_util_mem_free(hdr, blk); - mutex_unlock(&hdr->block_mutex); - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/via82xx.c b/ANDROID_3.4.5/sound/pci/via82xx.c deleted file mode 100644 index 75630408..00000000 --- a/ANDROID_3.4.5/sound/pci/via82xx.c +++ /dev/null @@ -1,2644 +0,0 @@ -/* - * ALSA driver for VIA VT82xx (South Bridge) - * - * VT82C686A/B/C, VT8233A/C, VT8235 - * - * Copyright (c) 2000 Jaroslav Kysela - * Tjeerd.Mulder - * 2002 Takashi Iwai - * - * 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 - * - */ - -/* - * Changes: - * - * Dec. 19, 2002 Takashi Iwai - * - use the DSX channels for the first pcm playback. - * (on VIA8233, 8233C and 8235 only) - * this will allow you play simultaneously up to 4 streams. - * multi-channel playback is assigned to the second device - * on these chips. - * - support the secondary capture (on VIA8233/C,8235) - * - SPDIF support - * the DSX3 channel can be used for SPDIF output. - * on VIA8233A, this channel is assigned to the second pcm - * playback. - * the card config of alsa-lib will assign the correct - * device for applications. - * - clean up the code, separate low-level initialization - * routines for each chipset. - * - * Sep. 26, 2005 Karsten Wiese - * - Optimize position calculation for the 823x chips. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#define POINTER_DEBUG -#endif - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("VIA VT82xx audio"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}"); - -#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) -#define SUPPORT_JOYSTICK 1 -#endif - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static long mpu_port; -#ifdef SUPPORT_JOYSTICK -static bool joystick; -#endif -static int ac97_clock = 48000; -static char *ac97_quirk; -static int dxs_support; -static int dxs_init_volume = 31; -static int nodelay; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge."); -module_param(mpu_port, long, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port. (VT82C686x only)"); -#ifdef SUPPORT_JOYSTICK -module_param(joystick, bool, 0444); -MODULE_PARM_DESC(joystick, "Enable joystick. (VT82C686x only)"); -#endif -module_param(ac97_clock, int, 0444); -MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); -module_param(ac97_quirk, charp, 0444); -MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); -module_param(dxs_support, int, 0444); -MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); -module_param(dxs_init_volume, int, 0644); -MODULE_PARM_DESC(dxs_init_volume, "initial DXS volume (0-31)"); -module_param(nodelay, int, 0444); -MODULE_PARM_DESC(nodelay, "Disable 500ms init delay"); - -/* just for backward compatibility */ -static bool enable; -module_param(enable, bool, 0444); - - -/* revision numbers for via686 */ -#define VIA_REV_686_A 0x10 -#define VIA_REV_686_B 0x11 -#define VIA_REV_686_C 0x12 -#define VIA_REV_686_D 0x13 -#define VIA_REV_686_E 0x14 -#define VIA_REV_686_H 0x20 - -/* revision numbers for via8233 */ -#define VIA_REV_PRE_8233 0x10 /* not in market */ -#define VIA_REV_8233C 0x20 /* 2 rec, 4 pb, 1 multi-pb */ -#define VIA_REV_8233 0x30 /* 2 rec, 4 pb, 1 multi-pb, spdif */ -#define VIA_REV_8233A 0x40 /* 1 rec, 1 multi-pb, spdf */ -#define VIA_REV_8235 0x50 /* 2 rec, 4 pb, 1 multi-pb, spdif */ -#define VIA_REV_8237 0x60 -#define VIA_REV_8251 0x70 - -/* - * Direct registers - */ - -#define VIAREG(via, x) ((via)->port + VIA_REG_##x) -#define VIADEV_REG(viadev, x) ((viadev)->port + VIA_REG_##x) - -/* common offsets */ -#define VIA_REG_OFFSET_STATUS 0x00 /* byte - channel status */ -#define VIA_REG_STAT_ACTIVE 0x80 /* RO */ -#define VIA8233_SHADOW_STAT_ACTIVE 0x08 /* RO */ -#define VIA_REG_STAT_PAUSED 0x40 /* RO */ -#define VIA_REG_STAT_TRIGGER_QUEUED 0x08 /* RO */ -#define VIA_REG_STAT_STOPPED 0x04 /* RWC */ -#define VIA_REG_STAT_EOL 0x02 /* RWC */ -#define VIA_REG_STAT_FLAG 0x01 /* RWC */ -#define VIA_REG_OFFSET_CONTROL 0x01 /* byte - channel control */ -#define VIA_REG_CTRL_START 0x80 /* WO */ -#define VIA_REG_CTRL_TERMINATE 0x40 /* WO */ -#define VIA_REG_CTRL_AUTOSTART 0x20 -#define VIA_REG_CTRL_PAUSE 0x08 /* RW */ -#define VIA_REG_CTRL_INT_STOP 0x04 -#define VIA_REG_CTRL_INT_EOL 0x02 -#define VIA_REG_CTRL_INT_FLAG 0x01 -#define VIA_REG_CTRL_RESET 0x01 /* RW - probably reset? undocumented */ -#define VIA_REG_CTRL_INT (VIA_REG_CTRL_INT_FLAG | VIA_REG_CTRL_INT_EOL | VIA_REG_CTRL_AUTOSTART) -#define VIA_REG_OFFSET_TYPE 0x02 /* byte - channel type (686 only) */ -#define VIA_REG_TYPE_AUTOSTART 0x80 /* RW - autostart at EOL */ -#define VIA_REG_TYPE_16BIT 0x20 /* RW */ -#define VIA_REG_TYPE_STEREO 0x10 /* RW */ -#define VIA_REG_TYPE_INT_LLINE 0x00 -#define VIA_REG_TYPE_INT_LSAMPLE 0x04 -#define VIA_REG_TYPE_INT_LESSONE 0x08 -#define VIA_REG_TYPE_INT_MASK 0x0c -#define VIA_REG_TYPE_INT_EOL 0x02 -#define VIA_REG_TYPE_INT_FLAG 0x01 -#define VIA_REG_OFFSET_TABLE_PTR 0x04 /* dword - channel table pointer */ -#define VIA_REG_OFFSET_CURR_PTR 0x04 /* dword - channel current pointer */ -#define VIA_REG_OFFSET_STOP_IDX 0x08 /* dword - stop index, channel type, sample rate */ -#define VIA8233_REG_TYPE_16BIT 0x00200000 /* RW */ -#define VIA8233_REG_TYPE_STEREO 0x00100000 /* RW */ -#define VIA_REG_OFFSET_CURR_COUNT 0x0c /* dword - channel current count (24 bit) */ -#define VIA_REG_OFFSET_CURR_INDEX 0x0f /* byte - channel current index (for via8233 only) */ - -#define DEFINE_VIA_REGSET(name,val) \ -enum {\ - VIA_REG_##name##_STATUS = (val),\ - VIA_REG_##name##_CONTROL = (val) + 0x01,\ - VIA_REG_##name##_TYPE = (val) + 0x02,\ - VIA_REG_##name##_TABLE_PTR = (val) + 0x04,\ - VIA_REG_##name##_CURR_PTR = (val) + 0x04,\ - VIA_REG_##name##_STOP_IDX = (val) + 0x08,\ - VIA_REG_##name##_CURR_COUNT = (val) + 0x0c,\ -} - -/* playback block */ -DEFINE_VIA_REGSET(PLAYBACK, 0x00); -DEFINE_VIA_REGSET(CAPTURE, 0x10); -DEFINE_VIA_REGSET(FM, 0x20); - -/* AC'97 */ -#define VIA_REG_AC97 0x80 /* dword */ -#define VIA_REG_AC97_CODEC_ID_MASK (3<<30) -#define VIA_REG_AC97_CODEC_ID_SHIFT 30 -#define VIA_REG_AC97_CODEC_ID_PRIMARY 0x00 -#define VIA_REG_AC97_CODEC_ID_SECONDARY 0x01 -#define VIA_REG_AC97_SECONDARY_VALID (1<<27) -#define VIA_REG_AC97_PRIMARY_VALID (1<<25) -#define VIA_REG_AC97_BUSY (1<<24) -#define VIA_REG_AC97_READ (1<<23) -#define VIA_REG_AC97_CMD_SHIFT 16 -#define VIA_REG_AC97_CMD_MASK 0x7e -#define VIA_REG_AC97_DATA_SHIFT 0 -#define VIA_REG_AC97_DATA_MASK 0xffff - -#define VIA_REG_SGD_SHADOW 0x84 /* dword */ -/* via686 */ -#define VIA_REG_SGD_STAT_PB_FLAG (1<<0) -#define VIA_REG_SGD_STAT_CP_FLAG (1<<1) -#define VIA_REG_SGD_STAT_FM_FLAG (1<<2) -#define VIA_REG_SGD_STAT_PB_EOL (1<<4) -#define VIA_REG_SGD_STAT_CP_EOL (1<<5) -#define VIA_REG_SGD_STAT_FM_EOL (1<<6) -#define VIA_REG_SGD_STAT_PB_STOP (1<<8) -#define VIA_REG_SGD_STAT_CP_STOP (1<<9) -#define VIA_REG_SGD_STAT_FM_STOP (1<<10) -#define VIA_REG_SGD_STAT_PB_ACTIVE (1<<12) -#define VIA_REG_SGD_STAT_CP_ACTIVE (1<<13) -#define VIA_REG_SGD_STAT_FM_ACTIVE (1<<14) -/* via8233 */ -#define VIA8233_REG_SGD_STAT_FLAG (1<<0) -#define VIA8233_REG_SGD_STAT_EOL (1<<1) -#define VIA8233_REG_SGD_STAT_STOP (1<<2) -#define VIA8233_REG_SGD_STAT_ACTIVE (1<<3) -#define VIA8233_INTR_MASK(chan) ((VIA8233_REG_SGD_STAT_FLAG|VIA8233_REG_SGD_STAT_EOL) << ((chan) * 4)) -#define VIA8233_REG_SGD_CHAN_SDX 0 -#define VIA8233_REG_SGD_CHAN_MULTI 4 -#define VIA8233_REG_SGD_CHAN_REC 6 -#define VIA8233_REG_SGD_CHAN_REC1 7 - -#define VIA_REG_GPI_STATUS 0x88 -#define VIA_REG_GPI_INTR 0x8c - -/* multi-channel and capture registers for via8233 */ -DEFINE_VIA_REGSET(MULTPLAY, 0x40); -DEFINE_VIA_REGSET(CAPTURE_8233, 0x60); - -/* via8233-specific registers */ -#define VIA_REG_OFS_PLAYBACK_VOLUME_L 0x02 /* byte */ -#define VIA_REG_OFS_PLAYBACK_VOLUME_R 0x03 /* byte */ -#define VIA_REG_OFS_MULTPLAY_FORMAT 0x02 /* byte - format and channels */ -#define VIA_REG_MULTPLAY_FMT_8BIT 0x00 -#define VIA_REG_MULTPLAY_FMT_16BIT 0x80 -#define VIA_REG_MULTPLAY_FMT_CH_MASK 0x70 /* # channels << 4 (valid = 1,2,4,6) */ -#define VIA_REG_OFS_CAPTURE_FIFO 0x02 /* byte - bit 6 = fifo enable */ -#define VIA_REG_CAPTURE_FIFO_ENABLE 0x40 - -#define VIA_DXS_MAX_VOLUME 31 /* max. volume (attenuation) of reg 0x32/33 */ - -#define VIA_REG_CAPTURE_CHANNEL 0x63 /* byte - input select */ -#define VIA_REG_CAPTURE_CHANNEL_MIC 0x4 -#define VIA_REG_CAPTURE_CHANNEL_LINE 0 -#define VIA_REG_CAPTURE_SELECT_CODEC 0x03 /* recording source codec (0 = primary) */ - -#define VIA_TBL_BIT_FLAG 0x40000000 -#define VIA_TBL_BIT_EOL 0x80000000 - -/* pci space */ -#define VIA_ACLINK_STAT 0x40 -#define VIA_ACLINK_C11_READY 0x20 -#define VIA_ACLINK_C10_READY 0x10 -#define VIA_ACLINK_C01_READY 0x04 /* secondary codec ready */ -#define VIA_ACLINK_LOWPOWER 0x02 /* low-power state */ -#define VIA_ACLINK_C00_READY 0x01 /* primary codec ready */ -#define VIA_ACLINK_CTRL 0x41 -#define VIA_ACLINK_CTRL_ENABLE 0x80 /* 0: disable, 1: enable */ -#define VIA_ACLINK_CTRL_RESET 0x40 /* 0: assert, 1: de-assert */ -#define VIA_ACLINK_CTRL_SYNC 0x20 /* 0: release SYNC, 1: force SYNC hi */ -#define VIA_ACLINK_CTRL_SDO 0x10 /* 0: release SDO, 1: force SDO hi */ -#define VIA_ACLINK_CTRL_VRA 0x08 /* 0: disable VRA, 1: enable VRA */ -#define VIA_ACLINK_CTRL_PCM 0x04 /* 0: disable PCM, 1: enable PCM */ -#define VIA_ACLINK_CTRL_FM 0x02 /* via686 only */ -#define VIA_ACLINK_CTRL_SB 0x01 /* via686 only */ -#define VIA_ACLINK_CTRL_INIT (VIA_ACLINK_CTRL_ENABLE|\ - VIA_ACLINK_CTRL_RESET|\ - VIA_ACLINK_CTRL_PCM|\ - VIA_ACLINK_CTRL_VRA) -#define VIA_FUNC_ENABLE 0x42 -#define VIA_FUNC_MIDI_PNP 0x80 /* FIXME: it's 0x40 in the datasheet! */ -#define VIA_FUNC_MIDI_IRQMASK 0x40 /* FIXME: not documented! */ -#define VIA_FUNC_RX2C_WRITE 0x20 -#define VIA_FUNC_SB_FIFO_EMPTY 0x10 -#define VIA_FUNC_ENABLE_GAME 0x08 -#define VIA_FUNC_ENABLE_FM 0x04 -#define VIA_FUNC_ENABLE_MIDI 0x02 -#define VIA_FUNC_ENABLE_SB 0x01 -#define VIA_PNP_CONTROL 0x43 -#define VIA_FM_NMI_CTRL 0x48 -#define VIA8233_VOLCHG_CTRL 0x48 -#define VIA8233_SPDIF_CTRL 0x49 -#define VIA8233_SPDIF_DX3 0x08 -#define VIA8233_SPDIF_SLOT_MASK 0x03 -#define VIA8233_SPDIF_SLOT_1011 0x00 -#define VIA8233_SPDIF_SLOT_34 0x01 -#define VIA8233_SPDIF_SLOT_78 0x02 -#define VIA8233_SPDIF_SLOT_69 0x03 - -/* - */ - -#define VIA_DXS_AUTO 0 -#define VIA_DXS_ENABLE 1 -#define VIA_DXS_DISABLE 2 -#define VIA_DXS_48K 3 -#define VIA_DXS_NO_VRA 4 -#define VIA_DXS_SRC 5 - - -/* - * pcm stream - */ - -struct snd_via_sg_table { - unsigned int offset; - unsigned int size; -} ; - -#define VIA_TABLE_SIZE 255 -#define VIA_MAX_BUFSIZE (1<<24) - -struct viadev { - unsigned int reg_offset; - unsigned long port; - int direction; /* playback = 0, capture = 1 */ - struct snd_pcm_substream *substream; - int running; - unsigned int tbl_entries; /* # descriptors */ - struct snd_dma_buffer table; - struct snd_via_sg_table *idx_table; - /* for recovery from the unexpected pointer */ - unsigned int lastpos; - unsigned int fragsize; - unsigned int bufsize; - unsigned int bufsize2; - int hwptr_done; /* processed frame position in the buffer */ - int in_interrupt; - int shadow_shift; -}; - - -enum { TYPE_CARD_VIA686 = 1, TYPE_CARD_VIA8233 }; -enum { TYPE_VIA686, TYPE_VIA8233, TYPE_VIA8233A }; - -#define VIA_MAX_DEVS 7 /* 4 playback, 1 multi, 2 capture */ - -struct via_rate_lock { - spinlock_t lock; - int rate; - int used; -}; - -struct via82xx { - int irq; - - unsigned long port; - struct resource *mpu_res; - int chip_type; - unsigned char revision; - - unsigned char old_legacy; - unsigned char old_legacy_cfg; -#ifdef CONFIG_PM - unsigned char legacy_saved; - unsigned char legacy_cfg_saved; - unsigned char spdif_ctrl_saved; - unsigned char capture_src_saved[2]; - unsigned int mpu_port_saved; -#endif - - unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */ - unsigned char playback_volume_c[2]; /* for VIA8233/C/8235; default = 0 */ - - unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */ - - struct pci_dev *pci; - struct snd_card *card; - - unsigned int num_devs; - unsigned int playback_devno, multi_devno, capture_devno; - struct viadev devs[VIA_MAX_DEVS]; - struct via_rate_lock rates[2]; /* playback and capture */ - unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */ - unsigned int no_vra: 1; /* no need to set VRA on DXS channels */ - unsigned int dxs_src: 1; /* use full SRC capabilities of DXS */ - unsigned int spdif_on: 1; /* only spdif rates work to external DACs */ - - struct snd_pcm *pcms[2]; - struct snd_rawmidi *rmidi; - struct snd_kcontrol *dxs_controls[4]; - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97; - unsigned int ac97_clock; - unsigned int ac97_secondary; /* secondary AC'97 codec is present */ - - spinlock_t reg_lock; - struct snd_info_entry *proc_entry; - -#ifdef SUPPORT_JOYSTICK - struct gameport *gameport; -#endif -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_via82xx_ids) = { - /* 0x1106, 0x3058 */ - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686_5), TYPE_CARD_VIA686, }, /* 686A */ - /* 0x1106, 0x3059 */ - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_5), TYPE_CARD_VIA8233, }, /* VT8233 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_via82xx_ids); - -/* - */ - -/* - * allocate and initialize the descriptor buffers - * periods = number of periods - * fragsize = period size in bytes - */ -static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substream, - struct pci_dev *pci, - unsigned int periods, unsigned int fragsize) -{ - unsigned int i, idx, ofs, rest; - struct via82xx *chip = snd_pcm_substream_chip(substream); - - if (dev->table.area == NULL) { - /* the start of each lists must be aligned to 8 bytes, - * but the kernel pages are much bigger, so we don't care - */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8), - &dev->table) < 0) - return -ENOMEM; - } - if (! dev->idx_table) { - dev->idx_table = kmalloc(sizeof(*dev->idx_table) * VIA_TABLE_SIZE, GFP_KERNEL); - if (! dev->idx_table) - return -ENOMEM; - } - - /* fill the entries */ - idx = 0; - ofs = 0; - for (i = 0; i < periods; i++) { - rest = fragsize; - /* fill descriptors for a period. - * a period can be split to several descriptors if it's - * over page boundary. - */ - do { - unsigned int r; - unsigned int flag; - unsigned int addr; - - if (idx >= VIA_TABLE_SIZE) { - snd_printk(KERN_ERR "via82xx: too much table size!\n"); - return -EINVAL; - } - addr = snd_pcm_sgbuf_get_addr(substream, ofs); - ((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr); - r = snd_pcm_sgbuf_get_chunk_size(substream, ofs, rest); - rest -= r; - if (! rest) { - if (i == periods - 1) - flag = VIA_TBL_BIT_EOL; /* buffer boundary */ - else - flag = VIA_TBL_BIT_FLAG; /* period boundary */ - } else - flag = 0; /* period continues to the next */ - /* - printk(KERN_DEBUG "via: tbl %d: at %d size %d " - "(rest %d)\n", idx, ofs, r, rest); - */ - ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); - dev->idx_table[idx].offset = ofs; - dev->idx_table[idx].size = r; - ofs += r; - idx++; - } while (rest > 0); - } - dev->tbl_entries = idx; - dev->bufsize = periods * fragsize; - dev->bufsize2 = dev->bufsize / 2; - dev->fragsize = fragsize; - return 0; -} - - -static int clean_via_table(struct viadev *dev, struct snd_pcm_substream *substream, - struct pci_dev *pci) -{ - if (dev->table.area) { - snd_dma_free_pages(&dev->table); - dev->table.area = NULL; - } - kfree(dev->idx_table); - dev->idx_table = NULL; - return 0; -} - -/* - * Basic I/O - */ - -static inline unsigned int snd_via82xx_codec_xread(struct via82xx *chip) -{ - return inl(VIAREG(chip, AC97)); -} - -static inline void snd_via82xx_codec_xwrite(struct via82xx *chip, unsigned int val) -{ - outl(val, VIAREG(chip, AC97)); -} - -static int snd_via82xx_codec_ready(struct via82xx *chip, int secondary) -{ - unsigned int timeout = 1000; /* 1ms */ - unsigned int val; - - while (timeout-- > 0) { - udelay(1); - if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)) - return val & 0xffff; - } - snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", - secondary, snd_via82xx_codec_xread(chip)); - return -EIO; -} - -static int snd_via82xx_codec_valid(struct via82xx *chip, int secondary) -{ - unsigned int timeout = 1000; /* 1ms */ - unsigned int val, val1; - unsigned int stat = !secondary ? VIA_REG_AC97_PRIMARY_VALID : - VIA_REG_AC97_SECONDARY_VALID; - - while (timeout-- > 0) { - val = snd_via82xx_codec_xread(chip); - val1 = val & (VIA_REG_AC97_BUSY | stat); - if (val1 == stat) - return val & 0xffff; - udelay(1); - } - return -EIO; -} - -static void snd_via82xx_codec_wait(struct snd_ac97 *ac97) -{ - struct via82xx *chip = ac97->private_data; - int err; - err = snd_via82xx_codec_ready(chip, ac97->num); - /* here we need to wait fairly for long time.. */ - if (!nodelay) - msleep(500); -} - -static void snd_via82xx_codec_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct via82xx *chip = ac97->private_data; - unsigned int xval; - - xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; - xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; - xval |= reg << VIA_REG_AC97_CMD_SHIFT; - xval |= val << VIA_REG_AC97_DATA_SHIFT; - snd_via82xx_codec_xwrite(chip, xval); - snd_via82xx_codec_ready(chip, ac97->num); -} - -static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct via82xx *chip = ac97->private_data; - unsigned int xval, val = 0xffff; - int again = 0; - - xval = ac97->num << VIA_REG_AC97_CODEC_ID_SHIFT; - xval |= ac97->num ? VIA_REG_AC97_SECONDARY_VALID : VIA_REG_AC97_PRIMARY_VALID; - xval |= VIA_REG_AC97_READ; - xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT; - while (1) { - if (again++ > 3) { - snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n", - ac97->num, snd_via82xx_codec_xread(chip)); - return 0xffff; - } - snd_via82xx_codec_xwrite(chip, xval); - udelay (20); - if (snd_via82xx_codec_valid(chip, ac97->num) >= 0) { - udelay(25); - val = snd_via82xx_codec_xread(chip); - break; - } - } - return val & 0xffff; -} - -static void snd_via82xx_channel_reset(struct via82xx *chip, struct viadev *viadev) -{ - outb(VIA_REG_CTRL_PAUSE | VIA_REG_CTRL_TERMINATE | VIA_REG_CTRL_RESET, - VIADEV_REG(viadev, OFFSET_CONTROL)); - inb(VIADEV_REG(viadev, OFFSET_CONTROL)); - udelay(50); - /* disable interrupts */ - outb(0x00, VIADEV_REG(viadev, OFFSET_CONTROL)); - /* clear interrupts */ - outb(0x03, VIADEV_REG(viadev, OFFSET_STATUS)); - outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ - // outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); - viadev->lastpos = 0; - viadev->hwptr_done = 0; -} - - -/* - * Interrupt handler - * Used for 686 and 8233A - */ -static irqreturn_t snd_via686_interrupt(int irq, void *dev_id) -{ - struct via82xx *chip = dev_id; - unsigned int status; - unsigned int i; - - status = inl(VIAREG(chip, SGD_SHADOW)); - if (! (status & chip->intr_mask)) { - if (chip->rmidi) - /* check mpu401 interrupt */ - return snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - return IRQ_NONE; - } - - /* check status for each stream */ - spin_lock(&chip->reg_lock); - for (i = 0; i < chip->num_devs; i++) { - struct viadev *viadev = &chip->devs[i]; - unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); - if (! (c_status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED))) - continue; - if (viadev->substream && viadev->running) { - /* - * Update hwptr_done based on 'period elapsed' - * interrupts. We'll use it, when the chip returns 0 - * for OFFSET_CURR_COUNT. - */ - if (c_status & VIA_REG_STAT_EOL) - viadev->hwptr_done = 0; - else - viadev->hwptr_done += viadev->fragsize; - viadev->in_interrupt = c_status; - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(viadev->substream); - spin_lock(&chip->reg_lock); - viadev->in_interrupt = 0; - } - outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ - } - spin_unlock(&chip->reg_lock); - return IRQ_HANDLED; -} - -/* - * Interrupt handler - */ -static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id) -{ - struct via82xx *chip = dev_id; - unsigned int status; - unsigned int i; - int irqreturn = 0; - - /* check status for each stream */ - spin_lock(&chip->reg_lock); - status = inl(VIAREG(chip, SGD_SHADOW)); - - for (i = 0; i < chip->num_devs; i++) { - struct viadev *viadev = &chip->devs[i]; - struct snd_pcm_substream *substream; - unsigned char c_status, shadow_status; - - shadow_status = (status >> viadev->shadow_shift) & - (VIA8233_SHADOW_STAT_ACTIVE|VIA_REG_STAT_EOL| - VIA_REG_STAT_FLAG); - c_status = shadow_status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG); - if (!c_status) - continue; - - substream = viadev->substream; - if (substream && viadev->running) { - /* - * Update hwptr_done based on 'period elapsed' - * interrupts. We'll use it, when the chip returns 0 - * for OFFSET_CURR_COUNT. - */ - if (c_status & VIA_REG_STAT_EOL) - viadev->hwptr_done = 0; - else - viadev->hwptr_done += viadev->fragsize; - viadev->in_interrupt = c_status; - if (shadow_status & VIA8233_SHADOW_STAT_ACTIVE) - viadev->in_interrupt |= VIA_REG_STAT_ACTIVE; - spin_unlock(&chip->reg_lock); - - snd_pcm_period_elapsed(substream); - - spin_lock(&chip->reg_lock); - viadev->in_interrupt = 0; - } - outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ - irqreturn = 1; - } - spin_unlock(&chip->reg_lock); - return IRQ_RETVAL(irqreturn); -} - -/* - * PCM callbacks - */ - -/* - * trigger callback - */ -static int snd_via82xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - unsigned char val; - - if (chip->chip_type != TYPE_VIA686) - val = VIA_REG_CTRL_INT; - else - val = 0; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - val |= VIA_REG_CTRL_START; - viadev->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - val = VIA_REG_CTRL_TERMINATE; - viadev->running = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - val |= VIA_REG_CTRL_PAUSE; - viadev->running = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - viadev->running = 1; - break; - default: - return -EINVAL; - } - outb(val, VIADEV_REG(viadev, OFFSET_CONTROL)); - if (cmd == SNDRV_PCM_TRIGGER_STOP) - snd_via82xx_channel_reset(chip, viadev); - return 0; -} - - -/* - * pointer callbacks - */ - -/* - * calculate the linear position at the given sg-buffer index and the rest count - */ - -#define check_invalid_pos(viadev,pos) \ - ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 ||\ - viadev->lastpos < viadev->bufsize2)) - -static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int idx, - unsigned int count) -{ - unsigned int size, base, res; - - size = viadev->idx_table[idx].size; - base = viadev->idx_table[idx].offset; - res = base + size - count; - if (res >= viadev->bufsize) - res -= viadev->bufsize; - - /* check the validity of the calculated position */ - if (size < count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", - (int)size, (int)count); - res = viadev->lastpos; - } else { - if (! count) { - /* Some mobos report count = 0 on the DMA boundary, - * i.e. count = size indeed. - * Let's check whether this step is above the expected size. - */ - int delta = res - viadev->lastpos; - if (delta < 0) - delta += viadev->bufsize; - if ((unsigned int)delta > viadev->fragsize) - res = base; - } - if (check_invalid_pos(viadev, res)) { -#ifdef POINTER_DEBUG - printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, " - "bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, " - "count = 0x%x\n", idx, viadev->tbl_entries, - viadev->lastpos, viadev->bufsize2, - viadev->idx_table[idx].offset, - viadev->idx_table[idx].size, count); -#endif - /* count register returns full size when end of buffer is reached */ - res = base + size; - if (check_invalid_pos(viadev, res)) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), " - "using last valid pointer\n"); - res = viadev->lastpos; - } - } - } - return res; -} - -/* - * get the current pointer on via686 - */ -static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - unsigned int idx, ptr, count, res; - - if (snd_BUG_ON(!viadev->tbl_entries)) - return 0; - if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) - return 0; - - spin_lock(&chip->reg_lock); - count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)) & 0xffffff; - /* The via686a does not have the current index register, - * so we need to calculate the index from CURR_PTR. - */ - ptr = inl(VIADEV_REG(viadev, OFFSET_CURR_PTR)); - if (ptr <= (unsigned int)viadev->table.addr) - idx = 0; - else /* CURR_PTR holds the address + 8 */ - idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries; - res = calc_linear_pos(viadev, idx, count); - viadev->lastpos = res; /* remember the last position */ - spin_unlock(&chip->reg_lock); - - return bytes_to_frames(substream->runtime, res); -} - -/* - * get the current pointer on via823x - */ -static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - unsigned int idx, count, res; - int status; - - if (snd_BUG_ON(!viadev->tbl_entries)) - return 0; - - spin_lock(&chip->reg_lock); - count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)); - status = viadev->in_interrupt; - if (!status) - status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); - - /* An apparent bug in the 8251 is worked around by sending a - * REG_CTRL_START. */ - if (chip->revision == VIA_REV_8251 && (status & VIA_REG_STAT_EOL)) - snd_via82xx_pcm_trigger(substream, SNDRV_PCM_TRIGGER_START); - - if (!(status & VIA_REG_STAT_ACTIVE)) { - res = 0; - goto unlock; - } - if (count & 0xffffff) { - idx = count >> 24; - if (idx >= viadev->tbl_entries) { -#ifdef POINTER_DEBUG - printk(KERN_DEBUG "fail: invalid idx = %i/%i\n", idx, - viadev->tbl_entries); -#endif - res = viadev->lastpos; - } else { - count &= 0xffffff; - res = calc_linear_pos(viadev, idx, count); - } - } else { - res = viadev->hwptr_done; - if (!viadev->in_interrupt) { - if (status & VIA_REG_STAT_EOL) { - res = 0; - } else - if (status & VIA_REG_STAT_FLAG) { - res += viadev->fragsize; - } - } - } -unlock: - viadev->lastpos = res; - spin_unlock(&chip->reg_lock); - - return bytes_to_frames(substream->runtime, res); -} - - -/* - * hw_params callback: - * allocate the buffer and build up the buffer description table - */ -static int snd_via82xx_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - int err; - - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) - return err; - err = build_via_table(viadev, substream, chip->pci, - params_periods(hw_params), - params_period_bytes(hw_params)); - if (err < 0) - return err; - - return 0; -} - -/* - * hw_free callback: - * clean up the buffer description table and release the buffer - */ -static int snd_via82xx_hw_free(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - - clean_via_table(viadev, substream, chip->pci); - snd_pcm_lib_free_pages(substream); - return 0; -} - - -/* - * set up the table pointer - */ -static void snd_via82xx_set_table_ptr(struct via82xx *chip, struct viadev *viadev) -{ - snd_via82xx_codec_ready(chip, 0); - outl((u32)viadev->table.addr, VIADEV_REG(viadev, OFFSET_TABLE_PTR)); - udelay(20); - snd_via82xx_codec_ready(chip, 0); -} - -/* - * prepare callback for playback and capture on via686 - */ -static void via686_setup_format(struct via82xx *chip, struct viadev *viadev, - struct snd_pcm_runtime *runtime) -{ - snd_via82xx_channel_reset(chip, viadev); - /* this must be set after channel_reset */ - snd_via82xx_set_table_ptr(chip, viadev); - outb(VIA_REG_TYPE_AUTOSTART | - (runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA_REG_TYPE_16BIT : 0) | - (runtime->channels > 1 ? VIA_REG_TYPE_STEREO : 0) | - ((viadev->reg_offset & 0x10) == 0 ? VIA_REG_TYPE_INT_LSAMPLE : 0) | - VIA_REG_TYPE_INT_EOL | - VIA_REG_TYPE_INT_FLAG, VIADEV_REG(viadev, OFFSET_TYPE)); -} - -static int snd_via686_playback_prepare(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate); - snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate); - via686_setup_format(chip, viadev, runtime); - return 0; -} - -static int snd_via686_capture_prepare(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); - via686_setup_format(chip, viadev, runtime); - return 0; -} - -/* - * lock the current rate - */ -static int via_lock_rate(struct via_rate_lock *rec, int rate) -{ - int changed = 0; - - spin_lock_irq(&rec->lock); - if (rec->rate != rate) { - if (rec->rate && rec->used > 1) /* already set */ - changed = -EINVAL; - else { - rec->rate = rate; - changed = 1; - } - } - spin_unlock_irq(&rec->lock); - return changed; -} - -/* - * prepare callback for DSX playback on via823x - */ -static int snd_via8233_playback_prepare(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - int ac97_rate = chip->dxs_src ? 48000 : runtime->rate; - int rate_changed; - u32 rbits; - - if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0) - return rate_changed; - if (rate_changed) - snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, - chip->no_vra ? 48000 : runtime->rate); - if (chip->spdif_on && viadev->reg_offset == 0x30) - snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate); - - if (runtime->rate == 48000) - rbits = 0xfffff; - else - rbits = (0x100000 / 48000) * runtime->rate + - ((0x100000 % 48000) * runtime->rate) / 48000; - snd_BUG_ON(rbits & ~0xfffff); - snd_via82xx_channel_reset(chip, viadev); - snd_via82xx_set_table_ptr(chip, viadev); - outb(chip->playback_volume[viadev->reg_offset / 0x10][0], - VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); - outb(chip->playback_volume[viadev->reg_offset / 0x10][1], - VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); - outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */ - (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */ - rbits | /* rate */ - 0xff000000, /* STOP index is never reached */ - VIADEV_REG(viadev, OFFSET_STOP_IDX)); - udelay(20); - snd_via82xx_codec_ready(chip, 0); - return 0; -} - -/* - * prepare callback for multi-channel playback on via823x - */ -static int snd_via8233_multi_prepare(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int slots; - int fmt; - - if (via_lock_rate(&chip->rates[0], runtime->rate) < 0) - return -EINVAL; - snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate); - snd_ac97_set_rate(chip->ac97, AC97_PCM_SURR_DAC_RATE, runtime->rate); - snd_ac97_set_rate(chip->ac97, AC97_PCM_LFE_DAC_RATE, runtime->rate); - snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate); - snd_via82xx_channel_reset(chip, viadev); - snd_via82xx_set_table_ptr(chip, viadev); - - fmt = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? - VIA_REG_MULTPLAY_FMT_16BIT : VIA_REG_MULTPLAY_FMT_8BIT; - fmt |= runtime->channels << 4; - outb(fmt, VIADEV_REG(viadev, OFS_MULTPLAY_FORMAT)); -#if 0 - if (chip->revision == VIA_REV_8233A) - slots = 0; - else -#endif - { - /* set sample number to slot 3, 4, 7, 8, 6, 9 (for VIA8233/C,8235) */ - /* corresponding to FL, FR, RL, RR, C, LFE ?? */ - switch (runtime->channels) { - case 1: slots = (1<<0) | (1<<4); break; - case 2: slots = (1<<0) | (2<<4); break; - case 3: slots = (1<<0) | (2<<4) | (5<<8); break; - case 4: slots = (1<<0) | (2<<4) | (3<<8) | (4<<12); break; - case 5: slots = (1<<0) | (2<<4) | (3<<8) | (4<<12) | (5<<16); break; - case 6: slots = (1<<0) | (2<<4) | (3<<8) | (4<<12) | (5<<16) | (6<<20); break; - default: slots = 0; break; - } - } - /* STOP index is never reached */ - outl(0xff000000 | slots, VIADEV_REG(viadev, OFFSET_STOP_IDX)); - udelay(20); - snd_via82xx_codec_ready(chip, 0); - return 0; -} - -/* - * prepare callback for capture on via823x - */ -static int snd_via8233_capture_prepare(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (via_lock_rate(&chip->rates[1], runtime->rate) < 0) - return -EINVAL; - snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); - snd_via82xx_channel_reset(chip, viadev); - snd_via82xx_set_table_ptr(chip, viadev); - outb(VIA_REG_CAPTURE_FIFO_ENABLE, VIADEV_REG(viadev, OFS_CAPTURE_FIFO)); - outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | - (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | - 0xff000000, /* STOP index is never reached */ - VIADEV_REG(viadev, OFFSET_STOP_IDX)); - udelay(20); - snd_via82xx_codec_ready(chip, 0); - return 0; -} - - -/* - * pcm hardware definition, identical for both playback and capture - */ -static struct snd_pcm_hardware snd_via82xx_hw = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - /* SNDRV_PCM_INFO_RESUME | */ - SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = VIA_MAX_BUFSIZE, - .period_bytes_min = 32, - .period_bytes_max = VIA_MAX_BUFSIZE / 2, - .periods_min = 2, - .periods_max = VIA_TABLE_SIZE / 2, - .fifo_size = 0, -}; - - -/* - * open callback skeleton - */ -static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - struct via_rate_lock *ratep; - bool use_src = false; - - runtime->hw = snd_via82xx_hw; - - /* set the hw rate condition */ - ratep = &chip->rates[viadev->direction]; - spin_lock_irq(&ratep->lock); - ratep->used++; - if (chip->spdif_on && viadev->reg_offset == 0x30) { - /* DXS#3 and spdif is on */ - runtime->hw.rates = chip->ac97->rates[AC97_RATES_SPDIF]; - snd_pcm_limit_hw_rates(runtime); - } else if (chip->dxs_fixed && viadev->reg_offset < 0x40) { - /* fixed DXS playback rate */ - runtime->hw.rates = SNDRV_PCM_RATE_48000; - runtime->hw.rate_min = runtime->hw.rate_max = 48000; - } else if (chip->dxs_src && viadev->reg_offset < 0x40) { - /* use full SRC capabilities of DXS */ - runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS | - SNDRV_PCM_RATE_8000_48000); - runtime->hw.rate_min = 8000; - runtime->hw.rate_max = 48000; - use_src = true; - } else if (! ratep->rate) { - int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; - runtime->hw.rates = chip->ac97->rates[idx]; - snd_pcm_limit_hw_rates(runtime); - } else { - /* a fixed rate */ - runtime->hw.rates = SNDRV_PCM_RATE_KNOT; - runtime->hw.rate_max = runtime->hw.rate_min = ratep->rate; - } - spin_unlock_irq(&ratep->lock); - - /* we may remove following constaint when we modify table entries - in interrupt */ - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - if (use_src) { - err = snd_pcm_hw_rule_noresample(runtime, 48000); - if (err < 0) - return err; - } - - runtime->private_data = viadev; - viadev->substream = substream; - - return 0; -} - - -/* - * open callback for playback on via686 - */ -static int snd_via686_playback_open(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = &chip->devs[chip->playback_devno + substream->number]; - int err; - - if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0) - return err; - return 0; -} - -/* - * open callback for playback on via823x DXS - */ -static int snd_via8233_playback_open(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev; - unsigned int stream; - int err; - - viadev = &chip->devs[chip->playback_devno + substream->number]; - if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0) - return err; - stream = viadev->reg_offset / 0x10; - if (chip->dxs_controls[stream]) { - chip->playback_volume[stream][0] = - VIA_DXS_MAX_VOLUME - (dxs_init_volume & 31); - chip->playback_volume[stream][1] = - VIA_DXS_MAX_VOLUME - (dxs_init_volume & 31); - chip->dxs_controls[stream]->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - &chip->dxs_controls[stream]->id); - } - return 0; -} - -/* - * open callback for playback on via823x multi-channel - */ -static int snd_via8233_multi_open(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = &chip->devs[chip->multi_devno]; - int err; - /* channels constraint for VIA8233A - * 3 and 5 channels are not supported - */ - static unsigned int channels[] = { - 1, 2, 4, 6 - }; - static struct snd_pcm_hw_constraint_list hw_constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - - if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0) - return err; - substream->runtime->hw.channels_max = 6; - if (chip->revision == VIA_REV_8233A) - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &hw_constraints_channels); - return 0; -} - -/* - * open callback for capture on via686 and via823x - */ -static int snd_via82xx_capture_open(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = &chip->devs[chip->capture_devno + substream->pcm->device]; - - return snd_via82xx_pcm_open(chip, viadev, substream); -} - -/* - * close callback - */ -static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - struct via_rate_lock *ratep; - - /* release the rate lock */ - ratep = &chip->rates[viadev->direction]; - spin_lock_irq(&ratep->lock); - ratep->used--; - if (! ratep->used) - ratep->rate = 0; - spin_unlock_irq(&ratep->lock); - if (! ratep->rate) { - if (! viadev->direction) { - snd_ac97_update_power(chip->ac97, - AC97_PCM_FRONT_DAC_RATE, 0); - snd_ac97_update_power(chip->ac97, - AC97_PCM_SURR_DAC_RATE, 0); - snd_ac97_update_power(chip->ac97, - AC97_PCM_LFE_DAC_RATE, 0); - } else - snd_ac97_update_power(chip->ac97, - AC97_PCM_LR_ADC_RATE, 0); - } - viadev->substream = NULL; - return 0; -} - -static int snd_via8233_playback_close(struct snd_pcm_substream *substream) -{ - struct via82xx *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - unsigned int stream; - - stream = viadev->reg_offset / 0x10; - if (chip->dxs_controls[stream]) { - chip->dxs_controls[stream]->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, - &chip->dxs_controls[stream]->id); - } - return snd_via82xx_pcm_close(substream); -} - - -/* via686 playback callbacks */ -static struct snd_pcm_ops snd_via686_playback_ops = { - .open = snd_via686_playback_open, - .close = snd_via82xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_via82xx_hw_params, - .hw_free = snd_via82xx_hw_free, - .prepare = snd_via686_playback_prepare, - .trigger = snd_via82xx_pcm_trigger, - .pointer = snd_via686_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -/* via686 capture callbacks */ -static struct snd_pcm_ops snd_via686_capture_ops = { - .open = snd_via82xx_capture_open, - .close = snd_via82xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_via82xx_hw_params, - .hw_free = snd_via82xx_hw_free, - .prepare = snd_via686_capture_prepare, - .trigger = snd_via82xx_pcm_trigger, - .pointer = snd_via686_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -/* via823x DSX playback callbacks */ -static struct snd_pcm_ops snd_via8233_playback_ops = { - .open = snd_via8233_playback_open, - .close = snd_via8233_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_via82xx_hw_params, - .hw_free = snd_via82xx_hw_free, - .prepare = snd_via8233_playback_prepare, - .trigger = snd_via82xx_pcm_trigger, - .pointer = snd_via8233_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -/* via823x multi-channel playback callbacks */ -static struct snd_pcm_ops snd_via8233_multi_ops = { - .open = snd_via8233_multi_open, - .close = snd_via82xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_via82xx_hw_params, - .hw_free = snd_via82xx_hw_free, - .prepare = snd_via8233_multi_prepare, - .trigger = snd_via82xx_pcm_trigger, - .pointer = snd_via8233_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -/* via823x capture callbacks */ -static struct snd_pcm_ops snd_via8233_capture_ops = { - .open = snd_via82xx_capture_open, - .close = snd_via82xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_via82xx_hw_params, - .hw_free = snd_via82xx_hw_free, - .prepare = snd_via8233_capture_prepare, - .trigger = snd_via82xx_pcm_trigger, - .pointer = snd_via8233_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - - -static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset, - int shadow_pos, int direction) -{ - chip->devs[idx].reg_offset = reg_offset; - chip->devs[idx].shadow_shift = shadow_pos * 4; - chip->devs[idx].direction = direction; - chip->devs[idx].port = chip->port + reg_offset; -} - -/* - * create pcm instances for VIA8233, 8233C and 8235 (not 8233A) - */ -static int __devinit snd_via8233_pcm_new(struct via82xx *chip) -{ - struct snd_pcm *pcm; - int i, err; - - chip->playback_devno = 0; /* x 4 */ - chip->multi_devno = 4; /* x 1 */ - chip->capture_devno = 5; /* x 2 */ - chip->num_devs = 7; - chip->intr_mask = 0x33033333; /* FLAG|EOL for rec0-1, mc, sdx0-3 */ - - /* PCM #0: 4 DSX playbacks and 1 capture */ - err = snd_pcm_new(chip->card, chip->card->shortname, 0, 4, 1, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops); - pcm->private_data = chip; - strcpy(pcm->name, chip->card->shortname); - chip->pcms[0] = pcm; - /* set up playbacks */ - for (i = 0; i < 4; i++) - init_viadev(chip, i, 0x10 * i, i, 0); - /* capture */ - init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 64*1024, VIA_MAX_BUFSIZE); - - /* PCM #1: multi-channel playback and 2nd capture */ - err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 1, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_multi_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops); - pcm->private_data = chip; - strcpy(pcm->name, chip->card->shortname); - chip->pcms[1] = pcm; - /* set up playback */ - init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0); - /* set up capture */ - init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 7, 1); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 64*1024, VIA_MAX_BUFSIZE); - return 0; -} - -/* - * create pcm instances for VIA8233A - */ -static int __devinit snd_via8233a_pcm_new(struct via82xx *chip) -{ - struct snd_pcm *pcm; - int err; - - chip->multi_devno = 0; - chip->playback_devno = 1; - chip->capture_devno = 2; - chip->num_devs = 3; - chip->intr_mask = 0x03033000; /* FLAG|EOL for rec0, mc, sdx3 */ - - /* PCM #0: multi-channel playback and capture */ - err = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_multi_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops); - pcm->private_data = chip; - strcpy(pcm->name, chip->card->shortname); - chip->pcms[0] = pcm; - /* set up playback */ - init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0); - /* capture */ - init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 64*1024, VIA_MAX_BUFSIZE); - - /* SPDIF supported? */ - if (! ac97_can_spdif(chip->ac97)) - return 0; - - /* PCM #1: DXS3 playback (for spdif) */ - err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 0, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_playback_ops); - pcm->private_data = chip; - strcpy(pcm->name, chip->card->shortname); - chip->pcms[1] = pcm; - /* set up playback */ - init_viadev(chip, chip->playback_devno, 0x30, 3, 0); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 64*1024, VIA_MAX_BUFSIZE); - return 0; -} - -/* - * create a pcm instance for via686a/b - */ -static int __devinit snd_via686_pcm_new(struct via82xx *chip) -{ - struct snd_pcm *pcm; - int err; - - chip->playback_devno = 0; - chip->capture_devno = 1; - chip->num_devs = 2; - chip->intr_mask = 0x77; /* FLAG | EOL for PB, CP, FM */ - - err = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via686_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via686_capture_ops); - pcm->private_data = chip; - strcpy(pcm->name, chip->card->shortname); - chip->pcms[0] = pcm; - init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0, 0); - init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 0, 1); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 64*1024, VIA_MAX_BUFSIZE); - return 0; -} - - -/* - * Mixer part - */ - -static int snd_via8233_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - /* formerly they were "Line" and "Mic", but it looks like that they - * have nothing to do with the actual physical connections... - */ - static char *texts[2] = { - "Input1", "Input2" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item >= 2) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_via8233_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct via82xx *chip = snd_kcontrol_chip(kcontrol); - unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL); - ucontrol->value.enumerated.item[0] = inb(port) & VIA_REG_CAPTURE_CHANNEL_MIC ? 1 : 0; - return 0; -} - -static int snd_via8233_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct via82xx *chip = snd_kcontrol_chip(kcontrol); - unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL); - u8 val, oval; - - spin_lock_irq(&chip->reg_lock); - oval = inb(port); - val = oval & ~VIA_REG_CAPTURE_CHANNEL_MIC; - if (ucontrol->value.enumerated.item[0]) - val |= VIA_REG_CAPTURE_CHANNEL_MIC; - if (val != oval) - outb(val, port); - spin_unlock_irq(&chip->reg_lock); - return val != oval; -} - -static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = { - .name = "Input Source Select", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_via8233_capture_source_info, - .get = snd_via8233_capture_source_get, - .put = snd_via8233_capture_source_put, -}; - -#define snd_via8233_dxs3_spdif_info snd_ctl_boolean_mono_info - -static int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct via82xx *chip = snd_kcontrol_chip(kcontrol); - u8 val; - - pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val); - ucontrol->value.integer.value[0] = (val & VIA8233_SPDIF_DX3) ? 1 : 0; - return 0; -} - -static int snd_via8233_dxs3_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct via82xx *chip = snd_kcontrol_chip(kcontrol); - u8 val, oval; - - pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &oval); - val = oval & ~VIA8233_SPDIF_DX3; - if (ucontrol->value.integer.value[0]) - val |= VIA8233_SPDIF_DX3; - /* save the spdif flag for rate filtering */ - chip->spdif_on = ucontrol->value.integer.value[0] ? 1 : 0; - if (val != oval) { - pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, val); - return 1; - } - return 0; -} - -static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control __devinitdata = { - .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_via8233_dxs3_spdif_info, - .get = snd_via8233_dxs3_spdif_get, - .put = snd_via8233_dxs3_spdif_put, -}; - -static int snd_via8233_dxs_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = VIA_DXS_MAX_VOLUME; - return 0; -} - -static int snd_via8233_dxs_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct via82xx *chip = snd_kcontrol_chip(kcontrol); - unsigned int idx = kcontrol->id.subdevice; - - ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0]; - ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1]; - return 0; -} - -static int snd_via8233_pcmdxs_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct via82xx *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[0]; - ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[1]; - return 0; -} - -static int snd_via8233_dxs_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct via82xx *chip = snd_kcontrol_chip(kcontrol); - unsigned int idx = kcontrol->id.subdevice; - unsigned long port = chip->port + 0x10 * idx; - unsigned char val; - int i, change = 0; - - for (i = 0; i < 2; i++) { - val = ucontrol->value.integer.value[i]; - if (val > VIA_DXS_MAX_VOLUME) - val = VIA_DXS_MAX_VOLUME; - val = VIA_DXS_MAX_VOLUME - val; - change |= val != chip->playback_volume[idx][i]; - if (change) { - chip->playback_volume[idx][i] = val; - outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); - } - } - return change; -} - -static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct via82xx *chip = snd_kcontrol_chip(kcontrol); - unsigned int idx; - unsigned char val; - int i, change = 0; - - for (i = 0; i < 2; i++) { - val = ucontrol->value.integer.value[i]; - if (val > VIA_DXS_MAX_VOLUME) - val = VIA_DXS_MAX_VOLUME; - val = VIA_DXS_MAX_VOLUME - val; - if (val != chip->playback_volume_c[i]) { - change = 1; - chip->playback_volume_c[i] = val; - for (idx = 0; idx < 4; idx++) { - unsigned long port = chip->port + 0x10 * idx; - chip->playback_volume[idx][i] = val; - outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); - } - } - } - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -4650, 150, 1); - -static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = { - .name = "PCM Playback Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .info = snd_via8233_dxs_volume_info, - .get = snd_via8233_pcmdxs_volume_get, - .put = snd_via8233_pcmdxs_volume_put, - .tlv = { .p = db_scale_dxs } -}; - -static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 0, - /* .subdevice set later */ - .name = "PCM Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .info = snd_via8233_dxs_volume_info, - .get = snd_via8233_dxs_volume_get, - .put = snd_via8233_dxs_volume_put, - .tlv = { .p = db_scale_dxs } -}; - -/* - */ - -static void snd_via82xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct via82xx *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct via82xx *chip = ac97->private_data; - chip->ac97 = NULL; -} - -static struct ac97_quirk ac97_quirks[] = { - { - .subvendor = 0x1106, - .subdevice = 0x4161, - .codec_id = 0x56494161, /* VT1612A */ - .name = "Soltek SL-75DRV5", - .type = AC97_TUNE_NONE - }, - { /* FIXME: which codec? */ - .subvendor = 0x1106, - .subdevice = 0x4161, - .name = "ASRock K7VT2", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x110a, - .subdevice = 0x0079, - .name = "Fujitsu Siemens D1289", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1019, - .subdevice = 0x0a81, - .name = "ECS K7VTA3", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1019, - .subdevice = 0x0a85, - .name = "ECS L7VMM2", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1019, - .subdevice = 0x1841, - .name = "ECS K7VTA3", - .type = AC97_TUNE_HP_ONLY - }, - { - .subvendor = 0x1849, - .subdevice = 0x3059, - .name = "ASRock K7VM2", - .type = AC97_TUNE_HP_ONLY /* VT1616 */ - }, - { - .subvendor = 0x14cd, - .subdevice = 0x7002, - .name = "Unknown", - .type = AC97_TUNE_ALC_JACK - }, - { - .subvendor = 0x1071, - .subdevice = 0x8590, - .name = "Mitac Mobo", - .type = AC97_TUNE_ALC_JACK - }, - { - .subvendor = 0x161f, - .subdevice = 0x202b, - .name = "Arima Notebook", - .type = AC97_TUNE_HP_ONLY, - }, - { - .subvendor = 0x161f, - .subdevice = 0x2032, - .name = "Targa Traveller 811", - .type = AC97_TUNE_HP_ONLY, - }, - { - .subvendor = 0x161f, - .subdevice = 0x2032, - .name = "m680x", - .type = AC97_TUNE_HP_ONLY, /* http://launchpad.net/bugs/38546 */ - }, - { - .subvendor = 0x1297, - .subdevice = 0xa232, - .name = "Shuttle AK32VN", - .type = AC97_TUNE_HP_ONLY - }, - { } /* terminator */ -}; - -static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override) -{ - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_via82xx_codec_write, - .read = snd_via82xx_codec_read, - .wait = snd_via82xx_codec_wait, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) - return err; - chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; - chip->ac97_bus->clock = chip->ac97_clock; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_via82xx_mixer_free_ac97; - ac97.pci = chip->pci; - ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) - return err; - - snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override); - - if (chip->chip_type != TYPE_VIA686) { - /* use slot 10/11 */ - snd_ac97_update_bits(chip->ac97, AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4); - } - - return 0; -} - -#ifdef SUPPORT_JOYSTICK -#define JOYSTICK_ADDR 0x200 -static int __devinit snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy) -{ - struct gameport *gp; - struct resource *r; - - if (!joystick) - return -ENODEV; - - r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport"); - if (!r) { - printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n", - JOYSTICK_ADDR); - return -EBUSY; - } - - chip->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n"); - release_and_free_resource(r); - return -ENOMEM; - } - - gameport_set_name(gp, "VIA686 Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); - gameport_set_dev_parent(gp, &chip->pci->dev); - gp->io = JOYSTICK_ADDR; - gameport_set_port_data(gp, r); - - /* Enable legacy joystick port */ - *legacy |= VIA_FUNC_ENABLE_GAME; - pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, *legacy); - - gameport_register_port(chip->gameport); - - return 0; -} - -static void snd_via686_free_gameport(struct via82xx *chip) -{ - if (chip->gameport) { - struct resource *r = gameport_get_port_data(chip->gameport); - - gameport_unregister_port(chip->gameport); - chip->gameport = NULL; - release_and_free_resource(r); - } -} -#else -static inline int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy) -{ - return -ENOSYS; -} -static inline void snd_via686_free_gameport(struct via82xx *chip) { } -#endif - - -/* - * - */ - -static int __devinit snd_via8233_init_misc(struct via82xx *chip) -{ - int i, err, caps; - unsigned char val; - - caps = chip->chip_type == TYPE_VIA8233A ? 1 : 2; - for (i = 0; i < caps; i++) { - snd_via8233_capture_source.index = i; - err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_capture_source, chip)); - if (err < 0) - return err; - } - if (ac97_can_spdif(chip->ac97)) { - err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip)); - if (err < 0) - return err; - } - if (chip->chip_type != TYPE_VIA8233A) { - /* when no h/w PCM volume control is found, use DXS volume control - * as the PCM vol control - */ - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - strcpy(sid.name, "PCM Playback Volume"); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - if (! snd_ctl_find_id(chip->card, &sid)) { - snd_printd(KERN_INFO "Using DXS as PCM Playback\n"); - err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_pcmdxs_volume_control, chip)); - if (err < 0) - return err; - } - else /* Using DXS when PCM emulation is enabled is really weird */ - { - for (i = 0; i < 4; ++i) { - struct snd_kcontrol *kctl; - - kctl = snd_ctl_new1( - &snd_via8233_dxs_volume_control, chip); - if (!kctl) - return -ENOMEM; - kctl->id.subdevice = i; - err = snd_ctl_add(chip->card, kctl); - if (err < 0) - return err; - chip->dxs_controls[i] = kctl; - } - } - } - /* select spdif data slot 10/11 */ - pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val); - val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011; - val &= ~VIA8233_SPDIF_DX3; /* SPDIF off as default */ - pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, val); - - return 0; -} - -static int __devinit snd_via686_init_misc(struct via82xx *chip) -{ - unsigned char legacy, legacy_cfg; - int rev_h = 0; - - legacy = chip->old_legacy; - legacy_cfg = chip->old_legacy_cfg; - legacy |= VIA_FUNC_MIDI_IRQMASK; /* FIXME: correct? (disable MIDI) */ - legacy &= ~VIA_FUNC_ENABLE_GAME; /* disable joystick */ - if (chip->revision >= VIA_REV_686_H) { - rev_h = 1; - if (mpu_port >= 0x200) { /* force MIDI */ - mpu_port &= 0xfffc; - pci_write_config_dword(chip->pci, 0x18, mpu_port | 0x01); -#ifdef CONFIG_PM - chip->mpu_port_saved = mpu_port; -#endif - } else { - mpu_port = pci_resource_start(chip->pci, 2); - } - } else { - switch (mpu_port) { /* force MIDI */ - case 0x300: - case 0x310: - case 0x320: - case 0x330: - legacy_cfg &= ~(3 << 2); - legacy_cfg |= (mpu_port & 0x0030) >> 2; - break; - default: /* no, use BIOS settings */ - if (legacy & VIA_FUNC_ENABLE_MIDI) - mpu_port = 0x300 + ((legacy_cfg & 0x000c) << 2); - break; - } - } - if (mpu_port >= 0x200 && - (chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401")) - != NULL) { - if (rev_h) - legacy |= VIA_FUNC_MIDI_PNP; /* enable PCI I/O 2 */ - legacy |= VIA_FUNC_ENABLE_MIDI; - } else { - if (rev_h) - legacy &= ~VIA_FUNC_MIDI_PNP; /* disable PCI I/O 2 */ - legacy &= ~VIA_FUNC_ENABLE_MIDI; - mpu_port = 0; - } - - pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); - pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); - if (chip->mpu_res) { - if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, - mpu_port, MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, -1, - &chip->rmidi) < 0) { - printk(KERN_WARNING "unable to initialize MPU-401" - " at 0x%lx, skipping\n", mpu_port); - legacy &= ~VIA_FUNC_ENABLE_MIDI; - } else { - legacy &= ~VIA_FUNC_MIDI_IRQMASK; /* enable MIDI interrupt */ - } - pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy); - } - - snd_via686_create_gameport(chip, &legacy); - -#ifdef CONFIG_PM - chip->legacy_saved = legacy; - chip->legacy_cfg_saved = legacy_cfg; -#endif - - return 0; -} - - -/* - * proc interface - */ -static void snd_via82xx_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct via82xx *chip = entry->private_data; - int i; - - snd_iprintf(buffer, "%s\n\n", chip->card->longname); - for (i = 0; i < 0xa0; i += 4) { - snd_iprintf(buffer, "%02x: %08x\n", i, inl(chip->port + i)); - } -} - -static void __devinit snd_via82xx_proc_init(struct via82xx *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "via82xx", &entry)) - snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read); -} - -/* - * - */ - -static int snd_via82xx_chip_init(struct via82xx *chip) -{ - unsigned int val; - unsigned long end_time; - unsigned char pval; - -#if 0 /* broken on K7M? */ - if (chip->chip_type == TYPE_VIA686) - /* disable all legacy ports */ - pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, 0); -#endif - pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); - if (! (pval & VIA_ACLINK_C00_READY)) { /* codec not ready? */ - /* deassert ACLink reset, force SYNC */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, - VIA_ACLINK_CTRL_ENABLE | - VIA_ACLINK_CTRL_RESET | - VIA_ACLINK_CTRL_SYNC); - udelay(100); -#if 1 /* FIXME: should we do full reset here for all chip models? */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00); - udelay(100); -#else - /* deassert ACLink reset, force SYNC (warm AC'97 reset) */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, - VIA_ACLINK_CTRL_RESET|VIA_ACLINK_CTRL_SYNC); - udelay(2); -#endif - /* ACLink on, deassert ACLink reset, VSR, SGD data out */ - /* note - FM data out has trouble with non VRA codecs !! */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT); - udelay(100); - } - - /* Make sure VRA is enabled, in case we didn't do a - * complete codec reset, above */ - pci_read_config_byte(chip->pci, VIA_ACLINK_CTRL, &pval); - if ((pval & VIA_ACLINK_CTRL_INIT) != VIA_ACLINK_CTRL_INIT) { - /* ACLink on, deassert ACLink reset, VSR, SGD data out */ - /* note - FM data out has trouble with non VRA codecs !! */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT); - udelay(100); - } - - /* wait until codec ready */ - end_time = jiffies + msecs_to_jiffies(750); - do { - pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); - if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ - break; - schedule_timeout_uninterruptible(1); - } while (time_before(jiffies, end_time)); - - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) - snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); - -#if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */ - snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | - VIA_REG_AC97_SECONDARY_VALID | - (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); - end_time = jiffies + msecs_to_jiffies(750); - snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | - VIA_REG_AC97_SECONDARY_VALID | - (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); - do { - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) { - chip->ac97_secondary = 1; - goto __ac97_ok2; - } - schedule_timeout_uninterruptible(1); - } while (time_before(jiffies, end_time)); - /* This is ok, the most of motherboards have only one codec */ - - __ac97_ok2: -#endif - - if (chip->chip_type == TYPE_VIA686) { - /* route FM trap to IRQ, disable FM trap */ - pci_write_config_byte(chip->pci, VIA_FM_NMI_CTRL, 0); - /* disable all GPI interrupts */ - outl(0, VIAREG(chip, GPI_INTR)); - } - - if (chip->chip_type != TYPE_VIA686) { - /* Workaround for Award BIOS bug: - * DXS channels don't work properly with VRA if MC97 is disabled. - */ - struct pci_dev *pci; - pci = pci_get_device(0x1106, 0x3068, NULL); /* MC97 */ - if (pci) { - unsigned char data; - pci_read_config_byte(pci, 0x44, &data); - pci_write_config_byte(pci, 0x44, data | 0x40); - pci_dev_put(pci); - } - } - - if (chip->chip_type != TYPE_VIA8233A) { - int i, idx; - for (idx = 0; idx < 4; idx++) { - unsigned long port = chip->port + 0x10 * idx; - for (i = 0; i < 2; i++) { - chip->playback_volume[idx][i]=chip->playback_volume_c[i]; - outb(chip->playback_volume_c[i], - port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); - } - } - } - - return 0; -} - -#ifdef CONFIG_PM -/* - * power management - */ -static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct via82xx *chip = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < 2; i++) - snd_pcm_suspend_all(chip->pcms[i]); - for (i = 0; i < chip->num_devs; i++) - snd_via82xx_channel_reset(chip, &chip->devs[i]); - synchronize_irq(chip->irq); - snd_ac97_suspend(chip->ac97); - - /* save misc values */ - if (chip->chip_type != TYPE_VIA686) { - pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &chip->spdif_ctrl_saved); - chip->capture_src_saved[0] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL); - chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10); - } - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_via82xx_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct via82xx *chip = card->private_data; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "via82xx: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_via82xx_chip_init(chip); - - if (chip->chip_type == TYPE_VIA686) { - if (chip->mpu_port_saved) - pci_write_config_dword(chip->pci, 0x18, chip->mpu_port_saved | 0x01); - pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->legacy_saved); - pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->legacy_cfg_saved); - } else { - pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, chip->spdif_ctrl_saved); - outb(chip->capture_src_saved[0], chip->port + VIA_REG_CAPTURE_CHANNEL); - outb(chip->capture_src_saved[1], chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10); - } - - snd_ac97_resume(chip->ac97); - - for (i = 0; i < chip->num_devs; i++) - snd_via82xx_channel_reset(chip, &chip->devs[i]); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -static int snd_via82xx_free(struct via82xx *chip) -{ - unsigned int i; - - if (chip->irq < 0) - goto __end_hw; - /* disable interrupts */ - for (i = 0; i < chip->num_devs; i++) - snd_via82xx_channel_reset(chip, &chip->devs[i]); - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - __end_hw: - release_and_free_resource(chip->mpu_res); - pci_release_regions(chip->pci); - - if (chip->chip_type == TYPE_VIA686) { - snd_via686_free_gameport(chip); - pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy); - pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg); - } - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_via82xx_dev_free(struct snd_device *device) -{ - struct via82xx *chip = device->device_data; - return snd_via82xx_free(chip); -} - -static int __devinit snd_via82xx_create(struct snd_card *card, - struct pci_dev *pci, - int chip_type, - int revision, - unsigned int ac97_clock, - struct via82xx ** r_via) -{ - struct via82xx *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_via82xx_dev_free, - }; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->chip_type = chip_type; - chip->revision = revision; - - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->rates[0].lock); - spin_lock_init(&chip->rates[1].lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - pci_read_config_byte(pci, VIA_FUNC_ENABLE, &chip->old_legacy); - pci_read_config_byte(pci, VIA_PNP_CONTROL, &chip->old_legacy_cfg); - pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, - chip->old_legacy & ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM)); - - if ((err = pci_request_regions(pci, card->driver)) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, - chip_type == TYPE_VIA8233 ? - snd_via8233_interrupt : snd_via686_interrupt, - IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_via82xx_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - if (ac97_clock >= 8000 && ac97_clock <= 48000) - chip->ac97_clock = ac97_clock; - synchronize_irq(chip->irq); - - if ((err = snd_via82xx_chip_init(chip)) < 0) { - snd_via82xx_free(chip); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_via82xx_free(chip); - return err; - } - - /* The 8233 ac97 controller does not implement the master bit - * in the pci command register. IMHO this is a violation of the PCI spec. - * We call pci_set_master here because it does not hurt. */ - pci_set_master(pci); - - snd_card_set_dev(card, &pci->dev); - - *r_via = chip; - return 0; -} - -struct via823x_info { - int revision; - char *name; - int type; -}; -static struct via823x_info via823x_cards[] __devinitdata = { - { VIA_REV_PRE_8233, "VIA 8233-Pre", TYPE_VIA8233 }, - { VIA_REV_8233C, "VIA 8233C", TYPE_VIA8233 }, - { VIA_REV_8233, "VIA 8233", TYPE_VIA8233 }, - { VIA_REV_8233A, "VIA 8233A", TYPE_VIA8233A }, - { VIA_REV_8235, "VIA 8235", TYPE_VIA8233 }, - { VIA_REV_8237, "VIA 8237", TYPE_VIA8233 }, - { VIA_REV_8251, "VIA 8251", TYPE_VIA8233 }, -}; - -/* - * auto detection of DXS channel supports. - */ - -static struct snd_pci_quirk dxs_whitelist[] __devinitdata = { - SND_PCI_QUIRK(0x1005, 0x4710, "Avance Logic Mobo", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K), - SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x1019, 0x0a85, "ECS L7VMM2", VIA_DXS_NO_VRA), - SND_PCI_QUIRK_VENDOR(0x1019, "ESC K8", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1019, 0xaa01, "ESC K8T890-A", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1025, 0x0033, "Acer Inspire 1353LM", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x1025, 0x0046, "Acer Aspire 1524 WLMi", VIA_DXS_SRC), - SND_PCI_QUIRK_VENDOR(0x1043, "ASUS A7/A8", VIA_DXS_NO_VRA), - SND_PCI_QUIRK_VENDOR(0x1071, "Diverse Notebook", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE), - SND_PCI_QUIRK_VENDOR(0x1106, "ASRock", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1297, 0xa231, "Shuttle AK31v2", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte GA-7VAXP", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1462, 0x3800, "MSI KT266", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1462, 0x7120, "MSI KT4V", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1462, 0x7142, "MSI K8MM-V", VIA_DXS_ENABLE), - SND_PCI_QUIRK_VENDOR(0x1462, "MSI Mobo", VIA_DXS_SRC), - SND_PCI_QUIRK(0x147b, 0x1401, "ABIT KD7(-RAID)", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x147b, 0x1411, "ABIT VA-20", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x147b, 0x1413, "ABIT KV8 Pro", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x147b, 0x1415, "ABIT AV8", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x14ff, 0x0403, "Twinhead mobo", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x14ff, 0x0408, "Twinhead laptop", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1558, 0x4701, "Clevo D470", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1584, 0x8120, "Diverse Laptop", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1584, 0x8123, "Targa/Uniwill", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x161f, 0x202b, "Amira Notebook", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x161f, 0x2032, "m680x machines", VIA_DXS_48K), - SND_PCI_QUIRK(0x1631, 0xe004, "PB EasyNote 3174", VIA_DXS_ENABLE), - SND_PCI_QUIRK(0x1695, 0x3005, "EPoX EP-8K9A", VIA_DXS_ENABLE), - SND_PCI_QUIRK_VENDOR(0x1695, "EPoX mobo", VIA_DXS_SRC), - SND_PCI_QUIRK_VENDOR(0x16f3, "Jetway K8", VIA_DXS_SRC), - SND_PCI_QUIRK_VENDOR(0x1734, "FSC Laptop", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1849, 0x3059, "ASRock K7VM2", VIA_DXS_NO_VRA), - SND_PCI_QUIRK_VENDOR(0x1849, "ASRock mobo", VIA_DXS_SRC), - SND_PCI_QUIRK(0x1919, 0x200a, "Soltek SL-K8", VIA_DXS_NO_VRA), - SND_PCI_QUIRK(0x4005, 0x4710, "MSI K7T266", VIA_DXS_SRC), - { } /* terminator */ -}; - -static int __devinit check_dxs_list(struct pci_dev *pci, int revision) -{ - const struct snd_pci_quirk *w; - - w = snd_pci_quirk_lookup(pci, dxs_whitelist); - if (w) { - snd_printdd(KERN_INFO "via82xx: DXS white list for %s found\n", - w->name); - return w->value; - } - - /* for newer revision, default to DXS_SRC */ - if (revision >= VIA_REV_8235) - return VIA_DXS_SRC; - - /* - * not detected, try 48k rate only to be sure. - */ - printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n"); - printk(KERN_INFO " Please try dxs_support=5 option\n"); - printk(KERN_INFO " and report if it works on your machine.\n"); - printk(KERN_INFO " For more details, read ALSA-Configuration.txt.\n"); - return VIA_DXS_48K; -}; - -static int __devinit snd_via82xx_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct via82xx *chip; - int chip_type = 0, card_type; - unsigned int i; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - card_type = pci_id->driver_data; - switch (card_type) { - case TYPE_CARD_VIA686: - strcpy(card->driver, "VIA686A"); - sprintf(card->shortname, "VIA 82C686A/B rev%x", pci->revision); - chip_type = TYPE_VIA686; - break; - case TYPE_CARD_VIA8233: - chip_type = TYPE_VIA8233; - sprintf(card->shortname, "VIA 823x rev%x", pci->revision); - for (i = 0; i < ARRAY_SIZE(via823x_cards); i++) { - if (pci->revision == via823x_cards[i].revision) { - chip_type = via823x_cards[i].type; - strcpy(card->shortname, via823x_cards[i].name); - break; - } - } - if (chip_type != TYPE_VIA8233A) { - if (dxs_support == VIA_DXS_AUTO) - dxs_support = check_dxs_list(pci, pci->revision); - /* force to use VIA8233 or 8233A model according to - * dxs_support module option - */ - if (dxs_support == VIA_DXS_DISABLE) - chip_type = TYPE_VIA8233A; - else - chip_type = TYPE_VIA8233; - } - if (chip_type == TYPE_VIA8233A) - strcpy(card->driver, "VIA8233A"); - else if (pci->revision >= VIA_REV_8237) - strcpy(card->driver, "VIA8237"); /* no slog assignment */ - else - strcpy(card->driver, "VIA8233"); - break; - default: - snd_printk(KERN_ERR "invalid card type %d\n", card_type); - err = -EINVAL; - goto __error; - } - - if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision, - ac97_clock, &chip)) < 0) - goto __error; - card->private_data = chip; - if ((err = snd_via82xx_mixer_new(chip, ac97_quirk)) < 0) - goto __error; - - if (chip_type == TYPE_VIA686) { - if ((err = snd_via686_pcm_new(chip)) < 0 || - (err = snd_via686_init_misc(chip)) < 0) - goto __error; - } else { - if (chip_type == TYPE_VIA8233A) { - if ((err = snd_via8233a_pcm_new(chip)) < 0) - goto __error; - // chip->dxs_fixed = 1; /* FIXME: use 48k for DXS #3? */ - } else { - if ((err = snd_via8233_pcm_new(chip)) < 0) - goto __error; - if (dxs_support == VIA_DXS_48K) - chip->dxs_fixed = 1; - else if (dxs_support == VIA_DXS_NO_VRA) - chip->no_vra = 1; - else if (dxs_support == VIA_DXS_SRC) { - chip->no_vra = 1; - chip->dxs_src = 1; - } - } - if ((err = snd_via8233_init_misc(chip)) < 0) - goto __error; - } - - /* disable interrupts */ - for (i = 0; i < chip->num_devs; i++) - snd_via82xx_channel_reset(chip, &chip->devs[i]); - - snprintf(card->longname, sizeof(card->longname), - "%s with %s at %#lx, irq %d", card->shortname, - snd_ac97_get_short_name(chip->ac97), chip->port, chip->irq); - - snd_via82xx_proc_init(chip); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - return 0; - - __error: - snd_card_free(card); - return err; -} - -static void __devexit snd_via82xx_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_via82xx_ids, - .probe = snd_via82xx_probe, - .remove = __devexit_p(snd_via82xx_remove), -#ifdef CONFIG_PM - .suspend = snd_via82xx_suspend, - .resume = snd_via82xx_resume, -#endif -}; - -static int __init alsa_card_via82xx_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_via82xx_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_via82xx_init) -module_exit(alsa_card_via82xx_exit) diff --git a/ANDROID_3.4.5/sound/pci/via82xx_modem.c b/ANDROID_3.4.5/sound/pci/via82xx_modem.c deleted file mode 100644 index 5efcbcac..00000000 --- a/ANDROID_3.4.5/sound/pci/via82xx_modem.c +++ /dev/null @@ -1,1248 +0,0 @@ -/* - * ALSA modem driver for VIA VT82xx (South Bridge) - * - * VT82C686A/B/C, VT8233A/C, VT8235 - * - * Copyright (c) 2000 Jaroslav Kysela - * Tjeerd.Mulder - * 2002 Takashi Iwai - * - * 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 - * - */ - -/* - * Changes: - * - * Sep. 2, 2004 Sasha Khapyorsky - * Modified from original audio driver 'via82xx.c' to support AC97 - * modems. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#define POINTER_DEBUG -#endif - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("VIA VT82xx modem"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}"); - -static int index = -2; /* Exclude the first card */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int ac97_clock = 48000; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge."); -module_param(ac97_clock, int, 0444); -MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); - -/* just for backward compatibility */ -static bool enable; -module_param(enable, bool, 0444); - - -/* - * Direct registers - */ - -#define VIAREG(via, x) ((via)->port + VIA_REG_##x) -#define VIADEV_REG(viadev, x) ((viadev)->port + VIA_REG_##x) - -/* common offsets */ -#define VIA_REG_OFFSET_STATUS 0x00 /* byte - channel status */ -#define VIA_REG_STAT_ACTIVE 0x80 /* RO */ -#define VIA_REG_STAT_PAUSED 0x40 /* RO */ -#define VIA_REG_STAT_TRIGGER_QUEUED 0x08 /* RO */ -#define VIA_REG_STAT_STOPPED 0x04 /* RWC */ -#define VIA_REG_STAT_EOL 0x02 /* RWC */ -#define VIA_REG_STAT_FLAG 0x01 /* RWC */ -#define VIA_REG_OFFSET_CONTROL 0x01 /* byte - channel control */ -#define VIA_REG_CTRL_START 0x80 /* WO */ -#define VIA_REG_CTRL_TERMINATE 0x40 /* WO */ -#define VIA_REG_CTRL_AUTOSTART 0x20 -#define VIA_REG_CTRL_PAUSE 0x08 /* RW */ -#define VIA_REG_CTRL_INT_STOP 0x04 -#define VIA_REG_CTRL_INT_EOL 0x02 -#define VIA_REG_CTRL_INT_FLAG 0x01 -#define VIA_REG_CTRL_RESET 0x01 /* RW - probably reset? undocumented */ -#define VIA_REG_CTRL_INT (VIA_REG_CTRL_INT_FLAG | VIA_REG_CTRL_INT_EOL | VIA_REG_CTRL_AUTOSTART) -#define VIA_REG_OFFSET_TYPE 0x02 /* byte - channel type (686 only) */ -#define VIA_REG_TYPE_AUTOSTART 0x80 /* RW - autostart at EOL */ -#define VIA_REG_TYPE_16BIT 0x20 /* RW */ -#define VIA_REG_TYPE_STEREO 0x10 /* RW */ -#define VIA_REG_TYPE_INT_LLINE 0x00 -#define VIA_REG_TYPE_INT_LSAMPLE 0x04 -#define VIA_REG_TYPE_INT_LESSONE 0x08 -#define VIA_REG_TYPE_INT_MASK 0x0c -#define VIA_REG_TYPE_INT_EOL 0x02 -#define VIA_REG_TYPE_INT_FLAG 0x01 -#define VIA_REG_OFFSET_TABLE_PTR 0x04 /* dword - channel table pointer */ -#define VIA_REG_OFFSET_CURR_PTR 0x04 /* dword - channel current pointer */ -#define VIA_REG_OFFSET_STOP_IDX 0x08 /* dword - stop index, channel type, sample rate */ -#define VIA_REG_OFFSET_CURR_COUNT 0x0c /* dword - channel current count (24 bit) */ -#define VIA_REG_OFFSET_CURR_INDEX 0x0f /* byte - channel current index (for via8233 only) */ - -#define DEFINE_VIA_REGSET(name,val) \ -enum {\ - VIA_REG_##name##_STATUS = (val),\ - VIA_REG_##name##_CONTROL = (val) + 0x01,\ - VIA_REG_##name##_TYPE = (val) + 0x02,\ - VIA_REG_##name##_TABLE_PTR = (val) + 0x04,\ - VIA_REG_##name##_CURR_PTR = (val) + 0x04,\ - VIA_REG_##name##_STOP_IDX = (val) + 0x08,\ - VIA_REG_##name##_CURR_COUNT = (val) + 0x0c,\ -} - -/* modem block */ -DEFINE_VIA_REGSET(MO, 0x40); -DEFINE_VIA_REGSET(MI, 0x50); - -/* AC'97 */ -#define VIA_REG_AC97 0x80 /* dword */ -#define VIA_REG_AC97_CODEC_ID_MASK (3<<30) -#define VIA_REG_AC97_CODEC_ID_SHIFT 30 -#define VIA_REG_AC97_CODEC_ID_PRIMARY 0x00 -#define VIA_REG_AC97_CODEC_ID_SECONDARY 0x01 -#define VIA_REG_AC97_SECONDARY_VALID (1<<27) -#define VIA_REG_AC97_PRIMARY_VALID (1<<25) -#define VIA_REG_AC97_BUSY (1<<24) -#define VIA_REG_AC97_READ (1<<23) -#define VIA_REG_AC97_CMD_SHIFT 16 -#define VIA_REG_AC97_CMD_MASK 0x7e -#define VIA_REG_AC97_DATA_SHIFT 0 -#define VIA_REG_AC97_DATA_MASK 0xffff - -#define VIA_REG_SGD_SHADOW 0x84 /* dword */ -#define VIA_REG_SGD_STAT_PB_FLAG (1<<0) -#define VIA_REG_SGD_STAT_CP_FLAG (1<<1) -#define VIA_REG_SGD_STAT_FM_FLAG (1<<2) -#define VIA_REG_SGD_STAT_PB_EOL (1<<4) -#define VIA_REG_SGD_STAT_CP_EOL (1<<5) -#define VIA_REG_SGD_STAT_FM_EOL (1<<6) -#define VIA_REG_SGD_STAT_PB_STOP (1<<8) -#define VIA_REG_SGD_STAT_CP_STOP (1<<9) -#define VIA_REG_SGD_STAT_FM_STOP (1<<10) -#define VIA_REG_SGD_STAT_PB_ACTIVE (1<<12) -#define VIA_REG_SGD_STAT_CP_ACTIVE (1<<13) -#define VIA_REG_SGD_STAT_FM_ACTIVE (1<<14) -#define VIA_REG_SGD_STAT_MR_FLAG (1<<16) -#define VIA_REG_SGD_STAT_MW_FLAG (1<<17) -#define VIA_REG_SGD_STAT_MR_EOL (1<<20) -#define VIA_REG_SGD_STAT_MW_EOL (1<<21) -#define VIA_REG_SGD_STAT_MR_STOP (1<<24) -#define VIA_REG_SGD_STAT_MW_STOP (1<<25) -#define VIA_REG_SGD_STAT_MR_ACTIVE (1<<28) -#define VIA_REG_SGD_STAT_MW_ACTIVE (1<<29) - -#define VIA_REG_GPI_STATUS 0x88 -#define VIA_REG_GPI_INTR 0x8c - -#define VIA_TBL_BIT_FLAG 0x40000000 -#define VIA_TBL_BIT_EOL 0x80000000 - -/* pci space */ -#define VIA_ACLINK_STAT 0x40 -#define VIA_ACLINK_C11_READY 0x20 -#define VIA_ACLINK_C10_READY 0x10 -#define VIA_ACLINK_C01_READY 0x04 /* secondary codec ready */ -#define VIA_ACLINK_LOWPOWER 0x02 /* low-power state */ -#define VIA_ACLINK_C00_READY 0x01 /* primary codec ready */ -#define VIA_ACLINK_CTRL 0x41 -#define VIA_ACLINK_CTRL_ENABLE 0x80 /* 0: disable, 1: enable */ -#define VIA_ACLINK_CTRL_RESET 0x40 /* 0: assert, 1: de-assert */ -#define VIA_ACLINK_CTRL_SYNC 0x20 /* 0: release SYNC, 1: force SYNC hi */ -#define VIA_ACLINK_CTRL_SDO 0x10 /* 0: release SDO, 1: force SDO hi */ -#define VIA_ACLINK_CTRL_VRA 0x08 /* 0: disable VRA, 1: enable VRA */ -#define VIA_ACLINK_CTRL_PCM 0x04 /* 0: disable PCM, 1: enable PCM */ -#define VIA_ACLINK_CTRL_FM 0x02 /* via686 only */ -#define VIA_ACLINK_CTRL_SB 0x01 /* via686 only */ -#define VIA_ACLINK_CTRL_INIT (VIA_ACLINK_CTRL_ENABLE|\ - VIA_ACLINK_CTRL_RESET|\ - VIA_ACLINK_CTRL_PCM) -#define VIA_FUNC_ENABLE 0x42 -#define VIA_FUNC_MIDI_PNP 0x80 /* FIXME: it's 0x40 in the datasheet! */ -#define VIA_FUNC_MIDI_IRQMASK 0x40 /* FIXME: not documented! */ -#define VIA_FUNC_RX2C_WRITE 0x20 -#define VIA_FUNC_SB_FIFO_EMPTY 0x10 -#define VIA_FUNC_ENABLE_GAME 0x08 -#define VIA_FUNC_ENABLE_FM 0x04 -#define VIA_FUNC_ENABLE_MIDI 0x02 -#define VIA_FUNC_ENABLE_SB 0x01 -#define VIA_PNP_CONTROL 0x43 -#define VIA_MC97_CTRL 0x44 -#define VIA_MC97_CTRL_ENABLE 0x80 -#define VIA_MC97_CTRL_SECONDARY 0x40 -#define VIA_MC97_CTRL_INIT (VIA_MC97_CTRL_ENABLE|\ - VIA_MC97_CTRL_SECONDARY) - - -/* - * pcm stream - */ - -struct snd_via_sg_table { - unsigned int offset; - unsigned int size; -} ; - -#define VIA_TABLE_SIZE 255 - -struct viadev { - unsigned int reg_offset; - unsigned long port; - int direction; /* playback = 0, capture = 1 */ - struct snd_pcm_substream *substream; - int running; - unsigned int tbl_entries; /* # descriptors */ - struct snd_dma_buffer table; - struct snd_via_sg_table *idx_table; - /* for recovery from the unexpected pointer */ - unsigned int lastpos; - unsigned int bufsize; - unsigned int bufsize2; -}; - -enum { TYPE_CARD_VIA82XX_MODEM = 1 }; - -#define VIA_MAX_MODEM_DEVS 2 - -struct via82xx_modem { - int irq; - - unsigned long port; - - unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */ - - struct pci_dev *pci; - struct snd_card *card; - - unsigned int num_devs; - unsigned int playback_devno, capture_devno; - struct viadev devs[VIA_MAX_MODEM_DEVS]; - - struct snd_pcm *pcms[2]; - - struct snd_ac97_bus *ac97_bus; - struct snd_ac97 *ac97; - unsigned int ac97_clock; - unsigned int ac97_secondary; /* secondary AC'97 codec is present */ - - spinlock_t reg_lock; - struct snd_info_entry *proc_entry; -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_via82xx_modem_ids) = { - { PCI_VDEVICE(VIA, 0x3068), TYPE_CARD_VIA82XX_MODEM, }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_via82xx_modem_ids); - -/* - */ - -/* - * allocate and initialize the descriptor buffers - * periods = number of periods - * fragsize = period size in bytes - */ -static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substream, - struct pci_dev *pci, - unsigned int periods, unsigned int fragsize) -{ - unsigned int i, idx, ofs, rest; - struct via82xx_modem *chip = snd_pcm_substream_chip(substream); - - if (dev->table.area == NULL) { - /* the start of each lists must be aligned to 8 bytes, - * but the kernel pages are much bigger, so we don't care - */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8), - &dev->table) < 0) - return -ENOMEM; - } - if (! dev->idx_table) { - dev->idx_table = kmalloc(sizeof(*dev->idx_table) * VIA_TABLE_SIZE, GFP_KERNEL); - if (! dev->idx_table) - return -ENOMEM; - } - - /* fill the entries */ - idx = 0; - ofs = 0; - for (i = 0; i < periods; i++) { - rest = fragsize; - /* fill descriptors for a period. - * a period can be split to several descriptors if it's - * over page boundary. - */ - do { - unsigned int r; - unsigned int flag; - unsigned int addr; - - if (idx >= VIA_TABLE_SIZE) { - snd_printk(KERN_ERR "via82xx: too much table size!\n"); - return -EINVAL; - } - addr = snd_pcm_sgbuf_get_addr(substream, ofs); - ((u32 *)dev->table.area)[idx << 1] = cpu_to_le32(addr); - r = PAGE_SIZE - (ofs % PAGE_SIZE); - if (rest < r) - r = rest; - rest -= r; - if (! rest) { - if (i == periods - 1) - flag = VIA_TBL_BIT_EOL; /* buffer boundary */ - else - flag = VIA_TBL_BIT_FLAG; /* period boundary */ - } else - flag = 0; /* period continues to the next */ - /* - printk(KERN_DEBUG "via: tbl %d: at %d size %d " - "(rest %d)\n", idx, ofs, r, rest); - */ - ((u32 *)dev->table.area)[(idx<<1) + 1] = cpu_to_le32(r | flag); - dev->idx_table[idx].offset = ofs; - dev->idx_table[idx].size = r; - ofs += r; - idx++; - } while (rest > 0); - } - dev->tbl_entries = idx; - dev->bufsize = periods * fragsize; - dev->bufsize2 = dev->bufsize / 2; - return 0; -} - - -static int clean_via_table(struct viadev *dev, struct snd_pcm_substream *substream, - struct pci_dev *pci) -{ - if (dev->table.area) { - snd_dma_free_pages(&dev->table); - dev->table.area = NULL; - } - kfree(dev->idx_table); - dev->idx_table = NULL; - return 0; -} - -/* - * Basic I/O - */ - -static inline unsigned int snd_via82xx_codec_xread(struct via82xx_modem *chip) -{ - return inl(VIAREG(chip, AC97)); -} - -static inline void snd_via82xx_codec_xwrite(struct via82xx_modem *chip, unsigned int val) -{ - outl(val, VIAREG(chip, AC97)); -} - -static int snd_via82xx_codec_ready(struct via82xx_modem *chip, int secondary) -{ - unsigned int timeout = 1000; /* 1ms */ - unsigned int val; - - while (timeout-- > 0) { - udelay(1); - if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)) - return val & 0xffff; - } - snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", - secondary, snd_via82xx_codec_xread(chip)); - return -EIO; -} - -static int snd_via82xx_codec_valid(struct via82xx_modem *chip, int secondary) -{ - unsigned int timeout = 1000; /* 1ms */ - unsigned int val, val1; - unsigned int stat = !secondary ? VIA_REG_AC97_PRIMARY_VALID : - VIA_REG_AC97_SECONDARY_VALID; - - while (timeout-- > 0) { - val = snd_via82xx_codec_xread(chip); - val1 = val & (VIA_REG_AC97_BUSY | stat); - if (val1 == stat) - return val & 0xffff; - udelay(1); - } - return -EIO; -} - -static void snd_via82xx_codec_wait(struct snd_ac97 *ac97) -{ - struct via82xx_modem *chip = ac97->private_data; - int err; - err = snd_via82xx_codec_ready(chip, ac97->num); - /* here we need to wait fairly for long time.. */ - msleep(500); -} - -static void snd_via82xx_codec_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct via82xx_modem *chip = ac97->private_data; - unsigned int xval; - if(reg == AC97_GPIO_STATUS) { - outl(val, VIAREG(chip, GPI_STATUS)); - return; - } - xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; - xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; - xval |= reg << VIA_REG_AC97_CMD_SHIFT; - xval |= val << VIA_REG_AC97_DATA_SHIFT; - snd_via82xx_codec_xwrite(chip, xval); - snd_via82xx_codec_ready(chip, ac97->num); -} - -static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct via82xx_modem *chip = ac97->private_data; - unsigned int xval, val = 0xffff; - int again = 0; - - xval = ac97->num << VIA_REG_AC97_CODEC_ID_SHIFT; - xval |= ac97->num ? VIA_REG_AC97_SECONDARY_VALID : VIA_REG_AC97_PRIMARY_VALID; - xval |= VIA_REG_AC97_READ; - xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT; - while (1) { - if (again++ > 3) { - snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n", - ac97->num, snd_via82xx_codec_xread(chip)); - return 0xffff; - } - snd_via82xx_codec_xwrite(chip, xval); - udelay (20); - if (snd_via82xx_codec_valid(chip, ac97->num) >= 0) { - udelay(25); - val = snd_via82xx_codec_xread(chip); - break; - } - } - return val & 0xffff; -} - -static void snd_via82xx_channel_reset(struct via82xx_modem *chip, struct viadev *viadev) -{ - outb(VIA_REG_CTRL_PAUSE | VIA_REG_CTRL_TERMINATE | VIA_REG_CTRL_RESET, - VIADEV_REG(viadev, OFFSET_CONTROL)); - inb(VIADEV_REG(viadev, OFFSET_CONTROL)); - udelay(50); - /* disable interrupts */ - outb(0x00, VIADEV_REG(viadev, OFFSET_CONTROL)); - /* clear interrupts */ - outb(0x03, VIADEV_REG(viadev, OFFSET_STATUS)); - outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ - // outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); - viadev->lastpos = 0; -} - - -/* - * Interrupt handler - */ - -static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id) -{ - struct via82xx_modem *chip = dev_id; - unsigned int status; - unsigned int i; - - status = inl(VIAREG(chip, SGD_SHADOW)); - if (! (status & chip->intr_mask)) { - return IRQ_NONE; - } -// _skip_sgd: - - /* check status for each stream */ - spin_lock(&chip->reg_lock); - for (i = 0; i < chip->num_devs; i++) { - struct viadev *viadev = &chip->devs[i]; - unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS)); - c_status &= (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED); - if (! c_status) - continue; - if (viadev->substream && viadev->running) { - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(viadev->substream); - spin_lock(&chip->reg_lock); - } - outb(c_status, VIADEV_REG(viadev, OFFSET_STATUS)); /* ack */ - } - spin_unlock(&chip->reg_lock); - return IRQ_HANDLED; -} - -/* - * PCM callbacks - */ - -/* - * trigger callback - */ -static int snd_via82xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct via82xx_modem *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - unsigned char val = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_SUSPEND: - val |= VIA_REG_CTRL_START; - viadev->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - val = VIA_REG_CTRL_TERMINATE; - viadev->running = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - val |= VIA_REG_CTRL_PAUSE; - viadev->running = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - viadev->running = 1; - break; - default: - return -EINVAL; - } - outb(val, VIADEV_REG(viadev, OFFSET_CONTROL)); - if (cmd == SNDRV_PCM_TRIGGER_STOP) - snd_via82xx_channel_reset(chip, viadev); - return 0; -} - -/* - * pointer callbacks - */ - -/* - * calculate the linear position at the given sg-buffer index and the rest count - */ - -#define check_invalid_pos(viadev,pos) \ - ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 ||\ - viadev->lastpos < viadev->bufsize2)) - -static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int idx, - unsigned int count) -{ - unsigned int size, res; - - size = viadev->idx_table[idx].size; - res = viadev->idx_table[idx].offset + size - count; - - /* check the validity of the calculated position */ - if (size < count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", - (int)size, (int)count); - res = viadev->lastpos; - } else if (check_invalid_pos(viadev, res)) { -#ifdef POINTER_DEBUG - printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, " - "bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, " - "count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, - viadev->bufsize2, viadev->idx_table[idx].offset, - viadev->idx_table[idx].size, count); -#endif - if (count && size < count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr, " - "using last valid pointer\n"); - res = viadev->lastpos; - } else { - if (! count) - /* bogus count 0 on the DMA boundary? */ - res = viadev->idx_table[idx].offset; - else - /* count register returns full size - * when end of buffer is reached - */ - res = viadev->idx_table[idx].offset + size; - if (check_invalid_pos(viadev, res)) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), " - "using last valid pointer\n"); - res = viadev->lastpos; - } - } - } - viadev->lastpos = res; /* remember the last position */ - if (res >= viadev->bufsize) - res -= viadev->bufsize; - return res; -} - -/* - * get the current pointer on via686 - */ -static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct via82xx_modem *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - unsigned int idx, ptr, count, res; - - if (snd_BUG_ON(!viadev->tbl_entries)) - return 0; - if (!(inb(VIADEV_REG(viadev, OFFSET_STATUS)) & VIA_REG_STAT_ACTIVE)) - return 0; - - spin_lock(&chip->reg_lock); - count = inl(VIADEV_REG(viadev, OFFSET_CURR_COUNT)) & 0xffffff; - /* The via686a does not have the current index register, - * so we need to calculate the index from CURR_PTR. - */ - ptr = inl(VIADEV_REG(viadev, OFFSET_CURR_PTR)); - if (ptr <= (unsigned int)viadev->table.addr) - idx = 0; - else /* CURR_PTR holds the address + 8 */ - idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % - viadev->tbl_entries; - res = calc_linear_pos(viadev, idx, count); - spin_unlock(&chip->reg_lock); - - return bytes_to_frames(substream->runtime, res); -} - -/* - * hw_params callback: - * allocate the buffer and build up the buffer description table - */ -static int snd_via82xx_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct via82xx_modem *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - int err; - - err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - if (err < 0) - return err; - err = build_via_table(viadev, substream, chip->pci, - params_periods(hw_params), - params_period_bytes(hw_params)); - if (err < 0) - return err; - - snd_ac97_write(chip->ac97, AC97_LINE1_RATE, params_rate(hw_params)); - snd_ac97_write(chip->ac97, AC97_LINE1_LEVEL, 0); - - return 0; -} - -/* - * hw_free callback: - * clean up the buffer description table and release the buffer - */ -static int snd_via82xx_hw_free(struct snd_pcm_substream *substream) -{ - struct via82xx_modem *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - - clean_via_table(viadev, substream, chip->pci); - snd_pcm_lib_free_pages(substream); - return 0; -} - - -/* - * set up the table pointer - */ -static void snd_via82xx_set_table_ptr(struct via82xx_modem *chip, struct viadev *viadev) -{ - snd_via82xx_codec_ready(chip, chip->ac97_secondary); - outl((u32)viadev->table.addr, VIADEV_REG(viadev, OFFSET_TABLE_PTR)); - udelay(20); - snd_via82xx_codec_ready(chip, chip->ac97_secondary); -} - -/* - * prepare callback for playback and capture - */ -static int snd_via82xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct via82xx_modem *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = substream->runtime->private_data; - - snd_via82xx_channel_reset(chip, viadev); - /* this must be set after channel_reset */ - snd_via82xx_set_table_ptr(chip, viadev); - outb(VIA_REG_TYPE_AUTOSTART|VIA_REG_TYPE_INT_EOL|VIA_REG_TYPE_INT_FLAG, - VIADEV_REG(viadev, OFFSET_TYPE)); - return 0; -} - -/* - * pcm hardware definition, identical for both playback and capture - */ -static struct snd_pcm_hardware snd_via82xx_hw = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - /* SNDRV_PCM_INFO_RESUME | */ - SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_KNOT, - .rate_min = 8000, - .rate_max = 16000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = 128 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 128 * 1024, - .periods_min = 2, - .periods_max = VIA_TABLE_SIZE / 2, - .fifo_size = 0, -}; - - -/* - * open callback skeleton - */ -static int snd_via82xx_modem_pcm_open(struct via82xx_modem *chip, struct viadev *viadev, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - - runtime->hw = snd_via82xx_hw; - - if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates)) < 0) - return err; - - /* we may remove following constaint when we modify table entries - in interrupt */ - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - runtime->private_data = viadev; - viadev->substream = substream; - - return 0; -} - - -/* - * open callback for playback - */ -static int snd_via82xx_playback_open(struct snd_pcm_substream *substream) -{ - struct via82xx_modem *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = &chip->devs[chip->playback_devno + substream->number]; - - return snd_via82xx_modem_pcm_open(chip, viadev, substream); -} - -/* - * open callback for capture - */ -static int snd_via82xx_capture_open(struct snd_pcm_substream *substream) -{ - struct via82xx_modem *chip = snd_pcm_substream_chip(substream); - struct viadev *viadev = &chip->devs[chip->capture_devno + substream->pcm->device]; - - return snd_via82xx_modem_pcm_open(chip, viadev, substream); -} - -/* - * close callback - */ -static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct viadev *viadev = substream->runtime->private_data; - - viadev->substream = NULL; - return 0; -} - - -/* via686 playback callbacks */ -static struct snd_pcm_ops snd_via686_playback_ops = { - .open = snd_via82xx_playback_open, - .close = snd_via82xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_via82xx_hw_params, - .hw_free = snd_via82xx_hw_free, - .prepare = snd_via82xx_pcm_prepare, - .trigger = snd_via82xx_pcm_trigger, - .pointer = snd_via686_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -/* via686 capture callbacks */ -static struct snd_pcm_ops snd_via686_capture_ops = { - .open = snd_via82xx_capture_open, - .close = snd_via82xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_via82xx_hw_params, - .hw_free = snd_via82xx_hw_free, - .prepare = snd_via82xx_pcm_prepare, - .trigger = snd_via82xx_pcm_trigger, - .pointer = snd_via686_pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - - -static void init_viadev(struct via82xx_modem *chip, int idx, unsigned int reg_offset, - int direction) -{ - chip->devs[idx].reg_offset = reg_offset; - chip->devs[idx].direction = direction; - chip->devs[idx].port = chip->port + reg_offset; -} - -/* - * create a pcm instance for via686a/b - */ -static int __devinit snd_via686_pcm_new(struct via82xx_modem *chip) -{ - struct snd_pcm *pcm; - int err; - - chip->playback_devno = 0; - chip->capture_devno = 1; - chip->num_devs = 2; - chip->intr_mask = 0x330000; /* FLAGS | EOL for MR, MW */ - - err = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via686_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via686_capture_ops); - pcm->dev_class = SNDRV_PCM_CLASS_MODEM; - pcm->private_data = chip; - strcpy(pcm->name, chip->card->shortname); - chip->pcms[0] = pcm; - init_viadev(chip, 0, VIA_REG_MO_STATUS, 0); - init_viadev(chip, 1, VIA_REG_MI_STATUS, 1); - - if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 64*1024, 128*1024)) < 0) - return err; - - return 0; -} - - -/* - * Mixer part - */ - - -static void snd_via82xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct via82xx_modem *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct via82xx_modem *chip = ac97->private_data; - chip->ac97 = NULL; -} - - -static int __devinit snd_via82xx_mixer_new(struct via82xx_modem *chip) -{ - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_via82xx_codec_write, - .read = snd_via82xx_codec_read, - .wait = snd_via82xx_codec_wait, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) - return err; - chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; - chip->ac97_bus->clock = chip->ac97_clock; - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_via82xx_mixer_free_ac97; - ac97.pci = chip->pci; - ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; - ac97.num = chip->ac97_secondary; - - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) - return err; - - return 0; -} - - -/* - * proc interface - */ -static void snd_via82xx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct via82xx_modem *chip = entry->private_data; - int i; - - snd_iprintf(buffer, "%s\n\n", chip->card->longname); - for (i = 0; i < 0xa0; i += 4) { - snd_iprintf(buffer, "%02x: %08x\n", i, inl(chip->port + i)); - } -} - -static void __devinit snd_via82xx_proc_init(struct via82xx_modem *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "via82xx", &entry)) - snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read); -} - -/* - * - */ - -static int snd_via82xx_chip_init(struct via82xx_modem *chip) -{ - unsigned int val; - unsigned long end_time; - unsigned char pval; - - pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval); - if((pval & VIA_MC97_CTRL_INIT) != VIA_MC97_CTRL_INIT) { - pci_write_config_byte(chip->pci, 0x44, pval|VIA_MC97_CTRL_INIT); - udelay(100); - } - - pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); - if (! (pval & VIA_ACLINK_C00_READY)) { /* codec not ready? */ - /* deassert ACLink reset, force SYNC */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, - VIA_ACLINK_CTRL_ENABLE | - VIA_ACLINK_CTRL_RESET | - VIA_ACLINK_CTRL_SYNC); - udelay(100); -#if 1 /* FIXME: should we do full reset here for all chip models? */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00); - udelay(100); -#else - /* deassert ACLink reset, force SYNC (warm AC'97 reset) */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, - VIA_ACLINK_CTRL_RESET|VIA_ACLINK_CTRL_SYNC); - udelay(2); -#endif - /* ACLink on, deassert ACLink reset, VSR, SGD data out */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT); - udelay(100); - } - - pci_read_config_byte(chip->pci, VIA_ACLINK_CTRL, &pval); - if ((pval & VIA_ACLINK_CTRL_INIT) != VIA_ACLINK_CTRL_INIT) { - /* ACLink on, deassert ACLink reset, VSR, SGD data out */ - pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT); - udelay(100); - } - - /* wait until codec ready */ - end_time = jiffies + msecs_to_jiffies(750); - do { - pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); - if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ - break; - schedule_timeout_uninterruptible(1); - } while (time_before(jiffies, end_time)); - - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) - snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val); - - snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | - VIA_REG_AC97_SECONDARY_VALID | - (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); - end_time = jiffies + msecs_to_jiffies(750); - snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | - VIA_REG_AC97_SECONDARY_VALID | - (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); - do { - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) { - chip->ac97_secondary = 1; - goto __ac97_ok2; - } - schedule_timeout_uninterruptible(1); - } while (time_before(jiffies, end_time)); - /* This is ok, the most of motherboards have only one codec */ - - __ac97_ok2: - - /* route FM trap to IRQ, disable FM trap */ - // pci_write_config_byte(chip->pci, VIA_FM_NMI_CTRL, 0); - /* disable all GPI interrupts */ - outl(0, VIAREG(chip, GPI_INTR)); - - return 0; -} - -#ifdef CONFIG_PM -/* - * power management - */ -static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct via82xx_modem *chip = card->private_data; - int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - for (i = 0; i < 2; i++) - snd_pcm_suspend_all(chip->pcms[i]); - for (i = 0; i < chip->num_devs; i++) - snd_via82xx_channel_reset(chip, &chip->devs[i]); - synchronize_irq(chip->irq); - snd_ac97_suspend(chip->ac97); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_via82xx_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct via82xx_modem *chip = card->private_data; - int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "via82xx-modem: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_via82xx_chip_init(chip); - - snd_ac97_resume(chip->ac97); - - for (i = 0; i < chip->num_devs; i++) - snd_via82xx_channel_reset(chip, &chip->devs[i]); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -static int snd_via82xx_free(struct via82xx_modem *chip) -{ - unsigned int i; - - if (chip->irq < 0) - goto __end_hw; - /* disable interrupts */ - for (i = 0; i < chip->num_devs; i++) - snd_via82xx_channel_reset(chip, &chip->devs[i]); - - __end_hw: - if (chip->irq >= 0) - free_irq(chip->irq, chip); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); - kfree(chip); - return 0; -} - -static int snd_via82xx_dev_free(struct snd_device *device) -{ - struct via82xx_modem *chip = device->device_data; - return snd_via82xx_free(chip); -} - -static int __devinit snd_via82xx_create(struct snd_card *card, - struct pci_dev *pci, - int chip_type, - int revision, - unsigned int ac97_clock, - struct via82xx_modem ** r_via) -{ - struct via82xx_modem *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_via82xx_dev_free, - }; - - if ((err = pci_enable_device(pci)) < 0) - return err; - - if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - spin_lock_init(&chip->reg_lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - if ((err = pci_request_regions(pci, card->driver)) < 0) { - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_via82xx_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - if (ac97_clock >= 8000 && ac97_clock <= 48000) - chip->ac97_clock = ac97_clock; - synchronize_irq(chip->irq); - - if ((err = snd_via82xx_chip_init(chip)) < 0) { - snd_via82xx_free(chip); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_via82xx_free(chip); - return err; - } - - /* The 8233 ac97 controller does not implement the master bit - * in the pci command register. IMHO this is a violation of the PCI spec. - * We call pci_set_master here because it does not hurt. */ - pci_set_master(pci); - - snd_card_set_dev(card, &pci->dev); - - *r_via = chip; - return 0; -} - - -static int __devinit snd_via82xx_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - struct via82xx_modem *chip; - int chip_type = 0, card_type; - unsigned int i; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - card_type = pci_id->driver_data; - switch (card_type) { - case TYPE_CARD_VIA82XX_MODEM: - strcpy(card->driver, "VIA82XX-MODEM"); - sprintf(card->shortname, "VIA 82XX modem"); - break; - default: - snd_printk(KERN_ERR "invalid card type %d\n", card_type); - err = -EINVAL; - goto __error; - } - - if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision, - ac97_clock, &chip)) < 0) - goto __error; - card->private_data = chip; - if ((err = snd_via82xx_mixer_new(chip)) < 0) - goto __error; - - if ((err = snd_via686_pcm_new(chip)) < 0 ) - goto __error; - - /* disable interrupts */ - for (i = 0; i < chip->num_devs; i++) - snd_via82xx_channel_reset(chip, &chip->devs[i]); - - sprintf(card->longname, "%s at 0x%lx, irq %d", - card->shortname, chip->port, chip->irq); - - snd_via82xx_proc_init(chip); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - return 0; - - __error: - snd_card_free(card); - return err; -} - -static void __devexit snd_via82xx_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_via82xx_modem_ids, - .probe = snd_via82xx_probe, - .remove = __devexit_p(snd_via82xx_remove), -#ifdef CONFIG_PM - .suspend = snd_via82xx_suspend, - .resume = snd_via82xx_resume, -#endif -}; - -static int __init alsa_card_via82xx_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_via82xx_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_via82xx_init) -module_exit(alsa_card_via82xx_exit) diff --git a/ANDROID_3.4.5/sound/pci/vx222/Makefile b/ANDROID_3.4.5/sound/pci/vx222/Makefile deleted file mode 100644 index a4d08d4d..00000000 --- a/ANDROID_3.4.5/sound/pci/vx222/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-vx222-objs := vx222.o vx222_ops.o - -obj-$(CONFIG_SND_VX222) += snd-vx222.o diff --git a/ANDROID_3.4.5/sound/pci/vx222/vx222.c b/ANDROID_3.4.5/sound/pci/vx222/vx222.c deleted file mode 100644 index 6a534bfe..00000000 --- a/ANDROID_3.4.5/sound/pci/vx222/vx222.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Driver for Digigram VX222 V2/Mic PCI soundcards - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 "vx222.h" - -#define CARD_NAME "VX222" - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("Digigram VX222 V2/Mic"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static bool mic[SNDRV_CARDS]; /* microphone */ -static int ibl[SNDRV_CARDS]; /* microphone */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); -module_param_array(mic, bool, NULL, 0444); -MODULE_PARM_DESC(mic, "Enable Microphone."); -module_param_array(ibl, int, NULL, 0444); -MODULE_PARM_DESC(ibl, "Capture IBL size."); - -/* - */ - -enum { - VX_PCI_VX222_OLD, - VX_PCI_VX222_NEW -}; - -static DEFINE_PCI_DEVICE_TABLE(snd_vx222_ids) = { - { 0x10b5, 0x9050, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_OLD, }, /* PLX */ - { 0x10b5, 0x9030, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_NEW, }, /* PLX */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_vx222_ids); - - -/* - */ - -static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_akm, -7350, 50, 0); - -static struct snd_vx_hardware vx222_old_hw = { - - .name = "VX222/Old", - .type = VX_TYPE_BOARD, - /* hw specs */ - .num_codecs = 1, - .num_ins = 1, - .num_outs = 1, - .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, - .output_level_db_scale = db_scale_old_vol, -}; - -static struct snd_vx_hardware vx222_v2_hw = { - - .name = "VX222/v2", - .type = VX_TYPE_V2, - /* hw specs */ - .num_codecs = 1, - .num_ins = 1, - .num_outs = 1, - .output_level_max = VX2_AKM_LEVEL_MAX, - .output_level_db_scale = db_scale_akm, -}; - -static struct snd_vx_hardware vx222_mic_hw = { - - .name = "VX222/Mic", - .type = VX_TYPE_MIC, - /* hw specs */ - .num_codecs = 1, - .num_ins = 1, - .num_outs = 1, - .output_level_max = VX2_AKM_LEVEL_MAX, - .output_level_db_scale = db_scale_akm, -}; - - -/* - */ -static int snd_vx222_free(struct vx_core *chip) -{ - struct snd_vx222 *vx = (struct snd_vx222 *)chip; - - if (chip->irq >= 0) - free_irq(chip->irq, (void*)chip); - if (vx->port[0]) - pci_release_regions(vx->pci); - pci_disable_device(vx->pci); - kfree(chip); - return 0; -} - -static int snd_vx222_dev_free(struct snd_device *device) -{ - struct vx_core *chip = device->device_data; - return snd_vx222_free(chip); -} - - -static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci, - struct snd_vx_hardware *hw, - struct snd_vx222 **rchip) -{ - struct vx_core *chip; - struct snd_vx222 *vx; - int i, err; - static struct snd_device_ops ops = { - .dev_free = snd_vx222_dev_free, - }; - struct snd_vx_ops *vx_ops; - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - pci_set_master(pci); - - vx_ops = hw->type == VX_TYPE_BOARD ? &vx222_old_ops : &vx222_ops; - chip = snd_vx_create(card, hw, vx_ops, - sizeof(struct snd_vx222) - sizeof(struct vx_core)); - if (! chip) { - pci_disable_device(pci); - return -ENOMEM; - } - vx = (struct snd_vx222 *)chip; - vx->pci = pci; - - if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { - snd_vx222_free(chip); - return err; - } - for (i = 0; i < 2; i++) - vx->port[i] = pci_resource_start(pci, i + 1); - - if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_vx222_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_vx222_free(chip); - return err; - } - - snd_card_set_dev(card, &pci->dev); - - *rchip = vx; - return 0; -} - - -static int __devinit snd_vx222_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_vx_hardware *hw; - struct snd_vx222 *vx; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - switch ((int)pci_id->driver_data) { - case VX_PCI_VX222_OLD: - hw = &vx222_old_hw; - break; - case VX_PCI_VX222_NEW: - default: - if (mic[dev]) - hw = &vx222_mic_hw; - else - hw = &vx222_v2_hw; - break; - } - if ((err = snd_vx222_create(card, pci, hw, &vx)) < 0) { - snd_card_free(card); - return err; - } - card->private_data = vx; - vx->core.ibl.size = ibl[dev]; - - sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %i", - card->shortname, vx->port[0], vx->port[1], vx->core.irq); - snd_printdd("%s at 0x%lx & 0x%lx, irq %i\n", - card->shortname, vx->port[0], vx->port[1], vx->core.irq); - -#ifdef SND_VX_FW_LOADER - vx->core.dev = &pci->dev; -#endif - - if ((err = snd_vx_setup_firmware(&vx->core)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_vx222_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -#ifdef CONFIG_PM -static int snd_vx222_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_vx222 *vx = card->private_data; - int err; - - err = snd_vx_suspend(&vx->core, state); - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return err; -} - -static int snd_vx222_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_vx222 *vx = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "vx222: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - return snd_vx_resume(&vx->core); -} -#endif - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_vx222_ids, - .probe = snd_vx222_probe, - .remove = __devexit_p(snd_vx222_remove), -#ifdef CONFIG_PM - .suspend = snd_vx222_suspend, - .resume = snd_vx222_resume, -#endif -}; - -static int __init alsa_card_vx222_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_vx222_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_vx222_init) -module_exit(alsa_card_vx222_exit) diff --git a/ANDROID_3.4.5/sound/pci/vx222/vx222.h b/ANDROID_3.4.5/sound/pci/vx222/vx222.h deleted file mode 100644 index 2f0d78f6..00000000 --- a/ANDROID_3.4.5/sound/pci/vx222/vx222.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Driver for Digigram VX222 PCI soundcards - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 - */ - -#ifndef __VX222_H -#define __VX222_H - -#include - -struct snd_vx222 { - - struct vx_core core; - - /* h/w config; for PLX and for DSP */ - struct pci_dev *pci; - unsigned long port[2]; - - unsigned int regCDSP; /* current CDSP register */ - unsigned int regCFG; /* current CFG register */ - unsigned int regSELMIC; /* current SELMIC reg. (for VX222 Mic) */ - - int input_level[2]; /* input level for vx222 mic */ - int mic_level; /* mic level for vx222 mic */ -}; - -/* we use a lookup table with 148 values, see vx_mixer.c */ -#define VX2_AKM_LEVEL_MAX 0x93 - -extern struct snd_vx_ops vx222_ops; -extern struct snd_vx_ops vx222_old_ops; - -/* Offset of registers with base equal to portDSP. */ -#define VX_RESET_DMA_REGISTER_OFFSET 0x00000008 - -/* Constants used to access the INTCSR register. */ -#define VX_INTCSR_VALUE 0x00000001 -#define VX_PCI_INTERRUPT_MASK 0x00000040 - -/* Constants used to access the CDSP register (0x20). */ -#define VX_CDSP_TEST1_MASK 0x00000080 -#define VX_CDSP_TOR1_MASK 0x00000040 -#define VX_CDSP_TOR2_MASK 0x00000020 -#define VX_CDSP_RESERVED0_0_MASK 0x00000010 -#define VX_CDSP_CODEC_RESET_MASK 0x00000008 -#define VX_CDSP_VALID_IRQ_MASK 0x00000004 -#define VX_CDSP_TEST0_MASK 0x00000002 -#define VX_CDSP_DSP_RESET_MASK 0x00000001 - -#define VX_CDSP_GPIO_OUT_MASK 0x00000060 -#define VX_GPIO_OUT_BIT_OFFSET 5 // transform output to bit 0 and 1 - -/* Constants used to access the CFG register (0x24). */ -#define VX_CFG_SYNCDSP_MASK 0x00000080 -#define VX_CFG_RESERVED0_0_MASK 0x00000040 -#define VX_CFG_RESERVED1_0_MASK 0x00000020 -#define VX_CFG_RESERVED2_0_MASK 0x00000010 -#define VX_CFG_DATAIN_SEL_MASK 0x00000008 // 0 (ana), 1 (UER) -#define VX_CFG_RESERVED3_0_MASK 0x00000004 -#define VX_CFG_RESERVED4_0_MASK 0x00000002 -#define VX_CFG_CLOCKIN_SEL_MASK 0x00000001 // 0 (internal), 1 (AES/EBU) - -/* Constants used to access the STATUS register (0x30). */ -#define VX_STATUS_DATA_XICOR_MASK 0x00000080 -#define VX_STATUS_VAL_TEST1_MASK 0x00000040 -#define VX_STATUS_VAL_TEST0_MASK 0x00000020 -#define VX_STATUS_RESERVED0_MASK 0x00000010 -#define VX_STATUS_VAL_TOR1_MASK 0x00000008 -#define VX_STATUS_VAL_TOR0_MASK 0x00000004 -#define VX_STATUS_LEVEL_IN_MASK 0x00000002 // 6 dBu (0), 22 dBu (1) -#define VX_STATUS_MEMIRQ_MASK 0x00000001 - -#define VX_STATUS_GPIO_IN_MASK 0x0000000C -#define VX_GPIO_IN_BIT_OFFSET 0 // leave input as bit 2 and 3 - -/* Constants used to access the MICRO INPUT SELECT register (0x40). */ -#define MICRO_SELECT_INPUT_NORM 0x00 -#define MICRO_SELECT_INPUT_MUTE 0x01 -#define MICRO_SELECT_INPUT_LIMIT 0x02 -#define MICRO_SELECT_INPUT_MASK 0x03 - -#define MICRO_SELECT_PREAMPLI_G_0 0x00 -#define MICRO_SELECT_PREAMPLI_G_1 0x04 -#define MICRO_SELECT_PREAMPLI_G_2 0x08 -#define MICRO_SELECT_PREAMPLI_G_3 0x0C -#define MICRO_SELECT_PREAMPLI_MASK 0x0C -#define MICRO_SELECT_PREAMPLI_OFFSET 2 - -#define MICRO_SELECT_RAISE_COMPR 0x10 - -#define MICRO_SELECT_NOISE_T_52DB 0x00 -#define MICRO_SELECT_NOISE_T_42DB 0x20 -#define MICRO_SELECT_NOISE_T_32DB 0x40 -#define MICRO_SELECT_NOISE_T_MASK 0x60 - -#define MICRO_SELECT_PHANTOM_ALIM 0x80 - - -#endif /* __VX222_H */ diff --git a/ANDROID_3.4.5/sound/pci/vx222/vx222_ops.c b/ANDROID_3.4.5/sound/pci/vx222/vx222_ops.c deleted file mode 100644 index a69e774d..00000000 --- a/ANDROID_3.4.5/sound/pci/vx222/vx222_ops.c +++ /dev/null @@ -1,1031 +0,0 @@ -/* - * Driver for Digigram VX222 V2/Mic soundcards - * - * VX222-specific low-level routines - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 "vx222.h" - - -static int vx2_reg_offset[VX_REG_MAX] = { - [VX_ICR] = 0x00, - [VX_CVR] = 0x04, - [VX_ISR] = 0x08, - [VX_IVR] = 0x0c, - [VX_RXH] = 0x14, - [VX_RXM] = 0x18, - [VX_RXL] = 0x1c, - [VX_DMA] = 0x10, - [VX_CDSP] = 0x20, - [VX_CFG] = 0x24, - [VX_RUER] = 0x28, - [VX_DATA] = 0x2c, - [VX_STATUS] = 0x30, - [VX_LOFREQ] = 0x34, - [VX_HIFREQ] = 0x38, - [VX_CSUER] = 0x3c, - [VX_SELMIC] = 0x40, - [VX_COMPOT] = 0x44, // Write: POTENTIOMETER ; Read: COMPRESSION LEVEL activate - [VX_SCOMPR] = 0x48, // Read: COMPRESSION THRESHOLD activate - [VX_GLIMIT] = 0x4c, // Read: LEVEL LIMITATION activate - [VX_INTCSR] = 0x4c, // VX_INTCSR_REGISTER_OFFSET - [VX_CNTRL] = 0x50, // VX_CNTRL_REGISTER_OFFSET - [VX_GPIOC] = 0x54, // VX_GPIOC (new with PLX9030) -}; - -static int vx2_reg_index[VX_REG_MAX] = { - [VX_ICR] = 1, - [VX_CVR] = 1, - [VX_ISR] = 1, - [VX_IVR] = 1, - [VX_RXH] = 1, - [VX_RXM] = 1, - [VX_RXL] = 1, - [VX_DMA] = 1, - [VX_CDSP] = 1, - [VX_CFG] = 1, - [VX_RUER] = 1, - [VX_DATA] = 1, - [VX_STATUS] = 1, - [VX_LOFREQ] = 1, - [VX_HIFREQ] = 1, - [VX_CSUER] = 1, - [VX_SELMIC] = 1, - [VX_COMPOT] = 1, - [VX_SCOMPR] = 1, - [VX_GLIMIT] = 1, - [VX_INTCSR] = 0, /* on the PLX */ - [VX_CNTRL] = 0, /* on the PLX */ - [VX_GPIOC] = 0, /* on the PLX */ -}; - -static inline unsigned long vx2_reg_addr(struct vx_core *_chip, int reg) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg]; -} - -/** - * snd_vx_inb - read a byte from the register - * @offset: register enum - */ -static unsigned char vx2_inb(struct vx_core *chip, int offset) -{ - return inb(vx2_reg_addr(chip, offset)); -} - -/** - * snd_vx_outb - write a byte on the register - * @offset: the register offset - * @val: the value to write - */ -static void vx2_outb(struct vx_core *chip, int offset, unsigned char val) -{ - outb(val, vx2_reg_addr(chip, offset)); - /* - printk(KERN_DEBUG "outb: %x -> %x\n", val, vx2_reg_addr(chip, offset)); - */ -} - -/** - * snd_vx_inl - read a 32bit word from the register - * @offset: register enum - */ -static unsigned int vx2_inl(struct vx_core *chip, int offset) -{ - return inl(vx2_reg_addr(chip, offset)); -} - -/** - * snd_vx_outl - write a 32bit word on the register - * @offset: the register enum - * @val: the value to write - */ -static void vx2_outl(struct vx_core *chip, int offset, unsigned int val) -{ - /* - printk(KERN_DEBUG "outl: %x -> %x\n", val, vx2_reg_addr(chip, offset)); - */ - outl(val, vx2_reg_addr(chip, offset)); -} - -/* - * redefine macros to call directly - */ -#undef vx_inb -#define vx_inb(chip,reg) vx2_inb((struct vx_core*)(chip), VX_##reg) -#undef vx_outb -#define vx_outb(chip,reg,val) vx2_outb((struct vx_core*)(chip), VX_##reg, val) -#undef vx_inl -#define vx_inl(chip,reg) vx2_inl((struct vx_core*)(chip), VX_##reg) -#undef vx_outl -#define vx_outl(chip,reg,val) vx2_outl((struct vx_core*)(chip), VX_##reg, val) - - -/* - * vx_reset_dsp - reset the DSP - */ - -#define XX_DSP_RESET_WAIT_TIME 2 /* ms */ - -static void vx2_reset_dsp(struct vx_core *_chip) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - - /* set the reset dsp bit to 0 */ - vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_DSP_RESET_MASK); - - mdelay(XX_DSP_RESET_WAIT_TIME); - - chip->regCDSP |= VX_CDSP_DSP_RESET_MASK; - /* set the reset dsp bit to 1 */ - vx_outl(chip, CDSP, chip->regCDSP); -} - - -static int vx2_test_xilinx(struct vx_core *_chip) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - unsigned int data; - - snd_printdd("testing xilinx...\n"); - /* This test uses several write/read sequences on TEST0 and TEST1 bits - * to figure out whever or not the xilinx was correctly loaded - */ - - /* We write 1 on CDSP.TEST0. We should get 0 on STATUS.TEST0. */ - vx_outl(chip, CDSP, chip->regCDSP | VX_CDSP_TEST0_MASK); - vx_inl(chip, ISR); - data = vx_inl(chip, STATUS); - if ((data & VX_STATUS_VAL_TEST0_MASK) == VX_STATUS_VAL_TEST0_MASK) { - snd_printdd("bad!\n"); - return -ENODEV; - } - - /* We write 0 on CDSP.TEST0. We should get 1 on STATUS.TEST0. */ - vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_TEST0_MASK); - vx_inl(chip, ISR); - data = vx_inl(chip, STATUS); - if (! (data & VX_STATUS_VAL_TEST0_MASK)) { - snd_printdd("bad! #2\n"); - return -ENODEV; - } - - if (_chip->type == VX_TYPE_BOARD) { - /* not implemented on VX_2_BOARDS */ - /* We write 1 on CDSP.TEST1. We should get 0 on STATUS.TEST1. */ - vx_outl(chip, CDSP, chip->regCDSP | VX_CDSP_TEST1_MASK); - vx_inl(chip, ISR); - data = vx_inl(chip, STATUS); - if ((data & VX_STATUS_VAL_TEST1_MASK) == VX_STATUS_VAL_TEST1_MASK) { - snd_printdd("bad! #3\n"); - return -ENODEV; - } - - /* We write 0 on CDSP.TEST1. We should get 1 on STATUS.TEST1. */ - vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_TEST1_MASK); - vx_inl(chip, ISR); - data = vx_inl(chip, STATUS); - if (! (data & VX_STATUS_VAL_TEST1_MASK)) { - snd_printdd("bad! #4\n"); - return -ENODEV; - } - } - snd_printdd("ok, xilinx fine.\n"); - return 0; -} - - -/** - * vx_setup_pseudo_dma - set up the pseudo dma read/write mode. - * @do_write: 0 = read, 1 = set up for DMA write - */ -static void vx2_setup_pseudo_dma(struct vx_core *chip, int do_write) -{ - /* Interrupt mode and HREQ pin enabled for host transmit data transfers - * (in case of the use of the pseudo-dma facility). - */ - vx_outl(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ); - - /* Reset the pseudo-dma register (in case of the use of the - * pseudo-dma facility). - */ - vx_outl(chip, RESET_DMA, 0); -} - -/* - * vx_release_pseudo_dma - disable the pseudo-DMA mode - */ -static inline void vx2_release_pseudo_dma(struct vx_core *chip) -{ - /* HREQ pin disabled. */ - vx_outl(chip, ICR, 0); -} - - - -/* pseudo-dma write */ -static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe, int count) -{ - unsigned long port = vx2_reg_addr(chip, VX_DMA); - int offset = pipe->hw_ptr; - u32 *addr = (u32 *)(runtime->dma_area + offset); - - if (snd_BUG_ON(count % 4)) - return; - - vx2_setup_pseudo_dma(chip, 1); - - /* Transfer using pseudo-dma. - */ - if (offset + count > pipe->buffer_bytes) { - int length = pipe->buffer_bytes - offset; - count -= length; - length >>= 2; /* in 32bit words */ - /* Transfer using pseudo-dma. */ - while (length-- > 0) { - outl(cpu_to_le32(*addr), port); - addr++; - } - addr = (u32 *)runtime->dma_area; - pipe->hw_ptr = 0; - } - pipe->hw_ptr += count; - count >>= 2; /* in 32bit words */ - /* Transfer using pseudo-dma. */ - while (count-- > 0) { - outl(cpu_to_le32(*addr), port); - addr++; - } - - vx2_release_pseudo_dma(chip); -} - - -/* pseudo dma read */ -static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe, int count) -{ - int offset = pipe->hw_ptr; - u32 *addr = (u32 *)(runtime->dma_area + offset); - unsigned long port = vx2_reg_addr(chip, VX_DMA); - - if (snd_BUG_ON(count % 4)) - return; - - vx2_setup_pseudo_dma(chip, 0); - /* Transfer using pseudo-dma. - */ - if (offset + count > pipe->buffer_bytes) { - int length = pipe->buffer_bytes - offset; - count -= length; - length >>= 2; /* in 32bit words */ - /* Transfer using pseudo-dma. */ - while (length-- > 0) - *addr++ = le32_to_cpu(inl(port)); - addr = (u32 *)runtime->dma_area; - pipe->hw_ptr = 0; - } - pipe->hw_ptr += count; - count >>= 2; /* in 32bit words */ - /* Transfer using pseudo-dma. */ - while (count-- > 0) - *addr++ = le32_to_cpu(inl(port)); - - vx2_release_pseudo_dma(chip); -} - -#define VX_XILINX_RESET_MASK 0x40000000 -#define VX_USERBIT0_MASK 0x00000004 -#define VX_USERBIT1_MASK 0x00000020 -#define VX_CNTRL_REGISTER_VALUE 0x00172012 - -/* - * transfer counts bits to PLX - */ -static int put_xilinx_data(struct vx_core *chip, unsigned int port, unsigned int counts, unsigned char data) -{ - unsigned int i; - - for (i = 0; i < counts; i++) { - unsigned int val; - - /* set the clock bit to 0. */ - val = VX_CNTRL_REGISTER_VALUE & ~VX_USERBIT0_MASK; - vx2_outl(chip, port, val); - vx2_inl(chip, port); - udelay(1); - - if (data & (1 << i)) - val |= VX_USERBIT1_MASK; - else - val &= ~VX_USERBIT1_MASK; - vx2_outl(chip, port, val); - vx2_inl(chip, port); - - /* set the clock bit to 1. */ - val |= VX_USERBIT0_MASK; - vx2_outl(chip, port, val); - vx2_inl(chip, port); - udelay(1); - } - return 0; -} - -/* - * load the xilinx image - */ -static int vx2_load_xilinx_binary(struct vx_core *chip, const struct firmware *xilinx) -{ - unsigned int i; - unsigned int port; - const unsigned char *image; - - /* XILINX reset (wait at least 1 millisecond between reset on and off). */ - vx_outl(chip, CNTRL, VX_CNTRL_REGISTER_VALUE | VX_XILINX_RESET_MASK); - vx_inl(chip, CNTRL); - msleep(10); - vx_outl(chip, CNTRL, VX_CNTRL_REGISTER_VALUE); - vx_inl(chip, CNTRL); - msleep(10); - - if (chip->type == VX_TYPE_BOARD) - port = VX_CNTRL; - else - port = VX_GPIOC; /* VX222 V2 and VX222_MIC_BOARD with new PLX9030 use this register */ - - image = xilinx->data; - for (i = 0; i < xilinx->size; i++, image++) { - if (put_xilinx_data(chip, port, 8, *image) < 0) - return -EINVAL; - /* don't take too much time in this loop... */ - cond_resched(); - } - put_xilinx_data(chip, port, 4, 0xff); /* end signature */ - - msleep(200); - - /* test after loading (is buggy with VX222) */ - if (chip->type != VX_TYPE_BOARD) { - /* Test if load successful: test bit 8 of register GPIOC (VX222: use CNTRL) ! */ - i = vx_inl(chip, GPIOC); - if (i & 0x0100) - return 0; - snd_printk(KERN_ERR "vx222: xilinx test failed after load, GPIOC=0x%x\n", i); - return -EINVAL; - } - - return 0; -} - - -/* - * load the boot/dsp images - */ -static int vx2_load_dsp(struct vx_core *vx, int index, const struct firmware *dsp) -{ - int err; - - switch (index) { - case 1: - /* xilinx image */ - if ((err = vx2_load_xilinx_binary(vx, dsp)) < 0) - return err; - if ((err = vx2_test_xilinx(vx)) < 0) - return err; - return 0; - case 2: - /* DSP boot */ - return snd_vx_dsp_boot(vx, dsp); - case 3: - /* DSP image */ - return snd_vx_dsp_load(vx, dsp); - default: - snd_BUG(); - return -EINVAL; - } -} - - -/* - * vx_test_and_ack - test and acknowledge interrupt - * - * called from irq hander, too - * - * spinlock held! - */ -static int vx2_test_and_ack(struct vx_core *chip) -{ - /* not booted yet? */ - if (! (chip->chip_status & VX_STAT_XILINX_LOADED)) - return -ENXIO; - - if (! (vx_inl(chip, STATUS) & VX_STATUS_MEMIRQ_MASK)) - return -EIO; - - /* ok, interrupts generated, now ack it */ - /* set ACQUIT bit up and down */ - vx_outl(chip, STATUS, 0); - /* useless read just to spend some time and maintain - * the ACQUIT signal up for a while ( a bus cycle ) - */ - vx_inl(chip, STATUS); - /* ack */ - vx_outl(chip, STATUS, VX_STATUS_MEMIRQ_MASK); - /* useless read just to spend some time and maintain - * the ACQUIT signal up for a while ( a bus cycle ) */ - vx_inl(chip, STATUS); - /* clear */ - vx_outl(chip, STATUS, 0); - - return 0; -} - - -/* - * vx_validate_irq - enable/disable IRQ - */ -static void vx2_validate_irq(struct vx_core *_chip, int enable) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - - /* Set the interrupt enable bit to 1 in CDSP register */ - if (enable) { - /* Set the PCI interrupt enable bit to 1.*/ - vx_outl(chip, INTCSR, VX_INTCSR_VALUE|VX_PCI_INTERRUPT_MASK); - chip->regCDSP |= VX_CDSP_VALID_IRQ_MASK; - } else { - /* Set the PCI interrupt enable bit to 0. */ - vx_outl(chip, INTCSR, VX_INTCSR_VALUE&~VX_PCI_INTERRUPT_MASK); - chip->regCDSP &= ~VX_CDSP_VALID_IRQ_MASK; - } - vx_outl(chip, CDSP, chip->regCDSP); -} - - -/* - * write an AKM codec data (24bit) - */ -static void vx2_write_codec_reg(struct vx_core *chip, unsigned int data) -{ - unsigned int i; - - vx_inl(chip, HIFREQ); - - /* We have to send 24 bits (3 x 8 bits). Start with most signif. Bit */ - for (i = 0; i < 24; i++, data <<= 1) - vx_outl(chip, DATA, ((data & 0x800000) ? VX_DATA_CODEC_MASK : 0)); - /* Terminate access to codec registers */ - vx_inl(chip, RUER); -} - - -#define AKM_CODEC_POWER_CONTROL_CMD 0xA007 -#define AKM_CODEC_RESET_ON_CMD 0xA100 -#define AKM_CODEC_RESET_OFF_CMD 0xA103 -#define AKM_CODEC_CLOCK_FORMAT_CMD 0xA240 -#define AKM_CODEC_MUTE_CMD 0xA38D -#define AKM_CODEC_UNMUTE_CMD 0xA30D -#define AKM_CODEC_LEFT_LEVEL_CMD 0xA400 -#define AKM_CODEC_RIGHT_LEVEL_CMD 0xA500 - -static const u8 vx2_akm_gains_lut[VX2_AKM_LEVEL_MAX+1] = { - 0x7f, // [000] = +0.000 dB -> AKM(0x7f) = +0.000 dB error(+0.000 dB) - 0x7d, // [001] = -0.500 dB -> AKM(0x7d) = -0.572 dB error(-0.072 dB) - 0x7c, // [002] = -1.000 dB -> AKM(0x7c) = -0.873 dB error(+0.127 dB) - 0x7a, // [003] = -1.500 dB -> AKM(0x7a) = -1.508 dB error(-0.008 dB) - 0x79, // [004] = -2.000 dB -> AKM(0x79) = -1.844 dB error(+0.156 dB) - 0x77, // [005] = -2.500 dB -> AKM(0x77) = -2.557 dB error(-0.057 dB) - 0x76, // [006] = -3.000 dB -> AKM(0x76) = -2.937 dB error(+0.063 dB) - 0x75, // [007] = -3.500 dB -> AKM(0x75) = -3.334 dB error(+0.166 dB) - 0x73, // [008] = -4.000 dB -> AKM(0x73) = -4.188 dB error(-0.188 dB) - 0x72, // [009] = -4.500 dB -> AKM(0x72) = -4.648 dB error(-0.148 dB) - 0x71, // [010] = -5.000 dB -> AKM(0x71) = -5.134 dB error(-0.134 dB) - 0x70, // [011] = -5.500 dB -> AKM(0x70) = -5.649 dB error(-0.149 dB) - 0x6f, // [012] = -6.000 dB -> AKM(0x6f) = -6.056 dB error(-0.056 dB) - 0x6d, // [013] = -6.500 dB -> AKM(0x6d) = -6.631 dB error(-0.131 dB) - 0x6c, // [014] = -7.000 dB -> AKM(0x6c) = -6.933 dB error(+0.067 dB) - 0x6a, // [015] = -7.500 dB -> AKM(0x6a) = -7.571 dB error(-0.071 dB) - 0x69, // [016] = -8.000 dB -> AKM(0x69) = -7.909 dB error(+0.091 dB) - 0x67, // [017] = -8.500 dB -> AKM(0x67) = -8.626 dB error(-0.126 dB) - 0x66, // [018] = -9.000 dB -> AKM(0x66) = -9.008 dB error(-0.008 dB) - 0x65, // [019] = -9.500 dB -> AKM(0x65) = -9.407 dB error(+0.093 dB) - 0x64, // [020] = -10.000 dB -> AKM(0x64) = -9.826 dB error(+0.174 dB) - 0x62, // [021] = -10.500 dB -> AKM(0x62) = -10.730 dB error(-0.230 dB) - 0x61, // [022] = -11.000 dB -> AKM(0x61) = -11.219 dB error(-0.219 dB) - 0x60, // [023] = -11.500 dB -> AKM(0x60) = -11.738 dB error(-0.238 dB) - 0x5f, // [024] = -12.000 dB -> AKM(0x5f) = -12.149 dB error(-0.149 dB) - 0x5e, // [025] = -12.500 dB -> AKM(0x5e) = -12.434 dB error(+0.066 dB) - 0x5c, // [026] = -13.000 dB -> AKM(0x5c) = -13.033 dB error(-0.033 dB) - 0x5b, // [027] = -13.500 dB -> AKM(0x5b) = -13.350 dB error(+0.150 dB) - 0x59, // [028] = -14.000 dB -> AKM(0x59) = -14.018 dB error(-0.018 dB) - 0x58, // [029] = -14.500 dB -> AKM(0x58) = -14.373 dB error(+0.127 dB) - 0x56, // [030] = -15.000 dB -> AKM(0x56) = -15.130 dB error(-0.130 dB) - 0x55, // [031] = -15.500 dB -> AKM(0x55) = -15.534 dB error(-0.034 dB) - 0x54, // [032] = -16.000 dB -> AKM(0x54) = -15.958 dB error(+0.042 dB) - 0x53, // [033] = -16.500 dB -> AKM(0x53) = -16.404 dB error(+0.096 dB) - 0x52, // [034] = -17.000 dB -> AKM(0x52) = -16.874 dB error(+0.126 dB) - 0x51, // [035] = -17.500 dB -> AKM(0x51) = -17.371 dB error(+0.129 dB) - 0x50, // [036] = -18.000 dB -> AKM(0x50) = -17.898 dB error(+0.102 dB) - 0x4e, // [037] = -18.500 dB -> AKM(0x4e) = -18.605 dB error(-0.105 dB) - 0x4d, // [038] = -19.000 dB -> AKM(0x4d) = -18.905 dB error(+0.095 dB) - 0x4b, // [039] = -19.500 dB -> AKM(0x4b) = -19.538 dB error(-0.038 dB) - 0x4a, // [040] = -20.000 dB -> AKM(0x4a) = -19.872 dB error(+0.128 dB) - 0x48, // [041] = -20.500 dB -> AKM(0x48) = -20.583 dB error(-0.083 dB) - 0x47, // [042] = -21.000 dB -> AKM(0x47) = -20.961 dB error(+0.039 dB) - 0x46, // [043] = -21.500 dB -> AKM(0x46) = -21.356 dB error(+0.144 dB) - 0x44, // [044] = -22.000 dB -> AKM(0x44) = -22.206 dB error(-0.206 dB) - 0x43, // [045] = -22.500 dB -> AKM(0x43) = -22.664 dB error(-0.164 dB) - 0x42, // [046] = -23.000 dB -> AKM(0x42) = -23.147 dB error(-0.147 dB) - 0x41, // [047] = -23.500 dB -> AKM(0x41) = -23.659 dB error(-0.159 dB) - 0x40, // [048] = -24.000 dB -> AKM(0x40) = -24.203 dB error(-0.203 dB) - 0x3f, // [049] = -24.500 dB -> AKM(0x3f) = -24.635 dB error(-0.135 dB) - 0x3e, // [050] = -25.000 dB -> AKM(0x3e) = -24.935 dB error(+0.065 dB) - 0x3c, // [051] = -25.500 dB -> AKM(0x3c) = -25.569 dB error(-0.069 dB) - 0x3b, // [052] = -26.000 dB -> AKM(0x3b) = -25.904 dB error(+0.096 dB) - 0x39, // [053] = -26.500 dB -> AKM(0x39) = -26.615 dB error(-0.115 dB) - 0x38, // [054] = -27.000 dB -> AKM(0x38) = -26.994 dB error(+0.006 dB) - 0x37, // [055] = -27.500 dB -> AKM(0x37) = -27.390 dB error(+0.110 dB) - 0x36, // [056] = -28.000 dB -> AKM(0x36) = -27.804 dB error(+0.196 dB) - 0x34, // [057] = -28.500 dB -> AKM(0x34) = -28.699 dB error(-0.199 dB) - 0x33, // [058] = -29.000 dB -> AKM(0x33) = -29.183 dB error(-0.183 dB) - 0x32, // [059] = -29.500 dB -> AKM(0x32) = -29.696 dB error(-0.196 dB) - 0x31, // [060] = -30.000 dB -> AKM(0x31) = -30.241 dB error(-0.241 dB) - 0x31, // [061] = -30.500 dB -> AKM(0x31) = -30.241 dB error(+0.259 dB) - 0x30, // [062] = -31.000 dB -> AKM(0x30) = -30.823 dB error(+0.177 dB) - 0x2e, // [063] = -31.500 dB -> AKM(0x2e) = -31.610 dB error(-0.110 dB) - 0x2d, // [064] = -32.000 dB -> AKM(0x2d) = -31.945 dB error(+0.055 dB) - 0x2b, // [065] = -32.500 dB -> AKM(0x2b) = -32.659 dB error(-0.159 dB) - 0x2a, // [066] = -33.000 dB -> AKM(0x2a) = -33.038 dB error(-0.038 dB) - 0x29, // [067] = -33.500 dB -> AKM(0x29) = -33.435 dB error(+0.065 dB) - 0x28, // [068] = -34.000 dB -> AKM(0x28) = -33.852 dB error(+0.148 dB) - 0x27, // [069] = -34.500 dB -> AKM(0x27) = -34.289 dB error(+0.211 dB) - 0x25, // [070] = -35.000 dB -> AKM(0x25) = -35.235 dB error(-0.235 dB) - 0x24, // [071] = -35.500 dB -> AKM(0x24) = -35.750 dB error(-0.250 dB) - 0x24, // [072] = -36.000 dB -> AKM(0x24) = -35.750 dB error(+0.250 dB) - 0x23, // [073] = -36.500 dB -> AKM(0x23) = -36.297 dB error(+0.203 dB) - 0x22, // [074] = -37.000 dB -> AKM(0x22) = -36.881 dB error(+0.119 dB) - 0x21, // [075] = -37.500 dB -> AKM(0x21) = -37.508 dB error(-0.008 dB) - 0x20, // [076] = -38.000 dB -> AKM(0x20) = -38.183 dB error(-0.183 dB) - 0x1f, // [077] = -38.500 dB -> AKM(0x1f) = -38.726 dB error(-0.226 dB) - 0x1e, // [078] = -39.000 dB -> AKM(0x1e) = -39.108 dB error(-0.108 dB) - 0x1d, // [079] = -39.500 dB -> AKM(0x1d) = -39.507 dB error(-0.007 dB) - 0x1c, // [080] = -40.000 dB -> AKM(0x1c) = -39.926 dB error(+0.074 dB) - 0x1b, // [081] = -40.500 dB -> AKM(0x1b) = -40.366 dB error(+0.134 dB) - 0x1a, // [082] = -41.000 dB -> AKM(0x1a) = -40.829 dB error(+0.171 dB) - 0x19, // [083] = -41.500 dB -> AKM(0x19) = -41.318 dB error(+0.182 dB) - 0x18, // [084] = -42.000 dB -> AKM(0x18) = -41.837 dB error(+0.163 dB) - 0x17, // [085] = -42.500 dB -> AKM(0x17) = -42.389 dB error(+0.111 dB) - 0x16, // [086] = -43.000 dB -> AKM(0x16) = -42.978 dB error(+0.022 dB) - 0x15, // [087] = -43.500 dB -> AKM(0x15) = -43.610 dB error(-0.110 dB) - 0x14, // [088] = -44.000 dB -> AKM(0x14) = -44.291 dB error(-0.291 dB) - 0x14, // [089] = -44.500 dB -> AKM(0x14) = -44.291 dB error(+0.209 dB) - 0x13, // [090] = -45.000 dB -> AKM(0x13) = -45.031 dB error(-0.031 dB) - 0x12, // [091] = -45.500 dB -> AKM(0x12) = -45.840 dB error(-0.340 dB) - 0x12, // [092] = -46.000 dB -> AKM(0x12) = -45.840 dB error(+0.160 dB) - 0x11, // [093] = -46.500 dB -> AKM(0x11) = -46.731 dB error(-0.231 dB) - 0x11, // [094] = -47.000 dB -> AKM(0x11) = -46.731 dB error(+0.269 dB) - 0x10, // [095] = -47.500 dB -> AKM(0x10) = -47.725 dB error(-0.225 dB) - 0x10, // [096] = -48.000 dB -> AKM(0x10) = -47.725 dB error(+0.275 dB) - 0x0f, // [097] = -48.500 dB -> AKM(0x0f) = -48.553 dB error(-0.053 dB) - 0x0e, // [098] = -49.000 dB -> AKM(0x0e) = -49.152 dB error(-0.152 dB) - 0x0d, // [099] = -49.500 dB -> AKM(0x0d) = -49.796 dB error(-0.296 dB) - 0x0d, // [100] = -50.000 dB -> AKM(0x0d) = -49.796 dB error(+0.204 dB) - 0x0c, // [101] = -50.500 dB -> AKM(0x0c) = -50.491 dB error(+0.009 dB) - 0x0b, // [102] = -51.000 dB -> AKM(0x0b) = -51.247 dB error(-0.247 dB) - 0x0b, // [103] = -51.500 dB -> AKM(0x0b) = -51.247 dB error(+0.253 dB) - 0x0a, // [104] = -52.000 dB -> AKM(0x0a) = -52.075 dB error(-0.075 dB) - 0x0a, // [105] = -52.500 dB -> AKM(0x0a) = -52.075 dB error(+0.425 dB) - 0x09, // [106] = -53.000 dB -> AKM(0x09) = -52.990 dB error(+0.010 dB) - 0x09, // [107] = -53.500 dB -> AKM(0x09) = -52.990 dB error(+0.510 dB) - 0x08, // [108] = -54.000 dB -> AKM(0x08) = -54.013 dB error(-0.013 dB) - 0x08, // [109] = -54.500 dB -> AKM(0x08) = -54.013 dB error(+0.487 dB) - 0x07, // [110] = -55.000 dB -> AKM(0x07) = -55.173 dB error(-0.173 dB) - 0x07, // [111] = -55.500 dB -> AKM(0x07) = -55.173 dB error(+0.327 dB) - 0x06, // [112] = -56.000 dB -> AKM(0x06) = -56.512 dB error(-0.512 dB) - 0x06, // [113] = -56.500 dB -> AKM(0x06) = -56.512 dB error(-0.012 dB) - 0x06, // [114] = -57.000 dB -> AKM(0x06) = -56.512 dB error(+0.488 dB) - 0x05, // [115] = -57.500 dB -> AKM(0x05) = -58.095 dB error(-0.595 dB) - 0x05, // [116] = -58.000 dB -> AKM(0x05) = -58.095 dB error(-0.095 dB) - 0x05, // [117] = -58.500 dB -> AKM(0x05) = -58.095 dB error(+0.405 dB) - 0x05, // [118] = -59.000 dB -> AKM(0x05) = -58.095 dB error(+0.905 dB) - 0x04, // [119] = -59.500 dB -> AKM(0x04) = -60.034 dB error(-0.534 dB) - 0x04, // [120] = -60.000 dB -> AKM(0x04) = -60.034 dB error(-0.034 dB) - 0x04, // [121] = -60.500 dB -> AKM(0x04) = -60.034 dB error(+0.466 dB) - 0x04, // [122] = -61.000 dB -> AKM(0x04) = -60.034 dB error(+0.966 dB) - 0x03, // [123] = -61.500 dB -> AKM(0x03) = -62.532 dB error(-1.032 dB) - 0x03, // [124] = -62.000 dB -> AKM(0x03) = -62.532 dB error(-0.532 dB) - 0x03, // [125] = -62.500 dB -> AKM(0x03) = -62.532 dB error(-0.032 dB) - 0x03, // [126] = -63.000 dB -> AKM(0x03) = -62.532 dB error(+0.468 dB) - 0x03, // [127] = -63.500 dB -> AKM(0x03) = -62.532 dB error(+0.968 dB) - 0x03, // [128] = -64.000 dB -> AKM(0x03) = -62.532 dB error(+1.468 dB) - 0x02, // [129] = -64.500 dB -> AKM(0x02) = -66.054 dB error(-1.554 dB) - 0x02, // [130] = -65.000 dB -> AKM(0x02) = -66.054 dB error(-1.054 dB) - 0x02, // [131] = -65.500 dB -> AKM(0x02) = -66.054 dB error(-0.554 dB) - 0x02, // [132] = -66.000 dB -> AKM(0x02) = -66.054 dB error(-0.054 dB) - 0x02, // [133] = -66.500 dB -> AKM(0x02) = -66.054 dB error(+0.446 dB) - 0x02, // [134] = -67.000 dB -> AKM(0x02) = -66.054 dB error(+0.946 dB) - 0x02, // [135] = -67.500 dB -> AKM(0x02) = -66.054 dB error(+1.446 dB) - 0x02, // [136] = -68.000 dB -> AKM(0x02) = -66.054 dB error(+1.946 dB) - 0x02, // [137] = -68.500 dB -> AKM(0x02) = -66.054 dB error(+2.446 dB) - 0x02, // [138] = -69.000 dB -> AKM(0x02) = -66.054 dB error(+2.946 dB) - 0x01, // [139] = -69.500 dB -> AKM(0x01) = -72.075 dB error(-2.575 dB) - 0x01, // [140] = -70.000 dB -> AKM(0x01) = -72.075 dB error(-2.075 dB) - 0x01, // [141] = -70.500 dB -> AKM(0x01) = -72.075 dB error(-1.575 dB) - 0x01, // [142] = -71.000 dB -> AKM(0x01) = -72.075 dB error(-1.075 dB) - 0x01, // [143] = -71.500 dB -> AKM(0x01) = -72.075 dB error(-0.575 dB) - 0x01, // [144] = -72.000 dB -> AKM(0x01) = -72.075 dB error(-0.075 dB) - 0x01, // [145] = -72.500 dB -> AKM(0x01) = -72.075 dB error(+0.425 dB) - 0x01, // [146] = -73.000 dB -> AKM(0x01) = -72.075 dB error(+0.925 dB) - 0x00}; // [147] = -73.500 dB -> AKM(0x00) = mute error(+infini) - -/* - * pseudo-codec write entry - */ -static void vx2_write_akm(struct vx_core *chip, int reg, unsigned int data) -{ - unsigned int val; - - if (reg == XX_CODEC_DAC_CONTROL_REGISTER) { - vx2_write_codec_reg(chip, data ? AKM_CODEC_MUTE_CMD : AKM_CODEC_UNMUTE_CMD); - return; - } - - /* `data' is a value between 0x0 and VX2_AKM_LEVEL_MAX = 0x093, in the case of the AKM codecs, we need - a look up table, as there is no linear matching between the driver codec values - and the real dBu value - */ - if (snd_BUG_ON(data >= sizeof(vx2_akm_gains_lut))) - return; - - switch (reg) { - case XX_CODEC_LEVEL_LEFT_REGISTER: - val = AKM_CODEC_LEFT_LEVEL_CMD; - break; - case XX_CODEC_LEVEL_RIGHT_REGISTER: - val = AKM_CODEC_RIGHT_LEVEL_CMD; - break; - default: - snd_BUG(); - return; - } - val |= vx2_akm_gains_lut[data]; - - vx2_write_codec_reg(chip, val); -} - - -/* - * write codec bit for old VX222 board - */ -static void vx2_old_write_codec_bit(struct vx_core *chip, int codec, unsigned int data) -{ - int i; - - /* activate access to codec registers */ - vx_inl(chip, HIFREQ); - - for (i = 0; i < 24; i++, data <<= 1) - vx_outl(chip, DATA, ((data & 0x800000) ? VX_DATA_CODEC_MASK : 0)); - - /* Terminate access to codec registers */ - vx_inl(chip, RUER); -} - - -/* - * reset codec bit - */ -static void vx2_reset_codec(struct vx_core *_chip) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - - /* Set the reset CODEC bit to 0. */ - vx_outl(chip, CDSP, chip->regCDSP &~ VX_CDSP_CODEC_RESET_MASK); - vx_inl(chip, CDSP); - msleep(10); - /* Set the reset CODEC bit to 1. */ - chip->regCDSP |= VX_CDSP_CODEC_RESET_MASK; - vx_outl(chip, CDSP, chip->regCDSP); - vx_inl(chip, CDSP); - if (_chip->type == VX_TYPE_BOARD) { - msleep(1); - return; - } - - msleep(5); /* additionnel wait time for AKM's */ - - vx2_write_codec_reg(_chip, AKM_CODEC_POWER_CONTROL_CMD); /* DAC power up, ADC power up, Vref power down */ - - vx2_write_codec_reg(_chip, AKM_CODEC_CLOCK_FORMAT_CMD); /* default */ - vx2_write_codec_reg(_chip, AKM_CODEC_MUTE_CMD); /* Mute = ON ,Deemphasis = OFF */ - vx2_write_codec_reg(_chip, AKM_CODEC_RESET_OFF_CMD); /* DAC and ADC normal operation */ - - if (_chip->type == VX_TYPE_MIC) { - /* set up the micro input selector */ - chip->regSELMIC = MICRO_SELECT_INPUT_NORM | - MICRO_SELECT_PREAMPLI_G_0 | - MICRO_SELECT_NOISE_T_52DB; - - /* reset phantom power supply */ - chip->regSELMIC &= ~MICRO_SELECT_PHANTOM_ALIM; - - vx_outl(_chip, SELMIC, chip->regSELMIC); - } -} - - -/* - * change the audio source - */ -static void vx2_change_audio_source(struct vx_core *_chip, int src) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - - switch (src) { - case VX_AUDIO_SRC_DIGITAL: - chip->regCFG |= VX_CFG_DATAIN_SEL_MASK; - break; - default: - chip->regCFG &= ~VX_CFG_DATAIN_SEL_MASK; - break; - } - vx_outl(chip, CFG, chip->regCFG); -} - - -/* - * set the clock source - */ -static void vx2_set_clock_source(struct vx_core *_chip, int source) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - - if (source == INTERNAL_QUARTZ) - chip->regCFG &= ~VX_CFG_CLOCKIN_SEL_MASK; - else - chip->regCFG |= VX_CFG_CLOCKIN_SEL_MASK; - vx_outl(chip, CFG, chip->regCFG); -} - -/* - * reset the board - */ -static void vx2_reset_board(struct vx_core *_chip, int cold_reset) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - - /* initialize the register values */ - chip->regCDSP = VX_CDSP_CODEC_RESET_MASK | VX_CDSP_DSP_RESET_MASK ; - chip->regCFG = 0; -} - - - -/* - * input level controls for VX222 Mic - */ - -/* Micro level is specified to be adjustable from -96dB to 63 dB (board coded 0x00 ... 318), - * 318 = 210 + 36 + 36 + 36 (210 = +9dB variable) (3 * 36 = 3 steps of 18dB pre ampli) - * as we will mute if less than -110dB, so let's simply use line input coded levels and add constant offset ! - */ -#define V2_MICRO_LEVEL_RANGE (318 - 255) - -static void vx2_set_input_level(struct snd_vx222 *chip) -{ - int i, miclevel, preamp; - unsigned int data; - - miclevel = chip->mic_level; - miclevel += V2_MICRO_LEVEL_RANGE; /* add 318 - 0xff */ - preamp = 0; - while (miclevel > 210) { /* limitation to +9dB of 3310 real gain */ - preamp++; /* raise pre ampli + 18dB */ - miclevel -= (18 * 2); /* lower level 18 dB (*2 because of 0.5 dB steps !) */ - } - if (snd_BUG_ON(preamp >= 4)) - return; - - /* set pre-amp level */ - chip->regSELMIC &= ~MICRO_SELECT_PREAMPLI_MASK; - chip->regSELMIC |= (preamp << MICRO_SELECT_PREAMPLI_OFFSET) & MICRO_SELECT_PREAMPLI_MASK; - vx_outl(chip, SELMIC, chip->regSELMIC); - - data = (unsigned int)miclevel << 16 | - (unsigned int)chip->input_level[1] << 8 | - (unsigned int)chip->input_level[0]; - vx_inl(chip, DATA); /* Activate input level programming */ - - /* We have to send 32 bits (4 x 8 bits) */ - for (i = 0; i < 32; i++, data <<= 1) - vx_outl(chip, DATA, ((data & 0x80000000) ? VX_DATA_CODEC_MASK : 0)); - - vx_inl(chip, RUER); /* Terminate input level programming */ -} - - -#define MIC_LEVEL_MAX 0xff - -static const DECLARE_TLV_DB_SCALE(db_scale_mic, -6450, 50, 0); - -/* - * controls API for input levels - */ - -/* input levels */ -static int vx_input_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = MIC_LEVEL_MAX; - return 0; -} - -static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - mutex_lock(&_chip->mixer_mutex); - ucontrol->value.integer.value[0] = chip->input_level[0]; - ucontrol->value.integer.value[1] = chip->input_level[1]; - mutex_unlock(&_chip->mixer_mutex); - return 0; -} - -static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - if (ucontrol->value.integer.value[0] < 0 || - ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) - return -EINVAL; - if (ucontrol->value.integer.value[1] < 0 || - ucontrol->value.integer.value[1] > MIC_LEVEL_MAX) - return -EINVAL; - mutex_lock(&_chip->mixer_mutex); - if (chip->input_level[0] != ucontrol->value.integer.value[0] || - chip->input_level[1] != ucontrol->value.integer.value[1]) { - chip->input_level[0] = ucontrol->value.integer.value[0]; - chip->input_level[1] = ucontrol->value.integer.value[1]; - vx2_set_input_level(chip); - mutex_unlock(&_chip->mixer_mutex); - return 1; - } - mutex_unlock(&_chip->mixer_mutex); - return 0; -} - -/* mic level */ -static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = MIC_LEVEL_MAX; - return 0; -} - -static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - ucontrol->value.integer.value[0] = chip->mic_level; - return 0; -} - -static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - if (ucontrol->value.integer.value[0] < 0 || - ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) - return -EINVAL; - mutex_lock(&_chip->mixer_mutex); - if (chip->mic_level != ucontrol->value.integer.value[0]) { - chip->mic_level = ucontrol->value.integer.value[0]; - vx2_set_input_level(chip); - mutex_unlock(&_chip->mixer_mutex); - return 1; - } - mutex_unlock(&_chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_input_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Capture Volume", - .info = vx_input_level_info, - .get = vx_input_level_get, - .put = vx_input_level_put, - .tlv = { .p = db_scale_mic }, -}; - -static struct snd_kcontrol_new vx_control_mic_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Mic Capture Volume", - .info = vx_mic_level_info, - .get = vx_mic_level_get, - .put = vx_mic_level_put, - .tlv = { .p = db_scale_mic }, -}; - -/* - * FIXME: compressor/limiter implementation is missing yet... - */ - -static int vx2_add_mic_controls(struct vx_core *_chip) -{ - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; - int err; - - if (_chip->type != VX_TYPE_MIC) - return 0; - - /* mute input levels */ - chip->input_level[0] = chip->input_level[1] = 0; - chip->mic_level = 0; - vx2_set_input_level(chip); - - /* controls */ - if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_input_level, chip))) < 0) - return err; - if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip))) < 0) - return err; - - return 0; -} - - -/* - * callbacks - */ -struct snd_vx_ops vx222_ops = { - .in8 = vx2_inb, - .in32 = vx2_inl, - .out8 = vx2_outb, - .out32 = vx2_outl, - .test_and_ack = vx2_test_and_ack, - .validate_irq = vx2_validate_irq, - .akm_write = vx2_write_akm, - .reset_codec = vx2_reset_codec, - .change_audio_source = vx2_change_audio_source, - .set_clock_source = vx2_set_clock_source, - .load_dsp = vx2_load_dsp, - .reset_dsp = vx2_reset_dsp, - .reset_board = vx2_reset_board, - .dma_write = vx2_dma_write, - .dma_read = vx2_dma_read, - .add_controls = vx2_add_mic_controls, -}; - -/* for old VX222 board */ -struct snd_vx_ops vx222_old_ops = { - .in8 = vx2_inb, - .in32 = vx2_inl, - .out8 = vx2_outb, - .out32 = vx2_outl, - .test_and_ack = vx2_test_and_ack, - .validate_irq = vx2_validate_irq, - .write_codec = vx2_old_write_codec_bit, - .reset_codec = vx2_reset_codec, - .change_audio_source = vx2_change_audio_source, - .set_clock_source = vx2_set_clock_source, - .load_dsp = vx2_load_dsp, - .reset_dsp = vx2_reset_dsp, - .reset_board = vx2_reset_board, - .dma_write = vx2_dma_write, - .dma_read = vx2_dma_read, -}; - diff --git a/ANDROID_3.4.5/sound/pci/ymfpci/Makefile b/ANDROID_3.4.5/sound/pci/ymfpci/Makefile deleted file mode 100644 index bd3d514e..00000000 --- a/ANDROID_3.4.5/sound/pci/ymfpci/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-ymfpci-objs := ymfpci.o ymfpci_main.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_YMFPCI) += snd-ymfpci.o diff --git a/ANDROID_3.4.5/sound/pci/ymfpci/ymfpci.c b/ANDROID_3.4.5/sound/pci/ymfpci/ymfpci.c deleted file mode 100644 index 94ab728f..00000000 --- a/ANDROID_3.4.5/sound/pci/ymfpci/ymfpci.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * The driver for the Yamaha's DS1/DS1E cards - * Copyright (c) by Jaroslav Kysela - * - * - * 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 - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Yamaha DS-1 PCI"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724}," - "{Yamaha,YMF724F}," - "{Yamaha,YMF740}," - "{Yamaha,YMF740C}," - "{Yamaha,YMF744}," - "{Yamaha,YMF754}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static long fm_port[SNDRV_CARDS]; -static long mpu_port[SNDRV_CARDS]; -#ifdef SUPPORT_JOYSTICK -static long joystick_port[SNDRV_CARDS]; -#endif -static bool rear_switch[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the Yamaha DS-1 PCI soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Yamaha DS-1 soundcard."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 Port."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM OPL-3 Port."); -#ifdef SUPPORT_JOYSTICK -module_param_array(joystick_port, long, NULL, 0444); -MODULE_PARM_DESC(joystick_port, "Joystick port address"); -#endif -module_param_array(rear_switch, bool, NULL, 0444); -MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); - -static DEFINE_PCI_DEVICE_TABLE(snd_ymfpci_ids) = { - { PCI_VDEVICE(YAMAHA, 0x0004), 0, }, /* YMF724 */ - { PCI_VDEVICE(YAMAHA, 0x000d), 0, }, /* YMF724F */ - { PCI_VDEVICE(YAMAHA, 0x000a), 0, }, /* YMF740 */ - { PCI_VDEVICE(YAMAHA, 0x000c), 0, }, /* YMF740C */ - { PCI_VDEVICE(YAMAHA, 0x0010), 0, }, /* YMF744 */ - { PCI_VDEVICE(YAMAHA, 0x0012), 0, }, /* YMF754 */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids); - -#ifdef SUPPORT_JOYSTICK -static int __devinit snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, - int legacy_ctrl, int legacy_ctrl2) -{ - struct gameport *gp; - struct resource *r = NULL; - int io_port = joystick_port[dev]; - - if (!io_port) - return -ENODEV; - - if (chip->pci->device >= 0x0010) { /* YMF 744/754 */ - - if (io_port == 1) { - /* auto-detect */ - if (!(io_port = pci_resource_start(chip->pci, 2))) - return -ENODEV; - } - } else { - if (io_port == 1) { - /* auto-detect */ - for (io_port = 0x201; io_port <= 0x205; io_port++) { - if (io_port == 0x203) - continue; - if ((r = request_region(io_port, 1, "YMFPCI gameport")) != NULL) - break; - } - if (!r) { - printk(KERN_ERR "ymfpci: no gameport ports available\n"); - return -EBUSY; - } - } - switch (io_port) { - case 0x201: legacy_ctrl2 |= 0 << 6; break; - case 0x202: legacy_ctrl2 |= 1 << 6; break; - case 0x204: legacy_ctrl2 |= 2 << 6; break; - case 0x205: legacy_ctrl2 |= 3 << 6; break; - default: - printk(KERN_ERR "ymfpci: invalid joystick port %#x", io_port); - return -EINVAL; - } - } - - if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) { - printk(KERN_ERR "ymfpci: joystick port %#x is in use.\n", io_port); - return -EBUSY; - } - - chip->gameport = gp = gameport_allocate_port(); - if (!gp) { - printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n"); - release_and_free_resource(r); - return -ENOMEM; - } - - - gameport_set_name(gp, "Yamaha YMF Gameport"); - gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); - gameport_set_dev_parent(gp, &chip->pci->dev); - gp->io = io_port; - gameport_set_port_data(gp, r); - - if (chip->pci->device >= 0x0010) /* YMF 744/754 */ - pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port); - - pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, legacy_ctrl | YMFPCI_LEGACY_JPEN); - pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2); - - gameport_register_port(chip->gameport); - - return 0; -} - -void snd_ymfpci_free_gameport(struct snd_ymfpci *chip) -{ - if (chip->gameport) { - struct resource *r = gameport_get_port_data(chip->gameport); - - gameport_unregister_port(chip->gameport); - chip->gameport = NULL; - - release_and_free_resource(r); - } -} -#else -static inline int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, int l, int l2) { return -ENOSYS; } -void snd_ymfpci_free_gameport(struct snd_ymfpci *chip) { } -#endif /* SUPPORT_JOYSTICK */ - -static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct resource *fm_res = NULL; - struct resource *mpu_res = NULL; - struct snd_ymfpci *chip; - struct snd_opl3 *opl3; - const char *str, *model; - int err; - u16 legacy_ctrl, legacy_ctrl2, old_legacy_ctrl; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - switch (pci_id->device) { - case 0x0004: str = "YMF724"; model = "DS-1"; break; - case 0x000d: str = "YMF724F"; model = "DS-1"; break; - case 0x000a: str = "YMF740"; model = "DS-1L"; break; - case 0x000c: str = "YMF740C"; model = "DS-1L"; break; - case 0x0010: str = "YMF744"; model = "DS-1S"; break; - case 0x0012: str = "YMF754"; model = "DS-1E"; break; - default: model = str = "???"; break; - } - - legacy_ctrl = 0; - legacy_ctrl2 = 0x0800; /* SBEN = 0, SMOD = 01, LAD = 0 */ - - if (pci_id->device >= 0x0010) { /* YMF 744/754 */ - if (fm_port[dev] == 1) { - /* auto-detect */ - fm_port[dev] = pci_resource_start(pci, 1); - } - if (fm_port[dev] > 0 && - (fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3")) != NULL) { - legacy_ctrl |= YMFPCI_LEGACY_FMEN; - pci_write_config_word(pci, PCIR_DSXG_FMBASE, fm_port[dev]); - } - if (mpu_port[dev] == 1) { - /* auto-detect */ - mpu_port[dev] = pci_resource_start(pci, 1) + 0x20; - } - if (mpu_port[dev] > 0 && - (mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401")) != NULL) { - legacy_ctrl |= YMFPCI_LEGACY_MEN; - pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]); - } - } else { - switch (fm_port[dev]) { - case 0x388: legacy_ctrl2 |= 0; break; - case 0x398: legacy_ctrl2 |= 1; break; - case 0x3a0: legacy_ctrl2 |= 2; break; - case 0x3a8: legacy_ctrl2 |= 3; break; - default: fm_port[dev] = 0; break; - } - if (fm_port[dev] > 0 && - (fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3")) != NULL) { - legacy_ctrl |= YMFPCI_LEGACY_FMEN; - } else { - legacy_ctrl2 &= ~YMFPCI_LEGACY2_FMIO; - fm_port[dev] = 0; - } - switch (mpu_port[dev]) { - case 0x330: legacy_ctrl2 |= 0 << 4; break; - case 0x300: legacy_ctrl2 |= 1 << 4; break; - case 0x332: legacy_ctrl2 |= 2 << 4; break; - case 0x334: legacy_ctrl2 |= 3 << 4; break; - default: mpu_port[dev] = 0; break; - } - if (mpu_port[dev] > 0 && - (mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401")) != NULL) { - legacy_ctrl |= YMFPCI_LEGACY_MEN; - } else { - legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO; - mpu_port[dev] = 0; - } - } - if (mpu_res) { - legacy_ctrl |= YMFPCI_LEGACY_MIEN; - legacy_ctrl2 |= YMFPCI_LEGACY2_IMOD; - } - pci_read_config_word(pci, PCIR_DSXG_LEGACY, &old_legacy_ctrl); - pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); - pci_write_config_word(pci, PCIR_DSXG_ELEGACY, legacy_ctrl2); - if ((err = snd_ymfpci_create(card, pci, - old_legacy_ctrl, - &chip)) < 0) { - snd_card_free(card); - release_and_free_resource(mpu_res); - release_and_free_resource(fm_res); - return err; - } - chip->fm_res = fm_res; - chip->mpu_res = mpu_res; - card->private_data = chip; - - strcpy(card->driver, str); - sprintf(card->shortname, "Yamaha %s (%s)", model, str); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, - chip->reg_area_phys, - chip->irq); - if ((err = snd_ymfpci_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_ymfpci_pcm_spdif(chip, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - err = snd_ymfpci_mixer(chip, rear_switch[dev]); - if (err < 0) { - snd_card_free(card); - return err; - } - if (chip->ac97->ext_id & AC97_EI_SDAC) { - err = snd_ymfpci_pcm_4ch(chip, 2, NULL); - if (err < 0) { - snd_card_free(card); - return err; - } - err = snd_ymfpci_pcm2(chip, 3, NULL); - if (err < 0) { - snd_card_free(card); - return err; - } - } - if ((err = snd_ymfpci_timer(chip, 0)) < 0) { - snd_card_free(card); - return err; - } - if (chip->mpu_res) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, - mpu_port[dev], - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rawmidi)) < 0) { - printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); - legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */ - pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); - } - } - if (chip->fm_res) { - if ((err = snd_opl3_create(card, - fm_port[dev], - fm_port[dev] + 2, - OPL3_HW_OPL3, 1, &opl3)) < 0) { - printk(KERN_WARNING "ymfpci: cannot initialize FM OPL3 at 0x%lx, skipping...\n", fm_port[dev]); - legacy_ctrl &= ~YMFPCI_LEGACY_FMEN; - pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); - } else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "cannot create opl3 hwdep\n"); - return err; - } - } - - snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_ymfpci_ids, - .probe = snd_card_ymfpci_probe, - .remove = __devexit_p(snd_card_ymfpci_remove), -#ifdef CONFIG_PM - .suspend = snd_ymfpci_suspend, - .resume = snd_ymfpci_resume, -#endif -}; - -static int __init alsa_card_ymfpci_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_ymfpci_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_ymfpci_init) -module_exit(alsa_card_ymfpci_exit) diff --git a/ANDROID_3.4.5/sound/pci/ymfpci/ymfpci_main.c b/ANDROID_3.4.5/sound/pci/ymfpci/ymfpci_main.c deleted file mode 100644 index a8159b81..00000000 --- a/ANDROID_3.4.5/sound/pci/ymfpci/ymfpci_main.c +++ /dev/null @@ -1,2470 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela - * Routines for control of YMF724/740/744/754 chips - * - * 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 -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* - * common I/O routines - */ - -static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip); - -static inline u8 snd_ymfpci_readb(struct snd_ymfpci *chip, u32 offset) -{ - return readb(chip->reg_area_virt + offset); -} - -static inline void snd_ymfpci_writeb(struct snd_ymfpci *chip, u32 offset, u8 val) -{ - writeb(val, chip->reg_area_virt + offset); -} - -static inline u16 snd_ymfpci_readw(struct snd_ymfpci *chip, u32 offset) -{ - return readw(chip->reg_area_virt + offset); -} - -static inline void snd_ymfpci_writew(struct snd_ymfpci *chip, u32 offset, u16 val) -{ - writew(val, chip->reg_area_virt + offset); -} - -static inline u32 snd_ymfpci_readl(struct snd_ymfpci *chip, u32 offset) -{ - return readl(chip->reg_area_virt + offset); -} - -static inline void snd_ymfpci_writel(struct snd_ymfpci *chip, u32 offset, u32 val) -{ - writel(val, chip->reg_area_virt + offset); -} - -static int snd_ymfpci_codec_ready(struct snd_ymfpci *chip, int secondary) -{ - unsigned long end_time; - u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; - - end_time = jiffies + msecs_to_jiffies(750); - do { - if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) - return 0; - schedule_timeout_uninterruptible(1); - } while (time_before(jiffies, end_time)); - snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); - return -EBUSY; -} - -static void snd_ymfpci_codec_write(struct snd_ac97 *ac97, u16 reg, u16 val) -{ - struct snd_ymfpci *chip = ac97->private_data; - u32 cmd; - - snd_ymfpci_codec_ready(chip, 0); - cmd = ((YDSXG_AC97WRITECMD | reg) << 16) | val; - snd_ymfpci_writel(chip, YDSXGR_AC97CMDDATA, cmd); -} - -static u16 snd_ymfpci_codec_read(struct snd_ac97 *ac97, u16 reg) -{ - struct snd_ymfpci *chip = ac97->private_data; - - if (snd_ymfpci_codec_ready(chip, 0)) - return ~0; - snd_ymfpci_writew(chip, YDSXGR_AC97CMDADR, YDSXG_AC97READCMD | reg); - if (snd_ymfpci_codec_ready(chip, 0)) - return ~0; - if (chip->device_id == PCI_DEVICE_ID_YAMAHA_744 && chip->rev < 2) { - int i; - for (i = 0; i < 600; i++) - snd_ymfpci_readw(chip, YDSXGR_PRISTATUSDATA); - } - return snd_ymfpci_readw(chip, YDSXGR_PRISTATUSDATA); -} - -/* - * Misc routines - */ - -static u32 snd_ymfpci_calc_delta(u32 rate) -{ - switch (rate) { - case 8000: return 0x02aaab00; - case 11025: return 0x03accd00; - case 16000: return 0x05555500; - case 22050: return 0x07599a00; - case 32000: return 0x0aaaab00; - case 44100: return 0x0eb33300; - default: return ((rate << 16) / 375) << 5; - } -} - -static u32 def_rate[8] = { - 100, 2000, 8000, 11025, 16000, 22050, 32000, 48000 -}; - -static u32 snd_ymfpci_calc_lpfK(u32 rate) -{ - u32 i; - static u32 val[8] = { - 0x00570000, 0x06AA0000, 0x18B20000, 0x20930000, - 0x2B9A0000, 0x35A10000, 0x3EAA0000, 0x40000000 - }; - - if (rate == 44100) - return 0x40000000; /* FIXME: What's the right value? */ - for (i = 0; i < 8; i++) - if (rate <= def_rate[i]) - return val[i]; - return val[0]; -} - -static u32 snd_ymfpci_calc_lpfQ(u32 rate) -{ - u32 i; - static u32 val[8] = { - 0x35280000, 0x34A70000, 0x32020000, 0x31770000, - 0x31390000, 0x31C90000, 0x33D00000, 0x40000000 - }; - - if (rate == 44100) - return 0x370A0000; - for (i = 0; i < 8; i++) - if (rate <= def_rate[i]) - return val[i]; - return val[0]; -} - -/* - * Hardware start management - */ - -static void snd_ymfpci_hw_start(struct snd_ymfpci *chip) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->start_count++ > 0) - goto __end; - snd_ymfpci_writel(chip, YDSXGR_MODE, - snd_ymfpci_readl(chip, YDSXGR_MODE) | 3); - chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT) & 1; - __end: - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_ymfpci_hw_stop(struct snd_ymfpci *chip) -{ - unsigned long flags; - long timeout = 1000; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (--chip->start_count > 0) - goto __end; - snd_ymfpci_writel(chip, YDSXGR_MODE, - snd_ymfpci_readl(chip, YDSXGR_MODE) & ~3); - while (timeout-- > 0) { - if ((snd_ymfpci_readl(chip, YDSXGR_STATUS) & 2) == 0) - break; - } - if (atomic_read(&chip->interrupt_sleep_count)) { - atomic_set(&chip->interrupt_sleep_count, 0); - wake_up(&chip->interrupt_sleep); - } - __end: - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -/* - * Playback voice management - */ - -static int voice_alloc(struct snd_ymfpci *chip, - enum snd_ymfpci_voice_type type, int pair, - struct snd_ymfpci_voice **rvoice) -{ - struct snd_ymfpci_voice *voice, *voice2; - int idx; - - *rvoice = NULL; - for (idx = 0; idx < YDSXG_PLAYBACK_VOICES; idx += pair ? 2 : 1) { - voice = &chip->voices[idx]; - voice2 = pair ? &chip->voices[idx+1] : NULL; - if (voice->use || (voice2 && voice2->use)) - continue; - voice->use = 1; - if (voice2) - voice2->use = 1; - switch (type) { - case YMFPCI_PCM: - voice->pcm = 1; - if (voice2) - voice2->pcm = 1; - break; - case YMFPCI_SYNTH: - voice->synth = 1; - break; - case YMFPCI_MIDI: - voice->midi = 1; - break; - } - snd_ymfpci_hw_start(chip); - if (voice2) - snd_ymfpci_hw_start(chip); - *rvoice = voice; - return 0; - } - return -ENOMEM; -} - -static int snd_ymfpci_voice_alloc(struct snd_ymfpci *chip, - enum snd_ymfpci_voice_type type, int pair, - struct snd_ymfpci_voice **rvoice) -{ - unsigned long flags; - int result; - - if (snd_BUG_ON(!rvoice)) - return -EINVAL; - if (snd_BUG_ON(pair && type != YMFPCI_PCM)) - return -EINVAL; - - spin_lock_irqsave(&chip->voice_lock, flags); - for (;;) { - result = voice_alloc(chip, type, pair, rvoice); - if (result == 0 || type != YMFPCI_PCM) - break; - /* TODO: synth/midi voice deallocation */ - break; - } - spin_unlock_irqrestore(&chip->voice_lock, flags); - return result; -} - -static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voice *pvoice) -{ - unsigned long flags; - - if (snd_BUG_ON(!pvoice)) - return -EINVAL; - snd_ymfpci_hw_stop(chip); - spin_lock_irqsave(&chip->voice_lock, flags); - if (pvoice->number == chip->src441_used) { - chip->src441_used = -1; - pvoice->ypcm->use_441_slot = 0; - } - pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; - pvoice->ypcm = NULL; - pvoice->interrupt = NULL; - spin_unlock_irqrestore(&chip->voice_lock, flags); - return 0; -} - -/* - * PCM part - */ - -static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_voice *voice) -{ - struct snd_ymfpci_pcm *ypcm; - u32 pos, delta; - - if ((ypcm = voice->ypcm) == NULL) - return; - if (ypcm->substream == NULL) - return; - spin_lock(&chip->reg_lock); - if (ypcm->running) { - pos = le32_to_cpu(voice->bank[chip->active_bank].start); - if (pos < ypcm->last_pos) - delta = pos + (ypcm->buffer_size - ypcm->last_pos); - else - delta = pos - ypcm->last_pos; - ypcm->period_pos += delta; - ypcm->last_pos = pos; - if (ypcm->period_pos >= ypcm->period_size) { - /* - printk(KERN_DEBUG - "done - active_bank = 0x%x, start = 0x%x\n", - chip->active_bank, - voice->bank[chip->active_bank].start); - */ - ypcm->period_pos %= ypcm->period_size; - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(ypcm->substream); - spin_lock(&chip->reg_lock); - } - - if (unlikely(ypcm->update_pcm_vol)) { - unsigned int subs = ypcm->substream->number; - unsigned int next_bank = 1 - chip->active_bank; - struct snd_ymfpci_playback_bank *bank; - u32 volume; - - bank = &voice->bank[next_bank]; - volume = cpu_to_le32(chip->pcm_mixer[subs].left << 15); - bank->left_gain_end = volume; - if (ypcm->output_rear) - bank->eff2_gain_end = volume; - if (ypcm->voices[1]) - bank = &ypcm->voices[1]->bank[next_bank]; - volume = cpu_to_le32(chip->pcm_mixer[subs].right << 15); - bank->right_gain_end = volume; - if (ypcm->output_rear) - bank->eff3_gain_end = volume; - ypcm->update_pcm_vol--; - } - } - spin_unlock(&chip->reg_lock); -} - -static void snd_ymfpci_pcm_capture_interrupt(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm = runtime->private_data; - struct snd_ymfpci *chip = ypcm->chip; - u32 pos, delta; - - spin_lock(&chip->reg_lock); - if (ypcm->running) { - pos = le32_to_cpu(chip->bank_capture[ypcm->capture_bank_number][chip->active_bank]->start) >> ypcm->shift; - if (pos < ypcm->last_pos) - delta = pos + (ypcm->buffer_size - ypcm->last_pos); - else - delta = pos - ypcm->last_pos; - ypcm->period_pos += delta; - ypcm->last_pos = pos; - if (ypcm->period_pos >= ypcm->period_size) { - ypcm->period_pos %= ypcm->period_size; - /* - printk(KERN_DEBUG - "done - active_bank = 0x%x, start = 0x%x\n", - chip->active_bank, - voice->bank[chip->active_bank].start); - */ - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(substream); - spin_lock(&chip->reg_lock); - } - } - spin_unlock(&chip->reg_lock); -} - -static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; - struct snd_kcontrol *kctl = NULL; - int result = 0; - - spin_lock(&chip->reg_lock); - if (ypcm->voices[0] == NULL) { - result = -EINVAL; - goto __unlock; - } - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - chip->ctrl_playback[ypcm->voices[0]->number + 1] = cpu_to_le32(ypcm->voices[0]->bank_addr); - if (ypcm->voices[1] != NULL && !ypcm->use_441_slot) - chip->ctrl_playback[ypcm->voices[1]->number + 1] = cpu_to_le32(ypcm->voices[1]->bank_addr); - ypcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - if (substream->pcm == chip->pcm && !ypcm->use_441_slot) { - kctl = chip->pcm_mixer[substream->number].ctl; - kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - } - /* fall through */ - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; - if (ypcm->voices[1] != NULL && !ypcm->use_441_slot) - chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0; - ypcm->running = 0; - break; - default: - result = -EINVAL; - break; - } - __unlock: - spin_unlock(&chip->reg_lock); - if (kctl) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); - return result; -} -static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; - int result = 0; - u32 tmp; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - tmp = snd_ymfpci_readl(chip, YDSXGR_MAPOFREC) | (1 << ypcm->capture_bank_number); - snd_ymfpci_writel(chip, YDSXGR_MAPOFREC, tmp); - ypcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - tmp = snd_ymfpci_readl(chip, YDSXGR_MAPOFREC) & ~(1 << ypcm->capture_bank_number); - snd_ymfpci_writel(chip, YDSXGR_MAPOFREC, tmp); - ypcm->running = 0; - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&chip->reg_lock); - return result; -} - -static int snd_ymfpci_pcm_voice_alloc(struct snd_ymfpci_pcm *ypcm, int voices) -{ - int err; - - if (ypcm->voices[1] != NULL && voices < 2) { - snd_ymfpci_voice_free(ypcm->chip, ypcm->voices[1]); - ypcm->voices[1] = NULL; - } - if (voices == 1 && ypcm->voices[0] != NULL) - return 0; /* already allocated */ - if (voices == 2 && ypcm->voices[0] != NULL && ypcm->voices[1] != NULL) - return 0; /* already allocated */ - if (voices > 1) { - if (ypcm->voices[0] != NULL && ypcm->voices[1] == NULL) { - snd_ymfpci_voice_free(ypcm->chip, ypcm->voices[0]); - ypcm->voices[0] = NULL; - } - } - err = snd_ymfpci_voice_alloc(ypcm->chip, YMFPCI_PCM, voices > 1, &ypcm->voices[0]); - if (err < 0) - return err; - ypcm->voices[0]->ypcm = ypcm; - ypcm->voices[0]->interrupt = snd_ymfpci_pcm_interrupt; - if (voices > 1) { - ypcm->voices[1] = &ypcm->chip->voices[ypcm->voices[0]->number + 1]; - ypcm->voices[1]->ypcm = ypcm; - } - return 0; -} - -static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int voiceidx, - struct snd_pcm_runtime *runtime, - int has_pcm_volume) -{ - struct snd_ymfpci_voice *voice = ypcm->voices[voiceidx]; - u32 format; - u32 delta = snd_ymfpci_calc_delta(runtime->rate); - u32 lpfQ = snd_ymfpci_calc_lpfQ(runtime->rate); - u32 lpfK = snd_ymfpci_calc_lpfK(runtime->rate); - struct snd_ymfpci_playback_bank *bank; - unsigned int nbank; - u32 vol_left, vol_right; - u8 use_left, use_right; - unsigned long flags; - - if (snd_BUG_ON(!voice)) - return; - if (runtime->channels == 1) { - use_left = 1; - use_right = 1; - } else { - use_left = (voiceidx & 1) == 0; - use_right = !use_left; - } - if (has_pcm_volume) { - vol_left = cpu_to_le32(ypcm->chip->pcm_mixer - [ypcm->substream->number].left << 15); - vol_right = cpu_to_le32(ypcm->chip->pcm_mixer - [ypcm->substream->number].right << 15); - } else { - vol_left = cpu_to_le32(0x40000000); - vol_right = cpu_to_le32(0x40000000); - } - spin_lock_irqsave(&ypcm->chip->voice_lock, flags); - format = runtime->channels == 2 ? 0x00010000 : 0; - if (snd_pcm_format_width(runtime->format) == 8) - format |= 0x80000000; - else if (ypcm->chip->device_id == PCI_DEVICE_ID_YAMAHA_754 && - runtime->rate == 44100 && runtime->channels == 2 && - voiceidx == 0 && (ypcm->chip->src441_used == -1 || - ypcm->chip->src441_used == voice->number)) { - ypcm->chip->src441_used = voice->number; - ypcm->use_441_slot = 1; - format |= 0x10000000; - } - if (ypcm->chip->src441_used == voice->number && - (format & 0x10000000) == 0) { - ypcm->chip->src441_used = -1; - ypcm->use_441_slot = 0; - } - if (runtime->channels == 2 && (voiceidx & 1) != 0) - format |= 1; - spin_unlock_irqrestore(&ypcm->chip->voice_lock, flags); - for (nbank = 0; nbank < 2; nbank++) { - bank = &voice->bank[nbank]; - memset(bank, 0, sizeof(*bank)); - bank->format = cpu_to_le32(format); - bank->base = cpu_to_le32(runtime->dma_addr); - bank->loop_end = cpu_to_le32(ypcm->buffer_size); - bank->lpfQ = cpu_to_le32(lpfQ); - bank->delta = - bank->delta_end = cpu_to_le32(delta); - bank->lpfK = - bank->lpfK_end = cpu_to_le32(lpfK); - bank->eg_gain = - bank->eg_gain_end = cpu_to_le32(0x40000000); - - if (ypcm->output_front) { - if (use_left) { - bank->left_gain = - bank->left_gain_end = vol_left; - } - if (use_right) { - bank->right_gain = - bank->right_gain_end = vol_right; - } - } - if (ypcm->output_rear) { - if (!ypcm->swap_rear) { - if (use_left) { - bank->eff2_gain = - bank->eff2_gain_end = vol_left; - } - if (use_right) { - bank->eff3_gain = - bank->eff3_gain_end = vol_right; - } - } else { - /* The SPDIF out channels seem to be swapped, so we have - * to swap them here, too. The rear analog out channels - * will be wrong, but otherwise AC3 would not work. - */ - if (use_left) { - bank->eff3_gain = - bank->eff3_gain_end = vol_left; - } - if (use_right) { - bank->eff2_gain = - bank->eff2_gain_end = vol_right; - } - } - } - } -} - -static int __devinit snd_ymfpci_ac3_init(struct snd_ymfpci *chip) -{ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - 4096, &chip->ac3_tmp_base) < 0) - return -ENOMEM; - - chip->bank_effect[3][0]->base = - chip->bank_effect[3][1]->base = cpu_to_le32(chip->ac3_tmp_base.addr); - chip->bank_effect[3][0]->loop_end = - chip->bank_effect[3][1]->loop_end = cpu_to_le32(1024); - chip->bank_effect[4][0]->base = - chip->bank_effect[4][1]->base = cpu_to_le32(chip->ac3_tmp_base.addr + 2048); - chip->bank_effect[4][0]->loop_end = - chip->bank_effect[4][1]->loop_end = cpu_to_le32(1024); - - spin_lock_irq(&chip->reg_lock); - snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT, - snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) | 3 << 3); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_ymfpci_ac3_done(struct snd_ymfpci *chip) -{ - spin_lock_irq(&chip->reg_lock); - snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT, - snd_ymfpci_readl(chip, YDSXGR_MAPOFEFFECT) & ~(3 << 3)); - spin_unlock_irq(&chip->reg_lock); - // snd_ymfpci_irq_wait(chip); - if (chip->ac3_tmp_base.area) { - snd_dma_free_pages(&chip->ac3_tmp_base); - chip->ac3_tmp_base.area = NULL; - } - return 0; -} - -static int snd_ymfpci_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm = runtime->private_data; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - if ((err = snd_ymfpci_pcm_voice_alloc(ypcm, params_channels(hw_params))) < 0) - return err; - return 0; -} - -static int snd_ymfpci_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm; - - if (runtime->private_data == NULL) - return 0; - ypcm = runtime->private_data; - - /* wait, until the PCI operations are not finished */ - snd_ymfpci_irq_wait(chip); - snd_pcm_lib_free_pages(substream); - if (ypcm->voices[1]) { - snd_ymfpci_voice_free(chip, ypcm->voices[1]); - ypcm->voices[1] = NULL; - } - if (ypcm->voices[0]) { - snd_ymfpci_voice_free(chip, ypcm->voices[0]); - ypcm->voices[0] = NULL; - } - return 0; -} - -static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm = runtime->private_data; - struct snd_kcontrol *kctl; - unsigned int nvoice; - - ypcm->period_size = runtime->period_size; - ypcm->buffer_size = runtime->buffer_size; - ypcm->period_pos = 0; - ypcm->last_pos = 0; - for (nvoice = 0; nvoice < runtime->channels; nvoice++) - snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime, - substream->pcm == chip->pcm); - - if (substream->pcm == chip->pcm && !ypcm->use_441_slot) { - kctl = chip->pcm_mixer[substream->number].ctl; - kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id); - } - return 0; -} - -static int snd_ymfpci_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_ymfpci_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - - /* wait, until the PCI operations are not finished */ - snd_ymfpci_irq_wait(chip); - return snd_pcm_lib_free_pages(substream); -} - -static int snd_ymfpci_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm = runtime->private_data; - struct snd_ymfpci_capture_bank * bank; - int nbank; - u32 rate, format; - - ypcm->period_size = runtime->period_size; - ypcm->buffer_size = runtime->buffer_size; - ypcm->period_pos = 0; - ypcm->last_pos = 0; - ypcm->shift = 0; - rate = ((48000 * 4096) / runtime->rate) - 1; - format = 0; - if (runtime->channels == 2) { - format |= 2; - ypcm->shift++; - } - if (snd_pcm_format_width(runtime->format) == 8) - format |= 1; - else - ypcm->shift++; - switch (ypcm->capture_bank_number) { - case 0: - snd_ymfpci_writel(chip, YDSXGR_RECFORMAT, format); - snd_ymfpci_writel(chip, YDSXGR_RECSLOTSR, rate); - break; - case 1: - snd_ymfpci_writel(chip, YDSXGR_ADCFORMAT, format); - snd_ymfpci_writel(chip, YDSXGR_ADCSLOTSR, rate); - break; - } - for (nbank = 0; nbank < 2; nbank++) { - bank = chip->bank_capture[ypcm->capture_bank_number][nbank]; - bank->base = cpu_to_le32(runtime->dma_addr); - bank->loop_end = cpu_to_le32(ypcm->buffer_size << ypcm->shift); - bank->start = 0; - bank->num_of_loops = 0; - } - return 0; -} - -static snd_pcm_uframes_t snd_ymfpci_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm = runtime->private_data; - struct snd_ymfpci_voice *voice = ypcm->voices[0]; - - if (!(ypcm->running && voice)) - return 0; - return le32_to_cpu(voice->bank[chip->active_bank].start); -} - -static snd_pcm_uframes_t snd_ymfpci_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm = runtime->private_data; - - if (!ypcm->running) - return 0; - return le32_to_cpu(chip->bank_capture[ypcm->capture_bank_number][chip->active_bank]->start) >> ypcm->shift; -} - -static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip) -{ - wait_queue_t wait; - int loops = 4; - - while (loops-- > 0) { - if ((snd_ymfpci_readl(chip, YDSXGR_MODE) & 3) == 0) - continue; - init_waitqueue_entry(&wait, current); - add_wait_queue(&chip->interrupt_sleep, &wait); - atomic_inc(&chip->interrupt_sleep_count); - schedule_timeout_uninterruptible(msecs_to_jiffies(50)); - remove_wait_queue(&chip->interrupt_sleep, &wait); - } -} - -static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id) -{ - struct snd_ymfpci *chip = dev_id; - u32 status, nvoice, mode; - struct snd_ymfpci_voice *voice; - - status = snd_ymfpci_readl(chip, YDSXGR_STATUS); - if (status & 0x80000000) { - chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT) & 1; - spin_lock(&chip->voice_lock); - for (nvoice = 0; nvoice < YDSXG_PLAYBACK_VOICES; nvoice++) { - voice = &chip->voices[nvoice]; - if (voice->interrupt) - voice->interrupt(chip, voice); - } - for (nvoice = 0; nvoice < YDSXG_CAPTURE_VOICES; nvoice++) { - if (chip->capture_substream[nvoice]) - snd_ymfpci_pcm_capture_interrupt(chip->capture_substream[nvoice]); - } -#if 0 - for (nvoice = 0; nvoice < YDSXG_EFFECT_VOICES; nvoice++) { - if (chip->effect_substream[nvoice]) - snd_ymfpci_pcm_effect_interrupt(chip->effect_substream[nvoice]); - } -#endif - spin_unlock(&chip->voice_lock); - spin_lock(&chip->reg_lock); - snd_ymfpci_writel(chip, YDSXGR_STATUS, 0x80000000); - mode = snd_ymfpci_readl(chip, YDSXGR_MODE) | 2; - snd_ymfpci_writel(chip, YDSXGR_MODE, mode); - spin_unlock(&chip->reg_lock); - - if (atomic_read(&chip->interrupt_sleep_count)) { - atomic_set(&chip->interrupt_sleep_count, 0); - wake_up(&chip->interrupt_sleep); - } - } - - status = snd_ymfpci_readw(chip, YDSXGR_INTFLAG); - if (status & 1) { - if (chip->timer) - snd_timer_interrupt(chip->timer, chip->timer_ticks); - } - snd_ymfpci_writew(chip, YDSXGR_INTFLAG, status); - - if (chip->rawmidi) - snd_mpu401_uart_interrupt(irq, chip->rawmidi->private_data); - return IRQ_HANDLED; -} - -static struct snd_pcm_hardware snd_ymfpci_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 256 * 1024, /* FIXME: enough? */ - .period_bytes_min = 64, - .period_bytes_max = 256 * 1024, /* FIXME: enough? */ - .periods_min = 3, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_ymfpci_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 256 * 1024, /* FIXME: enough? */ - .period_bytes_min = 64, - .period_bytes_max = 256 * 1024, /* FIXME: enough? */ - .periods_min = 3, - .periods_max = 1024, - .fifo_size = 0, -}; - -static void snd_ymfpci_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static int snd_ymfpci_playback_open_1(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm; - int err; - - runtime->hw = snd_ymfpci_playback; - /* FIXME? True value is 256/48 = 5.33333 ms */ - err = snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_TIME, - 5334, UINT_MAX); - if (err < 0) - return err; - err = snd_pcm_hw_rule_noresample(runtime, 48000); - if (err < 0) - return err; - - ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL); - if (ypcm == NULL) - return -ENOMEM; - ypcm->chip = chip; - ypcm->type = PLAYBACK_VOICE; - ypcm->substream = substream; - runtime->private_data = ypcm; - runtime->private_free = snd_ymfpci_pcm_free_substream; - return 0; -} - -/* call with spinlock held */ -static void ymfpci_open_extension(struct snd_ymfpci *chip) -{ - if (! chip->rear_opened) { - if (! chip->spdif_opened) /* set AC3 */ - snd_ymfpci_writel(chip, YDSXGR_MODE, - snd_ymfpci_readl(chip, YDSXGR_MODE) | (1 << 30)); - /* enable second codec (4CHEN) */ - snd_ymfpci_writew(chip, YDSXGR_SECCONFIG, - (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0330) | 0x0010); - } -} - -/* call with spinlock held */ -static void ymfpci_close_extension(struct snd_ymfpci *chip) -{ - if (! chip->rear_opened) { - if (! chip->spdif_opened) - snd_ymfpci_writel(chip, YDSXGR_MODE, - snd_ymfpci_readl(chip, YDSXGR_MODE) & ~(1 << 30)); - snd_ymfpci_writew(chip, YDSXGR_SECCONFIG, - (snd_ymfpci_readw(chip, YDSXGR_SECCONFIG) & ~0x0330) & ~0x0010); - } -} - -static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm; - int err; - - if ((err = snd_ymfpci_playback_open_1(substream)) < 0) - return err; - ypcm = runtime->private_data; - ypcm->output_front = 1; - ypcm->output_rear = chip->mode_dup4ch ? 1 : 0; - ypcm->swap_rear = 0; - spin_lock_irq(&chip->reg_lock); - if (ypcm->output_rear) { - ymfpci_open_extension(chip); - chip->rear_opened++; - } - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_ymfpci_playback_spdif_open(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm; - int err; - - if ((err = snd_ymfpci_playback_open_1(substream)) < 0) - return err; - ypcm = runtime->private_data; - ypcm->output_front = 0; - ypcm->output_rear = 1; - ypcm->swap_rear = 1; - spin_lock_irq(&chip->reg_lock); - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL, - snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2); - ymfpci_open_extension(chip); - chip->spdif_pcm_bits = chip->spdif_bits; - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits); - chip->spdif_opened++; - spin_unlock_irq(&chip->reg_lock); - - chip->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id); - return 0; -} - -static int snd_ymfpci_playback_4ch_open(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm; - int err; - - if ((err = snd_ymfpci_playback_open_1(substream)) < 0) - return err; - ypcm = runtime->private_data; - ypcm->output_front = 0; - ypcm->output_rear = 1; - ypcm->swap_rear = 0; - spin_lock_irq(&chip->reg_lock); - ymfpci_open_extension(chip); - chip->rear_opened++; - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_ymfpci_capture_open(struct snd_pcm_substream *substream, - u32 capture_bank_number) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm; - int err; - - runtime->hw = snd_ymfpci_capture; - /* FIXME? True value is 256/48 = 5.33333 ms */ - err = snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_PERIOD_TIME, - 5334, UINT_MAX); - if (err < 0) - return err; - err = snd_pcm_hw_rule_noresample(runtime, 48000); - if (err < 0) - return err; - - ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL); - if (ypcm == NULL) - return -ENOMEM; - ypcm->chip = chip; - ypcm->type = capture_bank_number + CAPTURE_REC; - ypcm->substream = substream; - ypcm->capture_bank_number = capture_bank_number; - chip->capture_substream[capture_bank_number] = substream; - runtime->private_data = ypcm; - runtime->private_free = snd_ymfpci_pcm_free_substream; - snd_ymfpci_hw_start(chip); - return 0; -} - -static int snd_ymfpci_capture_rec_open(struct snd_pcm_substream *substream) -{ - return snd_ymfpci_capture_open(substream, 0); -} - -static int snd_ymfpci_capture_ac97_open(struct snd_pcm_substream *substream) -{ - return snd_ymfpci_capture_open(substream, 1); -} - -static int snd_ymfpci_playback_close_1(struct snd_pcm_substream *substream) -{ - return 0; -} - -static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; - - spin_lock_irq(&chip->reg_lock); - if (ypcm->output_rear && chip->rear_opened > 0) { - chip->rear_opened--; - ymfpci_close_extension(chip); - } - spin_unlock_irq(&chip->reg_lock); - return snd_ymfpci_playback_close_1(substream); -} - -static int snd_ymfpci_playback_spdif_close(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - chip->spdif_opened = 0; - ymfpci_close_extension(chip); - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL, - snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & ~2); - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits); - spin_unlock_irq(&chip->reg_lock); - chip->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id); - return snd_ymfpci_playback_close_1(substream); -} - -static int snd_ymfpci_playback_4ch_close(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - if (chip->rear_opened > 0) { - chip->rear_opened--; - ymfpci_close_extension(chip); - } - spin_unlock_irq(&chip->reg_lock); - return snd_ymfpci_playback_close_1(substream); -} - -static int snd_ymfpci_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ymfpci_pcm *ypcm = runtime->private_data; - - if (ypcm != NULL) { - chip->capture_substream[ypcm->capture_bank_number] = NULL; - snd_ymfpci_hw_stop(chip); - } - return 0; -} - -static struct snd_pcm_ops snd_ymfpci_playback_ops = { - .open = snd_ymfpci_playback_open, - .close = snd_ymfpci_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ymfpci_playback_hw_params, - .hw_free = snd_ymfpci_playback_hw_free, - .prepare = snd_ymfpci_playback_prepare, - .trigger = snd_ymfpci_playback_trigger, - .pointer = snd_ymfpci_playback_pointer, -}; - -static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = { - .open = snd_ymfpci_capture_rec_open, - .close = snd_ymfpci_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ymfpci_capture_hw_params, - .hw_free = snd_ymfpci_capture_hw_free, - .prepare = snd_ymfpci_capture_prepare, - .trigger = snd_ymfpci_capture_trigger, - .pointer = snd_ymfpci_capture_pointer, -}; - -int __devinit snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(chip->card, "YMFPCI", device, 32, 1, &pcm)) < 0) - return err; - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ymfpci_capture_rec_ops); - - /* global setup */ - pcm->info_flags = 0; - strcpy(pcm->name, "YMFPCI"); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 256*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = { - .open = snd_ymfpci_capture_ac97_open, - .close = snd_ymfpci_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ymfpci_capture_hw_params, - .hw_free = snd_ymfpci_capture_hw_free, - .prepare = snd_ymfpci_capture_prepare, - .trigger = snd_ymfpci_capture_trigger, - .pointer = snd_ymfpci_capture_pointer, -}; - -int __devinit snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(chip->card, "YMFPCI - PCM2", device, 0, 1, &pcm)) < 0) - return err; - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ymfpci_capture_ac97_ops); - - /* global setup */ - pcm->info_flags = 0; - sprintf(pcm->name, "YMFPCI - %s", - chip->device_id == PCI_DEVICE_ID_YAMAHA_754 ? "Direct Recording" : "AC'97"); - chip->pcm2 = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 256*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = { - .open = snd_ymfpci_playback_spdif_open, - .close = snd_ymfpci_playback_spdif_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ymfpci_playback_hw_params, - .hw_free = snd_ymfpci_playback_hw_free, - .prepare = snd_ymfpci_playback_prepare, - .trigger = snd_ymfpci_playback_trigger, - .pointer = snd_ymfpci_playback_pointer, -}; - -int __devinit snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(chip->card, "YMFPCI - IEC958", device, 1, 0, &pcm)) < 0) - return err; - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_spdif_ops); - - /* global setup */ - pcm->info_flags = 0; - strcpy(pcm->name, "YMFPCI - IEC958"); - chip->pcm_spdif = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 256*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -static struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = { - .open = snd_ymfpci_playback_4ch_open, - .close = snd_ymfpci_playback_4ch_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ymfpci_playback_hw_params, - .hw_free = snd_ymfpci_playback_hw_free, - .prepare = snd_ymfpci_playback_prepare, - .trigger = snd_ymfpci_playback_trigger, - .pointer = snd_ymfpci_playback_pointer, -}; - -int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(chip->card, "YMFPCI - Rear", device, 1, 0, &pcm)) < 0) - return err; - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_4ch_ops); - - /* global setup */ - pcm->info_flags = 0; - strcpy(pcm->name, "YMFPCI - Rear PCM"); - chip->pcm_4ch = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), 64*1024, 256*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -static int snd_ymfpci_spdif_default_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ymfpci_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&chip->reg_lock); - ucontrol->value.iec958.status[0] = (chip->spdif_bits >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (chip->spdif_bits >> 8) & 0xff; - ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_ymfpci_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) | - (ucontrol->value.iec958.status[1] << 8); - spin_lock_irq(&chip->reg_lock); - change = chip->spdif_bits != val; - chip->spdif_bits = val; - if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 1) && chip->pcm_spdif == NULL) - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits); - spin_unlock_irq(&chip->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_ymfpci_spdif_default __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .info = snd_ymfpci_spdif_default_info, - .get = snd_ymfpci_spdif_default_get, - .put = snd_ymfpci_spdif_default_put -}; - -static int snd_ymfpci_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ymfpci_spdif_mask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&chip->reg_lock); - ucontrol->value.iec958.status[0] = 0x3e; - ucontrol->value.iec958.status[1] = 0xff; - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static struct snd_kcontrol_new snd_ymfpci_spdif_mask __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), - .info = snd_ymfpci_spdif_mask_info, - .get = snd_ymfpci_spdif_mask_get, -}; - -static int snd_ymfpci_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_ymfpci_spdif_stream_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - - spin_lock_irq(&chip->reg_lock); - ucontrol->value.iec958.status[0] = (chip->spdif_pcm_bits >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (chip->spdif_pcm_bits >> 8) & 0xff; - ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int snd_ymfpci_spdif_stream_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change; - - val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) | - (ucontrol->value.iec958.status[1] << 8); - spin_lock_irq(&chip->reg_lock); - change = chip->spdif_pcm_bits != val; - chip->spdif_pcm_bits = val; - if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 2)) - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits); - spin_unlock_irq(&chip->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_ymfpci_spdif_stream __devinitdata = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), - .info = snd_ymfpci_spdif_stream_info, - .get = snd_ymfpci_spdif_stream_get, - .put = snd_ymfpci_spdif_stream_put -}; - -static int snd_ymfpci_drec_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *info) -{ - static const char *const texts[3] = {"AC'97", "IEC958", "ZV Port"}; - - return snd_ctl_enum_info(info, 1, 3, texts); -} - -static int snd_ymfpci_drec_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *value) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - u16 reg; - - spin_lock_irq(&chip->reg_lock); - reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL); - spin_unlock_irq(&chip->reg_lock); - if (!(reg & 0x100)) - value->value.enumerated.item[0] = 0; - else - value->value.enumerated.item[0] = 1 + ((reg & 0x200) != 0); - return 0; -} - -static int snd_ymfpci_drec_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *value) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - u16 reg, old_reg; - - spin_lock_irq(&chip->reg_lock); - old_reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL); - if (value->value.enumerated.item[0] == 0) - reg = old_reg & ~0x100; - else - reg = (old_reg & ~0x300) | 0x100 | ((value->value.enumerated.item[0] == 2) << 9); - snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, reg); - spin_unlock_irq(&chip->reg_lock); - return reg != old_reg; -} - -static struct snd_kcontrol_new snd_ymfpci_drec_source __devinitdata = { - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Direct Recording Source", - .info = snd_ymfpci_drec_source_info, - .get = snd_ymfpci_drec_source_get, - .put = snd_ymfpci_drec_source_put -}; - -/* - * Mixer controls - */ - -#define YMFPCI_SINGLE(xname, xindex, reg, shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_ymfpci_info_single, \ - .get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \ - .private_value = ((reg) | ((shift) << 16)) } - -#define snd_ymfpci_info_single snd_ctl_boolean_mono_info - -static int snd_ymfpci_get_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xffff; - unsigned int shift = (kcontrol->private_value >> 16) & 0xff; - unsigned int mask = 1; - - switch (reg) { - case YDSXGR_SPDIFOUTCTRL: break; - case YDSXGR_SPDIFINCTRL: break; - default: return -EINVAL; - } - ucontrol->value.integer.value[0] = - (snd_ymfpci_readl(chip, reg) >> shift) & mask; - return 0; -} - -static int snd_ymfpci_put_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xffff; - unsigned int shift = (kcontrol->private_value >> 16) & 0xff; - unsigned int mask = 1; - int change; - unsigned int val, oval; - - switch (reg) { - case YDSXGR_SPDIFOUTCTRL: break; - case YDSXGR_SPDIFINCTRL: break; - default: return -EINVAL; - } - val = (ucontrol->value.integer.value[0] & mask); - val <<= shift; - spin_lock_irq(&chip->reg_lock); - oval = snd_ymfpci_readl(chip, reg); - val = (oval & ~(mask << shift)) | val; - change = val != oval; - snd_ymfpci_writel(chip, reg, val); - spin_unlock_irq(&chip->reg_lock); - return change; -} - -static const DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0); - -#define YMFPCI_DOUBLE(xname, xindex, reg) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_ymfpci_info_double, \ - .get = snd_ymfpci_get_double, .put = snd_ymfpci_put_double, \ - .private_value = reg, \ - .tlv = { .p = db_scale_native } } - -static int snd_ymfpci_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - unsigned int reg = kcontrol->private_value; - - if (reg < 0x80 || reg >= 0xc0) - return -EINVAL; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 16383; - return 0; -} - -static int snd_ymfpci_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - unsigned int reg = kcontrol->private_value; - unsigned int shift_left = 0, shift_right = 16, mask = 16383; - unsigned int val; - - if (reg < 0x80 || reg >= 0xc0) - return -EINVAL; - spin_lock_irq(&chip->reg_lock); - val = snd_ymfpci_readl(chip, reg); - spin_unlock_irq(&chip->reg_lock); - ucontrol->value.integer.value[0] = (val >> shift_left) & mask; - ucontrol->value.integer.value[1] = (val >> shift_right) & mask; - return 0; -} - -static int snd_ymfpci_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - unsigned int reg = kcontrol->private_value; - unsigned int shift_left = 0, shift_right = 16, mask = 16383; - int change; - unsigned int val1, val2, oval; - - if (reg < 0x80 || reg >= 0xc0) - return -EINVAL; - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irq(&chip->reg_lock); - oval = snd_ymfpci_readl(chip, reg); - val1 = (oval & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != oval; - snd_ymfpci_writel(chip, reg, val1); - spin_unlock_irq(&chip->reg_lock); - return change; -} - -static int snd_ymfpci_put_nativedacvol(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - unsigned int reg = YDSXGR_NATIVEDACOUTVOL; - unsigned int reg2 = YDSXGR_BUF441OUTVOL; - int change; - unsigned int value, oval; - - value = ucontrol->value.integer.value[0] & 0x3fff; - value |= (ucontrol->value.integer.value[1] & 0x3fff) << 16; - spin_lock_irq(&chip->reg_lock); - oval = snd_ymfpci_readl(chip, reg); - change = value != oval; - snd_ymfpci_writel(chip, reg, value); - snd_ymfpci_writel(chip, reg2, value); - spin_unlock_irq(&chip->reg_lock); - return change; -} - -/* - * 4ch duplication - */ -#define snd_ymfpci_info_dup4ch snd_ctl_boolean_mono_info - -static int snd_ymfpci_get_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->mode_dup4ch; - return 0; -} - -static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - int change; - change = (ucontrol->value.integer.value[0] != chip->mode_dup4ch); - if (change) - chip->mode_dup4ch = !!ucontrol->value.integer.value[0]; - return change; -} - -static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "4ch Duplication", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = snd_ymfpci_info_dup4ch, - .get = snd_ymfpci_get_dup4ch, - .put = snd_ymfpci_put_dup4ch, -}; - -static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Wave Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = snd_ymfpci_info_double, - .get = snd_ymfpci_get_double, - .put = snd_ymfpci_put_nativedacvol, - .private_value = YDSXGR_NATIVEDACOUTVOL, - .tlv = { .p = db_scale_native }, -}, -YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL), -YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL), -YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL), -YMFPCI_DOUBLE("ADC Playback Volume", 0, YDSXGR_PRIADCOUTVOL), -YMFPCI_DOUBLE("ADC Capture Volume", 0, YDSXGR_PRIADCLOOPVOL), -YMFPCI_DOUBLE("ADC Playback Volume", 1, YDSXGR_SECADCOUTVOL), -YMFPCI_DOUBLE("ADC Capture Volume", 1, YDSXGR_SECADCLOOPVOL), -YMFPCI_DOUBLE("FM Legacy Playback Volume", 0, YDSXGR_LEGACYOUTVOL), -YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ", PLAYBACK,VOLUME), 0, YDSXGR_ZVOUTVOL), -YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("", CAPTURE,VOLUME), 0, YDSXGR_ZVLOOPVOL), -YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ",PLAYBACK,VOLUME), 1, YDSXGR_SPDIFOUTVOL), -YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,VOLUME), 1, YDSXGR_SPDIFLOOPVOL), -YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL, 0), -YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL, 0), -YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4), -}; - - -/* - * GPIO - */ - -static int snd_ymfpci_get_gpio_out(struct snd_ymfpci *chip, int pin) -{ - u16 reg, mode; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - reg = snd_ymfpci_readw(chip, YDSXGR_GPIOFUNCENABLE); - reg &= ~(1 << (pin + 8)); - reg |= (1 << pin); - snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg); - /* set the level mode for input line */ - mode = snd_ymfpci_readw(chip, YDSXGR_GPIOTYPECONFIG); - mode &= ~(3 << (pin * 2)); - snd_ymfpci_writew(chip, YDSXGR_GPIOTYPECONFIG, mode); - snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg | (1 << (pin + 8))); - mode = snd_ymfpci_readw(chip, YDSXGR_GPIOINSTATUS); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return (mode >> pin) & 1; -} - -static int snd_ymfpci_set_gpio_out(struct snd_ymfpci *chip, int pin, int enable) -{ - u16 reg; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - reg = snd_ymfpci_readw(chip, YDSXGR_GPIOFUNCENABLE); - reg &= ~(1 << pin); - reg &= ~(1 << (pin + 8)); - snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg); - snd_ymfpci_writew(chip, YDSXGR_GPIOOUTCTRL, enable << pin); - snd_ymfpci_writew(chip, YDSXGR_GPIOFUNCENABLE, reg | (1 << (pin + 8))); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return 0; -} - -#define snd_ymfpci_gpio_sw_info snd_ctl_boolean_mono_info - -static int snd_ymfpci_gpio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - int pin = (int)kcontrol->private_value; - ucontrol->value.integer.value[0] = snd_ymfpci_get_gpio_out(chip, pin); - return 0; -} - -static int snd_ymfpci_gpio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - int pin = (int)kcontrol->private_value; - - if (snd_ymfpci_get_gpio_out(chip, pin) != ucontrol->value.integer.value[0]) { - snd_ymfpci_set_gpio_out(chip, pin, !!ucontrol->value.integer.value[0]); - ucontrol->value.integer.value[0] = snd_ymfpci_get_gpio_out(chip, pin); - return 1; - } - return 0; -} - -static struct snd_kcontrol_new snd_ymfpci_rear_shared __devinitdata = { - .name = "Shared Rear/Line-In Switch", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_ymfpci_gpio_sw_info, - .get = snd_ymfpci_gpio_sw_get, - .put = snd_ymfpci_gpio_sw_put, - .private_value = 2, -}; - -/* - * PCM voice volume - */ - -static int snd_ymfpci_pcm_vol_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0x8000; - return 0; -} - -static int snd_ymfpci_pcm_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - unsigned int subs = kcontrol->id.subdevice; - - ucontrol->value.integer.value[0] = chip->pcm_mixer[subs].left; - ucontrol->value.integer.value[1] = chip->pcm_mixer[subs].right; - return 0; -} - -static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol); - unsigned int subs = kcontrol->id.subdevice; - struct snd_pcm_substream *substream; - unsigned long flags; - - if (ucontrol->value.integer.value[0] != chip->pcm_mixer[subs].left || - ucontrol->value.integer.value[1] != chip->pcm_mixer[subs].right) { - chip->pcm_mixer[subs].left = ucontrol->value.integer.value[0]; - chip->pcm_mixer[subs].right = ucontrol->value.integer.value[1]; - if (chip->pcm_mixer[subs].left > 0x8000) - chip->pcm_mixer[subs].left = 0x8000; - if (chip->pcm_mixer[subs].right > 0x8000) - chip->pcm_mixer[subs].right = 0x8000; - - substream = (struct snd_pcm_substream *)kcontrol->private_value; - spin_lock_irqsave(&chip->voice_lock, flags); - if (substream->runtime && substream->runtime->private_data) { - struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; - if (!ypcm->use_441_slot) - ypcm->update_pcm_vol = 2; - } - spin_unlock_irqrestore(&chip->voice_lock, flags); - return 1; - } - return 0; -} - -static struct snd_kcontrol_new snd_ymfpci_pcm_volume __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "PCM Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .info = snd_ymfpci_pcm_vol_info, - .get = snd_ymfpci_pcm_vol_get, - .put = snd_ymfpci_pcm_vol_put, -}; - - -/* - * Mixer routines - */ - -static void snd_ymfpci_mixer_free_ac97_bus(struct snd_ac97_bus *bus) -{ - struct snd_ymfpci *chip = bus->private_data; - chip->ac97_bus = NULL; -} - -static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct snd_ymfpci *chip = ac97->private_data; - chip->ac97 = NULL; -} - -int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) -{ - struct snd_ac97_template ac97; - struct snd_kcontrol *kctl; - struct snd_pcm_substream *substream; - unsigned int idx; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_ymfpci_codec_write, - .read = snd_ymfpci_codec_read, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) - return err; - chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus; - chip->ac97_bus->no_vra = 1; /* YMFPCI doesn't need VRA */ - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.private_free = snd_ymfpci_mixer_free_ac97; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) - return err; - - /* to be sure */ - snd_ac97_update_bits(chip->ac97, AC97_EXTENDED_STATUS, - AC97_EA_VRA|AC97_EA_VRM, 0); - - for (idx = 0; idx < ARRAY_SIZE(snd_ymfpci_controls); idx++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0) - return err; - } - if (chip->ac97->ext_id & AC97_EI_SDAC) { - kctl = snd_ctl_new1(&snd_ymfpci_dup4ch, chip); - err = snd_ctl_add(chip->card, kctl); - if (err < 0) - return err; - } - - /* add S/PDIF control */ - if (snd_BUG_ON(!chip->pcm_spdif)) - return -ENXIO; - if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_default, chip))) < 0) - return err; - kctl->id.device = chip->pcm_spdif->device; - if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_mask, chip))) < 0) - return err; - kctl->id.device = chip->pcm_spdif->device; - if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_stream, chip))) < 0) - return err; - kctl->id.device = chip->pcm_spdif->device; - chip->spdif_pcm_ctl = kctl; - - /* direct recording source */ - if (chip->device_id == PCI_DEVICE_ID_YAMAHA_754 && - (err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_drec_source, chip))) < 0) - return err; - - /* - * shared rear/line-in - */ - if (rear_switch) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_rear_shared, chip))) < 0) - return err; - } - - /* per-voice volume */ - substream = chip->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - for (idx = 0; idx < 32; ++idx) { - kctl = snd_ctl_new1(&snd_ymfpci_pcm_volume, chip); - if (!kctl) - return -ENOMEM; - kctl->id.device = chip->pcm->device; - kctl->id.subdevice = idx; - kctl->private_value = (unsigned long)substream; - if ((err = snd_ctl_add(chip->card, kctl)) < 0) - return err; - chip->pcm_mixer[idx].left = 0x8000; - chip->pcm_mixer[idx].right = 0x8000; - chip->pcm_mixer[idx].ctl = kctl; - substream = substream->next; - } - - return 0; -} - - -/* - * timer - */ - -static int snd_ymfpci_timer_start(struct snd_timer *timer) -{ - struct snd_ymfpci *chip; - unsigned long flags; - unsigned int count; - - chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); - if (timer->sticks > 1) { - chip->timer_ticks = timer->sticks; - count = timer->sticks - 1; - } else { - /* - * Divisor 1 is not allowed; fake it by using divisor 2 and - * counting two ticks for each interrupt. - */ - chip->timer_ticks = 2; - count = 2 - 1; - } - snd_ymfpci_writew(chip, YDSXGR_TIMERCOUNT, count); - snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x03); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_ymfpci_timer_stop(struct snd_timer *timer) -{ - struct snd_ymfpci *chip; - unsigned long flags; - - chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x00); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_ymfpci_timer_precise_resolution(struct snd_timer *timer, - unsigned long *num, unsigned long *den) -{ - *num = 1; - *den = 96000; - return 0; -} - -static struct snd_timer_hardware snd_ymfpci_timer_hw = { - .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 10417, /* 1 / 96 kHz = 10.41666...us */ - .ticks = 0x10000, - .start = snd_ymfpci_timer_start, - .stop = snd_ymfpci_timer_stop, - .precise_resolution = snd_ymfpci_timer_precise_resolution, -}; - -int __devinit snd_ymfpci_timer(struct snd_ymfpci *chip, int device) -{ - struct snd_timer *timer = NULL; - struct snd_timer_id tid; - int err; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = chip->card->number; - tid.device = device; - tid.subdevice = 0; - if ((err = snd_timer_new(chip->card, "YMFPCI", &tid, &timer)) >= 0) { - strcpy(timer->name, "YMFPCI timer"); - timer->private_data = chip; - timer->hw = snd_ymfpci_timer_hw; - } - chip->timer = timer; - return err; -} - - -/* - * proc interface - */ - -static void snd_ymfpci_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_ymfpci *chip = entry->private_data; - int i; - - snd_iprintf(buffer, "YMFPCI\n\n"); - for (i = 0; i <= YDSXGR_WORKBASE; i += 4) - snd_iprintf(buffer, "%04x: %04x\n", i, snd_ymfpci_readl(chip, i)); -} - -static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(card, "ymfpci", &entry)) - snd_info_set_text_ops(entry, chip, snd_ymfpci_proc_read); - return 0; -} - -/* - * initialization routines - */ - -static void snd_ymfpci_aclink_reset(struct pci_dev * pci) -{ - u8 cmd; - - pci_read_config_byte(pci, PCIR_DSXG_CTRL, &cmd); -#if 0 // force to reset - if (cmd & 0x03) { -#endif - pci_write_config_byte(pci, PCIR_DSXG_CTRL, cmd & 0xfc); - pci_write_config_byte(pci, PCIR_DSXG_CTRL, cmd | 0x03); - pci_write_config_byte(pci, PCIR_DSXG_CTRL, cmd & 0xfc); - pci_write_config_word(pci, PCIR_DSXG_PWRCTRL1, 0); - pci_write_config_word(pci, PCIR_DSXG_PWRCTRL2, 0); -#if 0 - } -#endif -} - -static void snd_ymfpci_enable_dsp(struct snd_ymfpci *chip) -{ - snd_ymfpci_writel(chip, YDSXGR_CONFIG, 0x00000001); -} - -static void snd_ymfpci_disable_dsp(struct snd_ymfpci *chip) -{ - u32 val; - int timeout = 1000; - - val = snd_ymfpci_readl(chip, YDSXGR_CONFIG); - if (val) - snd_ymfpci_writel(chip, YDSXGR_CONFIG, 0x00000000); - while (timeout-- > 0) { - val = snd_ymfpci_readl(chip, YDSXGR_STATUS); - if ((val & 0x00000002) == 0) - break; - } -} - -static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip) -{ - int err, is_1e; - const char *name; - - err = request_firmware(&chip->dsp_microcode, "yamaha/ds1_dsp.fw", - &chip->pci->dev); - if (err >= 0) { - if (chip->dsp_microcode->size != YDSXG_DSPLENGTH) { - snd_printk(KERN_ERR "DSP microcode has wrong size\n"); - err = -EINVAL; - } - } - if (err < 0) - return err; - is_1e = chip->device_id == PCI_DEVICE_ID_YAMAHA_724F || - chip->device_id == PCI_DEVICE_ID_YAMAHA_740C || - chip->device_id == PCI_DEVICE_ID_YAMAHA_744 || - chip->device_id == PCI_DEVICE_ID_YAMAHA_754; - name = is_1e ? "yamaha/ds1e_ctrl.fw" : "yamaha/ds1_ctrl.fw"; - err = request_firmware(&chip->controller_microcode, name, - &chip->pci->dev); - if (err >= 0) { - if (chip->controller_microcode->size != YDSXG_CTRLLENGTH) { - snd_printk(KERN_ERR "controller microcode" - " has wrong size\n"); - err = -EINVAL; - } - } - if (err < 0) - return err; - return 0; -} - -MODULE_FIRMWARE("yamaha/ds1_dsp.fw"); -MODULE_FIRMWARE("yamaha/ds1_ctrl.fw"); -MODULE_FIRMWARE("yamaha/ds1e_ctrl.fw"); - -static void snd_ymfpci_download_image(struct snd_ymfpci *chip) -{ - int i; - u16 ctrl; - const __le32 *inst; - - snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000); - snd_ymfpci_disable_dsp(chip); - snd_ymfpci_writel(chip, YDSXGR_MODE, 0x00010000); - snd_ymfpci_writel(chip, YDSXGR_MODE, 0x00000000); - snd_ymfpci_writel(chip, YDSXGR_MAPOFREC, 0x00000000); - snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT, 0x00000000); - snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0x00000000); - snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0x00000000); - snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0x00000000); - ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL); - snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); - - /* setup DSP instruction code */ - inst = (const __le32 *)chip->dsp_microcode->data; - for (i = 0; i < YDSXG_DSPLENGTH / 4; i++) - snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), - le32_to_cpu(inst[i])); - - /* setup control instruction code */ - inst = (const __le32 *)chip->controller_microcode->data; - for (i = 0; i < YDSXG_CTRLLENGTH / 4; i++) - snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), - le32_to_cpu(inst[i])); - - snd_ymfpci_enable_dsp(chip); -} - -static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip) -{ - long size, playback_ctrl_size; - int voice, bank, reg; - u8 *ptr; - dma_addr_t ptr_addr; - - playback_ctrl_size = 4 + 4 * YDSXG_PLAYBACK_VOICES; - chip->bank_size_playback = snd_ymfpci_readl(chip, YDSXGR_PLAYCTRLSIZE) << 2; - chip->bank_size_capture = snd_ymfpci_readl(chip, YDSXGR_RECCTRLSIZE) << 2; - chip->bank_size_effect = snd_ymfpci_readl(chip, YDSXGR_EFFCTRLSIZE) << 2; - chip->work_size = YDSXG_DEFAULT_WORK_SIZE; - - size = ALIGN(playback_ctrl_size, 0x100) + - ALIGN(chip->bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES, 0x100) + - ALIGN(chip->bank_size_capture * 2 * YDSXG_CAPTURE_VOICES, 0x100) + - ALIGN(chip->bank_size_effect * 2 * YDSXG_EFFECT_VOICES, 0x100) + - chip->work_size; - /* work_ptr must be aligned to 256 bytes, but it's already - covered with the kernel page allocation mechanism */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - size, &chip->work_ptr) < 0) - return -ENOMEM; - ptr = chip->work_ptr.area; - ptr_addr = chip->work_ptr.addr; - memset(ptr, 0, size); /* for sure */ - - chip->bank_base_playback = ptr; - chip->bank_base_playback_addr = ptr_addr; - chip->ctrl_playback = (u32 *)ptr; - chip->ctrl_playback[0] = cpu_to_le32(YDSXG_PLAYBACK_VOICES); - ptr += ALIGN(playback_ctrl_size, 0x100); - ptr_addr += ALIGN(playback_ctrl_size, 0x100); - for (voice = 0; voice < YDSXG_PLAYBACK_VOICES; voice++) { - chip->voices[voice].number = voice; - chip->voices[voice].bank = (struct snd_ymfpci_playback_bank *)ptr; - chip->voices[voice].bank_addr = ptr_addr; - for (bank = 0; bank < 2; bank++) { - chip->bank_playback[voice][bank] = (struct snd_ymfpci_playback_bank *)ptr; - ptr += chip->bank_size_playback; - ptr_addr += chip->bank_size_playback; - } - } - ptr = (char *)ALIGN((unsigned long)ptr, 0x100); - ptr_addr = ALIGN(ptr_addr, 0x100); - chip->bank_base_capture = ptr; - chip->bank_base_capture_addr = ptr_addr; - for (voice = 0; voice < YDSXG_CAPTURE_VOICES; voice++) - for (bank = 0; bank < 2; bank++) { - chip->bank_capture[voice][bank] = (struct snd_ymfpci_capture_bank *)ptr; - ptr += chip->bank_size_capture; - ptr_addr += chip->bank_size_capture; - } - ptr = (char *)ALIGN((unsigned long)ptr, 0x100); - ptr_addr = ALIGN(ptr_addr, 0x100); - chip->bank_base_effect = ptr; - chip->bank_base_effect_addr = ptr_addr; - for (voice = 0; voice < YDSXG_EFFECT_VOICES; voice++) - for (bank = 0; bank < 2; bank++) { - chip->bank_effect[voice][bank] = (struct snd_ymfpci_effect_bank *)ptr; - ptr += chip->bank_size_effect; - ptr_addr += chip->bank_size_effect; - } - ptr = (char *)ALIGN((unsigned long)ptr, 0x100); - ptr_addr = ALIGN(ptr_addr, 0x100); - chip->work_base = ptr; - chip->work_base_addr = ptr_addr; - - snd_BUG_ON(ptr + chip->work_size != - chip->work_ptr.area + chip->work_ptr.bytes); - - snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, chip->bank_base_playback_addr); - snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, chip->bank_base_capture_addr); - snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, chip->bank_base_effect_addr); - snd_ymfpci_writel(chip, YDSXGR_WORKBASE, chip->work_base_addr); - snd_ymfpci_writel(chip, YDSXGR_WORKSIZE, chip->work_size >> 2); - - /* S/PDIF output initialization */ - chip->spdif_bits = chip->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF & 0xffff; - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL, 0); - snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits); - - /* S/PDIF input initialization */ - snd_ymfpci_writew(chip, YDSXGR_SPDIFINCTRL, 0); - - /* digital mixer setup */ - for (reg = 0x80; reg < 0xc0; reg += 4) - snd_ymfpci_writel(chip, reg, 0); - snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff); - snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0x3fff3fff); - snd_ymfpci_writel(chip, YDSXGR_ZVOUTVOL, 0x3fff3fff); - snd_ymfpci_writel(chip, YDSXGR_SPDIFOUTVOL, 0x3fff3fff); - snd_ymfpci_writel(chip, YDSXGR_NATIVEADCINVOL, 0x3fff3fff); - snd_ymfpci_writel(chip, YDSXGR_NATIVEDACINVOL, 0x3fff3fff); - snd_ymfpci_writel(chip, YDSXGR_PRIADCLOOPVOL, 0x3fff3fff); - snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0x3fff3fff); - - return 0; -} - -static int snd_ymfpci_free(struct snd_ymfpci *chip) -{ - u16 ctrl; - - if (snd_BUG_ON(!chip)) - return -EINVAL; - - if (chip->res_reg_area) { /* don't touch busy hardware */ - snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); - snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); - snd_ymfpci_writel(chip, YDSXGR_LEGACYOUTVOL, 0); - snd_ymfpci_writel(chip, YDSXGR_STATUS, ~0); - snd_ymfpci_disable_dsp(chip); - snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, 0); - snd_ymfpci_writel(chip, YDSXGR_RECCTRLBASE, 0); - snd_ymfpci_writel(chip, YDSXGR_EFFCTRLBASE, 0); - snd_ymfpci_writel(chip, YDSXGR_WORKBASE, 0); - snd_ymfpci_writel(chip, YDSXGR_WORKSIZE, 0); - ctrl = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL); - snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); - } - - snd_ymfpci_ac3_done(chip); - - /* Set PCI device to D3 state */ -#if 0 - /* FIXME: temporarily disabled, otherwise we cannot fire up - * the chip again unless reboot. ACPI bug? - */ - pci_set_power_state(chip->pci, 3); -#endif - -#ifdef CONFIG_PM - vfree(chip->saved_regs); -#endif - if (chip->irq >= 0) - free_irq(chip->irq, chip); - release_and_free_resource(chip->mpu_res); - release_and_free_resource(chip->fm_res); - snd_ymfpci_free_gameport(chip); - if (chip->reg_area_virt) - iounmap(chip->reg_area_virt); - if (chip->work_ptr.area) - snd_dma_free_pages(&chip->work_ptr); - - release_and_free_resource(chip->res_reg_area); - - pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); - - pci_disable_device(chip->pci); - release_firmware(chip->dsp_microcode); - release_firmware(chip->controller_microcode); - kfree(chip); - return 0; -} - -static int snd_ymfpci_dev_free(struct snd_device *device) -{ - struct snd_ymfpci *chip = device->device_data; - return snd_ymfpci_free(chip); -} - -#ifdef CONFIG_PM -static int saved_regs_index[] = { - /* spdif */ - YDSXGR_SPDIFOUTCTRL, - YDSXGR_SPDIFOUTSTATUS, - YDSXGR_SPDIFINCTRL, - /* volumes */ - YDSXGR_PRIADCLOOPVOL, - YDSXGR_NATIVEDACINVOL, - YDSXGR_NATIVEDACOUTVOL, - YDSXGR_BUF441OUTVOL, - YDSXGR_NATIVEADCINVOL, - YDSXGR_SPDIFLOOPVOL, - YDSXGR_SPDIFOUTVOL, - YDSXGR_ZVOUTVOL, - YDSXGR_LEGACYOUTVOL, - /* address bases */ - YDSXGR_PLAYCTRLBASE, - YDSXGR_RECCTRLBASE, - YDSXGR_EFFCTRLBASE, - YDSXGR_WORKBASE, - /* capture set up */ - YDSXGR_MAPOFREC, - YDSXGR_RECFORMAT, - YDSXGR_RECSLOTSR, - YDSXGR_ADCFORMAT, - YDSXGR_ADCSLOTSR, -}; -#define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index) - -int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ymfpci *chip = card->private_data; - unsigned int i; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_pcm_suspend_all(chip->pcm2); - snd_pcm_suspend_all(chip->pcm_spdif); - snd_pcm_suspend_all(chip->pcm_4ch); - snd_ac97_suspend(chip->ac97); - for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++) - chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]); - chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE); - pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY, - &chip->saved_dsxg_legacy); - pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY, - &chip->saved_dsxg_elegacy); - snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0); - snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0); - snd_ymfpci_disable_dsp(chip); - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -int snd_ymfpci_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_ymfpci *chip = card->private_data; - unsigned int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "ymfpci: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - snd_ymfpci_aclink_reset(pci); - snd_ymfpci_codec_ready(chip, 0); - snd_ymfpci_download_image(chip); - udelay(100); - - for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++) - snd_ymfpci_writel(chip, saved_regs_index[i], chip->saved_regs[i]); - - snd_ac97_resume(chip->ac97); - - pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, - chip->saved_dsxg_legacy); - pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, - chip->saved_dsxg_elegacy); - - /* start hw again */ - if (chip->start_count > 0) { - spin_lock_irq(&chip->reg_lock); - snd_ymfpci_writel(chip, YDSXGR_MODE, chip->saved_ydsxgr_mode); - chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT); - spin_unlock_irq(&chip->reg_lock); - } - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -int __devinit snd_ymfpci_create(struct snd_card *card, - struct pci_dev * pci, - unsigned short old_legacy_ctrl, - struct snd_ymfpci ** rchip) -{ - struct snd_ymfpci *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_ymfpci_dev_free, - }; - - *rchip = NULL; - - /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) - return err; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - chip->old_legacy_ctrl = old_legacy_ctrl; - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->voice_lock); - init_waitqueue_head(&chip->interrupt_sleep); - atomic_set(&chip->interrupt_sleep_count, 0); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - chip->device_id = pci->device; - chip->rev = pci->revision; - chip->reg_area_phys = pci_resource_start(pci, 0); - chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000); - pci_set_master(pci); - chip->src441_used = -1; - - if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) { - snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); - snd_ymfpci_free(chip); - return -EBUSY; - } - if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); - snd_ymfpci_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - - snd_ymfpci_aclink_reset(pci); - if (snd_ymfpci_codec_ready(chip, 0) < 0) { - snd_ymfpci_free(chip); - return -EIO; - } - - err = snd_ymfpci_request_firmware(chip); - if (err < 0) { - snd_printk(KERN_ERR "firmware request failed: %d\n", err); - snd_ymfpci_free(chip); - return err; - } - snd_ymfpci_download_image(chip); - - udelay(100); /* seems we need a delay after downloading image.. */ - - if (snd_ymfpci_memalloc(chip) < 0) { - snd_ymfpci_free(chip); - return -EIO; - } - - if ((err = snd_ymfpci_ac3_init(chip)) < 0) { - snd_ymfpci_free(chip); - return err; - } - -#ifdef CONFIG_PM - chip->saved_regs = vmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32)); - if (chip->saved_regs == NULL) { - snd_ymfpci_free(chip); - return -ENOMEM; - } -#endif - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_ymfpci_free(chip); - return err; - } - - snd_ymfpci_proc_init(card, chip); - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - return 0; -} diff --git a/ANDROID_3.4.5/sound/pcmcia/Kconfig b/ANDROID_3.4.5/sound/pcmcia/Kconfig deleted file mode 100644 index 7fbb190a..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -# ALSA PCMCIA drivers - -menuconfig SND_PCMCIA - bool "PCMCIA sound devices" - depends on PCMCIA - default y - help - Support for sound devices connected via the PCMCIA bus. - -if SND_PCMCIA && PCMCIA - -config SND_VXPOCKET - tristate "Digigram VXpocket" - select SND_VX_LIB - help - Say Y here to include support for Digigram VXpocket and - VXpocket 440 soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-vxpocket. - -config SND_PDAUDIOCF - tristate "Sound Core PDAudioCF" - select SND_PCM - help - Say Y here to include support for Sound Core PDAudioCF - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-pdaudiocf. - -endif # SND_PCMCIA - diff --git a/ANDROID_3.4.5/sound/pcmcia/Makefile b/ANDROID_3.4.5/sound/pcmcia/Makefile deleted file mode 100644 index beef2e33..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -obj-$(CONFIG_SND) += vx/ pdaudiocf/ diff --git a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/Makefile b/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/Makefile deleted file mode 100644 index e892d729..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2004 by Jaroslav Kysela -# - -snd-pdaudiocf-objs := pdaudiocf.o pdaudiocf_core.o pdaudiocf_irq.o pdaudiocf_pcm.o - -obj-$(CONFIG_SND_PDAUDIOCF) += snd-pdaudiocf.o diff --git a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.c b/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.c deleted file mode 100644 index 830839a8..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Driver for Sound Core PDAudioCF soundcard - * - * Copyright (c) 2003 by Jaroslav Kysela - * - * 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 "pdaudiocf.h" -#include -#include - -/* - */ - -#define CARD_NAME "PDAudio-CF" - -MODULE_AUTHOR("Jaroslav Kysela "); -MODULE_DESCRIPTION("Sound Core " CARD_NAME); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - -/* - */ - -static struct snd_card *card_list[SNDRV_CARDS]; - -/* - * prototypes - */ -static int pdacf_config(struct pcmcia_device *link); -static void snd_pdacf_detach(struct pcmcia_device *p_dev); - -static void pdacf_release(struct pcmcia_device *link) -{ - pcmcia_disable_device(link); -} - -/* - * destructor - */ -static int snd_pdacf_free(struct snd_pdacf *pdacf) -{ - struct pcmcia_device *link = pdacf->p_dev; - - pdacf_release(link); - - card_list[pdacf->index] = NULL; - pdacf->card = NULL; - - kfree(pdacf); - return 0; -} - -static int snd_pdacf_dev_free(struct snd_device *device) -{ - struct snd_pdacf *chip = device->device_data; - return snd_pdacf_free(chip); -} - -/* - * snd_pdacf_attach - attach callback for cs - */ -static int snd_pdacf_probe(struct pcmcia_device *link) -{ - int i, err; - struct snd_pdacf *pdacf; - struct snd_card *card; - static struct snd_device_ops ops = { - .dev_free = snd_pdacf_dev_free, - }; - - snd_printdd(KERN_DEBUG "pdacf_attach called\n"); - /* find an empty slot from the card list */ - for (i = 0; i < SNDRV_CARDS; i++) { - if (! card_list[i]) - break; - } - if (i >= SNDRV_CARDS) { - snd_printk(KERN_ERR "pdacf: too many cards found\n"); - return -EINVAL; - } - if (! enable[i]) - return -ENODEV; /* disabled explicitly */ - - /* ok, create a card instance */ - err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); - return err; - } - - pdacf = snd_pdacf_create(card); - if (!pdacf) { - snd_card_free(card); - return -ENOMEM; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops); - if (err < 0) { - kfree(pdacf); - snd_card_free(card); - return err; - } - - snd_card_set_dev(card, &link->dev); - - pdacf->index = i; - card_list[i] = card; - - pdacf->p_dev = link; - link->priv = pdacf; - - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - link->resource[0]->end = 16; - - link->config_flags = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ; - link->config_index = 1; - link->config_regs = PRESENT_OPTION; - - return pdacf_config(link); -} - - -/** - * snd_pdacf_assign_resources - initialize the hardware and card instance. - * @port: i/o port for the card - * @irq: irq number for the card - * - * this function assigns the specified port and irq, boot the card, - * create pcm and control instances, and initialize the rest hardware. - * - * returns 0 if successful, or a negative error code. - */ -static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq) -{ - int err; - struct snd_card *card = pdacf->card; - - snd_printdd(KERN_DEBUG "pdacf assign resources: port = 0x%x, irq = %d\n", port, irq); - pdacf->port = port; - pdacf->irq = irq; - pdacf->chip_status |= PDAUDIOCF_STAT_IS_CONFIGURED; - - err = snd_pdacf_ak4117_create(pdacf); - if (err < 0) - return err; - - strcpy(card->driver, "PDAudio-CF"); - sprintf(card->shortname, "Core Sound %s", card->driver); - sprintf(card->longname, "%s at 0x%x, irq %i", - card->shortname, port, irq); - - err = snd_pdacf_pcm_new(pdacf); - if (err < 0) - return err; - - if ((err = snd_card_register(card)) < 0) - return err; - - return 0; -} - - -/* - * snd_pdacf_detach - detach callback for cs - */ -static void snd_pdacf_detach(struct pcmcia_device *link) -{ - struct snd_pdacf *chip = link->priv; - - snd_printdd(KERN_DEBUG "pdacf_detach called\n"); - - if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED) - snd_pdacf_powerdown(chip); - chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ - snd_card_disconnect(chip->card); - snd_card_free_when_closed(chip->card); -} - -/* - * configuration callback - */ - -static int pdacf_config(struct pcmcia_device *link) -{ - struct snd_pdacf *pdacf = link->priv; - int ret; - - snd_printdd(KERN_DEBUG "pdacf_config called\n"); - link->config_index = 0x5; - link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ; - - ret = pcmcia_request_io(link); - if (ret) - goto failed; - - ret = pcmcia_request_irq(link, pdacf_interrupt); - if (ret) - goto failed; - - ret = pcmcia_enable_device(link); - if (ret) - goto failed; - - if (snd_pdacf_assign_resources(pdacf, link->resource[0]->start, - link->irq) < 0) - goto failed; - - return 0; - -failed: - pcmcia_disable_device(link); - return -ENODEV; -} - -#ifdef CONFIG_PM - -static int pdacf_suspend(struct pcmcia_device *link) -{ - struct snd_pdacf *chip = link->priv; - - snd_printdd(KERN_DEBUG "SUSPEND\n"); - if (chip) { - snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n"); - snd_pdacf_suspend(chip, PMSG_SUSPEND); - } - - return 0; -} - -static int pdacf_resume(struct pcmcia_device *link) -{ - struct snd_pdacf *chip = link->priv; - - snd_printdd(KERN_DEBUG "RESUME\n"); - if (pcmcia_dev_present(link)) { - if (chip) { - snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n"); - snd_pdacf_resume(chip); - } - } - snd_printdd(KERN_DEBUG "resume done!\n"); - - return 0; -} - -#endif - -/* - * Module entry points - */ -static const struct pcmcia_device_id snd_pdacf_ids[] = { - /* this is too general PCMCIA_DEVICE_MANF_CARD(0x015d, 0x4c45), */ - PCMCIA_DEVICE_PROD_ID12("Core Sound","PDAudio-CF",0x396d19d2,0x71717b49), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids); - -static struct pcmcia_driver pdacf_cs_driver = { - .owner = THIS_MODULE, - .name = "snd-pdaudiocf", - .probe = snd_pdacf_probe, - .remove = snd_pdacf_detach, - .id_table = snd_pdacf_ids, -#ifdef CONFIG_PM - .suspend = pdacf_suspend, - .resume = pdacf_resume, -#endif - -}; - -static int __init init_pdacf(void) -{ - return pcmcia_register_driver(&pdacf_cs_driver); -} - -static void __exit exit_pdacf(void) -{ - pcmcia_unregister_driver(&pdacf_cs_driver); -} - -module_init(init_pdacf); -module_exit(exit_pdacf); diff --git a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.h b/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.h deleted file mode 100644 index 6ce9ad70..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Driver for Sound Cors PDAudioCF soundcard - * - * Copyright (c) 2003 by Jaroslav Kysela - * - * 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 - */ - -#ifndef __PDAUDIOCF_H -#define __PDAUDIOCF_H - -#include -#include -#include -#include -#include - -#include - -/* PDAUDIOCF registers */ -#define PDAUDIOCF_REG_MD 0x00 /* music data, R/O */ -#define PDAUDIOCF_REG_WDP 0x02 /* write data pointer / 2, R/O */ -#define PDAUDIOCF_REG_RDP 0x04 /* read data pointer / 2, R/O */ -#define PDAUDIOCF_REG_TCR 0x06 /* test control register W/O */ -#define PDAUDIOCF_REG_SCR 0x08 /* status and control, R/W (see bit description) */ -#define PDAUDIOCF_REG_ISR 0x0a /* interrupt status, R/O */ -#define PDAUDIOCF_REG_IER 0x0c /* interrupt enable, R/W */ -#define PDAUDIOCF_REG_AK_IFR 0x0e /* AK interface register, R/W */ - -/* PDAUDIOCF_REG_TCR */ -#define PDAUDIOCF_ELIMAKMBIT (1<<0) /* simulate AKM music data */ -#define PDAUDIOCF_TESTDATASEL (1<<1) /* test data selection, 0 = 0x55, 1 = pseudo-random */ - -/* PDAUDIOCF_REG_SCR */ -#define PDAUDIOCF_AK_SBP (1<<0) /* serial port busy flag */ -#define PDAUDIOCF_RST (1<<2) /* FPGA, AKM + SRAM buffer reset */ -#define PDAUDIOCF_PDN (1<<3) /* power down bit */ -#define PDAUDIOCF_CLKDIV0 (1<<4) /* choose 24.576Mhz clock divided by 1,2,3 or 4 */ -#define PDAUDIOCF_CLKDIV1 (1<<5) -#define PDAUDIOCF_RECORD (1<<6) /* start capturing to SRAM */ -#define PDAUDIOCF_AK_SDD (1<<7) /* music data detected */ -#define PDAUDIOCF_RED_LED_OFF (1<<8) /* red LED off override */ -#define PDAUDIOCF_BLUE_LED_OFF (1<<9) /* blue LED off override */ -#define PDAUDIOCF_DATAFMT0 (1<<10) /* data format bits: 00 = 16-bit, 01 = 18-bit */ -#define PDAUDIOCF_DATAFMT1 (1<<11) /* 10 = 20-bit, 11 = 24-bit, all right justified */ -#define PDAUDIOCF_FPGAREV(x) ((x>>12)&0x0f) /* FPGA revision */ - -/* PDAUDIOCF_REG_ISR */ -#define PDAUDIOCF_IRQLVL (1<<0) /* Buffer level IRQ */ -#define PDAUDIOCF_IRQOVR (1<<1) /* Overrun IRQ */ -#define PDAUDIOCF_IRQAKM (1<<2) /* AKM IRQ */ - -/* PDAUDIOCF_REG_IER */ -#define PDAUDIOCF_IRQLVLEN0 (1<<0) /* fill threshold levels; 00 = none, 01 = 1/8th of buffer */ -#define PDAUDIOCF_IRQLVLEN1 (1<<1) /* 10 = 1/4th of buffer, 11 = 1/2th of buffer */ -#define PDAUDIOCF_IRQOVREN (1<<2) /* enable overrun IRQ */ -#define PDAUDIOCF_IRQAKMEN (1<<3) /* enable AKM IRQ */ -#define PDAUDIOCF_BLUEDUTY0 (1<<8) /* blue LED duty cycle; 00 = 100%, 01 = 50% */ -#define PDAUDIOCF_BLUEDUTY1 (1<<9) /* 02 = 25%, 11 = 12% */ -#define PDAUDIOCF_REDDUTY0 (1<<10) /* red LED duty cycle; 00 = 100%, 01 = 50% */ -#define PDAUDIOCF_REDDUTY1 (1<<11) /* 02 = 25%, 11 = 12% */ -#define PDAUDIOCF_BLUESDD (1<<12) /* blue LED against SDD bit */ -#define PDAUDIOCF_BLUEMODULATE (1<<13) /* save power when 100% duty cycle selected */ -#define PDAUDIOCF_REDMODULATE (1<<14) /* save power when 100% duty cycle selected */ -#define PDAUDIOCF_HALFRATE (1<<15) /* slow both LED blinks by half (also spdif detect rate) */ - -/* chip status */ -#define PDAUDIOCF_STAT_IS_STALE (1<<0) -#define PDAUDIOCF_STAT_IS_CONFIGURED (1<<1) -#define PDAUDIOCF_STAT_IS_SUSPENDED (1<<2) - -struct snd_pdacf { - struct snd_card *card; - int index; - - unsigned long port; - int irq; - - spinlock_t reg_lock; - unsigned short regmap[8]; - unsigned short suspend_reg_scr; - struct tasklet_struct tq; - - spinlock_t ak4117_lock; - struct ak4117 *ak4117; - - unsigned int chip_status; - - struct snd_pcm *pcm; - struct snd_pcm_substream *pcm_substream; - unsigned int pcm_running: 1; - unsigned int pcm_channels; - unsigned int pcm_swab; - unsigned int pcm_little; - unsigned int pcm_frame; - unsigned int pcm_sample; - unsigned int pcm_xor; - unsigned int pcm_size; - unsigned int pcm_period; - unsigned int pcm_tdone; - unsigned int pcm_hwptr; - void *pcm_area; - - /* pcmcia stuff */ - struct pcmcia_device *p_dev; -}; - -static inline void pdacf_reg_write(struct snd_pdacf *chip, unsigned char reg, unsigned short val) -{ - outw(chip->regmap[reg>>1] = val, chip->port + reg); -} - -static inline unsigned short pdacf_reg_read(struct snd_pdacf *chip, unsigned char reg) -{ - return inw(chip->port + reg); -} - -struct snd_pdacf *snd_pdacf_create(struct snd_card *card); -int snd_pdacf_ak4117_create(struct snd_pdacf *pdacf); -void snd_pdacf_powerdown(struct snd_pdacf *chip); -#ifdef CONFIG_PM -int snd_pdacf_suspend(struct snd_pdacf *chip, pm_message_t state); -int snd_pdacf_resume(struct snd_pdacf *chip); -#endif -int snd_pdacf_pcm_new(struct snd_pdacf *chip); -irqreturn_t pdacf_interrupt(int irq, void *dev); -void pdacf_tasklet(unsigned long private_data); -void pdacf_reinit(struct snd_pdacf *chip, int resume); - -#endif /* __PDAUDIOCF_H */ diff --git a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_core.c deleted file mode 100644 index 9dce0bde..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Driver for Sound Core PDAudioCF soundcard - * - * Copyright (c) 2003 by Jaroslav Kysela - * - * 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 "pdaudiocf.h" -#include - -/* - * - */ -static unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg) -{ - struct snd_pdacf *chip = private_data; - unsigned long timeout; - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&chip->ak4117_lock, flags); - timeout = 1000; - while (pdacf_reg_read(chip, PDAUDIOCF_REG_SCR) & PDAUDIOCF_AK_SBP) { - udelay(5); - if (--timeout == 0) { - spin_unlock_irqrestore(&chip->ak4117_lock, flags); - snd_printk(KERN_ERR "AK4117 ready timeout (read)\n"); - return 0; - } - } - pdacf_reg_write(chip, PDAUDIOCF_REG_AK_IFR, (u16)reg << 8); - timeout = 1000; - while (pdacf_reg_read(chip, PDAUDIOCF_REG_SCR) & PDAUDIOCF_AK_SBP) { - udelay(5); - if (--timeout == 0) { - spin_unlock_irqrestore(&chip->ak4117_lock, flags); - snd_printk(KERN_ERR "AK4117 read timeout (read2)\n"); - return 0; - } - } - res = (unsigned char)pdacf_reg_read(chip, PDAUDIOCF_REG_AK_IFR); - spin_unlock_irqrestore(&chip->ak4117_lock, flags); - return res; -} - -static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned char val) -{ - struct snd_pdacf *chip = private_data; - unsigned long timeout; - unsigned long flags; - - spin_lock_irqsave(&chip->ak4117_lock, flags); - timeout = 1000; - while (inw(chip->port + PDAUDIOCF_REG_SCR) & PDAUDIOCF_AK_SBP) { - udelay(5); - if (--timeout == 0) { - spin_unlock_irqrestore(&chip->ak4117_lock, flags); - snd_printk(KERN_ERR "AK4117 ready timeout (write)\n"); - return; - } - } - outw((u16)reg << 8 | val | (1<<13), chip->port + PDAUDIOCF_REG_AK_IFR); - spin_unlock_irqrestore(&chip->ak4117_lock, flags); -} - -#if 0 -void pdacf_dump(struct snd_pdacf *chip) -{ - printk(KERN_DEBUG "PDAUDIOCF DUMP (0x%lx):\n", chip->port); - printk(KERN_DEBUG "WPD : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_WDP)); - printk(KERN_DEBUG "RDP : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_RDP)); - printk(KERN_DEBUG "TCR : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_TCR)); - printk(KERN_DEBUG "SCR : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_SCR)); - printk(KERN_DEBUG "ISR : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_ISR)); - printk(KERN_DEBUG "IER : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_IER)); - printk(KERN_DEBUG "AK_IFR : 0x%x\n", - inw(chip->port + PDAUDIOCF_REG_AK_IFR)); -} -#endif - -static int pdacf_reset(struct snd_pdacf *chip, int powerdown) -{ - u16 val; - - val = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); - val |= PDAUDIOCF_PDN; - val &= ~PDAUDIOCF_RECORD; /* for sure */ - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); - udelay(5); - val |= PDAUDIOCF_RST; - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); - udelay(200); - val &= ~PDAUDIOCF_RST; - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); - udelay(5); - if (!powerdown) { - val &= ~PDAUDIOCF_PDN; - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); - udelay(200); - } - return 0; -} - -void pdacf_reinit(struct snd_pdacf *chip, int resume) -{ - pdacf_reset(chip, 0); - if (resume) - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, chip->suspend_reg_scr); - snd_ak4117_reinit(chip->ak4117); - pdacf_reg_write(chip, PDAUDIOCF_REG_TCR, chip->regmap[PDAUDIOCF_REG_TCR>>1]); - pdacf_reg_write(chip, PDAUDIOCF_REG_IER, chip->regmap[PDAUDIOCF_REG_IER>>1]); -} - -static void pdacf_proc_read(struct snd_info_entry * entry, - struct snd_info_buffer *buffer) -{ - struct snd_pdacf *chip = entry->private_data; - u16 tmp; - - snd_iprintf(buffer, "PDAudioCF\n\n"); - tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); - snd_iprintf(buffer, "FPGA revision : 0x%x\n", PDAUDIOCF_FPGAREV(tmp)); - -} - -static void pdacf_proc_init(struct snd_pdacf *chip) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry)) - snd_info_set_text_ops(entry, chip, pdacf_proc_read); -} - -struct snd_pdacf *snd_pdacf_create(struct snd_card *card) -{ - struct snd_pdacf *chip; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return NULL; - chip->card = card; - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->ak4117_lock); - tasklet_init(&chip->tq, pdacf_tasklet, (unsigned long)chip); - card->private_data = chip; - - pdacf_proc_init(chip); - return chip; -} - -static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1) -{ - struct snd_pdacf *chip = ak4117->change_callback_private; - unsigned long flags; - u16 val; - - if (!(c0 & AK4117_UNLCK)) - return; - spin_lock_irqsave(&chip->reg_lock, flags); - val = chip->regmap[PDAUDIOCF_REG_SCR>>1]; - if (ak4117->rcs0 & AK4117_UNLCK) - val |= PDAUDIOCF_BLUE_LED_OFF; - else - val &= ~PDAUDIOCF_BLUE_LED_OFF; - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -int snd_pdacf_ak4117_create(struct snd_pdacf *chip) -{ - int err; - u16 val; - /* design note: if we unmask PLL unlock, parity, valid, audio or auto bit interrupts */ - /* from AK4117 then INT1 pin from AK4117 will be high all time, because PCMCIA interrupts are */ - /* egde based and FPGA does logical OR for all interrupt sources, we cannot use these */ - /* high-rate sources */ - static unsigned char pgm[5] = { - AK4117_XTL_24_576M | AK4117_EXCT, /* AK4117_REG_PWRDN */ - AK4117_CM_PLL_XTAL | AK4117_PKCS_128fs | AK4117_XCKS_128fs, /* AK4117_REQ_CLOCK */ - AK4117_EFH_1024LRCLK | AK4117_DIF_24R | AK4117_IPS, /* AK4117_REG_IO */ - 0xff, /* AK4117_REG_INT0_MASK */ - AK4117_MAUTO | AK4117_MAUD | AK4117_MULK | AK4117_MPAR | AK4117_MV, /* AK4117_REG_INT1_MASK */ - }; - - err = pdacf_reset(chip, 0); - if (err < 0) - return err; - err = snd_ak4117_create(chip->card, pdacf_ak4117_read, pdacf_ak4117_write, pgm, chip, &chip->ak4117); - if (err < 0) - return err; - - val = pdacf_reg_read(chip, PDAUDIOCF_REG_TCR); -#if 1 /* normal operation */ - val &= ~(PDAUDIOCF_ELIMAKMBIT|PDAUDIOCF_TESTDATASEL); -#else /* debug */ - val |= PDAUDIOCF_ELIMAKMBIT; - val &= ~PDAUDIOCF_TESTDATASEL; -#endif - pdacf_reg_write(chip, PDAUDIOCF_REG_TCR, val); - - /* setup the FPGA to match AK4117 setup */ - val = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); - val &= ~(PDAUDIOCF_CLKDIV0 | PDAUDIOCF_CLKDIV1); /* use 24.576Mhz clock */ - val &= ~(PDAUDIOCF_RED_LED_OFF|PDAUDIOCF_BLUE_LED_OFF); - val |= PDAUDIOCF_DATAFMT0 | PDAUDIOCF_DATAFMT1; /* 24-bit data */ - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); - - /* setup LEDs and IRQ */ - val = pdacf_reg_read(chip, PDAUDIOCF_REG_IER); - val &= ~(PDAUDIOCF_IRQLVLEN0 | PDAUDIOCF_IRQLVLEN1); - val &= ~(PDAUDIOCF_BLUEDUTY0 | PDAUDIOCF_REDDUTY0 | PDAUDIOCF_REDDUTY1); - val |= PDAUDIOCF_BLUEDUTY1 | PDAUDIOCF_HALFRATE; - val |= PDAUDIOCF_IRQOVREN | PDAUDIOCF_IRQAKMEN; - pdacf_reg_write(chip, PDAUDIOCF_REG_IER, val); - - chip->ak4117->change_callback_private = chip; - chip->ak4117->change_callback = snd_pdacf_ak4117_change; - - /* update LED status */ - snd_pdacf_ak4117_change(chip->ak4117, AK4117_UNLCK, 0); - - return 0; -} - -void snd_pdacf_powerdown(struct snd_pdacf *chip) -{ - u16 val; - - val = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); - chip->suspend_reg_scr = val; - val |= PDAUDIOCF_RED_LED_OFF | PDAUDIOCF_BLUE_LED_OFF; - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val); - /* disable interrupts, but use direct write to preserve old register value in chip->regmap */ - val = inw(chip->port + PDAUDIOCF_REG_IER); - val &= ~(PDAUDIOCF_IRQOVREN|PDAUDIOCF_IRQAKMEN|PDAUDIOCF_IRQLVLEN0|PDAUDIOCF_IRQLVLEN1); - outw(val, chip->port + PDAUDIOCF_REG_IER); - pdacf_reset(chip, 1); -} - -#ifdef CONFIG_PM - -int snd_pdacf_suspend(struct snd_pdacf *chip, pm_message_t state) -{ - u16 val; - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - /* disable interrupts, but use direct write to preserve old register value in chip->regmap */ - val = inw(chip->port + PDAUDIOCF_REG_IER); - val &= ~(PDAUDIOCF_IRQOVREN|PDAUDIOCF_IRQAKMEN|PDAUDIOCF_IRQLVLEN0|PDAUDIOCF_IRQLVLEN1); - outw(val, chip->port + PDAUDIOCF_REG_IER); - chip->chip_status |= PDAUDIOCF_STAT_IS_SUSPENDED; /* ignore interrupts from now */ - snd_pdacf_powerdown(chip); - return 0; -} - -static inline int check_signal(struct snd_pdacf *chip) -{ - return (chip->ak4117->rcs0 & AK4117_UNLCK) == 0; -} - -int snd_pdacf_resume(struct snd_pdacf *chip) -{ - int timeout = 40; - - pdacf_reinit(chip, 1); - /* wait for AK4117's PLL */ - while (timeout-- > 0 && - (snd_ak4117_external_rate(chip->ak4117) <= 0 || !check_signal(chip))) - mdelay(1); - chip->chip_status &= ~PDAUDIOCF_STAT_IS_SUSPENDED; - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif diff --git a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c deleted file mode 100644 index dcd32201..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Driver for Sound Core PDAudioCF soundcard - * - * Copyright (c) 2003 by Jaroslav Kysela - * - * 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 "pdaudiocf.h" -#include -#include - -/* - * - */ -irqreturn_t pdacf_interrupt(int irq, void *dev) -{ - struct snd_pdacf *chip = dev; - unsigned short stat; - - if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE| - PDAUDIOCF_STAT_IS_CONFIGURED| - PDAUDIOCF_STAT_IS_SUSPENDED)) != PDAUDIOCF_STAT_IS_CONFIGURED) - return IRQ_HANDLED; /* IRQ_NONE here? */ - - stat = inw(chip->port + PDAUDIOCF_REG_ISR); - if (stat & (PDAUDIOCF_IRQLVL|PDAUDIOCF_IRQOVR)) { - if (stat & PDAUDIOCF_IRQOVR) /* should never happen */ - snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n"); - if (chip->pcm_substream) - tasklet_schedule(&chip->tq); - if (!(stat & PDAUDIOCF_IRQAKM)) - stat |= PDAUDIOCF_IRQAKM; /* check rate */ - } - if (get_irq_regs() != NULL) - snd_ak4117_check_rate_and_errors(chip->ak4117, 0); - return IRQ_HANDLED; -} - -static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port) -{ - while (size-- > 0) { - *dst++ = inw(rdp_port) ^ xor; - inw(rdp_port); - } -} - -static inline void pdacf_transfer_mono32(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port) -{ - register u16 val1, val2; - - while (size-- > 0) { - val1 = inw(rdp_port); - val2 = inw(rdp_port); - inw(rdp_port); - *dst++ = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor; - } -} - -static inline void pdacf_transfer_stereo16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port) -{ - while (size-- > 0) { - *dst++ = inw(rdp_port) ^ xor; - *dst++ = inw(rdp_port) ^ xor; - } -} - -static inline void pdacf_transfer_stereo32(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port) -{ - register u16 val1, val2, val3; - - while (size-- > 0) { - val1 = inw(rdp_port); - val2 = inw(rdp_port); - val3 = inw(rdp_port); - *dst++ = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor; - *dst++ = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor; - } -} - -static inline void pdacf_transfer_mono16sw(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port) -{ - while (size-- > 0) { - *dst++ = swab16(inw(rdp_port) ^ xor); - inw(rdp_port); - } -} - -static inline void pdacf_transfer_mono32sw(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port) -{ - register u16 val1, val2; - - while (size-- > 0) { - val1 = inw(rdp_port); - val2 = inw(rdp_port); - inw(rdp_port); - *dst++ = swab32((((val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor); - } -} - -static inline void pdacf_transfer_stereo16sw(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port) -{ - while (size-- > 0) { - *dst++ = swab16(inw(rdp_port) ^ xor); - *dst++ = swab16(inw(rdp_port) ^ xor); - } -} - -static inline void pdacf_transfer_stereo32sw(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port) -{ - register u16 val1, val2, val3; - - while (size-- > 0) { - val1 = inw(rdp_port); - val2 = inw(rdp_port); - val3 = inw(rdp_port); - *dst++ = swab32((((val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor); - *dst++ = swab32((((u32)val3 << 16) | (val2 & 0xff00)) ^ xor); - } -} - -static inline void pdacf_transfer_mono24le(u8 *dst, u16 xor, unsigned int size, unsigned long rdp_port) -{ - register u16 val1, val2; - register u32 xval1; - - while (size-- > 0) { - val1 = inw(rdp_port); - val2 = inw(rdp_port); - inw(rdp_port); - xval1 = (((val2 & 0xff) << 8) | (val1 << 16)) ^ xor; - *dst++ = (u8)(xval1 >> 8); - *dst++ = (u8)(xval1 >> 16); - *dst++ = (u8)(xval1 >> 24); - } -} - -static inline void pdacf_transfer_mono24be(u8 *dst, u16 xor, unsigned int size, unsigned long rdp_port) -{ - register u16 val1, val2; - register u32 xval1; - - while (size-- > 0) { - val1 = inw(rdp_port); - val2 = inw(rdp_port); - inw(rdp_port); - xval1 = (((val2 & 0xff) << 8) | (val1 << 16)) ^ xor; - *dst++ = (u8)(xval1 >> 24); - *dst++ = (u8)(xval1 >> 16); - *dst++ = (u8)(xval1 >> 8); - } -} - -static inline void pdacf_transfer_stereo24le(u8 *dst, u32 xor, unsigned int size, unsigned long rdp_port) -{ - register u16 val1, val2, val3; - register u32 xval1, xval2; - - while (size-- > 0) { - val1 = inw(rdp_port); - val2 = inw(rdp_port); - val3 = inw(rdp_port); - xval1 = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor; - xval2 = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor; - *dst++ = (u8)(xval1 >> 8); - *dst++ = (u8)(xval1 >> 16); - *dst++ = (u8)(xval1 >> 24); - *dst++ = (u8)(xval2 >> 8); - *dst++ = (u8)(xval2 >> 16); - *dst++ = (u8)(xval2 >> 24); - } -} - -static inline void pdacf_transfer_stereo24be(u8 *dst, u32 xor, unsigned int size, unsigned long rdp_port) -{ - register u16 val1, val2, val3; - register u32 xval1, xval2; - - while (size-- > 0) { - val1 = inw(rdp_port); - val2 = inw(rdp_port); - val3 = inw(rdp_port); - xval1 = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor; - xval2 = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor; - *dst++ = (u8)(xval1 >> 24); - *dst++ = (u8)(xval1 >> 16); - *dst++ = (u8)(xval1 >> 8); - *dst++ = (u8)(xval2 >> 24); - *dst++ = (u8)(xval2 >> 16); - *dst++ = (u8)(xval2 >> 8); - } -} - -static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned int off) -{ - unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD; - unsigned int xor = chip->pcm_xor; - - if (chip->pcm_sample == 3) { - if (chip->pcm_little) { - if (chip->pcm_channels == 1) { - pdacf_transfer_mono24le((char *)chip->pcm_area + (off * 3), xor, size, rdp_port); - } else { - pdacf_transfer_stereo24le((char *)chip->pcm_area + (off * 6), xor, size, rdp_port); - } - } else { - if (chip->pcm_channels == 1) { - pdacf_transfer_mono24be((char *)chip->pcm_area + (off * 3), xor, size, rdp_port); - } else { - pdacf_transfer_stereo24be((char *)chip->pcm_area + (off * 6), xor, size, rdp_port); - } - } - return; - } - if (chip->pcm_swab == 0) { - if (chip->pcm_channels == 1) { - if (chip->pcm_frame == 2) { - pdacf_transfer_mono16((u16 *)chip->pcm_area + off, xor, size, rdp_port); - } else { - pdacf_transfer_mono32((u32 *)chip->pcm_area + off, xor, size, rdp_port); - } - } else { - if (chip->pcm_frame == 2) { - pdacf_transfer_stereo16((u16 *)chip->pcm_area + (off * 2), xor, size, rdp_port); - } else { - pdacf_transfer_stereo32((u32 *)chip->pcm_area + (off * 2), xor, size, rdp_port); - } - } - } else { - if (chip->pcm_channels == 1) { - if (chip->pcm_frame == 2) { - pdacf_transfer_mono16sw((u16 *)chip->pcm_area + off, xor, size, rdp_port); - } else { - pdacf_transfer_mono32sw((u32 *)chip->pcm_area + off, xor, size, rdp_port); - } - } else { - if (chip->pcm_frame == 2) { - pdacf_transfer_stereo16sw((u16 *)chip->pcm_area + (off * 2), xor, size, rdp_port); - } else { - pdacf_transfer_stereo32sw((u32 *)chip->pcm_area + (off * 2), xor, size, rdp_port); - } - } - } -} - -void pdacf_tasklet(unsigned long private_data) -{ - struct snd_pdacf *chip = (struct snd_pdacf *) private_data; - int size, off, cont, rdp, wdp; - - if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED) - return; - - if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream)) - return; - - rdp = inw(chip->port + PDAUDIOCF_REG_RDP); - wdp = inw(chip->port + PDAUDIOCF_REG_WDP); - /* printk(KERN_DEBUG "TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); */ - size = wdp - rdp; - if (size < 0) - size += 0x10000; - if (size == 0) - size = 0x10000; - size /= chip->pcm_frame; - if (size > 64) - size -= 32; - -#if 0 - chip->pcm_hwptr += size; - chip->pcm_hwptr %= chip->pcm_size; - chip->pcm_tdone += size; - if (chip->pcm_frame == 2) { - unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD; - while (size-- > 0) { - inw(rdp_port); - inw(rdp_port); - } - } else { - unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD; - while (size-- > 0) { - inw(rdp_port); - inw(rdp_port); - inw(rdp_port); - } - } -#else - off = chip->pcm_hwptr + chip->pcm_tdone; - off %= chip->pcm_size; - chip->pcm_tdone += size; - while (size > 0) { - cont = chip->pcm_size - off; - if (cont > size) - cont = size; - pdacf_transfer(chip, cont, off); - off += cont; - off %= chip->pcm_size; - size -= cont; - } -#endif - spin_lock(&chip->reg_lock); - while (chip->pcm_tdone >= chip->pcm_period) { - chip->pcm_hwptr += chip->pcm_period; - chip->pcm_hwptr %= chip->pcm_size; - chip->pcm_tdone -= chip->pcm_period; - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(chip->pcm_substream); - spin_lock(&chip->reg_lock); - } - spin_unlock(&chip->reg_lock); - /* printk(KERN_DEBUG "TASKLET: end\n"); */ -} diff --git a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c deleted file mode 100644 index 43f995a3..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Driver for Sound Core PDAudioCF soundcards - * - * PCM part - * - * Copyright (c) 2003 by Jaroslav Kysela - * - * 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 "pdaudiocf.h" - - -/* - * clear the SRAM contents - */ -static int pdacf_pcm_clear_sram(struct snd_pdacf *chip) -{ - int max_loop = 64 * 1024; - - while (inw(chip->port + PDAUDIOCF_REG_RDP) != inw(chip->port + PDAUDIOCF_REG_WDP)) { - if (max_loop-- < 0) - return -EIO; - inw(chip->port + PDAUDIOCF_REG_MD); - } - return 0; -} - -/* - * pdacf_pcm_trigger - trigger callback for capture - */ -static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct snd_pdacf *chip = snd_pcm_substream_chip(subs); - struct snd_pcm_runtime *runtime = subs->runtime; - int inc, ret = 0, rate; - unsigned short mask, val, tmp; - - if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE) - return -EBUSY; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - chip->pcm_hwptr = 0; - chip->pcm_tdone = 0; - /* fall thru */ - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - mask = 0; - val = PDAUDIOCF_RECORD; - inc = 1; - rate = snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_STAT|AK4117_CHECK_NO_RATE); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - mask = PDAUDIOCF_RECORD; - val = 0; - inc = -1; - rate = 0; - break; - default: - return -EINVAL; - } - spin_lock(&chip->reg_lock); - chip->pcm_running += inc; - tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); - if (chip->pcm_running) { - if ((chip->ak4117->rcs0 & AK4117_UNLCK) || runtime->rate != rate) { - chip->pcm_running -= inc; - ret = -EIO; - goto __end; - } - } - tmp &= ~mask; - tmp |= val; - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp); - __end: - spin_unlock(&chip->reg_lock); - snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE); - return ret; -} - -/* - * pdacf_pcm_hw_params - hw_params callback for playback and capture - */ -static int pdacf_pcm_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_alloc_vmalloc_32_buffer - (subs, params_buffer_bytes(hw_params)); -} - -/* - * pdacf_pcm_hw_free - hw_free callback for playback and capture - */ -static int pdacf_pcm_hw_free(struct snd_pcm_substream *subs) -{ - return snd_pcm_lib_free_vmalloc_buffer(subs); -} - -/* - * pdacf_pcm_prepare - prepare callback for playback and capture - */ -static int pdacf_pcm_prepare(struct snd_pcm_substream *subs) -{ - struct snd_pdacf *chip = snd_pcm_substream_chip(subs); - struct snd_pcm_runtime *runtime = subs->runtime; - u16 val, nval, aval; - - if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE) - return -EBUSY; - - chip->pcm_channels = runtime->channels; - - chip->pcm_little = snd_pcm_format_little_endian(runtime->format) > 0; -#ifdef SNDRV_LITTLE_ENDIAN - chip->pcm_swab = snd_pcm_format_big_endian(runtime->format) > 0; -#else - chip->pcm_swab = chip->pcm_little; -#endif - - if (snd_pcm_format_unsigned(runtime->format)) - chip->pcm_xor = 0x80008000; - - if (pdacf_pcm_clear_sram(chip) < 0) - return -EIO; - - val = nval = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR); - nval &= ~(PDAUDIOCF_DATAFMT0|PDAUDIOCF_DATAFMT1); - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: - break; - default: /* 24-bit */ - nval |= PDAUDIOCF_DATAFMT0 | PDAUDIOCF_DATAFMT1; - break; - } - aval = 0; - chip->pcm_sample = 4; - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: - aval = AK4117_DIF_16R; - chip->pcm_frame = 2; - chip->pcm_sample = 2; - break; - case SNDRV_PCM_FORMAT_S24_3LE: - case SNDRV_PCM_FORMAT_S24_3BE: - chip->pcm_sample = 3; - /* fall through */ - default: /* 24-bit */ - aval = AK4117_DIF_24R; - chip->pcm_frame = 3; - chip->pcm_xor &= 0xffff0000; - break; - } - - if (val != nval) { - snd_ak4117_reg_write(chip->ak4117, AK4117_REG_IO, AK4117_DIF2|AK4117_DIF1|AK4117_DIF0, aval); - pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, nval); - } - - val = pdacf_reg_read(chip, PDAUDIOCF_REG_IER); - val &= ~(PDAUDIOCF_IRQLVLEN1); - val |= PDAUDIOCF_IRQLVLEN0; - pdacf_reg_write(chip, PDAUDIOCF_REG_IER, val); - - chip->pcm_size = runtime->buffer_size; - chip->pcm_period = runtime->period_size; - chip->pcm_area = runtime->dma_area; - - return 0; -} - - -/* - * capture hw information - */ - -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_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, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .rate_min = 32000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (512*1024), - .period_bytes_min = 8*1024, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = 128, - .fifo_size = 0, -}; - - -/* - * pdacf_pcm_capture_open - open callback for capture - */ -static int pdacf_pcm_capture_open(struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - struct snd_pdacf *chip = snd_pcm_substream_chip(subs); - - if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE) - return -EBUSY; - - runtime->hw = pdacf_pcm_capture_hw; - runtime->private_data = chip; - chip->pcm_substream = subs; - - return 0; -} - -/* - * pdacf_pcm_capture_close - close callback for capture - */ -static int pdacf_pcm_capture_close(struct snd_pcm_substream *subs) -{ - struct snd_pdacf *chip = snd_pcm_substream_chip(subs); - - if (!chip) - return -EINVAL; - pdacf_reinit(chip, 0); - chip->pcm_substream = NULL; - return 0; -} - - -/* - * pdacf_pcm_capture_pointer - pointer callback for capture - */ -static snd_pcm_uframes_t pdacf_pcm_capture_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pdacf *chip = snd_pcm_substream_chip(subs); - return chip->pcm_hwptr; -} - -/* - * operators for PCM capture - */ -static struct snd_pcm_ops pdacf_pcm_capture_ops = { - .open = pdacf_pcm_capture_open, - .close = pdacf_pcm_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pdacf_pcm_hw_params, - .hw_free = pdacf_pcm_hw_free, - .prepare = pdacf_pcm_prepare, - .trigger = pdacf_pcm_trigger, - .pointer = pdacf_pcm_capture_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; - - -/* - * snd_pdacf_pcm_new - create and initialize a pcm - */ -int snd_pdacf_pcm_new(struct snd_pdacf *chip) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(chip->card, "PDAudioCF", 0, 0, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->shortname); - chip->pcm = pcm; - - err = snd_ak4117_build(chip->ak4117, pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); - if (err < 0) - return err; - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pcmcia/vx/Makefile b/ANDROID_3.4.5/sound/pcmcia/vx/Makefile deleted file mode 100644 index 2bb42ea1..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/vx/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-vxpocket-objs := vxpocket.o vxp_ops.o vxp_mixer.o - -obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o diff --git a/ANDROID_3.4.5/sound/pcmcia/vx/vxp_mixer.c b/ANDROID_3.4.5/sound/pcmcia/vx/vxp_mixer.c deleted file mode 100644 index a4a66425..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/vx/vxp_mixer.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Driver for Digigram VXpocket soundcards - * - * VX-pocket mixer - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 "vxpocket.h" - -#define MIC_LEVEL_MIN 0 -#define MIC_LEVEL_MAX 8 - -/* - * mic level control (for VXPocket) - */ -static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = MIC_LEVEL_MAX; - return 0; -} - -static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - ucontrol->value.integer.value[0] = chip->mic_level; - return 0; -} - -static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - unsigned int val = ucontrol->value.integer.value[0]; - - if (val > MIC_LEVEL_MAX) - return -EINVAL; - mutex_lock(&_chip->mixer_mutex); - if (chip->mic_level != ucontrol->value.integer.value[0]) { - vx_set_mic_level(_chip, ucontrol->value.integer.value[0]); - chip->mic_level = ucontrol->value.integer.value[0]; - mutex_unlock(&_chip->mixer_mutex); - return 1; - } - mutex_unlock(&_chip->mixer_mutex); - return 0; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0); - -static struct snd_kcontrol_new vx_control_mic_level = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), - .name = "Mic Capture Volume", - .info = vx_mic_level_info, - .get = vx_mic_level_get, - .put = vx_mic_level_put, - .tlv = { .p = db_scale_mic }, -}; - -/* - * mic boost level control (for VXP440) - */ -#define vx_mic_boost_info snd_ctl_boolean_mono_info - -static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - ucontrol->value.integer.value[0] = chip->mic_level; - return 0; -} - -static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - int val = !!ucontrol->value.integer.value[0]; - mutex_lock(&_chip->mixer_mutex); - if (chip->mic_level != val) { - vx_set_mic_boost(_chip, val); - chip->mic_level = val; - mutex_unlock(&_chip->mixer_mutex); - return 1; - } - mutex_unlock(&_chip->mixer_mutex); - return 0; -} - -static struct snd_kcontrol_new vx_control_mic_boost = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Boost", - .info = vx_mic_boost_info, - .get = vx_mic_boost_get, - .put = vx_mic_boost_put, -}; - - -int vxp_add_mic_controls(struct vx_core *_chip) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - int err; - - /* mute input levels */ - chip->mic_level = 0; - switch (_chip->type) { - case VX_TYPE_VXPOCKET: - vx_set_mic_level(_chip, 0); - break; - case VX_TYPE_VXP440: - vx_set_mic_boost(_chip, 0); - break; - } - - /* mic level */ - switch (_chip->type) { - case VX_TYPE_VXPOCKET: - if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip))) < 0) - return err; - break; - case VX_TYPE_VXP440: - if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_boost, chip))) < 0) - return err; - break; - } - - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pcmcia/vx/vxp_ops.c b/ANDROID_3.4.5/sound/pcmcia/vx/vxp_ops.c deleted file mode 100644 index fe33e122..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/vx/vxp_ops.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Driver for Digigram VXpocket soundcards - * - * lowlevel routines for VXpocket soundcards - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 "vxpocket.h" - - -static int vxp_reg_offset[VX_REG_MAX] = { - [VX_ICR] = 0x00, // ICR - [VX_CVR] = 0x01, // CVR - [VX_ISR] = 0x02, // ISR - [VX_IVR] = 0x03, // IVR - [VX_RXH] = 0x05, // RXH - [VX_RXM] = 0x06, // RXM - [VX_RXL] = 0x07, // RXL - [VX_DMA] = 0x04, // DMA - [VX_CDSP] = 0x08, // CDSP - [VX_LOFREQ] = 0x09, // LFREQ - [VX_HIFREQ] = 0x0a, // HFREQ - [VX_DATA] = 0x0b, // DATA - [VX_MICRO] = 0x0c, // MICRO - [VX_DIALOG] = 0x0d, // DIALOG - [VX_CSUER] = 0x0e, // CSUER - [VX_RUER] = 0x0f, // RUER -}; - - -static inline unsigned long vxp_reg_addr(struct vx_core *_chip, int reg) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - return chip->port + vxp_reg_offset[reg]; -} - -/* - * snd_vx_inb - read a byte from the register - * @offset: register offset - */ -static unsigned char vxp_inb(struct vx_core *chip, int offset) -{ - return inb(vxp_reg_addr(chip, offset)); -} - -/* - * snd_vx_outb - write a byte on the register - * @offset: the register offset - * @val: the value to write - */ -static void vxp_outb(struct vx_core *chip, int offset, unsigned char val) -{ - outb(val, vxp_reg_addr(chip, offset)); -} - -/* - * redefine macros to call directly - */ -#undef vx_inb -#define vx_inb(chip,reg) vxp_inb((struct vx_core *)(chip), VX_##reg) -#undef vx_outb -#define vx_outb(chip,reg,val) vxp_outb((struct vx_core *)(chip), VX_##reg,val) - - -/* - * vx_check_magic - check the magic word on xilinx - * - * returns zero if a magic word is detected, or a negative error code. - */ -static int vx_check_magic(struct vx_core *chip) -{ - unsigned long end_time = jiffies + HZ / 5; - int c; - do { - c = vx_inb(chip, CDSP); - if (c == CDSP_MAGIC) - return 0; - msleep(10); - } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "cannot find xilinx magic word (%x)\n", c); - return -EIO; -} - - -/* - * vx_reset_dsp - reset the DSP - */ - -#define XX_DSP_RESET_WAIT_TIME 2 /* ms */ - -static void vxp_reset_dsp(struct vx_core *_chip) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - /* set the reset dsp bit to 1 */ - vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_DSP_RESET_MASK); - vx_inb(chip, CDSP); - mdelay(XX_DSP_RESET_WAIT_TIME); - /* reset the bit */ - chip->regCDSP &= ~VXP_CDSP_DSP_RESET_MASK; - vx_outb(chip, CDSP, chip->regCDSP); - vx_inb(chip, CDSP); - mdelay(XX_DSP_RESET_WAIT_TIME); -} - -/* - * reset codec bit - */ -static void vxp_reset_codec(struct vx_core *_chip) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - /* Set the reset CODEC bit to 1. */ - vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK); - vx_inb(chip, CDSP); - msleep(10); - /* Set the reset CODEC bit to 0. */ - chip->regCDSP &= ~VXP_CDSP_CODEC_RESET_MASK; - vx_outb(chip, CDSP, chip->regCDSP); - vx_inb(chip, CDSP); - msleep(1); -} - -/* - * vx_load_xilinx_binary - load the xilinx binary image - * the binary image is the binary array converted from the bitstream file. - */ -static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *fw) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - unsigned int i; - int c; - int regCSUER, regRUER; - const unsigned char *image; - unsigned char data; - - /* Switch to programmation mode */ - chip->regDIALOG |= VXP_DLG_XILINX_REPROG_MASK; - vx_outb(chip, DIALOG, chip->regDIALOG); - - /* Save register CSUER and RUER */ - regCSUER = vx_inb(chip, CSUER); - regRUER = vx_inb(chip, RUER); - - /* reset HF0 and HF1 */ - vx_outb(chip, ICR, 0); - - /* Wait for answer HF2 equal to 1 */ - snd_printdd(KERN_DEBUG "check ISR_HF2\n"); - if (vx_check_isr(_chip, ISR_HF2, ISR_HF2, 20) < 0) - goto _error; - - /* set HF1 for loading xilinx binary */ - vx_outb(chip, ICR, ICR_HF1); - image = fw->data; - for (i = 0; i < fw->size; i++, image++) { - data = *image; - if (vx_wait_isr_bit(_chip, ISR_TX_EMPTY) < 0) - goto _error; - vx_outb(chip, TXL, data); - /* wait for reading */ - if (vx_wait_for_rx_full(_chip) < 0) - goto _error; - c = vx_inb(chip, RXL); - if (c != (int)data) - snd_printk(KERN_ERR "vxpocket: load xilinx mismatch at %d: 0x%x != 0x%x\n", i, c, (int)data); - } - - /* reset HF1 */ - vx_outb(chip, ICR, 0); - - /* wait for HF3 */ - if (vx_check_isr(_chip, ISR_HF3, ISR_HF3, 20) < 0) - goto _error; - - /* read the number of bytes received */ - if (vx_wait_for_rx_full(_chip) < 0) - goto _error; - - c = (int)vx_inb(chip, RXH) << 16; - c |= (int)vx_inb(chip, RXM) << 8; - c |= vx_inb(chip, RXL); - - snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%Zx\n", c, fw->size); - - vx_outb(chip, ICR, ICR_HF0); - - /* TEMPO 250ms : wait until Xilinx is downloaded */ - msleep(300); - - /* test magical word */ - if (vx_check_magic(_chip) < 0) - goto _error; - - /* Restore register 0x0E and 0x0F (thus replacing COR and FCSR) */ - vx_outb(chip, CSUER, regCSUER); - vx_outb(chip, RUER, regRUER); - - /* Reset the Xilinx's signal enabling IO access */ - chip->regDIALOG |= VXP_DLG_XILINX_REPROG_MASK; - vx_outb(chip, DIALOG, chip->regDIALOG); - vx_inb(chip, DIALOG); - msleep(10); - chip->regDIALOG &= ~VXP_DLG_XILINX_REPROG_MASK; - vx_outb(chip, DIALOG, chip->regDIALOG); - vx_inb(chip, DIALOG); - - /* Reset of the Codec */ - vxp_reset_codec(_chip); - vx_reset_dsp(_chip); - - return 0; - - _error: - vx_outb(chip, CSUER, regCSUER); - vx_outb(chip, RUER, regRUER); - chip->regDIALOG &= ~VXP_DLG_XILINX_REPROG_MASK; - vx_outb(chip, DIALOG, chip->regDIALOG); - return -EIO; -} - - -/* - * vxp_load_dsp - load_dsp callback - */ -static int vxp_load_dsp(struct vx_core *vx, int index, const struct firmware *fw) -{ - int err; - - switch (index) { - case 0: - /* xilinx boot */ - if ((err = vx_check_magic(vx)) < 0) - return err; - if ((err = snd_vx_load_boot_image(vx, fw)) < 0) - return err; - return 0; - case 1: - /* xilinx image */ - return vxp_load_xilinx_binary(vx, fw); - case 2: - /* DSP boot */ - return snd_vx_dsp_boot(vx, fw); - case 3: - /* DSP image */ - return snd_vx_dsp_load(vx, fw); - default: - snd_BUG(); - return -EINVAL; - } -} - - -/* - * vx_test_and_ack - test and acknowledge interrupt - * - * called from irq hander, too - * - * spinlock held! - */ -static int vxp_test_and_ack(struct vx_core *_chip) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - /* not booted yet? */ - if (! (_chip->chip_status & VX_STAT_XILINX_LOADED)) - return -ENXIO; - - if (! (vx_inb(chip, DIALOG) & VXP_DLG_MEMIRQ_MASK)) - return -EIO; - - /* ok, interrupts generated, now ack it */ - /* set ACQUIT bit up and down */ - vx_outb(chip, DIALOG, chip->regDIALOG | VXP_DLG_ACK_MEMIRQ_MASK); - /* useless read just to spend some time and maintain - * the ACQUIT signal up for a while ( a bus cycle ) - */ - vx_inb(chip, DIALOG); - vx_outb(chip, DIALOG, chip->regDIALOG & ~VXP_DLG_ACK_MEMIRQ_MASK); - - return 0; -} - - -/* - * vx_validate_irq - enable/disable IRQ - */ -static void vxp_validate_irq(struct vx_core *_chip, int enable) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - /* Set the interrupt enable bit to 1 in CDSP register */ - if (enable) - chip->regCDSP |= VXP_CDSP_VALID_IRQ_MASK; - else - chip->regCDSP &= ~VXP_CDSP_VALID_IRQ_MASK; - vx_outb(chip, CDSP, chip->regCDSP); -} - -/* - * vx_setup_pseudo_dma - set up the pseudo dma read/write mode. - * @do_write: 0 = read, 1 = set up for DMA write - */ -static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - /* Interrupt mode and HREQ pin enabled for host transmit / receive data transfers */ - vx_outb(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ); - /* Reset the pseudo-dma register */ - vx_inb(chip, ISR); - vx_outb(chip, ISR, 0); - - /* Select DMA in read/write transfer mode and in 16-bit accesses */ - chip->regDIALOG |= VXP_DLG_DMA16_SEL_MASK; - chip->regDIALOG |= do_write ? VXP_DLG_DMAWRITE_SEL_MASK : VXP_DLG_DMAREAD_SEL_MASK; - vx_outb(chip, DIALOG, chip->regDIALOG); - -} - -/* - * vx_release_pseudo_dma - disable the pseudo-DMA mode - */ -static void vx_release_pseudo_dma(struct vx_core *_chip) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - /* Disable DMA and 16-bit accesses */ - chip->regDIALOG &= ~(VXP_DLG_DMAWRITE_SEL_MASK| - VXP_DLG_DMAREAD_SEL_MASK| - VXP_DLG_DMA16_SEL_MASK); - vx_outb(chip, DIALOG, chip->regDIALOG); - /* HREQ pin disabled. */ - vx_outb(chip, ICR, 0); -} - -/* - * vx_pseudo_dma_write - write bulk data on pseudo-DMA mode - * @count: data length to transfer in bytes - * - * data size must be aligned to 6 bytes to ensure the 24bit alignment on DSP. - * NB: call with a certain lock! - */ -static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe, int count) -{ - long port = vxp_reg_addr(chip, VX_DMA); - int offset = pipe->hw_ptr; - unsigned short *addr = (unsigned short *)(runtime->dma_area + offset); - - vx_setup_pseudo_dma(chip, 1); - if (offset + count > pipe->buffer_bytes) { - int length = pipe->buffer_bytes - offset; - count -= length; - length >>= 1; /* in 16bit words */ - /* Transfer using pseudo-dma. */ - while (length-- > 0) { - outw(cpu_to_le16(*addr), port); - addr++; - } - addr = (unsigned short *)runtime->dma_area; - pipe->hw_ptr = 0; - } - pipe->hw_ptr += count; - count >>= 1; /* in 16bit words */ - /* Transfer using pseudo-dma. */ - while (count-- > 0) { - outw(cpu_to_le16(*addr), port); - addr++; - } - vx_release_pseudo_dma(chip); -} - - -/* - * vx_pseudo_dma_read - read bulk data on pseudo DMA mode - * @offset: buffer offset in bytes - * @count: data length to transfer in bytes - * - * the read length must be aligned to 6 bytes, as well as write. - * NB: call with a certain lock! - */ -static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, - struct vx_pipe *pipe, int count) -{ - struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; - long port = vxp_reg_addr(chip, VX_DMA); - int offset = pipe->hw_ptr; - unsigned short *addr = (unsigned short *)(runtime->dma_area + offset); - - if (snd_BUG_ON(count % 2)) - return; - vx_setup_pseudo_dma(chip, 0); - if (offset + count > pipe->buffer_bytes) { - int length = pipe->buffer_bytes - offset; - count -= length; - length >>= 1; /* in 16bit words */ - /* Transfer using pseudo-dma. */ - while (length-- > 0) - *addr++ = le16_to_cpu(inw(port)); - addr = (unsigned short *)runtime->dma_area; - pipe->hw_ptr = 0; - } - pipe->hw_ptr += count; - count >>= 1; /* in 16bit words */ - /* Transfer using pseudo-dma. */ - while (count-- > 1) - *addr++ = le16_to_cpu(inw(port)); - /* Disable DMA */ - pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK; - vx_outb(chip, DIALOG, pchip->regDIALOG); - /* Read the last word (16 bits) */ - *addr = le16_to_cpu(inw(port)); - /* Disable 16-bit accesses */ - pchip->regDIALOG &= ~VXP_DLG_DMA16_SEL_MASK; - vx_outb(chip, DIALOG, pchip->regDIALOG); - /* HREQ pin disabled. */ - vx_outb(chip, ICR, 0); -} - - -/* - * write a codec data (24bit) - */ -static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int data) -{ - int i; - - /* Activate access to the corresponding codec register */ - if (! codec) - vx_inb(chip, LOFREQ); - else - vx_inb(chip, CODEC2); - - /* We have to send 24 bits (3 x 8 bits). Start with most signif. Bit */ - for (i = 0; i < 24; i++, data <<= 1) - vx_outb(chip, DATA, ((data & 0x800000) ? VX_DATA_CODEC_MASK : 0)); - - /* Terminate access to codec registers */ - vx_inb(chip, HIFREQ); -} - - -/* - * vx_set_mic_boost - set mic boost level (on vxp440 only) - * @boost: 0 = 20dB, 1 = +38dB - */ -void vx_set_mic_boost(struct vx_core *chip, int boost) -{ - struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; - unsigned long flags; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - spin_lock_irqsave(&chip->lock, flags); - if (pchip->regCDSP & P24_CDSP_MICS_SEL_MASK) { - if (boost) { - /* boost: 38 dB */ - pchip->regCDSP &= ~P24_CDSP_MIC20_SEL_MASK; - pchip->regCDSP |= P24_CDSP_MIC38_SEL_MASK; - } else { - /* minimum value: 20 dB */ - pchip->regCDSP |= P24_CDSP_MIC20_SEL_MASK; - pchip->regCDSP &= ~P24_CDSP_MIC38_SEL_MASK; - } - vx_outb(chip, CDSP, pchip->regCDSP); - } - spin_unlock_irqrestore(&chip->lock, flags); -} - -/* - * remap the linear value (0-8) to the actual value (0-15) - */ -static int vx_compute_mic_level(int level) -{ - switch (level) { - case 5: level = 6 ; break; - case 6: level = 8 ; break; - case 7: level = 11; break; - case 8: level = 15; break; - default: break ; - } - return level; -} - -/* - * vx_set_mic_level - set mic level (on vxpocket only) - * @level: the mic level = 0 - 8 (max) - */ -void vx_set_mic_level(struct vx_core *chip, int level) -{ - struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; - unsigned long flags; - - if (chip->chip_status & VX_STAT_IS_STALE) - return; - - spin_lock_irqsave(&chip->lock, flags); - if (pchip->regCDSP & VXP_CDSP_MIC_SEL_MASK) { - level = vx_compute_mic_level(level); - vx_outb(chip, MICRO, level); - } - spin_unlock_irqrestore(&chip->lock, flags); -} - - -/* - * change the input audio source - */ -static void vxp_change_audio_source(struct vx_core *_chip, int src) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - switch (src) { - case VX_AUDIO_SRC_DIGITAL: - chip->regCDSP |= VXP_CDSP_DATAIN_SEL_MASK; - vx_outb(chip, CDSP, chip->regCDSP); - break; - case VX_AUDIO_SRC_LINE: - chip->regCDSP &= ~VXP_CDSP_DATAIN_SEL_MASK; - if (_chip->type == VX_TYPE_VXP440) - chip->regCDSP &= ~P24_CDSP_MICS_SEL_MASK; - else - chip->regCDSP &= ~VXP_CDSP_MIC_SEL_MASK; - vx_outb(chip, CDSP, chip->regCDSP); - break; - case VX_AUDIO_SRC_MIC: - chip->regCDSP &= ~VXP_CDSP_DATAIN_SEL_MASK; - /* reset mic levels */ - if (_chip->type == VX_TYPE_VXP440) { - chip->regCDSP &= ~P24_CDSP_MICS_SEL_MASK; - if (chip->mic_level) - chip->regCDSP |= P24_CDSP_MIC38_SEL_MASK; - else - chip->regCDSP |= P24_CDSP_MIC20_SEL_MASK; - vx_outb(chip, CDSP, chip->regCDSP); - } else { - chip->regCDSP |= VXP_CDSP_MIC_SEL_MASK; - vx_outb(chip, CDSP, chip->regCDSP); - vx_outb(chip, MICRO, vx_compute_mic_level(chip->mic_level)); - } - break; - } -} - -/* - * change the clock source - * source = INTERNAL_QUARTZ or UER_SYNC - */ -static void vxp_set_clock_source(struct vx_core *_chip, int source) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - if (source == INTERNAL_QUARTZ) - chip->regCDSP &= ~VXP_CDSP_CLOCKIN_SEL_MASK; - else - chip->regCDSP |= VXP_CDSP_CLOCKIN_SEL_MASK; - vx_outb(chip, CDSP, chip->regCDSP); -} - - -/* - * reset the board - */ -static void vxp_reset_board(struct vx_core *_chip, int cold_reset) -{ - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; - - chip->regCDSP = 0; - chip->regDIALOG = 0; -} - - -/* - * callbacks - */ -/* exported */ -struct snd_vx_ops snd_vxpocket_ops = { - .in8 = vxp_inb, - .out8 = vxp_outb, - .test_and_ack = vxp_test_and_ack, - .validate_irq = vxp_validate_irq, - .write_codec = vxp_write_codec_reg, - .reset_codec = vxp_reset_codec, - .change_audio_source = vxp_change_audio_source, - .set_clock_source = vxp_set_clock_source, - .load_dsp = vxp_load_dsp, - .add_controls = vxp_add_mic_controls, - .reset_dsp = vxp_reset_dsp, - .reset_board = vxp_reset_board, - .dma_write = vxp_dma_write, - .dma_read = vxp_dma_read, -}; diff --git a/ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.c b/ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.c deleted file mode 100644 index 512f0b47..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Driver for Digigram VXpocket V2/440 soundcards - * - * Copyright (c) 2002 by Takashi Iwai - - * 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 "vxpocket.h" -#include -#include -#include -#include - -/* - */ - -MODULE_AUTHOR("Takashi Iwai "); -MODULE_DESCRIPTION("Digigram VXPocket"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Digigram,VXPocket},{Digigram,VXPocket440}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ -static int ibl[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for VXPocket soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for VXPocket soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable VXPocket soundcard."); -module_param_array(ibl, int, NULL, 0444); -MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard."); - - -/* - */ - -static unsigned int card_alloc; - - -/* - */ -static void vxpocket_release(struct pcmcia_device *link) -{ - pcmcia_disable_device(link); -} - -/* - * destructor, called from snd_card_free_when_closed() - */ -static int snd_vxpocket_dev_free(struct snd_device *device) -{ - struct vx_core *chip = device->device_data; - - snd_vx_free_firmware(chip); - kfree(chip); - return 0; -} - - -/* - * Hardware information - */ - -/* VX-pocket V2 - * - * 1 DSP, 1 sync UER - * 1 programmable clock (NIY) - * 1 stereo analog input (line/micro) - * 1 stereo analog output - * Only output levels can be modified - */ - -static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0); - -static struct snd_vx_hardware vxpocket_hw = { - .name = "VXPocket", - .type = VX_TYPE_VXPOCKET, - - /* hardware specs */ - .num_codecs = 1, - .num_ins = 1, - .num_outs = 1, - .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, - .output_level_db_scale = db_scale_old_vol, -}; - -/* VX-pocket 440 - * - * 1 DSP, 1 sync UER, 1 sync World Clock (NIY) - * SMPTE (NIY) - * 2 stereo analog input (line/micro) - * 2 stereo analog output - * Only output levels can be modified - * UER, but only for the first two inputs and outputs. - */ - -static struct snd_vx_hardware vxp440_hw = { - .name = "VXPocket440", - .type = VX_TYPE_VXP440, - - /* hardware specs */ - .num_codecs = 2, - .num_ins = 2, - .num_outs = 2, - .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, - .output_level_db_scale = db_scale_old_vol, -}; - - -/* - * create vxpocket instance - */ -static int snd_vxpocket_new(struct snd_card *card, int ibl, - struct pcmcia_device *link, - struct snd_vxpocket **chip_ret) -{ - struct vx_core *chip; - struct snd_vxpocket *vxp; - static struct snd_device_ops ops = { - .dev_free = snd_vxpocket_dev_free, - }; - int err; - - chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, - sizeof(struct snd_vxpocket) - sizeof(struct vx_core)); - if (!chip) - return -ENOMEM; - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - kfree(chip); - return err; - } - chip->ibl.size = ibl; - - vxp = (struct snd_vxpocket *)chip; - - vxp->p_dev = link; - link->priv = chip; - - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - link->resource[0]->end = 16; - - link->config_flags |= CONF_ENABLE_IRQ; - link->config_index = 1; - link->config_regs = PRESENT_OPTION; - - *chip_ret = vxp; - return 0; -} - - -/** - * snd_vxpocket_assign_resources - initialize the hardware and card instance. - * @port: i/o port for the card - * @irq: irq number for the card - * - * this function assigns the specified port and irq, boot the card, - * create pcm and control instances, and initialize the rest hardware. - * - * returns 0 if successful, or a negative error code. - */ -static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq) -{ - int err; - struct snd_card *card = chip->card; - struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; - - snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); - vxp->port = port; - - sprintf(card->shortname, "Digigram %s", card->driver); - sprintf(card->longname, "%s at 0x%x, irq %i", - card->shortname, port, irq); - - chip->irq = irq; - - if ((err = snd_vx_setup_firmware(chip)) < 0) - return err; - - return 0; -} - - -/* - * configuration callback - */ - -static int vxpocket_config(struct pcmcia_device *link) -{ - struct vx_core *chip = link->priv; - int ret; - - snd_printdd(KERN_DEBUG "vxpocket_config called\n"); - - /* redefine hardware record according to the VERSION1 string */ - if (!strcmp(link->prod_id[1], "VX-POCKET")) { - snd_printdd("VX-pocket is detected\n"); - } else { - snd_printdd("VX-pocket 440 is detected\n"); - /* overwrite the hardware information */ - chip->hw = &vxp440_hw; - chip->type = vxp440_hw.type; - strcpy(chip->card->driver, vxp440_hw.name); - } - - ret = pcmcia_request_io(link); - if (ret) - goto failed; - - ret = pcmcia_request_irq(link, snd_vx_irq_handler); - if (ret) - goto failed; - - ret = pcmcia_enable_device(link); - if (ret) - goto failed; - - chip->dev = &link->dev; - snd_card_set_dev(chip->card, chip->dev); - - if (snd_vxpocket_assign_resources(chip, link->resource[0]->start, - link->irq) < 0) - goto failed; - - return 0; - -failed: - pcmcia_disable_device(link); - return -ENODEV; -} - -#ifdef CONFIG_PM - -static int vxp_suspend(struct pcmcia_device *link) -{ - struct vx_core *chip = link->priv; - - snd_printdd(KERN_DEBUG "SUSPEND\n"); - if (chip) { - snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); - snd_vx_suspend(chip, PMSG_SUSPEND); - } - - return 0; -} - -static int vxp_resume(struct pcmcia_device *link) -{ - struct vx_core *chip = link->priv; - - snd_printdd(KERN_DEBUG "RESUME\n"); - if (pcmcia_dev_present(link)) { - //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; - if (chip) { - snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); - snd_vx_resume(chip); - } - } - snd_printdd(KERN_DEBUG "resume done!\n"); - - return 0; -} - -#endif - - -/* - */ -static int vxpocket_probe(struct pcmcia_device *p_dev) -{ - struct snd_card *card; - struct snd_vxpocket *vxp; - int i, err; - - /* find an empty slot from the card list */ - for (i = 0; i < SNDRV_CARDS; i++) { - if (!(card_alloc & (1 << i))) - break; - } - if (i >= SNDRV_CARDS) { - snd_printk(KERN_ERR "vxpocket: too many cards found\n"); - return -EINVAL; - } - if (! enable[i]) - return -ENODEV; /* disabled explicitly */ - - /* ok, create a card instance */ - err = snd_card_create(index[i], id[i], THIS_MODULE, 0, &card); - if (err < 0) { - snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); - return err; - } - - err = snd_vxpocket_new(card, ibl[i], p_dev, &vxp); - if (err < 0) { - snd_card_free(card); - return err; - } - card->private_data = vxp; - - vxp->index = i; - card_alloc |= 1 << i; - - vxp->p_dev = p_dev; - - return vxpocket_config(p_dev); -} - -static void vxpocket_detach(struct pcmcia_device *link) -{ - struct snd_vxpocket *vxp; - struct vx_core *chip; - - if (! link) - return; - - vxp = link->priv; - chip = (struct vx_core *)vxp; - card_alloc &= ~(1 << vxp->index); - - chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ - snd_card_disconnect(chip->card); - vxpocket_release(link); - snd_card_free_when_closed(chip->card); -} - -/* - * Module entry points - */ - -static const struct pcmcia_device_id vxp_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x01f1, 0x0100), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, vxp_ids); - -static struct pcmcia_driver vxp_cs_driver = { - .owner = THIS_MODULE, - .name = "snd-vxpocket", - .probe = vxpocket_probe, - .remove = vxpocket_detach, - .id_table = vxp_ids, -#ifdef CONFIG_PM - .suspend = vxp_suspend, - .resume = vxp_resume, -#endif -}; - -static int __init init_vxpocket(void) -{ - return pcmcia_register_driver(&vxp_cs_driver); -} - -static void __exit exit_vxpocket(void) -{ - pcmcia_unregister_driver(&vxp_cs_driver); -} - -module_init(init_vxpocket); -module_exit(exit_vxpocket); diff --git a/ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.h b/ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.h deleted file mode 100644 index 13d658c1..00000000 --- a/ANDROID_3.4.5/sound/pcmcia/vx/vxpocket.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Driver for Digigram VXpocket soundcards - * - * Copyright (c) 2002 by Takashi Iwai - * - * 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 - */ - -#ifndef __VXPOCKET_H -#define __VXPOCKET_H - -#include - -#include -#include - -struct snd_vxpocket { - - struct vx_core core; - - unsigned long port; - - int mic_level; /* analog mic level (or boost) */ - - unsigned int regCDSP; /* current CDSP register */ - unsigned int regDIALOG; /* current DIALOG register */ - - int index; /* card index */ - - /* pcmcia stuff */ - struct pcmcia_device *p_dev; -}; - -extern struct snd_vx_ops snd_vxpocket_ops; - -void vx_set_mic_boost(struct vx_core *chip, int boost); -void vx_set_mic_level(struct vx_core *chip, int level); - -int vxp_add_mic_controls(struct vx_core *chip); - -/* Constants used to access the CDSP register (0x08). */ -#define CDSP_MAGIC 0xA7 /* magic value (for read) */ -/* for write */ -#define VXP_CDSP_CLOCKIN_SEL_MASK 0x80 /* 0 (internal), 1 (AES/EBU) */ -#define VXP_CDSP_DATAIN_SEL_MASK 0x40 /* 0 (analog), 1 (UER) */ -#define VXP_CDSP_SMPTE_SEL_MASK 0x20 -#define VXP_CDSP_RESERVED_MASK 0x10 -#define VXP_CDSP_MIC_SEL_MASK 0x08 -#define VXP_CDSP_VALID_IRQ_MASK 0x04 -#define VXP_CDSP_CODEC_RESET_MASK 0x02 -#define VXP_CDSP_DSP_RESET_MASK 0x01 -/* VXPOCKET 240/440 */ -#define P24_CDSP_MICS_SEL_MASK 0x18 -#define P24_CDSP_MIC20_SEL_MASK 0x10 -#define P24_CDSP_MIC38_SEL_MASK 0x08 - -/* Constants used to access the MEMIRQ register (0x0C). */ -#define P44_MEMIRQ_MASTER_SLAVE_SEL_MASK 0x08 -#define P44_MEMIRQ_SYNCED_ALONE_SEL_MASK 0x04 -#define P44_MEMIRQ_WCLK_OUT_IN_SEL_MASK 0x02 /* Not used */ -#define P44_MEMIRQ_WCLK_UER_SEL_MASK 0x01 /* Not used */ - -/* Micro levels (0x0C) */ - -/* Constants used to access the DIALOG register (0x0D). */ -#define VXP_DLG_XILINX_REPROG_MASK 0x80 /* W */ -#define VXP_DLG_DATA_XICOR_MASK 0x80 /* R */ -#define VXP_DLG_RESERVED4_0_MASK 0x40 -#define VXP_DLG_RESERVED2_0_MASK 0x20 -#define VXP_DLG_RESERVED1_0_MASK 0x10 -#define VXP_DLG_DMAWRITE_SEL_MASK 0x08 /* W */ -#define VXP_DLG_DMAREAD_SEL_MASK 0x04 /* W */ -#define VXP_DLG_MEMIRQ_MASK 0x02 /* R */ -#define VXP_DLG_DMA16_SEL_MASK 0x02 /* W */ -#define VXP_DLG_ACK_MEMIRQ_MASK 0x01 /* R/W */ - - -#endif /* __VXPOCKET_H */ diff --git a/ANDROID_3.4.5/sound/ppc/Kconfig b/ANDROID_3.4.5/sound/ppc/Kconfig deleted file mode 100644 index 0519c60f..00000000 --- a/ANDROID_3.4.5/sound/ppc/Kconfig +++ /dev/null @@ -1,52 +0,0 @@ -# ALSA PowerMac drivers - -menuconfig SND_PPC - bool "PowerPC sound devices" - depends on PPC - default y - help - Support for sound devices specific to PowerPC architectures. - -if SND_PPC - -config SND_POWERMAC - tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)" - depends on I2C && INPUT && PPC_PMAC - select SND_PCM - select SND_VMASTER - help - Say Y here to include support for the integrated sound device. - - To compile this driver as a module, choose M here: the module - will be called snd-powermac. - -config SND_POWERMAC_AUTO_DRC - bool "Toggle DRC automatically at headphone/line plug-in" - depends on SND_POWERMAC - default y - help - Say Y here to enable the automatic toggle of DRC (dynamic - range compression) on Tumbler/Snapper. - If this feature is enabled, DRC is turned off when the - headphone/line jack is plugged, and turned on when unplugged. - - Note that you can turn on/off DRC manually even without this - option. - -config SND_PS3 - tristate "PS3 Audio support" - depends on PS3_PS3AV - select SND_PCM - default m - help - Say Y here to include support for audio on the PS3 - - To compile this driver as a module, choose M here: the module - will be called snd_ps3. - -config SND_PS3_DEFAULT_START_DELAY - int "Startup delay time in ms" - depends on SND_PS3 - default "2000" - -endif # SND_PPC diff --git a/ANDROID_3.4.5/sound/ppc/Makefile b/ANDROID_3.4.5/sound/ppc/Makefile deleted file mode 100644 index 679c45a8..00000000 --- a/ANDROID_3.4.5/sound/ppc/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela -# - -snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o -obj-$(CONFIG_SND_PS3) += snd_ps3.o diff --git a/ANDROID_3.4.5/sound/ppc/awacs.c b/ANDROID_3.4.5/sound/ppc/awacs.c deleted file mode 100644 index b3667938..00000000 --- a/ANDROID_3.4.5/sound/ppc/awacs.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * PMac AWACS lowlevel functions - * - * Copyright (c) by Takashi Iwai - * code based on dmasound.c. - * - * 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 "pmac.h" - - -#ifdef CONFIG_ADB_CUDA -#define PMAC_AMP_AVAIL -#endif - -#ifdef PMAC_AMP_AVAIL -struct awacs_amp { - unsigned char amp_master; - unsigned char amp_vol[2][2]; - unsigned char amp_tone[2]; -}; - -#define CHECK_CUDA_AMP() (sys_ctrler == SYS_CTRLER_CUDA) - -#endif /* PMAC_AMP_AVAIL */ - - -static void snd_pmac_screamer_wait(struct snd_pmac *chip) -{ - long timeout = 2000; - while (!(in_le32(&chip->awacs->codec_stat) & MASK_VALID)) { - mdelay(1); - if (! --timeout) { - snd_printd("snd_pmac_screamer_wait timeout\n"); - break; - } - } -} - -/* - * write AWACS register - */ -static void -snd_pmac_awacs_write(struct snd_pmac *chip, int val) -{ - long timeout = 5000000; - - if (chip->model == PMAC_SCREAMER) - snd_pmac_screamer_wait(chip); - out_le32(&chip->awacs->codec_ctrl, val | (chip->subframe << 22)); - while (in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) { - if (! --timeout) { - snd_printd("snd_pmac_awacs_write timeout\n"); - break; - } - } -} - -static void -snd_pmac_awacs_write_reg(struct snd_pmac *chip, int reg, int val) -{ - snd_pmac_awacs_write(chip, val | (reg << 12)); - chip->awacs_reg[reg] = val; -} - -static void -snd_pmac_awacs_write_noreg(struct snd_pmac *chip, int reg, int val) -{ - snd_pmac_awacs_write(chip, val | (reg << 12)); -} - -#ifdef CONFIG_PM -/* Recalibrate chip */ -static void screamer_recalibrate(struct snd_pmac *chip) -{ - if (chip->model != PMAC_SCREAMER) - return; - - /* Sorry for the horrible delays... I hope to get that improved - * by making the whole PM process asynchronous in a future version - */ - snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); - if (chip->manufacturer == 0x1) - /* delay for broken crystal part */ - msleep(750); - snd_pmac_awacs_write_noreg(chip, 1, - chip->awacs_reg[1] | MASK_RECALIBRATE | - MASK_CMUTE | MASK_AMUTE); - snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); - snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]); -} - -#else -#define screamer_recalibrate(chip) /* NOP */ -#endif - - -/* - * additional callback to set the pcm format - */ -static void snd_pmac_awacs_set_format(struct snd_pmac *chip) -{ - chip->awacs_reg[1] &= ~MASK_SAMPLERATE; - chip->awacs_reg[1] |= chip->rate_index << 3; - snd_pmac_awacs_write_reg(chip, 1, chip->awacs_reg[1]); -} - - -/* - * AWACS volume callbacks - */ -/* - * volumes: 0-15 stereo - */ -static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 15; - return 0; -} - -static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int lshift = (kcontrol->private_value >> 8) & 0xff; - int inverted = (kcontrol->private_value >> 16) & 1; - unsigned long flags; - int vol[2]; - - spin_lock_irqsave(&chip->reg_lock, flags); - vol[0] = (chip->awacs_reg[reg] >> lshift) & 0xf; - vol[1] = chip->awacs_reg[reg] & 0xf; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (inverted) { - vol[0] = 0x0f - vol[0]; - vol[1] = 0x0f - vol[1]; - } - ucontrol->value.integer.value[0] = vol[0]; - ucontrol->value.integer.value[1] = vol[1]; - return 0; -} - -static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int lshift = (kcontrol->private_value >> 8) & 0xff; - int inverted = (kcontrol->private_value >> 16) & 1; - int val, oldval; - unsigned long flags; - unsigned int vol[2]; - - vol[0] = ucontrol->value.integer.value[0]; - vol[1] = ucontrol->value.integer.value[1]; - if (vol[0] > 0x0f || vol[1] > 0x0f) - return -EINVAL; - if (inverted) { - vol[0] = 0x0f - vol[0]; - vol[1] = 0x0f - vol[1]; - } - vol[0] &= 0x0f; - vol[1] &= 0x0f; - spin_lock_irqsave(&chip->reg_lock, flags); - oldval = chip->awacs_reg[reg]; - val = oldval & ~(0xf | (0xf << lshift)); - val |= vol[0] << lshift; - val |= vol[1]; - if (oldval != val) - snd_pmac_awacs_write_reg(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return oldval != reg; -} - - -#define AWACS_VOLUME(xname, xreg, xshift, xinverted) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = snd_pmac_awacs_info_volume, \ - .get = snd_pmac_awacs_get_volume, \ - .put = snd_pmac_awacs_put_volume, \ - .private_value = (xreg) | ((xshift) << 8) | ((xinverted) << 16) } - -/* - * mute master/ogain for AWACS: mono - */ -static int snd_pmac_awacs_get_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int invert = (kcontrol->private_value >> 16) & 1; - int val; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->awacs_reg[reg] >> shift) & 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - val = 1 - val; - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int invert = (kcontrol->private_value >> 16) & 1; - int mask = 1 << shift; - int val, changed; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - val = chip->awacs_reg[reg] & ~mask; - if (ucontrol->value.integer.value[0] != invert) - val |= mask; - changed = chip->awacs_reg[reg] != val; - if (changed) - snd_pmac_awacs_write_reg(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return changed; -} - -#define AWACS_SWITCH(xname, xreg, xshift, xinvert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = snd_pmac_boolean_mono_info, \ - .get = snd_pmac_awacs_get_switch, \ - .put = snd_pmac_awacs_put_switch, \ - .private_value = (xreg) | ((xshift) << 8) | ((xinvert) << 16) } - - -#ifdef PMAC_AMP_AVAIL -/* - * controls for perch/whisper extension cards, e.g. G3 desktop - * - * TDA7433 connected via i2c address 0x45 (= 0x8a), - * accessed through cuda - */ -static void awacs_set_cuda(int reg, int val) -{ - struct adb_request req; - cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, - reg, val); - while (! req.complete) - cuda_poll(); -} - -/* - * level = 0 - 14, 7 = 0 dB - */ -static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble) -{ - amp->amp_tone[0] = bass; - amp->amp_tone[1] = treble; - if (bass > 7) - bass = (14 - bass) + 8; - if (treble > 7) - treble = (14 - treble) + 8; - awacs_set_cuda(2, (bass << 4) | treble); -} - -/* - * vol = 0 - 31 (attenuation), 32 = mute bit, stereo - */ -static int awacs_amp_set_vol(struct awacs_amp *amp, int index, - int lvol, int rvol, int do_check) -{ - if (do_check && amp->amp_vol[index][0] == lvol && - amp->amp_vol[index][1] == rvol) - return 0; - awacs_set_cuda(3 + index, lvol); - awacs_set_cuda(5 + index, rvol); - amp->amp_vol[index][0] = lvol; - amp->amp_vol[index][1] = rvol; - return 1; -} - -/* - * 0 = -79 dB, 79 = 0 dB, 99 = +20 dB - */ -static void awacs_amp_set_master(struct awacs_amp *amp, int vol) -{ - amp->amp_master = vol; - if (vol <= 79) - vol = 32 + (79 - vol); - else - vol = 32 - (vol - 79); - awacs_set_cuda(1, vol); -} - -static void awacs_amp_free(struct snd_pmac *chip) -{ - struct awacs_amp *amp = chip->mixer_data; - if (!amp) - return; - kfree(amp); - chip->mixer_data = NULL; - chip->mixer_free = NULL; -} - - -/* - * mixer controls - */ -static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 31; - return 0; -} - -static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - struct awacs_amp *amp = chip->mixer_data; - - ucontrol->value.integer.value[0] = 31 - (amp->amp_vol[index][0] & 31); - ucontrol->value.integer.value[1] = 31 - (amp->amp_vol[index][1] & 31); - return 0; -} - -static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - int vol[2]; - struct awacs_amp *amp = chip->mixer_data; - - vol[0] = (31 - (ucontrol->value.integer.value[0] & 31)) - | (amp->amp_vol[index][0] & 32); - vol[1] = (31 - (ucontrol->value.integer.value[1] & 31)) - | (amp->amp_vol[index][1] & 32); - return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1); -} - -static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - struct awacs_amp *amp = chip->mixer_data; - - ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) - ? 0 : 1; - ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32) - ? 0 : 1; - return 0; -} - -static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - int vol[2]; - struct awacs_amp *amp = chip->mixer_data; - - vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32) - | (amp->amp_vol[index][0] & 31); - vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32) - | (amp->amp_vol[index][1] & 31); - return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1); -} - -static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 14; - return 0; -} - -static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - struct awacs_amp *amp = chip->mixer_data; - - ucontrol->value.integer.value[0] = amp->amp_tone[index]; - return 0; -} - -static int snd_pmac_awacs_put_tone_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int index = kcontrol->private_value; - struct awacs_amp *amp = chip->mixer_data; - unsigned int val; - - val = ucontrol->value.integer.value[0]; - if (val > 14) - return -EINVAL; - if (val != amp->amp_tone[index]) { - amp->amp_tone[index] = val; - awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]); - return 1; - } - return 0; -} - -static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 99; - return 0; -} - -static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct awacs_amp *amp = chip->mixer_data; - - ucontrol->value.integer.value[0] = amp->amp_master; - return 0; -} - -static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct awacs_amp *amp = chip->mixer_data; - unsigned int val; - - val = ucontrol->value.integer.value[0]; - if (val > 99) - return -EINVAL; - if (val != amp->amp_master) { - amp->amp_master = val; - awacs_amp_set_master(amp, amp->amp_master); - return 1; - } - return 0; -} - -#define AMP_CH_SPK 0 -#define AMP_CH_HD 1 - -static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Speaker Playback Volume", - .info = snd_pmac_awacs_info_volume_amp, - .get = snd_pmac_awacs_get_volume_amp, - .put = snd_pmac_awacs_put_volume_amp, - .private_value = AMP_CH_SPK, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Volume", - .info = snd_pmac_awacs_info_volume_amp, - .get = snd_pmac_awacs_get_volume_amp, - .put = snd_pmac_awacs_put_volume_amp, - .private_value = AMP_CH_HD, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Tone Control - Bass", - .info = snd_pmac_awacs_info_tone_amp, - .get = snd_pmac_awacs_get_tone_amp, - .put = snd_pmac_awacs_put_tone_amp, - .private_value = 0, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Tone Control - Treble", - .info = snd_pmac_awacs_info_tone_amp, - .get = snd_pmac_awacs_get_tone_amp, - .put = snd_pmac_awacs_put_tone_amp, - .private_value = 1, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Amp Master Playback Volume", - .info = snd_pmac_awacs_info_master_amp, - .get = snd_pmac_awacs_get_master_amp, - .put = snd_pmac_awacs_put_master_amp, - }, -}; - -static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Switch", - .info = snd_pmac_boolean_stereo_info, - .get = snd_pmac_awacs_get_switch_amp, - .put = snd_pmac_awacs_put_switch_amp, - .private_value = AMP_CH_HD, -}; - -static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Speaker Playback Switch", - .info = snd_pmac_boolean_stereo_info, - .get = snd_pmac_awacs_get_switch_amp, - .put = snd_pmac_awacs_put_switch_amp, - .private_value = AMP_CH_SPK, -}; - -#endif /* PMAC_AMP_AVAIL */ - - -/* - * mic boost for screamer - */ -static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 3; - return 0; -} - -static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int val = 0; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->awacs_reg[6] & MASK_MIC_BOOST) - val |= 2; - if (chip->awacs_reg[0] & MASK_GAINLINE) - val |= 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - int changed = 0; - int val0, val6; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - val0 = chip->awacs_reg[0] & ~MASK_GAINLINE; - val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST; - if (ucontrol->value.integer.value[0] & 1) - val0 |= MASK_GAINLINE; - if (ucontrol->value.integer.value[0] & 2) - val6 |= MASK_MIC_BOOST; - if (val0 != chip->awacs_reg[0]) { - snd_pmac_awacs_write_reg(chip, 0, val0); - changed = 1; - } - if (val6 != chip->awacs_reg[6]) { - snd_pmac_awacs_write_reg(chip, 6, val6); - changed = 1; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return changed; -} - -/* - * lists of mixer elements - */ -static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __devinitdata = { - AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0), - AWACS_VOLUME("Master Capture Volume", 0, 4, 0), -/* AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */ -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __devinitdata = { - AWACS_VOLUME("Master Playback Volume", 2, 6, 1), - AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1), - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __devinitdata = { - AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __devinitdata = { - AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] __devinitdata = { - AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), - AWACS_VOLUME("Master Playback Volume", 5, 6, 1), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __devinitdata = { - AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __devinitdata = { - AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __devinitdata = { - AWACS_VOLUME("Master Playback Volume", 2, 6, 1), - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), -}; - -/* FIXME: is this correct order? - * screamer (powerbook G3 pismo) seems to have different bits... - */ -static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] __devinitdata = { - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0), - AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __devinitdata = { - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), - AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __devinitdata = { - AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_master_sw __devinitdata = -AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __devinitdata = -AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 __devinitdata = -AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __devinitdata = { - AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Boost Capture Volume", - .info = snd_pmac_screamer_mic_boost_info, - .get = snd_pmac_screamer_mic_boost_get, - .put = snd_pmac_screamer_mic_boost_put, - }, -}; - -static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __devinitdata = -{ - AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __devinitdata = -{ - AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), - AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0), -}; - -static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __devinitdata = -{ - AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), - AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __devinitdata = { - AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1), -}; - -static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __devinitdata = -AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 __devinitdata = -AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1); - -static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 __devinitdata = -AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0); - - -/* - * add new mixer elements to the card - */ -static int build_mixers(struct snd_pmac *chip, int nums, - struct snd_kcontrol_new *mixers) -{ - int i, err; - - for (i = 0; i < nums; i++) { - err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip)); - if (err < 0) - return err; - } - return 0; -} - - -/* - * restore all registers - */ -static void awacs_restore_all_regs(struct snd_pmac *chip) -{ - snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]); - snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); - snd_pmac_awacs_write_noreg(chip, 2, chip->awacs_reg[2]); - snd_pmac_awacs_write_noreg(chip, 4, chip->awacs_reg[4]); - if (chip->model == PMAC_SCREAMER) { - snd_pmac_awacs_write_noreg(chip, 5, chip->awacs_reg[5]); - snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]); - snd_pmac_awacs_write_noreg(chip, 7, chip->awacs_reg[7]); - } -} - -#ifdef CONFIG_PM -static void snd_pmac_awacs_suspend(struct snd_pmac *chip) -{ - snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1] - | MASK_AMUTE | MASK_CMUTE)); -} - -static void snd_pmac_awacs_resume(struct snd_pmac *chip) -{ - if (of_machine_is_compatible("PowerBook3,1") - || of_machine_is_compatible("PowerBook3,2")) { - msleep(100); - snd_pmac_awacs_write_reg(chip, 1, - chip->awacs_reg[1] & ~MASK_PAROUT); - msleep(300); - } - - awacs_restore_all_regs(chip); - if (chip->model == PMAC_SCREAMER) { - /* reset power bits in reg 6 */ - mdelay(5); - snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]); - } - screamer_recalibrate(chip); -#ifdef PMAC_AMP_AVAIL - if (chip->mixer_data) { - struct awacs_amp *amp = chip->mixer_data; - awacs_amp_set_vol(amp, 0, - amp->amp_vol[0][0], amp->amp_vol[0][1], 0); - awacs_amp_set_vol(amp, 1, - amp->amp_vol[1][0], amp->amp_vol[1][1], 0); - awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]); - awacs_amp_set_master(amp, amp->amp_master); - } -#endif -} -#endif /* CONFIG_PM */ - -#define IS_PM7500 (of_machine_is_compatible("AAPL,7500") \ - || of_machine_is_compatible("AAPL,8500") \ - || of_machine_is_compatible("AAPL,9500")) -#define IS_PM5500 (of_machine_is_compatible("AAPL,e411")) -#define IS_BEIGE (of_machine_is_compatible("AAPL,Gossamer")) -#define IS_IMAC1 (of_machine_is_compatible("PowerMac2,1")) -#define IS_IMAC2 (of_machine_is_compatible("PowerMac2,2") \ - || of_machine_is_compatible("PowerMac4,1")) -#define IS_G4AGP (of_machine_is_compatible("PowerMac3,1")) -#define IS_LOMBARD (of_machine_is_compatible("PowerBook1,1")) - -static int imac1, imac2; - -#ifdef PMAC_SUPPORT_AUTOMUTE -/* - * auto-mute stuffs - */ -static int snd_pmac_awacs_detect_headphone(struct snd_pmac *chip) -{ - return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0; -} - -#ifdef PMAC_AMP_AVAIL -static int toggle_amp_mute(struct awacs_amp *amp, int index, int mute) -{ - int vol[2]; - vol[0] = amp->amp_vol[index][0] & 31; - vol[1] = amp->amp_vol[index][1] & 31; - if (mute) { - vol[0] |= 32; - vol[1] |= 32; - } - return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1); -} -#endif - -static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify) -{ - if (chip->auto_mute) { -#ifdef PMAC_AMP_AVAIL - if (chip->mixer_data) { - struct awacs_amp *amp = chip->mixer_data; - int changed; - if (snd_pmac_awacs_detect_headphone(chip)) { - changed = toggle_amp_mute(amp, AMP_CH_HD, 0); - changed |= toggle_amp_mute(amp, AMP_CH_SPK, 1); - } else { - changed = toggle_amp_mute(amp, AMP_CH_HD, 1); - changed |= toggle_amp_mute(amp, AMP_CH_SPK, 0); - } - if (do_notify && ! changed) - return; - } else -#endif - { - int reg = chip->awacs_reg[1] - | (MASK_HDMUTE | MASK_SPKMUTE); - if (imac1) { - reg &= ~MASK_SPKMUTE; - reg |= MASK_PAROUT1; - } else if (imac2) { - reg &= ~MASK_SPKMUTE; - reg &= ~MASK_PAROUT1; - } - if (snd_pmac_awacs_detect_headphone(chip)) - reg &= ~MASK_HDMUTE; - else if (imac1) - reg &= ~MASK_PAROUT1; - else if (imac2) - reg |= MASK_PAROUT1; - else - reg &= ~MASK_SPKMUTE; - if (do_notify && reg == chip->awacs_reg[1]) - return; - snd_pmac_awacs_write_reg(chip, 1, reg); - } - if (do_notify) { - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_sw_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->speaker_sw_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hp_detect_ctl->id); - } - } -} -#endif /* PMAC_SUPPORT_AUTOMUTE */ - - -/* - * initialize chip - */ -int __devinit -snd_pmac_awacs_init(struct snd_pmac *chip) -{ - int pm7500 = IS_PM7500; - int pm5500 = IS_PM5500; - int beige = IS_BEIGE; - int g4agp = IS_G4AGP; - int lombard = IS_LOMBARD; - int imac; - int err, vol; - struct snd_kcontrol *vmaster_sw, *vmaster_vol; - struct snd_kcontrol *master_vol, *speaker_vol; - - imac1 = IS_IMAC1; - imac2 = IS_IMAC2; - imac = imac1 || imac2; - /* looks like MASK_GAINLINE triggers something, so we set here - * as start-up - */ - chip->awacs_reg[0] = MASK_MUX_CD | 0xff | MASK_GAINLINE; - chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE; - /* FIXME: Only machines with external SRS module need MASK_PAROUT */ - if (chip->has_iic || chip->device_id == 0x5 || - /* chip->_device_id == 0x8 || */ - chip->device_id == 0xb) - chip->awacs_reg[1] |= MASK_PAROUT; - /* get default volume from nvram */ - // vol = (~nvram_read_byte(0x1308) & 7) << 1; - // vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 ); - vol = 0x0f; /* no, on alsa, muted as default */ - vol = vol + (vol << 6); - chip->awacs_reg[2] = vol; - chip->awacs_reg[4] = vol; - if (chip->model == PMAC_SCREAMER) { - /* FIXME: screamer has loopthru vol control */ - chip->awacs_reg[5] = vol; - /* FIXME: maybe should be vol << 3 for PCMCIA speaker */ - chip->awacs_reg[6] = MASK_MIC_BOOST; - chip->awacs_reg[7] = 0; - } - - awacs_restore_all_regs(chip); - chip->manufacturer = (in_le32(&chip->awacs->codec_stat) >> 8) & 0xf; - screamer_recalibrate(chip); - - chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf; -#ifdef PMAC_AMP_AVAIL - if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) { - struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL); - if (! amp) - return -ENOMEM; - chip->mixer_data = amp; - chip->mixer_free = awacs_amp_free; - /* mute and zero vol */ - awacs_amp_set_vol(amp, 0, 63, 63, 0); - awacs_amp_set_vol(amp, 1, 63, 63, 0); - awacs_amp_set_tone(amp, 7, 7); /* 0 dB */ - awacs_amp_set_master(amp, 79); /* 0 dB */ - } -#endif /* PMAC_AMP_AVAIL */ - - if (chip->hp_stat_mask == 0) { - /* set headphone-jack detection bit */ - switch (chip->model) { - case PMAC_AWACS: - chip->hp_stat_mask = pm7500 || pm5500 ? MASK_HDPCONN - : MASK_LOCONN; - break; - case PMAC_SCREAMER: - switch (chip->device_id) { - case 0x08: - case 0x0B: - chip->hp_stat_mask = imac - ? MASK_LOCONN_IMAC | - MASK_HDPLCONN_IMAC | - MASK_HDPRCONN_IMAC - : MASK_HDPCONN; - break; - case 0x00: - case 0x05: - chip->hp_stat_mask = MASK_LOCONN; - break; - default: - chip->hp_stat_mask = MASK_HDPCONN; - break; - } - break; - default: - snd_BUG(); - break; - } - } - - /* - * build mixers - */ - strcpy(chip->card->mixername, "PowerMac AWACS"); - - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers), - snd_pmac_awacs_mixers); - if (err < 0) - return err; - if (beige || g4agp) - ; - else if (chip->model == PMAC_SCREAMER || pm5500) - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2), - snd_pmac_screamer_mixers2); - else if (!pm7500) - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2), - snd_pmac_awacs_mixers2); - if (err < 0) - return err; - if (pm5500) { - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_awacs_mixers2_pmac5500), - snd_pmac_awacs_mixers2_pmac5500); - if (err < 0) - return err; - } - if (pm7500) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500), - snd_pmac_awacs_mixers_pmac7500); - else if (pm5500) - err = snd_ctl_add(chip->card, - (master_vol = snd_ctl_new1(snd_pmac_awacs_mixers_pmac5500, - chip))); - else if (beige) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mixers_beige), - snd_pmac_screamer_mixers_beige); - else if (imac || lombard) { - err = snd_ctl_add(chip->card, - (master_vol = snd_ctl_new1(snd_pmac_screamer_mixers_lo, - chip))); - if (err < 0) - return err; - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mixers_imac), - snd_pmac_screamer_mixers_imac); - } else if (g4agp) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp), - snd_pmac_screamer_mixers_g4agp); - else - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_awacs_mixers_pmac), - snd_pmac_awacs_mixers_pmac); - if (err < 0) - return err; - chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp || lombard) - ? &snd_pmac_awacs_master_sw_imac - : pm5500 - ? &snd_pmac_awacs_master_sw_pmac5500 - : &snd_pmac_awacs_master_sw, chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; -#ifdef PMAC_AMP_AVAIL - if (chip->mixer_data) { - /* use amplifier. the signal is connected from route A - * to the amp. the amp has its headphone and speaker - * volumes and mute switches, so we use them instead of - * screamer registers. - * in this case, it seems the route C is not used. - */ - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol), - snd_pmac_awacs_amp_vol); - if (err < 0) - return err; - /* overwrite */ - chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw, - chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; - chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw, - chip); - err = snd_ctl_add(chip->card, chip->speaker_sw_ctl); - if (err < 0) - return err; - } else -#endif /* PMAC_AMP_AVAIL */ - { - /* route A = headphone, route C = speaker */ - err = snd_ctl_add(chip->card, - (speaker_vol = snd_ctl_new1(snd_pmac_awacs_speaker_vol, - chip))); - if (err < 0) - return err; - chip->speaker_sw_ctl = snd_ctl_new1(imac1 - ? &snd_pmac_awacs_speaker_sw_imac1 - : imac2 - ? &snd_pmac_awacs_speaker_sw_imac2 - : &snd_pmac_awacs_speaker_sw, chip); - err = snd_ctl_add(chip->card, chip->speaker_sw_ctl); - if (err < 0) - return err; - } - - if (pm5500 || imac || lombard) { - vmaster_sw = snd_ctl_make_virtual_master( - "Master Playback Switch", (unsigned int *) NULL); - err = snd_ctl_add_slave_uncached(vmaster_sw, - chip->master_sw_ctl); - if (err < 0) - return err; - err = snd_ctl_add_slave_uncached(vmaster_sw, - chip->speaker_sw_ctl); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, vmaster_sw); - if (err < 0) - return err; - vmaster_vol = snd_ctl_make_virtual_master( - "Master Playback Volume", (unsigned int *) NULL); - err = snd_ctl_add_slave(vmaster_vol, master_vol); - if (err < 0) - return err; - err = snd_ctl_add_slave(vmaster_vol, speaker_vol); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, vmaster_vol); - if (err < 0) - return err; - } - - if (beige || g4agp) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige), - snd_pmac_screamer_mic_boost_beige); - else if (imac) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac), - snd_pmac_screamer_mic_boost_imac); - else if (chip->model == PMAC_SCREAMER) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_screamer_mic_boost), - snd_pmac_screamer_mic_boost); - else if (pm7500) - err = build_mixers(chip, - ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500), - snd_pmac_awacs_mic_boost_pmac7500); - else - err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost), - snd_pmac_awacs_mic_boost); - if (err < 0) - return err; - - /* - * set lowlevel callbacks - */ - chip->set_format = snd_pmac_awacs_set_format; -#ifdef CONFIG_PM - chip->suspend = snd_pmac_awacs_suspend; - chip->resume = snd_pmac_awacs_resume; -#endif -#ifdef PMAC_SUPPORT_AUTOMUTE - err = snd_pmac_add_automute(chip); - if (err < 0) - return err; - chip->detect_headphone = snd_pmac_awacs_detect_headphone; - chip->update_automute = snd_pmac_awacs_update_automute; - snd_pmac_awacs_update_automute(chip, 0); /* update the status only */ -#endif - if (chip->model == PMAC_SCREAMER) { - snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]); - snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]); - } - - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/awacs.h b/ANDROID_3.4.5/sound/ppc/awacs.h deleted file mode 100644 index c33e6a53..00000000 --- a/ANDROID_3.4.5/sound/ppc/awacs.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Driver for PowerMac AWACS onboard soundchips - * Copyright (c) 2001 by Takashi Iwai - * based on dmasound.c. - * - * 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 - */ - - -#ifndef __AWACS_H -#define __AWACS_H - -/*******************************/ -/* AWACs Audio Register Layout */ -/*******************************/ - -struct awacs_regs { - unsigned control; /* Audio control register */ - unsigned pad0[3]; - unsigned codec_ctrl; /* Codec control register */ - unsigned pad1[3]; - unsigned codec_stat; /* Codec status register */ - unsigned pad2[3]; - unsigned clip_count; /* Clipping count register */ - unsigned pad3[3]; - unsigned byteswap; /* Data is little-endian if 1 */ -}; - -/*******************/ -/* Audio Bit Masks */ -/*******************/ - -/* Audio Control Reg Bit Masks */ -/* ----- ------- --- --- ----- */ -#define MASK_ISFSEL (0xf) /* Input SubFrame Select */ -#define MASK_OSFSEL (0xf << 4) /* Output SubFrame Select */ -#define MASK_RATE (0x7 << 8) /* Sound Rate */ -#define MASK_CNTLERR (0x1 << 11) /* Error */ -#define MASK_PORTCHG (0x1 << 12) /* Port Change */ -#define MASK_IEE (0x1 << 13) /* Enable Interrupt on Error */ -#define MASK_IEPC (0x1 << 14) /* Enable Interrupt on Port Change */ -#define MASK_SSFSEL (0x3 << 15) /* Status SubFrame Select */ - -/* Audio Codec Control Reg Bit Masks */ -/* ----- ----- ------- --- --- ----- */ -#define MASK_NEWECMD (0x1 << 24) /* Lock: don't write to reg when 1 */ -#define MASK_EMODESEL (0x3 << 22) /* Send info out on which frame? */ -#define MASK_EXMODEADDR (0x3ff << 12) /* Extended Mode Address -- 10 bits */ -#define MASK_EXMODEDATA (0xfff) /* Extended Mode Data -- 12 bits */ - -/* Audio Codec Control Address Values / Masks */ -/* ----- ----- ------- ------- ------ - ----- */ -#define MASK_ADDR0 (0x0 << 12) /* Expanded Data Mode Address 0 */ -#define MASK_ADDR_MUX MASK_ADDR0 /* Mux Control */ -#define MASK_ADDR_GAIN MASK_ADDR0 - -#define MASK_ADDR1 (0x1 << 12) /* Expanded Data Mode Address 1 */ -#define MASK_ADDR_MUTE MASK_ADDR1 -#define MASK_ADDR_RATE MASK_ADDR1 - -#define MASK_ADDR2 (0x2 << 12) /* Expanded Data Mode Address 2 */ -#define MASK_ADDR_VOLA MASK_ADDR2 /* Volume Control A -- Headphones */ -#define MASK_ADDR_VOLHD MASK_ADDR2 - -#define MASK_ADDR4 (0x4 << 12) /* Expanded Data Mode Address 4 */ -#define MASK_ADDR_VOLC MASK_ADDR4 /* Volume Control C -- Speaker */ -#define MASK_ADDR_VOLSPK MASK_ADDR4 - -/* additional registers of screamer */ -#define MASK_ADDR5 (0x5 << 12) /* Expanded Data Mode Address 5 */ -#define MASK_ADDR6 (0x6 << 12) /* Expanded Data Mode Address 6 */ -#define MASK_ADDR7 (0x7 << 12) /* Expanded Data Mode Address 7 */ - -/* Address 0 Bit Masks & Macros */ -/* ------- - --- ----- - ------ */ -#define MASK_GAINRIGHT (0xf) /* Gain Right Mask */ -#define MASK_GAINLEFT (0xf << 4) /* Gain Left Mask */ -#define MASK_GAINLINE (0x1 << 8) /* Disable Mic preamp */ -#define MASK_GAINMIC (0x0 << 8) /* Enable Mic preamp */ -#define MASK_MUX_CD (0x1 << 9) /* Select CD in MUX */ -#define MASK_MUX_MIC (0x1 << 10) /* Select Mic in MUX */ -#define MASK_MUX_AUDIN (0x1 << 11) /* Select Audio In in MUX */ -#define MASK_MUX_LINE MASK_MUX_AUDIN -#define SHIFT_GAINLINE 8 -#define SHIFT_MUX_CD 9 -#define SHIFT_MUX_MIC 10 -#define SHIFT_MUX_LINE 11 - -#define GAINRIGHT(x) ((x) & MASK_GAINRIGHT) -#define GAINLEFT(x) (((x) << 4) & MASK_GAINLEFT) - -/* Address 1 Bit Masks */ -/* ------- - --- ----- */ -#define MASK_ADDR1RES1 (0x3) /* Reserved */ -#define MASK_RECALIBRATE (0x1 << 2) /* Recalibrate */ -#define MASK_SAMPLERATE (0x7 << 3) /* Sample Rate: */ -#define MASK_LOOPTHRU (0x1 << 6) /* Loopthrough Enable */ -#define SHIFT_LOOPTHRU 6 -#define MASK_CMUTE (0x1 << 7) /* Output C (Speaker) Mute when 1 */ -#define MASK_SPKMUTE MASK_CMUTE -#define SHIFT_SPKMUTE 7 -#define MASK_ADDR1RES2 (0x1 << 8) /* Reserved */ -#define MASK_AMUTE (0x1 << 9) /* Output A (Headphone) Mute when 1 */ -#define MASK_HDMUTE MASK_AMUTE -#define SHIFT_HDMUTE 9 -#define MASK_PAROUT (0x3 << 10) /* Parallel Out (???) */ -#define MASK_PAROUT0 (0x1 << 10) /* Parallel Out (???) */ -#define MASK_PAROUT1 (0x1 << 11) /* Parallel Out (enable speaker) */ -#define SHIFT_PAROUT 10 -#define SHIFT_PAROUT0 10 -#define SHIFT_PAROUT1 11 - -#define SAMPLERATE_48000 (0x0 << 3) /* 48 or 44.1 kHz */ -#define SAMPLERATE_32000 (0x1 << 3) /* 32 or 29.4 kHz */ -#define SAMPLERATE_24000 (0x2 << 3) /* 24 or 22.05 kHz */ -#define SAMPLERATE_19200 (0x3 << 3) /* 19.2 or 17.64 kHz */ -#define SAMPLERATE_16000 (0x4 << 3) /* 16 or 14.7 kHz */ -#define SAMPLERATE_12000 (0x5 << 3) /* 12 or 11.025 kHz */ -#define SAMPLERATE_9600 (0x6 << 3) /* 9.6 or 8.82 kHz */ -#define SAMPLERATE_8000 (0x7 << 3) /* 8 or 7.35 kHz */ - -/* Address 2 & 4 Bit Masks & Macros */ -/* ------- - - - --- ----- - ------ */ -#define MASK_OUTVOLRIGHT (0xf) /* Output Right Volume */ -#define MASK_ADDR2RES1 (0x2 << 4) /* Reserved */ -#define MASK_ADDR4RES1 MASK_ADDR2RES1 -#define MASK_OUTVOLLEFT (0xf << 6) /* Output Left Volume */ -#define MASK_ADDR2RES2 (0x2 << 10) /* Reserved */ -#define MASK_ADDR4RES2 MASK_ADDR2RES2 - -#define VOLRIGHT(x) (((~(x)) & MASK_OUTVOLRIGHT)) -#define VOLLEFT(x) (((~(x)) << 6) & MASK_OUTVOLLEFT) - -/* address 6 */ -#define MASK_MIC_BOOST (0x4) /* screamer mic boost */ -#define SHIFT_MIC_BOOST 2 - -/* Audio Codec Status Reg Bit Masks */ -/* ----- ----- ------ --- --- ----- */ -#define MASK_EXTEND (0x1 << 23) /* Extend */ -#define MASK_VALID (0x1 << 22) /* Valid Data? */ -#define MASK_OFLEFT (0x1 << 21) /* Overflow Left */ -#define MASK_OFRIGHT (0x1 << 20) /* Overflow Right */ -#define MASK_ERRCODE (0xf << 16) /* Error Code */ -#define MASK_REVISION (0xf << 12) /* Revision Number */ -#define MASK_MFGID (0xf << 8) /* Mfg. ID */ -#define MASK_CODSTATRES (0xf << 4) /* bits 4 - 7 reserved */ -#define MASK_INSENSE (0xf) /* port sense bits: */ -#define MASK_HDPCONN 8 /* headphone plugged in */ -#define MASK_LOCONN 4 /* line-out plugged in */ -#define MASK_LICONN 2 /* line-in plugged in */ -#define MASK_MICCONN 1 /* microphone plugged in */ -#define MASK_LICONN_IMAC 8 /* line-in plugged in */ -#define MASK_HDPRCONN_IMAC 4 /* headphone right plugged in */ -#define MASK_HDPLCONN_IMAC 2 /* headphone left plugged in */ -#define MASK_LOCONN_IMAC 1 /* line-out plugged in */ - -/* Clipping Count Reg Bit Masks */ -/* -------- ----- --- --- ----- */ -#define MASK_CLIPLEFT (0xff << 7) /* Clipping Count, Left Channel */ -#define MASK_CLIPRIGHT (0xff) /* Clipping Count, Right Channel */ - -/* DBDMA ChannelStatus Bit Masks */ -/* ----- ------------- --- ----- */ -#define MASK_CSERR (0x1 << 7) /* Error */ -#define MASK_EOI (0x1 << 6) /* End of Input -- - only for Input Channel */ -#define MASK_CSUNUSED (0x1f << 1) /* bits 1-5 not used */ -#define MASK_WAIT (0x1) /* Wait */ - -/* Various Rates */ -/* ------- ----- */ -#define RATE_48000 (0x0 << 8) /* 48 kHz */ -#define RATE_44100 (0x0 << 8) /* 44.1 kHz */ -#define RATE_32000 (0x1 << 8) /* 32 kHz */ -#define RATE_29400 (0x1 << 8) /* 29.4 kHz */ -#define RATE_24000 (0x2 << 8) /* 24 kHz */ -#define RATE_22050 (0x2 << 8) /* 22.05 kHz */ -#define RATE_19200 (0x3 << 8) /* 19.2 kHz */ -#define RATE_17640 (0x3 << 8) /* 17.64 kHz */ -#define RATE_16000 (0x4 << 8) /* 16 kHz */ -#define RATE_14700 (0x4 << 8) /* 14.7 kHz */ -#define RATE_12000 (0x5 << 8) /* 12 kHz */ -#define RATE_11025 (0x5 << 8) /* 11.025 kHz */ -#define RATE_9600 (0x6 << 8) /* 9.6 kHz */ -#define RATE_8820 (0x6 << 8) /* 8.82 kHz */ -#define RATE_8000 (0x7 << 8) /* 8 kHz */ -#define RATE_7350 (0x7 << 8) /* 7.35 kHz */ - -#define RATE_LOW 1 /* HIGH = 48kHz, etc; LOW = 44.1kHz, etc. */ - - -#endif /* __AWACS_H */ diff --git a/ANDROID_3.4.5/sound/ppc/beep.c b/ANDROID_3.4.5/sound/ppc/beep.c deleted file mode 100644 index a9d35078..00000000 --- a/ANDROID_3.4.5/sound/ppc/beep.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Beep using pcm - * - * Copyright (c) by Takashi Iwai - * - * 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 -#include "pmac.h" - -struct pmac_beep { - int running; /* boolean */ - int volume; /* mixer volume: 0-100 */ - int volume_play; /* currently playing volume */ - int hz; - int nsamples; - short *buf; /* allocated wave buffer */ - dma_addr_t addr; /* physical address of buffer */ - struct input_dev *dev; -}; - -/* - * stop beep if running - */ -void snd_pmac_beep_stop(struct snd_pmac *chip) -{ - struct pmac_beep *beep = chip->beep; - if (beep && beep->running) { - beep->running = 0; - snd_pmac_beep_dma_stop(chip); - } -} - -/* - * Stuff for outputting a beep. The values range from -327 to +327 - * so we can multiply by an amplitude in the range 0..100 to get a - * signed short value to put in the output buffer. - */ -static short beep_wform[256] = { - 0, 40, 79, 117, 153, 187, 218, 245, - 269, 288, 304, 316, 323, 327, 327, 324, - 318, 310, 299, 288, 275, 262, 249, 236, - 224, 213, 204, 196, 190, 186, 183, 182, - 182, 183, 186, 189, 192, 196, 200, 203, - 206, 208, 209, 209, 209, 207, 204, 201, - 197, 193, 188, 183, 179, 174, 170, 166, - 163, 161, 160, 159, 159, 160, 161, 162, - 164, 166, 168, 169, 171, 171, 171, 170, - 169, 167, 163, 159, 155, 150, 144, 139, - 133, 128, 122, 117, 113, 110, 107, 105, - 103, 103, 103, 103, 104, 104, 105, 105, - 105, 103, 101, 97, 92, 86, 78, 68, - 58, 45, 32, 18, 3, -11, -26, -41, - -55, -68, -79, -88, -95, -100, -102, -102, - -99, -93, -85, -75, -62, -48, -33, -16, - 0, 16, 33, 48, 62, 75, 85, 93, - 99, 102, 102, 100, 95, 88, 79, 68, - 55, 41, 26, 11, -3, -18, -32, -45, - -58, -68, -78, -86, -92, -97, -101, -103, - -105, -105, -105, -104, -104, -103, -103, -103, - -103, -105, -107, -110, -113, -117, -122, -128, - -133, -139, -144, -150, -155, -159, -163, -167, - -169, -170, -171, -171, -171, -169, -168, -166, - -164, -162, -161, -160, -159, -159, -160, -161, - -163, -166, -170, -174, -179, -183, -188, -193, - -197, -201, -204, -207, -209, -209, -209, -208, - -206, -203, -200, -196, -192, -189, -186, -183, - -182, -182, -183, -186, -190, -196, -204, -213, - -224, -236, -249, -262, -275, -288, -299, -310, - -318, -324, -327, -327, -323, -316, -304, -288, - -269, -245, -218, -187, -153, -117, -79, -40, -}; - -#define BEEP_SRATE 22050 /* 22050 Hz sample rate */ -#define BEEP_BUFLEN 512 -#define BEEP_VOLUME 15 /* 0 - 100 */ - -static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, - unsigned int code, int hz) -{ - struct snd_pmac *chip; - struct pmac_beep *beep; - unsigned long flags; - int beep_speed = 0; - int srate; - int period, ncycles, nsamples; - int i, j, f; - short *p; - - if (type != EV_SND) - return -1; - - switch (code) { - case SND_BELL: if (hz) hz = 1000; - case SND_TONE: break; - default: return -1; - } - - chip = input_get_drvdata(dev); - if (! chip || (beep = chip->beep) == NULL) - return -1; - - if (! hz) { - spin_lock_irqsave(&chip->reg_lock, flags); - if (beep->running) - snd_pmac_beep_stop(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; - } - - beep_speed = snd_pmac_rate_index(chip, &chip->playback, BEEP_SRATE); - srate = chip->freq_table[beep_speed]; - - if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) - hz = 1000; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->playback.running || chip->capture.running || beep->running) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; - } - beep->running = 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); - - if (hz == beep->hz && beep->volume == beep->volume_play) { - nsamples = beep->nsamples; - } else { - period = srate * 256 / hz; /* fixed point */ - ncycles = BEEP_BUFLEN * 256 / period; - nsamples = (period * ncycles) >> 8; - f = ncycles * 65536 / nsamples; - j = 0; - p = beep->buf; - for (i = 0; i < nsamples; ++i, p += 2) { - p[0] = p[1] = beep_wform[j >> 8] * beep->volume; - j = (j + f) & 0xffff; - } - beep->hz = hz; - beep->volume_play = beep->volume; - beep->nsamples = nsamples; - } - - spin_lock_irqsave(&chip->reg_lock, flags); - snd_pmac_beep_dma_start(chip, beep->nsamples * 4, beep->addr, beep_speed); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -/* - * beep volume mixer - */ - -static int snd_pmac_info_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_pmac_get_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - if (snd_BUG_ON(!chip->beep)) - return -ENXIO; - ucontrol->value.integer.value[0] = chip->beep->volume; - return 0; -} - -static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int oval, nval; - if (snd_BUG_ON(!chip->beep)) - return -ENXIO; - oval = chip->beep->volume; - nval = ucontrol->value.integer.value[0]; - if (nval > 100) - return -EINVAL; - chip->beep->volume = nval; - return oval != chip->beep->volume; -} - -static struct snd_kcontrol_new snd_pmac_beep_mixer = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Beep Playback Volume", - .info = snd_pmac_info_beep, - .get = snd_pmac_get_beep, - .put = snd_pmac_put_beep, -}; - -/* Initialize beep stuff */ -int __devinit snd_pmac_attach_beep(struct snd_pmac *chip) -{ - struct pmac_beep *beep; - struct input_dev *input_dev; - struct snd_kcontrol *beep_ctl; - void *dmabuf; - int err = -ENOMEM; - - beep = kzalloc(sizeof(*beep), GFP_KERNEL); - if (! beep) - return -ENOMEM; - dmabuf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, - &beep->addr, GFP_KERNEL); - input_dev = input_allocate_device(); - if (! dmabuf || ! input_dev) - goto fail1; - - /* FIXME: set more better values */ - input_dev->name = "PowerMac Beep"; - input_dev->phys = "powermac/beep"; - input_dev->id.bustype = BUS_ADB; - input_dev->id.vendor = 0x001f; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - - input_dev->evbit[0] = BIT_MASK(EV_SND); - input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); - input_dev->event = snd_pmac_beep_event; - input_dev->dev.parent = &chip->pdev->dev; - input_set_drvdata(input_dev, chip); - - beep->dev = input_dev; - beep->buf = dmabuf; - beep->volume = BEEP_VOLUME; - beep->running = 0; - - beep_ctl = snd_ctl_new1(&snd_pmac_beep_mixer, chip); - err = snd_ctl_add(chip->card, beep_ctl); - if (err < 0) - goto fail1; - - chip->beep = beep; - - err = input_register_device(beep->dev); - if (err) - goto fail2; - - return 0; - - fail2: snd_ctl_remove(chip->card, beep_ctl); - fail1: input_free_device(input_dev); - if (dmabuf) - dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, - dmabuf, beep->addr); - kfree(beep); - return err; -} - -void snd_pmac_detach_beep(struct snd_pmac *chip) -{ - if (chip->beep) { - input_unregister_device(chip->beep->dev); - dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, - chip->beep->buf, chip->beep->addr); - kfree(chip->beep); - chip->beep = NULL; - } -} diff --git a/ANDROID_3.4.5/sound/ppc/burgundy.c b/ANDROID_3.4.5/sound/ppc/burgundy.c deleted file mode 100644 index 00e2d516..00000000 --- a/ANDROID_3.4.5/sound/ppc/burgundy.c +++ /dev/null @@ -1,732 +0,0 @@ -/* - * PMac Burgundy lowlevel functions - * - * Copyright (c) by Takashi Iwai - * code based on dmasound.c. - * - * 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 "pmac.h" -#include "burgundy.h" - - -/* Waits for busy flag to clear */ -static inline void -snd_pmac_burgundy_busy_wait(struct snd_pmac *chip) -{ - int timeout = 50; - while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--) - udelay(1); - if (timeout < 0) - printk(KERN_DEBUG "burgundy_busy_wait: timeout\n"); -} - -static inline void -snd_pmac_burgundy_extend_wait(struct snd_pmac *chip) -{ - int timeout; - timeout = 50; - while (!(in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--) - udelay(1); - if (timeout < 0) - printk(KERN_DEBUG "burgundy_extend_wait: timeout #1\n"); - timeout = 50; - while ((in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--) - udelay(1); - if (timeout < 0) - printk(KERN_DEBUG "burgundy_extend_wait: timeout #2\n"); -} - -static void -snd_pmac_burgundy_wcw(struct snd_pmac *chip, unsigned addr, unsigned val) -{ - out_le32(&chip->awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff)); - snd_pmac_burgundy_busy_wait(chip); - out_le32(&chip->awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff)); - snd_pmac_burgundy_busy_wait(chip); - out_le32(&chip->awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff)); - snd_pmac_burgundy_busy_wait(chip); - out_le32(&chip->awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff)); - snd_pmac_burgundy_busy_wait(chip); -} - -static unsigned -snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr) -{ - unsigned val = 0; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100000); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff; - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100100); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<8; - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100200); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<16; - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100300); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<24; - - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return val; -} - -static void -snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, - unsigned int val) -{ - out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff)); - snd_pmac_burgundy_busy_wait(chip); -} - -static unsigned -snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr) -{ - unsigned val = 0; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - - out_le32(&chip->awacs->codec_ctrl, addr + 0x100000); - snd_pmac_burgundy_busy_wait(chip); - snd_pmac_burgundy_extend_wait(chip); - val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff; - - spin_unlock_irqrestore(&chip->reg_lock, flags); - - return val; -} - -#define BASE2ADDR(base) ((base) << 12) -#define ADDR2BASE(addr) ((addr) >> 12) - -/* - * Burgundy volume: 0 - 100, stereo, word reg - */ -static void -snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address, - long *volume, int shift) -{ - int hardvolume, lvolume, rvolume; - - if (volume[0] < 0 || volume[0] > 100 || - volume[1] < 0 || volume[1] > 100) - return; /* -EINVAL */ - lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0; - rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0; - - hardvolume = lvolume + (rvolume << shift); - if (shift == 8) - hardvolume |= hardvolume << 16; - - snd_pmac_burgundy_wcw(chip, address, hardvolume); -} - -static void -snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address, - long *volume, int shift) -{ - int wvolume; - - wvolume = snd_pmac_burgundy_rcw(chip, address); - - volume[0] = wvolume & 0xff; - if (volume[0] >= BURGUNDY_VOLUME_OFFSET) - volume[0] -= BURGUNDY_VOLUME_OFFSET; - else - volume[0] = 0; - volume[1] = (wvolume >> shift) & 0xff; - if (volume[1] >= BURGUNDY_VOLUME_OFFSET) - volume[1] -= BURGUNDY_VOLUME_OFFSET; - else - volume[1] = 0; -} - -static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int shift = (kcontrol->private_value >> 8) & 0xff; - snd_pmac_burgundy_read_volume(chip, addr, - ucontrol->value.integer.value, shift); - return 0; -} - -static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int shift = (kcontrol->private_value >> 8) & 0xff; - long nvoices[2]; - - snd_pmac_burgundy_write_volume(chip, addr, - ucontrol->value.integer.value, shift); - snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift); - return (nvoices[0] != ucontrol->value.integer.value[0] || - nvoices[1] != ucontrol->value.integer.value[1]); -} - -#define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_volume,\ - .get = snd_pmac_burgundy_get_volume,\ - .put = snd_pmac_burgundy_put_volume,\ - .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) } - -/* - * Burgundy volume: 0 - 100, stereo, 2-byte reg - */ -static void -snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address, - long *volume, int off) -{ - int lvolume, rvolume; - - off |= off << 2; - lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0; - rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0; - - snd_pmac_burgundy_wcb(chip, address + off, lvolume); - snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume); -} - -static void -snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address, - long *volume, int off) -{ - volume[0] = snd_pmac_burgundy_rcb(chip, address + off); - if (volume[0] >= BURGUNDY_VOLUME_OFFSET) - volume[0] -= BURGUNDY_VOLUME_OFFSET; - else - volume[0] = 0; - volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100); - if (volume[1] >= BURGUNDY_VOLUME_OFFSET) - volume[1] -= BURGUNDY_VOLUME_OFFSET; - else - volume[1] = 0; -} - -static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 100; - return 0; -} - -static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int off = kcontrol->private_value & 0x300; - snd_pmac_burgundy_read_volume_2b(chip, addr, - ucontrol->value.integer.value, off); - return 0; -} - -static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int off = kcontrol->private_value & 0x300; - long nvoices[2]; - - snd_pmac_burgundy_write_volume_2b(chip, addr, - ucontrol->value.integer.value, off); - snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off); - return (nvoices[0] != ucontrol->value.integer.value[0] || - nvoices[1] != ucontrol->value.integer.value[1]); -} - -#define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_volume_2b,\ - .get = snd_pmac_burgundy_get_volume_2b,\ - .put = snd_pmac_burgundy_put_volume_2b,\ - .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) } - -/* - * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg - */ -static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int stereo = (kcontrol->private_value >> 24) & 1; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 15; - return 0; -} - -static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int stereo = (kcontrol->private_value >> 24) & 1; - int atten = (kcontrol->private_value >> 25) & 1; - int oval; - - oval = snd_pmac_burgundy_rcb(chip, addr); - if (atten) - oval = ~oval & 0xff; - ucontrol->value.integer.value[0] = oval & 0xf; - if (stereo) - ucontrol->value.integer.value[1] = (oval >> 4) & 0xf; - return 0; -} - -static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); - int stereo = (kcontrol->private_value >> 24) & 1; - int atten = (kcontrol->private_value >> 25) & 1; - int oval, val; - - oval = snd_pmac_burgundy_rcb(chip, addr); - if (atten) - oval = ~oval & 0xff; - val = ucontrol->value.integer.value[0]; - if (stereo) - val |= ucontrol->value.integer.value[1] << 4; - else - val |= ucontrol->value.integer.value[0] << 4; - if (atten) - val = ~val & 0xff; - snd_pmac_burgundy_wcb(chip, addr, val); - return val != oval; -} - -#define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_gain,\ - .get = snd_pmac_burgundy_get_gain,\ - .put = snd_pmac_burgundy_put_gain,\ - .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) } - -/* - * Burgundy switch: 0/1, mono/stereo, word reg - */ -static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int stereo = (kcontrol->private_value >> 24) & 1; - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); - int lmask = 1 << (kcontrol->private_value & 0xff); - int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff); - int stereo = (kcontrol->private_value >> 24) & 1; - int val = snd_pmac_burgundy_rcw(chip, addr); - ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; - if (stereo) - ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; - return 0; -} - -static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); - int lmask = 1 << (kcontrol->private_value & 0xff); - int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff); - int stereo = (kcontrol->private_value >> 24) & 1; - int val, oval; - oval = snd_pmac_burgundy_rcw(chip, addr); - val = oval & ~(lmask | (stereo ? rmask : 0)); - if (ucontrol->value.integer.value[0]) - val |= lmask; - if (stereo && ucontrol->value.integer.value[1]) - val |= rmask; - snd_pmac_burgundy_wcw(chip, addr, val); - return val != oval; -} - -#define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_switch_w,\ - .get = snd_pmac_burgundy_get_switch_w,\ - .put = snd_pmac_burgundy_put_switch_w,\ - .private_value = ((lbit) | ((rbit) << 8)\ - | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) } - -/* - * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask - */ -static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int stereo = (kcontrol->private_value >> 24) & 1; - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = stereo + 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); - int lmask = kcontrol->private_value & 0xff; - int rmask = (kcontrol->private_value >> 8) & 0xff; - int stereo = (kcontrol->private_value >> 24) & 1; - int val = snd_pmac_burgundy_rcb(chip, addr); - ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; - if (stereo) - ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; - return 0; -} - -static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); - int lmask = kcontrol->private_value & 0xff; - int rmask = (kcontrol->private_value >> 8) & 0xff; - int stereo = (kcontrol->private_value >> 24) & 1; - int val, oval; - oval = snd_pmac_burgundy_rcb(chip, addr); - val = oval & ~(lmask | rmask); - if (ucontrol->value.integer.value[0]) - val |= lmask; - if (stereo && ucontrol->value.integer.value[1]) - val |= rmask; - snd_pmac_burgundy_wcb(chip, addr, val); - return val != oval; -} - -#define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ - .info = snd_pmac_burgundy_info_switch_b,\ - .get = snd_pmac_burgundy_get_switch_b,\ - .put = snd_pmac_burgundy_put_switch_b,\ - .private_value = ((lmask) | ((rmask) << 8)\ - | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) } - -/* - * Burgundy mixers - */ -static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __devinitdata = { - BURGUNDY_VOLUME_W("Master Playback Volume", 0, - MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8), - BURGUNDY_VOLUME_W("CD Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLCD, 16), - BURGUNDY_VOLUME_2B("Input Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLMIX01, 2), - BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0, - MASK_ADDR_BURGUNDY_VOLMIX23, 0), - BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0, - MASK_ADDR_BURGUNDY_GAINCD, 1, 0), - BURGUNDY_SWITCH_W("Master Capture Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0), - BURGUNDY_SWITCH_W("CD Capture Switch", 0, - MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1), - BURGUNDY_SWITCH_W("CD Playback Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1), -/* BURGUNDY_SWITCH_W("Loop Capture Switch", 0, - * MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1), - * BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0, - * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0), - * BURGUNDY_SWITCH_B("Mixer Capture Switch", 0, - * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0), - * BURGUNDY_SWITCH_B("PCM out Capture Switch", 0, - * MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0), - */ BURGUNDY_SWITCH_B("PCM Capture Switch", 0, - MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0) -}; -static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __devinitdata = { - BURGUNDY_VOLUME_W("Line in Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLLINE, 16), - BURGUNDY_VOLUME_W("Mic Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLMIC, 16), - BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, - MASK_ADDR_BURGUNDY_GAINLINE, 1, 0), - BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0, - MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), - BURGUNDY_VOLUME_B("Speaker Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), - BURGUNDY_VOLUME_B("Line out Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1), - BURGUNDY_VOLUME_B("Headphone Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENHP, 1, 1), - BURGUNDY_SWITCH_W("Line in Capture Switch", 0, - MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1), - BURGUNDY_SWITCH_W("Mic Capture Switch", 0, - MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1), - BURGUNDY_SWITCH_W("Line in Playback Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1), - BURGUNDY_SWITCH_W("Mic Playback Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1), - BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0, - MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) -}; -static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __devinitdata = { - BURGUNDY_VOLUME_W("Line in Capture Volume", 0, - MASK_ADDR_BURGUNDY_VOLMIC, 16), - BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, - MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), - BURGUNDY_VOLUME_B("Speaker Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1), - BURGUNDY_VOLUME_B("Line out Playback Volume", 0, - MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), - BURGUNDY_SWITCH_W("Line in Capture Switch", 0, - MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1), - BURGUNDY_SWITCH_W("Line in Playback Switch", 0, - MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1), -/* BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0, - * MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */ -}; -static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __devinitdata = -BURGUNDY_SWITCH_B("Master Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT, - BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __devinitdata = -BURGUNDY_SWITCH_B("Master Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_INTERN - | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __devinitdata = -BURGUNDY_SWITCH_B("Speaker Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __devinitdata = -BURGUNDY_SWITCH_B("Speaker Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_INTERN, 0, 0); -static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __devinitdata = -BURGUNDY_SWITCH_B("Line out Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __devinitdata = -BURGUNDY_SWITCH_B("Line out Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); -static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __devinitdata = -BURGUNDY_SWITCH_B("Headphone Playback Switch", 0, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1); - - -#ifdef PMAC_SUPPORT_AUTOMUTE -/* - * auto-mute stuffs - */ -static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip) -{ - return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0; -} - -static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify) -{ - if (chip->auto_mute) { - int imac = of_machine_is_compatible("iMac"); - int reg, oreg; - reg = oreg = snd_pmac_burgundy_rcb(chip, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES); - reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT - | BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT) - : ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT - | BURGUNDY_OUTPUT_INTERN); - if (snd_pmac_burgundy_detect_headphone(chip)) - reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT) - : (BURGUNDY_OUTPUT_LEFT - | BURGUNDY_OUTPUT_RIGHT); - else - reg |= imac ? (BURGUNDY_OUTPUT_LEFT - | BURGUNDY_OUTPUT_RIGHT) - : (BURGUNDY_OUTPUT_INTERN); - if (do_notify && reg == oreg) - return; - snd_pmac_burgundy_wcb(chip, - MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg); - if (do_notify) { - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_sw_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->speaker_sw_ctl->id); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hp_detect_ctl->id); - } - } -} -#endif /* PMAC_SUPPORT_AUTOMUTE */ - - -/* - * initialize burgundy - */ -int __devinit snd_pmac_burgundy_init(struct snd_pmac *chip) -{ - int imac = of_machine_is_compatible("iMac"); - int i, err; - - /* Checks to see the chip is alive and kicking */ - if ((in_le32(&chip->awacs->codec_ctrl) & MASK_ERRCODE) == 0xf0000) { - printk(KERN_WARNING "pmac burgundy: disabled by MacOS :-(\n"); - return 1; - } - - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES, - DEF_BURGUNDY_OUTPUTENABLES); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - DEF_BURGUNDY_MORE_OUTPUTENABLES); - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTSELECTS, - DEF_BURGUNDY_OUTPUTSELECTS); - - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21, - DEF_BURGUNDY_INPSEL21); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3, - imac ? DEF_BURGUNDY_INPSEL3_IMAC - : DEF_BURGUNDY_INPSEL3_PMAC); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD, - DEF_BURGUNDY_GAINCD); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE, - DEF_BURGUNDY_GAINLINE); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMIC, - DEF_BURGUNDY_GAINMIC); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMODEM, - DEF_BURGUNDY_GAINMODEM); - - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENSPEAKER, - DEF_BURGUNDY_ATTENSPEAKER); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENLINEOUT, - DEF_BURGUNDY_ATTENLINEOUT); - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENHP, - DEF_BURGUNDY_ATTENHP); - - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_MASTER_VOLUME, - DEF_BURGUNDY_MASTER_VOLUME); - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLCD, - DEF_BURGUNDY_VOLCD); - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLLINE, - DEF_BURGUNDY_VOLLINE); - snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC, - DEF_BURGUNDY_VOLMIC); - - if (chip->hp_stat_mask == 0) { - /* set headphone-jack detection bit */ - if (imac) - chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER - | BURGUNDY_HPDETECT_IMAC_LOWER - | BURGUNDY_HPDETECT_IMAC_SIDE; - else - chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK; - } - /* - * build burgundy mixers - */ - strcpy(chip->card->mixername, "PowerMac Burgundy"); - - for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip)); - if (err < 0) - return err; - } - for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac) - : ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i] - : &snd_pmac_burgundy_mixers_pmac[i], chip)); - if (err < 0) - return err; - } - chip->master_sw_ctl = snd_ctl_new1(imac - ? &snd_pmac_burgundy_master_sw_imac - : &snd_pmac_burgundy_master_sw_pmac, chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; - chip->master_sw_ctl = snd_ctl_new1(imac - ? &snd_pmac_burgundy_line_sw_imac - : &snd_pmac_burgundy_line_sw_pmac, chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; - if (imac) { - chip->master_sw_ctl = snd_ctl_new1( - &snd_pmac_burgundy_hp_sw_imac, chip); - err = snd_ctl_add(chip->card, chip->master_sw_ctl); - if (err < 0) - return err; - } - chip->speaker_sw_ctl = snd_ctl_new1(imac - ? &snd_pmac_burgundy_speaker_sw_imac - : &snd_pmac_burgundy_speaker_sw_pmac, chip); - err = snd_ctl_add(chip->card, chip->speaker_sw_ctl); - if (err < 0) - return err; -#ifdef PMAC_SUPPORT_AUTOMUTE - err = snd_pmac_add_automute(chip); - if (err < 0) - return err; - - chip->detect_headphone = snd_pmac_burgundy_detect_headphone; - chip->update_automute = snd_pmac_burgundy_update_automute; - snd_pmac_burgundy_update_automute(chip, 0); /* update the status only */ -#endif - - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/burgundy.h b/ANDROID_3.4.5/sound/ppc/burgundy.h deleted file mode 100644 index 7a7f9cf3..00000000 --- a/ANDROID_3.4.5/sound/ppc/burgundy.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Driver for PowerMac Burgundy onboard soundchips - * Copyright (c) 2001 by Takashi Iwai - * based on dmasound.c. - * - * 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 - */ - - -#ifndef __BURGUNDY_H -#define __BURGUNDY_H - -#define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12) -#define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12) -#define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12) - -#define MASK_ADDR_BURGUNDY_GAINCH1 (0x13 << 12) -#define MASK_ADDR_BURGUNDY_GAINCH2 (0x14 << 12) -#define MASK_ADDR_BURGUNDY_GAINCH3 (0x15 << 12) -#define MASK_ADDR_BURGUNDY_GAINCH4 (0x16 << 12) - -#define MASK_ADDR_BURGUNDY_VOLCH1 (0x20 << 12) -#define MASK_ADDR_BURGUNDY_VOLCH2 (0x21 << 12) -#define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12) -#define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12) - -#define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12) -#define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12) -#define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12) -#define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12) -#define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12) - -#define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12) - -#define MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES (0x60 << 12) - -#define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12) -#define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12) -#define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12) -#define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12) - -#define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12) -#define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12) - -#define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1) -#define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2) -#define MASK_ADDR_BURGUNDY_VOLMIC (MASK_ADDR_BURGUNDY_VOLCH3) -#define MASK_ADDR_BURGUNDY_VOLMODEM (MASK_ADDR_BURGUNDY_VOLCH4) - -#define MASK_ADDR_BURGUNDY_GAINCD (MASK_ADDR_BURGUNDY_GAINCH1) -#define MASK_ADDR_BURGUNDY_GAINLINE (MASK_ADDR_BURGUNDY_GAINCH2) -#define MASK_ADDR_BURGUNDY_GAINMIC (MASK_ADDR_BURGUNDY_GAINCH3) -#define MASK_ADDR_BURGUNDY_GAINMODEM (MASK_ADDR_BURGUNDY_VOLCH4) - - -/* These are all default values for the burgundy */ -#define DEF_BURGUNDY_INPSEL21 (0xAA) -#define DEF_BURGUNDY_INPSEL3_IMAC (0x0A) -#define DEF_BURGUNDY_INPSEL3_PMAC (0x05) - -#define DEF_BURGUNDY_GAINCD (0x33) -#define DEF_BURGUNDY_GAINLINE (0x44) -#define DEF_BURGUNDY_GAINMIC (0x44) -#define DEF_BURGUNDY_GAINMODEM (0x06) - -/* Remember: lowest volume here is 0x9B (155) */ -#define DEF_BURGUNDY_VOLCD (0xCCCCCCCC) -#define DEF_BURGUNDY_VOLLINE (0x00000000) -#define DEF_BURGUNDY_VOLMIC (0x00000000) -#define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC) - -#define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F) -#define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A) - -/* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */ -#define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD) - -#define DEF_BURGUNDY_MORE_OUTPUTENABLES (0x7E) - -#define DEF_BURGUNDY_ATTENSPEAKER (0x44) -#define DEF_BURGUNDY_ATTENLINEOUT (0xCC) -#define DEF_BURGUNDY_ATTENHP (0xCC) - -/* MORE_OUTPUTENABLES bits */ -#define BURGUNDY_OUTPUT_LEFT 0x02 -#define BURGUNDY_OUTPUT_RIGHT 0x04 -#define BURGUNDY_LINEOUT_LEFT 0x08 -#define BURGUNDY_LINEOUT_RIGHT 0x10 -#define BURGUNDY_HP_LEFT 0x20 -#define BURGUNDY_HP_RIGHT 0x40 -#define BURGUNDY_OUTPUT_INTERN 0x80 - -/* Headphone detection bits */ -#define BURGUNDY_HPDETECT_PMAC_BACK 0x04 -#define BURGUNDY_HPDETECT_IMAC_SIDE 0x04 -#define BURGUNDY_HPDETECT_IMAC_UPPER 0x08 -#define BURGUNDY_HPDETECT_IMAC_LOWER 0x01 - -/* Volume offset */ -#define BURGUNDY_VOLUME_OFFSET 155 - -#endif /* __BURGUNDY_H */ diff --git a/ANDROID_3.4.5/sound/ppc/daca.c b/ANDROID_3.4.5/sound/ppc/daca.c deleted file mode 100644 index 24200b7b..00000000 --- a/ANDROID_3.4.5/sound/ppc/daca.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * PMac DACA lowlevel functions - * - * Copyright (c) by Takashi Iwai - * - * 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 "pmac.h" - -/* i2c address */ -#define DACA_I2C_ADDR 0x4d - -/* registers */ -#define DACA_REG_SR 0x01 -#define DACA_REG_AVOL 0x02 -#define DACA_REG_GCFG 0x03 - -/* maximum volume value */ -#define DACA_VOL_MAX 0x38 - - -struct pmac_daca { - struct pmac_keywest i2c; - int left_vol, right_vol; - unsigned int deemphasis : 1; - unsigned int amp_on : 1; -}; - - -/* - * initialize / detect DACA - */ -static int daca_init_client(struct pmac_keywest *i2c) -{ - unsigned short wdata = 0x00; - /* SR: no swap, 1bit delay, 32-48kHz */ - /* GCFG: power amp inverted, DAC on */ - if (i2c_smbus_write_byte_data(i2c->client, DACA_REG_SR, 0x08) < 0 || - i2c_smbus_write_byte_data(i2c->client, DACA_REG_GCFG, 0x05) < 0) - return -EINVAL; - return i2c_smbus_write_block_data(i2c->client, DACA_REG_AVOL, - 2, (unsigned char*)&wdata); -} - -/* - * update volume - */ -static int daca_set_volume(struct pmac_daca *mix) -{ - unsigned char data[2]; - - if (! mix->i2c.client) - return -ENODEV; - - if (mix->left_vol > DACA_VOL_MAX) - data[0] = DACA_VOL_MAX; - else - data[0] = mix->left_vol; - if (mix->right_vol > DACA_VOL_MAX) - data[1] = DACA_VOL_MAX; - else - data[1] = mix->right_vol; - data[1] |= mix->deemphasis ? 0x40 : 0; - if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL, - 2, data) < 0) { - snd_printk(KERN_ERR "failed to set volume \n"); - return -EINVAL; - } - return 0; -} - - -/* deemphasis switch */ -#define daca_info_deemphasis snd_ctl_boolean_mono_info - -static int daca_get_deemphasis(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->deemphasis ? 1 : 0; - return 0; -} - -static int daca_put_deemphasis(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - change = mix->deemphasis != ucontrol->value.integer.value[0]; - if (change) { - mix->deemphasis = !!ucontrol->value.integer.value[0]; - daca_set_volume(mix); - } - return change; -} - -/* output volume */ -static int daca_info_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = DACA_VOL_MAX; - return 0; -} - -static int daca_get_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->left_vol; - ucontrol->value.integer.value[1] = mix->right_vol; - return 0; -} - -static int daca_put_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - unsigned int vol[2]; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - vol[0] = ucontrol->value.integer.value[0]; - vol[1] = ucontrol->value.integer.value[1]; - if (vol[0] > DACA_VOL_MAX || vol[1] > DACA_VOL_MAX) - return -EINVAL; - change = mix->left_vol != vol[0] || - mix->right_vol != vol[1]; - if (change) { - mix->left_vol = vol[0]; - mix->right_vol = vol[1]; - daca_set_volume(mix); - } - return change; -} - -/* amplifier switch */ -#define daca_info_amp daca_info_deemphasis - -static int daca_get_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->amp_on ? 1 : 0; - return 0; -} - -static int daca_put_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_daca *mix; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - change = mix->amp_on != ucontrol->value.integer.value[0]; - if (change) { - mix->amp_on = !!ucontrol->value.integer.value[0]; - i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG, - mix->amp_on ? 0x05 : 0x04); - } - return change; -} - -static struct snd_kcontrol_new daca_mixers[] = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Deemphasis Switch", - .info = daca_info_deemphasis, - .get = daca_get_deemphasis, - .put = daca_put_deemphasis - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = daca_info_volume, - .get = daca_get_volume, - .put = daca_put_volume - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Power Amplifier Switch", - .info = daca_info_amp, - .get = daca_get_amp, - .put = daca_put_amp - }, -}; - - -#ifdef CONFIG_PM -static void daca_resume(struct snd_pmac *chip) -{ - struct pmac_daca *mix = chip->mixer_data; - i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_SR, 0x08); - i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG, - mix->amp_on ? 0x05 : 0x04); - daca_set_volume(mix); -} -#endif /* CONFIG_PM */ - - -static void daca_cleanup(struct snd_pmac *chip) -{ - struct pmac_daca *mix = chip->mixer_data; - if (! mix) - return; - snd_pmac_keywest_cleanup(&mix->i2c); - kfree(mix); - chip->mixer_data = NULL; -} - -/* exported */ -int __devinit snd_pmac_daca_init(struct snd_pmac *chip) -{ - int i, err; - struct pmac_daca *mix; - - request_module("i2c-powermac"); - - mix = kzalloc(sizeof(*mix), GFP_KERNEL); - if (! mix) - return -ENOMEM; - chip->mixer_data = mix; - chip->mixer_free = daca_cleanup; - mix->amp_on = 1; /* default on */ - - mix->i2c.addr = DACA_I2C_ADDR; - mix->i2c.init_client = daca_init_client; - mix->i2c.name = "DACA"; - if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0) - return err; - - /* - * build mixers - */ - strcpy(chip->card->mixername, "PowerMac DACA"); - - for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0) - return err; - } - -#ifdef CONFIG_PM - chip->resume = daca_resume; -#endif - - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/keywest.c b/ANDROID_3.4.5/sound/ppc/keywest.c deleted file mode 100644 index 4080becf..00000000 --- a/ANDROID_3.4.5/sound/ppc/keywest.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * common keywest i2c layer - * - * Copyright (c) by Takashi Iwai - * - * 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 "pmac.h" - -/* - * we have to keep a static variable here since i2c attach_adapter - * callback cannot pass a private data. - */ -static struct pmac_keywest *keywest_ctx; - - -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) -{ - struct i2c_board_info info; - - if (! keywest_ctx) - return -EINVAL; - - if (strncmp(adapter->name, "mac-io", 6)) - return 0; /* ignored */ - - 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); - if (!keywest_ctx->client) - return -ENODEV; - /* - * We know the driver is already loaded, so the device should be - * already bound. If not it means binding failed, and then there - * is no point in keeping the device instantiated. - */ - if (!keywest_ctx->client->driver) { - i2c_unregister_device(keywest_ctx->client); - keywest_ctx->client = NULL; - 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(&keywest_ctx->client->detected, - &keywest_ctx->client->driver->clients); - return 0; -} - -static int keywest_remove(struct i2c_client *client) -{ - if (! keywest_ctx) - return 0; - if (client == keywest_ctx->client) - keywest_ctx->client = NULL; - - return 0; -} - - -static const struct i2c_device_id keywest_i2c_id[] = { - { "keywest", 0 }, - { } -}; - -static 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) -{ - if (keywest_ctx && keywest_ctx == i2c) { - i2c_del_driver(&keywest_driver); - keywest_ctx = NULL; - } -} - -int __devinit snd_pmac_tumbler_post_init(void) -{ - int err; - - if (!keywest_ctx || !keywest_ctx->client) - return -ENXIO; - - if ((err = keywest_ctx->init_client(keywest_ctx)) < 0) { - snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err); - return err; - } - return 0; -} - -/* exported */ -int __devinit snd_pmac_keywest_init(struct pmac_keywest *i2c) -{ - int err; - - if (keywest_ctx) - return -EBUSY; - - keywest_ctx = i2c; - - if ((err = i2c_add_driver(&keywest_driver))) { - snd_printk(KERN_ERR "cannot register keywest i2c driver\n"); - return err; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/pmac.c b/ANDROID_3.4.5/sound/ppc/pmac.c deleted file mode 100644 index ab96cde7..00000000 --- a/ANDROID_3.4.5/sound/ppc/pmac.c +++ /dev/null @@ -1,1410 +0,0 @@ -/* - * PMac DBDMA lowlevel functions - * - * Copyright (c) by Takashi Iwai - * code based on dmasound.c. - * - * 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 -#include "pmac.h" -#include -#include -#include - - -/* fixed frequency table for awacs, screamer, burgundy, DACA (44100 max) */ -static int awacs_freqs[8] = { - 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350 -}; -/* fixed frequency table for tumbler */ -static int tumbler_freqs[1] = { - 44100 -}; - - -/* - * we will allocate a single 'emergency' dbdma cmd block to use if the - * tx status comes up "DEAD". This happens on some PowerComputing Pmac - * clones, either owing to a bug in dbdma or some interaction between - * IDE and sound. However, this measure would deal with DEAD status if - * it appeared elsewhere. - */ -static struct pmac_dbdma emergency_dbdma; -static int emergency_in_use; - - -/* - * allocate DBDMA command arrays - */ -static int snd_pmac_dbdma_alloc(struct snd_pmac *chip, struct pmac_dbdma *rec, int size) -{ - unsigned int rsize = sizeof(struct dbdma_cmd) * (size + 1); - - rec->space = dma_alloc_coherent(&chip->pdev->dev, rsize, - &rec->dma_base, GFP_KERNEL); - if (rec->space == NULL) - return -ENOMEM; - rec->size = size; - memset(rec->space, 0, rsize); - rec->cmds = (void __iomem *)DBDMA_ALIGN(rec->space); - rec->addr = rec->dma_base + (unsigned long)((char *)rec->cmds - (char *)rec->space); - - return 0; -} - -static void snd_pmac_dbdma_free(struct snd_pmac *chip, struct pmac_dbdma *rec) -{ - if (rec->space) { - unsigned int rsize = sizeof(struct dbdma_cmd) * (rec->size + 1); - - dma_free_coherent(&chip->pdev->dev, rsize, rec->space, rec->dma_base); - } -} - - -/* - * pcm stuff - */ - -/* - * look up frequency table - */ - -unsigned int snd_pmac_rate_index(struct snd_pmac *chip, struct pmac_stream *rec, unsigned int rate) -{ - int i, ok, found; - - ok = rec->cur_freqs; - if (rate > chip->freq_table[0]) - return 0; - found = 0; - for (i = 0; i < chip->num_freqs; i++, ok >>= 1) { - if (! (ok & 1)) continue; - found = i; - if (rate >= chip->freq_table[i]) - break; - } - return found; -} - -/* - * check whether another stream is active - */ -static inline int another_stream(int stream) -{ - return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; -} - -/* - * allocate buffers - */ -static int snd_pmac_pcm_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw_params)); -} - -/* - * release buffers - */ -static int snd_pmac_pcm_hw_free(struct snd_pcm_substream *subs) -{ - snd_pcm_lib_free_pages(subs); - return 0; -} - -/* - * get a stream of the opposite direction - */ -static struct pmac_stream *snd_pmac_get_stream(struct snd_pmac *chip, int stream) -{ - switch (stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - return &chip->playback; - case SNDRV_PCM_STREAM_CAPTURE: - return &chip->capture; - default: - snd_BUG(); - return NULL; - } -} - -/* - * wait while run status is on - */ -static inline void -snd_pmac_wait_ack(struct pmac_stream *rec) -{ - int timeout = 50000; - while ((in_le32(&rec->dma->status) & RUN) && timeout-- > 0) - udelay(1); -} - -/* - * set the format and rate to the chip. - * call the lowlevel function if defined (e.g. for AWACS). - */ -static void snd_pmac_pcm_set_format(struct snd_pmac *chip) -{ - /* set up frequency and format */ - out_le32(&chip->awacs->control, chip->control_mask | (chip->rate_index << 8)); - out_le32(&chip->awacs->byteswap, chip->format == SNDRV_PCM_FORMAT_S16_LE ? 1 : 0); - if (chip->set_format) - chip->set_format(chip); -} - -/* - * stop the DMA transfer - */ -static inline void snd_pmac_dma_stop(struct pmac_stream *rec) -{ - out_le32(&rec->dma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); - snd_pmac_wait_ack(rec); -} - -/* - * set the command pointer address - */ -static inline void snd_pmac_dma_set_command(struct pmac_stream *rec, struct pmac_dbdma *cmd) -{ - out_le32(&rec->dma->cmdptr, cmd->addr); -} - -/* - * start the DMA - */ -static inline void snd_pmac_dma_run(struct pmac_stream *rec, int status) -{ - out_le32(&rec->dma->control, status | (status << 16)); -} - - -/* - * prepare playback/capture stream - */ -static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, struct snd_pcm_substream *subs) -{ - int i; - volatile struct dbdma_cmd __iomem *cp; - struct snd_pcm_runtime *runtime = subs->runtime; - int rate_index; - long offset; - struct pmac_stream *astr; - - rec->dma_size = snd_pcm_lib_buffer_bytes(subs); - rec->period_size = snd_pcm_lib_period_bytes(subs); - rec->nperiods = rec->dma_size / rec->period_size; - rec->cur_period = 0; - rate_index = snd_pmac_rate_index(chip, rec, runtime->rate); - - /* set up constraints */ - astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); - if (! astr) - return -EINVAL; - astr->cur_freqs = 1 << rate_index; - astr->cur_formats = 1 << runtime->format; - chip->rate_index = rate_index; - chip->format = runtime->format; - - /* We really want to execute a DMA stop command, after the AWACS - * is initialized. - * For reasons I don't understand, it stops the hissing noise - * common to many PowerBook G3 systems and random noise otherwise - * captured on iBook2's about every third time. -ReneR - */ - spin_lock_irq(&chip->reg_lock); - snd_pmac_dma_stop(rec); - st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); - snd_pmac_dma_set_command(rec, &chip->extra_dma); - snd_pmac_dma_run(rec, RUN); - spin_unlock_irq(&chip->reg_lock); - mdelay(5); - spin_lock_irq(&chip->reg_lock); - /* continuous DMA memory type doesn't provide the physical address, - * so we need to resolve the address here... - */ - offset = runtime->dma_addr; - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { - st_le32(&cp->phy_addr, offset); - st_le16(&cp->req_count, rec->period_size); - /*st_le16(&cp->res_count, 0);*/ - st_le16(&cp->xfer_status, 0); - offset += rec->period_size; - } - /* make loop */ - st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); - st_le32(&cp->cmd_dep, rec->cmd.addr); - - snd_pmac_dma_stop(rec); - snd_pmac_dma_set_command(rec, &rec->cmd); - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - - -/* - * PCM trigger/stop - */ -static int snd_pmac_pcm_trigger(struct snd_pmac *chip, struct pmac_stream *rec, - struct snd_pcm_substream *subs, int cmd) -{ - volatile struct dbdma_cmd __iomem *cp; - int i, command; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (rec->running) - return -EBUSY; - command = (subs->stream == SNDRV_PCM_STREAM_PLAYBACK ? - OUTPUT_MORE : INPUT_MORE) + INTR_ALWAYS; - spin_lock(&chip->reg_lock); - snd_pmac_beep_stop(chip); - snd_pmac_pcm_set_format(chip); - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) - out_le16(&cp->command, command); - snd_pmac_dma_set_command(rec, &rec->cmd); - (void)in_le32(&rec->dma->status); - snd_pmac_dma_run(rec, RUN|WAKE); - rec->running = 1; - spin_unlock(&chip->reg_lock); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - spin_lock(&chip->reg_lock); - rec->running = 0; - /*printk(KERN_DEBUG "stopped!!\n");*/ - snd_pmac_dma_stop(rec); - for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) - out_le16(&cp->command, DBDMA_STOP); - spin_unlock(&chip->reg_lock); - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * return the current pointer - */ -inline -static snd_pcm_uframes_t snd_pmac_pcm_pointer(struct snd_pmac *chip, - struct pmac_stream *rec, - struct snd_pcm_substream *subs) -{ - int count = 0; - -#if 1 /* hmm.. how can we get the current dma pointer?? */ - int stat; - volatile struct dbdma_cmd __iomem *cp = &rec->cmd.cmds[rec->cur_period]; - stat = ld_le16(&cp->xfer_status); - if (stat & (ACTIVE|DEAD)) { - count = in_le16(&cp->res_count); - if (count) - count = rec->period_size - count; - } -#endif - count += rec->cur_period * rec->period_size; - /*printk(KERN_DEBUG "pointer=%d\n", count);*/ - return bytes_to_frames(subs->runtime, count); -} - -/* - * playback - */ - -static int snd_pmac_playback_prepare(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_prepare(chip, &chip->playback, subs); -} - -static int snd_pmac_playback_trigger(struct snd_pcm_substream *subs, - int cmd) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_trigger(chip, &chip->playback, subs, cmd); -} - -static snd_pcm_uframes_t snd_pmac_playback_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_pointer(chip, &chip->playback, subs); -} - - -/* - * capture - */ - -static int snd_pmac_capture_prepare(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_prepare(chip, &chip->capture, subs); -} - -static int snd_pmac_capture_trigger(struct snd_pcm_substream *subs, - int cmd) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_trigger(chip, &chip->capture, subs, cmd); -} - -static snd_pcm_uframes_t snd_pmac_capture_pointer(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - return snd_pmac_pcm_pointer(chip, &chip->capture, subs); -} - - -/* - * Handle DEAD DMA transfers: - * if the TX status comes up "DEAD" - reported on some Power Computing machines - * we need to re-start the dbdma - but from a different physical start address - * and with a different transfer length. It would get very messy to do this - * with the normal dbdma_cmd blocks - we would have to re-write the buffer start - * addresses each time. So, we will keep a single dbdma_cmd block which can be - * fiddled with. - * When DEAD status is first reported the content of the faulted dbdma block is - * copied into the emergency buffer and we note that the buffer is in use. - * we then bump the start physical address by the amount that was successfully - * output before it died. - * On any subsequent DEAD result we just do the bump-ups (we know that we are - * already using the emergency dbdma_cmd). - * CHECK: this just tries to "do it". It is possible that we should abandon - * xfers when the number of residual bytes gets below a certain value - I can - * see that this might cause a loop-forever if a too small transfer causes - * DEAD status. However this is a TODO for now - we'll see what gets reported. - * When we get a successful transfer result with the emergency buffer we just - * pretend that it completed using the original dmdma_cmd and carry on. The - * 'next_cmd' field will already point back to the original loop of blocks. - */ -static inline void snd_pmac_pcm_dead_xfer(struct pmac_stream *rec, - volatile struct dbdma_cmd __iomem *cp) -{ - unsigned short req, res ; - unsigned int phy ; - - /* printk(KERN_WARNING "snd-powermac: DMA died - patching it up!\n"); */ - - /* to clear DEAD status we must first clear RUN - set it to quiescent to be on the safe side */ - (void)in_le32(&rec->dma->status); - out_le32(&rec->dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); - - if (!emergency_in_use) { /* new problem */ - memcpy((void *)emergency_dbdma.cmds, (void *)cp, - sizeof(struct dbdma_cmd)); - emergency_in_use = 1; - st_le16(&cp->xfer_status, 0); - st_le16(&cp->req_count, rec->period_size); - cp = emergency_dbdma.cmds; - } - - /* now bump the values to reflect the amount - we haven't yet shifted */ - req = ld_le16(&cp->req_count); - res = ld_le16(&cp->res_count); - phy = ld_le32(&cp->phy_addr); - phy += (req - res); - st_le16(&cp->req_count, res); - st_le16(&cp->res_count, 0); - st_le16(&cp->xfer_status, 0); - st_le32(&cp->phy_addr, phy); - - st_le32(&cp->cmd_dep, rec->cmd.addr - + sizeof(struct dbdma_cmd)*((rec->cur_period+1)%rec->nperiods)); - - st_le16(&cp->command, OUTPUT_MORE | BR_ALWAYS | INTR_ALWAYS); - - /* point at our patched up command block */ - out_le32(&rec->dma->cmdptr, emergency_dbdma.addr); - - /* we must re-start the controller */ - (void)in_le32(&rec->dma->status); - /* should complete clearing the DEAD status */ - out_le32(&rec->dma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); -} - -/* - * update playback/capture pointer from interrupts - */ -static void snd_pmac_pcm_update(struct snd_pmac *chip, struct pmac_stream *rec) -{ - volatile struct dbdma_cmd __iomem *cp; - int c; - int stat; - - spin_lock(&chip->reg_lock); - if (rec->running) { - for (c = 0; c < rec->nperiods; c++) { /* at most all fragments */ - - if (emergency_in_use) /* already using DEAD xfer? */ - cp = emergency_dbdma.cmds; - else - cp = &rec->cmd.cmds[rec->cur_period]; - - stat = ld_le16(&cp->xfer_status); - - if (stat & DEAD) { - snd_pmac_pcm_dead_xfer(rec, cp); - break; /* this block is still going */ - } - - if (emergency_in_use) - emergency_in_use = 0 ; /* done that */ - - if (! (stat & ACTIVE)) - break; - - /*printk(KERN_DEBUG "update frag %d\n", rec->cur_period);*/ - st_le16(&cp->xfer_status, 0); - st_le16(&cp->req_count, rec->period_size); - /*st_le16(&cp->res_count, 0);*/ - rec->cur_period++; - if (rec->cur_period >= rec->nperiods) { - rec->cur_period = 0; - } - - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(rec->substream); - spin_lock(&chip->reg_lock); - } - } - spin_unlock(&chip->reg_lock); -} - - -/* - * hw info - */ - -static struct snd_pcm_hardware snd_pmac_playback = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_44100, - .rate_min = 7350, - .rate_max = 44100, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 131072, - .period_bytes_min = 256, - .period_bytes_max = 16384, - .periods_min = 3, - .periods_max = PMAC_MAX_FRAGS, -}; - -static struct snd_pcm_hardware snd_pmac_capture = -{ - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_44100, - .rate_min = 7350, - .rate_max = 44100, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 131072, - .period_bytes_min = 256, - .period_bytes_max = 16384, - .periods_min = 3, - .periods_max = PMAC_MAX_FRAGS, -}; - - -#if 0 // NYI -static int snd_pmac_hw_rule_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pmac *chip = rule->private; - struct pmac_stream *rec = snd_pmac_get_stream(chip, rule->deps[0]); - int i, freq_table[8], num_freqs; - - if (! rec) - return -EINVAL; - num_freqs = 0; - for (i = chip->num_freqs - 1; i >= 0; i--) { - if (rec->cur_freqs & (1 << i)) - freq_table[num_freqs++] = chip->freq_table[i]; - } - - return snd_interval_list(hw_param_interval(params, rule->var), - num_freqs, freq_table, 0); -} - -static int snd_pmac_hw_rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_pmac *chip = rule->private; - struct pmac_stream *rec = snd_pmac_get_stream(chip, rule->deps[0]); - - if (! rec) - return -EINVAL; - return snd_mask_refine_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), - rec->cur_formats); -} -#endif // NYI - -static int snd_pmac_pcm_open(struct snd_pmac *chip, struct pmac_stream *rec, - struct snd_pcm_substream *subs) -{ - struct snd_pcm_runtime *runtime = subs->runtime; - int i; - - /* look up frequency table and fill bit mask */ - runtime->hw.rates = 0; - for (i = 0; i < chip->num_freqs; i++) - if (chip->freqs_ok & (1 << i)) - runtime->hw.rates |= - snd_pcm_rate_to_rate_bit(chip->freq_table[i]); - - /* check for minimum and maximum rates */ - for (i = 0; i < chip->num_freqs; i++) { - if (chip->freqs_ok & (1 << i)) { - runtime->hw.rate_max = chip->freq_table[i]; - break; - } - } - for (i = chip->num_freqs - 1; i >= 0; i--) { - if (chip->freqs_ok & (1 << i)) { - runtime->hw.rate_min = chip->freq_table[i]; - break; - } - } - runtime->hw.formats = chip->formats_ok; - if (chip->can_capture) { - if (! chip->can_duplex) - runtime->hw.info |= SNDRV_PCM_INFO_HALF_DUPLEX; - runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; - } - runtime->private_data = rec; - rec->substream = subs; - -#if 0 /* FIXME: still under development.. */ - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_pmac_hw_rule_rate, chip, rec->stream, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, - snd_pmac_hw_rule_format, chip, rec->stream, -1); -#endif - - runtime->hw.periods_max = rec->cmd.size - 1; - - /* constraints to fix choppy sound */ - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - return 0; -} - -static int snd_pmac_pcm_close(struct snd_pmac *chip, struct pmac_stream *rec, - struct snd_pcm_substream *subs) -{ - struct pmac_stream *astr; - - snd_pmac_dma_stop(rec); - - astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); - if (! astr) - return -EINVAL; - - /* reset constraints */ - astr->cur_freqs = chip->freqs_ok; - astr->cur_formats = chip->formats_ok; - - return 0; -} - -static int snd_pmac_playback_open(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - - subs->runtime->hw = snd_pmac_playback; - return snd_pmac_pcm_open(chip, &chip->playback, subs); -} - -static int snd_pmac_capture_open(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - - subs->runtime->hw = snd_pmac_capture; - return snd_pmac_pcm_open(chip, &chip->capture, subs); -} - -static int snd_pmac_playback_close(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - - return snd_pmac_pcm_close(chip, &chip->playback, subs); -} - -static int snd_pmac_capture_close(struct snd_pcm_substream *subs) -{ - struct snd_pmac *chip = snd_pcm_substream_chip(subs); - - return snd_pmac_pcm_close(chip, &chip->capture, subs); -} - -/* - */ - -static struct snd_pcm_ops snd_pmac_playback_ops = { - .open = snd_pmac_playback_open, - .close = snd_pmac_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_pmac_pcm_hw_params, - .hw_free = snd_pmac_pcm_hw_free, - .prepare = snd_pmac_playback_prepare, - .trigger = snd_pmac_playback_trigger, - .pointer = snd_pmac_playback_pointer, -}; - -static struct snd_pcm_ops snd_pmac_capture_ops = { - .open = snd_pmac_capture_open, - .close = snd_pmac_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_pmac_pcm_hw_params, - .hw_free = snd_pmac_pcm_hw_free, - .prepare = snd_pmac_capture_prepare, - .trigger = snd_pmac_capture_trigger, - .pointer = snd_pmac_capture_pointer, -}; - -int __devinit snd_pmac_pcm_new(struct snd_pmac *chip) -{ - struct snd_pcm *pcm; - int err; - int num_captures = 1; - - if (! chip->can_capture) - num_captures = 0; - err = snd_pcm_new(chip->card, chip->card->driver, 0, 1, num_captures, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_pmac_playback_ops); - if (chip->can_capture) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_pmac_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - strcpy(pcm->name, chip->card->shortname); - chip->pcm = pcm; - - chip->formats_ok = SNDRV_PCM_FMTBIT_S16_BE; - if (chip->can_byte_swap) - chip->formats_ok |= SNDRV_PCM_FMTBIT_S16_LE; - - chip->playback.cur_formats = chip->formats_ok; - chip->capture.cur_formats = chip->formats_ok; - chip->playback.cur_freqs = chip->freqs_ok; - chip->capture.cur_freqs = chip->freqs_ok; - - /* preallocate 64k buffer */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - &chip->pdev->dev, - 64 * 1024, 64 * 1024); - - return 0; -} - - -static void snd_pmac_dbdma_reset(struct snd_pmac *chip) -{ - out_le32(&chip->playback.dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); - snd_pmac_wait_ack(&chip->playback); - out_le32(&chip->capture.dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); - snd_pmac_wait_ack(&chip->capture); -} - - -/* - * handling beep - */ -void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long addr, int speed) -{ - struct pmac_stream *rec = &chip->playback; - - snd_pmac_dma_stop(rec); - st_le16(&chip->extra_dma.cmds->req_count, bytes); - st_le16(&chip->extra_dma.cmds->xfer_status, 0); - st_le32(&chip->extra_dma.cmds->cmd_dep, chip->extra_dma.addr); - st_le32(&chip->extra_dma.cmds->phy_addr, addr); - st_le16(&chip->extra_dma.cmds->command, OUTPUT_MORE + BR_ALWAYS); - out_le32(&chip->awacs->control, - (in_le32(&chip->awacs->control) & ~0x1f00) - | (speed << 8)); - out_le32(&chip->awacs->byteswap, 0); - snd_pmac_dma_set_command(rec, &chip->extra_dma); - snd_pmac_dma_run(rec, RUN); -} - -void snd_pmac_beep_dma_stop(struct snd_pmac *chip) -{ - snd_pmac_dma_stop(&chip->playback); - st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); - snd_pmac_pcm_set_format(chip); /* reset format */ -} - - -/* - * interrupt handlers - */ -static irqreturn_t -snd_pmac_tx_intr(int irq, void *devid) -{ - struct snd_pmac *chip = devid; - snd_pmac_pcm_update(chip, &chip->playback); - return IRQ_HANDLED; -} - - -static irqreturn_t -snd_pmac_rx_intr(int irq, void *devid) -{ - struct snd_pmac *chip = devid; - snd_pmac_pcm_update(chip, &chip->capture); - return IRQ_HANDLED; -} - - -static irqreturn_t -snd_pmac_ctrl_intr(int irq, void *devid) -{ - struct snd_pmac *chip = devid; - int ctrl = in_le32(&chip->awacs->control); - - /*printk(KERN_DEBUG "pmac: control interrupt.. 0x%x\n", ctrl);*/ - if (ctrl & MASK_PORTCHG) { - /* do something when headphone is plugged/unplugged? */ - if (chip->update_automute) - chip->update_automute(chip, 1); - } - if (ctrl & MASK_CNTLERR) { - int err = (in_le32(&chip->awacs->codec_stat) & MASK_ERRCODE) >> 16; - if (err && chip->model <= PMAC_SCREAMER) - snd_printk(KERN_DEBUG "error %x\n", err); - } - /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */ - out_le32(&chip->awacs->control, ctrl); - return IRQ_HANDLED; -} - - -/* - * a wrapper to feature call for compatibility - */ -static void snd_pmac_sound_feature(struct snd_pmac *chip, int enable) -{ - if (ppc_md.feature_call) - ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable); -} - -/* - * release resources - */ - -static int snd_pmac_free(struct snd_pmac *chip) -{ - /* stop sounds */ - if (chip->initialized) { - snd_pmac_dbdma_reset(chip); - /* disable interrupts from awacs interface */ - out_le32(&chip->awacs->control, in_le32(&chip->awacs->control) & 0xfff); - } - - if (chip->node) - snd_pmac_sound_feature(chip, 0); - - /* clean up mixer if any */ - if (chip->mixer_free) - chip->mixer_free(chip); - - snd_pmac_detach_beep(chip); - - /* release resources */ - if (chip->irq >= 0) - free_irq(chip->irq, (void*)chip); - if (chip->tx_irq >= 0) - free_irq(chip->tx_irq, (void*)chip); - if (chip->rx_irq >= 0) - free_irq(chip->rx_irq, (void*)chip); - snd_pmac_dbdma_free(chip, &chip->playback.cmd); - snd_pmac_dbdma_free(chip, &chip->capture.cmd); - snd_pmac_dbdma_free(chip, &chip->extra_dma); - snd_pmac_dbdma_free(chip, &emergency_dbdma); - if (chip->macio_base) - iounmap(chip->macio_base); - if (chip->latch_base) - iounmap(chip->latch_base); - if (chip->awacs) - iounmap(chip->awacs); - if (chip->playback.dma) - iounmap(chip->playback.dma); - if (chip->capture.dma) - iounmap(chip->capture.dma); - - if (chip->node) { - int i; - for (i = 0; i < 3; i++) { - if (chip->requested & (1 << i)) - release_mem_region(chip->rsrc[i].start, - resource_size(&chip->rsrc[i])); - } - } - - if (chip->pdev) - pci_dev_put(chip->pdev); - of_node_put(chip->node); - kfree(chip); - return 0; -} - - -/* - * free the device - */ -static int snd_pmac_dev_free(struct snd_device *device) -{ - struct snd_pmac *chip = device->device_data; - return snd_pmac_free(chip); -} - - -/* - * check the machine support byteswap (little-endian) - */ - -static void __devinit detect_byte_swap(struct snd_pmac *chip) -{ - struct device_node *mio; - - /* if seems that Keylargo can't byte-swap */ - for (mio = chip->node->parent; mio; mio = mio->parent) { - if (strcmp(mio->name, "mac-io") == 0) { - if (of_device_is_compatible(mio, "Keylargo")) - chip->can_byte_swap = 0; - break; - } - } - - /* it seems the Pismo & iBook can't byte-swap in hardware. */ - if (of_machine_is_compatible("PowerBook3,1") || - of_machine_is_compatible("PowerBook2,1")) - chip->can_byte_swap = 0 ; - - if (of_machine_is_compatible("PowerBook2,1")) - chip->can_duplex = 0; -} - - -/* - * detect a sound chip - */ -static int __devinit snd_pmac_detect(struct snd_pmac *chip) -{ - struct device_node *sound; - struct device_node *dn; - const unsigned int *prop; - unsigned int l; - struct macio_chip* macio; - - if (!machine_is(powermac)) - return -ENODEV; - - chip->subframe = 0; - chip->revision = 0; - chip->freqs_ok = 0xff; /* all ok */ - chip->model = PMAC_AWACS; - chip->can_byte_swap = 1; - chip->can_duplex = 1; - chip->can_capture = 1; - chip->num_freqs = ARRAY_SIZE(awacs_freqs); - chip->freq_table = awacs_freqs; - chip->pdev = NULL; - - chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */ - - /* check machine type */ - if (of_machine_is_compatible("AAPL,3400/2400") - || of_machine_is_compatible("AAPL,3500")) - chip->is_pbook_3400 = 1; - else if (of_machine_is_compatible("PowerBook1,1") - || of_machine_is_compatible("AAPL,PowerBook1998")) - chip->is_pbook_G3 = 1; - chip->node = of_find_node_by_name(NULL, "awacs"); - sound = of_node_get(chip->node); - - /* - * powermac G3 models have a node called "davbus" - * with a child called "sound". - */ - if (!chip->node) - chip->node = of_find_node_by_name(NULL, "davbus"); - /* - * if we didn't find a davbus device, try 'i2s-a' since - * this seems to be what iBooks have - */ - if (! chip->node) { - chip->node = of_find_node_by_name(NULL, "i2s-a"); - if (chip->node && chip->node->parent && - chip->node->parent->parent) { - if (of_device_is_compatible(chip->node->parent->parent, - "K2-Keylargo")) - chip->is_k2 = 1; - } - } - if (! chip->node) - return -ENODEV; - - if (!sound) { - sound = of_find_node_by_name(NULL, "sound"); - while (sound && sound->parent != chip->node) - sound = of_find_node_by_name(sound, "sound"); - } - if (! sound) { - of_node_put(chip->node); - chip->node = NULL; - return -ENODEV; - } - prop = of_get_property(sound, "sub-frame", NULL); - if (prop && *prop < 16) - chip->subframe = *prop; - prop = of_get_property(sound, "layout-id", NULL); - if (prop) { - /* partly deprecate snd-powermac, for those machines - * that have a layout-id property for now */ - printk(KERN_INFO "snd-powermac no longer handles any " - "machines with a layout-id property " - "in the device-tree, use snd-aoa.\n"); - of_node_put(sound); - of_node_put(chip->node); - chip->node = NULL; - return -ENODEV; - } - /* This should be verified on older screamers */ - if (of_device_is_compatible(sound, "screamer")) { - chip->model = PMAC_SCREAMER; - // chip->can_byte_swap = 0; /* FIXME: check this */ - } - if (of_device_is_compatible(sound, "burgundy")) { - chip->model = PMAC_BURGUNDY; - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ - } - if (of_device_is_compatible(sound, "daca")) { - chip->model = PMAC_DACA; - chip->can_capture = 0; /* no capture */ - chip->can_duplex = 0; - // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ - } - if (of_device_is_compatible(sound, "tumbler")) { - chip->model = PMAC_TUMBLER; - chip->can_capture = of_machine_is_compatible("PowerMac4,2") - || of_machine_is_compatible("PowerBook3,2") - || of_machine_is_compatible("PowerBook3,3") - || of_machine_is_compatible("PowerBook4,1") - || of_machine_is_compatible("PowerBook4,2") - || of_machine_is_compatible("PowerBook4,3"); - chip->can_duplex = 0; - // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->num_freqs = ARRAY_SIZE(tumbler_freqs); - chip->freq_table = tumbler_freqs; - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ - } - if (of_device_is_compatible(sound, "snapper")) { - chip->model = PMAC_SNAPPER; - // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->num_freqs = ARRAY_SIZE(tumbler_freqs); - chip->freq_table = tumbler_freqs; - chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ - } - prop = of_get_property(sound, "device-id", NULL); - if (prop) - chip->device_id = *prop; - dn = of_find_node_by_name(NULL, "perch"); - chip->has_iic = (dn != NULL); - of_node_put(dn); - - /* We need the PCI device for DMA allocations, let's use a crude method - * for now ... - */ - macio = macio_find(chip->node, macio_unknown); - if (macio == NULL) - printk(KERN_WARNING "snd-powermac: can't locate macio !\n"); - else { - struct pci_dev *pdev = NULL; - - for_each_pci_dev(pdev) { - struct device_node *np = pci_device_to_OF_node(pdev); - if (np && np == macio->of_node) { - chip->pdev = pdev; - break; - } - } - } - if (chip->pdev == NULL) - printk(KERN_WARNING "snd-powermac: can't locate macio PCI" - " device !\n"); - - detect_byte_swap(chip); - - /* look for a property saying what sample rates - are available */ - prop = of_get_property(sound, "sample-rates", &l); - if (! prop) - prop = of_get_property(sound, "output-frame-rates", &l); - if (prop) { - int i; - chip->freqs_ok = 0; - for (l /= sizeof(int); l > 0; --l) { - unsigned int r = *prop++; - /* Apple 'Fixed' format */ - if (r >= 0x10000) - r >>= 16; - for (i = 0; i < chip->num_freqs; ++i) { - if (r == chip->freq_table[i]) { - chip->freqs_ok |= (1 << i); - break; - } - } - } - } else { - /* assume only 44.1khz */ - chip->freqs_ok = 1; - } - - of_node_put(sound); - return 0; -} - -#ifdef PMAC_SUPPORT_AUTOMUTE -/* - * auto-mute - */ -static int pmac_auto_mute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = chip->auto_mute; - return 0; -} - -static int pmac_auto_mute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - if (ucontrol->value.integer.value[0] != chip->auto_mute) { - chip->auto_mute = !!ucontrol->value.integer.value[0]; - if (chip->update_automute) - chip->update_automute(chip, 1); - return 1; - } - return 0; -} - -static int pmac_hp_detect_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - if (chip->detect_headphone) - ucontrol->value.integer.value[0] = chip->detect_headphone(chip); - else - ucontrol->value.integer.value[0] = 0; - return 0; -} - -static struct snd_kcontrol_new auto_mute_controls[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Auto Mute Switch", - .info = snd_pmac_boolean_mono_info, - .get = pmac_auto_mute_get, - .put = pmac_auto_mute_put, - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Detection", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_pmac_boolean_mono_info, - .get = pmac_hp_detect_get, - }, -}; - -int __devinit snd_pmac_add_automute(struct snd_pmac *chip) -{ - int err; - chip->auto_mute = 1; - err = snd_ctl_add(chip->card, snd_ctl_new1(&auto_mute_controls[0], chip)); - if (err < 0) { - printk(KERN_ERR "snd-powermac: Failed to add automute control\n"); - return err; - } - chip->hp_detect_ctl = snd_ctl_new1(&auto_mute_controls[1], chip); - return snd_ctl_add(chip->card, chip->hp_detect_ctl); -} -#endif /* PMAC_SUPPORT_AUTOMUTE */ - -/* - * create and detect a pmac chip record - */ -int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) -{ - struct snd_pmac *chip; - struct device_node *np; - int i, err; - unsigned int irq; - unsigned long ctrl_addr, txdma_addr, rxdma_addr; - static struct snd_device_ops ops = { - .dev_free = snd_pmac_dev_free, - }; - - *chip_return = NULL; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - chip->card = card; - - spin_lock_init(&chip->reg_lock); - chip->irq = chip->tx_irq = chip->rx_irq = -1; - - chip->playback.stream = SNDRV_PCM_STREAM_PLAYBACK; - chip->capture.stream = SNDRV_PCM_STREAM_CAPTURE; - - if ((err = snd_pmac_detect(chip)) < 0) - goto __error; - - if (snd_pmac_dbdma_alloc(chip, &chip->playback.cmd, PMAC_MAX_FRAGS + 1) < 0 || - snd_pmac_dbdma_alloc(chip, &chip->capture.cmd, PMAC_MAX_FRAGS + 1) < 0 || - snd_pmac_dbdma_alloc(chip, &chip->extra_dma, 2) < 0 || - snd_pmac_dbdma_alloc(chip, &emergency_dbdma, 2) < 0) { - err = -ENOMEM; - goto __error; - } - - np = chip->node; - chip->requested = 0; - if (chip->is_k2) { - static char *rnames[] = { - "Sound Control", "Sound DMA" }; - for (i = 0; i < 2; i ++) { - if (of_address_to_resource(np->parent, i, - &chip->rsrc[i])) { - printk(KERN_ERR "snd: can't translate rsrc " - " %d (%s)\n", i, rnames[i]); - err = -ENODEV; - goto __error; - } - if (request_mem_region(chip->rsrc[i].start, - resource_size(&chip->rsrc[i]), - rnames[i]) == NULL) { - printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: %pR)\n", - i, rnames[i], &chip->rsrc[i]); - err = -ENODEV; - goto __error; - } - chip->requested |= (1 << i); - } - ctrl_addr = chip->rsrc[0].start; - txdma_addr = chip->rsrc[1].start; - rxdma_addr = txdma_addr + 0x100; - } else { - static char *rnames[] = { - "Sound Control", "Sound Tx DMA", "Sound Rx DMA" }; - for (i = 0; i < 3; i ++) { - if (of_address_to_resource(np, i, - &chip->rsrc[i])) { - printk(KERN_ERR "snd: can't translate rsrc " - " %d (%s)\n", i, rnames[i]); - err = -ENODEV; - goto __error; - } - if (request_mem_region(chip->rsrc[i].start, - resource_size(&chip->rsrc[i]), - rnames[i]) == NULL) { - printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: %pR)\n", - i, rnames[i], &chip->rsrc[i]); - err = -ENODEV; - goto __error; - } - chip->requested |= (1 << i); - } - ctrl_addr = chip->rsrc[0].start; - txdma_addr = chip->rsrc[1].start; - rxdma_addr = chip->rsrc[2].start; - } - - chip->awacs = ioremap(ctrl_addr, 0x1000); - chip->playback.dma = ioremap(txdma_addr, 0x100); - chip->capture.dma = ioremap(rxdma_addr, 0x100); - if (chip->model <= PMAC_BURGUNDY) { - irq = irq_of_parse_and_map(np, 0); - if (request_irq(irq, snd_pmac_ctrl_intr, 0, - "PMac", (void*)chip)) { - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", - irq); - err = -EBUSY; - goto __error; - } - chip->irq = irq; - } - irq = irq_of_parse_and_map(np, 1); - if (request_irq(irq, snd_pmac_tx_intr, 0, "PMac Output", (void*)chip)){ - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", irq); - err = -EBUSY; - goto __error; - } - chip->tx_irq = irq; - irq = irq_of_parse_and_map(np, 2); - if (request_irq(irq, snd_pmac_rx_intr, 0, "PMac Input", (void*)chip)) { - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", irq); - err = -EBUSY; - goto __error; - } - chip->rx_irq = irq; - - snd_pmac_sound_feature(chip, 1); - - /* reset & enable interrupts */ - if (chip->model <= PMAC_BURGUNDY) - out_le32(&chip->awacs->control, chip->control_mask); - - /* Powerbooks have odd ways of enabling inputs such as - an expansion-bay CD or sound from an internal modem - or a PC-card modem. */ - if (chip->is_pbook_3400) { - /* Enable CD and PC-card sound inputs. */ - /* This is done by reading from address - * f301a000, + 0x10 to enable the expansion-bay - * CD sound input, + 0x80 to enable the PC-card - * sound input. The 0x100 enables the SCSI bus - * terminator power. - */ - chip->latch_base = ioremap (0xf301a000, 0x1000); - in_8(chip->latch_base + 0x190); - } else if (chip->is_pbook_G3) { - struct device_node* mio; - for (mio = chip->node->parent; mio; mio = mio->parent) { - if (strcmp(mio->name, "mac-io") == 0) { - struct resource r; - if (of_address_to_resource(mio, 0, &r) == 0) - chip->macio_base = - ioremap(r.start, 0x40); - break; - } - } - /* Enable CD sound input. */ - /* The relevant bits for writing to this byte are 0x8f. - * I haven't found out what the 0x80 bit does. - * For the 0xf bits, writing 3 or 7 enables the CD - * input, any other value disables it. Values - * 1, 3, 5, 7 enable the microphone. Values 0, 2, - * 4, 6, 8 - f enable the input from the modem. - */ - if (chip->macio_base) - out_8(chip->macio_base + 0x37, 3); - } - - /* Reset dbdma channels */ - snd_pmac_dbdma_reset(chip); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) - goto __error; - - *chip_return = chip; - return 0; - - __error: - snd_pmac_free(chip); - return err; -} - - -/* - * sleep notify for powerbook - */ - -#ifdef CONFIG_PM - -/* - * Save state when going to sleep, restore it afterwards. - */ - -void snd_pmac_suspend(struct snd_pmac *chip) -{ - unsigned long flags; - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); - if (chip->suspend) - chip->suspend(chip); - snd_pcm_suspend_all(chip->pcm); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_pmac_beep_stop(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (chip->irq >= 0) - disable_irq(chip->irq); - if (chip->tx_irq >= 0) - disable_irq(chip->tx_irq); - if (chip->rx_irq >= 0) - disable_irq(chip->rx_irq); - snd_pmac_sound_feature(chip, 0); -} - -void snd_pmac_resume(struct snd_pmac *chip) -{ - snd_pmac_sound_feature(chip, 1); - if (chip->resume) - chip->resume(chip); - /* enable CD sound input */ - if (chip->macio_base && chip->is_pbook_G3) - out_8(chip->macio_base + 0x37, 3); - else if (chip->is_pbook_3400) - in_8(chip->latch_base + 0x190); - - snd_pmac_pcm_set_format(chip); - - if (chip->irq >= 0) - enable_irq(chip->irq); - if (chip->tx_irq >= 0) - enable_irq(chip->tx_irq); - if (chip->rx_irq >= 0) - enable_irq(chip->rx_irq); - - snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); -} - -#endif /* CONFIG_PM */ - diff --git a/ANDROID_3.4.5/sound/ppc/pmac.h b/ANDROID_3.4.5/sound/ppc/pmac.h deleted file mode 100644 index 25c512c2..00000000 --- a/ANDROID_3.4.5/sound/ppc/pmac.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Driver for PowerMac onboard soundchips - * Copyright (c) 2001 by Takashi Iwai - * based on dmasound.c. - * - * 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 - */ - - -#ifndef __PMAC_H -#define __PMAC_H - -#include -#include -#include "awacs.h" - -#include -#ifdef CONFIG_ADB_CUDA -#include -#endif -#ifdef CONFIG_ADB_PMU -#include -#endif -#include -#include -#include -#include -#include -#include - -/* maximum number of fragments */ -#define PMAC_MAX_FRAGS 32 - - -#define PMAC_SUPPORT_AUTOMUTE - -/* - * DBDMA space - */ -struct pmac_dbdma { - dma_addr_t dma_base; - dma_addr_t addr; - struct dbdma_cmd __iomem *cmds; - void *space; - int size; -}; - -/* - * playback/capture stream - */ -struct pmac_stream { - int running; /* boolean */ - - int stream; /* PLAYBACK/CAPTURE */ - - int dma_size; /* in bytes */ - int period_size; /* in bytes */ - int buffer_size; /* in kbytes */ - int nperiods, cur_period; - - struct pmac_dbdma cmd; - volatile struct dbdma_regs __iomem *dma; - - struct snd_pcm_substream *substream; - - unsigned int cur_freqs; /* currently available frequencies */ - unsigned int cur_formats; /* currently available formats */ -}; - - -/* - */ - -enum snd_pmac_model { - PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, - PMAC_SNAPPER -}; - -struct snd_pmac { - struct snd_card *card; - - /* h/w info */ - struct device_node *node; - struct pci_dev *pdev; - unsigned int revision; - unsigned int manufacturer; - unsigned int subframe; - unsigned int device_id; - enum snd_pmac_model model; - - unsigned int has_iic : 1; - unsigned int is_pbook_3400 : 1; - unsigned int is_pbook_G3 : 1; - unsigned int is_k2 : 1; - - unsigned int can_byte_swap : 1; - unsigned int can_duplex : 1; - unsigned int can_capture : 1; - - unsigned int auto_mute : 1; - unsigned int initialized : 1; - unsigned int feature_is_set : 1; - - unsigned int requested; - struct resource rsrc[3]; - - int num_freqs; - int *freq_table; - unsigned int freqs_ok; /* bit flags */ - unsigned int formats_ok; /* pcm hwinfo */ - int active; - int rate_index; - int format; /* current format */ - - spinlock_t reg_lock; - volatile struct awacs_regs __iomem *awacs; - int awacs_reg[8]; /* register cache */ - unsigned int hp_stat_mask; - - unsigned char __iomem *latch_base; - unsigned char __iomem *macio_base; - - struct pmac_stream playback; - struct pmac_stream capture; - - struct pmac_dbdma extra_dma; - - int irq, tx_irq, rx_irq; - - struct snd_pcm *pcm; - - struct pmac_beep *beep; - - unsigned int control_mask; /* control mask */ - - /* mixer stuffs */ - void *mixer_data; - void (*mixer_free)(struct snd_pmac *); - struct snd_kcontrol *master_sw_ctl; - struct snd_kcontrol *speaker_sw_ctl; - struct snd_kcontrol *drc_sw_ctl; /* only used for tumbler -ReneR */ - struct snd_kcontrol *hp_detect_ctl; - struct snd_kcontrol *lineout_sw_ctl; - - /* lowlevel callbacks */ - void (*set_format)(struct snd_pmac *chip); - void (*update_automute)(struct snd_pmac *chip, int do_notify); - int (*detect_headphone)(struct snd_pmac *chip); -#ifdef CONFIG_PM - void (*suspend)(struct snd_pmac *chip); - void (*resume)(struct snd_pmac *chip); -#endif - -}; - - -/* exported functions */ -int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return); -int snd_pmac_pcm_new(struct snd_pmac *chip); -int snd_pmac_attach_beep(struct snd_pmac *chip); -void snd_pmac_detach_beep(struct snd_pmac *chip); -void snd_pmac_beep_stop(struct snd_pmac *chip); -unsigned int snd_pmac_rate_index(struct snd_pmac *chip, struct pmac_stream *rec, unsigned int rate); - -void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long addr, int speed); -void snd_pmac_beep_dma_stop(struct snd_pmac *chip); - -#ifdef CONFIG_PM -void snd_pmac_suspend(struct snd_pmac *chip); -void snd_pmac_resume(struct snd_pmac *chip); -#endif - -/* initialize mixer */ -int snd_pmac_awacs_init(struct snd_pmac *chip); -int snd_pmac_burgundy_init(struct snd_pmac *chip); -int snd_pmac_daca_init(struct snd_pmac *chip); -int snd_pmac_tumbler_init(struct snd_pmac *chip); -int snd_pmac_tumbler_post_init(void); - -/* i2c functions */ -struct pmac_keywest { - int addr; - struct i2c_client *client; - int id; - int (*init_client)(struct pmac_keywest *i2c); - char *name; -}; - -int snd_pmac_keywest_init(struct pmac_keywest *i2c); -void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c); - -/* misc */ -#define snd_pmac_boolean_stereo_info snd_ctl_boolean_stereo_info -#define snd_pmac_boolean_mono_info snd_ctl_boolean_mono_info - -int snd_pmac_add_automute(struct snd_pmac *chip); - -#endif /* __PMAC_H */ diff --git a/ANDROID_3.4.5/sound/ppc/powermac.c b/ANDROID_3.4.5/sound/ppc/powermac.c deleted file mode 100644 index 5a4e263b..00000000 --- a/ANDROID_3.4.5/sound/ppc/powermac.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Driver for PowerMac AWACS - * Copyright (c) 2001 by Takashi Iwai - * based on dmasound.c. - * - * 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 "pmac.h" -#include "awacs.h" -#include "burgundy.h" - -#define CHIP_NAME "PMac" - -MODULE_DESCRIPTION("PowerMac"); -MODULE_SUPPORTED_DEVICE("{{Apple,PowerMac}}"); -MODULE_LICENSE("GPL"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static bool enable_beep = 1; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for " CHIP_NAME " soundchip."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for " CHIP_NAME " soundchip."); -module_param(enable_beep, bool, 0444); -MODULE_PARM_DESC(enable_beep, "Enable beep using PCM."); - -static struct platform_device *device; - - -/* - */ - -static int __devinit snd_pmac_probe(struct platform_device *devptr) -{ - struct snd_card *card; - struct snd_pmac *chip; - char *name_ext; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_pmac_new(card, &chip)) < 0) - goto __error; - card->private_data = chip; - - switch (chip->model) { - case PMAC_BURGUNDY: - strcpy(card->driver, "PMac Burgundy"); - strcpy(card->shortname, "PowerMac Burgundy"); - sprintf(card->longname, "%s (Dev %d) Sub-frame %d", - card->shortname, chip->device_id, chip->subframe); - if ((err = snd_pmac_burgundy_init(chip)) < 0) - goto __error; - break; - case PMAC_DACA: - strcpy(card->driver, "PMac DACA"); - strcpy(card->shortname, "PowerMac DACA"); - sprintf(card->longname, "%s (Dev %d) Sub-frame %d", - card->shortname, chip->device_id, chip->subframe); - if ((err = snd_pmac_daca_init(chip)) < 0) - goto __error; - break; - case PMAC_TUMBLER: - case PMAC_SNAPPER: - name_ext = chip->model == PMAC_TUMBLER ? "Tumbler" : "Snapper"; - sprintf(card->driver, "PMac %s", name_ext); - sprintf(card->shortname, "PowerMac %s", name_ext); - sprintf(card->longname, "%s (Dev %d) Sub-frame %d", - card->shortname, chip->device_id, chip->subframe); - if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) - goto __error; - break; - case PMAC_AWACS: - case PMAC_SCREAMER: - name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS"; - sprintf(card->driver, "PMac %s", name_ext); - sprintf(card->shortname, "PowerMac %s", name_ext); - if (chip->is_pbook_3400) - name_ext = " [PB3400]"; - else if (chip->is_pbook_G3) - name_ext = " [PBG3]"; - else - name_ext = ""; - sprintf(card->longname, "%s%s Rev %d", - card->shortname, name_ext, chip->revision); - if ((err = snd_pmac_awacs_init(chip)) < 0) - goto __error; - break; - default: - snd_printk(KERN_ERR "unsupported hardware %d\n", chip->model); - err = -EINVAL; - goto __error; - } - - if ((err = snd_pmac_pcm_new(chip)) < 0) - goto __error; - - chip->initialized = 1; - if (enable_beep) - snd_pmac_attach_beep(chip); - - snd_card_set_dev(card, &devptr->dev); - - if ((err = snd_card_register(card)) < 0) - goto __error; - - platform_set_drvdata(devptr, card); - return 0; - -__error: - snd_card_free(card); - return err; -} - - -static int __devexit snd_pmac_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_pmac_driver_suspend(struct platform_device *devptr, pm_message_t state) -{ - struct snd_card *card = platform_get_drvdata(devptr); - snd_pmac_suspend(card->private_data); - return 0; -} - -static int snd_pmac_driver_resume(struct platform_device *devptr) -{ - struct snd_card *card = platform_get_drvdata(devptr); - snd_pmac_resume(card->private_data); - return 0; -} -#endif - -#define SND_PMAC_DRIVER "snd_powermac" - -static struct platform_driver snd_pmac_driver = { - .probe = snd_pmac_probe, - .remove = __devexit_p(snd_pmac_remove), -#ifdef CONFIG_PM - .suspend = snd_pmac_driver_suspend, - .resume = snd_pmac_driver_resume, -#endif - .driver = { - .name = SND_PMAC_DRIVER - }, -}; - -static int __init alsa_card_pmac_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_pmac_driver)) < 0) - return err; - device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); - return 0; - -} - -static void __exit alsa_card_pmac_exit(void) -{ - if (!IS_ERR(device)) - platform_device_unregister(device); - platform_driver_unregister(&snd_pmac_driver); -} - -module_init(alsa_card_pmac_init) -module_exit(alsa_card_pmac_exit) diff --git a/ANDROID_3.4.5/sound/ppc/snd_ps3.c b/ANDROID_3.4.5/sound/ppc/snd_ps3.c deleted file mode 100644 index 1aa52eff..00000000 --- a/ANDROID_3.4.5/sound/ppc/snd_ps3.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * Audio support for PS3 - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * All rights reserved. - * Copyright 2006, 2007 Sony Corporation - * - * 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; version 2 of the Licence. - * - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "snd_ps3.h" -#include "snd_ps3_reg.h" - - -/* - * global - */ -static struct snd_ps3_card_info the_card; - -static int snd_ps3_start_delay = CONFIG_SND_PS3_DEFAULT_START_DELAY; - -module_param_named(start_delay, snd_ps3_start_delay, uint, 0644); -MODULE_PARM_DESC(start_delay, "time to insert silent data in ms"); - -static int index = SNDRV_DEFAULT_IDX1; -static char *id = SNDRV_DEFAULT_STR1; - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for PS3 soundchip."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for PS3 soundchip."); - - -/* - * PS3 audio register access - */ -static inline u32 read_reg(unsigned int reg) -{ - return in_be32(the_card.mapped_mmio_vaddr + reg); -} -static inline void write_reg(unsigned int reg, u32 val) -{ - out_be32(the_card.mapped_mmio_vaddr + reg, val); -} -static inline void update_reg(unsigned int reg, u32 or_val) -{ - u32 newval = read_reg(reg) | or_val; - write_reg(reg, newval); -} -static inline void update_mask_reg(unsigned int reg, u32 mask, u32 or_val) -{ - u32 newval = (read_reg(reg) & mask) | or_val; - write_reg(reg, newval); -} - -/* - * ALSA defs - */ -static const struct snd_pcm_hardware snd_ps3_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_S16_BE | - SNDRV_PCM_FMTBIT_S24_BE), - .rates = (SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000), - .rate_min = 44100, - .rate_max = 96000, - - .channels_min = 2, /* stereo only */ - .channels_max = 2, - - .buffer_bytes_max = PS3_AUDIO_FIFO_SIZE * 64, - - /* interrupt by four stages */ - .period_bytes_min = PS3_AUDIO_FIFO_STAGE_SIZE * 4, - .period_bytes_max = PS3_AUDIO_FIFO_STAGE_SIZE * 4, - - .periods_min = 16, - .periods_max = 32, /* buffer_size_max/ period_bytes_max */ - - .fifo_size = PS3_AUDIO_FIFO_SIZE -}; - -static int snd_ps3_verify_dma_stop(struct snd_ps3_card_info *card, - int count, int force_stop) -{ - int dma_ch, done, retries, stop_forced = 0; - uint32_t status; - - for (dma_ch = 0; dma_ch < 8; dma_ch++) { - retries = count; - do { - status = read_reg(PS3_AUDIO_KICK(dma_ch)) & - PS3_AUDIO_KICK_STATUS_MASK; - switch (status) { - case PS3_AUDIO_KICK_STATUS_DONE: - case PS3_AUDIO_KICK_STATUS_NOTIFY: - case PS3_AUDIO_KICK_STATUS_CLEAR: - case PS3_AUDIO_KICK_STATUS_ERROR: - done = 1; - break; - default: - done = 0; - udelay(10); - } - } while (!done && --retries); - if (!retries && force_stop) { - pr_info("%s: DMA ch %d is not stopped.", - __func__, dma_ch); - /* last resort. force to stop dma. - * NOTE: this cause DMA done interrupts - */ - update_reg(PS3_AUDIO_CONFIG, PS3_AUDIO_CONFIG_CLEAR); - stop_forced = 1; - } - } - return stop_forced; -} - -/* - * wait for all dma is done. - * NOTE: caller should reset card->running before call. - * If not, the interrupt handler will re-start DMA, - * then DMA is never stopped. - */ -static void snd_ps3_wait_for_dma_stop(struct snd_ps3_card_info *card) -{ - int stop_forced; - /* - * wait for the last dma is done - */ - - /* - * expected maximum DMA done time is 5.7ms + something (DMA itself). - * 5.7ms is from 16bit/sample 2ch 44.1Khz; the time next - * DMA kick event would occur. - */ - stop_forced = snd_ps3_verify_dma_stop(card, 700, 1); - - /* - * clear outstanding interrupts. - */ - update_reg(PS3_AUDIO_INTR_0, 0); - update_reg(PS3_AUDIO_AX_IS, 0); - - /* - *revert CLEAR bit since it will not reset automatically after DMA stop - */ - if (stop_forced) - update_mask_reg(PS3_AUDIO_CONFIG, ~PS3_AUDIO_CONFIG_CLEAR, 0); - /* ensure the hardware sees changes */ - wmb(); -} - -static void snd_ps3_kick_dma(struct snd_ps3_card_info *card) -{ - - update_reg(PS3_AUDIO_KICK(0), PS3_AUDIO_KICK_REQUEST); - /* ensure the hardware sees the change */ - wmb(); -} - -/* - * convert virtual addr to ioif bus addr. - */ -static dma_addr_t v_to_bus(struct snd_ps3_card_info *card, void *paddr, int ch) -{ - return card->dma_start_bus_addr[ch] + - (paddr - card->dma_start_vaddr[ch]); -}; - - -/* - * increment ring buffer pointer. - * NOTE: caller must hold write spinlock - */ -static void snd_ps3_bump_buffer(struct snd_ps3_card_info *card, - enum snd_ps3_ch ch, size_t byte_count, - int stage) -{ - if (!stage) - card->dma_last_transfer_vaddr[ch] = - card->dma_next_transfer_vaddr[ch]; - card->dma_next_transfer_vaddr[ch] += byte_count; - if ((card->dma_start_vaddr[ch] + (card->dma_buffer_size / 2)) <= - card->dma_next_transfer_vaddr[ch]) { - card->dma_next_transfer_vaddr[ch] = card->dma_start_vaddr[ch]; - } -} -/* - * setup dmac to send data to audio and attenuate samples on the ring buffer - */ -static int snd_ps3_program_dma(struct snd_ps3_card_info *card, - enum snd_ps3_dma_filltype filltype) -{ - /* this dmac does not support over 4G */ - uint32_t dma_addr; - int fill_stages, dma_ch, stage; - enum snd_ps3_ch ch; - uint32_t ch0_kick_event = 0; /* initialize to mute gcc */ - void *start_vaddr; - unsigned long irqsave; - int silent = 0; - - switch (filltype) { - case SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL: - silent = 1; - /* intentionally fall thru */ - case SND_PS3_DMA_FILLTYPE_FIRSTFILL: - ch0_kick_event = PS3_AUDIO_KICK_EVENT_ALWAYS; - break; - - case SND_PS3_DMA_FILLTYPE_SILENT_RUNNING: - silent = 1; - /* intentionally fall thru */ - case SND_PS3_DMA_FILLTYPE_RUNNING: - ch0_kick_event = PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY; - break; - } - - snd_ps3_verify_dma_stop(card, 700, 0); - fill_stages = 4; - spin_lock_irqsave(&card->dma_lock, irqsave); - for (ch = 0; ch < 2; ch++) { - start_vaddr = card->dma_next_transfer_vaddr[0]; - for (stage = 0; stage < fill_stages; stage++) { - dma_ch = stage * 2 + ch; - if (silent) - dma_addr = card->null_buffer_start_dma_addr; - else - dma_addr = - v_to_bus(card, - card->dma_next_transfer_vaddr[ch], - ch); - - write_reg(PS3_AUDIO_SOURCE(dma_ch), - (PS3_AUDIO_SOURCE_TARGET_SYSTEM_MEMORY | - dma_addr)); - - /* dst: fixed to 3wire#0 */ - if (ch == 0) - write_reg(PS3_AUDIO_DEST(dma_ch), - (PS3_AUDIO_DEST_TARGET_AUDIOFIFO | - PS3_AUDIO_AO_3W_LDATA(0))); - else - write_reg(PS3_AUDIO_DEST(dma_ch), - (PS3_AUDIO_DEST_TARGET_AUDIOFIFO | - PS3_AUDIO_AO_3W_RDATA(0))); - - /* count always 1 DMA block (1/2 stage = 128 bytes) */ - write_reg(PS3_AUDIO_DMASIZE(dma_ch), 0); - /* bump pointer if needed */ - if (!silent) - snd_ps3_bump_buffer(card, ch, - PS3_AUDIO_DMAC_BLOCK_SIZE, - stage); - - /* kick event */ - if (dma_ch == 0) - write_reg(PS3_AUDIO_KICK(dma_ch), - ch0_kick_event); - else - write_reg(PS3_AUDIO_KICK(dma_ch), - PS3_AUDIO_KICK_EVENT_AUDIO_DMA(dma_ch - - 1) | - PS3_AUDIO_KICK_REQUEST); - } - } - /* ensure the hardware sees the change */ - wmb(); - spin_unlock_irqrestore(&card->dma_lock, irqsave); - - return 0; -} - -/* - * Interrupt handler - */ -static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id) -{ - - uint32_t port_intr; - int underflow_occured = 0; - struct snd_ps3_card_info *card = dev_id; - - if (!card->running) { - update_reg(PS3_AUDIO_AX_IS, 0); - update_reg(PS3_AUDIO_INTR_0, 0); - return IRQ_HANDLED; - } - - port_intr = read_reg(PS3_AUDIO_AX_IS); - /* - *serial buffer empty detected (every 4 times), - *program next dma and kick it - */ - if (port_intr & PS3_AUDIO_AX_IE_ASOBEIE(0)) { - write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBEIE(0)); - if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) { - write_reg(PS3_AUDIO_AX_IS, port_intr); - underflow_occured = 1; - } - if (card->silent) { - /* we are still in silent time */ - snd_ps3_program_dma(card, - (underflow_occured) ? - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL : - SND_PS3_DMA_FILLTYPE_SILENT_RUNNING); - snd_ps3_kick_dma(card); - card->silent--; - } else { - snd_ps3_program_dma(card, - (underflow_occured) ? - SND_PS3_DMA_FILLTYPE_FIRSTFILL : - SND_PS3_DMA_FILLTYPE_RUNNING); - snd_ps3_kick_dma(card); - snd_pcm_period_elapsed(card->substream); - } - } else if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) { - write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBUIE(0)); - /* - * serial out underflow, but buffer empty not detected. - * in this case, fill fifo with 0 to recover. After - * filling dummy data, serial automatically start to - * consume them and then will generate normal buffer - * empty interrupts. - * If both buffer underflow and buffer empty are occurred, - * it is better to do nomal data transfer than empty one - */ - snd_ps3_program_dma(card, - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); - snd_ps3_kick_dma(card); - snd_ps3_program_dma(card, - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); - snd_ps3_kick_dma(card); - } - /* clear interrupt cause */ - return IRQ_HANDLED; -}; - -/* - * audio mute on/off - * mute_on : 0 output enabled - * 1 mute - */ -static int snd_ps3_mute(int mute_on) -{ - return ps3av_audio_mute(mute_on); -} - -/* - * av setting - * NOTE: calling this function may generate audio interrupt. - */ -static int snd_ps3_change_avsetting(struct snd_ps3_card_info *card) -{ - int ret, retries, i; - pr_debug("%s: start\n", __func__); - - ret = ps3av_set_audio_mode(card->avs.avs_audio_ch, - card->avs.avs_audio_rate, - card->avs.avs_audio_width, - card->avs.avs_audio_format, - card->avs.avs_audio_source); - /* - * Reset the following unwanted settings: - */ - - /* disable all 3wire buffers */ - update_mask_reg(PS3_AUDIO_AO_3WMCTRL, - ~(PS3_AUDIO_AO_3WMCTRL_ASOEN(0) | - PS3_AUDIO_AO_3WMCTRL_ASOEN(1) | - PS3_AUDIO_AO_3WMCTRL_ASOEN(2) | - PS3_AUDIO_AO_3WMCTRL_ASOEN(3)), - 0); - wmb(); /* ensure the hardware sees the change */ - /* wait for actually stopped */ - retries = 1000; - while ((read_reg(PS3_AUDIO_AO_3WMCTRL) & - (PS3_AUDIO_AO_3WMCTRL_ASORUN(0) | - PS3_AUDIO_AO_3WMCTRL_ASORUN(1) | - PS3_AUDIO_AO_3WMCTRL_ASORUN(2) | - PS3_AUDIO_AO_3WMCTRL_ASORUN(3))) && - --retries) { - udelay(1); - } - - /* reset buffer pointer */ - for (i = 0; i < 4; i++) { - update_reg(PS3_AUDIO_AO_3WCTRL(i), - PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET); - udelay(10); - } - wmb(); /* ensure the hardware actually start resetting */ - - /* enable 3wire#0 buffer */ - update_reg(PS3_AUDIO_AO_3WMCTRL, PS3_AUDIO_AO_3WMCTRL_ASOEN(0)); - - - /* In 24bit mode,ALSA inserts a zero byte at first byte of per sample */ - update_mask_reg(PS3_AUDIO_AO_3WCTRL(0), - ~PS3_AUDIO_AO_3WCTRL_ASODF, - PS3_AUDIO_AO_3WCTRL_ASODF_LSB); - update_mask_reg(PS3_AUDIO_AO_SPDCTRL(0), - ~PS3_AUDIO_AO_SPDCTRL_SPODF, - PS3_AUDIO_AO_SPDCTRL_SPODF_LSB); - /* ensure all the setting above is written back to register */ - wmb(); - /* avsetting driver altered AX_IE, caller must reset it if you want */ - pr_debug("%s: end\n", __func__); - return ret; -} - -/* - * set sampling rate according to the substream - */ -static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream) -{ - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - struct snd_ps3_avsetting_info avs; - int ret; - - avs = card->avs; - - pr_debug("%s: called freq=%d width=%d\n", __func__, - substream->runtime->rate, - snd_pcm_format_width(substream->runtime->format)); - - pr_debug("%s: before freq=%d width=%d\n", __func__, - card->avs.avs_audio_rate, card->avs.avs_audio_width); - - /* sample rate */ - switch (substream->runtime->rate) { - case 44100: - avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_44K; - break; - case 48000: - avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K; - break; - case 88200: - avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_88K; - break; - case 96000: - avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_96K; - break; - default: - pr_info("%s: invalid rate %d\n", __func__, - substream->runtime->rate); - return 1; - } - - /* width */ - switch (snd_pcm_format_width(substream->runtime->format)) { - case 16: - avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16; - break; - case 24: - avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_24; - break; - default: - pr_info("%s: invalid width %d\n", __func__, - snd_pcm_format_width(substream->runtime->format)); - return 1; - } - - memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8); - - if (memcmp(&card->avs, &avs, sizeof(avs))) { - pr_debug("%s: after freq=%d width=%d\n", __func__, - card->avs.avs_audio_rate, card->avs.avs_audio_width); - - card->avs = avs; - snd_ps3_change_avsetting(card); - ret = 0; - } else - ret = 1; - - /* check CS non-audio bit and mute accordingly */ - if (avs.avs_cs_info[0] & 0x02) - ps3av_audio_mute_analog(1); /* mute if non-audio */ - else - ps3av_audio_mute_analog(0); - - return ret; -} - -/* - * PCM operators - */ -static int snd_ps3_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - int pcm_index; - - pcm_index = substream->pcm->device; - /* to retrieve substream/runtime in interrupt handler */ - card->substream = substream; - - runtime->hw = snd_ps3_pcm_hw; - - card->start_delay = snd_ps3_start_delay; - - /* mute off */ - snd_ps3_mute(0); /* this function sleep */ - - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - PS3_AUDIO_FIFO_STAGE_SIZE * 4 * 2); - return 0; -}; - -static int snd_ps3_pcm_close(struct snd_pcm_substream *substream) -{ - /* mute on */ - snd_ps3_mute(1); - return 0; -}; - -static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - size_t size; - - /* alloc transport buffer */ - size = params_buffer_bytes(hw_params); - snd_pcm_lib_malloc_pages(substream, size); - return 0; -}; - -static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream) -{ - int ret; - ret = snd_pcm_lib_free_pages(substream); - return ret; -}; - -static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream, - unsigned int delay_ms) -{ - int ret; - int rate ; - - rate = substream->runtime->rate; - ret = snd_pcm_format_size(substream->runtime->format, - rate * delay_ms / 1000) - * substream->runtime->channels; - - pr_debug("%s: time=%d rate=%d bytes=%ld, frames=%d, ret=%d\n", - __func__, - delay_ms, - rate, - snd_pcm_format_size(substream->runtime->format, rate), - rate * delay_ms / 1000, - ret); - - return ret; -}; - -static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - unsigned long irqsave; - - if (!snd_ps3_set_avsetting(substream)) { - /* some parameter changed */ - write_reg(PS3_AUDIO_AX_IE, - PS3_AUDIO_AX_IE_ASOBEIE(0) | - PS3_AUDIO_AX_IE_ASOBUIE(0)); - /* - * let SPDIF device re-lock with SPDIF signal, - * start with some silence - */ - card->silent = snd_ps3_delay_to_bytes(substream, - card->start_delay) / - (PS3_AUDIO_FIFO_STAGE_SIZE * 4); /* every 4 times */ - } - - /* restart ring buffer pointer */ - spin_lock_irqsave(&card->dma_lock, irqsave); - { - card->dma_buffer_size = runtime->dma_bytes; - - card->dma_last_transfer_vaddr[SND_PS3_CH_L] = - card->dma_next_transfer_vaddr[SND_PS3_CH_L] = - card->dma_start_vaddr[SND_PS3_CH_L] = - runtime->dma_area; - card->dma_start_bus_addr[SND_PS3_CH_L] = runtime->dma_addr; - - card->dma_last_transfer_vaddr[SND_PS3_CH_R] = - card->dma_next_transfer_vaddr[SND_PS3_CH_R] = - card->dma_start_vaddr[SND_PS3_CH_R] = - runtime->dma_area + (runtime->dma_bytes / 2); - card->dma_start_bus_addr[SND_PS3_CH_R] = - runtime->dma_addr + (runtime->dma_bytes / 2); - - pr_debug("%s: vaddr=%p bus=%#llx\n", __func__, - card->dma_start_vaddr[SND_PS3_CH_L], - card->dma_start_bus_addr[SND_PS3_CH_L]); - - } - spin_unlock_irqrestore(&card->dma_lock, irqsave); - - /* ensure the hardware sees the change */ - mb(); - - return 0; -}; - -static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* clear outstanding interrupts */ - update_reg(PS3_AUDIO_AX_IS, 0); - - spin_lock(&card->dma_lock); - { - card->running = 1; - } - spin_unlock(&card->dma_lock); - - snd_ps3_program_dma(card, - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); - snd_ps3_kick_dma(card); - while (read_reg(PS3_AUDIO_KICK(7)) & - PS3_AUDIO_KICK_STATUS_MASK) { - udelay(1); - } - snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_RUNNING); - snd_ps3_kick_dma(card); - break; - - case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&card->dma_lock); - { - card->running = 0; - } - spin_unlock(&card->dma_lock); - snd_ps3_wait_for_dma_stop(card); - break; - default: - break; - - } - - return ret; -}; - -/* - * report current pointer - */ -static snd_pcm_uframes_t snd_ps3_pcm_pointer( - struct snd_pcm_substream *substream) -{ - struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); - size_t bytes; - snd_pcm_uframes_t ret; - - spin_lock(&card->dma_lock); - { - bytes = (size_t)(card->dma_last_transfer_vaddr[SND_PS3_CH_L] - - card->dma_start_vaddr[SND_PS3_CH_L]); - } - spin_unlock(&card->dma_lock); - - ret = bytes_to_frames(substream->runtime, bytes * 2); - - return ret; -}; - -/* - * SPDIF status bits controls - */ -static int snd_ps3_spdif_mask_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -/* FIXME: ps3av_set_audio_mode() assumes only consumer mode */ -static int snd_ps3_spdif_cmask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - memset(ucontrol->value.iec958.status, 0xff, 8); - return 0; -} - -static int snd_ps3_spdif_pmask_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return 0; -} - -static int snd_ps3_spdif_default_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - memcpy(ucontrol->value.iec958.status, ps3av_mode_cs_info, 8); - return 0; -} - -static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - if (memcmp(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8)) { - memcpy(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8); - return 1; - } - return 0; -} - -static struct snd_kcontrol_new spdif_ctls[] = { - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), - .info = snd_ps3_spdif_mask_info, - .get = snd_ps3_spdif_cmask_get, - }, - { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), - .info = snd_ps3_spdif_mask_info, - .get = snd_ps3_spdif_pmask_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = snd_ps3_spdif_mask_info, - .get = snd_ps3_spdif_default_get, - .put = snd_ps3_spdif_default_put, - }, -}; - -static struct snd_pcm_ops snd_ps3_pcm_spdif_ops = { - .open = snd_ps3_pcm_open, - .close = snd_ps3_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ps3_pcm_hw_params, - .hw_free = snd_ps3_pcm_hw_free, - .prepare = snd_ps3_pcm_prepare, - .trigger = snd_ps3_pcm_trigger, - .pointer = snd_ps3_pcm_pointer, -}; - - -static int __devinit snd_ps3_map_mmio(void) -{ - the_card.mapped_mmio_vaddr = - ioremap(the_card.ps3_dev->m_region->bus_addr, - the_card.ps3_dev->m_region->len); - - if (!the_card.mapped_mmio_vaddr) { - pr_info("%s: ioremap 0 failed p=%#lx l=%#lx \n", - __func__, the_card.ps3_dev->m_region->lpar_addr, - the_card.ps3_dev->m_region->len); - return -ENXIO; - } - - return 0; -}; - -static void snd_ps3_unmap_mmio(void) -{ - iounmap(the_card.mapped_mmio_vaddr); - the_card.mapped_mmio_vaddr = NULL; -} - -static int __devinit snd_ps3_allocate_irq(void) -{ - int ret; - u64 lpar_addr, lpar_size; - u64 __iomem *mapped; - - /* FIXME: move this to device_init (H/W probe) */ - - /* get irq outlet */ - ret = lv1_gpu_device_map(1, &lpar_addr, &lpar_size); - if (ret) { - pr_info("%s: device map 1 failed %d\n", __func__, - ret); - return -ENXIO; - } - - mapped = ioremap(lpar_addr, lpar_size); - if (!mapped) { - pr_info("%s: ioremap 1 failed \n", __func__); - return -ENXIO; - } - - the_card.audio_irq_outlet = in_be64(mapped); - - iounmap(mapped); - ret = lv1_gpu_device_unmap(1); - if (ret) - pr_info("%s: unmap 1 failed\n", __func__); - - /* irq */ - ret = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, - the_card.audio_irq_outlet, - &the_card.irq_no); - if (ret) { - pr_info("%s:ps3_alloc_irq failed (%d)\n", __func__, ret); - return ret; - } - - ret = request_irq(the_card.irq_no, snd_ps3_interrupt, 0, - SND_PS3_DRIVER_NAME, &the_card); - if (ret) { - pr_info("%s: request_irq failed (%d)\n", __func__, ret); - goto cleanup_irq; - } - - return 0; - - cleanup_irq: - ps3_irq_plug_destroy(the_card.irq_no); - return ret; -}; - -static void snd_ps3_free_irq(void) -{ - free_irq(the_card.irq_no, &the_card); - ps3_irq_plug_destroy(the_card.irq_no); -} - -static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start) -{ - uint64_t val; - int ret; - - val = (ioaddr_start & (0x0fUL << 32)) >> (32 - 20) | - (0x03UL << 24) | - (0x0fUL << 12) | - (PS3_AUDIO_IOID); - - ret = lv1_gpu_attribute(0x100, 0x007, val); - if (ret) - pr_info("%s: gpu_attribute failed %d\n", __func__, - ret); -} - -static void __devinit snd_ps3_audio_fixup(struct snd_ps3_card_info *card) -{ - /* - * avsetting driver seems to never change the followings - * so, init them here once - */ - - /* no dma interrupt needed */ - write_reg(PS3_AUDIO_INTR_EN_0, 0); - - /* use every 4 buffer empty interrupt */ - update_mask_reg(PS3_AUDIO_AX_IC, - PS3_AUDIO_AX_IC_AASOIMD_MASK, - PS3_AUDIO_AX_IC_AASOIMD_EVERY4); - - /* enable 3wire clocks */ - update_mask_reg(PS3_AUDIO_AO_3WMCTRL, - ~(PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED | - PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED), - 0); - update_reg(PS3_AUDIO_AO_3WMCTRL, - PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT); -} - -static int __devinit snd_ps3_init_avsetting(struct snd_ps3_card_info *card) -{ - int ret; - pr_debug("%s: start\n", __func__); - card->avs.avs_audio_ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2; - card->avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K; - card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16; - card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM; - card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL; - memcpy(card->avs.avs_cs_info, ps3av_mode_cs_info, 8); - - ret = snd_ps3_change_avsetting(card); - - snd_ps3_audio_fixup(card); - - /* to start to generate SPDIF signal, fill data */ - snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); - snd_ps3_kick_dma(card); - pr_debug("%s: end\n", __func__); - return ret; -} - -static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev) -{ - int i, ret; - u64 lpar_addr, lpar_size; - - BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)); - BUG_ON(dev->match_id != PS3_MATCH_ID_SOUND); - - the_card.ps3_dev = dev; - - ret = ps3_open_hv_device(dev); - - if (ret) - return -ENXIO; - - /* setup MMIO */ - ret = lv1_gpu_device_map(2, &lpar_addr, &lpar_size); - if (ret) { - pr_info("%s: device map 2 failed %d\n", __func__, ret); - goto clean_open; - } - ps3_mmio_region_init(dev, dev->m_region, lpar_addr, lpar_size, - PAGE_SHIFT); - - ret = snd_ps3_map_mmio(); - if (ret) - goto clean_dev_map; - - /* setup DMA area */ - ps3_dma_region_init(dev, dev->d_region, - PAGE_SHIFT, /* use system page size */ - 0, /* dma type; not used */ - NULL, - _ALIGN_UP(SND_PS3_DMA_REGION_SIZE, PAGE_SIZE)); - dev->d_region->ioid = PS3_AUDIO_IOID; - - ret = ps3_dma_region_create(dev->d_region); - if (ret) { - pr_info("%s: region_create\n", __func__); - goto clean_mmio; - } - - snd_ps3_audio_set_base_addr(dev->d_region->bus_addr); - - /* CONFIG_SND_PS3_DEFAULT_START_DELAY */ - the_card.start_delay = snd_ps3_start_delay; - - /* irq */ - if (snd_ps3_allocate_irq()) { - ret = -ENXIO; - goto clean_dma_region; - } - - /* create card instance */ - ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); - if (ret < 0) - goto clean_irq; - - strcpy(the_card.card->driver, "PS3"); - strcpy(the_card.card->shortname, "PS3"); - strcpy(the_card.card->longname, "PS3 sound"); - - /* create control elements */ - for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) { - ret = snd_ctl_add(the_card.card, - snd_ctl_new1(&spdif_ctls[i], &the_card)); - if (ret < 0) - goto clean_card; - } - - /* create PCM devices instance */ - /* NOTE:this driver works assuming pcm:substream = 1:1 */ - ret = snd_pcm_new(the_card.card, - "SPDIF", - 0, /* instance index, will be stored pcm.device*/ - 1, /* output substream */ - 0, /* input substream */ - &(the_card.pcm)); - if (ret) - goto clean_card; - - the_card.pcm->private_data = &the_card; - strcpy(the_card.pcm->name, "SPDIF"); - - /* set pcm ops */ - snd_pcm_set_ops(the_card.pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_ps3_pcm_spdif_ops); - - the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED; - /* pre-alloc PCM DMA buffer*/ - ret = snd_pcm_lib_preallocate_pages_for_all(the_card.pcm, - SNDRV_DMA_TYPE_DEV, - &dev->core, - SND_PS3_PCM_PREALLOC_SIZE, - SND_PS3_PCM_PREALLOC_SIZE); - if (ret < 0) { - pr_info("%s: prealloc failed\n", __func__); - goto clean_card; - } - - /* - * allocate null buffer - * its size should be lager than PS3_AUDIO_FIFO_STAGE_SIZE * 2 - * PAGE_SIZE is enogh - */ - the_card.null_buffer_start_vaddr = - dma_alloc_coherent(&the_card.ps3_dev->core, - PAGE_SIZE, - &the_card.null_buffer_start_dma_addr, - GFP_KERNEL); - if (!the_card.null_buffer_start_vaddr) { - pr_info("%s: nullbuffer alloc failed\n", __func__); - goto clean_preallocate; - } - pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, - the_card.null_buffer_start_vaddr, - the_card.null_buffer_start_dma_addr); - /* set default sample rate/word width */ - snd_ps3_init_avsetting(&the_card); - - /* register the card */ - snd_card_set_dev(the_card.card, &dev->core); - ret = snd_card_register(the_card.card); - if (ret < 0) - goto clean_dma_map; - - pr_info("%s started. start_delay=%dms\n", - the_card.card->longname, the_card.start_delay); - return 0; - -clean_dma_map: - dma_free_coherent(&the_card.ps3_dev->core, - PAGE_SIZE, - the_card.null_buffer_start_vaddr, - the_card.null_buffer_start_dma_addr); -clean_preallocate: - snd_pcm_lib_preallocate_free_for_all(the_card.pcm); -clean_card: - snd_card_free(the_card.card); -clean_irq: - snd_ps3_free_irq(); -clean_dma_region: - ps3_dma_region_free(dev->d_region); -clean_mmio: - snd_ps3_unmap_mmio(); -clean_dev_map: - lv1_gpu_device_unmap(2); -clean_open: - ps3_close_hv_device(dev); - /* - * there is no destructor function to pcm. - * midlayer automatically releases if the card removed - */ - return ret; -}; /* snd_ps3_probe */ - -/* called when module removal */ -static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev) -{ - int ret; - pr_info("%s:start id=%d\n", __func__, dev->match_id); - if (dev->match_id != PS3_MATCH_ID_SOUND) - return -ENXIO; - - /* - * ctl and preallocate buffer will be freed in - * snd_card_free - */ - ret = snd_card_free(the_card.card); - if (ret) - pr_info("%s: ctl freecard=%d\n", __func__, ret); - - dma_free_coherent(&dev->core, - PAGE_SIZE, - the_card.null_buffer_start_vaddr, - the_card.null_buffer_start_dma_addr); - - ps3_dma_region_free(dev->d_region); - - snd_ps3_free_irq(); - snd_ps3_unmap_mmio(); - - lv1_gpu_device_unmap(2); - ps3_close_hv_device(dev); - pr_info("%s:end id=%d\n", __func__, dev->match_id); - return 0; -} /* snd_ps3_remove */ - -static struct ps3_system_bus_driver snd_ps3_bus_driver_info = { - .match_id = PS3_MATCH_ID_SOUND, - .probe = snd_ps3_driver_probe, - .remove = snd_ps3_driver_remove, - .shutdown = snd_ps3_driver_remove, - .core = { - .name = SND_PS3_DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - - -/* - * module/subsystem initialize/terminate - */ -static int __init snd_ps3_init(void) -{ - int ret; - - if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) - return -ENXIO; - - memset(&the_card, 0, sizeof(the_card)); - spin_lock_init(&the_card.dma_lock); - - /* register systembus DRIVER, this calls our probe() func */ - ret = ps3_system_bus_driver_register(&snd_ps3_bus_driver_info); - - return ret; -} -module_init(snd_ps3_init); - -static void __exit snd_ps3_exit(void) -{ - ps3_system_bus_driver_unregister(&snd_ps3_bus_driver_info); -} -module_exit(snd_ps3_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("PS3 sound driver"); -MODULE_AUTHOR("Sony Computer Entertainment Inc."); -MODULE_ALIAS(PS3_MODULE_ALIAS_SOUND); diff --git a/ANDROID_3.4.5/sound/ppc/snd_ps3.h b/ANDROID_3.4.5/sound/ppc/snd_ps3.h deleted file mode 100644 index 326fb29e..00000000 --- a/ANDROID_3.4.5/sound/ppc/snd_ps3.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Audio support for PS3 - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * All rights reserved. - * Copyright 2006, 2007 Sony Corporation - * - * 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; version 2 of the Licence. - * - * 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 - */ - -#if !defined(_SND_PS3_H_) -#define _SND_PS3_H_ - -#include - -#define SND_PS3_DRIVER_NAME "snd_ps3" - -enum snd_ps3_out_channel { - SND_PS3_OUT_SPDIF_0, - SND_PS3_OUT_SPDIF_1, - SND_PS3_OUT_SERIAL_0, - SND_PS3_OUT_DEVS -}; - -enum snd_ps3_dma_filltype { - SND_PS3_DMA_FILLTYPE_FIRSTFILL, - SND_PS3_DMA_FILLTYPE_RUNNING, - SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL, - SND_PS3_DMA_FILLTYPE_SILENT_RUNNING -}; - -enum snd_ps3_ch { - SND_PS3_CH_L = 0, - SND_PS3_CH_R = 1, - SND_PS3_CH_MAX = 2 -}; - -struct snd_ps3_avsetting_info { - uint32_t avs_audio_ch; /* fixed */ - uint32_t avs_audio_rate; - uint32_t avs_audio_width; - uint32_t avs_audio_format; /* fixed */ - uint32_t avs_audio_source; /* fixed */ - unsigned char avs_cs_info[8]; -}; -/* - * PS3 audio 'card' instance - * there should be only ONE hardware. - */ -struct snd_ps3_card_info { - struct ps3_system_bus_device *ps3_dev; - struct snd_card *card; - - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - - /* hvc info */ - u64 audio_lpar_addr; - u64 audio_lpar_size; - - /* registers */ - void __iomem *mapped_mmio_vaddr; - - /* irq */ - u64 audio_irq_outlet; - unsigned int irq_no; - - /* remember avsetting */ - struct snd_ps3_avsetting_info avs; - - /* dma buffer management */ - spinlock_t dma_lock; - /* dma_lock start */ - void * dma_start_vaddr[2]; /* 0 for L, 1 for R */ - dma_addr_t dma_start_bus_addr[2]; - size_t dma_buffer_size; - void * dma_last_transfer_vaddr[2]; - void * dma_next_transfer_vaddr[2]; - int silent; - /* dma_lock end */ - - int running; - - /* null buffer */ - void *null_buffer_start_vaddr; - dma_addr_t null_buffer_start_dma_addr; - - /* start delay */ - unsigned int start_delay; - -}; - - -/* PS3 audio DMAC block size in bytes */ -#define PS3_AUDIO_DMAC_BLOCK_SIZE (128) -/* one stage (stereo) of audio FIFO in bytes */ -#define PS3_AUDIO_FIFO_STAGE_SIZE (256) -/* how many stages the fifo have */ -#define PS3_AUDIO_FIFO_STAGE_COUNT (8) -/* fifo size 128 bytes * 8 stages * stereo (2ch) */ -#define PS3_AUDIO_FIFO_SIZE \ - (PS3_AUDIO_FIFO_STAGE_SIZE * PS3_AUDIO_FIFO_STAGE_COUNT) - -/* PS3 audio DMAC max block count in one dma shot = 128 (0x80) blocks*/ -#define PS3_AUDIO_DMAC_MAX_BLOCKS (PS3_AUDIO_DMASIZE_BLOCKS_MASK + 1) - -#define PS3_AUDIO_NORMAL_DMA_START_CH (0) -#define PS3_AUDIO_NORMAL_DMA_COUNT (8) -#define PS3_AUDIO_NULL_DMA_START_CH \ - (PS3_AUDIO_NORMAL_DMA_START_CH + PS3_AUDIO_NORMAL_DMA_COUNT) -#define PS3_AUDIO_NULL_DMA_COUNT (2) - -#define SND_PS3_MAX_VOL (0x0F) -#define SND_PS3_MIN_VOL (0x00) -#define SND_PS3_MIN_ATT SND_PS3_MIN_VOL -#define SND_PS3_MAX_ATT SND_PS3_MAX_VOL - -#define SND_PS3_PCM_PREALLOC_SIZE \ - (PS3_AUDIO_DMAC_BLOCK_SIZE * PS3_AUDIO_DMAC_MAX_BLOCKS * 4) - -#define SND_PS3_DMA_REGION_SIZE \ - (SND_PS3_PCM_PREALLOC_SIZE + PAGE_SIZE) - -#define PS3_AUDIO_IOID (1UL) - -#endif /* _SND_PS3_H_ */ diff --git a/ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h b/ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h deleted file mode 100644 index 2e630207..00000000 --- a/ANDROID_3.4.5/sound/ppc/snd_ps3_reg.h +++ /dev/null @@ -1,891 +0,0 @@ -/* - * Audio support for PS3 - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2006, 2007 Sony Corporation - * All rights reserved. - * - * 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; version 2 of the License. - * - * 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 - */ - -/* - * interrupt / configure registers - */ - -#define PS3_AUDIO_INTR_0 (0x00000100) -#define PS3_AUDIO_INTR_EN_0 (0x00000140) -#define PS3_AUDIO_CONFIG (0x00000200) - -/* - * DMAC registers - * n:0..9 - */ -#define PS3_AUDIO_DMAC_REGBASE(x) (0x0000210 + 0x20 * (x)) - -#define PS3_AUDIO_KICK(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x00) -#define PS3_AUDIO_SOURCE(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x04) -#define PS3_AUDIO_DEST(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x08) -#define PS3_AUDIO_DMASIZE(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x0C) - -/* - * mute control - */ -#define PS3_AUDIO_AX_MCTRL (0x00004000) -#define PS3_AUDIO_AX_ISBP (0x00004004) -#define PS3_AUDIO_AX_AOBP (0x00004008) -#define PS3_AUDIO_AX_IC (0x00004010) -#define PS3_AUDIO_AX_IE (0x00004014) -#define PS3_AUDIO_AX_IS (0x00004018) - -/* - * three wire serial - * n:0..3 - */ -#define PS3_AUDIO_AO_MCTRL (0x00006000) -#define PS3_AUDIO_AO_3WMCTRL (0x00006004) - -#define PS3_AUDIO_AO_3WCTRL(n) (0x00006200 + 0x200 * (n)) - -/* - * S/PDIF - * n:0..1 - * x:0..11 - * y:0..5 - */ -#define PS3_AUDIO_AO_SPD_REGBASE(n) (0x00007200 + 0x200 * (n)) - -#define PS3_AUDIO_AO_SPDCTRL(n) \ - (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x00) -#define PS3_AUDIO_AO_SPDUB(n, x) \ - (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x04 + 0x04 * (x)) -#define PS3_AUDIO_AO_SPDCS(n, y) \ - (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x34 + 0x04 * (y)) - - -/* - PS3_AUDIO_INTR_0 register tells an interrupt handler which audio - DMA channel triggered the interrupt. The interrupt status for a channel - can be cleared by writing a '1' to the corresponding bit. A new interrupt - cannot be generated until the previous interrupt has been cleared. - - Note that the status reported by PS3_AUDIO_INTR_0 is independent of the - value of PS3_AUDIO_INTR_EN_0. - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C| INTR_0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -#define PS3_AUDIO_INTR_0_CHAN(n) (1 << ((n) * 2)) -#define PS3_AUDIO_INTR_0_CHAN9 PS3_AUDIO_INTR_0_CHAN(9) -#define PS3_AUDIO_INTR_0_CHAN8 PS3_AUDIO_INTR_0_CHAN(8) -#define PS3_AUDIO_INTR_0_CHAN7 PS3_AUDIO_INTR_0_CHAN(7) -#define PS3_AUDIO_INTR_0_CHAN6 PS3_AUDIO_INTR_0_CHAN(6) -#define PS3_AUDIO_INTR_0_CHAN5 PS3_AUDIO_INTR_0_CHAN(5) -#define PS3_AUDIO_INTR_0_CHAN4 PS3_AUDIO_INTR_0_CHAN(4) -#define PS3_AUDIO_INTR_0_CHAN3 PS3_AUDIO_INTR_0_CHAN(3) -#define PS3_AUDIO_INTR_0_CHAN2 PS3_AUDIO_INTR_0_CHAN(2) -#define PS3_AUDIO_INTR_0_CHAN1 PS3_AUDIO_INTR_0_CHAN(1) -#define PS3_AUDIO_INTR_0_CHAN0 PS3_AUDIO_INTR_0_CHAN(0) - -/* - The PS3_AUDIO_INTR_EN_0 register specifies which DMA channels can generate - an interrupt to the PU. Each bit of PS3_AUDIO_INTR_EN_0 is ANDed with the - corresponding bit in PS3_AUDIO_INTR_0. The resulting bits are OR'd together - to generate the Audio interrupt. - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C| INTR_EN_0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - - Bit assignments are same as PS3_AUDIO_INTR_0 -*/ - -/* - PS3_AUDIO_CONFIG - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 C|0 0 0 0 0 0 0 0| CONFIG - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -*/ - -/* The CLEAR field cancels all pending transfers, and stops any running DMA - transfers. Any interrupts associated with the canceled transfers - will occur as if the transfer had finished. - Since this bit is designed to recover from DMA related issues - which are caused by unpredictable situations, it is preferred to wait - for normal DMA transfer end without using this bit. -*/ -#define PS3_AUDIO_CONFIG_CLEAR (1 << 8) /* RWIVF */ - -/* - PS3_AUDIO_AX_MCTRL: Audio Port Mute Control Register - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|A|A|A|0 0 0 0 0 0 0|S|S|A|A|A|A| AX_MCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* 3 Wire Audio Serial Output Channel Mutes (0..3) */ -#define PS3_AUDIO_AX_MCTRL_ASOMT(n) (1 << (3 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_ASO3MT (1 << 0) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_ASO2MT (1 << 1) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_ASO1MT (1 << 2) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_ASO0MT (1 << 3) /* RWIVF */ - -/* S/PDIF mutes (0,1)*/ -#define PS3_AUDIO_AX_MCTRL_SPOMT(n) (1 << (5 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_SPO1MT (1 << 4) /* RWIVF */ -#define PS3_AUDIO_AX_MCTRL_SPO0MT (1 << 5) /* RWIVF */ - -/* All 3 Wire Serial Outputs Mute */ -#define PS3_AUDIO_AX_MCTRL_AASOMT (1 << 13) /* RWIVF */ - -/* All S/PDIF Mute */ -#define PS3_AUDIO_AX_MCTRL_ASPOMT (1 << 14) /* RWIVF */ - -/* All Audio Outputs Mute */ -#define PS3_AUDIO_AX_MCTRL_AAOMT (1 << 15) /* RWIVF */ - -/* - S/PDIF Outputs Buffer Read/Write Pointer Register - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|0|SPO0B|0|SPO1B|0 0 0 0 0 0 0 0|0|SPO0B|0|SPO1B| AX_ISBP - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -*/ -/* - S/PDIF Output Channel Read Buffer Numbers - Buffer number is value of field. - Indicates current read access buffer ID from Audio Data - Transfer controller of S/PDIF Output -*/ - -#define PS3_AUDIO_AX_ISBP_SPOBRN_MASK(n) (0x7 << 4 * (1 - (n))) /* R-IUF */ -#define PS3_AUDIO_AX_ISBP_SPO1BRN_MASK (0x7 << 0) /* R-IUF */ -#define PS3_AUDIO_AX_ISBP_SPO0BRN_MASK (0x7 << 4) /* R-IUF */ - -/* -S/PDIF Output Channel Buffer Write Numbers -Indicates current write access buffer ID from bus master. -*/ -#define PS3_AUDIO_AX_ISBP_SPOBWN_MASK(n) (0x7 << 4 * (5 - (n))) /* R-IUF */ -#define PS3_AUDIO_AX_ISBP_SPO1BWN_MASK (0x7 << 16) /* R-IUF */ -#define PS3_AUDIO_AX_ISBP_SPO0BWN_MASK (0x7 << 20) /* R-IUF */ - -/* - 3 Wire Audio Serial Outputs Buffer Read/Write - Pointer Register - Buffer number is value of field - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0|ASO0B|0|ASO1B|0|ASO2B|0|ASO3B|0|ASO0B|0|ASO1B|0|ASO2B|0|ASO3B| AX_AOBP - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* -3 Wire Audio Serial Output Channel Buffer Read Numbers -Indicates current read access buffer Id from Audio Data Transfer -Controller of 3 Wire Audio Serial Output Channels -*/ -#define PS3_AUDIO_AX_AOBP_ASOBRN_MASK(n) (0x7 << 4 * (3 - (n))) /* R-IUF */ - -#define PS3_AUDIO_AX_AOBP_ASO3BRN_MASK (0x7 << 0) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO2BRN_MASK (0x7 << 4) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO1BRN_MASK (0x7 << 8) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO0BRN_MASK (0x7 << 12) /* R-IUF */ - -/* -3 Wire Audio Serial Output Channel Buffer Write Numbers -Indicates current write access buffer ID from bus master. -*/ -#define PS3_AUDIO_AX_AOBP_ASOBWN_MASK(n) (0x7 << 4 * (7 - (n))) /* R-IUF */ - -#define PS3_AUDIO_AX_AOBP_ASO3BWN_MASK (0x7 << 16) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO2BWN_MASK (0x7 << 20) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO1BWN_MASK (0x7 << 24) /* R-IUF */ -#define PS3_AUDIO_AX_AOBP_ASO0BWN_MASK (0x7 << 28) /* R-IUF */ - - - -/* -Audio Port Interrupt Condition Register -For the fields in this register, the following values apply: -0 = Interrupt is generated every interrupt event. -1 = Interrupt is generated every 2 interrupt events. -2 = Interrupt is generated every 4 interrupt events. -3 = Reserved - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|0 0|SPO|0 0|SPO|0 0|AAS|0 0 0 0 0 0 0 0 0 0 0 0| AX_IC - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -/* -All 3-Wire Audio Serial Outputs Interrupt Mode -Configures the Interrupt and Signal Notification -condition of all 3-wire Audio Serial Outputs. -*/ -#define PS3_AUDIO_AX_IC_AASOIMD_MASK (0x3 << 12) /* RWIVF */ -#define PS3_AUDIO_AX_IC_AASOIMD_EVERY1 (0x0 << 12) /* RWI-V */ -#define PS3_AUDIO_AX_IC_AASOIMD_EVERY2 (0x1 << 12) /* RW--V */ -#define PS3_AUDIO_AX_IC_AASOIMD_EVERY4 (0x2 << 12) /* RW--V */ - -/* -S/PDIF Output Channel Interrupt Modes -Configures the Interrupt and signal Notification -conditions of S/PDIF output channels. -*/ -#define PS3_AUDIO_AX_IC_SPO1IMD_MASK (0x3 << 16) /* RWIVF */ -#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY1 (0x0 << 16) /* RWI-V */ -#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY2 (0x1 << 16) /* RW--V */ -#define PS3_AUDIO_AX_IC_SPO1IMD_EVERY4 (0x2 << 16) /* RW--V */ - -#define PS3_AUDIO_AX_IC_SPO0IMD_MASK (0x3 << 20) /* RWIVF */ -#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY1 (0x0 << 20) /* RWI-V */ -#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY2 (0x1 << 20) /* RW--V */ -#define PS3_AUDIO_AX_IC_SPO0IMD_EVERY4 (0x2 << 20) /* RW--V */ - -/* -Audio Port interrupt Enable Register -Configures whether to enable or disable each Interrupt Generation. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|S|S|0 0|A|A|A|A|0 0 0 0|S|S|0 0|S|S|0 0|A|A|A|A| AX_IE - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -*/ - -/* -3 Wire Audio Serial Output Channel Buffer Underflow -Interrupt Enables -Select enable/disable of Buffer Underflow Interrupts for -3-Wire Audio Serial Output Channels -DISABLED=Interrupt generation disabled. -*/ -#define PS3_AUDIO_AX_IE_ASOBUIE(n) (1 << (3 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO3BUIE (1 << 0) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO2BUIE (1 << 1) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO1BUIE (1 << 2) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO0BUIE (1 << 3) /* RWIVF */ - -/* S/PDIF Output Channel Buffer Underflow Interrupt Enables */ - -#define PS3_AUDIO_AX_IE_SPOBUIE(n) (1 << (7 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO1BUIE (1 << 6) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO0BUIE (1 << 7) /* RWIVF */ - -/* S/PDIF Output Channel One Block Transfer Completion Interrupt Enables */ - -#define PS3_AUDIO_AX_IE_SPOBTCIE(n) (1 << (11 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO1BTCIE (1 << 10) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO0BTCIE (1 << 11) /* RWIVF */ - -/* 3-Wire Audio Serial Output Channel Buffer Empty Interrupt Enables */ - -#define PS3_AUDIO_AX_IE_ASOBEIE(n) (1 << (19 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO3BEIE (1 << 16) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO2BEIE (1 << 17) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO1BEIE (1 << 18) /* RWIVF */ -#define PS3_AUDIO_AX_IE_ASO0BEIE (1 << 19) /* RWIVF */ - -/* S/PDIF Output Channel Buffer Empty Interrupt Enables */ - -#define PS3_AUDIO_AX_IE_SPOBEIE(n) (1 << (23 - (n))) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO1BEIE (1 << 22) /* RWIVF */ -#define PS3_AUDIO_AX_IE_SPO0BEIE (1 << 23) /* RWIVF */ - -/* -Audio Port Interrupt Status Register -Indicates Interrupt status, which interrupt has occurred, and can clear -each interrupt in this register. -Writing 1b to a field containing 1b clears field and de-asserts interrupt. -Writing 0b to a field has no effect. -Field vaules are the following: -0 - Interrupt hasn't occurred. -1 - Interrupt has occurred. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0|S|S|0 0|A|A|A|A|0 0 0 0|S|S|0 0|S|S|0 0|A|A|A|A| AX_IS - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - - Bit assignment are same as AX_IE -*/ - -/* -Audio Output Master Control Register -Configures Master Clock and other master Audio Output Settings - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0|SCKSE|0|SCKSE| MR0 | MR1 |MCL|MCL|0 0 0 0|0 0 0 0 0 0 0 0| AO_MCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* -MCLK Output Control -Controls mclko[1] output. -0 - Disable output (fixed at High) -1 - Output clock produced by clock selected -with scksel1 by mr1 -2 - Reserved -3 - Reserved -*/ - -#define PS3_AUDIO_AO_MCTRL_MCLKC1_MASK (0x3 << 12) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_MCLKC1_DISABLED (0x0 << 12) /* RWI-V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC1_ENABLED (0x1 << 12) /* RW--V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC1_RESVD2 (0x2 << 12) /* RW--V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC1_RESVD3 (0x3 << 12) /* RW--V */ - -/* -MCLK Output Control -Controls mclko[0] output. -0 - Disable output (fixed at High) -1 - Output clock produced by clock selected -with SCKSEL0 by MR0 -2 - Reserved -3 - Reserved -*/ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_MASK (0x3 << 14) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_DISABLED (0x0 << 14) /* RWI-V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_ENABLED (0x1 << 14) /* RW--V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_RESVD2 (0x2 << 14) /* RW--V */ -#define PS3_AUDIO_AO_MCTRL_MCLKC0_RESVD3 (0x3 << 14) /* RW--V */ -/* -Master Clock Rate 1 -Sets the divide ration of Master Clock1 (clock output from -mclko[1] for the input clock selected by scksel1. -*/ -#define PS3_AUDIO_AO_MCTRL_MR1_MASK (0xf << 16) -#define PS3_AUDIO_AO_MCTRL_MR1_DEFAULT (0x0 << 16) /* RWI-V */ -/* -Master Clock Rate 0 -Sets the divide ratio of Master Clock0 (clock output from -mclko[0] for the input clock selected by scksel0). -*/ -#define PS3_AUDIO_AO_MCTRL_MR0_MASK (0xf << 20) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_MR0_DEFAULT (0x0 << 20) /* RWI-V */ -/* -System Clock Select 0/1 -Selects the system clock to be used as Master Clock 0/1 -Input the system clock that is appropriate for the sampling -rate. -*/ -#define PS3_AUDIO_AO_MCTRL_SCKSEL1_MASK (0x7 << 24) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_SCKSEL1_DEFAULT (0x2 << 24) /* RWI-V */ - -#define PS3_AUDIO_AO_MCTRL_SCKSEL0_MASK (0x7 << 28) /* RWIVF */ -#define PS3_AUDIO_AO_MCTRL_SCKSEL0_DEFAULT (0x2 << 28) /* RWI-V */ - - -/* -3-Wire Audio Output Master Control Register -Configures clock, 3-Wire Audio Serial Output Enable, and -other 3-Wire Audio Serial Output Master Settings - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |A|A|A|A|0 0 0|A| ASOSR |0 0 0 0|A|A|A|A|A|A|0|1|0 0 0 0 0 0 0 0| AO_3WMCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - - -/* -LRCKO Polarity -0 - Reserved -1 - default -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASOPLRCK (1 << 8) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT (1 << 8) /* RW--V */ - -/* LRCK Output Disable */ - -#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD (1 << 10) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_ENABLED (0 << 10) /* RW--V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED (1 << 10) /* RWI-V */ - -/* Bit Clock Output Disable */ - -#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD (1 << 11) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_ENABLED (0 << 11) /* RW--V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED (1 << 11) /* RWI-V */ - -/* -3-Wire Audio Serial Output Channel 0-3 Operational -Status. Each bit becomes 1 after each 3-Wire Audio -Serial Output Channel N is in action by setting 1 to -asoen. -Each bit becomes 0 after each 3-Wire Audio Serial Output -Channel N is out of action by setting 0 to asoen. -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASORUN(n) (1 << (15 - (n))) /* R-IVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(n) (0 << (15 - (n))) /* R-I-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(n) (1 << (15 - (n))) /* R---V */ -#define PS3_AUDIO_AO_3WMCTRL_ASORUN0 \ - PS3_AUDIO_AO_3WMCTRL_ASORUN(0) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN0_STOPPED \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(0) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN0_RUNNING \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(0) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN1 \ - PS3_AUDIO_AO_3WMCTRL_ASORUN(1) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN1_STOPPED \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(1) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN1_RUNNING \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(1) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN2 \ - PS3_AUDIO_AO_3WMCTRL_ASORUN(2) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN2_STOPPED \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(2) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN2_RUNNING \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(2) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN3 \ - PS3_AUDIO_AO_3WMCTRL_ASORUN(3) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN3_STOPPED \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(3) -#define PS3_AUDIO_AO_3WMCTRL_ASORUN3_RUNNING \ - PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(3) - -/* -Sampling Rate -Specifies the divide ratio of the bit clock (clock output -from bclko) used by the 3-wire Audio Output Clock, which -is applied to the master clock selected by mcksel. -Data output is synchronized with this clock. -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_MASK (0xf << 20) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV2 (0x1 << 20) /* RWI-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV4 (0x2 << 20) /* RW--V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV8 (0x4 << 20) /* RW--V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV12 (0x6 << 20) /* RW--V */ - -/* -Master Clock Select -0 - Master Clock 0 -1 - Master Clock 1 -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL (1 << 24) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL_CLK0 (0 << 24) /* RWI-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL_CLK1 (1 << 24) /* RW--V */ - -/* -Enables and disables 4ch 3-Wire Audio Serial Output -operation. Each Bit from 0 to 3 corresponds to an -output channel, which means that each output channel -can be enabled or disabled individually. When -multiple channels are enabled at the same time, output -operations are performed in synchronization. -Bit 0 - Output Channel 0 (SDOUT[0]) -Bit 1 - Output Channel 1 (SDOUT[1]) -Bit 2 - Output Channel 2 (SDOUT[2]) -Bit 3 - Output Channel 3 (SDOUT[3]) -*/ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN(n) (1 << (31 - (n))) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(n) (0 << (31 - (n))) /* RWI-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(n) (1 << (31 - (n))) /* RW--V */ - -#define PS3_AUDIO_AO_3WMCTRL_ASOEN0 \ - PS3_AUDIO_AO_3WMCTRL_ASOEN(0) /* RWIVF */ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN0_DISABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(0) /* RWI-V */ -#define PS3_AUDIO_AO_3WMCTRL_ASOEN0_ENABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(0) /* RW--V */ -#define PS3_AUDIO_A1_3WMCTRL_ASOEN0 \ - PS3_AUDIO_AO_3WMCTRL_ASOEN(1) /* RWIVF */ -#define PS3_AUDIO_A1_3WMCTRL_ASOEN0_DISABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(1) /* RWI-V */ -#define PS3_AUDIO_A1_3WMCTRL_ASOEN0_ENABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(1) /* RW--V */ -#define PS3_AUDIO_A2_3WMCTRL_ASOEN0 \ - PS3_AUDIO_AO_3WMCTRL_ASOEN(2) /* RWIVF */ -#define PS3_AUDIO_A2_3WMCTRL_ASOEN0_DISABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(2) /* RWI-V */ -#define PS3_AUDIO_A2_3WMCTRL_ASOEN0_ENABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(2) /* RW--V */ -#define PS3_AUDIO_A3_3WMCTRL_ASOEN0 \ - PS3_AUDIO_AO_3WMCTRL_ASOEN(3) /* RWIVF */ -#define PS3_AUDIO_A3_3WMCTRL_ASOEN0_DISABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(3) /* RWI-V */ -#define PS3_AUDIO_A3_3WMCTRL_ASOEN0_ENABLED \ - PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(3) /* RW--V */ - -/* -3-Wire Audio Serial output Channel 0-3 Control Register -Configures settings for 3-Wire Serial Audio Output Channel 0-3 - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|A|0 0 0 0|A|0|ASO|0 0 0|0|0|0|0|0| AO_3WCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -*/ -/* -Data Bit Mode -Specifies the number of data bits -0 - 16 bits -1 - reserved -2 - 20 bits -3 - 24 bits -*/ -#define PS3_AUDIO_AO_3WCTRL_ASODB_MASK (0x3 << 8) /* RWIVF */ -#define PS3_AUDIO_AO_3WCTRL_ASODB_16BIT (0x0 << 8) /* RWI-V */ -#define PS3_AUDIO_AO_3WCTRL_ASODB_RESVD (0x1 << 8) /* RWI-V */ -#define PS3_AUDIO_AO_3WCTRL_ASODB_20BIT (0x2 << 8) /* RW--V */ -#define PS3_AUDIO_AO_3WCTRL_ASODB_24BIT (0x3 << 8) /* RW--V */ -/* -Data Format Mode -Specifies the data format where (LSB side or MSB) the data(in 20 bit -or 24 bit resolution mode) is put in a 32 bit field. -0 - Data put on LSB side -1 - Data put on MSB side -*/ -#define PS3_AUDIO_AO_3WCTRL_ASODF (1 << 11) /* RWIVF */ -#define PS3_AUDIO_AO_3WCTRL_ASODF_LSB (0 << 11) /* RWI-V */ -#define PS3_AUDIO_AO_3WCTRL_ASODF_MSB (1 << 11) /* RW--V */ -/* -Buffer Reset -Performs buffer reset. Writing 1 to this bit initializes the -corresponding 3-Wire Audio Output buffers(both L and R). -*/ -#define PS3_AUDIO_AO_3WCTRL_ASOBRST (1 << 16) /* CWIVF */ -#define PS3_AUDIO_AO_3WCTRL_ASOBRST_IDLE (0 << 16) /* -WI-V */ -#define PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET (1 << 16) /* -W--T */ - -/* -S/PDIF Audio Output Channel 0/1 Control Register -Configures settings for S/PDIF Audio Output Channel 0/1. - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |S|0 0 0|S|0 0|S| SPOSR |0 0|SPO|0 0 0 0|S|0|SPO|0 0 0 0 0 0 0|S| AO_SPDCTRL - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -/* -Buffer reset. Writing 1 to this bit initializes the -corresponding S/PDIF output buffer pointer. -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOBRST (1 << 0) /* CWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOBRST_IDLE (0 << 0) /* -WI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOBRST_RESET (1 << 0) /* -W--T */ - -/* -Data Bit Mode -Specifies number of data bits -0 - 16 bits -1 - Reserved -2 - 20 bits -3 - 24 bits -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_MASK (0x3 << 8) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_16BIT (0x0 << 8) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_RESVD (0x1 << 8) /* RW--V */ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_20BIT (0x2 << 8) /* RW--V */ -#define PS3_AUDIO_AO_SPDCTRL_SPODB_24BIT (0x3 << 8) /* RW--V */ -/* -Data format Mode -Specifies the data format, where (LSB side or MSB) -the data(in 20 or 24 bit resolution) is put in the -32 bit field. -0 - LSB Side -1 - MSB Side -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPODF (1 << 11) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPODF_LSB (0 << 11) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPODF_MSB (1 << 11) /* RW--V */ -/* -Source Select -Specifies the source of the S/PDIF output. When 0, output -operation is controlled by 3wen[0] of AO_3WMCTRL register. -The SR must have the same setting as the a0_3wmctrl reg. -0 - 3-Wire Audio OUT Ch0 Buffer -1 - S/PDIF buffer -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOSS_MASK (0x3 << 16) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSS_3WEN (0x0 << 16) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSS_SPDIF (0x1 << 16) /* RW--V */ -/* -Sampling Rate -Specifies the divide ratio of the bit clock (clock output -from bclko) used by the S/PDIF Output Clock, which -is applied to the master clock selected by mcksel. -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR (0xf << 20) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV2 (0x1 << 20) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV4 (0x2 << 20) /* RW--V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV8 (0x4 << 20) /* RW--V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV12 (0x6 << 20) /* RW--V */ -/* -Master Clock Select -0 - Master Clock 0 -1 - Master Clock 1 -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL (1 << 24) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL_CLK0 (0 << 24) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL_CLK1 (1 << 24) /* RW--V */ - -/* -S/PDIF Output Channel Operational Status -This bit becomes 1 after S/PDIF Output Channel is in -action by setting 1 to spoen. This bit becomes 0 -after S/PDIF Output Channel is out of action by setting -0 to spoen. -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPORUN (1 << 27) /* R-IVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPORUN_STOPPED (0 << 27) /* R-I-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPORUN_RUNNING (1 << 27) /* R---V */ - -/* -S/PDIF Audio Output Channel Output Enable -Enables and disables output operation. This bit is used -only when sposs = 1 -*/ -#define PS3_AUDIO_AO_SPDCTRL_SPOEN (1 << 31) /* RWIVF */ -#define PS3_AUDIO_AO_SPDCTRL_SPOEN_DISABLED (0 << 31) /* RWI-V */ -#define PS3_AUDIO_AO_SPDCTRL_SPOEN_ENABLED (1 << 31) /* RW--V */ - -/* -S/PDIF Audio Output Channel Channel Status -Setting Registers. -Configures channel status bit settings for each block -(192 bits). -Output is performed from the MSB(AO_SPDCS0 register bit 31). -The same value is added for subframes within the same frame. - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - | SPOCS | AO_SPDCS - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - -S/PDIF Audio Output Channel User Bit Setting -Configures user bit settings for each block (384 bits). -Output is performed from the MSB(ao_spdub0 register bit 31). - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - | SPOUB | AO_SPDUB - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -/***************************************************************************** - * - * DMAC register - * - *****************************************************************************/ -/* -The PS3_AUDIO_KICK register is used to initiate a DMA transfer and monitor -its status - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0|STATU|0 0 0| EVENT |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|R| KICK - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ -/* -The REQUEST field is written to ACTIVE to initiate a DMA request when EVENT -occurs. -It will return to the DONE state when the request is completed. -The registers for a DMA channel should only be written if REQUEST is IDLE. -*/ - -#define PS3_AUDIO_KICK_REQUEST (1 << 0) /* RWIVF */ -#define PS3_AUDIO_KICK_REQUEST_IDLE (0 << 0) /* RWI-V */ -#define PS3_AUDIO_KICK_REQUEST_ACTIVE (1 << 0) /* -W--T */ - -/* - *The EVENT field is used to set the event in which - *the DMA request becomes active. - */ -#define PS3_AUDIO_KICK_EVENT_MASK (0x1f << 16) /* RWIVF */ -#define PS3_AUDIO_KICK_EVENT_ALWAYS (0x00 << 16) /* RWI-V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY (0x01 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT0_UNDERFLOW (0x02 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT1_EMPTY (0x03 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT1_UNDERFLOW (0x04 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT2_EMPTY (0x05 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT2_UNDERFLOW (0x06 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT3_EMPTY (0x07 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SERIALOUT3_UNDERFLOW (0x08 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF0_BLOCKTRANSFERCOMPLETE \ - (0x09 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF0_UNDERFLOW (0x0A << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF0_EMPTY (0x0B << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF1_BLOCKTRANSFERCOMPLETE \ - (0x0C << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF1_UNDERFLOW (0x0D << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_SPDIF1_EMPTY (0x0E << 16) /* RW--V */ - -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA(n) \ - ((0x13 + (n)) << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA0 (0x13 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA1 (0x14 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA2 (0x15 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA3 (0x16 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA4 (0x17 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA5 (0x18 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA6 (0x19 << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA7 (0x1A << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA8 (0x1B << 16) /* RW--V */ -#define PS3_AUDIO_KICK_EVENT_AUDIO_DMA9 (0x1C << 16) /* RW--V */ - -/* -The STATUS field can be used to monitor the progress of a DMA request. -DONE indicates the previous request has completed. -EVENT indicates that the DMA engine is waiting for the EVENT to occur. -PENDING indicates that the DMA engine has not started processing this -request, but the EVENT has occurred. -DMA indicates that the data transfer is in progress. -NOTIFY indicates that the notifier signalling end of transfer is being written. -CLEAR indicated that the previous transfer was cleared. -ERROR indicates the previous transfer requested an unsupported -source/destination combination. -*/ - -#define PS3_AUDIO_KICK_STATUS_MASK (0x7 << 24) /* R-IVF */ -#define PS3_AUDIO_KICK_STATUS_DONE (0x0 << 24) /* R-I-V */ -#define PS3_AUDIO_KICK_STATUS_EVENT (0x1 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_PENDING (0x2 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_DMA (0x3 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_NOTIFY (0x4 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_CLEAR (0x5 << 24) /* R---V */ -#define PS3_AUDIO_KICK_STATUS_ERROR (0x6 << 24) /* R---V */ - -/* -The PS3_AUDIO_SOURCE register specifies the source address for transfers. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - | START |0 0 0 0 0|TAR| SOURCE - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* -The Audio DMA engine uses 128-byte transfers, thus the address must be aligned -to a 128 byte boundary. The low seven bits are assumed to be 0. -*/ - -#define PS3_AUDIO_SOURCE_START_MASK (0x01FFFFFF << 7) /* RWIUF */ - -/* -The TARGET field specifies the memory space containing the source address. -*/ - -#define PS3_AUDIO_SOURCE_TARGET_MASK (3 << 0) /* RWIVF */ -#define PS3_AUDIO_SOURCE_TARGET_SYSTEM_MEMORY (2 << 0) /* RW--V */ - -/* -The PS3_AUDIO_DEST register specifies the destination address for transfers. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - | START |0 0 0 0 0|TAR| DEST - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - -/* -The Audio DMA engine uses 128-byte transfers, thus the address must be aligned -to a 128 byte boundary. The low seven bits are assumed to be 0. -*/ - -#define PS3_AUDIO_DEST_START_MASK (0x01FFFFFF << 7) /* RWIUF */ - -/* -The TARGET field specifies the memory space containing the destination address -AUDIOFIFO = Audio WriteData FIFO, -*/ - -#define PS3_AUDIO_DEST_TARGET_MASK (3 << 0) /* RWIVF */ -#define PS3_AUDIO_DEST_TARGET_AUDIOFIFO (1 << 0) /* RW--V */ - -/* -PS3_AUDIO_DMASIZE specifies the number of 128-byte blocks + 1 to transfer. -So a value of 0 means 128-bytes will get transferred. - - - 31 24 23 16 15 8 7 0 - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ - |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| BLOCKS | DMASIZE - +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ -*/ - - -#define PS3_AUDIO_DMASIZE_BLOCKS_MASK (0x7f << 0) /* RWIUF */ - -/* - * source/destination address for internal fifos - */ -#define PS3_AUDIO_AO_3W_LDATA(n) (0x1000 + (0x100 * (n))) -#define PS3_AUDIO_AO_3W_RDATA(n) (0x1080 + (0x100 * (n))) - -#define PS3_AUDIO_AO_SPD_DATA(n) (0x2000 + (0x400 * (n))) - - -/* - * field attiribute - * - * Read - * ' ' = Other Information - * '-' = Field is part of a write-only register - * 'C' = Value read is always the same, constant value line follows (C) - * 'R' = Value is read - * - * Write - * ' ' = Other Information - * '-' = Must not be written (D), value ignored when written (R,A,F) - * 'W' = Can be written - * - * Internal State - * ' ' = Other Information - * '-' = No internal state - * 'X' = Internal state, initial value is unknown - * 'I' = Internal state, initial value is known and follows (I) - * - * Declaration/Size - * ' ' = Other Information - * '-' = Does Not Apply - * 'V' = Type is void - * 'U' = Type is unsigned integer - * 'S' = Type is signed integer - * 'F' = Type is IEEE floating point - * '1' = Byte size (008) - * '2' = Short size (016) - * '3' = Three byte size (024) - * '4' = Word size (032) - * '8' = Double size (064) - * - * Define Indicator - * ' ' = Other Information - * 'D' = Device - * 'M' = Memory - * 'R' = Register - * 'A' = Array of Registers - * 'F' = Field - * 'V' = Value - * 'T' = Task - */ - diff --git a/ANDROID_3.4.5/sound/ppc/tumbler.c b/ANDROID_3.4.5/sound/ppc/tumbler.c deleted file mode 100644 index 9cea84c3..00000000 --- a/ANDROID_3.4.5/sound/ppc/tumbler.c +++ /dev/null @@ -1,1495 +0,0 @@ -/* - * PMac Tumbler/Snapper lowlevel functions - * - * Copyright (c) by Takashi Iwai - * - * 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 - * - * Rene Rebe : - * * update from shadow registers on wakeup and headphone plug - * * automatically toggle DRC on headphone plug - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pmac.h" -#include "tumbler_volume.h" - -#undef DEBUG - -#ifdef DEBUG -#define DBG(fmt...) printk(KERN_DEBUG fmt) -#else -#define DBG(fmt...) -#endif - -#define IS_G4DA (of_machine_is_compatible("PowerMac3,4")) - -/* i2c address for tumbler */ -#define TAS_I2C_ADDR 0x34 - -/* registers */ -#define TAS_REG_MCS 0x01 /* main control */ -#define TAS_REG_DRC 0x02 -#define TAS_REG_VOL 0x04 -#define TAS_REG_TREBLE 0x05 -#define TAS_REG_BASS 0x06 -#define TAS_REG_INPUT1 0x07 -#define TAS_REG_INPUT2 0x08 - -/* tas3001c */ -#define TAS_REG_PCM TAS_REG_INPUT1 - -/* tas3004 */ -#define TAS_REG_LMIX TAS_REG_INPUT1 -#define TAS_REG_RMIX TAS_REG_INPUT2 -#define TAS_REG_MCS2 0x43 /* main control 2 */ -#define TAS_REG_ACS 0x40 /* analog control */ - -/* mono volumes for tas3001c/tas3004 */ -enum { - VOL_IDX_PCM_MONO, /* tas3001c only */ - VOL_IDX_BASS, VOL_IDX_TREBLE, - VOL_IDX_LAST_MONO -}; - -/* stereo volumes for tas3004 */ -enum { - VOL_IDX_PCM, VOL_IDX_PCM2, VOL_IDX_ADC, - VOL_IDX_LAST_MIX -}; - -struct pmac_gpio { - unsigned int addr; - u8 active_val; - u8 inactive_val; - u8 active_state; -}; - -struct pmac_tumbler { - struct pmac_keywest i2c; - struct pmac_gpio audio_reset; - struct pmac_gpio amp_mute; - struct pmac_gpio line_mute; - struct pmac_gpio line_detect; - struct pmac_gpio hp_mute; - struct pmac_gpio hp_detect; - int headphone_irq; - int lineout_irq; - unsigned int save_master_vol[2]; - unsigned int master_vol[2]; - unsigned int save_master_switch[2]; - unsigned int master_switch[2]; - unsigned int mono_vol[VOL_IDX_LAST_MONO]; - unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */ - int drc_range; - int drc_enable; - int capture_source; - int anded_reset; - int auto_mute_notify; - int reset_on_sleep; - u8 acs; -}; - - -/* - */ - -static int send_init_client(struct pmac_keywest *i2c, unsigned int *regs) -{ - while (*regs > 0) { - int err, count = 10; - do { - err = i2c_smbus_write_byte_data(i2c->client, - regs[0], regs[1]); - if (err >= 0) - break; - DBG("(W) i2c error %d\n", err); - mdelay(10); - } while (count--); - if (err < 0) - return -ENXIO; - regs += 2; - } - return 0; -} - - -static int tumbler_init_client(struct pmac_keywest *i2c) -{ - static unsigned int regs[] = { - /* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */ - TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0, - 0, /* terminator */ - }; - DBG("(I) tumbler init client\n"); - return send_init_client(i2c, regs); -} - -static int snapper_init_client(struct pmac_keywest *i2c) -{ - static unsigned int regs[] = { - /* normal operation, SCLK=64fps, i2s output, 16bit width */ - TAS_REG_MCS, (1<<6)|(2<<4)|0, - /* normal operation, all-pass mode */ - TAS_REG_MCS2, (1<<1), - /* normal output, no deemphasis, A input, power-up, line-in */ - TAS_REG_ACS, 0, - 0, /* terminator */ - }; - DBG("(I) snapper init client\n"); - return send_init_client(i2c, regs); -} - -/* - * gpio access - */ -#define do_gpio_write(gp, val) \ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) -#define do_gpio_read(gp) \ - pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) -#define tumbler_gpio_free(gp) /* NOP */ - -static void write_audio_gpio(struct pmac_gpio *gp, int active) -{ - if (! gp->addr) - return; - active = active ? gp->active_val : gp->inactive_val; - do_gpio_write(gp, active); - DBG("(I) gpio %x write %d\n", gp->addr, active); -} - -static int check_audio_gpio(struct pmac_gpio *gp) -{ - int ret; - - if (! gp->addr) - return 0; - - ret = do_gpio_read(gp); - - return (ret & 0x1) == (gp->active_val & 0x1); -} - -static int read_audio_gpio(struct pmac_gpio *gp) -{ - int ret; - if (! gp->addr) - return 0; - ret = do_gpio_read(gp); - ret = (ret & 0x02) !=0; - return ret == gp->active_state; -} - -/* - * update master volume - */ -static int tumbler_set_master_volume(struct pmac_tumbler *mix) -{ - unsigned char block[6]; - unsigned int left_vol, right_vol; - - if (! mix->i2c.client) - return -ENODEV; - - if (! mix->master_switch[0]) - left_vol = 0; - else { - left_vol = mix->master_vol[0]; - if (left_vol >= ARRAY_SIZE(master_volume_table)) - left_vol = ARRAY_SIZE(master_volume_table) - 1; - left_vol = master_volume_table[left_vol]; - } - if (! mix->master_switch[1]) - right_vol = 0; - else { - right_vol = mix->master_vol[1]; - if (right_vol >= ARRAY_SIZE(master_volume_table)) - right_vol = ARRAY_SIZE(master_volume_table) - 1; - right_vol = master_volume_table[right_vol]; - } - - block[0] = (left_vol >> 16) & 0xff; - block[1] = (left_vol >> 8) & 0xff; - block[2] = (left_vol >> 0) & 0xff; - - block[3] = (right_vol >> 16) & 0xff; - block[4] = (right_vol >> 8) & 0xff; - block[5] = (right_vol >> 0) & 0xff; - - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6, - block) < 0) { - snd_printk(KERN_ERR "failed to set volume \n"); - return -EINVAL; - } - DBG("(I) succeeded to set volume (%u, %u)\n", left_vol, right_vol); - return 0; -} - - -/* output volume */ -static int tumbler_info_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = ARRAY_SIZE(master_volume_table) - 1; - return 0; -} - -static int tumbler_get_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - - ucontrol->value.integer.value[0] = mix->master_vol[0]; - ucontrol->value.integer.value[1] = mix->master_vol[1]; - return 0; -} - -static int tumbler_put_master_volume(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - unsigned int vol[2]; - int change; - - vol[0] = ucontrol->value.integer.value[0]; - vol[1] = ucontrol->value.integer.value[1]; - if (vol[0] >= ARRAY_SIZE(master_volume_table) || - vol[1] >= ARRAY_SIZE(master_volume_table)) - return -EINVAL; - change = mix->master_vol[0] != vol[0] || - mix->master_vol[1] != vol[1]; - if (change) { - mix->master_vol[0] = vol[0]; - mix->master_vol[1] = vol[1]; - tumbler_set_master_volume(mix); - } - return change; -} - -/* output switch */ -static int tumbler_get_master_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - - ucontrol->value.integer.value[0] = mix->master_switch[0]; - ucontrol->value.integer.value[1] = mix->master_switch[1]; - return 0; -} - -static int tumbler_put_master_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - int change; - - change = mix->master_switch[0] != ucontrol->value.integer.value[0] || - mix->master_switch[1] != ucontrol->value.integer.value[1]; - if (change) { - mix->master_switch[0] = !!ucontrol->value.integer.value[0]; - mix->master_switch[1] = !!ucontrol->value.integer.value[1]; - tumbler_set_master_volume(mix); - } - return change; -} - - -/* - * TAS3001c dynamic range compression - */ - -#define TAS3001_DRC_MAX 0x5f - -static int tumbler_set_drc(struct pmac_tumbler *mix) -{ - unsigned char val[2]; - - if (! mix->i2c.client) - return -ENODEV; - - if (mix->drc_enable) { - val[0] = 0xc1; /* enable, 3:1 compression */ - if (mix->drc_range > TAS3001_DRC_MAX) - val[1] = 0xf0; - else if (mix->drc_range < 0) - val[1] = 0x91; - else - val[1] = mix->drc_range + 0x91; - } else { - val[0] = 0; - val[1] = 0; - } - - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, - 2, val) < 0) { - snd_printk(KERN_ERR "failed to set DRC\n"); - return -EINVAL; - } - DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]); - return 0; -} - -/* - * TAS3004 - */ - -#define TAS3004_DRC_MAX 0xef - -static int snapper_set_drc(struct pmac_tumbler *mix) -{ - unsigned char val[6]; - - if (! mix->i2c.client) - return -ENODEV; - - if (mix->drc_enable) - val[0] = 0x50; /* 3:1 above threshold */ - else - val[0] = 0x51; /* disabled */ - val[1] = 0x02; /* 1:1 below threshold */ - if (mix->drc_range > 0xef) - val[2] = 0xef; - else if (mix->drc_range < 0) - val[2] = 0x00; - else - val[2] = mix->drc_range; - val[3] = 0xb0; - val[4] = 0x60; - val[5] = 0xa0; - - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC, - 6, val) < 0) { - snd_printk(KERN_ERR "failed to set DRC\n"); - return -EINVAL; - } - DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]); - return 0; -} - -static int tumbler_info_drc_value(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = - chip->model == PMAC_TUMBLER ? TAS3001_DRC_MAX : TAS3004_DRC_MAX; - return 0; -} - -static int tumbler_get_drc_value(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->drc_range; - return 0; -} - -static int tumbler_put_drc_value(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - unsigned int val; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - val = ucontrol->value.integer.value[0]; - if (chip->model == PMAC_TUMBLER) { - if (val > TAS3001_DRC_MAX) - return -EINVAL; - } else { - if (val > TAS3004_DRC_MAX) - return -EINVAL; - } - change = mix->drc_range != val; - if (change) { - mix->drc_range = val; - if (chip->model == PMAC_TUMBLER) - tumbler_set_drc(mix); - else - snapper_set_drc(mix); - } - return change; -} - -static int tumbler_get_drc_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->drc_enable; - return 0; -} - -static int tumbler_put_drc_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - change = mix->drc_enable != ucontrol->value.integer.value[0]; - if (change) { - mix->drc_enable = !!ucontrol->value.integer.value[0]; - if (chip->model == PMAC_TUMBLER) - tumbler_set_drc(mix); - else - snapper_set_drc(mix); - } - return change; -} - - -/* - * mono volumes - */ - -struct tumbler_mono_vol { - int index; - int reg; - int bytes; - unsigned int max; - unsigned int *table; -}; - -static int tumbler_set_mono_volume(struct pmac_tumbler *mix, - struct tumbler_mono_vol *info) -{ - unsigned char block[4]; - unsigned int vol; - int i; - - if (! mix->i2c.client) - return -ENODEV; - - vol = mix->mono_vol[info->index]; - if (vol >= info->max) - vol = info->max - 1; - vol = info->table[vol]; - for (i = 0; i < info->bytes; i++) - block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff; - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg, - info->bytes, block) < 0) { - snd_printk(KERN_ERR "failed to set mono volume %d\n", - info->index); - return -EINVAL; - } - return 0; -} - -static int tumbler_info_mono(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = info->max - 1; - return 0; -} - -static int tumbler_get_mono(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value; - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->mono_vol[info->index]; - return 0; -} - -static int tumbler_put_mono(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value; - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - unsigned int vol; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - vol = ucontrol->value.integer.value[0]; - if (vol >= info->max) - return -EINVAL; - change = mix->mono_vol[info->index] != vol; - if (change) { - mix->mono_vol[info->index] = vol; - tumbler_set_mono_volume(mix, info); - } - return change; -} - -/* TAS3001c mono volumes */ -static struct tumbler_mono_vol tumbler_pcm_vol_info = { - .index = VOL_IDX_PCM_MONO, - .reg = TAS_REG_PCM, - .bytes = 3, - .max = ARRAY_SIZE(mixer_volume_table), - .table = mixer_volume_table, -}; - -static struct tumbler_mono_vol tumbler_bass_vol_info = { - .index = VOL_IDX_BASS, - .reg = TAS_REG_BASS, - .bytes = 1, - .max = ARRAY_SIZE(bass_volume_table), - .table = bass_volume_table, -}; - -static struct tumbler_mono_vol tumbler_treble_vol_info = { - .index = VOL_IDX_TREBLE, - .reg = TAS_REG_TREBLE, - .bytes = 1, - .max = ARRAY_SIZE(treble_volume_table), - .table = treble_volume_table, -}; - -/* TAS3004 mono volumes */ -static struct tumbler_mono_vol snapper_bass_vol_info = { - .index = VOL_IDX_BASS, - .reg = TAS_REG_BASS, - .bytes = 1, - .max = ARRAY_SIZE(snapper_bass_volume_table), - .table = snapper_bass_volume_table, -}; - -static struct tumbler_mono_vol snapper_treble_vol_info = { - .index = VOL_IDX_TREBLE, - .reg = TAS_REG_TREBLE, - .bytes = 1, - .max = ARRAY_SIZE(snapper_treble_volume_table), - .table = snapper_treble_volume_table, -}; - - -#define DEFINE_MONO(xname,type) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = tumbler_info_mono, \ - .get = tumbler_get_mono, \ - .put = tumbler_put_mono, \ - .private_value = (unsigned long)(&tumbler_##type##_vol_info), \ -} - -#define DEFINE_SNAPPER_MONO(xname,type) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = tumbler_info_mono, \ - .get = tumbler_get_mono, \ - .put = tumbler_put_mono, \ - .private_value = (unsigned long)(&snapper_##type##_vol_info), \ -} - - -/* - * snapper mixer volumes - */ - -static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int reg) -{ - int i, j, vol; - unsigned char block[9]; - - vol = mix->mix_vol[idx][ch]; - if (vol >= ARRAY_SIZE(mixer_volume_table)) { - vol = ARRAY_SIZE(mixer_volume_table) - 1; - mix->mix_vol[idx][ch] = vol; - } - - for (i = 0; i < 3; i++) { - vol = mix->mix_vol[i][ch]; - vol = mixer_volume_table[vol]; - for (j = 0; j < 3; j++) - block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff; - } - if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg, - 9, block) < 0) { - snd_printk(KERN_ERR "failed to set mono volume %d\n", reg); - return -EINVAL; - } - return 0; -} - -static int snapper_set_mix_vol(struct pmac_tumbler *mix, int idx) -{ - if (! mix->i2c.client) - return -ENODEV; - if (snapper_set_mix_vol1(mix, idx, 0, TAS_REG_LMIX) < 0 || - snapper_set_mix_vol1(mix, idx, 1, TAS_REG_RMIX) < 0) - return -EINVAL; - return 0; -} - -static int snapper_info_mix(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = ARRAY_SIZE(mixer_volume_table) - 1; - return 0; -} - -static int snapper_get_mix(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int idx = (int)kcontrol->private_value; - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) - return -ENODEV; - ucontrol->value.integer.value[0] = mix->mix_vol[idx][0]; - ucontrol->value.integer.value[1] = mix->mix_vol[idx][1]; - return 0; -} - -static int snapper_put_mix(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int idx = (int)kcontrol->private_value; - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - unsigned int vol[2]; - int change; - - if (! (mix = chip->mixer_data)) - return -ENODEV; - vol[0] = ucontrol->value.integer.value[0]; - vol[1] = ucontrol->value.integer.value[1]; - if (vol[0] >= ARRAY_SIZE(mixer_volume_table) || - vol[1] >= ARRAY_SIZE(mixer_volume_table)) - return -EINVAL; - change = mix->mix_vol[idx][0] != vol[0] || - mix->mix_vol[idx][1] != vol[1]; - if (change) { - mix->mix_vol[idx][0] = vol[0]; - mix->mix_vol[idx][1] = vol[1]; - snapper_set_mix_vol(mix, idx); - } - return change; -} - - -/* - * mute switches. FIXME: Turn that into software mute when both outputs are muted - * to avoid codec reset on ibook M7 - */ - -enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE }; - -static int tumbler_get_mute_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - struct pmac_gpio *gp; - if (! (mix = chip->mixer_data)) - return -ENODEV; - switch(kcontrol->private_value) { - case TUMBLER_MUTE_HP: - gp = &mix->hp_mute; break; - case TUMBLER_MUTE_AMP: - gp = &mix->amp_mute; break; - case TUMBLER_MUTE_LINE: - gp = &mix->line_mute; break; - default: - gp = NULL; - } - if (gp == NULL) - return -EINVAL; - ucontrol->value.integer.value[0] = !check_audio_gpio(gp); - return 0; -} - -static int tumbler_put_mute_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix; - struct pmac_gpio *gp; - int val; -#ifdef PMAC_SUPPORT_AUTOMUTE - if (chip->update_automute && chip->auto_mute) - return 0; /* don't touch in the auto-mute mode */ -#endif - if (! (mix = chip->mixer_data)) - return -ENODEV; - switch(kcontrol->private_value) { - case TUMBLER_MUTE_HP: - gp = &mix->hp_mute; break; - case TUMBLER_MUTE_AMP: - gp = &mix->amp_mute; break; - case TUMBLER_MUTE_LINE: - gp = &mix->line_mute; break; - default: - gp = NULL; - } - if (gp == NULL) - return -EINVAL; - val = ! check_audio_gpio(gp); - if (val != ucontrol->value.integer.value[0]) { - write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); - return 1; - } - return 0; -} - -static int snapper_set_capture_source(struct pmac_tumbler *mix) -{ - if (! mix->i2c.client) - return -ENODEV; - if (mix->capture_source) - mix->acs |= 2; - else - mix->acs &= ~2; - return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs); -} - -static int snapper_info_capture_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[2] = { - "Line", "Mic" - }; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snapper_get_capture_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - - ucontrol->value.enumerated.item[0] = mix->capture_source; - return 0; -} - -static int snapper_put_capture_source(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); - struct pmac_tumbler *mix = chip->mixer_data; - int change; - - change = ucontrol->value.enumerated.item[0] != mix->capture_source; - if (change) { - mix->capture_source = !!ucontrol->value.enumerated.item[0]; - snapper_set_capture_source(mix); - } - return change; -} - -#define DEFINE_SNAPPER_MIX(xname,idx,ofs) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = snapper_info_mix, \ - .get = snapper_get_mix, \ - .put = snapper_put_mix, \ - .index = idx,\ - .private_value = ofs, \ -} - - -/* - */ -static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = tumbler_info_master_volume, - .get = tumbler_get_master_volume, - .put = tumbler_put_master_volume - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = snd_pmac_boolean_stereo_info, - .get = tumbler_get_master_switch, - .put = tumbler_put_master_switch - }, - DEFINE_MONO("Tone Control - Bass", bass), - DEFINE_MONO("Tone Control - Treble", treble), - DEFINE_MONO("PCM Playback Volume", pcm), - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Range", - .info = tumbler_info_drc_value, - .get = tumbler_get_drc_value, - .put = tumbler_put_drc_value - }, -}; - -static struct snd_kcontrol_new snapper_mixers[] __devinitdata = { - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = tumbler_info_master_volume, - .get = tumbler_get_master_volume, - .put = tumbler_put_master_volume - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = snd_pmac_boolean_stereo_info, - .get = tumbler_get_master_switch, - .put = tumbler_put_master_switch - }, - DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM), - /* Alternative PCM is assigned to Mic analog loopback on iBook G4 */ - DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2), - DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC), - DEFINE_SNAPPER_MONO("Tone Control - Bass", bass), - DEFINE_SNAPPER_MONO("Tone Control - Treble", treble), - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Range", - .info = tumbler_info_drc_value, - .get = tumbler_get_drc_value, - .put = tumbler_put_drc_value - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", /* FIXME: "Capture Source" doesn't work properly */ - .info = snapper_info_capture_source, - .get = snapper_get_capture_source, - .put = snapper_put_capture_source - }, -}; - -static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_mute_switch, - .put = tumbler_put_mute_switch, - .private_value = TUMBLER_MUTE_HP, -}; -static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Speaker Playback Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_mute_switch, - .put = tumbler_put_mute_switch, - .private_value = TUMBLER_MUTE_AMP, -}; -static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Out Playback Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_mute_switch, - .put = tumbler_put_mute_switch, - .private_value = TUMBLER_MUTE_LINE, -}; -static struct snd_kcontrol_new tumbler_drc_sw __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_drc_switch, - .put = tumbler_put_drc_switch -}; - - -#ifdef PMAC_SUPPORT_AUTOMUTE -/* - * auto-mute stuffs - */ -static int tumbler_detect_headphone(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - int detect = 0; - - if (mix->hp_detect.addr) - detect |= read_audio_gpio(&mix->hp_detect); - return detect; -} - -static int tumbler_detect_lineout(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - int detect = 0; - - if (mix->line_detect.addr) - detect |= read_audio_gpio(&mix->line_detect); - return detect; -} - -static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int do_notify, - struct snd_kcontrol *sw) -{ - if (check_audio_gpio(gp) != val) { - write_audio_gpio(gp, val); - if (do_notify) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &sw->id); - } -} - -static struct work_struct device_change; -static struct snd_pmac *device_change_chip; - -static void device_change_handler(struct work_struct *work) -{ - struct snd_pmac *chip = device_change_chip; - struct pmac_tumbler *mix; - int headphone, lineout; - - if (!chip) - return; - - mix = chip->mixer_data; - if (snd_BUG_ON(!mix)) - return; - - headphone = tumbler_detect_headphone(chip); - lineout = tumbler_detect_lineout(chip); - - DBG("headphone: %d, lineout: %d\n", headphone, lineout); - - if (headphone || lineout) { - /* unmute headphone/lineout & mute speaker */ - if (headphone) - check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify, - chip->master_sw_ctl); - if (lineout && mix->line_mute.addr != 0) - check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, - chip->lineout_sw_ctl); - if (mix->anded_reset) - msleep(10); - check_mute(chip, &mix->amp_mute, !IS_G4DA, mix->auto_mute_notify, - chip->speaker_sw_ctl); - } else { - /* unmute speaker, mute others */ - check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, - chip->speaker_sw_ctl); - if (mix->anded_reset) - msleep(10); - check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, - chip->master_sw_ctl); - if (mix->line_mute.addr != 0) - check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify, - chip->lineout_sw_ctl); - } - if (mix->auto_mute_notify) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hp_detect_ctl->id); - -#ifdef CONFIG_SND_POWERMAC_AUTO_DRC - mix->drc_enable = ! (headphone || lineout); - if (mix->auto_mute_notify) - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->drc_sw_ctl->id); - if (chip->model == PMAC_TUMBLER) - tumbler_set_drc(mix); - else - snapper_set_drc(mix); -#endif - - /* reset the master volume so the correct amplification is applied */ - tumbler_set_master_volume(mix); -} - -static void tumbler_update_automute(struct snd_pmac *chip, int do_notify) -{ - if (chip->auto_mute) { - struct pmac_tumbler *mix; - mix = chip->mixer_data; - if (snd_BUG_ON(!mix)) - return; - mix->auto_mute_notify = do_notify; - schedule_work(&device_change); - } -} -#endif /* PMAC_SUPPORT_AUTOMUTE */ - - -/* interrupt - headphone plug changed */ -static irqreturn_t headphone_intr(int irq, void *devid) -{ - struct snd_pmac *chip = devid; - if (chip->update_automute && chip->initialized) { - chip->update_automute(chip, 1); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/* look for audio-gpio device */ -static struct device_node *find_audio_device(const char *name) -{ - struct device_node *gpiop; - struct device_node *np; - - gpiop = of_find_node_by_name(NULL, "gpio"); - if (! gpiop) - return NULL; - - for (np = of_get_next_child(gpiop, NULL); np; - np = of_get_next_child(gpiop, np)) { - const char *property = of_get_property(np, "audio-gpio", NULL); - if (property && strcmp(property, name) == 0) - break; - } - of_node_put(gpiop); - return np; -} - -/* look for audio-gpio device */ -static struct device_node *find_compatible_audio_device(const char *name) -{ - struct device_node *gpiop; - struct device_node *np; - - gpiop = of_find_node_by_name(NULL, "gpio"); - if (!gpiop) - return NULL; - - for (np = of_get_next_child(gpiop, NULL); np; - np = of_get_next_child(gpiop, np)) { - if (of_device_is_compatible(np, name)) - break; - } - of_node_put(gpiop); - return np; -} - -/* find an audio device and get its address */ -static long tumbler_find_device(const char *device, const char *platform, - struct pmac_gpio *gp, int is_compatible) -{ - struct device_node *node; - const u32 *base; - u32 addr; - long ret; - - if (is_compatible) - node = find_compatible_audio_device(device); - else - node = find_audio_device(device); - if (! node) { - DBG("(W) cannot find audio device %s !\n", device); - snd_printdd("cannot find device %s\n", device); - return -ENODEV; - } - - base = of_get_property(node, "AAPL,address", NULL); - if (! base) { - base = of_get_property(node, "reg", NULL); - if (!base) { - DBG("(E) cannot find address for device %s !\n", device); - snd_printd("cannot find address for device %s\n", device); - of_node_put(node); - return -ENODEV; - } - addr = *base; - if (addr < 0x50) - addr += 0x50; - } else - addr = *base; - - gp->addr = addr & 0x0000ffff; - /* Try to find the active state, default to 0 ! */ - base = of_get_property(node, "audio-gpio-active-state", NULL); - if (base) { - gp->active_state = *base; - gp->active_val = (*base) ? 0x5 : 0x4; - gp->inactive_val = (*base) ? 0x4 : 0x5; - } else { - const u32 *prop = NULL; - gp->active_state = IS_G4DA - && !strncmp(device, "keywest-gpio1", 13); - gp->active_val = 0x4; - gp->inactive_val = 0x5; - /* Here are some crude hacks to extract the GPIO polarity and - * open collector informations out of the do-platform script - * as we don't yet have an interpreter for these things - */ - if (platform) - prop = of_get_property(node, platform, NULL); - if (prop) { - if (prop[3] == 0x9 && prop[4] == 0x9) { - gp->active_val = 0xd; - gp->inactive_val = 0xc; - } - if (prop[3] == 0x1 && prop[4] == 0x1) { - gp->active_val = 0x5; - gp->inactive_val = 0x4; - } - } - } - - DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", - device, gp->addr, gp->active_state); - - ret = irq_of_parse_and_map(node, 0); - of_node_put(node); - return ret; -} - -/* reset audio */ -static void tumbler_reset_audio(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - - if (mix->anded_reset) { - DBG("(I) codec anded reset !\n"); - write_audio_gpio(&mix->hp_mute, 0); - write_audio_gpio(&mix->amp_mute, 0); - msleep(200); - write_audio_gpio(&mix->hp_mute, 1); - write_audio_gpio(&mix->amp_mute, 1); - msleep(100); - write_audio_gpio(&mix->hp_mute, 0); - write_audio_gpio(&mix->amp_mute, 0); - msleep(100); - } else { - DBG("(I) codec normal reset !\n"); - - write_audio_gpio(&mix->audio_reset, 0); - msleep(200); - write_audio_gpio(&mix->audio_reset, 1); - msleep(100); - write_audio_gpio(&mix->audio_reset, 0); - msleep(100); - } -} - -#ifdef CONFIG_PM -/* suspend mixer */ -static void tumbler_suspend(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - - if (mix->headphone_irq >= 0) - disable_irq(mix->headphone_irq); - if (mix->lineout_irq >= 0) - disable_irq(mix->lineout_irq); - mix->save_master_switch[0] = mix->master_switch[0]; - mix->save_master_switch[1] = mix->master_switch[1]; - mix->save_master_vol[0] = mix->master_vol[0]; - mix->save_master_vol[1] = mix->master_vol[1]; - mix->master_switch[0] = mix->master_switch[1] = 0; - tumbler_set_master_volume(mix); - if (!mix->anded_reset) { - write_audio_gpio(&mix->amp_mute, 1); - write_audio_gpio(&mix->hp_mute, 1); - } - if (chip->model == PMAC_SNAPPER) { - mix->acs |= 1; - i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs); - } - if (mix->anded_reset) { - write_audio_gpio(&mix->amp_mute, 1); - write_audio_gpio(&mix->hp_mute, 1); - } else - write_audio_gpio(&mix->audio_reset, 1); -} - -/* resume mixer */ -static void tumbler_resume(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - - mix->acs &= ~1; - mix->master_switch[0] = mix->save_master_switch[0]; - mix->master_switch[1] = mix->save_master_switch[1]; - mix->master_vol[0] = mix->save_master_vol[0]; - mix->master_vol[1] = mix->save_master_vol[1]; - tumbler_reset_audio(chip); - if (mix->i2c.client && mix->i2c.init_client) { - if (mix->i2c.init_client(&mix->i2c) < 0) - printk(KERN_ERR "tumbler_init_client error\n"); - } else - printk(KERN_ERR "tumbler: i2c is not initialized\n"); - if (chip->model == PMAC_TUMBLER) { - tumbler_set_mono_volume(mix, &tumbler_pcm_vol_info); - tumbler_set_mono_volume(mix, &tumbler_bass_vol_info); - tumbler_set_mono_volume(mix, &tumbler_treble_vol_info); - tumbler_set_drc(mix); - } else { - snapper_set_mix_vol(mix, VOL_IDX_PCM); - snapper_set_mix_vol(mix, VOL_IDX_PCM2); - snapper_set_mix_vol(mix, VOL_IDX_ADC); - tumbler_set_mono_volume(mix, &snapper_bass_vol_info); - tumbler_set_mono_volume(mix, &snapper_treble_vol_info); - snapper_set_drc(mix); - snapper_set_capture_source(mix); - } - tumbler_set_master_volume(mix); - if (chip->update_automute) - chip->update_automute(chip, 0); - if (mix->headphone_irq >= 0) { - unsigned char val; - - enable_irq(mix->headphone_irq); - /* activate headphone status interrupts */ - val = do_gpio_read(&mix->hp_detect); - do_gpio_write(&mix->hp_detect, val | 0x80); - } - if (mix->lineout_irq >= 0) - enable_irq(mix->lineout_irq); -} -#endif - -/* initialize tumbler */ -static int __devinit tumbler_init(struct snd_pmac *chip) -{ - int irq; - struct pmac_tumbler *mix = chip->mixer_data; - - if (tumbler_find_device("audio-hw-reset", - "platform-do-hw-reset", - &mix->audio_reset, 0) < 0) - tumbler_find_device("hw-reset", - "platform-do-hw-reset", - &mix->audio_reset, 1); - if (tumbler_find_device("amp-mute", - "platform-do-amp-mute", - &mix->amp_mute, 0) < 0) - tumbler_find_device("amp-mute", - "platform-do-amp-mute", - &mix->amp_mute, 1); - if (tumbler_find_device("headphone-mute", - "platform-do-headphone-mute", - &mix->hp_mute, 0) < 0) - tumbler_find_device("headphone-mute", - "platform-do-headphone-mute", - &mix->hp_mute, 1); - if (tumbler_find_device("line-output-mute", - "platform-do-lineout-mute", - &mix->line_mute, 0) < 0) - tumbler_find_device("line-output-mute", - "platform-do-lineout-mute", - &mix->line_mute, 1); - irq = tumbler_find_device("headphone-detect", - NULL, &mix->hp_detect, 0); - if (irq <= NO_IRQ) - irq = tumbler_find_device("headphone-detect", - NULL, &mix->hp_detect, 1); - if (irq <= NO_IRQ) - irq = tumbler_find_device("keywest-gpio15", - NULL, &mix->hp_detect, 1); - mix->headphone_irq = irq; - irq = tumbler_find_device("line-output-detect", - NULL, &mix->line_detect, 0); - if (irq <= NO_IRQ) - irq = tumbler_find_device("line-output-detect", - NULL, &mix->line_detect, 1); - if (IS_G4DA && irq <= NO_IRQ) - irq = tumbler_find_device("keywest-gpio16", - NULL, &mix->line_detect, 1); - mix->lineout_irq = irq; - - tumbler_reset_audio(chip); - - return 0; -} - -static void tumbler_cleanup(struct snd_pmac *chip) -{ - struct pmac_tumbler *mix = chip->mixer_data; - if (! mix) - return; - - if (mix->headphone_irq >= 0) - free_irq(mix->headphone_irq, chip); - if (mix->lineout_irq >= 0) - free_irq(mix->lineout_irq, chip); - tumbler_gpio_free(&mix->audio_reset); - tumbler_gpio_free(&mix->amp_mute); - tumbler_gpio_free(&mix->hp_mute); - tumbler_gpio_free(&mix->hp_detect); - snd_pmac_keywest_cleanup(&mix->i2c); - kfree(mix); - chip->mixer_data = NULL; -} - -/* exported */ -int __devinit snd_pmac_tumbler_init(struct snd_pmac *chip) -{ - int i, err; - struct pmac_tumbler *mix; - const u32 *paddr; - struct device_node *tas_node, *np; - char *chipname; - - request_module("i2c-powermac"); - - mix = kzalloc(sizeof(*mix), GFP_KERNEL); - if (! mix) - return -ENOMEM; - mix->headphone_irq = -1; - - chip->mixer_data = mix; - chip->mixer_free = tumbler_cleanup; - mix->anded_reset = 0; - mix->reset_on_sleep = 1; - - for (np = chip->node->child; np; np = np->sibling) { - if (!strcmp(np->name, "sound")) { - if (of_get_property(np, "has-anded-reset", NULL)) - mix->anded_reset = 1; - if (of_get_property(np, "layout-id", NULL)) - mix->reset_on_sleep = 0; - break; - } - } - if ((err = tumbler_init(chip)) < 0) - return err; - - /* set up TAS */ - tas_node = of_find_node_by_name(NULL, "deq"); - if (tas_node == NULL) - tas_node = of_find_node_by_name(NULL, "codec"); - if (tas_node == NULL) - return -ENODEV; - - paddr = of_get_property(tas_node, "i2c-address", NULL); - if (paddr == NULL) - paddr = of_get_property(tas_node, "reg", NULL); - if (paddr) - mix->i2c.addr = (*paddr) >> 1; - else - mix->i2c.addr = TAS_I2C_ADDR; - of_node_put(tas_node); - - DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr); - - if (chip->model == PMAC_TUMBLER) { - mix->i2c.init_client = tumbler_init_client; - mix->i2c.name = "TAS3001c"; - chipname = "Tumbler"; - } else { - mix->i2c.init_client = snapper_init_client; - mix->i2c.name = "TAS3004"; - chipname = "Snapper"; - } - - if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0) - return err; - - /* - * build mixers - */ - sprintf(chip->card->mixername, "PowerMac %s", chipname); - - if (chip->model == PMAC_TUMBLER) { - for (i = 0; i < ARRAY_SIZE(tumbler_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&tumbler_mixers[i], chip))) < 0) - return err; - } - } else { - for (i = 0; i < ARRAY_SIZE(snapper_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snapper_mixers[i], chip))) < 0) - return err; - } - } - chip->master_sw_ctl = snd_ctl_new1(&tumbler_hp_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0) - return err; - chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) - return err; - if (mix->line_mute.addr != 0) { - chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0) - return err; - } - chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) - return err; - - /* set initial DRC range to 60% */ - if (chip->model == PMAC_TUMBLER) - mix->drc_range = (TAS3001_DRC_MAX * 6) / 10; - else - mix->drc_range = (TAS3004_DRC_MAX * 6) / 10; - mix->drc_enable = 1; /* will be changed later if AUTO_DRC is set */ - if (chip->model == PMAC_TUMBLER) - tumbler_set_drc(mix); - else - snapper_set_drc(mix); - -#ifdef CONFIG_PM - chip->suspend = tumbler_suspend; - chip->resume = tumbler_resume; -#endif - - INIT_WORK(&device_change, device_change_handler); - device_change_chip = chip; - -#ifdef PMAC_SUPPORT_AUTOMUTE - if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0) - && (err = snd_pmac_add_automute(chip)) < 0) - return err; - chip->detect_headphone = tumbler_detect_headphone; - chip->update_automute = tumbler_update_automute; - tumbler_update_automute(chip, 0); /* update the status only */ - - /* activate headphone status interrupts */ - if (mix->headphone_irq >= 0) { - unsigned char val; - if ((err = request_irq(mix->headphone_irq, headphone_intr, 0, - "Sound Headphone Detection", chip)) < 0) - return 0; - /* activate headphone status interrupts */ - val = do_gpio_read(&mix->hp_detect); - do_gpio_write(&mix->hp_detect, val | 0x80); - } - if (mix->lineout_irq >= 0) { - unsigned char val; - if ((err = request_irq(mix->lineout_irq, headphone_intr, 0, - "Sound Lineout Detection", chip)) < 0) - return 0; - /* activate headphone status interrupts */ - val = do_gpio_read(&mix->line_detect); - do_gpio_write(&mix->line_detect, val | 0x80); - } -#endif - - return 0; -} diff --git a/ANDROID_3.4.5/sound/ppc/tumbler_volume.h b/ANDROID_3.4.5/sound/ppc/tumbler_volume.h deleted file mode 100644 index ef8d85d5..00000000 --- a/ANDROID_3.4.5/sound/ppc/tumbler_volume.h +++ /dev/null @@ -1,250 +0,0 @@ -/* volume tables, taken from TAS3001c data manual */ -/* volume gain values */ -/* 0 = -70 dB, 175 = 18.0 dB in 0.5 dB step */ -static unsigned int master_volume_table[] = { - 0x00000015, 0x00000016, 0x00000017, - 0x00000019, 0x0000001a, 0x0000001c, - 0x0000001d, 0x0000001f, 0x00000021, - 0x00000023, 0x00000025, 0x00000027, - 0x00000029, 0x0000002c, 0x0000002e, - 0x00000031, 0x00000034, 0x00000037, - 0x0000003a, 0x0000003e, 0x00000042, - 0x00000045, 0x0000004a, 0x0000004e, - 0x00000053, 0x00000057, 0x0000005d, - 0x00000062, 0x00000068, 0x0000006e, - 0x00000075, 0x0000007b, 0x00000083, - 0x0000008b, 0x00000093, 0x0000009b, - 0x000000a5, 0x000000ae, 0x000000b9, - 0x000000c4, 0x000000cf, 0x000000dc, - 0x000000e9, 0x000000f6, 0x00000105, - 0x00000114, 0x00000125, 0x00000136, - 0x00000148, 0x0000015c, 0x00000171, - 0x00000186, 0x0000019e, 0x000001b6, - 0x000001d0, 0x000001eb, 0x00000209, - 0x00000227, 0x00000248, 0x0000026b, - 0x0000028f, 0x000002b6, 0x000002df, - 0x0000030b, 0x00000339, 0x0000036a, - 0x0000039e, 0x000003d5, 0x0000040f, - 0x0000044c, 0x0000048d, 0x000004d2, - 0x0000051c, 0x00000569, 0x000005bb, - 0x00000612, 0x0000066e, 0x000006d0, - 0x00000737, 0x000007a5, 0x00000818, - 0x00000893, 0x00000915, 0x0000099f, - 0x00000a31, 0x00000acc, 0x00000b6f, - 0x00000c1d, 0x00000cd5, 0x00000d97, - 0x00000e65, 0x00000f40, 0x00001027, - 0x0000111c, 0x00001220, 0x00001333, - 0x00001456, 0x0000158a, 0x000016d1, - 0x0000182b, 0x0000199a, 0x00001b1e, - 0x00001cb9, 0x00001e6d, 0x0000203a, - 0x00002223, 0x00002429, 0x0000264e, - 0x00002893, 0x00002afa, 0x00002d86, - 0x00003039, 0x00003314, 0x0000361b, - 0x00003950, 0x00003cb5, 0x0000404e, - 0x0000441d, 0x00004827, 0x00004c6d, - 0x000050f4, 0x000055c0, 0x00005ad5, - 0x00006037, 0x000065ea, 0x00006bf4, - 0x0000725a, 0x00007920, 0x0000804e, - 0x000087e8, 0x00008ff6, 0x0000987d, - 0x0000a186, 0x0000ab19, 0x0000b53c, - 0x0000bff9, 0x0000cb59, 0x0000d766, - 0x0000e429, 0x0000f1ae, 0x00010000, - 0x00010f2b, 0x00011f3d, 0x00013042, - 0x00014249, 0x00015562, 0x0001699c, - 0x00017f09, 0x000195bc, 0x0001adc6, - 0x0001c73d, 0x0001e237, 0x0001feca, - 0x00021d0e, 0x00023d1d, 0x00025f12, - 0x0002830b, 0x0002a925, 0x0002d182, - 0x0002fc42, 0x0003298b, 0x00035983, - 0x00038c53, 0x0003c225, 0x0003fb28, - 0x0004378b, 0x00047783, 0x0004bb44, - 0x0005030a, 0x00054f10, 0x00059f98, - 0x0005f4e5, 0x00064f40, 0x0006aef6, - 0x00071457, 0x00077fbb, 0x0007f17b, -}; - -/* treble table for TAS3001c */ -/* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */ -static unsigned int treble_volume_table[] = { - 0x96, 0x95, 0x94, - 0x93, 0x92, 0x91, - 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, - 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, - 0x84, 0x83, 0x82, - 0x81, 0x80, 0x7f, - 0x7e, 0x7d, 0x7c, - 0x7b, 0x7a, 0x79, - 0x78, 0x77, 0x76, - 0x75, 0x74, 0x73, - 0x72, 0x71, 0x70, - 0x6e, 0x6d, 0x6c, - 0x6b, 0x69, 0x68, - 0x66, 0x65, 0x63, - 0x62, 0x60, 0x5e, - 0x5c, 0x5a, 0x57, - 0x55, 0x52, 0x4f, - 0x4c, 0x49, 0x45, - 0x42, 0x3e, 0x3a, - 0x36, 0x32, 0x2d, - 0x28, 0x22, 0x1c, - 0x16, 0x10, 0x09, - 0x01, -}; - -/* bass table for TAS3001c */ -/* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */ -static unsigned int bass_volume_table[] = { - 0x86, 0x82, 0x7f, - 0x7d, 0x7a, 0x78, - 0x76, 0x74, 0x72, - 0x70, 0x6e, 0x6d, - 0x6b, 0x69, 0x66, - 0x64, 0x61, 0x5f, - 0x5d, 0x5c, 0x5a, - 0x59, 0x58, 0x56, - 0x55, 0x54, 0x53, - 0x51, 0x4f, 0x4d, - 0x4b, 0x49, 0x46, - 0x44, 0x42, 0x40, - 0x3e, 0x3c, 0x3b, - 0x39, 0x38, 0x36, - 0x35, 0x33, 0x31, - 0x30, 0x2e, 0x2c, - 0x2b, 0x29, 0x28, - 0x26, 0x25, 0x23, - 0x21, 0x1f, 0x1c, - 0x19, 0x18, 0x17, - 0x16, 0x14, 0x13, - 0x12, 0x10, 0x0f, - 0x0d, 0x0b, 0x0a, - 0x08, 0x06, 0x03, - 0x01, -}; - -/* mixer (pcm) volume table */ -/* 0 = -70 dB, 175 = 18.0 dB in 0.5 dB step */ -static unsigned int mixer_volume_table[] = { - 0x00014b, 0x00015f, 0x000174, - 0x00018a, 0x0001a1, 0x0001ba, - 0x0001d4, 0x0001f0, 0x00020d, - 0x00022c, 0x00024d, 0x000270, - 0x000295, 0x0002bc, 0x0002e6, - 0x000312, 0x000340, 0x000372, - 0x0003a6, 0x0003dd, 0x000418, - 0x000456, 0x000498, 0x0004de, - 0x000528, 0x000576, 0x0005c9, - 0x000620, 0x00067d, 0x0006e0, - 0x000748, 0x0007b7, 0x00082c, - 0x0008a8, 0x00092b, 0x0009b6, - 0x000a49, 0x000ae5, 0x000b8b, - 0x000c3a, 0x000cf3, 0x000db8, - 0x000e88, 0x000f64, 0x00104e, - 0x001145, 0x00124b, 0x001361, - 0x001487, 0x0015be, 0x001708, - 0x001865, 0x0019d8, 0x001b60, - 0x001cff, 0x001eb7, 0x002089, - 0x002276, 0x002481, 0x0026ab, - 0x0028f5, 0x002b63, 0x002df5, - 0x0030ae, 0x003390, 0x00369e, - 0x0039db, 0x003d49, 0x0040ea, - 0x0044c3, 0x0048d6, 0x004d27, - 0x0051b9, 0x005691, 0x005bb2, - 0x006121, 0x0066e3, 0x006cfb, - 0x007370, 0x007a48, 0x008186, - 0x008933, 0x009154, 0x0099f1, - 0x00a310, 0x00acba, 0x00b6f6, - 0x00c1cd, 0x00cd49, 0x00d973, - 0x00e655, 0x00f3fb, 0x010270, - 0x0111c0, 0x0121f9, 0x013328, - 0x01455b, 0x0158a2, 0x016d0e, - 0x0182af, 0x019999, 0x01b1de, - 0x01cb94, 0x01e6cf, 0x0203a7, - 0x022235, 0x024293, 0x0264db, - 0x02892c, 0x02afa3, 0x02d862, - 0x03038a, 0x033142, 0x0361af, - 0x0394fa, 0x03cb50, 0x0404de, - 0x0441d5, 0x048268, 0x04c6d0, - 0x050f44, 0x055c04, 0x05ad50, - 0x06036e, 0x065ea5, 0x06bf44, - 0x07259d, 0x079207, 0x0804dc, - 0x087e80, 0x08ff59, 0x0987d5, - 0x0a1866, 0x0ab189, 0x0b53be, - 0x0bff91, 0x0cb591, 0x0d765a, - 0x0e4290, 0x0f1adf, 0x100000, - 0x10f2b4, 0x11f3c9, 0x13041a, - 0x14248e, 0x15561a, 0x1699c0, - 0x17f094, 0x195bb8, 0x1adc61, - 0x1c73d5, 0x1e236d, 0x1fec98, - 0x21d0d9, 0x23d1cd, 0x25f125, - 0x2830af, 0x2a9254, 0x2d1818, - 0x2fc420, 0x3298b0, 0x35982f, - 0x38c528, 0x3c224c, 0x3fb278, - 0x437880, 0x477828, 0x4bb446, - 0x5030a1, 0x54f106, 0x59f980, - 0x5f4e52, 0x64f403, 0x6aef5d, - 0x714575, 0x77fbaa, 0x7f17af, -}; - - -/* treble table for TAS3004 */ -/* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */ -static unsigned int snapper_treble_volume_table[] = { - 0x96, 0x95, 0x94, - 0x93, 0x92, 0x91, - 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, - 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, - 0x84, 0x83, 0x82, - 0x81, 0x80, 0x7f, - 0x7e, 0x7d, 0x7c, - 0x7b, 0x7a, 0x79, - 0x78, 0x77, 0x76, - 0x75, 0x74, 0x73, - 0x72, 0x71, 0x70, - 0x6f, 0x6d, 0x6c, - 0x6b, 0x69, 0x68, - 0x67, 0x65, 0x63, - 0x62, 0x60, 0x5d, - 0x5b, 0x59, 0x56, - 0x53, 0x51, 0x4d, - 0x4a, 0x47, 0x43, - 0x3f, 0x3b, 0x36, - 0x31, 0x2c, 0x26, - 0x20, 0x1a, 0x13, - 0x08, 0x04, 0x01, - 0x01, -}; - -/* bass table for TAS3004 */ -/* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */ -static unsigned int snapper_bass_volume_table[] = { - 0x96, 0x95, 0x94, - 0x93, 0x92, 0x91, - 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, - 0x8a, 0x89, 0x88, - 0x87, 0x86, 0x85, - 0x84, 0x83, 0x82, - 0x81, 0x80, 0x7f, - 0x7e, 0x7d, 0x7c, - 0x7b, 0x7a, 0x79, - 0x78, 0x77, 0x76, - 0x75, 0x74, 0x73, - 0x72, 0x71, 0x6f, - 0x6e, 0x6d, 0x6b, - 0x6a, 0x69, 0x67, - 0x66, 0x65, 0x63, - 0x62, 0x61, 0x5f, - 0x5d, 0x5b, 0x58, - 0x55, 0x52, 0x4f, - 0x4c, 0x49, 0x46, - 0x43, 0x3f, 0x3b, - 0x37, 0x33, 0x2e, - 0x29, 0x24, 0x1e, - 0x18, 0x11, 0x0a, - 0x01, -}; - diff --git a/ANDROID_3.4.5/sound/sh/Kconfig b/ANDROID_3.4.5/sound/sh/Kconfig deleted file mode 100644 index 61139f3c..00000000 --- a/ANDROID_3.4.5/sound/sh/Kconfig +++ /dev/null @@ -1,31 +0,0 @@ -# ALSA SH drivers - -menuconfig SND_SUPERH - bool "SUPERH sound devices" - depends on SUPERH - default y - help - Support for sound devices specific to SUPERH architectures. - Drivers that are implemented on ASoC can be found in - "ALSA for SoC audio support" section. - -if SND_SUPERH - -config SND_AICA - tristate "Dreamcast Yamaha AICA sound" - depends on SH_DREAMCAST - select SND_PCM - select G2_DMA - help - ALSA Sound driver for the SEGA Dreamcast console. - -config SND_SH_DAC_AUDIO - tristate "SuperH DAC audio support" - depends on SND - depends on CPU_SH3 && HIGH_RES_TIMERS - select SND_PCM - help - Say Y here to include support for the on-chip DAC. - -endif # SND_SUPERH - diff --git a/ANDROID_3.4.5/sound/sh/Makefile b/ANDROID_3.4.5/sound/sh/Makefile deleted file mode 100644 index 7d09b518..00000000 --- a/ANDROID_3.4.5/sound/sh/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# - -snd-aica-objs := aica.o -snd-sh_dac_audio-objs := sh_dac_audio.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AICA) += snd-aica.o -obj-$(CONFIG_SND_SH_DAC_AUDIO) += snd-sh_dac_audio.o diff --git a/ANDROID_3.4.5/sound/sh/aica.c b/ANDROID_3.4.5/sound/sh/aica.c deleted file mode 100644 index 391a38ca..00000000 --- a/ANDROID_3.4.5/sound/sh/aica.c +++ /dev/null @@ -1,689 +0,0 @@ -/* -* This code is licenced under -* the General Public Licence -* version 2 -* -* Copyright Adrian McMenamin 2005, 2006, 2007 -* -* Requires firmware (BSD licenced) available from: -* http://linuxdc.cvs.sourceforge.net/linuxdc/linux-sh-dc/sound/oss/aica/firmware/ -* or the maintainer -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of version 2 of the GNU General Public License as published by -* the Free Software Foundation. -* -* 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "aica.h" - -MODULE_AUTHOR("Adrian McMenamin "); -MODULE_DESCRIPTION("Dreamcast AICA sound (pcm) driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Yamaha/SEGA, AICA}}"); -MODULE_FIRMWARE("aica_firmware.bin"); - -/* module parameters */ -#define CARD_NAME "AICA" -static int index = -1; -static char *id; -static bool enable = 1; -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param(enable, bool, 0644); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - -/* Use workqueue */ -static struct workqueue_struct *aica_queue; - -/* Simple platform device */ -static struct platform_device *pd; -static struct resource aica_memory_space[2] = { - { - .name = "AICA ARM CONTROL", - .start = ARM_RESET_REGISTER, - .flags = IORESOURCE_MEM, - .end = ARM_RESET_REGISTER + 3, - }, - { - .name = "AICA Sound RAM", - .start = SPU_MEMORY_BASE, - .flags = IORESOURCE_MEM, - .end = SPU_MEMORY_BASE + 0x200000 - 1, - }, -}; - -/* SPU specific functions */ -/* spu_write_wait - wait for G2-SH FIFO to clear */ -static void spu_write_wait(void) -{ - int time_count; - time_count = 0; - while (1) { - if (!(readl(G2_FIFO) & 0x11)) - break; - /* To ensure hardware failure doesn't wedge kernel */ - time_count++; - if (time_count > 0x10000) { - snd_printk - ("WARNING: G2 FIFO appears to be blocked.\n"); - break; - } - } -} - -/* spu_memset - write to memory in SPU address space */ -static void spu_memset(u32 toi, u32 what, int length) -{ - int i; - unsigned long flags; - if (snd_BUG_ON(length % 4)) - return; - for (i = 0; i < length; i++) { - if (!(i % 8)) - spu_write_wait(); - local_irq_save(flags); - writel(what, toi + SPU_MEMORY_BASE); - local_irq_restore(flags); - toi++; - } -} - -/* spu_memload - write to SPU address space */ -static void spu_memload(u32 toi, void *from, int length) -{ - unsigned long flags; - u32 *froml = from; - u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi); - int i; - u32 val; - length = DIV_ROUND_UP(length, 4); - spu_write_wait(); - for (i = 0; i < length; i++) { - if (!(i % 8)) - spu_write_wait(); - val = *froml; - local_irq_save(flags); - writel(val, to); - local_irq_restore(flags); - froml++; - to++; - } -} - -/* spu_disable - set spu registers to stop sound output */ -static void spu_disable(void) -{ - int i; - unsigned long flags; - u32 regval; - spu_write_wait(); - regval = readl(ARM_RESET_REGISTER); - regval |= 1; - spu_write_wait(); - local_irq_save(flags); - writel(regval, ARM_RESET_REGISTER); - local_irq_restore(flags); - for (i = 0; i < 64; i++) { - spu_write_wait(); - regval = readl(SPU_REGISTER_BASE + (i * 0x80)); - regval = (regval & ~0x4000) | 0x8000; - spu_write_wait(); - local_irq_save(flags); - writel(regval, SPU_REGISTER_BASE + (i * 0x80)); - local_irq_restore(flags); - } -} - -/* spu_enable - set spu registers to enable sound output */ -static void spu_enable(void) -{ - unsigned long flags; - u32 regval = readl(ARM_RESET_REGISTER); - regval &= ~1; - spu_write_wait(); - local_irq_save(flags); - writel(regval, ARM_RESET_REGISTER); - local_irq_restore(flags); -} - -/* - * Halt the sound processor, clear the memory, - * load some default ARM7 code, and then restart ARM7 -*/ -static void spu_reset(void) -{ - unsigned long flags; - spu_disable(); - spu_memset(0, 0, 0x200000 / 4); - /* Put ARM7 in endless loop */ - local_irq_save(flags); - __raw_writel(0xea000002, SPU_MEMORY_BASE); - local_irq_restore(flags); - spu_enable(); -} - -/* aica_chn_start - write to spu to start playback */ -static void aica_chn_start(void) -{ - unsigned long flags; - spu_write_wait(); - local_irq_save(flags); - writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT); - local_irq_restore(flags); -} - -/* aica_chn_halt - write to spu to halt playback */ -static void aica_chn_halt(void) -{ - unsigned long flags; - spu_write_wait(); - local_irq_save(flags); - writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT); - local_irq_restore(flags); -} - -/* ALSA code below */ -static struct snd_pcm_hardware snd_pcm_aica_playback_hw = { - .info = (SNDRV_PCM_INFO_NONINTERLEAVED), - .formats = - (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_IMA_ADPCM), - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = AICA_BUFFER_SIZE, - .period_bytes_min = AICA_PERIOD_SIZE, - .period_bytes_max = AICA_PERIOD_SIZE, - .periods_min = AICA_PERIOD_NUMBER, - .periods_max = AICA_PERIOD_NUMBER, -}; - -static int aica_dma_transfer(int channels, int buffer_size, - struct snd_pcm_substream *substream) -{ - int q, err, period_offset; - struct snd_card_aica *dreamcastcard; - struct snd_pcm_runtime *runtime; - unsigned long flags; - err = 0; - dreamcastcard = substream->pcm->private_data; - period_offset = dreamcastcard->clicks; - period_offset %= (AICA_PERIOD_NUMBER / channels); - runtime = substream->runtime; - for (q = 0; q < channels; q++) { - local_irq_save(flags); - err = dma_xfer(AICA_DMA_CHANNEL, - (unsigned long) (runtime->dma_area + - (AICA_BUFFER_SIZE * q) / - channels + - AICA_PERIOD_SIZE * - period_offset), - AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET + - AICA_PERIOD_SIZE * period_offset, - buffer_size / channels, AICA_DMA_MODE); - if (unlikely(err < 0)) { - local_irq_restore(flags); - break; - } - dma_wait_for_completion(AICA_DMA_CHANNEL); - local_irq_restore(flags); - } - return err; -} - -static void startup_aica(struct snd_card_aica *dreamcastcard) -{ - spu_memload(AICA_CHANNEL0_CONTROL_OFFSET, - dreamcastcard->channel, sizeof(struct aica_channel)); - aica_chn_start(); -} - -static void run_spu_dma(struct work_struct *work) -{ - int buffer_size; - struct snd_pcm_runtime *runtime; - struct snd_card_aica *dreamcastcard; - dreamcastcard = - container_of(work, struct snd_card_aica, spu_dma_work); - runtime = dreamcastcard->substream->runtime; - if (unlikely(dreamcastcard->dma_check == 0)) { - buffer_size = - frames_to_bytes(runtime, runtime->buffer_size); - if (runtime->channels > 1) - dreamcastcard->channel->flags |= 0x01; - aica_dma_transfer(runtime->channels, buffer_size, - dreamcastcard->substream); - startup_aica(dreamcastcard); - dreamcastcard->clicks = - buffer_size / (AICA_PERIOD_SIZE * runtime->channels); - return; - } else { - aica_dma_transfer(runtime->channels, - AICA_PERIOD_SIZE * runtime->channels, - dreamcastcard->substream); - snd_pcm_period_elapsed(dreamcastcard->substream); - dreamcastcard->clicks++; - if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER)) - dreamcastcard->clicks %= AICA_PERIOD_NUMBER; - mod_timer(&dreamcastcard->timer, jiffies + 1); - } -} - -static void aica_period_elapsed(unsigned long timer_var) -{ - /*timer function - so cannot sleep */ - int play_period; - struct snd_pcm_runtime *runtime; - struct snd_pcm_substream *substream; - struct snd_card_aica *dreamcastcard; - substream = (struct snd_pcm_substream *) timer_var; - runtime = substream->runtime; - dreamcastcard = substream->pcm->private_data; - /* Have we played out an additional period? */ - play_period = - frames_to_bytes(runtime, - readl - (AICA_CONTROL_CHANNEL_SAMPLE_NUMBER)) / - AICA_PERIOD_SIZE; - if (play_period == dreamcastcard->current_period) { - /* reschedule the timer */ - mod_timer(&(dreamcastcard->timer), jiffies + 1); - return; - } - if (runtime->channels > 1) - dreamcastcard->current_period = play_period; - if (unlikely(dreamcastcard->dma_check == 0)) - dreamcastcard->dma_check = 1; - queue_work(aica_queue, &(dreamcastcard->spu_dma_work)); -} - -static void spu_begin_dma(struct snd_pcm_substream *substream) -{ - struct snd_card_aica *dreamcastcard; - struct snd_pcm_runtime *runtime; - runtime = substream->runtime; - dreamcastcard = substream->pcm->private_data; - /*get the queue to do the work */ - queue_work(aica_queue, &(dreamcastcard->spu_dma_work)); - /* Timer may already be running */ - if (unlikely(dreamcastcard->timer.data)) { - mod_timer(&dreamcastcard->timer, jiffies + 4); - return; - } - init_timer(&(dreamcastcard->timer)); - dreamcastcard->timer.data = (unsigned long) substream; - dreamcastcard->timer.function = aica_period_elapsed; - dreamcastcard->timer.expires = jiffies + 4; - add_timer(&(dreamcastcard->timer)); -} - -static int snd_aicapcm_pcm_open(struct snd_pcm_substream - *substream) -{ - struct snd_pcm_runtime *runtime; - struct aica_channel *channel; - struct snd_card_aica *dreamcastcard; - if (!enable) - return -ENOENT; - dreamcastcard = substream->pcm->private_data; - channel = kmalloc(sizeof(struct aica_channel), GFP_KERNEL); - if (!channel) - return -ENOMEM; - /* set defaults for channel */ - channel->sfmt = SM_8BIT; - channel->cmd = AICA_CMD_START; - channel->vol = dreamcastcard->master_volume; - channel->pan = 0x80; - channel->pos = 0; - channel->flags = 0; /* default to mono */ - dreamcastcard->channel = channel; - runtime = substream->runtime; - runtime->hw = snd_pcm_aica_playback_hw; - spu_enable(); - dreamcastcard->clicks = 0; - dreamcastcard->current_period = 0; - dreamcastcard->dma_check = 0; - return 0; -} - -static int snd_aicapcm_pcm_close(struct snd_pcm_substream - *substream) -{ - struct snd_card_aica *dreamcastcard = substream->pcm->private_data; - flush_workqueue(aica_queue); - if (dreamcastcard->timer.data) - del_timer(&dreamcastcard->timer); - kfree(dreamcastcard->channel); - spu_disable(); - return 0; -} - -static int snd_aicapcm_pcm_hw_free(struct snd_pcm_substream - *substream) -{ - /* Free the DMA buffer */ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_aicapcm_pcm_hw_params(struct snd_pcm_substream - *substream, struct snd_pcm_hw_params - *hw_params) -{ - /* Allocate a DMA buffer using ALSA built-ins */ - return - snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int snd_aicapcm_pcm_prepare(struct snd_pcm_substream - *substream) -{ - struct snd_card_aica *dreamcastcard = substream->pcm->private_data; - if ((substream->runtime)->format == SNDRV_PCM_FORMAT_S16_LE) - dreamcastcard->channel->sfmt = SM_16BIT; - dreamcastcard->channel->freq = substream->runtime->rate; - dreamcastcard->substream = substream; - return 0; -} - -static int snd_aicapcm_pcm_trigger(struct snd_pcm_substream - *substream, int cmd) -{ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - spu_begin_dma(substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - aica_chn_halt(); - break; - default: - return -EINVAL; - } - return 0; -} - -static unsigned long snd_aicapcm_pcm_pointer(struct snd_pcm_substream - *substream) -{ - return readl(AICA_CONTROL_CHANNEL_SAMPLE_NUMBER); -} - -static struct snd_pcm_ops snd_aicapcm_playback_ops = { - .open = snd_aicapcm_pcm_open, - .close = snd_aicapcm_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_aicapcm_pcm_hw_params, - .hw_free = snd_aicapcm_pcm_hw_free, - .prepare = snd_aicapcm_pcm_prepare, - .trigger = snd_aicapcm_pcm_trigger, - .pointer = snd_aicapcm_pcm_pointer, -}; - -/* TO DO: set up to handle more than one pcm instance */ -static int __init snd_aicapcmchip(struct snd_card_aica - *dreamcastcard, int pcm_index) -{ - struct snd_pcm *pcm; - int err; - /* AICA has no capture ability */ - err = - snd_pcm_new(dreamcastcard->card, "AICA PCM", pcm_index, 1, 0, - &pcm); - if (unlikely(err < 0)) - return err; - pcm->private_data = dreamcastcard; - strcpy(pcm->name, "AICA PCM"); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_aicapcm_playback_ops); - /* Allocate the DMA buffers */ - err = - snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data - (GFP_KERNEL), - AICA_BUFFER_SIZE, - AICA_BUFFER_SIZE); - return err; -} - -/* Mixer controls */ -#define aica_pcmswitch_info snd_ctl_boolean_mono_info - -static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = 1; /* TO DO: Fix me */ - return 0; -} - -static int aica_pcmswitch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - if (ucontrol->value.integer.value[0] == 1) - return 0; /* TO DO: Fix me */ - else - aica_chn_halt(); - return 0; -} - -static int aica_pcmvolume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xFF; - return 0; -} - -static int aica_pcmvolume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_card_aica *dreamcastcard; - dreamcastcard = kcontrol->private_data; - if (unlikely(!dreamcastcard->channel)) - return -ETXTBSY; /* we've not yet been set up */ - ucontrol->value.integer.value[0] = dreamcastcard->channel->vol; - return 0; -} - -static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_card_aica *dreamcastcard; - unsigned int vol; - dreamcastcard = kcontrol->private_data; - if (unlikely(!dreamcastcard->channel)) - return -ETXTBSY; - vol = ucontrol->value.integer.value[0]; - if (vol > 0xff) - return -EINVAL; - if (unlikely(dreamcastcard->channel->vol == vol)) - return 0; - dreamcastcard->channel->vol = ucontrol->value.integer.value[0]; - dreamcastcard->master_volume = ucontrol->value.integer.value[0]; - spu_memload(AICA_CHANNEL0_CONTROL_OFFSET, - dreamcastcard->channel, sizeof(struct aica_channel)); - return 1; -} - -static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Switch", - .index = 0, - .info = aica_pcmswitch_info, - .get = aica_pcmswitch_get, - .put = aica_pcmswitch_put -}; - -static struct snd_kcontrol_new snd_aica_pcmvolume_control __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .index = 0, - .info = aica_pcmvolume_info, - .get = aica_pcmvolume_get, - .put = aica_pcmvolume_put -}; - -static int load_aica_firmware(void) -{ - int err; - const struct firmware *fw_entry; - spu_reset(); - err = request_firmware(&fw_entry, "aica_firmware.bin", &pd->dev); - if (unlikely(err)) - return err; - /* write firmware into memory */ - spu_disable(); - spu_memload(0, fw_entry->data, fw_entry->size); - spu_enable(); - release_firmware(fw_entry); - return err; -} - -static int __devinit add_aicamixer_controls(struct snd_card_aica - *dreamcastcard) -{ - int err; - err = snd_ctl_add - (dreamcastcard->card, - snd_ctl_new1(&snd_aica_pcmvolume_control, dreamcastcard)); - if (unlikely(err < 0)) - return err; - err = snd_ctl_add - (dreamcastcard->card, - snd_ctl_new1(&snd_aica_pcmswitch_control, dreamcastcard)); - if (unlikely(err < 0)) - return err; - return 0; -} - -static int __devexit snd_aica_remove(struct platform_device *devptr) -{ - struct snd_card_aica *dreamcastcard; - dreamcastcard = platform_get_drvdata(devptr); - if (unlikely(!dreamcastcard)) - return -ENODEV; - snd_card_free(dreamcastcard->card); - kfree(dreamcastcard); - platform_set_drvdata(devptr, NULL); - return 0; -} - -static int __devinit snd_aica_probe(struct platform_device *devptr) -{ - int err; - struct snd_card_aica *dreamcastcard; - dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL); - if (unlikely(!dreamcastcard)) - return -ENOMEM; - err = snd_card_create(index, SND_AICA_DRIVER, THIS_MODULE, 0, - &dreamcastcard->card); - if (unlikely(err < 0)) { - kfree(dreamcastcard); - return err; - } - strcpy(dreamcastcard->card->driver, "snd_aica"); - strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER); - strcpy(dreamcastcard->card->longname, - "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast"); - /* Prepare to use the queue */ - INIT_WORK(&(dreamcastcard->spu_dma_work), run_spu_dma); - /* Load the PCM 'chip' */ - err = snd_aicapcmchip(dreamcastcard, 0); - if (unlikely(err < 0)) - goto freedreamcast; - snd_card_set_dev(dreamcastcard->card, &devptr->dev); - dreamcastcard->timer.data = 0; - dreamcastcard->channel = NULL; - /* Add basic controls */ - err = add_aicamixer_controls(dreamcastcard); - if (unlikely(err < 0)) - goto freedreamcast; - /* Register the card with ALSA subsystem */ - err = snd_card_register(dreamcastcard->card); - if (unlikely(err < 0)) - goto freedreamcast; - platform_set_drvdata(devptr, dreamcastcard); - aica_queue = create_workqueue(CARD_NAME); - if (unlikely(!aica_queue)) - goto freedreamcast; - snd_printk - ("ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n"); - return 0; - freedreamcast: - snd_card_free(dreamcastcard->card); - kfree(dreamcastcard); - return err; -} - -static struct platform_driver snd_aica_driver = { - .probe = snd_aica_probe, - .remove = __devexit_p(snd_aica_remove), - .driver = { - .name = SND_AICA_DRIVER}, -}; - -static int __init aica_init(void) -{ - int err; - err = platform_driver_register(&snd_aica_driver); - if (unlikely(err < 0)) - return err; - pd = platform_device_register_simple(SND_AICA_DRIVER, -1, - aica_memory_space, 2); - if (IS_ERR(pd)) { - platform_driver_unregister(&snd_aica_driver); - return PTR_ERR(pd); - } - /* Load the firmware */ - return load_aica_firmware(); -} - -static void __exit aica_exit(void) -{ - /* Destroy the aica kernel thread * - * being extra cautious to check if it exists*/ - if (likely(aica_queue)) - destroy_workqueue(aica_queue); - platform_device_unregister(pd); - platform_driver_unregister(&snd_aica_driver); - /* Kill any sound still playing and reset ARM7 to safe state */ - spu_reset(); -} - -module_init(aica_init); -module_exit(aica_exit); diff --git a/ANDROID_3.4.5/sound/sh/aica.h b/ANDROID_3.4.5/sound/sh/aica.h deleted file mode 100644 index d098baaa..00000000 --- a/ANDROID_3.4.5/sound/sh/aica.h +++ /dev/null @@ -1,81 +0,0 @@ -/* aica.h - * Header file for ALSA driver for - * Sega Dreamcast Yamaha AICA sound - * Copyright Adrian McMenamin - * - * 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as published by - * the Free Software Foundation. - * - * 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 - * - */ - -/* SPU memory and register constants etc */ -#define G2_FIFO 0xa05f688c -#define SPU_MEMORY_BASE 0xA0800000 -#define ARM_RESET_REGISTER 0xA0702C00 -#define SPU_REGISTER_BASE 0xA0700000 - -/* AICA channels stuff */ -#define AICA_CONTROL_POINT 0xA0810000 -#define AICA_CONTROL_CHANNEL_SAMPLE_NUMBER 0xA0810008 -#define AICA_CHANNEL0_CONTROL_OFFSET 0x10004 - -/* Command values */ -#define AICA_CMD_KICK 0x80000000 -#define AICA_CMD_NONE 0 -#define AICA_CMD_START 1 -#define AICA_CMD_STOP 2 -#define AICA_CMD_VOL 3 - -/* Sound modes */ -#define SM_8BIT 1 -#define SM_16BIT 0 -#define SM_ADPCM 2 - -/* Buffer and period size */ -#define AICA_BUFFER_SIZE 0x8000 -#define AICA_PERIOD_SIZE 0x800 -#define AICA_PERIOD_NUMBER 16 - -#define AICA_CHANNEL0_OFFSET 0x11000 -#define AICA_CHANNEL1_OFFSET 0x21000 -#define CHANNEL_OFFSET 0x10000 - -#define AICA_DMA_CHANNEL 5 -#define AICA_DMA_MODE 5 - -#define SND_AICA_DRIVER "AICA" - -struct aica_channel { - uint32_t cmd; /* Command ID */ - uint32_t pos; /* Sample position */ - uint32_t length; /* Sample length */ - uint32_t freq; /* Frequency */ - uint32_t vol; /* Volume 0-255 */ - uint32_t pan; /* Pan 0-255 */ - uint32_t sfmt; /* Sound format */ - uint32_t flags; /* Bit flags */ -}; - -struct snd_card_aica { - struct work_struct spu_dma_work; - struct snd_card *card; - struct aica_channel *channel; - struct snd_pcm_substream *substream; - int clicks; - int current_period; - struct timer_list timer; - int master_volume; - int dma_check; -}; diff --git a/ANDROID_3.4.5/sound/sh/sh_dac_audio.c b/ANDROID_3.4.5/sound/sh/sh_dac_audio.c deleted file mode 100644 index b11f82b5..00000000 --- a/ANDROID_3.4.5/sound/sh/sh_dac_audio.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * sh_dac_audio.c - SuperH DAC audio driver for ALSA - * - * Copyright (c) 2009 by Rafael Ignacio Zurita - * - * - * Based on sh_dac_audio.c (Copyright (C) 2004, 2005 by Andriy Skulysh) - * - * 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 -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Rafael Ignacio Zurita "); -MODULE_DESCRIPTION("SuperH DAC audio driver"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{SuperH DAC audio support}}"); - -/* Module Parameters */ -static int index = SNDRV_DEFAULT_IDX1; -static char *id = SNDRV_DEFAULT_STR1; -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for SuperH DAC audio."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for SuperH DAC audio."); - -/* main struct */ -struct snd_sh_dac { - struct snd_card *card; - struct snd_pcm_substream *substream; - struct hrtimer hrtimer; - ktime_t wakeups_per_second; - - int rate; - int empty; - char *data_buffer, *buffer_begin, *buffer_end; - int processed; /* bytes proccesed, to compare with period_size */ - int buffer_size; - struct dac_audio_pdata *pdata; -}; - - -static void dac_audio_start_timer(struct snd_sh_dac *chip) -{ - hrtimer_start(&chip->hrtimer, chip->wakeups_per_second, - HRTIMER_MODE_REL); -} - -static void dac_audio_stop_timer(struct snd_sh_dac *chip) -{ - hrtimer_cancel(&chip->hrtimer); -} - -static void dac_audio_reset(struct snd_sh_dac *chip) -{ - dac_audio_stop_timer(chip); - chip->buffer_begin = chip->buffer_end = chip->data_buffer; - chip->processed = 0; - chip->empty = 1; -} - -static void dac_audio_set_rate(struct snd_sh_dac *chip) -{ - chip->wakeups_per_second = ktime_set(0, 1000000000 / chip->rate); -} - - -/* PCM INTERFACE */ - -static struct snd_pcm_hardware snd_sh_dac_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_HALF_DUPLEX), - .formats = SNDRV_PCM_FMTBIT_U8, - .rates = SNDRV_PCM_RATE_8000, - .rate_min = 8000, - .rate_max = 8000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = (48*1024), - .period_bytes_min = 1, - .period_bytes_max = (48*1024), - .periods_min = 1, - .periods_max = 1024, -}; - -static int snd_sh_dac_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw = snd_sh_dac_pcm_hw; - - chip->substream = substream; - chip->buffer_begin = chip->buffer_end = chip->data_buffer; - chip->processed = 0; - chip->empty = 1; - - chip->pdata->start(chip->pdata); - - return 0; -} - -static int snd_sh_dac_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - - chip->substream = NULL; - - dac_audio_stop_timer(chip); - chip->pdata->stop(chip->pdata); - - return 0; -} - -static int snd_sh_dac_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int snd_sh_dac_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_sh_dac_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = chip->substream->runtime; - - chip->buffer_size = runtime->buffer_size; - memset(chip->data_buffer, 0, chip->pdata->buffer_size); - - return 0; -} - -static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - dac_audio_start_timer(chip); - break; - case SNDRV_PCM_TRIGGER_STOP: - chip->buffer_begin = chip->buffer_end = chip->data_buffer; - chip->processed = 0; - chip->empty = 1; - dac_audio_stop_timer(chip); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) -{ - /* channel is not used (interleaved data) */ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - ssize_t b_count = frames_to_bytes(runtime , count); - ssize_t b_pos = frames_to_bytes(runtime , pos); - - if (count < 0) - return -EINVAL; - - if (!count) - return 0; - - memcpy_toio(chip->data_buffer + b_pos, src, b_count); - chip->buffer_end = chip->data_buffer + b_pos + b_count; - - if (chip->empty) { - chip->empty = 0; - dac_audio_start_timer(chip); - } - - return 0; -} - -static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - /* channel is not used (interleaved data) */ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - ssize_t b_count = frames_to_bytes(runtime , count); - ssize_t b_pos = frames_to_bytes(runtime , pos); - - if (count < 0) - return -EINVAL; - - if (!count) - return 0; - - memset_io(chip->data_buffer + b_pos, 0, b_count); - chip->buffer_end = chip->data_buffer + b_pos + b_count; - - if (chip->empty) { - chip->empty = 0; - dac_audio_start_timer(chip); - } - - return 0; -} - -static -snd_pcm_uframes_t snd_sh_dac_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); - int pointer = chip->buffer_begin - chip->data_buffer; - - return pointer; -} - -/* pcm ops */ -static struct snd_pcm_ops snd_sh_dac_pcm_ops = { - .open = snd_sh_dac_pcm_open, - .close = snd_sh_dac_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sh_dac_pcm_hw_params, - .hw_free = snd_sh_dac_pcm_hw_free, - .prepare = snd_sh_dac_pcm_prepare, - .trigger = snd_sh_dac_pcm_trigger, - .pointer = snd_sh_dac_pcm_pointer, - .copy = snd_sh_dac_pcm_copy, - .silence = snd_sh_dac_pcm_silence, - .mmap = snd_pcm_lib_mmap_iomem, -}; - -static int __devinit snd_sh_dac_pcm(struct snd_sh_dac *chip, int device) -{ - int err; - struct snd_pcm *pcm; - - /* device should be always 0 for us */ - err = snd_pcm_new(chip->card, "SH_DAC PCM", device, 1, 0, &pcm); - if (err < 0) - return err; - - pcm->private_data = chip; - strcpy(pcm->name, "SH_DAC PCM"); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sh_dac_pcm_ops); - - /* buffer size=48K */ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - 48 * 1024, - 48 * 1024); - - return 0; -} -/* END OF PCM INTERFACE */ - - -/* driver .remove -- destructor */ -static int snd_sh_dac_remove(struct platform_device *devptr) -{ - snd_card_free(platform_get_drvdata(devptr)); - platform_set_drvdata(devptr, NULL); - - return 0; -} - -/* free -- it has been defined by create */ -static int snd_sh_dac_free(struct snd_sh_dac *chip) -{ - /* release the data */ - kfree(chip->data_buffer); - kfree(chip); - - return 0; -} - -static int snd_sh_dac_dev_free(struct snd_device *device) -{ - struct snd_sh_dac *chip = device->device_data; - - return snd_sh_dac_free(chip); -} - -static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle) -{ - struct snd_sh_dac *chip = container_of(handle, struct snd_sh_dac, - hrtimer); - struct snd_pcm_runtime *runtime = chip->substream->runtime; - ssize_t b_ps = frames_to_bytes(runtime, runtime->period_size); - - if (!chip->empty) { - sh_dac_output(*chip->buffer_begin, chip->pdata->channel); - chip->buffer_begin++; - - chip->processed++; - if (chip->processed >= b_ps) { - chip->processed -= b_ps; - snd_pcm_period_elapsed(chip->substream); - } - - if (chip->buffer_begin == (chip->data_buffer + - chip->buffer_size - 1)) - chip->buffer_begin = chip->data_buffer; - - if (chip->buffer_begin == chip->buffer_end) - chip->empty = 1; - - } - - if (!chip->empty) - hrtimer_start(&chip->hrtimer, chip->wakeups_per_second, - HRTIMER_MODE_REL); - - return HRTIMER_NORESTART; -} - -/* create -- chip-specific constructor for the cards components */ -static int __devinit snd_sh_dac_create(struct snd_card *card, - struct platform_device *devptr, - struct snd_sh_dac **rchip) -{ - struct snd_sh_dac *chip; - int err; - - static struct snd_device_ops ops = { - .dev_free = snd_sh_dac_dev_free, - }; - - *rchip = NULL; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - - chip->card = card; - - hrtimer_init(&chip->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - chip->hrtimer.function = sh_dac_audio_timer; - - dac_audio_reset(chip); - chip->rate = 8000; - dac_audio_set_rate(chip); - - chip->pdata = devptr->dev.platform_data; - - chip->data_buffer = kmalloc(chip->pdata->buffer_size, GFP_KERNEL); - if (chip->data_buffer == NULL) { - kfree(chip); - return -ENOMEM; - } - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_sh_dac_free(chip); - return err; - } - - *rchip = chip; - - return 0; -} - -/* driver .probe -- constructor */ -static int __devinit snd_sh_dac_probe(struct platform_device *devptr) -{ - struct snd_sh_dac *chip; - struct snd_card *card; - int err; - - err = snd_card_create(index, id, THIS_MODULE, 0, &card); - if (err < 0) { - snd_printk(KERN_ERR "cannot allocate the card\n"); - return err; - } - - err = snd_sh_dac_create(card, devptr, &chip); - if (err < 0) - goto probe_error; - - err = snd_sh_dac_pcm(chip, 0); - if (err < 0) - goto probe_error; - - strcpy(card->driver, "snd_sh_dac"); - strcpy(card->shortname, "SuperH DAC audio driver"); - printk(KERN_INFO "%s %s", card->longname, card->shortname); - - err = snd_card_register(card); - if (err < 0) - goto probe_error; - - snd_printk("ALSA driver for SuperH DAC audio"); - - platform_set_drvdata(devptr, card); - return 0; - -probe_error: - snd_card_free(card); - return err; -} - -/* - * "driver" definition - */ -static struct platform_driver driver = { - .probe = snd_sh_dac_probe, - .remove = snd_sh_dac_remove, - .driver = { - .name = "dac_audio", - }, -}; - -module_platform_driver(driver); diff --git a/ANDROID_3.4.5/sound/soc/Kconfig b/ANDROID_3.4.5/sound/soc/Kconfig deleted file mode 100644 index 5727227d..00000000 --- a/ANDROID_3.4.5/sound/soc/Kconfig +++ /dev/null @@ -1,57 +0,0 @@ -# -# SoC audio configuration -# - -menuconfig SND_SOC - tristate "ALSA for SoC audio support" - select SND_PCM - select AC97_BUS if SND_SOC_AC97_BUS - select SND_JACK if INPUT=y || INPUT=SND - select REGMAP_I2C if I2C - select REGMAP_SPI if SPI_MASTER - ---help--- - - If you want ASoC support, you should say Y here and also to the - specific driver for your SoC platform below. - - ASoC provides power efficient ALSA support for embedded battery powered - SoC based systems like PDA's, Phones and Personal Media Players. - - This ASoC audio support can also be built as a module. If so, the module - will be called snd-soc-core. - -if SND_SOC - -config SND_SOC_AC97_BUS - bool - -config SND_SOC_DMAENGINE_PCM - bool - -# All the supported SoCs -source "sound/soc/atmel/Kconfig" -source "sound/soc/au1x/Kconfig" -source "sound/soc/blackfin/Kconfig" -source "sound/soc/davinci/Kconfig" -source "sound/soc/ep93xx/Kconfig" -source "sound/soc/fsl/Kconfig" -source "sound/soc/imx/Kconfig" -source "sound/soc/jz4740/Kconfig" -source "sound/soc/nuc900/Kconfig" -source "sound/soc/omap/Kconfig" -source "sound/soc/kirkwood/Kconfig" -source "sound/soc/mid-x86/Kconfig" -source "sound/soc/mxs/Kconfig" -source "sound/soc/pxa/Kconfig" -source "sound/soc/samsung/Kconfig" -source "sound/soc/s6000/Kconfig" -source "sound/soc/sh/Kconfig" -source "sound/soc/tegra/Kconfig" -source "sound/soc/txx9/Kconfig" -source "sound/soc/wmt/Kconfig" - -# Supported codecs -source "sound/soc/codecs/Kconfig" - -endif # SND_SOC - diff --git a/ANDROID_3.4.5/sound/soc/Makefile b/ANDROID_3.4.5/sound/soc/Makefile deleted file mode 100644 index 4dca9714..00000000 --- a/ANDROID_3.4.5/sound/soc/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o -snd-soc-core-objs += soc-pcm.o soc-io.o - -snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o -obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o - -obj-$(CONFIG_SND_SOC) += snd-soc-core.o -obj-$(CONFIG_SND_SOC) += wmt/ -obj-$(CONFIG_SND_SOC) += codecs/ -obj-$(CONFIG_SND_SOC) += atmel/ -obj-$(CONFIG_SND_SOC) += au1x/ -obj-$(CONFIG_SND_SOC) += blackfin/ -obj-$(CONFIG_SND_SOC) += davinci/ -obj-$(CONFIG_SND_SOC) += ep93xx/ -obj-$(CONFIG_SND_SOC) += fsl/ -obj-$(CONFIG_SND_SOC) += imx/ -obj-$(CONFIG_SND_SOC) += jz4740/ -obj-$(CONFIG_SND_SOC) += mid-x86/ -obj-$(CONFIG_SND_SOC) += mxs/ -obj-$(CONFIG_SND_SOC) += nuc900/ -obj-$(CONFIG_SND_SOC) += omap/ -obj-$(CONFIG_SND_SOC) += kirkwood/ -obj-$(CONFIG_SND_SOC) += pxa/ -obj-$(CONFIG_SND_SOC) += samsung/ -obj-$(CONFIG_SND_SOC) += s6000/ -obj-$(CONFIG_SND_SOC) += sh/ -obj-$(CONFIG_SND_SOC) += tegra/ -obj-$(CONFIG_SND_SOC) += txx9/ diff --git a/ANDROID_3.4.5/sound/soc/atmel/Kconfig b/ANDROID_3.4.5/sound/soc/atmel/Kconfig deleted file mode 100644 index 72b09cfd..00000000 --- a/ANDROID_3.4.5/sound/soc/atmel/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -config SND_ATMEL_SOC - tristate "SoC Audio for the Atmel System-on-Chip" - depends on ARCH_AT91 - help - Say Y or M if you want to add support for codecs attached to - the ATMEL SSC interface. You will also need - to select the audio interfaces to support below. - -config SND_ATMEL_SOC_SSC - tristate - depends on SND_ATMEL_SOC - help - Say Y or M if you want to add support for codecs the - ATMEL SSC interface. You will also needs to select the individual - machine drivers to support below. - -config SND_AT91_SOC_SAM9G20_WM8731 - tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" - depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \ - AT91_PROGRAMMABLE_CLOCKS - select SND_ATMEL_SOC_SSC - select SND_SOC_WM8731 - help - Say Y if you want to add support for SoC audio on WM8731-based - AT91sam9g20 evaluation board. - -config SND_AT91_SOC_AFEB9260 - tristate "SoC Audio support for AFEB9260 board" - depends on ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC - select SND_ATMEL_SOC_SSC - select SND_SOC_TLV320AIC23 - help - Say Y here to support sound on AFEB9260 board. diff --git a/ANDROID_3.4.5/sound/soc/atmel/Makefile b/ANDROID_3.4.5/sound/soc/atmel/Makefile deleted file mode 100644 index a5c0bf19..00000000 --- a/ANDROID_3.4.5/sound/soc/atmel/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# AT91 Platform Support -snd-soc-atmel-pcm-objs := atmel-pcm.o -snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o - -obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o -obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o - -# AT91 Machine Support -snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o - -obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o -obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o diff --git a/ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.c b/ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.c deleted file mode 100644 index 9b84f985..00000000 --- a/ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * atmel-pcm.c -- ALSA PCM interface for the Atmel atmel SoC. - * - * Copyright (C) 2005 SAN People - * Copyright (C) 2008 Atmel - * - * Authors: Sedji Gaouaou - * - * Based on at91-pcm. by: - * Frank Mandarino - * Copyright 2006 Endrelia Technologies Inc. - * - * Based on pxa2xx-pcm.c by: - * - * Author: Nicolas Pitre - * Created: Nov 30, 2004 - * Copyright: (C) 2004 MontaVista Software, Inc. - * - * 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 -#include -#include - -#include "atmel-pcm.h" - - -/*--------------------------------------------------------------------------*\ - * Hardware definition -\*--------------------------------------------------------------------------*/ -/* TODO: These values were taken from the AT91 platform driver, check - * them against real values for AT32 - */ -static const struct snd_pcm_hardware atmel_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .period_bytes_min = 32, - .period_bytes_max = 8192, - .periods_min = 2, - .periods_max = 1024, - .buffer_bytes_max = 32 * 1024, -}; - - -/*--------------------------------------------------------------------------*\ - * Data types -\*--------------------------------------------------------------------------*/ -struct atmel_runtime_data { - struct atmel_pcm_dma_params *params; - dma_addr_t dma_buffer; /* physical address of dma buffer */ - dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */ - size_t period_size; - - dma_addr_t period_ptr; /* physical address of next period */ - - /* PDC register save */ - u32 pdc_xpr_save; - u32 pdc_xcr_save; - u32 pdc_xnpr_save; - u32 pdc_xncr_save; -}; - - -/*--------------------------------------------------------------------------*\ - * Helper functions -\*--------------------------------------------------------------------------*/ -static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = atmel_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - pr_debug("atmel-pcm:" - "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", - (void *) buf->area, - (void *) buf->addr, - size); - - if (!buf->area) - return -ENOMEM; - - buf->bytes = size; - return 0; -} -/*--------------------------------------------------------------------------*\ - * ISR -\*--------------------------------------------------------------------------*/ -static void atmel_pcm_dma_irq(u32 ssc_sr, - struct snd_pcm_substream *substream) -{ - struct atmel_runtime_data *prtd = substream->runtime->private_data; - struct atmel_pcm_dma_params *params = prtd->params; - static int count; - - count++; - - if (ssc_sr & params->mask->ssc_endbuf) { - pr_warning("atmel-pcm: buffer %s on %s" - " (SSC_SR=%#x, count=%d)\n", - substream->stream == SNDRV_PCM_STREAM_PLAYBACK - ? "underrun" : "overrun", - params->name, ssc_sr, count); - - /* re-start the PDC */ - ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, - params->mask->pdc_disable); - prtd->period_ptr += prtd->period_size; - if (prtd->period_ptr >= prtd->dma_buffer_end) - prtd->period_ptr = prtd->dma_buffer; - - ssc_writex(params->ssc->regs, params->pdc->xpr, - prtd->period_ptr); - ssc_writex(params->ssc->regs, params->pdc->xcr, - prtd->period_size / params->pdc_xfer_size); - ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, - params->mask->pdc_enable); - } - - if (ssc_sr & params->mask->ssc_endx) { - /* Load the PDC next pointer and counter registers */ - prtd->period_ptr += prtd->period_size; - if (prtd->period_ptr >= prtd->dma_buffer_end) - prtd->period_ptr = prtd->dma_buffer; - - ssc_writex(params->ssc->regs, params->pdc->xnpr, - prtd->period_ptr); - ssc_writex(params->ssc->regs, params->pdc->xncr, - prtd->period_size / params->pdc_xfer_size); - } - - snd_pcm_period_elapsed(substream); -} - - -/*--------------------------------------------------------------------------*\ - * PCM operations -\*--------------------------------------------------------------------------*/ -static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct atmel_runtime_data *prtd = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - - /* this may get called several times by oss emulation - * with different params */ - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - - prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - prtd->params->dma_intr_handler = atmel_pcm_dma_irq; - - prtd->dma_buffer = runtime->dma_addr; - prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; - prtd->period_size = params_period_bytes(params); - - pr_debug("atmel-pcm: " - "hw_params: DMA for %s initialized " - "(dma_bytes=%u, period_size=%u)\n", - prtd->params->name, - runtime->dma_bytes, - prtd->period_size); - return 0; -} - -static int atmel_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct atmel_runtime_data *prtd = substream->runtime->private_data; - struct atmel_pcm_dma_params *params = prtd->params; - - if (params != NULL) { - ssc_writex(params->ssc->regs, SSC_PDC_PTCR, - params->mask->pdc_disable); - prtd->params->dma_intr_handler = NULL; - } - - return 0; -} - -static int atmel_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct atmel_runtime_data *prtd = substream->runtime->private_data; - struct atmel_pcm_dma_params *params = prtd->params; - - ssc_writex(params->ssc->regs, SSC_IDR, - params->mask->ssc_endx | params->mask->ssc_endbuf); - ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, - params->mask->pdc_disable); - return 0; -} - -static int atmel_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_pcm_runtime *rtd = substream->runtime; - struct atmel_runtime_data *prtd = rtd->private_data; - struct atmel_pcm_dma_params *params = prtd->params; - int ret = 0; - - pr_debug("atmel-pcm:buffer_size = %ld," - "dma_area = %p, dma_bytes = %u\n", - rtd->buffer_size, rtd->dma_area, rtd->dma_bytes); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - prtd->period_ptr = prtd->dma_buffer; - - ssc_writex(params->ssc->regs, params->pdc->xpr, - prtd->period_ptr); - ssc_writex(params->ssc->regs, params->pdc->xcr, - prtd->period_size / params->pdc_xfer_size); - - prtd->period_ptr += prtd->period_size; - ssc_writex(params->ssc->regs, params->pdc->xnpr, - prtd->period_ptr); - ssc_writex(params->ssc->regs, params->pdc->xncr, - prtd->period_size / params->pdc_xfer_size); - - pr_debug("atmel-pcm: trigger: " - "period_ptr=%lx, xpr=%u, " - "xcr=%u, xnpr=%u, xncr=%u\n", - (unsigned long)prtd->period_ptr, - ssc_readx(params->ssc->regs, params->pdc->xpr), - ssc_readx(params->ssc->regs, params->pdc->xcr), - ssc_readx(params->ssc->regs, params->pdc->xnpr), - ssc_readx(params->ssc->regs, params->pdc->xncr)); - - ssc_writex(params->ssc->regs, SSC_IER, - params->mask->ssc_endx | params->mask->ssc_endbuf); - ssc_writex(params->ssc->regs, SSC_PDC_PTCR, - params->mask->pdc_enable); - - pr_debug("sr=%u imr=%u\n", - ssc_readx(params->ssc->regs, SSC_SR), - ssc_readx(params->ssc->regs, SSC_IER)); - break; /* SNDRV_PCM_TRIGGER_START */ - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, - params->mask->pdc_disable); - break; - - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, - params->mask->pdc_enable); - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static snd_pcm_uframes_t atmel_pcm_pointer( - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct atmel_runtime_data *prtd = runtime->private_data; - struct atmel_pcm_dma_params *params = prtd->params; - dma_addr_t ptr; - snd_pcm_uframes_t x; - - ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr); - x = bytes_to_frames(runtime, ptr - prtd->dma_buffer); - - if (x == runtime->buffer_size) - x = 0; - - return x; -} - -static int atmel_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct atmel_runtime_data *prtd; - int ret = 0; - - snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware); - - /* ensure that buffer size is a multiple of period size */ - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL); - if (prtd == NULL) { - ret = -ENOMEM; - goto out; - } - runtime->private_data = prtd; - - out: - return ret; -} - -static int atmel_pcm_close(struct snd_pcm_substream *substream) -{ - struct atmel_runtime_data *prtd = substream->runtime->private_data; - - kfree(prtd); - return 0; -} - -static int atmel_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - return remap_pfn_range(vma, vma->vm_start, - substream->dma_buffer.addr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot); -} - -static struct snd_pcm_ops atmel_pcm_ops = { - .open = atmel_pcm_open, - .close = atmel_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = atmel_pcm_hw_params, - .hw_free = atmel_pcm_hw_free, - .prepare = atmel_pcm_prepare, - .trigger = atmel_pcm_trigger, - .pointer = atmel_pcm_pointer, - .mmap = atmel_pcm_mmap, -}; - - -/*--------------------------------------------------------------------------*\ - * ASoC platform driver -\*--------------------------------------------------------------------------*/ -static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32); - -static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &atmel_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = atmel_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - pr_debug("atmel-pcm:" - "Allocating PCM capture DMA buffer\n"); - ret = atmel_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - out: - return ret; -} - -static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - -#ifdef CONFIG_PM -static int atmel_pcm_suspend(struct snd_soc_dai *dai) -{ - struct snd_pcm_runtime *runtime = dai->runtime; - struct atmel_runtime_data *prtd; - struct atmel_pcm_dma_params *params; - - if (!runtime) - return 0; - - prtd = runtime->private_data; - params = prtd->params; - - /* disable the PDC and save the PDC registers */ - - ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable); - - prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr); - prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr); - prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr); - prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr); - - return 0; -} - -static int atmel_pcm_resume(struct snd_soc_dai *dai) -{ - struct snd_pcm_runtime *runtime = dai->runtime; - struct atmel_runtime_data *prtd; - struct atmel_pcm_dma_params *params; - - if (!runtime) - return 0; - - prtd = runtime->private_data; - params = prtd->params; - - /* restore the PDC registers and enable the PDC */ - ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save); - ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save); - ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save); - ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save); - - ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable); - return 0; -} -#else -#define atmel_pcm_suspend NULL -#define atmel_pcm_resume NULL -#endif - -static struct snd_soc_platform_driver atmel_soc_platform = { - .ops = &atmel_pcm_ops, - .pcm_new = atmel_pcm_new, - .pcm_free = atmel_pcm_free_dma_buffers, - .suspend = atmel_pcm_suspend, - .resume = atmel_pcm_resume, -}; - -static int __devinit atmel_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform); -} - -static int __devexit atmel_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver atmel_pcm_driver = { - .driver = { - .name = "atmel-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = atmel_soc_platform_probe, - .remove = __devexit_p(atmel_soc_platform_remove), -}; - -module_platform_driver(atmel_pcm_driver); - -MODULE_AUTHOR("Sedji Gaouaou "); -MODULE_DESCRIPTION("Atmel PCM module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.h b/ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.h deleted file mode 100644 index 5e0a95e6..00000000 --- a/ANDROID_3.4.5/sound/soc/atmel/atmel-pcm.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC. - * - * Copyright (C) 2005 SAN People - * Copyright (C) 2008 Atmel - * - * Authors: Sedji Gaouaou - * - * Based on at91-pcm. by: - * Frank Mandarino - * Copyright 2006 Endrelia Technologies Inc. - * - * Based on pxa2xx-pcm.c by: - * - * Author: Nicolas Pitre - * Created: Nov 30, 2004 - * Copyright: (C) 2004 MontaVista Software, Inc. - * - * 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 - */ - -#ifndef _ATMEL_PCM_H -#define _ATMEL_PCM_H - -#include - -/* - * Registers and status bits that are required by the PCM driver. - */ -struct atmel_pdc_regs { - unsigned int xpr; /* PDC recv/trans pointer */ - unsigned int xcr; /* PDC recv/trans counter */ - unsigned int xnpr; /* PDC next recv/trans pointer */ - unsigned int xncr; /* PDC next recv/trans counter */ - unsigned int ptcr; /* PDC transfer control */ -}; - -struct atmel_ssc_mask { - u32 ssc_enable; /* SSC recv/trans enable */ - u32 ssc_disable; /* SSC recv/trans disable */ - u32 ssc_endx; /* SSC ENDTX or ENDRX */ - u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */ - u32 pdc_enable; /* PDC recv/trans enable */ - u32 pdc_disable; /* PDC recv/trans disable */ -}; - -/* - * This structure, shared between the PCM driver and the interface, - * contains all information required by the PCM driver to perform the - * PDC DMA operation. All fields except dma_intr_handler() are initialized - * by the interface. The dma_intr_handler() pointer is set by the PCM - * driver and called by the interface SSC interrupt handler if it is - * non-NULL. - */ -struct atmel_pcm_dma_params { - char *name; /* stream identifier */ - int pdc_xfer_size; /* PDC counter increment in bytes */ - struct ssc_device *ssc; /* SSC device for stream */ - struct atmel_pdc_regs *pdc; /* PDC receive or transmit registers */ - struct atmel_ssc_mask *mask; /* SSC & PDC status bits */ - struct snd_pcm_substream *substream; - void (*dma_intr_handler)(u32, struct snd_pcm_substream *); -}; - -/* - * SSC register access (since ssc_writel() / ssc_readl() require literal name) - */ -#define ssc_readx(base, reg) (__raw_readl((base) + (reg))) -#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg)) - -#endif /* _ATMEL_PCM_H */ diff --git a/ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.c b/ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.c deleted file mode 100644 index 354341ec..00000000 --- a/ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.c +++ /dev/null @@ -1,867 +0,0 @@ -/* - * atmel_ssc_dai.c -- ALSA SoC ATMEL SSC Audio Layer Platform driver - * - * Copyright (C) 2005 SAN People - * Copyright (C) 2008 Atmel - * - * Author: Sedji Gaouaou - * ATMEL CORP. - * - * Based on at91-ssc.c by - * Frank Mandarino - * Based on pxa2xx Platform drivers by - * Liam Girdwood - * - * 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 -#include -#include -#include -#include - -#include - -#include "atmel-pcm.h" -#include "atmel_ssc_dai.h" - - -#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20) -#define NUM_SSC_DEVICES 1 -#else -#define NUM_SSC_DEVICES 3 -#endif - -/* - * SSC PDC registers required by the PCM DMA engine. - */ -static struct atmel_pdc_regs pdc_tx_reg = { - .xpr = ATMEL_PDC_TPR, - .xcr = ATMEL_PDC_TCR, - .xnpr = ATMEL_PDC_TNPR, - .xncr = ATMEL_PDC_TNCR, -}; - -static struct atmel_pdc_regs pdc_rx_reg = { - .xpr = ATMEL_PDC_RPR, - .xcr = ATMEL_PDC_RCR, - .xnpr = ATMEL_PDC_RNPR, - .xncr = ATMEL_PDC_RNCR, -}; - -/* - * SSC & PDC status bits for transmit and receive. - */ -static struct atmel_ssc_mask ssc_tx_mask = { - .ssc_enable = SSC_BIT(CR_TXEN), - .ssc_disable = SSC_BIT(CR_TXDIS), - .ssc_endx = SSC_BIT(SR_ENDTX), - .ssc_endbuf = SSC_BIT(SR_TXBUFE), - .pdc_enable = ATMEL_PDC_TXTEN, - .pdc_disable = ATMEL_PDC_TXTDIS, -}; - -static struct atmel_ssc_mask ssc_rx_mask = { - .ssc_enable = SSC_BIT(CR_RXEN), - .ssc_disable = SSC_BIT(CR_RXDIS), - .ssc_endx = SSC_BIT(SR_ENDRX), - .ssc_endbuf = SSC_BIT(SR_RXBUFF), - .pdc_enable = ATMEL_PDC_RXTEN, - .pdc_disable = ATMEL_PDC_RXTDIS, -}; - - -/* - * DMA parameters. - */ -static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = { - {{ - .name = "SSC0 PCM out", - .pdc = &pdc_tx_reg, - .mask = &ssc_tx_mask, - }, - { - .name = "SSC0 PCM in", - .pdc = &pdc_rx_reg, - .mask = &ssc_rx_mask, - } }, -#if NUM_SSC_DEVICES == 3 - {{ - .name = "SSC1 PCM out", - .pdc = &pdc_tx_reg, - .mask = &ssc_tx_mask, - }, - { - .name = "SSC1 PCM in", - .pdc = &pdc_rx_reg, - .mask = &ssc_rx_mask, - } }, - {{ - .name = "SSC2 PCM out", - .pdc = &pdc_tx_reg, - .mask = &ssc_tx_mask, - }, - { - .name = "SSC2 PCM in", - .pdc = &pdc_rx_reg, - .mask = &ssc_rx_mask, - } }, -#endif -}; - - -static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = { - { - .name = "ssc0", - .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock), - .dir_mask = SSC_DIR_MASK_UNUSED, - .initialized = 0, - }, -#if NUM_SSC_DEVICES == 3 - { - .name = "ssc1", - .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock), - .dir_mask = SSC_DIR_MASK_UNUSED, - .initialized = 0, - }, - { - .name = "ssc2", - .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock), - .dir_mask = SSC_DIR_MASK_UNUSED, - .initialized = 0, - }, -#endif -}; - - -/* - * SSC interrupt handler. Passes PDC interrupts to the DMA - * interrupt handler in the PCM driver. - */ -static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id) -{ - struct atmel_ssc_info *ssc_p = dev_id; - struct atmel_pcm_dma_params *dma_params; - u32 ssc_sr; - u32 ssc_substream_mask; - int i; - - ssc_sr = (unsigned long)ssc_readl(ssc_p->ssc->regs, SR) - & (unsigned long)ssc_readl(ssc_p->ssc->regs, IMR); - - /* - * Loop through the substreams attached to this SSC. If - * a DMA-related interrupt occurred on that substream, call - * the DMA interrupt handler function, if one has been - * registered in the dma_params structure by the PCM driver. - */ - for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) { - dma_params = ssc_p->dma_params[i]; - - if ((dma_params != NULL) && - (dma_params->dma_intr_handler != NULL)) { - ssc_substream_mask = (dma_params->mask->ssc_endx | - dma_params->mask->ssc_endbuf); - if (ssc_sr & ssc_substream_mask) { - dma_params->dma_intr_handler(ssc_sr, - dma_params-> - substream); - } - } - } - - return IRQ_HANDLED; -} - - -/*-------------------------------------------------------------------------*\ - * DAI functions -\*-------------------------------------------------------------------------*/ -/* - * Startup. Only that one substream allowed in each direction. - */ -static int atmel_ssc_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; - int dir_mask; - - pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", - ssc_readl(ssc_p->ssc->regs, SR)); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dir_mask = SSC_DIR_MASK_PLAYBACK; - else - dir_mask = SSC_DIR_MASK_CAPTURE; - - spin_lock_irq(&ssc_p->lock); - if (ssc_p->dir_mask & dir_mask) { - spin_unlock_irq(&ssc_p->lock); - return -EBUSY; - } - ssc_p->dir_mask |= dir_mask; - spin_unlock_irq(&ssc_p->lock); - - return 0; -} - -/* - * Shutdown. Clear DMA parameters and shutdown the SSC if there - * are no other substreams open. - */ -static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; - struct atmel_pcm_dma_params *dma_params; - int dir, dir_mask; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dir = 0; - else - dir = 1; - - dma_params = ssc_p->dma_params[dir]; - - if (dma_params != NULL) { - ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); - pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n", - (dir ? "receive" : "transmit"), - ssc_readl(ssc_p->ssc->regs, SR)); - - dma_params->ssc = NULL; - dma_params->substream = NULL; - ssc_p->dma_params[dir] = NULL; - } - - dir_mask = 1 << dir; - - spin_lock_irq(&ssc_p->lock); - ssc_p->dir_mask &= ~dir_mask; - if (!ssc_p->dir_mask) { - if (ssc_p->initialized) { - /* Shutdown the SSC clock. */ - pr_debug("atmel_ssc_dau: Stopping clock\n"); - clk_disable(ssc_p->ssc->clk); - - free_irq(ssc_p->ssc->irq, ssc_p); - ssc_p->initialized = 0; - } - - /* Reset the SSC */ - ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); - /* Clear the SSC dividers */ - ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; - } - spin_unlock_irq(&ssc_p->lock); -} - - -/* - * Record the DAI format for use in hw_params(). - */ -static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; - - ssc_p->daifmt = fmt; - return 0; -} - -/* - * Record SSC clock dividers for use in hw_params(). - */ -static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; - - switch (div_id) { - case ATMEL_SSC_CMR_DIV: - /* - * The same master clock divider is used for both - * transmit and receive, so if a value has already - * been set, it must match this value. - */ - if (ssc_p->cmr_div == 0) - ssc_p->cmr_div = div; - else - if (div != ssc_p->cmr_div) - return -EBUSY; - break; - - case ATMEL_SSC_TCMR_PERIOD: - ssc_p->tcmr_period = div; - break; - - case ATMEL_SSC_RCMR_PERIOD: - ssc_p->rcmr_period = div; - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * Configure the SSC. - */ -static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); - int id = dai->id; - struct atmel_ssc_info *ssc_p = &ssc_info[id]; - struct atmel_pcm_dma_params *dma_params; - int dir, channels, bits; - u32 tfmr, rfmr, tcmr, rcmr; - int start_event; - int ret; - - /* - * Currently, there is only one set of dma params for - * each direction. If more are added, this code will - * have to be changed to select the proper set. - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dir = 0; - else - dir = 1; - - dma_params = &ssc_dma_params[id][dir]; - dma_params->ssc = ssc_p->ssc; - dma_params->substream = substream; - - ssc_p->dma_params[dir] = dma_params; - - /* - * The snd_soc_pcm_stream->dma_data field is only used to communicate - * the appropriate DMA parameters to the pcm driver hw_params() - * function. It should not be used for other purposes - * as it is common to all substreams. - */ - snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params); - - channels = params_channels(params); - - /* - * Determine sample size in bits and the PDC increment. - */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - bits = 8; - dma_params->pdc_xfer_size = 1; - break; - case SNDRV_PCM_FORMAT_S16_LE: - bits = 16; - dma_params->pdc_xfer_size = 2; - break; - case SNDRV_PCM_FORMAT_S24_LE: - bits = 24; - dma_params->pdc_xfer_size = 4; - break; - case SNDRV_PCM_FORMAT_S32_LE: - bits = 32; - dma_params->pdc_xfer_size = 4; - break; - default: - printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format"); - return -EINVAL; - } - - /* - * The SSC only supports up to 16-bit samples in I2S format, due - * to the size of the Frame Mode Register FSLEN field. - */ - if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S - && bits > 16) { - printk(KERN_WARNING - "atmel_ssc_dai: sample size %d " - "is too large for I2S\n", bits); - return -EINVAL; - } - - /* - * Compute SSC register settings. - */ - switch (ssc_p->daifmt - & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { - - case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: - /* - * I2S format, SSC provides BCLK and LRC clocks. - * - * The SSC transmit and receive clocks are generated - * from the MCK divider, and the BCLK signal - * is output on the SSC TK line. - */ - rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) - | SSC_BF(RCMR_STTDLY, START_DELAY) - | SSC_BF(RCMR_START, SSC_START_FALLING_RF) - | SSC_BF(RCMR_CKI, SSC_CKI_RISING) - | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_DIV); - - rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) - | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) - | SSC_BF(RFMR_FSLEN, (bits - 1)) - | SSC_BF(RFMR_DATNB, (channels - 1)) - | SSC_BIT(RFMR_MSBF) - | SSC_BF(RFMR_LOOP, 0) - | SSC_BF(RFMR_DATLEN, (bits - 1)); - - tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) - | SSC_BF(TCMR_STTDLY, START_DELAY) - | SSC_BF(TCMR_START, SSC_START_FALLING_RF) - | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) - | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) - | SSC_BF(TCMR_CKS, SSC_CKS_DIV); - - tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) - | SSC_BF(TFMR_FSDEN, 0) - | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) - | SSC_BF(TFMR_FSLEN, (bits - 1)) - | SSC_BF(TFMR_DATNB, (channels - 1)) - | SSC_BIT(TFMR_MSBF) - | SSC_BF(TFMR_DATDEF, 0) - | SSC_BF(TFMR_DATLEN, (bits - 1)); - break; - - case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: - /* - * I2S format, CODEC supplies BCLK and LRC clocks. - * - * The SSC transmit clock is obtained from the BCLK signal on - * on the TK line, and the SSC receive clock is - * generated from the transmit clock. - * - * For single channel data, one sample is transferred - * on the falling edge of the LRC clock. - * For two channel data, one sample is - * transferred on both edges of the LRC clock. - */ - start_event = ((channels == 1) - ? SSC_START_FALLING_RF - : SSC_START_EDGE_RF); - - rcmr = SSC_BF(RCMR_PERIOD, 0) - | SSC_BF(RCMR_STTDLY, START_DELAY) - | SSC_BF(RCMR_START, start_event) - | SSC_BF(RCMR_CKI, SSC_CKI_RISING) - | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); - - rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) - | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) - | SSC_BF(RFMR_FSLEN, 0) - | SSC_BF(RFMR_DATNB, 0) - | SSC_BIT(RFMR_MSBF) - | SSC_BF(RFMR_LOOP, 0) - | SSC_BF(RFMR_DATLEN, (bits - 1)); - - tcmr = SSC_BF(TCMR_PERIOD, 0) - | SSC_BF(TCMR_STTDLY, START_DELAY) - | SSC_BF(TCMR_START, start_event) - | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) - | SSC_BF(TCMR_CKO, SSC_CKO_NONE) - | SSC_BF(TCMR_CKS, SSC_CKS_PIN); - - tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) - | SSC_BF(TFMR_FSDEN, 0) - | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) - | SSC_BF(TFMR_FSLEN, 0) - | SSC_BF(TFMR_DATNB, 0) - | SSC_BIT(TFMR_MSBF) - | SSC_BF(TFMR_DATDEF, 0) - | SSC_BF(TFMR_DATLEN, (bits - 1)); - break; - - case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: - /* - * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. - * - * The SSC transmit and receive clocks are generated from the - * MCK divider, and the BCLK signal is output - * on the SSC TK line. - */ - rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) - | SSC_BF(RCMR_STTDLY, 1) - | SSC_BF(RCMR_START, SSC_START_RISING_RF) - | SSC_BF(RCMR_CKI, SSC_CKI_RISING) - | SSC_BF(RCMR_CKO, SSC_CKO_NONE) - | SSC_BF(RCMR_CKS, SSC_CKS_DIV); - - rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) - | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) - | SSC_BF(RFMR_FSLEN, 0) - | SSC_BF(RFMR_DATNB, (channels - 1)) - | SSC_BIT(RFMR_MSBF) - | SSC_BF(RFMR_LOOP, 0) - | SSC_BF(RFMR_DATLEN, (bits - 1)); - - tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) - | SSC_BF(TCMR_STTDLY, 1) - | SSC_BF(TCMR_START, SSC_START_RISING_RF) - | SSC_BF(TCMR_CKI, SSC_CKI_RISING) - | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) - | SSC_BF(TCMR_CKS, SSC_CKS_DIV); - - tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) - | SSC_BF(TFMR_FSDEN, 0) - | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) - | SSC_BF(TFMR_FSLEN, 0) - | SSC_BF(TFMR_DATNB, (channels - 1)) - | SSC_BIT(TFMR_MSBF) - | SSC_BF(TFMR_DATDEF, 0) - | SSC_BF(TFMR_DATLEN, (bits - 1)); - break; - - case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: - default: - printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n", - ssc_p->daifmt); - return -EINVAL; - } - pr_debug("atmel_ssc_hw_params: " - "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", - rcmr, rfmr, tcmr, tfmr); - - if (!ssc_p->initialized) { - - /* Enable PMC peripheral clock for this SSC */ - pr_debug("atmel_ssc_dai: Starting clock\n"); - clk_enable(ssc_p->ssc->clk); - - /* Reset the SSC and its PDC registers */ - ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); - - ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); - - ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); - ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); - - ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0, - ssc_p->name, ssc_p); - if (ret < 0) { - printk(KERN_WARNING - "atmel_ssc_dai: request_irq failure\n"); - pr_debug("Atmel_ssc_dai: Stoping clock\n"); - clk_disable(ssc_p->ssc->clk); - return ret; - } - - ssc_p->initialized = 1; - } - - /* set SSC clock mode register */ - ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div); - - /* set receive clock mode and format */ - ssc_writel(ssc_p->ssc->regs, RCMR, rcmr); - ssc_writel(ssc_p->ssc->regs, RFMR, rfmr); - - /* set transmit clock mode and format */ - ssc_writel(ssc_p->ssc->regs, TCMR, tcmr); - ssc_writel(ssc_p->ssc->regs, TFMR, tfmr); - - pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n"); - return 0; -} - - -static int atmel_ssc_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; - struct atmel_pcm_dma_params *dma_params; - int dir; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dir = 0; - else - dir = 1; - - dma_params = ssc_p->dma_params[dir]; - - ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); - - pr_debug("%s enabled SSC_SR=0x%08x\n", - dir ? "receive" : "transmit", - ssc_readl(ssc_p->ssc->regs, SR)); - return 0; -} - - -#ifdef CONFIG_PM -static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai) -{ - struct atmel_ssc_info *ssc_p; - - if (!cpu_dai->active) - return 0; - - ssc_p = &ssc_info[cpu_dai->id]; - - /* Save the status register before disabling transmit and receive */ - ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR); - ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS)); - - /* Save the current interrupt mask, then disable unmasked interrupts */ - ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR); - ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr); - - ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR); - ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR); - ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR); - ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR); - ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR); - - return 0; -} - - - -static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai) -{ - struct atmel_ssc_info *ssc_p; - u32 cr; - - if (!cpu_dai->active) - return 0; - - ssc_p = &ssc_info[cpu_dai->id]; - - /* restore SSC register settings */ - ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr); - ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr); - ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr); - ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr); - ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr); - - /* re-enable interrupts */ - ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr); - - /* Re-enable receive and transmit as appropriate */ - cr = 0; - cr |= - (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0; - cr |= - (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0; - ssc_writel(ssc_p->ssc->regs, CR, cr); - - return 0; -} -#else /* CONFIG_PM */ -# define atmel_ssc_suspend NULL -# define atmel_ssc_resume NULL -#endif /* CONFIG_PM */ - -static int atmel_ssc_probe(struct snd_soc_dai *dai) -{ - struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; - int ret = 0; - - snd_soc_dai_set_drvdata(dai, ssc_p); - - /* - * Request SSC device - */ - ssc_p->ssc = ssc_request(dai->id); - if (IS_ERR(ssc_p->ssc)) { - printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id); - ret = PTR_ERR(ssc_p->ssc); - } - - return ret; -} - -static int atmel_ssc_remove(struct snd_soc_dai *dai) -{ - struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai); - - ssc_free(ssc_p->ssc); - return 0; -} - -#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000) - -#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops atmel_ssc_dai_ops = { - .startup = atmel_ssc_startup, - .shutdown = atmel_ssc_shutdown, - .prepare = atmel_ssc_prepare, - .hw_params = atmel_ssc_hw_params, - .set_fmt = atmel_ssc_set_dai_fmt, - .set_clkdiv = atmel_ssc_set_dai_clkdiv, -}; - -static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = { - { - .name = "atmel-ssc-dai.0", - .probe = atmel_ssc_probe, - .remove = atmel_ssc_remove, - .suspend = atmel_ssc_suspend, - .resume = atmel_ssc_resume, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = ATMEL_SSC_RATES, - .formats = ATMEL_SSC_FORMATS,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = ATMEL_SSC_RATES, - .formats = ATMEL_SSC_FORMATS,}, - .ops = &atmel_ssc_dai_ops, - }, -#if NUM_SSC_DEVICES == 3 - { - .name = "atmel-ssc-dai.1", - .probe = atmel_ssc_probe, - .remove = atmel_ssc_remove, - .suspend = atmel_ssc_suspend, - .resume = atmel_ssc_resume, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = ATMEL_SSC_RATES, - .formats = ATMEL_SSC_FORMATS,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = ATMEL_SSC_RATES, - .formats = ATMEL_SSC_FORMATS,}, - .ops = &atmel_ssc_dai_ops, - }, - { - .name = "atmel-ssc-dai.2", - .probe = atmel_ssc_probe, - .remove = atmel_ssc_remove, - .suspend = atmel_ssc_suspend, - .resume = atmel_ssc_resume, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = ATMEL_SSC_RATES, - .formats = ATMEL_SSC_FORMATS,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = ATMEL_SSC_RATES, - .formats = ATMEL_SSC_FORMATS,}, - .ops = &atmel_ssc_dai_ops, - }, -#endif -}; - -static __devinit int asoc_ssc_probe(struct platform_device *pdev) -{ - BUG_ON(pdev->id < 0); - BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai)); - return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]); -} - -static int __devexit asoc_ssc_remove(struct platform_device *pdev) -{ - snd_soc_unregister_dai(&pdev->dev); - return 0; -} - -static struct platform_driver asoc_ssc_driver = { - .driver = { - .name = "atmel-ssc-dai", - .owner = THIS_MODULE, - }, - - .probe = asoc_ssc_probe, - .remove = __devexit_p(asoc_ssc_remove), -}; - -/** - * atmel_ssc_set_audio - Allocate the specified SSC for audio use. - */ -int atmel_ssc_set_audio(int ssc_id) -{ - struct ssc_device *ssc; - static struct platform_device *dma_pdev; - struct platform_device *ssc_pdev; - int ret; - - if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai)) - return -EINVAL; - - /* Allocate a dummy device for DMA if we don't have one already */ - if (!dma_pdev) { - dma_pdev = platform_device_alloc("atmel-pcm-audio", -1); - if (!dma_pdev) - return -ENOMEM; - - ret = platform_device_add(dma_pdev); - if (ret < 0) { - platform_device_put(dma_pdev); - dma_pdev = NULL; - return ret; - } - } - - ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id); - if (!ssc_pdev) - return -ENOMEM; - - /* If we can grab the SSC briefly to parent the DAI device off it */ - ssc = ssc_request(ssc_id); - if (IS_ERR(ssc)) - pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n", - PTR_ERR(ssc)); - else { - ssc_pdev->dev.parent = &(ssc->pdev->dev); - ssc_free(ssc); - } - - ret = platform_device_add(ssc_pdev); - if (ret < 0) - platform_device_put(ssc_pdev); - - return ret; -} -EXPORT_SYMBOL_GPL(atmel_ssc_set_audio); - -module_platform_driver(asoc_ssc_driver); - -/* Module information */ -MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); -MODULE_DESCRIPTION("ATMEL SSC ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.h b/ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.h deleted file mode 100644 index 5d4f0f9b..00000000 --- a/ANDROID_3.4.5/sound/soc/atmel/atmel_ssc_dai.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * atmel_ssc_dai.h - ALSA SSC interface for the Atmel SoC - * - * Copyright (C) 2005 SAN People - * Copyright (C) 2008 Atmel - * - * Author: Sedji Gaouaou - * ATMEL CORP. - * - * Based on at91-ssc.c by - * Frank Mandarino - * Based on pxa2xx Platform drivers by - * Liam Girdwood - * - * 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 - */ - -#ifndef _ATMEL_SSC_DAI_H -#define _ATMEL_SSC_DAI_H - -#include -#include - -#include "atmel-pcm.h" - -/* SSC system clock ids */ -#define ATMEL_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */ - -/* SSC divider ids */ -#define ATMEL_SSC_CMR_DIV 0 /* MCK divider for BCLK */ -#define ATMEL_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */ -#define ATMEL_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */ -/* - * SSC direction masks - */ -#define SSC_DIR_MASK_UNUSED 0 -#define SSC_DIR_MASK_PLAYBACK 1 -#define SSC_DIR_MASK_CAPTURE 2 - -/* - * SSC register values that Atmel left out of . These - * are expected to be used with SSC_BF - */ -/* START bit field values */ -#define SSC_START_CONTINUOUS 0 -#define SSC_START_TX_RX 1 -#define SSC_START_LOW_RF 2 -#define SSC_START_HIGH_RF 3 -#define SSC_START_FALLING_RF 4 -#define SSC_START_RISING_RF 5 -#define SSC_START_LEVEL_RF 6 -#define SSC_START_EDGE_RF 7 -#define SSS_START_COMPARE_0 8 - -/* CKI bit field values */ -#define SSC_CKI_FALLING 0 -#define SSC_CKI_RISING 1 - -/* CKO bit field values */ -#define SSC_CKO_NONE 0 -#define SSC_CKO_CONTINUOUS 1 -#define SSC_CKO_TRANSFER 2 - -/* CKS bit field values */ -#define SSC_CKS_DIV 0 -#define SSC_CKS_CLOCK 1 -#define SSC_CKS_PIN 2 - -/* FSEDGE bit field values */ -#define SSC_FSEDGE_POSITIVE 0 -#define SSC_FSEDGE_NEGATIVE 1 - -/* FSOS bit field values */ -#define SSC_FSOS_NONE 0 -#define SSC_FSOS_NEGATIVE 1 -#define SSC_FSOS_POSITIVE 2 -#define SSC_FSOS_LOW 3 -#define SSC_FSOS_HIGH 4 -#define SSC_FSOS_TOGGLE 5 - -#define START_DELAY 1 - -struct atmel_ssc_state { - u32 ssc_cmr; - u32 ssc_rcmr; - u32 ssc_rfmr; - u32 ssc_tcmr; - u32 ssc_tfmr; - u32 ssc_sr; - u32 ssc_imr; -}; - - -struct atmel_ssc_info { - char *name; - struct ssc_device *ssc; - spinlock_t lock; /* lock for dir_mask */ - unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */ - unsigned short initialized; /* true if SSC has been initialized */ - unsigned short daifmt; - unsigned short cmr_div; - unsigned short tcmr_period; - unsigned short rcmr_period; - struct atmel_pcm_dma_params *dma_params[2]; - struct atmel_ssc_state ssc_state; -}; - -int atmel_ssc_set_audio(int ssc); - -#endif /* _AT91_SSC_DAI_H */ diff --git a/ANDROID_3.4.5/sound/soc/atmel/sam9g20_wm8731.c b/ANDROID_3.4.5/sound/soc/atmel/sam9g20_wm8731.c deleted file mode 100644 index c8835148..00000000 --- a/ANDROID_3.4.5/sound/soc/atmel/sam9g20_wm8731.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * sam9g20_wm8731 -- SoC audio for AT91SAM9G20-based - * ATMEL AT91SAM9G20ek board. - * - * Copyright (C) 2005 SAN People - * Copyright (C) 2008 Atmel - * - * Authors: Sedji Gaouaou - * - * Based on ati_b1_wm8731.c by: - * Frank Mandarino - * Copyright 2006 Endrelia Technologies Inc. - * Based on corgi.c by: - * Copyright 2005 Wolfson Microelectronics PLC. - * Copyright 2005 Openedhand Ltd. - * - * 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 - -#include -#include -#include -#include - -#include -#include -#include - -#include "../codecs/wm8731.h" -#include "atmel-pcm.h" -#include "atmel_ssc_dai.h" - -#define MCLK_RATE 12000000 - -/* - * As shipped the board does not have inputs. However, it is relatively - * straightforward to modify the board to hook them up so support is left - * in the driver. - */ -#undef ENABLE_MIC_INPUT - -static struct clk *mclk; - -static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops at91sam9g20ek_ops = { - .hw_params = at91sam9g20ek_hw_params, -}; - -static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, - struct snd_soc_dapm_context *dapm, - enum snd_soc_bias_level level) -{ - static int mclk_on; - int ret = 0; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - if (!mclk_on) - ret = clk_enable(mclk); - if (ret == 0) - mclk_on = 1; - break; - - case SND_SOC_BIAS_OFF: - case SND_SOC_BIAS_STANDBY: - if (mclk_on) - clk_disable(mclk); - mclk_on = 0; - break; - } - - return ret; -} - -static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Int Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), -}; - -static const struct snd_soc_dapm_route intercon[] = { - - /* speaker connected to LHPOUT */ - {"Ext Spk", NULL, "LHPOUT"}, - - /* mic is connected to Mic Jack, with WM8731 Mic Bias */ - {"MICIN", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Int Mic"}, -}; - -/* - * Logic for a wm8731 as connected on a at91sam9g20ek board. - */ -static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - printk(KERN_DEBUG - "at91sam9g20ek_wm8731 " - ": at91sam9g20ek_wm8731_init() called\n"); - - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_MCLK, - MCLK_RATE, SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); - return ret; - } - - /* Add specific widgets */ - snd_soc_dapm_new_controls(dapm, at91sam9g20ek_dapm_widgets, - ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); - /* Set up specific audio path interconnects */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - /* not connected */ - snd_soc_dapm_nc_pin(dapm, "RLINEIN"); - snd_soc_dapm_nc_pin(dapm, "LLINEIN"); - -#ifdef ENABLE_MIC_INPUT - snd_soc_dapm_enable_pin(dapm, "Int Mic"); -#else - snd_soc_dapm_nc_pin(dapm, "Int Mic"); -#endif - - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - - return 0; -} - -static struct snd_soc_dai_link at91sam9g20ek_dai = { - .name = "WM8731", - .stream_name = "WM8731 PCM", - .cpu_dai_name = "atmel-ssc-dai.0", - .codec_dai_name = "wm8731-hifi", - .init = at91sam9g20ek_wm8731_init, - .platform_name = "atmel-pcm-audio", - .codec_name = "wm8731.0-001b", - .ops = &at91sam9g20ek_ops, -}; - -static struct snd_soc_card snd_soc_at91sam9g20ek = { - .name = "AT91SAMG20-EK", - .owner = THIS_MODULE, - .dai_link = &at91sam9g20ek_dai, - .num_links = 1, - .set_bias_level = at91sam9g20ek_set_bias_level, -}; - -static struct platform_device *at91sam9g20ek_snd_device; - -static int __init at91sam9g20ek_init(void) -{ - struct clk *pllb; - int ret; - - if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc())) - return -ENODEV; - - ret = atmel_ssc_set_audio(0); - if (ret != 0) { - pr_err("Failed to set SSC 0 for audio: %d\n", ret); - return ret; - } - - /* - * Codec MCLK is supplied by PCK0 - set it up. - */ - mclk = clk_get(NULL, "pck0"); - if (IS_ERR(mclk)) { - printk(KERN_ERR "ASoC: Failed to get MCLK\n"); - ret = PTR_ERR(mclk); - goto err; - } - - pllb = clk_get(NULL, "pllb"); - if (IS_ERR(pllb)) { - printk(KERN_ERR "ASoC: Failed to get PLLB\n"); - ret = PTR_ERR(pllb); - goto err_mclk; - } - ret = clk_set_parent(mclk, pllb); - clk_put(pllb); - if (ret != 0) { - printk(KERN_ERR "ASoC: Failed to set MCLK parent\n"); - goto err_mclk; - } - - clk_set_rate(mclk, MCLK_RATE); - - at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); - if (!at91sam9g20ek_snd_device) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - ret = -ENOMEM; - goto err_mclk; - } - - platform_set_drvdata(at91sam9g20ek_snd_device, - &snd_soc_at91sam9g20ek); - - ret = platform_device_add(at91sam9g20ek_snd_device); - if (ret) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - goto err_device_add; - } - - return ret; - -err_device_add: - platform_device_put(at91sam9g20ek_snd_device); -err_mclk: - clk_put(mclk); - mclk = NULL; -err: - return ret; -} - -static void __exit at91sam9g20ek_exit(void) -{ - platform_device_unregister(at91sam9g20ek_snd_device); - at91sam9g20ek_snd_device = NULL; - clk_put(mclk); - mclk = NULL; -} - -module_init(at91sam9g20ek_init); -module_exit(at91sam9g20ek_exit); - -/* Module information */ -MODULE_AUTHOR("Sedji Gaouaou "); -MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/atmel/snd-soc-afeb9260.c b/ANDROID_3.4.5/sound/soc/atmel/snd-soc-afeb9260.c deleted file mode 100644 index f65f08be..00000000 --- a/ANDROID_3.4.5/sound/soc/atmel/snd-soc-afeb9260.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * afeb9260.c -- SoC audio for AFEB9260 - * - * Copyright (C) 2009 Sergey Lapin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../codecs/tlv320aic23.h" -#include "atmel-pcm.h" -#include "atmel_ssc_dai.h" - -#define CODEC_CLOCK 12000000 - -static int afeb9260_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int err; - - /* Set the codec system clock for DAC and ADC */ - err = - snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN); - - if (err < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return err; - } - - return err; -} - -static struct snd_soc_ops afeb9260_ops = { - .hw_params = afeb9260_hw_params, -}; - -static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), -}; - -static const struct snd_soc_dapm_route afeb9260_audio_map[] = { - {"Headphone Jack", NULL, "LHPOUT"}, - {"Headphone Jack", NULL, "RHPOUT"}, - - {"LLINEIN", NULL, "Line In"}, - {"RLINEIN", NULL, "Line In"}, - - {"MICIN", NULL, "Mic Jack"}, -}; - -static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Line In"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - - return 0; -} - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link afeb9260_dai = { - .name = "TLV320AIC23", - .stream_name = "AIC23", - .cpu_dai_name = "atmel-ssc-dai.0", - .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "atmel_pcm-audio", - .codec_name = "tlv320aic23-codec.0-001a", - .init = afeb9260_tlv320aic23_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &afeb9260_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_machine_afeb9260 = { - .name = "AFEB9260", - .owner = THIS_MODULE, - .dai_link = &afeb9260_dai, - .num_links = 1, - - .dapm_widgets = tlv320aic23_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), - .dapm_routes = afeb9260_audio_map, - .num_dapm_routes = ARRAY_SIZE(afeb9260_audio_map), -}; - -static struct platform_device *afeb9260_snd_device; - -static int __init afeb9260_soc_init(void) -{ - int err; - struct device *dev; - - if (!(machine_is_afeb9260())) - return -ENODEV; - - - afeb9260_snd_device = platform_device_alloc("soc-audio", -1); - if (!afeb9260_snd_device) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260); - err = platform_device_add(afeb9260_snd_device); - if (err) - goto err1; - - dev = &afeb9260_snd_device->dev; - - return 0; -err1: - platform_device_put(afeb9260_snd_device); - return err; -} - -static void __exit afeb9260_soc_exit(void) -{ - platform_device_unregister(afeb9260_snd_device); -} - -module_init(afeb9260_soc_init); -module_exit(afeb9260_soc_exit); - -MODULE_AUTHOR("Sergey Lapin "); -MODULE_DESCRIPTION("ALSA SoC for AFEB9260"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/au1x/Kconfig b/ANDROID_3.4.5/sound/soc/au1x/Kconfig deleted file mode 100644 index a5610404..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/Kconfig +++ /dev/null @@ -1,64 +0,0 @@ -## -## Au1200/Au1550/Au1300 PSC + DBDMA -## -config SND_SOC_AU1XPSC - tristate "SoC Audio for Au12xx/Au13xx/Au1550" - depends on MIPS_ALCHEMY - help - This option enables support for the Programmable Serial - Controllers in AC97 and I2S mode, and the Descriptor-Based DMA - Controller (DBDMA) as found on the Au12xx/Au13xx/Au1550 SoC. - -config SND_SOC_AU1XPSC_I2S - tristate - -config SND_SOC_AU1XPSC_AC97 - tristate - select AC97_BUS - select SND_AC97_CODEC - select SND_SOC_AC97_BUS - -## -## Au1000/1500/1100 DMA + AC97C/I2SC -## -config SND_SOC_AU1XAUDIO - tristate "SoC Audio for Au1000/Au1500/Au1100" - depends on MIPS_ALCHEMY - help - This is a driver set for the AC97 unit and the - old DMA controller as found on the Au1000/Au1500/Au1100 chips. - -config SND_SOC_AU1XAC97C - tristate - select AC97_BUS - select SND_AC97_CODEC - select SND_SOC_AC97_BUS - -config SND_SOC_AU1XI2SC - tristate - - -## -## Boards -## -config SND_SOC_DB1000 - tristate "DB1000 Audio support" - depends on SND_SOC_AU1XAUDIO - select SND_SOC_AU1XAC97C - select SND_SOC_AC97_CODEC - help - Select this option to enable AC97 audio on the early DB1x00 series - of boards (DB1000/DB1500/DB1100). - -config SND_SOC_DB1200 - tristate "DB1200/DB1300/DB1550 Audio support" - depends on SND_SOC_AU1XPSC - select SND_SOC_AU1XPSC_AC97 - select SND_SOC_AC97_CODEC - select SND_SOC_WM9712 - select SND_SOC_AU1XPSC_I2S - select SND_SOC_WM8731 - help - Select this option to enable audio (AC97 and I2S) on the - Alchemy/AMD/RMI/NetLogic Db1200, Db1550 and Db1300 evaluation boards. - If you need Db1300 touchscreen support, you definitely want to say Y. diff --git a/ANDROID_3.4.5/sound/soc/au1x/Makefile b/ANDROID_3.4.5/sound/soc/au1x/Makefile deleted file mode 100644 index 92071051..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# Au1200/Au1550 PSC audio -snd-soc-au1xpsc-dbdma-objs := dbdma2.o -snd-soc-au1xpsc-i2s-objs := psc-i2s.o -snd-soc-au1xpsc-ac97-objs := psc-ac97.o - -# Au1000/1500/1100 Audio units -snd-soc-au1x-dma-objs := dma.o -snd-soc-au1x-ac97c-objs := ac97c.o -snd-soc-au1x-i2sc-objs := i2sc.o - -obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o -obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o -obj-$(CONFIG_SND_SOC_AU1XPSC_AC97) += snd-soc-au1xpsc-ac97.o -obj-$(CONFIG_SND_SOC_AU1XAUDIO) += snd-soc-au1x-dma.o -obj-$(CONFIG_SND_SOC_AU1XAC97C) += snd-soc-au1x-ac97c.o -obj-$(CONFIG_SND_SOC_AU1XI2SC) += snd-soc-au1x-i2sc.o - -# Boards -snd-soc-db1000-objs := db1000.o -snd-soc-db1200-objs := db1200.o - -obj-$(CONFIG_SND_SOC_DB1000) += snd-soc-db1000.o -obj-$(CONFIG_SND_SOC_DB1200) += snd-soc-db1200.o diff --git a/ANDROID_3.4.5/sound/soc/au1x/ac97c.c b/ANDROID_3.4.5/sound/soc/au1x/ac97c.c deleted file mode 100644 index c5ac2449..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/ac97c.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Au1000/Au1500/Au1100 AC97C controller driver for ASoC - * - * (c) 2011 Manuel Lauss - * - * based on the old ALSA driver originally written by - * Charles Eidsness - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "psc.h" - -/* register offsets and bits */ -#define AC97_CONFIG 0x00 -#define AC97_STATUS 0x04 -#define AC97_DATA 0x08 -#define AC97_CMDRESP 0x0c -#define AC97_ENABLE 0x10 - -#define CFG_RC(x) (((x) & 0x3ff) << 13) /* valid rx slots mask */ -#define CFG_XS(x) (((x) & 0x3ff) << 3) /* valid tx slots mask */ -#define CFG_SG (1 << 2) /* sync gate */ -#define CFG_SN (1 << 1) /* sync control */ -#define CFG_RS (1 << 0) /* acrst# control */ -#define STAT_XU (1 << 11) /* tx underflow */ -#define STAT_XO (1 << 10) /* tx overflow */ -#define STAT_RU (1 << 9) /* rx underflow */ -#define STAT_RO (1 << 8) /* rx overflow */ -#define STAT_RD (1 << 7) /* codec ready */ -#define STAT_CP (1 << 6) /* command pending */ -#define STAT_TE (1 << 4) /* tx fifo empty */ -#define STAT_TF (1 << 3) /* tx fifo full */ -#define STAT_RE (1 << 1) /* rx fifo empty */ -#define STAT_RF (1 << 0) /* rx fifo full */ -#define CMD_SET_DATA(x) (((x) & 0xffff) << 16) -#define CMD_GET_DATA(x) ((x) & 0xffff) -#define CMD_READ (1 << 7) -#define CMD_WRITE (0 << 7) -#define CMD_IDX(x) ((x) & 0x7f) -#define EN_D (1 << 1) /* DISable bit */ -#define EN_CE (1 << 0) /* clock enable bit */ - -/* how often to retry failed codec register reads/writes */ -#define AC97_RW_RETRIES 5 - -#define AC97_RATES \ - SNDRV_PCM_RATE_CONTINUOUS - -#define AC97_FMTS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE) - -/* instance data. There can be only one, MacLeod!!!!, fortunately there IS only - * once AC97C on early Alchemy chips. The newer ones aren't so lucky. - */ -static struct au1xpsc_audio_data *ac97c_workdata; -#define ac97_to_ctx(x) ac97c_workdata - -static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg) -{ - return __raw_readl(ctx->mmio + reg); -} - -static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v) -{ - __raw_writel(v, ctx->mmio + reg); - wmb(); -} - -static unsigned short au1xac97c_ac97_read(struct snd_ac97 *ac97, - unsigned short r) -{ - struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); - unsigned int tmo, retry; - unsigned long data; - - data = ~0; - retry = AC97_RW_RETRIES; - do { - mutex_lock(&ctx->lock); - - tmo = 5; - while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--) - udelay(21); /* wait an ac97 frame time */ - if (!tmo) { - pr_debug("ac97rd timeout #1\n"); - goto next; - } - - WR(ctx, AC97_CMDRESP, CMD_IDX(r) | CMD_READ); - - /* stupid errata: data is only valid for 21us, so - * poll, Forrest, poll... - */ - tmo = 0x10000; - while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--) - asm volatile ("nop"); - data = RD(ctx, AC97_CMDRESP); - - if (!tmo) - pr_debug("ac97rd timeout #2\n"); - -next: - mutex_unlock(&ctx->lock); - } while (--retry && !tmo); - - pr_debug("AC97RD %04x %04lx %d\n", r, data, retry); - - return retry ? data & 0xffff : 0xffff; -} - -static void au1xac97c_ac97_write(struct snd_ac97 *ac97, unsigned short r, - unsigned short v) -{ - struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); - unsigned int tmo, retry; - - retry = AC97_RW_RETRIES; - do { - mutex_lock(&ctx->lock); - - for (tmo = 5; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--) - udelay(21); - if (!tmo) { - pr_debug("ac97wr timeout #1\n"); - goto next; - } - - WR(ctx, AC97_CMDRESP, CMD_WRITE | CMD_IDX(r) | CMD_SET_DATA(v)); - - for (tmo = 10; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--) - udelay(21); - if (!tmo) - pr_debug("ac97wr timeout #2\n"); -next: - mutex_unlock(&ctx->lock); - } while (--retry && !tmo); - - pr_debug("AC97WR %04x %04x %d\n", r, v, retry); -} - -static void au1xac97c_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); - - WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG | CFG_SN); - msleep(20); - WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG); - WR(ctx, AC97_CONFIG, ctx->cfg); -} - -static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); - int i; - - WR(ctx, AC97_CONFIG, ctx->cfg | CFG_RS); - msleep(500); - WR(ctx, AC97_CONFIG, ctx->cfg); - - /* wait for codec ready */ - i = 50; - while (((RD(ctx, AC97_STATUS) & STAT_RD) == 0) && --i) - msleep(20); - if (!i) - printk(KERN_ERR "ac97c: codec not ready after cold reset\n"); -} - -/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { - .read = au1xac97c_ac97_read, - .write = au1xac97c_ac97_write, - .reset = au1xac97c_ac97_cold_reset, - .warm_reset = au1xac97c_ac97_warm_reset, -}; -EXPORT_SYMBOL_GPL(soc_ac97_ops); /* globals be gone! */ - -static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai); - snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]); - return 0; -} - -static const struct snd_soc_dai_ops alchemy_ac97c_ops = { - .startup = alchemy_ac97c_startup, -}; - -static int au1xac97c_dai_probe(struct snd_soc_dai *dai) -{ - return ac97c_workdata ? 0 : -ENODEV; -} - -static struct snd_soc_dai_driver au1xac97c_dai_driver = { - .name = "alchemy-ac97c", - .ac97_control = 1, - .probe = au1xac97c_dai_probe, - .playback = { - .rates = AC97_RATES, - .formats = AC97_FMTS, - .channels_min = 2, - .channels_max = 2, - }, - .capture = { - .rates = AC97_RATES, - .formats = AC97_FMTS, - .channels_min = 2, - .channels_max = 2, - }, - .ops = &alchemy_ac97c_ops, -}; - -static int __devinit au1xac97c_drvprobe(struct platform_device *pdev) -{ - int ret; - struct resource *iores, *dmares; - struct au1xpsc_audio_data *ctx; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - mutex_init(&ctx->lock); - - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) - return -ENODEV; - - if (!devm_request_mem_region(&pdev->dev, iores->start, - resource_size(iores), - pdev->name)) - return -EBUSY; - - ctx->mmio = devm_ioremap_nocache(&pdev->dev, iores->start, - resource_size(iores)); - if (!ctx->mmio) - return -EBUSY; - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!dmares) - return -EBUSY; - ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start; - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!dmares) - return -EBUSY; - ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start; - - /* switch it on */ - WR(ctx, AC97_ENABLE, EN_D | EN_CE); - WR(ctx, AC97_ENABLE, EN_CE); - - ctx->cfg = CFG_RC(3) | CFG_XS(3); - WR(ctx, AC97_CONFIG, ctx->cfg); - - platform_set_drvdata(pdev, ctx); - - ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver); - if (ret) - return ret; - - ac97c_workdata = ctx; - return 0; -} - -static int __devexit au1xac97c_drvremove(struct platform_device *pdev) -{ - struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - - WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ - - ac97c_workdata = NULL; /* MDEV */ - - return 0; -} - -#ifdef CONFIG_PM -static int au1xac97c_drvsuspend(struct device *dev) -{ - struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev); - - WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */ - - return 0; -} - -static int au1xac97c_drvresume(struct device *dev) -{ - struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev); - - WR(ctx, AC97_ENABLE, EN_D | EN_CE); - WR(ctx, AC97_ENABLE, EN_CE); - WR(ctx, AC97_CONFIG, ctx->cfg); - - return 0; -} - -static const struct dev_pm_ops au1xpscac97_pmops = { - .suspend = au1xac97c_drvsuspend, - .resume = au1xac97c_drvresume, -}; - -#define AU1XPSCAC97_PMOPS (&au1xpscac97_pmops) - -#else - -#define AU1XPSCAC97_PMOPS NULL - -#endif - -static struct platform_driver au1xac97c_driver = { - .driver = { - .name = "alchemy-ac97c", - .owner = THIS_MODULE, - .pm = AU1XPSCAC97_PMOPS, - }, - .probe = au1xac97c_drvprobe, - .remove = __devexit_p(au1xac97c_drvremove), -}; - -static int __init au1xac97c_load(void) -{ - ac97c_workdata = NULL; - return platform_driver_register(&au1xac97c_driver); -} - -static void __exit au1xac97c_unload(void) -{ - platform_driver_unregister(&au1xac97c_driver); -} - -module_init(au1xac97c_load); -module_exit(au1xac97c_unload); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); -MODULE_AUTHOR("Manuel Lauss"); diff --git a/ANDROID_3.4.5/sound/soc/au1x/db1000.c b/ANDROID_3.4.5/sound/soc/au1x/db1000.c deleted file mode 100644 index 511d83c1..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/db1000.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * DB1000/DB1500/DB1100 ASoC audio fabric support code. - * - * (c) 2011 Manuel Lauss - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "psc.h" - -static struct snd_soc_dai_link db1000_ac97_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - .codec_dai_name = "ac97-hifi", - .cpu_dai_name = "alchemy-ac97c", - .platform_name = "alchemy-pcm-dma.0", - .codec_name = "ac97-codec", -}; - -static struct snd_soc_card db1000_ac97 = { - .name = "DB1000_AC97", - .owner = THIS_MODULE, - .dai_link = &db1000_ac97_dai, - .num_links = 1, -}; - -static int __devinit db1000_audio_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &db1000_ac97; - card->dev = &pdev->dev; - return snd_soc_register_card(card); -} - -static int __devexit db1000_audio_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - snd_soc_unregister_card(card); - return 0; -} - -static struct platform_driver db1000_audio_driver = { - .driver = { - .name = "db1000-audio", - .owner = THIS_MODULE, - .pm = &snd_soc_pm_ops, - }, - .probe = db1000_audio_probe, - .remove = __devexit_p(db1000_audio_remove), -}; - -module_platform_driver(db1000_audio_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("DB1000/DB1500/DB1100 ASoC audio"); -MODULE_AUTHOR("Manuel Lauss"); diff --git a/ANDROID_3.4.5/sound/soc/au1x/db1200.c b/ANDROID_3.4.5/sound/soc/au1x/db1200.c deleted file mode 100644 index 30ea513d..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/db1200.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * DB1200/DB1300/DB1550 ASoC audio fabric support code. - * - * (c) 2008-2011 Manuel Lauss - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../codecs/wm8731.h" -#include "psc.h" - -static struct platform_device_id db1200_pids[] = { - { - .name = "db1200-ac97", - .driver_data = 0, - }, { - .name = "db1200-i2s", - .driver_data = 1, - }, { - .name = "db1300-ac97", - .driver_data = 2, - }, { - .name = "db1300-i2s", - .driver_data = 3, - }, { - .name = "db1550-ac97", - .driver_data = 4, - }, { - .name = "db1550-i2s", - .driver_data = 5, - }, - {}, -}; - -/*------------------------- AC97 PART ---------------------------*/ - -static struct snd_soc_dai_link db1200_ac97_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - .codec_dai_name = "ac97-hifi", - .cpu_dai_name = "au1xpsc_ac97.1", - .platform_name = "au1xpsc-pcm.1", - .codec_name = "ac97-codec.1", -}; - -static struct snd_soc_card db1200_ac97_machine = { - .name = "DB1200_AC97", - .owner = THIS_MODULE, - .dai_link = &db1200_ac97_dai, - .num_links = 1, -}; - -static struct snd_soc_dai_link db1300_ac97_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - .codec_dai_name = "wm9712-hifi", - .cpu_dai_name = "au1xpsc_ac97.1", - .platform_name = "au1xpsc-pcm.1", - .codec_name = "wm9712-codec.1", -}; - -static struct snd_soc_card db1300_ac97_machine = { - .name = "DB1300_AC97", - .dai_link = &db1300_ac97_dai, - .num_links = 1, -}; - -static struct snd_soc_card db1550_ac97_machine = { - .name = "DB1550_AC97", - .dai_link = &db1200_ac97_dai, - .num_links = 1, -}; - -/*------------------------- I2S PART ---------------------------*/ - -static int db1200_i2s_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - - /* WM8731 has its own 12MHz crystal */ - snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, - 12000000, SND_SOC_CLOCK_IN); - - /* codec is bitclock and lrclk master */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - goto out; - - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_LEFT_J | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - goto out; - - ret = 0; -out: - return ret; -} - -static struct snd_soc_ops db1200_i2s_wm8731_ops = { - .startup = db1200_i2s_startup, -}; - -static struct snd_soc_dai_link db1200_i2s_dai = { - .name = "WM8731", - .stream_name = "WM8731 PCM", - .codec_dai_name = "wm8731-hifi", - .cpu_dai_name = "au1xpsc_i2s.1", - .platform_name = "au1xpsc-pcm.1", - .codec_name = "wm8731.0-001b", - .ops = &db1200_i2s_wm8731_ops, -}; - -static struct snd_soc_card db1200_i2s_machine = { - .name = "DB1200_I2S", - .owner = THIS_MODULE, - .dai_link = &db1200_i2s_dai, - .num_links = 1, -}; - -static struct snd_soc_dai_link db1300_i2s_dai = { - .name = "WM8731", - .stream_name = "WM8731 PCM", - .codec_dai_name = "wm8731-hifi", - .cpu_dai_name = "au1xpsc_i2s.2", - .platform_name = "au1xpsc-pcm.2", - .codec_name = "wm8731.0-001b", - .ops = &db1200_i2s_wm8731_ops, -}; - -static struct snd_soc_card db1300_i2s_machine = { - .name = "DB1300_I2S", - .dai_link = &db1300_i2s_dai, - .num_links = 1, -}; - -static struct snd_soc_dai_link db1550_i2s_dai = { - .name = "WM8731", - .stream_name = "WM8731 PCM", - .codec_dai_name = "wm8731-hifi", - .cpu_dai_name = "au1xpsc_i2s.3", - .platform_name = "au1xpsc-pcm.3", - .codec_name = "wm8731.0-001b", - .ops = &db1200_i2s_wm8731_ops, -}; - -static struct snd_soc_card db1550_i2s_machine = { - .name = "DB1550_I2S", - .dai_link = &db1550_i2s_dai, - .num_links = 1, -}; - -/*------------------------- COMMON PART ---------------------------*/ - -static struct snd_soc_card *db1200_cards[] __devinitdata = { - &db1200_ac97_machine, - &db1200_i2s_machine, - &db1300_ac97_machine, - &db1300_i2s_machine, - &db1550_ac97_machine, - &db1550_i2s_machine, -}; - -static int __devinit db1200_audio_probe(struct platform_device *pdev) -{ - const struct platform_device_id *pid = platform_get_device_id(pdev); - struct snd_soc_card *card; - - card = db1200_cards[pid->driver_data]; - card->dev = &pdev->dev; - return snd_soc_register_card(card); -} - -static int __devexit db1200_audio_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - snd_soc_unregister_card(card); - return 0; -} - -static struct platform_driver db1200_audio_driver = { - .driver = { - .name = "db1200-ac97", - .owner = THIS_MODULE, - .pm = &snd_soc_pm_ops, - }, - .id_table = db1200_pids, - .probe = db1200_audio_probe, - .remove = __devexit_p(db1200_audio_remove), -}; - -module_platform_driver(db1200_audio_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("DB1200/DB1300/DB1550 ASoC audio support"); -MODULE_AUTHOR("Manuel Lauss"); diff --git a/ANDROID_3.4.5/sound/soc/au1x/dbdma2.c b/ANDROID_3.4.5/sound/soc/au1x/dbdma2.c deleted file mode 100644 index 8372cd35..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/dbdma2.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Au12x0/Au1550 PSC ALSA ASoC audio support. - * - * (c) 2007-2008 MSC Vertriebsges.m.b.H., - * Manuel Lauss - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * DMA glue for Au1x-PSC audio. - * - */ - - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "psc.h" - -/*#define PCM_DEBUG*/ - -#define MSG(x...) printk(KERN_INFO "au1xpsc_pcm: " x) -#ifdef PCM_DEBUG -#define DBG MSG -#else -#define DBG(x...) do {} while (0) -#endif - -struct au1xpsc_audio_dmadata { - /* DDMA control data */ - unsigned int ddma_id; /* DDMA direction ID for this PSC */ - u32 ddma_chan; /* DDMA context */ - - /* PCM context (for irq handlers) */ - struct snd_pcm_substream *substream; - unsigned long curr_period; /* current segment DDMA is working on */ - unsigned long q_period; /* queue period(s) */ - dma_addr_t dma_area; /* address of queued DMA area */ - dma_addr_t dma_area_s; /* start address of DMA area */ - unsigned long pos; /* current byte position being played */ - unsigned long periods; /* number of SG segments in total */ - unsigned long period_bytes; /* size in bytes of one SG segment */ - - /* runtime data */ - int msbits; -}; - -/* - * These settings are somewhat okay, at least on my machine audio plays - * almost skip-free. Especially the 64kB buffer seems to help a LOT. - */ -#define AU1XPSC_PERIOD_MIN_BYTES 1024 -#define AU1XPSC_BUFFER_MIN_BYTES 65536 - -#define AU1XPSC_PCM_FMTS \ - (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \ - SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | \ - SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE | \ - 0) - -/* 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_BATCH, - .formats = AU1XPSC_PCM_FMTS, - .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES, - .period_bytes_max = 4096 * 1024 - 1, - .periods_min = 2, - .periods_max = 4096, /* 2 to as-much-as-you-like */ - .buffer_bytes_max = 4096 * 1024 - 1, - .fifo_size = 16, /* fifo entries of AC97/I2S PSC */ -}; - -static void au1x_pcm_queue_tx(struct au1xpsc_audio_dmadata *cd) -{ - au1xxx_dbdma_put_source(cd->ddma_chan, cd->dma_area, - cd->period_bytes, DDMA_FLAGS_IE); - - /* update next-to-queue period */ - ++cd->q_period; - cd->dma_area += cd->period_bytes; - if (cd->q_period >= cd->periods) { - cd->q_period = 0; - cd->dma_area = cd->dma_area_s; - } -} - -static void au1x_pcm_queue_rx(struct au1xpsc_audio_dmadata *cd) -{ - au1xxx_dbdma_put_dest(cd->ddma_chan, cd->dma_area, - cd->period_bytes, DDMA_FLAGS_IE); - - /* update next-to-queue period */ - ++cd->q_period; - cd->dma_area += cd->period_bytes; - if (cd->q_period >= cd->periods) { - cd->q_period = 0; - cd->dma_area = cd->dma_area_s; - } -} - -static void au1x_pcm_dmatx_cb(int irq, void *dev_id) -{ - struct au1xpsc_audio_dmadata *cd = dev_id; - - cd->pos += cd->period_bytes; - if (++cd->curr_period >= cd->periods) { - cd->pos = 0; - cd->curr_period = 0; - } - snd_pcm_period_elapsed(cd->substream); - au1x_pcm_queue_tx(cd); -} - -static void au1x_pcm_dmarx_cb(int irq, void *dev_id) -{ - struct au1xpsc_audio_dmadata *cd = dev_id; - - cd->pos += cd->period_bytes; - if (++cd->curr_period >= cd->periods) { - cd->pos = 0; - cd->curr_period = 0; - } - snd_pcm_period_elapsed(cd->substream); - au1x_pcm_queue_rx(cd); -} - -static void au1x_pcm_dbdma_free(struct au1xpsc_audio_dmadata *pcd) -{ - if (pcd->ddma_chan) { - au1xxx_dbdma_stop(pcd->ddma_chan); - au1xxx_dbdma_reset(pcd->ddma_chan); - au1xxx_dbdma_chan_free(pcd->ddma_chan); - pcd->ddma_chan = 0; - pcd->msbits = 0; - } -} - -/* in case of missing DMA ring or changed TX-source / RX-dest bit widths, - * allocate (or reallocate) a 2-descriptor DMA ring with bit depth according - * to ALSA-supplied sample depth. This is due to limitations in the dbdma api - * (cannot adjust source/dest widths of already allocated descriptor ring). - */ -static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd, - int stype, int msbits) -{ - /* DMA only in 8/16/32 bit widths */ - if (msbits == 24) - msbits = 32; - - /* check current config: correct bits and descriptors allocated? */ - if ((pcd->ddma_chan) && (msbits == pcd->msbits)) - goto out; /* all ok! */ - - au1x_pcm_dbdma_free(pcd); - - if (stype == SNDRV_PCM_STREAM_CAPTURE) - pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id, - DSCR_CMD0_ALWAYS, - au1x_pcm_dmarx_cb, (void *)pcd); - else - pcd->ddma_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS, - pcd->ddma_id, - au1x_pcm_dmatx_cb, (void *)pcd); - - if (!pcd->ddma_chan) - return -ENOMEM; - - au1xxx_dbdma_set_devwidth(pcd->ddma_chan, msbits); - au1xxx_dbdma_ring_alloc(pcd->ddma_chan, 2); - - pcd->msbits = msbits; - - au1xxx_dbdma_stop(pcd->ddma_chan); - au1xxx_dbdma_reset(pcd->ddma_chan); - -out: - return 0; -} - -static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss) -{ - struct snd_soc_pcm_runtime *rtd = ss->private_data; - struct au1xpsc_audio_dmadata *pcd = - snd_soc_platform_get_drvdata(rtd->platform); - return &pcd[ss->stream]; -} - -static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct au1xpsc_audio_dmadata *pcd; - int stype, ret; - - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (ret < 0) - goto out; - - stype = substream->stream; - pcd = to_dmadata(substream); - - DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " - "runtime->min_align %d\n", - (unsigned long)runtime->dma_area, - (unsigned long)runtime->dma_addr, runtime->dma_bytes, - runtime->min_align); - - DBG("bits %d frags %d frag_bytes %d is_rx %d\n", params->msbits, - params_periods(params), params_period_bytes(params), stype); - - ret = au1x_pcm_dbdma_realloc(pcd, stype, params->msbits); - if (ret) { - MSG("DDMA channel (re)alloc failed!\n"); - goto out; - } - - pcd->substream = substream; - pcd->period_bytes = params_period_bytes(params); - pcd->periods = params_periods(params); - pcd->dma_area_s = pcd->dma_area = runtime->dma_addr; - pcd->q_period = 0; - pcd->curr_period = 0; - pcd->pos = 0; - - ret = 0; -out: - return ret; -} - -static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream); - - au1xxx_dbdma_reset(pcd->ddma_chan); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - au1x_pcm_queue_rx(pcd); - au1x_pcm_queue_rx(pcd); - } else { - au1x_pcm_queue_tx(pcd); - au1x_pcm_queue_tx(pcd); - } - - return 0; -} - -static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - u32 c = to_dmadata(substream)->ddma_chan; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - au1xxx_dbdma_start(c); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - au1xxx_dbdma_stop(c); - break; - default: - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t -au1xpsc_pcm_pointer(struct snd_pcm_substream *substream) -{ - return bytes_to_frames(substream->runtime, to_dmadata(substream)->pos); -} - -static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) -{ - struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream); - struct snd_soc_pcm_runtime *rtd = substream->private_data; - int stype = substream->stream, *dmaids; - - dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - if (!dmaids) - return -ENODEV; /* whoa, has ordering changed? */ - - pcd->ddma_id = dmaids[stype]; - - snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware); - return 0; -} - -static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) -{ - au1x_pcm_dbdma_free(to_dmadata(substream)); - return 0; -} - -static struct snd_pcm_ops au1xpsc_pcm_ops = { - .open = au1xpsc_pcm_open, - .close = au1xpsc_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = au1xpsc_pcm_hw_params, - .hw_free = au1xpsc_pcm_hw_free, - .prepare = au1xpsc_pcm_prepare, - .trigger = au1xpsc_pcm_trigger, - .pointer = au1xpsc_pcm_pointer, -}; - -static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1); - - return 0; -} - -/* au1xpsc audio platform */ -static struct snd_soc_platform_driver au1xpsc_soc_platform = { - .ops = &au1xpsc_pcm_ops, - .pcm_new = au1xpsc_pcm_new, - .pcm_free = au1xpsc_pcm_free_dma_buffers, -}; - -static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) -{ - struct au1xpsc_audio_dmadata *dmadata; - - dmadata = devm_kzalloc(&pdev->dev, - 2 * sizeof(struct au1xpsc_audio_dmadata), - GFP_KERNEL); - if (!dmadata) - return -ENOMEM; - - platform_set_drvdata(pdev, dmadata); - - return snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); -} - -static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - - return 0; -} - -static struct platform_driver au1xpsc_pcm_driver = { - .driver = { - .name = "au1xpsc-pcm", - .owner = THIS_MODULE, - }, - .probe = au1xpsc_pcm_drvprobe, - .remove = __devexit_p(au1xpsc_pcm_drvremove), -}; - -module_platform_driver(au1xpsc_pcm_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver"); -MODULE_AUTHOR("Manuel Lauss"); diff --git a/ANDROID_3.4.5/sound/soc/au1x/dma.c b/ANDROID_3.4.5/sound/soc/au1x/dma.c deleted file mode 100644 index 0a91b186..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/dma.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Au1000/Au1500/Au1100 Audio DMA support. - * - * (c) 2011 Manuel Lauss - * - * copied almost verbatim from the old ALSA driver, written by - * Charles Eidsness - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "psc.h" - -#define ALCHEMY_PCM_FMTS \ - (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \ - SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | \ - SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE | \ - 0) - -struct pcm_period { - u32 start; - u32 relative_end; /* relative to start of buffer */ - struct pcm_period *next; -}; - -struct audio_stream { - struct snd_pcm_substream *substream; - int dma; - struct pcm_period *buffer; - unsigned int period_size; - unsigned int periods; -}; - -struct alchemy_pcm_ctx { - struct audio_stream stream[2]; /* playback & capture */ -}; - -static void au1000_release_dma_link(struct audio_stream *stream) -{ - struct pcm_period *pointer; - struct pcm_period *pointer_next; - - stream->period_size = 0; - stream->periods = 0; - pointer = stream->buffer; - if (!pointer) - return; - do { - pointer_next = pointer->next; - kfree(pointer); - pointer = pointer_next; - } while (pointer != stream->buffer); - stream->buffer = NULL; -} - -static int au1000_setup_dma_link(struct audio_stream *stream, - unsigned int period_bytes, - unsigned int periods) -{ - struct snd_pcm_substream *substream = stream->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - struct pcm_period *pointer; - unsigned long dma_start; - int i; - - dma_start = virt_to_phys(runtime->dma_area); - - if (stream->period_size == period_bytes && - stream->periods == periods) - return 0; /* not changed */ - - au1000_release_dma_link(stream); - - stream->period_size = period_bytes; - stream->periods = periods; - - stream->buffer = kmalloc(sizeof(struct pcm_period), GFP_KERNEL); - if (!stream->buffer) - return -ENOMEM; - pointer = stream->buffer; - for (i = 0; i < periods; i++) { - pointer->start = (u32)(dma_start + (i * period_bytes)); - pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1); - if (i < periods - 1) { - pointer->next = kmalloc(sizeof(struct pcm_period), - GFP_KERNEL); - if (!pointer->next) { - au1000_release_dma_link(stream); - return -ENOMEM; - } - pointer = pointer->next; - } - } - pointer->next = stream->buffer; - return 0; -} - -static void au1000_dma_stop(struct audio_stream *stream) -{ - if (stream->buffer) - disable_dma(stream->dma); -} - -static void au1000_dma_start(struct audio_stream *stream) -{ - if (!stream->buffer) - return; - - init_dma(stream->dma); - if (get_dma_active_buffer(stream->dma) == 0) { - clear_dma_done0(stream->dma); - set_dma_addr0(stream->dma, stream->buffer->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - set_dma_addr1(stream->dma, stream->buffer->next->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - } else { - clear_dma_done1(stream->dma); - set_dma_addr1(stream->dma, stream->buffer->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - set_dma_addr0(stream->dma, stream->buffer->next->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - } - enable_dma_buffers(stream->dma); - start_dma(stream->dma); -} - -static irqreturn_t au1000_dma_interrupt(int irq, void *ptr) -{ - struct audio_stream *stream = (struct audio_stream *)ptr; - struct snd_pcm_substream *substream = stream->substream; - - switch (get_dma_buffer_done(stream->dma)) { - case DMA_D0: - stream->buffer = stream->buffer->next; - clear_dma_done0(stream->dma); - set_dma_addr0(stream->dma, stream->buffer->next->start); - set_dma_count0(stream->dma, stream->period_size >> 1); - enable_dma_buffer0(stream->dma); - break; - case DMA_D1: - stream->buffer = stream->buffer->next; - clear_dma_done1(stream->dma); - set_dma_addr1(stream->dma, stream->buffer->next->start); - set_dma_count1(stream->dma, stream->period_size >> 1); - enable_dma_buffer1(stream->dma); - break; - case (DMA_D0 | DMA_D1): - pr_debug("DMA %d missed interrupt.\n", stream->dma); - au1000_dma_stop(stream); - au1000_dma_start(stream); - break; - case (~DMA_D0 & ~DMA_D1): - pr_debug("DMA %d empty irq.\n", stream->dma); - } - snd_pcm_period_elapsed(substream); - return IRQ_HANDLED; -} - -static const struct snd_pcm_hardware alchemy_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, - .formats = ALCHEMY_PCM_FMTS, - .rates = SNDRV_PCM_RATE_8000_192000, - .rate_min = SNDRV_PCM_RATE_8000, - .rate_max = SNDRV_PCM_RATE_192000, - .channels_min = 2, - .channels_max = 2, - .period_bytes_min = 1024, - .period_bytes_max = 16 * 1024 - 1, - .periods_min = 4, - .periods_max = 255, - .buffer_bytes_max = 128 * 1024, - .fifo_size = 16, -}; - -static inline struct alchemy_pcm_ctx *ss_to_ctx(struct snd_pcm_substream *ss) -{ - struct snd_soc_pcm_runtime *rtd = ss->private_data; - return snd_soc_platform_get_drvdata(rtd->platform); -} - -static inline struct audio_stream *ss_to_as(struct snd_pcm_substream *ss) -{ - struct alchemy_pcm_ctx *ctx = ss_to_ctx(ss); - return &(ctx->stream[ss->stream]); -} - -static int alchemy_pcm_open(struct snd_pcm_substream *substream) -{ - struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream); - struct snd_soc_pcm_runtime *rtd = substream->private_data; - int *dmaids, s = substream->stream; - char *name; - - dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - if (!dmaids) - return -ENODEV; /* whoa, has ordering changed? */ - - /* DMA setup */ - name = (s == SNDRV_PCM_STREAM_PLAYBACK) ? "audio-tx" : "audio-rx"; - ctx->stream[s].dma = request_au1000_dma(dmaids[s], name, - au1000_dma_interrupt, 0, - &ctx->stream[s]); - set_dma_mode(ctx->stream[s].dma, - get_dma_mode(ctx->stream[s].dma) & ~DMA_NC); - - ctx->stream[s].substream = substream; - ctx->stream[s].buffer = NULL; - snd_soc_set_runtime_hwparams(substream, &alchemy_pcm_hardware); - - return 0; -} - -static int alchemy_pcm_close(struct snd_pcm_substream *substream) -{ - struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream); - int stype = substream->stream; - - ctx->stream[stype].substream = NULL; - free_au1000_dma(ctx->stream[stype].dma); - - return 0; -} - -static int alchemy_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct audio_stream *stream = ss_to_as(substream); - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - err = au1000_setup_dma_link(stream, - params_period_bytes(hw_params), - params_periods(hw_params)); - if (err) - snd_pcm_lib_free_pages(substream); - - return err; -} - -static int alchemy_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct audio_stream *stream = ss_to_as(substream); - au1000_release_dma_link(stream); - return snd_pcm_lib_free_pages(substream); -} - -static int alchemy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct audio_stream *stream = ss_to_as(substream); - int err = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - au1000_dma_start(stream); - break; - case SNDRV_PCM_TRIGGER_STOP: - au1000_dma_stop(stream); - break; - default: - err = -EINVAL; - break; - } - return err; -} - -static snd_pcm_uframes_t alchemy_pcm_pointer(struct snd_pcm_substream *ss) -{ - struct audio_stream *stream = ss_to_as(ss); - long location; - - location = get_dma_residue(stream->dma); - location = stream->buffer->relative_end - location; - if (location == -1) - location = 0; - return bytes_to_frames(ss->runtime, location); -} - -static struct snd_pcm_ops alchemy_pcm_ops = { - .open = alchemy_pcm_open, - .close = alchemy_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = alchemy_pcm_hw_params, - .hw_free = alchemy_pcm_hw_free, - .trigger = alchemy_pcm_trigger, - .pointer = alchemy_pcm_pointer, -}; - -static void alchemy_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_pcm *pcm = rtd->pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), 65536, (4096 * 1024) - 1); - - return 0; -} - -static struct snd_soc_platform_driver alchemy_pcm_soc_platform = { - .ops = &alchemy_pcm_ops, - .pcm_new = alchemy_pcm_new, - .pcm_free = alchemy_pcm_free_dma_buffers, -}; - -static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev) -{ - struct alchemy_pcm_ctx *ctx; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - platform_set_drvdata(pdev, ctx); - - return snd_soc_register_platform(&pdev->dev, &alchemy_pcm_soc_platform); -} - -static int __devexit alchemy_pcm_drvremove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - - return 0; -} - -static struct platform_driver alchemy_pcmdma_driver = { - .driver = { - .name = "alchemy-pcm-dma", - .owner = THIS_MODULE, - }, - .probe = alchemy_pcm_drvprobe, - .remove = __devexit_p(alchemy_pcm_drvremove), -}; - -module_platform_driver(alchemy_pcmdma_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Au1000/Au1500/Au1100 Audio DMA driver"); -MODULE_AUTHOR("Manuel Lauss"); diff --git a/ANDROID_3.4.5/sound/soc/au1x/i2sc.c b/ANDROID_3.4.5/sound/soc/au1x/i2sc.c deleted file mode 100644 index d4b9e364..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/i2sc.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Au1000/Au1500/Au1100 I2S controller driver for ASoC - * - * (c) 2011 Manuel Lauss - * - * Note: clock supplied to the I2S controller must be 256x samplerate. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "psc.h" - -#define I2S_RXTX 0x00 -#define I2S_CFG 0x04 -#define I2S_ENABLE 0x08 - -#define CFG_XU (1 << 25) /* tx underflow */ -#define CFG_XO (1 << 24) -#define CFG_RU (1 << 23) -#define CFG_RO (1 << 22) -#define CFG_TR (1 << 21) -#define CFG_TE (1 << 20) -#define CFG_TF (1 << 19) -#define CFG_RR (1 << 18) -#define CFG_RF (1 << 17) -#define CFG_ICK (1 << 12) /* clock invert */ -#define CFG_PD (1 << 11) /* set to make I2SDIO INPUT */ -#define CFG_LB (1 << 10) /* loopback */ -#define CFG_IC (1 << 9) /* word select invert */ -#define CFG_FM_I2S (0 << 7) /* I2S format */ -#define CFG_FM_LJ (1 << 7) /* left-justified */ -#define CFG_FM_RJ (2 << 7) /* right-justified */ -#define CFG_FM_MASK (3 << 7) -#define CFG_TN (1 << 6) /* tx fifo en */ -#define CFG_RN (1 << 5) /* rx fifo en */ -#define CFG_SZ_8 (0x08) -#define CFG_SZ_16 (0x10) -#define CFG_SZ_18 (0x12) -#define CFG_SZ_20 (0x14) -#define CFG_SZ_24 (0x18) -#define CFG_SZ_MASK (0x1f) -#define EN_D (1 << 1) /* DISable */ -#define EN_CE (1 << 0) /* clock enable */ - -/* only limited by clock generator and board design */ -#define AU1XI2SC_RATES \ - SNDRV_PCM_RATE_CONTINUOUS - -#define AU1XI2SC_FMTS \ - (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \ - SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \ - SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_U18_3BE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ - SNDRV_PCM_FMTBIT_S20_3BE | SNDRV_PCM_FMTBIT_U20_3BE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ - SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE | \ - 0) - -static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg) -{ - return __raw_readl(ctx->mmio + reg); -} - -static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v) -{ - __raw_writel(v, ctx->mmio + reg); - wmb(); -} - -static int au1xi2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) -{ - struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long c; - int ret; - - ret = -EINVAL; - c = ctx->cfg; - - c &= ~CFG_FM_MASK; - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - c |= CFG_FM_I2S; - break; - case SND_SOC_DAIFMT_MSB: - c |= CFG_FM_RJ; - break; - case SND_SOC_DAIFMT_LSB: - c |= CFG_FM_LJ; - break; - default: - goto out; - } - - c &= ~(CFG_IC | CFG_ICK); /* IB-IF */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - c |= CFG_IC | CFG_ICK; - break; - case SND_SOC_DAIFMT_NB_IF: - c |= CFG_IC; - break; - case SND_SOC_DAIFMT_IB_NF: - c |= CFG_ICK; - break; - case SND_SOC_DAIFMT_IB_IF: - break; - default: - goto out; - } - - /* I2S controller only supports master */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: /* CODEC slave */ - break; - default: - goto out; - } - - ret = 0; - ctx->cfg = c; -out: - return ret; -} - -static int au1xi2s_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai); - int stype = SUBSTREAM_TYPE(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - /* power up */ - WR(ctx, I2S_ENABLE, EN_D | EN_CE); - WR(ctx, I2S_ENABLE, EN_CE); - ctx->cfg |= (stype == PCM_TX) ? CFG_TN : CFG_RN; - WR(ctx, I2S_CFG, ctx->cfg); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - ctx->cfg &= ~((stype == PCM_TX) ? CFG_TN : CFG_RN); - WR(ctx, I2S_CFG, ctx->cfg); - WR(ctx, I2S_ENABLE, EN_D); /* power off */ - break; - default: - return -EINVAL; - } - - return 0; -} - -static unsigned long msbits_to_reg(int msbits) -{ - switch (msbits) { - case 8: - return CFG_SZ_8; - case 16: - return CFG_SZ_16; - case 18: - return CFG_SZ_18; - case 20: - return CFG_SZ_20; - case 24: - return CFG_SZ_24; - } - return 0; -} - -static int au1xi2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai); - unsigned long v; - - v = msbits_to_reg(params->msbits); - if (!v) - return -EINVAL; - - ctx->cfg &= ~CFG_SZ_MASK; - ctx->cfg |= v; - return 0; -} - -static int au1xi2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai); - snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]); - return 0; -} - -static const struct snd_soc_dai_ops au1xi2s_dai_ops = { - .startup = au1xi2s_startup, - .trigger = au1xi2s_trigger, - .hw_params = au1xi2s_hw_params, - .set_fmt = au1xi2s_set_fmt, -}; - -static struct snd_soc_dai_driver au1xi2s_dai_driver = { - .symmetric_rates = 1, - .playback = { - .rates = AU1XI2SC_RATES, - .formats = AU1XI2SC_FMTS, - .channels_min = 2, - .channels_max = 2, - }, - .capture = { - .rates = AU1XI2SC_RATES, - .formats = AU1XI2SC_FMTS, - .channels_min = 2, - .channels_max = 2, - }, - .ops = &au1xi2s_dai_ops, -}; - -static int __devinit au1xi2s_drvprobe(struct platform_device *pdev) -{ - struct resource *iores, *dmares; - struct au1xpsc_audio_data *ctx; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) - return -ENODEV; - - if (!devm_request_mem_region(&pdev->dev, iores->start, - resource_size(iores), - pdev->name)) - return -EBUSY; - - ctx->mmio = devm_ioremap_nocache(&pdev->dev, iores->start, - resource_size(iores)); - if (!ctx->mmio) - return -EBUSY; - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!dmares) - return -EBUSY; - ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start; - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!dmares) - return -EBUSY; - ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start; - - platform_set_drvdata(pdev, ctx); - - return snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver); -} - -static int __devexit au1xi2s_drvremove(struct platform_device *pdev) -{ - struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - - WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ - - return 0; -} - -#ifdef CONFIG_PM -static int au1xi2s_drvsuspend(struct device *dev) -{ - struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev); - - WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */ - - return 0; -} - -static int au1xi2s_drvresume(struct device *dev) -{ - return 0; -} - -static const struct dev_pm_ops au1xi2sc_pmops = { - .suspend = au1xi2s_drvsuspend, - .resume = au1xi2s_drvresume, -}; - -#define AU1XI2SC_PMOPS (&au1xi2sc_pmops) - -#else - -#define AU1XI2SC_PMOPS NULL - -#endif - -static struct platform_driver au1xi2s_driver = { - .driver = { - .name = "alchemy-i2sc", - .owner = THIS_MODULE, - .pm = AU1XI2SC_PMOPS, - }, - .probe = au1xi2s_drvprobe, - .remove = __devexit_p(au1xi2s_drvremove), -}; - -module_platform_driver(au1xi2s_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Au1000/1500/1100 I2S ASoC driver"); -MODULE_AUTHOR("Manuel Lauss"); diff --git a/ANDROID_3.4.5/sound/soc/au1x/psc-ac97.c b/ANDROID_3.4.5/sound/soc/au1x/psc-ac97.c deleted file mode 100644 index 476b79a1..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/psc-ac97.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Au12x0/Au1550 PSC ALSA ASoC audio support. - * - * (c) 2007-2009 MSC Vertriebsges.m.b.H., - * Manuel Lauss - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Au1xxx-PSC AC97 glue. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "psc.h" - -/* how often to retry failed codec register reads/writes */ -#define AC97_RW_RETRIES 5 - -#define AC97_DIR \ - (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) - -#define AC97_RATES \ - SNDRV_PCM_RATE_8000_48000 - -#define AC97_FMTS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE) - -#define AC97PCR_START(stype) \ - ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TS : PSC_AC97PCR_RS) -#define AC97PCR_STOP(stype) \ - ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TP : PSC_AC97PCR_RP) -#define AC97PCR_CLRFIFO(stype) \ - ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TC : PSC_AC97PCR_RC) - -#define AC97STAT_BUSY(stype) \ - ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97STAT_TB : PSC_AC97STAT_RB) - -/* instance data. There can be only one, MacLeod!!!! */ -static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; - -#if 0 - -/* this could theoretically work, but ac97->bus->card->private_data can be NULL - * when snd_ac97_mixer() is called; I don't know if the rest further down the - * chain are always valid either. - */ -static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x) -{ - struct snd_soc_card *c = x->bus->card->private_data; - return snd_soc_dai_get_drvdata(c->rtd->cpu_dai); -} - -#else - -#define ac97_to_pscdata(x) au1xpsc_ac97_workdata - -#endif - -/* AC97 controller reads codec register */ -static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); - unsigned short retry, tmo; - unsigned long data; - - au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); - au_sync(); - - retry = AC97_RW_RETRIES; - do { - mutex_lock(&pscdata->lock); - - au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg), - AC97_CDC(pscdata)); - au_sync(); - - tmo = 20; - do { - udelay(21); - if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD) - break; - } while (--tmo); - - data = au_readl(AC97_CDC(pscdata)); - - au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); - au_sync(); - - mutex_unlock(&pscdata->lock); - - if (reg != ((data >> 16) & 0x7f)) - tmo = 1; /* wrong register, try again */ - - } while (--retry && !tmo); - - return retry ? data & 0xffff : 0xffff; -} - -/* AC97 controller writes to codec register */ -static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); - unsigned int tmo, retry; - - au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); - au_sync(); - - retry = AC97_RW_RETRIES; - do { - mutex_lock(&pscdata->lock); - - au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff), - AC97_CDC(pscdata)); - au_sync(); - - tmo = 20; - do { - udelay(21); - if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD) - break; - } while (--tmo); - - au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); - au_sync(); - - mutex_unlock(&pscdata->lock); - } while (--retry && !tmo); -} - -/* AC97 controller asserts a warm reset */ -static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); - - au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata)); - au_sync(); - msleep(10); - au_writel(0, AC97_RST(pscdata)); - au_sync(); -} - -static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); - int i; - - /* disable PSC during cold reset */ - au_writel(0, AC97_CFG(au1xpsc_ac97_workdata)); - au_sync(); - au_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata)); - au_sync(); - - /* issue cold reset */ - au_writel(PSC_AC97RST_RST, AC97_RST(pscdata)); - au_sync(); - msleep(500); - au_writel(0, AC97_RST(pscdata)); - au_sync(); - - /* enable PSC */ - au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata)); - au_sync(); - - /* wait for PSC to indicate it's ready */ - i = 1000; - while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i)) - msleep(1); - - if (i == 0) { - printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n"); - return; - } - - /* enable the ac97 function */ - au_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata)); - au_sync(); - - /* wait for AC97 core to become ready */ - i = 1000; - while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i)) - msleep(1); - if (i == 0) - printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n"); -} - -/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { - .read = au1xpsc_ac97_read, - .write = au1xpsc_ac97_write, - .reset = au1xpsc_ac97_cold_reset, - .warm_reset = au1xpsc_ac97_warm_reset, -}; -EXPORT_SYMBOL_GPL(soc_ac97_ops); - -static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); - unsigned long r, ro, stat; - int chans, t, stype = substream->stream; - - chans = params_channels(params); - - r = ro = au_readl(AC97_CFG(pscdata)); - stat = au_readl(AC97_STAT(pscdata)); - - /* already active? */ - if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) { - /* reject parameters not currently set up */ - if ((PSC_AC97CFG_GET_LEN(r) != params->msbits) || - (pscdata->rate != params_rate(params))) - return -EINVAL; - } else { - - /* set sample bitdepth: REG[24:21]=(BITS-2)/2 */ - r &= ~PSC_AC97CFG_LEN_MASK; - r |= PSC_AC97CFG_SET_LEN(params->msbits); - - /* channels: enable slots for front L/R channel */ - if (stype == SNDRV_PCM_STREAM_PLAYBACK) { - r &= ~PSC_AC97CFG_TXSLOT_MASK; - r |= PSC_AC97CFG_TXSLOT_ENA(3); - r |= PSC_AC97CFG_TXSLOT_ENA(4); - } else { - r &= ~PSC_AC97CFG_RXSLOT_MASK; - r |= PSC_AC97CFG_RXSLOT_ENA(3); - r |= PSC_AC97CFG_RXSLOT_ENA(4); - } - - /* do we need to poke the hardware? */ - if (!(r ^ ro)) - goto out; - - /* ac97 engine is about to be disabled */ - mutex_lock(&pscdata->lock); - - /* disable AC97 device controller first... */ - au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata)); - au_sync(); - - /* ...wait for it... */ - t = 100; - while ((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t) - msleep(1); - - if (!t) - printk(KERN_ERR "PSC-AC97: can't disable!\n"); - - /* ...write config... */ - au_writel(r, AC97_CFG(pscdata)); - au_sync(); - - /* ...enable the AC97 controller again... */ - au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata)); - au_sync(); - - /* ...and wait for ready bit */ - t = 100; - while ((!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t) - msleep(1); - - if (!t) - printk(KERN_ERR "PSC-AC97: can't enable!\n"); - - mutex_unlock(&pscdata->lock); - - pscdata->cfg = r; - pscdata->rate = params_rate(params); - } - -out: - return 0; -} - -static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); - int ret, stype = substream->stream; - - ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata)); - au_sync(); - au_writel(AC97PCR_START(stype), AC97_PCR(pscdata)); - au_sync(); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata)); - au_sync(); - - while (au_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype)) - asm volatile ("nop"); - - au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata)); - au_sync(); - - break; - default: - ret = -EINVAL; - } - return ret; -} - -static int au1xpsc_ac97_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); - snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]); - return 0; -} - -static int au1xpsc_ac97_probe(struct snd_soc_dai *dai) -{ - return au1xpsc_ac97_workdata ? 0 : -ENODEV; -} - -static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { - .startup = au1xpsc_ac97_startup, - .trigger = au1xpsc_ac97_trigger, - .hw_params = au1xpsc_ac97_hw_params, -}; - -static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { - .ac97_control = 1, - .probe = au1xpsc_ac97_probe, - .playback = { - .rates = AC97_RATES, - .formats = AC97_FMTS, - .channels_min = 2, - .channels_max = 2, - }, - .capture = { - .rates = AC97_RATES, - .formats = AC97_FMTS, - .channels_min = 2, - .channels_max = 2, - }, - .ops = &au1xpsc_ac97_dai_ops, -}; - -static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) -{ - int ret; - struct resource *iores, *dmares; - unsigned long sel; - struct au1xpsc_audio_data *wd; - - wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data), - GFP_KERNEL); - if (!wd) - return -ENOMEM; - - mutex_init(&wd->lock); - - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) - return -ENODEV; - - if (!devm_request_mem_region(&pdev->dev, iores->start, - resource_size(iores), - pdev->name)) - return -EBUSY; - - wd->mmio = devm_ioremap(&pdev->dev, iores->start, - resource_size(iores)); - if (!wd->mmio) - return -EBUSY; - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!dmares) - return -EBUSY; - wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start; - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!dmares) - return -EBUSY; - wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start; - - /* configuration: max dma trigger threshold, enable ac97 */ - wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 | - PSC_AC97CFG_DE_ENABLE; - - /* preserve PSC clock source set up by platform */ - sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK; - au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); - au_sync(); - au_writel(0, PSC_SEL(wd)); - au_sync(); - au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); - au_sync(); - - /* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */ - memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template, - sizeof(struct snd_soc_dai_driver)); - wd->dai_drv.name = dev_name(&pdev->dev); - - platform_set_drvdata(pdev, wd); - - ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); - if (ret) - return ret; - - au1xpsc_ac97_workdata = wd; - return 0; -} - -static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev) -{ - struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - - /* disable PSC completely */ - au_writel(0, AC97_CFG(wd)); - au_sync(); - au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); - au_sync(); - - au1xpsc_ac97_workdata = NULL; /* MDEV */ - - return 0; -} - -#ifdef CONFIG_PM -static int au1xpsc_ac97_drvsuspend(struct device *dev) -{ - struct au1xpsc_audio_data *wd = dev_get_drvdata(dev); - - /* save interesting registers and disable PSC */ - wd->pm[0] = au_readl(PSC_SEL(wd)); - - au_writel(0, AC97_CFG(wd)); - au_sync(); - au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); - au_sync(); - - return 0; -} - -static int au1xpsc_ac97_drvresume(struct device *dev) -{ - struct au1xpsc_audio_data *wd = dev_get_drvdata(dev); - - /* restore PSC clock config */ - au_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd)); - au_sync(); - - /* after this point the ac97 core will cold-reset the codec. - * During cold-reset the PSC is reinitialized and the last - * configuration set up in hw_params() is restored. - */ - return 0; -} - -static struct dev_pm_ops au1xpscac97_pmops = { - .suspend = au1xpsc_ac97_drvsuspend, - .resume = au1xpsc_ac97_drvresume, -}; - -#define AU1XPSCAC97_PMOPS &au1xpscac97_pmops - -#else - -#define AU1XPSCAC97_PMOPS NULL - -#endif - -static struct platform_driver au1xpsc_ac97_driver = { - .driver = { - .name = "au1xpsc_ac97", - .owner = THIS_MODULE, - .pm = AU1XPSCAC97_PMOPS, - }, - .probe = au1xpsc_ac97_drvprobe, - .remove = __devexit_p(au1xpsc_ac97_drvremove), -}; - -static int __init au1xpsc_ac97_load(void) -{ - au1xpsc_ac97_workdata = NULL; - return platform_driver_register(&au1xpsc_ac97_driver); -} - -static void __exit au1xpsc_ac97_unload(void) -{ - platform_driver_unregister(&au1xpsc_ac97_driver); -} - -module_init(au1xpsc_ac97_load); -module_exit(au1xpsc_ac97_unload); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); -MODULE_AUTHOR("Manuel Lauss"); - diff --git a/ANDROID_3.4.5/sound/soc/au1x/psc-i2s.c b/ANDROID_3.4.5/sound/soc/au1x/psc-i2s.c deleted file mode 100644 index 0607ba3d..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/psc-i2s.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Au12x0/Au1550 PSC ALSA ASoC audio support. - * - * (c) 2007-2008 MSC Vertriebsges.m.b.H., - * Manuel Lauss - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Au1xxx-PSC I2S glue. - * - * NOTE: so far only PSC slave mode (bit- and frameclock) is supported. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "psc.h" - -/* supported I2S DAI hardware formats */ -#define AU1XPSC_I2S_DAIFMT \ - (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | \ - SND_SOC_DAIFMT_NB_NF) - -/* supported I2S direction */ -#define AU1XPSC_I2S_DIR \ - (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) - -#define AU1XPSC_I2S_RATES \ - SNDRV_PCM_RATE_8000_192000 - -#define AU1XPSC_I2S_FMTS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) - -#define I2SSTAT_BUSY(stype) \ - ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB) -#define I2SPCR_START(stype) \ - ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TS : PSC_I2SPCR_RS) -#define I2SPCR_STOP(stype) \ - ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TP : PSC_I2SPCR_RP) -#define I2SPCR_CLRFIFO(stype) \ - ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TC : PSC_I2SPCR_RC) - - -static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long ct; - int ret; - - ret = -EINVAL; - - ct = pscdata->cfg; - - ct &= ~(PSC_I2SCFG_XM | PSC_I2SCFG_MLJ); /* left-justified */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - ct |= PSC_I2SCFG_XM; /* enable I2S mode */ - break; - case SND_SOC_DAIFMT_MSB: - break; - case SND_SOC_DAIFMT_LSB: - ct |= PSC_I2SCFG_MLJ; /* LSB (right-) justified */ - break; - default: - goto out; - } - - ct &= ~(PSC_I2SCFG_BI | PSC_I2SCFG_WI); /* IB-IF */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - ct |= PSC_I2SCFG_BI | PSC_I2SCFG_WI; - break; - case SND_SOC_DAIFMT_NB_IF: - ct |= PSC_I2SCFG_BI; - break; - case SND_SOC_DAIFMT_IB_NF: - ct |= PSC_I2SCFG_WI; - break; - case SND_SOC_DAIFMT_IB_IF: - break; - default: - goto out; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: /* CODEC master */ - ct |= PSC_I2SCFG_MS; /* PSC I2S slave mode */ - break; - case SND_SOC_DAIFMT_CBS_CFS: /* CODEC slave */ - ct &= ~PSC_I2SCFG_MS; /* PSC I2S Master mode */ - break; - default: - goto out; - } - - pscdata->cfg = ct; - ret = 0; -out: - return ret; -} - -static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); - - int cfgbits; - unsigned long stat; - - /* check if the PSC is already streaming data */ - stat = au_readl(I2S_STAT(pscdata)); - if (stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB)) { - /* reject parameters not currently set up in hardware */ - cfgbits = au_readl(I2S_CFG(pscdata)); - if ((PSC_I2SCFG_GET_LEN(cfgbits) != params->msbits) || - (params_rate(params) != pscdata->rate)) - return -EINVAL; - } else { - /* set sample bitdepth */ - pscdata->cfg &= ~(0x1f << 4); - pscdata->cfg |= PSC_I2SCFG_SET_LEN(params->msbits); - /* remember current rate for other stream */ - pscdata->rate = params_rate(params); - } - return 0; -} - -/* Configure PSC late: on my devel systems the codec is I2S master and - * supplies the i2sbitclock __AND__ i2sMclk (!) to the PSC unit. ASoC - * uses aggressive PM and switches the codec off when it is not in use - * which also means the PSC unit doesn't get any clocks and is therefore - * dead. That's why this chunk here gets called from the trigger callback - * because I can be reasonably certain the codec is driving the clocks. - */ -static int au1xpsc_i2s_configure(struct au1xpsc_audio_data *pscdata) -{ - unsigned long tmo; - - /* bring PSC out of sleep, and configure I2S unit */ - au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata)); - au_sync(); - - tmo = 1000000; - while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_SR) && tmo) - tmo--; - - if (!tmo) - goto psc_err; - - au_writel(0, I2S_CFG(pscdata)); - au_sync(); - au_writel(pscdata->cfg | PSC_I2SCFG_DE_ENABLE, I2S_CFG(pscdata)); - au_sync(); - - /* wait for I2S controller to become ready */ - tmo = 1000000; - while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_DR) && tmo) - tmo--; - - if (tmo) - return 0; - -psc_err: - au_writel(0, I2S_CFG(pscdata)); - au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata)); - au_sync(); - return -ETIMEDOUT; -} - -static int au1xpsc_i2s_start(struct au1xpsc_audio_data *pscdata, int stype) -{ - unsigned long tmo, stat; - int ret; - - ret = 0; - - /* if both TX and RX are idle, configure the PSC */ - stat = au_readl(I2S_STAT(pscdata)); - if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) { - ret = au1xpsc_i2s_configure(pscdata); - if (ret) - goto out; - } - - au_writel(I2SPCR_CLRFIFO(stype), I2S_PCR(pscdata)); - au_sync(); - au_writel(I2SPCR_START(stype), I2S_PCR(pscdata)); - au_sync(); - - /* wait for start confirmation */ - tmo = 1000000; - while (!(au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo) - tmo--; - - if (!tmo) { - au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata)); - au_sync(); - ret = -ETIMEDOUT; - } -out: - return ret; -} - -static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype) -{ - unsigned long tmo, stat; - - au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata)); - au_sync(); - - /* wait for stop confirmation */ - tmo = 1000000; - while ((au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo) - tmo--; - - /* if both TX and RX are idle, disable PSC */ - stat = au_readl(I2S_STAT(pscdata)); - if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) { - au_writel(0, I2S_CFG(pscdata)); - au_sync(); - au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata)); - au_sync(); - } - return 0; -} - -static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); - int ret, stype = substream->stream; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - ret = au1xpsc_i2s_start(pscdata, stype); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - ret = au1xpsc_i2s_stop(pscdata, stype); - break; - default: - ret = -EINVAL; - } - return ret; -} - -static int au1xpsc_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); - snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]); - return 0; -} - -static const struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { - .startup = au1xpsc_i2s_startup, - .trigger = au1xpsc_i2s_trigger, - .hw_params = au1xpsc_i2s_hw_params, - .set_fmt = au1xpsc_i2s_set_fmt, -}; - -static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = { - .playback = { - .rates = AU1XPSC_I2S_RATES, - .formats = AU1XPSC_I2S_FMTS, - .channels_min = 2, - .channels_max = 8, /* 2 without external help */ - }, - .capture = { - .rates = AU1XPSC_I2S_RATES, - .formats = AU1XPSC_I2S_FMTS, - .channels_min = 2, - .channels_max = 8, /* 2 without external help */ - }, - .ops = &au1xpsc_i2s_dai_ops, -}; - -static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) -{ - struct resource *iores, *dmares; - unsigned long sel; - int ret; - struct au1xpsc_audio_data *wd; - - wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data), - GFP_KERNEL); - if (!wd) - return -ENOMEM; - - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) - return -ENODEV; - - ret = -EBUSY; - if (!devm_request_mem_region(&pdev->dev, iores->start, - resource_size(iores), - pdev->name)) - return -EBUSY; - - wd->mmio = devm_ioremap(&pdev->dev, iores->start, - resource_size(iores)); - if (!wd->mmio) - return -EBUSY; - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!dmares) - return -EBUSY; - wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start; - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!dmares) - return -EBUSY; - wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start; - - /* preserve PSC clock source set up by platform (dev.platform_data - * is already occupied by soc layer) - */ - sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK; - au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); - au_sync(); - au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(wd)); - au_writel(0, I2S_CFG(wd)); - au_sync(); - - /* preconfigure: set max rx/tx fifo depths */ - wd->cfg |= PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8; - - /* don't wait for I2S core to become ready now; clocks may not - * be running yet; depending on clock input for PSC a wait might - * time out. - */ - - /* name the DAI like this device instance ("au1xpsc-i2s.PSCINDEX") */ - memcpy(&wd->dai_drv, &au1xpsc_i2s_dai_template, - sizeof(struct snd_soc_dai_driver)); - wd->dai_drv.name = dev_name(&pdev->dev); - - platform_set_drvdata(pdev, wd); - - return snd_soc_register_dai(&pdev->dev, &wd->dai_drv); -} - -static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) -{ - struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - - au_writel(0, I2S_CFG(wd)); - au_sync(); - au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); - au_sync(); - - return 0; -} - -#ifdef CONFIG_PM -static int au1xpsc_i2s_drvsuspend(struct device *dev) -{ - struct au1xpsc_audio_data *wd = dev_get_drvdata(dev); - - /* save interesting register and disable PSC */ - wd->pm[0] = au_readl(PSC_SEL(wd)); - - au_writel(0, I2S_CFG(wd)); - au_sync(); - au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); - au_sync(); - - return 0; -} - -static int au1xpsc_i2s_drvresume(struct device *dev) -{ - struct au1xpsc_audio_data *wd = dev_get_drvdata(dev); - - /* select I2S mode and PSC clock */ - au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd)); - au_sync(); - au_writel(0, PSC_SEL(wd)); - au_sync(); - au_writel(wd->pm[0], PSC_SEL(wd)); - au_sync(); - - return 0; -} - -static struct dev_pm_ops au1xpsci2s_pmops = { - .suspend = au1xpsc_i2s_drvsuspend, - .resume = au1xpsc_i2s_drvresume, -}; - -#define AU1XPSCI2S_PMOPS &au1xpsci2s_pmops - -#else - -#define AU1XPSCI2S_PMOPS NULL - -#endif - -static struct platform_driver au1xpsc_i2s_driver = { - .driver = { - .name = "au1xpsc_i2s", - .owner = THIS_MODULE, - .pm = AU1XPSCI2S_PMOPS, - }, - .probe = au1xpsc_i2s_drvprobe, - .remove = __devexit_p(au1xpsc_i2s_drvremove), -}; - -module_platform_driver(au1xpsc_i2s_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver"); -MODULE_AUTHOR("Manuel Lauss"); diff --git a/ANDROID_3.4.5/sound/soc/au1x/psc.h b/ANDROID_3.4.5/sound/soc/au1x/psc.h deleted file mode 100644 index b16b2e02..00000000 --- a/ANDROID_3.4.5/sound/soc/au1x/psc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Alchemy ALSA ASoC audio support. - * - * (c) 2007-2011 MSC Vertriebsges.m.b.H., - * Manuel Lauss - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _AU1X_PCM_H -#define _AU1X_PCM_H - -struct au1xpsc_audio_data { - void __iomem *mmio; - - unsigned long cfg; - unsigned long rate; - - struct snd_soc_dai_driver dai_drv; - - unsigned long pm[2]; - struct mutex lock; - int dmaids[2]; -}; - -/* easy access macros */ -#define PSC_CTRL(x) ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET) -#define PSC_SEL(x) ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET) -#define I2S_STAT(x) ((unsigned long)((x)->mmio) + PSC_I2SSTAT_OFFSET) -#define I2S_CFG(x) ((unsigned long)((x)->mmio) + PSC_I2SCFG_OFFSET) -#define I2S_PCR(x) ((unsigned long)((x)->mmio) + PSC_I2SPCR_OFFSET) -#define AC97_CFG(x) ((unsigned long)((x)->mmio) + PSC_AC97CFG_OFFSET) -#define AC97_CDC(x) ((unsigned long)((x)->mmio) + PSC_AC97CDC_OFFSET) -#define AC97_EVNT(x) ((unsigned long)((x)->mmio) + PSC_AC97EVNT_OFFSET) -#define AC97_PCR(x) ((unsigned long)((x)->mmio) + PSC_AC97PCR_OFFSET) -#define AC97_RST(x) ((unsigned long)((x)->mmio) + PSC_AC97RST_OFFSET) -#define AC97_STAT(x) ((unsigned long)((x)->mmio) + PSC_AC97STAT_OFFSET) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/blackfin/Kconfig b/ANDROID_3.4.5/sound/soc/blackfin/Kconfig deleted file mode 100644 index 9f6bc55f..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/Kconfig +++ /dev/null @@ -1,181 +0,0 @@ -config SND_BF5XX_I2S - tristate "SoC I2S Audio for the ADI BF5xx chip" - depends on BLACKFIN - select SND_BF5XX_SOC_SPORT - help - Say Y or M if you want to add support for codecs attached to - the Blackfin SPORT (synchronous serial ports) interface in I2S - mode (supports single stereo In/Out). - You will also need to select the audio interfaces to support below. - -config SND_BF5XX_SOC_SSM2602 - tristate "SoC SSM2602 Audio support for BF52x ezkit" - depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) - select SND_BF5XX_SOC_I2S - select SND_SOC_SSM2602 - help - Say Y if you want to add support for SoC audio on BF527-EZKIT. - -config SND_SOC_BFIN_EVAL_ADAU1701 - tristate "Support for the EVAL-ADAU1701MINIZ board on Blackfin eval boards" - depends on SND_BF5XX_I2S - select SND_BF5XX_SOC_I2S - select SND_SOC_ADAU1701 - select I2C - help - Say Y if you want to add support for the Analog Devices EVAL-ADAU1701MINIZ - board connected to one of the Blackfin evaluation boards like the - BF5XX-STAMP or BF5XX-EZKIT. - -config SND_SOC_BFIN_EVAL_ADAU1373 - tristate "Support for the EVAL-ADAU1373 board on Blackfin eval boards" - depends on SND_BF5XX_I2S && I2C - select SND_BF5XX_SOC_I2S - select SND_SOC_ADAU1373 - help - Say Y if you want to add support for the Analog Devices EVAL-ADAU1373 - board connected to one of the Blackfin evaluation boards like the - BF5XX-STAMP or BF5XX-EZKIT. - - Note: This driver assumes that first ADAU1373 DAI is connected to the - first SPORT port on the BF5XX board. - -config SND_SOC_BFIN_EVAL_ADAV80X - tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards" - depends on SND_BF5XX_I2S && (SPI_MASTER || I2C) - select SND_BF5XX_SOC_I2S - select SND_SOC_ADAV80X - help - Say Y if you want to add support for the Analog Devices EVAL-ADAV801 or - EVAL-ADAV803 board connected to one of the Blackfin evaluation boards - like the BF5XX-STAMP or BF5XX-EZKIT. - - Note: This driver assumes that the ADAV80X digital record and playback - interfaces are connected to the first SPORT port on the BF5XX board. - -config SND_BF5XX_SOC_AD73311 - tristate "SoC AD73311 Audio support for Blackfin" - depends on SND_BF5XX_I2S - select SND_BF5XX_SOC_I2S - select SND_SOC_AD73311 - help - Say Y if you want to add support for AD73311 codec on Blackfin. - -config SND_BFIN_AD73311_SE - int "PF pin for AD73311L Chip Select" - depends on SND_BF5XX_SOC_AD73311 - default 4 - help - Enter the GPIO used to control AD73311's SE pin. Acceptable - values are 0 to 7 - -config SND_BF5XX_TDM - tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip" - depends on (BLACKFIN && SND_SOC) - select SND_BF5XX_SOC_SPORT - help - Say Y or M if you want to add support for codecs attached to - the Blackfin SPORT (synchronous serial ports) interface in TDM - mode. - You will also need to select the audio interfaces to support below. - -config SND_BF5XX_SOC_AD1836 - tristate "SoC AD1836 Audio support for BF5xx" - depends on SND_BF5XX_TDM - select SND_BF5XX_SOC_TDM - select SND_SOC_AD1836 - help - Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. - -config SND_BF5XX_SOC_AD193X - tristate "SoC AD193X Audio support for Blackfin" - depends on SND_BF5XX_TDM - select SND_BF5XX_SOC_TDM - select SND_SOC_AD193X - help - Say Y if you want to add support for AD193X codec on Blackfin. - This driver supports AD1936, AD1937, AD1938 and AD1939. - -config SND_BF5XX_AC97 - tristate "SoC AC97 Audio for the ADI BF5xx chip" - depends on BLACKFIN - select AC97_BUS - select SND_SOC_AC97_BUS - select SND_BF5XX_SOC_SPORT - select SND_BF5XX_SOC_AC97 - help - Say Y or M if you want to add support for codecs attached to - the Blackfin SPORT (synchronous serial ports) interface in slot 16 - mode (pseudo AC97 interface). - You will also need to select the audio interfaces to support below. - - Note: - AC97 codecs which do not implement the slot-16 mode will not function - properly with this driver. This driver is known to work with the - Analog Devices line of AC97 codecs. - -config SND_BF5XX_MMAP_SUPPORT - bool "Enable MMAP Support" - depends on SND_BF5XX_AC97 - default y - help - Say y if you want AC97 driver to support mmap mode. - We introduce an intermediate buffer to simulate mmap. - -config SND_BF5XX_MULTICHAN_SUPPORT - bool "Enable Multichannel Support" - depends on SND_BF5XX_AC97 - default n - help - Say y if you want AC97 driver to support up to 5.1 channel audio. - this mode will consume much more memory for DMA. - -config SND_BF5XX_HAVE_COLD_RESET - bool "BOARD has COLD Reset GPIO" - depends on SND_BF5XX_AC97 - default y if BFIN548_EZKIT - default n if !BFIN548_EZKIT - -config SND_BF5XX_RESET_GPIO_NUM - int "Set a GPIO for cold reset" - depends on SND_BF5XX_HAVE_COLD_RESET - range 0 159 - default 19 if BFIN548_EZKIT - default 5 if BFIN537_STAMP - default 0 - help - Set the correct GPIO for RESET the sound chip. - -config SND_BF5XX_SOC_AD1980 - tristate "SoC AD1980/1 Audio support for BF5xx (Obsolete)" - depends on SND_BF5XX_AC97 - select SND_BF5XX_SOC_AC97 - select SND_SOC_AD1980 - help - Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. - - Warning: - Because Analog Devices Inc. discontinued the ad1980 sound chip since - Sep. 2009, this ad1980 driver is not maintained, tested and supported - by ADI now. - -config SND_BF5XX_SOC_SPORT - tristate - -config SND_BF5XX_SOC_I2S - tristate - -config SND_BF5XX_SOC_TDM - tristate - -config SND_BF5XX_SOC_AC97 - tristate - -config SND_BF5XX_SPORT_NUM - int "Set a SPORT for Sound chip" - depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM) - range 0 3 if BF54x - range 0 1 if !BF54x - default 0 - help - Set the correct SPORT for sound chip. diff --git a/ANDROID_3.4.5/sound/soc/blackfin/Makefile b/ANDROID_3.4.5/sound/soc/blackfin/Makefile deleted file mode 100644 index 1bf86cca..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# Blackfin Platform Support -snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o -snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o -snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o -snd-soc-bf5xx-sport-objs := bf5xx-sport.o -snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o -snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o -snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o - -obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o -obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o -obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o -obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o -obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o -obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o -obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o - -# Blackfin Machine Support -snd-ad1836-objs := bf5xx-ad1836.o -snd-ad1980-objs := bf5xx-ad1980.o -snd-ssm2602-objs := bf5xx-ssm2602.o -snd-ad73311-objs := bf5xx-ad73311.o -snd-ad193x-objs := bf5xx-ad193x.o -snd-soc-bfin-eval-adau1373-objs := bfin-eval-adau1373.o -snd-soc-bfin-eval-adau1701-objs := bfin-eval-adau1701.o -snd-soc-bfin-eval-adav80x-objs := bfin-eval-adav80x.o - -obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o -obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o -obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o -obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o -obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o -obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) += snd-soc-bfin-eval-adau1373.o -obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) += snd-soc-bfin-eval-adau1701.o -obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) += snd-soc-bfin-eval-adav80x.o diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.c deleted file mode 100644 index d7dc9bde..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ac97-pcm.c - * Author: Cliff Cai - * - * Created: Tue June 06 2008 - * Description: DMA Driver for AC97 sound chip - * - * Modified: - * Copyright 2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "bf5xx-ac97-pcm.h" -#include "bf5xx-ac97.h" -#include "bf5xx-sport.h" - -static unsigned int ac97_chan_mask[] = { - SP_FL, /* Mono */ - SP_STEREO, /* Stereo */ - SP_2DOT1, /* 2.1*/ - SP_QUAD,/*Quadraquic*/ - SP_FL | SP_FR | SP_FC | SP_SL | SP_SR,/*5 channels */ - SP_5DOT1, /* 5.1 */ -}; - -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) -static void bf5xx_mmap_copy(struct snd_pcm_substream *substream, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - bf5xx_pcm_to_ac97((struct ac97_frame *)sport->tx_dma_buf + - sport->tx_pos, (__u16 *)runtime->dma_area + sport->tx_pos * - runtime->channels, count, chan_mask); - sport->tx_pos += runtime->period_size; - if (sport->tx_pos >= runtime->buffer_size) - sport->tx_pos %= runtime->buffer_size; - sport->tx_delay_pos = sport->tx_pos; - } else { - bf5xx_ac97_to_pcm((struct ac97_frame *)sport->rx_dma_buf + - sport->rx_pos, (__u16 *)runtime->dma_area + sport->rx_pos * - runtime->channels, count); - sport->rx_pos += runtime->period_size; - if (sport->rx_pos >= runtime->buffer_size) - sport->rx_pos %= runtime->buffer_size; - } -} -#endif - -static void bf5xx_dma_irq(void *data) -{ - struct snd_pcm_substream *pcm = data; -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - struct snd_pcm_runtime *runtime = pcm->runtime; - struct sport_device *sport = runtime->private_data; - bf5xx_mmap_copy(pcm, runtime->period_size); - if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (sport->once == 0) { - snd_pcm_period_elapsed(pcm); - bf5xx_mmap_copy(pcm, runtime->period_size); - sport->once = 1; - } - } -#endif - snd_pcm_period_elapsed(pcm); -} - -/* The memory size for pure pcm data is 128*1024 = 0x20000 bytes. - * The total rx/tx buffer is for ac97 frame to hold all pcm data - * is 0x20000 * sizeof(struct ac97_frame) / 4. - */ -static const struct snd_pcm_hardware bf5xx_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | -#endif - SNDRV_PCM_INFO_BLOCK_TRANSFER, - - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .period_bytes_min = 32, - .period_bytes_max = 0x10000, - .periods_min = 1, - .periods_max = PAGE_SIZE/32, - .buffer_bytes_max = 0x20000, /* 128 kbytes */ - .fifo_size = 16, -}; - -static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - size_t size = bf5xx_pcm_hardware.buffer_bytes_max - * sizeof(struct ac97_frame) / 4; - - snd_pcm_lib_malloc_pages(substream, size); - - return 0; -} - -static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - sport->once = 0; - if (runtime->dma_area) - memset(runtime->dma_area, 0, runtime->buffer_size); - memset(sport->tx_dma_buf, 0, runtime->buffer_size * - sizeof(struct ac97_frame)); - } else - memset(sport->rx_dma_buf, 0, runtime->buffer_size * - sizeof(struct ac97_frame)); -#endif - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - - /* An intermediate buffer is introduced for implementing mmap for - * SPORT working in TMD mode(include AC97). - */ -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - sport_set_tx_callback(sport, bf5xx_dma_irq, substream); - sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, - runtime->period_size * sizeof(struct ac97_frame)); - } else { - sport_set_rx_callback(sport, bf5xx_dma_irq, substream); - sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods, - runtime->period_size * sizeof(struct ac97_frame)); - } -#else - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - sport_set_tx_callback(sport, bf5xx_dma_irq, substream); - sport_config_tx_dma(sport, runtime->dma_area, runtime->periods, - runtime->period_size * sizeof(struct ac97_frame)); - } else { - sport_set_rx_callback(sport, bf5xx_dma_irq, substream); - sport_config_rx_dma(sport, runtime->dma_area, runtime->periods, - runtime->period_size * sizeof(struct ac97_frame)); - } -#endif - return 0; -} - -static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int ret = 0; - - pr_debug("%s enter\n", __func__); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - bf5xx_mmap_copy(substream, runtime->period_size); - sport->tx_delay_pos = 0; -#endif - sport_tx_start(sport); - } else - sport_rx_start(sport); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - sport->tx_pos = 0; -#endif - sport_tx_stop(sport); - } else { -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - sport->rx_pos = 0; -#endif - sport_rx_stop(sport); - } - break; - default: - ret = -EINVAL; - } - return ret; -} - -static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - unsigned int curr; - -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - curr = sport->tx_delay_pos; - else - curr = sport->rx_pos; -#else - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - curr = sport_curr_offset_tx(sport) / sizeof(struct ac97_frame); - else - curr = sport_curr_offset_rx(sport) / sizeof(struct ac97_frame); - -#endif - return curr; -} - -static int bf5xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - pr_debug("%s enter\n", __func__); - snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - if (sport_handle != NULL) - runtime->private_data = sport_handle; - else { - pr_err("sport_handle is NULL\n"); - return -1; - } - return 0; - - out: - return ret; -} - -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) -static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - size_t size = vma->vm_end - vma->vm_start; - vma->vm_start = (unsigned long)runtime->dma_area; - vma->vm_end = vma->vm_start + size; - vma->vm_flags |= VM_SHARED; - return 0 ; -} -#else -static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, - void __user *buf, snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; - pr_debug("%s copy pos:0x%lx count:0x%lx\n", - substream->stream ? "Capture" : "Playback", pos, count); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos, - (__u16 *)buf, count, chan_mask); - else - bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos, - (__u16 *)buf, count); - return 0; -} -#endif - -static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { - .open = bf5xx_pcm_open, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = bf5xx_pcm_hw_params, - .hw_free = bf5xx_pcm_hw_free, - .prepare = bf5xx_pcm_prepare, - .trigger = bf5xx_pcm_trigger, - .pointer = bf5xx_pcm_pointer, -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - .mmap = bf5xx_pcm_mmap, -#else - .copy = bf5xx_pcm_copy, -#endif -}; - -static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_soc_pcm_runtime *rtd = pcm->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = bf5xx_pcm_hardware.buffer_bytes_max - * sizeof(struct ac97_frame) / 4; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) { - pr_err("Failed to allocate dma memory\n"); - pr_err("Please increase uncached DMA memory region\n"); - return -ENOMEM; - } - buf->bytes = size; - - pr_debug("%s, area:%p, size:0x%08lx\n", __func__, - buf->area, buf->bytes); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_handle->tx_buf = buf->area; - else - sport_handle->rx_buf = buf->area; - -/* - * Need to allocate local buffer when enable - * MMAP for SPORT working in TMD mode (include AC97). - */ -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (!sport_handle->tx_dma_buf) { - sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \ - size, &sport_handle->tx_dma_phy, GFP_KERNEL); - if (!sport_handle->tx_dma_buf) { - pr_err("Failed to allocate memory for tx dma buf - Please increase uncached DMA memory region\n"); - return -ENOMEM; - } else - memset(sport_handle->tx_dma_buf, 0, size); - } else - memset(sport_handle->tx_dma_buf, 0, size); - } else { - if (!sport_handle->rx_dma_buf) { - sport_handle->rx_dma_buf = dma_alloc_coherent(NULL, \ - size, &sport_handle->rx_dma_phy, GFP_KERNEL); - if (!sport_handle->rx_dma_buf) { - pr_err("Failed to allocate memory for rx dma buf - Please increase uncached DMA memory region\n"); - return -ENOMEM; - } else - memset(sport_handle->rx_dma_buf, 0, size); - } else - memset(sport_handle->rx_dma_buf, 0, size); - } -#endif - return 0; -} - -static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - struct snd_soc_pcm_runtime *rtd = pcm->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); - size_t size = bf5xx_pcm_hardware.buffer_bytes_max * - sizeof(struct ac97_frame) / 4; -#endif - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_coherent(NULL, buf->bytes, buf->area, 0); - buf->area = NULL; -#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (sport_handle->tx_dma_buf) - dma_free_coherent(NULL, size, \ - sport_handle->tx_dma_buf, 0); - sport_handle->tx_dma_buf = NULL; - } else { - - if (sport_handle->rx_dma_buf) - dma_free_coherent(NULL, size, \ - sport_handle->rx_dma_buf, 0); - sport_handle->rx_dma_buf = NULL; - } -#endif - } -} - -static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); - -static int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - pr_debug("%s enter\n", __func__); - if (!card->dev->dma_mask) - card->dev->dma_mask = &bf5xx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - out: - return ret; -} - -static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = { - .ops = &bf5xx_pcm_ac97_ops, - .pcm_new = bf5xx_pcm_ac97_new, - .pcm_free = bf5xx_pcm_free_dma_buffers, -}; - -static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform); -} - -static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver bf5xx_pcm_driver = { - .driver = { - .name = "bfin-ac97-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = bf5xx_soc_platform_probe, - .remove = __devexit_p(bf5xx_soc_platform_remove), -}; - -module_platform_driver(bf5xx_pcm_driver); - -MODULE_AUTHOR("Cliff Cai"); -MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.h b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.h deleted file mode 100644 index d324d582..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97-pcm.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * linux/sound/arm/bf5xx-ac97-pcm.h -- ALSA PCM interface for the Blackfin - * - * Copyright 2007 Analog Device Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_AC97_PCM_H -#define _BF5XX_AC97_PCM_H - -struct bf5xx_pcm_dma_params { - char *name; /* stream identifier */ -}; - -struct bf5xx_gpio { - u32 sys; - u32 rx; - u32 tx; - u32 clk; - u32 frm; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.c deleted file mode 100644 index f4e9dc4e..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * bf5xx-ac97.c -- AC97 support for the ADI blackfin chip. - * - * Author: Roy Huang - * Created: 11th. June 2007 - * Copyright: Analog Device Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "bf5xx-sport.h" -#include "bf5xx-ac97.h" - -/* Anomaly notes: - * 05000250 - AD1980 is running in TDM mode and RFS/TFS are generated by SPORT - * contrtoller. But, RFSDIV and TFSDIV are always set to 16*16-1, - * while the max AC97 data size is 13*16. The DIV is always larger - * than data size. AD73311 and ad2602 are not running in TDM mode. - * AD1836 and AD73322 depend on external RFS/TFS only. So, this - * anomaly does not affect blackfin sound drivers. -*/ - -static struct sport_device *ac97_sport_handle; - -void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, - size_t count, unsigned int chan_mask) -{ - while (count--) { - dst->ac97_tag = TAG_VALID; - if (chan_mask & SP_FL) { - dst->ac97_pcm_r = *src++; - dst->ac97_tag |= TAG_PCM_RIGHT; - } - if (chan_mask & SP_FR) { - dst->ac97_pcm_l = *src++; - dst->ac97_tag |= TAG_PCM_LEFT; - - } -#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) - if (chan_mask & SP_SR) { - dst->ac97_sl = *src++; - dst->ac97_tag |= TAG_PCM_SL; - } - if (chan_mask & SP_SL) { - dst->ac97_sr = *src++; - dst->ac97_tag |= TAG_PCM_SR; - } - if (chan_mask & SP_LFE) { - dst->ac97_lfe = *src++; - dst->ac97_tag |= TAG_PCM_LFE; - } - if (chan_mask & SP_FC) { - dst->ac97_center = *src++; - dst->ac97_tag |= TAG_PCM_CENTER; - } -#endif - dst++; - } -} -EXPORT_SYMBOL(bf5xx_pcm_to_ac97); - -void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, - size_t count) -{ - while (count--) { - *(dst++) = src->ac97_pcm_l; - *(dst++) = src->ac97_pcm_r; - src++; - } -} -EXPORT_SYMBOL(bf5xx_ac97_to_pcm); - -static unsigned int sport_tx_curr_frag(struct sport_device *sport) -{ - return sport->tx_curr_frag = sport_curr_offset_tx(sport) / - sport->tx_fragsize; -} - -static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) -{ - struct sport_device *sport = ac97_sport_handle; - int *cmd_count = sport->private_data; - int nextfrag = sport_tx_curr_frag(sport); - struct ac97_frame *nextwrite; - - sport_incfrag(sport, &nextfrag, 1); - - nextwrite = (struct ac97_frame *)(sport->tx_buf + - nextfrag * sport->tx_fragsize); - pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n", - sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]); - nextwrite[cmd_count[nextfrag]].ac97_tag |= TAG_CMD; - nextwrite[cmd_count[nextfrag]].ac97_addr = addr; - nextwrite[cmd_count[nextfrag]].ac97_data = data; - ++cmd_count[nextfrag]; - pr_debug("ac97_sport: Inserting %02x/%04x into fragment %d\n", - addr >> 8, data, nextfrag); -} - -static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct sport_device *sport_handle = ac97_sport_handle; - struct ac97_frame out_frame[2], in_frame[2]; - - pr_debug("%s enter 0x%x\n", __func__, reg); - - /* When dma descriptor is enabled, the register should not be read */ - if (sport_handle->tx_run || sport_handle->rx_run) { - pr_err("Could you send a mail to cliff.cai@analog.com " - "to report this?\n"); - return -EFAULT; - } - - memset(&out_frame, 0, 2 * sizeof(struct ac97_frame)); - memset(&in_frame, 0, 2 * sizeof(struct ac97_frame)); - out_frame[0].ac97_tag = TAG_VALID | TAG_CMD; - out_frame[0].ac97_addr = ((reg << 8) | 0x8000); - sport_send_and_recv(sport_handle, (unsigned char *)&out_frame, - (unsigned char *)&in_frame, - 2 * sizeof(struct ac97_frame)); - return in_frame[1].ac97_data; -} - -void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct sport_device *sport_handle = ac97_sport_handle; - - pr_debug("%s enter 0x%x:0x%04x\n", __func__, reg, val); - - if (sport_handle->tx_run) { - enqueue_cmd(ac97, (reg << 8), val); /* write */ - enqueue_cmd(ac97, (reg << 8) | 0x8000, 0); /* read back */ - } else { - struct ac97_frame frame; - memset(&frame, 0, sizeof(struct ac97_frame)); - frame.ac97_tag = TAG_VALID | TAG_CMD; - frame.ac97_addr = (reg << 8); - frame.ac97_data = val; - sport_send_and_recv(sport_handle, (unsigned char *)&frame, \ - NULL, sizeof(struct ac97_frame)); - } -} - -static void bf5xx_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct sport_device *sport_handle = ac97_sport_handle; - u16 gpio = P_IDENT(sport_handle->pin_req[3]); - - pr_debug("%s enter\n", __func__); - - peripheral_free_list(sport_handle->pin_req); - gpio_request(gpio, "bf5xx-ac97"); - gpio_direction_output(gpio, 1); - udelay(2); - gpio_set_value(gpio, 0); - udelay(1); - gpio_free(gpio); - peripheral_request_list(sport_handle->pin_req, "soc-audio"); -} - -static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97) -{ -#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET - pr_debug("%s enter\n", __func__); - - /* It is specified for bf548-ezkit */ - gpio_set_value(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 0); - /* Keep reset pin low for 1 ms */ - mdelay(1); - gpio_set_value(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); - /* Wait for bit clock recover */ - mdelay(1); -#else - pr_info("%s: Not implemented\n", __func__); -#endif -} - -struct snd_ac97_bus_ops soc_ac97_ops = { - .read = bf5xx_ac97_read, - .write = bf5xx_ac97_write, - .warm_reset = bf5xx_ac97_warm_reset, - .reset = bf5xx_ac97_cold_reset, -}; -EXPORT_SYMBOL_GPL(soc_ac97_ops); - -#ifdef CONFIG_PM -static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) -{ - struct sport_device *sport = snd_soc_dai_get_drvdata(dai); - - pr_debug("%s : sport %d\n", __func__, dai->id); - if (!dai->active) - return 0; - if (dai->capture_active) - sport_rx_stop(sport); - if (dai->playback_active) - sport_tx_stop(sport); - return 0; -} - -static int bf5xx_ac97_resume(struct snd_soc_dai *dai) -{ - int ret; - struct sport_device *sport = snd_soc_dai_get_drvdata(dai); - - pr_debug("%s : sport %d\n", __func__, dai->id); - if (!dai->active) - return 0; - -#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) - ret = sport_set_multichannel(sport, 16, 0x3FF, 1); -#else - ret = sport_set_multichannel(sport, 16, 0x1F, 1); -#endif - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - ret = sport_config_rx(sport, IRFS, 0xF, 0, (16*16-1)); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - ret = sport_config_tx(sport, ITFS, 0xF, 0, (16*16-1)); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - return 0; -} - -#else -#define bf5xx_ac97_suspend NULL -#define bf5xx_ac97_resume NULL -#endif - -static struct snd_soc_dai_driver bfin_ac97_dai = { - .ac97_control = 1, - .suspend = bf5xx_ac97_suspend, - .resume = bf5xx_ac97_resume, - .playback = { - .stream_name = "AC97 Playback", - .channels_min = 2, -#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) - .channels_max = 6, -#else - .channels_max = 2, -#endif - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .capture = { - .stream_name = "AC97 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, }, -}; - -static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev) -{ - struct sport_device *sport_handle; - int ret; - -#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET - /* Request PB3 as reset pin */ - if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { - pr_err("Failed to request GPIO_%d for reset\n", - CONFIG_SND_BF5XX_RESET_GPIO_NUM); - ret = -1; - goto gpio_err; - } - gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); -#endif - - sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), - PAGE_SIZE); - if (!sport_handle) { - ret = -ENODEV; - goto sport_err; - } - - /*SPORT works in TDM mode to simulate AC97 transfers*/ -#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) - ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1); -#else - ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); -#endif - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); - if (ret) { - pr_err("Failed to register DAI: %d\n", ret); - goto sport_config_err; - } - - ac97_sport_handle = sport_handle; - - return 0; - -sport_config_err: - sport_done(sport_handle); -sport_err: -#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET - gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); -gpio_err: -#endif - - return ret; -} - -static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev) -{ - struct sport_device *sport_handle = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - sport_done(sport_handle); -#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET - gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); -#endif - - return 0; -} - -static struct platform_driver asoc_bfin_ac97_driver = { - .driver = { - .name = "bfin-ac97", - .owner = THIS_MODULE, - }, - - .probe = asoc_bfin_ac97_probe, - .remove = __devexit_p(asoc_bfin_ac97_remove), -}; - -module_platform_driver(asoc_bfin_ac97_driver); - -MODULE_AUTHOR("Roy Huang"); -MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.h b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.h deleted file mode 100644 index 15c635e3..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ac97.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-ac97.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_AC97_H -#define _BF5XX_AC97_H - -extern struct snd_ac97_bus_ops bf5xx_ac97_ops; -extern struct snd_ac97 *ac97; -/* Frame format in memory, only support stereo currently */ -struct ac97_frame { - u16 ac97_tag; /* slot 0 */ - u16 ac97_addr; /* slot 1 */ - u16 ac97_data; /* slot 2 */ - u16 ac97_pcm_l; /*slot 3:front left*/ - u16 ac97_pcm_r; /*slot 4:front left*/ -#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) - u16 ac97_mdm_l1; - u16 ac97_center; /*slot 6:center*/ - u16 ac97_sl; /*slot 7:surround left*/ - u16 ac97_sr; /*slot 8:surround right*/ - u16 ac97_lfe; /*slot 9:lfe*/ -#endif -} __attribute__ ((packed)); - -/* Speaker location */ -#define SP_FL 0x0001 -#define SP_FR 0x0010 -#define SP_FC 0x0002 -#define SP_LFE 0x0020 -#define SP_SL 0x0004 -#define SP_SR 0x0040 - -#define SP_STEREO (SP_FL | SP_FR) -#define SP_2DOT1 (SP_FL | SP_FR | SP_LFE) -#define SP_QUAD (SP_FL | SP_FR | SP_SL | SP_SR) -#define SP_5DOT1 (SP_FL | SP_FR | SP_FC | SP_LFE | SP_SL | SP_SR) - -#define TAG_VALID 0x8000 -#define TAG_CMD 0x6000 -#define TAG_PCM_LEFT 0x1000 -#define TAG_PCM_RIGHT 0x0800 -#define TAG_PCM_MDM_L1 0x0400 -#define TAG_PCM_CENTER 0x0200 -#define TAG_PCM_SL 0x0100 -#define TAG_PCM_SR 0x0080 -#define TAG_PCM_LFE 0x0040 - -void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \ - size_t count, unsigned int chan_mask); - -void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, \ - size_t count); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1836.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1836.c deleted file mode 100644 index d542d406..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1836.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ad1836.c - * Author: Barry Song - * - * Created: Aug 4 2009 - * Description: Board driver for ad1836 sound chip - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../codecs/ad1836.h" - -#include "bf5xx-tdm-pcm.h" -#include "bf5xx-tdm.h" - -static struct snd_soc_card bf5xx_ad1836; - -static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; - int ret = 0; - - /* set cpu DAI channel mapping */ - ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map), - channel_map, ARRAY_SIZE(channel_map), channel_map); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops bf5xx_ad1836_ops = { - .hw_params = bf5xx_ad1836_hw_params, -}; - -#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ - SND_SOC_DAIFMT_CBM_CFM) - -static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { - { - .name = "ad1836", - .stream_name = "AD1836", - .cpu_dai_name = "bfin-tdm.0", - .codec_dai_name = "ad1836-hifi", - .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "spi0.4", - .ops = &bf5xx_ad1836_ops, - .dai_fmt = BF5XX_AD1836_DAIFMT, - }, - { - .name = "ad1836", - .stream_name = "AD1836", - .cpu_dai_name = "bfin-tdm.1", - .codec_dai_name = "ad1836-hifi", - .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "spi0.4", - .ops = &bf5xx_ad1836_ops, - .dai_fmt = BF5XX_AD1836_DAIFMT, - }, -}; - -static struct snd_soc_card bf5xx_ad1836 = { - .name = "bfin-ad1836", - .owner = THIS_MODULE, - .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM], - .num_links = 1, -}; - -static struct platform_device *bfxx_ad1836_snd_device; - -static int __init bf5xx_ad1836_init(void) -{ - int ret; - - bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1); - if (!bfxx_ad1836_snd_device) - return -ENOMEM; - - platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836); - ret = platform_device_add(bfxx_ad1836_snd_device); - - if (ret) - platform_device_put(bfxx_ad1836_snd_device); - - return ret; -} - -static void __exit bf5xx_ad1836_exit(void) -{ - platform_device_unregister(bfxx_ad1836_snd_device); -} - -module_init(bf5xx_ad1836_init); -module_exit(bf5xx_ad1836_exit); - -/* Module information */ -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("ALSA SoC AD1836 board driver"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad193x.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad193x.c deleted file mode 100644 index 0e55e9f2..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad193x.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ad193x.c - * Author: Barry Song - * - * Created: Thur June 4 2009 - * Description: Board driver for ad193x sound chip - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../codecs/ad193x.h" - -#include "bf5xx-tdm-pcm.h" -#include "bf5xx-tdm.h" - -static struct snd_soc_card bf5xx_ad193x; - -static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - unsigned int clk = 0; - unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; - int ret = 0; - - switch (params_rate(params)) { - case 48000: - clk = 24576000; - break; - } - - /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, - SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - /* set codec DAI slots, 8 channels, all channels are enabled */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32); - if (ret < 0) - return ret; - - /* set cpu DAI channel mapping */ - ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map), - channel_map, ARRAY_SIZE(channel_map), channel_map); - if (ret < 0) - return ret; - - return 0; -} - -#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ - SND_SOC_DAIFMT_CBM_CFM) - -static struct snd_soc_ops bf5xx_ad193x_ops = { - .hw_params = bf5xx_ad193x_hw_params, -}; - -static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { - { - .name = "ad193x", - .stream_name = "AD193X", - .cpu_dai_name = "bfin-tdm.0", - .codec_dai_name ="ad193x-hifi", - .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "spi0.5", - .ops = &bf5xx_ad193x_ops, - .dai_fmt = BF5XX_AD193X_DAIFMT, - }, - { - .name = "ad193x", - .stream_name = "AD193X", - .cpu_dai_name = "bfin-tdm.1", - .codec_dai_name ="ad193x-hifi", - .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "spi0.5", - .ops = &bf5xx_ad193x_ops, - .dai_fmt = BF5XX_AD193X_DAIFMT, - }, -}; - -static struct snd_soc_card bf5xx_ad193x = { - .name = "bfin-ad193x", - .owner = THIS_MODULE, - .dai_link = &bf5xx_ad193x_dai[CONFIG_SND_BF5XX_SPORT_NUM], - .num_links = 1, -}; - -static struct platform_device *bfxx_ad193x_snd_device; - -static int __init bf5xx_ad193x_init(void) -{ - int ret; - - bfxx_ad193x_snd_device = platform_device_alloc("soc-audio", -1); - if (!bfxx_ad193x_snd_device) - return -ENOMEM; - - platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x); - ret = platform_device_add(bfxx_ad193x_snd_device); - - if (ret) - platform_device_put(bfxx_ad193x_snd_device); - - return ret; -} - -static void __exit bf5xx_ad193x_exit(void) -{ - platform_device_unregister(bfxx_ad193x_snd_device); -} - -module_init(bf5xx_ad193x_init); -module_exit(bf5xx_ad193x_exit); - -/* Module information */ -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("ALSA SoC AD193X board driver"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1980.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1980.c deleted file mode 100644 index b30f88bb..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad1980.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ad1980.c - * Author: Cliff Cai - * - * Created: Tue June 06 2008 - * Description: Board driver for AD1980/1 audio codec - * - * Modified: - * Copyright 2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * WARNING: - * - * Because Analog Devices Inc. discontinued the ad1980 sound chip since - * Sep. 2009, this ad1980 driver is not maintained, tested and supported - * by ADI now. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "../codecs/ad1980.h" - -#include "bf5xx-ac97-pcm.h" -#include "bf5xx-ac97.h" - -static struct snd_soc_card bf5xx_board; - -static struct snd_soc_dai_link bf5xx_board_dai[] = { - { - .name = "AC97", - .stream_name = "AC97 HiFi", - .cpu_dai_name = "bfin-ac97.0", - .codec_dai_name = "ad1980-hifi", - .platform_name = "bfin-ac97-pcm-audio", - .codec_name = "ad1980", - }, - { - .name = "AC97", - .stream_name = "AC97 HiFi", - .cpu_dai_name = "bfin-ac97.1", - .codec_dai_name = "ad1980-hifi", - .platform_name = "bfin-ac97-pcm-audio", - .codec_name = "ad1980", - }, -}; - -static struct snd_soc_card bf5xx_board = { - .name = "bfin-ad1980", - .owner = THIS_MODULE, - .dai_link = &bf5xx_board_dai[CONFIG_SND_BF5XX_SPORT_NUM], - .num_links = 1, -}; - -static struct platform_device *bf5xx_board_snd_device; - -static int __init bf5xx_board_init(void) -{ - int ret; - - bf5xx_board_snd_device = platform_device_alloc("soc-audio", -1); - if (!bf5xx_board_snd_device) - return -ENOMEM; - - platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board); - ret = platform_device_add(bf5xx_board_snd_device); - - if (ret) - platform_device_put(bf5xx_board_snd_device); - - return ret; -} - -static void __exit bf5xx_board_exit(void) -{ - platform_device_unregister(bf5xx_board_snd_device); -} - -module_init(bf5xx_board_init); -module_exit(bf5xx_board_exit); - -/* Module information */ -MODULE_AUTHOR("Cliff Cai"); -MODULE_DESCRIPTION("ALSA SoC AD1980/1 BF5xx board (Obsolete)"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad73311.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad73311.c deleted file mode 100644 index 61cc91d4..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ad73311.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ad73311.c - * Author: Cliff Cai - * - * Created: Thur Sep 25 2008 - * Description: Board driver for ad73311 sound chip - * - * Modified: - * Copyright 2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../codecs/ad73311.h" -#include "bf5xx-sport.h" -#include "bf5xx-i2s-pcm.h" - -#if CONFIG_SND_BF5XX_SPORT_NUM == 0 -#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 -#define bfin_read_SPORT_TCR1 bfin_read_SPORT0_TCR1 -#define bfin_write_SPORT_TCR2 bfin_write_SPORT0_TCR2 -#define bfin_write_SPORT_TX16 bfin_write_SPORT0_TX16 -#define bfin_read_SPORT_STAT bfin_read_SPORT0_STAT -#else -#define bfin_write_SPORT_TCR1 bfin_write_SPORT1_TCR1 -#define bfin_read_SPORT_TCR1 bfin_read_SPORT1_TCR1 -#define bfin_write_SPORT_TCR2 bfin_write_SPORT1_TCR2 -#define bfin_write_SPORT_TX16 bfin_write_SPORT1_TX16 -#define bfin_read_SPORT_STAT bfin_read_SPORT1_STAT -#endif - -#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE - -static struct snd_soc_card bf5xx_ad73311; - -static int snd_ad73311_startup(void) -{ - pr_debug("%s enter\n", __func__); - - /* Pull up SE pin on AD73311L */ - gpio_set_value(GPIO_SE, 1); - return 0; -} - -static int snd_ad73311_configure(void) -{ - unsigned short ctrl_regs[6]; - unsigned short status = 0; - int count = 0; - - /* DMCLK = MCLK = 16.384 MHz - * SCLK = DMCLK/8 = 2.048 MHz - * Sample Rate = DMCLK/2048 = 8 KHz - */ - ctrl_regs[0] = AD_CONTROL | AD_WRITE | CTRL_REG_B | REGB_MCDIV(0) | \ - REGB_SCDIV(0) | REGB_DIRATE(0); - ctrl_regs[1] = AD_CONTROL | AD_WRITE | CTRL_REG_C | REGC_PUDEV | \ - REGC_PUADC | REGC_PUDAC | REGC_PUREF | REGC_REFUSE ; - ctrl_regs[2] = AD_CONTROL | AD_WRITE | CTRL_REG_D | REGD_OGS(2) | \ - REGD_IGS(2); - ctrl_regs[3] = AD_CONTROL | AD_WRITE | CTRL_REG_E | REGE_DA(0x1f); - ctrl_regs[4] = AD_CONTROL | AD_WRITE | CTRL_REG_F | REGF_SEEN ; - ctrl_regs[5] = AD_CONTROL | AD_WRITE | CTRL_REG_A | REGA_MODE_DATA; - - local_irq_disable(); - snd_ad73311_startup(); - udelay(1); - - bfin_write_SPORT_TCR1(TFSR); - bfin_write_SPORT_TCR2(0xF); - SSYNC(); - - /* SPORT Tx Register is a 8 x 16 FIFO, all the data can be put to - * FIFO before enable SPORT to transfer the data - */ - for (count = 0; count < 6; count++) - bfin_write_SPORT_TX16(ctrl_regs[count]); - SSYNC(); - bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() | TSPEN); - SSYNC(); - - /* When TUVF is set, the data is already send out */ - while (!(status & TUVF) && ++count < 10000) { - udelay(1); - status = bfin_read_SPORT_STAT(); - SSYNC(); - } - bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() & ~TSPEN); - SSYNC(); - local_irq_enable(); - - if (count >= 10000) { - printk(KERN_ERR "ad73311: failed to configure codec\n"); - return -1; - } - return 0; -} - -static int bf5xx_probe(struct snd_soc_card *card) -{ - int err; - if (gpio_request(GPIO_SE, "AD73311_SE")) { - printk(KERN_ERR "%s: Failed ro request GPIO_%d\n", __func__, GPIO_SE); - return -EBUSY; - } - - gpio_direction_output(GPIO_SE, 0); - - err = snd_ad73311_configure(); - if (err < 0) - return -EFAULT; - - return 0; -} - -#define BF5XX_AD7311_DAI_FMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | \ - SND_SOC_DAIFMT_CBM_CFM) - -static struct snd_soc_dai_link bf5xx_ad73311_dai[] = { - { - .name = "ad73311", - .stream_name = "AD73311", - .cpu_dai_name = "bfin-i2s.0", - .codec_dai_name = "ad73311-hifi", - .platform_name = "bfin-i2s-pcm-audio", - .codec_name = "ad73311", - .dai_fmt = BF5XX_AD7311_DAI_FMT, - }, - { - .name = "ad73311", - .stream_name = "AD73311", - .cpu_dai_name = "bfin-i2s.1", - .codec_dai_name = "ad73311-hifi", - .platform_name = "bfin-i2s-pcm-audio", - .codec_name = "ad73311", - .dai_fmt = BF5XX_AD7311_DAI_FMT, - }, -}; - -static struct snd_soc_card bf5xx_ad73311 = { - .name = "bfin-ad73311", - .owner = THIS_MODULE, - .probe = bf5xx_probe, - .dai_link = &bf5xx_ad73311_dai[CONFIG_SND_BF5XX_SPORT_NUM], - .num_links = 1, -}; - -static struct platform_device *bf5xx_ad73311_snd_device; - -static int __init bf5xx_ad73311_init(void) -{ - int ret; - - pr_debug("%s enter\n", __func__); - bf5xx_ad73311_snd_device = platform_device_alloc("soc-audio", -1); - if (!bf5xx_ad73311_snd_device) - return -ENOMEM; - - platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311); - ret = platform_device_add(bf5xx_ad73311_snd_device); - - if (ret) - platform_device_put(bf5xx_ad73311_snd_device); - - return ret; -} - -static void __exit bf5xx_ad73311_exit(void) -{ - pr_debug("%s enter\n", __func__); - platform_device_unregister(bf5xx_ad73311_snd_device); -} - -module_init(bf5xx_ad73311_init); -module_exit(bf5xx_ad73311_exit); - -/* Module information */ -MODULE_AUTHOR("Cliff Cai"); -MODULE_DESCRIPTION("ALSA SoC AD73311 Blackfin"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.c deleted file mode 100644 index 63205d72..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-i2s-pcm.c - * Author: Cliff Cai - * - * Created: Tue June 06 2008 - * Description: DMA driver for i2s codec - * - * Modified: - * Copyright 2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "bf5xx-i2s-pcm.h" -#include "bf5xx-sport.h" - -static void bf5xx_dma_irq(void *data) -{ - struct snd_pcm_substream *pcm = data; - snd_pcm_period_elapsed(pcm); -} - -static const struct snd_pcm_hardware bf5xx_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .period_bytes_min = 32, - .period_bytes_max = 0x10000, - .periods_min = 1, - .periods_max = PAGE_SIZE/32, - .buffer_bytes_max = 0x20000, /* 128 kbytes */ - .fifo_size = 16, -}; - -static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - size_t size = bf5xx_pcm_hardware.buffer_bytes_max; - snd_pcm_lib_malloc_pages(substream, size); - - return 0; -} - -static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - - return 0; -} - -static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int period_bytes = frames_to_bytes(runtime, runtime->period_size); - - pr_debug("%s enter\n", __func__); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - sport_set_tx_callback(sport, bf5xx_dma_irq, substream); - sport_config_tx_dma(sport, runtime->dma_area, - runtime->periods, period_bytes); - } else { - sport_set_rx_callback(sport, bf5xx_dma_irq, substream); - sport_config_rx_dma(sport, runtime->dma_area, - runtime->periods, period_bytes); - } - - return 0; -} - -static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int ret = 0; - - pr_debug("%s enter\n", __func__); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_tx_start(sport); - else - sport_rx_start(sport); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_tx_stop(sport); - else - sport_rx_stop(sport); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - unsigned int diff; - snd_pcm_uframes_t frames; - pr_debug("%s enter\n", __func__); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - diff = sport_curr_offset_tx(sport); - } else { - diff = sport_curr_offset_rx(sport); - } - - /* - * TX at least can report one frame beyond the end of the - * buffer if we hit the wraparound case - clamp to within the - * buffer as the ALSA APIs require. - */ - if (diff == snd_pcm_lib_buffer_bytes(substream)) - diff = 0; - - frames = bytes_to_frames(substream->runtime, diff); - - return frames; -} - -static int bf5xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dma_buffer *buf = &substream->dma_buffer; - int ret; - - pr_debug("%s enter\n", __func__); - - snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - if (sport_handle != NULL) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_handle->tx_buf = buf->area; - else - sport_handle->rx_buf = buf->area; - - runtime->private_data = sport_handle; - } else { - pr_err("sport_handle is NULL\n"); - return -1; - } - return 0; - - out: - return ret; -} - -static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - size_t size = vma->vm_end - vma->vm_start; - vma->vm_start = (unsigned long)runtime->dma_area; - vma->vm_end = vma->vm_start + size; - vma->vm_flags |= VM_SHARED; - - return 0 ; -} - -static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { - .open = bf5xx_pcm_open, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = bf5xx_pcm_hw_params, - .hw_free = bf5xx_pcm_hw_free, - .prepare = bf5xx_pcm_prepare, - .trigger = bf5xx_pcm_trigger, - .pointer = bf5xx_pcm_pointer, - .mmap = bf5xx_pcm_mmap, -}; - -static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = bf5xx_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) { - pr_err("Failed to allocate dma memory - Please increase uncached DMA memory region\n"); - return -ENOMEM; - } - buf->bytes = size; - - pr_debug("%s, area:%p, size:0x%08lx\n", __func__, - buf->area, buf->bytes); - - return 0; -} - -static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_coherent(NULL, buf->bytes, buf->area, 0); - buf->area = NULL; - } -} - -static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); - -static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - pr_debug("%s enter\n", __func__); - if (!card->dev->dma_mask) - card->dev->dma_mask = &bf5xx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - out: - return ret; -} - -static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = { - .ops = &bf5xx_pcm_i2s_ops, - .pcm_new = bf5xx_pcm_i2s_new, - .pcm_free = bf5xx_pcm_free_dma_buffers, -}; - -static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform); -} - -static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver bfin_i2s_pcm_driver = { - .driver = { - .name = "bfin-i2s-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = bfin_i2s_soc_platform_probe, - .remove = __devexit_p(bfin_i2s_soc_platform_remove), -}; - -module_platform_driver(bfin_i2s_pcm_driver); - -MODULE_AUTHOR("Cliff Cai"); -MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.h b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.h deleted file mode 100644 index 0c2c5a68..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s-pcm.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * linux/sound/arm/bf5xx-i2s-pcm.h -- ALSA PCM interface for the Blackfin - * - * Copyright 2007 Analog Device Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_I2S_PCM_H -#define _BF5XX_I2S_PCM_H - -struct bf5xx_pcm_dma_params { - char *name; /* stream identifier */ -}; - -struct bf5xx_gpio { - u32 sys; - u32 rx; - u32 tx; - u32 clk; - u32 frm; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s.c deleted file mode 100644 index 4dccf037..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-i2s.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-i2s.c - * Author: Cliff Cai - * - * Created: Tue June 06 2008 - * Description: Blackfin I2S CPU DAI driver - * - * Modified: - * Copyright 2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "bf5xx-sport.h" - -struct bf5xx_i2s_port { - u16 tcr1; - u16 rcr1; - u16 tcr2; - u16 rcr2; - int configured; -}; - -static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); - struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; - int ret = 0; - - /* interface format:support I2S,slave mode */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - bf5xx_i2s->tcr1 |= TFSR | TCKFE; - bf5xx_i2s->rcr1 |= RFSR | RCKFE; - bf5xx_i2s->tcr2 |= TSFSE; - bf5xx_i2s->rcr2 |= RSFSE; - break; - case SND_SOC_DAIFMT_DSP_A: - bf5xx_i2s->tcr1 |= TFSR; - bf5xx_i2s->rcr1 |= RFSR; - break; - case SND_SOC_DAIFMT_LEFT_J: - ret = -EINVAL; - break; - default: - printk(KERN_ERR "%s: Unknown DAI format type\n", __func__); - ret = -EINVAL; - break; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBM_CFS: - case SND_SOC_DAIFMT_CBS_CFM: - ret = -EINVAL; - break; - default: - printk(KERN_ERR "%s: Unknown DAI master type\n", __func__); - ret = -EINVAL; - break; - } - - return ret; -} - -static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); - struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; - int ret = 0; - - bf5xx_i2s->tcr2 &= ~0x1f; - bf5xx_i2s->rcr2 &= ~0x1f; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - bf5xx_i2s->tcr2 |= 7; - bf5xx_i2s->rcr2 |= 7; - sport_handle->wdsize = 1; - case SNDRV_PCM_FORMAT_S16_LE: - bf5xx_i2s->tcr2 |= 15; - bf5xx_i2s->rcr2 |= 15; - sport_handle->wdsize = 2; - break; - case SNDRV_PCM_FORMAT_S24_LE: - bf5xx_i2s->tcr2 |= 23; - bf5xx_i2s->rcr2 |= 23; - sport_handle->wdsize = 3; - break; - case SNDRV_PCM_FORMAT_S32_LE: - bf5xx_i2s->tcr2 |= 31; - bf5xx_i2s->rcr2 |= 31; - sport_handle->wdsize = 4; - break; - } - - if (!bf5xx_i2s->configured) { - /* - * TX and RX are not independent,they are enabled at the - * same time, even if only one side is running. So, we - * need to configure both of them at the time when the first - * stream is opened. - * - * CPU DAI:slave mode. - */ - bf5xx_i2s->configured = 1; - ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, - bf5xx_i2s->rcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, - bf5xx_i2s->tcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - } - - return 0; -} - -static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); - struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; - - pr_debug("%s enter\n", __func__); - /* No active stream, SPORT is allowed to be configured again. */ - if (!dai->active) - bf5xx_i2s->configured = 0; -} - -#ifdef CONFIG_PM -static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) -{ - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); - - pr_debug("%s : sport %d\n", __func__, dai->id); - - if (dai->capture_active) - sport_rx_stop(sport_handle); - if (dai->playback_active) - sport_tx_stop(sport_handle); - return 0; -} - -static int bf5xx_i2s_resume(struct snd_soc_dai *dai) -{ - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); - struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; - int ret; - - pr_debug("%s : sport %d\n", __func__, dai->id); - - ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, - bf5xx_i2s->rcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, - bf5xx_i2s->tcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - return 0; -} - -#else -#define bf5xx_i2s_suspend NULL -#define bf5xx_i2s_resume NULL -#endif - -#define BF5XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ - SNDRV_PCM_RATE_96000) - -#define BF5XX_I2S_FORMATS \ - (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { - .shutdown = bf5xx_i2s_shutdown, - .hw_params = bf5xx_i2s_hw_params, - .set_fmt = bf5xx_i2s_set_dai_fmt, -}; - -static struct snd_soc_dai_driver bf5xx_i2s_dai = { - .suspend = bf5xx_i2s_suspend, - .resume = bf5xx_i2s_resume, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = BF5XX_I2S_RATES, - .formats = BF5XX_I2S_FORMATS,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = BF5XX_I2S_RATES, - .formats = BF5XX_I2S_FORMATS,}, - .ops = &bf5xx_i2s_dai_ops, -}; - -static int __devinit bf5xx_i2s_probe(struct platform_device *pdev) -{ - struct sport_device *sport_handle; - int ret; - - /* configure SPORT for I2S */ - sport_handle = sport_init(pdev, 4, 2 * sizeof(u32), - sizeof(struct bf5xx_i2s_port)); - if (!sport_handle) - return -ENODEV; - - /* register with the ASoC layers */ - ret = snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); - if (ret) { - pr_err("Failed to register DAI: %d\n", ret); - sport_done(sport_handle); - return ret; - } - - return 0; -} - -static int __devexit bf5xx_i2s_remove(struct platform_device *pdev) -{ - struct sport_device *sport_handle = platform_get_drvdata(pdev); - - pr_debug("%s enter\n", __func__); - - snd_soc_unregister_dai(&pdev->dev); - sport_done(sport_handle); - - return 0; -} - -static struct platform_driver bfin_i2s_driver = { - .probe = bf5xx_i2s_probe, - .remove = __devexit_p(bf5xx_i2s_remove), - .driver = { - .name = "bfin-i2s", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(bfin_i2s_driver); - -/* Module information */ -MODULE_AUTHOR("Cliff Cai"); -MODULE_DESCRIPTION("I2S driver for ADI Blackfin"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.c deleted file mode 100644 index 2fd9f2a0..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.c +++ /dev/null @@ -1,1094 +0,0 @@ -/* - * File: bf5xx_sport.c - * Based on: - * Author: Roy Huang - * - * Created: Tue Sep 21 10:52:42 CEST 2004 - * Description: - * Blackfin SPORT Driver - * - * Copyright 2004-2007 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bf5xx-sport.h" -/* delay between frame sync pulse and first data bit in multichannel mode */ -#define FRAME_DELAY (1<<12) - -/* note: multichannel is in units of 8 channels, - * tdm_count is # channels NOT / 8 ! */ -int sport_set_multichannel(struct sport_device *sport, - int tdm_count, u32 mask, int packed) -{ - pr_debug("%s tdm_count=%d mask:0x%08x packed=%d\n", __func__, - tdm_count, mask, packed); - - if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN)) - return -EBUSY; - - if (tdm_count & 0x7) - return -EINVAL; - - if (tdm_count > 32) - return -EINVAL; /* Only support less than 32 channels now */ - - if (tdm_count) { - sport->regs->mcmc1 = ((tdm_count>>3)-1) << 12; - sport->regs->mcmc2 = FRAME_DELAY | MCMEN | \ - (packed ? (MCDTXPE|MCDRXPE) : 0); - - sport->regs->mtcs0 = mask; - sport->regs->mrcs0 = mask; - sport->regs->mtcs1 = 0; - sport->regs->mrcs1 = 0; - sport->regs->mtcs2 = 0; - sport->regs->mrcs2 = 0; - sport->regs->mtcs3 = 0; - sport->regs->mrcs3 = 0; - } else { - sport->regs->mcmc1 = 0; - sport->regs->mcmc2 = 0; - - sport->regs->mtcs0 = 0; - sport->regs->mrcs0 = 0; - } - - sport->regs->mtcs1 = 0; sport->regs->mtcs2 = 0; sport->regs->mtcs3 = 0; - sport->regs->mrcs1 = 0; sport->regs->mrcs2 = 0; sport->regs->mrcs3 = 0; - - SSYNC(); - - return 0; -} -EXPORT_SYMBOL(sport_set_multichannel); - -int sport_config_rx(struct sport_device *sport, unsigned int rcr1, - unsigned int rcr2, unsigned int clkdiv, unsigned int fsdiv) -{ - if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN)) - return -EBUSY; - - sport->regs->rcr1 = rcr1; - sport->regs->rcr2 = rcr2; - sport->regs->rclkdiv = clkdiv; - sport->regs->rfsdiv = fsdiv; - - SSYNC(); - - return 0; -} -EXPORT_SYMBOL(sport_config_rx); - -int sport_config_tx(struct sport_device *sport, unsigned int tcr1, - unsigned int tcr2, unsigned int clkdiv, unsigned int fsdiv) -{ - if ((sport->regs->tcr1 & TSPEN) || (sport->regs->rcr1 & RSPEN)) - return -EBUSY; - - sport->regs->tcr1 = tcr1; - sport->regs->tcr2 = tcr2; - sport->regs->tclkdiv = clkdiv; - sport->regs->tfsdiv = fsdiv; - - SSYNC(); - - return 0; -} -EXPORT_SYMBOL(sport_config_tx); - -static void setup_desc(struct dmasg *desc, void *buf, int fragcount, - size_t fragsize, unsigned int cfg, - unsigned int x_count, unsigned int ycount, size_t wdsize) -{ - - int i; - - for (i = 0; i < fragcount; ++i) { - desc[i].next_desc_addr = &(desc[i + 1]); - desc[i].start_addr = (unsigned long)buf + i*fragsize; - desc[i].cfg = cfg; - desc[i].x_count = x_count; - desc[i].x_modify = wdsize; - desc[i].y_count = ycount; - desc[i].y_modify = wdsize; - } - - /* make circular */ - desc[fragcount-1].next_desc_addr = desc; - - pr_debug("setup desc: desc0=%p, next0=%p, desc1=%p," - "next1=%p\nx_count=%x,y_count=%x,addr=0x%lx,cfs=0x%x\n", - desc, desc[0].next_desc_addr, - desc+1, desc[1].next_desc_addr, - desc[0].x_count, desc[0].y_count, - desc[0].start_addr, desc[0].cfg); -} - -static int sport_start(struct sport_device *sport) -{ - enable_dma(sport->dma_rx_chan); - enable_dma(sport->dma_tx_chan); - sport->regs->rcr1 |= RSPEN; - sport->regs->tcr1 |= TSPEN; - SSYNC(); - - return 0; -} - -static int sport_stop(struct sport_device *sport) -{ - sport->regs->tcr1 &= ~TSPEN; - sport->regs->rcr1 &= ~RSPEN; - SSYNC(); - - disable_dma(sport->dma_rx_chan); - disable_dma(sport->dma_tx_chan); - return 0; -} - -static inline int sport_hook_rx_dummy(struct sport_device *sport) -{ - struct dmasg *desc, temp_desc; - unsigned long flags; - - BUG_ON(sport->dummy_rx_desc == NULL); - BUG_ON(sport->curr_rx_desc == sport->dummy_rx_desc); - - /* Maybe the dummy buffer descriptor ring is damaged */ - sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc + 1; - - local_irq_save(flags); - desc = get_dma_next_desc_ptr(sport->dma_rx_chan); - /* Copy the descriptor which will be damaged to backup */ - temp_desc = *desc; - desc->x_count = sport->dummy_count / 2; - desc->y_count = 0; - desc->next_desc_addr = sport->dummy_rx_desc; - local_irq_restore(flags); - /* Waiting for dummy buffer descriptor is already hooked*/ - while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) - - sizeof(struct dmasg)) != sport->dummy_rx_desc) - continue; - sport->curr_rx_desc = sport->dummy_rx_desc; - /* Restore the damaged descriptor */ - *desc = temp_desc; - - return 0; -} - -static inline int sport_rx_dma_start(struct sport_device *sport, int dummy) -{ - if (dummy) { - sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc; - sport->curr_rx_desc = sport->dummy_rx_desc; - } else - sport->curr_rx_desc = sport->dma_rx_desc; - - set_dma_next_desc_addr(sport->dma_rx_chan, sport->curr_rx_desc); - set_dma_x_count(sport->dma_rx_chan, 0); - set_dma_x_modify(sport->dma_rx_chan, 0); - set_dma_config(sport->dma_rx_chan, (DMAFLOW_LARGE | NDSIZE_9 | \ - WDSIZE_32 | WNR)); - set_dma_curr_addr(sport->dma_rx_chan, sport->curr_rx_desc->start_addr); - SSYNC(); - - return 0; -} - -static inline int sport_tx_dma_start(struct sport_device *sport, int dummy) -{ - if (dummy) { - sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc; - sport->curr_tx_desc = sport->dummy_tx_desc; - } else - sport->curr_tx_desc = sport->dma_tx_desc; - - set_dma_next_desc_addr(sport->dma_tx_chan, sport->curr_tx_desc); - set_dma_x_count(sport->dma_tx_chan, 0); - set_dma_x_modify(sport->dma_tx_chan, 0); - set_dma_config(sport->dma_tx_chan, - (DMAFLOW_LARGE | NDSIZE_9 | WDSIZE_32)); - set_dma_curr_addr(sport->dma_tx_chan, sport->curr_tx_desc->start_addr); - SSYNC(); - - return 0; -} - -int sport_rx_start(struct sport_device *sport) -{ - unsigned long flags; - pr_debug("%s enter\n", __func__); - if (sport->rx_run) - return -EBUSY; - if (sport->tx_run) { - /* tx is running, rx is not running */ - BUG_ON(sport->dma_rx_desc == NULL); - BUG_ON(sport->curr_rx_desc != sport->dummy_rx_desc); - local_irq_save(flags); - while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) - - sizeof(struct dmasg)) != sport->dummy_rx_desc) - continue; - sport->dummy_rx_desc->next_desc_addr = sport->dma_rx_desc; - local_irq_restore(flags); - sport->curr_rx_desc = sport->dma_rx_desc; - } else { - sport_tx_dma_start(sport, 1); - sport_rx_dma_start(sport, 0); - sport_start(sport); - } - - sport->rx_run = 1; - - return 0; -} -EXPORT_SYMBOL(sport_rx_start); - -int sport_rx_stop(struct sport_device *sport) -{ - pr_debug("%s enter\n", __func__); - - if (!sport->rx_run) - return 0; - if (sport->tx_run) { - /* TX dma is still running, hook the dummy buffer */ - sport_hook_rx_dummy(sport); - } else { - /* Both rx and tx dma will be stopped */ - sport_stop(sport); - sport->curr_rx_desc = NULL; - sport->curr_tx_desc = NULL; - } - - sport->rx_run = 0; - - return 0; -} -EXPORT_SYMBOL(sport_rx_stop); - -static inline int sport_hook_tx_dummy(struct sport_device *sport) -{ - struct dmasg *desc, temp_desc; - unsigned long flags; - - BUG_ON(sport->dummy_tx_desc == NULL); - BUG_ON(sport->curr_tx_desc == sport->dummy_tx_desc); - - sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc + 1; - - /* Shorten the time on last normal descriptor */ - local_irq_save(flags); - desc = get_dma_next_desc_ptr(sport->dma_tx_chan); - /* Store the descriptor which will be damaged */ - temp_desc = *desc; - desc->x_count = sport->dummy_count / 2; - desc->y_count = 0; - desc->next_desc_addr = sport->dummy_tx_desc; - local_irq_restore(flags); - /* Waiting for dummy buffer descriptor is already hooked*/ - while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - \ - sizeof(struct dmasg)) != sport->dummy_tx_desc) - continue; - sport->curr_tx_desc = sport->dummy_tx_desc; - /* Restore the damaged descriptor */ - *desc = temp_desc; - - return 0; -} - -int sport_tx_start(struct sport_device *sport) -{ - unsigned long flags; - pr_debug("%s: tx_run:%d, rx_run:%d\n", __func__, - sport->tx_run, sport->rx_run); - if (sport->tx_run) - return -EBUSY; - if (sport->rx_run) { - BUG_ON(sport->dma_tx_desc == NULL); - BUG_ON(sport->curr_tx_desc != sport->dummy_tx_desc); - /* Hook the normal buffer descriptor */ - local_irq_save(flags); - while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) - - sizeof(struct dmasg)) != sport->dummy_tx_desc) - continue; - sport->dummy_tx_desc->next_desc_addr = sport->dma_tx_desc; - local_irq_restore(flags); - sport->curr_tx_desc = sport->dma_tx_desc; - } else { - - sport_tx_dma_start(sport, 0); - /* Let rx dma run the dummy buffer */ - sport_rx_dma_start(sport, 1); - sport_start(sport); - } - sport->tx_run = 1; - return 0; -} -EXPORT_SYMBOL(sport_tx_start); - -int sport_tx_stop(struct sport_device *sport) -{ - if (!sport->tx_run) - return 0; - if (sport->rx_run) { - /* RX is still running, hook the dummy buffer */ - sport_hook_tx_dummy(sport); - } else { - /* Both rx and tx dma stopped */ - sport_stop(sport); - sport->curr_rx_desc = NULL; - sport->curr_tx_desc = NULL; - } - - sport->tx_run = 0; - - return 0; -} -EXPORT_SYMBOL(sport_tx_stop); - -static inline int compute_wdsize(size_t wdsize) -{ - switch (wdsize) { - case 1: - return WDSIZE_8; - case 2: - return WDSIZE_16; - case 4: - default: - return WDSIZE_32; - } -} - -int sport_config_rx_dma(struct sport_device *sport, void *buf, - int fragcount, size_t fragsize) -{ - unsigned int x_count; - unsigned int y_count; - unsigned int cfg; - dma_addr_t addr; - - pr_debug("%s buf:%p, frag:%d, fragsize:0x%lx\n", __func__, \ - buf, fragcount, fragsize); - - x_count = fragsize / sport->wdsize; - y_count = 0; - - /* for fragments larger than 64k words we use 2d dma, - * denote fragecount as two numbers' mutliply and both of them - * are less than 64k.*/ - if (x_count >= 0x10000) { - int i, count = x_count; - - for (i = 16; i > 0; i--) { - x_count = 1 << i; - if ((count & (x_count - 1)) == 0) { - y_count = count >> i; - if (y_count < 0x10000) - break; - } - } - if (i == 0) - return -EINVAL; - } - pr_debug("%s(x_count:0x%x, y_count:0x%x)\n", __func__, - x_count, y_count); - - if (sport->dma_rx_desc) - dma_free_coherent(NULL, sport->rx_desc_bytes, - sport->dma_rx_desc, 0); - - /* Allocate a new descritor ring as current one. */ - sport->dma_rx_desc = dma_alloc_coherent(NULL, \ - fragcount * sizeof(struct dmasg), &addr, 0); - sport->rx_desc_bytes = fragcount * sizeof(struct dmasg); - - if (!sport->dma_rx_desc) { - pr_err("Failed to allocate memory for rx desc\n"); - return -ENOMEM; - } - - sport->rx_buf = buf; - sport->rx_fragsize = fragsize; - sport->rx_frags = fragcount; - - cfg = 0x7000 | DI_EN | compute_wdsize(sport->wdsize) | WNR | \ - (DESC_ELEMENT_COUNT << 8); /* large descriptor mode */ - - if (y_count != 0) - cfg |= DMA2D; - - setup_desc(sport->dma_rx_desc, buf, fragcount, fragsize, - cfg|DMAEN, x_count, y_count, sport->wdsize); - - return 0; -} -EXPORT_SYMBOL(sport_config_rx_dma); - -int sport_config_tx_dma(struct sport_device *sport, void *buf, \ - int fragcount, size_t fragsize) -{ - unsigned int x_count; - unsigned int y_count; - unsigned int cfg; - dma_addr_t addr; - - pr_debug("%s buf:%p, fragcount:%d, fragsize:0x%lx\n", - __func__, buf, fragcount, fragsize); - - x_count = fragsize/sport->wdsize; - y_count = 0; - - /* for fragments larger than 64k words we use 2d dma, - * denote fragecount as two numbers' mutliply and both of them - * are less than 64k.*/ - if (x_count >= 0x10000) { - int i, count = x_count; - - for (i = 16; i > 0; i--) { - x_count = 1 << i; - if ((count & (x_count - 1)) == 0) { - y_count = count >> i; - if (y_count < 0x10000) - break; - } - } - if (i == 0) - return -EINVAL; - } - pr_debug("%s x_count:0x%x, y_count:0x%x\n", __func__, - x_count, y_count); - - - if (sport->dma_tx_desc) { - dma_free_coherent(NULL, sport->tx_desc_bytes, \ - sport->dma_tx_desc, 0); - } - - sport->dma_tx_desc = dma_alloc_coherent(NULL, \ - fragcount * sizeof(struct dmasg), &addr, 0); - sport->tx_desc_bytes = fragcount * sizeof(struct dmasg); - if (!sport->dma_tx_desc) { - pr_err("Failed to allocate memory for tx desc\n"); - return -ENOMEM; - } - - sport->tx_buf = buf; - sport->tx_fragsize = fragsize; - sport->tx_frags = fragcount; - cfg = 0x7000 | DI_EN | compute_wdsize(sport->wdsize) | \ - (DESC_ELEMENT_COUNT << 8); /* large descriptor mode */ - - if (y_count != 0) - cfg |= DMA2D; - - setup_desc(sport->dma_tx_desc, buf, fragcount, fragsize, - cfg|DMAEN, x_count, y_count, sport->wdsize); - - return 0; -} -EXPORT_SYMBOL(sport_config_tx_dma); - -/* setup dummy dma descriptor ring, which don't generate interrupts, - * the x_modify is set to 0 */ -static int sport_config_rx_dummy(struct sport_device *sport) -{ - struct dmasg *desc; - unsigned config; - - pr_debug("%s entered\n", __func__); - if (L1_DATA_A_LENGTH) - desc = l1_data_sram_zalloc(2 * sizeof(*desc)); - else { - dma_addr_t addr; - desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0); - memset(desc, 0, 2 * sizeof(*desc)); - } - if (desc == NULL) { - pr_err("Failed to allocate memory for dummy rx desc\n"); - return -ENOMEM; - } - sport->dummy_rx_desc = desc; - desc->start_addr = (unsigned long)sport->dummy_buf; - config = DMAFLOW_LARGE | NDSIZE_9 | compute_wdsize(sport->wdsize) - | WNR | DMAEN; - desc->cfg = config; - desc->x_count = sport->dummy_count/sport->wdsize; - desc->x_modify = sport->wdsize; - desc->y_count = 0; - desc->y_modify = 0; - memcpy(desc+1, desc, sizeof(*desc)); - desc->next_desc_addr = desc + 1; - desc[1].next_desc_addr = desc; - return 0; -} - -static int sport_config_tx_dummy(struct sport_device *sport) -{ - struct dmasg *desc; - unsigned int config; - - pr_debug("%s entered\n", __func__); - - if (L1_DATA_A_LENGTH) - desc = l1_data_sram_zalloc(2 * sizeof(*desc)); - else { - dma_addr_t addr; - desc = dma_alloc_coherent(NULL, 2 * sizeof(*desc), &addr, 0); - memset(desc, 0, 2 * sizeof(*desc)); - } - if (!desc) { - pr_err("Failed to allocate memory for dummy tx desc\n"); - return -ENOMEM; - } - sport->dummy_tx_desc = desc; - desc->start_addr = (unsigned long)sport->dummy_buf + \ - sport->dummy_count; - config = DMAFLOW_LARGE | NDSIZE_9 | - compute_wdsize(sport->wdsize) | DMAEN; - desc->cfg = config; - desc->x_count = sport->dummy_count/sport->wdsize; - desc->x_modify = sport->wdsize; - desc->y_count = 0; - desc->y_modify = 0; - memcpy(desc+1, desc, sizeof(*desc)); - desc->next_desc_addr = desc + 1; - desc[1].next_desc_addr = desc; - return 0; -} - -unsigned long sport_curr_offset_rx(struct sport_device *sport) -{ - unsigned long curr = get_dma_curr_addr(sport->dma_rx_chan); - - return (unsigned char *)curr - sport->rx_buf; -} -EXPORT_SYMBOL(sport_curr_offset_rx); - -unsigned long sport_curr_offset_tx(struct sport_device *sport) -{ - unsigned long curr = get_dma_curr_addr(sport->dma_tx_chan); - - return (unsigned char *)curr - sport->tx_buf; -} -EXPORT_SYMBOL(sport_curr_offset_tx); - -void sport_incfrag(struct sport_device *sport, int *frag, int tx) -{ - ++(*frag); - if (tx == 1 && *frag == sport->tx_frags) - *frag = 0; - - if (tx == 0 && *frag == sport->rx_frags) - *frag = 0; -} -EXPORT_SYMBOL(sport_incfrag); - -void sport_decfrag(struct sport_device *sport, int *frag, int tx) -{ - --(*frag); - if (tx == 1 && *frag == 0) - *frag = sport->tx_frags; - - if (tx == 0 && *frag == 0) - *frag = sport->rx_frags; -} -EXPORT_SYMBOL(sport_decfrag); - -static int sport_check_status(struct sport_device *sport, - unsigned int *sport_stat, - unsigned int *rx_stat, - unsigned int *tx_stat) -{ - int status = 0; - - if (sport_stat) { - SSYNC(); - status = sport->regs->stat; - if (status & (TOVF|TUVF|ROVF|RUVF)) - sport->regs->stat = (status & (TOVF|TUVF|ROVF|RUVF)); - SSYNC(); - *sport_stat = status; - } - - if (rx_stat) { - SSYNC(); - status = get_dma_curr_irqstat(sport->dma_rx_chan); - if (status & (DMA_DONE|DMA_ERR)) - clear_dma_irqstat(sport->dma_rx_chan); - SSYNC(); - *rx_stat = status; - } - - if (tx_stat) { - SSYNC(); - status = get_dma_curr_irqstat(sport->dma_tx_chan); - if (status & (DMA_DONE|DMA_ERR)) - clear_dma_irqstat(sport->dma_tx_chan); - SSYNC(); - *tx_stat = status; - } - - return 0; -} - -int sport_dump_stat(struct sport_device *sport, char *buf, size_t len) -{ - int ret; - - ret = snprintf(buf, len, - "sts: 0x%04x\n" - "rx dma %d sts: 0x%04x tx dma %d sts: 0x%04x\n", - sport->regs->stat, - sport->dma_rx_chan, - get_dma_curr_irqstat(sport->dma_rx_chan), - sport->dma_tx_chan, - get_dma_curr_irqstat(sport->dma_tx_chan)); - buf += ret; - len -= ret; - - ret += snprintf(buf, len, - "curr_rx_desc:0x%p, curr_tx_desc:0x%p\n" - "dma_rx_desc:0x%p, dma_tx_desc:0x%p\n" - "dummy_rx_desc:0x%p, dummy_tx_desc:0x%p\n", - sport->curr_rx_desc, sport->curr_tx_desc, - sport->dma_rx_desc, sport->dma_tx_desc, - sport->dummy_rx_desc, sport->dummy_tx_desc); - - return ret; -} - -static irqreturn_t rx_handler(int irq, void *dev_id) -{ - unsigned int rx_stat; - struct sport_device *sport = dev_id; - - pr_debug("%s enter\n", __func__); - sport_check_status(sport, NULL, &rx_stat, NULL); - if (!(rx_stat & DMA_DONE)) - pr_err("rx dma is already stopped\n"); - - if (sport->rx_callback) { - sport->rx_callback(sport->rx_data); - return IRQ_HANDLED; - } - - return IRQ_NONE; -} - -static irqreturn_t tx_handler(int irq, void *dev_id) -{ - unsigned int tx_stat; - struct sport_device *sport = dev_id; - pr_debug("%s enter\n", __func__); - sport_check_status(sport, NULL, NULL, &tx_stat); - if (!(tx_stat & DMA_DONE)) { - pr_err("tx dma is already stopped\n"); - return IRQ_HANDLED; - } - if (sport->tx_callback) { - sport->tx_callback(sport->tx_data); - return IRQ_HANDLED; - } - - return IRQ_NONE; -} - -static irqreturn_t err_handler(int irq, void *dev_id) -{ - unsigned int status = 0; - struct sport_device *sport = dev_id; - - pr_debug("%s\n", __func__); - if (sport_check_status(sport, &status, NULL, NULL)) { - pr_err("error checking status ??"); - return IRQ_NONE; - } - - if (status & (TOVF|TUVF|ROVF|RUVF)) { - pr_info("sport status error:%s%s%s%s\n", - status & TOVF ? " TOVF" : "", - status & TUVF ? " TUVF" : "", - status & ROVF ? " ROVF" : "", - status & RUVF ? " RUVF" : ""); - if (status & TOVF || status & TUVF) { - disable_dma(sport->dma_tx_chan); - if (sport->tx_run) - sport_tx_dma_start(sport, 0); - else - sport_tx_dma_start(sport, 1); - enable_dma(sport->dma_tx_chan); - } else { - disable_dma(sport->dma_rx_chan); - if (sport->rx_run) - sport_rx_dma_start(sport, 0); - else - sport_rx_dma_start(sport, 1); - enable_dma(sport->dma_rx_chan); - } - } - status = sport->regs->stat; - if (status & (TOVF|TUVF|ROVF|RUVF)) - sport->regs->stat = (status & (TOVF|TUVF|ROVF|RUVF)); - SSYNC(); - - if (sport->err_callback) - sport->err_callback(sport->err_data); - - return IRQ_HANDLED; -} - -int sport_set_rx_callback(struct sport_device *sport, - void (*rx_callback)(void *), void *rx_data) -{ - BUG_ON(rx_callback == NULL); - sport->rx_callback = rx_callback; - sport->rx_data = rx_data; - - return 0; -} -EXPORT_SYMBOL(sport_set_rx_callback); - -int sport_set_tx_callback(struct sport_device *sport, - void (*tx_callback)(void *), void *tx_data) -{ - BUG_ON(tx_callback == NULL); - sport->tx_callback = tx_callback; - sport->tx_data = tx_data; - - return 0; -} -EXPORT_SYMBOL(sport_set_tx_callback); - -int sport_set_err_callback(struct sport_device *sport, - void (*err_callback)(void *), void *err_data) -{ - BUG_ON(err_callback == NULL); - sport->err_callback = err_callback; - sport->err_data = err_data; - - return 0; -} -EXPORT_SYMBOL(sport_set_err_callback); - -static int sport_config_pdev(struct platform_device *pdev, struct sport_param *param) -{ - /* Extract settings from platform data */ - struct device *dev = &pdev->dev; - struct bfin_snd_platform_data *pdata = dev->platform_data; - struct resource *res; - - param->num = pdev->id; - - if (!pdata) { - dev_err(dev, "no platform_data\n"); - return -ENODEV; - } - param->pin_req = pdata->pin_req; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "no MEM resource\n"); - return -ENODEV; - } - param->regs = (struct sport_register *)res->start; - - /* first RX, then TX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(dev, "no rx DMA resource\n"); - return -ENODEV; - } - param->dma_rx_chan = res->start; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(dev, "no tx DMA resource\n"); - return -ENODEV; - } - param->dma_tx_chan = res->start; - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "no irq resource\n"); - return -ENODEV; - } - param->err_irq = res->start; - - return 0; -} - -struct sport_device *sport_init(struct platform_device *pdev, - unsigned int wdsize, unsigned int dummy_count, size_t priv_size) -{ - struct device *dev = &pdev->dev; - struct sport_param param; - struct sport_device *sport; - int ret; - - dev_dbg(dev, "%s enter\n", __func__); - - param.wdsize = wdsize; - param.dummy_count = dummy_count; - BUG_ON(param.wdsize == 0 || param.dummy_count == 0); - - ret = sport_config_pdev(pdev, ¶m); - if (ret) - return NULL; - - if (peripheral_request_list(param.pin_req, "soc-audio")) { - dev_err(dev, "requesting Peripherals failed\n"); - return NULL; - } - - sport = kzalloc(sizeof(*sport), GFP_KERNEL); - if (!sport) { - dev_err(dev, "failed to allocate for sport device\n"); - goto __init_err0; - } - - sport->num = param.num; - sport->dma_rx_chan = param.dma_rx_chan; - sport->dma_tx_chan = param.dma_tx_chan; - sport->err_irq = param.err_irq; - sport->regs = param.regs; - sport->pin_req = param.pin_req; - - if (request_dma(sport->dma_rx_chan, "SPORT RX Data") == -EBUSY) { - dev_err(dev, "failed to request RX dma %d\n", sport->dma_rx_chan); - goto __init_err1; - } - if (set_dma_callback(sport->dma_rx_chan, rx_handler, sport) != 0) { - dev_err(dev, "failed to request RX irq %d\n", sport->dma_rx_chan); - goto __init_err2; - } - - if (request_dma(sport->dma_tx_chan, "SPORT TX Data") == -EBUSY) { - dev_err(dev, "failed to request TX dma %d\n", sport->dma_tx_chan); - goto __init_err2; - } - - if (set_dma_callback(sport->dma_tx_chan, tx_handler, sport) != 0) { - dev_err(dev, "failed to request TX irq %d\n", sport->dma_tx_chan); - goto __init_err3; - } - - if (request_irq(sport->err_irq, err_handler, IRQF_SHARED, "SPORT err", - sport) < 0) { - dev_err(dev, "failed to request err irq %d\n", sport->err_irq); - goto __init_err3; - } - - dev_info(dev, "dma rx:%d tx:%d, err irq:%d, regs:%p\n", - sport->dma_rx_chan, sport->dma_tx_chan, - sport->err_irq, sport->regs); - - sport->wdsize = param.wdsize; - sport->dummy_count = param.dummy_count; - - sport->private_data = kzalloc(priv_size, GFP_KERNEL); - if (!sport->private_data) { - dev_err(dev, "could not alloc priv data %zu bytes\n", priv_size); - goto __init_err4; - } - - if (L1_DATA_A_LENGTH) - sport->dummy_buf = l1_data_sram_zalloc(param.dummy_count * 2); - else - sport->dummy_buf = kzalloc(param.dummy_count * 2, GFP_KERNEL); - if (sport->dummy_buf == NULL) { - dev_err(dev, "failed to allocate dummy buffer\n"); - goto __error1; - } - - ret = sport_config_rx_dummy(sport); - if (ret) { - dev_err(dev, "failed to config rx dummy ring\n"); - goto __error2; - } - ret = sport_config_tx_dummy(sport); - if (ret) { - dev_err(dev, "failed to config tx dummy ring\n"); - goto __error3; - } - - platform_set_drvdata(pdev, sport); - - return sport; -__error3: - if (L1_DATA_A_LENGTH) - l1_data_sram_free(sport->dummy_rx_desc); - else - dma_free_coherent(NULL, 2*sizeof(struct dmasg), - sport->dummy_rx_desc, 0); -__error2: - if (L1_DATA_A_LENGTH) - l1_data_sram_free(sport->dummy_buf); - else - kfree(sport->dummy_buf); -__error1: - kfree(sport->private_data); -__init_err4: - free_irq(sport->err_irq, sport); -__init_err3: - free_dma(sport->dma_tx_chan); -__init_err2: - free_dma(sport->dma_rx_chan); -__init_err1: - kfree(sport); -__init_err0: - peripheral_free_list(param.pin_req); - return NULL; -} -EXPORT_SYMBOL(sport_init); - -void sport_done(struct sport_device *sport) -{ - if (sport == NULL) - return; - - sport_stop(sport); - if (sport->dma_rx_desc) - dma_free_coherent(NULL, sport->rx_desc_bytes, - sport->dma_rx_desc, 0); - if (sport->dma_tx_desc) - dma_free_coherent(NULL, sport->tx_desc_bytes, - sport->dma_tx_desc, 0); - -#if L1_DATA_A_LENGTH != 0 - l1_data_sram_free(sport->dummy_rx_desc); - l1_data_sram_free(sport->dummy_tx_desc); - l1_data_sram_free(sport->dummy_buf); -#else - dma_free_coherent(NULL, 2*sizeof(struct dmasg), - sport->dummy_rx_desc, 0); - dma_free_coherent(NULL, 2*sizeof(struct dmasg), - sport->dummy_tx_desc, 0); - kfree(sport->dummy_buf); -#endif - free_dma(sport->dma_rx_chan); - free_dma(sport->dma_tx_chan); - free_irq(sport->err_irq, sport); - - kfree(sport->private_data); - peripheral_free_list(sport->pin_req); - kfree(sport); -} -EXPORT_SYMBOL(sport_done); - -/* -* It is only used to send several bytes when dma is not enabled - * sport controller is configured but not enabled. - * Multichannel cannot works with pio mode */ -/* Used by ac97 to write and read codec register */ -int sport_send_and_recv(struct sport_device *sport, u8 *out_data, \ - u8 *in_data, int len) -{ - unsigned short dma_config; - unsigned short status; - unsigned long flags; - unsigned long wait = 0; - - pr_debug("%s enter, out_data:%p, in_data:%p len:%d\n", \ - __func__, out_data, in_data, len); - pr_debug("tcr1:0x%04x, tcr2:0x%04x, tclkdiv:0x%04x, tfsdiv:0x%04x\n" - "mcmc1:0x%04x, mcmc2:0x%04x\n", - sport->regs->tcr1, sport->regs->tcr2, - sport->regs->tclkdiv, sport->regs->tfsdiv, - sport->regs->mcmc1, sport->regs->mcmc2); - flush_dcache_range((unsigned)out_data, (unsigned)(out_data + len)); - - /* Enable tx dma */ - dma_config = (RESTART | WDSIZE_16 | DI_EN); - set_dma_start_addr(sport->dma_tx_chan, (unsigned long)out_data); - set_dma_x_count(sport->dma_tx_chan, len/2); - set_dma_x_modify(sport->dma_tx_chan, 2); - set_dma_config(sport->dma_tx_chan, dma_config); - enable_dma(sport->dma_tx_chan); - - if (in_data != NULL) { - invalidate_dcache_range((unsigned)in_data, \ - (unsigned)(in_data + len)); - /* Enable rx dma */ - dma_config = (RESTART | WDSIZE_16 | WNR | DI_EN); - set_dma_start_addr(sport->dma_rx_chan, (unsigned long)in_data); - set_dma_x_count(sport->dma_rx_chan, len/2); - set_dma_x_modify(sport->dma_rx_chan, 2); - set_dma_config(sport->dma_rx_chan, dma_config); - enable_dma(sport->dma_rx_chan); - } - - local_irq_save(flags); - sport->regs->tcr1 |= TSPEN; - sport->regs->rcr1 |= RSPEN; - SSYNC(); - - status = get_dma_curr_irqstat(sport->dma_tx_chan); - while (status & DMA_RUN) { - udelay(1); - status = get_dma_curr_irqstat(sport->dma_tx_chan); - pr_debug("DMA status:0x%04x\n", status); - if (wait++ > 100) - goto __over; - } - status = sport->regs->stat; - wait = 0; - - while (!(status & TXHRE)) { - pr_debug("sport status:0x%04x\n", status); - udelay(1); - status = *(unsigned short *)&sport->regs->stat; - if (wait++ > 1000) - goto __over; - } - /* Wait for the last byte sent out */ - udelay(20); - pr_debug("sport status:0x%04x\n", status); - -__over: - sport->regs->tcr1 &= ~TSPEN; - sport->regs->rcr1 &= ~RSPEN; - SSYNC(); - disable_dma(sport->dma_tx_chan); - /* Clear the status */ - clear_dma_irqstat(sport->dma_tx_chan); - if (in_data != NULL) { - disable_dma(sport->dma_rx_chan); - clear_dma_irqstat(sport->dma_rx_chan); - } - SSYNC(); - local_irq_restore(flags); - - return 0; -} -EXPORT_SYMBOL(sport_send_and_recv); - -MODULE_AUTHOR("Roy Huang"); -MODULE_DESCRIPTION("SPORT driver for ADI Blackfin"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.h b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.h deleted file mode 100644 index 5ab60bd6..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-sport.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * File: bf5xx_sport.h - * Based on: - * Author: Roy Huang - * - * Created: - * Description: - * - * Copyright 2004-2007 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#ifndef __BF5XX_SPORT_H__ -#define __BF5XX_SPORT_H__ - -#include -#include -#include -#include -#include -#include - -#define DESC_ELEMENT_COUNT 9 - -struct sport_device { - int num; - int dma_rx_chan; - int dma_tx_chan; - int err_irq; - const unsigned short *pin_req; - struct sport_register *regs; - - unsigned char *rx_buf; - unsigned char *tx_buf; - unsigned int rx_fragsize; - unsigned int tx_fragsize; - unsigned int rx_frags; - unsigned int tx_frags; - unsigned int wdsize; - - /* for dummy dma transfer */ - void *dummy_buf; - unsigned int dummy_count; - - /* DMA descriptor ring head of current audio stream*/ - struct dmasg *dma_rx_desc; - struct dmasg *dma_tx_desc; - unsigned int rx_desc_bytes; - unsigned int tx_desc_bytes; - - unsigned int rx_run:1; /* rx is running */ - unsigned int tx_run:1; /* tx is running */ - - struct dmasg *dummy_rx_desc; - struct dmasg *dummy_tx_desc; - - struct dmasg *curr_rx_desc; - struct dmasg *curr_tx_desc; - - int rx_curr_frag; - int tx_curr_frag; - - unsigned int rcr1; - unsigned int rcr2; - int rx_tdm_count; - - unsigned int tcr1; - unsigned int tcr2; - int tx_tdm_count; - - void (*rx_callback)(void *data); - void *rx_data; - void (*tx_callback)(void *data); - void *tx_data; - void (*err_callback)(void *data); - void *err_data; - unsigned char *tx_dma_buf; - unsigned char *rx_dma_buf; -#ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT - dma_addr_t tx_dma_phy; - dma_addr_t rx_dma_phy; - int tx_pos;/*pcm sample count*/ - int rx_pos; - unsigned int tx_buffer_size; - unsigned int rx_buffer_size; - int tx_delay_pos; - int once; -#endif - void *private_data; -}; - -struct sport_param { - int num; - int dma_rx_chan; - int dma_tx_chan; - int err_irq; - const unsigned short *pin_req; - struct sport_register *regs; - unsigned int wdsize; - unsigned int dummy_count; - void *private_data; -}; - -struct sport_device *sport_init(struct platform_device *pdev, - unsigned int wdsize, unsigned int dummy_count, size_t priv_size); - -void sport_done(struct sport_device *sport); - -/* first use these ...*/ - -/* note: multichannel is in units of 8 channels, tdm_count is number of channels - * NOT / 8 ! all channels are enabled by default */ -int sport_set_multichannel(struct sport_device *sport, int tdm_count, - u32 mask, int packed); - -int sport_config_rx(struct sport_device *sport, - unsigned int rcr1, unsigned int rcr2, - unsigned int clkdiv, unsigned int fsdiv); - -int sport_config_tx(struct sport_device *sport, - unsigned int tcr1, unsigned int tcr2, - unsigned int clkdiv, unsigned int fsdiv); - -/* ... then these: */ - -/* buffer size (in bytes) == fragcount * fragsize_bytes */ - -/* this is not a very general api, it sets the dma to 2d autobuffer mode */ - -int sport_config_rx_dma(struct sport_device *sport, void *buf, - int fragcount, size_t fragsize_bytes); - -int sport_config_tx_dma(struct sport_device *sport, void *buf, - int fragcount, size_t fragsize_bytes); - -int sport_tx_start(struct sport_device *sport); -int sport_tx_stop(struct sport_device *sport); -int sport_rx_start(struct sport_device *sport); -int sport_rx_stop(struct sport_device *sport); - -/* for use in interrupt handler */ -unsigned long sport_curr_offset_rx(struct sport_device *sport); -unsigned long sport_curr_offset_tx(struct sport_device *sport); - -void sport_incfrag(struct sport_device *sport, int *frag, int tx); -void sport_decfrag(struct sport_device *sport, int *frag, int tx); - -int sport_set_rx_callback(struct sport_device *sport, - void (*rx_callback)(void *), void *rx_data); -int sport_set_tx_callback(struct sport_device *sport, - void (*tx_callback)(void *), void *tx_data); -int sport_set_err_callback(struct sport_device *sport, - void (*err_callback)(void *), void *err_data); - -int sport_send_and_recv(struct sport_device *sport, u8 *out_data, \ - u8 *in_data, int len); -#endif /* BF53X_SPORT_H */ diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ssm2602.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ssm2602.c deleted file mode 100644 index b39ad356..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-ssm2602.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ssm2602.c - * Author: Cliff Cai - * - * Created: Tue June 06 2008 - * Description: board driver for SSM2602 sound chip - * - * Modified: - * Copyright 2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include "../codecs/ssm2602.h" -#include "bf5xx-sport.h" -#include "bf5xx-i2s-pcm.h" - -static struct snd_soc_card bf5xx_ssm2602; - -static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - unsigned int clk = 0; - int ret = 0; - - pr_debug("%s rate %d format %x\n", __func__, params_rate(params), - params_format(params)); - /* - * If you are using a crystal source which frequency is not 12MHz - * then modify the below case statement with frequency of the crystal. - * - * If you are using the SPORT to generate clocking then this is - * where to do it. - */ - - switch (params_rate(params)) { - case 8000: - case 16000: - case 48000: - case 96000: - case 11025: - case 22050: - case 44100: - clk = 12000000; - break; - } - - ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk, - SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops bf5xx_ssm2602_ops = { - .hw_params = bf5xx_ssm2602_hw_params, -}; - -/* CODEC is master for BCLK and LRC in this configuration. */ -#define BF5XX_SSM2602_DAIFMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ - SND_SOC_DAIFMT_CBM_CFM) - -static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = { - { - .name = "ssm2602", - .stream_name = "SSM2602", - .cpu_dai_name = "bfin-i2s.0", - .codec_dai_name = "ssm2602-hifi", - .platform_name = "bfin-i2s-pcm-audio", - .codec_name = "ssm2602.0-001b", - .ops = &bf5xx_ssm2602_ops, - .dai_fmt = BF5XX_SSM2602_DAIFMT, - }, - { - .name = "ssm2602", - .stream_name = "SSM2602", - .cpu_dai_name = "bfin-i2s.1", - .codec_dai_name = "ssm2602-hifi", - .platform_name = "bfin-i2s-pcm-audio", - .codec_name = "ssm2602.0-001b", - .ops = &bf5xx_ssm2602_ops, - .dai_fmt = BF5XX_SSM2602_DAIFMT, - }, -}; - -static struct snd_soc_card bf5xx_ssm2602 = { - .name = "bfin-ssm2602", - .owner = THIS_MODULE, - .dai_link = &bf5xx_ssm2602_dai[CONFIG_SND_BF5XX_SPORT_NUM], - .num_links = 1, -}; - -static struct platform_device *bf5xx_ssm2602_snd_device; - -static int __init bf5xx_ssm2602_init(void) -{ - int ret; - - pr_debug("%s enter\n", __func__); - bf5xx_ssm2602_snd_device = platform_device_alloc("soc-audio", -1); - if (!bf5xx_ssm2602_snd_device) - return -ENOMEM; - - platform_set_drvdata(bf5xx_ssm2602_snd_device, &bf5xx_ssm2602); - ret = platform_device_add(bf5xx_ssm2602_snd_device); - - if (ret) - platform_device_put(bf5xx_ssm2602_snd_device); - - return ret; -} - -static void __exit bf5xx_ssm2602_exit(void) -{ - pr_debug("%s enter\n", __func__); - platform_device_unregister(bf5xx_ssm2602_snd_device); -} - -module_init(bf5xx_ssm2602_init); -module_exit(bf5xx_ssm2602_exit); - -/* Module information */ -MODULE_AUTHOR("Cliff Cai"); -MODULE_DESCRIPTION("ALSA SoC SSM2602 BF527-EZKIT"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.c deleted file mode 100644 index 254490cf..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-tdm-pcm.c - * Author: Barry Song - * - * Created: Tue June 06 2009 - * Description: DMA driver for tdm codec - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "bf5xx-tdm-pcm.h" -#include "bf5xx-tdm.h" -#include "bf5xx-sport.h" - -#define PCM_BUFFER_MAX 0x8000 -#define FRAGMENT_SIZE_MIN (4*1024) -#define FRAGMENTS_MIN 2 -#define FRAGMENTS_MAX 32 - -static void bf5xx_dma_irq(void *data) -{ - struct snd_pcm_substream *pcm = data; - snd_pcm_period_elapsed(pcm); -} - -static const struct snd_pcm_hardware bf5xx_pcm_hardware = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_48000, - .channels_min = 2, - .channels_max = 8, - .buffer_bytes_max = PCM_BUFFER_MAX, - .period_bytes_min = FRAGMENT_SIZE_MIN, - .period_bytes_max = PCM_BUFFER_MAX/2, - .periods_min = FRAGMENTS_MIN, - .periods_max = FRAGMENTS_MAX, -}; - -static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - size_t size = bf5xx_pcm_hardware.buffer_bytes_max; - snd_pcm_lib_malloc_pages(substream, size * 4); - - return 0; -} - -static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - - return 0; -} - -static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size); - - fragsize_bytes /= runtime->channels; - /* inflate the fragsize to match the dma width of SPORT */ - fragsize_bytes *= 8; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - sport_set_tx_callback(sport, bf5xx_dma_irq, substream); - sport_config_tx_dma(sport, runtime->dma_area, - runtime->periods, fragsize_bytes); - } else { - sport_set_rx_callback(sport, bf5xx_dma_irq, substream); - sport_config_rx_dma(sport, runtime->dma_area, - runtime->periods, fragsize_bytes); - } - - return 0; -} - -static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_tx_start(sport); - else - sport_rx_start(sport); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_tx_stop(sport); - else - sport_rx_stop(sport); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - unsigned int diff; - snd_pcm_uframes_t frames; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - diff = sport_curr_offset_tx(sport); - frames = diff / (8*4); /* 32 bytes per frame */ - } else { - diff = sport_curr_offset_rx(sport); - frames = diff / (8*4); - } - return frames; -} - -static int bf5xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dma_buffer *buf = &substream->dma_buffer; - - int ret = 0; - - snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - if (sport_handle != NULL) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_handle->tx_buf = buf->area; - else - sport_handle->rx_buf = buf->area; - - runtime->private_data = sport_handle; - } else { - pr_err("sport_handle is NULL\n"); - ret = -ENODEV; - } -out: - return ret; -} - -static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - struct bf5xx_tdm_port *tdm_port = sport->private_data; - unsigned int *src; - unsigned int *dst; - int i; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - src = buf; - dst = (unsigned int *)substream->runtime->dma_area; - - dst += pos * 8; - while (count--) { - for (i = 0; i < substream->runtime->channels; i++) - *(dst + tdm_port->tx_map[i]) = *src++; - dst += 8; - } - } else { - src = (unsigned int *)substream->runtime->dma_area; - dst = buf; - - src += pos * 8; - while (count--) { - for (i = 0; i < substream->runtime->channels; i++) - *dst++ = *(src + tdm_port->rx_map[i]); - src += 8; - } - } - - return 0; -} - -static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) -{ - unsigned char *buf = substream->runtime->dma_area; - buf += pos * 8 * 4; - memset(buf, '\0', count * 8 * 4); - - return 0; -} - - -struct snd_pcm_ops bf5xx_pcm_tdm_ops = { - .open = bf5xx_pcm_open, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = bf5xx_pcm_hw_params, - .hw_free = bf5xx_pcm_hw_free, - .prepare = bf5xx_pcm_prepare, - .trigger = bf5xx_pcm_trigger, - .pointer = bf5xx_pcm_pointer, - .copy = bf5xx_pcm_copy, - .silence = bf5xx_pcm_silence, -}; - -static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = bf5xx_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size * 4, - &buf->addr, GFP_KERNEL); - if (!buf->area) { - pr_err("Failed to allocate dma memory - Please increase uncached DMA memory region\n"); - return -ENOMEM; - } - buf->bytes = size; - - return 0; -} - -static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_coherent(NULL, buf->bytes, buf->area, 0); - buf->area = NULL; - } -} - -static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); - -static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &bf5xx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } -out: - return ret; -} - -static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = { - .ops = &bf5xx_pcm_tdm_ops, - .pcm_new = bf5xx_pcm_tdm_new, - .pcm_free = bf5xx_pcm_free_dma_buffers, -}; - -static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform); -} - -static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver bfin_tdm_driver = { - .driver = { - .name = "bfin-tdm-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = bf5xx_soc_platform_probe, - .remove = __devexit_p(bf5xx_soc_platform_remove), -}; - -module_platform_driver(bfin_tdm_driver); - -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.h b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.h deleted file mode 100644 index 7f8cc01c..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm-pcm.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin - * - * Copyright 2009 Analog Device Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_TDM_PCM_H -#define _BF5XX_TDM_PCM_H - -struct bf5xx_pcm_dma_params { - char *name; /* stream identifier */ -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.c b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.c deleted file mode 100644 index 594f8821..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-tdm.c - * Author: Barry Song - * - * Created: Thurs June 04 2009 - * Description: Blackfin I2S(TDM) CPU DAI driver - * Even though TDM mode can be as part of I2S DAI, but there - * are so much difference in configuration and data flow, - * it's very ugly to integrate I2S and TDM into a module - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "bf5xx-sport.h" -#include "bf5xx-tdm.h" - -static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - int ret = 0; - - /* interface format:support TDM,slave mode */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - break; - default: - printk(KERN_ERR "%s: Unknown DAI format type\n", __func__); - ret = -EINVAL; - break; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBM_CFS: - case SND_SOC_DAIFMT_CBS_CFM: - ret = -EINVAL; - break; - default: - printk(KERN_ERR "%s: Unknown DAI master type\n", __func__); - ret = -EINVAL; - break; - } - - return ret; -} - -static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); - struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; - int ret = 0; - - bf5xx_tdm->tcr2 &= ~0x1f; - bf5xx_tdm->rcr2 &= ~0x1f; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S32_LE: - bf5xx_tdm->tcr2 |= 31; - bf5xx_tdm->rcr2 |= 31; - sport_handle->wdsize = 4; - break; - /* at present, we only support 32bit transfer */ - default: - pr_err("not supported PCM format yet\n"); - return -EINVAL; - break; - } - - if (!bf5xx_tdm->configured) { - /* - * TX and RX are not independent,they are enabled at the - * same time, even if only one side is running. So, we - * need to configure both of them at the time when the first - * stream is opened. - * - * CPU DAI:slave mode. - */ - ret = sport_config_rx(sport_handle, bf5xx_tdm->rcr1, - bf5xx_tdm->rcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - ret = sport_config_tx(sport_handle, bf5xx_tdm->tcr1, - bf5xx_tdm->tcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - bf5xx_tdm->configured = 1; - } - - return 0; -} - -static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); - struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; - - /* No active stream, SPORT is allowed to be configured again. */ - if (!dai->active) - bf5xx_tdm->configured = 0; -} - -static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, - unsigned int tx_num, unsigned int *tx_slot, - unsigned int rx_num, unsigned int *rx_slot) -{ - struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); - struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; - int i; - unsigned int slot; - unsigned int tx_mapped = 0, rx_mapped = 0; - - if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) || - (rx_num > BFIN_TDM_DAI_MAX_SLOTS)) - return -EINVAL; - - for (i = 0; i < tx_num; i++) { - slot = tx_slot[i]; - if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && - (!(tx_mapped & (1 << slot)))) { - bf5xx_tdm->tx_map[i] = slot; - tx_mapped |= 1 << slot; - } else - return -EINVAL; - } - for (i = 0; i < rx_num; i++) { - slot = rx_slot[i]; - if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && - (!(rx_mapped & (1 << slot)))) { - bf5xx_tdm->rx_map[i] = slot; - rx_mapped |= 1 << slot; - } else - return -EINVAL; - } - - return 0; -} - -#ifdef CONFIG_PM -static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) -{ - struct sport_device *sport = snd_soc_dai_get_drvdata(dai); - - if (dai->playback_active) - sport_tx_stop(sport); - if (dai->capture_active) - sport_rx_stop(sport); - - /* isolate sync/clock pins from codec while sports resume */ - peripheral_free_list(sport->pin_req); - - return 0; -} - -static int bf5xx_tdm_resume(struct snd_soc_dai *dai) -{ - int ret; - struct sport_device *sport = snd_soc_dai_get_drvdata(dai); - - ret = sport_set_multichannel(sport, 8, 0xFF, 1); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - ret = sport_config_rx(sport, 0, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - ret = sport_config_tx(sport, 0, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - peripheral_request_list(sport->pin_req, "soc-audio"); - - return 0; -} - -#else -#define bf5xx_tdm_suspend NULL -#define bf5xx_tdm_resume NULL -#endif - -static const struct snd_soc_dai_ops bf5xx_tdm_dai_ops = { - .hw_params = bf5xx_tdm_hw_params, - .set_fmt = bf5xx_tdm_set_dai_fmt, - .shutdown = bf5xx_tdm_shutdown, - .set_channel_map = bf5xx_tdm_set_channel_map, -}; - -static struct snd_soc_dai_driver bf5xx_tdm_dai = { - .suspend = bf5xx_tdm_suspend, - .resume = bf5xx_tdm_resume, - .playback = { - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE,}, - .capture = { - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE,}, - .ops = &bf5xx_tdm_dai_ops, -}; - -static int __devinit bfin_tdm_probe(struct platform_device *pdev) -{ - struct sport_device *sport_handle; - int ret; - - /* configure SPORT for TDM */ - sport_handle = sport_init(pdev, 4, 8 * sizeof(u32), - sizeof(struct bf5xx_tdm_port)); - if (!sport_handle) - return -ENODEV; - - /* SPORT works in TDM mode */ - ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = sport_config_rx(sport_handle, 0, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = sport_config_tx(sport_handle, 0, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai); - if (ret) { - pr_err("Failed to register DAI: %d\n", ret); - goto sport_config_err; - } - - return 0; - -sport_config_err: - sport_done(sport_handle); - return ret; -} - -static int __devexit bfin_tdm_remove(struct platform_device *pdev) -{ - struct sport_device *sport_handle = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - sport_done(sport_handle); - - return 0; -} - -static struct platform_driver bfin_tdm_driver = { - .probe = bfin_tdm_probe, - .remove = __devexit_p(bfin_tdm_remove), - .driver = { - .name = "bfin-tdm", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(bfin_tdm_driver); - -/* Module information */ -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("TDM driver for ADI Blackfin"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.h b/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.h deleted file mode 100644 index e986a3ea..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bf5xx-tdm.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-tdm.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_TDM_H -#define _BF5XX_TDM_H - -#define BFIN_TDM_DAI_MAX_SLOTS 8 -struct bf5xx_tdm_port { - u16 tcr1; - u16 rcr1; - u16 tcr2; - u16 rcr2; - unsigned int tx_map[BFIN_TDM_DAI_MAX_SLOTS]; - unsigned int rx_map[BFIN_TDM_DAI_MAX_SLOTS]; - int configured; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adau1373.c b/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adau1373.c deleted file mode 100644 index f3adbdbd..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adau1373.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Machine driver for EVAL-ADAU1373 on Analog Devices bfin - * evaluation boards. - * - * Copyright 2011 Analog Devices Inc. - * Author: Lars-Peter Clausen - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include - -#include "../codecs/adau1373.h" - -static const struct snd_soc_dapm_widget bfin_eval_adau1373_dapm_widgets[] = { - SND_SOC_DAPM_LINE("Line In1", NULL), - SND_SOC_DAPM_LINE("Line In2", NULL), - SND_SOC_DAPM_LINE("Line In3", NULL), - SND_SOC_DAPM_LINE("Line In4", NULL), - - SND_SOC_DAPM_LINE("Line Out1", NULL), - SND_SOC_DAPM_LINE("Line Out2", NULL), - SND_SOC_DAPM_LINE("Stereo Out", NULL), - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_HP("Earpiece", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -static const struct snd_soc_dapm_route bfin_eval_adau1373_dapm_routes[] = { - { "AIN1L", NULL, "Line In1" }, - { "AIN1R", NULL, "Line In1" }, - { "AIN2L", NULL, "Line In2" }, - { "AIN2R", NULL, "Line In2" }, - { "AIN3L", NULL, "Line In3" }, - { "AIN3R", NULL, "Line In3" }, - { "AIN4L", NULL, "Line In4" }, - { "AIN4R", NULL, "Line In4" }, - - /* MICBIAS can be connected via a jumper to the line-in jack, since w - don't know which one is going to be used, just power both. */ - { "Line In1", NULL, "MICBIAS1" }, - { "Line In2", NULL, "MICBIAS1" }, - { "Line In3", NULL, "MICBIAS1" }, - { "Line In4", NULL, "MICBIAS1" }, - { "Line In1", NULL, "MICBIAS2" }, - { "Line In2", NULL, "MICBIAS2" }, - { "Line In3", NULL, "MICBIAS2" }, - { "Line In4", NULL, "MICBIAS2" }, - - { "Line Out1", NULL, "LOUT1L" }, - { "Line Out1", NULL, "LOUT1R" }, - { "Line Out2", NULL, "LOUT2L" }, - { "Line Out2", NULL, "LOUT2R" }, - { "Headphone", NULL, "HPL" }, - { "Headphone", NULL, "HPR" }, - { "Earpiece", NULL, "EP" }, - { "Speaker", NULL, "SPKL" }, - { "Stereo Out", NULL, "SPKR" }, -}; - -static int bfin_eval_adau1373_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - int pll_rate; - - switch (params_rate(params)) { - case 48000: - case 8000: - case 12000: - case 16000: - case 24000: - case 32000: - pll_rate = 48000 * 1024; - break; - case 44100: - case 7350: - case 11025: - case 14700: - case 22050: - case 29400: - pll_rate = 44100 * 1024; - break; - default: - return -EINVAL; - } - - ret = snd_soc_dai_set_pll(codec_dai, ADAU1373_PLL1, - ADAU1373_PLL_SRC_MCLK1, 12288000, pll_rate); - if (ret) - return ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1373_CLK_SRC_PLL1, pll_rate, - SND_SOC_CLOCK_IN); - - return ret; -} - -static int bfin_eval_adau1373_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *codec_dai = rtd->codec_dai; - unsigned int pll_rate = 48000 * 1024; - int ret; - - ret = snd_soc_dai_set_pll(codec_dai, ADAU1373_PLL1, - ADAU1373_PLL_SRC_MCLK1, 12288000, pll_rate); - if (ret) - return ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1373_CLK_SRC_PLL1, pll_rate, - SND_SOC_CLOCK_IN); - - return ret; -} -static struct snd_soc_ops bfin_eval_adau1373_ops = { - .hw_params = bfin_eval_adau1373_hw_params, -}; - -static struct snd_soc_dai_link bfin_eval_adau1373_dai = { - .name = "adau1373", - .stream_name = "adau1373", - .cpu_dai_name = "bfin-i2s.0", - .codec_dai_name = "adau1373-aif1", - .platform_name = "bfin-i2s-pcm-audio", - .codec_name = "adau1373.0-001a", - .ops = &bfin_eval_adau1373_ops, - .init = bfin_eval_adau1373_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, -}; - -static struct snd_soc_card bfin_eval_adau1373 = { - .name = "bfin-eval-adau1373", - .owner = THIS_MODULE, - .dai_link = &bfin_eval_adau1373_dai, - .num_links = 1, - - .dapm_widgets = bfin_eval_adau1373_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(bfin_eval_adau1373_dapm_widgets), - .dapm_routes = bfin_eval_adau1373_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(bfin_eval_adau1373_dapm_routes), -}; - -static int bfin_eval_adau1373_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &bfin_eval_adau1373; - - card->dev = &pdev->dev; - - return snd_soc_register_card(&bfin_eval_adau1373); -} - -static int __devexit bfin_eval_adau1373_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - -static struct platform_driver bfin_eval_adau1373_driver = { - .driver = { - .name = "bfin-eval-adau1373", - .owner = THIS_MODULE, - .pm = &snd_soc_pm_ops, - }, - .probe = bfin_eval_adau1373_probe, - .remove = __devexit_p(bfin_eval_adau1373_remove), -}; - -module_platform_driver(bfin_eval_adau1373_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("ALSA SoC bfin adau1373 driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:bfin-eval-adau1373"); diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adau1701.c b/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adau1701.c deleted file mode 100644 index b0531fc9..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adau1701.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Machine driver for EVAL-ADAU1701MINIZ on Analog Devices bfin - * evaluation boards. - * - * Copyright 2011 Analog Devices Inc. - * Author: Lars-Peter Clausen - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include - -#include "../codecs/adau1701.h" - -static const struct snd_soc_dapm_widget bfin_eval_adau1701_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), -}; - -static const struct snd_soc_dapm_route bfin_eval_adau1701_dapm_routes[] = { - { "Speaker", NULL, "OUT0" }, - { "Speaker", NULL, "OUT1" }, - { "Line Out", NULL, "OUT2" }, - { "Line Out", NULL, "OUT3" }, - - { "IN0", NULL, "Line In" }, - { "IN1", NULL, "Line In" }, -}; - -static int bfin_eval_adau1701_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1701_CLK_SRC_OSC, 12288000, - SND_SOC_CLOCK_IN); - - return ret; -} - -static struct snd_soc_ops bfin_eval_adau1701_ops = { - .hw_params = bfin_eval_adau1701_hw_params, -}; - -#define BFIN_EVAL_ADAU1701_DAI_FMT (SND_SOC_DAIFMT_I2S | \ - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM) - -static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = { - { - .name = "adau1701", - .stream_name = "adau1701", - .cpu_dai_name = "bfin-i2s.0", - .codec_dai_name = "adau1701", - .platform_name = "bfin-i2s-pcm-audio", - .codec_name = "adau1701.0-0034", - .ops = &bfin_eval_adau1701_ops, - .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT, - }, - { - .name = "adau1701", - .stream_name = "adau1701", - .cpu_dai_name = "bfin-i2s.1", - .codec_dai_name = "adau1701", - .platform_name = "bfin-i2s-pcm-audio", - .codec_name = "adau1701.0-0034", - .ops = &bfin_eval_adau1701_ops, - .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT, - }, -}; - -static struct snd_soc_card bfin_eval_adau1701 = { - .name = "bfin-eval-adau1701", - .owner = THIS_MODULE, - .dai_link = &bfin_eval_adau1701_dai[CONFIG_SND_BF5XX_SPORT_NUM], - .num_links = 1, - - .dapm_widgets = bfin_eval_adau1701_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(bfin_eval_adau1701_dapm_widgets), - .dapm_routes = bfin_eval_adau1701_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(bfin_eval_adau1701_dapm_routes), -}; - -static int bfin_eval_adau1701_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &bfin_eval_adau1701; - - card->dev = &pdev->dev; - - return snd_soc_register_card(&bfin_eval_adau1701); -} - -static int __devexit bfin_eval_adau1701_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - -static struct platform_driver bfin_eval_adau1701_driver = { - .driver = { - .name = "bfin-eval-adau1701", - .owner = THIS_MODULE, - .pm = &snd_soc_pm_ops, - }, - .probe = bfin_eval_adau1701_probe, - .remove = __devexit_p(bfin_eval_adau1701_remove), -}; - -module_platform_driver(bfin_eval_adau1701_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("ALSA SoC bfin ADAU1701 driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:bfin-eval-adau1701"); diff --git a/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adav80x.c b/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adav80x.c deleted file mode 100644 index 84b09987..00000000 --- a/ANDROID_3.4.5/sound/soc/blackfin/bfin-eval-adav80x.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Machine driver for EVAL-ADAV801 and EVAL-ADAV803 on Analog Devices bfin - * evaluation boards. - * - * Copyright 2011 Analog Devices Inc. - * Author: Lars-Peter Clausen - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include - -#include "../codecs/adav80x.h" - -static const struct snd_soc_dapm_widget bfin_eval_adav80x_dapm_widgets[] = { - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), -}; - -static const struct snd_soc_dapm_route bfin_eval_adav80x_dapm_routes[] = { - { "Line Out", NULL, "VOUTL" }, - { "Line Out", NULL, "VOUTR" }, - - { "VINL", NULL, "Line In" }, - { "VINR", NULL, "Line In" }, -}; - -static int bfin_eval_adav80x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - ret = snd_soc_dai_set_pll(codec_dai, ADAV80X_PLL1, ADAV80X_PLL_SRC_XTAL, - 27000000, params_rate(params) * 256); - if (ret) - return ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_PLL1, - params_rate(params) * 256, SND_SOC_CLOCK_IN); - - return ret; -} - -static int bfin_eval_adav80x_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *codec_dai = rtd->codec_dai; - - snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK1, 0, - SND_SOC_CLOCK_OUT); - snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK2, 0, - SND_SOC_CLOCK_OUT); - snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_SYSCLK3, 0, - SND_SOC_CLOCK_OUT); - - snd_soc_dai_set_sysclk(codec_dai, ADAV80X_CLK_XTAL, 2700000, 0); - - return 0; -} - -static struct snd_soc_ops bfin_eval_adav80x_ops = { - .hw_params = bfin_eval_adav80x_hw_params, -}; - -static struct snd_soc_dai_link bfin_eval_adav80x_dais[] = { - { - .name = "adav80x", - .stream_name = "ADAV80x HiFi", - .cpu_dai_name = "bfin-i2s.0", - .codec_dai_name = "adav80x-hifi", - .platform_name = "bfin-i2s-pcm-audio", - .init = bfin_eval_adav80x_codec_init, - .ops = &bfin_eval_adav80x_ops, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - }, -}; - -static struct snd_soc_card bfin_eval_adav80x = { - .name = "bfin-eval-adav80x", - .owner = THIS_MODULE, - .dai_link = bfin_eval_adav80x_dais, - .num_links = ARRAY_SIZE(bfin_eval_adav80x_dais), - - .dapm_widgets = bfin_eval_adav80x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(bfin_eval_adav80x_dapm_widgets), - .dapm_routes = bfin_eval_adav80x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(bfin_eval_adav80x_dapm_routes), -}; - -enum bfin_eval_adav80x_type { - BFIN_EVAL_ADAV801, - BFIN_EVAL_ADAV803, -}; - -static int bfin_eval_adav80x_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &bfin_eval_adav80x; - const char *codec_name; - - switch (platform_get_device_id(pdev)->driver_data) { - case BFIN_EVAL_ADAV801: - codec_name = "spi0.1"; - break; - case BFIN_EVAL_ADAV803: - codec_name = "adav803.0-0034"; - break; - default: - return -EINVAL; - } - - bfin_eval_adav80x_dais[0].codec_name = codec_name; - - card->dev = &pdev->dev; - - return snd_soc_register_card(&bfin_eval_adav80x); -} - -static int __devexit bfin_eval_adav80x_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - -static const struct platform_device_id bfin_eval_adav80x_ids[] = { - { "bfin-eval-adav801", BFIN_EVAL_ADAV801 }, - { "bfin-eval-adav803", BFIN_EVAL_ADAV803 }, - { }, -}; -MODULE_DEVICE_TABLE(platform, bfin_eval_adav80x_ids); - -static struct platform_driver bfin_eval_adav80x_driver = { - .driver = { - .name = "bfin-eval-adav80x", - .owner = THIS_MODULE, - .pm = &snd_soc_pm_ops, - }, - .probe = bfin_eval_adav80x_probe, - .remove = __devexit_p(bfin_eval_adav80x_remove), - .id_table = bfin_eval_adav80x_ids, -}; - -module_platform_driver(bfin_eval_adav80x_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("ALSA SoC bfin adav80x driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.c b/ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.c deleted file mode 100644 index 9fd3b682..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.c +++ /dev/null @@ -1,1488 +0,0 @@ -/* - * 88pm860x-codec.c -- 88PM860x ALSA SoC Audio Driver - * - * Copyright 2010 Marvell International Ltd. - * Author: Haojian Zhuang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "88pm860x-codec.h" - -#define MAX_NAME_LEN 20 -#define REG_CACHE_SIZE 0x40 -#define REG_CACHE_BASE 0xb0 - -/* Status Register 1 (0x01) */ -#define REG_STATUS_1 0x01 -#define MIC_STATUS (1 << 7) -#define HOOK_STATUS (1 << 6) -#define HEADSET_STATUS (1 << 5) - -/* Mic Detection Register (0x37) */ -#define REG_MIC_DET 0x37 -#define CONTINUOUS_POLLING (3 << 1) -#define EN_MIC_DET (1 << 0) -#define MICDET_MASK 0x07 - -/* Headset Detection Register (0x38) */ -#define REG_HS_DET 0x38 -#define EN_HS_DET (1 << 0) - -/* Misc2 Register (0x42) */ -#define REG_MISC2 0x42 -#define AUDIO_PLL (1 << 5) -#define AUDIO_SECTION_RESET (1 << 4) -#define AUDIO_SECTION_ON (1 << 3) - -/* PCM Interface Register 2 (0xb1) */ -#define PCM_INF2_BCLK (1 << 6) /* Bit clock polarity */ -#define PCM_INF2_FS (1 << 5) /* Frame Sync polarity */ -#define PCM_INF2_MASTER (1 << 4) /* Master / Slave */ -#define PCM_INF2_18WL (1 << 3) /* 18 / 16 bits */ -#define PCM_GENERAL_I2S 0 -#define PCM_EXACT_I2S 1 -#define PCM_LEFT_I2S 2 -#define PCM_RIGHT_I2S 3 -#define PCM_SHORT_FS 4 -#define PCM_LONG_FS 5 -#define PCM_MODE_MASK 7 - -/* I2S Interface Register 4 (0xbe) */ -#define I2S_EQU_BYP (1 << 6) - -/* DAC Offset Register (0xcb) */ -#define DAC_MUTE (1 << 7) -#define MUTE_LEFT (1 << 6) -#define MUTE_RIGHT (1 << 2) - -/* ADC Analog Register 1 (0xd0) */ -#define REG_ADC_ANA_1 0xd0 -#define MIC1BIAS_MASK 0x60 - -/* Earpiece/Speaker Control Register 2 (0xda) */ -#define REG_EAR2 0xda -#define RSYNC_CHANGE (1 << 2) - -/* Audio Supplies Register 2 (0xdc) */ -#define REG_SUPPLIES2 0xdc -#define LDO15_READY (1 << 4) -#define LDO15_EN (1 << 3) -#define CPUMP_READY (1 << 2) -#define CPUMP_EN (1 << 1) -#define AUDIO_EN (1 << 0) -#define SUPPLY_MASK (LDO15_EN | CPUMP_EN | AUDIO_EN) - -/* Audio Enable Register 1 (0xdd) */ -#define ADC_MOD_RIGHT (1 << 1) -#define ADC_MOD_LEFT (1 << 0) - -/* Audio Enable Register 2 (0xde) */ -#define ADC_LEFT (1 << 5) -#define ADC_RIGHT (1 << 4) - -/* DAC Enable Register 2 (0xe1) */ -#define DAC_LEFT (1 << 5) -#define DAC_RIGHT (1 << 4) -#define MODULATOR (1 << 3) - -/* Shorts Register (0xeb) */ -#define REG_SHORTS 0xeb -#define CLR_SHORT_LO2 (1 << 7) -#define SHORT_LO2 (1 << 6) -#define CLR_SHORT_LO1 (1 << 5) -#define SHORT_LO1 (1 << 4) -#define CLR_SHORT_HS2 (1 << 3) -#define SHORT_HS2 (1 << 2) -#define CLR_SHORT_HS1 (1 << 1) -#define SHORT_HS1 (1 << 0) - -/* - * This widget should be just after DAC & PGA in DAPM power-on sequence and - * before DAC & PGA in DAPM power-off sequence. - */ -#define PM860X_DAPM_OUTPUT(wname, wevent) \ -{ .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ - .shift = 0, .invert = 0, .kcontrol_news = NULL, \ - .num_kcontrols = 0, .event = wevent, \ - .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, } - -struct pm860x_det { - struct snd_soc_jack *hp_jack; - struct snd_soc_jack *mic_jack; - int hp_det; - int mic_det; - int hook_det; - int hs_shrt; - int lo_shrt; -}; - -struct pm860x_priv { - unsigned int sysclk; - unsigned int pcmclk; - unsigned int dir; - unsigned int filter; - struct snd_soc_codec *codec; - struct i2c_client *i2c; - struct pm860x_chip *chip; - struct pm860x_det det; - - int irq[4]; - unsigned char name[4][MAX_NAME_LEN]; -}; - -/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */ -static const DECLARE_TLV_DB_SCALE(dpga_tlv, -9450, 150, 1); - -/* -9dB to 0db in 3dB steps */ -static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0); - -/* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */ -static const unsigned int mic_tlv[] = { - TLV_DB_RANGE_HEAD(5), - 0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0), - 3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0), - 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0), -}; - -/* {0, 0, 0, -6, 0, 6, 12, 18}dB */ -static const unsigned int aux_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 2, TLV_DB_SCALE_ITEM(0, 0, 0), - 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0), -}; - -/* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */ -static const unsigned int out_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1), - 4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0), - 5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0), - 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0), -}; - -static const unsigned int st_tlv[] = { - TLV_DB_RANGE_HEAD(8), - 0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0), - 2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0), - 4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0), - 6, 7, TLV_DB_SCALE_ITEM(-10351, 116, 0), - 8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0), - 10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0), - 14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0), - 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0), -}; - -/* Sidetone Gain = M * 2^(-5-N) */ -struct st_gain { - unsigned int db; - unsigned int m; - unsigned int n; -}; - -static struct st_gain st_table[] = { - {-12041, 1, 15}, {-11439, 1, 14}, {-11087, 3, 15}, {-10837, 1, 13}, - {-10643, 5, 15}, {-10485, 3, 14}, {-10351, 7, 15}, {-10235, 1, 12}, - {-10133, 9, 15}, {-10041, 5, 14}, { -9958, 11, 15}, { -9883, 3, 13}, - { -9813, 13, 15}, { -9749, 7, 14}, { -9689, 15, 15}, { -9633, 1, 11}, - { -9580, 17, 15}, { -9531, 9, 14}, { -9484, 19, 15}, { -9439, 5, 13}, - { -9397, 21, 15}, { -9356, 11, 14}, { -9318, 23, 15}, { -9281, 3, 12}, - { -9245, 25, 15}, { -9211, 13, 14}, { -9178, 27, 15}, { -9147, 7, 13}, - { -9116, 29, 15}, { -9087, 15, 14}, { -9058, 31, 15}, { -9031, 1, 10}, - { -8978, 17, 14}, { -8929, 9, 13}, { -8882, 19, 14}, { -8837, 5, 12}, - { -8795, 21, 14}, { -8754, 11, 13}, { -8716, 23, 14}, { -8679, 3, 11}, - { -8643, 25, 14}, { -8609, 13, 13}, { -8576, 27, 14}, { -8545, 7, 12}, - { -8514, 29, 14}, { -8485, 15, 13}, { -8456, 31, 14}, { -8429, 1, 9}, - { -8376, 17, 13}, { -8327, 9, 12}, { -8280, 19, 13}, { -8235, 5, 11}, - { -8193, 21, 13}, { -8152, 11, 12}, { -8114, 23, 13}, { -8077, 3, 10}, - { -8041, 25, 13}, { -8007, 13, 12}, { -7974, 27, 13}, { -7943, 7, 11}, - { -7912, 29, 13}, { -7883, 15, 12}, { -7854, 31, 13}, { -7827, 1, 8}, - { -7774, 17, 12}, { -7724, 9, 11}, { -7678, 19, 12}, { -7633, 5, 10}, - { -7591, 21, 12}, { -7550, 11, 11}, { -7512, 23, 12}, { -7475, 3, 9}, - { -7439, 25, 12}, { -7405, 13, 11}, { -7372, 27, 12}, { -7341, 7, 10}, - { -7310, 29, 12}, { -7281, 15, 11}, { -7252, 31, 12}, { -7225, 1, 7}, - { -7172, 17, 11}, { -7122, 9, 10}, { -7075, 19, 11}, { -7031, 5, 9}, - { -6989, 21, 11}, { -6948, 11, 10}, { -6910, 23, 11}, { -6873, 3, 8}, - { -6837, 25, 11}, { -6803, 13, 10}, { -6770, 27, 11}, { -6739, 7, 9}, - { -6708, 29, 11}, { -6679, 15, 10}, { -6650, 31, 11}, { -6623, 1, 6}, - { -6570, 17, 10}, { -6520, 9, 9}, { -6473, 19, 10}, { -6429, 5, 8}, - { -6386, 21, 10}, { -6346, 11, 9}, { -6307, 23, 10}, { -6270, 3, 7}, - { -6235, 25, 10}, { -6201, 13, 9}, { -6168, 27, 10}, { -6137, 7, 8}, - { -6106, 29, 10}, { -6077, 15, 9}, { -6048, 31, 10}, { -6021, 1, 5}, - { -5968, 17, 9}, { -5918, 9, 8}, { -5871, 19, 9}, { -5827, 5, 7}, - { -5784, 21, 9}, { -5744, 11, 8}, { -5705, 23, 9}, { -5668, 3, 6}, - { -5633, 25, 9}, { -5599, 13, 8}, { -5566, 27, 9}, { -5535, 7, 7}, - { -5504, 29, 9}, { -5475, 15, 8}, { -5446, 31, 9}, { -5419, 1, 4}, - { -5366, 17, 8}, { -5316, 9, 7}, { -5269, 19, 8}, { -5225, 5, 6}, - { -5182, 21, 8}, { -5142, 11, 7}, { -5103, 23, 8}, { -5066, 3, 5}, - { -5031, 25, 8}, { -4997, 13, 7}, { -4964, 27, 8}, { -4932, 7, 6}, - { -4902, 29, 8}, { -4873, 15, 7}, { -4844, 31, 8}, { -4816, 1, 3}, - { -4764, 17, 7}, { -4714, 9, 6}, { -4667, 19, 7}, { -4623, 5, 5}, - { -4580, 21, 7}, { -4540, 11, 6}, { -4501, 23, 7}, { -4464, 3, 4}, - { -4429, 25, 7}, { -4395, 13, 6}, { -4362, 27, 7}, { -4330, 7, 5}, - { -4300, 29, 7}, { -4270, 15, 6}, { -4242, 31, 7}, { -4214, 1, 2}, - { -4162, 17, 6}, { -4112, 9, 5}, { -4065, 19, 6}, { -4021, 5, 4}, - { -3978, 21, 6}, { -3938, 11, 5}, { -3899, 23, 6}, { -3862, 3, 3}, - { -3827, 25, 6}, { -3793, 13, 5}, { -3760, 27, 6}, { -3728, 7, 4}, - { -3698, 29, 6}, { -3668, 15, 5}, { -3640, 31, 6}, { -3612, 1, 1}, - { -3560, 17, 5}, { -3510, 9, 4}, { -3463, 19, 5}, { -3419, 5, 3}, - { -3376, 21, 5}, { -3336, 11, 4}, { -3297, 23, 5}, { -3260, 3, 2}, - { -3225, 25, 5}, { -3191, 13, 4}, { -3158, 27, 5}, { -3126, 7, 3}, - { -3096, 29, 5}, { -3066, 15, 4}, { -3038, 31, 5}, { -3010, 1, 0}, - { -2958, 17, 4}, { -2908, 9, 3}, { -2861, 19, 4}, { -2816, 5, 2}, - { -2774, 21, 4}, { -2734, 11, 3}, { -2695, 23, 4}, { -2658, 3, 1}, - { -2623, 25, 4}, { -2589, 13, 3}, { -2556, 27, 4}, { -2524, 7, 2}, - { -2494, 29, 4}, { -2464, 15, 3}, { -2436, 31, 4}, { -2408, 2, 0}, - { -2356, 17, 3}, { -2306, 9, 2}, { -2259, 19, 3}, { -2214, 5, 1}, - { -2172, 21, 3}, { -2132, 11, 2}, { -2093, 23, 3}, { -2056, 3, 0}, - { -2021, 25, 3}, { -1987, 13, 2}, { -1954, 27, 3}, { -1922, 7, 1}, - { -1892, 29, 3}, { -1862, 15, 2}, { -1834, 31, 3}, { -1806, 4, 0}, - { -1754, 17, 2}, { -1704, 9, 1}, { -1657, 19, 2}, { -1612, 5, 0}, - { -1570, 21, 2}, { -1530, 11, 1}, { -1491, 23, 2}, { -1454, 6, 0}, - { -1419, 25, 2}, { -1384, 13, 1}, { -1352, 27, 2}, { -1320, 7, 0}, - { -1290, 29, 2}, { -1260, 15, 1}, { -1232, 31, 2}, { -1204, 8, 0}, - { -1151, 17, 1}, { -1102, 9, 0}, { -1055, 19, 1}, { -1010, 10, 0}, - { -968, 21, 1}, { -928, 11, 0}, { -889, 23, 1}, { -852, 12, 0}, - { -816, 25, 1}, { -782, 13, 0}, { -750, 27, 1}, { -718, 14, 0}, - { -688, 29, 1}, { -658, 15, 0}, { -630, 31, 1}, { -602, 16, 0}, - { -549, 17, 0}, { -500, 18, 0}, { -453, 19, 0}, { -408, 20, 0}, - { -366, 21, 0}, { -325, 22, 0}, { -287, 23, 0}, { -250, 24, 0}, - { -214, 25, 0}, { -180, 26, 0}, { -148, 27, 0}, { -116, 28, 0}, - { -86, 29, 0}, { -56, 30, 0}, { -28, 31, 0}, { 0, 0, 0}, -}; - -static int pm860x_volatile(unsigned int reg) -{ - BUG_ON(reg >= REG_CACHE_SIZE); - - switch (reg) { - case PM860X_AUDIO_SUPPLIES_2: - return 1; - } - - return 0; -} - -static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - unsigned char *cache = codec->reg_cache; - - BUG_ON(reg >= REG_CACHE_SIZE); - - if (pm860x_volatile(reg)) - return cache[reg]; - - reg += REG_CACHE_BASE; - - return pm860x_reg_read(codec->control_data, reg); -} - -static int pm860x_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - unsigned char *cache = codec->reg_cache; - - BUG_ON(reg >= REG_CACHE_SIZE); - - if (!pm860x_volatile(reg)) - cache[reg] = (unsigned char)value; - - reg += REG_CACHE_BASE; - - return pm860x_reg_write(codec->control_data, reg, value); -} - -static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - int val[2], val2[2], i; - - val[0] = snd_soc_read(codec, reg) & 0x3f; - val[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT) >> 4) & 0xf; - val2[0] = snd_soc_read(codec, reg2) & 0x3f; - val2[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT)) & 0xf; - - for (i = 0; i < ARRAY_SIZE(st_table); i++) { - if ((st_table[i].m == val[0]) && (st_table[i].n == val[1])) - ucontrol->value.integer.value[0] = i; - if ((st_table[i].m == val2[0]) && (st_table[i].n == val2[1])) - ucontrol->value.integer.value[1] = i; - } - return 0; -} - -static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - int err; - unsigned int val, val2; - - val = ucontrol->value.integer.value[0]; - val2 = ucontrol->value.integer.value[1]; - - err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m); - if (err < 0) - return err; - err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0xf0, - st_table[val].n << 4); - if (err < 0) - return err; - - err = snd_soc_update_bits(codec, reg2, 0x3f, st_table[val2].m); - if (err < 0) - return err; - err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0x0f, - st_table[val2].n); - return err; -} - -static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - int max = mc->max, val, val2; - unsigned int mask = (1 << fls(max)) - 1; - - val = snd_soc_read(codec, reg) >> shift; - val2 = snd_soc_read(codec, reg2) >> shift; - ucontrol->value.integer.value[0] = (max - val) & mask; - ucontrol->value.integer.value[1] = (max - val2) & mask; - - return 0; -} - -static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - int err; - unsigned int val, val2, val_mask; - - val_mask = mask << shift; - val = ((max - ucontrol->value.integer.value[0]) & mask); - val2 = ((max - ucontrol->value.integer.value[1]) & mask); - - val = val << shift; - val2 = val2 << shift; - - err = snd_soc_update_bits(codec, reg, val_mask, val); - if (err < 0) - return err; - - err = snd_soc_update_bits(codec, reg2, val_mask, val2); - return err; -} - -/* DAPM Widget Events */ -/* - * A lot registers are belong to RSYNC domain. It requires enabling RSYNC bit - * after updating these registers. Otherwise, these updated registers won't - * be effective. - */ -static int pm860x_rsync_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - - /* - * In order to avoid current on the load, mute power-on and power-off - * should be transients. - * Unmute by DAC_MUTE. It should be unmuted when DAPM sequence is - * finished. - */ - snd_soc_update_bits(codec, PM860X_DAC_OFFSET, DAC_MUTE, 0); - snd_soc_update_bits(codec, PM860X_EAR_CTRL_2, - RSYNC_CHANGE, RSYNC_CHANGE); - return 0; -} - -static int pm860x_dac_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - unsigned int dac = 0; - int data; - - if (!strcmp(w->name, "Left DAC")) - dac = DAC_LEFT; - if (!strcmp(w->name, "Right DAC")) - dac = DAC_RIGHT; - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - if (dac) { - /* Auto mute in power-on sequence. */ - dac |= MODULATOR; - snd_soc_update_bits(codec, PM860X_DAC_OFFSET, - DAC_MUTE, DAC_MUTE); - snd_soc_update_bits(codec, PM860X_EAR_CTRL_2, - RSYNC_CHANGE, RSYNC_CHANGE); - /* update dac */ - snd_soc_update_bits(codec, PM860X_DAC_EN_2, - dac, dac); - } - break; - case SND_SOC_DAPM_PRE_PMD: - if (dac) { - /* Auto mute in power-off sequence. */ - snd_soc_update_bits(codec, PM860X_DAC_OFFSET, - DAC_MUTE, DAC_MUTE); - snd_soc_update_bits(codec, PM860X_EAR_CTRL_2, - RSYNC_CHANGE, RSYNC_CHANGE); - /* update dac */ - data = snd_soc_read(codec, PM860X_DAC_EN_2); - data &= ~dac; - if (!(data & (DAC_LEFT | DAC_RIGHT))) - data &= ~MODULATOR; - snd_soc_write(codec, PM860X_DAC_EN_2, data); - } - break; - } - return 0; -} - -static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"}; - -static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"}; - -static const struct soc_enum pm860x_hs1_opamp_enum = - SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts); - -static const struct soc_enum pm860x_hs2_opamp_enum = - SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts); - -static const struct soc_enum pm860x_hs1_pa_enum = - SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts); - -static const struct soc_enum pm860x_hs2_pa_enum = - SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts); - -static const struct soc_enum pm860x_lo1_opamp_enum = - SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts); - -static const struct soc_enum pm860x_lo2_opamp_enum = - SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts); - -static const struct soc_enum pm860x_lo1_pa_enum = - SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts); - -static const struct soc_enum pm860x_lo2_pa_enum = - SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts); - -static const struct soc_enum pm860x_spk_pa_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts); - -static const struct soc_enum pm860x_ear_pa_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts); - -static const struct soc_enum pm860x_spk_ear_opamp_enum = - SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts); - -static const struct snd_kcontrol_new pm860x_snd_controls[] = { - SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2, - PM860X_ADC_ANA_3, 6, 3, 0, adc_tlv), - SOC_DOUBLE_TLV("AUX Capture Volume", PM860X_ADC_ANA_3, 0, 3, 7, 0, - aux_tlv), - SOC_SINGLE_TLV("MIC1 Capture Volume", PM860X_ADC_ANA_2, 0, 7, 0, - mic_tlv), - SOC_SINGLE_TLV("MIC3 Capture Volume", PM860X_ADC_ANA_2, 3, 7, 0, - mic_tlv), - SOC_DOUBLE_R_EXT_TLV("Sidetone Volume", PM860X_SIDETONE_L_GAIN, - PM860X_SIDETONE_R_GAIN, 0, ARRAY_SIZE(st_table)-1, - 0, snd_soc_get_volsw_2r_st, - snd_soc_put_volsw_2r_st, st_tlv), - SOC_SINGLE_TLV("Speaker Playback Volume", PM860X_EAR_CTRL_1, - 0, 7, 0, out_tlv), - SOC_DOUBLE_R_TLV("Line Playback Volume", PM860X_LO1_CTRL, - PM860X_LO2_CTRL, 0, 7, 0, out_tlv), - SOC_DOUBLE_R_TLV("Headset Playback Volume", PM860X_HS1_CTRL, - PM860X_HS2_CTRL, 0, 7, 0, out_tlv), - SOC_DOUBLE_R_EXT_TLV("Hifi Left Playback Volume", - PM860X_HIFIL_GAIN_LEFT, - PM860X_HIFIL_GAIN_RIGHT, 0, 63, 0, - snd_soc_get_volsw_2r_out, - snd_soc_put_volsw_2r_out, dpga_tlv), - SOC_DOUBLE_R_EXT_TLV("Hifi Right Playback Volume", - PM860X_HIFIR_GAIN_LEFT, - PM860X_HIFIR_GAIN_RIGHT, 0, 63, 0, - snd_soc_get_volsw_2r_out, - snd_soc_put_volsw_2r_out, dpga_tlv), - SOC_DOUBLE_R_EXT_TLV("Lofi Playback Volume", PM860X_LOFI_GAIN_LEFT, - PM860X_LOFI_GAIN_RIGHT, 0, 63, 0, - snd_soc_get_volsw_2r_out, - snd_soc_put_volsw_2r_out, dpga_tlv), - SOC_ENUM("Headset1 Operational Amplifier Current", - pm860x_hs1_opamp_enum), - SOC_ENUM("Headset2 Operational Amplifier Current", - pm860x_hs2_opamp_enum), - SOC_ENUM("Headset1 Amplifier Current", pm860x_hs1_pa_enum), - SOC_ENUM("Headset2 Amplifier Current", pm860x_hs2_pa_enum), - SOC_ENUM("Lineout1 Operational Amplifier Current", - pm860x_lo1_opamp_enum), - SOC_ENUM("Lineout2 Operational Amplifier Current", - pm860x_lo2_opamp_enum), - SOC_ENUM("Lineout1 Amplifier Current", pm860x_lo1_pa_enum), - SOC_ENUM("Lineout2 Amplifier Current", pm860x_lo2_pa_enum), - SOC_ENUM("Speaker Operational Amplifier Current", - pm860x_spk_ear_opamp_enum), - SOC_ENUM("Speaker Amplifier Current", pm860x_spk_pa_enum), - SOC_ENUM("Earpiece Amplifier Current", pm860x_ear_pa_enum), -}; - -/* - * DAPM Controls - */ - -/* PCM Switch / PCM Interface */ -static const struct snd_kcontrol_new pcm_switch_controls = - SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0); - -/* AUX1 Switch */ -static const struct snd_kcontrol_new aux1_switch_controls = - SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0); - -/* AUX2 Switch */ -static const struct snd_kcontrol_new aux2_switch_controls = - SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 5, 1, 0); - -/* Left Ex. PA Switch */ -static const struct snd_kcontrol_new lepa_switch_controls = - SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 2, 1, 0); - -/* Right Ex. PA Switch */ -static const struct snd_kcontrol_new repa_switch_controls = - SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0); - -/* PCM Mux / Mux7 */ -static const char *aif1_text[] = { - "PCM L", "PCM R", -}; - -static const struct soc_enum aif1_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text); - -static const struct snd_kcontrol_new aif1_mux = - SOC_DAPM_ENUM("PCM Mux", aif1_enum); - -/* I2S Mux / Mux9 */ -static const char *i2s_din_text[] = { - "DIN", "DIN1", -}; - -static const struct soc_enum i2s_din_enum = - SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text); - -static const struct snd_kcontrol_new i2s_din_mux = - SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum); - -/* I2S Mic Mux / Mux8 */ -static const char *i2s_mic_text[] = { - "Ex PA", "ADC", -}; - -static const struct soc_enum i2s_mic_enum = - SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text); - -static const struct snd_kcontrol_new i2s_mic_mux = - SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum); - -/* ADCL Mux / Mux2 */ -static const char *adcl_text[] = { - "ADCR", "ADCL", -}; - -static const struct soc_enum adcl_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text); - -static const struct snd_kcontrol_new adcl_mux = - SOC_DAPM_ENUM("ADC Left Mux", adcl_enum); - -/* ADCR Mux / Mux3 */ -static const char *adcr_text[] = { - "ADCL", "ADCR", -}; - -static const struct soc_enum adcr_enum = - SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text); - -static const struct snd_kcontrol_new adcr_mux = - SOC_DAPM_ENUM("ADC Right Mux", adcr_enum); - -/* ADCR EC Mux / Mux6 */ -static const char *adcr_ec_text[] = { - "ADCR", "EC", -}; - -static const struct soc_enum adcr_ec_enum = - SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text); - -static const struct snd_kcontrol_new adcr_ec_mux = - SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum); - -/* EC Mux / Mux4 */ -static const char *ec_text[] = { - "Left", "Right", "Left + Right", -}; - -static const struct soc_enum ec_enum = - SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text); - -static const struct snd_kcontrol_new ec_mux = - SOC_DAPM_ENUM("EC Mux", ec_enum); - -static const char *dac_text[] = { - "No input", "Right", "Left", "No input", -}; - -/* DAC Headset 1 Mux / Mux10 */ -static const struct soc_enum dac_hs1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text); - -static const struct snd_kcontrol_new dac_hs1_mux = - SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum); - -/* DAC Headset 2 Mux / Mux11 */ -static const struct soc_enum dac_hs2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text); - -static const struct snd_kcontrol_new dac_hs2_mux = - SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum); - -/* DAC Lineout 1 Mux / Mux12 */ -static const struct soc_enum dac_lo1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text); - -static const struct snd_kcontrol_new dac_lo1_mux = - SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum); - -/* DAC Lineout 2 Mux / Mux13 */ -static const struct soc_enum dac_lo2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text); - -static const struct snd_kcontrol_new dac_lo2_mux = - SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum); - -/* DAC Spearker Earphone Mux / Mux14 */ -static const struct soc_enum dac_spk_ear_enum = - SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text); - -static const struct snd_kcontrol_new dac_spk_ear_mux = - SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum); - -/* Headset 1 Mux / Mux15 */ -static const char *in_text[] = { - "Digital", "Analog", -}; - -static const struct soc_enum hs1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text); - -static const struct snd_kcontrol_new hs1_mux = - SOC_DAPM_ENUM("Headset1 Mux", hs1_enum); - -/* Headset 2 Mux / Mux16 */ -static const struct soc_enum hs2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text); - -static const struct snd_kcontrol_new hs2_mux = - SOC_DAPM_ENUM("Headset2 Mux", hs2_enum); - -/* Lineout 1 Mux / Mux17 */ -static const struct soc_enum lo1_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text); - -static const struct snd_kcontrol_new lo1_mux = - SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum); - -/* Lineout 2 Mux / Mux18 */ -static const struct soc_enum lo2_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text); - -static const struct snd_kcontrol_new lo2_mux = - SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum); - -/* Speaker Earpiece Demux */ -static const char *spk_text[] = { - "Earpiece", "Speaker", -}; - -static const struct soc_enum spk_enum = - SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text); - -static const struct snd_kcontrol_new spk_demux = - SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum); - -/* MIC Mux / Mux1 */ -static const char *mic_text[] = { - "Mic 1", "Mic 2", -}; - -static const struct soc_enum mic_enum = - SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text); - -static const struct snd_kcontrol_new mic_mux = - SOC_DAPM_ENUM("MIC Mux", mic_enum); - -static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = { - SND_SOC_DAPM_AIF_IN("PCM SDI", "PCM Playback", 0, - PM860X_ADC_EN_2, 0, 0), - SND_SOC_DAPM_AIF_OUT("PCM SDO", "PCM Capture", 0, - PM860X_PCM_IFACE_3, 1, 1), - - - SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0, - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0, - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0, - PM860X_I2S_IFACE_3, 5, 1), - SND_SOC_DAPM_SUPPLY("I2S CLK", PM860X_DAC_EN_2, 0, 0, NULL, 0), - SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux), - SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux), - SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux), - SND_SOC_DAPM_MUX("EC Mux", SND_SOC_NOPM, 0, 0, &ec_mux), - SND_SOC_DAPM_MUX("ADCR EC Mux", SND_SOC_NOPM, 0, 0, &adcr_ec_mux), - SND_SOC_DAPM_SWITCH("Left EPA", SND_SOC_NOPM, 0, 0, - &lepa_switch_controls), - SND_SOC_DAPM_SWITCH("Right EPA", SND_SOC_NOPM, 0, 0, - &repa_switch_controls), - - SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Left ADC MOD", PM860X_ADC_EN_1, - 0, 1, 1, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Right ADC MOD", PM860X_ADC_EN_1, - 1, 1, 1, 0), - SND_SOC_DAPM_ADC("Left ADC", NULL, PM860X_ADC_EN_2, 5, 0), - SND_SOC_DAPM_ADC("Right ADC", NULL, PM860X_ADC_EN_2, 4, 0), - - SND_SOC_DAPM_SWITCH("AUX1 Switch", SND_SOC_NOPM, 0, 0, - &aux1_switch_controls), - SND_SOC_DAPM_SWITCH("AUX2 Switch", SND_SOC_NOPM, 0, 0, - &aux2_switch_controls), - - SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &mic_mux), - SND_SOC_DAPM_MICBIAS("Mic1 Bias", PM860X_ADC_ANA_1, 2, 0), - SND_SOC_DAPM_MICBIAS("Mic3 Bias", PM860X_ADC_ANA_1, 7, 0), - SND_SOC_DAPM_PGA("MIC1 Volume", PM860X_ADC_EN_1, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("MIC3 Volume", PM860X_ADC_EN_1, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("AUX1 Volume", PM860X_ADC_EN_1, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("AUX2 Volume", PM860X_ADC_EN_1, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Sidetone PGA", PM860X_ADC_EN_2, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("Lofi PGA", PM860X_ADC_EN_2, 2, 0, NULL, 0), - - SND_SOC_DAPM_INPUT("AUX1"), - SND_SOC_DAPM_INPUT("AUX2"), - SND_SOC_DAPM_INPUT("MIC1P"), - SND_SOC_DAPM_INPUT("MIC1N"), - SND_SOC_DAPM_INPUT("MIC2P"), - SND_SOC_DAPM_INPUT("MIC2N"), - SND_SOC_DAPM_INPUT("MIC3P"), - SND_SOC_DAPM_INPUT("MIC3N"), - - SND_SOC_DAPM_DAC_E("Left DAC", NULL, SND_SOC_NOPM, 0, 0, - pm860x_dac_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_DAC_E("Right DAC", NULL, SND_SOC_NOPM, 0, 0, - pm860x_dac_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_MUX("I2S DIN Mux", SND_SOC_NOPM, 0, 0, &i2s_din_mux), - SND_SOC_DAPM_MUX("DAC HS1 Mux", SND_SOC_NOPM, 0, 0, &dac_hs1_mux), - SND_SOC_DAPM_MUX("DAC HS2 Mux", SND_SOC_NOPM, 0, 0, &dac_hs2_mux), - SND_SOC_DAPM_MUX("DAC LO1 Mux", SND_SOC_NOPM, 0, 0, &dac_lo1_mux), - SND_SOC_DAPM_MUX("DAC LO2 Mux", SND_SOC_NOPM, 0, 0, &dac_lo2_mux), - SND_SOC_DAPM_MUX("DAC SP Mux", SND_SOC_NOPM, 0, 0, &dac_spk_ear_mux), - SND_SOC_DAPM_MUX("Headset1 Mux", SND_SOC_NOPM, 0, 0, &hs1_mux), - SND_SOC_DAPM_MUX("Headset2 Mux", SND_SOC_NOPM, 0, 0, &hs2_mux), - SND_SOC_DAPM_MUX("Lineout1 Mux", SND_SOC_NOPM, 0, 0, &lo1_mux), - SND_SOC_DAPM_MUX("Lineout2 Mux", SND_SOC_NOPM, 0, 0, &lo2_mux), - SND_SOC_DAPM_MUX("Speaker Earpiece Demux", SND_SOC_NOPM, 0, 0, - &spk_demux), - - - SND_SOC_DAPM_PGA("Headset1 PGA", PM860X_DAC_EN_1, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Headset2 PGA", PM860X_DAC_EN_1, 1, 0, NULL, 0), - SND_SOC_DAPM_OUTPUT("HS1"), - SND_SOC_DAPM_OUTPUT("HS2"), - SND_SOC_DAPM_PGA("Lineout1 PGA", PM860X_DAC_EN_1, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("Lineout2 PGA", PM860X_DAC_EN_1, 3, 0, NULL, 0), - SND_SOC_DAPM_OUTPUT("LINEOUT1"), - SND_SOC_DAPM_OUTPUT("LINEOUT2"), - SND_SOC_DAPM_PGA("Earpiece PGA", PM860X_DAC_EN_1, 4, 0, NULL, 0), - SND_SOC_DAPM_OUTPUT("EARP"), - SND_SOC_DAPM_OUTPUT("EARN"), - SND_SOC_DAPM_PGA("Speaker PGA", PM860X_DAC_EN_1, 5, 0, NULL, 0), - SND_SOC_DAPM_OUTPUT("LSP"), - SND_SOC_DAPM_OUTPUT("LSN"), - SND_SOC_DAPM_REG(snd_soc_dapm_supply, "VCODEC", PM860X_AUDIO_SUPPLIES_2, - 0, SUPPLY_MASK, SUPPLY_MASK, 0), - - PM860X_DAPM_OUTPUT("RSYNC", pm860x_rsync_event), -}; - -static const struct snd_soc_dapm_route pm860x_dapm_routes[] = { - /* supply */ - {"Left DAC", NULL, "VCODEC"}, - {"Right DAC", NULL, "VCODEC"}, - {"Left ADC", NULL, "VCODEC"}, - {"Right ADC", NULL, "VCODEC"}, - {"Left ADC", NULL, "Left ADC MOD"}, - {"Right ADC", NULL, "Right ADC MOD"}, - - /* I2S Clock */ - {"I2S DIN", NULL, "I2S CLK"}, - {"I2S DIN1", NULL, "I2S CLK"}, - {"I2S DOUT", NULL, "I2S CLK"}, - - /* PCM/AIF1 Inputs */ - {"PCM SDO", NULL, "ADC Left Mux"}, - {"PCM SDO", NULL, "ADCR EC Mux"}, - - /* PCM/AFI2 Outputs */ - {"Lofi PGA", NULL, "PCM SDI"}, - {"Lofi PGA", NULL, "Sidetone PGA"}, - {"Left DAC", NULL, "Lofi PGA"}, - {"Right DAC", NULL, "Lofi PGA"}, - - /* I2S/AIF2 Inputs */ - {"MIC Mux", "Mic 1", "MIC1P"}, - {"MIC Mux", "Mic 1", "MIC1N"}, - {"MIC Mux", "Mic 2", "MIC2P"}, - {"MIC Mux", "Mic 2", "MIC2N"}, - {"MIC1 Volume", NULL, "MIC Mux"}, - {"MIC3 Volume", NULL, "MIC3P"}, - {"MIC3 Volume", NULL, "MIC3N"}, - {"Left ADC", NULL, "MIC1 Volume"}, - {"Right ADC", NULL, "MIC3 Volume"}, - {"ADC Left Mux", "ADCR", "Right ADC"}, - {"ADC Left Mux", "ADCL", "Left ADC"}, - {"ADC Right Mux", "ADCL", "Left ADC"}, - {"ADC Right Mux", "ADCR", "Right ADC"}, - {"Left EPA", "Switch", "Left DAC"}, - {"Right EPA", "Switch", "Right DAC"}, - {"EC Mux", "Left", "Left DAC"}, - {"EC Mux", "Right", "Right DAC"}, - {"EC Mux", "Left + Right", "Left DAC"}, - {"EC Mux", "Left + Right", "Right DAC"}, - {"ADCR EC Mux", "ADCR", "ADC Right Mux"}, - {"ADCR EC Mux", "EC", "EC Mux"}, - {"I2S Mic Mux", "Ex PA", "Left EPA"}, - {"I2S Mic Mux", "Ex PA", "Right EPA"}, - {"I2S Mic Mux", "ADC", "ADC Left Mux"}, - {"I2S Mic Mux", "ADC", "ADCR EC Mux"}, - {"I2S DOUT", NULL, "I2S Mic Mux"}, - - /* I2S/AIF2 Outputs */ - {"I2S DIN Mux", "DIN", "I2S DIN"}, - {"I2S DIN Mux", "DIN1", "I2S DIN1"}, - {"Left DAC", NULL, "I2S DIN Mux"}, - {"Right DAC", NULL, "I2S DIN Mux"}, - {"DAC HS1 Mux", "Left", "Left DAC"}, - {"DAC HS1 Mux", "Right", "Right DAC"}, - {"DAC HS2 Mux", "Left", "Left DAC"}, - {"DAC HS2 Mux", "Right", "Right DAC"}, - {"DAC LO1 Mux", "Left", "Left DAC"}, - {"DAC LO1 Mux", "Right", "Right DAC"}, - {"DAC LO2 Mux", "Left", "Left DAC"}, - {"DAC LO2 Mux", "Right", "Right DAC"}, - {"Headset1 Mux", "Digital", "DAC HS1 Mux"}, - {"Headset2 Mux", "Digital", "DAC HS2 Mux"}, - {"Lineout1 Mux", "Digital", "DAC LO1 Mux"}, - {"Lineout2 Mux", "Digital", "DAC LO2 Mux"}, - {"Headset1 PGA", NULL, "Headset1 Mux"}, - {"Headset2 PGA", NULL, "Headset2 Mux"}, - {"Lineout1 PGA", NULL, "Lineout1 Mux"}, - {"Lineout2 PGA", NULL, "Lineout2 Mux"}, - {"DAC SP Mux", "Left", "Left DAC"}, - {"DAC SP Mux", "Right", "Right DAC"}, - {"Speaker Earpiece Demux", "Speaker", "DAC SP Mux"}, - {"Speaker PGA", NULL, "Speaker Earpiece Demux"}, - {"Earpiece PGA", NULL, "Speaker Earpiece Demux"}, - - {"RSYNC", NULL, "Headset1 PGA"}, - {"RSYNC", NULL, "Headset2 PGA"}, - {"RSYNC", NULL, "Lineout1 PGA"}, - {"RSYNC", NULL, "Lineout2 PGA"}, - {"RSYNC", NULL, "Speaker PGA"}, - {"RSYNC", NULL, "Speaker PGA"}, - {"RSYNC", NULL, "Earpiece PGA"}, - {"RSYNC", NULL, "Earpiece PGA"}, - - {"HS1", NULL, "RSYNC"}, - {"HS2", NULL, "RSYNC"}, - {"LINEOUT1", NULL, "RSYNC"}, - {"LINEOUT2", NULL, "RSYNC"}, - {"LSP", NULL, "RSYNC"}, - {"LSN", NULL, "RSYNC"}, - {"EARP", NULL, "RSYNC"}, - {"EARN", NULL, "RSYNC"}, -}; - -/* - * Use MUTE_LEFT & MUTE_RIGHT to implement digital mute. - * These bits can also be used to mute. - */ -static int pm860x_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int data = 0, mask = MUTE_LEFT | MUTE_RIGHT; - - if (mute) - data = mask; - snd_soc_update_bits(codec, PM860X_DAC_OFFSET, mask, data); - snd_soc_update_bits(codec, PM860X_EAR_CTRL_2, - RSYNC_CHANGE, RSYNC_CHANGE); - return 0; -} - -static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - unsigned char inf = 0, mask = 0; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - inf &= ~PCM_INF2_18WL; - break; - case SNDRV_PCM_FORMAT_S18_3LE: - inf |= PCM_INF2_18WL; - break; - default: - return -EINVAL; - } - mask |= PCM_INF2_18WL; - snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf); - - /* sample rate */ - switch (params_rate(params)) { - case 8000: - inf = 0; - break; - case 16000: - inf = 3; - break; - case 32000: - inf = 6; - break; - case 48000: - inf = 8; - break; - default: - return -EINVAL; - } - snd_soc_update_bits(codec, PM860X_PCM_RATE, 0x0f, inf); - - return 0; -} - -static int pm860x_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); - unsigned char inf = 0, mask = 0; - int ret = -EINVAL; - - mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - if (pm860x->dir == PM860X_CLK_DIR_OUT) { - inf |= PCM_INF2_MASTER; - ret = 0; - } - break; - case SND_SOC_DAIFMT_CBS_CFS: - if (pm860x->dir == PM860X_CLK_DIR_IN) { - inf &= ~PCM_INF2_MASTER; - ret = 0; - } - break; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - inf |= PCM_EXACT_I2S; - ret = 0; - break; - } - mask |= PCM_MODE_MASK; - if (ret) - return ret; - snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf); - return 0; -} - -static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); - - if (dir == PM860X_CLK_DIR_OUT) - pm860x->dir = PM860X_CLK_DIR_OUT; - else { - pm860x->dir = PM860X_CLK_DIR_IN; - return -EINVAL; - } - - return 0; -} - -static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - unsigned char inf; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - inf = 0; - break; - case SNDRV_PCM_FORMAT_S18_3LE: - inf = PCM_INF2_18WL; - break; - default: - return -EINVAL; - } - snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, PCM_INF2_18WL, inf); - - /* sample rate */ - switch (params_rate(params)) { - case 8000: - inf = 0; - break; - case 11025: - inf = 1; - break; - case 16000: - inf = 3; - break; - case 22050: - inf = 4; - break; - case 32000: - inf = 6; - break; - case 44100: - inf = 7; - break; - case 48000: - inf = 8; - break; - default: - return -EINVAL; - } - snd_soc_update_bits(codec, PM860X_I2S_IFACE_4, 0xf, inf); - - return 0; -} - -static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); - unsigned char inf = 0, mask = 0; - - mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - if (pm860x->dir == PM860X_CLK_DIR_OUT) - inf |= PCM_INF2_MASTER; - else - return -EINVAL; - break; - case SND_SOC_DAIFMT_CBS_CFS: - if (pm860x->dir == PM860X_CLK_DIR_IN) - inf &= ~PCM_INF2_MASTER; - else - return -EINVAL; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - inf |= PCM_EXACT_I2S; - break; - default: - return -EINVAL; - } - mask |= PCM_MODE_MASK; - snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, mask, inf); - return 0; -} - -static int pm860x_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int data; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - /* Enable Audio PLL & Audio section */ - data = AUDIO_PLL | AUDIO_SECTION_ON; - pm860x_reg_write(codec->control_data, REG_MISC2, data); - udelay(300); - data = AUDIO_PLL | AUDIO_SECTION_RESET - | AUDIO_SECTION_ON; - pm860x_reg_write(codec->control_data, REG_MISC2, data); - } - break; - - case SND_SOC_BIAS_OFF: - data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON; - pm860x_set_bits(codec->control_data, REG_MISC2, data, 0); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static const struct snd_soc_dai_ops pm860x_pcm_dai_ops = { - .digital_mute = pm860x_digital_mute, - .hw_params = pm860x_pcm_hw_params, - .set_fmt = pm860x_pcm_set_dai_fmt, - .set_sysclk = pm860x_set_dai_sysclk, -}; - -static const struct snd_soc_dai_ops pm860x_i2s_dai_ops = { - .digital_mute = pm860x_digital_mute, - .hw_params = pm860x_i2s_hw_params, - .set_fmt = pm860x_i2s_set_dai_fmt, - .set_sysclk = pm860x_set_dai_sysclk, -}; - -#define PM860X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) - -static struct snd_soc_dai_driver pm860x_dai[] = { - { - /* DAI PCM */ - .name = "88pm860x-pcm", - .id = 1, - .playback = { - .stream_name = "PCM Playback", - .channels_min = 2, - .channels_max = 2, - .rates = PM860X_RATES, - .formats = SNDRV_PCM_FORMAT_S16_LE | \ - SNDRV_PCM_FORMAT_S18_3LE, - }, - .capture = { - .stream_name = "PCM Capture", - .channels_min = 2, - .channels_max = 2, - .rates = PM860X_RATES, - .formats = SNDRV_PCM_FORMAT_S16_LE | \ - SNDRV_PCM_FORMAT_S18_3LE, - }, - .ops = &pm860x_pcm_dai_ops, - }, { - /* DAI I2S */ - .name = "88pm860x-i2s", - .id = 2, - .playback = { - .stream_name = "I2S Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FORMAT_S16_LE | \ - SNDRV_PCM_FORMAT_S18_3LE, - }, - .capture = { - .stream_name = "I2S Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FORMAT_S16_LE | \ - SNDRV_PCM_FORMAT_S18_3LE, - }, - .ops = &pm860x_i2s_dai_ops, - }, -}; - -static irqreturn_t pm860x_codec_handler(int irq, void *data) -{ - struct pm860x_priv *pm860x = data; - int status, shrt, report = 0, mic_report = 0; - int mask; - - status = pm860x_reg_read(pm860x->i2c, REG_STATUS_1); - shrt = pm860x_reg_read(pm860x->i2c, REG_SHORTS); - mask = pm860x->det.hs_shrt | pm860x->det.hook_det | pm860x->det.lo_shrt - | pm860x->det.hp_det; - -#ifndef CONFIG_SND_SOC_88PM860X_MODULE - if (status & (HEADSET_STATUS | MIC_STATUS | SHORT_HS1 | SHORT_HS2 | - SHORT_LO1 | SHORT_LO2)) - trace_snd_soc_jack_irq(dev_name(pm860x->codec->dev)); -#endif - - if ((pm860x->det.hp_det & SND_JACK_HEADPHONE) - && (status & HEADSET_STATUS)) - report |= SND_JACK_HEADPHONE; - - if ((pm860x->det.mic_det & SND_JACK_MICROPHONE) - && (status & MIC_STATUS)) - mic_report |= SND_JACK_MICROPHONE; - - if (pm860x->det.hs_shrt && (shrt & (SHORT_HS1 | SHORT_HS2))) - report |= pm860x->det.hs_shrt; - - if (pm860x->det.hook_det && (status & HOOK_STATUS)) - report |= pm860x->det.hook_det; - - if (pm860x->det.lo_shrt && (shrt & (SHORT_LO1 | SHORT_LO2))) - report |= pm860x->det.lo_shrt; - - if (report) - snd_soc_jack_report(pm860x->det.hp_jack, report, mask); - if (mic_report) - snd_soc_jack_report(pm860x->det.mic_jack, SND_JACK_MICROPHONE, - SND_JACK_MICROPHONE); - - dev_dbg(pm860x->codec->dev, "headphone report:0x%x, mask:%x\n", - report, mask); - dev_dbg(pm860x->codec->dev, "microphone report:0x%x\n", mic_report); - return IRQ_HANDLED; -} - -int pm860x_hs_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack, - int det, int hook, int hs_shrt, int lo_shrt) -{ - struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); - int data; - - pm860x->det.hp_jack = jack; - pm860x->det.hp_det = det; - pm860x->det.hook_det = hook; - pm860x->det.hs_shrt = hs_shrt; - pm860x->det.lo_shrt = lo_shrt; - - if (det & SND_JACK_HEADPHONE) - pm860x_set_bits(codec->control_data, REG_HS_DET, - EN_HS_DET, EN_HS_DET); - /* headset short detect */ - if (hs_shrt) { - data = CLR_SHORT_HS2 | CLR_SHORT_HS1; - pm860x_set_bits(codec->control_data, REG_SHORTS, data, data); - } - /* Lineout short detect */ - if (lo_shrt) { - data = CLR_SHORT_LO2 | CLR_SHORT_LO1; - pm860x_set_bits(codec->control_data, REG_SHORTS, data, data); - } - - /* sync status */ - pm860x_codec_handler(0, pm860x); - return 0; -} -EXPORT_SYMBOL_GPL(pm860x_hs_jack_detect); - -int pm860x_mic_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack, int det) -{ - struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); - - pm860x->det.mic_jack = jack; - pm860x->det.mic_det = det; - - if (det & SND_JACK_MICROPHONE) - pm860x_set_bits(codec->control_data, REG_MIC_DET, - MICDET_MASK, MICDET_MASK); - - /* sync status */ - pm860x_codec_handler(0, pm860x); - return 0; -} -EXPORT_SYMBOL_GPL(pm860x_mic_jack_detect); - -static int pm860x_probe(struct snd_soc_codec *codec) -{ - struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); - int i, ret; - - pm860x->codec = codec; - - codec->control_data = pm860x->i2c; - - for (i = 0; i < 4; i++) { - ret = request_threaded_irq(pm860x->irq[i], NULL, - pm860x_codec_handler, IRQF_ONESHOT, - pm860x->name[i], pm860x); - if (ret < 0) { - dev_err(codec->dev, "Failed to request IRQ!\n"); - goto out; - } - } - - pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE, - REG_CACHE_SIZE, codec->reg_cache); - if (ret < 0) { - dev_err(codec->dev, "Failed to fill register cache: %d\n", - ret); - goto out; - } - - return 0; - -out: - while (--i >= 0) - free_irq(pm860x->irq[i], pm860x); - return ret; -} - -static int pm860x_remove(struct snd_soc_codec *codec) -{ - struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec); - int i; - - for (i = 3; i >= 0; i--) - free_irq(pm860x->irq[i], pm860x); - pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_pm860x = { - .probe = pm860x_probe, - .remove = pm860x_remove, - .read = pm860x_read_reg_cache, - .write = pm860x_write_reg_cache, - .reg_cache_size = REG_CACHE_SIZE, - .reg_word_size = sizeof(u8), - .set_bias_level = pm860x_set_bias_level, - - .controls = pm860x_snd_controls, - .num_controls = ARRAY_SIZE(pm860x_snd_controls), - .dapm_widgets = pm860x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(pm860x_dapm_widgets), - .dapm_routes = pm860x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes), -}; - -static int __devinit pm860x_codec_probe(struct platform_device *pdev) -{ - struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm860x_priv *pm860x; - struct resource *res; - int i, ret; - - pm860x = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_priv), - GFP_KERNEL); - if (pm860x == NULL) - return -ENOMEM; - - pm860x->chip = chip; - pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client - : chip->companion; - platform_set_drvdata(pdev, pm860x); - - for (i = 0; i < 4; i++) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!res) { - dev_err(&pdev->dev, "Failed to get IRQ resources\n"); - goto out; - } - pm860x->irq[i] = res->start + chip->irq_base; - strncpy(pm860x->name[i], res->name, MAX_NAME_LEN); - } - - ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pm860x, - pm860x_dai, ARRAY_SIZE(pm860x_dai)); - if (ret) { - dev_err(&pdev->dev, "Failed to register codec\n"); - goto out; - } - return ret; - -out: - platform_set_drvdata(pdev, NULL); - return -EINVAL; -} - -static int __devexit pm860x_codec_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver pm860x_codec_driver = { - .driver = { - .name = "88pm860x-codec", - .owner = THIS_MODULE, - }, - .probe = pm860x_codec_probe, - .remove = __devexit_p(pm860x_codec_remove), -}; - -module_platform_driver(pm860x_codec_driver); - -MODULE_DESCRIPTION("ASoC 88PM860x driver"); -MODULE_AUTHOR("Haojian Zhuang "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:88pm860x-codec"); - diff --git a/ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.h b/ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.h deleted file mode 100644 index 3364ba4a..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/88pm860x-codec.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 88pm860x-codec.h -- 88PM860x ALSA SoC Audio Driver - * - * Copyright 2010 Marvell International Ltd. - * Haojian Zhuang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __88PM860X_H -#define __88PM860X_H - -/* The offset of these registers are 0xb0 */ -#define PM860X_PCM_IFACE_1 0x00 -#define PM860X_PCM_IFACE_2 0x01 -#define PM860X_PCM_IFACE_3 0x02 -#define PM860X_PCM_RATE 0x03 -#define PM860X_EC_PATH 0x04 -#define PM860X_SIDETONE_L_GAIN 0x05 -#define PM860X_SIDETONE_R_GAIN 0x06 -#define PM860X_SIDETONE_SHIFT 0x07 -#define PM860X_ADC_OFFSET_1 0x08 -#define PM860X_ADC_OFFSET_2 0x09 -#define PM860X_DMIC_DELAY 0x0a - -#define PM860X_I2S_IFACE_1 0x0b -#define PM860X_I2S_IFACE_2 0x0c -#define PM860X_I2S_IFACE_3 0x0d -#define PM860X_I2S_IFACE_4 0x0e -#define PM860X_EQUALIZER_N0_1 0x0f -#define PM860X_EQUALIZER_N0_2 0x10 -#define PM860X_EQUALIZER_N1_1 0x11 -#define PM860X_EQUALIZER_N1_2 0x12 -#define PM860X_EQUALIZER_D1_1 0x13 -#define PM860X_EQUALIZER_D1_2 0x14 -#define PM860X_LOFI_GAIN_LEFT 0x15 -#define PM860X_LOFI_GAIN_RIGHT 0x16 -#define PM860X_HIFIL_GAIN_LEFT 0x17 -#define PM860X_HIFIL_GAIN_RIGHT 0x18 -#define PM860X_HIFIR_GAIN_LEFT 0x19 -#define PM860X_HIFIR_GAIN_RIGHT 0x1a -#define PM860X_DAC_OFFSET 0x1b -#define PM860X_OFFSET_LEFT_1 0x1c -#define PM860X_OFFSET_LEFT_2 0x1d -#define PM860X_OFFSET_RIGHT_1 0x1e -#define PM860X_OFFSET_RIGHT_2 0x1f -#define PM860X_ADC_ANA_1 0x20 -#define PM860X_ADC_ANA_2 0x21 -#define PM860X_ADC_ANA_3 0x22 -#define PM860X_ADC_ANA_4 0x23 -#define PM860X_ANA_TO_ANA 0x24 -#define PM860X_HS1_CTRL 0x25 -#define PM860X_HS2_CTRL 0x26 -#define PM860X_LO1_CTRL 0x27 -#define PM860X_LO2_CTRL 0x28 -#define PM860X_EAR_CTRL_1 0x29 -#define PM860X_EAR_CTRL_2 0x2a -#define PM860X_AUDIO_SUPPLIES_1 0x2b -#define PM860X_AUDIO_SUPPLIES_2 0x2c -#define PM860X_ADC_EN_1 0x2d -#define PM860X_ADC_EN_2 0x2e -#define PM860X_DAC_EN_1 0x2f -#define PM860X_DAC_EN_2 0x31 -#define PM860X_AUDIO_CAL_1 0x32 -#define PM860X_AUDIO_CAL_2 0x33 -#define PM860X_AUDIO_CAL_3 0x34 -#define PM860X_AUDIO_CAL_4 0x35 -#define PM860X_AUDIO_CAL_5 0x36 -#define PM860X_ANA_INPUT_SEL_1 0x37 -#define PM860X_ANA_INPUT_SEL_2 0x38 - -#define PM860X_PCM_IFACE_4 0x39 -#define PM860X_I2S_IFACE_5 0x3a - -#define PM860X_SHORTS 0x3b -#define PM860X_PLL_ADJ_1 0x3c -#define PM860X_PLL_ADJ_2 0x3d - -/* bits definition */ -#define PM860X_CLK_DIR_IN 0 -#define PM860X_CLK_DIR_OUT 1 - -#define PM860X_DET_HEADSET (1 << 0) -#define PM860X_DET_MIC (1 << 1) -#define PM860X_DET_HOOK (1 << 2) -#define PM860X_SHORT_HEADSET (1 << 3) -#define PM860X_SHORT_LINEOUT (1 << 4) -#define PM860X_DET_MASK 0x1F - -extern int pm860x_hs_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *, - int, int, int, int); -extern int pm860x_mic_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *, - int); - -#endif /* __88PM860X_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/Kconfig b/ANDROID_3.4.5/sound/soc/codecs/Kconfig deleted file mode 100644 index 7077ac69..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/Kconfig +++ /dev/null @@ -1,455 +0,0 @@ -# Helper to resolve issues with configs that have SPI enabled but I2C -# modular, meaning we can't build the codec driver in with I2C support. -# We use an ordered list of conditional defaults to pick the appropriate -# setting - SPI can't be modular so that case doesn't need to be covered. -config SND_SOC_I2C_AND_SPI - tristate - default m if I2C=m - default y if I2C=y - default y if SPI_MASTER=y - -config SND_SOC_ALL_CODECS - tristate "Build all ASoC CODEC drivers" - select SND_SOC_88PM860X if MFD_88PM860X - select SND_SOC_L3 - select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS - select SND_SOC_AD1836 if SPI_MASTER - select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI - select SND_SOC_AD1980 if SND_SOC_AC97_BUS - select SND_SOC_AD73311 - select SND_SOC_ADAU1373 if I2C - select SND_SOC_ADAV80X - select SND_SOC_ADS117X - select SND_SOC_AK4104 if SPI_MASTER - select SND_SOC_AK4535 if I2C - select SND_SOC_AK4641 if I2C - select SND_SOC_AK4642 if I2C - select SND_SOC_AK4671 if I2C - select SND_SOC_ALC5623 if I2C - select SND_SOC_ALC5632 if I2C - select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC - select SND_SOC_CS42L51 if I2C - select SND_SOC_CS42L73 if I2C - select SND_SOC_CS4270 if I2C - select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI - select SND_SOC_CX20442 - select SND_SOC_DA7210 if I2C - select SND_SOC_DFBMCS320 - select SND_SOC_JZ4740_CODEC - select SND_SOC_LM4857 if I2C - select SND_SOC_MAX98088 if I2C - select SND_SOC_MAX98095 if I2C - select SND_SOC_MAX9850 if I2C - select SND_SOC_MAX9768 if I2C - select SND_SOC_MAX9877 if I2C - select SND_SOC_PCM3008 - select SND_SOC_RT5631 if I2C - select SND_SOC_SGTL5000 if I2C - select SND_SOC_SN95031 if INTEL_SCU_IPC - select SND_SOC_SPDIF - select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI - select SND_SOC_STA32X if I2C - select SND_SOC_STAC9766 if SND_SOC_AC97_BUS - select SND_SOC_TLV320AIC23 if I2C - select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TLV320AIC32X4 if I2C - select SND_SOC_TLV320AIC3X if I2C - select SND_SOC_TPA6130A2 if I2C - select SND_SOC_TLV320DAC33 if I2C - select SND_SOC_TWL4030 if TWL4030_CORE - select SND_SOC_TWL6040 if TWL6040_CORE - select SND_SOC_UDA134X - select SND_SOC_UDA1380 if I2C - select SND_SOC_WL1273 if MFD_WL1273_CORE - select SND_SOC_WM1250_EV1 if I2C - select SND_SOC_WM2000 if I2C - select SND_SOC_WM2200 if I2C - select SND_SOC_WM5100 if I2C - select SND_SOC_WM8350 if MFD_WM8350 - select SND_SOC_WM8400 if MFD_WM8400 - select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8523 if I2C - select SND_SOC_WM8580 if I2C - select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8727 - select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8737 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8741 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8770 if SPI_MASTER - select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8782 - select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8900 if I2C - select SND_SOC_WM8903 if I2C - select SND_SOC_WM8904 if I2C - select SND_SOC_WM8940 if I2C - select SND_SOC_WM8955 if I2C - select SND_SOC_WM8960 if I2C - select SND_SOC_WM8961 if I2C - select SND_SOC_WM8962 if I2C - select SND_SOC_WM8971 if I2C - select SND_SOC_WM8974 if I2C - select SND_SOC_WM8978 if I2C - select SND_SOC_WM8983 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8990 if I2C - select SND_SOC_WM8991 if I2C - select SND_SOC_WM8993 if I2C - select SND_SOC_WM8994 if MFD_WM8994 - select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8996 if I2C - select SND_SOC_WM9081 if I2C - select SND_SOC_WM9090 if I2C - select SND_SOC_WM9705 if SND_SOC_AC97_BUS - select SND_SOC_WM9712 if SND_SOC_AC97_BUS - select SND_SOC_WM9713 if SND_SOC_AC97_BUS - help - Normally ASoC codec drivers are only built if a machine driver which - uses them is also built since they are only usable with a machine - driver. Selecting this option will allow these drivers to be built - without an explicit machine driver for test and development purposes. - - Support for the bus types used to access the codecs to be built must - be selected separately. - - If unsure select "N". - -config SND_SOC_88PM860X - tristate - -config SND_SOC_WM_HUBS - tristate - default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y - default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m - -config SND_SOC_AC97_CODEC - tristate - select SND_AC97_CODEC - -config SND_SOC_AD1836 - tristate - -config SND_SOC_AD193X - tristate - -config SND_SOC_AD1980 - tristate - -config SND_SOC_AD73311 - tristate - -config SND_SOC_ADAU1701 - select SND_SOC_SIGMADSP - tristate - -config SND_SOC_ADAU1373 - tristate - -config SND_SOC_ADAV80X - tristate - -config SND_SOC_ADS117X - tristate - -config SND_SOC_AK4104 - tristate - -config SND_SOC_AK4535 - tristate - -config SND_SOC_AK4641 - tristate - -config SND_SOC_AK4642 - tristate - -config SND_SOC_AK4671 - tristate - -config SND_SOC_ALC5623 - tristate -config SND_SOC_ALC5632 - tristate - -config SND_SOC_CQ0093VC - tristate - -config SND_SOC_CS42L51 - tristate - -config SND_SOC_CS42L73 - tristate - -# Cirrus Logic CS4270 Codec -config SND_SOC_CS4270 - tristate - -# Cirrus Logic CS4270 Codec VD = 3.3V Errata -# Select if you are affected by the errata where the part will not function -# if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will -# not select any sample rates that require MCLK to be divided by 1.5. -config SND_SOC_CS4270_VD33_ERRATA - bool - depends on SND_SOC_CS4270 - -config SND_SOC_CS4271 - tristate - -config SND_SOC_CX20442 - tristate - -config SND_SOC_JZ4740_CODEC - tristate - -config SND_SOC_L3 - tristate - -config SND_SOC_DA7210 - tristate - -config SND_SOC_DFBMCS320 - tristate - -config SND_SOC_DMIC - tristate - -config SND_SOC_MAX98088 - tristate - -config SND_SOC_MAX98095 - tristate - -config SND_SOC_MAX9850 - tristate - -config SND_SOC_PCM3008 - tristate - -config SND_SOC_RT5631 - tristate - -#Freescale sgtl5000 codec -config SND_SOC_SGTL5000 - tristate - -config SND_SOC_SIGMADSP - tristate - select CRC32 - -config SND_SOC_SN95031 - tristate - -config SND_SOC_SPDIF - tristate - -config SND_SOC_SSM2602 - tristate - -config SND_SOC_STA32X - tristate - -config SND_SOC_STAC9766 - tristate - -config SND_SOC_TLV320AIC23 - tristate - -config SND_SOC_TLV320AIC26 - tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE - depends on SPI - -config SND_SOC_TLV320AIC32X4 - tristate - -config SND_SOC_TLV320AIC3X - tristate - -config SND_SOC_TLV320DAC33 - tristate - -config SND_SOC_TWL4030 - select MFD_TWL4030_AUDIO - tristate - -config SND_SOC_TWL6040 - tristate - -config SND_SOC_UDA134X - tristate - -config SND_SOC_UDA1380 - tristate - -config SND_SOC_WL1273 - tristate - -config SND_SOC_WM1250_EV1 - tristate - -config SND_SOC_WM2000 - tristate - -config SND_SOC_WM2200 - tristate - -config SND_SOC_WM5100 - tristate - -config SND_SOC_WM8350 - tristate - -config SND_SOC_WM8400 - tristate - -config SND_SOC_WM8510 - tristate - -config SND_SOC_WM8523 - tristate - -config SND_SOC_WM8580 - tristate - -config SND_SOC_WM8711 - tristate - -config SND_SOC_WM8727 - tristate - -config SND_SOC_WM8728 - tristate - -config SND_SOC_WM8731 - tristate - -config SND_SOC_WM8737 - tristate - -config SND_SOC_WM8741 - tristate - -config SND_SOC_WM8750 - tristate - -config SND_SOC_VT1602 - tristate - depends on SND_SOC - -config SND_SOC_VT1603 - tristate - depends on SND_SOC - -config SND_SOC_HWDAC - tristate - depends on SND_SOC - -config SND_SOC_WM8753 - tristate - -config SND_SOC_WM8770 - tristate - -config SND_SOC_WM8776 - tristate - -config SND_SOC_WM8782 - tristate - -config SND_SOC_WM8804 - tristate - -config SND_SOC_WM8900 - tristate - -config SND_SOC_WM8903 - tristate - -config SND_SOC_WM8904 - tristate - -config SND_SOC_WM8940 - tristate - -config SND_SOC_WM8955 - tristate - -config SND_SOC_WM8960 - tristate - -config SND_SOC_WM8961 - tristate - -config SND_SOC_WM8962 - tristate - -config SND_SOC_WM8971 - tristate - -config SND_SOC_WM8974 - tristate - -config SND_SOC_WM8978 - tristate - -config SND_SOC_WM8983 - tristate - -config SND_SOC_WM8985 - tristate - -config SND_SOC_WM8988 - tristate - -config SND_SOC_WM8990 - tristate - -config SND_SOC_WM8991 - tristate - -config SND_SOC_WM8993 - tristate - -config SND_SOC_WM8994 - tristate - -config SND_SOC_WM8995 - tristate - -config SND_SOC_WM8996 - tristate - -config SND_SOC_WM9081 - tristate - -config SND_SOC_WM9090 - tristate - -config SND_SOC_WM9705 - tristate - -config SND_SOC_WM9712 - tristate - -config SND_SOC_WM9713 - tristate - -# Amp -config SND_SOC_LM4857 - tristate - -config SND_SOC_MAX9768 - tristate - -config SND_SOC_MAX9877 - tristate - -config SND_SOC_TPA6130A2 - tristate - -# echo cancellation -config SND_SOC_WMT_FM34 - tristate diff --git a/ANDROID_3.4.5/sound/soc/codecs/Makefile b/ANDROID_3.4.5/sound/soc/codecs/Makefile deleted file mode 100644 index 83175a64..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/Makefile +++ /dev/null @@ -1,219 +0,0 @@ -snd-soc-88pm860x-objs := 88pm860x-codec.o -snd-soc-ac97-objs := ac97.o -snd-soc-ad1836-objs := ad1836.o -snd-soc-ad193x-objs := ad193x.o -snd-soc-ad1980-objs := ad1980.o -snd-soc-ad73311-objs := ad73311.o -snd-soc-adau1701-objs := adau1701.o -snd-soc-adau1373-objs := adau1373.o -snd-soc-adav80x-objs := adav80x.o -snd-soc-ads117x-objs := ads117x.o -snd-soc-ak4104-objs := ak4104.o -snd-soc-ak4535-objs := ak4535.o -snd-soc-ak4641-objs := ak4641.o -snd-soc-ak4642-objs := ak4642.o -snd-soc-ak4671-objs := ak4671.o -snd-soc-cq93vc-objs := cq93vc.o -snd-soc-cs42l51-objs := cs42l51.o -snd-soc-cs42l73-objs := cs42l73.o -snd-soc-cs4270-objs := cs4270.o -snd-soc-cs4271-objs := cs4271.o -snd-soc-cx20442-objs := cx20442.o -snd-soc-da7210-objs := da7210.o -snd-soc-dfbmcs320-objs := dfbmcs320.o -snd-soc-dmic-objs := dmic.o -snd-soc-jz4740-codec-objs := jz4740.o -snd-soc-l3-objs := l3.o -snd-soc-lm4857-objs := lm4857.o -snd-soc-max9768-objs := max9768.o -snd-soc-max98088-objs := max98088.o -snd-soc-max98095-objs := max98095.o -snd-soc-max9850-objs := max9850.o -snd-soc-pcm3008-objs := pcm3008.o -snd-soc-rt5631-objs := rt5631.o -snd-soc-sgtl5000-objs := sgtl5000.o -snd-soc-alc5623-objs := alc5623.o -snd-soc-alc5632-objs := alc5632.o -snd-soc-sigmadsp-objs := sigmadsp.o -snd-soc-sn95031-objs := sn95031.o -snd-soc-spdif-objs := spdif_transciever.o -snd-soc-ssm2602-objs := ssm2602.o -snd-soc-sta32x-objs := sta32x.o -snd-soc-stac9766-objs := stac9766.o -snd-soc-tlv320aic23-objs := tlv320aic23.o -snd-soc-tlv320aic26-objs := tlv320aic26.o -snd-soc-tlv320aic3x-objs := tlv320aic3x.o -snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o -snd-soc-tlv320dac33-objs := tlv320dac33.o -snd-soc-twl4030-objs := twl4030.o -snd-soc-twl6040-objs := twl6040.o -snd-soc-uda134x-objs := uda134x.o -snd-soc-uda1380-objs := uda1380.o -snd-soc-wl1273-objs := wl1273.o -snd-soc-wm1250-ev1-objs := wm1250-ev1.o -snd-soc-wm2000-objs := wm2000.o -snd-soc-wm2200-objs := wm2200.o -snd-soc-wm5100-objs := wm5100.o wm5100-tables.o -snd-soc-wm8350-objs := wm8350.o -snd-soc-wm8400-objs := wm8400.o -snd-soc-wm8510-objs := wm8510.o -snd-soc-wm8523-objs := wm8523.o -snd-soc-wm8580-objs := wm8580.o -snd-soc-wm8711-objs := wm8711.o -snd-soc-wm8727-objs := wm8727.o -snd-soc-wm8728-objs := wm8728.o -snd-soc-wm8731-objs := wm8731.o -snd-soc-wm8737-objs := wm8737.o -snd-soc-wm8741-objs := wm8741.o -snd-soc-wm8750-objs := wm8750.o -snd-soc-vt1602-objs := wmt_vt1602.o -snd-soc-vt1603-objs := vt1603.o -snd-soc-hwdac-objs := wmt_hwdac.o -snd-soc-wm8753-objs := wm8753.o -snd-soc-wm8770-objs := wm8770.o -snd-soc-wm8776-objs := wm8776.o -snd-soc-wm8782-objs := wm8782.o -snd-soc-wm8804-objs := wm8804.o -snd-soc-wm8900-objs := wm8900.o -snd-soc-wm8903-objs := wm8903.o -snd-soc-wm8904-objs := wm8904.o -snd-soc-wm8996-objs := wm8996.o -snd-soc-wm8940-objs := wm8940.o -snd-soc-wm8955-objs := wm8955.o -snd-soc-wm8960-objs := wm8960.o -snd-soc-wm8961-objs := wm8961.o -snd-soc-wm8962-objs := wm8962.o -snd-soc-wm8971-objs := wm8971.o -snd-soc-wm8974-objs := wm8974.o -snd-soc-wm8978-objs := wm8978.o -snd-soc-wm8983-objs := wm8983.o -snd-soc-wm8985-objs := wm8985.o -snd-soc-wm8988-objs := wm8988.o -snd-soc-wm8990-objs := wm8990.o -snd-soc-wm8991-objs := wm8991.o -snd-soc-wm8993-objs := wm8993.o -snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o -snd-soc-wm8995-objs := wm8995.o -snd-soc-wm9081-objs := wm9081.o -snd-soc-wm9090-objs := wm9090.o -snd-soc-wm9705-objs := wm9705.o -snd-soc-wm9712-objs := wm9712.o -snd-soc-wm9713-objs := wm9713.o -snd-soc-wm-hubs-objs := wm_hubs.o - -# Amp -snd-soc-max9877-objs := max9877.o -snd-soc-tpa6130a2-objs := tpa6130a2.o - -# echo cancellation -snd-soc-wmt-fm34-objs := wmt_fm34.o - -obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o -obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o -obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o -obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o -obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o -obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o -obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o -obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o -obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o -obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o -obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o -obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o -obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o -obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o -obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o -obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o -obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o -obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o -obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o -obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o -obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o -obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o -obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o -obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o -obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o -obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o -obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o -obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o -obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o -obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o -obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o -obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o -obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o -obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o -obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o -obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o -obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o -obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o -obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o -obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o -obj-$(CONFIG_SND_SOC_STA32X) += snd-soc-sta32x.o -obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o -obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o -obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o -obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o -obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o -obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o -obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o -obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o -obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o -obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o -obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o -obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o -obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o -obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o -obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o -obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o -obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o -obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o -obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o -obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o -obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o -obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o -obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o -obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o -obj-$(CONFIG_SND_SOC_WM8737) += snd-soc-wm8737.o -obj-$(CONFIG_SND_SOC_WM8741) += snd-soc-wm8741.o -obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o -obj-$(CONFIG_SND_SOC_VT1602) += snd-soc-vt1602.o -obj-$(CONFIG_SND_SOC_VT1603) += snd-soc-vt1603.o -obj-$(CONFIG_SND_SOC_HWDAC) += snd-soc-hwdac.o -obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o -obj-$(CONFIG_SND_SOC_WM8770) += snd-soc-wm8770.o -obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o -obj-$(CONFIG_SND_SOC_WM8782) += snd-soc-wm8782.o -obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o -obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o -obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o -obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o -obj-$(CONFIG_SND_SOC_WM8996) += snd-soc-wm8996.o -obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o -obj-$(CONFIG_SND_SOC_WM8955) += snd-soc-wm8955.o -obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o -obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o -obj-$(CONFIG_SND_SOC_WM8962) += snd-soc-wm8962.o -obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o -obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o -obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o -obj-$(CONFIG_SND_SOC_WM8983) += snd-soc-wm8983.o -obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o -obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o -obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o -obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o -obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o -obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o -obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o -obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o -obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o -obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o -obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o -obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o -obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o - -# Amp -obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o -obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o - -# echo cancellation -obj-$(CONFIG_SND_SOC_WMT_FM34) += snd-soc-wmt-fm34.o diff --git a/ANDROID_3.4.5/sound/soc/codecs/ac97.c b/ANDROID_3.4.5/sound/soc/codecs/ac97.c deleted file mode 100644 index 1bbad4c1..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ac97.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * ac97.c -- ALSA Soc AC97 codec support - * - * Copyright 2005 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * - * 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. - * - * Generic AC97 support. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int ac97_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; - return snd_ac97_set_rate(codec->ac97, reg, runtime->rate); -} - -#define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000) - -static const struct snd_soc_dai_ops ac97_dai_ops = { - .prepare = ac97_prepare, -}; - -static struct snd_soc_dai_driver ac97_dai = { - .name = "ac97-hifi", - .ac97_control = 1, - .playback = { - .stream_name = "AC97 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = STD_AC97_RATES, - .formats = SND_SOC_STD_AC97_FMTS,}, - .capture = { - .stream_name = "AC97 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = STD_AC97_RATES, - .formats = SND_SOC_STD_AC97_FMTS,}, - .ops = &ac97_dai_ops, -}; - -static unsigned int ac97_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - return soc_ac97_ops.read(codec->ac97, reg); -} - -static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int val) -{ - soc_ac97_ops.write(codec->ac97, reg, val); - return 0; -} - -static int ac97_soc_probe(struct snd_soc_codec *codec) -{ - struct snd_ac97_bus *ac97_bus; - struct snd_ac97_template ac97_template; - int ret; - - /* add codec as bus device for standard ac97 */ - ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus); - if (ret < 0) - return ret; - - memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); - ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); - if (ret < 0) - return ret; - - return 0; -} - -static int ac97_soc_remove(struct snd_soc_codec *codec) -{ - return 0; -} - -#ifdef CONFIG_PM -static int ac97_soc_suspend(struct snd_soc_codec *codec) -{ - snd_ac97_suspend(codec->ac97); - - return 0; -} - -static int ac97_soc_resume(struct snd_soc_codec *codec) -{ - snd_ac97_resume(codec->ac97); - - return 0; -} -#else -#define ac97_soc_suspend NULL -#define ac97_soc_resume NULL -#endif - -static struct snd_soc_codec_driver soc_codec_dev_ac97 = { - .write = ac97_write, - .read = ac97_read, - .probe = ac97_soc_probe, - .remove = ac97_soc_remove, - .suspend = ac97_soc_suspend, - .resume = ac97_soc_resume, -}; - -static __devinit int ac97_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_ac97, &ac97_dai, 1); -} - -static int __devexit ac97_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver ac97_codec_driver = { - .driver = { - .name = "ac97-codec", - .owner = THIS_MODULE, - }, - - .probe = ac97_probe, - .remove = __devexit_p(ac97_remove), -}; - -module_platform_driver(ac97_codec_driver); - -MODULE_DESCRIPTION("Soc Generic AC97 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ac97-codec"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ad1836.c b/ANDROID_3.4.5/sound/soc/codecs/ad1836.c deleted file mode 100644 index 12e3b411..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ad1836.c +++ /dev/null @@ -1,398 +0,0 @@ - /* - * Audio Codec driver supporting: - * AD1835A, AD1836, AD1837A, AD1838A, AD1839A - * - * Copyright 2009-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ad1836.h" - -enum ad1836_type { - AD1835, - AD1836, - AD1838, -}; - -/* codec private data */ -struct ad1836_priv { - enum ad1836_type type; -}; - -/* - * AD1836 volume/mute/de-emphasis etc. controls - */ -static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; - -static const struct soc_enum ad1836_deemp_enum = - SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); - -#define AD1836_DAC_VOLUME(x) \ - SOC_DOUBLE_R("DAC" #x " Playback Volume", AD1836_DAC_L_VOL(x), \ - AD1836_DAC_R_VOL(x), 0, 0x3FF, 0) - -#define AD1836_DAC_SWITCH(x) \ - SOC_DOUBLE("DAC" #x " Playback Switch", AD1836_DAC_CTRL2, \ - AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1) - -#define AD1836_ADC_SWITCH(x) \ - SOC_DOUBLE("ADC" #x " Capture Switch", AD1836_ADC_CTRL2, \ - AD1836_MUTE_LEFT(x), AD1836_MUTE_RIGHT(x), 1, 1) - -static const struct snd_kcontrol_new ad183x_dac_controls[] = { - AD1836_DAC_VOLUME(1), - AD1836_DAC_SWITCH(1), - AD1836_DAC_VOLUME(2), - AD1836_DAC_SWITCH(2), - AD1836_DAC_VOLUME(3), - AD1836_DAC_SWITCH(3), - AD1836_DAC_VOLUME(4), - AD1836_DAC_SWITCH(4), -}; - -static const struct snd_soc_dapm_widget ad183x_dac_dapm_widgets[] = { - SND_SOC_DAPM_OUTPUT("DAC1OUT"), - SND_SOC_DAPM_OUTPUT("DAC2OUT"), - SND_SOC_DAPM_OUTPUT("DAC3OUT"), - SND_SOC_DAPM_OUTPUT("DAC4OUT"), -}; - -static const struct snd_soc_dapm_route ad183x_dac_routes[] = { - { "DAC1OUT", NULL, "DAC" }, - { "DAC2OUT", NULL, "DAC" }, - { "DAC3OUT", NULL, "DAC" }, - { "DAC4OUT", NULL, "DAC" }, -}; - -static const struct snd_kcontrol_new ad183x_adc_controls[] = { - AD1836_ADC_SWITCH(1), - AD1836_ADC_SWITCH(2), - AD1836_ADC_SWITCH(3), -}; - -static const struct snd_soc_dapm_widget ad183x_adc_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("ADC1IN"), - SND_SOC_DAPM_INPUT("ADC2IN"), -}; - -static const struct snd_soc_dapm_route ad183x_adc_routes[] = { - { "ADC", NULL, "ADC1IN" }, - { "ADC", NULL, "ADC2IN" }, -}; - -static const struct snd_kcontrol_new ad183x_controls[] = { - /* ADC high-pass filter */ - SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, - AD1836_ADC_HIGHPASS_FILTER, 1, 0), - - /* DAC de-emphasis */ - SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum), -}; - -static const struct snd_soc_dapm_widget ad183x_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1, - AD1836_DAC_POWERDOWN, 1), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1, - AD1836_ADC_POWERDOWN, 1, NULL, 0), -}; - -static const struct snd_soc_dapm_route ad183x_dapm_routes[] = { - { "DAC", NULL, "ADC_PWR" }, - { "ADC", NULL, "ADC_PWR" }, -}; - -static const DECLARE_TLV_DB_SCALE(ad1836_in_tlv, 0, 300, 0); - -static const struct snd_kcontrol_new ad1836_controls[] = { - SOC_DOUBLE_TLV("ADC2 Capture Volume", AD1836_ADC_CTRL1, 3, 0, 4, 0, - ad1836_in_tlv), -}; - -/* - * DAI ops entries - */ - -static int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - /* at present, we support adc aux mode to interface with - * blackfin sport tdm mode - */ - case SND_SOC_DAIFMT_DSP_A: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - /* ALCLK,ABCLK are both output, AD1836 can only be master */ - case SND_SOC_DAIFMT_CBM_CFM: - break; - default: - return -EINVAL; - } - - return 0; -} - -static int ad1836_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int word_len = 0; - - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - word_len = AD1836_WORD_LEN_16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - word_len = AD1836_WORD_LEN_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S32_LE: - word_len = AD1836_WORD_LEN_24; - break; - } - - snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, - word_len << AD1836_DAC_WORD_LEN_OFFSET); - - snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, - word_len << AD1836_ADC_WORD_OFFSET); - - return 0; -} - -static const struct snd_soc_dai_ops ad1836_dai_ops = { - .hw_params = ad1836_hw_params, - .set_fmt = ad1836_set_dai_fmt, -}; - -#define AD183X_DAI(_name, num_dacs, num_adcs) \ -{ \ - .name = _name "-hifi", \ - .playback = { \ - .stream_name = "Playback", \ - .channels_min = 2, \ - .channels_max = (num_dacs) * 2, \ - .rates = SNDRV_PCM_RATE_48000, \ - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \ - }, \ - .capture = { \ - .stream_name = "Capture", \ - .channels_min = 2, \ - .channels_max = (num_adcs) * 2, \ - .rates = SNDRV_PCM_RATE_48000, \ - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, \ - }, \ - .ops = &ad1836_dai_ops, \ -} - -static struct snd_soc_dai_driver ad183x_dais[] = { - [AD1835] = AD183X_DAI("ad1835", 4, 1), - [AD1836] = AD183X_DAI("ad1836", 3, 2), - [AD1838] = AD183X_DAI("ad1838", 3, 1), -}; - -#ifdef CONFIG_PM -static int ad1836_suspend(struct snd_soc_codec *codec) -{ - /* reset clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, - AD1836_ADC_SERFMT_MASK, 0); -} - -static int ad1836_resume(struct snd_soc_codec *codec) -{ - /* restore clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, - AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); -} -#else -#define ad1836_suspend NULL -#define ad1836_resume NULL -#endif - -static int ad1836_probe(struct snd_soc_codec *codec) -{ - struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - int num_dacs, num_adcs; - int ret = 0; - int i; - - num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; - num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; - - ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", - ret); - return ret; - } - - /* default setting for ad1836 */ - /* de-emphasis: 48kHz, power-on dac */ - snd_soc_write(codec, AD1836_DAC_CTRL1, 0x300); - /* unmute dac channels */ - snd_soc_write(codec, AD1836_DAC_CTRL2, 0x0); - /* high-pass filter enable, power-on adc */ - snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); - /* unmute adc channles, adc aux mode */ - snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); - /* volume */ - for (i = 1; i <= num_dacs; ++i) { - snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF); - snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF); - } - - if (ad1836->type == AD1836) { - /* left/right diff:PGA/MUX */ - snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); - ret = snd_soc_add_codec_controls(codec, ad1836_controls, - ARRAY_SIZE(ad1836_controls)); - if (ret) - return ret; - } else { - snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); - } - - ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2); - if (ret) - return ret; - - ret = snd_soc_add_codec_controls(codec, ad183x_adc_controls, num_adcs); - if (ret) - return ret; - - ret = snd_soc_dapm_new_controls(dapm, ad183x_dac_dapm_widgets, num_dacs); - if (ret) - return ret; - - ret = snd_soc_dapm_new_controls(dapm, ad183x_adc_dapm_widgets, num_adcs); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(dapm, ad183x_dac_routes, num_dacs); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs); - if (ret) - return ret; - - return ret; -} - -/* power down chip */ -static int ad1836_remove(struct snd_soc_codec *codec) -{ - /* reset clock control mode */ - return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, - AD1836_ADC_SERFMT_MASK, 0); -} - -static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { - .probe = ad1836_probe, - .remove = ad1836_remove, - .suspend = ad1836_suspend, - .resume = ad1836_resume, - .reg_cache_size = AD1836_NUM_REGS, - .reg_word_size = sizeof(u16), - - .controls = ad183x_controls, - .num_controls = ARRAY_SIZE(ad183x_controls), - .dapm_widgets = ad183x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad183x_dapm_widgets), - .dapm_routes = ad183x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), -}; - -static int __devinit ad1836_spi_probe(struct spi_device *spi) -{ - struct ad1836_priv *ad1836; - int ret; - - ad1836 = devm_kzalloc(&spi->dev, sizeof(struct ad1836_priv), - GFP_KERNEL); - if (ad1836 == NULL) - return -ENOMEM; - - ad1836->type = spi_get_device_id(spi)->driver_data; - - spi_set_drvdata(spi, ad1836); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ad1836, &ad183x_dais[ad1836->type], 1); - return ret; -} - -static int __devexit ad1836_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static const struct spi_device_id ad1836_ids[] = { - { "ad1835", AD1835 }, - { "ad1836", AD1836 }, - { "ad1837", AD1835 }, - { "ad1838", AD1838 }, - { "ad1839", AD1838 }, - { }, -}; -MODULE_DEVICE_TABLE(spi, ad1836_ids); - -static struct spi_driver ad1836_spi_driver = { - .driver = { - .name = "ad1836", - .owner = THIS_MODULE, - }, - .probe = ad1836_spi_probe, - .remove = __devexit_p(ad1836_spi_remove), - .id_table = ad1836_ids, -}; - -static int __init ad1836_init(void) -{ - return spi_register_driver(&ad1836_spi_driver); -} -module_init(ad1836_init); - -static void __exit ad1836_exit(void) -{ - spi_unregister_driver(&ad1836_spi_driver); -} -module_exit(ad1836_exit); - -MODULE_DESCRIPTION("ASoC ad1836 driver"); -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ad1836.h b/ANDROID_3.4.5/sound/soc/codecs/ad1836.h deleted file mode 100644 index dd7be0db..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ad1836.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Audio Codec driver supporting: - * AD1835A, AD1836, AD1837A, AD1838A, AD1839A - * - * Copyright 2009-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __AD1836_H__ -#define __AD1836_H__ - -#define AD1836_DAC_CTRL1 0 -#define AD1836_DAC_POWERDOWN 2 -#define AD1836_DAC_SERFMT_MASK 0xE0 -#define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) -#define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) -#define AD1836_DAC_WORD_LEN_MASK 0x18 -#define AD1836_DAC_WORD_LEN_OFFSET 3 - -#define AD1836_DAC_CTRL2 1 - -/* These macros are one-based. So AD183X_MUTE_LEFT(1) will return the mute bit - * for the first ADC/DAC */ -#define AD1836_MUTE_LEFT(x) (((x) * 2) - 2) -#define AD1836_MUTE_RIGHT(x) (((x) * 2) - 1) - -#define AD1836_DAC_L_VOL(x) ((x) * 2) -#define AD1836_DAC_R_VOL(x) (1 + ((x) * 2)) - -#define AD1836_ADC_CTRL1 12 -#define AD1836_ADC_POWERDOWN 7 -#define AD1836_ADC_HIGHPASS_FILTER 8 - -#define AD1836_ADC_CTRL2 13 -#define AD1836_ADC_WORD_LEN_MASK 0x30 -#define AD1836_ADC_WORD_OFFSET 4 -#define AD1836_ADC_SERFMT_MASK (7 << 6) -#define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) -#define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) -#define AD1836_ADC_AUX (0x6 << 6) - -#define AD1836_ADC_CTRL3 14 - -#define AD1836_NUM_REGS 16 - -#define AD1836_WORD_LEN_24 0x0 -#define AD1836_WORD_LEN_20 0x1 -#define AD1836_WORD_LEN_16 0x2 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/ad193x.c b/ANDROID_3.4.5/sound/soc/codecs/ad193x.c deleted file mode 100644 index a4a6bef2..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ad193x.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * AD193X Audio Codec driver supporting AD1936/7/8/9 - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ad193x.h" - -/* codec private data */ -struct ad193x_priv { - struct regmap *regmap; - int sysclk; -}; - -/* - * AD193X volume/mute/de-emphasis etc. controls - */ -static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; - -static const struct soc_enum ad193x_deemp_enum = - SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp); - -static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); - -static const struct snd_kcontrol_new ad193x_snd_controls[] = { - /* DAC volume control */ - SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL, - AD193X_DAC_R1_VOL, 0, 0xFF, 1, adau193x_tlv), - SOC_DOUBLE_R_TLV("DAC2 Volume", AD193X_DAC_L2_VOL, - AD193X_DAC_R2_VOL, 0, 0xFF, 1, adau193x_tlv), - SOC_DOUBLE_R_TLV("DAC3 Volume", AD193X_DAC_L3_VOL, - AD193X_DAC_R3_VOL, 0, 0xFF, 1, adau193x_tlv), - SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL, - AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv), - - /* ADC switch control */ - SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE, - AD193X_ADCR1_MUTE, 1, 1), - SOC_DOUBLE("ADC2 Switch", AD193X_ADC_CTRL0, AD193X_ADCL2_MUTE, - AD193X_ADCR2_MUTE, 1, 1), - - /* DAC switch control */ - SOC_DOUBLE("DAC1 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL1_MUTE, - AD193X_DACR1_MUTE, 1, 1), - SOC_DOUBLE("DAC2 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL2_MUTE, - AD193X_DACR2_MUTE, 1, 1), - SOC_DOUBLE("DAC3 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL3_MUTE, - AD193X_DACR3_MUTE, 1, 1), - SOC_DOUBLE("DAC4 Switch", AD193X_DAC_CHNL_MUTE, AD193X_DACL4_MUTE, - AD193X_DACR4_MUTE, 1, 1), - - /* ADC high-pass filter */ - SOC_SINGLE("ADC High Pass Filter Switch", AD193X_ADC_CTRL0, - AD193X_ADC_HIGHPASS_FILTER, 1, 0), - - /* DAC de-emphasis */ - SOC_ENUM("Playback Deemphasis", ad193x_deemp_enum), -}; - -static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", "Playback", AD193X_DAC_CTRL0, 0, 1), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), - SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), - SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), - SND_SOC_DAPM_OUTPUT("DAC1OUT"), - SND_SOC_DAPM_OUTPUT("DAC2OUT"), - SND_SOC_DAPM_OUTPUT("DAC3OUT"), - SND_SOC_DAPM_OUTPUT("DAC4OUT"), - SND_SOC_DAPM_INPUT("ADC1IN"), - SND_SOC_DAPM_INPUT("ADC2IN"), -}; - -static const struct snd_soc_dapm_route audio_paths[] = { - { "DAC", NULL, "SYSCLK" }, - { "ADC", NULL, "SYSCLK" }, - { "DAC", NULL, "ADC_PWR" }, - { "ADC", NULL, "ADC_PWR" }, - { "DAC1OUT", NULL, "DAC" }, - { "DAC2OUT", NULL, "DAC" }, - { "DAC3OUT", NULL, "DAC" }, - { "DAC4OUT", NULL, "DAC" }, - { "ADC", NULL, "ADC1IN" }, - { "ADC", NULL, "ADC2IN" }, - { "SYSCLK", NULL, "PLL_PWR" }, -}; - -/* - * DAI ops entries - */ - -static int ad193x_mute(struct snd_soc_dai *dai, int mute) -{ - struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec); - - if (mute) - regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, - AD193X_DAC_MASTER_MUTE, - AD193X_DAC_MASTER_MUTE); - else - regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, - AD193X_DAC_MASTER_MUTE, 0); - - return 0; -} - -static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, - unsigned int rx_mask, int slots, int width) -{ - struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec); - unsigned int channels; - - switch (slots) { - case 2: - channels = AD193X_2_CHANNELS; - break; - case 4: - channels = AD193X_4_CHANNELS; - break; - case 8: - channels = AD193X_8_CHANNELS; - break; - case 16: - channels = AD193X_16_CHANNELS; - break; - default: - return -EINVAL; - } - - regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, - AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT); - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, - AD193X_ADC_CHAN_MASK, channels << AD193X_ADC_CHAN_SHFT); - - return 0; -} - -static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec_dai->codec); - unsigned int adc_serfmt = 0; - unsigned int adc_fmt = 0; - unsigned int dac_fmt = 0; - - /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S - * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) - */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - adc_serfmt |= AD193X_ADC_SERFMT_TDM; - break; - case SND_SOC_DAIFMT_DSP_A: - adc_serfmt |= AD193X_ADC_SERFMT_AUX; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ - break; - case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */ - adc_fmt |= AD193X_ADC_LEFT_HIGH; - dac_fmt |= AD193X_DAC_LEFT_HIGH; - break; - case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */ - adc_fmt |= AD193X_ADC_BCLK_INV; - dac_fmt |= AD193X_DAC_BCLK_INV; - break; - case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ - adc_fmt |= AD193X_ADC_LEFT_HIGH; - adc_fmt |= AD193X_ADC_BCLK_INV; - dac_fmt |= AD193X_DAC_LEFT_HIGH; - dac_fmt |= AD193X_DAC_BCLK_INV; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ - adc_fmt |= AD193X_ADC_LCR_MASTER; - adc_fmt |= AD193X_ADC_BCLK_MASTER; - dac_fmt |= AD193X_DAC_LCR_MASTER; - dac_fmt |= AD193X_DAC_BCLK_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */ - adc_fmt |= AD193X_ADC_LCR_MASTER; - dac_fmt |= AD193X_DAC_LCR_MASTER; - break; - case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */ - adc_fmt |= AD193X_ADC_BCLK_MASTER; - dac_fmt |= AD193X_DAC_BCLK_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */ - break; - default: - return -EINVAL; - } - - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, - AD193X_ADC_SERFMT_MASK, adc_serfmt); - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2, - AD193X_ADC_FMT_MASK, adc_fmt); - regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1, - AD193X_DAC_FMT_MASK, dac_fmt); - - return 0; -} - -static int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); - switch (freq) { - case 12288000: - case 18432000: - case 24576000: - case 36864000: - ad193x->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int ad193x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int word_len = 0, master_rate = 0; - - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - word_len = 3; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - word_len = 1; - break; - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S32_LE: - word_len = 0; - break; - } - - switch (ad193x->sysclk) { - case 12288000: - master_rate = AD193X_PLL_INPUT_256; - break; - case 18432000: - master_rate = AD193X_PLL_INPUT_384; - break; - case 24576000: - master_rate = AD193X_PLL_INPUT_512; - break; - case 36864000: - master_rate = AD193X_PLL_INPUT_768; - break; - } - - regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0, - AD193X_PLL_INPUT_MASK, master_rate); - - regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2, - AD193X_DAC_WORD_LEN_MASK, - word_len << AD193X_DAC_WORD_LEN_SHFT); - - regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1, - AD193X_ADC_WORD_LEN_MASK, word_len); - - return 0; -} - -static const struct snd_soc_dai_ops ad193x_dai_ops = { - .hw_params = ad193x_hw_params, - .digital_mute = ad193x_mute, - .set_tdm_slot = ad193x_set_tdm_slot, - .set_sysclk = ad193x_set_dai_sysclk, - .set_fmt = ad193x_set_dai_fmt, -}; - -/* codec DAI instance */ -static struct snd_soc_dai_driver ad193x_dai = { - .name = "ad193x-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 4, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .ops = &ad193x_dai_ops, -}; - -static int ad193x_probe(struct snd_soc_codec *codec) -{ - struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ad193x->regmap; - ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - - /* default setting for ad193x */ - - /* unmute dac channels */ - regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0); - /* de-emphasis: 48kHz, powedown dac */ - regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); - /* powerdown dac, dac in tdm mode */ - regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x41); - /* high-pass filter enable */ - regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3); - /* sata delay=1, adc aux mode */ - regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43); - /* pll input: mclki/xi */ - regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */ - regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04); - - return ret; -} - -static struct snd_soc_codec_driver soc_codec_dev_ad193x = { - .probe = ad193x_probe, - .controls = ad193x_snd_controls, - .num_controls = ARRAY_SIZE(ad193x_snd_controls), - .dapm_widgets = ad193x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets), - .dapm_routes = audio_paths, - .num_dapm_routes = ARRAY_SIZE(audio_paths), -}; - -static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) -{ - return false; -} - -#if defined(CONFIG_SPI_MASTER) - -static const struct regmap_config ad193x_spi_regmap_config = { - .val_bits = 8, - .reg_bits = 16, - .read_flag_mask = 0x09, - .write_flag_mask = 0x08, - - .max_register = AD193X_NUM_REGS - 1, - .volatile_reg = adau193x_reg_volatile, -}; - -static int __devinit ad193x_spi_probe(struct spi_device *spi) -{ - struct ad193x_priv *ad193x; - int ret; - - ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); - if (ad193x == NULL) - return -ENOMEM; - - ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); - if (IS_ERR(ad193x->regmap)) { - ret = PTR_ERR(ad193x->regmap); - goto err_out; - } - - spi_set_drvdata(spi, ad193x); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ad193x, &ad193x_dai, 1); - if (ret < 0) - goto err_regmap_exit; - - return 0; - -err_regmap_exit: - regmap_exit(ad193x->regmap); -err_out: - return ret; -} - -static int __devexit ad193x_spi_remove(struct spi_device *spi) -{ - struct ad193x_priv *ad193x = spi_get_drvdata(spi); - - snd_soc_unregister_codec(&spi->dev); - regmap_exit(ad193x->regmap); - return 0; -} - -static struct spi_driver ad193x_spi_driver = { - .driver = { - .name = "ad193x", - .owner = THIS_MODULE, - }, - .probe = ad193x_spi_probe, - .remove = __devexit_p(ad193x_spi_remove), -}; -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -static const struct regmap_config ad193x_i2c_regmap_config = { - .val_bits = 8, - .reg_bits = 8, - - .max_register = AD193X_NUM_REGS - 1, - .volatile_reg = adau193x_reg_volatile, -}; - -static const struct i2c_device_id ad193x_id[] = { - { "ad1936", 0 }, - { "ad1937", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad193x_id); - -static int __devinit ad193x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ad193x_priv *ad193x; - int ret; - - ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); - if (ad193x == NULL) - return -ENOMEM; - - ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); - if (IS_ERR(ad193x->regmap)) { - ret = PTR_ERR(ad193x->regmap); - goto err_out; - } - - i2c_set_clientdata(client, ad193x); - - ret = snd_soc_register_codec(&client->dev, - &soc_codec_dev_ad193x, &ad193x_dai, 1); - if (ret < 0) - goto err_regmap_exit; - - return 0; - -err_regmap_exit: - regmap_exit(ad193x->regmap); -err_out: - return ret; -} - -static int __devexit ad193x_i2c_remove(struct i2c_client *client) -{ - struct ad193x_priv *ad193x = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(ad193x->regmap); - return 0; -} - -static struct i2c_driver ad193x_i2c_driver = { - .driver = { - .name = "ad193x", - }, - .probe = ad193x_i2c_probe, - .remove = __devexit_p(ad193x_i2c_remove), - .id_table = ad193x_id, -}; -#endif - -static int __init ad193x_modinit(void) -{ - int ret; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&ad193x_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", - ret); - } -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ad193x_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(ad193x_modinit); - -static void __exit ad193x_modexit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ad193x_spi_driver); -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&ad193x_i2c_driver); -#endif -} -module_exit(ad193x_modexit); - -MODULE_DESCRIPTION("ASoC ad193x driver"); -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ad193x.h b/ANDROID_3.4.5/sound/soc/codecs/ad193x.h deleted file mode 100644 index 47338804..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ad193x.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * AD193X Audio Codec driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __AD193X_H__ -#define __AD193X_H__ - -#define AD193X_PLL_CLK_CTRL0 0x00 -#define AD193X_PLL_POWERDOWN 0x01 -#define AD193X_PLL_INPUT_MASK 0x6 -#define AD193X_PLL_INPUT_256 (0 << 1) -#define AD193X_PLL_INPUT_384 (1 << 1) -#define AD193X_PLL_INPUT_512 (2 << 1) -#define AD193X_PLL_INPUT_768 (3 << 1) -#define AD193X_PLL_CLK_CTRL1 0x01 -#define AD193X_DAC_CTRL0 0x02 -#define AD193X_DAC_POWERDOWN 0x01 -#define AD193X_DAC_SERFMT_MASK 0xC0 -#define AD193X_DAC_SERFMT_STEREO (0 << 6) -#define AD193X_DAC_SERFMT_TDM (1 << 6) -#define AD193X_DAC_CTRL1 0x03 -#define AD193X_DAC_CHAN_SHFT 1 -#define AD193X_DAC_CHAN_MASK (3 << AD193X_DAC_CHAN_SHFT) -#define AD193X_DAC_LCR_MASTER (1 << 4) -#define AD193X_DAC_BCLK_MASTER (1 << 5) -#define AD193X_DAC_LEFT_HIGH (1 << 3) -#define AD193X_DAC_BCLK_INV (1 << 7) -#define AD193X_DAC_FMT_MASK (AD193X_DAC_LCR_MASTER | \ - AD193X_DAC_BCLK_MASTER | AD193X_DAC_LEFT_HIGH | AD193X_DAC_BCLK_INV) -#define AD193X_DAC_CTRL2 0x04 -#define AD193X_DAC_WORD_LEN_SHFT 3 -#define AD193X_DAC_WORD_LEN_MASK 0x18 -#define AD193X_DAC_MASTER_MUTE 1 -#define AD193X_DAC_CHNL_MUTE 0x05 -#define AD193X_DACL1_MUTE 0 -#define AD193X_DACR1_MUTE 1 -#define AD193X_DACL2_MUTE 2 -#define AD193X_DACR2_MUTE 3 -#define AD193X_DACL3_MUTE 4 -#define AD193X_DACR3_MUTE 5 -#define AD193X_DACL4_MUTE 6 -#define AD193X_DACR4_MUTE 7 -#define AD193X_DAC_L1_VOL 0x06 -#define AD193X_DAC_R1_VOL 0x07 -#define AD193X_DAC_L2_VOL 0x08 -#define AD193X_DAC_R2_VOL 0x09 -#define AD193X_DAC_L3_VOL 0x0a -#define AD193X_DAC_R3_VOL 0x0b -#define AD193X_DAC_L4_VOL 0x0c -#define AD193X_DAC_R4_VOL 0x0d -#define AD193X_ADC_CTRL0 0x0e -#define AD193X_ADC_POWERDOWN 0x01 -#define AD193X_ADC_HIGHPASS_FILTER 1 -#define AD193X_ADCL1_MUTE 2 -#define AD193X_ADCR1_MUTE 3 -#define AD193X_ADCL2_MUTE 4 -#define AD193X_ADCR2_MUTE 5 -#define AD193X_ADC_CTRL1 0x0f -#define AD193X_ADC_SERFMT_MASK 0x60 -#define AD193X_ADC_SERFMT_STEREO (0 << 5) -#define AD193X_ADC_SERFMT_TDM (1 << 5) -#define AD193X_ADC_SERFMT_AUX (2 << 5) -#define AD193X_ADC_WORD_LEN_MASK 0x3 -#define AD193X_ADC_CTRL2 0x10 -#define AD193X_ADC_CHAN_SHFT 4 -#define AD193X_ADC_CHAN_MASK (3 << AD193X_ADC_CHAN_SHFT) -#define AD193X_ADC_LCR_MASTER (1 << 3) -#define AD193X_ADC_BCLK_MASTER (1 << 6) -#define AD193X_ADC_LEFT_HIGH (1 << 2) -#define AD193X_ADC_BCLK_INV (1 << 1) -#define AD193X_ADC_FMT_MASK (AD193X_ADC_LCR_MASTER | \ - AD193X_ADC_BCLK_MASTER | AD193X_ADC_LEFT_HIGH | AD193X_ADC_BCLK_INV) - -#define AD193X_2_CHANNELS 0 -#define AD193X_4_CHANNELS 1 -#define AD193X_8_CHANNELS 2 -#define AD193X_16_CHANNELS 3 - -#define AD193X_NUM_REGS 17 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/ad1980.c b/ANDROID_3.4.5/sound/soc/codecs/ad1980.c deleted file mode 100644 index 8c39dddd..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ad1980.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * ad1980.c -- ALSA Soc AD1980 codec support - * - * Copyright: Analog Device Inc. - * Author: Roy Huang - * Cliff Cai - * - * 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. - */ - -/* - * WARNING: - * - * Because Analog Devices Inc. discontinued the ad1980 sound chip since - * Sep. 2009, this ad1980 driver is not maintained, tested and supported - * by ADI now. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ad1980.h" - -/* - * AD1980 register cache - */ -static const u16 ad1980_reg[] = { - 0x0090, 0x8000, 0x8000, 0x8000, /* 0 - 6 */ - 0x0000, 0x0000, 0x8008, 0x8008, /* 8 - e */ - 0x8808, 0x8808, 0x0000, 0x8808, /* 10 - 16 */ - 0x8808, 0x0000, 0x8000, 0x0000, /* 18 - 1e */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 20 - 26 */ - 0x03c7, 0x0000, 0xbb80, 0xbb80, /* 28 - 2e */ - 0xbb80, 0xbb80, 0x0000, 0x8080, /* 30 - 36 */ - 0x8080, 0x2000, 0x0000, 0x0000, /* 38 - 3e */ - 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ - 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ - 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ - 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ - 0x8080, 0x0000, 0x0000, 0x0000, /* 60 - 66 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ - 0x0000, 0x0000, 0x1001, 0x0000, /* 70 - 76 */ - 0x0000, 0x0000, 0x4144, 0x5370 /* 78 - 7e */ -}; - -static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", - "Stereo Mix", "Mono Mix", "Phone"}; - -static const struct soc_enum ad1980_cap_src = - SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 7, ad1980_rec_sel); - -static const struct snd_kcontrol_new ad1980_snd_ac97_controls[] = { -SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), -SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1), - -SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1), -SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1), - -SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1), -SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1), - -SOC_DOUBLE("PCM Capture Volume", AC97_REC_GAIN, 8, 0, 31, 0), -SOC_SINGLE("PCM Capture Switch", AC97_REC_GAIN, 15, 1, 1), - -SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1), -SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), - -SOC_SINGLE("Phone Capture Volume", AC97_PHONE, 0, 31, 1), -SOC_SINGLE("Phone Capture Switch", AC97_PHONE, 15, 1, 1), - -SOC_SINGLE("Mic Volume", AC97_MIC, 0, 31, 1), -SOC_SINGLE("Mic Switch", AC97_MIC, 15, 1, 1), - -SOC_SINGLE("Stereo Mic Switch", AC97_AD_MISC, 6, 1, 0), -SOC_DOUBLE("Line HP Swap Switch", AC97_AD_MISC, 10, 5, 1, 0), - -SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), -SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1), - -SOC_DOUBLE("Center/LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 0, 31, 1), -SOC_DOUBLE("Center/LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 7, 1, 1), - -SOC_ENUM("Capture Source", ad1980_cap_src), - -SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), -}; - -static unsigned int ac97_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - - switch (reg) { - case AC97_RESET: - case AC97_INT_PAGING: - case AC97_POWERDOWN: - case AC97_EXTENDED_STATUS: - case AC97_VENDOR_ID1: - case AC97_VENDOR_ID2: - return soc_ac97_ops.read(codec->ac97, reg); - default: - reg = reg >> 1; - - if (reg >= ARRAY_SIZE(ad1980_reg)) - return -EINVAL; - - return cache[reg]; - } -} - -static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int val) -{ - u16 *cache = codec->reg_cache; - - soc_ac97_ops.write(codec->ac97, reg, val); - reg = reg >> 1; - if (reg < ARRAY_SIZE(ad1980_reg)) - cache[reg] = val; - - return 0; -} - -static struct snd_soc_dai_driver ad1980_dai = { - .name = "ad1980-hifi", - .ac97_control = 1, - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 6, - .rates = SNDRV_PCM_RATE_48000, - .formats = SND_SOC_STD_AC97_FMTS, }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SND_SOC_STD_AC97_FMTS, }, -}; - -static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) -{ - u16 retry_cnt = 0; - -retry: - if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset(codec->ac97); - if (ac97_read(codec, AC97_RESET) == 0x0090) - return 1; - } - - soc_ac97_ops.reset(codec->ac97); - /* Set bit 16slot in register 74h, then every slot will has only 16 - * bits. This command is sent out in 20bit mode, in which case the - * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ - ac97_write(codec, AC97_AD_SERIAL_CFG, 0x9900); - - if (ac97_read(codec, AC97_RESET) != 0x0090) - goto err; - return 0; - -err: - while (retry_cnt++ < 10) - goto retry; - - printk(KERN_ERR "AD1980 AC97 reset failed\n"); - return -EIO; -} - -static int ad1980_soc_probe(struct snd_soc_codec *codec) -{ - int ret; - u16 vendor_id2; - u16 ext_status; - - printk(KERN_INFO "AD1980 SoC Audio Codec\n"); - - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); - if (ret < 0) { - printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); - return ret; - } - - ret = ad1980_reset(codec, 0); - if (ret < 0) { - printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); - goto reset_err; - } - - /* Read out vendor ID to make sure it is ad1980 */ - if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) { - ret = -ENODEV; - goto reset_err; - } - - vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); - - if (vendor_id2 != 0x5370) { - if (vendor_id2 != 0x5374) { - ret = -ENODEV; - goto reset_err; - } else { - printk(KERN_WARNING "ad1980: " - "Found AD1981 - only 2/2 IN/OUT Channels " - "supported\n"); - } - } - - /* unmute captures and playbacks volume */ - ac97_write(codec, AC97_MASTER, 0x0000); - ac97_write(codec, AC97_PCM, 0x0000); - ac97_write(codec, AC97_REC_GAIN, 0x0000); - ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000); - ac97_write(codec, AC97_SURROUND_MASTER, 0x0000); - - /*power on LFE/CENTER/Surround DACs*/ - ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); - ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); - - snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls, - ARRAY_SIZE(ad1980_snd_ac97_controls)); - - return 0; - -reset_err: - snd_soc_free_ac97_codec(codec); - return ret; -} - -static int ad1980_soc_remove(struct snd_soc_codec *codec) -{ - snd_soc_free_ac97_codec(codec); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { - .probe = ad1980_soc_probe, - .remove = ad1980_soc_remove, - .reg_cache_size = ARRAY_SIZE(ad1980_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = ad1980_reg, - .reg_cache_step = 2, - .write = ac97_write, - .read = ac97_read, -}; - -static __devinit int ad1980_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_ad1980, &ad1980_dai, 1); -} - -static int __devexit ad1980_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver ad1980_codec_driver = { - .driver = { - .name = "ad1980", - .owner = THIS_MODULE, - }, - - .probe = ad1980_probe, - .remove = __devexit_p(ad1980_remove), -}; - -module_platform_driver(ad1980_codec_driver); - -MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)"); -MODULE_AUTHOR("Roy Huang, Cliff Cai"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ad1980.h b/ANDROID_3.4.5/sound/soc/codecs/ad1980.h deleted file mode 100644 index eb0af44a..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ad1980.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * ad1980.h -- ad1980 Soc Audio driver - * - * WARNING: - * - * Because Analog Devices Inc. discontinued the ad1980 sound chip since - * Sep. 2009, this ad1980 driver is not maintained, tested and supported - * by ADI now. - */ - -#ifndef _AD1980_H -#define _AD1980_H -/* Bit definition of Power-Down Control/Status Register */ -#define ADC 0x0001 -#define DAC 0x0002 -#define ANL 0x0004 -#define REF 0x0008 -#define PR0 0x0100 -#define PR1 0x0200 -#define PR2 0x0400 -#define PR3 0x0800 -#define PR4 0x1000 -#define PR5 0x2000 -#define PR6 0x4000 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/ad73311.c b/ANDROID_3.4.5/sound/soc/codecs/ad73311.c deleted file mode 100644 index ee7a68dc..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ad73311.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * ad73311.c -- ALSA Soc AD73311 codec support - * - * Copyright: Analog Device Inc. - * Author: Cliff Cai - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ad73311.h" - -static struct snd_soc_dai_driver ad73311_dai = { - .name = "ad73311-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, }, -}; - -static struct snd_soc_codec_driver soc_codec_dev_ad73311; - -static int ad73311_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_ad73311, &ad73311_dai, 1); -} - -static int __devexit ad73311_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver ad73311_codec_driver = { - .driver = { - .name = "ad73311", - .owner = THIS_MODULE, - }, - - .probe = ad73311_probe, - .remove = __devexit_p(ad73311_remove), -}; - -module_platform_driver(ad73311_codec_driver); - -MODULE_DESCRIPTION("ASoC ad73311 driver"); -MODULE_AUTHOR("Cliff Cai "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ad73311.h b/ANDROID_3.4.5/sound/soc/codecs/ad73311.h deleted file mode 100644 index 4b353eef..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ad73311.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * File: sound/soc/codec/ad73311.h - * Based on: - * Author: Cliff Cai - * - * Created: Thur Sep 25, 2008 - * Description: definitions for AD73311 registers - * - * - * Modified: - * Copyright 2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __AD73311_H__ -#define __AD73311_H__ - -#define AD_CONTROL 0x8000 -#define AD_DATA 0x0000 -#define AD_READ 0x4000 -#define AD_WRITE 0x0000 - -/* Control register A */ -#define CTRL_REG_A (0 << 8) - -#define REGA_MODE_PRO 0x00 -#define REGA_MODE_DATA 0x01 -#define REGA_MODE_MIXED 0x03 -#define REGA_DLB 0x04 -#define REGA_SLB 0x08 -#define REGA_DEVC(x) ((x & 0x7) << 4) -#define REGA_RESET 0x80 - -/* Control register B */ -#define CTRL_REG_B (1 << 8) - -#define REGB_DIRATE(x) (x & 0x3) -#define REGB_SCDIV(x) ((x & 0x3) << 2) -#define REGB_MCDIV(x) ((x & 0x7) << 4) -#define REGB_CEE (1 << 7) - -/* Control register C */ -#define CTRL_REG_C (2 << 8) - -#define REGC_PUDEV (1 << 0) -#define REGC_PUADC (1 << 3) -#define REGC_PUDAC (1 << 4) -#define REGC_PUREF (1 << 5) -#define REGC_REFUSE (1 << 6) - -/* Control register D */ -#define CTRL_REG_D (3 << 8) - -#define REGD_IGS(x) (x & 0x7) -#define REGD_RMOD (1 << 3) -#define REGD_OGS(x) ((x & 0x7) << 4) -#define REGD_MUTE (1 << 7) - -/* Control register E */ -#define CTRL_REG_E (4 << 8) - -#define REGE_DA(x) (x & 0x1f) -#define REGE_IBYP (1 << 5) - -/* Control register F */ -#define CTRL_REG_F (5 << 8) - -#define REGF_SEEN (1 << 5) -#define REGF_INV (1 << 6) -#define REGF_ALB (1 << 7) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/adau1373.c b/ANDROID_3.4.5/sound/soc/codecs/adau1373.c deleted file mode 100644 index 44f59064..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/adau1373.c +++ /dev/null @@ -1,1409 +0,0 @@ -/* - * Analog Devices ADAU1373 Audio Codec drive - * - * Copyright 2011 Analog Devices Inc. - * Author: Lars-Peter Clausen - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "adau1373.h" - -struct adau1373_dai { - unsigned int clk_src; - unsigned int sysclk; - bool enable_src; - bool master; -}; - -struct adau1373 { - struct adau1373_dai dais[3]; -}; - -#define ADAU1373_INPUT_MODE 0x00 -#define ADAU1373_AINL_CTRL(x) (0x01 + (x) * 2) -#define ADAU1373_AINR_CTRL(x) (0x02 + (x) * 2) -#define ADAU1373_LLINE_OUT(x) (0x9 + (x) * 2) -#define ADAU1373_RLINE_OUT(x) (0xa + (x) * 2) -#define ADAU1373_LSPK_OUT 0x0d -#define ADAU1373_RSPK_OUT 0x0e -#define ADAU1373_LHP_OUT 0x0f -#define ADAU1373_RHP_OUT 0x10 -#define ADAU1373_ADC_GAIN 0x11 -#define ADAU1373_LADC_MIXER 0x12 -#define ADAU1373_RADC_MIXER 0x13 -#define ADAU1373_LLINE1_MIX 0x14 -#define ADAU1373_RLINE1_MIX 0x15 -#define ADAU1373_LLINE2_MIX 0x16 -#define ADAU1373_RLINE2_MIX 0x17 -#define ADAU1373_LSPK_MIX 0x18 -#define ADAU1373_RSPK_MIX 0x19 -#define ADAU1373_LHP_MIX 0x1a -#define ADAU1373_RHP_MIX 0x1b -#define ADAU1373_EP_MIX 0x1c -#define ADAU1373_HP_CTRL 0x1d -#define ADAU1373_HP_CTRL2 0x1e -#define ADAU1373_LS_CTRL 0x1f -#define ADAU1373_EP_CTRL 0x21 -#define ADAU1373_MICBIAS_CTRL1 0x22 -#define ADAU1373_MICBIAS_CTRL2 0x23 -#define ADAU1373_OUTPUT_CTRL 0x24 -#define ADAU1373_PWDN_CTRL1 0x25 -#define ADAU1373_PWDN_CTRL2 0x26 -#define ADAU1373_PWDN_CTRL3 0x27 -#define ADAU1373_DPLL_CTRL(x) (0x28 + (x) * 7) -#define ADAU1373_PLL_CTRL1(x) (0x29 + (x) * 7) -#define ADAU1373_PLL_CTRL2(x) (0x2a + (x) * 7) -#define ADAU1373_PLL_CTRL3(x) (0x2b + (x) * 7) -#define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7) -#define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7) -#define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7) -#define ADAU1373_PLL_CTRL7(x) (0x2f + (x) * 7) -#define ADAU1373_HEADDECT 0x36 -#define ADAU1373_ADC_DAC_STATUS 0x37 -#define ADAU1373_ADC_CTRL 0x3c -#define ADAU1373_DAI(x) (0x44 + (x)) -#define ADAU1373_CLK_SRC_DIV(x) (0x40 + (x) * 2) -#define ADAU1373_BCLKDIV(x) (0x47 + (x)) -#define ADAU1373_SRC_RATIOA(x) (0x4a + (x) * 2) -#define ADAU1373_SRC_RATIOB(x) (0x4b + (x) * 2) -#define ADAU1373_DEEMP_CTRL 0x50 -#define ADAU1373_SRC_DAI_CTRL(x) (0x51 + (x)) -#define ADAU1373_DIN_MIX_CTRL(x) (0x56 + (x)) -#define ADAU1373_DOUT_MIX_CTRL(x) (0x5b + (x)) -#define ADAU1373_DAI_PBL_VOL(x) (0x62 + (x) * 2) -#define ADAU1373_DAI_PBR_VOL(x) (0x63 + (x) * 2) -#define ADAU1373_DAI_RECL_VOL(x) (0x68 + (x) * 2) -#define ADAU1373_DAI_RECR_VOL(x) (0x69 + (x) * 2) -#define ADAU1373_DAC1_PBL_VOL 0x6e -#define ADAU1373_DAC1_PBR_VOL 0x6f -#define ADAU1373_DAC2_PBL_VOL 0x70 -#define ADAU1373_DAC2_PBR_VOL 0x71 -#define ADAU1373_ADC_RECL_VOL 0x72 -#define ADAU1373_ADC_RECR_VOL 0x73 -#define ADAU1373_DMIC_RECL_VOL 0x74 -#define ADAU1373_DMIC_RECR_VOL 0x75 -#define ADAU1373_VOL_GAIN1 0x76 -#define ADAU1373_VOL_GAIN2 0x77 -#define ADAU1373_VOL_GAIN3 0x78 -#define ADAU1373_HPF_CTRL 0x7d -#define ADAU1373_BASS1 0x7e -#define ADAU1373_BASS2 0x7f -#define ADAU1373_DRC(x) (0x80 + (x) * 0x10) -#define ADAU1373_3D_CTRL1 0xc0 -#define ADAU1373_3D_CTRL2 0xc1 -#define ADAU1373_FDSP_SEL1 0xdc -#define ADAU1373_FDSP_SEL2 0xdd -#define ADAU1373_FDSP_SEL3 0xde -#define ADAU1373_FDSP_SEL4 0xdf -#define ADAU1373_DIGMICCTRL 0xe2 -#define ADAU1373_DIGEN 0xeb -#define ADAU1373_SOFT_RESET 0xff - - -#define ADAU1373_PLL_CTRL6_DPLL_BYPASS BIT(1) -#define ADAU1373_PLL_CTRL6_PLL_EN BIT(0) - -#define ADAU1373_DAI_INVERT_BCLK BIT(7) -#define ADAU1373_DAI_MASTER BIT(6) -#define ADAU1373_DAI_INVERT_LRCLK BIT(4) -#define ADAU1373_DAI_WLEN_16 0x0 -#define ADAU1373_DAI_WLEN_20 0x4 -#define ADAU1373_DAI_WLEN_24 0x8 -#define ADAU1373_DAI_WLEN_32 0xc -#define ADAU1373_DAI_WLEN_MASK 0xc -#define ADAU1373_DAI_FORMAT_RIGHT_J 0x0 -#define ADAU1373_DAI_FORMAT_LEFT_J 0x1 -#define ADAU1373_DAI_FORMAT_I2S 0x2 -#define ADAU1373_DAI_FORMAT_DSP 0x3 - -#define ADAU1373_BCLKDIV_SOURCE BIT(5) -#define ADAU1373_BCLKDIV_32 0x03 -#define ADAU1373_BCLKDIV_64 0x02 -#define ADAU1373_BCLKDIV_128 0x01 -#define ADAU1373_BCLKDIV_256 0x00 - -#define ADAU1373_ADC_CTRL_PEAK_DETECT BIT(0) -#define ADAU1373_ADC_CTRL_RESET BIT(1) -#define ADAU1373_ADC_CTRL_RESET_FORCE BIT(2) - -#define ADAU1373_OUTPUT_CTRL_LDIFF BIT(3) -#define ADAU1373_OUTPUT_CTRL_LNFBEN BIT(2) - -#define ADAU1373_PWDN_CTRL3_PWR_EN BIT(0) - -#define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4 -#define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2 - -static const uint8_t adau1373_default_regs[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */ - 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */ - 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, - 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */ - 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, - 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */ - 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */ - 0x00, 0x1f, 0x0f, 0x00, 0x00, -}; - -static const unsigned int adau1373_out_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), - 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), - 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), - 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), -}; - -static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0); -static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1); -static const DECLARE_TLV_DB_SCALE(adau1373_ep_tlv, -600, 600, 1); - -static const DECLARE_TLV_DB_SCALE(adau1373_input_boost_tlv, 0, 2000, 0); -static const DECLARE_TLV_DB_SCALE(adau1373_gain_boost_tlv, 0, 600, 0); -static const DECLARE_TLV_DB_SCALE(adau1373_speaker_boost_tlv, 1200, 600, 0); - -static const char *adau1373_fdsp_sel_text[] = { - "None", - "Channel 1", - "Channel 2", - "Channel 3", - "Channel 4", - "Channel 5", -}; - -static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, - ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, - ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, - ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, - ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, - ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); - -static const char *adau1373_hpf_cutoff_text[] = { - "3.7Hz", "50Hz", "100Hz", "150Hz", "200Hz", "250Hz", "300Hz", "350Hz", - "400Hz", "450Hz", "500Hz", "550Hz", "600Hz", "650Hz", "700Hz", "750Hz", - "800Hz", -}; - -static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, - ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); - -static const char *adau1373_bass_lpf_cutoff_text[] = { - "801Hz", "1001Hz", -}; - -static const char *adau1373_bass_clip_level_text[] = { - "0.125", "0.250", "0.370", "0.500", "0.625", "0.750", "0.875", -}; - -static const unsigned int adau1373_bass_clip_level_values[] = { - 1, 2, 3, 4, 5, 6, 7, -}; - -static const char *adau1373_bass_hpf_cutoff_text[] = { - "158Hz", "232Hz", "347Hz", "520Hz", -}; - -static const unsigned int adau1373_bass_tlv[] = { - TLV_DB_RANGE_HEAD(3), - 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1), - 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0), - 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), -}; - -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, - ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); - -static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, - ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, - adau1373_bass_clip_level_values); - -static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, - ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); - -static const char *adau1373_3d_level_text[] = { - "0%", "6.67%", "13.33%", "20%", "26.67%", "33.33%", - "40%", "46.67%", "53.33%", "60%", "66.67%", "73.33%", - "80%", "86.67", "99.33%", "100%" -}; - -static const char *adau1373_3d_cutoff_text[] = { - "No 3D", "0.03125 fs", "0.04583 fs", "0.075 fs", "0.11458 fs", - "0.16875 fs", "0.27083 fs" -}; - -static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, - ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, - ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); - -static const unsigned int adau1373_3d_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), - 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120), -}; - -static const char *adau1373_lr_mux_text[] = { - "Mute", - "Right Channel (L+R)", - "Left Channel (L+R)", - "Stereo", -}; - -static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, - ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, - ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); -static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, - ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); - -static const struct snd_kcontrol_new adau1373_controls[] = { - SOC_DOUBLE_R_TLV("AIF1 Capture Volume", ADAU1373_DAI_RECL_VOL(0), - ADAU1373_DAI_RECR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv), - SOC_DOUBLE_R_TLV("AIF2 Capture Volume", ADAU1373_DAI_RECL_VOL(1), - ADAU1373_DAI_RECR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv), - SOC_DOUBLE_R_TLV("AIF3 Capture Volume", ADAU1373_DAI_RECL_VOL(2), - ADAU1373_DAI_RECR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv), - - SOC_DOUBLE_R_TLV("ADC Capture Volume", ADAU1373_ADC_RECL_VOL, - ADAU1373_ADC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv), - SOC_DOUBLE_R_TLV("DMIC Capture Volume", ADAU1373_DMIC_RECL_VOL, - ADAU1373_DMIC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv), - - SOC_DOUBLE_R_TLV("AIF1 Playback Volume", ADAU1373_DAI_PBL_VOL(0), - ADAU1373_DAI_PBR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv), - SOC_DOUBLE_R_TLV("AIF2 Playback Volume", ADAU1373_DAI_PBL_VOL(1), - ADAU1373_DAI_PBR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv), - SOC_DOUBLE_R_TLV("AIF3 Playback Volume", ADAU1373_DAI_PBL_VOL(2), - ADAU1373_DAI_PBR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv), - - SOC_DOUBLE_R_TLV("DAC1 Playback Volume", ADAU1373_DAC1_PBL_VOL, - ADAU1373_DAC1_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv), - SOC_DOUBLE_R_TLV("DAC2 Playback Volume", ADAU1373_DAC2_PBL_VOL, - ADAU1373_DAC2_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv), - - SOC_DOUBLE_R_TLV("Lineout1 Playback Volume", ADAU1373_LLINE_OUT(0), - ADAU1373_RLINE_OUT(0), 0, 0x1f, 0, adau1373_out_tlv), - SOC_DOUBLE_R_TLV("Speaker Playback Volume", ADAU1373_LSPK_OUT, - ADAU1373_RSPK_OUT, 0, 0x1f, 0, adau1373_out_tlv), - SOC_DOUBLE_R_TLV("Headphone Playback Volume", ADAU1373_LHP_OUT, - ADAU1373_RHP_OUT, 0, 0x1f, 0, adau1373_out_tlv), - - SOC_DOUBLE_R_TLV("Input 1 Capture Volume", ADAU1373_AINL_CTRL(0), - ADAU1373_AINR_CTRL(0), 0, 0x1f, 0, adau1373_in_pga_tlv), - SOC_DOUBLE_R_TLV("Input 2 Capture Volume", ADAU1373_AINL_CTRL(1), - ADAU1373_AINR_CTRL(1), 0, 0x1f, 0, adau1373_in_pga_tlv), - SOC_DOUBLE_R_TLV("Input 3 Capture Volume", ADAU1373_AINL_CTRL(2), - ADAU1373_AINR_CTRL(2), 0, 0x1f, 0, adau1373_in_pga_tlv), - SOC_DOUBLE_R_TLV("Input 4 Capture Volume", ADAU1373_AINL_CTRL(3), - ADAU1373_AINR_CTRL(3), 0, 0x1f, 0, adau1373_in_pga_tlv), - - SOC_SINGLE_TLV("Earpiece Playback Volume", ADAU1373_EP_CTRL, 0, 3, 0, - adau1373_ep_tlv), - - SOC_DOUBLE_TLV("AIF3 Boost Playback Volume", ADAU1373_VOL_GAIN1, 4, 5, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("AIF2 Boost Playback Volume", ADAU1373_VOL_GAIN1, 2, 3, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("AIF1 Boost Playback Volume", ADAU1373_VOL_GAIN1, 0, 1, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("AIF3 Boost Capture Volume", ADAU1373_VOL_GAIN2, 4, 5, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("AIF2 Boost Capture Volume", ADAU1373_VOL_GAIN2, 2, 3, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("AIF1 Boost Capture Volume", ADAU1373_VOL_GAIN2, 0, 1, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("DMIC Boost Capture Volume", ADAU1373_VOL_GAIN3, 6, 7, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("ADC Boost Capture Volume", ADAU1373_VOL_GAIN3, 4, 5, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("DAC2 Boost Playback Volume", ADAU1373_VOL_GAIN3, 2, 3, - 1, 0, adau1373_gain_boost_tlv), - SOC_DOUBLE_TLV("DAC1 Boost Playback Volume", ADAU1373_VOL_GAIN3, 0, 1, - 1, 0, adau1373_gain_boost_tlv), - - SOC_DOUBLE_TLV("Input 1 Boost Capture Volume", ADAU1373_ADC_GAIN, 0, 4, - 1, 0, adau1373_input_boost_tlv), - SOC_DOUBLE_TLV("Input 2 Boost Capture Volume", ADAU1373_ADC_GAIN, 1, 5, - 1, 0, adau1373_input_boost_tlv), - SOC_DOUBLE_TLV("Input 3 Boost Capture Volume", ADAU1373_ADC_GAIN, 2, 6, - 1, 0, adau1373_input_boost_tlv), - SOC_DOUBLE_TLV("Input 4 Boost Capture Volume", ADAU1373_ADC_GAIN, 3, 7, - 1, 0, adau1373_input_boost_tlv), - - SOC_DOUBLE_TLV("Speaker Boost Playback Volume", ADAU1373_LS_CTRL, 2, 3, - 1, 0, adau1373_speaker_boost_tlv), - - SOC_ENUM("Lineout1 LR Mux", adau1373_lineout1_lr_mux_enum), - SOC_ENUM("Speaker LR Mux", adau1373_speaker_lr_mux_enum), - - SOC_ENUM("HPF Cutoff", adau1373_hpf_cutoff_enum), - SOC_DOUBLE("HPF Switch", ADAU1373_HPF_CTRL, 1, 0, 1, 0), - SOC_ENUM("HPF Channel", adau1373_hpf_channel_enum), - - SOC_ENUM("Bass HPF Cutoff", adau1373_bass_hpf_cutoff_enum), - SOC_VALUE_ENUM("Bass Clip Level Threshold", - adau1373_bass_clip_level_enum), - SOC_ENUM("Bass LPF Cutoff", adau1373_bass_lpf_cutoff_enum), - SOC_DOUBLE("Bass Playback Switch", ADAU1373_BASS2, 0, 1, 1, 0), - SOC_SINGLE_TLV("Bass Playback Volume", ADAU1373_BASS2, 2, 7, 0, - adau1373_bass_tlv), - SOC_ENUM("Bass Channel", adau1373_bass_channel_enum), - - SOC_ENUM("3D Freq", adau1373_3d_cutoff_enum), - SOC_ENUM("3D Level", adau1373_3d_level_enum), - SOC_SINGLE("3D Playback Switch", ADAU1373_3D_CTRL2, 0, 1, 0), - SOC_SINGLE_TLV("3D Playback Volume", ADAU1373_3D_CTRL2, 2, 7, 0, - adau1373_3d_tlv), - SOC_ENUM("3D Channel", adau1373_bass_channel_enum), - - SOC_SINGLE("Zero Cross Switch", ADAU1373_PWDN_CTRL3, 7, 1, 0), -}; - -static const struct snd_kcontrol_new adau1373_lineout2_controls[] = { - SOC_DOUBLE_R_TLV("Lineout2 Playback Volume", ADAU1373_LLINE_OUT(1), - ADAU1373_RLINE_OUT(1), 0, 0x1f, 0, adau1373_out_tlv), - SOC_ENUM("Lineout2 LR Mux", adau1373_lineout2_lr_mux_enum), -}; - -static const struct snd_kcontrol_new adau1373_drc_controls[] = { - SOC_ENUM("DRC1 Channel", adau1373_drc1_channel_enum), - SOC_ENUM("DRC2 Channel", adau1373_drc2_channel_enum), - SOC_ENUM("DRC3 Channel", adau1373_drc3_channel_enum), -}; - -static int adau1373_pll_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - unsigned int pll_id = w->name[3] - '1'; - unsigned int val; - - if (SND_SOC_DAPM_EVENT_ON(event)) - val = ADAU1373_PLL_CTRL6_PLL_EN; - else - val = 0; - - snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), - ADAU1373_PLL_CTRL6_PLL_EN, val); - - if (SND_SOC_DAPM_EVENT_ON(event)) - mdelay(5); - - return 0; -} - -static const char *adau1373_decimator_text[] = { - "ADC", - "DMIC1", -}; - -static const struct soc_enum adau1373_decimator_enum = - SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); - -static const struct snd_kcontrol_new adau1373_decimator_mux = - SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); - -static const struct snd_kcontrol_new adau1373_left_adc_mixer_controls[] = { - SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_LADC_MIXER, 4, 1, 0), - SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_LADC_MIXER, 3, 1, 0), - SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_LADC_MIXER, 2, 1, 0), - SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_LADC_MIXER, 1, 1, 0), - SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_LADC_MIXER, 0, 1, 0), -}; - -static const struct snd_kcontrol_new adau1373_right_adc_mixer_controls[] = { - SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_RADC_MIXER, 4, 1, 0), - SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_RADC_MIXER, 3, 1, 0), - SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_RADC_MIXER, 2, 1, 0), - SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_RADC_MIXER, 1, 1, 0), - SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_RADC_MIXER, 0, 1, 0), -}; - -#define DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(_name, _reg) \ -const struct snd_kcontrol_new _name[] = { \ - SOC_DAPM_SINGLE("Left DAC2 Switch", _reg, 7, 1, 0), \ - SOC_DAPM_SINGLE("Right DAC2 Switch", _reg, 6, 1, 0), \ - SOC_DAPM_SINGLE("Left DAC1 Switch", _reg, 5, 1, 0), \ - SOC_DAPM_SINGLE("Right DAC1 Switch", _reg, 4, 1, 0), \ - SOC_DAPM_SINGLE("Input 4 Bypass Switch", _reg, 3, 1, 0), \ - SOC_DAPM_SINGLE("Input 3 Bypass Switch", _reg, 2, 1, 0), \ - SOC_DAPM_SINGLE("Input 2 Bypass Switch", _reg, 1, 1, 0), \ - SOC_DAPM_SINGLE("Input 1 Bypass Switch", _reg, 0, 1, 0), \ -} - -static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line1_mixer_controls, - ADAU1373_LLINE1_MIX); -static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line1_mixer_controls, - ADAU1373_RLINE1_MIX); -static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line2_mixer_controls, - ADAU1373_LLINE2_MIX); -static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line2_mixer_controls, - ADAU1373_RLINE2_MIX); -static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_spk_mixer_controls, - ADAU1373_LSPK_MIX); -static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_spk_mixer_controls, - ADAU1373_RSPK_MIX); -static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_ep_mixer_controls, - ADAU1373_EP_MIX); - -static const struct snd_kcontrol_new adau1373_left_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", ADAU1373_LHP_MIX, 5, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", ADAU1373_LHP_MIX, 4, 1, 0), - SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_LHP_MIX, 3, 1, 0), - SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_LHP_MIX, 2, 1, 0), - SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_LHP_MIX, 1, 1, 0), - SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_LHP_MIX, 0, 1, 0), -}; - -static const struct snd_kcontrol_new adau1373_right_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Right DAC1 Switch", ADAU1373_RHP_MIX, 5, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", ADAU1373_RHP_MIX, 4, 1, 0), - SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_RHP_MIX, 3, 1, 0), - SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_RHP_MIX, 2, 1, 0), - SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_RHP_MIX, 1, 1, 0), - SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_RHP_MIX, 0, 1, 0), -}; - -#define DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(_name, _reg) \ -const struct snd_kcontrol_new _name[] = { \ - SOC_DAPM_SINGLE("DMIC2 Swapped Switch", _reg, 6, 1, 0), \ - SOC_DAPM_SINGLE("DMIC2 Switch", _reg, 5, 1, 0), \ - SOC_DAPM_SINGLE("ADC/DMIC1 Swapped Switch", _reg, 4, 1, 0), \ - SOC_DAPM_SINGLE("ADC/DMIC1 Switch", _reg, 3, 1, 0), \ - SOC_DAPM_SINGLE("AIF3 Switch", _reg, 2, 1, 0), \ - SOC_DAPM_SINGLE("AIF2 Switch", _reg, 1, 1, 0), \ - SOC_DAPM_SINGLE("AIF1 Switch", _reg, 0, 1, 0), \ -} - -static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel1_mixer_controls, - ADAU1373_DIN_MIX_CTRL(0)); -static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel2_mixer_controls, - ADAU1373_DIN_MIX_CTRL(1)); -static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel3_mixer_controls, - ADAU1373_DIN_MIX_CTRL(2)); -static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel4_mixer_controls, - ADAU1373_DIN_MIX_CTRL(3)); -static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel5_mixer_controls, - ADAU1373_DIN_MIX_CTRL(4)); - -#define DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(_name, _reg) \ -const struct snd_kcontrol_new _name[] = { \ - SOC_DAPM_SINGLE("DSP Channel5 Switch", _reg, 4, 1, 0), \ - SOC_DAPM_SINGLE("DSP Channel4 Switch", _reg, 3, 1, 0), \ - SOC_DAPM_SINGLE("DSP Channel3 Switch", _reg, 2, 1, 0), \ - SOC_DAPM_SINGLE("DSP Channel2 Switch", _reg, 1, 1, 0), \ - SOC_DAPM_SINGLE("DSP Channel1 Switch", _reg, 0, 1, 0), \ -} - -static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif1_mixer_controls, - ADAU1373_DOUT_MIX_CTRL(0)); -static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif2_mixer_controls, - ADAU1373_DOUT_MIX_CTRL(1)); -static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif3_mixer_controls, - ADAU1373_DOUT_MIX_CTRL(2)); -static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac1_mixer_controls, - ADAU1373_DOUT_MIX_CTRL(3)); -static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac2_mixer_controls, - ADAU1373_DOUT_MIX_CTRL(4)); - -static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = { - /* Datasheet claims Left ADC is bit 6 and Right ADC is bit 7, but that - * doesn't seem to be the case. */ - SND_SOC_DAPM_ADC("Left ADC", NULL, ADAU1373_PWDN_CTRL1, 7, 0), - SND_SOC_DAPM_ADC("Right ADC", NULL, ADAU1373_PWDN_CTRL1, 6, 0), - - SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1373_DIGMICCTRL, 0, 0), - SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1373_DIGMICCTRL, 2, 0), - - SND_SOC_DAPM_VIRT_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0, - &adau1373_decimator_mux), - - SND_SOC_DAPM_SUPPLY("MICBIAS2", ADAU1373_PWDN_CTRL1, 5, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("MICBIAS1", ADAU1373_PWDN_CTRL1, 4, 0, NULL, 0), - - SND_SOC_DAPM_PGA("IN4PGA", ADAU1373_PWDN_CTRL1, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("IN3PGA", ADAU1373_PWDN_CTRL1, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("IN2PGA", ADAU1373_PWDN_CTRL1, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("IN1PGA", ADAU1373_PWDN_CTRL1, 0, 0, NULL, 0), - - SND_SOC_DAPM_DAC("Left DAC2", NULL, ADAU1373_PWDN_CTRL2, 7, 0), - SND_SOC_DAPM_DAC("Right DAC2", NULL, ADAU1373_PWDN_CTRL2, 6, 0), - SND_SOC_DAPM_DAC("Left DAC1", NULL, ADAU1373_PWDN_CTRL2, 5, 0), - SND_SOC_DAPM_DAC("Right DAC1", NULL, ADAU1373_PWDN_CTRL2, 4, 0), - - SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0, - adau1373_left_adc_mixer_controls), - SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0, - adau1373_right_adc_mixer_controls), - - SOC_MIXER_ARRAY("Left Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 3, 0, - adau1373_left_line2_mixer_controls), - SOC_MIXER_ARRAY("Right Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 2, 0, - adau1373_right_line2_mixer_controls), - SOC_MIXER_ARRAY("Left Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 1, 0, - adau1373_left_line1_mixer_controls), - SOC_MIXER_ARRAY("Right Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 0, 0, - adau1373_right_line1_mixer_controls), - - SOC_MIXER_ARRAY("Earpiece Mixer", ADAU1373_PWDN_CTRL3, 4, 0, - adau1373_ep_mixer_controls), - SOC_MIXER_ARRAY("Left Speaker Mixer", ADAU1373_PWDN_CTRL3, 3, 0, - adau1373_left_spk_mixer_controls), - SOC_MIXER_ARRAY("Right Speaker Mixer", ADAU1373_PWDN_CTRL3, 2, 0, - adau1373_right_spk_mixer_controls), - SOC_MIXER_ARRAY("Left Headphone Mixer", SND_SOC_NOPM, 0, 0, - adau1373_left_hp_mixer_controls), - SOC_MIXER_ARRAY("Right Headphone Mixer", SND_SOC_NOPM, 0, 0, - adau1373_right_hp_mixer_controls), - SND_SOC_DAPM_SUPPLY("Headphone Enable", ADAU1373_PWDN_CTRL3, 1, 0, - NULL, 0), - - SND_SOC_DAPM_SUPPLY("AIF1 CLK", ADAU1373_SRC_DAI_CTRL(0), 0, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF2 CLK", ADAU1373_SRC_DAI_CTRL(1), 0, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF3 CLK", ADAU1373_SRC_DAI_CTRL(2), 0, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF1 IN SRC", ADAU1373_SRC_DAI_CTRL(0), 2, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF1 OUT SRC", ADAU1373_SRC_DAI_CTRL(0), 1, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF2 IN SRC", ADAU1373_SRC_DAI_CTRL(1), 2, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF2 OUT SRC", ADAU1373_SRC_DAI_CTRL(1), 1, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF3 IN SRC", ADAU1373_SRC_DAI_CTRL(2), 2, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF3 OUT SRC", ADAU1373_SRC_DAI_CTRL(2), 1, 0, - NULL, 0), - - SND_SOC_DAPM_AIF_IN("AIF1 IN", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_OUT("AIF1 OUT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_IN("AIF2 IN", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_OUT("AIF2 OUT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_IN("AIF3 IN", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_OUT("AIF3 OUT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0), - - SOC_MIXER_ARRAY("DSP Channel1 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_dsp_channel1_mixer_controls), - SOC_MIXER_ARRAY("DSP Channel2 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_dsp_channel2_mixer_controls), - SOC_MIXER_ARRAY("DSP Channel3 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_dsp_channel3_mixer_controls), - SOC_MIXER_ARRAY("DSP Channel4 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_dsp_channel4_mixer_controls), - SOC_MIXER_ARRAY("DSP Channel5 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_dsp_channel5_mixer_controls), - - SOC_MIXER_ARRAY("AIF1 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_aif1_mixer_controls), - SOC_MIXER_ARRAY("AIF2 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_aif2_mixer_controls), - SOC_MIXER_ARRAY("AIF3 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_aif3_mixer_controls), - SOC_MIXER_ARRAY("DAC1 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_dac1_mixer_controls), - SOC_MIXER_ARRAY("DAC2 Mixer", SND_SOC_NOPM, 0, 0, - adau1373_dac2_mixer_controls), - - SND_SOC_DAPM_SUPPLY("DSP", ADAU1373_DIGEN, 4, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Recording Engine B", ADAU1373_DIGEN, 3, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Recording Engine A", ADAU1373_DIGEN, 2, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Playback Engine B", ADAU1373_DIGEN, 1, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Playback Engine A", ADAU1373_DIGEN, 0, 0, NULL, 0), - - SND_SOC_DAPM_SUPPLY("PLL1", SND_SOC_NOPM, 0, 0, adau1373_pll_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_SUPPLY("PLL2", SND_SOC_NOPM, 0, 0, adau1373_pll_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_SUPPLY("SYSCLK1", ADAU1373_CLK_SRC_DIV(0), 7, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("SYSCLK2", ADAU1373_CLK_SRC_DIV(1), 7, 0, NULL, 0), - - SND_SOC_DAPM_INPUT("AIN1L"), - SND_SOC_DAPM_INPUT("AIN1R"), - SND_SOC_DAPM_INPUT("AIN2L"), - SND_SOC_DAPM_INPUT("AIN2R"), - SND_SOC_DAPM_INPUT("AIN3L"), - SND_SOC_DAPM_INPUT("AIN3R"), - SND_SOC_DAPM_INPUT("AIN4L"), - SND_SOC_DAPM_INPUT("AIN4R"), - - SND_SOC_DAPM_INPUT("DMIC1DAT"), - SND_SOC_DAPM_INPUT("DMIC2DAT"), - - SND_SOC_DAPM_OUTPUT("LOUT1L"), - SND_SOC_DAPM_OUTPUT("LOUT1R"), - SND_SOC_DAPM_OUTPUT("LOUT2L"), - SND_SOC_DAPM_OUTPUT("LOUT2R"), - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - SND_SOC_DAPM_OUTPUT("SPKL"), - SND_SOC_DAPM_OUTPUT("SPKR"), - SND_SOC_DAPM_OUTPUT("EP"), -}; - -static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - struct snd_soc_codec *codec = source->codec; - struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); - unsigned int dai; - const char *clk; - - dai = sink->name[3] - '1'; - - if (!adau1373->dais[dai].master) - return 0; - - if (adau1373->dais[dai].clk_src == ADAU1373_CLK_SRC_PLL1) - clk = "SYSCLK1"; - else - clk = "SYSCLK2"; - - return strcmp(source->name, clk) == 0; -} - -static int adau1373_check_src(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - struct snd_soc_codec *codec = source->codec; - struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); - unsigned int dai; - - dai = sink->name[3] - '1'; - - return adau1373->dais[dai].enable_src; -} - -#define DSP_CHANNEL_MIXER_ROUTES(_sink) \ - { _sink, "DMIC2 Swapped Switch", "DMIC2" }, \ - { _sink, "DMIC2 Switch", "DMIC2" }, \ - { _sink, "ADC/DMIC1 Swapped Switch", "Decimator Mux" }, \ - { _sink, "ADC/DMIC1 Switch", "Decimator Mux" }, \ - { _sink, "AIF1 Switch", "AIF1 IN" }, \ - { _sink, "AIF2 Switch", "AIF2 IN" }, \ - { _sink, "AIF3 Switch", "AIF3 IN" } - -#define DSP_OUTPUT_MIXER_ROUTES(_sink) \ - { _sink, "DSP Channel1 Switch", "DSP Channel1 Mixer" }, \ - { _sink, "DSP Channel2 Switch", "DSP Channel2 Mixer" }, \ - { _sink, "DSP Channel3 Switch", "DSP Channel3 Mixer" }, \ - { _sink, "DSP Channel4 Switch", "DSP Channel4 Mixer" }, \ - { _sink, "DSP Channel5 Switch", "DSP Channel5 Mixer" } - -#define LEFT_OUTPUT_MIXER_ROUTES(_sink) \ - { _sink, "Right DAC2 Switch", "Right DAC2" }, \ - { _sink, "Left DAC2 Switch", "Left DAC2" }, \ - { _sink, "Right DAC1 Switch", "Right DAC1" }, \ - { _sink, "Left DAC1 Switch", "Left DAC1" }, \ - { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \ - { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \ - { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \ - { _sink, "Input 4 Bypass Switch", "IN4PGA" } - -#define RIGHT_OUTPUT_MIXER_ROUTES(_sink) \ - { _sink, "Right DAC2 Switch", "Right DAC2" }, \ - { _sink, "Left DAC2 Switch", "Left DAC2" }, \ - { _sink, "Right DAC1 Switch", "Right DAC1" }, \ - { _sink, "Left DAC1 Switch", "Left DAC1" }, \ - { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \ - { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \ - { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \ - { _sink, "Input 4 Bypass Switch", "IN4PGA" } - -static const struct snd_soc_dapm_route adau1373_dapm_routes[] = { - { "Left ADC Mixer", "DAC1 Switch", "Left DAC1" }, - { "Left ADC Mixer", "Input 1 Switch", "IN1PGA" }, - { "Left ADC Mixer", "Input 2 Switch", "IN2PGA" }, - { "Left ADC Mixer", "Input 3 Switch", "IN3PGA" }, - { "Left ADC Mixer", "Input 4 Switch", "IN4PGA" }, - - { "Right ADC Mixer", "DAC1 Switch", "Right DAC1" }, - { "Right ADC Mixer", "Input 1 Switch", "IN1PGA" }, - { "Right ADC Mixer", "Input 2 Switch", "IN2PGA" }, - { "Right ADC Mixer", "Input 3 Switch", "IN3PGA" }, - { "Right ADC Mixer", "Input 4 Switch", "IN4PGA" }, - - { "Left ADC", NULL, "Left ADC Mixer" }, - { "Right ADC", NULL, "Right ADC Mixer" }, - - { "Decimator Mux", "ADC", "Left ADC" }, - { "Decimator Mux", "ADC", "Right ADC" }, - { "Decimator Mux", "DMIC1", "DMIC1" }, - - DSP_CHANNEL_MIXER_ROUTES("DSP Channel1 Mixer"), - DSP_CHANNEL_MIXER_ROUTES("DSP Channel2 Mixer"), - DSP_CHANNEL_MIXER_ROUTES("DSP Channel3 Mixer"), - DSP_CHANNEL_MIXER_ROUTES("DSP Channel4 Mixer"), - DSP_CHANNEL_MIXER_ROUTES("DSP Channel5 Mixer"), - - DSP_OUTPUT_MIXER_ROUTES("AIF1 Mixer"), - DSP_OUTPUT_MIXER_ROUTES("AIF2 Mixer"), - DSP_OUTPUT_MIXER_ROUTES("AIF3 Mixer"), - DSP_OUTPUT_MIXER_ROUTES("DAC1 Mixer"), - DSP_OUTPUT_MIXER_ROUTES("DAC2 Mixer"), - - { "AIF1 OUT", NULL, "AIF1 Mixer" }, - { "AIF2 OUT", NULL, "AIF2 Mixer" }, - { "AIF3 OUT", NULL, "AIF3 Mixer" }, - { "Left DAC1", NULL, "DAC1 Mixer" }, - { "Right DAC1", NULL, "DAC1 Mixer" }, - { "Left DAC2", NULL, "DAC2 Mixer" }, - { "Right DAC2", NULL, "DAC2 Mixer" }, - - LEFT_OUTPUT_MIXER_ROUTES("Left Lineout1 Mixer"), - RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout1 Mixer"), - LEFT_OUTPUT_MIXER_ROUTES("Left Lineout2 Mixer"), - RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout2 Mixer"), - LEFT_OUTPUT_MIXER_ROUTES("Left Speaker Mixer"), - RIGHT_OUTPUT_MIXER_ROUTES("Right Speaker Mixer"), - - { "Left Headphone Mixer", "Left DAC2 Switch", "Left DAC2" }, - { "Left Headphone Mixer", "Left DAC1 Switch", "Left DAC1" }, - { "Left Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" }, - { "Left Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" }, - { "Left Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" }, - { "Left Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" }, - { "Right Headphone Mixer", "Right DAC2 Switch", "Right DAC2" }, - { "Right Headphone Mixer", "Right DAC1 Switch", "Right DAC1" }, - { "Right Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" }, - { "Right Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" }, - { "Right Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" }, - { "Right Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" }, - - { "Left Headphone Mixer", NULL, "Headphone Enable" }, - { "Right Headphone Mixer", NULL, "Headphone Enable" }, - - { "Earpiece Mixer", "Right DAC2 Switch", "Right DAC2" }, - { "Earpiece Mixer", "Left DAC2 Switch", "Left DAC2" }, - { "Earpiece Mixer", "Right DAC1 Switch", "Right DAC1" }, - { "Earpiece Mixer", "Left DAC1 Switch", "Left DAC1" }, - { "Earpiece Mixer", "Input 1 Bypass Switch", "IN1PGA" }, - { "Earpiece Mixer", "Input 2 Bypass Switch", "IN2PGA" }, - { "Earpiece Mixer", "Input 3 Bypass Switch", "IN3PGA" }, - { "Earpiece Mixer", "Input 4 Bypass Switch", "IN4PGA" }, - - { "LOUT1L", NULL, "Left Lineout1 Mixer" }, - { "LOUT1R", NULL, "Right Lineout1 Mixer" }, - { "LOUT2L", NULL, "Left Lineout2 Mixer" }, - { "LOUT2R", NULL, "Right Lineout2 Mixer" }, - { "SPKL", NULL, "Left Speaker Mixer" }, - { "SPKR", NULL, "Right Speaker Mixer" }, - { "HPL", NULL, "Left Headphone Mixer" }, - { "HPR", NULL, "Right Headphone Mixer" }, - { "EP", NULL, "Earpiece Mixer" }, - - { "IN1PGA", NULL, "AIN1L" }, - { "IN2PGA", NULL, "AIN2L" }, - { "IN3PGA", NULL, "AIN3L" }, - { "IN4PGA", NULL, "AIN4L" }, - { "IN1PGA", NULL, "AIN1R" }, - { "IN2PGA", NULL, "AIN2R" }, - { "IN3PGA", NULL, "AIN3R" }, - { "IN4PGA", NULL, "AIN4R" }, - - { "SYSCLK1", NULL, "PLL1" }, - { "SYSCLK2", NULL, "PLL2" }, - - { "Left DAC1", NULL, "SYSCLK1" }, - { "Right DAC1", NULL, "SYSCLK1" }, - { "Left DAC2", NULL, "SYSCLK1" }, - { "Right DAC2", NULL, "SYSCLK1" }, - { "Left ADC", NULL, "SYSCLK1" }, - { "Right ADC", NULL, "SYSCLK1" }, - - { "DSP", NULL, "SYSCLK1" }, - - { "AIF1 Mixer", NULL, "DSP" }, - { "AIF2 Mixer", NULL, "DSP" }, - { "AIF3 Mixer", NULL, "DSP" }, - { "DAC1 Mixer", NULL, "DSP" }, - { "DAC2 Mixer", NULL, "DSP" }, - { "DAC1 Mixer", NULL, "Playback Engine A" }, - { "DAC2 Mixer", NULL, "Playback Engine B" }, - { "Left ADC Mixer", NULL, "Recording Engine A" }, - { "Right ADC Mixer", NULL, "Recording Engine A" }, - - { "AIF1 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, - { "AIF2 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, - { "AIF3 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, - { "AIF1 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, - { "AIF2 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, - { "AIF3 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, - - { "AIF1 IN", NULL, "AIF1 CLK" }, - { "AIF1 OUT", NULL, "AIF1 CLK" }, - { "AIF2 IN", NULL, "AIF2 CLK" }, - { "AIF2 OUT", NULL, "AIF2 CLK" }, - { "AIF3 IN", NULL, "AIF3 CLK" }, - { "AIF3 OUT", NULL, "AIF3 CLK" }, - { "AIF1 IN", NULL, "AIF1 IN SRC", adau1373_check_src }, - { "AIF1 OUT", NULL, "AIF1 OUT SRC", adau1373_check_src }, - { "AIF2 IN", NULL, "AIF2 IN SRC", adau1373_check_src }, - { "AIF2 OUT", NULL, "AIF2 OUT SRC", adau1373_check_src }, - { "AIF3 IN", NULL, "AIF3 IN SRC", adau1373_check_src }, - { "AIF3 OUT", NULL, "AIF3 OUT SRC", adau1373_check_src }, - - { "DMIC1", NULL, "DMIC1DAT" }, - { "DMIC1", NULL, "SYSCLK1" }, - { "DMIC1", NULL, "Recording Engine A" }, - { "DMIC2", NULL, "DMIC2DAT" }, - { "DMIC2", NULL, "SYSCLK1" }, - { "DMIC2", NULL, "Recording Engine B" }, -}; - -static int adau1373_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); - struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; - unsigned int div; - unsigned int freq; - unsigned int ctrl; - - freq = adau1373_dai->sysclk; - - if (freq % params_rate(params) != 0) - return -EINVAL; - - switch (freq / params_rate(params)) { - case 1024: /* sysclk / 256 */ - div = 0; - break; - case 1536: /* 2/3 sysclk / 256 */ - div = 1; - break; - case 2048: /* 1/2 sysclk / 256 */ - div = 2; - break; - case 3072: /* 1/3 sysclk / 256 */ - div = 3; - break; - case 4096: /* 1/4 sysclk / 256 */ - div = 4; - break; - case 6144: /* 1/6 sysclk / 256 */ - div = 5; - break; - case 5632: /* 2/11 sysclk / 256 */ - div = 6; - break; - default: - return -EINVAL; - } - - adau1373_dai->enable_src = (div != 0); - - snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), - ~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - ctrl = ADAU1373_DAI_WLEN_16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - ctrl = ADAU1373_DAI_WLEN_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - ctrl = ADAU1373_DAI_WLEN_24; - break; - case SNDRV_PCM_FORMAT_S32_LE: - ctrl = ADAU1373_DAI_WLEN_32; - break; - default: - return -EINVAL; - } - - return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), - ADAU1373_DAI_WLEN_MASK, ctrl); -} - -static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); - struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; - unsigned int ctrl; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - ctrl = ADAU1373_DAI_MASTER; - adau1373_dai->master = true; - break; - case SND_SOC_DAIFMT_CBS_CFS: - ctrl = 0; - adau1373_dai->master = false; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - ctrl |= ADAU1373_DAI_FORMAT_I2S; - break; - case SND_SOC_DAIFMT_LEFT_J: - ctrl |= ADAU1373_DAI_FORMAT_LEFT_J; - break; - case SND_SOC_DAIFMT_RIGHT_J: - ctrl |= ADAU1373_DAI_FORMAT_RIGHT_J; - break; - case SND_SOC_DAIFMT_DSP_B: - ctrl |= ADAU1373_DAI_FORMAT_DSP; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - ctrl |= ADAU1373_DAI_INVERT_BCLK; - break; - case SND_SOC_DAIFMT_NB_IF: - ctrl |= ADAU1373_DAI_INVERT_LRCLK; - break; - case SND_SOC_DAIFMT_IB_IF: - ctrl |= ADAU1373_DAI_INVERT_LRCLK | ADAU1373_DAI_INVERT_BCLK; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), - ~ADAU1373_DAI_WLEN_MASK, ctrl); - - return 0; -} - -static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(dai->codec); - struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; - - switch (clk_id) { - case ADAU1373_CLK_SRC_PLL1: - case ADAU1373_CLK_SRC_PLL2: - break; - default: - return -EINVAL; - } - - adau1373_dai->sysclk = freq; - adau1373_dai->clk_src = clk_id; - - snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id), - ADAU1373_BCLKDIV_SOURCE, clk_id << 5); - - return 0; -} - -static const struct snd_soc_dai_ops adau1373_dai_ops = { - .hw_params = adau1373_hw_params, - .set_sysclk = adau1373_set_dai_sysclk, - .set_fmt = adau1373_set_dai_fmt, -}; - -#define ADAU1373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_driver adau1373_dai_driver[] = { - { - .id = 0, - .name = "adau1373-aif1", - .playback = { - .stream_name = "AIF1 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ADAU1373_FORMATS, - }, - .capture = { - .stream_name = "AIF1 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ADAU1373_FORMATS, - }, - .ops = &adau1373_dai_ops, - .symmetric_rates = 1, - }, - { - .id = 1, - .name = "adau1373-aif2", - .playback = { - .stream_name = "AIF2 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ADAU1373_FORMATS, - }, - .capture = { - .stream_name = "AIF2 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ADAU1373_FORMATS, - }, - .ops = &adau1373_dai_ops, - .symmetric_rates = 1, - }, - { - .id = 2, - .name = "adau1373-aif3", - .playback = { - .stream_name = "AIF3 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ADAU1373_FORMATS, - }, - .capture = { - .stream_name = "AIF3 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ADAU1373_FORMATS, - }, - .ops = &adau1373_dai_ops, - .symmetric_rates = 1, - }, -}; - -static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - unsigned int dpll_div = 0; - unsigned int x, r, n, m, i, j, mode; - - switch (pll_id) { - case ADAU1373_PLL1: - case ADAU1373_PLL2: - break; - default: - return -EINVAL; - } - - switch (source) { - case ADAU1373_PLL_SRC_BCLK1: - case ADAU1373_PLL_SRC_BCLK2: - case ADAU1373_PLL_SRC_BCLK3: - case ADAU1373_PLL_SRC_LRCLK1: - case ADAU1373_PLL_SRC_LRCLK2: - case ADAU1373_PLL_SRC_LRCLK3: - case ADAU1373_PLL_SRC_MCLK1: - case ADAU1373_PLL_SRC_MCLK2: - case ADAU1373_PLL_SRC_GPIO1: - case ADAU1373_PLL_SRC_GPIO2: - case ADAU1373_PLL_SRC_GPIO3: - case ADAU1373_PLL_SRC_GPIO4: - break; - default: - return -EINVAL; - } - - if (freq_in < 7813 || freq_in > 27000000) - return -EINVAL; - - if (freq_out < 45158000 || freq_out > 49152000) - return -EINVAL; - - /* APLL input needs to be >= 8Mhz, so in case freq_in is less we use the - * DPLL to get it there. DPLL_out = (DPLL_in / div) * 1024 */ - while (freq_in < 8000000) { - freq_in *= 2; - dpll_div++; - } - - if (freq_out % freq_in != 0) { - /* fout = fin * (r + (n/m)) / x */ - x = DIV_ROUND_UP(freq_in, 13500000); - freq_in /= x; - r = freq_out / freq_in; - i = freq_out % freq_in; - j = gcd(i, freq_in); - n = i / j; - m = freq_in / j; - x--; - mode = 1; - } else { - /* fout = fin / r */ - r = freq_out / freq_in; - n = 0; - m = 0; - x = 0; - mode = 0; - } - - if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff) - return -EINVAL; - - if (dpll_div) { - dpll_div = 11 - dpll_div; - snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), - ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0); - } else { - snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), - ADAU1373_PLL_CTRL6_DPLL_BYPASS, - ADAU1373_PLL_CTRL6_DPLL_BYPASS); - } - - snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id), - (source << 4) | dpll_div); - snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); - snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); - snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); - snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); - snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id), - (r << 3) | (x << 1) | mode); - - /* Set sysclk to pll_rate / 4 */ - snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); - - return 0; -} - -static void adau1373_load_drc_settings(struct snd_soc_codec *codec, - unsigned int nr, uint8_t *drc) -{ - unsigned int i; - - for (i = 0; i < ADAU1373_DRC_SIZE; ++i) - snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]); -} - -static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) -{ - switch (micbias) { - case ADAU1373_MICBIAS_2_9V: - case ADAU1373_MICBIAS_2_2V: - case ADAU1373_MICBIAS_2_6V: - case ADAU1373_MICBIAS_1_8V: - return true; - default: - break; - } - return false; -} - -static int adau1373_probe(struct snd_soc_codec *codec) -{ - struct adau1373_platform_data *pdata = codec->dev->platform_data; - bool lineout_differential = false; - unsigned int val; - int ret; - int i; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); - if (ret) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - - if (pdata) { - if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) - return -EINVAL; - - if (!adau1373_valid_micbias(pdata->micbias1) || - !adau1373_valid_micbias(pdata->micbias2)) - return -EINVAL; - - for (i = 0; i < pdata->num_drc; ++i) { - adau1373_load_drc_settings(codec, i, - pdata->drc_setting[i]); - } - - snd_soc_add_codec_controls(codec, adau1373_drc_controls, - pdata->num_drc); - - val = 0; - for (i = 0; i < 4; ++i) { - if (pdata->input_differential[i]) - val |= BIT(i); - } - snd_soc_write(codec, ADAU1373_INPUT_MODE, val); - - val = 0; - if (pdata->lineout_differential) - val |= ADAU1373_OUTPUT_CTRL_LDIFF; - if (pdata->lineout_ground_sense) - val |= ADAU1373_OUTPUT_CTRL_LNFBEN; - snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val); - - lineout_differential = pdata->lineout_differential; - - snd_soc_write(codec, ADAU1373_EP_CTRL, - (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) | - (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET)); - } - - if (!lineout_differential) { - snd_soc_add_codec_controls(codec, adau1373_lineout2_controls, - ARRAY_SIZE(adau1373_lineout2_controls)); - } - - snd_soc_write(codec, ADAU1373_ADC_CTRL, - ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT); - - return 0; -} - -static int adau1373_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, - ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN); - break; - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, - ADAU1373_PWDN_CTRL3_PWR_EN, 0); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static int adau1373_remove(struct snd_soc_codec *codec) -{ - adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int adau1373_suspend(struct snd_soc_codec *codec) -{ - return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); -} - -static int adau1373_resume(struct snd_soc_codec *codec) -{ - adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - snd_soc_cache_sync(codec); - - return 0; -} - -static struct snd_soc_codec_driver adau1373_codec_driver = { - .probe = adau1373_probe, - .remove = adau1373_remove, - .suspend = adau1373_suspend, - .resume = adau1373_resume, - .set_bias_level = adau1373_set_bias_level, - .idle_bias_off = true, - .reg_cache_size = ARRAY_SIZE(adau1373_default_regs), - .reg_cache_default = adau1373_default_regs, - .reg_word_size = sizeof(uint8_t), - - .set_pll = adau1373_set_pll, - - .controls = adau1373_controls, - .num_controls = ARRAY_SIZE(adau1373_controls), - .dapm_widgets = adau1373_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets), - .dapm_routes = adau1373_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes), -}; - -static int __devinit adau1373_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adau1373 *adau1373; - int ret; - - adau1373 = devm_kzalloc(&client->dev, sizeof(*adau1373), GFP_KERNEL); - if (!adau1373) - return -ENOMEM; - - dev_set_drvdata(&client->dev, adau1373); - - ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver, - adau1373_dai_driver, ARRAY_SIZE(adau1373_dai_driver)); - return ret; -} - -static int __devexit adau1373_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id adau1373_i2c_id[] = { - { "adau1373", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id); - -static struct i2c_driver adau1373_i2c_driver = { - .driver = { - .name = "adau1373", - .owner = THIS_MODULE, - }, - .probe = adau1373_i2c_probe, - .remove = __devexit_p(adau1373_i2c_remove), - .id_table = adau1373_i2c_id, -}; - -static int __init adau1373_init(void) -{ - return i2c_add_driver(&adau1373_i2c_driver); -} -module_init(adau1373_init); - -static void __exit adau1373_exit(void) -{ - i2c_del_driver(&adau1373_i2c_driver); -} -module_exit(adau1373_exit); - -MODULE_DESCRIPTION("ASoC ADAU1373 driver"); -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/adau1373.h b/ANDROID_3.4.5/sound/soc/codecs/adau1373.h deleted file mode 100644 index c6ab5530..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/adau1373.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __ADAU1373_H__ -#define __ADAU1373_H__ - -enum adau1373_pll_src { - ADAU1373_PLL_SRC_MCLK1 = 0, - ADAU1373_PLL_SRC_BCLK1 = 1, - ADAU1373_PLL_SRC_BCLK2 = 2, - ADAU1373_PLL_SRC_BCLK3 = 3, - ADAU1373_PLL_SRC_LRCLK1 = 4, - ADAU1373_PLL_SRC_LRCLK2 = 5, - ADAU1373_PLL_SRC_LRCLK3 = 6, - ADAU1373_PLL_SRC_GPIO1 = 7, - ADAU1373_PLL_SRC_GPIO2 = 8, - ADAU1373_PLL_SRC_GPIO3 = 9, - ADAU1373_PLL_SRC_GPIO4 = 10, - ADAU1373_PLL_SRC_MCLK2 = 11, -}; - -enum adau1373_pll { - ADAU1373_PLL1 = 0, - ADAU1373_PLL2 = 1, -}; - -enum adau1373_clk_src { - ADAU1373_CLK_SRC_PLL1 = 0, - ADAU1373_CLK_SRC_PLL2 = 1, -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/adau1701.c b/ANDROID_3.4.5/sound/soc/codecs/adau1701.c deleted file mode 100644 index 78e9ce48..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/adau1701.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Driver for ADAU1701 SigmaDSP processor - * - * Copyright 2011 Analog Devices Inc. - * Author: Lars-Peter Clausen - * based on an inital version by Cliff Cai - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sigmadsp.h" -#include "adau1701.h" - -#define ADAU1701_DSPCTRL 0x1c -#define ADAU1701_SEROCTL 0x1e -#define ADAU1701_SERICTL 0x1f - -#define ADAU1701_AUXNPOW 0x22 - -#define ADAU1701_OSCIPOW 0x26 -#define ADAU1701_DACSET 0x27 - -#define ADAU1701_NUM_REGS 0x28 - -#define ADAU1701_DSPCTRL_CR (1 << 2) -#define ADAU1701_DSPCTRL_DAM (1 << 3) -#define ADAU1701_DSPCTRL_ADM (1 << 4) -#define ADAU1701_DSPCTRL_SR_48 0x00 -#define ADAU1701_DSPCTRL_SR_96 0x01 -#define ADAU1701_DSPCTRL_SR_192 0x02 -#define ADAU1701_DSPCTRL_SR_MASK 0x03 - -#define ADAU1701_SEROCTL_INV_LRCLK 0x2000 -#define ADAU1701_SEROCTL_INV_BCLK 0x1000 -#define ADAU1701_SEROCTL_MASTER 0x0800 - -#define ADAU1701_SEROCTL_OBF16 0x0000 -#define ADAU1701_SEROCTL_OBF8 0x0200 -#define ADAU1701_SEROCTL_OBF4 0x0400 -#define ADAU1701_SEROCTL_OBF2 0x0600 -#define ADAU1701_SEROCTL_OBF_MASK 0x0600 - -#define ADAU1701_SEROCTL_OLF1024 0x0000 -#define ADAU1701_SEROCTL_OLF512 0x0080 -#define ADAU1701_SEROCTL_OLF256 0x0100 -#define ADAU1701_SEROCTL_OLF_MASK 0x0180 - -#define ADAU1701_SEROCTL_MSB_DEALY1 0x0000 -#define ADAU1701_SEROCTL_MSB_DEALY0 0x0004 -#define ADAU1701_SEROCTL_MSB_DEALY8 0x0008 -#define ADAU1701_SEROCTL_MSB_DEALY12 0x000c -#define ADAU1701_SEROCTL_MSB_DEALY16 0x0010 -#define ADAU1701_SEROCTL_MSB_DEALY_MASK 0x001c - -#define ADAU1701_SEROCTL_WORD_LEN_24 0x0000 -#define ADAU1701_SEROCTL_WORD_LEN_20 0x0001 -#define ADAU1701_SEROCTL_WORD_LEN_16 0x0010 -#define ADAU1701_SEROCTL_WORD_LEN_MASK 0x0003 - -#define ADAU1701_AUXNPOW_VBPD 0x40 -#define ADAU1701_AUXNPOW_VRPD 0x20 - -#define ADAU1701_SERICTL_I2S 0 -#define ADAU1701_SERICTL_LEFTJ 1 -#define ADAU1701_SERICTL_TDM 2 -#define ADAU1701_SERICTL_RIGHTJ_24 3 -#define ADAU1701_SERICTL_RIGHTJ_20 4 -#define ADAU1701_SERICTL_RIGHTJ_18 5 -#define ADAU1701_SERICTL_RIGHTJ_16 6 -#define ADAU1701_SERICTL_MODE_MASK 7 -#define ADAU1701_SERICTL_INV_BCLK BIT(3) -#define ADAU1701_SERICTL_INV_LRCLK BIT(4) - -#define ADAU1701_OSCIPOW_OPD 0x04 -#define ADAU1701_DACSET_DACINIT 1 - -#define ADAU1701_FIRMWARE "adau1701.bin" - -struct adau1701 { - unsigned int dai_fmt; -}; - -static const struct snd_kcontrol_new adau1701_controls[] = { - SOC_SINGLE("Master Capture Switch", ADAU1701_DSPCTRL, 4, 1, 0), -}; - -static const struct snd_soc_dapm_widget adau1701_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC0", "Playback", ADAU1701_AUXNPOW, 3, 1), - SND_SOC_DAPM_DAC("DAC1", "Playback", ADAU1701_AUXNPOW, 2, 1), - SND_SOC_DAPM_DAC("DAC2", "Playback", ADAU1701_AUXNPOW, 1, 1), - SND_SOC_DAPM_DAC("DAC3", "Playback", ADAU1701_AUXNPOW, 0, 1), - SND_SOC_DAPM_ADC("ADC", "Capture", ADAU1701_AUXNPOW, 7, 1), - - SND_SOC_DAPM_OUTPUT("OUT0"), - SND_SOC_DAPM_OUTPUT("OUT1"), - SND_SOC_DAPM_OUTPUT("OUT2"), - SND_SOC_DAPM_OUTPUT("OUT3"), - SND_SOC_DAPM_INPUT("IN0"), - SND_SOC_DAPM_INPUT("IN1"), -}; - -static const struct snd_soc_dapm_route adau1701_dapm_routes[] = { - { "OUT0", NULL, "DAC0" }, - { "OUT1", NULL, "DAC1" }, - { "OUT2", NULL, "DAC2" }, - { "OUT3", NULL, "DAC3" }, - - { "ADC", NULL, "IN0" }, - { "ADC", NULL, "IN1" }, -}; - -static unsigned int adau1701_register_size(struct snd_soc_codec *codec, - unsigned int reg) -{ - switch (reg) { - case ADAU1701_DSPCTRL: - case ADAU1701_SEROCTL: - case ADAU1701_AUXNPOW: - case ADAU1701_OSCIPOW: - case ADAU1701_DACSET: - return 2; - case ADAU1701_SERICTL: - return 1; - } - - dev_err(codec->dev, "Unsupported register address: %d\n", reg); - return 0; -} - -static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - unsigned int i; - unsigned int size; - uint8_t buf[4]; - int ret; - - size = adau1701_register_size(codec, reg); - if (size == 0) - return -EINVAL; - - snd_soc_cache_write(codec, reg, value); - - buf[0] = 0x08; - buf[1] = reg; - - for (i = size + 1; i >= 2; --i) { - buf[i] = value; - value >>= 8; - } - - ret = i2c_master_send(to_i2c_client(codec->dev), buf, size + 2); - if (ret == size + 2) - return 0; - else if (ret < 0) - return ret; - else - return -EIO; -} - -static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg) -{ - unsigned int value; - unsigned int ret; - - ret = snd_soc_cache_read(codec, reg, &value); - if (ret) - return ret; - - return value; -} - -static int adau1701_load_firmware(struct snd_soc_codec *codec) -{ - return process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE); -} - -static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, - snd_pcm_format_t format) -{ - struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); - unsigned int mask = ADAU1701_SEROCTL_WORD_LEN_MASK; - unsigned int val; - - switch (format) { - case SNDRV_PCM_FORMAT_S16_LE: - val = ADAU1701_SEROCTL_WORD_LEN_16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - val = ADAU1701_SEROCTL_WORD_LEN_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - val = ADAU1701_SEROCTL_WORD_LEN_24; - break; - default: - return -EINVAL; - } - - if (adau1701->dai_fmt == SND_SOC_DAIFMT_RIGHT_J) { - switch (format) { - case SNDRV_PCM_FORMAT_S16_LE: - val |= ADAU1701_SEROCTL_MSB_DEALY16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - val |= ADAU1701_SEROCTL_MSB_DEALY12; - break; - case SNDRV_PCM_FORMAT_S24_LE: - val |= ADAU1701_SEROCTL_MSB_DEALY8; - break; - } - mask |= ADAU1701_SEROCTL_MSB_DEALY_MASK; - } - - snd_soc_update_bits(codec, ADAU1701_SEROCTL, mask, val); - - return 0; -} - -static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec, - snd_pcm_format_t format) -{ - struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); - unsigned int val; - - if (adau1701->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) - return 0; - - switch (format) { - case SNDRV_PCM_FORMAT_S16_LE: - val = ADAU1701_SERICTL_RIGHTJ_16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - val = ADAU1701_SERICTL_RIGHTJ_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - val = ADAU1701_SERICTL_RIGHTJ_24; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, ADAU1701_SERICTL, - ADAU1701_SERICTL_MODE_MASK, val); - - return 0; -} - -static int adau1701_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - snd_pcm_format_t format; - unsigned int val; - - switch (params_rate(params)) { - case 192000: - val = ADAU1701_DSPCTRL_SR_192; - break; - case 96000: - val = ADAU1701_DSPCTRL_SR_96; - break; - case 48000: - val = ADAU1701_DSPCTRL_SR_48; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, ADAU1701_DSPCTRL, - ADAU1701_DSPCTRL_SR_MASK, val); - - format = params_format(params); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - return adau1701_set_playback_pcm_format(codec, format); - else - return adau1701_set_capture_pcm_format(codec, format); -} - -static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); - unsigned int serictl = 0x00, seroctl = 0x00; - bool invert_lrclk; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - /* master, 64-bits per sample, 1 frame per sample */ - seroctl |= ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16 - | ADAU1701_SEROCTL_OLF1024; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - invert_lrclk = false; - break; - case SND_SOC_DAIFMT_NB_IF: - invert_lrclk = true; - break; - case SND_SOC_DAIFMT_IB_NF: - invert_lrclk = false; - serictl |= ADAU1701_SERICTL_INV_BCLK; - seroctl |= ADAU1701_SEROCTL_INV_BCLK; - break; - case SND_SOC_DAIFMT_IB_IF: - invert_lrclk = true; - serictl |= ADAU1701_SERICTL_INV_BCLK; - seroctl |= ADAU1701_SEROCTL_INV_BCLK; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - break; - case SND_SOC_DAIFMT_LEFT_J: - serictl |= ADAU1701_SERICTL_LEFTJ; - seroctl |= ADAU1701_SEROCTL_MSB_DEALY0; - invert_lrclk = !invert_lrclk; - break; - case SND_SOC_DAIFMT_RIGHT_J: - serictl |= ADAU1701_SERICTL_RIGHTJ_24; - seroctl |= ADAU1701_SEROCTL_MSB_DEALY8; - invert_lrclk = !invert_lrclk; - break; - default: - return -EINVAL; - } - - if (invert_lrclk) { - seroctl |= ADAU1701_SEROCTL_INV_LRCLK; - serictl |= ADAU1701_SERICTL_INV_LRCLK; - } - - adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; - - snd_soc_write(codec, ADAU1701_SERICTL, serictl); - snd_soc_update_bits(codec, ADAU1701_SEROCTL, - ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); - - return 0; -} - -static int adau1701_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - unsigned int mask = ADAU1701_AUXNPOW_VBPD | ADAU1701_AUXNPOW_VRPD; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - /* Enable VREF and VREF buffer */ - snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, 0x00); - break; - case SND_SOC_BIAS_OFF: - /* Disable VREF and VREF buffer */ - snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, mask); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - unsigned int mask = ADAU1701_DSPCTRL_DAM; - unsigned int val; - - if (mute) - val = 0; - else - val = mask; - - snd_soc_update_bits(codec, ADAU1701_DSPCTRL, mask, val); - - return 0; -} - -static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, - int source, unsigned int freq, int dir) -{ - unsigned int val; - - switch (clk_id) { - case ADAU1701_CLK_SRC_OSC: - val = 0x0; - break; - case ADAU1701_CLK_SRC_MCLK: - val = ADAU1701_OSCIPOW_OPD; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val); - - return 0; -} - -#define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ - SNDRV_PCM_RATE_192000) - -#define ADAU1701_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops adau1701_dai_ops = { - .set_fmt = adau1701_set_dai_fmt, - .hw_params = adau1701_hw_params, - .digital_mute = adau1701_digital_mute, -}; - -static struct snd_soc_dai_driver adau1701_dai = { - .name = "adau1701", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 8, - .rates = ADAU1701_RATES, - .formats = ADAU1701_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 8, - .rates = ADAU1701_RATES, - .formats = ADAU1701_FORMATS, - }, - .ops = &adau1701_dai_ops, - .symmetric_rates = 1, -}; - -static int adau1701_probe(struct snd_soc_codec *codec) -{ - int ret; - - codec->control_data = to_i2c_client(codec->dev); - - ret = adau1701_load_firmware(codec); - if (ret) - dev_warn(codec->dev, "Failed to load firmware\n"); - - snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); - snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); - - return 0; -} - -static struct snd_soc_codec_driver adau1701_codec_drv = { - .probe = adau1701_probe, - .set_bias_level = adau1701_set_bias_level, - .idle_bias_off = true, - - .reg_cache_size = ADAU1701_NUM_REGS, - .reg_word_size = sizeof(u16), - - .controls = adau1701_controls, - .num_controls = ARRAY_SIZE(adau1701_controls), - .dapm_widgets = adau1701_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adau1701_dapm_widgets), - .dapm_routes = adau1701_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), - - .write = adau1701_write, - .read = adau1701_read, - - .set_sysclk = adau1701_set_sysclk, -}; - -static __devinit int adau1701_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adau1701 *adau1701; - int ret; - - adau1701 = devm_kzalloc(&client->dev, sizeof(*adau1701), GFP_KERNEL); - if (!adau1701) - return -ENOMEM; - - i2c_set_clientdata(client, adau1701); - ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, - &adau1701_dai, 1); - return ret; -} - -static __devexit int adau1701_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id adau1701_i2c_id[] = { - { "adau1701", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); - -static struct i2c_driver adau1701_i2c_driver = { - .driver = { - .name = "adau1701", - .owner = THIS_MODULE, - }, - .probe = adau1701_i2c_probe, - .remove = __devexit_p(adau1701_i2c_remove), - .id_table = adau1701_i2c_id, -}; - -static int __init adau1701_init(void) -{ - return i2c_add_driver(&adau1701_i2c_driver); -} -module_init(adau1701_init); - -static void __exit adau1701_exit(void) -{ - i2c_del_driver(&adau1701_i2c_driver); -} -module_exit(adau1701_exit); - -MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); -MODULE_AUTHOR("Cliff Cai "); -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/adau1701.h b/ANDROID_3.4.5/sound/soc/codecs/adau1701.h deleted file mode 100644 index 8d0949a2..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/adau1701.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * header file for ADAU1701 SigmaDSP processor - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef _ADAU1701_H -#define _ADAU1701_H - -enum adau1701_clk_src { - ADAU1701_CLK_SRC_OSC, - ADAU1701_CLK_SRC_MCLK, -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/adav80x.c b/ANDROID_3.4.5/sound/soc/codecs/adav80x.c deleted file mode 100644 index ebd7b37b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/adav80x.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - * ADAV80X Audio Codec driver supporting ADAV801, ADAV803 - * - * Copyright 2011 Analog Devices Inc. - * Author: Yi Li - * Author: Lars-Peter Clausen - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "adav80x.h" - -#define ADAV80X_PLAYBACK_CTRL 0x04 -#define ADAV80X_AUX_IN_CTRL 0x05 -#define ADAV80X_REC_CTRL 0x06 -#define ADAV80X_AUX_OUT_CTRL 0x07 -#define ADAV80X_DPATH_CTRL1 0x62 -#define ADAV80X_DPATH_CTRL2 0x63 -#define ADAV80X_DAC_CTRL1 0x64 -#define ADAV80X_DAC_CTRL2 0x65 -#define ADAV80X_DAC_CTRL3 0x66 -#define ADAV80X_DAC_L_VOL 0x68 -#define ADAV80X_DAC_R_VOL 0x69 -#define ADAV80X_PGA_L_VOL 0x6c -#define ADAV80X_PGA_R_VOL 0x6d -#define ADAV80X_ADC_CTRL1 0x6e -#define ADAV80X_ADC_CTRL2 0x6f -#define ADAV80X_ADC_L_VOL 0x70 -#define ADAV80X_ADC_R_VOL 0x71 -#define ADAV80X_PLL_CTRL1 0x74 -#define ADAV80X_PLL_CTRL2 0x75 -#define ADAV80X_ICLK_CTRL1 0x76 -#define ADAV80X_ICLK_CTRL2 0x77 -#define ADAV80X_PLL_CLK_SRC 0x78 -#define ADAV80X_PLL_OUTE 0x7a - -#define ADAV80X_PLL_CLK_SRC_PLL_XIN(pll) 0x00 -#define ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll) (0x40 << (pll)) -#define ADAV80X_PLL_CLK_SRC_PLL_MASK(pll) (0x40 << (pll)) - -#define ADAV80X_ICLK_CTRL1_DAC_SRC(src) ((src) << 5) -#define ADAV80X_ICLK_CTRL1_ADC_SRC(src) ((src) << 2) -#define ADAV80X_ICLK_CTRL1_ICLK2_SRC(src) (src) -#define ADAV80X_ICLK_CTRL2_ICLK1_SRC(src) ((src) << 3) - -#define ADAV80X_PLL_CTRL1_PLLDIV 0x10 -#define ADAV80X_PLL_CTRL1_PLLPD(pll) (0x04 << (pll)) -#define ADAV80X_PLL_CTRL1_XTLPD 0x02 - -#define ADAV80X_PLL_CTRL2_FIELD(pll, x) ((x) << ((pll) * 4)) - -#define ADAV80X_PLL_CTRL2_FS_48(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x00) -#define ADAV80X_PLL_CTRL2_FS_32(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x08) -#define ADAV80X_PLL_CTRL2_FS_44(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0c) - -#define ADAV80X_PLL_CTRL2_SEL(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x02) -#define ADAV80X_PLL_CTRL2_DOUB(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x01) -#define ADAV80X_PLL_CTRL2_PLL_MASK(pll) ADAV80X_PLL_CTRL2_FIELD((pll), 0x0f) - -#define ADAV80X_ADC_CTRL1_MODULATOR_MASK 0x80 -#define ADAV80X_ADC_CTRL1_MODULATOR_128FS 0x00 -#define ADAV80X_ADC_CTRL1_MODULATOR_64FS 0x80 - -#define ADAV80X_DAC_CTRL1_PD 0x80 - -#define ADAV80X_DAC_CTRL2_DIV1 0x00 -#define ADAV80X_DAC_CTRL2_DIV1_5 0x10 -#define ADAV80X_DAC_CTRL2_DIV2 0x20 -#define ADAV80X_DAC_CTRL2_DIV3 0x30 -#define ADAV80X_DAC_CTRL2_DIV_MASK 0x30 - -#define ADAV80X_DAC_CTRL2_INTERPOL_256FS 0x00 -#define ADAV80X_DAC_CTRL2_INTERPOL_128FS 0x40 -#define ADAV80X_DAC_CTRL2_INTERPOL_64FS 0x80 -#define ADAV80X_DAC_CTRL2_INTERPOL_MASK 0xc0 - -#define ADAV80X_DAC_CTRL2_DEEMPH_NONE 0x00 -#define ADAV80X_DAC_CTRL2_DEEMPH_44 0x01 -#define ADAV80X_DAC_CTRL2_DEEMPH_32 0x02 -#define ADAV80X_DAC_CTRL2_DEEMPH_48 0x03 -#define ADAV80X_DAC_CTRL2_DEEMPH_MASK 0x01 - -#define ADAV80X_CAPTURE_MODE_MASTER 0x20 -#define ADAV80X_CAPTURE_WORD_LEN24 0x00 -#define ADAV80X_CAPTURE_WORD_LEN20 0x04 -#define ADAV80X_CAPTRUE_WORD_LEN18 0x08 -#define ADAV80X_CAPTURE_WORD_LEN16 0x0c -#define ADAV80X_CAPTURE_WORD_LEN_MASK 0x0c - -#define ADAV80X_CAPTURE_MODE_LEFT_J 0x00 -#define ADAV80X_CAPTURE_MODE_I2S 0x01 -#define ADAV80X_CAPTURE_MODE_RIGHT_J 0x03 -#define ADAV80X_CAPTURE_MODE_MASK 0x03 - -#define ADAV80X_PLAYBACK_MODE_MASTER 0x10 -#define ADAV80X_PLAYBACK_MODE_LEFT_J 0x00 -#define ADAV80X_PLAYBACK_MODE_I2S 0x01 -#define ADAV80X_PLAYBACK_MODE_RIGHT_J_24 0x04 -#define ADAV80X_PLAYBACK_MODE_RIGHT_J_20 0x05 -#define ADAV80X_PLAYBACK_MODE_RIGHT_J_18 0x06 -#define ADAV80X_PLAYBACK_MODE_RIGHT_J_16 0x07 -#define ADAV80X_PLAYBACK_MODE_MASK 0x07 - -#define ADAV80X_PLL_OUTE_SYSCLKPD(x) BIT(2 - (x)) - -static u8 adav80x_default_regs[] = { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0x80, 0x26, 0x00, 0x00, - 0x02, 0x40, 0x20, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x92, 0xb1, 0x37, - 0x48, 0xd2, 0xfb, 0xca, 0xd2, 0x15, 0xe8, 0x29, 0xb9, 0x6a, 0xda, 0x2b, - 0xb7, 0xc0, 0x11, 0x65, 0x5c, 0xf6, 0xff, 0x8d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, - 0x00, 0xe8, 0x46, 0xe1, 0x5b, 0xd3, 0x43, 0x77, 0x93, 0xa7, 0x44, 0xee, - 0x32, 0x12, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, -}; - -struct adav80x { - enum snd_soc_control_type control_type; - - enum adav80x_clk_src clk_src; - unsigned int sysclk; - enum adav80x_pll_src pll_src; - - unsigned int dai_fmt[2]; - unsigned int rate; - bool deemph; - bool sysclk_pd[3]; -}; - -static const char *adav80x_mux_text[] = { - "ADC", - "Playback", - "Aux Playback", -}; - -static const unsigned int adav80x_mux_values[] = { - 0, 2, 3, -}; - -#define ADAV80X_MUX_ENUM_DECL(name, reg, shift) \ - SOC_VALUE_ENUM_DOUBLE_DECL(name, reg, shift, 7, \ - ARRAY_SIZE(adav80x_mux_text), adav80x_mux_text, \ - adav80x_mux_values) - -static ADAV80X_MUX_ENUM_DECL(adav80x_aux_capture_enum, ADAV80X_DPATH_CTRL1, 0); -static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3); -static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3); - -static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl = - SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum); -static const struct snd_kcontrol_new adav80x_capture_mux_ctrl = - SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum); -static const struct snd_kcontrol_new adav80x_dac_mux_ctrl = - SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum); - -#define ADAV80X_MUX(name, ctrl) \ - SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) - -static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1), - SND_SOC_DAPM_ADC("ADC", NULL, ADAV80X_ADC_CTRL1, 5, 1), - - SND_SOC_DAPM_PGA("Right PGA", ADAV80X_ADC_CTRL1, 0, 1, NULL, 0), - SND_SOC_DAPM_PGA("Left PGA", ADAV80X_ADC_CTRL1, 1, 1, NULL, 0), - - SND_SOC_DAPM_AIF_OUT("AIFOUT", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_IN("AIFIN", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), - - SND_SOC_DAPM_AIF_OUT("AIFAUXOUT", "Aux Capture", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_IN("AIFAUXIN", "Aux Playback", 0, SND_SOC_NOPM, 0, 0), - - ADAV80X_MUX("Aux Capture Select", &adav80x_aux_capture_mux_ctrl), - ADAV80X_MUX("Capture Select", &adav80x_capture_mux_ctrl), - ADAV80X_MUX("DAC Select", &adav80x_dac_mux_ctrl), - - SND_SOC_DAPM_INPUT("VINR"), - SND_SOC_DAPM_INPUT("VINL"), - SND_SOC_DAPM_OUTPUT("VOUTR"), - SND_SOC_DAPM_OUTPUT("VOUTL"), - - SND_SOC_DAPM_SUPPLY("SYSCLK", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("PLL1", ADAV80X_PLL_CTRL1, 2, 1, NULL, 0), - SND_SOC_DAPM_SUPPLY("PLL2", ADAV80X_PLL_CTRL1, 3, 1, NULL, 0), - SND_SOC_DAPM_SUPPLY("OSC", ADAV80X_PLL_CTRL1, 1, 1, NULL, 0), -}; - -static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - struct snd_soc_codec *codec = source->codec; - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - const char *clk; - - switch (adav80x->clk_src) { - case ADAV80X_CLK_PLL1: - clk = "PLL1"; - break; - case ADAV80X_CLK_PLL2: - clk = "PLL2"; - break; - case ADAV80X_CLK_XTAL: - clk = "OSC"; - break; - default: - return 0; - } - - return strcmp(source->name, clk) == 0; -} - -static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - struct snd_soc_codec *codec = source->codec; - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - - return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL; -} - - -static const struct snd_soc_dapm_route adav80x_dapm_routes[] = { - { "DAC Select", "ADC", "ADC" }, - { "DAC Select", "Playback", "AIFIN" }, - { "DAC Select", "Aux Playback", "AIFAUXIN" }, - { "DAC", NULL, "DAC Select" }, - - { "Capture Select", "ADC", "ADC" }, - { "Capture Select", "Playback", "AIFIN" }, - { "Capture Select", "Aux Playback", "AIFAUXIN" }, - { "AIFOUT", NULL, "Capture Select" }, - - { "Aux Capture Select", "ADC", "ADC" }, - { "Aux Capture Select", "Playback", "AIFIN" }, - { "Aux Capture Select", "Aux Playback", "AIFAUXIN" }, - { "AIFAUXOUT", NULL, "Aux Capture Select" }, - - { "VOUTR", NULL, "DAC" }, - { "VOUTL", NULL, "DAC" }, - - { "Left PGA", NULL, "VINL" }, - { "Right PGA", NULL, "VINR" }, - { "ADC", NULL, "Left PGA" }, - { "ADC", NULL, "Right PGA" }, - - { "SYSCLK", NULL, "PLL1", adav80x_dapm_sysclk_check }, - { "SYSCLK", NULL, "PLL2", adav80x_dapm_sysclk_check }, - { "SYSCLK", NULL, "OSC", adav80x_dapm_sysclk_check }, - { "PLL1", NULL, "OSC", adav80x_dapm_pll_check }, - { "PLL2", NULL, "OSC", adav80x_dapm_pll_check }, - - { "ADC", NULL, "SYSCLK" }, - { "DAC", NULL, "SYSCLK" }, - { "AIFOUT", NULL, "SYSCLK" }, - { "AIFAUXOUT", NULL, "SYSCLK" }, - { "AIFIN", NULL, "SYSCLK" }, - { "AIFAUXIN", NULL, "SYSCLK" }, -}; - -static int adav80x_set_deemph(struct snd_soc_codec *codec) -{ - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - unsigned int val; - - if (adav80x->deemph) { - switch (adav80x->rate) { - case 32000: - val = ADAV80X_DAC_CTRL2_DEEMPH_32; - break; - case 44100: - val = ADAV80X_DAC_CTRL2_DEEMPH_44; - break; - case 48000: - case 64000: - case 88200: - case 96000: - val = ADAV80X_DAC_CTRL2_DEEMPH_48; - break; - default: - val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; - break; - } - } else { - val = ADAV80X_DAC_CTRL2_DEEMPH_NONE; - } - - return snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2, - ADAV80X_DAC_CTRL2_DEEMPH_MASK, val); -} - -static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - unsigned int deemph = ucontrol->value.enumerated.item[0]; - - if (deemph > 1) - return -EINVAL; - - adav80x->deemph = deemph; - - return adav80x_set_deemph(codec); -} - -static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = adav80x->deemph; - return 0; -}; - -static const DECLARE_TLV_DB_SCALE(adav80x_inpga_tlv, 0, 50, 0); -static const DECLARE_TLV_DB_MINMAX(adav80x_digital_tlv, -9563, 0); - -static const struct snd_kcontrol_new adav80x_controls[] = { - SOC_DOUBLE_R_TLV("Master Playback Volume", ADAV80X_DAC_L_VOL, - ADAV80X_DAC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), - SOC_DOUBLE_R_TLV("Master Capture Volume", ADAV80X_ADC_L_VOL, - ADAV80X_ADC_R_VOL, 0, 0xff, 0, adav80x_digital_tlv), - - SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAV80X_PGA_L_VOL, - ADAV80X_PGA_R_VOL, 0, 0x30, 0, adav80x_inpga_tlv), - - SOC_DOUBLE("Master Playback Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 0), - SOC_DOUBLE("Master Capture Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1), - - SOC_SINGLE("ADC High Pass Filter Switch", ADAV80X_ADC_CTRL1, 6, 1, 0), - - SOC_SINGLE_BOOL_EXT("Playback De-emphasis Switch", 0, - adav80x_get_deemph, adav80x_put_deemph), -}; - -static unsigned int adav80x_port_ctrl_regs[2][2] = { - { ADAV80X_REC_CTRL, ADAV80X_PLAYBACK_CTRL, }, - { ADAV80X_AUX_OUT_CTRL, ADAV80X_AUX_IN_CTRL }, -}; - -static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - unsigned int capture = 0x00; - unsigned int playback = 0x00; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - capture |= ADAV80X_CAPTURE_MODE_MASTER; - playback |= ADAV80X_PLAYBACK_MODE_MASTER; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - capture |= ADAV80X_CAPTURE_MODE_I2S; - playback |= ADAV80X_PLAYBACK_MODE_I2S; - break; - case SND_SOC_DAIFMT_LEFT_J: - capture |= ADAV80X_CAPTURE_MODE_LEFT_J; - playback |= ADAV80X_PLAYBACK_MODE_LEFT_J; - break; - case SND_SOC_DAIFMT_RIGHT_J: - capture |= ADAV80X_CAPTURE_MODE_RIGHT_J; - playback |= ADAV80X_PLAYBACK_MODE_RIGHT_J_24; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0], - ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER, - capture); - snd_soc_write(codec, adav80x_port_ctrl_regs[dai->id][1], playback); - - adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK; - - return 0; -} - -static int adav80x_set_adc_clock(struct snd_soc_codec *codec, - unsigned int sample_rate) -{ - unsigned int val; - - if (sample_rate <= 48000) - val = ADAV80X_ADC_CTRL1_MODULATOR_128FS; - else - val = ADAV80X_ADC_CTRL1_MODULATOR_64FS; - - snd_soc_update_bits(codec, ADAV80X_ADC_CTRL1, - ADAV80X_ADC_CTRL1_MODULATOR_MASK, val); - - return 0; -} - -static int adav80x_set_dac_clock(struct snd_soc_codec *codec, - unsigned int sample_rate) -{ - unsigned int val; - - if (sample_rate <= 48000) - val = ADAV80X_DAC_CTRL2_DIV1 | ADAV80X_DAC_CTRL2_INTERPOL_256FS; - else - val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS; - - snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2, - ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK, - val); - - return 0; -} - -static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec, - struct snd_soc_dai *dai, snd_pcm_format_t format) -{ - unsigned int val; - - switch (format) { - case SNDRV_PCM_FORMAT_S16_LE: - val = ADAV80X_CAPTURE_WORD_LEN16; - break; - case SNDRV_PCM_FORMAT_S18_3LE: - val = ADAV80X_CAPTRUE_WORD_LEN18; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - val = ADAV80X_CAPTURE_WORD_LEN20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - val = ADAV80X_CAPTURE_WORD_LEN24; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0], - ADAV80X_CAPTURE_WORD_LEN_MASK, val); - - return 0; -} - -static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec, - struct snd_soc_dai *dai, snd_pcm_format_t format) -{ - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - unsigned int val; - - if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J) - return 0; - - switch (format) { - case SNDRV_PCM_FORMAT_S16_LE: - val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16; - break; - case SNDRV_PCM_FORMAT_S18_3LE: - val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][1], - ADAV80X_PLAYBACK_MODE_MASK, val); - - return 0; -} - -static int adav80x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - unsigned int rate = params_rate(params); - - if (rate * 256 != adav80x->sysclk) - return -EINVAL; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - adav80x_set_playback_pcm_format(codec, dai, - params_format(params)); - adav80x_set_dac_clock(codec, rate); - } else { - adav80x_set_capture_pcm_format(codec, dai, - params_format(params)); - adav80x_set_adc_clock(codec, rate); - } - adav80x->rate = rate; - adav80x_set_deemph(codec); - - return 0; -} - -static int adav80x_set_sysclk(struct snd_soc_codec *codec, - int clk_id, int source, - unsigned int freq, int dir) -{ - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - - if (dir == SND_SOC_CLOCK_IN) { - switch (clk_id) { - case ADAV80X_CLK_XIN: - case ADAV80X_CLK_XTAL: - case ADAV80X_CLK_MCLKI: - case ADAV80X_CLK_PLL1: - case ADAV80X_CLK_PLL2: - break; - default: - return -EINVAL; - } - - adav80x->sysclk = freq; - - if (adav80x->clk_src != clk_id) { - unsigned int iclk_ctrl1, iclk_ctrl2; - - adav80x->clk_src = clk_id; - if (clk_id == ADAV80X_CLK_XTAL) - clk_id = ADAV80X_CLK_XIN; - - iclk_ctrl1 = ADAV80X_ICLK_CTRL1_DAC_SRC(clk_id) | - ADAV80X_ICLK_CTRL1_ADC_SRC(clk_id) | - ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id); - iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id); - - snd_soc_write(codec, ADAV80X_ICLK_CTRL1, iclk_ctrl1); - snd_soc_write(codec, ADAV80X_ICLK_CTRL2, iclk_ctrl2); - - snd_soc_dapm_sync(&codec->dapm); - } - } else { - unsigned int mask; - - switch (clk_id) { - case ADAV80X_CLK_SYSCLK1: - case ADAV80X_CLK_SYSCLK2: - case ADAV80X_CLK_SYSCLK3: - break; - default: - return -EINVAL; - } - - clk_id -= ADAV80X_CLK_SYSCLK1; - mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id); - - if (freq == 0) { - snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, mask); - adav80x->sysclk_pd[clk_id] = true; - } else { - snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, 0); - adav80x->sysclk_pd[clk_id] = false; - } - - if (adav80x->sysclk_pd[0]) - snd_soc_dapm_disable_pin(&codec->dapm, "PLL1"); - else - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); - - if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2]) - snd_soc_dapm_disable_pin(&codec->dapm, "PLL2"); - else - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); - - snd_soc_dapm_sync(&codec->dapm); - } - - return 0; -} - -static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - unsigned int pll_ctrl1 = 0; - unsigned int pll_ctrl2 = 0; - unsigned int pll_src; - - switch (source) { - case ADAV80X_PLL_SRC_XTAL: - case ADAV80X_PLL_SRC_XIN: - case ADAV80X_PLL_SRC_MCLKI: - break; - default: - return -EINVAL; - } - - if (!freq_out) - return 0; - - switch (freq_in) { - case 27000000: - break; - case 54000000: - if (source == ADAV80X_PLL_SRC_XIN) { - pll_ctrl1 |= ADAV80X_PLL_CTRL1_PLLDIV; - break; - } - default: - return -EINVAL; - } - - if (freq_out > 12288000) { - pll_ctrl2 |= ADAV80X_PLL_CTRL2_DOUB(pll_id); - freq_out /= 2; - } - - /* freq_out = sample_rate * 256 */ - switch (freq_out) { - case 8192000: - pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_32(pll_id); - break; - case 11289600: - pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_44(pll_id); - break; - case 12288000: - pll_ctrl2 |= ADAV80X_PLL_CTRL2_FS_48(pll_id); - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, ADAV80X_PLL_CTRL1, ADAV80X_PLL_CTRL1_PLLDIV, - pll_ctrl1); - snd_soc_update_bits(codec, ADAV80X_PLL_CTRL2, - ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2); - - if (source != adav80x->pll_src) { - if (source == ADAV80X_PLL_SRC_MCLKI) - pll_src = ADAV80X_PLL_CLK_SRC_PLL_MCLKI(pll_id); - else - pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id); - - snd_soc_update_bits(codec, ADAV80X_PLL_CLK_SRC, - ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src); - - adav80x->pll_src = source; - - snd_soc_dapm_sync(&codec->dapm); - } - - return 0; -} - -static int adav80x_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - unsigned int mask = ADAV80X_DAC_CTRL1_PD; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, 0x00); - break; - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, mask); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -/* Enforce the same sample rate on all audio interfaces */ -static int adav80x_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - - if (!codec->active || !adav80x->rate) - return 0; - - return snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, adav80x->rate, adav80x->rate); -} - -static void adav80x_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - - if (!codec->active) - adav80x->rate = 0; -} - -static const struct snd_soc_dai_ops adav80x_dai_ops = { - .set_fmt = adav80x_set_dai_fmt, - .hw_params = adav80x_hw_params, - .startup = adav80x_dai_startup, - .shutdown = adav80x_dai_shutdown, -}; - -#define ADAV80X_PLAYBACK_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | \ - SNDRV_PCM_RATE_96000) - -#define ADAV80X_CAPTURE_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) - -#define ADAV80X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) - -static struct snd_soc_dai_driver adav80x_dais[] = { - { - .name = "adav80x-hifi", - .id = 0, - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 2, - .channels_max = 2, - .rates = ADAV80X_PLAYBACK_RATES, - .formats = ADAV80X_FORMATS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 2, - .channels_max = 2, - .rates = ADAV80X_CAPTURE_RATES, - .formats = ADAV80X_FORMATS, - }, - .ops = &adav80x_dai_ops, - }, - { - .name = "adav80x-aux", - .id = 1, - .playback = { - .stream_name = "Aux Playback", - .channels_min = 2, - .channels_max = 2, - .rates = ADAV80X_PLAYBACK_RATES, - .formats = ADAV80X_FORMATS, - }, - .capture = { - .stream_name = "Aux Capture", - .channels_min = 2, - .channels_max = 2, - .rates = ADAV80X_CAPTURE_RATES, - .formats = ADAV80X_FORMATS, - }, - .ops = &adav80x_dai_ops, - }, -}; - -static int adav80x_probe(struct snd_soc_codec *codec) -{ - int ret; - struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, adav80x->control_type); - if (ret) { - dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); - return ret; - } - - /* Force PLLs on for SYSCLK output */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2"); - - /* Power down S/PDIF receiver, since it is currently not supported */ - snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x20); - /* Disable DAC zero flag */ - snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6); - - return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -} - -static int adav80x_suspend(struct snd_soc_codec *codec) -{ - return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); -} - -static int adav80x_resume(struct snd_soc_codec *codec) -{ - adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - codec->cache_sync = 1; - snd_soc_cache_sync(codec); - - return 0; -} - -static int adav80x_remove(struct snd_soc_codec *codec) -{ - return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF); -} - -static struct snd_soc_codec_driver adav80x_codec_driver = { - .probe = adav80x_probe, - .remove = adav80x_remove, - .suspend = adav80x_suspend, - .resume = adav80x_resume, - .set_bias_level = adav80x_set_bias_level, - - .set_pll = adav80x_set_pll, - .set_sysclk = adav80x_set_sysclk, - - .reg_word_size = sizeof(u8), - .reg_cache_size = ARRAY_SIZE(adav80x_default_regs), - .reg_cache_default = adav80x_default_regs, - - .controls = adav80x_controls, - .num_controls = ARRAY_SIZE(adav80x_controls), - .dapm_widgets = adav80x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(adav80x_dapm_widgets), - .dapm_routes = adav80x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes), -}; - -static int __devinit adav80x_bus_probe(struct device *dev, - enum snd_soc_control_type control_type) -{ - struct adav80x *adav80x; - int ret; - - adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL); - if (!adav80x) - return -ENOMEM; - - dev_set_drvdata(dev, adav80x); - adav80x->control_type = control_type; - - ret = snd_soc_register_codec(dev, &adav80x_codec_driver, - adav80x_dais, ARRAY_SIZE(adav80x_dais)); - if (ret) - kfree(adav80x); - - return ret; -} - -static int __devexit adav80x_bus_remove(struct device *dev) -{ - snd_soc_unregister_codec(dev); - kfree(dev_get_drvdata(dev)); - return 0; -} - -#if defined(CONFIG_SPI_MASTER) -static int __devinit adav80x_spi_probe(struct spi_device *spi) -{ - return adav80x_bus_probe(&spi->dev, SND_SOC_SPI); -} - -static int __devexit adav80x_spi_remove(struct spi_device *spi) -{ - return adav80x_bus_remove(&spi->dev); -} - -static struct spi_driver adav80x_spi_driver = { - .driver = { - .name = "adav801", - .owner = THIS_MODULE, - }, - .probe = adav80x_spi_probe, - .remove = __devexit_p(adav80x_spi_remove), -}; -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static const struct i2c_device_id adav80x_id[] = { - { "adav803", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adav80x_id); - -static int __devinit adav80x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - return adav80x_bus_probe(&client->dev, SND_SOC_I2C); -} - -static int __devexit adav80x_i2c_remove(struct i2c_client *client) -{ - return adav80x_bus_remove(&client->dev); -} - -static struct i2c_driver adav80x_i2c_driver = { - .driver = { - .name = "adav803", - .owner = THIS_MODULE, - }, - .probe = adav80x_i2c_probe, - .remove = __devexit_p(adav80x_i2c_remove), - .id_table = adav80x_id, -}; -#endif - -static int __init adav80x_init(void) -{ - int ret = 0; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&adav80x_i2c_driver); - if (ret) - return ret; -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&adav80x_spi_driver); -#endif - - return ret; -} -module_init(adav80x_init); - -static void __exit adav80x_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&adav80x_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&adav80x_spi_driver); -#endif -} -module_exit(adav80x_exit); - -MODULE_DESCRIPTION("ASoC ADAV80x driver"); -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_AUTHOR("Yi Li >"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/adav80x.h b/ANDROID_3.4.5/sound/soc/codecs/adav80x.h deleted file mode 100644 index adb0fc76..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/adav80x.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * header file for ADAV80X parts - * - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef _ADAV80X_H -#define _ADAV80X_H - -enum adav80x_pll_src { - ADAV80X_PLL_SRC_XIN, - ADAV80X_PLL_SRC_XTAL, - ADAV80X_PLL_SRC_MCLKI, -}; - -enum adav80x_pll { - ADAV80X_PLL1 = 0, - ADAV80X_PLL2 = 1, -}; - -enum adav80x_clk_src { - ADAV80X_CLK_XIN = 0, - ADAV80X_CLK_MCLKI = 1, - ADAV80X_CLK_PLL1 = 2, - ADAV80X_CLK_PLL2 = 3, - ADAV80X_CLK_XTAL = 6, - - ADAV80X_CLK_SYSCLK1 = 6, - ADAV80X_CLK_SYSCLK2 = 7, - ADAV80X_CLK_SYSCLK3 = 8, -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/ads117x.c b/ANDROID_3.4.5/sound/soc/codecs/ads117x.c deleted file mode 100644 index 8103b938..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ads117x.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * ads117x.c -- Driver for ads1174/8 ADC chips - * - * Copyright 2009 ShotSpotter Inc. - * Author: Graeme Gregory - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) -#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) - -static struct snd_soc_dai_driver ads117x_dai = { -/* ADC */ - .name = "ads117x-hifi", - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 32, - .rates = ADS117X_RATES, - .formats = ADS117X_FORMATS,}, -}; - -static struct snd_soc_codec_driver soc_codec_dev_ads117x; - -static __devinit int ads117x_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_ads117x, &ads117x_dai, 1); -} - -static int __devexit ads117x_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver ads117x_codec_driver = { - .driver = { - .name = "ads117x-codec", - .owner = THIS_MODULE, - }, - - .probe = ads117x_probe, - .remove = __devexit_p(ads117x_remove), -}; - -module_platform_driver(ads117x_codec_driver); - -MODULE_DESCRIPTION("ASoC ads117x driver"); -MODULE_AUTHOR("Graeme Gregory"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ak4104.c b/ANDROID_3.4.5/sound/soc/codecs/ak4104.c deleted file mode 100644 index ceb96ecf..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ak4104.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * AK4104 ALSA SoC (ASoC) driver - * - * Copyright (c) 2009 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -/* AK4104 registers addresses */ -#define AK4104_REG_CONTROL1 0x00 -#define AK4104_REG_RESERVED 0x01 -#define AK4104_REG_CONTROL2 0x02 -#define AK4104_REG_TX 0x03 -#define AK4104_REG_CHN_STATUS(x) ((x) + 0x04) -#define AK4104_NUM_REGS 10 - -#define AK4104_REG_MASK 0x1f -#define AK4104_READ 0xc0 -#define AK4104_WRITE 0xe0 -#define AK4104_RESERVED_VAL 0x5b - -/* Bit masks for AK4104 registers */ -#define AK4104_CONTROL1_RSTN (1 << 0) -#define AK4104_CONTROL1_PW (1 << 1) -#define AK4104_CONTROL1_DIF0 (1 << 2) -#define AK4104_CONTROL1_DIF1 (1 << 3) - -#define AK4104_CONTROL2_SEL0 (1 << 0) -#define AK4104_CONTROL2_SEL1 (1 << 1) -#define AK4104_CONTROL2_MODE (1 << 2) - -#define AK4104_TX_TXE (1 << 0) -#define AK4104_TX_V (1 << 1) - -#define DRV_NAME "ak4104-codec" - -struct ak4104_private { - struct regmap *regmap; -}; - -static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int format) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int val = 0; - int ret; - - /* set DAI format */ - switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - val |= AK4104_CONTROL1_DIF0; - break; - case SND_SOC_DAIFMT_I2S: - val |= AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1; - break; - default: - dev_err(codec->dev, "invalid dai format\n"); - return -EINVAL; - } - - /* This device can only be slave */ - if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) - return -EINVAL; - - ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1, - AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1, - val); - if (ret < 0) - return ret; - - return 0; -} - -static int ak4104_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - int val = 0; - - /* set the IEC958 bits: consumer mode, no copyright bit */ - val |= IEC958_AES0_CON_NOT_COPYRIGHT; - snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val); - - val = 0; - - switch (params_rate(params)) { - case 44100: - val |= IEC958_AES3_CON_FS_44100; - break; - case 48000: - val |= IEC958_AES3_CON_FS_48000; - break; - case 32000: - val |= IEC958_AES3_CON_FS_32000; - break; - default: - dev_err(codec->dev, "unsupported sampling rate\n"); - return -EINVAL; - } - - return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val); -} - -static const struct snd_soc_dai_ops ak4101_dai_ops = { - .hw_params = ak4104_hw_params, - .set_fmt = ak4104_set_dai_fmt, -}; - -static struct snd_soc_dai_driver ak4104_dai = { - .name = "ak4104-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S24_LE - }, - .ops = &ak4101_dai_ops, -}; - -static int ak4104_probe(struct snd_soc_codec *codec) -{ - struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ak4104->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret != 0) - return ret; - - /* set power-up and non-reset bits */ - ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1, - AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, - AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); - if (ret < 0) - return ret; - - /* enable transmitter */ - ret = snd_soc_update_bits(codec, AK4104_REG_TX, - AK4104_TX_TXE, AK4104_TX_TXE); - if (ret < 0) - return ret; - - return 0; -} - -static int ak4104_remove(struct snd_soc_codec *codec) -{ - snd_soc_update_bits(codec, AK4104_REG_CONTROL1, - AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_device_ak4104 = { - .probe = ak4104_probe, - .remove = ak4104_remove, -}; - -static const struct regmap_config ak4104_regmap = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = AK4104_NUM_REGS - 1, - .read_flag_mask = AK4104_READ, - .write_flag_mask = AK4104_WRITE, - - .cache_type = REGCACHE_RBTREE, -}; - -static int ak4104_spi_probe(struct spi_device *spi) -{ - struct ak4104_private *ak4104; - unsigned int val; - int ret; - - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - ret = spi_setup(spi); - if (ret < 0) - return ret; - - ak4104 = devm_kzalloc(&spi->dev, sizeof(struct ak4104_private), - GFP_KERNEL); - if (ak4104 == NULL) - return -ENOMEM; - - ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap); - if (IS_ERR(ak4104->regmap)) { - ret = PTR_ERR(ak4104->regmap); - return ret; - } - - /* read the 'reserved' register - according to the datasheet, it - * should contain 0x5b. Not a good way to verify the presence of - * the device, but there is no hardware ID register. */ - ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val); - if (ret != 0) - goto err; - if (val != AK4104_RESERVED_VAL) { - ret = -ENODEV; - goto err; - } - - spi_set_drvdata(spi, ak4104); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_device_ak4104, &ak4104_dai, 1); - if (ret != 0) - goto err; - - return 0; - -err: - regmap_exit(ak4104->regmap); - return ret; -} - -static int __devexit ak4104_spi_remove(struct spi_device *spi) -{ - struct ak4104_private *ak4101 = spi_get_drvdata(spi); - regmap_exit(ak4101->regmap); - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ak4104_spi_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, - .probe = ak4104_spi_probe, - .remove = __devexit_p(ak4104_spi_remove), -}; - -module_spi_driver(ak4104_spi_driver); - -MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/codecs/ak4535.c b/ANDROID_3.4.5/sound/soc/codecs/ak4535.c deleted file mode 100644 index 838ae8b2..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ak4535.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * ak4535.c -- AK4535 ALSA Soc Audio driver - * - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie - * - * Based on wm8753.c by Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ak4535.h" - -/* codec private data */ -struct ak4535_priv { - struct regmap *regmap; - unsigned int sysclk; -}; - -/* - * ak4535 register cache - */ -static const struct reg_default ak4535_reg_defaults[] = { - { 0, 0x00 }, - { 1, 0x80 }, - { 2, 0x00 }, - { 3, 0x03 }, - { 4, 0x02 }, - { 5, 0x00 }, - { 6, 0x11 }, - { 7, 0x01 }, - { 8, 0x00 }, - { 9, 0x40 }, - { 10, 0x36 }, - { 11, 0x10 }, - { 12, 0x00 }, - { 13, 0x00 }, - { 14, 0x57 }, -}; - -static bool ak4535_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case AK4535_STATUS: - return true; - default: - return false; - } -} - -static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"}; -static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"}; -static const char *ak4535_hp_out[] = {"Stereo", "Mono"}; -static const char *ak4535_deemp[] = {"44.1kHz", "Off", "48kHz", "32kHz"}; -static const char *ak4535_mic_select[] = {"Internal", "External"}; - -static const struct soc_enum ak4535_enum[] = { - SOC_ENUM_SINGLE(AK4535_SIG1, 7, 2, ak4535_mono_gain), - SOC_ENUM_SINGLE(AK4535_SIG1, 6, 2, ak4535_mono_out), - SOC_ENUM_SINGLE(AK4535_MODE2, 2, 2, ak4535_hp_out), - SOC_ENUM_SINGLE(AK4535_DAC, 0, 4, ak4535_deemp), - SOC_ENUM_SINGLE(AK4535_MIC, 1, 2, ak4535_mic_select), -}; - -static const struct snd_kcontrol_new ak4535_snd_controls[] = { - SOC_SINGLE("ALC2 Switch", AK4535_SIG1, 1, 1, 0), - SOC_ENUM("Mono 1 Output", ak4535_enum[1]), - SOC_ENUM("Mono 1 Gain", ak4535_enum[0]), - SOC_ENUM("Headphone Output", ak4535_enum[2]), - SOC_ENUM("Playback Deemphasis", ak4535_enum[3]), - SOC_SINGLE("Bass Volume", AK4535_DAC, 2, 3, 0), - SOC_SINGLE("Mic Boost (+20dB) Switch", AK4535_MIC, 0, 1, 0), - SOC_ENUM("Mic Select", ak4535_enum[4]), - SOC_SINGLE("ALC Operation Time", AK4535_TIMER, 0, 3, 0), - SOC_SINGLE("ALC Recovery Time", AK4535_TIMER, 2, 3, 0), - SOC_SINGLE("ALC ZC Time", AK4535_TIMER, 4, 3, 0), - SOC_SINGLE("ALC 1 Switch", AK4535_ALC1, 5, 1, 0), - SOC_SINGLE("ALC 2 Switch", AK4535_ALC1, 6, 1, 0), - SOC_SINGLE("ALC Volume", AK4535_ALC2, 0, 127, 0), - SOC_SINGLE("Capture Volume", AK4535_PGA, 0, 127, 0), - SOC_SINGLE("Left Playback Volume", AK4535_LATT, 0, 127, 1), - SOC_SINGLE("Right Playback Volume", AK4535_RATT, 0, 127, 1), - SOC_SINGLE("AUX Bypass Volume", AK4535_VOL, 0, 15, 0), - SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0), -}; - -/* Mono 1 Mixer */ -static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = { - SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0), - SOC_DAPM_SINGLE("Mono Playback Switch", AK4535_SIG1, 5, 1, 0), -}; - -/* Stereo Mixer */ -static const struct snd_kcontrol_new ak4535_stereo_mixer_controls[] = { - SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG2, 4, 1, 0), - SOC_DAPM_SINGLE("Playback Switch", AK4535_SIG2, 7, 1, 0), - SOC_DAPM_SINGLE("Aux Bypass Switch", AK4535_SIG2, 5, 1, 0), -}; - -/* Input Mixer */ -static const struct snd_kcontrol_new ak4535_input_mixer_controls[] = { - SOC_DAPM_SINGLE("Mic Capture Switch", AK4535_MIC, 2, 1, 0), - SOC_DAPM_SINGLE("Aux Capture Switch", AK4535_MIC, 5, 1, 0), -}; - -/* Input mux */ -static const struct snd_kcontrol_new ak4535_input_mux_control = - SOC_DAPM_ENUM("Input Select", ak4535_enum[4]); - -/* HP L switch */ -static const struct snd_kcontrol_new ak4535_hpl_control = - SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 1, 1, 1); - -/* HP R switch */ -static const struct snd_kcontrol_new ak4535_hpr_control = - SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 0, 1, 1); - -/* mono 2 switch */ -static const struct snd_kcontrol_new ak4535_mono2_control = - SOC_DAPM_SINGLE("Switch", AK4535_SIG1, 0, 1, 0); - -/* Line out switch */ -static const struct snd_kcontrol_new ak4535_line_control = - SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 6, 1, 0); - -/* ak4535 dapm widgets */ -static const struct snd_soc_dapm_widget ak4535_dapm_widgets[] = { - SND_SOC_DAPM_MIXER("Stereo Mixer", SND_SOC_NOPM, 0, 0, - &ak4535_stereo_mixer_controls[0], - ARRAY_SIZE(ak4535_stereo_mixer_controls)), - SND_SOC_DAPM_MIXER("Mono1 Mixer", SND_SOC_NOPM, 0, 0, - &ak4535_mono1_mixer_controls[0], - ARRAY_SIZE(ak4535_mono1_mixer_controls)), - SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, - &ak4535_input_mixer_controls[0], - ARRAY_SIZE(ak4535_input_mixer_controls)), - SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, - &ak4535_input_mux_control), - SND_SOC_DAPM_DAC("DAC", "Playback", AK4535_PM2, 0, 0), - SND_SOC_DAPM_SWITCH("Mono 2 Enable", SND_SOC_NOPM, 0, 0, - &ak4535_mono2_control), - /* speaker powersave bit */ - SND_SOC_DAPM_PGA("Speaker Enable", AK4535_MODE2, 0, 0, NULL, 0), - SND_SOC_DAPM_SWITCH("Line Out Enable", SND_SOC_NOPM, 0, 0, - &ak4535_line_control), - SND_SOC_DAPM_SWITCH("Left HP Enable", SND_SOC_NOPM, 0, 0, - &ak4535_hpl_control), - SND_SOC_DAPM_SWITCH("Right HP Enable", SND_SOC_NOPM, 0, 0, - &ak4535_hpr_control), - SND_SOC_DAPM_OUTPUT("LOUT"), - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("ROUT"), - SND_SOC_DAPM_OUTPUT("HPR"), - SND_SOC_DAPM_OUTPUT("SPP"), - SND_SOC_DAPM_OUTPUT("SPN"), - SND_SOC_DAPM_OUTPUT("MOUT1"), - SND_SOC_DAPM_OUTPUT("MOUT2"), - SND_SOC_DAPM_OUTPUT("MICOUT"), - SND_SOC_DAPM_ADC("ADC", "Capture", AK4535_PM1, 0, 0), - SND_SOC_DAPM_PGA("Spk Amp", AK4535_PM2, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("HP R Amp", AK4535_PM2, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("HP L Amp", AK4535_PM2, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mic", AK4535_PM1, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("Line Out", AK4535_PM1, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mono Out", AK4535_PM1, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("AUX In", AK4535_PM1, 2, 0, NULL, 0), - - SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4535_MIC, 3, 0), - SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4535_MIC, 4, 0), - SND_SOC_DAPM_INPUT("MICIN"), - SND_SOC_DAPM_INPUT("MICEXT"), - SND_SOC_DAPM_INPUT("AUX"), - SND_SOC_DAPM_INPUT("MIN"), - SND_SOC_DAPM_INPUT("AIN"), -}; - -static const struct snd_soc_dapm_route ak4535_audio_map[] = { - /*stereo mixer */ - {"Stereo Mixer", "Playback Switch", "DAC"}, - {"Stereo Mixer", "Mic Sidetone Switch", "Mic"}, - {"Stereo Mixer", "Aux Bypass Switch", "AUX In"}, - - /* mono1 mixer */ - {"Mono1 Mixer", "Mic Sidetone Switch", "Mic"}, - {"Mono1 Mixer", "Mono Playback Switch", "DAC"}, - - /* Mic */ - {"Mic", NULL, "AIN"}, - {"Input Mux", "Internal", "Mic Int Bias"}, - {"Input Mux", "External", "Mic Ext Bias"}, - {"Mic Int Bias", NULL, "MICIN"}, - {"Mic Ext Bias", NULL, "MICEXT"}, - {"MICOUT", NULL, "Input Mux"}, - - /* line out */ - {"LOUT", NULL, "Line Out Enable"}, - {"ROUT", NULL, "Line Out Enable"}, - {"Line Out Enable", "Switch", "Line Out"}, - {"Line Out", NULL, "Stereo Mixer"}, - - /* mono1 out */ - {"MOUT1", NULL, "Mono Out"}, - {"Mono Out", NULL, "Mono1 Mixer"}, - - /* left HP */ - {"HPL", NULL, "Left HP Enable"}, - {"Left HP Enable", "Switch", "HP L Amp"}, - {"HP L Amp", NULL, "Stereo Mixer"}, - - /* right HP */ - {"HPR", NULL, "Right HP Enable"}, - {"Right HP Enable", "Switch", "HP R Amp"}, - {"HP R Amp", NULL, "Stereo Mixer"}, - - /* speaker */ - {"SPP", NULL, "Speaker Enable"}, - {"SPN", NULL, "Speaker Enable"}, - {"Speaker Enable", "Switch", "Spk Amp"}, - {"Spk Amp", NULL, "MIN"}, - - /* mono 2 */ - {"MOUT2", NULL, "Mono 2 Enable"}, - {"Mono 2 Enable", "Switch", "Stereo Mixer"}, - - /* Aux In */ - {"Aux In", NULL, "AUX"}, - - /* ADC */ - {"ADC", NULL, "Input Mixer"}, - {"Input Mixer", "Mic Capture Switch", "Mic"}, - {"Input Mixer", "Aux Capture Switch", "Aux In"}, -}; - -static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); - - ak4535->sysclk = freq; - return 0; -} - -static int ak4535_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); - u8 mode2 = snd_soc_read(codec, AK4535_MODE2) & ~(0x3 << 5); - int rate = params_rate(params), fs = 256; - - if (rate) - fs = ak4535->sysclk / rate; - - /* set fs */ - switch (fs) { - case 1024: - mode2 |= (0x2 << 5); - break; - case 512: - mode2 |= (0x1 << 5); - break; - case 256: - break; - } - - /* set rate */ - snd_soc_write(codec, AK4535_MODE2, mode2); - return 0; -} - -static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u8 mode1 = 0; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - mode1 = 0x0002; - break; - case SND_SOC_DAIFMT_LEFT_J: - mode1 = 0x0001; - break; - default: - return -EINVAL; - } - - /* use 32 fs for BCLK to save power */ - mode1 |= 0x4; - - snd_soc_write(codec, AK4535_MODE1, mode1); - return 0; -} - -static int ak4535_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, AK4535_DAC); - if (!mute) - snd_soc_write(codec, AK4535_DAC, mute_reg & ~0x20); - else - snd_soc_write(codec, AK4535_DAC, mute_reg | 0x20); - return 0; -} - -static int ak4535_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0); - break; - case SND_SOC_BIAS_PREPARE: - snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0x20); - break; - case SND_SOC_BIAS_STANDBY: - snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0x80); - snd_soc_update_bits(codec, AK4535_PM2, 0x80, 0); - break; - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define AK4535_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) - -static const struct snd_soc_dai_ops ak4535_dai_ops = { - .hw_params = ak4535_hw_params, - .set_fmt = ak4535_set_dai_fmt, - .digital_mute = ak4535_mute, - .set_sysclk = ak4535_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver ak4535_dai = { - .name = "ak4535-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = AK4535_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = AK4535_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &ak4535_dai_ops, -}; - -static int ak4535_suspend(struct snd_soc_codec *codec) -{ - ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int ak4535_resume(struct snd_soc_codec *codec) -{ - snd_soc_cache_sync(codec); - ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int ak4535_probe(struct snd_soc_codec *codec) -{ - struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = ak4535->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - /* power on device */ - ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - snd_soc_add_codec_controls(codec, ak4535_snd_controls, - ARRAY_SIZE(ak4535_snd_controls)); - return 0; -} - -/* power down chip */ -static int ak4535_remove(struct snd_soc_codec *codec) -{ - ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static const struct regmap_config ak4535_regmap = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = AK4535_STATUS, - .volatile_reg = ak4535_volatile, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = ak4535_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(ak4535_reg_defaults), -}; - -static struct snd_soc_codec_driver soc_codec_dev_ak4535 = { - .probe = ak4535_probe, - .remove = ak4535_remove, - .suspend = ak4535_suspend, - .resume = ak4535_resume, - .set_bias_level = ak4535_set_bias_level, - .dapm_widgets = ak4535_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets), - .dapm_routes = ak4535_audio_map, - .num_dapm_routes = ARRAY_SIZE(ak4535_audio_map), -}; - -static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct ak4535_priv *ak4535; - int ret; - - ak4535 = devm_kzalloc(&i2c->dev, sizeof(struct ak4535_priv), - GFP_KERNEL); - if (ak4535 == NULL) - return -ENOMEM; - - ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap); - if (IS_ERR(ak4535->regmap)) { - ret = PTR_ERR(ak4535->regmap); - dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); - return ret; - } - - i2c_set_clientdata(i2c, ak4535); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_ak4535, &ak4535_dai, 1); - if (ret != 0) - regmap_exit(ak4535->regmap); - - return ret; -} - -static __devexit int ak4535_i2c_remove(struct i2c_client *client) -{ - struct ak4535_priv *ak4535 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(ak4535->regmap); - return 0; -} - -static const struct i2c_device_id ak4535_i2c_id[] = { - { "ak4535", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id); - -static struct i2c_driver ak4535_i2c_driver = { - .driver = { - .name = "ak4535", - .owner = THIS_MODULE, - }, - .probe = ak4535_i2c_probe, - .remove = __devexit_p(ak4535_i2c_remove), - .id_table = ak4535_i2c_id, -}; - -module_i2c_driver(ak4535_i2c_driver); - -MODULE_DESCRIPTION("Soc AK4535 driver"); -MODULE_AUTHOR("Richard Purdie"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ak4535.h b/ANDROID_3.4.5/sound/soc/codecs/ak4535.h deleted file mode 100644 index 402de1d2..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ak4535.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * ak4535.h -- AK4535 Soc Audio driver - * - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie - * - * Based on wm8753.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _AK4535_H -#define _AK4535_H - -/* AK4535 register space */ - -#define AK4535_PM1 0x0 -#define AK4535_PM2 0x1 -#define AK4535_SIG1 0x2 -#define AK4535_SIG2 0x3 -#define AK4535_MODE1 0x4 -#define AK4535_MODE2 0x5 -#define AK4535_DAC 0x6 -#define AK4535_MIC 0x7 -#define AK4535_TIMER 0x8 -#define AK4535_ALC1 0x9 -#define AK4535_ALC2 0xa -#define AK4535_PGA 0xb -#define AK4535_LATT 0xc -#define AK4535_RATT 0xd -#define AK4535_VOL 0xe -#define AK4535_STATUS 0xf - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/ak4641.c b/ANDROID_3.4.5/sound/soc/codecs/ak4641.c deleted file mode 100644 index c4d165a4..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ak4641.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * ak4641.c -- AK4641 ALSA Soc Audio driver - * - * Copyright (C) 2008 Harald Welte - * Copyright (C) 2011 Dmitry Artamonow - * - * Based on ak4535.c by Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ak4641.h" - -/* codec private data */ -struct ak4641_priv { - unsigned int sysclk; - int deemph; - int playback_fs; -}; - -/* - * ak4641 register cache - */ -static const u8 ak4641_reg[AK4641_CACHEREGNUM] = { - 0x00, 0x80, 0x00, 0x80, - 0x02, 0x00, 0x11, 0x05, - 0x00, 0x00, 0x36, 0x10, - 0x00, 0x00, 0x57, 0x00, - 0x88, 0x88, 0x08, 0x08 -}; - -static const int deemph_settings[] = {44100, 0, 48000, 32000}; - -static int ak4641_set_deemph(struct snd_soc_codec *codec) -{ - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); - int i, best = 0; - - for (i = 0 ; i < ARRAY_SIZE(deemph_settings); i++) { - /* if deemphasis is on, select the nearest available rate */ - if (ak4641->deemph && deemph_settings[i] != 0 && - abs(deemph_settings[i] - ak4641->playback_fs) < - abs(deemph_settings[best] - ak4641->playback_fs)) - best = i; - - if (!ak4641->deemph && deemph_settings[i] == 0) - best = i; - } - - dev_dbg(codec->dev, "Set deemphasis %d\n", best); - - return snd_soc_update_bits(codec, AK4641_DAC, 0x3, best); -} - -static int ak4641_put_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); - int deemph = ucontrol->value.enumerated.item[0]; - - if (deemph > 1) - return -EINVAL; - - ak4641->deemph = deemph; - - return ak4641_set_deemph(codec); -} - -static int ak4641_get_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = ak4641->deemph; - return 0; -}; - -static const char *ak4641_mono_out[] = {"(L + R)/2", "Hi-Z"}; -static const char *ak4641_hp_out[] = {"Stereo", "Mono"}; -static const char *ak4641_mic_select[] = {"Internal", "External"}; -static const char *ak4641_mic_or_dac[] = {"Microphone", "Voice DAC"}; - - -static const DECLARE_TLV_DB_SCALE(mono_gain_tlv, -1700, 2300, 0); -static const DECLARE_TLV_DB_SCALE(mic_boost_tlv, 0, 2000, 0); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1050, 150, 0); -static const DECLARE_TLV_DB_SCALE(master_tlv, -12750, 50, 0); -static const DECLARE_TLV_DB_SCALE(mic_stereo_sidetone_tlv, -2700, 300, 0); -static const DECLARE_TLV_DB_SCALE(mic_mono_sidetone_tlv, -400, 400, 0); -static const DECLARE_TLV_DB_SCALE(capture_tlv, -800, 50, 0); -static const DECLARE_TLV_DB_SCALE(alc_tlv, -800, 50, 0); -static const DECLARE_TLV_DB_SCALE(aux_in_tlv, -2100, 300, 0); - - -static const struct soc_enum ak4641_mono_out_enum = - SOC_ENUM_SINGLE(AK4641_SIG1, 6, 2, ak4641_mono_out); -static const struct soc_enum ak4641_hp_out_enum = - SOC_ENUM_SINGLE(AK4641_MODE2, 2, 2, ak4641_hp_out); -static const struct soc_enum ak4641_mic_select_enum = - SOC_ENUM_SINGLE(AK4641_MIC, 1, 2, ak4641_mic_select); -static const struct soc_enum ak4641_mic_or_dac_enum = - SOC_ENUM_SINGLE(AK4641_BTIF, 4, 2, ak4641_mic_or_dac); - -static const struct snd_kcontrol_new ak4641_snd_controls[] = { - SOC_ENUM("Mono 1 Output", ak4641_mono_out_enum), - SOC_SINGLE_TLV("Mono 1 Gain Volume", AK4641_SIG1, 7, 1, 1, - mono_gain_tlv), - SOC_ENUM("Headphone Output", ak4641_hp_out_enum), - SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, - ak4641_get_deemph, ak4641_put_deemph), - - SOC_SINGLE_TLV("Mic Boost Volume", AK4641_MIC, 0, 1, 0, mic_boost_tlv), - - SOC_SINGLE("ALC Operation Time", AK4641_TIMER, 0, 3, 0), - SOC_SINGLE("ALC Recovery Time", AK4641_TIMER, 2, 3, 0), - SOC_SINGLE("ALC ZC Time", AK4641_TIMER, 4, 3, 0), - - SOC_SINGLE("ALC 1 Switch", AK4641_ALC1, 5, 1, 0), - - SOC_SINGLE_TLV("ALC Volume", AK4641_ALC2, 0, 71, 0, alc_tlv), - SOC_SINGLE("Left Out Enable Switch", AK4641_SIG2, 1, 1, 0), - SOC_SINGLE("Right Out Enable Switch", AK4641_SIG2, 0, 1, 0), - - SOC_SINGLE_TLV("Capture Volume", AK4641_PGA, 0, 71, 0, capture_tlv), - - SOC_DOUBLE_R_TLV("Master Playback Volume", AK4641_LATT, - AK4641_RATT, 0, 255, 1, master_tlv), - - SOC_SINGLE_TLV("AUX In Volume", AK4641_VOL, 0, 15, 0, aux_in_tlv), - - SOC_SINGLE("Equalizer Switch", AK4641_DAC, 2, 1, 0), - SOC_SINGLE_TLV("EQ1 100 Hz Volume", AK4641_EQLO, 0, 15, 1, eq_tlv), - SOC_SINGLE_TLV("EQ2 250 Hz Volume", AK4641_EQLO, 4, 15, 1, eq_tlv), - SOC_SINGLE_TLV("EQ3 1 kHz Volume", AK4641_EQMID, 0, 15, 1, eq_tlv), - SOC_SINGLE_TLV("EQ4 3.5 kHz Volume", AK4641_EQMID, 4, 15, 1, eq_tlv), - SOC_SINGLE_TLV("EQ5 10 kHz Volume", AK4641_EQHI, 0, 15, 1, eq_tlv), -}; - -/* Mono 1 Mixer */ -static const struct snd_kcontrol_new ak4641_mono1_mixer_controls[] = { - SOC_DAPM_SINGLE_TLV("Mic Mono Sidetone Volume", AK4641_VOL, 7, 1, 0, - mic_mono_sidetone_tlv), - SOC_DAPM_SINGLE("Mic Mono Sidetone Switch", AK4641_SIG1, 4, 1, 0), - SOC_DAPM_SINGLE("Mono Playback Switch", AK4641_SIG1, 5, 1, 0), -}; - -/* Stereo Mixer */ -static const struct snd_kcontrol_new ak4641_stereo_mixer_controls[] = { - SOC_DAPM_SINGLE_TLV("Mic Sidetone Volume", AK4641_VOL, 4, 7, 0, - mic_stereo_sidetone_tlv), - SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4641_SIG2, 4, 1, 0), - SOC_DAPM_SINGLE("Playback Switch", AK4641_SIG2, 7, 1, 0), - SOC_DAPM_SINGLE("Aux Bypass Switch", AK4641_SIG2, 5, 1, 0), -}; - -/* Input Mixer */ -static const struct snd_kcontrol_new ak4641_input_mixer_controls[] = { - SOC_DAPM_SINGLE("Mic Capture Switch", AK4641_MIC, 2, 1, 0), - SOC_DAPM_SINGLE("Aux Capture Switch", AK4641_MIC, 5, 1, 0), -}; - -/* Mic mux */ -static const struct snd_kcontrol_new ak4641_mic_mux_control = - SOC_DAPM_ENUM("Mic Select", ak4641_mic_select_enum); - -/* Input mux */ -static const struct snd_kcontrol_new ak4641_input_mux_control = - SOC_DAPM_ENUM("Input Select", ak4641_mic_or_dac_enum); - -/* mono 2 switch */ -static const struct snd_kcontrol_new ak4641_mono2_control = - SOC_DAPM_SINGLE("Switch", AK4641_SIG1, 0, 1, 0); - -/* ak4641 dapm widgets */ -static const struct snd_soc_dapm_widget ak4641_dapm_widgets[] = { - SND_SOC_DAPM_MIXER("Stereo Mixer", SND_SOC_NOPM, 0, 0, - &ak4641_stereo_mixer_controls[0], - ARRAY_SIZE(ak4641_stereo_mixer_controls)), - SND_SOC_DAPM_MIXER("Mono1 Mixer", SND_SOC_NOPM, 0, 0, - &ak4641_mono1_mixer_controls[0], - ARRAY_SIZE(ak4641_mono1_mixer_controls)), - SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, - &ak4641_input_mixer_controls[0], - ARRAY_SIZE(ak4641_input_mixer_controls)), - SND_SOC_DAPM_MUX("Mic Mux", SND_SOC_NOPM, 0, 0, - &ak4641_mic_mux_control), - SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, - &ak4641_input_mux_control), - SND_SOC_DAPM_SWITCH("Mono 2 Enable", SND_SOC_NOPM, 0, 0, - &ak4641_mono2_control), - - SND_SOC_DAPM_OUTPUT("LOUT"), - SND_SOC_DAPM_OUTPUT("ROUT"), - SND_SOC_DAPM_OUTPUT("MOUT1"), - SND_SOC_DAPM_OUTPUT("MOUT2"), - SND_SOC_DAPM_OUTPUT("MICOUT"), - - SND_SOC_DAPM_ADC("ADC", "HiFi Capture", AK4641_PM1, 0, 0), - SND_SOC_DAPM_PGA("Mic", AK4641_PM1, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("AUX In", AK4641_PM1, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mono Out", AK4641_PM1, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Line Out", AK4641_PM1, 4, 0, NULL, 0), - - SND_SOC_DAPM_DAC("DAC", "HiFi Playback", AK4641_PM2, 0, 0), - SND_SOC_DAPM_PGA("Mono Out 2", AK4641_PM2, 3, 0, NULL, 0), - - SND_SOC_DAPM_ADC("Voice ADC", "Voice Capture", AK4641_BTIF, 0, 0), - SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0), - - SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4641_MIC, 3, 0), - SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4641_MIC, 4, 0), - - SND_SOC_DAPM_INPUT("MICIN"), - SND_SOC_DAPM_INPUT("MICEXT"), - SND_SOC_DAPM_INPUT("AUX"), - SND_SOC_DAPM_INPUT("AIN"), -}; - -static const struct snd_soc_dapm_route ak4641_audio_map[] = { - /* Stereo Mixer */ - {"Stereo Mixer", "Playback Switch", "DAC"}, - {"Stereo Mixer", "Mic Sidetone Switch", "Input Mux"}, - {"Stereo Mixer", "Aux Bypass Switch", "AUX In"}, - - /* Mono 1 Mixer */ - {"Mono1 Mixer", "Mic Mono Sidetone Switch", "Input Mux"}, - {"Mono1 Mixer", "Mono Playback Switch", "DAC"}, - - /* Mic */ - {"Mic", NULL, "AIN"}, - {"Mic Mux", "Internal", "Mic Int Bias"}, - {"Mic Mux", "External", "Mic Ext Bias"}, - {"Mic Int Bias", NULL, "MICIN"}, - {"Mic Ext Bias", NULL, "MICEXT"}, - {"MICOUT", NULL, "Mic Mux"}, - - /* Input Mux */ - {"Input Mux", "Microphone", "Mic"}, - {"Input Mux", "Voice DAC", "Voice DAC"}, - - /* Line Out */ - {"LOUT", NULL, "Line Out"}, - {"ROUT", NULL, "Line Out"}, - {"Line Out", NULL, "Stereo Mixer"}, - - /* Mono 1 Out */ - {"MOUT1", NULL, "Mono Out"}, - {"Mono Out", NULL, "Mono1 Mixer"}, - - /* Mono 2 Out */ - {"MOUT2", NULL, "Mono 2 Enable"}, - {"Mono 2 Enable", "Switch", "Mono Out 2"}, - {"Mono Out 2", NULL, "Stereo Mixer"}, - - {"Voice ADC", NULL, "Mono 2 Enable"}, - - /* Aux In */ - {"AUX In", NULL, "AUX"}, - - /* ADC */ - {"ADC", NULL, "Input Mixer"}, - {"Input Mixer", "Mic Capture Switch", "Mic"}, - {"Input Mixer", "Aux Capture Switch", "AUX In"}, -}; - -static int ak4641_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); - - ak4641->sysclk = freq; - return 0; -} - -static int ak4641_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); - int rate = params_rate(params), fs = 256; - u8 mode2; - - if (rate) - fs = ak4641->sysclk / rate; - else - return -EINVAL; - - /* set fs */ - switch (fs) { - case 1024: - mode2 = (0x2 << 5); - break; - case 512: - mode2 = (0x1 << 5); - break; - case 256: - mode2 = (0x0 << 5); - break; - default: - dev_err(codec->dev, "Error: unsupported fs=%d\n", fs); - return -EINVAL; - } - - snd_soc_update_bits(codec, AK4641_MODE2, (0x3 << 5), mode2); - - /* Update de-emphasis filter for the new rate */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ak4641->playback_fs = rate; - ak4641_set_deemph(codec); - }; - - return 0; -} - -static int ak4641_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u8 btif; - int ret; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - btif = (0x3 << 5); - break; - case SND_SOC_DAIFMT_LEFT_J: - btif = (0x2 << 5); - break; - case SND_SOC_DAIFMT_DSP_A: /* MSB after FRM */ - btif = (0x0 << 5); - break; - case SND_SOC_DAIFMT_DSP_B: /* MSB during FRM */ - btif = (0x1 << 5); - break; - default: - return -EINVAL; - } - - ret = snd_soc_update_bits(codec, AK4641_BTIF, (0x3 << 5), btif); - if (ret < 0) - return ret; - - return 0; -} - -static int ak4641_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u8 mode1 = 0; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - mode1 = 0x02; - break; - case SND_SOC_DAIFMT_LEFT_J: - mode1 = 0x01; - break; - default: - return -EINVAL; - } - - return snd_soc_write(codec, AK4641_MODE1, mode1); -} - -static int ak4641_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - return snd_soc_update_bits(codec, AK4641_DAC, 0x20, mute ? 0x20 : 0); -} - -static int ak4641_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct ak4641_platform_data *pdata = codec->dev->platform_data; - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - /* unmute */ - snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0); - break; - case SND_SOC_BIAS_PREPARE: - /* mute */ - snd_soc_update_bits(codec, AK4641_DAC, 0x20, 0x20); - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - if (pdata && gpio_is_valid(pdata->gpio_power)) - gpio_set_value(pdata->gpio_power, 1); - mdelay(1); - if (pdata && gpio_is_valid(pdata->gpio_npdn)) - gpio_set_value(pdata->gpio_npdn, 1); - mdelay(1); - - ret = snd_soc_cache_sync(codec); - if (ret) { - dev_err(codec->dev, - "Failed to sync cache: %d\n", ret); - return ret; - } - } - snd_soc_update_bits(codec, AK4641_PM1, 0x80, 0x80); - snd_soc_update_bits(codec, AK4641_PM2, 0x80, 0); - break; - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, AK4641_PM1, 0x80, 0); - if (pdata && gpio_is_valid(pdata->gpio_npdn)) - gpio_set_value(pdata->gpio_npdn, 0); - if (pdata && gpio_is_valid(pdata->gpio_power)) - gpio_set_value(pdata->gpio_power, 0); - codec->cache_sync = 1; - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define AK4641_RATES (SNDRV_PCM_RATE_8000_48000) -#define AK4641_RATES_BT (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000) -#define AK4641_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) - -static const struct snd_soc_dai_ops ak4641_i2s_dai_ops = { - .hw_params = ak4641_i2s_hw_params, - .set_fmt = ak4641_i2s_set_dai_fmt, - .digital_mute = ak4641_mute, - .set_sysclk = ak4641_set_dai_sysclk, -}; - -static const struct snd_soc_dai_ops ak4641_pcm_dai_ops = { - .hw_params = NULL, /* rates are controlled by BT chip */ - .set_fmt = ak4641_pcm_set_dai_fmt, - .digital_mute = ak4641_mute, - .set_sysclk = ak4641_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver ak4641_dai[] = { -{ - .name = "ak4641-hifi", - .id = 1, - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = AK4641_RATES, - .formats = AK4641_FORMATS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = AK4641_RATES, - .formats = AK4641_FORMATS, - }, - .ops = &ak4641_i2s_dai_ops, - .symmetric_rates = 1, -}, -{ - .name = "ak4641-voice", - .id = 1, - .playback = { - .stream_name = "Voice Playback", - .channels_min = 1, - .channels_max = 1, - .rates = AK4641_RATES_BT, - .formats = AK4641_FORMATS, - }, - .capture = { - .stream_name = "Voice Capture", - .channels_min = 1, - .channels_max = 1, - .rates = AK4641_RATES_BT, - .formats = AK4641_FORMATS, - }, - .ops = &ak4641_pcm_dai_ops, - .symmetric_rates = 1, -}, -}; - -static int ak4641_suspend(struct snd_soc_codec *codec) -{ - ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int ak4641_resume(struct snd_soc_codec *codec) -{ - ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int ak4641_probe(struct snd_soc_codec *codec) -{ - struct ak4641_platform_data *pdata = codec->dev->platform_data; - int ret; - - - if (pdata) { - if (gpio_is_valid(pdata->gpio_power)) { - ret = gpio_request_one(pdata->gpio_power, - GPIOF_OUT_INIT_LOW, "ak4641 power"); - if (ret) - goto err_out; - } - if (gpio_is_valid(pdata->gpio_npdn)) { - ret = gpio_request_one(pdata->gpio_npdn, - GPIOF_OUT_INIT_LOW, "ak4641 npdn"); - if (ret) - goto err_gpio; - - udelay(1); /* > 150 ns */ - gpio_set_value(pdata->gpio_npdn, 1); - } - } - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err_register; - } - - /* power on device */ - ak4641_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; - -err_register: - if (pdata) { - if (gpio_is_valid(pdata->gpio_power)) - gpio_set_value(pdata->gpio_power, 0); - if (gpio_is_valid(pdata->gpio_npdn)) - gpio_free(pdata->gpio_npdn); - } -err_gpio: - if (pdata && gpio_is_valid(pdata->gpio_power)) - gpio_free(pdata->gpio_power); -err_out: - return ret; -} - -static int ak4641_remove(struct snd_soc_codec *codec) -{ - struct ak4641_platform_data *pdata = codec->dev->platform_data; - - ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF); - - if (pdata) { - if (gpio_is_valid(pdata->gpio_power)) { - gpio_set_value(pdata->gpio_power, 0); - gpio_free(pdata->gpio_power); - } - if (gpio_is_valid(pdata->gpio_npdn)) - gpio_free(pdata->gpio_npdn); - } - return 0; -} - - -static struct snd_soc_codec_driver soc_codec_dev_ak4641 = { - .probe = ak4641_probe, - .remove = ak4641_remove, - .suspend = ak4641_suspend, - .resume = ak4641_resume, - .controls = ak4641_snd_controls, - .num_controls = ARRAY_SIZE(ak4641_snd_controls), - .dapm_widgets = ak4641_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4641_dapm_widgets), - .dapm_routes = ak4641_audio_map, - .num_dapm_routes = ARRAY_SIZE(ak4641_audio_map), - .set_bias_level = ak4641_set_bias_level, - .reg_cache_size = ARRAY_SIZE(ak4641_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = ak4641_reg, - .reg_cache_step = 1, -}; - - -static int __devinit ak4641_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct ak4641_priv *ak4641; - int ret; - - ak4641 = devm_kzalloc(&i2c->dev, sizeof(struct ak4641_priv), - GFP_KERNEL); - if (!ak4641) - return -ENOMEM; - - i2c_set_clientdata(i2c, ak4641); - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak4641, - ak4641_dai, ARRAY_SIZE(ak4641_dai)); - return ret; -} - -static int __devexit ak4641_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - return 0; -} - -static const struct i2c_device_id ak4641_i2c_id[] = { - { "ak4641", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ak4641_i2c_id); - -static struct i2c_driver ak4641_i2c_driver = { - .driver = { - .name = "ak4641", - .owner = THIS_MODULE, - }, - .probe = ak4641_i2c_probe, - .remove = __devexit_p(ak4641_i2c_remove), - .id_table = ak4641_i2c_id, -}; - -static int __init ak4641_modinit(void) -{ - int ret; - - ret = i2c_add_driver(&ak4641_i2c_driver); - if (ret != 0) - pr_err("Failed to register AK4641 I2C driver: %d\n", ret); - - return ret; -} -module_init(ak4641_modinit); - -static void __exit ak4641_exit(void) -{ - i2c_del_driver(&ak4641_i2c_driver); -} -module_exit(ak4641_exit); - -MODULE_DESCRIPTION("SoC AK4641 driver"); -MODULE_AUTHOR("Harald Welte "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ak4641.h b/ANDROID_3.4.5/sound/soc/codecs/ak4641.h deleted file mode 100644 index 4a263248..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ak4641.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ak4641.h -- AK4641 SoC Audio driver - * - * Copyright 2008 Harald Welte - * - * Based on ak4535.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _AK4641_H -#define _AK4641_H - -/* AK4641 register space */ - -#define AK4641_PM1 0x00 -#define AK4641_PM2 0x01 -#define AK4641_SIG1 0x02 -#define AK4641_SIG2 0x03 -#define AK4641_MODE1 0x04 -#define AK4641_MODE2 0x05 -#define AK4641_DAC 0x06 -#define AK4641_MIC 0x07 -#define AK4641_TIMER 0x08 -#define AK4641_ALC1 0x09 -#define AK4641_ALC2 0x0a -#define AK4641_PGA 0x0b -#define AK4641_LATT 0x0c -#define AK4641_RATT 0x0d -#define AK4641_VOL 0x0e -#define AK4641_STATUS 0x0f -#define AK4641_EQLO 0x10 -#define AK4641_EQMID 0x11 -#define AK4641_EQHI 0x12 -#define AK4641_BTIF 0x13 - -#define AK4641_CACHEREGNUM 0x14 - - - -#define AK4641_DAI_HIFI 0 -#define AK4641_DAI_VOICE 1 - - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/ak4642.c b/ANDROID_3.4.5/sound/soc/codecs/ak4642.c deleted file mode 100644 index b3e24f28..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ak4642.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * ak4642.c -- AK4642/AK4643 ALSA Soc Audio driver - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto - * - * Based on wm8731.c by Richard Purdie - * Based on ak4535.c by Richard Purdie - * Based on wm8753.c by Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* ** CAUTION ** - * - * This is very simple driver. - * It can use headphone output / stereo input only - * - * AK4642 is tested. - * AK4643 is tested. - * AK4648 is tested. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define PW_MGMT1 0x00 -#define PW_MGMT2 0x01 -#define SG_SL1 0x02 -#define SG_SL2 0x03 -#define MD_CTL1 0x04 -#define MD_CTL2 0x05 -#define TIMER 0x06 -#define ALC_CTL1 0x07 -#define ALC_CTL2 0x08 -#define L_IVC 0x09 -#define L_DVC 0x0a -#define ALC_CTL3 0x0b -#define R_IVC 0x0c -#define R_DVC 0x0d -#define MD_CTL3 0x0e -#define MD_CTL4 0x0f -#define PW_MGMT3 0x10 -#define DF_S 0x11 -#define FIL3_0 0x12 -#define FIL3_1 0x13 -#define FIL3_2 0x14 -#define FIL3_3 0x15 -#define EQ_0 0x16 -#define EQ_1 0x17 -#define EQ_2 0x18 -#define EQ_3 0x19 -#define EQ_4 0x1a -#define EQ_5 0x1b -#define FIL1_0 0x1c -#define FIL1_1 0x1d -#define FIL1_2 0x1e -#define FIL1_3 0x1f -#define PW_MGMT4 0x20 -#define MD_CTL5 0x21 -#define LO_MS 0x22 -#define HP_MS 0x23 -#define SPK_MS 0x24 - -/* PW_MGMT1*/ -#define PMVCM (1 << 6) /* VCOM Power Management */ -#define PMMIN (1 << 5) /* MIN Input Power Management */ -#define PMDAC (1 << 2) /* DAC Power Management */ -#define PMADL (1 << 0) /* MIC Amp Lch and ADC Lch Power Management */ - -/* PW_MGMT2 */ -#define HPMTN (1 << 6) -#define PMHPL (1 << 5) -#define PMHPR (1 << 4) -#define MS (1 << 3) /* master/slave select */ -#define MCKO (1 << 1) -#define PMPLL (1 << 0) - -#define PMHP_MASK (PMHPL | PMHPR) -#define PMHP PMHP_MASK - -/* PW_MGMT3 */ -#define PMADR (1 << 0) /* MIC L / ADC R Power Management */ - -/* SG_SL1 */ -#define MINS (1 << 6) /* Switch from MIN to Speaker */ -#define DACL (1 << 4) /* Switch from DAC to Stereo or Receiver */ -#define PMMP (1 << 2) /* MPWR pin Power Management */ -#define MGAIN0 (1 << 0) /* MIC amp gain*/ - -/* TIMER */ -#define ZTM(param) ((param & 0x3) << 4) /* ALC Zoro Crossing TimeOut */ -#define WTM(param) (((param & 0x4) << 4) | ((param & 0x3) << 2)) - -/* ALC_CTL1 */ -#define ALC (1 << 5) /* ALC Enable */ -#define LMTH0 (1 << 0) /* ALC Limiter / Recovery Level */ - -/* MD_CTL1 */ -#define PLL3 (1 << 7) -#define PLL2 (1 << 6) -#define PLL1 (1 << 5) -#define PLL0 (1 << 4) -#define PLL_MASK (PLL3 | PLL2 | PLL1 | PLL0) - -#define BCKO_MASK (1 << 3) -#define BCKO_64 BCKO_MASK - -#define DIF_MASK (3 << 0) -#define DSP (0 << 0) -#define RIGHT_J (1 << 0) -#define LEFT_J (2 << 0) -#define I2S (3 << 0) - -/* MD_CTL2 */ -#define FS0 (1 << 0) -#define FS1 (1 << 1) -#define FS2 (1 << 2) -#define FS3 (1 << 5) -#define FS_MASK (FS0 | FS1 | FS2 | FS3) - -/* MD_CTL3 */ -#define BST1 (1 << 3) - -/* MD_CTL4 */ -#define DACH (1 << 0) - -/* - * Playback Volume (table 39) - * - * max : 0x00 : +12.0 dB - * ( 0.5 dB step ) - * min : 0xFE : -115.0 dB - * mute: 0xFF - */ -static const DECLARE_TLV_DB_SCALE(out_tlv, -11550, 50, 1); - -static const struct snd_kcontrol_new ak4642_snd_controls[] = { - - SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC, - 0, 0xFF, 1, out_tlv), -}; - -static const struct snd_kcontrol_new ak4642_headphone_control = - SOC_DAPM_SINGLE("Switch", PW_MGMT2, 6, 1, 0); - -static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = { - SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0), -}; - -static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = { - - /* Outputs */ - SND_SOC_DAPM_OUTPUT("HPOUTL"), - SND_SOC_DAPM_OUTPUT("HPOUTR"), - SND_SOC_DAPM_OUTPUT("LINEOUT"), - - SND_SOC_DAPM_PGA("HPL Out", PW_MGMT2, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("HPR Out", PW_MGMT2, 4, 0, NULL, 0), - SND_SOC_DAPM_SWITCH("Headphone Enable", SND_SOC_NOPM, 0, 0, - &ak4642_headphone_control), - - SND_SOC_DAPM_PGA("DACH", MD_CTL4, 0, 0, NULL, 0), - - SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0, - &ak4642_lout_mixer_controls[0], - ARRAY_SIZE(ak4642_lout_mixer_controls)), - - /* DAC */ - SND_SOC_DAPM_DAC("DAC", "HiFi Playback", PW_MGMT1, 2, 0), -}; - -static const struct snd_soc_dapm_route ak4642_intercon[] = { - - /* Outputs */ - {"HPOUTL", NULL, "HPL Out"}, - {"HPOUTR", NULL, "HPR Out"}, - {"LINEOUT", NULL, "LINEOUT Mixer"}, - - {"HPL Out", NULL, "Headphone Enable"}, - {"HPR Out", NULL, "Headphone Enable"}, - - {"Headphone Enable", "Switch", "DACH"}, - - {"DACH", NULL, "DAC"}, - - {"LINEOUT Mixer", "DACL", "DAC"}, -}; - -/* codec private data */ -struct ak4642_priv { - unsigned int sysclk; - enum snd_soc_control_type control_type; -}; - -/* - * ak4642 register cache - */ -static const u8 ak4642_reg[] = { - 0x00, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0xe1, 0xe1, 0x18, 0x00, - 0xe1, 0x18, 0x11, 0x08, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, -}; - -static const u8 ak4648_reg[] = { - 0x00, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0xe1, 0xe1, 0x18, 0x00, - 0xe1, 0x18, 0x11, 0xb8, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x88, 0x88, 0x08, -}; - -static int ak4642_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct snd_soc_codec *codec = dai->codec; - - if (is_play) { - /* - * start headphone output - * - * PLL, Master Mode - * Audio I/F Format :MSB justified (ADC & DAC) - * Bass Boost Level : Middle - * - * This operation came from example code of - * "ASAHI KASEI AK4642" (japanese) manual p97. - */ - snd_soc_write(codec, L_IVC, 0x91); /* volume */ - snd_soc_write(codec, R_IVC, 0x91); /* volume */ - } else { - /* - * start stereo input - * - * PLL Master Mode - * Audio I/F Format:MSB justified (ADC & DAC) - * Pre MIC AMP:+20dB - * MIC Power On - * ALC setting:Refer to Table 35 - * ALC bit=“1” - * - * This operation came from example code of - * "ASAHI KASEI AK4642" (japanese) manual p94. - */ - snd_soc_write(codec, SG_SL1, PMMP | MGAIN0); - snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); - snd_soc_write(codec, ALC_CTL1, ALC | LMTH0); - snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL); - snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR); - } - - return 0; -} - -static void ak4642_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct snd_soc_codec *codec = dai->codec; - - if (is_play) { - } else { - /* stop stereo input */ - snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0); - snd_soc_update_bits(codec, PW_MGMT3, PMADR, 0); - snd_soc_update_bits(codec, ALC_CTL1, ALC, 0); - } -} - -static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u8 pll; - - switch (freq) { - case 11289600: - pll = PLL2; - break; - case 12288000: - pll = PLL2 | PLL0; - break; - case 12000000: - pll = PLL2 | PLL1; - break; - case 24000000: - pll = PLL2 | PLL1 | PLL0; - break; - case 13500000: - pll = PLL3 | PLL2; - break; - case 27000000: - pll = PLL3 | PLL2 | PLL0; - break; - default: - return -EINVAL; - } - snd_soc_update_bits(codec, MD_CTL1, PLL_MASK, pll); - - return 0; -} - -static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - u8 data; - u8 bcko; - - data = MCKO | PMPLL; /* use MCKO */ - bcko = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - data |= MS; - bcko = BCKO_64; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - snd_soc_update_bits(codec, PW_MGMT2, MS | MCKO | PMPLL, data); - snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko); - - /* format type */ - data = 0; - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_LEFT_J: - data = LEFT_J; - break; - case SND_SOC_DAIFMT_I2S: - data = I2S; - break; - /* FIXME - * Please add RIGHT_J / DSP support here - */ - default: - return -EINVAL; - break; - } - snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data); - - return 0; -} - -static int ak4642_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - u8 rate; - - switch (params_rate(params)) { - case 7350: - rate = FS2; - break; - case 8000: - rate = 0; - break; - case 11025: - rate = FS2 | FS0; - break; - case 12000: - rate = FS0; - break; - case 14700: - rate = FS2 | FS1; - break; - case 16000: - rate = FS1; - break; - case 22050: - rate = FS2 | FS1 | FS0; - break; - case 24000: - rate = FS1 | FS0; - break; - case 29400: - rate = FS3 | FS2 | FS1; - break; - case 32000: - rate = FS3 | FS1; - break; - case 44100: - rate = FS3 | FS2 | FS1 | FS0; - break; - case 48000: - rate = FS3 | FS1 | FS0; - break; - default: - return -EINVAL; - break; - } - snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate); - - return 0; -} - -static int ak4642_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, PW_MGMT1, 0x00); - break; - default: - snd_soc_update_bits(codec, PW_MGMT1, PMVCM, PMVCM); - break; - } - codec->dapm.bias_level = level; - - return 0; -} - -static const struct snd_soc_dai_ops ak4642_dai_ops = { - .startup = ak4642_dai_startup, - .shutdown = ak4642_dai_shutdown, - .set_sysclk = ak4642_dai_set_sysclk, - .set_fmt = ak4642_dai_set_fmt, - .hw_params = ak4642_dai_hw_params, -}; - -static struct snd_soc_dai_driver ak4642_dai = { - .name = "ak4642-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE }, - .ops = &ak4642_dai_ops, - .symmetric_rates = 1, -}; - -static int ak4642_resume(struct snd_soc_codec *codec) -{ - snd_soc_cache_sync(codec); - return 0; -} - - -static int ak4642_probe(struct snd_soc_codec *codec) -{ - struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - snd_soc_add_codec_controls(codec, ak4642_snd_controls, - ARRAY_SIZE(ak4642_snd_controls)); - - ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int ak4642_remove(struct snd_soc_codec *codec) -{ - ak4642_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_ak4642 = { - .probe = ak4642_probe, - .remove = ak4642_remove, - .resume = ak4642_resume, - .set_bias_level = ak4642_set_bias_level, - .reg_cache_default = ak4642_reg, /* ak4642 reg */ - .reg_cache_size = ARRAY_SIZE(ak4642_reg), /* ak4642 reg */ - .reg_word_size = sizeof(u8), - .dapm_widgets = ak4642_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), - .dapm_routes = ak4642_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), -}; - -static struct snd_soc_codec_driver soc_codec_dev_ak4648 = { - .probe = ak4642_probe, - .remove = ak4642_remove, - .resume = ak4642_resume, - .set_bias_level = ak4642_set_bias_level, - .reg_cache_default = ak4648_reg, /* ak4648 reg */ - .reg_cache_size = ARRAY_SIZE(ak4648_reg), /* ak4648 reg */ - .reg_word_size = sizeof(u8), - .dapm_widgets = ak4642_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets), - .dapm_routes = ak4642_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4642_intercon), -}; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct ak4642_priv *ak4642; - int ret; - - ak4642 = devm_kzalloc(&i2c->dev, sizeof(struct ak4642_priv), - GFP_KERNEL); - if (!ak4642) - return -ENOMEM; - - i2c_set_clientdata(i2c, ak4642); - ak4642->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - (struct snd_soc_codec_driver *)id->driver_data, - &ak4642_dai, 1); - return ret; -} - -static __devexit int ak4642_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id ak4642_i2c_id[] = { - { "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 }, - { "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 }, - { "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); - -static struct i2c_driver ak4642_i2c_driver = { - .driver = { - .name = "ak4642-codec", - .owner = THIS_MODULE, - }, - .probe = ak4642_i2c_probe, - .remove = __devexit_p(ak4642_i2c_remove), - .id_table = ak4642_i2c_id, -}; -#endif - -static int __init ak4642_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&ak4642_i2c_driver); -#endif - return ret; - -} -module_init(ak4642_modinit); - -static void __exit ak4642_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&ak4642_i2c_driver); -#endif - -} -module_exit(ak4642_exit); - -MODULE_DESCRIPTION("Soc AK4642 driver"); -MODULE_AUTHOR("Kuninori Morimoto "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ak4671.c b/ANDROID_3.4.5/sound/soc/codecs/ak4671.c deleted file mode 100644 index 5fb7c2a8..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ak4671.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - * ak4671.c -- audio driver for AK4671 - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ak4671.h" - - -/* codec private data */ -struct ak4671_priv { - enum snd_soc_control_type control_type; -}; - -/* ak4671 register cache & default register settings */ -static const u8 ak4671_reg[AK4671_CACHEREGNUM] = { - 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */ - 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */ - 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */ - 0x02, /* AK4671_FORMAT_SELECT (0x03) */ - 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */ - 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */ - 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */ - 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */ - 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */ - 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */ - 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */ - 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */ - 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */ - 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */ - 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */ - 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */ - 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */ - 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */ - 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */ - 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */ - 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */ - 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */ - 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */ - 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */ - 0x02, /* AK4671_MODE_CONTROL1 (0x18) */ - 0x01, /* AK4671_MODE_CONTROL2 (0x19) */ - 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */ - 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */ - 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */ - 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */ - 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */ - 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */ - 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */ - 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */ - 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */ - 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */ - 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */ - 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */ - 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */ - 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */ - 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */ - 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */ - 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */ - 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */ - 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */ - 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */ - 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */ - 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */ - 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */ - 0x00, /* this register not used */ - 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */ - 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */ - 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */ - 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */ - 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */ - 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */ - 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */ - 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */ - 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */ - 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */ - 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */ - 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */ - 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */ - 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */ - 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */ - 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */ - 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */ - 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */ - 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */ - 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */ - 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */ - 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */ - 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */ - 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */ - 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */ - 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */ - 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */ - 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */ - 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */ - 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */ - 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */ - 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */ - 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */ - 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */ - 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */ - 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */ - 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */ - 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */ - 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */ - 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */ - 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */ -}; - -/* - * LOUT1/ROUT1 output volume control: - * from -24 to 6 dB in 6 dB steps (mute instead of -30 dB) - */ -static DECLARE_TLV_DB_SCALE(out1_tlv, -3000, 600, 1); - -/* - * LOUT2/ROUT2 output volume control: - * from -33 to 6 dB in 3 dB steps (mute instead of -33 dB) - */ -static DECLARE_TLV_DB_SCALE(out2_tlv, -3300, 300, 1); - -/* - * LOUT3/ROUT3 output volume control: - * from -6 to 3 dB in 3 dB steps - */ -static DECLARE_TLV_DB_SCALE(out3_tlv, -600, 300, 0); - -/* - * Mic amp gain control: - * from -15 to 30 dB in 3 dB steps - * REVISIT: The actual min value(0x01) is -12 dB and the reg value 0x00 is not - * available - */ -static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -1500, 300, 0); - -static const struct snd_kcontrol_new ak4671_snd_controls[] = { - /* Common playback gain controls */ - SOC_SINGLE_TLV("Line Output1 Playback Volume", - AK4671_OUTPUT_VOLUME_CONTROL, 0, 0x6, 0, out1_tlv), - SOC_SINGLE_TLV("Headphone Output2 Playback Volume", - AK4671_OUTPUT_VOLUME_CONTROL, 4, 0xd, 0, out2_tlv), - SOC_SINGLE_TLV("Line Output3 Playback Volume", - AK4671_LOUT3_POWER_MANAGERMENT, 6, 0x3, 0, out3_tlv), - - /* Common capture gain controls */ - SOC_DOUBLE_TLV("Mic Amp Capture Volume", - AK4671_MIC_AMP_GAIN, 0, 4, 0xf, 0, mic_amp_tlv), -}; - -/* event handlers */ -static int ak4671_out2_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT, - AK4671_MUTEN, AK4671_MUTEN); - break; - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT, - AK4671_MUTEN, 0); - break; - } - - return 0; -} - -/* Output Mixers */ -static const struct snd_kcontrol_new ak4671_lout1_mixer_controls[] = { - SOC_DAPM_SINGLE("DACL", AK4671_LOUT1_SIGNAL_SELECT, 0, 1, 0), - SOC_DAPM_SINGLE("LINL1", AK4671_LOUT1_SIGNAL_SELECT, 1, 1, 0), - SOC_DAPM_SINGLE("LINL2", AK4671_LOUT1_SIGNAL_SELECT, 2, 1, 0), - SOC_DAPM_SINGLE("LINL3", AK4671_LOUT1_SIGNAL_SELECT, 3, 1, 0), - SOC_DAPM_SINGLE("LINL4", AK4671_LOUT1_SIGNAL_SELECT, 4, 1, 0), - SOC_DAPM_SINGLE("LOOPL", AK4671_LOUT1_SIGNAL_SELECT, 5, 1, 0), -}; - -static const struct snd_kcontrol_new ak4671_rout1_mixer_controls[] = { - SOC_DAPM_SINGLE("DACR", AK4671_ROUT1_SIGNAL_SELECT, 0, 1, 0), - SOC_DAPM_SINGLE("RINR1", AK4671_ROUT1_SIGNAL_SELECT, 1, 1, 0), - SOC_DAPM_SINGLE("RINR2", AK4671_ROUT1_SIGNAL_SELECT, 2, 1, 0), - SOC_DAPM_SINGLE("RINR3", AK4671_ROUT1_SIGNAL_SELECT, 3, 1, 0), - SOC_DAPM_SINGLE("RINR4", AK4671_ROUT1_SIGNAL_SELECT, 4, 1, 0), - SOC_DAPM_SINGLE("LOOPR", AK4671_ROUT1_SIGNAL_SELECT, 5, 1, 0), -}; - -static const struct snd_kcontrol_new ak4671_lout2_mixer_controls[] = { - SOC_DAPM_SINGLE("DACHL", AK4671_LOUT2_SIGNAL_SELECT, 0, 1, 0), - SOC_DAPM_SINGLE("LINH1", AK4671_LOUT2_SIGNAL_SELECT, 1, 1, 0), - SOC_DAPM_SINGLE("LINH2", AK4671_LOUT2_SIGNAL_SELECT, 2, 1, 0), - SOC_DAPM_SINGLE("LINH3", AK4671_LOUT2_SIGNAL_SELECT, 3, 1, 0), - SOC_DAPM_SINGLE("LINH4", AK4671_LOUT2_SIGNAL_SELECT, 4, 1, 0), - SOC_DAPM_SINGLE("LOOPHL", AK4671_LOUT2_SIGNAL_SELECT, 5, 1, 0), -}; - -static const struct snd_kcontrol_new ak4671_rout2_mixer_controls[] = { - SOC_DAPM_SINGLE("DACHR", AK4671_ROUT2_SIGNAL_SELECT, 0, 1, 0), - SOC_DAPM_SINGLE("RINH1", AK4671_ROUT2_SIGNAL_SELECT, 1, 1, 0), - SOC_DAPM_SINGLE("RINH2", AK4671_ROUT2_SIGNAL_SELECT, 2, 1, 0), - SOC_DAPM_SINGLE("RINH3", AK4671_ROUT2_SIGNAL_SELECT, 3, 1, 0), - SOC_DAPM_SINGLE("RINH4", AK4671_ROUT2_SIGNAL_SELECT, 4, 1, 0), - SOC_DAPM_SINGLE("LOOPHR", AK4671_ROUT2_SIGNAL_SELECT, 5, 1, 0), -}; - -static const struct snd_kcontrol_new ak4671_lout3_mixer_controls[] = { - SOC_DAPM_SINGLE("DACSL", AK4671_LOUT3_SIGNAL_SELECT, 0, 1, 0), - SOC_DAPM_SINGLE("LINS1", AK4671_LOUT3_SIGNAL_SELECT, 1, 1, 0), - SOC_DAPM_SINGLE("LINS2", AK4671_LOUT3_SIGNAL_SELECT, 2, 1, 0), - SOC_DAPM_SINGLE("LINS3", AK4671_LOUT3_SIGNAL_SELECT, 3, 1, 0), - SOC_DAPM_SINGLE("LINS4", AK4671_LOUT3_SIGNAL_SELECT, 4, 1, 0), - SOC_DAPM_SINGLE("LOOPSL", AK4671_LOUT3_SIGNAL_SELECT, 5, 1, 0), -}; - -static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = { - SOC_DAPM_SINGLE("DACSR", AK4671_ROUT3_SIGNAL_SELECT, 0, 1, 0), - SOC_DAPM_SINGLE("RINS1", AK4671_ROUT3_SIGNAL_SELECT, 1, 1, 0), - SOC_DAPM_SINGLE("RINS2", AK4671_ROUT3_SIGNAL_SELECT, 2, 1, 0), - SOC_DAPM_SINGLE("RINS3", AK4671_ROUT3_SIGNAL_SELECT, 3, 1, 0), - SOC_DAPM_SINGLE("RINS4", AK4671_ROUT3_SIGNAL_SELECT, 4, 1, 0), - SOC_DAPM_SINGLE("LOOPSR", AK4671_ROUT3_SIGNAL_SELECT, 5, 1, 0), -}; - -/* Input MUXs */ -static const char *ak4671_lin_mux_texts[] = - {"LIN1", "LIN2", "LIN3", "LIN4"}; -static const struct soc_enum ak4671_lin_mux_enum = - SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0, - ARRAY_SIZE(ak4671_lin_mux_texts), - ak4671_lin_mux_texts); -static const struct snd_kcontrol_new ak4671_lin_mux_control = - SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum); - -static const char *ak4671_rin_mux_texts[] = - {"RIN1", "RIN2", "RIN3", "RIN4"}; -static const struct soc_enum ak4671_rin_mux_enum = - SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2, - ARRAY_SIZE(ak4671_rin_mux_texts), - ak4671_rin_mux_texts); -static const struct snd_kcontrol_new ak4671_rin_mux_control = - SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum); - -static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = { - /* Inputs */ - SND_SOC_DAPM_INPUT("LIN1"), - SND_SOC_DAPM_INPUT("RIN1"), - SND_SOC_DAPM_INPUT("LIN2"), - SND_SOC_DAPM_INPUT("RIN2"), - SND_SOC_DAPM_INPUT("LIN3"), - SND_SOC_DAPM_INPUT("RIN3"), - SND_SOC_DAPM_INPUT("LIN4"), - SND_SOC_DAPM_INPUT("RIN4"), - - /* Outputs */ - SND_SOC_DAPM_OUTPUT("LOUT1"), - SND_SOC_DAPM_OUTPUT("ROUT1"), - SND_SOC_DAPM_OUTPUT("LOUT2"), - SND_SOC_DAPM_OUTPUT("ROUT2"), - SND_SOC_DAPM_OUTPUT("LOUT3"), - SND_SOC_DAPM_OUTPUT("ROUT3"), - - /* DAC */ - SND_SOC_DAPM_DAC("DAC Left", "Left HiFi Playback", - AK4671_AD_DA_POWER_MANAGEMENT, 6, 0), - SND_SOC_DAPM_DAC("DAC Right", "Right HiFi Playback", - AK4671_AD_DA_POWER_MANAGEMENT, 7, 0), - - /* ADC */ - SND_SOC_DAPM_ADC("ADC Left", "Left HiFi Capture", - AK4671_AD_DA_POWER_MANAGEMENT, 4, 0), - SND_SOC_DAPM_ADC("ADC Right", "Right HiFi Capture", - AK4671_AD_DA_POWER_MANAGEMENT, 5, 0), - - /* PGA */ - SND_SOC_DAPM_PGA("LOUT2 Mix Amp", - AK4671_LOUT2_POWER_MANAGERMENT, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("ROUT2 Mix Amp", - AK4671_LOUT2_POWER_MANAGERMENT, 6, 0, NULL, 0), - - SND_SOC_DAPM_PGA("LIN1 Mixing Circuit", - AK4671_MIXING_POWER_MANAGEMENT1, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("RIN1 Mixing Circuit", - AK4671_MIXING_POWER_MANAGEMENT1, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("LIN2 Mixing Circuit", - AK4671_MIXING_POWER_MANAGEMENT1, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("RIN2 Mixing Circuit", - AK4671_MIXING_POWER_MANAGEMENT1, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("LIN3 Mixing Circuit", - AK4671_MIXING_POWER_MANAGEMENT1, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("RIN3 Mixing Circuit", - AK4671_MIXING_POWER_MANAGEMENT1, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("LIN4 Mixing Circuit", - AK4671_MIXING_POWER_MANAGEMENT1, 6, 0, NULL, 0), - SND_SOC_DAPM_PGA("RIN4 Mixing Circuit", - AK4671_MIXING_POWER_MANAGEMENT1, 7, 0, NULL, 0), - - /* Output Mixers */ - SND_SOC_DAPM_MIXER("LOUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 0, 0, - &ak4671_lout1_mixer_controls[0], - ARRAY_SIZE(ak4671_lout1_mixer_controls)), - SND_SOC_DAPM_MIXER("ROUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 1, 0, - &ak4671_rout1_mixer_controls[0], - ARRAY_SIZE(ak4671_rout1_mixer_controls)), - SND_SOC_DAPM_MIXER_E("LOUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT, - 0, 0, &ak4671_lout2_mixer_controls[0], - ARRAY_SIZE(ak4671_lout2_mixer_controls), - ak4671_out2_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_MIXER_E("ROUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT, - 1, 0, &ak4671_rout2_mixer_controls[0], - ARRAY_SIZE(ak4671_rout2_mixer_controls), - ak4671_out2_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_MIXER("LOUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 0, 0, - &ak4671_lout3_mixer_controls[0], - ARRAY_SIZE(ak4671_lout3_mixer_controls)), - SND_SOC_DAPM_MIXER("ROUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 1, 0, - &ak4671_rout3_mixer_controls[0], - ARRAY_SIZE(ak4671_rout3_mixer_controls)), - - /* Input MUXs */ - SND_SOC_DAPM_MUX("LIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 2, 0, - &ak4671_lin_mux_control), - SND_SOC_DAPM_MUX("RIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 3, 0, - &ak4671_rin_mux_control), - - /* Mic Power */ - SND_SOC_DAPM_MICBIAS("Mic Bias", AK4671_AD_DA_POWER_MANAGEMENT, 1, 0), - - /* Supply */ - SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_route ak4671_intercon[] = { - {"DAC Left", "NULL", "PMPLL"}, - {"DAC Right", "NULL", "PMPLL"}, - {"ADC Left", "NULL", "PMPLL"}, - {"ADC Right", "NULL", "PMPLL"}, - - /* Outputs */ - {"LOUT1", "NULL", "LOUT1 Mixer"}, - {"ROUT1", "NULL", "ROUT1 Mixer"}, - {"LOUT2", "NULL", "LOUT2 Mix Amp"}, - {"ROUT2", "NULL", "ROUT2 Mix Amp"}, - {"LOUT3", "NULL", "LOUT3 Mixer"}, - {"ROUT3", "NULL", "ROUT3 Mixer"}, - - {"LOUT1 Mixer", "DACL", "DAC Left"}, - {"ROUT1 Mixer", "DACR", "DAC Right"}, - {"LOUT2 Mixer", "DACHL", "DAC Left"}, - {"ROUT2 Mixer", "DACHR", "DAC Right"}, - {"LOUT2 Mix Amp", "NULL", "LOUT2 Mixer"}, - {"ROUT2 Mix Amp", "NULL", "ROUT2 Mixer"}, - {"LOUT3 Mixer", "DACSL", "DAC Left"}, - {"ROUT3 Mixer", "DACSR", "DAC Right"}, - - /* Inputs */ - {"LIN MUX", "LIN1", "LIN1"}, - {"LIN MUX", "LIN2", "LIN2"}, - {"LIN MUX", "LIN3", "LIN3"}, - {"LIN MUX", "LIN4", "LIN4"}, - - {"RIN MUX", "RIN1", "RIN1"}, - {"RIN MUX", "RIN2", "RIN2"}, - {"RIN MUX", "RIN3", "RIN3"}, - {"RIN MUX", "RIN4", "RIN4"}, - - {"LIN1", NULL, "Mic Bias"}, - {"RIN1", NULL, "Mic Bias"}, - {"LIN2", NULL, "Mic Bias"}, - {"RIN2", NULL, "Mic Bias"}, - - {"ADC Left", "NULL", "LIN MUX"}, - {"ADC Right", "NULL", "RIN MUX"}, - - /* Analog Loops */ - {"LIN1 Mixing Circuit", "NULL", "LIN1"}, - {"RIN1 Mixing Circuit", "NULL", "RIN1"}, - {"LIN2 Mixing Circuit", "NULL", "LIN2"}, - {"RIN2 Mixing Circuit", "NULL", "RIN2"}, - {"LIN3 Mixing Circuit", "NULL", "LIN3"}, - {"RIN3 Mixing Circuit", "NULL", "RIN3"}, - {"LIN4 Mixing Circuit", "NULL", "LIN4"}, - {"RIN4 Mixing Circuit", "NULL", "RIN4"}, - - {"LOUT1 Mixer", "LINL1", "LIN1 Mixing Circuit"}, - {"ROUT1 Mixer", "RINR1", "RIN1 Mixing Circuit"}, - {"LOUT2 Mixer", "LINH1", "LIN1 Mixing Circuit"}, - {"ROUT2 Mixer", "RINH1", "RIN1 Mixing Circuit"}, - {"LOUT3 Mixer", "LINS1", "LIN1 Mixing Circuit"}, - {"ROUT3 Mixer", "RINS1", "RIN1 Mixing Circuit"}, - - {"LOUT1 Mixer", "LINL2", "LIN2 Mixing Circuit"}, - {"ROUT1 Mixer", "RINR2", "RIN2 Mixing Circuit"}, - {"LOUT2 Mixer", "LINH2", "LIN2 Mixing Circuit"}, - {"ROUT2 Mixer", "RINH2", "RIN2 Mixing Circuit"}, - {"LOUT3 Mixer", "LINS2", "LIN2 Mixing Circuit"}, - {"ROUT3 Mixer", "RINS2", "RIN2 Mixing Circuit"}, - - {"LOUT1 Mixer", "LINL3", "LIN3 Mixing Circuit"}, - {"ROUT1 Mixer", "RINR3", "RIN3 Mixing Circuit"}, - {"LOUT2 Mixer", "LINH3", "LIN3 Mixing Circuit"}, - {"ROUT2 Mixer", "RINH3", "RIN3 Mixing Circuit"}, - {"LOUT3 Mixer", "LINS3", "LIN3 Mixing Circuit"}, - {"ROUT3 Mixer", "RINS3", "RIN3 Mixing Circuit"}, - - {"LOUT1 Mixer", "LINL4", "LIN4 Mixing Circuit"}, - {"ROUT1 Mixer", "RINR4", "RIN4 Mixing Circuit"}, - {"LOUT2 Mixer", "LINH4", "LIN4 Mixing Circuit"}, - {"ROUT2 Mixer", "RINH4", "RIN4 Mixing Circuit"}, - {"LOUT3 Mixer", "LINS4", "LIN4 Mixing Circuit"}, - {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"}, -}; - -static int ak4671_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - u8 fs; - - fs = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0); - fs &= ~AK4671_FS; - - switch (params_rate(params)) { - case 8000: - fs |= AK4671_FS_8KHZ; - break; - case 12000: - fs |= AK4671_FS_12KHZ; - break; - case 16000: - fs |= AK4671_FS_16KHZ; - break; - case 24000: - fs |= AK4671_FS_24KHZ; - break; - case 11025: - fs |= AK4671_FS_11_025KHZ; - break; - case 22050: - fs |= AK4671_FS_22_05KHZ; - break; - case 32000: - fs |= AK4671_FS_32KHZ; - break; - case 44100: - fs |= AK4671_FS_44_1KHZ; - break; - case 48000: - fs |= AK4671_FS_48KHZ; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, fs); - - return 0; -} - -static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - u8 pll; - - pll = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0); - pll &= ~AK4671_PLL; - - switch (freq) { - case 11289600: - pll |= AK4671_PLL_11_2896MHZ; - break; - case 12000000: - pll |= AK4671_PLL_12MHZ; - break; - case 12288000: - pll |= AK4671_PLL_12_288MHZ; - break; - case 13000000: - pll |= AK4671_PLL_13MHZ; - break; - case 13500000: - pll |= AK4671_PLL_13_5MHZ; - break; - case 19200000: - pll |= AK4671_PLL_19_2MHZ; - break; - case 24000000: - pll |= AK4671_PLL_24MHZ; - break; - case 26000000: - pll |= AK4671_PLL_26MHZ; - break; - case 27000000: - pll |= AK4671_PLL_27MHZ; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, pll); - - return 0; -} - -static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - u8 mode; - u8 format; - - /* set master/slave audio interface */ - mode = snd_soc_read(codec, AK4671_PLL_MODE_SELECT1); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - mode |= AK4671_M_S; - break; - case SND_SOC_DAIFMT_CBM_CFS: - mode &= ~(AK4671_M_S); - break; - default: - return -EINVAL; - } - - /* interface format */ - format = snd_soc_read(codec, AK4671_FORMAT_SELECT); - format &= ~AK4671_DIF; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - format |= AK4671_DIF_I2S_MODE; - break; - case SND_SOC_DAIFMT_LEFT_J: - format |= AK4671_DIF_MSB_MODE; - break; - case SND_SOC_DAIFMT_DSP_A: - format |= AK4671_DIF_DSP_MODE; - format |= AK4671_BCKP; - format |= AK4671_MSBS; - break; - default: - return -EINVAL; - } - - /* set mode and format */ - snd_soc_write(codec, AK4671_PLL_MODE_SELECT1, mode); - snd_soc_write(codec, AK4671_FORMAT_SELECT, format); - - return 0; -} - -static int ak4671_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - case SND_SOC_BIAS_STANDBY: - snd_soc_update_bits(codec, AK4671_AD_DA_POWER_MANAGEMENT, - AK4671_PMVCM, AK4671_PMVCM); - break; - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define AK4671_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000) - -#define AK4671_FORMATS SNDRV_PCM_FMTBIT_S16_LE - -static const struct snd_soc_dai_ops ak4671_dai_ops = { - .hw_params = ak4671_hw_params, - .set_sysclk = ak4671_set_dai_sysclk, - .set_fmt = ak4671_set_dai_fmt, -}; - -static struct snd_soc_dai_driver ak4671_dai = { - .name = "ak4671-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = AK4671_RATES, - .formats = AK4671_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = AK4671_RATES, - .formats = AK4671_FORMATS,}, - .ops = &ak4671_dai_ops, -}; - -static int ak4671_probe(struct snd_soc_codec *codec) -{ - struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - snd_soc_add_codec_controls(codec, ak4671_snd_controls, - ARRAY_SIZE(ak4671_snd_controls)); - - ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return ret; -} - -static int ak4671_remove(struct snd_soc_codec *codec) -{ - ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_ak4671 = { - .probe = ak4671_probe, - .remove = ak4671_remove, - .set_bias_level = ak4671_set_bias_level, - .reg_cache_size = AK4671_CACHEREGNUM, - .reg_word_size = sizeof(u8), - .reg_cache_default = ak4671_reg, - .dapm_widgets = ak4671_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ak4671_dapm_widgets), - .dapm_routes = ak4671_intercon, - .num_dapm_routes = ARRAY_SIZE(ak4671_intercon), -}; - -static int __devinit ak4671_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ak4671_priv *ak4671; - int ret; - - ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv), - GFP_KERNEL); - if (ak4671 == NULL) - return -ENOMEM; - - i2c_set_clientdata(client, ak4671); - ak4671->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&client->dev, - &soc_codec_dev_ak4671, &ak4671_dai, 1); - return ret; -} - -static __devexit int ak4671_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id ak4671_i2c_id[] = { - { "ak4671", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); - -static struct i2c_driver ak4671_i2c_driver = { - .driver = { - .name = "ak4671-codec", - .owner = THIS_MODULE, - }, - .probe = ak4671_i2c_probe, - .remove = __devexit_p(ak4671_i2c_remove), - .id_table = ak4671_i2c_id, -}; - -static int __init ak4671_modinit(void) -{ - return i2c_add_driver(&ak4671_i2c_driver); -} -module_init(ak4671_modinit); - -static void __exit ak4671_exit(void) -{ - i2c_del_driver(&ak4671_i2c_driver); -} -module_exit(ak4671_exit); - -MODULE_DESCRIPTION("ASoC AK4671 codec driver"); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ak4671.h b/ANDROID_3.4.5/sound/soc/codecs/ak4671.h deleted file mode 100644 index 61cb7ab7..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ak4671.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * ak4671.h -- audio driver for AK4671 - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * 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. - * - */ - -#ifndef _AK4671_H -#define _AK4671_H - -#define AK4671_AD_DA_POWER_MANAGEMENT 0x00 -#define AK4671_PLL_MODE_SELECT0 0x01 -#define AK4671_PLL_MODE_SELECT1 0x02 -#define AK4671_FORMAT_SELECT 0x03 -#define AK4671_MIC_SIGNAL_SELECT 0x04 -#define AK4671_MIC_AMP_GAIN 0x05 -#define AK4671_MIXING_POWER_MANAGEMENT0 0x06 -#define AK4671_MIXING_POWER_MANAGEMENT1 0x07 -#define AK4671_OUTPUT_VOLUME_CONTROL 0x08 -#define AK4671_LOUT1_SIGNAL_SELECT 0x09 -#define AK4671_ROUT1_SIGNAL_SELECT 0x0a -#define AK4671_LOUT2_SIGNAL_SELECT 0x0b -#define AK4671_ROUT2_SIGNAL_SELECT 0x0c -#define AK4671_LOUT3_SIGNAL_SELECT 0x0d -#define AK4671_ROUT3_SIGNAL_SELECT 0x0e -#define AK4671_LOUT1_POWER_MANAGERMENT 0x0f -#define AK4671_LOUT2_POWER_MANAGERMENT 0x10 -#define AK4671_LOUT3_POWER_MANAGERMENT 0x11 -#define AK4671_LCH_INPUT_VOLUME_CONTROL 0x12 -#define AK4671_RCH_INPUT_VOLUME_CONTROL 0x13 -#define AK4671_ALC_REFERENCE_SELECT 0x14 -#define AK4671_DIGITAL_MIXING_CONTROL 0x15 -#define AK4671_ALC_TIMER_SELECT 0x16 -#define AK4671_ALC_MODE_CONTROL 0x17 -#define AK4671_MODE_CONTROL1 0x18 -#define AK4671_MODE_CONTROL2 0x19 -#define AK4671_LCH_OUTPUT_VOLUME_CONTROL 0x1a -#define AK4671_RCH_OUTPUT_VOLUME_CONTROL 0x1b -#define AK4671_SIDETONE_A_CONTROL 0x1c -#define AK4671_DIGITAL_FILTER_SELECT 0x1d -#define AK4671_FIL3_COEFFICIENT0 0x1e -#define AK4671_FIL3_COEFFICIENT1 0x1f -#define AK4671_FIL3_COEFFICIENT2 0x20 -#define AK4671_FIL3_COEFFICIENT3 0x21 -#define AK4671_EQ_COEFFICIENT0 0x22 -#define AK4671_EQ_COEFFICIENT1 0x23 -#define AK4671_EQ_COEFFICIENT2 0x24 -#define AK4671_EQ_COEFFICIENT3 0x25 -#define AK4671_EQ_COEFFICIENT4 0x26 -#define AK4671_EQ_COEFFICIENT5 0x27 -#define AK4671_FIL1_COEFFICIENT0 0x28 -#define AK4671_FIL1_COEFFICIENT1 0x29 -#define AK4671_FIL1_COEFFICIENT2 0x2a -#define AK4671_FIL1_COEFFICIENT3 0x2b -#define AK4671_FIL2_COEFFICIENT0 0x2c -#define AK4671_FIL2_COEFFICIENT1 0x2d -#define AK4671_FIL2_COEFFICIENT2 0x2e -#define AK4671_FIL2_COEFFICIENT3 0x2f -#define AK4671_DIGITAL_FILTER_SELECT2 0x30 -#define AK4671_E1_COEFFICIENT0 0x32 -#define AK4671_E1_COEFFICIENT1 0x33 -#define AK4671_E1_COEFFICIENT2 0x34 -#define AK4671_E1_COEFFICIENT3 0x35 -#define AK4671_E1_COEFFICIENT4 0x36 -#define AK4671_E1_COEFFICIENT5 0x37 -#define AK4671_E2_COEFFICIENT0 0x38 -#define AK4671_E2_COEFFICIENT1 0x39 -#define AK4671_E2_COEFFICIENT2 0x3a -#define AK4671_E2_COEFFICIENT3 0x3b -#define AK4671_E2_COEFFICIENT4 0x3c -#define AK4671_E2_COEFFICIENT5 0x3d -#define AK4671_E3_COEFFICIENT0 0x3e -#define AK4671_E3_COEFFICIENT1 0x3f -#define AK4671_E3_COEFFICIENT2 0x40 -#define AK4671_E3_COEFFICIENT3 0x41 -#define AK4671_E3_COEFFICIENT4 0x42 -#define AK4671_E3_COEFFICIENT5 0x43 -#define AK4671_E4_COEFFICIENT0 0x44 -#define AK4671_E4_COEFFICIENT1 0x45 -#define AK4671_E4_COEFFICIENT2 0x46 -#define AK4671_E4_COEFFICIENT3 0x47 -#define AK4671_E4_COEFFICIENT4 0x48 -#define AK4671_E4_COEFFICIENT5 0x49 -#define AK4671_E5_COEFFICIENT0 0x4a -#define AK4671_E5_COEFFICIENT1 0x4b -#define AK4671_E5_COEFFICIENT2 0x4c -#define AK4671_E5_COEFFICIENT3 0x4d -#define AK4671_E5_COEFFICIENT4 0x4e -#define AK4671_E5_COEFFICIENT5 0x4f -#define AK4671_EQ_CONTROL_250HZ_100HZ 0x50 -#define AK4671_EQ_CONTROL_3500HZ_1KHZ 0x51 -#define AK4671_EQ_CONTRO_10KHZ 0x52 -#define AK4671_PCM_IF_CONTROL0 0x53 -#define AK4671_PCM_IF_CONTROL1 0x54 -#define AK4671_PCM_IF_CONTROL2 0x55 -#define AK4671_DIGITAL_VOLUME_B_CONTROL 0x56 -#define AK4671_DIGITAL_VOLUME_C_CONTROL 0x57 -#define AK4671_SIDETONE_VOLUME_CONTROL 0x58 -#define AK4671_DIGITAL_MIXING_CONTROL2 0x59 -#define AK4671_SAR_ADC_CONTROL 0x5a - -#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1) - -/* Bitfield Definitions */ - -/* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */ -#define AK4671_PMVCM 0x01 - -/* AK4671_PLL_MODE_SELECT0 (0x01) Fields */ -#define AK4671_PLL 0x0f -#define AK4671_PLL_11_2896MHZ (4 << 0) -#define AK4671_PLL_12_288MHZ (5 << 0) -#define AK4671_PLL_12MHZ (6 << 0) -#define AK4671_PLL_24MHZ (7 << 0) -#define AK4671_PLL_19_2MHZ (8 << 0) -#define AK4671_PLL_13_5MHZ (12 << 0) -#define AK4671_PLL_27MHZ (13 << 0) -#define AK4671_PLL_13MHZ (14 << 0) -#define AK4671_PLL_26MHZ (15 << 0) -#define AK4671_FS 0xf0 -#define AK4671_FS_8KHZ (0 << 4) -#define AK4671_FS_12KHZ (1 << 4) -#define AK4671_FS_16KHZ (2 << 4) -#define AK4671_FS_24KHZ (3 << 4) -#define AK4671_FS_11_025KHZ (5 << 4) -#define AK4671_FS_22_05KHZ (7 << 4) -#define AK4671_FS_32KHZ (10 << 4) -#define AK4671_FS_48KHZ (11 << 4) -#define AK4671_FS_44_1KHZ (15 << 4) - -/* AK4671_PLL_MODE_SELECT1 (0x02) Fields */ -#define AK4671_PMPLL 0x01 -#define AK4671_M_S 0x02 - -/* AK4671_FORMAT_SELECT (0x03) Fields */ -#define AK4671_DIF 0x03 -#define AK4671_DIF_DSP_MODE (0 << 0) -#define AK4671_DIF_MSB_MODE (2 << 0) -#define AK4671_DIF_I2S_MODE (3 << 0) -#define AK4671_BCKP 0x04 -#define AK4671_MSBS 0x08 -#define AK4671_SDOD 0x10 - -/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ -#define AK4671_MUTEN 0x04 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/alc5623.c b/ANDROID_3.4.5/sound/soc/codecs/alc5623.c deleted file mode 100644 index d47b62dd..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/alc5623.c +++ /dev/null @@ -1,1109 +0,0 @@ -/* - * alc5623.c -- alc562[123] ALSA Soc Audio driver - * - * Copyright 2008 Realtek Microelectronics - * Author: flove Ethan - * - * Copyright 2010 Arnaud Patard - * - * - * Based on WM8753.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "alc5623.h" - -static int caps_charge = 2000; -module_param(caps_charge, int, 0); -MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); - -/* codec private data */ -struct alc5623_priv { - enum snd_soc_control_type control_type; - u8 id; - unsigned int sysclk; - u16 reg_cache[ALC5623_VENDOR_ID2+2]; - unsigned int add_ctrl; - unsigned int jack_det_ctrl; -}; - -static void alc5623_fill_cache(struct snd_soc_codec *codec) -{ - int i, step = codec->driver->reg_cache_step; - u16 *cache = codec->reg_cache; - - /* not really efficient ... */ - codec->cache_bypass = 1; - for (i = 0 ; i < codec->driver->reg_cache_size ; i += step) - cache[i] = snd_soc_read(codec, i); - codec->cache_bypass = 0; -} - -static inline int alc5623_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, ALC5623_RESET, 0); -} - -static int amp_mixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - /* to power-on/off class-d amp generators/speaker */ - /* need to write to 'index-46h' register : */ - /* so write index num (here 0x46) to reg 0x6a */ - /* and then 0xffff/0 to reg 0x6c */ - snd_soc_write(w->codec, ALC5623_HID_CTRL_INDEX, 0x46); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0xFFFF); - break; - case SND_SOC_DAPM_POST_PMD: - snd_soc_write(w->codec, ALC5623_HID_CTRL_DATA, 0); - break; - } - - return 0; -} - -/* - * ALC5623 Controls - */ - -static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0); -static const unsigned int boost_tlv[] = { - TLV_DB_RANGE_HEAD(3), - 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0); - -static const struct snd_kcontrol_new alc5621_vol_snd_controls[] = { - SOC_DOUBLE_TLV("Speaker Playback Volume", - ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Speaker Playback Switch", - ALC5623_SPK_OUT_VOL, 15, 7, 1, 1), - SOC_DOUBLE_TLV("Headphone Playback Volume", - ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Headphone Playback Switch", - ALC5623_HP_OUT_VOL, 15, 7, 1, 1), -}; - -static const struct snd_kcontrol_new alc5622_vol_snd_controls[] = { - SOC_DOUBLE_TLV("Speaker Playback Volume", - ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Speaker Playback Switch", - ALC5623_SPK_OUT_VOL, 15, 7, 1, 1), - SOC_DOUBLE_TLV("Line Playback Volume", - ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Line Playback Switch", - ALC5623_HP_OUT_VOL, 15, 7, 1, 1), -}; - -static const struct snd_kcontrol_new alc5623_vol_snd_controls[] = { - SOC_DOUBLE_TLV("Line Playback Volume", - ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Line Playback Switch", - ALC5623_SPK_OUT_VOL, 15, 7, 1, 1), - SOC_DOUBLE_TLV("Headphone Playback Volume", - ALC5623_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Headphone Playback Switch", - ALC5623_HP_OUT_VOL, 15, 7, 1, 1), -}; - -static const struct snd_kcontrol_new alc5623_snd_controls[] = { - SOC_DOUBLE_TLV("Auxout Playback Volume", - ALC5623_MONO_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Auxout Playback Switch", - ALC5623_MONO_AUX_OUT_VOL, 15, 7, 1, 1), - SOC_DOUBLE_TLV("PCM Playback Volume", - ALC5623_STEREO_DAC_VOL, 8, 0, 31, 1, vol_tlv), - SOC_DOUBLE_TLV("AuxI Capture Volume", - ALC5623_AUXIN_VOL, 8, 0, 31, 1, vol_tlv), - SOC_DOUBLE_TLV("LineIn Capture Volume", - ALC5623_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv), - SOC_SINGLE_TLV("Mic1 Capture Volume", - ALC5623_MIC_VOL, 8, 31, 1, vol_tlv), - SOC_SINGLE_TLV("Mic2 Capture Volume", - ALC5623_MIC_VOL, 0, 31, 1, vol_tlv), - SOC_DOUBLE_TLV("Rec Capture Volume", - ALC5623_ADC_REC_GAIN, 7, 0, 31, 0, adc_rec_tlv), - SOC_SINGLE_TLV("Mic 1 Boost Volume", - ALC5623_MIC_CTRL, 10, 2, 0, boost_tlv), - SOC_SINGLE_TLV("Mic 2 Boost Volume", - ALC5623_MIC_CTRL, 8, 2, 0, boost_tlv), - SOC_SINGLE_TLV("Digital Boost Volume", - ALC5623_ADD_CTRL_REG, 4, 3, 0, dig_tlv), -}; - -/* - * DAPM Controls - */ -static const struct snd_kcontrol_new alc5623_hp_mixer_controls[] = { -SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5623_LINE_IN_VOL, 15, 1, 1), -SOC_DAPM_SINGLE("AUXI2HP Playback Switch", ALC5623_AUXIN_VOL, 15, 1, 1), -SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 15, 1, 1), -SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5623_MIC_ROUTING_CTRL, 7, 1, 1), -SOC_DAPM_SINGLE("DAC2HP Playback Switch", ALC5623_STEREO_DAC_VOL, 15, 1, 1), -}; - -static const struct snd_kcontrol_new alc5623_hpl_mixer_controls[] = { -SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5623_ADC_REC_GAIN, 15, 1, 1), -}; - -static const struct snd_kcontrol_new alc5623_hpr_mixer_controls[] = { -SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5623_ADC_REC_GAIN, 14, 1, 1), -}; - -static const struct snd_kcontrol_new alc5623_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5623_ADC_REC_GAIN, 13, 1, 1), -SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5623_ADC_REC_GAIN, 12, 1, 1), -SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5623_LINE_IN_VOL, 13, 1, 1), -SOC_DAPM_SINGLE("AUXI2MONO Playback Switch", ALC5623_AUXIN_VOL, 13, 1, 1), -SOC_DAPM_SINGLE("MIC12MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 13, 1, 1), -SOC_DAPM_SINGLE("MIC22MONO Playback Switch", ALC5623_MIC_ROUTING_CTRL, 5, 1, 1), -SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5623_STEREO_DAC_VOL, 13, 1, 1), -}; - -static const struct snd_kcontrol_new alc5623_speaker_mixer_controls[] = { -SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5623_LINE_IN_VOL, 14, 1, 1), -SOC_DAPM_SINGLE("AUXI2SPK Playback Switch", ALC5623_AUXIN_VOL, 14, 1, 1), -SOC_DAPM_SINGLE("MIC12SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 14, 1, 1), -SOC_DAPM_SINGLE("MIC22SPK Playback Switch", ALC5623_MIC_ROUTING_CTRL, 6, 1, 1), -SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5623_STEREO_DAC_VOL, 14, 1, 1), -}; - -/* Left Record Mixer */ -static const struct snd_kcontrol_new alc5623_captureL_mixer_controls[] = { -SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 14, 1, 1), -SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 13, 1, 1), -SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5623_ADC_REC_MIXER, 12, 1, 1), -SOC_DAPM_SINGLE("Left AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 11, 1, 1), -SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5623_ADC_REC_MIXER, 10, 1, 1), -SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 9, 1, 1), -SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 8, 1, 1), -}; - -/* Right Record Mixer */ -static const struct snd_kcontrol_new alc5623_captureR_mixer_controls[] = { -SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5623_ADC_REC_MIXER, 6, 1, 1), -SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5623_ADC_REC_MIXER, 5, 1, 1), -SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5623_ADC_REC_MIXER, 4, 1, 1), -SOC_DAPM_SINGLE("Right AuxI Capture Switch", ALC5623_ADC_REC_MIXER, 3, 1, 1), -SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5623_ADC_REC_MIXER, 2, 1, 1), -SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5623_ADC_REC_MIXER, 1, 1, 1), -SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5623_ADC_REC_MIXER, 0, 1, 1), -}; - -static const char *alc5623_spk_n_sour_sel[] = { - "RN/-R", "RP/+R", "LN/-R", "Vmid" }; -static const char *alc5623_hpl_out_input_sel[] = { - "Vmid", "HP Left Mix"}; -static const char *alc5623_hpr_out_input_sel[] = { - "Vmid", "HP Right Mix"}; -static const char *alc5623_spkout_input_sel[] = { - "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; -static const char *alc5623_aux_out_input_sel[] = { - "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; - -/* auxout output mux */ -static const struct soc_enum alc5623_aux_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 6, 4, alc5623_aux_out_input_sel); -static const struct snd_kcontrol_new alc5623_auxout_mux_controls = -SOC_DAPM_ENUM("Route", alc5623_aux_out_input_enum); - -/* speaker output mux */ -static const struct soc_enum alc5623_spkout_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 10, 4, alc5623_spkout_input_sel); -static const struct snd_kcontrol_new alc5623_spkout_mux_controls = -SOC_DAPM_ENUM("Route", alc5623_spkout_input_enum); - -/* headphone left output mux */ -static const struct soc_enum alc5623_hpl_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 9, 2, alc5623_hpl_out_input_sel); -static const struct snd_kcontrol_new alc5623_hpl_out_mux_controls = -SOC_DAPM_ENUM("Route", alc5623_hpl_out_input_enum); - -/* headphone right output mux */ -static const struct soc_enum alc5623_hpr_out_input_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 8, 2, alc5623_hpr_out_input_sel); -static const struct snd_kcontrol_new alc5623_hpr_out_mux_controls = -SOC_DAPM_ENUM("Route", alc5623_hpr_out_input_enum); - -/* speaker output N select */ -static const struct soc_enum alc5623_spk_n_sour_enum = -SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 14, 4, alc5623_spk_n_sour_sel); -static const struct snd_kcontrol_new alc5623_spkoutn_mux_controls = -SOC_DAPM_ENUM("Route", alc5623_spk_n_sour_enum); - -static const struct snd_soc_dapm_widget alc5623_dapm_widgets[] = { -/* Muxes */ -SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0, - &alc5623_auxout_mux_controls), -SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0, - &alc5623_spkout_mux_controls), -SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, - &alc5623_hpl_out_mux_controls), -SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, - &alc5623_hpr_out_mux_controls), -SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0, - &alc5623_spkoutn_mux_controls), - -/* output mixers */ -SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0, - &alc5623_hp_mixer_controls[0], - ARRAY_SIZE(alc5623_hp_mixer_controls)), -SND_SOC_DAPM_MIXER("HPR Mix", ALC5623_PWR_MANAG_ADD2, 4, 0, - &alc5623_hpr_mixer_controls[0], - ARRAY_SIZE(alc5623_hpr_mixer_controls)), -SND_SOC_DAPM_MIXER("HPL Mix", ALC5623_PWR_MANAG_ADD2, 5, 0, - &alc5623_hpl_mixer_controls[0], - ARRAY_SIZE(alc5623_hpl_mixer_controls)), -SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Mono Mix", ALC5623_PWR_MANAG_ADD2, 2, 0, - &alc5623_mono_mixer_controls[0], - ARRAY_SIZE(alc5623_mono_mixer_controls)), -SND_SOC_DAPM_MIXER("Speaker Mix", ALC5623_PWR_MANAG_ADD2, 3, 0, - &alc5623_speaker_mixer_controls[0], - ARRAY_SIZE(alc5623_speaker_mixer_controls)), - -/* input mixers */ -SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5623_PWR_MANAG_ADD2, 1, 0, - &alc5623_captureL_mixer_controls[0], - ARRAY_SIZE(alc5623_captureL_mixer_controls)), -SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5623_PWR_MANAG_ADD2, 0, 0, - &alc5623_captureR_mixer_controls[0], - ARRAY_SIZE(alc5623_captureR_mixer_controls)), - -SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", - ALC5623_PWR_MANAG_ADD2, 9, 0), -SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", - ALC5623_PWR_MANAG_ADD2, 8, 0), -SND_SOC_DAPM_MIXER("I2S Mix", ALC5623_PWR_MANAG_ADD1, 15, 0, NULL, 0), -SND_SOC_DAPM_MIXER("AuxI Mix", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", - ALC5623_PWR_MANAG_ADD2, 7, 0), -SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", - ALC5623_PWR_MANAG_ADD2, 6, 0), -SND_SOC_DAPM_PGA("Left Headphone", ALC5623_PWR_MANAG_ADD3, 10, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Headphone", ALC5623_PWR_MANAG_ADD3, 9, 0, NULL, 0), -SND_SOC_DAPM_PGA("SpeakerOut", ALC5623_PWR_MANAG_ADD3, 12, 0, NULL, 0), -SND_SOC_DAPM_PGA("Left AuxOut", ALC5623_PWR_MANAG_ADD3, 14, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right AuxOut", ALC5623_PWR_MANAG_ADD3, 13, 0, NULL, 0), -SND_SOC_DAPM_PGA("Left LineIn", ALC5623_PWR_MANAG_ADD3, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right LineIn", ALC5623_PWR_MANAG_ADD3, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("Left AuxI", ALC5623_PWR_MANAG_ADD3, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right AuxI", ALC5623_PWR_MANAG_ADD3, 4, 0, NULL, 0), -SND_SOC_DAPM_PGA("MIC1 PGA", ALC5623_PWR_MANAG_ADD3, 3, 0, NULL, 0), -SND_SOC_DAPM_PGA("MIC2 PGA", ALC5623_PWR_MANAG_ADD3, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5623_PWR_MANAG_ADD3, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5623_PWR_MANAG_ADD3, 0, 0, NULL, 0), -SND_SOC_DAPM_MICBIAS("Mic Bias1", ALC5623_PWR_MANAG_ADD1, 11, 0), - -SND_SOC_DAPM_OUTPUT("AUXOUTL"), -SND_SOC_DAPM_OUTPUT("AUXOUTR"), -SND_SOC_DAPM_OUTPUT("HPL"), -SND_SOC_DAPM_OUTPUT("HPR"), -SND_SOC_DAPM_OUTPUT("SPKOUT"), -SND_SOC_DAPM_OUTPUT("SPKOUTN"), -SND_SOC_DAPM_INPUT("LINEINL"), -SND_SOC_DAPM_INPUT("LINEINR"), -SND_SOC_DAPM_INPUT("AUXINL"), -SND_SOC_DAPM_INPUT("AUXINR"), -SND_SOC_DAPM_INPUT("MIC1"), -SND_SOC_DAPM_INPUT("MIC2"), -SND_SOC_DAPM_VMID("Vmid"), -}; - -static const char *alc5623_amp_names[] = {"AB Amp", "D Amp"}; -static const struct soc_enum alc5623_amp_enum = - SOC_ENUM_SINGLE(ALC5623_OUTPUT_MIXER_CTRL, 13, 2, alc5623_amp_names); -static const struct snd_kcontrol_new alc5623_amp_mux_controls = - SOC_DAPM_ENUM("Route", alc5623_amp_enum); - -static const struct snd_soc_dapm_widget alc5623_dapm_amp_widgets[] = { -SND_SOC_DAPM_PGA_E("D Amp", ALC5623_PWR_MANAG_ADD2, 14, 0, NULL, 0, - amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_PGA("AB Amp", ALC5623_PWR_MANAG_ADD2, 15, 0, NULL, 0), -SND_SOC_DAPM_MUX("AB-D Amp Mux", SND_SOC_NOPM, 0, 0, - &alc5623_amp_mux_controls), -}; - -static const struct snd_soc_dapm_route intercon[] = { - /* virtual mixer - mixes left & right channels */ - {"I2S Mix", NULL, "Left DAC"}, - {"I2S Mix", NULL, "Right DAC"}, - {"Line Mix", NULL, "Right LineIn"}, - {"Line Mix", NULL, "Left LineIn"}, - {"AuxI Mix", NULL, "Left AuxI"}, - {"AuxI Mix", NULL, "Right AuxI"}, - {"AUXOUTL", NULL, "Left AuxOut"}, - {"AUXOUTR", NULL, "Right AuxOut"}, - - /* HP mixer */ - {"HPL Mix", "ADC2HP_L Playback Switch", "Left Capture Mix"}, - {"HPL Mix", NULL, "HP Mix"}, - {"HPR Mix", "ADC2HP_R Playback Switch", "Right Capture Mix"}, - {"HPR Mix", NULL, "HP Mix"}, - {"HP Mix", "LI2HP Playback Switch", "Line Mix"}, - {"HP Mix", "AUXI2HP Playback Switch", "AuxI Mix"}, - {"HP Mix", "MIC12HP Playback Switch", "MIC1 PGA"}, - {"HP Mix", "MIC22HP Playback Switch", "MIC2 PGA"}, - {"HP Mix", "DAC2HP Playback Switch", "I2S Mix"}, - - /* speaker mixer */ - {"Speaker Mix", "LI2SPK Playback Switch", "Line Mix"}, - {"Speaker Mix", "AUXI2SPK Playback Switch", "AuxI Mix"}, - {"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"}, - {"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"}, - {"Speaker Mix", "DAC2SPK Playback Switch", "I2S Mix"}, - - /* mono mixer */ - {"Mono Mix", "ADC2MONO_L Playback Switch", "Left Capture Mix"}, - {"Mono Mix", "ADC2MONO_R Playback Switch", "Right Capture Mix"}, - {"Mono Mix", "LI2MONO Playback Switch", "Line Mix"}, - {"Mono Mix", "AUXI2MONO Playback Switch", "AuxI Mix"}, - {"Mono Mix", "MIC12MONO Playback Switch", "MIC1 PGA"}, - {"Mono Mix", "MIC22MONO Playback Switch", "MIC2 PGA"}, - {"Mono Mix", "DAC2MONO Playback Switch", "I2S Mix"}, - - /* Left record mixer */ - {"Left Capture Mix", "LineInL Capture Switch", "LINEINL"}, - {"Left Capture Mix", "Left AuxI Capture Switch", "AUXINL"}, - {"Left Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"}, - {"Left Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"}, - {"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"}, - {"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"}, - {"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"}, - - /*Right record mixer */ - {"Right Capture Mix", "LineInR Capture Switch", "LINEINR"}, - {"Right Capture Mix", "Right AuxI Capture Switch", "AUXINR"}, - {"Right Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"}, - {"Right Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"}, - {"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"}, - {"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"}, - {"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"}, - - /* headphone left mux */ - {"Left Headphone Mux", "HP Left Mix", "HPL Mix"}, - {"Left Headphone Mux", "Vmid", "Vmid"}, - - /* headphone right mux */ - {"Right Headphone Mux", "HP Right Mix", "HPR Mix"}, - {"Right Headphone Mux", "Vmid", "Vmid"}, - - /* speaker out mux */ - {"SpeakerOut Mux", "Vmid", "Vmid"}, - {"SpeakerOut Mux", "HPOut Mix", "HPOut Mix"}, - {"SpeakerOut Mux", "Speaker Mix", "Speaker Mix"}, - {"SpeakerOut Mux", "Mono Mix", "Mono Mix"}, - - /* Mono/Aux Out mux */ - {"AuxOut Mux", "Vmid", "Vmid"}, - {"AuxOut Mux", "HPOut Mix", "HPOut Mix"}, - {"AuxOut Mux", "Speaker Mix", "Speaker Mix"}, - {"AuxOut Mux", "Mono Mix", "Mono Mix"}, - - /* output pga */ - {"HPL", NULL, "Left Headphone"}, - {"Left Headphone", NULL, "Left Headphone Mux"}, - {"HPR", NULL, "Right Headphone"}, - {"Right Headphone", NULL, "Right Headphone Mux"}, - {"Left AuxOut", NULL, "AuxOut Mux"}, - {"Right AuxOut", NULL, "AuxOut Mux"}, - - /* input pga */ - {"Left LineIn", NULL, "LINEINL"}, - {"Right LineIn", NULL, "LINEINR"}, - {"Left AuxI", NULL, "AUXINL"}, - {"Right AuxI", NULL, "AUXINR"}, - {"MIC1 Pre Amp", NULL, "MIC1"}, - {"MIC2 Pre Amp", NULL, "MIC2"}, - {"MIC1 PGA", NULL, "MIC1 Pre Amp"}, - {"MIC2 PGA", NULL, "MIC2 Pre Amp"}, - - /* left ADC */ - {"Left ADC", NULL, "Left Capture Mix"}, - - /* right ADC */ - {"Right ADC", NULL, "Right Capture Mix"}, - - {"SpeakerOut N Mux", "RN/-R", "SpeakerOut"}, - {"SpeakerOut N Mux", "RP/+R", "SpeakerOut"}, - {"SpeakerOut N Mux", "LN/-R", "SpeakerOut"}, - {"SpeakerOut N Mux", "Vmid", "Vmid"}, - - {"SPKOUT", NULL, "SpeakerOut"}, - {"SPKOUTN", NULL, "SpeakerOut N Mux"}, -}; - -static const struct snd_soc_dapm_route intercon_spk[] = { - {"SpeakerOut", NULL, "SpeakerOut Mux"}, -}; - -static const struct snd_soc_dapm_route intercon_amp_spk[] = { - {"AB Amp", NULL, "SpeakerOut Mux"}, - {"D Amp", NULL, "SpeakerOut Mux"}, - {"AB-D Amp Mux", "AB Amp", "AB Amp"}, - {"AB-D Amp Mux", "D Amp", "D Amp"}, - {"SpeakerOut", NULL, "AB-D Amp Mux"}, -}; - -/* PLL divisors */ -struct _pll_div { - u32 pll_in; - u32 pll_out; - u16 regvalue; -}; - -/* Note : pll code from original alc5623 driver. Not sure of how good it is */ -/* useful only for master mode */ -static const struct _pll_div codec_master_pll_div[] = { - - { 2048000, 8192000, 0x0ea0}, - { 3686400, 8192000, 0x4e27}, - { 12000000, 8192000, 0x456b}, - { 13000000, 8192000, 0x495f}, - { 13100000, 8192000, 0x0320}, - { 2048000, 11289600, 0xf637}, - { 3686400, 11289600, 0x2f22}, - { 12000000, 11289600, 0x3e2f}, - { 13000000, 11289600, 0x4d5b}, - { 13100000, 11289600, 0x363b}, - { 2048000, 16384000, 0x1ea0}, - { 3686400, 16384000, 0x9e27}, - { 12000000, 16384000, 0x452b}, - { 13000000, 16384000, 0x542f}, - { 13100000, 16384000, 0x03a0}, - { 2048000, 16934400, 0xe625}, - { 3686400, 16934400, 0x9126}, - { 12000000, 16934400, 0x4d2c}, - { 13000000, 16934400, 0x742f}, - { 13100000, 16934400, 0x3c27}, - { 2048000, 22579200, 0x2aa0}, - { 3686400, 22579200, 0x2f20}, - { 12000000, 22579200, 0x7e2f}, - { 13000000, 22579200, 0x742f}, - { 13100000, 22579200, 0x3c27}, - { 2048000, 24576000, 0x2ea0}, - { 3686400, 24576000, 0xee27}, - { 12000000, 24576000, 0x2915}, - { 13000000, 24576000, 0x772e}, - { 13100000, 24576000, 0x0d20}, -}; - -static const struct _pll_div codec_slave_pll_div[] = { - - { 1024000, 16384000, 0x3ea0}, - { 1411200, 22579200, 0x3ea0}, - { 1536000, 24576000, 0x3ea0}, - { 2048000, 16384000, 0x1ea0}, - { 2822400, 22579200, 0x1ea0}, - { 3072000, 24576000, 0x1ea0}, - -}; - -static int alc5623_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - int i; - struct snd_soc_codec *codec = codec_dai->codec; - int gbl_clk = 0, pll_div = 0; - u16 reg; - - if (pll_id < ALC5623_PLL_FR_MCLK || pll_id > ALC5623_PLL_FR_BCK) - return -ENODEV; - - /* Disable PLL power */ - snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD2, - ALC5623_PWR_ADD2_PLL, - 0); - - /* pll is not used in slave mode */ - reg = snd_soc_read(codec, ALC5623_DAI_CONTROL); - if (reg & ALC5623_DAI_SDP_SLAVE_MODE) - return 0; - - if (!freq_in || !freq_out) - return 0; - - switch (pll_id) { - case ALC5623_PLL_FR_MCLK: - for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) { - if (codec_master_pll_div[i].pll_in == freq_in - && codec_master_pll_div[i].pll_out == freq_out) { - /* PLL source from MCLK */ - pll_div = codec_master_pll_div[i].regvalue; - break; - } - } - break; - case ALC5623_PLL_FR_BCK: - for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) { - if (codec_slave_pll_div[i].pll_in == freq_in - && codec_slave_pll_div[i].pll_out == freq_out) { - /* PLL source from Bitclk */ - gbl_clk = ALC5623_GBL_CLK_PLL_SOUR_SEL_BITCLK; - pll_div = codec_slave_pll_div[i].regvalue; - break; - } - } - break; - default: - return -EINVAL; - } - - if (!pll_div) - return -EINVAL; - - snd_soc_write(codec, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk); - snd_soc_write(codec, ALC5623_PLL_CTRL, pll_div); - snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD2, - ALC5623_PWR_ADD2_PLL, - ALC5623_PWR_ADD2_PLL); - gbl_clk |= ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL; - snd_soc_write(codec, ALC5623_GLOBAL_CLK_CTRL_REG, gbl_clk); - - return 0; -} - -struct _coeff_div { - u16 fs; - u16 regvalue; -}; - -/* codec hifi mclk (after PLL) clock divider coefficients */ -/* values inspired from column BCLK=32Fs of Appendix A table */ -static const struct _coeff_div coeff_div[] = { - {256*8, 0x3a69}, - {384*8, 0x3c6b}, - {256*4, 0x2a69}, - {384*4, 0x2c6b}, - {256*2, 0x1a69}, - {384*2, 0x1c6b}, - {256*1, 0x0a69}, - {384*1, 0x0c6b}, -}; - -static int get_coeff(struct snd_soc_codec *codec, int rate) -{ - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].fs * rate == alc5623->sysclk) - return i; - } - return -EINVAL; -} - -/* - * Clock after PLL and dividers - */ -static int alc5623_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 8192000: - case 11289600: - case 12288000: - case 16384000: - case 16934400: - case 18432000: - case 22579200: - case 24576000: - alc5623->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int alc5623_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface = ALC5623_DAI_SDP_MASTER_MODE; - break; - case SND_SOC_DAIFMT_CBS_CFS: - iface = ALC5623_DAI_SDP_SLAVE_MODE; - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= ALC5623_DAI_I2S_DF_I2S; - break; - case SND_SOC_DAIFMT_RIGHT_J: - iface |= ALC5623_DAI_I2S_DF_RIGHT; - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= ALC5623_DAI_I2S_DF_LEFT; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= ALC5623_DAI_I2S_DF_PCM; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= ALC5623_DAI_I2S_DF_PCM | ALC5623_DAI_I2S_PCM_MODE; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL; - break; - case SND_SOC_DAIFMT_NB_IF: - break; - default: - return -EINVAL; - } - - return snd_soc_write(codec, ALC5623_DAI_CONTROL, iface); -} - -static int alc5623_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); - int coeff, rate; - u16 iface; - - iface = snd_soc_read(codec, ALC5623_DAI_CONTROL); - iface &= ~ALC5623_DAI_I2S_DL_MASK; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - iface |= ALC5623_DAI_I2S_DL_16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= ALC5623_DAI_I2S_DL_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= ALC5623_DAI_I2S_DL_24; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= ALC5623_DAI_I2S_DL_32; - break; - default: - return -EINVAL; - } - - /* set iface & srate */ - snd_soc_write(codec, ALC5623_DAI_CONTROL, iface); - rate = params_rate(params); - coeff = get_coeff(codec, rate); - if (coeff < 0) - return -EINVAL; - - coeff = coeff_div[coeff].regvalue; - dev_dbg(codec->dev, "%s: sysclk=%d,rate=%d,coeff=0x%04x\n", - __func__, alc5623->sysclk, rate, coeff); - snd_soc_write(codec, ALC5623_STEREO_AD_DA_CLK_CTRL, coeff); - - return 0; -} - -static int alc5623_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 hp_mute = ALC5623_MISC_M_DAC_L_INPUT | ALC5623_MISC_M_DAC_R_INPUT; - u16 mute_reg = snd_soc_read(codec, ALC5623_MISC_CTRL) & ~hp_mute; - - if (mute) - mute_reg |= hp_mute; - - return snd_soc_write(codec, ALC5623_MISC_CTRL, mute_reg); -} - -#define ALC5623_ADD2_POWER_EN (ALC5623_PWR_ADD2_VREF \ - | ALC5623_PWR_ADD2_DAC_REF_CIR) - -#define ALC5623_ADD3_POWER_EN (ALC5623_PWR_ADD3_MAIN_BIAS \ - | ALC5623_PWR_ADD3_MIC1_BOOST_AD) - -#define ALC5623_ADD1_POWER_EN \ - (ALC5623_PWR_ADD1_SHORT_CURR_DET_EN | ALC5623_PWR_ADD1_SOFTGEN_EN \ - | ALC5623_PWR_ADD1_DEPOP_BUF_HP | ALC5623_PWR_ADD1_HP_OUT_AMP \ - | ALC5623_PWR_ADD1_HP_OUT_ENH_AMP) - -#define ALC5623_ADD1_POWER_EN_5622 \ - (ALC5623_PWR_ADD1_SHORT_CURR_DET_EN \ - | ALC5623_PWR_ADD1_HP_OUT_AMP) - -static void enable_power_depop(struct snd_soc_codec *codec) -{ - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); - - snd_soc_update_bits(codec, ALC5623_PWR_MANAG_ADD1, - ALC5623_PWR_ADD1_SOFTGEN_EN, - ALC5623_PWR_ADD1_SOFTGEN_EN); - - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, ALC5623_ADD3_POWER_EN); - - snd_soc_update_bits(codec, ALC5623_MISC_CTRL, - ALC5623_MISC_HP_DEPOP_MODE2_EN, - ALC5623_MISC_HP_DEPOP_MODE2_EN); - - msleep(500); - - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, ALC5623_ADD2_POWER_EN); - - /* avoid writing '1' into 5622 reserved bits */ - if (alc5623->id == 0x22) - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, - ALC5623_ADD1_POWER_EN_5622); - else - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, - ALC5623_ADD1_POWER_EN); - - /* disable HP Depop2 */ - snd_soc_update_bits(codec, ALC5623_MISC_CTRL, - ALC5623_MISC_HP_DEPOP_MODE2_EN, - 0); - -} - -static int alc5623_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - enable_power_depop(codec); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - /* everything off except vref/vmid, */ - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, - ALC5623_PWR_ADD2_VREF); - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, - ALC5623_PWR_ADD3_MAIN_BIAS); - break; - case SND_SOC_BIAS_OFF: - /* everything off, dac mute, inactive */ - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD2, 0); - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD3, 0); - snd_soc_write(codec, ALC5623_PWR_MANAG_ADD1, 0); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define ALC5623_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \ - | SNDRV_PCM_FMTBIT_S24_LE \ - | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops alc5623_dai_ops = { - .hw_params = alc5623_pcm_hw_params, - .digital_mute = alc5623_mute, - .set_fmt = alc5623_set_dai_fmt, - .set_sysclk = alc5623_set_dai_sysclk, - .set_pll = alc5623_set_dai_pll, -}; - -static struct snd_soc_dai_driver alc5623_dai = { - .name = "alc5623-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rate_min = 8000, - .rate_max = 48000, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ALC5623_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rate_min = 8000, - .rate_max = 48000, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ALC5623_FORMATS,}, - - .ops = &alc5623_dai_ops, -}; - -static int alc5623_suspend(struct snd_soc_codec *codec) -{ - alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int alc5623_resume(struct snd_soc_codec *codec) -{ - int i, step = codec->driver->reg_cache_step; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) - snd_soc_write(codec, i, cache[i]); - - alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* charge alc5623 caps */ - if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { - alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - codec->dapm.bias_level = SND_SOC_BIAS_ON; - alc5623_set_bias_level(codec, codec->dapm.bias_level); - } - - return 0; -} - -static int alc5623_probe(struct snd_soc_codec *codec) -{ - struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - alc5623_reset(codec); - alc5623_fill_cache(codec); - - /* power on device */ - alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - if (alc5623->add_ctrl) { - snd_soc_write(codec, ALC5623_ADD_CTRL_REG, - alc5623->add_ctrl); - } - - if (alc5623->jack_det_ctrl) { - snd_soc_write(codec, ALC5623_JACK_DET_CTRL, - alc5623->jack_det_ctrl); - } - - switch (alc5623->id) { - case 0x21: - snd_soc_add_codec_controls(codec, alc5621_vol_snd_controls, - ARRAY_SIZE(alc5621_vol_snd_controls)); - break; - case 0x22: - snd_soc_add_codec_controls(codec, alc5622_vol_snd_controls, - ARRAY_SIZE(alc5622_vol_snd_controls)); - break; - case 0x23: - snd_soc_add_codec_controls(codec, alc5623_vol_snd_controls, - ARRAY_SIZE(alc5623_vol_snd_controls)); - break; - default: - return -EINVAL; - } - - snd_soc_add_codec_controls(codec, alc5623_snd_controls, - ARRAY_SIZE(alc5623_snd_controls)); - - snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets, - ARRAY_SIZE(alc5623_dapm_widgets)); - - /* set up audio path interconnects */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - switch (alc5623->id) { - case 0x21: - case 0x22: - snd_soc_dapm_new_controls(dapm, alc5623_dapm_amp_widgets, - ARRAY_SIZE(alc5623_dapm_amp_widgets)); - snd_soc_dapm_add_routes(dapm, intercon_amp_spk, - ARRAY_SIZE(intercon_amp_spk)); - break; - case 0x23: - snd_soc_dapm_add_routes(dapm, intercon_spk, - ARRAY_SIZE(intercon_spk)); - break; - default: - return -EINVAL; - } - - return ret; -} - -/* power down chip */ -static int alc5623_remove(struct snd_soc_codec *codec) -{ - alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_device_alc5623 = { - .probe = alc5623_probe, - .remove = alc5623_remove, - .suspend = alc5623_suspend, - .resume = alc5623_resume, - .set_bias_level = alc5623_set_bias_level, - .reg_cache_size = ALC5623_VENDOR_ID2+2, - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, -}; - -/* - * ALC5623 2 wire address is determined by A1 pin - * state during powerup. - * low = 0x1a - * high = 0x1b - */ -static __devinit int alc5623_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct alc5623_platform_data *pdata; - struct alc5623_priv *alc5623; - int ret, vid1, vid2; - - vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); - if (vid1 < 0) { - dev_err(&client->dev, "failed to read I2C\n"); - return -EIO; - } - vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); - - vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); - if (vid2 < 0) { - dev_err(&client->dev, "failed to read I2C\n"); - return -EIO; - } - - if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { - dev_err(&client->dev, "unknown or wrong codec\n"); - dev_err(&client->dev, "Expected %x:%lx, got %x:%x\n", - 0x10ec, id->driver_data, - vid1, vid2); - return -ENODEV; - } - - dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); - - alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv), - GFP_KERNEL); - if (alc5623 == NULL) - return -ENOMEM; - - pdata = client->dev.platform_data; - if (pdata) { - alc5623->add_ctrl = pdata->add_ctrl; - alc5623->jack_det_ctrl = pdata->jack_det_ctrl; - } - - alc5623->id = vid2; - switch (alc5623->id) { - case 0x21: - alc5623_dai.name = "alc5621-hifi"; - break; - case 0x22: - alc5623_dai.name = "alc5622-hifi"; - break; - case 0x23: - alc5623_dai.name = "alc5623-hifi"; - break; - default: - return -EINVAL; - } - - i2c_set_clientdata(client, alc5623); - alc5623->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&client->dev, - &soc_codec_device_alc5623, &alc5623_dai, 1); - if (ret != 0) - dev_err(&client->dev, "Failed to register codec: %d\n", ret); - - return ret; -} - -static __devexit int alc5623_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id alc5623_i2c_table[] = { - {"alc5621", 0x21}, - {"alc5622", 0x22}, - {"alc5623", 0x23}, - {} -}; -MODULE_DEVICE_TABLE(i2c, alc5623_i2c_table); - -/* i2c codec control layer */ -static struct i2c_driver alc5623_i2c_driver = { - .driver = { - .name = "alc562x-codec", - .owner = THIS_MODULE, - }, - .probe = alc5623_i2c_probe, - .remove = __devexit_p(alc5623_i2c_remove), - .id_table = alc5623_i2c_table, -}; - -static int __init alc5623_modinit(void) -{ - int ret; - - ret = i2c_add_driver(&alc5623_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "%s: can't add i2c driver", __func__); - return ret; - } - - return ret; -} -module_init(alc5623_modinit); - -static void __exit alc5623_modexit(void) -{ - i2c_del_driver(&alc5623_i2c_driver); -} -module_exit(alc5623_modexit); - -MODULE_DESCRIPTION("ASoC alc5621/2/3 driver"); -MODULE_AUTHOR("Arnaud Patard "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/alc5623.h b/ANDROID_3.4.5/sound/soc/codecs/alc5623.h deleted file mode 100644 index f3d68260..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/alc5623.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * alc5623.h -- alc562[123] ALSA Soc Audio driver - * - * Copyright 2008 Realtek Microelectronics - * Copyright 2010 Arnaud Patard - * - * Author: flove - * Arnaud Patard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _ALC5623_H -#define _ALC5623_H - -#define ALC5623_RESET 0x00 -/* 5621 5622 5623 */ -/* speaker output vol 2 2 */ -/* line output vol 4 2 */ -/* HP output vol 4 0 4 */ -#define ALC5623_SPK_OUT_VOL 0x02 -#define ALC5623_HP_OUT_VOL 0x04 -#define ALC5623_MONO_AUX_OUT_VOL 0x06 -#define ALC5623_AUXIN_VOL 0x08 -#define ALC5623_LINE_IN_VOL 0x0A -#define ALC5623_STEREO_DAC_VOL 0x0C -#define ALC5623_MIC_VOL 0x0E -#define ALC5623_MIC_ROUTING_CTRL 0x10 -#define ALC5623_ADC_REC_GAIN 0x12 -#define ALC5623_ADC_REC_MIXER 0x14 -#define ALC5623_SOFT_VOL_CTRL_TIME 0x16 -/* ALC5623_OUTPUT_MIXER_CTRL : */ -/* same remark as for reg 2 line vs speaker */ -#define ALC5623_OUTPUT_MIXER_CTRL 0x1C -#define ALC5623_MIC_CTRL 0x22 - -#define ALC5623_DAI_CONTROL 0x34 -#define ALC5623_DAI_SDP_MASTER_MODE (0 << 15) -#define ALC5623_DAI_SDP_SLAVE_MODE (1 << 15) -#define ALC5623_DAI_I2S_PCM_MODE (1 << 14) -#define ALC5623_DAI_MAIN_I2S_BCLK_POL_CTRL (1 << 7) -#define ALC5623_DAI_ADC_DATA_L_R_SWAP (1 << 5) -#define ALC5623_DAI_DAC_DATA_L_R_SWAP (1 << 4) -#define ALC5623_DAI_I2S_DL_MASK (3 << 2) -#define ALC5623_DAI_I2S_DL_32 (3 << 2) -#define ALC5623_DAI_I2S_DL_24 (2 << 2) -#define ALC5623_DAI_I2S_DL_20 (1 << 2) -#define ALC5623_DAI_I2S_DL_16 (0 << 2) -#define ALC5623_DAI_I2S_DF_PCM (3 << 0) -#define ALC5623_DAI_I2S_DF_LEFT (2 << 0) -#define ALC5623_DAI_I2S_DF_RIGHT (1 << 0) -#define ALC5623_DAI_I2S_DF_I2S (0 << 0) - -#define ALC5623_STEREO_AD_DA_CLK_CTRL 0x36 -#define ALC5623_COMPANDING_CTRL 0x38 - -#define ALC5623_PWR_MANAG_ADD1 0x3A -#define ALC5623_PWR_ADD1_MAIN_I2S_EN (1 << 15) -#define ALC5623_PWR_ADD1_ZC_DET_PD_EN (1 << 14) -#define ALC5623_PWR_ADD1_MIC1_BIAS_EN (1 << 11) -#define ALC5623_PWR_ADD1_SHORT_CURR_DET_EN (1 << 10) -#define ALC5623_PWR_ADD1_SOFTGEN_EN (1 << 8) /* rsvd on 5622 */ -#define ALC5623_PWR_ADD1_DEPOP_BUF_HP (1 << 6) /* rsvd on 5622 */ -#define ALC5623_PWR_ADD1_HP_OUT_AMP (1 << 5) -#define ALC5623_PWR_ADD1_HP_OUT_ENH_AMP (1 << 4) /* rsvd on 5622 */ -#define ALC5623_PWR_ADD1_DEPOP_BUF_AUX (1 << 2) -#define ALC5623_PWR_ADD1_AUX_OUT_AMP (1 << 1) -#define ALC5623_PWR_ADD1_AUX_OUT_ENH_AMP (1 << 0) /* rsvd on 5622 */ - -#define ALC5623_PWR_MANAG_ADD2 0x3C -#define ALC5623_PWR_ADD2_LINEOUT (1 << 15) /* rt5623 */ -#define ALC5623_PWR_ADD2_CLASS_AB (1 << 15) /* rt5621 */ -#define ALC5623_PWR_ADD2_CLASS_D (1 << 14) /* rt5621 */ -#define ALC5623_PWR_ADD2_VREF (1 << 13) -#define ALC5623_PWR_ADD2_PLL (1 << 12) -#define ALC5623_PWR_ADD2_DAC_REF_CIR (1 << 10) -#define ALC5623_PWR_ADD2_L_DAC_CLK (1 << 9) -#define ALC5623_PWR_ADD2_R_DAC_CLK (1 << 8) -#define ALC5623_PWR_ADD2_L_ADC_CLK_GAIN (1 << 7) -#define ALC5623_PWR_ADD2_R_ADC_CLK_GAIN (1 << 6) -#define ALC5623_PWR_ADD2_L_HP_MIXER (1 << 5) -#define ALC5623_PWR_ADD2_R_HP_MIXER (1 << 4) -#define ALC5623_PWR_ADD2_SPK_MIXER (1 << 3) -#define ALC5623_PWR_ADD2_MONO_MIXER (1 << 2) -#define ALC5623_PWR_ADD2_L_ADC_REC_MIXER (1 << 1) -#define ALC5623_PWR_ADD2_R_ADC_REC_MIXER (1 << 0) - -#define ALC5623_PWR_MANAG_ADD3 0x3E -#define ALC5623_PWR_ADD3_MAIN_BIAS (1 << 15) -#define ALC5623_PWR_ADD3_AUXOUT_L_VOL_AMP (1 << 14) -#define ALC5623_PWR_ADD3_AUXOUT_R_VOL_AMP (1 << 13) -#define ALC5623_PWR_ADD3_SPK_OUT (1 << 12) -#define ALC5623_PWR_ADD3_HP_L_OUT_VOL (1 << 10) -#define ALC5623_PWR_ADD3_HP_R_OUT_VOL (1 << 9) -#define ALC5623_PWR_ADD3_LINEIN_L_VOL (1 << 7) -#define ALC5623_PWR_ADD3_LINEIN_R_VOL (1 << 6) -#define ALC5623_PWR_ADD3_AUXIN_L_VOL (1 << 5) -#define ALC5623_PWR_ADD3_AUXIN_R_VOL (1 << 4) -#define ALC5623_PWR_ADD3_MIC1_FUN_CTRL (1 << 3) -#define ALC5623_PWR_ADD3_MIC2_FUN_CTRL (1 << 2) -#define ALC5623_PWR_ADD3_MIC1_BOOST_AD (1 << 1) -#define ALC5623_PWR_ADD3_MIC2_BOOST_AD (1 << 0) - -#define ALC5623_ADD_CTRL_REG 0x40 - -#define ALC5623_GLOBAL_CLK_CTRL_REG 0x42 -#define ALC5623_GBL_CLK_SYS_SOUR_SEL_PLL (1 << 15) -#define ALC5623_GBL_CLK_SYS_SOUR_SEL_MCLK (0 << 15) -#define ALC5623_GBL_CLK_PLL_SOUR_SEL_BITCLK (1 << 14) -#define ALC5623_GBL_CLK_PLL_SOUR_SEL_MCLK (0 << 14) -#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV8 (3 << 1) -#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV4 (2 << 1) -#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV2 (1 << 1) -#define ALC5623_GBL_CLK_PLL_DIV_RATIO_DIV1 (0 << 1) -#define ALC5623_GBL_CLK_PLL_PRE_DIV2 (1 << 0) -#define ALC5623_GBL_CLK_PLL_PRE_DIV1 (0 << 0) - -#define ALC5623_PLL_CTRL 0x44 -#define ALC5623_PLL_CTRL_N_VAL(n) (((n)&0xff) << 8) -#define ALC5623_PLL_CTRL_K_VAL(k) (((k)&0x7) << 4) -#define ALC5623_PLL_CTRL_M_VAL(m) ((m)&0xf) - -#define ALC5623_GPIO_OUTPUT_PIN_CTRL 0x4A -#define ALC5623_GPIO_PIN_CONFIG 0x4C -#define ALC5623_GPIO_PIN_POLARITY 0x4E -#define ALC5623_GPIO_PIN_STICKY 0x50 -#define ALC5623_GPIO_PIN_WAKEUP 0x52 -#define ALC5623_GPIO_PIN_STATUS 0x54 -#define ALC5623_GPIO_PIN_SHARING 0x56 -#define ALC5623_OVER_CURR_STATUS 0x58 -#define ALC5623_JACK_DET_CTRL 0x5A - -#define ALC5623_MISC_CTRL 0x5E -#define ALC5623_MISC_DISABLE_FAST_VREG (1 << 15) -#define ALC5623_MISC_SPK_CLASS_AB_OC_PD (1 << 13) /* 5621 */ -#define ALC5623_MISC_SPK_CLASS_AB_OC_DET (1 << 12) /* 5621 */ -#define ALC5623_MISC_HP_DEPOP_MODE3_EN (1 << 10) -#define ALC5623_MISC_HP_DEPOP_MODE2_EN (1 << 9) -#define ALC5623_MISC_HP_DEPOP_MODE1_EN (1 << 8) -#define ALC5623_MISC_AUXOUT_DEPOP_MODE3_EN (1 << 6) -#define ALC5623_MISC_AUXOUT_DEPOP_MODE2_EN (1 << 5) -#define ALC5623_MISC_AUXOUT_DEPOP_MODE1_EN (1 << 4) -#define ALC5623_MISC_M_DAC_L_INPUT (1 << 3) -#define ALC5623_MISC_M_DAC_R_INPUT (1 << 2) -#define ALC5623_MISC_IRQOUT_INV_CTRL (1 << 0) - -#define ALC5623_PSEDUEO_SPATIAL_CTRL 0x60 -#define ALC5623_EQ_CTRL 0x62 -#define ALC5623_EQ_MODE_ENABLE 0x66 -#define ALC5623_AVC_CTRL 0x68 -#define ALC5623_HID_CTRL_INDEX 0x6A -#define ALC5623_HID_CTRL_DATA 0x6C -#define ALC5623_VENDOR_ID1 0x7C -#define ALC5623_VENDOR_ID2 0x7E - -#define ALC5623_PLL_FR_MCLK 0 -#define ALC5623_PLL_FR_BCK 1 -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/alc5632.c b/ANDROID_3.4.5/sound/soc/codecs/alc5632.c deleted file mode 100644 index e2111e0c..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/alc5632.c +++ /dev/null @@ -1,1234 +0,0 @@ -/* -* alc5632.c -- ALC5632 ALSA SoC Audio Codec -* -* Copyright (C) 2011 The AC100 Kernel Team -* -* Authors: Leon Romanovsky -* Andrey Danin -* Ilya Petrov -* Marc Dietrich -* -* Based on alc5623.c by Arnaud Patard -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "alc5632.h" - -/* - * ALC5632 register cache - */ -static struct reg_default alc5632_reg_defaults[] = { - { 2, 0x8080 }, /* R2 - Speaker Output Volume */ - { 4, 0x8080 }, /* R4 - Headphone Output Volume */ - { 6, 0x8080 }, /* R6 - AUXOUT Volume */ - { 8, 0xC800 }, /* R8 - Phone Input */ - { 10, 0xE808 }, /* R10 - LINE_IN Volume */ - { 12, 0x1010 }, /* R12 - STEREO DAC Input Volume */ - { 14, 0x0808 }, /* R14 - MIC Input Volume */ - { 16, 0xEE0F }, /* R16 - Stereo DAC and MIC Routing Control */ - { 18, 0xCBCB }, /* R18 - ADC Record Gain */ - { 20, 0x7F7F }, /* R20 - ADC Record Mixer Control */ - { 24, 0xE010 }, /* R24 - Voice DAC Volume */ - { 28, 0x8008 }, /* R28 - Output Mixer Control */ - { 34, 0x0000 }, /* R34 - Microphone Control */ - { 36, 0x00C0 }, /* R36 - Codec Digital MIC/Digital Boost - Control */ - { 46, 0x0000 }, /* R46 - Stereo DAC/Voice DAC/Stereo ADC - Function Select */ - { 52, 0x8000 }, /* R52 - Main Serial Data Port Control - (Stereo I2S) */ - { 54, 0x0000 }, /* R54 - Extend Serial Data Port Control - (VoDAC_I2S/PCM) */ - { 58, 0x0000 }, /* R58 - Power Management Addition 1 */ - { 60, 0x0000 }, /* R60 - Power Management Addition 2 */ - { 62, 0x8000 }, /* R62 - Power Management Addition 3 */ - { 64, 0x0C0A }, /* R64 - General Purpose Control Register 1 */ - { 66, 0x0000 }, /* R66 - General Purpose Control Register 2 */ - { 68, 0x0000 }, /* R68 - PLL1 Control */ - { 70, 0x0000 }, /* R70 - PLL2 Control */ - { 76, 0xBE3E }, /* R76 - GPIO Pin Configuration */ - { 78, 0xBE3E }, /* R78 - GPIO Pin Polarity */ - { 80, 0x0000 }, /* R80 - GPIO Pin Sticky */ - { 82, 0x0000 }, /* R82 - GPIO Pin Wake Up */ - { 86, 0x0000 }, /* R86 - Pin Sharing */ - { 90, 0x0009 }, /* R90 - Soft Volume Control Setting */ - { 92, 0x0000 }, /* R92 - GPIO_Output Pin Control */ - { 94, 0x3000 }, /* R94 - MISC Control */ - { 96, 0x3075 }, /* R96 - Stereo DAC Clock Control_1 */ - { 98, 0x1010 }, /* R98 - Stereo DAC Clock Control_2 */ - { 100, 0x3110 }, /* R100 - VoDAC_PCM Clock Control_1 */ - { 104, 0x0553 }, /* R104 - Pseudo Stereo and Spatial Effect - Block Control */ - { 106, 0x0000 }, /* R106 - Private Register Address */ -}; - -/* codec private data */ -struct alc5632_priv { - struct regmap *regmap; - u8 id; - unsigned int sysclk; -}; - -static bool alc5632_volatile_register(struct device *dev, - unsigned int reg) -{ - switch (reg) { - case ALC5632_RESET: - case ALC5632_PWR_DOWN_CTRL_STATUS: - case ALC5632_GPIO_PIN_STATUS: - case ALC5632_OVER_CURR_STATUS: - case ALC5632_HID_CTRL_DATA: - case ALC5632_EQ_CTRL: - case ALC5632_VENDOR_ID1: - case ALC5632_VENDOR_ID2: - return true; - - default: - break; - } - - return false; -} - -static inline int alc5632_reset(struct regmap *map) -{ - return regmap_write(map, ALC5632_RESET, 0x59B4); -} - -static int amp_mixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - /* to power-on/off class-d amp generators/speaker */ - /* need to write to 'index-46h' register : */ - /* so write index num (here 0x46) to reg 0x6a */ - /* and then 0xffff/0 to reg 0x6c */ - snd_soc_write(w->codec, ALC5632_HID_CTRL_INDEX, 0x46); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0xFFFF); - break; - case SND_SOC_DAPM_POST_PMD: - snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0); - break; - } - - return 0; -} - -/* - * ALC5632 Controls - */ - -/* -34.5db min scale, 1.5db steps, no mute */ -static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0); -/* -46.5db min scale, 1.5db steps, no mute */ -static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0); -/* -16.5db min scale, 1.5db steps, no mute */ -static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0); -static const unsigned int boost_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), - 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0), -}; -/* 0db min scale, 6 db steps, no mute */ -static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0); -/* 0db min scalem 0.75db steps, no mute */ -static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 75, 0); - -static const struct snd_kcontrol_new alc5632_vol_snd_controls[] = { - /* left starts at bit 8, right at bit 0 */ - /* 31 steps (5 bit), -46.5db scale */ - SOC_DOUBLE_TLV("Speaker Playback Volume", - ALC5632_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv), - /* bit 15 mutes left, bit 7 right */ - SOC_DOUBLE("Speaker Playback Switch", - ALC5632_SPK_OUT_VOL, 15, 7, 1, 1), - SOC_DOUBLE_TLV("Headphone Playback Volume", - ALC5632_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Headphone Playback Switch", - ALC5632_HP_OUT_VOL, 15, 7, 1, 1), -}; - -static const struct snd_kcontrol_new alc5632_snd_controls[] = { - SOC_DOUBLE_TLV("Auxout Playback Volume", - ALC5632_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv), - SOC_DOUBLE("Auxout Playback Switch", - ALC5632_AUX_OUT_VOL, 15, 7, 1, 1), - SOC_SINGLE_TLV("Voice DAC Playback Volume", - ALC5632_VOICE_DAC_VOL, 0, 63, 0, vdac_tlv), - SOC_SINGLE("Voice DAC Playback Switch", - ALC5632_VOICE_DAC_VOL, 12, 1, 1), - SOC_SINGLE_TLV("Phone Playback Volume", - ALC5632_PHONE_IN_VOL, 8, 31, 1, vol_tlv), - SOC_DOUBLE_TLV("LineIn Playback Volume", - ALC5632_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv), - SOC_DOUBLE_TLV("Master Playback Volume", - ALC5632_STEREO_DAC_IN_VOL, 8, 0, 63, 1, vdac_tlv), - SOC_DOUBLE("Master Playback Switch", - ALC5632_STEREO_DAC_IN_VOL, 15, 7, 1, 1), - SOC_SINGLE_TLV("Mic1 Playback Volume", - ALC5632_MIC_VOL, 8, 31, 1, vol_tlv), - SOC_SINGLE_TLV("Mic2 Playback Volume", - ALC5632_MIC_VOL, 0, 31, 1, vol_tlv), - SOC_DOUBLE_TLV("Rec Capture Volume", - ALC5632_ADC_REC_GAIN, 8, 0, 31, 0, adc_rec_tlv), - SOC_SINGLE_TLV("Mic 1 Boost Volume", - ALC5632_MIC_CTRL, 10, 3, 0, boost_tlv), - SOC_SINGLE_TLV("Mic 2 Boost Volume", - ALC5632_MIC_CTRL, 8, 3, 0, boost_tlv), - SOC_SINGLE_TLV("DMIC Boost Capture Volume", - ALC5632_DIGI_BOOST_CTRL, 0, 7, 0, dig_tlv), - SOC_SINGLE("DMIC En Capture Switch", - ALC5632_DIGI_BOOST_CTRL, 15, 1, 0), - SOC_SINGLE("DMIC PreFilter Capture Switch", - ALC5632_DIGI_BOOST_CTRL, 12, 1, 0), -}; - -/* - * DAPM Controls - */ -static const struct snd_kcontrol_new alc5632_hp_mixer_controls[] = { -SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5632_LINE_IN_VOL, 15, 1, 1), -SOC_DAPM_SINGLE("PHONE2HP Playback Switch", ALC5632_PHONE_IN_VOL, 15, 1, 1), -SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 15, 1, 1), -SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 11, 1, 1), -SOC_DAPM_SINGLE("VOICE2HP Playback Switch", ALC5632_VOICE_DAC_VOL, 15, 1, 1), -}; - -static const struct snd_kcontrol_new alc5632_hpl_mixer_controls[] = { -SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5632_ADC_REC_GAIN, 15, 1, 1), -SOC_DAPM_SINGLE("DACL2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 3, 1, 1), -}; - -static const struct snd_kcontrol_new alc5632_hpr_mixer_controls[] = { -SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5632_ADC_REC_GAIN, 7, 1, 1), -SOC_DAPM_SINGLE("DACR2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 2, 1, 1), -}; - -static const struct snd_kcontrol_new alc5632_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5632_ADC_REC_GAIN, 14, 1, 1), -SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5632_ADC_REC_GAIN, 6, 1, 1), -SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5632_LINE_IN_VOL, 13, 1, 1), -SOC_DAPM_SINGLE("MIC12MONO Playback Switch", - ALC5632_MIC_ROUTING_CTRL, 13, 1, 1), -SOC_DAPM_SINGLE("MIC22MONO Playback Switch", - ALC5632_MIC_ROUTING_CTRL, 9, 1, 1), -SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5632_MIC_ROUTING_CTRL, 0, 1, 1), -SOC_DAPM_SINGLE("VOICE2MONO Playback Switch", ALC5632_VOICE_DAC_VOL, 13, 1, 1), -}; - -static const struct snd_kcontrol_new alc5632_speaker_mixer_controls[] = { -SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5632_LINE_IN_VOL, 14, 1, 1), -SOC_DAPM_SINGLE("PHONE2SPK Playback Switch", ALC5632_PHONE_IN_VOL, 14, 1, 1), -SOC_DAPM_SINGLE("MIC12SPK Playback Switch", - ALC5632_MIC_ROUTING_CTRL, 14, 1, 1), -SOC_DAPM_SINGLE("MIC22SPK Playback Switch", - ALC5632_MIC_ROUTING_CTRL, 10, 1, 1), -SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5632_MIC_ROUTING_CTRL, 1, 1, 1), -SOC_DAPM_SINGLE("VOICE2SPK Playback Switch", ALC5632_VOICE_DAC_VOL, 14, 1, 1), -}; - -/* Left Record Mixer */ -static const struct snd_kcontrol_new alc5632_captureL_mixer_controls[] = { -SOC_DAPM_SINGLE("MIC12REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1), -SOC_DAPM_SINGLE("MIC22REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1), -SOC_DAPM_SINGLE("LIL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1), -SOC_DAPM_SINGLE("PH2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1), -SOC_DAPM_SINGLE("HPL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1), -SOC_DAPM_SINGLE("SPK2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1), -SOC_DAPM_SINGLE("MONO2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1), -}; - -/* Right Record Mixer */ -static const struct snd_kcontrol_new alc5632_captureR_mixer_controls[] = { -SOC_DAPM_SINGLE("MIC12REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1), -SOC_DAPM_SINGLE("MIC22REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1), -SOC_DAPM_SINGLE("LIR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1), -SOC_DAPM_SINGLE("PH2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1), -SOC_DAPM_SINGLE("HPR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1), -SOC_DAPM_SINGLE("SPK2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1), -SOC_DAPM_SINGLE("MONO2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1), -}; - -/* Dmic Mixer */ -static const struct snd_kcontrol_new alc5632_dmicl_mixer_controls[] = { -SOC_DAPM_SINGLE("DMICL2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 7, 1, 1), -}; -static const struct snd_kcontrol_new alc5632_dmicr_mixer_controls[] = { -SOC_DAPM_SINGLE("DMICR2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 6, 1, 1), -}; - -static const char * const alc5632_spk_n_sour_sel[] = { - "RN/-R", "RP/+R", "LN/-R", "Mute"}; -static const char * const alc5632_hpl_out_input_sel[] = { - "Vmid", "HP Left Mix"}; -static const char * const alc5632_hpr_out_input_sel[] = { - "Vmid", "HP Right Mix"}; -static const char * const alc5632_spkout_input_sel[] = { - "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; -static const char * const alc5632_aux_out_input_sel[] = { - "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"}; -static const char * const alc5632_adcr_func_sel[] = { - "Stereo ADC", "Voice ADC"}; -static const char * const alc5632_i2s_out_sel[] = { - "ADC LR", "Voice Stereo Digital"}; - -/* auxout output mux */ -static const struct soc_enum alc5632_aux_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel); -static const struct snd_kcontrol_new alc5632_auxout_mux_controls = -SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum); - -/* speaker output mux */ -static const struct soc_enum alc5632_spkout_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel); -static const struct snd_kcontrol_new alc5632_spkout_mux_controls = -SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum); - -/* headphone left output mux */ -static const struct soc_enum alc5632_hpl_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel); -static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls = -SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum); - -/* headphone right output mux */ -static const struct soc_enum alc5632_hpr_out_input_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel); -static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls = -SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum); - -/* speaker output N select */ -static const struct soc_enum alc5632_spk_n_sour_enum = -SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel); -static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls = -SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum); - -/* speaker amplifier */ -static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"}; -static const struct soc_enum alc5632_amp_enum = - SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names); -static const struct snd_kcontrol_new alc5632_amp_mux_controls = - SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum); - -/* ADC output select */ -static const struct soc_enum alc5632_adcr_func_enum = - SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel); -static const struct snd_kcontrol_new alc5632_adcr_func_controls = - SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum); - -/* I2S out select */ -static const struct soc_enum alc5632_i2s_out_enum = - SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel); -static const struct snd_kcontrol_new alc5632_i2s_out_controls = - SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum); - -static const struct snd_soc_dapm_widget alc5632_dapm_widgets[] = { -/* Muxes */ -SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0, - &alc5632_auxout_mux_controls), -SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0, - &alc5632_spkout_mux_controls), -SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, - &alc5632_hpl_out_mux_controls), -SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, - &alc5632_hpr_out_mux_controls), -SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0, - &alc5632_spkoutn_mux_controls), -SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0, - &alc5632_adcr_func_controls), -SND_SOC_DAPM_MUX("I2SOut Mux", ALC5632_PWR_MANAG_ADD1, 11, 0, - &alc5632_i2s_out_controls), - -/* output mixers */ -SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0, - &alc5632_hp_mixer_controls[0], - ARRAY_SIZE(alc5632_hp_mixer_controls)), -SND_SOC_DAPM_MIXER("HPR Mix", ALC5632_PWR_MANAG_ADD2, 4, 0, - &alc5632_hpr_mixer_controls[0], - ARRAY_SIZE(alc5632_hpr_mixer_controls)), -SND_SOC_DAPM_MIXER("HPL Mix", ALC5632_PWR_MANAG_ADD2, 5, 0, - &alc5632_hpl_mixer_controls[0], - ARRAY_SIZE(alc5632_hpl_mixer_controls)), -SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2, 2, 0, - &alc5632_mono_mixer_controls[0], - ARRAY_SIZE(alc5632_mono_mixer_controls)), -SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2, 3, 0, - &alc5632_speaker_mixer_controls[0], - ARRAY_SIZE(alc5632_speaker_mixer_controls)), -SND_SOC_DAPM_MIXER("DMICL Mix", SND_SOC_NOPM, 0, 0, - &alc5632_dmicl_mixer_controls[0], - ARRAY_SIZE(alc5632_dmicl_mixer_controls)), -SND_SOC_DAPM_MIXER("DMICR Mix", SND_SOC_NOPM, 0, 0, - &alc5632_dmicr_mixer_controls[0], - ARRAY_SIZE(alc5632_dmicr_mixer_controls)), - -/* input mixers */ -SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2, 1, 0, - &alc5632_captureL_mixer_controls[0], - ARRAY_SIZE(alc5632_captureL_mixer_controls)), -SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5632_PWR_MANAG_ADD2, 0, 0, - &alc5632_captureR_mixer_controls[0], - ARRAY_SIZE(alc5632_captureR_mixer_controls)), - -SND_SOC_DAPM_AIF_IN("AIFRXL", "Left HiFi Playback", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_IN("AIFRXR", "Right HiFi Playback", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_IN("VAIFRX", "Voice Playback", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("VAIFTX", "Voice Capture", 0, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_DAC("Voice DAC", NULL, ALC5632_PWR_MANAG_ADD2, 10, 0), -SND_SOC_DAPM_DAC("Left DAC", NULL, ALC5632_PWR_MANAG_ADD2, 9, 0), -SND_SOC_DAPM_DAC("Right DAC", NULL, ALC5632_PWR_MANAG_ADD2, 8, 0), -SND_SOC_DAPM_ADC("Left ADC", NULL, ALC5632_PWR_MANAG_ADD2, 7, 0), -SND_SOC_DAPM_ADC("Right ADC", NULL, ALC5632_PWR_MANAG_ADD2, 6, 0), - -SND_SOC_DAPM_MIXER("DAC Left Channel", ALC5632_PWR_MANAG_ADD1, 15, 0, NULL, 0), -SND_SOC_DAPM_MIXER("DAC Right Channel", - ALC5632_PWR_MANAG_ADD1, 14, 0, NULL, 0), -SND_SOC_DAPM_MIXER("I2S Mix", ALC5632_PWR_MANAG_ADD1, 11, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Phone Mix", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Voice Mix", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("ADCLR", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3, 11, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3, 10, 0, NULL, 0), -SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3, 13, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Speaker", ALC5632_PWR_MANAG_ADD3, 12, 0, NULL, 0), -SND_SOC_DAPM_PGA("Aux Out", ALC5632_PWR_MANAG_ADD3, 14, 0, NULL, 0), -SND_SOC_DAPM_PGA("Left LineIn", ALC5632_PWR_MANAG_ADD3, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right LineIn", ALC5632_PWR_MANAG_ADD3, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("Phone", ALC5632_PWR_MANAG_ADD3, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("Phone ADMix", ALC5632_PWR_MANAG_ADD3, 4, 0, NULL, 0), -SND_SOC_DAPM_PGA("MIC1 PGA", ALC5632_PWR_MANAG_ADD3, 3, 0, NULL, 0), -SND_SOC_DAPM_PGA("MIC2 PGA", ALC5632_PWR_MANAG_ADD3, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5632_PWR_MANAG_ADD3, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5632_PWR_MANAG_ADD3, 0, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS1", ALC5632_PWR_MANAG_ADD1, 3, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS2", ALC5632_PWR_MANAG_ADD1, 2, 0, NULL, 0), - -SND_SOC_DAPM_PGA_E("D Amp", ALC5632_PWR_MANAG_ADD2, 14, 0, NULL, 0, - amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_PGA("AB Amp", ALC5632_PWR_MANAG_ADD2, 15, 0, NULL, 0), -SND_SOC_DAPM_MUX("AB-D Amp Mux", ALC5632_PWR_MANAG_ADD1, 10, 0, - &alc5632_amp_mux_controls), - -SND_SOC_DAPM_OUTPUT("AUXOUT"), -SND_SOC_DAPM_OUTPUT("HPL"), -SND_SOC_DAPM_OUTPUT("HPR"), -SND_SOC_DAPM_OUTPUT("SPKOUT"), -SND_SOC_DAPM_OUTPUT("SPKOUTN"), - -SND_SOC_DAPM_INPUT("LINEINL"), -SND_SOC_DAPM_INPUT("LINEINR"), -SND_SOC_DAPM_INPUT("PHONEP"), -SND_SOC_DAPM_INPUT("PHONEN"), -SND_SOC_DAPM_INPUT("DMICDAT"), -SND_SOC_DAPM_INPUT("MIC1"), -SND_SOC_DAPM_INPUT("MIC2"), -SND_SOC_DAPM_VMID("Vmid"), -}; - - -static const struct snd_soc_dapm_route alc5632_dapm_routes[] = { - /* Playback streams */ - {"Left DAC", NULL, "AIFRXL"}, - {"Right DAC", NULL, "AIFRXR"}, - - /* virtual mixer - mixes left & right channels */ - {"I2S Mix", NULL, "Left DAC"}, - {"I2S Mix", NULL, "Right DAC"}, - {"Line Mix", NULL, "Right LineIn"}, - {"Line Mix", NULL, "Left LineIn"}, - {"Phone Mix", NULL, "Phone"}, - {"Phone Mix", NULL, "Phone ADMix"}, - {"AUXOUT", NULL, "Aux Out"}, - - /* DAC */ - {"DAC Right Channel", NULL, "I2S Mix"}, - {"DAC Left Channel", NULL, "I2S Mix"}, - - /* HP mixer */ - {"HPL Mix", "ADC2HP_L Playback Switch", "Left Capture Mix"}, - {"HPL Mix", NULL, "HP Mix"}, - {"HPR Mix", "ADC2HP_R Playback Switch", "Right Capture Mix"}, - {"HPR Mix", NULL, "HP Mix"}, - {"HP Mix", "LI2HP Playback Switch", "Line Mix"}, - {"HP Mix", "PHONE2HP Playback Switch", "Phone Mix"}, - {"HP Mix", "MIC12HP Playback Switch", "MIC1 PGA"}, - {"HP Mix", "MIC22HP Playback Switch", "MIC2 PGA"}, - {"HP Mix", "VOICE2HP Playback Switch", "Voice Mix"}, - {"HPR Mix", "DACR2HP Playback Switch", "DAC Right Channel"}, - {"HPL Mix", "DACL2HP Playback Switch", "DAC Left Channel"}, - {"HPOut Mix", NULL, "HP Mix"}, - {"HPOut Mix", NULL, "HPR Mix"}, - {"HPOut Mix", NULL, "HPL Mix"}, - - /* speaker mixer */ - {"Speaker Mix", "LI2SPK Playback Switch", "Line Mix"}, - {"Speaker Mix", "PHONE2SPK Playback Switch", "Phone Mix"}, - {"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"}, - {"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"}, - {"Speaker Mix", "DAC2SPK Playback Switch", "DAC Left Channel"}, - {"Speaker Mix", "VOICE2SPK Playback Switch", "Voice Mix"}, - - /* mono mixer */ - {"Mono Mix", "ADC2MONO_L Playback Switch", "Left Capture Mix"}, - {"Mono Mix", "ADC2MONO_R Playback Switch", "Right Capture Mix"}, - {"Mono Mix", "LI2MONO Playback Switch", "Line Mix"}, - {"Mono Mix", "MIC12MONO Playback Switch", "MIC1 PGA"}, - {"Mono Mix", "MIC22MONO Playback Switch", "MIC2 PGA"}, - {"Mono Mix", "DAC2MONO Playback Switch", "DAC Left Channel"}, - {"Mono Mix", "VOICE2MONO Playback Switch", "Voice Mix"}, - - /* Left record mixer */ - {"Left Capture Mix", "LIL2REC Capture Switch", "LINEINL"}, - {"Left Capture Mix", "PH2REC_L Capture Switch", "PHONEN"}, - {"Left Capture Mix", "MIC12REC_L Capture Switch", "MIC1 Pre Amp"}, - {"Left Capture Mix", "MIC22REC_L Capture Switch", "MIC2 Pre Amp"}, - {"Left Capture Mix", "HPL2REC Capture Switch", "HPL Mix"}, - {"Left Capture Mix", "SPK2REC_L Capture Switch", "Speaker Mix"}, - {"Left Capture Mix", "MONO2REC_L Capture Switch", "Mono Mix"}, - - /*Right record mixer */ - {"Right Capture Mix", "LIR2REC Capture Switch", "LINEINR"}, - {"Right Capture Mix", "PH2REC_R Capture Switch", "PHONEP"}, - {"Right Capture Mix", "MIC12REC_R Capture Switch", "MIC1 Pre Amp"}, - {"Right Capture Mix", "MIC22REC_R Capture Switch", "MIC2 Pre Amp"}, - {"Right Capture Mix", "HPR2REC Capture Switch", "HPR Mix"}, - {"Right Capture Mix", "SPK2REC_R Capture Switch", "Speaker Mix"}, - {"Right Capture Mix", "MONO2REC_R Capture Switch", "Mono Mix"}, - - /* headphone left mux */ - {"Left Headphone Mux", "HP Left Mix", "HPL Mix"}, - {"Left Headphone Mux", "Vmid", "Vmid"}, - - /* headphone right mux */ - {"Right Headphone Mux", "HP Right Mix", "HPR Mix"}, - {"Right Headphone Mux", "Vmid", "Vmid"}, - - /* speaker out mux */ - {"SpeakerOut Mux", "Vmid", "Vmid"}, - {"SpeakerOut Mux", "HPOut Mix", "HPOut Mix"}, - {"SpeakerOut Mux", "Speaker Mix", "Speaker Mix"}, - {"SpeakerOut Mux", "Mono Mix", "Mono Mix"}, - - /* Mono/Aux Out mux */ - {"AuxOut Mux", "Vmid", "Vmid"}, - {"AuxOut Mux", "HPOut Mix", "HPOut Mix"}, - {"AuxOut Mux", "Speaker Mix", "Speaker Mix"}, - {"AuxOut Mux", "Mono Mix", "Mono Mix"}, - - /* output pga */ - {"HPL", NULL, "Left Headphone"}, - {"Left Headphone", NULL, "Left Headphone Mux"}, - {"HPR", NULL, "Right Headphone"}, - {"Right Headphone", NULL, "Right Headphone Mux"}, - {"Aux Out", NULL, "AuxOut Mux"}, - - /* input pga */ - {"Left LineIn", NULL, "LINEINL"}, - {"Right LineIn", NULL, "LINEINR"}, - {"Phone", NULL, "PHONEP"}, - {"MIC1 Pre Amp", NULL, "MIC1"}, - {"MIC2 Pre Amp", NULL, "MIC2"}, - {"MIC1 PGA", NULL, "MIC1 Pre Amp"}, - {"MIC2 PGA", NULL, "MIC2 Pre Amp"}, - - /* left ADC */ - {"Left ADC", NULL, "Left Capture Mix"}, - {"DMICL Mix", "DMICL2ADC Capture Switch", "DMICDAT"}, - {"Left ADC", NULL, "DMICL Mix"}, - {"ADCLR", NULL, "Left ADC"}, - - /* right ADC */ - {"Right ADC", NULL, "Right Capture Mix"}, - {"DMICR Mix", "DMICR2ADC Capture Switch", "DMICDAT"}, - {"Right ADC", NULL, "DMICR Mix"}, - {"ADCR Mux", "Stereo ADC", "Right ADC"}, - {"ADCR Mux", "Voice ADC", "Right ADC"}, - {"ADCLR", NULL, "ADCR Mux"}, - {"VAIFTX", NULL, "ADCR Mux"}, - - /* Digital I2S out */ - {"I2SOut Mux", "ADC LR", "ADCLR"}, - {"I2SOut Mux", "Voice Stereo Digital", "VAIFRX"}, - {"AIFTXL", NULL, "I2SOut Mux"}, - {"AIFTXR", NULL, "I2SOut Mux"}, - - /* Voice Mix */ - {"Voice DAC", NULL, "VAIFRX"}, - {"Voice Mix", NULL, "Voice DAC"}, - - /* Speaker Output */ - {"SpeakerOut N Mux", "RN/-R", "Left Speaker"}, - {"SpeakerOut N Mux", "RP/+R", "Left Speaker"}, - {"SpeakerOut N Mux", "LN/-R", "Left Speaker"}, - {"SpeakerOut N Mux", "Mute", "Vmid"}, - - {"SpeakerOut N Mux", "RN/-R", "Right Speaker"}, - {"SpeakerOut N Mux", "RP/+R", "Right Speaker"}, - {"SpeakerOut N Mux", "LN/-R", "Right Speaker"}, - {"SpeakerOut N Mux", "Mute", "Vmid"}, - - {"AB Amp", NULL, "SpeakerOut Mux"}, - {"D Amp", NULL, "SpeakerOut Mux"}, - {"AB-D Amp Mux", "AB Amp", "AB Amp"}, - {"AB-D Amp Mux", "D Amp", "D Amp"}, - {"Left Speaker", NULL, "AB-D Amp Mux"}, - {"Right Speaker", NULL, "AB-D Amp Mux"}, - - {"SPKOUT", NULL, "Left Speaker"}, - {"SPKOUT", NULL, "Right Speaker"}, - - {"SPKOUTN", NULL, "SpeakerOut N Mux"}, - -}; - -/* PLL divisors */ -struct _pll_div { - u32 pll_in; - u32 pll_out; - u16 regvalue; -}; - -/* Note : pll code from original alc5632 driver. Not sure of how good it is */ -/* usefull only for master mode */ -static const struct _pll_div codec_master_pll_div[] = { - - { 2048000, 8192000, 0x0ea0}, - { 3686400, 8192000, 0x4e27}, - { 12000000, 8192000, 0x456b}, - { 13000000, 8192000, 0x495f}, - { 13100000, 8192000, 0x0320}, - { 2048000, 11289600, 0xf637}, - { 3686400, 11289600, 0x2f22}, - { 12000000, 11289600, 0x3e2f}, - { 13000000, 11289600, 0x4d5b}, - { 13100000, 11289600, 0x363b}, - { 2048000, 16384000, 0x1ea0}, - { 3686400, 16384000, 0x9e27}, - { 12000000, 16384000, 0x452b}, - { 13000000, 16384000, 0x542f}, - { 13100000, 16384000, 0x03a0}, - { 2048000, 16934400, 0xe625}, - { 3686400, 16934400, 0x9126}, - { 12000000, 16934400, 0x4d2c}, - { 13000000, 16934400, 0x742f}, - { 13100000, 16934400, 0x3c27}, - { 2048000, 22579200, 0x2aa0}, - { 3686400, 22579200, 0x2f20}, - { 12000000, 22579200, 0x7e2f}, - { 13000000, 22579200, 0x742f}, - { 13100000, 22579200, 0x3c27}, - { 2048000, 24576000, 0x2ea0}, - { 3686400, 24576000, 0xee27}, - { 12000000, 24576000, 0x2915}, - { 13000000, 24576000, 0x772e}, - { 13100000, 24576000, 0x0d20}, -}; - -/* FOUT = MCLK*(N+2)/((M+2)*(K+2)) - N: bit 15:8 (div 2 .. div 257) - K: bit 6:4 typical 2 - M: bit 3:0 (div 2 .. div 17) - - same as for 5623 - thanks! -*/ - -static const struct _pll_div codec_slave_pll_div[] = { - - { 1024000, 16384000, 0x3ea0}, - { 1411200, 22579200, 0x3ea0}, - { 1536000, 24576000, 0x3ea0}, - { 2048000, 16384000, 0x1ea0}, - { 2822400, 22579200, 0x1ea0}, - { 3072000, 24576000, 0x1ea0}, - -}; - -static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - int i; - struct snd_soc_codec *codec = codec_dai->codec; - int gbl_clk = 0, pll_div = 0; - u16 reg; - - if (pll_id < ALC5632_PLL_FR_MCLK || pll_id > ALC5632_PLL_FR_VBCLK) - return -EINVAL; - - /* Disable PLL power */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, - ALC5632_PWR_ADD2_PLL1, - 0); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, - ALC5632_PWR_ADD2_PLL2, - 0); - - /* pll is not used in slave mode */ - reg = snd_soc_read(codec, ALC5632_DAI_CONTROL); - if (reg & ALC5632_DAI_SDP_SLAVE_MODE) - return 0; - - if (!freq_in || !freq_out) - return 0; - - switch (pll_id) { - case ALC5632_PLL_FR_MCLK: - for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) { - if (codec_master_pll_div[i].pll_in == freq_in - && codec_master_pll_div[i].pll_out == freq_out) { - /* PLL source from MCLK */ - pll_div = codec_master_pll_div[i].regvalue; - break; - } - } - break; - case ALC5632_PLL_FR_BCLK: - for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) { - if (codec_slave_pll_div[i].pll_in == freq_in - && codec_slave_pll_div[i].pll_out == freq_out) { - /* PLL source from Bitclk */ - gbl_clk = ALC5632_PLL_FR_BCLK; - pll_div = codec_slave_pll_div[i].regvalue; - break; - } - } - break; - case ALC5632_PLL_FR_VBCLK: - for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) { - if (codec_slave_pll_div[i].pll_in == freq_in - && codec_slave_pll_div[i].pll_out == freq_out) { - /* PLL source from voice clock */ - gbl_clk = ALC5632_PLL_FR_VBCLK; - pll_div = codec_slave_pll_div[i].regvalue; - break; - } - } - break; - default: - return -EINVAL; - } - - if (!pll_div) - return -EINVAL; - - /* choose MCLK/BCLK/VBCLK */ - snd_soc_write(codec, ALC5632_GPCR2, gbl_clk); - /* choose PLL1 clock rate */ - snd_soc_write(codec, ALC5632_PLL1_CTRL, pll_div); - /* enable PLL1 */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, - ALC5632_PWR_ADD2_PLL1, - ALC5632_PWR_ADD2_PLL1); - /* enable PLL2 */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, - ALC5632_PWR_ADD2_PLL2, - ALC5632_PWR_ADD2_PLL2); - /* use PLL1 as main SYSCLK */ - snd_soc_update_bits(codec, ALC5632_GPCR1, - ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1, - ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1); - - return 0; -} - -struct _coeff_div { - u16 fs; - u16 regvalue; -}; - -/* codec hifi mclk (after PLL) clock divider coefficients */ -/* values inspired from column BCLK=32Fs of Appendix A table */ -static const struct _coeff_div coeff_div[] = { - {512*1, 0x3075}, -}; - -static int get_coeff(struct snd_soc_codec *codec, int rate) -{ - struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].fs * rate == alc5632->sysclk) - return i; - } - return -EINVAL; -} - -/* - * Clock after PLL and dividers - */ -static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 4096000: - case 8192000: - case 11289600: - case 12288000: - case 16384000: - case 16934400: - case 18432000: - case 22579200: - case 24576000: - alc5632->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int alc5632_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface = ALC5632_DAI_SDP_MASTER_MODE; - break; - case SND_SOC_DAIFMT_CBS_CFS: - iface = ALC5632_DAI_SDP_SLAVE_MODE; - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= ALC5632_DAI_I2S_DF_I2S; - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= ALC5632_DAI_I2S_DF_LEFT; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= ALC5632_DAI_I2S_DF_PCM_A; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= ALC5632_DAI_I2S_DF_PCM_B; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL; - break; - case SND_SOC_DAIFMT_NB_IF: - break; - default: - return -EINVAL; - } - - return snd_soc_write(codec, ALC5632_DAI_CONTROL, iface); -} - -static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - int coeff, rate; - u16 iface; - - iface = snd_soc_read(codec, ALC5632_DAI_CONTROL); - iface &= ~ALC5632_DAI_I2S_DL_MASK; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - iface |= ALC5632_DAI_I2S_DL_16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= ALC5632_DAI_I2S_DL_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= ALC5632_DAI_I2S_DL_24; - break; - default: - return -EINVAL; - } - - /* set iface & srate */ - snd_soc_write(codec, ALC5632_DAI_CONTROL, iface); - rate = params_rate(params); - coeff = get_coeff(codec, rate); - if (coeff < 0) - return -EINVAL; - - coeff = coeff_div[coeff].regvalue; - snd_soc_write(codec, ALC5632_DAC_CLK_CTRL1, coeff); - - return 0; -} - -static int alc5632_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 hp_mute = ALC5632_MISC_HP_DEPOP_MUTE_L - |ALC5632_MISC_HP_DEPOP_MUTE_R; - u16 mute_reg = snd_soc_read(codec, ALC5632_MISC_CTRL) & ~hp_mute; - - if (mute) - mute_reg |= hp_mute; - - return snd_soc_write(codec, ALC5632_MISC_CTRL, mute_reg); -} - -#define ALC5632_ADD2_POWER_EN (ALC5632_PWR_ADD2_VREF) - -#define ALC5632_ADD3_POWER_EN (ALC5632_PWR_ADD3_MIC1_BOOST_AD) - -#define ALC5632_ADD1_POWER_EN \ - (ALC5632_PWR_ADD1_DAC_REF \ - | ALC5632_PWR_ADD1_SOFTGEN_EN \ - | ALC5632_PWR_ADD1_HP_OUT_AMP \ - | ALC5632_PWR_ADD1_HP_OUT_ENH_AMP \ - | ALC5632_PWR_ADD1_MAIN_BIAS) - -static void enable_power_depop(struct snd_soc_codec *codec) -{ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, - ALC5632_PWR_ADD1_SOFTGEN_EN, - ALC5632_PWR_ADD1_SOFTGEN_EN); - - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3, - ALC5632_ADD3_POWER_EN, - ALC5632_ADD3_POWER_EN); - - snd_soc_update_bits(codec, ALC5632_MISC_CTRL, - ALC5632_MISC_HP_DEPOP_MODE2_EN, - ALC5632_MISC_HP_DEPOP_MODE2_EN); - - /* "normal" mode: 0 @ 26 */ - /* set all PR0-7 mixers to 0 */ - snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS, - ALC5632_PWR_DOWN_CTRL_STATUS_MASK, - 0); - - msleep(500); - - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, - ALC5632_ADD2_POWER_EN, - ALC5632_ADD2_POWER_EN); - - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, - ALC5632_ADD1_POWER_EN, - ALC5632_ADD1_POWER_EN); - - /* disable HP Depop2 */ - snd_soc_update_bits(codec, ALC5632_MISC_CTRL, - ALC5632_MISC_HP_DEPOP_MODE2_EN, - 0); - -} - -static int alc5632_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - enable_power_depop(codec); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - /* everything off except vref/vmid, */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, - ALC5632_PWR_MANAG_ADD1_MASK, - ALC5632_PWR_ADD1_MAIN_BIAS); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, - ALC5632_PWR_MANAG_ADD2_MASK, - ALC5632_PWR_ADD2_VREF); - /* "normal" mode: 0 @ 26 */ - snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS, - ALC5632_PWR_DOWN_CTRL_STATUS_MASK, - 0xffff ^ (ALC5632_PWR_VREF_PR3 - | ALC5632_PWR_VREF_PR2)); - break; - case SND_SOC_BIAS_OFF: - /* everything off, dac mute, inactive */ - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2, - ALC5632_PWR_MANAG_ADD2_MASK, 0); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3, - ALC5632_PWR_MANAG_ADD3_MASK, 0); - snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1, - ALC5632_PWR_MANAG_ADD1_MASK, 0); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define ALC5632_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \ - | SNDRV_PCM_FMTBIT_S24_LE \ - | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops alc5632_dai_ops = { - .hw_params = alc5632_pcm_hw_params, - .digital_mute = alc5632_mute, - .set_fmt = alc5632_set_dai_fmt, - .set_sysclk = alc5632_set_dai_sysclk, - .set_pll = alc5632_set_dai_pll, -}; - -static struct snd_soc_dai_driver alc5632_dai = { - .name = "alc5632-hifi", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rate_min = 8000, - .rate_max = 48000, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ALC5632_FORMATS,}, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rate_min = 8000, - .rate_max = 48000, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = ALC5632_FORMATS,}, - - .ops = &alc5632_dai_ops, - .symmetric_rates = 1, -}; - -#ifdef CONFIG_PM -static int alc5632_suspend(struct snd_soc_codec *codec) -{ - alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int alc5632_resume(struct snd_soc_codec *codec) -{ - struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); - - regcache_sync(alc5632->regmap); - - alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define alc5632_suspend NULL -#define alc5632_resume NULL -#endif - -static int alc5632_probe(struct snd_soc_codec *codec) -{ - struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = alc5632->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* power on device */ - alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - switch (alc5632->id) { - case 0x5c: - snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls, - ARRAY_SIZE(alc5632_vol_snd_controls)); - break; - default: - return -EINVAL; - } - - return ret; -} - -/* power down chip */ -static int alc5632_remove(struct snd_soc_codec *codec) -{ - alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_device_alc5632 = { - .probe = alc5632_probe, - .remove = alc5632_remove, - .suspend = alc5632_suspend, - .resume = alc5632_resume, - .set_bias_level = alc5632_set_bias_level, - .controls = alc5632_snd_controls, - .num_controls = ARRAY_SIZE(alc5632_snd_controls), - .dapm_widgets = alc5632_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets), - .dapm_routes = alc5632_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes), -}; - -static struct regmap_config alc5632_regmap = { - .reg_bits = 8, - .val_bits = 16, - - .max_register = ALC5632_MAX_REGISTER, - .reg_defaults = alc5632_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(alc5632_reg_defaults), - .volatile_reg = alc5632_volatile_register, - .cache_type = REGCACHE_RBTREE, -}; - -/* - * alc5632 2 wire address is determined by A1 pin - * state during powerup. - * low = 0x1a - * high = 0x1b - */ -static __devinit int alc5632_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct alc5632_priv *alc5632; - int ret, ret1, ret2; - unsigned int vid1, vid2; - - alc5632 = devm_kzalloc(&client->dev, - sizeof(struct alc5632_priv), GFP_KERNEL); - if (alc5632 == NULL) - return -ENOMEM; - - i2c_set_clientdata(client, alc5632); - - alc5632->regmap = regmap_init_i2c(client, &alc5632_regmap); - if (IS_ERR(alc5632->regmap)) { - ret = PTR_ERR(alc5632->regmap); - dev_err(&client->dev, "regmap_init() failed: %d\n", ret); - return ret; - } - - ret1 = regmap_read(alc5632->regmap, ALC5632_VENDOR_ID1, &vid1); - ret2 = regmap_read(alc5632->regmap, ALC5632_VENDOR_ID2, &vid2); - if (ret1 != 0 || ret2 != 0) { - dev_err(&client->dev, - "Failed to read chip ID: ret1=%d, ret2=%d\n", ret1, ret2); - regmap_exit(alc5632->regmap); - return -EIO; - } - - vid2 >>= 8; - - if ((vid1 != 0x10EC) || (vid2 != id->driver_data)) { - dev_err(&client->dev, - "Device is not a ALC5632: VID1=0x%x, VID2=0x%x\n", vid1, vid2); - regmap_exit(alc5632->regmap); - return -EINVAL; - } - - ret = alc5632_reset(alc5632->regmap); - if (ret < 0) { - dev_err(&client->dev, "Failed to issue reset\n"); - regmap_exit(alc5632->regmap); - return ret; - } - - alc5632->id = vid2; - switch (alc5632->id) { - case 0x5c: - alc5632_dai.name = "alc5632-hifi"; - break; - default: - return -EINVAL; - } - - ret = snd_soc_register_codec(&client->dev, - &soc_codec_device_alc5632, &alc5632_dai, 1); - - if (ret < 0) { - dev_err(&client->dev, "Failed to register codec: %d\n", ret); - regmap_exit(alc5632->regmap); - return ret; - } - - return ret; -} - -static __devexit int alc5632_i2c_remove(struct i2c_client *client) -{ - struct alc5632_priv *alc5632 = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(alc5632->regmap); - return 0; -} - -static const struct i2c_device_id alc5632_i2c_table[] = { - {"alc5632", 0x5c}, - {} -}; -MODULE_DEVICE_TABLE(i2c, alc5632_i2c_table); - -/* i2c codec control layer */ -static struct i2c_driver alc5632_i2c_driver = { - .driver = { - .name = "alc5632", - .owner = THIS_MODULE, - }, - .probe = alc5632_i2c_probe, - .remove = __devexit_p(alc5632_i2c_remove), - .id_table = alc5632_i2c_table, -}; - -static int __init alc5632_modinit(void) -{ - int ret; - - ret = i2c_add_driver(&alc5632_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "%s: can't add i2c driver", __func__); - return ret; - } - - return ret; -} -module_init(alc5632_modinit); - -static void __exit alc5632_modexit(void) -{ - i2c_del_driver(&alc5632_i2c_driver); -} -module_exit(alc5632_modexit); - -MODULE_DESCRIPTION("ASoC ALC5632 driver"); -MODULE_AUTHOR("Leon Romanovsky "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/alc5632.h b/ANDROID_3.4.5/sound/soc/codecs/alc5632.h deleted file mode 100644 index 1b5bda59..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/alc5632.h +++ /dev/null @@ -1,252 +0,0 @@ -/* -* alc5632.h -- ALC5632 ALSA SoC Audio Codec -* -* Copyright (C) 2011 The AC100 Kernel Team -* -* Authors: Leon Romanovsky -* Andrey Danin -* Ilya Petrov -* Marc Dietrich -* -* Based on alc5623.h by Arnaud Patard -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -*/ - -#ifndef _ALC5632_H -#define _ALC5632_H - -#define ALC5632_RESET 0x00 -/* speaker output vol 2 2 */ -/* line output vol 4 2 */ -/* HP output vol 4 0 4 */ -#define ALC5632_SPK_OUT_VOL 0x02 /* spe out vol */ -#define ALC5632_SPK_OUT_VOL_STEP 1.5 -#define ALC5632_HP_OUT_VOL 0x04 /* hp out vol */ -#define ALC5632_AUX_OUT_VOL 0x06 /* aux out vol */ -#define ALC5632_PHONE_IN_VOL 0x08 /* phone in vol */ -#define ALC5632_LINE_IN_VOL 0x0A /* line in vol */ -#define ALC5632_STEREO_DAC_IN_VOL 0x0C /* stereo dac in vol */ -#define ALC5632_MIC_VOL 0x0E /* mic in vol */ -/* stero dac/mic routing */ -#define ALC5632_MIC_ROUTING_CTRL 0x10 -#define ALC5632_MIC_ROUTE_MONOMIX (1 << 0) -#define ALC5632_MIC_ROUTE_SPK (1 << 1) -#define ALC5632_MIC_ROUTE_HP (1 << 2) - -#define ALC5632_ADC_REC_GAIN 0x12 /* rec gain */ -#define ALC5632_ADC_REC_GAIN_RANGE 0x1F1F -#define ALC5632_ADC_REC_GAIN_BASE (-16.5) -#define ALC5632_ADC_REC_GAIN_STEP 1.5 - -#define ALC5632_ADC_REC_MIXER 0x14 /* mixer control */ -#define ALC5632_ADC_REC_MIC1 (1 << 6) -#define ALC5632_ADC_REC_MIC2 (1 << 5) -#define ALC5632_ADC_REC_LINE_IN (1 << 4) -#define ALC5632_ADC_REC_AUX (1 << 3) -#define ALC5632_ADC_REC_HP (1 << 2) -#define ALC5632_ADC_REC_SPK (1 << 1) -#define ALC5632_ADC_REC_MONOMIX (1 << 0) - -#define ALC5632_VOICE_DAC_VOL 0x18 /* voice dac vol */ -#define ALC5632_I2S_OUT_CTL 0x1A /* undocumented reg. found in path scheme */ -/* ALC5632_OUTPUT_MIXER_CTRL : */ -/* same remark as for reg 2 line vs speaker */ -#define ALC5632_OUTPUT_MIXER_CTRL 0x1C /* out mix ctrl */ -#define ALC5632_OUTPUT_MIXER_RP (1 << 14) -#define ALC5632_OUTPUT_MIXER_WEEK (1 << 12) -#define ALC5632_OUTPUT_MIXER_HP (1 << 10) -#define ALC5632_OUTPUT_MIXER_AUX_SPK (2 << 6) -#define ALC5632_OUTPUT_MIXER_AUX_HP_LR (1 << 6) -#define ALC5632_OUTPUT_MIXER_HP_R (1 << 8) -#define ALC5632_OUTPUT_MIXER_HP_L (1 << 9) - -#define ALC5632_MIC_CTRL 0x22 /* mic phone ctrl */ -#define ALC5632_MIC_BOOST_BYPASS 0 -#define ALC5632_MIC_BOOST_20DB 1 -#define ALC5632_MIC_BOOST_30DB 2 -#define ALC5632_MIC_BOOST_40DB 3 - -#define ALC5632_DIGI_BOOST_CTRL 0x24 /* digi mic / bost ctl */ -#define ALC5632_MIC_BOOST_RANGE 7 -#define ALC5632_MIC_BOOST_STEP 6 -#define ALC5632_PWR_DOWN_CTRL_STATUS 0x26 -#define ALC5632_PWR_DOWN_CTRL_STATUS_MASK 0xEF00 -#define ALC5632_PWR_VREF_PR3 (1 << 11) -#define ALC5632_PWR_VREF_PR2 (1 << 10) -#define ALC5632_PWR_VREF_STATUS (1 << 3) -#define ALC5632_PWR_AMIX_STATUS (1 << 2) -#define ALC5632_PWR_DAC_STATUS (1 << 1) -#define ALC5632_PWR_ADC_STATUS (1 << 0) -/* stereo/voice DAC / stereo adc func ctrl */ -#define ALC5632_DAC_FUNC_SELECT 0x2E - -/* Main serial data port ctrl (i2s) */ -#define ALC5632_DAI_CONTROL 0x34 - -#define ALC5632_DAI_SDP_MASTER_MODE (0 << 15) -#define ALC5632_DAI_SDP_SLAVE_MODE (1 << 15) -#define ALC5632_DAI_SADLRCK_MODE (1 << 14) -/* 0:voice, 1:main */ -#define ALC5632_DAI_MAIN_I2S_SYSCLK_SEL (1 << 8) -#define ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL (1 << 7) -/* 0:normal, 1:invert */ -#define ALC5632_DAI_MAIN_I2S_LRCK_INV (1 << 6) -#define ALC5632_DAI_I2S_DL_MASK (3 << 2) -#define ALC5632_DAI_I2S_DL_8 (3 << 2) -#define ALC5632_DAI_I2S_DL_24 (2 << 2) -#define ALC5632_DAI_I2S_DL_20 (1 << 2) -#define ALC5632_DAI_I2S_DL_16 (0 << 2) -#define ALC5632_DAI_I2S_DF_MASK (3 << 0) -#define ALC5632_DAI_I2S_DF_PCM_B (3 << 0) -#define ALC5632_DAI_I2S_DF_PCM_A (2 << 0) -#define ALC5632_DAI_I2S_DF_LEFT (1 << 0) -#define ALC5632_DAI_I2S_DF_I2S (0 << 0) -/* extend serial data port control (VoDAC_i2c/pcm) */ -#define ALC5632_DAI_CONTROL2 0x36 -/* 0:gpio func, 1:voice pcm */ -#define ALC5632_DAI_VOICE_PCM_ENABLE (1 << 15) -/* 0:master, 1:slave */ -#define ALC5632_DAI_VOICE_MODE_SEL (1 << 14) -/* 0:disable, 1:enable */ -#define ALC5632_DAI_HPF_CLK_CTRL (1 << 13) -/* 0:main, 1:voice */ -#define ALC5632_DAI_VOICE_I2S_SYSCLK_SEL (1 << 8) -/* 0:normal, 1:invert */ -#define ALC5632_DAI_VOICE_VBCLK_SYSCLK_SEL (1 << 7) -/* 0:normal, 1:invert */ -#define ALC5632_DAI_VOICE_I2S_LR_INV (1 << 6) -#define ALC5632_DAI_VOICE_DL_MASK (3 << 2) -#define ALC5632_DAI_VOICE_DL_16 (0 << 2) -#define ALC5632_DAI_VOICE_DL_20 (1 << 2) -#define ALC5632_DAI_VOICE_DL_24 (2 << 2) -#define ALC5632_DAI_VOICE_DL_8 (3 << 2) -#define ALC5632_DAI_VOICE_DF_MASK (3 << 0) -#define ALC5632_DAI_VOICE_DF_I2S (0 << 0) -#define ALC5632_DAI_VOICE_DF_LEFT (1 << 0) -#define ALC5632_DAI_VOICE_DF_PCM_A (2 << 0) -#define ALC5632_DAI_VOICE_DF_PCM_B (3 << 0) - -#define ALC5632_PWR_MANAG_ADD1 0x3A -#define ALC5632_PWR_MANAG_ADD1_MASK 0xEFFF -#define ALC5632_PWR_ADD1_DAC_L_EN (1 << 15) -#define ALC5632_PWR_ADD1_DAC_R_EN (1 << 14) -#define ALC5632_PWR_ADD1_ZERO_CROSS (1 << 13) -#define ALC5632_PWR_ADD1_MAIN_I2S_EN (1 << 11) -#define ALC5632_PWR_ADD1_SPK_AMP_EN (1 << 10) -#define ALC5632_PWR_ADD1_HP_OUT_AMP (1 << 9) -#define ALC5632_PWR_ADD1_HP_OUT_ENH_AMP (1 << 8) -#define ALC5632_PWR_ADD1_VOICE_DAC_MIX (1 << 7) -#define ALC5632_PWR_ADD1_SOFTGEN_EN (1 << 6) -#define ALC5632_PWR_ADD1_MIC1_SHORT_CURR (1 << 5) -#define ALC5632_PWR_ADD1_MIC2_SHORT_CURR (1 << 4) -#define ALC5632_PWR_ADD1_MIC1_EN (1 << 3) -#define ALC5632_PWR_ADD1_MIC2_EN (1 << 2) -#define ALC5632_PWR_ADD1_MAIN_BIAS (1 << 1) -#define ALC5632_PWR_ADD1_DAC_REF (1 << 0) - -#define ALC5632_PWR_MANAG_ADD2 0x3C -#define ALC5632_PWR_MANAG_ADD2_MASK 0x7FFF -#define ALC5632_PWR_ADD2_PLL1 (1 << 15) -#define ALC5632_PWR_ADD2_PLL2 (1 << 14) -#define ALC5632_PWR_ADD2_VREF (1 << 13) -#define ALC5632_PWR_ADD2_OVT_DET (1 << 12) -#define ALC5632_PWR_ADD2_VOICE_DAC (1 << 10) -#define ALC5632_PWR_ADD2_L_DAC_CLK (1 << 9) -#define ALC5632_PWR_ADD2_R_DAC_CLK (1 << 8) -#define ALC5632_PWR_ADD2_L_ADC_CLK_GAIN (1 << 7) -#define ALC5632_PWR_ADD2_R_ADC_CLK_GAIN (1 << 6) -#define ALC5632_PWR_ADD2_L_HP_MIXER (1 << 5) -#define ALC5632_PWR_ADD2_R_HP_MIXER (1 << 4) -#define ALC5632_PWR_ADD2_SPK_MIXER (1 << 3) -#define ALC5632_PWR_ADD2_MONO_MIXER (1 << 2) -#define ALC5632_PWR_ADD2_L_ADC_REC_MIXER (1 << 1) -#define ALC5632_PWR_ADD2_R_ADC_REC_MIXER (1 << 0) - -#define ALC5632_PWR_MANAG_ADD3 0x3E -#define ALC5632_PWR_MANAG_ADD3_MASK 0x7CFF -#define ALC5632_PWR_ADD3_AUXOUT_VOL (1 << 14) -#define ALC5632_PWR_ADD3_SPK_L_OUT (1 << 13) -#define ALC5632_PWR_ADD3_SPK_R_OUT (1 << 12) -#define ALC5632_PWR_ADD3_HP_L_OUT_VOL (1 << 11) -#define ALC5632_PWR_ADD3_HP_R_OUT_VOL (1 << 10) -#define ALC5632_PWR_ADD3_LINEIN_L_VOL (1 << 7) -#define ALC5632_PWR_ADD3_LINEIN_R_VOL (1 << 6) -#define ALC5632_PWR_ADD3_AUXIN_VOL (1 << 5) -#define ALC5632_PWR_ADD3_AUXIN_MIX (1 << 4) -#define ALC5632_PWR_ADD3_MIC1_VOL (1 << 3) -#define ALC5632_PWR_ADD3_MIC2_VOL (1 << 2) -#define ALC5632_PWR_ADD3_MIC1_BOOST_AD (1 << 1) -#define ALC5632_PWR_ADD3_MIC2_BOOST_AD (1 << 0) - -#define ALC5632_GPCR1 0x40 -#define ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1 (1 << 15) -#define ALC5632_GPCR1_CLK_SYS_SRC_SEL_MCLK (0 << 15) -#define ALC5632_GPCR1_DAC_HI_FLT_EN (1 << 10) -#define ALC5632_GPCR1_SPK_AMP_CTRL (7 << 1) -#define ALC5632_GPCR1_VDD_100 (5 << 1) -#define ALC5632_GPCR1_VDD_125 (4 << 1) -#define ALC5632_GPCR1_VDD_150 (3 << 1) -#define ALC5632_GPCR1_VDD_175 (2 << 1) -#define ALC5632_GPCR1_VDD_200 (1 << 1) -#define ALC5632_GPCR1_VDD_225 (0 << 1) - -#define ALC5632_GPCR2 0x42 -#define ALC5632_GPCR2_PLL1_SOUR_SEL (3 << 12) -#define ALC5632_PLL_FR_MCLK (0 << 12) -#define ALC5632_PLL_FR_BCLK (2 << 12) -#define ALC5632_PLL_FR_VBCLK (3 << 12) -#define ALC5632_GPCR2_CLK_PLL_PRE_DIV1 (0 << 0) - -#define ALC5632_PLL1_CTRL 0x44 -#define ALC5632_PLL1_CTRL_N_VAL(n) (((n) & 0x0f) << 8) -#define ALC5632_PLL1_M_BYPASS (1 << 7) -#define ALC5632_PLL1_CTRL_K_VAL(k) (((k) & 0x07) << 4) -#define ALC5632_PLL1_CTRL_M_VAL(m) (((m) & 0x0f) << 0) - -#define ALC5632_PLL2_CTRL 0x46 -#define ALC5632_PLL2_EN (1 << 15) -#define ALC5632_PLL2_RATIO (0 << 15) - -#define ALC5632_GPIO_PIN_CONFIG 0x4C -#define ALC5632_GPIO_PIN_POLARITY 0x4E -#define ALC5632_GPIO_PIN_STICKY 0x50 -#define ALC5632_GPIO_PIN_WAKEUP 0x52 -#define ALC5632_GPIO_PIN_STATUS 0x54 -#define ALC5632_GPIO_PIN_SHARING 0x56 -#define ALC5632_OVER_CURR_STATUS 0x58 -#define ALC5632_SOFTVOL_CTRL 0x5A -#define ALC5632_GPIO_OUPUT_PIN_CTRL 0x5C - -#define ALC5632_MISC_CTRL 0x5E -#define ALC5632_MISC_DISABLE_FAST_VREG (1 << 15) -#define ALC5632_MISC_AVC_TRGT_SEL (3 << 12) -#define ALC5632_MISC_AVC_TRGT_RIGHT (1 << 12) -#define ALC5632_MISC_AVC_TRGT_LEFT (2 << 12) -#define ALC5632_MISC_AVC_TRGT_BOTH (3 << 12) -#define ALC5632_MISC_HP_DEPOP_MODE1_EN (1 << 9) -#define ALC5632_MISC_HP_DEPOP_MODE2_EN (1 << 8) -#define ALC5632_MISC_HP_DEPOP_MUTE_L (1 << 7) -#define ALC5632_MISC_HP_DEPOP_MUTE_R (1 << 6) -#define ALC5632_MISC_HP_DEPOP_MUTE (1 << 5) -#define ALC5632_MISC_GPIO_WAKEUP_CTRL (1 << 1) -#define ALC5632_MISC_IRQOUT_INV_CTRL (1 << 0) - -#define ALC5632_DAC_CLK_CTRL1 0x60 -#define ALC5632_DAC_CLK_CTRL2 0x62 -#define ALC5632_DAC_CLK_CTRL2_DIV1_2 (1 << 0) -#define ALC5632_VOICE_DAC_PCM_CLK_CTRL1 0x64 -#define ALC5632_PSEUDO_SPATIAL_CTRL 0x68 -#define ALC5632_HID_CTRL_INDEX 0x6A -#define ALC5632_HID_CTRL_DATA 0x6C -#define ALC5632_EQ_CTRL 0x6E - -/* undocumented */ -#define ALC5632_VENDOR_ID1 0x7C -#define ALC5632_VENDOR_ID2 0x7E - -#define ALC5632_MAX_REGISTER 0x7E - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/cq93vc.c b/ANDROID_3.4.5/sound/soc/codecs/cq93vc.c deleted file mode 100644 index 064cd6a9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cq93vc.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms - * - * Copyright (C) 2010 Texas Instruments, Inc - * - * Author: Miguel Aguilar - * - * 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 -#include -#include -#include - -#include -#include -#include -#include -#include - -static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct davinci_vc *davinci_vc = codec->control_data; - - return readl(davinci_vc->base + reg); -} - -static inline int cq93vc_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct davinci_vc *davinci_vc = codec->control_data; - - writel(value, davinci_vc->base + reg); - - return 0; -} - -static const struct snd_kcontrol_new cq93vc_snd_controls[] = { - SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0), - SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0), -}; - -static int cq93vc_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u8 reg = cq93vc_read(codec, DAVINCI_VC_REG09) & ~DAVINCI_VC_REG09_MUTE; - - if (mute) - cq93vc_write(codec, DAVINCI_VC_REG09, - reg | DAVINCI_VC_REG09_MUTE); - else - cq93vc_write(codec, DAVINCI_VC_REG09, reg); - - return 0; -} - -static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct davinci_vc *davinci_vc = codec->control_data; - - switch (freq) { - case 22579200: - case 27000000: - case 33868800: - davinci_vc->cq93vc.sysclk = freq; - return 0; - } - - return -EINVAL; -} - -static int cq93vc_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - cq93vc_write(codec, DAVINCI_VC_REG12, - DAVINCI_VC_REG12_POWER_ALL_ON); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - cq93vc_write(codec, DAVINCI_VC_REG12, - DAVINCI_VC_REG12_POWER_ALL_OFF); - break; - case SND_SOC_BIAS_OFF: - /* force all power off */ - cq93vc_write(codec, DAVINCI_VC_REG12, - DAVINCI_VC_REG12_POWER_ALL_OFF); - break; - } - codec->dapm.bias_level = level; - - return 0; -} - -#define CQ93VC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000) -#define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE) - -static const struct snd_soc_dai_ops cq93vc_dai_ops = { - .digital_mute = cq93vc_mute, - .set_sysclk = cq93vc_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver cq93vc_dai = { - .name = "cq93vc-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = CQ93VC_RATES, - .formats = CQ93VC_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = CQ93VC_RATES, - .formats = CQ93VC_FORMATS,}, - .ops = &cq93vc_dai_ops, -}; - -static int cq93vc_resume(struct snd_soc_codec *codec) -{ - cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int cq93vc_probe(struct snd_soc_codec *codec) -{ - struct davinci_vc *davinci_vc = codec->dev->platform_data; - - davinci_vc->cq93vc.codec = codec; - codec->control_data = davinci_vc; - - /* Set controls */ - snd_soc_add_codec_controls(codec, cq93vc_snd_controls, - ARRAY_SIZE(cq93vc_snd_controls)); - - /* Off, with power on */ - cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int cq93vc_remove(struct snd_soc_codec *codec) -{ - cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_cq93vc = { - .read = cq93vc_read, - .write = cq93vc_write, - .set_bias_level = cq93vc_set_bias_level, - .probe = cq93vc_probe, - .remove = cq93vc_remove, - .resume = cq93vc_resume, -}; - -static int cq93vc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_cq93vc, &cq93vc_dai, 1); -} - -static int cq93vc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver cq93vc_codec_driver = { - .driver = { - .name = "cq93vc-codec", - .owner = THIS_MODULE, - }, - - .probe = cq93vc_platform_probe, - .remove = __devexit_p(cq93vc_platform_remove), -}; - -module_platform_driver(cq93vc_codec_driver); - -MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver"); -MODULE_AUTHOR("Miguel Aguilar"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/cs4270.c b/ANDROID_3.4.5/sound/soc/codecs/cs4270.c deleted file mode 100644 index 1d672f52..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cs4270.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * CS4270 ALSA SoC (ASoC) codec driver - * - * Author: Timur Tabi - * - * Copyright 2007-2009 Freescale Semiconductor, Inc. This file is licensed - * under the terms of the GNU General Public License version 2. This - * program is licensed "as is" without any warranty of any kind, whether - * express or implied. - * - * This is an ASoC device driver for the Cirrus Logic CS4270 codec. - * - * Current features/limitations: - * - * - Software mode is supported. Stand-alone mode is not supported. - * - Only I2C is supported, not SPI - * - Support for master and slave mode - * - The machine driver's 'startup' function must call - * cs4270_set_dai_sysclk() with the value of MCLK. - * - Only I2S and left-justified modes are supported - * - Power management is supported - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * The codec isn't really big-endian or little-endian, since the I2S - * interface requires data to be sent serially with the MSbit first. - * However, to support BE and LE I2S devices, we specify both here. That - * way, ALSA will always match the bit patterns. - */ -#define CS4270_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) - -/* CS4270 registers addresses */ -#define CS4270_CHIPID 0x01 /* Chip ID */ -#define CS4270_PWRCTL 0x02 /* Power Control */ -#define CS4270_MODE 0x03 /* Mode Control */ -#define CS4270_FORMAT 0x04 /* Serial Format, ADC/DAC Control */ -#define CS4270_TRANS 0x05 /* Transition Control */ -#define CS4270_MUTE 0x06 /* Mute Control */ -#define CS4270_VOLA 0x07 /* DAC Channel A Volume Control */ -#define CS4270_VOLB 0x08 /* DAC Channel B Volume Control */ - -#define CS4270_FIRSTREG 0x01 -#define CS4270_LASTREG 0x08 -#define CS4270_NUMREGS (CS4270_LASTREG - CS4270_FIRSTREG + 1) -#define CS4270_I2C_INCR 0x80 - -/* Bit masks for the CS4270 registers */ -#define CS4270_CHIPID_ID 0xF0 -#define CS4270_CHIPID_REV 0x0F -#define CS4270_PWRCTL_FREEZE 0x80 -#define CS4270_PWRCTL_PDN_ADC 0x20 -#define CS4270_PWRCTL_PDN_DAC 0x02 -#define CS4270_PWRCTL_PDN 0x01 -#define CS4270_PWRCTL_PDN_ALL \ - (CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | CS4270_PWRCTL_PDN) -#define CS4270_MODE_SPEED_MASK 0x30 -#define CS4270_MODE_1X 0x00 -#define CS4270_MODE_2X 0x10 -#define CS4270_MODE_4X 0x20 -#define CS4270_MODE_SLAVE 0x30 -#define CS4270_MODE_DIV_MASK 0x0E -#define CS4270_MODE_DIV1 0x00 -#define CS4270_MODE_DIV15 0x02 -#define CS4270_MODE_DIV2 0x04 -#define CS4270_MODE_DIV3 0x06 -#define CS4270_MODE_DIV4 0x08 -#define CS4270_MODE_POPGUARD 0x01 -#define CS4270_FORMAT_FREEZE_A 0x80 -#define CS4270_FORMAT_FREEZE_B 0x40 -#define CS4270_FORMAT_LOOPBACK 0x20 -#define CS4270_FORMAT_DAC_MASK 0x18 -#define CS4270_FORMAT_DAC_LJ 0x00 -#define CS4270_FORMAT_DAC_I2S 0x08 -#define CS4270_FORMAT_DAC_RJ16 0x18 -#define CS4270_FORMAT_DAC_RJ24 0x10 -#define CS4270_FORMAT_ADC_MASK 0x01 -#define CS4270_FORMAT_ADC_LJ 0x00 -#define CS4270_FORMAT_ADC_I2S 0x01 -#define CS4270_TRANS_ONE_VOL 0x80 -#define CS4270_TRANS_SOFT 0x40 -#define CS4270_TRANS_ZERO 0x20 -#define CS4270_TRANS_INV_ADC_A 0x08 -#define CS4270_TRANS_INV_ADC_B 0x10 -#define CS4270_TRANS_INV_DAC_A 0x02 -#define CS4270_TRANS_INV_DAC_B 0x04 -#define CS4270_TRANS_DEEMPH 0x01 -#define CS4270_MUTE_AUTO 0x20 -#define CS4270_MUTE_ADC_A 0x08 -#define CS4270_MUTE_ADC_B 0x10 -#define CS4270_MUTE_POLARITY 0x04 -#define CS4270_MUTE_DAC_A 0x01 -#define CS4270_MUTE_DAC_B 0x02 - -/* Power-on default values for the registers - * - * This array contains the power-on default values of the registers, with the - * exception of the "CHIPID" register (01h). The lower four bits of that - * register contain the hardware revision, so it is treated as volatile. - * - * Also note that on the CS4270, the first readable register is 1, but ASoC - * assumes the first register is 0. Therfore, the array must have an entry for - * register 0, but we use cs4270_reg_is_readable() to tell ASoC that it can't - * be read. - */ -static const u8 cs4270_default_reg_cache[CS4270_LASTREG + 1] = { - 0x00, 0x00, 0x00, 0x30, 0x00, 0x60, 0x20, 0x00, 0x00 -}; - -static const char *supply_names[] = { - "va", "vd", "vlc" -}; - -/* Private data for the CS4270 */ -struct cs4270_private { - enum snd_soc_control_type control_type; - unsigned int mclk; /* Input frequency of the MCLK pin */ - unsigned int mode; /* The mode (I2S or left-justified) */ - unsigned int slave_mode; - unsigned int manual_mute; - - /* power domain regulators */ - struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; -}; - -/** - * struct cs4270_mode_ratios - clock ratio tables - * @ratio: the ratio of MCLK to the sample rate - * @speed_mode: the Speed Mode bits to set in the Mode Control register for - * this ratio - * @mclk: the Ratio Select bits to set in the Mode Control register for this - * ratio - * - * The data for this chart is taken from Table 5 of the CS4270 reference - * manual. - * - * This table is used to determine how to program the Mode Control register. - * It is also used by cs4270_set_dai_sysclk() to tell ALSA which sampling - * rates the CS4270 currently supports. - * - * @speed_mode is the corresponding bit pattern to be written to the - * MODE bits of the Mode Control Register - * - * @mclk is the corresponding bit pattern to be wirten to the MCLK bits of - * the Mode Control Register. - * - * In situations where a single ratio is represented by multiple speed - * modes, we favor the slowest speed. E.g, for a ratio of 128, we pick - * double-speed instead of quad-speed. However, the CS4270 errata states - * that divide-By-1.5 can cause failures, so we avoid that mode where - * possible. - * - * Errata: There is an errata for the CS4270 where divide-by-1.5 does not - * work if Vd is 3.3V. If this effects you, select the - * CONFIG_SND_SOC_CS4270_VD33_ERRATA Kconfig option, and the driver will - * never select any sample rates that require divide-by-1.5. - */ -struct cs4270_mode_ratios { - unsigned int ratio; - u8 speed_mode; - u8 mclk; -}; - -static struct cs4270_mode_ratios cs4270_mode_ratios[] = { - {64, CS4270_MODE_4X, CS4270_MODE_DIV1}, -#ifndef CONFIG_SND_SOC_CS4270_VD33_ERRATA - {96, CS4270_MODE_4X, CS4270_MODE_DIV15}, -#endif - {128, CS4270_MODE_2X, CS4270_MODE_DIV1}, - {192, CS4270_MODE_4X, CS4270_MODE_DIV3}, - {256, CS4270_MODE_1X, CS4270_MODE_DIV1}, - {384, CS4270_MODE_2X, CS4270_MODE_DIV3}, - {512, CS4270_MODE_1X, CS4270_MODE_DIV2}, - {768, CS4270_MODE_1X, CS4270_MODE_DIV3}, - {1024, CS4270_MODE_1X, CS4270_MODE_DIV4} -}; - -/* The number of MCLK/LRCK ratios supported by the CS4270 */ -#define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) - -static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg) -{ - return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); -} - -static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg) -{ - /* Unreadable registers are considered volatile */ - if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) - return 1; - - return reg == CS4270_CHIPID; -} - -/** - * cs4270_set_dai_sysclk - determine the CS4270 samples rates. - * @codec_dai: the codec DAI - * @clk_id: the clock ID (ignored) - * @freq: the MCLK input frequency - * @dir: the clock direction (ignored) - * - * This function is used to tell the codec driver what the input MCLK - * frequency is. - * - * The value of MCLK is used to determine which sample rates are supported - * by the CS4270. The ratio of MCLK / Fs must be equal to one of nine - * supported values - 64, 96, 128, 192, 256, 384, 512, 768, and 1024. - * - * This function calculates the nine ratios and determines which ones match - * a standard sample rate. If there's a match, then it is added to the list - * of supported sample rates. - * - * This function must be called by the machine driver's 'startup' function, - * otherwise the list of supported sample rates will not be available in - * time for ALSA. - * - * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause - * theoretically possible sample rates to be enabled. Call it again with a - * proper value set one the external clock is set (most probably you would do - * that from a machine's driver 'hw_param' hook. - */ -static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - - cs4270->mclk = freq; - return 0; -} - -/** - * cs4270_set_dai_fmt - configure the codec for the selected audio format - * @codec_dai: the codec DAI - * @format: a SND_SOC_DAIFMT_x value indicating the data format - * - * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the - * codec accordingly. - * - * Currently, this function only supports SND_SOC_DAIFMT_I2S and - * SND_SOC_DAIFMT_LEFT_J. The CS4270 codec also supports right-justified - * data for playback only, but ASoC currently does not support different - * formats for playback vs. record. - */ -static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int format) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - - /* set DAI format */ - switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_LEFT_J: - cs4270->mode = format & SND_SOC_DAIFMT_FORMAT_MASK; - break; - default: - dev_err(codec->dev, "invalid dai format\n"); - return -EINVAL; - } - - /* set master/slave audio interface */ - switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - cs4270->slave_mode = 1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - cs4270->slave_mode = 0; - break; - default: - /* all other modes are unsupported by the hardware */ - dev_err(codec->dev, "Unknown master/slave configuration\n"); - return -EINVAL; - } - - return 0; -} - -/** - * cs4270_hw_params - program the CS4270 with the given hardware parameters. - * @substream: the audio stream - * @params: the hardware parameters to set - * @dai: the SOC DAI (ignored) - * - * This function programs the hardware with the values provided. - * Specifically, the sample rate and the data format. - * - * The .ops functions are used to provide board-specific data, like input - * frequencies, to this driver. This function takes that information, - * combines it with the hardware parameters provided, and programs the - * hardware accordingly. - */ -static int cs4270_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int ret; - unsigned int i; - unsigned int rate; - unsigned int ratio; - int reg; - - /* Figure out which MCLK/LRCK ratio to use */ - - rate = params_rate(params); /* Sampling rate, in Hz */ - ratio = cs4270->mclk / rate; /* MCLK/LRCK ratio */ - - for (i = 0; i < NUM_MCLK_RATIOS; i++) { - if (cs4270_mode_ratios[i].ratio == ratio) - break; - } - - if (i == NUM_MCLK_RATIOS) { - /* We did not find a matching ratio */ - dev_err(codec->dev, "could not find matching ratio\n"); - return -EINVAL; - } - - /* Set the sample rate */ - - reg = snd_soc_read(codec, CS4270_MODE); - reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); - reg |= cs4270_mode_ratios[i].mclk; - - if (cs4270->slave_mode) - reg |= CS4270_MODE_SLAVE; - else - reg |= cs4270_mode_ratios[i].speed_mode; - - ret = snd_soc_write(codec, CS4270_MODE, reg); - if (ret < 0) { - dev_err(codec->dev, "i2c write failed\n"); - return ret; - } - - /* Set the DAI format */ - - reg = snd_soc_read(codec, CS4270_FORMAT); - reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); - - switch (cs4270->mode) { - case SND_SOC_DAIFMT_I2S: - reg |= CS4270_FORMAT_DAC_I2S | CS4270_FORMAT_ADC_I2S; - break; - case SND_SOC_DAIFMT_LEFT_J: - reg |= CS4270_FORMAT_DAC_LJ | CS4270_FORMAT_ADC_LJ; - break; - default: - dev_err(codec->dev, "unknown dai format\n"); - return -EINVAL; - } - - ret = snd_soc_write(codec, CS4270_FORMAT, reg); - if (ret < 0) { - dev_err(codec->dev, "i2c write failed\n"); - return ret; - } - - return ret; -} - -/** - * cs4270_dai_mute - enable/disable the CS4270 external mute - * @dai: the SOC DAI - * @mute: 0 = disable mute, 1 = enable mute - * - * This function toggles the mute bits in the MUTE register. The CS4270's - * mute capability is intended for external muting circuitry, so if the - * board does not have the MUTEA or MUTEB pins connected to such circuitry, - * then this function will do nothing. - */ -static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int reg6; - - reg6 = snd_soc_read(codec, CS4270_MUTE); - - if (mute) - reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; - else { - reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); - reg6 |= cs4270->manual_mute; - } - - return snd_soc_write(codec, CS4270_MUTE, reg6); -} - -/** - * cs4270_soc_put_mute - put callback for the 'Master Playback switch' - * alsa control. - * @kcontrol: mixer control - * @ucontrol: control element information - * - * This function basically passes the arguments on to the generic - * snd_soc_put_volsw() function and saves the mute information in - * our private data structure. This is because we want to prevent - * cs4270_dai_mute() neglecting the user's decision to manually - * mute the codec's output. - * - * Returns 0 for success. - */ -static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int left = !ucontrol->value.integer.value[0]; - int right = !ucontrol->value.integer.value[1]; - - cs4270->manual_mute = (left ? CS4270_MUTE_DAC_A : 0) | - (right ? CS4270_MUTE_DAC_B : 0); - - return snd_soc_put_volsw(kcontrol, ucontrol); -} - -/* A list of non-DAPM controls that the CS4270 supports */ -static const struct snd_kcontrol_new cs4270_snd_controls[] = { - SOC_DOUBLE_R("Master Playback Volume", - CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1), - SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0), - SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0), - SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), - SOC_SINGLE("De-emphasis filter", CS4270_TRANS, 0, 1, 0), - SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), - SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), - SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1), - SOC_DOUBLE_EXT("Master Playback Switch", CS4270_MUTE, 0, 1, 1, 1, - snd_soc_get_volsw, cs4270_soc_put_mute), -}; - -static const struct snd_soc_dai_ops cs4270_dai_ops = { - .hw_params = cs4270_hw_params, - .set_sysclk = cs4270_set_dai_sysclk, - .set_fmt = cs4270_set_dai_fmt, - .digital_mute = cs4270_dai_mute, -}; - -static struct snd_soc_dai_driver cs4270_dai = { - .name = "cs4270-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 4000, - .rate_max = 216000, - .formats = CS4270_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 4000, - .rate_max = 216000, - .formats = CS4270_FORMATS, - }, - .ops = &cs4270_dai_ops, -}; - -/** - * cs4270_probe - ASoC probe function - * @pdev: platform device - * - * This function is called when ASoC has all the pieces it needs to - * instantiate a sound driver. - */ -static int cs4270_probe(struct snd_soc_codec *codec) -{ - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int i, ret; - - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will - * then do the I2C transactions itself. - */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs4270->control_type); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - return ret; - } - - /* Disable auto-mute. This feature appears to be buggy. In some - * situations, auto-mute will not deactivate when it should, so we want - * this feature disabled by default. An application (e.g. alsactl) can - * re-enabled it by using the controls. - */ - ret = snd_soc_update_bits(codec, CS4270_MUTE, CS4270_MUTE_AUTO, 0); - if (ret < 0) { - dev_err(codec->dev, "i2c write failed\n"); - return ret; - } - - /* Disable automatic volume control. The hardware enables, and it - * causes volume change commands to be delayed, sometimes until after - * playback has started. An application (e.g. alsactl) can - * re-enabled it by using the controls. - */ - ret = snd_soc_update_bits(codec, CS4270_TRANS, - CS4270_TRANS_SOFT | CS4270_TRANS_ZERO, 0); - if (ret < 0) { - dev_err(codec->dev, "i2c write failed\n"); - return ret; - } - - /* Add the non-DAPM controls */ - ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls, - ARRAY_SIZE(cs4270_snd_controls)); - if (ret < 0) { - dev_err(codec->dev, "failed to add controls\n"); - return ret; - } - - /* get the power supply regulators */ - for (i = 0; i < ARRAY_SIZE(supply_names); i++) - cs4270->supplies[i].supply = supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - if (ret < 0) - return ret; - - ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - if (ret < 0) - goto error_free_regulators; - - return 0; - -error_free_regulators: - regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - - return ret; -} - -/** - * cs4270_remove - ASoC remove function - * @pdev: platform device - * - * This function is the counterpart to cs4270_probe(). - */ -static int cs4270_remove(struct snd_soc_codec *codec) -{ - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - - regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); - - return 0; -}; - -#ifdef CONFIG_PM - -/* This suspend/resume implementation can handle both - a simple standby - * where the codec remains powered, and a full suspend, where the voltage - * domain the codec is connected to is teared down and/or any other hardware - * reset condition is asserted. - * - * The codec's own power saving features are enabled in the suspend callback, - * and all registers are written back to the hardware when resuming. - */ - -static int cs4270_soc_suspend(struct snd_soc_codec *codec) -{ - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int reg, ret; - - reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; - if (reg < 0) - return reg; - - ret = snd_soc_write(codec, CS4270_PWRCTL, reg); - if (ret < 0) - return ret; - - regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - - return 0; -} - -static int cs4270_soc_resume(struct snd_soc_codec *codec) -{ - struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); - int reg; - - regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), - cs4270->supplies); - - /* In case the device was put to hard reset during sleep, we need to - * wait 500ns here before any I2C communication. */ - ndelay(500); - - /* first restore the entire register cache ... */ - snd_soc_cache_sync(codec); - - /* ... then disable the power-down bits */ - reg = snd_soc_read(codec, CS4270_PWRCTL); - reg &= ~CS4270_PWRCTL_PDN_ALL; - - return snd_soc_write(codec, CS4270_PWRCTL, reg); -} -#else -#define cs4270_soc_suspend NULL -#define cs4270_soc_resume NULL -#endif /* CONFIG_PM */ - -/* - * ASoC codec driver structure - */ -static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { - .probe = cs4270_probe, - .remove = cs4270_remove, - .suspend = cs4270_soc_suspend, - .resume = cs4270_soc_resume, - .volatile_register = cs4270_reg_is_volatile, - .readable_register = cs4270_reg_is_readable, - .reg_cache_size = CS4270_LASTREG + 1, - .reg_word_size = sizeof(u8), - .reg_cache_default = cs4270_default_reg_cache, -}; - -/** - * cs4270_i2c_probe - initialize the I2C interface of the CS4270 - * @i2c_client: the I2C client object - * @id: the I2C device ID (ignored) - * - * This function is called whenever the I2C subsystem finds a device that - * matches the device ID given via a prior call to i2c_add_driver(). - */ -static int cs4270_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) -{ - struct cs4270_private *cs4270; - int ret; - - /* Verify that we have a CS4270 */ - - ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); - if (ret < 0) { - dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", - i2c_client->addr); - return ret; - } - /* The top four bits of the chip ID should be 1100. */ - if ((ret & 0xF0) != 0xC0) { - dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", - i2c_client->addr); - return -ENODEV; - } - - dev_info(&i2c_client->dev, "found device at i2c address %X\n", - i2c_client->addr); - dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); - - cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), - GFP_KERNEL); - if (!cs4270) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); - return -ENOMEM; - } - - i2c_set_clientdata(i2c_client, cs4270); - cs4270->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c_client->dev, - &soc_codec_device_cs4270, &cs4270_dai, 1); - return ret; -} - -/** - * cs4270_i2c_remove - remove an I2C device - * @i2c_client: the I2C client object - * - * This function is the counterpart to cs4270_i2c_probe(). - */ -static int cs4270_i2c_remove(struct i2c_client *i2c_client) -{ - snd_soc_unregister_codec(&i2c_client->dev); - return 0; -} - -/* - * cs4270_id - I2C device IDs supported by this driver - */ -static const struct i2c_device_id cs4270_id[] = { - {"cs4270", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, cs4270_id); - -/* - * cs4270_i2c_driver - I2C device identification - * - * This structure tells the I2C subsystem how to identify and support a - * given I2C device type. - */ -static struct i2c_driver cs4270_i2c_driver = { - .driver = { - .name = "cs4270", - .owner = THIS_MODULE, - }, - .id_table = cs4270_id, - .probe = cs4270_i2c_probe, - .remove = cs4270_i2c_remove, -}; - -static int __init cs4270_init(void) -{ - return i2c_add_driver(&cs4270_i2c_driver); -} -module_init(cs4270_init); - -static void __exit cs4270_exit(void) -{ - i2c_del_driver(&cs4270_i2c_driver); -} -module_exit(cs4270_exit); - -MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/cs4271.c b/ANDROID_3.4.5/sound/soc/codecs/cs4271.c deleted file mode 100644 index bf714128..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cs4271.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * CS4271 ASoC codec driver - * - * Copyright (c) 2010 Alexander Sverdlin - * - * 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. - * - * This driver support CS4271 codec being master or slave, working - * in control port mode, connected either via SPI or I2C. - * The data format accepted is I2S or left-justified. - * DAPM support not implemented. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE) -#define CS4271_PCM_RATES SNDRV_PCM_RATE_8000_192000 - -/* - * CS4271 registers - * High byte represents SPI chip address (0x10) + write command (0) - * Low byte - codec register address - */ -#define CS4271_MODE1 0x2001 /* Mode Control 1 */ -#define CS4271_DACCTL 0x2002 /* DAC Control */ -#define CS4271_DACVOL 0x2003 /* DAC Volume & Mixing Control */ -#define CS4271_VOLA 0x2004 /* DAC Channel A Volume Control */ -#define CS4271_VOLB 0x2005 /* DAC Channel B Volume Control */ -#define CS4271_ADCCTL 0x2006 /* ADC Control */ -#define CS4271_MODE2 0x2007 /* Mode Control 2 */ -#define CS4271_CHIPID 0x2008 /* Chip ID */ - -#define CS4271_FIRSTREG CS4271_MODE1 -#define CS4271_LASTREG CS4271_MODE2 -#define CS4271_NR_REGS ((CS4271_LASTREG & 0xFF) + 1) - -/* Bit masks for the CS4271 registers */ -#define CS4271_MODE1_MODE_MASK 0xC0 -#define CS4271_MODE1_MODE_1X 0x00 -#define CS4271_MODE1_MODE_2X 0x80 -#define CS4271_MODE1_MODE_4X 0xC0 - -#define CS4271_MODE1_DIV_MASK 0x30 -#define CS4271_MODE1_DIV_1 0x00 -#define CS4271_MODE1_DIV_15 0x10 -#define CS4271_MODE1_DIV_2 0x20 -#define CS4271_MODE1_DIV_3 0x30 - -#define CS4271_MODE1_MASTER 0x08 - -#define CS4271_MODE1_DAC_DIF_MASK 0x07 -#define CS4271_MODE1_DAC_DIF_LJ 0x00 -#define CS4271_MODE1_DAC_DIF_I2S 0x01 -#define CS4271_MODE1_DAC_DIF_RJ16 0x02 -#define CS4271_MODE1_DAC_DIF_RJ24 0x03 -#define CS4271_MODE1_DAC_DIF_RJ20 0x04 -#define CS4271_MODE1_DAC_DIF_RJ18 0x05 - -#define CS4271_DACCTL_AMUTE 0x80 -#define CS4271_DACCTL_IF_SLOW 0x40 - -#define CS4271_DACCTL_DEM_MASK 0x30 -#define CS4271_DACCTL_DEM_DIS 0x00 -#define CS4271_DACCTL_DEM_441 0x10 -#define CS4271_DACCTL_DEM_48 0x20 -#define CS4271_DACCTL_DEM_32 0x30 - -#define CS4271_DACCTL_SVRU 0x08 -#define CS4271_DACCTL_SRD 0x04 -#define CS4271_DACCTL_INVA 0x02 -#define CS4271_DACCTL_INVB 0x01 - -#define CS4271_DACVOL_BEQUA 0x40 -#define CS4271_DACVOL_SOFT 0x20 -#define CS4271_DACVOL_ZEROC 0x10 - -#define CS4271_DACVOL_ATAPI_MASK 0x0F -#define CS4271_DACVOL_ATAPI_M_M 0x00 -#define CS4271_DACVOL_ATAPI_M_BR 0x01 -#define CS4271_DACVOL_ATAPI_M_BL 0x02 -#define CS4271_DACVOL_ATAPI_M_BLR2 0x03 -#define CS4271_DACVOL_ATAPI_AR_M 0x04 -#define CS4271_DACVOL_ATAPI_AR_BR 0x05 -#define CS4271_DACVOL_ATAPI_AR_BL 0x06 -#define CS4271_DACVOL_ATAPI_AR_BLR2 0x07 -#define CS4271_DACVOL_ATAPI_AL_M 0x08 -#define CS4271_DACVOL_ATAPI_AL_BR 0x09 -#define CS4271_DACVOL_ATAPI_AL_BL 0x0A -#define CS4271_DACVOL_ATAPI_AL_BLR2 0x0B -#define CS4271_DACVOL_ATAPI_ALR2_M 0x0C -#define CS4271_DACVOL_ATAPI_ALR2_BR 0x0D -#define CS4271_DACVOL_ATAPI_ALR2_BL 0x0E -#define CS4271_DACVOL_ATAPI_ALR2_BLR2 0x0F - -#define CS4271_VOLA_MUTE 0x80 -#define CS4271_VOLA_VOL_MASK 0x7F -#define CS4271_VOLB_MUTE 0x80 -#define CS4271_VOLB_VOL_MASK 0x7F - -#define CS4271_ADCCTL_DITHER16 0x20 - -#define CS4271_ADCCTL_ADC_DIF_MASK 0x10 -#define CS4271_ADCCTL_ADC_DIF_LJ 0x00 -#define CS4271_ADCCTL_ADC_DIF_I2S 0x10 - -#define CS4271_ADCCTL_MUTEA 0x08 -#define CS4271_ADCCTL_MUTEB 0x04 -#define CS4271_ADCCTL_HPFDA 0x02 -#define CS4271_ADCCTL_HPFDB 0x01 - -#define CS4271_MODE2_LOOP 0x10 -#define CS4271_MODE2_MUTECAEQUB 0x08 -#define CS4271_MODE2_FREEZE 0x04 -#define CS4271_MODE2_CPEN 0x02 -#define CS4271_MODE2_PDN 0x01 - -#define CS4271_CHIPID_PART_MASK 0xF0 -#define CS4271_CHIPID_REV_MASK 0x0F - -/* - * Default CS4271 power-up configuration - * Array contains non-existing in hw register at address 0 - * Array do not include Chip ID, as codec driver does not use - * registers read operations at all - */ -static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = { - 0, - 0, - CS4271_DACCTL_AMUTE, - CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, - 0, - 0, - 0, - 0, -}; - -struct cs4271_private { - /* SND_SOC_I2C or SND_SOC_SPI */ - enum snd_soc_control_type bus_type; - unsigned int mclk; - bool master; - bool deemph; - /* Current sample rate for de-emphasis control */ - int rate; - /* GPIO driving Reset pin, if any */ - int gpio_nreset; - /* GPIO that disable serial bus, if any */ - int gpio_disable; -}; - -/* - * @freq is the desired MCLK rate - * MCLK rate should (c) be the sample rate, multiplied by one of the - * ratios listed in cs4271_mclk_fs_ratios table - */ -static int cs4271_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - - cs4271->mclk = freq; - return 0; -} - -static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int format) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - unsigned int val = 0; - int ret; - - switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - cs4271->master = 0; - break; - case SND_SOC_DAIFMT_CBM_CFM: - cs4271->master = 1; - val |= CS4271_MODE1_MASTER; - break; - default: - dev_err(codec->dev, "Invalid DAI format\n"); - return -EINVAL; - } - - switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_LEFT_J: - val |= CS4271_MODE1_DAC_DIF_LJ; - ret = snd_soc_update_bits(codec, CS4271_ADCCTL, - CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ); - if (ret < 0) - return ret; - break; - case SND_SOC_DAIFMT_I2S: - val |= CS4271_MODE1_DAC_DIF_I2S; - ret = snd_soc_update_bits(codec, CS4271_ADCCTL, - CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S); - if (ret < 0) - return ret; - break; - default: - dev_err(codec->dev, "Invalid DAI format\n"); - return -EINVAL; - } - - ret = snd_soc_update_bits(codec, CS4271_MODE1, - CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val); - if (ret < 0) - return ret; - return 0; -} - -static int cs4271_deemph[] = {0, 44100, 48000, 32000}; - -static int cs4271_set_deemph(struct snd_soc_codec *codec) -{ - struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - int i, ret; - int val = CS4271_DACCTL_DEM_DIS; - - if (cs4271->deemph) { - /* Find closest de-emphasis freq */ - val = 1; - for (i = 2; i < ARRAY_SIZE(cs4271_deemph); i++) - if (abs(cs4271_deemph[i] - cs4271->rate) < - abs(cs4271_deemph[val] - cs4271->rate)) - val = i; - val <<= 4; - } - - ret = snd_soc_update_bits(codec, CS4271_DACCTL, - CS4271_DACCTL_DEM_MASK, val); - if (ret < 0) - return ret; - return 0; -} - -static int cs4271_get_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = cs4271->deemph; - return 0; -} - -static int cs4271_put_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - - cs4271->deemph = ucontrol->value.enumerated.item[0]; - return cs4271_set_deemph(codec); -} - -struct cs4271_clk_cfg { - bool master; /* codec mode */ - u8 speed_mode; /* codec speed mode: 1x, 2x, 4x */ - unsigned short ratio; /* MCLK / sample rate */ - u8 ratio_mask; /* ratio bit mask for Master mode */ -}; - -static struct cs4271_clk_cfg cs4271_clk_tab[] = { - {1, CS4271_MODE1_MODE_1X, 256, CS4271_MODE1_DIV_1}, - {1, CS4271_MODE1_MODE_1X, 384, CS4271_MODE1_DIV_15}, - {1, CS4271_MODE1_MODE_1X, 512, CS4271_MODE1_DIV_2}, - {1, CS4271_MODE1_MODE_1X, 768, CS4271_MODE1_DIV_3}, - {1, CS4271_MODE1_MODE_2X, 128, CS4271_MODE1_DIV_1}, - {1, CS4271_MODE1_MODE_2X, 192, CS4271_MODE1_DIV_15}, - {1, CS4271_MODE1_MODE_2X, 256, CS4271_MODE1_DIV_2}, - {1, CS4271_MODE1_MODE_2X, 384, CS4271_MODE1_DIV_3}, - {1, CS4271_MODE1_MODE_4X, 64, CS4271_MODE1_DIV_1}, - {1, CS4271_MODE1_MODE_4X, 96, CS4271_MODE1_DIV_15}, - {1, CS4271_MODE1_MODE_4X, 128, CS4271_MODE1_DIV_2}, - {1, CS4271_MODE1_MODE_4X, 192, CS4271_MODE1_DIV_3}, - {0, CS4271_MODE1_MODE_1X, 256, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_1X, 384, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_1X, 512, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_1X, 768, CS4271_MODE1_DIV_2}, - {0, CS4271_MODE1_MODE_1X, 1024, CS4271_MODE1_DIV_2}, - {0, CS4271_MODE1_MODE_2X, 128, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_2X, 192, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_2X, 256, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_2X, 384, CS4271_MODE1_DIV_2}, - {0, CS4271_MODE1_MODE_2X, 512, CS4271_MODE1_DIV_2}, - {0, CS4271_MODE1_MODE_4X, 64, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_4X, 96, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_4X, 128, CS4271_MODE1_DIV_1}, - {0, CS4271_MODE1_MODE_4X, 192, CS4271_MODE1_DIV_2}, - {0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2}, -}; - -#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab) - -static int cs4271_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - int i, ret; - unsigned int ratio, val; - - cs4271->rate = params_rate(params); - - /* Configure DAC */ - if (cs4271->rate < 50000) - val = CS4271_MODE1_MODE_1X; - else if (cs4271->rate < 100000) - val = CS4271_MODE1_MODE_2X; - else - val = CS4271_MODE1_MODE_4X; - - ratio = cs4271->mclk / cs4271->rate; - for (i = 0; i < CS4171_NR_RATIOS; i++) - if ((cs4271_clk_tab[i].master == cs4271->master) && - (cs4271_clk_tab[i].speed_mode == val) && - (cs4271_clk_tab[i].ratio == ratio)) - break; - - if (i == CS4171_NR_RATIOS) { - dev_err(codec->dev, "Invalid sample rate\n"); - return -EINVAL; - } - - val |= cs4271_clk_tab[i].ratio_mask; - - ret = snd_soc_update_bits(codec, CS4271_MODE1, - CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); - if (ret < 0) - return ret; - - return cs4271_set_deemph(codec); -} - -static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - int ret; - int val_a = 0; - int val_b = 0; - - if (mute) { - val_a = CS4271_VOLA_MUTE; - val_b = CS4271_VOLB_MUTE; - } - - ret = snd_soc_update_bits(codec, CS4271_VOLA, CS4271_VOLA_MUTE, val_a); - if (ret < 0) - return ret; - ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b); - if (ret < 0) - return ret; - - return 0; -} - -/* CS4271 controls */ -static DECLARE_TLV_DB_SCALE(cs4271_dac_tlv, -12700, 100, 0); - -static const struct snd_kcontrol_new cs4271_snd_controls[] = { - SOC_DOUBLE_R_TLV("Master Playback Volume", CS4271_VOLA, CS4271_VOLB, - 0, 0x7F, 1, cs4271_dac_tlv), - SOC_SINGLE("Digital Loopback Switch", CS4271_MODE2, 4, 1, 0), - SOC_SINGLE("Soft Ramp Switch", CS4271_DACVOL, 5, 1, 0), - SOC_SINGLE("Zero Cross Switch", CS4271_DACVOL, 4, 1, 0), - SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0, - cs4271_get_deemph, cs4271_put_deemph), - SOC_SINGLE("Auto-Mute Switch", CS4271_DACCTL, 7, 1, 0), - SOC_SINGLE("Slow Roll Off Filter Switch", CS4271_DACCTL, 6, 1, 0), - SOC_SINGLE("Soft Volume Ramp-Up Switch", CS4271_DACCTL, 3, 1, 0), - SOC_SINGLE("Soft Ramp-Down Switch", CS4271_DACCTL, 2, 1, 0), - SOC_SINGLE("Left Channel Inversion Switch", CS4271_DACCTL, 1, 1, 0), - SOC_SINGLE("Right Channel Inversion Switch", CS4271_DACCTL, 0, 1, 0), - SOC_DOUBLE("Master Capture Switch", CS4271_ADCCTL, 3, 2, 1, 1), - SOC_SINGLE("Dither 16-Bit Data Switch", CS4271_ADCCTL, 5, 1, 0), - SOC_DOUBLE("High Pass Filter Switch", CS4271_ADCCTL, 1, 0, 1, 1), - SOC_DOUBLE_R("Master Playback Switch", CS4271_VOLA, CS4271_VOLB, - 7, 1, 1), -}; - -static const struct snd_soc_dai_ops cs4271_dai_ops = { - .hw_params = cs4271_hw_params, - .set_sysclk = cs4271_set_dai_sysclk, - .set_fmt = cs4271_set_dai_fmt, - .digital_mute = cs4271_digital_mute, -}; - -static struct snd_soc_dai_driver cs4271_dai = { - .name = "cs4271-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = CS4271_PCM_RATES, - .formats = CS4271_PCM_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = CS4271_PCM_RATES, - .formats = CS4271_PCM_FORMATS, - }, - .ops = &cs4271_dai_ops, - .symmetric_rates = 1, -}; - -#ifdef CONFIG_PM -static int cs4271_soc_suspend(struct snd_soc_codec *codec) -{ - int ret; - /* Set power-down bit */ - ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, - CS4271_MODE2_PDN); - if (ret < 0) - return ret; - return 0; -} - -static int cs4271_soc_resume(struct snd_soc_codec *codec) -{ - int ret; - /* Restore codec state */ - ret = snd_soc_cache_sync(codec); - if (ret < 0) - return ret; - /* then disable the power-down bit */ - ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); - if (ret < 0) - return ret; - return 0; -} -#else -#define cs4271_soc_suspend NULL -#define cs4271_soc_resume NULL -#endif /* CONFIG_PM */ - -static int cs4271_probe(struct snd_soc_codec *codec) -{ - struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; - int ret; - int gpio_nreset = -EINVAL; - - if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset)) - gpio_nreset = cs4271plat->gpio_nreset; - - if (gpio_nreset >= 0) - if (gpio_request(gpio_nreset, "CS4271 Reset")) - gpio_nreset = -EINVAL; - if (gpio_nreset >= 0) { - /* Reset codec */ - gpio_direction_output(gpio_nreset, 0); - udelay(1); - gpio_set_value(gpio_nreset, 1); - /* Give the codec time to wake up */ - udelay(1); - } - - cs4271->gpio_nreset = gpio_nreset; - - /* - * In case of I2C, chip address specified in board data. - * So cache IO operations use 8 bit codec register address. - * In case of SPI, chip address and register address - * passed together as 16 bit value. - * Anyway, register address is masked with 0xFF inside - * soc-cache code. - */ - if (cs4271->bus_type == SND_SOC_SPI) - ret = snd_soc_codec_set_cache_io(codec, 16, 8, - cs4271->bus_type); - else - ret = snd_soc_codec_set_cache_io(codec, 8, 8, - cs4271->bus_type); - if (ret) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = snd_soc_update_bits(codec, CS4271_MODE2, - CS4271_MODE2_PDN | CS4271_MODE2_CPEN, - CS4271_MODE2_PDN | CS4271_MODE2_CPEN); - if (ret < 0) - return ret; - ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); - if (ret < 0) - return ret; - /* Power-up sequence requires 85 uS */ - udelay(85); - - return snd_soc_add_codec_controls(codec, cs4271_snd_controls, - ARRAY_SIZE(cs4271_snd_controls)); -} - -static int cs4271_remove(struct snd_soc_codec *codec) -{ - struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - int gpio_nreset; - - gpio_nreset = cs4271->gpio_nreset; - - if (gpio_is_valid(gpio_nreset)) { - /* Set codec to the reset state */ - gpio_set_value(gpio_nreset, 0); - gpio_free(gpio_nreset); - } - - return 0; -}; - -static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { - .probe = cs4271_probe, - .remove = cs4271_remove, - .suspend = cs4271_soc_suspend, - .resume = cs4271_soc_resume, - .reg_cache_default = cs4271_dflt_reg, - .reg_cache_size = ARRAY_SIZE(cs4271_dflt_reg), - .reg_word_size = sizeof(cs4271_dflt_reg[0]), - .compress_type = SND_SOC_FLAT_COMPRESSION, -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit cs4271_spi_probe(struct spi_device *spi) -{ - struct cs4271_private *cs4271; - - cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL); - if (!cs4271) - return -ENOMEM; - - spi_set_drvdata(spi, cs4271); - cs4271->bus_type = SND_SOC_SPI; - - return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, - &cs4271_dai, 1); -} - -static int __devexit cs4271_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver cs4271_spi_driver = { - .driver = { - .name = "cs4271", - .owner = THIS_MODULE, - }, - .probe = cs4271_spi_probe, - .remove = __devexit_p(cs4271_spi_remove), -}; -#endif /* defined(CONFIG_SPI_MASTER) */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static const struct i2c_device_id cs4271_i2c_id[] = { - {"cs4271", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); - -static int __devinit cs4271_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct cs4271_private *cs4271; - - cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL); - if (!cs4271) - return -ENOMEM; - - i2c_set_clientdata(client, cs4271); - cs4271->bus_type = SND_SOC_I2C; - - return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, - &cs4271_dai, 1); -} - -static int __devexit cs4271_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static struct i2c_driver cs4271_i2c_driver = { - .driver = { - .name = "cs4271", - .owner = THIS_MODULE, - }, - .id_table = cs4271_i2c_id, - .probe = cs4271_i2c_probe, - .remove = __devexit_p(cs4271_i2c_remove), -}; -#endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */ - -/* - * We only register our serial bus driver here without - * assignment to particular chip. So if any of the below - * fails, there is some problem with I2C or SPI subsystem. - * In most cases this module will be compiled with support - * of only one serial bus. - */ -static int __init cs4271_modinit(void) -{ - int ret; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&cs4271_i2c_driver); - if (ret) { - pr_err("Failed to register CS4271 I2C driver: %d\n", ret); - return ret; - } -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&cs4271_spi_driver); - if (ret) { - pr_err("Failed to register CS4271 SPI driver: %d\n", ret); - return ret; - } -#endif - - return 0; -} -module_init(cs4271_modinit); - -static void __exit cs4271_modexit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&cs4271_spi_driver); -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&cs4271_i2c_driver); -#endif -} -module_exit(cs4271_modexit); - -MODULE_AUTHOR("Alexander Sverdlin "); -MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/cs42l51.c b/ANDROID_3.4.5/sound/soc/codecs/cs42l51.c deleted file mode 100644 index a8bf588e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cs42l51.c +++ /dev/null @@ -1,639 +0,0 @@ -/* - * cs42l51.c - * - * ASoC Driver for Cirrus Logic CS42L51 codecs - * - * Copyright (c) 2010 Arnaud Patard - * - * Based on cs4270.c - Copyright (c) Freescale Semiconductor - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - * - * For now: - * - Only I2C is support. Not SPI - * - master mode *NOT* supported - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cs42l51.h" - -enum master_slave_mode { - MODE_SLAVE, - MODE_SLAVE_AUTO, - MODE_MASTER, -}; - -struct cs42l51_private { - enum snd_soc_control_type control_type; - unsigned int mclk; - unsigned int audio_mode; /* The mode (I2S or left-justified) */ - enum master_slave_mode func; -}; - -#define CS42L51_FORMATS ( \ - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) - -static int cs42l51_fill_cache(struct snd_soc_codec *codec) -{ - u8 *cache = codec->reg_cache + 1; - struct i2c_client *i2c_client = to_i2c_client(codec->dev); - s32 length; - - length = i2c_smbus_read_i2c_block_data(i2c_client, - CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache); - if (length != CS42L51_NUMREGS) { - dev_err(&i2c_client->dev, - "I2C read failure, addr=0x%x (ret=%d vs %d)\n", - i2c_client->addr, length, CS42L51_NUMREGS); - return -EIO; - } - - return 0; -} - -static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned long value = snd_soc_read(codec, CS42L51_PCM_MIXER)&3; - - switch (value) { - default: - case 0: - ucontrol->value.integer.value[0] = 0; - break; - /* same value : (L+R)/2 and (R+L)/2 */ - case 1: - case 2: - ucontrol->value.integer.value[0] = 1; - break; - case 3: - ucontrol->value.integer.value[0] = 2; - break; - } - - return 0; -} - -#define CHAN_MIX_NORMAL 0x00 -#define CHAN_MIX_BOTH 0x55 -#define CHAN_MIX_SWAP 0xFF - -static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned char val; - - switch (ucontrol->value.integer.value[0]) { - default: - case 0: - val = CHAN_MIX_NORMAL; - break; - case 1: - val = CHAN_MIX_BOTH; - break; - case 2: - val = CHAN_MIX_SWAP; - break; - } - - snd_soc_write(codec, CS42L51_PCM_MIXER, val); - - return 1; -} - -static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0); -static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); -/* This is a lie. after -102 db, it stays at -102 */ -/* maybe a range would be better */ -static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0); - -static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0); -static const char *chan_mix[] = { - "L R", - "L+R", - "R L", -}; - -static const struct soc_enum cs42l51_chan_mix = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix); - -static const struct snd_kcontrol_new cs42l51_snd_controls[] = { - SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", - CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, - 7, 0xffffff99, 0x18, adc_pcm_tlv), - SOC_DOUBLE_R("PCM Playback Switch", - CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1), - SOC_DOUBLE_R_SX_TLV("Analog Playback Volume", - CS42L51_AOUTA_VOL, CS42L51_AOUTB_VOL, - 8, 0xffffff19, 0x18, aout_tlv), - SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", - CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, - 7, 0xffffff99, 0x18, adc_pcm_tlv), - SOC_DOUBLE_R("ADC Mixer Switch", - CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1), - SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), - SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0), - SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0), - SOC_SINGLE("Zero Cross Switch", CS42L51_DAC_CTL, 0, 0, 0), - SOC_DOUBLE_TLV("Mic Boost Volume", - CS42L51_MIC_CTL, 0, 1, 1, 0, boost_tlv), - SOC_SINGLE_TLV("Bass Volume", CS42L51_TONE_CTL, 0, 0xf, 1, tone_tlv), - SOC_SINGLE_TLV("Treble Volume", CS42L51_TONE_CTL, 4, 0xf, 1, tone_tlv), - SOC_ENUM_EXT("PCM channel mixer", - cs42l51_chan_mix, - cs42l51_get_chan_mix, cs42l51_set_chan_mix), -}; - -/* - * to power down, one must: - * 1.) Enable the PDN bit - * 2.) enable power-down for the select channels - * 3.) disable the PDN bit. - */ -static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - switch (event) { - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1, - CS42L51_POWER_CTL1_PDN, - CS42L51_POWER_CTL1_PDN); - break; - default: - case SND_SOC_DAPM_POST_PMD: - snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1, - CS42L51_POWER_CTL1_PDN, 0); - break; - } - - return 0; -} - -static const char *cs42l51_dac_names[] = {"Direct PCM", - "DSP PCM", "ADC"}; -static const struct soc_enum cs42l51_dac_mux_enum = - SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names); -static const struct snd_kcontrol_new cs42l51_dac_mux_controls = - SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum); - -static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left", - "MIC Left", "MIC+preamp Left"}; -static const struct soc_enum cs42l51_adcl_mux_enum = - SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names); -static const struct snd_kcontrol_new cs42l51_adcl_mux_controls = - SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum); - -static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right", - "MIC Right", "MIC+preamp Right"}; -static const struct soc_enum cs42l51_adcr_mux_enum = - SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names); -static const struct snd_kcontrol_new cs42l51_adcr_mux_controls = - SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum); - -static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = { - SND_SOC_DAPM_MICBIAS("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1), - SND_SOC_DAPM_PGA_E("Left PGA", CS42L51_POWER_CTL1, 3, 1, NULL, 0, - cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), - SND_SOC_DAPM_PGA_E("Right PGA", CS42L51_POWER_CTL1, 4, 1, NULL, 0, - cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), - SND_SOC_DAPM_ADC_E("Left ADC", "Left HiFi Capture", - CS42L51_POWER_CTL1, 1, 1, - cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), - SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture", - CS42L51_POWER_CTL1, 2, 1, - cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), - SND_SOC_DAPM_DAC_E("Left DAC", "Left HiFi Playback", - CS42L51_POWER_CTL1, 5, 1, - cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), - SND_SOC_DAPM_DAC_E("Right DAC", "Right HiFi Playback", - CS42L51_POWER_CTL1, 6, 1, - cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), - - /* analog/mic */ - SND_SOC_DAPM_INPUT("AIN1L"), - SND_SOC_DAPM_INPUT("AIN1R"), - SND_SOC_DAPM_INPUT("AIN2L"), - SND_SOC_DAPM_INPUT("AIN2R"), - SND_SOC_DAPM_INPUT("MICL"), - SND_SOC_DAPM_INPUT("MICR"), - - SND_SOC_DAPM_MIXER("Mic Preamp Left", - CS42L51_MIC_POWER_CTL, 2, 1, NULL, 0), - SND_SOC_DAPM_MIXER("Mic Preamp Right", - CS42L51_MIC_POWER_CTL, 3, 1, NULL, 0), - - /* HP */ - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - - /* mux */ - SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0, - &cs42l51_dac_mux_controls), - SND_SOC_DAPM_MUX("PGA-ADC Mux Left", SND_SOC_NOPM, 0, 0, - &cs42l51_adcl_mux_controls), - SND_SOC_DAPM_MUX("PGA-ADC Mux Right", SND_SOC_NOPM, 0, 0, - &cs42l51_adcr_mux_controls), -}; - -static const struct snd_soc_dapm_route cs42l51_routes[] = { - {"HPL", NULL, "Left DAC"}, - {"HPR", NULL, "Right DAC"}, - - {"Left ADC", NULL, "Left PGA"}, - {"Right ADC", NULL, "Right PGA"}, - - {"Mic Preamp Left", NULL, "MICL"}, - {"Mic Preamp Right", NULL, "MICR"}, - - {"PGA-ADC Mux Left", "AIN1 Left", "AIN1L" }, - {"PGA-ADC Mux Left", "AIN2 Left", "AIN2L" }, - {"PGA-ADC Mux Left", "MIC Left", "MICL" }, - {"PGA-ADC Mux Left", "MIC+preamp Left", "Mic Preamp Left" }, - {"PGA-ADC Mux Right", "AIN1 Right", "AIN1R" }, - {"PGA-ADC Mux Right", "AIN2 Right", "AIN2R" }, - {"PGA-ADC Mux Right", "MIC Right", "MICR" }, - {"PGA-ADC Mux Right", "MIC+preamp Right", "Mic Preamp Right" }, - - {"Left PGA", NULL, "PGA-ADC Mux Left"}, - {"Right PGA", NULL, "PGA-ADC Mux Right"}, -}; - -static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int format) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); - - switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_LEFT_J: - case SND_SOC_DAIFMT_RIGHT_J: - cs42l51->audio_mode = format & SND_SOC_DAIFMT_FORMAT_MASK; - break; - default: - dev_err(codec->dev, "invalid DAI format\n"); - return -EINVAL; - } - - switch (format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - cs42l51->func = MODE_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: - cs42l51->func = MODE_SLAVE_AUTO; - break; - default: - dev_err(codec->dev, "Unknown master/slave configuration\n"); - return -EINVAL; - } - - return 0; -} - -struct cs42l51_ratios { - unsigned int ratio; - unsigned char speed_mode; - unsigned char mclk; -}; - -static struct cs42l51_ratios slave_ratios[] = { - { 512, CS42L51_QSM_MODE, 0 }, { 768, CS42L51_QSM_MODE, 0 }, - { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 }, - { 2048, CS42L51_QSM_MODE, 0 }, { 3072, CS42L51_QSM_MODE, 0 }, - { 256, CS42L51_HSM_MODE, 0 }, { 384, CS42L51_HSM_MODE, 0 }, - { 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 }, - { 1024, CS42L51_HSM_MODE, 0 }, { 1536, CS42L51_HSM_MODE, 0 }, - { 128, CS42L51_SSM_MODE, 0 }, { 192, CS42L51_SSM_MODE, 0 }, - { 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 }, - { 512, CS42L51_SSM_MODE, 0 }, { 768, CS42L51_SSM_MODE, 0 }, - { 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 }, - { 256, CS42L51_DSM_MODE, 0 }, { 384, CS42L51_DSM_MODE, 0 }, -}; - -static struct cs42l51_ratios slave_auto_ratios[] = { - { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 }, - { 2048, CS42L51_QSM_MODE, 1 }, { 3072, CS42L51_QSM_MODE, 1 }, - { 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 }, - { 1024, CS42L51_HSM_MODE, 1 }, { 1536, CS42L51_HSM_MODE, 1 }, - { 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 }, - { 512, CS42L51_SSM_MODE, 1 }, { 768, CS42L51_SSM_MODE, 1 }, - { 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 }, - { 256, CS42L51_DSM_MODE, 1 }, { 384, CS42L51_DSM_MODE, 1 }, -}; - -static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); - - cs42l51->mclk = freq; - return 0; -} - -static int cs42l51_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); - int ret; - unsigned int i; - unsigned int rate; - unsigned int ratio; - struct cs42l51_ratios *ratios = NULL; - int nr_ratios = 0; - int intf_ctl, power_ctl, fmt; - - switch (cs42l51->func) { - case MODE_MASTER: - return -EINVAL; - case MODE_SLAVE: - ratios = slave_ratios; - nr_ratios = ARRAY_SIZE(slave_ratios); - break; - case MODE_SLAVE_AUTO: - ratios = slave_auto_ratios; - nr_ratios = ARRAY_SIZE(slave_auto_ratios); - break; - } - - /* Figure out which MCLK/LRCK ratio to use */ - rate = params_rate(params); /* Sampling rate, in Hz */ - ratio = cs42l51->mclk / rate; /* MCLK/LRCK ratio */ - for (i = 0; i < nr_ratios; i++) { - if (ratios[i].ratio == ratio) - break; - } - - if (i == nr_ratios) { - /* We did not find a matching ratio */ - dev_err(codec->dev, "could not find matching ratio\n"); - return -EINVAL; - } - - intf_ctl = snd_soc_read(codec, CS42L51_INTF_CTL); - power_ctl = snd_soc_read(codec, CS42L51_MIC_POWER_CTL); - - intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S - | CS42L51_INTF_CTL_DAC_FORMAT(7)); - power_ctl &= ~(CS42L51_MIC_POWER_CTL_SPEED(3) - | CS42L51_MIC_POWER_CTL_MCLK_DIV2); - - switch (cs42l51->func) { - case MODE_MASTER: - intf_ctl |= CS42L51_INTF_CTL_MASTER; - power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode); - break; - case MODE_SLAVE: - power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode); - break; - case MODE_SLAVE_AUTO: - power_ctl |= CS42L51_MIC_POWER_CTL_AUTO; - break; - } - - switch (cs42l51->audio_mode) { - case SND_SOC_DAIFMT_I2S: - intf_ctl |= CS42L51_INTF_CTL_ADC_I2S; - intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_I2S); - break; - case SND_SOC_DAIFMT_LEFT_J: - intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24); - break; - case SND_SOC_DAIFMT_RIGHT_J: - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: - fmt = CS42L51_DAC_DIF_RJ16; - break; - case SNDRV_PCM_FORMAT_S18_3LE: - case SNDRV_PCM_FORMAT_S18_3BE: - fmt = CS42L51_DAC_DIF_RJ18; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - case SNDRV_PCM_FORMAT_S20_3BE: - fmt = CS42L51_DAC_DIF_RJ20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S24_BE: - fmt = CS42L51_DAC_DIF_RJ24; - break; - default: - dev_err(codec->dev, "unknown format\n"); - return -EINVAL; - } - intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(fmt); - break; - default: - dev_err(codec->dev, "unknown format\n"); - return -EINVAL; - } - - if (ratios[i].mclk) - power_ctl |= CS42L51_MIC_POWER_CTL_MCLK_DIV2; - - ret = snd_soc_write(codec, CS42L51_INTF_CTL, intf_ctl); - if (ret < 0) - return ret; - - ret = snd_soc_write(codec, CS42L51_MIC_POWER_CTL, power_ctl); - if (ret < 0) - return ret; - - return 0; -} - -static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - int reg; - int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE; - - reg = snd_soc_read(codec, CS42L51_DAC_OUT_CTL); - - if (mute) - reg |= mask; - else - reg &= ~mask; - - return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg); -} - -static const struct snd_soc_dai_ops cs42l51_dai_ops = { - .hw_params = cs42l51_hw_params, - .set_sysclk = cs42l51_set_dai_sysclk, - .set_fmt = cs42l51_set_dai_fmt, - .digital_mute = cs42l51_dai_mute, -}; - -static struct snd_soc_dai_driver cs42l51_dai = { - .name = "cs42l51-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = CS42L51_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = CS42L51_FORMATS, - }, - .ops = &cs42l51_dai_ops, -}; - -static int cs42l51_probe(struct snd_soc_codec *codec) -{ - struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); - int ret, reg; - - ret = cs42l51_fill_cache(codec); - if (ret < 0) { - dev_err(codec->dev, "failed to fill register cache\n"); - return ret; - } - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* - * DAC configuration - * - Use signal processor - * - auto mute - * - vol changes immediate - * - no de-emphasize - */ - reg = CS42L51_DAC_CTL_DATA_SEL(1) - | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); - ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { - .probe = cs42l51_probe, - .reg_cache_size = CS42L51_NUMREGS + 1, - .reg_word_size = sizeof(u8), - - .controls = cs42l51_snd_controls, - .num_controls = ARRAY_SIZE(cs42l51_snd_controls), - .dapm_widgets = cs42l51_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets), - .dapm_routes = cs42l51_routes, - .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), -}; - -static int cs42l51_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) -{ - struct cs42l51_private *cs42l51; - int ret; - - /* Verify that we have a CS42L51 */ - ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); - if (ret < 0) { - dev_err(&i2c_client->dev, "failed to read I2C\n"); - goto error; - } - - if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && - (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { - dev_err(&i2c_client->dev, "Invalid chip id\n"); - ret = -ENODEV; - goto error; - } - - dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", - ret & 7); - - cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), - GFP_KERNEL); - if (!cs42l51) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); - return -ENOMEM; - } - - i2c_set_clientdata(i2c_client, cs42l51); - cs42l51->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c_client->dev, - &soc_codec_device_cs42l51, &cs42l51_dai, 1); -error: - return ret; -} - -static int cs42l51_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id cs42l51_id[] = { - {"cs42l51", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, cs42l51_id); - -static struct i2c_driver cs42l51_i2c_driver = { - .driver = { - .name = "cs42l51-codec", - .owner = THIS_MODULE, - }, - .id_table = cs42l51_id, - .probe = cs42l51_i2c_probe, - .remove = cs42l51_i2c_remove, -}; - -static int __init cs42l51_init(void) -{ - int ret; - - ret = i2c_add_driver(&cs42l51_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "%s: can't add i2c driver\n", __func__); - return ret; - } - return 0; -} -module_init(cs42l51_init); - -static void __exit cs42l51_exit(void) -{ - i2c_del_driver(&cs42l51_i2c_driver); -} -module_exit(cs42l51_exit); - -MODULE_AUTHOR("Arnaud Patard "); -MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/cs42l51.h b/ANDROID_3.4.5/sound/soc/codecs/cs42l51.h deleted file mode 100644 index 2beeb171..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cs42l51.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * cs42l51.h - * - * ASoC Driver for Cirrus Logic CS42L51 codecs - * - * Copyright (c) 2010 Arnaud Patard - * - * 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. - */ -#ifndef _CS42L51_H -#define _CS42L51_H - -#define CS42L51_CHIP_ID 0x1B -#define CS42L51_CHIP_REV_A 0x00 -#define CS42L51_CHIP_REV_B 0x01 - -#define CS42L51_CHIP_REV_ID 0x01 -#define CS42L51_MK_CHIP_REV(a, b) ((a)<<3|(b)) - -#define CS42L51_POWER_CTL1 0x02 -#define CS42L51_POWER_CTL1_PDN_DACB (1<<6) -#define CS42L51_POWER_CTL1_PDN_DACA (1<<5) -#define CS42L51_POWER_CTL1_PDN_PGAB (1<<4) -#define CS42L51_POWER_CTL1_PDN_PGAA (1<<3) -#define CS42L51_POWER_CTL1_PDN_ADCB (1<<2) -#define CS42L51_POWER_CTL1_PDN_ADCA (1<<1) -#define CS42L51_POWER_CTL1_PDN (1<<0) - -#define CS42L51_MIC_POWER_CTL 0x03 -#define CS42L51_MIC_POWER_CTL_AUTO (1<<7) -#define CS42L51_MIC_POWER_CTL_SPEED(x) (((x)&3)<<5) -#define CS42L51_QSM_MODE 3 -#define CS42L51_HSM_MODE 2 -#define CS42L51_SSM_MODE 1 -#define CS42L51_DSM_MODE 0 -#define CS42L51_MIC_POWER_CTL_3ST_SP (1<<4) -#define CS42L51_MIC_POWER_CTL_PDN_MICB (1<<3) -#define CS42L51_MIC_POWER_CTL_PDN_MICA (1<<2) -#define CS42L51_MIC_POWER_CTL_PDN_BIAS (1<<1) -#define CS42L51_MIC_POWER_CTL_MCLK_DIV2 (1<<0) - -#define CS42L51_INTF_CTL 0x04 -#define CS42L51_INTF_CTL_LOOPBACK (1<<7) -#define CS42L51_INTF_CTL_MASTER (1<<6) -#define CS42L51_INTF_CTL_DAC_FORMAT(x) (((x)&7)<<3) -#define CS42L51_DAC_DIF_LJ24 0x00 -#define CS42L51_DAC_DIF_I2S 0x01 -#define CS42L51_DAC_DIF_RJ24 0x02 -#define CS42L51_DAC_DIF_RJ20 0x03 -#define CS42L51_DAC_DIF_RJ18 0x04 -#define CS42L51_DAC_DIF_RJ16 0x05 -#define CS42L51_INTF_CTL_ADC_I2S (1<<2) -#define CS42L51_INTF_CTL_DIGMIX (1<<1) -#define CS42L51_INTF_CTL_MICMIX (1<<0) - -#define CS42L51_MIC_CTL 0x05 -#define CS42L51_MIC_CTL_ADC_SNGVOL (1<<7) -#define CS42L51_MIC_CTL_ADCD_DBOOST (1<<6) -#define CS42L51_MIC_CTL_ADCA_DBOOST (1<<5) -#define CS42L51_MIC_CTL_MICBIAS_SEL (1<<4) -#define CS42L51_MIC_CTL_MICBIAS_LVL(x) (((x)&3)<<2) -#define CS42L51_MIC_CTL_MICB_BOOST (1<<1) -#define CS42L51_MIC_CTL_MICA_BOOST (1<<0) - -#define CS42L51_ADC_CTL 0x06 -#define CS42L51_ADC_CTL_ADCB_HPFEN (1<<7) -#define CS42L51_ADC_CTL_ADCB_HPFRZ (1<<6) -#define CS42L51_ADC_CTL_ADCA_HPFEN (1<<5) -#define CS42L51_ADC_CTL_ADCA_HPFRZ (1<<4) -#define CS42L51_ADC_CTL_SOFTB (1<<3) -#define CS42L51_ADC_CTL_ZCROSSB (1<<2) -#define CS42L51_ADC_CTL_SOFTA (1<<1) -#define CS42L51_ADC_CTL_ZCROSSA (1<<0) - -#define CS42L51_ADC_INPUT 0x07 -#define CS42L51_ADC_INPUT_AINB_MUX(x) (((x)&3)<<6) -#define CS42L51_ADC_INPUT_AINA_MUX(x) (((x)&3)<<4) -#define CS42L51_ADC_INPUT_INV_ADCB (1<<3) -#define CS42L51_ADC_INPUT_INV_ADCA (1<<2) -#define CS42L51_ADC_INPUT_ADCB_MUTE (1<<1) -#define CS42L51_ADC_INPUT_ADCA_MUTE (1<<0) - -#define CS42L51_DAC_OUT_CTL 0x08 -#define CS42L51_DAC_OUT_CTL_HP_GAIN(x) (((x)&7)<<5) -#define CS42L51_DAC_OUT_CTL_DAC_SNGVOL (1<<4) -#define CS42L51_DAC_OUT_CTL_INV_PCMB (1<<3) -#define CS42L51_DAC_OUT_CTL_INV_PCMA (1<<2) -#define CS42L51_DAC_OUT_CTL_DACB_MUTE (1<<1) -#define CS42L51_DAC_OUT_CTL_DACA_MUTE (1<<0) - -#define CS42L51_DAC_CTL 0x09 -#define CS42L51_DAC_CTL_DATA_SEL(x) (((x)&3)<<6) -#define CS42L51_DAC_CTL_FREEZE (1<<5) -#define CS42L51_DAC_CTL_DEEMPH (1<<3) -#define CS42L51_DAC_CTL_AMUTE (1<<2) -#define CS42L51_DAC_CTL_DACSZ(x) (((x)&3)<<0) - -#define CS42L51_ALC_PGA_CTL 0x0A -#define CS42L51_ALC_PGB_CTL 0x0B -#define CS42L51_ALC_PGX_ALCX_SRDIS (1<<7) -#define CS42L51_ALC_PGX_ALCX_ZCDIS (1<<6) -#define CS42L51_ALC_PGX_PGX_VOL(x) (((x)&0x1f)<<0) - -#define CS42L51_ADCA_ATT 0x0C -#define CS42L51_ADCB_ATT 0x0D - -#define CS42L51_ADCA_VOL 0x0E -#define CS42L51_ADCB_VOL 0x0F -#define CS42L51_PCMA_VOL 0x10 -#define CS42L51_PCMB_VOL 0x11 -#define CS42L51_MIX_MUTE_ADCMIX (1<<7) -#define CS42L51_MIX_VOLUME(x) (((x)&0x7f)<<0) - -#define CS42L51_BEEP_FREQ 0x12 -#define CS42L51_BEEP_VOL 0x13 -#define CS42L51_BEEP_CONF 0x14 - -#define CS42L51_TONE_CTL 0x15 -#define CS42L51_TONE_CTL_TREB(x) (((x)&0xf)<<4) -#define CS42L51_TONE_CTL_BASS(x) (((x)&0xf)<<0) - -#define CS42L51_AOUTA_VOL 0x16 -#define CS42L51_AOUTB_VOL 0x17 -#define CS42L51_PCM_MIXER 0x18 -#define CS42L51_LIMIT_THRES_DIS 0x19 -#define CS42L51_LIMIT_REL 0x1A -#define CS42L51_LIMIT_ATT 0x1B -#define CS42L51_ALC_EN 0x1C -#define CS42L51_ALC_REL 0x1D -#define CS42L51_ALC_THRES 0x1E -#define CS42L51_NOISE_CONF 0x1F - -#define CS42L51_STATUS 0x20 -#define CS42L51_STATUS_SP_CLKERR (1<<6) -#define CS42L51_STATUS_SPEA_OVFL (1<<5) -#define CS42L51_STATUS_SPEB_OVFL (1<<4) -#define CS42L51_STATUS_PCMA_OVFL (1<<3) -#define CS42L51_STATUS_PCMB_OVFL (1<<2) -#define CS42L51_STATUS_ADCA_OVFL (1<<1) -#define CS42L51_STATUS_ADCB_OVFL (1<<0) - -#define CS42L51_CHARGE_FREQ 0x21 - -#define CS42L51_FIRSTREG 0x01 -/* - * Hack: with register 0x21, it makes 33 registers. Looks like someone in the - * i2c layer doesn't like i2c smbus block read of 33 regs. Workaround by using - * 32 regs - */ -#define CS42L51_LASTREG 0x20 -#define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/cs42l73.c b/ANDROID_3.4.5/sound/soc/codecs/cs42l73.c deleted file mode 100644 index 3686417f..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cs42l73.c +++ /dev/null @@ -1,1455 +0,0 @@ -/* - * cs42l73.c -- CS42L73 ALSA Soc Audio driver - * - * Copyright 2011 Cirrus Logic, Inc. - * - * Authors: Georgi Vlaev, Nucleus Systems Ltd, - * Brian Austin, Cirrus Logic Inc, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cs42l73.h" - -struct sp_config { - u8 spc, mmcc, spfs; - u32 srate; -}; -struct cs42l73_private { - struct sp_config config[3]; - struct regmap *regmap; - u32 sysclk; - u8 mclksel; - u32 mclk; -}; - -static const struct reg_default cs42l73_reg_defaults[] = { - { 1, 0x42 }, /* r01 - Device ID A&B */ - { 2, 0xA7 }, /* r02 - Device ID C&D */ - { 3, 0x30 }, /* r03 - Device ID E */ - { 6, 0xF1 }, /* r06 - Power Ctl 1 */ - { 7, 0xDF }, /* r07 - Power Ctl 2 */ - { 8, 0x3F }, /* r08 - Power Ctl 3 */ - { 9, 0x50 }, /* r09 - Charge Pump Freq */ - { 10, 0x53 }, /* r0A - Output Load MicBias Short Detect */ - { 11, 0x00 }, /* r0B - DMIC Master Clock Ctl */ - { 12, 0x00 }, /* r0C - Aux PCM Ctl */ - { 13, 0x15 }, /* r0D - Aux PCM Master Clock Ctl */ - { 14, 0x00 }, /* r0E - Audio PCM Ctl */ - { 15, 0x15 }, /* r0F - Audio PCM Master Clock Ctl */ - { 16, 0x00 }, /* r10 - Voice PCM Ctl */ - { 17, 0x15 }, /* r11 - Voice PCM Master Clock Ctl */ - { 18, 0x00 }, /* r12 - Voice/Aux Sample Rate */ - { 19, 0x06 }, /* r13 - Misc I/O Path Ctl */ - { 20, 0x00 }, /* r14 - ADC Input Path Ctl */ - { 21, 0x00 }, /* r15 - MICA Preamp, PGA Volume */ - { 22, 0x00 }, /* r16 - MICB Preamp, PGA Volume */ - { 23, 0x00 }, /* r17 - Input Path A Digital Volume */ - { 24, 0x00 }, /* r18 - Input Path B Digital Volume */ - { 25, 0x00 }, /* r19 - Playback Digital Ctl */ - { 26, 0x00 }, /* r1A - HP/LO Left Digital Volume */ - { 27, 0x00 }, /* r1B - HP/LO Right Digital Volume */ - { 28, 0x00 }, /* r1C - Speakerphone Digital Volume */ - { 29, 0x00 }, /* r1D - Ear/SPKLO Digital Volume */ - { 30, 0x00 }, /* r1E - HP Left Analog Volume */ - { 31, 0x00 }, /* r1F - HP Right Analog Volume */ - { 32, 0x00 }, /* r20 - LO Left Analog Volume */ - { 33, 0x00 }, /* r21 - LO Right Analog Volume */ - { 34, 0x00 }, /* r22 - Stereo Input Path Advisory Volume */ - { 35, 0x00 }, /* r23 - Aux PCM Input Advisory Volume */ - { 36, 0x00 }, /* r24 - Audio PCM Input Advisory Volume */ - { 37, 0x00 }, /* r25 - Voice PCM Input Advisory Volume */ - { 38, 0x00 }, /* r26 - Limiter Attack Rate HP/LO */ - { 39, 0x7F }, /* r27 - Limter Ctl, Release Rate HP/LO */ - { 40, 0x00 }, /* r28 - Limter Threshold HP/LO */ - { 41, 0x00 }, /* r29 - Limiter Attack Rate Speakerphone */ - { 42, 0x3F }, /* r2A - Limter Ctl, Release Rate Speakerphone */ - { 43, 0x00 }, /* r2B - Limter Threshold Speakerphone */ - { 44, 0x00 }, /* r2C - Limiter Attack Rate Ear/SPKLO */ - { 45, 0x3F }, /* r2D - Limter Ctl, Release Rate Ear/SPKLO */ - { 46, 0x00 }, /* r2E - Limter Threshold Ear/SPKLO */ - { 47, 0x00 }, /* r2F - ALC Enable, Attack Rate Left/Right */ - { 48, 0x3F }, /* r30 - ALC Release Rate Left/Right */ - { 49, 0x00 }, /* r31 - ALC Threshold Left/Right */ - { 50, 0x00 }, /* r32 - Noise Gate Ctl Left/Right */ - { 51, 0x00 }, /* r33 - ALC/NG Misc Ctl */ - { 52, 0x18 }, /* r34 - Mixer Ctl */ - { 53, 0x3F }, /* r35 - HP/LO Left Mixer Input Path Volume */ - { 54, 0x3F }, /* r36 - HP/LO Right Mixer Input Path Volume */ - { 55, 0x3F }, /* r37 - HP/LO Left Mixer Aux PCM Volume */ - { 56, 0x3F }, /* r38 - HP/LO Right Mixer Aux PCM Volume */ - { 57, 0x3F }, /* r39 - HP/LO Left Mixer Audio PCM Volume */ - { 58, 0x3F }, /* r3A - HP/LO Right Mixer Audio PCM Volume */ - { 59, 0x3F }, /* r3B - HP/LO Left Mixer Voice PCM Mono Volume */ - { 60, 0x3F }, /* r3C - HP/LO Right Mixer Voice PCM Mono Volume */ - { 61, 0x3F }, /* r3D - Aux PCM Left Mixer Input Path Volume */ - { 62, 0x3F }, /* r3E - Aux PCM Right Mixer Input Path Volume */ - { 63, 0x3F }, /* r3F - Aux PCM Left Mixer Volume */ - { 64, 0x3F }, /* r40 - Aux PCM Left Mixer Volume */ - { 65, 0x3F }, /* r41 - Aux PCM Left Mixer Audio PCM L Volume */ - { 66, 0x3F }, /* r42 - Aux PCM Right Mixer Audio PCM R Volume */ - { 67, 0x3F }, /* r43 - Aux PCM Left Mixer Voice PCM Volume */ - { 68, 0x3F }, /* r44 - Aux PCM Right Mixer Voice PCM Volume */ - { 69, 0x3F }, /* r45 - Audio PCM Left Input Path Volume */ - { 70, 0x3F }, /* r46 - Audio PCM Right Input Path Volume */ - { 71, 0x3F }, /* r47 - Audio PCM Left Mixer Aux PCM L Volume */ - { 72, 0x3F }, /* r48 - Audio PCM Right Mixer Aux PCM R Volume */ - { 73, 0x3F }, /* r49 - Audio PCM Left Mixer Volume */ - { 74, 0x3F }, /* r4A - Audio PCM Right Mixer Volume */ - { 75, 0x3F }, /* r4B - Audio PCM Left Mixer Voice PCM Volume */ - { 76, 0x3F }, /* r4C - Audio PCM Right Mixer Voice PCM Volume */ - { 77, 0x3F }, /* r4D - Voice PCM Left Input Path Volume */ - { 78, 0x3F }, /* r4E - Voice PCM Right Input Path Volume */ - { 79, 0x3F }, /* r4F - Voice PCM Left Mixer Aux PCM L Volume */ - { 80, 0x3F }, /* r50 - Voice PCM Right Mixer Aux PCM R Volume */ - { 81, 0x3F }, /* r51 - Voice PCM Left Mixer Audio PCM L Volume */ - { 82, 0x3F }, /* r52 - Voice PCM Right Mixer Audio PCM R Volume */ - { 83, 0x3F }, /* r53 - Voice PCM Left Mixer Voice PCM Volume */ - { 84, 0x3F }, /* r54 - Voice PCM Right Mixer Voice PCM Volume */ - { 85, 0xAA }, /* r55 - Mono Mixer Ctl */ - { 86, 0x3F }, /* r56 - SPK Mono Mixer Input Path Volume */ - { 87, 0x3F }, /* r57 - SPK Mono Mixer Aux PCM Mono/L/R Volume */ - { 88, 0x3F }, /* r58 - SPK Mono Mixer Audio PCM Mono/L/R Volume */ - { 89, 0x3F }, /* r59 - SPK Mono Mixer Voice PCM Mono Volume */ - { 90, 0x3F }, /* r5A - SPKLO Mono Mixer Input Path Mono Volume */ - { 91, 0x3F }, /* r5B - SPKLO Mono Mixer Aux Mono/L/R Volume */ - { 92, 0x3F }, /* r5C - SPKLO Mono Mixer Audio Mono/L/R Volume */ - { 93, 0x3F }, /* r5D - SPKLO Mono Mixer Voice Mono Volume */ - { 94, 0x00 }, /* r5E - Interrupt Mask 1 */ - { 95, 0x00 }, /* r5F - Interrupt Mask 2 */ -}; - -static bool cs42l73_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case CS42L73_IS1: - case CS42L73_IS2: - return true; - default: - return false; - } -} - -static bool cs42l73_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case CS42L73_DEVID_AB: - case CS42L73_DEVID_CD: - case CS42L73_DEVID_E: - case CS42L73_REVID: - case CS42L73_PWRCTL1: - case CS42L73_PWRCTL2: - case CS42L73_PWRCTL3: - case CS42L73_CPFCHC: - case CS42L73_OLMBMSDC: - case CS42L73_DMMCC: - case CS42L73_XSPC: - case CS42L73_XSPMMCC: - case CS42L73_ASPC: - case CS42L73_ASPMMCC: - case CS42L73_VSPC: - case CS42L73_VSPMMCC: - case CS42L73_VXSPFS: - case CS42L73_MIOPC: - case CS42L73_ADCIPC: - case CS42L73_MICAPREPGAAVOL: - case CS42L73_MICBPREPGABVOL: - case CS42L73_IPADVOL: - case CS42L73_IPBDVOL: - case CS42L73_PBDC: - case CS42L73_HLADVOL: - case CS42L73_HLBDVOL: - case CS42L73_SPKDVOL: - case CS42L73_ESLDVOL: - case CS42L73_HPAAVOL: - case CS42L73_HPBAVOL: - case CS42L73_LOAAVOL: - case CS42L73_LOBAVOL: - case CS42L73_STRINV: - case CS42L73_XSPINV: - case CS42L73_ASPINV: - case CS42L73_VSPINV: - case CS42L73_LIMARATEHL: - case CS42L73_LIMRRATEHL: - case CS42L73_LMAXHL: - case CS42L73_LIMARATESPK: - case CS42L73_LIMRRATESPK: - case CS42L73_LMAXSPK: - case CS42L73_LIMARATEESL: - case CS42L73_LIMRRATEESL: - case CS42L73_LMAXESL: - case CS42L73_ALCARATE: - case CS42L73_ALCRRATE: - case CS42L73_ALCMINMAX: - case CS42L73_NGCAB: - case CS42L73_ALCNGMC: - case CS42L73_MIXERCTL: - case CS42L73_HLAIPAA: - case CS42L73_HLBIPBA: - case CS42L73_HLAXSPAA: - case CS42L73_HLBXSPBA: - case CS42L73_HLAASPAA: - case CS42L73_HLBASPBA: - case CS42L73_HLAVSPMA: - case CS42L73_HLBVSPMA: - case CS42L73_XSPAIPAA: - case CS42L73_XSPBIPBA: - case CS42L73_XSPAXSPAA: - case CS42L73_XSPBXSPBA: - case CS42L73_XSPAASPAA: - case CS42L73_XSPAASPBA: - case CS42L73_XSPAVSPMA: - case CS42L73_XSPBVSPMA: - case CS42L73_ASPAIPAA: - case CS42L73_ASPBIPBA: - case CS42L73_ASPAXSPAA: - case CS42L73_ASPBXSPBA: - case CS42L73_ASPAASPAA: - case CS42L73_ASPBASPBA: - case CS42L73_ASPAVSPMA: - case CS42L73_ASPBVSPMA: - case CS42L73_VSPAIPAA: - case CS42L73_VSPBIPBA: - case CS42L73_VSPAXSPAA: - case CS42L73_VSPBXSPBA: - case CS42L73_VSPAASPAA: - case CS42L73_VSPBASPBA: - case CS42L73_VSPAVSPMA: - case CS42L73_VSPBVSPMA: - case CS42L73_MMIXCTL: - case CS42L73_SPKMIPMA: - case CS42L73_SPKMXSPA: - case CS42L73_SPKMASPA: - case CS42L73_SPKMVSPMA: - case CS42L73_ESLMIPMA: - case CS42L73_ESLMXSPA: - case CS42L73_ESLMASPA: - case CS42L73_ESLMVSPMA: - case CS42L73_IM1: - case CS42L73_IM2: - return true; - default: - return false; - } -} - -static const unsigned int hpaloa_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0), - 14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0), -}; - -static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0); - -static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0); - -static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0); - -static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0); - -static const unsigned int limiter_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), - 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0), -}; - -static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1); - -static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" }; -static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" }; - -static const struct soc_enum pgaa_enum = - SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3, - ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text); - -static const struct soc_enum pgab_enum = - SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7, - ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text); - -static const struct snd_kcontrol_new pgaa_mux = - SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum); - -static const struct snd_kcontrol_new pgab_mux = - SOC_DAPM_ENUM("Right Analog Input Capture Mux", pgab_enum); - -static const struct snd_kcontrol_new input_left_mixer[] = { - SOC_DAPM_SINGLE("ADC Left Input", CS42L73_PWRCTL1, - 5, 1, 1), - SOC_DAPM_SINGLE("DMIC Left Input", CS42L73_PWRCTL1, - 4, 1, 1), -}; - -static const struct snd_kcontrol_new input_right_mixer[] = { - SOC_DAPM_SINGLE("ADC Right Input", CS42L73_PWRCTL1, - 7, 1, 1), - SOC_DAPM_SINGLE("DMIC Right Input", CS42L73_PWRCTL1, - 6, 1, 1), -}; - -static const char * const cs42l73_ng_delay_text[] = { - "50ms", "100ms", "150ms", "200ms" }; - -static const struct soc_enum ng_delay_enum = - SOC_ENUM_SINGLE(CS42L73_NGCAB, 0, - ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text); - -static const char * const charge_pump_freq_text[] = { - "0", "1", "2", "3", "4", - "5", "6", "7", "8", "9", - "10", "11", "12", "13", "14", "15" }; - -static const struct soc_enum charge_pump_enum = - SOC_ENUM_SINGLE(CS42L73_CPFCHC, 4, - ARRAY_SIZE(charge_pump_freq_text), charge_pump_freq_text); - -static const char * const cs42l73_mono_mix_texts[] = { - "Left", "Right", "Mono Mix"}; - -static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 }; - -static const struct soc_enum spk_asp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1, - ARRAY_SIZE(cs42l73_mono_mix_texts), - cs42l73_mono_mix_texts, - cs42l73_mono_mix_values); - -static const struct snd_kcontrol_new spk_asp_mixer = - SOC_DAPM_ENUM("Route", spk_asp_enum); - -static const struct soc_enum spk_xsp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 4, 3, - ARRAY_SIZE(cs42l73_mono_mix_texts), - cs42l73_mono_mix_texts, - cs42l73_mono_mix_values); - -static const struct snd_kcontrol_new spk_xsp_mixer = - SOC_DAPM_ENUM("Route", spk_xsp_enum); - -static const struct soc_enum esl_asp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5, - ARRAY_SIZE(cs42l73_mono_mix_texts), - cs42l73_mono_mix_texts, - cs42l73_mono_mix_values); - -static const struct snd_kcontrol_new esl_asp_mixer = - SOC_DAPM_ENUM("Route", esl_asp_enum); - -static const struct soc_enum esl_xsp_enum = - SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7, - ARRAY_SIZE(cs42l73_mono_mix_texts), - cs42l73_mono_mix_texts, - cs42l73_mono_mix_values); - -static const struct snd_kcontrol_new esl_xsp_mixer = - SOC_DAPM_ENUM("Route", esl_xsp_enum); - -static const char * const cs42l73_ip_swap_text[] = { - "Stereo", "Mono A", "Mono B", "Swap A-B"}; - -static const struct soc_enum ip_swap_enum = - SOC_ENUM_SINGLE(CS42L73_MIOPC, 6, - ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text); - -static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"}; - -static const struct soc_enum vsp_output_mux_enum = - SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5, - ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); - -static const struct soc_enum xsp_output_mux_enum = - SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4, - ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text); - -static const struct snd_kcontrol_new vsp_output_mux = - SOC_DAPM_ENUM("Route", vsp_output_mux_enum); - -static const struct snd_kcontrol_new xsp_output_mux = - SOC_DAPM_ENUM("Route", xsp_output_mux_enum); - -static const struct snd_kcontrol_new hp_amp_ctl = - SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1); - -static const struct snd_kcontrol_new lo_amp_ctl = - SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 1, 1, 1); - -static const struct snd_kcontrol_new spk_amp_ctl = - SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 2, 1, 1); - -static const struct snd_kcontrol_new spklo_amp_ctl = - SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 4, 1, 1); - -static const struct snd_kcontrol_new ear_amp_ctl = - SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 3, 1, 1); - -static const struct snd_kcontrol_new cs42l73_snd_controls[] = { - SOC_DOUBLE_R_SX_TLV("Headphone Analog Playback Volume", - CS42L73_HPAAVOL, CS42L73_HPBAVOL, 7, - 0xffffffC1, 0x0C, hpaloa_tlv), - - SOC_DOUBLE_R_SX_TLV("LineOut Analog Playback Volume", CS42L73_LOAAVOL, - CS42L73_LOBAVOL, 7, 0xffffffC1, 0x0C, hpaloa_tlv), - - SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL, - CS42L73_MICBPREPGABVOL, 5, 0xffffff35, - 0x34, micpga_tlv), - - SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL, - CS42L73_MICBPREPGABVOL, 6, 1, 1), - - SOC_DOUBLE_R_SX_TLV("Input Path Digital Volume", CS42L73_IPADVOL, - CS42L73_IPBDVOL, 7, 0xffffffA0, 0xA0, ipd_tlv), - - SOC_DOUBLE_R_SX_TLV("HL Digital Playback Volume", - CS42L73_HLADVOL, CS42L73_HLBDVOL, 7, 0xffffffE5, - 0xE4, hl_tlv), - - SOC_SINGLE_TLV("ADC A Boost Volume", - CS42L73_ADCIPC, 2, 0x01, 1, adc_boost_tlv), - - SOC_SINGLE_TLV("ADC B Boost Volume", - CS42L73_ADCIPC, 6, 0x01, 1, adc_boost_tlv), - - SOC_SINGLE_TLV("Speakerphone Digital Playback Volume", - CS42L73_SPKDVOL, 0, 0xE4, 1, hl_tlv), - - SOC_SINGLE_TLV("Ear Speaker Digital Playback Volume", - CS42L73_ESLDVOL, 0, 0xE4, 1, hl_tlv), - - SOC_DOUBLE_R("Headphone Analog Playback Switch", CS42L73_HPAAVOL, - CS42L73_HPBAVOL, 7, 1, 1), - - SOC_DOUBLE_R("LineOut Analog Playback Switch", CS42L73_LOAAVOL, - CS42L73_LOBAVOL, 7, 1, 1), - SOC_DOUBLE("Input Path Digital Switch", CS42L73_ADCIPC, 0, 4, 1, 1), - SOC_DOUBLE("HL Digital Playback Switch", CS42L73_PBDC, 0, - 1, 1, 1), - SOC_SINGLE("Speakerphone Digital Playback Switch", CS42L73_PBDC, 2, 1, - 1), - SOC_SINGLE("Ear Speaker Digital Playback Switch", CS42L73_PBDC, 3, 1, - 1), - - SOC_SINGLE("PGA Soft-Ramp Switch", CS42L73_MIOPC, 3, 1, 0), - SOC_SINGLE("Analog Zero Cross Switch", CS42L73_MIOPC, 2, 1, 0), - SOC_SINGLE("Digital Soft-Ramp Switch", CS42L73_MIOPC, 1, 1, 0), - SOC_SINGLE("Analog Output Soft-Ramp Switch", CS42L73_MIOPC, 0, 1, 0), - - SOC_DOUBLE("ADC Signal Polarity Switch", CS42L73_ADCIPC, 1, 5, 1, - 0), - - SOC_SINGLE("HL Limiter Attack Rate", CS42L73_LIMARATEHL, 0, 0x3F, - 0), - SOC_SINGLE("HL Limiter Release Rate", CS42L73_LIMRRATEHL, 0, - 0x3F, 0), - - - SOC_SINGLE("HL Limiter Switch", CS42L73_LIMRRATEHL, 7, 1, 0), - SOC_SINGLE("HL Limiter All Channels Switch", CS42L73_LIMRRATEHL, 6, 1, - 0), - - SOC_SINGLE_TLV("HL Limiter Max Threshold Volume", CS42L73_LMAXHL, 5, 7, - 1, limiter_tlv), - - SOC_SINGLE_TLV("HL Limiter Cushion Volume", CS42L73_LMAXHL, 2, 7, 1, - limiter_tlv), - - SOC_SINGLE("SPK Limiter Attack Rate Volume", CS42L73_LIMARATESPK, 0, - 0x3F, 0), - SOC_SINGLE("SPK Limiter Release Rate Volume", CS42L73_LIMRRATESPK, 0, - 0x3F, 0), - SOC_SINGLE("SPK Limiter Switch", CS42L73_LIMRRATESPK, 7, 1, 0), - SOC_SINGLE("SPK Limiter All Channels Switch", CS42L73_LIMRRATESPK, - 6, 1, 0), - SOC_SINGLE_TLV("SPK Limiter Max Threshold Volume", CS42L73_LMAXSPK, 5, - 7, 1, limiter_tlv), - - SOC_SINGLE_TLV("SPK Limiter Cushion Volume", CS42L73_LMAXSPK, 2, 7, 1, - limiter_tlv), - - SOC_SINGLE("ESL Limiter Attack Rate Volume", CS42L73_LIMARATEESL, 0, - 0x3F, 0), - SOC_SINGLE("ESL Limiter Release Rate Volume", CS42L73_LIMRRATEESL, 0, - 0x3F, 0), - SOC_SINGLE("ESL Limiter Switch", CS42L73_LIMRRATEESL, 7, 1, 0), - SOC_SINGLE_TLV("ESL Limiter Max Threshold Volume", CS42L73_LMAXESL, 5, - 7, 1, limiter_tlv), - - SOC_SINGLE_TLV("ESL Limiter Cushion Volume", CS42L73_LMAXESL, 2, 7, 1, - limiter_tlv), - - SOC_SINGLE("ALC Attack Rate Volume", CS42L73_ALCARATE, 0, 0x3F, 0), - SOC_SINGLE("ALC Release Rate Volume", CS42L73_ALCRRATE, 0, 0x3F, 0), - SOC_DOUBLE("ALC Switch", CS42L73_ALCARATE, 6, 7, 1, 0), - SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L73_ALCMINMAX, 5, 7, 0, - limiter_tlv), - SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L73_ALCMINMAX, 2, 7, 0, - limiter_tlv), - - SOC_DOUBLE("NG Enable Switch", CS42L73_NGCAB, 6, 7, 1, 0), - SOC_SINGLE("NG Boost Switch", CS42L73_NGCAB, 5, 1, 0), - /* - NG Threshold depends on NG_BOOTSAB, which selects - between two threshold scales in decibels. - Set linear values for now .. - */ - SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0), - SOC_ENUM("NG Delay", ng_delay_enum), - - SOC_ENUM("Charge Pump Frequency", charge_pump_enum), - - SOC_DOUBLE_R_TLV("XSP-IP Volume", - CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("XSP-XSP Volume", - CS42L73_XSPAXSPAA, CS42L73_XSPBXSPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("XSP-ASP Volume", - CS42L73_XSPAASPAA, CS42L73_XSPAASPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("XSP-VSP Volume", - CS42L73_XSPAVSPMA, CS42L73_XSPBVSPMA, 0, 0x3F, 1, - attn_tlv), - - SOC_DOUBLE_R_TLV("ASP-IP Volume", - CS42L73_ASPAIPAA, CS42L73_ASPBIPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("ASP-XSP Volume", - CS42L73_ASPAXSPAA, CS42L73_ASPBXSPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("ASP-ASP Volume", - CS42L73_ASPAASPAA, CS42L73_ASPBASPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("ASP-VSP Volume", - CS42L73_ASPAVSPMA, CS42L73_ASPBVSPMA, 0, 0x3F, 1, - attn_tlv), - - SOC_DOUBLE_R_TLV("VSP-IP Volume", - CS42L73_VSPAIPAA, CS42L73_VSPBIPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("VSP-XSP Volume", - CS42L73_VSPAXSPAA, CS42L73_VSPBXSPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("VSP-ASP Volume", - CS42L73_VSPAASPAA, CS42L73_VSPBASPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("VSP-VSP Volume", - CS42L73_VSPAVSPMA, CS42L73_VSPBVSPMA, 0, 0x3F, 1, - attn_tlv), - - SOC_DOUBLE_R_TLV("HL-IP Volume", - CS42L73_HLAIPAA, CS42L73_HLBIPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("HL-XSP Volume", - CS42L73_HLAXSPAA, CS42L73_HLBXSPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("HL-ASP Volume", - CS42L73_HLAASPAA, CS42L73_HLBASPBA, 0, 0x3F, 1, - attn_tlv), - SOC_DOUBLE_R_TLV("HL-VSP Volume", - CS42L73_HLAVSPMA, CS42L73_HLBVSPMA, 0, 0x3F, 1, - attn_tlv), - - SOC_SINGLE_TLV("SPK-IP Mono Volume", - CS42L73_SPKMIPMA, 0, 0x3F, 1, attn_tlv), - SOC_SINGLE_TLV("SPK-XSP Mono Volume", - CS42L73_SPKMXSPA, 0, 0x3F, 1, attn_tlv), - SOC_SINGLE_TLV("SPK-ASP Mono Volume", - CS42L73_SPKMASPA, 0, 0x3F, 1, attn_tlv), - SOC_SINGLE_TLV("SPK-VSP Mono Volume", - CS42L73_SPKMVSPMA, 0, 0x3F, 1, attn_tlv), - - SOC_SINGLE_TLV("ESL-IP Mono Volume", - CS42L73_ESLMIPMA, 0, 0x3F, 1, attn_tlv), - SOC_SINGLE_TLV("ESL-XSP Mono Volume", - CS42L73_ESLMXSPA, 0, 0x3F, 1, attn_tlv), - SOC_SINGLE_TLV("ESL-ASP Mono Volume", - CS42L73_ESLMASPA, 0, 0x3F, 1, attn_tlv), - SOC_SINGLE_TLV("ESL-VSP Mono Volume", - CS42L73_ESLMVSPMA, 0, 0x3F, 1, attn_tlv), - - SOC_ENUM("IP Digital Swap/Mono Select", ip_swap_enum), - - SOC_ENUM("VSPOUT Mono/Stereo Select", vsp_output_mux_enum), - SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum), -}; - -static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("LINEINA"), - SND_SOC_DAPM_INPUT("LINEINB"), - SND_SOC_DAPM_INPUT("MIC1"), - SND_SOC_DAPM_SUPPLY("MIC1 Bias", CS42L73_PWRCTL2, 6, 1, NULL, 0), - SND_SOC_DAPM_INPUT("MIC2"), - SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS42L73_PWRCTL2, 7, 1, NULL, 0), - - SND_SOC_DAPM_AIF_OUT("XSPOUTL", "XSP Capture", 0, - CS42L73_PWRCTL2, 1, 1), - SND_SOC_DAPM_AIF_OUT("XSPOUTR", "XSP Capture", 0, - CS42L73_PWRCTL2, 1, 1), - SND_SOC_DAPM_AIF_OUT("ASPOUTL", "ASP Capture", 0, - CS42L73_PWRCTL2, 3, 1), - SND_SOC_DAPM_AIF_OUT("ASPOUTR", "ASP Capture", 0, - CS42L73_PWRCTL2, 3, 1), - SND_SOC_DAPM_AIF_OUT("VSPOUTL", "VSP Capture", 0, - CS42L73_PWRCTL2, 4, 1), - SND_SOC_DAPM_AIF_OUT("VSPOUTR", "VSP Capture", 0, - CS42L73_PWRCTL2, 4, 1), - - SND_SOC_DAPM_PGA("PGA Left", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("PGA Right", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MUX("PGA Left Mux", SND_SOC_NOPM, 0, 0, &pgaa_mux), - SND_SOC_DAPM_MUX("PGA Right Mux", SND_SOC_NOPM, 0, 0, &pgab_mux), - - SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L73_PWRCTL1, 7, 1), - SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L73_PWRCTL1, 5, 1), - SND_SOC_DAPM_ADC("DMIC Left", NULL, CS42L73_PWRCTL1, 6, 1), - SND_SOC_DAPM_ADC("DMIC Right", NULL, CS42L73_PWRCTL1, 4, 1), - - SND_SOC_DAPM_MIXER_NAMED_CTL("Input Left Capture", SND_SOC_NOPM, - 0, 0, input_left_mixer, - ARRAY_SIZE(input_left_mixer)), - - SND_SOC_DAPM_MIXER_NAMED_CTL("Input Right Capture", SND_SOC_NOPM, - 0, 0, input_right_mixer, - ARRAY_SIZE(input_right_mixer)), - - SND_SOC_DAPM_MIXER("ASPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("ASPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("XSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("XSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("VSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("VSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_AIF_IN("XSPINL", "XSP Playback", 0, - CS42L73_PWRCTL2, 0, 1), - SND_SOC_DAPM_AIF_IN("XSPINR", "XSP Playback", 0, - CS42L73_PWRCTL2, 0, 1), - SND_SOC_DAPM_AIF_IN("XSPINM", "XSP Playback", 0, - CS42L73_PWRCTL2, 0, 1), - - SND_SOC_DAPM_AIF_IN("ASPINL", "ASP Playback", 0, - CS42L73_PWRCTL2, 2, 1), - SND_SOC_DAPM_AIF_IN("ASPINR", "ASP Playback", 0, - CS42L73_PWRCTL2, 2, 1), - SND_SOC_DAPM_AIF_IN("ASPINM", "ASP Playback", 0, - CS42L73_PWRCTL2, 2, 1), - - SND_SOC_DAPM_AIF_IN("VSPIN", "VSP Playback", 0, - CS42L73_PWRCTL2, 4, 1), - - SND_SOC_DAPM_MIXER("HL Left Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("HL Right Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("ESL Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MUX("ESL-XSP Mux", SND_SOC_NOPM, - 0, 0, &esl_xsp_mixer), - - SND_SOC_DAPM_MUX("ESL-ASP Mux", SND_SOC_NOPM, - 0, 0, &esl_asp_mixer), - - SND_SOC_DAPM_MUX("SPK-ASP Mux", SND_SOC_NOPM, - 0, 0, &spk_asp_mixer), - - SND_SOC_DAPM_MUX("SPK-XSP Mux", SND_SOC_NOPM, - 0, 0, &spk_xsp_mixer), - - SND_SOC_DAPM_PGA("HL Left DAC", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("HL Right DAC", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_SWITCH("HP Amp", CS42L73_PWRCTL3, 0, 1, - &hp_amp_ctl), - SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1, - &lo_amp_ctl), - SND_SOC_DAPM_SWITCH("SPK Amp", CS42L73_PWRCTL3, 2, 1, - &spk_amp_ctl), - SND_SOC_DAPM_SWITCH("EAR Amp", CS42L73_PWRCTL3, 3, 1, - &ear_amp_ctl), - SND_SOC_DAPM_SWITCH("SPKLO Amp", CS42L73_PWRCTL3, 4, 1, - &spklo_amp_ctl), - - SND_SOC_DAPM_OUTPUT("HPOUTA"), - SND_SOC_DAPM_OUTPUT("HPOUTB"), - SND_SOC_DAPM_OUTPUT("LINEOUTA"), - SND_SOC_DAPM_OUTPUT("LINEOUTB"), - SND_SOC_DAPM_OUTPUT("EAROUT"), - SND_SOC_DAPM_OUTPUT("SPKOUT"), - SND_SOC_DAPM_OUTPUT("SPKLINEOUT"), -}; - -static const struct snd_soc_dapm_route cs42l73_audio_map[] = { - - /* SPKLO EARSPK Paths */ - {"EAROUT", NULL, "EAR Amp"}, - {"SPKLINEOUT", NULL, "SPKLO Amp"}, - - {"EAR Amp", "Switch", "ESL DAC"}, - {"SPKLO Amp", "Switch", "ESL DAC"}, - - {"ESL DAC", "ESL-ASP Mono Volume", "ESL Mixer"}, - {"ESL DAC", "ESL-XSP Mono Volume", "ESL Mixer"}, - {"ESL DAC", "ESL-VSP Mono Volume", "VSPIN"}, - /* Loopback */ - {"ESL DAC", "ESL-IP Mono Volume", "Input Left Capture"}, - {"ESL DAC", "ESL-IP Mono Volume", "Input Right Capture"}, - - {"ESL Mixer", NULL, "ESL-ASP Mux"}, - {"ESL Mixer", NULL, "ESL-XSP Mux"}, - - {"ESL-ASP Mux", "Left", "ASPINL"}, - {"ESL-ASP Mux", "Right", "ASPINR"}, - {"ESL-ASP Mux", "Mono Mix", "ASPINM"}, - - {"ESL-XSP Mux", "Left", "XSPINL"}, - {"ESL-XSP Mux", "Right", "XSPINR"}, - {"ESL-XSP Mux", "Mono Mix", "XSPINM"}, - - /* Speakerphone Paths */ - {"SPKOUT", NULL, "SPK Amp"}, - {"SPK Amp", "Switch", "SPK DAC"}, - - {"SPK DAC", "SPK-ASP Mono Volume", "SPK Mixer"}, - {"SPK DAC", "SPK-XSP Mono Volume", "SPK Mixer"}, - {"SPK DAC", "SPK-VSP Mono Volume", "VSPIN"}, - /* Loopback */ - {"SPK DAC", "SPK-IP Mono Volume", "Input Left Capture"}, - {"SPK DAC", "SPK-IP Mono Volume", "Input Right Capture"}, - - {"SPK Mixer", NULL, "SPK-ASP Mux"}, - {"SPK Mixer", NULL, "SPK-XSP Mux"}, - - {"SPK-ASP Mux", "Left", "ASPINL"}, - {"SPK-ASP Mux", "Mono Mix", "ASPINM"}, - {"SPK-ASP Mux", "Right", "ASPINR"}, - - {"SPK-XSP Mux", "Left", "XSPINL"}, - {"SPK-XSP Mux", "Mono Mix", "XSPINM"}, - {"SPK-XSP Mux", "Right", "XSPINR"}, - - /* HP LineOUT Paths */ - {"HPOUTA", NULL, "HP Amp"}, - {"HPOUTB", NULL, "HP Amp"}, - {"LINEOUTA", NULL, "LO Amp"}, - {"LINEOUTB", NULL, "LO Amp"}, - - {"HP Amp", "Switch", "HL Left DAC"}, - {"HP Amp", "Switch", "HL Right DAC"}, - {"LO Amp", "Switch", "HL Left DAC"}, - {"LO Amp", "Switch", "HL Right DAC"}, - - {"HL Left DAC", "HL-XSP Volume", "HL Left Mixer"}, - {"HL Right DAC", "HL-XSP Volume", "HL Right Mixer"}, - {"HL Left DAC", "HL-ASP Volume", "HL Left Mixer"}, - {"HL Right DAC", "HL-ASP Volume", "HL Right Mixer"}, - {"HL Left DAC", "HL-VSP Volume", "HL Left Mixer"}, - {"HL Right DAC", "HL-VSP Volume", "HL Right Mixer"}, - /* Loopback */ - {"HL Left DAC", "HL-IP Volume", "HL Left Mixer"}, - {"HL Right DAC", "HL-IP Volume", "HL Right Mixer"}, - {"HL Left Mixer", NULL, "Input Left Capture"}, - {"HL Right Mixer", NULL, "Input Right Capture"}, - - {"HL Left Mixer", NULL, "ASPINL"}, - {"HL Right Mixer", NULL, "ASPINR"}, - {"HL Left Mixer", NULL, "XSPINL"}, - {"HL Right Mixer", NULL, "XSPINR"}, - {"HL Left Mixer", NULL, "VSPIN"}, - {"HL Right Mixer", NULL, "VSPIN"}, - - /* Capture Paths */ - {"MIC1", NULL, "MIC1 Bias"}, - {"PGA Left Mux", "Mic 1", "MIC1"}, - {"MIC2", NULL, "MIC2 Bias"}, - {"PGA Right Mux", "Mic 2", "MIC2"}, - - {"PGA Left Mux", "Line A", "LINEINA"}, - {"PGA Right Mux", "Line B", "LINEINB"}, - - {"PGA Left", NULL, "PGA Left Mux"}, - {"PGA Right", NULL, "PGA Right Mux"}, - - {"ADC Left", NULL, "PGA Left"}, - {"ADC Right", NULL, "PGA Right"}, - - {"Input Left Capture", "ADC Left Input", "ADC Left"}, - {"Input Right Capture", "ADC Right Input", "ADC Right"}, - {"Input Left Capture", "DMIC Left Input", "DMIC Left"}, - {"Input Right Capture", "DMIC Right Input", "DMIC Right"}, - - /* Audio Capture */ - {"ASPL Output Mixer", NULL, "Input Left Capture"}, - {"ASPR Output Mixer", NULL, "Input Right Capture"}, - - {"ASPOUTL", "ASP-IP Volume", "ASPL Output Mixer"}, - {"ASPOUTR", "ASP-IP Volume", "ASPR Output Mixer"}, - - /* Auxillary Capture */ - {"XSPL Output Mixer", NULL, "Input Left Capture"}, - {"XSPR Output Mixer", NULL, "Input Right Capture"}, - - {"XSPOUTL", "XSP-IP Volume", "XSPL Output Mixer"}, - {"XSPOUTR", "XSP-IP Volume", "XSPR Output Mixer"}, - - {"XSPOUTL", NULL, "XSPL Output Mixer"}, - {"XSPOUTR", NULL, "XSPR Output Mixer"}, - - /* Voice Capture */ - {"VSPL Output Mixer", NULL, "Input Left Capture"}, - {"VSPR Output Mixer", NULL, "Input Left Capture"}, - - {"VSPOUTL", "VSP-IP Volume", "VSPL Output Mixer"}, - {"VSPOUTR", "VSP-IP Volume", "VSPR Output Mixer"}, - - {"VSPOUTL", NULL, "VSPL Output Mixer"}, - {"VSPOUTR", NULL, "VSPR Output Mixer"}, -}; - -struct cs42l73_mclk_div { - u32 mclk; - u32 srate; - u8 mmcc; -}; - -static struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = { - /* MCLK, Sample Rate, xMMCC[5:0] */ - {5644800, 11025, 0x30}, - {5644800, 22050, 0x20}, - {5644800, 44100, 0x10}, - - {6000000, 8000, 0x39}, - {6000000, 11025, 0x33}, - {6000000, 12000, 0x31}, - {6000000, 16000, 0x29}, - {6000000, 22050, 0x23}, - {6000000, 24000, 0x21}, - {6000000, 32000, 0x19}, - {6000000, 44100, 0x13}, - {6000000, 48000, 0x11}, - - {6144000, 8000, 0x38}, - {6144000, 12000, 0x30}, - {6144000, 16000, 0x28}, - {6144000, 24000, 0x20}, - {6144000, 32000, 0x18}, - {6144000, 48000, 0x10}, - - {6500000, 8000, 0x3C}, - {6500000, 11025, 0x35}, - {6500000, 12000, 0x34}, - {6500000, 16000, 0x2C}, - {6500000, 22050, 0x25}, - {6500000, 24000, 0x24}, - {6500000, 32000, 0x1C}, - {6500000, 44100, 0x15}, - {6500000, 48000, 0x14}, - - {6400000, 8000, 0x3E}, - {6400000, 11025, 0x37}, - {6400000, 12000, 0x36}, - {6400000, 16000, 0x2E}, - {6400000, 22050, 0x27}, - {6400000, 24000, 0x26}, - {6400000, 32000, 0x1E}, - {6400000, 44100, 0x17}, - {6400000, 48000, 0x16}, -}; - -struct cs42l73_mclkx_div { - u32 mclkx; - u8 ratio; - u8 mclkdiv; -}; - -static struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = { - {5644800, 1, 0}, /* 5644800 */ - {6000000, 1, 0}, /* 6000000 */ - {6144000, 1, 0}, /* 6144000 */ - {11289600, 2, 2}, /* 5644800 */ - {12288000, 2, 2}, /* 6144000 */ - {12000000, 2, 2}, /* 6000000 */ - {13000000, 2, 2}, /* 6500000 */ - {19200000, 3, 3}, /* 6400000 */ - {24000000, 4, 4}, /* 6000000 */ - {26000000, 4, 4}, /* 6500000 */ - {38400000, 6, 5} /* 6400000 */ -}; - -static int cs42l73_get_mclkx_coeff(int mclkx) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cs42l73_mclkx_coeffs); i++) { - if (cs42l73_mclkx_coeffs[i].mclkx == mclkx) - return i; - } - return -EINVAL; -} - -static int cs42l73_get_mclk_coeff(int mclk, int srate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cs42l73_mclk_coeffs); i++) { - if (cs42l73_mclk_coeffs[i].mclk == mclk && - cs42l73_mclk_coeffs[i].srate == srate) - return i; - } - return -EINVAL; - -} - -static int cs42l73_set_mclk(struct snd_soc_dai *dai, unsigned int freq) -{ - struct snd_soc_codec *codec = dai->codec; - struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); - - int mclkx_coeff; - u32 mclk = 0; - u8 dmmcc = 0; - - /* MCLKX -> MCLK */ - mclkx_coeff = cs42l73_get_mclkx_coeff(freq); - if (mclkx_coeff < 0) - return mclkx_coeff; - - mclk = cs42l73_mclkx_coeffs[mclkx_coeff].mclkx / - cs42l73_mclkx_coeffs[mclkx_coeff].ratio; - - dev_dbg(codec->dev, "MCLK%u %u <-> internal MCLK %u\n", - priv->mclksel + 1, cs42l73_mclkx_coeffs[mclkx_coeff].mclkx, - mclk); - - dmmcc = (priv->mclksel << 4) | - (cs42l73_mclkx_coeffs[mclkx_coeff].mclkdiv << 1); - - snd_soc_write(codec, CS42L73_DMMCC, dmmcc); - - priv->sysclk = mclkx_coeff; - priv->mclk = mclk; - - return 0; -} - -static int cs42l73_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case CS42L73_CLKID_MCLK1: - break; - case CS42L73_CLKID_MCLK2: - break; - default: - return -EINVAL; - } - - if ((cs42l73_set_mclk(dai, freq)) < 0) { - dev_err(codec->dev, "Unable to set MCLK for dai %s\n", - dai->name); - return -EINVAL; - } - - priv->mclksel = clk_id; - - return 0; -} - -static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); - u8 id = codec_dai->id; - unsigned int inv, format; - u8 spc, mmcc; - - spc = snd_soc_read(codec, CS42L73_SPC(id)); - mmcc = snd_soc_read(codec, CS42L73_MMCC(id)); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - mmcc |= MS_MASTER; - break; - - case SND_SOC_DAIFMT_CBS_CFS: - mmcc &= ~MS_MASTER; - break; - - default: - return -EINVAL; - } - - format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK); - inv = (fmt & SND_SOC_DAIFMT_INV_MASK); - - switch (format) { - case SND_SOC_DAIFMT_I2S: - spc &= ~SPDIF_PCM; - break; - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - if (mmcc & MS_MASTER) { - dev_err(codec->dev, - "PCM format in slave mode only\n"); - return -EINVAL; - } - if (id == CS42L73_ASP) { - dev_err(codec->dev, - "PCM format is not supported on ASP port\n"); - return -EINVAL; - } - spc |= SPDIF_PCM; - break; - default: - return -EINVAL; - } - - if (spc & SPDIF_PCM) { - /* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */ - spc &= ~(PCM_MODE_MASK | PCM_BIT_ORDER); - switch (format) { - case SND_SOC_DAIFMT_DSP_B: - if (inv == SND_SOC_DAIFMT_IB_IF) - spc |= PCM_MODE0; - if (inv == SND_SOC_DAIFMT_IB_NF) - spc |= PCM_MODE1; - break; - case SND_SOC_DAIFMT_DSP_A: - if (inv == SND_SOC_DAIFMT_IB_IF) - spc |= PCM_MODE1; - break; - default: - return -EINVAL; - } - } - - priv->config[id].spc = spc; - priv->config[id].mmcc = mmcc; - - return 0; -} - -static u32 cs42l73_asrc_rates[] = { - 8000, 11025, 12000, 16000, 22050, - 24000, 32000, 44100, 48000 -}; - -static unsigned int cs42l73_get_xspfs_coeff(u32 rate) -{ - int i; - for (i = 0; i < ARRAY_SIZE(cs42l73_asrc_rates); i++) { - if (cs42l73_asrc_rates[i] == rate) - return i + 1; - } - return 0; /* 0 = Don't know */ -} - -static void cs42l73_update_asrc(struct snd_soc_codec *codec, int id, int srate) -{ - u8 spfs = 0; - - if (srate > 0) - spfs = cs42l73_get_xspfs_coeff(srate); - - switch (id) { - case CS42L73_XSP: - snd_soc_update_bits(codec, CS42L73_VXSPFS, 0x0f, spfs); - break; - case CS42L73_ASP: - snd_soc_update_bits(codec, CS42L73_ASPC, 0x3c, spfs << 2); - break; - case CS42L73_VSP: - snd_soc_update_bits(codec, CS42L73_VXSPFS, 0xf0, spfs << 4); - break; - default: - break; - } -} - -static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec); - int id = dai->id; - int mclk_coeff; - int srate = params_rate(params); - - if (priv->config[id].mmcc & MS_MASTER) { - /* CS42L73 Master */ - /* MCLK -> srate */ - mclk_coeff = - cs42l73_get_mclk_coeff(priv->mclk, srate); - - if (mclk_coeff < 0) - return -EINVAL; - - dev_dbg(codec->dev, - "DAI[%d]: MCLK %u, srate %u, MMCC[5:0] = %x\n", - id, priv->mclk, srate, - cs42l73_mclk_coeffs[mclk_coeff].mmcc); - - priv->config[id].mmcc &= 0xC0; - priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc; - priv->config[id].spc &= 0xFC; - priv->config[id].spc |= MCK_SCLK_MCLK; - } else { - /* CS42L73 Slave */ - priv->config[id].spc &= 0xFC; - priv->config[id].spc |= MCK_SCLK_64FS; - } - /* Update ASRCs */ - priv->config[id].srate = srate; - - snd_soc_write(codec, CS42L73_SPC(id), priv->config[id].spc); - snd_soc_write(codec, CS42L73_MMCC(id), priv->config[id].mmcc); - - cs42l73_update_asrc(codec, id, srate); - - return 0; -} - -static int cs42l73_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); - - switch (level) { - case SND_SOC_BIAS_ON: - snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 0); - snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 0); - break; - - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - regcache_cache_only(cs42l73->regmap, false); - regcache_sync(cs42l73->regmap); - } - snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1); - snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - int id = dai->id; - - return snd_soc_update_bits(codec, CS42L73_SPC(id), - 0x7F, tristate << 7); -} - -static struct snd_pcm_hw_constraint_list constraints_12_24 = { - .count = ARRAY_SIZE(cs42l73_asrc_rates), - .list = cs42l73_asrc_rates, -}; - -static int cs42l73_pcm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_12_24); - return 0; -} - -/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */ -#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT) - - -#define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops cs42l73_ops = { - .startup = cs42l73_pcm_startup, - .hw_params = cs42l73_pcm_hw_params, - .set_fmt = cs42l73_set_dai_fmt, - .set_sysclk = cs42l73_set_sysclk, - .set_tristate = cs42l73_set_tristate, -}; - -static struct snd_soc_dai_driver cs42l73_dai[] = { - { - .name = "cs42l73-xsp", - .id = CS42L73_XSP, - .playback = { - .stream_name = "XSP Playback", - .channels_min = 1, - .channels_max = 2, - .rates = CS42L73_RATES, - .formats = CS42L73_FORMATS, - }, - .capture = { - .stream_name = "XSP Capture", - .channels_min = 1, - .channels_max = 2, - .rates = CS42L73_RATES, - .formats = CS42L73_FORMATS, - }, - .ops = &cs42l73_ops, - .symmetric_rates = 1, - }, - { - .name = "cs42l73-asp", - .id = CS42L73_ASP, - .playback = { - .stream_name = "ASP Playback", - .channels_min = 2, - .channels_max = 2, - .rates = CS42L73_RATES, - .formats = CS42L73_FORMATS, - }, - .capture = { - .stream_name = "ASP Capture", - .channels_min = 2, - .channels_max = 2, - .rates = CS42L73_RATES, - .formats = CS42L73_FORMATS, - }, - .ops = &cs42l73_ops, - .symmetric_rates = 1, - }, - { - .name = "cs42l73-vsp", - .id = CS42L73_VSP, - .playback = { - .stream_name = "VSP Playback", - .channels_min = 1, - .channels_max = 2, - .rates = CS42L73_RATES, - .formats = CS42L73_FORMATS, - }, - .capture = { - .stream_name = "VSP Capture", - .channels_min = 1, - .channels_max = 2, - .rates = CS42L73_RATES, - .formats = CS42L73_FORMATS, - }, - .ops = &cs42l73_ops, - .symmetric_rates = 1, - } -}; - -static int cs42l73_suspend(struct snd_soc_codec *codec) -{ - cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int cs42l73_resume(struct snd_soc_codec *codec) -{ - cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int cs42l73_probe(struct snd_soc_codec *codec) -{ - int ret; - struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); - - codec->control_data = cs42l73->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - regcache_cache_only(cs42l73->regmap, true); - - cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - cs42l73->mclksel = CS42L73_CLKID_MCLK1; /* MCLK1 as master clk */ - cs42l73->mclk = 0; - - return ret; -} - -static int cs42l73_remove(struct snd_soc_codec *codec) -{ - cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = { - .probe = cs42l73_probe, - .remove = cs42l73_remove, - .suspend = cs42l73_suspend, - .resume = cs42l73_resume, - .set_bias_level = cs42l73_set_bias_level, - - .dapm_widgets = cs42l73_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets), - .dapm_routes = cs42l73_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map), - - .controls = cs42l73_snd_controls, - .num_controls = ARRAY_SIZE(cs42l73_snd_controls), -}; - -static struct regmap_config cs42l73_regmap = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = CS42L73_MAX_REGISTER, - .reg_defaults = cs42l73_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(cs42l73_reg_defaults), - .volatile_reg = cs42l73_volatile_register, - .readable_reg = cs42l73_readable_register, - .cache_type = REGCACHE_RBTREE, -}; - -static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) -{ - struct cs42l73_private *cs42l73; - int ret; - unsigned int devid = 0; - unsigned int reg; - - cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private), - GFP_KERNEL); - if (!cs42l73) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); - return -ENOMEM; - } - - i2c_set_clientdata(i2c_client, cs42l73); - - cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap); - if (IS_ERR(cs42l73->regmap)) { - ret = PTR_ERR(cs42l73->regmap); - dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); - goto err; - } - /* initialize codec */ - ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, ®); - devid = (reg & 0xFF) << 12; - - ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_CD, ®); - devid |= (reg & 0xFF) << 4; - - ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, ®); - devid |= (reg & 0xF0) >> 4; - - - if (devid != CS42L73_DEVID) { - ret = -ENODEV; - dev_err(&i2c_client->dev, - "CS42L73 Device ID (%X). Expected %X\n", - devid, CS42L73_DEVID); - goto err_regmap; - } - - ret = regmap_read(cs42l73->regmap, CS42L73_REVID, ®); - if (ret < 0) { - dev_err(&i2c_client->dev, "Get Revision ID failed\n"); - goto err_regmap; - } - - dev_info(&i2c_client->dev, - "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF); - - regcache_cache_only(cs42l73->regmap, true); - - ret = snd_soc_register_codec(&i2c_client->dev, - &soc_codec_dev_cs42l73, cs42l73_dai, - ARRAY_SIZE(cs42l73_dai)); - if (ret < 0) - goto err_regmap; - return 0; - -err_regmap: - regmap_exit(cs42l73->regmap); - -err: - return ret; -} - -static __devexit int cs42l73_i2c_remove(struct i2c_client *client) -{ - struct cs42l73_private *cs42l73 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(cs42l73->regmap); - - return 0; -} - -static const struct i2c_device_id cs42l73_id[] = { - {"cs42l73", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, cs42l73_id); - -static struct i2c_driver cs42l73_i2c_driver = { - .driver = { - .name = "cs42l73", - .owner = THIS_MODULE, - }, - .id_table = cs42l73_id, - .probe = cs42l73_i2c_probe, - .remove = __devexit_p(cs42l73_i2c_remove), - -}; - -static int __init cs42l73_modinit(void) -{ - int ret; - ret = i2c_add_driver(&cs42l73_i2c_driver); - if (ret != 0) { - pr_err("Failed to register CS42L73 I2C driver: %d\n", ret); - return ret; - } - return 0; -} - -module_init(cs42l73_modinit); - -static void __exit cs42l73_exit(void) -{ - i2c_del_driver(&cs42l73_i2c_driver); -} - -module_exit(cs42l73_exit); - -MODULE_DESCRIPTION("ASoC CS42L73 driver"); -MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, "); -MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/cs42l73.h b/ANDROID_3.4.5/sound/soc/codecs/cs42l73.h deleted file mode 100644 index f30a4c4d..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cs42l73.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * ALSA SoC CS42L73 codec driver - * - * Copyright 2011 Cirrus Logic, Inc. - * - * Author: Georgi Vlaev - * Brian Austin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __CS42L73_H__ -#define __CS42L73_H__ - -/* I2C Registers */ -/* I2C Address: 1001010[R/W] - 10010100 = 0x94(Write); 10010101 = 0x95(Read) */ -#define CS42L73_CHIP_ID 0x4a -#define CS42L73_DEVID_AB 0x01 /* Device ID A & B [RO]. */ -#define CS42L73_DEVID_CD 0x02 /* Device ID C & D [RO]. */ -#define CS42L73_DEVID_E 0x03 /* Device ID E [RO]. */ -#define CS42L73_REVID 0x05 /* Revision ID [RO]. */ -#define CS42L73_PWRCTL1 0x06 /* Power Control 1. */ -#define CS42L73_PWRCTL2 0x07 /* Power Control 2. */ -#define CS42L73_PWRCTL3 0x08 /* Power Control 3. */ -#define CS42L73_CPFCHC 0x09 /* Charge Pump Freq. Class H Ctl. */ -#define CS42L73_OLMBMSDC 0x0A /* Output Load, MIC Bias, MIC2 SDT */ -#define CS42L73_DMMCC 0x0B /* Digital MIC & Master Clock Ctl. */ -#define CS42L73_XSPC 0x0C /* Auxiliary Serial Port (XSP) Ctl. */ -#define CS42L73_XSPMMCC 0x0D /* XSP Master Mode Clocking Control. */ -#define CS42L73_ASPC 0x0E /* Audio Serial Port (ASP) Control. */ -#define CS42L73_ASPMMCC 0x0F /* ASP Master Mode Clocking Control. */ -#define CS42L73_VSPC 0x10 /* Voice Serial Port (VSP) Control. */ -#define CS42L73_VSPMMCC 0x11 /* VSP Master Mode Clocking Control. */ -#define CS42L73_VXSPFS 0x12 /* VSP & XSP Sample Rate. */ -#define CS42L73_MIOPC 0x13 /* Misc. Input & Output Path Control. */ -#define CS42L73_ADCIPC 0x14 /* ADC/IP Control. */ -#define CS42L73_MICAPREPGAAVOL 0x15 /* MIC 1 [A] PreAmp, PGAA Vol. */ -#define CS42L73_MICBPREPGABVOL 0x16 /* MIC 2 [B] PreAmp, PGAB Vol. */ -#define CS42L73_IPADVOL 0x17 /* Input Pat7h A Digital Volume. */ -#define CS42L73_IPBDVOL 0x18 /* Input Path B Digital Volume. */ -#define CS42L73_PBDC 0x19 /* Playback Digital Control. */ -#define CS42L73_HLADVOL 0x1A /* HP/Line A Out Digital Vol. */ -#define CS42L73_HLBDVOL 0x1B /* HP/Line B Out Digital Vol. */ -#define CS42L73_SPKDVOL 0x1C /* Spkphone Out [A] Digital Vol. */ -#define CS42L73_ESLDVOL 0x1D /* Ear/Spkphone LO [B] Digital */ -#define CS42L73_HPAAVOL 0x1E /* HP A Analog Volume. */ -#define CS42L73_HPBAVOL 0x1F /* HP B Analog Volume. */ -#define CS42L73_LOAAVOL 0x20 /* Line Out A Analog Volume. */ -#define CS42L73_LOBAVOL 0x21 /* Line Out B Analog Volume. */ -#define CS42L73_STRINV 0x22 /* Stereo Input Path Adv. Vol. */ -#define CS42L73_XSPINV 0x23 /* Auxiliary Port Input Advisory Vol. */ -#define CS42L73_ASPINV 0x24 /* Audio Port Input Advisory Vol. */ -#define CS42L73_VSPINV 0x25 /* Voice Port Input Advisory Vol. */ -#define CS42L73_LIMARATEHL 0x26 /* Lmtr Attack Rate HP/Line. */ -#define CS42L73_LIMRRATEHL 0x27 /* Lmtr Ctl, Rel.Rate HP/Line. */ -#define CS42L73_LMAXHL 0x28 /* Lmtr Thresholds HP/Line. */ -#define CS42L73_LIMARATESPK 0x29 /* Lmtr Attack Rate Spkphone [A]. */ -#define CS42L73_LIMRRATESPK 0x2A /* Lmtr Ctl,Release Rate Spk. [A]. */ -#define CS42L73_LMAXSPK 0x2B /* Lmtr Thresholds Spkphone [A]. */ -#define CS42L73_LIMARATEESL 0x2C /* Lmtr Attack Rate */ -#define CS42L73_LIMRRATEESL 0x2D /* Lmtr Ctl,Release Rate */ -#define CS42L73_LMAXESL 0x2E /* Lmtr Thresholds */ -#define CS42L73_ALCARATE 0x2F /* ALC Enable, Attack Rate AB. */ -#define CS42L73_ALCRRATE 0x30 /* ALC Release Rate AB. */ -#define CS42L73_ALCMINMAX 0x31 /* ALC Thresholds AB. */ -#define CS42L73_NGCAB 0x32 /* Noise Gate Ctl AB. */ -#define CS42L73_ALCNGMC 0x33 /* ALC & Noise Gate Misc Ctl. */ -#define CS42L73_MIXERCTL 0x34 /* Mixer Control. */ -#define CS42L73_HLAIPAA 0x35 /* HP/LO Left Mixer: L. */ -#define CS42L73_HLBIPBA 0x36 /* HP/LO Right Mixer: R. */ -#define CS42L73_HLAXSPAA 0x37 /* HP/LO Left Mixer: XSP L */ -#define CS42L73_HLBXSPBA 0x38 /* HP/LO Right Mixer: XSP R */ -#define CS42L73_HLAASPAA 0x39 /* HP/LO Left Mixer: ASP L */ -#define CS42L73_HLBASPBA 0x3A /* HP/LO Right Mixer: ASP R */ -#define CS42L73_HLAVSPMA 0x3B /* HP/LO Left Mixer: VSP. */ -#define CS42L73_HLBVSPMA 0x3C /* HP/LO Right Mixer: VSP */ -#define CS42L73_XSPAIPAA 0x3D /* XSP Left Mixer: Left */ -#define CS42L73_XSPBIPBA 0x3E /* XSP Rt. Mixer: Right */ -#define CS42L73_XSPAXSPAA 0x3F /* XSP Left Mixer: XSP L */ -#define CS42L73_XSPBXSPBA 0x40 /* XSP Rt. Mixer: XSP R */ -#define CS42L73_XSPAASPAA 0x41 /* XSP Left Mixer: ASP L */ -#define CS42L73_XSPAASPBA 0x42 /* XSP Rt. Mixer: ASP R */ -#define CS42L73_XSPAVSPMA 0x43 /* XSP Left Mixer: VSP */ -#define CS42L73_XSPBVSPMA 0x44 /* XSP Rt. Mixer: VSP */ -#define CS42L73_ASPAIPAA 0x45 /* ASP Left Mixer: Left */ -#define CS42L73_ASPBIPBA 0x46 /* ASP Rt. Mixer: Right */ -#define CS42L73_ASPAXSPAA 0x47 /* ASP Left Mixer: XSP L */ -#define CS42L73_ASPBXSPBA 0x48 /* ASP Rt. Mixer: XSP R */ -#define CS42L73_ASPAASPAA 0x49 /* ASP Left Mixer: ASP L */ -#define CS42L73_ASPBASPBA 0x4A /* ASP Rt. Mixer: ASP R */ -#define CS42L73_ASPAVSPMA 0x4B /* ASP Left Mixer: VSP */ -#define CS42L73_ASPBVSPMA 0x4C /* ASP Rt. Mixer: VSP */ -#define CS42L73_VSPAIPAA 0x4D /* VSP Left Mixer: Left */ -#define CS42L73_VSPBIPBA 0x4E /* VSP Rt. Mixer: Right */ -#define CS42L73_VSPAXSPAA 0x4F /* VSP Left Mixer: XSP L */ -#define CS42L73_VSPBXSPBA 0x50 /* VSP Rt. Mixer: XSP R */ -#define CS42L73_VSPAASPAA 0x51 /* VSP Left Mixer: ASP Left */ -#define CS42L73_VSPBASPBA 0x52 /* VSP Rt. Mixer: ASP Right */ -#define CS42L73_VSPAVSPMA 0x53 /* VSP Left Mixer: VSP */ -#define CS42L73_VSPBVSPMA 0x54 /* VSP Rt. Mixer: VSP */ -#define CS42L73_MMIXCTL 0x55 /* Mono Mixer Controls. */ -#define CS42L73_SPKMIPMA 0x56 /* SPK Mono Mixer: In. Path */ -#define CS42L73_SPKMXSPA 0x57 /* SPK Mono Mixer: XSP Mono/L/R Att. */ -#define CS42L73_SPKMASPA 0x58 /* SPK Mono Mixer: ASP Mono/L/R Att. */ -#define CS42L73_SPKMVSPMA 0x59 /* SPK Mono Mixer: VSP Mono Atten. */ -#define CS42L73_ESLMIPMA 0x5A /* Ear/SpLO Mono Mixer: */ -#define CS42L73_ESLMXSPA 0x5B /* Ear/SpLO Mono Mixer: XSP */ -#define CS42L73_ESLMASPA 0x5C /* Ear/SpLO Mono Mixer: ASP */ -#define CS42L73_ESLMVSPMA 0x5D /* Ear/SpLO Mono Mixer: VSP */ -#define CS42L73_IM1 0x5E /* Interrupt Mask 1. */ -#define CS42L73_IM2 0x5F /* Interrupt Mask 2. */ -#define CS42L73_IS1 0x60 /* Interrupt Status 1 [RO]. */ -#define CS42L73_IS2 0x61 /* Interrupt Status 2 [RO]. */ -#define CS42L73_MAX_REGISTER 0x61 /* Total Registers */ -/* Bitfield Definitions */ - -/* CS42L73_PWRCTL1 */ -#define PDN_ADCB (1 << 7) -#define PDN_DMICB (1 << 6) -#define PDN_ADCA (1 << 5) -#define PDN_DMICA (1 << 4) -#define PDN_LDO (1 << 2) -#define DISCHG_FILT (1 << 1) -#define PDN (1 << 0) - -/* CS42L73_PWRCTL2 */ -#define PDN_MIC2_BIAS (1 << 7) -#define PDN_MIC1_BIAS (1 << 6) -#define PDN_VSP (1 << 4) -#define PDN_ASP_SDOUT (1 << 3) -#define PDN_ASP_SDIN (1 << 2) -#define PDN_XSP_SDOUT (1 << 1) -#define PDN_XSP_SDIN (1 << 0) - -/* CS42L73_PWRCTL3 */ -#define PDN_THMS (1 << 5) -#define PDN_SPKLO (1 << 4) -#define PDN_EAR (1 << 3) -#define PDN_SPK (1 << 2) -#define PDN_LO (1 << 1) -#define PDN_HP (1 << 0) - -/* Thermal Overload Detect. Requires interrupt ... */ -#define THMOVLD_150C 0 -#define THMOVLD_132C 1 -#define THMOVLD_115C 2 -#define THMOVLD_098C 3 - - -/* CS42L73_ASPC, CS42L73_XSPC, CS42L73_VSPC */ -#define SP_3ST (1 << 7) -#define SPDIF_I2S (0 << 6) -#define SPDIF_PCM (1 << 6) -#define PCM_MODE0 (0 << 4) -#define PCM_MODE1 (1 << 4) -#define PCM_MODE2 (2 << 4) -#define PCM_MODE_MASK (3 << 4) -#define PCM_BIT_ORDER (1 << 3) -#define MCK_SCLK_64FS (0 << 0) -#define MCK_SCLK_MCLK (2 << 0) -#define MCK_SCLK_PREMCLK (3 << 0) - -/* CS42L73_xSPMMCC */ -#define MS_MASTER (1 << 7) - - -/* CS42L73_DMMCC */ -#define MCLKDIS (1 << 0) -#define MCLKSEL_MCLK2 (1 << 4) -#define MCLKSEL_MCLK1 (0 << 4) - -/* CS42L73 MCLK derived from MCLK1 or MCLK2 */ -#define CS42L73_CLKID_MCLK1 0 -#define CS42L73_CLKID_MCLK2 1 - -#define CS42L73_MCLKXDIV 0 -#define CS42L73_MMCCDIV 1 - -#define CS42L73_XSP 0 -#define CS42L73_ASP 1 -#define CS42L73_VSP 2 - -/* IS1, IM1 */ -#define MIC2_SDET (1 << 6) -#define THMOVLD (1 << 4) -#define DIGMIXOVFL (1 << 3) -#define IPBOVFL (1 << 1) -#define IPAOVFL (1 << 0) - -/* Analog Softramp */ -#define ANLGOSFT (1 << 0) - -/* HP A/B Analog Mute */ -#define HPA_MUTE (1 << 7) -/* LO A/B Analog Mute */ -#define LOA_MUTE (1 << 7) -/* Digital Mute */ -#define HLAD_MUTE (1 << 0) -#define HLBD_MUTE (1 << 1) -#define SPKD_MUTE (1 << 2) -#define ESLD_MUTE (1 << 3) - -/* Misc defines for codec */ -#define CS42L73_RESET_GPIO 143 - -#define CS42L73_DEVID 0x00042A73 -#define CS42L73_MCLKX_MIN 5644800 -#define CS42L73_MCLKX_MAX 38400000 - -#define CS42L73_SPC(id) (CS42L73_XSPC + (id << 1)) -#define CS42L73_MMCC(id) (CS42L73_XSPMMCC + (id << 1)) -#define CS42L73_SPFS(id) ((id == CS42L73_ASP) ? CS42L73_ASPC : CS42L73_VXSPFS) - -#endif /* __CS42L73_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/cx20442.c b/ANDROID_3.4.5/sound/soc/codecs/cx20442.c deleted file mode 100644 index d5fd00a6..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cx20442.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * cx20442.c -- CX20442 ALSA Soc Audio driver - * - * Copyright 2009 Janusz Krzysztofik - * - * Initially based on sound/soc/codecs/wm8400.c - * Copyright 2008, 2009 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * 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. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "cx20442.h" - - -struct cx20442_priv { - void *control_data; - struct regulator *por; -}; - -#define CX20442_PM 0x0 - -#define CX20442_TELIN 0 -#define CX20442_TELOUT 1 -#define CX20442_MIC 2 -#define CX20442_SPKOUT 3 -#define CX20442_AGC 4 - -static const struct snd_soc_dapm_widget cx20442_dapm_widgets[] = { - SND_SOC_DAPM_OUTPUT("TELOUT"), - SND_SOC_DAPM_OUTPUT("SPKOUT"), - SND_SOC_DAPM_OUTPUT("AGCOUT"), - - SND_SOC_DAPM_MIXER("SPKOUT Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_PGA("TELOUT Amp", CX20442_PM, CX20442_TELOUT, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPKOUT Amp", CX20442_PM, CX20442_SPKOUT, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPKOUT AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0), - - SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), - - SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MICBIAS("TELIN Bias", CX20442_PM, CX20442_TELIN, 0), - SND_SOC_DAPM_MICBIAS("MIC Bias", CX20442_PM, CX20442_MIC, 0), - - SND_SOC_DAPM_PGA("MIC AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0), - - SND_SOC_DAPM_INPUT("TELIN"), - SND_SOC_DAPM_INPUT("MIC"), - SND_SOC_DAPM_INPUT("AGCIN"), -}; - -static const struct snd_soc_dapm_route cx20442_audio_map[] = { - {"TELOUT", NULL, "TELOUT Amp"}, - - {"SPKOUT", NULL, "SPKOUT Mixer"}, - {"SPKOUT Mixer", NULL, "SPKOUT Amp"}, - - {"TELOUT Amp", NULL, "DAC"}, - {"SPKOUT Amp", NULL, "DAC"}, - - {"SPKOUT Mixer", NULL, "SPKOUT AGC"}, - {"SPKOUT AGC", NULL, "AGCIN"}, - - {"AGCOUT", NULL, "MIC AGC"}, - {"MIC AGC", NULL, "MIC"}, - - {"MIC Bias", NULL, "MIC"}, - {"Input Mixer", NULL, "MIC Bias"}, - - {"TELIN Bias", NULL, "TELIN"}, - {"Input Mixer", NULL, "TELIN Bias"}, - - {"ADC", NULL, "Input Mixer"}, -}; - -static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *reg_cache = codec->reg_cache; - - if (reg >= codec->driver->reg_cache_size) - return -EINVAL; - - return reg_cache[reg]; -} - -enum v253_vls { - V253_VLS_NONE = 0, - V253_VLS_T, - V253_VLS_L, - V253_VLS_LT, - V253_VLS_S, - V253_VLS_ST, - V253_VLS_M, - V253_VLS_MST, - V253_VLS_S1, - V253_VLS_S1T, - V253_VLS_MS1T, - V253_VLS_M1, - V253_VLS_M1ST, - V253_VLS_M1S1T, - V253_VLS_H, - V253_VLS_HT, - V253_VLS_MS, - V253_VLS_MS1, - V253_VLS_M1S, - V253_VLS_M1S1, - V253_VLS_TEST, -}; - -static int cx20442_pm_to_v253_vls(u8 value) -{ - switch (value & ~(1 << CX20442_AGC)) { - case 0: - return V253_VLS_T; - case (1 << CX20442_SPKOUT): - case (1 << CX20442_MIC): - case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC): - return V253_VLS_M1S1; - case (1 << CX20442_TELOUT): - case (1 << CX20442_TELIN): - case (1 << CX20442_TELOUT) | (1 << CX20442_TELIN): - return V253_VLS_L; - case (1 << CX20442_TELOUT) | (1 << CX20442_MIC): - return V253_VLS_NONE; - } - return -EINVAL; -} -static int cx20442_pm_to_v253_vsp(u8 value) -{ - switch (value & ~(1 << CX20442_AGC)) { - case (1 << CX20442_SPKOUT): - case (1 << CX20442_MIC): - case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC): - return (bool)(value & (1 << CX20442_AGC)); - } - return (value & (1 << CX20442_AGC)) ? -EINVAL : 0; -} - -static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); - u8 *reg_cache = codec->reg_cache; - int vls, vsp, old, len; - char buf[18]; - - if (reg >= codec->driver->reg_cache_size) - return -EINVAL; - - /* hw_write and control_data pointers required for talking to the modem - * are expected to be set by the line discipline initialization code */ - if (!codec->hw_write || !cx20442->control_data) - return -EIO; - - old = reg_cache[reg]; - reg_cache[reg] = value; - - vls = cx20442_pm_to_v253_vls(value); - if (vls < 0) - return vls; - - vsp = cx20442_pm_to_v253_vsp(value); - if (vsp < 0) - return vsp; - - if ((vls == V253_VLS_T) || - (vls == cx20442_pm_to_v253_vls(old))) { - if (vsp == cx20442_pm_to_v253_vsp(old)) - return 0; - len = snprintf(buf, ARRAY_SIZE(buf), "at+vsp=%d\r", vsp); - } else if (vsp == cx20442_pm_to_v253_vsp(old)) - len = snprintf(buf, ARRAY_SIZE(buf), "at+vls=%d\r", vls); - else - len = snprintf(buf, ARRAY_SIZE(buf), - "at+vls=%d;+vsp=%d\r", vls, vsp); - - if (unlikely(len > (ARRAY_SIZE(buf) - 1))) - return -ENOMEM; - - dev_dbg(codec->dev, "%s: %s\n", __func__, buf); - if (codec->hw_write(cx20442->control_data, buf, len) != len) - return -EIO; - - return 0; -} - - -/* - * Line discpline related code - * - * Any of the callback functions below can be used in two ways: - * 1) registerd by a machine driver as one of line discipline operations, - * 2) called from a machine's provided line discipline callback function - * in case when extra machine specific code must be run as well. - */ - -/* Modem init: echo off, digital speaker off, quiet off, voice mode */ -static const char *v253_init = "ate0m0q0+fclass=8\r"; - -/* Line discipline .open() */ -static int v253_open(struct tty_struct *tty) -{ - int ret, len = strlen(v253_init); - - /* Doesn't make sense without write callback */ - if (!tty->ops->write) - return -EINVAL; - - /* Won't work if no codec pointer has been passed by a card driver */ - if (!tty->disc_data) - return -ENODEV; - - if (tty->ops->write(tty, v253_init, len) != len) { - ret = -EIO; - goto err; - } - /* Actual setup will be performed after the modem responds. */ - return 0; -err: - tty->disc_data = NULL; - return ret; -} - -/* Line discipline .close() */ -static void v253_close(struct tty_struct *tty) -{ - struct snd_soc_codec *codec = tty->disc_data; - struct cx20442_priv *cx20442; - - tty->disc_data = NULL; - - if (!codec) - return; - - cx20442 = snd_soc_codec_get_drvdata(codec); - - /* Prevent the codec driver from further accessing the modem */ - codec->hw_write = NULL; - cx20442->control_data = NULL; - codec->card->pop_time = 0; -} - -/* Line discipline .hangup() */ -static int v253_hangup(struct tty_struct *tty) -{ - v253_close(tty); - return 0; -} - -/* Line discipline .receive_buf() */ -static void v253_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) -{ - struct snd_soc_codec *codec = tty->disc_data; - struct cx20442_priv *cx20442; - - if (!codec) - return; - - cx20442 = snd_soc_codec_get_drvdata(codec); - - if (!cx20442->control_data) { - /* First modem response, complete setup procedure */ - - /* Set up codec driver access to modem controls */ - cx20442->control_data = tty; - codec->hw_write = (hw_write_t)tty->ops->write; - codec->card->pop_time = 1; - } -} - -/* Line discipline .write_wakeup() */ -static void v253_wakeup(struct tty_struct *tty) -{ -} - -struct tty_ldisc_ops v253_ops = { - .magic = TTY_LDISC_MAGIC, - .name = "cx20442", - .owner = THIS_MODULE, - .open = v253_open, - .close = v253_close, - .hangup = v253_hangup, - .receive_buf = v253_receive, - .write_wakeup = v253_wakeup, -}; -EXPORT_SYMBOL_GPL(v253_ops); - - -/* - * Codec DAI - */ - -static struct snd_soc_dai_driver cx20442_dai = { - .name = "cx20442-voice", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}; - -static int cx20442_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); - int err = 0; - - switch (level) { - case SND_SOC_BIAS_PREPARE: - if (codec->dapm.bias_level != SND_SOC_BIAS_STANDBY) - break; - if (IS_ERR(cx20442->por)) - err = PTR_ERR(cx20442->por); - else - err = regulator_enable(cx20442->por); - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level != SND_SOC_BIAS_PREPARE) - break; - if (IS_ERR(cx20442->por)) - err = PTR_ERR(cx20442->por); - else - err = regulator_disable(cx20442->por); - break; - default: - break; - } - if (!err) - codec->dapm.bias_level = level; - - return err; -} - -static int cx20442_codec_probe(struct snd_soc_codec *codec) -{ - struct cx20442_priv *cx20442; - - cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); - if (cx20442 == NULL) - return -ENOMEM; - - cx20442->por = regulator_get(codec->dev, "POR"); - if (IS_ERR(cx20442->por)) - dev_warn(codec->dev, "failed to get the regulator"); - cx20442->control_data = NULL; - - snd_soc_codec_set_drvdata(codec, cx20442); - codec->hw_write = NULL; - codec->card->pop_time = 0; - - return 0; -} - -/* power down chip */ -static int cx20442_codec_remove(struct snd_soc_codec *codec) -{ - struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec); - - if (cx20442->control_data) { - struct tty_struct *tty = cx20442->control_data; - tty_hangup(tty); - } - - if (!IS_ERR(cx20442->por)) { - /* should be already in STANDBY, hence disabled */ - regulator_put(cx20442->por); - } - - snd_soc_codec_set_drvdata(codec, NULL); - kfree(cx20442); - return 0; -} - -static const u8 cx20442_reg; - -static struct snd_soc_codec_driver cx20442_codec_dev = { - .probe = cx20442_codec_probe, - .remove = cx20442_codec_remove, - .set_bias_level = cx20442_set_bias_level, - .reg_cache_default = &cx20442_reg, - .reg_cache_size = 1, - .reg_word_size = sizeof(u8), - .read = cx20442_read_reg_cache, - .write = cx20442_write, - .dapm_widgets = cx20442_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cx20442_dapm_widgets), - .dapm_routes = cx20442_audio_map, - .num_dapm_routes = ARRAY_SIZE(cx20442_audio_map), -}; - -static int cx20442_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &cx20442_codec_dev, &cx20442_dai, 1); -} - -static int __exit cx20442_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver cx20442_platform_driver = { - .driver = { - .name = "cx20442-codec", - .owner = THIS_MODULE, - }, - .probe = cx20442_platform_probe, - .remove = __exit_p(cx20442_platform_remove), -}; - -module_platform_driver(cx20442_platform_driver); - -MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); -MODULE_AUTHOR("Janusz Krzysztofik"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:cx20442-codec"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/cx20442.h b/ANDROID_3.4.5/sound/soc/codecs/cx20442.h deleted file mode 100644 index c7a7c79e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/cx20442.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * cx20442.h -- audio driver for CX20442 - * - * Copyright 2009 Janusz Krzysztofik - * - * 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. - * - */ - -#ifndef _CX20442_CODEC_H -#define _CX20442_CODEC_H - -extern struct tty_ldisc_ops v253_ops; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/da7210.c b/ANDROID_3.4.5/sound/soc/codecs/da7210.c deleted file mode 100644 index 78437117..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/da7210.c +++ /dev/null @@ -1,1151 +0,0 @@ -/* - * DA7210 ALSA Soc codec driver - * - * Copyright (c) 2009 Dialog Semiconductor - * Written by David Chen - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Cleanups by Kuninori Morimoto - * - * Tested on SuperH Ecovec24 board with S16/S24 LE in 48KHz using I2S - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* DA7210 register space */ -#define DA7210_CONTROL 0x01 -#define DA7210_STATUS 0x02 -#define DA7210_STARTUP1 0x03 -#define DA7210_STARTUP2 0x04 -#define DA7210_STARTUP3 0x05 -#define DA7210_MIC_L 0x07 -#define DA7210_MIC_R 0x08 -#define DA7210_AUX1_L 0x09 -#define DA7210_AUX1_R 0x0A -#define DA7210_AUX2 0x0B -#define DA7210_IN_GAIN 0x0C -#define DA7210_INMIX_L 0x0D -#define DA7210_INMIX_R 0x0E -#define DA7210_ADC_HPF 0x0F -#define DA7210_ADC 0x10 -#define DA7210_ADC_EQ1_2 0X11 -#define DA7210_ADC_EQ3_4 0x12 -#define DA7210_ADC_EQ5 0x13 -#define DA7210_DAC_HPF 0x14 -#define DA7210_DAC_L 0x15 -#define DA7210_DAC_R 0x16 -#define DA7210_DAC_SEL 0x17 -#define DA7210_SOFTMUTE 0x18 -#define DA7210_DAC_EQ1_2 0x19 -#define DA7210_DAC_EQ3_4 0x1A -#define DA7210_DAC_EQ5 0x1B -#define DA7210_OUTMIX_L 0x1C -#define DA7210_OUTMIX_R 0x1D -#define DA7210_OUT1_L 0x1E -#define DA7210_OUT1_R 0x1F -#define DA7210_OUT2 0x20 -#define DA7210_HP_L_VOL 0x21 -#define DA7210_HP_R_VOL 0x22 -#define DA7210_HP_CFG 0x23 -#define DA7210_ZERO_CROSS 0x24 -#define DA7210_DAI_SRC_SEL 0x25 -#define DA7210_DAI_CFG1 0x26 -#define DA7210_DAI_CFG3 0x28 -#define DA7210_PLL_DIV1 0x29 -#define DA7210_PLL_DIV2 0x2A -#define DA7210_PLL_DIV3 0x2B -#define DA7210_PLL 0x2C -#define DA7210_ALC_MAX 0x83 -#define DA7210_ALC_MIN 0x84 -#define DA7210_ALC_NOIS 0x85 -#define DA7210_ALC_ATT 0x86 -#define DA7210_ALC_REL 0x87 -#define DA7210_ALC_DEL 0x88 -#define DA7210_A_HID_UNLOCK 0x8A -#define DA7210_A_TEST_UNLOCK 0x8B -#define DA7210_A_PLL1 0x90 -#define DA7210_A_CP_MODE 0xA7 - -/* STARTUP1 bit fields */ -#define DA7210_SC_MST_EN (1 << 0) - -/* MIC_L bit fields */ -#define DA7210_MICBIAS_EN (1 << 6) -#define DA7210_MIC_L_EN (1 << 7) - -/* MIC_R bit fields */ -#define DA7210_MIC_R_EN (1 << 7) - -/* INMIX_L bit fields */ -#define DA7210_IN_L_EN (1 << 7) - -/* INMIX_R bit fields */ -#define DA7210_IN_R_EN (1 << 7) - -/* ADC bit fields */ -#define DA7210_ADC_ALC_EN (1 << 0) -#define DA7210_ADC_L_EN (1 << 3) -#define DA7210_ADC_R_EN (1 << 7) - -/* DAC/ADC HPF fields */ -#define DA7210_VOICE_F0_MASK (0x7 << 4) -#define DA7210_VOICE_F0_25 (1 << 4) -#define DA7210_VOICE_EN (1 << 7) - -/* DAC_SEL bit fields */ -#define DA7210_DAC_L_SRC_DAI_L (4 << 0) -#define DA7210_DAC_L_EN (1 << 3) -#define DA7210_DAC_R_SRC_DAI_R (5 << 4) -#define DA7210_DAC_R_EN (1 << 7) - -/* OUTMIX_L bit fields */ -#define DA7210_OUT_L_EN (1 << 7) - -/* OUTMIX_R bit fields */ -#define DA7210_OUT_R_EN (1 << 7) - -/* HP_CFG bit fields */ -#define DA7210_HP_2CAP_MODE (1 << 1) -#define DA7210_HP_SENSE_EN (1 << 2) -#define DA7210_HP_L_EN (1 << 3) -#define DA7210_HP_MODE (1 << 6) -#define DA7210_HP_R_EN (1 << 7) - -/* DAI_SRC_SEL bit fields */ -#define DA7210_DAI_OUT_L_SRC (6 << 0) -#define DA7210_DAI_OUT_R_SRC (7 << 4) - -/* DAI_CFG1 bit fields */ -#define DA7210_DAI_WORD_S16_LE (0 << 0) -#define DA7210_DAI_WORD_S20_3LE (1 << 0) -#define DA7210_DAI_WORD_S24_LE (2 << 0) -#define DA7210_DAI_WORD_S32_LE (3 << 0) -#define DA7210_DAI_FLEN_64BIT (1 << 2) -#define DA7210_DAI_MODE_SLAVE (0 << 7) -#define DA7210_DAI_MODE_MASTER (1 << 7) - -/* DAI_CFG3 bit fields */ -#define DA7210_DAI_FORMAT_I2SMODE (0 << 0) -#define DA7210_DAI_FORMAT_LEFT_J (1 << 0) -#define DA7210_DAI_FORMAT_RIGHT_J (2 << 0) -#define DA7210_DAI_OE (1 << 3) -#define DA7210_DAI_EN (1 << 7) - -/*PLL_DIV3 bit fields */ -#define DA7210_MCLK_RANGE_10_20_MHZ (1 << 4) -#define DA7210_PLL_BYP (1 << 6) - -/* PLL bit fields */ -#define DA7210_PLL_FS_MASK (0xF << 0) -#define DA7210_PLL_FS_8000 (0x1 << 0) -#define DA7210_PLL_FS_11025 (0x2 << 0) -#define DA7210_PLL_FS_12000 (0x3 << 0) -#define DA7210_PLL_FS_16000 (0x5 << 0) -#define DA7210_PLL_FS_22050 (0x6 << 0) -#define DA7210_PLL_FS_24000 (0x7 << 0) -#define DA7210_PLL_FS_32000 (0x9 << 0) -#define DA7210_PLL_FS_44100 (0xA << 0) -#define DA7210_PLL_FS_48000 (0xB << 0) -#define DA7210_PLL_FS_88200 (0xE << 0) -#define DA7210_PLL_FS_96000 (0xF << 0) -#define DA7210_PLL_EN (0x1 << 7) - -/* SOFTMUTE bit fields */ -#define DA7210_RAMP_EN (1 << 6) - -/* CONTROL bit fields */ -#define DA7210_NOISE_SUP_EN (1 << 3) - -/* IN_GAIN bit fields */ -#define DA7210_INPGA_L_VOL (0x0F << 0) -#define DA7210_INPGA_R_VOL (0xF0 << 0) - -/* ZERO_CROSS bit fields */ -#define DA7210_AUX1_L_ZC (1 << 0) -#define DA7210_AUX1_R_ZC (1 << 1) -#define DA7210_HP_L_ZC (1 << 6) -#define DA7210_HP_R_ZC (1 << 7) - -/* AUX1_L bit fields */ -#define DA7210_AUX1_L_VOL (0x3F << 0) -#define DA7210_AUX1_L_EN (1 << 7) - -/* AUX1_R bit fields */ -#define DA7210_AUX1_R_VOL (0x3F << 0) -#define DA7210_AUX1_R_EN (1 << 7) - -/* AUX2 bit fields */ -#define DA7210_AUX2_EN (1 << 3) - -/* Minimum INPGA and AUX1 volume to enable noise suppression */ -#define DA7210_INPGA_MIN_VOL_NS 0x0A /* 10.5dB */ -#define DA7210_AUX1_MIN_VOL_NS 0x35 /* 6dB */ - -/* OUT1_L bit fields */ -#define DA7210_OUT1_L_EN (1 << 7) - -/* OUT1_R bit fields */ -#define DA7210_OUT1_R_EN (1 << 7) - -/* OUT2 bit fields */ -#define DA7210_OUT2_OUTMIX_R (1 << 5) -#define DA7210_OUT2_OUTMIX_L (1 << 6) -#define DA7210_OUT2_EN (1 << 7) - -#define DA7210_VERSION "0.0.1" - -/* - * Playback Volume - * - * max : 0x3F (+15.0 dB) - * (1.5 dB step) - * min : 0x11 (-54.0 dB) - * mute : 0x10 - * reserved : 0x00 - 0x0F - * - * Reserved area are considered as "mute". - */ -static const unsigned int hp_out_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), - /* -54 dB to +15 dB */ - 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0), -}; - -static const unsigned int lineout_vol_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), - /* -54dB to 15dB */ - 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) -}; - -static const unsigned int mono_vol_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1), - /* -18dB to 6dB */ - 0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0) -}; - -static const unsigned int aux1_vol_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), - /* -48dB to 21dB */ - 0x11, 0x3f, TLV_DB_SCALE_ITEM(-4800, 150, 0) -}; - -static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1); -static const DECLARE_TLV_DB_SCALE(dac_gain_tlv, -7725, 75, 0); -static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(aux2_vol_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(inpga_gain_tlv, -450, 150, 0); - -/* ADC and DAC high pass filter f0 value */ -static const char * const da7210_hpf_cutoff_txt[] = { - "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi" -}; - -static const struct soc_enum da7210_dac_hpf_cutoff = - SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt); - -static const struct soc_enum da7210_adc_hpf_cutoff = - SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt); - -/* ADC and DAC voice (8kHz) high pass cutoff value */ -static const char * const da7210_vf_cutoff_txt[] = { - "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" -}; - -static const struct soc_enum da7210_dac_vf_cutoff = - SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt); - -static const struct soc_enum da7210_adc_vf_cutoff = - SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt); - -static const char *da7210_hp_mode_txt[] = { - "Class H", "Class G" -}; - -static const struct soc_enum da7210_hp_mode_sel = - SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt); - -/* ALC can be enabled only if noise suppression is disabled */ -static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.integer.value[0]) { - /* Check if noise suppression is enabled */ - if (snd_soc_read(codec, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) { - dev_dbg(codec->dev, - "Disable noise suppression to enable ALC\n"); - return -EINVAL; - } - } - /* If all conditions are met or we are actually disabling ALC */ - return snd_soc_put_volsw(kcontrol, ucontrol); -} - -/* Noise suppression can be enabled only if following conditions are met - * ALC disabled - * ZC enabled for HP and AUX1 PGA - * INPGA_L_VOL and INPGA_R_VOL >= 10.5 dB - * AUX1_L_VOL and AUX1_R_VOL >= 6 dB - */ -static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u8 val; - - if (ucontrol->value.integer.value[0]) { - /* Check if ALC is enabled */ - if (snd_soc_read(codec, DA7210_ADC) & DA7210_ADC_ALC_EN) - goto err; - - /* Check ZC for HP and AUX1 PGA */ - if ((snd_soc_read(codec, DA7210_ZERO_CROSS) & - (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | - DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC | - DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC)) - goto err; - - /* Check INPGA_L_VOL and INPGA_R_VOL */ - val = snd_soc_read(codec, DA7210_IN_GAIN); - if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) || - (((val & DA7210_INPGA_R_VOL) >> 4) < - DA7210_INPGA_MIN_VOL_NS)) - goto err; - - /* Check AUX1_L_VOL and AUX1_R_VOL */ - if (((snd_soc_read(codec, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) < - DA7210_AUX1_MIN_VOL_NS) || - ((snd_soc_read(codec, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) < - DA7210_AUX1_MIN_VOL_NS)) - goto err; - } - /* If all conditions are met or we are actually disabling Noise sup */ - return snd_soc_put_volsw(kcontrol, ucontrol); - -err: - return -EINVAL; -} - -static const struct snd_kcontrol_new da7210_snd_controls[] = { - - SOC_DOUBLE_R_TLV("HeadPhone Playback Volume", - DA7210_HP_L_VOL, DA7210_HP_R_VOL, - 0, 0x3F, 0, hp_out_tlv), - SOC_DOUBLE_R_TLV("Digital Playback Volume", - DA7210_DAC_L, DA7210_DAC_R, - 0, 0x77, 1, dac_gain_tlv), - SOC_DOUBLE_R_TLV("Lineout Playback Volume", - DA7210_OUT1_L, DA7210_OUT1_R, - 0, 0x3f, 0, lineout_vol_tlv), - SOC_SINGLE_TLV("Mono Playback Volume", DA7210_OUT2, 0, 0x7, 0, - mono_vol_tlv), - - SOC_DOUBLE_R_TLV("Mic Capture Volume", - DA7210_MIC_L, DA7210_MIC_R, - 0, 0x5, 0, mic_vol_tlv), - SOC_DOUBLE_R_TLV("Aux1 Capture Volume", - DA7210_AUX1_L, DA7210_AUX1_R, - 0, 0x3f, 0, aux1_vol_tlv), - SOC_SINGLE_TLV("Aux2 Capture Volume", DA7210_AUX2, 0, 0x3, 0, - aux2_vol_tlv), - SOC_DOUBLE_TLV("In PGA Capture Volume", DA7210_IN_GAIN, 0, 4, 0xF, 0, - inpga_gain_tlv), - - /* DAC Equalizer controls */ - SOC_SINGLE("DAC EQ Switch", DA7210_DAC_EQ5, 7, 1, 0), - SOC_SINGLE_TLV("DAC EQ1 Volume", DA7210_DAC_EQ1_2, 0, 0xf, 1, - eq_gain_tlv), - SOC_SINGLE_TLV("DAC EQ2 Volume", DA7210_DAC_EQ1_2, 4, 0xf, 1, - eq_gain_tlv), - SOC_SINGLE_TLV("DAC EQ3 Volume", DA7210_DAC_EQ3_4, 0, 0xf, 1, - eq_gain_tlv), - SOC_SINGLE_TLV("DAC EQ4 Volume", DA7210_DAC_EQ3_4, 4, 0xf, 1, - eq_gain_tlv), - SOC_SINGLE_TLV("DAC EQ5 Volume", DA7210_DAC_EQ5, 0, 0xf, 1, - eq_gain_tlv), - - /* ADC Equalizer controls */ - SOC_SINGLE("ADC EQ Switch", DA7210_ADC_EQ5, 7, 1, 0), - SOC_SINGLE_TLV("ADC EQ Master Volume", DA7210_ADC_EQ5, 4, 0x3, - 1, adc_eq_master_gain_tlv), - SOC_SINGLE_TLV("ADC EQ1 Volume", DA7210_ADC_EQ1_2, 0, 0xf, 1, - eq_gain_tlv), - SOC_SINGLE_TLV("ADC EQ2 Volume", DA7210_ADC_EQ1_2, 4, 0xf, 1, - eq_gain_tlv), - SOC_SINGLE_TLV("ADC EQ3 Volume", DA7210_ADC_EQ3_4, 0, 0xf, 1, - eq_gain_tlv), - SOC_SINGLE_TLV("ADC EQ4 Volume", DA7210_ADC_EQ3_4, 4, 0xf, 1, - eq_gain_tlv), - SOC_SINGLE_TLV("ADC EQ5 Volume", DA7210_ADC_EQ5, 0, 0xf, 1, - eq_gain_tlv), - - SOC_SINGLE("DAC HPF Switch", DA7210_DAC_HPF, 3, 1, 0), - SOC_ENUM("DAC HPF Cutoff", da7210_dac_hpf_cutoff), - SOC_SINGLE("DAC Voice Mode Switch", DA7210_DAC_HPF, 7, 1, 0), - SOC_ENUM("DAC Voice Cutoff", da7210_dac_vf_cutoff), - - SOC_SINGLE("ADC HPF Switch", DA7210_ADC_HPF, 3, 1, 0), - SOC_ENUM("ADC HPF Cutoff", da7210_adc_hpf_cutoff), - SOC_SINGLE("ADC Voice Mode Switch", DA7210_ADC_HPF, 7, 1, 0), - SOC_ENUM("ADC Voice Cutoff", da7210_adc_vf_cutoff), - - /* Mute controls */ - SOC_DOUBLE_R("Mic Capture Switch", DA7210_MIC_L, DA7210_MIC_R, 3, 1, 0), - SOC_SINGLE("Aux2 Capture Switch", DA7210_AUX2, 2, 1, 0), - SOC_DOUBLE("ADC Capture Switch", DA7210_ADC, 2, 6, 1, 0), - SOC_SINGLE("Digital Soft Mute Switch", DA7210_SOFTMUTE, 7, 1, 0), - SOC_SINGLE("Digital Soft Mute Rate", DA7210_SOFTMUTE, 0, 0x7, 0), - - /* Zero cross controls */ - SOC_DOUBLE("Aux1 ZC Switch", DA7210_ZERO_CROSS, 0, 1, 1, 0), - SOC_DOUBLE("In PGA ZC Switch", DA7210_ZERO_CROSS, 2, 3, 1, 0), - SOC_DOUBLE("Lineout ZC Switch", DA7210_ZERO_CROSS, 4, 5, 1, 0), - SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0), - - SOC_ENUM("Headphone Class", da7210_hp_mode_sel), - - /* ALC controls */ - SOC_SINGLE_EXT("ALC Enable Switch", DA7210_ADC, 0, 1, 0, - snd_soc_get_volsw, da7210_put_alc_sw), - SOC_SINGLE("ALC Capture Max Volume", DA7210_ALC_MAX, 0, 0x3F, 0), - SOC_SINGLE("ALC Capture Min Volume", DA7210_ALC_MIN, 0, 0x3F, 0), - SOC_SINGLE("ALC Capture Noise Volume", DA7210_ALC_NOIS, 0, 0x3F, 0), - SOC_SINGLE("ALC Capture Attack Rate", DA7210_ALC_ATT, 0, 0xFF, 0), - SOC_SINGLE("ALC Capture Release Rate", DA7210_ALC_REL, 0, 0xFF, 0), - SOC_SINGLE("ALC Capture Release Delay", DA7210_ALC_DEL, 0, 0xFF, 0), - - SOC_SINGLE_EXT("Noise Suppression Enable Switch", DA7210_CONTROL, 3, 1, - 0, snd_soc_get_volsw, da7210_put_noise_sup_sw), -}; - -/* - * DAPM Controls - * - * Current DAPM implementation covers almost all codec components e.g. IOs, - * mixers, PGAs,ADC and DAC. - */ -/* In Mixer Left */ -static const struct snd_kcontrol_new da7210_dapm_inmixl_controls[] = { - SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_L, 0, 1, 0), - SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_L, 1, 1, 0), - SOC_DAPM_SINGLE("Aux1 Left Switch", DA7210_INMIX_L, 2, 1, 0), - SOC_DAPM_SINGLE("Aux2 Switch", DA7210_INMIX_L, 3, 1, 0), - SOC_DAPM_SINGLE("Outmix Left Switch", DA7210_INMIX_L, 4, 1, 0), -}; - -/* In Mixer Right */ -static const struct snd_kcontrol_new da7210_dapm_inmixr_controls[] = { - SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_R, 0, 1, 0), - SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_R, 1, 1, 0), - SOC_DAPM_SINGLE("Aux1 Right Switch", DA7210_INMIX_R, 2, 1, 0), - SOC_DAPM_SINGLE("Aux2 Switch", DA7210_INMIX_R, 3, 1, 0), - SOC_DAPM_SINGLE("Outmix Right Switch", DA7210_INMIX_R, 4, 1, 0), -}; - -/* Out Mixer Left */ -static const struct snd_kcontrol_new da7210_dapm_outmixl_controls[] = { - SOC_DAPM_SINGLE("Aux1 Left Switch", DA7210_OUTMIX_L, 0, 1, 0), - SOC_DAPM_SINGLE("Aux2 Switch", DA7210_OUTMIX_L, 1, 1, 0), - SOC_DAPM_SINGLE("INPGA Left Switch", DA7210_OUTMIX_L, 2, 1, 0), - SOC_DAPM_SINGLE("INPGA Right Switch", DA7210_OUTMIX_L, 3, 1, 0), - SOC_DAPM_SINGLE("DAC Left Switch", DA7210_OUTMIX_L, 4, 1, 0), -}; - -/* Out Mixer Right */ -static const struct snd_kcontrol_new da7210_dapm_outmixr_controls[] = { - SOC_DAPM_SINGLE("Aux1 Right Switch", DA7210_OUTMIX_R, 0, 1, 0), - SOC_DAPM_SINGLE("Aux2 Switch", DA7210_OUTMIX_R, 1, 1, 0), - SOC_DAPM_SINGLE("INPGA Left Switch", DA7210_OUTMIX_R, 2, 1, 0), - SOC_DAPM_SINGLE("INPGA Right Switch", DA7210_OUTMIX_R, 3, 1, 0), - SOC_DAPM_SINGLE("DAC Right Switch", DA7210_OUTMIX_R, 4, 1, 0), -}; - -/* Mono Mixer */ -static const struct snd_kcontrol_new da7210_dapm_monomix_controls[] = { - SOC_DAPM_SINGLE("INPGA Right Switch", DA7210_OUT2, 3, 1, 0), - SOC_DAPM_SINGLE("INPGA Left Switch", DA7210_OUT2, 4, 1, 0), - SOC_DAPM_SINGLE("Outmix Right Switch", DA7210_OUT2, 5, 1, 0), - SOC_DAPM_SINGLE("Outmix Left Switch", DA7210_OUT2, 6, 1, 0), -}; - -/* DAPM widgets */ -static const struct snd_soc_dapm_widget da7210_dapm_widgets[] = { - /* Input Side */ - /* Input Lines */ - SND_SOC_DAPM_INPUT("MICL"), - SND_SOC_DAPM_INPUT("MICR"), - SND_SOC_DAPM_INPUT("AUX1L"), - SND_SOC_DAPM_INPUT("AUX1R"), - SND_SOC_DAPM_INPUT("AUX2"), - - /* Input PGAs */ - SND_SOC_DAPM_PGA("Mic Left", DA7210_STARTUP3, 0, 1, NULL, 0), - SND_SOC_DAPM_PGA("Mic Right", DA7210_STARTUP3, 1, 1, NULL, 0), - SND_SOC_DAPM_PGA("Aux1 Left", DA7210_STARTUP3, 2, 1, NULL, 0), - SND_SOC_DAPM_PGA("Aux1 Right", DA7210_STARTUP3, 3, 1, NULL, 0), - SND_SOC_DAPM_PGA("Aux2 Mono", DA7210_STARTUP3, 4, 1, NULL, 0), - - SND_SOC_DAPM_PGA("INPGA Left", DA7210_INMIX_L, 7, 0, NULL, 0), - SND_SOC_DAPM_PGA("INPGA Right", DA7210_INMIX_R, 7, 0, NULL, 0), - - /* MICBIAS */ - SND_SOC_DAPM_SUPPLY("Mic Bias", DA7210_MIC_L, 6, 0, NULL, 0), - - /* Input Mixers */ - SND_SOC_DAPM_MIXER("In Mixer Left", SND_SOC_NOPM, 0, 0, - &da7210_dapm_inmixl_controls[0], - ARRAY_SIZE(da7210_dapm_inmixl_controls)), - - SND_SOC_DAPM_MIXER("In Mixer Right", SND_SOC_NOPM, 0, 0, - &da7210_dapm_inmixr_controls[0], - ARRAY_SIZE(da7210_dapm_inmixr_controls)), - - /* ADCs */ - SND_SOC_DAPM_ADC("ADC Left", "Capture", DA7210_STARTUP3, 5, 1), - SND_SOC_DAPM_ADC("ADC Right", "Capture", DA7210_STARTUP3, 6, 1), - - /* Output Side */ - /* DACs */ - SND_SOC_DAPM_DAC("DAC Left", "Playback", DA7210_STARTUP2, 5, 1), - SND_SOC_DAPM_DAC("DAC Right", "Playback", DA7210_STARTUP2, 6, 1), - - /* Output Mixers */ - SND_SOC_DAPM_MIXER("Out Mixer Left", SND_SOC_NOPM, 0, 0, - &da7210_dapm_outmixl_controls[0], - ARRAY_SIZE(da7210_dapm_outmixl_controls)), - - SND_SOC_DAPM_MIXER("Out Mixer Right", SND_SOC_NOPM, 0, 0, - &da7210_dapm_outmixr_controls[0], - ARRAY_SIZE(da7210_dapm_outmixr_controls)), - - SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, - &da7210_dapm_monomix_controls[0], - ARRAY_SIZE(da7210_dapm_monomix_controls)), - - /* Output PGAs */ - SND_SOC_DAPM_PGA("OUTPGA Left Enable", DA7210_OUTMIX_L, 7, 0, NULL, 0), - SND_SOC_DAPM_PGA("OUTPGA Right Enable", DA7210_OUTMIX_R, 7, 0, NULL, 0), - - SND_SOC_DAPM_PGA("Out1 Left", DA7210_STARTUP2, 0, 1, NULL, 0), - SND_SOC_DAPM_PGA("Out1 Right", DA7210_STARTUP2, 1, 1, NULL, 0), - SND_SOC_DAPM_PGA("Out2 Mono", DA7210_STARTUP2, 2, 1, NULL, 0), - SND_SOC_DAPM_PGA("Headphone Left", DA7210_STARTUP2, 3, 1, NULL, 0), - SND_SOC_DAPM_PGA("Headphone Right", DA7210_STARTUP2, 4, 1, NULL, 0), - - /* Output Lines */ - SND_SOC_DAPM_OUTPUT("OUT1L"), - SND_SOC_DAPM_OUTPUT("OUT1R"), - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - SND_SOC_DAPM_OUTPUT("OUT2"), -}; - -/* DAPM audio route definition */ -static const struct snd_soc_dapm_route da7210_audio_map[] = { - /* Dest Connecting Widget source */ - /* Input path */ - {"Mic Left", NULL, "MICL"}, - {"Mic Right", NULL, "MICR"}, - {"Aux1 Left", NULL, "AUX1L"}, - {"Aux1 Right", NULL, "AUX1R"}, - {"Aux2 Mono", NULL, "AUX2"}, - - {"In Mixer Left", "Mic Left Switch", "Mic Left"}, - {"In Mixer Left", "Mic Right Switch", "Mic Right"}, - {"In Mixer Left", "Aux1 Left Switch", "Aux1 Left"}, - {"In Mixer Left", "Aux2 Switch", "Aux2 Mono"}, - {"In Mixer Left", "Outmix Left Switch", "Out Mixer Left"}, - - {"In Mixer Right", "Mic Right Switch", "Mic Right"}, - {"In Mixer Right", "Mic Left Switch", "Mic Left"}, - {"In Mixer Right", "Aux1 Right Switch", "Aux1 Right"}, - {"In Mixer Right", "Aux2 Switch", "Aux2 Mono"}, - {"In Mixer Right", "Outmix Right Switch", "Out Mixer Right"}, - - {"INPGA Left", NULL, "In Mixer Left"}, - {"ADC Left", NULL, "INPGA Left"}, - - {"INPGA Right", NULL, "In Mixer Right"}, - {"ADC Right", NULL, "INPGA Right"}, - - /* Output path */ - {"Out Mixer Left", "Aux1 Left Switch", "Aux1 Left"}, - {"Out Mixer Left", "Aux2 Switch", "Aux2 Mono"}, - {"Out Mixer Left", "INPGA Left Switch", "INPGA Left"}, - {"Out Mixer Left", "INPGA Right Switch", "INPGA Right"}, - {"Out Mixer Left", "DAC Left Switch", "DAC Left"}, - - {"Out Mixer Right", "Aux1 Right Switch", "Aux1 Right"}, - {"Out Mixer Right", "Aux2 Switch", "Aux2 Mono"}, - {"Out Mixer Right", "INPGA Right Switch", "INPGA Right"}, - {"Out Mixer Right", "INPGA Left Switch", "INPGA Left"}, - {"Out Mixer Right", "DAC Right Switch", "DAC Right"}, - - {"Mono Mixer", "INPGA Right Switch", "INPGA Right"}, - {"Mono Mixer", "INPGA Left Switch", "INPGA Left"}, - {"Mono Mixer", "Outmix Right Switch", "Out Mixer Right"}, - {"Mono Mixer", "Outmix Left Switch", "Out Mixer Left"}, - - {"OUTPGA Left Enable", NULL, "Out Mixer Left"}, - {"OUTPGA Right Enable", NULL, "Out Mixer Right"}, - - {"Out1 Left", NULL, "OUTPGA Left Enable"}, - {"OUT1L", NULL, "Out1 Left"}, - - {"Out1 Right", NULL, "OUTPGA Right Enable"}, - {"OUT1R", NULL, "Out1 Right"}, - - {"Headphone Left", NULL, "OUTPGA Left Enable"}, - {"HPL", NULL, "Headphone Left"}, - - {"Headphone Right", NULL, "OUTPGA Right Enable"}, - {"HPR", NULL, "Headphone Right"}, - - {"Out2 Mono", NULL, "Mono Mixer"}, - {"OUT2", NULL, "Out2 Mono"}, -}; - -/* Codec private data */ -struct da7210_priv { - struct regmap *regmap; -}; - -static struct reg_default da7210_reg_defaults[] = { - { 0x01, 0x11 }, - { 0x03, 0x00 }, - { 0x04, 0x00 }, - { 0x05, 0x00 }, - { 0x06, 0x00 }, - { 0x07, 0x00 }, - { 0x08, 0x00 }, - { 0x09, 0x00 }, - { 0x0a, 0x00 }, - { 0x0b, 0x00 }, - { 0x0c, 0x00 }, - { 0x0d, 0x00 }, - { 0x0e, 0x00 }, - { 0x0f, 0x08 }, - { 0x10, 0x00 }, - { 0x11, 0x00 }, - { 0x12, 0x00 }, - { 0x13, 0x00 }, - { 0x14, 0x08 }, - { 0x15, 0x10 }, - { 0x16, 0x10 }, - { 0x17, 0x54 }, - { 0x18, 0x40 }, - { 0x19, 0x00 }, - { 0x1a, 0x00 }, - { 0x1b, 0x00 }, - { 0x1c, 0x00 }, - { 0x1d, 0x00 }, - { 0x1e, 0x00 }, - { 0x1f, 0x00 }, - { 0x20, 0x00 }, - { 0x21, 0x00 }, - { 0x22, 0x00 }, - { 0x23, 0x02 }, - { 0x24, 0x00 }, - { 0x25, 0x76 }, - { 0x26, 0x00 }, - { 0x27, 0x00 }, - { 0x28, 0x04 }, - { 0x29, 0x00 }, - { 0x2a, 0x00 }, - { 0x2b, 0x30 }, - { 0x2c, 0x2A }, - { 0x83, 0x00 }, - { 0x84, 0x00 }, - { 0x85, 0x00 }, - { 0x86, 0x00 }, - { 0x87, 0x00 }, - { 0x88, 0x00 }, -}; - -static bool da7210_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case DA7210_A_HID_UNLOCK: - case DA7210_A_TEST_UNLOCK: - case DA7210_A_PLL1: - case DA7210_A_CP_MODE: - return false; - default: - return true; - } -} - -static bool da7210_volatile_register(struct device *dev, - unsigned int reg) -{ - switch (reg) { - case DA7210_STATUS: - return true; - default: - return false; - } -} - -/* - * Set PCM DAI word length. - */ -static int da7210_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u32 dai_cfg1; - u32 fs, bypass; - - /* set DAI source to Left and Right ADC */ - snd_soc_write(codec, DA7210_DAI_SRC_SEL, - DA7210_DAI_OUT_R_SRC | DA7210_DAI_OUT_L_SRC); - - /* Enable DAI */ - snd_soc_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN); - - dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - dai_cfg1 |= DA7210_DAI_WORD_S16_LE; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - dai_cfg1 |= DA7210_DAI_WORD_S20_3LE; - break; - case SNDRV_PCM_FORMAT_S24_LE: - dai_cfg1 |= DA7210_DAI_WORD_S24_LE; - break; - case SNDRV_PCM_FORMAT_S32_LE: - dai_cfg1 |= DA7210_DAI_WORD_S32_LE; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1); - - switch (params_rate(params)) { - case 8000: - fs = DA7210_PLL_FS_8000; - bypass = DA7210_PLL_BYP; - break; - case 11025: - fs = DA7210_PLL_FS_11025; - bypass = 0; - break; - case 12000: - fs = DA7210_PLL_FS_12000; - bypass = DA7210_PLL_BYP; - break; - case 16000: - fs = DA7210_PLL_FS_16000; - bypass = DA7210_PLL_BYP; - break; - case 22050: - fs = DA7210_PLL_FS_22050; - bypass = 0; - break; - case 32000: - fs = DA7210_PLL_FS_32000; - bypass = DA7210_PLL_BYP; - break; - case 44100: - fs = DA7210_PLL_FS_44100; - bypass = 0; - break; - case 48000: - fs = DA7210_PLL_FS_48000; - bypass = DA7210_PLL_BYP; - break; - case 88200: - fs = DA7210_PLL_FS_88200; - bypass = 0; - break; - case 96000: - fs = DA7210_PLL_FS_96000; - bypass = DA7210_PLL_BYP; - break; - default: - return -EINVAL; - } - - /* Disable active mode */ - snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0); - - snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs); - snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass); - - /* Enable active mode */ - snd_soc_update_bits(codec, DA7210_STARTUP1, - DA7210_SC_MST_EN, DA7210_SC_MST_EN); - - return 0; -} - -/* - * Set DAI mode and Format - */ -static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u32 dai_cfg1; - u32 dai_cfg3; - - dai_cfg1 = 0x7f & snd_soc_read(codec, DA7210_DAI_CFG1); - dai_cfg3 = 0xfc & snd_soc_read(codec, DA7210_DAI_CFG3); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - dai_cfg1 |= DA7210_DAI_MODE_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: - dai_cfg1 |= DA7210_DAI_MODE_SLAVE; - break; - default: - return -EINVAL; - } - - /* FIXME - * - * It support I2S only now - */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - dai_cfg3 |= DA7210_DAI_FORMAT_I2SMODE; - break; - case SND_SOC_DAIFMT_LEFT_J: - dai_cfg3 |= DA7210_DAI_FORMAT_LEFT_J; - break; - case SND_SOC_DAIFMT_RIGHT_J: - dai_cfg3 |= DA7210_DAI_FORMAT_RIGHT_J; - break; - default: - return -EINVAL; - } - - /* FIXME - * - * It support 64bit data transmission only now - */ - dai_cfg1 |= DA7210_DAI_FLEN_64BIT; - - snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1); - snd_soc_write(codec, DA7210_DAI_CFG3, dai_cfg3); - - return 0; -} - -static int da7210_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u8 mute_reg = snd_soc_read(codec, DA7210_DAC_HPF) & 0xFB; - - if (mute) - snd_soc_write(codec, DA7210_DAC_HPF, mute_reg | 0x4); - else - snd_soc_write(codec, DA7210_DAC_HPF, mute_reg); - return 0; -} - -#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -/* DAI operations */ -static const struct snd_soc_dai_ops da7210_dai_ops = { - .hw_params = da7210_hw_params, - .set_fmt = da7210_set_dai_fmt, - .digital_mute = da7210_mute, -}; - -static struct snd_soc_dai_driver da7210_dai = { - .name = "da7210-hifi", - /* playback capabilities */ - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = DA7210_FORMATS, - }, - /* capture capabilities */ - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = DA7210_FORMATS, - }, - .ops = &da7210_dai_ops, - .symmetric_rates = 1, -}; - -static int da7210_probe(struct snd_soc_codec *codec) -{ - struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec); - int ret; - - dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - - codec->control_data = da7210->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* FIXME - * - * This driver use fixed value here - * And below settings expects MCLK = 12.288MHz - * - * When you select different MCLK, please check... - * DA7210_PLL_DIV1 val - * DA7210_PLL_DIV2 val - * DA7210_PLL_DIV3 val - * DA7210_PLL_DIV3 :: DA7210_MCLK_RANGExxx - */ - - /* - * make sure that DA7210 use bypass mode before start up - */ - snd_soc_write(codec, DA7210_STARTUP1, 0); - snd_soc_write(codec, DA7210_PLL_DIV3, - DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); - - /* - * ADC settings - */ - - /* Enable Left & Right MIC PGA and Mic Bias */ - snd_soc_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN); - snd_soc_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN); - - /* Enable Left and Right input PGA */ - snd_soc_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN); - snd_soc_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN); - - /* Enable Left and Right ADC */ - snd_soc_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN); - - /* - * DAC settings - */ - - /* Enable Left and Right DAC */ - snd_soc_write(codec, DA7210_DAC_SEL, - DA7210_DAC_L_SRC_DAI_L | DA7210_DAC_L_EN | - DA7210_DAC_R_SRC_DAI_R | DA7210_DAC_R_EN); - - /* Enable Left and Right out PGA */ - snd_soc_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN); - snd_soc_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN); - - /* Enable Left and Right HeadPhone PGA */ - snd_soc_write(codec, DA7210_HP_CFG, - DA7210_HP_2CAP_MODE | DA7210_HP_SENSE_EN | - DA7210_HP_L_EN | DA7210_HP_MODE | DA7210_HP_R_EN); - - /* Enable ramp mode for DAC gain update */ - snd_soc_write(codec, DA7210_SOFTMUTE, DA7210_RAMP_EN); - - /* - * For DA7210 codec, there are two ways to enable/disable analog IOs - * and ADC/DAC, - * (1) Using "Enable Bit" of register associated with that IO - * (or ADC/DAC) - * e.g. Mic Left can be enabled using bit 7 of MIC_L(0x7) reg - * - * (2) Using "Standby Bit" of STARTUP2 or STARTUP3 register - * e.g. Mic left can be put to STANDBY using bit 0 of STARTUP3(0x5) - * - * Out of these two methods, the one using STANDBY bits is preferred - * way to enable/disable individual blocks. This is because STANDBY - * registers are part of system controller which allows system power - * up/down in a controlled, pop-free manner. Also, as per application - * note of DA7210, STANDBY register bits are only effective if a - * particular IO (or ADC/DAC) is already enabled using enable/disable - * register bits. Keeping these things in mind, current DAPM - * implementation manipulates only STANDBY bits. - * - * Overall implementation can be outlined as below, - * - * - "Enable bit" of an IO or ADC/DAC is used to enable it in probe() - * - "STANDBY bit" is controlled by DAPM - */ - - /* Enable Line out amplifiers */ - snd_soc_write(codec, DA7210_OUT1_L, DA7210_OUT1_L_EN); - snd_soc_write(codec, DA7210_OUT1_R, DA7210_OUT1_R_EN); - snd_soc_write(codec, DA7210_OUT2, DA7210_OUT2_EN | - DA7210_OUT2_OUTMIX_L | DA7210_OUT2_OUTMIX_R); - - /* Enable Aux1 */ - snd_soc_write(codec, DA7210_AUX1_L, DA7210_AUX1_L_EN); - snd_soc_write(codec, DA7210_AUX1_R, DA7210_AUX1_R_EN); - /* Enable Aux2 */ - snd_soc_write(codec, DA7210_AUX2, DA7210_AUX2_EN); - - /* Diable PLL and bypass it */ - snd_soc_write(codec, DA7210_PLL, DA7210_PLL_FS_48000); - - /* - * If 48kHz sound came, it use bypass mode, - * and when it is 44.1kHz, it use PLL. - * - * This time, this driver sets PLL always ON - * and controls bypass/PLL mode by switching - * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit. - * see da7210_hw_params - */ - snd_soc_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */ - snd_soc_write(codec, DA7210_PLL_DIV2, 0x99); - snd_soc_write(codec, DA7210_PLL_DIV3, 0x0A | - DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP); - snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN); - - /* As suggested by Dialog */ - /* unlock */ - regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x8B); - regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0xB4); - regmap_write(da7210->regmap, DA7210_A_PLL1, 0x01); - regmap_write(da7210->regmap, DA7210_A_CP_MODE, 0x7C); - /* re-lock */ - regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x00); - regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0x00); - - /* Activate all enabled subsystem */ - snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); - - dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_da7210 = { - .probe = da7210_probe, - - .controls = da7210_snd_controls, - .num_controls = ARRAY_SIZE(da7210_snd_controls), - - .dapm_widgets = da7210_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(da7210_dapm_widgets), - .dapm_routes = da7210_audio_map, - .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), -}; - -static struct regmap_config da7210_regmap = { - .reg_bits = 8, - .val_bits = 8, - - .reg_defaults = da7210_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(da7210_reg_defaults), - .volatile_reg = da7210_volatile_register, - .readable_reg = da7210_readable_register, - .cache_type = REGCACHE_RBTREE, -}; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int __devinit da7210_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct da7210_priv *da7210; - int ret; - - da7210 = devm_kzalloc(&i2c->dev, sizeof(struct da7210_priv), - GFP_KERNEL); - if (!da7210) - return -ENOMEM; - - i2c_set_clientdata(i2c, da7210); - - da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap); - if (IS_ERR(da7210->regmap)) { - ret = PTR_ERR(da7210->regmap); - dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); - return ret; - } - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_da7210, &da7210_dai, 1); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); - goto err_regmap; - } - return ret; - -err_regmap: - regmap_exit(da7210->regmap); - - return ret; -} - -static int __devexit da7210_i2c_remove(struct i2c_client *client) -{ - struct da7210_priv *da7210 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(da7210->regmap); - return 0; -} - -static const struct i2c_device_id da7210_i2c_id[] = { - { "da7210", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, da7210_i2c_id); - -/* I2C codec control layer */ -static struct i2c_driver da7210_i2c_driver = { - .driver = { - .name = "da7210-codec", - .owner = THIS_MODULE, - }, - .probe = da7210_i2c_probe, - .remove = __devexit_p(da7210_i2c_remove), - .id_table = da7210_i2c_id, -}; -#endif - -static int __init da7210_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&da7210_i2c_driver); -#endif - return ret; -} -module_init(da7210_modinit); - -static void __exit da7210_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&da7210_i2c_driver); -#endif -} -module_exit(da7210_exit); - -MODULE_DESCRIPTION("ASoC DA7210 driver"); -MODULE_AUTHOR("David Chen, Kuninori Morimoto"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/dfbmcs320.c b/ANDROID_3.4.5/sound/soc/codecs/dfbmcs320.c deleted file mode 100644 index bfe46aa9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/dfbmcs320.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Driver for the DFBM-CS320 bluetooth module - * Copyright 2011 Lars-Peter Clausen - * - * 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. - * - */ - -#include -#include -#include - -#include - -static struct snd_soc_dai_driver dfbmcs320_dai = { - .name = "dfbmcs320-pcm", - .playback = { - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}; - -static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320; - -static int __devinit dfbmcs320_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320, - &dfbmcs320_dai, 1); -} - -static int __devexit dfbmcs320_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - - return 0; -} - -static struct platform_driver dfmcs320_driver = { - .driver = { - .name = "dfbmcs320", - .owner = THIS_MODULE, - }, - .probe = dfbmcs320_probe, - .remove = __devexit_p(dfbmcs320_remove), -}; - -module_platform_driver(dfmcs320_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/dmic.c b/ANDROID_3.4.5/sound/soc/codecs/dmic.c deleted file mode 100644 index 3e929f07..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/dmic.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * dmic.c -- SoC audio for Generic Digital MICs - * - * Author: Liam Girdwood - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -static struct snd_soc_dai_driver dmic_dai = { - .name = "dmic-hifi", - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .formats = SNDRV_PCM_FMTBIT_S32_LE - | SNDRV_PCM_FMTBIT_S24_LE - | SNDRV_PCM_FMTBIT_S16_LE, - }, -}; - -static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = { - SND_SOC_DAPM_AIF_OUT("DMIC AIF", "Capture", 0, - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_INPUT("DMic"), -}; - -static const struct snd_soc_dapm_route intercon[] = { - {"DMIC AIF", NULL, "DMic"}, -}; - -static int dmic_probe(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, dmic_dapm_widgets, - ARRAY_SIZE(dmic_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - snd_soc_dapm_new_widgets(dapm); - - return 0; -} - -static struct snd_soc_codec_driver soc_dmic = { - .probe = dmic_probe, -}; - -static int __devinit dmic_dev_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_dmic, &dmic_dai, 1); -} - -static int __devexit dmic_dev_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -MODULE_ALIAS("platform:dmic-codec"); - -static struct platform_driver dmic_driver = { - .driver = { - .name = "dmic-codec", - .owner = THIS_MODULE, - }, - .probe = dmic_dev_probe, - .remove = __devexit_p(dmic_dev_remove), -}; - -module_platform_driver(dmic_driver); - -MODULE_DESCRIPTION("Generic DMIC driver"); -MODULE_AUTHOR("Liam Girdwood "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/jz4740.c b/ANDROID_3.4.5/sound/soc/codecs/jz4740.c deleted file mode 100644 index 4624e752..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/jz4740.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright (C) 2009-2010, Lars-Peter Clausen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#define JZ4740_REG_CODEC_1 0x0 -#define JZ4740_REG_CODEC_2 0x1 - -#define JZ4740_CODEC_1_LINE_ENABLE BIT(29) -#define JZ4740_CODEC_1_MIC_ENABLE BIT(28) -#define JZ4740_CODEC_1_SW1_ENABLE BIT(27) -#define JZ4740_CODEC_1_ADC_ENABLE BIT(26) -#define JZ4740_CODEC_1_SW2_ENABLE BIT(25) -#define JZ4740_CODEC_1_DAC_ENABLE BIT(24) -#define JZ4740_CODEC_1_VREF_DISABLE BIT(20) -#define JZ4740_CODEC_1_VREF_AMP_DISABLE BIT(19) -#define JZ4740_CODEC_1_VREF_PULLDOWN BIT(18) -#define JZ4740_CODEC_1_VREF_LOW_CURRENT BIT(17) -#define JZ4740_CODEC_1_VREF_HIGH_CURRENT BIT(16) -#define JZ4740_CODEC_1_HEADPHONE_DISABLE BIT(14) -#define JZ4740_CODEC_1_HEADPHONE_AMP_CHANGE_ANY BIT(13) -#define JZ4740_CODEC_1_HEADPHONE_CHARGE BIT(12) -#define JZ4740_CODEC_1_HEADPHONE_PULLDOWN (BIT(11) | BIT(10)) -#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M BIT(9) -#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN BIT(8) -#define JZ4740_CODEC_1_SUSPEND BIT(1) -#define JZ4740_CODEC_1_RESET BIT(0) - -#define JZ4740_CODEC_1_LINE_ENABLE_OFFSET 29 -#define JZ4740_CODEC_1_MIC_ENABLE_OFFSET 28 -#define JZ4740_CODEC_1_SW1_ENABLE_OFFSET 27 -#define JZ4740_CODEC_1_ADC_ENABLE_OFFSET 26 -#define JZ4740_CODEC_1_SW2_ENABLE_OFFSET 25 -#define JZ4740_CODEC_1_DAC_ENABLE_OFFSET 24 -#define JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET 14 -#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN_OFFSET 8 - -#define JZ4740_CODEC_2_INPUT_VOLUME_MASK 0x1f0000 -#define JZ4740_CODEC_2_SAMPLE_RATE_MASK 0x000f00 -#define JZ4740_CODEC_2_MIC_BOOST_GAIN_MASK 0x000030 -#define JZ4740_CODEC_2_HEADPHONE_VOLUME_MASK 0x000003 - -#define JZ4740_CODEC_2_INPUT_VOLUME_OFFSET 16 -#define JZ4740_CODEC_2_SAMPLE_RATE_OFFSET 8 -#define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET 4 -#define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET 0 - -static const uint32_t jz4740_codec_regs[] = { - 0x021b2302, 0x00170803, -}; - -struct jz4740_codec { - void __iomem *base; - struct resource *mem; -}; - -static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); - return readl(jz4740_codec->base + (reg << 2)); -} - -static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int val) -{ - struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); - u32 *cache = codec->reg_cache; - - cache[reg] = val; - writel(val, jz4740_codec->base + (reg << 2)); - - return 0; -} - -static const struct snd_kcontrol_new jz4740_codec_controls[] = { - SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2, - JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0), - SOC_SINGLE("Master Capture Volume", JZ4740_REG_CODEC_2, - JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0), - SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1), - SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2, - JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0), -}; - -static const struct snd_kcontrol_new jz4740_codec_output_controls[] = { - SOC_DAPM_SINGLE("Bypass Switch", JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_SW1_ENABLE_OFFSET, 1, 0), - SOC_DAPM_SINGLE("DAC Switch", JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_SW2_ENABLE_OFFSET, 1, 0), -}; - -static const struct snd_kcontrol_new jz4740_codec_input_controls[] = { - SOC_DAPM_SINGLE("Line Capture Switch", JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_LINE_ENABLE_OFFSET, 1, 0), - SOC_DAPM_SINGLE("Mic Capture Switch", JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_MIC_ENABLE_OFFSET, 1, 0), -}; - -static const struct snd_soc_dapm_widget jz4740_codec_dapm_widgets[] = { - SND_SOC_DAPM_ADC("ADC", "Capture", JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_ADC_ENABLE_OFFSET, 0), - SND_SOC_DAPM_DAC("DAC", "Playback", JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_DAC_ENABLE_OFFSET, 0), - - SND_SOC_DAPM_MIXER("Output Mixer", JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_HEADPHONE_POWERDOWN_OFFSET, 1, - jz4740_codec_output_controls, - ARRAY_SIZE(jz4740_codec_output_controls)), - - SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0, - jz4740_codec_input_controls, - ARRAY_SIZE(jz4740_codec_input_controls)), - SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_OUTPUT("LOUT"), - SND_SOC_DAPM_OUTPUT("ROUT"), - - SND_SOC_DAPM_INPUT("MIC"), - SND_SOC_DAPM_INPUT("LIN"), - SND_SOC_DAPM_INPUT("RIN"), -}; - -static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = { - {"Line Input", NULL, "LIN"}, - {"Line Input", NULL, "RIN"}, - - {"Input Mixer", "Line Capture Switch", "Line Input"}, - {"Input Mixer", "Mic Capture Switch", "MIC"}, - - {"ADC", NULL, "Input Mixer"}, - - {"Output Mixer", "Bypass Switch", "Input Mixer"}, - {"Output Mixer", "DAC Switch", "DAC"}, - - {"LOUT", NULL, "Output Mixer"}, - {"ROUT", NULL, "Output Mixer"}, -}; - -static int jz4740_codec_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - uint32_t val; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec =rtd->codec; - - switch (params_rate(params)) { - case 8000: - val = 0; - break; - case 11025: - val = 1; - break; - case 12000: - val = 2; - break; - case 16000: - val = 3; - break; - case 22050: - val = 4; - break; - case 24000: - val = 5; - break; - case 32000: - val = 6; - break; - case 44100: - val = 7; - break; - case 48000: - val = 8; - break; - default: - return -EINVAL; - } - - val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET; - - snd_soc_update_bits(codec, JZ4740_REG_CODEC_2, - JZ4740_CODEC_2_SAMPLE_RATE_MASK, val); - - return 0; -} - -static const struct snd_soc_dai_ops jz4740_codec_dai_ops = { - .hw_params = jz4740_codec_hw_params, -}; - -static struct snd_soc_dai_driver jz4740_codec_dai = { - .name = "jz4740-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, - }, - .ops = &jz4740_codec_dai_ops, - .symmetric_rates = 1, -}; - -static void jz4740_codec_wakeup(struct snd_soc_codec *codec) -{ - int i; - uint32_t *cache = codec->reg_cache; - - snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET); - udelay(2); - - snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0); - - for (i = 0; i < ARRAY_SIZE(jz4740_codec_regs); ++i) - jz4740_codec_write(codec, i, cache[i]); -} - -static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - unsigned int mask; - unsigned int value; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - mask = JZ4740_CODEC_1_VREF_DISABLE | - JZ4740_CODEC_1_VREF_AMP_DISABLE | - JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; - value = 0; - - snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value); - break; - case SND_SOC_BIAS_STANDBY: - /* The only way to clear the suspend flag is to reset the codec */ - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - jz4740_codec_wakeup(codec); - - mask = JZ4740_CODEC_1_VREF_DISABLE | - JZ4740_CODEC_1_VREF_AMP_DISABLE | - JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; - value = JZ4740_CODEC_1_VREF_DISABLE | - JZ4740_CODEC_1_VREF_AMP_DISABLE | - JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; - - snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value); - break; - case SND_SOC_BIAS_OFF: - mask = JZ4740_CODEC_1_SUSPEND; - value = JZ4740_CODEC_1_SUSPEND; - - snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value); - break; - default: - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) -{ - snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, - JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); - - jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int jz4740_codec_dev_remove(struct snd_soc_codec *codec) -{ - jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP - -static int jz4740_codec_suspend(struct snd_soc_codec *codec) -{ - return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); -} - -static int jz4740_codec_resume(struct snd_soc_codec *codec) -{ - return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -} - -#else -#define jz4740_codec_suspend NULL -#define jz4740_codec_resume NULL -#endif - -static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { - .probe = jz4740_codec_dev_probe, - .remove = jz4740_codec_dev_remove, - .suspend = jz4740_codec_suspend, - .resume = jz4740_codec_resume, - .read = jz4740_codec_read, - .write = jz4740_codec_write, - .set_bias_level = jz4740_codec_set_bias_level, - .reg_cache_default = jz4740_codec_regs, - .reg_word_size = sizeof(u32), - .reg_cache_size = 2, - - .controls = jz4740_codec_controls, - .num_controls = ARRAY_SIZE(jz4740_codec_controls), - .dapm_widgets = jz4740_codec_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(jz4740_codec_dapm_widgets), - .dapm_routes = jz4740_codec_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes), -}; - -static int __devinit jz4740_codec_probe(struct platform_device *pdev) -{ - int ret; - struct jz4740_codec *jz4740_codec; - struct resource *mem; - - jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec), - GFP_KERNEL); - if (!jz4740_codec) - return -ENOMEM; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "Failed to get mmio memory resource\n"); - ret = -ENOENT; - goto err_out; - } - - mem = request_mem_region(mem->start, resource_size(mem), pdev->name); - if (!mem) { - dev_err(&pdev->dev, "Failed to request mmio memory region\n"); - ret = -EBUSY; - goto err_out; - } - - jz4740_codec->base = ioremap(mem->start, resource_size(mem)); - if (!jz4740_codec->base) { - dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); - ret = -EBUSY; - goto err_release_mem_region; - } - jz4740_codec->mem = mem; - - platform_set_drvdata(pdev, jz4740_codec); - - ret = snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1); - if (ret) { - dev_err(&pdev->dev, "Failed to register codec\n"); - goto err_iounmap; - } - - return 0; - -err_iounmap: - iounmap(jz4740_codec->base); -err_release_mem_region: - release_mem_region(mem->start, resource_size(mem)); -err_out: - return ret; -} - -static int __devexit jz4740_codec_remove(struct platform_device *pdev) -{ - struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); - struct resource *mem = jz4740_codec->mem; - - snd_soc_unregister_codec(&pdev->dev); - - iounmap(jz4740_codec->base); - release_mem_region(mem->start, resource_size(mem)); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver jz4740_codec_driver = { - .probe = jz4740_codec_probe, - .remove = __devexit_p(jz4740_codec_remove), - .driver = { - .name = "jz4740-codec", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(jz4740_codec_driver); - -MODULE_DESCRIPTION("JZ4740 SoC internal codec driver"); -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:jz4740-codec"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/l3.c b/ANDROID_3.4.5/sound/soc/codecs/l3.c deleted file mode 100644 index 5353af58..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/l3.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * L3 code - * - * Copyright (C) 2008, Christian Pellegrin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * - * based on: - * - * L3 bus algorithm module. - * - * Copyright (C) 2001 Russell King, All Rights Reserved. - * - * - */ - -#include -#include -#include - -#include - -/* - * Send one byte of data to the chip. Data is latched into the chip on - * the rising edge of the clock. - */ -static void sendbyte(struct l3_pins *adap, unsigned int byte) -{ - int i; - - for (i = 0; i < 8; i++) { - adap->setclk(0); - udelay(adap->data_hold); - adap->setdat(byte & 1); - udelay(adap->data_setup); - adap->setclk(1); - udelay(adap->clock_high); - byte >>= 1; - } -} - -/* - * Send a set of bytes to the chip. We need to pulse the MODE line - * between each byte, but never at the start nor at the end of the - * transfer. - */ -static void sendbytes(struct l3_pins *adap, const u8 *buf, - int len) -{ - int i; - - for (i = 0; i < len; i++) { - if (i) { - udelay(adap->mode_hold); - adap->setmode(0); - udelay(adap->mode); - } - adap->setmode(1); - udelay(adap->mode_setup); - sendbyte(adap, buf[i]); - } -} - -int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len) -{ - adap->setclk(1); - adap->setdat(1); - adap->setmode(1); - udelay(adap->mode); - - adap->setmode(0); - udelay(adap->mode_setup); - sendbyte(adap, addr); - udelay(adap->mode_hold); - - sendbytes(adap, data, len); - - adap->setclk(1); - adap->setdat(1); - adap->setmode(0); - - return len; -} -EXPORT_SYMBOL_GPL(l3_write); - -MODULE_DESCRIPTION("L3 bit-banging driver"); -MODULE_AUTHOR("Christian Pellegrin "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/lm4857.c b/ANDROID_3.4.5/sound/soc/codecs/lm4857.c deleted file mode 100644 index ba4fafb9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/lm4857.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * LM4857 AMP driver - * - * Copyright 2007 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * graeme.gregory@wolfsonmicro.com - * Copyright 2011 Lars-Peter Clausen - * - * 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. - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -struct lm4857 { - struct i2c_client *i2c; - uint8_t mode; -}; - -static const uint8_t lm4857_default_regs[] = { - 0x00, 0x00, 0x00, 0x00, -}; - -/* The register offsets in the cache array */ -#define LM4857_MVOL 0 -#define LM4857_LVOL 1 -#define LM4857_RVOL 2 -#define LM4857_CTRL 3 - -/* the shifts required to set these bits */ -#define LM4857_3D 5 -#define LM4857_WAKEUP 5 -#define LM4857_EPGAIN 4 - -static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - uint8_t data; - int ret; - - ret = snd_soc_cache_write(codec, reg, value); - if (ret < 0) - return ret; - - data = (reg << 6) | value; - ret = i2c_master_send(codec->control_data, &data, 1); - if (ret != 1) { - dev_err(codec->dev, "Failed to write register: %d\n", ret); - return ret; - } - - return 0; -} - -static unsigned int lm4857_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - unsigned int val; - int ret; - - ret = snd_soc_cache_read(codec, reg, &val); - if (ret) - return -1; - - return val; -} - -static int lm4857_get_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = lm4857->mode; - - return 0; -} - -static int lm4857_set_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); - uint8_t value = ucontrol->value.integer.value[0]; - - lm4857->mode = value; - - if (codec->dapm.bias_level == SND_SOC_BIAS_ON) - snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6); - - return 1; -} - -static int lm4857_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); - - switch (level) { - case SND_SOC_BIAS_ON: - snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6); - break; - case SND_SOC_BIAS_STANDBY: - snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0); - break; - default: - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static const char *lm4857_mode[] = { - "Earpiece", - "Loudspeaker", - "Loudspeaker + Headphone", - "Headphone", -}; - -static const struct soc_enum lm4857_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode); - -static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("IN"), - - SND_SOC_DAPM_OUTPUT("LS"), - SND_SOC_DAPM_OUTPUT("HP"), - SND_SOC_DAPM_OUTPUT("EP"), -}; - -static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0); -static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0); - -static const struct snd_kcontrol_new lm4857_controls[] = { - SOC_SINGLE_TLV("Left Playback Volume", LM4857_LVOL, 0, 31, 0, - stereo_tlv), - SOC_SINGLE_TLV("Right Playback Volume", LM4857_RVOL, 0, 31, 0, - stereo_tlv), - SOC_SINGLE_TLV("Mono Playback Volume", LM4857_MVOL, 0, 31, 0, - mono_tlv), - SOC_SINGLE("Spk 3D Playback Switch", LM4857_LVOL, LM4857_3D, 1, 0), - SOC_SINGLE("HP 3D Playback Switch", LM4857_RVOL, LM4857_3D, 1, 0), - SOC_SINGLE("Fast Wakeup Playback Switch", LM4857_CTRL, - LM4857_WAKEUP, 1, 0), - SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL, - LM4857_EPGAIN, 1, 0), - - SOC_ENUM_EXT("Mode", lm4857_mode_enum, - lm4857_get_mode, lm4857_set_mode), -}; - -/* There is a demux between the input signal and the output signals. - * Currently there is no easy way to model it in ASoC and since it does not make - * much of a difference in practice simply connect the input direclty to the - * outputs. */ -static const struct snd_soc_dapm_route lm4857_routes[] = { - {"LS", NULL, "IN"}, - {"HP", NULL, "IN"}, - {"EP", NULL, "IN"}, -}; - -static int lm4857_probe(struct snd_soc_codec *codec) -{ - struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - codec->control_data = lm4857->i2c; - - ret = snd_soc_add_codec_controls(codec, lm4857_controls, - ARRAY_SIZE(lm4857_controls)); - if (ret) - return ret; - - ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets, - ARRAY_SIZE(lm4857_dapm_widgets)); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(dapm, lm4857_routes, - ARRAY_SIZE(lm4857_routes)); - if (ret) - return ret; - - snd_soc_dapm_new_widgets(dapm); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { - .write = lm4857_write, - .read = lm4857_read, - .probe = lm4857_probe, - .reg_cache_size = ARRAY_SIZE(lm4857_default_regs), - .reg_word_size = sizeof(uint8_t), - .reg_cache_default = lm4857_default_regs, - .set_bias_level = lm4857_set_bias_level, -}; - -static int __devinit lm4857_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct lm4857 *lm4857; - int ret; - - lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL); - if (!lm4857) - return -ENOMEM; - - i2c_set_clientdata(i2c, lm4857); - - lm4857->i2c = i2c; - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); - - return ret; -} - -static int __devexit lm4857_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - return 0; -} - -static const struct i2c_device_id lm4857_i2c_id[] = { - { "lm4857", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id); - -static struct i2c_driver lm4857_i2c_driver = { - .driver = { - .name = "lm4857", - .owner = THIS_MODULE, - }, - .probe = lm4857_i2c_probe, - .remove = __devexit_p(lm4857_i2c_remove), - .id_table = lm4857_i2c_id, -}; - -static int __init lm4857_init(void) -{ - return i2c_add_driver(&lm4857_i2c_driver); -} -module_init(lm4857_init); - -static void __exit lm4857_exit(void) -{ - i2c_del_driver(&lm4857_i2c_driver); -} -module_exit(lm4857_exit); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("LM4857 amplifier driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/max9768.c b/ANDROID_3.4.5/sound/soc/codecs/max9768.c deleted file mode 100644 index 17b3ec2d..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max9768.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * MAX9768 AMP driver - * - * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K. - * - * 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; version 2 of the License. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* "Registers" */ -#define MAX9768_VOL 0 -#define MAX9768_CTRL 3 - -/* Commands */ -#define MAX9768_CTRL_PWM 0x15 -#define MAX9768_CTRL_FILTERLESS 0x16 - -struct max9768 { - struct regmap *regmap; - int mute_gpio; - int shdn_gpio; - u32 flags; -}; - -static struct reg_default max9768_default_regs[] = { - { 0, 0 }, - { 3, MAX9768_CTRL_FILTERLESS}, -}; - -static int max9768_get_gpio(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); - int val = gpio_get_value_cansleep(max9768->mute_gpio); - - ucontrol->value.integer.value[0] = !val; - - return 0; -} - -static int max9768_set_gpio(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); - - gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]); - - return 0; -} - -static const unsigned int volume_tlv[] = { - TLV_DB_RANGE_HEAD(43), - 0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0), - 3, 3, TLV_DB_SCALE_ITEM(-8680, 0, 0), - 4, 4, TLV_DB_SCALE_ITEM(-8430, 0, 0), - 5, 5, TLV_DB_SCALE_ITEM(-8080, 0, 0), - 6, 6, TLV_DB_SCALE_ITEM(-7830, 0, 0), - 7, 7, TLV_DB_SCALE_ITEM(-7470, 0, 0), - 8, 8, TLV_DB_SCALE_ITEM(-7220, 0, 0), - 9, 9, TLV_DB_SCALE_ITEM(-6870, 0, 0), - 10, 10, TLV_DB_SCALE_ITEM(-6620, 0, 0), - 11, 11, TLV_DB_SCALE_ITEM(-6270, 0, 0), - 12, 12, TLV_DB_SCALE_ITEM(-6020, 0, 0), - 13, 13, TLV_DB_SCALE_ITEM(-5670, 0, 0), - 14, 14, TLV_DB_SCALE_ITEM(-5420, 0, 0), - 15, 17, TLV_DB_SCALE_ITEM(-5060, 250, 0), - 18, 18, TLV_DB_SCALE_ITEM(-4370, 0, 0), - 19, 19, TLV_DB_SCALE_ITEM(-4210, 0, 0), - 20, 20, TLV_DB_SCALE_ITEM(-3960, 0, 0), - 21, 21, TLV_DB_SCALE_ITEM(-3760, 0, 0), - 22, 22, TLV_DB_SCALE_ITEM(-3600, 0, 0), - 23, 23, TLV_DB_SCALE_ITEM(-3340, 0, 0), - 24, 24, TLV_DB_SCALE_ITEM(-3150, 0, 0), - 25, 25, TLV_DB_SCALE_ITEM(-2980, 0, 0), - 26, 26, TLV_DB_SCALE_ITEM(-2720, 0, 0), - 27, 27, TLV_DB_SCALE_ITEM(-2520, 0, 0), - 28, 30, TLV_DB_SCALE_ITEM(-2350, 190, 0), - 31, 31, TLV_DB_SCALE_ITEM(-1750, 0, 0), - 32, 34, TLV_DB_SCALE_ITEM(-1640, 100, 0), - 35, 37, TLV_DB_SCALE_ITEM(-1310, 110, 0), - 38, 39, TLV_DB_SCALE_ITEM(-990, 100, 0), - 40, 40, TLV_DB_SCALE_ITEM(-710, 0, 0), - 41, 41, TLV_DB_SCALE_ITEM(-600, 0, 0), - 42, 42, TLV_DB_SCALE_ITEM(-500, 0, 0), - 43, 43, TLV_DB_SCALE_ITEM(-340, 0, 0), - 44, 44, TLV_DB_SCALE_ITEM(-190, 0, 0), - 45, 45, TLV_DB_SCALE_ITEM(-50, 0, 0), - 46, 46, TLV_DB_SCALE_ITEM(50, 0, 0), - 47, 50, TLV_DB_SCALE_ITEM(120, 40, 0), - 51, 57, TLV_DB_SCALE_ITEM(290, 50, 0), - 58, 58, TLV_DB_SCALE_ITEM(650, 0, 0), - 59, 62, TLV_DB_SCALE_ITEM(700, 60, 0), - 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0), -}; - -static const struct snd_kcontrol_new max9768_volume[] = { - SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv), -}; - -static const struct snd_kcontrol_new max9768_mute[] = { - SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio), -}; - -static int max9768_probe(struct snd_soc_codec *codec) -{ - struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = max9768->regmap; - ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP); - if (ret) - return ret; - - if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { - ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM); - if (ret) - return ret; - } - - if (gpio_is_valid(max9768->mute_gpio)) { - ret = snd_soc_add_codec_controls(codec, max9768_mute, - ARRAY_SIZE(max9768_mute)); - if (ret) - return ret; - } - - return 0; -} - -static struct snd_soc_codec_driver max9768_codec_driver = { - .probe = max9768_probe, - .controls = max9768_volume, - .num_controls = ARRAY_SIZE(max9768_volume), -}; - -static const struct regmap_config max9768_i2c_regmap_config = { - .reg_bits = 2, - .val_bits = 6, - .max_register = 3, - .reg_defaults = max9768_default_regs, - .num_reg_defaults = ARRAY_SIZE(max9768_default_regs), - .cache_type = REGCACHE_RBTREE, -}; - -static int __devinit max9768_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max9768 *max9768; - struct max9768_pdata *pdata = client->dev.platform_data; - int err; - - max9768 = devm_kzalloc(&client->dev, sizeof(*max9768), GFP_KERNEL); - if (!max9768) - return -ENOMEM; - - if (pdata) { - /* Mute on powerup to avoid clicks */ - err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute"); - max9768->mute_gpio = err ?: pdata->mute_gpio; - - /* Activate chip by releasing shutdown, enables I2C */ - err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown"); - max9768->shdn_gpio = err ?: pdata->shdn_gpio; - - max9768->flags = pdata->flags; - } else { - max9768->shdn_gpio = -EINVAL; - max9768->mute_gpio = -EINVAL; - } - - i2c_set_clientdata(client, max9768); - - max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config); - if (IS_ERR(max9768->regmap)) { - err = PTR_ERR(max9768->regmap); - goto err_gpio_free; - } - - err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0); - if (err) - goto err_regmap_free; - - return 0; - - err_regmap_free: - regmap_exit(max9768->regmap); - err_gpio_free: - if (gpio_is_valid(max9768->shdn_gpio)) - gpio_free(max9768->shdn_gpio); - if (gpio_is_valid(max9768->mute_gpio)) - gpio_free(max9768->mute_gpio); - - return err; -} - -static int __devexit max9768_i2c_remove(struct i2c_client *client) -{ - struct max9768 *max9768 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(max9768->regmap); - - if (gpio_is_valid(max9768->shdn_gpio)) - gpio_free(max9768->shdn_gpio); - if (gpio_is_valid(max9768->mute_gpio)) - gpio_free(max9768->mute_gpio); - - return 0; -} - -static const struct i2c_device_id max9768_i2c_id[] = { - { "max9768", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max9768_i2c_id); - -static struct i2c_driver max9768_i2c_driver = { - .driver = { - .name = "max9768", - .owner = THIS_MODULE, - }, - .probe = max9768_i2c_probe, - .remove = __devexit_p(max9768_i2c_remove), - .id_table = max9768_i2c_id, -}; -module_i2c_driver(max9768_i2c_driver); - -MODULE_AUTHOR("Wolfram Sang "); -MODULE_DESCRIPTION("ASoC MAX9768 amplifier driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/max98088.c b/ANDROID_3.4.5/sound/soc/codecs/max98088.c deleted file mode 100644 index af7324b7..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max98088.c +++ /dev/null @@ -1,2130 +0,0 @@ -/* - * max98088.c -- MAX98088 ALSA SoC Audio driver - * - * Copyright 2010 Maxim Integrated Products - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "max98088.h" - -enum max98088_type { - MAX98088, - MAX98089, -}; - -struct max98088_cdata { - unsigned int rate; - unsigned int fmt; - int eq_sel; -}; - -struct max98088_priv { - enum max98088_type devtype; - struct max98088_pdata *pdata; - unsigned int sysclk; - struct max98088_cdata dai[2]; - int eq_textcnt; - const char **eq_texts; - struct soc_enum eq_enum; - u8 ina_state; - u8 inb_state; - unsigned int ex_mode; - unsigned int digmic; - unsigned int mic1pre; - unsigned int mic2pre; - unsigned int extmic_mode; -}; - -static const u8 max98088_reg[M98088_REG_CNT] = { - 0x00, /* 00 IRQ status */ - 0x00, /* 01 MIC status */ - 0x00, /* 02 jack status */ - 0x00, /* 03 battery voltage */ - 0x00, /* 04 */ - 0x00, /* 05 */ - 0x00, /* 06 */ - 0x00, /* 07 */ - 0x00, /* 08 */ - 0x00, /* 09 */ - 0x00, /* 0A */ - 0x00, /* 0B */ - 0x00, /* 0C */ - 0x00, /* 0D */ - 0x00, /* 0E */ - 0x00, /* 0F interrupt enable */ - - 0x00, /* 10 master clock */ - 0x00, /* 11 DAI1 clock mode */ - 0x00, /* 12 DAI1 clock control */ - 0x00, /* 13 DAI1 clock control */ - 0x00, /* 14 DAI1 format */ - 0x00, /* 15 DAI1 clock */ - 0x00, /* 16 DAI1 config */ - 0x00, /* 17 DAI1 TDM */ - 0x00, /* 18 DAI1 filters */ - 0x00, /* 19 DAI2 clock mode */ - 0x00, /* 1A DAI2 clock control */ - 0x00, /* 1B DAI2 clock control */ - 0x00, /* 1C DAI2 format */ - 0x00, /* 1D DAI2 clock */ - 0x00, /* 1E DAI2 config */ - 0x00, /* 1F DAI2 TDM */ - - 0x00, /* 20 DAI2 filters */ - 0x00, /* 21 data config */ - 0x00, /* 22 DAC mixer */ - 0x00, /* 23 left ADC mixer */ - 0x00, /* 24 right ADC mixer */ - 0x00, /* 25 left HP mixer */ - 0x00, /* 26 right HP mixer */ - 0x00, /* 27 HP control */ - 0x00, /* 28 left REC mixer */ - 0x00, /* 29 right REC mixer */ - 0x00, /* 2A REC control */ - 0x00, /* 2B left SPK mixer */ - 0x00, /* 2C right SPK mixer */ - 0x00, /* 2D SPK control */ - 0x00, /* 2E sidetone */ - 0x00, /* 2F DAI1 playback level */ - - 0x00, /* 30 DAI1 playback level */ - 0x00, /* 31 DAI2 playback level */ - 0x00, /* 32 DAI2 playbakc level */ - 0x00, /* 33 left ADC level */ - 0x00, /* 34 right ADC level */ - 0x00, /* 35 MIC1 level */ - 0x00, /* 36 MIC2 level */ - 0x00, /* 37 INA level */ - 0x00, /* 38 INB level */ - 0x00, /* 39 left HP volume */ - 0x00, /* 3A right HP volume */ - 0x00, /* 3B left REC volume */ - 0x00, /* 3C right REC volume */ - 0x00, /* 3D left SPK volume */ - 0x00, /* 3E right SPK volume */ - 0x00, /* 3F MIC config */ - - 0x00, /* 40 MIC threshold */ - 0x00, /* 41 excursion limiter filter */ - 0x00, /* 42 excursion limiter threshold */ - 0x00, /* 43 ALC */ - 0x00, /* 44 power limiter threshold */ - 0x00, /* 45 power limiter config */ - 0x00, /* 46 distortion limiter config */ - 0x00, /* 47 audio input */ - 0x00, /* 48 microphone */ - 0x00, /* 49 level control */ - 0x00, /* 4A bypass switches */ - 0x00, /* 4B jack detect */ - 0x00, /* 4C input enable */ - 0x00, /* 4D output enable */ - 0xF0, /* 4E bias control */ - 0x00, /* 4F DAC power */ - - 0x0F, /* 50 DAC power */ - 0x00, /* 51 system */ - 0x00, /* 52 DAI1 EQ1 */ - 0x00, /* 53 DAI1 EQ1 */ - 0x00, /* 54 DAI1 EQ1 */ - 0x00, /* 55 DAI1 EQ1 */ - 0x00, /* 56 DAI1 EQ1 */ - 0x00, /* 57 DAI1 EQ1 */ - 0x00, /* 58 DAI1 EQ1 */ - 0x00, /* 59 DAI1 EQ1 */ - 0x00, /* 5A DAI1 EQ1 */ - 0x00, /* 5B DAI1 EQ1 */ - 0x00, /* 5C DAI1 EQ2 */ - 0x00, /* 5D DAI1 EQ2 */ - 0x00, /* 5E DAI1 EQ2 */ - 0x00, /* 5F DAI1 EQ2 */ - - 0x00, /* 60 DAI1 EQ2 */ - 0x00, /* 61 DAI1 EQ2 */ - 0x00, /* 62 DAI1 EQ2 */ - 0x00, /* 63 DAI1 EQ2 */ - 0x00, /* 64 DAI1 EQ2 */ - 0x00, /* 65 DAI1 EQ2 */ - 0x00, /* 66 DAI1 EQ3 */ - 0x00, /* 67 DAI1 EQ3 */ - 0x00, /* 68 DAI1 EQ3 */ - 0x00, /* 69 DAI1 EQ3 */ - 0x00, /* 6A DAI1 EQ3 */ - 0x00, /* 6B DAI1 EQ3 */ - 0x00, /* 6C DAI1 EQ3 */ - 0x00, /* 6D DAI1 EQ3 */ - 0x00, /* 6E DAI1 EQ3 */ - 0x00, /* 6F DAI1 EQ3 */ - - 0x00, /* 70 DAI1 EQ4 */ - 0x00, /* 71 DAI1 EQ4 */ - 0x00, /* 72 DAI1 EQ4 */ - 0x00, /* 73 DAI1 EQ4 */ - 0x00, /* 74 DAI1 EQ4 */ - 0x00, /* 75 DAI1 EQ4 */ - 0x00, /* 76 DAI1 EQ4 */ - 0x00, /* 77 DAI1 EQ4 */ - 0x00, /* 78 DAI1 EQ4 */ - 0x00, /* 79 DAI1 EQ4 */ - 0x00, /* 7A DAI1 EQ5 */ - 0x00, /* 7B DAI1 EQ5 */ - 0x00, /* 7C DAI1 EQ5 */ - 0x00, /* 7D DAI1 EQ5 */ - 0x00, /* 7E DAI1 EQ5 */ - 0x00, /* 7F DAI1 EQ5 */ - - 0x00, /* 80 DAI1 EQ5 */ - 0x00, /* 81 DAI1 EQ5 */ - 0x00, /* 82 DAI1 EQ5 */ - 0x00, /* 83 DAI1 EQ5 */ - 0x00, /* 84 DAI2 EQ1 */ - 0x00, /* 85 DAI2 EQ1 */ - 0x00, /* 86 DAI2 EQ1 */ - 0x00, /* 87 DAI2 EQ1 */ - 0x00, /* 88 DAI2 EQ1 */ - 0x00, /* 89 DAI2 EQ1 */ - 0x00, /* 8A DAI2 EQ1 */ - 0x00, /* 8B DAI2 EQ1 */ - 0x00, /* 8C DAI2 EQ1 */ - 0x00, /* 8D DAI2 EQ1 */ - 0x00, /* 8E DAI2 EQ2 */ - 0x00, /* 8F DAI2 EQ2 */ - - 0x00, /* 90 DAI2 EQ2 */ - 0x00, /* 91 DAI2 EQ2 */ - 0x00, /* 92 DAI2 EQ2 */ - 0x00, /* 93 DAI2 EQ2 */ - 0x00, /* 94 DAI2 EQ2 */ - 0x00, /* 95 DAI2 EQ2 */ - 0x00, /* 96 DAI2 EQ2 */ - 0x00, /* 97 DAI2 EQ2 */ - 0x00, /* 98 DAI2 EQ3 */ - 0x00, /* 99 DAI2 EQ3 */ - 0x00, /* 9A DAI2 EQ3 */ - 0x00, /* 9B DAI2 EQ3 */ - 0x00, /* 9C DAI2 EQ3 */ - 0x00, /* 9D DAI2 EQ3 */ - 0x00, /* 9E DAI2 EQ3 */ - 0x00, /* 9F DAI2 EQ3 */ - - 0x00, /* A0 DAI2 EQ3 */ - 0x00, /* A1 DAI2 EQ3 */ - 0x00, /* A2 DAI2 EQ4 */ - 0x00, /* A3 DAI2 EQ4 */ - 0x00, /* A4 DAI2 EQ4 */ - 0x00, /* A5 DAI2 EQ4 */ - 0x00, /* A6 DAI2 EQ4 */ - 0x00, /* A7 DAI2 EQ4 */ - 0x00, /* A8 DAI2 EQ4 */ - 0x00, /* A9 DAI2 EQ4 */ - 0x00, /* AA DAI2 EQ4 */ - 0x00, /* AB DAI2 EQ4 */ - 0x00, /* AC DAI2 EQ5 */ - 0x00, /* AD DAI2 EQ5 */ - 0x00, /* AE DAI2 EQ5 */ - 0x00, /* AF DAI2 EQ5 */ - - 0x00, /* B0 DAI2 EQ5 */ - 0x00, /* B1 DAI2 EQ5 */ - 0x00, /* B2 DAI2 EQ5 */ - 0x00, /* B3 DAI2 EQ5 */ - 0x00, /* B4 DAI2 EQ5 */ - 0x00, /* B5 DAI2 EQ5 */ - 0x00, /* B6 DAI1 biquad */ - 0x00, /* B7 DAI1 biquad */ - 0x00, /* B8 DAI1 biquad */ - 0x00, /* B9 DAI1 biquad */ - 0x00, /* BA DAI1 biquad */ - 0x00, /* BB DAI1 biquad */ - 0x00, /* BC DAI1 biquad */ - 0x00, /* BD DAI1 biquad */ - 0x00, /* BE DAI1 biquad */ - 0x00, /* BF DAI1 biquad */ - - 0x00, /* C0 DAI2 biquad */ - 0x00, /* C1 DAI2 biquad */ - 0x00, /* C2 DAI2 biquad */ - 0x00, /* C3 DAI2 biquad */ - 0x00, /* C4 DAI2 biquad */ - 0x00, /* C5 DAI2 biquad */ - 0x00, /* C6 DAI2 biquad */ - 0x00, /* C7 DAI2 biquad */ - 0x00, /* C8 DAI2 biquad */ - 0x00, /* C9 DAI2 biquad */ - 0x00, /* CA */ - 0x00, /* CB */ - 0x00, /* CC */ - 0x00, /* CD */ - 0x00, /* CE */ - 0x00, /* CF */ - - 0x00, /* D0 */ - 0x00, /* D1 */ - 0x00, /* D2 */ - 0x00, /* D3 */ - 0x00, /* D4 */ - 0x00, /* D5 */ - 0x00, /* D6 */ - 0x00, /* D7 */ - 0x00, /* D8 */ - 0x00, /* D9 */ - 0x00, /* DA */ - 0x70, /* DB */ - 0x00, /* DC */ - 0x00, /* DD */ - 0x00, /* DE */ - 0x00, /* DF */ - - 0x00, /* E0 */ - 0x00, /* E1 */ - 0x00, /* E2 */ - 0x00, /* E3 */ - 0x00, /* E4 */ - 0x00, /* E5 */ - 0x00, /* E6 */ - 0x00, /* E7 */ - 0x00, /* E8 */ - 0x00, /* E9 */ - 0x00, /* EA */ - 0x00, /* EB */ - 0x00, /* EC */ - 0x00, /* ED */ - 0x00, /* EE */ - 0x00, /* EF */ - - 0x00, /* F0 */ - 0x00, /* F1 */ - 0x00, /* F2 */ - 0x00, /* F3 */ - 0x00, /* F4 */ - 0x00, /* F5 */ - 0x00, /* F6 */ - 0x00, /* F7 */ - 0x00, /* F8 */ - 0x00, /* F9 */ - 0x00, /* FA */ - 0x00, /* FB */ - 0x00, /* FC */ - 0x00, /* FD */ - 0x00, /* FE */ - 0x00, /* FF */ -}; - -static struct { - int readable; - int writable; - int vol; -} max98088_access[M98088_REG_CNT] = { - { 0xFF, 0xFF, 1 }, /* 00 IRQ status */ - { 0xFF, 0x00, 1 }, /* 01 MIC status */ - { 0xFF, 0x00, 1 }, /* 02 jack status */ - { 0x1F, 0x1F, 1 }, /* 03 battery voltage */ - { 0xFF, 0xFF, 0 }, /* 04 */ - { 0xFF, 0xFF, 0 }, /* 05 */ - { 0xFF, 0xFF, 0 }, /* 06 */ - { 0xFF, 0xFF, 0 }, /* 07 */ - { 0xFF, 0xFF, 0 }, /* 08 */ - { 0xFF, 0xFF, 0 }, /* 09 */ - { 0xFF, 0xFF, 0 }, /* 0A */ - { 0xFF, 0xFF, 0 }, /* 0B */ - { 0xFF, 0xFF, 0 }, /* 0C */ - { 0xFF, 0xFF, 0 }, /* 0D */ - { 0xFF, 0xFF, 0 }, /* 0E */ - { 0xFF, 0xFF, 0 }, /* 0F interrupt enable */ - - { 0xFF, 0xFF, 0 }, /* 10 master clock */ - { 0xFF, 0xFF, 0 }, /* 11 DAI1 clock mode */ - { 0xFF, 0xFF, 0 }, /* 12 DAI1 clock control */ - { 0xFF, 0xFF, 0 }, /* 13 DAI1 clock control */ - { 0xFF, 0xFF, 0 }, /* 14 DAI1 format */ - { 0xFF, 0xFF, 0 }, /* 15 DAI1 clock */ - { 0xFF, 0xFF, 0 }, /* 16 DAI1 config */ - { 0xFF, 0xFF, 0 }, /* 17 DAI1 TDM */ - { 0xFF, 0xFF, 0 }, /* 18 DAI1 filters */ - { 0xFF, 0xFF, 0 }, /* 19 DAI2 clock mode */ - { 0xFF, 0xFF, 0 }, /* 1A DAI2 clock control */ - { 0xFF, 0xFF, 0 }, /* 1B DAI2 clock control */ - { 0xFF, 0xFF, 0 }, /* 1C DAI2 format */ - { 0xFF, 0xFF, 0 }, /* 1D DAI2 clock */ - { 0xFF, 0xFF, 0 }, /* 1E DAI2 config */ - { 0xFF, 0xFF, 0 }, /* 1F DAI2 TDM */ - - { 0xFF, 0xFF, 0 }, /* 20 DAI2 filters */ - { 0xFF, 0xFF, 0 }, /* 21 data config */ - { 0xFF, 0xFF, 0 }, /* 22 DAC mixer */ - { 0xFF, 0xFF, 0 }, /* 23 left ADC mixer */ - { 0xFF, 0xFF, 0 }, /* 24 right ADC mixer */ - { 0xFF, 0xFF, 0 }, /* 25 left HP mixer */ - { 0xFF, 0xFF, 0 }, /* 26 right HP mixer */ - { 0xFF, 0xFF, 0 }, /* 27 HP control */ - { 0xFF, 0xFF, 0 }, /* 28 left REC mixer */ - { 0xFF, 0xFF, 0 }, /* 29 right REC mixer */ - { 0xFF, 0xFF, 0 }, /* 2A REC control */ - { 0xFF, 0xFF, 0 }, /* 2B left SPK mixer */ - { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */ - { 0xFF, 0xFF, 0 }, /* 2D SPK control */ - { 0xFF, 0xFF, 0 }, /* 2E sidetone */ - { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */ - - { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */ - { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */ - { 0xFF, 0xFF, 0 }, /* 32 DAI2 playbakc level */ - { 0xFF, 0xFF, 0 }, /* 33 left ADC level */ - { 0xFF, 0xFF, 0 }, /* 34 right ADC level */ - { 0xFF, 0xFF, 0 }, /* 35 MIC1 level */ - { 0xFF, 0xFF, 0 }, /* 36 MIC2 level */ - { 0xFF, 0xFF, 0 }, /* 37 INA level */ - { 0xFF, 0xFF, 0 }, /* 38 INB level */ - { 0xFF, 0xFF, 0 }, /* 39 left HP volume */ - { 0xFF, 0xFF, 0 }, /* 3A right HP volume */ - { 0xFF, 0xFF, 0 }, /* 3B left REC volume */ - { 0xFF, 0xFF, 0 }, /* 3C right REC volume */ - { 0xFF, 0xFF, 0 }, /* 3D left SPK volume */ - { 0xFF, 0xFF, 0 }, /* 3E right SPK volume */ - { 0xFF, 0xFF, 0 }, /* 3F MIC config */ - - { 0xFF, 0xFF, 0 }, /* 40 MIC threshold */ - { 0xFF, 0xFF, 0 }, /* 41 excursion limiter filter */ - { 0xFF, 0xFF, 0 }, /* 42 excursion limiter threshold */ - { 0xFF, 0xFF, 0 }, /* 43 ALC */ - { 0xFF, 0xFF, 0 }, /* 44 power limiter threshold */ - { 0xFF, 0xFF, 0 }, /* 45 power limiter config */ - { 0xFF, 0xFF, 0 }, /* 46 distortion limiter config */ - { 0xFF, 0xFF, 0 }, /* 47 audio input */ - { 0xFF, 0xFF, 0 }, /* 48 microphone */ - { 0xFF, 0xFF, 0 }, /* 49 level control */ - { 0xFF, 0xFF, 0 }, /* 4A bypass switches */ - { 0xFF, 0xFF, 0 }, /* 4B jack detect */ - { 0xFF, 0xFF, 0 }, /* 4C input enable */ - { 0xFF, 0xFF, 0 }, /* 4D output enable */ - { 0xFF, 0xFF, 0 }, /* 4E bias control */ - { 0xFF, 0xFF, 0 }, /* 4F DAC power */ - - { 0xFF, 0xFF, 0 }, /* 50 DAC power */ - { 0xFF, 0xFF, 0 }, /* 51 system */ - { 0xFF, 0xFF, 0 }, /* 52 DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 53 DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 54 DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 55 DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 56 DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 57 DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 58 DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 59 DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 5A DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 5B DAI1 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 5C DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 5D DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 5E DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 5F DAI1 EQ2 */ - - { 0xFF, 0xFF, 0 }, /* 60 DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 61 DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 62 DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 63 DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 64 DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 65 DAI1 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 66 DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 67 DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 68 DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 69 DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 6A DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 6B DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 6C DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 6D DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 6E DAI1 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 6F DAI1 EQ3 */ - - { 0xFF, 0xFF, 0 }, /* 70 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 71 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 72 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 73 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 74 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 75 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 76 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 77 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 78 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 79 DAI1 EQ4 */ - { 0xFF, 0xFF, 0 }, /* 7A DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 7B DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 7C DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 7D DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 7E DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 7F DAI1 EQ5 */ - - { 0xFF, 0xFF, 0 }, /* 80 DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 81 DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 82 DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 83 DAI1 EQ5 */ - { 0xFF, 0xFF, 0 }, /* 84 DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 85 DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 86 DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 87 DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 88 DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 89 DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 8A DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 8B DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 8C DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 8D DAI2 EQ1 */ - { 0xFF, 0xFF, 0 }, /* 8E DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 8F DAI2 EQ2 */ - - { 0xFF, 0xFF, 0 }, /* 90 DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 91 DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 92 DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 93 DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 94 DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 95 DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 96 DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 97 DAI2 EQ2 */ - { 0xFF, 0xFF, 0 }, /* 98 DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 99 DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 9A DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 9B DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 9C DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 9D DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 9E DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* 9F DAI2 EQ3 */ - - { 0xFF, 0xFF, 0 }, /* A0 DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* A1 DAI2 EQ3 */ - { 0xFF, 0xFF, 0 }, /* A2 DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* A3 DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* A4 DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* A5 DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* A6 DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* A7 DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* A8 DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* A9 DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* AA DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* AB DAI2 EQ4 */ - { 0xFF, 0xFF, 0 }, /* AC DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* AD DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* AE DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* AF DAI2 EQ5 */ - - { 0xFF, 0xFF, 0 }, /* B0 DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* B1 DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* B2 DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* B3 DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* B4 DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* B5 DAI2 EQ5 */ - { 0xFF, 0xFF, 0 }, /* B6 DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* B7 DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* B8 DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* B9 DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* BA DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* BB DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* BC DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* BD DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* BE DAI1 biquad */ - { 0xFF, 0xFF, 0 }, /* BF DAI1 biquad */ - - { 0xFF, 0xFF, 0 }, /* C0 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C1 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C2 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C3 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C4 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C5 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C6 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C7 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C8 DAI2 biquad */ - { 0xFF, 0xFF, 0 }, /* C9 DAI2 biquad */ - { 0x00, 0x00, 0 }, /* CA */ - { 0x00, 0x00, 0 }, /* CB */ - { 0x00, 0x00, 0 }, /* CC */ - { 0x00, 0x00, 0 }, /* CD */ - { 0x00, 0x00, 0 }, /* CE */ - { 0x00, 0x00, 0 }, /* CF */ - - { 0x00, 0x00, 0 }, /* D0 */ - { 0x00, 0x00, 0 }, /* D1 */ - { 0x00, 0x00, 0 }, /* D2 */ - { 0x00, 0x00, 0 }, /* D3 */ - { 0x00, 0x00, 0 }, /* D4 */ - { 0x00, 0x00, 0 }, /* D5 */ - { 0x00, 0x00, 0 }, /* D6 */ - { 0x00, 0x00, 0 }, /* D7 */ - { 0x00, 0x00, 0 }, /* D8 */ - { 0x00, 0x00, 0 }, /* D9 */ - { 0x00, 0x00, 0 }, /* DA */ - { 0x00, 0x00, 0 }, /* DB */ - { 0x00, 0x00, 0 }, /* DC */ - { 0x00, 0x00, 0 }, /* DD */ - { 0x00, 0x00, 0 }, /* DE */ - { 0x00, 0x00, 0 }, /* DF */ - - { 0x00, 0x00, 0 }, /* E0 */ - { 0x00, 0x00, 0 }, /* E1 */ - { 0x00, 0x00, 0 }, /* E2 */ - { 0x00, 0x00, 0 }, /* E3 */ - { 0x00, 0x00, 0 }, /* E4 */ - { 0x00, 0x00, 0 }, /* E5 */ - { 0x00, 0x00, 0 }, /* E6 */ - { 0x00, 0x00, 0 }, /* E7 */ - { 0x00, 0x00, 0 }, /* E8 */ - { 0x00, 0x00, 0 }, /* E9 */ - { 0x00, 0x00, 0 }, /* EA */ - { 0x00, 0x00, 0 }, /* EB */ - { 0x00, 0x00, 0 }, /* EC */ - { 0x00, 0x00, 0 }, /* ED */ - { 0x00, 0x00, 0 }, /* EE */ - { 0x00, 0x00, 0 }, /* EF */ - - { 0x00, 0x00, 0 }, /* F0 */ - { 0x00, 0x00, 0 }, /* F1 */ - { 0x00, 0x00, 0 }, /* F2 */ - { 0x00, 0x00, 0 }, /* F3 */ - { 0x00, 0x00, 0 }, /* F4 */ - { 0x00, 0x00, 0 }, /* F5 */ - { 0x00, 0x00, 0 }, /* F6 */ - { 0x00, 0x00, 0 }, /* F7 */ - { 0x00, 0x00, 0 }, /* F8 */ - { 0x00, 0x00, 0 }, /* F9 */ - { 0x00, 0x00, 0 }, /* FA */ - { 0x00, 0x00, 0 }, /* FB */ - { 0x00, 0x00, 0 }, /* FC */ - { 0x00, 0x00, 0 }, /* FD */ - { 0x00, 0x00, 0 }, /* FE */ - { 0xFF, 0x00, 1 }, /* FF */ -}; - -static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg) -{ - return max98088_access[reg].vol; -} - - -/* - * Load equalizer DSP coefficient configurations registers - */ -static void m98088_eq_band(struct snd_soc_codec *codec, unsigned int dai, - unsigned int band, u16 *coefs) -{ - unsigned int eq_reg; - unsigned int i; - - BUG_ON(band > 4); - BUG_ON(dai > 1); - - /* Load the base register address */ - eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE; - - /* Add the band address offset, note adjustment for word address */ - eq_reg += band * (M98088_COEFS_PER_BAND << 1); - - /* Step through the registers and coefs */ - for (i = 0; i < M98088_COEFS_PER_BAND; i++) { - snd_soc_write(codec, eq_reg++, M98088_BYTE1(coefs[i])); - snd_soc_write(codec, eq_reg++, M98088_BYTE0(coefs[i])); - } -} - -/* - * Excursion limiter modes - */ -static const char *max98088_exmode_texts[] = { - "Off", "100Hz", "400Hz", "600Hz", "800Hz", "1000Hz", "200-400Hz", - "400-600Hz", "400-800Hz", -}; - -static const unsigned int max98088_exmode_values[] = { - 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 -}; - -static const struct soc_enum max98088_exmode_enum = - SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127, - ARRAY_SIZE(max98088_exmode_texts), - max98088_exmode_texts, - max98088_exmode_values); - -static const char *max98088_ex_thresh[] = { /* volts PP */ - "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; -static const struct soc_enum max98088_ex_thresh_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8, - max98088_ex_thresh), -}; - -static const char *max98088_fltr_mode[] = {"Voice", "Music" }; -static const struct soc_enum max98088_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode), -}; - -static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; - -static const struct soc_enum max98088_extmic_enum = - SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text); - -static const struct snd_kcontrol_new max98088_extmic_mux = - SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); - -static const char *max98088_dai1_fltr[] = { - "Off", "fc=258/fs=16k", "fc=500/fs=16k", - "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; -static const struct soc_enum max98088_dai1_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr), -}; -static const struct soc_enum max98088_dai1_adc_filter_enum[] = { - SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr), -}; - -static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - unsigned int sel = ucontrol->value.integer.value[0]; - - max98088->mic1pre = sel; - snd_soc_update_bits(codec, M98088_REG_35_LVL_MIC1, M98088_MICPRE_MASK, - (1+sel)<value.integer.value[0] = max98088->mic1pre; - return 0; -} - -static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - unsigned int sel = ucontrol->value.integer.value[0]; - - max98088->mic2pre = sel; - snd_soc_update_bits(codec, M98088_REG_36_LVL_MIC2, M98088_MICPRE_MASK, - (1+sel)<value.integer.value[0] = max98088->mic2pre; - return 0; -} - -static const unsigned int max98088_micboost_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), - 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), -}; - -static const struct snd_kcontrol_new max98088_snd_controls[] = { - - SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L, - M98088_REG_3A_LVL_HP_R, 0, 31, 0), - SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L, - M98088_REG_3E_LVL_SPK_R, 0, 31, 0), - SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L, - M98088_REG_3C_LVL_REC_R, 0, 31, 0), - - SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L, - M98088_REG_3A_LVL_HP_R, 7, 1, 1), - SOC_DOUBLE_R("Speaker Switch", M98088_REG_3D_LVL_SPK_L, - M98088_REG_3E_LVL_SPK_R, 7, 1, 1), - SOC_DOUBLE_R("Receiver Switch", M98088_REG_3B_LVL_REC_L, - M98088_REG_3C_LVL_REC_R, 7, 1, 1), - - SOC_SINGLE("MIC1 Volume", M98088_REG_35_LVL_MIC1, 0, 31, 1), - SOC_SINGLE("MIC2 Volume", M98088_REG_36_LVL_MIC2, 0, 31, 1), - - SOC_SINGLE_EXT_TLV("MIC1 Boost Volume", - M98088_REG_35_LVL_MIC1, 5, 2, 0, - max98088_mic1pre_get, max98088_mic1pre_set, - max98088_micboost_tlv), - SOC_SINGLE_EXT_TLV("MIC2 Boost Volume", - M98088_REG_36_LVL_MIC2, 5, 2, 0, - max98088_mic2pre_get, max98088_mic2pre_set, - max98088_micboost_tlv), - - SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1), - SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1), - - SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0), - SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0), - - SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0), - SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0), - - SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0), - SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0), - - SOC_ENUM("EX Limiter Mode", max98088_exmode_enum), - SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum), - - SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum), - SOC_ENUM("DAI1 DAC Filter", max98088_dai1_dac_filter_enum), - SOC_ENUM("DAI1 ADC Filter", max98088_dai1_adc_filter_enum), - SOC_SINGLE("DAI2 DC Block Switch", M98088_REG_20_DAI2_FILTERS, - 0, 1, 0), - - SOC_SINGLE("ALC Switch", M98088_REG_43_SPKALC_COMP, 7, 1, 0), - SOC_SINGLE("ALC Threshold", M98088_REG_43_SPKALC_COMP, 0, 7, 0), - SOC_SINGLE("ALC Multiband", M98088_REG_43_SPKALC_COMP, 3, 1, 0), - SOC_SINGLE("ALC Release Time", M98088_REG_43_SPKALC_COMP, 4, 7, 0), - - SOC_SINGLE("PWR Limiter Threshold", M98088_REG_44_PWRLMT_CFG, - 4, 15, 0), - SOC_SINGLE("PWR Limiter Weight", M98088_REG_44_PWRLMT_CFG, 0, 7, 0), - SOC_SINGLE("PWR Limiter Time1", M98088_REG_45_PWRLMT_TIME, 0, 15, 0), - SOC_SINGLE("PWR Limiter Time2", M98088_REG_45_PWRLMT_TIME, 4, 15, 0), - - SOC_SINGLE("THD Limiter Threshold", M98088_REG_46_THDLMT_CFG, 4, 15, 0), - SOC_SINGLE("THD Limiter Time", M98088_REG_46_THDLMT_CFG, 0, 7, 0), -}; - -/* Left speaker mixer switch */ -static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), - SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), - SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 2, 1, 0), - SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 3, 1, 0), - SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 4, 1, 0), -}; - -/* Right speaker mixer switch */ -static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0), - SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0), - SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 2, 1, 0), - SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 3, 1, 0), - SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 4, 1, 0), -}; - -/* Left headphone mixer switch */ -static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), - SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), - SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_25_MIX_HP_LEFT, 2, 1, 0), - SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_25_MIX_HP_LEFT, 3, 1, 0), - SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_25_MIX_HP_LEFT, 4, 1, 0), -}; - -/* Right headphone mixer switch */ -static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0), - SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0), - SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_26_MIX_HP_RIGHT, 2, 1, 0), - SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_26_MIX_HP_RIGHT, 3, 1, 0), - SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_26_MIX_HP_RIGHT, 4, 1, 0), -}; - -/* Left earpiece/receiver mixer switch */ -static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), - SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), - SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_28_MIX_REC_LEFT, 2, 1, 0), - SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_28_MIX_REC_LEFT, 3, 1, 0), - SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_28_MIX_REC_LEFT, 4, 1, 0), -}; - -/* Right earpiece/receiver mixer switch */ -static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0), - SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0), - SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_29_MIX_REC_RIGHT, 2, 1, 0), - SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_29_MIX_REC_RIGHT, 3, 1, 0), - SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_29_MIX_REC_RIGHT, 4, 1, 0), -}; - -/* Left ADC mixer switch */ -static const struct snd_kcontrol_new max98088_left_ADC_mixer_controls[] = { - SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_23_MIX_ADC_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_23_MIX_ADC_LEFT, 6, 1, 0), - SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_23_MIX_ADC_LEFT, 3, 1, 0), - SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_23_MIX_ADC_LEFT, 2, 1, 0), - SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_23_MIX_ADC_LEFT, 1, 1, 0), - SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_23_MIX_ADC_LEFT, 0, 1, 0), -}; - -/* Right ADC mixer switch */ -static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { - SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 6, 1, 0), - SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 3, 1, 0), - SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 2, 1, 0), - SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 1, 1, 0), - SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 0, 1, 0), -}; - -static int max98088_mic_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - if (w->reg == M98088_REG_35_LVL_MIC1) { - snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, - (1+max98088->mic1pre)<reg, M98088_MICPRE_MASK, - (1+max98088->mic2pre)<reg, M98088_MICPRE_MASK, 0); - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * The line inputs are 2-channel stereo inputs with the left - * and right channels sharing a common PGA power control signal. - */ -static int max98088_line_pga(struct snd_soc_dapm_widget *w, - int event, int line, u8 channel) -{ - struct snd_soc_codec *codec = w->codec; - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - u8 *state; - - BUG_ON(!((channel == 1) || (channel == 2))); - - switch (line) { - case LINE_INA: - state = &max98088->ina_state; - break; - case LINE_INB: - state = &max98088->inb_state; - break; - default: - return -EINVAL; - } - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - *state |= channel; - snd_soc_update_bits(codec, w->reg, - (1 << w->shift), (1 << w->shift)); - break; - case SND_SOC_DAPM_POST_PMD: - *state &= ~channel; - if (*state == 0) { - snd_soc_update_bits(codec, w->reg, - (1 << w->shift), 0); - } - break; - default: - return -EINVAL; - } - - return 0; -} - -static int max98088_pga_ina1_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - return max98088_line_pga(w, event, LINE_INA, 1); -} - -static int max98088_pga_ina2_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - return max98088_line_pga(w, event, LINE_INA, 2); -} - -static int max98088_pga_inb1_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - return max98088_line_pga(w, event, LINE_INB, 1); -} - -static int max98088_pga_inb2_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - return max98088_line_pga(w, event, LINE_INB, 2); -} - -static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { - - SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0), - SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0), - - SND_SOC_DAPM_DAC("DACL1", "HiFi Playback", - M98088_REG_4D_PWR_EN_OUT, 1, 0), - SND_SOC_DAPM_DAC("DACR1", "HiFi Playback", - M98088_REG_4D_PWR_EN_OUT, 0, 0), - SND_SOC_DAPM_DAC("DACL2", "Aux Playback", - M98088_REG_4D_PWR_EN_OUT, 1, 0), - SND_SOC_DAPM_DAC("DACR2", "Aux Playback", - M98088_REG_4D_PWR_EN_OUT, 0, 0), - - SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT, - 7, 0, NULL, 0), - SND_SOC_DAPM_PGA("HP Right Out", M98088_REG_4D_PWR_EN_OUT, - 6, 0, NULL, 0), - - SND_SOC_DAPM_PGA("SPK Left Out", M98088_REG_4D_PWR_EN_OUT, - 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPK Right Out", M98088_REG_4D_PWR_EN_OUT, - 4, 0, NULL, 0), - - SND_SOC_DAPM_PGA("REC Left Out", M98088_REG_4D_PWR_EN_OUT, - 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("REC Right Out", M98088_REG_4D_PWR_EN_OUT, - 2, 0, NULL, 0), - - SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0, - &max98088_extmic_mux), - - SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, - &max98088_left_hp_mixer_controls[0], - ARRAY_SIZE(max98088_left_hp_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0, - &max98088_right_hp_mixer_controls[0], - ARRAY_SIZE(max98088_right_hp_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left SPK Mixer", SND_SOC_NOPM, 0, 0, - &max98088_left_speaker_mixer_controls[0], - ARRAY_SIZE(max98088_left_speaker_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right SPK Mixer", SND_SOC_NOPM, 0, 0, - &max98088_right_speaker_mixer_controls[0], - ARRAY_SIZE(max98088_right_speaker_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left REC Mixer", SND_SOC_NOPM, 0, 0, - &max98088_left_rec_mixer_controls[0], - ARRAY_SIZE(max98088_left_rec_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right REC Mixer", SND_SOC_NOPM, 0, 0, - &max98088_right_rec_mixer_controls[0], - ARRAY_SIZE(max98088_right_rec_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0, - &max98088_left_ADC_mixer_controls[0], - ARRAY_SIZE(max98088_left_ADC_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0, - &max98088_right_ADC_mixer_controls[0], - ARRAY_SIZE(max98088_right_ADC_mixer_controls)), - - SND_SOC_DAPM_PGA_E("MIC1 Input", M98088_REG_35_LVL_MIC1, - 5, 0, NULL, 0, max98088_mic_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("MIC2 Input", M98088_REG_36_LVL_MIC2, - 5, 0, NULL, 0, max98088_mic_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("INA1 Input", M98088_REG_4C_PWR_EN_IN, - 7, 0, NULL, 0, max98088_pga_ina1_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("INA2 Input", M98088_REG_4C_PWR_EN_IN, - 7, 0, NULL, 0, max98088_pga_ina2_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("INB1 Input", M98088_REG_4C_PWR_EN_IN, - 6, 0, NULL, 0, max98088_pga_inb1_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("INB2 Input", M98088_REG_4C_PWR_EN_IN, - 6, 0, NULL, 0, max98088_pga_inb2_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0), - - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - SND_SOC_DAPM_OUTPUT("SPKL"), - SND_SOC_DAPM_OUTPUT("SPKR"), - SND_SOC_DAPM_OUTPUT("RECL"), - SND_SOC_DAPM_OUTPUT("RECR"), - - SND_SOC_DAPM_INPUT("MIC1"), - SND_SOC_DAPM_INPUT("MIC2"), - SND_SOC_DAPM_INPUT("INA1"), - SND_SOC_DAPM_INPUT("INA2"), - SND_SOC_DAPM_INPUT("INB1"), - SND_SOC_DAPM_INPUT("INB2"), -}; - -static const struct snd_soc_dapm_route max98088_audio_map[] = { - /* Left headphone output mixer */ - {"Left HP Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left HP Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left HP Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left HP Mixer", "Right DAC2 Switch", "DACR2"}, - {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Left HP Mixer", "INA1 Switch", "INA1 Input"}, - {"Left HP Mixer", "INA2 Switch", "INA2 Input"}, - {"Left HP Mixer", "INB1 Switch", "INB1 Input"}, - {"Left HP Mixer", "INB2 Switch", "INB2 Input"}, - - /* Right headphone output mixer */ - {"Right HP Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right HP Mixer", "Left DAC2 Switch", "DACL2" }, - {"Right HP Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right HP Mixer", "Right DAC2 Switch", "DACR2"}, - {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Right HP Mixer", "INA1 Switch", "INA1 Input"}, - {"Right HP Mixer", "INA2 Switch", "INA2 Input"}, - {"Right HP Mixer", "INB1 Switch", "INB1 Input"}, - {"Right HP Mixer", "INB2 Switch", "INB2 Input"}, - - /* Left speaker output mixer */ - {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"}, - {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Left SPK Mixer", "INA1 Switch", "INA1 Input"}, - {"Left SPK Mixer", "INA2 Switch", "INA2 Input"}, - {"Left SPK Mixer", "INB1 Switch", "INB1 Input"}, - {"Left SPK Mixer", "INB2 Switch", "INB2 Input"}, - - /* Right speaker output mixer */ - {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"}, - {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"}, - {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Right SPK Mixer", "INA1 Switch", "INA1 Input"}, - {"Right SPK Mixer", "INA2 Switch", "INA2 Input"}, - {"Right SPK Mixer", "INB1 Switch", "INB1 Input"}, - {"Right SPK Mixer", "INB2 Switch", "INB2 Input"}, - - /* Earpiece/Receiver output mixer */ - {"Left REC Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left REC Mixer", "Left DAC2 Switch", "DACL2"}, - {"Left REC Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left REC Mixer", "Right DAC2 Switch", "DACR2"}, - {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Left REC Mixer", "INA1 Switch", "INA1 Input"}, - {"Left REC Mixer", "INA2 Switch", "INA2 Input"}, - {"Left REC Mixer", "INB1 Switch", "INB1 Input"}, - {"Left REC Mixer", "INB2 Switch", "INB2 Input"}, - - /* Earpiece/Receiver output mixer */ - {"Right REC Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right REC Mixer", "Left DAC2 Switch", "DACL2"}, - {"Right REC Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right REC Mixer", "Right DAC2 Switch", "DACR2"}, - {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Right REC Mixer", "INA1 Switch", "INA1 Input"}, - {"Right REC Mixer", "INA2 Switch", "INA2 Input"}, - {"Right REC Mixer", "INB1 Switch", "INB1 Input"}, - {"Right REC Mixer", "INB2 Switch", "INB2 Input"}, - - {"HP Left Out", NULL, "Left HP Mixer"}, - {"HP Right Out", NULL, "Right HP Mixer"}, - {"SPK Left Out", NULL, "Left SPK Mixer"}, - {"SPK Right Out", NULL, "Right SPK Mixer"}, - {"REC Left Out", NULL, "Left REC Mixer"}, - {"REC Right Out", NULL, "Right REC Mixer"}, - - {"HPL", NULL, "HP Left Out"}, - {"HPR", NULL, "HP Right Out"}, - {"SPKL", NULL, "SPK Left Out"}, - {"SPKR", NULL, "SPK Right Out"}, - {"RECL", NULL, "REC Left Out"}, - {"RECR", NULL, "REC Right Out"}, - - /* Left ADC input mixer */ - {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Left ADC Mixer", "INA1 Switch", "INA1 Input"}, - {"Left ADC Mixer", "INA2 Switch", "INA2 Input"}, - {"Left ADC Mixer", "INB1 Switch", "INB1 Input"}, - {"Left ADC Mixer", "INB2 Switch", "INB2 Input"}, - - /* Right ADC input mixer */ - {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Right ADC Mixer", "INA1 Switch", "INA1 Input"}, - {"Right ADC Mixer", "INA2 Switch", "INA2 Input"}, - {"Right ADC Mixer", "INB1 Switch", "INB1 Input"}, - {"Right ADC Mixer", "INB2 Switch", "INB2 Input"}, - - /* Inputs */ - {"ADCL", NULL, "Left ADC Mixer"}, - {"ADCR", NULL, "Right ADC Mixer"}, - {"INA1 Input", NULL, "INA1"}, - {"INA2 Input", NULL, "INA2"}, - {"INB1 Input", NULL, "INB1"}, - {"INB2 Input", NULL, "INB2"}, - {"MIC1 Input", NULL, "MIC1"}, - {"MIC2 Input", NULL, "MIC2"}, -}; - -/* codec mclk clock divider coefficients */ -static const struct { - u32 rate; - u8 sr; -} rate_table[] = { - {8000, 0x10}, - {11025, 0x20}, - {16000, 0x30}, - {22050, 0x40}, - {24000, 0x50}, - {32000, 0x60}, - {44100, 0x70}, - {48000, 0x80}, - {88200, 0x90}, - {96000, 0xA0}, -}; - -static inline int rate_value(int rate, u8 *value) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(rate_table); i++) { - if (rate_table[i].rate >= rate) { - *value = rate_table[i].sr; - return 0; - } - } - *value = rate_table[0].sr; - return -EINVAL; -} - -static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; - unsigned long long ni; - unsigned int rate; - u8 regval; - - cdata = &max98088->dai[0]; - - rate = params_rate(params); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, - M98088_DAI_WS, 0); - break; - case SNDRV_PCM_FORMAT_S24_LE: - snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, - M98088_DAI_WS, M98088_DAI_WS); - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); - - if (rate_value(rate, ®val)) - return -EINVAL; - - snd_soc_update_bits(codec, M98088_REG_11_DAI1_CLKMODE, - M98088_CLKMODE_MASK, regval); - cdata->rate = rate; - - /* Configure NI when operating as master */ - if (snd_soc_read(codec, M98088_REG_14_DAI1_FORMAT) - & M98088_DAI_MAS) { - if (max98088->sysclk == 0) { - dev_err(codec->dev, "Invalid system clock frequency\n"); - return -EINVAL; - } - ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) - * (unsigned long long int)rate; - do_div(ni, (unsigned long long int)max98088->sysclk); - snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI, - (ni >> 8) & 0x7F); - snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO, - ni & 0xFF); - } - - /* Update sample rate mode */ - if (rate < 50000) - snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS, - M98088_DAI_DHF, 0); - else - snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS, - M98088_DAI_DHF, M98088_DAI_DHF); - - snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, - M98088_SHDNRUN); - - return 0; -} - -static int max98088_dai2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; - unsigned long long ni; - unsigned int rate; - u8 regval; - - cdata = &max98088->dai[1]; - - rate = params_rate(params); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, - M98088_DAI_WS, 0); - break; - case SNDRV_PCM_FORMAT_S24_LE: - snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, - M98088_DAI_WS, M98088_DAI_WS); - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); - - if (rate_value(rate, ®val)) - return -EINVAL; - - snd_soc_update_bits(codec, M98088_REG_19_DAI2_CLKMODE, - M98088_CLKMODE_MASK, regval); - cdata->rate = rate; - - /* Configure NI when operating as master */ - if (snd_soc_read(codec, M98088_REG_1C_DAI2_FORMAT) - & M98088_DAI_MAS) { - if (max98088->sysclk == 0) { - dev_err(codec->dev, "Invalid system clock frequency\n"); - return -EINVAL; - } - ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) - * (unsigned long long int)rate; - do_div(ni, (unsigned long long int)max98088->sysclk); - snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI, - (ni >> 8) & 0x7F); - snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO, - ni & 0xFF); - } - - /* Update sample rate mode */ - if (rate < 50000) - snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS, - M98088_DAI_DHF, 0); - else - snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS, - M98088_DAI_DHF, M98088_DAI_DHF); - - snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, - M98088_SHDNRUN); - - return 0; -} - -static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - - /* Requested clock frequency is already setup */ - if (freq == max98088->sysclk) - return 0; - - /* Setup clocks for slave mode, and using the PLL - * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) - * 0x02 (when master clk is 20MHz to 30MHz).. - */ - if ((freq >= 10000000) && (freq < 20000000)) { - snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x10); - } else if ((freq >= 20000000) && (freq < 30000000)) { - snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x20); - } else { - dev_err(codec->dev, "Invalid master clock frequency\n"); - return -EINVAL; - } - - if (snd_soc_read(codec, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) { - snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, - M98088_SHDNRUN, 0); - snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, - M98088_SHDNRUN, M98088_SHDNRUN); - } - - dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); - - max98088->sysclk = freq; - return 0; -} - -static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; - u8 reg15val; - u8 reg14val = 0; - - cdata = &max98088->dai[0]; - - if (fmt != cdata->fmt) { - cdata->fmt = fmt; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* Slave mode PLL */ - snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI, - 0x80); - snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO, - 0x00); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Set to master mode */ - reg14val |= M98088_DAI_MAS; - break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - default: - dev_err(codec->dev, "Clock mode unsupported"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - reg14val |= M98088_DAI_DLY; - break; - case SND_SOC_DAIFMT_LEFT_J: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - reg14val |= M98088_DAI_WCI; - break; - case SND_SOC_DAIFMT_IB_NF: - reg14val |= M98088_DAI_BCI; - break; - case SND_SOC_DAIFMT_IB_IF: - reg14val |= M98088_DAI_BCI|M98088_DAI_WCI; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, - M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | - M98088_DAI_WCI, reg14val); - - reg15val = M98088_DAI_BSEL64; - if (max98088->digmic) - reg15val |= M98088_DAI_OSR64; - snd_soc_write(codec, M98088_REG_15_DAI1_CLOCK, reg15val); - } - - return 0; -} - -static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; - u8 reg1Cval = 0; - - cdata = &max98088->dai[1]; - - if (fmt != cdata->fmt) { - cdata->fmt = fmt; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* Slave mode PLL */ - snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI, - 0x80); - snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO, - 0x00); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Set to master mode */ - reg1Cval |= M98088_DAI_MAS; - break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - default: - dev_err(codec->dev, "Clock mode unsupported"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - reg1Cval |= M98088_DAI_DLY; - break; - case SND_SOC_DAIFMT_LEFT_J: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - reg1Cval |= M98088_DAI_WCI; - break; - case SND_SOC_DAIFMT_IB_NF: - reg1Cval |= M98088_DAI_BCI; - break; - case SND_SOC_DAIFMT_IB_IF: - reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, - M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | - M98088_DAI_WCI, reg1Cval); - - snd_soc_write(codec, M98088_REG_1D_DAI2_CLOCK, - M98088_DAI_BSEL64); - } - - return 0; -} - -static int max98088_dai1_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int reg; - - if (mute) - reg = M98088_DAI_MUTE; - else - reg = 0; - - snd_soc_update_bits(codec, M98088_REG_2F_LVL_DAI1_PLAY, - M98088_DAI_MUTE_MASK, reg); - return 0; -} - -static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int reg; - - if (mute) - reg = M98088_DAI_MUTE; - else - reg = 0; - - snd_soc_update_bits(codec, M98088_REG_31_LVL_DAI2_PLAY, - M98088_DAI_MUTE_MASK, reg); - return 0; -} - -static void max98088_sync_cache(struct snd_soc_codec *codec) -{ - u16 *reg_cache = codec->reg_cache; - int i; - - if (!codec->cache_sync) - return; - - codec->cache_only = 0; - - /* write back cached values if they're writeable and - * different from the hardware default. - */ - for (i = 1; i < codec->driver->reg_cache_size; i++) { - if (!max98088_access[i].writable) - continue; - - if (reg_cache[i] == max98088_reg[i]) - continue; - - snd_soc_write(codec, i, reg_cache[i]); - } - - codec->cache_sync = 0; -} - -static int max98088_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - max98088_sync_cache(codec); - - snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, - M98088_MBEN, M98088_MBEN); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, - M98088_MBEN, 0); - codec->cache_sync = 1; - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define MAX98088_RATES SNDRV_PCM_RATE_8000_96000 -#define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops max98088_dai1_ops = { - .set_sysclk = max98088_dai_set_sysclk, - .set_fmt = max98088_dai1_set_fmt, - .hw_params = max98088_dai1_hw_params, - .digital_mute = max98088_dai1_digital_mute, -}; - -static const struct snd_soc_dai_ops max98088_dai2_ops = { - .set_sysclk = max98088_dai_set_sysclk, - .set_fmt = max98088_dai2_set_fmt, - .hw_params = max98088_dai2_hw_params, - .digital_mute = max98088_dai2_digital_mute, -}; - -static struct snd_soc_dai_driver max98088_dai[] = { -{ - .name = "HiFi", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98088_RATES, - .formats = MAX98088_FORMATS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98088_RATES, - .formats = MAX98088_FORMATS, - }, - .ops = &max98088_dai1_ops, -}, -{ - .name = "Aux", - .playback = { - .stream_name = "Aux Playback", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98088_RATES, - .formats = MAX98088_FORMATS, - }, - .ops = &max98088_dai2_ops, -} -}; - -static const char *eq_mode_name[] = {"EQ1 Mode", "EQ2 Mode"}; - -static int max98088_get_channel(struct snd_soc_codec *codec, const char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(eq_mode_name); i++) - if (strcmp(name, eq_mode_name[i]) == 0) - return i; - - /* Shouldn't happen */ - dev_err(codec->dev, "Bad EQ channel name '%s'\n", name); - return -EINVAL; -} - -static void max98088_setup_eq1(struct snd_soc_codec *codec) -{ - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_pdata *pdata = max98088->pdata; - struct max98088_eq_cfg *coef_set; - int best, best_val, save, i, sel, fs; - struct max98088_cdata *cdata; - - cdata = &max98088->dai[0]; - - if (!pdata || !max98088->eq_textcnt) - return; - - /* Find the selected configuration with nearest sample rate */ - fs = cdata->rate; - sel = cdata->eq_sel; - - best = 0; - best_val = INT_MAX; - for (i = 0; i < pdata->eq_cfgcnt; i++) { - if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && - abs(pdata->eq_cfg[i].rate - fs) < best_val) { - best = i; - best_val = abs(pdata->eq_cfg[i].rate - fs); - } - } - - dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", - pdata->eq_cfg[best].name, - pdata->eq_cfg[best].rate, fs); - - /* Disable EQ while configuring, and save current on/off state */ - save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL); - snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0); - - coef_set = &pdata->eq_cfg[sel]; - - m98088_eq_band(codec, 0, 0, coef_set->band1); - m98088_eq_band(codec, 0, 1, coef_set->band2); - m98088_eq_band(codec, 0, 2, coef_set->band3); - m98088_eq_band(codec, 0, 3, coef_set->band4); - m98088_eq_band(codec, 0, 4, coef_set->band5); - - /* Restore the original on/off state */ - snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, save); -} - -static void max98088_setup_eq2(struct snd_soc_codec *codec) -{ - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_pdata *pdata = max98088->pdata; - struct max98088_eq_cfg *coef_set; - int best, best_val, save, i, sel, fs; - struct max98088_cdata *cdata; - - cdata = &max98088->dai[1]; - - if (!pdata || !max98088->eq_textcnt) - return; - - /* Find the selected configuration with nearest sample rate */ - fs = cdata->rate; - - sel = cdata->eq_sel; - best = 0; - best_val = INT_MAX; - for (i = 0; i < pdata->eq_cfgcnt; i++) { - if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && - abs(pdata->eq_cfg[i].rate - fs) < best_val) { - best = i; - best_val = abs(pdata->eq_cfg[i].rate - fs); - } - } - - dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", - pdata->eq_cfg[best].name, - pdata->eq_cfg[best].rate, fs); - - /* Disable EQ while configuring, and save current on/off state */ - save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL); - snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0); - - coef_set = &pdata->eq_cfg[sel]; - - m98088_eq_band(codec, 1, 0, coef_set->band1); - m98088_eq_band(codec, 1, 1, coef_set->band2); - m98088_eq_band(codec, 1, 2, coef_set->band3); - m98088_eq_band(codec, 1, 3, coef_set->band4); - m98088_eq_band(codec, 1, 4, coef_set->band5); - - /* Restore the original on/off state */ - snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, - save); -} - -static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_pdata *pdata = max98088->pdata; - int channel = max98088_get_channel(codec, kcontrol->id.name); - struct max98088_cdata *cdata; - int sel = ucontrol->value.integer.value[0]; - - if (channel < 0) - return channel; - - cdata = &max98088->dai[channel]; - - if (sel >= pdata->eq_cfgcnt) - return -EINVAL; - - cdata->eq_sel = sel; - - switch (channel) { - case 0: - max98088_setup_eq1(codec); - break; - case 1: - max98088_setup_eq2(codec); - break; - } - - return 0; -} - -static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - int channel = max98088_get_channel(codec, kcontrol->id.name); - struct max98088_cdata *cdata; - - if (channel < 0) - return channel; - - cdata = &max98088->dai[channel]; - ucontrol->value.enumerated.item[0] = cdata->eq_sel; - return 0; -} - -static void max98088_handle_eq_pdata(struct snd_soc_codec *codec) -{ - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_pdata *pdata = max98088->pdata; - struct max98088_eq_cfg *cfg; - unsigned int cfgcnt; - int i, j; - const char **t; - int ret; - struct snd_kcontrol_new controls[] = { - SOC_ENUM_EXT((char *)eq_mode_name[0], - max98088->eq_enum, - max98088_get_eq_enum, - max98088_put_eq_enum), - SOC_ENUM_EXT((char *)eq_mode_name[1], - max98088->eq_enum, - max98088_get_eq_enum, - max98088_put_eq_enum), - }; - BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(eq_mode_name)); - - cfg = pdata->eq_cfg; - cfgcnt = pdata->eq_cfgcnt; - - /* Setup an array of texts for the equalizer enum. - * This is based on Mark Brown's equalizer driver code. - */ - max98088->eq_textcnt = 0; - max98088->eq_texts = NULL; - for (i = 0; i < cfgcnt; i++) { - for (j = 0; j < max98088->eq_textcnt; j++) { - if (strcmp(cfg[i].name, max98088->eq_texts[j]) == 0) - break; - } - - if (j != max98088->eq_textcnt) - continue; - - /* Expand the array */ - t = krealloc(max98088->eq_texts, - sizeof(char *) * (max98088->eq_textcnt + 1), - GFP_KERNEL); - if (t == NULL) - continue; - - /* Store the new entry */ - t[max98088->eq_textcnt] = cfg[i].name; - max98088->eq_textcnt++; - max98088->eq_texts = t; - } - - /* Now point the soc_enum to .texts array items */ - max98088->eq_enum.texts = max98088->eq_texts; - max98088->eq_enum.max = max98088->eq_textcnt; - - ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); - if (ret != 0) - dev_err(codec->dev, "Failed to add EQ control: %d\n", ret); -} - -static void max98088_handle_pdata(struct snd_soc_codec *codec) -{ - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_pdata *pdata = max98088->pdata; - u8 regval = 0; - - if (!pdata) { - dev_dbg(codec->dev, "No platform data\n"); - return; - } - - /* Configure mic for analog/digital mic mode */ - if (pdata->digmic_left_mode) - regval |= M98088_DIGMIC_L; - - if (pdata->digmic_right_mode) - regval |= M98088_DIGMIC_R; - - max98088->digmic = (regval ? 1 : 0); - - snd_soc_write(codec, M98088_REG_48_CFG_MIC, regval); - - /* Configure receiver output */ - regval = ((pdata->receiver_mode) ? M98088_REC_LINEMODE : 0); - snd_soc_update_bits(codec, M98088_REG_2A_MIC_REC_CNTL, - M98088_REC_LINEMODE_MASK, regval); - - /* Configure equalizers */ - if (pdata->eq_cfgcnt) - max98088_handle_eq_pdata(codec); -} - -#ifdef CONFIG_PM -static int max98088_suspend(struct snd_soc_codec *codec) -{ - max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int max98088_resume(struct snd_soc_codec *codec) -{ - max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define max98088_suspend NULL -#define max98088_resume NULL -#endif - -static int max98088_probe(struct snd_soc_codec *codec) -{ - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - struct max98088_cdata *cdata; - int ret = 0; - - codec->cache_sync = 1; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* initialize private data */ - - max98088->sysclk = (unsigned)-1; - max98088->eq_textcnt = 0; - - cdata = &max98088->dai[0]; - cdata->rate = (unsigned)-1; - cdata->fmt = (unsigned)-1; - cdata->eq_sel = 0; - - cdata = &max98088->dai[1]; - cdata->rate = (unsigned)-1; - cdata->fmt = (unsigned)-1; - cdata->eq_sel = 0; - - max98088->ina_state = 0; - max98088->inb_state = 0; - max98088->ex_mode = 0; - max98088->digmic = 0; - max98088->mic1pre = 0; - max98088->mic2pre = 0; - - ret = snd_soc_read(codec, M98088_REG_FF_REV_ID); - if (ret < 0) { - dev_err(codec->dev, "Failed to read device revision: %d\n", - ret); - goto err_access; - } - dev_info(codec->dev, "revision %c\n", ret + 'A'); - - snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); - - /* initialize registers cache to hardware default */ - max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00); - - snd_soc_write(codec, M98088_REG_22_MIX_DAC, - M98088_DAI1L_TO_DACL|M98088_DAI2L_TO_DACL| - M98088_DAI1R_TO_DACR|M98088_DAI2R_TO_DACR); - - snd_soc_write(codec, M98088_REG_4E_BIAS_CNTL, 0xF0); - snd_soc_write(codec, M98088_REG_50_DAC_BIAS2, 0x0F); - - snd_soc_write(codec, M98088_REG_16_DAI1_IOCFG, - M98088_S1NORMAL|M98088_SDATA); - - snd_soc_write(codec, M98088_REG_1E_DAI2_IOCFG, - M98088_S2NORMAL|M98088_SDATA); - - max98088_handle_pdata(codec); - - snd_soc_add_codec_controls(codec, max98088_snd_controls, - ARRAY_SIZE(max98088_snd_controls)); - -err_access: - return ret; -} - -static int max98088_remove(struct snd_soc_codec *codec) -{ - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); - - max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); - kfree(max98088->eq_texts); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_max98088 = { - .probe = max98088_probe, - .remove = max98088_remove, - .suspend = max98088_suspend, - .resume = max98088_resume, - .set_bias_level = max98088_set_bias_level, - .reg_cache_size = ARRAY_SIZE(max98088_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = max98088_reg, - .volatile_register = max98088_volatile_register, - .dapm_widgets = max98088_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), - .dapm_routes = max98088_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98088_audio_map), -}; - -static int max98088_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct max98088_priv *max98088; - int ret; - - max98088 = devm_kzalloc(&i2c->dev, sizeof(struct max98088_priv), - GFP_KERNEL); - if (max98088 == NULL) - return -ENOMEM; - - max98088->devtype = id->driver_data; - - i2c_set_clientdata(i2c, max98088); - max98088->pdata = i2c->dev.platform_data; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_max98088, &max98088_dai[0], 2); - return ret; -} - -static int __devexit max98088_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id max98088_i2c_id[] = { - { "max98088", MAX98088 }, - { "max98089", MAX98089 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); - -static struct i2c_driver max98088_i2c_driver = { - .driver = { - .name = "max98088", - .owner = THIS_MODULE, - }, - .probe = max98088_i2c_probe, - .remove = __devexit_p(max98088_i2c_remove), - .id_table = max98088_i2c_id, -}; - -static int __init max98088_init(void) -{ - int ret; - - ret = i2c_add_driver(&max98088_i2c_driver); - if (ret) - pr_err("Failed to register max98088 I2C driver: %d\n", ret); - - return ret; -} -module_init(max98088_init); - -static void __exit max98088_exit(void) -{ - i2c_del_driver(&max98088_i2c_driver); -} -module_exit(max98088_exit); - -MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); -MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/max98088.h b/ANDROID_3.4.5/sound/soc/codecs/max98088.h deleted file mode 100644 index be89a4f4..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max98088.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * max98088.h -- MAX98088 ALSA SoC Audio driver - * - * Copyright 2010 Maxim Integrated Products - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _MAX98088_H -#define _MAX98088_H - -/* - * MAX98088 Registers Definition - */ -#define M98088_REG_00_IRQ_STATUS 0x00 -#define M98088_REG_01_MIC_STATUS 0x01 -#define M98088_REG_02_JACK_STAUS 0x02 -#define M98088_REG_03_BATTERY_VOLTAGE 0x03 -#define M98088_REG_0F_IRQ_ENABLE 0x0F -#define M98088_REG_10_SYS_CLK 0x10 -#define M98088_REG_11_DAI1_CLKMODE 0x11 -#define M98088_REG_12_DAI1_CLKCFG_HI 0x12 -#define M98088_REG_13_DAI1_CLKCFG_LO 0x13 -#define M98088_REG_14_DAI1_FORMAT 0x14 -#define M98088_REG_15_DAI1_CLOCK 0x15 -#define M98088_REG_16_DAI1_IOCFG 0x16 -#define M98088_REG_17_DAI1_TDM 0x17 -#define M98088_REG_18_DAI1_FILTERS 0x18 -#define M98088_REG_19_DAI2_CLKMODE 0x19 -#define M98088_REG_1A_DAI2_CLKCFG_HI 0x1A -#define M98088_REG_1B_DAI2_CLKCFG_LO 0x1B -#define M98088_REG_1C_DAI2_FORMAT 0x1C -#define M98088_REG_1D_DAI2_CLOCK 0x1D -#define M98088_REG_1E_DAI2_IOCFG 0x1E -#define M98088_REG_1F_DAI2_TDM 0x1F -#define M98088_REG_20_DAI2_FILTERS 0x20 -#define M98088_REG_21_SRC 0x21 -#define M98088_REG_22_MIX_DAC 0x22 -#define M98088_REG_23_MIX_ADC_LEFT 0x23 -#define M98088_REG_24_MIX_ADC_RIGHT 0x24 -#define M98088_REG_25_MIX_HP_LEFT 0x25 -#define M98088_REG_26_MIX_HP_RIGHT 0x26 -#define M98088_REG_27_MIX_HP_CNTL 0x27 -#define M98088_REG_28_MIX_REC_LEFT 0x28 -#define M98088_REG_29_MIX_REC_RIGHT 0x29 -#define M98088_REG_2A_MIC_REC_CNTL 0x2A -#define M98088_REG_2B_MIX_SPK_LEFT 0x2B -#define M98088_REG_2C_MIX_SPK_RIGHT 0x2C -#define M98088_REG_2D_MIX_SPK_CNTL 0x2D -#define M98088_REG_2E_LVL_SIDETONE 0x2E -#define M98088_REG_2F_LVL_DAI1_PLAY 0x2F -#define M98088_REG_30_LVL_DAI1_PLAY_EQ 0x30 -#define M98088_REG_31_LVL_DAI2_PLAY 0x31 -#define M98088_REG_32_LVL_DAI2_PLAY_EQ 0x32 -#define M98088_REG_33_LVL_ADC_L 0x33 -#define M98088_REG_34_LVL_ADC_R 0x34 -#define M98088_REG_35_LVL_MIC1 0x35 -#define M98088_REG_36_LVL_MIC2 0x36 -#define M98088_REG_37_LVL_INA 0x37 -#define M98088_REG_38_LVL_INB 0x38 -#define M98088_REG_39_LVL_HP_L 0x39 -#define M98088_REG_3A_LVL_HP_R 0x3A -#define M98088_REG_3B_LVL_REC_L 0x3B -#define M98088_REG_3C_LVL_REC_R 0x3C -#define M98088_REG_3D_LVL_SPK_L 0x3D -#define M98088_REG_3E_LVL_SPK_R 0x3E -#define M98088_REG_3F_MICAGC_CFG 0x3F -#define M98088_REG_40_MICAGC_THRESH 0x40 -#define M98088_REG_41_SPKDHP 0x41 -#define M98088_REG_42_SPKDHP_THRESH 0x42 -#define M98088_REG_43_SPKALC_COMP 0x43 -#define M98088_REG_44_PWRLMT_CFG 0x44 -#define M98088_REG_45_PWRLMT_TIME 0x45 -#define M98088_REG_46_THDLMT_CFG 0x46 -#define M98088_REG_47_CFG_AUDIO_IN 0x47 -#define M98088_REG_48_CFG_MIC 0x48 -#define M98088_REG_49_CFG_LEVEL 0x49 -#define M98088_REG_4A_CFG_BYPASS 0x4A -#define M98088_REG_4B_CFG_JACKDET 0x4B -#define M98088_REG_4C_PWR_EN_IN 0x4C -#define M98088_REG_4D_PWR_EN_OUT 0x4D -#define M98088_REG_4E_BIAS_CNTL 0x4E -#define M98088_REG_4F_DAC_BIAS1 0x4F -#define M98088_REG_50_DAC_BIAS2 0x50 -#define M98088_REG_51_PWR_SYS 0x51 -#define M98088_REG_52_DAI1_EQ_BASE 0x52 -#define M98088_REG_84_DAI2_EQ_BASE 0x84 -#define M98088_REG_B6_DAI1_BIQUAD_BASE 0xB6 -#define M98088_REG_C0_DAI2_BIQUAD_BASE 0xC0 -#define M98088_REG_FF_REV_ID 0xFF - -#define M98088_REG_CNT (0xFF+1) - -/* MAX98088 Registers Bit Fields */ - -/* M98088_REG_11_DAI1_CLKMODE, M98088_REG_19_DAI2_CLKMODE */ - #define M98088_CLKMODE_MASK 0xFF - -/* M98088_REG_14_DAI1_FORMAT, M98088_REG_1C_DAI2_FORMAT */ - #define M98088_DAI_MAS (1<<7) - #define M98088_DAI_WCI (1<<6) - #define M98088_DAI_BCI (1<<5) - #define M98088_DAI_DLY (1<<4) - #define M98088_DAI_TDM (1<<2) - #define M98088_DAI_FSW (1<<1) - #define M98088_DAI_WS (1<<0) - -/* M98088_REG_15_DAI1_CLOCK, M98088_REG_1D_DAI2_CLOCK */ - #define M98088_DAI_BSEL64 (1<<0) - #define M98088_DAI_OSR64 (1<<6) - -/* M98088_REG_16_DAI1_IOCFG, M98088_REG_1E_DAI2_IOCFG */ - #define M98088_S1NORMAL (1<<6) - #define M98088_S2NORMAL (2<<6) - #define M98088_SDATA (3<<0) - -/* M98088_REG_18_DAI1_FILTERS, M98088_REG_20_DAI2_FILTERS */ - #define M98088_DAI_DHF (1<<3) - -/* M98088_REG_22_MIX_DAC */ - #define M98088_DAI1L_TO_DACL (1<<7) - #define M98088_DAI1R_TO_DACL (1<<6) - #define M98088_DAI2L_TO_DACL (1<<5) - #define M98088_DAI2R_TO_DACL (1<<4) - #define M98088_DAI1L_TO_DACR (1<<3) - #define M98088_DAI1R_TO_DACR (1<<2) - #define M98088_DAI2L_TO_DACR (1<<1) - #define M98088_DAI2R_TO_DACR (1<<0) - -/* M98088_REG_2A_MIC_REC_CNTL */ - #define M98088_REC_LINEMODE (1<<7) - #define M98088_REC_LINEMODE_MASK (1<<7) - -/* M98088_REG_2D_MIX_SPK_CNTL */ - #define M98088_MIX_SPKR_GAIN_MASK (3<<2) - #define M98088_MIX_SPKR_GAIN_SHIFT 2 - #define M98088_MIX_SPKL_GAIN_MASK (3<<0) - #define M98088_MIX_SPKL_GAIN_SHIFT 0 - -/* M98088_REG_2F_LVL_DAI1_PLAY, M98088_REG_31_LVL_DAI2_PLAY */ - #define M98088_DAI_MUTE (1<<7) - #define M98088_DAI_MUTE_MASK (1<<7) - #define M98088_DAI_VOICE_GAIN_MASK (3<<4) - #define M98088_DAI_ATTENUATION_MASK (0xF<<0) - #define M98088_DAI_ATTENUATION_SHIFT 0 - -/* M98088_REG_35_LVL_MIC1, M98088_REG_36_LVL_MIC2 */ - #define M98088_MICPRE_MASK (3<<5) - #define M98088_MICPRE_SHIFT 5 - -/* M98088_REG_3A_LVL_HP_R */ - #define M98088_HP_MUTE (1<<7) - -/* M98088_REG_3C_LVL_REC_R */ - #define M98088_REC_MUTE (1<<7) - -/* M98088_REG_3E_LVL_SPK_R */ - #define M98088_SP_MUTE (1<<7) - -/* M98088_REG_48_CFG_MIC */ - #define M98088_EXTMIC_MASK (3<<0) - #define M98088_DIGMIC_L (1<<5) - #define M98088_DIGMIC_R (1<<4) - -/* M98088_REG_49_CFG_LEVEL */ - #define M98088_VSEN (1<<6) - #define M98088_ZDEN (1<<5) - #define M98088_EQ2EN (1<<1) - #define M98088_EQ1EN (1<<0) - -/* M98088_REG_4C_PWR_EN_IN */ - #define M98088_INAEN (1<<7) - #define M98088_INBEN (1<<6) - #define M98088_MBEN (1<<3) - #define M98088_ADLEN (1<<1) - #define M98088_ADREN (1<<0) - -/* M98088_REG_4D_PWR_EN_OUT */ - #define M98088_HPLEN (1<<7) - #define M98088_HPREN (1<<6) - #define M98088_HPEN ((1<<7)|(1<<6)) - #define M98088_SPLEN (1<<5) - #define M98088_SPREN (1<<4) - #define M98088_RECEN (1<<3) - #define M98088_DALEN (1<<1) - #define M98088_DAREN (1<<0) - -/* M98088_REG_51_PWR_SYS */ - #define M98088_SHDNRUN (1<<7) - #define M98088_PERFMODE (1<<3) - #define M98088_HPPLYBACK (1<<2) - #define M98088_PWRSV8K (1<<1) - #define M98088_PWRSV (1<<0) - -/* Line inputs */ -#define LINE_INA 0 -#define LINE_INB 1 - -#define M98088_COEFS_PER_BAND 5 - -#define M98088_BYTE1(w) ((w >> 8) & 0xff) -#define M98088_BYTE0(w) (w & 0xff) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/max98095.c b/ANDROID_3.4.5/sound/soc/codecs/max98095.c deleted file mode 100644 index 0bb511a0..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max98095.c +++ /dev/null @@ -1,2399 +0,0 @@ -/* - * max98095.c -- MAX98095 ALSA SoC Audio driver - * - * Copyright 2011 Maxim Integrated Products - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "max98095.h" - -enum max98095_type { - MAX98095, -}; - -struct max98095_cdata { - unsigned int rate; - unsigned int fmt; - int eq_sel; - int bq_sel; -}; - -struct max98095_priv { - enum max98095_type devtype; - struct max98095_pdata *pdata; - unsigned int sysclk; - struct max98095_cdata dai[3]; - const char **eq_texts; - const char **bq_texts; - struct soc_enum eq_enum; - struct soc_enum bq_enum; - int eq_textcnt; - int bq_textcnt; - u8 lin_state; - unsigned int mic1pre; - unsigned int mic2pre; -}; - -static const u8 max98095_reg_def[M98095_REG_CNT] = { - 0x00, /* 00 */ - 0x00, /* 01 */ - 0x00, /* 02 */ - 0x00, /* 03 */ - 0x00, /* 04 */ - 0x00, /* 05 */ - 0x00, /* 06 */ - 0x00, /* 07 */ - 0x00, /* 08 */ - 0x00, /* 09 */ - 0x00, /* 0A */ - 0x00, /* 0B */ - 0x00, /* 0C */ - 0x00, /* 0D */ - 0x00, /* 0E */ - 0x00, /* 0F */ - 0x00, /* 10 */ - 0x00, /* 11 */ - 0x00, /* 12 */ - 0x00, /* 13 */ - 0x00, /* 14 */ - 0x00, /* 15 */ - 0x00, /* 16 */ - 0x00, /* 17 */ - 0x00, /* 18 */ - 0x00, /* 19 */ - 0x00, /* 1A */ - 0x00, /* 1B */ - 0x00, /* 1C */ - 0x00, /* 1D */ - 0x00, /* 1E */ - 0x00, /* 1F */ - 0x00, /* 20 */ - 0x00, /* 21 */ - 0x00, /* 22 */ - 0x00, /* 23 */ - 0x00, /* 24 */ - 0x00, /* 25 */ - 0x00, /* 26 */ - 0x00, /* 27 */ - 0x00, /* 28 */ - 0x00, /* 29 */ - 0x00, /* 2A */ - 0x00, /* 2B */ - 0x00, /* 2C */ - 0x00, /* 2D */ - 0x00, /* 2E */ - 0x00, /* 2F */ - 0x00, /* 30 */ - 0x00, /* 31 */ - 0x00, /* 32 */ - 0x00, /* 33 */ - 0x00, /* 34 */ - 0x00, /* 35 */ - 0x00, /* 36 */ - 0x00, /* 37 */ - 0x00, /* 38 */ - 0x00, /* 39 */ - 0x00, /* 3A */ - 0x00, /* 3B */ - 0x00, /* 3C */ - 0x00, /* 3D */ - 0x00, /* 3E */ - 0x00, /* 3F */ - 0x00, /* 40 */ - 0x00, /* 41 */ - 0x00, /* 42 */ - 0x00, /* 43 */ - 0x00, /* 44 */ - 0x00, /* 45 */ - 0x00, /* 46 */ - 0x00, /* 47 */ - 0x00, /* 48 */ - 0x00, /* 49 */ - 0x00, /* 4A */ - 0x00, /* 4B */ - 0x00, /* 4C */ - 0x00, /* 4D */ - 0x00, /* 4E */ - 0x00, /* 4F */ - 0x00, /* 50 */ - 0x00, /* 51 */ - 0x00, /* 52 */ - 0x00, /* 53 */ - 0x00, /* 54 */ - 0x00, /* 55 */ - 0x00, /* 56 */ - 0x00, /* 57 */ - 0x00, /* 58 */ - 0x00, /* 59 */ - 0x00, /* 5A */ - 0x00, /* 5B */ - 0x00, /* 5C */ - 0x00, /* 5D */ - 0x00, /* 5E */ - 0x00, /* 5F */ - 0x00, /* 60 */ - 0x00, /* 61 */ - 0x00, /* 62 */ - 0x00, /* 63 */ - 0x00, /* 64 */ - 0x00, /* 65 */ - 0x00, /* 66 */ - 0x00, /* 67 */ - 0x00, /* 68 */ - 0x00, /* 69 */ - 0x00, /* 6A */ - 0x00, /* 6B */ - 0x00, /* 6C */ - 0x00, /* 6D */ - 0x00, /* 6E */ - 0x00, /* 6F */ - 0x00, /* 70 */ - 0x00, /* 71 */ - 0x00, /* 72 */ - 0x00, /* 73 */ - 0x00, /* 74 */ - 0x00, /* 75 */ - 0x00, /* 76 */ - 0x00, /* 77 */ - 0x00, /* 78 */ - 0x00, /* 79 */ - 0x00, /* 7A */ - 0x00, /* 7B */ - 0x00, /* 7C */ - 0x00, /* 7D */ - 0x00, /* 7E */ - 0x00, /* 7F */ - 0x00, /* 80 */ - 0x00, /* 81 */ - 0x00, /* 82 */ - 0x00, /* 83 */ - 0x00, /* 84 */ - 0x00, /* 85 */ - 0x00, /* 86 */ - 0x00, /* 87 */ - 0x00, /* 88 */ - 0x00, /* 89 */ - 0x00, /* 8A */ - 0x00, /* 8B */ - 0x00, /* 8C */ - 0x00, /* 8D */ - 0x00, /* 8E */ - 0x00, /* 8F */ - 0x00, /* 90 */ - 0x00, /* 91 */ - 0x30, /* 92 */ - 0xF0, /* 93 */ - 0x00, /* 94 */ - 0x00, /* 95 */ - 0x3F, /* 96 */ - 0x00, /* 97 */ - 0x00, /* 98 */ - 0x00, /* 99 */ - 0x00, /* 9A */ - 0x00, /* 9B */ - 0x00, /* 9C */ - 0x00, /* 9D */ - 0x00, /* 9E */ - 0x00, /* 9F */ - 0x00, /* A0 */ - 0x00, /* A1 */ - 0x00, /* A2 */ - 0x00, /* A3 */ - 0x00, /* A4 */ - 0x00, /* A5 */ - 0x00, /* A6 */ - 0x00, /* A7 */ - 0x00, /* A8 */ - 0x00, /* A9 */ - 0x00, /* AA */ - 0x00, /* AB */ - 0x00, /* AC */ - 0x00, /* AD */ - 0x00, /* AE */ - 0x00, /* AF */ - 0x00, /* B0 */ - 0x00, /* B1 */ - 0x00, /* B2 */ - 0x00, /* B3 */ - 0x00, /* B4 */ - 0x00, /* B5 */ - 0x00, /* B6 */ - 0x00, /* B7 */ - 0x00, /* B8 */ - 0x00, /* B9 */ - 0x00, /* BA */ - 0x00, /* BB */ - 0x00, /* BC */ - 0x00, /* BD */ - 0x00, /* BE */ - 0x00, /* BF */ - 0x00, /* C0 */ - 0x00, /* C1 */ - 0x00, /* C2 */ - 0x00, /* C3 */ - 0x00, /* C4 */ - 0x00, /* C5 */ - 0x00, /* C6 */ - 0x00, /* C7 */ - 0x00, /* C8 */ - 0x00, /* C9 */ - 0x00, /* CA */ - 0x00, /* CB */ - 0x00, /* CC */ - 0x00, /* CD */ - 0x00, /* CE */ - 0x00, /* CF */ - 0x00, /* D0 */ - 0x00, /* D1 */ - 0x00, /* D2 */ - 0x00, /* D3 */ - 0x00, /* D4 */ - 0x00, /* D5 */ - 0x00, /* D6 */ - 0x00, /* D7 */ - 0x00, /* D8 */ - 0x00, /* D9 */ - 0x00, /* DA */ - 0x00, /* DB */ - 0x00, /* DC */ - 0x00, /* DD */ - 0x00, /* DE */ - 0x00, /* DF */ - 0x00, /* E0 */ - 0x00, /* E1 */ - 0x00, /* E2 */ - 0x00, /* E3 */ - 0x00, /* E4 */ - 0x00, /* E5 */ - 0x00, /* E6 */ - 0x00, /* E7 */ - 0x00, /* E8 */ - 0x00, /* E9 */ - 0x00, /* EA */ - 0x00, /* EB */ - 0x00, /* EC */ - 0x00, /* ED */ - 0x00, /* EE */ - 0x00, /* EF */ - 0x00, /* F0 */ - 0x00, /* F1 */ - 0x00, /* F2 */ - 0x00, /* F3 */ - 0x00, /* F4 */ - 0x00, /* F5 */ - 0x00, /* F6 */ - 0x00, /* F7 */ - 0x00, /* F8 */ - 0x00, /* F9 */ - 0x00, /* FA */ - 0x00, /* FB */ - 0x00, /* FC */ - 0x00, /* FD */ - 0x00, /* FE */ - 0x00, /* FF */ -}; - -static struct { - int readable; - int writable; -} max98095_access[M98095_REG_CNT] = { - { 0x00, 0x00 }, /* 00 */ - { 0xFF, 0x00 }, /* 01 */ - { 0xFF, 0x00 }, /* 02 */ - { 0xFF, 0x00 }, /* 03 */ - { 0xFF, 0x00 }, /* 04 */ - { 0xFF, 0x00 }, /* 05 */ - { 0xFF, 0x00 }, /* 06 */ - { 0xFF, 0x00 }, /* 07 */ - { 0xFF, 0x00 }, /* 08 */ - { 0xFF, 0x00 }, /* 09 */ - { 0xFF, 0x00 }, /* 0A */ - { 0xFF, 0x00 }, /* 0B */ - { 0xFF, 0x00 }, /* 0C */ - { 0xFF, 0x00 }, /* 0D */ - { 0xFF, 0x00 }, /* 0E */ - { 0xFF, 0x9F }, /* 0F */ - { 0xFF, 0xFF }, /* 10 */ - { 0xFF, 0xFF }, /* 11 */ - { 0xFF, 0xFF }, /* 12 */ - { 0xFF, 0xFF }, /* 13 */ - { 0xFF, 0xFF }, /* 14 */ - { 0xFF, 0xFF }, /* 15 */ - { 0xFF, 0xFF }, /* 16 */ - { 0xFF, 0xFF }, /* 17 */ - { 0xFF, 0xFF }, /* 18 */ - { 0xFF, 0xFF }, /* 19 */ - { 0xFF, 0xFF }, /* 1A */ - { 0xFF, 0xFF }, /* 1B */ - { 0xFF, 0xFF }, /* 1C */ - { 0xFF, 0xFF }, /* 1D */ - { 0xFF, 0x77 }, /* 1E */ - { 0xFF, 0x77 }, /* 1F */ - { 0xFF, 0x77 }, /* 20 */ - { 0xFF, 0x77 }, /* 21 */ - { 0xFF, 0x77 }, /* 22 */ - { 0xFF, 0x77 }, /* 23 */ - { 0xFF, 0xFF }, /* 24 */ - { 0xFF, 0x7F }, /* 25 */ - { 0xFF, 0x31 }, /* 26 */ - { 0xFF, 0xFF }, /* 27 */ - { 0xFF, 0xFF }, /* 28 */ - { 0xFF, 0xFF }, /* 29 */ - { 0xFF, 0xF7 }, /* 2A */ - { 0xFF, 0x2F }, /* 2B */ - { 0xFF, 0xEF }, /* 2C */ - { 0xFF, 0xFF }, /* 2D */ - { 0xFF, 0xFF }, /* 2E */ - { 0xFF, 0xFF }, /* 2F */ - { 0xFF, 0xFF }, /* 30 */ - { 0xFF, 0xFF }, /* 31 */ - { 0xFF, 0xFF }, /* 32 */ - { 0xFF, 0xFF }, /* 33 */ - { 0xFF, 0xF7 }, /* 34 */ - { 0xFF, 0x2F }, /* 35 */ - { 0xFF, 0xCF }, /* 36 */ - { 0xFF, 0xFF }, /* 37 */ - { 0xFF, 0xFF }, /* 38 */ - { 0xFF, 0xFF }, /* 39 */ - { 0xFF, 0xFF }, /* 3A */ - { 0xFF, 0xFF }, /* 3B */ - { 0xFF, 0xFF }, /* 3C */ - { 0xFF, 0xFF }, /* 3D */ - { 0xFF, 0xF7 }, /* 3E */ - { 0xFF, 0x2F }, /* 3F */ - { 0xFF, 0xCF }, /* 40 */ - { 0xFF, 0xFF }, /* 41 */ - { 0xFF, 0x77 }, /* 42 */ - { 0xFF, 0xFF }, /* 43 */ - { 0xFF, 0xFF }, /* 44 */ - { 0xFF, 0xFF }, /* 45 */ - { 0xFF, 0xFF }, /* 46 */ - { 0xFF, 0xFF }, /* 47 */ - { 0xFF, 0xFF }, /* 48 */ - { 0xFF, 0x0F }, /* 49 */ - { 0xFF, 0xFF }, /* 4A */ - { 0xFF, 0xFF }, /* 4B */ - { 0xFF, 0x3F }, /* 4C */ - { 0xFF, 0x3F }, /* 4D */ - { 0xFF, 0x3F }, /* 4E */ - { 0xFF, 0xFF }, /* 4F */ - { 0xFF, 0x7F }, /* 50 */ - { 0xFF, 0x7F }, /* 51 */ - { 0xFF, 0x0F }, /* 52 */ - { 0xFF, 0x3F }, /* 53 */ - { 0xFF, 0x3F }, /* 54 */ - { 0xFF, 0x3F }, /* 55 */ - { 0xFF, 0xFF }, /* 56 */ - { 0xFF, 0xFF }, /* 57 */ - { 0xFF, 0xBF }, /* 58 */ - { 0xFF, 0x1F }, /* 59 */ - { 0xFF, 0xBF }, /* 5A */ - { 0xFF, 0x1F }, /* 5B */ - { 0xFF, 0xBF }, /* 5C */ - { 0xFF, 0x3F }, /* 5D */ - { 0xFF, 0x3F }, /* 5E */ - { 0xFF, 0x7F }, /* 5F */ - { 0xFF, 0x7F }, /* 60 */ - { 0xFF, 0x47 }, /* 61 */ - { 0xFF, 0x9F }, /* 62 */ - { 0xFF, 0x9F }, /* 63 */ - { 0xFF, 0x9F }, /* 64 */ - { 0xFF, 0x9F }, /* 65 */ - { 0xFF, 0x9F }, /* 66 */ - { 0xFF, 0xBF }, /* 67 */ - { 0xFF, 0xBF }, /* 68 */ - { 0xFF, 0xFF }, /* 69 */ - { 0xFF, 0xFF }, /* 6A */ - { 0xFF, 0x7F }, /* 6B */ - { 0xFF, 0xF7 }, /* 6C */ - { 0xFF, 0xFF }, /* 6D */ - { 0xFF, 0xFF }, /* 6E */ - { 0xFF, 0x1F }, /* 6F */ - { 0xFF, 0xF7 }, /* 70 */ - { 0xFF, 0xFF }, /* 71 */ - { 0xFF, 0xFF }, /* 72 */ - { 0xFF, 0x1F }, /* 73 */ - { 0xFF, 0xF7 }, /* 74 */ - { 0xFF, 0xFF }, /* 75 */ - { 0xFF, 0xFF }, /* 76 */ - { 0xFF, 0x1F }, /* 77 */ - { 0xFF, 0xF7 }, /* 78 */ - { 0xFF, 0xFF }, /* 79 */ - { 0xFF, 0xFF }, /* 7A */ - { 0xFF, 0x1F }, /* 7B */ - { 0xFF, 0xF7 }, /* 7C */ - { 0xFF, 0xFF }, /* 7D */ - { 0xFF, 0xFF }, /* 7E */ - { 0xFF, 0x1F }, /* 7F */ - { 0xFF, 0xF7 }, /* 80 */ - { 0xFF, 0xFF }, /* 81 */ - { 0xFF, 0xFF }, /* 82 */ - { 0xFF, 0x1F }, /* 83 */ - { 0xFF, 0x7F }, /* 84 */ - { 0xFF, 0x0F }, /* 85 */ - { 0xFF, 0xD8 }, /* 86 */ - { 0xFF, 0xFF }, /* 87 */ - { 0xFF, 0xEF }, /* 88 */ - { 0xFF, 0xFE }, /* 89 */ - { 0xFF, 0xFE }, /* 8A */ - { 0xFF, 0xFF }, /* 8B */ - { 0xFF, 0xFF }, /* 8C */ - { 0xFF, 0x3F }, /* 8D */ - { 0xFF, 0xFF }, /* 8E */ - { 0xFF, 0x3F }, /* 8F */ - { 0xFF, 0x8F }, /* 90 */ - { 0xFF, 0xFF }, /* 91 */ - { 0xFF, 0x3F }, /* 92 */ - { 0xFF, 0xFF }, /* 93 */ - { 0xFF, 0xFF }, /* 94 */ - { 0xFF, 0x0F }, /* 95 */ - { 0xFF, 0x3F }, /* 96 */ - { 0xFF, 0x8C }, /* 97 */ - { 0x00, 0x00 }, /* 98 */ - { 0x00, 0x00 }, /* 99 */ - { 0x00, 0x00 }, /* 9A */ - { 0x00, 0x00 }, /* 9B */ - { 0x00, 0x00 }, /* 9C */ - { 0x00, 0x00 }, /* 9D */ - { 0x00, 0x00 }, /* 9E */ - { 0x00, 0x00 }, /* 9F */ - { 0x00, 0x00 }, /* A0 */ - { 0x00, 0x00 }, /* A1 */ - { 0x00, 0x00 }, /* A2 */ - { 0x00, 0x00 }, /* A3 */ - { 0x00, 0x00 }, /* A4 */ - { 0x00, 0x00 }, /* A5 */ - { 0x00, 0x00 }, /* A6 */ - { 0x00, 0x00 }, /* A7 */ - { 0x00, 0x00 }, /* A8 */ - { 0x00, 0x00 }, /* A9 */ - { 0x00, 0x00 }, /* AA */ - { 0x00, 0x00 }, /* AB */ - { 0x00, 0x00 }, /* AC */ - { 0x00, 0x00 }, /* AD */ - { 0x00, 0x00 }, /* AE */ - { 0x00, 0x00 }, /* AF */ - { 0x00, 0x00 }, /* B0 */ - { 0x00, 0x00 }, /* B1 */ - { 0x00, 0x00 }, /* B2 */ - { 0x00, 0x00 }, /* B3 */ - { 0x00, 0x00 }, /* B4 */ - { 0x00, 0x00 }, /* B5 */ - { 0x00, 0x00 }, /* B6 */ - { 0x00, 0x00 }, /* B7 */ - { 0x00, 0x00 }, /* B8 */ - { 0x00, 0x00 }, /* B9 */ - { 0x00, 0x00 }, /* BA */ - { 0x00, 0x00 }, /* BB */ - { 0x00, 0x00 }, /* BC */ - { 0x00, 0x00 }, /* BD */ - { 0x00, 0x00 }, /* BE */ - { 0x00, 0x00 }, /* BF */ - { 0x00, 0x00 }, /* C0 */ - { 0x00, 0x00 }, /* C1 */ - { 0x00, 0x00 }, /* C2 */ - { 0x00, 0x00 }, /* C3 */ - { 0x00, 0x00 }, /* C4 */ - { 0x00, 0x00 }, /* C5 */ - { 0x00, 0x00 }, /* C6 */ - { 0x00, 0x00 }, /* C7 */ - { 0x00, 0x00 }, /* C8 */ - { 0x00, 0x00 }, /* C9 */ - { 0x00, 0x00 }, /* CA */ - { 0x00, 0x00 }, /* CB */ - { 0x00, 0x00 }, /* CC */ - { 0x00, 0x00 }, /* CD */ - { 0x00, 0x00 }, /* CE */ - { 0x00, 0x00 }, /* CF */ - { 0x00, 0x00 }, /* D0 */ - { 0x00, 0x00 }, /* D1 */ - { 0x00, 0x00 }, /* D2 */ - { 0x00, 0x00 }, /* D3 */ - { 0x00, 0x00 }, /* D4 */ - { 0x00, 0x00 }, /* D5 */ - { 0x00, 0x00 }, /* D6 */ - { 0x00, 0x00 }, /* D7 */ - { 0x00, 0x00 }, /* D8 */ - { 0x00, 0x00 }, /* D9 */ - { 0x00, 0x00 }, /* DA */ - { 0x00, 0x00 }, /* DB */ - { 0x00, 0x00 }, /* DC */ - { 0x00, 0x00 }, /* DD */ - { 0x00, 0x00 }, /* DE */ - { 0x00, 0x00 }, /* DF */ - { 0x00, 0x00 }, /* E0 */ - { 0x00, 0x00 }, /* E1 */ - { 0x00, 0x00 }, /* E2 */ - { 0x00, 0x00 }, /* E3 */ - { 0x00, 0x00 }, /* E4 */ - { 0x00, 0x00 }, /* E5 */ - { 0x00, 0x00 }, /* E6 */ - { 0x00, 0x00 }, /* E7 */ - { 0x00, 0x00 }, /* E8 */ - { 0x00, 0x00 }, /* E9 */ - { 0x00, 0x00 }, /* EA */ - { 0x00, 0x00 }, /* EB */ - { 0x00, 0x00 }, /* EC */ - { 0x00, 0x00 }, /* ED */ - { 0x00, 0x00 }, /* EE */ - { 0x00, 0x00 }, /* EF */ - { 0x00, 0x00 }, /* F0 */ - { 0x00, 0x00 }, /* F1 */ - { 0x00, 0x00 }, /* F2 */ - { 0x00, 0x00 }, /* F3 */ - { 0x00, 0x00 }, /* F4 */ - { 0x00, 0x00 }, /* F5 */ - { 0x00, 0x00 }, /* F6 */ - { 0x00, 0x00 }, /* F7 */ - { 0x00, 0x00 }, /* F8 */ - { 0x00, 0x00 }, /* F9 */ - { 0x00, 0x00 }, /* FA */ - { 0x00, 0x00 }, /* FB */ - { 0x00, 0x00 }, /* FC */ - { 0x00, 0x00 }, /* FD */ - { 0x00, 0x00 }, /* FE */ - { 0xFF, 0x00 }, /* FF */ -}; - -static int max98095_readable(struct snd_soc_codec *codec, unsigned int reg) -{ - if (reg >= M98095_REG_CNT) - return 0; - return max98095_access[reg].readable != 0; -} - -static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg) -{ - if (reg > M98095_REG_MAX_CACHED) - return 1; - - switch (reg) { - case M98095_000_HOST_DATA: - case M98095_001_HOST_INT_STS: - case M98095_002_HOST_RSP_STS: - case M98095_003_HOST_CMD_STS: - case M98095_004_CODEC_STS: - case M98095_005_DAI1_ALC_STS: - case M98095_006_DAI2_ALC_STS: - case M98095_007_JACK_AUTO_STS: - case M98095_008_JACK_MANUAL_STS: - case M98095_009_JACK_VBAT_STS: - case M98095_00A_ACC_ADC_STS: - case M98095_00B_MIC_NG_AGC_STS: - case M98095_00C_SPK_L_VOLT_STS: - case M98095_00D_SPK_R_VOLT_STS: - case M98095_00E_TEMP_SENSOR_STS: - return 1; - } - - return 0; -} - -/* - * Filter coefficients are in a separate register segment - * and they share the address space of the normal registers. - * The coefficient registers do not need or share the cache. - */ -static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - int ret; - - codec->cache_bypass = 1; - ret = snd_soc_write(codec, reg, value); - codec->cache_bypass = 0; - - return ret ? -EIO : 0; -} - -/* - * Load equalizer DSP coefficient configurations registers - */ -static void m98095_eq_band(struct snd_soc_codec *codec, unsigned int dai, - unsigned int band, u16 *coefs) -{ - unsigned int eq_reg; - unsigned int i; - - BUG_ON(band > 4); - BUG_ON(dai > 1); - - /* Load the base register address */ - eq_reg = dai ? M98095_142_DAI2_EQ_BASE : M98095_110_DAI1_EQ_BASE; - - /* Add the band address offset, note adjustment for word address */ - eq_reg += band * (M98095_COEFS_PER_BAND << 1); - - /* Step through the registers and coefs */ - for (i = 0; i < M98095_COEFS_PER_BAND; i++) { - max98095_hw_write(codec, eq_reg++, M98095_BYTE1(coefs[i])); - max98095_hw_write(codec, eq_reg++, M98095_BYTE0(coefs[i])); - } -} - -/* - * Load biquad filter coefficient configurations registers - */ -static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai, - unsigned int band, u16 *coefs) -{ - unsigned int bq_reg; - unsigned int i; - - BUG_ON(band > 1); - BUG_ON(dai > 1); - - /* Load the base register address */ - bq_reg = dai ? M98095_17E_DAI2_BQ_BASE : M98095_174_DAI1_BQ_BASE; - - /* Add the band address offset, note adjustment for word address */ - bq_reg += band * (M98095_COEFS_PER_BAND << 1); - - /* Step through the registers and coefs */ - for (i = 0; i < M98095_COEFS_PER_BAND; i++) { - max98095_hw_write(codec, bq_reg++, M98095_BYTE1(coefs[i])); - max98095_hw_write(codec, bq_reg++, M98095_BYTE0(coefs[i])); - } -} - -static const char * const max98095_fltr_mode[] = { "Voice", "Music" }; -static const struct soc_enum max98095_dai1_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 7, 2, max98095_fltr_mode), -}; -static const struct soc_enum max98095_dai2_filter_mode_enum[] = { - SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 7, 2, max98095_fltr_mode), -}; - -static const char * const max98095_extmic_text[] = { "None", "MIC1", "MIC2" }; - -static const struct soc_enum max98095_extmic_enum = - SOC_ENUM_SINGLE(M98095_087_CFG_MIC, 0, 3, max98095_extmic_text); - -static const struct snd_kcontrol_new max98095_extmic_mux = - SOC_DAPM_ENUM("External MIC Mux", max98095_extmic_enum); - -static const char * const max98095_linein_text[] = { "INA", "INB" }; - -static const struct soc_enum max98095_linein_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 6, 2, max98095_linein_text); - -static const struct snd_kcontrol_new max98095_linein_mux = - SOC_DAPM_ENUM("Linein Input Mux", max98095_linein_enum); - -static const char * const max98095_line_mode_text[] = { - "Stereo", "Differential"}; - -static const struct soc_enum max98095_linein_mode_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 7, 2, max98095_line_mode_text); - -static const struct soc_enum max98095_lineout_mode_enum = - SOC_ENUM_SINGLE(M98095_086_CFG_LINE, 4, 2, max98095_line_mode_text); - -static const char * const max98095_dai_fltr[] = { - "Off", "Elliptical-HPF-16k", "Butterworth-HPF-16k", - "Elliptical-HPF-8k", "Butterworth-HPF-8k", "Butterworth-HPF-Fs/240"}; -static const struct soc_enum max98095_dai1_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_02E_DAI1_FILTERS, 0, 6, max98095_dai_fltr), -}; -static const struct soc_enum max98095_dai2_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_038_DAI2_FILTERS, 0, 6, max98095_dai_fltr), -}; -static const struct soc_enum max98095_dai3_dac_filter_enum[] = { - SOC_ENUM_SINGLE(M98095_042_DAI3_FILTERS, 0, 6, max98095_dai_fltr), -}; - -static int max98095_mic1pre_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - unsigned int sel = ucontrol->value.integer.value[0]; - - max98095->mic1pre = sel; - snd_soc_update_bits(codec, M98095_05F_LVL_MIC1, M98095_MICPRE_MASK, - (1+sel)<value.integer.value[0] = max98095->mic1pre; - return 0; -} - -static int max98095_mic2pre_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - unsigned int sel = ucontrol->value.integer.value[0]; - - max98095->mic2pre = sel; - snd_soc_update_bits(codec, M98095_060_LVL_MIC2, M98095_MICPRE_MASK, - (1+sel)<value.integer.value[0] = max98095->mic2pre; - return 0; -} - -static const unsigned int max98095_micboost_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), - 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), -}; - -static const DECLARE_TLV_DB_SCALE(max98095_mic_tlv, 0, 100, 0); -static const DECLARE_TLV_DB_SCALE(max98095_adc_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(max98095_adcboost_tlv, 0, 600, 0); - -static const unsigned int max98095_hp_tlv[] = { - TLV_DB_RANGE_HEAD(5), - 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), - 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), - 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), - 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), - 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0), -}; - -static const unsigned int max98095_spk_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 10, TLV_DB_SCALE_ITEM(-5900, 400, 0), - 11, 18, TLV_DB_SCALE_ITEM(-1700, 200, 0), - 19, 27, TLV_DB_SCALE_ITEM(-200, 100, 0), - 28, 39, TLV_DB_SCALE_ITEM(650, 50, 0), -}; - -static const unsigned int max98095_rcv_lout_tlv[] = { - TLV_DB_RANGE_HEAD(5), - 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), - 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), - 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), - 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), - 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0), -}; - -static const unsigned int max98095_lin_tlv[] = { - TLV_DB_RANGE_HEAD(3), - 0, 2, TLV_DB_SCALE_ITEM(-600, 300, 0), - 3, 3, TLV_DB_SCALE_ITEM(300, 1100, 0), - 4, 5, TLV_DB_SCALE_ITEM(1400, 600, 0), -}; - -static const struct snd_kcontrol_new max98095_snd_controls[] = { - - SOC_DOUBLE_R_TLV("Headphone Volume", M98095_064_LVL_HP_L, - M98095_065_LVL_HP_R, 0, 31, 0, max98095_hp_tlv), - - SOC_DOUBLE_R_TLV("Speaker Volume", M98095_067_LVL_SPK_L, - M98095_068_LVL_SPK_R, 0, 39, 0, max98095_spk_tlv), - - SOC_SINGLE_TLV("Receiver Volume", M98095_066_LVL_RCV, - 0, 31, 0, max98095_rcv_lout_tlv), - - SOC_DOUBLE_R_TLV("Lineout Volume", M98095_062_LVL_LINEOUT1, - M98095_063_LVL_LINEOUT2, 0, 31, 0, max98095_rcv_lout_tlv), - - SOC_DOUBLE_R("Headphone Switch", M98095_064_LVL_HP_L, - M98095_065_LVL_HP_R, 7, 1, 1), - - SOC_DOUBLE_R("Speaker Switch", M98095_067_LVL_SPK_L, - M98095_068_LVL_SPK_R, 7, 1, 1), - - SOC_SINGLE("Receiver Switch", M98095_066_LVL_RCV, 7, 1, 1), - - SOC_DOUBLE_R("Lineout Switch", M98095_062_LVL_LINEOUT1, - M98095_063_LVL_LINEOUT2, 7, 1, 1), - - SOC_SINGLE_TLV("MIC1 Volume", M98095_05F_LVL_MIC1, 0, 20, 1, - max98095_mic_tlv), - - SOC_SINGLE_TLV("MIC2 Volume", M98095_060_LVL_MIC2, 0, 20, 1, - max98095_mic_tlv), - - SOC_SINGLE_EXT_TLV("MIC1 Boost Volume", - M98095_05F_LVL_MIC1, 5, 2, 0, - max98095_mic1pre_get, max98095_mic1pre_set, - max98095_micboost_tlv), - SOC_SINGLE_EXT_TLV("MIC2 Boost Volume", - M98095_060_LVL_MIC2, 5, 2, 0, - max98095_mic2pre_get, max98095_mic2pre_set, - max98095_micboost_tlv), - - SOC_SINGLE_TLV("Linein Volume", M98095_061_LVL_LINEIN, 0, 5, 1, - max98095_lin_tlv), - - SOC_SINGLE_TLV("ADCL Volume", M98095_05D_LVL_ADC_L, 0, 15, 1, - max98095_adc_tlv), - SOC_SINGLE_TLV("ADCR Volume", M98095_05E_LVL_ADC_R, 0, 15, 1, - max98095_adc_tlv), - - SOC_SINGLE_TLV("ADCL Boost Volume", M98095_05D_LVL_ADC_L, 4, 3, 0, - max98095_adcboost_tlv), - SOC_SINGLE_TLV("ADCR Boost Volume", M98095_05E_LVL_ADC_R, 4, 3, 0, - max98095_adcboost_tlv), - - SOC_SINGLE("EQ1 Switch", M98095_088_CFG_LEVEL, 0, 1, 0), - SOC_SINGLE("EQ2 Switch", M98095_088_CFG_LEVEL, 1, 1, 0), - - SOC_SINGLE("Biquad1 Switch", M98095_088_CFG_LEVEL, 2, 1, 0), - SOC_SINGLE("Biquad2 Switch", M98095_088_CFG_LEVEL, 3, 1, 0), - - SOC_ENUM("DAI1 Filter Mode", max98095_dai1_filter_mode_enum), - SOC_ENUM("DAI2 Filter Mode", max98095_dai2_filter_mode_enum), - SOC_ENUM("DAI1 DAC Filter", max98095_dai1_dac_filter_enum), - SOC_ENUM("DAI2 DAC Filter", max98095_dai2_dac_filter_enum), - SOC_ENUM("DAI3 DAC Filter", max98095_dai3_dac_filter_enum), - - SOC_ENUM("Linein Mode", max98095_linein_mode_enum), - SOC_ENUM("Lineout Mode", max98095_lineout_mode_enum), -}; - -/* Left speaker mixer switch */ -static const struct snd_kcontrol_new max98095_left_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_050_MIX_SPK_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_050_MIX_SPK_LEFT, 6, 1, 0), - SOC_DAPM_SINGLE("Mono DAC2 Switch", M98095_050_MIX_SPK_LEFT, 3, 1, 0), - SOC_DAPM_SINGLE("Mono DAC3 Switch", M98095_050_MIX_SPK_LEFT, 3, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98095_050_MIX_SPK_LEFT, 4, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_050_MIX_SPK_LEFT, 5, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_050_MIX_SPK_LEFT, 1, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_050_MIX_SPK_LEFT, 2, 1, 0), -}; - -/* Right speaker mixer switch */ -static const struct snd_kcontrol_new max98095_right_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_051_MIX_SPK_RIGHT, 6, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_051_MIX_SPK_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("Mono DAC2 Switch", M98095_051_MIX_SPK_RIGHT, 3, 1, 0), - SOC_DAPM_SINGLE("Mono DAC3 Switch", M98095_051_MIX_SPK_RIGHT, 3, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98095_051_MIX_SPK_RIGHT, 5, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_051_MIX_SPK_RIGHT, 4, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_051_MIX_SPK_RIGHT, 1, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_051_MIX_SPK_RIGHT, 2, 1, 0), -}; - -/* Left headphone mixer switch */ -static const struct snd_kcontrol_new max98095_left_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04C_MIX_HP_LEFT, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04C_MIX_HP_LEFT, 5, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98095_04C_MIX_HP_LEFT, 3, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_04C_MIX_HP_LEFT, 4, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_04C_MIX_HP_LEFT, 1, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_04C_MIX_HP_LEFT, 2, 1, 0), -}; - -/* Right headphone mixer switch */ -static const struct snd_kcontrol_new max98095_right_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04D_MIX_HP_RIGHT, 5, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04D_MIX_HP_RIGHT, 0, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98095_04D_MIX_HP_RIGHT, 3, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_04D_MIX_HP_RIGHT, 4, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_04D_MIX_HP_RIGHT, 1, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_04D_MIX_HP_RIGHT, 2, 1, 0), -}; - -/* Receiver earpiece mixer switch */ -static const struct snd_kcontrol_new max98095_mono_rcv_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_04F_MIX_RCV, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_04F_MIX_RCV, 5, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98095_04F_MIX_RCV, 3, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_04F_MIX_RCV, 4, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_04F_MIX_RCV, 1, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_04F_MIX_RCV, 2, 1, 0), -}; - -/* Left lineout mixer switch */ -static const struct snd_kcontrol_new max98095_left_lineout_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_053_MIX_LINEOUT1, 5, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_053_MIX_LINEOUT1, 0, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98095_053_MIX_LINEOUT1, 3, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_053_MIX_LINEOUT1, 4, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_053_MIX_LINEOUT1, 1, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_053_MIX_LINEOUT1, 2, 1, 0), -}; - -/* Right lineout mixer switch */ -static const struct snd_kcontrol_new max98095_right_lineout_mixer_controls[] = { - SOC_DAPM_SINGLE("Left DAC1 Switch", M98095_054_MIX_LINEOUT2, 0, 1, 0), - SOC_DAPM_SINGLE("Right DAC1 Switch", M98095_054_MIX_LINEOUT2, 5, 1, 0), - SOC_DAPM_SINGLE("MIC1 Switch", M98095_054_MIX_LINEOUT2, 3, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_054_MIX_LINEOUT2, 4, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_054_MIX_LINEOUT2, 1, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_054_MIX_LINEOUT2, 2, 1, 0), -}; - -/* Left ADC mixer switch */ -static const struct snd_kcontrol_new max98095_left_ADC_mixer_controls[] = { - SOC_DAPM_SINGLE("MIC1 Switch", M98095_04A_MIX_ADC_LEFT, 7, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_04A_MIX_ADC_LEFT, 6, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_04A_MIX_ADC_LEFT, 3, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_04A_MIX_ADC_LEFT, 2, 1, 0), -}; - -/* Right ADC mixer switch */ -static const struct snd_kcontrol_new max98095_right_ADC_mixer_controls[] = { - SOC_DAPM_SINGLE("MIC1 Switch", M98095_04B_MIX_ADC_RIGHT, 7, 1, 0), - SOC_DAPM_SINGLE("MIC2 Switch", M98095_04B_MIX_ADC_RIGHT, 6, 1, 0), - SOC_DAPM_SINGLE("IN1 Switch", M98095_04B_MIX_ADC_RIGHT, 3, 1, 0), - SOC_DAPM_SINGLE("IN2 Switch", M98095_04B_MIX_ADC_RIGHT, 2, 1, 0), -}; - -static int max98095_mic_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - if (w->reg == M98095_05F_LVL_MIC1) { - snd_soc_update_bits(codec, w->reg, M98095_MICPRE_MASK, - (1+max98095->mic1pre)<reg, M98095_MICPRE_MASK, - (1+max98095->mic2pre)<reg, M98095_MICPRE_MASK, 0); - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * The line inputs are stereo inputs with the left and right - * channels sharing a common PGA power control signal. - */ -static int max98095_line_pga(struct snd_soc_dapm_widget *w, - int event, u8 channel) -{ - struct snd_soc_codec *codec = w->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - u8 *state; - - BUG_ON(!((channel == 1) || (channel == 2))); - - state = &max98095->lin_state; - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - *state |= channel; - snd_soc_update_bits(codec, w->reg, - (1 << w->shift), (1 << w->shift)); - break; - case SND_SOC_DAPM_POST_PMD: - *state &= ~channel; - if (*state == 0) { - snd_soc_update_bits(codec, w->reg, - (1 << w->shift), 0); - } - break; - default: - return -EINVAL; - } - - return 0; -} - -static int max98095_pga_in1_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - return max98095_line_pga(w, event, 1); -} - -static int max98095_pga_in2_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - return max98095_line_pga(w, event, 2); -} - -/* - * The stereo line out mixer outputs to two stereo line outs. - * The 2nd pair has a separate set of enables. - */ -static int max98095_lineout_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(codec, w->reg, - (1 << (w->shift+2)), (1 << (w->shift+2))); - break; - case SND_SOC_DAPM_POST_PMD: - snd_soc_update_bits(codec, w->reg, - (1 << (w->shift+2)), 0); - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct snd_soc_dapm_widget max98095_dapm_widgets[] = { - - SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98095_090_PWR_EN_IN, 0, 0), - SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98095_090_PWR_EN_IN, 1, 0), - - SND_SOC_DAPM_DAC("DACL1", "HiFi Playback", - M98095_091_PWR_EN_OUT, 0, 0), - SND_SOC_DAPM_DAC("DACR1", "HiFi Playback", - M98095_091_PWR_EN_OUT, 1, 0), - SND_SOC_DAPM_DAC("DACM2", "Aux Playback", - M98095_091_PWR_EN_OUT, 2, 0), - SND_SOC_DAPM_DAC("DACM3", "Voice Playback", - M98095_091_PWR_EN_OUT, 2, 0), - - SND_SOC_DAPM_PGA("HP Left Out", M98095_091_PWR_EN_OUT, - 6, 0, NULL, 0), - SND_SOC_DAPM_PGA("HP Right Out", M98095_091_PWR_EN_OUT, - 7, 0, NULL, 0), - - SND_SOC_DAPM_PGA("SPK Left Out", M98095_091_PWR_EN_OUT, - 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPK Right Out", M98095_091_PWR_EN_OUT, - 5, 0, NULL, 0), - - SND_SOC_DAPM_PGA("RCV Mono Out", M98095_091_PWR_EN_OUT, - 3, 0, NULL, 0), - - SND_SOC_DAPM_PGA_E("LINE Left Out", M98095_092_PWR_EN_OUT, - 0, 0, NULL, 0, max98095_lineout_event, SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("LINE Right Out", M98095_092_PWR_EN_OUT, - 1, 0, NULL, 0, max98095_lineout_event, SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0, - &max98095_extmic_mux), - - SND_SOC_DAPM_MUX("Linein Mux", SND_SOC_NOPM, 0, 0, - &max98095_linein_mux), - - SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0, - &max98095_left_hp_mixer_controls[0], - ARRAY_SIZE(max98095_left_hp_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right Headphone Mixer", SND_SOC_NOPM, 0, 0, - &max98095_right_hp_mixer_controls[0], - ARRAY_SIZE(max98095_right_hp_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left Speaker Mixer", SND_SOC_NOPM, 0, 0, - &max98095_left_speaker_mixer_controls[0], - ARRAY_SIZE(max98095_left_speaker_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right Speaker Mixer", SND_SOC_NOPM, 0, 0, - &max98095_right_speaker_mixer_controls[0], - ARRAY_SIZE(max98095_right_speaker_mixer_controls)), - - SND_SOC_DAPM_MIXER("Receiver Mixer", SND_SOC_NOPM, 0, 0, - &max98095_mono_rcv_mixer_controls[0], - ARRAY_SIZE(max98095_mono_rcv_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left Lineout Mixer", SND_SOC_NOPM, 0, 0, - &max98095_left_lineout_mixer_controls[0], - ARRAY_SIZE(max98095_left_lineout_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right Lineout Mixer", SND_SOC_NOPM, 0, 0, - &max98095_right_lineout_mixer_controls[0], - ARRAY_SIZE(max98095_right_lineout_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0, - &max98095_left_ADC_mixer_controls[0], - ARRAY_SIZE(max98095_left_ADC_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0, - &max98095_right_ADC_mixer_controls[0], - ARRAY_SIZE(max98095_right_ADC_mixer_controls)), - - SND_SOC_DAPM_PGA_E("MIC1 Input", M98095_05F_LVL_MIC1, - 5, 0, NULL, 0, max98095_mic_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("MIC2 Input", M98095_060_LVL_MIC2, - 5, 0, NULL, 0, max98095_mic_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("IN1 Input", M98095_090_PWR_EN_IN, - 7, 0, NULL, 0, max98095_pga_in1_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_PGA_E("IN2 Input", M98095_090_PWR_EN_IN, - 7, 0, NULL, 0, max98095_pga_in2_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_MICBIAS("MICBIAS1", M98095_090_PWR_EN_IN, 2, 0), - SND_SOC_DAPM_MICBIAS("MICBIAS2", M98095_090_PWR_EN_IN, 3, 0), - - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - SND_SOC_DAPM_OUTPUT("SPKL"), - SND_SOC_DAPM_OUTPUT("SPKR"), - SND_SOC_DAPM_OUTPUT("RCV"), - SND_SOC_DAPM_OUTPUT("OUT1"), - SND_SOC_DAPM_OUTPUT("OUT2"), - SND_SOC_DAPM_OUTPUT("OUT3"), - SND_SOC_DAPM_OUTPUT("OUT4"), - - SND_SOC_DAPM_INPUT("MIC1"), - SND_SOC_DAPM_INPUT("MIC2"), - SND_SOC_DAPM_INPUT("INA1"), - SND_SOC_DAPM_INPUT("INA2"), - SND_SOC_DAPM_INPUT("INB1"), - SND_SOC_DAPM_INPUT("INB2"), -}; - -static const struct snd_soc_dapm_route max98095_audio_map[] = { - /* Left headphone output mixer */ - {"Left Headphone Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left Headphone Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left Headphone Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Left Headphone Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Left Headphone Mixer", "IN1 Switch", "IN1 Input"}, - {"Left Headphone Mixer", "IN2 Switch", "IN2 Input"}, - - /* Right headphone output mixer */ - {"Right Headphone Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right Headphone Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right Headphone Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Right Headphone Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Right Headphone Mixer", "IN1 Switch", "IN1 Input"}, - {"Right Headphone Mixer", "IN2 Switch", "IN2 Input"}, - - /* Left speaker output mixer */ - {"Left Speaker Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left Speaker Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left Speaker Mixer", "Mono DAC2 Switch", "DACM2"}, - {"Left Speaker Mixer", "Mono DAC3 Switch", "DACM3"}, - {"Left Speaker Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Left Speaker Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Left Speaker Mixer", "IN1 Switch", "IN1 Input"}, - {"Left Speaker Mixer", "IN2 Switch", "IN2 Input"}, - - /* Right speaker output mixer */ - {"Right Speaker Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right Speaker Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right Speaker Mixer", "Mono DAC2 Switch", "DACM2"}, - {"Right Speaker Mixer", "Mono DAC3 Switch", "DACM3"}, - {"Right Speaker Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Right Speaker Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Right Speaker Mixer", "IN1 Switch", "IN1 Input"}, - {"Right Speaker Mixer", "IN2 Switch", "IN2 Input"}, - - /* Earpiece/Receiver output mixer */ - {"Receiver Mixer", "Left DAC1 Switch", "DACL1"}, - {"Receiver Mixer", "Right DAC1 Switch", "DACR1"}, - {"Receiver Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Receiver Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Receiver Mixer", "IN1 Switch", "IN1 Input"}, - {"Receiver Mixer", "IN2 Switch", "IN2 Input"}, - - /* Left Lineout output mixer */ - {"Left Lineout Mixer", "Left DAC1 Switch", "DACL1"}, - {"Left Lineout Mixer", "Right DAC1 Switch", "DACR1"}, - {"Left Lineout Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Left Lineout Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Left Lineout Mixer", "IN1 Switch", "IN1 Input"}, - {"Left Lineout Mixer", "IN2 Switch", "IN2 Input"}, - - /* Right lineout output mixer */ - {"Right Lineout Mixer", "Left DAC1 Switch", "DACL1"}, - {"Right Lineout Mixer", "Right DAC1 Switch", "DACR1"}, - {"Right Lineout Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Right Lineout Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Right Lineout Mixer", "IN1 Switch", "IN1 Input"}, - {"Right Lineout Mixer", "IN2 Switch", "IN2 Input"}, - - {"HP Left Out", NULL, "Left Headphone Mixer"}, - {"HP Right Out", NULL, "Right Headphone Mixer"}, - {"SPK Left Out", NULL, "Left Speaker Mixer"}, - {"SPK Right Out", NULL, "Right Speaker Mixer"}, - {"RCV Mono Out", NULL, "Receiver Mixer"}, - {"LINE Left Out", NULL, "Left Lineout Mixer"}, - {"LINE Right Out", NULL, "Right Lineout Mixer"}, - - {"HPL", NULL, "HP Left Out"}, - {"HPR", NULL, "HP Right Out"}, - {"SPKL", NULL, "SPK Left Out"}, - {"SPKR", NULL, "SPK Right Out"}, - {"RCV", NULL, "RCV Mono Out"}, - {"OUT1", NULL, "LINE Left Out"}, - {"OUT2", NULL, "LINE Right Out"}, - {"OUT3", NULL, "LINE Left Out"}, - {"OUT4", NULL, "LINE Right Out"}, - - /* Left ADC input mixer */ - {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Left ADC Mixer", "IN1 Switch", "IN1 Input"}, - {"Left ADC Mixer", "IN2 Switch", "IN2 Input"}, - - /* Right ADC input mixer */ - {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"}, - {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"}, - {"Right ADC Mixer", "IN1 Switch", "IN1 Input"}, - {"Right ADC Mixer", "IN2 Switch", "IN2 Input"}, - - /* Inputs */ - {"ADCL", NULL, "Left ADC Mixer"}, - {"ADCR", NULL, "Right ADC Mixer"}, - - {"IN1 Input", NULL, "INA1"}, - {"IN2 Input", NULL, "INA2"}, - - {"MIC1 Input", NULL, "MIC1"}, - {"MIC2 Input", NULL, "MIC2"}, -}; - -static int max98095_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_add_codec_controls(codec, max98095_snd_controls, - ARRAY_SIZE(max98095_snd_controls)); - - return 0; -} - -/* codec mclk clock divider coefficients */ -static const struct { - u32 rate; - u8 sr; -} rate_table[] = { - {8000, 0x01}, - {11025, 0x02}, - {16000, 0x03}, - {22050, 0x04}, - {24000, 0x05}, - {32000, 0x06}, - {44100, 0x07}, - {48000, 0x08}, - {88200, 0x09}, - {96000, 0x0A}, -}; - -static int rate_value(int rate, u8 *value) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(rate_table); i++) { - if (rate_table[i].rate >= rate) { - *value = rate_table[i].sr; - return 0; - } - } - *value = rate_table[0].sr; - return -EINVAL; -} - -static int max98095_dai1_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_cdata *cdata; - unsigned long long ni; - unsigned int rate; - u8 regval; - - cdata = &max98095->dai[0]; - - rate = params_rate(params); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, - M98095_DAI_WS, 0); - break; - case SNDRV_PCM_FORMAT_S24_LE: - snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, - M98095_DAI_WS, M98095_DAI_WS); - break; - default: - return -EINVAL; - } - - if (rate_value(rate, ®val)) - return -EINVAL; - - snd_soc_update_bits(codec, M98095_027_DAI1_CLKMODE, - M98095_CLKMODE_MASK, regval); - cdata->rate = rate; - - /* Configure NI when operating as master */ - if (snd_soc_read(codec, M98095_02A_DAI1_FORMAT) & M98095_DAI_MAS) { - if (max98095->sysclk == 0) { - dev_err(codec->dev, "Invalid system clock frequency\n"); - return -EINVAL; - } - ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) - * (unsigned long long int)rate; - do_div(ni, (unsigned long long int)max98095->sysclk); - snd_soc_write(codec, M98095_028_DAI1_CLKCFG_HI, - (ni >> 8) & 0x7F); - snd_soc_write(codec, M98095_029_DAI1_CLKCFG_LO, - ni & 0xFF); - } - - /* Update sample rate mode */ - if (rate < 50000) - snd_soc_update_bits(codec, M98095_02E_DAI1_FILTERS, - M98095_DAI_DHF, 0); - else - snd_soc_update_bits(codec, M98095_02E_DAI1_FILTERS, - M98095_DAI_DHF, M98095_DAI_DHF); - - return 0; -} - -static int max98095_dai2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_cdata *cdata; - unsigned long long ni; - unsigned int rate; - u8 regval; - - cdata = &max98095->dai[1]; - - rate = params_rate(params); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, - M98095_DAI_WS, 0); - break; - case SNDRV_PCM_FORMAT_S24_LE: - snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, - M98095_DAI_WS, M98095_DAI_WS); - break; - default: - return -EINVAL; - } - - if (rate_value(rate, ®val)) - return -EINVAL; - - snd_soc_update_bits(codec, M98095_031_DAI2_CLKMODE, - M98095_CLKMODE_MASK, regval); - cdata->rate = rate; - - /* Configure NI when operating as master */ - if (snd_soc_read(codec, M98095_034_DAI2_FORMAT) & M98095_DAI_MAS) { - if (max98095->sysclk == 0) { - dev_err(codec->dev, "Invalid system clock frequency\n"); - return -EINVAL; - } - ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) - * (unsigned long long int)rate; - do_div(ni, (unsigned long long int)max98095->sysclk); - snd_soc_write(codec, M98095_032_DAI2_CLKCFG_HI, - (ni >> 8) & 0x7F); - snd_soc_write(codec, M98095_033_DAI2_CLKCFG_LO, - ni & 0xFF); - } - - /* Update sample rate mode */ - if (rate < 50000) - snd_soc_update_bits(codec, M98095_038_DAI2_FILTERS, - M98095_DAI_DHF, 0); - else - snd_soc_update_bits(codec, M98095_038_DAI2_FILTERS, - M98095_DAI_DHF, M98095_DAI_DHF); - - return 0; -} - -static int max98095_dai3_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_cdata *cdata; - unsigned long long ni; - unsigned int rate; - u8 regval; - - cdata = &max98095->dai[2]; - - rate = params_rate(params); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, - M98095_DAI_WS, 0); - break; - case SNDRV_PCM_FORMAT_S24_LE: - snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, - M98095_DAI_WS, M98095_DAI_WS); - break; - default: - return -EINVAL; - } - - if (rate_value(rate, ®val)) - return -EINVAL; - - snd_soc_update_bits(codec, M98095_03B_DAI3_CLKMODE, - M98095_CLKMODE_MASK, regval); - cdata->rate = rate; - - /* Configure NI when operating as master */ - if (snd_soc_read(codec, M98095_03E_DAI3_FORMAT) & M98095_DAI_MAS) { - if (max98095->sysclk == 0) { - dev_err(codec->dev, "Invalid system clock frequency\n"); - return -EINVAL; - } - ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) - * (unsigned long long int)rate; - do_div(ni, (unsigned long long int)max98095->sysclk); - snd_soc_write(codec, M98095_03C_DAI3_CLKCFG_HI, - (ni >> 8) & 0x7F); - snd_soc_write(codec, M98095_03D_DAI3_CLKCFG_LO, - ni & 0xFF); - } - - /* Update sample rate mode */ - if (rate < 50000) - snd_soc_update_bits(codec, M98095_042_DAI3_FILTERS, - M98095_DAI_DHF, 0); - else - snd_soc_update_bits(codec, M98095_042_DAI3_FILTERS, - M98095_DAI_DHF, M98095_DAI_DHF); - - return 0; -} - -static int max98095_dai_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - - /* Requested clock frequency is already setup */ - if (freq == max98095->sysclk) - return 0; - - /* Setup clocks for slave mode, and using the PLL - * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) - * 0x02 (when master clk is 20MHz to 40MHz).. - * 0x03 (when master clk is 40MHz to 60MHz).. - */ - if ((freq >= 10000000) && (freq < 20000000)) { - snd_soc_write(codec, M98095_026_SYS_CLK, 0x10); - } else if ((freq >= 20000000) && (freq < 40000000)) { - snd_soc_write(codec, M98095_026_SYS_CLK, 0x20); - } else if ((freq >= 40000000) && (freq < 60000000)) { - snd_soc_write(codec, M98095_026_SYS_CLK, 0x30); - } else { - dev_err(codec->dev, "Invalid master clock frequency\n"); - return -EINVAL; - } - - dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); - - max98095->sysclk = freq; - return 0; -} - -static int max98095_dai1_set_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_cdata *cdata; - u8 regval = 0; - - cdata = &max98095->dai[0]; - - if (fmt != cdata->fmt) { - cdata->fmt = fmt; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* Slave mode PLL */ - snd_soc_write(codec, M98095_028_DAI1_CLKCFG_HI, - 0x80); - snd_soc_write(codec, M98095_029_DAI1_CLKCFG_LO, - 0x00); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Set to master mode */ - regval |= M98095_DAI_MAS; - break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - default: - dev_err(codec->dev, "Clock mode unsupported"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - regval |= M98095_DAI_DLY; - break; - case SND_SOC_DAIFMT_LEFT_J: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - regval |= M98095_DAI_WCI; - break; - case SND_SOC_DAIFMT_IB_NF: - regval |= M98095_DAI_BCI; - break; - case SND_SOC_DAIFMT_IB_IF: - regval |= M98095_DAI_BCI|M98095_DAI_WCI; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98095_02A_DAI1_FORMAT, - M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | - M98095_DAI_WCI, regval); - - snd_soc_write(codec, M98095_02B_DAI1_CLOCK, M98095_DAI_BSEL64); - } - - return 0; -} - -static int max98095_dai2_set_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_cdata *cdata; - u8 regval = 0; - - cdata = &max98095->dai[1]; - - if (fmt != cdata->fmt) { - cdata->fmt = fmt; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* Slave mode PLL */ - snd_soc_write(codec, M98095_032_DAI2_CLKCFG_HI, - 0x80); - snd_soc_write(codec, M98095_033_DAI2_CLKCFG_LO, - 0x00); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Set to master mode */ - regval |= M98095_DAI_MAS; - break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - default: - dev_err(codec->dev, "Clock mode unsupported"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - regval |= M98095_DAI_DLY; - break; - case SND_SOC_DAIFMT_LEFT_J: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - regval |= M98095_DAI_WCI; - break; - case SND_SOC_DAIFMT_IB_NF: - regval |= M98095_DAI_BCI; - break; - case SND_SOC_DAIFMT_IB_IF: - regval |= M98095_DAI_BCI|M98095_DAI_WCI; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98095_034_DAI2_FORMAT, - M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | - M98095_DAI_WCI, regval); - - snd_soc_write(codec, M98095_035_DAI2_CLOCK, - M98095_DAI_BSEL64); - } - - return 0; -} - -static int max98095_dai3_set_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_cdata *cdata; - u8 regval = 0; - - cdata = &max98095->dai[2]; - - if (fmt != cdata->fmt) { - cdata->fmt = fmt; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* Slave mode PLL */ - snd_soc_write(codec, M98095_03C_DAI3_CLKCFG_HI, - 0x80); - snd_soc_write(codec, M98095_03D_DAI3_CLKCFG_LO, - 0x00); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Set to master mode */ - regval |= M98095_DAI_MAS; - break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - default: - dev_err(codec->dev, "Clock mode unsupported"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - regval |= M98095_DAI_DLY; - break; - case SND_SOC_DAIFMT_LEFT_J: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - regval |= M98095_DAI_WCI; - break; - case SND_SOC_DAIFMT_IB_NF: - regval |= M98095_DAI_BCI; - break; - case SND_SOC_DAIFMT_IB_IF: - regval |= M98095_DAI_BCI|M98095_DAI_WCI; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, M98095_03E_DAI3_FORMAT, - M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | - M98095_DAI_WCI, regval); - - snd_soc_write(codec, M98095_03F_DAI3_CLOCK, - M98095_DAI_BSEL64); - } - - return 0; -} - -static int max98095_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); - - if (ret != 0) { - dev_err(codec->dev, "Failed to sync cache: %d\n", ret); - return ret; - } - } - - snd_soc_update_bits(codec, M98095_090_PWR_EN_IN, - M98095_MBEN, M98095_MBEN); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, M98095_090_PWR_EN_IN, - M98095_MBEN, 0); - codec->cache_sync = 1; - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define MAX98095_RATES SNDRV_PCM_RATE_8000_96000 -#define MAX98095_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops max98095_dai1_ops = { - .set_sysclk = max98095_dai_set_sysclk, - .set_fmt = max98095_dai1_set_fmt, - .hw_params = max98095_dai1_hw_params, -}; - -static const struct snd_soc_dai_ops max98095_dai2_ops = { - .set_sysclk = max98095_dai_set_sysclk, - .set_fmt = max98095_dai2_set_fmt, - .hw_params = max98095_dai2_hw_params, -}; - -static const struct snd_soc_dai_ops max98095_dai3_ops = { - .set_sysclk = max98095_dai_set_sysclk, - .set_fmt = max98095_dai3_set_fmt, - .hw_params = max98095_dai3_hw_params, -}; - -static struct snd_soc_dai_driver max98095_dai[] = { -{ - .name = "HiFi", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98095_RATES, - .formats = MAX98095_FORMATS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = MAX98095_RATES, - .formats = MAX98095_FORMATS, - }, - .ops = &max98095_dai1_ops, -}, -{ - .name = "Aux", - .playback = { - .stream_name = "Aux Playback", - .channels_min = 1, - .channels_max = 1, - .rates = MAX98095_RATES, - .formats = MAX98095_FORMATS, - }, - .ops = &max98095_dai2_ops, -}, -{ - .name = "Voice", - .playback = { - .stream_name = "Voice Playback", - .channels_min = 1, - .channels_max = 1, - .rates = MAX98095_RATES, - .formats = MAX98095_FORMATS, - }, - .ops = &max98095_dai3_ops, -} - -}; - -static int max98095_get_eq_channel(const char *name) -{ - if (strcmp(name, "EQ1 Mode") == 0) - return 0; - if (strcmp(name, "EQ2 Mode") == 0) - return 1; - return -EINVAL; -} - -static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_pdata *pdata = max98095->pdata; - int channel = max98095_get_eq_channel(kcontrol->id.name); - struct max98095_cdata *cdata; - int sel = ucontrol->value.integer.value[0]; - struct max98095_eq_cfg *coef_set; - int fs, best, best_val, i; - int regmask, regsave; - - BUG_ON(channel > 1); - - if (!pdata || !max98095->eq_textcnt) - return 0; - - if (sel >= pdata->eq_cfgcnt) - return -EINVAL; - - cdata = &max98095->dai[channel]; - cdata->eq_sel = sel; - fs = cdata->rate; - - /* Find the selected configuration with nearest sample rate */ - best = 0; - best_val = INT_MAX; - for (i = 0; i < pdata->eq_cfgcnt; i++) { - if (strcmp(pdata->eq_cfg[i].name, max98095->eq_texts[sel]) == 0 && - abs(pdata->eq_cfg[i].rate - fs) < best_val) { - best = i; - best_val = abs(pdata->eq_cfg[i].rate - fs); - } - } - - dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", - pdata->eq_cfg[best].name, - pdata->eq_cfg[best].rate, fs); - - coef_set = &pdata->eq_cfg[best]; - - regmask = (channel == 0) ? M98095_EQ1EN : M98095_EQ2EN; - - /* Disable filter while configuring, and save current on/off state */ - regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); - snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); - - mutex_lock(&codec->mutex); - snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); - m98095_eq_band(codec, channel, 0, coef_set->band1); - m98095_eq_band(codec, channel, 1, coef_set->band2); - m98095_eq_band(codec, channel, 2, coef_set->band3); - m98095_eq_band(codec, channel, 3, coef_set->band4); - m98095_eq_band(codec, channel, 4, coef_set->band5); - snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); - mutex_unlock(&codec->mutex); - - /* Restore the original on/off state */ - snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); - return 0; -} - -static int max98095_get_eq_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - int channel = max98095_get_eq_channel(kcontrol->id.name); - struct max98095_cdata *cdata; - - cdata = &max98095->dai[channel]; - ucontrol->value.enumerated.item[0] = cdata->eq_sel; - - return 0; -} - -static void max98095_handle_eq_pdata(struct snd_soc_codec *codec) -{ - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_pdata *pdata = max98095->pdata; - struct max98095_eq_cfg *cfg; - unsigned int cfgcnt; - int i, j; - const char **t; - int ret; - - struct snd_kcontrol_new controls[] = { - SOC_ENUM_EXT("EQ1 Mode", - max98095->eq_enum, - max98095_get_eq_enum, - max98095_put_eq_enum), - SOC_ENUM_EXT("EQ2 Mode", - max98095->eq_enum, - max98095_get_eq_enum, - max98095_put_eq_enum), - }; - - cfg = pdata->eq_cfg; - cfgcnt = pdata->eq_cfgcnt; - - /* Setup an array of texts for the equalizer enum. - * This is based on Mark Brown's equalizer driver code. - */ - max98095->eq_textcnt = 0; - max98095->eq_texts = NULL; - for (i = 0; i < cfgcnt; i++) { - for (j = 0; j < max98095->eq_textcnt; j++) { - if (strcmp(cfg[i].name, max98095->eq_texts[j]) == 0) - break; - } - - if (j != max98095->eq_textcnt) - continue; - - /* Expand the array */ - t = krealloc(max98095->eq_texts, - sizeof(char *) * (max98095->eq_textcnt + 1), - GFP_KERNEL); - if (t == NULL) - continue; - - /* Store the new entry */ - t[max98095->eq_textcnt] = cfg[i].name; - max98095->eq_textcnt++; - max98095->eq_texts = t; - } - - /* Now point the soc_enum to .texts array items */ - max98095->eq_enum.texts = max98095->eq_texts; - max98095->eq_enum.max = max98095->eq_textcnt; - - ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); - if (ret != 0) - dev_err(codec->dev, "Failed to add EQ control: %d\n", ret); -} - -static const char *bq_mode_name[] = {"Biquad1 Mode", "Biquad2 Mode"}; - -static int max98095_get_bq_channel(struct snd_soc_codec *codec, - const char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bq_mode_name); i++) - if (strcmp(name, bq_mode_name[i]) == 0) - return i; - - /* Shouldn't happen */ - dev_err(codec->dev, "Bad biquad channel name '%s'\n", name); - return -EINVAL; -} - -static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_pdata *pdata = max98095->pdata; - int channel = max98095_get_bq_channel(codec, kcontrol->id.name); - struct max98095_cdata *cdata; - int sel = ucontrol->value.integer.value[0]; - struct max98095_biquad_cfg *coef_set; - int fs, best, best_val, i; - int regmask, regsave; - - if (channel < 0) - return channel; - - if (!pdata || !max98095->bq_textcnt) - return 0; - - if (sel >= pdata->bq_cfgcnt) - return -EINVAL; - - cdata = &max98095->dai[channel]; - cdata->bq_sel = sel; - fs = cdata->rate; - - /* Find the selected configuration with nearest sample rate */ - best = 0; - best_val = INT_MAX; - for (i = 0; i < pdata->bq_cfgcnt; i++) { - if (strcmp(pdata->bq_cfg[i].name, max98095->bq_texts[sel]) == 0 && - abs(pdata->bq_cfg[i].rate - fs) < best_val) { - best = i; - best_val = abs(pdata->bq_cfg[i].rate - fs); - } - } - - dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", - pdata->bq_cfg[best].name, - pdata->bq_cfg[best].rate, fs); - - coef_set = &pdata->bq_cfg[best]; - - regmask = (channel == 0) ? M98095_BQ1EN : M98095_BQ2EN; - - /* Disable filter while configuring, and save current on/off state */ - regsave = snd_soc_read(codec, M98095_088_CFG_LEVEL); - snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, 0); - - mutex_lock(&codec->mutex); - snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, M98095_SEG); - m98095_biquad_band(codec, channel, 0, coef_set->band1); - m98095_biquad_band(codec, channel, 1, coef_set->band2); - snd_soc_update_bits(codec, M98095_00F_HOST_CFG, M98095_SEG, 0); - mutex_unlock(&codec->mutex); - - /* Restore the original on/off state */ - snd_soc_update_bits(codec, M98095_088_CFG_LEVEL, regmask, regsave); - return 0; -} - -static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - int channel = max98095_get_bq_channel(codec, kcontrol->id.name); - struct max98095_cdata *cdata; - - if (channel < 0) - return channel; - - cdata = &max98095->dai[channel]; - ucontrol->value.enumerated.item[0] = cdata->bq_sel; - - return 0; -} - -static void max98095_handle_bq_pdata(struct snd_soc_codec *codec) -{ - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_pdata *pdata = max98095->pdata; - struct max98095_biquad_cfg *cfg; - unsigned int cfgcnt; - int i, j; - const char **t; - int ret; - - struct snd_kcontrol_new controls[] = { - SOC_ENUM_EXT((char *)bq_mode_name[0], - max98095->bq_enum, - max98095_get_bq_enum, - max98095_put_bq_enum), - SOC_ENUM_EXT((char *)bq_mode_name[1], - max98095->bq_enum, - max98095_get_bq_enum, - max98095_put_bq_enum), - }; - BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(bq_mode_name)); - - cfg = pdata->bq_cfg; - cfgcnt = pdata->bq_cfgcnt; - - /* Setup an array of texts for the biquad enum. - * This is based on Mark Brown's equalizer driver code. - */ - max98095->bq_textcnt = 0; - max98095->bq_texts = NULL; - for (i = 0; i < cfgcnt; i++) { - for (j = 0; j < max98095->bq_textcnt; j++) { - if (strcmp(cfg[i].name, max98095->bq_texts[j]) == 0) - break; - } - - if (j != max98095->bq_textcnt) - continue; - - /* Expand the array */ - t = krealloc(max98095->bq_texts, - sizeof(char *) * (max98095->bq_textcnt + 1), - GFP_KERNEL); - if (t == NULL) - continue; - - /* Store the new entry */ - t[max98095->bq_textcnt] = cfg[i].name; - max98095->bq_textcnt++; - max98095->bq_texts = t; - } - - /* Now point the soc_enum to .texts array items */ - max98095->bq_enum.texts = max98095->bq_texts; - max98095->bq_enum.max = max98095->bq_textcnt; - - ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); - if (ret != 0) - dev_err(codec->dev, "Failed to add Biquad control: %d\n", ret); -} - -static void max98095_handle_pdata(struct snd_soc_codec *codec) -{ - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_pdata *pdata = max98095->pdata; - u8 regval = 0; - - if (!pdata) { - dev_dbg(codec->dev, "No platform data\n"); - return; - } - - /* Configure mic for analog/digital mic mode */ - if (pdata->digmic_left_mode) - regval |= M98095_DIGMIC_L; - - if (pdata->digmic_right_mode) - regval |= M98095_DIGMIC_R; - - snd_soc_write(codec, M98095_087_CFG_MIC, regval); - - /* Configure equalizers */ - if (pdata->eq_cfgcnt) - max98095_handle_eq_pdata(codec); - - /* Configure bi-quad filters */ - if (pdata->bq_cfgcnt) - max98095_handle_bq_pdata(codec); -} - -#ifdef CONFIG_PM -static int max98095_suspend(struct snd_soc_codec *codec) -{ - max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int max98095_resume(struct snd_soc_codec *codec) -{ - max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define max98095_suspend NULL -#define max98095_resume NULL -#endif - -static int max98095_reset(struct snd_soc_codec *codec) -{ - int i, ret; - - /* Gracefully reset the DSP core and the codec hardware - * in a proper sequence */ - ret = snd_soc_write(codec, M98095_00F_HOST_CFG, 0); - if (ret < 0) { - dev_err(codec->dev, "Failed to reset DSP: %d\n", ret); - return ret; - } - - ret = snd_soc_write(codec, M98095_097_PWR_SYS, 0); - if (ret < 0) { - dev_err(codec->dev, "Failed to reset codec: %d\n", ret); - return ret; - } - - /* Reset to hardware default for registers, as there is not - * a soft reset hardware control register */ - for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { - ret = snd_soc_write(codec, i, max98095_reg_def[i]); - if (ret < 0) { - dev_err(codec->dev, "Failed to reset: %d\n", ret); - return ret; - } - } - - return ret; -} - -static int max98095_probe(struct snd_soc_codec *codec) -{ - struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); - struct max98095_cdata *cdata; - int ret = 0; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* reset the codec, the DSP core, and disable all interrupts */ - max98095_reset(codec); - - /* initialize private data */ - - max98095->sysclk = (unsigned)-1; - max98095->eq_textcnt = 0; - max98095->bq_textcnt = 0; - - cdata = &max98095->dai[0]; - cdata->rate = (unsigned)-1; - cdata->fmt = (unsigned)-1; - cdata->eq_sel = 0; - cdata->bq_sel = 0; - - cdata = &max98095->dai[1]; - cdata->rate = (unsigned)-1; - cdata->fmt = (unsigned)-1; - cdata->eq_sel = 0; - cdata->bq_sel = 0; - - cdata = &max98095->dai[2]; - cdata->rate = (unsigned)-1; - cdata->fmt = (unsigned)-1; - cdata->eq_sel = 0; - cdata->bq_sel = 0; - - max98095->lin_state = 0; - max98095->mic1pre = 0; - max98095->mic2pre = 0; - - ret = snd_soc_read(codec, M98095_0FF_REV_ID); - if (ret < 0) { - dev_err(codec->dev, "Failure reading hardware revision: %d\n", - ret); - goto err_access; - } - dev_info(codec->dev, "Hardware revision: %c\n", ret - 0x40 + 'A'); - - snd_soc_write(codec, M98095_097_PWR_SYS, M98095_PWRSV); - - /* initialize registers cache to hardware default */ - max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - snd_soc_write(codec, M98095_048_MIX_DAC_LR, - M98095_DAI1L_TO_DACL|M98095_DAI1R_TO_DACR); - - snd_soc_write(codec, M98095_049_MIX_DAC_M, - M98095_DAI2M_TO_DACM|M98095_DAI3M_TO_DACM); - - snd_soc_write(codec, M98095_092_PWR_EN_OUT, M98095_SPK_SPREADSPECTRUM); - snd_soc_write(codec, M98095_045_CFG_DSP, M98095_DSPNORMAL); - snd_soc_write(codec, M98095_04E_CFG_HP, M98095_HPNORMAL); - - snd_soc_write(codec, M98095_02C_DAI1_IOCFG, - M98095_S1NORMAL|M98095_SDATA); - - snd_soc_write(codec, M98095_036_DAI2_IOCFG, - M98095_S2NORMAL|M98095_SDATA); - - snd_soc_write(codec, M98095_040_DAI3_IOCFG, - M98095_S3NORMAL|M98095_SDATA); - - max98095_handle_pdata(codec); - - /* take the codec out of the shut down */ - snd_soc_update_bits(codec, M98095_097_PWR_SYS, M98095_SHDNRUN, - M98095_SHDNRUN); - - max98095_add_widgets(codec); - -err_access: - return ret; -} - -static int max98095_remove(struct snd_soc_codec *codec) -{ - max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_max98095 = { - .probe = max98095_probe, - .remove = max98095_remove, - .suspend = max98095_suspend, - .resume = max98095_resume, - .set_bias_level = max98095_set_bias_level, - .reg_cache_size = ARRAY_SIZE(max98095_reg_def), - .reg_word_size = sizeof(u8), - .reg_cache_default = max98095_reg_def, - .readable_register = max98095_readable, - .volatile_register = max98095_volatile, - .dapm_widgets = max98095_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets), - .dapm_routes = max98095_audio_map, - .num_dapm_routes = ARRAY_SIZE(max98095_audio_map), -}; - -static int max98095_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct max98095_priv *max98095; - int ret; - - max98095 = devm_kzalloc(&i2c->dev, sizeof(struct max98095_priv), - GFP_KERNEL); - if (max98095 == NULL) - return -ENOMEM; - - max98095->devtype = id->driver_data; - i2c_set_clientdata(i2c, max98095); - max98095->pdata = i2c->dev.platform_data; - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095, - max98095_dai, ARRAY_SIZE(max98095_dai)); - return ret; -} - -static int __devexit max98095_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id max98095_i2c_id[] = { - { "max98095", MAX98095 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max98095_i2c_id); - -static struct i2c_driver max98095_i2c_driver = { - .driver = { - .name = "max98095", - .owner = THIS_MODULE, - }, - .probe = max98095_i2c_probe, - .remove = __devexit_p(max98095_i2c_remove), - .id_table = max98095_i2c_id, -}; - -static int __init max98095_init(void) -{ - int ret; - - ret = i2c_add_driver(&max98095_i2c_driver); - if (ret) - pr_err("Failed to register max98095 I2C driver: %d\n", ret); - - return ret; -} -module_init(max98095_init); - -static void __exit max98095_exit(void) -{ - i2c_del_driver(&max98095_i2c_driver); -} -module_exit(max98095_exit); - -MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); -MODULE_AUTHOR("Peter Hsiang"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/max98095.h b/ANDROID_3.4.5/sound/soc/codecs/max98095.h deleted file mode 100644 index 891584a0..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max98095.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * max98095.h -- MAX98095 ALSA SoC Audio driver - * - * Copyright 2011 Maxim Integrated Products - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _MAX98095_H -#define _MAX98095_H - -/* - * MAX98095 Registers Definition - */ - -#define M98095_000_HOST_DATA 0x00 -#define M98095_001_HOST_INT_STS 0x01 -#define M98095_002_HOST_RSP_STS 0x02 -#define M98095_003_HOST_CMD_STS 0x03 -#define M98095_004_CODEC_STS 0x04 -#define M98095_005_DAI1_ALC_STS 0x05 -#define M98095_006_DAI2_ALC_STS 0x06 -#define M98095_007_JACK_AUTO_STS 0x07 -#define M98095_008_JACK_MANUAL_STS 0x08 -#define M98095_009_JACK_VBAT_STS 0x09 -#define M98095_00A_ACC_ADC_STS 0x0A -#define M98095_00B_MIC_NG_AGC_STS 0x0B -#define M98095_00C_SPK_L_VOLT_STS 0x0C -#define M98095_00D_SPK_R_VOLT_STS 0x0D -#define M98095_00E_TEMP_SENSOR_STS 0x0E -#define M98095_00F_HOST_CFG 0x0F -#define M98095_010_HOST_INT_CFG 0x10 -#define M98095_011_HOST_INT_EN 0x11 -#define M98095_012_CODEC_INT_EN 0x12 -#define M98095_013_JACK_INT_EN 0x13 -#define M98095_014_JACK_INT_EN 0x14 -#define M98095_015_DEC 0x15 -#define M98095_016_RESERVED 0x16 -#define M98095_017_RESERVED 0x17 -#define M98095_018_KEYCODE3 0x18 -#define M98095_019_KEYCODE2 0x19 -#define M98095_01A_KEYCODE1 0x1A -#define M98095_01B_KEYCODE0 0x1B -#define M98095_01C_OEMCODE1 0x1C -#define M98095_01D_OEMCODE0 0x1D -#define M98095_01E_XCFG1 0x1E -#define M98095_01F_XCFG2 0x1F -#define M98095_020_XCFG3 0x20 -#define M98095_021_XCFG4 0x21 -#define M98095_022_XCFG5 0x22 -#define M98095_023_XCFG6 0x23 -#define M98095_024_XGPIO 0x24 -#define M98095_025_XCLKCFG 0x25 -#define M98095_026_SYS_CLK 0x26 -#define M98095_027_DAI1_CLKMODE 0x27 -#define M98095_028_DAI1_CLKCFG_HI 0x28 -#define M98095_029_DAI1_CLKCFG_LO 0x29 -#define M98095_02A_DAI1_FORMAT 0x2A -#define M98095_02B_DAI1_CLOCK 0x2B -#define M98095_02C_DAI1_IOCFG 0x2C -#define M98095_02D_DAI1_TDM 0x2D -#define M98095_02E_DAI1_FILTERS 0x2E -#define M98095_02F_DAI1_LVL1 0x2F -#define M98095_030_DAI1_LVL2 0x30 -#define M98095_031_DAI2_CLKMODE 0x31 -#define M98095_032_DAI2_CLKCFG_HI 0x32 -#define M98095_033_DAI2_CLKCFG_LO 0x33 -#define M98095_034_DAI2_FORMAT 0x34 -#define M98095_035_DAI2_CLOCK 0x35 -#define M98095_036_DAI2_IOCFG 0x36 -#define M98095_037_DAI2_TDM 0x37 -#define M98095_038_DAI2_FILTERS 0x38 -#define M98095_039_DAI2_LVL1 0x39 -#define M98095_03A_DAI2_LVL2 0x3A -#define M98095_03B_DAI3_CLKMODE 0x3B -#define M98095_03C_DAI3_CLKCFG_HI 0x3C -#define M98095_03D_DAI3_CLKCFG_LO 0x3D -#define M98095_03E_DAI3_FORMAT 0x3E -#define M98095_03F_DAI3_CLOCK 0x3F -#define M98095_040_DAI3_IOCFG 0x40 -#define M98095_041_DAI3_TDM 0x41 -#define M98095_042_DAI3_FILTERS 0x42 -#define M98095_043_DAI3_LVL1 0x43 -#define M98095_044_DAI3_LVL2 0x44 -#define M98095_045_CFG_DSP 0x45 -#define M98095_046_DAC_CTRL1 0x46 -#define M98095_047_DAC_CTRL2 0x47 -#define M98095_048_MIX_DAC_LR 0x48 -#define M98095_049_MIX_DAC_M 0x49 -#define M98095_04A_MIX_ADC_LEFT 0x4A -#define M98095_04B_MIX_ADC_RIGHT 0x4B -#define M98095_04C_MIX_HP_LEFT 0x4C -#define M98095_04D_MIX_HP_RIGHT 0x4D -#define M98095_04E_CFG_HP 0x4E -#define M98095_04F_MIX_RCV 0x4F -#define M98095_050_MIX_SPK_LEFT 0x50 -#define M98095_051_MIX_SPK_RIGHT 0x51 -#define M98095_052_MIX_SPK_CFG 0x52 -#define M98095_053_MIX_LINEOUT1 0x53 -#define M98095_054_MIX_LINEOUT2 0x54 -#define M98095_055_MIX_LINEOUT_CFG 0x55 -#define M98095_056_LVL_SIDETONE_DAI12 0x56 -#define M98095_057_LVL_SIDETONE_DAI3 0x57 -#define M98095_058_LVL_DAI1_PLAY 0x58 -#define M98095_059_LVL_DAI1_EQ 0x59 -#define M98095_05A_LVL_DAI2_PLAY 0x5A -#define M98095_05B_LVL_DAI2_EQ 0x5B -#define M98095_05C_LVL_DAI3_PLAY 0x5C -#define M98095_05D_LVL_ADC_L 0x5D -#define M98095_05E_LVL_ADC_R 0x5E -#define M98095_05F_LVL_MIC1 0x5F -#define M98095_060_LVL_MIC2 0x60 -#define M98095_061_LVL_LINEIN 0x61 -#define M98095_062_LVL_LINEOUT1 0x62 -#define M98095_063_LVL_LINEOUT2 0x63 -#define M98095_064_LVL_HP_L 0x64 -#define M98095_065_LVL_HP_R 0x65 -#define M98095_066_LVL_RCV 0x66 -#define M98095_067_LVL_SPK_L 0x67 -#define M98095_068_LVL_SPK_R 0x68 -#define M98095_069_MICAGC_CFG 0x69 -#define M98095_06A_MICAGC_THRESH 0x6A -#define M98095_06B_SPK_NOISEGATE 0x6B -#define M98095_06C_DAI1_ALC1_TIME 0x6C -#define M98095_06D_DAI1_ALC1_COMP 0x6D -#define M98095_06E_DAI1_ALC1_EXPN 0x6E -#define M98095_06F_DAI1_ALC1_GAIN 0x6F -#define M98095_070_DAI1_ALC2_TIME 0x70 -#define M98095_071_DAI1_ALC2_COMP 0x71 -#define M98095_072_DAI1_ALC2_EXPN 0x72 -#define M98095_073_DAI1_ALC2_GAIN 0x73 -#define M98095_074_DAI1_ALC3_TIME 0x74 -#define M98095_075_DAI1_ALC3_COMP 0x75 -#define M98095_076_DAI1_ALC3_EXPN 0x76 -#define M98095_077_DAI1_ALC3_GAIN 0x77 -#define M98095_078_DAI2_ALC1_TIME 0x78 -#define M98095_079_DAI2_ALC1_COMP 0x79 -#define M98095_07A_DAI2_ALC1_EXPN 0x7A -#define M98095_07B_DAI2_ALC1_GAIN 0x7B -#define M98095_07C_DAI2_ALC2_TIME 0x7C -#define M98095_07D_DAI2_ALC2_COMP 0x7D -#define M98095_07E_DAI2_ALC2_EXPN 0x7E -#define M98095_07F_DAI2_ALC2_GAIN 0x7F -#define M98095_080_DAI2_ALC3_TIME 0x80 -#define M98095_081_DAI2_ALC3_COMP 0x81 -#define M98095_082_DAI2_ALC3_EXPN 0x82 -#define M98095_083_DAI2_ALC3_GAIN 0x83 -#define M98095_084_HP_NOISE_GATE 0x84 -#define M98095_085_AUX_ADC 0x85 -#define M98095_086_CFG_LINE 0x86 -#define M98095_087_CFG_MIC 0x87 -#define M98095_088_CFG_LEVEL 0x88 -#define M98095_089_JACK_DET_AUTO 0x89 -#define M98095_08A_JACK_DET_MANUAL 0x8A -#define M98095_08B_JACK_KEYSCAN_DBC 0x8B -#define M98095_08C_JACK_KEYSCAN_DLY 0x8C -#define M98095_08D_JACK_KEY_THRESH 0x8D -#define M98095_08E_JACK_DC_SLEW 0x8E -#define M98095_08F_JACK_TEST_CFG 0x8F -#define M98095_090_PWR_EN_IN 0x90 -#define M98095_091_PWR_EN_OUT 0x91 -#define M98095_092_PWR_EN_OUT 0x92 -#define M98095_093_BIAS_CTRL 0x93 -#define M98095_094_PWR_DAC_21 0x94 -#define M98095_095_PWR_DAC_03 0x95 -#define M98095_096_PWR_DAC_CK 0x96 -#define M98095_097_PWR_SYS 0x97 - -#define M98095_0FF_REV_ID 0xFF - -#define M98095_REG_CNT (0xFF+1) -#define M98095_REG_MAX_CACHED 0X97 - -/* MAX98095 Registers Bit Fields */ - -/* M98095_00F_HOST_CFG */ - #define M98095_SEG (1<<0) - #define M98095_XTEN (1<<1) - #define M98095_MDLLEN (1<<2) - -/* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */ - #define M98095_CLKMODE_MASK 0xFF - -/* M98095_02A_DAI1_FORMAT, M98095_034_DAI2_FORMAT, M98095_03E_DAI3_FORMAT */ - #define M98095_DAI_MAS (1<<7) - #define M98095_DAI_WCI (1<<6) - #define M98095_DAI_BCI (1<<5) - #define M98095_DAI_DLY (1<<4) - #define M98095_DAI_TDM (1<<2) - #define M98095_DAI_FSW (1<<1) - #define M98095_DAI_WS (1<<0) - -/* M98095_02B_DAI1_CLOCK, M98095_035_DAI2_CLOCK, M98095_03F_DAI3_CLOCK */ - #define M98095_DAI_BSEL64 (1<<0) - #define M98095_DAI_DOSR_DIV2 (0<<5) - #define M98095_DAI_DOSR_DIV4 (1<<5) - -/* M98095_02C_DAI1_IOCFG, M98095_036_DAI2_IOCFG, M98095_040_DAI3_IOCFG */ - #define M98095_S1NORMAL (1<<6) - #define M98095_S2NORMAL (2<<6) - #define M98095_S3NORMAL (3<<6) - #define M98095_SDATA (3<<0) - -/* M98095_02E_DAI1_FILTERS, M98095_038_DAI2_FILTERS, M98095_042_DAI3_FILTERS */ - #define M98095_DAI_DHF (1<<3) - -/* M98095_045_DSP_CFG */ - #define M98095_DSPNORMAL (5<<4) - -/* M98095_048_MIX_DAC_LR */ - #define M98095_DAI1L_TO_DACR (1<<7) - #define M98095_DAI1R_TO_DACR (1<<6) - #define M98095_DAI2M_TO_DACR (1<<5) - #define M98095_DAI1L_TO_DACL (1<<3) - #define M98095_DAI1R_TO_DACL (1<<2) - #define M98095_DAI2M_TO_DACL (1<<1) - #define M98095_DAI3M_TO_DACL (1<<0) - -/* M98095_049_MIX_DAC_M */ - #define M98095_DAI1L_TO_DACM (1<<3) - #define M98095_DAI1R_TO_DACM (1<<2) - #define M98095_DAI2M_TO_DACM (1<<1) - #define M98095_DAI3M_TO_DACM (1<<0) - -/* M98095_04E_MIX_HP_CFG */ - #define M98095_HPNORMAL (3<<4) - -/* M98095_05F_LVL_MIC1, M98095_060_LVL_MIC2 */ - #define M98095_MICPRE_MASK (3<<5) - #define M98095_MICPRE_SHIFT 5 - -/* M98095_064_LVL_HP_L, M98095_065_LVL_HP_R */ - #define M98095_HP_MUTE (1<<7) - -/* M98095_066_LVL_RCV */ - #define M98095_REC_MUTE (1<<7) - -/* M98095_067_LVL_SPK_L, M98095_068_LVL_SPK_R */ - #define M98095_SP_MUTE (1<<7) - -/* M98095_087_CFG_MIC */ - #define M98095_MICSEL_MASK (3<<0) - #define M98095_DIGMIC_L (1<<2) - #define M98095_DIGMIC_R (1<<3) - #define M98095_DIGMIC2L (1<<4) - #define M98095_DIGMIC2R (1<<5) - -/* M98095_088_CFG_LEVEL */ - #define M98095_VSEN (1<<6) - #define M98095_ZDEN (1<<5) - #define M98095_BQ2EN (1<<3) - #define M98095_BQ1EN (1<<2) - #define M98095_EQ2EN (1<<1) - #define M98095_EQ1EN (1<<0) - -/* M98095_090_PWR_EN_IN */ - #define M98095_INEN (1<<7) - #define M98095_MB2EN (1<<3) - #define M98095_MB1EN (1<<2) - #define M98095_MBEN (3<<2) - #define M98095_ADREN (1<<1) - #define M98095_ADLEN (1<<0) - -/* M98095_091_PWR_EN_OUT */ - #define M98095_HPLEN (1<<7) - #define M98095_HPREN (1<<6) - #define M98095_SPLEN (1<<5) - #define M98095_SPREN (1<<4) - #define M98095_RECEN (1<<3) - #define M98095_DALEN (1<<1) - #define M98095_DAREN (1<<0) - -/* M98095_092_PWR_EN_OUT */ - #define M98095_SPK_FIXEDSPECTRUM (0<<4) - #define M98095_SPK_SPREADSPECTRUM (1<<4) - -/* M98095_097_PWR_SYS */ - #define M98095_SHDNRUN (1<<7) - #define M98095_PERFMODE (1<<3) - #define M98095_HPPLYBACK (1<<2) - #define M98095_PWRSV8K (1<<1) - #define M98095_PWRSV (1<<0) - -#define M98095_COEFS_PER_BAND 5 - -#define M98095_BYTE1(w) ((w >> 8) & 0xff) -#define M98095_BYTE0(w) (w & 0xff) - -/* Equalizer filter coefficients */ -#define M98095_110_DAI1_EQ_BASE 0x10 -#define M98095_142_DAI2_EQ_BASE 0x42 - -/* Biquad filter coefficients */ -#define M98095_174_DAI1_BQ_BASE 0x74 -#define M98095_17E_DAI2_BQ_BASE 0x7E - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/max9850.c b/ANDROID_3.4.5/sound/soc/codecs/max9850.c deleted file mode 100644 index a1913091..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max9850.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * max9850.c -- codec driver for max9850 - * - * Copyright (C) 2011 taskit GmbH - * - * Author: Christian Glindkamp - * - * Initial development of this code was funded by - * MICRONIC Computer Systeme GmbH, http://www.mcsberlin.de/ - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "max9850.h" - -struct max9850_priv { - unsigned int sysclk; -}; - -/* max9850 register cache */ -static const u8 max9850_reg[MAX9850_CACHEREGNUM] = { - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* these registers are not used at the moment but provided for the sake of - * completeness */ -static int max9850_volatile_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - switch (reg) { - case MAX9850_STATUSA: - case MAX9850_STATUSB: - return 1; - default: - return 0; - } -} - -static const unsigned int max9850_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0), - 0x20, 0x33, TLV_DB_SCALE_ITEM(-4150, 200, 0), - 0x34, 0x37, TLV_DB_SCALE_ITEM(-150, 100, 0), - 0x38, 0x3f, TLV_DB_SCALE_ITEM(250, 50, 0), -}; - -static const struct snd_kcontrol_new max9850_controls[] = { -SOC_SINGLE_TLV("Headphone Volume", MAX9850_VOLUME, 0, 0x3f, 1, max9850_tlv), -SOC_SINGLE("Headphone Switch", MAX9850_VOLUME, 7, 1, 1), -SOC_SINGLE("Mono Switch", MAX9850_GENERAL_PURPOSE, 2, 1, 0), -}; - -static const struct snd_kcontrol_new max9850_mixer_controls[] = { - SOC_DAPM_SINGLE("Line In Switch", MAX9850_ENABLE, 1, 1, 0), -}; - -static const struct snd_soc_dapm_widget max9850_dapm_widgets[] = { -SND_SOC_DAPM_SUPPLY("Charge Pump 1", MAX9850_ENABLE, 4, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("Charge Pump 2", MAX9850_ENABLE, 5, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MCLK", MAX9850_ENABLE, 6, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("SHDN", MAX9850_ENABLE, 7, 0, NULL, 0), -SND_SOC_DAPM_MIXER_NAMED_CTL("Output Mixer", MAX9850_ENABLE, 2, 0, - &max9850_mixer_controls[0], - ARRAY_SIZE(max9850_mixer_controls)), -SND_SOC_DAPM_PGA("Headphone Output", MAX9850_ENABLE, 3, 0, NULL, 0), -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", MAX9850_ENABLE, 0, 0), -SND_SOC_DAPM_OUTPUT("OUTL"), -SND_SOC_DAPM_OUTPUT("HPL"), -SND_SOC_DAPM_OUTPUT("OUTR"), -SND_SOC_DAPM_OUTPUT("HPR"), -SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_INPUT("INL"), -SND_SOC_DAPM_INPUT("INR"), -}; - -static const struct snd_soc_dapm_route max9850_dapm_routes[] = { - /* output mixer */ - {"Output Mixer", NULL, "DAC"}, - {"Output Mixer", "Line In Switch", "Line Input"}, - - /* outputs */ - {"Headphone Output", NULL, "Output Mixer"}, - {"HPL", NULL, "Headphone Output"}, - {"HPR", NULL, "Headphone Output"}, - {"OUTL", NULL, "Output Mixer"}, - {"OUTR", NULL, "Output Mixer"}, - - /* inputs */ - {"Line Input", NULL, "INL"}, - {"Line Input", NULL, "INR"}, - - /* supplies */ - {"Output Mixer", NULL, "Charge Pump 1"}, - {"Output Mixer", NULL, "Charge Pump 2"}, - {"Output Mixer", NULL, "SHDN"}, - {"DAC", NULL, "MCLK"}, -}; - -static int max9850_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec); - u64 lrclk_div; - u8 sf, da; - - if (!max9850->sysclk) - return -EINVAL; - - /* lrclk_div = 2^22 * rate / iclk with iclk = mclk / sf */ - sf = (snd_soc_read(codec, MAX9850_CLOCK) >> 2) + 1; - lrclk_div = (1 << 22); - lrclk_div *= params_rate(params); - lrclk_div *= sf; - do_div(lrclk_div, max9850->sysclk); - - snd_soc_write(codec, MAX9850_LRCLK_MSB, (lrclk_div >> 8) & 0x7f); - snd_soc_write(codec, MAX9850_LRCLK_LSB, lrclk_div & 0xff); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - da = 0; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - da = 0x2; - break; - case SNDRV_PCM_FORMAT_S24_LE: - da = 0x3; - break; - default: - return -EINVAL; - } - snd_soc_update_bits(codec, MAX9850_DIGITAL_AUDIO, 0x3, da); - - return 0; -} - -static int max9850_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec); - - /* calculate mclk -> iclk divider */ - if (freq <= 13000000) - snd_soc_write(codec, MAX9850_CLOCK, 0x0); - else if (freq <= 26000000) - snd_soc_write(codec, MAX9850_CLOCK, 0x4); - else if (freq <= 40000000) - snd_soc_write(codec, MAX9850_CLOCK, 0x8); - else - return -EINVAL; - - max9850->sysclk = freq; - return 0; -} - -static int max9850_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u8 da = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - da |= MAX9850_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - da |= MAX9850_DLY; - break; - case SND_SOC_DAIFMT_RIGHT_J: - da |= MAX9850_RTJ; - break; - case SND_SOC_DAIFMT_LEFT_J: - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - da |= MAX9850_BCINV | MAX9850_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - da |= MAX9850_BCINV; - break; - case SND_SOC_DAIFMT_NB_IF: - da |= MAX9850_INV; - break; - default: - return -EINVAL; - } - - /* set da */ - snd_soc_write(codec, MAX9850_DIGITAL_AUDIO, da); - - return 0; -} - -static int max9850_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); - if (ret) { - dev_err(codec->dev, - "Failed to sync cache: %d\n", ret); - return ret; - } - } - break; - case SND_SOC_BIAS_OFF: - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define MAX9850_RATES SNDRV_PCM_RATE_8000_48000 - -#define MAX9850_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops max9850_dai_ops = { - .hw_params = max9850_hw_params, - .set_sysclk = max9850_set_dai_sysclk, - .set_fmt = max9850_set_dai_fmt, -}; - -static struct snd_soc_dai_driver max9850_dai = { - .name = "max9850-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = MAX9850_RATES, - .formats = MAX9850_FORMATS - }, - .ops = &max9850_dai_ops, -}; - -#ifdef CONFIG_PM -static int max9850_suspend(struct snd_soc_codec *codec) -{ - max9850_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int max9850_resume(struct snd_soc_codec *codec) -{ - max9850_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define max9850_suspend NULL -#define max9850_resume NULL -#endif - -static int max9850_probe(struct snd_soc_codec *codec) -{ - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* enable zero-detect */ - snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1); - /* enable slew-rate control */ - snd_soc_update_bits(codec, MAX9850_VOLUME, 0x40, 0x40); - /* set slew-rate 125ms */ - snd_soc_update_bits(codec, MAX9850_CHARGE_PUMP, 0xff, 0xc0); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_max9850 = { - .probe = max9850_probe, - .suspend = max9850_suspend, - .resume = max9850_resume, - .set_bias_level = max9850_set_bias_level, - .reg_cache_size = ARRAY_SIZE(max9850_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = max9850_reg, - .volatile_register = max9850_volatile_register, - - .controls = max9850_controls, - .num_controls = ARRAY_SIZE(max9850_controls), - .dapm_widgets = max9850_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(max9850_dapm_widgets), - .dapm_routes = max9850_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes), -}; - -static int __devinit max9850_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct max9850_priv *max9850; - int ret; - - max9850 = devm_kzalloc(&i2c->dev, sizeof(struct max9850_priv), - GFP_KERNEL); - if (max9850 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, max9850); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_max9850, &max9850_dai, 1); - return ret; -} - -static __devexit int max9850_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id max9850_i2c_id[] = { - { "max9850", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max9850_i2c_id); - -static struct i2c_driver max9850_i2c_driver = { - .driver = { - .name = "max9850", - .owner = THIS_MODULE, - }, - .probe = max9850_i2c_probe, - .remove = __devexit_p(max9850_i2c_remove), - .id_table = max9850_i2c_id, -}; - -static int __init max9850_init(void) -{ - return i2c_add_driver(&max9850_i2c_driver); -} -module_init(max9850_init); - -static void __exit max9850_exit(void) -{ - i2c_del_driver(&max9850_i2c_driver); -} -module_exit(max9850_exit); - -MODULE_AUTHOR("Christian Glindkamp "); -MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/max9850.h b/ANDROID_3.4.5/sound/soc/codecs/max9850.h deleted file mode 100644 index 72b1ddb0..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max9850.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * max9850.h -- codec driver for max9850 - * - * Copyright (C) 2011 taskit GmbH - * Author: Christian Glindkamp - * - * 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. - * - */ - -#ifndef _MAX9850_H -#define _MAX9850_H - -#define MAX9850_STATUSA 0x00 -#define MAX9850_STATUSB 0x01 -#define MAX9850_VOLUME 0x02 -#define MAX9850_GENERAL_PURPOSE 0x03 -#define MAX9850_INTERRUPT 0x04 -#define MAX9850_ENABLE 0x05 -#define MAX9850_CLOCK 0x06 -#define MAX9850_CHARGE_PUMP 0x07 -#define MAX9850_LRCLK_MSB 0x08 -#define MAX9850_LRCLK_LSB 0x09 -#define MAX9850_DIGITAL_AUDIO 0x0a - -#define MAX9850_CACHEREGNUM 11 - -/* MAX9850_DIGITAL_AUDIO */ -#define MAX9850_MASTER (1<<7) -#define MAX9850_INV (1<<6) -#define MAX9850_BCINV (1<<5) -#define MAX9850_DLY (1<<3) -#define MAX9850_RTJ (1<<2) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/max9877.c b/ANDROID_3.4.5/sound/soc/codecs/max9877.c deleted file mode 100644 index 3a2ba3d8..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max9877.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * max9877.c -- amp driver for max9877 - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * 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. - * - */ - -#include -#include -#include -#include -#include - -#include "max9877.h" - -static struct i2c_client *i2c; - -static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 }; - -static void max9877_write_regs(void) -{ - unsigned int i; - u8 data[6]; - - data[0] = MAX9877_INPUT_MODE; - for (i = 0; i < ARRAY_SIZE(max9877_regs); i++) - data[i + 1] = max9877_regs[i]; - - if (i2c_master_send(i2c, data, 6) != 6) - dev_err(&i2c->dev, "i2c write failed\n"); -} - -static int max9877_get_reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int invert = mc->invert; - - ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; - - if (invert) - ucontrol->value.integer.value[0] = - mask - ucontrol->value.integer.value[0]; - - return 0; -} - -static int max9877_set_reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int invert = mc->invert; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - - if (invert) - val = mask - val; - - if (((max9877_regs[reg] >> shift) & mask) == val) - return 0; - - max9877_regs[reg] &= ~(mask << shift); - max9877_regs[reg] |= val << shift; - max9877_write_regs(); - - return 1; -} - -static int max9877_get_2reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - - ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; - ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask; - - return 0; -} - -static int max9877_set_2reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - unsigned int val2 = (ucontrol->value.integer.value[1] & mask); - unsigned int change = 0; - - if (((max9877_regs[reg] >> shift) & mask) != val) - change = 1; - - if (((max9877_regs[reg2] >> shift) & mask) != val2) - change = 1; - - if (change) { - max9877_regs[reg] &= ~(mask << shift); - max9877_regs[reg] |= val << shift; - max9877_regs[reg2] &= ~(mask << shift); - max9877_regs[reg2] |= val2 << shift; - max9877_write_regs(); - } - - return change; -} - -static int max9877_get_out_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK; - - if (value) - value -= 1; - - ucontrol->value.integer.value[0] = value; - return 0; -} - -static int max9877_set_out_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = ucontrol->value.integer.value[0]; - - value += 1; - - if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value) - return 0; - - max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK; - max9877_regs[MAX9877_OUTPUT_MODE] |= value; - max9877_write_regs(); - return 1; -} - -static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK); - - value = value >> MAX9877_OSC_OFFSET; - - ucontrol->value.integer.value[0] = value; - return 0; -} - -static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = ucontrol->value.integer.value[0]; - - value = value << MAX9877_OSC_OFFSET; - if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value) - return 0; - - max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK; - max9877_regs[MAX9877_OUTPUT_MODE] |= value; - max9877_write_regs(); - return 1; -} - -static const unsigned int max9877_pgain_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 1, TLV_DB_SCALE_ITEM(0, 900, 0), - 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0), -}; - -static const unsigned int max9877_output_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), - 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), - 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), - 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), -}; - -static const char *max9877_out_mode[] = { - "INA -> SPK", - "INA -> HP", - "INA -> SPK and HP", - "INB -> SPK", - "INB -> HP", - "INB -> SPK and HP", - "INA + INB -> SPK", - "INA + INB -> HP", - "INA + INB -> SPK and HP", -}; - -static const char *max9877_osc_mode[] = { - "1176KHz", - "1100KHz", - "700KHz", -}; - -static const struct soc_enum max9877_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode), - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode), -}; - -static const struct snd_kcontrol_new max9877_controls[] = { - SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume", - MAX9877_INPUT_MODE, 0, 2, 0, - max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), - SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume", - MAX9877_INPUT_MODE, 2, 2, 0, - max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), - SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume", - MAX9877_SPK_VOLUME, 0, 31, 0, - max9877_get_reg, max9877_set_reg, max9877_output_tlv), - SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume", - MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0, - max9877_get_2reg, max9877_set_2reg, max9877_output_tlv), - SOC_SINGLE_EXT("MAX9877 INB Stereo Switch", - MAX9877_INPUT_MODE, 4, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 INA Stereo Switch", - MAX9877_INPUT_MODE, 5, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch", - MAX9877_INPUT_MODE, 6, 1, 0, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch", - MAX9877_OUTPUT_MODE, 6, 1, 0, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch", - MAX9877_OUTPUT_MODE, 7, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0], - max9877_get_out_mode, max9877_set_out_mode), - SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1], - max9877_get_osc_mode, max9877_set_osc_mode), -}; - -/* This function is called from ASoC machine driver */ -int max9877_add_controls(struct snd_soc_codec *codec) -{ - return snd_soc_add_codec_controls(codec, max9877_controls, - ARRAY_SIZE(max9877_controls)); -} -EXPORT_SYMBOL_GPL(max9877_add_controls); - -static int __devinit max9877_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - i2c = client; - - max9877_write_regs(); - - return 0; -} - -static __devexit int max9877_i2c_remove(struct i2c_client *client) -{ - i2c = NULL; - - return 0; -} - -static const struct i2c_device_id max9877_i2c_id[] = { - { "max9877", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max9877_i2c_id); - -static struct i2c_driver max9877_i2c_driver = { - .driver = { - .name = "max9877", - .owner = THIS_MODULE, - }, - .probe = max9877_i2c_probe, - .remove = __devexit_p(max9877_i2c_remove), - .id_table = max9877_i2c_id, -}; - -static int __init max9877_init(void) -{ - return i2c_add_driver(&max9877_i2c_driver); -} -module_init(max9877_init); - -static void __exit max9877_exit(void) -{ - i2c_del_driver(&max9877_i2c_driver); -} -module_exit(max9877_exit); - -MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/max9877.h b/ANDROID_3.4.5/sound/soc/codecs/max9877.h deleted file mode 100644 index 6da72290..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/max9877.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * max9877.h -- amp driver for max9877 - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * 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. - * - */ - -#ifndef _MAX9877_H -#define _MAX9877_H - -#define MAX9877_INPUT_MODE 0x00 -#define MAX9877_SPK_VOLUME 0x01 -#define MAX9877_HPL_VOLUME 0x02 -#define MAX9877_HPR_VOLUME 0x03 -#define MAX9877_OUTPUT_MODE 0x04 - -/* MAX9877_INPUT_MODE */ -#define MAX9877_INB (1 << 4) -#define MAX9877_INA (1 << 5) -#define MAX9877_ZCD (1 << 6) - -/* MAX9877_OUTPUT_MODE */ -#define MAX9877_OUTMODE_MASK (15 << 0) -#define MAX9877_OSC_MASK (3 << 4) -#define MAX9877_OSC_OFFSET 4 -#define MAX9877_BYPASS (1 << 6) -#define MAX9877_SHDN (1 << 7) - -extern int max9877_add_controls(struct snd_soc_codec *codec); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/pcm3008.c b/ANDROID_3.4.5/sound/soc/codecs/pcm3008.c deleted file mode 100644 index edcaa7ea..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/pcm3008.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * ALSA Soc PCM3008 codec support - * - * Author: Hugo Villeneuve - * Copyright (C) 2008 Lyrtech inc - * - * Based on AC97 Soc codec, original copyright follow: - * Copyright 2005 Wolfson Microelectronics PLC. - * - * 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. - * - * Generic PCM3008 support. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pcm3008.h" - -#define PCM3008_VERSION "0.2" - -#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000) - -static struct snd_soc_dai_driver pcm3008_dai = { - .name = "pcm3008-hifi", - .playback = { - .stream_name = "PCM3008 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = PCM3008_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "PCM3008 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = PCM3008_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}; - -static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) -{ - gpio_free(setup->dem0_pin); - gpio_free(setup->dem1_pin); - gpio_free(setup->pdad_pin); - gpio_free(setup->pdda_pin); -} - -static int pcm3008_soc_probe(struct snd_soc_codec *codec) -{ - struct pcm3008_setup_data *setup = codec->dev->platform_data; - int ret = 0; - - printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); - - /* DEM1 DEM0 DE-EMPHASIS_MODE - * Low Low De-emphasis 44.1 kHz ON - * Low High De-emphasis OFF - * High Low De-emphasis 48 kHz ON - * High High De-emphasis 32 kHz ON - */ - - /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */ - ret = gpio_request(setup->dem0_pin, "codec_dem0"); - if (ret == 0) - ret = gpio_direction_output(setup->dem0_pin, 1); - if (ret != 0) - goto gpio_err; - - /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */ - ret = gpio_request(setup->dem1_pin, "codec_dem1"); - if (ret == 0) - ret = gpio_direction_output(setup->dem1_pin, 0); - if (ret != 0) - goto gpio_err; - - /* Configure PDAD GPIO. */ - ret = gpio_request(setup->pdad_pin, "codec_pdad"); - if (ret == 0) - ret = gpio_direction_output(setup->pdad_pin, 1); - if (ret != 0) - goto gpio_err; - - /* Configure PDDA GPIO. */ - ret = gpio_request(setup->pdda_pin, "codec_pdda"); - if (ret == 0) - ret = gpio_direction_output(setup->pdda_pin, 1); - if (ret != 0) - goto gpio_err; - - return ret; - -gpio_err: - pcm3008_gpio_free(setup); - - return ret; -} - -static int pcm3008_soc_remove(struct snd_soc_codec *codec) -{ - struct pcm3008_setup_data *setup = codec->dev->platform_data; - - pcm3008_gpio_free(setup); - return 0; -} - -#ifdef CONFIG_PM -static int pcm3008_soc_suspend(struct snd_soc_codec *codec) -{ - struct pcm3008_setup_data *setup = codec->dev->platform_data; - - gpio_set_value(setup->pdad_pin, 0); - gpio_set_value(setup->pdda_pin, 0); - - return 0; -} - -static int pcm3008_soc_resume(struct snd_soc_codec *codec) -{ - struct pcm3008_setup_data *setup = codec->dev->platform_data; - - gpio_set_value(setup->pdad_pin, 1); - gpio_set_value(setup->pdda_pin, 1); - - return 0; -} -#else -#define pcm3008_soc_suspend NULL -#define pcm3008_soc_resume NULL -#endif - -static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = { - .probe = pcm3008_soc_probe, - .remove = pcm3008_soc_remove, - .suspend = pcm3008_soc_suspend, - .resume = pcm3008_soc_resume, -}; - -static int __devinit pcm3008_codec_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_pcm3008, &pcm3008_dai, 1); -} - -static int __devexit pcm3008_codec_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -MODULE_ALIAS("platform:pcm3008-codec"); - -static struct platform_driver pcm3008_codec_driver = { - .probe = pcm3008_codec_probe, - .remove = __devexit_p(pcm3008_codec_remove), - .driver = { - .name = "pcm3008-codec", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(pcm3008_codec_driver); - -MODULE_DESCRIPTION("Soc PCM3008 driver"); -MODULE_AUTHOR("Hugo Villeneuve"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/pcm3008.h b/ANDROID_3.4.5/sound/soc/codecs/pcm3008.h deleted file mode 100644 index 7e5489ab..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/pcm3008.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * PCM3008 ALSA SoC Layer - * - * Author: Hugo Villeneuve - * Copyright (C) 2008 Lyrtech inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __LINUX_SND_SOC_PCM3008_H -#define __LINUX_SND_SOC_PCM3008_H - -struct pcm3008_setup_data { - unsigned dem0_pin; - unsigned dem1_pin; - unsigned pdad_pin; - unsigned pdda_pin; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/rt5631.c b/ANDROID_3.4.5/sound/soc/codecs/rt5631.c deleted file mode 100644 index 20c324c7..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/rt5631.c +++ /dev/null @@ -1,1769 +0,0 @@ -/* - * rt5631.c -- RT5631 ALSA Soc Audio driver - * - * Copyright 2011 Realtek Microelectronics - * - * Author: flove - * - * Based on WM8753.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rt5631.h" - -struct rt5631_priv { - int codec_version; - int master; - int sysclk; - int rx_rate; - int bclk_rate; - int dmic_used_flag; -}; - -static const u16 rt5631_reg[RT5631_VENDOR_ID2 + 1] = { - [RT5631_SPK_OUT_VOL] = 0x8888, - [RT5631_HP_OUT_VOL] = 0x8080, - [RT5631_MONO_AXO_1_2_VOL] = 0xa080, - [RT5631_AUX_IN_VOL] = 0x0808, - [RT5631_ADC_REC_MIXER] = 0xf0f0, - [RT5631_VDAC_DIG_VOL] = 0x0010, - [RT5631_OUTMIXER_L_CTRL] = 0xffc0, - [RT5631_OUTMIXER_R_CTRL] = 0xffc0, - [RT5631_AXO1MIXER_CTRL] = 0x88c0, - [RT5631_AXO2MIXER_CTRL] = 0x88c0, - [RT5631_DIG_MIC_CTRL] = 0x3000, - [RT5631_MONO_INPUT_VOL] = 0x8808, - [RT5631_SPK_MIXER_CTRL] = 0xf8f8, - [RT5631_SPK_MONO_OUT_CTRL] = 0xfc00, - [RT5631_SPK_MONO_HP_OUT_CTRL] = 0x4440, - [RT5631_SDP_CTRL] = 0x8000, - [RT5631_MONO_SDP_CTRL] = 0x8000, - [RT5631_STEREO_AD_DA_CLK_CTRL] = 0x2010, - [RT5631_GEN_PUR_CTRL_REG] = 0x0e00, - [RT5631_INT_ST_IRQ_CTRL_2] = 0x071a, - [RT5631_MISC_CTRL] = 0x2040, - [RT5631_DEPOP_FUN_CTRL_2] = 0x8000, - [RT5631_SOFT_VOL_CTRL] = 0x07e0, - [RT5631_ALC_CTRL_1] = 0x0206, - [RT5631_ALC_CTRL_3] = 0x2000, - [RT5631_PSEUDO_SPATL_CTRL] = 0x0553, -}; - -/** - * rt5631_write_index - write index register of 2nd layer - */ -static void rt5631_write_index(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - snd_soc_write(codec, RT5631_INDEX_ADD, reg); - snd_soc_write(codec, RT5631_INDEX_DATA, value); -} - -/** - * rt5631_read_index - read index register of 2nd layer - */ -static unsigned int rt5631_read_index(struct snd_soc_codec *codec, - unsigned int reg) -{ - unsigned int value; - - snd_soc_write(codec, RT5631_INDEX_ADD, reg); - value = snd_soc_read(codec, RT5631_INDEX_DATA); - - return value; -} - -static int rt5631_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, RT5631_RESET, 0); -} - -static int rt5631_volatile_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - switch (reg) { - case RT5631_RESET: - case RT5631_INT_ST_IRQ_CTRL_2: - case RT5631_INDEX_ADD: - case RT5631_INDEX_DATA: - case RT5631_EQ_CTRL: - return 1; - default: - return 0; - } -} - -static int rt5631_readable_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - switch (reg) { - case RT5631_RESET: - case RT5631_SPK_OUT_VOL: - case RT5631_HP_OUT_VOL: - case RT5631_MONO_AXO_1_2_VOL: - case RT5631_AUX_IN_VOL: - case RT5631_STEREO_DAC_VOL_1: - case RT5631_MIC_CTRL_1: - case RT5631_STEREO_DAC_VOL_2: - case RT5631_ADC_CTRL_1: - case RT5631_ADC_REC_MIXER: - case RT5631_ADC_CTRL_2: - case RT5631_VDAC_DIG_VOL: - case RT5631_OUTMIXER_L_CTRL: - case RT5631_OUTMIXER_R_CTRL: - case RT5631_AXO1MIXER_CTRL: - case RT5631_AXO2MIXER_CTRL: - case RT5631_MIC_CTRL_2: - case RT5631_DIG_MIC_CTRL: - case RT5631_MONO_INPUT_VOL: - case RT5631_SPK_MIXER_CTRL: - case RT5631_SPK_MONO_OUT_CTRL: - case RT5631_SPK_MONO_HP_OUT_CTRL: - case RT5631_SDP_CTRL: - case RT5631_MONO_SDP_CTRL: - case RT5631_STEREO_AD_DA_CLK_CTRL: - case RT5631_PWR_MANAG_ADD1: - case RT5631_PWR_MANAG_ADD2: - case RT5631_PWR_MANAG_ADD3: - case RT5631_PWR_MANAG_ADD4: - case RT5631_GEN_PUR_CTRL_REG: - case RT5631_GLOBAL_CLK_CTRL: - case RT5631_PLL_CTRL: - case RT5631_INT_ST_IRQ_CTRL_1: - case RT5631_INT_ST_IRQ_CTRL_2: - case RT5631_GPIO_CTRL: - case RT5631_MISC_CTRL: - case RT5631_DEPOP_FUN_CTRL_1: - case RT5631_DEPOP_FUN_CTRL_2: - case RT5631_JACK_DET_CTRL: - case RT5631_SOFT_VOL_CTRL: - case RT5631_ALC_CTRL_1: - case RT5631_ALC_CTRL_2: - case RT5631_ALC_CTRL_3: - case RT5631_PSEUDO_SPATL_CTRL: - case RT5631_INDEX_ADD: - case RT5631_INDEX_DATA: - case RT5631_EQ_CTRL: - case RT5631_VENDOR_ID: - case RT5631_VENDOR_ID1: - case RT5631_VENDOR_ID2: - return 1; - default: - return 0; - } -} - -static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0); -static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); -/* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */ -static unsigned int mic_bst_tlv[] = { - TLV_DB_RANGE_HEAD(7), - 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), - 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0), - 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0), - 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0), - 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), -}; - -static int rt5631_dmic_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = rt5631->dmic_used_flag; - - return 0; -} - -static int rt5631_dmic_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - - rt5631->dmic_used_flag = ucontrol->value.integer.value[0]; - return 0; -} - -/* MIC Input Type */ -static const char *rt5631_input_mode[] = { - "Single ended", "Differential"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1, - RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode); - -static const SOC_ENUM_SINGLE_DECL( - rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1, - RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode); - -/* MONO Input Type */ -static const SOC_ENUM_SINGLE_DECL( - rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL, - RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode); - -/* SPK Ratio Gain Control */ -static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x", - "1.56x", "1.68x", "1.99x", "2.34x"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG, - RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio); - -static const struct snd_kcontrol_new rt5631_snd_controls[] = { - /* MIC */ - SOC_ENUM("MIC1 Mode Control", rt5631_mic1_mode_enum), - SOC_SINGLE_TLV("MIC1 Boost", RT5631_MIC_CTRL_2, - RT5631_MIC1_BOOST_SHIFT, 8, 0, mic_bst_tlv), - SOC_ENUM("MIC2 Mode Control", rt5631_mic2_mode_enum), - SOC_SINGLE_TLV("MIC2 Boost", RT5631_MIC_CTRL_2, - RT5631_MIC2_BOOST_SHIFT, 8, 0, mic_bst_tlv), - /* MONO IN */ - SOC_ENUM("MONOIN Mode Control", rt5631_monoin_mode_enum), - SOC_DOUBLE_TLV("MONOIN_RX Capture Volume", RT5631_MONO_INPUT_VOL, - RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, - RT5631_VOL_MASK, 1, in_vol_tlv), - /* AXI */ - SOC_DOUBLE_TLV("AXI Capture Volume", RT5631_AUX_IN_VOL, - RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, - RT5631_VOL_MASK, 1, in_vol_tlv), - /* DAC */ - SOC_DOUBLE_TLV("PCM Playback Volume", RT5631_STEREO_DAC_VOL_2, - RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, - RT5631_DAC_VOL_MASK, 1, dac_vol_tlv), - SOC_DOUBLE("PCM Playback Switch", RT5631_STEREO_DAC_VOL_1, - RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1), - /* AXO */ - SOC_SINGLE("AXO1 Playback Switch", RT5631_MONO_AXO_1_2_VOL, - RT5631_L_MUTE_SHIFT, 1, 1), - SOC_SINGLE("AXO2 Playback Switch", RT5631_MONO_AXO_1_2_VOL, - RT5631_R_VOL_SHIFT, 1, 1), - /* OUTVOL */ - SOC_DOUBLE("OUTVOL Channel Switch", RT5631_SPK_OUT_VOL, - RT5631_L_EN_SHIFT, RT5631_R_EN_SHIFT, 1, 0), - - /* SPK */ - SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL, - RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1), - SOC_DOUBLE_TLV("Speaker Playback Volume", RT5631_SPK_OUT_VOL, - RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, 39, 1, out_vol_tlv), - /* MONO OUT */ - SOC_SINGLE("MONO Playback Switch", RT5631_MONO_AXO_1_2_VOL, - RT5631_MUTE_MONO_SHIFT, 1, 1), - /* HP */ - SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL, - RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1), - SOC_DOUBLE_TLV("HP Playback Volume", RT5631_HP_OUT_VOL, - RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, - RT5631_VOL_MASK, 1, out_vol_tlv), - /* DMIC */ - SOC_SINGLE_EXT("DMIC Switch", 0, 0, 1, 0, - rt5631_dmic_get, rt5631_dmic_put), - SOC_DOUBLE("DMIC Capture Switch", RT5631_DIG_MIC_CTRL, - RT5631_DMIC_L_CH_MUTE_SHIFT, - RT5631_DMIC_R_CH_MUTE_SHIFT, 1, 1), - - /* SPK Ratio Gain Control */ - SOC_ENUM("SPK Ratio Control", rt5631_spk_ratio_enum), -}; - -static int check_sysclk1_source(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - unsigned int reg; - - reg = snd_soc_read(source->codec, RT5631_GLOBAL_CLK_CTRL); - return reg & RT5631_SYSCLK_SOUR_SEL_PLL; -} - -static int check_dmic_used(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(source->codec); - return rt5631->dmic_used_flag; -} - -static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - unsigned int reg; - - reg = snd_soc_read(source->codec, RT5631_OUTMIXER_L_CTRL); - return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L); -} - -static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - unsigned int reg; - - reg = snd_soc_read(source->codec, RT5631_OUTMIXER_R_CTRL); - return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R); -} - -static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - unsigned int reg; - - reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL); - return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L); -} - -static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - unsigned int reg; - - reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL); - return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R); -} - -static int check_adcl_select(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - unsigned int reg; - - reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER); - return !(reg & RT5631_M_MIC1_TO_RECMIXER_L); -} - -static int check_adcr_select(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - unsigned int reg; - - reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER); - return !(reg & RT5631_M_MIC2_TO_RECMIXER_R); -} - -/** - * onebit_depop_power_stage - auto depop in power stage. - * @enable: power on/off - * - * When power on/off headphone, the depop sequence is done by hardware. - */ -static void onebit_depop_power_stage(struct snd_soc_codec *codec, int enable) -{ - unsigned int soft_vol, hp_zc; - - /* enable one-bit depop function */ - snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2, - RT5631_EN_ONE_BIT_DEPOP, 0); - - /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL); - snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2); - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); - if (enable) { - /* config one-bit depop parameter */ - rt5631_write_index(codec, RT5631_TEST_MODE_CTRL, 0x84c0); - rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x309f); - rt5631_write_index(codec, RT5631_CP_INTL_REG2, 0x6530); - /* power on capless block */ - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2, - RT5631_EN_CAP_FREE_DEPOP); - } else { - /* power off capless block */ - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2, 0); - msleep(100); - } - - /* recover soft volume and zero crossing setting */ - snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); -} - -/** - * onebit_depop_mute_stage - auto depop in mute stage. - * @enable: mute/unmute - * - * When mute/unmute headphone, the depop sequence is done by hardware. - */ -static void onebit_depop_mute_stage(struct snd_soc_codec *codec, int enable) -{ - unsigned int soft_vol, hp_zc; - - /* enable one-bit depop function */ - snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2, - RT5631_EN_ONE_BIT_DEPOP, 0); - - /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL); - snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2); - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); - if (enable) { - schedule_timeout_uninterruptible(msecs_to_jiffies(10)); - /* config one-bit depop parameter */ - rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x307f); - snd_soc_update_bits(codec, RT5631_HP_OUT_VOL, - RT5631_L_MUTE | RT5631_R_MUTE, 0); - msleep(300); - } else { - snd_soc_update_bits(codec, RT5631_HP_OUT_VOL, - RT5631_L_MUTE | RT5631_R_MUTE, - RT5631_L_MUTE | RT5631_R_MUTE); - msleep(100); - } - - /* recover soft volume and zero crossing setting */ - snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); -} - -/** - * onebit_depop_power_stage - step by step depop sequence in power stage. - * @enable: power on/off - * - * When power on/off headphone, the depop sequence is done in step by step. - */ -static void depop_seq_power_stage(struct snd_soc_codec *codec, int enable) -{ - unsigned int soft_vol, hp_zc; - - /* depop control by register */ - snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2, - RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP); - - /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL); - snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2); - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); - if (enable) { - /* config depop sequence parameter */ - rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303e); - - /* power on headphone and charge pump */ - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, - RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP | - RT5631_PWR_HP_R_AMP, - RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP | - RT5631_PWR_HP_R_AMP); - - /* power on soft generator and depop mode2 */ - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, - RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP); - msleep(100); - - /* stop depop mode */ - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, - RT5631_PWR_HP_DEPOP_DIS, RT5631_PWR_HP_DEPOP_DIS); - } else { - /* config depop sequence parameter */ - rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303F); - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, - RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP | - RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP); - msleep(75); - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, - RT5631_POW_ON_SOFT_GEN | RT5631_PD_HPAMP_L_ST_UP | - RT5631_PD_HPAMP_R_ST_UP); - - /* start depop mode */ - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, - RT5631_PWR_HP_DEPOP_DIS, 0); - - /* config depop sequence parameter */ - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, - RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP | - RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP); - msleep(80); - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, - RT5631_POW_ON_SOFT_GEN); - - /* power down headphone and charge pump */ - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, - RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP | - RT5631_PWR_HP_R_AMP, 0); - } - - /* recover soft volume and zero crossing setting */ - snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); -} - -/** - * depop_seq_mute_stage - step by step depop sequence in mute stage. - * @enable: mute/unmute - * - * When mute/unmute headphone, the depop sequence is done in step by step. - */ -static void depop_seq_mute_stage(struct snd_soc_codec *codec, int enable) -{ - unsigned int soft_vol, hp_zc; - - /* depop control by register */ - snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2, - RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP); - - /* keep soft volume and zero crossing setting */ - soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL); - snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0); - hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2); - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff); - if (enable) { - schedule_timeout_uninterruptible(msecs_to_jiffies(10)); - - /* config depop sequence parameter */ - rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f); - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, - RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP | - RT5631_EN_HP_R_M_UN_MUTE_DEPOP | - RT5631_EN_HP_L_M_UN_MUTE_DEPOP); - - snd_soc_update_bits(codec, RT5631_HP_OUT_VOL, - RT5631_L_MUTE | RT5631_R_MUTE, 0); - msleep(160); - } else { - /* config depop sequence parameter */ - rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f); - snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1, - RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP | - RT5631_EN_HP_R_M_UN_MUTE_DEPOP | - RT5631_EN_HP_L_M_UN_MUTE_DEPOP); - - snd_soc_update_bits(codec, RT5631_HP_OUT_VOL, - RT5631_L_MUTE | RT5631_R_MUTE, - RT5631_L_MUTE | RT5631_R_MUTE); - msleep(150); - } - - /* recover soft volume and zero crossing setting */ - snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol); - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc); -} - -static int hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_PRE_PMD: - if (rt5631->codec_version) { - onebit_depop_mute_stage(codec, 0); - onebit_depop_power_stage(codec, 0); - } else { - depop_seq_mute_stage(codec, 0); - depop_seq_power_stage(codec, 0); - } - break; - - case SND_SOC_DAPM_POST_PMU: - if (rt5631->codec_version) { - onebit_depop_power_stage(codec, 1); - onebit_depop_mute_stage(codec, 1); - } else { - depop_seq_power_stage(codec, 1); - depop_seq_mute_stage(codec, 1); - } - break; - - default: - break; - } - - return 0; -} - -static int set_dmic_params(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - - switch (rt5631->rx_rate) { - case 44100: - case 48000: - snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL, - RT5631_DMIC_CLK_CTRL_MASK, - RT5631_DMIC_CLK_CTRL_TO_32FS); - break; - - case 32000: - case 22050: - snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL, - RT5631_DMIC_CLK_CTRL_MASK, - RT5631_DMIC_CLK_CTRL_TO_64FS); - break; - - case 16000: - case 11025: - case 8000: - snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL, - RT5631_DMIC_CLK_CTRL_MASK, - RT5631_DMIC_CLK_CTRL_TO_128FS); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static const struct snd_kcontrol_new rt5631_recmixl_mixer_controls[] = { - SOC_DAPM_SINGLE("OUTMIXL Capture Switch", RT5631_ADC_REC_MIXER, - RT5631_M_OUTMIXL_RECMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC1_BST1 Capture Switch", RT5631_ADC_REC_MIXER, - RT5631_M_MIC1_RECMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("AXILVOL Capture Switch", RT5631_ADC_REC_MIXER, - RT5631_M_AXIL_RECMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER, - RT5631_M_MONO_IN_RECMIXL_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_recmixr_mixer_controls[] = { - SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER, - RT5631_M_MONO_IN_RECMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("AXIRVOL Capture Switch", RT5631_ADC_REC_MIXER, - RT5631_M_AXIR_RECMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC2_BST2 Capture Switch", RT5631_ADC_REC_MIXER, - RT5631_M_MIC2_RECMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("OUTMIXR Capture Switch", RT5631_ADC_REC_MIXER, - RT5631_M_OUTMIXR_RECMIXR_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_spkmixl_mixer_controls[] = { - SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_SPK_MIXER_CTRL, - RT5631_M_RECMIXL_SPKMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC1_P Playback Switch", RT5631_SPK_MIXER_CTRL, - RT5631_M_MIC1P_SPKMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_SPK_MIXER_CTRL, - RT5631_M_DACL_SPKMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("OUTMIXL Playback Switch", RT5631_SPK_MIXER_CTRL, - RT5631_M_OUTMIXL_SPKMIXL_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_spkmixr_mixer_controls[] = { - SOC_DAPM_SINGLE("OUTMIXR Playback Switch", RT5631_SPK_MIXER_CTRL, - RT5631_M_OUTMIXR_SPKMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_SPK_MIXER_CTRL, - RT5631_M_DACR_SPKMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC2_P Playback Switch", RT5631_SPK_MIXER_CTRL, - RT5631_M_MIC2P_SPKMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_SPK_MIXER_CTRL, - RT5631_M_RECMIXR_SPKMIXR_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_outmixl_mixer_controls[] = { - SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_RECMIXL_OUTMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_RECMIXR_OUTMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_DACL_OUTMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_MIC1_OUTMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_MIC2_OUTMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("MONOIN_RXP Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_MONO_INP_OUTMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_AXIL_OUTMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_AXIR_OUTMIXL_BIT, 1, 1), - SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_L_CTRL, - RT5631_M_VDAC_OUTMIXL_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_outmixr_mixer_controls[] = { - SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_VDAC_OUTMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_AXIR_OUTMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_AXIL_OUTMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("MONOIN_RXN Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_MONO_INN_OUTMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_MIC2_OUTMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_MIC1_OUTMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_DACR_OUTMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_RECMIXR_OUTMIXR_BIT, 1, 1), - SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_R_CTRL, - RT5631_M_RECMIXL_OUTMIXR_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_AXO1MIX_mixer_controls[] = { - SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO1MIXER_CTRL, - RT5631_M_MIC1_AXO1MIX_BIT , 1, 1), - SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO1MIXER_CTRL, - RT5631_M_MIC2_AXO1MIX_BIT, 1, 1), - SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO1MIXER_CTRL, - RT5631_M_OUTMIXL_AXO1MIX_BIT , 1 , 1), - SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO1MIXER_CTRL, - RT5631_M_OUTMIXR_AXO1MIX_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_AXO2MIX_mixer_controls[] = { - SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO2MIXER_CTRL, - RT5631_M_MIC1_AXO2MIX_BIT, 1, 1), - SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO2MIXER_CTRL, - RT5631_M_MIC2_AXO2MIX_BIT, 1, 1), - SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO2MIXER_CTRL, - RT5631_M_OUTMIXL_AXO2MIX_BIT, 1, 1), - SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO2MIXER_CTRL, - RT5631_M_OUTMIXR_AXO2MIX_BIT, 1 , 1), -}; - -static const struct snd_kcontrol_new rt5631_spolmix_mixer_controls[] = { - SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, - RT5631_M_SPKVOLL_SPOLMIX_BIT, 1, 1), - SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, - RT5631_M_SPKVOLR_SPOLMIX_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_spormix_mixer_controls[] = { - SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, - RT5631_M_SPKVOLL_SPORMIX_BIT, 1, 1), - SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, - RT5631_M_SPKVOLR_SPORMIX_BIT, 1, 1), -}; - -static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = { - SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL, - RT5631_M_OUTVOLL_MONOMIX_BIT, 1, 1), - SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL, - RT5631_M_OUTVOLR_MONOMIX_BIT, 1, 1), -}; - -/* Left SPK Volume Input */ -static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL, - RT5631_L_EN_SHIFT, rt5631_spkvoll_sel); - -static const struct snd_kcontrol_new rt5631_spkvoll_mux_control = - SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum); - -/* Left HP Volume Input */ -static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpvoll_enum, RT5631_HP_OUT_VOL, - RT5631_L_EN_SHIFT, rt5631_hpvoll_sel); - -static const struct snd_kcontrol_new rt5631_hpvoll_mux_control = - SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum); - -/* Left Out Volume Input */ -static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL, - RT5631_L_EN_SHIFT, rt5631_outvoll_sel); - -static const struct snd_kcontrol_new rt5631_outvoll_mux_control = - SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum); - -/* Right Out Volume Input */ -static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL, - RT5631_R_EN_SHIFT, rt5631_outvolr_sel); - -static const struct snd_kcontrol_new rt5631_outvolr_mux_control = - SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum); - -/* Right HP Volume Input */ -static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpvolr_enum, RT5631_HP_OUT_VOL, - RT5631_R_EN_SHIFT, rt5631_hpvolr_sel); - -static const struct snd_kcontrol_new rt5631_hpvolr_mux_control = - SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum); - -/* Right SPK Volume Input */ -static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL, - RT5631_R_EN_SHIFT, rt5631_spkvolr_sel); - -static const struct snd_kcontrol_new rt5631_spkvolr_mux_control = - SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum); - -/* SPO Left Channel Input */ -static const char *rt5631_spol_src_sel[] = { - "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel); - -static const struct snd_kcontrol_new rt5631_spol_mux_control = - SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum); - -/* SPO Right Channel Input */ -static const char *rt5631_spor_src_sel[] = { - "SPORMIX", "MONOIN_RX", "VDAC", "DACR"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel); - -static const struct snd_kcontrol_new rt5631_spor_mux_control = - SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum); - -/* MONO Input */ -static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel); - -static const struct snd_kcontrol_new rt5631_mono_mux_control = - SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum); - -/* Left HPO Input */ -static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel); - -static const struct snd_kcontrol_new rt5631_hpl_mux_control = - SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum); - -/* Right HPO Input */ -static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"}; - -static const SOC_ENUM_SINGLE_DECL( - rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL, - RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel); - -static const struct snd_kcontrol_new rt5631_hpr_mux_control = - SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum); - -static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = { - /* Vmid */ - SND_SOC_DAPM_VMID("Vmid"), - /* PLL1 */ - SND_SOC_DAPM_SUPPLY("PLL1", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_PLL1_BIT, 0, NULL, 0), - - /* Input Side */ - /* Input Lines */ - SND_SOC_DAPM_INPUT("MIC1"), - SND_SOC_DAPM_INPUT("MIC2"), - SND_SOC_DAPM_INPUT("AXIL"), - SND_SOC_DAPM_INPUT("AXIR"), - SND_SOC_DAPM_INPUT("MONOIN_RXN"), - SND_SOC_DAPM_INPUT("MONOIN_RXP"), - SND_SOC_DAPM_INPUT("DMIC"), - - /* MICBIAS */ - SND_SOC_DAPM_MICBIAS("MIC Bias1", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_MICBIAS1_VOL_BIT, 0), - SND_SOC_DAPM_MICBIAS("MIC Bias2", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_MICBIAS2_VOL_BIT, 0), - - /* Boost */ - SND_SOC_DAPM_PGA("MIC1 Boost", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_MIC1_BOOT_GAIN_BIT, 0, NULL, 0), - SND_SOC_DAPM_PGA("MIC2 Boost", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_MIC2_BOOT_GAIN_BIT, 0, NULL, 0), - SND_SOC_DAPM_PGA("MONOIN_RXP Boost", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_MONO_IN_P_VOL_BIT, 0, NULL, 0), - SND_SOC_DAPM_PGA("MONOIN_RXN Boost", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_MONO_IN_N_VOL_BIT, 0, NULL, 0), - SND_SOC_DAPM_PGA("AXIL Boost", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_AXIL_IN_VOL_BIT, 0, NULL, 0), - SND_SOC_DAPM_PGA("AXIR Boost", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_AXIR_IN_VOL_BIT, 0, NULL, 0), - - /* MONO In */ - SND_SOC_DAPM_MIXER("MONO_IN", SND_SOC_NOPM, 0, 0, NULL, 0), - - /* REC Mixer */ - SND_SOC_DAPM_MIXER("RECMIXL Mixer", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_RECMIXER_L_BIT, 0, - &rt5631_recmixl_mixer_controls[0], - ARRAY_SIZE(rt5631_recmixl_mixer_controls)), - SND_SOC_DAPM_MIXER("RECMIXR Mixer", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_RECMIXER_R_BIT, 0, - &rt5631_recmixr_mixer_controls[0], - ARRAY_SIZE(rt5631_recmixr_mixer_controls)), - /* Because of record duplication for L/R channel, - * L/R ADCs need power up at the same time */ - SND_SOC_DAPM_MIXER("ADC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - /* DMIC */ - SND_SOC_DAPM_SUPPLY("DMIC Supply", RT5631_DIG_MIC_CTRL, - RT5631_DMIC_ENA_SHIFT, 0, - set_dmic_params, SND_SOC_DAPM_PRE_PMU), - /* ADC Data Srouce */ - SND_SOC_DAPM_SUPPLY("Left ADC Select", RT5631_INT_ST_IRQ_CTRL_2, - RT5631_ADC_DATA_SEL_MIC1_SHIFT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Right ADC Select", RT5631_INT_ST_IRQ_CTRL_2, - RT5631_ADC_DATA_SEL_MIC2_SHIFT, 0, NULL, 0), - - /* ADCs */ - SND_SOC_DAPM_ADC("Left ADC", "HIFI Capture", - RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_L_CLK_BIT, 0), - SND_SOC_DAPM_ADC("Right ADC", "HIFI Capture", - RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_R_CLK_BIT, 0), - - /* DAC and ADC supply power */ - SND_SOC_DAPM_SUPPLY("I2S", RT5631_PWR_MANAG_ADD1, - RT5631_PWR_MAIN_I2S_BIT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("DAC REF", RT5631_PWR_MANAG_ADD1, - RT5631_PWR_DAC_REF_BIT, 0, NULL, 0), - - /* Output Side */ - /* DACs */ - SND_SOC_DAPM_DAC("Left DAC", "HIFI Playback", - RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_L_CLK_BIT, 0), - SND_SOC_DAPM_DAC("Right DAC", "HIFI Playback", - RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_R_CLK_BIT, 0), - SND_SOC_DAPM_DAC("Voice DAC", "Voice DAC Mono Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_PGA("Voice DAC Boost", SND_SOC_NOPM, 0, 0, NULL, 0), - /* DAC supply power */ - SND_SOC_DAPM_SUPPLY("Left DAC To Mixer", RT5631_PWR_MANAG_ADD1, - RT5631_PWR_DAC_L_TO_MIXER_BIT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Right DAC To Mixer", RT5631_PWR_MANAG_ADD1, - RT5631_PWR_DAC_R_TO_MIXER_BIT, 0, NULL, 0), - - /* Left SPK Mixer */ - SND_SOC_DAPM_MIXER("SPKMIXL Mixer", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_SPKMIXER_L_BIT, 0, - &rt5631_spkmixl_mixer_controls[0], - ARRAY_SIZE(rt5631_spkmixl_mixer_controls)), - /* Left Out Mixer */ - SND_SOC_DAPM_MIXER("OUTMIXL Mixer", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_OUTMIXER_L_BIT, 0, - &rt5631_outmixl_mixer_controls[0], - ARRAY_SIZE(rt5631_outmixl_mixer_controls)), - /* Right Out Mixer */ - SND_SOC_DAPM_MIXER("OUTMIXR Mixer", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_OUTMIXER_R_BIT, 0, - &rt5631_outmixr_mixer_controls[0], - ARRAY_SIZE(rt5631_outmixr_mixer_controls)), - /* Right SPK Mixer */ - SND_SOC_DAPM_MIXER("SPKMIXR Mixer", RT5631_PWR_MANAG_ADD2, - RT5631_PWR_SPKMIXER_R_BIT, 0, - &rt5631_spkmixr_mixer_controls[0], - ARRAY_SIZE(rt5631_spkmixr_mixer_controls)), - - /* Volume Mux */ - SND_SOC_DAPM_MUX("Left SPKVOL Mux", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_SPK_L_VOL_BIT, 0, - &rt5631_spkvoll_mux_control), - SND_SOC_DAPM_MUX("Left HPVOL Mux", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_HP_L_OUT_VOL_BIT, 0, - &rt5631_hpvoll_mux_control), - SND_SOC_DAPM_MUX("Left OUTVOL Mux", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_LOUT_VOL_BIT, 0, - &rt5631_outvoll_mux_control), - SND_SOC_DAPM_MUX("Right OUTVOL Mux", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_ROUT_VOL_BIT, 0, - &rt5631_outvolr_mux_control), - SND_SOC_DAPM_MUX("Right HPVOL Mux", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_HP_R_OUT_VOL_BIT, 0, - &rt5631_hpvolr_mux_control), - SND_SOC_DAPM_MUX("Right SPKVOL Mux", RT5631_PWR_MANAG_ADD4, - RT5631_PWR_SPK_R_VOL_BIT, 0, - &rt5631_spkvolr_mux_control), - - /* DAC To HP */ - SND_SOC_DAPM_PGA_S("Left DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA_S("Right DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0), - - /* HP Depop */ - SND_SOC_DAPM_PGA_S("HP Depop", 1, SND_SOC_NOPM, 0, 0, - hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), - - /* AXO1 Mixer */ - SND_SOC_DAPM_MIXER("AXO1MIX Mixer", RT5631_PWR_MANAG_ADD3, - RT5631_PWR_AXO1MIXER_BIT, 0, - &rt5631_AXO1MIX_mixer_controls[0], - ARRAY_SIZE(rt5631_AXO1MIX_mixer_controls)), - /* SPOL Mixer */ - SND_SOC_DAPM_MIXER("SPOLMIX Mixer", SND_SOC_NOPM, 0, 0, - &rt5631_spolmix_mixer_controls[0], - ARRAY_SIZE(rt5631_spolmix_mixer_controls)), - /* MONO Mixer */ - SND_SOC_DAPM_MIXER("MONOMIX Mixer", RT5631_PWR_MANAG_ADD3, - RT5631_PWR_MONOMIXER_BIT, 0, - &rt5631_monomix_mixer_controls[0], - ARRAY_SIZE(rt5631_monomix_mixer_controls)), - /* SPOR Mixer */ - SND_SOC_DAPM_MIXER("SPORMIX Mixer", SND_SOC_NOPM, 0, 0, - &rt5631_spormix_mixer_controls[0], - ARRAY_SIZE(rt5631_spormix_mixer_controls)), - /* AXO2 Mixer */ - SND_SOC_DAPM_MIXER("AXO2MIX Mixer", RT5631_PWR_MANAG_ADD3, - RT5631_PWR_AXO2MIXER_BIT, 0, - &rt5631_AXO2MIX_mixer_controls[0], - ARRAY_SIZE(rt5631_AXO2MIX_mixer_controls)), - - /* Mux */ - SND_SOC_DAPM_MUX("SPOL Mux", SND_SOC_NOPM, 0, 0, - &rt5631_spol_mux_control), - SND_SOC_DAPM_MUX("SPOR Mux", SND_SOC_NOPM, 0, 0, - &rt5631_spor_mux_control), - SND_SOC_DAPM_MUX("MONO Mux", SND_SOC_NOPM, 0, 0, - &rt5631_mono_mux_control), - SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0, - &rt5631_hpl_mux_control), - SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0, - &rt5631_hpr_mux_control), - - /* AMP supply */ - SND_SOC_DAPM_SUPPLY("MONO Depop", RT5631_PWR_MANAG_ADD3, - RT5631_PWR_MONO_DEPOP_DIS_BIT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Class D", RT5631_PWR_MANAG_ADD1, - RT5631_PWR_CLASS_D_BIT, 0, NULL, 0), - - /* Output Lines */ - SND_SOC_DAPM_OUTPUT("AUXO1"), - SND_SOC_DAPM_OUTPUT("AUXO2"), - SND_SOC_DAPM_OUTPUT("SPOL"), - SND_SOC_DAPM_OUTPUT("SPOR"), - SND_SOC_DAPM_OUTPUT("HPOL"), - SND_SOC_DAPM_OUTPUT("HPOR"), - SND_SOC_DAPM_OUTPUT("MONO"), -}; - -static const struct snd_soc_dapm_route rt5631_dapm_routes[] = { - {"MIC1 Boost", NULL, "MIC1"}, - {"MIC2 Boost", NULL, "MIC2"}, - {"MONOIN_RXP Boost", NULL, "MONOIN_RXP"}, - {"MONOIN_RXN Boost", NULL, "MONOIN_RXN"}, - {"AXIL Boost", NULL, "AXIL"}, - {"AXIR Boost", NULL, "AXIR"}, - - {"MONO_IN", NULL, "MONOIN_RXP Boost"}, - {"MONO_IN", NULL, "MONOIN_RXN Boost"}, - - {"RECMIXL Mixer", "OUTMIXL Capture Switch", "OUTMIXL Mixer"}, - {"RECMIXL Mixer", "MIC1_BST1 Capture Switch", "MIC1 Boost"}, - {"RECMIXL Mixer", "AXILVOL Capture Switch", "AXIL Boost"}, - {"RECMIXL Mixer", "MONOIN_RX Capture Switch", "MONO_IN"}, - - {"RECMIXR Mixer", "OUTMIXR Capture Switch", "OUTMIXR Mixer"}, - {"RECMIXR Mixer", "MIC2_BST2 Capture Switch", "MIC2 Boost"}, - {"RECMIXR Mixer", "AXIRVOL Capture Switch", "AXIR Boost"}, - {"RECMIXR Mixer", "MONOIN_RX Capture Switch", "MONO_IN"}, - - {"ADC Mixer", NULL, "RECMIXL Mixer"}, - {"ADC Mixer", NULL, "RECMIXR Mixer"}, - - {"Left ADC", NULL, "ADC Mixer"}, - {"Left ADC", NULL, "Left ADC Select", check_adcl_select}, - {"Left ADC", NULL, "PLL1", check_sysclk1_source}, - {"Left ADC", NULL, "I2S"}, - {"Left ADC", NULL, "DAC REF"}, - - {"Right ADC", NULL, "ADC Mixer"}, - {"Right ADC", NULL, "Right ADC Select", check_adcr_select}, - {"Right ADC", NULL, "PLL1", check_sysclk1_source}, - {"Right ADC", NULL, "I2S"}, - {"Right ADC", NULL, "DAC REF"}, - - {"DMIC", NULL, "DMIC Supply", check_dmic_used}, - {"Left ADC", NULL, "DMIC"}, - {"Right ADC", NULL, "DMIC"}, - - {"Left DAC", NULL, "PLL1", check_sysclk1_source}, - {"Left DAC", NULL, "I2S"}, - {"Left DAC", NULL, "DAC REF"}, - {"Right DAC", NULL, "PLL1", check_sysclk1_source}, - {"Right DAC", NULL, "I2S"}, - {"Right DAC", NULL, "DAC REF"}, - - {"Voice DAC Boost", NULL, "Voice DAC"}, - - {"SPKMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_spkmixl}, - {"SPKMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"}, - {"SPKMIXL Mixer", "MIC1_P Playback Switch", "MIC1"}, - {"SPKMIXL Mixer", "DACL Playback Switch", "Left DAC"}, - {"SPKMIXL Mixer", "OUTMIXL Playback Switch", "OUTMIXL Mixer"}, - - {"SPKMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_spkmixr}, - {"SPKMIXR Mixer", "OUTMIXR Playback Switch", "OUTMIXR Mixer"}, - {"SPKMIXR Mixer", "DACR Playback Switch", "Right DAC"}, - {"SPKMIXR Mixer", "MIC2_P Playback Switch", "MIC2"}, - {"SPKMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"}, - - {"OUTMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_outmixl}, - {"OUTMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"}, - {"OUTMIXL Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"}, - {"OUTMIXL Mixer", "DACL Playback Switch", "Left DAC"}, - {"OUTMIXL Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"}, - {"OUTMIXL Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"}, - {"OUTMIXL Mixer", "MONOIN_RXP Playback Switch", "MONOIN_RXP Boost"}, - {"OUTMIXL Mixer", "AXILVOL Playback Switch", "AXIL Boost"}, - {"OUTMIXL Mixer", "AXIRVOL Playback Switch", "AXIR Boost"}, - {"OUTMIXL Mixer", "VDAC Playback Switch", "Voice DAC Boost"}, - - {"OUTMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_outmixr}, - {"OUTMIXR Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"}, - {"OUTMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"}, - {"OUTMIXR Mixer", "DACR Playback Switch", "Right DAC"}, - {"OUTMIXR Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"}, - {"OUTMIXR Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"}, - {"OUTMIXR Mixer", "MONOIN_RXN Playback Switch", "MONOIN_RXN Boost"}, - {"OUTMIXR Mixer", "AXILVOL Playback Switch", "AXIL Boost"}, - {"OUTMIXR Mixer", "AXIRVOL Playback Switch", "AXIR Boost"}, - {"OUTMIXR Mixer", "VDAC Playback Switch", "Voice DAC Boost"}, - - {"Left SPKVOL Mux", "SPKMIXL", "SPKMIXL Mixer"}, - {"Left SPKVOL Mux", "Vmid", "Vmid"}, - {"Left HPVOL Mux", "OUTMIXL", "OUTMIXL Mixer"}, - {"Left HPVOL Mux", "Vmid", "Vmid"}, - {"Left OUTVOL Mux", "OUTMIXL", "OUTMIXL Mixer"}, - {"Left OUTVOL Mux", "Vmid", "Vmid"}, - {"Right OUTVOL Mux", "OUTMIXR", "OUTMIXR Mixer"}, - {"Right OUTVOL Mux", "Vmid", "Vmid"}, - {"Right HPVOL Mux", "OUTMIXR", "OUTMIXR Mixer"}, - {"Right HPVOL Mux", "Vmid", "Vmid"}, - {"Right SPKVOL Mux", "SPKMIXR", "SPKMIXR Mixer"}, - {"Right SPKVOL Mux", "Vmid", "Vmid"}, - - {"AXO1MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"}, - {"AXO1MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"}, - {"AXO1MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"}, - {"AXO1MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"}, - - {"AXO2MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"}, - {"AXO2MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"}, - {"AXO2MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"}, - {"AXO2MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"}, - - {"SPOLMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"}, - {"SPOLMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"}, - - {"SPORMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"}, - {"SPORMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"}, - - {"MONOMIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"}, - {"MONOMIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"}, - - {"SPOL Mux", "SPOLMIX", "SPOLMIX Mixer"}, - {"SPOL Mux", "MONOIN_RX", "MONO_IN"}, - {"SPOL Mux", "VDAC", "Voice DAC Boost"}, - {"SPOL Mux", "DACL", "Left DAC"}, - - {"SPOR Mux", "SPORMIX", "SPORMIX Mixer"}, - {"SPOR Mux", "MONOIN_RX", "MONO_IN"}, - {"SPOR Mux", "VDAC", "Voice DAC Boost"}, - {"SPOR Mux", "DACR", "Right DAC"}, - - {"MONO Mux", "MONOMIX", "MONOMIX Mixer"}, - {"MONO Mux", "MONOIN_RX", "MONO_IN"}, - {"MONO Mux", "VDAC", "Voice DAC Boost"}, - - {"Right DAC_HP", NULL, "Right DAC"}, - {"Left DAC_HP", NULL, "Left DAC"}, - - {"HPL Mux", "Left HPVOL", "Left HPVOL Mux"}, - {"HPL Mux", "Left DAC", "Left DAC_HP"}, - {"HPR Mux", "Right HPVOL", "Right HPVOL Mux"}, - {"HPR Mux", "Right DAC", "Right DAC_HP"}, - - {"HP Depop", NULL, "HPL Mux"}, - {"HP Depop", NULL, "HPR Mux"}, - - {"AUXO1", NULL, "AXO1MIX Mixer"}, - {"AUXO2", NULL, "AXO2MIX Mixer"}, - - {"SPOL", NULL, "Class D"}, - {"SPOL", NULL, "SPOL Mux"}, - {"SPOR", NULL, "Class D"}, - {"SPOR", NULL, "SPOR Mux"}, - - {"HPOL", NULL, "HP Depop"}, - {"HPOR", NULL, "HP Depop"}, - - {"MONO", NULL, "MONO Depop"}, - {"MONO", NULL, "MONO Mux"}, -}; - -struct coeff_clk_div { - u32 mclk; - u32 bclk; - u32 rate; - u16 reg_val; -}; - -/* PLL divisors */ -struct pll_div { - u32 pll_in; - u32 pll_out; - u16 reg_val; -}; - -static const struct pll_div codec_master_pll_div[] = { - {2048000, 8192000, 0x0ea0}, - {3686400, 8192000, 0x4e27}, - {12000000, 8192000, 0x456b}, - {13000000, 8192000, 0x495f}, - {13100000, 8192000, 0x0320}, - {2048000, 11289600, 0xf637}, - {3686400, 11289600, 0x2f22}, - {12000000, 11289600, 0x3e2f}, - {13000000, 11289600, 0x4d5b}, - {13100000, 11289600, 0x363b}, - {2048000, 16384000, 0x1ea0}, - {3686400, 16384000, 0x9e27}, - {12000000, 16384000, 0x452b}, - {13000000, 16384000, 0x542f}, - {13100000, 16384000, 0x03a0}, - {2048000, 16934400, 0xe625}, - {3686400, 16934400, 0x9126}, - {12000000, 16934400, 0x4d2c}, - {13000000, 16934400, 0x742f}, - {13100000, 16934400, 0x3c27}, - {2048000, 22579200, 0x2aa0}, - {3686400, 22579200, 0x2f20}, - {12000000, 22579200, 0x7e2f}, - {13000000, 22579200, 0x742f}, - {13100000, 22579200, 0x3c27}, - {2048000, 24576000, 0x2ea0}, - {3686400, 24576000, 0xee27}, - {12000000, 24576000, 0x2915}, - {13000000, 24576000, 0x772e}, - {13100000, 24576000, 0x0d20}, - {26000000, 24576000, 0x2027}, - {26000000, 22579200, 0x392f}, - {24576000, 22579200, 0x0921}, - {24576000, 24576000, 0x02a0}, -}; - -static const struct pll_div codec_slave_pll_div[] = { - {256000, 2048000, 0x46f0}, - {256000, 4096000, 0x3ea0}, - {352800, 5644800, 0x3ea0}, - {512000, 8192000, 0x3ea0}, - {1024000, 8192000, 0x46f0}, - {705600, 11289600, 0x3ea0}, - {1024000, 16384000, 0x3ea0}, - {1411200, 22579200, 0x3ea0}, - {1536000, 24576000, 0x3ea0}, - {2048000, 16384000, 0x1ea0}, - {2822400, 22579200, 0x1ea0}, - {2822400, 45158400, 0x5ec0}, - {5644800, 45158400, 0x46f0}, - {3072000, 24576000, 0x1ea0}, - {3072000, 49152000, 0x5ec0}, - {6144000, 49152000, 0x46f0}, - {705600, 11289600, 0x3ea0}, - {705600, 8467200, 0x3ab0}, - {24576000, 24576000, 0x02a0}, - {1411200, 11289600, 0x1690}, - {2822400, 11289600, 0x0a90}, - {1536000, 12288000, 0x1690}, - {3072000, 12288000, 0x0a90}, -}; - -static struct coeff_clk_div coeff_div[] = { - /* sysclk is 256fs */ - {2048000, 8000 * 32, 8000, 0x1000}, - {2048000, 8000 * 64, 8000, 0x0000}, - {2822400, 11025 * 32, 11025, 0x1000}, - {2822400, 11025 * 64, 11025, 0x0000}, - {4096000, 16000 * 32, 16000, 0x1000}, - {4096000, 16000 * 64, 16000, 0x0000}, - {5644800, 22050 * 32, 22050, 0x1000}, - {5644800, 22050 * 64, 22050, 0x0000}, - {8192000, 32000 * 32, 32000, 0x1000}, - {8192000, 32000 * 64, 32000, 0x0000}, - {11289600, 44100 * 32, 44100, 0x1000}, - {11289600, 44100 * 64, 44100, 0x0000}, - {12288000, 48000 * 32, 48000, 0x1000}, - {12288000, 48000 * 64, 48000, 0x0000}, - {22579200, 88200 * 32, 88200, 0x1000}, - {22579200, 88200 * 64, 88200, 0x0000}, - {24576000, 96000 * 32, 96000, 0x1000}, - {24576000, 96000 * 64, 96000, 0x0000}, - /* sysclk is 512fs */ - {4096000, 8000 * 32, 8000, 0x3000}, - {4096000, 8000 * 64, 8000, 0x2000}, - {5644800, 11025 * 32, 11025, 0x3000}, - {5644800, 11025 * 64, 11025, 0x2000}, - {8192000, 16000 * 32, 16000, 0x3000}, - {8192000, 16000 * 64, 16000, 0x2000}, - {11289600, 22050 * 32, 22050, 0x3000}, - {11289600, 22050 * 64, 22050, 0x2000}, - {16384000, 32000 * 32, 32000, 0x3000}, - {16384000, 32000 * 64, 32000, 0x2000}, - {22579200, 44100 * 32, 44100, 0x3000}, - {22579200, 44100 * 64, 44100, 0x2000}, - {24576000, 48000 * 32, 48000, 0x3000}, - {24576000, 48000 * 64, 48000, 0x2000}, - {45158400, 88200 * 32, 88200, 0x3000}, - {45158400, 88200 * 64, 88200, 0x2000}, - {49152000, 96000 * 32, 96000, 0x3000}, - {49152000, 96000 * 64, 96000, 0x2000}, - /* sysclk is 24.576Mhz or 22.5792Mhz */ - {24576000, 8000 * 32, 8000, 0x7080}, - {24576000, 8000 * 64, 8000, 0x6080}, - {24576000, 16000 * 32, 16000, 0x5080}, - {24576000, 16000 * 64, 16000, 0x4080}, - {24576000, 24000 * 32, 24000, 0x5000}, - {24576000, 24000 * 64, 24000, 0x4000}, - {24576000, 32000 * 32, 32000, 0x3080}, - {24576000, 32000 * 64, 32000, 0x2080}, - {22579200, 11025 * 32, 11025, 0x7000}, - {22579200, 11025 * 64, 11025, 0x6000}, - {22579200, 22050 * 32, 22050, 0x5000}, - {22579200, 22050 * 64, 22050, 0x4000}, -}; - -static int get_coeff(int mclk, int rate, int timesofbclk) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].mclk == mclk && coeff_div[i].rate == rate && - (coeff_div[i].bclk / coeff_div[i].rate) == timesofbclk) - return i; - } - return -EINVAL; -} - -static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - int timesofbclk = 32, coeff; - unsigned int iface = 0; - - dev_dbg(codec->dev, "enter %s\n", __func__); - - rt5631->bclk_rate = snd_soc_params_to_bclk(params); - if (rt5631->bclk_rate < 0) { - dev_err(codec->dev, "Fail to get BCLK rate\n"); - return rt5631->bclk_rate; - } - rt5631->rx_rate = params_rate(params); - - if (rt5631->master) - coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate, - rt5631->bclk_rate / rt5631->rx_rate); - else - coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate, - timesofbclk); - if (coeff < 0) { - dev_err(codec->dev, "Fail to get coeff\n"); - return -EINVAL; - } - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= RT5631_SDP_I2S_DL_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= RT5631_SDP_I2S_DL_24; - break; - case SNDRV_PCM_FORMAT_S8: - iface |= RT5631_SDP_I2S_DL_8; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, RT5631_SDP_CTRL, - RT5631_SDP_I2S_DL_MASK, iface); - snd_soc_write(codec, RT5631_STEREO_AD_DA_CLK_CTRL, - coeff_div[coeff].reg_val); - - return 0; -} - -static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - unsigned int iface = 0; - - dev_dbg(codec->dev, "enter %s\n", __func__); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - rt5631->master = 1; - break; - case SND_SOC_DAIFMT_CBS_CFS: - iface |= RT5631_SDP_MODE_SEL_SLAVE; - rt5631->master = 0; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= RT5631_SDP_I2S_DF_LEFT; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= RT5631_SDP_I2S_DF_PCM_A; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= RT5631_SDP_I2S_DF_PCM_B; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= RT5631_SDP_I2S_BCLK_POL_CTRL; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, RT5631_SDP_CTRL, iface); - - return 0; -} - -static int rt5631_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - - dev_dbg(codec->dev, "enter %s, syclk=%d\n", __func__, freq); - - if ((freq >= (256 * 8000)) && (freq <= (512 * 96000))) { - rt5631->sysclk = freq; - return 0; - } - - return -EINVAL; -} - -static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - int i, ret = -EINVAL; - - dev_dbg(codec->dev, "enter %s\n", __func__); - - if (!freq_in || !freq_out) { - dev_dbg(codec->dev, "PLL disabled\n"); - - snd_soc_update_bits(codec, RT5631_GLOBAL_CLK_CTRL, - RT5631_SYSCLK_SOUR_SEL_MASK, - RT5631_SYSCLK_SOUR_SEL_MCLK); - - return 0; - } - - if (rt5631->master) { - for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) - if (freq_in == codec_master_pll_div[i].pll_in && - freq_out == codec_master_pll_div[i].pll_out) { - dev_info(codec->dev, - "change PLL in master mode\n"); - snd_soc_write(codec, RT5631_PLL_CTRL, - codec_master_pll_div[i].reg_val); - schedule_timeout_uninterruptible( - msecs_to_jiffies(20)); - snd_soc_update_bits(codec, - RT5631_GLOBAL_CLK_CTRL, - RT5631_SYSCLK_SOUR_SEL_MASK | - RT5631_PLLCLK_SOUR_SEL_MASK, - RT5631_SYSCLK_SOUR_SEL_PLL | - RT5631_PLLCLK_SOUR_SEL_MCLK); - ret = 0; - break; - } - } else { - for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) - if (freq_in == codec_slave_pll_div[i].pll_in && - freq_out == codec_slave_pll_div[i].pll_out) { - dev_info(codec->dev, - "change PLL in slave mode\n"); - snd_soc_write(codec, RT5631_PLL_CTRL, - codec_slave_pll_div[i].reg_val); - schedule_timeout_uninterruptible( - msecs_to_jiffies(20)); - snd_soc_update_bits(codec, - RT5631_GLOBAL_CLK_CTRL, - RT5631_SYSCLK_SOUR_SEL_MASK | - RT5631_PLLCLK_SOUR_SEL_MASK, - RT5631_SYSCLK_SOUR_SEL_PLL | - RT5631_PLLCLK_SOUR_SEL_BCLK); - ret = 0; - break; - } - } - - return ret; -} - -static int rt5631_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD2, - RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL, - RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, - RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS, - RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS); - msleep(80); - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, - RT5631_PWR_FAST_VREF_CTRL, - RT5631_PWR_FAST_VREF_CTRL); - codec->cache_only = false; - snd_soc_cache_sync(codec); - } - break; - - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, RT5631_PWR_MANAG_ADD1, 0x0000); - snd_soc_write(codec, RT5631_PWR_MANAG_ADD2, 0x0000); - snd_soc_write(codec, RT5631_PWR_MANAG_ADD3, 0x0000); - snd_soc_write(codec, RT5631_PWR_MANAG_ADD4, 0x0000); - break; - - default: - break; - } - codec->dapm.bias_level = level; - - return 0; -} - -static int rt5631_probe(struct snd_soc_codec *codec) -{ - struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec); - unsigned int val; - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3); - if (val & 0x0002) - rt5631->codec_version = 1; - else - rt5631->codec_version = 0; - - rt5631_reset(codec); - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, - RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS, - RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS); - msleep(80); - snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3, - RT5631_PWR_FAST_VREF_CTRL, RT5631_PWR_FAST_VREF_CTRL); - /* enable HP zero cross */ - snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0f18); - /* power off ClassD auto Recovery */ - if (rt5631->codec_version) - snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2, - 0x2000, 0x2000); - else - snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2, - 0x2000, 0); - /* DMIC */ - if (rt5631->dmic_used_flag) { - snd_soc_update_bits(codec, RT5631_GPIO_CTRL, - RT5631_GPIO_PIN_FUN_SEL_MASK | - RT5631_GPIO_DMIC_FUN_SEL_MASK, - RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC | - RT5631_GPIO_DMIC_FUN_SEL_DIMC); - snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL, - RT5631_DMIC_L_CH_LATCH_MASK | - RT5631_DMIC_R_CH_LATCH_MASK, - RT5631_DMIC_L_CH_LATCH_FALLING | - RT5631_DMIC_R_CH_LATCH_RISING); - } - - codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; - - return 0; -} - -static int rt5631_remove(struct snd_soc_codec *codec) -{ - rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -#ifdef CONFIG_PM -static int rt5631_suspend(struct snd_soc_codec *codec) -{ - rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int rt5631_resume(struct snd_soc_codec *codec) -{ - rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define rt5631_suspend NULL -#define rt5631_resume NULL -#endif - -#define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000 -#define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S8) - -static const struct snd_soc_dai_ops rt5631_ops = { - .hw_params = rt5631_hifi_pcm_params, - .set_fmt = rt5631_hifi_codec_set_dai_fmt, - .set_sysclk = rt5631_hifi_codec_set_dai_sysclk, - .set_pll = rt5631_codec_set_dai_pll, -}; - -static struct snd_soc_dai_driver rt5631_dai[] = { - { - .name = "rt5631-hifi", - .id = 1, - .playback = { - .stream_name = "HIFI Playback", - .channels_min = 1, - .channels_max = 2, - .rates = RT5631_STEREO_RATES, - .formats = RT5631_FORMAT, - }, - .capture = { - .stream_name = "HIFI Capture", - .channels_min = 1, - .channels_max = 2, - .rates = RT5631_STEREO_RATES, - .formats = RT5631_FORMAT, - }, - .ops = &rt5631_ops, - }, -}; - -static struct snd_soc_codec_driver soc_codec_dev_rt5631 = { - .probe = rt5631_probe, - .remove = rt5631_remove, - .suspend = rt5631_suspend, - .resume = rt5631_resume, - .set_bias_level = rt5631_set_bias_level, - .reg_cache_size = RT5631_VENDOR_ID2 + 1, - .reg_word_size = sizeof(u16), - .reg_cache_default = rt5631_reg, - .volatile_register = rt5631_volatile_register, - .readable_register = rt5631_readable_register, - .reg_cache_step = 1, - .controls = rt5631_snd_controls, - .num_controls = ARRAY_SIZE(rt5631_snd_controls), - .dapm_widgets = rt5631_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets), - .dapm_routes = rt5631_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes), -}; - -static const struct i2c_device_id rt5631_i2c_id[] = { - { "rt5631", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); - -static int rt5631_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct rt5631_priv *rt5631; - int ret; - - rt5631 = devm_kzalloc(&i2c->dev, sizeof(struct rt5631_priv), - GFP_KERNEL); - if (NULL == rt5631) - return -ENOMEM; - - i2c_set_clientdata(i2c, rt5631); - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5631, - rt5631_dai, ARRAY_SIZE(rt5631_dai)); - return ret; -} - -static __devexit int rt5631_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static struct i2c_driver rt5631_i2c_driver = { - .driver = { - .name = "rt5631", - .owner = THIS_MODULE, - }, - .probe = rt5631_i2c_probe, - .remove = __devexit_p(rt5631_i2c_remove), - .id_table = rt5631_i2c_id, -}; - -static int __init rt5631_modinit(void) -{ - return i2c_add_driver(&rt5631_i2c_driver); -} -module_init(rt5631_modinit); - -static void __exit rt5631_modexit(void) -{ - i2c_del_driver(&rt5631_i2c_driver); -} -module_exit(rt5631_modexit); - -MODULE_DESCRIPTION("ASoC RT5631 driver"); -MODULE_AUTHOR("flove "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/rt5631.h b/ANDROID_3.4.5/sound/soc/codecs/rt5631.h deleted file mode 100644 index 13401581..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/rt5631.h +++ /dev/null @@ -1,701 +0,0 @@ -#ifndef __RTCODEC5631_H__ -#define __RTCODEC5631_H__ - - -#define RT5631_RESET 0x00 -#define RT5631_SPK_OUT_VOL 0x02 -#define RT5631_HP_OUT_VOL 0x04 -#define RT5631_MONO_AXO_1_2_VOL 0x06 -#define RT5631_AUX_IN_VOL 0x0A -#define RT5631_STEREO_DAC_VOL_1 0x0C -#define RT5631_MIC_CTRL_1 0x0E -#define RT5631_STEREO_DAC_VOL_2 0x10 -#define RT5631_ADC_CTRL_1 0x12 -#define RT5631_ADC_REC_MIXER 0x14 -#define RT5631_ADC_CTRL_2 0x16 -#define RT5631_VDAC_DIG_VOL 0x18 -#define RT5631_OUTMIXER_L_CTRL 0x1A -#define RT5631_OUTMIXER_R_CTRL 0x1C -#define RT5631_AXO1MIXER_CTRL 0x1E -#define RT5631_AXO2MIXER_CTRL 0x20 -#define RT5631_MIC_CTRL_2 0x22 -#define RT5631_DIG_MIC_CTRL 0x24 -#define RT5631_MONO_INPUT_VOL 0x26 -#define RT5631_SPK_MIXER_CTRL 0x28 -#define RT5631_SPK_MONO_OUT_CTRL 0x2A -#define RT5631_SPK_MONO_HP_OUT_CTRL 0x2C -#define RT5631_SDP_CTRL 0x34 -#define RT5631_MONO_SDP_CTRL 0x36 -#define RT5631_STEREO_AD_DA_CLK_CTRL 0x38 -#define RT5631_PWR_MANAG_ADD1 0x3A -#define RT5631_PWR_MANAG_ADD2 0x3B -#define RT5631_PWR_MANAG_ADD3 0x3C -#define RT5631_PWR_MANAG_ADD4 0x3E -#define RT5631_GEN_PUR_CTRL_REG 0x40 -#define RT5631_GLOBAL_CLK_CTRL 0x42 -#define RT5631_PLL_CTRL 0x44 -#define RT5631_INT_ST_IRQ_CTRL_1 0x48 -#define RT5631_INT_ST_IRQ_CTRL_2 0x4A -#define RT5631_GPIO_CTRL 0x4C -#define RT5631_MISC_CTRL 0x52 -#define RT5631_DEPOP_FUN_CTRL_1 0x54 -#define RT5631_DEPOP_FUN_CTRL_2 0x56 -#define RT5631_JACK_DET_CTRL 0x5A -#define RT5631_SOFT_VOL_CTRL 0x5C -#define RT5631_ALC_CTRL_1 0x64 -#define RT5631_ALC_CTRL_2 0x65 -#define RT5631_ALC_CTRL_3 0x66 -#define RT5631_PSEUDO_SPATL_CTRL 0x68 -#define RT5631_INDEX_ADD 0x6A -#define RT5631_INDEX_DATA 0x6C -#define RT5631_EQ_CTRL 0x6E -#define RT5631_VENDOR_ID 0x7A -#define RT5631_VENDOR_ID1 0x7C -#define RT5631_VENDOR_ID2 0x7E - -/* Index of Codec Private Register definition */ -#define RT5631_EQ_BW_LOP 0x00 -#define RT5631_EQ_GAIN_LOP 0x01 -#define RT5631_EQ_FC_BP1 0x02 -#define RT5631_EQ_BW_BP1 0x03 -#define RT5631_EQ_GAIN_BP1 0x04 -#define RT5631_EQ_FC_BP2 0x05 -#define RT5631_EQ_BW_BP2 0x06 -#define RT5631_EQ_GAIN_BP2 0x07 -#define RT5631_EQ_FC_BP3 0x08 -#define RT5631_EQ_BW_BP3 0x09 -#define RT5631_EQ_GAIN_BP3 0x0a -#define RT5631_EQ_BW_HIP 0x0b -#define RT5631_EQ_GAIN_HIP 0x0c -#define RT5631_EQ_HPF_A1 0x0d -#define RT5631_EQ_HPF_A2 0x0e -#define RT5631_EQ_HPF_GAIN 0x0f -#define RT5631_EQ_PRE_VOL_CTRL 0x11 -#define RT5631_EQ_POST_VOL_CTRL 0x12 -#define RT5631_TEST_MODE_CTRL 0x39 -#define RT5631_CP_INTL_REG2 0x45 -#define RT5631_ADDA_MIXER_INTL_REG3 0x52 -#define RT5631_SPK_INTL_CTRL 0x56 - - -/* global definition */ -#define RT5631_L_MUTE (0x1 << 15) -#define RT5631_L_MUTE_SHIFT 15 -#define RT5631_L_EN (0x1 << 14) -#define RT5631_L_EN_SHIFT 14 -#define RT5631_R_MUTE (0x1 << 7) -#define RT5631_R_MUTE_SHIFT 7 -#define RT5631_R_EN (0x1 << 6) -#define RT5631_R_EN_SHIFT 6 -#define RT5631_VOL_MASK 0x1f -#define RT5631_L_VOL_SHIFT 8 -#define RT5631_R_VOL_SHIFT 0 - -/* Speaker Output Control(0x02) */ -#define RT5631_SPK_L_VOL_SEL_MASK (0x1 << 14) -#define RT5631_SPK_L_VOL_SEL_VMID (0x0 << 14) -#define RT5631_SPK_L_VOL_SEL_SPKMIX_L (0x1 << 14) -#define RT5631_SPK_R_VOL_SEL_MASK (0x1 << 6) -#define RT5631_SPK_R_VOL_SEL_VMID (0x0 << 6) -#define RT5631_SPK_R_VOL_SEL_SPKMIX_R (0x1 << 6) - -/* Headphone Output Control(0x04) */ -#define RT5631_HP_L_VOL_SEL_MASK (0x1 << 14) -#define RT5631_HP_L_VOL_SEL_VMID (0x0 << 14) -#define RT5631_HP_L_VOL_SEL_OUTMIX_L (0x1 << 14) -#define RT5631_HP_R_VOL_SEL_MASK (0x1 << 6) -#define RT5631_HP_R_VOL_SEL_VMID (0x0 << 6) -#define RT5631_HP_R_VOL_SEL_OUTMIX_R (0x1 << 6) - -/* Output Control for AUXOUT/MONO(0x06) */ -#define RT5631_AUXOUT_1_VOL_SEL_MASK (0x1 << 14) -#define RT5631_AUXOUT_1_VOL_SEL_VMID (0x0 << 14) -#define RT5631_AUXOUT_1_VOL_SEL_OUTMIX_L (0x1 << 14) -#define RT5631_MUTE_MONO (0x1 << 13) -#define RT5631_MUTE_MONO_SHIFT 13 -#define RT5631_AUXOUT_2_VOL_SEL_MASK (0x1 << 6) -#define RT5631_AUXOUT_2_VOL_SEL_VMID (0x0 << 6) -#define RT5631_AUXOUT_2_VOL_SEL_OUTMIX_R (0x1 << 6) - -/* Microphone Input Control 1(0x0E) */ -#define RT5631_MIC1_DIFF_INPUT_CTRL (0x1 << 15) -#define RT5631_MIC1_DIFF_INPUT_SHIFT 15 -#define RT5631_MIC2_DIFF_INPUT_CTRL (0x1 << 7) -#define RT5631_MIC2_DIFF_INPUT_SHIFT 7 - -/* Stereo DAC Digital Volume2(0x10) */ -#define RT5631_DAC_VOL_MASK 0xff - -/* ADC Recording Mixer Control(0x14) */ -#define RT5631_M_OUTMIXER_L_TO_RECMIXER_L (0x1 << 15) -#define RT5631_M_OUTMIXL_RECMIXL_BIT 15 -#define RT5631_M_MIC1_TO_RECMIXER_L (0x1 << 14) -#define RT5631_M_MIC1_RECMIXL_BIT 14 -#define RT5631_M_AXIL_TO_RECMIXER_L (0x1 << 13) -#define RT5631_M_AXIL_RECMIXL_BIT 13 -#define RT5631_M_MONO_IN_TO_RECMIXER_L (0x1 << 12) -#define RT5631_M_MONO_IN_RECMIXL_BIT 12 -#define RT5631_M_OUTMIXER_R_TO_RECMIXER_R (0x1 << 7) -#define RT5631_M_OUTMIXR_RECMIXR_BIT 7 -#define RT5631_M_MIC2_TO_RECMIXER_R (0x1 << 6) -#define RT5631_M_MIC2_RECMIXR_BIT 6 -#define RT5631_M_AXIR_TO_RECMIXER_R (0x1 << 5) -#define RT5631_M_AXIR_RECMIXR_BIT 5 -#define RT5631_M_MONO_IN_TO_RECMIXER_R (0x1 << 4) -#define RT5631_M_MONO_IN_RECMIXR_BIT 4 - -/* Left Output Mixer Control(0x1A) */ -#define RT5631_M_RECMIXER_L_TO_OUTMIXER_L (0x1 << 15) -#define RT5631_M_RECMIXL_OUTMIXL_BIT 15 -#define RT5631_M_RECMIXER_R_TO_OUTMIXER_L (0x1 << 14) -#define RT5631_M_RECMIXR_OUTMIXL_BIT 14 -#define RT5631_M_DAC_L_TO_OUTMIXER_L (0x1 << 13) -#define RT5631_M_DACL_OUTMIXL_BIT 13 -#define RT5631_M_MIC1_TO_OUTMIXER_L (0x1 << 12) -#define RT5631_M_MIC1_OUTMIXL_BIT 12 -#define RT5631_M_MIC2_TO_OUTMIXER_L (0x1 << 11) -#define RT5631_M_MIC2_OUTMIXL_BIT 11 -#define RT5631_M_MONO_IN_P_TO_OUTMIXER_L (0x1 << 10) -#define RT5631_M_MONO_INP_OUTMIXL_BIT 10 -#define RT5631_M_AXIL_TO_OUTMIXER_L (0x1 << 9) -#define RT5631_M_AXIL_OUTMIXL_BIT 9 -#define RT5631_M_AXIR_TO_OUTMIXER_L (0x1 << 8) -#define RT5631_M_AXIR_OUTMIXL_BIT 8 -#define RT5631_M_VDAC_TO_OUTMIXER_L (0x1 << 7) -#define RT5631_M_VDAC_OUTMIXL_BIT 7 - -/* Right Output Mixer Control(0x1C) */ -#define RT5631_M_RECMIXER_L_TO_OUTMIXER_R (0x1 << 15) -#define RT5631_M_RECMIXL_OUTMIXR_BIT 15 -#define RT5631_M_RECMIXER_R_TO_OUTMIXER_R (0x1 << 14) -#define RT5631_M_RECMIXR_OUTMIXR_BIT 14 -#define RT5631_M_DAC_R_TO_OUTMIXER_R (0x1 << 13) -#define RT5631_M_DACR_OUTMIXR_BIT 13 -#define RT5631_M_MIC1_TO_OUTMIXER_R (0x1 << 12) -#define RT5631_M_MIC1_OUTMIXR_BIT 12 -#define RT5631_M_MIC2_TO_OUTMIXER_R (0x1 << 11) -#define RT5631_M_MIC2_OUTMIXR_BIT 11 -#define RT5631_M_MONO_IN_N_TO_OUTMIXER_R (0x1 << 10) -#define RT5631_M_MONO_INN_OUTMIXR_BIT 10 -#define RT5631_M_AXIL_TO_OUTMIXER_R (0x1 << 9) -#define RT5631_M_AXIL_OUTMIXR_BIT 9 -#define RT5631_M_AXIR_TO_OUTMIXER_R (0x1 << 8) -#define RT5631_M_AXIR_OUTMIXR_BIT 8 -#define RT5631_M_VDAC_TO_OUTMIXER_R (0x1 << 7) -#define RT5631_M_VDAC_OUTMIXR_BIT 7 - -/* Lout Mixer Control(0x1E) */ -#define RT5631_M_MIC1_TO_AXO1MIXER (0x1 << 15) -#define RT5631_M_MIC1_AXO1MIX_BIT 15 -#define RT5631_M_MIC2_TO_AXO1MIXER (0x1 << 11) -#define RT5631_M_MIC2_AXO1MIX_BIT 11 -#define RT5631_M_OUTMIXER_L_TO_AXO1MIXER (0x1 << 7) -#define RT5631_M_OUTMIXL_AXO1MIX_BIT 7 -#define RT5631_M_OUTMIXER_R_TO_AXO1MIXER (0x1 << 6) -#define RT5631_M_OUTMIXR_AXO1MIX_BIT 6 - -/* Rout Mixer Control(0x20) */ -#define RT5631_M_MIC1_TO_AXO2MIXER (0x1 << 15) -#define RT5631_M_MIC1_AXO2MIX_BIT 15 -#define RT5631_M_MIC2_TO_AXO2MIXER (0x1 << 11) -#define RT5631_M_MIC2_AXO2MIX_BIT 11 -#define RT5631_M_OUTMIXER_L_TO_AXO2MIXER (0x1 << 7) -#define RT5631_M_OUTMIXL_AXO2MIX_BIT 7 -#define RT5631_M_OUTMIXER_R_TO_AXO2MIXER (0x1 << 6) -#define RT5631_M_OUTMIXR_AXO2MIX_BIT 6 - -/* Micphone Input Control 2(0x22) */ -#define RT5631_MIC_BIAS_90_PRECNET_AVDD 1 -#define RT5631_MIC_BIAS_75_PRECNET_AVDD 2 - -#define RT5631_MIC1_BOOST_CTRL_MASK (0xf << 12) -#define RT5631_MIC1_BOOST_CTRL_BYPASS (0x0 << 12) -#define RT5631_MIC1_BOOST_CTRL_20DB (0x1 << 12) -#define RT5631_MIC1_BOOST_CTRL_24DB (0x2 << 12) -#define RT5631_MIC1_BOOST_CTRL_30DB (0x3 << 12) -#define RT5631_MIC1_BOOST_CTRL_35DB (0x4 << 12) -#define RT5631_MIC1_BOOST_CTRL_40DB (0x5 << 12) -#define RT5631_MIC1_BOOST_CTRL_34DB (0x6 << 12) -#define RT5631_MIC1_BOOST_CTRL_50DB (0x7 << 12) -#define RT5631_MIC1_BOOST_CTRL_52DB (0x8 << 12) -#define RT5631_MIC1_BOOST_SHIFT 12 - -#define RT5631_MIC2_BOOST_CTRL_MASK (0xf << 8) -#define RT5631_MIC2_BOOST_CTRL_BYPASS (0x0 << 8) -#define RT5631_MIC2_BOOST_CTRL_20DB (0x1 << 8) -#define RT5631_MIC2_BOOST_CTRL_24DB (0x2 << 8) -#define RT5631_MIC2_BOOST_CTRL_30DB (0x3 << 8) -#define RT5631_MIC2_BOOST_CTRL_35DB (0x4 << 8) -#define RT5631_MIC2_BOOST_CTRL_40DB (0x5 << 8) -#define RT5631_MIC2_BOOST_CTRL_34DB (0x6 << 8) -#define RT5631_MIC2_BOOST_CTRL_50DB (0x7 << 8) -#define RT5631_MIC2_BOOST_CTRL_52DB (0x8 << 8) -#define RT5631_MIC2_BOOST_SHIFT 8 - -#define RT5631_MICBIAS1_VOLT_CTRL_MASK (0x1 << 7) -#define RT5631_MICBIAS1_VOLT_CTRL_90P (0x0 << 7) -#define RT5631_MICBIAS1_VOLT_CTRL_75P (0x1 << 7) - -#define RT5631_MICBIAS1_S_C_DET_MASK (0x1 << 6) -#define RT5631_MICBIAS1_S_C_DET_DIS (0x0 << 6) -#define RT5631_MICBIAS1_S_C_DET_ENA (0x1 << 6) - -#define RT5631_MICBIAS1_SHORT_CURR_DET_MASK (0x3 << 4) -#define RT5631_MICBIAS1_SHORT_CURR_DET_600UA (0x0 << 4) -#define RT5631_MICBIAS1_SHORT_CURR_DET_1500UA (0x1 << 4) -#define RT5631_MICBIAS1_SHORT_CURR_DET_2000UA (0x2 << 4) - -#define RT5631_MICBIAS2_VOLT_CTRL_MASK (0x1 << 3) -#define RT5631_MICBIAS2_VOLT_CTRL_90P (0x0 << 3) -#define RT5631_MICBIAS2_VOLT_CTRL_75P (0x1 << 3) - -#define RT5631_MICBIAS2_S_C_DET_MASK (0x1 << 2) -#define RT5631_MICBIAS2_S_C_DET_DIS (0x0 << 2) -#define RT5631_MICBIAS2_S_C_DET_ENA (0x1 << 2) - -#define RT5631_MICBIAS2_SHORT_CURR_DET_MASK (0x3) -#define RT5631_MICBIAS2_SHORT_CURR_DET_600UA (0x0) -#define RT5631_MICBIAS2_SHORT_CURR_DET_1500UA (0x1) -#define RT5631_MICBIAS2_SHORT_CURR_DET_2000UA (0x2) - - -/* Digital Microphone Control(0x24) */ -#define RT5631_DMIC_ENA_MASK (0x1 << 15) -#define RT5631_DMIC_ENA_SHIFT 15 -/* DMIC_ENA: DMIC to ADC Digital filter */ -#define RT5631_DMIC_ENA (0x1 << 15) -/* DMIC_DIS: ADC mixer to ADC Digital filter */ -#define RT5631_DMIC_DIS (0x0 << 15) -#define RT5631_DMIC_L_CH_MUTE (0x1 << 13) -#define RT5631_DMIC_L_CH_MUTE_SHIFT 13 -#define RT5631_DMIC_R_CH_MUTE (0x1 << 12) -#define RT5631_DMIC_R_CH_MUTE_SHIFT 12 -#define RT5631_DMIC_L_CH_LATCH_MASK (0x1 << 9) -#define RT5631_DMIC_L_CH_LATCH_RISING (0x1 << 9) -#define RT5631_DMIC_L_CH_LATCH_FALLING (0x0 << 9) -#define RT5631_DMIC_R_CH_LATCH_MASK (0x1 << 8) -#define RT5631_DMIC_R_CH_LATCH_RISING (0x1 << 8) -#define RT5631_DMIC_R_CH_LATCH_FALLING (0x0 << 8) -#define RT5631_DMIC_CLK_CTRL_MASK (0x3 << 4) -#define RT5631_DMIC_CLK_CTRL_TO_128FS (0x0 << 4) -#define RT5631_DMIC_CLK_CTRL_TO_64FS (0x1 << 4) -#define RT5631_DMIC_CLK_CTRL_TO_32FS (0x2 << 4) - -/* Microphone Input Volume(0x26) */ -#define RT5631_MONO_DIFF_INPUT_SHIFT 15 - -/* Speaker Mixer Control(0x28) */ -#define RT5631_M_RECMIXER_L_TO_SPKMIXER_L (0x1 << 15) -#define RT5631_M_RECMIXL_SPKMIXL_BIT 15 -#define RT5631_M_MIC1_P_TO_SPKMIXER_L (0x1 << 14) -#define RT5631_M_MIC1P_SPKMIXL_BIT 14 -#define RT5631_M_DAC_L_TO_SPKMIXER_L (0x1 << 13) -#define RT5631_M_DACL_SPKMIXL_BIT 13 -#define RT5631_M_OUTMIXER_L_TO_SPKMIXER_L (0x1 << 12) -#define RT5631_M_OUTMIXL_SPKMIXL_BIT 12 - -#define RT5631_M_RECMIXER_R_TO_SPKMIXER_R (0x1 << 7) -#define RT5631_M_RECMIXR_SPKMIXR_BIT 7 -#define RT5631_M_MIC2_P_TO_SPKMIXER_R (0x1 << 6) -#define RT5631_M_MIC2P_SPKMIXR_BIT 6 -#define RT5631_M_DAC_R_TO_SPKMIXER_R (0x1 << 5) -#define RT5631_M_DACR_SPKMIXR_BIT 5 -#define RT5631_M_OUTMIXER_R_TO_SPKMIXER_R (0x1 << 4) -#define RT5631_M_OUTMIXR_SPKMIXR_BIT 4 - -/* Speaker/Mono Output Control(0x2A) */ -#define RT5631_M_SPKVOL_L_TO_SPOL_MIXER (0x1 << 15) -#define RT5631_M_SPKVOLL_SPOLMIX_BIT 15 -#define RT5631_M_SPKVOL_R_TO_SPOL_MIXER (0x1 << 14) -#define RT5631_M_SPKVOLR_SPOLMIX_BIT 14 -#define RT5631_M_SPKVOL_L_TO_SPOR_MIXER (0x1 << 13) -#define RT5631_M_SPKVOLL_SPORMIX_BIT 13 -#define RT5631_M_SPKVOL_R_TO_SPOR_MIXER (0x1 << 12) -#define RT5631_M_SPKVOLR_SPORMIX_BIT 12 -#define RT5631_M_OUTVOL_L_TO_MONOMIXER (0x1 << 11) -#define RT5631_M_OUTVOLL_MONOMIX_BIT 11 -#define RT5631_M_OUTVOL_R_TO_MONOMIXER (0x1 << 10) -#define RT5631_M_OUTVOLR_MONOMIX_BIT 10 - -/* Speaker/Mono/HP Output Control(0x2C) */ -#define RT5631_SPK_L_MUX_SEL_MASK (0x3 << 14) -#define RT5631_SPK_L_MUX_SEL_SPKMIXER_L (0x0 << 14) -#define RT5631_SPK_L_MUX_SEL_MONO_IN (0x1 << 14) -#define RT5631_SPK_L_MUX_SEL_DAC_L (0x3 << 14) -#define RT5631_SPK_L_MUX_SEL_SHIFT 14 - -#define RT5631_SPK_R_MUX_SEL_MASK (0x3 << 10) -#define RT5631_SPK_R_MUX_SEL_SPKMIXER_R (0x0 << 10) -#define RT5631_SPK_R_MUX_SEL_MONO_IN (0x1 << 10) -#define RT5631_SPK_R_MUX_SEL_DAC_R (0x3 << 10) -#define RT5631_SPK_R_MUX_SEL_SHIFT 10 - -#define RT5631_MONO_MUX_SEL_MASK (0x3 << 6) -#define RT5631_MONO_MUX_SEL_MONOMIXER (0x0 << 6) -#define RT5631_MONO_MUX_SEL_MONO_IN (0x1 << 6) -#define RT5631_MONO_MUX_SEL_SHIFT 6 - -#define RT5631_HP_L_MUX_SEL_MASK (0x1 << 3) -#define RT5631_HP_L_MUX_SEL_HPVOL_L (0x0 << 3) -#define RT5631_HP_L_MUX_SEL_DAC_L (0x1 << 3) -#define RT5631_HP_L_MUX_SEL_SHIFT 3 - -#define RT5631_HP_R_MUX_SEL_MASK (0x1 << 2) -#define RT5631_HP_R_MUX_SEL_HPVOL_R (0x0 << 2) -#define RT5631_HP_R_MUX_SEL_DAC_R (0x1 << 2) -#define RT5631_HP_R_MUX_SEL_SHIFT 2 - -/* Stereo I2S Serial Data Port Control(0x34) */ -#define RT5631_SDP_MODE_SEL_MASK (0x1 << 15) -#define RT5631_SDP_MODE_SEL_MASTER (0x0 << 15) -#define RT5631_SDP_MODE_SEL_SLAVE (0x1 << 15) - -#define RT5631_SDP_ADC_CPS_SEL_MASK (0x3 << 10) -#define RT5631_SDP_ADC_CPS_SEL_OFF (0x0 << 10) -#define RT5631_SDP_ADC_CPS_SEL_U_LAW (0x1 << 10) -#define RT5631_SDP_ADC_CPS_SEL_A_LAW (0x2 << 10) - -#define RT5631_SDP_DAC_CPS_SEL_MASK (0x3 << 8) -#define RT5631_SDP_DAC_CPS_SEL_OFF (0x0 << 8) -#define RT5631_SDP_DAC_CPS_SEL_U_LAW (0x1 << 8) -#define RT5631_SDP_DAC_CPS_SEL_A_LAW (0x2 << 8) -/* 0:Normal 1:Invert */ -#define RT5631_SDP_I2S_BCLK_POL_CTRL (0x1 << 7) -/* 0:Normal 1:Invert */ -#define RT5631_SDP_DAC_R_INV (0x1 << 6) -/* 0:ADC data appear at left phase of LRCK - * 1:ADC data appear at right phase of LRCK - */ -#define RT5631_SDP_ADC_DATA_L_R_SWAP (0x1 << 5) -/* 0:DAC data appear at left phase of LRCK - * 1:DAC data appear at right phase of LRCK - */ -#define RT5631_SDP_DAC_DATA_L_R_SWAP (0x1 << 4) - -/* Data Length Slection */ -#define RT5631_SDP_I2S_DL_MASK (0x3 << 2) -#define RT5631_SDP_I2S_DL_16 (0x0 << 2) -#define RT5631_SDP_I2S_DL_20 (0x1 << 2) -#define RT5631_SDP_I2S_DL_24 (0x2 << 2) -#define RT5631_SDP_I2S_DL_8 (0x3 << 2) - -/* PCM Data Format Selection */ -#define RT5631_SDP_I2S_DF_MASK (0x3) -#define RT5631_SDP_I2S_DF_I2S (0x0) -#define RT5631_SDP_I2S_DF_LEFT (0x1) -#define RT5631_SDP_I2S_DF_PCM_A (0x2) -#define RT5631_SDP_I2S_DF_PCM_B (0x3) - -/* Stereo AD/DA Clock Control(0x38h) */ -#define RT5631_I2S_PRE_DIV_MASK (0x7 << 13) -#define RT5631_I2S_PRE_DIV_1 (0x0 << 13) -#define RT5631_I2S_PRE_DIV_2 (0x1 << 13) -#define RT5631_I2S_PRE_DIV_4 (0x2 << 13) -#define RT5631_I2S_PRE_DIV_8 (0x3 << 13) -#define RT5631_I2S_PRE_DIV_16 (0x4 << 13) -#define RT5631_I2S_PRE_DIV_32 (0x5 << 13) -/* CLOCK RELATIVE OF BCLK AND LCRK */ -#define RT5631_I2S_LRCK_SEL_N_BCLK_MASK (0x1 << 12) -#define RT5631_I2S_LRCK_SEL_64_BCLK (0x0 << 12) /* 64FS */ -#define RT5631_I2S_LRCK_SEL_32_BCLK (0x1 << 12) /* 32FS */ - -#define RT5631_DAC_OSR_SEL_MASK (0x3 << 10) -#define RT5631_DAC_OSR_SEL_128FS (0x3 << 10) -#define RT5631_DAC_OSR_SEL_64FS (0x3 << 10) -#define RT5631_DAC_OSR_SEL_32FS (0x3 << 10) -#define RT5631_DAC_OSR_SEL_16FS (0x3 << 10) - -#define RT5631_ADC_OSR_SEL_MASK (0x3 << 8) -#define RT5631_ADC_OSR_SEL_128FS (0x3 << 8) -#define RT5631_ADC_OSR_SEL_64FS (0x3 << 8) -#define RT5631_ADC_OSR_SEL_32FS (0x3 << 8) -#define RT5631_ADC_OSR_SEL_16FS (0x3 << 8) - -#define RT5631_ADDA_FILTER_CLK_SEL_256FS (0 << 7) /* 256FS */ -#define RT5631_ADDA_FILTER_CLK_SEL_384FS (1 << 7) /* 384FS */ - -/* Power managment addition 1 (0x3A) */ -#define RT5631_PWR_MAIN_I2S_EN (0x1 << 15) -#define RT5631_PWR_MAIN_I2S_BIT 15 -#define RT5631_PWR_CLASS_D (0x1 << 12) -#define RT5631_PWR_CLASS_D_BIT 12 -#define RT5631_PWR_ADC_L_CLK (0x1 << 11) -#define RT5631_PWR_ADC_L_CLK_BIT 11 -#define RT5631_PWR_ADC_R_CLK (0x1 << 10) -#define RT5631_PWR_ADC_R_CLK_BIT 10 -#define RT5631_PWR_DAC_L_CLK (0x1 << 9) -#define RT5631_PWR_DAC_L_CLK_BIT 9 -#define RT5631_PWR_DAC_R_CLK (0x1 << 8) -#define RT5631_PWR_DAC_R_CLK_BIT 8 -#define RT5631_PWR_DAC_REF (0x1 << 7) -#define RT5631_PWR_DAC_REF_BIT 7 -#define RT5631_PWR_DAC_L_TO_MIXER (0x1 << 6) -#define RT5631_PWR_DAC_L_TO_MIXER_BIT 6 -#define RT5631_PWR_DAC_R_TO_MIXER (0x1 << 5) -#define RT5631_PWR_DAC_R_TO_MIXER_BIT 5 - -/* Power managment addition 2 (0x3B) */ -#define RT5631_PWR_OUTMIXER_L (0x1 << 15) -#define RT5631_PWR_OUTMIXER_L_BIT 15 -#define RT5631_PWR_OUTMIXER_R (0x1 << 14) -#define RT5631_PWR_OUTMIXER_R_BIT 14 -#define RT5631_PWR_SPKMIXER_L (0x1 << 13) -#define RT5631_PWR_SPKMIXER_L_BIT 13 -#define RT5631_PWR_SPKMIXER_R (0x1 << 12) -#define RT5631_PWR_SPKMIXER_R_BIT 12 -#define RT5631_PWR_RECMIXER_L (0x1 << 11) -#define RT5631_PWR_RECMIXER_L_BIT 11 -#define RT5631_PWR_RECMIXER_R (0x1 << 10) -#define RT5631_PWR_RECMIXER_R_BIT 10 -#define RT5631_PWR_MIC1_BOOT_GAIN (0x1 << 5) -#define RT5631_PWR_MIC1_BOOT_GAIN_BIT 5 -#define RT5631_PWR_MIC2_BOOT_GAIN (0x1 << 4) -#define RT5631_PWR_MIC2_BOOT_GAIN_BIT 4 -#define RT5631_PWR_MICBIAS1_VOL (0x1 << 3) -#define RT5631_PWR_MICBIAS1_VOL_BIT 3 -#define RT5631_PWR_MICBIAS2_VOL (0x1 << 2) -#define RT5631_PWR_MICBIAS2_VOL_BIT 2 -#define RT5631_PWR_PLL1 (0x1 << 1) -#define RT5631_PWR_PLL1_BIT 1 -#define RT5631_PWR_PLL2 (0x1 << 0) -#define RT5631_PWR_PLL2_BIT 0 - -/* Power managment addition 3(0x3C) */ -#define RT5631_PWR_VREF (0x1 << 15) -#define RT5631_PWR_VREF_BIT 15 -#define RT5631_PWR_FAST_VREF_CTRL (0x1 << 14) -#define RT5631_PWR_FAST_VREF_CTRL_BIT 14 -#define RT5631_PWR_MAIN_BIAS (0x1 << 13) -#define RT5631_PWR_MAIN_BIAS_BIT 13 -#define RT5631_PWR_AXO1MIXER (0x1 << 11) -#define RT5631_PWR_AXO1MIXER_BIT 11 -#define RT5631_PWR_AXO2MIXER (0x1 << 10) -#define RT5631_PWR_AXO2MIXER_BIT 10 -#define RT5631_PWR_MONOMIXER (0x1 << 9) -#define RT5631_PWR_MONOMIXER_BIT 9 -#define RT5631_PWR_MONO_DEPOP_DIS (0x1 << 8) -#define RT5631_PWR_MONO_DEPOP_DIS_BIT 8 -#define RT5631_PWR_MONO_AMP_EN (0x1 << 7) -#define RT5631_PWR_MONO_AMP_EN_BIT 7 -#define RT5631_PWR_CHARGE_PUMP (0x1 << 4) -#define RT5631_PWR_CHARGE_PUMP_BIT 4 -#define RT5631_PWR_HP_L_AMP (0x1 << 3) -#define RT5631_PWR_HP_L_AMP_BIT 3 -#define RT5631_PWR_HP_R_AMP (0x1 << 2) -#define RT5631_PWR_HP_R_AMP_BIT 2 -#define RT5631_PWR_HP_DEPOP_DIS (0x1 << 1) -#define RT5631_PWR_HP_DEPOP_DIS_BIT 1 -#define RT5631_PWR_HP_AMP_DRIVING (0x1 << 0) -#define RT5631_PWR_HP_AMP_DRIVING_BIT 0 - -/* Power managment addition 4(0x3E) */ -#define RT5631_PWR_SPK_L_VOL (0x1 << 15) -#define RT5631_PWR_SPK_L_VOL_BIT 15 -#define RT5631_PWR_SPK_R_VOL (0x1 << 14) -#define RT5631_PWR_SPK_R_VOL_BIT 14 -#define RT5631_PWR_LOUT_VOL (0x1 << 13) -#define RT5631_PWR_LOUT_VOL_BIT 13 -#define RT5631_PWR_ROUT_VOL (0x1 << 12) -#define RT5631_PWR_ROUT_VOL_BIT 12 -#define RT5631_PWR_HP_L_OUT_VOL (0x1 << 11) -#define RT5631_PWR_HP_L_OUT_VOL_BIT 11 -#define RT5631_PWR_HP_R_OUT_VOL (0x1 << 10) -#define RT5631_PWR_HP_R_OUT_VOL_BIT 10 -#define RT5631_PWR_AXIL_IN_VOL (0x1 << 9) -#define RT5631_PWR_AXIL_IN_VOL_BIT 9 -#define RT5631_PWR_AXIR_IN_VOL (0x1 << 8) -#define RT5631_PWR_AXIR_IN_VOL_BIT 8 -#define RT5631_PWR_MONO_IN_P_VOL (0x1 << 7) -#define RT5631_PWR_MONO_IN_P_VOL_BIT 7 -#define RT5631_PWR_MONO_IN_N_VOL (0x1 << 6) -#define RT5631_PWR_MONO_IN_N_VOL_BIT 6 - -/* General Purpose Control Register(0x40) */ -#define RT5631_SPK_AMP_AUTO_RATIO_EN (0x1 << 15) - -#define RT5631_SPK_AMP_RATIO_CTRL_MASK (0x7 << 12) -#define RT5631_SPK_AMP_RATIO_CTRL_2_34 (0x0 << 12) /* 7.40DB */ -#define RT5631_SPK_AMP_RATIO_CTRL_1_99 (0x1 << 12) /* 5.99DB */ -#define RT5631_SPK_AMP_RATIO_CTRL_1_68 (0x2 << 12) /* 4.50DB */ -#define RT5631_SPK_AMP_RATIO_CTRL_1_56 (0x3 << 12) /* 3.86DB */ -#define RT5631_SPK_AMP_RATIO_CTRL_1_44 (0x4 << 12) /* 3.16DB */ -#define RT5631_SPK_AMP_RATIO_CTRL_1_27 (0x5 << 12) /* 2.10DB */ -#define RT5631_SPK_AMP_RATIO_CTRL_1_09 (0x6 << 12) /* 0.80DB */ -#define RT5631_SPK_AMP_RATIO_CTRL_1_00 (0x7 << 12) /* 0.00DB */ -#define RT5631_SPK_AMP_RATIO_CTRL_SHIFT 12 - -#define RT5631_STEREO_DAC_HI_PASS_FILT_EN (0x1 << 11) -#define RT5631_STEREO_ADC_HI_PASS_FILT_EN (0x1 << 10) -/* Select ADC Wind Filter Clock type */ -#define RT5631_ADC_WIND_FILT_MASK (0x3 << 4) -#define RT5631_ADC_WIND_FILT_8_16_32K (0x0 << 4) /*8/16/32k*/ -#define RT5631_ADC_WIND_FILT_11_22_44K (0x1 << 4) /*11/22/44k*/ -#define RT5631_ADC_WIND_FILT_12_24_48K (0x2 << 4) /*12/24/48k*/ -#define RT5631_ADC_WIND_FILT_EN (0x1 << 3) -/* SelectADC Wind Filter Corner Frequency */ -#define RT5631_ADC_WIND_CNR_FREQ_MASK (0x7 << 0) -#define RT5631_ADC_WIND_CNR_FREQ_82_113_122 (0x0 << 0) /* 82/113/122 Hz */ -#define RT5631_ADC_WIND_CNR_FREQ_102_141_153 (0x1 << 0) /* 102/141/153 Hz */ -#define RT5631_ADC_WIND_CNR_FREQ_131_180_156 (0x2 << 0) /* 131/180/156 Hz */ -#define RT5631_ADC_WIND_CNR_FREQ_163_225_245 (0x3 << 0) /* 163/225/245 Hz */ -#define RT5631_ADC_WIND_CNR_FREQ_204_281_306 (0x4 << 0) /* 204/281/306 Hz */ -#define RT5631_ADC_WIND_CNR_FREQ_261_360_392 (0x5 << 0) /* 261/360/392 Hz */ -#define RT5631_ADC_WIND_CNR_FREQ_327_450_490 (0x6 << 0) /* 327/450/490 Hz */ -#define RT5631_ADC_WIND_CNR_FREQ_408_563_612 (0x7 << 0) /* 408/563/612 Hz */ - -/* Global Clock Control Register(0x42) */ -#define RT5631_SYSCLK_SOUR_SEL_MASK (0x3 << 14) -#define RT5631_SYSCLK_SOUR_SEL_MCLK (0x0 << 14) -#define RT5631_SYSCLK_SOUR_SEL_PLL (0x1 << 14) -#define RT5631_SYSCLK_SOUR_SEL_PLL_TCK (0x2 << 14) - -#define RT5631_PLLCLK_SOUR_SEL_MASK (0x3 << 12) -#define RT5631_PLLCLK_SOUR_SEL_MCLK (0x0 << 12) -#define RT5631_PLLCLK_SOUR_SEL_BCLK (0x1 << 12) -#define RT5631_PLLCLK_SOUR_SEL_VBCLK (0x2 << 12) - -#define RT5631_PLLCLK_PRE_DIV1 (0x0 << 11) -#define RT5631_PLLCLK_PRE_DIV2 (0x1 << 11) - -/* PLL Control(0x44) */ -#define RT5631_PLL_CTRL_M_VAL(m) ((m)&0xf) -#define RT5631_PLL_CTRL_K_VAL(k) (((k)&0x7) << 4) -#define RT5631_PLL_CTRL_N_VAL(n) (((n)&0xff) << 8) - -/* Internal Status and IRQ Control2(0x4A) */ -#define RT5631_ADC_DATA_SEL_MASK (0x3 << 14) -#define RT5631_ADC_DATA_SEL_Disable (0x0 << 14) -#define RT5631_ADC_DATA_SEL_MIC1 (0x1 << 14) -#define RT5631_ADC_DATA_SEL_MIC1_SHIFT 14 -#define RT5631_ADC_DATA_SEL_MIC2 (0x2 << 14) -#define RT5631_ADC_DATA_SEL_MIC2_SHIFT 15 -#define RT5631_ADC_DATA_SEL_STO (0x3 << 14) -#define RT5631_ADC_DATA_SEL_SHIFT 14 - -/* GPIO Pin Configuration(0x4C) */ -#define RT5631_GPIO_PIN_FUN_SEL_MASK (0x1 << 15) -#define RT5631_GPIO_PIN_FUN_SEL_IRQ (0x1 << 15) -#define RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC (0x0 << 15) - -#define RT5631_GPIO_DMIC_FUN_SEL_MASK (0x1 << 3) -#define RT5631_GPIO_DMIC_FUN_SEL_DIMC (0x1 << 3) -#define RT5631_GPIO_DMIC_FUN_SEL_GPIO (0x0 << 3) - -#define RT5631_GPIO_PIN_CON_MASK (0x1 << 2) -#define RT5631_GPIO_PIN_SET_INPUT (0x0 << 2) -#define RT5631_GPIO_PIN_SET_OUTPUT (0x1 << 2) - -/* De-POP function Control 1(0x54) */ -#define RT5631_POW_ON_SOFT_GEN (0x1 << 15) -#define RT5631_EN_MUTE_UNMUTE_DEPOP (0x1 << 14) -#define RT5631_EN_DEPOP2_FOR_HP (0x1 << 7) -/* Power Down HPAMP_L Starts Up Signal */ -#define RT5631_PD_HPAMP_L_ST_UP (0x1 << 5) -/* Power Down HPAMP_R Starts Up Signal */ -#define RT5631_PD_HPAMP_R_ST_UP (0x1 << 4) -/* Enable left HP mute/unmute depop */ -#define RT5631_EN_HP_L_M_UN_MUTE_DEPOP (0x1 << 1) -/* Enable right HP mute/unmute depop */ -#define RT5631_EN_HP_R_M_UN_MUTE_DEPOP (0x1 << 0) - -/* De-POP Fnction Control(0x56) */ -#define RT5631_EN_ONE_BIT_DEPOP (0x1 << 15) -#define RT5631_EN_CAP_FREE_DEPOP (0x1 << 14) - -/* Jack Detect Control Register(0x5A) */ -#define RT5631_JD_USE_MASK (0x3 << 14) -#define RT5631_JD_USE_JD2 (0x3 << 14) -#define RT5631_JD_USE_JD1 (0x2 << 14) -#define RT5631_JD_USE_GPIO (0x1 << 14) -#define RT5631_JD_OFF (0x0 << 14) -/* JD trigger enable for HP */ -#define RT5631_JD_HP_EN (0x1 << 11) -#define RT5631_JD_HP_TRI_MASK (0x1 << 10) -#define RT5631_JD_HP_TRI_HI (0x1 << 10) -#define RT5631_JD_HP_TRI_LO (0x1 << 10) -/* JD trigger enable for speaker LP/LN */ -#define RT5631_JD_SPK_L_EN (0x1 << 9) -#define RT5631_JD_SPK_L_TRI_MASK (0x1 << 8) -#define RT5631_JD_SPK_L_TRI_HI (0x1 << 8) -#define RT5631_JD_SPK_L_TRI_LO (0x0 << 8) -/* JD trigger enable for speaker RP/RN */ -#define RT5631_JD_SPK_R_EN (0x1 << 7) -#define RT5631_JD_SPK_R_TRI_MASK (0x1 << 6) -#define RT5631_JD_SPK_R_TRI_HI (0x1 << 6) -#define RT5631_JD_SPK_R_TRI_LO (0x0 << 6) -/* JD trigger enable for monoout */ -#define RT5631_JD_MONO_EN (0x1 << 5) -#define RT5631_JD_MONO_TRI_MASK (0x1 << 4) -#define RT5631_JD_MONO_TRI_HI (0x1 << 4) -#define RT5631_JD_MONO_TRI_LO (0x0 << 4) -/* JD trigger enable for Lout */ -#define RT5631_JD_AUX_1_EN (0x1 << 3) -#define RT5631_JD_AUX_1_MASK (0x1 << 2) -#define RT5631_JD_AUX_1_TRI_HI (0x1 << 2) -#define RT5631_JD_AUX_1_TRI_LO (0x0 << 2) -/* JD trigger enable for Rout */ -#define RT5631_JD_AUX_2_EN (0x1 << 1) -#define RT5631_JD_AUX_2_MASK (0x1 << 0) -#define RT5631_JD_AUX_2_TRI_HI (0x1 << 0) -#define RT5631_JD_AUX_2_TRI_LO (0x0 << 0) - -/* ALC CONTROL 1(0x64) */ -#define RT5631_ALC_ATTACK_RATE_MASK (0x1F << 8) -#define RT5631_ALC_RECOVERY_RATE_MASK (0x1F << 0) - -/* ALC CONTROL 2(0x65) */ -/* select Compensation gain for Noise gate function */ -#define RT5631_ALC_COM_NOISE_GATE_MASK (0xF << 0) - -/* ALC CONTROL 3(0x66) */ -#define RT5631_ALC_FUN_MASK (0x3 << 14) -#define RT5631_ALC_FUN_DIS (0x0 << 14) -#define RT5631_ALC_ENA_DAC_PATH (0x1 << 14) -#define RT5631_ALC_ENA_ADC_PATH (0x3 << 14) -#define RT5631_ALC_PARA_UPDATE (0x1 << 13) -#define RT5631_ALC_LIMIT_LEVEL_MASK (0x1F << 8) -#define RT5631_ALC_NOISE_GATE_FUN_MASK (0x1 << 7) -#define RT5631_ALC_NOISE_GATE_FUN_DIS (0x0 << 7) -#define RT5631_ALC_NOISE_GATE_FUN_ENA (0x1 << 7) -/* ALC noise gate hold data function */ -#define RT5631_ALC_NOISE_GATE_H_D_MASK (0x1 << 6) -#define RT5631_ALC_NOISE_GATE_H_D_DIS (0x0 << 6) -#define RT5631_ALC_NOISE_GATE_H_D_ENA (0x1 << 6) - -/* Psedueo Stereo & Spatial Effect Block Control(0x68) */ -#define RT5631_SPATIAL_CTRL_EN (0x1 << 15) -#define RT5631_ALL_PASS_FILTER_EN (0x1 << 14) -#define RT5631_PSEUDO_STEREO_EN (0x1 << 13) -#define RT5631_STEREO_EXPENSION_EN (0x1 << 12) -/* 3D gain parameter */ -#define RT5631_GAIN_3D_PARA_MASK (0x3 << 6) -#define RT5631_GAIN_3D_PARA_1_00 (0x0 << 6) /* 3D gain 1.0 */ -#define RT5631_GAIN_3D_PARA_1_50 (0x1 << 6) /* 3D gain 1.5 */ -#define RT5631_GAIN_3D_PARA_2_00 (0x2 << 6) /* 3D gain 2.0 */ -/* 3D ratio parameter */ -#define RT5631_RATIO_3D_MASK (0x3 << 4) -#define RT5631_RATIO_3D_0_0 (0x0 << 4) /* 3D ratio 0.0 */ -#define RT5631_RATIO_3D_0_66 (0x1 << 4) /* 3D ratio 0.66 */ -#define RT5631_RATIO_3D_1_0 (0x2 << 4) /* 3D ratio 1.0 */ -/* select samplerate for all pass filter */ -#define RT5631_APF_FUN_SLE_MASK (0x3 << 0) -#define RT5631_APF_FUN_SEL_48K (0x3 << 0) -#define RT5631_APF_FUN_SEL_44_1K (0x2 << 0) -#define RT5631_APF_FUN_SEL_32K (0x1 << 0) -#define RT5631_APF_FUN_DIS (0x0 << 0) - -/* EQ CONTROL 1(0x6E) */ -#define RT5631_HW_EQ_PATH_SEL_MASK (0x1 << 15) -#define RT5631_HW_EQ_PATH_SEL_DAC (0x0 << 15) -#define RT5631_HW_EQ_PATH_SEL_ADC (0x1 << 15) -#define RT5631_HW_EQ_UPDATE_CTRL (0x1 << 14) - -#define RT5631_EN_HW_EQ_HPF2 (0x1 << 5) -#define RT5631_EN_HW_EQ_HPF1 (0x1 << 4) -#define RT5631_EN_HW_EQ_BP3 (0x1 << 3) -#define RT5631_EN_HW_EQ_BP2 (0x1 << 2) -#define RT5631_EN_HW_EQ_BP1 (0x1 << 1) -#define RT5631_EN_HW_EQ_LPF (0x1 << 0) - - -#endif /* __RTCODEC5631_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/sgtl5000.c b/ANDROID_3.4.5/sound/soc/codecs/sgtl5000.c deleted file mode 100644 index 8e92fb88..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/sgtl5000.c +++ /dev/null @@ -1,1468 +0,0 @@ -/* - * sgtl5000.c -- SGTL5000 ALSA SoC Audio driver - * - * Copyright 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sgtl5000.h" - -#define SGTL5000_DAP_REG_OFFSET 0x0100 -#define SGTL5000_MAX_REG_OFFSET 0x013A - -/* default value of sgtl5000 registers */ -static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] = { - [SGTL5000_CHIP_CLK_CTRL] = 0x0008, - [SGTL5000_CHIP_I2S_CTRL] = 0x0010, - [SGTL5000_CHIP_SSS_CTRL] = 0x0008, - [SGTL5000_CHIP_DAC_VOL] = 0x3c3c, - [SGTL5000_CHIP_PAD_STRENGTH] = 0x015f, - [SGTL5000_CHIP_ANA_HP_CTRL] = 0x1818, - [SGTL5000_CHIP_ANA_CTRL] = 0x0111, - [SGTL5000_CHIP_LINE_OUT_VOL] = 0x0404, - [SGTL5000_CHIP_ANA_POWER] = 0x7060, - [SGTL5000_CHIP_PLL_CTRL] = 0x5000, - [SGTL5000_DAP_BASS_ENHANCE] = 0x0040, - [SGTL5000_DAP_BASS_ENHANCE_CTRL] = 0x051f, - [SGTL5000_DAP_SURROUND] = 0x0040, - [SGTL5000_DAP_EQ_BASS_BAND0] = 0x002f, - [SGTL5000_DAP_EQ_BASS_BAND1] = 0x002f, - [SGTL5000_DAP_EQ_BASS_BAND2] = 0x002f, - [SGTL5000_DAP_EQ_BASS_BAND3] = 0x002f, - [SGTL5000_DAP_EQ_BASS_BAND4] = 0x002f, - [SGTL5000_DAP_MAIN_CHAN] = 0x8000, - [SGTL5000_DAP_AVC_CTRL] = 0x0510, - [SGTL5000_DAP_AVC_THRESHOLD] = 0x1473, - [SGTL5000_DAP_AVC_ATTACK] = 0x0028, - [SGTL5000_DAP_AVC_DECAY] = 0x0050, -}; - -/* regulator supplies for sgtl5000, VDDD is an optional external supply */ -enum sgtl5000_regulator_supplies { - VDDA, - VDDIO, - VDDD, - SGTL5000_SUPPLY_NUM -}; - -/* vddd is optional supply */ -static const char *supply_names[SGTL5000_SUPPLY_NUM] = { - "VDDA", - "VDDIO", - "VDDD" -}; - -#define LDO_CONSUMER_NAME "VDDD_LDO" -#define LDO_VOLTAGE 1200000 - -static struct regulator_consumer_supply ldo_consumer[] = { - REGULATOR_SUPPLY(LDO_CONSUMER_NAME, NULL), -}; - -static struct regulator_init_data ldo_init_data = { - .constraints = { - .min_uV = 850000, - .max_uV = 1600000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = &ldo_consumer[0], -}; - -/* - * sgtl5000 internal ldo regulator, - * enabled when VDDD not provided - */ -struct ldo_regulator { - struct regulator_desc desc; - struct regulator_dev *dev; - int voltage; - void *codec_data; - bool enabled; -}; - -/* sgtl5000 private structure in codec */ -struct sgtl5000_priv { - int sysclk; /* sysclk rate */ - int master; /* i2s master or not */ - int fmt; /* i2s data format */ - struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM]; - struct ldo_regulator *ldo; -}; - -/* - * mic_bias power on/off share the same register bits with - * output impedance of mic bias, when power on mic bias, we - * need reclaim it to impedance value. - * 0x0 = Powered off - * 0x1 = 2Kohm - * 0x2 = 4Kohm - * 0x3 = 8Kohm - */ -static int mic_bias_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - switch (event) { - case SND_SOC_DAPM_POST_PMU: - /* change mic bias resistor to 4Kohm */ - snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, - SGTL5000_BIAS_R_MASK, - SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT); - break; - - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, - SGTL5000_BIAS_R_MASK, 0); - break; - } - return 0; -} - -/* - * As manual described, ADC/DAC only works when VAG powerup, - * So enabled VAG before ADC/DAC up. - * In power down case, we need wait 400ms when vag fully ramped down. - */ -static int power_vag_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); - break; - - case SND_SOC_DAPM_POST_PMD: - snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_VAG_POWERUP, 0); - msleep(400); - break; - default: - break; - } - - return 0; -} - -/* input sources for ADC */ -static const char *adc_mux_text[] = { - "MIC_IN", "LINE_IN" -}; - -static const struct soc_enum adc_enum = -SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text); - -static const struct snd_kcontrol_new adc_mux = -SOC_DAPM_ENUM("Capture Mux", adc_enum); - -/* input sources for DAC */ -static const char *dac_mux_text[] = { - "DAC", "LINE_IN" -}; - -static const struct soc_enum dac_enum = -SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text); - -static const struct snd_kcontrol_new dac_mux = -SOC_DAPM_ENUM("Headphone Mux", dac_enum); - -static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("LINE_IN"), - SND_SOC_DAPM_INPUT("MIC_IN"), - - SND_SOC_DAPM_OUTPUT("HP_OUT"), - SND_SOC_DAPM_OUTPUT("LINE_OUT"), - - SND_SOC_DAPM_MICBIAS_E("Mic Bias", SGTL5000_CHIP_MIC_CTRL, 8, 0, - mic_bias_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0), - - SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux), - SND_SOC_DAPM_MUX("Headphone Mux", SND_SOC_NOPM, 0, 0, &dac_mux), - - /* aif for i2s input */ - SND_SOC_DAPM_AIF_IN("AIFIN", "Playback", - 0, SGTL5000_CHIP_DIG_POWER, - 0, 0), - - /* aif for i2s output */ - SND_SOC_DAPM_AIF_OUT("AIFOUT", "Capture", - 0, SGTL5000_CHIP_DIG_POWER, - 1, 0), - - SND_SOC_DAPM_SUPPLY("VAG_POWER", SGTL5000_CHIP_ANA_POWER, 7, 0, - power_vag_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), - SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), -}; - -/* routes for sgtl5000 */ -static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = { - {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */ - {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */ - - {"ADC", NULL, "VAG_POWER"}, - {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */ - {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */ - - {"DAC", NULL, "VAG_POWER"}, - {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */ - {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ - {"LO", NULL, "DAC"}, /* dac --> line_out */ - - {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ - {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ - - {"LINE_OUT", NULL, "LO"}, - {"HP_OUT", NULL, "HP"}, -}; - -/* custom function to fetch info of PCM playback volume */ -static int dac_info_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xfc - 0x3c; - return 0; -} - -/* - * custom function to get of PCM playback volume - * - * dac volume register - * 15-------------8-7--------------0 - * | R channel vol | L channel vol | - * ------------------------------- - * - * PCM volume with 0.5017 dB steps from 0 to -90 dB - * - * register values map to dB - * 0x3B and less = Reserved - * 0x3C = 0 dB - * 0x3D = -0.5 dB - * 0xF0 = -90 dB - * 0xFC and greater = Muted - * - * register value map to userspace value - * - * register value 0x3c(0dB) 0xf0(-90dB)0xfc - * ------------------------------ - * userspace value 0xc0 0 - */ -static int dac_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg; - int l; - int r; - - reg = snd_soc_read(codec, SGTL5000_CHIP_DAC_VOL); - - /* get left channel volume */ - l = (reg & SGTL5000_DAC_VOL_LEFT_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT; - - /* get right channel volume */ - r = (reg & SGTL5000_DAC_VOL_RIGHT_MASK) >> SGTL5000_DAC_VOL_RIGHT_SHIFT; - - /* make sure value fall in (0x3c,0xfc) */ - l = clamp(l, 0x3c, 0xfc); - r = clamp(r, 0x3c, 0xfc); - - /* invert it and map to userspace value */ - l = 0xfc - l; - r = 0xfc - r; - - ucontrol->value.integer.value[0] = l; - ucontrol->value.integer.value[1] = r; - - return 0; -} - -/* - * custom function to put of PCM playback volume - * - * dac volume register - * 15-------------8-7--------------0 - * | R channel vol | L channel vol | - * ------------------------------- - * - * PCM volume with 0.5017 dB steps from 0 to -90 dB - * - * register values map to dB - * 0x3B and less = Reserved - * 0x3C = 0 dB - * 0x3D = -0.5 dB - * 0xF0 = -90 dB - * 0xFC and greater = Muted - * - * userspace value map to register value - * - * userspace value 0xc0 0 - * ------------------------------ - * register value 0x3c(0dB) 0xf0(-90dB)0xfc - */ -static int dac_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg; - int l; - int r; - - l = ucontrol->value.integer.value[0]; - r = ucontrol->value.integer.value[1]; - - /* make sure userspace volume fall in (0, 0xfc-0x3c) */ - l = clamp(l, 0, 0xfc - 0x3c); - r = clamp(r, 0, 0xfc - 0x3c); - - /* invert it, get the value can be set to register */ - l = 0xfc - l; - r = 0xfc - r; - - /* shift to get the register value */ - reg = l << SGTL5000_DAC_VOL_LEFT_SHIFT | - r << SGTL5000_DAC_VOL_RIGHT_SHIFT; - - snd_soc_write(codec, SGTL5000_CHIP_DAC_VOL, reg); - - return 0; -} - -static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0); - -/* tlv for mic gain, 0db 20db 30db 40db */ -static const unsigned int mic_gain_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), - 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0), -}; - -/* tlv for hp volume, -51.5db to 12.0db, step .5db */ -static const DECLARE_TLV_DB_SCALE(headphone_volume, -5150, 50, 0); - -static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { - /* SOC_DOUBLE_S8_TLV with invert */ - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = dac_info_volsw, - .get = dac_get_volsw, - .put = dac_put_volsw, - }, - - SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0), - SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)", - SGTL5000_CHIP_ANA_ADC_CTRL, - 8, 2, 0, capture_6db_attenuate), - SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), - - SOC_DOUBLE_TLV("Headphone Playback Volume", - SGTL5000_CHIP_ANA_HP_CTRL, - 0, 8, - 0x7f, 1, - headphone_volume), - SOC_SINGLE("Headphone Playback ZC Switch", SGTL5000_CHIP_ANA_CTRL, - 5, 1, 0), - - SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL, - 0, 4, 0, mic_gain_tlv), -}; - -/* mute the codec used by alsa core */ -static int sgtl5000_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 adcdac_ctrl = SGTL5000_DAC_MUTE_LEFT | SGTL5000_DAC_MUTE_RIGHT; - - snd_soc_update_bits(codec, SGTL5000_CHIP_ADCDAC_CTRL, - adcdac_ctrl, mute ? adcdac_ctrl : 0); - - return 0; -} - -/* set codec format */ -static int sgtl5000_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - u16 i2sctl = 0; - - sgtl5000->master = 0; - /* - * i2s clock and frame master setting. - * ONLY support: - * - clock and frame slave, - * - clock and frame master - */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBM_CFM: - i2sctl |= SGTL5000_I2S_MASTER; - sgtl5000->master = 1; - break; - default: - return -EINVAL; - } - - /* setting i2s data format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - i2sctl |= SGTL5000_I2S_MODE_PCM; - break; - case SND_SOC_DAIFMT_DSP_B: - i2sctl |= SGTL5000_I2S_MODE_PCM; - i2sctl |= SGTL5000_I2S_LRALIGN; - break; - case SND_SOC_DAIFMT_I2S: - i2sctl |= SGTL5000_I2S_MODE_I2S_LJ; - break; - case SND_SOC_DAIFMT_RIGHT_J: - i2sctl |= SGTL5000_I2S_MODE_RJ; - i2sctl |= SGTL5000_I2S_LRPOL; - break; - case SND_SOC_DAIFMT_LEFT_J: - i2sctl |= SGTL5000_I2S_MODE_I2S_LJ; - i2sctl |= SGTL5000_I2S_LRALIGN; - break; - default: - return -EINVAL; - } - - sgtl5000->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; - - /* Clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - i2sctl |= SGTL5000_I2S_SCLK_INV; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, SGTL5000_CHIP_I2S_CTRL, i2sctl); - - return 0; -} - -/* set codec sysclk */ -static int sgtl5000_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case SGTL5000_SYSCLK: - sgtl5000->sysclk = freq; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * set clock according to i2s frame clock, - * sgtl5000 provide 2 clock sources. - * 1. sys_mclk. sample freq can only configure to - * 1/256, 1/384, 1/512 of sys_mclk. - * 2. pll. can derive any audio clocks. - * - * clock setting rules: - * 1. in slave mode, only sys_mclk can use. - * 2. as constraint by sys_mclk, sample freq should - * set to 32k, 44.1k and above. - * 3. using sys_mclk prefer to pll to save power. - */ -static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) -{ - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - int clk_ctl = 0; - int sys_fs; /* sample freq */ - - /* - * sample freq should be divided by frame clock, - * if frame clock lower than 44.1khz, sample feq should set to - * 32khz or 44.1khz. - */ - switch (frame_rate) { - case 8000: - case 16000: - sys_fs = 32000; - break; - case 11025: - case 22050: - sys_fs = 44100; - break; - default: - sys_fs = frame_rate; - break; - } - - /* set divided factor of frame clock */ - switch (sys_fs / frame_rate) { - case 4: - clk_ctl |= SGTL5000_RATE_MODE_DIV_4 << SGTL5000_RATE_MODE_SHIFT; - break; - case 2: - clk_ctl |= SGTL5000_RATE_MODE_DIV_2 << SGTL5000_RATE_MODE_SHIFT; - break; - case 1: - clk_ctl |= SGTL5000_RATE_MODE_DIV_1 << SGTL5000_RATE_MODE_SHIFT; - break; - default: - return -EINVAL; - } - - /* set the sys_fs according to frame rate */ - switch (sys_fs) { - case 32000: - clk_ctl |= SGTL5000_SYS_FS_32k << SGTL5000_SYS_FS_SHIFT; - break; - case 44100: - clk_ctl |= SGTL5000_SYS_FS_44_1k << SGTL5000_SYS_FS_SHIFT; - break; - case 48000: - clk_ctl |= SGTL5000_SYS_FS_48k << SGTL5000_SYS_FS_SHIFT; - break; - case 96000: - clk_ctl |= SGTL5000_SYS_FS_96k << SGTL5000_SYS_FS_SHIFT; - break; - default: - dev_err(codec->dev, "frame rate %d not supported\n", - frame_rate); - return -EINVAL; - } - - /* - * calculate the divider of mclk/sample_freq, - * factor of freq =96k can only be 256, since mclk in range (12m,27m) - */ - switch (sgtl5000->sysclk / sys_fs) { - case 256: - clk_ctl |= SGTL5000_MCLK_FREQ_256FS << - SGTL5000_MCLK_FREQ_SHIFT; - break; - case 384: - clk_ctl |= SGTL5000_MCLK_FREQ_384FS << - SGTL5000_MCLK_FREQ_SHIFT; - break; - case 512: - clk_ctl |= SGTL5000_MCLK_FREQ_512FS << - SGTL5000_MCLK_FREQ_SHIFT; - break; - default: - /* if mclk not satisify the divider, use pll */ - if (sgtl5000->master) { - clk_ctl |= SGTL5000_MCLK_FREQ_PLL << - SGTL5000_MCLK_FREQ_SHIFT; - } else { - dev_err(codec->dev, - "PLL not supported in slave mode\n"); - return -EINVAL; - } - } - - /* if using pll, please check manual 6.4.2 for detail */ - if ((clk_ctl & SGTL5000_MCLK_FREQ_MASK) == SGTL5000_MCLK_FREQ_PLL) { - u64 out, t; - int div2; - int pll_ctl; - unsigned int in, int_div, frac_div; - - if (sgtl5000->sysclk > 17000000) { - div2 = 1; - in = sgtl5000->sysclk / 2; - } else { - div2 = 0; - in = sgtl5000->sysclk; - } - if (sys_fs == 44100) - out = 180633600; - else - out = 196608000; - t = do_div(out, in); - int_div = out; - t *= 2048; - do_div(t, in); - frac_div = t; - pll_ctl = int_div << SGTL5000_PLL_INT_DIV_SHIFT | - frac_div << SGTL5000_PLL_FRAC_DIV_SHIFT; - - snd_soc_write(codec, SGTL5000_CHIP_PLL_CTRL, pll_ctl); - if (div2) - snd_soc_update_bits(codec, - SGTL5000_CHIP_CLK_TOP_CTRL, - SGTL5000_INPUT_FREQ_DIV2, - SGTL5000_INPUT_FREQ_DIV2); - else - snd_soc_update_bits(codec, - SGTL5000_CHIP_CLK_TOP_CTRL, - SGTL5000_INPUT_FREQ_DIV2, - 0); - - /* power up pll */ - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, - SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP); - } else { - /* power down pll */ - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, - 0); - } - - /* if using pll, clk_ctrl must be set after pll power up */ - snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl); - - return 0; -} - -/* - * Set PCM DAI bit size and sample rate. - * input: params_rate, params_fmt - */ -static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - int channels = params_channels(params); - int i2s_ctl = 0; - int stereo; - int ret; - - /* sysclk should already set */ - if (!sgtl5000->sysclk) { - dev_err(codec->dev, "%s: set sysclk first!\n", __func__); - return -EFAULT; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - stereo = SGTL5000_DAC_STEREO; - else - stereo = SGTL5000_ADC_STEREO; - - /* set mono to save power */ - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, stereo, - channels == 1 ? 0 : stereo); - - /* set codec clock base on lrclk */ - ret = sgtl5000_set_clock(codec, params_rate(params)); - if (ret) - return ret; - - /* set i2s data format */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J) - return -EINVAL; - i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT; - i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS << - SGTL5000_I2S_SCLKFREQ_SHIFT; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT; - i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << - SGTL5000_I2S_SCLKFREQ_SHIFT; - break; - case SNDRV_PCM_FORMAT_S24_LE: - i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT; - i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << - SGTL5000_I2S_SCLKFREQ_SHIFT; - break; - case SNDRV_PCM_FORMAT_S32_LE: - if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J) - return -EINVAL; - i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT; - i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << - SGTL5000_I2S_SCLKFREQ_SHIFT; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, - SGTL5000_I2S_DLEN_MASK | SGTL5000_I2S_SCLKFREQ_MASK, - i2s_ctl); - - return 0; -} - -#ifdef CONFIG_REGULATOR -static int ldo_regulator_is_enabled(struct regulator_dev *dev) -{ - struct ldo_regulator *ldo = rdev_get_drvdata(dev); - - return ldo->enabled; -} - -static int ldo_regulator_enable(struct regulator_dev *dev) -{ - struct ldo_regulator *ldo = rdev_get_drvdata(dev); - struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data; - int reg; - - if (ldo_regulator_is_enabled(dev)) - return 0; - - /* set regulator value firstly */ - reg = (1600 - ldo->voltage / 1000) / 50; - reg = clamp(reg, 0x0, 0xf); - - /* amend the voltage value, unit: uV */ - ldo->voltage = (1600 - reg * 50) * 1000; - - /* set voltage to register */ - snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, - SGTL5000_LINREG_VDDD_MASK, reg); - - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_LINEREG_D_POWERUP, - SGTL5000_LINEREG_D_POWERUP); - - /* when internal ldo enabled, simple digital power can be disabled */ - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_LINREG_SIMPLE_POWERUP, - 0); - - ldo->enabled = 1; - return 0; -} - -static int ldo_regulator_disable(struct regulator_dev *dev) -{ - struct ldo_regulator *ldo = rdev_get_drvdata(dev); - struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data; - - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_LINEREG_D_POWERUP, - 0); - - /* clear voltage info */ - snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, - SGTL5000_LINREG_VDDD_MASK, 0); - - ldo->enabled = 0; - - return 0; -} - -static int ldo_regulator_get_voltage(struct regulator_dev *dev) -{ - struct ldo_regulator *ldo = rdev_get_drvdata(dev); - - return ldo->voltage; -} - -static struct regulator_ops ldo_regulator_ops = { - .is_enabled = ldo_regulator_is_enabled, - .enable = ldo_regulator_enable, - .disable = ldo_regulator_disable, - .get_voltage = ldo_regulator_get_voltage, -}; - -static int ldo_regulator_register(struct snd_soc_codec *codec, - struct regulator_init_data *init_data, - int voltage) -{ - struct ldo_regulator *ldo; - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - - ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL); - - if (!ldo) { - dev_err(codec->dev, "failed to allocate ldo_regulator\n"); - return -ENOMEM; - } - - ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL); - if (!ldo->desc.name) { - kfree(ldo); - dev_err(codec->dev, "failed to allocate decs name memory\n"); - return -ENOMEM; - } - - ldo->desc.type = REGULATOR_VOLTAGE; - ldo->desc.owner = THIS_MODULE; - ldo->desc.ops = &ldo_regulator_ops; - ldo->desc.n_voltages = 1; - - ldo->codec_data = codec; - ldo->voltage = voltage; - - ldo->dev = regulator_register(&ldo->desc, codec->dev, - init_data, ldo, NULL); - if (IS_ERR(ldo->dev)) { - int ret = PTR_ERR(ldo->dev); - - dev_err(codec->dev, "failed to register regulator\n"); - kfree(ldo->desc.name); - kfree(ldo); - - return ret; - } - sgtl5000->ldo = ldo; - - return 0; -} - -static int ldo_regulator_remove(struct snd_soc_codec *codec) -{ - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - struct ldo_regulator *ldo = sgtl5000->ldo; - - if (!ldo) - return 0; - - regulator_unregister(ldo->dev); - kfree(ldo->desc.name); - kfree(ldo); - - return 0; -} -#else -static int ldo_regulator_register(struct snd_soc_codec *codec, - struct regulator_init_data *init_data, - int voltage) -{ - dev_err(codec->dev, "this setup needs regulator support in the kernel\n"); - return -EINVAL; -} - -static int ldo_regulator_remove(struct snd_soc_codec *codec) -{ - return 0; -} -#endif - -/* - * set dac bias - * common state changes: - * startup: - * off --> standby --> prepare --> on - * standby --> prepare --> on - * - * stop: - * on --> prepare --> standby - */ -static int sgtl5000_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable( - ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - if (ret) - return ret; - udelay(10); - } - - break; - case SND_SOC_BIAS_OFF: - regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#define SGTL5000_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops sgtl5000_ops = { - .hw_params = sgtl5000_pcm_hw_params, - .digital_mute = sgtl5000_digital_mute, - .set_fmt = sgtl5000_set_dai_fmt, - .set_sysclk = sgtl5000_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver sgtl5000_dai = { - .name = "sgtl5000", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - /* - * only support 8~48K + 96K, - * TODO modify hw_param to support more - */ - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_96000, - .formats = SGTL5000_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_96000, - .formats = SGTL5000_FORMATS, - }, - .ops = &sgtl5000_ops, - .symmetric_rates = 1, -}; - -static int sgtl5000_volatile_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - switch (reg) { - case SGTL5000_CHIP_ID: - case SGTL5000_CHIP_ADCDAC_CTRL: - case SGTL5000_CHIP_ANA_STATUS: - return 1; - } - - return 0; -} - -#ifdef CONFIG_SUSPEND -static int sgtl5000_suspend(struct snd_soc_codec *codec) -{ - sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -/* - * restore all sgtl5000 registers, - * since a big hole between dap and regular registers, - * we will restore them respectively. - */ -static int sgtl5000_restore_regs(struct snd_soc_codec *codec) -{ - u16 *cache = codec->reg_cache; - u16 reg; - - /* restore regular registers */ - for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) { - - /* These regs should restore in particular order */ - if (reg == SGTL5000_CHIP_ANA_POWER || - reg == SGTL5000_CHIP_CLK_CTRL || - reg == SGTL5000_CHIP_LINREG_CTRL || - reg == SGTL5000_CHIP_LINE_OUT_CTRL || - reg == SGTL5000_CHIP_REF_CTRL) - continue; - - snd_soc_write(codec, reg, cache[reg]); - } - - /* restore dap registers */ - for (reg = SGTL5000_DAP_REG_OFFSET; reg < SGTL5000_MAX_REG_OFFSET; reg += 2) - snd_soc_write(codec, reg, cache[reg]); - - /* - * restore these regs according to the power setting sequence in - * sgtl5000_set_power_regs() and clock setting sequence in - * sgtl5000_set_clock(). - * - * The order of restore is: - * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after - * SGTL5000_CHIP_ANA_POWER PLL bits set - * 2. SGTL5000_CHIP_LINREG_CTRL should be set before - * SGTL5000_CHIP_ANA_POWER LINREG_D restored - * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage, - * prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored - */ - snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, - cache[SGTL5000_CHIP_LINREG_CTRL]); - - snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER, - cache[SGTL5000_CHIP_ANA_POWER]); - - snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, - cache[SGTL5000_CHIP_CLK_CTRL]); - - snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL, - cache[SGTL5000_CHIP_REF_CTRL]); - - snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL, - cache[SGTL5000_CHIP_LINE_OUT_CTRL]); - return 0; -} - -static int sgtl5000_resume(struct snd_soc_codec *codec) -{ - /* Bring the codec back up to standby to enable regulators */ - sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Restore registers by cached in memory */ - sgtl5000_restore_regs(codec); - return 0; -} -#else -#define sgtl5000_suspend NULL -#define sgtl5000_resume NULL -#endif /* CONFIG_SUSPEND */ - -/* - * sgtl5000 has 3 internal power supplies: - * 1. VAG, normally set to vdda/2 - * 2. chargepump, set to different value - * according to voltage of vdda and vddio - * 3. line out VAG, normally set to vddio/2 - * - * and should be set according to: - * 1. vddd provided by external or not - * 2. vdda and vddio voltage value. > 3.1v or not - * 3. chip revision >=0x11 or not. If >=0x11, not use external vddd. - */ -static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) -{ - int vddd; - int vdda; - int vddio; - u16 ana_pwr; - u16 lreg_ctrl; - int vag; - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - - vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer); - vddio = regulator_get_voltage(sgtl5000->supplies[VDDIO].consumer); - vddd = regulator_get_voltage(sgtl5000->supplies[VDDD].consumer); - - vdda = vdda / 1000; - vddio = vddio / 1000; - vddd = vddd / 1000; - - if (vdda <= 0 || vddio <= 0 || vddd < 0) { - dev_err(codec->dev, "regulator voltage not set correctly\n"); - - return -EINVAL; - } - - /* according to datasheet, maximum voltage of supplies */ - if (vdda > 3600 || vddio > 3600 || vddd > 1980) { - dev_err(codec->dev, - "exceed max voltage vdda %dmV vddio %dmV vddd %dmV\n", - vdda, vddio, vddd); - - return -EINVAL; - } - - /* reset value */ - ana_pwr = snd_soc_read(codec, SGTL5000_CHIP_ANA_POWER); - ana_pwr |= SGTL5000_DAC_STEREO | - SGTL5000_ADC_STEREO | - SGTL5000_REFTOP_POWERUP; - lreg_ctrl = snd_soc_read(codec, SGTL5000_CHIP_LINREG_CTRL); - - if (vddio < 3100 && vdda < 3100) { - /* enable internal oscillator used for charge pump */ - snd_soc_update_bits(codec, SGTL5000_CHIP_CLK_TOP_CTRL, - SGTL5000_INT_OSC_EN, - SGTL5000_INT_OSC_EN); - /* Enable VDDC charge pump */ - ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; - } else if (vddio >= 3100 && vdda >= 3100) { - /* - * if vddio and vddd > 3.1v, - * charge pump should be clean before set ana_pwr - */ - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_VDDC_CHRGPMP_POWERUP, 0); - - /* VDDC use VDDIO rail */ - lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; - lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << - SGTL5000_VDDC_MAN_ASSN_SHIFT; - } - - snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl); - - snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER, ana_pwr); - - /* set voltage to register */ - snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, - SGTL5000_LINREG_VDDD_MASK, 0x8); - - /* - * if vddd linear reg has been enabled, - * simple digital supply should be clear to get - * proper VDDD voltage. - */ - if (ana_pwr & SGTL5000_LINEREG_D_POWERUP) - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_LINREG_SIMPLE_POWERUP, - 0); - else - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_LINREG_SIMPLE_POWERUP | - SGTL5000_STARTUP_POWERUP, - 0); - - /* - * set ADC/DAC VAG to vdda / 2, - * should stay in range (0.8v, 1.575v) - */ - vag = vdda / 2; - if (vag <= SGTL5000_ANA_GND_BASE) - vag = 0; - else if (vag >= SGTL5000_ANA_GND_BASE + SGTL5000_ANA_GND_STP * - (SGTL5000_ANA_GND_MASK >> SGTL5000_ANA_GND_SHIFT)) - vag = SGTL5000_ANA_GND_MASK >> SGTL5000_ANA_GND_SHIFT; - else - vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP; - - snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, - SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT); - - /* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */ - vag = vddio / 2; - if (vag <= SGTL5000_LINE_OUT_GND_BASE) - vag = 0; - else if (vag >= SGTL5000_LINE_OUT_GND_BASE + - SGTL5000_LINE_OUT_GND_STP * SGTL5000_LINE_OUT_GND_MAX) - vag = SGTL5000_LINE_OUT_GND_MAX; - else - vag = (vag - SGTL5000_LINE_OUT_GND_BASE) / - SGTL5000_LINE_OUT_GND_STP; - - snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL, - SGTL5000_LINE_OUT_CURRENT_MASK | - SGTL5000_LINE_OUT_GND_MASK, - vag << SGTL5000_LINE_OUT_GND_SHIFT | - SGTL5000_LINE_OUT_CURRENT_360u << - SGTL5000_LINE_OUT_CURRENT_SHIFT); - - return 0; -} - -static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec) -{ - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - int ret; - - /* set internal ldo to 1.2v */ - ret = ldo_regulator_register(codec, &ldo_init_data, LDO_VOLTAGE); - if (ret) { - dev_err(codec->dev, - "Failed to register vddd internal supplies: %d\n", ret); - return ret; - } - - sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - - if (ret) { - ldo_regulator_remove(codec); - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - dev_info(codec->dev, "Using internal LDO instead of VDDD\n"); - return 0; -} - -static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) -{ - u16 reg; - int ret; - int rev; - int i; - int external_vddd = 0; - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - - for (i = 0; i < ARRAY_SIZE(sgtl5000->supplies); i++) - sgtl5000->supplies[i].supply = supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - if (!ret) - external_vddd = 1; - else { - ret = sgtl5000_replace_vddd_with_ldo(codec); - if (ret) - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - if (ret) - goto err_regulator_free; - - /* wait for all power rails bring up */ - udelay(10); - - /* read chip information */ - reg = snd_soc_read(codec, SGTL5000_CHIP_ID); - if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) != - SGTL5000_PARTID_PART_ID) { - dev_err(codec->dev, - "Device with ID register %x is not a sgtl5000\n", reg); - ret = -ENODEV; - goto err_regulator_disable; - } - - rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; - dev_info(codec->dev, "sgtl5000 revision 0x%x\n", rev); - - /* - * workaround for revision 0x11 and later, - * roll back to use internal LDO - */ - if (external_vddd && rev >= 0x11) { - /* disable all regulator first */ - regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - /* free VDDD regulator */ - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - - ret = sgtl5000_replace_vddd_with_ldo(codec); - if (ret) - return ret; - - ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - if (ret) - goto err_regulator_free; - - /* wait for all power rails bring up */ - udelay(10); - } - - return 0; - -err_regulator_disable: - regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); -err_regulator_free: - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - if (external_vddd) - ldo_regulator_remove(codec); - return ret; - -} - -static int sgtl5000_probe(struct snd_soc_codec *codec) -{ - int ret; - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - - /* setup i2c data ops */ - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = sgtl5000_enable_regulators(codec); - if (ret) - return ret; - - /* power up sgtl5000 */ - ret = sgtl5000_set_power_regs(codec); - if (ret) - goto err; - - /* enable small pop, introduce 400ms delay in turning off */ - snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, - SGTL5000_SMALL_POP, - SGTL5000_SMALL_POP); - - /* disable short cut detector */ - snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0); - - /* - * set i2s as default input of sound switch - * TODO: add sound switch to control and dapm widge. - */ - snd_soc_write(codec, SGTL5000_CHIP_SSS_CTRL, - SGTL5000_DAC_SEL_I2S_IN << SGTL5000_DAC_SEL_SHIFT); - snd_soc_write(codec, SGTL5000_CHIP_DIG_POWER, - SGTL5000_ADC_EN | SGTL5000_DAC_EN); - - /* enable dac volume ramp by default */ - snd_soc_write(codec, SGTL5000_CHIP_ADCDAC_CTRL, - SGTL5000_DAC_VOL_RAMP_EN | - SGTL5000_DAC_MUTE_RIGHT | - SGTL5000_DAC_MUTE_LEFT); - - snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f); - - snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL, - SGTL5000_HP_ZCD_EN | - SGTL5000_ADC_ZCD_EN); - - snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 0); - - /* - * disable DAP - * TODO: - * Enable DAP in kcontrol and dapm. - */ - snd_soc_write(codec, SGTL5000_DAP_CTRL, 0); - - /* leading to standby state */ - ret = sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - if (ret) - goto err; - - snd_soc_dapm_new_widgets(&codec->dapm); - - return 0; - -err: - regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - ldo_regulator_remove(codec); - - return ret; -} - -static int sgtl5000_remove(struct snd_soc_codec *codec) -{ - struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - - sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF); - - regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), - sgtl5000->supplies); - ldo_regulator_remove(codec); - - return 0; -} - -static struct snd_soc_codec_driver sgtl5000_driver = { - .probe = sgtl5000_probe, - .remove = sgtl5000_remove, - .suspend = sgtl5000_suspend, - .resume = sgtl5000_resume, - .set_bias_level = sgtl5000_set_bias_level, - .reg_cache_size = ARRAY_SIZE(sgtl5000_regs), - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, - .reg_cache_default = sgtl5000_regs, - .volatile_register = sgtl5000_volatile_register, - .controls = sgtl5000_snd_controls, - .num_controls = ARRAY_SIZE(sgtl5000_snd_controls), - .dapm_widgets = sgtl5000_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets), - .dapm_routes = sgtl5000_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes), -}; - -static __devinit int sgtl5000_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct sgtl5000_priv *sgtl5000; - int ret; - - sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv), - GFP_KERNEL); - if (!sgtl5000) - return -ENOMEM; - - i2c_set_clientdata(client, sgtl5000); - - ret = snd_soc_register_codec(&client->dev, - &sgtl5000_driver, &sgtl5000_dai, 1); - return ret; -} - -static __devexit int sgtl5000_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - - return 0; -} - -static const struct i2c_device_id sgtl5000_id[] = { - {"sgtl5000", 0}, - {}, -}; - -MODULE_DEVICE_TABLE(i2c, sgtl5000_id); - -static const struct of_device_id sgtl5000_dt_ids[] = { - { .compatible = "fsl,sgtl5000", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids); - -static struct i2c_driver sgtl5000_i2c_driver = { - .driver = { - .name = "sgtl5000", - .owner = THIS_MODULE, - .of_match_table = sgtl5000_dt_ids, - }, - .probe = sgtl5000_i2c_probe, - .remove = __devexit_p(sgtl5000_i2c_remove), - .id_table = sgtl5000_id, -}; - -static int __init sgtl5000_modinit(void) -{ - return i2c_add_driver(&sgtl5000_i2c_driver); -} -module_init(sgtl5000_modinit); - -static void __exit sgtl5000_exit(void) -{ - i2c_del_driver(&sgtl5000_i2c_driver); -} -module_exit(sgtl5000_exit); - -MODULE_DESCRIPTION("Freescale SGTL5000 ALSA SoC Codec Driver"); -MODULE_AUTHOR("Zeng Zhaoming "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/sgtl5000.h b/ANDROID_3.4.5/sound/soc/codecs/sgtl5000.h deleted file mode 100644 index 8a9f4353..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/sgtl5000.h +++ /dev/null @@ -1,400 +0,0 @@ -/* - * sgtl5000.h - SGTL5000 audio codec interface - * - * Copyright 2010-2011 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _SGTL5000_H -#define _SGTL5000_H - -/* - * Register values. - */ -#define SGTL5000_CHIP_ID 0x0000 -#define SGTL5000_CHIP_DIG_POWER 0x0002 -#define SGTL5000_CHIP_CLK_CTRL 0x0004 -#define SGTL5000_CHIP_I2S_CTRL 0x0006 -#define SGTL5000_CHIP_SSS_CTRL 0x000a -#define SGTL5000_CHIP_ADCDAC_CTRL 0x000e -#define SGTL5000_CHIP_DAC_VOL 0x0010 -#define SGTL5000_CHIP_PAD_STRENGTH 0x0014 -#define SGTL5000_CHIP_ANA_ADC_CTRL 0x0020 -#define SGTL5000_CHIP_ANA_HP_CTRL 0x0022 -#define SGTL5000_CHIP_ANA_CTRL 0x0024 -#define SGTL5000_CHIP_LINREG_CTRL 0x0026 -#define SGTL5000_CHIP_REF_CTRL 0x0028 -#define SGTL5000_CHIP_MIC_CTRL 0x002a -#define SGTL5000_CHIP_LINE_OUT_CTRL 0x002c -#define SGTL5000_CHIP_LINE_OUT_VOL 0x002e -#define SGTL5000_CHIP_ANA_POWER 0x0030 -#define SGTL5000_CHIP_PLL_CTRL 0x0032 -#define SGTL5000_CHIP_CLK_TOP_CTRL 0x0034 -#define SGTL5000_CHIP_ANA_STATUS 0x0036 -#define SGTL5000_CHIP_SHORT_CTRL 0x003c -#define SGTL5000_CHIP_ANA_TEST2 0x003a -#define SGTL5000_DAP_CTRL 0x0100 -#define SGTL5000_DAP_PEQ 0x0102 -#define SGTL5000_DAP_BASS_ENHANCE 0x0104 -#define SGTL5000_DAP_BASS_ENHANCE_CTRL 0x0106 -#define SGTL5000_DAP_AUDIO_EQ 0x0108 -#define SGTL5000_DAP_SURROUND 0x010a -#define SGTL5000_DAP_FLT_COEF_ACCESS 0x010c -#define SGTL5000_DAP_COEF_WR_B0_MSB 0x010e -#define SGTL5000_DAP_COEF_WR_B0_LSB 0x0110 -#define SGTL5000_DAP_EQ_BASS_BAND0 0x0116 -#define SGTL5000_DAP_EQ_BASS_BAND1 0x0118 -#define SGTL5000_DAP_EQ_BASS_BAND2 0x011a -#define SGTL5000_DAP_EQ_BASS_BAND3 0x011c -#define SGTL5000_DAP_EQ_BASS_BAND4 0x011e -#define SGTL5000_DAP_MAIN_CHAN 0x0120 -#define SGTL5000_DAP_MIX_CHAN 0x0122 -#define SGTL5000_DAP_AVC_CTRL 0x0124 -#define SGTL5000_DAP_AVC_THRESHOLD 0x0126 -#define SGTL5000_DAP_AVC_ATTACK 0x0128 -#define SGTL5000_DAP_AVC_DECAY 0x012a -#define SGTL5000_DAP_COEF_WR_B1_MSB 0x012c -#define SGTL5000_DAP_COEF_WR_B1_LSB 0x012e -#define SGTL5000_DAP_COEF_WR_B2_MSB 0x0130 -#define SGTL5000_DAP_COEF_WR_B2_LSB 0x0132 -#define SGTL5000_DAP_COEF_WR_A1_MSB 0x0134 -#define SGTL5000_DAP_COEF_WR_A1_LSB 0x0136 -#define SGTL5000_DAP_COEF_WR_A2_MSB 0x0138 -#define SGTL5000_DAP_COEF_WR_A2_LSB 0x013a - -/* - * Field Definitions. - */ - -/* - * SGTL5000_CHIP_ID - */ -#define SGTL5000_PARTID_MASK 0xff00 -#define SGTL5000_PARTID_SHIFT 8 -#define SGTL5000_PARTID_WIDTH 8 -#define SGTL5000_PARTID_PART_ID 0xa0 -#define SGTL5000_REVID_MASK 0x00ff -#define SGTL5000_REVID_SHIFT 0 -#define SGTL5000_REVID_WIDTH 8 - -/* - * SGTL5000_CHIP_DIG_POWER - */ -#define SGTL5000_ADC_EN 0x0040 -#define SGTL5000_DAC_EN 0x0020 -#define SGTL5000_DAP_POWERUP 0x0010 -#define SGTL5000_I2S_OUT_POWERUP 0x0002 -#define SGTL5000_I2S_IN_POWERUP 0x0001 - -/* - * SGTL5000_CHIP_CLK_CTRL - */ -#define SGTL5000_RATE_MODE_MASK 0x0030 -#define SGTL5000_RATE_MODE_SHIFT 4 -#define SGTL5000_RATE_MODE_WIDTH 2 -#define SGTL5000_RATE_MODE_DIV_1 0 -#define SGTL5000_RATE_MODE_DIV_2 1 -#define SGTL5000_RATE_MODE_DIV_4 2 -#define SGTL5000_RATE_MODE_DIV_6 3 -#define SGTL5000_SYS_FS_MASK 0x000c -#define SGTL5000_SYS_FS_SHIFT 2 -#define SGTL5000_SYS_FS_WIDTH 2 -#define SGTL5000_SYS_FS_32k 0x0 -#define SGTL5000_SYS_FS_44_1k 0x1 -#define SGTL5000_SYS_FS_48k 0x2 -#define SGTL5000_SYS_FS_96k 0x3 -#define SGTL5000_MCLK_FREQ_MASK 0x0003 -#define SGTL5000_MCLK_FREQ_SHIFT 0 -#define SGTL5000_MCLK_FREQ_WIDTH 2 -#define SGTL5000_MCLK_FREQ_256FS 0x0 -#define SGTL5000_MCLK_FREQ_384FS 0x1 -#define SGTL5000_MCLK_FREQ_512FS 0x2 -#define SGTL5000_MCLK_FREQ_PLL 0x3 - -/* - * SGTL5000_CHIP_I2S_CTRL - */ -#define SGTL5000_I2S_SCLKFREQ_MASK 0x0100 -#define SGTL5000_I2S_SCLKFREQ_SHIFT 8 -#define SGTL5000_I2S_SCLKFREQ_WIDTH 1 -#define SGTL5000_I2S_SCLKFREQ_64FS 0x0 -#define SGTL5000_I2S_SCLKFREQ_32FS 0x1 /* Not for RJ mode */ -#define SGTL5000_I2S_MASTER 0x0080 -#define SGTL5000_I2S_SCLK_INV 0x0040 -#define SGTL5000_I2S_DLEN_MASK 0x0030 -#define SGTL5000_I2S_DLEN_SHIFT 4 -#define SGTL5000_I2S_DLEN_WIDTH 2 -#define SGTL5000_I2S_DLEN_32 0x0 -#define SGTL5000_I2S_DLEN_24 0x1 -#define SGTL5000_I2S_DLEN_20 0x2 -#define SGTL5000_I2S_DLEN_16 0x3 -#define SGTL5000_I2S_MODE_MASK 0x000c -#define SGTL5000_I2S_MODE_SHIFT 2 -#define SGTL5000_I2S_MODE_WIDTH 2 -#define SGTL5000_I2S_MODE_I2S_LJ 0x0 -#define SGTL5000_I2S_MODE_RJ 0x1 -#define SGTL5000_I2S_MODE_PCM 0x2 -#define SGTL5000_I2S_LRALIGN 0x0002 -#define SGTL5000_I2S_LRPOL 0x0001 /* set for which mode */ - -/* - * SGTL5000_CHIP_SSS_CTRL - */ -#define SGTL5000_DAP_MIX_LRSWAP 0x4000 -#define SGTL5000_DAP_LRSWAP 0x2000 -#define SGTL5000_DAC_LRSWAP 0x1000 -#define SGTL5000_I2S_OUT_LRSWAP 0x0400 -#define SGTL5000_DAP_MIX_SEL_MASK 0x0300 -#define SGTL5000_DAP_MIX_SEL_SHIFT 8 -#define SGTL5000_DAP_MIX_SEL_WIDTH 2 -#define SGTL5000_DAP_MIX_SEL_ADC 0x0 -#define SGTL5000_DAP_MIX_SEL_I2S_IN 0x1 -#define SGTL5000_DAP_SEL_MASK 0x00c0 -#define SGTL5000_DAP_SEL_SHIFT 6 -#define SGTL5000_DAP_SEL_WIDTH 2 -#define SGTL5000_DAP_SEL_ADC 0x0 -#define SGTL5000_DAP_SEL_I2S_IN 0x1 -#define SGTL5000_DAC_SEL_MASK 0x0030 -#define SGTL5000_DAC_SEL_SHIFT 4 -#define SGTL5000_DAC_SEL_WIDTH 2 -#define SGTL5000_DAC_SEL_ADC 0x0 -#define SGTL5000_DAC_SEL_I2S_IN 0x1 -#define SGTL5000_DAC_SEL_DAP 0x3 -#define SGTL5000_I2S_OUT_SEL_MASK 0x0003 -#define SGTL5000_I2S_OUT_SEL_SHIFT 0 -#define SGTL5000_I2S_OUT_SEL_WIDTH 2 -#define SGTL5000_I2S_OUT_SEL_ADC 0x0 -#define SGTL5000_I2S_OUT_SEL_I2S_IN 0x1 -#define SGTL5000_I2S_OUT_SEL_DAP 0x3 - -/* - * SGTL5000_CHIP_ADCDAC_CTRL - */ -#define SGTL5000_VOL_BUSY_DAC_RIGHT 0x2000 -#define SGTL5000_VOL_BUSY_DAC_LEFT 0x1000 -#define SGTL5000_DAC_VOL_RAMP_EN 0x0200 -#define SGTL5000_DAC_VOL_RAMP_EXPO 0x0100 -#define SGTL5000_DAC_MUTE_RIGHT 0x0008 -#define SGTL5000_DAC_MUTE_LEFT 0x0004 -#define SGTL5000_ADC_HPF_FREEZE 0x0002 -#define SGTL5000_ADC_HPF_BYPASS 0x0001 - -/* - * SGTL5000_CHIP_DAC_VOL - */ -#define SGTL5000_DAC_VOL_RIGHT_MASK 0xff00 -#define SGTL5000_DAC_VOL_RIGHT_SHIFT 8 -#define SGTL5000_DAC_VOL_RIGHT_WIDTH 8 -#define SGTL5000_DAC_VOL_LEFT_MASK 0x00ff -#define SGTL5000_DAC_VOL_LEFT_SHIFT 0 -#define SGTL5000_DAC_VOL_LEFT_WIDTH 8 - -/* - * SGTL5000_CHIP_PAD_STRENGTH - */ -#define SGTL5000_PAD_I2S_LRCLK_MASK 0x0300 -#define SGTL5000_PAD_I2S_LRCLK_SHIFT 8 -#define SGTL5000_PAD_I2S_LRCLK_WIDTH 2 -#define SGTL5000_PAD_I2S_SCLK_MASK 0x00c0 -#define SGTL5000_PAD_I2S_SCLK_SHIFT 6 -#define SGTL5000_PAD_I2S_SCLK_WIDTH 2 -#define SGTL5000_PAD_I2S_DOUT_MASK 0x0030 -#define SGTL5000_PAD_I2S_DOUT_SHIFT 4 -#define SGTL5000_PAD_I2S_DOUT_WIDTH 2 -#define SGTL5000_PAD_I2C_SDA_MASK 0x000c -#define SGTL5000_PAD_I2C_SDA_SHIFT 2 -#define SGTL5000_PAD_I2C_SDA_WIDTH 2 -#define SGTL5000_PAD_I2C_SCL_MASK 0x0003 -#define SGTL5000_PAD_I2C_SCL_SHIFT 0 -#define SGTL5000_PAD_I2C_SCL_WIDTH 2 - -/* - * SGTL5000_CHIP_ANA_ADC_CTRL - */ -#define SGTL5000_ADC_VOL_M6DB 0x0100 -#define SGTL5000_ADC_VOL_RIGHT_MASK 0x00f0 -#define SGTL5000_ADC_VOL_RIGHT_SHIFT 4 -#define SGTL5000_ADC_VOL_RIGHT_WIDTH 4 -#define SGTL5000_ADC_VOL_LEFT_MASK 0x000f -#define SGTL5000_ADC_VOL_LEFT_SHIFT 0 -#define SGTL5000_ADC_VOL_LEFT_WIDTH 4 - -/* - * SGTL5000_CHIP_ANA_HP_CTRL - */ -#define SGTL5000_HP_VOL_RIGHT_MASK 0x7f00 -#define SGTL5000_HP_VOL_RIGHT_SHIFT 8 -#define SGTL5000_HP_VOL_RIGHT_WIDTH 7 -#define SGTL5000_HP_VOL_LEFT_MASK 0x007f -#define SGTL5000_HP_VOL_LEFT_SHIFT 0 -#define SGTL5000_HP_VOL_LEFT_WIDTH 7 - -/* - * SGTL5000_CHIP_ANA_CTRL - */ -#define SGTL5000_LINE_OUT_MUTE 0x0100 -#define SGTL5000_HP_SEL_MASK 0x0040 -#define SGTL5000_HP_SEL_SHIFT 6 -#define SGTL5000_HP_SEL_WIDTH 1 -#define SGTL5000_HP_SEL_DAC 0x0 -#define SGTL5000_HP_SEL_LINE_IN 0x1 -#define SGTL5000_HP_ZCD_EN 0x0020 -#define SGTL5000_HP_MUTE 0x0010 -#define SGTL5000_ADC_SEL_MASK 0x0004 -#define SGTL5000_ADC_SEL_SHIFT 2 -#define SGTL5000_ADC_SEL_WIDTH 1 -#define SGTL5000_ADC_SEL_MIC 0x0 -#define SGTL5000_ADC_SEL_LINE_IN 0x1 -#define SGTL5000_ADC_ZCD_EN 0x0002 -#define SGTL5000_ADC_MUTE 0x0001 - -/* - * SGTL5000_CHIP_LINREG_CTRL - */ -#define SGTL5000_VDDC_MAN_ASSN_MASK 0x0040 -#define SGTL5000_VDDC_MAN_ASSN_SHIFT 6 -#define SGTL5000_VDDC_MAN_ASSN_WIDTH 1 -#define SGTL5000_VDDC_MAN_ASSN_VDDA 0x0 -#define SGTL5000_VDDC_MAN_ASSN_VDDIO 0x1 -#define SGTL5000_VDDC_ASSN_OVRD 0x0020 -#define SGTL5000_LINREG_VDDD_MASK 0x000f -#define SGTL5000_LINREG_VDDD_SHIFT 0 -#define SGTL5000_LINREG_VDDD_WIDTH 4 - -/* - * SGTL5000_CHIP_REF_CTRL - */ -#define SGTL5000_ANA_GND_MASK 0x01f0 -#define SGTL5000_ANA_GND_SHIFT 4 -#define SGTL5000_ANA_GND_WIDTH 5 -#define SGTL5000_ANA_GND_BASE 800 /* mv */ -#define SGTL5000_ANA_GND_STP 25 /*mv */ -#define SGTL5000_BIAS_CTRL_MASK 0x000e -#define SGTL5000_BIAS_CTRL_SHIFT 1 -#define SGTL5000_BIAS_CTRL_WIDTH 3 -#define SGTL5000_SMALL_POP 0x0001 - -/* - * SGTL5000_CHIP_MIC_CTRL - */ -#define SGTL5000_BIAS_R_MASK 0x0300 -#define SGTL5000_BIAS_R_SHIFT 8 -#define SGTL5000_BIAS_R_WIDTH 2 -#define SGTL5000_BIAS_R_off 0x0 -#define SGTL5000_BIAS_R_2K 0x1 -#define SGTL5000_BIAS_R_4k 0x2 -#define SGTL5000_BIAS_R_8k 0x3 -#define SGTL5000_BIAS_VOLT_MASK 0x0070 -#define SGTL5000_BIAS_VOLT_SHIFT 4 -#define SGTL5000_BIAS_VOLT_WIDTH 3 -#define SGTL5000_MIC_GAIN_MASK 0x0003 -#define SGTL5000_MIC_GAIN_SHIFT 0 -#define SGTL5000_MIC_GAIN_WIDTH 2 - -/* - * SGTL5000_CHIP_LINE_OUT_CTRL - */ -#define SGTL5000_LINE_OUT_CURRENT_MASK 0x0f00 -#define SGTL5000_LINE_OUT_CURRENT_SHIFT 8 -#define SGTL5000_LINE_OUT_CURRENT_WIDTH 4 -#define SGTL5000_LINE_OUT_CURRENT_180u 0x0 -#define SGTL5000_LINE_OUT_CURRENT_270u 0x1 -#define SGTL5000_LINE_OUT_CURRENT_360u 0x3 -#define SGTL5000_LINE_OUT_CURRENT_450u 0x7 -#define SGTL5000_LINE_OUT_CURRENT_540u 0xf -#define SGTL5000_LINE_OUT_GND_MASK 0x003f -#define SGTL5000_LINE_OUT_GND_SHIFT 0 -#define SGTL5000_LINE_OUT_GND_WIDTH 6 -#define SGTL5000_LINE_OUT_GND_BASE 800 /* mv */ -#define SGTL5000_LINE_OUT_GND_STP 25 -#define SGTL5000_LINE_OUT_GND_MAX 0x23 - -/* - * SGTL5000_CHIP_LINE_OUT_VOL - */ -#define SGTL5000_LINE_OUT_VOL_RIGHT_MASK 0x1f00 -#define SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT 8 -#define SGTL5000_LINE_OUT_VOL_RIGHT_WIDTH 5 -#define SGTL5000_LINE_OUT_VOL_LEFT_MASK 0x001f -#define SGTL5000_LINE_OUT_VOL_LEFT_SHIFT 0 -#define SGTL5000_LINE_OUT_VOL_LEFT_WIDTH 5 - -/* - * SGTL5000_CHIP_ANA_POWER - */ -#define SGTL5000_DAC_STEREO 0x4000 -#define SGTL5000_LINREG_SIMPLE_POWERUP 0x2000 -#define SGTL5000_STARTUP_POWERUP 0x1000 -#define SGTL5000_VDDC_CHRGPMP_POWERUP 0x0800 -#define SGTL5000_PLL_POWERUP 0x0400 -#define SGTL5000_LINEREG_D_POWERUP 0x0200 -#define SGTL5000_VCOAMP_POWERUP 0x0100 -#define SGTL5000_VAG_POWERUP 0x0080 -#define SGTL5000_ADC_STEREO 0x0040 -#define SGTL5000_REFTOP_POWERUP 0x0020 -#define SGTL5000_HP_POWERUP 0x0010 -#define SGTL5000_DAC_POWERUP 0x0008 -#define SGTL5000_CAPLESS_HP_POWERUP 0x0004 -#define SGTL5000_ADC_POWERUP 0x0002 -#define SGTL5000_LINE_OUT_POWERUP 0x0001 - -/* - * SGTL5000_CHIP_PLL_CTRL - */ -#define SGTL5000_PLL_INT_DIV_MASK 0xf800 -#define SGTL5000_PLL_INT_DIV_SHIFT 11 -#define SGTL5000_PLL_INT_DIV_WIDTH 5 -#define SGTL5000_PLL_FRAC_DIV_MASK 0x0700 -#define SGTL5000_PLL_FRAC_DIV_SHIFT 0 -#define SGTL5000_PLL_FRAC_DIV_WIDTH 11 - -/* - * SGTL5000_CHIP_CLK_TOP_CTRL - */ -#define SGTL5000_INT_OSC_EN 0x0800 -#define SGTL5000_INPUT_FREQ_DIV2 0x0008 - -/* - * SGTL5000_CHIP_ANA_STATUS - */ -#define SGTL5000_HP_LRSHORT 0x0200 -#define SGTL5000_CAPLESS_SHORT 0x0100 -#define SGTL5000_PLL_LOCKED 0x0010 - -/* - * SGTL5000_CHIP_SHORT_CTRL - */ -#define SGTL5000_LVLADJR_MASK 0x7000 -#define SGTL5000_LVLADJR_SHIFT 12 -#define SGTL5000_LVLADJR_WIDTH 3 -#define SGTL5000_LVLADJL_MASK 0x0700 -#define SGTL5000_LVLADJL_SHIFT 8 -#define SGTL5000_LVLADJL_WIDTH 3 -#define SGTL5000_LVLADJC_MASK 0x0070 -#define SGTL5000_LVLADJC_SHIFT 4 -#define SGTL5000_LVLADJC_WIDTH 3 -#define SGTL5000_LR_SHORT_MOD_MASK 0x000c -#define SGTL5000_LR_SHORT_MOD_SHIFT 2 -#define SGTL5000_LR_SHORT_MOD_WIDTH 2 -#define SGTL5000_CM_SHORT_MOD_MASK 0x0003 -#define SGTL5000_CM_SHORT_MOD_SHIFT 0 -#define SGTL5000_CM_SHORT_MOD_WIDTH 2 - -/* - *SGTL5000_CHIP_ANA_TEST2 - */ -#define SGTL5000_MONO_DAC 0x1000 - -/* - * SGTL5000_DAP_CTRL - */ -#define SGTL5000_DAP_MIX_EN 0x0010 -#define SGTL5000_DAP_EN 0x0001 - -#define SGTL5000_SYSCLK 0x00 -#define SGTL5000_LRCLK 0x01 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/sigmadsp.c b/ANDROID_3.4.5/sound/soc/codecs/sigmadsp.c deleted file mode 100644 index 5be42bf5..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/sigmadsp.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Load Analog Devices SigmaStudio firmware files - * - * Copyright 2009-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "sigmadsp.h" - -#define SIGMA_MAGIC "ADISIGM" - -struct sigma_firmware_header { - unsigned char magic[7]; - u8 version; - __le32 crc; -} __packed; - -enum { - SIGMA_ACTION_WRITEXBYTES = 0, - SIGMA_ACTION_WRITESINGLE, - SIGMA_ACTION_WRITESAFELOAD, - SIGMA_ACTION_DELAY, - SIGMA_ACTION_PLLWAIT, - SIGMA_ACTION_NOOP, - SIGMA_ACTION_END, -}; - -struct sigma_action { - u8 instr; - u8 len_hi; - __le16 len; - __be16 addr; - unsigned char payload[]; -} __packed; - -struct sigma_firmware { - const struct firmware *fw; - size_t pos; - - void *control_data; - int (*write)(void *control_data, const struct sigma_action *sa, - size_t len); -}; - -static inline u32 sigma_action_len(struct sigma_action *sa) -{ - return (sa->len_hi << 16) | le16_to_cpu(sa->len); -} - -static size_t sigma_action_size(struct sigma_action *sa) -{ - size_t payload = 0; - - switch (sa->instr) { - case SIGMA_ACTION_WRITEXBYTES: - case SIGMA_ACTION_WRITESINGLE: - case SIGMA_ACTION_WRITESAFELOAD: - payload = sigma_action_len(sa); - break; - default: - break; - } - - payload = ALIGN(payload, 2); - - return payload + sizeof(struct sigma_action); -} - -/* - * Returns a negative error value in case of an error, 0 if processing of - * the firmware should be stopped after this action, 1 otherwise. - */ -static int -process_sigma_action(struct sigma_firmware *ssfw, struct sigma_action *sa) -{ - size_t len = sigma_action_len(sa); - int ret; - - pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, - sa->instr, sa->addr, len); - - switch (sa->instr) { - case SIGMA_ACTION_WRITEXBYTES: - case SIGMA_ACTION_WRITESINGLE: - case SIGMA_ACTION_WRITESAFELOAD: - ret = ssfw->write(ssfw->control_data, sa, len); - if (ret < 0) - return -EINVAL; - break; - case SIGMA_ACTION_DELAY: - udelay(len); - len = 0; - break; - case SIGMA_ACTION_END: - return 0; - default: - return -EINVAL; - } - - return 1; -} - -static int -process_sigma_actions(struct sigma_firmware *ssfw) -{ - struct sigma_action *sa; - size_t size; - int ret; - - while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { - sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); - - size = sigma_action_size(sa); - ssfw->pos += size; - if (ssfw->pos > ssfw->fw->size || size == 0) - break; - - ret = process_sigma_action(ssfw, sa); - - pr_debug("%s: action returned %i\n", __func__, ret); - - if (ret <= 0) - return ret; - } - - if (ssfw->pos != ssfw->fw->size) - return -EINVAL; - - return 0; -} - -static int _process_sigma_firmware(struct device *dev, - struct sigma_firmware *ssfw, const char *name) -{ - int ret; - struct sigma_firmware_header *ssfw_head; - const struct firmware *fw; - u32 crc; - - pr_debug("%s: loading firmware %s\n", __func__, name); - - /* first load the blob */ - ret = request_firmware(&fw, name, dev); - if (ret) { - pr_debug("%s: request_firmware() failed with %i\n", __func__, ret); - return ret; - } - ssfw->fw = fw; - - /* then verify the header */ - ret = -EINVAL; - - /* - * Reject too small or unreasonable large files. The upper limit has been - * chosen a bit arbitrarily, but it should be enough for all practical - * purposes and having the limit makes it easier to avoid integer - * overflows later in the loading process. - */ - if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) { - dev_err(dev, "Failed to load firmware: Invalid size\n"); - goto done; - } - - ssfw_head = (void *)fw->data; - if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) { - dev_err(dev, "Failed to load firmware: Invalid magic\n"); - goto done; - } - - crc = crc32(0, fw->data + sizeof(*ssfw_head), - fw->size - sizeof(*ssfw_head)); - pr_debug("%s: crc=%x\n", __func__, crc); - if (crc != le32_to_cpu(ssfw_head->crc)) { - dev_err(dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n", - le32_to_cpu(ssfw_head->crc), crc); - goto done; - } - - ssfw->pos = sizeof(*ssfw_head); - - /* finally process all of the actions */ - ret = process_sigma_actions(ssfw); - - done: - release_firmware(fw); - - pr_debug("%s: loaded %s\n", __func__, name); - - return ret; -} - -#if IS_ENABLED(CONFIG_I2C) - -static int sigma_action_write_i2c(void *control_data, - const struct sigma_action *sa, size_t len) -{ - return i2c_master_send(control_data, (const unsigned char *)&sa->addr, - len); -} - -int process_sigma_firmware(struct i2c_client *client, const char *name) -{ - struct sigma_firmware ssfw; - - ssfw.control_data = client; - ssfw.write = sigma_action_write_i2c; - - return _process_sigma_firmware(&client->dev, &ssfw, name); -} -EXPORT_SYMBOL(process_sigma_firmware); - -#endif - -#if IS_ENABLED(CONFIG_REGMAP) - -static int sigma_action_write_regmap(void *control_data, - const struct sigma_action *sa, size_t len) -{ - return regmap_raw_write(control_data, le16_to_cpu(sa->addr), - sa->payload, len - 2); -} - -int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap, - const char *name) -{ - struct sigma_firmware ssfw; - - ssfw.control_data = regmap; - ssfw.write = sigma_action_write_regmap; - - return _process_sigma_firmware(dev, &ssfw, name); -} -EXPORT_SYMBOL(process_sigma_firmware_regmap); - -#endif - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/sigmadsp.h b/ANDROID_3.4.5/sound/soc/codecs/sigmadsp.h deleted file mode 100644 index e439cbd7..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/sigmadsp.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Load firmware files from Analog Devices SigmaStudio - * - * Copyright 2009-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __SIGMA_FIRMWARE_H__ -#define __SIGMA_FIRMWARE_H__ - -#include -#include - -struct i2c_client; - -extern int process_sigma_firmware(struct i2c_client *client, const char *name); -extern int process_sigma_firmware_regmap(struct device *dev, - struct regmap *regmap, const char *name); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/sn95031.c b/ANDROID_3.4.5/sound/soc/codecs/sn95031.c deleted file mode 100644 index 50dbdb93..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/sn95031.c +++ /dev/null @@ -1,928 +0,0 @@ -/* - * sn95031.c - TI sn95031 Codec driver - * - * Copyright (C) 2010 Intel Corp - * Author: Vinod Koul - * Author: Harsha Priya - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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; version 2 of the License. - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include "sn95031.h" - -#define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100) -#define SN95031_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) - -/* adc helper functions */ - -/* enables mic bias voltage */ -static void sn95031_enable_mic_bias(struct snd_soc_codec *codec) -{ - snd_soc_write(codec, SN95031_VAUD, BIT(2)|BIT(1)|BIT(0)); - snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(2), BIT(2)); -} - -/* Enable/Disable the ADC depending on the argument */ -static void configure_adc(struct snd_soc_codec *sn95031_codec, int val) -{ - int value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); - - if (val) { - /* Enable and start the ADC */ - value |= (SN95031_ADC_ENBL | SN95031_ADC_START); - value &= (~SN95031_ADC_NO_LOOP); - } else { - /* Just stop the ADC */ - value &= (~SN95031_ADC_START); - } - snd_soc_write(sn95031_codec, SN95031_ADC1CNTL1, value); -} - -/* - * finds an empty channel for conversion - * If the ADC is not enabled then start using 0th channel - * itself. Otherwise find an empty channel by looking for a - * channel in which the stopbit is set to 1. returns the index - * of the first free channel if succeeds or an error code. - * - * Context: can sleep - * - */ -static int find_free_channel(struct snd_soc_codec *sn95031_codec) -{ - int i, value; - - /* check whether ADC is enabled */ - value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); - - if ((value & SN95031_ADC_ENBL) == 0) - return 0; - - /* ADC is already enabled; Looking for an empty channel */ - for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) { - value = snd_soc_read(sn95031_codec, - SN95031_ADC_CHNL_START_ADDR + i); - if (value & SN95031_STOPBIT_MASK) - break; - } - return (i == SN95031_ADC_CHANLS_MAX) ? (-EINVAL) : i; -} - -/* Initialize the ADC for reading micbias values. Can sleep. */ -static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec) -{ - int base_addr, chnl_addr; - int value; - int channel_index; - - /* Index of the first channel in which the stop bit is set */ - channel_index = find_free_channel(sn95031_codec); - if (channel_index < 0) { - pr_err("No free ADC channels"); - return channel_index; - } - - base_addr = SN95031_ADC_CHNL_START_ADDR + channel_index; - - if (!(channel_index == 0 || channel_index == SN95031_ADC_LOOP_MAX)) { - /* Reset stop bit for channels other than 0 and 12 */ - value = snd_soc_read(sn95031_codec, base_addr); - /* Set the stop bit to zero */ - snd_soc_write(sn95031_codec, base_addr, value & 0xEF); - /* Index of the first free channel */ - base_addr++; - channel_index++; - } - - /* Since this is the last channel, set the stop bit - to 1 by ORing the DIE_SENSOR_CODE with 0x10 */ - snd_soc_write(sn95031_codec, base_addr, - SN95031_AUDIO_DETECT_CODE | 0x10); - - chnl_addr = SN95031_ADC_DATA_START_ADDR + 2 * channel_index; - pr_debug("mid_initialize : %x", chnl_addr); - configure_adc(sn95031_codec, 1); - return chnl_addr; -} - - -/* reads the ADC registers and gets the mic bias value in mV. */ -static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec) -{ - u16 adc_adr = sn95031_initialize_adc(codec); - u16 adc_val1, adc_val2; - unsigned int mic_bias; - - sn95031_enable_mic_bias(codec); - - /* Enable the sound card for conversion before reading */ - snd_soc_write(codec, SN95031_ADC1CNTL3, 0x05); - /* Re-toggle the RRDATARD bit */ - snd_soc_write(codec, SN95031_ADC1CNTL3, 0x04); - - /* Read the higher bits of data */ - msleep(1000); - adc_val1 = snd_soc_read(codec, adc_adr); - adc_adr++; - adc_val2 = snd_soc_read(codec, adc_adr); - - /* Adding lower two bits to the higher bits */ - mic_bias = (adc_val1 << 2) + (adc_val2 & 3); - mic_bias = (mic_bias * SN95031_ADC_ONE_LSB_MULTIPLIER) / 1000; - pr_debug("mic bias = %dmV\n", mic_bias); - return mic_bias; -} -/*end - adc helper functions */ - -static inline unsigned int sn95031_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 value = 0; - int ret; - - ret = intel_scu_ipc_ioread8(reg, &value); - if (ret) - pr_err("read of %x failed, err %d\n", reg, ret); - return value; - -} - -static inline int sn95031_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - int ret; - - ret = intel_scu_ipc_iowrite8(reg, value); - if (ret) - pr_err("write of %x failed, err %d\n", reg, ret); - return ret; -} - -static int sn95031_set_vaud_bias(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { - pr_debug("vaud_bias powering up pll\n"); - /* power up the pll */ - snd_soc_write(codec, SN95031_AUDPLLCTRL, BIT(5)); - /* enable pcm 2 */ - snd_soc_update_bits(codec, SN95031_PCM2C2, - BIT(0), BIT(0)); - } - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - pr_debug("vaud_bias power up rail\n"); - /* power up the rail */ - snd_soc_write(codec, SN95031_VAUD, - BIT(2)|BIT(1)|BIT(0)); - msleep(1); - } else if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { - /* turn off pcm */ - pr_debug("vaud_bias power dn pcm\n"); - snd_soc_update_bits(codec, SN95031_PCM2C2, BIT(0), 0); - snd_soc_write(codec, SN95031_AUDPLLCTRL, 0); - } - break; - - - case SND_SOC_BIAS_OFF: - pr_debug("vaud_bias _OFF doing rail shutdown\n"); - snd_soc_write(codec, SN95031_VAUD, BIT(3)); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -static int sn95031_vhs_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - if (SND_SOC_DAPM_EVENT_ON(event)) { - pr_debug("VHS SND_SOC_DAPM_EVENT_ON doing rail startup now\n"); - /* power up the rail */ - snd_soc_write(w->codec, SN95031_VHSP, 0x3D); - snd_soc_write(w->codec, SN95031_VHSN, 0x3F); - msleep(1); - } else if (SND_SOC_DAPM_EVENT_OFF(event)) { - pr_debug("VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n"); - snd_soc_write(w->codec, SN95031_VHSP, 0xC4); - snd_soc_write(w->codec, SN95031_VHSN, 0x04); - } - return 0; -} - -static int sn95031_vihf_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - if (SND_SOC_DAPM_EVENT_ON(event)) { - pr_debug("VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now\n"); - /* power up the rail */ - snd_soc_write(w->codec, SN95031_VIHF, 0x27); - msleep(1); - } else if (SND_SOC_DAPM_EVENT_OFF(event)) { - pr_debug("VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n"); - snd_soc_write(w->codec, SN95031_VIHF, 0x24); - } - return 0; -} - -static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - unsigned int ldo = 0, clk_dir = 0, data_dir = 0; - - if (SND_SOC_DAPM_EVENT_ON(event)) { - ldo = BIT(5)|BIT(4); - clk_dir = BIT(0); - data_dir = BIT(7); - } - /* program DMIC LDO, clock and set clock */ - snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); - snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(0), clk_dir); - snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(7), data_dir); - return 0; -} - -static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - unsigned int ldo = 0, clk_dir = 0, data_dir = 0; - - if (SND_SOC_DAPM_EVENT_ON(event)) { - ldo = BIT(5)|BIT(4); - clk_dir = BIT(2); - data_dir = BIT(1); - } - /* program DMIC LDO, clock and set clock */ - snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); - snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(2), clk_dir); - snd_soc_update_bits(w->codec, SN95031_DMICBUF45, BIT(1), data_dir); - return 0; -} - -static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - unsigned int ldo = 0; - - if (SND_SOC_DAPM_EVENT_ON(event)) - ldo = BIT(7)|BIT(6); - - /* program DMIC LDO */ - snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo); - return 0; -} - -/* mux controls */ -static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" }; - -static const struct soc_enum sn95031_micl_enum = - SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts); - -static const struct snd_kcontrol_new sn95031_micl_mux_control = - SOC_DAPM_ENUM("Route", sn95031_micl_enum); - -static const struct soc_enum sn95031_micr_enum = - SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts); - -static const struct snd_kcontrol_new sn95031_micr_mux_control = - SOC_DAPM_ENUM("Route", sn95031_micr_enum); - -static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3", - "DMIC4", "DMIC5", "DMIC6", - "ADC Left", "ADC Right" }; - -static const struct soc_enum sn95031_input1_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts); - -static const struct snd_kcontrol_new sn95031_input1_mux_control = - SOC_DAPM_ENUM("Route", sn95031_input1_enum); - -static const struct soc_enum sn95031_input2_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts); - -static const struct snd_kcontrol_new sn95031_input2_mux_control = - SOC_DAPM_ENUM("Route", sn95031_input2_enum); - -static const struct soc_enum sn95031_input3_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts); - -static const struct snd_kcontrol_new sn95031_input3_mux_control = - SOC_DAPM_ENUM("Route", sn95031_input3_enum); - -static const struct soc_enum sn95031_input4_enum = - SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts); - -static const struct snd_kcontrol_new sn95031_input4_mux_control = - SOC_DAPM_ENUM("Route", sn95031_input4_enum); - -/* capture path controls */ - -static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"}; - -/* 0dB to 30dB in 10dB steps */ -static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0); - -static const struct soc_enum sn95031_micmode1_enum = - SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text); -static const struct soc_enum sn95031_micmode2_enum = - SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text); - -static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"}; - -static const struct soc_enum sn95031_dmic12_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text); -static const struct soc_enum sn95031_dmic34_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text); -static const struct soc_enum sn95031_dmic56_cfg_enum = - SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text); - -static const struct snd_kcontrol_new sn95031_snd_controls[] = { - SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum), - SOC_ENUM("Mic2Mode Capture Route", sn95031_micmode2_enum), - SOC_ENUM("DMIC12 Capture Route", sn95031_dmic12_cfg_enum), - SOC_ENUM("DMIC34 Capture Route", sn95031_dmic34_cfg_enum), - SOC_ENUM("DMIC56 Capture Route", sn95031_dmic56_cfg_enum), - SOC_SINGLE_TLV("Mic1 Capture Volume", SN95031_MICAMP1, - 2, 4, 0, mic_tlv), - SOC_SINGLE_TLV("Mic2 Capture Volume", SN95031_MICAMP2, - 2, 4, 0, mic_tlv), -}; - -/* DAPM widgets */ -static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = { - - /* all end points mic, hs etc */ - SND_SOC_DAPM_OUTPUT("HPOUTL"), - SND_SOC_DAPM_OUTPUT("HPOUTR"), - SND_SOC_DAPM_OUTPUT("EPOUT"), - SND_SOC_DAPM_OUTPUT("IHFOUTL"), - SND_SOC_DAPM_OUTPUT("IHFOUTR"), - SND_SOC_DAPM_OUTPUT("LINEOUTL"), - SND_SOC_DAPM_OUTPUT("LINEOUTR"), - SND_SOC_DAPM_OUTPUT("VIB1OUT"), - SND_SOC_DAPM_OUTPUT("VIB2OUT"), - - SND_SOC_DAPM_INPUT("AMIC1"), /* headset mic */ - SND_SOC_DAPM_INPUT("AMIC2"), - SND_SOC_DAPM_INPUT("DMIC1"), - SND_SOC_DAPM_INPUT("DMIC2"), - SND_SOC_DAPM_INPUT("DMIC3"), - SND_SOC_DAPM_INPUT("DMIC4"), - SND_SOC_DAPM_INPUT("DMIC5"), - SND_SOC_DAPM_INPUT("DMIC6"), - SND_SOC_DAPM_INPUT("LINEINL"), - SND_SOC_DAPM_INPUT("LINEINR"), - - SND_SOC_DAPM_MICBIAS("AMIC1Bias", SN95031_MICBIAS, 2, 0), - SND_SOC_DAPM_MICBIAS("AMIC2Bias", SN95031_MICBIAS, 3, 0), - SND_SOC_DAPM_MICBIAS("DMIC12Bias", SN95031_DMICMUX, 3, 0), - SND_SOC_DAPM_MICBIAS("DMIC34Bias", SN95031_DMICMUX, 4, 0), - SND_SOC_DAPM_MICBIAS("DMIC56Bias", SN95031_DMICMUX, 5, 0), - - SND_SOC_DAPM_SUPPLY("DMIC12supply", SN95031_DMICLK, 0, 0, - sn95031_dmic12_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_SUPPLY("DMIC34supply", SN95031_DMICLK, 1, 0, - sn95031_dmic34_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_SUPPLY("DMIC56supply", SN95031_DMICLK, 2, 0, - sn95031_dmic56_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_AIF_OUT("PCM_Out", "Capture", 0, - SND_SOC_NOPM, 0, 0), - - SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0, - sn95031_vhs_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_SUPPLY("Speaker Rail", SND_SOC_NOPM, 0, 0, - sn95031_vihf_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - - /* playback path driver enables */ - SND_SOC_DAPM_PGA("Headset Left Playback", - SN95031_DRIVEREN, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Headset Right Playback", - SN95031_DRIVEREN, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("Speaker Left Playback", - SN95031_DRIVEREN, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("Speaker Right Playback", - SN95031_DRIVEREN, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Vibra1 Playback", - SN95031_DRIVEREN, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Vibra2 Playback", - SN95031_DRIVEREN, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Earpiece Playback", - SN95031_DRIVEREN, 6, 0, NULL, 0), - SND_SOC_DAPM_PGA("Lineout Left Playback", - SN95031_LOCTL, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Lineout Right Playback", - SN95031_LOCTL, 4, 0, NULL, 0), - - /* playback path filter enable */ - SND_SOC_DAPM_PGA("Headset Left Filter", - SN95031_HSEPRXCTRL, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Headset Right Filter", - SN95031_HSEPRXCTRL, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Speaker Left Filter", - SN95031_IHFRXCTRL, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Speaker Right Filter", - SN95031_IHFRXCTRL, 1, 0, NULL, 0), - - /* DACs */ - SND_SOC_DAPM_DAC("HSDAC Left", "Headset", - SN95031_DACCONFIG, 0, 0), - SND_SOC_DAPM_DAC("HSDAC Right", "Headset", - SN95031_DACCONFIG, 1, 0), - SND_SOC_DAPM_DAC("IHFDAC Left", "Speaker", - SN95031_DACCONFIG, 2, 0), - SND_SOC_DAPM_DAC("IHFDAC Right", "Speaker", - SN95031_DACCONFIG, 3, 0), - SND_SOC_DAPM_DAC("Vibra1 DAC", "Vibra1", - SN95031_VIB1C5, 1, 0), - SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2", - SN95031_VIB2C5, 1, 0), - - /* capture widgets */ - SND_SOC_DAPM_PGA("LineIn Enable Left", SN95031_MICAMP1, - 7, 0, NULL, 0), - SND_SOC_DAPM_PGA("LineIn Enable Right", SN95031_MICAMP2, - 7, 0, NULL, 0), - - SND_SOC_DAPM_PGA("MIC1 Enable", SN95031_MICAMP1, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("MIC2 Enable", SN95031_MICAMP2, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("TX1 Enable", SN95031_AUDIOTXEN, 2, 0, NULL, 0), - SND_SOC_DAPM_PGA("TX2 Enable", SN95031_AUDIOTXEN, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("TX3 Enable", SN95031_AUDIOTXEN, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("TX4 Enable", SN95031_AUDIOTXEN, 5, 0, NULL, 0), - - /* ADC have null stream as they will be turned ON by TX path */ - SND_SOC_DAPM_ADC("ADC Left", NULL, - SN95031_ADCCONFIG, 0, 0), - SND_SOC_DAPM_ADC("ADC Right", NULL, - SN95031_ADCCONFIG, 2, 0), - - SND_SOC_DAPM_MUX("Mic_InputL Capture Route", - SND_SOC_NOPM, 0, 0, &sn95031_micl_mux_control), - SND_SOC_DAPM_MUX("Mic_InputR Capture Route", - SND_SOC_NOPM, 0, 0, &sn95031_micr_mux_control), - - SND_SOC_DAPM_MUX("Txpath1 Capture Route", - SND_SOC_NOPM, 0, 0, &sn95031_input1_mux_control), - SND_SOC_DAPM_MUX("Txpath2 Capture Route", - SND_SOC_NOPM, 0, 0, &sn95031_input2_mux_control), - SND_SOC_DAPM_MUX("Txpath3 Capture Route", - SND_SOC_NOPM, 0, 0, &sn95031_input3_mux_control), - SND_SOC_DAPM_MUX("Txpath4 Capture Route", - SND_SOC_NOPM, 0, 0, &sn95031_input4_mux_control), - -}; - -static const struct snd_soc_dapm_route sn95031_audio_map[] = { - /* headset and earpiece map */ - { "HPOUTL", NULL, "Headset Rail"}, - { "HPOUTR", NULL, "Headset Rail"}, - { "HPOUTL", NULL, "Headset Left Playback" }, - { "HPOUTR", NULL, "Headset Right Playback" }, - { "EPOUT", NULL, "Earpiece Playback" }, - { "Headset Left Playback", NULL, "Headset Left Filter"}, - { "Headset Right Playback", NULL, "Headset Right Filter"}, - { "Earpiece Playback", NULL, "Headset Left Filter"}, - { "Headset Left Filter", NULL, "HSDAC Left"}, - { "Headset Right Filter", NULL, "HSDAC Right"}, - - /* speaker map */ - { "IHFOUTL", NULL, "Speaker Rail"}, - { "IHFOUTR", NULL, "Speaker Rail"}, - { "IHFOUTL", "NULL", "Speaker Left Playback"}, - { "IHFOUTR", "NULL", "Speaker Right Playback"}, - { "Speaker Left Playback", NULL, "Speaker Left Filter"}, - { "Speaker Right Playback", NULL, "Speaker Right Filter"}, - { "Speaker Left Filter", NULL, "IHFDAC Left"}, - { "Speaker Right Filter", NULL, "IHFDAC Right"}, - - /* vibra map */ - { "VIB1OUT", NULL, "Vibra1 Playback"}, - { "Vibra1 Playback", NULL, "Vibra1 DAC"}, - - { "VIB2OUT", NULL, "Vibra2 Playback"}, - { "Vibra2 Playback", NULL, "Vibra2 DAC"}, - - /* lineout */ - { "LINEOUTL", NULL, "Lineout Left Playback"}, - { "LINEOUTR", NULL, "Lineout Right Playback"}, - { "Lineout Left Playback", NULL, "Headset Left Filter"}, - { "Lineout Left Playback", NULL, "Speaker Left Filter"}, - { "Lineout Left Playback", NULL, "Vibra1 DAC"}, - { "Lineout Right Playback", NULL, "Headset Right Filter"}, - { "Lineout Right Playback", NULL, "Speaker Right Filter"}, - { "Lineout Right Playback", NULL, "Vibra2 DAC"}, - - /* Headset (AMIC1) mic */ - { "AMIC1Bias", NULL, "AMIC1"}, - { "MIC1 Enable", NULL, "AMIC1Bias"}, - { "Mic_InputL Capture Route", "AMIC", "MIC1 Enable"}, - - /* AMIC2 */ - { "AMIC2Bias", NULL, "AMIC2"}, - { "MIC2 Enable", NULL, "AMIC2Bias"}, - { "Mic_InputR Capture Route", "AMIC", "MIC2 Enable"}, - - - /* Linein */ - { "LineIn Enable Left", NULL, "LINEINL"}, - { "LineIn Enable Right", NULL, "LINEINR"}, - { "Mic_InputL Capture Route", "LineIn", "LineIn Enable Left"}, - { "Mic_InputR Capture Route", "LineIn", "LineIn Enable Right"}, - - /* ADC connection */ - { "ADC Left", NULL, "Mic_InputL Capture Route"}, - { "ADC Right", NULL, "Mic_InputR Capture Route"}, - - /*DMIC connections */ - { "DMIC1", NULL, "DMIC12supply"}, - { "DMIC2", NULL, "DMIC12supply"}, - { "DMIC3", NULL, "DMIC34supply"}, - { "DMIC4", NULL, "DMIC34supply"}, - { "DMIC5", NULL, "DMIC56supply"}, - { "DMIC6", NULL, "DMIC56supply"}, - - { "DMIC12Bias", NULL, "DMIC1"}, - { "DMIC12Bias", NULL, "DMIC2"}, - { "DMIC34Bias", NULL, "DMIC3"}, - { "DMIC34Bias", NULL, "DMIC4"}, - { "DMIC56Bias", NULL, "DMIC5"}, - { "DMIC56Bias", NULL, "DMIC6"}, - - /*TX path inputs*/ - { "Txpath1 Capture Route", "ADC Left", "ADC Left"}, - { "Txpath2 Capture Route", "ADC Left", "ADC Left"}, - { "Txpath3 Capture Route", "ADC Left", "ADC Left"}, - { "Txpath4 Capture Route", "ADC Left", "ADC Left"}, - { "Txpath1 Capture Route", "ADC Right", "ADC Right"}, - { "Txpath2 Capture Route", "ADC Right", "ADC Right"}, - { "Txpath3 Capture Route", "ADC Right", "ADC Right"}, - { "Txpath4 Capture Route", "ADC Right", "ADC Right"}, - { "Txpath1 Capture Route", "DMIC1", "DMIC1"}, - { "Txpath2 Capture Route", "DMIC1", "DMIC1"}, - { "Txpath3 Capture Route", "DMIC1", "DMIC1"}, - { "Txpath4 Capture Route", "DMIC1", "DMIC1"}, - { "Txpath1 Capture Route", "DMIC2", "DMIC2"}, - { "Txpath2 Capture Route", "DMIC2", "DMIC2"}, - { "Txpath3 Capture Route", "DMIC2", "DMIC2"}, - { "Txpath4 Capture Route", "DMIC2", "DMIC2"}, - { "Txpath1 Capture Route", "DMIC3", "DMIC3"}, - { "Txpath2 Capture Route", "DMIC3", "DMIC3"}, - { "Txpath3 Capture Route", "DMIC3", "DMIC3"}, - { "Txpath4 Capture Route", "DMIC3", "DMIC3"}, - { "Txpath1 Capture Route", "DMIC4", "DMIC4"}, - { "Txpath2 Capture Route", "DMIC4", "DMIC4"}, - { "Txpath3 Capture Route", "DMIC4", "DMIC4"}, - { "Txpath4 Capture Route", "DMIC4", "DMIC4"}, - { "Txpath1 Capture Route", "DMIC5", "DMIC5"}, - { "Txpath2 Capture Route", "DMIC5", "DMIC5"}, - { "Txpath3 Capture Route", "DMIC5", "DMIC5"}, - { "Txpath4 Capture Route", "DMIC5", "DMIC5"}, - { "Txpath1 Capture Route", "DMIC6", "DMIC6"}, - { "Txpath2 Capture Route", "DMIC6", "DMIC6"}, - { "Txpath3 Capture Route", "DMIC6", "DMIC6"}, - { "Txpath4 Capture Route", "DMIC6", "DMIC6"}, - - /* tx path */ - { "TX1 Enable", NULL, "Txpath1 Capture Route"}, - { "TX2 Enable", NULL, "Txpath2 Capture Route"}, - { "TX3 Enable", NULL, "Txpath3 Capture Route"}, - { "TX4 Enable", NULL, "Txpath4 Capture Route"}, - { "PCM_Out", NULL, "TX1 Enable"}, - { "PCM_Out", NULL, "TX2 Enable"}, - { "PCM_Out", NULL, "TX3 Enable"}, - { "PCM_Out", NULL, "TX4 Enable"}, - -}; - -/* speaker and headset mutes, for audio pops and clicks */ -static int sn95031_pcm_hs_mute(struct snd_soc_dai *dai, int mute) -{ - snd_soc_update_bits(dai->codec, - SN95031_HSLVOLCTRL, BIT(7), (!mute << 7)); - snd_soc_update_bits(dai->codec, - SN95031_HSRVOLCTRL, BIT(7), (!mute << 7)); - return 0; -} - -static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute) -{ - snd_soc_update_bits(dai->codec, - SN95031_IHFLVOLCTRL, BIT(7), (!mute << 7)); - snd_soc_update_bits(dai->codec, - SN95031_IHFRVOLCTRL, BIT(7), (!mute << 7)); - return 0; -} - -static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - unsigned int format, rate; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - format = BIT(4)|BIT(5); - break; - - case SNDRV_PCM_FORMAT_S24_LE: - format = 0; - break; - default: - return -EINVAL; - } - snd_soc_update_bits(dai->codec, SN95031_PCM2C2, - BIT(4)|BIT(5), format); - - switch (params_rate(params)) { - case 48000: - pr_debug("RATE_48000\n"); - rate = 0; - break; - - case 44100: - pr_debug("RATE_44100\n"); - rate = BIT(7); - break; - - default: - pr_err("ERR rate %d\n", params_rate(params)); - return -EINVAL; - } - snd_soc_update_bits(dai->codec, SN95031_PCM1C1, BIT(7), rate); - - return 0; -} - -/* Codec DAI section */ -static const struct snd_soc_dai_ops sn95031_headset_dai_ops = { - .digital_mute = sn95031_pcm_hs_mute, - .hw_params = sn95031_pcm_hw_params, -}; - -static const struct snd_soc_dai_ops sn95031_speaker_dai_ops = { - .digital_mute = sn95031_pcm_spkr_mute, - .hw_params = sn95031_pcm_hw_params, -}; - -static const struct snd_soc_dai_ops sn95031_vib1_dai_ops = { - .hw_params = sn95031_pcm_hw_params, -}; - -static const struct snd_soc_dai_ops sn95031_vib2_dai_ops = { - .hw_params = sn95031_pcm_hw_params, -}; - -static struct snd_soc_dai_driver sn95031_dais[] = { -{ - .name = "SN95031 Headset", - .playback = { - .stream_name = "Headset", - .channels_min = 2, - .channels_max = 2, - .rates = SN95031_RATES, - .formats = SN95031_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 5, - .rates = SN95031_RATES, - .formats = SN95031_FORMATS, - }, - .ops = &sn95031_headset_dai_ops, -}, -{ .name = "SN95031 Speaker", - .playback = { - .stream_name = "Speaker", - .channels_min = 2, - .channels_max = 2, - .rates = SN95031_RATES, - .formats = SN95031_FORMATS, - }, - .ops = &sn95031_speaker_dai_ops, -}, -{ .name = "SN95031 Vibra1", - .playback = { - .stream_name = "Vibra1", - .channels_min = 1, - .channels_max = 1, - .rates = SN95031_RATES, - .formats = SN95031_FORMATS, - }, - .ops = &sn95031_vib1_dai_ops, -}, -{ .name = "SN95031 Vibra2", - .playback = { - .stream_name = "Vibra2", - .channels_min = 1, - .channels_max = 1, - .rates = SN95031_RATES, - .formats = SN95031_FORMATS, - }, - .ops = &sn95031_vib2_dai_ops, -}, -}; - -static inline void sn95031_disable_jack_btn(struct snd_soc_codec *codec) -{ - snd_soc_write(codec, SN95031_BTNCTRL2, 0x00); -} - -static inline void sn95031_enable_jack_btn(struct snd_soc_codec *codec) -{ - snd_soc_write(codec, SN95031_BTNCTRL1, 0x77); - snd_soc_write(codec, SN95031_BTNCTRL2, 0x01); -} - -static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack) -{ - int micbias = sn95031_get_mic_bias(mfld_jack->codec); - - int jack_type = snd_soc_jack_get_type(mfld_jack, micbias); - - pr_debug("jack type detected = %d\n", jack_type); - if (jack_type == SND_JACK_HEADSET) - sn95031_enable_jack_btn(mfld_jack->codec); - return jack_type; -} - -void sn95031_jack_detection(struct mfld_jack_data *jack_data) -{ - unsigned int status; - unsigned int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET; - - pr_debug("interrupt id read in sram = 0x%x\n", jack_data->intr_id); - if (jack_data->intr_id & 0x1) { - pr_debug("short_push detected\n"); - status = SND_JACK_HEADSET | SND_JACK_BTN_0; - } else if (jack_data->intr_id & 0x2) { - pr_debug("long_push detected\n"); - status = SND_JACK_HEADSET | SND_JACK_BTN_1; - } else if (jack_data->intr_id & 0x4) { - pr_debug("headset or headphones inserted\n"); - status = sn95031_get_headset_state(jack_data->mfld_jack); - } else if (jack_data->intr_id & 0x8) { - pr_debug("headset or headphones removed\n"); - status = 0; - sn95031_disable_jack_btn(jack_data->mfld_jack->codec); - } else { - pr_err("unidentified interrupt\n"); - return; - } - - snd_soc_jack_report(jack_data->mfld_jack, status, mask); - /*button pressed and released so we send explicit button release */ - if ((status & SND_JACK_BTN_0) | (status & SND_JACK_BTN_1)) - snd_soc_jack_report(jack_data->mfld_jack, - SND_JACK_HEADSET, mask); -} -EXPORT_SYMBOL_GPL(sn95031_jack_detection); - -/* codec registration */ -static int sn95031_codec_probe(struct snd_soc_codec *codec) -{ - pr_debug("codec_probe called\n"); - - /* PCM interface config - * This sets the pcm rx slot conguration to max 6 slots - * for max 4 dais (2 stereo and 2 mono) - */ - snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10); - snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32); - snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54); - snd_soc_write(codec, SN95031_PCM2TXSLOT01, 0x10); - snd_soc_write(codec, SN95031_PCM2TXSLOT23, 0x32); - /* pcm port setting - * This sets the pcm port to slave and clock at 19.2Mhz which - * can support 6slots, sampling rate set per stream in hw-params - */ - snd_soc_write(codec, SN95031_PCM1C1, 0x00); - snd_soc_write(codec, SN95031_PCM2C1, 0x01); - snd_soc_write(codec, SN95031_PCM2C2, 0x0A); - snd_soc_write(codec, SN95031_HSMIXER, BIT(0)|BIT(4)); - /* vendor vibra workround, the vibras are muted by - * custom register so unmute them - */ - snd_soc_write(codec, SN95031_SSR5, 0x80); - snd_soc_write(codec, SN95031_SSR6, 0x80); - snd_soc_write(codec, SN95031_VIB1C5, 0x00); - snd_soc_write(codec, SN95031_VIB2C5, 0x00); - /* configure vibras for pcm port */ - snd_soc_write(codec, SN95031_VIB1C3, 0x00); - snd_soc_write(codec, SN95031_VIB2C3, 0x00); - - /* soft mute ramp time */ - snd_soc_write(codec, SN95031_SOFTMUTE, 0x3); - /* fix the initial volume at 1dB, - * default in +9dB, - * 1dB give optimal swing on DAC, amps - */ - snd_soc_write(codec, SN95031_HSLVOLCTRL, 0x08); - snd_soc_write(codec, SN95031_HSRVOLCTRL, 0x08); - snd_soc_write(codec, SN95031_IHFLVOLCTRL, 0x08); - snd_soc_write(codec, SN95031_IHFRVOLCTRL, 0x08); - /* dac mode and lineout workaround */ - snd_soc_write(codec, SN95031_SSR2, 0x10); - snd_soc_write(codec, SN95031_SSR3, 0x40); - - snd_soc_add_codec_controls(codec, sn95031_snd_controls, - ARRAY_SIZE(sn95031_snd_controls)); - - return 0; -} - -static int sn95031_codec_remove(struct snd_soc_codec *codec) -{ - pr_debug("codec_remove called\n"); - sn95031_set_vaud_bias(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -struct snd_soc_codec_driver sn95031_codec = { - .probe = sn95031_codec_probe, - .remove = sn95031_codec_remove, - .read = sn95031_read, - .write = sn95031_write, - .set_bias_level = sn95031_set_vaud_bias, - .idle_bias_off = true, - .dapm_widgets = sn95031_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets), - .dapm_routes = sn95031_audio_map, - .num_dapm_routes = ARRAY_SIZE(sn95031_audio_map), -}; - -static int __devinit sn95031_device_probe(struct platform_device *pdev) -{ - pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev)); - return snd_soc_register_codec(&pdev->dev, &sn95031_codec, - sn95031_dais, ARRAY_SIZE(sn95031_dais)); -} - -static int __devexit sn95031_device_remove(struct platform_device *pdev) -{ - pr_debug("codec device remove called\n"); - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver sn95031_codec_driver = { - .driver = { - .name = "sn95031", - .owner = THIS_MODULE, - }, - .probe = sn95031_device_probe, - .remove = __devexit_p(sn95031_device_remove), -}; - -module_platform_driver(sn95031_codec_driver); - -MODULE_DESCRIPTION("ASoC TI SN95031 codec driver"); -MODULE_AUTHOR("Vinod Koul "); -MODULE_AUTHOR("Harsha Priya "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:sn95031"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/sn95031.h b/ANDROID_3.4.5/sound/soc/codecs/sn95031.h deleted file mode 100644 index 20376d23..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/sn95031.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * sn95031.h - TI sn95031 Codec driver - * - * Copyright (C) 2010 Intel Corp - * Author: Vinod Koul - * Author: Harsha Priya - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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; version 2 of the License. - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * - */ -#ifndef _SN95031_H -#define _SN95031_H - -/*register map*/ -#define SN95031_VAUD 0xDB -#define SN95031_VHSP 0xDC -#define SN95031_VHSN 0xDD -#define SN95031_VIHF 0xC9 - -#define SN95031_AUDPLLCTRL 0x240 -#define SN95031_DMICBUF0123 0x241 -#define SN95031_DMICBUF45 0x242 -#define SN95031_DMICGPO 0x244 -#define SN95031_DMICMUX 0x245 -#define SN95031_DMICLK 0x246 -#define SN95031_MICBIAS 0x247 -#define SN95031_ADCCONFIG 0x248 -#define SN95031_MICAMP1 0x249 -#define SN95031_MICAMP2 0x24A -#define SN95031_NOISEMUX 0x24B -#define SN95031_AUDIOMUX12 0x24C -#define SN95031_AUDIOMUX34 0x24D -#define SN95031_AUDIOSINC 0x24E -#define SN95031_AUDIOTXEN 0x24F -#define SN95031_HSEPRXCTRL 0x250 -#define SN95031_IHFRXCTRL 0x251 -#define SN95031_HSMIXER 0x256 -#define SN95031_DACCONFIG 0x257 -#define SN95031_SOFTMUTE 0x258 -#define SN95031_HSLVOLCTRL 0x259 -#define SN95031_HSRVOLCTRL 0x25A -#define SN95031_IHFLVOLCTRL 0x25B -#define SN95031_IHFRVOLCTRL 0x25C -#define SN95031_DRIVEREN 0x25D -#define SN95031_LOCTL 0x25E -#define SN95031_VIB1C1 0x25F -#define SN95031_VIB1C2 0x260 -#define SN95031_VIB1C3 0x261 -#define SN95031_VIB1SPIPCM1 0x262 -#define SN95031_VIB1SPIPCM2 0x263 -#define SN95031_VIB1C5 0x264 -#define SN95031_VIB2C1 0x265 -#define SN95031_VIB2C2 0x266 -#define SN95031_VIB2C3 0x267 -#define SN95031_VIB2SPIPCM1 0x268 -#define SN95031_VIB2SPIPCM2 0x269 -#define SN95031_VIB2C5 0x26A -#define SN95031_BTNCTRL1 0x26B -#define SN95031_BTNCTRL2 0x26C -#define SN95031_PCM1TXSLOT01 0x26D -#define SN95031_PCM1TXSLOT23 0x26E -#define SN95031_PCM1TXSLOT45 0x26F -#define SN95031_PCM1RXSLOT0_3 0x270 -#define SN95031_PCM1RXSLOT45 0x271 -#define SN95031_PCM2TXSLOT01 0x272 -#define SN95031_PCM2TXSLOT23 0x273 -#define SN95031_PCM2TXSLOT45 0x274 -#define SN95031_PCM2RXSLOT01 0x275 -#define SN95031_PCM2RXSLOT23 0x276 -#define SN95031_PCM2RXSLOT45 0x277 -#define SN95031_PCM1C1 0x278 -#define SN95031_PCM1C2 0x279 -#define SN95031_PCM1C3 0x27A -#define SN95031_PCM2C1 0x27B -#define SN95031_PCM2C2 0x27C -/*end codec register defn*/ - -/*vendor defn these are not part of avp*/ -#define SN95031_SSR2 0x381 -#define SN95031_SSR3 0x382 -#define SN95031_SSR5 0x384 -#define SN95031_SSR6 0x385 - -/* ADC registers */ - -#define SN95031_ADC1CNTL1 0x1C0 -#define SN95031_ADC_ENBL 0x10 -#define SN95031_ADC_START 0x08 -#define SN95031_ADC1CNTL3 0x1C2 -#define SN95031_ADCTHERM_ENBL 0x04 -#define SN95031_ADCRRDATA_ENBL 0x05 -#define SN95031_STOPBIT_MASK 16 -#define SN95031_ADCTHERM_MASK 4 -#define SN95031_ADC_CHANLS_MAX 15 /* Number of ADC channels */ -#define SN95031_ADC_LOOP_MAX (SN95031_ADC_CHANLS_MAX - 1) -#define SN95031_ADC_NO_LOOP 0x07 -#define SN95031_AUDIO_GPIO_CTRL 0x070 - -/* ADC channel code values */ -#define SN95031_AUDIO_DETECT_CODE 0x06 - -/* ADC base addresses */ -#define SN95031_ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */ -#define SN95031_ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */ -/* multipier to convert to mV */ -#define SN95031_ADC_ONE_LSB_MULTIPLIER 2346 - - -struct mfld_jack_data { - int intr_id; - int micbias_vol; - struct snd_soc_jack *mfld_jack; -}; - -extern void sn95031_jack_detection(struct mfld_jack_data *jack_data); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/spdif_transciever.c b/ANDROID_3.4.5/sound/soc/codecs/spdif_transciever.c deleted file mode 100644 index 112a49d6..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/spdif_transciever.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * ALSA SoC SPDIF DIT driver - * - * This driver is used by controllers which can operate in DIT (SPDI/F) where - * no codec is needed. This file provides stub codec that can be used - * in these configurations. TI DaVinci Audio controller uses this driver. - * - * Author: Steve Chen, - * Copyright: (C) 2009 MontaVista Software, Inc., - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "spdif-dit" - -#define STUB_RATES SNDRV_PCM_RATE_8000_96000 -#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE - - -static struct snd_soc_codec_driver soc_codec_spdif_dit; - -static struct snd_soc_dai_driver dit_stub_dai = { - .name = "dit-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 384, - .rates = STUB_RATES, - .formats = STUB_FORMATS, - }, -}; - -static int spdif_dit_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit, - &dit_stub_dai, 1); -} - -static int spdif_dit_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver spdif_dit_driver = { - .probe = spdif_dit_probe, - .remove = spdif_dit_remove, - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(spdif_dit_driver); - -MODULE_AUTHOR("Steve Chen "); -MODULE_DESCRIPTION("SPDIF dummy codec driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ssm2602.c b/ANDROID_3.4.5/sound/soc/codecs/ssm2602.c deleted file mode 100644 index de2b2054..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ssm2602.c +++ /dev/null @@ -1,773 +0,0 @@ -/* - * File: sound/soc/codecs/ssm2602.c - * Author: Cliff Cai - * - * Created: Tue June 06 2008 - * Description: Driver for ssm2602 sound chip - * - * Modified: - * Copyright 2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ssm2602.h" - -#define SSM2602_VERSION "0.1" - -enum ssm2602_type { - SSM2602, - SSM2604, -}; - -/* codec private data */ -struct ssm2602_priv { - unsigned int sysclk; - enum snd_soc_control_type control_type; - struct snd_pcm_substream *master_substream; - struct snd_pcm_substream *slave_substream; - - enum ssm2602_type type; - unsigned int clk_out_pwr; -}; - -/* - * ssm2602 register cache - * We can't read the ssm2602 register space when we are - * using 2 wire for device control, so we cache them instead. - * There is no point in caching the reset register - */ -static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { - 0x0097, 0x0097, 0x0079, 0x0079, - 0x000a, 0x0008, 0x009f, 0x000a, - 0x0000, 0x0000 -}; - -#define ssm2602_reset(c) snd_soc_write(c, SSM2602_RESET, 0) - -/*Appending several "None"s just for OSS mixer use*/ -static const char *ssm2602_input_select[] = { - "Line", "Mic", "None", "None", "None", - "None", "None", "None", -}; - -static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; - -static const struct soc_enum ssm2602_enum[] = { - SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select), - SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), -}; - -static const unsigned int ssm260x_outmix_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 47, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), - 48, 127, TLV_DB_SCALE_ITEM(-7400, 100, 0), -}; - -static const DECLARE_TLV_DB_SCALE(ssm260x_inpga_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(ssm260x_sidetone_tlv, -1500, 300, 0); - -static const struct snd_kcontrol_new ssm260x_snd_controls[] = { -SOC_DOUBLE_R_TLV("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 45, 0, - ssm260x_inpga_tlv), -SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), - -SOC_SINGLE("ADC High Pass Filter Switch", SSM2602_APDIGI, 0, 1, 1), -SOC_SINGLE("Store DC Offset Switch", SSM2602_APDIGI, 4, 1, 0), - -SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), -}; - -static const struct snd_kcontrol_new ssm2602_snd_controls[] = { -SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2602_LOUT1V, SSM2602_ROUT1V, - 0, 127, 0, ssm260x_outmix_tlv), -SOC_DOUBLE_R("Master Playback ZC Switch", SSM2602_LOUT1V, SSM2602_ROUT1V, - 7, 1, 0), -SOC_SINGLE_TLV("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1, - ssm260x_sidetone_tlv), - -SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), -SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 8, 1, 0), -SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), -}; - -/* Output Mixer */ -static const struct snd_kcontrol_new ssm260x_output_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), -SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0), -SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0), -}; - -/* Input mux */ -static const struct snd_kcontrol_new ssm2602_input_mux_controls = -SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]); - -static const struct snd_soc_dapm_widget ssm260x_dapm_widgets[] = { -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1), -SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1), -SND_SOC_DAPM_PGA("Line Input", SSM2602_PWR, 0, 1, NULL, 0), - -SND_SOC_DAPM_SUPPLY("Digital Core Power", SSM2602_ACTIVE, 0, 0, NULL, 0), - -SND_SOC_DAPM_OUTPUT("LOUT"), -SND_SOC_DAPM_OUTPUT("ROUT"), -SND_SOC_DAPM_INPUT("RLINEIN"), -SND_SOC_DAPM_INPUT("LLINEIN"), -}; - -static const struct snd_soc_dapm_widget ssm2602_dapm_widgets[] = { -SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1, - ssm260x_output_mixer_controls, - ARRAY_SIZE(ssm260x_output_mixer_controls)), - -SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls), -SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1), - -SND_SOC_DAPM_OUTPUT("LHPOUT"), -SND_SOC_DAPM_OUTPUT("RHPOUT"), -SND_SOC_DAPM_INPUT("MICIN"), -}; - -static const struct snd_soc_dapm_widget ssm2604_dapm_widgets[] = { -SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, - ssm260x_output_mixer_controls, - ARRAY_SIZE(ssm260x_output_mixer_controls) - 1), /* Last element is the mic */ -}; - -static const struct snd_soc_dapm_route ssm260x_routes[] = { - {"DAC", NULL, "Digital Core Power"}, - {"ADC", NULL, "Digital Core Power"}, - - {"Output Mixer", "Line Bypass Switch", "Line Input"}, - {"Output Mixer", "HiFi Playback Switch", "DAC"}, - - {"ROUT", NULL, "Output Mixer"}, - {"LOUT", NULL, "Output Mixer"}, - - {"Line Input", NULL, "LLINEIN"}, - {"Line Input", NULL, "RLINEIN"}, -}; - -static const struct snd_soc_dapm_route ssm2602_routes[] = { - {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, - - {"RHPOUT", NULL, "Output Mixer"}, - {"LHPOUT", NULL, "Output Mixer"}, - - {"Input Mux", "Line", "Line Input"}, - {"Input Mux", "Mic", "Mic Bias"}, - {"ADC", NULL, "Input Mux"}, - - {"Mic Bias", NULL, "MICIN"}, -}; - -static const struct snd_soc_dapm_route ssm2604_routes[] = { - {"ADC", NULL, "Line Input"}, -}; - -struct ssm2602_coeff { - u32 mclk; - u32 rate; - u8 srate; -}; - -#define SSM2602_COEFF_SRATE(sr, bosr, usb) (((sr) << 2) | ((bosr) << 1) | (usb)) - -/* codec mclk clock coefficients */ -static const struct ssm2602_coeff ssm2602_coeff_table[] = { - /* 48k */ - {12288000, 48000, SSM2602_COEFF_SRATE(0x0, 0x0, 0x0)}, - {18432000, 48000, SSM2602_COEFF_SRATE(0x0, 0x1, 0x0)}, - {12000000, 48000, SSM2602_COEFF_SRATE(0x0, 0x0, 0x1)}, - - /* 32k */ - {12288000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x0)}, - {18432000, 32000, SSM2602_COEFF_SRATE(0x6, 0x1, 0x0)}, - {12000000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x1)}, - - /* 8k */ - {12288000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x0)}, - {18432000, 8000, SSM2602_COEFF_SRATE(0x3, 0x1, 0x0)}, - {11289600, 8000, SSM2602_COEFF_SRATE(0xb, 0x0, 0x0)}, - {16934400, 8000, SSM2602_COEFF_SRATE(0xb, 0x1, 0x0)}, - {12000000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x1)}, - - /* 96k */ - {12288000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x0)}, - {18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)}, - {12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)}, - - /* 44.1k */ - {11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)}, - {16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)}, - {12000000, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x1)}, - - /* 88.2k */ - {11289600, 88200, SSM2602_COEFF_SRATE(0xf, 0x0, 0x0)}, - {16934400, 88200, SSM2602_COEFF_SRATE(0xf, 0x1, 0x0)}, - {12000000, 88200, SSM2602_COEFF_SRATE(0xf, 0x1, 0x1)}, -}; - -static inline int ssm2602_get_coeff(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ssm2602_coeff_table); i++) { - if (ssm2602_coeff_table[i].rate == rate && - ssm2602_coeff_table[i].mclk == mclk) - return ssm2602_coeff_table[i].srate; - } - return -EINVAL; -} - -static int ssm2602_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, SSM2602_IFACE) & 0xfff3; - int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params)); - - if (substream == ssm2602->slave_substream) { - dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n"); - return 0; - } - - if (srate < 0) - return srate; - - snd_soc_write(codec, SSM2602_SRATE, srate); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x000c; - break; - } - snd_soc_write(codec, SSM2602_IFACE, iface); - return 0; -} - -static int ssm2602_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - struct snd_pcm_runtime *master_runtime; - - /* The DAI has shared clocks so if we already have a playback or - * capture going then constrain this substream to match it. - * TODO: the ssm2602 allows pairs of non-matching PB/REC rates - */ - if (ssm2602->master_substream) { - master_runtime = ssm2602->master_substream->runtime; - dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n", - master_runtime->sample_bits, - master_runtime->rate); - - if (master_runtime->rate != 0) - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - master_runtime->rate, - master_runtime->rate); - - if (master_runtime->sample_bits != 0) - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - master_runtime->sample_bits, - master_runtime->sample_bits); - - ssm2602->slave_substream = substream; - } else - ssm2602->master_substream = substream; - - return 0; -} - -static void ssm2602_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - - if (ssm2602->master_substream == substream) - ssm2602->master_substream = ssm2602->slave_substream; - - ssm2602->slave_substream = NULL; -} - - -static int ssm2602_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - if (mute) - snd_soc_update_bits(codec, SSM2602_APDIGI, - APDIGI_ENABLE_DAC_MUTE, - APDIGI_ENABLE_DAC_MUTE); - else - snd_soc_update_bits(codec, SSM2602_APDIGI, - APDIGI_ENABLE_DAC_MUTE, 0); - return 0; -} - -static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - - if (dir == SND_SOC_CLOCK_IN) { - if (clk_id != SSM2602_SYSCLK) - return -EINVAL; - - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - ssm2602->sysclk = freq; - break; - default: - return -EINVAL; - } - } else { - unsigned int mask; - - switch (clk_id) { - case SSM2602_CLK_CLKOUT: - mask = PWR_CLK_OUT_PDN; - break; - case SSM2602_CLK_XTO: - mask = PWR_OSC_PDN; - break; - default: - return -EINVAL; - } - - if (freq == 0) - ssm2602->clk_out_pwr |= mask; - else - ssm2602->clk_out_pwr &= ~mask; - - snd_soc_update_bits(codec, SSM2602_PWR, - PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr); - } - - return 0; -} - -static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface |= 0x0040; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0013; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0003; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - /* set iface */ - snd_soc_write(codec, SSM2602_IFACE, iface); - return 0; -} - -static int ssm2602_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - - switch (level) { - case SND_SOC_BIAS_ON: - /* vref/mid on, osc and clkout on if enabled */ - snd_soc_update_bits(codec, SSM2602_PWR, - PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN, - ssm2602->clk_out_pwr); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - /* everything off except vref/vmid, */ - snd_soc_update_bits(codec, SSM2602_PWR, - PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN, - PWR_CLK_OUT_PDN | PWR_OSC_PDN); - break; - case SND_SOC_BIAS_OFF: - /* everything off */ - snd_soc_update_bits(codec, SSM2602_PWR, - PWR_POWER_OFF, PWR_POWER_OFF); - break; - - } - codec->dapm.bias_level = level; - return 0; -} - -#define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_32000 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) - -#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops ssm2602_dai_ops = { - .startup = ssm2602_startup, - .hw_params = ssm2602_hw_params, - .shutdown = ssm2602_shutdown, - .digital_mute = ssm2602_mute, - .set_sysclk = ssm2602_set_dai_sysclk, - .set_fmt = ssm2602_set_dai_fmt, -}; - -static struct snd_soc_dai_driver ssm2602_dai = { - .name = "ssm2602-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SSM2602_RATES, - .formats = SSM2602_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SSM2602_RATES, - .formats = SSM2602_FORMATS,}, - .ops = &ssm2602_dai_ops, -}; - -static int ssm2602_suspend(struct snd_soc_codec *codec) -{ - ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int ssm2602_resume(struct snd_soc_codec *codec) -{ - snd_soc_cache_sync(codec); - - ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int ssm2602_probe(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - snd_soc_update_bits(codec, SSM2602_LOUT1V, - LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH); - snd_soc_update_bits(codec, SSM2602_ROUT1V, - ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH); - - ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls, - ARRAY_SIZE(ssm2602_snd_controls)); - if (ret) - return ret; - - ret = snd_soc_dapm_new_controls(dapm, ssm2602_dapm_widgets, - ARRAY_SIZE(ssm2602_dapm_widgets)); - if (ret) - return ret; - - return snd_soc_dapm_add_routes(dapm, ssm2602_routes, - ARRAY_SIZE(ssm2602_routes)); -} - -static int ssm2604_probe(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets, - ARRAY_SIZE(ssm2604_dapm_widgets)); - if (ret) - return ret; - - return snd_soc_dapm_add_routes(dapm, ssm2604_routes, - ARRAY_SIZE(ssm2604_routes)); -} - -static int ssm260x_probe(struct snd_soc_codec *codec) -{ - struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); - int ret; - - pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, ssm2602->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = ssm2602_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - return ret; - } - - /* set the update bits */ - snd_soc_update_bits(codec, SSM2602_LINVOL, - LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH); - snd_soc_update_bits(codec, SSM2602_RINVOL, - RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH); - /*select Line in as default input*/ - snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC | - APANA_ENABLE_MIC_BOOST); - - switch (ssm2602->type) { - case SSM2602: - ret = ssm2602_probe(codec); - break; - case SSM2604: - ret = ssm2604_probe(codec); - break; - } - - if (ret) - return ret; - - ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -/* remove everything here */ -static int ssm2602_remove(struct snd_soc_codec *codec) -{ - ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { - .probe = ssm260x_probe, - .remove = ssm2602_remove, - .suspend = ssm2602_suspend, - .resume = ssm2602_resume, - .set_bias_level = ssm2602_set_bias_level, - .reg_cache_size = ARRAY_SIZE(ssm2602_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = ssm2602_reg, - - .controls = ssm260x_snd_controls, - .num_controls = ARRAY_SIZE(ssm260x_snd_controls), - .dapm_widgets = ssm260x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(ssm260x_dapm_widgets), - .dapm_routes = ssm260x_routes, - .num_dapm_routes = ARRAY_SIZE(ssm260x_routes), -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit ssm2602_spi_probe(struct spi_device *spi) -{ - struct ssm2602_priv *ssm2602; - int ret; - - ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv), - GFP_KERNEL); - if (ssm2602 == NULL) - return -ENOMEM; - - spi_set_drvdata(spi, ssm2602); - ssm2602->control_type = SND_SOC_SPI; - ssm2602->type = SSM2602; - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_ssm2602, &ssm2602_dai, 1); - return ret; -} - -static int __devexit ssm2602_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ssm2602_spi_driver = { - .driver = { - .name = "ssm2602", - .owner = THIS_MODULE, - }, - .probe = ssm2602_spi_probe, - .remove = __devexit_p(ssm2602_spi_remove), -}; -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -/* - * ssm2602 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x1a - * high = 0x1b - */ -static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct ssm2602_priv *ssm2602; - int ret; - - ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv), - GFP_KERNEL); - if (ssm2602 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, ssm2602); - ssm2602->control_type = SND_SOC_I2C; - ssm2602->type = id->driver_data; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_ssm2602, &ssm2602_dai, 1); - return ret; -} - -static int __devexit ssm2602_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id ssm2602_i2c_id[] = { - { "ssm2602", SSM2602 }, - { "ssm2603", SSM2602 }, - { "ssm2604", SSM2604 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); - -/* corgi i2c codec control layer */ -static struct i2c_driver ssm2602_i2c_driver = { - .driver = { - .name = "ssm2602", - .owner = THIS_MODULE, - }, - .probe = ssm2602_i2c_probe, - .remove = __devexit_p(ssm2602_i2c_remove), - .id_table = ssm2602_i2c_id, -}; -#endif - - -static int __init ssm2602_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ssm2602_spi_driver); - if (ret) - return ret; -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&ssm2602_i2c_driver); - if (ret) - return ret; -#endif - - return ret; -} -module_init(ssm2602_modinit); - -static void __exit ssm2602_exit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ssm2602_spi_driver); -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&ssm2602_i2c_driver); -#endif -} -module_exit(ssm2602_exit); - -MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); -MODULE_AUTHOR("Cliff Cai"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/ssm2602.h b/ANDROID_3.4.5/sound/soc/codecs/ssm2602.h deleted file mode 100644 index fbd07d7b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/ssm2602.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * File: sound/soc/codecs/ssm2602.h - * Author: Cliff Cai - * - * Created: Tue June 06 2008 - * - * Modified: - * Copyright 2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _SSM2602_H -#define _SSM2602_H - -/* SSM2602 Codec Register definitions */ - -#define SSM2602_LINVOL 0x00 -#define SSM2602_RINVOL 0x01 -#define SSM2602_LOUT1V 0x02 -#define SSM2602_ROUT1V 0x03 -#define SSM2602_APANA 0x04 -#define SSM2602_APDIGI 0x05 -#define SSM2602_PWR 0x06 -#define SSM2602_IFACE 0x07 -#define SSM2602_SRATE 0x08 -#define SSM2602_ACTIVE 0x09 -#define SSM2602_RESET 0x0f - -/*SSM2602 Codec Register Field definitions - *(Mask value to extract the corresponding Register field) - */ - -/*Left ADC Volume Control (SSM2602_REG_LEFT_ADC_VOL)*/ -#define LINVOL_LIN_VOL 0x01F /* Left Channel PGA Volume control */ -#define LINVOL_LIN_ENABLE_MUTE 0x080 /* Left Channel Input Mute */ -#define LINVOL_LRIN_BOTH 0x100 /* Left Channel Line Input Volume update */ - -/*Right ADC Volume Control (SSM2602_REG_RIGHT_ADC_VOL)*/ -#define RINVOL_RIN_VOL 0x01F /* Right Channel PGA Volume control */ -#define RINVOL_RIN_ENABLE_MUTE 0x080 /* Right Channel Input Mute */ -#define RINVOL_RLIN_BOTH 0x100 /* Right Channel Line Input Volume update */ - -/*Left DAC Volume Control (SSM2602_REG_LEFT_DAC_VOL)*/ -#define LOUT1V_LHP_VOL 0x07F /* Left Channel Headphone volume control */ -#define LOUT1V_ENABLE_LZC 0x080 /* Left Channel Zero cross detect enable */ -#define LOUT1V_LRHP_BOTH 0x100 /* Left Channel Headphone volume update */ - -/*Right DAC Volume Control (SSM2602_REG_RIGHT_DAC_VOL)*/ -#define ROUT1V_RHP_VOL 0x07F /* Right Channel Headphone volume control */ -#define ROUT1V_ENABLE_RZC 0x080 /* Right Channel Zero cross detect enable */ -#define ROUT1V_RLHP_BOTH 0x100 /* Right Channel Headphone volume update */ - -/*Analogue Audio Path Control (SSM2602_REG_ANALOGUE_PATH)*/ -#define APANA_ENABLE_MIC_BOOST 0x001 /* Primary Microphone Amplifier gain booster control */ -#define APANA_ENABLE_MIC_MUTE 0x002 /* Microphone Mute Control */ -#define APANA_ADC_IN_SELECT 0x004 /* Microphone/Line IN select to ADC (1=MIC, 0=Line In) */ -#define APANA_ENABLE_BYPASS 0x008 /* Line input bypass to line output */ -#define APANA_SELECT_DAC 0x010 /* Select DAC (1=Select DAC, 0=Don't Select DAC) */ -#define APANA_ENABLE_SIDETONE 0x020 /* Enable/Disable Side Tone */ -#define APANA_SIDETONE_ATTN 0x0C0 /* Side Tone Attenuation */ -#define APANA_ENABLE_MIC_BOOST2 0x100 /* Secondary Microphone Amplifier gain booster control */ - -/*Digital Audio Path Control (SSM2602_REG_DIGITAL_PATH)*/ -#define APDIGI_ENABLE_ADC_HPF 0x001 /* Enable/Disable ADC Highpass Filter */ -#define APDIGI_DE_EMPHASIS 0x006 /* De-Emphasis Control */ -#define APDIGI_ENABLE_DAC_MUTE 0x008 /* DAC Mute Control */ -#define APDIGI_STORE_OFFSET 0x010 /* Store/Clear DC offset when HPF is disabled */ - -/*Power Down Control (SSM2602_REG_POWER) - *(1=Enable PowerDown, 0=Disable PowerDown) - */ -#define PWR_LINE_IN_PDN 0x001 /* Line Input Power Down */ -#define PWR_MIC_PDN 0x002 /* Microphone Input & Bias Power Down */ -#define PWR_ADC_PDN 0x004 /* ADC Power Down */ -#define PWR_DAC_PDN 0x008 /* DAC Power Down */ -#define PWR_OUT_PDN 0x010 /* Outputs Power Down */ -#define PWR_OSC_PDN 0x020 /* Oscillator Power Down */ -#define PWR_CLK_OUT_PDN 0x040 /* CLKOUT Power Down */ -#define PWR_POWER_OFF 0x080 /* POWEROFF Mode */ - -/*Digital Audio Interface Format (SSM2602_REG_DIGITAL_IFACE)*/ -#define IFACE_IFACE_FORMAT 0x003 /* Digital Audio input format control */ -#define IFACE_AUDIO_DATA_LEN 0x00C /* Audio Data word length control */ -#define IFACE_DAC_LR_POLARITY 0x010 /* Polarity Control for clocks in RJ,LJ and I2S modes */ -#define IFACE_DAC_LR_SWAP 0x020 /* Swap DAC data control */ -#define IFACE_ENABLE_MASTER 0x040 /* Enable/Disable Master Mode */ -#define IFACE_BCLK_INVERT 0x080 /* Bit Clock Inversion control */ - -/*Sampling Control (SSM2602_REG_SAMPLING_CTRL)*/ -#define SRATE_ENABLE_USB_MODE 0x001 /* Enable/Disable USB Mode */ -#define SRATE_BOS_RATE 0x002 /* Base Over-Sampling rate */ -#define SRATE_SAMPLE_RATE 0x03C /* Clock setting condition (Sampling rate control) */ -#define SRATE_CORECLK_DIV2 0x040 /* Core Clock divider select */ -#define SRATE_CLKOUT_DIV2 0x080 /* Clock Out divider select */ - -/*Active Control (SSM2602_REG_ACTIVE_CTRL)*/ -#define ACTIVE_ACTIVATE_CODEC 0x001 /* Activate Codec Digital Audio Interface */ - -/*********************************************************************/ - -#define SSM2602_CACHEREGNUM 10 - -enum ssm2602_clk { - SSM2602_SYSCLK, - SSM2602_CLK_CLKOUT, - SSM2602_CLK_XTO -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/sta32x.c b/ANDROID_3.4.5/sound/soc/codecs/sta32x.c deleted file mode 100644 index 7db6fa51..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/sta32x.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system - * - * Copyright: 2011 Raumfeld GmbH - * Author: Johannes Stezenbach - * - * based on code from: - * Wolfson Microelectronics PLC. - * Mark Brown - * Freescale Semiconductor, Inc. - * Timur Tabi - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ":%s:%d: " fmt, __func__, __LINE__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "sta32x.h" - -#define STA32X_RATES (SNDRV_PCM_RATE_32000 | \ - SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | \ - SNDRV_PCM_RATE_88200 | \ - SNDRV_PCM_RATE_96000 | \ - SNDRV_PCM_RATE_176400 | \ - SNDRV_PCM_RATE_192000) - -#define STA32X_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ - SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) - -/* Power-up register defaults */ -static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = { - 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60, - 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69, - 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, - 0xc0, 0xf3, 0x33, 0x00, 0x0c, -}; - -/* regulator power supply names */ -static const char *sta32x_supply_names[] = { - "Vdda", /* analog supply, 3.3VV */ - "Vdd3", /* digital supply, 3.3V */ - "Vcc" /* power amp spply, 10V - 36V */ -}; - -/* codec private data */ -struct sta32x_priv { - struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; - struct snd_soc_codec *codec; - struct sta32x_platform_data *pdata; - - unsigned int mclk; - unsigned int format; - - u32 coef_shadow[STA32X_COEF_COUNT]; - struct delayed_work watchdog_work; - int shutdown; -}; - -static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1); -static const DECLARE_TLV_DB_SCALE(chvol_tlv, -7950, 50, 1); -static const DECLARE_TLV_DB_SCALE(tone_tlv, -120, 200, 0); - -static const char *sta32x_drc_ac[] = { - "Anti-Clipping", "Dynamic Range Compression" }; -static const char *sta32x_auto_eq_mode[] = { - "User", "Preset", "Loudness" }; -static const char *sta32x_auto_gc_mode[] = { - "User", "AC no clipping", "AC limited clipping (10%)", - "DRC nighttime listening mode" }; -static const char *sta32x_auto_xo_mode[] = { - "User", "80Hz", "100Hz", "120Hz", "140Hz", "160Hz", "180Hz", "200Hz", - "220Hz", "240Hz", "260Hz", "280Hz", "300Hz", "320Hz", "340Hz", "360Hz" }; -static const char *sta32x_preset_eq_mode[] = { - "Flat", "Rock", "Soft Rock", "Jazz", "Classical", "Dance", "Pop", "Soft", - "Hard", "Party", "Vocal", "Hip-Hop", "Dialog", "Bass-boost #1", - "Bass-boost #2", "Bass-boost #3", "Loudness 1", "Loudness 2", - "Loudness 3", "Loudness 4", "Loudness 5", "Loudness 6", "Loudness 7", - "Loudness 8", "Loudness 9", "Loudness 10", "Loudness 11", "Loudness 12", - "Loudness 13", "Loudness 14", "Loudness 15", "Loudness 16" }; -static const char *sta32x_limiter_select[] = { - "Limiter Disabled", "Limiter #1", "Limiter #2" }; -static const char *sta32x_limiter_attack_rate[] = { - "3.1584", "2.7072", "2.2560", "1.8048", "1.3536", "0.9024", - "0.4512", "0.2256", "0.1504", "0.1123", "0.0902", "0.0752", - "0.0645", "0.0564", "0.0501", "0.0451" }; -static const char *sta32x_limiter_release_rate[] = { - "0.5116", "0.1370", "0.0744", "0.0499", "0.0360", "0.0299", - "0.0264", "0.0208", "0.0198", "0.0172", "0.0147", "0.0137", - "0.0134", "0.0117", "0.0110", "0.0104" }; - -static const unsigned int sta32x_limiter_ac_attack_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 7, TLV_DB_SCALE_ITEM(-1200, 200, 0), - 8, 16, TLV_DB_SCALE_ITEM(300, 100, 0), -}; - -static const unsigned int sta32x_limiter_ac_release_tlv[] = { - TLV_DB_RANGE_HEAD(5), - 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(-2900, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(-2000, 0, 0), - 3, 8, TLV_DB_SCALE_ITEM(-1400, 200, 0), - 8, 16, TLV_DB_SCALE_ITEM(-700, 100, 0), -}; - -static const unsigned int sta32x_limiter_drc_attack_tlv[] = { - TLV_DB_RANGE_HEAD(3), - 0, 7, TLV_DB_SCALE_ITEM(-3100, 200, 0), - 8, 13, TLV_DB_SCALE_ITEM(-1600, 100, 0), - 14, 16, TLV_DB_SCALE_ITEM(-1000, 300, 0), -}; - -static const unsigned int sta32x_limiter_drc_release_tlv[] = { - TLV_DB_RANGE_HEAD(5), - 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), - 1, 2, TLV_DB_SCALE_ITEM(-3800, 200, 0), - 3, 4, TLV_DB_SCALE_ITEM(-3300, 200, 0), - 5, 12, TLV_DB_SCALE_ITEM(-3000, 200, 0), - 13, 16, TLV_DB_SCALE_ITEM(-1500, 300, 0), -}; - -static const struct soc_enum sta32x_drc_ac_enum = - SOC_ENUM_SINGLE(STA32X_CONFD, STA32X_CONFD_DRC_SHIFT, - 2, sta32x_drc_ac); -static const struct soc_enum sta32x_auto_eq_enum = - SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMEQ_SHIFT, - 3, sta32x_auto_eq_mode); -static const struct soc_enum sta32x_auto_gc_enum = - SOC_ENUM_SINGLE(STA32X_AUTO1, STA32X_AUTO1_AMGC_SHIFT, - 4, sta32x_auto_gc_mode); -static const struct soc_enum sta32x_auto_xo_enum = - SOC_ENUM_SINGLE(STA32X_AUTO2, STA32X_AUTO2_XO_SHIFT, - 16, sta32x_auto_xo_mode); -static const struct soc_enum sta32x_preset_eq_enum = - SOC_ENUM_SINGLE(STA32X_AUTO3, STA32X_AUTO3_PEQ_SHIFT, - 32, sta32x_preset_eq_mode); -static const struct soc_enum sta32x_limiter_ch1_enum = - SOC_ENUM_SINGLE(STA32X_C1CFG, STA32X_CxCFG_LS_SHIFT, - 3, sta32x_limiter_select); -static const struct soc_enum sta32x_limiter_ch2_enum = - SOC_ENUM_SINGLE(STA32X_C2CFG, STA32X_CxCFG_LS_SHIFT, - 3, sta32x_limiter_select); -static const struct soc_enum sta32x_limiter_ch3_enum = - SOC_ENUM_SINGLE(STA32X_C3CFG, STA32X_CxCFG_LS_SHIFT, - 3, sta32x_limiter_select); -static const struct soc_enum sta32x_limiter1_attack_rate_enum = - SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxA_SHIFT, - 16, sta32x_limiter_attack_rate); -static const struct soc_enum sta32x_limiter2_attack_rate_enum = - SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxA_SHIFT, - 16, sta32x_limiter_attack_rate); -static const struct soc_enum sta32x_limiter1_release_rate_enum = - SOC_ENUM_SINGLE(STA32X_L1AR, STA32X_LxR_SHIFT, - 16, sta32x_limiter_release_rate); -static const struct soc_enum sta32x_limiter2_release_rate_enum = - SOC_ENUM_SINGLE(STA32X_L2AR, STA32X_LxR_SHIFT, - 16, sta32x_limiter_release_rate); - -/* byte array controls for setting biquad, mixer, scaling coefficients; - * for biquads all five coefficients need to be set in one go, - * mixer and pre/postscale coefs can be set individually; - * each coef is 24bit, the bytes are ordered in the same way - * as given in the STA32x data sheet (big endian; b1, b2, a1, a2, b0) - */ - -static int sta32x_coefficient_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int numcoef = kcontrol->private_value >> 16; - uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = 3 * numcoef; - return 0; -} - -static int sta32x_coefficient_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int numcoef = kcontrol->private_value >> 16; - int index = kcontrol->private_value & 0xffff; - unsigned int cfud; - int i; - - /* preserve reserved bits in STA32X_CFUD */ - cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; - /* chip documentation does not say if the bits are self clearing, - * so do it explicitly */ - snd_soc_write(codec, STA32X_CFUD, cfud); - - snd_soc_write(codec, STA32X_CFADDR2, index); - if (numcoef == 1) - snd_soc_write(codec, STA32X_CFUD, cfud | 0x04); - else if (numcoef == 5) - snd_soc_write(codec, STA32X_CFUD, cfud | 0x08); - else - return -EINVAL; - for (i = 0; i < 3 * numcoef; i++) - ucontrol->value.bytes.data[i] = - snd_soc_read(codec, STA32X_B1CF1 + i); - - return 0; -} - -static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); - int numcoef = kcontrol->private_value >> 16; - int index = kcontrol->private_value & 0xffff; - unsigned int cfud; - int i; - - /* preserve reserved bits in STA32X_CFUD */ - cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; - /* chip documentation does not say if the bits are self clearing, - * so do it explicitly */ - snd_soc_write(codec, STA32X_CFUD, cfud); - - snd_soc_write(codec, STA32X_CFADDR2, index); - for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++) - sta32x->coef_shadow[index + i] = - (ucontrol->value.bytes.data[3 * i] << 16) - | (ucontrol->value.bytes.data[3 * i + 1] << 8) - | (ucontrol->value.bytes.data[3 * i + 2]); - for (i = 0; i < 3 * numcoef; i++) - snd_soc_write(codec, STA32X_B1CF1 + i, - ucontrol->value.bytes.data[i]); - if (numcoef == 1) - snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); - else if (numcoef == 5) - snd_soc_write(codec, STA32X_CFUD, cfud | 0x02); - else - return -EINVAL; - - return 0; -} - -static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) -{ - struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); - unsigned int cfud; - int i; - - /* preserve reserved bits in STA32X_CFUD */ - cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0; - - for (i = 0; i < STA32X_COEF_COUNT; i++) { - snd_soc_write(codec, STA32X_CFADDR2, i); - snd_soc_write(codec, STA32X_B1CF1, - (sta32x->coef_shadow[i] >> 16) & 0xff); - snd_soc_write(codec, STA32X_B1CF2, - (sta32x->coef_shadow[i] >> 8) & 0xff); - snd_soc_write(codec, STA32X_B1CF3, - (sta32x->coef_shadow[i]) & 0xff); - /* chip documentation does not say if the bits are - * self-clearing, so do it explicitly */ - snd_soc_write(codec, STA32X_CFUD, cfud); - snd_soc_write(codec, STA32X_CFUD, cfud | 0x01); - } - return 0; -} - -static int sta32x_cache_sync(struct snd_soc_codec *codec) -{ - unsigned int mute; - int rc; - - if (!codec->cache_sync) - return 0; - - /* mute during register sync */ - mute = snd_soc_read(codec, STA32X_MMUTE); - snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); - sta32x_sync_coef_shadow(codec); - rc = snd_soc_cache_sync(codec); - snd_soc_write(codec, STA32X_MMUTE, mute); - return rc; -} - -/* work around ESD issue where sta32x resets and loses all configuration */ -static void sta32x_watchdog(struct work_struct *work) -{ - struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv, - watchdog_work.work); - struct snd_soc_codec *codec = sta32x->codec; - unsigned int confa, confa_cached; - - /* check if sta32x has reset itself */ - confa_cached = snd_soc_read(codec, STA32X_CONFA); - codec->cache_bypass = 1; - confa = snd_soc_read(codec, STA32X_CONFA); - codec->cache_bypass = 0; - if (confa != confa_cached) { - codec->cache_sync = 1; - sta32x_cache_sync(codec); - } - - if (!sta32x->shutdown) - schedule_delayed_work(&sta32x->watchdog_work, - round_jiffies_relative(HZ)); -} - -static void sta32x_watchdog_start(struct sta32x_priv *sta32x) -{ - if (sta32x->pdata->needs_esd_watchdog) { - sta32x->shutdown = 0; - schedule_delayed_work(&sta32x->watchdog_work, - round_jiffies_relative(HZ)); - } -} - -static void sta32x_watchdog_stop(struct sta32x_priv *sta32x) -{ - if (sta32x->pdata->needs_esd_watchdog) { - sta32x->shutdown = 1; - cancel_delayed_work_sync(&sta32x->watchdog_work); - } -} - -#define SINGLE_COEF(xname, index) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = sta32x_coefficient_info, \ - .get = sta32x_coefficient_get,\ - .put = sta32x_coefficient_put, \ - .private_value = index | (1 << 16) } - -#define BIQUAD_COEFS(xname, index) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = sta32x_coefficient_info, \ - .get = sta32x_coefficient_get,\ - .put = sta32x_coefficient_put, \ - .private_value = index | (5 << 16) } - -static const struct snd_kcontrol_new sta32x_snd_controls[] = { -SOC_SINGLE_TLV("Master Volume", STA32X_MVOL, 0, 0xff, 1, mvol_tlv), -SOC_SINGLE("Master Switch", STA32X_MMUTE, 0, 1, 1), -SOC_SINGLE("Ch1 Switch", STA32X_MMUTE, 1, 1, 1), -SOC_SINGLE("Ch2 Switch", STA32X_MMUTE, 2, 1, 1), -SOC_SINGLE("Ch3 Switch", STA32X_MMUTE, 3, 1, 1), -SOC_SINGLE_TLV("Ch1 Volume", STA32X_C1VOL, 0, 0xff, 1, chvol_tlv), -SOC_SINGLE_TLV("Ch2 Volume", STA32X_C2VOL, 0, 0xff, 1, chvol_tlv), -SOC_SINGLE_TLV("Ch3 Volume", STA32X_C3VOL, 0, 0xff, 1, chvol_tlv), -SOC_SINGLE("De-emphasis Filter Switch", STA32X_CONFD, STA32X_CONFD_DEMP_SHIFT, 1, 0), -SOC_ENUM("Compressor/Limiter Switch", sta32x_drc_ac_enum), -SOC_SINGLE("Miami Mode Switch", STA32X_CONFD, STA32X_CONFD_MME_SHIFT, 1, 0), -SOC_SINGLE("Zero Cross Switch", STA32X_CONFE, STA32X_CONFE_ZCE_SHIFT, 1, 0), -SOC_SINGLE("Soft Ramp Switch", STA32X_CONFE, STA32X_CONFE_SVE_SHIFT, 1, 0), -SOC_SINGLE("Auto-Mute Switch", STA32X_CONFF, STA32X_CONFF_IDE_SHIFT, 1, 0), -SOC_ENUM("Automode EQ", sta32x_auto_eq_enum), -SOC_ENUM("Automode GC", sta32x_auto_gc_enum), -SOC_ENUM("Automode XO", sta32x_auto_xo_enum), -SOC_ENUM("Preset EQ", sta32x_preset_eq_enum), -SOC_SINGLE("Ch1 Tone Control Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0), -SOC_SINGLE("Ch2 Tone Control Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_TCB_SHIFT, 1, 0), -SOC_SINGLE("Ch1 EQ Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0), -SOC_SINGLE("Ch2 EQ Bypass Switch", STA32X_C2CFG, STA32X_CxCFG_EQBP_SHIFT, 1, 0), -SOC_SINGLE("Ch1 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), -SOC_SINGLE("Ch2 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), -SOC_SINGLE("Ch3 Master Volume Bypass Switch", STA32X_C1CFG, STA32X_CxCFG_VBP_SHIFT, 1, 0), -SOC_ENUM("Ch1 Limiter Select", sta32x_limiter_ch1_enum), -SOC_ENUM("Ch2 Limiter Select", sta32x_limiter_ch2_enum), -SOC_ENUM("Ch3 Limiter Select", sta32x_limiter_ch3_enum), -SOC_SINGLE_TLV("Bass Tone Control", STA32X_TONE, STA32X_TONE_BTC_SHIFT, 15, 0, tone_tlv), -SOC_SINGLE_TLV("Treble Tone Control", STA32X_TONE, STA32X_TONE_TTC_SHIFT, 15, 0, tone_tlv), -SOC_ENUM("Limiter1 Attack Rate (dB/ms)", sta32x_limiter1_attack_rate_enum), -SOC_ENUM("Limiter2 Attack Rate (dB/ms)", sta32x_limiter2_attack_rate_enum), -SOC_ENUM("Limiter1 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), -SOC_ENUM("Limiter2 Release Rate (dB/ms)", sta32x_limiter1_release_rate_enum), - -/* depending on mode, the attack/release thresholds have - * two different enum definitions; provide both - */ -SOC_SINGLE_TLV("Limiter1 Attack Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT, - 16, 0, sta32x_limiter_ac_attack_tlv), -SOC_SINGLE_TLV("Limiter2 Attack Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT, - 16, 0, sta32x_limiter_ac_attack_tlv), -SOC_SINGLE_TLV("Limiter1 Release Threshold (AC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT, - 16, 0, sta32x_limiter_ac_release_tlv), -SOC_SINGLE_TLV("Limiter2 Release Threshold (AC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT, - 16, 0, sta32x_limiter_ac_release_tlv), -SOC_SINGLE_TLV("Limiter1 Attack Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxA_SHIFT, - 16, 0, sta32x_limiter_drc_attack_tlv), -SOC_SINGLE_TLV("Limiter2 Attack Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxA_SHIFT, - 16, 0, sta32x_limiter_drc_attack_tlv), -SOC_SINGLE_TLV("Limiter1 Release Threshold (DRC Mode)", STA32X_L1ATRT, STA32X_LxR_SHIFT, - 16, 0, sta32x_limiter_drc_release_tlv), -SOC_SINGLE_TLV("Limiter2 Release Threshold (DRC Mode)", STA32X_L2ATRT, STA32X_LxR_SHIFT, - 16, 0, sta32x_limiter_drc_release_tlv), - -BIQUAD_COEFS("Ch1 - Biquad 1", 0), -BIQUAD_COEFS("Ch1 - Biquad 2", 5), -BIQUAD_COEFS("Ch1 - Biquad 3", 10), -BIQUAD_COEFS("Ch1 - Biquad 4", 15), -BIQUAD_COEFS("Ch2 - Biquad 1", 20), -BIQUAD_COEFS("Ch2 - Biquad 2", 25), -BIQUAD_COEFS("Ch2 - Biquad 3", 30), -BIQUAD_COEFS("Ch2 - Biquad 4", 35), -BIQUAD_COEFS("High-pass", 40), -BIQUAD_COEFS("Low-pass", 45), -SINGLE_COEF("Ch1 - Prescale", 50), -SINGLE_COEF("Ch2 - Prescale", 51), -SINGLE_COEF("Ch1 - Postscale", 52), -SINGLE_COEF("Ch2 - Postscale", 53), -SINGLE_COEF("Ch3 - Postscale", 54), -SINGLE_COEF("Thermal warning - Postscale", 55), -SINGLE_COEF("Ch1 - Mix 1", 56), -SINGLE_COEF("Ch1 - Mix 2", 57), -SINGLE_COEF("Ch2 - Mix 1", 58), -SINGLE_COEF("Ch2 - Mix 2", 59), -SINGLE_COEF("Ch3 - Mix 1", 60), -SINGLE_COEF("Ch3 - Mix 2", 61), -}; - -static const struct snd_soc_dapm_widget sta32x_dapm_widgets[] = { -SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_OUTPUT("LEFT"), -SND_SOC_DAPM_OUTPUT("RIGHT"), -SND_SOC_DAPM_OUTPUT("SUB"), -}; - -static const struct snd_soc_dapm_route sta32x_dapm_routes[] = { - { "LEFT", NULL, "DAC" }, - { "RIGHT", NULL, "DAC" }, - { "SUB", NULL, "DAC" }, -}; - -/* MCLK interpolation ratio per fs */ -static struct { - int fs; - int ir; -} interpolation_ratios[] = { - { 32000, 0 }, - { 44100, 0 }, - { 48000, 0 }, - { 88200, 1 }, - { 96000, 1 }, - { 176400, 2 }, - { 192000, 2 }, -}; - -/* MCLK to fs clock ratios */ -static struct { - int ratio; - int mcs; -} mclk_ratios[3][7] = { - { { 768, 0 }, { 512, 1 }, { 384, 2 }, { 256, 3 }, - { 128, 4 }, { 576, 5 }, { 0, 0 } }, - { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } }, - { { 384, 2 }, { 256, 3 }, { 192, 4 }, { 128, 5 }, {64, 0 }, { 0, 0 } }, -}; - - -/** - * sta32x_set_dai_sysclk - configure MCLK - * @codec_dai: the codec DAI - * @clk_id: the clock ID (ignored) - * @freq: the MCLK input frequency - * @dir: the clock direction (ignored) - * - * The value of MCLK is used to determine which sample rates are supported - * by the STA32X, based on the mclk_ratios table. - * - * This function must be called by the machine driver's 'startup' function, - * otherwise the list of supported sample rates will not be available in - * time for ALSA. - * - * For setups with variable MCLKs, pass 0 as 'freq' argument. This will cause - * theoretically possible sample rates to be enabled. Call it again with a - * proper value set one the external clock is set (most probably you would do - * that from a machine's driver 'hw_param' hook. - */ -static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); - int i, j, ir, fs; - unsigned int rates = 0; - unsigned int rate_min = -1; - unsigned int rate_max = 0; - - pr_debug("mclk=%u\n", freq); - sta32x->mclk = freq; - - if (sta32x->mclk) { - for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) { - ir = interpolation_ratios[i].ir; - fs = interpolation_ratios[i].fs; - for (j = 0; mclk_ratios[ir][j].ratio; j++) { - if (mclk_ratios[ir][j].ratio * fs == freq) { - rates |= snd_pcm_rate_to_rate_bit(fs); - if (fs < rate_min) - rate_min = fs; - if (fs > rate_max) - rate_max = fs; - break; - } - } - } - /* FIXME: soc should support a rate list */ - rates &= ~SNDRV_PCM_RATE_KNOT; - - if (!rates) { - dev_err(codec->dev, "could not find a valid sample rate\n"); - return -EINVAL; - } - } else { - /* enable all possible rates */ - rates = STA32X_RATES; - rate_min = 32000; - rate_max = 192000; - } - - codec_dai->driver->playback.rates = rates; - codec_dai->driver->playback.rate_min = rate_min; - codec_dai->driver->playback.rate_max = rate_max; - return 0; -} - -/** - * sta32x_set_dai_fmt - configure the codec for the selected audio format - * @codec_dai: the codec DAI - * @fmt: a SND_SOC_DAIFMT_x value indicating the data format - * - * This function takes a bitmask of SND_SOC_DAIFMT_x bits and programs the - * codec accordingly. - */ -static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); - u8 confb = snd_soc_read(codec, STA32X_CONFB); - - pr_debug("\n"); - confb &= ~(STA32X_CONFB_C1IM | STA32X_CONFB_C2IM); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - sta32x->format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - confb |= STA32X_CONFB_C2IM; - break; - case SND_SOC_DAIFMT_NB_IF: - confb |= STA32X_CONFB_C1IM; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, STA32X_CONFB, confb); - return 0; -} - -/** - * sta32x_hw_params - program the STA32X with the given hardware parameters. - * @substream: the audio stream - * @params: the hardware parameters to set - * @dai: the SOC DAI (ignored) - * - * This function programs the hardware with the values provided. - * Specifically, the sample rate and the data format. - */ -static int sta32x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); - unsigned int rate; - int i, mcs = -1, ir = -1; - u8 confa, confb; - - rate = params_rate(params); - pr_debug("rate: %u\n", rate); - for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) - if (interpolation_ratios[i].fs == rate) { - ir = interpolation_ratios[i].ir; - break; - } - if (ir < 0) - return -EINVAL; - for (i = 0; mclk_ratios[ir][i].ratio; i++) - if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) { - mcs = mclk_ratios[ir][i].mcs; - break; - } - if (mcs < 0) - return -EINVAL; - - confa = snd_soc_read(codec, STA32X_CONFA); - confa &= ~(STA32X_CONFA_MCS_MASK | STA32X_CONFA_IR_MASK); - confa |= (ir << STA32X_CONFA_IR_SHIFT) | (mcs << STA32X_CONFA_MCS_SHIFT); - - confb = snd_soc_read(codec, STA32X_CONFB); - confb &= ~(STA32X_CONFB_SAI_MASK | STA32X_CONFB_SAIFB); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S24_BE: - case SNDRV_PCM_FORMAT_S24_3LE: - case SNDRV_PCM_FORMAT_S24_3BE: - pr_debug("24bit\n"); - /* fall through */ - case SNDRV_PCM_FORMAT_S32_LE: - case SNDRV_PCM_FORMAT_S32_BE: - pr_debug("24bit or 32bit\n"); - switch (sta32x->format) { - case SND_SOC_DAIFMT_I2S: - confb |= 0x0; - break; - case SND_SOC_DAIFMT_LEFT_J: - confb |= 0x1; - break; - case SND_SOC_DAIFMT_RIGHT_J: - confb |= 0x2; - break; - } - - break; - case SNDRV_PCM_FORMAT_S20_3LE: - case SNDRV_PCM_FORMAT_S20_3BE: - pr_debug("20bit\n"); - switch (sta32x->format) { - case SND_SOC_DAIFMT_I2S: - confb |= 0x4; - break; - case SND_SOC_DAIFMT_LEFT_J: - confb |= 0x5; - break; - case SND_SOC_DAIFMT_RIGHT_J: - confb |= 0x6; - break; - } - - break; - case SNDRV_PCM_FORMAT_S18_3LE: - case SNDRV_PCM_FORMAT_S18_3BE: - pr_debug("18bit\n"); - switch (sta32x->format) { - case SND_SOC_DAIFMT_I2S: - confb |= 0x8; - break; - case SND_SOC_DAIFMT_LEFT_J: - confb |= 0x9; - break; - case SND_SOC_DAIFMT_RIGHT_J: - confb |= 0xa; - break; - } - - break; - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: - pr_debug("16bit\n"); - switch (sta32x->format) { - case SND_SOC_DAIFMT_I2S: - confb |= 0x0; - break; - case SND_SOC_DAIFMT_LEFT_J: - confb |= 0xd; - break; - case SND_SOC_DAIFMT_RIGHT_J: - confb |= 0xe; - break; - } - - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, STA32X_CONFA, confa); - snd_soc_write(codec, STA32X_CONFB, confb); - return 0; -} - -/** - * sta32x_set_bias_level - DAPM callback - * @codec: the codec device - * @level: DAPM power level - * - * This is called by ALSA to put the codec into low power mode - * or to wake it up. If the codec is powered off completely - * all registers must be restored after power on. - */ -static int sta32x_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); - - pr_debug("level = %d\n", level); - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* Full power on */ - snd_soc_update_bits(codec, STA32X_CONFF, - STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, - STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), - sta32x->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", ret); - return ret; - } - - sta32x_cache_sync(codec); - sta32x_watchdog_start(sta32x); - } - - /* Power up to mute */ - /* FIXME */ - snd_soc_update_bits(codec, STA32X_CONFF, - STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, - STA32X_CONFF_PWDN | STA32X_CONFF_EAPD); - - break; - - case SND_SOC_BIAS_OFF: - /* The chip runs through the power down sequence for us. */ - snd_soc_update_bits(codec, STA32X_CONFF, - STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, - STA32X_CONFF_PWDN); - msleep(300); - sta32x_watchdog_stop(sta32x); - regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), - sta32x->supplies); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static const struct snd_soc_dai_ops sta32x_dai_ops = { - .hw_params = sta32x_hw_params, - .set_sysclk = sta32x_set_dai_sysclk, - .set_fmt = sta32x_set_dai_fmt, -}; - -static struct snd_soc_dai_driver sta32x_dai = { - .name = "STA32X", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = STA32X_RATES, - .formats = STA32X_FORMATS, - }, - .ops = &sta32x_dai_ops, -}; - -#ifdef CONFIG_PM -static int sta32x_suspend(struct snd_soc_codec *codec) -{ - sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int sta32x_resume(struct snd_soc_codec *codec) -{ - sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define sta32x_suspend NULL -#define sta32x_resume NULL -#endif - -static int sta32x_probe(struct snd_soc_codec *codec) -{ - struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); - int i, ret = 0, thermal = 0; - - sta32x->codec = codec; - sta32x->pdata = dev_get_platdata(codec->dev); - - /* regulators */ - for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) - sta32x->supplies[i].supply = sta32x_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies), - sta32x->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), - sta32x->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - /* Tell ASoC what kind of I/O to use to read the registers. ASoC will - * then do the I2C transactions itself. - */ - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); - if (ret < 0) { - dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); - return ret; - } - - /* Chip documentation explicitly requires that the reset values - * of reserved register bits are left untouched. - * Write the register default value to cache for reserved registers, - * so the write to the these registers are suppressed by the cache - * restore code when it skips writes of default registers. - */ - snd_soc_cache_write(codec, STA32X_CONFC, 0xc2); - snd_soc_cache_write(codec, STA32X_CONFE, 0xc2); - snd_soc_cache_write(codec, STA32X_CONFF, 0x5c); - snd_soc_cache_write(codec, STA32X_MMUTE, 0x10); - snd_soc_cache_write(codec, STA32X_AUTO1, 0x60); - snd_soc_cache_write(codec, STA32X_AUTO3, 0x00); - snd_soc_cache_write(codec, STA32X_C3CFG, 0x40); - - /* set thermal warning adjustment and recovery */ - if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) - thermal |= STA32X_CONFA_TWAB; - if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE)) - thermal |= STA32X_CONFA_TWRB; - snd_soc_update_bits(codec, STA32X_CONFA, - STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, - thermal); - - /* select output configuration */ - snd_soc_update_bits(codec, STA32X_CONFF, - STA32X_CONFF_OCFG_MASK, - sta32x->pdata->output_conf - << STA32X_CONFF_OCFG_SHIFT); - - /* channel to output mapping */ - snd_soc_update_bits(codec, STA32X_C1CFG, - STA32X_CxCFG_OM_MASK, - sta32x->pdata->ch1_output_mapping - << STA32X_CxCFG_OM_SHIFT); - snd_soc_update_bits(codec, STA32X_C2CFG, - STA32X_CxCFG_OM_MASK, - sta32x->pdata->ch2_output_mapping - << STA32X_CxCFG_OM_SHIFT); - snd_soc_update_bits(codec, STA32X_C3CFG, - STA32X_CxCFG_OM_MASK, - sta32x->pdata->ch3_output_mapping - << STA32X_CxCFG_OM_SHIFT); - - /* initialize coefficient shadow RAM with reset values */ - for (i = 4; i <= 49; i += 5) - sta32x->coef_shadow[i] = 0x400000; - for (i = 50; i <= 54; i++) - sta32x->coef_shadow[i] = 0x7fffff; - sta32x->coef_shadow[55] = 0x5a9df7; - sta32x->coef_shadow[56] = 0x7fffff; - sta32x->coef_shadow[59] = 0x7fffff; - sta32x->coef_shadow[60] = 0x400000; - sta32x->coef_shadow[61] = 0x400000; - - if (sta32x->pdata->needs_esd_watchdog) - INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog); - - sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - - return 0; - -err_get: - regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); -err: - return ret; -} - -static int sta32x_remove(struct snd_soc_codec *codec) -{ - struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); - - sta32x_watchdog_stop(sta32x); - sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); - - return 0; -} - -static int sta32x_reg_is_volatile(struct snd_soc_codec *codec, - unsigned int reg) -{ - switch (reg) { - case STA32X_CONFA ... STA32X_L2ATRT: - case STA32X_MPCC1 ... STA32X_FDRC2: - return 0; - } - return 1; -} - -static const struct snd_soc_codec_driver sta32x_codec = { - .probe = sta32x_probe, - .remove = sta32x_remove, - .suspend = sta32x_suspend, - .resume = sta32x_resume, - .reg_cache_size = STA32X_REGISTER_COUNT, - .reg_word_size = sizeof(u8), - .reg_cache_default = sta32x_regs, - .volatile_register = sta32x_reg_is_volatile, - .set_bias_level = sta32x_set_bias_level, - .controls = sta32x_snd_controls, - .num_controls = ARRAY_SIZE(sta32x_snd_controls), - .dapm_widgets = sta32x_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(sta32x_dapm_widgets), - .dapm_routes = sta32x_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), -}; - -static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct sta32x_priv *sta32x; - int ret; - - sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), - GFP_KERNEL); - if (!sta32x) - return -ENOMEM; - - i2c_set_clientdata(i2c, sta32x); - - ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); - if (ret != 0) - dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); - - return ret; -} - -static __devexit int sta32x_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id sta32x_i2c_id[] = { - { "sta326", 0 }, - { "sta328", 0 }, - { "sta329", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id); - -static struct i2c_driver sta32x_i2c_driver = { - .driver = { - .name = "sta32x", - .owner = THIS_MODULE, - }, - .probe = sta32x_i2c_probe, - .remove = __devexit_p(sta32x_i2c_remove), - .id_table = sta32x_i2c_id, -}; - -static int __init sta32x_init(void) -{ - return i2c_add_driver(&sta32x_i2c_driver); -} -module_init(sta32x_init); - -static void __exit sta32x_exit(void) -{ - i2c_del_driver(&sta32x_i2c_driver); -} -module_exit(sta32x_exit); - -MODULE_DESCRIPTION("ASoC STA32X driver"); -MODULE_AUTHOR("Johannes Stezenbach "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/sta32x.h b/ANDROID_3.4.5/sound/soc/codecs/sta32x.h deleted file mode 100644 index d8e32a62..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/sta32x.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Codec driver for ST STA32x 2.1-channel high-efficiency digital audio system - * - * Copyright: 2011 Raumfeld GmbH - * Author: Johannes Stezenbach - * - * based on code from: - * Wolfson Microelectronics PLC. - * Mark Brown - * - * 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. - */ -#ifndef _ASOC_STA_32X_H -#define _ASOC_STA_32X_H - -/* STA326 register addresses */ - -#define STA32X_REGISTER_COUNT 0x2d -#define STA32X_COEF_COUNT 62 - -#define STA32X_CONFA 0x00 -#define STA32X_CONFB 0x01 -#define STA32X_CONFC 0x02 -#define STA32X_CONFD 0x03 -#define STA32X_CONFE 0x04 -#define STA32X_CONFF 0x05 -#define STA32X_MMUTE 0x06 -#define STA32X_MVOL 0x07 -#define STA32X_C1VOL 0x08 -#define STA32X_C2VOL 0x09 -#define STA32X_C3VOL 0x0a -#define STA32X_AUTO1 0x0b -#define STA32X_AUTO2 0x0c -#define STA32X_AUTO3 0x0d -#define STA32X_C1CFG 0x0e -#define STA32X_C2CFG 0x0f -#define STA32X_C3CFG 0x10 -#define STA32X_TONE 0x11 -#define STA32X_L1AR 0x12 -#define STA32X_L1ATRT 0x13 -#define STA32X_L2AR 0x14 -#define STA32X_L2ATRT 0x15 -#define STA32X_CFADDR2 0x16 -#define STA32X_B1CF1 0x17 -#define STA32X_B1CF2 0x18 -#define STA32X_B1CF3 0x19 -#define STA32X_B2CF1 0x1a -#define STA32X_B2CF2 0x1b -#define STA32X_B2CF3 0x1c -#define STA32X_A1CF1 0x1d -#define STA32X_A1CF2 0x1e -#define STA32X_A1CF3 0x1f -#define STA32X_A2CF1 0x20 -#define STA32X_A2CF2 0x21 -#define STA32X_A2CF3 0x22 -#define STA32X_B0CF1 0x23 -#define STA32X_B0CF2 0x24 -#define STA32X_B0CF3 0x25 -#define STA32X_CFUD 0x26 -#define STA32X_MPCC1 0x27 -#define STA32X_MPCC2 0x28 -/* Reserved 0x29 */ -/* Reserved 0x2a */ -#define STA32X_Reserved 0x2a -#define STA32X_FDRC1 0x2b -#define STA32X_FDRC2 0x2c -/* Reserved 0x2d */ - - -/* STA326 register field definitions */ - -/* 0x00 CONFA */ -#define STA32X_CONFA_MCS_MASK 0x03 -#define STA32X_CONFA_MCS_SHIFT 0 -#define STA32X_CONFA_IR_MASK 0x18 -#define STA32X_CONFA_IR_SHIFT 3 -#define STA32X_CONFA_TWRB 0x20 -#define STA32X_CONFA_TWAB 0x40 -#define STA32X_CONFA_FDRB 0x80 - -/* 0x01 CONFB */ -#define STA32X_CONFB_SAI_MASK 0x0f -#define STA32X_CONFB_SAI_SHIFT 0 -#define STA32X_CONFB_SAIFB 0x10 -#define STA32X_CONFB_DSCKE 0x20 -#define STA32X_CONFB_C1IM 0x40 -#define STA32X_CONFB_C2IM 0x80 - -/* 0x02 CONFC */ -#define STA32X_CONFC_OM_MASK 0x03 -#define STA32X_CONFC_OM_SHIFT 0 -#define STA32X_CONFC_CSZ_MASK 0x7c -#define STA32X_CONFC_CSZ_SHIFT 2 - -/* 0x03 CONFD */ -#define STA32X_CONFD_HPB 0x01 -#define STA32X_CONFD_HPB_SHIFT 0 -#define STA32X_CONFD_DEMP 0x02 -#define STA32X_CONFD_DEMP_SHIFT 1 -#define STA32X_CONFD_DSPB 0x04 -#define STA32X_CONFD_DSPB_SHIFT 2 -#define STA32X_CONFD_PSL 0x08 -#define STA32X_CONFD_PSL_SHIFT 3 -#define STA32X_CONFD_BQL 0x10 -#define STA32X_CONFD_BQL_SHIFT 4 -#define STA32X_CONFD_DRC 0x20 -#define STA32X_CONFD_DRC_SHIFT 5 -#define STA32X_CONFD_ZDE 0x40 -#define STA32X_CONFD_ZDE_SHIFT 6 -#define STA32X_CONFD_MME 0x80 -#define STA32X_CONFD_MME_SHIFT 7 - -/* 0x04 CONFE */ -#define STA32X_CONFE_MPCV 0x01 -#define STA32X_CONFE_MPCV_SHIFT 0 -#define STA32X_CONFE_MPC 0x02 -#define STA32X_CONFE_MPC_SHIFT 1 -#define STA32X_CONFE_AME 0x08 -#define STA32X_CONFE_AME_SHIFT 3 -#define STA32X_CONFE_PWMS 0x10 -#define STA32X_CONFE_PWMS_SHIFT 4 -#define STA32X_CONFE_ZCE 0x40 -#define STA32X_CONFE_ZCE_SHIFT 6 -#define STA32X_CONFE_SVE 0x80 -#define STA32X_CONFE_SVE_SHIFT 7 - -/* 0x05 CONFF */ -#define STA32X_CONFF_OCFG_MASK 0x03 -#define STA32X_CONFF_OCFG_SHIFT 0 -#define STA32X_CONFF_IDE 0x04 -#define STA32X_CONFF_IDE_SHIFT 3 -#define STA32X_CONFF_BCLE 0x08 -#define STA32X_CONFF_ECLE 0x20 -#define STA32X_CONFF_PWDN 0x40 -#define STA32X_CONFF_EAPD 0x80 - -/* 0x06 MMUTE */ -#define STA32X_MMUTE_MMUTE 0x01 - -/* 0x0b AUTO1 */ -#define STA32X_AUTO1_AMEQ_MASK 0x03 -#define STA32X_AUTO1_AMEQ_SHIFT 0 -#define STA32X_AUTO1_AMV_MASK 0xc0 -#define STA32X_AUTO1_AMV_SHIFT 2 -#define STA32X_AUTO1_AMGC_MASK 0x30 -#define STA32X_AUTO1_AMGC_SHIFT 4 -#define STA32X_AUTO1_AMPS 0x80 - -/* 0x0c AUTO2 */ -#define STA32X_AUTO2_AMAME 0x01 -#define STA32X_AUTO2_AMAM_MASK 0x0e -#define STA32X_AUTO2_AMAM_SHIFT 1 -#define STA32X_AUTO2_XO_MASK 0xf0 -#define STA32X_AUTO2_XO_SHIFT 4 - -/* 0x0d AUTO3 */ -#define STA32X_AUTO3_PEQ_MASK 0x1f -#define STA32X_AUTO3_PEQ_SHIFT 0 - -/* 0x0e 0x0f 0x10 CxCFG */ -#define STA32X_CxCFG_TCB 0x01 /* only C1 and C2 */ -#define STA32X_CxCFG_TCB_SHIFT 0 -#define STA32X_CxCFG_EQBP 0x02 /* only C1 and C2 */ -#define STA32X_CxCFG_EQBP_SHIFT 1 -#define STA32X_CxCFG_VBP 0x03 -#define STA32X_CxCFG_VBP_SHIFT 2 -#define STA32X_CxCFG_BO 0x04 -#define STA32X_CxCFG_LS_MASK 0x30 -#define STA32X_CxCFG_LS_SHIFT 4 -#define STA32X_CxCFG_OM_MASK 0xc0 -#define STA32X_CxCFG_OM_SHIFT 6 - -/* 0x11 TONE */ -#define STA32X_TONE_BTC_SHIFT 0 -#define STA32X_TONE_TTC_SHIFT 4 - -/* 0x12 0x13 0x14 0x15 limiter attack/release */ -#define STA32X_LxA_SHIFT 0 -#define STA32X_LxR_SHIFT 4 - -/* 0x26 CFUD */ -#define STA32X_CFUD_W1 0x01 -#define STA32X_CFUD_WA 0x02 -#define STA32X_CFUD_R1 0x04 -#define STA32X_CFUD_RA 0x08 - - -/* biquad filter coefficient table offsets */ -#define STA32X_C1_BQ_BASE 0 -#define STA32X_C2_BQ_BASE 20 -#define STA32X_CH_BQ_NUM 4 -#define STA32X_BQ_NUM_COEF 5 -#define STA32X_XO_HP_BQ_BASE 40 -#define STA32X_XO_LP_BQ_BASE 45 -#define STA32X_C1_PRESCALE 50 -#define STA32X_C2_PRESCALE 51 -#define STA32X_C1_POSTSCALE 52 -#define STA32X_C2_POSTSCALE 53 -#define STA32X_C3_POSTSCALE 54 -#define STA32X_TW_POSTSCALE 55 -#define STA32X_C1_MIX1 56 -#define STA32X_C1_MIX2 57 -#define STA32X_C2_MIX1 58 -#define STA32X_C2_MIX2 59 -#define STA32X_C3_MIX1 60 -#define STA32X_C3_MIX2 61 - -#endif /* _ASOC_STA_32X_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/stac9766.c b/ANDROID_3.4.5/sound/soc/codecs/stac9766.c deleted file mode 100644 index 982e4377..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/stac9766.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * stac9766.c -- ALSA SoC STAC9766 codec support - * - * Copyright 2009 Jon Smirl, Digispeaker - * Author: Jon Smirl - * - * 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. - * - * Features:- - * - * o Support for AC97 Codec, S/PDIF - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stac9766.h" - -#define STAC9766_VERSION "0.10" - -/* - * STAC9766 register cache - */ -static const u16 stac9766_reg[] = { - 0x6A90, 0x8000, 0x8000, 0x8000, /* 6 */ - 0x0000, 0x0000, 0x8008, 0x8008, /* e */ - 0x8808, 0x8808, 0x8808, 0x8808, /* 16 */ - 0x8808, 0x0000, 0x8000, 0x0000, /* 1e */ - 0x0000, 0x0000, 0x0000, 0x000f, /* 26 */ - 0x0a05, 0x0400, 0xbb80, 0x0000, /* 2e */ - 0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */ - 0x0000, 0x2000, 0x0000, 0x0100, /* 3e */ - 0x0000, 0x0000, 0x0080, 0x0000, /* 46 */ - 0x0000, 0x0000, 0x0003, 0xffff, /* 4e */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 56 */ - 0x4000, 0x0000, 0x0000, 0x0000, /* 5e */ - 0x1201, 0xFFFF, 0xFFFF, 0x0000, /* 66 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ - 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 7e */ -}; - -static const char *stac9766_record_mux[] = {"Mic", "CD", "Video", "AUX", - "Line", "Stereo Mix", "Mono Mix", "Phone"}; -static const char *stac9766_mono_mux[] = {"Mix", "Mic"}; -static const char *stac9766_mic_mux[] = {"Mic1", "Mic2"}; -static const char *stac9766_SPDIF_mux[] = {"PCM", "ADC Record"}; -static const char *stac9766_popbypass_mux[] = {"Normal", "Bypass Mixer"}; -static const char *stac9766_record_all_mux[] = {"All analog", - "Analog plus DAC"}; -static const char *stac9766_boost1[] = {"0dB", "10dB"}; -static const char *stac9766_boost2[] = {"0dB", "20dB"}; -static const char *stac9766_stereo_mic[] = {"Off", "On"}; - -static const struct soc_enum stac9766_record_enum = - SOC_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, stac9766_record_mux); -static const struct soc_enum stac9766_mono_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, stac9766_mono_mux); -static const struct soc_enum stac9766_mic_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, stac9766_mic_mux); -static const struct soc_enum stac9766_SPDIF_enum = - SOC_ENUM_SINGLE(AC97_STAC_DA_CONTROL, 1, 2, stac9766_SPDIF_mux); -static const struct soc_enum stac9766_popbypass_enum = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, stac9766_popbypass_mux); -static const struct soc_enum stac9766_record_all_enum = - SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 12, 2, - stac9766_record_all_mux); -static const struct soc_enum stac9766_boost1_enum = - SOC_ENUM_SINGLE(AC97_MIC, 6, 2, stac9766_boost1); /* 0/10dB */ -static const struct soc_enum stac9766_boost2_enum = - SOC_ENUM_SINGLE(AC97_STAC_ANALOG_SPECIAL, 2, 2, stac9766_boost2); /* 0/20dB */ -static const struct soc_enum stac9766_stereo_mic_enum = - SOC_ENUM_SINGLE(AC97_STAC_STEREO_MIC, 2, 1, stac9766_stereo_mic); - -static const DECLARE_TLV_DB_LINEAR(master_tlv, -4600, 0); -static const DECLARE_TLV_DB_LINEAR(record_tlv, 0, 2250); -static const DECLARE_TLV_DB_LINEAR(beep_tlv, -4500, 0); -static const DECLARE_TLV_DB_LINEAR(mix_tlv, -3450, 1200); - -static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = { - SOC_DOUBLE_TLV("Speaker Volume", AC97_MASTER, 8, 0, 31, 1, master_tlv), - SOC_SINGLE("Speaker Switch", AC97_MASTER, 15, 1, 1), - SOC_DOUBLE_TLV("Headphone Volume", AC97_HEADPHONE, 8, 0, 31, 1, - master_tlv), - SOC_SINGLE("Headphone Switch", AC97_HEADPHONE, 15, 1, 1), - SOC_SINGLE_TLV("Mono Out Volume", AC97_MASTER_MONO, 0, 31, 1, - master_tlv), - SOC_SINGLE("Mono Out Switch", AC97_MASTER_MONO, 15, 1, 1), - - SOC_DOUBLE_TLV("Record Volume", AC97_REC_GAIN, 8, 0, 15, 0, record_tlv), - SOC_SINGLE("Record Switch", AC97_REC_GAIN, 15, 1, 1), - - - SOC_SINGLE_TLV("Beep Volume", AC97_PC_BEEP, 1, 15, 1, beep_tlv), - SOC_SINGLE("Beep Switch", AC97_PC_BEEP, 15, 1, 1), - SOC_SINGLE("Beep Frequency", AC97_PC_BEEP, 5, 127, 1), - SOC_SINGLE_TLV("Phone Volume", AC97_PHONE, 0, 31, 1, mix_tlv), - SOC_SINGLE("Phone Switch", AC97_PHONE, 15, 1, 1), - - SOC_ENUM("Mic Boost1", stac9766_boost1_enum), - SOC_ENUM("Mic Boost2", stac9766_boost2_enum), - SOC_SINGLE_TLV("Mic Volume", AC97_MIC, 0, 31, 1, mix_tlv), - SOC_SINGLE("Mic Switch", AC97_MIC, 15, 1, 1), - SOC_ENUM("Stereo Mic", stac9766_stereo_mic_enum), - - SOC_DOUBLE_TLV("Line Volume", AC97_LINE, 8, 0, 31, 1, mix_tlv), - SOC_SINGLE("Line Switch", AC97_LINE, 15, 1, 1), - SOC_DOUBLE_TLV("CD Volume", AC97_CD, 8, 0, 31, 1, mix_tlv), - SOC_SINGLE("CD Switch", AC97_CD, 15, 1, 1), - SOC_DOUBLE_TLV("AUX Volume", AC97_AUX, 8, 0, 31, 1, mix_tlv), - SOC_SINGLE("AUX Switch", AC97_AUX, 15, 1, 1), - SOC_DOUBLE_TLV("Video Volume", AC97_VIDEO, 8, 0, 31, 1, mix_tlv), - SOC_SINGLE("Video Switch", AC97_VIDEO, 15, 1, 1), - - SOC_DOUBLE_TLV("DAC Volume", AC97_PCM, 8, 0, 31, 1, mix_tlv), - SOC_SINGLE("DAC Switch", AC97_PCM, 15, 1, 1), - SOC_SINGLE("Loopback Test Switch", AC97_GENERAL_PURPOSE, 7, 1, 0), - SOC_SINGLE("3D Volume", AC97_3D_CONTROL, 3, 2, 1), - SOC_SINGLE("3D Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), - - SOC_ENUM("SPDIF Mux", stac9766_SPDIF_enum), - SOC_ENUM("Mic1/2 Mux", stac9766_mic_enum), - SOC_ENUM("Record All Mux", stac9766_record_all_enum), - SOC_ENUM("Record Mux", stac9766_record_enum), - SOC_ENUM("Mono Mux", stac9766_mono_enum), - SOC_ENUM("Pop Bypass Mux", stac9766_popbypass_enum), -}; - -static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int val) -{ - u16 *cache = codec->reg_cache; - - if (reg > AC97_STAC_PAGE0) { - stac9766_ac97_write(codec, AC97_INT_PAGING, 0); - soc_ac97_ops.write(codec->ac97, reg, val); - stac9766_ac97_write(codec, AC97_INT_PAGING, 1); - return 0; - } - if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) - return -EIO; - - soc_ac97_ops.write(codec->ac97, reg, val); - cache[reg / 2] = val; - return 0; -} - -static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 val = 0, *cache = codec->reg_cache; - - if (reg > AC97_STAC_PAGE0) { - stac9766_ac97_write(codec, AC97_INT_PAGING, 0); - val = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0); - stac9766_ac97_write(codec, AC97_INT_PAGING, 1); - return val; - } - if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) - return -EIO; - - if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || - reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || - reg == AC97_VENDOR_ID2) { - - val = soc_ac97_ops.read(codec->ac97, reg); - return val; - } - return cache[reg / 2]; -} - -static int ac97_analog_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned short reg, vra; - - vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); - - vra |= 0x1; /* enable variable rate audio */ - vra &= ~0x4; /* disable SPDIF output */ - - stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - reg = AC97_PCM_FRONT_DAC_RATE; - else - reg = AC97_PCM_LR_ADC_RATE; - - return stac9766_ac97_write(codec, reg, runtime->rate); -} - -static int ac97_digital_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned short reg, vra; - - stac9766_ac97_write(codec, AC97_SPDIF, 0x2002); - - vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); - vra |= 0x5; /* Enable VRA and SPDIF out */ - - stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); - - reg = AC97_PCM_FRONT_DAC_RATE; - - return stac9766_ac97_write(codec, reg, runtime->rate); -} - -static int stac9766_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: /* full On */ - case SND_SOC_BIAS_PREPARE: /* partial On */ - case SND_SOC_BIAS_STANDBY: /* Off, with power */ - stac9766_ac97_write(codec, AC97_POWERDOWN, 0x0000); - break; - case SND_SOC_BIAS_OFF: /* Off, without power */ - /* disable everything including AC link */ - stac9766_ac97_write(codec, AC97_POWERDOWN, 0xffff); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) -{ - if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset(codec->ac97); - if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) - return 1; - } - - soc_ac97_ops.reset(codec->ac97); - if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset(codec->ac97); - if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) - return -EIO; - return 0; -} - -static int stac9766_codec_suspend(struct snd_soc_codec *codec) -{ - stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int stac9766_codec_resume(struct snd_soc_codec *codec) -{ - u16 id, reset; - - reset = 0; - /* give the codec an AC97 warm reset to start the link */ -reset: - if (reset > 5) { - printk(KERN_ERR "stac9766 failed to resume"); - return -EIO; - } - codec->ac97->bus->ops->warm_reset(codec->ac97); - id = soc_ac97_ops.read(codec->ac97, AC97_VENDOR_ID2); - if (id != 0x4c13) { - stac9766_reset(codec, 0); - reset++; - goto reset; - } - stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static const struct snd_soc_dai_ops stac9766_dai_ops_analog = { - .prepare = ac97_analog_prepare, -}; - -static const struct snd_soc_dai_ops stac9766_dai_ops_digital = { - .prepare = ac97_digital_prepare, -}; - -static struct snd_soc_dai_driver stac9766_dai[] = { -{ - .name = "stac9766-hifi-analog", - .ac97_control = 1, - - /* stream cababilities */ - .playback = { - .stream_name = "stac9766 analog", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SND_SOC_STD_AC97_FMTS, - }, - .capture = { - .stream_name = "stac9766 analog", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SND_SOC_STD_AC97_FMTS, - }, - /* alsa ops */ - .ops = &stac9766_dai_ops_analog, -}, -{ - .name = "stac9766-hifi-IEC958", - .ac97_control = 1, - - /* stream cababilities */ - .playback = { - .stream_name = "stac9766 IEC958", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_32000 | \ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE, - }, - /* alsa ops */ - .ops = &stac9766_dai_ops_digital, -} -}; - -static int stac9766_codec_probe(struct snd_soc_codec *codec) -{ - int ret = 0; - - printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); - - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); - if (ret < 0) - goto codec_err; - - /* do a cold reset for the controller and then try - * a warm reset followed by an optional cold reset for codec */ - stac9766_reset(codec, 0); - ret = stac9766_reset(codec, 1); - if (ret < 0) { - printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); - goto codec_err; - } - - stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - snd_soc_add_codec_controls(codec, stac9766_snd_ac97_controls, - ARRAY_SIZE(stac9766_snd_ac97_controls)); - - return 0; - -codec_err: - snd_soc_free_ac97_codec(codec); - return ret; -} - -static int stac9766_codec_remove(struct snd_soc_codec *codec) -{ - snd_soc_free_ac97_codec(codec); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { - .write = stac9766_ac97_write, - .read = stac9766_ac97_read, - .set_bias_level = stac9766_set_bias_level, - .probe = stac9766_codec_probe, - .remove = stac9766_codec_remove, - .suspend = stac9766_codec_suspend, - .resume = stac9766_codec_resume, - .reg_cache_size = ARRAY_SIZE(stac9766_reg), - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, - .reg_cache_default = stac9766_reg, -}; - -static __devinit int stac9766_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai)); -} - -static int __devexit stac9766_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver stac9766_codec_driver = { - .driver = { - .name = "stac9766-codec", - .owner = THIS_MODULE, - }, - - .probe = stac9766_probe, - .remove = __devexit_p(stac9766_remove), -}; - -module_platform_driver(stac9766_codec_driver); - -MODULE_DESCRIPTION("ASoC stac9766 driver"); -MODULE_AUTHOR("Jon Smirl "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/stac9766.h b/ANDROID_3.4.5/sound/soc/codecs/stac9766.h deleted file mode 100644 index c726f907..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/stac9766.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * stac9766.h -- STAC9766 Soc Audio driver - */ - -#ifndef _STAC9766_H -#define _STAC9766_H - -#define AC97_STAC_PAGE0 0x1000 -#define AC97_STAC_DA_CONTROL (AC97_STAC_PAGE0 | 0x6A) -#define AC97_STAC_ANALOG_SPECIAL (AC97_STAC_PAGE0 | 0x6E) -#define AC97_STAC_STEREO_MIC 0x78 - -/* STAC9766 DAI ID's */ -#define STAC9766_DAI_AC97_ANALOG 0 -#define STAC9766_DAI_AC97_DIGITAL 1 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.c b/ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.c deleted file mode 100644 index df1e07ff..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * ALSA SoC TLV320AIC23 codec driver - * - * Author: Arun KS, - * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., - * - * Based on sound/soc/codecs/wm8731.c by Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Notes: - * The AIC23 is a driver for a low power stereo audio - * codec tlv320aic23 - * - * The machine layer should disable unsupported inputs/outputs by - * snd_soc_dapm_disable_pin(codec, "LHPOUT"), etc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tlv320aic23.h" - -#define AIC23_VERSION "0.1" - -/* - * AIC23 register cache - */ -static const u16 tlv320aic23_reg[] = { - 0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */ - 0x001A, 0x0004, 0x0007, 0x0001, /* 4 */ - 0x0020, 0x0000, 0x0000, 0x0000, /* 8 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */ -}; - -static const char *rec_src_text[] = { "Line", "Mic" }; -static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; - -static const struct soc_enum rec_src_enum = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); - -static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = -SOC_DAPM_ENUM("Input Select", rec_src_enum); - -static const struct soc_enum tlv320aic23_rec_src = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); -static const struct soc_enum tlv320aic23_deemph = - SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text); - -static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); -static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); -static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0); - -static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 val, reg; - - val = (ucontrol->value.integer.value[0] & 0x07); - - /* linear conversion to userspace - * 000 = -6db - * 001 = -9db - * 010 = -12db - * 011 = -18db (Min) - * 100 = 0db (Max) - */ - val = (val >= 4) ? 4 : (3 - val); - - reg = snd_soc_read(codec, TLV320AIC23_ANLG) & (~0x1C0); - snd_soc_write(codec, TLV320AIC23_ANLG, reg | (val << 6)); - - return 0; -} - -static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 val; - - val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0); - val = val >> 6; - val = (val >= 4) ? 4 : (3 - val); - ucontrol->value.integer.value[0] = val; - return 0; - -} - -static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { - SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL, - TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv), - SOC_SINGLE("Digital Playback Switch", TLV320AIC23_DIGT, 3, 1, 1), - SOC_DOUBLE_R("Line Input Switch", TLV320AIC23_LINVOL, - TLV320AIC23_RINVOL, 7, 1, 0), - SOC_DOUBLE_R_TLV("Line Input Volume", TLV320AIC23_LINVOL, - TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv), - SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1), - SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0), - SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0, - snd_soc_tlv320aic23_get_volsw, - snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv), - SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), -}; - -/* PGA Mixer controls for Line and Mic switch */ -static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = { - SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0), - SOC_DAPM_SINGLE("Mic Sidetone Switch", TLV320AIC23_ANLG, 5, 1, 0), - SOC_DAPM_SINGLE("Playback Switch", TLV320AIC23_ANLG, 4, 1, 0), -}; - -static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", "Playback", TLV320AIC23_PWR, 3, 1), - SND_SOC_DAPM_ADC("ADC", "Capture", TLV320AIC23_PWR, 2, 1), - SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0, - &tlv320aic23_rec_src_mux_controls), - SND_SOC_DAPM_MIXER("Output Mixer", TLV320AIC23_PWR, 4, 1, - &tlv320aic23_output_mixer_controls[0], - ARRAY_SIZE(tlv320aic23_output_mixer_controls)), - SND_SOC_DAPM_PGA("Line Input", TLV320AIC23_PWR, 0, 1, NULL, 0), - SND_SOC_DAPM_PGA("Mic Input", TLV320AIC23_PWR, 1, 1, NULL, 0), - - SND_SOC_DAPM_OUTPUT("LHPOUT"), - SND_SOC_DAPM_OUTPUT("RHPOUT"), - SND_SOC_DAPM_OUTPUT("LOUT"), - SND_SOC_DAPM_OUTPUT("ROUT"), - - SND_SOC_DAPM_INPUT("LLINEIN"), - SND_SOC_DAPM_INPUT("RLINEIN"), - - SND_SOC_DAPM_INPUT("MICIN"), -}; - -static const struct snd_soc_dapm_route tlv320aic23_intercon[] = { - /* Output Mixer */ - {"Output Mixer", "Line Bypass Switch", "Line Input"}, - {"Output Mixer", "Playback Switch", "DAC"}, - {"Output Mixer", "Mic Sidetone Switch", "Mic Input"}, - - /* Outputs */ - {"RHPOUT", NULL, "Output Mixer"}, - {"LHPOUT", NULL, "Output Mixer"}, - {"LOUT", NULL, "Output Mixer"}, - {"ROUT", NULL, "Output Mixer"}, - - /* Inputs */ - {"Line Input", "NULL", "LLINEIN"}, - {"Line Input", "NULL", "RLINEIN"}, - - {"Mic Input", "NULL", "MICIN"}, - - /* input mux */ - {"Capture Source", "Line", "Line Input"}, - {"Capture Source", "Mic", "Mic Input"}, - {"ADC", NULL, "Capture Source"}, - -}; - -/* AIC23 driver data */ -struct aic23 { - enum snd_soc_control_type control_type; - int mclk; - int requested_adc; - int requested_dac; -}; - -/* - * Common Crystals used - * 11.2896 Mhz /128 = *88.2k /192 = 58.8k - * 12.0000 Mhz /125 = *96k /136 = 88.235K - * 12.2880 Mhz /128 = *96k /192 = 64k - * 16.9344 Mhz /128 = 132.3k /192 = *88.2k - * 18.4320 Mhz /128 = 144k /192 = *96k - */ - -/* - * Normal BOSR 0-256/2 = 128, 1-384/2 = 192 - * USB BOSR 0-250/2 = 125, 1-272/2 = 136 - */ -static const int bosr_usb_divisor_table[] = { - 128, 125, 192, 136 -}; -#define LOWER_GROUP ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6) | (1<<7)) -#define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15)) -static const unsigned short sr_valid_mask[] = { - LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/ - LOWER_GROUP, /* Usb, bosr - 0*/ - LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/ - UPPER_GROUP, /* Usb, bosr - 1*/ -}; -/* - * Every divisor is a factor of 11*12 - */ -#define SR_MULT (11*12) -#define A(x) (SR_MULT/x) -static const unsigned char sr_adc_mult_table[] = { - A(2), A(2), A(12), A(12), 0, 0, A(3), A(1), - A(2), A(2), A(11), A(11), 0, 0, 0, A(1) -}; -static const unsigned char sr_dac_mult_table[] = { - A(2), A(12), A(2), A(12), 0, 0, A(3), A(1), - A(2), A(11), A(2), A(11), 0, 0, 0, A(1) -}; - -static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc, - int dac, int dac_l, int dac_h, int need_dac) -{ - if ((adc >= adc_l) && (adc <= adc_h) && - (dac >= dac_l) && (dac <= dac_h)) { - int diff_adc = need_adc - adc; - int diff_dac = need_dac - dac; - return abs(diff_adc) + abs(diff_dac); - } - return UINT_MAX; -} - -static int find_rate(int mclk, u32 need_adc, u32 need_dac) -{ - int i, j; - int best_i = -1; - int best_j = -1; - int best_div = 0; - unsigned best_score = UINT_MAX; - int adc_l, adc_h, dac_l, dac_h; - - need_adc *= SR_MULT; - need_dac *= SR_MULT; - /* - * rates given are +/- 1/32 - */ - adc_l = need_adc - (need_adc >> 5); - adc_h = need_adc + (need_adc >> 5); - dac_l = need_dac - (need_dac >> 5); - dac_h = need_dac + (need_dac >> 5); - for (i = 0; i < ARRAY_SIZE(bosr_usb_divisor_table); i++) { - int base = mclk / bosr_usb_divisor_table[i]; - int mask = sr_valid_mask[i]; - for (j = 0; j < ARRAY_SIZE(sr_adc_mult_table); - j++, mask >>= 1) { - int adc; - int dac; - int score; - if ((mask & 1) == 0) - continue; - adc = base * sr_adc_mult_table[j]; - dac = base * sr_dac_mult_table[j]; - score = get_score(adc, adc_l, adc_h, need_adc, - dac, dac_l, dac_h, need_dac); - if (best_score > score) { - best_score = score; - best_i = i; - best_j = j; - best_div = 0; - } - score = get_score((adc >> 1), adc_l, adc_h, need_adc, - (dac >> 1), dac_l, dac_h, need_dac); - /* prefer to have a /2 */ - if ((score != UINT_MAX) && (best_score >= score)) { - best_score = score; - best_i = i; - best_j = j; - best_div = 1; - } - } - } - return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT); -} - -#ifdef DEBUG -static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk, - u32 *sample_rate_adc, u32 *sample_rate_dac) -{ - int src = snd_soc_read(codec, TLV320AIC23_SRATE); - int sr = (src >> 2) & 0x0f; - int val = (mclk / bosr_usb_divisor_table[src & 3]); - int adc = (val * sr_adc_mult_table[sr]) / SR_MULT; - int dac = (val * sr_dac_mult_table[sr]) / SR_MULT; - if (src & TLV320AIC23_CLKIN_HALF) { - adc >>= 1; - dac >>= 1; - } - *sample_rate_adc = adc; - *sample_rate_dac = dac; -} -#endif - -static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk, - u32 sample_rate_adc, u32 sample_rate_dac) -{ - /* Search for the right sample rate */ - int data = find_rate(mclk, sample_rate_adc, sample_rate_dac); - if (data < 0) { - printk(KERN_ERR "%s:Invalid rate %u,%u requested\n", - __func__, sample_rate_adc, sample_rate_dac); - return -EINVAL; - } - snd_soc_write(codec, TLV320AIC23_SRATE, data); -#ifdef DEBUG - { - u32 adc, dac; - get_current_sample_rates(codec, mclk, &adc, &dac); - printk(KERN_DEBUG "actual samplerate = %u,%u reg=%x\n", - adc, dac, data); - } -#endif - return 0; -} - -static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 iface_reg; - int ret; - struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); - u32 sample_rate_adc = aic23->requested_adc; - u32 sample_rate_dac = aic23->requested_dac; - u32 sample_rate = params_rate(params); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - aic23->requested_dac = sample_rate_dac = sample_rate; - if (!sample_rate_adc) - sample_rate_adc = sample_rate; - } else { - aic23->requested_adc = sample_rate_adc = sample_rate; - if (!sample_rate_dac) - sample_rate_dac = sample_rate; - } - ret = set_sample_rate_control(codec, aic23->mclk, sample_rate_adc, - sample_rate_dac); - if (ret < 0) - return ret; - - iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface_reg |= (0x01 << 2); - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface_reg |= (0x02 << 2); - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface_reg |= (0x03 << 2); - break; - } - snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); - - return 0; -} - -static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - /* set active */ - snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001); - - return 0; -} - -static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); - - /* deactivate */ - if (!codec->active) { - udelay(50); - snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); - } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - aic23->requested_dac = 0; - else - aic23->requested_adc = 0; -} - -static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg; - - reg = snd_soc_read(codec, TLV320AIC23_DIGT); - if (mute) - reg |= TLV320AIC23_DACM_MUTE; - - else - reg &= ~TLV320AIC23_DACM_MUTE; - - snd_soc_write(codec, TLV320AIC23_DIGT, reg); - - return 0; -} - -static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface_reg; - - iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & (~0x03); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface_reg |= TLV320AIC23_MS_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: - iface_reg &= ~TLV320AIC23_MS_MASTER; - break; - default: - return -EINVAL; - - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface_reg |= TLV320AIC23_FOR_I2S; - break; - case SND_SOC_DAIFMT_DSP_A: - iface_reg |= TLV320AIC23_LRP_ON; - case SND_SOC_DAIFMT_DSP_B: - iface_reg |= TLV320AIC23_FOR_DSP; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface_reg |= TLV320AIC23_FOR_LJUST; - break; - default: - return -EINVAL; - - } - - snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); - - return 0; -} - -static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai); - aic23->mclk = freq; - return 0; -} - -static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 reg = snd_soc_read(codec, TLV320AIC23_PWR) & 0x17f; - - switch (level) { - case SND_SOC_BIAS_ON: - /* vref/mid, osc on, dac unmute */ - reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \ - TLV320AIC23_DAC_OFF); - snd_soc_write(codec, TLV320AIC23_PWR, reg); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - /* everything off except vref/vmid, */ - snd_soc_write(codec, TLV320AIC23_PWR, - reg | TLV320AIC23_CLK_OFF); - break; - case SND_SOC_BIAS_OFF: - /* everything off, dac mute, inactive */ - snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); - snd_soc_write(codec, TLV320AIC23_PWR, 0x1ff); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define AIC23_RATES SNDRV_PCM_RATE_8000_96000 -#define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops tlv320aic23_dai_ops = { - .prepare = tlv320aic23_pcm_prepare, - .hw_params = tlv320aic23_hw_params, - .shutdown = tlv320aic23_shutdown, - .digital_mute = tlv320aic23_mute, - .set_fmt = tlv320aic23_set_dai_fmt, - .set_sysclk = tlv320aic23_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver tlv320aic23_dai = { - .name = "tlv320aic23-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = AIC23_RATES, - .formats = AIC23_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = AIC23_RATES, - .formats = AIC23_FORMATS,}, - .ops = &tlv320aic23_dai_ops, -}; - -static int tlv320aic23_suspend(struct snd_soc_codec *codec) -{ - tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int tlv320aic23_resume(struct snd_soc_codec *codec) -{ - snd_soc_cache_sync(codec); - tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int tlv320aic23_probe(struct snd_soc_codec *codec) -{ - struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); - int ret; - - printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* Reset codec */ - snd_soc_write(codec, TLV320AIC23_RESET, 0); - - /* Write the register default value to cache for reserved registers, - * so the write to the these registers are suppressed by the cache - * restore code when it skips writes of default registers. - */ - snd_soc_cache_write(codec, 0x0A, 0); - snd_soc_cache_write(codec, 0x0B, 0); - snd_soc_cache_write(codec, 0x0C, 0); - snd_soc_cache_write(codec, 0x0D, 0); - snd_soc_cache_write(codec, 0x0E, 0); - - /* power on device */ - tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K); - - /* Unmute input */ - snd_soc_update_bits(codec, TLV320AIC23_LINVOL, - TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED); - - snd_soc_update_bits(codec, TLV320AIC23_RINVOL, - TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED); - - snd_soc_update_bits(codec, TLV320AIC23_ANLG, - TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED, - 0); - - /* Default output volume */ - snd_soc_write(codec, TLV320AIC23_LCHNVOL, - TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK); - snd_soc_write(codec, TLV320AIC23_RCHNVOL, - TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK); - - snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1); - - snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls, - ARRAY_SIZE(tlv320aic23_snd_controls)); - - return 0; -} - -static int tlv320aic23_remove(struct snd_soc_codec *codec) -{ - tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { - .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = tlv320aic23_reg, - .probe = tlv320aic23_probe, - .remove = tlv320aic23_remove, - .suspend = tlv320aic23_suspend, - .resume = tlv320aic23_resume, - .set_bias_level = tlv320aic23_set_bias_level, - .dapm_widgets = tlv320aic23_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), - .dapm_routes = tlv320aic23_intercon, - .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), -}; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -/* - * If the i2c layer weren't so broken, we could pass this kind of data - * around - */ -static int tlv320aic23_codec_probe(struct i2c_client *i2c, - const struct i2c_device_id *i2c_id) -{ - struct aic23 *aic23; - int ret; - - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EINVAL; - - aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL); - if (aic23 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, aic23); - aic23->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); - return ret; -} -static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - return 0; -} - -static const struct i2c_device_id tlv320aic23_id[] = { - {"tlv320aic23", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); - -static struct i2c_driver tlv320aic23_i2c_driver = { - .driver = { - .name = "tlv320aic23-codec", - }, - .probe = tlv320aic23_codec_probe, - .remove = __exit_p(tlv320aic23_i2c_remove), - .id_table = tlv320aic23_id, -}; - -#endif - -static int __init tlv320aic23_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&tlv320aic23_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(tlv320aic23_modinit); - -static void __exit tlv320aic23_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&tlv320aic23_i2c_driver); -#endif -} -module_exit(tlv320aic23_exit); - -MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); -MODULE_AUTHOR("Arun KS "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.h b/ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.h deleted file mode 100644 index e804120b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic23.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * ALSA SoC TLV320AIC23 codec driver - * - * Author: Arun KS, - * Copyright: (C) 2008 Mistral Solutions Pvt Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _TLV320AIC23_H -#define _TLV320AIC23_H - -/* Codec TLV320AIC23 */ -#define TLV320AIC23_LINVOL 0x00 -#define TLV320AIC23_RINVOL 0x01 -#define TLV320AIC23_LCHNVOL 0x02 -#define TLV320AIC23_RCHNVOL 0x03 -#define TLV320AIC23_ANLG 0x04 -#define TLV320AIC23_DIGT 0x05 -#define TLV320AIC23_PWR 0x06 -#define TLV320AIC23_DIGT_FMT 0x07 -#define TLV320AIC23_SRATE 0x08 -#define TLV320AIC23_ACTIVE 0x09 -#define TLV320AIC23_RESET 0x0F - -/* Left (right) line input volume control register */ -#define TLV320AIC23_LRS_ENABLED 0x0100 -#define TLV320AIC23_LIM_MUTED 0x0080 -#define TLV320AIC23_LIV_DEFAULT 0x0017 -#define TLV320AIC23_LIV_MAX 0x001f -#define TLV320AIC23_LIV_MIN 0x0000 - -/* Left (right) channel headphone volume control register */ -#define TLV320AIC23_LZC_ON 0x0080 -#define TLV320AIC23_LHV_DEFAULT 0x0079 -#define TLV320AIC23_LHV_MAX 0x007f -#define TLV320AIC23_LHV_MIN 0x0000 - -/* Analog audio path control register */ -#define TLV320AIC23_STA_REG(x) ((x)<<6) -#define TLV320AIC23_STE_ENABLED 0x0020 -#define TLV320AIC23_DAC_SELECTED 0x0010 -#define TLV320AIC23_BYPASS_ON 0x0008 -#define TLV320AIC23_INSEL_MIC 0x0004 -#define TLV320AIC23_MICM_MUTED 0x0002 -#define TLV320AIC23_MICB_20DB 0x0001 - -/* Digital audio path control register */ -#define TLV320AIC23_DACM_MUTE 0x0008 -#define TLV320AIC23_DEEMP_32K 0x0002 -#define TLV320AIC23_DEEMP_44K 0x0004 -#define TLV320AIC23_DEEMP_48K 0x0006 -#define TLV320AIC23_ADCHP_ON 0x0001 - -/* Power control down register */ -#define TLV320AIC23_DEVICE_PWR_OFF 0x0080 -#define TLV320AIC23_CLK_OFF 0x0040 -#define TLV320AIC23_OSC_OFF 0x0020 -#define TLV320AIC23_OUT_OFF 0x0010 -#define TLV320AIC23_DAC_OFF 0x0008 -#define TLV320AIC23_ADC_OFF 0x0004 -#define TLV320AIC23_MIC_OFF 0x0002 -#define TLV320AIC23_LINE_OFF 0x0001 - -/* Digital audio interface register */ -#define TLV320AIC23_MS_MASTER 0x0040 -#define TLV320AIC23_LRSWAP_ON 0x0020 -#define TLV320AIC23_LRP_ON 0x0010 -#define TLV320AIC23_IWL_16 0x0000 -#define TLV320AIC23_IWL_20 0x0004 -#define TLV320AIC23_IWL_24 0x0008 -#define TLV320AIC23_IWL_32 0x000C -#define TLV320AIC23_FOR_I2S 0x0002 -#define TLV320AIC23_FOR_DSP 0x0003 -#define TLV320AIC23_FOR_LJUST 0x0001 - -/* Sample rate control register */ -#define TLV320AIC23_CLKOUT_HALF 0x0080 -#define TLV320AIC23_CLKIN_HALF 0x0040 -#define TLV320AIC23_BOSR_384fs 0x0002 /* BOSR_272fs in USB mode */ -#define TLV320AIC23_USB_CLK_ON 0x0001 -#define TLV320AIC23_SR_MASK 0xf -#define TLV320AIC23_CLKOUT_SHIFT 7 -#define TLV320AIC23_CLKIN_SHIFT 6 -#define TLV320AIC23_SR_SHIFT 2 -#define TLV320AIC23_BOSR_SHIFT 1 - -/* Digital interface register */ -#define TLV320AIC23_ACT_ON 0x0001 - -/* - * AUDIO related MACROS - */ - -#define TLV320AIC23_DEFAULT_OUT_VOL 0x70 -#define TLV320AIC23_DEFAULT_IN_VOLUME 0x10 - -#define TLV320AIC23_OUT_VOL_MIN TLV320AIC23_LHV_MIN -#define TLV320AIC23_OUT_VOL_MAX TLV320AIC23_LHV_MAX -#define TLV320AIC23_OUT_VO_RANGE (TLV320AIC23_OUT_VOL_MAX - \ - TLV320AIC23_OUT_VOL_MIN) -#define TLV320AIC23_OUT_VOL_MASK TLV320AIC23_OUT_VOL_MAX - -#define TLV320AIC23_IN_VOL_MIN TLV320AIC23_LIV_MIN -#define TLV320AIC23_IN_VOL_MAX TLV320AIC23_LIV_MAX -#define TLV320AIC23_IN_VOL_RANGE (TLV320AIC23_IN_VOL_MAX - \ - TLV320AIC23_IN_VOL_MIN) -#define TLV320AIC23_IN_VOL_MASK TLV320AIC23_IN_VOL_MAX - -#define TLV320AIC23_SIDETONE_MASK 0x1c0 -#define TLV320AIC23_SIDETONE_0 0x100 -#define TLV320AIC23_SIDETONE_6 0x000 -#define TLV320AIC23_SIDETONE_9 0x040 -#define TLV320AIC23_SIDETONE_12 0x080 -#define TLV320AIC23_SIDETONE_18 0x0c0 - -#endif /* _TLV320AIC23_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.c b/ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.c deleted file mode 100644 index 802064b5..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Texas Instruments TLV320AIC26 low power audio CODEC - * ALSA SoC CODEC driver - * - * Copyright (C) 2008 Secret Lab Technologies Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tlv320aic26.h" - -MODULE_DESCRIPTION("ASoC TLV320AIC26 codec driver"); -MODULE_AUTHOR("Grant Likely "); -MODULE_LICENSE("GPL"); - -/* AIC26 driver private data */ -struct aic26 { - struct spi_device *spi; - struct snd_soc_codec codec; - int master; - int datfm; - int mclk; - - /* Keyclick parameters */ - int keyclick_amplitude; - int keyclick_freq; - int keyclick_len; -}; - -/* --------------------------------------------------------------------- - * Register access routines - */ -static unsigned int aic26_reg_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); - u16 *cache = codec->reg_cache; - u16 cmd, value; - u8 buffer[2]; - int rc; - - if (reg >= AIC26_NUM_REGS) { - WARN_ON_ONCE(1); - return 0; - } - - /* Do SPI transfer; first 16bits are command; remaining is - * register contents */ - cmd = AIC26_READ_COMMAND_WORD(reg); - buffer[0] = (cmd >> 8) & 0xff; - buffer[1] = cmd & 0xff; - rc = spi_write_then_read(aic26->spi, buffer, 2, buffer, 2); - if (rc) { - dev_err(&aic26->spi->dev, "AIC26 reg read error\n"); - return -EIO; - } - value = (buffer[0] << 8) | buffer[1]; - - /* Update the cache before returning with the value */ - cache[reg] = value; - return value; -} - -static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - - if (reg >= AIC26_NUM_REGS) { - WARN_ON_ONCE(1); - return 0; - } - - return cache[reg]; -} - -static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); - u16 *cache = codec->reg_cache; - u16 cmd; - u8 buffer[4]; - int rc; - - if (reg >= AIC26_NUM_REGS) { - WARN_ON_ONCE(1); - return -EINVAL; - } - - /* Do SPI transfer; first 16bits are command; remaining is data - * to write into register */ - cmd = AIC26_WRITE_COMMAND_WORD(reg); - buffer[0] = (cmd >> 8) & 0xff; - buffer[1] = cmd & 0xff; - buffer[2] = value >> 8; - buffer[3] = value; - rc = spi_write(aic26->spi, buffer, 4); - if (rc) { - dev_err(&aic26->spi->dev, "AIC26 reg read error\n"); - return -EIO; - } - - /* update cache before returning */ - cache[reg] = value; - return 0; -} - -/* --------------------------------------------------------------------- - * Digital Audio Interface Operations - */ -static int aic26_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); - int fsref, divisor, wlen, pval, jval, dval, qval; - u16 reg; - - dev_dbg(&aic26->spi->dev, "aic26_hw_params(substream=%p, params=%p)\n", - substream, params); - dev_dbg(&aic26->spi->dev, "rate=%i format=%i\n", params_rate(params), - params_format(params)); - - switch (params_rate(params)) { - case 8000: fsref = 48000; divisor = AIC26_DIV_6; break; - case 11025: fsref = 44100; divisor = AIC26_DIV_4; break; - case 12000: fsref = 48000; divisor = AIC26_DIV_4; break; - case 16000: fsref = 48000; divisor = AIC26_DIV_3; break; - case 22050: fsref = 44100; divisor = AIC26_DIV_2; break; - case 24000: fsref = 48000; divisor = AIC26_DIV_2; break; - case 32000: fsref = 48000; divisor = AIC26_DIV_1_5; break; - case 44100: fsref = 44100; divisor = AIC26_DIV_1; break; - case 48000: fsref = 48000; divisor = AIC26_DIV_1; break; - default: - dev_dbg(&aic26->spi->dev, "bad rate\n"); return -EINVAL; - } - - /* select data word length */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: wlen = AIC26_WLEN_16; break; - case SNDRV_PCM_FORMAT_S16_BE: wlen = AIC26_WLEN_16; break; - case SNDRV_PCM_FORMAT_S24_BE: wlen = AIC26_WLEN_24; break; - case SNDRV_PCM_FORMAT_S32_BE: wlen = AIC26_WLEN_32; break; - default: - dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; - } - - /** - * Configure PLL - * fsref = (mclk * PLLM) / 2048 - * where PLLM = J.DDDD (DDDD register ranges from 0 to 9999, decimal) - */ - pval = 1; - /* compute J portion of multiplier */ - jval = fsref / (aic26->mclk / 2048); - /* compute fractional DDDD component of multiplier */ - dval = fsref - (jval * (aic26->mclk / 2048)); - dval = (10000 * dval) / (aic26->mclk / 2048); - dev_dbg(&aic26->spi->dev, "Setting PLLM to %d.%04d\n", jval, dval); - qval = 0; - reg = 0x8000 | qval << 11 | pval << 8 | jval << 2; - aic26_reg_write(codec, AIC26_REG_PLL_PROG1, reg); - reg = dval << 2; - aic26_reg_write(codec, AIC26_REG_PLL_PROG2, reg); - - /* Audio Control 3 (master mode, fsref rate) */ - reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3); - reg &= ~0xf800; - if (aic26->master) - reg |= 0x0800; - if (fsref == 48000) - reg |= 0x2000; - aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); - - /* Audio Control 1 (FSref divisor) */ - reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1); - reg &= ~0x0fff; - reg |= wlen | aic26->datfm | (divisor << 3) | divisor; - aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL1, reg); - - return 0; -} - -/** - * aic26_mute - Mute control to reduce noise when changing audio format - */ -static int aic26_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); - u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN); - - dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n", - dai, mute); - - if (mute) - reg |= 0x8080; - else - reg &= ~0x8080; - aic26_reg_write(codec, AIC26_REG_DAC_GAIN, reg); - - return 0; -} - -static int aic26_set_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); - - dev_dbg(&aic26->spi->dev, "aic26_set_sysclk(dai=%p, clk_id==%i," - " freq=%i, dir=%i)\n", - codec_dai, clk_id, freq, dir); - - /* MCLK needs to fall between 2MHz and 50 MHz */ - if ((freq < 2000000) || (freq > 50000000)) - return -EINVAL; - - aic26->mclk = freq; - return 0; -} - -static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); - - dev_dbg(&aic26->spi->dev, "aic26_set_fmt(dai=%p, fmt==%i)\n", - codec_dai, fmt); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: aic26->master = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: aic26->master = 0; break; - default: - dev_dbg(&aic26->spi->dev, "bad master\n"); return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: aic26->datfm = AIC26_DATFM_I2S; break; - case SND_SOC_DAIFMT_DSP_A: aic26->datfm = AIC26_DATFM_DSP; break; - case SND_SOC_DAIFMT_RIGHT_J: aic26->datfm = AIC26_DATFM_RIGHTJ; break; - case SND_SOC_DAIFMT_LEFT_J: aic26->datfm = AIC26_DATFM_LEFTJ; break; - default: - dev_dbg(&aic26->spi->dev, "bad format\n"); return -EINVAL; - } - - return 0; -} - -/* --------------------------------------------------------------------- - * Digital Audio Interface Definition - */ -#define AIC26_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000) -#define AIC26_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\ - SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE) - -static const struct snd_soc_dai_ops aic26_dai_ops = { - .hw_params = aic26_hw_params, - .digital_mute = aic26_mute, - .set_sysclk = aic26_set_sysclk, - .set_fmt = aic26_set_fmt, -}; - -static struct snd_soc_dai_driver aic26_dai = { - .name = "tlv320aic26-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = AIC26_RATES, - .formats = AIC26_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = AIC26_RATES, - .formats = AIC26_FORMATS, - }, - .ops = &aic26_dai_ops, -}; - -/* --------------------------------------------------------------------- - * ALSA controls - */ -static const char *aic26_capture_src_text[] = {"Mic", "Aux"}; -static const struct soc_enum aic26_capture_src_enum = - SOC_ENUM_SINGLE(AIC26_REG_AUDIO_CTRL1, 12, 2, aic26_capture_src_text); - -static const struct snd_kcontrol_new aic26_snd_controls[] = { - /* Output */ - SOC_DOUBLE("PCM Playback Volume", AIC26_REG_DAC_GAIN, 8, 0, 0x7f, 1), - SOC_DOUBLE("PCM Playback Switch", AIC26_REG_DAC_GAIN, 15, 7, 1, 1), - SOC_SINGLE("PCM Capture Volume", AIC26_REG_ADC_GAIN, 8, 0x7f, 0), - SOC_SINGLE("PCM Capture Mute", AIC26_REG_ADC_GAIN, 15, 1, 1), - SOC_SINGLE("Keyclick activate", AIC26_REG_AUDIO_CTRL2, 15, 0x1, 0), - SOC_SINGLE("Keyclick amplitude", AIC26_REG_AUDIO_CTRL2, 12, 0x7, 0), - SOC_SINGLE("Keyclick frequency", AIC26_REG_AUDIO_CTRL2, 8, 0x7, 0), - SOC_SINGLE("Keyclick period", AIC26_REG_AUDIO_CTRL2, 4, 0xf, 0), - SOC_ENUM("Capture Source", aic26_capture_src_enum), -}; - -/* --------------------------------------------------------------------- - * SPI device portion of driver: sysfs files for debugging - */ - -static ssize_t aic26_keyclick_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct aic26 *aic26 = dev_get_drvdata(dev); - int val, amp, freq, len; - - val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2); - amp = (val >> 12) & 0x7; - freq = (125 << ((val >> 8) & 0x7)) >> 1; - len = 2 * (1 + ((val >> 4) & 0xf)); - - return sprintf(buf, "amp=%x freq=%iHz len=%iclks\n", amp, freq, len); -} - -/* Any write to the keyclick attribute will trigger the keyclick event */ -static ssize_t aic26_keyclick_set(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct aic26 *aic26 = dev_get_drvdata(dev); - int val; - - val = aic26_reg_read_cache(&aic26->codec, AIC26_REG_AUDIO_CTRL2); - val |= 0x8000; - aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL2, val); - - return count; -} - -static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); - -/* --------------------------------------------------------------------- - * SoC CODEC portion of driver: probe and release routines - */ -static int aic26_probe(struct snd_soc_codec *codec) -{ - int ret, err, i, reg; - - dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n"); - - /* Reset the codec to power on defaults */ - aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00); - - /* Power up CODEC */ - aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0); - - /* Audio Control 3 (master mode, fsref rate) */ - reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3); - reg &= ~0xf800; - reg |= 0x0800; /* set master mode */ - aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg); - - /* Fill register cache */ - for (i = 0; i < codec->driver->reg_cache_size; i++) - aic26_reg_read(codec, i); - - /* Register the sysfs files for debugging */ - /* Create SysFS files */ - ret = device_create_file(codec->dev, &dev_attr_keyclick); - if (ret) - dev_info(codec->dev, "error creating sysfs files\n"); - - /* register controls */ - dev_dbg(codec->dev, "Registering controls\n"); - err = snd_soc_add_codec_controls(codec, aic26_snd_controls, - ARRAY_SIZE(aic26_snd_controls)); - WARN_ON(err < 0); - - return 0; -} - -static struct snd_soc_codec_driver aic26_soc_codec_dev = { - .probe = aic26_probe, - .read = aic26_reg_read, - .write = aic26_reg_write, - .reg_cache_size = AIC26_NUM_REGS, - .reg_word_size = sizeof(u16), -}; - -/* --------------------------------------------------------------------- - * SPI device portion of driver: probe and release routines and SPI - * driver registration. - */ -static int aic26_spi_probe(struct spi_device *spi) -{ - struct aic26 *aic26; - int ret; - - dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); - - /* Allocate driver data */ - aic26 = devm_kzalloc(&spi->dev, sizeof *aic26, GFP_KERNEL); - if (!aic26) - return -ENOMEM; - - /* Initialize the driver data */ - aic26->spi = spi; - dev_set_drvdata(&spi->dev, aic26); - aic26->master = 1; - - ret = snd_soc_register_codec(&spi->dev, - &aic26_soc_codec_dev, &aic26_dai, 1); - return ret; -} - -static int aic26_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver aic26_spi = { - .driver = { - .name = "tlv320aic26-codec", - .owner = THIS_MODULE, - }, - .probe = aic26_spi_probe, - .remove = aic26_spi_remove, -}; - -static int __init aic26_init(void) -{ - return spi_register_driver(&aic26_spi); -} -module_init(aic26_init); - -static void __exit aic26_exit(void) -{ - spi_unregister_driver(&aic26_spi); -} -module_exit(aic26_exit); diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.h b/ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.h deleted file mode 100644 index 67f19c3b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic26.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Texas Instruments TLV320AIC26 low power audio CODEC - * register definitions - * - * Copyright (C) 2008 Secret Lab Technologies Ltd. - */ - -#ifndef _TLV320AIC16_H_ -#define _TLV320AIC16_H_ - -/* AIC26 Registers */ -#define AIC26_READ_COMMAND_WORD(addr) ((1 << 15) | (addr << 5)) -#define AIC26_WRITE_COMMAND_WORD(addr) ((0 << 15) | (addr << 5)) -#define AIC26_PAGE_ADDR(page, offset) ((page << 6) | offset) -#define AIC26_NUM_REGS AIC26_PAGE_ADDR(3, 0) - -/* Page 0: Auxiliary data registers */ -#define AIC26_REG_BAT1 AIC26_PAGE_ADDR(0, 0x05) -#define AIC26_REG_BAT2 AIC26_PAGE_ADDR(0, 0x06) -#define AIC26_REG_AUX AIC26_PAGE_ADDR(0, 0x07) -#define AIC26_REG_TEMP1 AIC26_PAGE_ADDR(0, 0x09) -#define AIC26_REG_TEMP2 AIC26_PAGE_ADDR(0, 0x0A) - -/* Page 1: Auxiliary control registers */ -#define AIC26_REG_AUX_ADC AIC26_PAGE_ADDR(1, 0x00) -#define AIC26_REG_STATUS AIC26_PAGE_ADDR(1, 0x01) -#define AIC26_REG_REFERENCE AIC26_PAGE_ADDR(1, 0x03) -#define AIC26_REG_RESET AIC26_PAGE_ADDR(1, 0x04) - -/* Page 2: Audio control registers */ -#define AIC26_REG_AUDIO_CTRL1 AIC26_PAGE_ADDR(2, 0x00) -#define AIC26_REG_ADC_GAIN AIC26_PAGE_ADDR(2, 0x01) -#define AIC26_REG_DAC_GAIN AIC26_PAGE_ADDR(2, 0x02) -#define AIC26_REG_SIDETONE AIC26_PAGE_ADDR(2, 0x03) -#define AIC26_REG_AUDIO_CTRL2 AIC26_PAGE_ADDR(2, 0x04) -#define AIC26_REG_POWER_CTRL AIC26_PAGE_ADDR(2, 0x05) -#define AIC26_REG_AUDIO_CTRL3 AIC26_PAGE_ADDR(2, 0x06) - -#define AIC26_REG_FILTER_COEFF_L_N0 AIC26_PAGE_ADDR(2, 0x07) -#define AIC26_REG_FILTER_COEFF_L_N1 AIC26_PAGE_ADDR(2, 0x08) -#define AIC26_REG_FILTER_COEFF_L_N2 AIC26_PAGE_ADDR(2, 0x09) -#define AIC26_REG_FILTER_COEFF_L_N3 AIC26_PAGE_ADDR(2, 0x0A) -#define AIC26_REG_FILTER_COEFF_L_N4 AIC26_PAGE_ADDR(2, 0x0B) -#define AIC26_REG_FILTER_COEFF_L_N5 AIC26_PAGE_ADDR(2, 0x0C) -#define AIC26_REG_FILTER_COEFF_L_D1 AIC26_PAGE_ADDR(2, 0x0D) -#define AIC26_REG_FILTER_COEFF_L_D2 AIC26_PAGE_ADDR(2, 0x0E) -#define AIC26_REG_FILTER_COEFF_L_D4 AIC26_PAGE_ADDR(2, 0x0F) -#define AIC26_REG_FILTER_COEFF_L_D5 AIC26_PAGE_ADDR(2, 0x10) -#define AIC26_REG_FILTER_COEFF_R_N0 AIC26_PAGE_ADDR(2, 0x11) -#define AIC26_REG_FILTER_COEFF_R_N1 AIC26_PAGE_ADDR(2, 0x12) -#define AIC26_REG_FILTER_COEFF_R_N2 AIC26_PAGE_ADDR(2, 0x13) -#define AIC26_REG_FILTER_COEFF_R_N3 AIC26_PAGE_ADDR(2, 0x14) -#define AIC26_REG_FILTER_COEFF_R_N4 AIC26_PAGE_ADDR(2, 0x15) -#define AIC26_REG_FILTER_COEFF_R_N5 AIC26_PAGE_ADDR(2, 0x16) -#define AIC26_REG_FILTER_COEFF_R_D1 AIC26_PAGE_ADDR(2, 0x17) -#define AIC26_REG_FILTER_COEFF_R_D2 AIC26_PAGE_ADDR(2, 0x18) -#define AIC26_REG_FILTER_COEFF_R_D4 AIC26_PAGE_ADDR(2, 0x19) -#define AIC26_REG_FILTER_COEFF_R_D5 AIC26_PAGE_ADDR(2, 0x1A) - -#define AIC26_REG_PLL_PROG1 AIC26_PAGE_ADDR(2, 0x1B) -#define AIC26_REG_PLL_PROG2 AIC26_PAGE_ADDR(2, 0x1C) -#define AIC26_REG_AUDIO_CTRL4 AIC26_PAGE_ADDR(2, 0x1D) -#define AIC26_REG_AUDIO_CTRL5 AIC26_PAGE_ADDR(2, 0x1E) - -/* fsref dividers; used in register 'Audio Control 1' */ -enum aic26_divisors { - AIC26_DIV_1 = 0, - AIC26_DIV_1_5 = 1, - AIC26_DIV_2 = 2, - AIC26_DIV_3 = 3, - AIC26_DIV_4 = 4, - AIC26_DIV_5 = 5, - AIC26_DIV_5_5 = 6, - AIC26_DIV_6 = 7, -}; - -/* Digital data format */ -enum aic26_datfm { - AIC26_DATFM_I2S = 0 << 8, - AIC26_DATFM_DSP = 1 << 8, - AIC26_DATFM_RIGHTJ = 2 << 8, /* right justified */ - AIC26_DATFM_LEFTJ = 3 << 8, /* left justified */ -}; - -/* Sample word length in bits; used in register 'Audio Control 1' */ -enum aic26_wlen { - AIC26_WLEN_16 = 0 << 10, - AIC26_WLEN_20 = 1 << 10, - AIC26_WLEN_24 = 2 << 10, - AIC26_WLEN_32 = 3 << 10, -}; - -#endif /* _TLV320AIC16_H_ */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.c b/ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.c deleted file mode 100644 index b0a73d37..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * linux/sound/soc/codecs/tlv320aic32x4.c - * - * Copyright 2011 Vista Silicon S.L. - * - * Author: Javier Martin - * - * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tlv320aic32x4.h" - -struct aic32x4_rate_divs { - u32 mclk; - u32 rate; - u8 p_val; - u8 pll_j; - u16 pll_d; - u16 dosr; - u8 ndac; - u8 mdac; - u8 aosr; - u8 nadc; - u8 madc; - u8 blck_N; -}; - -struct aic32x4_priv { - u32 sysclk; - u8 page_no; - void *control_data; - u32 power_cfg; - u32 micpga_routing; - bool swapdacs; -}; - -/* 0dB min, 1dB steps */ -static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0); -/* 0dB min, 0.5dB steps */ -static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); - -static const struct snd_kcontrol_new aic32x4_snd_controls[] = { - SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL, - AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5), - SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, - AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1), - SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, - AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1), - SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, - AIC32X4_HPRGAIN, 6, 0x01, 1), - SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, - AIC32X4_LORGAIN, 6, 0x01, 1), - SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL, - AIC32X4_RMICPGAVOL, 7, 0x01, 1), - - SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), - SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), - - SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL, - AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5), - SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, - AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), - - SOC_SINGLE("Auto-mute Switch", AIC32X4_DACMUTE, 4, 7, 0), - - SOC_SINGLE("AGC Left Switch", AIC32X4_LAGC1, 7, 1, 0), - SOC_SINGLE("AGC Right Switch", AIC32X4_RAGC1, 7, 1, 0), - SOC_DOUBLE_R("AGC Target Level", AIC32X4_LAGC1, AIC32X4_RAGC1, - 4, 0x07, 0), - SOC_DOUBLE_R("AGC Gain Hysteresis", AIC32X4_LAGC1, AIC32X4_RAGC1, - 0, 0x03, 0), - SOC_DOUBLE_R("AGC Hysteresis", AIC32X4_LAGC2, AIC32X4_RAGC2, - 6, 0x03, 0), - SOC_DOUBLE_R("AGC Noise Threshold", AIC32X4_LAGC2, AIC32X4_RAGC2, - 1, 0x1F, 0), - SOC_DOUBLE_R("AGC Max PGA", AIC32X4_LAGC3, AIC32X4_RAGC3, - 0, 0x7F, 0), - SOC_DOUBLE_R("AGC Attack Time", AIC32X4_LAGC4, AIC32X4_RAGC4, - 3, 0x1F, 0), - SOC_DOUBLE_R("AGC Decay Time", AIC32X4_LAGC5, AIC32X4_RAGC5, - 3, 0x1F, 0), - SOC_DOUBLE_R("AGC Noise Debounce", AIC32X4_LAGC6, AIC32X4_RAGC6, - 0, 0x1F, 0), - SOC_DOUBLE_R("AGC Signal Debounce", AIC32X4_LAGC7, AIC32X4_RAGC7, - 0, 0x0F, 0), -}; - -static const struct aic32x4_rate_divs aic32x4_divs[] = { - /* 8k rate */ - {AIC32X4_FREQ_12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24}, - {AIC32X4_FREQ_24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24}, - {AIC32X4_FREQ_25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24}, - /* 11.025k rate */ - {AIC32X4_FREQ_12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16}, - {AIC32X4_FREQ_24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16}, - /* 16k rate */ - {AIC32X4_FREQ_12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12}, - {AIC32X4_FREQ_24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12}, - {AIC32X4_FREQ_25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12}, - /* 22.05k rate */ - {AIC32X4_FREQ_12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8}, - {AIC32X4_FREQ_24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8}, - {AIC32X4_FREQ_25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8}, - /* 32k rate */ - {AIC32X4_FREQ_12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6}, - {AIC32X4_FREQ_24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6}, - /* 44.1k rate */ - {AIC32X4_FREQ_12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4}, - {AIC32X4_FREQ_24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4}, - {AIC32X4_FREQ_25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4}, - /* 48k rate */ - {AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4}, - {AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4}, - {AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4} -}; - -static const struct snd_kcontrol_new hpl_output_mixer_controls[] = { - SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_HPLROUTE, 3, 1, 0), - SOC_DAPM_SINGLE("IN1_L Switch", AIC32X4_HPLROUTE, 2, 1, 0), -}; - -static const struct snd_kcontrol_new hpr_output_mixer_controls[] = { - SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_HPRROUTE, 3, 1, 0), - SOC_DAPM_SINGLE("IN1_R Switch", AIC32X4_HPRROUTE, 2, 1, 0), -}; - -static const struct snd_kcontrol_new lol_output_mixer_controls[] = { - SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_LOLROUTE, 3, 1, 0), -}; - -static const struct snd_kcontrol_new lor_output_mixer_controls[] = { - SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_LORROUTE, 3, 1, 0), -}; - -static const struct snd_kcontrol_new left_input_mixer_controls[] = { - SOC_DAPM_SINGLE("IN1_L P Switch", AIC32X4_LMICPGAPIN, 6, 1, 0), - SOC_DAPM_SINGLE("IN2_L P Switch", AIC32X4_LMICPGAPIN, 4, 1, 0), - SOC_DAPM_SINGLE("IN3_L P Switch", AIC32X4_LMICPGAPIN, 2, 1, 0), -}; - -static const struct snd_kcontrol_new right_input_mixer_controls[] = { - SOC_DAPM_SINGLE("IN1_R P Switch", AIC32X4_RMICPGAPIN, 6, 1, 0), - SOC_DAPM_SINGLE("IN2_R P Switch", AIC32X4_RMICPGAPIN, 4, 1, 0), - SOC_DAPM_SINGLE("IN3_R P Switch", AIC32X4_RMICPGAPIN, 2, 1, 0), -}; - -static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", AIC32X4_DACSETUP, 7, 0), - SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0, - &hpl_output_mixer_controls[0], - ARRAY_SIZE(hpl_output_mixer_controls)), - SND_SOC_DAPM_PGA("HPL Power", AIC32X4_OUTPWRCTL, 5, 0, NULL, 0), - - SND_SOC_DAPM_MIXER("LOL Output Mixer", SND_SOC_NOPM, 0, 0, - &lol_output_mixer_controls[0], - ARRAY_SIZE(lol_output_mixer_controls)), - SND_SOC_DAPM_PGA("LOL Power", AIC32X4_OUTPWRCTL, 3, 0, NULL, 0), - - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", AIC32X4_DACSETUP, 6, 0), - SND_SOC_DAPM_MIXER("HPR Output Mixer", SND_SOC_NOPM, 0, 0, - &hpr_output_mixer_controls[0], - ARRAY_SIZE(hpr_output_mixer_controls)), - SND_SOC_DAPM_PGA("HPR Power", AIC32X4_OUTPWRCTL, 4, 0, NULL, 0), - SND_SOC_DAPM_MIXER("LOR Output Mixer", SND_SOC_NOPM, 0, 0, - &lor_output_mixer_controls[0], - ARRAY_SIZE(lor_output_mixer_controls)), - SND_SOC_DAPM_PGA("LOR Power", AIC32X4_OUTPWRCTL, 2, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0, - &left_input_mixer_controls[0], - ARRAY_SIZE(left_input_mixer_controls)), - SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0, - &right_input_mixer_controls[0], - ARRAY_SIZE(right_input_mixer_controls)), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC32X4_ADCSETUP, 7, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", AIC32X4_ADCSETUP, 6, 0), - SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0), - - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - SND_SOC_DAPM_OUTPUT("LOL"), - SND_SOC_DAPM_OUTPUT("LOR"), - SND_SOC_DAPM_INPUT("IN1_L"), - SND_SOC_DAPM_INPUT("IN1_R"), - SND_SOC_DAPM_INPUT("IN2_L"), - SND_SOC_DAPM_INPUT("IN2_R"), - SND_SOC_DAPM_INPUT("IN3_L"), - SND_SOC_DAPM_INPUT("IN3_R"), -}; - -static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { - /* Left Output */ - {"HPL Output Mixer", "L_DAC Switch", "Left DAC"}, - {"HPL Output Mixer", "IN1_L Switch", "IN1_L"}, - - {"HPL Power", NULL, "HPL Output Mixer"}, - {"HPL", NULL, "HPL Power"}, - - {"LOL Output Mixer", "L_DAC Switch", "Left DAC"}, - - {"LOL Power", NULL, "LOL Output Mixer"}, - {"LOL", NULL, "LOL Power"}, - - /* Right Output */ - {"HPR Output Mixer", "R_DAC Switch", "Right DAC"}, - {"HPR Output Mixer", "IN1_R Switch", "IN1_R"}, - - {"HPR Power", NULL, "HPR Output Mixer"}, - {"HPR", NULL, "HPR Power"}, - - {"LOR Output Mixer", "R_DAC Switch", "Right DAC"}, - - {"LOR Power", NULL, "LOR Output Mixer"}, - {"LOR", NULL, "LOR Power"}, - - /* Left input */ - {"Left Input Mixer", "IN1_L P Switch", "IN1_L"}, - {"Left Input Mixer", "IN2_L P Switch", "IN2_L"}, - {"Left Input Mixer", "IN3_L P Switch", "IN3_L"}, - - {"Left ADC", NULL, "Left Input Mixer"}, - - /* Right Input */ - {"Right Input Mixer", "IN1_R P Switch", "IN1_R"}, - {"Right Input Mixer", "IN2_R P Switch", "IN2_R"}, - {"Right Input Mixer", "IN3_R P Switch", "IN3_R"}, - - {"Right ADC", NULL, "Right Input Mixer"}, -}; - -static inline int aic32x4_change_page(struct snd_soc_codec *codec, - unsigned int new_page) -{ - struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); - u8 data[2]; - int ret; - - data[0] = 0x00; - data[1] = new_page & 0xff; - - ret = codec->hw_write(codec->control_data, data, 2); - if (ret == 2) { - aic32x4->page_no = new_page; - return 0; - } else { - return ret; - } -} - -static int aic32x4_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int val) -{ - struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); - unsigned int page = reg / 128; - unsigned int fixed_reg = reg % 128; - u8 data[2]; - int ret; - - /* A write to AIC32X4_PSEL is really a non-explicit page change */ - if (reg == AIC32X4_PSEL) - return aic32x4_change_page(codec, val); - - if (aic32x4->page_no != page) { - ret = aic32x4_change_page(codec, page); - if (ret != 0) - return ret; - } - - data[0] = fixed_reg & 0xff; - data[1] = val & 0xff; - - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -static unsigned int aic32x4_read(struct snd_soc_codec *codec, unsigned int reg) -{ - struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); - unsigned int page = reg / 128; - unsigned int fixed_reg = reg % 128; - int ret; - - if (aic32x4->page_no != page) { - ret = aic32x4_change_page(codec, page); - if (ret != 0) - return ret; - } - return i2c_smbus_read_byte_data(codec->control_data, fixed_reg & 0xff); -} - -static inline int aic32x4_get_divs(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) { - if ((aic32x4_divs[i].rate == rate) - && (aic32x4_divs[i].mclk == mclk)) { - return i; - } - } - printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n"); - return -EINVAL; -} - -static int aic32x4_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(&codec->dapm, aic32x4_dapm_widgets, - ARRAY_SIZE(aic32x4_dapm_widgets)); - - snd_soc_dapm_add_routes(&codec->dapm, aic32x4_dapm_routes, - ARRAY_SIZE(aic32x4_dapm_routes)); - - snd_soc_dapm_new_widgets(&codec->dapm); - return 0; -} - -static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case AIC32X4_FREQ_12000000: - case AIC32X4_FREQ_24000000: - case AIC32X4_FREQ_25000000: - aic32x4->sysclk = freq; - return 0; - } - printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n"); - return -EINVAL; -} - -static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u8 iface_reg_1; - u8 iface_reg_2; - u8 iface_reg_3; - - iface_reg_1 = snd_soc_read(codec, AIC32X4_IFACE1); - iface_reg_1 = iface_reg_1 & ~(3 << 6 | 3 << 2); - iface_reg_2 = snd_soc_read(codec, AIC32X4_IFACE2); - iface_reg_2 = 0; - iface_reg_3 = snd_soc_read(codec, AIC32X4_IFACE3); - iface_reg_3 = iface_reg_3 & ~(1 << 3); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - break; - case SND_SOC_DAIFMT_DSP_A: - iface_reg_1 |= (AIC32X4_DSP_MODE << AIC32X4_PLLJ_SHIFT); - iface_reg_3 |= (1 << 3); /* invert bit clock */ - iface_reg_2 = 0x01; /* add offset 1 */ - break; - case SND_SOC_DAIFMT_DSP_B: - iface_reg_1 |= (AIC32X4_DSP_MODE << AIC32X4_PLLJ_SHIFT); - iface_reg_3 |= (1 << 3); /* invert bit clock */ - break; - case SND_SOC_DAIFMT_RIGHT_J: - iface_reg_1 |= - (AIC32X4_RIGHT_JUSTIFIED_MODE << AIC32X4_PLLJ_SHIFT); - break; - case SND_SOC_DAIFMT_LEFT_J: - iface_reg_1 |= - (AIC32X4_LEFT_JUSTIFIED_MODE << AIC32X4_PLLJ_SHIFT); - break; - default: - printk(KERN_ERR "aic32x4: invalid DAI interface format\n"); - return -EINVAL; - } - - snd_soc_write(codec, AIC32X4_IFACE1, iface_reg_1); - snd_soc_write(codec, AIC32X4_IFACE2, iface_reg_2); - snd_soc_write(codec, AIC32X4_IFACE3, iface_reg_3); - return 0; -} - -static int aic32x4_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); - u8 data; - int i; - - i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params)); - if (i < 0) { - printk(KERN_ERR "aic32x4: sampling rate not supported\n"); - return i; - } - - /* Use PLL as CODEC_CLKIN and DAC_MOD_CLK as BDIV_CLKIN */ - snd_soc_write(codec, AIC32X4_CLKMUX, AIC32X4_PLLCLKIN); - snd_soc_write(codec, AIC32X4_IFACE3, AIC32X4_DACMOD2BCLK); - - /* We will fix R value to 1 and will make P & J=K.D as varialble */ - data = snd_soc_read(codec, AIC32X4_PLLPR); - data &= ~(7 << 4); - snd_soc_write(codec, AIC32X4_PLLPR, - (data | (aic32x4_divs[i].p_val << 4) | 0x01)); - - snd_soc_write(codec, AIC32X4_PLLJ, aic32x4_divs[i].pll_j); - - snd_soc_write(codec, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8)); - snd_soc_write(codec, AIC32X4_PLLDLSB, - (aic32x4_divs[i].pll_d & 0xff)); - - /* NDAC divider value */ - data = snd_soc_read(codec, AIC32X4_NDAC); - data &= ~(0x7f); - snd_soc_write(codec, AIC32X4_NDAC, data | aic32x4_divs[i].ndac); - - /* MDAC divider value */ - data = snd_soc_read(codec, AIC32X4_MDAC); - data &= ~(0x7f); - snd_soc_write(codec, AIC32X4_MDAC, data | aic32x4_divs[i].mdac); - - /* DOSR MSB & LSB values */ - snd_soc_write(codec, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8); - snd_soc_write(codec, AIC32X4_DOSRLSB, - (aic32x4_divs[i].dosr & 0xff)); - - /* NADC divider value */ - data = snd_soc_read(codec, AIC32X4_NADC); - data &= ~(0x7f); - snd_soc_write(codec, AIC32X4_NADC, data | aic32x4_divs[i].nadc); - - /* MADC divider value */ - data = snd_soc_read(codec, AIC32X4_MADC); - data &= ~(0x7f); - snd_soc_write(codec, AIC32X4_MADC, data | aic32x4_divs[i].madc); - - /* AOSR value */ - snd_soc_write(codec, AIC32X4_AOSR, aic32x4_divs[i].aosr); - - /* BCLK N divider */ - data = snd_soc_read(codec, AIC32X4_BCLKN); - data &= ~(0x7f); - snd_soc_write(codec, AIC32X4_BCLKN, data | aic32x4_divs[i].blck_N); - - data = snd_soc_read(codec, AIC32X4_IFACE1); - data = data & ~(3 << 4); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - data |= (AIC32X4_WORD_LEN_20BITS << AIC32X4_DOSRMSB_SHIFT); - break; - case SNDRV_PCM_FORMAT_S24_LE: - data |= (AIC32X4_WORD_LEN_24BITS << AIC32X4_DOSRMSB_SHIFT); - break; - case SNDRV_PCM_FORMAT_S32_LE: - data |= (AIC32X4_WORD_LEN_32BITS << AIC32X4_DOSRMSB_SHIFT); - break; - } - snd_soc_write(codec, AIC32X4_IFACE1, data); - - return 0; -} - -static int aic32x4_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u8 dac_reg; - - dac_reg = snd_soc_read(codec, AIC32X4_DACMUTE) & ~AIC32X4_MUTEON; - if (mute) - snd_soc_write(codec, AIC32X4_DACMUTE, dac_reg | AIC32X4_MUTEON); - else - snd_soc_write(codec, AIC32X4_DACMUTE, dac_reg); - return 0; -} - -static int aic32x4_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - /* Switch on PLL */ - snd_soc_update_bits(codec, AIC32X4_PLLPR, - AIC32X4_PLLEN, AIC32X4_PLLEN); - - /* Switch on NDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_NDAC, - AIC32X4_NDACEN, AIC32X4_NDACEN); - - /* Switch on MDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_MDAC, - AIC32X4_MDACEN, AIC32X4_MDACEN); - - /* Switch on NADC Divider */ - snd_soc_update_bits(codec, AIC32X4_NADC, - AIC32X4_NADCEN, AIC32X4_NADCEN); - - /* Switch on MADC Divider */ - snd_soc_update_bits(codec, AIC32X4_MADC, - AIC32X4_MADCEN, AIC32X4_MADCEN); - - /* Switch on BCLK_N Divider */ - snd_soc_update_bits(codec, AIC32X4_BCLKN, - AIC32X4_BCLKEN, AIC32X4_BCLKEN); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - /* Switch off PLL */ - snd_soc_update_bits(codec, AIC32X4_PLLPR, - AIC32X4_PLLEN, 0); - - /* Switch off NDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_NDAC, - AIC32X4_NDACEN, 0); - - /* Switch off MDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_MDAC, - AIC32X4_MDACEN, 0); - - /* Switch off NADC Divider */ - snd_soc_update_bits(codec, AIC32X4_NADC, - AIC32X4_NADCEN, 0); - - /* Switch off MADC Divider */ - snd_soc_update_bits(codec, AIC32X4_MADC, - AIC32X4_MADCEN, 0); - - /* Switch off BCLK_N Divider */ - snd_soc_update_bits(codec, AIC32X4_BCLKN, - AIC32X4_BCLKEN, 0); - break; - case SND_SOC_BIAS_OFF: - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define AIC32X4_RATES SNDRV_PCM_RATE_8000_48000 -#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ - | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops aic32x4_ops = { - .hw_params = aic32x4_hw_params, - .digital_mute = aic32x4_mute, - .set_fmt = aic32x4_set_dai_fmt, - .set_sysclk = aic32x4_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver aic32x4_dai = { - .name = "tlv320aic32x4-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = AIC32X4_RATES, - .formats = AIC32X4_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = AIC32X4_RATES, - .formats = AIC32X4_FORMATS,}, - .ops = &aic32x4_ops, - .symmetric_rates = 1, -}; - -static int aic32x4_suspend(struct snd_soc_codec *codec) -{ - aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int aic32x4_resume(struct snd_soc_codec *codec) -{ - aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int aic32x4_probe(struct snd_soc_codec *codec) -{ - struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); - u32 tmp_reg; - - codec->hw_write = (hw_write_t) i2c_master_send; - codec->control_data = aic32x4->control_data; - - snd_soc_write(codec, AIC32X4_RESET, 0x01); - - /* Power platform configuration */ - if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) { - snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN | - AIC32X4_MICBIAS_2075V); - } - if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) { - snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); - } - - tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ? - AIC32X4_LDOCTLEN : 0; - snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg); - - tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); - if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) { - tmp_reg |= AIC32X4_LDOIN_18_36; - } - if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) { - tmp_reg |= AIC32X4_LDOIN2HP; - } - snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg); - - /* Do DACs need to be swapped? */ - if (aic32x4->swapdacs) { - snd_soc_write(codec, AIC32X4_DACSETUP, AIC32X4_LDAC2RCHN | AIC32X4_RDAC2LCHN); - } else { - snd_soc_write(codec, AIC32X4_DACSETUP, AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN); - } - - /* Mic PGA routing */ - if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) { - snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K); - } - if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) { - snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K); - } - - aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - snd_soc_add_codec_controls(codec, aic32x4_snd_controls, - ARRAY_SIZE(aic32x4_snd_controls)); - aic32x4_add_widgets(codec); - - return 0; -} - -static int aic32x4_remove(struct snd_soc_codec *codec) -{ - aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { - .read = aic32x4_read, - .write = aic32x4_write, - .probe = aic32x4_probe, - .remove = aic32x4_remove, - .suspend = aic32x4_suspend, - .resume = aic32x4_resume, - .set_bias_level = aic32x4_set_bias_level, -}; - -static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct aic32x4_pdata *pdata = i2c->dev.platform_data; - struct aic32x4_priv *aic32x4; - int ret; - - aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), - GFP_KERNEL); - if (aic32x4 == NULL) - return -ENOMEM; - - aic32x4->control_data = i2c; - i2c_set_clientdata(i2c, aic32x4); - - if (pdata) { - aic32x4->power_cfg = pdata->power_cfg; - aic32x4->swapdacs = pdata->swapdacs; - aic32x4->micpga_routing = pdata->micpga_routing; - } else { - aic32x4->power_cfg = 0; - aic32x4->swapdacs = false; - aic32x4->micpga_routing = 0; - } - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_aic32x4, &aic32x4_dai, 1); - return ret; -} - -static __devexit int aic32x4_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id aic32x4_i2c_id[] = { - { "tlv320aic32x4", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); - -static struct i2c_driver aic32x4_i2c_driver = { - .driver = { - .name = "tlv320aic32x4", - .owner = THIS_MODULE, - }, - .probe = aic32x4_i2c_probe, - .remove = __devexit_p(aic32x4_i2c_remove), - .id_table = aic32x4_i2c_id, -}; - -static int __init aic32x4_modinit(void) -{ - int ret = 0; - - ret = i2c_add_driver(&aic32x4_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(aic32x4_modinit); - -static void __exit aic32x4_exit(void) -{ - i2c_del_driver(&aic32x4_i2c_driver); -} -module_exit(aic32x4_exit); - -MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); -MODULE_AUTHOR("Javier Martin "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.h b/ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.h deleted file mode 100644 index aae2b244..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic32x4.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * tlv320aic32x4.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - - -#ifndef _TLV320AIC32X4_H -#define _TLV320AIC32X4_H - -/* tlv320aic32x4 register space (in decimal to match datasheet) */ - -#define AIC32X4_PAGE1 128 - -#define AIC32X4_PSEL 0 -#define AIC32X4_RESET 1 -#define AIC32X4_CLKMUX 4 -#define AIC32X4_PLLPR 5 -#define AIC32X4_PLLJ 6 -#define AIC32X4_PLLDMSB 7 -#define AIC32X4_PLLDLSB 8 -#define AIC32X4_NDAC 11 -#define AIC32X4_MDAC 12 -#define AIC32X4_DOSRMSB 13 -#define AIC32X4_DOSRLSB 14 -#define AIC32X4_NADC 18 -#define AIC32X4_MADC 19 -#define AIC32X4_AOSR 20 -#define AIC32X4_CLKMUX2 25 -#define AIC32X4_CLKOUTM 26 -#define AIC32X4_IFACE1 27 -#define AIC32X4_IFACE2 28 -#define AIC32X4_IFACE3 29 -#define AIC32X4_BCLKN 30 -#define AIC32X4_IFACE4 31 -#define AIC32X4_IFACE5 32 -#define AIC32X4_IFACE6 33 -#define AIC32X4_DOUTCTL 53 -#define AIC32X4_DINCTL 54 -#define AIC32X4_DACSPB 60 -#define AIC32X4_ADCSPB 61 -#define AIC32X4_DACSETUP 63 -#define AIC32X4_DACMUTE 64 -#define AIC32X4_LDACVOL 65 -#define AIC32X4_RDACVOL 66 -#define AIC32X4_ADCSETUP 81 -#define AIC32X4_ADCFGA 82 -#define AIC32X4_LADCVOL 83 -#define AIC32X4_RADCVOL 84 -#define AIC32X4_LAGC1 86 -#define AIC32X4_LAGC2 87 -#define AIC32X4_LAGC3 88 -#define AIC32X4_LAGC4 89 -#define AIC32X4_LAGC5 90 -#define AIC32X4_LAGC6 91 -#define AIC32X4_LAGC7 92 -#define AIC32X4_RAGC1 94 -#define AIC32X4_RAGC2 95 -#define AIC32X4_RAGC3 96 -#define AIC32X4_RAGC4 97 -#define AIC32X4_RAGC5 98 -#define AIC32X4_RAGC6 99 -#define AIC32X4_RAGC7 100 -#define AIC32X4_PWRCFG (AIC32X4_PAGE1 + 1) -#define AIC32X4_LDOCTL (AIC32X4_PAGE1 + 2) -#define AIC32X4_OUTPWRCTL (AIC32X4_PAGE1 + 9) -#define AIC32X4_CMMODE (AIC32X4_PAGE1 + 10) -#define AIC32X4_HPLROUTE (AIC32X4_PAGE1 + 12) -#define AIC32X4_HPRROUTE (AIC32X4_PAGE1 + 13) -#define AIC32X4_LOLROUTE (AIC32X4_PAGE1 + 14) -#define AIC32X4_LORROUTE (AIC32X4_PAGE1 + 15) -#define AIC32X4_HPLGAIN (AIC32X4_PAGE1 + 16) -#define AIC32X4_HPRGAIN (AIC32X4_PAGE1 + 17) -#define AIC32X4_LOLGAIN (AIC32X4_PAGE1 + 18) -#define AIC32X4_LORGAIN (AIC32X4_PAGE1 + 19) -#define AIC32X4_HEADSTART (AIC32X4_PAGE1 + 20) -#define AIC32X4_MICBIAS (AIC32X4_PAGE1 + 51) -#define AIC32X4_LMICPGAPIN (AIC32X4_PAGE1 + 52) -#define AIC32X4_LMICPGANIN (AIC32X4_PAGE1 + 54) -#define AIC32X4_RMICPGAPIN (AIC32X4_PAGE1 + 55) -#define AIC32X4_RMICPGANIN (AIC32X4_PAGE1 + 57) -#define AIC32X4_FLOATINGINPUT (AIC32X4_PAGE1 + 58) -#define AIC32X4_LMICPGAVOL (AIC32X4_PAGE1 + 59) -#define AIC32X4_RMICPGAVOL (AIC32X4_PAGE1 + 60) - -#define AIC32X4_FREQ_12000000 12000000 -#define AIC32X4_FREQ_24000000 24000000 -#define AIC32X4_FREQ_25000000 25000000 - -#define AIC32X4_WORD_LEN_16BITS 0x00 -#define AIC32X4_WORD_LEN_20BITS 0x01 -#define AIC32X4_WORD_LEN_24BITS 0x02 -#define AIC32X4_WORD_LEN_32BITS 0x03 - -#define AIC32X4_I2S_MODE 0x00 -#define AIC32X4_DSP_MODE 0x01 -#define AIC32X4_RIGHT_JUSTIFIED_MODE 0x02 -#define AIC32X4_LEFT_JUSTIFIED_MODE 0x03 - -#define AIC32X4_AVDDWEAKDISABLE 0x08 -#define AIC32X4_LDOCTLEN 0x01 - -#define AIC32X4_LDOIN_18_36 0x01 -#define AIC32X4_LDOIN2HP 0x02 - -#define AIC32X4_DACSPBLOCK_MASK 0x1f -#define AIC32X4_ADCSPBLOCK_MASK 0x1f - -#define AIC32X4_PLLJ_SHIFT 6 -#define AIC32X4_DOSRMSB_SHIFT 4 - -#define AIC32X4_PLLCLKIN 0x03 - -#define AIC32X4_MICBIAS_LDOIN 0x08 -#define AIC32X4_MICBIAS_2075V 0x60 - -#define AIC32X4_LMICPGANIN_IN2R_10K 0x10 -#define AIC32X4_RMICPGANIN_IN1L_10K 0x10 - -#define AIC32X4_LMICPGAVOL_NOGAIN 0x80 -#define AIC32X4_RMICPGAVOL_NOGAIN 0x80 - -#define AIC32X4_BCLKMASTER 0x08 -#define AIC32X4_WCLKMASTER 0x04 -#define AIC32X4_PLLEN (0x01 << 7) -#define AIC32X4_NDACEN (0x01 << 7) -#define AIC32X4_MDACEN (0x01 << 7) -#define AIC32X4_NADCEN (0x01 << 7) -#define AIC32X4_MADCEN (0x01 << 7) -#define AIC32X4_BCLKEN (0x01 << 7) -#define AIC32X4_DACEN (0x03 << 6) -#define AIC32X4_RDAC2LCHN (0x02 << 2) -#define AIC32X4_LDAC2RCHN (0x02 << 4) -#define AIC32X4_LDAC2LCHN (0x01 << 4) -#define AIC32X4_RDAC2RCHN (0x01 << 2) - -#define AIC32X4_SSTEP2WCLK 0x01 -#define AIC32X4_MUTEON 0x0C -#define AIC32X4_DACMOD2BCLK 0x01 - -#endif /* _TLV320AIC32X4_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.c b/ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.c deleted file mode 100644 index b8f0262a..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.c +++ /dev/null @@ -1,1505 +0,0 @@ -/* - * ALSA SoC TLV320AIC3X codec driver - * - * Author: Vladimir Barinov, - * Copyright: (C) 2007 MontaVista Software, Inc., - * - * Based on sound/soc/codecs/wm8753.c by Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Notes: - * The AIC3X is a driver for a low power stereo audio - * codecs aic31, aic32, aic33, aic3007. - * - * It supports full aic33 codec functionality. - * The compatibility with aic32, aic31 and aic3007 is as follows: - * aic32/aic3007 | aic31 - * --------------------------------------- - * MONO_LOUT -> N/A | MONO_LOUT -> N/A - * | IN1L -> LINE1L - * | IN1R -> LINE1R - * | IN2L -> LINE2L - * | IN2R -> LINE2R - * | MIC3L/R -> N/A - * truncated internal functionality in - * accordance with documentation - * --------------------------------------- - * - * Hence the machine layer should disable unsupported inputs/outputs by - * snd_soc_dapm_disable_pin(codec, "MONO_LOUT"), etc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tlv320aic3x.h" - -#define AIC3X_NUM_SUPPLIES 4 -static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = { - "IOVDD", /* I/O Voltage */ - "DVDD", /* Digital Core Voltage */ - "AVDD", /* Analog DAC Voltage */ - "DRVDD", /* ADC Analog and Output Driver Voltage */ -}; - -static LIST_HEAD(reset_list); - -struct aic3x_priv; - -struct aic3x_disable_nb { - struct notifier_block nb; - struct aic3x_priv *aic3x; -}; - -/* codec private data */ -struct aic3x_priv { - struct snd_soc_codec *codec; - struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; - struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES]; - enum snd_soc_control_type control_type; - struct aic3x_setup_data *setup; - unsigned int sysclk; - struct list_head list; - int master; - int gpio_reset; - int power; -#define AIC3X_MODEL_3X 0 -#define AIC3X_MODEL_33 1 -#define AIC3X_MODEL_3007 2 - u16 model; -}; - -/* - * AIC3X register cache - * We can't read the AIC3X register space when we are - * using 2 wire for device control, so we cache them instead. - * There is no point in caching the reset register - */ -static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { - 0x00, 0x00, 0x00, 0x10, /* 0 */ - 0x04, 0x00, 0x00, 0x00, /* 4 */ - 0x00, 0x00, 0x00, 0x01, /* 8 */ - 0x00, 0x00, 0x00, 0x80, /* 12 */ - 0x80, 0xff, 0xff, 0x78, /* 16 */ - 0x78, 0x78, 0x78, 0x78, /* 20 */ - 0x78, 0x00, 0x00, 0xfe, /* 24 */ - 0x00, 0x00, 0xfe, 0x00, /* 28 */ - 0x18, 0x18, 0x00, 0x00, /* 32 */ - 0x00, 0x00, 0x00, 0x00, /* 36 */ - 0x00, 0x00, 0x00, 0x80, /* 40 */ - 0x80, 0x00, 0x00, 0x00, /* 44 */ - 0x00, 0x00, 0x00, 0x04, /* 48 */ - 0x00, 0x00, 0x00, 0x00, /* 52 */ - 0x00, 0x00, 0x04, 0x00, /* 56 */ - 0x00, 0x00, 0x00, 0x00, /* 60 */ - 0x00, 0x04, 0x00, 0x00, /* 64 */ - 0x00, 0x00, 0x00, 0x00, /* 68 */ - 0x04, 0x00, 0x00, 0x00, /* 72 */ - 0x00, 0x00, 0x00, 0x00, /* 76 */ - 0x00, 0x00, 0x00, 0x00, /* 80 */ - 0x00, 0x00, 0x00, 0x00, /* 84 */ - 0x00, 0x00, 0x00, 0x00, /* 88 */ - 0x00, 0x00, 0x00, 0x00, /* 92 */ - 0x00, 0x00, 0x00, 0x00, /* 96 */ - 0x00, 0x00, 0x02, /* 100 */ -}; - -#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw_aic3x, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) } - -/* - * All input lines are connected when !0xf and disconnected with 0xf bit field, - * so we have to use specific dapm_put call for input mixer - */ -static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - unsigned short val, val_mask; - int ret; - struct snd_soc_dapm_path *path; - int found = 0; - - val = (ucontrol->value.integer.value[0] & mask); - - mask = 0xf; - if (val) - val = mask; - - if (invert) - val = mask - val; - val_mask = mask << shift; - val = val << shift; - - mutex_lock(&widget->codec->mutex); - - if (snd_soc_test_bits(widget->codec, reg, val_mask, val)) { - /* find dapm widget path assoc with kcontrol */ - list_for_each_entry(path, &widget->dapm->card->paths, list) { - if (path->kcontrol != kcontrol) - continue; - - /* found, now check type */ - found = 1; - if (val) - /* new connection */ - path->connect = invert ? 0 : 1; - else - /* old connection must be powered down */ - path->connect = invert ? 1 : 0; - - dapm_mark_dirty(path->source, "tlv320aic3x source"); - dapm_mark_dirty(path->sink, "tlv320aic3x sink"); - - break; - } - - if (found) - snd_soc_dapm_sync(widget->dapm); - } - - ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); - - mutex_unlock(&widget->codec->mutex); - return ret; -} - -static const char *aic3x_left_dac_mux[] = { "DAC_L1", "DAC_L3", "DAC_L2" }; -static const char *aic3x_right_dac_mux[] = { "DAC_R1", "DAC_R3", "DAC_R2" }; -static const char *aic3x_left_hpcom_mux[] = - { "differential of HPLOUT", "constant VCM", "single-ended" }; -static const char *aic3x_right_hpcom_mux[] = - { "differential of HPROUT", "constant VCM", "single-ended", - "differential of HPLCOM", "external feedback" }; -static const char *aic3x_linein_mode_mux[] = { "single-ended", "differential" }; -static const char *aic3x_adc_hpf[] = - { "Disabled", "0.0045xFs", "0.0125xFs", "0.025xFs" }; - -#define LDAC_ENUM 0 -#define RDAC_ENUM 1 -#define LHPCOM_ENUM 2 -#define RHPCOM_ENUM 3 -#define LINE1L_2_L_ENUM 4 -#define LINE1L_2_R_ENUM 5 -#define LINE1R_2_L_ENUM 6 -#define LINE1R_2_R_ENUM 7 -#define LINE2L_ENUM 8 -#define LINE2R_ENUM 9 -#define ADC_HPF_ENUM 10 - -static const struct soc_enum aic3x_enum[] = { - SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux), - SOC_ENUM_SINGLE(DAC_LINE_MUX, 4, 3, aic3x_right_dac_mux), - SOC_ENUM_SINGLE(HPLCOM_CFG, 4, 3, aic3x_left_hpcom_mux), - SOC_ENUM_SINGLE(HPRCOM_CFG, 3, 5, aic3x_right_hpcom_mux), - SOC_ENUM_SINGLE(LINE1L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), - SOC_ENUM_SINGLE(LINE1L_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), - SOC_ENUM_SINGLE(LINE1R_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), - SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), - SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), - SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), - SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), -}; - -/* - * DAC digital volumes. From -63.5 to 0 dB in 0.5 dB steps - */ -static DECLARE_TLV_DB_SCALE(dac_tlv, -6350, 50, 0); -/* ADC PGA gain volumes. From 0 to 59.5 dB in 0.5 dB steps */ -static DECLARE_TLV_DB_SCALE(adc_tlv, 0, 50, 0); -/* - * Output stage volumes. From -78.3 to 0 dB. Muted below -78.3 dB. - * Step size is approximately 0.5 dB over most of the scale but increasing - * near the very low levels. - * Define dB scale so that it is mostly correct for range about -55 to 0 dB - * but having increasing dB difference below that (and where it doesn't count - * so much). This setting shows -50 dB (actual is -50.3 dB) for register - * value 100 and -58.5 dB (actual is -78.3 dB) for register value 117. - */ -static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1); - -static const struct snd_kcontrol_new aic3x_snd_controls[] = { - /* Output */ - SOC_DOUBLE_R_TLV("PCM Playback Volume", - LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv), - - /* - * Output controls that map to output mixer switches. Note these are - * only for swapped L-to-R and R-to-L routes. See below stereo controls - * for direct L-to-L and R-to-R routes. - */ - SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume", - LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume", - PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume", - DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv), - - SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume", - LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume", - PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume", - DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv), - - SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume", - LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume", - PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume", - DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), - - SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume", - LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume", - PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume", - DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv), - - SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume", - LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume", - PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume", - DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv), - - SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume", - LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume", - PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume", - DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - - /* Stereo output controls for direct L-to-L and R-to-R routes */ - SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume", - LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL, - 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("Line PGA Bypass Volume", - PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL, - 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("Line DAC Playback Volume", - DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, - 0, 118, 1, output_stage_tlv), - - SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume", - LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, - 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume", - PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, - 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("Mono DAC Playback Volume", - DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, - 0, 118, 1, output_stage_tlv), - - SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume", - LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL, - 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("HP PGA Bypass Volume", - PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL, - 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("HP DAC Playback Volume", - DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, - 0, 118, 1, output_stage_tlv), - - SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume", - LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL, - 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume", - PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL, - 0, 118, 1, output_stage_tlv), - SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume", - DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, - 0, 118, 1, output_stage_tlv), - - /* Output pin mute controls */ - SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, - 0x01, 0), - SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), - SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, - 0x01, 0), - SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, - 0x01, 0), - - /* - * Note: enable Automatic input Gain Controller with care. It can - * adjust PGA to max value when ADC is on and will never go back. - */ - SOC_DOUBLE_R("AGC Switch", LAGC_CTRL_A, RAGC_CTRL_A, 7, 0x01, 0), - - /* Input */ - SOC_DOUBLE_R_TLV("PGA Capture Volume", LADC_VOL, RADC_VOL, - 0, 119, 0, adc_tlv), - SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1), - - SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), -}; - -/* - * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps - */ -static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0); - -static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl = - SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv); - -/* Left DAC Mux */ -static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); - -/* Right DAC Mux */ -static const struct snd_kcontrol_new aic3x_right_dac_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[RDAC_ENUM]); - -/* Left HPCOM Mux */ -static const struct snd_kcontrol_new aic3x_left_hpcom_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[LHPCOM_ENUM]); - -/* Right HPCOM Mux */ -static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]); - -/* Left Line Mixer */ -static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = { - SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_LLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_LLOPM_VOL, 7, 1, 0), -}; - -/* Right Line Mixer */ -static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = { - SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_RLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), -}; - -/* Mono Mixer */ -static const struct snd_kcontrol_new aic3x_mono_mixer_controls[] = { - SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0), -}; - -/* Left HP Mixer */ -static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLOUT_VOL, 7, 1, 0), -}; - -/* Right HP Mixer */ -static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPROUT_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), -}; - -/* Left HPCOM Mixer */ -static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = { - SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLCOM_VOL, 7, 1, 0), -}; - -/* Right HPCOM Mixer */ -static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = { - SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPRCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0), - SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), -}; - -/* Left PGA Mixer */ -static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = { - SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1), - SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_LADC_CTRL, 3, 1, 1), - SOC_DAPM_SINGLE_AIC3X("Line2L Switch", LINE2L_2_LADC_CTRL, 3, 1, 1), - SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1), - SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_LADC_CTRL, 0, 1, 1), -}; - -/* Right PGA Mixer */ -static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { - SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1), - SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_RADC_CTRL, 3, 1, 1), - SOC_DAPM_SINGLE_AIC3X("Line2R Switch", LINE2R_2_RADC_CTRL, 3, 1, 1), - SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_RADC_CTRL, 4, 1, 1), - SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1), -}; - -/* Left Line1 Mux */ -static const struct snd_kcontrol_new aic3x_left_line1l_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_L_ENUM]); -static const struct snd_kcontrol_new aic3x_right_line1l_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[LINE1L_2_R_ENUM]); - -/* Right Line1 Mux */ -static const struct snd_kcontrol_new aic3x_right_line1r_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_R_ENUM]); -static const struct snd_kcontrol_new aic3x_left_line1r_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[LINE1R_2_L_ENUM]); - -/* Left Line2 Mux */ -static const struct snd_kcontrol_new aic3x_left_line2_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[LINE2L_ENUM]); - -/* Right Line2 Mux */ -static const struct snd_kcontrol_new aic3x_right_line2_mux_controls = -SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]); - -static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { - /* Left DAC to Left Outputs */ - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", DAC_PWR, 7, 0), - SND_SOC_DAPM_MUX("Left DAC Mux", SND_SOC_NOPM, 0, 0, - &aic3x_left_dac_mux_controls), - SND_SOC_DAPM_MUX("Left HPCOM Mux", SND_SOC_NOPM, 0, 0, - &aic3x_left_hpcom_mux_controls), - SND_SOC_DAPM_PGA("Left Line Out", LLOPM_CTRL, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left HP Out", HPLOUT_CTRL, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left HP Com", HPLCOM_CTRL, 0, 0, NULL, 0), - - /* Right DAC to Right Outputs */ - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", DAC_PWR, 6, 0), - SND_SOC_DAPM_MUX("Right DAC Mux", SND_SOC_NOPM, 0, 0, - &aic3x_right_dac_mux_controls), - SND_SOC_DAPM_MUX("Right HPCOM Mux", SND_SOC_NOPM, 0, 0, - &aic3x_right_hpcom_mux_controls), - SND_SOC_DAPM_PGA("Right Line Out", RLOPM_CTRL, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right HP Out", HPROUT_CTRL, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right HP Com", HPRCOM_CTRL, 0, 0, NULL, 0), - - /* Mono Output */ - SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0), - - /* Inputs to Left ADC */ - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0), - SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_left_pga_mixer_controls[0], - ARRAY_SIZE(aic3x_left_pga_mixer_controls)), - SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, - &aic3x_left_line1l_mux_controls), - SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0, - &aic3x_left_line1r_mux_controls), - SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, - &aic3x_left_line2_mux_controls), - - /* Inputs to Right ADC */ - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", - LINE1R_2_RADC_CTRL, 2, 0), - SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_right_pga_mixer_controls[0], - ARRAY_SIZE(aic3x_right_pga_mixer_controls)), - SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0, - &aic3x_right_line1l_mux_controls), - SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, - &aic3x_right_line1r_mux_controls), - SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, - &aic3x_right_line2_mux_controls), - - /* - * Not a real mic bias widget but similar function. This is for dynamic - * control of GPIO1 digital mic modulator clock output function when - * using digital mic. - */ - SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "GPIO1 dmic modclk", - AIC3X_GPIO1_REG, 4, 0xf, - AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK, - AIC3X_GPIO1_FUNC_DISABLED), - - /* - * Also similar function like mic bias. Selects digital mic with - * configurable oversampling rate instead of ADC converter. - */ - SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 128", - AIC3X_ASD_INTF_CTRLA, 0, 3, 1, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 64", - AIC3X_ASD_INTF_CTRLA, 0, 3, 2, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 32", - AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0), - - /* Mic Bias */ - SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2V", - MICBIAS_CTRL, 6, 3, 1, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2.5V", - MICBIAS_CTRL, 6, 3, 2, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD", - MICBIAS_CTRL, 6, 3, 3, 0), - - /* Output mixers */ - SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_left_line_mixer_controls[0], - ARRAY_SIZE(aic3x_left_line_mixer_controls)), - SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_right_line_mixer_controls[0], - ARRAY_SIZE(aic3x_right_line_mixer_controls)), - SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_mono_mixer_controls[0], - ARRAY_SIZE(aic3x_mono_mixer_controls)), - SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_left_hp_mixer_controls[0], - ARRAY_SIZE(aic3x_left_hp_mixer_controls)), - SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_right_hp_mixer_controls[0], - ARRAY_SIZE(aic3x_right_hp_mixer_controls)), - SND_SOC_DAPM_MIXER("Left HPCOM Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_left_hpcom_mixer_controls[0], - ARRAY_SIZE(aic3x_left_hpcom_mixer_controls)), - SND_SOC_DAPM_MIXER("Right HPCOM Mixer", SND_SOC_NOPM, 0, 0, - &aic3x_right_hpcom_mixer_controls[0], - ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)), - - SND_SOC_DAPM_OUTPUT("LLOUT"), - SND_SOC_DAPM_OUTPUT("RLOUT"), - SND_SOC_DAPM_OUTPUT("MONO_LOUT"), - SND_SOC_DAPM_OUTPUT("HPLOUT"), - SND_SOC_DAPM_OUTPUT("HPROUT"), - SND_SOC_DAPM_OUTPUT("HPLCOM"), - SND_SOC_DAPM_OUTPUT("HPRCOM"), - - SND_SOC_DAPM_INPUT("MIC3L"), - SND_SOC_DAPM_INPUT("MIC3R"), - SND_SOC_DAPM_INPUT("LINE1L"), - SND_SOC_DAPM_INPUT("LINE1R"), - SND_SOC_DAPM_INPUT("LINE2L"), - SND_SOC_DAPM_INPUT("LINE2R"), - - /* - * Virtual output pin to detection block inside codec. This can be - * used to keep codec bias on if gpio or detection features are needed. - * Force pin on or construct a path with an input jack and mic bias - * widgets. - */ - SND_SOC_DAPM_OUTPUT("Detection"), -}; - -static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = { - /* Class-D outputs */ - SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Class-D Out", CLASSD_CTRL, 2, 0, NULL, 0), - - SND_SOC_DAPM_OUTPUT("SPOP"), - SND_SOC_DAPM_OUTPUT("SPOM"), -}; - -static const struct snd_soc_dapm_route intercon[] = { - /* Left Input */ - {"Left Line1L Mux", "single-ended", "LINE1L"}, - {"Left Line1L Mux", "differential", "LINE1L"}, - - {"Left Line2L Mux", "single-ended", "LINE2L"}, - {"Left Line2L Mux", "differential", "LINE2L"}, - - {"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"}, - {"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"}, - {"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"}, - {"Left PGA Mixer", "Mic3L Switch", "MIC3L"}, - {"Left PGA Mixer", "Mic3R Switch", "MIC3R"}, - - {"Left ADC", NULL, "Left PGA Mixer"}, - {"Left ADC", NULL, "GPIO1 dmic modclk"}, - - /* Right Input */ - {"Right Line1R Mux", "single-ended", "LINE1R"}, - {"Right Line1R Mux", "differential", "LINE1R"}, - - {"Right Line2R Mux", "single-ended", "LINE2R"}, - {"Right Line2R Mux", "differential", "LINE2R"}, - - {"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"}, - {"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"}, - {"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"}, - {"Right PGA Mixer", "Mic3L Switch", "MIC3L"}, - {"Right PGA Mixer", "Mic3R Switch", "MIC3R"}, - - {"Right ADC", NULL, "Right PGA Mixer"}, - {"Right ADC", NULL, "GPIO1 dmic modclk"}, - - /* - * Logical path between digital mic enable and GPIO1 modulator clock - * output function - */ - {"GPIO1 dmic modclk", NULL, "DMic Rate 128"}, - {"GPIO1 dmic modclk", NULL, "DMic Rate 64"}, - {"GPIO1 dmic modclk", NULL, "DMic Rate 32"}, - - /* Left DAC Output */ - {"Left DAC Mux", "DAC_L1", "Left DAC"}, - {"Left DAC Mux", "DAC_L2", "Left DAC"}, - {"Left DAC Mux", "DAC_L3", "Left DAC"}, - - /* Right DAC Output */ - {"Right DAC Mux", "DAC_R1", "Right DAC"}, - {"Right DAC Mux", "DAC_R2", "Right DAC"}, - {"Right DAC Mux", "DAC_R3", "Right DAC"}, - - /* Left Line Output */ - {"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, - {"Left Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, - {"Left Line Mixer", "DACL1 Switch", "Left DAC Mux"}, - {"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, - {"Left Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, - {"Left Line Mixer", "DACR1 Switch", "Right DAC Mux"}, - - {"Left Line Out", NULL, "Left Line Mixer"}, - {"Left Line Out", NULL, "Left DAC Mux"}, - {"LLOUT", NULL, "Left Line Out"}, - - /* Right Line Output */ - {"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, - {"Right Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, - {"Right Line Mixer", "DACL1 Switch", "Left DAC Mux"}, - {"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, - {"Right Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, - {"Right Line Mixer", "DACR1 Switch", "Right DAC Mux"}, - - {"Right Line Out", NULL, "Right Line Mixer"}, - {"Right Line Out", NULL, "Right DAC Mux"}, - {"RLOUT", NULL, "Right Line Out"}, - - /* Mono Output */ - {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, - {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, - {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"}, - {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, - {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, - {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"}, - - {"Mono Out", NULL, "Mono Mixer"}, - {"MONO_LOUT", NULL, "Mono Out"}, - - /* Left HP Output */ - {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, - {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, - {"Left HP Mixer", "DACL1 Switch", "Left DAC Mux"}, - {"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, - {"Left HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, - {"Left HP Mixer", "DACR1 Switch", "Right DAC Mux"}, - - {"Left HP Out", NULL, "Left HP Mixer"}, - {"Left HP Out", NULL, "Left DAC Mux"}, - {"HPLOUT", NULL, "Left HP Out"}, - - /* Right HP Output */ - {"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, - {"Right HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, - {"Right HP Mixer", "DACL1 Switch", "Left DAC Mux"}, - {"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, - {"Right HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, - {"Right HP Mixer", "DACR1 Switch", "Right DAC Mux"}, - - {"Right HP Out", NULL, "Right HP Mixer"}, - {"Right HP Out", NULL, "Right DAC Mux"}, - {"HPROUT", NULL, "Right HP Out"}, - - /* Left HPCOM Output */ - {"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, - {"Left HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, - {"Left HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"}, - {"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, - {"Left HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, - {"Left HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"}, - - {"Left HPCOM Mux", "differential of HPLOUT", "Left HP Mixer"}, - {"Left HPCOM Mux", "constant VCM", "Left HPCOM Mixer"}, - {"Left HPCOM Mux", "single-ended", "Left HPCOM Mixer"}, - {"Left HP Com", NULL, "Left HPCOM Mux"}, - {"HPLCOM", NULL, "Left HP Com"}, - - /* Right HPCOM Output */ - {"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"}, - {"Right HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"}, - {"Right HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"}, - {"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"}, - {"Right HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"}, - {"Right HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"}, - - {"Right HPCOM Mux", "differential of HPROUT", "Right HP Mixer"}, - {"Right HPCOM Mux", "constant VCM", "Right HPCOM Mixer"}, - {"Right HPCOM Mux", "single-ended", "Right HPCOM Mixer"}, - {"Right HPCOM Mux", "differential of HPLCOM", "Left HPCOM Mixer"}, - {"Right HPCOM Mux", "external feedback", "Right HPCOM Mixer"}, - {"Right HP Com", NULL, "Right HPCOM Mux"}, - {"HPRCOM", NULL, "Right HP Com"}, -}; - -static const struct snd_soc_dapm_route intercon_3007[] = { - /* Class-D outputs */ - {"Left Class-D Out", NULL, "Left Line Out"}, - {"Right Class-D Out", NULL, "Left Line Out"}, - {"SPOP", NULL, "Left Class-D Out"}, - {"SPOM", NULL, "Right Class-D Out"}, -}; - -static int aic3x_add_widgets(struct snd_soc_codec *codec) -{ - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, - ARRAY_SIZE(aic3x_dapm_widgets)); - - /* set up audio path interconnects */ - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - if (aic3x->model == AIC3X_MODEL_3007) { - snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets, - ARRAY_SIZE(aic3007_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, intercon_3007, - ARRAY_SIZE(intercon_3007)); - } - - return 0; -} - -static int aic3x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec =rtd->codec; - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; - u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; - u16 d, pll_d = 1; - int clk; - - /* select data word length */ - data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - data |= (0x01 << 4); - break; - case SNDRV_PCM_FORMAT_S24_LE: - data |= (0x02 << 4); - break; - case SNDRV_PCM_FORMAT_S32_LE: - data |= (0x03 << 4); - break; - } - snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, data); - - /* Fsref can be 44100 or 48000 */ - fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000; - - /* Try to find a value for Q which allows us to bypass the PLL and - * generate CODEC_CLK directly. */ - for (pll_q = 2; pll_q < 18; pll_q++) - if (aic3x->sysclk / (128 * pll_q) == fsref) { - bypass_pll = 1; - break; - } - - if (bypass_pll) { - pll_q &= 0xf; - snd_soc_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT); - snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV); - /* disable PLL if it is bypassed */ - snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, PLL_ENABLE, 0); - - } else { - snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV); - /* enable PLL when it is used */ - snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, - PLL_ENABLE, PLL_ENABLE); - } - - /* Route Left DAC to left channel input and - * right DAC to right channel input */ - data = (LDAC2LCH | RDAC2RCH); - data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000; - if (params_rate(params) >= 64000) - data |= DUAL_RATE_MODE; - snd_soc_write(codec, AIC3X_CODEC_DATAPATH_REG, data); - - /* codec sample rate select */ - data = (fsref * 20) / params_rate(params); - if (params_rate(params) < 64000) - data /= 2; - data /= 5; - data -= 2; - data |= (data << 4); - snd_soc_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data); - - if (bypass_pll) - return 0; - - /* Use PLL, compute appropriate setup for j, d, r and p, the closest - * one wins the game. Try with d==0 first, next with d!=0. - * Constraints for j are according to the datasheet. - * The sysclk is divided by 1000 to prevent integer overflows. - */ - - codec_clk = (2048 * fsref) / (aic3x->sysclk / 1000); - - for (r = 1; r <= 16; r++) - for (p = 1; p <= 8; p++) { - for (j = 4; j <= 55; j++) { - /* This is actually 1000*((j+(d/10000))*r)/p - * The term had to be converted to get - * rid of the division by 10000; d = 0 here - */ - int tmp_clk = (1000 * j * r) / p; - - /* Check whether this values get closer than - * the best ones we had before - */ - if (abs(codec_clk - tmp_clk) < - abs(codec_clk - last_clk)) { - pll_j = j; pll_d = 0; - pll_r = r; pll_p = p; - last_clk = tmp_clk; - } - - /* Early exit for exact matches */ - if (tmp_clk == codec_clk) - goto found; - } - } - - /* try with d != 0 */ - for (p = 1; p <= 8; p++) { - j = codec_clk * p / 1000; - - if (j < 4 || j > 11) - continue; - - /* do not use codec_clk here since we'd loose precision */ - d = ((2048 * p * fsref) - j * aic3x->sysclk) - * 100 / (aic3x->sysclk/100); - - clk = (10000 * j + d) / (10 * p); - - /* check whether this values get closer than the best - * ones we had before */ - if (abs(codec_clk - clk) < abs(codec_clk - last_clk)) { - pll_j = j; pll_d = d; pll_r = 1; pll_p = p; - last_clk = clk; - } - - /* Early exit for exact matches */ - if (clk == codec_clk) - goto found; - } - - if (last_clk == 0) { - printk(KERN_ERR "%s(): unable to setup PLL\n", __func__); - return -EINVAL; - } - -found: - snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, PLLP_MASK, pll_p); - snd_soc_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG, - pll_r << PLLR_SHIFT); - snd_soc_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT); - snd_soc_write(codec, AIC3X_PLL_PROGC_REG, - (pll_d >> 6) << PLLD_MSB_SHIFT); - snd_soc_write(codec, AIC3X_PLL_PROGD_REG, - (pll_d & 0x3F) << PLLD_LSB_SHIFT); - - return 0; -} - -static int aic3x_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u8 ldac_reg = snd_soc_read(codec, LDAC_VOL) & ~MUTE_ON; - u8 rdac_reg = snd_soc_read(codec, RDAC_VOL) & ~MUTE_ON; - - if (mute) { - snd_soc_write(codec, LDAC_VOL, ldac_reg | MUTE_ON); - snd_soc_write(codec, RDAC_VOL, rdac_reg | MUTE_ON); - } else { - snd_soc_write(codec, LDAC_VOL, ldac_reg); - snd_soc_write(codec, RDAC_VOL, rdac_reg); - } - - return 0; -} - -static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - - aic3x->sysclk = freq; - return 0; -} - -static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - u8 iface_areg, iface_breg; - int delay = 0; - - iface_areg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f; - iface_breg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - aic3x->master = 1; - iface_areg |= BIT_CLK_MASTER | WORD_CLK_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: - aic3x->master = 0; - iface_areg &= ~(BIT_CLK_MASTER | WORD_CLK_MASTER); - break; - default: - return -EINVAL; - } - - /* - * match both interface format and signal polarities since they - * are fixed - */ - switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | - SND_SOC_DAIFMT_INV_MASK)) { - case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): - break; - case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF): - delay = 1; - case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): - iface_breg |= (0x01 << 6); - break; - case (SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF): - iface_breg |= (0x02 << 6); - break; - case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF): - iface_breg |= (0x03 << 6); - break; - default: - return -EINVAL; - } - - /* set iface */ - snd_soc_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg); - snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg); - snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, delay); - - return 0; -} - -static int aic3x_init_3007(struct snd_soc_codec *codec) -{ - u8 tmp1, tmp2, *cache = codec->reg_cache; - - /* - * There is no need to cache writes to undocumented page 0xD but - * respective page 0 register cache entries must be preserved - */ - tmp1 = cache[0xD]; - tmp2 = cache[0x8]; - /* Class-D speaker driver init; datasheet p. 46 */ - snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D); - snd_soc_write(codec, 0xD, 0x0D); - snd_soc_write(codec, 0x8, 0x5C); - snd_soc_write(codec, 0x8, 0x5D); - snd_soc_write(codec, 0x8, 0x5C); - snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00); - cache[0xD] = tmp1; - cache[0x8] = tmp2; - - return 0; -} - -static int aic3x_regulator_event(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct aic3x_disable_nb *disable_nb = - container_of(nb, struct aic3x_disable_nb, nb); - struct aic3x_priv *aic3x = disable_nb->aic3x; - - if (event & REGULATOR_EVENT_DISABLE) { - /* - * Put codec to reset and require cache sync as at least one - * of the supplies was disabled - */ - if (gpio_is_valid(aic3x->gpio_reset)) - gpio_set_value(aic3x->gpio_reset, 0); - aic3x->codec->cache_sync = 1; - } - - return 0; -} - -static int aic3x_set_power(struct snd_soc_codec *codec, int power) -{ - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - int i, ret; - u8 *cache = codec->reg_cache; - - if (power) { - ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), - aic3x->supplies); - if (ret) - goto out; - aic3x->power = 1; - /* - * Reset release and cache sync is necessary only if some - * supply was off or if there were cached writes - */ - if (!codec->cache_sync) - goto out; - - if (gpio_is_valid(aic3x->gpio_reset)) { - udelay(1); - gpio_set_value(aic3x->gpio_reset, 1); - } - - /* Sync reg_cache with the hardware */ - codec->cache_only = 0; - for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++) - snd_soc_write(codec, i, cache[i]); - if (aic3x->model == AIC3X_MODEL_3007) - aic3x_init_3007(codec); - codec->cache_sync = 0; - } else { - /* - * Do soft reset to this codec instance in order to clear - * possible VDD leakage currents in case the supply regulators - * remain on - */ - snd_soc_write(codec, AIC3X_RESET, SOFT_RESET); - codec->cache_sync = 1; - aic3x->power = 0; - /* HW writes are needless when bias is off */ - codec->cache_only = 1; - ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), - aic3x->supplies); - } -out: - return ret; -} - -static int aic3x_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY && - aic3x->master) { - /* enable pll */ - snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, - PLL_ENABLE, PLL_ENABLE); - } - break; - case SND_SOC_BIAS_STANDBY: - if (!aic3x->power) - aic3x_set_power(codec, 1); - if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE && - aic3x->master) { - /* disable pll */ - snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, - PLL_ENABLE, 0); - } - break; - case SND_SOC_BIAS_OFF: - if (aic3x->power) - aic3x_set_power(codec, 0); - break; - } - codec->dapm.bias_level = level; - - return 0; -} - -void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect, - int headset_debounce, int button_debounce) -{ - u8 val; - - val = ((detect & AIC3X_HEADSET_DETECT_MASK) - << AIC3X_HEADSET_DETECT_SHIFT) | - ((headset_debounce & AIC3X_HEADSET_DEBOUNCE_MASK) - << AIC3X_HEADSET_DEBOUNCE_SHIFT) | - ((button_debounce & AIC3X_BUTTON_DEBOUNCE_MASK) - << AIC3X_BUTTON_DEBOUNCE_SHIFT); - - if (detect & AIC3X_HEADSET_DETECT_MASK) - val |= AIC3X_HEADSET_DETECT_ENABLED; - - snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val); -} - -#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 -#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops aic3x_dai_ops = { - .hw_params = aic3x_hw_params, - .digital_mute = aic3x_mute, - .set_sysclk = aic3x_set_dai_sysclk, - .set_fmt = aic3x_set_dai_fmt, -}; - -static struct snd_soc_dai_driver aic3x_dai = { - .name = "tlv320aic3x-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = AIC3X_RATES, - .formats = AIC3X_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = AIC3X_RATES, - .formats = AIC3X_FORMATS,}, - .ops = &aic3x_dai_ops, - .symmetric_rates = 1, -}; - -static int aic3x_suspend(struct snd_soc_codec *codec) -{ - aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int aic3x_resume(struct snd_soc_codec *codec) -{ - aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -/* - * initialise the AIC3X driver - * register the mixer and dsp interfaces with the kernel - */ -static int aic3x_init(struct snd_soc_codec *codec) -{ - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - - snd_soc_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); - snd_soc_write(codec, AIC3X_RESET, SOFT_RESET); - - /* DAC default volume and mute */ - snd_soc_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON); - snd_soc_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON); - - /* DAC to HP default volume and route to Output mixer */ - snd_soc_write(codec, DACL1_2_HPLOUT_VOL, DEFAULT_VOL | ROUTE_ON); - snd_soc_write(codec, DACR1_2_HPROUT_VOL, DEFAULT_VOL | ROUTE_ON); - snd_soc_write(codec, DACL1_2_HPLCOM_VOL, DEFAULT_VOL | ROUTE_ON); - snd_soc_write(codec, DACR1_2_HPRCOM_VOL, DEFAULT_VOL | ROUTE_ON); - /* DAC to Line Out default volume and route to Output mixer */ - snd_soc_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON); - snd_soc_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON); - /* DAC to Mono Line Out default volume and route to Output mixer */ - snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); - snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); - - /* unmute all outputs */ - snd_soc_update_bits(codec, LLOPM_CTRL, UNMUTE, UNMUTE); - snd_soc_update_bits(codec, RLOPM_CTRL, UNMUTE, UNMUTE); - snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE); - snd_soc_update_bits(codec, HPLOUT_CTRL, UNMUTE, UNMUTE); - snd_soc_update_bits(codec, HPROUT_CTRL, UNMUTE, UNMUTE); - snd_soc_update_bits(codec, HPLCOM_CTRL, UNMUTE, UNMUTE); - snd_soc_update_bits(codec, HPRCOM_CTRL, UNMUTE, UNMUTE); - - /* ADC default volume and unmute */ - snd_soc_write(codec, LADC_VOL, DEFAULT_GAIN); - snd_soc_write(codec, RADC_VOL, DEFAULT_GAIN); - /* By default route Line1 to ADC PGA mixer */ - snd_soc_write(codec, LINE1L_2_LADC_CTRL, 0x0); - snd_soc_write(codec, LINE1R_2_RADC_CTRL, 0x0); - - /* PGA to HP Bypass default volume, disconnect from Output Mixer */ - snd_soc_write(codec, PGAL_2_HPLOUT_VOL, DEFAULT_VOL); - snd_soc_write(codec, PGAR_2_HPROUT_VOL, DEFAULT_VOL); - snd_soc_write(codec, PGAL_2_HPLCOM_VOL, DEFAULT_VOL); - snd_soc_write(codec, PGAR_2_HPRCOM_VOL, DEFAULT_VOL); - /* PGA to Line Out default volume, disconnect from Output Mixer */ - snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL); - snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL); - /* PGA to Mono Line Out default volume, disconnect from Output Mixer */ - snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL); - snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL); - - /* Line2 to HP Bypass default volume, disconnect from Output Mixer */ - snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL); - snd_soc_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL); - snd_soc_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL); - snd_soc_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL); - /* Line2 Line Out default volume, disconnect from Output Mixer */ - snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL); - snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL); - /* Line2 to Mono Out default volume, disconnect from Output Mixer */ - snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL); - snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); - - if (aic3x->model == AIC3X_MODEL_3007) { - aic3x_init_3007(codec); - snd_soc_write(codec, CLASSD_CTRL, 0); - } - - return 0; -} - -static bool aic3x_is_shared_reset(struct aic3x_priv *aic3x) -{ - struct aic3x_priv *a; - - list_for_each_entry(a, &reset_list, list) { - if (gpio_is_valid(aic3x->gpio_reset) && - aic3x->gpio_reset == a->gpio_reset) - return true; - } - - return false; -} - -static int aic3x_probe(struct snd_soc_codec *codec) -{ - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - int ret, i; - - INIT_LIST_HEAD(&aic3x->list); - aic3x->codec = codec; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - if (gpio_is_valid(aic3x->gpio_reset) && - !aic3x_is_shared_reset(aic3x)) { - ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); - if (ret != 0) - goto err_gpio; - gpio_direction_output(aic3x->gpio_reset, 0); - } - - for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) - aic3x->supplies[i].supply = aic3x_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies), - aic3x->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err_get; - } - for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { - aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; - aic3x->disable_nb[i].aic3x = aic3x; - ret = regulator_register_notifier(aic3x->supplies[i].consumer, - &aic3x->disable_nb[i].nb); - if (ret) { - dev_err(codec->dev, - "Failed to request regulator notifier: %d\n", - ret); - goto err_notif; - } - } - - codec->cache_only = 1; - aic3x_init(codec); - - if (aic3x->setup) { - /* setup GPIO functions */ - snd_soc_write(codec, AIC3X_GPIO1_REG, - (aic3x->setup->gpio_func[0] & 0xf) << 4); - snd_soc_write(codec, AIC3X_GPIO2_REG, - (aic3x->setup->gpio_func[1] & 0xf) << 4); - } - - snd_soc_add_codec_controls(codec, aic3x_snd_controls, - ARRAY_SIZE(aic3x_snd_controls)); - if (aic3x->model == AIC3X_MODEL_3007) - snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); - - aic3x_add_widgets(codec); - list_add(&aic3x->list, &reset_list); - - return 0; - -err_notif: - while (i--) - regulator_unregister_notifier(aic3x->supplies[i].consumer, - &aic3x->disable_nb[i].nb); - regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); -err_get: - if (gpio_is_valid(aic3x->gpio_reset) && - !aic3x_is_shared_reset(aic3x)) - gpio_free(aic3x->gpio_reset); -err_gpio: - return ret; -} - -static int aic3x_remove(struct snd_soc_codec *codec) -{ - struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); - int i; - - aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); - list_del(&aic3x->list); - if (gpio_is_valid(aic3x->gpio_reset) && - !aic3x_is_shared_reset(aic3x)) { - gpio_set_value(aic3x->gpio_reset, 0); - gpio_free(aic3x->gpio_reset); - } - for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) - regulator_unregister_notifier(aic3x->supplies[i].consumer, - &aic3x->disable_nb[i].nb); - regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_aic3x = { - .set_bias_level = aic3x_set_bias_level, - .idle_bias_off = true, - .reg_cache_size = ARRAY_SIZE(aic3x_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = aic3x_reg, - .probe = aic3x_probe, - .remove = aic3x_remove, - .suspend = aic3x_suspend, - .resume = aic3x_resume, -}; - -/* - * AIC3X 2 wire address can be up to 4 devices with device addresses - * 0x18, 0x19, 0x1A, 0x1B - */ - -static const struct i2c_device_id aic3x_i2c_id[] = { - { "tlv320aic3x", AIC3X_MODEL_3X }, - { "tlv320aic33", AIC3X_MODEL_33 }, - { "tlv320aic3007", AIC3X_MODEL_3007 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); - -/* - * If the i2c layer weren't so broken, we could pass this kind of data - * around - */ -static int aic3x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct aic3x_pdata *pdata = i2c->dev.platform_data; - struct aic3x_priv *aic3x; - int ret; - - aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); - if (aic3x == NULL) { - dev_err(&i2c->dev, "failed to create private data\n"); - return -ENOMEM; - } - - aic3x->control_type = SND_SOC_I2C; - - i2c_set_clientdata(i2c, aic3x); - if (pdata) { - aic3x->gpio_reset = pdata->gpio_reset; - aic3x->setup = pdata->setup; - } else { - aic3x->gpio_reset = -1; - } - - aic3x->model = id->driver_data; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_aic3x, &aic3x_dai, 1); - return ret; -} - -static int aic3x_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -/* machine i2c codec control layer */ -static struct i2c_driver aic3x_i2c_driver = { - .driver = { - .name = "tlv320aic3x-codec", - .owner = THIS_MODULE, - }, - .probe = aic3x_i2c_probe, - .remove = aic3x_i2c_remove, - .id_table = aic3x_i2c_id, -}; - -static int __init aic3x_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&aic3x_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", - ret); - } - return ret; -} -module_init(aic3x_modinit); - -static void __exit aic3x_exit(void) -{ - i2c_del_driver(&aic3x_i2c_driver); -} -module_exit(aic3x_exit); - -MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); -MODULE_AUTHOR("Vladimir Barinov"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.h b/ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.h deleted file mode 100644 index 08c7f668..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320aic3x.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * ALSA SoC TLV320AIC3X codec driver - * - * Author: Vladimir Barinov, - * Copyright: (C) 2007 MontaVista Software, Inc., - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _AIC3X_H -#define _AIC3X_H - -/* AIC3X register space */ -#define AIC3X_CACHEREGNUM 103 - -/* Page select register */ -#define AIC3X_PAGE_SELECT 0 -/* Software reset register */ -#define AIC3X_RESET 1 -/* Codec Sample rate select register */ -#define AIC3X_SAMPLE_RATE_SEL_REG 2 -/* PLL progrramming register A */ -#define AIC3X_PLL_PROGA_REG 3 -/* PLL progrramming register B */ -#define AIC3X_PLL_PROGB_REG 4 -/* PLL progrramming register C */ -#define AIC3X_PLL_PROGC_REG 5 -/* PLL progrramming register D */ -#define AIC3X_PLL_PROGD_REG 6 -/* Codec datapath setup register */ -#define AIC3X_CODEC_DATAPATH_REG 7 -/* Audio serial data interface control register A */ -#define AIC3X_ASD_INTF_CTRLA 8 -/* Audio serial data interface control register B */ -#define AIC3X_ASD_INTF_CTRLB 9 -/* Audio serial data interface control register C */ -#define AIC3X_ASD_INTF_CTRLC 10 -/* Audio overflow status and PLL R value programming register */ -#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11 -/* Audio codec digital filter control register */ -#define AIC3X_CODEC_DFILT_CTRL 12 -/* Headset/button press detection register */ -#define AIC3X_HEADSET_DETECT_CTRL_A 13 -#define AIC3X_HEADSET_DETECT_CTRL_B 14 -/* ADC PGA Gain control registers */ -#define LADC_VOL 15 -#define RADC_VOL 16 -/* MIC3 control registers */ -#define MIC3LR_2_LADC_CTRL 17 -#define MIC3LR_2_RADC_CTRL 18 -/* Line1 Input control registers */ -#define LINE1L_2_LADC_CTRL 19 -#define LINE1R_2_LADC_CTRL 21 -#define LINE1R_2_RADC_CTRL 22 -#define LINE1L_2_RADC_CTRL 24 -/* Line2 Input control registers */ -#define LINE2L_2_LADC_CTRL 20 -#define LINE2R_2_RADC_CTRL 23 -/* MICBIAS Control Register */ -#define MICBIAS_CTRL 25 - -/* AGC Control Registers A, B, C */ -#define LAGC_CTRL_A 26 -#define LAGC_CTRL_B 27 -#define LAGC_CTRL_C 28 -#define RAGC_CTRL_A 29 -#define RAGC_CTRL_B 30 -#define RAGC_CTRL_C 31 - -/* DAC Power and Left High Power Output control registers */ -#define DAC_PWR 37 -#define HPLCOM_CFG 37 -/* Right High Power Output control registers */ -#define HPRCOM_CFG 38 -/* DAC Output Switching control registers */ -#define DAC_LINE_MUX 41 -/* High Power Output Driver Pop Reduction registers */ -#define HPOUT_POP_REDUCTION 42 -/* DAC Digital control registers */ -#define LDAC_VOL 43 -#define RDAC_VOL 44 -/* Left High Power Output control registers */ -#define LINE2L_2_HPLOUT_VOL 45 -#define PGAL_2_HPLOUT_VOL 46 -#define DACL1_2_HPLOUT_VOL 47 -#define LINE2R_2_HPLOUT_VOL 48 -#define PGAR_2_HPLOUT_VOL 49 -#define DACR1_2_HPLOUT_VOL 50 -#define HPLOUT_CTRL 51 -/* Left High Power COM control registers */ -#define LINE2L_2_HPLCOM_VOL 52 -#define PGAL_2_HPLCOM_VOL 53 -#define DACL1_2_HPLCOM_VOL 54 -#define LINE2R_2_HPLCOM_VOL 55 -#define PGAR_2_HPLCOM_VOL 56 -#define DACR1_2_HPLCOM_VOL 57 -#define HPLCOM_CTRL 58 -/* Right High Power Output control registers */ -#define LINE2L_2_HPROUT_VOL 59 -#define PGAL_2_HPROUT_VOL 60 -#define DACL1_2_HPROUT_VOL 61 -#define LINE2R_2_HPROUT_VOL 62 -#define PGAR_2_HPROUT_VOL 63 -#define DACR1_2_HPROUT_VOL 64 -#define HPROUT_CTRL 65 -/* Right High Power COM control registers */ -#define LINE2L_2_HPRCOM_VOL 66 -#define PGAL_2_HPRCOM_VOL 67 -#define DACL1_2_HPRCOM_VOL 68 -#define LINE2R_2_HPRCOM_VOL 69 -#define PGAR_2_HPRCOM_VOL 70 -#define DACR1_2_HPRCOM_VOL 71 -#define HPRCOM_CTRL 72 -/* Mono Line Output Plus/Minus control registers */ -#define LINE2L_2_MONOLOPM_VOL 73 -#define PGAL_2_MONOLOPM_VOL 74 -#define DACL1_2_MONOLOPM_VOL 75 -#define LINE2R_2_MONOLOPM_VOL 76 -#define PGAR_2_MONOLOPM_VOL 77 -#define DACR1_2_MONOLOPM_VOL 78 -#define MONOLOPM_CTRL 79 -/* Class-D speaker driver on tlv320aic3007 */ -#define CLASSD_CTRL 73 -/* Left Line Output Plus/Minus control registers */ -#define LINE2L_2_LLOPM_VOL 80 -#define PGAL_2_LLOPM_VOL 81 -#define DACL1_2_LLOPM_VOL 82 -#define LINE2R_2_LLOPM_VOL 83 -#define PGAR_2_LLOPM_VOL 84 -#define DACR1_2_LLOPM_VOL 85 -#define LLOPM_CTRL 86 -/* Right Line Output Plus/Minus control registers */ -#define LINE2L_2_RLOPM_VOL 87 -#define PGAL_2_RLOPM_VOL 88 -#define DACL1_2_RLOPM_VOL 89 -#define LINE2R_2_RLOPM_VOL 90 -#define PGAR_2_RLOPM_VOL 91 -#define DACR1_2_RLOPM_VOL 92 -#define RLOPM_CTRL 93 -/* GPIO/IRQ registers */ -#define AIC3X_STICKY_IRQ_FLAGS_REG 96 -#define AIC3X_RT_IRQ_FLAGS_REG 97 -#define AIC3X_GPIO1_REG 98 -#define AIC3X_GPIO2_REG 99 -#define AIC3X_GPIOA_REG 100 -#define AIC3X_GPIOB_REG 101 -/* Clock generation control register */ -#define AIC3X_CLKGEN_CTRL_REG 102 - -/* Page select register bits */ -#define PAGE0_SELECT 0 -#define PAGE1_SELECT 1 - -/* Audio serial data interface control register A bits */ -#define BIT_CLK_MASTER 0x80 -#define WORD_CLK_MASTER 0x40 - -/* Codec Datapath setup register 7 */ -#define FSREF_44100 (1 << 7) -#define FSREF_48000 (0 << 7) -#define DUAL_RATE_MODE ((1 << 5) | (1 << 6)) -#define LDAC2LCH (0x1 << 3) -#define RDAC2RCH (0x1 << 1) - -/* PLL registers bitfields */ -#define PLLP_SHIFT 0 -#define PLLP_MASK 7 -#define PLLQ_SHIFT 3 -#define PLLR_SHIFT 0 -#define PLLJ_SHIFT 2 -#define PLLD_MSB_SHIFT 0 -#define PLLD_LSB_SHIFT 2 - -/* Clock generation register bits */ -#define CODEC_CLKIN_PLLDIV 0 -#define CODEC_CLKIN_CLKDIV 1 -#define PLL_CLKIN_SHIFT 4 -#define MCLK_SOURCE 0x0 -#define PLL_CLKDIV_SHIFT 0 - -/* Software reset register bits */ -#define SOFT_RESET 0x80 - -/* PLL progrramming register A bits */ -#define PLL_ENABLE 0x80 - -/* Route bits */ -#define ROUTE_ON 0x80 - -/* Mute bits */ -#define UNMUTE 0x08 -#define MUTE_ON 0x80 - -/* Power bits */ -#define LADC_PWR_ON 0x04 -#define RADC_PWR_ON 0x04 -#define LDAC_PWR_ON 0x80 -#define RDAC_PWR_ON 0x40 -#define HPLOUT_PWR_ON 0x01 -#define HPROUT_PWR_ON 0x01 -#define HPLCOM_PWR_ON 0x01 -#define HPRCOM_PWR_ON 0x01 -#define MONOLOPM_PWR_ON 0x01 -#define LLOPM_PWR_ON 0x01 -#define RLOPM_PWR_ON 0x01 - -#define INVERT_VOL(val) (0x7f - val) - -/* Default output volume (inverted) */ -#define DEFAULT_VOL INVERT_VOL(0x50) -/* Default input volume */ -#define DEFAULT_GAIN 0x20 - -/* headset detection / button API */ - -/* The AIC3x supports detection of stereo headsets (GND + left + right signal) - * and cellular headsets (GND + speaker output + microphone input). - * It is recommended to enable MIC bias for this function to work properly. - * For more information, please refer to the datasheet. */ -enum { - AIC3X_HEADSET_DETECT_OFF = 0, - AIC3X_HEADSET_DETECT_STEREO = 1, - AIC3X_HEADSET_DETECT_CELLULAR = 2, - AIC3X_HEADSET_DETECT_BOTH = 3 -}; - -enum { - AIC3X_HEADSET_DEBOUNCE_16MS = 0, - AIC3X_HEADSET_DEBOUNCE_32MS = 1, - AIC3X_HEADSET_DEBOUNCE_64MS = 2, - AIC3X_HEADSET_DEBOUNCE_128MS = 3, - AIC3X_HEADSET_DEBOUNCE_256MS = 4, - AIC3X_HEADSET_DEBOUNCE_512MS = 5 -}; - -enum { - AIC3X_BUTTON_DEBOUNCE_0MS = 0, - AIC3X_BUTTON_DEBOUNCE_8MS = 1, - AIC3X_BUTTON_DEBOUNCE_16MS = 2, - AIC3X_BUTTON_DEBOUNCE_32MS = 3 -}; - -#define AIC3X_HEADSET_DETECT_ENABLED 0x80 -#define AIC3X_HEADSET_DETECT_SHIFT 5 -#define AIC3X_HEADSET_DETECT_MASK 3 -#define AIC3X_HEADSET_DEBOUNCE_SHIFT 2 -#define AIC3X_HEADSET_DEBOUNCE_MASK 7 -#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0 -#define AIC3X_BUTTON_DEBOUNCE_MASK 3 - -#endif /* _AIC3X_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.c b/ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.c deleted file mode 100644 index 4587ddd0..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.c +++ /dev/null @@ -1,1650 +0,0 @@ -/* - * ALSA SoC Texas Instruments TLV320DAC33 codec driver - * - * Author: Peter Ujfalusi - * - * Copyright: (C) 2009 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "tlv320dac33.h" - -/* - * The internal FIFO is 24576 bytes long - * It can be configured to hold 16bit or 24bit samples - * In 16bit configuration the FIFO can hold 6144 stereo samples - * In 24bit configuration the FIFO can hold 4096 stereo samples - */ -#define DAC33_FIFO_SIZE_16BIT 6144 -#define DAC33_FIFO_SIZE_24BIT 4096 -#define DAC33_MODE7_MARGIN 10 /* Safety margin for FIFO in Mode7 */ - -#define BURST_BASEFREQ_HZ 49152000 - -#define SAMPLES_TO_US(rate, samples) \ - (1000000000 / (((rate) * 1000) / (samples))) - -#define US_TO_SAMPLES(rate, us) \ - ((rate) / (1000000 / ((us) < 1000000 ? (us) : 1000000))) - -#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \ - (((samples)*5000) / (((burstrate)*5000) / ((burstrate) - (playrate)))) - -static void dac33_calculate_times(struct snd_pcm_substream *substream); -static int dac33_prepare_chip(struct snd_pcm_substream *substream); - -enum dac33_state { - DAC33_IDLE = 0, - DAC33_PREFILL, - DAC33_PLAYBACK, - DAC33_FLUSH, -}; - -enum dac33_fifo_modes { - DAC33_FIFO_BYPASS = 0, - DAC33_FIFO_MODE1, - DAC33_FIFO_MODE7, - DAC33_FIFO_LAST_MODE, -}; - -#define DAC33_NUM_SUPPLIES 3 -static const char *dac33_supply_names[DAC33_NUM_SUPPLIES] = { - "AVDD", - "DVDD", - "IOVDD", -}; - -struct tlv320dac33_priv { - struct mutex mutex; - struct workqueue_struct *dac33_wq; - struct work_struct work; - struct snd_soc_codec *codec; - struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; - struct snd_pcm_substream *substream; - int power_gpio; - int chip_power; - int irq; - unsigned int refclk; - - unsigned int alarm_threshold; /* set to be half of LATENCY_TIME_MS */ - enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ - unsigned int fifo_size; /* Size of the FIFO in samples */ - unsigned int nsample; /* burst read amount from host */ - int mode1_latency; /* latency caused by the i2c writes in - * us */ - u8 burst_bclkdiv; /* BCLK divider value in burst mode */ - unsigned int burst_rate; /* Interface speed in Burst modes */ - - int keep_bclk; /* Keep the BCLK continuously running - * in FIFO modes */ - spinlock_t lock; - unsigned long long t_stamp1; /* Time stamp for FIFO modes to */ - unsigned long long t_stamp2; /* calculate the FIFO caused delay */ - - unsigned int mode1_us_burst; /* Time to burst read n number of - * samples */ - unsigned int mode7_us_to_lthr; /* Time to reach lthr from uthr */ - - unsigned int uthr; - - enum dac33_state state; - enum snd_soc_control_type control_type; - void *control_data; -}; - -static const u8 dac33_reg[DAC33_CACHEREGNUM] = { -0x00, 0x00, 0x00, 0x00, /* 0x00 - 0x03 */ -0x00, 0x00, 0x00, 0x00, /* 0x04 - 0x07 */ -0x00, 0x00, 0x00, 0x00, /* 0x08 - 0x0b */ -0x00, 0x00, 0x00, 0x00, /* 0x0c - 0x0f */ -0x00, 0x00, 0x00, 0x00, /* 0x10 - 0x13 */ -0x00, 0x00, 0x00, 0x00, /* 0x14 - 0x17 */ -0x00, 0x00, 0x00, 0x00, /* 0x18 - 0x1b */ -0x00, 0x00, 0x00, 0x00, /* 0x1c - 0x1f */ -0x00, 0x00, 0x00, 0x00, /* 0x20 - 0x23 */ -0x00, 0x00, 0x00, 0x00, /* 0x24 - 0x27 */ -0x00, 0x00, 0x00, 0x00, /* 0x28 - 0x2b */ -0x00, 0x00, 0x00, 0x80, /* 0x2c - 0x2f */ -0x80, 0x00, 0x00, 0x00, /* 0x30 - 0x33 */ -0x00, 0x00, 0x00, 0x00, /* 0x34 - 0x37 */ -0x00, 0x00, /* 0x38 - 0x39 */ -/* Registers 0x3a - 0x3f are reserved */ - 0x00, 0x00, /* 0x3a - 0x3b */ -0x00, 0x00, 0x00, 0x00, /* 0x3c - 0x3f */ - -0x00, 0x00, 0x00, 0x00, /* 0x40 - 0x43 */ -0x00, 0x80, /* 0x44 - 0x45 */ -/* Registers 0x46 - 0x47 are reserved */ - 0x80, 0x80, /* 0x46 - 0x47 */ - -0x80, 0x00, 0x00, /* 0x48 - 0x4a */ -/* Registers 0x4b - 0x7c are reserved */ - 0x00, /* 0x4b */ -0x00, 0x00, 0x00, 0x00, /* 0x4c - 0x4f */ -0x00, 0x00, 0x00, 0x00, /* 0x50 - 0x53 */ -0x00, 0x00, 0x00, 0x00, /* 0x54 - 0x57 */ -0x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5b */ -0x00, 0x00, 0x00, 0x00, /* 0x5c - 0x5f */ -0x00, 0x00, 0x00, 0x00, /* 0x60 - 0x63 */ -0x00, 0x00, 0x00, 0x00, /* 0x64 - 0x67 */ -0x00, 0x00, 0x00, 0x00, /* 0x68 - 0x6b */ -0x00, 0x00, 0x00, 0x00, /* 0x6c - 0x6f */ -0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x73 */ -0x00, 0x00, 0x00, 0x00, /* 0x74 - 0x77 */ -0x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7b */ -0x00, /* 0x7c */ - - 0xda, 0x33, 0x03, /* 0x7d - 0x7f */ -}; - -/* Register read and write */ -static inline unsigned int dac33_read_reg_cache(struct snd_soc_codec *codec, - unsigned reg) -{ - u8 *cache = codec->reg_cache; - if (reg >= DAC33_CACHEREGNUM) - return 0; - - return cache[reg]; -} - -static inline void dac33_write_reg_cache(struct snd_soc_codec *codec, - u8 reg, u8 value) -{ - u8 *cache = codec->reg_cache; - if (reg >= DAC33_CACHEREGNUM) - return; - - cache[reg] = value; -} - -static int dac33_read(struct snd_soc_codec *codec, unsigned int reg, - u8 *value) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - int val, ret = 0; - - *value = reg & 0xff; - - /* If powered off, return the cached value */ - if (dac33->chip_power) { - val = i2c_smbus_read_byte_data(codec->control_data, value[0]); - if (val < 0) { - dev_err(codec->dev, "Read failed (%d)\n", val); - value[0] = dac33_read_reg_cache(codec, reg); - ret = val; - } else { - value[0] = val; - dac33_write_reg_cache(codec, reg, val); - } - } else { - value[0] = dac33_read_reg_cache(codec, reg); - } - - return ret; -} - -static int dac33_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - u8 data[2]; - int ret = 0; - - /* - * data is - * D15..D8 dac33 register offset - * D7...D0 register data - */ - data[0] = reg & 0xff; - data[1] = value & 0xff; - - dac33_write_reg_cache(codec, data[0], data[1]); - if (dac33->chip_power) { - ret = codec->hw_write(codec->control_data, data, 2); - if (ret != 2) - dev_err(codec->dev, "Write failed (%d)\n", ret); - else - ret = 0; - } - - return ret; -} - -static int dac33_write_locked(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - int ret; - - mutex_lock(&dac33->mutex); - ret = dac33_write(codec, reg, value); - mutex_unlock(&dac33->mutex); - - return ret; -} - -#define DAC33_I2C_ADDR_AUTOINC 0x80 -static int dac33_write16(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - u8 data[3]; - int ret = 0; - - /* - * data is - * D23..D16 dac33 register offset - * D15..D8 register data MSB - * D7...D0 register data LSB - */ - data[0] = reg & 0xff; - data[1] = (value >> 8) & 0xff; - data[2] = value & 0xff; - - dac33_write_reg_cache(codec, data[0], data[1]); - dac33_write_reg_cache(codec, data[0] + 1, data[2]); - - if (dac33->chip_power) { - /* We need to set autoincrement mode for 16 bit writes */ - data[0] |= DAC33_I2C_ADDR_AUTOINC; - ret = codec->hw_write(codec->control_data, data, 3); - if (ret != 3) - dev_err(codec->dev, "Write failed (%d)\n", ret); - else - ret = 0; - } - - return ret; -} - -static void dac33_init_chip(struct snd_soc_codec *codec) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - - if (unlikely(!dac33->chip_power)) - return; - - /* A : DAC sample rate Fsref/1.5 */ - dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); - /* B : DAC src=normal, not muted */ - dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | - DAC33_DACSRCL_LEFT); - /* C : (defaults) */ - dac33_write(codec, DAC33_DAC_CTRL_C, 0x00); - - /* 73 : volume soft stepping control, - clock source = internal osc (?) */ - dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); - - /* Restore only selected registers (gains mostly) */ - dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL, - dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL)); - dac33_write(codec, DAC33_RDAC_DIG_VOL_CTRL, - dac33_read_reg_cache(codec, DAC33_RDAC_DIG_VOL_CTRL)); - - dac33_write(codec, DAC33_LINEL_TO_LLO_VOL, - dac33_read_reg_cache(codec, DAC33_LINEL_TO_LLO_VOL)); - dac33_write(codec, DAC33_LINER_TO_RLO_VOL, - dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL)); - - dac33_write(codec, DAC33_OUT_AMP_CTRL, - dac33_read_reg_cache(codec, DAC33_OUT_AMP_CTRL)); - - dac33_write(codec, DAC33_LDAC_PWR_CTRL, - dac33_read_reg_cache(codec, DAC33_LDAC_PWR_CTRL)); - dac33_write(codec, DAC33_RDAC_PWR_CTRL, - dac33_read_reg_cache(codec, DAC33_RDAC_PWR_CTRL)); -} - -static inline int dac33_read_id(struct snd_soc_codec *codec) -{ - int i, ret = 0; - u8 reg; - - for (i = 0; i < 3; i++) { - ret = dac33_read(codec, DAC33_DEVICE_ID_MSB + i, ®); - if (ret < 0) - break; - } - - return ret; -} - -static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) -{ - u8 reg; - - reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL); - if (power) - reg |= DAC33_PDNALLB; - else - reg &= ~(DAC33_PDNALLB | DAC33_OSCPDNB | - DAC33_DACRPDNB | DAC33_DACLPDNB); - dac33_write(codec, DAC33_PWR_CTRL, reg); -} - -static inline void dac33_disable_digital(struct snd_soc_codec *codec) -{ - u8 reg; - - /* Stop the DAI clock */ - reg = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B); - reg &= ~DAC33_BCLKON; - dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, reg); - - /* Power down the Oscillator, and DACs */ - reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL); - reg &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB); - dac33_write(codec, DAC33_PWR_CTRL, reg); -} - -static int dac33_hard_power(struct snd_soc_codec *codec, int power) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - mutex_lock(&dac33->mutex); - - /* Safety check */ - if (unlikely(power == dac33->chip_power)) { - dev_dbg(codec->dev, "Trying to set the same power state: %s\n", - power ? "ON" : "OFF"); - goto exit; - } - - if (power) { - ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), - dac33->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", ret); - goto exit; - } - - if (dac33->power_gpio >= 0) - gpio_set_value(dac33->power_gpio, 1); - - dac33->chip_power = 1; - } else { - dac33_soft_power(codec, 0); - if (dac33->power_gpio >= 0) - gpio_set_value(dac33->power_gpio, 0); - - ret = regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), - dac33->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to disable supplies: %d\n", ret); - goto exit; - } - - dac33->chip_power = 0; - } - -exit: - mutex_unlock(&dac33->mutex); - return ret; -} - -static int dac33_playback_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - if (likely(dac33->substream)) { - dac33_calculate_times(dac33->substream); - dac33_prepare_chip(dac33->substream); - } - break; - case SND_SOC_DAPM_POST_PMD: - dac33_disable_digital(w->codec); - break; - } - return 0; -} - -static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = dac33->fifo_mode; - - return 0; -} - -static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - if (dac33->fifo_mode == ucontrol->value.integer.value[0]) - return 0; - /* Do not allow changes while stream is running*/ - if (codec->active) - return -EPERM; - - if (ucontrol->value.integer.value[0] < 0 || - ucontrol->value.integer.value[0] >= DAC33_FIFO_LAST_MODE) - ret = -EINVAL; - else - dac33->fifo_mode = ucontrol->value.integer.value[0]; - - return ret; -} - -/* Codec operation modes */ -static const char *dac33_fifo_mode_texts[] = { - "Bypass", "Mode 1", "Mode 7" -}; - -static const struct soc_enum dac33_fifo_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts), - dac33_fifo_mode_texts); - -/* L/R Line Output Gain */ -static const char *lr_lineout_gain_texts[] = { - "Line -12dB DAC 0dB", "Line -6dB DAC 6dB", - "Line 0dB DAC 12dB", "Line 6dB DAC 18dB", -}; - -static const struct soc_enum l_lineout_gain_enum = - SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0, - ARRAY_SIZE(lr_lineout_gain_texts), - lr_lineout_gain_texts); - -static const struct soc_enum r_lineout_gain_enum = - SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0, - ARRAY_SIZE(lr_lineout_gain_texts), - lr_lineout_gain_texts); - -/* - * DACL/R digital volume control: - * from 0 dB to -63.5 in 0.5 dB steps - * Need to be inverted later on: - * 0x00 == 0 dB - * 0x7f == -63.5 dB - */ -static DECLARE_TLV_DB_SCALE(dac_digivol_tlv, -6350, 50, 0); - -static const struct snd_kcontrol_new dac33_snd_controls[] = { - SOC_DOUBLE_R_TLV("DAC Digital Playback Volume", - DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, - 0, 0x7f, 1, dac_digivol_tlv), - SOC_DOUBLE_R("DAC Digital Playback Switch", - DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1), - SOC_DOUBLE_R("Line to Line Out Volume", - DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), - SOC_ENUM("Left Line Output Gain", l_lineout_gain_enum), - SOC_ENUM("Right Line Output Gain", r_lineout_gain_enum), -}; - -static const struct snd_kcontrol_new dac33_mode_snd_controls[] = { - SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, - dac33_get_fifo_mode, dac33_set_fifo_mode), -}; - -/* Analog bypass */ -static const struct snd_kcontrol_new dac33_dapm_abypassl_control = - SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1); - -static const struct snd_kcontrol_new dac33_dapm_abypassr_control = - SOC_DAPM_SINGLE("Switch", DAC33_LINER_TO_RLO_VOL, 7, 1, 1); - -/* LOP L/R invert selection */ -static const char *dac33_lr_lom_texts[] = {"DAC", "LOP"}; - -static const struct soc_enum dac33_left_lom_enum = - SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 3, - ARRAY_SIZE(dac33_lr_lom_texts), - dac33_lr_lom_texts); - -static const struct snd_kcontrol_new dac33_dapm_left_lom_control = -SOC_DAPM_ENUM("Route", dac33_left_lom_enum); - -static const struct soc_enum dac33_right_lom_enum = - SOC_ENUM_SINGLE(DAC33_OUT_AMP_CTRL, 2, - ARRAY_SIZE(dac33_lr_lom_texts), - dac33_lr_lom_texts); - -static const struct snd_kcontrol_new dac33_dapm_right_lom_control = -SOC_DAPM_ENUM("Route", dac33_right_lom_enum); - -static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { - SND_SOC_DAPM_OUTPUT("LEFT_LO"), - SND_SOC_DAPM_OUTPUT("RIGHT_LO"), - - SND_SOC_DAPM_INPUT("LINEL"), - SND_SOC_DAPM_INPUT("LINER"), - - SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0), - - /* Analog bypass */ - SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0, - &dac33_dapm_abypassl_control), - SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0, - &dac33_dapm_abypassr_control), - - SND_SOC_DAPM_MUX("Left LOM Inverted From", SND_SOC_NOPM, 0, 0, - &dac33_dapm_left_lom_control), - SND_SOC_DAPM_MUX("Right LOM Inverted From", SND_SOC_NOPM, 0, 0, - &dac33_dapm_right_lom_control), - /* - * For DAPM path, when only the anlog bypass path is enabled, and the - * LOP inverted from the corresponding DAC side. - * This is needed, so we can attach the DAC power supply in this case. - */ - SND_SOC_DAPM_PGA("Left Bypass PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Bypass PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amplifier", - DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amplifier", - DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), - - SND_SOC_DAPM_SUPPLY("Left DAC Power", - DAC33_LDAC_PWR_CTRL, 2, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Right DAC Power", - DAC33_RDAC_PWR_CTRL, 2, 0, NULL, 0), - - SND_SOC_DAPM_SUPPLY("Codec Power", - DAC33_PWR_CTRL, 4, 0, NULL, 0), - - SND_SOC_DAPM_PRE("Pre Playback", dac33_playback_event), - SND_SOC_DAPM_POST("Post Playback", dac33_playback_event), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Analog bypass */ - {"Analog Left Bypass", "Switch", "LINEL"}, - {"Analog Right Bypass", "Switch", "LINER"}, - - {"Output Left Amplifier", NULL, "DACL"}, - {"Output Right Amplifier", NULL, "DACR"}, - - {"Left Bypass PGA", NULL, "Analog Left Bypass"}, - {"Right Bypass PGA", NULL, "Analog Right Bypass"}, - - {"Left LOM Inverted From", "DAC", "Left Bypass PGA"}, - {"Right LOM Inverted From", "DAC", "Right Bypass PGA"}, - {"Left LOM Inverted From", "LOP", "Analog Left Bypass"}, - {"Right LOM Inverted From", "LOP", "Analog Right Bypass"}, - - {"Output Left Amplifier", NULL, "Left LOM Inverted From"}, - {"Output Right Amplifier", NULL, "Right LOM Inverted From"}, - - {"DACL", NULL, "Left DAC Power"}, - {"DACR", NULL, "Right DAC Power"}, - - {"Left Bypass PGA", NULL, "Left DAC Power"}, - {"Right Bypass PGA", NULL, "Right DAC Power"}, - - /* output */ - {"LEFT_LO", NULL, "Output Left Amplifier"}, - {"RIGHT_LO", NULL, "Output Right Amplifier"}, - - {"LEFT_LO", NULL, "Codec Power"}, - {"RIGHT_LO", NULL, "Codec Power"}, -}; - -static int dac33_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - /* Coming from OFF, switch on the codec */ - ret = dac33_hard_power(codec, 1); - if (ret != 0) - return ret; - - dac33_init_chip(codec); - } - break; - case SND_SOC_BIAS_OFF: - /* Do not power off, when the codec is already off */ - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - return 0; - ret = dac33_hard_power(codec, 0); - if (ret != 0) - return ret; - break; - } - codec->dapm.bias_level = level; - - return 0; -} - -static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) -{ - struct snd_soc_codec *codec = dac33->codec; - unsigned int delay; - unsigned long flags; - - switch (dac33->fifo_mode) { - case DAC33_FIFO_MODE1: - dac33_write16(codec, DAC33_NSAMPLE_MSB, - DAC33_THRREG(dac33->nsample)); - - /* Take the timestamps */ - spin_lock_irqsave(&dac33->lock, flags); - dac33->t_stamp2 = ktime_to_us(ktime_get()); - dac33->t_stamp1 = dac33->t_stamp2; - spin_unlock_irqrestore(&dac33->lock, flags); - - dac33_write16(codec, DAC33_PREFILL_MSB, - DAC33_THRREG(dac33->alarm_threshold)); - /* Enable Alarm Threshold IRQ with a delay */ - delay = SAMPLES_TO_US(dac33->burst_rate, - dac33->alarm_threshold) + 1000; - usleep_range(delay, delay + 500); - dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT); - break; - case DAC33_FIFO_MODE7: - /* Take the timestamp */ - spin_lock_irqsave(&dac33->lock, flags); - dac33->t_stamp1 = ktime_to_us(ktime_get()); - /* Move back the timestamp with drain time */ - dac33->t_stamp1 -= dac33->mode7_us_to_lthr; - spin_unlock_irqrestore(&dac33->lock, flags); - - dac33_write16(codec, DAC33_PREFILL_MSB, - DAC33_THRREG(DAC33_MODE7_MARGIN)); - - /* Enable Upper Threshold IRQ */ - dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MUT); - break; - default: - dev_warn(codec->dev, "Unhandled FIFO mode: %d\n", - dac33->fifo_mode); - break; - } -} - -static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) -{ - struct snd_soc_codec *codec = dac33->codec; - unsigned long flags; - - switch (dac33->fifo_mode) { - case DAC33_FIFO_MODE1: - /* Take the timestamp */ - spin_lock_irqsave(&dac33->lock, flags); - dac33->t_stamp2 = ktime_to_us(ktime_get()); - spin_unlock_irqrestore(&dac33->lock, flags); - - dac33_write16(codec, DAC33_NSAMPLE_MSB, - DAC33_THRREG(dac33->nsample)); - break; - case DAC33_FIFO_MODE7: - /* At the moment we are not using interrupts in mode7 */ - break; - default: - dev_warn(codec->dev, "Unhandled FIFO mode: %d\n", - dac33->fifo_mode); - break; - } -} - -static void dac33_work(struct work_struct *work) -{ - struct snd_soc_codec *codec; - struct tlv320dac33_priv *dac33; - u8 reg; - - dac33 = container_of(work, struct tlv320dac33_priv, work); - codec = dac33->codec; - - mutex_lock(&dac33->mutex); - switch (dac33->state) { - case DAC33_PREFILL: - dac33->state = DAC33_PLAYBACK; - dac33_prefill_handler(dac33); - break; - case DAC33_PLAYBACK: - dac33_playback_handler(dac33); - break; - case DAC33_IDLE: - break; - case DAC33_FLUSH: - dac33->state = DAC33_IDLE; - /* Mask all interrupts from dac33 */ - dac33_write(codec, DAC33_FIFO_IRQ_MASK, 0); - - /* flush fifo */ - reg = dac33_read_reg_cache(codec, DAC33_FIFO_CTRL_A); - reg |= DAC33_FIFOFLUSH; - dac33_write(codec, DAC33_FIFO_CTRL_A, reg); - break; - } - mutex_unlock(&dac33->mutex); -} - -static irqreturn_t dac33_interrupt_handler(int irq, void *dev) -{ - struct snd_soc_codec *codec = dev; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - unsigned long flags; - - spin_lock_irqsave(&dac33->lock, flags); - dac33->t_stamp1 = ktime_to_us(ktime_get()); - spin_unlock_irqrestore(&dac33->lock, flags); - - /* Do not schedule the workqueue in Mode7 */ - if (dac33->fifo_mode != DAC33_FIFO_MODE7) - queue_work(dac33->dac33_wq, &dac33->work); - - return IRQ_HANDLED; -} - -static void dac33_oscwait(struct snd_soc_codec *codec) -{ - int timeout = 60; - u8 reg; - - do { - usleep_range(1000, 2000); - dac33_read(codec, DAC33_INT_OSC_STATUS, ®); - } while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--); - if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) - dev_err(codec->dev, - "internal oscillator calibration failed\n"); -} - -static int dac33_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - - /* Stream started, save the substream pointer */ - dac33->substream = substream; - - return 0; -} - -static void dac33_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - - dac33->substream = NULL; -} - -#define CALC_BURST_RATE(bclkdiv, bclk_per_sample) \ - (BURST_BASEFREQ_HZ / bclkdiv / bclk_per_sample) -static int dac33_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - - /* Check parameters for validity */ - switch (params_rate(params)) { - case 44100: - case 48000: - break; - default: - dev_err(codec->dev, "unsupported rate %d\n", - params_rate(params)); - return -EINVAL; - } - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - dac33->fifo_size = DAC33_FIFO_SIZE_16BIT; - dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 32); - break; - case SNDRV_PCM_FORMAT_S32_LE: - dac33->fifo_size = DAC33_FIFO_SIZE_24BIT; - dac33->burst_rate = CALC_BURST_RATE(dac33->burst_bclkdiv, 64); - break; - default: - dev_err(codec->dev, "unsupported format %d\n", - params_format(params)); - return -EINVAL; - } - - return 0; -} - -#define CALC_OSCSET(rate, refclk) ( \ - ((((rate * 10000) / refclk) * 4096) + 7000) / 10000) -#define CALC_RATIOSET(rate, refclk) ( \ - ((((refclk * 100000) / rate) * 16384) + 50000) / 100000) - -/* - * tlv320dac33 is strict on the sequence of the register writes, if the register - * writes happens in different order, than dac33 might end up in unknown state. - * Use the known, working sequence of register writes to initialize the dac33. - */ -static int dac33_prepare_chip(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; - u8 aictrl_a, aictrl_b, fifoctrl_a; - - switch (substream->runtime->rate) { - case 44100: - case 48000: - oscset = CALC_OSCSET(substream->runtime->rate, dac33->refclk); - ratioset = CALC_RATIOSET(substream->runtime->rate, - dac33->refclk); - break; - default: - dev_err(codec->dev, "unsupported rate %d\n", - substream->runtime->rate); - return -EINVAL; - } - - - aictrl_a = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A); - aictrl_a &= ~(DAC33_NCYCL_MASK | DAC33_WLEN_MASK); - /* Read FIFO control A, and clear FIFO flush bit */ - fifoctrl_a = dac33_read_reg_cache(codec, DAC33_FIFO_CTRL_A); - fifoctrl_a &= ~DAC33_FIFOFLUSH; - - fifoctrl_a &= ~DAC33_WIDTH; - switch (substream->runtime->format) { - case SNDRV_PCM_FORMAT_S16_LE: - aictrl_a |= (DAC33_NCYCL_16 | DAC33_WLEN_16); - fifoctrl_a |= DAC33_WIDTH; - break; - case SNDRV_PCM_FORMAT_S32_LE: - aictrl_a |= (DAC33_NCYCL_32 | DAC33_WLEN_24); - break; - default: - dev_err(codec->dev, "unsupported format %d\n", - substream->runtime->format); - return -EINVAL; - } - - mutex_lock(&dac33->mutex); - - if (!dac33->chip_power) { - /* - * Chip is not powered yet. - * Do the init in the dac33_set_bias_level later. - */ - mutex_unlock(&dac33->mutex); - return 0; - } - - dac33_soft_power(codec, 0); - dac33_soft_power(codec, 1); - - reg_tmp = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL); - dac33_write(codec, DAC33_INT_OSC_CTRL, reg_tmp); - - /* Write registers 0x08 and 0x09 (MSB, LSB) */ - dac33_write16(codec, DAC33_INT_OSC_FREQ_RAT_A, oscset); - - /* OSC calibration time */ - dac33_write(codec, DAC33_CALIB_TIME, 96); - - /* adjustment treshold & step */ - dac33_write(codec, DAC33_INT_OSC_CTRL_B, DAC33_ADJTHRSHLD(2) | - DAC33_ADJSTEP(1)); - - /* div=4 / gain=1 / div */ - dac33_write(codec, DAC33_INT_OSC_CTRL_C, DAC33_REFDIV(4)); - - pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL); - pwr_ctrl |= DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB; - dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl); - - dac33_oscwait(codec); - - if (dac33->fifo_mode) { - /* Generic for all FIFO modes */ - /* 50-51 : ASRC Control registers */ - dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCLKDIV(1)); - dac33_write(codec, DAC33_ASRC_CTRL_B, 1); /* ??? */ - - /* Write registers 0x34 and 0x35 (MSB, LSB) */ - dac33_write16(codec, DAC33_SRC_REF_CLK_RATIO_A, ratioset); - - /* Set interrupts to high active */ - dac33_write(codec, DAC33_INTP_CTRL_A, DAC33_INTPM_AHIGH); - } else { - /* FIFO bypass mode */ - /* 50-51 : ASRC Control registers */ - dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCBYP); - dac33_write(codec, DAC33_ASRC_CTRL_B, 0); /* ??? */ - } - - /* Interrupt behaviour configuration */ - switch (dac33->fifo_mode) { - case DAC33_FIFO_MODE1: - dac33_write(codec, DAC33_FIFO_IRQ_MODE_B, - DAC33_ATM(DAC33_FIFO_IRQ_MODE_LEVEL)); - break; - case DAC33_FIFO_MODE7: - dac33_write(codec, DAC33_FIFO_IRQ_MODE_A, - DAC33_UTM(DAC33_FIFO_IRQ_MODE_LEVEL)); - break; - default: - /* in FIFO bypass mode, the interrupts are not used */ - break; - } - - aictrl_b = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B); - - switch (dac33->fifo_mode) { - case DAC33_FIFO_MODE1: - /* - * For mode1: - * Disable the FIFO bypass (Enable the use of FIFO) - * Select nSample mode - * BCLK is only running when data is needed by DAC33 - */ - fifoctrl_a &= ~DAC33_FBYPAS; - fifoctrl_a &= ~DAC33_FAUTO; - if (dac33->keep_bclk) - aictrl_b |= DAC33_BCLKON; - else - aictrl_b &= ~DAC33_BCLKON; - break; - case DAC33_FIFO_MODE7: - /* - * For mode1: - * Disable the FIFO bypass (Enable the use of FIFO) - * Select Threshold mode - * BCLK is only running when data is needed by DAC33 - */ - fifoctrl_a &= ~DAC33_FBYPAS; - fifoctrl_a |= DAC33_FAUTO; - if (dac33->keep_bclk) - aictrl_b |= DAC33_BCLKON; - else - aictrl_b &= ~DAC33_BCLKON; - break; - default: - /* - * For FIFO bypass mode: - * Enable the FIFO bypass (Disable the FIFO use) - * Set the BCLK as continuous - */ - fifoctrl_a |= DAC33_FBYPAS; - aictrl_b |= DAC33_BCLKON; - break; - } - - dac33_write(codec, DAC33_FIFO_CTRL_A, fifoctrl_a); - dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_A, aictrl_a); - dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, aictrl_b); - - /* - * BCLK divide ratio - * 0: 1.5 - * 1: 1 - * 2: 2 - * ... - * 254: 254 - * 255: 255 - */ - if (dac33->fifo_mode) - dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, - dac33->burst_bclkdiv); - else - if (substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE) - dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 32); - else - dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 16); - - switch (dac33->fifo_mode) { - case DAC33_FIFO_MODE1: - dac33_write16(codec, DAC33_ATHR_MSB, - DAC33_THRREG(dac33->alarm_threshold)); - break; - case DAC33_FIFO_MODE7: - /* - * Configure the threshold levels, and leave 10 sample space - * at the bottom, and also at the top of the FIFO - */ - dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(dac33->uthr)); - dac33_write16(codec, DAC33_LTHR_MSB, - DAC33_THRREG(DAC33_MODE7_MARGIN)); - break; - default: - break; - } - - mutex_unlock(&dac33->mutex); - - return 0; -} - -static void dac33_calculate_times(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - unsigned int period_size = substream->runtime->period_size; - unsigned int rate = substream->runtime->rate; - unsigned int nsample_limit; - - /* In bypass mode we don't need to calculate */ - if (!dac33->fifo_mode) - return; - - switch (dac33->fifo_mode) { - case DAC33_FIFO_MODE1: - /* Number of samples under i2c latency */ - dac33->alarm_threshold = US_TO_SAMPLES(rate, - dac33->mode1_latency); - nsample_limit = dac33->fifo_size - dac33->alarm_threshold; - - if (period_size <= dac33->alarm_threshold) - /* - * Configure nSamaple to number of periods, - * which covers the latency requironment. - */ - dac33->nsample = period_size * - ((dac33->alarm_threshold / period_size) + - (dac33->alarm_threshold % period_size ? - 1 : 0)); - else if (period_size > nsample_limit) - dac33->nsample = nsample_limit; - else - dac33->nsample = period_size; - - dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, - dac33->nsample); - dac33->t_stamp1 = 0; - dac33->t_stamp2 = 0; - break; - case DAC33_FIFO_MODE7: - dac33->uthr = UTHR_FROM_PERIOD_SIZE(period_size, rate, - dac33->burst_rate) + 9; - if (dac33->uthr > (dac33->fifo_size - DAC33_MODE7_MARGIN)) - dac33->uthr = dac33->fifo_size - DAC33_MODE7_MARGIN; - if (dac33->uthr < (DAC33_MODE7_MARGIN + 10)) - dac33->uthr = (DAC33_MODE7_MARGIN + 10); - - dac33->mode7_us_to_lthr = - SAMPLES_TO_US(substream->runtime->rate, - dac33->uthr - DAC33_MODE7_MARGIN + 1); - dac33->t_stamp1 = 0; - break; - default: - break; - } - -} - -static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (dac33->fifo_mode) { - dac33->state = DAC33_PREFILL; - queue_work(dac33->dac33_wq, &dac33->work); - } - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (dac33->fifo_mode) { - dac33->state = DAC33_FLUSH; - queue_work(dac33->dac33_wq, &dac33->work); - } - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static snd_pcm_sframes_t dac33_dai_delay( - struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - unsigned long long t0, t1, t_now; - unsigned int time_delta, uthr; - int samples_out, samples_in, samples; - snd_pcm_sframes_t delay = 0; - unsigned long flags; - - switch (dac33->fifo_mode) { - case DAC33_FIFO_BYPASS: - break; - case DAC33_FIFO_MODE1: - spin_lock_irqsave(&dac33->lock, flags); - t0 = dac33->t_stamp1; - t1 = dac33->t_stamp2; - spin_unlock_irqrestore(&dac33->lock, flags); - t_now = ktime_to_us(ktime_get()); - - /* We have not started to fill the FIFO yet, delay is 0 */ - if (!t1) - goto out; - - if (t0 > t1) { - /* - * Phase 1: - * After Alarm threshold, and before nSample write - */ - time_delta = t_now - t0; - samples_out = time_delta ? US_TO_SAMPLES( - substream->runtime->rate, - time_delta) : 0; - - if (likely(dac33->alarm_threshold > samples_out)) - delay = dac33->alarm_threshold - samples_out; - else - delay = 0; - } else if ((t_now - t1) <= dac33->mode1_us_burst) { - /* - * Phase 2: - * After nSample write (during burst operation) - */ - time_delta = t_now - t0; - samples_out = time_delta ? US_TO_SAMPLES( - substream->runtime->rate, - time_delta) : 0; - - time_delta = t_now - t1; - samples_in = time_delta ? US_TO_SAMPLES( - dac33->burst_rate, - time_delta) : 0; - - samples = dac33->alarm_threshold; - samples += (samples_in - samples_out); - - if (likely(samples > 0)) - delay = samples; - else - delay = 0; - } else { - /* - * Phase 3: - * After burst operation, before next alarm threshold - */ - time_delta = t_now - t0; - samples_out = time_delta ? US_TO_SAMPLES( - substream->runtime->rate, - time_delta) : 0; - - samples_in = dac33->nsample; - samples = dac33->alarm_threshold; - samples += (samples_in - samples_out); - - if (likely(samples > 0)) - delay = samples > dac33->fifo_size ? - dac33->fifo_size : samples; - else - delay = 0; - } - break; - case DAC33_FIFO_MODE7: - spin_lock_irqsave(&dac33->lock, flags); - t0 = dac33->t_stamp1; - uthr = dac33->uthr; - spin_unlock_irqrestore(&dac33->lock, flags); - t_now = ktime_to_us(ktime_get()); - - /* We have not started to fill the FIFO yet, delay is 0 */ - if (!t0) - goto out; - - if (t_now <= t0) { - /* - * Either the timestamps are messed or equal. Report - * maximum delay - */ - delay = uthr; - goto out; - } - - time_delta = t_now - t0; - if (time_delta <= dac33->mode7_us_to_lthr) { - /* - * Phase 1: - * After burst (draining phase) - */ - samples_out = US_TO_SAMPLES( - substream->runtime->rate, - time_delta); - - if (likely(uthr > samples_out)) - delay = uthr - samples_out; - else - delay = 0; - } else { - /* - * Phase 2: - * During burst operation - */ - time_delta = time_delta - dac33->mode7_us_to_lthr; - - samples_out = US_TO_SAMPLES( - substream->runtime->rate, - time_delta); - samples_in = US_TO_SAMPLES( - dac33->burst_rate, - time_delta); - delay = DAC33_MODE7_MARGIN + samples_in - samples_out; - - if (unlikely(delay > uthr)) - delay = uthr; - } - break; - default: - dev_warn(codec->dev, "Unhandled FIFO mode: %d\n", - dac33->fifo_mode); - break; - } -out: - return delay; -} - -static int dac33_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - u8 ioc_reg, asrcb_reg; - - ioc_reg = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL); - asrcb_reg = dac33_read_reg_cache(codec, DAC33_ASRC_CTRL_B); - switch (clk_id) { - case TLV320DAC33_MCLK: - ioc_reg |= DAC33_REFSEL; - asrcb_reg |= DAC33_SRCREFSEL; - break; - case TLV320DAC33_SLEEPCLK: - ioc_reg &= ~DAC33_REFSEL; - asrcb_reg &= ~DAC33_SRCREFSEL; - break; - default: - dev_err(codec->dev, "Invalid clock ID (%d)\n", clk_id); - break; - } - dac33->refclk = freq; - - dac33_write_reg_cache(codec, DAC33_INT_OSC_CTRL, ioc_reg); - dac33_write_reg_cache(codec, DAC33_ASRC_CTRL_B, asrcb_reg); - - return 0; -} - -static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - u8 aictrl_a, aictrl_b; - - aictrl_a = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A); - aictrl_b = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B); - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - /* Codec Master */ - aictrl_a |= (DAC33_MSBCLK | DAC33_MSWCLK); - break; - case SND_SOC_DAIFMT_CBS_CFS: - /* Codec Slave */ - if (dac33->fifo_mode) { - dev_err(codec->dev, "FIFO mode requires master mode\n"); - return -EINVAL; - } else - aictrl_a &= ~(DAC33_MSBCLK | DAC33_MSWCLK); - break; - default: - return -EINVAL; - } - - aictrl_a &= ~DAC33_AFMT_MASK; - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - aictrl_a |= DAC33_AFMT_I2S; - break; - case SND_SOC_DAIFMT_DSP_A: - aictrl_a |= DAC33_AFMT_DSP; - aictrl_b &= ~DAC33_DATA_DELAY_MASK; - aictrl_b |= DAC33_DATA_DELAY(0); - break; - case SND_SOC_DAIFMT_RIGHT_J: - aictrl_a |= DAC33_AFMT_RIGHT_J; - break; - case SND_SOC_DAIFMT_LEFT_J: - aictrl_a |= DAC33_AFMT_LEFT_J; - break; - default: - dev_err(codec->dev, "Unsupported format (%u)\n", - fmt & SND_SOC_DAIFMT_FORMAT_MASK); - return -EINVAL; - } - - dac33_write_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A, aictrl_a); - dac33_write_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B, aictrl_b); - - return 0; -} - -static int dac33_soc_probe(struct snd_soc_codec *codec) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - codec->control_data = dac33->control_data; - codec->hw_write = (hw_write_t) i2c_master_send; - dac33->codec = codec; - - /* Read the tlv320dac33 ID registers */ - ret = dac33_hard_power(codec, 1); - if (ret != 0) { - dev_err(codec->dev, "Failed to power up codec: %d\n", ret); - goto err_power; - } - ret = dac33_read_id(codec); - dac33_hard_power(codec, 0); - - if (ret < 0) { - dev_err(codec->dev, "Failed to read chip ID: %d\n", ret); - ret = -ENODEV; - goto err_power; - } - - /* Check if the IRQ number is valid and request it */ - if (dac33->irq >= 0) { - ret = request_irq(dac33->irq, dac33_interrupt_handler, - IRQF_TRIGGER_RISING, - codec->name, codec); - if (ret < 0) { - dev_err(codec->dev, "Could not request IRQ%d (%d)\n", - dac33->irq, ret); - dac33->irq = -1; - } - if (dac33->irq != -1) { - /* Setup work queue */ - dac33->dac33_wq = - create_singlethread_workqueue("tlv320dac33"); - if (dac33->dac33_wq == NULL) { - free_irq(dac33->irq, codec); - return -ENOMEM; - } - - INIT_WORK(&dac33->work, dac33_work); - } - } - - /* Only add the FIFO controls, if we have valid IRQ number */ - if (dac33->irq >= 0) - snd_soc_add_codec_controls(codec, dac33_mode_snd_controls, - ARRAY_SIZE(dac33_mode_snd_controls)); - -err_power: - return ret; -} - -static int dac33_soc_remove(struct snd_soc_codec *codec) -{ - struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); - - dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); - - if (dac33->irq >= 0) { - free_irq(dac33->irq, dac33->codec); - destroy_workqueue(dac33->dac33_wq); - } - return 0; -} - -static int dac33_soc_suspend(struct snd_soc_codec *codec) -{ - dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int dac33_soc_resume(struct snd_soc_codec *codec) -{ - dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { - .read = dac33_read_reg_cache, - .write = dac33_write_locked, - .set_bias_level = dac33_set_bias_level, - .idle_bias_off = true, - .reg_cache_size = ARRAY_SIZE(dac33_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = dac33_reg, - .probe = dac33_soc_probe, - .remove = dac33_soc_remove, - .suspend = dac33_soc_suspend, - .resume = dac33_soc_resume, - - .controls = dac33_snd_controls, - .num_controls = ARRAY_SIZE(dac33_snd_controls), - .dapm_widgets = dac33_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), -}; - -#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000) -#define DAC33_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops dac33_dai_ops = { - .startup = dac33_startup, - .shutdown = dac33_shutdown, - .hw_params = dac33_hw_params, - .trigger = dac33_pcm_trigger, - .delay = dac33_dai_delay, - .set_sysclk = dac33_set_dai_sysclk, - .set_fmt = dac33_set_dai_fmt, -}; - -static struct snd_soc_dai_driver dac33_dai = { - .name = "tlv320dac33-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = DAC33_RATES, - .formats = DAC33_FORMATS, - .sig_bits = 24, - }, - .ops = &dac33_dai_ops, -}; - -static int __devinit dac33_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct tlv320dac33_platform_data *pdata; - struct tlv320dac33_priv *dac33; - int ret, i; - - if (client->dev.platform_data == NULL) { - dev_err(&client->dev, "Platform data not set\n"); - return -ENODEV; - } - pdata = client->dev.platform_data; - - dac33 = devm_kzalloc(&client->dev, sizeof(struct tlv320dac33_priv), - GFP_KERNEL); - if (dac33 == NULL) - return -ENOMEM; - - dac33->control_data = client; - mutex_init(&dac33->mutex); - spin_lock_init(&dac33->lock); - - i2c_set_clientdata(client, dac33); - - dac33->power_gpio = pdata->power_gpio; - dac33->burst_bclkdiv = pdata->burst_bclkdiv; - dac33->keep_bclk = pdata->keep_bclk; - dac33->mode1_latency = pdata->mode1_latency; - if (!dac33->mode1_latency) - dac33->mode1_latency = 10000; /* 10ms */ - dac33->irq = client->irq; - /* Disable FIFO use by default */ - dac33->fifo_mode = DAC33_FIFO_BYPASS; - - /* Check if the reset GPIO number is valid and request it */ - if (dac33->power_gpio >= 0) { - ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); - if (ret < 0) { - dev_err(&client->dev, - "Failed to request reset GPIO (%d)\n", - dac33->power_gpio); - goto err_gpio; - } - gpio_direction_output(dac33->power_gpio, 0); - } - - for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) - dac33->supplies[i].supply = dac33_supply_names[i]; - - ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), - dac33->supplies); - - if (ret != 0) { - dev_err(&client->dev, "Failed to request supplies: %d\n", ret); - goto err_get; - } - - ret = snd_soc_register_codec(&client->dev, - &soc_codec_dev_tlv320dac33, &dac33_dai, 1); - if (ret < 0) - goto err_register; - - return ret; -err_register: - regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); -err_get: - if (dac33->power_gpio >= 0) - gpio_free(dac33->power_gpio); -err_gpio: - return ret; -} - -static int __devexit dac33_i2c_remove(struct i2c_client *client) -{ - struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client); - - if (unlikely(dac33->chip_power)) - dac33_hard_power(dac33->codec, 0); - - if (dac33->power_gpio >= 0) - gpio_free(dac33->power_gpio); - - regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); - - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id tlv320dac33_i2c_id[] = { - { - .name = "tlv320dac33", - .driver_data = 0, - }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, tlv320dac33_i2c_id); - -static struct i2c_driver tlv320dac33_i2c_driver = { - .driver = { - .name = "tlv320dac33-codec", - .owner = THIS_MODULE, - }, - .probe = dac33_i2c_probe, - .remove = __devexit_p(dac33_i2c_remove), - .id_table = tlv320dac33_i2c_id, -}; - -static int __init dac33_module_init(void) -{ - int r; - r = i2c_add_driver(&tlv320dac33_i2c_driver); - if (r < 0) { - printk(KERN_ERR "DAC33: driver registration failed\n"); - return r; - } - return 0; -} -module_init(dac33_module_init); - -static void __exit dac33_module_exit(void) -{ - i2c_del_driver(&tlv320dac33_i2c_driver); -} -module_exit(dac33_module_exit); - - -MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); -MODULE_AUTHOR("Peter Ujfalusi "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.h b/ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.h deleted file mode 100644 index ed696707..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tlv320dac33.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * ALSA SoC Texas Instruments TLV320DAC33 codec driver - * - * Author: Peter Ujfalusi - * - * Copyright: (C) 2009 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __TLV320DAC33_H -#define __TLV320DAC33_H - -#define DAC33_PAGE_SELECT 0x00 -#define DAC33_PWR_CTRL 0x01 -#define DAC33_PLL_CTRL_A 0x02 -#define DAC33_PLL_CTRL_B 0x03 -#define DAC33_PLL_CTRL_C 0x04 -#define DAC33_PLL_CTRL_D 0x05 -#define DAC33_PLL_CTRL_E 0x06 -#define DAC33_INT_OSC_CTRL 0x07 -#define DAC33_INT_OSC_FREQ_RAT_A 0x08 -#define DAC33_INT_OSC_FREQ_RAT_B 0x09 -#define DAC33_INT_OSC_DAC_RATIO_SET 0x0A -#define DAC33_CALIB_TIME 0x0B -#define DAC33_INT_OSC_CTRL_B 0x0C -#define DAC33_INT_OSC_CTRL_C 0x0D -#define DAC33_INT_OSC_STATUS 0x0E -#define DAC33_INT_OSC_DAC_RATIO_READ 0x0F -#define DAC33_INT_OSC_FREQ_RAT_READ_A 0x10 -#define DAC33_INT_OSC_FREQ_RAT_READ_B 0x11 -#define DAC33_SER_AUDIOIF_CTRL_A 0x12 -#define DAC33_SER_AUDIOIF_CTRL_B 0x13 -#define DAC33_SER_AUDIOIF_CTRL_C 0x14 -#define DAC33_FIFO_CTRL_A 0x15 -#define DAC33_UTHR_MSB 0x16 -#define DAC33_UTHR_LSB 0x17 -#define DAC33_ATHR_MSB 0x18 -#define DAC33_ATHR_LSB 0x19 -#define DAC33_LTHR_MSB 0x1A -#define DAC33_LTHR_LSB 0x1B -#define DAC33_PREFILL_MSB 0x1C -#define DAC33_PREFILL_LSB 0x1D -#define DAC33_NSAMPLE_MSB 0x1E -#define DAC33_NSAMPLE_LSB 0x1F -#define DAC33_FIFO_WPTR_MSB 0x20 -#define DAC33_FIFO_WPTR_LSB 0x21 -#define DAC33_FIFO_RPTR_MSB 0x22 -#define DAC33_FIFO_RPTR_LSB 0x23 -#define DAC33_FIFO_DEPTH_MSB 0x24 -#define DAC33_FIFO_DEPTH_LSB 0x25 -#define DAC33_SAMPLES_REMAINING_MSB 0x26 -#define DAC33_SAMPLES_REMAINING_LSB 0x27 -#define DAC33_FIFO_IRQ_FLAG 0x28 -#define DAC33_FIFO_IRQ_MASK 0x29 -#define DAC33_FIFO_IRQ_MODE_A 0x2A -#define DAC33_FIFO_IRQ_MODE_B 0x2B -#define DAC33_DAC_CTRL_A 0x2C -#define DAC33_DAC_CTRL_B 0x2D -#define DAC33_DAC_CTRL_C 0x2E -#define DAC33_LDAC_DIG_VOL_CTRL 0x2F -#define DAC33_RDAC_DIG_VOL_CTRL 0x30 -#define DAC33_DAC_STATUS_FLAGS 0x31 -#define DAC33_ASRC_CTRL_A 0x32 -#define DAC33_ASRC_CTRL_B 0x33 -#define DAC33_SRC_REF_CLK_RATIO_A 0x34 -#define DAC33_SRC_REF_CLK_RATIO_B 0x35 -#define DAC33_SRC_EST_REF_CLK_RATIO_A 0x36 -#define DAC33_SRC_EST_REF_CLK_RATIO_B 0x37 -#define DAC33_INTP_CTRL_A 0x38 -#define DAC33_INTP_CTRL_B 0x39 -/* Registers 0x3A - 0x3F Reserved */ -#define DAC33_LDAC_PWR_CTRL 0x40 -#define DAC33_RDAC_PWR_CTRL 0x41 -#define DAC33_OUT_AMP_CM_CTRL 0x42 -#define DAC33_OUT_AMP_PWR_CTRL 0x43 -#define DAC33_OUT_AMP_CTRL 0x44 -#define DAC33_LINEL_TO_LLO_VOL 0x45 -/* Registers 0x45 - 0x47 Reserved */ -#define DAC33_LINER_TO_RLO_VOL 0x48 -#define DAC33_ANA_VOL_SOFT_STEP_CTRL 0x49 -#define DAC33_OSC_TRIM 0x4A -/* Registers 0x4B - 0x7C Reserved */ -#define DAC33_DEVICE_ID_MSB 0x7D -#define DAC33_DEVICE_ID_LSB 0x7E -#define DAC33_DEVICE_REV_ID 0x7F - -#define DAC33_CACHEREGNUM 128 - -/* Bit definitions */ - -/* DAC33_PWR_CTRL (0x01) */ -#define DAC33_DACRPDNB (0x01 << 0) -#define DAC33_DACLPDNB (0x01 << 1) -#define DAC33_OSCPDNB (0x01 << 2) -#define DAC33_PLLPDNB (0x01 << 3) -#define DAC33_PDNALLB (0x01 << 4) -#define DAC33_SOFT_RESET (0x01 << 7) - -/* DAC33_INT_OSC_CTRL (0x07) */ -#define DAC33_REFSEL (0x01 << 1) - -/* DAC33_INT_OSC_CTRL_B (0x0C) */ -#define DAC33_ADJSTEP(x) (x << 0) -#define DAC33_ADJTHRSHLD(x) (x << 4) - -/* DAC33_INT_OSC_CTRL_C (0x0D) */ -#define DAC33_REFDIV(x) (x << 4) - -/* DAC33_INT_OSC_STATUS (0x0E) */ -#define DAC33_OSCSTATUS_IDLE_CALIB (0x00) -#define DAC33_OSCSTATUS_NORMAL (0x01) -#define DAC33_OSCSTATUS_ADJUSTMENT (0x03) -#define DAC33_OSCSTATUS_NOT_USED (0x02) - -/* DAC33_SER_AUDIOIF_CTRL_A (0x12) */ -#define DAC33_MSWCLK (0x01 << 0) -#define DAC33_MSBCLK (0x01 << 1) -#define DAC33_AFMT_MASK (0x03 << 2) -#define DAC33_AFMT_I2S (0x00 << 2) -#define DAC33_AFMT_DSP (0x01 << 2) -#define DAC33_AFMT_RIGHT_J (0x02 << 2) -#define DAC33_AFMT_LEFT_J (0x03 << 2) -#define DAC33_WLEN_MASK (0x03 << 4) -#define DAC33_WLEN_16 (0x00 << 4) -#define DAC33_WLEN_20 (0x01 << 4) -#define DAC33_WLEN_24 (0x02 << 4) -#define DAC33_WLEN_32 (0x03 << 4) -#define DAC33_NCYCL_MASK (0x03 << 6) -#define DAC33_NCYCL_16 (0x00 << 6) -#define DAC33_NCYCL_20 (0x01 << 6) -#define DAC33_NCYCL_24 (0x02 << 6) -#define DAC33_NCYCL_32 (0x03 << 6) - -/* DAC33_SER_AUDIOIF_CTRL_B (0x13) */ -#define DAC33_DATA_DELAY_MASK (0x03 << 2) -#define DAC33_DATA_DELAY(x) (x << 2) -#define DAC33_BCLKON (0x01 << 5) - -/* DAC33_FIFO_CTRL_A (0x15) */ -#define DAC33_WIDTH (0x01 << 0) -#define DAC33_FBYPAS (0x01 << 1) -#define DAC33_FAUTO (0x01 << 2) -#define DAC33_FIFOFLUSH (0x01 << 3) - -/* - * UTHR, ATHR, LTHR, PREFILL, NSAMPLE (0x16 - 0x1F) - * 13-bit values -*/ -#define DAC33_THRREG(x) (((x) & 0x1FFF) << 3) - -/* DAC33_FIFO_IRQ_MASK (0x29) */ -#define DAC33_MNS (0x01 << 0) -#define DAC33_MPS (0x01 << 1) -#define DAC33_MAT (0x01 << 2) -#define DAC33_MLT (0x01 << 3) -#define DAC33_MUT (0x01 << 4) -#define DAC33_MUF (0x01 << 5) -#define DAC33_MOF (0x01 << 6) - -#define DAC33_FIFO_IRQ_MODE_MASK (0x03) -#define DAC33_FIFO_IRQ_MODE_RISING (0x00) -#define DAC33_FIFO_IRQ_MODE_FALLING (0x01) -#define DAC33_FIFO_IRQ_MODE_LEVEL (0x02) -#define DAC33_FIFO_IRQ_MODE_EDGE (0x03) - -/* DAC33_FIFO_IRQ_MODE_A (0x2A) */ -#define DAC33_UTM(x) (x << 0) -#define DAC33_UFM(x) (x << 2) -#define DAC33_OFM(x) (x << 4) - -/* DAC33_FIFO_IRQ_MODE_B (0x2B) */ -#define DAC33_NSM(x) (x << 0) -#define DAC33_PSM(x) (x << 2) -#define DAC33_ATM(x) (x << 4) -#define DAC33_LTM(x) (x << 6) - -/* DAC33_DAC_CTRL_A (0x2C) */ -#define DAC33_DACRATE(x) (x << 0) -#define DAC33_DACDUAL (0x01 << 4) -#define DAC33_DACLKSEL_MASK (0x03 << 5) -#define DAC33_DACLKSEL_INTSOC (0x00 << 5) -#define DAC33_DACLKSEL_PLL (0x01 << 5) -#define DAC33_DACLKSEL_MCLK (0x02 << 5) -#define DAC33_DACLKSEL_BCLK (0x03 << 5) - -/* DAC33_DAC_CTRL_B (0x2D) */ -#define DAC33_DACSRCR_MASK (0x03 << 0) -#define DAC33_DACSRCR_MUTE (0x00 << 0) -#define DAC33_DACSRCR_RIGHT (0x01 << 0) -#define DAC33_DACSRCR_LEFT (0x02 << 0) -#define DAC33_DACSRCR_MONOMIX (0x03 << 0) -#define DAC33_DACSRCL_MASK (0x03 << 2) -#define DAC33_DACSRCL_MUTE (0x00 << 2) -#define DAC33_DACSRCL_LEFT (0x01 << 2) -#define DAC33_DACSRCL_RIGHT (0x02 << 2) -#define DAC33_DACSRCL_MONOMIX (0x03 << 2) -#define DAC33_DVOLSTEP_MASK (0x03 << 4) -#define DAC33_DVOLSTEP_SS_PERFS (0x00 << 4) -#define DAC33_DVOLSTEP_SS_PER2FS (0x01 << 4) -#define DAC33_DVOLSTEP_SS_DISABLED (0x02 << 4) -#define DAC33_DVOLCTRL_MASK (0x03 << 6) -#define DAC33_DVOLCTRL_LR_INDEPENDENT1 (0x00 << 6) -#define DAC33_DVOLCTRL_LR_RIGHT_CONTROL (0x01 << 6) -#define DAC33_DVOLCTRL_LR_LEFT_CONTROL (0x02 << 6) -#define DAC33_DVOLCTRL_LR_INDEPENDENT2 (0x03 << 6) - -/* DAC33_DAC_CTRL_C (0x2E) */ -#define DAC33_DEEMENR (0x01 << 0) -#define DAC33_EFFENR (0x01 << 1) -#define DAC33_DEEMENL (0x01 << 2) -#define DAC33_EFFENL (0x01 << 3) -#define DAC33_EN3D (0x01 << 4) -#define DAC33_RESYNMUTE (0x01 << 5) -#define DAC33_RESYNEN (0x01 << 6) - -/* DAC33_ASRC_CTRL_A (0x32) */ -#define DAC33_SRCBYP (0x01 << 0) -#define DAC33_SRCLKSEL_MASK (0x03 << 1) -#define DAC33_SRCLKSEL_INTSOC (0x00 << 1) -#define DAC33_SRCLKSEL_PLL (0x01 << 1) -#define DAC33_SRCLKSEL_MCLK (0x02 << 1) -#define DAC33_SRCLKSEL_BCLK (0x03 << 1) -#define DAC33_SRCLKDIV(x) (x << 3) - -/* DAC33_ASRC_CTRL_B (0x33) */ -#define DAC33_SRCSETUP(x) (x << 0) -#define DAC33_SRCREFSEL (0x01 << 4) -#define DAC33_SRCREFDIV(x) (x << 5) - -/* DAC33_INTP_CTRL_A (0x38) */ -#define DAC33_INTPSEL (0x01 << 0) -#define DAC33_INTPM_MASK (0x03 << 1) -#define DAC33_INTPM_ALOW_OPENDRAIN (0x00 << 1) -#define DAC33_INTPM_ALOW (0x01 << 1) -#define DAC33_INTPM_AHIGH (0x02 << 1) - -/* DAC33_LDAC_PWR_CTRL (0x40) */ -/* DAC33_RDAC_PWR_CTRL (0x41) */ -#define DAC33_DACLRNUM (0x01 << 2) -#define DAC33_LROUT_GAIN(x) (x << 0) - -/* DAC33_ANA_VOL_SOFT_STEP_CTRL (0x49) */ -#define DAC33_VOLCLKSEL (0x01 << 0) -#define DAC33_VOLCLKEN (0x01 << 1) -#define DAC33_VOLBYPASS (0x01 << 2) - -#define TLV320DAC33_MCLK 0 -#define TLV320DAC33_SLEEPCLK 1 - -#endif /* __TLV320DAC33_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.c b/ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.c deleted file mode 100644 index 6fe4aa3a..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver - * - * Copyright (C) Nokia Corporation - * - * Author: Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tpa6130a2.h" - -enum tpa_model { - TPA6130A2, - TPA6140A2, -}; - -static struct i2c_client *tpa6130a2_client; - -/* This struct is used to save the context */ -struct tpa6130a2_data { - struct mutex mutex; - unsigned char regs[TPA6130A2_CACHEREGNUM]; - struct regulator *supply; - int power_gpio; - u8 power_state:1; - enum tpa_model id; -}; - -static int tpa6130a2_i2c_read(int reg) -{ - struct tpa6130a2_data *data; - int val; - - BUG_ON(tpa6130a2_client == NULL); - data = i2c_get_clientdata(tpa6130a2_client); - - /* If powered off, return the cached value */ - if (data->power_state) { - val = i2c_smbus_read_byte_data(tpa6130a2_client, reg); - if (val < 0) - dev_err(&tpa6130a2_client->dev, "Read failed\n"); - else - data->regs[reg] = val; - } else { - val = data->regs[reg]; - } - - return val; -} - -static int tpa6130a2_i2c_write(int reg, u8 value) -{ - struct tpa6130a2_data *data; - int val = 0; - - BUG_ON(tpa6130a2_client == NULL); - data = i2c_get_clientdata(tpa6130a2_client); - - if (data->power_state) { - val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value); - if (val < 0) { - dev_err(&tpa6130a2_client->dev, "Write failed\n"); - return val; - } - } - - /* Either powered on or off, we save the context */ - data->regs[reg] = value; - - return val; -} - -static u8 tpa6130a2_read(int reg) -{ - struct tpa6130a2_data *data; - - BUG_ON(tpa6130a2_client == NULL); - data = i2c_get_clientdata(tpa6130a2_client); - - return data->regs[reg]; -} - -static int tpa6130a2_initialize(void) -{ - struct tpa6130a2_data *data; - int i, ret = 0; - - BUG_ON(tpa6130a2_client == NULL); - data = i2c_get_clientdata(tpa6130a2_client); - - for (i = 1; i < TPA6130A2_REG_VERSION; i++) { - ret = tpa6130a2_i2c_write(i, data->regs[i]); - if (ret < 0) - break; - } - - return ret; -} - -static int tpa6130a2_power(u8 power) -{ - struct tpa6130a2_data *data; - u8 val; - int ret = 0; - - BUG_ON(tpa6130a2_client == NULL); - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - if (power == data->power_state) - goto exit; - - if (power) { - ret = regulator_enable(data->supply); - if (ret != 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to enable supply: %d\n", ret); - goto exit; - } - /* Power on */ - if (data->power_gpio >= 0) - gpio_set_value(data->power_gpio, 1); - - data->power_state = 1; - ret = tpa6130a2_initialize(); - if (ret < 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to initialize chip\n"); - if (data->power_gpio >= 0) - gpio_set_value(data->power_gpio, 0); - regulator_disable(data->supply); - data->power_state = 0; - goto exit; - } - } else { - /* set SWS */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val |= TPA6130A2_SWS; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); - - /* Power off */ - if (data->power_gpio >= 0) - gpio_set_value(data->power_gpio, 0); - - ret = regulator_disable(data->supply); - if (ret != 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to disable supply: %d\n", ret); - goto exit; - } - - data->power_state = 0; - } - -exit: - mutex_unlock(&data->mutex); - return ret; -} - -static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct tpa6130a2_data *data; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - - BUG_ON(tpa6130a2_client == NULL); - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - - ucontrol->value.integer.value[0] = - (tpa6130a2_read(reg) >> shift) & mask; - - if (invert) - ucontrol->value.integer.value[0] = - max - ucontrol->value.integer.value[0]; - - mutex_unlock(&data->mutex); - return 0; -} - -static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct tpa6130a2_data *data; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - unsigned int val_reg; - - BUG_ON(tpa6130a2_client == NULL); - data = i2c_get_clientdata(tpa6130a2_client); - - if (invert) - val = max - val; - - mutex_lock(&data->mutex); - - val_reg = tpa6130a2_read(reg); - if (((val_reg >> shift) & mask) == val) { - mutex_unlock(&data->mutex); - return 0; - } - - val_reg &= ~(mask << shift); - val_reg |= val << shift; - tpa6130a2_i2c_write(reg, val_reg); - - mutex_unlock(&data->mutex); - - return 1; -} - -/* - * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going - * down in gain. - */ -static const unsigned int tpa6130_tlv[] = { - TLV_DB_RANGE_HEAD(10), - 0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0), - 2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0), - 4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0), - 6, 7, TLV_DB_SCALE_ITEM(-4140, 190, 0), - 8, 9, TLV_DB_SCALE_ITEM(-3650, 120, 0), - 10, 11, TLV_DB_SCALE_ITEM(-3330, 160, 0), - 12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0), - 14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0), - 21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0), - 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0), -}; - -static const struct snd_kcontrol_new tpa6130a2_controls[] = { - SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", - TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, - tpa6130a2_get_volsw, tpa6130a2_put_volsw, - tpa6130_tlv), -}; - -static const unsigned int tpa6140_tlv[] = { - TLV_DB_RANGE_HEAD(3), - 0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0), - 9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0), - 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0), -}; - -static const struct snd_kcontrol_new tpa6140a2_controls[] = { - SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume", - TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0, - tpa6130a2_get_volsw, tpa6130a2_put_volsw, - tpa6140_tlv), -}; - -/* - * Enable or disable channel (left or right) - * The bit number for mute and amplifier are the same per channel: - * bit 6: Right channel - * bit 7: Left channel - * in both registers. - */ -static void tpa6130a2_channel_enable(u8 channel, int enable) -{ - u8 val; - - if (enable) { - /* Enable channel */ - /* Enable amplifier */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val |= channel; - val &= ~TPA6130A2_SWS; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); - - /* Unmute channel */ - val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); - val &= ~channel; - tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); - } else { - /* Disable channel */ - /* Mute channel */ - val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); - val |= channel; - tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); - - /* Disable amplifier */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val &= ~channel; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); - } -} - -int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) -{ - int ret = 0; - if (enable) { - ret = tpa6130a2_power(1); - if (ret < 0) - return ret; - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 1); - } else { - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 0); - ret = tpa6130a2_power(0); - } - - return ret; -} -EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable); - -int tpa6130a2_add_controls(struct snd_soc_codec *codec) -{ - struct tpa6130a2_data *data; - - if (tpa6130a2_client == NULL) - return -ENODEV; - - data = i2c_get_clientdata(tpa6130a2_client); - - if (data->id == TPA6140A2) - return snd_soc_add_codec_controls(codec, tpa6140a2_controls, - ARRAY_SIZE(tpa6140a2_controls)); - else - return snd_soc_add_codec_controls(codec, tpa6130a2_controls, - ARRAY_SIZE(tpa6130a2_controls)); -} -EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); - -static int __devinit tpa6130a2_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct device *dev; - struct tpa6130a2_data *data; - struct tpa6130a2_platform_data *pdata; - const char *regulator; - int ret; - - dev = &client->dev; - - if (client->dev.platform_data == NULL) { - dev_err(dev, "Platform data not set\n"); - dump_stack(); - return -ENODEV; - } - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (data == NULL) { - dev_err(dev, "Can not allocate memory\n"); - return -ENOMEM; - } - - tpa6130a2_client = client; - - i2c_set_clientdata(tpa6130a2_client, data); - - pdata = client->dev.platform_data; - data->power_gpio = pdata->power_gpio; - data->id = id->driver_data; - - mutex_init(&data->mutex); - - /* Set default register values */ - data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS; - data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_MUTE_R | - TPA6130A2_MUTE_L; - - if (data->power_gpio >= 0) { - ret = gpio_request(data->power_gpio, "tpa6130a2 enable"); - if (ret < 0) { - dev_err(dev, "Failed to request power GPIO (%d)\n", - data->power_gpio); - goto err_gpio; - } - gpio_direction_output(data->power_gpio, 0); - } - - switch (data->id) { - default: - dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", - data->id); - case TPA6130A2: - regulator = "Vdd"; - break; - case TPA6140A2: - regulator = "AVdd"; - break; - } - - data->supply = regulator_get(dev, regulator); - if (IS_ERR(data->supply)) { - ret = PTR_ERR(data->supply); - dev_err(dev, "Failed to request supply: %d\n", ret); - goto err_regulator; - } - - ret = tpa6130a2_power(1); - if (ret != 0) - goto err_power; - - - /* Read version */ - ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) & - TPA6130A2_VERSION_MASK; - if ((ret != 1) && (ret != 2)) - dev_warn(dev, "UNTESTED version detected (%d)\n", ret); - - /* Disable the chip */ - ret = tpa6130a2_power(0); - if (ret != 0) - goto err_power; - - return 0; - -err_power: - regulator_put(data->supply); -err_regulator: - if (data->power_gpio >= 0) - gpio_free(data->power_gpio); -err_gpio: - tpa6130a2_client = NULL; - - return ret; -} - -static int __devexit tpa6130a2_remove(struct i2c_client *client) -{ - struct tpa6130a2_data *data = i2c_get_clientdata(client); - - tpa6130a2_power(0); - - if (data->power_gpio >= 0) - gpio_free(data->power_gpio); - - regulator_put(data->supply); - tpa6130a2_client = NULL; - - return 0; -} - -static const struct i2c_device_id tpa6130a2_id[] = { - { "tpa6130a2", TPA6130A2 }, - { "tpa6140a2", TPA6140A2 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tpa6130a2_id); - -static struct i2c_driver tpa6130a2_i2c_driver = { - .driver = { - .name = "tpa6130a2", - .owner = THIS_MODULE, - }, - .probe = tpa6130a2_probe, - .remove = __devexit_p(tpa6130a2_remove), - .id_table = tpa6130a2_id, -}; - -static int __init tpa6130a2_init(void) -{ - return i2c_add_driver(&tpa6130a2_i2c_driver); -} - -static void __exit tpa6130a2_exit(void) -{ - i2c_del_driver(&tpa6130a2_i2c_driver); -} - -MODULE_AUTHOR("Peter Ujfalusi "); -MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); -MODULE_LICENSE("GPL"); - -module_init(tpa6130a2_init); -module_exit(tpa6130a2_exit); diff --git a/ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.h b/ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.h deleted file mode 100644 index 41744402..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/tpa6130a2.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ALSA SoC TPA6130A2 amplifier driver - * - * Copyright (C) Nokia Corporation - * - * Author: Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __TPA6130A2_H__ -#define __TPA6130A2_H__ - -/* Register addresses */ -#define TPA6130A2_REG_CONTROL 0x01 -#define TPA6130A2_REG_VOL_MUTE 0x02 -#define TPA6130A2_REG_OUT_IMPEDANCE 0x03 -#define TPA6130A2_REG_VERSION 0x04 - -#define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1) - -/* Register bits */ -/* TPA6130A2_REG_CONTROL (0x01) */ -#define TPA6130A2_SWS (0x01 << 0) -#define TPA6130A2_TERMAL (0x01 << 1) -#define TPA6130A2_MODE(x) (x << 4) -#define TPA6130A2_MODE_STEREO (0x00) -#define TPA6130A2_MODE_DUAL_MONO (0x01) -#define TPA6130A2_MODE_BRIDGE (0x02) -#define TPA6130A2_MODE_MASK (0x03) -#define TPA6130A2_HP_EN_R (0x01 << 6) -#define TPA6130A2_HP_EN_L (0x01 << 7) - -/* TPA6130A2_REG_VOL_MUTE (0x02) */ -#define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0) -#define TPA6130A2_MUTE_R (0x01 << 6) -#define TPA6130A2_MUTE_L (0x01 << 7) - -/* TPA6130A2_REG_OUT_IMPEDANCE (0x03) */ -#define TPA6130A2_HIZ_R (0x01 << 0) -#define TPA6130A2_HIZ_L (0x01 << 1) - -/* TPA6130A2_REG_VERSION (0x04) */ -#define TPA6130A2_VERSION_MASK (0x0f) - -extern int tpa6130a2_add_controls(struct snd_soc_codec *codec); -extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable); - -#endif /* __TPA6130A2_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/twl4030.c b/ANDROID_3.4.5/sound/soc/codecs/twl4030.c deleted file mode 100644 index 170cf9a8..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/twl4030.c +++ /dev/null @@ -1,2303 +0,0 @@ -/* - * ALSA SoC TWL4030 codec driver - * - * Author: Steve Sakoman, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Register descriptions are here */ -#include - -/* Shadow register used by the audio driver */ -#define TWL4030_REG_SW_SHADOW 0x4A -#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) - -/* TWL4030_REG_SW_SHADOW (0x4A) Fields */ -#define TWL4030_HFL_EN 0x01 -#define TWL4030_HFR_EN 0x02 - -/* - * twl4030 register cache & default register settings - */ -static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { - 0x00, /* this register not used */ - 0x00, /* REG_CODEC_MODE (0x1) */ - 0x00, /* REG_OPTION (0x2) */ - 0x00, /* REG_UNKNOWN (0x3) */ - 0x00, /* REG_MICBIAS_CTL (0x4) */ - 0x00, /* REG_ANAMICL (0x5) */ - 0x00, /* REG_ANAMICR (0x6) */ - 0x00, /* REG_AVADC_CTL (0x7) */ - 0x00, /* REG_ADCMICSEL (0x8) */ - 0x00, /* REG_DIGMIXING (0x9) */ - 0x0f, /* REG_ATXL1PGA (0xA) */ - 0x0f, /* REG_ATXR1PGA (0xB) */ - 0x0f, /* REG_AVTXL2PGA (0xC) */ - 0x0f, /* REG_AVTXR2PGA (0xD) */ - 0x00, /* REG_AUDIO_IF (0xE) */ - 0x00, /* REG_VOICE_IF (0xF) */ - 0x3f, /* REG_ARXR1PGA (0x10) */ - 0x3f, /* REG_ARXL1PGA (0x11) */ - 0x3f, /* REG_ARXR2PGA (0x12) */ - 0x3f, /* REG_ARXL2PGA (0x13) */ - 0x25, /* REG_VRXPGA (0x14) */ - 0x00, /* REG_VSTPGA (0x15) */ - 0x00, /* REG_VRX2ARXPGA (0x16) */ - 0x00, /* REG_AVDAC_CTL (0x17) */ - 0x00, /* REG_ARX2VTXPGA (0x18) */ - 0x32, /* REG_ARXL1_APGA_CTL (0x19) */ - 0x32, /* REG_ARXR1_APGA_CTL (0x1A) */ - 0x32, /* REG_ARXL2_APGA_CTL (0x1B) */ - 0x32, /* REG_ARXR2_APGA_CTL (0x1C) */ - 0x00, /* REG_ATX2ARXPGA (0x1D) */ - 0x00, /* REG_BT_IF (0x1E) */ - 0x55, /* REG_BTPGA (0x1F) */ - 0x00, /* REG_BTSTPGA (0x20) */ - 0x00, /* REG_EAR_CTL (0x21) */ - 0x00, /* REG_HS_SEL (0x22) */ - 0x00, /* REG_HS_GAIN_SET (0x23) */ - 0x00, /* REG_HS_POPN_SET (0x24) */ - 0x00, /* REG_PREDL_CTL (0x25) */ - 0x00, /* REG_PREDR_CTL (0x26) */ - 0x00, /* REG_PRECKL_CTL (0x27) */ - 0x00, /* REG_PRECKR_CTL (0x28) */ - 0x00, /* REG_HFL_CTL (0x29) */ - 0x00, /* REG_HFR_CTL (0x2A) */ - 0x05, /* REG_ALC_CTL (0x2B) */ - 0x00, /* REG_ALC_SET1 (0x2C) */ - 0x00, /* REG_ALC_SET2 (0x2D) */ - 0x00, /* REG_BOOST_CTL (0x2E) */ - 0x00, /* REG_SOFTVOL_CTL (0x2F) */ - 0x13, /* REG_DTMF_FREQSEL (0x30) */ - 0x00, /* REG_DTMF_TONEXT1H (0x31) */ - 0x00, /* REG_DTMF_TONEXT1L (0x32) */ - 0x00, /* REG_DTMF_TONEXT2H (0x33) */ - 0x00, /* REG_DTMF_TONEXT2L (0x34) */ - 0x79, /* REG_DTMF_TONOFF (0x35) */ - 0x11, /* REG_DTMF_WANONOFF (0x36) */ - 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */ - 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */ - 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */ - 0x06, /* REG_APLL_CTL (0x3A) */ - 0x00, /* REG_DTMF_CTL (0x3B) */ - 0x44, /* REG_DTMF_PGA_CTL2 (0x3C) */ - 0x69, /* REG_DTMF_PGA_CTL1 (0x3D) */ - 0x00, /* REG_MISC_SET_1 (0x3E) */ - 0x00, /* REG_PCMBTMUX (0x3F) */ - 0x00, /* not used (0x40) */ - 0x00, /* not used (0x41) */ - 0x00, /* not used (0x42) */ - 0x00, /* REG_RX_PATH_SEL (0x43) */ - 0x32, /* REG_VDL_APGA_CTL (0x44) */ - 0x00, /* REG_VIBRA_CTL (0x45) */ - 0x00, /* REG_VIBRA_SET (0x46) */ - 0x00, /* REG_VIBRA_PWM_SET (0x47) */ - 0x00, /* REG_ANAMIC_GAIN (0x48) */ - 0x00, /* REG_MISC_SET_2 (0x49) */ - 0x00, /* REG_SW_SHADOW (0x4A) - Shadow, non HW register */ -}; - -/* codec private data */ -struct twl4030_priv { - struct snd_soc_codec codec; - - unsigned int codec_powered; - - /* reference counts of AIF/APLL users */ - unsigned int apll_enabled; - - struct snd_pcm_substream *master_substream; - struct snd_pcm_substream *slave_substream; - - unsigned int configured; - unsigned int rate; - unsigned int sample_bits; - unsigned int channels; - - unsigned int sysclk; - - /* Output (with associated amp) states */ - u8 hsl_enabled, hsr_enabled; - u8 earpiece_enabled; - u8 predrivel_enabled, predriver_enabled; - u8 carkitl_enabled, carkitr_enabled; - - /* Delay needed after enabling the digimic interface */ - unsigned int digimic_delay; -}; - -/* - * read twl4030 register cache - */ -static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *cache = codec->reg_cache; - - if (reg >= TWL4030_CACHEREGNUM) - return -EIO; - - return cache[reg]; -} - -/* - * write twl4030 register cache - */ -static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec, - u8 reg, u8 value) -{ - u8 *cache = codec->reg_cache; - - if (reg >= TWL4030_CACHEREGNUM) - return; - cache[reg] = value; -} - -/* - * write to the twl4030 register space - */ -static int twl4030_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - int write_to_reg = 0; - - twl4030_write_reg_cache(codec, reg, value); - if (likely(reg < TWL4030_REG_SW_SHADOW)) { - /* Decide if the given register can be written */ - switch (reg) { - case TWL4030_REG_EAR_CTL: - if (twl4030->earpiece_enabled) - write_to_reg = 1; - break; - case TWL4030_REG_PREDL_CTL: - if (twl4030->predrivel_enabled) - write_to_reg = 1; - break; - case TWL4030_REG_PREDR_CTL: - if (twl4030->predriver_enabled) - write_to_reg = 1; - break; - case TWL4030_REG_PRECKL_CTL: - if (twl4030->carkitl_enabled) - write_to_reg = 1; - break; - case TWL4030_REG_PRECKR_CTL: - if (twl4030->carkitr_enabled) - write_to_reg = 1; - break; - case TWL4030_REG_HS_GAIN_SET: - if (twl4030->hsl_enabled || twl4030->hsr_enabled) - write_to_reg = 1; - break; - default: - /* All other register can be written */ - write_to_reg = 1; - break; - } - if (write_to_reg) - return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, - value, reg); - } - return 0; -} - -static inline void twl4030_wait_ms(int time) -{ - if (time < 60) { - time *= 1000; - usleep_range(time, time + 500); - } else { - msleep(time); - } -} - -static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) -{ - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - int mode; - - if (enable == twl4030->codec_powered) - return; - - if (enable) - mode = twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER); - else - mode = twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER); - - if (mode >= 0) { - twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode); - twl4030->codec_powered = enable; - } - - /* REVISIT: this delay is present in TI sample drivers */ - /* but there seems to be no TRM requirement for it */ - udelay(10); -} - -static inline void twl4030_check_defaults(struct snd_soc_codec *codec) -{ - int i, difference = 0; - u8 val; - - dev_dbg(codec->dev, "Checking TWL audio default configuration\n"); - for (i = 1; i <= TWL4030_REG_MISC_SET_2; i++) { - twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val, i); - if (val != twl4030_reg[i]) { - difference++; - dev_dbg(codec->dev, - "Reg 0x%02x: chip: 0x%02x driver: 0x%02x\n", - i, val, twl4030_reg[i]); - } - } - dev_dbg(codec->dev, "Found %d non-matching registers. %s\n", - difference, difference ? "Not OK" : "OK"); -} - -static inline void twl4030_reset_registers(struct snd_soc_codec *codec) -{ - int i; - - /* set all audio section registers to reasonable defaults */ - for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) - if (i != TWL4030_REG_APLL_CTL) - twl4030_write(codec, i, twl4030_reg[i]); - -} - -static void twl4030_init_chip(struct snd_soc_codec *codec) -{ - struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - u8 reg, byte; - int i = 0; - - /* Check defaults, if instructed before anything else */ - if (pdata && pdata->check_defaults) - twl4030_check_defaults(codec); - - /* Reset registers, if no setup data or if instructed to do so */ - if (!pdata || (pdata && pdata->reset_registers)) - twl4030_reset_registers(codec); - - /* Refresh APLL_CTL register from HW */ - twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, - TWL4030_REG_APLL_CTL); - twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, byte); - - /* anti-pop when changing analog gain */ - reg = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); - twl4030_write(codec, TWL4030_REG_MISC_SET_1, - reg | TWL4030_SMOOTH_ANAVOL_EN); - - twl4030_write(codec, TWL4030_REG_OPTION, - TWL4030_ATXL1_EN | TWL4030_ATXR1_EN | - TWL4030_ARXL2_EN | TWL4030_ARXR2_EN); - - /* REG_ARXR2_APGA_CTL reset according to the TRM: 0dB, DA_EN */ - twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); - - /* Machine dependent setup */ - if (!pdata) - return; - - twl4030->digimic_delay = pdata->digimic_delay; - - reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - reg &= ~TWL4030_RAMP_DELAY; - reg |= (pdata->ramp_delay_value << 2); - twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); - - /* initiate offset cancellation */ - twl4030_codec_enable(codec, 1); - - reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); - reg &= ~TWL4030_OFFSET_CNCL_SEL; - reg |= pdata->offset_cncl_path; - twl4030_write(codec, TWL4030_REG_ANAMICL, - reg | TWL4030_CNCL_OFFSET_START); - - /* - * Wait for offset cancellation to complete. - * Since this takes a while, do not slam the i2c. - * Start polling the status after ~20ms. - */ - msleep(20); - do { - usleep_range(1000, 2000); - twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, - TWL4030_REG_ANAMICL); - } while ((i++ < 100) && - ((byte & TWL4030_CNCL_OFFSET_START) == - TWL4030_CNCL_OFFSET_START)); - - /* Make sure that the reg_cache has the same value as the HW */ - twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); - - twl4030_codec_enable(codec, 0); -} - -static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) -{ - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - int status = -1; - - if (enable) { - twl4030->apll_enabled++; - if (twl4030->apll_enabled == 1) - status = twl4030_audio_enable_resource( - TWL4030_AUDIO_RES_APLL); - } else { - twl4030->apll_enabled--; - if (!twl4030->apll_enabled) - status = twl4030_audio_disable_resource( - TWL4030_AUDIO_RES_APLL); - } - - if (status >= 0) - twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); -} - -/* Earpiece */ -static const struct snd_kcontrol_new twl4030_dapm_earpiece_controls[] = { - SOC_DAPM_SINGLE("Voice", TWL4030_REG_EAR_CTL, 0, 1, 0), - SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_EAR_CTL, 1, 1, 0), - SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_EAR_CTL, 2, 1, 0), - SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_EAR_CTL, 3, 1, 0), -}; - -/* PreDrive Left */ -static const struct snd_kcontrol_new twl4030_dapm_predrivel_controls[] = { - SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDL_CTL, 0, 1, 0), - SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PREDL_CTL, 1, 1, 0), - SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDL_CTL, 2, 1, 0), - SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDL_CTL, 3, 1, 0), -}; - -/* PreDrive Right */ -static const struct snd_kcontrol_new twl4030_dapm_predriver_controls[] = { - SOC_DAPM_SINGLE("Voice", TWL4030_REG_PREDR_CTL, 0, 1, 0), - SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PREDR_CTL, 1, 1, 0), - SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PREDR_CTL, 2, 1, 0), - SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PREDR_CTL, 3, 1, 0), -}; - -/* Headset Left */ -static const struct snd_kcontrol_new twl4030_dapm_hsol_controls[] = { - SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 0, 1, 0), - SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_HS_SEL, 1, 1, 0), - SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_HS_SEL, 2, 1, 0), -}; - -/* Headset Right */ -static const struct snd_kcontrol_new twl4030_dapm_hsor_controls[] = { - SOC_DAPM_SINGLE("Voice", TWL4030_REG_HS_SEL, 3, 1, 0), - SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_HS_SEL, 4, 1, 0), - SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_HS_SEL, 5, 1, 0), -}; - -/* Carkit Left */ -static const struct snd_kcontrol_new twl4030_dapm_carkitl_controls[] = { - SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKL_CTL, 0, 1, 0), - SOC_DAPM_SINGLE("AudioL1", TWL4030_REG_PRECKL_CTL, 1, 1, 0), - SOC_DAPM_SINGLE("AudioL2", TWL4030_REG_PRECKL_CTL, 2, 1, 0), -}; - -/* Carkit Right */ -static const struct snd_kcontrol_new twl4030_dapm_carkitr_controls[] = { - SOC_DAPM_SINGLE("Voice", TWL4030_REG_PRECKR_CTL, 0, 1, 0), - SOC_DAPM_SINGLE("AudioR1", TWL4030_REG_PRECKR_CTL, 1, 1, 0), - SOC_DAPM_SINGLE("AudioR2", TWL4030_REG_PRECKR_CTL, 2, 1, 0), -}; - -/* Handsfree Left */ -static const char *twl4030_handsfreel_texts[] = - {"Voice", "AudioL1", "AudioL2", "AudioR2"}; - -static const struct soc_enum twl4030_handsfreel_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, - ARRAY_SIZE(twl4030_handsfreel_texts), - twl4030_handsfreel_texts); - -static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = -SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); - -/* Handsfree Left virtual mute */ -static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control = - SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 0, 1, 0); - -/* Handsfree Right */ -static const char *twl4030_handsfreer_texts[] = - {"Voice", "AudioR1", "AudioR2", "AudioL2"}; - -static const struct soc_enum twl4030_handsfreer_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, - ARRAY_SIZE(twl4030_handsfreer_texts), - twl4030_handsfreer_texts); - -static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = -SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); - -/* Handsfree Right virtual mute */ -static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control = - SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 1, 1, 0); - -/* Vibra */ -/* Vibra audio path selection */ -static const char *twl4030_vibra_texts[] = - {"AudioL1", "AudioR1", "AudioL2", "AudioR2"}; - -static const struct soc_enum twl4030_vibra_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 2, - ARRAY_SIZE(twl4030_vibra_texts), - twl4030_vibra_texts); - -static const struct snd_kcontrol_new twl4030_dapm_vibra_control = -SOC_DAPM_ENUM("Route", twl4030_vibra_enum); - -/* Vibra path selection: local vibrator (PWM) or audio driven */ -static const char *twl4030_vibrapath_texts[] = - {"Local vibrator", "Audio"}; - -static const struct soc_enum twl4030_vibrapath_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 4, - ARRAY_SIZE(twl4030_vibrapath_texts), - twl4030_vibrapath_texts); - -static const struct snd_kcontrol_new twl4030_dapm_vibrapath_control = -SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum); - -/* Left analog microphone selection */ -static const struct snd_kcontrol_new twl4030_dapm_analoglmic_controls[] = { - SOC_DAPM_SINGLE("Main Mic Capture Switch", - TWL4030_REG_ANAMICL, 0, 1, 0), - SOC_DAPM_SINGLE("Headset Mic Capture Switch", - TWL4030_REG_ANAMICL, 1, 1, 0), - SOC_DAPM_SINGLE("AUXL Capture Switch", - TWL4030_REG_ANAMICL, 2, 1, 0), - SOC_DAPM_SINGLE("Carkit Mic Capture Switch", - TWL4030_REG_ANAMICL, 3, 1, 0), -}; - -/* Right analog microphone selection */ -static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = { - SOC_DAPM_SINGLE("Sub Mic Capture Switch", TWL4030_REG_ANAMICR, 0, 1, 0), - SOC_DAPM_SINGLE("AUXR Capture Switch", TWL4030_REG_ANAMICR, 2, 1, 0), -}; - -/* TX1 L/R Analog/Digital microphone selection */ -static const char *twl4030_micpathtx1_texts[] = - {"Analog", "Digimic0"}; - -static const struct soc_enum twl4030_micpathtx1_enum = - SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 0, - ARRAY_SIZE(twl4030_micpathtx1_texts), - twl4030_micpathtx1_texts); - -static const struct snd_kcontrol_new twl4030_dapm_micpathtx1_control = -SOC_DAPM_ENUM("Route", twl4030_micpathtx1_enum); - -/* TX2 L/R Analog/Digital microphone selection */ -static const char *twl4030_micpathtx2_texts[] = - {"Analog", "Digimic1"}; - -static const struct soc_enum twl4030_micpathtx2_enum = - SOC_ENUM_SINGLE(TWL4030_REG_ADCMICSEL, 2, - ARRAY_SIZE(twl4030_micpathtx2_texts), - twl4030_micpathtx2_texts); - -static const struct snd_kcontrol_new twl4030_dapm_micpathtx2_control = -SOC_DAPM_ENUM("Route", twl4030_micpathtx2_enum); - -/* Analog bypass for AudioR1 */ -static const struct snd_kcontrol_new twl4030_dapm_abypassr1_control = - SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR1_APGA_CTL, 2, 1, 0); - -/* Analog bypass for AudioL1 */ -static const struct snd_kcontrol_new twl4030_dapm_abypassl1_control = - SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL1_APGA_CTL, 2, 1, 0); - -/* Analog bypass for AudioR2 */ -static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control = - SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXR2_APGA_CTL, 2, 1, 0); - -/* Analog bypass for AudioL2 */ -static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control = - SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0); - -/* Analog bypass for Voice */ -static const struct snd_kcontrol_new twl4030_dapm_abypassv_control = - SOC_DAPM_SINGLE("Switch", TWL4030_REG_VDL_APGA_CTL, 2, 1, 0); - -/* Digital bypass gain, mute instead of -30dB */ -static const unsigned int twl4030_dapm_dbypass_tlv[] = { - TLV_DB_RANGE_HEAD(3), - 0, 1, TLV_DB_SCALE_ITEM(-3000, 600, 1), - 2, 3, TLV_DB_SCALE_ITEM(-2400, 0, 0), - 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0), -}; - -/* Digital bypass left (TX1L -> RX2L) */ -static const struct snd_kcontrol_new twl4030_dapm_dbypassl_control = - SOC_DAPM_SINGLE_TLV("Volume", - TWL4030_REG_ATX2ARXPGA, 3, 7, 0, - twl4030_dapm_dbypass_tlv); - -/* Digital bypass right (TX1R -> RX2R) */ -static const struct snd_kcontrol_new twl4030_dapm_dbypassr_control = - SOC_DAPM_SINGLE_TLV("Volume", - TWL4030_REG_ATX2ARXPGA, 0, 7, 0, - twl4030_dapm_dbypass_tlv); - -/* - * Voice Sidetone GAIN volume control: - * from -51 to -10 dB in 1 dB steps (mute instead of -51 dB) - */ -static DECLARE_TLV_DB_SCALE(twl4030_dapm_dbypassv_tlv, -5100, 100, 1); - -/* Digital bypass voice: sidetone (VUL -> VDL)*/ -static const struct snd_kcontrol_new twl4030_dapm_dbypassv_control = - SOC_DAPM_SINGLE_TLV("Volume", - TWL4030_REG_VSTPGA, 0, 0x29, 0, - twl4030_dapm_dbypassv_tlv); - -/* - * Output PGA builder: - * Handle the muting and unmuting of the given output (turning off the - * amplifier associated with the output pin) - * On mute bypass the reg_cache and write 0 to the register - * On unmute: restore the register content from the reg_cache - * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R - */ -#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \ -static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ - struct snd_kcontrol *kcontrol, int event) \ -{ \ - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); \ - \ - switch (event) { \ - case SND_SOC_DAPM_POST_PMU: \ - twl4030->pin_name##_enabled = 1; \ - twl4030_write(w->codec, reg, \ - twl4030_read_reg_cache(w->codec, reg)); \ - break; \ - case SND_SOC_DAPM_POST_PMD: \ - twl4030->pin_name##_enabled = 0; \ - twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ - 0, reg); \ - break; \ - } \ - return 0; \ -} - -TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL, TWL4030_EAR_GAIN); -TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL, TWL4030_PREDL_GAIN); -TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL, TWL4030_PREDR_GAIN); -TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL, TWL4030_PRECKL_GAIN); -TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL, TWL4030_PRECKR_GAIN); - -static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp) -{ - unsigned char hs_ctl; - - hs_ctl = twl4030_read_reg_cache(codec, reg); - - if (ramp) { - /* HF ramp-up */ - hs_ctl |= TWL4030_HF_CTL_REF_EN; - twl4030_write(codec, reg, hs_ctl); - udelay(10); - hs_ctl |= TWL4030_HF_CTL_RAMP_EN; - twl4030_write(codec, reg, hs_ctl); - udelay(40); - hs_ctl |= TWL4030_HF_CTL_LOOP_EN; - hs_ctl |= TWL4030_HF_CTL_HB_EN; - twl4030_write(codec, reg, hs_ctl); - } else { - /* HF ramp-down */ - hs_ctl &= ~TWL4030_HF_CTL_LOOP_EN; - hs_ctl &= ~TWL4030_HF_CTL_HB_EN; - twl4030_write(codec, reg, hs_ctl); - hs_ctl &= ~TWL4030_HF_CTL_RAMP_EN; - twl4030_write(codec, reg, hs_ctl); - udelay(40); - hs_ctl &= ~TWL4030_HF_CTL_REF_EN; - twl4030_write(codec, reg, hs_ctl); - } -} - -static int handsfreelpga_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - switch (event) { - case SND_SOC_DAPM_POST_PMU: - handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 1); - break; - case SND_SOC_DAPM_POST_PMD: - handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 0); - break; - } - return 0; -} - -static int handsfreerpga_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - switch (event) { - case SND_SOC_DAPM_POST_PMU: - handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 1); - break; - case SND_SOC_DAPM_POST_PMD: - handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 0); - break; - } - return 0; -} - -static int vibramux_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff); - return 0; -} - -static int apll_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - twl4030_apll_enable(w->codec, 1); - break; - case SND_SOC_DAPM_POST_PMD: - twl4030_apll_enable(w->codec, 0); - break; - } - return 0; -} - -static int aif_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - u8 audio_if; - - audio_if = twl4030_read_reg_cache(w->codec, TWL4030_REG_AUDIO_IF); - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - /* Enable AIF */ - /* enable the PLL before we use it to clock the DAI */ - twl4030_apll_enable(w->codec, 1); - - twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, - audio_if | TWL4030_AIF_EN); - break; - case SND_SOC_DAPM_POST_PMD: - /* disable the DAI before we stop it's source PLL */ - twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, - audio_if & ~TWL4030_AIF_EN); - twl4030_apll_enable(w->codec, 0); - break; - } - return 0; -} - -static void headset_ramp(struct snd_soc_codec *codec, int ramp) -{ - struct twl4030_codec_data *pdata = codec->dev->platform_data; - unsigned char hs_gain, hs_pop; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - /* Base values for ramp delay calculation: 2^19 - 2^26 */ - unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, - 8388608, 16777216, 33554432, 67108864}; - unsigned int delay; - - hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); - hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / - twl4030->sysclk) + 1; - - /* Enable external mute control, this dramatically reduces - * the pop-noise */ - if (pdata && pdata->hs_extmute) { - if (pdata->set_hs_extmute) { - pdata->set_hs_extmute(1); - } else { - hs_pop |= TWL4030_EXTMUTE; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - } - } - - if (ramp) { - /* Headset ramp-up according to the TRM */ - hs_pop |= TWL4030_VMID_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - /* Actually write to the register */ - twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, - hs_gain, - TWL4030_REG_HS_GAIN_SET); - hs_pop |= TWL4030_RAMP_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - /* Wait ramp delay time + 1, so the VMID can settle */ - twl4030_wait_ms(delay); - } else { - /* Headset ramp-down _not_ according to - * the TRM, but in a way that it is working */ - hs_pop &= ~TWL4030_RAMP_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - /* Wait ramp delay time + 1, so the VMID can settle */ - twl4030_wait_ms(delay); - /* Bypass the reg_cache to mute the headset */ - twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, - hs_gain & (~0x0f), - TWL4030_REG_HS_GAIN_SET); - - hs_pop &= ~TWL4030_VMID_EN; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - } - - /* Disable external mute */ - if (pdata && pdata->hs_extmute) { - if (pdata->set_hs_extmute) { - pdata->set_hs_extmute(0); - } else { - hs_pop &= ~TWL4030_EXTMUTE; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - } - } -} - -static int headsetlpga_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - /* Do the ramp-up only once */ - if (!twl4030->hsr_enabled) - headset_ramp(w->codec, 1); - - twl4030->hsl_enabled = 1; - break; - case SND_SOC_DAPM_POST_PMD: - /* Do the ramp-down only if both headsetL/R is disabled */ - if (!twl4030->hsr_enabled) - headset_ramp(w->codec, 0); - - twl4030->hsl_enabled = 0; - break; - } - return 0; -} - -static int headsetrpga_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - /* Do the ramp-up only once */ - if (!twl4030->hsl_enabled) - headset_ramp(w->codec, 1); - - twl4030->hsr_enabled = 1; - break; - case SND_SOC_DAPM_POST_PMD: - /* Do the ramp-down only if both headsetL/R is disabled */ - if (!twl4030->hsl_enabled) - headset_ramp(w->codec, 0); - - twl4030->hsr_enabled = 0; - break; - } - return 0; -} - -static int digimic_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); - - if (twl4030->digimic_delay) - twl4030_wait_ms(twl4030->digimic_delay); - return 0; -} - -/* - * Some of the gain controls in TWL (mostly those which are associated with - * the outputs) are implemented in an interesting way: - * 0x0 : Power down (mute) - * 0x1 : 6dB - * 0x2 : 0 dB - * 0x3 : -6 dB - * Inverting not going to help with these. - * Custom volsw and volsw_2r get/put functions to handle these gain bits. - */ -static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int rshift = mc->rshift; - int max = mc->max; - int mask = (1 << fls(max)) - 1; - - ucontrol->value.integer.value[0] = - (snd_soc_read(codec, reg) >> shift) & mask; - if (ucontrol->value.integer.value[0]) - ucontrol->value.integer.value[0] = - max + 1 - ucontrol->value.integer.value[0]; - - if (shift != rshift) { - ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg) >> rshift) & mask; - if (ucontrol->value.integer.value[1]) - ucontrol->value.integer.value[1] = - max + 1 - ucontrol->value.integer.value[1]; - } - - return 0; -} - -static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int rshift = mc->rshift; - int max = mc->max; - int mask = (1 << fls(max)) - 1; - unsigned short val, val2, val_mask; - - val = (ucontrol->value.integer.value[0] & mask); - - val_mask = mask << shift; - if (val) - val = max + 1 - val; - val = val << shift; - if (shift != rshift) { - val2 = (ucontrol->value.integer.value[1] & mask); - val_mask |= mask << rshift; - if (val2) - val2 = max + 1 - val2; - val |= val2 << rshift; - } - return snd_soc_update_bits(codec, reg, val_mask, val); -} - -static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - int max = mc->max; - int mask = (1<value.integer.value[0] = - (snd_soc_read(codec, reg) >> shift) & mask; - ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg2) >> shift) & mask; - - if (ucontrol->value.integer.value[0]) - ucontrol->value.integer.value[0] = - max + 1 - ucontrol->value.integer.value[0]; - if (ucontrol->value.integer.value[1]) - ucontrol->value.integer.value[1] = - max + 1 - ucontrol->value.integer.value[1]; - - return 0; -} - -static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - int max = mc->max; - int mask = (1 << fls(max)) - 1; - int err; - unsigned short val, val2, val_mask; - - val_mask = mask << shift; - val = (ucontrol->value.integer.value[0] & mask); - val2 = (ucontrol->value.integer.value[1] & mask); - - if (val) - val = max + 1 - val; - if (val2) - val2 = max + 1 - val2; - - val = val << shift; - val2 = val2 << shift; - - err = snd_soc_update_bits(codec, reg, val_mask, val); - if (err < 0) - return err; - - err = snd_soc_update_bits(codec, reg2, val_mask, val2); - return err; -} - -/* Codec operation modes */ -static const char *twl4030_op_modes_texts[] = { - "Option 2 (voice/audio)", "Option 1 (audio)" -}; - -static const struct soc_enum twl4030_op_modes_enum = - SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0, - ARRAY_SIZE(twl4030_op_modes_texts), - twl4030_op_modes_texts); - -static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned short val; - unsigned short mask, bitmask; - - if (twl4030->configured) { - dev_err(codec->dev, - "operation mode cannot be changed on-the-fly\n"); - return -EBUSY; - } - - for (bitmask = 1; bitmask < e->max; bitmask <<= 1) - ; - if (ucontrol->value.enumerated.item[0] > e->max - 1) - return -EINVAL; - - val = ucontrol->value.enumerated.item[0] << e->shift_l; - mask = (bitmask - 1) << e->shift_l; - if (e->shift_l != e->shift_r) { - if (ucontrol->value.enumerated.item[1] > e->max - 1) - return -EINVAL; - val |= ucontrol->value.enumerated.item[1] << e->shift_r; - mask |= (bitmask - 1) << e->shift_r; - } - - return snd_soc_update_bits(codec, e->reg, mask, val); -} - -/* - * FGAIN volume control: - * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB) - */ -static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1); - -/* - * CGAIN volume control: - * 0 dB to 12 dB in 6 dB steps - * value 2 and 3 means 12 dB - */ -static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0); - -/* - * Voice Downlink GAIN volume control: - * from -37 to 12 dB in 1 dB steps (mute instead of -37 dB) - */ -static DECLARE_TLV_DB_SCALE(digital_voice_downlink_tlv, -3700, 100, 1); - -/* - * Analog playback gain - * -24 dB to 12 dB in 2 dB steps - */ -static DECLARE_TLV_DB_SCALE(analog_tlv, -2400, 200, 0); - -/* - * Gain controls tied to outputs - * -6 dB to 6 dB in 6 dB steps (mute instead of -12) - */ -static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1); - -/* - * Gain control for earpiece amplifier - * 0 dB to 12 dB in 6 dB steps (mute instead of -6) - */ -static DECLARE_TLV_DB_SCALE(output_ear_tvl, -600, 600, 1); - -/* - * Capture gain after the ADCs - * from 0 dB to 31 dB in 1 dB steps - */ -static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0); - -/* - * Gain control for input amplifiers - * 0 dB to 30 dB in 6 dB steps - */ -static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); - -/* AVADC clock priority */ -static const char *twl4030_avadc_clk_priority_texts[] = { - "Voice high priority", "HiFi high priority" -}; - -static const struct soc_enum twl4030_avadc_clk_priority_enum = - SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2, - ARRAY_SIZE(twl4030_avadc_clk_priority_texts), - twl4030_avadc_clk_priority_texts); - -static const char *twl4030_rampdelay_texts[] = { - "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", - "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms", - "3495/2581/1748 ms" -}; - -static const struct soc_enum twl4030_rampdelay_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2, - ARRAY_SIZE(twl4030_rampdelay_texts), - twl4030_rampdelay_texts); - -/* Vibra H-bridge direction mode */ -static const char *twl4030_vibradirmode_texts[] = { - "Vibra H-bridge direction", "Audio data MSB", -}; - -static const struct soc_enum twl4030_vibradirmode_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 5, - ARRAY_SIZE(twl4030_vibradirmode_texts), - twl4030_vibradirmode_texts); - -/* Vibra H-bridge direction */ -static const char *twl4030_vibradir_texts[] = { - "Positive polarity", "Negative polarity", -}; - -static const struct soc_enum twl4030_vibradir_enum = - SOC_ENUM_SINGLE(TWL4030_REG_VIBRA_CTL, 1, - ARRAY_SIZE(twl4030_vibradir_texts), - twl4030_vibradir_texts); - -/* Digimic Left and right swapping */ -static const char *twl4030_digimicswap_texts[] = { - "Not swapped", "Swapped", -}; - -static const struct soc_enum twl4030_digimicswap_enum = - SOC_ENUM_SINGLE(TWL4030_REG_MISC_SET_1, 0, - ARRAY_SIZE(twl4030_digimicswap_texts), - twl4030_digimicswap_texts); - -static const struct snd_kcontrol_new twl4030_snd_controls[] = { - /* Codec operation mode control */ - SOC_ENUM_EXT("Codec Operation Mode", twl4030_op_modes_enum, - snd_soc_get_enum_double, - snd_soc_put_twl4030_opmode_enum_double), - - /* Common playback gain controls */ - SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", - TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, - 0, 0x3f, 0, digital_fine_tlv), - SOC_DOUBLE_R_TLV("DAC2 Digital Fine Playback Volume", - TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA, - 0, 0x3f, 0, digital_fine_tlv), - - SOC_DOUBLE_R_TLV("DAC1 Digital Coarse Playback Volume", - TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, - 6, 0x2, 0, digital_coarse_tlv), - SOC_DOUBLE_R_TLV("DAC2 Digital Coarse Playback Volume", - TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA, - 6, 0x2, 0, digital_coarse_tlv), - - SOC_DOUBLE_R_TLV("DAC1 Analog Playback Volume", - TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL, - 3, 0x12, 1, analog_tlv), - SOC_DOUBLE_R_TLV("DAC2 Analog Playback Volume", - TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL, - 3, 0x12, 1, analog_tlv), - SOC_DOUBLE_R("DAC1 Analog Playback Switch", - TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL, - 1, 1, 0), - SOC_DOUBLE_R("DAC2 Analog Playback Switch", - TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL, - 1, 1, 0), - - /* Common voice downlink gain controls */ - SOC_SINGLE_TLV("DAC Voice Digital Downlink Volume", - TWL4030_REG_VRXPGA, 0, 0x31, 0, digital_voice_downlink_tlv), - - SOC_SINGLE_TLV("DAC Voice Analog Downlink Volume", - TWL4030_REG_VDL_APGA_CTL, 3, 0x12, 1, analog_tlv), - - SOC_SINGLE("DAC Voice Analog Downlink Switch", - TWL4030_REG_VDL_APGA_CTL, 1, 1, 0), - - /* Separate output gain controls */ - SOC_DOUBLE_R_EXT_TLV("PreDriv Playback Volume", - TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL, - 4, 3, 0, snd_soc_get_volsw_r2_twl4030, - snd_soc_put_volsw_r2_twl4030, output_tvl), - - SOC_DOUBLE_EXT_TLV("Headset Playback Volume", - TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, snd_soc_get_volsw_twl4030, - snd_soc_put_volsw_twl4030, output_tvl), - - SOC_DOUBLE_R_EXT_TLV("Carkit Playback Volume", - TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL, - 4, 3, 0, snd_soc_get_volsw_r2_twl4030, - snd_soc_put_volsw_r2_twl4030, output_tvl), - - SOC_SINGLE_EXT_TLV("Earpiece Playback Volume", - TWL4030_REG_EAR_CTL, 4, 3, 0, snd_soc_get_volsw_twl4030, - snd_soc_put_volsw_twl4030, output_ear_tvl), - - /* Common capture gain controls */ - SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume", - TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA, - 0, 0x1f, 0, digital_capture_tlv), - SOC_DOUBLE_R_TLV("TX2 Digital Capture Volume", - TWL4030_REG_AVTXL2PGA, TWL4030_REG_AVTXR2PGA, - 0, 0x1f, 0, digital_capture_tlv), - - SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, - 0, 3, 5, 0, input_gain_tlv), - - SOC_ENUM("AVADC Clock Priority", twl4030_avadc_clk_priority_enum), - - SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), - - SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum), - SOC_ENUM("Vibra H-bridge direction", twl4030_vibradir_enum), - - SOC_ENUM("Digimic LR Swap", twl4030_digimicswap_enum), -}; - -static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { - /* Left channel inputs */ - SND_SOC_DAPM_INPUT("MAINMIC"), - SND_SOC_DAPM_INPUT("HSMIC"), - SND_SOC_DAPM_INPUT("AUXL"), - SND_SOC_DAPM_INPUT("CARKITMIC"), - /* Right channel inputs */ - SND_SOC_DAPM_INPUT("SUBMIC"), - SND_SOC_DAPM_INPUT("AUXR"), - /* Digital microphones (Stereo) */ - SND_SOC_DAPM_INPUT("DIGIMIC0"), - SND_SOC_DAPM_INPUT("DIGIMIC1"), - - /* Outputs */ - SND_SOC_DAPM_OUTPUT("EARPIECE"), - SND_SOC_DAPM_OUTPUT("PREDRIVEL"), - SND_SOC_DAPM_OUTPUT("PREDRIVER"), - SND_SOC_DAPM_OUTPUT("HSOL"), - SND_SOC_DAPM_OUTPUT("HSOR"), - SND_SOC_DAPM_OUTPUT("CARKITL"), - SND_SOC_DAPM_OUTPUT("CARKITR"), - SND_SOC_DAPM_OUTPUT("HFL"), - SND_SOC_DAPM_OUTPUT("HFR"), - SND_SOC_DAPM_OUTPUT("VIBRA"), - - /* AIF and APLL clocks for running DAIs (including loopback) */ - SND_SOC_DAPM_OUTPUT("Virtual HiFi OUT"), - SND_SOC_DAPM_INPUT("Virtual HiFi IN"), - SND_SOC_DAPM_OUTPUT("Virtual Voice OUT"), - - /* DACs */ - SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Left1", "Left Front HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Right2", "Right Rear HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Left2", "Left Rear HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback", - SND_SOC_NOPM, 0, 0), - - /* Analog bypasses */ - SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_abypassr1_control), - SND_SOC_DAPM_SWITCH("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_abypassl1_control), - SND_SOC_DAPM_SWITCH("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_abypassr2_control), - SND_SOC_DAPM_SWITCH("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_abypassl2_control), - SND_SOC_DAPM_SWITCH("Voice Analog Loopback", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_abypassv_control), - - /* Master analog loopback switch */ - SND_SOC_DAPM_SUPPLY("FM Loop Enable", TWL4030_REG_MISC_SET_1, 5, 0, - NULL, 0), - - /* Digital bypasses */ - SND_SOC_DAPM_SWITCH("Left Digital Loopback", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_dbypassl_control), - SND_SOC_DAPM_SWITCH("Right Digital Loopback", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_dbypassr_control), - SND_SOC_DAPM_SWITCH("Voice Digital Loopback", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_dbypassv_control), - - /* Digital mixers, power control for the physical DACs */ - SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer", - TWL4030_REG_AVDAC_CTL, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Digital L1 Playback Mixer", - TWL4030_REG_AVDAC_CTL, 1, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Digital R2 Playback Mixer", - TWL4030_REG_AVDAC_CTL, 2, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Digital L2 Playback Mixer", - TWL4030_REG_AVDAC_CTL, 3, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Digital Voice Playback Mixer", - TWL4030_REG_AVDAC_CTL, 4, 0, NULL, 0), - - /* Analog mixers, power control for the physical PGAs */ - SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", - TWL4030_REG_ARXR1_APGA_CTL, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", - TWL4030_REG_ARXL1_APGA_CTL, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Analog R2 Playback Mixer", - TWL4030_REG_ARXR2_APGA_CTL, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Analog L2 Playback Mixer", - TWL4030_REG_ARXL2_APGA_CTL, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer", - TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0), - - SND_SOC_DAPM_SUPPLY("APLL Enable", SND_SOC_NOPM, 0, 0, apll_event, - SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_SUPPLY("AIF Enable", SND_SOC_NOPM, 0, 0, aif_event, - SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD), - - /* Output MIXER controls */ - /* Earpiece */ - SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_earpiece_controls[0], - ARRAY_SIZE(twl4030_dapm_earpiece_controls)), - SND_SOC_DAPM_PGA_E("Earpiece PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, earpiecepga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - /* PreDrivL/R */ - SND_SOC_DAPM_MIXER("PredriveL Mixer", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_predrivel_controls[0], - ARRAY_SIZE(twl4030_dapm_predrivel_controls)), - SND_SOC_DAPM_PGA_E("PredriveL PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, predrivelpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_MIXER("PredriveR Mixer", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_predriver_controls[0], - ARRAY_SIZE(twl4030_dapm_predriver_controls)), - SND_SOC_DAPM_PGA_E("PredriveR PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, predriverpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - /* HeadsetL/R */ - SND_SOC_DAPM_MIXER("HeadsetL Mixer", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_hsol_controls[0], - ARRAY_SIZE(twl4030_dapm_hsol_controls)), - SND_SOC_DAPM_PGA_E("HeadsetL PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, headsetlpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_MIXER("HeadsetR Mixer", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_hsor_controls[0], - ARRAY_SIZE(twl4030_dapm_hsor_controls)), - SND_SOC_DAPM_PGA_E("HeadsetR PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, headsetrpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - /* CarkitL/R */ - SND_SOC_DAPM_MIXER("CarkitL Mixer", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_carkitl_controls[0], - ARRAY_SIZE(twl4030_dapm_carkitl_controls)), - SND_SOC_DAPM_PGA_E("CarkitL PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, carkitlpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_MIXER("CarkitR Mixer", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_carkitr_controls[0], - ARRAY_SIZE(twl4030_dapm_carkitr_controls)), - SND_SOC_DAPM_PGA_E("CarkitR PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, carkitrpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - - /* Output MUX controls */ - /* HandsfreeL/R */ - SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_handsfreel_control), - SND_SOC_DAPM_SWITCH("HandsfreeL", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_handsfreelmute_control), - SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, handsfreelpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0, - &twl4030_dapm_handsfreer_control), - SND_SOC_DAPM_SWITCH("HandsfreeR", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_handsfreermute_control), - SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, handsfreerpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), - /* Vibra */ - SND_SOC_DAPM_MUX_E("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, - &twl4030_dapm_vibra_control, vibramux_event, - SND_SOC_DAPM_PRE_PMU), - SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_vibrapath_control), - - /* Introducing four virtual ADC, since TWL4030 have four channel for - capture */ - SND_SOC_DAPM_ADC("ADC Virtual Left1", "Left Front Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Right1", "Right Front Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Left2", "Left Rear Capture", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC Virtual Right2", "Right Rear Capture", - SND_SOC_NOPM, 0, 0), - - /* Analog/Digital mic path selection. - TX1 Left/Right: either analog Left/Right or Digimic0 - TX2 Left/Right: either analog Left/Right or Digimic1 */ - SND_SOC_DAPM_MUX("TX1 Capture Route", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_micpathtx1_control), - SND_SOC_DAPM_MUX("TX2 Capture Route", SND_SOC_NOPM, 0, 0, - &twl4030_dapm_micpathtx2_control), - - /* Analog input mixers for the capture amplifiers */ - SND_SOC_DAPM_MIXER("Analog Left", - TWL4030_REG_ANAMICL, 4, 0, - &twl4030_dapm_analoglmic_controls[0], - ARRAY_SIZE(twl4030_dapm_analoglmic_controls)), - SND_SOC_DAPM_MIXER("Analog Right", - TWL4030_REG_ANAMICR, 4, 0, - &twl4030_dapm_analogrmic_controls[0], - ARRAY_SIZE(twl4030_dapm_analogrmic_controls)), - - SND_SOC_DAPM_PGA("ADC Physical Left", - TWL4030_REG_AVADC_CTL, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("ADC Physical Right", - TWL4030_REG_AVADC_CTL, 1, 0, NULL, 0), - - SND_SOC_DAPM_PGA_E("Digimic0 Enable", - TWL4030_REG_ADCMICSEL, 1, 0, NULL, 0, - digimic_event, SND_SOC_DAPM_POST_PMU), - SND_SOC_DAPM_PGA_E("Digimic1 Enable", - TWL4030_REG_ADCMICSEL, 3, 0, NULL, 0, - digimic_event, SND_SOC_DAPM_POST_PMU), - - SND_SOC_DAPM_SUPPLY("micbias1 select", TWL4030_REG_MICBIAS_CTL, 5, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("micbias2 select", TWL4030_REG_MICBIAS_CTL, 6, 0, - NULL, 0), - - SND_SOC_DAPM_MICBIAS("Mic Bias 1", TWL4030_REG_MICBIAS_CTL, 0, 0), - SND_SOC_DAPM_MICBIAS("Mic Bias 2", TWL4030_REG_MICBIAS_CTL, 1, 0), - SND_SOC_DAPM_MICBIAS("Headset Mic Bias", TWL4030_REG_MICBIAS_CTL, 2, 0), - -}; - -static const struct snd_soc_dapm_route intercon[] = { - {"Digital L1 Playback Mixer", NULL, "DAC Left1"}, - {"Digital R1 Playback Mixer", NULL, "DAC Right1"}, - {"Digital L2 Playback Mixer", NULL, "DAC Left2"}, - {"Digital R2 Playback Mixer", NULL, "DAC Right2"}, - {"Digital Voice Playback Mixer", NULL, "DAC Voice"}, - - /* Supply for the digital part (APLL) */ - {"Digital Voice Playback Mixer", NULL, "APLL Enable"}, - - {"DAC Left1", NULL, "AIF Enable"}, - {"DAC Right1", NULL, "AIF Enable"}, - {"DAC Left2", NULL, "AIF Enable"}, - {"DAC Right1", NULL, "AIF Enable"}, - - {"Digital R2 Playback Mixer", NULL, "AIF Enable"}, - {"Digital L2 Playback Mixer", NULL, "AIF Enable"}, - - {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"}, - {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"}, - {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"}, - {"Analog R2 Playback Mixer", NULL, "Digital R2 Playback Mixer"}, - {"Analog Voice Playback Mixer", NULL, "Digital Voice Playback Mixer"}, - - /* Internal playback routings */ - /* Earpiece */ - {"Earpiece Mixer", "Voice", "Analog Voice Playback Mixer"}, - {"Earpiece Mixer", "AudioL1", "Analog L1 Playback Mixer"}, - {"Earpiece Mixer", "AudioL2", "Analog L2 Playback Mixer"}, - {"Earpiece Mixer", "AudioR1", "Analog R1 Playback Mixer"}, - {"Earpiece PGA", NULL, "Earpiece Mixer"}, - /* PreDrivL */ - {"PredriveL Mixer", "Voice", "Analog Voice Playback Mixer"}, - {"PredriveL Mixer", "AudioL1", "Analog L1 Playback Mixer"}, - {"PredriveL Mixer", "AudioL2", "Analog L2 Playback Mixer"}, - {"PredriveL Mixer", "AudioR2", "Analog R2 Playback Mixer"}, - {"PredriveL PGA", NULL, "PredriveL Mixer"}, - /* PreDrivR */ - {"PredriveR Mixer", "Voice", "Analog Voice Playback Mixer"}, - {"PredriveR Mixer", "AudioR1", "Analog R1 Playback Mixer"}, - {"PredriveR Mixer", "AudioR2", "Analog R2 Playback Mixer"}, - {"PredriveR Mixer", "AudioL2", "Analog L2 Playback Mixer"}, - {"PredriveR PGA", NULL, "PredriveR Mixer"}, - /* HeadsetL */ - {"HeadsetL Mixer", "Voice", "Analog Voice Playback Mixer"}, - {"HeadsetL Mixer", "AudioL1", "Analog L1 Playback Mixer"}, - {"HeadsetL Mixer", "AudioL2", "Analog L2 Playback Mixer"}, - {"HeadsetL PGA", NULL, "HeadsetL Mixer"}, - /* HeadsetR */ - {"HeadsetR Mixer", "Voice", "Analog Voice Playback Mixer"}, - {"HeadsetR Mixer", "AudioR1", "Analog R1 Playback Mixer"}, - {"HeadsetR Mixer", "AudioR2", "Analog R2 Playback Mixer"}, - {"HeadsetR PGA", NULL, "HeadsetR Mixer"}, - /* CarkitL */ - {"CarkitL Mixer", "Voice", "Analog Voice Playback Mixer"}, - {"CarkitL Mixer", "AudioL1", "Analog L1 Playback Mixer"}, - {"CarkitL Mixer", "AudioL2", "Analog L2 Playback Mixer"}, - {"CarkitL PGA", NULL, "CarkitL Mixer"}, - /* CarkitR */ - {"CarkitR Mixer", "Voice", "Analog Voice Playback Mixer"}, - {"CarkitR Mixer", "AudioR1", "Analog R1 Playback Mixer"}, - {"CarkitR Mixer", "AudioR2", "Analog R2 Playback Mixer"}, - {"CarkitR PGA", NULL, "CarkitR Mixer"}, - /* HandsfreeL */ - {"HandsfreeL Mux", "Voice", "Analog Voice Playback Mixer"}, - {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"}, - {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"}, - {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"}, - {"HandsfreeL", "Switch", "HandsfreeL Mux"}, - {"HandsfreeL PGA", NULL, "HandsfreeL"}, - /* HandsfreeR */ - {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"}, - {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"}, - {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"}, - {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"}, - {"HandsfreeR", "Switch", "HandsfreeR Mux"}, - {"HandsfreeR PGA", NULL, "HandsfreeR"}, - /* Vibra */ - {"Vibra Mux", "AudioL1", "DAC Left1"}, - {"Vibra Mux", "AudioR1", "DAC Right1"}, - {"Vibra Mux", "AudioL2", "DAC Left2"}, - {"Vibra Mux", "AudioR2", "DAC Right2"}, - - /* outputs */ - /* Must be always connected (for AIF and APLL) */ - {"Virtual HiFi OUT", NULL, "DAC Left1"}, - {"Virtual HiFi OUT", NULL, "DAC Right1"}, - {"Virtual HiFi OUT", NULL, "DAC Left2"}, - {"Virtual HiFi OUT", NULL, "DAC Right2"}, - /* Must be always connected (for APLL) */ - {"Virtual Voice OUT", NULL, "Digital Voice Playback Mixer"}, - /* Physical outputs */ - {"EARPIECE", NULL, "Earpiece PGA"}, - {"PREDRIVEL", NULL, "PredriveL PGA"}, - {"PREDRIVER", NULL, "PredriveR PGA"}, - {"HSOL", NULL, "HeadsetL PGA"}, - {"HSOR", NULL, "HeadsetR PGA"}, - {"CARKITL", NULL, "CarkitL PGA"}, - {"CARKITR", NULL, "CarkitR PGA"}, - {"HFL", NULL, "HandsfreeL PGA"}, - {"HFR", NULL, "HandsfreeR PGA"}, - {"Vibra Route", "Audio", "Vibra Mux"}, - {"VIBRA", NULL, "Vibra Route"}, - - /* Capture path */ - /* Must be always connected (for AIF and APLL) */ - {"ADC Virtual Left1", NULL, "Virtual HiFi IN"}, - {"ADC Virtual Right1", NULL, "Virtual HiFi IN"}, - {"ADC Virtual Left2", NULL, "Virtual HiFi IN"}, - {"ADC Virtual Right2", NULL, "Virtual HiFi IN"}, - /* Physical inputs */ - {"Analog Left", "Main Mic Capture Switch", "MAINMIC"}, - {"Analog Left", "Headset Mic Capture Switch", "HSMIC"}, - {"Analog Left", "AUXL Capture Switch", "AUXL"}, - {"Analog Left", "Carkit Mic Capture Switch", "CARKITMIC"}, - - {"Analog Right", "Sub Mic Capture Switch", "SUBMIC"}, - {"Analog Right", "AUXR Capture Switch", "AUXR"}, - - {"ADC Physical Left", NULL, "Analog Left"}, - {"ADC Physical Right", NULL, "Analog Right"}, - - {"Digimic0 Enable", NULL, "DIGIMIC0"}, - {"Digimic1 Enable", NULL, "DIGIMIC1"}, - - {"DIGIMIC0", NULL, "micbias1 select"}, - {"DIGIMIC1", NULL, "micbias2 select"}, - - /* TX1 Left capture path */ - {"TX1 Capture Route", "Analog", "ADC Physical Left"}, - {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, - /* TX1 Right capture path */ - {"TX1 Capture Route", "Analog", "ADC Physical Right"}, - {"TX1 Capture Route", "Digimic0", "Digimic0 Enable"}, - /* TX2 Left capture path */ - {"TX2 Capture Route", "Analog", "ADC Physical Left"}, - {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, - /* TX2 Right capture path */ - {"TX2 Capture Route", "Analog", "ADC Physical Right"}, - {"TX2 Capture Route", "Digimic1", "Digimic1 Enable"}, - - {"ADC Virtual Left1", NULL, "TX1 Capture Route"}, - {"ADC Virtual Right1", NULL, "TX1 Capture Route"}, - {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, - {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, - - {"ADC Virtual Left1", NULL, "AIF Enable"}, - {"ADC Virtual Right1", NULL, "AIF Enable"}, - {"ADC Virtual Left2", NULL, "AIF Enable"}, - {"ADC Virtual Right2", NULL, "AIF Enable"}, - - /* Analog bypass routes */ - {"Right1 Analog Loopback", "Switch", "Analog Right"}, - {"Left1 Analog Loopback", "Switch", "Analog Left"}, - {"Right2 Analog Loopback", "Switch", "Analog Right"}, - {"Left2 Analog Loopback", "Switch", "Analog Left"}, - {"Voice Analog Loopback", "Switch", "Analog Left"}, - - /* Supply for the Analog loopbacks */ - {"Right1 Analog Loopback", NULL, "FM Loop Enable"}, - {"Left1 Analog Loopback", NULL, "FM Loop Enable"}, - {"Right2 Analog Loopback", NULL, "FM Loop Enable"}, - {"Left2 Analog Loopback", NULL, "FM Loop Enable"}, - {"Voice Analog Loopback", NULL, "FM Loop Enable"}, - - {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, - {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, - {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, - {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"}, - {"Analog Voice Playback Mixer", NULL, "Voice Analog Loopback"}, - - /* Digital bypass routes */ - {"Right Digital Loopback", "Volume", "TX1 Capture Route"}, - {"Left Digital Loopback", "Volume", "TX1 Capture Route"}, - {"Voice Digital Loopback", "Volume", "TX2 Capture Route"}, - - {"Digital R2 Playback Mixer", NULL, "Right Digital Loopback"}, - {"Digital L2 Playback Mixer", NULL, "Left Digital Loopback"}, - {"Digital Voice Playback Mixer", NULL, "Voice Digital Loopback"}, - -}; - -static int twl4030_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - twl4030_codec_enable(codec, 1); - break; - case SND_SOC_BIAS_OFF: - twl4030_codec_enable(codec, 0); - break; - } - codec->dapm.bias_level = level; - - return 0; -} - -static void twl4030_constraints(struct twl4030_priv *twl4030, - struct snd_pcm_substream *mst_substream) -{ - struct snd_pcm_substream *slv_substream; - - /* Pick the stream, which need to be constrained */ - if (mst_substream == twl4030->master_substream) - slv_substream = twl4030->slave_substream; - else if (mst_substream == twl4030->slave_substream) - slv_substream = twl4030->master_substream; - else /* This should not happen.. */ - return; - - /* Set the constraints according to the already configured stream */ - snd_pcm_hw_constraint_minmax(slv_substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - twl4030->rate, - twl4030->rate); - - snd_pcm_hw_constraint_minmax(slv_substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - twl4030->sample_bits, - twl4030->sample_bits); - - snd_pcm_hw_constraint_minmax(slv_substream->runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, - twl4030->channels, - twl4030->channels); -} - -/* In case of 4 channel mode, the RX1 L/R for playback and the TX2 L/R for - * capture has to be enabled/disabled. */ -static void twl4030_tdm_enable(struct snd_soc_codec *codec, int direction, - int enable) -{ - u8 reg, mask; - - reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION); - - if (direction == SNDRV_PCM_STREAM_PLAYBACK) - mask = TWL4030_ARXL1_VRX_EN | TWL4030_ARXR1_EN; - else - mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN; - - if (enable) - reg |= mask; - else - reg &= ~mask; - - twl4030_write(codec, TWL4030_REG_OPTION, reg); -} - -static int twl4030_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - - if (twl4030->master_substream) { - twl4030->slave_substream = substream; - /* The DAI has one configuration for playback and capture, so - * if the DAI has been already configured then constrain this - * substream to match it. */ - if (twl4030->configured) - twl4030_constraints(twl4030, twl4030->master_substream); - } else { - if (!(twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) & - TWL4030_OPTION_1)) { - /* In option2 4 channel is not supported, set the - * constraint for the first stream for channels, the - * second stream will 'inherit' this cosntraint */ - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, - 2, 2); - } - twl4030->master_substream = substream; - } - - return 0; -} - -static void twl4030_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - - if (twl4030->master_substream == substream) - twl4030->master_substream = twl4030->slave_substream; - - twl4030->slave_substream = NULL; - - /* If all streams are closed, or the remaining stream has not yet - * been configured than set the DAI as not configured. */ - if (!twl4030->master_substream) - twl4030->configured = 0; - else if (!twl4030->master_substream->runtime->channels) - twl4030->configured = 0; - - /* If the closing substream had 4 channel, do the necessary cleanup */ - if (substream->runtime->channels == 4) - twl4030_tdm_enable(codec, substream->stream, 0); -} - -static int twl4030_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - u8 mode, old_mode, format, old_format; - - /* If the substream has 4 channel, do the necessary setup */ - if (params_channels(params) == 4) { - format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); - mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); - - /* Safety check: are we in the correct operating mode and - * the interface is in TDM mode? */ - if ((mode & TWL4030_OPTION_1) && - ((format & TWL4030_AIF_FORMAT) == TWL4030_AIF_FORMAT_TDM)) - twl4030_tdm_enable(codec, substream->stream, 1); - else - return -EINVAL; - } - - if (twl4030->configured) - /* Ignoring hw_params for already configured DAI */ - return 0; - - /* bit rate */ - old_mode = twl4030_read_reg_cache(codec, - TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; - mode = old_mode & ~TWL4030_APLL_RATE; - - switch (params_rate(params)) { - case 8000: - mode |= TWL4030_APLL_RATE_8000; - break; - case 11025: - mode |= TWL4030_APLL_RATE_11025; - break; - case 12000: - mode |= TWL4030_APLL_RATE_12000; - break; - case 16000: - mode |= TWL4030_APLL_RATE_16000; - break; - case 22050: - mode |= TWL4030_APLL_RATE_22050; - break; - case 24000: - mode |= TWL4030_APLL_RATE_24000; - break; - case 32000: - mode |= TWL4030_APLL_RATE_32000; - break; - case 44100: - mode |= TWL4030_APLL_RATE_44100; - break; - case 48000: - mode |= TWL4030_APLL_RATE_48000; - break; - case 96000: - mode |= TWL4030_APLL_RATE_96000; - break; - default: - dev_err(codec->dev, "%s: unknown rate %d\n", __func__, - params_rate(params)); - return -EINVAL; - } - - /* sample size */ - old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); - format = old_format; - format &= ~TWL4030_DATA_WIDTH; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - format |= TWL4030_DATA_WIDTH_16S_16W; - break; - case SNDRV_PCM_FORMAT_S32_LE: - format |= TWL4030_DATA_WIDTH_32S_24W; - break; - default: - dev_err(codec->dev, "%s: unknown format %d\n", __func__, - params_format(params)); - return -EINVAL; - } - - if (format != old_format || mode != old_mode) { - if (twl4030->codec_powered) { - /* - * If the codec is powered, than we need to toggle the - * codec power. - */ - twl4030_codec_enable(codec, 0); - twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); - twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); - twl4030_codec_enable(codec, 1); - } else { - twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); - twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); - } - } - - /* Store the important parameters for the DAI configuration and set - * the DAI as configured */ - twl4030->configured = 1; - twl4030->rate = params_rate(params); - twl4030->sample_bits = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; - twl4030->channels = params_channels(params); - - /* If both playback and capture streams are open, and one of them - * is setting the hw parameters right now (since we are here), set - * constraints to the other stream to match the current one. */ - if (twl4030->slave_substream) - twl4030_constraints(twl4030, substream); - - return 0; -} - -static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 19200000: - case 26000000: - case 38400000: - break; - default: - dev_err(codec->dev, "Unsupported HFCLKIN: %u\n", freq); - return -EINVAL; - } - - if ((freq / 1000) != twl4030->sysclk) { - dev_err(codec->dev, - "Mismatch in HFCLKIN: %u (configured: %u)\n", - freq, twl4030->sysclk * 1000); - return -EINVAL; - } - - return 0; -} - -static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - u8 old_format, format; - - /* get format */ - old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); - format = old_format; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - format &= ~(TWL4030_AIF_SLAVE_EN); - format &= ~(TWL4030_CLK256FS_EN); - break; - case SND_SOC_DAIFMT_CBS_CFS: - format |= TWL4030_AIF_SLAVE_EN; - format |= TWL4030_CLK256FS_EN; - break; - default: - return -EINVAL; - } - - /* interface format */ - format &= ~TWL4030_AIF_FORMAT; - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - format |= TWL4030_AIF_FORMAT_CODEC; - break; - case SND_SOC_DAIFMT_DSP_A: - format |= TWL4030_AIF_FORMAT_TDM; - break; - default: - return -EINVAL; - } - - if (format != old_format) { - if (twl4030->codec_powered) { - /* - * If the codec is powered, than we need to toggle the - * codec power. - */ - twl4030_codec_enable(codec, 0); - twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); - twl4030_codec_enable(codec, 1); - } else { - twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); - } - } - - return 0; -} - -static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); - - if (tristate) - reg |= TWL4030_AIF_TRI_EN; - else - reg &= ~TWL4030_AIF_TRI_EN; - - return twl4030_write(codec, TWL4030_REG_AUDIO_IF, reg); -} - -/* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R - * (VTXL, VTXR) for uplink has to be enabled/disabled. */ -static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction, - int enable) -{ - u8 reg, mask; - - reg = twl4030_read_reg_cache(codec, TWL4030_REG_OPTION); - - if (direction == SNDRV_PCM_STREAM_PLAYBACK) - mask = TWL4030_ARXL1_VRX_EN; - else - mask = TWL4030_ATXL2_VTXL_EN | TWL4030_ATXR2_VTXR_EN; - - if (enable) - reg |= mask; - else - reg &= ~mask; - - twl4030_write(codec, TWL4030_REG_OPTION, reg); -} - -static int twl4030_voice_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - u8 mode; - - /* If the system master clock is not 26MHz, the voice PCM interface is - * not available. - */ - if (twl4030->sysclk != 26000) { - dev_err(codec->dev, - "%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n", - __func__, twl4030->sysclk); - return -EINVAL; - } - - /* If the codec mode is not option2, the voice PCM interface is not - * available. - */ - mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) - & TWL4030_OPT_MODE; - - if (mode != TWL4030_OPTION_2) { - dev_err(codec->dev, "%s: the codec mode is not option2\n", - __func__); - return -EINVAL; - } - - return 0; -} - -static void twl4030_voice_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - /* Enable voice digital filters */ - twl4030_voice_enable(codec, substream->stream, 0); -} - -static int twl4030_voice_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - u8 old_mode, mode; - - /* Enable voice digital filters */ - twl4030_voice_enable(codec, substream->stream, 1); - - /* bit rate */ - old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE) - & ~(TWL4030_CODECPDZ); - mode = old_mode; - - switch (params_rate(params)) { - case 8000: - mode &= ~(TWL4030_SEL_16K); - break; - case 16000: - mode |= TWL4030_SEL_16K; - break; - default: - dev_err(codec->dev, "%s: unknown rate %d\n", __func__, - params_rate(params)); - return -EINVAL; - } - - if (mode != old_mode) { - if (twl4030->codec_powered) { - /* - * If the codec is powered, than we need to toggle the - * codec power. - */ - twl4030_codec_enable(codec, 0); - twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); - twl4030_codec_enable(codec, 1); - } else { - twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); - } - } - - return 0; -} - -static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - - if (freq != 26000000) { - dev_err(codec->dev, - "%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n", - __func__, freq / 1000); - return -EINVAL; - } - if ((freq / 1000) != twl4030->sysclk) { - dev_err(codec->dev, - "Mismatch in HFCLKIN: %u (configured: %u)\n", - freq, twl4030->sysclk * 1000); - return -EINVAL; - } - return 0; -} - -static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - u8 old_format, format; - - /* get format */ - old_format = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF); - format = old_format; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - format &= ~(TWL4030_VIF_SLAVE_EN); - break; - case SND_SOC_DAIFMT_CBS_CFS: - format |= TWL4030_VIF_SLAVE_EN; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_NF: - format &= ~(TWL4030_VIF_FORMAT); - break; - case SND_SOC_DAIFMT_NB_IF: - format |= TWL4030_VIF_FORMAT; - break; - default: - return -EINVAL; - } - - if (format != old_format) { - if (twl4030->codec_powered) { - /* - * If the codec is powered, than we need to toggle the - * codec power. - */ - twl4030_codec_enable(codec, 0); - twl4030_write(codec, TWL4030_REG_VOICE_IF, format); - twl4030_codec_enable(codec, 1); - } else { - twl4030_write(codec, TWL4030_REG_VOICE_IF, format); - } - } - - return 0; -} - -static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF); - - if (tristate) - reg |= TWL4030_VIF_TRI_EN; - else - reg &= ~TWL4030_VIF_TRI_EN; - - return twl4030_write(codec, TWL4030_REG_VOICE_IF, reg); -} - -#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) -#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops twl4030_dai_hifi_ops = { - .startup = twl4030_startup, - .shutdown = twl4030_shutdown, - .hw_params = twl4030_hw_params, - .set_sysclk = twl4030_set_dai_sysclk, - .set_fmt = twl4030_set_dai_fmt, - .set_tristate = twl4030_set_tristate, -}; - -static const struct snd_soc_dai_ops twl4030_dai_voice_ops = { - .startup = twl4030_voice_startup, - .shutdown = twl4030_voice_shutdown, - .hw_params = twl4030_voice_hw_params, - .set_sysclk = twl4030_voice_set_dai_sysclk, - .set_fmt = twl4030_voice_set_dai_fmt, - .set_tristate = twl4030_voice_set_tristate, -}; - -static struct snd_soc_dai_driver twl4030_dai[] = { -{ - .name = "twl4030-hifi", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 2, - .channels_max = 4, - .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000, - .formats = TWL4030_FORMATS, - .sig_bits = 24,}, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 4, - .rates = TWL4030_RATES, - .formats = TWL4030_FORMATS, - .sig_bits = 24,}, - .ops = &twl4030_dai_hifi_ops, -}, -{ - .name = "twl4030-voice", - .playback = { - .stream_name = "Voice Playback", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &twl4030_dai_voice_ops, -}, -}; - -static int twl4030_soc_suspend(struct snd_soc_codec *codec) -{ - twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int twl4030_soc_resume(struct snd_soc_codec *codec) -{ - twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int twl4030_soc_probe(struct snd_soc_codec *codec) -{ - struct twl4030_priv *twl4030; - - twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); - if (twl4030 == NULL) { - dev_err(codec->dev, "Can not allocate memory\n"); - return -ENOMEM; - } - snd_soc_codec_set_drvdata(codec, twl4030); - /* Set the defaults, and power up the codec */ - twl4030->sysclk = twl4030_audio_get_mclk() / 1000; - - twl4030_init_chip(codec); - - return 0; -} - -static int twl4030_soc_remove(struct snd_soc_codec *codec) -{ - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - - /* Reset registers to their chip default before leaving */ - twl4030_reset_registers(codec); - twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); - kfree(twl4030); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { - .probe = twl4030_soc_probe, - .remove = twl4030_soc_remove, - .suspend = twl4030_soc_suspend, - .resume = twl4030_soc_resume, - .read = twl4030_read_reg_cache, - .write = twl4030_write, - .set_bias_level = twl4030_set_bias_level, - .idle_bias_off = true, - .reg_cache_size = sizeof(twl4030_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = twl4030_reg, - - .controls = twl4030_snd_controls, - .num_controls = ARRAY_SIZE(twl4030_snd_controls), - .dapm_widgets = twl4030_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), -}; - -static int __devinit twl4030_codec_probe(struct platform_device *pdev) -{ - struct twl4030_codec_data *pdata = pdev->dev.platform_data; - - if (!pdata) { - dev_err(&pdev->dev, "platform_data is missing\n"); - return -EINVAL; - } - - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, - twl4030_dai, ARRAY_SIZE(twl4030_dai)); -} - -static int __devexit twl4030_codec_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -MODULE_ALIAS("platform:twl4030-codec"); - -static struct platform_driver twl4030_codec_driver = { - .probe = twl4030_codec_probe, - .remove = __devexit_p(twl4030_codec_remove), - .driver = { - .name = "twl4030-codec", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(twl4030_codec_driver); - -MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); -MODULE_AUTHOR("Steve Sakoman"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/twl6040.c b/ANDROID_3.4.5/sound/soc/codecs/twl6040.c deleted file mode 100644 index dc7509b9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/twl6040.c +++ /dev/null @@ -1,1662 +0,0 @@ -/* - * ALSA SoC TWL6040 codec driver - * - * Author: Misael Lopez Cruz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "twl6040.h" - -#define TWL6040_RATES SNDRV_PCM_RATE_8000_96000 -#define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) - -#define TWL6040_OUTHS_0dB 0x00 -#define TWL6040_OUTHS_M30dB 0x0F -#define TWL6040_OUTHF_0dB 0x03 -#define TWL6040_OUTHF_M52dB 0x1D - -#define TWL6040_RAMP_NONE 0 -#define TWL6040_RAMP_UP 1 -#define TWL6040_RAMP_DOWN 2 - -#define TWL6040_HSL_VOL_MASK 0x0F -#define TWL6040_HSL_VOL_SHIFT 0 -#define TWL6040_HSR_VOL_MASK 0xF0 -#define TWL6040_HSR_VOL_SHIFT 4 -#define TWL6040_HF_VOL_MASK 0x1F -#define TWL6040_HF_VOL_SHIFT 0 - -/* Shadow register used by the driver */ -#define TWL6040_REG_SW_SHADOW 0x2F -#define TWL6040_CACHEREGNUM (TWL6040_REG_SW_SHADOW + 1) - -/* TWL6040_REG_SW_SHADOW (0x2F) fields */ -#define TWL6040_EAR_PATH_ENABLE 0x01 - -struct twl6040_output { - u16 active; - u16 left_vol; - u16 right_vol; - u16 left_step; - u16 right_step; - unsigned int step_delay; - u16 ramp; - struct delayed_work work; - struct completion ramp_done; -}; - -struct twl6040_jack_data { - struct snd_soc_jack *jack; - struct delayed_work work; - int report; -}; - -/* codec private data */ -struct twl6040_data { - int plug_irq; - int codec_powered; - int pll; - int pll_power_mode; - int hs_power_mode; - int hs_power_mode_locked; - unsigned int clk_in; - unsigned int sysclk; - u16 hs_left_step; - u16 hs_right_step; - u16 hf_left_step; - u16 hf_right_step; - struct twl6040_jack_data hs_jack; - struct snd_soc_codec *codec; - struct workqueue_struct *workqueue; - struct mutex mutex; - struct twl6040_output headset; - struct twl6040_output handsfree; -}; - -/* - * twl6040 register cache & default register settings - */ -static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = { - 0x00, /* not used 0x00 */ - 0x4B, /* REG_ASICID 0x01 (ro) */ - 0x00, /* REG_ASICREV 0x02 (ro) */ - 0x00, /* REG_INTID 0x03 */ - 0x00, /* REG_INTMR 0x04 */ - 0x00, /* REG_NCPCTRL 0x05 */ - 0x00, /* REG_LDOCTL 0x06 */ - 0x60, /* REG_HPPLLCTL 0x07 */ - 0x00, /* REG_LPPLLCTL 0x08 */ - 0x4A, /* REG_LPPLLDIV 0x09 */ - 0x00, /* REG_AMICBCTL 0x0A */ - 0x00, /* REG_DMICBCTL 0x0B */ - 0x00, /* REG_MICLCTL 0x0C */ - 0x00, /* REG_MICRCTL 0x0D */ - 0x00, /* REG_MICGAIN 0x0E */ - 0x1B, /* REG_LINEGAIN 0x0F */ - 0x00, /* REG_HSLCTL 0x10 */ - 0x00, /* REG_HSRCTL 0x11 */ - 0x00, /* REG_HSGAIN 0x12 */ - 0x00, /* REG_EARCTL 0x13 */ - 0x00, /* REG_HFLCTL 0x14 */ - 0x00, /* REG_HFLGAIN 0x15 */ - 0x00, /* REG_HFRCTL 0x16 */ - 0x00, /* REG_HFRGAIN 0x17 */ - 0x00, /* REG_VIBCTLL 0x18 */ - 0x00, /* REG_VIBDATL 0x19 */ - 0x00, /* REG_VIBCTLR 0x1A */ - 0x00, /* REG_VIBDATR 0x1B */ - 0x00, /* REG_HKCTL1 0x1C */ - 0x00, /* REG_HKCTL2 0x1D */ - 0x00, /* REG_GPOCTL 0x1E */ - 0x00, /* REG_ALB 0x1F */ - 0x00, /* REG_DLB 0x20 */ - 0x00, /* not used 0x21 */ - 0x00, /* not used 0x22 */ - 0x00, /* not used 0x23 */ - 0x00, /* not used 0x24 */ - 0x00, /* not used 0x25 */ - 0x00, /* not used 0x26 */ - 0x00, /* not used 0x27 */ - 0x00, /* REG_TRIM1 0x28 */ - 0x00, /* REG_TRIM2 0x29 */ - 0x00, /* REG_TRIM3 0x2A */ - 0x00, /* REG_HSOTRIM 0x2B */ - 0x00, /* REG_HFOTRIM 0x2C */ - 0x09, /* REG_ACCCTL 0x2D */ - 0x00, /* REG_STATUS 0x2E (ro) */ - - 0x00, /* REG_SW_SHADOW 0x2F - Shadow, non HW register */ -}; - -/* List of registers to be restored after power up */ -static const int twl6040_restore_list[] = { - TWL6040_REG_MICLCTL, - TWL6040_REG_MICRCTL, - TWL6040_REG_MICGAIN, - TWL6040_REG_LINEGAIN, - TWL6040_REG_HSLCTL, - TWL6040_REG_HSRCTL, - TWL6040_REG_HSGAIN, - TWL6040_REG_EARCTL, - TWL6040_REG_HFLCTL, - TWL6040_REG_HFLGAIN, - TWL6040_REG_HFRCTL, - TWL6040_REG_HFRGAIN, -}; - -/* set of rates for each pll: low-power and high-performance */ -static unsigned int lp_rates[] = { - 8000, - 11250, - 16000, - 22500, - 32000, - 44100, - 48000, - 88200, - 96000, -}; - -static unsigned int hp_rates[] = { - 8000, - 16000, - 32000, - 48000, - 96000, -}; - -static struct snd_pcm_hw_constraint_list sysclk_constraints[] = { - { .count = ARRAY_SIZE(lp_rates), .list = lp_rates, }, - { .count = ARRAY_SIZE(hp_rates), .list = hp_rates, }, -}; - -/* - * read twl6040 register cache - */ -static inline unsigned int twl6040_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *cache = codec->reg_cache; - - if (reg >= TWL6040_CACHEREGNUM) - return -EIO; - - return cache[reg]; -} - -/* - * write twl6040 register cache - */ -static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec, - u8 reg, u8 value) -{ - u8 *cache = codec->reg_cache; - - if (reg >= TWL6040_CACHEREGNUM) - return; - cache[reg] = value; -} - -/* - * read from twl6040 hardware register - */ -static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct twl6040 *twl6040 = codec->control_data; - u8 value; - - if (reg >= TWL6040_CACHEREGNUM) - return -EIO; - - if (likely(reg < TWL6040_REG_SW_SHADOW)) { - value = twl6040_reg_read(twl6040, reg); - twl6040_write_reg_cache(codec, reg, value); - } else { - value = twl6040_read_reg_cache(codec, reg); - } - - return value; -} - -/* - * write to the twl6040 register space - */ -static int twl6040_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - struct twl6040 *twl6040 = codec->control_data; - - if (reg >= TWL6040_CACHEREGNUM) - return -EIO; - - twl6040_write_reg_cache(codec, reg, value); - if (likely(reg < TWL6040_REG_SW_SHADOW)) - return twl6040_reg_write(twl6040, reg, value); - else - return 0; -} - -static void twl6040_init_chip(struct snd_soc_codec *codec) -{ - struct twl6040 *twl6040 = codec->control_data; - u8 val; - - /* Update reg_cache: ASICREV, and TRIM values */ - val = twl6040_get_revid(twl6040); - twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val); - - twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1); - twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2); - twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3); - twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM); - twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM); - - /* Change chip defaults */ - /* No imput selected for microphone amplifiers */ - twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18); - twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18); - - /* - * We need to lower the default gain values, so the ramp code - * can work correctly for the first playback. - * This reduces the pop noise heard at the first playback. - */ - twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff); - twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e); - twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d); - twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d); - twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0); -} - -static void twl6040_restore_regs(struct snd_soc_codec *codec) -{ - u8 *cache = codec->reg_cache; - int reg, i; - - for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) { - reg = twl6040_restore_list[i]; - twl6040_write(codec, reg, cache[reg]); - } -} - -/* - * Ramp HS PGA volume to minimise pops at stream startup and shutdown. - */ -static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec, - unsigned int left_step, unsigned int right_step) -{ - - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - struct twl6040_output *headset = &priv->headset; - int left_complete = 0, right_complete = 0; - u8 reg, val; - - /* left channel */ - left_step = (left_step > 0xF) ? 0xF : left_step; - reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN); - val = (~reg & TWL6040_HSL_VOL_MASK); - - if (headset->ramp == TWL6040_RAMP_UP) { - /* ramp step up */ - if (val < headset->left_vol) { - if (val + left_step > headset->left_vol) - val = headset->left_vol; - else - val += left_step; - - reg &= ~TWL6040_HSL_VOL_MASK; - twl6040_write(codec, TWL6040_REG_HSGAIN, - (reg | (~val & TWL6040_HSL_VOL_MASK))); - } else { - left_complete = 1; - } - } else if (headset->ramp == TWL6040_RAMP_DOWN) { - /* ramp step down */ - if (val > 0x0) { - if ((int)val - (int)left_step < 0) - val = 0; - else - val -= left_step; - - reg &= ~TWL6040_HSL_VOL_MASK; - twl6040_write(codec, TWL6040_REG_HSGAIN, reg | - (~val & TWL6040_HSL_VOL_MASK)); - } else { - left_complete = 1; - } - } - - /* right channel */ - right_step = (right_step > 0xF) ? 0xF : right_step; - reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN); - val = (~reg & TWL6040_HSR_VOL_MASK) >> TWL6040_HSR_VOL_SHIFT; - - if (headset->ramp == TWL6040_RAMP_UP) { - /* ramp step up */ - if (val < headset->right_vol) { - if (val + right_step > headset->right_vol) - val = headset->right_vol; - else - val += right_step; - - reg &= ~TWL6040_HSR_VOL_MASK; - twl6040_write(codec, TWL6040_REG_HSGAIN, - (reg | (~val << TWL6040_HSR_VOL_SHIFT))); - } else { - right_complete = 1; - } - } else if (headset->ramp == TWL6040_RAMP_DOWN) { - /* ramp step down */ - if (val > 0x0) { - if ((int)val - (int)right_step < 0) - val = 0; - else - val -= right_step; - - reg &= ~TWL6040_HSR_VOL_MASK; - twl6040_write(codec, TWL6040_REG_HSGAIN, - reg | (~val << TWL6040_HSR_VOL_SHIFT)); - } else { - right_complete = 1; - } - } - - return left_complete & right_complete; -} - -/* - * Ramp HF PGA volume to minimise pops at stream startup and shutdown. - */ -static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec, - unsigned int left_step, unsigned int right_step) -{ - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - struct twl6040_output *handsfree = &priv->handsfree; - int left_complete = 0, right_complete = 0; - u16 reg, val; - - /* left channel */ - left_step = (left_step > 0x1D) ? 0x1D : left_step; - reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN); - reg = 0x1D - reg; - val = (reg & TWL6040_HF_VOL_MASK); - if (handsfree->ramp == TWL6040_RAMP_UP) { - /* ramp step up */ - if (val < handsfree->left_vol) { - if (val + left_step > handsfree->left_vol) - val = handsfree->left_vol; - else - val += left_step; - - reg &= ~TWL6040_HF_VOL_MASK; - twl6040_write(codec, TWL6040_REG_HFLGAIN, - reg | (0x1D - val)); - } else { - left_complete = 1; - } - } else if (handsfree->ramp == TWL6040_RAMP_DOWN) { - /* ramp step down */ - if (val > 0) { - if ((int)val - (int)left_step < 0) - val = 0; - else - val -= left_step; - - reg &= ~TWL6040_HF_VOL_MASK; - twl6040_write(codec, TWL6040_REG_HFLGAIN, - reg | (0x1D - val)); - } else { - left_complete = 1; - } - } - - /* right channel */ - right_step = (right_step > 0x1D) ? 0x1D : right_step; - reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN); - reg = 0x1D - reg; - val = (reg & TWL6040_HF_VOL_MASK); - if (handsfree->ramp == TWL6040_RAMP_UP) { - /* ramp step up */ - if (val < handsfree->right_vol) { - if (val + right_step > handsfree->right_vol) - val = handsfree->right_vol; - else - val += right_step; - - reg &= ~TWL6040_HF_VOL_MASK; - twl6040_write(codec, TWL6040_REG_HFRGAIN, - reg | (0x1D - val)); - } else { - right_complete = 1; - } - } else if (handsfree->ramp == TWL6040_RAMP_DOWN) { - /* ramp step down */ - if (val > 0) { - if ((int)val - (int)right_step < 0) - val = 0; - else - val -= right_step; - - reg &= ~TWL6040_HF_VOL_MASK; - twl6040_write(codec, TWL6040_REG_HFRGAIN, - reg | (0x1D - val)); - } - } - - return left_complete & right_complete; -} - -/* - * This work ramps both output PGAs at stream start/stop time to - * minimise pop associated with DAPM power switching. - */ -static void twl6040_pga_hs_work(struct work_struct *work) -{ - struct twl6040_data *priv = - container_of(work, struct twl6040_data, headset.work.work); - struct snd_soc_codec *codec = priv->codec; - struct twl6040_output *headset = &priv->headset; - int i, headset_complete; - - /* do we need to ramp at all ? */ - if (headset->ramp == TWL6040_RAMP_NONE) - return; - - /* HS PGA gain range: 0x0 - 0xf (0 - 15) */ - for (i = 0; i < 16; i++) { - headset_complete = twl6040_hs_ramp_step(codec, - headset->left_step, - headset->right_step); - - /* ramp finished ? */ - if (headset_complete) - break; - - schedule_timeout_interruptible( - msecs_to_jiffies(headset->step_delay)); - } - - if (headset->ramp == TWL6040_RAMP_DOWN) { - headset->active = 0; - complete(&headset->ramp_done); - } else { - headset->active = 1; - } - headset->ramp = TWL6040_RAMP_NONE; -} - -static void twl6040_pga_hf_work(struct work_struct *work) -{ - struct twl6040_data *priv = - container_of(work, struct twl6040_data, handsfree.work.work); - struct snd_soc_codec *codec = priv->codec; - struct twl6040_output *handsfree = &priv->handsfree; - int i, handsfree_complete; - - /* do we need to ramp at all ? */ - if (handsfree->ramp == TWL6040_RAMP_NONE) - return; - - /* - * HF PGA gain range: 0x00 - 0x1d (0 - 29) */ - for (i = 0; i < 30; i++) { - handsfree_complete = twl6040_hf_ramp_step(codec, - handsfree->left_step, - handsfree->right_step); - - /* ramp finished ? */ - if (handsfree_complete) - break; - - schedule_timeout_interruptible( - msecs_to_jiffies(handsfree->step_delay)); - } - - - if (handsfree->ramp == TWL6040_RAMP_DOWN) { - handsfree->active = 0; - complete(&handsfree->ramp_done); - } else - handsfree->active = 1; - handsfree->ramp = TWL6040_RAMP_NONE; -} - -static int out_drv_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - struct twl6040_output *out; - struct delayed_work *work; - - switch (w->shift) { - case 2: /* Headset output driver */ - out = &priv->headset; - work = &out->work; - /* - * Make sure, that we do not mess up variables for already - * executing work. - */ - cancel_delayed_work_sync(work); - - out->left_step = priv->hs_left_step; - out->right_step = priv->hs_right_step; - out->step_delay = 5; /* 5 ms between volume ramp steps */ - break; - case 4: /* Handsfree output driver */ - out = &priv->handsfree; - work = &out->work; - /* - * Make sure, that we do not mess up variables for already - * executing work. - */ - cancel_delayed_work_sync(work); - - out->left_step = priv->hf_left_step; - out->right_step = priv->hf_right_step; - out->step_delay = 5; /* 5 ms between volume ramp steps */ - break; - default: - return -1; - } - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - if (out->active) - break; - - /* don't use volume ramp for power-up */ - out->ramp = TWL6040_RAMP_UP; - out->left_step = out->left_vol; - out->right_step = out->right_vol; - - queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1)); - break; - - case SND_SOC_DAPM_PRE_PMD: - if (!out->active) - break; - - /* use volume ramp for power-down */ - out->ramp = TWL6040_RAMP_DOWN; - INIT_COMPLETION(out->ramp_done); - - queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1)); - - wait_for_completion_timeout(&out->ramp_done, - msecs_to_jiffies(2000)); - break; - } - - return 0; -} - -/* set headset dac and driver power mode */ -static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) -{ - int hslctl, hsrctl; - int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE; - - hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); - hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); - - if (high_perf) { - hslctl &= ~mask; - hsrctl &= ~mask; - } else { - hslctl |= mask; - hsrctl |= mask; - } - - twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl); - twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl); - - return 0; -} - -static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u8 hslctl, hsrctl; - - /* - * Workaround for Headset DC offset caused pop noise: - * Both HS DAC need to be turned on (before the HS driver) and off at - * the same time. - */ - hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); - hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); - if (SND_SOC_DAPM_EVENT_ON(event)) { - hslctl |= TWL6040_HSDACENA; - hsrctl |= TWL6040_HSDACENA; - } else { - hslctl &= ~TWL6040_HSDACENA; - hsrctl &= ~TWL6040_HSDACENA; - } - twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl); - twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl); - - msleep(1); - return 0; -} - -static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - if (SND_SOC_DAPM_EVENT_ON(event)) { - /* Earphone doesn't support low power mode */ - priv->hs_power_mode_locked = 1; - ret = headset_power_mode(codec, 1); - } else { - priv->hs_power_mode_locked = 0; - ret = headset_power_mode(codec, priv->hs_power_mode); - } - - msleep(1); - - return ret; -} - -static void twl6040_hs_jack_report(struct snd_soc_codec *codec, - struct snd_soc_jack *jack, int report) -{ - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int status; - - mutex_lock(&priv->mutex); - - /* Sync status */ - status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS); - if (status & TWL6040_PLUGCOMP) - snd_soc_jack_report(jack, report, report); - else - snd_soc_jack_report(jack, 0, report); - - mutex_unlock(&priv->mutex); -} - -void twl6040_hs_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack, int report) -{ - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - struct twl6040_jack_data *hs_jack = &priv->hs_jack; - - hs_jack->jack = jack; - hs_jack->report = report; - - twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report); -} -EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect); - -static void twl6040_accessory_work(struct work_struct *work) -{ - struct twl6040_data *priv = container_of(work, - struct twl6040_data, hs_jack.work.work); - struct snd_soc_codec *codec = priv->codec; - struct twl6040_jack_data *hs_jack = &priv->hs_jack; - - twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report); -} - -/* audio interrupt handler */ -static irqreturn_t twl6040_audio_handler(int irq, void *data) -{ - struct snd_soc_codec *codec = data; - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - - queue_delayed_work(priv->workqueue, &priv->hs_jack.work, - msecs_to_jiffies(200)); - - return IRQ_HANDLED; -} - -static int twl6040_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec); - struct twl6040_output *out = NULL; - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int ret; - - /* For HS and HF we shadow the values and only actually write - * them out when active in order to ensure the amplifier comes on - * as quietly as possible. */ - switch (mc->reg) { - case TWL6040_REG_HSGAIN: - out = &twl6040_priv->headset; - break; - case TWL6040_REG_HFLGAIN: - out = &twl6040_priv->handsfree; - break; - default: - dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n", - __func__, mc->reg); - return -EINVAL; - } - - out->left_vol = ucontrol->value.integer.value[0]; - out->right_vol = ucontrol->value.integer.value[1]; - if (!out->active) - return 1; - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret < 0) - return ret; - - return 1; -} - -static int twl6040_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec); - struct twl6040_output *out = &twl6040_priv->headset; - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - - switch (mc->reg) { - case TWL6040_REG_HSGAIN: - out = &twl6040_priv->headset; - break; - case TWL6040_REG_HFLGAIN: - out = &twl6040_priv->handsfree; - break; - default: - dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n", - __func__, mc->reg); - return -EINVAL; - } - - ucontrol->value.integer.value[0] = out->left_vol; - ucontrol->value.integer.value[1] = out->right_vol; - return 0; -} - -static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - - /* Do not allow changes while Input/FF efect is running */ - val = twl6040_read_reg_volatile(codec, e->reg); - if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL)) - return -EBUSY; - - return snd_soc_dapm_put_enum_double(kcontrol, ucontrol); -} - -/* - * MICATT volume control: - * from -6 to 0 dB in 6 dB steps - */ -static DECLARE_TLV_DB_SCALE(mic_preamp_tlv, -600, 600, 0); - -/* - * MICGAIN volume control: - * from 6 to 30 dB in 6 dB steps - */ -static DECLARE_TLV_DB_SCALE(mic_amp_tlv, 600, 600, 0); - -/* - * AFMGAIN volume control: - * from -18 to 24 dB in 6 dB steps - */ -static DECLARE_TLV_DB_SCALE(afm_amp_tlv, -1800, 600, 0); - -/* - * HSGAIN volume control: - * from -30 to 0 dB in 2 dB steps - */ -static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0); - -/* - * HFGAIN volume control: - * from -52 to 6 dB in 2 dB steps - */ -static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0); - -/* - * EPGAIN volume control: - * from -24 to 6 dB in 2 dB steps - */ -static DECLARE_TLV_DB_SCALE(ep_tlv, -2400, 200, 0); - -/* Left analog microphone selection */ -static const char *twl6040_amicl_texts[] = - {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"}; - -/* Right analog microphone selection */ -static const char *twl6040_amicr_texts[] = - {"Headset Mic", "Sub Mic", "Aux/FM Right", "Off"}; - -static const struct soc_enum twl6040_enum[] = { - SOC_ENUM_SINGLE(TWL6040_REG_MICLCTL, 3, 4, twl6040_amicl_texts), - SOC_ENUM_SINGLE(TWL6040_REG_MICRCTL, 3, 4, twl6040_amicr_texts), -}; - -static const char *twl6040_hs_texts[] = { - "Off", "HS DAC", "Line-In amp" -}; - -static const struct soc_enum twl6040_hs_enum[] = { - SOC_ENUM_SINGLE(TWL6040_REG_HSLCTL, 5, ARRAY_SIZE(twl6040_hs_texts), - twl6040_hs_texts), - SOC_ENUM_SINGLE(TWL6040_REG_HSRCTL, 5, ARRAY_SIZE(twl6040_hs_texts), - twl6040_hs_texts), -}; - -static const char *twl6040_hf_texts[] = { - "Off", "HF DAC", "Line-In amp" -}; - -static const struct soc_enum twl6040_hf_enum[] = { - SOC_ENUM_SINGLE(TWL6040_REG_HFLCTL, 2, ARRAY_SIZE(twl6040_hf_texts), - twl6040_hf_texts), - SOC_ENUM_SINGLE(TWL6040_REG_HFRCTL, 2, ARRAY_SIZE(twl6040_hf_texts), - twl6040_hf_texts), -}; - -static const char *twl6040_vibrapath_texts[] = { - "Input FF", "Audio PDM" -}; - -static const struct soc_enum twl6040_vibra_enum[] = { - SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1, - ARRAY_SIZE(twl6040_vibrapath_texts), - twl6040_vibrapath_texts), - SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1, - ARRAY_SIZE(twl6040_vibrapath_texts), - twl6040_vibrapath_texts), -}; - -static const struct snd_kcontrol_new amicl_control = - SOC_DAPM_ENUM("Route", twl6040_enum[0]); - -static const struct snd_kcontrol_new amicr_control = - SOC_DAPM_ENUM("Route", twl6040_enum[1]); - -/* Headset DAC playback switches */ -static const struct snd_kcontrol_new hsl_mux_controls = - SOC_DAPM_ENUM("Route", twl6040_hs_enum[0]); - -static const struct snd_kcontrol_new hsr_mux_controls = - SOC_DAPM_ENUM("Route", twl6040_hs_enum[1]); - -/* Handsfree DAC playback switches */ -static const struct snd_kcontrol_new hfl_mux_controls = - SOC_DAPM_ENUM("Route", twl6040_hf_enum[0]); - -static const struct snd_kcontrol_new hfr_mux_controls = - SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]); - -static const struct snd_kcontrol_new ep_path_enable_control = - SOC_DAPM_SINGLE("Switch", TWL6040_REG_SW_SHADOW, 0, 1, 0); - -static const struct snd_kcontrol_new auxl_switch_control = - SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0); - -static const struct snd_kcontrol_new auxr_switch_control = - SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0); - -/* Vibra playback switches */ -static const struct snd_kcontrol_new vibral_mux_controls = - SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0], - snd_soc_dapm_get_enum_double, - twl6040_soc_dapm_put_vibra_enum); - -static const struct snd_kcontrol_new vibrar_mux_controls = - SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1], - snd_soc_dapm_get_enum_double, - twl6040_soc_dapm_put_vibra_enum); - -/* Headset power mode */ -static const char *twl6040_power_mode_texts[] = { - "Low-Power", "High-Perfomance", -}; - -static const struct soc_enum twl6040_power_mode_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl6040_power_mode_texts), - twl6040_power_mode_texts); - -static int twl6040_headset_power_get_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = priv->hs_power_mode; - - return 0; -} - -static int twl6040_headset_power_put_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int high_perf = ucontrol->value.enumerated.item[0]; - int ret = 0; - - if (!priv->hs_power_mode_locked) - ret = headset_power_mode(codec, high_perf); - - if (!ret) - priv->hs_power_mode = high_perf; - - return ret; -} - -static int twl6040_pll_get_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = priv->pll_power_mode; - - return 0; -} - -static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - - priv->pll_power_mode = ucontrol->value.enumerated.item[0]; - - return 0; -} - -int twl6040_get_dl1_gain(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - - if (snd_soc_dapm_get_pin_status(dapm, "EP")) - return -1; /* -1dB */ - - if (snd_soc_dapm_get_pin_status(dapm, "HSOR") || - snd_soc_dapm_get_pin_status(dapm, "HSOL")) { - - u8 val = snd_soc_read(codec, TWL6040_REG_HSLCTL); - if (val & TWL6040_HSDACMODE) - /* HSDACL in LP mode */ - return -8; /* -8dB */ - else - /* HSDACL in HP mode */ - return -1; /* -1dB */ - } - return 0; /* 0dB */ -} -EXPORT_SYMBOL_GPL(twl6040_get_dl1_gain); - -int twl6040_get_clk_id(struct snd_soc_codec *codec) -{ - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - - return priv->pll_power_mode; -} -EXPORT_SYMBOL_GPL(twl6040_get_clk_id); - -int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim) -{ - if (unlikely(trim >= TWL6040_TRIM_INVAL)) - return -EINVAL; - - return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim); -} -EXPORT_SYMBOL_GPL(twl6040_get_trim_value); - -int twl6040_get_hs_step_size(struct snd_soc_codec *codec) -{ - struct twl6040 *twl6040 = codec->control_data; - - if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_2) - /* For ES under ES_1.3 HS step is 2 mV */ - return 2; - else - /* For ES_1.3 HS step is 1 mV */ - return 1; -} -EXPORT_SYMBOL_GPL(twl6040_get_hs_step_size); - -static const struct snd_kcontrol_new twl6040_snd_controls[] = { - /* Capture gains */ - SOC_DOUBLE_TLV("Capture Preamplifier Volume", - TWL6040_REG_MICGAIN, 6, 7, 1, 1, mic_preamp_tlv), - SOC_DOUBLE_TLV("Capture Volume", - TWL6040_REG_MICGAIN, 0, 3, 4, 0, mic_amp_tlv), - - /* AFM gains */ - SOC_DOUBLE_TLV("Aux FM Volume", - TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv), - - /* Playback gains */ - SOC_DOUBLE_EXT_TLV("Headset Playback Volume", - TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, twl6040_get_volsw, - twl6040_put_volsw, hs_tlv), - SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume", - TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, - twl6040_get_volsw, twl6040_put_volsw, hf_tlv), - SOC_SINGLE_TLV("Earphone Playback Volume", - TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv), - - SOC_ENUM_EXT("Headset Power Mode", twl6040_power_mode_enum, - twl6040_headset_power_get_enum, - twl6040_headset_power_put_enum), - - SOC_ENUM_EXT("PLL Selection", twl6040_power_mode_enum, - twl6040_pll_get_enum, twl6040_pll_put_enum), -}; - -static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { - /* Inputs */ - SND_SOC_DAPM_INPUT("MAINMIC"), - SND_SOC_DAPM_INPUT("HSMIC"), - SND_SOC_DAPM_INPUT("SUBMIC"), - SND_SOC_DAPM_INPUT("AFML"), - SND_SOC_DAPM_INPUT("AFMR"), - - /* Outputs */ - SND_SOC_DAPM_OUTPUT("HSOL"), - SND_SOC_DAPM_OUTPUT("HSOR"), - SND_SOC_DAPM_OUTPUT("HFL"), - SND_SOC_DAPM_OUTPUT("HFR"), - SND_SOC_DAPM_OUTPUT("EP"), - SND_SOC_DAPM_OUTPUT("AUXL"), - SND_SOC_DAPM_OUTPUT("AUXR"), - SND_SOC_DAPM_OUTPUT("VIBRAL"), - SND_SOC_DAPM_OUTPUT("VIBRAR"), - - /* Analog input muxes for the capture amplifiers */ - SND_SOC_DAPM_MUX("Analog Left Capture Route", - SND_SOC_NOPM, 0, 0, &amicl_control), - SND_SOC_DAPM_MUX("Analog Right Capture Route", - SND_SOC_NOPM, 0, 0, &amicr_control), - - /* Analog capture PGAs */ - SND_SOC_DAPM_PGA("MicAmpL", - TWL6040_REG_MICLCTL, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("MicAmpR", - TWL6040_REG_MICRCTL, 0, 0, NULL, 0), - - /* Auxiliary FM PGAs */ - SND_SOC_DAPM_PGA("AFMAmpL", - TWL6040_REG_MICLCTL, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("AFMAmpR", - TWL6040_REG_MICRCTL, 1, 0, NULL, 0), - - /* ADCs */ - SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture", - TWL6040_REG_MICLCTL, 2, 0), - SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture", - TWL6040_REG_MICRCTL, 2, 0), - - /* Microphone bias */ - SND_SOC_DAPM_SUPPLY("Headset Mic Bias", - TWL6040_REG_AMICBCTL, 0, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Main Mic Bias", - TWL6040_REG_AMICBCTL, 4, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias", - TWL6040_REG_DMICBCTL, 0, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias", - TWL6040_REG_DMICBCTL, 4, 0, NULL, 0), - - /* DACs */ - SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback", - TWL6040_REG_HFLCTL, 0, 0), - SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback", - TWL6040_REG_HFRCTL, 0, 0), - /* Virtual DAC for vibra path (DL4 channel) */ - SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback", - SND_SOC_NOPM, 0, 0), - - SND_SOC_DAPM_MUX("Handsfree Left Playback", - SND_SOC_NOPM, 0, 0, &hfl_mux_controls), - SND_SOC_DAPM_MUX("Handsfree Right Playback", - SND_SOC_NOPM, 0, 0, &hfr_mux_controls), - /* Analog playback Muxes */ - SND_SOC_DAPM_MUX("Headset Left Playback", - SND_SOC_NOPM, 0, 0, &hsl_mux_controls), - SND_SOC_DAPM_MUX("Headset Right Playback", - SND_SOC_NOPM, 0, 0, &hsr_mux_controls), - - SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0, - &vibral_mux_controls), - SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0, - &vibrar_mux_controls), - - SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0, - &ep_path_enable_control), - SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0, - &auxl_switch_control), - SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0, - &auxr_switch_control), - - /* Analog playback drivers */ - SND_SOC_DAPM_OUT_DRV_E("HF Left Driver", - TWL6040_REG_HFLCTL, 4, 0, NULL, 0, - out_drv_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_OUT_DRV_E("HF Right Driver", - TWL6040_REG_HFRCTL, 4, 0, NULL, 0, - out_drv_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_OUT_DRV_E("HS Left Driver", - TWL6040_REG_HSLCTL, 2, 0, NULL, 0, - out_drv_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_OUT_DRV_E("HS Right Driver", - TWL6040_REG_HSRCTL, 2, 0, NULL, 0, - out_drv_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_OUT_DRV_E("Earphone Driver", - TWL6040_REG_EARCTL, 0, 0, NULL, 0, - twl6040_ep_drv_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_OUT_DRV("Vibra Left Driver", - TWL6040_REG_VIBCTLL, 0, 0, NULL, 0), - SND_SOC_DAPM_OUT_DRV("Vibra Right Driver", - TWL6040_REG_VIBCTLR, 0, 0, NULL, 0), - - SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0, - twl6040_hs_dac_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - /* Analog playback PGAs */ - SND_SOC_DAPM_PGA("HF Left PGA", - TWL6040_REG_HFLCTL, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("HF Right PGA", - TWL6040_REG_HFRCTL, 1, 0, NULL, 0), - -}; - -static const struct snd_soc_dapm_route intercon[] = { - /* Capture path */ - {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, - {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, - {"Analog Left Capture Route", "Aux/FM Left", "AFML"}, - - {"Analog Right Capture Route", "Headset Mic", "HSMIC"}, - {"Analog Right Capture Route", "Sub Mic", "SUBMIC"}, - {"Analog Right Capture Route", "Aux/FM Right", "AFMR"}, - - {"MicAmpL", NULL, "Analog Left Capture Route"}, - {"MicAmpR", NULL, "Analog Right Capture Route"}, - - {"ADC Left", NULL, "MicAmpL"}, - {"ADC Right", NULL, "MicAmpR"}, - - /* AFM path */ - {"AFMAmpL", NULL, "AFML"}, - {"AFMAmpR", NULL, "AFMR"}, - - {"HSDAC Left", NULL, "HSDAC Power"}, - {"HSDAC Right", NULL, "HSDAC Power"}, - - {"Headset Left Playback", "HS DAC", "HSDAC Left"}, - {"Headset Left Playback", "Line-In amp", "AFMAmpL"}, - - {"Headset Right Playback", "HS DAC", "HSDAC Right"}, - {"Headset Right Playback", "Line-In amp", "AFMAmpR"}, - - {"HS Left Driver", NULL, "Headset Left Playback"}, - {"HS Right Driver", NULL, "Headset Right Playback"}, - - {"HSOL", NULL, "HS Left Driver"}, - {"HSOR", NULL, "HS Right Driver"}, - - /* Earphone playback path */ - {"Earphone Playback", "Switch", "HSDAC Left"}, - {"Earphone Driver", NULL, "Earphone Playback"}, - {"EP", NULL, "Earphone Driver"}, - - {"Handsfree Left Playback", "HF DAC", "HFDAC Left"}, - {"Handsfree Left Playback", "Line-In amp", "AFMAmpL"}, - - {"Handsfree Right Playback", "HF DAC", "HFDAC Right"}, - {"Handsfree Right Playback", "Line-In amp", "AFMAmpR"}, - - {"HF Left PGA", NULL, "Handsfree Left Playback"}, - {"HF Right PGA", NULL, "Handsfree Right Playback"}, - - {"HF Left Driver", NULL, "HF Left PGA"}, - {"HF Right Driver", NULL, "HF Right PGA"}, - - {"HFL", NULL, "HF Left Driver"}, - {"HFR", NULL, "HF Right Driver"}, - - {"AUXL Playback", "Switch", "HF Left PGA"}, - {"AUXR Playback", "Switch", "HF Right PGA"}, - - {"AUXL", NULL, "AUXL Playback"}, - {"AUXR", NULL, "AUXR Playback"}, - - /* Vibrator paths */ - {"Vibra Left Playback", "Audio PDM", "VIBRA DAC"}, - {"Vibra Right Playback", "Audio PDM", "VIBRA DAC"}, - - {"Vibra Left Driver", NULL, "Vibra Left Playback"}, - {"Vibra Right Driver", NULL, "Vibra Right Playback"}, - {"Vibra Left Driver", NULL, "Vibra Left Control"}, - {"Vibra Right Driver", NULL, "Vibra Right Control"}, - - {"VIBRAL", NULL, "Vibra Left Driver"}, - {"VIBRAR", NULL, "Vibra Right Driver"}, -}; - -static int twl6040_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct twl6040 *twl6040 = codec->control_data; - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (priv->codec_powered) - break; - - ret = twl6040_power(twl6040, 1); - if (ret) - return ret; - - priv->codec_powered = 1; - - twl6040_restore_regs(codec); - - /* Set external boost GPO */ - twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); - break; - case SND_SOC_BIAS_OFF: - if (!priv->codec_powered) - break; - - twl6040_power(twl6040, 0); - priv->codec_powered = 0; - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static int twl6040_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &sysclk_constraints[priv->pll_power_mode]); - - return 0; -} - -static int twl6040_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int rate; - - rate = params_rate(params); - switch (rate) { - case 11250: - case 22500: - case 44100: - case 88200: - /* These rates are not supported when HPPLL is in use */ - if (unlikely(priv->pll == TWL6040_SYSCLK_SEL_HPPLL)) { - dev_err(codec->dev, "HPPLL does not support rate %d\n", - rate); - return -EINVAL; - } - priv->sysclk = 17640000; - break; - case 8000: - case 16000: - case 32000: - case 48000: - case 96000: - priv->sysclk = 19200000; - break; - default: - dev_err(codec->dev, "unsupported rate %d\n", rate); - return -EINVAL; - } - - return 0; -} - -static int twl6040_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct twl6040 *twl6040 = codec->control_data; - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - int ret; - - if (!priv->sysclk) { - dev_err(codec->dev, - "no mclk configured, call set_sysclk() on init\n"); - return -EINVAL; - } - - ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk); - if (ret) { - dev_err(codec->dev, "Can not set PLL (%d)\n", ret); - return -EPERM; - } - - return 0; -} - -static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case TWL6040_SYSCLK_SEL_LPPLL: - case TWL6040_SYSCLK_SEL_HPPLL: - priv->pll = clk_id; - priv->clk_in = freq; - break; - default: - dev_err(codec->dev, "unknown clk_id %d\n", clk_id); - return -EINVAL; - } - - return 0; -} - -static const struct snd_soc_dai_ops twl6040_dai_ops = { - .startup = twl6040_startup, - .hw_params = twl6040_hw_params, - .prepare = twl6040_prepare, - .set_sysclk = twl6040_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver twl6040_dai[] = { -{ - .name = "twl6040-legacy", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 5, - .rates = TWL6040_RATES, - .formats = TWL6040_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = TWL6040_RATES, - .formats = TWL6040_FORMATS, - }, - .ops = &twl6040_dai_ops, -}, -{ - .name = "twl6040-ul", - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = TWL6040_RATES, - .formats = TWL6040_FORMATS, - }, - .ops = &twl6040_dai_ops, -}, -{ - .name = "twl6040-dl1", - .playback = { - .stream_name = "Headset Playback", - .channels_min = 1, - .channels_max = 2, - .rates = TWL6040_RATES, - .formats = TWL6040_FORMATS, - }, - .ops = &twl6040_dai_ops, -}, -{ - .name = "twl6040-dl2", - .playback = { - .stream_name = "Handsfree Playback", - .channels_min = 1, - .channels_max = 2, - .rates = TWL6040_RATES, - .formats = TWL6040_FORMATS, - }, - .ops = &twl6040_dai_ops, -}, -{ - .name = "twl6040-vib", - .playback = { - .stream_name = "Vibra Playback", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .formats = TWL6040_FORMATS, - }, - .ops = &twl6040_dai_ops, -}, -}; - -#ifdef CONFIG_PM -static int twl6040_suspend(struct snd_soc_codec *codec) -{ - twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int twl6040_resume(struct snd_soc_codec *codec) -{ - twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - twl6040_set_bias_level(codec, codec->dapm.suspend_bias_level); - - return 0; -} -#else -#define twl6040_suspend NULL -#define twl6040_resume NULL -#endif - -static int twl6040_probe(struct snd_soc_codec *codec) -{ - struct twl6040_data *priv; - struct twl6040_codec_data *pdata = dev_get_platdata(codec->dev); - struct platform_device *pdev = container_of(codec->dev, - struct platform_device, dev); - int ret = 0; - - priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - snd_soc_codec_set_drvdata(codec, priv); - - priv->codec = codec; - codec->control_data = dev_get_drvdata(codec->dev->parent); - - if (pdata && pdata->hs_left_step && pdata->hs_right_step) { - priv->hs_left_step = pdata->hs_left_step; - priv->hs_right_step = pdata->hs_right_step; - } else { - priv->hs_left_step = 1; - priv->hs_right_step = 1; - } - - if (pdata && pdata->hf_left_step && pdata->hf_right_step) { - priv->hf_left_step = pdata->hf_left_step; - priv->hf_right_step = pdata->hf_right_step; - } else { - priv->hf_left_step = 1; - priv->hf_right_step = 1; - } - - priv->plug_irq = platform_get_irq(pdev, 0); - if (priv->plug_irq < 0) { - dev_err(codec->dev, "invalid irq\n"); - ret = -EINVAL; - goto work_err; - } - - priv->workqueue = alloc_workqueue("twl6040-codec", 0, 0); - if (!priv->workqueue) { - ret = -ENOMEM; - goto work_err; - } - - INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work); - INIT_DELAYED_WORK(&priv->headset.work, twl6040_pga_hs_work); - INIT_DELAYED_WORK(&priv->handsfree.work, twl6040_pga_hf_work); - - mutex_init(&priv->mutex); - - init_completion(&priv->headset.ramp_done); - init_completion(&priv->handsfree.ramp_done); - - ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler, - 0, "twl6040_irq_plug", codec); - if (ret) { - dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); - goto plugirq_err; - } - - twl6040_init_chip(codec); - - /* power on device */ - ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - if (!ret) - return 0; - - /* Error path */ - free_irq(priv->plug_irq, codec); -plugirq_err: - destroy_workqueue(priv->workqueue); -work_err: - kfree(priv); - return ret; -} - -static int twl6040_remove(struct snd_soc_codec *codec) -{ - struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); - - twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); - free_irq(priv->plug_irq, codec); - destroy_workqueue(priv->workqueue); - kfree(priv); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_twl6040 = { - .probe = twl6040_probe, - .remove = twl6040_remove, - .suspend = twl6040_suspend, - .resume = twl6040_resume, - .read = twl6040_read_reg_cache, - .write = twl6040_write, - .set_bias_level = twl6040_set_bias_level, - .reg_cache_size = ARRAY_SIZE(twl6040_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = twl6040_reg, - .ignore_pmdown_time = true, - - .controls = twl6040_snd_controls, - .num_controls = ARRAY_SIZE(twl6040_snd_controls), - .dapm_widgets = twl6040_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets), - .dapm_routes = intercon, - .num_dapm_routes = ARRAY_SIZE(intercon), -}; - -static int __devinit twl6040_codec_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl6040, - twl6040_dai, ARRAY_SIZE(twl6040_dai)); -} - -static int __devexit twl6040_codec_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver twl6040_codec_driver = { - .driver = { - .name = "twl6040-codec", - .owner = THIS_MODULE, - }, - .probe = twl6040_codec_probe, - .remove = __devexit_p(twl6040_codec_remove), -}; - -module_platform_driver(twl6040_codec_driver); - -MODULE_DESCRIPTION("ASoC TWL6040 codec driver"); -MODULE_AUTHOR("Misael Lopez Cruz"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/twl6040.h b/ANDROID_3.4.5/sound/soc/codecs/twl6040.h deleted file mode 100644 index 0611406c..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/twl6040.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * ALSA SoC TWL6040 codec driver - * - * Author: Misael Lopez Cruz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __TWL6040_H__ -#define __TWL6040_H__ - -enum twl6040_trim { - TWL6040_TRIM_TRIM1 = 0, - TWL6040_TRIM_TRIM2, - TWL6040_TRIM_TRIM3, - TWL6040_TRIM_HSOTRIM, - TWL6040_TRIM_HFOTRIM, - TWL6040_TRIM_INVAL, -}; - -#define TWL6040_HSF_TRIM_LEFT(x) (x & 0x0f) -#define TWL6040_HSF_TRIM_RIGHT(x) ((x >> 4) & 0x0f) - -int twl6040_get_dl1_gain(struct snd_soc_codec *codec); -void twl6040_hs_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack, int report); -int twl6040_get_clk_id(struct snd_soc_codec *codec); -int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim); -int twl6040_get_hs_step_size(struct snd_soc_codec *codec); - -#endif /* End of __TWL6040_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/uda134x.c b/ANDROID_3.4.5/sound/soc/codecs/uda134x.c deleted file mode 100644 index 797b0dde..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/uda134x.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - * uda134x.c -- UDA134X ALSA SoC Codec driver - * - * Modifications by Christian Pellegrin - * - * Copyright 2007 Dension Audio Systems Ltd. - * Author: Zoltan Devai - * - * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "uda134x.h" - - -#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000 -#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE) - -struct uda134x_priv { - int sysclk; - int dai_fmt; - - struct snd_pcm_substream *master_substream; - struct snd_pcm_substream *slave_substream; -}; - -/* In-data addresses are hard-coded into the reg-cache values */ -static const char uda134x_reg[UDA134X_REGS_NUM] = { - /* Extended address registers */ - 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Status, data regs */ - 0x00, 0x83, 0x00, 0x40, 0x80, 0xC0, 0x00, -}; - -/* - * The codec has no support for reading its registers except for peak level... - */ -static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *cache = codec->reg_cache; - - if (reg >= UDA134X_REGS_NUM) - return -1; - return cache[reg]; -} - -/* - * Write the register cache - */ -static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec, - u8 reg, unsigned int value) -{ - u8 *cache = codec->reg_cache; - - if (reg >= UDA134X_REGS_NUM) - return; - cache[reg] = value; -} - -/* - * Write to the uda134x registers - * - */ -static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - int ret; - u8 addr; - u8 data = value; - struct uda134x_platform_data *pd = codec->control_data; - - pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value); - - if (reg >= UDA134X_REGS_NUM) { - printk(KERN_ERR "%s unknown register: reg: %u", - __func__, reg); - return -EINVAL; - } - - uda134x_write_reg_cache(codec, reg, value); - - switch (reg) { - case UDA134X_STATUS0: - case UDA134X_STATUS1: - addr = UDA134X_STATUS_ADDR; - break; - case UDA134X_DATA000: - case UDA134X_DATA001: - case UDA134X_DATA010: - case UDA134X_DATA011: - addr = UDA134X_DATA0_ADDR; - break; - case UDA134X_DATA1: - addr = UDA134X_DATA1_ADDR; - break; - default: - /* It's an extended address register */ - addr = (reg | UDA134X_EXTADDR_PREFIX); - - ret = l3_write(&pd->l3, - UDA134X_DATA0_ADDR, &addr, 1); - if (ret != 1) - return -EIO; - - addr = UDA134X_DATA0_ADDR; - data = (value | UDA134X_EXTDATA_PREFIX); - break; - } - - ret = l3_write(&pd->l3, - addr, &data, 1); - if (ret != 1) - return -EIO; - - return 0; -} - -static inline void uda134x_reset(struct snd_soc_codec *codec) -{ - u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0); - uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6)); - msleep(1); - uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6)); -} - -static int uda134x_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010); - - pr_debug("%s mute: %d\n", __func__, mute); - - if (mute) - mute_reg |= (1<<2); - else - mute_reg &= ~(1<<2); - - uda134x_write(codec, UDA134X_DATA010, mute_reg); - - return 0; -} - -static int uda134x_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec =rtd->codec; - struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); - struct snd_pcm_runtime *master_runtime; - - if (uda134x->master_substream) { - master_runtime = uda134x->master_substream->runtime; - - pr_debug("%s constraining to %d bits at %d\n", __func__, - master_runtime->sample_bits, - master_runtime->rate); - - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - master_runtime->rate, - master_runtime->rate); - - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - master_runtime->sample_bits, - master_runtime->sample_bits); - - uda134x->slave_substream = substream; - } else - uda134x->master_substream = substream; - - return 0; -} - -static void uda134x_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); - - if (uda134x->master_substream == substream) - uda134x->master_substream = uda134x->slave_substream; - - uda134x->slave_substream = NULL; -} - -static int uda134x_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); - u8 hw_params; - - if (substream == uda134x->slave_substream) { - pr_debug("%s ignoring hw_params for slave substream\n", - __func__); - return 0; - } - - hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0); - hw_params &= STATUS0_SYSCLK_MASK; - hw_params &= STATUS0_DAIFMT_MASK; - - pr_debug("%s sysclk: %d, rate:%d\n", __func__, - uda134x->sysclk, params_rate(params)); - - /* set SYSCLK / fs ratio */ - switch (uda134x->sysclk / params_rate(params)) { - case 512: - break; - case 384: - hw_params |= (1<<4); - break; - case 256: - hw_params |= (1<<5); - break; - default: - printk(KERN_ERR "%s unsupported fs\n", __func__); - return -EINVAL; - } - - pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__, - uda134x->dai_fmt, params_format(params)); - - /* set DAI format and word length */ - switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - break; - case SND_SOC_DAIFMT_RIGHT_J: - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - hw_params |= (1<<1); - break; - case SNDRV_PCM_FORMAT_S18_3LE: - hw_params |= (1<<2); - break; - case SNDRV_PCM_FORMAT_S20_3LE: - hw_params |= ((1<<2) | (1<<1)); - break; - default: - printk(KERN_ERR "%s unsupported format (right)\n", - __func__); - return -EINVAL; - } - break; - case SND_SOC_DAIFMT_LEFT_J: - hw_params |= (1<<3); - break; - default: - printk(KERN_ERR "%s unsupported format\n", __func__); - return -EINVAL; - } - - uda134x_write(codec, UDA134X_STATUS0, hw_params); - - return 0; -} - -static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); - - pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__, - clk_id, freq, dir); - - /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable - because the codec is slave. Of course limitations of the clock - master (the IIS controller) apply. - We'll error out on set_hw_params if it's not OK */ - if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) { - uda134x->sysclk = freq; - return 0; - } - - printk(KERN_ERR "%s unsupported sysclk\n", __func__); - return -EINVAL; -} - -static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); - - pr_debug("%s fmt: %08X\n", __func__, fmt); - - /* codec supports only full slave mode */ - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { - printk(KERN_ERR "%s unsupported slave mode\n", __func__); - return -EINVAL; - } - - /* no support for clock inversion */ - if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) { - printk(KERN_ERR "%s unsupported clock inversion\n", __func__); - return -EINVAL; - } - - /* We can't setup DAI format here as it depends on the word bit num */ - /* so let's just store the value for later */ - uda134x->dai_fmt = fmt; - - return 0; -} - -static int uda134x_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u8 reg; - struct uda134x_platform_data *pd = codec->control_data; - int i; - u8 *cache = codec->reg_cache; - - pr_debug("%s bias level %d\n", __func__, level); - - switch (level) { - case SND_SOC_BIAS_ON: - /* ADC, DAC on */ - switch (pd->model) { - case UDA134X_UDA1340: - case UDA134X_UDA1344: - case UDA134X_UDA1345: - reg = uda134x_read_reg_cache(codec, UDA134X_DATA011); - uda134x_write(codec, UDA134X_DATA011, reg | 0x03); - break; - case UDA134X_UDA1341: - reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); - uda134x_write(codec, UDA134X_STATUS1, reg | 0x03); - break; - default: - printk(KERN_ERR "UDA134X SoC codec: " - "unsupported model %d\n", pd->model); - return -EINVAL; - } - break; - case SND_SOC_BIAS_PREPARE: - /* power on */ - if (pd->power) { - pd->power(1); - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) - codec->driver->write(codec, i, *cache++); - } - break; - case SND_SOC_BIAS_STANDBY: - /* ADC, DAC power off */ - switch (pd->model) { - case UDA134X_UDA1340: - case UDA134X_UDA1344: - case UDA134X_UDA1345: - reg = uda134x_read_reg_cache(codec, UDA134X_DATA011); - uda134x_write(codec, UDA134X_DATA011, reg & ~(0x03)); - break; - case UDA134X_UDA1341: - reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); - uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03)); - break; - default: - printk(KERN_ERR "UDA134X SoC codec: " - "unsupported model %d\n", pd->model); - return -EINVAL; - } - break; - case SND_SOC_BIAS_OFF: - /* power off */ - if (pd->power) - pd->power(0); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1", - "Minimum2", "Maximum"}; -static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const char *uda134x_mixmode[] = {"Differential", "Analog1", - "Analog2", "Both"}; - -static const struct soc_enum uda134x_mixer_enum[] = { -SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting), -SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph), -SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode), -}; - -static const struct snd_kcontrol_new uda1341_snd_controls[] = { -SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1), -SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0), -SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1), -SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1), - -SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0), -SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0), - -SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0), -SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0), - -SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]), -SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), -SOC_ENUM("Input Mux", uda134x_mixer_enum[2]), - -SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0), -SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1), -SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0), - -SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0), -SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0), -SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0), -SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0), -SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0), -SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), -}; - -static const struct snd_kcontrol_new uda1340_snd_controls[] = { -SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1), - -SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0), -SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0), - -SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]), -SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), - -SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), -}; - -static const struct snd_kcontrol_new uda1345_snd_controls[] = { -SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1), - -SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), - -SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), -}; - -static const struct snd_soc_dai_ops uda134x_dai_ops = { - .startup = uda134x_startup, - .shutdown = uda134x_shutdown, - .hw_params = uda134x_hw_params, - .digital_mute = uda134x_mute, - .set_sysclk = uda134x_set_dai_sysclk, - .set_fmt = uda134x_set_dai_fmt, -}; - -static struct snd_soc_dai_driver uda134x_dai = { - .name = "uda134x-hifi", - /* playback capabilities */ - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = UDA134X_RATES, - .formats = UDA134X_FORMATS, - }, - /* capture capabilities */ - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = UDA134X_RATES, - .formats = UDA134X_FORMATS, - }, - /* pcm operations */ - .ops = &uda134x_dai_ops, -}; - -static int uda134x_soc_probe(struct snd_soc_codec *codec) -{ - struct uda134x_priv *uda134x; - struct uda134x_platform_data *pd = codec->card->dev->platform_data; - - int ret; - - printk(KERN_INFO "UDA134X SoC Audio Codec\n"); - - if (!pd) { - printk(KERN_ERR "UDA134X SoC codec: " - "missing L3 bitbang function\n"); - return -ENODEV; - } - - switch (pd->model) { - case UDA134X_UDA1340: - case UDA134X_UDA1341: - case UDA134X_UDA1344: - case UDA134X_UDA1345: - break; - default: - printk(KERN_ERR "UDA134X SoC codec: " - "unsupported model %d\n", - pd->model); - return -EINVAL; - } - - uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); - if (uda134x == NULL) - return -ENOMEM; - snd_soc_codec_set_drvdata(codec, uda134x); - - codec->control_data = pd; - - if (pd->power) - pd->power(1); - - uda134x_reset(codec); - - if (pd->is_powered_on_standby) - uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); - else - uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - switch (pd->model) { - case UDA134X_UDA1340: - case UDA134X_UDA1344: - ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls, - ARRAY_SIZE(uda1340_snd_controls)); - break; - case UDA134X_UDA1341: - ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls, - ARRAY_SIZE(uda1341_snd_controls)); - break; - case UDA134X_UDA1345: - ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls, - ARRAY_SIZE(uda1345_snd_controls)); - break; - default: - printk(KERN_ERR "%s unknown codec type: %d", - __func__, pd->model); - kfree(uda134x); - return -EINVAL; - } - - if (ret < 0) { - printk(KERN_ERR "UDA134X: failed to register controls\n"); - kfree(uda134x); - return ret; - } - - return 0; -} - -/* power down chip */ -static int uda134x_soc_remove(struct snd_soc_codec *codec) -{ - struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); - - uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); - - kfree(uda134x); - return 0; -} - -#if defined(CONFIG_PM) -static int uda134x_soc_suspend(struct snd_soc_codec *codec) -{ - uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int uda134x_soc_resume(struct snd_soc_codec *codec) -{ - uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); - return 0; -} -#else -#define uda134x_soc_suspend NULL -#define uda134x_soc_resume NULL -#endif /* CONFIG_PM */ - -static struct snd_soc_codec_driver soc_codec_dev_uda134x = { - .probe = uda134x_soc_probe, - .remove = uda134x_soc_remove, - .suspend = uda134x_soc_suspend, - .resume = uda134x_soc_resume, - .reg_cache_size = sizeof(uda134x_reg), - .reg_word_size = sizeof(u8), - .reg_cache_default = uda134x_reg, - .reg_cache_step = 1, - .read = uda134x_read_reg_cache, - .write = uda134x_write, - .set_bias_level = uda134x_set_bias_level, -}; - -static int __devinit uda134x_codec_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_uda134x, &uda134x_dai, 1); -} - -static int __devexit uda134x_codec_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver uda134x_codec_driver = { - .driver = { - .name = "uda134x-codec", - .owner = THIS_MODULE, - }, - .probe = uda134x_codec_probe, - .remove = __devexit_p(uda134x_codec_remove), -}; - -module_platform_driver(uda134x_codec_driver); - -MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); -MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/uda134x.h b/ANDROID_3.4.5/sound/soc/codecs/uda134x.h deleted file mode 100644 index 9faae069..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/uda134x.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _UDA134X_CODEC_H -#define _UDA134X_CODEC_H - -#define UDA134X_L3ADDR 5 -#define UDA134X_DATA0_ADDR ((UDA134X_L3ADDR << 2) | 0) -#define UDA134X_DATA1_ADDR ((UDA134X_L3ADDR << 2) | 1) -#define UDA134X_STATUS_ADDR ((UDA134X_L3ADDR << 2) | 2) - -#define UDA134X_EXTADDR_PREFIX 0xC0 -#define UDA134X_EXTDATA_PREFIX 0xE0 - -/* UDA134X registers */ -#define UDA134X_EA000 0 -#define UDA134X_EA001 1 -#define UDA134X_EA010 2 -#define UDA134X_EA011 3 -#define UDA134X_EA100 4 -#define UDA134X_EA101 5 -#define UDA134X_EA110 6 -#define UDA134X_EA111 7 -#define UDA134X_STATUS0 8 -#define UDA134X_STATUS1 9 -#define UDA134X_DATA000 10 -#define UDA134X_DATA001 11 -#define UDA134X_DATA010 12 -#define UDA134X_DATA011 13 -#define UDA134X_DATA1 14 - -#define UDA134X_REGS_NUM 15 - -#define STATUS0_DAIFMT_MASK (~(7<<1)) -#define STATUS0_SYSCLK_MASK (~(3<<4)) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/uda1380.c b/ANDROID_3.4.5/sound/soc/codecs/uda1380.c deleted file mode 100644 index 4f1b23d7..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/uda1380.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * uda1380.c - Philips UDA1380 ALSA SoC audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Copyright (c) 2007-2009 Philipp Zabel - * - * Modified by Richard Purdie to fit into SoC - * codec model. - * - * Copyright (c) 2005 Giorgio Padrin - * Copyright 2005 Openedhand Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "uda1380.h" - -/* codec private data */ -struct uda1380_priv { - struct snd_soc_codec *codec; - unsigned int dac_clk; - struct work_struct work; - void *control_data; -}; - -/* - * uda1380 register cache - */ -static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = { - 0x0502, 0x0000, 0x0000, 0x3f3f, - 0x0202, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0xff00, 0x0000, 0x4800, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x8000, 0x0002, 0x0000, -}; - -static unsigned long uda1380_cache_dirty; - -/* - * read uda1380 register cache - */ -static inline unsigned int uda1380_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg == UDA1380_RESET) - return 0; - if (reg >= UDA1380_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write uda1380 register cache - */ -static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - - if (reg >= UDA1380_CACHEREGNUM) - return; - if ((reg >= 0x10) && (cache[reg] != value)) - set_bit(reg - 0x10, &uda1380_cache_dirty); - cache[reg] = value; -} - -/* - * write to the UDA1380 register space - */ -static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[3]; - - /* data is - * data[0] is register offset - * data[1] is MS byte - * data[2] is LS byte - */ - data[0] = reg; - data[1] = (value & 0xff00) >> 8; - data[2] = value & 0x00ff; - - uda1380_write_reg_cache(codec, reg, value); - - /* the interpolator & decimator regs must only be written when the - * codec DAI is active. - */ - if (!codec->active && (reg >= UDA1380_MVOL)) - return 0; - pr_debug("uda1380: hw write %x val %x\n", reg, value); - if (codec->hw_write(codec->control_data, data, 3) == 3) { - unsigned int val; - i2c_master_send(codec->control_data, data, 1); - i2c_master_recv(codec->control_data, data, 2); - val = (data[0]<<8) | data[1]; - if (val != value) { - pr_debug("uda1380: READ BACK VAL %x\n", - (data[0]<<8) | data[1]); - return -EIO; - } - if (reg >= 0x10) - clear_bit(reg - 0x10, &uda1380_cache_dirty); - return 0; - } else - return -EIO; -} - -static void uda1380_sync_cache(struct snd_soc_codec *codec) -{ - int reg; - u8 data[3]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (reg = 0; reg < UDA1380_MVOL; reg++) { - data[0] = reg; - data[1] = (cache[reg] & 0xff00) >> 8; - data[2] = cache[reg] & 0x00ff; - if (codec->hw_write(codec->control_data, data, 3) != 3) - dev_err(codec->dev, "%s: write to reg 0x%x failed\n", - __func__, reg); - } -} - -static int uda1380_reset(struct snd_soc_codec *codec) -{ - struct uda1380_platform_data *pdata = codec->dev->platform_data; - - if (gpio_is_valid(pdata->gpio_reset)) { - gpio_set_value(pdata->gpio_reset, 1); - mdelay(1); - gpio_set_value(pdata->gpio_reset, 0); - } else { - u8 data[3]; - - data[0] = UDA1380_RESET; - data[1] = 0; - data[2] = 0; - - if (codec->hw_write(codec->control_data, data, 3) != 3) { - dev_err(codec->dev, "%s: failed\n", __func__); - return -EIO; - } - } - - return 0; -} - -static void uda1380_flush_work(struct work_struct *work) -{ - struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work); - struct snd_soc_codec *uda1380_codec = uda1380->codec; - int bit, reg; - - for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { - reg = 0x10 + bit; - pr_debug("uda1380: flush reg %x val %x:\n", reg, - uda1380_read_reg_cache(uda1380_codec, reg)); - uda1380_write(uda1380_codec, reg, - uda1380_read_reg_cache(uda1380_codec, reg)); - clear_bit(bit, &uda1380_cache_dirty); - } - -} - -/* declarations of ALSA reg_elem_REAL controls */ -static const char *uda1380_deemp[] = { - "None", - "32kHz", - "44.1kHz", - "48kHz", - "96kHz", -}; -static const char *uda1380_input_sel[] = { - "Line", - "Mic + Line R", - "Line L", - "Mic", -}; -static const char *uda1380_output_sel[] = { - "DAC", - "Analog Mixer", -}; -static const char *uda1380_spf_mode[] = { - "Flat", - "Minimum1", - "Minimum2", - "Maximum" -}; -static const char *uda1380_capture_sel[] = { - "ADC", - "Digital Mixer" -}; -static const char *uda1380_sel_ns[] = { - "3rd-order", - "5th-order" -}; -static const char *uda1380_mix_control[] = { - "off", - "PCM only", - "before sound processing", - "after sound processing" -}; -static const char *uda1380_sdet_setting[] = { - "3200", - "4800", - "9600", - "19200" -}; -static const char *uda1380_os_setting[] = { - "single-speed", - "double-speed (no mixing)", - "quad-speed (no mixing)" -}; - -static const struct soc_enum uda1380_deemp_enum[] = { - SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp), - SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp), -}; -static const struct soc_enum uda1380_input_sel_enum = - SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel); /* SEL_MIC, SEL_LNA */ -static const struct soc_enum uda1380_output_sel_enum = - SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel); /* R02_EN_AVC */ -static const struct soc_enum uda1380_spf_enum = - SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode); /* M */ -static const struct soc_enum uda1380_capture_sel_enum = - SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel); /* SEL_SOURCE */ -static const struct soc_enum uda1380_sel_ns_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns); /* SEL_NS */ -static const struct soc_enum uda1380_mix_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control); /* MIX, MIX_POS */ -static const struct soc_enum uda1380_sdet_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting); /* SD_VALUE */ -static const struct soc_enum uda1380_os_enum = - SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting); /* OS */ - -/* - * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB) - */ -static DECLARE_TLV_DB_SCALE(amix_tlv, -4950, 150, 1); - -/* - * from -78 dB in 1 dB steps (3 dB steps, really. LSB are ignored), - * from -66 dB in 0.5 dB steps (2 dB steps, really) and - * from -52 dB in 0.25 dB steps - */ -static const unsigned int mvol_tlv[] = { - TLV_DB_RANGE_HEAD(3), - 0, 15, TLV_DB_SCALE_ITEM(-8200, 100, 1), - 16, 43, TLV_DB_SCALE_ITEM(-6600, 50, 0), - 44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0), -}; - -/* - * from -72 dB in 1.5 dB steps (6 dB steps really), - * from -66 dB in 0.75 dB steps (3 dB steps really), - * from -60 dB in 0.5 dB steps (2 dB steps really) and - * from -46 dB in 0.25 dB steps - */ -static const unsigned int vc_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 7, TLV_DB_SCALE_ITEM(-7800, 150, 1), - 8, 15, TLV_DB_SCALE_ITEM(-6600, 75, 0), - 16, 43, TLV_DB_SCALE_ITEM(-6000, 50, 0), - 44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0), -}; - -/* from 0 to 6 dB in 2 dB steps if SPF mode != flat */ -static DECLARE_TLV_DB_SCALE(tr_tlv, 0, 200, 0); - -/* from 0 to 24 dB in 2 dB steps, if SPF mode == maximum, otherwise cuts - * off at 18 dB max) */ -static DECLARE_TLV_DB_SCALE(bb_tlv, 0, 200, 0); - -/* from -63 to 24 dB in 0.5 dB steps (-128...48) */ -static DECLARE_TLV_DB_SCALE(dec_tlv, -6400, 50, 1); - -/* from 0 to 24 dB in 3 dB steps */ -static DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0); - -/* from 0 to 30 dB in 2 dB steps */ -static DECLARE_TLV_DB_SCALE(vga_tlv, 0, 200, 0); - -static const struct snd_kcontrol_new uda1380_snd_controls[] = { - SOC_DOUBLE_TLV("Analog Mixer Volume", UDA1380_AMIX, 0, 8, 44, 1, amix_tlv), /* AVCR, AVCL */ - SOC_DOUBLE_TLV("Master Playback Volume", UDA1380_MVOL, 0, 8, 252, 1, mvol_tlv), /* MVCL, MVCR */ - SOC_SINGLE_TLV("ADC Playback Volume", UDA1380_MIXVOL, 8, 228, 1, vc_tlv), /* VC2 */ - SOC_SINGLE_TLV("PCM Playback Volume", UDA1380_MIXVOL, 0, 228, 1, vc_tlv), /* VC1 */ - SOC_ENUM("Sound Processing Filter", uda1380_spf_enum), /* M */ - SOC_DOUBLE_TLV("Tone Control - Treble", UDA1380_MODE, 4, 12, 3, 0, tr_tlv), /* TRL, TRR */ - SOC_DOUBLE_TLV("Tone Control - Bass", UDA1380_MODE, 0, 8, 15, 0, bb_tlv), /* BBL, BBR */ -/**/ SOC_SINGLE("Master Playback Switch", UDA1380_DEEMP, 14, 1, 1), /* MTM */ - SOC_SINGLE("ADC Playback Switch", UDA1380_DEEMP, 11, 1, 1), /* MT2 from decimation filter */ - SOC_ENUM("ADC Playback De-emphasis", uda1380_deemp_enum[0]), /* DE2 */ - SOC_SINGLE("PCM Playback Switch", UDA1380_DEEMP, 3, 1, 1), /* MT1, from digital data input */ - SOC_ENUM("PCM Playback De-emphasis", uda1380_deemp_enum[1]), /* DE1 */ - SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */ - SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */ - SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */ - SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */ - SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */ - SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */ - SOC_DOUBLE_S8_TLV("ADC Capture Volume", UDA1380_DEC, -128, 48, dec_tlv), /* ML_DEC, MR_DEC */ -/**/ SOC_SINGLE("ADC Capture Switch", UDA1380_PGA, 15, 1, 1), /* MT_ADC */ - SOC_DOUBLE_TLV("Line Capture Volume", UDA1380_PGA, 0, 8, 8, 0, pga_tlv), /* PGA_GAINCTRLL, PGA_GAINCTRLR */ - SOC_SINGLE("ADC Polarity inverting Switch", UDA1380_ADC, 12, 1, 0), /* ADCPOL_INV */ - SOC_SINGLE_TLV("Mic Capture Volume", UDA1380_ADC, 8, 15, 0, vga_tlv), /* VGA_CTRL */ - SOC_SINGLE("DC Filter Bypass Switch", UDA1380_ADC, 1, 1, 0), /* SKIP_DCFIL (before decimator) */ - SOC_SINGLE("DC Filter Enable Switch", UDA1380_ADC, 0, 1, 0), /* EN_DCFIL (at output of decimator) */ - SOC_SINGLE("AGC Timing", UDA1380_AGC, 8, 7, 0), /* TODO: enum, see table 62 */ - SOC_SINGLE("AGC Target level", UDA1380_AGC, 2, 3, 1), /* AGC_LEVEL */ - /* -5.5, -8, -11.5, -14 dBFS */ - SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0), -}; - -/* Input mux */ -static const struct snd_kcontrol_new uda1380_input_mux_control = - SOC_DAPM_ENUM("Route", uda1380_input_sel_enum); - -/* Output mux */ -static const struct snd_kcontrol_new uda1380_output_mux_control = - SOC_DAPM_ENUM("Route", uda1380_output_sel_enum); - -/* Capture mux */ -static const struct snd_kcontrol_new uda1380_capture_mux_control = - SOC_DAPM_ENUM("Route", uda1380_capture_sel_enum); - - -static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = { - SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, - &uda1380_input_mux_control), - SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM, 0, 0, - &uda1380_output_mux_control), - SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, - &uda1380_capture_mux_control), - SND_SOC_DAPM_PGA("Left PGA", UDA1380_PM, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right PGA", UDA1380_PM, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mic LNA", UDA1380_PM, 4, 0, NULL, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", UDA1380_PM, 2, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", UDA1380_PM, 0, 0), - SND_SOC_DAPM_INPUT("VINM"), - SND_SOC_DAPM_INPUT("VINL"), - SND_SOC_DAPM_INPUT("VINR"), - SND_SOC_DAPM_MIXER("Analog Mixer", UDA1380_PM, 6, 0, NULL, 0), - SND_SOC_DAPM_OUTPUT("VOUTLHP"), - SND_SOC_DAPM_OUTPUT("VOUTRHP"), - SND_SOC_DAPM_OUTPUT("VOUTL"), - SND_SOC_DAPM_OUTPUT("VOUTR"), - SND_SOC_DAPM_DAC("DAC", "Playback", UDA1380_PM, 10, 0), - SND_SOC_DAPM_PGA("HeadPhone Driver", UDA1380_PM, 13, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_route uda1380_dapm_routes[] = { - - /* output mux */ - {"HeadPhone Driver", NULL, "Output Mux"}, - {"VOUTR", NULL, "Output Mux"}, - {"VOUTL", NULL, "Output Mux"}, - - {"Analog Mixer", NULL, "VINR"}, - {"Analog Mixer", NULL, "VINL"}, - {"Analog Mixer", NULL, "DAC"}, - - {"Output Mux", "DAC", "DAC"}, - {"Output Mux", "Analog Mixer", "Analog Mixer"}, - - /* {"DAC", "Digital Mixer", "I2S" } */ - - /* headphone driver */ - {"VOUTLHP", NULL, "HeadPhone Driver"}, - {"VOUTRHP", NULL, "HeadPhone Driver"}, - - /* input mux */ - {"Left ADC", NULL, "Input Mux"}, - {"Input Mux", "Mic", "Mic LNA"}, - {"Input Mux", "Mic + Line R", "Mic LNA"}, - {"Input Mux", "Line L", "Left PGA"}, - {"Input Mux", "Line", "Left PGA"}, - - /* right input */ - {"Right ADC", "Mic + Line R", "Right PGA"}, - {"Right ADC", "Line", "Right PGA"}, - - /* inputs */ - {"Mic LNA", NULL, "VINM"}, - {"Left PGA", NULL, "VINL"}, - {"Right PGA", NULL, "VINR"}, -}; - -static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int iface; - - /* set up DAI based upon fmt */ - iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); - iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK); - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= R01_SFORI_I2S | R01_SFORO_I2S; - break; - case SND_SOC_DAIFMT_LSB: - iface |= R01_SFORI_LSB16 | R01_SFORO_LSB16; - break; - case SND_SOC_DAIFMT_MSB: - iface |= R01_SFORI_MSB | R01_SFORO_MSB; - } - - /* DATAI is slave only, so in single-link mode, this has to be slave */ - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) - return -EINVAL; - - uda1380_write(codec, UDA1380_IFACE, iface); - - return 0; -} - -static int uda1380_set_dai_fmt_playback(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int iface; - - /* set up DAI based upon fmt */ - iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); - iface &= ~R01_SFORI_MASK; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= R01_SFORI_I2S; - break; - case SND_SOC_DAIFMT_LSB: - iface |= R01_SFORI_LSB16; - break; - case SND_SOC_DAIFMT_MSB: - iface |= R01_SFORI_MSB; - } - - /* DATAI is slave only, so this has to be slave */ - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) - return -EINVAL; - - uda1380_write(codec, UDA1380_IFACE, iface); - - return 0; -} - -static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int iface; - - /* set up DAI based upon fmt */ - iface = uda1380_read_reg_cache(codec, UDA1380_IFACE); - iface &= ~(R01_SIM | R01_SFORO_MASK); - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= R01_SFORO_I2S; - break; - case SND_SOC_DAIFMT_LSB: - iface |= R01_SFORO_LSB16; - break; - case SND_SOC_DAIFMT_MSB: - iface |= R01_SFORO_MSB; - } - - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) - iface |= R01_SIM; - - uda1380_write(codec, UDA1380_IFACE, iface); - - return 0; -} - -static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); - int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - uda1380_write_reg_cache(codec, UDA1380_MIXER, - mixer & ~R14_SILENCE); - schedule_work(&uda1380->work); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - uda1380_write_reg_cache(codec, UDA1380_MIXER, - mixer | R14_SILENCE); - schedule_work(&uda1380->work); - break; - } - return 0; -} - -static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); - - /* set WSPLL power and divider if running from this clock */ - if (clk & R00_DAC_CLK) { - int rate = params_rate(params); - u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM); - clk &= ~0x3; /* clear SEL_LOOP_DIV */ - switch (rate) { - case 6250 ... 12500: - clk |= 0x0; - break; - case 12501 ... 25000: - clk |= 0x1; - break; - case 25001 ... 50000: - clk |= 0x2; - break; - case 50001 ... 100000: - clk |= 0x3; - break; - } - uda1380_write(codec, UDA1380_PM, R02_PON_PLL | pm); - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - clk |= R00_EN_DAC | R00_EN_INT; - else - clk |= R00_EN_ADC | R00_EN_DEC; - - uda1380_write(codec, UDA1380_CLK, clk); - return 0; -} - -static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); - - /* shut down WSPLL power if running from this clock */ - if (clk & R00_DAC_CLK) { - u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM); - uda1380_write(codec, UDA1380_PM, ~R02_PON_PLL & pm); - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - clk &= ~(R00_EN_DAC | R00_EN_INT); - else - clk &= ~(R00_EN_ADC | R00_EN_DEC); - - uda1380_write(codec, UDA1380_CLK, clk); -} - -static int uda1380_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int pm = uda1380_read_reg_cache(codec, UDA1380_PM); - int reg; - struct uda1380_platform_data *pdata = codec->dev->platform_data; - - if (codec->dapm.bias_level == level) - return 0; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - /* ADC, DAC on */ - uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm); - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - if (gpio_is_valid(pdata->gpio_power)) { - gpio_set_value(pdata->gpio_power, 1); - mdelay(1); - uda1380_reset(codec); - } - - uda1380_sync_cache(codec); - } - uda1380_write(codec, UDA1380_PM, 0x0); - break; - case SND_SOC_BIAS_OFF: - if (!gpio_is_valid(pdata->gpio_power)) - break; - - gpio_set_value(pdata->gpio_power, 0); - - /* Mark mixer regs cache dirty to sync them with - * codec regs on power on. - */ - for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++) - set_bit(reg - 0x10, &uda1380_cache_dirty); - } - codec->dapm.bias_level = level; - return 0; -} - -#define UDA1380_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) - -static const struct snd_soc_dai_ops uda1380_dai_ops = { - .hw_params = uda1380_pcm_hw_params, - .shutdown = uda1380_pcm_shutdown, - .trigger = uda1380_trigger, - .set_fmt = uda1380_set_dai_fmt_both, -}; - -static const struct snd_soc_dai_ops uda1380_dai_ops_playback = { - .hw_params = uda1380_pcm_hw_params, - .shutdown = uda1380_pcm_shutdown, - .trigger = uda1380_trigger, - .set_fmt = uda1380_set_dai_fmt_playback, -}; - -static const struct snd_soc_dai_ops uda1380_dai_ops_capture = { - .hw_params = uda1380_pcm_hw_params, - .shutdown = uda1380_pcm_shutdown, - .trigger = uda1380_trigger, - .set_fmt = uda1380_set_dai_fmt_capture, -}; - -static struct snd_soc_dai_driver uda1380_dai[] = { -{ - .name = "uda1380-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = UDA1380_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = UDA1380_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &uda1380_dai_ops, -}, -{ /* playback only - dual interface */ - .name = "uda1380-hifi-playback", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = UDA1380_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &uda1380_dai_ops_playback, -}, -{ /* capture only - dual interface*/ - .name = "uda1380-hifi-capture", - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = UDA1380_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &uda1380_dai_ops_capture, -}, -}; - -static int uda1380_suspend(struct snd_soc_codec *codec) -{ - uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int uda1380_resume(struct snd_soc_codec *codec) -{ - uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int uda1380_probe(struct snd_soc_codec *codec) -{ - struct uda1380_platform_data *pdata =codec->dev->platform_data; - struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); - int ret; - - uda1380->codec = codec; - - codec->hw_write = (hw_write_t)i2c_master_send; - codec->control_data = uda1380->control_data; - - if (!pdata) - return -EINVAL; - - if (gpio_is_valid(pdata->gpio_reset)) { - ret = gpio_request_one(pdata->gpio_reset, GPIOF_OUT_INIT_LOW, - "uda1380 reset"); - if (ret) - goto err_out; - } - - if (gpio_is_valid(pdata->gpio_power)) { - ret = gpio_request_one(pdata->gpio_power, GPIOF_OUT_INIT_LOW, - "uda1380 power"); - if (ret) - goto err_free_gpio; - } else { - ret = uda1380_reset(codec); - if (ret) - goto err_free_gpio; - } - - INIT_WORK(&uda1380->work, uda1380_flush_work); - - /* power on device */ - uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - /* set clock input */ - switch (pdata->dac_clk) { - case UDA1380_DAC_CLK_SYSCLK: - uda1380_write_reg_cache(codec, UDA1380_CLK, 0); - break; - case UDA1380_DAC_CLK_WSPLL: - uda1380_write_reg_cache(codec, UDA1380_CLK, - R00_DAC_CLK); - break; - } - - return 0; - -err_free_gpio: - if (gpio_is_valid(pdata->gpio_reset)) - gpio_free(pdata->gpio_reset); -err_out: - return ret; -} - -/* power down chip */ -static int uda1380_remove(struct snd_soc_codec *codec) -{ - struct uda1380_platform_data *pdata =codec->dev->platform_data; - - uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); - - gpio_free(pdata->gpio_reset); - gpio_free(pdata->gpio_power); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_uda1380 = { - .probe = uda1380_probe, - .remove = uda1380_remove, - .suspend = uda1380_suspend, - .resume = uda1380_resume, - .read = uda1380_read_reg_cache, - .write = uda1380_write, - .set_bias_level = uda1380_set_bias_level, - .reg_cache_size = ARRAY_SIZE(uda1380_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = uda1380_reg, - .reg_cache_step = 1, - - .controls = uda1380_snd_controls, - .num_controls = ARRAY_SIZE(uda1380_snd_controls), - .dapm_widgets = uda1380_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets), - .dapm_routes = uda1380_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes), -}; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct uda1380_priv *uda1380; - int ret; - - uda1380 = devm_kzalloc(&i2c->dev, sizeof(struct uda1380_priv), - GFP_KERNEL); - if (uda1380 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, uda1380); - uda1380->control_data = i2c; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai)); - return ret; -} - -static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - return 0; -} - -static const struct i2c_device_id uda1380_i2c_id[] = { - { "uda1380", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); - -static struct i2c_driver uda1380_i2c_driver = { - .driver = { - .name = "uda1380-codec", - .owner = THIS_MODULE, - }, - .probe = uda1380_i2c_probe, - .remove = __devexit_p(uda1380_i2c_remove), - .id_table = uda1380_i2c_id, -}; -#endif - -static int __init uda1380_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&uda1380_i2c_driver); - if (ret != 0) - pr_err("Failed to register UDA1380 I2C driver: %d\n", ret); -#endif - return ret; -} -module_init(uda1380_modinit); - -static void __exit uda1380_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&uda1380_i2c_driver); -#endif -} -module_exit(uda1380_exit); - -MODULE_AUTHOR("Giorgio Padrin"); -MODULE_DESCRIPTION("Audio support for codec Philips UDA1380"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/uda1380.h b/ANDROID_3.4.5/sound/soc/codecs/uda1380.h deleted file mode 100644 index 942e3927..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/uda1380.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Audio support for Philips UDA1380 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Copyright (c) 2005 Giorgio Padrin - */ - -#ifndef _UDA1380_H -#define _UDA1380_H - -#define UDA1380_CLK 0x00 -#define UDA1380_IFACE 0x01 -#define UDA1380_PM 0x02 -#define UDA1380_AMIX 0x03 -#define UDA1380_HP 0x04 -#define UDA1380_MVOL 0x10 -#define UDA1380_MIXVOL 0x11 -#define UDA1380_MODE 0x12 -#define UDA1380_DEEMP 0x13 -#define UDA1380_MIXER 0x14 -#define UDA1380_INTSTAT 0x18 -#define UDA1380_DEC 0x20 -#define UDA1380_PGA 0x21 -#define UDA1380_ADC 0x22 -#define UDA1380_AGC 0x23 -#define UDA1380_DECSTAT 0x28 -#define UDA1380_RESET 0x7f - -#define UDA1380_CACHEREGNUM 0x24 - -/* Register flags */ -#define R00_EN_ADC 0x0800 -#define R00_EN_DEC 0x0400 -#define R00_EN_DAC 0x0200 -#define R00_EN_INT 0x0100 -#define R00_DAC_CLK 0x0010 -#define R01_SFORI_I2S 0x0000 -#define R01_SFORI_LSB16 0x0100 -#define R01_SFORI_LSB18 0x0200 -#define R01_SFORI_LSB20 0x0300 -#define R01_SFORI_MSB 0x0500 -#define R01_SFORI_MASK 0x0700 -#define R01_SFORO_I2S 0x0000 -#define R01_SFORO_LSB16 0x0001 -#define R01_SFORO_LSB18 0x0002 -#define R01_SFORO_LSB20 0x0003 -#define R01_SFORO_LSB24 0x0004 -#define R01_SFORO_MSB 0x0005 -#define R01_SFORO_MASK 0x0007 -#define R01_SEL_SOURCE 0x0040 -#define R01_SIM 0x0010 -#define R02_PON_PLL 0x8000 -#define R02_PON_HP 0x2000 -#define R02_PON_DAC 0x0400 -#define R02_PON_BIAS 0x0100 -#define R02_EN_AVC 0x0080 -#define R02_PON_AVC 0x0040 -#define R02_PON_LNA 0x0010 -#define R02_PON_PGAL 0x0008 -#define R02_PON_ADCL 0x0004 -#define R02_PON_PGAR 0x0002 -#define R02_PON_ADCR 0x0001 -#define R13_MTM 0x4000 -#define R14_SILENCE 0x0080 -#define R14_SDET_ON 0x0040 -#define R21_MT_ADC 0x8000 -#define R22_SEL_LNA 0x0008 -#define R22_SEL_MIC 0x0004 -#define R22_SKIP_DCFIL 0x0002 -#define R23_AGC_EN 0x0001 - -#define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */ -#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ -#define UDA1380_DAI_CAPTURE 2 /* capture DAI */ - -#endif /* _UDA1380_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/vt1603.c b/ANDROID_3.4.5/sound/soc/codecs/vt1603.c deleted file mode 100755 index eaa3d28e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/vt1603.c +++ /dev/null @@ -1,1249 +0,0 @@ -/*++ - * linux/sound/soc/codecs/vt1603.c - * WonderMedia audio driver for ALSA - * - * Copyright c 2010 WonderMedia Technologies, Inc. - * - * 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, see . - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "vt1603.h" -#include - -#define VT1603_TIMER_INTERVAL 100 // ms - -static struct snd_soc_codec *gvt1603_codec = NULL; // - -struct vt1603_priv { - unsigned int sysclk; - struct switch_dev hp_switch; // state of headphone insert or not - struct work_struct work; - struct snd_soc_codec *codec; - struct timer_list timer; // timer for detecting headphone - struct proc_dir_entry *proc; - struct notifier_block reboot_notifier; -}; - -struct vt1603_boardinfo { - int hp_level; // 0: headset level low; 1: high - int ignore_hp_event; - int rec_src; // 0: AMIC-IN; 1: DMIC-IN - - int hpd_rm; //add 2013-11-26 - int hp_debounce; //add 2014-1-14 - int timer_del; //2014-1-20 tvbox - - int out_on; //2014-4-29 av out on for tvbox noisy. hw not good! -}; -static struct vt1603_boardinfo vt1603_boardinfo; - -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); - -static const u16 vt1603_regs[] = { - 0x0020, 0x00D7, 0x00D7, 0x0004, /* 0-3 */ - 0x0000, 0x0040, 0x0000, 0x00c0, /* 4-7 */ - 0x00c0, 0x0010, 0x0001, 0x0041, /* 8-11 */ - 0x0000, 0x0000, 0x000b, 0x0093, /* 12-15 */ - 0x0004, 0x0016, 0x0026, 0x0060, /* 16-19 */ - 0x001a, 0x0000, 0x0002, 0x0000, /* 20-23 */ - 0x0000, 0x000a, 0x0000, 0x0010, /* 24-27 */ - 0x0000, 0x00e2, 0x0000, 0x0000, /* 28-31 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 32-35 */ - 0x0000, 0x000c, 0x0054, 0x0000, /* 36-39 */ - 0x0001, 0x000c, 0x000c, 0x000c, /* 40-43 */ - 0x000c, 0x000c, 0x00c0, 0x00d5, /* 44-47 */ - 0x00c5, 0x0012, 0x0085, 0x002b, /* 48-51 */ - 0x00cd, 0x00cd, 0x008e, 0x008d, /* 52-55 */ - 0x00e0, 0x00a6, 0x00a5, 0x0050, /* 56-59 */ - 0x00e9, 0x00cf, 0x0040, 0x0000, /* 60-63 */ - 0x0000, 0x0008, 0x0004, 0x0000, /* 64-67 */ - 0x0040, 0x0000, 0x0040, 0x0000, /* 68-71 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 72-75 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 76-79 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 80-83 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 84-87 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 88-91 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 92-95 */ - 0x00c4, 0x0079, 0x000c, 0x0024, /* 96-99 */ - 0x0016, 0x0016, 0x0060, 0x0002, /* 100-103 */ - 0x005b, 0x0003, 0x0039, 0x0039, /* 104-107 */ - 0x00fe, 0x0012, 0x0034, 0x0000, /* 108-111 */ - 0x0004, 0x00f0, 0x0000, 0x0000, /* 112-115 */ - 0x0000, 0x0000, 0x0003, 0x0000, /* 116-119 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 120-123 */ - 0x00f2, 0x0020, 0x0023, 0x006e, /* 124-127 */ - 0x0019, 0x0040, 0x0000, 0x0004, /* 128-131 */ - 0x000a, 0x0075, 0x0035, 0x00b0, /* 132-135 */ - 0x0040, 0x0000, 0x0000, 0x0000, /* 136-139 */ - 0x0088, 0x0013, 0x000c, 0x0003, /* 140-143 */ - 0x0000, 0x0000, 0x0008, 0x0000, /* 144-147 */ - 0x0003, 0x0020, 0x0030, 0x0018, /* 148-151 */ - 0x001b, -}; - -/*----------------------------------------------------------------------*/ - - -/*---------------------Control Interface Functions----------------------*/ - -static int vt1603_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - int ret = vt1603_reg_write(codec->control_data, reg, value); - if (ret == 0) - ((u16 *)codec->reg_cache)[reg] = value; - return ret; -} - -static unsigned int vt1603_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - return ((u16 *)codec->reg_cache)[reg]; -} - -static int vt1603_hw_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - return vt1603_reg_write(codec->control_data, reg, value); -} - -static unsigned int vt1603_hw_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 val; - int ret = vt1603_reg_read(codec->control_data, reg, &val); - if (ret == 0) - return val; - else - return ((u16 *)codec->reg_cache)[reg]; -} - -/*----------------------------------------------------------------------*/ - - -/*----------------------IRQ handle Functions----------------------------*/ - -static void vt1603_set_switch_state(struct snd_soc_codec *codec) -{ - /* Just report hp state, don't switch hw device, app will handle it. */ - - struct vt1603_priv *vt1603 = snd_soc_codec_get_drvdata(codec); - unsigned int val = vt1603_hw_read(codec, VT1603_R21); - - if (vt1603_boardinfo.hp_level) { - if (val & BIT1) { - val &= ~BIT1; - snd_soc_write(codec, VT1603_R21, val); - if (!vt1603_boardinfo.ignore_hp_event) - switch_set_state(&vt1603->hp_switch, 0); - pr_info("<<hp_switch, 1); - pr_info("<<hp_switch, 1); - pr_info("<<hp_switch, 0); - pr_info("<<codec; - unsigned int val; - static unsigned int count = 0; - int hp_state = 0; //switch_get_state(&priv->hp_switch); - if (!vt1603_boardinfo.hpd_rm) - hp_state = switch_get_state(&priv->hp_switch); - - unsigned int debounce = (hp_state == 0) ? 3 : 1; // sw-debounce for headset plugin - - if (vt1603_boardinfo.hp_debounce > 0) - debounce = (hp_state == 0) ? vt1603_boardinfo.hp_debounce : 1; - - - - val = vt1603_hw_read(codec, VT1603_R51); - if (val & BIT1) { - val = vt1603_hw_read(codec, VT1603_R1b); - val |= BIT1; - snd_soc_write(codec, VT1603_R1b, val); - val &= ~BIT1; - snd_soc_write(codec, VT1603_R1b, val); - count++; - } - else { - count = 0; - } - - if (count == debounce) { - pr_info("vt1603: hpdetect\n"); - vt1603_set_switch_state(codec); - // clear headphone irq mask - val = vt1603_hw_read(codec,VT1603_R1b); - val |= BIT1; - snd_soc_write(codec, VT1603_R1b, val); - val &= ~BIT1; - snd_soc_write(codec, VT1603_R1b, val); - count = 0; - } - - val = vt1603_hw_read(codec, VT1603_R52); - if (val & BIT4) { - pr_info("vt1603: left cld oc\n"); - val = vt1603_hw_read(codec,VT1603_R1c); - val |= BIT4; - snd_soc_write(codec, VT1603_R1c, val); - val &= ~BIT4; - snd_soc_write(codec, VT1603_R1c, val); - } - if (val & BIT3) { - pr_info("vt1603: right cld oc\n"); - val = vt1603_hw_read(codec,VT1603_R1c); - val |= BIT3; - snd_soc_write(codec, VT1603_R1c, val); - val &= ~BIT3; - snd_soc_write(codec, VT1603_R1c, val); - } -} - -static void vt1603_timer_handler(unsigned long data) -{ - struct vt1603_priv *vt1603 = (struct vt1603_priv *)data; - schedule_work(&vt1603->work); - mod_timer(&vt1603->timer, jiffies + msecs_to_jiffies(VT1603_TIMER_INTERVAL)); -} - -/*----------------------------------------------------------------------*/ - - -/*--------------------Mixer controls & dapm-----------------------------*/ - -static const DECLARE_TLV_DB_SCALE(digital_tlv, -9550, 50, 1); -static const DECLARE_TLV_DB_SCALE(digital_clv, -4350, 50, 1); -static const DECLARE_TLV_DB_SCALE(adc_boost_clv, 0, 1000, 1); -static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); -static const DECLARE_TLV_DB_SCALE(adc_pga_clv, -1650, 150, 1); -static const DECLARE_TLV_DB_SCALE(analog_tlv, -2100, 300, 1); -static const DECLARE_TLV_DB_SCALE(hp_mixer_clv, -5700, 100, 1); -static const DECLARE_TLV_DB_SCALE(cld_mixer_clv, -300, 300, 1); - -static const char *adc_cutoff_freq_txt[] = { - "Hi-fi mode", - "Voice mode 1", - "Voice mode 2", - "Voice mode 3", -}; - -static const struct soc_enum adc_cutoff_freq = -SOC_ENUM_SINGLE(VT1603_R00, 3, 4, adc_cutoff_freq_txt); - -static const char *lr_txt[] = { - "Left", "Right" -}; - -static const char *clamper_limit_voltage_txt[] = { - "Vih=2.40V, Vil=0.90V, P=0.63W", - "Vih=2.45V, Vil=0.85V, P=0.72W", - "Vih=2.50V, ViL=0.80V, P=0.81W", - "Vih=2.55V, Vil=0.75V, P=0.91W", - "Vih=2.60V, Vil=0.70V, P=1.02W", - "Vih=2.65V, Vil=0.65V, P=1.12W", - "Vih=2.70V, Vil=0.60V, P=1.24W", - "Vih=2.75V, Vil=0.55V, P=1.36W", - "Vih=2.80V, Vil=0.50V, P=1.49W", - "Vih=2.85V, Vil=0.45V, P=1.62W", - "Vih=2.90V, Vil=0.40V, P=1.76W", - "Vih=2.95V, Vil=0.35V, P=1.90W", - "Vih=3.00V, Vil=0.30V, P=2.05W", - "Vih=3.05V, Vil=0.25V, P=2.20W", - "Vih=3.10V, Vil=0.20V, P=2.37W", - "Vih=3.15V, Vil=0.15V, P=2.53W", -}; - -static const char *clamper_work_voltage_txt[] = { - "Voh=3.10V, Vol=1.90V, P=0.36W", - "Voh=3.25V, Vol=1.75V, P=0.56W", - "Voh=3.40V, Vol=1.60V, P=0.81W", - "Voh=3.55V, Vol=1.45V, P=1.10W", - "Voh=3.70V, Vol=1.30V, P=1.44W", - "Voh=3.85V, Vol=1.15V, P=1.82W", - "Voh=4.00V, Vol=1.00V, P=2.25W", - "Voh=4.15V, Vol=0.85V, P=2.72W", -}; - -static const struct soc_enum dacl_src = -SOC_ENUM_SINGLE(VT1603_R0b, 7, 2, lr_txt); - -static const struct soc_enum dacr_src = -SOC_ENUM_SINGLE(VT1603_R0b, 6, 2, lr_txt); - -static const struct soc_enum adcl_src = -SOC_ENUM_SINGLE(VT1603_R03, 3, 2, lr_txt); - -static const struct soc_enum adcr_src = -SOC_ENUM_SINGLE(VT1603_R03, 2, 2, lr_txt); - -static const struct soc_enum clamper_limit_voltage = -SOC_ENUM_SINGLE(VT1603_R87, 4, 16, clamper_limit_voltage_txt); - -static const struct soc_enum clamper_work_voltage = -SOC_ENUM_SINGLE(VT1603_R87, 0, 8, clamper_work_voltage_txt); - -static const struct snd_kcontrol_new vt1603_snd_controls[] = { -/* Volume */ -SOC_DOUBLE_R_TLV("Digital Capture Volume", VT1603_R01, VT1603_R02, 0, 0x7f, 0, digital_clv), -SOC_DOUBLE_R_TLV("Digital Playback Volume", VT1603_R07, VT1603_R08, 0, 0xc0, 0, digital_tlv), -SOC_DOUBLE_R_TLV("Analog Playback Volume", VT1603_R72, VT1603_R73, 0, 0x07, 1, analog_tlv), -SOC_DOUBLE_R_TLV("Input Boost Volume", VT1603_R64, VT1603_R65, 6, 4, 0, adc_boost_clv), -SOC_DOUBLE_R_TLV("Input PGA Volume", VT1603_R64, VT1603_R65, 1, 0x1f, 0, adc_pga_clv), -SOC_DOUBLE_TLV("Output Boost Volume", VT1603_R06, 0, 3, 7, 0, dac_boost_tlv), -SOC_DOUBLE_TLV("Output CLD Volume", VT1603_R91, 5, 2, 7, 0, cld_mixer_clv), -SOC_DOUBLE_R_TLV("Output HP Volume", VT1603_R6a, VT1603_R6b, 0, 0x3f, 0, hp_mixer_clv), - -/* Switch */ -SOC_SINGLE("EQ Switch", VT1603_R28, 0, 1, 0), - -SOC_SINGLE("DAC Mono Mix Switch", VT1603_R0d, 4, 1, 0), -SOC_SINGLE("Left DAC Switch", VT1603_R62, 5, 1, 0), -SOC_SINGLE("Right DAC Switch", VT1603_R62, 4, 1, 0), - -SOC_ENUM("Left DAC Source", dacl_src), -SOC_ENUM("Right DAC Source", dacr_src), - -SOC_ENUM("Digital Capture Voice Mode", adc_cutoff_freq), -SOC_ENUM("Left ADC Source", adcl_src), -SOC_ENUM("Right ADC Source", adcr_src), - -SOC_DOUBLE("Analog Playback Switch", VT1603_R71, 7, 6, 1, 1), -SOC_SINGLE("Digital Playback Switch", VT1603_R0b, 0, 1, 1), -SOC_DOUBLE("Digital Capture Switch", VT1603_R63, 7, 6, 1, 0), - -SOC_SINGLE("Headset Switch", VT1603_R68, 4, 1, 1), -SOC_SINGLE("Headfree Switch", VT1603_R25, 1, 1, 0), - -SOC_SINGLE("Left CLD Switch", VT1603_R82, 3, 1, 1), -SOC_SINGLE("Right CLD Switch", VT1603_R82, 4, 1, 1), - -SOC_ENUM("Limit Voltage of Power Clamper", clamper_limit_voltage), -SOC_ENUM("Voltage of Clamper Work", clamper_work_voltage), -}; - -/* DAPM Controls */ - -static const struct snd_kcontrol_new linmix_controls[] = { -SOC_DAPM_SINGLE("Left Mic Switch", VT1603_R8e, 5, 1, 0), -SOC_DAPM_SINGLE("Left Linein Switch", VT1603_R8e, 7, 1, 0), -}; - -static const struct snd_kcontrol_new rinmix_controls[] = { -SOC_DAPM_SINGLE("Right Mic Switch", VT1603_R8e, 4, 1, 0), -SOC_DAPM_SINGLE("Right Linein Switch", VT1603_R8e, 6, 1, 0), -}; - -static const struct snd_kcontrol_new loutmix_controls[] = { -SOC_DAPM_SINGLE("Left Input Mixer Switch", VT1603_R71, 3, 1, 0), -SOC_DAPM_SINGLE("DACL Switch", VT1603_R71, 1, 1, 0), -}; - -static const struct snd_kcontrol_new routmix_controls[] = { -SOC_DAPM_SINGLE("Right Input Mixer Switch", VT1603_R71, 2, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", VT1603_R71, 0, 1, 0), -}; - -static const struct snd_kcontrol_new lcld_controls[] = { -SOC_DAPM_SINGLE("Left Output Mixer Switch", VT1603_R90, 5, 1, 0), -SOC_DAPM_SINGLE("DACL Switch", VT1603_R90, 4, 1, 0), -}; - -static const struct snd_kcontrol_new rcld_controls[] = { -SOC_DAPM_SINGLE("Right Output Mixer Switch", VT1603_R90, 3, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", VT1603_R90, 2, 1, 0), -}; - -static const struct snd_kcontrol_new lhp_controls[] = { -SOC_DAPM_SINGLE("Left Output Mixer Switch", VT1603_R69, 5, 1, 0), -SOC_DAPM_SINGLE("DACL Switch", VT1603_R69, 7, 1, 0), -}; - -static const struct snd_kcontrol_new rhp_controls[] = { -SOC_DAPM_SINGLE("Right Output Mixer Switch", VT1603_R69, 2, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", VT1603_R69, 4, 1, 0), -}; - -static const struct snd_soc_dapm_widget vt1603_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("Mic"), -SND_SOC_DAPM_INPUT("Linein"), -SND_SOC_DAPM_INPUT("Internal ADC Source"), - -SND_SOC_DAPM_PGA("Left Input Boost", VT1603_R67, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Input Boost", VT1603_R67, 6, 0, NULL, 0), - -SND_SOC_DAPM_PGA("Left Input PGA", VT1603_R67, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Input PGA", VT1603_R67, 4, 0, NULL, 0), - - -SND_SOC_DAPM_MIXER("Left Input Mixer", VT1603_R66, 6, 1, - linmix_controls, ARRAY_SIZE(linmix_controls)), -SND_SOC_DAPM_MIXER("Right Input Mixer", VT1603_R66, 5, 1, - rinmix_controls, ARRAY_SIZE(rinmix_controls)), - -SND_SOC_DAPM_ADC("ADCL", "Left Capture", VT1603_R01, 7, 1), -SND_SOC_DAPM_ADC("ADCR", "Right Capture", VT1603_R02, 7, 1), - -//SND_SOC_DAPM_DAC("DACL", "Left Playback", VT1603_R62, 5, 0), -//SND_SOC_DAPM_DAC("DACR", "Right Playback", VT1603_R62, 4, 0), - -SND_SOC_DAPM_INPUT("DACL"), -SND_SOC_DAPM_INPUT("DACR"), - -SND_SOC_DAPM_MIXER("Left Output Mixer", VT1603_R72, 6, 0, - loutmix_controls, ARRAY_SIZE(loutmix_controls)), -SND_SOC_DAPM_MIXER("Right Output Mixer", VT1603_R73, 6, 0, - routmix_controls, ARRAY_SIZE(routmix_controls)), - -SND_SOC_DAPM_MIXER("Left CLD Mixer", VT1603_R91, 1, 0, - lcld_controls, ARRAY_SIZE(lcld_controls)), -SND_SOC_DAPM_MIXER("Right CLD Mixer", VT1603_R91, 0, 0, - rcld_controls, ARRAY_SIZE(rcld_controls)), - -SND_SOC_DAPM_PGA("Left CLD PGA", VT1603_R82, 3, 1, NULL, 0), -SND_SOC_DAPM_PGA("Right CLD PGA", VT1603_R82, 4, 1, NULL, 0), - -SND_SOC_DAPM_MIXER("Left HP Mixer", VT1603_R68, 1, 1, - lhp_controls, ARRAY_SIZE(lhp_controls)), -SND_SOC_DAPM_MIXER("Right HP Mixer", VT1603_R68, 0, 1, - rhp_controls, ARRAY_SIZE(rhp_controls)), - -SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), -SND_SOC_DAPM_OUTPUT("Left HP"), -SND_SOC_DAPM_OUTPUT("Right HP"), -SND_SOC_DAPM_OUTPUT("Left SPK"), -SND_SOC_DAPM_OUTPUT("Right SPK"), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Make DACs turn on when playing even if not mixed into any outputs */ - //{"Internal DAC Sink", NULL, "DACL"}, - //{"Internal DAC Sink", NULL, "DACR"}, - - /* Make ADCs turn on when recording even if not mixed from any inputs */ - //{"ADCL", NULL, "Internal ADC Source"}, - //{"ADCR", NULL, "Internal ADC Source"}, - - - /* Capture route */ - - { "Left Input Mixer", "Left Linein Switch", "Linein" }, - { "Left Input Mixer", "Left Mic Switch", "Mic" }, - { "Right Input Mixer", "Right Linein Switch", "Linein" }, - { "Right Input Mixer", "Right Mic Switch", "Mic" }, - - { "Left Input Boost", NULL, "Left Input Mixer"}, - { "Right Input Boost", NULL, "Right Input Mixer"}, - - { "Left Input PGA", NULL, "Left Input Boost"}, - { "Right Input PGA", NULL, "Right Input Boost"}, - - { "ADCL", NULL, "Left Input PGA" }, - { "ADCR", NULL, "Right Input PGA" }, - - //{ "Left Input Mixer", NULL, "Left Input PGA" }, - //{ "Right Input Mixer", NULL, "Right Input PGA" }, - - /* Playback route */ - - //{ "Left Output Mixer", "Left Input Mixer Switch", "Left Input Mixer" }, - { "Left Output Mixer", "Left Input Mixer Switch", "Left Input PGA"}, - { "Left Output Mixer", "DACL Switch", "DACL" }, - //{ "Right Output Mixer", "Right Input Mixer Switch", "Right Input Mixer" }, - { "Right Output Mixer", "Right Input Mixer Switch", "Right Input PGA"}, - { "Right Output Mixer", "DACR Switch", "DACR" }, - - { "Left CLD Mixer", "Left Output Mixer Switch", "Left Output Mixer" }, - { "Left CLD Mixer", "DACL Switch", "DACL" }, - { "Right CLD Mixer", "Right Output Mixer Switch", "Right Output Mixer" }, - { "Right CLD Mixer", "DACR Switch", "DACR" }, - - { "Left HP Mixer", "Left Output Mixer Switch", "Left Output Mixer" }, - { "Left HP Mixer", "DACL Switch", "DACL" }, - { "Right HP Mixer", "Right Output Mixer Switch", "Right Output Mixer" }, - { "Right HP Mixer", "DACR Switch", "DACR" }, - - { "Left CLD PGA", NULL, "Left CLD Mixer" }, - { "Right CLD PGA", NULL, "Right CLD Mixer" }, - - { "Left HP", NULL, "Left HP Mixer" }, - { "Right HP", NULL, "Right HP Mixer" }, - - { "Left SPK", NULL, "Left CLD PGA" }, - { "Right SPK", NULL, "Right CLD PGA" }, -}; - -/*----------------------------------------------------------------------*/ - - -/*----------------------codec dai functions-----------------------------*/ - -struct _coeff_div { - u32 mclk; - u32 rate; - u16 fs; - u8 sr; - u8 bclk_div; -}; - -/* codec hifi mclk clock divider coefficients */ -static const struct _coeff_div coeff_div[] = { - /* 8k */ - {12288000, 8000, 1536, 0x4, 0x0}, - /* 11.025k */ - {11289600, 11025, 1024, 0x8, 0x0}, - /* 16k */ - {12288000, 16000, 768, 0x5, 0x0}, - /* 22.05k */ - {11289600, 22050, 512, 0x9, 0x0}, - /* 32k */ - {12288000, 32000, 384, 0x7, 0x0}, - /* 44.1k */ - {11289600, 44100, 256, 0x6, 0x07}, - /* 48k */ - {12288000, 48000, 256, 0x0, 0x07}, - /* 96k */ - {12288000, 96000, 128, 0x1, 0x04}, -}; - -static inline int get_coeff(int mclk, int rate) -{ - int i; - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) - return i; - } - return -EINVAL; -} - -static int vt1603_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct vt1603_priv *vt1603 = snd_soc_codec_get_drvdata(codec); - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - vt1603->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int vt1603_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = snd_soc_read(codec, VT1603_R19); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface |= BIT5 ; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, VT1603_R19, iface); - return 0; -} - -static int vt1603_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct vt1603_priv *vt1603 = snd_soc_codec_get_drvdata(codec); - u16 val; - u16 iface = snd_soc_read(codec, VT1603_R19) & 0x73; - int coeff = get_coeff(vt1603->sysclk, params_rate(params)); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x04; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x08; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x0c; - break; - } - - /* set iface & srate */ - snd_soc_write(codec, VT1603_R19, iface); - - if (coeff >= 0) { - val = snd_soc_read(codec, VT1603_R42); - val &= 0xf0; - val |= coeff_div[coeff].bclk_div; - snd_soc_write(codec, VT1603_R42, val); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - val = snd_soc_read(codec, VT1603_R05); - val &= 0xf0; - val |= coeff_div[coeff].sr; - snd_soc_write(codec, VT1603_R05, val); - } - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - val = snd_soc_read(codec, VT1603_R03); - val &= 0x0f; - val |= ((coeff_div[coeff].sr<<4) & 0xf0); - snd_soc_write(codec, VT1603_R03, val); - } - } - - return 0; -} - -static int vt1603_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 val; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - val = snd_soc_read(codec, VT1603_R96); - val |= BIT4+BIT5; - snd_soc_write(codec, VT1603_R96, val); - break; - - case SND_SOC_BIAS_STANDBY: - break; - - case SND_SOC_BIAS_OFF: - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -static struct snd_soc_dai_ops vt1603_dai_ops = { - .hw_params = vt1603_pcm_hw_params, - .set_fmt = vt1603_set_dai_fmt, - .set_sysclk = vt1603_set_dai_sysclk, -}; - -struct snd_soc_dai_driver vt1603_dai = { - .name = "VT1603", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &vt1603_dai_ops, -}; - -/*----------------------------------------------------------------------*/ - - -/*----------------------------------------------------------------------*/ - -static void vt1603_get_boardinfo(void) -{ - int ret = 0; - unsigned char buf[64]; - int varlen = sizeof(buf); - - memset(buf, 0x0, sizeof(buf)); - ret = wmt_getsyspara("wmt.audio.i2s", buf, &varlen); - if (ret == 0) { - sscanf(buf, "vt1603:%d:%d:%d", - &vt1603_boardinfo.hp_level, - &vt1603_boardinfo.ignore_hp_event, - &vt1603_boardinfo.rec_src); - } - else { - vt1603_boardinfo.hp_level = 0; - vt1603_boardinfo.ignore_hp_event = 0; - vt1603_boardinfo.rec_src = 0; - } - - memset(buf, 0x0, sizeof(buf)); - vt1603_boardinfo.hpd_rm = 0; - ret = wmt_getsyspara("wmt.vt1603.hpd.rm", buf, &varlen); - if (ret == 0) { - sscanf(buf, "%d", - &vt1603_boardinfo.hpd_rm); - } - else { - vt1603_boardinfo.hpd_rm = 0; - - } - printk("<<<<%s hpd_rm %d\n", __func__, vt1603_boardinfo.hpd_rm); - - memset(buf, 0x0, sizeof(buf)); - vt1603_boardinfo.hp_debounce = 0; - ret = wmt_getsyspara("wmt.vt1603.hp.debounce", buf, &varlen); - if (ret == 0) { - sscanf(buf, "%d", - &vt1603_boardinfo.hp_debounce); - } - else { - vt1603_boardinfo.hp_debounce = 0; - - } - printk("<<<<%s hp_debounce %d\n", __func__, vt1603_boardinfo.hp_debounce); - - - memset(buf, 0x0, sizeof(buf)); - vt1603_boardinfo.timer_del = 0; - ret = wmt_getsyspara("wmt.vt1603.timer.del", buf, &varlen); - if (ret == 0) { - sscanf(buf, "%d", - &vt1603_boardinfo.timer_del); - } - else { - vt1603_boardinfo.timer_del = 0; - - } - printk("<<<<%s timer_del %d\n", __func__, vt1603_boardinfo.timer_del); - - memset(buf, 0x0, sizeof(buf)); - vt1603_boardinfo.out_on = 0; - ret = wmt_getsyspara("wmt.vt1603.out_on", buf, &varlen); - if (ret == 0) { - sscanf(buf, "%d", - &vt1603_boardinfo.out_on); - } - else { - vt1603_boardinfo.out_on = 0; - - } - printk("<<<<%s out_on %d\n", __func__, vt1603_boardinfo.out_on); -} - -static int vt1603_readproc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct vt1603_priv *vt1603 = data; - pr_info("\nvt1603 regs dump:\n"); - vt1603_regs_dump(vt1603->codec->control_data); - return 0; -} - -static void vt1603_codec_reset(struct snd_soc_codec *codec) -{ - unsigned int val; - - vt1603_hw_write(codec, 0xc2, 0x01); - - // reset all registers to default settings - vt1603_hw_write(codec, VT1603_REG_RESET, 0xff); - vt1603_hw_write(codec, VT1603_REG_RESET, 0x00); - - val = vt1603_hw_read(codec, VT1603_R60); - val &= ~(BIT6 + BIT7); - vt1603_hw_write(codec, VT1603_R60, val); - val |= BIT6 + BIT7; - vt1603_hw_write(codec, VT1603_R60, val); -} - -static void vt1603_codec_init(struct snd_soc_codec *codec) -{ - unsigned int val; - - // vt1603 touch uses irq low active??? - if (vt1603_boardinfo.hp_level) { - //hp high - snd_soc_write(codec, VT1603_R21, 0xfd); - } - else { - //hp low - snd_soc_write(codec, VT1603_R21, 0xff); - } - - // vt1603 codec irq settings - snd_soc_write(codec, VT1603_R1b, 0xff); - snd_soc_write(codec, VT1603_R1b, 0xfd); - snd_soc_write(codec, VT1603_R1c, 0xff); - snd_soc_write(codec, VT1603_R1d, 0xff); - snd_soc_write(codec, VT1603_R24, 0x04); - - snd_soc_write(codec, VT1603_R95, 0x00); - snd_soc_write(codec, VT1603_R60, 0xc7); - snd_soc_write(codec, VT1603_R93, 0x02); - snd_soc_write(codec, VT1603_R7b, 0x10); - snd_soc_write(codec, VT1603_R92, 0x2c); - - // r4 is reserved, I don't know more about it. - snd_soc_write(codec, VT1603_R04, 0x00); - // r9[5] is reserved, I don't know more about it. - val = snd_soc_read(codec, VT1603_R09); - val |= BIT5; - snd_soc_write(codec, VT1603_R09, val); - // r79 is reserved, I don't know more about it. - val = snd_soc_read(codec, VT1603_R79); - val |= BIT2; - val &= ~(BIT0+BIT1); - snd_soc_write(codec, VT1603_R79, val); - // r7a is reserved, I don't know more about it. - val = snd_soc_read(codec, VT1603_R7a); - val |= BIT3+BIT4+BIT7; - snd_soc_write(codec, VT1603_R7a, val); - // r87 is reserved, I don't know more about it. - snd_soc_write(codec, VT1603_R87, 0x90); - // r88 is reserved, I don't know more about it. - snd_soc_write(codec, VT1603_R88, 0x28); - // r8a is reserved, I don't know more about it. - val = snd_soc_read(codec, VT1603_R8a); - val |= BIT1; - snd_soc_write(codec, VT1603_R8a, val); - // enable CLK_SYS, CLK_DSP, CLK_AIF - val = snd_soc_read(codec, VT1603_R40); - val |= BIT4+BIT5+BIT6; - snd_soc_write(codec, VT1603_R40, val); - // set DAC sample rate divier=CLK_SYS/1, DAC clock divider=DAC_CLK_512X - val = snd_soc_read(codec, VT1603_R41); - val &= ~(BIT3+BIT2+BIT1+BIT0); - val |= BIT1;//add for mclk 24.576M, 10Khz 17kHz sine distortion 2014-6-12 - snd_soc_write(codec, VT1603_R41, val); - // set BCLK rate=CLK_SYS/8 - val = snd_soc_read(codec, VT1603_R42); - val |= BIT0+BIT1+BIT2; - val &= ~BIT3; - snd_soc_write(codec, VT1603_R42, val); - // enable VREF_SC_DA buffer - val = snd_soc_read(codec, VT1603_R61); - val |= BIT7; - snd_soc_write(codec, VT1603_R61, val); - // ADC VREF_SC offset voltage - snd_soc_write(codec, VT1603_R93, 0x20); - // set mic bias voltage = 90% * AVDD - val = snd_soc_read(codec, VT1603_R92); - val |= BIT2; - snd_soc_write(codec, VT1603_R92, val); - // enable bypass for AOW0 parameterized HPF - val = snd_soc_read(codec, VT1603_R0a); - val |= BIT6; - snd_soc_write(codec, VT1603_R0a, val); - // CPVEE=2.2uF, the ripple frequency ON CPVEE above 22kHz, that will reduce HP noise - val = snd_soc_read(codec, VT1603_R7a); - val |= BIT6; - val &= ~BIT5; - snd_soc_write(codec, VT1603_R7a, val); - - // set DAC soft mute mode - val = snd_soc_read(codec, VT1603_R0b); - val |= BIT1+BIT2; - snd_soc_write(codec, VT1603_R0b, val); - // DAC High Voltage Switch Control Signal enable??? - val = snd_soc_read(codec, VT1603_R62); - val |= BIT7+BIT6; - val &= ~BIT3; - snd_soc_write(codec, VT1603_R62, val); - // enable microphone bias - val = snd_soc_read(codec, VT1603_R60); - val |= 0x0f; - snd_soc_write(codec, VT1603_R60, val); - // capture pga settings?? - val = snd_soc_read(codec, VT1603_R8e); - val |= 0x0f; - snd_soc_write(codec, VT1603_R8e, val); - // capture pga settings?? - val = snd_soc_read(codec, VT1603_R66); - val |= BIT1+BIT2+BIT3+BIT4; // - snd_soc_write(codec, VT1603_R66, val); - // PGA Zero Cross Detector Enable, Change gain on zero cross only - val = snd_soc_read(codec, VT1603_R64); - val |= BIT0; - snd_soc_write(codec, VT1603_R64, val); - val = snd_soc_read(codec, VT1603_R65); - val |= BIT0; - snd_soc_write(codec, VT1603_R65, val); - // enable hp output mode - val = snd_soc_read(codec, VT1603_R68); - val |= BIT2; - snd_soc_write(codec, VT1603_R68, val); - // enable class-d, unmute channels - snd_soc_write(codec, VT1603_R7c, 0xe0); - - // set DAC gain update - val = snd_soc_read(codec, VT1603_R05); - val |= BIT6+BIT7; - snd_soc_write(codec, VT1603_R05, val); - // set class-d AC boost gain=1.6 - snd_soc_write(codec, VT1603_R97, 0x1c); - val = snd_soc_read(codec, VT1603_R97); - val = (val & (~0x07)) + 0x04; - snd_soc_write(codec, VT1603_R97, val); - // set ADC gain update, enable ADCDAT output - val = snd_soc_read(codec, VT1603_R00); - val |= BIT5+BIT6+BIT7; - snd_soc_write(codec, VT1603_R00, val); - - if (vt1603_boardinfo.out_on) - { - val = snd_soc_read(codec, VT1603_R68); - val &= ~(1<<4); - snd_soc_write(codec, VT1603_R68, val); - - val = snd_soc_read(codec, VT1603_R69); - val |= BIT2 +BIT5; - snd_soc_write(codec, VT1603_R69, val); - - - val = snd_soc_read(codec, VT1603_R25); - val |= BIT1; - snd_soc_write(codec, VT1603_R25, val); - - val = snd_soc_read(codec, VT1603_R90); - val |= BIT5 +BIT3; - snd_soc_write(codec, VT1603_R90, val); - - } - // DA DRC settings - //snd_soc_write(codec, VT1603_R0e, 0x0b); - //snd_soc_write(codec, VT1603_R0f, 0x94); - //snd_soc_write(codec, VT1603_R10, 0x02); - //snd_soc_write(codec, VT1603_R11, 0x00); - //snd_soc_write(codec, VT1603_R12, 0x60); -} - -static int vt1603_reboot_notify(struct notifier_block *this, - unsigned long code, void *unused) -{ - unsigned int val; - struct vt1603_priv *priv = container_of(this, struct vt1603_priv, reboot_notifier); - struct snd_soc_codec *codec = priv->codec; - - printk("vt1603_reboot_notify [%lu]\n", code); - - // power down headphone - val = snd_soc_read(codec, VT1603_R68); - val |= BIT4; - snd_soc_write(codec, VT1603_R68, val); - - // power down class-d - val = snd_soc_read(codec, VT1603_R25); - val &= ~BIT1; - snd_soc_write(codec, VT1603_R25, val); - - return NOTIFY_DONE; -} - -/*----------------------------------------------------------------------*/ - - -/*---------------------codec driver functions---------------------------*/ - -static int vt1603_codec_suspend(struct snd_soc_codec *codec) -{ - struct vt1603_priv *vt1603 = snd_soc_codec_get_drvdata(codec); - if (!vt1603_boardinfo.timer_del) { //add 2014-1-22 tvbox - del_timer_sync(&vt1603->timer); - } - return 0; -} - -static int vt1603_codec_resume(struct snd_soc_codec *codec) -{ - struct vt1603_priv *vt1603 = snd_soc_codec_get_drvdata(codec); - int reg; - u16 *cache = codec->reg_cache; - unsigned int val; - int state = 0;//switch_get_state(&vt1603->hp_switch); - if (!vt1603_boardinfo.hpd_rm) - state = switch_get_state(&vt1603->hp_switch); - // reset codec - vt1603_codec_reset(codec); - - // restore codec registers - for (reg = 0; reg < ARRAY_SIZE(vt1603_regs); reg++) { - if (reg == VT1603_REG_RESET) - continue; - snd_soc_write(codec, reg, cache[reg]); - } - - // restore headphone irq status - val = vt1603_hw_read(codec, VT1603_R21); - if ((vt1603_boardinfo.hp_level && state) || - (!vt1603_boardinfo.hp_level && !state)) { - val |= BIT1; - snd_soc_write(codec, VT1603_R21, val); - } - else { - val &= ~BIT1; - snd_soc_write(codec, VT1603_R21, val); - } - - // open headphone detect - val = vt1603_hw_read(codec,VT1603_R1b); - val |= BIT1; - snd_soc_write(codec, VT1603_R1b, val); - val &= ~BIT1; - snd_soc_write(codec, VT1603_R1b, val); - - // clear touch interrupt status??? why here??? - snd_soc_write(codec, 0xca, 0x0f); - - if (!vt1603_boardinfo.timer_del) { //add 2014-1-22 tvbox - mod_timer(&vt1603->timer, jiffies + msecs_to_jiffies(50)); - } - - return 0; -} - -static int vt1603_codec_probe(struct snd_soc_codec *codec) -{ - struct vt1603_priv *vt1603; - int ret; - - vt1603 = kzalloc(sizeof(struct vt1603_priv), GFP_KERNEL); - if (vt1603 == NULL) - return -ENOMEM; - - gvt1603_codec = codec;//add 2013-9-2 - snd_soc_codec_set_drvdata(codec, vt1603); - - codec->control_data = dev_get_platdata(codec->dev); - - vt1603->codec = codec; -// need close to use wmt-switch.c 2013-11-27 - if (!vt1603_boardinfo.hpd_rm) { - vt1603->hp_switch.name = "h2w"; - switch_dev_register(&vt1603->hp_switch); - } -//need close - vt1603_codec_reset(codec); - vt1603_codec_init(codec); - vt1603_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - - INIT_WORK(&vt1603->work, vt1603_codec_irq_handle); - if (!vt1603_boardinfo.timer_del) { //add 2014-1-20 tvbox - init_timer(&vt1603->timer); - vt1603->timer.data = (unsigned long)vt1603; - vt1603->timer.function = vt1603_timer_handler; - mod_timer(&vt1603->timer, jiffies + msecs_to_jiffies(2000)); - } - - vt1603->proc = create_proc_read_entry("vt1603_dumpregs", 0666, NULL, - vt1603_readproc, vt1603); - - // register reboot notifier event - vt1603->reboot_notifier.notifier_call = vt1603_reboot_notify; - ret = register_reboot_notifier(&vt1603->reboot_notifier); - if (ret != 0) - pr_err("cannot register reboot notifier (err=%d)\n", ret); - - return 0; -} - -static int vt1603_codec_remove(struct snd_soc_codec *codec) -{ - struct vt1603_priv *vt1603 = snd_soc_codec_get_drvdata(codec); - remove_proc_entry("vt1603_dumpregs", NULL); - if (!vt1603_boardinfo.hpd_rm) { - switch_dev_unregister(&vt1603->hp_switch); - } - del_timer_sync(&vt1603->timer); - vt1603_set_bias_level(codec, SND_SOC_BIAS_OFF); - kfree(vt1603); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_vt1603 = { - .probe = vt1603_codec_probe, - .remove = vt1603_codec_remove, - .suspend = vt1603_codec_suspend, - .resume = vt1603_codec_resume, - .read = vt1603_read, - .write = vt1603_write, - .set_bias_level = vt1603_set_bias_level, - .reg_cache_size = ARRAY_SIZE(vt1603_regs), - .reg_word_size = sizeof(u16), - .reg_cache_default = vt1603_regs, - - .controls = vt1603_snd_controls, - .num_controls = ARRAY_SIZE(vt1603_snd_controls), - .dapm_widgets = vt1603_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(vt1603_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), -}; - -static int __devinit vt1603_probe(struct platform_device *pdev) -{ - pr_info("<<<<%s \n", __FUNCTION__); - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_vt1603, - &vt1603_dai, 1); -} - -static int __devexit vt1603_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver vt1603_codec_driver = { - .driver = { - .name = "vt1603-codec", - .owner = THIS_MODULE, - }, - .probe = vt1603_probe, - .remove = __devexit_p(vt1603_remove), -}; - -static __init int vt1603_init(void) -{ - vt1603_get_boardinfo(); - return platform_driver_register(&vt1603_codec_driver); -} -module_init(vt1603_init); - -static __exit void vt1603_exit(void) -{ - platform_driver_unregister(&vt1603_codec_driver); -} -module_exit(vt1603_exit); - -int vt1603_hwdep_ioctl(u8 rw_flag, u16 offset, u16 value) -{ - struct snd_soc_codec *codec = gvt1603_codec; - if (!codec){ - printk("%s NULL!\n", __FUNCTION__); - return -1; - } - //info("rw_flag=%d, offset=0x%x, value=0x%x", rw_flag, offset, value); - - if (rw_flag) { - if ((offset >= VT1603_R00) && (offset <= VT1603_R97)) { - snd_soc_write(codec, offset, value); - } - else { - printk("write to offset 0x%x is not allowed", offset); - } - return 0; - } - else { - return snd_soc_read(codec, offset); - } -} -EXPORT_SYMBOL(vt1603_hwdep_ioctl); - -MODULE_DESCRIPTION("WMT [ALSA SoC/codec] driver"); -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:vt1603-codec"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/vt1603.h b/ANDROID_3.4.5/sound/soc/codecs/vt1603.h deleted file mode 100755 index ef130f10..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/vt1603.h +++ /dev/null @@ -1,119 +0,0 @@ -/*++ - * linux/sound/soc/codecs/vt1603.h - * WonderMedia audio driver for ALSA - * - * Copyright c 2010 WonderMedia Technologies, Inc. - * - * 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, see . - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ - -#ifndef _VT1603_H -#define _VT1603_H - -#define BIT0 0x00000001 -#define BIT1 0x00000002 -#define BIT2 0x00000004 -#define BIT3 0x00000008 -#define BIT4 0x00000010 -#define BIT5 0x00000020 -#define BIT6 0x00000040 -#define BIT7 0x00000080 -#define BIT8 0x00000100 - -#define VT1603_REG_RESET 0x15 - -#define VT1603_R00 0x00 -#define VT1603_R01 0x01 -#define VT1603_R02 0x02 -#define VT1603_R03 0x03 -#define VT1603_R04 0x04 -#define VT1603_R05 0x05 -#define VT1603_R06 0x06 -#define VT1603_R07 0x07 -#define VT1603_R08 0x08 -#define VT1603_R09 0x09 -#define VT1603_R0a 0x0a -#define VT1603_R0b 0x0b -#define VT1603_R0c 0x0c -#define VT1603_R0d 0x0d -#define VT1603_R0e 0x0e -#define VT1603_R0f 0x0f -#define VT1603_R10 0x10 -#define VT1603_R11 0x11 -#define VT1603_R12 0x12 -#define VT1603_R13 0x13 -#define VT1603_R15 0x15 -#define VT1603_R19 0x19 -#define VT1603_R1b 0x1b -#define VT1603_R1c 0x1c -#define VT1603_R1d 0x1d -#define VT1603_R20 0x20 -#define VT1603_R21 0x21 -#define VT1603_R23 0x23 -#define VT1603_R24 0x24 -#define VT1603_R25 0x25 -#define VT1603_R28 0x28 -#define VT1603_R29 0x29 -#define VT1603_R2a 0x2a -#define VT1603_R2b 0x2b -#define VT1603_R2c 0x2c -#define VT1603_R2d 0x2d -#define VT1603_R40 0x40 -#define VT1603_R41 0x41 -#define VT1603_R42 0x42 -#define VT1603_R47 0x47 -#define VT1603_R51 0x51 -#define VT1603_R52 0x52 -#define VT1603_R53 0x53 -#define VT1603_R5f 0x5f -#define VT1603_R60 0x60 -#define VT1603_R61 0x61 -#define VT1603_R62 0x62 -#define VT1603_R63 0x63 -#define VT1603_R64 0x64 -#define VT1603_R65 0x65 -#define VT1603_R66 0x66 -#define VT1603_R67 0x67 -#define VT1603_R68 0x68 -#define VT1603_R69 0x69 -#define VT1603_R6a 0x6a -#define VT1603_R6b 0x6b -#define VT1603_R6d 0x6d -#define VT1603_R6e 0x6e -#define VT1603_R70 0x70 -#define VT1603_R71 0x71 -#define VT1603_R72 0x72 -#define VT1603_R73 0x73 -#define VT1603_R77 0x77 -#define VT1603_R79 0x79 -#define VT1603_R7a 0x7a -#define VT1603_R7b 0x7b -#define VT1603_R7c 0x7c -#define VT1603_R82 0x82 -#define VT1603_R87 0x87 -#define VT1603_R88 0x88 -#define VT1603_R8a 0x8a -#define VT1603_R8e 0x8e -#define VT1603_R90 0x90 -#define VT1603_R91 0x91 -#define VT1603_R92 0x92 -#define VT1603_R93 0x93 -#define VT1603_R95 0x95 -#define VT1603_R96 0x96 -#define VT1603_R97 0x97 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wl1273.c b/ANDROID_3.4.5/sound/soc/codecs/wl1273.c deleted file mode 100644 index 3d868dc4..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wl1273.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * ALSA SoC WL1273 codec driver - * - * Author: Matti Aaltonen, - * - * Copyright: (C) 2010, 2011 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "wl1273.h" - -enum wl1273_mode { WL1273_MODE_BT, WL1273_MODE_FM_RX, WL1273_MODE_FM_TX }; - -/* codec private data */ -struct wl1273_priv { - enum wl1273_mode mode; - struct wl1273_core *core; - unsigned int channels; -}; - -static int snd_wl1273_fm_set_i2s_mode(struct wl1273_core *core, - int rate, int width) -{ - struct device *dev = &core->client->dev; - int r = 0; - u16 mode; - - dev_dbg(dev, "rate: %d\n", rate); - dev_dbg(dev, "width: %d\n", width); - - mutex_lock(&core->lock); - - mode = core->i2s_mode & ~WL1273_IS2_WIDTH & ~WL1273_IS2_RATE; - - switch (rate) { - case 48000: - mode |= WL1273_IS2_RATE_48K; - break; - case 44100: - mode |= WL1273_IS2_RATE_44_1K; - break; - case 32000: - mode |= WL1273_IS2_RATE_32K; - break; - case 22050: - mode |= WL1273_IS2_RATE_22_05K; - break; - case 16000: - mode |= WL1273_IS2_RATE_16K; - break; - case 12000: - mode |= WL1273_IS2_RATE_12K; - break; - case 11025: - mode |= WL1273_IS2_RATE_11_025; - break; - case 8000: - mode |= WL1273_IS2_RATE_8K; - break; - default: - dev_err(dev, "Sampling rate: %d not supported\n", rate); - r = -EINVAL; - goto out; - } - - switch (width) { - case 16: - mode |= WL1273_IS2_WIDTH_32; - break; - case 20: - mode |= WL1273_IS2_WIDTH_40; - break; - case 24: - mode |= WL1273_IS2_WIDTH_48; - break; - case 25: - mode |= WL1273_IS2_WIDTH_50; - break; - case 30: - mode |= WL1273_IS2_WIDTH_60; - break; - case 32: - mode |= WL1273_IS2_WIDTH_64; - break; - case 40: - mode |= WL1273_IS2_WIDTH_80; - break; - case 48: - mode |= WL1273_IS2_WIDTH_96; - break; - case 64: - mode |= WL1273_IS2_WIDTH_128; - break; - default: - dev_err(dev, "Data width: %d not supported\n", width); - r = -EINVAL; - goto out; - } - - dev_dbg(dev, "WL1273_I2S_DEF_MODE: 0x%04x\n", WL1273_I2S_DEF_MODE); - dev_dbg(dev, "core->i2s_mode: 0x%04x\n", core->i2s_mode); - dev_dbg(dev, "mode: 0x%04x\n", mode); - - if (core->i2s_mode != mode) { - r = core->write(core, WL1273_I2S_MODE_CONFIG_SET, mode); - if (r) - goto out; - - core->i2s_mode = mode; - r = core->write(core, WL1273_AUDIO_ENABLE, - WL1273_AUDIO_ENABLE_I2S); - if (r) - goto out; - } -out: - mutex_unlock(&core->lock); - - return r; -} - -static int snd_wl1273_fm_set_channel_number(struct wl1273_core *core, - int channel_number) -{ - struct device *dev = &core->client->dev; - int r = 0; - - dev_dbg(dev, "%s\n", __func__); - - mutex_lock(&core->lock); - - if (core->channel_number == channel_number) - goto out; - - if (channel_number == 1 && core->mode == WL1273_MODE_RX) - r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_MONO); - else if (channel_number == 1 && core->mode == WL1273_MODE_TX) - r = core->write(core, WL1273_MONO_SET, WL1273_TX_MONO); - else if (channel_number == 2 && core->mode == WL1273_MODE_RX) - r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_STEREO); - else if (channel_number == 2 && core->mode == WL1273_MODE_TX) - r = core->write(core, WL1273_MONO_SET, WL1273_TX_STEREO); - else - r = -EINVAL; -out: - mutex_unlock(&core->lock); - - return r; -} - -static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = wl1273->mode; - - return 0; -} - -/* - * TODO: Implement the audio routing in the driver. Now this control - * only indicates the setting that has been done elsewhere (in the user - * space). - */ -static const char * const wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" }; - -static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); - - if (wl1273->mode == ucontrol->value.integer.value[0]) - return 0; - - /* Do not allow changes while stream is running */ - if (codec->active) - return -EPERM; - - if (ucontrol->value.integer.value[0] < 0 || - ucontrol->value.integer.value[0] >= ARRAY_SIZE(wl1273_audio_route)) - return -EINVAL; - - wl1273->mode = ucontrol->value.integer.value[0]; - - return 1; -} - -static const struct soc_enum wl1273_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route); - -static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); - - dev_dbg(codec->dev, "%s: enter.\n", __func__); - - ucontrol->value.integer.value[0] = wl1273->core->audio_mode; - - return 0; -} - -static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); - int val, r = 0; - - dev_dbg(codec->dev, "%s: enter.\n", __func__); - - val = ucontrol->value.integer.value[0]; - if (wl1273->core->audio_mode == val) - return 0; - - r = wl1273->core->set_audio(wl1273->core, val); - if (r < 0) - return r; - - return 1; -} - -static const char * const wl1273_audio_strings[] = { "Digital", "Analog" }; - -static const struct soc_enum wl1273_audio_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings), - wl1273_audio_strings); - -static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); - - dev_dbg(codec->dev, "%s: enter.\n", __func__); - - ucontrol->value.integer.value[0] = wl1273->core->volume; - - return 0; -} - -static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); - int r; - - dev_dbg(codec->dev, "%s: enter.\n", __func__); - - r = wl1273->core->set_volume(wl1273->core, - ucontrol->value.integer.value[0]); - if (r) - return r; - - return 1; -} - -static const struct snd_kcontrol_new wl1273_controls[] = { - SOC_ENUM_EXT("Codec Mode", wl1273_enum, - snd_wl1273_get_audio_route, snd_wl1273_set_audio_route), - SOC_ENUM_EXT("Audio Switch", wl1273_audio_enum, - snd_wl1273_fm_audio_get, snd_wl1273_fm_audio_put), - SOC_SINGLE_EXT("Volume", 0, 0, WL1273_MAX_VOLUME, 0, - snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put), -}; - -static int wl1273_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); - - switch (wl1273->mode) { - case WL1273_MODE_BT: - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - 8000, 8000); - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, 1, 1); - break; - case WL1273_MODE_FM_RX: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - pr_err("Cannot play in RX mode.\n"); - return -EINVAL; - } - break; - case WL1273_MODE_FM_TX: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - pr_err("Cannot capture in TX mode.\n"); - return -EINVAL; - } - break; - default: - return -EINVAL; - break; - } - - return 0; -} - -static int wl1273_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(rtd->codec); - struct wl1273_core *core = wl1273->core; - unsigned int rate, width, r; - - if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) { - pr_err("Only SNDRV_PCM_FORMAT_S16_LE supported.\n"); - return -EINVAL; - } - - rate = params_rate(params); - width = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; - - if (wl1273->mode == WL1273_MODE_BT) { - if (rate != 8000) { - pr_err("Rate %d not supported.\n", params_rate(params)); - return -EINVAL; - } - - if (params_channels(params) != 1) { - pr_err("Only mono supported.\n"); - return -EINVAL; - } - - return 0; - } - - if (wl1273->mode == WL1273_MODE_FM_TX && - substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - pr_err("Only playback supported with TX.\n"); - return -EINVAL; - } - - if (wl1273->mode == WL1273_MODE_FM_RX && - substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - pr_err("Only capture supported with RX.\n"); - return -EINVAL; - } - - if (wl1273->mode != WL1273_MODE_FM_RX && - wl1273->mode != WL1273_MODE_FM_TX) { - pr_err("Unexpected mode: %d.\n", wl1273->mode); - return -EINVAL; - } - - r = snd_wl1273_fm_set_i2s_mode(core, rate, width); - if (r) - return r; - - wl1273->channels = params_channels(params); - r = snd_wl1273_fm_set_channel_number(core, wl1273->channels); - if (r) - return r; - - return 0; -} - -static const struct snd_soc_dai_ops wl1273_dai_ops = { - .startup = wl1273_startup, - .hw_params = wl1273_hw_params, -}; - -static struct snd_soc_dai_driver wl1273_dai = { - .name = "wl1273-fm", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE}, - .ops = &wl1273_dai_ops, -}; - -/* Audio interface format for the soc_card driver */ -int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt) -{ - struct wl1273_priv *wl1273; - - if (codec == NULL || fmt == NULL) - return -EINVAL; - - wl1273 = snd_soc_codec_get_drvdata(codec); - - switch (wl1273->mode) { - case WL1273_MODE_FM_RX: - case WL1273_MODE_FM_TX: - *fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM; - - break; - case WL1273_MODE_BT: - *fmt = SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM; - - break; - default: - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(wl1273_get_format); - -static int wl1273_probe(struct snd_soc_codec *codec) -{ - struct wl1273_core **core = codec->dev->platform_data; - struct wl1273_priv *wl1273; - int r; - - dev_dbg(codec->dev, "%s.\n", __func__); - - if (!core) { - dev_err(codec->dev, "Platform data is missing.\n"); - return -EINVAL; - } - - wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL); - if (wl1273 == NULL) { - dev_err(codec->dev, "Cannot allocate memory.\n"); - return -ENOMEM; - } - - wl1273->mode = WL1273_MODE_BT; - wl1273->core = *core; - - snd_soc_codec_set_drvdata(codec, wl1273); - - r = snd_soc_add_codec_controls(codec, wl1273_controls, - ARRAY_SIZE(wl1273_controls)); - if (r) - kfree(wl1273); - - return r; -} - -static int wl1273_remove(struct snd_soc_codec *codec) -{ - struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec); - - dev_dbg(codec->dev, "%s\n", __func__); - kfree(wl1273); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wl1273 = { - .probe = wl1273_probe, - .remove = wl1273_remove, -}; - -static int __devinit wl1273_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273, - &wl1273_dai, 1); -} - -static int __devexit wl1273_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -MODULE_ALIAS("platform:wl1273-codec"); - -static struct platform_driver wl1273_platform_driver = { - .driver = { - .name = "wl1273-codec", - .owner = THIS_MODULE, - }, - .probe = wl1273_platform_probe, - .remove = __devexit_p(wl1273_platform_remove), -}; - -module_platform_driver(wl1273_platform_driver); - -MODULE_AUTHOR("Matti Aaltonen "); -MODULE_DESCRIPTION("ASoC WL1273 codec driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wl1273.h b/ANDROID_3.4.5/sound/soc/codecs/wl1273.h deleted file mode 100644 index 43ec7e66..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wl1273.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * sound/soc/codec/wl1273.h - * - * ALSA SoC WL1273 codec driver - * - * Copyright (C) Nokia Corporation - * Author: Matti Aaltonen - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1273_CODEC_H__ -#define __WL1273_CODEC_H__ - -int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt); - -#endif /* End of __WL1273_CODEC_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm1250-ev1.c b/ANDROID_3.4.5/sound/soc/codecs/wm1250-ev1.c deleted file mode 100644 index aefb4f89..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm1250-ev1.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Driver for the 1250-EV1 audio I/O module - * - * Copyright 2011 Wolfson Microelectronics plc - * - * 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. - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -static const char *wm1250_gpio_names[WM1250_EV1_NUM_GPIOS] = { - "WM1250 CLK_ENA", - "WM1250 CLK_SEL0", - "WM1250 CLK_SEL1", - "WM1250 OSR", - "WM1250 MASTER", -}; - -struct wm1250_priv { - struct gpio gpios[WM1250_EV1_NUM_GPIOS]; -}; - -static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm1250_priv *wm1250 = dev_get_drvdata(codec->dev); - int ena; - - if (wm1250) - ena = wm1250->gpios[WM1250_EV1_GPIO_CLK_ENA].gpio; - else - ena = -1; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - if (ena >= 0) - gpio_set_value_cansleep(ena, 1); - break; - - case SND_SOC_BIAS_OFF: - if (ena >= 0) - gpio_set_value_cansleep(ena, 0); - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = { -SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_DAC("DAC", "wm1250-ev1 Playback", SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_INPUT("WM1250 Input"), -SND_SOC_DAPM_OUTPUT("WM1250 Output"), -}; - -static const struct snd_soc_dapm_route wm1250_ev1_dapm_routes[] = { - { "ADC", NULL, "WM1250 Input" }, - { "WM1250 Output", NULL, "DAC" }, -}; - -static struct snd_soc_dai_driver wm1250_ev1_dai = { - .name = "wm1250-ev1", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { - .dapm_widgets = wm1250_ev1_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets), - .dapm_routes = wm1250_ev1_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes), - - .set_bias_level = wm1250_ev1_set_bias_level, - .idle_bias_off = true, -}; - -static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c) -{ - struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev); - struct wm1250_priv *wm1250; - int i, ret; - - if (!pdata) - return 0; - - wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL); - if (!wm1250) { - dev_err(&i2c->dev, "Unable to allocate private data\n"); - ret = -ENOMEM; - goto err; - } - - for (i = 0; i < ARRAY_SIZE(wm1250->gpios); i++) { - wm1250->gpios[i].gpio = pdata->gpios[i]; - wm1250->gpios[i].label = wm1250_gpio_names[i]; - wm1250->gpios[i].flags = GPIOF_OUT_INIT_LOW; - } - wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].flags = GPIOF_OUT_INIT_HIGH; - wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].flags = GPIOF_OUT_INIT_HIGH; - - ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios)); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret); - goto err; - } - - dev_set_drvdata(&i2c->dev, wm1250); - - return ret; - -err: - return ret; -} - -static void wm1250_ev1_free(struct i2c_client *i2c) -{ - struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev); - - if (wm1250) - gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios)); -} - -static int __devinit wm1250_ev1_probe(struct i2c_client *i2c, - const struct i2c_device_id *i2c_id) -{ - int id, board, rev, ret; - - dev_set_drvdata(&i2c->dev, NULL); - - board = i2c_smbus_read_byte_data(i2c, 0); - if (board < 0) { - dev_err(&i2c->dev, "Failed to read ID: %d\n", board); - return board; - } - - id = (board & 0xfe) >> 2; - rev = board & 0x3; - - if (id != 1) { - dev_err(&i2c->dev, "Unknown board ID %d\n", id); - return -ENODEV; - } - - dev_info(&i2c->dev, "revision %d\n", rev + 1); - - ret = wm1250_ev1_pdata(i2c); - if (ret != 0) - return ret; - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, - &wm1250_ev1_dai, 1); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - wm1250_ev1_free(i2c); - return ret; - } - - return 0; -} - -static int __devexit wm1250_ev1_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - wm1250_ev1_free(i2c); - - return 0; -} - -static const struct i2c_device_id wm1250_ev1_i2c_id[] = { - { "wm1250-ev1", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm1250_ev1_i2c_id); - -static struct i2c_driver wm1250_ev1_i2c_driver = { - .driver = { - .name = "wm1250-ev1", - .owner = THIS_MODULE, - }, - .probe = wm1250_ev1_probe, - .remove = __devexit_p(wm1250_ev1_remove), - .id_table = wm1250_ev1_i2c_id, -}; - -static int __init wm1250_ev1_modinit(void) -{ - int ret = 0; - - ret = i2c_add_driver(&wm1250_ev1_i2c_driver); - if (ret != 0) - pr_err("Failed to register WM1250-EV1 I2C driver: %d\n", ret); - - return ret; -} -module_init(wm1250_ev1_modinit); - -static void __exit wm1250_ev1_exit(void) -{ - i2c_del_driver(&wm1250_ev1_i2c_driver); -} -module_exit(wm1250_ev1_exit); - -MODULE_AUTHOR("Mark Brown "); -MODULE_DESCRIPTION("WM1250-EV1 audio I/O module driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm2000.c b/ANDROID_3.4.5/sound/soc/codecs/wm2000.c deleted file mode 100644 index a75c3766..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm2000.c +++ /dev/null @@ -1,862 +0,0 @@ -/* - * wm2000.c -- WM2000 ALSA Soc Audio driver - * - * Copyright 2008-2010 Wolfson Microelectronics PLC. - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * The download image for the WM2000 will be requested as - * 'wm2000_anc.bin' by default (overridable via platform data) at - * runtime and is expected to be in flat binary format. This is - * generated by Wolfson configuration tools and includes - * system-specific callibration information. If supplied as a - * sequence of ASCII-encoded hexidecimal bytes this can be converted - * into a flat binary with a command such as this on the command line: - * - * perl -e 'while (<>) { s/[\r\n]+// ; printf("%c", hex($_)); }' - * < file > wm2000_anc.bin - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "wm2000.h" - -enum wm2000_anc_mode { - ANC_ACTIVE = 0, - ANC_BYPASS = 1, - ANC_STANDBY = 2, - ANC_OFF = 3, -}; - -struct wm2000_priv { - struct i2c_client *i2c; - struct regmap *regmap; - - enum wm2000_anc_mode anc_mode; - - unsigned int anc_active:1; - unsigned int anc_eng_ena:1; - unsigned int spk_ena:1; - - unsigned int mclk_div:1; - unsigned int speech_clarity:1; - - int anc_download_size; - char *anc_download; -}; - -static int wm2000_write(struct i2c_client *i2c, unsigned int reg, - unsigned int value) -{ - struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c); - return regmap_write(wm2000->regmap, reg, value); -} - -static unsigned int wm2000_read(struct i2c_client *i2c, unsigned int r) -{ - struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c); - unsigned int val; - int ret; - - ret = regmap_read(wm2000->regmap, r, &val); - if (ret < 0) - return -1; - - return val; -} - -static void wm2000_reset(struct wm2000_priv *wm2000) -{ - struct i2c_client *i2c = wm2000->i2c; - - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR); - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR); - wm2000_write(i2c, WM2000_REG_ID1, 0); - - wm2000->anc_mode = ANC_OFF; -} - -static int wm2000_poll_bit(struct i2c_client *i2c, - unsigned int reg, u8 mask, int timeout) -{ - int val; - - val = wm2000_read(i2c, reg); - - while (!(val & mask) && --timeout) { - msleep(1); - val = wm2000_read(i2c, reg); - } - - if (timeout == 0) - return 0; - else - return 1; -} - -static int wm2000_power_up(struct i2c_client *i2c, int analogue) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int ret, timeout; - - BUG_ON(wm2000->anc_mode != ANC_OFF); - - dev_dbg(&i2c->dev, "Beginning power up\n"); - - if (!wm2000->mclk_div) { - dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); - wm2000_write(i2c, WM2000_REG_SYS_CTL2, - WM2000_MCLK_DIV2_ENA_CLR); - } else { - dev_dbg(&i2c->dev, "Enabling MCLK divider\n"); - wm2000_write(i2c, WM2000_REG_SYS_CTL2, - WM2000_MCLK_DIV2_ENA_SET); - } - - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR); - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_SET); - - /* Wait for ANC engine to become ready */ - if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE, 1)) { - dev_err(&i2c->dev, "ANC engine failed to reset\n"); - return -ETIMEDOUT; - } - - if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_BOOT_COMPLETE, 1)) { - dev_err(&i2c->dev, "ANC engine failed to initialise\n"); - return -ETIMEDOUT; - } - - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET); - - /* Open code download of the data since it is the only bulk - * write we do. */ - dev_dbg(&i2c->dev, "Downloading %d bytes\n", - wm2000->anc_download_size - 2); - - ret = i2c_master_send(i2c, wm2000->anc_download, - wm2000->anc_download_size); - if (ret < 0) { - dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); - return ret; - } - if (ret != wm2000->anc_download_size) { - dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", - ret, wm2000->anc_download_size); - return -EIO; - } - - dev_dbg(&i2c->dev, "Download complete\n"); - - if (analogue) { - timeout = 248; - wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4); - - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_ANA_SEQ_INCLUDE | - WM2000_MODE_MOUSE_ENABLE | - WM2000_MODE_THERMAL_ENABLE); - } else { - timeout = 10; - - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_MOUSE_ENABLE | - WM2000_MODE_THERMAL_ENABLE); - } - - ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); - if (wm2000->speech_clarity) - ret &= ~WM2000_SPEECH_CLARITY; - else - ret |= WM2000_SPEECH_CLARITY; - wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); - - wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); - wm2000_write(i2c, WM2000_REG_SYS_START1, 0x02); - - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); - - if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE, timeout)) { - dev_err(&i2c->dev, "Timed out waiting for device after %dms\n", - timeout * 10); - return -ETIMEDOUT; - } - - dev_dbg(&i2c->dev, "ANC active\n"); - if (analogue) - dev_dbg(&i2c->dev, "Analogue active\n"); - wm2000->anc_mode = ANC_ACTIVE; - - return 0; -} - -static int wm2000_power_down(struct i2c_client *i2c, int analogue) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int timeout; - - if (analogue) { - timeout = 248; - wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4); - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_ANA_SEQ_INCLUDE | - WM2000_MODE_POWER_DOWN); - } else { - timeout = 10; - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_POWER_DOWN); - } - - if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_POWER_DOWN_COMPLETE, timeout)) { - dev_err(&i2c->dev, "Timeout waiting for ANC power down\n"); - return -ETIMEDOUT; - } - - if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE, 1)) { - dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n"); - return -ETIMEDOUT; - } - - dev_dbg(&i2c->dev, "powered off\n"); - wm2000->anc_mode = ANC_OFF; - - return 0; -} - -static int wm2000_enter_bypass(struct i2c_client *i2c, int analogue) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - - BUG_ON(wm2000->anc_mode != ANC_ACTIVE); - - if (analogue) { - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_ANA_SEQ_INCLUDE | - WM2000_MODE_THERMAL_ENABLE | - WM2000_MODE_BYPASS_ENTRY); - } else { - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_THERMAL_ENABLE | - WM2000_MODE_BYPASS_ENTRY); - } - - if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_ANC_DISABLED, 10)) { - dev_err(&i2c->dev, "Timeout waiting for ANC disable\n"); - return -ETIMEDOUT; - } - - if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE, 1)) { - dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n"); - return -ETIMEDOUT; - } - - wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY); - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR); - - wm2000->anc_mode = ANC_BYPASS; - dev_dbg(&i2c->dev, "bypass enabled\n"); - - return 0; -} - -static int wm2000_exit_bypass(struct i2c_client *i2c, int analogue) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - - BUG_ON(wm2000->anc_mode != ANC_BYPASS); - - wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0); - - if (analogue) { - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_ANA_SEQ_INCLUDE | - WM2000_MODE_MOUSE_ENABLE | - WM2000_MODE_THERMAL_ENABLE); - } else { - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_MOUSE_ENABLE | - WM2000_MODE_THERMAL_ENABLE); - } - - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET); - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); - - if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE, 10)) { - dev_err(&i2c->dev, "Timed out waiting for MOUSE\n"); - return -ETIMEDOUT; - } - - wm2000->anc_mode = ANC_ACTIVE; - dev_dbg(&i2c->dev, "MOUSE active\n"); - - return 0; -} - -static int wm2000_enter_standby(struct i2c_client *i2c, int analogue) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int timeout; - - BUG_ON(wm2000->anc_mode != ANC_ACTIVE); - - if (analogue) { - timeout = 248; - wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4); - - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_ANA_SEQ_INCLUDE | - WM2000_MODE_THERMAL_ENABLE | - WM2000_MODE_STANDBY_ENTRY); - } else { - timeout = 10; - - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_THERMAL_ENABLE | - WM2000_MODE_STANDBY_ENTRY); - } - - if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_ANC_DISABLED, timeout)) { - dev_err(&i2c->dev, - "Timed out waiting for ANC disable after 1ms\n"); - return -ETIMEDOUT; - } - - if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, WM2000_ANC_ENG_IDLE, - 1)) { - dev_err(&i2c->dev, - "Timed out waiting for standby after %dms\n", - timeout * 10); - return -ETIMEDOUT; - } - - wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY); - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR); - - wm2000->anc_mode = ANC_STANDBY; - dev_dbg(&i2c->dev, "standby\n"); - if (analogue) - dev_dbg(&i2c->dev, "Analogue disabled\n"); - - return 0; -} - -static int wm2000_exit_standby(struct i2c_client *i2c, int analogue) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int timeout; - - BUG_ON(wm2000->anc_mode != ANC_STANDBY); - - wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0); - - if (analogue) { - timeout = 248; - wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4); - - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_ANA_SEQ_INCLUDE | - WM2000_MODE_THERMAL_ENABLE | - WM2000_MODE_MOUSE_ENABLE); - } else { - timeout = 10; - - wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, - WM2000_MODE_THERMAL_ENABLE | - WM2000_MODE_MOUSE_ENABLE); - } - - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET); - wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); - - if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE, timeout)) { - dev_err(&i2c->dev, "Timed out waiting for MOUSE after %dms\n", - timeout * 10); - return -ETIMEDOUT; - } - - wm2000->anc_mode = ANC_ACTIVE; - dev_dbg(&i2c->dev, "MOUSE active\n"); - if (analogue) - dev_dbg(&i2c->dev, "Analogue enabled\n"); - - return 0; -} - -typedef int (*wm2000_mode_fn)(struct i2c_client *i2c, int analogue); - -static struct { - enum wm2000_anc_mode source; - enum wm2000_anc_mode dest; - int analogue; - wm2000_mode_fn step[2]; -} anc_transitions[] = { - { - .source = ANC_OFF, - .dest = ANC_ACTIVE, - .analogue = 1, - .step = { - wm2000_power_up, - }, - }, - { - .source = ANC_OFF, - .dest = ANC_STANDBY, - .step = { - wm2000_power_up, - wm2000_enter_standby, - }, - }, - { - .source = ANC_OFF, - .dest = ANC_BYPASS, - .analogue = 1, - .step = { - wm2000_power_up, - wm2000_enter_bypass, - }, - }, - { - .source = ANC_ACTIVE, - .dest = ANC_BYPASS, - .analogue = 1, - .step = { - wm2000_enter_bypass, - }, - }, - { - .source = ANC_ACTIVE, - .dest = ANC_STANDBY, - .analogue = 1, - .step = { - wm2000_enter_standby, - }, - }, - { - .source = ANC_ACTIVE, - .dest = ANC_OFF, - .analogue = 1, - .step = { - wm2000_power_down, - }, - }, - { - .source = ANC_BYPASS, - .dest = ANC_ACTIVE, - .analogue = 1, - .step = { - wm2000_exit_bypass, - }, - }, - { - .source = ANC_BYPASS, - .dest = ANC_STANDBY, - .analogue = 1, - .step = { - wm2000_exit_bypass, - wm2000_enter_standby, - }, - }, - { - .source = ANC_BYPASS, - .dest = ANC_OFF, - .step = { - wm2000_exit_bypass, - wm2000_power_down, - }, - }, - { - .source = ANC_STANDBY, - .dest = ANC_ACTIVE, - .analogue = 1, - .step = { - wm2000_exit_standby, - }, - }, - { - .source = ANC_STANDBY, - .dest = ANC_BYPASS, - .analogue = 1, - .step = { - wm2000_exit_standby, - wm2000_enter_bypass, - }, - }, - { - .source = ANC_STANDBY, - .dest = ANC_OFF, - .step = { - wm2000_exit_standby, - wm2000_power_down, - }, - }, -}; - -static int wm2000_anc_transition(struct wm2000_priv *wm2000, - enum wm2000_anc_mode mode) -{ - struct i2c_client *i2c = wm2000->i2c; - int i, j; - int ret; - - if (wm2000->anc_mode == mode) - return 0; - - for (i = 0; i < ARRAY_SIZE(anc_transitions); i++) - if (anc_transitions[i].source == wm2000->anc_mode && - anc_transitions[i].dest == mode) - break; - if (i == ARRAY_SIZE(anc_transitions)) { - dev_err(&i2c->dev, "No transition for %d->%d\n", - wm2000->anc_mode, mode); - return -EINVAL; - } - - for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) { - if (!anc_transitions[i].step[j]) - break; - ret = anc_transitions[i].step[j](i2c, - anc_transitions[i].analogue); - if (ret != 0) - return ret; - } - - return 0; -} - -static int wm2000_anc_set_mode(struct wm2000_priv *wm2000) -{ - struct i2c_client *i2c = wm2000->i2c; - enum wm2000_anc_mode mode; - - if (wm2000->anc_eng_ena && wm2000->spk_ena) - if (wm2000->anc_active) - mode = ANC_ACTIVE; - else - mode = ANC_BYPASS; - else - mode = ANC_STANDBY; - - dev_dbg(&i2c->dev, "Set mode %d (enabled %d, mute %d, active %d)\n", - mode, wm2000->anc_eng_ena, !wm2000->spk_ena, - wm2000->anc_active); - - return wm2000_anc_transition(wm2000, mode); -} - -static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - - ucontrol->value.enumerated.item[0] = wm2000->anc_active; - - return 0; -} - -static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - int anc_active = ucontrol->value.enumerated.item[0]; - - if (anc_active > 1) - return -EINVAL; - - wm2000->anc_active = anc_active; - - return wm2000_anc_set_mode(wm2000); -} - -static int wm2000_speaker_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - - ucontrol->value.enumerated.item[0] = wm2000->spk_ena; - - return 0; -} - -static int wm2000_speaker_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - int val = ucontrol->value.enumerated.item[0]; - - if (val > 1) - return -EINVAL; - - wm2000->spk_ena = val; - - return wm2000_anc_set_mode(wm2000); -} - -static const struct snd_kcontrol_new wm2000_controls[] = { - SOC_SINGLE_BOOL_EXT("WM2000 ANC Switch", 0, - wm2000_anc_mode_get, - wm2000_anc_mode_put), - SOC_SINGLE_BOOL_EXT("WM2000 Switch", 0, - wm2000_speaker_get, - wm2000_speaker_put), -}; - -static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - - if (SND_SOC_DAPM_EVENT_ON(event)) - wm2000->anc_eng_ena = 1; - - if (SND_SOC_DAPM_EVENT_OFF(event)) - wm2000->anc_eng_ena = 0; - - return wm2000_anc_set_mode(wm2000); -} - -static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = { -/* Externally visible pins */ -SND_SOC_DAPM_OUTPUT("SPKN"), -SND_SOC_DAPM_OUTPUT("SPKP"), - -SND_SOC_DAPM_INPUT("LINN"), -SND_SOC_DAPM_INPUT("LINP"), - -SND_SOC_DAPM_PGA_E("ANC Engine", SND_SOC_NOPM, 0, 0, NULL, 0, - wm2000_anc_power_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -}; - -/* Target, Path, Source */ -static const struct snd_soc_dapm_route wm2000_audio_map[] = { - { "SPKN", NULL, "ANC Engine" }, - { "SPKP", NULL, "ANC Engine" }, - { "ANC Engine", NULL, "LINN" }, - { "ANC Engine", NULL, "LINP" }, -}; - -#ifdef CONFIG_PM -static int wm2000_suspend(struct snd_soc_codec *codec) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - - return wm2000_anc_transition(wm2000, ANC_OFF); -} - -static int wm2000_resume(struct snd_soc_codec *codec) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - - return wm2000_anc_set_mode(wm2000); -} -#else -#define wm2000_suspend NULL -#define wm2000_resume NULL -#endif - -static const struct regmap_config wm2000_regmap = { - .reg_bits = 8, - .val_bits = 8, -}; - -static int wm2000_probe(struct snd_soc_codec *codec) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - - /* This will trigger a transition to standby mode by default */ - wm2000_anc_set_mode(wm2000); - - return 0; -} - -static int wm2000_remove(struct snd_soc_codec *codec) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); - - return wm2000_anc_transition(wm2000, ANC_OFF); -} - -static struct snd_soc_codec_driver soc_codec_dev_wm2000 = { - .probe = wm2000_probe, - .remove = wm2000_remove, - .suspend = wm2000_suspend, - .resume = wm2000_resume, - - .dapm_widgets = wm2000_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets), - .dapm_routes = wm2000_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map), - .controls = wm2000_controls, - .num_controls = ARRAY_SIZE(wm2000_controls), -}; - -static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *i2c_id) -{ - struct wm2000_priv *wm2000; - struct wm2000_platform_data *pdata; - const char *filename; - const struct firmware *fw = NULL; - int ret; - int reg; - u16 id; - - wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv), - GFP_KERNEL); - if (wm2000 == NULL) { - dev_err(&i2c->dev, "Unable to allocate private data\n"); - return -ENOMEM; - } - - dev_set_drvdata(&i2c->dev, wm2000); - - wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap); - if (IS_ERR(wm2000->regmap)) { - ret = PTR_ERR(wm2000->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - goto out; - } - - /* Verify that this is a WM2000 */ - reg = wm2000_read(i2c, WM2000_REG_ID1); - id = reg << 8; - reg = wm2000_read(i2c, WM2000_REG_ID2); - id |= reg & 0xff; - - if (id != 0x2000) { - dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); - ret = -ENODEV; - goto out_regmap_exit; - } - - reg = wm2000_read(i2c, WM2000_REG_REVISON); - dev_info(&i2c->dev, "revision %c\n", reg + 'A'); - - filename = "wm2000_anc.bin"; - pdata = dev_get_platdata(&i2c->dev); - if (pdata) { - wm2000->mclk_div = pdata->mclkdiv2; - wm2000->speech_clarity = !pdata->speech_enh_disable; - - if (pdata->download_file) - filename = pdata->download_file; - } - - ret = request_firmware(&fw, filename, &i2c->dev); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); - goto out_regmap_exit; - } - - /* Pre-cook the concatenation of the register address onto the image */ - wm2000->anc_download_size = fw->size + 2; - wm2000->anc_download = devm_kzalloc(&i2c->dev, - wm2000->anc_download_size, - GFP_KERNEL); - if (wm2000->anc_download == NULL) { - dev_err(&i2c->dev, "Out of memory\n"); - ret = -ENOMEM; - goto out_regmap_exit; - } - - wm2000->anc_download[0] = 0x80; - wm2000->anc_download[1] = 0x00; - memcpy(wm2000->anc_download + 2, fw->data, fw->size); - - wm2000->anc_eng_ena = 1; - wm2000->anc_active = 1; - wm2000->spk_ena = 1; - wm2000->i2c = i2c; - - wm2000_reset(wm2000); - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); - if (!ret) - goto out; - -out_regmap_exit: - regmap_exit(wm2000->regmap); -out: - release_firmware(fw); - return ret; -} - -static __devexit int wm2000_i2c_remove(struct i2c_client *i2c) -{ - struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - - snd_soc_unregister_codec(&i2c->dev); - regmap_exit(wm2000->regmap); - - return 0; -} - -static const struct i2c_device_id wm2000_i2c_id[] = { - { "wm2000", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm2000_i2c_id); - -static struct i2c_driver wm2000_i2c_driver = { - .driver = { - .name = "wm2000", - .owner = THIS_MODULE, - }, - .probe = wm2000_i2c_probe, - .remove = __devexit_p(wm2000_i2c_remove), - .id_table = wm2000_i2c_id, -}; - -static int __init wm2000_init(void) -{ - return i2c_add_driver(&wm2000_i2c_driver); -} -module_init(wm2000_init); - -static void __exit wm2000_exit(void) -{ - i2c_del_driver(&wm2000_i2c_driver); -} -module_exit(wm2000_exit); - -MODULE_DESCRIPTION("ASoC WM2000 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm2000.h b/ANDROID_3.4.5/sound/soc/codecs/wm2000.h deleted file mode 100644 index abcd82a9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm2000.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * wm2000.h -- WM2000 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM2000_H -#define _WM2000_H - -#define WM2000_REG_SYS_START 0x8000 -#define WM2000_REG_SPEECH_CLARITY 0x8fef -#define WM2000_REG_SYS_WATCHDOG 0x8ff6 -#define WM2000_REG_ANA_VMID_PD_TIME 0x8ff7 -#define WM2000_REG_ANA_VMID_PU_TIME 0x8ff8 -#define WM2000_REG_CAT_FLTR_INDX 0x8ff9 -#define WM2000_REG_CAT_GAIN_0 0x8ffa -#define WM2000_REG_SYS_STATUS 0x8ffc -#define WM2000_REG_SYS_MODE_CNTRL 0x8ffd -#define WM2000_REG_SYS_START0 0x8ffe -#define WM2000_REG_SYS_START1 0x8fff -#define WM2000_REG_ID1 0xf000 -#define WM2000_REG_ID2 0xf001 -#define WM2000_REG_REVISON 0xf002 -#define WM2000_REG_SYS_CTL1 0xf003 -#define WM2000_REG_SYS_CTL2 0xf004 -#define WM2000_REG_ANC_STAT 0xf005 -#define WM2000_REG_IF_CTL 0xf006 - -/* SPEECH_CLARITY */ -#define WM2000_SPEECH_CLARITY 0x01 - -/* SYS_STATUS */ -#define WM2000_STATUS_MOUSE_ACTIVE 0x40 -#define WM2000_STATUS_CAT_FREQ_COMPLETE 0x20 -#define WM2000_STATUS_CAT_GAIN_COMPLETE 0x10 -#define WM2000_STATUS_THERMAL_SHUTDOWN_COMPLETE 0x08 -#define WM2000_STATUS_ANC_DISABLED 0x04 -#define WM2000_STATUS_POWER_DOWN_COMPLETE 0x02 -#define WM2000_STATUS_BOOT_COMPLETE 0x01 - -/* SYS_MODE_CNTRL */ -#define WM2000_MODE_ANA_SEQ_INCLUDE 0x80 -#define WM2000_MODE_MOUSE_ENABLE 0x40 -#define WM2000_MODE_CAT_FREQ_ENABLE 0x20 -#define WM2000_MODE_CAT_GAIN_ENABLE 0x10 -#define WM2000_MODE_BYPASS_ENTRY 0x08 -#define WM2000_MODE_STANDBY_ENTRY 0x04 -#define WM2000_MODE_THERMAL_ENABLE 0x02 -#define WM2000_MODE_POWER_DOWN 0x01 - -/* SYS_CTL1 */ -#define WM2000_SYS_STBY 0x01 - -/* SYS_CTL2 */ -#define WM2000_MCLK_DIV2_ENA_CLR 0x80 -#define WM2000_MCLK_DIV2_ENA_SET 0x40 -#define WM2000_ANC_ENG_CLR 0x20 -#define WM2000_ANC_ENG_SET 0x10 -#define WM2000_ANC_INT_N_CLR 0x08 -#define WM2000_ANC_INT_N_SET 0x04 -#define WM2000_RAM_CLR 0x02 -#define WM2000_RAM_SET 0x01 - -/* ANC_STAT */ -#define WM2000_ANC_ENG_IDLE 0x01 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm2200.c b/ANDROID_3.4.5/sound/soc/codecs/wm2200.c deleted file mode 100644 index 32682c1b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm2200.c +++ /dev/null @@ -1,2287 +0,0 @@ -/* - * wm2200.c -- WM2200 ALSA SoC Audio driver - * - * Copyright 2012 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm2200.h" - -/* The code assumes DCVDD is generated internally */ -#define WM2200_NUM_CORE_SUPPLIES 2 -static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = { - "DBVDD", - "LDOVDD", -}; - -struct wm2200_fll { - int fref; - int fout; - int src; - struct completion lock; -}; - -/* codec private data */ -struct wm2200_priv { - struct regmap *regmap; - struct device *dev; - struct snd_soc_codec *codec; - struct wm2200_pdata pdata; - struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES]; - - struct completion fll_lock; - int fll_fout; - int fll_fref; - int fll_src; - - int rev; - int sysclk; -}; - -static struct reg_default wm2200_reg_defaults[] = { - { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */ - { 0x0102, 0x0000 }, /* R258 - Clocking 3 */ - { 0x0103, 0x0011 }, /* R259 - Clocking 4 */ - { 0x0111, 0x0000 }, /* R273 - FLL Control 1 */ - { 0x0112, 0x0000 }, /* R274 - FLL Control 2 */ - { 0x0113, 0x0000 }, /* R275 - FLL Control 3 */ - { 0x0114, 0x0000 }, /* R276 - FLL Control 4 */ - { 0x0116, 0x0177 }, /* R278 - FLL Control 6 */ - { 0x0117, 0x0004 }, /* R279 - FLL Control 7 */ - { 0x0119, 0x0000 }, /* R281 - FLL EFS 1 */ - { 0x011A, 0x0002 }, /* R282 - FLL EFS 2 */ - { 0x0200, 0x0000 }, /* R512 - Mic Charge Pump 1 */ - { 0x0201, 0x03FF }, /* R513 - Mic Charge Pump 2 */ - { 0x0202, 0x9BDE }, /* R514 - DM Charge Pump 1 */ - { 0x020C, 0x0000 }, /* R524 - Mic Bias Ctrl 1 */ - { 0x020D, 0x0000 }, /* R525 - Mic Bias Ctrl 2 */ - { 0x020F, 0x0000 }, /* R527 - Ear Piece Ctrl 1 */ - { 0x0210, 0x0000 }, /* R528 - Ear Piece Ctrl 2 */ - { 0x0301, 0x0000 }, /* R769 - Input Enables */ - { 0x0302, 0x2240 }, /* R770 - IN1L Control */ - { 0x0303, 0x0040 }, /* R771 - IN1R Control */ - { 0x0304, 0x2240 }, /* R772 - IN2L Control */ - { 0x0305, 0x0040 }, /* R773 - IN2R Control */ - { 0x0306, 0x2240 }, /* R774 - IN3L Control */ - { 0x0307, 0x0040 }, /* R775 - IN3R Control */ - { 0x030A, 0x0000 }, /* R778 - RXANC_SRC */ - { 0x030B, 0x0022 }, /* R779 - Input Volume Ramp */ - { 0x030C, 0x0180 }, /* R780 - ADC Digital Volume 1L */ - { 0x030D, 0x0180 }, /* R781 - ADC Digital Volume 1R */ - { 0x030E, 0x0180 }, /* R782 - ADC Digital Volume 2L */ - { 0x030F, 0x0180 }, /* R783 - ADC Digital Volume 2R */ - { 0x0310, 0x0180 }, /* R784 - ADC Digital Volume 3L */ - { 0x0311, 0x0180 }, /* R785 - ADC Digital Volume 3R */ - { 0x0400, 0x0000 }, /* R1024 - Output Enables */ - { 0x0401, 0x0000 }, /* R1025 - DAC Volume Limit 1L */ - { 0x0402, 0x0000 }, /* R1026 - DAC Volume Limit 1R */ - { 0x0403, 0x0000 }, /* R1027 - DAC Volume Limit 2L */ - { 0x0404, 0x0000 }, /* R1028 - DAC Volume Limit 2R */ - { 0x0409, 0x0000 }, /* R1033 - DAC AEC Control 1 */ - { 0x040A, 0x0022 }, /* R1034 - Output Volume Ramp */ - { 0x040B, 0x0180 }, /* R1035 - DAC Digital Volume 1L */ - { 0x040C, 0x0180 }, /* R1036 - DAC Digital Volume 1R */ - { 0x040D, 0x0180 }, /* R1037 - DAC Digital Volume 2L */ - { 0x040E, 0x0180 }, /* R1038 - DAC Digital Volume 2R */ - { 0x0417, 0x0069 }, /* R1047 - PDM 1 */ - { 0x0418, 0x0000 }, /* R1048 - PDM 2 */ - { 0x0500, 0x0000 }, /* R1280 - Audio IF 1_1 */ - { 0x0501, 0x0008 }, /* R1281 - Audio IF 1_2 */ - { 0x0502, 0x0000 }, /* R1282 - Audio IF 1_3 */ - { 0x0503, 0x0000 }, /* R1283 - Audio IF 1_4 */ - { 0x0504, 0x0000 }, /* R1284 - Audio IF 1_5 */ - { 0x0505, 0x0001 }, /* R1285 - Audio IF 1_6 */ - { 0x0506, 0x0001 }, /* R1286 - Audio IF 1_7 */ - { 0x0507, 0x0000 }, /* R1287 - Audio IF 1_8 */ - { 0x0508, 0x0000 }, /* R1288 - Audio IF 1_9 */ - { 0x0509, 0x0000 }, /* R1289 - Audio IF 1_10 */ - { 0x050A, 0x0000 }, /* R1290 - Audio IF 1_11 */ - { 0x050B, 0x0000 }, /* R1291 - Audio IF 1_12 */ - { 0x050C, 0x0000 }, /* R1292 - Audio IF 1_13 */ - { 0x050D, 0x0000 }, /* R1293 - Audio IF 1_14 */ - { 0x050E, 0x0000 }, /* R1294 - Audio IF 1_15 */ - { 0x050F, 0x0000 }, /* R1295 - Audio IF 1_16 */ - { 0x0510, 0x0000 }, /* R1296 - Audio IF 1_17 */ - { 0x0511, 0x0000 }, /* R1297 - Audio IF 1_18 */ - { 0x0512, 0x0000 }, /* R1298 - Audio IF 1_19 */ - { 0x0513, 0x0000 }, /* R1299 - Audio IF 1_20 */ - { 0x0514, 0x0000 }, /* R1300 - Audio IF 1_21 */ - { 0x0515, 0x0001 }, /* R1301 - Audio IF 1_22 */ - { 0x0600, 0x0000 }, /* R1536 - OUT1LMIX Input 1 Source */ - { 0x0601, 0x0080 }, /* R1537 - OUT1LMIX Input 1 Volume */ - { 0x0602, 0x0000 }, /* R1538 - OUT1LMIX Input 2 Source */ - { 0x0603, 0x0080 }, /* R1539 - OUT1LMIX Input 2 Volume */ - { 0x0604, 0x0000 }, /* R1540 - OUT1LMIX Input 3 Source */ - { 0x0605, 0x0080 }, /* R1541 - OUT1LMIX Input 3 Volume */ - { 0x0606, 0x0000 }, /* R1542 - OUT1LMIX Input 4 Source */ - { 0x0607, 0x0080 }, /* R1543 - OUT1LMIX Input 4 Volume */ - { 0x0608, 0x0000 }, /* R1544 - OUT1RMIX Input 1 Source */ - { 0x0609, 0x0080 }, /* R1545 - OUT1RMIX Input 1 Volume */ - { 0x060A, 0x0000 }, /* R1546 - OUT1RMIX Input 2 Source */ - { 0x060B, 0x0080 }, /* R1547 - OUT1RMIX Input 2 Volume */ - { 0x060C, 0x0000 }, /* R1548 - OUT1RMIX Input 3 Source */ - { 0x060D, 0x0080 }, /* R1549 - OUT1RMIX Input 3 Volume */ - { 0x060E, 0x0000 }, /* R1550 - OUT1RMIX Input 4 Source */ - { 0x060F, 0x0080 }, /* R1551 - OUT1RMIX Input 4 Volume */ - { 0x0610, 0x0000 }, /* R1552 - OUT2LMIX Input 1 Source */ - { 0x0611, 0x0080 }, /* R1553 - OUT2LMIX Input 1 Volume */ - { 0x0612, 0x0000 }, /* R1554 - OUT2LMIX Input 2 Source */ - { 0x0613, 0x0080 }, /* R1555 - OUT2LMIX Input 2 Volume */ - { 0x0614, 0x0000 }, /* R1556 - OUT2LMIX Input 3 Source */ - { 0x0615, 0x0080 }, /* R1557 - OUT2LMIX Input 3 Volume */ - { 0x0616, 0x0000 }, /* R1558 - OUT2LMIX Input 4 Source */ - { 0x0617, 0x0080 }, /* R1559 - OUT2LMIX Input 4 Volume */ - { 0x0618, 0x0000 }, /* R1560 - OUT2RMIX Input 1 Source */ - { 0x0619, 0x0080 }, /* R1561 - OUT2RMIX Input 1 Volume */ - { 0x061A, 0x0000 }, /* R1562 - OUT2RMIX Input 2 Source */ - { 0x061B, 0x0080 }, /* R1563 - OUT2RMIX Input 2 Volume */ - { 0x061C, 0x0000 }, /* R1564 - OUT2RMIX Input 3 Source */ - { 0x061D, 0x0080 }, /* R1565 - OUT2RMIX Input 3 Volume */ - { 0x061E, 0x0000 }, /* R1566 - OUT2RMIX Input 4 Source */ - { 0x061F, 0x0080 }, /* R1567 - OUT2RMIX Input 4 Volume */ - { 0x0620, 0x0000 }, /* R1568 - AIF1TX1MIX Input 1 Source */ - { 0x0621, 0x0080 }, /* R1569 - AIF1TX1MIX Input 1 Volume */ - { 0x0622, 0x0000 }, /* R1570 - AIF1TX1MIX Input 2 Source */ - { 0x0623, 0x0080 }, /* R1571 - AIF1TX1MIX Input 2 Volume */ - { 0x0624, 0x0000 }, /* R1572 - AIF1TX1MIX Input 3 Source */ - { 0x0625, 0x0080 }, /* R1573 - AIF1TX1MIX Input 3 Volume */ - { 0x0626, 0x0000 }, /* R1574 - AIF1TX1MIX Input 4 Source */ - { 0x0627, 0x0080 }, /* R1575 - AIF1TX1MIX Input 4 Volume */ - { 0x0628, 0x0000 }, /* R1576 - AIF1TX2MIX Input 1 Source */ - { 0x0629, 0x0080 }, /* R1577 - AIF1TX2MIX Input 1 Volume */ - { 0x062A, 0x0000 }, /* R1578 - AIF1TX2MIX Input 2 Source */ - { 0x062B, 0x0080 }, /* R1579 - AIF1TX2MIX Input 2 Volume */ - { 0x062C, 0x0000 }, /* R1580 - AIF1TX2MIX Input 3 Source */ - { 0x062D, 0x0080 }, /* R1581 - AIF1TX2MIX Input 3 Volume */ - { 0x062E, 0x0000 }, /* R1582 - AIF1TX2MIX Input 4 Source */ - { 0x062F, 0x0080 }, /* R1583 - AIF1TX2MIX Input 4 Volume */ - { 0x0630, 0x0000 }, /* R1584 - AIF1TX3MIX Input 1 Source */ - { 0x0631, 0x0080 }, /* R1585 - AIF1TX3MIX Input 1 Volume */ - { 0x0632, 0x0000 }, /* R1586 - AIF1TX3MIX Input 2 Source */ - { 0x0633, 0x0080 }, /* R1587 - AIF1TX3MIX Input 2 Volume */ - { 0x0634, 0x0000 }, /* R1588 - AIF1TX3MIX Input 3 Source */ - { 0x0635, 0x0080 }, /* R1589 - AIF1TX3MIX Input 3 Volume */ - { 0x0636, 0x0000 }, /* R1590 - AIF1TX3MIX Input 4 Source */ - { 0x0637, 0x0080 }, /* R1591 - AIF1TX3MIX Input 4 Volume */ - { 0x0638, 0x0000 }, /* R1592 - AIF1TX4MIX Input 1 Source */ - { 0x0639, 0x0080 }, /* R1593 - AIF1TX4MIX Input 1 Volume */ - { 0x063A, 0x0000 }, /* R1594 - AIF1TX4MIX Input 2 Source */ - { 0x063B, 0x0080 }, /* R1595 - AIF1TX4MIX Input 2 Volume */ - { 0x063C, 0x0000 }, /* R1596 - AIF1TX4MIX Input 3 Source */ - { 0x063D, 0x0080 }, /* R1597 - AIF1TX4MIX Input 3 Volume */ - { 0x063E, 0x0000 }, /* R1598 - AIF1TX4MIX Input 4 Source */ - { 0x063F, 0x0080 }, /* R1599 - AIF1TX4MIX Input 4 Volume */ - { 0x0640, 0x0000 }, /* R1600 - AIF1TX5MIX Input 1 Source */ - { 0x0641, 0x0080 }, /* R1601 - AIF1TX5MIX Input 1 Volume */ - { 0x0642, 0x0000 }, /* R1602 - AIF1TX5MIX Input 2 Source */ - { 0x0643, 0x0080 }, /* R1603 - AIF1TX5MIX Input 2 Volume */ - { 0x0644, 0x0000 }, /* R1604 - AIF1TX5MIX Input 3 Source */ - { 0x0645, 0x0080 }, /* R1605 - AIF1TX5MIX Input 3 Volume */ - { 0x0646, 0x0000 }, /* R1606 - AIF1TX5MIX Input 4 Source */ - { 0x0647, 0x0080 }, /* R1607 - AIF1TX5MIX Input 4 Volume */ - { 0x0648, 0x0000 }, /* R1608 - AIF1TX6MIX Input 1 Source */ - { 0x0649, 0x0080 }, /* R1609 - AIF1TX6MIX Input 1 Volume */ - { 0x064A, 0x0000 }, /* R1610 - AIF1TX6MIX Input 2 Source */ - { 0x064B, 0x0080 }, /* R1611 - AIF1TX6MIX Input 2 Volume */ - { 0x064C, 0x0000 }, /* R1612 - AIF1TX6MIX Input 3 Source */ - { 0x064D, 0x0080 }, /* R1613 - AIF1TX6MIX Input 3 Volume */ - { 0x064E, 0x0000 }, /* R1614 - AIF1TX6MIX Input 4 Source */ - { 0x064F, 0x0080 }, /* R1615 - AIF1TX6MIX Input 4 Volume */ - { 0x0650, 0x0000 }, /* R1616 - EQLMIX Input 1 Source */ - { 0x0651, 0x0080 }, /* R1617 - EQLMIX Input 1 Volume */ - { 0x0652, 0x0000 }, /* R1618 - EQLMIX Input 2 Source */ - { 0x0653, 0x0080 }, /* R1619 - EQLMIX Input 2 Volume */ - { 0x0654, 0x0000 }, /* R1620 - EQLMIX Input 3 Source */ - { 0x0655, 0x0080 }, /* R1621 - EQLMIX Input 3 Volume */ - { 0x0656, 0x0000 }, /* R1622 - EQLMIX Input 4 Source */ - { 0x0657, 0x0080 }, /* R1623 - EQLMIX Input 4 Volume */ - { 0x0658, 0x0000 }, /* R1624 - EQRMIX Input 1 Source */ - { 0x0659, 0x0080 }, /* R1625 - EQRMIX Input 1 Volume */ - { 0x065A, 0x0000 }, /* R1626 - EQRMIX Input 2 Source */ - { 0x065B, 0x0080 }, /* R1627 - EQRMIX Input 2 Volume */ - { 0x065C, 0x0000 }, /* R1628 - EQRMIX Input 3 Source */ - { 0x065D, 0x0080 }, /* R1629 - EQRMIX Input 3 Volume */ - { 0x065E, 0x0000 }, /* R1630 - EQRMIX Input 4 Source */ - { 0x065F, 0x0080 }, /* R1631 - EQRMIX Input 4 Volume */ - { 0x0660, 0x0000 }, /* R1632 - LHPF1MIX Input 1 Source */ - { 0x0661, 0x0080 }, /* R1633 - LHPF1MIX Input 1 Volume */ - { 0x0662, 0x0000 }, /* R1634 - LHPF1MIX Input 2 Source */ - { 0x0663, 0x0080 }, /* R1635 - LHPF1MIX Input 2 Volume */ - { 0x0664, 0x0000 }, /* R1636 - LHPF1MIX Input 3 Source */ - { 0x0665, 0x0080 }, /* R1637 - LHPF1MIX Input 3 Volume */ - { 0x0666, 0x0000 }, /* R1638 - LHPF1MIX Input 4 Source */ - { 0x0667, 0x0080 }, /* R1639 - LHPF1MIX Input 4 Volume */ - { 0x0668, 0x0000 }, /* R1640 - LHPF2MIX Input 1 Source */ - { 0x0669, 0x0080 }, /* R1641 - LHPF2MIX Input 1 Volume */ - { 0x066A, 0x0000 }, /* R1642 - LHPF2MIX Input 2 Source */ - { 0x066B, 0x0080 }, /* R1643 - LHPF2MIX Input 2 Volume */ - { 0x066C, 0x0000 }, /* R1644 - LHPF2MIX Input 3 Source */ - { 0x066D, 0x0080 }, /* R1645 - LHPF2MIX Input 3 Volume */ - { 0x066E, 0x0000 }, /* R1646 - LHPF2MIX Input 4 Source */ - { 0x066F, 0x0080 }, /* R1647 - LHPF2MIX Input 4 Volume */ - { 0x0670, 0x0000 }, /* R1648 - DSP1LMIX Input 1 Source */ - { 0x0671, 0x0080 }, /* R1649 - DSP1LMIX Input 1 Volume */ - { 0x0672, 0x0000 }, /* R1650 - DSP1LMIX Input 2 Source */ - { 0x0673, 0x0080 }, /* R1651 - DSP1LMIX Input 2 Volume */ - { 0x0674, 0x0000 }, /* R1652 - DSP1LMIX Input 3 Source */ - { 0x0675, 0x0080 }, /* R1653 - DSP1LMIX Input 3 Volume */ - { 0x0676, 0x0000 }, /* R1654 - DSP1LMIX Input 4 Source */ - { 0x0677, 0x0080 }, /* R1655 - DSP1LMIX Input 4 Volume */ - { 0x0678, 0x0000 }, /* R1656 - DSP1RMIX Input 1 Source */ - { 0x0679, 0x0080 }, /* R1657 - DSP1RMIX Input 1 Volume */ - { 0x067A, 0x0000 }, /* R1658 - DSP1RMIX Input 2 Source */ - { 0x067B, 0x0080 }, /* R1659 - DSP1RMIX Input 2 Volume */ - { 0x067C, 0x0000 }, /* R1660 - DSP1RMIX Input 3 Source */ - { 0x067D, 0x0080 }, /* R1661 - DSP1RMIX Input 3 Volume */ - { 0x067E, 0x0000 }, /* R1662 - DSP1RMIX Input 4 Source */ - { 0x067F, 0x0080 }, /* R1663 - DSP1RMIX Input 4 Volume */ - { 0x0680, 0x0000 }, /* R1664 - DSP1AUX1MIX Input 1 Source */ - { 0x0681, 0x0000 }, /* R1665 - DSP1AUX2MIX Input 1 Source */ - { 0x0682, 0x0000 }, /* R1666 - DSP1AUX3MIX Input 1 Source */ - { 0x0683, 0x0000 }, /* R1667 - DSP1AUX4MIX Input 1 Source */ - { 0x0684, 0x0000 }, /* R1668 - DSP1AUX5MIX Input 1 Source */ - { 0x0685, 0x0000 }, /* R1669 - DSP1AUX6MIX Input 1 Source */ - { 0x0686, 0x0000 }, /* R1670 - DSP2LMIX Input 1 Source */ - { 0x0687, 0x0080 }, /* R1671 - DSP2LMIX Input 1 Volume */ - { 0x0688, 0x0000 }, /* R1672 - DSP2LMIX Input 2 Source */ - { 0x0689, 0x0080 }, /* R1673 - DSP2LMIX Input 2 Volume */ - { 0x068A, 0x0000 }, /* R1674 - DSP2LMIX Input 3 Source */ - { 0x068B, 0x0080 }, /* R1675 - DSP2LMIX Input 3 Volume */ - { 0x068C, 0x0000 }, /* R1676 - DSP2LMIX Input 4 Source */ - { 0x068D, 0x0080 }, /* R1677 - DSP2LMIX Input 4 Volume */ - { 0x068E, 0x0000 }, /* R1678 - DSP2RMIX Input 1 Source */ - { 0x068F, 0x0080 }, /* R1679 - DSP2RMIX Input 1 Volume */ - { 0x0690, 0x0000 }, /* R1680 - DSP2RMIX Input 2 Source */ - { 0x0691, 0x0080 }, /* R1681 - DSP2RMIX Input 2 Volume */ - { 0x0692, 0x0000 }, /* R1682 - DSP2RMIX Input 3 Source */ - { 0x0693, 0x0080 }, /* R1683 - DSP2RMIX Input 3 Volume */ - { 0x0694, 0x0000 }, /* R1684 - DSP2RMIX Input 4 Source */ - { 0x0695, 0x0080 }, /* R1685 - DSP2RMIX Input 4 Volume */ - { 0x0696, 0x0000 }, /* R1686 - DSP2AUX1MIX Input 1 Source */ - { 0x0697, 0x0000 }, /* R1687 - DSP2AUX2MIX Input 1 Source */ - { 0x0698, 0x0000 }, /* R1688 - DSP2AUX3MIX Input 1 Source */ - { 0x0699, 0x0000 }, /* R1689 - DSP2AUX4MIX Input 1 Source */ - { 0x069A, 0x0000 }, /* R1690 - DSP2AUX5MIX Input 1 Source */ - { 0x069B, 0x0000 }, /* R1691 - DSP2AUX6MIX Input 1 Source */ - { 0x0700, 0xA101 }, /* R1792 - GPIO CTRL 1 */ - { 0x0701, 0xA101 }, /* R1793 - GPIO CTRL 2 */ - { 0x0702, 0xA101 }, /* R1794 - GPIO CTRL 3 */ - { 0x0703, 0xA101 }, /* R1795 - GPIO CTRL 4 */ - { 0x0709, 0x0000 }, /* R1801 - Misc Pad Ctrl 1 */ - { 0x0801, 0x00FF }, /* R2049 - Interrupt Status 1 Mask */ - { 0x0804, 0xFFFF }, /* R2052 - Interrupt Status 2 Mask */ - { 0x0808, 0x0000 }, /* R2056 - Interrupt Control */ - { 0x0900, 0x0000 }, /* R2304 - EQL_1 */ - { 0x0901, 0x0000 }, /* R2305 - EQL_2 */ - { 0x0902, 0x0000 }, /* R2306 - EQL_3 */ - { 0x0903, 0x0000 }, /* R2307 - EQL_4 */ - { 0x0904, 0x0000 }, /* R2308 - EQL_5 */ - { 0x0905, 0x0000 }, /* R2309 - EQL_6 */ - { 0x0906, 0x0000 }, /* R2310 - EQL_7 */ - { 0x0907, 0x0000 }, /* R2311 - EQL_8 */ - { 0x0908, 0x0000 }, /* R2312 - EQL_9 */ - { 0x0909, 0x0000 }, /* R2313 - EQL_10 */ - { 0x090A, 0x0000 }, /* R2314 - EQL_11 */ - { 0x090B, 0x0000 }, /* R2315 - EQL_12 */ - { 0x090C, 0x0000 }, /* R2316 - EQL_13 */ - { 0x090D, 0x0000 }, /* R2317 - EQL_14 */ - { 0x090E, 0x0000 }, /* R2318 - EQL_15 */ - { 0x090F, 0x0000 }, /* R2319 - EQL_16 */ - { 0x0910, 0x0000 }, /* R2320 - EQL_17 */ - { 0x0911, 0x0000 }, /* R2321 - EQL_18 */ - { 0x0912, 0x0000 }, /* R2322 - EQL_19 */ - { 0x0913, 0x0000 }, /* R2323 - EQL_20 */ - { 0x0916, 0x0000 }, /* R2326 - EQR_1 */ - { 0x0917, 0x0000 }, /* R2327 - EQR_2 */ - { 0x0918, 0x0000 }, /* R2328 - EQR_3 */ - { 0x0919, 0x0000 }, /* R2329 - EQR_4 */ - { 0x091A, 0x0000 }, /* R2330 - EQR_5 */ - { 0x091B, 0x0000 }, /* R2331 - EQR_6 */ - { 0x091C, 0x0000 }, /* R2332 - EQR_7 */ - { 0x091D, 0x0000 }, /* R2333 - EQR_8 */ - { 0x091E, 0x0000 }, /* R2334 - EQR_9 */ - { 0x091F, 0x0000 }, /* R2335 - EQR_10 */ - { 0x0920, 0x0000 }, /* R2336 - EQR_11 */ - { 0x0921, 0x0000 }, /* R2337 - EQR_12 */ - { 0x0922, 0x0000 }, /* R2338 - EQR_13 */ - { 0x0923, 0x0000 }, /* R2339 - EQR_14 */ - { 0x0924, 0x0000 }, /* R2340 - EQR_15 */ - { 0x0925, 0x0000 }, /* R2341 - EQR_16 */ - { 0x0926, 0x0000 }, /* R2342 - EQR_17 */ - { 0x0927, 0x0000 }, /* R2343 - EQR_18 */ - { 0x0928, 0x0000 }, /* R2344 - EQR_19 */ - { 0x0929, 0x0000 }, /* R2345 - EQR_20 */ - { 0x093E, 0x0000 }, /* R2366 - HPLPF1_1 */ - { 0x093F, 0x0000 }, /* R2367 - HPLPF1_2 */ - { 0x0942, 0x0000 }, /* R2370 - HPLPF2_1 */ - { 0x0943, 0x0000 }, /* R2371 - HPLPF2_2 */ - { 0x0A00, 0x0000 }, /* R2560 - DSP1 Control 1 */ - { 0x0A02, 0x0000 }, /* R2562 - DSP1 Control 2 */ - { 0x0A03, 0x0000 }, /* R2563 - DSP1 Control 3 */ - { 0x0A04, 0x0000 }, /* R2564 - DSP1 Control 4 */ - { 0x0A06, 0x0000 }, /* R2566 - DSP1 Control 5 */ - { 0x0A07, 0x0000 }, /* R2567 - DSP1 Control 6 */ - { 0x0A08, 0x0000 }, /* R2568 - DSP1 Control 7 */ - { 0x0A09, 0x0000 }, /* R2569 - DSP1 Control 8 */ - { 0x0A0A, 0x0000 }, /* R2570 - DSP1 Control 9 */ - { 0x0A0B, 0x0000 }, /* R2571 - DSP1 Control 10 */ - { 0x0A0C, 0x0000 }, /* R2572 - DSP1 Control 11 */ - { 0x0A0D, 0x0000 }, /* R2573 - DSP1 Control 12 */ - { 0x0A0F, 0x0000 }, /* R2575 - DSP1 Control 13 */ - { 0x0A10, 0x0000 }, /* R2576 - DSP1 Control 14 */ - { 0x0A11, 0x0000 }, /* R2577 - DSP1 Control 15 */ - { 0x0A12, 0x0000 }, /* R2578 - DSP1 Control 16 */ - { 0x0A13, 0x0000 }, /* R2579 - DSP1 Control 17 */ - { 0x0A14, 0x0000 }, /* R2580 - DSP1 Control 18 */ - { 0x0A16, 0x0000 }, /* R2582 - DSP1 Control 19 */ - { 0x0A17, 0x0000 }, /* R2583 - DSP1 Control 20 */ - { 0x0A18, 0x0000 }, /* R2584 - DSP1 Control 21 */ - { 0x0A1A, 0x1800 }, /* R2586 - DSP1 Control 22 */ - { 0x0A1B, 0x1000 }, /* R2587 - DSP1 Control 23 */ - { 0x0A1C, 0x0400 }, /* R2588 - DSP1 Control 24 */ - { 0x0A1E, 0x0000 }, /* R2590 - DSP1 Control 25 */ - { 0x0A20, 0x0000 }, /* R2592 - DSP1 Control 26 */ - { 0x0A21, 0x0000 }, /* R2593 - DSP1 Control 27 */ - { 0x0A22, 0x0000 }, /* R2594 - DSP1 Control 28 */ - { 0x0A23, 0x0000 }, /* R2595 - DSP1 Control 29 */ - { 0x0A24, 0x0000 }, /* R2596 - DSP1 Control 30 */ - { 0x0A26, 0x0000 }, /* R2598 - DSP1 Control 31 */ - { 0x0B00, 0x0000 }, /* R2816 - DSP2 Control 1 */ - { 0x0B02, 0x0000 }, /* R2818 - DSP2 Control 2 */ - { 0x0B03, 0x0000 }, /* R2819 - DSP2 Control 3 */ - { 0x0B04, 0x0000 }, /* R2820 - DSP2 Control 4 */ - { 0x0B06, 0x0000 }, /* R2822 - DSP2 Control 5 */ - { 0x0B07, 0x0000 }, /* R2823 - DSP2 Control 6 */ - { 0x0B08, 0x0000 }, /* R2824 - DSP2 Control 7 */ - { 0x0B09, 0x0000 }, /* R2825 - DSP2 Control 8 */ - { 0x0B0A, 0x0000 }, /* R2826 - DSP2 Control 9 */ - { 0x0B0B, 0x0000 }, /* R2827 - DSP2 Control 10 */ - { 0x0B0C, 0x0000 }, /* R2828 - DSP2 Control 11 */ - { 0x0B0D, 0x0000 }, /* R2829 - DSP2 Control 12 */ - { 0x0B0F, 0x0000 }, /* R2831 - DSP2 Control 13 */ - { 0x0B10, 0x0000 }, /* R2832 - DSP2 Control 14 */ - { 0x0B11, 0x0000 }, /* R2833 - DSP2 Control 15 */ - { 0x0B12, 0x0000 }, /* R2834 - DSP2 Control 16 */ - { 0x0B13, 0x0000 }, /* R2835 - DSP2 Control 17 */ - { 0x0B14, 0x0000 }, /* R2836 - DSP2 Control 18 */ - { 0x0B16, 0x0000 }, /* R2838 - DSP2 Control 19 */ - { 0x0B17, 0x0000 }, /* R2839 - DSP2 Control 20 */ - { 0x0B18, 0x0000 }, /* R2840 - DSP2 Control 21 */ - { 0x0B1A, 0x0800 }, /* R2842 - DSP2 Control 22 */ - { 0x0B1B, 0x1000 }, /* R2843 - DSP2 Control 23 */ - { 0x0B1C, 0x0400 }, /* R2844 - DSP2 Control 24 */ - { 0x0B1E, 0x0000 }, /* R2846 - DSP2 Control 25 */ - { 0x0B20, 0x0000 }, /* R2848 - DSP2 Control 26 */ - { 0x0B21, 0x0000 }, /* R2849 - DSP2 Control 27 */ - { 0x0B22, 0x0000 }, /* R2850 - DSP2 Control 28 */ - { 0x0B23, 0x0000 }, /* R2851 - DSP2 Control 29 */ - { 0x0B24, 0x0000 }, /* R2852 - DSP2 Control 30 */ - { 0x0B26, 0x0000 }, /* R2854 - DSP2 Control 31 */ -}; - -static bool wm2200_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM2200_SOFTWARE_RESET: - case WM2200_DEVICE_REVISION: - case WM2200_ADPS1_IRQ0: - case WM2200_ADPS1_IRQ1: - case WM2200_INTERRUPT_STATUS_1: - case WM2200_INTERRUPT_STATUS_2: - case WM2200_INTERRUPT_RAW_STATUS_2: - return true; - default: - return false; - } -} - -static bool wm2200_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM2200_SOFTWARE_RESET: - case WM2200_DEVICE_REVISION: - case WM2200_TONE_GENERATOR_1: - case WM2200_CLOCKING_3: - case WM2200_CLOCKING_4: - case WM2200_FLL_CONTROL_1: - case WM2200_FLL_CONTROL_2: - case WM2200_FLL_CONTROL_3: - case WM2200_FLL_CONTROL_4: - case WM2200_FLL_CONTROL_6: - case WM2200_FLL_CONTROL_7: - case WM2200_FLL_EFS_1: - case WM2200_FLL_EFS_2: - case WM2200_MIC_CHARGE_PUMP_1: - case WM2200_MIC_CHARGE_PUMP_2: - case WM2200_DM_CHARGE_PUMP_1: - case WM2200_MIC_BIAS_CTRL_1: - case WM2200_MIC_BIAS_CTRL_2: - case WM2200_EAR_PIECE_CTRL_1: - case WM2200_EAR_PIECE_CTRL_2: - case WM2200_INPUT_ENABLES: - case WM2200_IN1L_CONTROL: - case WM2200_IN1R_CONTROL: - case WM2200_IN2L_CONTROL: - case WM2200_IN2R_CONTROL: - case WM2200_IN3L_CONTROL: - case WM2200_IN3R_CONTROL: - case WM2200_RXANC_SRC: - case WM2200_INPUT_VOLUME_RAMP: - case WM2200_ADC_DIGITAL_VOLUME_1L: - case WM2200_ADC_DIGITAL_VOLUME_1R: - case WM2200_ADC_DIGITAL_VOLUME_2L: - case WM2200_ADC_DIGITAL_VOLUME_2R: - case WM2200_ADC_DIGITAL_VOLUME_3L: - case WM2200_ADC_DIGITAL_VOLUME_3R: - case WM2200_OUTPUT_ENABLES: - case WM2200_DAC_VOLUME_LIMIT_1L: - case WM2200_DAC_VOLUME_LIMIT_1R: - case WM2200_DAC_VOLUME_LIMIT_2L: - case WM2200_DAC_VOLUME_LIMIT_2R: - case WM2200_DAC_AEC_CONTROL_1: - case WM2200_OUTPUT_VOLUME_RAMP: - case WM2200_DAC_DIGITAL_VOLUME_1L: - case WM2200_DAC_DIGITAL_VOLUME_1R: - case WM2200_DAC_DIGITAL_VOLUME_2L: - case WM2200_DAC_DIGITAL_VOLUME_2R: - case WM2200_PDM_1: - case WM2200_PDM_2: - case WM2200_AUDIO_IF_1_1: - case WM2200_AUDIO_IF_1_2: - case WM2200_AUDIO_IF_1_3: - case WM2200_AUDIO_IF_1_4: - case WM2200_AUDIO_IF_1_5: - case WM2200_AUDIO_IF_1_6: - case WM2200_AUDIO_IF_1_7: - case WM2200_AUDIO_IF_1_8: - case WM2200_AUDIO_IF_1_9: - case WM2200_AUDIO_IF_1_10: - case WM2200_AUDIO_IF_1_11: - case WM2200_AUDIO_IF_1_12: - case WM2200_AUDIO_IF_1_13: - case WM2200_AUDIO_IF_1_14: - case WM2200_AUDIO_IF_1_15: - case WM2200_AUDIO_IF_1_16: - case WM2200_AUDIO_IF_1_17: - case WM2200_AUDIO_IF_1_18: - case WM2200_AUDIO_IF_1_19: - case WM2200_AUDIO_IF_1_20: - case WM2200_AUDIO_IF_1_21: - case WM2200_AUDIO_IF_1_22: - case WM2200_OUT1LMIX_INPUT_1_SOURCE: - case WM2200_OUT1LMIX_INPUT_1_VOLUME: - case WM2200_OUT1LMIX_INPUT_2_SOURCE: - case WM2200_OUT1LMIX_INPUT_2_VOLUME: - case WM2200_OUT1LMIX_INPUT_3_SOURCE: - case WM2200_OUT1LMIX_INPUT_3_VOLUME: - case WM2200_OUT1LMIX_INPUT_4_SOURCE: - case WM2200_OUT1LMIX_INPUT_4_VOLUME: - case WM2200_OUT1RMIX_INPUT_1_SOURCE: - case WM2200_OUT1RMIX_INPUT_1_VOLUME: - case WM2200_OUT1RMIX_INPUT_2_SOURCE: - case WM2200_OUT1RMIX_INPUT_2_VOLUME: - case WM2200_OUT1RMIX_INPUT_3_SOURCE: - case WM2200_OUT1RMIX_INPUT_3_VOLUME: - case WM2200_OUT1RMIX_INPUT_4_SOURCE: - case WM2200_OUT1RMIX_INPUT_4_VOLUME: - case WM2200_OUT2LMIX_INPUT_1_SOURCE: - case WM2200_OUT2LMIX_INPUT_1_VOLUME: - case WM2200_OUT2LMIX_INPUT_2_SOURCE: - case WM2200_OUT2LMIX_INPUT_2_VOLUME: - case WM2200_OUT2LMIX_INPUT_3_SOURCE: - case WM2200_OUT2LMIX_INPUT_3_VOLUME: - case WM2200_OUT2LMIX_INPUT_4_SOURCE: - case WM2200_OUT2LMIX_INPUT_4_VOLUME: - case WM2200_OUT2RMIX_INPUT_1_SOURCE: - case WM2200_OUT2RMIX_INPUT_1_VOLUME: - case WM2200_OUT2RMIX_INPUT_2_SOURCE: - case WM2200_OUT2RMIX_INPUT_2_VOLUME: - case WM2200_OUT2RMIX_INPUT_3_SOURCE: - case WM2200_OUT2RMIX_INPUT_3_VOLUME: - case WM2200_OUT2RMIX_INPUT_4_SOURCE: - case WM2200_OUT2RMIX_INPUT_4_VOLUME: - case WM2200_AIF1TX1MIX_INPUT_1_SOURCE: - case WM2200_AIF1TX1MIX_INPUT_1_VOLUME: - case WM2200_AIF1TX1MIX_INPUT_2_SOURCE: - case WM2200_AIF1TX1MIX_INPUT_2_VOLUME: - case WM2200_AIF1TX1MIX_INPUT_3_SOURCE: - case WM2200_AIF1TX1MIX_INPUT_3_VOLUME: - case WM2200_AIF1TX1MIX_INPUT_4_SOURCE: - case WM2200_AIF1TX1MIX_INPUT_4_VOLUME: - case WM2200_AIF1TX2MIX_INPUT_1_SOURCE: - case WM2200_AIF1TX2MIX_INPUT_1_VOLUME: - case WM2200_AIF1TX2MIX_INPUT_2_SOURCE: - case WM2200_AIF1TX2MIX_INPUT_2_VOLUME: - case WM2200_AIF1TX2MIX_INPUT_3_SOURCE: - case WM2200_AIF1TX2MIX_INPUT_3_VOLUME: - case WM2200_AIF1TX2MIX_INPUT_4_SOURCE: - case WM2200_AIF1TX2MIX_INPUT_4_VOLUME: - case WM2200_AIF1TX3MIX_INPUT_1_SOURCE: - case WM2200_AIF1TX3MIX_INPUT_1_VOLUME: - case WM2200_AIF1TX3MIX_INPUT_2_SOURCE: - case WM2200_AIF1TX3MIX_INPUT_2_VOLUME: - case WM2200_AIF1TX3MIX_INPUT_3_SOURCE: - case WM2200_AIF1TX3MIX_INPUT_3_VOLUME: - case WM2200_AIF1TX3MIX_INPUT_4_SOURCE: - case WM2200_AIF1TX3MIX_INPUT_4_VOLUME: - case WM2200_AIF1TX4MIX_INPUT_1_SOURCE: - case WM2200_AIF1TX4MIX_INPUT_1_VOLUME: - case WM2200_AIF1TX4MIX_INPUT_2_SOURCE: - case WM2200_AIF1TX4MIX_INPUT_2_VOLUME: - case WM2200_AIF1TX4MIX_INPUT_3_SOURCE: - case WM2200_AIF1TX4MIX_INPUT_3_VOLUME: - case WM2200_AIF1TX4MIX_INPUT_4_SOURCE: - case WM2200_AIF1TX4MIX_INPUT_4_VOLUME: - case WM2200_AIF1TX5MIX_INPUT_1_SOURCE: - case WM2200_AIF1TX5MIX_INPUT_1_VOLUME: - case WM2200_AIF1TX5MIX_INPUT_2_SOURCE: - case WM2200_AIF1TX5MIX_INPUT_2_VOLUME: - case WM2200_AIF1TX5MIX_INPUT_3_SOURCE: - case WM2200_AIF1TX5MIX_INPUT_3_VOLUME: - case WM2200_AIF1TX5MIX_INPUT_4_SOURCE: - case WM2200_AIF1TX5MIX_INPUT_4_VOLUME: - case WM2200_AIF1TX6MIX_INPUT_1_SOURCE: - case WM2200_AIF1TX6MIX_INPUT_1_VOLUME: - case WM2200_AIF1TX6MIX_INPUT_2_SOURCE: - case WM2200_AIF1TX6MIX_INPUT_2_VOLUME: - case WM2200_AIF1TX6MIX_INPUT_3_SOURCE: - case WM2200_AIF1TX6MIX_INPUT_3_VOLUME: - case WM2200_AIF1TX6MIX_INPUT_4_SOURCE: - case WM2200_AIF1TX6MIX_INPUT_4_VOLUME: - case WM2200_EQLMIX_INPUT_1_SOURCE: - case WM2200_EQLMIX_INPUT_1_VOLUME: - case WM2200_EQLMIX_INPUT_2_SOURCE: - case WM2200_EQLMIX_INPUT_2_VOLUME: - case WM2200_EQLMIX_INPUT_3_SOURCE: - case WM2200_EQLMIX_INPUT_3_VOLUME: - case WM2200_EQLMIX_INPUT_4_SOURCE: - case WM2200_EQLMIX_INPUT_4_VOLUME: - case WM2200_EQRMIX_INPUT_1_SOURCE: - case WM2200_EQRMIX_INPUT_1_VOLUME: - case WM2200_EQRMIX_INPUT_2_SOURCE: - case WM2200_EQRMIX_INPUT_2_VOLUME: - case WM2200_EQRMIX_INPUT_3_SOURCE: - case WM2200_EQRMIX_INPUT_3_VOLUME: - case WM2200_EQRMIX_INPUT_4_SOURCE: - case WM2200_EQRMIX_INPUT_4_VOLUME: - case WM2200_LHPF1MIX_INPUT_1_SOURCE: - case WM2200_LHPF1MIX_INPUT_1_VOLUME: - case WM2200_LHPF1MIX_INPUT_2_SOURCE: - case WM2200_LHPF1MIX_INPUT_2_VOLUME: - case WM2200_LHPF1MIX_INPUT_3_SOURCE: - case WM2200_LHPF1MIX_INPUT_3_VOLUME: - case WM2200_LHPF1MIX_INPUT_4_SOURCE: - case WM2200_LHPF1MIX_INPUT_4_VOLUME: - case WM2200_LHPF2MIX_INPUT_1_SOURCE: - case WM2200_LHPF2MIX_INPUT_1_VOLUME: - case WM2200_LHPF2MIX_INPUT_2_SOURCE: - case WM2200_LHPF2MIX_INPUT_2_VOLUME: - case WM2200_LHPF2MIX_INPUT_3_SOURCE: - case WM2200_LHPF2MIX_INPUT_3_VOLUME: - case WM2200_LHPF2MIX_INPUT_4_SOURCE: - case WM2200_LHPF2MIX_INPUT_4_VOLUME: - case WM2200_DSP1LMIX_INPUT_1_SOURCE: - case WM2200_DSP1LMIX_INPUT_1_VOLUME: - case WM2200_DSP1LMIX_INPUT_2_SOURCE: - case WM2200_DSP1LMIX_INPUT_2_VOLUME: - case WM2200_DSP1LMIX_INPUT_3_SOURCE: - case WM2200_DSP1LMIX_INPUT_3_VOLUME: - case WM2200_DSP1LMIX_INPUT_4_SOURCE: - case WM2200_DSP1LMIX_INPUT_4_VOLUME: - case WM2200_DSP1RMIX_INPUT_1_SOURCE: - case WM2200_DSP1RMIX_INPUT_1_VOLUME: - case WM2200_DSP1RMIX_INPUT_2_SOURCE: - case WM2200_DSP1RMIX_INPUT_2_VOLUME: - case WM2200_DSP1RMIX_INPUT_3_SOURCE: - case WM2200_DSP1RMIX_INPUT_3_VOLUME: - case WM2200_DSP1RMIX_INPUT_4_SOURCE: - case WM2200_DSP1RMIX_INPUT_4_VOLUME: - case WM2200_DSP1AUX1MIX_INPUT_1_SOURCE: - case WM2200_DSP1AUX2MIX_INPUT_1_SOURCE: - case WM2200_DSP1AUX3MIX_INPUT_1_SOURCE: - case WM2200_DSP1AUX4MIX_INPUT_1_SOURCE: - case WM2200_DSP1AUX5MIX_INPUT_1_SOURCE: - case WM2200_DSP1AUX6MIX_INPUT_1_SOURCE: - case WM2200_DSP2LMIX_INPUT_1_SOURCE: - case WM2200_DSP2LMIX_INPUT_1_VOLUME: - case WM2200_DSP2LMIX_INPUT_2_SOURCE: - case WM2200_DSP2LMIX_INPUT_2_VOLUME: - case WM2200_DSP2LMIX_INPUT_3_SOURCE: - case WM2200_DSP2LMIX_INPUT_3_VOLUME: - case WM2200_DSP2LMIX_INPUT_4_SOURCE: - case WM2200_DSP2LMIX_INPUT_4_VOLUME: - case WM2200_DSP2RMIX_INPUT_1_SOURCE: - case WM2200_DSP2RMIX_INPUT_1_VOLUME: - case WM2200_DSP2RMIX_INPUT_2_SOURCE: - case WM2200_DSP2RMIX_INPUT_2_VOLUME: - case WM2200_DSP2RMIX_INPUT_3_SOURCE: - case WM2200_DSP2RMIX_INPUT_3_VOLUME: - case WM2200_DSP2RMIX_INPUT_4_SOURCE: - case WM2200_DSP2RMIX_INPUT_4_VOLUME: - case WM2200_DSP2AUX1MIX_INPUT_1_SOURCE: - case WM2200_DSP2AUX2MIX_INPUT_1_SOURCE: - case WM2200_DSP2AUX3MIX_INPUT_1_SOURCE: - case WM2200_DSP2AUX4MIX_INPUT_1_SOURCE: - case WM2200_DSP2AUX5MIX_INPUT_1_SOURCE: - case WM2200_DSP2AUX6MIX_INPUT_1_SOURCE: - case WM2200_GPIO_CTRL_1: - case WM2200_GPIO_CTRL_2: - case WM2200_GPIO_CTRL_3: - case WM2200_GPIO_CTRL_4: - case WM2200_ADPS1_IRQ0: - case WM2200_ADPS1_IRQ1: - case WM2200_MISC_PAD_CTRL_1: - case WM2200_INTERRUPT_STATUS_1: - case WM2200_INTERRUPT_STATUS_1_MASK: - case WM2200_INTERRUPT_STATUS_2: - case WM2200_INTERRUPT_RAW_STATUS_2: - case WM2200_INTERRUPT_STATUS_2_MASK: - case WM2200_INTERRUPT_CONTROL: - case WM2200_EQL_1: - case WM2200_EQL_2: - case WM2200_EQL_3: - case WM2200_EQL_4: - case WM2200_EQL_5: - case WM2200_EQL_6: - case WM2200_EQL_7: - case WM2200_EQL_8: - case WM2200_EQL_9: - case WM2200_EQL_10: - case WM2200_EQL_11: - case WM2200_EQL_12: - case WM2200_EQL_13: - case WM2200_EQL_14: - case WM2200_EQL_15: - case WM2200_EQL_16: - case WM2200_EQL_17: - case WM2200_EQL_18: - case WM2200_EQL_19: - case WM2200_EQL_20: - case WM2200_EQR_1: - case WM2200_EQR_2: - case WM2200_EQR_3: - case WM2200_EQR_4: - case WM2200_EQR_5: - case WM2200_EQR_6: - case WM2200_EQR_7: - case WM2200_EQR_8: - case WM2200_EQR_9: - case WM2200_EQR_10: - case WM2200_EQR_11: - case WM2200_EQR_12: - case WM2200_EQR_13: - case WM2200_EQR_14: - case WM2200_EQR_15: - case WM2200_EQR_16: - case WM2200_EQR_17: - case WM2200_EQR_18: - case WM2200_EQR_19: - case WM2200_EQR_20: - case WM2200_HPLPF1_1: - case WM2200_HPLPF1_2: - case WM2200_HPLPF2_1: - case WM2200_HPLPF2_2: - case WM2200_DSP1_CONTROL_1: - case WM2200_DSP1_CONTROL_2: - case WM2200_DSP1_CONTROL_3: - case WM2200_DSP1_CONTROL_4: - case WM2200_DSP1_CONTROL_5: - case WM2200_DSP1_CONTROL_6: - case WM2200_DSP1_CONTROL_7: - case WM2200_DSP1_CONTROL_8: - case WM2200_DSP1_CONTROL_9: - case WM2200_DSP1_CONTROL_10: - case WM2200_DSP1_CONTROL_11: - case WM2200_DSP1_CONTROL_12: - case WM2200_DSP1_CONTROL_13: - case WM2200_DSP1_CONTROL_14: - case WM2200_DSP1_CONTROL_15: - case WM2200_DSP1_CONTROL_16: - case WM2200_DSP1_CONTROL_17: - case WM2200_DSP1_CONTROL_18: - case WM2200_DSP1_CONTROL_19: - case WM2200_DSP1_CONTROL_20: - case WM2200_DSP1_CONTROL_21: - case WM2200_DSP1_CONTROL_22: - case WM2200_DSP1_CONTROL_23: - case WM2200_DSP1_CONTROL_24: - case WM2200_DSP1_CONTROL_25: - case WM2200_DSP1_CONTROL_26: - case WM2200_DSP1_CONTROL_27: - case WM2200_DSP1_CONTROL_28: - case WM2200_DSP1_CONTROL_29: - case WM2200_DSP1_CONTROL_30: - case WM2200_DSP1_CONTROL_31: - case WM2200_DSP2_CONTROL_1: - case WM2200_DSP2_CONTROL_2: - case WM2200_DSP2_CONTROL_3: - case WM2200_DSP2_CONTROL_4: - case WM2200_DSP2_CONTROL_5: - case WM2200_DSP2_CONTROL_6: - case WM2200_DSP2_CONTROL_7: - case WM2200_DSP2_CONTROL_8: - case WM2200_DSP2_CONTROL_9: - case WM2200_DSP2_CONTROL_10: - case WM2200_DSP2_CONTROL_11: - case WM2200_DSP2_CONTROL_12: - case WM2200_DSP2_CONTROL_13: - case WM2200_DSP2_CONTROL_14: - case WM2200_DSP2_CONTROL_15: - case WM2200_DSP2_CONTROL_16: - case WM2200_DSP2_CONTROL_17: - case WM2200_DSP2_CONTROL_18: - case WM2200_DSP2_CONTROL_19: - case WM2200_DSP2_CONTROL_20: - case WM2200_DSP2_CONTROL_21: - case WM2200_DSP2_CONTROL_22: - case WM2200_DSP2_CONTROL_23: - case WM2200_DSP2_CONTROL_24: - case WM2200_DSP2_CONTROL_25: - case WM2200_DSP2_CONTROL_26: - case WM2200_DSP2_CONTROL_27: - case WM2200_DSP2_CONTROL_28: - case WM2200_DSP2_CONTROL_29: - case WM2200_DSP2_CONTROL_30: - case WM2200_DSP2_CONTROL_31: - return true; - default: - return false; - } -} - -static const struct reg_default wm2200_reva_patch[] = { - { 0x07, 0x0003 }, - { 0x102, 0x0200 }, - { 0x203, 0x0084 }, - { 0x201, 0x83FF }, - { 0x20C, 0x0062 }, - { 0x20D, 0x0062 }, - { 0x207, 0x2002 }, - { 0x208, 0x20C0 }, - { 0x21D, 0x01C0 }, - { 0x50A, 0x0001 }, - { 0x50B, 0x0002 }, - { 0x50C, 0x0003 }, - { 0x50D, 0x0004 }, - { 0x50E, 0x0005 }, - { 0x510, 0x0001 }, - { 0x511, 0x0002 }, - { 0x512, 0x0003 }, - { 0x513, 0x0004 }, - { 0x514, 0x0005 }, - { 0x515, 0x0000 }, - { 0x201, 0x8084 }, - { 0x202, 0xBBDE }, - { 0x203, 0x00EC }, - { 0x500, 0x8000 }, - { 0x507, 0x1820 }, - { 0x508, 0x1820 }, - { 0x505, 0x0300 }, - { 0x506, 0x0300 }, - { 0x302, 0x2280 }, - { 0x303, 0x0080 }, - { 0x304, 0x2280 }, - { 0x305, 0x0080 }, - { 0x306, 0x2280 }, - { 0x307, 0x0080 }, - { 0x401, 0x0080 }, - { 0x402, 0x0080 }, - { 0x417, 0x3069 }, - { 0x900, 0x6318 }, - { 0x901, 0x6300 }, - { 0x902, 0x0FC8 }, - { 0x903, 0x03FE }, - { 0x904, 0x00E0 }, - { 0x905, 0x1EC4 }, - { 0x906, 0xF136 }, - { 0x907, 0x0409 }, - { 0x908, 0x04CC }, - { 0x909, 0x1C9B }, - { 0x90A, 0xF337 }, - { 0x90B, 0x040B }, - { 0x90C, 0x0CBB }, - { 0x90D, 0x16F8 }, - { 0x90E, 0xF7D9 }, - { 0x90F, 0x040A }, - { 0x910, 0x1F14 }, - { 0x911, 0x058C }, - { 0x912, 0x0563 }, - { 0x913, 0x4000 }, - { 0x916, 0x6318 }, - { 0x917, 0x6300 }, - { 0x918, 0x0FC8 }, - { 0x919, 0x03FE }, - { 0x91A, 0x00E0 }, - { 0x91B, 0x1EC4 }, - { 0x91C, 0xF136 }, - { 0x91D, 0x0409 }, - { 0x91E, 0x04CC }, - { 0x91F, 0x1C9B }, - { 0x920, 0xF337 }, - { 0x921, 0x040B }, - { 0x922, 0x0CBB }, - { 0x923, 0x16F8 }, - { 0x924, 0xF7D9 }, - { 0x925, 0x040A }, - { 0x926, 0x1F14 }, - { 0x927, 0x058C }, - { 0x928, 0x0563 }, - { 0x929, 0x4000 }, - { 0x709, 0x2000 }, - { 0x207, 0x200E }, - { 0x208, 0x20D4 }, - { 0x20A, 0x0080 }, - { 0x07, 0x0000 }, -}; - -static int wm2200_reset(struct wm2200_priv *wm2200) -{ - if (wm2200->pdata.reset) { - gpio_set_value_cansleep(wm2200->pdata.reset, 0); - gpio_set_value_cansleep(wm2200->pdata.reset, 1); - - return 0; - } else { - return regmap_write(wm2200->regmap, WM2200_SOFTWARE_RESET, - 0x2200); - } -} - -static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0); -static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); -static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0); - -static const char *wm2200_mixer_texts[] = { - "None", - "Tone Generator", - "AEC loopback", - "IN1L", - "IN1R", - "IN2L", - "IN2R", - "IN3L", - "IN3R", - "AIF1RX1", - "AIF1RX2", - "AIF1RX3", - "AIF1RX4", - "AIF1RX5", - "AIF1RX6", - "EQL", - "EQR", - "LHPF1", - "LHPF2", - "LHPF3", - "LHPF4", - "DSP1.1", - "DSP1.2", - "DSP1.3", - "DSP1.4", - "DSP1.5", - "DSP1.6", - "DSP2.1", - "DSP2.2", - "DSP2.3", - "DSP2.4", - "DSP2.5", - "DSP2.6", -}; - -static int wm2200_mixer_values[] = { - 0x00, - 0x04, /* Tone */ - 0x08, /* AEC */ - 0x10, /* Input */ - 0x11, - 0x12, - 0x13, - 0x14, - 0x15, - 0x20, /* AIF */ - 0x21, - 0x22, - 0x23, - 0x24, - 0x25, - 0x50, /* EQ */ - 0x51, - 0x52, - 0x60, /* LHPF1 */ - 0x61, /* LHPF2 */ - 0x68, /* DSP1 */ - 0x69, - 0x6a, - 0x6b, - 0x6c, - 0x6d, - 0x70, /* DSP2 */ - 0x71, - 0x72, - 0x73, - 0x74, - 0x75, -}; - -#define WM2200_MIXER_CONTROLS(name, base) \ - SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \ - WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ - SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \ - WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ - SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \ - WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ - SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \ - WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv) - -#define WM2200_MUX_ENUM_DECL(name, reg) \ - SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \ - wm2200_mixer_texts, wm2200_mixer_values) - -#define WM2200_MUX_CTL_DECL(name) \ - const struct snd_kcontrol_new name##_mux = \ - SOC_DAPM_VALUE_ENUM("Route", name##_enum) - -#define WM2200_MIXER_ENUMS(name, base_reg) \ - static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg); \ - static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \ - static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \ - static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \ - static WM2200_MUX_CTL_DECL(name##_in1); \ - static WM2200_MUX_CTL_DECL(name##_in2); \ - static WM2200_MUX_CTL_DECL(name##_in3); \ - static WM2200_MUX_CTL_DECL(name##_in4) - -static const struct snd_kcontrol_new wm2200_snd_controls[] = { -SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, - WM2200_IN1_OSR_SHIFT, 1, 0), -SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL, - WM2200_IN2_OSR_SHIFT, 1, 0), -SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL, - WM2200_IN3_OSR_SHIFT, 1, 0), - -SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL, - WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv), -SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL, - WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv), -SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL, - WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv), - -SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, - WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, - WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, - WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1), - -SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L, - WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT, - 0xbf, 0, digital_tlv), -SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L, - WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT, - 0xbf, 0, digital_tlv), -SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L, - WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT, - 0xbf, 0, digital_tlv), - -SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L, - WM2200_OUT1_OSR_SHIFT, 1, 0), -SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L, - WM2200_OUT2_OSR_SHIFT, 1, 0), - -SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L, - WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L, - WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0, - digital_tlv), -SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L, - WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT, - 0x46, 0, out_tlv), - -SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L, - WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, - WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0, - digital_tlv), -SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, - WM2200_SPK1R_MUTE_SHIFT, 1, 0), -}; - -WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE); - -WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE); - -WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE); - -WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE); - -WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE); -WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE); - -#define WM2200_MUX(name, ctrl) \ - SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) - -#define WM2200_MIXER_WIDGETS(name, name_str) \ - WM2200_MUX(name_str " Input 1", &name##_in1_mux), \ - WM2200_MUX(name_str " Input 2", &name##_in2_mux), \ - WM2200_MUX(name_str " Input 3", &name##_in3_mux), \ - WM2200_MUX(name_str " Input 4", &name##_in4_mux), \ - SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) - -#define WM2200_MIXER_INPUT_ROUTES(name) \ - { name, "Tone Generator", "Tone Generator" }, \ - { name, "IN1L", "IN1L PGA" }, \ - { name, "IN1R", "IN1R PGA" }, \ - { name, "IN2L", "IN2L PGA" }, \ - { name, "IN2R", "IN2R PGA" }, \ - { name, "IN3L", "IN3L PGA" }, \ - { name, "IN3R", "IN3R PGA" }, \ - { name, "DSP1.1", "DSP1" }, \ - { name, "DSP1.2", "DSP1" }, \ - { name, "DSP1.3", "DSP1" }, \ - { name, "DSP1.4", "DSP1" }, \ - { name, "DSP1.5", "DSP1" }, \ - { name, "DSP1.6", "DSP1" }, \ - { name, "DSP2.1", "DSP2" }, \ - { name, "DSP2.2", "DSP2" }, \ - { name, "DSP2.3", "DSP2" }, \ - { name, "DSP2.4", "DSP2" }, \ - { name, "DSP2.5", "DSP2" }, \ - { name, "DSP2.6", "DSP2" }, \ - { name, "AIF1RX1", "AIF1RX1" }, \ - { name, "AIF1RX2", "AIF1RX2" }, \ - { name, "AIF1RX3", "AIF1RX3" }, \ - { name, "AIF1RX4", "AIF1RX4" }, \ - { name, "AIF1RX5", "AIF1RX5" }, \ - { name, "AIF1RX6", "AIF1RX6" }, \ - { name, "EQL", "EQL" }, \ - { name, "EQR", "EQR" }, \ - { name, "LHPF1", "LHPF1" }, \ - { name, "LHPF2", "LHPF2" } - -#define WM2200_MIXER_ROUTES(widget, name) \ - { widget, NULL, name " Mixer" }, \ - { name " Mixer", NULL, name " Input 1" }, \ - { name " Mixer", NULL, name " Input 2" }, \ - { name " Mixer", NULL, name " Input 3" }, \ - { name " Mixer", NULL, name " Input 4" }, \ - WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \ - WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \ - WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \ - WM2200_MIXER_INPUT_ROUTES(name " Input 4") - -static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = { -SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT, - 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT, - 0, NULL, 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20), - -SND_SOC_DAPM_INPUT("IN1L"), -SND_SOC_DAPM_INPUT("IN1R"), -SND_SOC_DAPM_INPUT("IN2L"), -SND_SOC_DAPM_INPUT("IN2R"), -SND_SOC_DAPM_INPUT("IN3L"), -SND_SOC_DAPM_INPUT("IN3R"), - -SND_SOC_DAPM_SIGGEN("TONE"), -SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1, - WM2200_TONE_ENA_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0, - NULL, 0), - -SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0, - WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1, - WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2, - WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3, - WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4, - WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5, - WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0), - -SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0, - NULL, 0), - -SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0), -SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0), - -SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0, - WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1, - WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2, - WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3, - WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4, - WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5, - WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0), - -SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES, - WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES, - WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1, - WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1, - WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1, - WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1, - WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1, - WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1, - WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2, - WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2, - WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2, - WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2, - WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2, - WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2, - WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT, - 0, NULL, 0), -SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT, - 0, NULL, 0), - -SND_SOC_DAPM_OUTPUT("EPOUTLN"), -SND_SOC_DAPM_OUTPUT("EPOUTLP"), -SND_SOC_DAPM_OUTPUT("EPOUTRN"), -SND_SOC_DAPM_OUTPUT("EPOUTRP"), -SND_SOC_DAPM_OUTPUT("SPK"), - -WM2200_MIXER_WIDGETS(EQL, "EQL"), -WM2200_MIXER_WIDGETS(EQR, "EQR"), - -WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"), -WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"), - -WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"), -WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"), -WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"), -WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"), - -WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), -WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), -WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), -WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), -WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), -WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), - -WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"), -WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"), -WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"), -WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"), -}; - -static const struct snd_soc_dapm_route wm2200_dapm_routes[] = { - /* Everything needs SYSCLK but only hook up things on the edge - * of the chip */ - { "IN1L", NULL, "SYSCLK" }, - { "IN1R", NULL, "SYSCLK" }, - { "IN2L", NULL, "SYSCLK" }, - { "IN2R", NULL, "SYSCLK" }, - { "IN3L", NULL, "SYSCLK" }, - { "IN3R", NULL, "SYSCLK" }, - { "OUT1L", NULL, "SYSCLK" }, - { "OUT1R", NULL, "SYSCLK" }, - { "OUT2L", NULL, "SYSCLK" }, - { "OUT2R", NULL, "SYSCLK" }, - { "AIF1RX1", NULL, "SYSCLK" }, - { "AIF1RX2", NULL, "SYSCLK" }, - { "AIF1RX3", NULL, "SYSCLK" }, - { "AIF1RX4", NULL, "SYSCLK" }, - { "AIF1RX5", NULL, "SYSCLK" }, - { "AIF1RX6", NULL, "SYSCLK" }, - { "AIF1TX1", NULL, "SYSCLK" }, - { "AIF1TX2", NULL, "SYSCLK" }, - { "AIF1TX3", NULL, "SYSCLK" }, - { "AIF1TX4", NULL, "SYSCLK" }, - { "AIF1TX5", NULL, "SYSCLK" }, - { "AIF1TX6", NULL, "SYSCLK" }, - - { "IN1L", NULL, "AVDD" }, - { "IN1R", NULL, "AVDD" }, - { "IN2L", NULL, "AVDD" }, - { "IN2R", NULL, "AVDD" }, - { "IN3L", NULL, "AVDD" }, - { "IN3R", NULL, "AVDD" }, - { "OUT1L", NULL, "AVDD" }, - { "OUT1R", NULL, "AVDD" }, - - { "IN1L PGA", NULL, "IN1L" }, - { "IN1R PGA", NULL, "IN1R" }, - { "IN2L PGA", NULL, "IN2L" }, - { "IN2R PGA", NULL, "IN2R" }, - { "IN3L PGA", NULL, "IN3L" }, - { "IN3R PGA", NULL, "IN3R" }, - - { "Tone Generator", NULL, "TONE" }, - - { "CP2", NULL, "CPVDD" }, - { "MICBIAS1", NULL, "CP2" }, - { "MICBIAS2", NULL, "CP2" }, - - { "CP1", NULL, "CPVDD" }, - { "EPD_LN", NULL, "CP1" }, - { "EPD_LP", NULL, "CP1" }, - { "EPD_RN", NULL, "CP1" }, - { "EPD_RP", NULL, "CP1" }, - - { "EPD_LP", NULL, "OUT1L" }, - { "EPD_OUTP_LP", NULL, "EPD_LP" }, - { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" }, - { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" }, - - { "EPD_LN", NULL, "OUT1L" }, - { "EPD_OUTP_LN", NULL, "EPD_LN" }, - { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" }, - { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" }, - - { "EPD_RP", NULL, "OUT1R" }, - { "EPD_OUTP_RP", NULL, "EPD_RP" }, - { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" }, - { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" }, - - { "EPD_RN", NULL, "OUT1R" }, - { "EPD_OUTP_RN", NULL, "EPD_RN" }, - { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" }, - { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" }, - - { "SPK", NULL, "OUT2L" }, - { "SPK", NULL, "OUT2R" }, - - WM2200_MIXER_ROUTES("DSP1", "DSP1L"), - WM2200_MIXER_ROUTES("DSP1", "DSP1R"), - WM2200_MIXER_ROUTES("DSP2", "DSP2L"), - WM2200_MIXER_ROUTES("DSP2", "DSP2R"), - - WM2200_MIXER_ROUTES("OUT1L", "OUT1L"), - WM2200_MIXER_ROUTES("OUT1R", "OUT1R"), - WM2200_MIXER_ROUTES("OUT2L", "OUT2L"), - WM2200_MIXER_ROUTES("OUT2R", "OUT2R"), - - WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), - WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), - WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), - WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), - WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), - WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), - - WM2200_MIXER_ROUTES("EQL", "EQL"), - WM2200_MIXER_ROUTES("EQR", "EQR"), - - WM2200_MIXER_ROUTES("LHPF1", "LHPF1"), - WM2200_MIXER_ROUTES("LHPF2", "LHPF2"), -}; - -static int wm2200_probe(struct snd_soc_codec *codec) -{ - struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev); - int ret; - - wm2200->codec = codec; - codec->control_data = wm2200->regmap; - codec->dapm.bias_level = SND_SOC_BIAS_OFF; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - return ret; -} - -static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - int lrclk, bclk, fmt_val; - - lrclk = 0; - bclk = 0; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - fmt_val = 0; - break; - case SND_SOC_DAIFMT_DSP_B: - fmt_val = 1; - break; - case SND_SOC_DAIFMT_I2S: - fmt_val = 2; - break; - case SND_SOC_DAIFMT_LEFT_J: - fmt_val = 3; - break; - default: - dev_err(codec->dev, "Unsupported DAI format %d\n", - fmt & SND_SOC_DAIFMT_FORMAT_MASK); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBS_CFM: - lrclk |= WM2200_AIF1TX_LRCLK_MSTR; - break; - case SND_SOC_DAIFMT_CBM_CFS: - bclk |= WM2200_AIF1_BCLK_MSTR; - break; - case SND_SOC_DAIFMT_CBM_CFM: - lrclk |= WM2200_AIF1TX_LRCLK_MSTR; - bclk |= WM2200_AIF1_BCLK_MSTR; - break; - default: - dev_err(codec->dev, "Unsupported master mode %d\n", - fmt & SND_SOC_DAIFMT_MASTER_MASK); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - bclk |= WM2200_AIF1_BCLK_INV; - lrclk |= WM2200_AIF1TX_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - bclk |= WM2200_AIF1_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - lrclk |= WM2200_AIF1TX_LRCLK_INV; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR | - WM2200_AIF1_BCLK_INV, bclk); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2, - WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, - lrclk); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3, - WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, - lrclk); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, - WM2200_AIF1_FMT_MASK << 1, fmt_val << 1); - - return 0; -} - -static int wm2200_sr_code[] = { - 0, - 12000, - 24000, - 48000, - 96000, - 192000, - 384000, - 768000, - 0, - 11025, - 22050, - 44100, - 88200, - 176400, - 352800, - 705600, - 4000, - 8000, - 16000, - 32000, - 64000, - 128000, - 256000, - 512000, -}; - -#define WM2200_NUM_BCLK_RATES 12 - -static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = { - 6144000, - 3072000, - 2048000, - 1536000, - 768000, - 512000, - 384000, - 256000, - 192000, - 128000, - 96000, - 64000, -}; - -static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = { - 5644800, - 3763200, - 2882400, - 1881600, - 1411200, - 705600, - 470400, - 352800, - 176400, - 117600, - 88200, - 58800, -}; - -static int wm2200_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec); - int i, bclk, lrclk, wl, fl, sr_code; - int *bclk_rates; - - /* Data sizes if not using TDM */ - wl = snd_pcm_format_width(params_format(params)); - if (wl < 0) - return wl; - fl = snd_soc_params_to_frame_size(params); - if (fl < 0) - return fl; - - dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n", - wl, fl); - - /* Target BCLK rate */ - bclk = snd_soc_params_to_bclk(params); - if (bclk < 0) - return bclk; - - if (!wm2200->sysclk) { - dev_err(codec->dev, "SYSCLK has no rate set\n"); - return -EINVAL; - } - - for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++) - if (wm2200_sr_code[i] == params_rate(params)) - break; - if (i == ARRAY_SIZE(wm2200_sr_code)) { - dev_err(codec->dev, "Unsupported sample rate: %dHz\n", - params_rate(params)); - return -EINVAL; - } - sr_code = i; - - dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n", - bclk, wm2200->sysclk); - - if (wm2200->sysclk % 4000) - bclk_rates = wm2200_bclk_rates_cd; - else - bclk_rates = wm2200_bclk_rates_dat; - - for (i = 0; i < WM2200_NUM_BCLK_RATES; i++) - if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0)) - break; - if (i == WM2200_NUM_BCLK_RATES) { - dev_err(codec->dev, - "No valid BCLK for %dHz found from %dHz SYSCLK\n", - bclk, wm2200->sysclk); - return -EINVAL; - } - - bclk = i; - dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]); - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, - WM2200_AIF1_BCLK_DIV_MASK, bclk); - - lrclk = bclk_rates[bclk] / params_rate(params); - dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - dai->symmetric_rates) - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7, - WM2200_AIF1RX_BCPF_MASK, lrclk); - else - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6, - WM2200_AIF1TX_BCPF_MASK, lrclk); - - i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9, - WM2200_AIF1RX_WL_MASK | - WM2200_AIF1RX_SLOT_LEN_MASK, i); - else - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8, - WM2200_AIF1TX_WL_MASK | - WM2200_AIF1TX_SLOT_LEN_MASK, i); - - snd_soc_update_bits(codec, WM2200_CLOCKING_4, - WM2200_SAMPLE_RATE_1_MASK, sr_code); - - return 0; -} - -static const struct snd_soc_dai_ops wm2200_dai_ops = { - .set_fmt = wm2200_set_fmt, - .hw_params = wm2200_hw_params, -}; - -static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id, - int source, unsigned int freq, int dir) -{ - struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec); - int fval; - - switch (clk_id) { - case WM2200_CLK_SYSCLK: - break; - - default: - dev_err(codec->dev, "Unknown clock %d\n", clk_id); - return -EINVAL; - } - - switch (source) { - case WM2200_CLKSRC_MCLK1: - case WM2200_CLKSRC_MCLK2: - case WM2200_CLKSRC_FLL: - case WM2200_CLKSRC_BCLK1: - break; - default: - dev_err(codec->dev, "Invalid source %d\n", source); - return -EINVAL; - } - - switch (freq) { - case 22579200: - case 24576000: - fval = 2; - break; - default: - dev_err(codec->dev, "Invalid clock rate: %d\n", freq); - return -EINVAL; - } - - /* TODO: Check if MCLKs are in use and enable/disable pulls to - * match. - */ - - snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK | - WM2200_SYSCLK_SRC_MASK, - fval << WM2200_SYSCLK_FREQ_SHIFT | source); - - wm2200->sysclk = freq; - - return 0; -} - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_refclk_div; - u16 n; - u16 theta; - u16 lambda; -}; - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - unsigned int target; - unsigned int div; - unsigned int fratio, gcd_fll; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - fll_div->fll_refclk_div = 0; - while ((Fref / div) > 13500000) { - div *= 2; - fll_div->fll_refclk_div++; - - if (div > 8) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - - pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 2; - while (Fout * div < 90000000) { - div++; - if (div > 64) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - target = Fout * div; - fll_div->fll_outdiv = div - 1; - - pr_debug("FLL Fvco=%dHz\n", target); - - /* Find an appropraite FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - fratio = fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - fll_div->n = target / (fratio * Fref); - - if (target % Fref == 0) { - fll_div->theta = 0; - fll_div->lambda = 0; - } else { - gcd_fll = gcd(target, fratio * Fref); - - fll_div->theta = (target - (fll_div->n * fratio * Fref)) - / gcd_fll; - fll_div->lambda = (fratio * Fref) / gcd_fll; - } - - pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n", - fll_div->n, fll_div->theta, fll_div->lambda); - pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n", - fll_div->fll_fratio, fratio, fll_div->fll_outdiv, - fll_div->fll_refclk_div); - - return 0; -} - -static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source, - unsigned int Fref, unsigned int Fout) -{ - struct i2c_client *i2c = to_i2c_client(codec->dev); - struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec); - struct _fll_div factors; - int ret, i, timeout; - - if (!Fout) { - dev_dbg(codec->dev, "FLL disabled"); - - if (wm2200->fll_fout) - pm_runtime_put(codec->dev); - - wm2200->fll_fout = 0; - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, - WM2200_FLL_ENA, 0); - return 0; - } - - switch (source) { - case WM2200_FLL_SRC_MCLK1: - case WM2200_FLL_SRC_MCLK2: - case WM2200_FLL_SRC_BCLK: - break; - default: - dev_err(codec->dev, "Invalid FLL source %d\n", source); - return -EINVAL; - } - - ret = fll_factors(&factors, Fref, Fout); - if (ret < 0) - return ret; - - /* Disable the FLL while we reconfigure */ - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0); - - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2, - WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK, - (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) | - factors.fll_fratio); - if (factors.theta) { - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3, - WM2200_FLL_FRACN_ENA, - WM2200_FLL_FRACN_ENA); - snd_soc_update_bits(codec, WM2200_FLL_EFS_2, - WM2200_FLL_EFS_ENA, - WM2200_FLL_EFS_ENA); - } else { - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3, - WM2200_FLL_FRACN_ENA, 0); - snd_soc_update_bits(codec, WM2200_FLL_EFS_2, - WM2200_FLL_EFS_ENA, 0); - } - - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK, - factors.theta); - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK, - factors.n); - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7, - WM2200_FLL_CLK_REF_DIV_MASK | - WM2200_FLL_CLK_REF_SRC_MASK, - (factors.fll_refclk_div - << WM2200_FLL_CLK_REF_DIV_SHIFT) | source); - snd_soc_update_bits(codec, WM2200_FLL_EFS_1, - WM2200_FLL_LAMBDA_MASK, factors.lambda); - - /* Clear any pending completions */ - try_wait_for_completion(&wm2200->fll_lock); - - pm_runtime_get_sync(codec->dev); - - snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, - WM2200_FLL_ENA, WM2200_FLL_ENA); - - if (i2c->irq) - timeout = 2; - else - timeout = 50; - - snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA, - WM2200_SYSCLK_ENA); - - /* Poll for the lock; will use the interrupt to exit quickly */ - for (i = 0; i < timeout; i++) { - if (i2c->irq) { - ret = wait_for_completion_timeout(&wm2200->fll_lock, - msecs_to_jiffies(25)); - if (ret > 0) - break; - } else { - msleep(1); - } - - ret = snd_soc_read(codec, - WM2200_INTERRUPT_RAW_STATUS_2); - if (ret < 0) { - dev_err(codec->dev, - "Failed to read FLL status: %d\n", - ret); - continue; - } - if (ret & WM2200_FLL_LOCK_STS) - break; - } - if (i == timeout) { - dev_err(codec->dev, "FLL lock timed out\n"); - pm_runtime_put(codec->dev); - return -ETIMEDOUT; - } - - wm2200->fll_src = source; - wm2200->fll_fref = Fref; - wm2200->fll_fout = Fout; - - dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout); - - return 0; -} - -static int wm2200_dai_probe(struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - unsigned int val = 0; - int ret; - - ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1); - if (ret >= 0) { - if ((ret & WM2200_GP1_FN_MASK) != 0) { - dai->symmetric_rates = true; - val = WM2200_AIF1TX_LRCLK_SRC; - } - } else { - dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret); - } - - snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2, - WM2200_AIF1TX_LRCLK_SRC, val); - - return 0; -} - -#define WM2200_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_driver wm2200_dai = { - .name = "wm2200", - .probe = wm2200_dai_probe, - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM2200_RATES, - .formats = WM2200_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM2200_RATES, - .formats = WM2200_FORMATS, - }, - .ops = &wm2200_dai_ops, -}; - -static struct snd_soc_codec_driver soc_codec_wm2200 = { - .probe = wm2200_probe, - - .idle_bias_off = true, - .ignore_pmdown_time = true, - .set_sysclk = wm2200_set_sysclk, - .set_pll = wm2200_set_fll, - - .controls = wm2200_snd_controls, - .num_controls = ARRAY_SIZE(wm2200_snd_controls), - .dapm_widgets = wm2200_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets), - .dapm_routes = wm2200_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes), -}; - -static irqreturn_t wm2200_irq(int irq, void *data) -{ - struct wm2200_priv *wm2200 = data; - unsigned int val, mask; - int ret; - - ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val); - if (ret != 0) { - dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret); - return IRQ_NONE; - } - - ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK, - &mask); - if (ret != 0) { - dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret); - mask = 0; - } - - val &= ~mask; - - if (val & WM2200_FLL_LOCK_EINT) { - dev_dbg(wm2200->dev, "FLL locked\n"); - complete(&wm2200->fll_lock); - } - - if (val) { - regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val); - - return IRQ_HANDLED; - } else { - return IRQ_NONE; - } -} - -static const struct regmap_config wm2200_regmap = { - .reg_bits = 16, - .val_bits = 16, - - .max_register = WM2200_MAX_REGISTER, - .reg_defaults = wm2200_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults), - .volatile_reg = wm2200_volatile_register, - .readable_reg = wm2200_readable_register, - .cache_type = REGCACHE_RBTREE, -}; - -static const unsigned int wm2200_dig_vu[] = { - WM2200_DAC_DIGITAL_VOLUME_1L, - WM2200_DAC_DIGITAL_VOLUME_1R, - WM2200_DAC_DIGITAL_VOLUME_2L, - WM2200_DAC_DIGITAL_VOLUME_2R, - WM2200_ADC_DIGITAL_VOLUME_1L, - WM2200_ADC_DIGITAL_VOLUME_1R, - WM2200_ADC_DIGITAL_VOLUME_2L, - WM2200_ADC_DIGITAL_VOLUME_2R, - WM2200_ADC_DIGITAL_VOLUME_3L, - WM2200_ADC_DIGITAL_VOLUME_3R, -}; - -static const unsigned int wm2200_mic_ctrl_reg[] = { - WM2200_IN1L_CONTROL, - WM2200_IN2L_CONTROL, - WM2200_IN3L_CONTROL, -}; - -static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev); - struct wm2200_priv *wm2200; - unsigned int reg; - int ret, i; - - wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv), - GFP_KERNEL); - if (wm2200 == NULL) - return -ENOMEM; - - wm2200->dev = &i2c->dev; - init_completion(&wm2200->fll_lock); - - wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap); - if (IS_ERR(wm2200->regmap)) { - ret = PTR_ERR(wm2200->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - goto err; - } - - if (pdata) - wm2200->pdata = *pdata; - - i2c_set_clientdata(i2c, wm2200); - - for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++) - wm2200->core_supplies[i].supply = wm2200_core_supply_names[i]; - - ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies), - wm2200->core_supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to request core supplies: %d\n", - ret); - goto err_regmap; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies), - wm2200->core_supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to enable core supplies: %d\n", - ret); - goto err_core; - } - - if (wm2200->pdata.ldo_ena) { - ret = gpio_request_one(wm2200->pdata.ldo_ena, - GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA"); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", - wm2200->pdata.ldo_ena, ret); - goto err_enable; - } - msleep(2); - } - - if (wm2200->pdata.reset) { - ret = gpio_request_one(wm2200->pdata.reset, - GPIOF_OUT_INIT_HIGH, "WM2200 /RESET"); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", - wm2200->pdata.reset, ret); - goto err_ldo; - } - } - - ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, ®); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); - goto err_reset; - } - switch (reg) { - case 0x2200: - break; - - default: - dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg); - ret = -EINVAL; - goto err_reset; - } - - ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, ®); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to read revision register\n"); - goto err_reset; - } - - wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK; - - dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A'); - - switch (wm2200->rev) { - case 0: - ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch, - ARRAY_SIZE(wm2200_reva_patch)); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register patch: %d\n", - ret); - } - break; - default: - break; - } - - ret = wm2200_reset(wm2200); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to issue reset\n"); - goto err_reset; - } - - for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) { - if (!wm2200->pdata.gpio_defaults[i]) - continue; - - regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i, - wm2200->pdata.gpio_defaults[i]); - } - - for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++) - regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i], - WM2200_OUT_VU, WM2200_OUT_VU); - - /* Assign slots 1-6 to channels 1-6 for both TX and RX */ - for (i = 0; i < 6; i++) { - regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i); - regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i); - } - - for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) { - regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i], - WM2200_IN1_MODE_MASK | - WM2200_IN1_DMIC_SUP_MASK, - (wm2200->pdata.in_mode[i] << - WM2200_IN1_MODE_SHIFT) | - (wm2200->pdata.dmic_sup[i] << - WM2200_IN1_DMIC_SUP_SHIFT)); - } - - if (i2c->irq) { - ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "wm2200", wm2200); - if (ret == 0) - regmap_update_bits(wm2200->regmap, - WM2200_INTERRUPT_STATUS_2_MASK, - WM2200_FLL_LOCK_EINT, 0); - else - dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", - i2c->irq, ret); - } - - pm_runtime_set_active(&i2c->dev); - pm_runtime_enable(&i2c->dev); - pm_request_idle(&i2c->dev); - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200, - &wm2200_dai, 1); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - goto err_pm_runtime; - } - - return 0; - -err_pm_runtime: - pm_runtime_disable(&i2c->dev); -err_reset: - if (wm2200->pdata.reset) { - gpio_set_value_cansleep(wm2200->pdata.reset, 0); - gpio_free(wm2200->pdata.reset); - } -err_ldo: - if (wm2200->pdata.ldo_ena) { - gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); - gpio_free(wm2200->pdata.ldo_ena); - } -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), - wm2200->core_supplies); -err_core: - regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies), - wm2200->core_supplies); -err_regmap: - regmap_exit(wm2200->regmap); -err: - return ret; -} - -static __devexit int wm2200_i2c_remove(struct i2c_client *i2c) -{ - struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c); - - snd_soc_unregister_codec(&i2c->dev); - if (i2c->irq) - free_irq(i2c->irq, wm2200); - if (wm2200->pdata.reset) { - gpio_set_value_cansleep(wm2200->pdata.reset, 0); - gpio_free(wm2200->pdata.reset); - } - if (wm2200->pdata.ldo_ena) { - gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); - gpio_free(wm2200->pdata.ldo_ena); - } - regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies), - wm2200->core_supplies); - regmap_exit(wm2200->regmap); - - return 0; -} - -#ifdef CONFIG_PM_RUNTIME -static int wm2200_runtime_suspend(struct device *dev) -{ - struct wm2200_priv *wm2200 = dev_get_drvdata(dev); - - regcache_cache_only(wm2200->regmap, true); - regcache_mark_dirty(wm2200->regmap); - if (wm2200->pdata.ldo_ena) - gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); - regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), - wm2200->core_supplies); - - return 0; -} - -static int wm2200_runtime_resume(struct device *dev) -{ - struct wm2200_priv *wm2200 = dev_get_drvdata(dev); - int ret; - - ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies), - wm2200->core_supplies); - if (ret != 0) { - dev_err(dev, "Failed to enable supplies: %d\n", - ret); - return ret; - } - - if (wm2200->pdata.ldo_ena) { - gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1); - msleep(2); - } - - regcache_cache_only(wm2200->regmap, false); - regcache_sync(wm2200->regmap); - - return 0; -} -#endif - -static struct dev_pm_ops wm2200_pm = { - SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume, - NULL) -}; - -static const struct i2c_device_id wm2200_i2c_id[] = { - { "wm2200", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id); - -static struct i2c_driver wm2200_i2c_driver = { - .driver = { - .name = "wm2200", - .owner = THIS_MODULE, - .pm = &wm2200_pm, - }, - .probe = wm2200_i2c_probe, - .remove = __devexit_p(wm2200_i2c_remove), - .id_table = wm2200_i2c_id, -}; - -static int __init wm2200_modinit(void) -{ - return i2c_add_driver(&wm2200_i2c_driver); -} -module_init(wm2200_modinit); - -static void __exit wm2200_exit(void) -{ - i2c_del_driver(&wm2200_i2c_driver); -} -module_exit(wm2200_exit); - -MODULE_DESCRIPTION("ASoC WM2200 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm2200.h b/ANDROID_3.4.5/sound/soc/codecs/wm2200.h deleted file mode 100644 index 5d719d6b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm2200.h +++ /dev/null @@ -1,3674 +0,0 @@ -/* - * wm2200.h - WM2200 audio codec interface - * - * Copyright 2012 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * 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. - */ - -#ifndef _WM2200_H -#define _WM2200_H - -#define WM2200_CLK_SYSCLK 1 - -#define WM2200_CLKSRC_MCLK1 0 -#define WM2200_CLKSRC_MCLK2 1 -#define WM2200_CLKSRC_FLL 4 -#define WM2200_CLKSRC_BCLK1 8 - -#define WM2200_FLL_SRC_MCLK1 0 -#define WM2200_FLL_SRC_MCLK2 1 -#define WM2200_FLL_SRC_BCLK 2 - -/* - * Register values. - */ -#define WM2200_SOFTWARE_RESET 0x00 -#define WM2200_DEVICE_REVISION 0x01 -#define WM2200_TONE_GENERATOR_1 0x0B -#define WM2200_CLOCKING_3 0x102 -#define WM2200_CLOCKING_4 0x103 -#define WM2200_FLL_CONTROL_1 0x111 -#define WM2200_FLL_CONTROL_2 0x112 -#define WM2200_FLL_CONTROL_3 0x113 -#define WM2200_FLL_CONTROL_4 0x114 -#define WM2200_FLL_CONTROL_6 0x116 -#define WM2200_FLL_CONTROL_7 0x117 -#define WM2200_FLL_EFS_1 0x119 -#define WM2200_FLL_EFS_2 0x11A -#define WM2200_MIC_CHARGE_PUMP_1 0x200 -#define WM2200_MIC_CHARGE_PUMP_2 0x201 -#define WM2200_DM_CHARGE_PUMP_1 0x202 -#define WM2200_MIC_BIAS_CTRL_1 0x20C -#define WM2200_MIC_BIAS_CTRL_2 0x20D -#define WM2200_EAR_PIECE_CTRL_1 0x20F -#define WM2200_EAR_PIECE_CTRL_2 0x210 -#define WM2200_INPUT_ENABLES 0x301 -#define WM2200_IN1L_CONTROL 0x302 -#define WM2200_IN1R_CONTROL 0x303 -#define WM2200_IN2L_CONTROL 0x304 -#define WM2200_IN2R_CONTROL 0x305 -#define WM2200_IN3L_CONTROL 0x306 -#define WM2200_IN3R_CONTROL 0x307 -#define WM2200_RXANC_SRC 0x30A -#define WM2200_INPUT_VOLUME_RAMP 0x30B -#define WM2200_ADC_DIGITAL_VOLUME_1L 0x30C -#define WM2200_ADC_DIGITAL_VOLUME_1R 0x30D -#define WM2200_ADC_DIGITAL_VOLUME_2L 0x30E -#define WM2200_ADC_DIGITAL_VOLUME_2R 0x30F -#define WM2200_ADC_DIGITAL_VOLUME_3L 0x310 -#define WM2200_ADC_DIGITAL_VOLUME_3R 0x311 -#define WM2200_OUTPUT_ENABLES 0x400 -#define WM2200_DAC_VOLUME_LIMIT_1L 0x401 -#define WM2200_DAC_VOLUME_LIMIT_1R 0x402 -#define WM2200_DAC_VOLUME_LIMIT_2L 0x403 -#define WM2200_DAC_VOLUME_LIMIT_2R 0x404 -#define WM2200_DAC_AEC_CONTROL_1 0x409 -#define WM2200_OUTPUT_VOLUME_RAMP 0x40A -#define WM2200_DAC_DIGITAL_VOLUME_1L 0x40B -#define WM2200_DAC_DIGITAL_VOLUME_1R 0x40C -#define WM2200_DAC_DIGITAL_VOLUME_2L 0x40D -#define WM2200_DAC_DIGITAL_VOLUME_2R 0x40E -#define WM2200_PDM_1 0x417 -#define WM2200_PDM_2 0x418 -#define WM2200_AUDIO_IF_1_1 0x500 -#define WM2200_AUDIO_IF_1_2 0x501 -#define WM2200_AUDIO_IF_1_3 0x502 -#define WM2200_AUDIO_IF_1_4 0x503 -#define WM2200_AUDIO_IF_1_5 0x504 -#define WM2200_AUDIO_IF_1_6 0x505 -#define WM2200_AUDIO_IF_1_7 0x506 -#define WM2200_AUDIO_IF_1_8 0x507 -#define WM2200_AUDIO_IF_1_9 0x508 -#define WM2200_AUDIO_IF_1_10 0x509 -#define WM2200_AUDIO_IF_1_11 0x50A -#define WM2200_AUDIO_IF_1_12 0x50B -#define WM2200_AUDIO_IF_1_13 0x50C -#define WM2200_AUDIO_IF_1_14 0x50D -#define WM2200_AUDIO_IF_1_15 0x50E -#define WM2200_AUDIO_IF_1_16 0x50F -#define WM2200_AUDIO_IF_1_17 0x510 -#define WM2200_AUDIO_IF_1_18 0x511 -#define WM2200_AUDIO_IF_1_19 0x512 -#define WM2200_AUDIO_IF_1_20 0x513 -#define WM2200_AUDIO_IF_1_21 0x514 -#define WM2200_AUDIO_IF_1_22 0x515 -#define WM2200_OUT1LMIX_INPUT_1_SOURCE 0x600 -#define WM2200_OUT1LMIX_INPUT_1_VOLUME 0x601 -#define WM2200_OUT1LMIX_INPUT_2_SOURCE 0x602 -#define WM2200_OUT1LMIX_INPUT_2_VOLUME 0x603 -#define WM2200_OUT1LMIX_INPUT_3_SOURCE 0x604 -#define WM2200_OUT1LMIX_INPUT_3_VOLUME 0x605 -#define WM2200_OUT1LMIX_INPUT_4_SOURCE 0x606 -#define WM2200_OUT1LMIX_INPUT_4_VOLUME 0x607 -#define WM2200_OUT1RMIX_INPUT_1_SOURCE 0x608 -#define WM2200_OUT1RMIX_INPUT_1_VOLUME 0x609 -#define WM2200_OUT1RMIX_INPUT_2_SOURCE 0x60A -#define WM2200_OUT1RMIX_INPUT_2_VOLUME 0x60B -#define WM2200_OUT1RMIX_INPUT_3_SOURCE 0x60C -#define WM2200_OUT1RMIX_INPUT_3_VOLUME 0x60D -#define WM2200_OUT1RMIX_INPUT_4_SOURCE 0x60E -#define WM2200_OUT1RMIX_INPUT_4_VOLUME 0x60F -#define WM2200_OUT2LMIX_INPUT_1_SOURCE 0x610 -#define WM2200_OUT2LMIX_INPUT_1_VOLUME 0x611 -#define WM2200_OUT2LMIX_INPUT_2_SOURCE 0x612 -#define WM2200_OUT2LMIX_INPUT_2_VOLUME 0x613 -#define WM2200_OUT2LMIX_INPUT_3_SOURCE 0x614 -#define WM2200_OUT2LMIX_INPUT_3_VOLUME 0x615 -#define WM2200_OUT2LMIX_INPUT_4_SOURCE 0x616 -#define WM2200_OUT2LMIX_INPUT_4_VOLUME 0x617 -#define WM2200_OUT2RMIX_INPUT_1_SOURCE 0x618 -#define WM2200_OUT2RMIX_INPUT_1_VOLUME 0x619 -#define WM2200_OUT2RMIX_INPUT_2_SOURCE 0x61A -#define WM2200_OUT2RMIX_INPUT_2_VOLUME 0x61B -#define WM2200_OUT2RMIX_INPUT_3_SOURCE 0x61C -#define WM2200_OUT2RMIX_INPUT_3_VOLUME 0x61D -#define WM2200_OUT2RMIX_INPUT_4_SOURCE 0x61E -#define WM2200_OUT2RMIX_INPUT_4_VOLUME 0x61F -#define WM2200_AIF1TX1MIX_INPUT_1_SOURCE 0x620 -#define WM2200_AIF1TX1MIX_INPUT_1_VOLUME 0x621 -#define WM2200_AIF1TX1MIX_INPUT_2_SOURCE 0x622 -#define WM2200_AIF1TX1MIX_INPUT_2_VOLUME 0x623 -#define WM2200_AIF1TX1MIX_INPUT_3_SOURCE 0x624 -#define WM2200_AIF1TX1MIX_INPUT_3_VOLUME 0x625 -#define WM2200_AIF1TX1MIX_INPUT_4_SOURCE 0x626 -#define WM2200_AIF1TX1MIX_INPUT_4_VOLUME 0x627 -#define WM2200_AIF1TX2MIX_INPUT_1_SOURCE 0x628 -#define WM2200_AIF1TX2MIX_INPUT_1_VOLUME 0x629 -#define WM2200_AIF1TX2MIX_INPUT_2_SOURCE 0x62A -#define WM2200_AIF1TX2MIX_INPUT_2_VOLUME 0x62B -#define WM2200_AIF1TX2MIX_INPUT_3_SOURCE 0x62C -#define WM2200_AIF1TX2MIX_INPUT_3_VOLUME 0x62D -#define WM2200_AIF1TX2MIX_INPUT_4_SOURCE 0x62E -#define WM2200_AIF1TX2MIX_INPUT_4_VOLUME 0x62F -#define WM2200_AIF1TX3MIX_INPUT_1_SOURCE 0x630 -#define WM2200_AIF1TX3MIX_INPUT_1_VOLUME 0x631 -#define WM2200_AIF1TX3MIX_INPUT_2_SOURCE 0x632 -#define WM2200_AIF1TX3MIX_INPUT_2_VOLUME 0x633 -#define WM2200_AIF1TX3MIX_INPUT_3_SOURCE 0x634 -#define WM2200_AIF1TX3MIX_INPUT_3_VOLUME 0x635 -#define WM2200_AIF1TX3MIX_INPUT_4_SOURCE 0x636 -#define WM2200_AIF1TX3MIX_INPUT_4_VOLUME 0x637 -#define WM2200_AIF1TX4MIX_INPUT_1_SOURCE 0x638 -#define WM2200_AIF1TX4MIX_INPUT_1_VOLUME 0x639 -#define WM2200_AIF1TX4MIX_INPUT_2_SOURCE 0x63A -#define WM2200_AIF1TX4MIX_INPUT_2_VOLUME 0x63B -#define WM2200_AIF1TX4MIX_INPUT_3_SOURCE 0x63C -#define WM2200_AIF1TX4MIX_INPUT_3_VOLUME 0x63D -#define WM2200_AIF1TX4MIX_INPUT_4_SOURCE 0x63E -#define WM2200_AIF1TX4MIX_INPUT_4_VOLUME 0x63F -#define WM2200_AIF1TX5MIX_INPUT_1_SOURCE 0x640 -#define WM2200_AIF1TX5MIX_INPUT_1_VOLUME 0x641 -#define WM2200_AIF1TX5MIX_INPUT_2_SOURCE 0x642 -#define WM2200_AIF1TX5MIX_INPUT_2_VOLUME 0x643 -#define WM2200_AIF1TX5MIX_INPUT_3_SOURCE 0x644 -#define WM2200_AIF1TX5MIX_INPUT_3_VOLUME 0x645 -#define WM2200_AIF1TX5MIX_INPUT_4_SOURCE 0x646 -#define WM2200_AIF1TX5MIX_INPUT_4_VOLUME 0x647 -#define WM2200_AIF1TX6MIX_INPUT_1_SOURCE 0x648 -#define WM2200_AIF1TX6MIX_INPUT_1_VOLUME 0x649 -#define WM2200_AIF1TX6MIX_INPUT_2_SOURCE 0x64A -#define WM2200_AIF1TX6MIX_INPUT_2_VOLUME 0x64B -#define WM2200_AIF1TX6MIX_INPUT_3_SOURCE 0x64C -#define WM2200_AIF1TX6MIX_INPUT_3_VOLUME 0x64D -#define WM2200_AIF1TX6MIX_INPUT_4_SOURCE 0x64E -#define WM2200_AIF1TX6MIX_INPUT_4_VOLUME 0x64F -#define WM2200_EQLMIX_INPUT_1_SOURCE 0x650 -#define WM2200_EQLMIX_INPUT_1_VOLUME 0x651 -#define WM2200_EQLMIX_INPUT_2_SOURCE 0x652 -#define WM2200_EQLMIX_INPUT_2_VOLUME 0x653 -#define WM2200_EQLMIX_INPUT_3_SOURCE 0x654 -#define WM2200_EQLMIX_INPUT_3_VOLUME 0x655 -#define WM2200_EQLMIX_INPUT_4_SOURCE 0x656 -#define WM2200_EQLMIX_INPUT_4_VOLUME 0x657 -#define WM2200_EQRMIX_INPUT_1_SOURCE 0x658 -#define WM2200_EQRMIX_INPUT_1_VOLUME 0x659 -#define WM2200_EQRMIX_INPUT_2_SOURCE 0x65A -#define WM2200_EQRMIX_INPUT_2_VOLUME 0x65B -#define WM2200_EQRMIX_INPUT_3_SOURCE 0x65C -#define WM2200_EQRMIX_INPUT_3_VOLUME 0x65D -#define WM2200_EQRMIX_INPUT_4_SOURCE 0x65E -#define WM2200_EQRMIX_INPUT_4_VOLUME 0x65F -#define WM2200_LHPF1MIX_INPUT_1_SOURCE 0x660 -#define WM2200_LHPF1MIX_INPUT_1_VOLUME 0x661 -#define WM2200_LHPF1MIX_INPUT_2_SOURCE 0x662 -#define WM2200_LHPF1MIX_INPUT_2_VOLUME 0x663 -#define WM2200_LHPF1MIX_INPUT_3_SOURCE 0x664 -#define WM2200_LHPF1MIX_INPUT_3_VOLUME 0x665 -#define WM2200_LHPF1MIX_INPUT_4_SOURCE 0x666 -#define WM2200_LHPF1MIX_INPUT_4_VOLUME 0x667 -#define WM2200_LHPF2MIX_INPUT_1_SOURCE 0x668 -#define WM2200_LHPF2MIX_INPUT_1_VOLUME 0x669 -#define WM2200_LHPF2MIX_INPUT_2_SOURCE 0x66A -#define WM2200_LHPF2MIX_INPUT_2_VOLUME 0x66B -#define WM2200_LHPF2MIX_INPUT_3_SOURCE 0x66C -#define WM2200_LHPF2MIX_INPUT_3_VOLUME 0x66D -#define WM2200_LHPF2MIX_INPUT_4_SOURCE 0x66E -#define WM2200_LHPF2MIX_INPUT_4_VOLUME 0x66F -#define WM2200_DSP1LMIX_INPUT_1_SOURCE 0x670 -#define WM2200_DSP1LMIX_INPUT_1_VOLUME 0x671 -#define WM2200_DSP1LMIX_INPUT_2_SOURCE 0x672 -#define WM2200_DSP1LMIX_INPUT_2_VOLUME 0x673 -#define WM2200_DSP1LMIX_INPUT_3_SOURCE 0x674 -#define WM2200_DSP1LMIX_INPUT_3_VOLUME 0x675 -#define WM2200_DSP1LMIX_INPUT_4_SOURCE 0x676 -#define WM2200_DSP1LMIX_INPUT_4_VOLUME 0x677 -#define WM2200_DSP1RMIX_INPUT_1_SOURCE 0x678 -#define WM2200_DSP1RMIX_INPUT_1_VOLUME 0x679 -#define WM2200_DSP1RMIX_INPUT_2_SOURCE 0x67A -#define WM2200_DSP1RMIX_INPUT_2_VOLUME 0x67B -#define WM2200_DSP1RMIX_INPUT_3_SOURCE 0x67C -#define WM2200_DSP1RMIX_INPUT_3_VOLUME 0x67D -#define WM2200_DSP1RMIX_INPUT_4_SOURCE 0x67E -#define WM2200_DSP1RMIX_INPUT_4_VOLUME 0x67F -#define WM2200_DSP1AUX1MIX_INPUT_1_SOURCE 0x680 -#define WM2200_DSP1AUX2MIX_INPUT_1_SOURCE 0x681 -#define WM2200_DSP1AUX3MIX_INPUT_1_SOURCE 0x682 -#define WM2200_DSP1AUX4MIX_INPUT_1_SOURCE 0x683 -#define WM2200_DSP1AUX5MIX_INPUT_1_SOURCE 0x684 -#define WM2200_DSP1AUX6MIX_INPUT_1_SOURCE 0x685 -#define WM2200_DSP2LMIX_INPUT_1_SOURCE 0x686 -#define WM2200_DSP2LMIX_INPUT_1_VOLUME 0x687 -#define WM2200_DSP2LMIX_INPUT_2_SOURCE 0x688 -#define WM2200_DSP2LMIX_INPUT_2_VOLUME 0x689 -#define WM2200_DSP2LMIX_INPUT_3_SOURCE 0x68A -#define WM2200_DSP2LMIX_INPUT_3_VOLUME 0x68B -#define WM2200_DSP2LMIX_INPUT_4_SOURCE 0x68C -#define WM2200_DSP2LMIX_INPUT_4_VOLUME 0x68D -#define WM2200_DSP2RMIX_INPUT_1_SOURCE 0x68E -#define WM2200_DSP2RMIX_INPUT_1_VOLUME 0x68F -#define WM2200_DSP2RMIX_INPUT_2_SOURCE 0x690 -#define WM2200_DSP2RMIX_INPUT_2_VOLUME 0x691 -#define WM2200_DSP2RMIX_INPUT_3_SOURCE 0x692 -#define WM2200_DSP2RMIX_INPUT_3_VOLUME 0x693 -#define WM2200_DSP2RMIX_INPUT_4_SOURCE 0x694 -#define WM2200_DSP2RMIX_INPUT_4_VOLUME 0x695 -#define WM2200_DSP2AUX1MIX_INPUT_1_SOURCE 0x696 -#define WM2200_DSP2AUX2MIX_INPUT_1_SOURCE 0x697 -#define WM2200_DSP2AUX3MIX_INPUT_1_SOURCE 0x698 -#define WM2200_DSP2AUX4MIX_INPUT_1_SOURCE 0x699 -#define WM2200_DSP2AUX5MIX_INPUT_1_SOURCE 0x69A -#define WM2200_DSP2AUX6MIX_INPUT_1_SOURCE 0x69B -#define WM2200_GPIO_CTRL_1 0x700 -#define WM2200_GPIO_CTRL_2 0x701 -#define WM2200_GPIO_CTRL_3 0x702 -#define WM2200_GPIO_CTRL_4 0x703 -#define WM2200_ADPS1_IRQ0 0x707 -#define WM2200_ADPS1_IRQ1 0x708 -#define WM2200_MISC_PAD_CTRL_1 0x709 -#define WM2200_INTERRUPT_STATUS_1 0x800 -#define WM2200_INTERRUPT_STATUS_1_MASK 0x801 -#define WM2200_INTERRUPT_STATUS_2 0x802 -#define WM2200_INTERRUPT_RAW_STATUS_2 0x803 -#define WM2200_INTERRUPT_STATUS_2_MASK 0x804 -#define WM2200_INTERRUPT_CONTROL 0x808 -#define WM2200_EQL_1 0x900 -#define WM2200_EQL_2 0x901 -#define WM2200_EQL_3 0x902 -#define WM2200_EQL_4 0x903 -#define WM2200_EQL_5 0x904 -#define WM2200_EQL_6 0x905 -#define WM2200_EQL_7 0x906 -#define WM2200_EQL_8 0x907 -#define WM2200_EQL_9 0x908 -#define WM2200_EQL_10 0x909 -#define WM2200_EQL_11 0x90A -#define WM2200_EQL_12 0x90B -#define WM2200_EQL_13 0x90C -#define WM2200_EQL_14 0x90D -#define WM2200_EQL_15 0x90E -#define WM2200_EQL_16 0x90F -#define WM2200_EQL_17 0x910 -#define WM2200_EQL_18 0x911 -#define WM2200_EQL_19 0x912 -#define WM2200_EQL_20 0x913 -#define WM2200_EQR_1 0x916 -#define WM2200_EQR_2 0x917 -#define WM2200_EQR_3 0x918 -#define WM2200_EQR_4 0x919 -#define WM2200_EQR_5 0x91A -#define WM2200_EQR_6 0x91B -#define WM2200_EQR_7 0x91C -#define WM2200_EQR_8 0x91D -#define WM2200_EQR_9 0x91E -#define WM2200_EQR_10 0x91F -#define WM2200_EQR_11 0x920 -#define WM2200_EQR_12 0x921 -#define WM2200_EQR_13 0x922 -#define WM2200_EQR_14 0x923 -#define WM2200_EQR_15 0x924 -#define WM2200_EQR_16 0x925 -#define WM2200_EQR_17 0x926 -#define WM2200_EQR_18 0x927 -#define WM2200_EQR_19 0x928 -#define WM2200_EQR_20 0x929 -#define WM2200_HPLPF1_1 0x93E -#define WM2200_HPLPF1_2 0x93F -#define WM2200_HPLPF2_1 0x942 -#define WM2200_HPLPF2_2 0x943 -#define WM2200_DSP1_CONTROL_1 0xA00 -#define WM2200_DSP1_CONTROL_2 0xA02 -#define WM2200_DSP1_CONTROL_3 0xA03 -#define WM2200_DSP1_CONTROL_4 0xA04 -#define WM2200_DSP1_CONTROL_5 0xA06 -#define WM2200_DSP1_CONTROL_6 0xA07 -#define WM2200_DSP1_CONTROL_7 0xA08 -#define WM2200_DSP1_CONTROL_8 0xA09 -#define WM2200_DSP1_CONTROL_9 0xA0A -#define WM2200_DSP1_CONTROL_10 0xA0B -#define WM2200_DSP1_CONTROL_11 0xA0C -#define WM2200_DSP1_CONTROL_12 0xA0D -#define WM2200_DSP1_CONTROL_13 0xA0F -#define WM2200_DSP1_CONTROL_14 0xA10 -#define WM2200_DSP1_CONTROL_15 0xA11 -#define WM2200_DSP1_CONTROL_16 0xA12 -#define WM2200_DSP1_CONTROL_17 0xA13 -#define WM2200_DSP1_CONTROL_18 0xA14 -#define WM2200_DSP1_CONTROL_19 0xA16 -#define WM2200_DSP1_CONTROL_20 0xA17 -#define WM2200_DSP1_CONTROL_21 0xA18 -#define WM2200_DSP1_CONTROL_22 0xA1A -#define WM2200_DSP1_CONTROL_23 0xA1B -#define WM2200_DSP1_CONTROL_24 0xA1C -#define WM2200_DSP1_CONTROL_25 0xA1E -#define WM2200_DSP1_CONTROL_26 0xA20 -#define WM2200_DSP1_CONTROL_27 0xA21 -#define WM2200_DSP1_CONTROL_28 0xA22 -#define WM2200_DSP1_CONTROL_29 0xA23 -#define WM2200_DSP1_CONTROL_30 0xA24 -#define WM2200_DSP1_CONTROL_31 0xA26 -#define WM2200_DSP2_CONTROL_1 0xB00 -#define WM2200_DSP2_CONTROL_2 0xB02 -#define WM2200_DSP2_CONTROL_3 0xB03 -#define WM2200_DSP2_CONTROL_4 0xB04 -#define WM2200_DSP2_CONTROL_5 0xB06 -#define WM2200_DSP2_CONTROL_6 0xB07 -#define WM2200_DSP2_CONTROL_7 0xB08 -#define WM2200_DSP2_CONTROL_8 0xB09 -#define WM2200_DSP2_CONTROL_9 0xB0A -#define WM2200_DSP2_CONTROL_10 0xB0B -#define WM2200_DSP2_CONTROL_11 0xB0C -#define WM2200_DSP2_CONTROL_12 0xB0D -#define WM2200_DSP2_CONTROL_13 0xB0F -#define WM2200_DSP2_CONTROL_14 0xB10 -#define WM2200_DSP2_CONTROL_15 0xB11 -#define WM2200_DSP2_CONTROL_16 0xB12 -#define WM2200_DSP2_CONTROL_17 0xB13 -#define WM2200_DSP2_CONTROL_18 0xB14 -#define WM2200_DSP2_CONTROL_19 0xB16 -#define WM2200_DSP2_CONTROL_20 0xB17 -#define WM2200_DSP2_CONTROL_21 0xB18 -#define WM2200_DSP2_CONTROL_22 0xB1A -#define WM2200_DSP2_CONTROL_23 0xB1B -#define WM2200_DSP2_CONTROL_24 0xB1C -#define WM2200_DSP2_CONTROL_25 0xB1E -#define WM2200_DSP2_CONTROL_26 0xB20 -#define WM2200_DSP2_CONTROL_27 0xB21 -#define WM2200_DSP2_CONTROL_28 0xB22 -#define WM2200_DSP2_CONTROL_29 0xB23 -#define WM2200_DSP2_CONTROL_30 0xB24 -#define WM2200_DSP2_CONTROL_31 0xB26 -#define WM2200_ANC_CTRL1 0xD00 -#define WM2200_ANC_CTRL2 0xD01 -#define WM2200_ANC_CTRL3 0xD02 -#define WM2200_ANC_CTRL7 0xD08 -#define WM2200_ANC_CTRL8 0xD09 -#define WM2200_ANC_CTRL9 0xD0A -#define WM2200_ANC_CTRL10 0xD0B -#define WM2200_ANC_CTRL11 0xD0C -#define WM2200_ANC_CTRL12 0xD0D -#define WM2200_ANC_CTRL13 0xD0E -#define WM2200_ANC_CTRL14 0xD0F -#define WM2200_ANC_CTRL15 0xD10 -#define WM2200_ANC_CTRL16 0xD11 -#define WM2200_ANC_CTRL17 0xD12 -#define WM2200_ANC_CTRL18 0xD15 -#define WM2200_ANC_CTRL19 0xD16 -#define WM2200_ANC_CTRL20 0xD17 -#define WM2200_ANC_CTRL21 0xD18 -#define WM2200_ANC_CTRL22 0xD19 -#define WM2200_ANC_CTRL23 0xD1A -#define WM2200_ANC_CTRL24 0xD1B -#define WM2200_ANC_CTRL25 0xD1C -#define WM2200_ANC_CTRL26 0xD1D -#define WM2200_ANC_CTRL27 0xD1E -#define WM2200_ANC_CTRL28 0xD1F -#define WM2200_ANC_CTRL29 0xD20 -#define WM2200_ANC_CTRL30 0xD21 -#define WM2200_ANC_CTRL31 0xD23 -#define WM2200_ANC_CTRL32 0xD24 -#define WM2200_ANC_CTRL33 0xD25 -#define WM2200_ANC_CTRL34 0xD27 -#define WM2200_ANC_CTRL35 0xD28 -#define WM2200_ANC_CTRL36 0xD29 -#define WM2200_ANC_CTRL37 0xD2A -#define WM2200_ANC_CTRL38 0xD2B -#define WM2200_ANC_CTRL39 0xD2C -#define WM2200_ANC_CTRL40 0xD2D -#define WM2200_ANC_CTRL41 0xD2E -#define WM2200_ANC_CTRL42 0xD2F -#define WM2200_ANC_CTRL43 0xD30 -#define WM2200_ANC_CTRL44 0xD31 -#define WM2200_ANC_CTRL45 0xD32 -#define WM2200_ANC_CTRL46 0xD33 -#define WM2200_ANC_CTRL47 0xD34 -#define WM2200_ANC_CTRL48 0xD35 -#define WM2200_ANC_CTRL49 0xD36 -#define WM2200_ANC_CTRL50 0xD37 -#define WM2200_ANC_CTRL51 0xD38 -#define WM2200_ANC_CTRL52 0xD39 -#define WM2200_ANC_CTRL53 0xD3A -#define WM2200_ANC_CTRL54 0xD3B -#define WM2200_ANC_CTRL55 0xD3C -#define WM2200_ANC_CTRL56 0xD3D -#define WM2200_ANC_CTRL57 0xD3E -#define WM2200_ANC_CTRL58 0xD3F -#define WM2200_ANC_CTRL59 0xD40 -#define WM2200_ANC_CTRL60 0xD41 -#define WM2200_ANC_CTRL61 0xD42 -#define WM2200_ANC_CTRL62 0xD43 -#define WM2200_ANC_CTRL63 0xD44 -#define WM2200_ANC_CTRL64 0xD45 -#define WM2200_ANC_CTRL65 0xD46 -#define WM2200_ANC_CTRL66 0xD47 -#define WM2200_ANC_CTRL67 0xD48 -#define WM2200_ANC_CTRL68 0xD49 -#define WM2200_ANC_CTRL69 0xD4A -#define WM2200_ANC_CTRL70 0xD4B -#define WM2200_ANC_CTRL71 0xD4C -#define WM2200_ANC_CTRL72 0xD4D -#define WM2200_ANC_CTRL73 0xD4E -#define WM2200_ANC_CTRL74 0xD4F -#define WM2200_ANC_CTRL75 0xD50 -#define WM2200_ANC_CTRL76 0xD51 -#define WM2200_ANC_CTRL77 0xD52 -#define WM2200_ANC_CTRL78 0xD53 -#define WM2200_ANC_CTRL79 0xD54 -#define WM2200_ANC_CTRL80 0xD55 -#define WM2200_ANC_CTRL81 0xD56 -#define WM2200_ANC_CTRL82 0xD57 -#define WM2200_ANC_CTRL83 0xD58 -#define WM2200_ANC_CTRL84 0xD5B -#define WM2200_ANC_CTRL85 0xD5C -#define WM2200_ANC_CTRL86 0xD5F -#define WM2200_ANC_CTRL87 0xD60 -#define WM2200_ANC_CTRL88 0xD61 -#define WM2200_ANC_CTRL89 0xD62 -#define WM2200_ANC_CTRL90 0xD63 -#define WM2200_ANC_CTRL91 0xD64 -#define WM2200_ANC_CTRL92 0xD65 -#define WM2200_ANC_CTRL93 0xD66 -#define WM2200_ANC_CTRL94 0xD67 -#define WM2200_ANC_CTRL95 0xD68 -#define WM2200_ANC_CTRL96 0xD69 -#define WM2200_DSP1_DM_0 0x3000 -#define WM2200_DSP1_DM_1 0x3001 -#define WM2200_DSP1_DM_2 0x3002 -#define WM2200_DSP1_DM_3 0x3003 -#define WM2200_DSP1_DM_2044 0x37FC -#define WM2200_DSP1_DM_2045 0x37FD -#define WM2200_DSP1_DM_2046 0x37FE -#define WM2200_DSP1_DM_2047 0x37FF -#define WM2200_DSP1_PM_0 0x3800 -#define WM2200_DSP1_PM_1 0x3801 -#define WM2200_DSP1_PM_2 0x3802 -#define WM2200_DSP1_PM_3 0x3803 -#define WM2200_DSP1_PM_4 0x3804 -#define WM2200_DSP1_PM_5 0x3805 -#define WM2200_DSP1_PM_762 0x3AFA -#define WM2200_DSP1_PM_763 0x3AFB -#define WM2200_DSP1_PM_764 0x3AFC -#define WM2200_DSP1_PM_765 0x3AFD -#define WM2200_DSP1_PM_766 0x3AFE -#define WM2200_DSP1_PM_767 0x3AFF -#define WM2200_DSP1_ZM_0 0x3C00 -#define WM2200_DSP1_ZM_1 0x3C01 -#define WM2200_DSP1_ZM_2 0x3C02 -#define WM2200_DSP1_ZM_3 0x3C03 -#define WM2200_DSP1_ZM_1020 0x3FFC -#define WM2200_DSP1_ZM_1021 0x3FFD -#define WM2200_DSP1_ZM_1022 0x3FFE -#define WM2200_DSP1_ZM_1023 0x3FFF -#define WM2200_DSP2_DM_0 0x4000 -#define WM2200_DSP2_DM_1 0x4001 -#define WM2200_DSP2_DM_2 0x4002 -#define WM2200_DSP2_DM_3 0x4003 -#define WM2200_DSP2_DM_2044 0x47FC -#define WM2200_DSP2_DM_2045 0x47FD -#define WM2200_DSP2_DM_2046 0x47FE -#define WM2200_DSP2_DM_2047 0x47FF -#define WM2200_DSP2_PM_0 0x4800 -#define WM2200_DSP2_PM_1 0x4801 -#define WM2200_DSP2_PM_2 0x4802 -#define WM2200_DSP2_PM_3 0x4803 -#define WM2200_DSP2_PM_4 0x4804 -#define WM2200_DSP2_PM_5 0x4805 -#define WM2200_DSP2_PM_762 0x4AFA -#define WM2200_DSP2_PM_763 0x4AFB -#define WM2200_DSP2_PM_764 0x4AFC -#define WM2200_DSP2_PM_765 0x4AFD -#define WM2200_DSP2_PM_766 0x4AFE -#define WM2200_DSP2_PM_767 0x4AFF -#define WM2200_DSP2_ZM_0 0x4C00 -#define WM2200_DSP2_ZM_1 0x4C01 -#define WM2200_DSP2_ZM_2 0x4C02 -#define WM2200_DSP2_ZM_3 0x4C03 -#define WM2200_DSP2_ZM_1020 0x4FFC -#define WM2200_DSP2_ZM_1021 0x4FFD -#define WM2200_DSP2_ZM_1022 0x4FFE -#define WM2200_DSP2_ZM_1023 0x4FFF - -#define WM2200_REGISTER_COUNT 494 -#define WM2200_MAX_REGISTER 0x4FFF - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - software reset - */ -#define WM2200_SW_RESET_CHIP_ID1_MASK 0xFFFF /* SW_RESET_CHIP_ID1 - [15:0] */ -#define WM2200_SW_RESET_CHIP_ID1_SHIFT 0 /* SW_RESET_CHIP_ID1 - [15:0] */ -#define WM2200_SW_RESET_CHIP_ID1_WIDTH 16 /* SW_RESET_CHIP_ID1 - [15:0] */ - -/* - * R1 (0x01) - Device Revision - */ -#define WM2200_DEVICE_REVISION_MASK 0x000F /* DEVICE_REVISION - [3:0] */ -#define WM2200_DEVICE_REVISION_SHIFT 0 /* DEVICE_REVISION - [3:0] */ -#define WM2200_DEVICE_REVISION_WIDTH 4 /* DEVICE_REVISION - [3:0] */ - -/* - * R11 (0x0B) - Tone Generator 1 - */ -#define WM2200_TONE_ENA 0x0001 /* TONE_ENA */ -#define WM2200_TONE_ENA_MASK 0x0001 /* TONE_ENA */ -#define WM2200_TONE_ENA_SHIFT 0 /* TONE_ENA */ -#define WM2200_TONE_ENA_WIDTH 1 /* TONE_ENA */ - -/* - * R258 (0x102) - Clocking 3 - */ -#define WM2200_SYSCLK_FREQ_MASK 0x0700 /* SYSCLK_FREQ - [10:8] */ -#define WM2200_SYSCLK_FREQ_SHIFT 8 /* SYSCLK_FREQ - [10:8] */ -#define WM2200_SYSCLK_FREQ_WIDTH 3 /* SYSCLK_FREQ - [10:8] */ -#define WM2200_SYSCLK_ENA 0x0040 /* SYSCLK_ENA */ -#define WM2200_SYSCLK_ENA_MASK 0x0040 /* SYSCLK_ENA */ -#define WM2200_SYSCLK_ENA_SHIFT 6 /* SYSCLK_ENA */ -#define WM2200_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */ -#define WM2200_SYSCLK_SRC_MASK 0x000F /* SYSCLK_SRC - [3:0] */ -#define WM2200_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC - [3:0] */ -#define WM2200_SYSCLK_SRC_WIDTH 4 /* SYSCLK_SRC - [3:0] */ - -/* - * R259 (0x103) - Clocking 4 - */ -#define WM2200_SAMPLE_RATE_1_MASK 0x001F /* SAMPLE_RATE_1 - [4:0] */ -#define WM2200_SAMPLE_RATE_1_SHIFT 0 /* SAMPLE_RATE_1 - [4:0] */ -#define WM2200_SAMPLE_RATE_1_WIDTH 5 /* SAMPLE_RATE_1 - [4:0] */ - -/* - * R273 (0x111) - FLL Control 1 - */ -#define WM2200_FLL_ENA 0x0001 /* FLL_ENA */ -#define WM2200_FLL_ENA_MASK 0x0001 /* FLL_ENA */ -#define WM2200_FLL_ENA_SHIFT 0 /* FLL_ENA */ -#define WM2200_FLL_ENA_WIDTH 1 /* FLL_ENA */ - -/* - * R274 (0x112) - FLL Control 2 - */ -#define WM2200_FLL_OUTDIV_MASK 0x3F00 /* FLL_OUTDIV - [13:8] */ -#define WM2200_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [13:8] */ -#define WM2200_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [13:8] */ -#define WM2200_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ -#define WM2200_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ -#define WM2200_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ - -/* - * R275 (0x113) - FLL Control 3 - */ -#define WM2200_FLL_FRACN_ENA 0x0001 /* FLL_FRACN_ENA */ -#define WM2200_FLL_FRACN_ENA_MASK 0x0001 /* FLL_FRACN_ENA */ -#define WM2200_FLL_FRACN_ENA_SHIFT 0 /* FLL_FRACN_ENA */ -#define WM2200_FLL_FRACN_ENA_WIDTH 1 /* FLL_FRACN_ENA */ - -/* - * R276 (0x114) - FLL Control 4 - */ -#define WM2200_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */ -#define WM2200_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */ -#define WM2200_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */ - -/* - * R278 (0x116) - FLL Control 6 - */ -#define WM2200_FLL_N_MASK 0x03FF /* FLL_N - [9:0] */ -#define WM2200_FLL_N_SHIFT 0 /* FLL_N - [9:0] */ -#define WM2200_FLL_N_WIDTH 10 /* FLL_N - [9:0] */ - -/* - * R279 (0x117) - FLL Control 7 - */ -#define WM2200_FLL_CLK_REF_DIV_MASK 0x0030 /* FLL_CLK_REF_DIV - [5:4] */ -#define WM2200_FLL_CLK_REF_DIV_SHIFT 4 /* FLL_CLK_REF_DIV - [5:4] */ -#define WM2200_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [5:4] */ -#define WM2200_FLL_CLK_REF_SRC_MASK 0x0003 /* FLL_CLK_REF_SRC - [1:0] */ -#define WM2200_FLL_CLK_REF_SRC_SHIFT 0 /* FLL_CLK_REF_SRC - [1:0] */ -#define WM2200_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */ - -/* - * R281 (0x119) - FLL EFS 1 - */ -#define WM2200_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */ -#define WM2200_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */ -#define WM2200_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */ - -/* - * R282 (0x11A) - FLL EFS 2 - */ -#define WM2200_FLL_EFS_ENA 0x0001 /* FLL_EFS_ENA */ -#define WM2200_FLL_EFS_ENA_MASK 0x0001 /* FLL_EFS_ENA */ -#define WM2200_FLL_EFS_ENA_SHIFT 0 /* FLL_EFS_ENA */ -#define WM2200_FLL_EFS_ENA_WIDTH 1 /* FLL_EFS_ENA */ - -/* - * R512 (0x200) - Mic Charge Pump 1 - */ -#define WM2200_CPMIC_BYPASS_MODE 0x0020 /* CPMIC_BYPASS_MODE */ -#define WM2200_CPMIC_BYPASS_MODE_MASK 0x0020 /* CPMIC_BYPASS_MODE */ -#define WM2200_CPMIC_BYPASS_MODE_SHIFT 5 /* CPMIC_BYPASS_MODE */ -#define WM2200_CPMIC_BYPASS_MODE_WIDTH 1 /* CPMIC_BYPASS_MODE */ -#define WM2200_CPMIC_ENA 0x0001 /* CPMIC_ENA */ -#define WM2200_CPMIC_ENA_MASK 0x0001 /* CPMIC_ENA */ -#define WM2200_CPMIC_ENA_SHIFT 0 /* CPMIC_ENA */ -#define WM2200_CPMIC_ENA_WIDTH 1 /* CPMIC_ENA */ - -/* - * R513 (0x201) - Mic Charge Pump 2 - */ -#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_MASK 0xF800 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */ -#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_SHIFT 11 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */ -#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_WIDTH 5 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */ - -/* - * R514 (0x202) - DM Charge Pump 1 - */ -#define WM2200_CPDM_ENA 0x0001 /* CPDM_ENA */ -#define WM2200_CPDM_ENA_MASK 0x0001 /* CPDM_ENA */ -#define WM2200_CPDM_ENA_SHIFT 0 /* CPDM_ENA */ -#define WM2200_CPDM_ENA_WIDTH 1 /* CPDM_ENA */ - -/* - * R524 (0x20C) - Mic Bias Ctrl 1 - */ -#define WM2200_MICB1_DISCH 0x0040 /* MICB1_DISCH */ -#define WM2200_MICB1_DISCH_MASK 0x0040 /* MICB1_DISCH */ -#define WM2200_MICB1_DISCH_SHIFT 6 /* MICB1_DISCH */ -#define WM2200_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */ -#define WM2200_MICB1_RATE 0x0020 /* MICB1_RATE */ -#define WM2200_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */ -#define WM2200_MICB1_RATE_SHIFT 5 /* MICB1_RATE */ -#define WM2200_MICB1_RATE_WIDTH 1 /* MICB1_RATE */ -#define WM2200_MICB1_LVL_MASK 0x001C /* MICB1_LVL - [4:2] */ -#define WM2200_MICB1_LVL_SHIFT 2 /* MICB1_LVL - [4:2] */ -#define WM2200_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [4:2] */ -#define WM2200_MICB1_MODE 0x0002 /* MICB1_MODE */ -#define WM2200_MICB1_MODE_MASK 0x0002 /* MICB1_MODE */ -#define WM2200_MICB1_MODE_SHIFT 1 /* MICB1_MODE */ -#define WM2200_MICB1_MODE_WIDTH 1 /* MICB1_MODE */ -#define WM2200_MICB1_ENA 0x0001 /* MICB1_ENA */ -#define WM2200_MICB1_ENA_MASK 0x0001 /* MICB1_ENA */ -#define WM2200_MICB1_ENA_SHIFT 0 /* MICB1_ENA */ -#define WM2200_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ - -/* - * R525 (0x20D) - Mic Bias Ctrl 2 - */ -#define WM2200_MICB2_DISCH 0x0040 /* MICB2_DISCH */ -#define WM2200_MICB2_DISCH_MASK 0x0040 /* MICB2_DISCH */ -#define WM2200_MICB2_DISCH_SHIFT 6 /* MICB2_DISCH */ -#define WM2200_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ -#define WM2200_MICB2_RATE 0x0020 /* MICB2_RATE */ -#define WM2200_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */ -#define WM2200_MICB2_RATE_SHIFT 5 /* MICB2_RATE */ -#define WM2200_MICB2_RATE_WIDTH 1 /* MICB2_RATE */ -#define WM2200_MICB2_LVL_MASK 0x001C /* MICB2_LVL - [4:2] */ -#define WM2200_MICB2_LVL_SHIFT 2 /* MICB2_LVL - [4:2] */ -#define WM2200_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [4:2] */ -#define WM2200_MICB2_MODE 0x0002 /* MICB2_MODE */ -#define WM2200_MICB2_MODE_MASK 0x0002 /* MICB2_MODE */ -#define WM2200_MICB2_MODE_SHIFT 1 /* MICB2_MODE */ -#define WM2200_MICB2_MODE_WIDTH 1 /* MICB2_MODE */ -#define WM2200_MICB2_ENA 0x0001 /* MICB2_ENA */ -#define WM2200_MICB2_ENA_MASK 0x0001 /* MICB2_ENA */ -#define WM2200_MICB2_ENA_SHIFT 0 /* MICB2_ENA */ -#define WM2200_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ - -/* - * R527 (0x20F) - Ear Piece Ctrl 1 - */ -#define WM2200_EPD_LP_ENA 0x4000 /* EPD_LP_ENA */ -#define WM2200_EPD_LP_ENA_MASK 0x4000 /* EPD_LP_ENA */ -#define WM2200_EPD_LP_ENA_SHIFT 14 /* EPD_LP_ENA */ -#define WM2200_EPD_LP_ENA_WIDTH 1 /* EPD_LP_ENA */ -#define WM2200_EPD_OUTP_LP_ENA 0x2000 /* EPD_OUTP_LP_ENA */ -#define WM2200_EPD_OUTP_LP_ENA_MASK 0x2000 /* EPD_OUTP_LP_ENA */ -#define WM2200_EPD_OUTP_LP_ENA_SHIFT 13 /* EPD_OUTP_LP_ENA */ -#define WM2200_EPD_OUTP_LP_ENA_WIDTH 1 /* EPD_OUTP_LP_ENA */ -#define WM2200_EPD_RMV_SHRT_LP 0x1000 /* EPD_RMV_SHRT_LP */ -#define WM2200_EPD_RMV_SHRT_LP_MASK 0x1000 /* EPD_RMV_SHRT_LP */ -#define WM2200_EPD_RMV_SHRT_LP_SHIFT 12 /* EPD_RMV_SHRT_LP */ -#define WM2200_EPD_RMV_SHRT_LP_WIDTH 1 /* EPD_RMV_SHRT_LP */ -#define WM2200_EPD_LN_ENA 0x0800 /* EPD_LN_ENA */ -#define WM2200_EPD_LN_ENA_MASK 0x0800 /* EPD_LN_ENA */ -#define WM2200_EPD_LN_ENA_SHIFT 11 /* EPD_LN_ENA */ -#define WM2200_EPD_LN_ENA_WIDTH 1 /* EPD_LN_ENA */ -#define WM2200_EPD_OUTP_LN_ENA 0x0400 /* EPD_OUTP_LN_ENA */ -#define WM2200_EPD_OUTP_LN_ENA_MASK 0x0400 /* EPD_OUTP_LN_ENA */ -#define WM2200_EPD_OUTP_LN_ENA_SHIFT 10 /* EPD_OUTP_LN_ENA */ -#define WM2200_EPD_OUTP_LN_ENA_WIDTH 1 /* EPD_OUTP_LN_ENA */ -#define WM2200_EPD_RMV_SHRT_LN 0x0200 /* EPD_RMV_SHRT_LN */ -#define WM2200_EPD_RMV_SHRT_LN_MASK 0x0200 /* EPD_RMV_SHRT_LN */ -#define WM2200_EPD_RMV_SHRT_LN_SHIFT 9 /* EPD_RMV_SHRT_LN */ -#define WM2200_EPD_RMV_SHRT_LN_WIDTH 1 /* EPD_RMV_SHRT_LN */ - -/* - * R528 (0x210) - Ear Piece Ctrl 2 - */ -#define WM2200_EPD_RP_ENA 0x4000 /* EPD_RP_ENA */ -#define WM2200_EPD_RP_ENA_MASK 0x4000 /* EPD_RP_ENA */ -#define WM2200_EPD_RP_ENA_SHIFT 14 /* EPD_RP_ENA */ -#define WM2200_EPD_RP_ENA_WIDTH 1 /* EPD_RP_ENA */ -#define WM2200_EPD_OUTP_RP_ENA 0x2000 /* EPD_OUTP_RP_ENA */ -#define WM2200_EPD_OUTP_RP_ENA_MASK 0x2000 /* EPD_OUTP_RP_ENA */ -#define WM2200_EPD_OUTP_RP_ENA_SHIFT 13 /* EPD_OUTP_RP_ENA */ -#define WM2200_EPD_OUTP_RP_ENA_WIDTH 1 /* EPD_OUTP_RP_ENA */ -#define WM2200_EPD_RMV_SHRT_RP 0x1000 /* EPD_RMV_SHRT_RP */ -#define WM2200_EPD_RMV_SHRT_RP_MASK 0x1000 /* EPD_RMV_SHRT_RP */ -#define WM2200_EPD_RMV_SHRT_RP_SHIFT 12 /* EPD_RMV_SHRT_RP */ -#define WM2200_EPD_RMV_SHRT_RP_WIDTH 1 /* EPD_RMV_SHRT_RP */ -#define WM2200_EPD_RN_ENA 0x0800 /* EPD_RN_ENA */ -#define WM2200_EPD_RN_ENA_MASK 0x0800 /* EPD_RN_ENA */ -#define WM2200_EPD_RN_ENA_SHIFT 11 /* EPD_RN_ENA */ -#define WM2200_EPD_RN_ENA_WIDTH 1 /* EPD_RN_ENA */ -#define WM2200_EPD_OUTP_RN_ENA 0x0400 /* EPD_OUTP_RN_ENA */ -#define WM2200_EPD_OUTP_RN_ENA_MASK 0x0400 /* EPD_OUTP_RN_ENA */ -#define WM2200_EPD_OUTP_RN_ENA_SHIFT 10 /* EPD_OUTP_RN_ENA */ -#define WM2200_EPD_OUTP_RN_ENA_WIDTH 1 /* EPD_OUTP_RN_ENA */ -#define WM2200_EPD_RMV_SHRT_RN 0x0200 /* EPD_RMV_SHRT_RN */ -#define WM2200_EPD_RMV_SHRT_RN_MASK 0x0200 /* EPD_RMV_SHRT_RN */ -#define WM2200_EPD_RMV_SHRT_RN_SHIFT 9 /* EPD_RMV_SHRT_RN */ -#define WM2200_EPD_RMV_SHRT_RN_WIDTH 1 /* EPD_RMV_SHRT_RN */ - -/* - * R769 (0x301) - Input Enables - */ -#define WM2200_IN3L_ENA 0x0020 /* IN3L_ENA */ -#define WM2200_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */ -#define WM2200_IN3L_ENA_SHIFT 5 /* IN3L_ENA */ -#define WM2200_IN3L_ENA_WIDTH 1 /* IN3L_ENA */ -#define WM2200_IN3R_ENA 0x0010 /* IN3R_ENA */ -#define WM2200_IN3R_ENA_MASK 0x0010 /* IN3R_ENA */ -#define WM2200_IN3R_ENA_SHIFT 4 /* IN3R_ENA */ -#define WM2200_IN3R_ENA_WIDTH 1 /* IN3R_ENA */ -#define WM2200_IN2L_ENA 0x0008 /* IN2L_ENA */ -#define WM2200_IN2L_ENA_MASK 0x0008 /* IN2L_ENA */ -#define WM2200_IN2L_ENA_SHIFT 3 /* IN2L_ENA */ -#define WM2200_IN2L_ENA_WIDTH 1 /* IN2L_ENA */ -#define WM2200_IN2R_ENA 0x0004 /* IN2R_ENA */ -#define WM2200_IN2R_ENA_MASK 0x0004 /* IN2R_ENA */ -#define WM2200_IN2R_ENA_SHIFT 2 /* IN2R_ENA */ -#define WM2200_IN2R_ENA_WIDTH 1 /* IN2R_ENA */ -#define WM2200_IN1L_ENA 0x0002 /* IN1L_ENA */ -#define WM2200_IN1L_ENA_MASK 0x0002 /* IN1L_ENA */ -#define WM2200_IN1L_ENA_SHIFT 1 /* IN1L_ENA */ -#define WM2200_IN1L_ENA_WIDTH 1 /* IN1L_ENA */ -#define WM2200_IN1R_ENA 0x0001 /* IN1R_ENA */ -#define WM2200_IN1R_ENA_MASK 0x0001 /* IN1R_ENA */ -#define WM2200_IN1R_ENA_SHIFT 0 /* IN1R_ENA */ -#define WM2200_IN1R_ENA_WIDTH 1 /* IN1R_ENA */ - -/* - * R770 (0x302) - IN1L Control - */ -#define WM2200_IN1_OSR 0x2000 /* IN1_OSR */ -#define WM2200_IN1_OSR_MASK 0x2000 /* IN1_OSR */ -#define WM2200_IN1_OSR_SHIFT 13 /* IN1_OSR */ -#define WM2200_IN1_OSR_WIDTH 1 /* IN1_OSR */ -#define WM2200_IN1_DMIC_SUP_MASK 0x1800 /* IN1_DMIC_SUP - [12:11] */ -#define WM2200_IN1_DMIC_SUP_SHIFT 11 /* IN1_DMIC_SUP - [12:11] */ -#define WM2200_IN1_DMIC_SUP_WIDTH 2 /* IN1_DMIC_SUP - [12:11] */ -#define WM2200_IN1_MODE_MASK 0x0600 /* IN1_MODE - [10:9] */ -#define WM2200_IN1_MODE_SHIFT 9 /* IN1_MODE - [10:9] */ -#define WM2200_IN1_MODE_WIDTH 2 /* IN1_MODE - [10:9] */ -#define WM2200_IN1L_PGA_VOL_MASK 0x00FE /* IN1L_PGA_VOL - [7:1] */ -#define WM2200_IN1L_PGA_VOL_SHIFT 1 /* IN1L_PGA_VOL - [7:1] */ -#define WM2200_IN1L_PGA_VOL_WIDTH 7 /* IN1L_PGA_VOL - [7:1] */ - -/* - * R771 (0x303) - IN1R Control - */ -#define WM2200_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */ -#define WM2200_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */ -#define WM2200_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */ - -/* - * R772 (0x304) - IN2L Control - */ -#define WM2200_IN2_OSR 0x2000 /* IN2_OSR */ -#define WM2200_IN2_OSR_MASK 0x2000 /* IN2_OSR */ -#define WM2200_IN2_OSR_SHIFT 13 /* IN2_OSR */ -#define WM2200_IN2_OSR_WIDTH 1 /* IN2_OSR */ -#define WM2200_IN2_DMIC_SUP_MASK 0x1800 /* IN2_DMIC_SUP - [12:11] */ -#define WM2200_IN2_DMIC_SUP_SHIFT 11 /* IN2_DMIC_SUP - [12:11] */ -#define WM2200_IN2_DMIC_SUP_WIDTH 2 /* IN2_DMIC_SUP - [12:11] */ -#define WM2200_IN2_MODE_MASK 0x0600 /* IN2_MODE - [10:9] */ -#define WM2200_IN2_MODE_SHIFT 9 /* IN2_MODE - [10:9] */ -#define WM2200_IN2_MODE_WIDTH 2 /* IN2_MODE - [10:9] */ -#define WM2200_IN2L_PGA_VOL_MASK 0x00FE /* IN2L_PGA_VOL - [7:1] */ -#define WM2200_IN2L_PGA_VOL_SHIFT 1 /* IN2L_PGA_VOL - [7:1] */ -#define WM2200_IN2L_PGA_VOL_WIDTH 7 /* IN2L_PGA_VOL - [7:1] */ - -/* - * R773 (0x305) - IN2R Control - */ -#define WM2200_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */ -#define WM2200_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */ -#define WM2200_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */ - -/* - * R774 (0x306) - IN3L Control - */ -#define WM2200_IN3_OSR 0x2000 /* IN3_OSR */ -#define WM2200_IN3_OSR_MASK 0x2000 /* IN3_OSR */ -#define WM2200_IN3_OSR_SHIFT 13 /* IN3_OSR */ -#define WM2200_IN3_OSR_WIDTH 1 /* IN3_OSR */ -#define WM2200_IN3_DMIC_SUP_MASK 0x1800 /* IN3_DMIC_SUP - [12:11] */ -#define WM2200_IN3_DMIC_SUP_SHIFT 11 /* IN3_DMIC_SUP - [12:11] */ -#define WM2200_IN3_DMIC_SUP_WIDTH 2 /* IN3_DMIC_SUP - [12:11] */ -#define WM2200_IN3_MODE_MASK 0x0600 /* IN3_MODE - [10:9] */ -#define WM2200_IN3_MODE_SHIFT 9 /* IN3_MODE - [10:9] */ -#define WM2200_IN3_MODE_WIDTH 2 /* IN3_MODE - [10:9] */ -#define WM2200_IN3L_PGA_VOL_MASK 0x00FE /* IN3L_PGA_VOL - [7:1] */ -#define WM2200_IN3L_PGA_VOL_SHIFT 1 /* IN3L_PGA_VOL - [7:1] */ -#define WM2200_IN3L_PGA_VOL_WIDTH 7 /* IN3L_PGA_VOL - [7:1] */ - -/* - * R775 (0x307) - IN3R Control - */ -#define WM2200_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */ -#define WM2200_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */ -#define WM2200_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */ - -/* - * R778 (0x30A) - RXANC_SRC - */ -#define WM2200_IN_RXANC_SEL_MASK 0x0007 /* IN_RXANC_SEL - [2:0] */ -#define WM2200_IN_RXANC_SEL_SHIFT 0 /* IN_RXANC_SEL - [2:0] */ -#define WM2200_IN_RXANC_SEL_WIDTH 3 /* IN_RXANC_SEL - [2:0] */ - -/* - * R779 (0x30B) - Input Volume Ramp - */ -#define WM2200_IN_VD_RAMP_MASK 0x0070 /* IN_VD_RAMP - [6:4] */ -#define WM2200_IN_VD_RAMP_SHIFT 4 /* IN_VD_RAMP - [6:4] */ -#define WM2200_IN_VD_RAMP_WIDTH 3 /* IN_VD_RAMP - [6:4] */ -#define WM2200_IN_VI_RAMP_MASK 0x0007 /* IN_VI_RAMP - [2:0] */ -#define WM2200_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */ -#define WM2200_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */ - -/* - * R780 (0x30C) - ADC Digital Volume 1L - */ -#define WM2200_IN_VU 0x0200 /* IN_VU */ -#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM2200_IN_VU_SHIFT 9 /* IN_VU */ -#define WM2200_IN_VU_WIDTH 1 /* IN_VU */ -#define WM2200_IN1L_MUTE 0x0100 /* IN1L_MUTE */ -#define WM2200_IN1L_MUTE_MASK 0x0100 /* IN1L_MUTE */ -#define WM2200_IN1L_MUTE_SHIFT 8 /* IN1L_MUTE */ -#define WM2200_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */ -#define WM2200_IN1L_DIG_VOL_MASK 0x00FF /* IN1L_DIG_VOL - [7:0] */ -#define WM2200_IN1L_DIG_VOL_SHIFT 0 /* IN1L_DIG_VOL - [7:0] */ -#define WM2200_IN1L_DIG_VOL_WIDTH 8 /* IN1L_DIG_VOL - [7:0] */ - -/* - * R781 (0x30D) - ADC Digital Volume 1R - */ -#define WM2200_IN_VU 0x0200 /* IN_VU */ -#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM2200_IN_VU_SHIFT 9 /* IN_VU */ -#define WM2200_IN_VU_WIDTH 1 /* IN_VU */ -#define WM2200_IN1R_MUTE 0x0100 /* IN1R_MUTE */ -#define WM2200_IN1R_MUTE_MASK 0x0100 /* IN1R_MUTE */ -#define WM2200_IN1R_MUTE_SHIFT 8 /* IN1R_MUTE */ -#define WM2200_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */ -#define WM2200_IN1R_DIG_VOL_MASK 0x00FF /* IN1R_DIG_VOL - [7:0] */ -#define WM2200_IN1R_DIG_VOL_SHIFT 0 /* IN1R_DIG_VOL - [7:0] */ -#define WM2200_IN1R_DIG_VOL_WIDTH 8 /* IN1R_DIG_VOL - [7:0] */ - -/* - * R782 (0x30E) - ADC Digital Volume 2L - */ -#define WM2200_IN_VU 0x0200 /* IN_VU */ -#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM2200_IN_VU_SHIFT 9 /* IN_VU */ -#define WM2200_IN_VU_WIDTH 1 /* IN_VU */ -#define WM2200_IN2L_MUTE 0x0100 /* IN2L_MUTE */ -#define WM2200_IN2L_MUTE_MASK 0x0100 /* IN2L_MUTE */ -#define WM2200_IN2L_MUTE_SHIFT 8 /* IN2L_MUTE */ -#define WM2200_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */ -#define WM2200_IN2L_DIG_VOL_MASK 0x00FF /* IN2L_DIG_VOL - [7:0] */ -#define WM2200_IN2L_DIG_VOL_SHIFT 0 /* IN2L_DIG_VOL - [7:0] */ -#define WM2200_IN2L_DIG_VOL_WIDTH 8 /* IN2L_DIG_VOL - [7:0] */ - -/* - * R783 (0x30F) - ADC Digital Volume 2R - */ -#define WM2200_IN_VU 0x0200 /* IN_VU */ -#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM2200_IN_VU_SHIFT 9 /* IN_VU */ -#define WM2200_IN_VU_WIDTH 1 /* IN_VU */ -#define WM2200_IN2R_MUTE 0x0100 /* IN2R_MUTE */ -#define WM2200_IN2R_MUTE_MASK 0x0100 /* IN2R_MUTE */ -#define WM2200_IN2R_MUTE_SHIFT 8 /* IN2R_MUTE */ -#define WM2200_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */ -#define WM2200_IN2R_DIG_VOL_MASK 0x00FF /* IN2R_DIG_VOL - [7:0] */ -#define WM2200_IN2R_DIG_VOL_SHIFT 0 /* IN2R_DIG_VOL - [7:0] */ -#define WM2200_IN2R_DIG_VOL_WIDTH 8 /* IN2R_DIG_VOL - [7:0] */ - -/* - * R784 (0x310) - ADC Digital Volume 3L - */ -#define WM2200_IN_VU 0x0200 /* IN_VU */ -#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM2200_IN_VU_SHIFT 9 /* IN_VU */ -#define WM2200_IN_VU_WIDTH 1 /* IN_VU */ -#define WM2200_IN3L_MUTE 0x0100 /* IN3L_MUTE */ -#define WM2200_IN3L_MUTE_MASK 0x0100 /* IN3L_MUTE */ -#define WM2200_IN3L_MUTE_SHIFT 8 /* IN3L_MUTE */ -#define WM2200_IN3L_MUTE_WIDTH 1 /* IN3L_MUTE */ -#define WM2200_IN3L_DIG_VOL_MASK 0x00FF /* IN3L_DIG_VOL - [7:0] */ -#define WM2200_IN3L_DIG_VOL_SHIFT 0 /* IN3L_DIG_VOL - [7:0] */ -#define WM2200_IN3L_DIG_VOL_WIDTH 8 /* IN3L_DIG_VOL - [7:0] */ - -/* - * R785 (0x311) - ADC Digital Volume 3R - */ -#define WM2200_IN_VU 0x0200 /* IN_VU */ -#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM2200_IN_VU_SHIFT 9 /* IN_VU */ -#define WM2200_IN_VU_WIDTH 1 /* IN_VU */ -#define WM2200_IN3R_MUTE 0x0100 /* IN3R_MUTE */ -#define WM2200_IN3R_MUTE_MASK 0x0100 /* IN3R_MUTE */ -#define WM2200_IN3R_MUTE_SHIFT 8 /* IN3R_MUTE */ -#define WM2200_IN3R_MUTE_WIDTH 1 /* IN3R_MUTE */ -#define WM2200_IN3R_DIG_VOL_MASK 0x00FF /* IN3R_DIG_VOL - [7:0] */ -#define WM2200_IN3R_DIG_VOL_SHIFT 0 /* IN3R_DIG_VOL - [7:0] */ -#define WM2200_IN3R_DIG_VOL_WIDTH 8 /* IN3R_DIG_VOL - [7:0] */ - -/* - * R1024 (0x400) - Output Enables - */ -#define WM2200_OUT2L_ENA 0x0008 /* OUT2L_ENA */ -#define WM2200_OUT2L_ENA_MASK 0x0008 /* OUT2L_ENA */ -#define WM2200_OUT2L_ENA_SHIFT 3 /* OUT2L_ENA */ -#define WM2200_OUT2L_ENA_WIDTH 1 /* OUT2L_ENA */ -#define WM2200_OUT2R_ENA 0x0004 /* OUT2R_ENA */ -#define WM2200_OUT2R_ENA_MASK 0x0004 /* OUT2R_ENA */ -#define WM2200_OUT2R_ENA_SHIFT 2 /* OUT2R_ENA */ -#define WM2200_OUT2R_ENA_WIDTH 1 /* OUT2R_ENA */ -#define WM2200_OUT1L_ENA 0x0002 /* OUT1L_ENA */ -#define WM2200_OUT1L_ENA_MASK 0x0002 /* OUT1L_ENA */ -#define WM2200_OUT1L_ENA_SHIFT 1 /* OUT1L_ENA */ -#define WM2200_OUT1L_ENA_WIDTH 1 /* OUT1L_ENA */ -#define WM2200_OUT1R_ENA 0x0001 /* OUT1R_ENA */ -#define WM2200_OUT1R_ENA_MASK 0x0001 /* OUT1R_ENA */ -#define WM2200_OUT1R_ENA_SHIFT 0 /* OUT1R_ENA */ -#define WM2200_OUT1R_ENA_WIDTH 1 /* OUT1R_ENA */ - -/* - * R1025 (0x401) - DAC Volume Limit 1L - */ -#define WM2200_OUT1_OSR 0x2000 /* OUT1_OSR */ -#define WM2200_OUT1_OSR_MASK 0x2000 /* OUT1_OSR */ -#define WM2200_OUT1_OSR_SHIFT 13 /* OUT1_OSR */ -#define WM2200_OUT1_OSR_WIDTH 1 /* OUT1_OSR */ -#define WM2200_OUT1L_ANC_SRC 0x0800 /* OUT1L_ANC_SRC */ -#define WM2200_OUT1L_ANC_SRC_MASK 0x0800 /* OUT1L_ANC_SRC */ -#define WM2200_OUT1L_ANC_SRC_SHIFT 11 /* OUT1L_ANC_SRC */ -#define WM2200_OUT1L_ANC_SRC_WIDTH 1 /* OUT1L_ANC_SRC */ -#define WM2200_OUT1L_PGA_VOL_MASK 0x00FE /* OUT1L_PGA_VOL - [7:1] */ -#define WM2200_OUT1L_PGA_VOL_SHIFT 1 /* OUT1L_PGA_VOL - [7:1] */ -#define WM2200_OUT1L_PGA_VOL_WIDTH 7 /* OUT1L_PGA_VOL - [7:1] */ - -/* - * R1026 (0x402) - DAC Volume Limit 1R - */ -#define WM2200_OUT1R_ANC_SRC 0x0800 /* OUT1R_ANC_SRC */ -#define WM2200_OUT1R_ANC_SRC_MASK 0x0800 /* OUT1R_ANC_SRC */ -#define WM2200_OUT1R_ANC_SRC_SHIFT 11 /* OUT1R_ANC_SRC */ -#define WM2200_OUT1R_ANC_SRC_WIDTH 1 /* OUT1R_ANC_SRC */ -#define WM2200_OUT1R_PGA_VOL_MASK 0x00FE /* OUT1R_PGA_VOL - [7:1] */ -#define WM2200_OUT1R_PGA_VOL_SHIFT 1 /* OUT1R_PGA_VOL - [7:1] */ -#define WM2200_OUT1R_PGA_VOL_WIDTH 7 /* OUT1R_PGA_VOL - [7:1] */ - -/* - * R1027 (0x403) - DAC Volume Limit 2L - */ -#define WM2200_OUT2_OSR 0x2000 /* OUT2_OSR */ -#define WM2200_OUT2_OSR_MASK 0x2000 /* OUT2_OSR */ -#define WM2200_OUT2_OSR_SHIFT 13 /* OUT2_OSR */ -#define WM2200_OUT2_OSR_WIDTH 1 /* OUT2_OSR */ -#define WM2200_OUT2L_ANC_SRC 0x0800 /* OUT2L_ANC_SRC */ -#define WM2200_OUT2L_ANC_SRC_MASK 0x0800 /* OUT2L_ANC_SRC */ -#define WM2200_OUT2L_ANC_SRC_SHIFT 11 /* OUT2L_ANC_SRC */ -#define WM2200_OUT2L_ANC_SRC_WIDTH 1 /* OUT2L_ANC_SRC */ - -/* - * R1028 (0x404) - DAC Volume Limit 2R - */ -#define WM2200_OUT2R_ANC_SRC 0x0800 /* OUT2R_ANC_SRC */ -#define WM2200_OUT2R_ANC_SRC_MASK 0x0800 /* OUT2R_ANC_SRC */ -#define WM2200_OUT2R_ANC_SRC_SHIFT 11 /* OUT2R_ANC_SRC */ -#define WM2200_OUT2R_ANC_SRC_WIDTH 1 /* OUT2R_ANC_SRC */ - -/* - * R1033 (0x409) - DAC AEC Control 1 - */ -#define WM2200_AEC_LOOPBACK_ENA 0x0004 /* AEC_LOOPBACK_ENA */ -#define WM2200_AEC_LOOPBACK_ENA_MASK 0x0004 /* AEC_LOOPBACK_ENA */ -#define WM2200_AEC_LOOPBACK_ENA_SHIFT 2 /* AEC_LOOPBACK_ENA */ -#define WM2200_AEC_LOOPBACK_ENA_WIDTH 1 /* AEC_LOOPBACK_ENA */ -#define WM2200_AEC_LOOPBACK_SRC_MASK 0x0003 /* AEC_LOOPBACK_SRC - [1:0] */ -#define WM2200_AEC_LOOPBACK_SRC_SHIFT 0 /* AEC_LOOPBACK_SRC - [1:0] */ -#define WM2200_AEC_LOOPBACK_SRC_WIDTH 2 /* AEC_LOOPBACK_SRC - [1:0] */ - -/* - * R1034 (0x40A) - Output Volume Ramp - */ -#define WM2200_OUT_VD_RAMP_MASK 0x0070 /* OUT_VD_RAMP - [6:4] */ -#define WM2200_OUT_VD_RAMP_SHIFT 4 /* OUT_VD_RAMP - [6:4] */ -#define WM2200_OUT_VD_RAMP_WIDTH 3 /* OUT_VD_RAMP - [6:4] */ -#define WM2200_OUT_VI_RAMP_MASK 0x0007 /* OUT_VI_RAMP - [2:0] */ -#define WM2200_OUT_VI_RAMP_SHIFT 0 /* OUT_VI_RAMP - [2:0] */ -#define WM2200_OUT_VI_RAMP_WIDTH 3 /* OUT_VI_RAMP - [2:0] */ - -/* - * R1035 (0x40B) - DAC Digital Volume 1L - */ -#define WM2200_OUT_VU 0x0200 /* OUT_VU */ -#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM2200_OUT1L_MUTE 0x0100 /* OUT1L_MUTE */ -#define WM2200_OUT1L_MUTE_MASK 0x0100 /* OUT1L_MUTE */ -#define WM2200_OUT1L_MUTE_SHIFT 8 /* OUT1L_MUTE */ -#define WM2200_OUT1L_MUTE_WIDTH 1 /* OUT1L_MUTE */ -#define WM2200_OUT1L_VOL_MASK 0x00FF /* OUT1L_VOL - [7:0] */ -#define WM2200_OUT1L_VOL_SHIFT 0 /* OUT1L_VOL - [7:0] */ -#define WM2200_OUT1L_VOL_WIDTH 8 /* OUT1L_VOL - [7:0] */ - -/* - * R1036 (0x40C) - DAC Digital Volume 1R - */ -#define WM2200_OUT_VU 0x0200 /* OUT_VU */ -#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM2200_OUT1R_MUTE 0x0100 /* OUT1R_MUTE */ -#define WM2200_OUT1R_MUTE_MASK 0x0100 /* OUT1R_MUTE */ -#define WM2200_OUT1R_MUTE_SHIFT 8 /* OUT1R_MUTE */ -#define WM2200_OUT1R_MUTE_WIDTH 1 /* OUT1R_MUTE */ -#define WM2200_OUT1R_VOL_MASK 0x00FF /* OUT1R_VOL - [7:0] */ -#define WM2200_OUT1R_VOL_SHIFT 0 /* OUT1R_VOL - [7:0] */ -#define WM2200_OUT1R_VOL_WIDTH 8 /* OUT1R_VOL - [7:0] */ - -/* - * R1037 (0x40D) - DAC Digital Volume 2L - */ -#define WM2200_OUT_VU 0x0200 /* OUT_VU */ -#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM2200_OUT2L_MUTE 0x0100 /* OUT2L_MUTE */ -#define WM2200_OUT2L_MUTE_MASK 0x0100 /* OUT2L_MUTE */ -#define WM2200_OUT2L_MUTE_SHIFT 8 /* OUT2L_MUTE */ -#define WM2200_OUT2L_MUTE_WIDTH 1 /* OUT2L_MUTE */ -#define WM2200_OUT2L_VOL_MASK 0x00FF /* OUT2L_VOL - [7:0] */ -#define WM2200_OUT2L_VOL_SHIFT 0 /* OUT2L_VOL - [7:0] */ -#define WM2200_OUT2L_VOL_WIDTH 8 /* OUT2L_VOL - [7:0] */ - -/* - * R1038 (0x40E) - DAC Digital Volume 2R - */ -#define WM2200_OUT_VU 0x0200 /* OUT_VU */ -#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM2200_OUT2R_MUTE 0x0100 /* OUT2R_MUTE */ -#define WM2200_OUT2R_MUTE_MASK 0x0100 /* OUT2R_MUTE */ -#define WM2200_OUT2R_MUTE_SHIFT 8 /* OUT2R_MUTE */ -#define WM2200_OUT2R_MUTE_WIDTH 1 /* OUT2R_MUTE */ -#define WM2200_OUT2R_VOL_MASK 0x00FF /* OUT2R_VOL - [7:0] */ -#define WM2200_OUT2R_VOL_SHIFT 0 /* OUT2R_VOL - [7:0] */ -#define WM2200_OUT2R_VOL_WIDTH 8 /* OUT2R_VOL - [7:0] */ - -/* - * R1047 (0x417) - PDM 1 - */ -#define WM2200_SPK1R_MUTE 0x2000 /* SPK1R_MUTE */ -#define WM2200_SPK1R_MUTE_MASK 0x2000 /* SPK1R_MUTE */ -#define WM2200_SPK1R_MUTE_SHIFT 13 /* SPK1R_MUTE */ -#define WM2200_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */ -#define WM2200_SPK1L_MUTE 0x1000 /* SPK1L_MUTE */ -#define WM2200_SPK1L_MUTE_MASK 0x1000 /* SPK1L_MUTE */ -#define WM2200_SPK1L_MUTE_SHIFT 12 /* SPK1L_MUTE */ -#define WM2200_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */ -#define WM2200_SPK1_MUTE_ENDIAN 0x0100 /* SPK1_MUTE_ENDIAN */ -#define WM2200_SPK1_MUTE_ENDIAN_MASK 0x0100 /* SPK1_MUTE_ENDIAN */ -#define WM2200_SPK1_MUTE_ENDIAN_SHIFT 8 /* SPK1_MUTE_ENDIAN */ -#define WM2200_SPK1_MUTE_ENDIAN_WIDTH 1 /* SPK1_MUTE_ENDIAN */ -#define WM2200_SPK1_MUTE_SEQL_MASK 0x00FF /* SPK1_MUTE_SEQL - [7:0] */ -#define WM2200_SPK1_MUTE_SEQL_SHIFT 0 /* SPK1_MUTE_SEQL - [7:0] */ -#define WM2200_SPK1_MUTE_SEQL_WIDTH 8 /* SPK1_MUTE_SEQL - [7:0] */ - -/* - * R1048 (0x418) - PDM 2 - */ -#define WM2200_SPK1_FMT 0x0001 /* SPK1_FMT */ -#define WM2200_SPK1_FMT_MASK 0x0001 /* SPK1_FMT */ -#define WM2200_SPK1_FMT_SHIFT 0 /* SPK1_FMT */ -#define WM2200_SPK1_FMT_WIDTH 1 /* SPK1_FMT */ - -/* - * R1280 (0x500) - Audio IF 1_1 - */ -#define WM2200_AIF1_BCLK_INV 0x0040 /* AIF1_BCLK_INV */ -#define WM2200_AIF1_BCLK_INV_MASK 0x0040 /* AIF1_BCLK_INV */ -#define WM2200_AIF1_BCLK_INV_SHIFT 6 /* AIF1_BCLK_INV */ -#define WM2200_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */ -#define WM2200_AIF1_BCLK_FRC 0x0020 /* AIF1_BCLK_FRC */ -#define WM2200_AIF1_BCLK_FRC_MASK 0x0020 /* AIF1_BCLK_FRC */ -#define WM2200_AIF1_BCLK_FRC_SHIFT 5 /* AIF1_BCLK_FRC */ -#define WM2200_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */ -#define WM2200_AIF1_BCLK_MSTR 0x0010 /* AIF1_BCLK_MSTR */ -#define WM2200_AIF1_BCLK_MSTR_MASK 0x0010 /* AIF1_BCLK_MSTR */ -#define WM2200_AIF1_BCLK_MSTR_SHIFT 4 /* AIF1_BCLK_MSTR */ -#define WM2200_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */ -#define WM2200_AIF1_BCLK_DIV_MASK 0x000F /* AIF1_BCLK_DIV - [3:0] */ -#define WM2200_AIF1_BCLK_DIV_SHIFT 0 /* AIF1_BCLK_DIV - [3:0] */ -#define WM2200_AIF1_BCLK_DIV_WIDTH 4 /* AIF1_BCLK_DIV - [3:0] */ - -/* - * R1281 (0x501) - Audio IF 1_2 - */ -#define WM2200_AIF1TX_DAT_TRI 0x0020 /* AIF1TX_DAT_TRI */ -#define WM2200_AIF1TX_DAT_TRI_MASK 0x0020 /* AIF1TX_DAT_TRI */ -#define WM2200_AIF1TX_DAT_TRI_SHIFT 5 /* AIF1TX_DAT_TRI */ -#define WM2200_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */ -#define WM2200_AIF1TX_LRCLK_SRC 0x0008 /* AIF1TX_LRCLK_SRC */ -#define WM2200_AIF1TX_LRCLK_SRC_MASK 0x0008 /* AIF1TX_LRCLK_SRC */ -#define WM2200_AIF1TX_LRCLK_SRC_SHIFT 3 /* AIF1TX_LRCLK_SRC */ -#define WM2200_AIF1TX_LRCLK_SRC_WIDTH 1 /* AIF1TX_LRCLK_SRC */ -#define WM2200_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */ -#define WM2200_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */ -#define WM2200_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */ -#define WM2200_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */ -#define WM2200_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */ -#define WM2200_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */ -#define WM2200_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */ -#define WM2200_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */ -#define WM2200_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */ -#define WM2200_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */ -#define WM2200_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */ -#define WM2200_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */ - -/* - * R1282 (0x502) - Audio IF 1_3 - */ -#define WM2200_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */ -#define WM2200_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */ -#define WM2200_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */ -#define WM2200_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */ -#define WM2200_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */ -#define WM2200_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */ -#define WM2200_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */ -#define WM2200_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */ -#define WM2200_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */ -#define WM2200_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */ -#define WM2200_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */ -#define WM2200_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */ - -/* - * R1283 (0x503) - Audio IF 1_4 - */ -#define WM2200_AIF1_TRI 0x0040 /* AIF1_TRI */ -#define WM2200_AIF1_TRI_MASK 0x0040 /* AIF1_TRI */ -#define WM2200_AIF1_TRI_SHIFT 6 /* AIF1_TRI */ -#define WM2200_AIF1_TRI_WIDTH 1 /* AIF1_TRI */ - -/* - * R1284 (0x504) - Audio IF 1_5 - */ -#define WM2200_AIF1_FMT_MASK 0x0007 /* AIF1_FMT - [2:0] */ -#define WM2200_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [2:0] */ -#define WM2200_AIF1_FMT_WIDTH 3 /* AIF1_FMT - [2:0] */ - -/* - * R1285 (0x505) - Audio IF 1_6 - */ -#define WM2200_AIF1TX_BCPF_MASK 0x07FF /* AIF1TX_BCPF - [10:0] */ -#define WM2200_AIF1TX_BCPF_SHIFT 0 /* AIF1TX_BCPF - [10:0] */ -#define WM2200_AIF1TX_BCPF_WIDTH 11 /* AIF1TX_BCPF - [10:0] */ - -/* - * R1286 (0x506) - Audio IF 1_7 - */ -#define WM2200_AIF1RX_BCPF_MASK 0x07FF /* AIF1RX_BCPF - [10:0] */ -#define WM2200_AIF1RX_BCPF_SHIFT 0 /* AIF1RX_BCPF - [10:0] */ -#define WM2200_AIF1RX_BCPF_WIDTH 11 /* AIF1RX_BCPF - [10:0] */ - -/* - * R1287 (0x507) - Audio IF 1_8 - */ -#define WM2200_AIF1TX_WL_MASK 0x3F00 /* AIF1TX_WL - [13:8] */ -#define WM2200_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [13:8] */ -#define WM2200_AIF1TX_WL_WIDTH 6 /* AIF1TX_WL - [13:8] */ -#define WM2200_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */ -#define WM2200_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */ -#define WM2200_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */ - -/* - * R1288 (0x508) - Audio IF 1_9 - */ -#define WM2200_AIF1RX_WL_MASK 0x3F00 /* AIF1RX_WL - [13:8] */ -#define WM2200_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [13:8] */ -#define WM2200_AIF1RX_WL_WIDTH 6 /* AIF1RX_WL - [13:8] */ -#define WM2200_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */ -#define WM2200_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */ -#define WM2200_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */ - -/* - * R1289 (0x509) - Audio IF 1_10 - */ -#define WM2200_AIF1TX1_SLOT_MASK 0x003F /* AIF1TX1_SLOT - [5:0] */ -#define WM2200_AIF1TX1_SLOT_SHIFT 0 /* AIF1TX1_SLOT - [5:0] */ -#define WM2200_AIF1TX1_SLOT_WIDTH 6 /* AIF1TX1_SLOT - [5:0] */ - -/* - * R1290 (0x50A) - Audio IF 1_11 - */ -#define WM2200_AIF1TX2_SLOT_MASK 0x003F /* AIF1TX2_SLOT - [5:0] */ -#define WM2200_AIF1TX2_SLOT_SHIFT 0 /* AIF1TX2_SLOT - [5:0] */ -#define WM2200_AIF1TX2_SLOT_WIDTH 6 /* AIF1TX2_SLOT - [5:0] */ - -/* - * R1291 (0x50B) - Audio IF 1_12 - */ -#define WM2200_AIF1TX3_SLOT_MASK 0x003F /* AIF1TX3_SLOT - [5:0] */ -#define WM2200_AIF1TX3_SLOT_SHIFT 0 /* AIF1TX3_SLOT - [5:0] */ -#define WM2200_AIF1TX3_SLOT_WIDTH 6 /* AIF1TX3_SLOT - [5:0] */ - -/* - * R1292 (0x50C) - Audio IF 1_13 - */ -#define WM2200_AIF1TX4_SLOT_MASK 0x003F /* AIF1TX4_SLOT - [5:0] */ -#define WM2200_AIF1TX4_SLOT_SHIFT 0 /* AIF1TX4_SLOT - [5:0] */ -#define WM2200_AIF1TX4_SLOT_WIDTH 6 /* AIF1TX4_SLOT - [5:0] */ - -/* - * R1293 (0x50D) - Audio IF 1_14 - */ -#define WM2200_AIF1TX5_SLOT_MASK 0x003F /* AIF1TX5_SLOT - [5:0] */ -#define WM2200_AIF1TX5_SLOT_SHIFT 0 /* AIF1TX5_SLOT - [5:0] */ -#define WM2200_AIF1TX5_SLOT_WIDTH 6 /* AIF1TX5_SLOT - [5:0] */ - -/* - * R1294 (0x50E) - Audio IF 1_15 - */ -#define WM2200_AIF1TX6_SLOT_MASK 0x003F /* AIF1TX6_SLOT - [5:0] */ -#define WM2200_AIF1TX6_SLOT_SHIFT 0 /* AIF1TX6_SLOT - [5:0] */ -#define WM2200_AIF1TX6_SLOT_WIDTH 6 /* AIF1TX6_SLOT - [5:0] */ - -/* - * R1295 (0x50F) - Audio IF 1_16 - */ -#define WM2200_AIF1RX1_SLOT_MASK 0x003F /* AIF1RX1_SLOT - [5:0] */ -#define WM2200_AIF1RX1_SLOT_SHIFT 0 /* AIF1RX1_SLOT - [5:0] */ -#define WM2200_AIF1RX1_SLOT_WIDTH 6 /* AIF1RX1_SLOT - [5:0] */ - -/* - * R1296 (0x510) - Audio IF 1_17 - */ -#define WM2200_AIF1RX2_SLOT_MASK 0x003F /* AIF1RX2_SLOT - [5:0] */ -#define WM2200_AIF1RX2_SLOT_SHIFT 0 /* AIF1RX2_SLOT - [5:0] */ -#define WM2200_AIF1RX2_SLOT_WIDTH 6 /* AIF1RX2_SLOT - [5:0] */ - -/* - * R1297 (0x511) - Audio IF 1_18 - */ -#define WM2200_AIF1RX3_SLOT_MASK 0x003F /* AIF1RX3_SLOT - [5:0] */ -#define WM2200_AIF1RX3_SLOT_SHIFT 0 /* AIF1RX3_SLOT - [5:0] */ -#define WM2200_AIF1RX3_SLOT_WIDTH 6 /* AIF1RX3_SLOT - [5:0] */ - -/* - * R1298 (0x512) - Audio IF 1_19 - */ -#define WM2200_AIF1RX4_SLOT_MASK 0x003F /* AIF1RX4_SLOT - [5:0] */ -#define WM2200_AIF1RX4_SLOT_SHIFT 0 /* AIF1RX4_SLOT - [5:0] */ -#define WM2200_AIF1RX4_SLOT_WIDTH 6 /* AIF1RX4_SLOT - [5:0] */ - -/* - * R1299 (0x513) - Audio IF 1_20 - */ -#define WM2200_AIF1RX5_SLOT_MASK 0x003F /* AIF1RX5_SLOT - [5:0] */ -#define WM2200_AIF1RX5_SLOT_SHIFT 0 /* AIF1RX5_SLOT - [5:0] */ -#define WM2200_AIF1RX5_SLOT_WIDTH 6 /* AIF1RX5_SLOT - [5:0] */ - -/* - * R1300 (0x514) - Audio IF 1_21 - */ -#define WM2200_AIF1RX6_SLOT_MASK 0x003F /* AIF1RX6_SLOT - [5:0] */ -#define WM2200_AIF1RX6_SLOT_SHIFT 0 /* AIF1RX6_SLOT - [5:0] */ -#define WM2200_AIF1RX6_SLOT_WIDTH 6 /* AIF1RX6_SLOT - [5:0] */ - -/* - * R1301 (0x515) - Audio IF 1_22 - */ -#define WM2200_AIF1RX6_ENA 0x0800 /* AIF1RX6_ENA */ -#define WM2200_AIF1RX6_ENA_MASK 0x0800 /* AIF1RX6_ENA */ -#define WM2200_AIF1RX6_ENA_SHIFT 11 /* AIF1RX6_ENA */ -#define WM2200_AIF1RX6_ENA_WIDTH 1 /* AIF1RX6_ENA */ -#define WM2200_AIF1RX5_ENA 0x0400 /* AIF1RX5_ENA */ -#define WM2200_AIF1RX5_ENA_MASK 0x0400 /* AIF1RX5_ENA */ -#define WM2200_AIF1RX5_ENA_SHIFT 10 /* AIF1RX5_ENA */ -#define WM2200_AIF1RX5_ENA_WIDTH 1 /* AIF1RX5_ENA */ -#define WM2200_AIF1RX4_ENA 0x0200 /* AIF1RX4_ENA */ -#define WM2200_AIF1RX4_ENA_MASK 0x0200 /* AIF1RX4_ENA */ -#define WM2200_AIF1RX4_ENA_SHIFT 9 /* AIF1RX4_ENA */ -#define WM2200_AIF1RX4_ENA_WIDTH 1 /* AIF1RX4_ENA */ -#define WM2200_AIF1RX3_ENA 0x0100 /* AIF1RX3_ENA */ -#define WM2200_AIF1RX3_ENA_MASK 0x0100 /* AIF1RX3_ENA */ -#define WM2200_AIF1RX3_ENA_SHIFT 8 /* AIF1RX3_ENA */ -#define WM2200_AIF1RX3_ENA_WIDTH 1 /* AIF1RX3_ENA */ -#define WM2200_AIF1RX2_ENA 0x0080 /* AIF1RX2_ENA */ -#define WM2200_AIF1RX2_ENA_MASK 0x0080 /* AIF1RX2_ENA */ -#define WM2200_AIF1RX2_ENA_SHIFT 7 /* AIF1RX2_ENA */ -#define WM2200_AIF1RX2_ENA_WIDTH 1 /* AIF1RX2_ENA */ -#define WM2200_AIF1RX1_ENA 0x0040 /* AIF1RX1_ENA */ -#define WM2200_AIF1RX1_ENA_MASK 0x0040 /* AIF1RX1_ENA */ -#define WM2200_AIF1RX1_ENA_SHIFT 6 /* AIF1RX1_ENA */ -#define WM2200_AIF1RX1_ENA_WIDTH 1 /* AIF1RX1_ENA */ -#define WM2200_AIF1TX6_ENA 0x0020 /* AIF1TX6_ENA */ -#define WM2200_AIF1TX6_ENA_MASK 0x0020 /* AIF1TX6_ENA */ -#define WM2200_AIF1TX6_ENA_SHIFT 5 /* AIF1TX6_ENA */ -#define WM2200_AIF1TX6_ENA_WIDTH 1 /* AIF1TX6_ENA */ -#define WM2200_AIF1TX5_ENA 0x0010 /* AIF1TX5_ENA */ -#define WM2200_AIF1TX5_ENA_MASK 0x0010 /* AIF1TX5_ENA */ -#define WM2200_AIF1TX5_ENA_SHIFT 4 /* AIF1TX5_ENA */ -#define WM2200_AIF1TX5_ENA_WIDTH 1 /* AIF1TX5_ENA */ -#define WM2200_AIF1TX4_ENA 0x0008 /* AIF1TX4_ENA */ -#define WM2200_AIF1TX4_ENA_MASK 0x0008 /* AIF1TX4_ENA */ -#define WM2200_AIF1TX4_ENA_SHIFT 3 /* AIF1TX4_ENA */ -#define WM2200_AIF1TX4_ENA_WIDTH 1 /* AIF1TX4_ENA */ -#define WM2200_AIF1TX3_ENA 0x0004 /* AIF1TX3_ENA */ -#define WM2200_AIF1TX3_ENA_MASK 0x0004 /* AIF1TX3_ENA */ -#define WM2200_AIF1TX3_ENA_SHIFT 2 /* AIF1TX3_ENA */ -#define WM2200_AIF1TX3_ENA_WIDTH 1 /* AIF1TX3_ENA */ -#define WM2200_AIF1TX2_ENA 0x0002 /* AIF1TX2_ENA */ -#define WM2200_AIF1TX2_ENA_MASK 0x0002 /* AIF1TX2_ENA */ -#define WM2200_AIF1TX2_ENA_SHIFT 1 /* AIF1TX2_ENA */ -#define WM2200_AIF1TX2_ENA_WIDTH 1 /* AIF1TX2_ENA */ -#define WM2200_AIF1TX1_ENA 0x0001 /* AIF1TX1_ENA */ -#define WM2200_AIF1TX1_ENA_MASK 0x0001 /* AIF1TX1_ENA */ -#define WM2200_AIF1TX1_ENA_SHIFT 0 /* AIF1TX1_ENA */ -#define WM2200_AIF1TX1_ENA_WIDTH 1 /* AIF1TX1_ENA */ - -/* - * R1536 (0x600) - OUT1LMIX Input 1 Source - */ -#define WM2200_OUT1LMIX_SRC1_MASK 0x007F /* OUT1LMIX_SRC1 - [6:0] */ -#define WM2200_OUT1LMIX_SRC1_SHIFT 0 /* OUT1LMIX_SRC1 - [6:0] */ -#define WM2200_OUT1LMIX_SRC1_WIDTH 7 /* OUT1LMIX_SRC1 - [6:0] */ - -/* - * R1537 (0x601) - OUT1LMIX Input 1 Volume - */ -#define WM2200_OUT1LMIX_VOL1_MASK 0x00FE /* OUT1LMIX_VOL1 - [7:1] */ -#define WM2200_OUT1LMIX_VOL1_SHIFT 1 /* OUT1LMIX_VOL1 - [7:1] */ -#define WM2200_OUT1LMIX_VOL1_WIDTH 7 /* OUT1LMIX_VOL1 - [7:1] */ - -/* - * R1538 (0x602) - OUT1LMIX Input 2 Source - */ -#define WM2200_OUT1LMIX_SRC2_MASK 0x007F /* OUT1LMIX_SRC2 - [6:0] */ -#define WM2200_OUT1LMIX_SRC2_SHIFT 0 /* OUT1LMIX_SRC2 - [6:0] */ -#define WM2200_OUT1LMIX_SRC2_WIDTH 7 /* OUT1LMIX_SRC2 - [6:0] */ - -/* - * R1539 (0x603) - OUT1LMIX Input 2 Volume - */ -#define WM2200_OUT1LMIX_VOL2_MASK 0x00FE /* OUT1LMIX_VOL2 - [7:1] */ -#define WM2200_OUT1LMIX_VOL2_SHIFT 1 /* OUT1LMIX_VOL2 - [7:1] */ -#define WM2200_OUT1LMIX_VOL2_WIDTH 7 /* OUT1LMIX_VOL2 - [7:1] */ - -/* - * R1540 (0x604) - OUT1LMIX Input 3 Source - */ -#define WM2200_OUT1LMIX_SRC3_MASK 0x007F /* OUT1LMIX_SRC3 - [6:0] */ -#define WM2200_OUT1LMIX_SRC3_SHIFT 0 /* OUT1LMIX_SRC3 - [6:0] */ -#define WM2200_OUT1LMIX_SRC3_WIDTH 7 /* OUT1LMIX_SRC3 - [6:0] */ - -/* - * R1541 (0x605) - OUT1LMIX Input 3 Volume - */ -#define WM2200_OUT1LMIX_VOL3_MASK 0x00FE /* OUT1LMIX_VOL3 - [7:1] */ -#define WM2200_OUT1LMIX_VOL3_SHIFT 1 /* OUT1LMIX_VOL3 - [7:1] */ -#define WM2200_OUT1LMIX_VOL3_WIDTH 7 /* OUT1LMIX_VOL3 - [7:1] */ - -/* - * R1542 (0x606) - OUT1LMIX Input 4 Source - */ -#define WM2200_OUT1LMIX_SRC4_MASK 0x007F /* OUT1LMIX_SRC4 - [6:0] */ -#define WM2200_OUT1LMIX_SRC4_SHIFT 0 /* OUT1LMIX_SRC4 - [6:0] */ -#define WM2200_OUT1LMIX_SRC4_WIDTH 7 /* OUT1LMIX_SRC4 - [6:0] */ - -/* - * R1543 (0x607) - OUT1LMIX Input 4 Volume - */ -#define WM2200_OUT1LMIX_VOL4_MASK 0x00FE /* OUT1LMIX_VOL4 - [7:1] */ -#define WM2200_OUT1LMIX_VOL4_SHIFT 1 /* OUT1LMIX_VOL4 - [7:1] */ -#define WM2200_OUT1LMIX_VOL4_WIDTH 7 /* OUT1LMIX_VOL4 - [7:1] */ - -/* - * R1544 (0x608) - OUT1RMIX Input 1 Source - */ -#define WM2200_OUT1RMIX_SRC1_MASK 0x007F /* OUT1RMIX_SRC1 - [6:0] */ -#define WM2200_OUT1RMIX_SRC1_SHIFT 0 /* OUT1RMIX_SRC1 - [6:0] */ -#define WM2200_OUT1RMIX_SRC1_WIDTH 7 /* OUT1RMIX_SRC1 - [6:0] */ - -/* - * R1545 (0x609) - OUT1RMIX Input 1 Volume - */ -#define WM2200_OUT1RMIX_VOL1_MASK 0x00FE /* OUT1RMIX_VOL1 - [7:1] */ -#define WM2200_OUT1RMIX_VOL1_SHIFT 1 /* OUT1RMIX_VOL1 - [7:1] */ -#define WM2200_OUT1RMIX_VOL1_WIDTH 7 /* OUT1RMIX_VOL1 - [7:1] */ - -/* - * R1546 (0x60A) - OUT1RMIX Input 2 Source - */ -#define WM2200_OUT1RMIX_SRC2_MASK 0x007F /* OUT1RMIX_SRC2 - [6:0] */ -#define WM2200_OUT1RMIX_SRC2_SHIFT 0 /* OUT1RMIX_SRC2 - [6:0] */ -#define WM2200_OUT1RMIX_SRC2_WIDTH 7 /* OUT1RMIX_SRC2 - [6:0] */ - -/* - * R1547 (0x60B) - OUT1RMIX Input 2 Volume - */ -#define WM2200_OUT1RMIX_VOL2_MASK 0x00FE /* OUT1RMIX_VOL2 - [7:1] */ -#define WM2200_OUT1RMIX_VOL2_SHIFT 1 /* OUT1RMIX_VOL2 - [7:1] */ -#define WM2200_OUT1RMIX_VOL2_WIDTH 7 /* OUT1RMIX_VOL2 - [7:1] */ - -/* - * R1548 (0x60C) - OUT1RMIX Input 3 Source - */ -#define WM2200_OUT1RMIX_SRC3_MASK 0x007F /* OUT1RMIX_SRC3 - [6:0] */ -#define WM2200_OUT1RMIX_SRC3_SHIFT 0 /* OUT1RMIX_SRC3 - [6:0] */ -#define WM2200_OUT1RMIX_SRC3_WIDTH 7 /* OUT1RMIX_SRC3 - [6:0] */ - -/* - * R1549 (0x60D) - OUT1RMIX Input 3 Volume - */ -#define WM2200_OUT1RMIX_VOL3_MASK 0x00FE /* OUT1RMIX_VOL3 - [7:1] */ -#define WM2200_OUT1RMIX_VOL3_SHIFT 1 /* OUT1RMIX_VOL3 - [7:1] */ -#define WM2200_OUT1RMIX_VOL3_WIDTH 7 /* OUT1RMIX_VOL3 - [7:1] */ - -/* - * R1550 (0x60E) - OUT1RMIX Input 4 Source - */ -#define WM2200_OUT1RMIX_SRC4_MASK 0x007F /* OUT1RMIX_SRC4 - [6:0] */ -#define WM2200_OUT1RMIX_SRC4_SHIFT 0 /* OUT1RMIX_SRC4 - [6:0] */ -#define WM2200_OUT1RMIX_SRC4_WIDTH 7 /* OUT1RMIX_SRC4 - [6:0] */ - -/* - * R1551 (0x60F) - OUT1RMIX Input 4 Volume - */ -#define WM2200_OUT1RMIX_VOL4_MASK 0x00FE /* OUT1RMIX_VOL4 - [7:1] */ -#define WM2200_OUT1RMIX_VOL4_SHIFT 1 /* OUT1RMIX_VOL4 - [7:1] */ -#define WM2200_OUT1RMIX_VOL4_WIDTH 7 /* OUT1RMIX_VOL4 - [7:1] */ - -/* - * R1552 (0x610) - OUT2LMIX Input 1 Source - */ -#define WM2200_OUT2LMIX_SRC1_MASK 0x007F /* OUT2LMIX_SRC1 - [6:0] */ -#define WM2200_OUT2LMIX_SRC1_SHIFT 0 /* OUT2LMIX_SRC1 - [6:0] */ -#define WM2200_OUT2LMIX_SRC1_WIDTH 7 /* OUT2LMIX_SRC1 - [6:0] */ - -/* - * R1553 (0x611) - OUT2LMIX Input 1 Volume - */ -#define WM2200_OUT2LMIX_VOL1_MASK 0x00FE /* OUT2LMIX_VOL1 - [7:1] */ -#define WM2200_OUT2LMIX_VOL1_SHIFT 1 /* OUT2LMIX_VOL1 - [7:1] */ -#define WM2200_OUT2LMIX_VOL1_WIDTH 7 /* OUT2LMIX_VOL1 - [7:1] */ - -/* - * R1554 (0x612) - OUT2LMIX Input 2 Source - */ -#define WM2200_OUT2LMIX_SRC2_MASK 0x007F /* OUT2LMIX_SRC2 - [6:0] */ -#define WM2200_OUT2LMIX_SRC2_SHIFT 0 /* OUT2LMIX_SRC2 - [6:0] */ -#define WM2200_OUT2LMIX_SRC2_WIDTH 7 /* OUT2LMIX_SRC2 - [6:0] */ - -/* - * R1555 (0x613) - OUT2LMIX Input 2 Volume - */ -#define WM2200_OUT2LMIX_VOL2_MASK 0x00FE /* OUT2LMIX_VOL2 - [7:1] */ -#define WM2200_OUT2LMIX_VOL2_SHIFT 1 /* OUT2LMIX_VOL2 - [7:1] */ -#define WM2200_OUT2LMIX_VOL2_WIDTH 7 /* OUT2LMIX_VOL2 - [7:1] */ - -/* - * R1556 (0x614) - OUT2LMIX Input 3 Source - */ -#define WM2200_OUT2LMIX_SRC3_MASK 0x007F /* OUT2LMIX_SRC3 - [6:0] */ -#define WM2200_OUT2LMIX_SRC3_SHIFT 0 /* OUT2LMIX_SRC3 - [6:0] */ -#define WM2200_OUT2LMIX_SRC3_WIDTH 7 /* OUT2LMIX_SRC3 - [6:0] */ - -/* - * R1557 (0x615) - OUT2LMIX Input 3 Volume - */ -#define WM2200_OUT2LMIX_VOL3_MASK 0x00FE /* OUT2LMIX_VOL3 - [7:1] */ -#define WM2200_OUT2LMIX_VOL3_SHIFT 1 /* OUT2LMIX_VOL3 - [7:1] */ -#define WM2200_OUT2LMIX_VOL3_WIDTH 7 /* OUT2LMIX_VOL3 - [7:1] */ - -/* - * R1558 (0x616) - OUT2LMIX Input 4 Source - */ -#define WM2200_OUT2LMIX_SRC4_MASK 0x007F /* OUT2LMIX_SRC4 - [6:0] */ -#define WM2200_OUT2LMIX_SRC4_SHIFT 0 /* OUT2LMIX_SRC4 - [6:0] */ -#define WM2200_OUT2LMIX_SRC4_WIDTH 7 /* OUT2LMIX_SRC4 - [6:0] */ - -/* - * R1559 (0x617) - OUT2LMIX Input 4 Volume - */ -#define WM2200_OUT2LMIX_VOL4_MASK 0x00FE /* OUT2LMIX_VOL4 - [7:1] */ -#define WM2200_OUT2LMIX_VOL4_SHIFT 1 /* OUT2LMIX_VOL4 - [7:1] */ -#define WM2200_OUT2LMIX_VOL4_WIDTH 7 /* OUT2LMIX_VOL4 - [7:1] */ - -/* - * R1560 (0x618) - OUT2RMIX Input 1 Source - */ -#define WM2200_OUT2RMIX_SRC1_MASK 0x007F /* OUT2RMIX_SRC1 - [6:0] */ -#define WM2200_OUT2RMIX_SRC1_SHIFT 0 /* OUT2RMIX_SRC1 - [6:0] */ -#define WM2200_OUT2RMIX_SRC1_WIDTH 7 /* OUT2RMIX_SRC1 - [6:0] */ - -/* - * R1561 (0x619) - OUT2RMIX Input 1 Volume - */ -#define WM2200_OUT2RMIX_VOL1_MASK 0x00FE /* OUT2RMIX_VOL1 - [7:1] */ -#define WM2200_OUT2RMIX_VOL1_SHIFT 1 /* OUT2RMIX_VOL1 - [7:1] */ -#define WM2200_OUT2RMIX_VOL1_WIDTH 7 /* OUT2RMIX_VOL1 - [7:1] */ - -/* - * R1562 (0x61A) - OUT2RMIX Input 2 Source - */ -#define WM2200_OUT2RMIX_SRC2_MASK 0x007F /* OUT2RMIX_SRC2 - [6:0] */ -#define WM2200_OUT2RMIX_SRC2_SHIFT 0 /* OUT2RMIX_SRC2 - [6:0] */ -#define WM2200_OUT2RMIX_SRC2_WIDTH 7 /* OUT2RMIX_SRC2 - [6:0] */ - -/* - * R1563 (0x61B) - OUT2RMIX Input 2 Volume - */ -#define WM2200_OUT2RMIX_VOL2_MASK 0x00FE /* OUT2RMIX_VOL2 - [7:1] */ -#define WM2200_OUT2RMIX_VOL2_SHIFT 1 /* OUT2RMIX_VOL2 - [7:1] */ -#define WM2200_OUT2RMIX_VOL2_WIDTH 7 /* OUT2RMIX_VOL2 - [7:1] */ - -/* - * R1564 (0x61C) - OUT2RMIX Input 3 Source - */ -#define WM2200_OUT2RMIX_SRC3_MASK 0x007F /* OUT2RMIX_SRC3 - [6:0] */ -#define WM2200_OUT2RMIX_SRC3_SHIFT 0 /* OUT2RMIX_SRC3 - [6:0] */ -#define WM2200_OUT2RMIX_SRC3_WIDTH 7 /* OUT2RMIX_SRC3 - [6:0] */ - -/* - * R1565 (0x61D) - OUT2RMIX Input 3 Volume - */ -#define WM2200_OUT2RMIX_VOL3_MASK 0x00FE /* OUT2RMIX_VOL3 - [7:1] */ -#define WM2200_OUT2RMIX_VOL3_SHIFT 1 /* OUT2RMIX_VOL3 - [7:1] */ -#define WM2200_OUT2RMIX_VOL3_WIDTH 7 /* OUT2RMIX_VOL3 - [7:1] */ - -/* - * R1566 (0x61E) - OUT2RMIX Input 4 Source - */ -#define WM2200_OUT2RMIX_SRC4_MASK 0x007F /* OUT2RMIX_SRC4 - [6:0] */ -#define WM2200_OUT2RMIX_SRC4_SHIFT 0 /* OUT2RMIX_SRC4 - [6:0] */ -#define WM2200_OUT2RMIX_SRC4_WIDTH 7 /* OUT2RMIX_SRC4 - [6:0] */ - -/* - * R1567 (0x61F) - OUT2RMIX Input 4 Volume - */ -#define WM2200_OUT2RMIX_VOL4_MASK 0x00FE /* OUT2RMIX_VOL4 - [7:1] */ -#define WM2200_OUT2RMIX_VOL4_SHIFT 1 /* OUT2RMIX_VOL4 - [7:1] */ -#define WM2200_OUT2RMIX_VOL4_WIDTH 7 /* OUT2RMIX_VOL4 - [7:1] */ - -/* - * R1568 (0x620) - AIF1TX1MIX Input 1 Source - */ -#define WM2200_AIF1TX1MIX_SRC1_MASK 0x007F /* AIF1TX1MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX1MIX_SRC1_SHIFT 0 /* AIF1TX1MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX1MIX_SRC1_WIDTH 7 /* AIF1TX1MIX_SRC1 - [6:0] */ - -/* - * R1569 (0x621) - AIF1TX1MIX Input 1 Volume - */ -#define WM2200_AIF1TX1MIX_VOL1_MASK 0x00FE /* AIF1TX1MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX1MIX_VOL1_SHIFT 1 /* AIF1TX1MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX1MIX_VOL1_WIDTH 7 /* AIF1TX1MIX_VOL1 - [7:1] */ - -/* - * R1570 (0x622) - AIF1TX1MIX Input 2 Source - */ -#define WM2200_AIF1TX1MIX_SRC2_MASK 0x007F /* AIF1TX1MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX1MIX_SRC2_SHIFT 0 /* AIF1TX1MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX1MIX_SRC2_WIDTH 7 /* AIF1TX1MIX_SRC2 - [6:0] */ - -/* - * R1571 (0x623) - AIF1TX1MIX Input 2 Volume - */ -#define WM2200_AIF1TX1MIX_VOL2_MASK 0x00FE /* AIF1TX1MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX1MIX_VOL2_SHIFT 1 /* AIF1TX1MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX1MIX_VOL2_WIDTH 7 /* AIF1TX1MIX_VOL2 - [7:1] */ - -/* - * R1572 (0x624) - AIF1TX1MIX Input 3 Source - */ -#define WM2200_AIF1TX1MIX_SRC3_MASK 0x007F /* AIF1TX1MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX1MIX_SRC3_SHIFT 0 /* AIF1TX1MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX1MIX_SRC3_WIDTH 7 /* AIF1TX1MIX_SRC3 - [6:0] */ - -/* - * R1573 (0x625) - AIF1TX1MIX Input 3 Volume - */ -#define WM2200_AIF1TX1MIX_VOL3_MASK 0x00FE /* AIF1TX1MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX1MIX_VOL3_SHIFT 1 /* AIF1TX1MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX1MIX_VOL3_WIDTH 7 /* AIF1TX1MIX_VOL3 - [7:1] */ - -/* - * R1574 (0x626) - AIF1TX1MIX Input 4 Source - */ -#define WM2200_AIF1TX1MIX_SRC4_MASK 0x007F /* AIF1TX1MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX1MIX_SRC4_SHIFT 0 /* AIF1TX1MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX1MIX_SRC4_WIDTH 7 /* AIF1TX1MIX_SRC4 - [6:0] */ - -/* - * R1575 (0x627) - AIF1TX1MIX Input 4 Volume - */ -#define WM2200_AIF1TX1MIX_VOL4_MASK 0x00FE /* AIF1TX1MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX1MIX_VOL4_SHIFT 1 /* AIF1TX1MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX1MIX_VOL4_WIDTH 7 /* AIF1TX1MIX_VOL4 - [7:1] */ - -/* - * R1576 (0x628) - AIF1TX2MIX Input 1 Source - */ -#define WM2200_AIF1TX2MIX_SRC1_MASK 0x007F /* AIF1TX2MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX2MIX_SRC1_SHIFT 0 /* AIF1TX2MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX2MIX_SRC1_WIDTH 7 /* AIF1TX2MIX_SRC1 - [6:0] */ - -/* - * R1577 (0x629) - AIF1TX2MIX Input 1 Volume - */ -#define WM2200_AIF1TX2MIX_VOL1_MASK 0x00FE /* AIF1TX2MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX2MIX_VOL1_SHIFT 1 /* AIF1TX2MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX2MIX_VOL1_WIDTH 7 /* AIF1TX2MIX_VOL1 - [7:1] */ - -/* - * R1578 (0x62A) - AIF1TX2MIX Input 2 Source - */ -#define WM2200_AIF1TX2MIX_SRC2_MASK 0x007F /* AIF1TX2MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX2MIX_SRC2_SHIFT 0 /* AIF1TX2MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX2MIX_SRC2_WIDTH 7 /* AIF1TX2MIX_SRC2 - [6:0] */ - -/* - * R1579 (0x62B) - AIF1TX2MIX Input 2 Volume - */ -#define WM2200_AIF1TX2MIX_VOL2_MASK 0x00FE /* AIF1TX2MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX2MIX_VOL2_SHIFT 1 /* AIF1TX2MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX2MIX_VOL2_WIDTH 7 /* AIF1TX2MIX_VOL2 - [7:1] */ - -/* - * R1580 (0x62C) - AIF1TX2MIX Input 3 Source - */ -#define WM2200_AIF1TX2MIX_SRC3_MASK 0x007F /* AIF1TX2MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX2MIX_SRC3_SHIFT 0 /* AIF1TX2MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX2MIX_SRC3_WIDTH 7 /* AIF1TX2MIX_SRC3 - [6:0] */ - -/* - * R1581 (0x62D) - AIF1TX2MIX Input 3 Volume - */ -#define WM2200_AIF1TX2MIX_VOL3_MASK 0x00FE /* AIF1TX2MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX2MIX_VOL3_SHIFT 1 /* AIF1TX2MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX2MIX_VOL3_WIDTH 7 /* AIF1TX2MIX_VOL3 - [7:1] */ - -/* - * R1582 (0x62E) - AIF1TX2MIX Input 4 Source - */ -#define WM2200_AIF1TX2MIX_SRC4_MASK 0x007F /* AIF1TX2MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX2MIX_SRC4_SHIFT 0 /* AIF1TX2MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX2MIX_SRC4_WIDTH 7 /* AIF1TX2MIX_SRC4 - [6:0] */ - -/* - * R1583 (0x62F) - AIF1TX2MIX Input 4 Volume - */ -#define WM2200_AIF1TX2MIX_VOL4_MASK 0x00FE /* AIF1TX2MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX2MIX_VOL4_SHIFT 1 /* AIF1TX2MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX2MIX_VOL4_WIDTH 7 /* AIF1TX2MIX_VOL4 - [7:1] */ - -/* - * R1584 (0x630) - AIF1TX3MIX Input 1 Source - */ -#define WM2200_AIF1TX3MIX_SRC1_MASK 0x007F /* AIF1TX3MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX3MIX_SRC1_SHIFT 0 /* AIF1TX3MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX3MIX_SRC1_WIDTH 7 /* AIF1TX3MIX_SRC1 - [6:0] */ - -/* - * R1585 (0x631) - AIF1TX3MIX Input 1 Volume - */ -#define WM2200_AIF1TX3MIX_VOL1_MASK 0x00FE /* AIF1TX3MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX3MIX_VOL1_SHIFT 1 /* AIF1TX3MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX3MIX_VOL1_WIDTH 7 /* AIF1TX3MIX_VOL1 - [7:1] */ - -/* - * R1586 (0x632) - AIF1TX3MIX Input 2 Source - */ -#define WM2200_AIF1TX3MIX_SRC2_MASK 0x007F /* AIF1TX3MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX3MIX_SRC2_SHIFT 0 /* AIF1TX3MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX3MIX_SRC2_WIDTH 7 /* AIF1TX3MIX_SRC2 - [6:0] */ - -/* - * R1587 (0x633) - AIF1TX3MIX Input 2 Volume - */ -#define WM2200_AIF1TX3MIX_VOL2_MASK 0x00FE /* AIF1TX3MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX3MIX_VOL2_SHIFT 1 /* AIF1TX3MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX3MIX_VOL2_WIDTH 7 /* AIF1TX3MIX_VOL2 - [7:1] */ - -/* - * R1588 (0x634) - AIF1TX3MIX Input 3 Source - */ -#define WM2200_AIF1TX3MIX_SRC3_MASK 0x007F /* AIF1TX3MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX3MIX_SRC3_SHIFT 0 /* AIF1TX3MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX3MIX_SRC3_WIDTH 7 /* AIF1TX3MIX_SRC3 - [6:0] */ - -/* - * R1589 (0x635) - AIF1TX3MIX Input 3 Volume - */ -#define WM2200_AIF1TX3MIX_VOL3_MASK 0x00FE /* AIF1TX3MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX3MIX_VOL3_SHIFT 1 /* AIF1TX3MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX3MIX_VOL3_WIDTH 7 /* AIF1TX3MIX_VOL3 - [7:1] */ - -/* - * R1590 (0x636) - AIF1TX3MIX Input 4 Source - */ -#define WM2200_AIF1TX3MIX_SRC4_MASK 0x007F /* AIF1TX3MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX3MIX_SRC4_SHIFT 0 /* AIF1TX3MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX3MIX_SRC4_WIDTH 7 /* AIF1TX3MIX_SRC4 - [6:0] */ - -/* - * R1591 (0x637) - AIF1TX3MIX Input 4 Volume - */ -#define WM2200_AIF1TX3MIX_VOL4_MASK 0x00FE /* AIF1TX3MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX3MIX_VOL4_SHIFT 1 /* AIF1TX3MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX3MIX_VOL4_WIDTH 7 /* AIF1TX3MIX_VOL4 - [7:1] */ - -/* - * R1592 (0x638) - AIF1TX4MIX Input 1 Source - */ -#define WM2200_AIF1TX4MIX_SRC1_MASK 0x007F /* AIF1TX4MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX4MIX_SRC1_SHIFT 0 /* AIF1TX4MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX4MIX_SRC1_WIDTH 7 /* AIF1TX4MIX_SRC1 - [6:0] */ - -/* - * R1593 (0x639) - AIF1TX4MIX Input 1 Volume - */ -#define WM2200_AIF1TX4MIX_VOL1_MASK 0x00FE /* AIF1TX4MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX4MIX_VOL1_SHIFT 1 /* AIF1TX4MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX4MIX_VOL1_WIDTH 7 /* AIF1TX4MIX_VOL1 - [7:1] */ - -/* - * R1594 (0x63A) - AIF1TX4MIX Input 2 Source - */ -#define WM2200_AIF1TX4MIX_SRC2_MASK 0x007F /* AIF1TX4MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX4MIX_SRC2_SHIFT 0 /* AIF1TX4MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX4MIX_SRC2_WIDTH 7 /* AIF1TX4MIX_SRC2 - [6:0] */ - -/* - * R1595 (0x63B) - AIF1TX4MIX Input 2 Volume - */ -#define WM2200_AIF1TX4MIX_VOL2_MASK 0x00FE /* AIF1TX4MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX4MIX_VOL2_SHIFT 1 /* AIF1TX4MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX4MIX_VOL2_WIDTH 7 /* AIF1TX4MIX_VOL2 - [7:1] */ - -/* - * R1596 (0x63C) - AIF1TX4MIX Input 3 Source - */ -#define WM2200_AIF1TX4MIX_SRC3_MASK 0x007F /* AIF1TX4MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX4MIX_SRC3_SHIFT 0 /* AIF1TX4MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX4MIX_SRC3_WIDTH 7 /* AIF1TX4MIX_SRC3 - [6:0] */ - -/* - * R1597 (0x63D) - AIF1TX4MIX Input 3 Volume - */ -#define WM2200_AIF1TX4MIX_VOL3_MASK 0x00FE /* AIF1TX4MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX4MIX_VOL3_SHIFT 1 /* AIF1TX4MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX4MIX_VOL3_WIDTH 7 /* AIF1TX4MIX_VOL3 - [7:1] */ - -/* - * R1598 (0x63E) - AIF1TX4MIX Input 4 Source - */ -#define WM2200_AIF1TX4MIX_SRC4_MASK 0x007F /* AIF1TX4MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX4MIX_SRC4_SHIFT 0 /* AIF1TX4MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX4MIX_SRC4_WIDTH 7 /* AIF1TX4MIX_SRC4 - [6:0] */ - -/* - * R1599 (0x63F) - AIF1TX4MIX Input 4 Volume - */ -#define WM2200_AIF1TX4MIX_VOL4_MASK 0x00FE /* AIF1TX4MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX4MIX_VOL4_SHIFT 1 /* AIF1TX4MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX4MIX_VOL4_WIDTH 7 /* AIF1TX4MIX_VOL4 - [7:1] */ - -/* - * R1600 (0x640) - AIF1TX5MIX Input 1 Source - */ -#define WM2200_AIF1TX5MIX_SRC1_MASK 0x007F /* AIF1TX5MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX5MIX_SRC1_SHIFT 0 /* AIF1TX5MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX5MIX_SRC1_WIDTH 7 /* AIF1TX5MIX_SRC1 - [6:0] */ - -/* - * R1601 (0x641) - AIF1TX5MIX Input 1 Volume - */ -#define WM2200_AIF1TX5MIX_VOL1_MASK 0x00FE /* AIF1TX5MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX5MIX_VOL1_SHIFT 1 /* AIF1TX5MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX5MIX_VOL1_WIDTH 7 /* AIF1TX5MIX_VOL1 - [7:1] */ - -/* - * R1602 (0x642) - AIF1TX5MIX Input 2 Source - */ -#define WM2200_AIF1TX5MIX_SRC2_MASK 0x007F /* AIF1TX5MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX5MIX_SRC2_SHIFT 0 /* AIF1TX5MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX5MIX_SRC2_WIDTH 7 /* AIF1TX5MIX_SRC2 - [6:0] */ - -/* - * R1603 (0x643) - AIF1TX5MIX Input 2 Volume - */ -#define WM2200_AIF1TX5MIX_VOL2_MASK 0x00FE /* AIF1TX5MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX5MIX_VOL2_SHIFT 1 /* AIF1TX5MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX5MIX_VOL2_WIDTH 7 /* AIF1TX5MIX_VOL2 - [7:1] */ - -/* - * R1604 (0x644) - AIF1TX5MIX Input 3 Source - */ -#define WM2200_AIF1TX5MIX_SRC3_MASK 0x007F /* AIF1TX5MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX5MIX_SRC3_SHIFT 0 /* AIF1TX5MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX5MIX_SRC3_WIDTH 7 /* AIF1TX5MIX_SRC3 - [6:0] */ - -/* - * R1605 (0x645) - AIF1TX5MIX Input 3 Volume - */ -#define WM2200_AIF1TX5MIX_VOL3_MASK 0x00FE /* AIF1TX5MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX5MIX_VOL3_SHIFT 1 /* AIF1TX5MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX5MIX_VOL3_WIDTH 7 /* AIF1TX5MIX_VOL3 - [7:1] */ - -/* - * R1606 (0x646) - AIF1TX5MIX Input 4 Source - */ -#define WM2200_AIF1TX5MIX_SRC4_MASK 0x007F /* AIF1TX5MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX5MIX_SRC4_SHIFT 0 /* AIF1TX5MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX5MIX_SRC4_WIDTH 7 /* AIF1TX5MIX_SRC4 - [6:0] */ - -/* - * R1607 (0x647) - AIF1TX5MIX Input 4 Volume - */ -#define WM2200_AIF1TX5MIX_VOL4_MASK 0x00FE /* AIF1TX5MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX5MIX_VOL4_SHIFT 1 /* AIF1TX5MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX5MIX_VOL4_WIDTH 7 /* AIF1TX5MIX_VOL4 - [7:1] */ - -/* - * R1608 (0x648) - AIF1TX6MIX Input 1 Source - */ -#define WM2200_AIF1TX6MIX_SRC1_MASK 0x007F /* AIF1TX6MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX6MIX_SRC1_SHIFT 0 /* AIF1TX6MIX_SRC1 - [6:0] */ -#define WM2200_AIF1TX6MIX_SRC1_WIDTH 7 /* AIF1TX6MIX_SRC1 - [6:0] */ - -/* - * R1609 (0x649) - AIF1TX6MIX Input 1 Volume - */ -#define WM2200_AIF1TX6MIX_VOL1_MASK 0x00FE /* AIF1TX6MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX6MIX_VOL1_SHIFT 1 /* AIF1TX6MIX_VOL1 - [7:1] */ -#define WM2200_AIF1TX6MIX_VOL1_WIDTH 7 /* AIF1TX6MIX_VOL1 - [7:1] */ - -/* - * R1610 (0x64A) - AIF1TX6MIX Input 2 Source - */ -#define WM2200_AIF1TX6MIX_SRC2_MASK 0x007F /* AIF1TX6MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX6MIX_SRC2_SHIFT 0 /* AIF1TX6MIX_SRC2 - [6:0] */ -#define WM2200_AIF1TX6MIX_SRC2_WIDTH 7 /* AIF1TX6MIX_SRC2 - [6:0] */ - -/* - * R1611 (0x64B) - AIF1TX6MIX Input 2 Volume - */ -#define WM2200_AIF1TX6MIX_VOL2_MASK 0x00FE /* AIF1TX6MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX6MIX_VOL2_SHIFT 1 /* AIF1TX6MIX_VOL2 - [7:1] */ -#define WM2200_AIF1TX6MIX_VOL2_WIDTH 7 /* AIF1TX6MIX_VOL2 - [7:1] */ - -/* - * R1612 (0x64C) - AIF1TX6MIX Input 3 Source - */ -#define WM2200_AIF1TX6MIX_SRC3_MASK 0x007F /* AIF1TX6MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX6MIX_SRC3_SHIFT 0 /* AIF1TX6MIX_SRC3 - [6:0] */ -#define WM2200_AIF1TX6MIX_SRC3_WIDTH 7 /* AIF1TX6MIX_SRC3 - [6:0] */ - -/* - * R1613 (0x64D) - AIF1TX6MIX Input 3 Volume - */ -#define WM2200_AIF1TX6MIX_VOL3_MASK 0x00FE /* AIF1TX6MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX6MIX_VOL3_SHIFT 1 /* AIF1TX6MIX_VOL3 - [7:1] */ -#define WM2200_AIF1TX6MIX_VOL3_WIDTH 7 /* AIF1TX6MIX_VOL3 - [7:1] */ - -/* - * R1614 (0x64E) - AIF1TX6MIX Input 4 Source - */ -#define WM2200_AIF1TX6MIX_SRC4_MASK 0x007F /* AIF1TX6MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX6MIX_SRC4_SHIFT 0 /* AIF1TX6MIX_SRC4 - [6:0] */ -#define WM2200_AIF1TX6MIX_SRC4_WIDTH 7 /* AIF1TX6MIX_SRC4 - [6:0] */ - -/* - * R1615 (0x64F) - AIF1TX6MIX Input 4 Volume - */ -#define WM2200_AIF1TX6MIX_VOL4_MASK 0x00FE /* AIF1TX6MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX6MIX_VOL4_SHIFT 1 /* AIF1TX6MIX_VOL4 - [7:1] */ -#define WM2200_AIF1TX6MIX_VOL4_WIDTH 7 /* AIF1TX6MIX_VOL4 - [7:1] */ - -/* - * R1616 (0x650) - EQLMIX Input 1 Source - */ -#define WM2200_EQLMIX_SRC1_MASK 0x007F /* EQLMIX_SRC1 - [6:0] */ -#define WM2200_EQLMIX_SRC1_SHIFT 0 /* EQLMIX_SRC1 - [6:0] */ -#define WM2200_EQLMIX_SRC1_WIDTH 7 /* EQLMIX_SRC1 - [6:0] */ - -/* - * R1617 (0x651) - EQLMIX Input 1 Volume - */ -#define WM2200_EQLMIX_VOL1_MASK 0x00FE /* EQLMIX_VOL1 - [7:1] */ -#define WM2200_EQLMIX_VOL1_SHIFT 1 /* EQLMIX_VOL1 - [7:1] */ -#define WM2200_EQLMIX_VOL1_WIDTH 7 /* EQLMIX_VOL1 - [7:1] */ - -/* - * R1618 (0x652) - EQLMIX Input 2 Source - */ -#define WM2200_EQLMIX_SRC2_MASK 0x007F /* EQLMIX_SRC2 - [6:0] */ -#define WM2200_EQLMIX_SRC2_SHIFT 0 /* EQLMIX_SRC2 - [6:0] */ -#define WM2200_EQLMIX_SRC2_WIDTH 7 /* EQLMIX_SRC2 - [6:0] */ - -/* - * R1619 (0x653) - EQLMIX Input 2 Volume - */ -#define WM2200_EQLMIX_VOL2_MASK 0x00FE /* EQLMIX_VOL2 - [7:1] */ -#define WM2200_EQLMIX_VOL2_SHIFT 1 /* EQLMIX_VOL2 - [7:1] */ -#define WM2200_EQLMIX_VOL2_WIDTH 7 /* EQLMIX_VOL2 - [7:1] */ - -/* - * R1620 (0x654) - EQLMIX Input 3 Source - */ -#define WM2200_EQLMIX_SRC3_MASK 0x007F /* EQLMIX_SRC3 - [6:0] */ -#define WM2200_EQLMIX_SRC3_SHIFT 0 /* EQLMIX_SRC3 - [6:0] */ -#define WM2200_EQLMIX_SRC3_WIDTH 7 /* EQLMIX_SRC3 - [6:0] */ - -/* - * R1621 (0x655) - EQLMIX Input 3 Volume - */ -#define WM2200_EQLMIX_VOL3_MASK 0x00FE /* EQLMIX_VOL3 - [7:1] */ -#define WM2200_EQLMIX_VOL3_SHIFT 1 /* EQLMIX_VOL3 - [7:1] */ -#define WM2200_EQLMIX_VOL3_WIDTH 7 /* EQLMIX_VOL3 - [7:1] */ - -/* - * R1622 (0x656) - EQLMIX Input 4 Source - */ -#define WM2200_EQLMIX_SRC4_MASK 0x007F /* EQLMIX_SRC4 - [6:0] */ -#define WM2200_EQLMIX_SRC4_SHIFT 0 /* EQLMIX_SRC4 - [6:0] */ -#define WM2200_EQLMIX_SRC4_WIDTH 7 /* EQLMIX_SRC4 - [6:0] */ - -/* - * R1623 (0x657) - EQLMIX Input 4 Volume - */ -#define WM2200_EQLMIX_VOL4_MASK 0x00FE /* EQLMIX_VOL4 - [7:1] */ -#define WM2200_EQLMIX_VOL4_SHIFT 1 /* EQLMIX_VOL4 - [7:1] */ -#define WM2200_EQLMIX_VOL4_WIDTH 7 /* EQLMIX_VOL4 - [7:1] */ - -/* - * R1624 (0x658) - EQRMIX Input 1 Source - */ -#define WM2200_EQRMIX_SRC1_MASK 0x007F /* EQRMIX_SRC1 - [6:0] */ -#define WM2200_EQRMIX_SRC1_SHIFT 0 /* EQRMIX_SRC1 - [6:0] */ -#define WM2200_EQRMIX_SRC1_WIDTH 7 /* EQRMIX_SRC1 - [6:0] */ - -/* - * R1625 (0x659) - EQRMIX Input 1 Volume - */ -#define WM2200_EQRMIX_VOL1_MASK 0x00FE /* EQRMIX_VOL1 - [7:1] */ -#define WM2200_EQRMIX_VOL1_SHIFT 1 /* EQRMIX_VOL1 - [7:1] */ -#define WM2200_EQRMIX_VOL1_WIDTH 7 /* EQRMIX_VOL1 - [7:1] */ - -/* - * R1626 (0x65A) - EQRMIX Input 2 Source - */ -#define WM2200_EQRMIX_SRC2_MASK 0x007F /* EQRMIX_SRC2 - [6:0] */ -#define WM2200_EQRMIX_SRC2_SHIFT 0 /* EQRMIX_SRC2 - [6:0] */ -#define WM2200_EQRMIX_SRC2_WIDTH 7 /* EQRMIX_SRC2 - [6:0] */ - -/* - * R1627 (0x65B) - EQRMIX Input 2 Volume - */ -#define WM2200_EQRMIX_VOL2_MASK 0x00FE /* EQRMIX_VOL2 - [7:1] */ -#define WM2200_EQRMIX_VOL2_SHIFT 1 /* EQRMIX_VOL2 - [7:1] */ -#define WM2200_EQRMIX_VOL2_WIDTH 7 /* EQRMIX_VOL2 - [7:1] */ - -/* - * R1628 (0x65C) - EQRMIX Input 3 Source - */ -#define WM2200_EQRMIX_SRC3_MASK 0x007F /* EQRMIX_SRC3 - [6:0] */ -#define WM2200_EQRMIX_SRC3_SHIFT 0 /* EQRMIX_SRC3 - [6:0] */ -#define WM2200_EQRMIX_SRC3_WIDTH 7 /* EQRMIX_SRC3 - [6:0] */ - -/* - * R1629 (0x65D) - EQRMIX Input 3 Volume - */ -#define WM2200_EQRMIX_VOL3_MASK 0x00FE /* EQRMIX_VOL3 - [7:1] */ -#define WM2200_EQRMIX_VOL3_SHIFT 1 /* EQRMIX_VOL3 - [7:1] */ -#define WM2200_EQRMIX_VOL3_WIDTH 7 /* EQRMIX_VOL3 - [7:1] */ - -/* - * R1630 (0x65E) - EQRMIX Input 4 Source - */ -#define WM2200_EQRMIX_SRC4_MASK 0x007F /* EQRMIX_SRC4 - [6:0] */ -#define WM2200_EQRMIX_SRC4_SHIFT 0 /* EQRMIX_SRC4 - [6:0] */ -#define WM2200_EQRMIX_SRC4_WIDTH 7 /* EQRMIX_SRC4 - [6:0] */ - -/* - * R1631 (0x65F) - EQRMIX Input 4 Volume - */ -#define WM2200_EQRMIX_VOL4_MASK 0x00FE /* EQRMIX_VOL4 - [7:1] */ -#define WM2200_EQRMIX_VOL4_SHIFT 1 /* EQRMIX_VOL4 - [7:1] */ -#define WM2200_EQRMIX_VOL4_WIDTH 7 /* EQRMIX_VOL4 - [7:1] */ - -/* - * R1632 (0x660) - LHPF1MIX Input 1 Source - */ -#define WM2200_LHPF1MIX_SRC1_MASK 0x007F /* LHPF1MIX_SRC1 - [6:0] */ -#define WM2200_LHPF1MIX_SRC1_SHIFT 0 /* LHPF1MIX_SRC1 - [6:0] */ -#define WM2200_LHPF1MIX_SRC1_WIDTH 7 /* LHPF1MIX_SRC1 - [6:0] */ - -/* - * R1633 (0x661) - LHPF1MIX Input 1 Volume - */ -#define WM2200_LHPF1MIX_VOL1_MASK 0x00FE /* LHPF1MIX_VOL1 - [7:1] */ -#define WM2200_LHPF1MIX_VOL1_SHIFT 1 /* LHPF1MIX_VOL1 - [7:1] */ -#define WM2200_LHPF1MIX_VOL1_WIDTH 7 /* LHPF1MIX_VOL1 - [7:1] */ - -/* - * R1634 (0x662) - LHPF1MIX Input 2 Source - */ -#define WM2200_LHPF1MIX_SRC2_MASK 0x007F /* LHPF1MIX_SRC2 - [6:0] */ -#define WM2200_LHPF1MIX_SRC2_SHIFT 0 /* LHPF1MIX_SRC2 - [6:0] */ -#define WM2200_LHPF1MIX_SRC2_WIDTH 7 /* LHPF1MIX_SRC2 - [6:0] */ - -/* - * R1635 (0x663) - LHPF1MIX Input 2 Volume - */ -#define WM2200_LHPF1MIX_VOL2_MASK 0x00FE /* LHPF1MIX_VOL2 - [7:1] */ -#define WM2200_LHPF1MIX_VOL2_SHIFT 1 /* LHPF1MIX_VOL2 - [7:1] */ -#define WM2200_LHPF1MIX_VOL2_WIDTH 7 /* LHPF1MIX_VOL2 - [7:1] */ - -/* - * R1636 (0x664) - LHPF1MIX Input 3 Source - */ -#define WM2200_LHPF1MIX_SRC3_MASK 0x007F /* LHPF1MIX_SRC3 - [6:0] */ -#define WM2200_LHPF1MIX_SRC3_SHIFT 0 /* LHPF1MIX_SRC3 - [6:0] */ -#define WM2200_LHPF1MIX_SRC3_WIDTH 7 /* LHPF1MIX_SRC3 - [6:0] */ - -/* - * R1637 (0x665) - LHPF1MIX Input 3 Volume - */ -#define WM2200_LHPF1MIX_VOL3_MASK 0x00FE /* LHPF1MIX_VOL3 - [7:1] */ -#define WM2200_LHPF1MIX_VOL3_SHIFT 1 /* LHPF1MIX_VOL3 - [7:1] */ -#define WM2200_LHPF1MIX_VOL3_WIDTH 7 /* LHPF1MIX_VOL3 - [7:1] */ - -/* - * R1638 (0x666) - LHPF1MIX Input 4 Source - */ -#define WM2200_LHPF1MIX_SRC4_MASK 0x007F /* LHPF1MIX_SRC4 - [6:0] */ -#define WM2200_LHPF1MIX_SRC4_SHIFT 0 /* LHPF1MIX_SRC4 - [6:0] */ -#define WM2200_LHPF1MIX_SRC4_WIDTH 7 /* LHPF1MIX_SRC4 - [6:0] */ - -/* - * R1639 (0x667) - LHPF1MIX Input 4 Volume - */ -#define WM2200_LHPF1MIX_VOL4_MASK 0x00FE /* LHPF1MIX_VOL4 - [7:1] */ -#define WM2200_LHPF1MIX_VOL4_SHIFT 1 /* LHPF1MIX_VOL4 - [7:1] */ -#define WM2200_LHPF1MIX_VOL4_WIDTH 7 /* LHPF1MIX_VOL4 - [7:1] */ - -/* - * R1640 (0x668) - LHPF2MIX Input 1 Source - */ -#define WM2200_LHPF2MIX_SRC1_MASK 0x007F /* LHPF2MIX_SRC1 - [6:0] */ -#define WM2200_LHPF2MIX_SRC1_SHIFT 0 /* LHPF2MIX_SRC1 - [6:0] */ -#define WM2200_LHPF2MIX_SRC1_WIDTH 7 /* LHPF2MIX_SRC1 - [6:0] */ - -/* - * R1641 (0x669) - LHPF2MIX Input 1 Volume - */ -#define WM2200_LHPF2MIX_VOL1_MASK 0x00FE /* LHPF2MIX_VOL1 - [7:1] */ -#define WM2200_LHPF2MIX_VOL1_SHIFT 1 /* LHPF2MIX_VOL1 - [7:1] */ -#define WM2200_LHPF2MIX_VOL1_WIDTH 7 /* LHPF2MIX_VOL1 - [7:1] */ - -/* - * R1642 (0x66A) - LHPF2MIX Input 2 Source - */ -#define WM2200_LHPF2MIX_SRC2_MASK 0x007F /* LHPF2MIX_SRC2 - [6:0] */ -#define WM2200_LHPF2MIX_SRC2_SHIFT 0 /* LHPF2MIX_SRC2 - [6:0] */ -#define WM2200_LHPF2MIX_SRC2_WIDTH 7 /* LHPF2MIX_SRC2 - [6:0] */ - -/* - * R1643 (0x66B) - LHPF2MIX Input 2 Volume - */ -#define WM2200_LHPF2MIX_VOL2_MASK 0x00FE /* LHPF2MIX_VOL2 - [7:1] */ -#define WM2200_LHPF2MIX_VOL2_SHIFT 1 /* LHPF2MIX_VOL2 - [7:1] */ -#define WM2200_LHPF2MIX_VOL2_WIDTH 7 /* LHPF2MIX_VOL2 - [7:1] */ - -/* - * R1644 (0x66C) - LHPF2MIX Input 3 Source - */ -#define WM2200_LHPF2MIX_SRC3_MASK 0x007F /* LHPF2MIX_SRC3 - [6:0] */ -#define WM2200_LHPF2MIX_SRC3_SHIFT 0 /* LHPF2MIX_SRC3 - [6:0] */ -#define WM2200_LHPF2MIX_SRC3_WIDTH 7 /* LHPF2MIX_SRC3 - [6:0] */ - -/* - * R1645 (0x66D) - LHPF2MIX Input 3 Volume - */ -#define WM2200_LHPF2MIX_VOL3_MASK 0x00FE /* LHPF2MIX_VOL3 - [7:1] */ -#define WM2200_LHPF2MIX_VOL3_SHIFT 1 /* LHPF2MIX_VOL3 - [7:1] */ -#define WM2200_LHPF2MIX_VOL3_WIDTH 7 /* LHPF2MIX_VOL3 - [7:1] */ - -/* - * R1646 (0x66E) - LHPF2MIX Input 4 Source - */ -#define WM2200_LHPF2MIX_SRC4_MASK 0x007F /* LHPF2MIX_SRC4 - [6:0] */ -#define WM2200_LHPF2MIX_SRC4_SHIFT 0 /* LHPF2MIX_SRC4 - [6:0] */ -#define WM2200_LHPF2MIX_SRC4_WIDTH 7 /* LHPF2MIX_SRC4 - [6:0] */ - -/* - * R1647 (0x66F) - LHPF2MIX Input 4 Volume - */ -#define WM2200_LHPF2MIX_VOL4_MASK 0x00FE /* LHPF2MIX_VOL4 - [7:1] */ -#define WM2200_LHPF2MIX_VOL4_SHIFT 1 /* LHPF2MIX_VOL4 - [7:1] */ -#define WM2200_LHPF2MIX_VOL4_WIDTH 7 /* LHPF2MIX_VOL4 - [7:1] */ - -/* - * R1648 (0x670) - DSP1LMIX Input 1 Source - */ -#define WM2200_DSP1LMIX_SRC1_MASK 0x007F /* DSP1LMIX_SRC1 - [6:0] */ -#define WM2200_DSP1LMIX_SRC1_SHIFT 0 /* DSP1LMIX_SRC1 - [6:0] */ -#define WM2200_DSP1LMIX_SRC1_WIDTH 7 /* DSP1LMIX_SRC1 - [6:0] */ - -/* - * R1649 (0x671) - DSP1LMIX Input 1 Volume - */ -#define WM2200_DSP1LMIX_VOL1_MASK 0x00FE /* DSP1LMIX_VOL1 - [7:1] */ -#define WM2200_DSP1LMIX_VOL1_SHIFT 1 /* DSP1LMIX_VOL1 - [7:1] */ -#define WM2200_DSP1LMIX_VOL1_WIDTH 7 /* DSP1LMIX_VOL1 - [7:1] */ - -/* - * R1650 (0x672) - DSP1LMIX Input 2 Source - */ -#define WM2200_DSP1LMIX_SRC2_MASK 0x007F /* DSP1LMIX_SRC2 - [6:0] */ -#define WM2200_DSP1LMIX_SRC2_SHIFT 0 /* DSP1LMIX_SRC2 - [6:0] */ -#define WM2200_DSP1LMIX_SRC2_WIDTH 7 /* DSP1LMIX_SRC2 - [6:0] */ - -/* - * R1651 (0x673) - DSP1LMIX Input 2 Volume - */ -#define WM2200_DSP1LMIX_VOL2_MASK 0x00FE /* DSP1LMIX_VOL2 - [7:1] */ -#define WM2200_DSP1LMIX_VOL2_SHIFT 1 /* DSP1LMIX_VOL2 - [7:1] */ -#define WM2200_DSP1LMIX_VOL2_WIDTH 7 /* DSP1LMIX_VOL2 - [7:1] */ - -/* - * R1652 (0x674) - DSP1LMIX Input 3 Source - */ -#define WM2200_DSP1LMIX_SRC3_MASK 0x007F /* DSP1LMIX_SRC3 - [6:0] */ -#define WM2200_DSP1LMIX_SRC3_SHIFT 0 /* DSP1LMIX_SRC3 - [6:0] */ -#define WM2200_DSP1LMIX_SRC3_WIDTH 7 /* DSP1LMIX_SRC3 - [6:0] */ - -/* - * R1653 (0x675) - DSP1LMIX Input 3 Volume - */ -#define WM2200_DSP1LMIX_VOL3_MASK 0x00FE /* DSP1LMIX_VOL3 - [7:1] */ -#define WM2200_DSP1LMIX_VOL3_SHIFT 1 /* DSP1LMIX_VOL3 - [7:1] */ -#define WM2200_DSP1LMIX_VOL3_WIDTH 7 /* DSP1LMIX_VOL3 - [7:1] */ - -/* - * R1654 (0x676) - DSP1LMIX Input 4 Source - */ -#define WM2200_DSP1LMIX_SRC4_MASK 0x007F /* DSP1LMIX_SRC4 - [6:0] */ -#define WM2200_DSP1LMIX_SRC4_SHIFT 0 /* DSP1LMIX_SRC4 - [6:0] */ -#define WM2200_DSP1LMIX_SRC4_WIDTH 7 /* DSP1LMIX_SRC4 - [6:0] */ - -/* - * R1655 (0x677) - DSP1LMIX Input 4 Volume - */ -#define WM2200_DSP1LMIX_VOL4_MASK 0x00FE /* DSP1LMIX_VOL4 - [7:1] */ -#define WM2200_DSP1LMIX_VOL4_SHIFT 1 /* DSP1LMIX_VOL4 - [7:1] */ -#define WM2200_DSP1LMIX_VOL4_WIDTH 7 /* DSP1LMIX_VOL4 - [7:1] */ - -/* - * R1656 (0x678) - DSP1RMIX Input 1 Source - */ -#define WM2200_DSP1RMIX_SRC1_MASK 0x007F /* DSP1RMIX_SRC1 - [6:0] */ -#define WM2200_DSP1RMIX_SRC1_SHIFT 0 /* DSP1RMIX_SRC1 - [6:0] */ -#define WM2200_DSP1RMIX_SRC1_WIDTH 7 /* DSP1RMIX_SRC1 - [6:0] */ - -/* - * R1657 (0x679) - DSP1RMIX Input 1 Volume - */ -#define WM2200_DSP1RMIX_VOL1_MASK 0x00FE /* DSP1RMIX_VOL1 - [7:1] */ -#define WM2200_DSP1RMIX_VOL1_SHIFT 1 /* DSP1RMIX_VOL1 - [7:1] */ -#define WM2200_DSP1RMIX_VOL1_WIDTH 7 /* DSP1RMIX_VOL1 - [7:1] */ - -/* - * R1658 (0x67A) - DSP1RMIX Input 2 Source - */ -#define WM2200_DSP1RMIX_SRC2_MASK 0x007F /* DSP1RMIX_SRC2 - [6:0] */ -#define WM2200_DSP1RMIX_SRC2_SHIFT 0 /* DSP1RMIX_SRC2 - [6:0] */ -#define WM2200_DSP1RMIX_SRC2_WIDTH 7 /* DSP1RMIX_SRC2 - [6:0] */ - -/* - * R1659 (0x67B) - DSP1RMIX Input 2 Volume - */ -#define WM2200_DSP1RMIX_VOL2_MASK 0x00FE /* DSP1RMIX_VOL2 - [7:1] */ -#define WM2200_DSP1RMIX_VOL2_SHIFT 1 /* DSP1RMIX_VOL2 - [7:1] */ -#define WM2200_DSP1RMIX_VOL2_WIDTH 7 /* DSP1RMIX_VOL2 - [7:1] */ - -/* - * R1660 (0x67C) - DSP1RMIX Input 3 Source - */ -#define WM2200_DSP1RMIX_SRC3_MASK 0x007F /* DSP1RMIX_SRC3 - [6:0] */ -#define WM2200_DSP1RMIX_SRC3_SHIFT 0 /* DSP1RMIX_SRC3 - [6:0] */ -#define WM2200_DSP1RMIX_SRC3_WIDTH 7 /* DSP1RMIX_SRC3 - [6:0] */ - -/* - * R1661 (0x67D) - DSP1RMIX Input 3 Volume - */ -#define WM2200_DSP1RMIX_VOL3_MASK 0x00FE /* DSP1RMIX_VOL3 - [7:1] */ -#define WM2200_DSP1RMIX_VOL3_SHIFT 1 /* DSP1RMIX_VOL3 - [7:1] */ -#define WM2200_DSP1RMIX_VOL3_WIDTH 7 /* DSP1RMIX_VOL3 - [7:1] */ - -/* - * R1662 (0x67E) - DSP1RMIX Input 4 Source - */ -#define WM2200_DSP1RMIX_SRC4_MASK 0x007F /* DSP1RMIX_SRC4 - [6:0] */ -#define WM2200_DSP1RMIX_SRC4_SHIFT 0 /* DSP1RMIX_SRC4 - [6:0] */ -#define WM2200_DSP1RMIX_SRC4_WIDTH 7 /* DSP1RMIX_SRC4 - [6:0] */ - -/* - * R1663 (0x67F) - DSP1RMIX Input 4 Volume - */ -#define WM2200_DSP1RMIX_VOL4_MASK 0x00FE /* DSP1RMIX_VOL4 - [7:1] */ -#define WM2200_DSP1RMIX_VOL4_SHIFT 1 /* DSP1RMIX_VOL4 - [7:1] */ -#define WM2200_DSP1RMIX_VOL4_WIDTH 7 /* DSP1RMIX_VOL4 - [7:1] */ - -/* - * R1664 (0x680) - DSP1AUX1MIX Input 1 Source - */ -#define WM2200_DSP1AUX1MIX_SRC1_MASK 0x007F /* DSP1AUX1MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX1MIX_SRC1_SHIFT 0 /* DSP1AUX1MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX1MIX_SRC1_WIDTH 7 /* DSP1AUX1MIX_SRC1 - [6:0] */ - -/* - * R1665 (0x681) - DSP1AUX2MIX Input 1 Source - */ -#define WM2200_DSP1AUX2MIX_SRC1_MASK 0x007F /* DSP1AUX2MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX2MIX_SRC1_SHIFT 0 /* DSP1AUX2MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX2MIX_SRC1_WIDTH 7 /* DSP1AUX2MIX_SRC1 - [6:0] */ - -/* - * R1666 (0x682) - DSP1AUX3MIX Input 1 Source - */ -#define WM2200_DSP1AUX3MIX_SRC1_MASK 0x007F /* DSP1AUX3MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX3MIX_SRC1_SHIFT 0 /* DSP1AUX3MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX3MIX_SRC1_WIDTH 7 /* DSP1AUX3MIX_SRC1 - [6:0] */ - -/* - * R1667 (0x683) - DSP1AUX4MIX Input 1 Source - */ -#define WM2200_DSP1AUX4MIX_SRC1_MASK 0x007F /* DSP1AUX4MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX4MIX_SRC1_SHIFT 0 /* DSP1AUX4MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX4MIX_SRC1_WIDTH 7 /* DSP1AUX4MIX_SRC1 - [6:0] */ - -/* - * R1668 (0x684) - DSP1AUX5MIX Input 1 Source - */ -#define WM2200_DSP1AUX5MIX_SRC1_MASK 0x007F /* DSP1AUX5MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX5MIX_SRC1_SHIFT 0 /* DSP1AUX5MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX5MIX_SRC1_WIDTH 7 /* DSP1AUX5MIX_SRC1 - [6:0] */ - -/* - * R1669 (0x685) - DSP1AUX6MIX Input 1 Source - */ -#define WM2200_DSP1AUX6MIX_SRC1_MASK 0x007F /* DSP1AUX6MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX6MIX_SRC1_SHIFT 0 /* DSP1AUX6MIX_SRC1 - [6:0] */ -#define WM2200_DSP1AUX6MIX_SRC1_WIDTH 7 /* DSP1AUX6MIX_SRC1 - [6:0] */ - -/* - * R1670 (0x686) - DSP2LMIX Input 1 Source - */ -#define WM2200_DSP2LMIX_SRC1_MASK 0x007F /* DSP2LMIX_SRC1 - [6:0] */ -#define WM2200_DSP2LMIX_SRC1_SHIFT 0 /* DSP2LMIX_SRC1 - [6:0] */ -#define WM2200_DSP2LMIX_SRC1_WIDTH 7 /* DSP2LMIX_SRC1 - [6:0] */ - -/* - * R1671 (0x687) - DSP2LMIX Input 1 Volume - */ -#define WM2200_DSP2LMIX_VOL1_MASK 0x00FE /* DSP2LMIX_VOL1 - [7:1] */ -#define WM2200_DSP2LMIX_VOL1_SHIFT 1 /* DSP2LMIX_VOL1 - [7:1] */ -#define WM2200_DSP2LMIX_VOL1_WIDTH 7 /* DSP2LMIX_VOL1 - [7:1] */ - -/* - * R1672 (0x688) - DSP2LMIX Input 2 Source - */ -#define WM2200_DSP2LMIX_SRC2_MASK 0x007F /* DSP2LMIX_SRC2 - [6:0] */ -#define WM2200_DSP2LMIX_SRC2_SHIFT 0 /* DSP2LMIX_SRC2 - [6:0] */ -#define WM2200_DSP2LMIX_SRC2_WIDTH 7 /* DSP2LMIX_SRC2 - [6:0] */ - -/* - * R1673 (0x689) - DSP2LMIX Input 2 Volume - */ -#define WM2200_DSP2LMIX_VOL2_MASK 0x00FE /* DSP2LMIX_VOL2 - [7:1] */ -#define WM2200_DSP2LMIX_VOL2_SHIFT 1 /* DSP2LMIX_VOL2 - [7:1] */ -#define WM2200_DSP2LMIX_VOL2_WIDTH 7 /* DSP2LMIX_VOL2 - [7:1] */ - -/* - * R1674 (0x68A) - DSP2LMIX Input 3 Source - */ -#define WM2200_DSP2LMIX_SRC3_MASK 0x007F /* DSP2LMIX_SRC3 - [6:0] */ -#define WM2200_DSP2LMIX_SRC3_SHIFT 0 /* DSP2LMIX_SRC3 - [6:0] */ -#define WM2200_DSP2LMIX_SRC3_WIDTH 7 /* DSP2LMIX_SRC3 - [6:0] */ - -/* - * R1675 (0x68B) - DSP2LMIX Input 3 Volume - */ -#define WM2200_DSP2LMIX_VOL3_MASK 0x00FE /* DSP2LMIX_VOL3 - [7:1] */ -#define WM2200_DSP2LMIX_VOL3_SHIFT 1 /* DSP2LMIX_VOL3 - [7:1] */ -#define WM2200_DSP2LMIX_VOL3_WIDTH 7 /* DSP2LMIX_VOL3 - [7:1] */ - -/* - * R1676 (0x68C) - DSP2LMIX Input 4 Source - */ -#define WM2200_DSP2LMIX_SRC4_MASK 0x007F /* DSP2LMIX_SRC4 - [6:0] */ -#define WM2200_DSP2LMIX_SRC4_SHIFT 0 /* DSP2LMIX_SRC4 - [6:0] */ -#define WM2200_DSP2LMIX_SRC4_WIDTH 7 /* DSP2LMIX_SRC4 - [6:0] */ - -/* - * R1677 (0x68D) - DSP2LMIX Input 4 Volume - */ -#define WM2200_DSP2LMIX_VOL4_MASK 0x00FE /* DSP2LMIX_VOL4 - [7:1] */ -#define WM2200_DSP2LMIX_VOL4_SHIFT 1 /* DSP2LMIX_VOL4 - [7:1] */ -#define WM2200_DSP2LMIX_VOL4_WIDTH 7 /* DSP2LMIX_VOL4 - [7:1] */ - -/* - * R1678 (0x68E) - DSP2RMIX Input 1 Source - */ -#define WM2200_DSP2RMIX_SRC1_MASK 0x007F /* DSP2RMIX_SRC1 - [6:0] */ -#define WM2200_DSP2RMIX_SRC1_SHIFT 0 /* DSP2RMIX_SRC1 - [6:0] */ -#define WM2200_DSP2RMIX_SRC1_WIDTH 7 /* DSP2RMIX_SRC1 - [6:0] */ - -/* - * R1679 (0x68F) - DSP2RMIX Input 1 Volume - */ -#define WM2200_DSP2RMIX_VOL1_MASK 0x00FE /* DSP2RMIX_VOL1 - [7:1] */ -#define WM2200_DSP2RMIX_VOL1_SHIFT 1 /* DSP2RMIX_VOL1 - [7:1] */ -#define WM2200_DSP2RMIX_VOL1_WIDTH 7 /* DSP2RMIX_VOL1 - [7:1] */ - -/* - * R1680 (0x690) - DSP2RMIX Input 2 Source - */ -#define WM2200_DSP2RMIX_SRC2_MASK 0x007F /* DSP2RMIX_SRC2 - [6:0] */ -#define WM2200_DSP2RMIX_SRC2_SHIFT 0 /* DSP2RMIX_SRC2 - [6:0] */ -#define WM2200_DSP2RMIX_SRC2_WIDTH 7 /* DSP2RMIX_SRC2 - [6:0] */ - -/* - * R1681 (0x691) - DSP2RMIX Input 2 Volume - */ -#define WM2200_DSP2RMIX_VOL2_MASK 0x00FE /* DSP2RMIX_VOL2 - [7:1] */ -#define WM2200_DSP2RMIX_VOL2_SHIFT 1 /* DSP2RMIX_VOL2 - [7:1] */ -#define WM2200_DSP2RMIX_VOL2_WIDTH 7 /* DSP2RMIX_VOL2 - [7:1] */ - -/* - * R1682 (0x692) - DSP2RMIX Input 3 Source - */ -#define WM2200_DSP2RMIX_SRC3_MASK 0x007F /* DSP2RMIX_SRC3 - [6:0] */ -#define WM2200_DSP2RMIX_SRC3_SHIFT 0 /* DSP2RMIX_SRC3 - [6:0] */ -#define WM2200_DSP2RMIX_SRC3_WIDTH 7 /* DSP2RMIX_SRC3 - [6:0] */ - -/* - * R1683 (0x693) - DSP2RMIX Input 3 Volume - */ -#define WM2200_DSP2RMIX_VOL3_MASK 0x00FE /* DSP2RMIX_VOL3 - [7:1] */ -#define WM2200_DSP2RMIX_VOL3_SHIFT 1 /* DSP2RMIX_VOL3 - [7:1] */ -#define WM2200_DSP2RMIX_VOL3_WIDTH 7 /* DSP2RMIX_VOL3 - [7:1] */ - -/* - * R1684 (0x694) - DSP2RMIX Input 4 Source - */ -#define WM2200_DSP2RMIX_SRC4_MASK 0x007F /* DSP2RMIX_SRC4 - [6:0] */ -#define WM2200_DSP2RMIX_SRC4_SHIFT 0 /* DSP2RMIX_SRC4 - [6:0] */ -#define WM2200_DSP2RMIX_SRC4_WIDTH 7 /* DSP2RMIX_SRC4 - [6:0] */ - -/* - * R1685 (0x695) - DSP2RMIX Input 4 Volume - */ -#define WM2200_DSP2RMIX_VOL4_MASK 0x00FE /* DSP2RMIX_VOL4 - [7:1] */ -#define WM2200_DSP2RMIX_VOL4_SHIFT 1 /* DSP2RMIX_VOL4 - [7:1] */ -#define WM2200_DSP2RMIX_VOL4_WIDTH 7 /* DSP2RMIX_VOL4 - [7:1] */ - -/* - * R1686 (0x696) - DSP2AUX1MIX Input 1 Source - */ -#define WM2200_DSP2AUX1MIX_SRC1_MASK 0x007F /* DSP2AUX1MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX1MIX_SRC1_SHIFT 0 /* DSP2AUX1MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX1MIX_SRC1_WIDTH 7 /* DSP2AUX1MIX_SRC1 - [6:0] */ - -/* - * R1687 (0x697) - DSP2AUX2MIX Input 1 Source - */ -#define WM2200_DSP2AUX2MIX_SRC1_MASK 0x007F /* DSP2AUX2MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX2MIX_SRC1_SHIFT 0 /* DSP2AUX2MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX2MIX_SRC1_WIDTH 7 /* DSP2AUX2MIX_SRC1 - [6:0] */ - -/* - * R1688 (0x698) - DSP2AUX3MIX Input 1 Source - */ -#define WM2200_DSP2AUX3MIX_SRC1_MASK 0x007F /* DSP2AUX3MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX3MIX_SRC1_SHIFT 0 /* DSP2AUX3MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX3MIX_SRC1_WIDTH 7 /* DSP2AUX3MIX_SRC1 - [6:0] */ - -/* - * R1689 (0x699) - DSP2AUX4MIX Input 1 Source - */ -#define WM2200_DSP2AUX4MIX_SRC1_MASK 0x007F /* DSP2AUX4MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX4MIX_SRC1_SHIFT 0 /* DSP2AUX4MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX4MIX_SRC1_WIDTH 7 /* DSP2AUX4MIX_SRC1 - [6:0] */ - -/* - * R1690 (0x69A) - DSP2AUX5MIX Input 1 Source - */ -#define WM2200_DSP2AUX5MIX_SRC1_MASK 0x007F /* DSP2AUX5MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX5MIX_SRC1_SHIFT 0 /* DSP2AUX5MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX5MIX_SRC1_WIDTH 7 /* DSP2AUX5MIX_SRC1 - [6:0] */ - -/* - * R1691 (0x69B) - DSP2AUX6MIX Input 1 Source - */ -#define WM2200_DSP2AUX6MIX_SRC1_MASK 0x007F /* DSP2AUX6MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX6MIX_SRC1_SHIFT 0 /* DSP2AUX6MIX_SRC1 - [6:0] */ -#define WM2200_DSP2AUX6MIX_SRC1_WIDTH 7 /* DSP2AUX6MIX_SRC1 - [6:0] */ - -/* - * R1792 (0x700) - GPIO CTRL 1 - */ -#define WM2200_GP1_DIR 0x8000 /* GP1_DIR */ -#define WM2200_GP1_DIR_MASK 0x8000 /* GP1_DIR */ -#define WM2200_GP1_DIR_SHIFT 15 /* GP1_DIR */ -#define WM2200_GP1_DIR_WIDTH 1 /* GP1_DIR */ -#define WM2200_GP1_PU 0x4000 /* GP1_PU */ -#define WM2200_GP1_PU_MASK 0x4000 /* GP1_PU */ -#define WM2200_GP1_PU_SHIFT 14 /* GP1_PU */ -#define WM2200_GP1_PU_WIDTH 1 /* GP1_PU */ -#define WM2200_GP1_PD 0x2000 /* GP1_PD */ -#define WM2200_GP1_PD_MASK 0x2000 /* GP1_PD */ -#define WM2200_GP1_PD_SHIFT 13 /* GP1_PD */ -#define WM2200_GP1_PD_WIDTH 1 /* GP1_PD */ -#define WM2200_GP1_POL 0x0400 /* GP1_POL */ -#define WM2200_GP1_POL_MASK 0x0400 /* GP1_POL */ -#define WM2200_GP1_POL_SHIFT 10 /* GP1_POL */ -#define WM2200_GP1_POL_WIDTH 1 /* GP1_POL */ -#define WM2200_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */ -#define WM2200_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */ -#define WM2200_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */ -#define WM2200_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */ -#define WM2200_GP1_DB 0x0100 /* GP1_DB */ -#define WM2200_GP1_DB_MASK 0x0100 /* GP1_DB */ -#define WM2200_GP1_DB_SHIFT 8 /* GP1_DB */ -#define WM2200_GP1_DB_WIDTH 1 /* GP1_DB */ -#define WM2200_GP1_LVL 0x0040 /* GP1_LVL */ -#define WM2200_GP1_LVL_MASK 0x0040 /* GP1_LVL */ -#define WM2200_GP1_LVL_SHIFT 6 /* GP1_LVL */ -#define WM2200_GP1_LVL_WIDTH 1 /* GP1_LVL */ -#define WM2200_GP1_FN_MASK 0x003F /* GP1_FN - [5:0] */ -#define WM2200_GP1_FN_SHIFT 0 /* GP1_FN - [5:0] */ -#define WM2200_GP1_FN_WIDTH 6 /* GP1_FN - [5:0] */ - -/* - * R1793 (0x701) - GPIO CTRL 2 - */ -#define WM2200_GP2_DIR 0x8000 /* GP2_DIR */ -#define WM2200_GP2_DIR_MASK 0x8000 /* GP2_DIR */ -#define WM2200_GP2_DIR_SHIFT 15 /* GP2_DIR */ -#define WM2200_GP2_DIR_WIDTH 1 /* GP2_DIR */ -#define WM2200_GP2_PU 0x4000 /* GP2_PU */ -#define WM2200_GP2_PU_MASK 0x4000 /* GP2_PU */ -#define WM2200_GP2_PU_SHIFT 14 /* GP2_PU */ -#define WM2200_GP2_PU_WIDTH 1 /* GP2_PU */ -#define WM2200_GP2_PD 0x2000 /* GP2_PD */ -#define WM2200_GP2_PD_MASK 0x2000 /* GP2_PD */ -#define WM2200_GP2_PD_SHIFT 13 /* GP2_PD */ -#define WM2200_GP2_PD_WIDTH 1 /* GP2_PD */ -#define WM2200_GP2_POL 0x0400 /* GP2_POL */ -#define WM2200_GP2_POL_MASK 0x0400 /* GP2_POL */ -#define WM2200_GP2_POL_SHIFT 10 /* GP2_POL */ -#define WM2200_GP2_POL_WIDTH 1 /* GP2_POL */ -#define WM2200_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */ -#define WM2200_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */ -#define WM2200_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */ -#define WM2200_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */ -#define WM2200_GP2_DB 0x0100 /* GP2_DB */ -#define WM2200_GP2_DB_MASK 0x0100 /* GP2_DB */ -#define WM2200_GP2_DB_SHIFT 8 /* GP2_DB */ -#define WM2200_GP2_DB_WIDTH 1 /* GP2_DB */ -#define WM2200_GP2_LVL 0x0040 /* GP2_LVL */ -#define WM2200_GP2_LVL_MASK 0x0040 /* GP2_LVL */ -#define WM2200_GP2_LVL_SHIFT 6 /* GP2_LVL */ -#define WM2200_GP2_LVL_WIDTH 1 /* GP2_LVL */ -#define WM2200_GP2_FN_MASK 0x003F /* GP2_FN - [5:0] */ -#define WM2200_GP2_FN_SHIFT 0 /* GP2_FN - [5:0] */ -#define WM2200_GP2_FN_WIDTH 6 /* GP2_FN - [5:0] */ - -/* - * R1794 (0x702) - GPIO CTRL 3 - */ -#define WM2200_GP3_DIR 0x8000 /* GP3_DIR */ -#define WM2200_GP3_DIR_MASK 0x8000 /* GP3_DIR */ -#define WM2200_GP3_DIR_SHIFT 15 /* GP3_DIR */ -#define WM2200_GP3_DIR_WIDTH 1 /* GP3_DIR */ -#define WM2200_GP3_PU 0x4000 /* GP3_PU */ -#define WM2200_GP3_PU_MASK 0x4000 /* GP3_PU */ -#define WM2200_GP3_PU_SHIFT 14 /* GP3_PU */ -#define WM2200_GP3_PU_WIDTH 1 /* GP3_PU */ -#define WM2200_GP3_PD 0x2000 /* GP3_PD */ -#define WM2200_GP3_PD_MASK 0x2000 /* GP3_PD */ -#define WM2200_GP3_PD_SHIFT 13 /* GP3_PD */ -#define WM2200_GP3_PD_WIDTH 1 /* GP3_PD */ -#define WM2200_GP3_POL 0x0400 /* GP3_POL */ -#define WM2200_GP3_POL_MASK 0x0400 /* GP3_POL */ -#define WM2200_GP3_POL_SHIFT 10 /* GP3_POL */ -#define WM2200_GP3_POL_WIDTH 1 /* GP3_POL */ -#define WM2200_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */ -#define WM2200_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */ -#define WM2200_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */ -#define WM2200_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */ -#define WM2200_GP3_DB 0x0100 /* GP3_DB */ -#define WM2200_GP3_DB_MASK 0x0100 /* GP3_DB */ -#define WM2200_GP3_DB_SHIFT 8 /* GP3_DB */ -#define WM2200_GP3_DB_WIDTH 1 /* GP3_DB */ -#define WM2200_GP3_LVL 0x0040 /* GP3_LVL */ -#define WM2200_GP3_LVL_MASK 0x0040 /* GP3_LVL */ -#define WM2200_GP3_LVL_SHIFT 6 /* GP3_LVL */ -#define WM2200_GP3_LVL_WIDTH 1 /* GP3_LVL */ -#define WM2200_GP3_FN_MASK 0x003F /* GP3_FN - [5:0] */ -#define WM2200_GP3_FN_SHIFT 0 /* GP3_FN - [5:0] */ -#define WM2200_GP3_FN_WIDTH 6 /* GP3_FN - [5:0] */ - -/* - * R1795 (0x703) - GPIO CTRL 4 - */ -#define WM2200_GP4_DIR 0x8000 /* GP4_DIR */ -#define WM2200_GP4_DIR_MASK 0x8000 /* GP4_DIR */ -#define WM2200_GP4_DIR_SHIFT 15 /* GP4_DIR */ -#define WM2200_GP4_DIR_WIDTH 1 /* GP4_DIR */ -#define WM2200_GP4_PU 0x4000 /* GP4_PU */ -#define WM2200_GP4_PU_MASK 0x4000 /* GP4_PU */ -#define WM2200_GP4_PU_SHIFT 14 /* GP4_PU */ -#define WM2200_GP4_PU_WIDTH 1 /* GP4_PU */ -#define WM2200_GP4_PD 0x2000 /* GP4_PD */ -#define WM2200_GP4_PD_MASK 0x2000 /* GP4_PD */ -#define WM2200_GP4_PD_SHIFT 13 /* GP4_PD */ -#define WM2200_GP4_PD_WIDTH 1 /* GP4_PD */ -#define WM2200_GP4_POL 0x0400 /* GP4_POL */ -#define WM2200_GP4_POL_MASK 0x0400 /* GP4_POL */ -#define WM2200_GP4_POL_SHIFT 10 /* GP4_POL */ -#define WM2200_GP4_POL_WIDTH 1 /* GP4_POL */ -#define WM2200_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */ -#define WM2200_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */ -#define WM2200_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */ -#define WM2200_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */ -#define WM2200_GP4_DB 0x0100 /* GP4_DB */ -#define WM2200_GP4_DB_MASK 0x0100 /* GP4_DB */ -#define WM2200_GP4_DB_SHIFT 8 /* GP4_DB */ -#define WM2200_GP4_DB_WIDTH 1 /* GP4_DB */ -#define WM2200_GP4_LVL 0x0040 /* GP4_LVL */ -#define WM2200_GP4_LVL_MASK 0x0040 /* GP4_LVL */ -#define WM2200_GP4_LVL_SHIFT 6 /* GP4_LVL */ -#define WM2200_GP4_LVL_WIDTH 1 /* GP4_LVL */ -#define WM2200_GP4_FN_MASK 0x003F /* GP4_FN - [5:0] */ -#define WM2200_GP4_FN_SHIFT 0 /* GP4_FN - [5:0] */ -#define WM2200_GP4_FN_WIDTH 6 /* GP4_FN - [5:0] */ - -/* - * R1799 (0x707) - ADPS1 IRQ0 - */ -#define WM2200_DSP_IRQ1 0x0002 /* DSP_IRQ1 */ -#define WM2200_DSP_IRQ1_MASK 0x0002 /* DSP_IRQ1 */ -#define WM2200_DSP_IRQ1_SHIFT 1 /* DSP_IRQ1 */ -#define WM2200_DSP_IRQ1_WIDTH 1 /* DSP_IRQ1 */ -#define WM2200_DSP_IRQ0 0x0001 /* DSP_IRQ0 */ -#define WM2200_DSP_IRQ0_MASK 0x0001 /* DSP_IRQ0 */ -#define WM2200_DSP_IRQ0_SHIFT 0 /* DSP_IRQ0 */ -#define WM2200_DSP_IRQ0_WIDTH 1 /* DSP_IRQ0 */ - -/* - * R1800 (0x708) - ADPS1 IRQ1 - */ -#define WM2200_DSP_IRQ3 0x0002 /* DSP_IRQ3 */ -#define WM2200_DSP_IRQ3_MASK 0x0002 /* DSP_IRQ3 */ -#define WM2200_DSP_IRQ3_SHIFT 1 /* DSP_IRQ3 */ -#define WM2200_DSP_IRQ3_WIDTH 1 /* DSP_IRQ3 */ -#define WM2200_DSP_IRQ2 0x0001 /* DSP_IRQ2 */ -#define WM2200_DSP_IRQ2_MASK 0x0001 /* DSP_IRQ2 */ -#define WM2200_DSP_IRQ2_SHIFT 0 /* DSP_IRQ2 */ -#define WM2200_DSP_IRQ2_WIDTH 1 /* DSP_IRQ2 */ - -/* - * R1801 (0x709) - Misc Pad Ctrl 1 - */ -#define WM2200_LDO1ENA_PD 0x8000 /* LDO1ENA_PD */ -#define WM2200_LDO1ENA_PD_MASK 0x8000 /* LDO1ENA_PD */ -#define WM2200_LDO1ENA_PD_SHIFT 15 /* LDO1ENA_PD */ -#define WM2200_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */ -#define WM2200_MCLK2_PD 0x2000 /* MCLK2_PD */ -#define WM2200_MCLK2_PD_MASK 0x2000 /* MCLK2_PD */ -#define WM2200_MCLK2_PD_SHIFT 13 /* MCLK2_PD */ -#define WM2200_MCLK2_PD_WIDTH 1 /* MCLK2_PD */ -#define WM2200_MCLK1_PD 0x1000 /* MCLK1_PD */ -#define WM2200_MCLK1_PD_MASK 0x1000 /* MCLK1_PD */ -#define WM2200_MCLK1_PD_SHIFT 12 /* MCLK1_PD */ -#define WM2200_MCLK1_PD_WIDTH 1 /* MCLK1_PD */ -#define WM2200_DACLRCLK1_PU 0x0400 /* DACLRCLK1_PU */ -#define WM2200_DACLRCLK1_PU_MASK 0x0400 /* DACLRCLK1_PU */ -#define WM2200_DACLRCLK1_PU_SHIFT 10 /* DACLRCLK1_PU */ -#define WM2200_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */ -#define WM2200_DACLRCLK1_PD 0x0200 /* DACLRCLK1_PD */ -#define WM2200_DACLRCLK1_PD_MASK 0x0200 /* DACLRCLK1_PD */ -#define WM2200_DACLRCLK1_PD_SHIFT 9 /* DACLRCLK1_PD */ -#define WM2200_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */ -#define WM2200_BCLK1_PU 0x0100 /* BCLK1_PU */ -#define WM2200_BCLK1_PU_MASK 0x0100 /* BCLK1_PU */ -#define WM2200_BCLK1_PU_SHIFT 8 /* BCLK1_PU */ -#define WM2200_BCLK1_PU_WIDTH 1 /* BCLK1_PU */ -#define WM2200_BCLK1_PD 0x0080 /* BCLK1_PD */ -#define WM2200_BCLK1_PD_MASK 0x0080 /* BCLK1_PD */ -#define WM2200_BCLK1_PD_SHIFT 7 /* BCLK1_PD */ -#define WM2200_BCLK1_PD_WIDTH 1 /* BCLK1_PD */ -#define WM2200_DACDAT1_PU 0x0040 /* DACDAT1_PU */ -#define WM2200_DACDAT1_PU_MASK 0x0040 /* DACDAT1_PU */ -#define WM2200_DACDAT1_PU_SHIFT 6 /* DACDAT1_PU */ -#define WM2200_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */ -#define WM2200_DACDAT1_PD 0x0020 /* DACDAT1_PD */ -#define WM2200_DACDAT1_PD_MASK 0x0020 /* DACDAT1_PD */ -#define WM2200_DACDAT1_PD_SHIFT 5 /* DACDAT1_PD */ -#define WM2200_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */ -#define WM2200_DMICDAT3_PD 0x0010 /* DMICDAT3_PD */ -#define WM2200_DMICDAT3_PD_MASK 0x0010 /* DMICDAT3_PD */ -#define WM2200_DMICDAT3_PD_SHIFT 4 /* DMICDAT3_PD */ -#define WM2200_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */ -#define WM2200_DMICDAT2_PD 0x0008 /* DMICDAT2_PD */ -#define WM2200_DMICDAT2_PD_MASK 0x0008 /* DMICDAT2_PD */ -#define WM2200_DMICDAT2_PD_SHIFT 3 /* DMICDAT2_PD */ -#define WM2200_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */ -#define WM2200_DMICDAT1_PD 0x0004 /* DMICDAT1_PD */ -#define WM2200_DMICDAT1_PD_MASK 0x0004 /* DMICDAT1_PD */ -#define WM2200_DMICDAT1_PD_SHIFT 2 /* DMICDAT1_PD */ -#define WM2200_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */ -#define WM2200_RSTB_PU 0x0002 /* RSTB_PU */ -#define WM2200_RSTB_PU_MASK 0x0002 /* RSTB_PU */ -#define WM2200_RSTB_PU_SHIFT 1 /* RSTB_PU */ -#define WM2200_RSTB_PU_WIDTH 1 /* RSTB_PU */ -#define WM2200_ADDR_PD 0x0001 /* ADDR_PD */ -#define WM2200_ADDR_PD_MASK 0x0001 /* ADDR_PD */ -#define WM2200_ADDR_PD_SHIFT 0 /* ADDR_PD */ -#define WM2200_ADDR_PD_WIDTH 1 /* ADDR_PD */ - -/* - * R2048 (0x800) - Interrupt Status 1 - */ -#define WM2200_DSP_IRQ0_EINT 0x0080 /* DSP_IRQ0_EINT */ -#define WM2200_DSP_IRQ0_EINT_MASK 0x0080 /* DSP_IRQ0_EINT */ -#define WM2200_DSP_IRQ0_EINT_SHIFT 7 /* DSP_IRQ0_EINT */ -#define WM2200_DSP_IRQ0_EINT_WIDTH 1 /* DSP_IRQ0_EINT */ -#define WM2200_DSP_IRQ1_EINT 0x0040 /* DSP_IRQ1_EINT */ -#define WM2200_DSP_IRQ1_EINT_MASK 0x0040 /* DSP_IRQ1_EINT */ -#define WM2200_DSP_IRQ1_EINT_SHIFT 6 /* DSP_IRQ1_EINT */ -#define WM2200_DSP_IRQ1_EINT_WIDTH 1 /* DSP_IRQ1_EINT */ -#define WM2200_DSP_IRQ2_EINT 0x0020 /* DSP_IRQ2_EINT */ -#define WM2200_DSP_IRQ2_EINT_MASK 0x0020 /* DSP_IRQ2_EINT */ -#define WM2200_DSP_IRQ2_EINT_SHIFT 5 /* DSP_IRQ2_EINT */ -#define WM2200_DSP_IRQ2_EINT_WIDTH 1 /* DSP_IRQ2_EINT */ -#define WM2200_DSP_IRQ3_EINT 0x0010 /* DSP_IRQ3_EINT */ -#define WM2200_DSP_IRQ3_EINT_MASK 0x0010 /* DSP_IRQ3_EINT */ -#define WM2200_DSP_IRQ3_EINT_SHIFT 4 /* DSP_IRQ3_EINT */ -#define WM2200_DSP_IRQ3_EINT_WIDTH 1 /* DSP_IRQ3_EINT */ -#define WM2200_GP4_EINT 0x0008 /* GP4_EINT */ -#define WM2200_GP4_EINT_MASK 0x0008 /* GP4_EINT */ -#define WM2200_GP4_EINT_SHIFT 3 /* GP4_EINT */ -#define WM2200_GP4_EINT_WIDTH 1 /* GP4_EINT */ -#define WM2200_GP3_EINT 0x0004 /* GP3_EINT */ -#define WM2200_GP3_EINT_MASK 0x0004 /* GP3_EINT */ -#define WM2200_GP3_EINT_SHIFT 2 /* GP3_EINT */ -#define WM2200_GP3_EINT_WIDTH 1 /* GP3_EINT */ -#define WM2200_GP2_EINT 0x0002 /* GP2_EINT */ -#define WM2200_GP2_EINT_MASK 0x0002 /* GP2_EINT */ -#define WM2200_GP2_EINT_SHIFT 1 /* GP2_EINT */ -#define WM2200_GP2_EINT_WIDTH 1 /* GP2_EINT */ -#define WM2200_GP1_EINT 0x0001 /* GP1_EINT */ -#define WM2200_GP1_EINT_MASK 0x0001 /* GP1_EINT */ -#define WM2200_GP1_EINT_SHIFT 0 /* GP1_EINT */ -#define WM2200_GP1_EINT_WIDTH 1 /* GP1_EINT */ - -/* - * R2049 (0x801) - Interrupt Status 1 Mask - */ -#define WM2200_IM_DSP_IRQ0_EINT 0x0080 /* IM_DSP_IRQ0_EINT */ -#define WM2200_IM_DSP_IRQ0_EINT_MASK 0x0080 /* IM_DSP_IRQ0_EINT */ -#define WM2200_IM_DSP_IRQ0_EINT_SHIFT 7 /* IM_DSP_IRQ0_EINT */ -#define WM2200_IM_DSP_IRQ0_EINT_WIDTH 1 /* IM_DSP_IRQ0_EINT */ -#define WM2200_IM_DSP_IRQ1_EINT 0x0040 /* IM_DSP_IRQ1_EINT */ -#define WM2200_IM_DSP_IRQ1_EINT_MASK 0x0040 /* IM_DSP_IRQ1_EINT */ -#define WM2200_IM_DSP_IRQ1_EINT_SHIFT 6 /* IM_DSP_IRQ1_EINT */ -#define WM2200_IM_DSP_IRQ1_EINT_WIDTH 1 /* IM_DSP_IRQ1_EINT */ -#define WM2200_IM_DSP_IRQ2_EINT 0x0020 /* IM_DSP_IRQ2_EINT */ -#define WM2200_IM_DSP_IRQ2_EINT_MASK 0x0020 /* IM_DSP_IRQ2_EINT */ -#define WM2200_IM_DSP_IRQ2_EINT_SHIFT 5 /* IM_DSP_IRQ2_EINT */ -#define WM2200_IM_DSP_IRQ2_EINT_WIDTH 1 /* IM_DSP_IRQ2_EINT */ -#define WM2200_IM_DSP_IRQ3_EINT 0x0010 /* IM_DSP_IRQ3_EINT */ -#define WM2200_IM_DSP_IRQ3_EINT_MASK 0x0010 /* IM_DSP_IRQ3_EINT */ -#define WM2200_IM_DSP_IRQ3_EINT_SHIFT 4 /* IM_DSP_IRQ3_EINT */ -#define WM2200_IM_DSP_IRQ3_EINT_WIDTH 1 /* IM_DSP_IRQ3_EINT */ -#define WM2200_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */ -#define WM2200_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */ -#define WM2200_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */ -#define WM2200_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */ -#define WM2200_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */ -#define WM2200_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */ -#define WM2200_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */ -#define WM2200_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */ -#define WM2200_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */ -#define WM2200_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */ -#define WM2200_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */ -#define WM2200_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */ -#define WM2200_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */ -#define WM2200_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */ -#define WM2200_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */ -#define WM2200_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */ - -/* - * R2050 (0x802) - Interrupt Status 2 - */ -#define WM2200_WSEQ_BUSY_EINT 0x0100 /* WSEQ_BUSY_EINT */ -#define WM2200_WSEQ_BUSY_EINT_MASK 0x0100 /* WSEQ_BUSY_EINT */ -#define WM2200_WSEQ_BUSY_EINT_SHIFT 8 /* WSEQ_BUSY_EINT */ -#define WM2200_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */ -#define WM2200_FLL_LOCK_EINT 0x0002 /* FLL_LOCK_EINT */ -#define WM2200_FLL_LOCK_EINT_MASK 0x0002 /* FLL_LOCK_EINT */ -#define WM2200_FLL_LOCK_EINT_SHIFT 1 /* FLL_LOCK_EINT */ -#define WM2200_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ -#define WM2200_CLKGEN_EINT 0x0001 /* CLKGEN_EINT */ -#define WM2200_CLKGEN_EINT_MASK 0x0001 /* CLKGEN_EINT */ -#define WM2200_CLKGEN_EINT_SHIFT 0 /* CLKGEN_EINT */ -#define WM2200_CLKGEN_EINT_WIDTH 1 /* CLKGEN_EINT */ - -/* - * R2051 (0x803) - Interrupt Raw Status 2 - */ -#define WM2200_WSEQ_BUSY_STS 0x0100 /* WSEQ_BUSY_STS */ -#define WM2200_WSEQ_BUSY_STS_MASK 0x0100 /* WSEQ_BUSY_STS */ -#define WM2200_WSEQ_BUSY_STS_SHIFT 8 /* WSEQ_BUSY_STS */ -#define WM2200_WSEQ_BUSY_STS_WIDTH 1 /* WSEQ_BUSY_STS */ -#define WM2200_FLL_LOCK_STS 0x0002 /* FLL_LOCK_STS */ -#define WM2200_FLL_LOCK_STS_MASK 0x0002 /* FLL_LOCK_STS */ -#define WM2200_FLL_LOCK_STS_SHIFT 1 /* FLL_LOCK_STS */ -#define WM2200_FLL_LOCK_STS_WIDTH 1 /* FLL_LOCK_STS */ -#define WM2200_CLKGEN_STS 0x0001 /* CLKGEN_STS */ -#define WM2200_CLKGEN_STS_MASK 0x0001 /* CLKGEN_STS */ -#define WM2200_CLKGEN_STS_SHIFT 0 /* CLKGEN_STS */ -#define WM2200_CLKGEN_STS_WIDTH 1 /* CLKGEN_STS */ - -/* - * R2052 (0x804) - Interrupt Status 2 Mask - */ -#define WM2200_IM_WSEQ_BUSY_EINT 0x0100 /* IM_WSEQ_BUSY_EINT */ -#define WM2200_IM_WSEQ_BUSY_EINT_MASK 0x0100 /* IM_WSEQ_BUSY_EINT */ -#define WM2200_IM_WSEQ_BUSY_EINT_SHIFT 8 /* IM_WSEQ_BUSY_EINT */ -#define WM2200_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */ -#define WM2200_IM_FLL_LOCK_EINT 0x0002 /* IM_FLL_LOCK_EINT */ -#define WM2200_IM_FLL_LOCK_EINT_MASK 0x0002 /* IM_FLL_LOCK_EINT */ -#define WM2200_IM_FLL_LOCK_EINT_SHIFT 1 /* IM_FLL_LOCK_EINT */ -#define WM2200_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ -#define WM2200_IM_CLKGEN_EINT 0x0001 /* IM_CLKGEN_EINT */ -#define WM2200_IM_CLKGEN_EINT_MASK 0x0001 /* IM_CLKGEN_EINT */ -#define WM2200_IM_CLKGEN_EINT_SHIFT 0 /* IM_CLKGEN_EINT */ -#define WM2200_IM_CLKGEN_EINT_WIDTH 1 /* IM_CLKGEN_EINT */ - -/* - * R2056 (0x808) - Interrupt Control - */ -#define WM2200_IM_IRQ 0x0001 /* IM_IRQ */ -#define WM2200_IM_IRQ_MASK 0x0001 /* IM_IRQ */ -#define WM2200_IM_IRQ_SHIFT 0 /* IM_IRQ */ -#define WM2200_IM_IRQ_WIDTH 1 /* IM_IRQ */ - -/* - * R2304 (0x900) - EQL_1 - */ -#define WM2200_EQL_B1_GAIN_MASK 0xF800 /* EQL_B1_GAIN - [15:11] */ -#define WM2200_EQL_B1_GAIN_SHIFT 11 /* EQL_B1_GAIN - [15:11] */ -#define WM2200_EQL_B1_GAIN_WIDTH 5 /* EQL_B1_GAIN - [15:11] */ -#define WM2200_EQL_B2_GAIN_MASK 0x07C0 /* EQL_B2_GAIN - [10:6] */ -#define WM2200_EQL_B2_GAIN_SHIFT 6 /* EQL_B2_GAIN - [10:6] */ -#define WM2200_EQL_B2_GAIN_WIDTH 5 /* EQL_B2_GAIN - [10:6] */ -#define WM2200_EQL_B3_GAIN_MASK 0x003E /* EQL_B3_GAIN - [5:1] */ -#define WM2200_EQL_B3_GAIN_SHIFT 1 /* EQL_B3_GAIN - [5:1] */ -#define WM2200_EQL_B3_GAIN_WIDTH 5 /* EQL_B3_GAIN - [5:1] */ -#define WM2200_EQL_ENA 0x0001 /* EQL_ENA */ -#define WM2200_EQL_ENA_MASK 0x0001 /* EQL_ENA */ -#define WM2200_EQL_ENA_SHIFT 0 /* EQL_ENA */ -#define WM2200_EQL_ENA_WIDTH 1 /* EQL_ENA */ - -/* - * R2305 (0x901) - EQL_2 - */ -#define WM2200_EQL_B4_GAIN_MASK 0xF800 /* EQL_B4_GAIN - [15:11] */ -#define WM2200_EQL_B4_GAIN_SHIFT 11 /* EQL_B4_GAIN - [15:11] */ -#define WM2200_EQL_B4_GAIN_WIDTH 5 /* EQL_B4_GAIN - [15:11] */ -#define WM2200_EQL_B5_GAIN_MASK 0x07C0 /* EQL_B5_GAIN - [10:6] */ -#define WM2200_EQL_B5_GAIN_SHIFT 6 /* EQL_B5_GAIN - [10:6] */ -#define WM2200_EQL_B5_GAIN_WIDTH 5 /* EQL_B5_GAIN - [10:6] */ - -/* - * R2306 (0x902) - EQL_3 - */ -#define WM2200_EQL_B1_A_MASK 0xFFFF /* EQL_B1_A - [15:0] */ -#define WM2200_EQL_B1_A_SHIFT 0 /* EQL_B1_A - [15:0] */ -#define WM2200_EQL_B1_A_WIDTH 16 /* EQL_B1_A - [15:0] */ - -/* - * R2307 (0x903) - EQL_4 - */ -#define WM2200_EQL_B1_B_MASK 0xFFFF /* EQL_B1_B - [15:0] */ -#define WM2200_EQL_B1_B_SHIFT 0 /* EQL_B1_B - [15:0] */ -#define WM2200_EQL_B1_B_WIDTH 16 /* EQL_B1_B - [15:0] */ - -/* - * R2308 (0x904) - EQL_5 - */ -#define WM2200_EQL_B1_PG_MASK 0xFFFF /* EQL_B1_PG - [15:0] */ -#define WM2200_EQL_B1_PG_SHIFT 0 /* EQL_B1_PG - [15:0] */ -#define WM2200_EQL_B1_PG_WIDTH 16 /* EQL_B1_PG - [15:0] */ - -/* - * R2309 (0x905) - EQL_6 - */ -#define WM2200_EQL_B2_A_MASK 0xFFFF /* EQL_B2_A - [15:0] */ -#define WM2200_EQL_B2_A_SHIFT 0 /* EQL_B2_A - [15:0] */ -#define WM2200_EQL_B2_A_WIDTH 16 /* EQL_B2_A - [15:0] */ - -/* - * R2310 (0x906) - EQL_7 - */ -#define WM2200_EQL_B2_B_MASK 0xFFFF /* EQL_B2_B - [15:0] */ -#define WM2200_EQL_B2_B_SHIFT 0 /* EQL_B2_B - [15:0] */ -#define WM2200_EQL_B2_B_WIDTH 16 /* EQL_B2_B - [15:0] */ - -/* - * R2311 (0x907) - EQL_8 - */ -#define WM2200_EQL_B2_C_MASK 0xFFFF /* EQL_B2_C - [15:0] */ -#define WM2200_EQL_B2_C_SHIFT 0 /* EQL_B2_C - [15:0] */ -#define WM2200_EQL_B2_C_WIDTH 16 /* EQL_B2_C - [15:0] */ - -/* - * R2312 (0x908) - EQL_9 - */ -#define WM2200_EQL_B2_PG_MASK 0xFFFF /* EQL_B2_PG - [15:0] */ -#define WM2200_EQL_B2_PG_SHIFT 0 /* EQL_B2_PG - [15:0] */ -#define WM2200_EQL_B2_PG_WIDTH 16 /* EQL_B2_PG - [15:0] */ - -/* - * R2313 (0x909) - EQL_10 - */ -#define WM2200_EQL_B3_A_MASK 0xFFFF /* EQL_B3_A - [15:0] */ -#define WM2200_EQL_B3_A_SHIFT 0 /* EQL_B3_A - [15:0] */ -#define WM2200_EQL_B3_A_WIDTH 16 /* EQL_B3_A - [15:0] */ - -/* - * R2314 (0x90A) - EQL_11 - */ -#define WM2200_EQL_B3_B_MASK 0xFFFF /* EQL_B3_B - [15:0] */ -#define WM2200_EQL_B3_B_SHIFT 0 /* EQL_B3_B - [15:0] */ -#define WM2200_EQL_B3_B_WIDTH 16 /* EQL_B3_B - [15:0] */ - -/* - * R2315 (0x90B) - EQL_12 - */ -#define WM2200_EQL_B3_C_MASK 0xFFFF /* EQL_B3_C - [15:0] */ -#define WM2200_EQL_B3_C_SHIFT 0 /* EQL_B3_C - [15:0] */ -#define WM2200_EQL_B3_C_WIDTH 16 /* EQL_B3_C - [15:0] */ - -/* - * R2316 (0x90C) - EQL_13 - */ -#define WM2200_EQL_B3_PG_MASK 0xFFFF /* EQL_B3_PG - [15:0] */ -#define WM2200_EQL_B3_PG_SHIFT 0 /* EQL_B3_PG - [15:0] */ -#define WM2200_EQL_B3_PG_WIDTH 16 /* EQL_B3_PG - [15:0] */ - -/* - * R2317 (0x90D) - EQL_14 - */ -#define WM2200_EQL_B4_A_MASK 0xFFFF /* EQL_B4_A - [15:0] */ -#define WM2200_EQL_B4_A_SHIFT 0 /* EQL_B4_A - [15:0] */ -#define WM2200_EQL_B4_A_WIDTH 16 /* EQL_B4_A - [15:0] */ - -/* - * R2318 (0x90E) - EQL_15 - */ -#define WM2200_EQL_B4_B_MASK 0xFFFF /* EQL_B4_B - [15:0] */ -#define WM2200_EQL_B4_B_SHIFT 0 /* EQL_B4_B - [15:0] */ -#define WM2200_EQL_B4_B_WIDTH 16 /* EQL_B4_B - [15:0] */ - -/* - * R2319 (0x90F) - EQL_16 - */ -#define WM2200_EQL_B4_C_MASK 0xFFFF /* EQL_B4_C - [15:0] */ -#define WM2200_EQL_B4_C_SHIFT 0 /* EQL_B4_C - [15:0] */ -#define WM2200_EQL_B4_C_WIDTH 16 /* EQL_B4_C - [15:0] */ - -/* - * R2320 (0x910) - EQL_17 - */ -#define WM2200_EQL_B4_PG_MASK 0xFFFF /* EQL_B4_PG - [15:0] */ -#define WM2200_EQL_B4_PG_SHIFT 0 /* EQL_B4_PG - [15:0] */ -#define WM2200_EQL_B4_PG_WIDTH 16 /* EQL_B4_PG - [15:0] */ - -/* - * R2321 (0x911) - EQL_18 - */ -#define WM2200_EQL_B5_A_MASK 0xFFFF /* EQL_B5_A - [15:0] */ -#define WM2200_EQL_B5_A_SHIFT 0 /* EQL_B5_A - [15:0] */ -#define WM2200_EQL_B5_A_WIDTH 16 /* EQL_B5_A - [15:0] */ - -/* - * R2322 (0x912) - EQL_19 - */ -#define WM2200_EQL_B5_B_MASK 0xFFFF /* EQL_B5_B - [15:0] */ -#define WM2200_EQL_B5_B_SHIFT 0 /* EQL_B5_B - [15:0] */ -#define WM2200_EQL_B5_B_WIDTH 16 /* EQL_B5_B - [15:0] */ - -/* - * R2323 (0x913) - EQL_20 - */ -#define WM2200_EQL_B5_PG_MASK 0xFFFF /* EQL_B5_PG - [15:0] */ -#define WM2200_EQL_B5_PG_SHIFT 0 /* EQL_B5_PG - [15:0] */ -#define WM2200_EQL_B5_PG_WIDTH 16 /* EQL_B5_PG - [15:0] */ - -/* - * R2326 (0x916) - EQR_1 - */ -#define WM2200_EQR_B1_GAIN_MASK 0xF800 /* EQR_B1_GAIN - [15:11] */ -#define WM2200_EQR_B1_GAIN_SHIFT 11 /* EQR_B1_GAIN - [15:11] */ -#define WM2200_EQR_B1_GAIN_WIDTH 5 /* EQR_B1_GAIN - [15:11] */ -#define WM2200_EQR_B2_GAIN_MASK 0x07C0 /* EQR_B2_GAIN - [10:6] */ -#define WM2200_EQR_B2_GAIN_SHIFT 6 /* EQR_B2_GAIN - [10:6] */ -#define WM2200_EQR_B2_GAIN_WIDTH 5 /* EQR_B2_GAIN - [10:6] */ -#define WM2200_EQR_B3_GAIN_MASK 0x003E /* EQR_B3_GAIN - [5:1] */ -#define WM2200_EQR_B3_GAIN_SHIFT 1 /* EQR_B3_GAIN - [5:1] */ -#define WM2200_EQR_B3_GAIN_WIDTH 5 /* EQR_B3_GAIN - [5:1] */ -#define WM2200_EQR_ENA 0x0001 /* EQR_ENA */ -#define WM2200_EQR_ENA_MASK 0x0001 /* EQR_ENA */ -#define WM2200_EQR_ENA_SHIFT 0 /* EQR_ENA */ -#define WM2200_EQR_ENA_WIDTH 1 /* EQR_ENA */ - -/* - * R2327 (0x917) - EQR_2 - */ -#define WM2200_EQR_B4_GAIN_MASK 0xF800 /* EQR_B4_GAIN - [15:11] */ -#define WM2200_EQR_B4_GAIN_SHIFT 11 /* EQR_B4_GAIN - [15:11] */ -#define WM2200_EQR_B4_GAIN_WIDTH 5 /* EQR_B4_GAIN - [15:11] */ -#define WM2200_EQR_B5_GAIN_MASK 0x07C0 /* EQR_B5_GAIN - [10:6] */ -#define WM2200_EQR_B5_GAIN_SHIFT 6 /* EQR_B5_GAIN - [10:6] */ -#define WM2200_EQR_B5_GAIN_WIDTH 5 /* EQR_B5_GAIN - [10:6] */ - -/* - * R2328 (0x918) - EQR_3 - */ -#define WM2200_EQR_B1_A_MASK 0xFFFF /* EQR_B1_A - [15:0] */ -#define WM2200_EQR_B1_A_SHIFT 0 /* EQR_B1_A - [15:0] */ -#define WM2200_EQR_B1_A_WIDTH 16 /* EQR_B1_A - [15:0] */ - -/* - * R2329 (0x919) - EQR_4 - */ -#define WM2200_EQR_B1_B_MASK 0xFFFF /* EQR_B1_B - [15:0] */ -#define WM2200_EQR_B1_B_SHIFT 0 /* EQR_B1_B - [15:0] */ -#define WM2200_EQR_B1_B_WIDTH 16 /* EQR_B1_B - [15:0] */ - -/* - * R2330 (0x91A) - EQR_5 - */ -#define WM2200_EQR_B1_PG_MASK 0xFFFF /* EQR_B1_PG - [15:0] */ -#define WM2200_EQR_B1_PG_SHIFT 0 /* EQR_B1_PG - [15:0] */ -#define WM2200_EQR_B1_PG_WIDTH 16 /* EQR_B1_PG - [15:0] */ - -/* - * R2331 (0x91B) - EQR_6 - */ -#define WM2200_EQR_B2_A_MASK 0xFFFF /* EQR_B2_A - [15:0] */ -#define WM2200_EQR_B2_A_SHIFT 0 /* EQR_B2_A - [15:0] */ -#define WM2200_EQR_B2_A_WIDTH 16 /* EQR_B2_A - [15:0] */ - -/* - * R2332 (0x91C) - EQR_7 - */ -#define WM2200_EQR_B2_B_MASK 0xFFFF /* EQR_B2_B - [15:0] */ -#define WM2200_EQR_B2_B_SHIFT 0 /* EQR_B2_B - [15:0] */ -#define WM2200_EQR_B2_B_WIDTH 16 /* EQR_B2_B - [15:0] */ - -/* - * R2333 (0x91D) - EQR_8 - */ -#define WM2200_EQR_B2_C_MASK 0xFFFF /* EQR_B2_C - [15:0] */ -#define WM2200_EQR_B2_C_SHIFT 0 /* EQR_B2_C - [15:0] */ -#define WM2200_EQR_B2_C_WIDTH 16 /* EQR_B2_C - [15:0] */ - -/* - * R2334 (0x91E) - EQR_9 - */ -#define WM2200_EQR_B2_PG_MASK 0xFFFF /* EQR_B2_PG - [15:0] */ -#define WM2200_EQR_B2_PG_SHIFT 0 /* EQR_B2_PG - [15:0] */ -#define WM2200_EQR_B2_PG_WIDTH 16 /* EQR_B2_PG - [15:0] */ - -/* - * R2335 (0x91F) - EQR_10 - */ -#define WM2200_EQR_B3_A_MASK 0xFFFF /* EQR_B3_A - [15:0] */ -#define WM2200_EQR_B3_A_SHIFT 0 /* EQR_B3_A - [15:0] */ -#define WM2200_EQR_B3_A_WIDTH 16 /* EQR_B3_A - [15:0] */ - -/* - * R2336 (0x920) - EQR_11 - */ -#define WM2200_EQR_B3_B_MASK 0xFFFF /* EQR_B3_B - [15:0] */ -#define WM2200_EQR_B3_B_SHIFT 0 /* EQR_B3_B - [15:0] */ -#define WM2200_EQR_B3_B_WIDTH 16 /* EQR_B3_B - [15:0] */ - -/* - * R2337 (0x921) - EQR_12 - */ -#define WM2200_EQR_B3_C_MASK 0xFFFF /* EQR_B3_C - [15:0] */ -#define WM2200_EQR_B3_C_SHIFT 0 /* EQR_B3_C - [15:0] */ -#define WM2200_EQR_B3_C_WIDTH 16 /* EQR_B3_C - [15:0] */ - -/* - * R2338 (0x922) - EQR_13 - */ -#define WM2200_EQR_B3_PG_MASK 0xFFFF /* EQR_B3_PG - [15:0] */ -#define WM2200_EQR_B3_PG_SHIFT 0 /* EQR_B3_PG - [15:0] */ -#define WM2200_EQR_B3_PG_WIDTH 16 /* EQR_B3_PG - [15:0] */ - -/* - * R2339 (0x923) - EQR_14 - */ -#define WM2200_EQR_B4_A_MASK 0xFFFF /* EQR_B4_A - [15:0] */ -#define WM2200_EQR_B4_A_SHIFT 0 /* EQR_B4_A - [15:0] */ -#define WM2200_EQR_B4_A_WIDTH 16 /* EQR_B4_A - [15:0] */ - -/* - * R2340 (0x924) - EQR_15 - */ -#define WM2200_EQR_B4_B_MASK 0xFFFF /* EQR_B4_B - [15:0] */ -#define WM2200_EQR_B4_B_SHIFT 0 /* EQR_B4_B - [15:0] */ -#define WM2200_EQR_B4_B_WIDTH 16 /* EQR_B4_B - [15:0] */ - -/* - * R2341 (0x925) - EQR_16 - */ -#define WM2200_EQR_B4_C_MASK 0xFFFF /* EQR_B4_C - [15:0] */ -#define WM2200_EQR_B4_C_SHIFT 0 /* EQR_B4_C - [15:0] */ -#define WM2200_EQR_B4_C_WIDTH 16 /* EQR_B4_C - [15:0] */ - -/* - * R2342 (0x926) - EQR_17 - */ -#define WM2200_EQR_B4_PG_MASK 0xFFFF /* EQR_B4_PG - [15:0] */ -#define WM2200_EQR_B4_PG_SHIFT 0 /* EQR_B4_PG - [15:0] */ -#define WM2200_EQR_B4_PG_WIDTH 16 /* EQR_B4_PG - [15:0] */ - -/* - * R2343 (0x927) - EQR_18 - */ -#define WM2200_EQR_B5_A_MASK 0xFFFF /* EQR_B5_A - [15:0] */ -#define WM2200_EQR_B5_A_SHIFT 0 /* EQR_B5_A - [15:0] */ -#define WM2200_EQR_B5_A_WIDTH 16 /* EQR_B5_A - [15:0] */ - -/* - * R2344 (0x928) - EQR_19 - */ -#define WM2200_EQR_B5_B_MASK 0xFFFF /* EQR_B5_B - [15:0] */ -#define WM2200_EQR_B5_B_SHIFT 0 /* EQR_B5_B - [15:0] */ -#define WM2200_EQR_B5_B_WIDTH 16 /* EQR_B5_B - [15:0] */ - -/* - * R2345 (0x929) - EQR_20 - */ -#define WM2200_EQR_B5_PG_MASK 0xFFFF /* EQR_B5_PG - [15:0] */ -#define WM2200_EQR_B5_PG_SHIFT 0 /* EQR_B5_PG - [15:0] */ -#define WM2200_EQR_B5_PG_WIDTH 16 /* EQR_B5_PG - [15:0] */ - -/* - * R2366 (0x93E) - HPLPF1_1 - */ -#define WM2200_LHPF1_MODE 0x0002 /* LHPF1_MODE */ -#define WM2200_LHPF1_MODE_MASK 0x0002 /* LHPF1_MODE */ -#define WM2200_LHPF1_MODE_SHIFT 1 /* LHPF1_MODE */ -#define WM2200_LHPF1_MODE_WIDTH 1 /* LHPF1_MODE */ -#define WM2200_LHPF1_ENA 0x0001 /* LHPF1_ENA */ -#define WM2200_LHPF1_ENA_MASK 0x0001 /* LHPF1_ENA */ -#define WM2200_LHPF1_ENA_SHIFT 0 /* LHPF1_ENA */ -#define WM2200_LHPF1_ENA_WIDTH 1 /* LHPF1_ENA */ - -/* - * R2367 (0x93F) - HPLPF1_2 - */ -#define WM2200_LHPF1_COEFF_MASK 0xFFFF /* LHPF1_COEFF - [15:0] */ -#define WM2200_LHPF1_COEFF_SHIFT 0 /* LHPF1_COEFF - [15:0] */ -#define WM2200_LHPF1_COEFF_WIDTH 16 /* LHPF1_COEFF - [15:0] */ - -/* - * R2370 (0x942) - HPLPF2_1 - */ -#define WM2200_LHPF2_MODE 0x0002 /* LHPF2_MODE */ -#define WM2200_LHPF2_MODE_MASK 0x0002 /* LHPF2_MODE */ -#define WM2200_LHPF2_MODE_SHIFT 1 /* LHPF2_MODE */ -#define WM2200_LHPF2_MODE_WIDTH 1 /* LHPF2_MODE */ -#define WM2200_LHPF2_ENA 0x0001 /* LHPF2_ENA */ -#define WM2200_LHPF2_ENA_MASK 0x0001 /* LHPF2_ENA */ -#define WM2200_LHPF2_ENA_SHIFT 0 /* LHPF2_ENA */ -#define WM2200_LHPF2_ENA_WIDTH 1 /* LHPF2_ENA */ - -/* - * R2371 (0x943) - HPLPF2_2 - */ -#define WM2200_LHPF2_COEFF_MASK 0xFFFF /* LHPF2_COEFF - [15:0] */ -#define WM2200_LHPF2_COEFF_SHIFT 0 /* LHPF2_COEFF - [15:0] */ -#define WM2200_LHPF2_COEFF_WIDTH 16 /* LHPF2_COEFF - [15:0] */ - -/* - * R2560 (0xA00) - DSP1 Control 1 - */ -#define WM2200_DSP1_RW_SEQUENCE_ENA 0x0001 /* DSP1_RW_SEQUENCE_ENA */ -#define WM2200_DSP1_RW_SEQUENCE_ENA_MASK 0x0001 /* DSP1_RW_SEQUENCE_ENA */ -#define WM2200_DSP1_RW_SEQUENCE_ENA_SHIFT 0 /* DSP1_RW_SEQUENCE_ENA */ -#define WM2200_DSP1_RW_SEQUENCE_ENA_WIDTH 1 /* DSP1_RW_SEQUENCE_ENA */ - -/* - * R2562 (0xA02) - DSP1 Control 2 - */ -#define WM2200_DSP1_PAGE_BASE_PM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_PM - [15:8] */ -#define WM2200_DSP1_PAGE_BASE_PM_0_SHIFT 8 /* DSP1_PAGE_BASE_PM - [15:8] */ -#define WM2200_DSP1_PAGE_BASE_PM_0_WIDTH 8 /* DSP1_PAGE_BASE_PM - [15:8] */ - -/* - * R2563 (0xA03) - DSP1 Control 3 - */ -#define WM2200_DSP1_PAGE_BASE_DM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_DM - [15:8] */ -#define WM2200_DSP1_PAGE_BASE_DM_0_SHIFT 8 /* DSP1_PAGE_BASE_DM - [15:8] */ -#define WM2200_DSP1_PAGE_BASE_DM_0_WIDTH 8 /* DSP1_PAGE_BASE_DM - [15:8] */ - -/* - * R2564 (0xA04) - DSP1 Control 4 - */ -#define WM2200_DSP1_PAGE_BASE_ZM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_ZM - [15:8] */ -#define WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT 8 /* DSP1_PAGE_BASE_ZM - [15:8] */ -#define WM2200_DSP1_PAGE_BASE_ZM_0_WIDTH 8 /* DSP1_PAGE_BASE_ZM - [15:8] */ - -/* - * R2566 (0xA06) - DSP1 Control 5 - */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */ - -/* - * R2567 (0xA07) - DSP1 Control 6 - */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */ - -/* - * R2568 (0xA08) - DSP1 Control 7 - */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */ - -/* - * R2569 (0xA09) - DSP1 Control 8 - */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */ - -/* - * R2570 (0xA0A) - DSP1 Control 9 - */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */ - -/* - * R2571 (0xA0B) - DSP1 Control 10 - */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */ - -/* - * R2572 (0xA0C) - DSP1 Control 11 - */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */ - -/* - * R2573 (0xA0D) - DSP1 Control 12 - */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */ - -/* - * R2575 (0xA0F) - DSP1 Control 13 - */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */ - -/* - * R2576 (0xA10) - DSP1 Control 14 - */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */ - -/* - * R2577 (0xA11) - DSP1 Control 15 - */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */ - -/* - * R2578 (0xA12) - DSP1 Control 16 - */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */ - -/* - * R2579 (0xA13) - DSP1 Control 17 - */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */ - -/* - * R2580 (0xA14) - DSP1 Control 18 - */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */ -#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */ - -/* - * R2582 (0xA16) - DSP1 Control 19 - */ -#define WM2200_DSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ -#define WM2200_DSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ -#define WM2200_DSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ - -/* - * R2583 (0xA17) - DSP1 Control 20 - */ -#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_MASK 0x00FF /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */ -#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */ -#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_WIDTH 8 /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */ - -/* - * R2584 (0xA18) - DSP1 Control 21 - */ -#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_MASK 0x003F /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */ -#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */ -#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_WIDTH 6 /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */ - -/* - * R2586 (0xA1A) - DSP1 Control 22 - */ -#define WM2200_DSP1_DM_SIZE_MASK 0xFFFF /* DSP1_DM_SIZE - [15:0] */ -#define WM2200_DSP1_DM_SIZE_SHIFT 0 /* DSP1_DM_SIZE - [15:0] */ -#define WM2200_DSP1_DM_SIZE_WIDTH 16 /* DSP1_DM_SIZE - [15:0] */ - -/* - * R2587 (0xA1B) - DSP1 Control 23 - */ -#define WM2200_DSP1_PM_SIZE_MASK 0xFFFF /* DSP1_PM_SIZE - [15:0] */ -#define WM2200_DSP1_PM_SIZE_SHIFT 0 /* DSP1_PM_SIZE - [15:0] */ -#define WM2200_DSP1_PM_SIZE_WIDTH 16 /* DSP1_PM_SIZE - [15:0] */ - -/* - * R2588 (0xA1C) - DSP1 Control 24 - */ -#define WM2200_DSP1_ZM_SIZE_MASK 0xFFFF /* DSP1_ZM_SIZE - [15:0] */ -#define WM2200_DSP1_ZM_SIZE_SHIFT 0 /* DSP1_ZM_SIZE - [15:0] */ -#define WM2200_DSP1_ZM_SIZE_WIDTH 16 /* DSP1_ZM_SIZE - [15:0] */ - -/* - * R2590 (0xA1E) - DSP1 Control 25 - */ -#define WM2200_DSP1_PING_FULL 0x8000 /* DSP1_PING_FULL */ -#define WM2200_DSP1_PING_FULL_MASK 0x8000 /* DSP1_PING_FULL */ -#define WM2200_DSP1_PING_FULL_SHIFT 15 /* DSP1_PING_FULL */ -#define WM2200_DSP1_PING_FULL_WIDTH 1 /* DSP1_PING_FULL */ -#define WM2200_DSP1_PONG_FULL 0x4000 /* DSP1_PONG_FULL */ -#define WM2200_DSP1_PONG_FULL_MASK 0x4000 /* DSP1_PONG_FULL */ -#define WM2200_DSP1_PONG_FULL_SHIFT 14 /* DSP1_PONG_FULL */ -#define WM2200_DSP1_PONG_FULL_WIDTH 1 /* DSP1_PONG_FULL */ -#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */ -#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */ -#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */ - -/* - * R2592 (0xA20) - DSP1 Control 26 - */ -#define WM2200_DSP1_SCRATCH_0_MASK 0xFFFF /* DSP1_SCRATCH_0 - [15:0] */ -#define WM2200_DSP1_SCRATCH_0_SHIFT 0 /* DSP1_SCRATCH_0 - [15:0] */ -#define WM2200_DSP1_SCRATCH_0_WIDTH 16 /* DSP1_SCRATCH_0 - [15:0] */ - -/* - * R2593 (0xA21) - DSP1 Control 27 - */ -#define WM2200_DSP1_SCRATCH_1_MASK 0xFFFF /* DSP1_SCRATCH_1 - [15:0] */ -#define WM2200_DSP1_SCRATCH_1_SHIFT 0 /* DSP1_SCRATCH_1 - [15:0] */ -#define WM2200_DSP1_SCRATCH_1_WIDTH 16 /* DSP1_SCRATCH_1 - [15:0] */ - -/* - * R2594 (0xA22) - DSP1 Control 28 - */ -#define WM2200_DSP1_SCRATCH_2_MASK 0xFFFF /* DSP1_SCRATCH_2 - [15:0] */ -#define WM2200_DSP1_SCRATCH_2_SHIFT 0 /* DSP1_SCRATCH_2 - [15:0] */ -#define WM2200_DSP1_SCRATCH_2_WIDTH 16 /* DSP1_SCRATCH_2 - [15:0] */ - -/* - * R2595 (0xA23) - DSP1 Control 29 - */ -#define WM2200_DSP1_SCRATCH_3_MASK 0xFFFF /* DSP1_SCRATCH_3 - [15:0] */ -#define WM2200_DSP1_SCRATCH_3_SHIFT 0 /* DSP1_SCRATCH_3 - [15:0] */ -#define WM2200_DSP1_SCRATCH_3_WIDTH 16 /* DSP1_SCRATCH_3 - [15:0] */ - -/* - * R2596 (0xA24) - DSP1 Control 30 - */ -#define WM2200_DSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */ -#define WM2200_DSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */ -#define WM2200_DSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */ -#define WM2200_DSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */ -#define WM2200_DSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ -#define WM2200_DSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ -#define WM2200_DSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ -#define WM2200_DSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ -#define WM2200_DSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ -#define WM2200_DSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ -#define WM2200_DSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ -#define WM2200_DSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ -#define WM2200_DSP1_START 0x0001 /* DSP1_START */ -#define WM2200_DSP1_START_MASK 0x0001 /* DSP1_START */ -#define WM2200_DSP1_START_SHIFT 0 /* DSP1_START */ -#define WM2200_DSP1_START_WIDTH 1 /* DSP1_START */ - -/* - * R2598 (0xA26) - DSP1 Control 31 - */ -#define WM2200_DSP1_CLK_RATE_MASK 0x0018 /* DSP1_CLK_RATE - [4:3] */ -#define WM2200_DSP1_CLK_RATE_SHIFT 3 /* DSP1_CLK_RATE - [4:3] */ -#define WM2200_DSP1_CLK_RATE_WIDTH 2 /* DSP1_CLK_RATE - [4:3] */ -#define WM2200_DSP1_CLK_AVAIL 0x0004 /* DSP1_CLK_AVAIL */ -#define WM2200_DSP1_CLK_AVAIL_MASK 0x0004 /* DSP1_CLK_AVAIL */ -#define WM2200_DSP1_CLK_AVAIL_SHIFT 2 /* DSP1_CLK_AVAIL */ -#define WM2200_DSP1_CLK_AVAIL_WIDTH 1 /* DSP1_CLK_AVAIL */ -#define WM2200_DSP1_CLK_REQ_MASK 0x0003 /* DSP1_CLK_REQ - [1:0] */ -#define WM2200_DSP1_CLK_REQ_SHIFT 0 /* DSP1_CLK_REQ - [1:0] */ -#define WM2200_DSP1_CLK_REQ_WIDTH 2 /* DSP1_CLK_REQ - [1:0] */ - -/* - * R2816 (0xB00) - DSP2 Control 1 - */ -#define WM2200_DSP2_RW_SEQUENCE_ENA 0x0001 /* DSP2_RW_SEQUENCE_ENA */ -#define WM2200_DSP2_RW_SEQUENCE_ENA_MASK 0x0001 /* DSP2_RW_SEQUENCE_ENA */ -#define WM2200_DSP2_RW_SEQUENCE_ENA_SHIFT 0 /* DSP2_RW_SEQUENCE_ENA */ -#define WM2200_DSP2_RW_SEQUENCE_ENA_WIDTH 1 /* DSP2_RW_SEQUENCE_ENA */ - -/* - * R2818 (0xB02) - DSP2 Control 2 - */ -#define WM2200_DSP2_PAGE_BASE_PM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_PM - [15:8] */ -#define WM2200_DSP2_PAGE_BASE_PM_0_SHIFT 8 /* DSP2_PAGE_BASE_PM - [15:8] */ -#define WM2200_DSP2_PAGE_BASE_PM_0_WIDTH 8 /* DSP2_PAGE_BASE_PM - [15:8] */ - -/* - * R2819 (0xB03) - DSP2 Control 3 - */ -#define WM2200_DSP2_PAGE_BASE_DM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_DM - [15:8] */ -#define WM2200_DSP2_PAGE_BASE_DM_0_SHIFT 8 /* DSP2_PAGE_BASE_DM - [15:8] */ -#define WM2200_DSP2_PAGE_BASE_DM_0_WIDTH 8 /* DSP2_PAGE_BASE_DM - [15:8] */ - -/* - * R2820 (0xB04) - DSP2 Control 4 - */ -#define WM2200_DSP2_PAGE_BASE_ZM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_ZM - [15:8] */ -#define WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT 8 /* DSP2_PAGE_BASE_ZM - [15:8] */ -#define WM2200_DSP2_PAGE_BASE_ZM_0_WIDTH 8 /* DSP2_PAGE_BASE_ZM - [15:8] */ - -/* - * R2822 (0xB06) - DSP2 Control 5 - */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */ - -/* - * R2823 (0xB07) - DSP2 Control 6 - */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */ - -/* - * R2824 (0xB08) - DSP2 Control 7 - */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */ - -/* - * R2825 (0xB09) - DSP2 Control 8 - */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */ - -/* - * R2826 (0xB0A) - DSP2 Control 9 - */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */ - -/* - * R2827 (0xB0B) - DSP2 Control 10 - */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */ - -/* - * R2828 (0xB0C) - DSP2 Control 11 - */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */ - -/* - * R2829 (0xB0D) - DSP2 Control 12 - */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */ - -/* - * R2831 (0xB0F) - DSP2 Control 13 - */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */ - -/* - * R2832 (0xB10) - DSP2 Control 14 - */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */ - -/* - * R2833 (0xB11) - DSP2 Control 15 - */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */ - -/* - * R2834 (0xB12) - DSP2 Control 16 - */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */ - -/* - * R2835 (0xB13) - DSP2 Control 17 - */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */ - -/* - * R2836 (0xB14) - DSP2 Control 18 - */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */ -#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */ - -/* - * R2838 (0xB16) - DSP2 Control 19 - */ -#define WM2200_DSP2_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */ -#define WM2200_DSP2_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */ -#define WM2200_DSP2_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */ - -/* - * R2839 (0xB17) - DSP2 Control 20 - */ -#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_MASK 0x00FF /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */ -#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */ -#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_WIDTH 8 /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */ - -/* - * R2840 (0xB18) - DSP2 Control 21 - */ -#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_MASK 0x003F /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */ -#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */ -#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_WIDTH 6 /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */ - -/* - * R2842 (0xB1A) - DSP2 Control 22 - */ -#define WM2200_DSP2_DM_SIZE_MASK 0xFFFF /* DSP2_DM_SIZE - [15:0] */ -#define WM2200_DSP2_DM_SIZE_SHIFT 0 /* DSP2_DM_SIZE - [15:0] */ -#define WM2200_DSP2_DM_SIZE_WIDTH 16 /* DSP2_DM_SIZE - [15:0] */ - -/* - * R2843 (0xB1B) - DSP2 Control 23 - */ -#define WM2200_DSP2_PM_SIZE_MASK 0xFFFF /* DSP2_PM_SIZE - [15:0] */ -#define WM2200_DSP2_PM_SIZE_SHIFT 0 /* DSP2_PM_SIZE - [15:0] */ -#define WM2200_DSP2_PM_SIZE_WIDTH 16 /* DSP2_PM_SIZE - [15:0] */ - -/* - * R2844 (0xB1C) - DSP2 Control 24 - */ -#define WM2200_DSP2_ZM_SIZE_MASK 0xFFFF /* DSP2_ZM_SIZE - [15:0] */ -#define WM2200_DSP2_ZM_SIZE_SHIFT 0 /* DSP2_ZM_SIZE - [15:0] */ -#define WM2200_DSP2_ZM_SIZE_WIDTH 16 /* DSP2_ZM_SIZE - [15:0] */ - -/* - * R2846 (0xB1E) - DSP2 Control 25 - */ -#define WM2200_DSP2_PING_FULL 0x8000 /* DSP2_PING_FULL */ -#define WM2200_DSP2_PING_FULL_MASK 0x8000 /* DSP2_PING_FULL */ -#define WM2200_DSP2_PING_FULL_SHIFT 15 /* DSP2_PING_FULL */ -#define WM2200_DSP2_PING_FULL_WIDTH 1 /* DSP2_PING_FULL */ -#define WM2200_DSP2_PONG_FULL 0x4000 /* DSP2_PONG_FULL */ -#define WM2200_DSP2_PONG_FULL_MASK 0x4000 /* DSP2_PONG_FULL */ -#define WM2200_DSP2_PONG_FULL_SHIFT 14 /* DSP2_PONG_FULL */ -#define WM2200_DSP2_PONG_FULL_WIDTH 1 /* DSP2_PONG_FULL */ -#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */ -#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */ -#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */ - -/* - * R2848 (0xB20) - DSP2 Control 26 - */ -#define WM2200_DSP2_SCRATCH_0_MASK 0xFFFF /* DSP2_SCRATCH_0 - [15:0] */ -#define WM2200_DSP2_SCRATCH_0_SHIFT 0 /* DSP2_SCRATCH_0 - [15:0] */ -#define WM2200_DSP2_SCRATCH_0_WIDTH 16 /* DSP2_SCRATCH_0 - [15:0] */ - -/* - * R2849 (0xB21) - DSP2 Control 27 - */ -#define WM2200_DSP2_SCRATCH_1_MASK 0xFFFF /* DSP2_SCRATCH_1 - [15:0] */ -#define WM2200_DSP2_SCRATCH_1_SHIFT 0 /* DSP2_SCRATCH_1 - [15:0] */ -#define WM2200_DSP2_SCRATCH_1_WIDTH 16 /* DSP2_SCRATCH_1 - [15:0] */ - -/* - * R2850 (0xB22) - DSP2 Control 28 - */ -#define WM2200_DSP2_SCRATCH_2_MASK 0xFFFF /* DSP2_SCRATCH_2 - [15:0] */ -#define WM2200_DSP2_SCRATCH_2_SHIFT 0 /* DSP2_SCRATCH_2 - [15:0] */ -#define WM2200_DSP2_SCRATCH_2_WIDTH 16 /* DSP2_SCRATCH_2 - [15:0] */ - -/* - * R2851 (0xB23) - DSP2 Control 29 - */ -#define WM2200_DSP2_SCRATCH_3_MASK 0xFFFF /* DSP2_SCRATCH_3 - [15:0] */ -#define WM2200_DSP2_SCRATCH_3_SHIFT 0 /* DSP2_SCRATCH_3 - [15:0] */ -#define WM2200_DSP2_SCRATCH_3_WIDTH 16 /* DSP2_SCRATCH_3 - [15:0] */ - -/* - * R2852 (0xB24) - DSP2 Control 30 - */ -#define WM2200_DSP2_DBG_CLK_ENA 0x0008 /* DSP2_DBG_CLK_ENA */ -#define WM2200_DSP2_DBG_CLK_ENA_MASK 0x0008 /* DSP2_DBG_CLK_ENA */ -#define WM2200_DSP2_DBG_CLK_ENA_SHIFT 3 /* DSP2_DBG_CLK_ENA */ -#define WM2200_DSP2_DBG_CLK_ENA_WIDTH 1 /* DSP2_DBG_CLK_ENA */ -#define WM2200_DSP2_SYS_ENA 0x0004 /* DSP2_SYS_ENA */ -#define WM2200_DSP2_SYS_ENA_MASK 0x0004 /* DSP2_SYS_ENA */ -#define WM2200_DSP2_SYS_ENA_SHIFT 2 /* DSP2_SYS_ENA */ -#define WM2200_DSP2_SYS_ENA_WIDTH 1 /* DSP2_SYS_ENA */ -#define WM2200_DSP2_CORE_ENA 0x0002 /* DSP2_CORE_ENA */ -#define WM2200_DSP2_CORE_ENA_MASK 0x0002 /* DSP2_CORE_ENA */ -#define WM2200_DSP2_CORE_ENA_SHIFT 1 /* DSP2_CORE_ENA */ -#define WM2200_DSP2_CORE_ENA_WIDTH 1 /* DSP2_CORE_ENA */ -#define WM2200_DSP2_START 0x0001 /* DSP2_START */ -#define WM2200_DSP2_START_MASK 0x0001 /* DSP2_START */ -#define WM2200_DSP2_START_SHIFT 0 /* DSP2_START */ -#define WM2200_DSP2_START_WIDTH 1 /* DSP2_START */ - -/* - * R2854 (0xB26) - DSP2 Control 31 - */ -#define WM2200_DSP2_CLK_RATE_MASK 0x0018 /* DSP2_CLK_RATE - [4:3] */ -#define WM2200_DSP2_CLK_RATE_SHIFT 3 /* DSP2_CLK_RATE - [4:3] */ -#define WM2200_DSP2_CLK_RATE_WIDTH 2 /* DSP2_CLK_RATE - [4:3] */ -#define WM2200_DSP2_CLK_AVAIL 0x0004 /* DSP2_CLK_AVAIL */ -#define WM2200_DSP2_CLK_AVAIL_MASK 0x0004 /* DSP2_CLK_AVAIL */ -#define WM2200_DSP2_CLK_AVAIL_SHIFT 2 /* DSP2_CLK_AVAIL */ -#define WM2200_DSP2_CLK_AVAIL_WIDTH 1 /* DSP2_CLK_AVAIL */ -#define WM2200_DSP2_CLK_REQ_MASK 0x0003 /* DSP2_CLK_REQ - [1:0] */ -#define WM2200_DSP2_CLK_REQ_SHIFT 0 /* DSP2_CLK_REQ - [1:0] */ -#define WM2200_DSP2_CLK_REQ_WIDTH 2 /* DSP2_CLK_REQ - [1:0] */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm5100-tables.c b/ANDROID_3.4.5/sound/soc/codecs/wm5100-tables.c deleted file mode 100644 index 9a18fae6..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm5100-tables.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* - * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data - * - * Copyright 2011 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "wm5100.h" - -bool wm5100_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM5100_SOFTWARE_RESET: - case WM5100_DEVICE_REVISION: - case WM5100_FX_CTRL: - case WM5100_INTERRUPT_STATUS_1: - case WM5100_INTERRUPT_STATUS_2: - case WM5100_INTERRUPT_STATUS_3: - case WM5100_INTERRUPT_STATUS_4: - case WM5100_INTERRUPT_RAW_STATUS_2: - case WM5100_INTERRUPT_RAW_STATUS_3: - case WM5100_INTERRUPT_RAW_STATUS_4: - case WM5100_OUTPUT_STATUS_1: - case WM5100_OUTPUT_STATUS_2: - case WM5100_INPUT_ENABLES_STATUS: - case WM5100_MIC_DETECT_3: - return 1; - default: - return 0; - } -} - -bool wm5100_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM5100_SOFTWARE_RESET: - case WM5100_DEVICE_REVISION: - case WM5100_CTRL_IF_1: - case WM5100_TONE_GENERATOR_1: - case WM5100_PWM_DRIVE_1: - case WM5100_PWM_DRIVE_2: - case WM5100_PWM_DRIVE_3: - case WM5100_CLOCKING_1: - case WM5100_CLOCKING_3: - case WM5100_CLOCKING_4: - case WM5100_CLOCKING_5: - case WM5100_CLOCKING_6: - case WM5100_CLOCKING_7: - case WM5100_CLOCKING_8: - case WM5100_ASRC_ENABLE: - case WM5100_ASRC_STATUS: - case WM5100_ASRC_RATE1: - case WM5100_ISRC_1_CTRL_1: - case WM5100_ISRC_1_CTRL_2: - case WM5100_ISRC_2_CTRL1: - case WM5100_ISRC_2_CTRL_2: - case WM5100_FLL1_CONTROL_1: - case WM5100_FLL1_CONTROL_2: - case WM5100_FLL1_CONTROL_3: - case WM5100_FLL1_CONTROL_5: - case WM5100_FLL1_CONTROL_6: - case WM5100_FLL1_EFS_1: - case WM5100_FLL2_CONTROL_1: - case WM5100_FLL2_CONTROL_2: - case WM5100_FLL2_CONTROL_3: - case WM5100_FLL2_CONTROL_5: - case WM5100_FLL2_CONTROL_6: - case WM5100_FLL2_EFS_1: - case WM5100_MIC_CHARGE_PUMP_1: - case WM5100_MIC_CHARGE_PUMP_2: - case WM5100_HP_CHARGE_PUMP_1: - case WM5100_LDO1_CONTROL: - case WM5100_MIC_BIAS_CTRL_1: - case WM5100_MIC_BIAS_CTRL_2: - case WM5100_MIC_BIAS_CTRL_3: - case WM5100_ACCESSORY_DETECT_MODE_1: - case WM5100_HEADPHONE_DETECT_1: - case WM5100_HEADPHONE_DETECT_2: - case WM5100_MIC_DETECT_1: - case WM5100_MIC_DETECT_2: - case WM5100_MIC_DETECT_3: - case WM5100_MISC_CONTROL: - case WM5100_INPUT_ENABLES: - case WM5100_INPUT_ENABLES_STATUS: - case WM5100_IN1L_CONTROL: - case WM5100_IN1R_CONTROL: - case WM5100_IN2L_CONTROL: - case WM5100_IN2R_CONTROL: - case WM5100_IN3L_CONTROL: - case WM5100_IN3R_CONTROL: - case WM5100_IN4L_CONTROL: - case WM5100_IN4R_CONTROL: - case WM5100_RXANC_SRC: - case WM5100_INPUT_VOLUME_RAMP: - case WM5100_ADC_DIGITAL_VOLUME_1L: - case WM5100_ADC_DIGITAL_VOLUME_1R: - case WM5100_ADC_DIGITAL_VOLUME_2L: - case WM5100_ADC_DIGITAL_VOLUME_2R: - case WM5100_ADC_DIGITAL_VOLUME_3L: - case WM5100_ADC_DIGITAL_VOLUME_3R: - case WM5100_ADC_DIGITAL_VOLUME_4L: - case WM5100_ADC_DIGITAL_VOLUME_4R: - case WM5100_OUTPUT_ENABLES_2: - case WM5100_OUTPUT_STATUS_1: - case WM5100_OUTPUT_STATUS_2: - case WM5100_CHANNEL_ENABLES_1: - case WM5100_OUT_VOLUME_1L: - case WM5100_OUT_VOLUME_1R: - case WM5100_DAC_VOLUME_LIMIT_1L: - case WM5100_DAC_VOLUME_LIMIT_1R: - case WM5100_OUT_VOLUME_2L: - case WM5100_OUT_VOLUME_2R: - case WM5100_DAC_VOLUME_LIMIT_2L: - case WM5100_DAC_VOLUME_LIMIT_2R: - case WM5100_OUT_VOLUME_3L: - case WM5100_OUT_VOLUME_3R: - case WM5100_DAC_VOLUME_LIMIT_3L: - case WM5100_DAC_VOLUME_LIMIT_3R: - case WM5100_OUT_VOLUME_4L: - case WM5100_OUT_VOLUME_4R: - case WM5100_DAC_VOLUME_LIMIT_5L: - case WM5100_DAC_VOLUME_LIMIT_5R: - case WM5100_DAC_VOLUME_LIMIT_6L: - case WM5100_DAC_VOLUME_LIMIT_6R: - case WM5100_DAC_AEC_CONTROL_1: - case WM5100_OUTPUT_VOLUME_RAMP: - case WM5100_DAC_DIGITAL_VOLUME_1L: - case WM5100_DAC_DIGITAL_VOLUME_1R: - case WM5100_DAC_DIGITAL_VOLUME_2L: - case WM5100_DAC_DIGITAL_VOLUME_2R: - case WM5100_DAC_DIGITAL_VOLUME_3L: - case WM5100_DAC_DIGITAL_VOLUME_3R: - case WM5100_DAC_DIGITAL_VOLUME_4L: - case WM5100_DAC_DIGITAL_VOLUME_4R: - case WM5100_DAC_DIGITAL_VOLUME_5L: - case WM5100_DAC_DIGITAL_VOLUME_5R: - case WM5100_DAC_DIGITAL_VOLUME_6L: - case WM5100_DAC_DIGITAL_VOLUME_6R: - case WM5100_PDM_SPK1_CTRL_1: - case WM5100_PDM_SPK1_CTRL_2: - case WM5100_PDM_SPK2_CTRL_1: - case WM5100_PDM_SPK2_CTRL_2: - case WM5100_AUDIO_IF_1_1: - case WM5100_AUDIO_IF_1_2: - case WM5100_AUDIO_IF_1_3: - case WM5100_AUDIO_IF_1_4: - case WM5100_AUDIO_IF_1_5: - case WM5100_AUDIO_IF_1_6: - case WM5100_AUDIO_IF_1_7: - case WM5100_AUDIO_IF_1_8: - case WM5100_AUDIO_IF_1_9: - case WM5100_AUDIO_IF_1_10: - case WM5100_AUDIO_IF_1_11: - case WM5100_AUDIO_IF_1_12: - case WM5100_AUDIO_IF_1_13: - case WM5100_AUDIO_IF_1_14: - case WM5100_AUDIO_IF_1_15: - case WM5100_AUDIO_IF_1_16: - case WM5100_AUDIO_IF_1_17: - case WM5100_AUDIO_IF_1_18: - case WM5100_AUDIO_IF_1_19: - case WM5100_AUDIO_IF_1_20: - case WM5100_AUDIO_IF_1_21: - case WM5100_AUDIO_IF_1_22: - case WM5100_AUDIO_IF_1_23: - case WM5100_AUDIO_IF_1_24: - case WM5100_AUDIO_IF_1_25: - case WM5100_AUDIO_IF_1_26: - case WM5100_AUDIO_IF_1_27: - case WM5100_AUDIO_IF_2_1: - case WM5100_AUDIO_IF_2_2: - case WM5100_AUDIO_IF_2_3: - case WM5100_AUDIO_IF_2_4: - case WM5100_AUDIO_IF_2_5: - case WM5100_AUDIO_IF_2_6: - case WM5100_AUDIO_IF_2_7: - case WM5100_AUDIO_IF_2_8: - case WM5100_AUDIO_IF_2_9: - case WM5100_AUDIO_IF_2_10: - case WM5100_AUDIO_IF_2_11: - case WM5100_AUDIO_IF_2_18: - case WM5100_AUDIO_IF_2_19: - case WM5100_AUDIO_IF_2_26: - case WM5100_AUDIO_IF_2_27: - case WM5100_AUDIO_IF_3_1: - case WM5100_AUDIO_IF_3_2: - case WM5100_AUDIO_IF_3_3: - case WM5100_AUDIO_IF_3_4: - case WM5100_AUDIO_IF_3_5: - case WM5100_AUDIO_IF_3_6: - case WM5100_AUDIO_IF_3_7: - case WM5100_AUDIO_IF_3_8: - case WM5100_AUDIO_IF_3_9: - case WM5100_AUDIO_IF_3_10: - case WM5100_AUDIO_IF_3_11: - case WM5100_AUDIO_IF_3_18: - case WM5100_AUDIO_IF_3_19: - case WM5100_AUDIO_IF_3_26: - case WM5100_AUDIO_IF_3_27: - case WM5100_PWM1MIX_INPUT_1_SOURCE: - case WM5100_PWM1MIX_INPUT_1_VOLUME: - case WM5100_PWM1MIX_INPUT_2_SOURCE: - case WM5100_PWM1MIX_INPUT_2_VOLUME: - case WM5100_PWM1MIX_INPUT_3_SOURCE: - case WM5100_PWM1MIX_INPUT_3_VOLUME: - case WM5100_PWM1MIX_INPUT_4_SOURCE: - case WM5100_PWM1MIX_INPUT_4_VOLUME: - case WM5100_PWM2MIX_INPUT_1_SOURCE: - case WM5100_PWM2MIX_INPUT_1_VOLUME: - case WM5100_PWM2MIX_INPUT_2_SOURCE: - case WM5100_PWM2MIX_INPUT_2_VOLUME: - case WM5100_PWM2MIX_INPUT_3_SOURCE: - case WM5100_PWM2MIX_INPUT_3_VOLUME: - case WM5100_PWM2MIX_INPUT_4_SOURCE: - case WM5100_PWM2MIX_INPUT_4_VOLUME: - case WM5100_OUT1LMIX_INPUT_1_SOURCE: - case WM5100_OUT1LMIX_INPUT_1_VOLUME: - case WM5100_OUT1LMIX_INPUT_2_SOURCE: - case WM5100_OUT1LMIX_INPUT_2_VOLUME: - case WM5100_OUT1LMIX_INPUT_3_SOURCE: - case WM5100_OUT1LMIX_INPUT_3_VOLUME: - case WM5100_OUT1LMIX_INPUT_4_SOURCE: - case WM5100_OUT1LMIX_INPUT_4_VOLUME: - case WM5100_OUT1RMIX_INPUT_1_SOURCE: - case WM5100_OUT1RMIX_INPUT_1_VOLUME: - case WM5100_OUT1RMIX_INPUT_2_SOURCE: - case WM5100_OUT1RMIX_INPUT_2_VOLUME: - case WM5100_OUT1RMIX_INPUT_3_SOURCE: - case WM5100_OUT1RMIX_INPUT_3_VOLUME: - case WM5100_OUT1RMIX_INPUT_4_SOURCE: - case WM5100_OUT1RMIX_INPUT_4_VOLUME: - case WM5100_OUT2LMIX_INPUT_1_SOURCE: - case WM5100_OUT2LMIX_INPUT_1_VOLUME: - case WM5100_OUT2LMIX_INPUT_2_SOURCE: - case WM5100_OUT2LMIX_INPUT_2_VOLUME: - case WM5100_OUT2LMIX_INPUT_3_SOURCE: - case WM5100_OUT2LMIX_INPUT_3_VOLUME: - case WM5100_OUT2LMIX_INPUT_4_SOURCE: - case WM5100_OUT2LMIX_INPUT_4_VOLUME: - case WM5100_OUT2RMIX_INPUT_1_SOURCE: - case WM5100_OUT2RMIX_INPUT_1_VOLUME: - case WM5100_OUT2RMIX_INPUT_2_SOURCE: - case WM5100_OUT2RMIX_INPUT_2_VOLUME: - case WM5100_OUT2RMIX_INPUT_3_SOURCE: - case WM5100_OUT2RMIX_INPUT_3_VOLUME: - case WM5100_OUT2RMIX_INPUT_4_SOURCE: - case WM5100_OUT2RMIX_INPUT_4_VOLUME: - case WM5100_OUT3LMIX_INPUT_1_SOURCE: - case WM5100_OUT3LMIX_INPUT_1_VOLUME: - case WM5100_OUT3LMIX_INPUT_2_SOURCE: - case WM5100_OUT3LMIX_INPUT_2_VOLUME: - case WM5100_OUT3LMIX_INPUT_3_SOURCE: - case WM5100_OUT3LMIX_INPUT_3_VOLUME: - case WM5100_OUT3LMIX_INPUT_4_SOURCE: - case WM5100_OUT3LMIX_INPUT_4_VOLUME: - case WM5100_OUT3RMIX_INPUT_1_SOURCE: - case WM5100_OUT3RMIX_INPUT_1_VOLUME: - case WM5100_OUT3RMIX_INPUT_2_SOURCE: - case WM5100_OUT3RMIX_INPUT_2_VOLUME: - case WM5100_OUT3RMIX_INPUT_3_SOURCE: - case WM5100_OUT3RMIX_INPUT_3_VOLUME: - case WM5100_OUT3RMIX_INPUT_4_SOURCE: - case WM5100_OUT3RMIX_INPUT_4_VOLUME: - case WM5100_OUT4LMIX_INPUT_1_SOURCE: - case WM5100_OUT4LMIX_INPUT_1_VOLUME: - case WM5100_OUT4LMIX_INPUT_2_SOURCE: - case WM5100_OUT4LMIX_INPUT_2_VOLUME: - case WM5100_OUT4LMIX_INPUT_3_SOURCE: - case WM5100_OUT4LMIX_INPUT_3_VOLUME: - case WM5100_OUT4LMIX_INPUT_4_SOURCE: - case WM5100_OUT4LMIX_INPUT_4_VOLUME: - case WM5100_OUT4RMIX_INPUT_1_SOURCE: - case WM5100_OUT4RMIX_INPUT_1_VOLUME: - case WM5100_OUT4RMIX_INPUT_2_SOURCE: - case WM5100_OUT4RMIX_INPUT_2_VOLUME: - case WM5100_OUT4RMIX_INPUT_3_SOURCE: - case WM5100_OUT4RMIX_INPUT_3_VOLUME: - case WM5100_OUT4RMIX_INPUT_4_SOURCE: - case WM5100_OUT4RMIX_INPUT_4_VOLUME: - case WM5100_OUT5LMIX_INPUT_1_SOURCE: - case WM5100_OUT5LMIX_INPUT_1_VOLUME: - case WM5100_OUT5LMIX_INPUT_2_SOURCE: - case WM5100_OUT5LMIX_INPUT_2_VOLUME: - case WM5100_OUT5LMIX_INPUT_3_SOURCE: - case WM5100_OUT5LMIX_INPUT_3_VOLUME: - case WM5100_OUT5LMIX_INPUT_4_SOURCE: - case WM5100_OUT5LMIX_INPUT_4_VOLUME: - case WM5100_OUT5RMIX_INPUT_1_SOURCE: - case WM5100_OUT5RMIX_INPUT_1_VOLUME: - case WM5100_OUT5RMIX_INPUT_2_SOURCE: - case WM5100_OUT5RMIX_INPUT_2_VOLUME: - case WM5100_OUT5RMIX_INPUT_3_SOURCE: - case WM5100_OUT5RMIX_INPUT_3_VOLUME: - case WM5100_OUT5RMIX_INPUT_4_SOURCE: - case WM5100_OUT5RMIX_INPUT_4_VOLUME: - case WM5100_OUT6LMIX_INPUT_1_SOURCE: - case WM5100_OUT6LMIX_INPUT_1_VOLUME: - case WM5100_OUT6LMIX_INPUT_2_SOURCE: - case WM5100_OUT6LMIX_INPUT_2_VOLUME: - case WM5100_OUT6LMIX_INPUT_3_SOURCE: - case WM5100_OUT6LMIX_INPUT_3_VOLUME: - case WM5100_OUT6LMIX_INPUT_4_SOURCE: - case WM5100_OUT6LMIX_INPUT_4_VOLUME: - case WM5100_OUT6RMIX_INPUT_1_SOURCE: - case WM5100_OUT6RMIX_INPUT_1_VOLUME: - case WM5100_OUT6RMIX_INPUT_2_SOURCE: - case WM5100_OUT6RMIX_INPUT_2_VOLUME: - case WM5100_OUT6RMIX_INPUT_3_SOURCE: - case WM5100_OUT6RMIX_INPUT_3_VOLUME: - case WM5100_OUT6RMIX_INPUT_4_SOURCE: - case WM5100_OUT6RMIX_INPUT_4_VOLUME: - case WM5100_AIF1TX1MIX_INPUT_1_SOURCE: - case WM5100_AIF1TX1MIX_INPUT_1_VOLUME: - case WM5100_AIF1TX1MIX_INPUT_2_SOURCE: - case WM5100_AIF1TX1MIX_INPUT_2_VOLUME: - case WM5100_AIF1TX1MIX_INPUT_3_SOURCE: - case WM5100_AIF1TX1MIX_INPUT_3_VOLUME: - case WM5100_AIF1TX1MIX_INPUT_4_SOURCE: - case WM5100_AIF1TX1MIX_INPUT_4_VOLUME: - case WM5100_AIF1TX2MIX_INPUT_1_SOURCE: - case WM5100_AIF1TX2MIX_INPUT_1_VOLUME: - case WM5100_AIF1TX2MIX_INPUT_2_SOURCE: - case WM5100_AIF1TX2MIX_INPUT_2_VOLUME: - case WM5100_AIF1TX2MIX_INPUT_3_SOURCE: - case WM5100_AIF1TX2MIX_INPUT_3_VOLUME: - case WM5100_AIF1TX2MIX_INPUT_4_SOURCE: - case WM5100_AIF1TX2MIX_INPUT_4_VOLUME: - case WM5100_AIF1TX3MIX_INPUT_1_SOURCE: - case WM5100_AIF1TX3MIX_INPUT_1_VOLUME: - case WM5100_AIF1TX3MIX_INPUT_2_SOURCE: - case WM5100_AIF1TX3MIX_INPUT_2_VOLUME: - case WM5100_AIF1TX3MIX_INPUT_3_SOURCE: - case WM5100_AIF1TX3MIX_INPUT_3_VOLUME: - case WM5100_AIF1TX3MIX_INPUT_4_SOURCE: - case WM5100_AIF1TX3MIX_INPUT_4_VOLUME: - case WM5100_AIF1TX4MIX_INPUT_1_SOURCE: - case WM5100_AIF1TX4MIX_INPUT_1_VOLUME: - case WM5100_AIF1TX4MIX_INPUT_2_SOURCE: - case WM5100_AIF1TX4MIX_INPUT_2_VOLUME: - case WM5100_AIF1TX4MIX_INPUT_3_SOURCE: - case WM5100_AIF1TX4MIX_INPUT_3_VOLUME: - case WM5100_AIF1TX4MIX_INPUT_4_SOURCE: - case WM5100_AIF1TX4MIX_INPUT_4_VOLUME: - case WM5100_AIF1TX5MIX_INPUT_1_SOURCE: - case WM5100_AIF1TX5MIX_INPUT_1_VOLUME: - case WM5100_AIF1TX5MIX_INPUT_2_SOURCE: - case WM5100_AIF1TX5MIX_INPUT_2_VOLUME: - case WM5100_AIF1TX5MIX_INPUT_3_SOURCE: - case WM5100_AIF1TX5MIX_INPUT_3_VOLUME: - case WM5100_AIF1TX5MIX_INPUT_4_SOURCE: - case WM5100_AIF1TX5MIX_INPUT_4_VOLUME: - case WM5100_AIF1TX6MIX_INPUT_1_SOURCE: - case WM5100_AIF1TX6MIX_INPUT_1_VOLUME: - case WM5100_AIF1TX6MIX_INPUT_2_SOURCE: - case WM5100_AIF1TX6MIX_INPUT_2_VOLUME: - case WM5100_AIF1TX6MIX_INPUT_3_SOURCE: - case WM5100_AIF1TX6MIX_INPUT_3_VOLUME: - case WM5100_AIF1TX6MIX_INPUT_4_SOURCE: - case WM5100_AIF1TX6MIX_INPUT_4_VOLUME: - case WM5100_AIF1TX7MIX_INPUT_1_SOURCE: - case WM5100_AIF1TX7MIX_INPUT_1_VOLUME: - case WM5100_AIF1TX7MIX_INPUT_2_SOURCE: - case WM5100_AIF1TX7MIX_INPUT_2_VOLUME: - case WM5100_AIF1TX7MIX_INPUT_3_SOURCE: - case WM5100_AIF1TX7MIX_INPUT_3_VOLUME: - case WM5100_AIF1TX7MIX_INPUT_4_SOURCE: - case WM5100_AIF1TX7MIX_INPUT_4_VOLUME: - case WM5100_AIF1TX8MIX_INPUT_1_SOURCE: - case WM5100_AIF1TX8MIX_INPUT_1_VOLUME: - case WM5100_AIF1TX8MIX_INPUT_2_SOURCE: - case WM5100_AIF1TX8MIX_INPUT_2_VOLUME: - case WM5100_AIF1TX8MIX_INPUT_3_SOURCE: - case WM5100_AIF1TX8MIX_INPUT_3_VOLUME: - case WM5100_AIF1TX8MIX_INPUT_4_SOURCE: - case WM5100_AIF1TX8MIX_INPUT_4_VOLUME: - case WM5100_AIF2TX1MIX_INPUT_1_SOURCE: - case WM5100_AIF2TX1MIX_INPUT_1_VOLUME: - case WM5100_AIF2TX1MIX_INPUT_2_SOURCE: - case WM5100_AIF2TX1MIX_INPUT_2_VOLUME: - case WM5100_AIF2TX1MIX_INPUT_3_SOURCE: - case WM5100_AIF2TX1MIX_INPUT_3_VOLUME: - case WM5100_AIF2TX1MIX_INPUT_4_SOURCE: - case WM5100_AIF2TX1MIX_INPUT_4_VOLUME: - case WM5100_AIF2TX2MIX_INPUT_1_SOURCE: - case WM5100_AIF2TX2MIX_INPUT_1_VOLUME: - case WM5100_AIF2TX2MIX_INPUT_2_SOURCE: - case WM5100_AIF2TX2MIX_INPUT_2_VOLUME: - case WM5100_AIF2TX2MIX_INPUT_3_SOURCE: - case WM5100_AIF2TX2MIX_INPUT_3_VOLUME: - case WM5100_AIF2TX2MIX_INPUT_4_SOURCE: - case WM5100_AIF2TX2MIX_INPUT_4_VOLUME: - case WM5100_AIF3TX1MIX_INPUT_1_SOURCE: - case WM5100_AIF3TX1MIX_INPUT_1_VOLUME: - case WM5100_AIF3TX1MIX_INPUT_2_SOURCE: - case WM5100_AIF3TX1MIX_INPUT_2_VOLUME: - case WM5100_AIF3TX1MIX_INPUT_3_SOURCE: - case WM5100_AIF3TX1MIX_INPUT_3_VOLUME: - case WM5100_AIF3TX1MIX_INPUT_4_SOURCE: - case WM5100_AIF3TX1MIX_INPUT_4_VOLUME: - case WM5100_AIF3TX2MIX_INPUT_1_SOURCE: - case WM5100_AIF3TX2MIX_INPUT_1_VOLUME: - case WM5100_AIF3TX2MIX_INPUT_2_SOURCE: - case WM5100_AIF3TX2MIX_INPUT_2_VOLUME: - case WM5100_AIF3TX2MIX_INPUT_3_SOURCE: - case WM5100_AIF3TX2MIX_INPUT_3_VOLUME: - case WM5100_AIF3TX2MIX_INPUT_4_SOURCE: - case WM5100_AIF3TX2MIX_INPUT_4_VOLUME: - case WM5100_EQ1MIX_INPUT_1_SOURCE: - case WM5100_EQ1MIX_INPUT_1_VOLUME: - case WM5100_EQ1MIX_INPUT_2_SOURCE: - case WM5100_EQ1MIX_INPUT_2_VOLUME: - case WM5100_EQ1MIX_INPUT_3_SOURCE: - case WM5100_EQ1MIX_INPUT_3_VOLUME: - case WM5100_EQ1MIX_INPUT_4_SOURCE: - case WM5100_EQ1MIX_INPUT_4_VOLUME: - case WM5100_EQ2MIX_INPUT_1_SOURCE: - case WM5100_EQ2MIX_INPUT_1_VOLUME: - case WM5100_EQ2MIX_INPUT_2_SOURCE: - case WM5100_EQ2MIX_INPUT_2_VOLUME: - case WM5100_EQ2MIX_INPUT_3_SOURCE: - case WM5100_EQ2MIX_INPUT_3_VOLUME: - case WM5100_EQ2MIX_INPUT_4_SOURCE: - case WM5100_EQ2MIX_INPUT_4_VOLUME: - case WM5100_EQ3MIX_INPUT_1_SOURCE: - case WM5100_EQ3MIX_INPUT_1_VOLUME: - case WM5100_EQ3MIX_INPUT_2_SOURCE: - case WM5100_EQ3MIX_INPUT_2_VOLUME: - case WM5100_EQ3MIX_INPUT_3_SOURCE: - case WM5100_EQ3MIX_INPUT_3_VOLUME: - case WM5100_EQ3MIX_INPUT_4_SOURCE: - case WM5100_EQ3MIX_INPUT_4_VOLUME: - case WM5100_EQ4MIX_INPUT_1_SOURCE: - case WM5100_EQ4MIX_INPUT_1_VOLUME: - case WM5100_EQ4MIX_INPUT_2_SOURCE: - case WM5100_EQ4MIX_INPUT_2_VOLUME: - case WM5100_EQ4MIX_INPUT_3_SOURCE: - case WM5100_EQ4MIX_INPUT_3_VOLUME: - case WM5100_EQ4MIX_INPUT_4_SOURCE: - case WM5100_EQ4MIX_INPUT_4_VOLUME: - case WM5100_DRC1LMIX_INPUT_1_SOURCE: - case WM5100_DRC1LMIX_INPUT_1_VOLUME: - case WM5100_DRC1LMIX_INPUT_2_SOURCE: - case WM5100_DRC1LMIX_INPUT_2_VOLUME: - case WM5100_DRC1LMIX_INPUT_3_SOURCE: - case WM5100_DRC1LMIX_INPUT_3_VOLUME: - case WM5100_DRC1LMIX_INPUT_4_SOURCE: - case WM5100_DRC1LMIX_INPUT_4_VOLUME: - case WM5100_DRC1RMIX_INPUT_1_SOURCE: - case WM5100_DRC1RMIX_INPUT_1_VOLUME: - case WM5100_DRC1RMIX_INPUT_2_SOURCE: - case WM5100_DRC1RMIX_INPUT_2_VOLUME: - case WM5100_DRC1RMIX_INPUT_3_SOURCE: - case WM5100_DRC1RMIX_INPUT_3_VOLUME: - case WM5100_DRC1RMIX_INPUT_4_SOURCE: - case WM5100_DRC1RMIX_INPUT_4_VOLUME: - case WM5100_HPLP1MIX_INPUT_1_SOURCE: - case WM5100_HPLP1MIX_INPUT_1_VOLUME: - case WM5100_HPLP1MIX_INPUT_2_SOURCE: - case WM5100_HPLP1MIX_INPUT_2_VOLUME: - case WM5100_HPLP1MIX_INPUT_3_SOURCE: - case WM5100_HPLP1MIX_INPUT_3_VOLUME: - case WM5100_HPLP1MIX_INPUT_4_SOURCE: - case WM5100_HPLP1MIX_INPUT_4_VOLUME: - case WM5100_HPLP2MIX_INPUT_1_SOURCE: - case WM5100_HPLP2MIX_INPUT_1_VOLUME: - case WM5100_HPLP2MIX_INPUT_2_SOURCE: - case WM5100_HPLP2MIX_INPUT_2_VOLUME: - case WM5100_HPLP2MIX_INPUT_3_SOURCE: - case WM5100_HPLP2MIX_INPUT_3_VOLUME: - case WM5100_HPLP2MIX_INPUT_4_SOURCE: - case WM5100_HPLP2MIX_INPUT_4_VOLUME: - case WM5100_HPLP3MIX_INPUT_1_SOURCE: - case WM5100_HPLP3MIX_INPUT_1_VOLUME: - case WM5100_HPLP3MIX_INPUT_2_SOURCE: - case WM5100_HPLP3MIX_INPUT_2_VOLUME: - case WM5100_HPLP3MIX_INPUT_3_SOURCE: - case WM5100_HPLP3MIX_INPUT_3_VOLUME: - case WM5100_HPLP3MIX_INPUT_4_SOURCE: - case WM5100_HPLP3MIX_INPUT_4_VOLUME: - case WM5100_HPLP4MIX_INPUT_1_SOURCE: - case WM5100_HPLP4MIX_INPUT_1_VOLUME: - case WM5100_HPLP4MIX_INPUT_2_SOURCE: - case WM5100_HPLP4MIX_INPUT_2_VOLUME: - case WM5100_HPLP4MIX_INPUT_3_SOURCE: - case WM5100_HPLP4MIX_INPUT_3_VOLUME: - case WM5100_HPLP4MIX_INPUT_4_SOURCE: - case WM5100_HPLP4MIX_INPUT_4_VOLUME: - case WM5100_DSP1LMIX_INPUT_1_SOURCE: - case WM5100_DSP1LMIX_INPUT_1_VOLUME: - case WM5100_DSP1LMIX_INPUT_2_SOURCE: - case WM5100_DSP1LMIX_INPUT_2_VOLUME: - case WM5100_DSP1LMIX_INPUT_3_SOURCE: - case WM5100_DSP1LMIX_INPUT_3_VOLUME: - case WM5100_DSP1LMIX_INPUT_4_SOURCE: - case WM5100_DSP1LMIX_INPUT_4_VOLUME: - case WM5100_DSP1RMIX_INPUT_1_SOURCE: - case WM5100_DSP1RMIX_INPUT_1_VOLUME: - case WM5100_DSP1RMIX_INPUT_2_SOURCE: - case WM5100_DSP1RMIX_INPUT_2_VOLUME: - case WM5100_DSP1RMIX_INPUT_3_SOURCE: - case WM5100_DSP1RMIX_INPUT_3_VOLUME: - case WM5100_DSP1RMIX_INPUT_4_SOURCE: - case WM5100_DSP1RMIX_INPUT_4_VOLUME: - case WM5100_DSP1AUX1MIX_INPUT_1_SOURCE: - case WM5100_DSP1AUX2MIX_INPUT_1_SOURCE: - case WM5100_DSP1AUX3MIX_INPUT_1_SOURCE: - case WM5100_DSP1AUX4MIX_INPUT_1_SOURCE: - case WM5100_DSP1AUX5MIX_INPUT_1_SOURCE: - case WM5100_DSP1AUX6MIX_INPUT_1_SOURCE: - case WM5100_DSP2LMIX_INPUT_1_SOURCE: - case WM5100_DSP2LMIX_INPUT_1_VOLUME: - case WM5100_DSP2LMIX_INPUT_2_SOURCE: - case WM5100_DSP2LMIX_INPUT_2_VOLUME: - case WM5100_DSP2LMIX_INPUT_3_SOURCE: - case WM5100_DSP2LMIX_INPUT_3_VOLUME: - case WM5100_DSP2LMIX_INPUT_4_SOURCE: - case WM5100_DSP2LMIX_INPUT_4_VOLUME: - case WM5100_DSP2RMIX_INPUT_1_SOURCE: - case WM5100_DSP2RMIX_INPUT_1_VOLUME: - case WM5100_DSP2RMIX_INPUT_2_SOURCE: - case WM5100_DSP2RMIX_INPUT_2_VOLUME: - case WM5100_DSP2RMIX_INPUT_3_SOURCE: - case WM5100_DSP2RMIX_INPUT_3_VOLUME: - case WM5100_DSP2RMIX_INPUT_4_SOURCE: - case WM5100_DSP2RMIX_INPUT_4_VOLUME: - case WM5100_DSP2AUX1MIX_INPUT_1_SOURCE: - case WM5100_DSP2AUX2MIX_INPUT_1_SOURCE: - case WM5100_DSP2AUX3MIX_INPUT_1_SOURCE: - case WM5100_DSP2AUX4MIX_INPUT_1_SOURCE: - case WM5100_DSP2AUX5MIX_INPUT_1_SOURCE: - case WM5100_DSP2AUX6MIX_INPUT_1_SOURCE: - case WM5100_DSP3LMIX_INPUT_1_SOURCE: - case WM5100_DSP3LMIX_INPUT_1_VOLUME: - case WM5100_DSP3LMIX_INPUT_2_SOURCE: - case WM5100_DSP3LMIX_INPUT_2_VOLUME: - case WM5100_DSP3LMIX_INPUT_3_SOURCE: - case WM5100_DSP3LMIX_INPUT_3_VOLUME: - case WM5100_DSP3LMIX_INPUT_4_SOURCE: - case WM5100_DSP3LMIX_INPUT_4_VOLUME: - case WM5100_DSP3RMIX_INPUT_1_SOURCE: - case WM5100_DSP3RMIX_INPUT_1_VOLUME: - case WM5100_DSP3RMIX_INPUT_2_SOURCE: - case WM5100_DSP3RMIX_INPUT_2_VOLUME: - case WM5100_DSP3RMIX_INPUT_3_SOURCE: - case WM5100_DSP3RMIX_INPUT_3_VOLUME: - case WM5100_DSP3RMIX_INPUT_4_SOURCE: - case WM5100_DSP3RMIX_INPUT_4_VOLUME: - case WM5100_DSP3AUX1MIX_INPUT_1_SOURCE: - case WM5100_DSP3AUX2MIX_INPUT_1_SOURCE: - case WM5100_DSP3AUX3MIX_INPUT_1_SOURCE: - case WM5100_DSP3AUX4MIX_INPUT_1_SOURCE: - case WM5100_DSP3AUX5MIX_INPUT_1_SOURCE: - case WM5100_DSP3AUX6MIX_INPUT_1_SOURCE: - case WM5100_ASRC1LMIX_INPUT_1_SOURCE: - case WM5100_ASRC1RMIX_INPUT_1_SOURCE: - case WM5100_ASRC2LMIX_INPUT_1_SOURCE: - case WM5100_ASRC2RMIX_INPUT_1_SOURCE: - case WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE: - case WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE: - case WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE: - case WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE: - case WM5100_ISRC1INT1MIX_INPUT_1_SOURCE: - case WM5100_ISRC1INT2MIX_INPUT_1_SOURCE: - case WM5100_ISRC1INT3MIX_INPUT_1_SOURCE: - case WM5100_ISRC1INT4MIX_INPUT_1_SOURCE: - case WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE: - case WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE: - case WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE: - case WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE: - case WM5100_ISRC2INT1MIX_INPUT_1_SOURCE: - case WM5100_ISRC2INT2MIX_INPUT_1_SOURCE: - case WM5100_ISRC2INT3MIX_INPUT_1_SOURCE: - case WM5100_ISRC2INT4MIX_INPUT_1_SOURCE: - case WM5100_GPIO_CTRL_1: - case WM5100_GPIO_CTRL_2: - case WM5100_GPIO_CTRL_3: - case WM5100_GPIO_CTRL_4: - case WM5100_GPIO_CTRL_5: - case WM5100_GPIO_CTRL_6: - case WM5100_MISC_PAD_CTRL_1: - case WM5100_MISC_PAD_CTRL_2: - case WM5100_MISC_PAD_CTRL_3: - case WM5100_MISC_PAD_CTRL_4: - case WM5100_MISC_PAD_CTRL_5: - case WM5100_MISC_GPIO_1: - case WM5100_INTERRUPT_STATUS_1: - case WM5100_INTERRUPT_STATUS_2: - case WM5100_INTERRUPT_STATUS_3: - case WM5100_INTERRUPT_STATUS_4: - case WM5100_INTERRUPT_RAW_STATUS_2: - case WM5100_INTERRUPT_RAW_STATUS_3: - case WM5100_INTERRUPT_RAW_STATUS_4: - case WM5100_INTERRUPT_STATUS_1_MASK: - case WM5100_INTERRUPT_STATUS_2_MASK: - case WM5100_INTERRUPT_STATUS_3_MASK: - case WM5100_INTERRUPT_STATUS_4_MASK: - case WM5100_INTERRUPT_CONTROL: - case WM5100_IRQ_DEBOUNCE_1: - case WM5100_IRQ_DEBOUNCE_2: - case WM5100_FX_CTRL: - case WM5100_EQ1_1: - case WM5100_EQ1_2: - case WM5100_EQ1_3: - case WM5100_EQ1_4: - case WM5100_EQ1_5: - case WM5100_EQ1_6: - case WM5100_EQ1_7: - case WM5100_EQ1_8: - case WM5100_EQ1_9: - case WM5100_EQ1_10: - case WM5100_EQ1_11: - case WM5100_EQ1_12: - case WM5100_EQ1_13: - case WM5100_EQ1_14: - case WM5100_EQ1_15: - case WM5100_EQ1_16: - case WM5100_EQ1_17: - case WM5100_EQ1_18: - case WM5100_EQ1_19: - case WM5100_EQ1_20: - case WM5100_EQ2_1: - case WM5100_EQ2_2: - case WM5100_EQ2_3: - case WM5100_EQ2_4: - case WM5100_EQ2_5: - case WM5100_EQ2_6: - case WM5100_EQ2_7: - case WM5100_EQ2_8: - case WM5100_EQ2_9: - case WM5100_EQ2_10: - case WM5100_EQ2_11: - case WM5100_EQ2_12: - case WM5100_EQ2_13: - case WM5100_EQ2_14: - case WM5100_EQ2_15: - case WM5100_EQ2_16: - case WM5100_EQ2_17: - case WM5100_EQ2_18: - case WM5100_EQ2_19: - case WM5100_EQ2_20: - case WM5100_EQ3_1: - case WM5100_EQ3_2: - case WM5100_EQ3_3: - case WM5100_EQ3_4: - case WM5100_EQ3_5: - case WM5100_EQ3_6: - case WM5100_EQ3_7: - case WM5100_EQ3_8: - case WM5100_EQ3_9: - case WM5100_EQ3_10: - case WM5100_EQ3_11: - case WM5100_EQ3_12: - case WM5100_EQ3_13: - case WM5100_EQ3_14: - case WM5100_EQ3_15: - case WM5100_EQ3_16: - case WM5100_EQ3_17: - case WM5100_EQ3_18: - case WM5100_EQ3_19: - case WM5100_EQ3_20: - case WM5100_EQ4_1: - case WM5100_EQ4_2: - case WM5100_EQ4_3: - case WM5100_EQ4_4: - case WM5100_EQ4_5: - case WM5100_EQ4_6: - case WM5100_EQ4_7: - case WM5100_EQ4_8: - case WM5100_EQ4_9: - case WM5100_EQ4_10: - case WM5100_EQ4_11: - case WM5100_EQ4_12: - case WM5100_EQ4_13: - case WM5100_EQ4_14: - case WM5100_EQ4_15: - case WM5100_EQ4_16: - case WM5100_EQ4_17: - case WM5100_EQ4_18: - case WM5100_EQ4_19: - case WM5100_EQ4_20: - case WM5100_DRC1_CTRL1: - case WM5100_DRC1_CTRL2: - case WM5100_DRC1_CTRL3: - case WM5100_DRC1_CTRL4: - case WM5100_DRC1_CTRL5: - case WM5100_HPLPF1_1: - case WM5100_HPLPF1_2: - case WM5100_HPLPF2_1: - case WM5100_HPLPF2_2: - case WM5100_HPLPF3_1: - case WM5100_HPLPF3_2: - case WM5100_HPLPF4_1: - case WM5100_HPLPF4_2: - return 1; - default: - return 0; - } -} - -struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT] = { - { 0x0000, 0x0000 }, /* R0 - software reset */ - { 0x0001, 0x0000 }, /* R1 - Device Revision */ - { 0x0010, 0x0801 }, /* R16 - Ctrl IF 1 */ - { 0x0020, 0x0000 }, /* R32 - Tone Generator 1 */ - { 0x0030, 0x0000 }, /* R48 - PWM Drive 1 */ - { 0x0031, 0x0100 }, /* R49 - PWM Drive 2 */ - { 0x0032, 0x0100 }, /* R50 - PWM Drive 3 */ - { 0x0100, 0x0002 }, /* R256 - Clocking 1 */ - { 0x0101, 0x0000 }, /* R257 - Clocking 3 */ - { 0x0102, 0x0011 }, /* R258 - Clocking 4 */ - { 0x0103, 0x0011 }, /* R259 - Clocking 5 */ - { 0x0104, 0x0011 }, /* R260 - Clocking 6 */ - { 0x0107, 0x0000 }, /* R263 - Clocking 7 */ - { 0x0108, 0x0000 }, /* R264 - Clocking 8 */ - { 0x0120, 0x0000 }, /* R288 - ASRC_ENABLE */ - { 0x0121, 0x0000 }, /* R289 - ASRC_STATUS */ - { 0x0122, 0x0000 }, /* R290 - ASRC_RATE1 */ - { 0x0141, 0x8000 }, /* R321 - ISRC 1 CTRL 1 */ - { 0x0142, 0x0000 }, /* R322 - ISRC 1 CTRL 2 */ - { 0x0143, 0x8000 }, /* R323 - ISRC 2 CTRL1 */ - { 0x0144, 0x0000 }, /* R324 - ISRC 2 CTRL 2 */ - { 0x0182, 0x0000 }, /* R386 - FLL1 Control 1 */ - { 0x0183, 0x0000 }, /* R387 - FLL1 Control 2 */ - { 0x0184, 0x0000 }, /* R388 - FLL1 Control 3 */ - { 0x0186, 0x0177 }, /* R390 - FLL1 Control 5 */ - { 0x0187, 0x0001 }, /* R391 - FLL1 Control 6 */ - { 0x0188, 0x0000 }, /* R392 - FLL1 EFS 1 */ - { 0x01A2, 0x0000 }, /* R418 - FLL2 Control 1 */ - { 0x01A3, 0x0000 }, /* R419 - FLL2 Control 2 */ - { 0x01A4, 0x0000 }, /* R420 - FLL2 Control 3 */ - { 0x01A6, 0x0177 }, /* R422 - FLL2 Control 5 */ - { 0x01A7, 0x0001 }, /* R423 - FLL2 Control 6 */ - { 0x01A8, 0x0000 }, /* R424 - FLL2 EFS 1 */ - { 0x0200, 0x0020 }, /* R512 - Mic Charge Pump 1 */ - { 0x0201, 0xB084 }, /* R513 - Mic Charge Pump 2 */ - { 0x0202, 0xBBDE }, /* R514 - HP Charge Pump 1 */ - { 0x0211, 0x20D4 }, /* R529 - LDO1 Control */ - { 0x0215, 0x0062 }, /* R533 - Mic Bias Ctrl 1 */ - { 0x0216, 0x0062 }, /* R534 - Mic Bias Ctrl 2 */ - { 0x0217, 0x0062 }, /* R535 - Mic Bias Ctrl 3 */ - { 0x0280, 0x0004 }, /* R640 - Accessory Detect Mode 1 */ - { 0x0288, 0x0020 }, /* R648 - Headphone Detect 1 */ - { 0x0289, 0x0000 }, /* R649 - Headphone Detect 2 */ - { 0x0290, 0x1100 }, /* R656 - Mic Detect 1 */ - { 0x0291, 0x009F }, /* R657 - Mic Detect 2 */ - { 0x0292, 0x0000 }, /* R658 - Mic Detect 3 */ - { 0x0301, 0x0000 }, /* R769 - Input Enables */ - { 0x0302, 0x0000 }, /* R770 - Input Enables Status */ - { 0x0310, 0x2280 }, /* R784 - Status */ - { 0x0311, 0x0080 }, /* R785 - IN1R Control */ - { 0x0312, 0x2280 }, /* R786 - IN2L Control */ - { 0x0313, 0x0080 }, /* R787 - IN2R Control */ - { 0x0314, 0x2280 }, /* R788 - IN3L Control */ - { 0x0315, 0x0080 }, /* R789 - IN3R Control */ - { 0x0316, 0x2280 }, /* R790 - IN4L Control */ - { 0x0317, 0x0080 }, /* R791 - IN4R Control */ - { 0x0318, 0x0000 }, /* R792 - RXANC_SRC */ - { 0x0319, 0x0022 }, /* R793 - Input Volume Ramp */ - { 0x0320, 0x0180 }, /* R800 - ADC Digital Volume 1L */ - { 0x0321, 0x0180 }, /* R801 - ADC Digital Volume 1R */ - { 0x0322, 0x0180 }, /* R802 - ADC Digital Volume 2L */ - { 0x0323, 0x0180 }, /* R803 - ADC Digital Volume 2R */ - { 0x0324, 0x0180 }, /* R804 - ADC Digital Volume 3L */ - { 0x0325, 0x0180 }, /* R805 - ADC Digital Volume 3R */ - { 0x0326, 0x0180 }, /* R806 - ADC Digital Volume 4L */ - { 0x0327, 0x0180 }, /* R807 - ADC Digital Volume 4R */ - { 0x0401, 0x0000 }, /* R1025 - Output Enables 2 */ - { 0x0402, 0x0000 }, /* R1026 - Output Status 1 */ - { 0x0403, 0x0000 }, /* R1027 - Output Status 2 */ - { 0x0408, 0x0000 }, /* R1032 - Channel Enables 1 */ - { 0x0410, 0x0080 }, /* R1040 - Out Volume 1L */ - { 0x0411, 0x0080 }, /* R1041 - Out Volume 1R */ - { 0x0412, 0x0080 }, /* R1042 - DAC Volume Limit 1L */ - { 0x0413, 0x0080 }, /* R1043 - DAC Volume Limit 1R */ - { 0x0414, 0x0080 }, /* R1044 - Out Volume 2L */ - { 0x0415, 0x0080 }, /* R1045 - Out Volume 2R */ - { 0x0416, 0x0080 }, /* R1046 - DAC Volume Limit 2L */ - { 0x0417, 0x0080 }, /* R1047 - DAC Volume Limit 2R */ - { 0x0418, 0x0080 }, /* R1048 - Out Volume 3L */ - { 0x0419, 0x0080 }, /* R1049 - Out Volume 3R */ - { 0x041A, 0x0080 }, /* R1050 - DAC Volume Limit 3L */ - { 0x041B, 0x0080 }, /* R1051 - DAC Volume Limit 3R */ - { 0x041C, 0x0080 }, /* R1052 - Out Volume 4L */ - { 0x041D, 0x0080 }, /* R1053 - Out Volume 4R */ - { 0x041E, 0x0080 }, /* R1054 - DAC Volume Limit 5L */ - { 0x041F, 0x0080 }, /* R1055 - DAC Volume Limit 5R */ - { 0x0420, 0x0080 }, /* R1056 - DAC Volume Limit 6L */ - { 0x0421, 0x0080 }, /* R1057 - DAC Volume Limit 6R */ - { 0x0440, 0x0000 }, /* R1088 - DAC AEC Control 1 */ - { 0x0441, 0x0022 }, /* R1089 - Output Volume Ramp */ - { 0x0480, 0x0180 }, /* R1152 - DAC Digital Volume 1L */ - { 0x0481, 0x0180 }, /* R1153 - DAC Digital Volume 1R */ - { 0x0482, 0x0180 }, /* R1154 - DAC Digital Volume 2L */ - { 0x0483, 0x0180 }, /* R1155 - DAC Digital Volume 2R */ - { 0x0484, 0x0180 }, /* R1156 - DAC Digital Volume 3L */ - { 0x0485, 0x0180 }, /* R1157 - DAC Digital Volume 3R */ - { 0x0486, 0x0180 }, /* R1158 - DAC Digital Volume 4L */ - { 0x0487, 0x0180 }, /* R1159 - DAC Digital Volume 4R */ - { 0x0488, 0x0180 }, /* R1160 - DAC Digital Volume 5L */ - { 0x0489, 0x0180 }, /* R1161 - DAC Digital Volume 5R */ - { 0x048A, 0x0180 }, /* R1162 - DAC Digital Volume 6L */ - { 0x048B, 0x0180 }, /* R1163 - DAC Digital Volume 6R */ - { 0x04C0, 0x0069 }, /* R1216 - PDM SPK1 CTRL 1 */ - { 0x04C1, 0x0000 }, /* R1217 - PDM SPK1 CTRL 2 */ - { 0x04C2, 0x0069 }, /* R1218 - PDM SPK2 CTRL 1 */ - { 0x04C3, 0x0000 }, /* R1219 - PDM SPK2 CTRL 2 */ - { 0x0500, 0x000C }, /* R1280 - Audio IF 1_1 */ - { 0x0501, 0x0008 }, /* R1281 - Audio IF 1_2 */ - { 0x0502, 0x0000 }, /* R1282 - Audio IF 1_3 */ - { 0x0503, 0x0000 }, /* R1283 - Audio IF 1_4 */ - { 0x0504, 0x0000 }, /* R1284 - Audio IF 1_5 */ - { 0x0505, 0x0300 }, /* R1285 - Audio IF 1_6 */ - { 0x0506, 0x0300 }, /* R1286 - Audio IF 1_7 */ - { 0x0507, 0x1820 }, /* R1287 - Audio IF 1_8 */ - { 0x0508, 0x1820 }, /* R1288 - Audio IF 1_9 */ - { 0x0509, 0x0000 }, /* R1289 - Audio IF 1_10 */ - { 0x050A, 0x0001 }, /* R1290 - Audio IF 1_11 */ - { 0x050B, 0x0002 }, /* R1291 - Audio IF 1_12 */ - { 0x050C, 0x0003 }, /* R1292 - Audio IF 1_13 */ - { 0x050D, 0x0004 }, /* R1293 - Audio IF 1_14 */ - { 0x050E, 0x0005 }, /* R1294 - Audio IF 1_15 */ - { 0x050F, 0x0006 }, /* R1295 - Audio IF 1_16 */ - { 0x0510, 0x0007 }, /* R1296 - Audio IF 1_17 */ - { 0x0511, 0x0000 }, /* R1297 - Audio IF 1_18 */ - { 0x0512, 0x0001 }, /* R1298 - Audio IF 1_19 */ - { 0x0513, 0x0002 }, /* R1299 - Audio IF 1_20 */ - { 0x0514, 0x0003 }, /* R1300 - Audio IF 1_21 */ - { 0x0515, 0x0004 }, /* R1301 - Audio IF 1_22 */ - { 0x0516, 0x0005 }, /* R1302 - Audio IF 1_23 */ - { 0x0517, 0x0006 }, /* R1303 - Audio IF 1_24 */ - { 0x0518, 0x0007 }, /* R1304 - Audio IF 1_25 */ - { 0x0519, 0x0000 }, /* R1305 - Audio IF 1_26 */ - { 0x051A, 0x0000 }, /* R1306 - Audio IF 1_27 */ - { 0x0540, 0x000C }, /* R1344 - Audio IF 2_1 */ - { 0x0541, 0x0008 }, /* R1345 - Audio IF 2_2 */ - { 0x0542, 0x0000 }, /* R1346 - Audio IF 2_3 */ - { 0x0543, 0x0000 }, /* R1347 - Audio IF 2_4 */ - { 0x0544, 0x0000 }, /* R1348 - Audio IF 2_5 */ - { 0x0545, 0x0300 }, /* R1349 - Audio IF 2_6 */ - { 0x0546, 0x0300 }, /* R1350 - Audio IF 2_7 */ - { 0x0547, 0x1820 }, /* R1351 - Audio IF 2_8 */ - { 0x0548, 0x1820 }, /* R1352 - Audio IF 2_9 */ - { 0x0549, 0x0000 }, /* R1353 - Audio IF 2_10 */ - { 0x054A, 0x0001 }, /* R1354 - Audio IF 2_11 */ - { 0x0551, 0x0000 }, /* R1361 - Audio IF 2_18 */ - { 0x0552, 0x0001 }, /* R1362 - Audio IF 2_19 */ - { 0x0559, 0x0000 }, /* R1369 - Audio IF 2_26 */ - { 0x055A, 0x0000 }, /* R1370 - Audio IF 2_27 */ - { 0x0580, 0x000C }, /* R1408 - Audio IF 3_1 */ - { 0x0581, 0x0008 }, /* R1409 - Audio IF 3_2 */ - { 0x0582, 0x0000 }, /* R1410 - Audio IF 3_3 */ - { 0x0583, 0x0000 }, /* R1411 - Audio IF 3_4 */ - { 0x0584, 0x0000 }, /* R1412 - Audio IF 3_5 */ - { 0x0585, 0x0300 }, /* R1413 - Audio IF 3_6 */ - { 0x0586, 0x0300 }, /* R1414 - Audio IF 3_7 */ - { 0x0587, 0x1820 }, /* R1415 - Audio IF 3_8 */ - { 0x0588, 0x1820 }, /* R1416 - Audio IF 3_9 */ - { 0x0589, 0x0000 }, /* R1417 - Audio IF 3_10 */ - { 0x058A, 0x0001 }, /* R1418 - Audio IF 3_11 */ - { 0x0591, 0x0000 }, /* R1425 - Audio IF 3_18 */ - { 0x0592, 0x0001 }, /* R1426 - Audio IF 3_19 */ - { 0x0599, 0x0000 }, /* R1433 - Audio IF 3_26 */ - { 0x059A, 0x0000 }, /* R1434 - Audio IF 3_27 */ - { 0x0640, 0x0000 }, /* R1600 - PWM1MIX Input 1 Source */ - { 0x0641, 0x0080 }, /* R1601 - PWM1MIX Input 1 Volume */ - { 0x0642, 0x0000 }, /* R1602 - PWM1MIX Input 2 Source */ - { 0x0643, 0x0080 }, /* R1603 - PWM1MIX Input 2 Volume */ - { 0x0644, 0x0000 }, /* R1604 - PWM1MIX Input 3 Source */ - { 0x0645, 0x0080 }, /* R1605 - PWM1MIX Input 3 Volume */ - { 0x0646, 0x0000 }, /* R1606 - PWM1MIX Input 4 Source */ - { 0x0647, 0x0080 }, /* R1607 - PWM1MIX Input 4 Volume */ - { 0x0648, 0x0000 }, /* R1608 - PWM2MIX Input 1 Source */ - { 0x0649, 0x0080 }, /* R1609 - PWM2MIX Input 1 Volume */ - { 0x064A, 0x0000 }, /* R1610 - PWM2MIX Input 2 Source */ - { 0x064B, 0x0080 }, /* R1611 - PWM2MIX Input 2 Volume */ - { 0x064C, 0x0000 }, /* R1612 - PWM2MIX Input 3 Source */ - { 0x064D, 0x0080 }, /* R1613 - PWM2MIX Input 3 Volume */ - { 0x064E, 0x0000 }, /* R1614 - PWM2MIX Input 4 Source */ - { 0x064F, 0x0080 }, /* R1615 - PWM2MIX Input 4 Volume */ - { 0x0680, 0x0000 }, /* R1664 - OUT1LMIX Input 1 Source */ - { 0x0681, 0x0080 }, /* R1665 - OUT1LMIX Input 1 Volume */ - { 0x0682, 0x0000 }, /* R1666 - OUT1LMIX Input 2 Source */ - { 0x0683, 0x0080 }, /* R1667 - OUT1LMIX Input 2 Volume */ - { 0x0684, 0x0000 }, /* R1668 - OUT1LMIX Input 3 Source */ - { 0x0685, 0x0080 }, /* R1669 - OUT1LMIX Input 3 Volume */ - { 0x0686, 0x0000 }, /* R1670 - OUT1LMIX Input 4 Source */ - { 0x0687, 0x0080 }, /* R1671 - OUT1LMIX Input 4 Volume */ - { 0x0688, 0x0000 }, /* R1672 - OUT1RMIX Input 1 Source */ - { 0x0689, 0x0080 }, /* R1673 - OUT1RMIX Input 1 Volume */ - { 0x068A, 0x0000 }, /* R1674 - OUT1RMIX Input 2 Source */ - { 0x068B, 0x0080 }, /* R1675 - OUT1RMIX Input 2 Volume */ - { 0x068C, 0x0000 }, /* R1676 - OUT1RMIX Input 3 Source */ - { 0x068D, 0x0080 }, /* R1677 - OUT1RMIX Input 3 Volume */ - { 0x068E, 0x0000 }, /* R1678 - OUT1RMIX Input 4 Source */ - { 0x068F, 0x0080 }, /* R1679 - OUT1RMIX Input 4 Volume */ - { 0x0690, 0x0000 }, /* R1680 - OUT2LMIX Input 1 Source */ - { 0x0691, 0x0080 }, /* R1681 - OUT2LMIX Input 1 Volume */ - { 0x0692, 0x0000 }, /* R1682 - OUT2LMIX Input 2 Source */ - { 0x0693, 0x0080 }, /* R1683 - OUT2LMIX Input 2 Volume */ - { 0x0694, 0x0000 }, /* R1684 - OUT2LMIX Input 3 Source */ - { 0x0695, 0x0080 }, /* R1685 - OUT2LMIX Input 3 Volume */ - { 0x0696, 0x0000 }, /* R1686 - OUT2LMIX Input 4 Source */ - { 0x0697, 0x0080 }, /* R1687 - OUT2LMIX Input 4 Volume */ - { 0x0698, 0x0000 }, /* R1688 - OUT2RMIX Input 1 Source */ - { 0x0699, 0x0080 }, /* R1689 - OUT2RMIX Input 1 Volume */ - { 0x069A, 0x0000 }, /* R1690 - OUT2RMIX Input 2 Source */ - { 0x069B, 0x0080 }, /* R1691 - OUT2RMIX Input 2 Volume */ - { 0x069C, 0x0000 }, /* R1692 - OUT2RMIX Input 3 Source */ - { 0x069D, 0x0080 }, /* R1693 - OUT2RMIX Input 3 Volume */ - { 0x069E, 0x0000 }, /* R1694 - OUT2RMIX Input 4 Source */ - { 0x069F, 0x0080 }, /* R1695 - OUT2RMIX Input 4 Volume */ - { 0x06A0, 0x0000 }, /* R1696 - OUT3LMIX Input 1 Source */ - { 0x06A1, 0x0080 }, /* R1697 - OUT3LMIX Input 1 Volume */ - { 0x06A2, 0x0000 }, /* R1698 - OUT3LMIX Input 2 Source */ - { 0x06A3, 0x0080 }, /* R1699 - OUT3LMIX Input 2 Volume */ - { 0x06A4, 0x0000 }, /* R1700 - OUT3LMIX Input 3 Source */ - { 0x06A5, 0x0080 }, /* R1701 - OUT3LMIX Input 3 Volume */ - { 0x06A6, 0x0000 }, /* R1702 - OUT3LMIX Input 4 Source */ - { 0x06A7, 0x0080 }, /* R1703 - OUT3LMIX Input 4 Volume */ - { 0x06A8, 0x0000 }, /* R1704 - OUT3RMIX Input 1 Source */ - { 0x06A9, 0x0080 }, /* R1705 - OUT3RMIX Input 1 Volume */ - { 0x06AA, 0x0000 }, /* R1706 - OUT3RMIX Input 2 Source */ - { 0x06AB, 0x0080 }, /* R1707 - OUT3RMIX Input 2 Volume */ - { 0x06AC, 0x0000 }, /* R1708 - OUT3RMIX Input 3 Source */ - { 0x06AD, 0x0080 }, /* R1709 - OUT3RMIX Input 3 Volume */ - { 0x06AE, 0x0000 }, /* R1710 - OUT3RMIX Input 4 Source */ - { 0x06AF, 0x0080 }, /* R1711 - OUT3RMIX Input 4 Volume */ - { 0x06B0, 0x0000 }, /* R1712 - OUT4LMIX Input 1 Source */ - { 0x06B1, 0x0080 }, /* R1713 - OUT4LMIX Input 1 Volume */ - { 0x06B2, 0x0000 }, /* R1714 - OUT4LMIX Input 2 Source */ - { 0x06B3, 0x0080 }, /* R1715 - OUT4LMIX Input 2 Volume */ - { 0x06B4, 0x0000 }, /* R1716 - OUT4LMIX Input 3 Source */ - { 0x06B5, 0x0080 }, /* R1717 - OUT4LMIX Input 3 Volume */ - { 0x06B6, 0x0000 }, /* R1718 - OUT4LMIX Input 4 Source */ - { 0x06B7, 0x0080 }, /* R1719 - OUT4LMIX Input 4 Volume */ - { 0x06B8, 0x0000 }, /* R1720 - OUT4RMIX Input 1 Source */ - { 0x06B9, 0x0080 }, /* R1721 - OUT4RMIX Input 1 Volume */ - { 0x06BA, 0x0000 }, /* R1722 - OUT4RMIX Input 2 Source */ - { 0x06BB, 0x0080 }, /* R1723 - OUT4RMIX Input 2 Volume */ - { 0x06BC, 0x0000 }, /* R1724 - OUT4RMIX Input 3 Source */ - { 0x06BD, 0x0080 }, /* R1725 - OUT4RMIX Input 3 Volume */ - { 0x06BE, 0x0000 }, /* R1726 - OUT4RMIX Input 4 Source */ - { 0x06BF, 0x0080 }, /* R1727 - OUT4RMIX Input 4 Volume */ - { 0x06C0, 0x0000 }, /* R1728 - OUT5LMIX Input 1 Source */ - { 0x06C1, 0x0080 }, /* R1729 - OUT5LMIX Input 1 Volume */ - { 0x06C2, 0x0000 }, /* R1730 - OUT5LMIX Input 2 Source */ - { 0x06C3, 0x0080 }, /* R1731 - OUT5LMIX Input 2 Volume */ - { 0x06C4, 0x0000 }, /* R1732 - OUT5LMIX Input 3 Source */ - { 0x06C5, 0x0080 }, /* R1733 - OUT5LMIX Input 3 Volume */ - { 0x06C6, 0x0000 }, /* R1734 - OUT5LMIX Input 4 Source */ - { 0x06C7, 0x0080 }, /* R1735 - OUT5LMIX Input 4 Volume */ - { 0x06C8, 0x0000 }, /* R1736 - OUT5RMIX Input 1 Source */ - { 0x06C9, 0x0080 }, /* R1737 - OUT5RMIX Input 1 Volume */ - { 0x06CA, 0x0000 }, /* R1738 - OUT5RMIX Input 2 Source */ - { 0x06CB, 0x0080 }, /* R1739 - OUT5RMIX Input 2 Volume */ - { 0x06CC, 0x0000 }, /* R1740 - OUT5RMIX Input 3 Source */ - { 0x06CD, 0x0080 }, /* R1741 - OUT5RMIX Input 3 Volume */ - { 0x06CE, 0x0000 }, /* R1742 - OUT5RMIX Input 4 Source */ - { 0x06CF, 0x0080 }, /* R1743 - OUT5RMIX Input 4 Volume */ - { 0x06D0, 0x0000 }, /* R1744 - OUT6LMIX Input 1 Source */ - { 0x06D1, 0x0080 }, /* R1745 - OUT6LMIX Input 1 Volume */ - { 0x06D2, 0x0000 }, /* R1746 - OUT6LMIX Input 2 Source */ - { 0x06D3, 0x0080 }, /* R1747 - OUT6LMIX Input 2 Volume */ - { 0x06D4, 0x0000 }, /* R1748 - OUT6LMIX Input 3 Source */ - { 0x06D5, 0x0080 }, /* R1749 - OUT6LMIX Input 3 Volume */ - { 0x06D6, 0x0000 }, /* R1750 - OUT6LMIX Input 4 Source */ - { 0x06D7, 0x0080 }, /* R1751 - OUT6LMIX Input 4 Volume */ - { 0x06D8, 0x0000 }, /* R1752 - OUT6RMIX Input 1 Source */ - { 0x06D9, 0x0080 }, /* R1753 - OUT6RMIX Input 1 Volume */ - { 0x06DA, 0x0000 }, /* R1754 - OUT6RMIX Input 2 Source */ - { 0x06DB, 0x0080 }, /* R1755 - OUT6RMIX Input 2 Volume */ - { 0x06DC, 0x0000 }, /* R1756 - OUT6RMIX Input 3 Source */ - { 0x06DD, 0x0080 }, /* R1757 - OUT6RMIX Input 3 Volume */ - { 0x06DE, 0x0000 }, /* R1758 - OUT6RMIX Input 4 Source */ - { 0x06DF, 0x0080 }, /* R1759 - OUT6RMIX Input 4 Volume */ - { 0x0700, 0x0000 }, /* R1792 - AIF1TX1MIX Input 1 Source */ - { 0x0701, 0x0080 }, /* R1793 - AIF1TX1MIX Input 1 Volume */ - { 0x0702, 0x0000 }, /* R1794 - AIF1TX1MIX Input 2 Source */ - { 0x0703, 0x0080 }, /* R1795 - AIF1TX1MIX Input 2 Volume */ - { 0x0704, 0x0000 }, /* R1796 - AIF1TX1MIX Input 3 Source */ - { 0x0705, 0x0080 }, /* R1797 - AIF1TX1MIX Input 3 Volume */ - { 0x0706, 0x0000 }, /* R1798 - AIF1TX1MIX Input 4 Source */ - { 0x0707, 0x0080 }, /* R1799 - AIF1TX1MIX Input 4 Volume */ - { 0x0708, 0x0000 }, /* R1800 - AIF1TX2MIX Input 1 Source */ - { 0x0709, 0x0080 }, /* R1801 - AIF1TX2MIX Input 1 Volume */ - { 0x070A, 0x0000 }, /* R1802 - AIF1TX2MIX Input 2 Source */ - { 0x070B, 0x0080 }, /* R1803 - AIF1TX2MIX Input 2 Volume */ - { 0x070C, 0x0000 }, /* R1804 - AIF1TX2MIX Input 3 Source */ - { 0x070D, 0x0080 }, /* R1805 - AIF1TX2MIX Input 3 Volume */ - { 0x070E, 0x0000 }, /* R1806 - AIF1TX2MIX Input 4 Source */ - { 0x070F, 0x0080 }, /* R1807 - AIF1TX2MIX Input 4 Volume */ - { 0x0710, 0x0000 }, /* R1808 - AIF1TX3MIX Input 1 Source */ - { 0x0711, 0x0080 }, /* R1809 - AIF1TX3MIX Input 1 Volume */ - { 0x0712, 0x0000 }, /* R1810 - AIF1TX3MIX Input 2 Source */ - { 0x0713, 0x0080 }, /* R1811 - AIF1TX3MIX Input 2 Volume */ - { 0x0714, 0x0000 }, /* R1812 - AIF1TX3MIX Input 3 Source */ - { 0x0715, 0x0080 }, /* R1813 - AIF1TX3MIX Input 3 Volume */ - { 0x0716, 0x0000 }, /* R1814 - AIF1TX3MIX Input 4 Source */ - { 0x0717, 0x0080 }, /* R1815 - AIF1TX3MIX Input 4 Volume */ - { 0x0718, 0x0000 }, /* R1816 - AIF1TX4MIX Input 1 Source */ - { 0x0719, 0x0080 }, /* R1817 - AIF1TX4MIX Input 1 Volume */ - { 0x071A, 0x0000 }, /* R1818 - AIF1TX4MIX Input 2 Source */ - { 0x071B, 0x0080 }, /* R1819 - AIF1TX4MIX Input 2 Volume */ - { 0x071C, 0x0000 }, /* R1820 - AIF1TX4MIX Input 3 Source */ - { 0x071D, 0x0080 }, /* R1821 - AIF1TX4MIX Input 3 Volume */ - { 0x071E, 0x0000 }, /* R1822 - AIF1TX4MIX Input 4 Source */ - { 0x071F, 0x0080 }, /* R1823 - AIF1TX4MIX Input 4 Volume */ - { 0x0720, 0x0000 }, /* R1824 - AIF1TX5MIX Input 1 Source */ - { 0x0721, 0x0080 }, /* R1825 - AIF1TX5MIX Input 1 Volume */ - { 0x0722, 0x0000 }, /* R1826 - AIF1TX5MIX Input 2 Source */ - { 0x0723, 0x0080 }, /* R1827 - AIF1TX5MIX Input 2 Volume */ - { 0x0724, 0x0000 }, /* R1828 - AIF1TX5MIX Input 3 Source */ - { 0x0725, 0x0080 }, /* R1829 - AIF1TX5MIX Input 3 Volume */ - { 0x0726, 0x0000 }, /* R1830 - AIF1TX5MIX Input 4 Source */ - { 0x0727, 0x0080 }, /* R1831 - AIF1TX5MIX Input 4 Volume */ - { 0x0728, 0x0000 }, /* R1832 - AIF1TX6MIX Input 1 Source */ - { 0x0729, 0x0080 }, /* R1833 - AIF1TX6MIX Input 1 Volume */ - { 0x072A, 0x0000 }, /* R1834 - AIF1TX6MIX Input 2 Source */ - { 0x072B, 0x0080 }, /* R1835 - AIF1TX6MIX Input 2 Volume */ - { 0x072C, 0x0000 }, /* R1836 - AIF1TX6MIX Input 3 Source */ - { 0x072D, 0x0080 }, /* R1837 - AIF1TX6MIX Input 3 Volume */ - { 0x072E, 0x0000 }, /* R1838 - AIF1TX6MIX Input 4 Source */ - { 0x072F, 0x0080 }, /* R1839 - AIF1TX6MIX Input 4 Volume */ - { 0x0730, 0x0000 }, /* R1840 - AIF1TX7MIX Input 1 Source */ - { 0x0731, 0x0080 }, /* R1841 - AIF1TX7MIX Input 1 Volume */ - { 0x0732, 0x0000 }, /* R1842 - AIF1TX7MIX Input 2 Source */ - { 0x0733, 0x0080 }, /* R1843 - AIF1TX7MIX Input 2 Volume */ - { 0x0734, 0x0000 }, /* R1844 - AIF1TX7MIX Input 3 Source */ - { 0x0735, 0x0080 }, /* R1845 - AIF1TX7MIX Input 3 Volume */ - { 0x0736, 0x0000 }, /* R1846 - AIF1TX7MIX Input 4 Source */ - { 0x0737, 0x0080 }, /* R1847 - AIF1TX7MIX Input 4 Volume */ - { 0x0738, 0x0000 }, /* R1848 - AIF1TX8MIX Input 1 Source */ - { 0x0739, 0x0080 }, /* R1849 - AIF1TX8MIX Input 1 Volume */ - { 0x073A, 0x0000 }, /* R1850 - AIF1TX8MIX Input 2 Source */ - { 0x073B, 0x0080 }, /* R1851 - AIF1TX8MIX Input 2 Volume */ - { 0x073C, 0x0000 }, /* R1852 - AIF1TX8MIX Input 3 Source */ - { 0x073D, 0x0080 }, /* R1853 - AIF1TX8MIX Input 3 Volume */ - { 0x073E, 0x0000 }, /* R1854 - AIF1TX8MIX Input 4 Source */ - { 0x073F, 0x0080 }, /* R1855 - AIF1TX8MIX Input 4 Volume */ - { 0x0740, 0x0000 }, /* R1856 - AIF2TX1MIX Input 1 Source */ - { 0x0741, 0x0080 }, /* R1857 - AIF2TX1MIX Input 1 Volume */ - { 0x0742, 0x0000 }, /* R1858 - AIF2TX1MIX Input 2 Source */ - { 0x0743, 0x0080 }, /* R1859 - AIF2TX1MIX Input 2 Volume */ - { 0x0744, 0x0000 }, /* R1860 - AIF2TX1MIX Input 3 Source */ - { 0x0745, 0x0080 }, /* R1861 - AIF2TX1MIX Input 3 Volume */ - { 0x0746, 0x0000 }, /* R1862 - AIF2TX1MIX Input 4 Source */ - { 0x0747, 0x0080 }, /* R1863 - AIF2TX1MIX Input 4 Volume */ - { 0x0748, 0x0000 }, /* R1864 - AIF2TX2MIX Input 1 Source */ - { 0x0749, 0x0080 }, /* R1865 - AIF2TX2MIX Input 1 Volume */ - { 0x074A, 0x0000 }, /* R1866 - AIF2TX2MIX Input 2 Source */ - { 0x074B, 0x0080 }, /* R1867 - AIF2TX2MIX Input 2 Volume */ - { 0x074C, 0x0000 }, /* R1868 - AIF2TX2MIX Input 3 Source */ - { 0x074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */ - { 0x074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */ - { 0x074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */ - { 0x0780, 0x0000 }, /* R1920 - AIF3TX1MIX Input 1 Source */ - { 0x0781, 0x0080 }, /* R1921 - AIF3TX1MIX Input 1 Volume */ - { 0x0782, 0x0000 }, /* R1922 - AIF3TX1MIX Input 2 Source */ - { 0x0783, 0x0080 }, /* R1923 - AIF3TX1MIX Input 2 Volume */ - { 0x0784, 0x0000 }, /* R1924 - AIF3TX1MIX Input 3 Source */ - { 0x0785, 0x0080 }, /* R1925 - AIF3TX1MIX Input 3 Volume */ - { 0x0786, 0x0000 }, /* R1926 - AIF3TX1MIX Input 4 Source */ - { 0x0787, 0x0080 }, /* R1927 - AIF3TX1MIX Input 4 Volume */ - { 0x0788, 0x0000 }, /* R1928 - AIF3TX2MIX Input 1 Source */ - { 0x0789, 0x0080 }, /* R1929 - AIF3TX2MIX Input 1 Volume */ - { 0x078A, 0x0000 }, /* R1930 - AIF3TX2MIX Input 2 Source */ - { 0x078B, 0x0080 }, /* R1931 - AIF3TX2MIX Input 2 Volume */ - { 0x078C, 0x0000 }, /* R1932 - AIF3TX2MIX Input 3 Source */ - { 0x078D, 0x0080 }, /* R1933 - AIF3TX2MIX Input 3 Volume */ - { 0x078E, 0x0000 }, /* R1934 - AIF3TX2MIX Input 4 Source */ - { 0x078F, 0x0080 }, /* R1935 - AIF3TX2MIX Input 4 Volume */ - { 0x0880, 0x0000 }, /* R2176 - EQ1MIX Input 1 Source */ - { 0x0881, 0x0080 }, /* R2177 - EQ1MIX Input 1 Volume */ - { 0x0882, 0x0000 }, /* R2178 - EQ1MIX Input 2 Source */ - { 0x0883, 0x0080 }, /* R2179 - EQ1MIX Input 2 Volume */ - { 0x0884, 0x0000 }, /* R2180 - EQ1MIX Input 3 Source */ - { 0x0885, 0x0080 }, /* R2181 - EQ1MIX Input 3 Volume */ - { 0x0886, 0x0000 }, /* R2182 - EQ1MIX Input 4 Source */ - { 0x0887, 0x0080 }, /* R2183 - EQ1MIX Input 4 Volume */ - { 0x0888, 0x0000 }, /* R2184 - EQ2MIX Input 1 Source */ - { 0x0889, 0x0080 }, /* R2185 - EQ2MIX Input 1 Volume */ - { 0x088A, 0x0000 }, /* R2186 - EQ2MIX Input 2 Source */ - { 0x088B, 0x0080 }, /* R2187 - EQ2MIX Input 2 Volume */ - { 0x088C, 0x0000 }, /* R2188 - EQ2MIX Input 3 Source */ - { 0x088D, 0x0080 }, /* R2189 - EQ2MIX Input 3 Volume */ - { 0x088E, 0x0000 }, /* R2190 - EQ2MIX Input 4 Source */ - { 0x088F, 0x0080 }, /* R2191 - EQ2MIX Input 4 Volume */ - { 0x0890, 0x0000 }, /* R2192 - EQ3MIX Input 1 Source */ - { 0x0891, 0x0080 }, /* R2193 - EQ3MIX Input 1 Volume */ - { 0x0892, 0x0000 }, /* R2194 - EQ3MIX Input 2 Source */ - { 0x0893, 0x0080 }, /* R2195 - EQ3MIX Input 2 Volume */ - { 0x0894, 0x0000 }, /* R2196 - EQ3MIX Input 3 Source */ - { 0x0895, 0x0080 }, /* R2197 - EQ3MIX Input 3 Volume */ - { 0x0896, 0x0000 }, /* R2198 - EQ3MIX Input 4 Source */ - { 0x0897, 0x0080 }, /* R2199 - EQ3MIX Input 4 Volume */ - { 0x0898, 0x0000 }, /* R2200 - EQ4MIX Input 1 Source */ - { 0x0899, 0x0080 }, /* R2201 - EQ4MIX Input 1 Volume */ - { 0x089A, 0x0000 }, /* R2202 - EQ4MIX Input 2 Source */ - { 0x089B, 0x0080 }, /* R2203 - EQ4MIX Input 2 Volume */ - { 0x089C, 0x0000 }, /* R2204 - EQ4MIX Input 3 Source */ - { 0x089D, 0x0080 }, /* R2205 - EQ4MIX Input 3 Volume */ - { 0x089E, 0x0000 }, /* R2206 - EQ4MIX Input 4 Source */ - { 0x089F, 0x0080 }, /* R2207 - EQ4MIX Input 4 Volume */ - { 0x08C0, 0x0000 }, /* R2240 - DRC1LMIX Input 1 Source */ - { 0x08C1, 0x0080 }, /* R2241 - DRC1LMIX Input 1 Volume */ - { 0x08C2, 0x0000 }, /* R2242 - DRC1LMIX Input 2 Source */ - { 0x08C3, 0x0080 }, /* R2243 - DRC1LMIX Input 2 Volume */ - { 0x08C4, 0x0000 }, /* R2244 - DRC1LMIX Input 3 Source */ - { 0x08C5, 0x0080 }, /* R2245 - DRC1LMIX Input 3 Volume */ - { 0x08C6, 0x0000 }, /* R2246 - DRC1LMIX Input 4 Source */ - { 0x08C7, 0x0080 }, /* R2247 - DRC1LMIX Input 4 Volume */ - { 0x08C8, 0x0000 }, /* R2248 - DRC1RMIX Input 1 Source */ - { 0x08C9, 0x0080 }, /* R2249 - DRC1RMIX Input 1 Volume */ - { 0x08CA, 0x0000 }, /* R2250 - DRC1RMIX Input 2 Source */ - { 0x08CB, 0x0080 }, /* R2251 - DRC1RMIX Input 2 Volume */ - { 0x08CC, 0x0000 }, /* R2252 - DRC1RMIX Input 3 Source */ - { 0x08CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */ - { 0x08CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */ - { 0x08CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */ - { 0x0900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */ - { 0x0901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */ - { 0x0902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */ - { 0x0903, 0x0080 }, /* R2307 - HPLP1MIX Input 2 Volume */ - { 0x0904, 0x0000 }, /* R2308 - HPLP1MIX Input 3 Source */ - { 0x0905, 0x0080 }, /* R2309 - HPLP1MIX Input 3 Volume */ - { 0x0906, 0x0000 }, /* R2310 - HPLP1MIX Input 4 Source */ - { 0x0907, 0x0080 }, /* R2311 - HPLP1MIX Input 4 Volume */ - { 0x0908, 0x0000 }, /* R2312 - HPLP2MIX Input 1 Source */ - { 0x0909, 0x0080 }, /* R2313 - HPLP2MIX Input 1 Volume */ - { 0x090A, 0x0000 }, /* R2314 - HPLP2MIX Input 2 Source */ - { 0x090B, 0x0080 }, /* R2315 - HPLP2MIX Input 2 Volume */ - { 0x090C, 0x0000 }, /* R2316 - HPLP2MIX Input 3 Source */ - { 0x090D, 0x0080 }, /* R2317 - HPLP2MIX Input 3 Volume */ - { 0x090E, 0x0000 }, /* R2318 - HPLP2MIX Input 4 Source */ - { 0x090F, 0x0080 }, /* R2319 - HPLP2MIX Input 4 Volume */ - { 0x0910, 0x0000 }, /* R2320 - HPLP3MIX Input 1 Source */ - { 0x0911, 0x0080 }, /* R2321 - HPLP3MIX Input 1 Volume */ - { 0x0912, 0x0000 }, /* R2322 - HPLP3MIX Input 2 Source */ - { 0x0913, 0x0080 }, /* R2323 - HPLP3MIX Input 2 Volume */ - { 0x0914, 0x0000 }, /* R2324 - HPLP3MIX Input 3 Source */ - { 0x0915, 0x0080 }, /* R2325 - HPLP3MIX Input 3 Volume */ - { 0x0916, 0x0000 }, /* R2326 - HPLP3MIX Input 4 Source */ - { 0x0917, 0x0080 }, /* R2327 - HPLP3MIX Input 4 Volume */ - { 0x0918, 0x0000 }, /* R2328 - HPLP4MIX Input 1 Source */ - { 0x0919, 0x0080 }, /* R2329 - HPLP4MIX Input 1 Volume */ - { 0x091A, 0x0000 }, /* R2330 - HPLP4MIX Input 2 Source */ - { 0x091B, 0x0080 }, /* R2331 - HPLP4MIX Input 2 Volume */ - { 0x091C, 0x0000 }, /* R2332 - HPLP4MIX Input 3 Source */ - { 0x091D, 0x0080 }, /* R2333 - HPLP4MIX Input 3 Volume */ - { 0x091E, 0x0000 }, /* R2334 - HPLP4MIX Input 4 Source */ - { 0x091F, 0x0080 }, /* R2335 - HPLP4MIX Input 4 Volume */ - { 0x0940, 0x0000 }, /* R2368 - DSP1LMIX Input 1 Source */ - { 0x0941, 0x0080 }, /* R2369 - DSP1LMIX Input 1 Volume */ - { 0x0942, 0x0000 }, /* R2370 - DSP1LMIX Input 2 Source */ - { 0x0943, 0x0080 }, /* R2371 - DSP1LMIX Input 2 Volume */ - { 0x0944, 0x0000 }, /* R2372 - DSP1LMIX Input 3 Source */ - { 0x0945, 0x0080 }, /* R2373 - DSP1LMIX Input 3 Volume */ - { 0x0946, 0x0000 }, /* R2374 - DSP1LMIX Input 4 Source */ - { 0x0947, 0x0080 }, /* R2375 - DSP1LMIX Input 4 Volume */ - { 0x0948, 0x0000 }, /* R2376 - DSP1RMIX Input 1 Source */ - { 0x0949, 0x0080 }, /* R2377 - DSP1RMIX Input 1 Volume */ - { 0x094A, 0x0000 }, /* R2378 - DSP1RMIX Input 2 Source */ - { 0x094B, 0x0080 }, /* R2379 - DSP1RMIX Input 2 Volume */ - { 0x094C, 0x0000 }, /* R2380 - DSP1RMIX Input 3 Source */ - { 0x094D, 0x0080 }, /* R2381 - DSP1RMIX Input 3 Volume */ - { 0x094E, 0x0000 }, /* R2382 - DSP1RMIX Input 4 Source */ - { 0x094F, 0x0080 }, /* R2383 - DSP1RMIX Input 4 Volume */ - { 0x0950, 0x0000 }, /* R2384 - DSP1AUX1MIX Input 1 Source */ - { 0x0958, 0x0000 }, /* R2392 - DSP1AUX2MIX Input 1 Source */ - { 0x0960, 0x0000 }, /* R2400 - DSP1AUX3MIX Input 1 Source */ - { 0x0968, 0x0000 }, /* R2408 - DSP1AUX4MIX Input 1 Source */ - { 0x0970, 0x0000 }, /* R2416 - DSP1AUX5MIX Input 1 Source */ - { 0x0978, 0x0000 }, /* R2424 - DSP1AUX6MIX Input 1 Source */ - { 0x0980, 0x0000 }, /* R2432 - DSP2LMIX Input 1 Source */ - { 0x0981, 0x0080 }, /* R2433 - DSP2LMIX Input 1 Volume */ - { 0x0982, 0x0000 }, /* R2434 - DSP2LMIX Input 2 Source */ - { 0x0983, 0x0080 }, /* R2435 - DSP2LMIX Input 2 Volume */ - { 0x0984, 0x0000 }, /* R2436 - DSP2LMIX Input 3 Source */ - { 0x0985, 0x0080 }, /* R2437 - DSP2LMIX Input 3 Volume */ - { 0x0986, 0x0000 }, /* R2438 - DSP2LMIX Input 4 Source */ - { 0x0987, 0x0080 }, /* R2439 - DSP2LMIX Input 4 Volume */ - { 0x0988, 0x0000 }, /* R2440 - DSP2RMIX Input 1 Source */ - { 0x0989, 0x0080 }, /* R2441 - DSP2RMIX Input 1 Volume */ - { 0x098A, 0x0000 }, /* R2442 - DSP2RMIX Input 2 Source */ - { 0x098B, 0x0080 }, /* R2443 - DSP2RMIX Input 2 Volume */ - { 0x098C, 0x0000 }, /* R2444 - DSP2RMIX Input 3 Source */ - { 0x098D, 0x0080 }, /* R2445 - DSP2RMIX Input 3 Volume */ - { 0x098E, 0x0000 }, /* R2446 - DSP2RMIX Input 4 Source */ - { 0x098F, 0x0080 }, /* R2447 - DSP2RMIX Input 4 Volume */ - { 0x0990, 0x0000 }, /* R2448 - DSP2AUX1MIX Input 1 Source */ - { 0x0998, 0x0000 }, /* R2456 - DSP2AUX2MIX Input 1 Source */ - { 0x09A0, 0x0000 }, /* R2464 - DSP2AUX3MIX Input 1 Source */ - { 0x09A8, 0x0000 }, /* R2472 - DSP2AUX4MIX Input 1 Source */ - { 0x09B0, 0x0000 }, /* R2480 - DSP2AUX5MIX Input 1 Source */ - { 0x09B8, 0x0000 }, /* R2488 - DSP2AUX6MIX Input 1 Source */ - { 0x09C0, 0x0000 }, /* R2496 - DSP3LMIX Input 1 Source */ - { 0x09C1, 0x0080 }, /* R2497 - DSP3LMIX Input 1 Volume */ - { 0x09C2, 0x0000 }, /* R2498 - DSP3LMIX Input 2 Source */ - { 0x09C3, 0x0080 }, /* R2499 - DSP3LMIX Input 2 Volume */ - { 0x09C4, 0x0000 }, /* R2500 - DSP3LMIX Input 3 Source */ - { 0x09C5, 0x0080 }, /* R2501 - DSP3LMIX Input 3 Volume */ - { 0x09C6, 0x0000 }, /* R2502 - DSP3LMIX Input 4 Source */ - { 0x09C7, 0x0080 }, /* R2503 - DSP3LMIX Input 4 Volume */ - { 0x09C8, 0x0000 }, /* R2504 - DSP3RMIX Input 1 Source */ - { 0x09C9, 0x0080 }, /* R2505 - DSP3RMIX Input 1 Volume */ - { 0x09CA, 0x0000 }, /* R2506 - DSP3RMIX Input 2 Source */ - { 0x09CB, 0x0080 }, /* R2507 - DSP3RMIX Input 2 Volume */ - { 0x09CC, 0x0000 }, /* R2508 - DSP3RMIX Input 3 Source */ - { 0x09CD, 0x0080 }, /* R2509 - DSP3RMIX Input 3 Volume */ - { 0x09CE, 0x0000 }, /* R2510 - DSP3RMIX Input 4 Source */ - { 0x09CF, 0x0080 }, /* R2511 - DSP3RMIX Input 4 Volume */ - { 0x09D0, 0x0000 }, /* R2512 - DSP3AUX1MIX Input 1 Source */ - { 0x09D8, 0x0000 }, /* R2520 - DSP3AUX2MIX Input 1 Source */ - { 0x09E0, 0x0000 }, /* R2528 - DSP3AUX3MIX Input 1 Source */ - { 0x09E8, 0x0000 }, /* R2536 - DSP3AUX4MIX Input 1 Source */ - { 0x09F0, 0x0000 }, /* R2544 - DSP3AUX5MIX Input 1 Source */ - { 0x09F8, 0x0000 }, /* R2552 - DSP3AUX6MIX Input 1 Source */ - { 0x0A80, 0x0000 }, /* R2688 - ASRC1LMIX Input 1 Source */ - { 0x0A88, 0x0000 }, /* R2696 - ASRC1RMIX Input 1 Source */ - { 0x0A90, 0x0000 }, /* R2704 - ASRC2LMIX Input 1 Source */ - { 0x0A98, 0x0000 }, /* R2712 - ASRC2RMIX Input 1 Source */ - { 0x0B00, 0x0000 }, /* R2816 - ISRC1DEC1MIX Input 1 Source */ - { 0x0B08, 0x0000 }, /* R2824 - ISRC1DEC2MIX Input 1 Source */ - { 0x0B10, 0x0000 }, /* R2832 - ISRC1DEC3MIX Input 1 Source */ - { 0x0B18, 0x0000 }, /* R2840 - ISRC1DEC4MIX Input 1 Source */ - { 0x0B20, 0x0000 }, /* R2848 - ISRC1INT1MIX Input 1 Source */ - { 0x0B28, 0x0000 }, /* R2856 - ISRC1INT2MIX Input 1 Source */ - { 0x0B30, 0x0000 }, /* R2864 - ISRC1INT3MIX Input 1 Source */ - { 0x0B38, 0x0000 }, /* R2872 - ISRC1INT4MIX Input 1 Source */ - { 0x0B40, 0x0000 }, /* R2880 - ISRC2DEC1MIX Input 1 Source */ - { 0x0B48, 0x0000 }, /* R2888 - ISRC2DEC2MIX Input 1 Source */ - { 0x0B50, 0x0000 }, /* R2896 - ISRC2DEC3MIX Input 1 Source */ - { 0x0B58, 0x0000 }, /* R2904 - ISRC2DEC4MIX Input 1 Source */ - { 0x0B60, 0x0000 }, /* R2912 - ISRC2INT1MIX Input 1 Source */ - { 0x0B68, 0x0000 }, /* R2920 - ISRC2INT2MIX Input 1 Source */ - { 0x0B70, 0x0000 }, /* R2928 - ISRC2INT3MIX Input 1 Source */ - { 0x0B78, 0x0000 }, /* R2936 - ISRC2INT4MIX Input 1 Source */ - { 0x0C00, 0xA001 }, /* R3072 - GPIO CTRL 1 */ - { 0x0C01, 0xA001 }, /* R3073 - GPIO CTRL 2 */ - { 0x0C02, 0xA001 }, /* R3074 - GPIO CTRL 3 */ - { 0x0C03, 0xA001 }, /* R3075 - GPIO CTRL 4 */ - { 0x0C04, 0xA001 }, /* R3076 - GPIO CTRL 5 */ - { 0x0C05, 0xA001 }, /* R3077 - GPIO CTRL 6 */ - { 0x0C23, 0x4003 }, /* R3107 - Misc Pad Ctrl 1 */ - { 0x0C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 2 */ - { 0x0C25, 0x0000 }, /* R3109 - Misc Pad Ctrl 3 */ - { 0x0C26, 0x0000 }, /* R3110 - Misc Pad Ctrl 4 */ - { 0x0C27, 0x0000 }, /* R3111 - Misc Pad Ctrl 5 */ - { 0x0C28, 0x0000 }, /* R3112 - Misc GPIO 1 */ - { 0x0D00, 0x0000 }, /* R3328 - Interrupt Status 1 */ - { 0x0D01, 0x0000 }, /* R3329 - Interrupt Status 2 */ - { 0x0D02, 0x0000 }, /* R3330 - Interrupt Status 3 */ - { 0x0D03, 0x0000 }, /* R3331 - Interrupt Status 4 */ - { 0x0D04, 0x0000 }, /* R3332 - Interrupt Raw Status 2 */ - { 0x0D05, 0x0000 }, /* R3333 - Interrupt Raw Status 3 */ - { 0x0D06, 0x0000 }, /* R3334 - Interrupt Raw Status 4 */ - { 0x0D07, 0xFFFF }, /* R3335 - Interrupt Status 1 Mask */ - { 0x0D08, 0xFFFF }, /* R3336 - Interrupt Status 2 Mask */ - { 0x0D09, 0xFFFF }, /* R3337 - Interrupt Status 3 Mask */ - { 0x0D0A, 0xFFFF }, /* R3338 - Interrupt Status 4 Mask */ - { 0x0D1F, 0x0000 }, /* R3359 - Interrupt Control */ - { 0x0D20, 0xFFFF }, /* R3360 - IRQ Debounce 1 */ - { 0x0D21, 0xFFFF }, /* R3361 - IRQ Debounce 2 */ - { 0x0E00, 0x0000 }, /* R3584 - FX_Ctrl */ - { 0x0E10, 0x6318 }, /* R3600 - EQ1_1 */ - { 0x0E11, 0x6300 }, /* R3601 - EQ1_2 */ - { 0x0E12, 0x0FC8 }, /* R3602 - EQ1_3 */ - { 0x0E13, 0x03FE }, /* R3603 - EQ1_4 */ - { 0x0E14, 0x00E0 }, /* R3604 - EQ1_5 */ - { 0x0E15, 0x1EC4 }, /* R3605 - EQ1_6 */ - { 0x0E16, 0xF136 }, /* R3606 - EQ1_7 */ - { 0x0E17, 0x0409 }, /* R3607 - EQ1_8 */ - { 0x0E18, 0x04CC }, /* R3608 - EQ1_9 */ - { 0x0E19, 0x1C9B }, /* R3609 - EQ1_10 */ - { 0x0E1A, 0xF337 }, /* R3610 - EQ1_11 */ - { 0x0E1B, 0x040B }, /* R3611 - EQ1_12 */ - { 0x0E1C, 0x0CBB }, /* R3612 - EQ1_13 */ - { 0x0E1D, 0x16F8 }, /* R3613 - EQ1_14 */ - { 0x0E1E, 0xF7D9 }, /* R3614 - EQ1_15 */ - { 0x0E1F, 0x040A }, /* R3615 - EQ1_16 */ - { 0x0E20, 0x1F14 }, /* R3616 - EQ1_17 */ - { 0x0E21, 0x058C }, /* R3617 - EQ1_18 */ - { 0x0E22, 0x0563 }, /* R3618 - EQ1_19 */ - { 0x0E23, 0x4000 }, /* R3619 - EQ1_20 */ - { 0x0E26, 0x6318 }, /* R3622 - EQ2_1 */ - { 0x0E27, 0x6300 }, /* R3623 - EQ2_2 */ - { 0x0E28, 0x0FC8 }, /* R3624 - EQ2_3 */ - { 0x0E29, 0x03FE }, /* R3625 - EQ2_4 */ - { 0x0E2A, 0x00E0 }, /* R3626 - EQ2_5 */ - { 0x0E2B, 0x1EC4 }, /* R3627 - EQ2_6 */ - { 0x0E2C, 0xF136 }, /* R3628 - EQ2_7 */ - { 0x0E2D, 0x0409 }, /* R3629 - EQ2_8 */ - { 0x0E2E, 0x04CC }, /* R3630 - EQ2_9 */ - { 0x0E2F, 0x1C9B }, /* R3631 - EQ2_10 */ - { 0x0E30, 0xF337 }, /* R3632 - EQ2_11 */ - { 0x0E31, 0x040B }, /* R3633 - EQ2_12 */ - { 0x0E32, 0x0CBB }, /* R3634 - EQ2_13 */ - { 0x0E33, 0x16F8 }, /* R3635 - EQ2_14 */ - { 0x0E34, 0xF7D9 }, /* R3636 - EQ2_15 */ - { 0x0E35, 0x040A }, /* R3637 - EQ2_16 */ - { 0x0E36, 0x1F14 }, /* R3638 - EQ2_17 */ - { 0x0E37, 0x058C }, /* R3639 - EQ2_18 */ - { 0x0E38, 0x0563 }, /* R3640 - EQ2_19 */ - { 0x0E39, 0x4000 }, /* R3641 - EQ2_20 */ - { 0x0E3C, 0x6318 }, /* R3644 - EQ3_1 */ - { 0x0E3D, 0x6300 }, /* R3645 - EQ3_2 */ - { 0x0E3E, 0x0FC8 }, /* R3646 - EQ3_3 */ - { 0x0E3F, 0x03FE }, /* R3647 - EQ3_4 */ - { 0x0E40, 0x00E0 }, /* R3648 - EQ3_5 */ - { 0x0E41, 0x1EC4 }, /* R3649 - EQ3_6 */ - { 0x0E42, 0xF136 }, /* R3650 - EQ3_7 */ - { 0x0E43, 0x0409 }, /* R3651 - EQ3_8 */ - { 0x0E44, 0x04CC }, /* R3652 - EQ3_9 */ - { 0x0E45, 0x1C9B }, /* R3653 - EQ3_10 */ - { 0x0E46, 0xF337 }, /* R3654 - EQ3_11 */ - { 0x0E47, 0x040B }, /* R3655 - EQ3_12 */ - { 0x0E48, 0x0CBB }, /* R3656 - EQ3_13 */ - { 0x0E49, 0x16F8 }, /* R3657 - EQ3_14 */ - { 0x0E4A, 0xF7D9 }, /* R3658 - EQ3_15 */ - { 0x0E4B, 0x040A }, /* R3659 - EQ3_16 */ - { 0x0E4C, 0x1F14 }, /* R3660 - EQ3_17 */ - { 0x0E4D, 0x058C }, /* R3661 - EQ3_18 */ - { 0x0E4E, 0x0563 }, /* R3662 - EQ3_19 */ - { 0x0E4F, 0x4000 }, /* R3663 - EQ3_20 */ - { 0x0E52, 0x6318 }, /* R3666 - EQ4_1 */ - { 0x0E53, 0x6300 }, /* R3667 - EQ4_2 */ - { 0x0E54, 0x0FC8 }, /* R3668 - EQ4_3 */ - { 0x0E55, 0x03FE }, /* R3669 - EQ4_4 */ - { 0x0E56, 0x00E0 }, /* R3670 - EQ4_5 */ - { 0x0E57, 0x1EC4 }, /* R3671 - EQ4_6 */ - { 0x0E58, 0xF136 }, /* R3672 - EQ4_7 */ - { 0x0E59, 0x0409 }, /* R3673 - EQ4_8 */ - { 0x0E5A, 0x04CC }, /* R3674 - EQ4_9 */ - { 0x0E5B, 0x1C9B }, /* R3675 - EQ4_10 */ - { 0x0E5C, 0xF337 }, /* R3676 - EQ4_11 */ - { 0x0E5D, 0x040B }, /* R3677 - EQ4_12 */ - { 0x0E5E, 0x0CBB }, /* R3678 - EQ4_13 */ - { 0x0E5F, 0x16F8 }, /* R3679 - EQ4_14 */ - { 0x0E60, 0xF7D9 }, /* R3680 - EQ4_15 */ - { 0x0E61, 0x040A }, /* R3681 - EQ4_16 */ - { 0x0E62, 0x1F14 }, /* R3682 - EQ4_17 */ - { 0x0E63, 0x058C }, /* R3683 - EQ4_18 */ - { 0x0E64, 0x0563 }, /* R3684 - EQ4_19 */ - { 0x0E65, 0x4000 }, /* R3685 - EQ4_20 */ - { 0x0E80, 0x0018 }, /* R3712 - DRC1 ctrl1 */ - { 0x0E81, 0x0933 }, /* R3713 - DRC1 ctrl2 */ - { 0x0E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */ - { 0x0E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */ - { 0x0E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */ - { 0x0EC0, 0x0000 }, /* R3776 - HPLPF1_1 */ - { 0x0EC1, 0x0000 }, /* R3777 - HPLPF1_2 */ - { 0x0EC4, 0x0000 }, /* R3780 - HPLPF2_1 */ - { 0x0EC5, 0x0000 }, /* R3781 - HPLPF2_2 */ - { 0x0EC8, 0x0000 }, /* R3784 - HPLPF3_1 */ - { 0x0EC9, 0x0000 }, /* R3785 - HPLPF3_2 */ - { 0x0ECC, 0x0000 }, /* R3788 - HPLPF4_1 */ - { 0x0ECD, 0x0000 }, /* R3789 - HPLPF4_2 */ -}; diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm5100.c b/ANDROID_3.4.5/sound/soc/codecs/wm5100.c deleted file mode 100644 index b9c185ce..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm5100.c +++ /dev/null @@ -1,2766 +0,0 @@ -/* - * wm5100.c -- WM5100 ALSA SoC Audio driver - * - * Copyright 2011 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm5100.h" - -#define WM5100_NUM_CORE_SUPPLIES 2 -static const char *wm5100_core_supply_names[WM5100_NUM_CORE_SUPPLIES] = { - "DBVDD1", - "LDOVDD", /* If DCVDD is supplied externally specify as LDOVDD */ -}; - -#define WM5100_AIFS 3 -#define WM5100_SYNC_SRS 3 - -struct wm5100_fll { - int fref; - int fout; - int src; - struct completion lock; -}; - -/* codec private data */ -struct wm5100_priv { - struct device *dev; - struct regmap *regmap; - struct snd_soc_codec *codec; - - struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES]; - - int rev; - - int sysclk; - int asyncclk; - - bool aif_async[WM5100_AIFS]; - bool aif_symmetric[WM5100_AIFS]; - int sr_ref[WM5100_SYNC_SRS]; - - bool out_ena[2]; - - struct snd_soc_jack *jack; - bool jack_detecting; - bool jack_mic; - int jack_mode; - int jack_flips; - - struct wm5100_fll fll[2]; - - struct wm5100_pdata pdata; - -#ifdef CONFIG_GPIOLIB - struct gpio_chip gpio_chip; -#endif -}; - -static int wm5100_sr_code[] = { - 0, - 12000, - 24000, - 48000, - 96000, - 192000, - 384000, - 768000, - 0, - 11025, - 22050, - 44100, - 88200, - 176400, - 352800, - 705600, - 4000, - 8000, - 16000, - 32000, - 64000, - 128000, - 256000, - 512000, -}; - -static int wm5100_sr_regs[WM5100_SYNC_SRS] = { - WM5100_CLOCKING_4, - WM5100_CLOCKING_5, - WM5100_CLOCKING_6, -}; - -static int wm5100_alloc_sr(struct snd_soc_codec *codec, int rate) -{ - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - int sr_code, sr_free, i; - - for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++) - if (wm5100_sr_code[i] == rate) - break; - if (i == ARRAY_SIZE(wm5100_sr_code)) { - dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate); - return -EINVAL; - } - sr_code = i; - - if ((wm5100->sysclk % rate) == 0) { - /* Is this rate already in use? */ - sr_free = -1; - for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) { - if (!wm5100->sr_ref[i] && sr_free == -1) { - sr_free = i; - continue; - } - if ((snd_soc_read(codec, wm5100_sr_regs[i]) & - WM5100_SAMPLE_RATE_1_MASK) == sr_code) - break; - } - - if (i < ARRAY_SIZE(wm5100_sr_regs)) { - wm5100->sr_ref[i]++; - dev_dbg(codec->dev, "SR %dHz, slot %d, ref %d\n", - rate, i, wm5100->sr_ref[i]); - return i; - } - - if (sr_free == -1) { - dev_err(codec->dev, "All SR slots already in use\n"); - return -EBUSY; - } - - dev_dbg(codec->dev, "Allocating SR slot %d for %dHz\n", - sr_free, rate); - wm5100->sr_ref[sr_free]++; - snd_soc_update_bits(codec, wm5100_sr_regs[sr_free], - WM5100_SAMPLE_RATE_1_MASK, - sr_code); - - return sr_free; - - } else { - dev_err(codec->dev, - "SR %dHz incompatible with %dHz SYSCLK and %dHz ASYNCCLK\n", - rate, wm5100->sysclk, wm5100->asyncclk); - return -EINVAL; - } -} - -static void wm5100_free_sr(struct snd_soc_codec *codec, int rate) -{ - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - int i, sr_code; - - for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++) - if (wm5100_sr_code[i] == rate) - break; - if (i == ARRAY_SIZE(wm5100_sr_code)) { - dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate); - return; - } - sr_code = wm5100_sr_code[i]; - - for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) { - if (!wm5100->sr_ref[i]) - continue; - - if ((snd_soc_read(codec, wm5100_sr_regs[i]) & - WM5100_SAMPLE_RATE_1_MASK) == sr_code) - break; - } - if (i < ARRAY_SIZE(wm5100_sr_regs)) { - wm5100->sr_ref[i]--; - dev_dbg(codec->dev, "Dereference SR %dHz, count now %d\n", - rate, wm5100->sr_ref[i]); - } else { - dev_warn(codec->dev, "Freeing unreferenced sample rate %dHz\n", - rate); - } -} - -static int wm5100_reset(struct wm5100_priv *wm5100) -{ - if (wm5100->pdata.reset) { - gpio_set_value_cansleep(wm5100->pdata.reset, 0); - gpio_set_value_cansleep(wm5100->pdata.reset, 1); - - return 0; - } else { - return regmap_write(wm5100->regmap, WM5100_SOFTWARE_RESET, 0); - } -} - -static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0); -static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static DECLARE_TLV_DB_SCALE(mixer_tlv, -3200, 100, 0); -static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0); -static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); - -static const char *wm5100_mixer_texts[] = { - "None", - "Tone Generator 1", - "Tone Generator 2", - "AEC loopback", - "IN1L", - "IN1R", - "IN2L", - "IN2R", - "IN3L", - "IN3R", - "IN4L", - "IN4R", - "AIF1RX1", - "AIF1RX2", - "AIF1RX3", - "AIF1RX4", - "AIF1RX5", - "AIF1RX6", - "AIF1RX7", - "AIF1RX8", - "AIF2RX1", - "AIF2RX2", - "AIF3RX1", - "AIF3RX2", - "EQ1", - "EQ2", - "EQ3", - "EQ4", - "DRC1L", - "DRC1R", - "LHPF1", - "LHPF2", - "LHPF3", - "LHPF4", - "DSP1.1", - "DSP1.2", - "DSP1.3", - "DSP1.4", - "DSP1.5", - "DSP1.6", - "DSP2.1", - "DSP2.2", - "DSP2.3", - "DSP2.4", - "DSP2.5", - "DSP2.6", - "DSP3.1", - "DSP3.2", - "DSP3.3", - "DSP3.4", - "DSP3.5", - "DSP3.6", - "ASRC1L", - "ASRC1R", - "ASRC2L", - "ASRC2R", - "ISRC1INT1", - "ISRC1INT2", - "ISRC1INT3", - "ISRC1INT4", - "ISRC2INT1", - "ISRC2INT2", - "ISRC2INT3", - "ISRC2INT4", - "ISRC1DEC1", - "ISRC1DEC2", - "ISRC1DEC3", - "ISRC1DEC4", - "ISRC2DEC1", - "ISRC2DEC2", - "ISRC2DEC3", - "ISRC2DEC4", -}; - -static int wm5100_mixer_values[] = { - 0x00, - 0x04, /* Tone */ - 0x05, - 0x08, /* AEC */ - 0x10, /* Input */ - 0x11, - 0x12, - 0x13, - 0x14, - 0x15, - 0x16, - 0x17, - 0x20, /* AIF */ - 0x21, - 0x22, - 0x23, - 0x24, - 0x25, - 0x26, - 0x27, - 0x28, - 0x29, - 0x30, /* AIF3 - check */ - 0x31, - 0x50, /* EQ */ - 0x51, - 0x52, - 0x53, - 0x54, - 0x58, /* DRC */ - 0x59, - 0x60, /* LHPF1 */ - 0x61, /* LHPF2 */ - 0x62, /* LHPF3 */ - 0x63, /* LHPF4 */ - 0x68, /* DSP1 */ - 0x69, - 0x6a, - 0x6b, - 0x6c, - 0x6d, - 0x70, /* DSP2 */ - 0x71, - 0x72, - 0x73, - 0x74, - 0x75, - 0x78, /* DSP3 */ - 0x79, - 0x7a, - 0x7b, - 0x7c, - 0x7d, - 0x90, /* ASRC1 */ - 0x91, - 0x92, /* ASRC2 */ - 0x93, - 0xa0, /* ISRC1DEC1 */ - 0xa1, - 0xa2, - 0xa3, - 0xa4, /* ISRC1INT1 */ - 0xa5, - 0xa6, - 0xa7, - 0xa8, /* ISRC2DEC1 */ - 0xa9, - 0xaa, - 0xab, - 0xac, /* ISRC2INT1 */ - 0xad, - 0xae, - 0xaf, -}; - -#define WM5100_MIXER_CONTROLS(name, base) \ - SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \ - WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ - SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \ - WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ - SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \ - WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ - SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \ - WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv) - -#define WM5100_MUX_ENUM_DECL(name, reg) \ - SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \ - wm5100_mixer_texts, wm5100_mixer_values) - -#define WM5100_MUX_CTL_DECL(name) \ - const struct snd_kcontrol_new name##_mux = \ - SOC_DAPM_VALUE_ENUM("Route", name##_enum) - -#define WM5100_MIXER_ENUMS(name, base_reg) \ - static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg); \ - static WM5100_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \ - static WM5100_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \ - static WM5100_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \ - static WM5100_MUX_CTL_DECL(name##_in1); \ - static WM5100_MUX_CTL_DECL(name##_in2); \ - static WM5100_MUX_CTL_DECL(name##_in3); \ - static WM5100_MUX_CTL_DECL(name##_in4) - -WM5100_MIXER_ENUMS(HPOUT1L, WM5100_OUT1LMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(HPOUT1R, WM5100_OUT1RMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(HPOUT2L, WM5100_OUT2LMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(HPOUT2R, WM5100_OUT2RMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(HPOUT3L, WM5100_OUT3LMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(HPOUT3R, WM5100_OUT3RMIX_INPUT_1_SOURCE); - -WM5100_MIXER_ENUMS(SPKOUTL, WM5100_OUT4LMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(SPKOUTR, WM5100_OUT4RMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(SPKDAT1L, WM5100_OUT5LMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(SPKDAT1R, WM5100_OUT5RMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(SPKDAT2L, WM5100_OUT6LMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(SPKDAT2R, WM5100_OUT6RMIX_INPUT_1_SOURCE); - -WM5100_MIXER_ENUMS(PWM1, WM5100_PWM1MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(PWM2, WM5100_PWM1MIX_INPUT_1_SOURCE); - -WM5100_MIXER_ENUMS(AIF1TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF1TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF1TX3, WM5100_AIF1TX3MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF1TX4, WM5100_AIF1TX4MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF1TX5, WM5100_AIF1TX5MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF1TX6, WM5100_AIF1TX6MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF1TX7, WM5100_AIF1TX7MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF1TX8, WM5100_AIF1TX8MIX_INPUT_1_SOURCE); - -WM5100_MIXER_ENUMS(AIF2TX1, WM5100_AIF2TX1MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF2TX2, WM5100_AIF2TX2MIX_INPUT_1_SOURCE); - -WM5100_MIXER_ENUMS(AIF3TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(AIF3TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE); - -WM5100_MIXER_ENUMS(EQ1, WM5100_EQ1MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(EQ2, WM5100_EQ2MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(EQ3, WM5100_EQ3MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(EQ4, WM5100_EQ4MIX_INPUT_1_SOURCE); - -WM5100_MIXER_ENUMS(DRC1L, WM5100_DRC1LMIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(DRC1R, WM5100_DRC1RMIX_INPUT_1_SOURCE); - -WM5100_MIXER_ENUMS(LHPF1, WM5100_HPLP1MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(LHPF2, WM5100_HPLP2MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE); -WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE); - -#define WM5100_MUX(name, ctrl) \ - SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) - -#define WM5100_MIXER_WIDGETS(name, name_str) \ - WM5100_MUX(name_str " Input 1", &name##_in1_mux), \ - WM5100_MUX(name_str " Input 2", &name##_in2_mux), \ - WM5100_MUX(name_str " Input 3", &name##_in3_mux), \ - WM5100_MUX(name_str " Input 4", &name##_in4_mux), \ - SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) - -#define WM5100_MIXER_INPUT_ROUTES(name) \ - { name, "Tone Generator 1", "Tone Generator 1" }, \ - { name, "Tone Generator 2", "Tone Generator 2" }, \ - { name, "IN1L", "IN1L PGA" }, \ - { name, "IN1R", "IN1R PGA" }, \ - { name, "IN2L", "IN2L PGA" }, \ - { name, "IN2R", "IN2R PGA" }, \ - { name, "IN3L", "IN3L PGA" }, \ - { name, "IN3R", "IN3R PGA" }, \ - { name, "IN4L", "IN4L PGA" }, \ - { name, "IN4R", "IN4R PGA" }, \ - { name, "AIF1RX1", "AIF1RX1" }, \ - { name, "AIF1RX2", "AIF1RX2" }, \ - { name, "AIF1RX3", "AIF1RX3" }, \ - { name, "AIF1RX4", "AIF1RX4" }, \ - { name, "AIF1RX5", "AIF1RX5" }, \ - { name, "AIF1RX6", "AIF1RX6" }, \ - { name, "AIF1RX7", "AIF1RX7" }, \ - { name, "AIF1RX8", "AIF1RX8" }, \ - { name, "AIF2RX1", "AIF2RX1" }, \ - { name, "AIF2RX2", "AIF2RX2" }, \ - { name, "AIF3RX1", "AIF3RX1" }, \ - { name, "AIF3RX2", "AIF3RX2" }, \ - { name, "EQ1", "EQ1" }, \ - { name, "EQ2", "EQ2" }, \ - { name, "EQ3", "EQ3" }, \ - { name, "EQ4", "EQ4" }, \ - { name, "DRC1L", "DRC1L" }, \ - { name, "DRC1R", "DRC1R" }, \ - { name, "LHPF1", "LHPF1" }, \ - { name, "LHPF2", "LHPF2" }, \ - { name, "LHPF3", "LHPF3" }, \ - { name, "LHPF4", "LHPF4" } - -#define WM5100_MIXER_ROUTES(widget, name) \ - { widget, NULL, name " Mixer" }, \ - { name " Mixer", NULL, name " Input 1" }, \ - { name " Mixer", NULL, name " Input 2" }, \ - { name " Mixer", NULL, name " Input 3" }, \ - { name " Mixer", NULL, name " Input 4" }, \ - WM5100_MIXER_INPUT_ROUTES(name " Input 1"), \ - WM5100_MIXER_INPUT_ROUTES(name " Input 2"), \ - WM5100_MIXER_INPUT_ROUTES(name " Input 3"), \ - WM5100_MIXER_INPUT_ROUTES(name " Input 4") - -static const char *wm5100_lhpf_mode_text[] = { - "Low-pass", "High-pass" -}; - -static const struct soc_enum wm5100_lhpf1_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); - -static const struct soc_enum wm5100_lhpf2_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); - -static const struct soc_enum wm5100_lhpf3_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); - -static const struct soc_enum wm5100_lhpf4_mode = - SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2, - wm5100_lhpf_mode_text); - -static const struct snd_kcontrol_new wm5100_snd_controls[] = { -SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL, - WM5100_IN1_OSR_SHIFT, 1, 0), -SOC_SINGLE("IN2 High Performance Switch", WM5100_IN2L_CONTROL, - WM5100_IN2_OSR_SHIFT, 1, 0), -SOC_SINGLE("IN3 High Performance Switch", WM5100_IN3L_CONTROL, - WM5100_IN3_OSR_SHIFT, 1, 0), -SOC_SINGLE("IN4 High Performance Switch", WM5100_IN4L_CONTROL, - WM5100_IN4_OSR_SHIFT, 1, 0), - -/* Only applicable for analogue inputs */ -SOC_DOUBLE_R_TLV("IN1 Volume", WM5100_IN1L_CONTROL, WM5100_IN1R_CONTROL, - WM5100_IN1L_PGA_VOL_SHIFT, 94, 0, in_tlv), -SOC_DOUBLE_R_TLV("IN2 Volume", WM5100_IN2L_CONTROL, WM5100_IN2R_CONTROL, - WM5100_IN2L_PGA_VOL_SHIFT, 94, 0, in_tlv), -SOC_DOUBLE_R_TLV("IN3 Volume", WM5100_IN3L_CONTROL, WM5100_IN3R_CONTROL, - WM5100_IN3L_PGA_VOL_SHIFT, 94, 0, in_tlv), -SOC_DOUBLE_R_TLV("IN4 Volume", WM5100_IN4L_CONTROL, WM5100_IN4R_CONTROL, - WM5100_IN4L_PGA_VOL_SHIFT, 94, 0, in_tlv), - -SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_1L, - WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_VOL_SHIFT, 191, - 0, digital_tlv), -SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_2L, - WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_VOL_SHIFT, 191, - 0, digital_tlv), -SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_3L, - WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_VOL_SHIFT, 191, - 0, digital_tlv), -SOC_DOUBLE_R_TLV("IN4 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_4L, - WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_VOL_SHIFT, 191, - 0, digital_tlv), - -SOC_DOUBLE_R("IN1 Switch", WM5100_ADC_DIGITAL_VOLUME_1L, - WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN2 Switch", WM5100_ADC_DIGITAL_VOLUME_2L, - WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN3 Switch", WM5100_ADC_DIGITAL_VOLUME_3L, - WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN4 Switch", WM5100_ADC_DIGITAL_VOLUME_4L, - WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_MUTE_SHIFT, 1, 1), - -SOC_SINGLE("HPOUT1 High Performance Switch", WM5100_OUT_VOLUME_1L, - WM5100_OUT1_OSR_SHIFT, 1, 0), -SOC_SINGLE("HPOUT2 High Performance Switch", WM5100_OUT_VOLUME_2L, - WM5100_OUT2_OSR_SHIFT, 1, 0), -SOC_SINGLE("HPOUT3 High Performance Switch", WM5100_OUT_VOLUME_3L, - WM5100_OUT3_OSR_SHIFT, 1, 0), -SOC_SINGLE("SPKOUT High Performance Switch", WM5100_OUT_VOLUME_4L, - WM5100_OUT4_OSR_SHIFT, 1, 0), -SOC_SINGLE("SPKDAT1 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_5L, - WM5100_OUT5_OSR_SHIFT, 1, 0), -SOC_SINGLE("SPKDAT2 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_6L, - WM5100_OUT6_OSR_SHIFT, 1, 0), - -SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_1L, - WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_VOL_SHIFT, 159, 0, - digital_tlv), -SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_2L, - WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_VOL_SHIFT, 159, 0, - digital_tlv), -SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_3L, - WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_VOL_SHIFT, 159, 0, - digital_tlv), -SOC_DOUBLE_R_TLV("SPKOUT Digital Volume", WM5100_DAC_DIGITAL_VOLUME_4L, - WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_VOL_SHIFT, 159, 0, - digital_tlv), -SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_5L, - WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_VOL_SHIFT, 159, 0, - digital_tlv), -SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_6L, - WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_VOL_SHIFT, 159, 0, - digital_tlv), - -SOC_DOUBLE_R("HPOUT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_1L, - WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("HPOUT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_2L, - WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("HPOUT3 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_3L, - WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("SPKOUT Digital Switch", WM5100_DAC_DIGITAL_VOLUME_4L, - WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("SPKDAT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_5L, - WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("SPKDAT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_6L, - WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_MUTE_SHIFT, 1, 1), - -/* FIXME: Only valid from -12dB to 0dB (52-64) */ -SOC_DOUBLE_R_TLV("HPOUT1 Volume", WM5100_OUT_VOLUME_1L, WM5100_OUT_VOLUME_1R, - WM5100_OUT1L_PGA_VOL_SHIFT, 64, 0, out_tlv), -SOC_DOUBLE_R_TLV("HPOUT2 Volume", WM5100_OUT_VOLUME_2L, WM5100_OUT_VOLUME_2R, - WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv), -SOC_DOUBLE_R_TLV("HPOUT3 Volume", WM5100_OUT_VOLUME_3L, WM5100_OUT_VOLUME_3R, - WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv), - -SOC_DOUBLE("SPKDAT1 Switch", WM5100_PDM_SPK1_CTRL_1, WM5100_SPK1L_MUTE_SHIFT, - WM5100_SPK1R_MUTE_SHIFT, 1, 1), -SOC_DOUBLE("SPKDAT2 Switch", WM5100_PDM_SPK2_CTRL_1, WM5100_SPK2L_MUTE_SHIFT, - WM5100_SPK2R_MUTE_SHIFT, 1, 1), - -SOC_SINGLE_TLV("EQ1 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ1_B1_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ1 Band 2 Volume", WM5100_EQ1_1, WM5100_EQ1_B2_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ1 Band 3 Volume", WM5100_EQ1_1, WM5100_EQ1_B3_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ1 Band 4 Volume", WM5100_EQ1_2, WM5100_EQ1_B4_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ1 Band 5 Volume", WM5100_EQ1_2, WM5100_EQ1_B5_GAIN_SHIFT, - 24, 0, eq_tlv), - -SOC_SINGLE_TLV("EQ2 Band 1 Volume", WM5100_EQ2_1, WM5100_EQ2_B1_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Band 2 Volume", WM5100_EQ2_1, WM5100_EQ2_B2_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Band 3 Volume", WM5100_EQ2_1, WM5100_EQ2_B3_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Band 4 Volume", WM5100_EQ2_2, WM5100_EQ2_B4_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Band 5 Volume", WM5100_EQ2_2, WM5100_EQ2_B5_GAIN_SHIFT, - 24, 0, eq_tlv), - -SOC_SINGLE_TLV("EQ3 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ3_B1_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Band 2 Volume", WM5100_EQ3_1, WM5100_EQ3_B2_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Band 3 Volume", WM5100_EQ3_1, WM5100_EQ3_B3_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Band 4 Volume", WM5100_EQ3_2, WM5100_EQ3_B4_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Band 5 Volume", WM5100_EQ3_2, WM5100_EQ3_B5_GAIN_SHIFT, - 24, 0, eq_tlv), - -SOC_SINGLE_TLV("EQ4 Band 1 Volume", WM5100_EQ4_1, WM5100_EQ4_B1_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Band 2 Volume", WM5100_EQ4_1, WM5100_EQ4_B2_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Band 3 Volume", WM5100_EQ4_1, WM5100_EQ4_B3_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Band 4 Volume", WM5100_EQ4_2, WM5100_EQ4_B4_GAIN_SHIFT, - 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Band 5 Volume", WM5100_EQ4_2, WM5100_EQ4_B5_GAIN_SHIFT, - 24, 0, eq_tlv), - -SOC_ENUM("LHPF1 Mode", wm5100_lhpf1_mode), -SOC_ENUM("LHPF2 Mode", wm5100_lhpf2_mode), -SOC_ENUM("LHPF3 Mode", wm5100_lhpf3_mode), -SOC_ENUM("LHPF4 Mode", wm5100_lhpf4_mode), - -WM5100_MIXER_CONTROLS("HPOUT1L", WM5100_OUT1LMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("HPOUT1R", WM5100_OUT1RMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("HPOUT2L", WM5100_OUT2LMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("HPOUT2R", WM5100_OUT2RMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("HPOUT3L", WM5100_OUT3LMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("HPOUT3R", WM5100_OUT3RMIX_INPUT_1_SOURCE), - -WM5100_MIXER_CONTROLS("SPKOUTL", WM5100_OUT4LMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("SPKOUTR", WM5100_OUT4RMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("SPKDAT1L", WM5100_OUT5LMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("SPKDAT1R", WM5100_OUT5RMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("SPKDAT2L", WM5100_OUT6LMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("SPKDAT2R", WM5100_OUT6RMIX_INPUT_1_SOURCE), - -WM5100_MIXER_CONTROLS("PWM1", WM5100_PWM1MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("PWM2", WM5100_PWM2MIX_INPUT_1_SOURCE), - -WM5100_MIXER_CONTROLS("AIF1TX1", WM5100_AIF1TX1MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF1TX2", WM5100_AIF1TX2MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF1TX3", WM5100_AIF1TX3MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF1TX4", WM5100_AIF1TX4MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF1TX5", WM5100_AIF1TX5MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF1TX6", WM5100_AIF1TX6MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF1TX7", WM5100_AIF1TX7MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF1TX8", WM5100_AIF1TX8MIX_INPUT_1_SOURCE), - -WM5100_MIXER_CONTROLS("AIF2TX1", WM5100_AIF2TX1MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF2TX2", WM5100_AIF2TX2MIX_INPUT_1_SOURCE), - -WM5100_MIXER_CONTROLS("AIF3TX1", WM5100_AIF3TX1MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("AIF3TX2", WM5100_AIF3TX2MIX_INPUT_1_SOURCE), - -WM5100_MIXER_CONTROLS("EQ1", WM5100_EQ1MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("EQ2", WM5100_EQ2MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("EQ3", WM5100_EQ3MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE), - -WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE), -SND_SOC_BYTES_MASK("DRC", WM5100_DRC1_CTRL1, 5, - WM5100_DRCL_ENA | WM5100_DRCR_ENA), - -WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("LHPF3", WM5100_HPLP3MIX_INPUT_1_SOURCE), -WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE), -}; - -static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm, - enum snd_soc_dapm_type event, int subseq) -{ - struct snd_soc_codec *codec = container_of(dapm, - struct snd_soc_codec, dapm); - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - u16 val, expect, i; - - /* Wait for the outputs to flag themselves as enabled */ - if (wm5100->out_ena[0]) { - expect = snd_soc_read(codec, WM5100_CHANNEL_ENABLES_1); - for (i = 0; i < 200; i++) { - val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_1); - if (val == expect) { - wm5100->out_ena[0] = false; - break; - } - } - if (i == 200) { - dev_err(codec->dev, "Timeout waiting for OUTPUT1 %x\n", - expect); - } - } - - if (wm5100->out_ena[1]) { - expect = snd_soc_read(codec, WM5100_OUTPUT_ENABLES_2); - for (i = 0; i < 200; i++) { - val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_2); - if (val == expect) { - wm5100->out_ena[1] = false; - break; - } - } - if (i == 200) { - dev_err(codec->dev, "Timeout waiting for OUTPUT2 %x\n", - expect); - } - } -} - -static int wm5100_out_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, - int event) -{ - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec); - - switch (w->reg) { - case WM5100_CHANNEL_ENABLES_1: - wm5100->out_ena[0] = true; - break; - case WM5100_OUTPUT_ENABLES_2: - wm5100->out_ena[0] = true; - break; - default: - break; - } - - return 0; -} - -static void wm5100_log_status3(struct wm5100_priv *wm5100, int val) -{ - if (val & WM5100_SPK_SHUTDOWN_WARN_EINT) - dev_crit(wm5100->dev, "Speaker shutdown warning\n"); - if (val & WM5100_SPK_SHUTDOWN_EINT) - dev_crit(wm5100->dev, "Speaker shutdown\n"); - if (val & WM5100_CLKGEN_ERR_EINT) - dev_crit(wm5100->dev, "SYSCLK underclocked\n"); - if (val & WM5100_CLKGEN_ERR_ASYNC_EINT) - dev_crit(wm5100->dev, "ASYNCCLK underclocked\n"); -} - -static void wm5100_log_status4(struct wm5100_priv *wm5100, int val) -{ - if (val & WM5100_AIF3_ERR_EINT) - dev_err(wm5100->dev, "AIF3 configuration error\n"); - if (val & WM5100_AIF2_ERR_EINT) - dev_err(wm5100->dev, "AIF2 configuration error\n"); - if (val & WM5100_AIF1_ERR_EINT) - dev_err(wm5100->dev, "AIF1 configuration error\n"); - if (val & WM5100_CTRLIF_ERR_EINT) - dev_err(wm5100->dev, "Control interface error\n"); - if (val & WM5100_ISRC2_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "ISRC2 underclocked\n"); - if (val & WM5100_ISRC1_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "ISRC1 underclocked\n"); - if (val & WM5100_FX_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "FX underclocked\n"); - if (val & WM5100_AIF3_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "AIF3 underclocked\n"); - if (val & WM5100_AIF2_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "AIF2 underclocked\n"); - if (val & WM5100_AIF1_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "AIF1 underclocked\n"); - if (val & WM5100_ASRC_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "ASRC underclocked\n"); - if (val & WM5100_DAC_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "DAC underclocked\n"); - if (val & WM5100_ADC_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "ADC underclocked\n"); - if (val & WM5100_MIXER_UNDERCLOCKED_EINT) - dev_err(wm5100->dev, "Mixer underclocked\n"); -} - -static int wm5100_post_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, - int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3); - ret &= WM5100_SPK_SHUTDOWN_WARN_STS | - WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS | - WM5100_CLKGEN_ERR_ASYNC_STS; - wm5100_log_status3(wm5100, ret); - - ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4); - wm5100_log_status4(wm5100, ret); - - return 0; -} - -static const struct snd_soc_dapm_widget wm5100_dapm_widgets[] = { -SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, - 0, NULL, 0), - -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), -SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), - -SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1, - WM5100_CP2_BYPASS_SHIFT, 1, NULL, 0), - -SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT, - 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS2", WM5100_MIC_BIAS_CTRL_2, WM5100_MICB2_ENA_SHIFT, - 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS3", WM5100_MIC_BIAS_CTRL_3, WM5100_MICB3_ENA_SHIFT, - 0, NULL, 0), - -SND_SOC_DAPM_INPUT("IN1L"), -SND_SOC_DAPM_INPUT("IN1R"), -SND_SOC_DAPM_INPUT("IN2L"), -SND_SOC_DAPM_INPUT("IN2R"), -SND_SOC_DAPM_INPUT("IN3L"), -SND_SOC_DAPM_INPUT("IN3R"), -SND_SOC_DAPM_INPUT("IN4L"), -SND_SOC_DAPM_INPUT("IN4R"), -SND_SOC_DAPM_SIGGEN("TONE"), - -SND_SOC_DAPM_PGA_E("IN1L PGA", WM5100_INPUT_ENABLES, WM5100_IN1L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("IN1R PGA", WM5100_INPUT_ENABLES, WM5100_IN1R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("IN2L PGA", WM5100_INPUT_ENABLES, WM5100_IN2L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("IN2R PGA", WM5100_INPUT_ENABLES, WM5100_IN2R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("IN3L PGA", WM5100_INPUT_ENABLES, WM5100_IN3L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("IN3R PGA", WM5100_INPUT_ENABLES, WM5100_IN3R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("IN4L PGA", WM5100_INPUT_ENABLES, WM5100_IN4L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("IN4R PGA", WM5100_INPUT_ENABLES, WM5100_IN4R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), - -SND_SOC_DAPM_PGA("Tone Generator 1", WM5100_TONE_GENERATOR_1, - WM5100_TONE1_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA("Tone Generator 2", WM5100_TONE_GENERATOR_1, - WM5100_TONE2_ENA_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 0, - WM5100_AUDIO_IF_1_27, WM5100_AIF1RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 1, - WM5100_AUDIO_IF_1_27, WM5100_AIF1RX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 2, - WM5100_AUDIO_IF_1_27, WM5100_AIF1RX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 3, - WM5100_AUDIO_IF_1_27, WM5100_AIF1RX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 4, - WM5100_AUDIO_IF_1_27, WM5100_AIF1RX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX6", "AIF1 Playback", 5, - WM5100_AUDIO_IF_1_27, WM5100_AIF1RX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX7", "AIF1 Playback", 6, - WM5100_AUDIO_IF_1_27, WM5100_AIF1RX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX8", "AIF1 Playback", 7, - WM5100_AUDIO_IF_1_27, WM5100_AIF1RX8_ENA_SHIFT, 0), - -SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0, - WM5100_AUDIO_IF_2_27, WM5100_AIF2RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX2", "AIF2 Playback", 1, - WM5100_AUDIO_IF_2_27, WM5100_AIF2RX2_ENA_SHIFT, 0), - -SND_SOC_DAPM_AIF_IN("AIF3RX1", "AIF3 Playback", 0, - WM5100_AUDIO_IF_3_27, WM5100_AIF3RX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_IN("AIF3RX2", "AIF3 Playback", 1, - WM5100_AUDIO_IF_3_27, WM5100_AIF3RX2_ENA_SHIFT, 0), - -SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 0, - WM5100_AUDIO_IF_1_26, WM5100_AIF1TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 1, - WM5100_AUDIO_IF_1_26, WM5100_AIF1TX2_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 2, - WM5100_AUDIO_IF_1_26, WM5100_AIF1TX3_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 3, - WM5100_AUDIO_IF_1_26, WM5100_AIF1TX4_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 4, - WM5100_AUDIO_IF_1_26, WM5100_AIF1TX5_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX6", "AIF1 Capture", 5, - WM5100_AUDIO_IF_1_26, WM5100_AIF1TX6_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX7", "AIF1 Capture", 6, - WM5100_AUDIO_IF_1_26, WM5100_AIF1TX7_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX8", "AIF1 Capture", 7, - WM5100_AUDIO_IF_1_26, WM5100_AIF1TX8_ENA_SHIFT, 0), - -SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0, - WM5100_AUDIO_IF_2_26, WM5100_AIF2TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX2", "AIF2 Capture", 1, - WM5100_AUDIO_IF_2_26, WM5100_AIF2TX2_ENA_SHIFT, 0), - -SND_SOC_DAPM_AIF_OUT("AIF3TX1", "AIF3 Capture", 0, - WM5100_AUDIO_IF_3_26, WM5100_AIF3TX1_ENA_SHIFT, 0), -SND_SOC_DAPM_AIF_OUT("AIF3TX2", "AIF3 Capture", 1, - WM5100_AUDIO_IF_3_26, WM5100_AIF3TX2_ENA_SHIFT, 0), - -SND_SOC_DAPM_PGA_E("OUT6L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT6R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT5L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT5R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT4L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT4R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT3L", WM5100_CHANNEL_ENABLES_1, WM5100_HP3L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT3R", WM5100_CHANNEL_ENABLES_1, WM5100_HP3R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT2L", WM5100_CHANNEL_ENABLES_1, WM5100_HP2L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT2R", WM5100_CHANNEL_ENABLES_1, WM5100_HP2R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT1L", WM5100_CHANNEL_ENABLES_1, WM5100_HP1L_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("OUT1R", WM5100_CHANNEL_ENABLES_1, WM5100_HP1R_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("PWM1 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM1_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_E("PWM2 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM2_ENA_SHIFT, 0, - NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU), - -SND_SOC_DAPM_PGA("EQ1", WM5100_EQ1_1, WM5100_EQ1_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA("EQ2", WM5100_EQ2_1, WM5100_EQ2_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA("EQ3", WM5100_EQ3_1, WM5100_EQ3_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_PGA("EQ4", WM5100_EQ4_1, WM5100_EQ4_ENA_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_PGA("DRC1L", WM5100_DRC1_CTRL1, WM5100_DRCL_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("DRC1R", WM5100_DRC1_CTRL1, WM5100_DRCR_ENA_SHIFT, 0, - NULL, 0), - -SND_SOC_DAPM_PGA("LHPF1", WM5100_HPLPF1_1, WM5100_LHPF1_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LHPF2", WM5100_HPLPF2_1, WM5100_LHPF2_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LHPF3", WM5100_HPLPF3_1, WM5100_LHPF3_ENA_SHIFT, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LHPF4", WM5100_HPLPF4_1, WM5100_LHPF4_ENA_SHIFT, 0, - NULL, 0), - -WM5100_MIXER_WIDGETS(EQ1, "EQ1"), -WM5100_MIXER_WIDGETS(EQ2, "EQ2"), -WM5100_MIXER_WIDGETS(EQ3, "EQ3"), -WM5100_MIXER_WIDGETS(EQ4, "EQ4"), - -WM5100_MIXER_WIDGETS(DRC1L, "DRC1L"), -WM5100_MIXER_WIDGETS(DRC1R, "DRC1R"), - -WM5100_MIXER_WIDGETS(LHPF1, "LHPF1"), -WM5100_MIXER_WIDGETS(LHPF2, "LHPF2"), -WM5100_MIXER_WIDGETS(LHPF3, "LHPF3"), -WM5100_MIXER_WIDGETS(LHPF4, "LHPF4"), - -WM5100_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), -WM5100_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), -WM5100_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), -WM5100_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), -WM5100_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), -WM5100_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), -WM5100_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"), -WM5100_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"), - -WM5100_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"), -WM5100_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), - -WM5100_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), -WM5100_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), - -WM5100_MIXER_WIDGETS(HPOUT1L, "HPOUT1L"), -WM5100_MIXER_WIDGETS(HPOUT1R, "HPOUT1R"), -WM5100_MIXER_WIDGETS(HPOUT2L, "HPOUT2L"), -WM5100_MIXER_WIDGETS(HPOUT2R, "HPOUT2R"), -WM5100_MIXER_WIDGETS(HPOUT3L, "HPOUT3L"), -WM5100_MIXER_WIDGETS(HPOUT3R, "HPOUT3R"), - -WM5100_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), -WM5100_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), -WM5100_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), -WM5100_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"), -WM5100_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"), -WM5100_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"), - -WM5100_MIXER_WIDGETS(PWM1, "PWM1"), -WM5100_MIXER_WIDGETS(PWM2, "PWM2"), - -SND_SOC_DAPM_OUTPUT("HPOUT1L"), -SND_SOC_DAPM_OUTPUT("HPOUT1R"), -SND_SOC_DAPM_OUTPUT("HPOUT2L"), -SND_SOC_DAPM_OUTPUT("HPOUT2R"), -SND_SOC_DAPM_OUTPUT("HPOUT3L"), -SND_SOC_DAPM_OUTPUT("HPOUT3R"), -SND_SOC_DAPM_OUTPUT("SPKOUTL"), -SND_SOC_DAPM_OUTPUT("SPKOUTR"), -SND_SOC_DAPM_OUTPUT("SPKDAT1"), -SND_SOC_DAPM_OUTPUT("SPKDAT2"), -SND_SOC_DAPM_OUTPUT("PWM1"), -SND_SOC_DAPM_OUTPUT("PWM2"), -}; - -/* We register a _POST event if we don't have IRQ support so we can - * look at the error status from the CODEC - if we've got the IRQ - * hooked up then we will get prompted to look by an interrupt. - */ -static const struct snd_soc_dapm_widget wm5100_dapm_widgets_noirq[] = { -SND_SOC_DAPM_POST("Post", wm5100_post_ev), -}; - -static const struct snd_soc_dapm_route wm5100_dapm_routes[] = { - { "CP1", NULL, "CPVDD" }, - { "CP2 Active", NULL, "CPVDD" }, - - { "IN1L", NULL, "SYSCLK" }, - { "IN1R", NULL, "SYSCLK" }, - { "IN2L", NULL, "SYSCLK" }, - { "IN2R", NULL, "SYSCLK" }, - { "IN3L", NULL, "SYSCLK" }, - { "IN3R", NULL, "SYSCLK" }, - { "IN4L", NULL, "SYSCLK" }, - { "IN4R", NULL, "SYSCLK" }, - - { "OUT1L", NULL, "SYSCLK" }, - { "OUT1R", NULL, "SYSCLK" }, - { "OUT2L", NULL, "SYSCLK" }, - { "OUT2R", NULL, "SYSCLK" }, - { "OUT3L", NULL, "SYSCLK" }, - { "OUT3R", NULL, "SYSCLK" }, - { "OUT4L", NULL, "SYSCLK" }, - { "OUT4R", NULL, "SYSCLK" }, - { "OUT5L", NULL, "SYSCLK" }, - { "OUT5R", NULL, "SYSCLK" }, - { "OUT6L", NULL, "SYSCLK" }, - { "OUT6R", NULL, "SYSCLK" }, - - { "AIF1RX1", NULL, "SYSCLK" }, - { "AIF1RX2", NULL, "SYSCLK" }, - { "AIF1RX3", NULL, "SYSCLK" }, - { "AIF1RX4", NULL, "SYSCLK" }, - { "AIF1RX5", NULL, "SYSCLK" }, - { "AIF1RX6", NULL, "SYSCLK" }, - { "AIF1RX7", NULL, "SYSCLK" }, - { "AIF1RX8", NULL, "SYSCLK" }, - - { "AIF2RX1", NULL, "SYSCLK" }, - { "AIF2RX1", NULL, "DBVDD2" }, - { "AIF2RX2", NULL, "SYSCLK" }, - { "AIF2RX2", NULL, "DBVDD2" }, - - { "AIF3RX1", NULL, "SYSCLK" }, - { "AIF3RX1", NULL, "DBVDD3" }, - { "AIF3RX2", NULL, "SYSCLK" }, - { "AIF3RX2", NULL, "DBVDD3" }, - - { "AIF1TX1", NULL, "SYSCLK" }, - { "AIF1TX2", NULL, "SYSCLK" }, - { "AIF1TX3", NULL, "SYSCLK" }, - { "AIF1TX4", NULL, "SYSCLK" }, - { "AIF1TX5", NULL, "SYSCLK" }, - { "AIF1TX6", NULL, "SYSCLK" }, - { "AIF1TX7", NULL, "SYSCLK" }, - { "AIF1TX8", NULL, "SYSCLK" }, - - { "AIF2TX1", NULL, "SYSCLK" }, - { "AIF2TX1", NULL, "DBVDD2" }, - { "AIF2TX2", NULL, "SYSCLK" }, - { "AIF2TX2", NULL, "DBVDD2" }, - - { "AIF3TX1", NULL, "SYSCLK" }, - { "AIF3TX1", NULL, "DBVDD3" }, - { "AIF3TX2", NULL, "SYSCLK" }, - { "AIF3TX2", NULL, "DBVDD3" }, - - { "MICBIAS1", NULL, "CP2" }, - { "MICBIAS2", NULL, "CP2" }, - { "MICBIAS3", NULL, "CP2" }, - - { "IN1L PGA", NULL, "CP2" }, - { "IN1R PGA", NULL, "CP2" }, - { "IN2L PGA", NULL, "CP2" }, - { "IN2R PGA", NULL, "CP2" }, - { "IN3L PGA", NULL, "CP2" }, - { "IN3R PGA", NULL, "CP2" }, - { "IN4L PGA", NULL, "CP2" }, - { "IN4R PGA", NULL, "CP2" }, - - { "IN1L PGA", NULL, "CP2 Active" }, - { "IN1R PGA", NULL, "CP2 Active" }, - { "IN2L PGA", NULL, "CP2 Active" }, - { "IN2R PGA", NULL, "CP2 Active" }, - { "IN3L PGA", NULL, "CP2 Active" }, - { "IN3R PGA", NULL, "CP2 Active" }, - { "IN4L PGA", NULL, "CP2 Active" }, - { "IN4R PGA", NULL, "CP2 Active" }, - - { "OUT1L", NULL, "CP1" }, - { "OUT1R", NULL, "CP1" }, - { "OUT2L", NULL, "CP1" }, - { "OUT2R", NULL, "CP1" }, - { "OUT3L", NULL, "CP1" }, - { "OUT3R", NULL, "CP1" }, - - { "Tone Generator 1", NULL, "TONE" }, - { "Tone Generator 2", NULL, "TONE" }, - - { "IN1L PGA", NULL, "IN1L" }, - { "IN1R PGA", NULL, "IN1R" }, - { "IN2L PGA", NULL, "IN2L" }, - { "IN2R PGA", NULL, "IN2R" }, - { "IN3L PGA", NULL, "IN3L" }, - { "IN3R PGA", NULL, "IN3R" }, - { "IN4L PGA", NULL, "IN4L" }, - { "IN4R PGA", NULL, "IN4R" }, - - WM5100_MIXER_ROUTES("OUT1L", "HPOUT1L"), - WM5100_MIXER_ROUTES("OUT1R", "HPOUT1R"), - WM5100_MIXER_ROUTES("OUT2L", "HPOUT2L"), - WM5100_MIXER_ROUTES("OUT2R", "HPOUT2R"), - WM5100_MIXER_ROUTES("OUT3L", "HPOUT3L"), - WM5100_MIXER_ROUTES("OUT3R", "HPOUT3R"), - - WM5100_MIXER_ROUTES("OUT4L", "SPKOUTL"), - WM5100_MIXER_ROUTES("OUT4R", "SPKOUTR"), - WM5100_MIXER_ROUTES("OUT5L", "SPKDAT1L"), - WM5100_MIXER_ROUTES("OUT5R", "SPKDAT1R"), - WM5100_MIXER_ROUTES("OUT6L", "SPKDAT2L"), - WM5100_MIXER_ROUTES("OUT6R", "SPKDAT2R"), - - WM5100_MIXER_ROUTES("PWM1 Driver", "PWM1"), - WM5100_MIXER_ROUTES("PWM2 Driver", "PWM2"), - - WM5100_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), - WM5100_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), - WM5100_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), - WM5100_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), - WM5100_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), - WM5100_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), - WM5100_MIXER_ROUTES("AIF1TX7", "AIF1TX7"), - WM5100_MIXER_ROUTES("AIF1TX8", "AIF1TX8"), - - WM5100_MIXER_ROUTES("AIF2TX1", "AIF2TX1"), - WM5100_MIXER_ROUTES("AIF2TX2", "AIF2TX2"), - - WM5100_MIXER_ROUTES("AIF3TX1", "AIF3TX1"), - WM5100_MIXER_ROUTES("AIF3TX2", "AIF3TX2"), - - WM5100_MIXER_ROUTES("EQ1", "EQ1"), - WM5100_MIXER_ROUTES("EQ2", "EQ2"), - WM5100_MIXER_ROUTES("EQ3", "EQ3"), - WM5100_MIXER_ROUTES("EQ4", "EQ4"), - - WM5100_MIXER_ROUTES("DRC1L", "DRC1L"), - WM5100_MIXER_ROUTES("DRC1R", "DRC1R"), - - WM5100_MIXER_ROUTES("LHPF1", "LHPF1"), - WM5100_MIXER_ROUTES("LHPF2", "LHPF2"), - WM5100_MIXER_ROUTES("LHPF3", "LHPF3"), - WM5100_MIXER_ROUTES("LHPF4", "LHPF4"), - - { "HPOUT1L", NULL, "OUT1L" }, - { "HPOUT1R", NULL, "OUT1R" }, - { "HPOUT2L", NULL, "OUT2L" }, - { "HPOUT2R", NULL, "OUT2R" }, - { "HPOUT3L", NULL, "OUT3L" }, - { "HPOUT3R", NULL, "OUT3R" }, - { "SPKOUTL", NULL, "OUT4L" }, - { "SPKOUTR", NULL, "OUT4R" }, - { "SPKDAT1", NULL, "OUT5L" }, - { "SPKDAT1", NULL, "OUT5R" }, - { "SPKDAT2", NULL, "OUT6L" }, - { "SPKDAT2", NULL, "OUT6R" }, - { "PWM1", NULL, "PWM1 Driver" }, - { "PWM2", NULL, "PWM2 Driver" }, -}; - -static const __devinitdata struct reg_default wm5100_reva_patches[] = { - { WM5100_AUDIO_IF_1_10, 0 }, - { WM5100_AUDIO_IF_1_11, 1 }, - { WM5100_AUDIO_IF_1_12, 2 }, - { WM5100_AUDIO_IF_1_13, 3 }, - { WM5100_AUDIO_IF_1_14, 4 }, - { WM5100_AUDIO_IF_1_15, 5 }, - { WM5100_AUDIO_IF_1_16, 6 }, - { WM5100_AUDIO_IF_1_17, 7 }, - - { WM5100_AUDIO_IF_1_18, 0 }, - { WM5100_AUDIO_IF_1_19, 1 }, - { WM5100_AUDIO_IF_1_20, 2 }, - { WM5100_AUDIO_IF_1_21, 3 }, - { WM5100_AUDIO_IF_1_22, 4 }, - { WM5100_AUDIO_IF_1_23, 5 }, - { WM5100_AUDIO_IF_1_24, 6 }, - { WM5100_AUDIO_IF_1_25, 7 }, - - { WM5100_AUDIO_IF_2_10, 0 }, - { WM5100_AUDIO_IF_2_11, 1 }, - - { WM5100_AUDIO_IF_2_18, 0 }, - { WM5100_AUDIO_IF_2_19, 1 }, - - { WM5100_AUDIO_IF_3_10, 0 }, - { WM5100_AUDIO_IF_3_11, 1 }, - - { WM5100_AUDIO_IF_3_18, 0 }, - { WM5100_AUDIO_IF_3_19, 1 }, -}; - -static int wm5100_dai_to_base(struct snd_soc_dai *dai) -{ - switch (dai->id) { - case 0: - return WM5100_AUDIO_IF_1_1 - 1; - case 1: - return WM5100_AUDIO_IF_2_1 - 1; - case 2: - return WM5100_AUDIO_IF_3_1 - 1; - default: - BUG(); - return -EINVAL; - } -} - -static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - int lrclk, bclk, mask, base; - - base = wm5100_dai_to_base(dai); - if (base < 0) - return base; - - lrclk = 0; - bclk = 0; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - mask = 0; - break; - case SND_SOC_DAIFMT_DSP_B: - mask = 1; - break; - case SND_SOC_DAIFMT_I2S: - mask = 2; - break; - case SND_SOC_DAIFMT_LEFT_J: - mask = 3; - break; - default: - dev_err(codec->dev, "Unsupported DAI format %d\n", - fmt & SND_SOC_DAIFMT_FORMAT_MASK); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBS_CFM: - lrclk |= WM5100_AIF1TX_LRCLK_MSTR; - break; - case SND_SOC_DAIFMT_CBM_CFS: - bclk |= WM5100_AIF1_BCLK_MSTR; - break; - case SND_SOC_DAIFMT_CBM_CFM: - lrclk |= WM5100_AIF1TX_LRCLK_MSTR; - bclk |= WM5100_AIF1_BCLK_MSTR; - break; - default: - dev_err(codec->dev, "Unsupported master mode %d\n", - fmt & SND_SOC_DAIFMT_MASTER_MASK); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - bclk |= WM5100_AIF1_BCLK_INV; - lrclk |= WM5100_AIF1TX_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - bclk |= WM5100_AIF1_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - lrclk |= WM5100_AIF1TX_LRCLK_INV; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_MSTR | - WM5100_AIF1_BCLK_INV, bclk); - snd_soc_update_bits(codec, base + 2, WM5100_AIF1TX_LRCLK_MSTR | - WM5100_AIF1TX_LRCLK_INV, lrclk); - snd_soc_update_bits(codec, base + 3, WM5100_AIF1TX_LRCLK_MSTR | - WM5100_AIF1TX_LRCLK_INV, lrclk); - snd_soc_update_bits(codec, base + 5, WM5100_AIF1_FMT_MASK, mask); - - return 0; -} - -#define WM5100_NUM_BCLK_RATES 19 - -static int wm5100_bclk_rates_dat[WM5100_NUM_BCLK_RATES] = { - 32000, - 48000, - 64000, - 96000, - 128000, - 192000, - 256000, - 384000, - 512000, - 768000, - 1024000, - 1536000, - 2048000, - 3072000, - 4096000, - 6144000, - 8192000, - 12288000, - 24576000, -}; - -static int wm5100_bclk_rates_cd[WM5100_NUM_BCLK_RATES] = { - 29400, - 44100, - 58800, - 88200, - 117600, - 176400, - 235200, - 352800, - 470400, - 705600, - 940800, - 1411200, - 1881600, - 2882400, - 3763200, - 5644800, - 7526400, - 11289600, - 22579600, -}; - -static int wm5100_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - bool async = wm5100->aif_async[dai->id]; - int i, base, bclk, aif_rate, lrclk, wl, fl, sr; - int *bclk_rates; - - base = wm5100_dai_to_base(dai); - if (base < 0) - return base; - - /* Data sizes if not using TDM */ - wl = snd_pcm_format_width(params_format(params)); - if (wl < 0) - return wl; - fl = snd_soc_params_to_frame_size(params); - if (fl < 0) - return fl; - - dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n", - wl, fl); - - /* Target BCLK rate */ - bclk = snd_soc_params_to_bclk(params); - if (bclk < 0) - return bclk; - - /* Root for BCLK depends on SYS/ASYNCCLK */ - if (!async) { - aif_rate = wm5100->sysclk; - sr = wm5100_alloc_sr(codec, params_rate(params)); - if (sr < 0) - return sr; - } else { - /* If we're in ASYNCCLK set the ASYNC sample rate */ - aif_rate = wm5100->asyncclk; - sr = 3; - - for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++) - if (params_rate(params) == wm5100_sr_code[i]) - break; - if (i == ARRAY_SIZE(wm5100_sr_code)) { - dev_err(codec->dev, "Invalid rate %dHzn", - params_rate(params)); - return -EINVAL; - } - - /* TODO: We should really check for symmetry */ - snd_soc_update_bits(codec, WM5100_CLOCKING_8, - WM5100_ASYNC_SAMPLE_RATE_MASK, i); - } - - if (!aif_rate) { - dev_err(codec->dev, "%s has no rate set\n", - async ? "ASYNCCLK" : "SYSCLK"); - return -EINVAL; - } - - dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz %s\n", - bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK"); - - if (aif_rate % 4000) - bclk_rates = wm5100_bclk_rates_cd; - else - bclk_rates = wm5100_bclk_rates_dat; - - for (i = 0; i < WM5100_NUM_BCLK_RATES; i++) - if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0)) - break; - if (i == WM5100_NUM_BCLK_RATES) { - dev_err(codec->dev, - "No valid BCLK for %dHz found from %dHz %s\n", - bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK"); - return -EINVAL; - } - - bclk = i; - dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]); - snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_FREQ_MASK, bclk); - - lrclk = bclk_rates[bclk] / params_rate(params); - dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - wm5100->aif_symmetric[dai->id]) - snd_soc_update_bits(codec, base + 7, - WM5100_AIF1RX_BCPF_MASK, lrclk); - else - snd_soc_update_bits(codec, base + 6, - WM5100_AIF1TX_BCPF_MASK, lrclk); - - i = (wl << WM5100_AIF1TX_WL_SHIFT) | fl; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - snd_soc_update_bits(codec, base + 9, - WM5100_AIF1RX_WL_MASK | - WM5100_AIF1RX_SLOT_LEN_MASK, i); - else - snd_soc_update_bits(codec, base + 8, - WM5100_AIF1TX_WL_MASK | - WM5100_AIF1TX_SLOT_LEN_MASK, i); - - snd_soc_update_bits(codec, base + 4, WM5100_AIF1_RATE_MASK, sr); - - return 0; -} - -static const struct snd_soc_dai_ops wm5100_dai_ops = { - .set_fmt = wm5100_set_fmt, - .hw_params = wm5100_hw_params, -}; - -static int wm5100_set_sysclk(struct snd_soc_codec *codec, int clk_id, - int source, unsigned int freq, int dir) -{ - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - int *rate_store; - int fval, audio_rate, ret, reg; - - switch (clk_id) { - case WM5100_CLK_SYSCLK: - reg = WM5100_CLOCKING_3; - rate_store = &wm5100->sysclk; - break; - case WM5100_CLK_ASYNCCLK: - reg = WM5100_CLOCKING_7; - rate_store = &wm5100->asyncclk; - break; - case WM5100_CLK_32KHZ: - /* The 32kHz clock is slightly different to the others */ - switch (source) { - case WM5100_CLKSRC_MCLK1: - case WM5100_CLKSRC_MCLK2: - case WM5100_CLKSRC_SYSCLK: - snd_soc_update_bits(codec, WM5100_CLOCKING_1, - WM5100_CLK_32K_SRC_MASK, - source); - break; - default: - return -EINVAL; - } - return 0; - - case WM5100_CLK_AIF1: - case WM5100_CLK_AIF2: - case WM5100_CLK_AIF3: - /* Not real clocks, record which clock domain they're in */ - switch (source) { - case WM5100_CLKSRC_SYSCLK: - wm5100->aif_async[clk_id - 1] = false; - break; - case WM5100_CLKSRC_ASYNCCLK: - wm5100->aif_async[clk_id - 1] = true; - break; - default: - dev_err(codec->dev, "Invalid source %d\n", source); - return -EINVAL; - } - return 0; - - case WM5100_CLK_OPCLK: - switch (freq) { - case 5644800: - case 6144000: - snd_soc_update_bits(codec, WM5100_MISC_GPIO_1, - WM5100_OPCLK_SEL_MASK, 0); - break; - case 11289600: - case 12288000: - snd_soc_update_bits(codec, WM5100_MISC_GPIO_1, - WM5100_OPCLK_SEL_MASK, 0); - break; - case 22579200: - case 24576000: - snd_soc_update_bits(codec, WM5100_MISC_GPIO_1, - WM5100_OPCLK_SEL_MASK, 0); - break; - default: - dev_err(codec->dev, "Unsupported OPCLK %dHz\n", - freq); - return -EINVAL; - } - return 0; - - default: - dev_err(codec->dev, "Unknown clock %d\n", clk_id); - return -EINVAL; - } - - switch (source) { - case WM5100_CLKSRC_SYSCLK: - case WM5100_CLKSRC_ASYNCCLK: - dev_err(codec->dev, "Invalid source %d\n", source); - return -EINVAL; - } - - switch (freq) { - case 5644800: - case 6144000: - fval = 0; - break; - case 11289600: - case 12288000: - fval = 1; - break; - case 22579200: - case 24576000: - fval = 2; - break; - default: - dev_err(codec->dev, "Invalid clock rate: %d\n", freq); - return -EINVAL; - } - - switch (freq) { - case 5644800: - case 11289600: - case 22579200: - audio_rate = 44100; - break; - - case 6144000: - case 12288000: - case 24576000: - audio_rate = 48000; - break; - - default: - BUG(); - audio_rate = 0; - break; - } - - /* TODO: Check if MCLKs are in use and enable/disable pulls to - * match. - */ - - snd_soc_update_bits(codec, reg, WM5100_SYSCLK_FREQ_MASK | - WM5100_SYSCLK_SRC_MASK, - fval << WM5100_SYSCLK_FREQ_SHIFT | source); - - /* If this is SYSCLK then configure the clock rate for the - * internal audio functions to the natural sample rate for - * this clock rate. - */ - if (clk_id == WM5100_CLK_SYSCLK) { - dev_dbg(codec->dev, "Setting primary audio rate to %dHz", - audio_rate); - if (0 && *rate_store) - wm5100_free_sr(codec, audio_rate); - ret = wm5100_alloc_sr(codec, audio_rate); - if (ret != 0) - dev_warn(codec->dev, "Primary audio slot is %d\n", - ret); - } - - *rate_store = freq; - - return 0; -} - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_refclk_div; - u16 n; - u16 theta; - u16 lambda; -}; - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - unsigned int target; - unsigned int div; - unsigned int fratio, gcd_fll; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - fll_div->fll_refclk_div = 0; - while ((Fref / div) > 13500000) { - div *= 2; - fll_div->fll_refclk_div++; - - if (div > 8) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - - pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 2; - while (Fout * div < 90000000) { - div++; - if (div > 64) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - target = Fout * div; - fll_div->fll_outdiv = div - 1; - - pr_debug("FLL Fvco=%dHz\n", target); - - /* Find an appropraite FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - fratio = fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - fll_div->n = target / (fratio * Fref); - - if (target % Fref == 0) { - fll_div->theta = 0; - fll_div->lambda = 0; - } else { - gcd_fll = gcd(target, fratio * Fref); - - fll_div->theta = (target - (fll_div->n * fratio * Fref)) - / gcd_fll; - fll_div->lambda = (fratio * Fref) / gcd_fll; - } - - pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n", - fll_div->n, fll_div->theta, fll_div->lambda); - pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n", - fll_div->fll_fratio, fratio, fll_div->fll_outdiv, - fll_div->fll_refclk_div); - - return 0; -} - -static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source, - unsigned int Fref, unsigned int Fout) -{ - struct i2c_client *i2c = to_i2c_client(codec->dev); - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - struct _fll_div factors; - struct wm5100_fll *fll; - int ret, base, lock, i, timeout; - - switch (fll_id) { - case WM5100_FLL1: - fll = &wm5100->fll[0]; - base = WM5100_FLL1_CONTROL_1 - 1; - lock = WM5100_FLL1_LOCK_STS; - break; - case WM5100_FLL2: - fll = &wm5100->fll[1]; - base = WM5100_FLL2_CONTROL_2 - 1; - lock = WM5100_FLL2_LOCK_STS; - break; - default: - dev_err(codec->dev, "Unknown FLL %d\n",fll_id); - return -EINVAL; - } - - if (!Fout) { - dev_dbg(codec->dev, "FLL%d disabled", fll_id); - if (fll->fout) - pm_runtime_put(codec->dev); - fll->fout = 0; - snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0); - return 0; - } - - switch (source) { - case WM5100_FLL_SRC_MCLK1: - case WM5100_FLL_SRC_MCLK2: - case WM5100_FLL_SRC_FLL1: - case WM5100_FLL_SRC_FLL2: - case WM5100_FLL_SRC_AIF1BCLK: - case WM5100_FLL_SRC_AIF2BCLK: - case WM5100_FLL_SRC_AIF3BCLK: - break; - default: - dev_err(codec->dev, "Invalid FLL source %d\n", source); - return -EINVAL; - } - - ret = fll_factors(&factors, Fref, Fout); - if (ret < 0) - return ret; - - /* Disable the FLL while we reconfigure */ - snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0); - - snd_soc_update_bits(codec, base + 2, - WM5100_FLL1_OUTDIV_MASK | WM5100_FLL1_FRATIO_MASK, - (factors.fll_outdiv << WM5100_FLL1_OUTDIV_SHIFT) | - factors.fll_fratio); - snd_soc_update_bits(codec, base + 3, WM5100_FLL1_THETA_MASK, - factors.theta); - snd_soc_update_bits(codec, base + 5, WM5100_FLL1_N_MASK, factors.n); - snd_soc_update_bits(codec, base + 6, - WM5100_FLL1_REFCLK_DIV_MASK | - WM5100_FLL1_REFCLK_SRC_MASK, - (factors.fll_refclk_div - << WM5100_FLL1_REFCLK_DIV_SHIFT) | source); - snd_soc_update_bits(codec, base + 7, WM5100_FLL1_LAMBDA_MASK, - factors.lambda); - - /* Clear any pending completions */ - try_wait_for_completion(&fll->lock); - - pm_runtime_get_sync(codec->dev); - - snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA); - - if (i2c->irq) - timeout = 2; - else - timeout = 50; - - snd_soc_update_bits(codec, WM5100_CLOCKING_3, WM5100_SYSCLK_ENA, - WM5100_SYSCLK_ENA); - - /* Poll for the lock; will use interrupt when we can test */ - for (i = 0; i < timeout; i++) { - if (i2c->irq) { - ret = wait_for_completion_timeout(&fll->lock, - msecs_to_jiffies(25)); - if (ret > 0) - break; - } else { - msleep(1); - } - - ret = snd_soc_read(codec, - WM5100_INTERRUPT_RAW_STATUS_3); - if (ret < 0) { - dev_err(codec->dev, - "Failed to read FLL status: %d\n", - ret); - continue; - } - if (ret & lock) - break; - } - if (i == timeout) { - dev_err(codec->dev, "FLL%d lock timed out\n", fll_id); - pm_runtime_put(codec->dev); - return -ETIMEDOUT; - } - - fll->src = source; - fll->fref = Fref; - fll->fout = Fout; - - dev_dbg(codec->dev, "FLL%d running %dHz->%dHz\n", fll_id, - Fref, Fout); - - return 0; -} - -/* Actually go much higher */ -#define WM5100_RATES SNDRV_PCM_RATE_8000_192000 - -#define WM5100_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_driver wm5100_dai[] = { - { - .name = "wm5100-aif1", - .playback = { - .stream_name = "AIF1 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM5100_RATES, - .formats = WM5100_FORMATS, - }, - .capture = { - .stream_name = "AIF1 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM5100_RATES, - .formats = WM5100_FORMATS, - }, - .ops = &wm5100_dai_ops, - }, - { - .name = "wm5100-aif2", - .id = 1, - .playback = { - .stream_name = "AIF2 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM5100_RATES, - .formats = WM5100_FORMATS, - }, - .capture = { - .stream_name = "AIF2 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM5100_RATES, - .formats = WM5100_FORMATS, - }, - .ops = &wm5100_dai_ops, - }, - { - .name = "wm5100-aif3", - .id = 2, - .playback = { - .stream_name = "AIF3 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM5100_RATES, - .formats = WM5100_FORMATS, - }, - .capture = { - .stream_name = "AIF3 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM5100_RATES, - .formats = WM5100_FORMATS, - }, - .ops = &wm5100_dai_ops, - }, -}; - -static int wm5100_dig_vu[] = { - WM5100_ADC_DIGITAL_VOLUME_1L, - WM5100_ADC_DIGITAL_VOLUME_1R, - WM5100_ADC_DIGITAL_VOLUME_2L, - WM5100_ADC_DIGITAL_VOLUME_2R, - WM5100_ADC_DIGITAL_VOLUME_3L, - WM5100_ADC_DIGITAL_VOLUME_3R, - WM5100_ADC_DIGITAL_VOLUME_4L, - WM5100_ADC_DIGITAL_VOLUME_4R, - - WM5100_DAC_DIGITAL_VOLUME_1L, - WM5100_DAC_DIGITAL_VOLUME_1R, - WM5100_DAC_DIGITAL_VOLUME_2L, - WM5100_DAC_DIGITAL_VOLUME_2R, - WM5100_DAC_DIGITAL_VOLUME_3L, - WM5100_DAC_DIGITAL_VOLUME_3R, - WM5100_DAC_DIGITAL_VOLUME_4L, - WM5100_DAC_DIGITAL_VOLUME_4R, - WM5100_DAC_DIGITAL_VOLUME_5L, - WM5100_DAC_DIGITAL_VOLUME_5R, - WM5100_DAC_DIGITAL_VOLUME_6L, - WM5100_DAC_DIGITAL_VOLUME_6R, -}; - -static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode) -{ - struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode]; - - BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes)); - - gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol); - regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1, - WM5100_ACCDET_BIAS_SRC_MASK | - WM5100_ACCDET_SRC, - (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) | - mode->micd_src << WM5100_ACCDET_SRC_SHIFT); - regmap_update_bits(wm5100->regmap, WM5100_MISC_CONTROL, - WM5100_HPCOM_SRC, - mode->micd_src << WM5100_HPCOM_SRC_SHIFT); - - wm5100->jack_mode = the_mode; - - dev_dbg(wm5100->dev, "Set microphone polarity to %d\n", - wm5100->jack_mode); -} - -static void wm5100_report_headphone(struct wm5100_priv *wm5100) -{ - dev_dbg(wm5100->dev, "Headphone detected\n"); - wm5100->jack_detecting = false; - snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE, - SND_JACK_HEADPHONE); - - /* Increase the detection rate a bit for responsiveness. */ - regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1, - WM5100_ACCDET_RATE_MASK, - 7 << WM5100_ACCDET_RATE_SHIFT); -} - -static void wm5100_micd_irq(struct wm5100_priv *wm5100) -{ - unsigned int val; - int ret; - - ret = regmap_read(wm5100->regmap, WM5100_MIC_DETECT_3, &val); - if (ret != 0) { - dev_err(wm5100->dev, "Failed to read micropone status: %d\n", - ret); - return; - } - - dev_dbg(wm5100->dev, "Microphone event: %x\n", val); - - if (!(val & WM5100_ACCDET_VALID)) { - dev_warn(wm5100->dev, "Microphone detection state invalid\n"); - return; - } - - /* No accessory, reset everything and report removal */ - if (!(val & WM5100_ACCDET_STS)) { - dev_dbg(wm5100->dev, "Jack removal detected\n"); - wm5100->jack_mic = false; - wm5100->jack_detecting = true; - wm5100->jack_flips = 0; - snd_soc_jack_report(wm5100->jack, 0, - SND_JACK_LINEOUT | SND_JACK_HEADSET | - SND_JACK_BTN_0); - - regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1, - WM5100_ACCDET_RATE_MASK, - WM5100_ACCDET_RATE_MASK); - return; - } - - /* If the measurement is very high we've got a microphone, - * either we just detected one or if we already reported then - * we've got a button release event. - */ - if (val & 0x400) { - if (wm5100->jack_detecting) { - dev_dbg(wm5100->dev, "Microphone detected\n"); - wm5100->jack_mic = true; - wm5100->jack_detecting = false; - snd_soc_jack_report(wm5100->jack, - SND_JACK_HEADSET, - SND_JACK_HEADSET | SND_JACK_BTN_0); - - /* Increase poll rate to give better responsiveness - * for buttons */ - regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1, - WM5100_ACCDET_RATE_MASK, - 5 << WM5100_ACCDET_RATE_SHIFT); - } else { - dev_dbg(wm5100->dev, "Mic button up\n"); - snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0); - } - - return; - } - - /* If we detected a lower impedence during initial startup - * then we probably have the wrong polarity, flip it. Don't - * do this for the lowest impedences to speed up detection of - * plain headphones and give up if neither polarity looks - * sensible. - */ - if (wm5100->jack_detecting && (val & 0x3f8)) { - wm5100->jack_flips++; - - if (wm5100->jack_flips > 1) - wm5100_report_headphone(wm5100); - else - wm5100_set_detect_mode(wm5100, !wm5100->jack_mode); - - return; - } - - /* Don't distinguish between buttons, just report any low - * impedence as BTN_0. - */ - if (val & 0x3fc) { - if (wm5100->jack_mic) { - dev_dbg(wm5100->dev, "Mic button detected\n"); - snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0, - SND_JACK_BTN_0); - } else if (wm5100->jack_detecting) { - wm5100_report_headphone(wm5100); - } - } -} - -int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) -{ - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - - if (jack) { - wm5100->jack = jack; - wm5100->jack_detecting = true; - wm5100->jack_flips = 0; - - wm5100_set_detect_mode(wm5100, 0); - - /* Slowest detection rate, gives debounce for initial - * detection */ - snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, - WM5100_ACCDET_BIAS_STARTTIME_MASK | - WM5100_ACCDET_RATE_MASK, - (7 << WM5100_ACCDET_BIAS_STARTTIME_SHIFT) | - WM5100_ACCDET_RATE_MASK); - - /* We need the charge pump to power MICBIAS */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_sync(&codec->dapm); - - /* We start off just enabling microphone detection - even a - * plain headphone will trigger detection. - */ - snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, - WM5100_ACCDET_ENA, WM5100_ACCDET_ENA); - - snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK, - WM5100_IM_ACCDET_EINT, 0); - } else { - snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK, - WM5100_IM_HPDET_EINT | - WM5100_IM_ACCDET_EINT, - WM5100_IM_HPDET_EINT | - WM5100_IM_ACCDET_EINT); - snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, - WM5100_ACCDET_ENA, 0); - wm5100->jack = NULL; - } - - return 0; -} - -static irqreturn_t wm5100_irq(int irq, void *data) -{ - struct wm5100_priv *wm5100 = data; - irqreturn_t status = IRQ_NONE; - unsigned int irq_val, mask_val; - int ret; - - ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, &irq_val); - if (ret < 0) { - dev_err(wm5100->dev, "Failed to read IRQ status 3: %d\n", - ret); - irq_val = 0; - } - - ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3_MASK, - &mask_val); - if (ret < 0) { - dev_err(wm5100->dev, "Failed to read IRQ mask 3: %d\n", - ret); - mask_val = 0xffff; - } - - irq_val &= ~mask_val; - - regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, irq_val); - - if (irq_val) - status = IRQ_HANDLED; - - wm5100_log_status3(wm5100, irq_val); - - if (irq_val & WM5100_FLL1_LOCK_EINT) { - dev_dbg(wm5100->dev, "FLL1 locked\n"); - complete(&wm5100->fll[0].lock); - } - if (irq_val & WM5100_FLL2_LOCK_EINT) { - dev_dbg(wm5100->dev, "FLL2 locked\n"); - complete(&wm5100->fll[1].lock); - } - - if (irq_val & WM5100_ACCDET_EINT) - wm5100_micd_irq(wm5100); - - ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, &irq_val); - if (ret < 0) { - dev_err(wm5100->dev, "Failed to read IRQ status 4: %d\n", - ret); - irq_val = 0; - } - - ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4_MASK, - &mask_val); - if (ret < 0) { - dev_err(wm5100->dev, "Failed to read IRQ mask 4: %d\n", - ret); - mask_val = 0xffff; - } - - irq_val &= ~mask_val; - - if (irq_val) - status = IRQ_HANDLED; - - regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, irq_val); - - wm5100_log_status4(wm5100, irq_val); - - return status; -} - -static irqreturn_t wm5100_edge_irq(int irq, void *data) -{ - irqreturn_t ret = IRQ_NONE; - irqreturn_t val; - - do { - val = wm5100_irq(irq, data); - if (val != IRQ_NONE) - ret = val; - } while (val != IRQ_NONE); - - return ret; -} - -#ifdef CONFIG_GPIOLIB -static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip) -{ - return container_of(chip, struct wm5100_priv, gpio_chip); -} - -static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); - - regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, - WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT); -} - -static int wm5100_gpio_direction_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); - int val, ret; - - val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT); - - ret = regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, - WM5100_GP1_FN_MASK | WM5100_GP1_DIR | - WM5100_GP1_LVL, val); - if (ret < 0) - return ret; - else - return 0; -} - -static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); - unsigned int reg; - int ret; - - ret = regmap_read(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, ®); - if (ret < 0) - return ret; - - return (reg & WM5100_GP1_LVL) != 0; -} - -static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct wm5100_priv *wm5100 = gpio_to_wm5100(chip); - - return regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, - WM5100_GP1_FN_MASK | WM5100_GP1_DIR, - (1 << WM5100_GP1_FN_SHIFT) | - (1 << WM5100_GP1_DIR_SHIFT)); -} - -static struct gpio_chip wm5100_template_chip = { - .label = "wm5100", - .owner = THIS_MODULE, - .direction_output = wm5100_gpio_direction_out, - .set = wm5100_gpio_set, - .direction_input = wm5100_gpio_direction_in, - .get = wm5100_gpio_get, - .can_sleep = 1, -}; - -static void wm5100_init_gpio(struct i2c_client *i2c) -{ - struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); - int ret; - - wm5100->gpio_chip = wm5100_template_chip; - wm5100->gpio_chip.ngpio = 6; - wm5100->gpio_chip.dev = &i2c->dev; - - if (wm5100->pdata.gpio_base) - wm5100->gpio_chip.base = wm5100->pdata.gpio_base; - else - wm5100->gpio_chip.base = -1; - - ret = gpiochip_add(&wm5100->gpio_chip); - if (ret != 0) - dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret); -} - -static void wm5100_free_gpio(struct i2c_client *i2c) -{ - struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); - int ret; - - ret = gpiochip_remove(&wm5100->gpio_chip); - if (ret != 0) - dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret); -} -#else -static void wm5100_init_gpio(struct i2c_client *i2c) -{ -} - -static void wm5100_free_gpio(struct i2c_client *i2c) -{ -} -#endif - -static int wm5100_probe(struct snd_soc_codec *codec) -{ - struct i2c_client *i2c = to_i2c_client(codec->dev); - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - int ret, i; - - wm5100->codec = codec; - codec->control_data = wm5100->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) - snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, - WM5100_OUT_VU); - - /* Don't debounce interrupts to support use of SYSCLK only */ - snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_1, 0); - snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_2, 0); - - /* TODO: check if we're symmetric */ - - if (i2c->irq) - snd_soc_dapm_new_controls(&codec->dapm, - wm5100_dapm_widgets_noirq, - ARRAY_SIZE(wm5100_dapm_widgets_noirq)); - - if (wm5100->pdata.hp_pol) { - ret = gpio_request_one(wm5100->pdata.hp_pol, - GPIOF_OUT_INIT_HIGH, "WM5100 HP_POL"); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to request HP_POL %d: %d\n", - wm5100->pdata.hp_pol, ret); - goto err_gpio; - } - } - - return 0; - -err_gpio: - - return ret; -} - -static int wm5100_remove(struct snd_soc_codec *codec) -{ - struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); - - if (wm5100->pdata.hp_pol) { - gpio_free(wm5100->pdata.hp_pol); - } - - return 0; -} - -static int wm5100_soc_volatile(struct snd_soc_codec *codec, - unsigned int reg) -{ - return true; -} - - -static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { - .probe = wm5100_probe, - .remove = wm5100_remove, - - .set_sysclk = wm5100_set_sysclk, - .set_pll = wm5100_set_fll, - .idle_bias_off = 1, - .reg_cache_size = WM5100_MAX_REGISTER, - .volatile_register = wm5100_soc_volatile, - - .seq_notifier = wm5100_seq_notifier, - .controls = wm5100_snd_controls, - .num_controls = ARRAY_SIZE(wm5100_snd_controls), - .dapm_widgets = wm5100_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets), - .dapm_routes = wm5100_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes), -}; - -static const struct regmap_config wm5100_regmap = { - .reg_bits = 16, - .val_bits = 16, - - .max_register = WM5100_MAX_REGISTER, - .reg_defaults = wm5100_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm5100_reg_defaults), - .volatile_reg = wm5100_volatile_register, - .readable_reg = wm5100_readable_register, - .cache_type = REGCACHE_RBTREE, -}; - -static const unsigned int wm5100_mic_ctrl_reg[] = { - WM5100_IN1L_CONTROL, - WM5100_IN2L_CONTROL, - WM5100_IN3L_CONTROL, - WM5100_IN4L_CONTROL, -}; - -static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev); - struct wm5100_priv *wm5100; - unsigned int reg; - int ret, i, irq_flags; - - wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv), - GFP_KERNEL); - if (wm5100 == NULL) - return -ENOMEM; - - wm5100->dev = &i2c->dev; - - wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap); - if (IS_ERR(wm5100->regmap)) { - ret = PTR_ERR(wm5100->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - goto err; - } - - for (i = 0; i < ARRAY_SIZE(wm5100->fll); i++) - init_completion(&wm5100->fll[i].lock); - - if (pdata) - wm5100->pdata = *pdata; - - i2c_set_clientdata(i2c, wm5100); - - for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++) - wm5100->core_supplies[i].supply = wm5100_core_supply_names[i]; - - ret = devm_regulator_bulk_get(&i2c->dev, - ARRAY_SIZE(wm5100->core_supplies), - wm5100->core_supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to request core supplies: %d\n", - ret); - goto err_regmap; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), - wm5100->core_supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to enable core supplies: %d\n", - ret); - goto err_regmap; - } - - if (wm5100->pdata.ldo_ena) { - ret = gpio_request_one(wm5100->pdata.ldo_ena, - GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA"); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", - wm5100->pdata.ldo_ena, ret); - goto err_enable; - } - msleep(2); - } - - if (wm5100->pdata.reset) { - ret = gpio_request_one(wm5100->pdata.reset, - GPIOF_OUT_INIT_HIGH, "WM5100 /RESET"); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", - wm5100->pdata.reset, ret); - goto err_ldo; - } - } - - ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, ®); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); - goto err_reset; - } - switch (reg) { - case 0x8997: - case 0x5100: - break; - - default: - dev_err(&i2c->dev, "Device is not a WM5100, ID is %x\n", reg); - ret = -EINVAL; - goto err_reset; - } - - ret = regmap_read(wm5100->regmap, WM5100_DEVICE_REVISION, ®); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to read revision register\n"); - goto err_reset; - } - wm5100->rev = reg & WM5100_DEVICE_REVISION_MASK; - - dev_info(&i2c->dev, "revision %c\n", wm5100->rev + 'A'); - - ret = wm5100_reset(wm5100); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to issue reset\n"); - goto err_reset; - } - - switch (wm5100->rev) { - case 0: - ret = regmap_register_patch(wm5100->regmap, - wm5100_reva_patches, - ARRAY_SIZE(wm5100_reva_patches)); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register patches: %d\n", - ret); - goto err_reset; - } - break; - default: - break; - } - - - wm5100_init_gpio(i2c); - - for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) { - if (!wm5100->pdata.gpio_defaults[i]) - continue; - - regmap_write(wm5100->regmap, WM5100_GPIO_CTRL_1 + i, - wm5100->pdata.gpio_defaults[i]); - } - - for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) { - regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i], - WM5100_IN1_MODE_MASK | - WM5100_IN1_DMIC_SUP_MASK, - (wm5100->pdata.in_mode[i] << - WM5100_IN1_MODE_SHIFT) | - (wm5100->pdata.dmic_sup[i] << - WM5100_IN1_DMIC_SUP_SHIFT)); - } - - if (i2c->irq) { - if (wm5100->pdata.irq_flags) - irq_flags = wm5100->pdata.irq_flags; - else - irq_flags = IRQF_TRIGGER_LOW; - - irq_flags |= IRQF_ONESHOT; - - if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) - ret = request_threaded_irq(i2c->irq, NULL, - wm5100_edge_irq, irq_flags, - "wm5100", wm5100); - else - ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq, - irq_flags, "wm5100", - wm5100); - - if (ret != 0) { - dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", - i2c->irq, ret); - } else { - /* Enable default interrupts */ - regmap_update_bits(wm5100->regmap, - WM5100_INTERRUPT_STATUS_3_MASK, - WM5100_IM_SPK_SHUTDOWN_WARN_EINT | - WM5100_IM_SPK_SHUTDOWN_EINT | - WM5100_IM_ASRC2_LOCK_EINT | - WM5100_IM_ASRC1_LOCK_EINT | - WM5100_IM_FLL2_LOCK_EINT | - WM5100_IM_FLL1_LOCK_EINT | - WM5100_CLKGEN_ERR_EINT | - WM5100_CLKGEN_ERR_ASYNC_EINT, 0); - - regmap_update_bits(wm5100->regmap, - WM5100_INTERRUPT_STATUS_4_MASK, - WM5100_AIF3_ERR_EINT | - WM5100_AIF2_ERR_EINT | - WM5100_AIF1_ERR_EINT | - WM5100_CTRLIF_ERR_EINT | - WM5100_ISRC2_UNDERCLOCKED_EINT | - WM5100_ISRC1_UNDERCLOCKED_EINT | - WM5100_FX_UNDERCLOCKED_EINT | - WM5100_AIF3_UNDERCLOCKED_EINT | - WM5100_AIF2_UNDERCLOCKED_EINT | - WM5100_AIF1_UNDERCLOCKED_EINT | - WM5100_ASRC_UNDERCLOCKED_EINT | - WM5100_DAC_UNDERCLOCKED_EINT | - WM5100_ADC_UNDERCLOCKED_EINT | - WM5100_MIXER_UNDERCLOCKED_EINT, 0); - } - } - - pm_runtime_set_active(&i2c->dev); - pm_runtime_enable(&i2c->dev); - pm_request_idle(&i2c->dev); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm5100, wm5100_dai, - ARRAY_SIZE(wm5100_dai)); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret); - goto err_reset; - } - - return ret; - -err_reset: - if (i2c->irq) - free_irq(i2c->irq, wm5100); - wm5100_free_gpio(i2c); - if (wm5100->pdata.reset) { - gpio_set_value_cansleep(wm5100->pdata.reset, 0); - gpio_free(wm5100->pdata.reset); - } -err_ldo: - if (wm5100->pdata.ldo_ena) { - gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); - gpio_free(wm5100->pdata.ldo_ena); - } -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), - wm5100->core_supplies); -err_regmap: - regmap_exit(wm5100->regmap); -err: - return ret; -} - -static __devexit int wm5100_i2c_remove(struct i2c_client *i2c) -{ - struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); - - snd_soc_unregister_codec(&i2c->dev); - if (i2c->irq) - free_irq(i2c->irq, wm5100); - wm5100_free_gpio(i2c); - if (wm5100->pdata.reset) { - gpio_set_value_cansleep(wm5100->pdata.reset, 0); - gpio_free(wm5100->pdata.reset); - } - if (wm5100->pdata.ldo_ena) { - gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); - gpio_free(wm5100->pdata.ldo_ena); - } - regmap_exit(wm5100->regmap); - - return 0; -} - -#ifdef CONFIG_PM_RUNTIME -static int wm5100_runtime_suspend(struct device *dev) -{ - struct wm5100_priv *wm5100 = dev_get_drvdata(dev); - - regcache_cache_only(wm5100->regmap, true); - regcache_mark_dirty(wm5100->regmap); - if (wm5100->pdata.ldo_ena) - gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); - regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), - wm5100->core_supplies); - - return 0; -} - -static int wm5100_runtime_resume(struct device *dev) -{ - struct wm5100_priv *wm5100 = dev_get_drvdata(dev); - int ret; - - ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), - wm5100->core_supplies); - if (ret != 0) { - dev_err(dev, "Failed to enable supplies: %d\n", - ret); - return ret; - } - - if (wm5100->pdata.ldo_ena) { - gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1); - msleep(2); - } - - regcache_cache_only(wm5100->regmap, false); - regcache_sync(wm5100->regmap); - - return 0; -} -#endif - -static struct dev_pm_ops wm5100_pm = { - SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume, - NULL) -}; - -static const struct i2c_device_id wm5100_i2c_id[] = { - { "wm5100", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id); - -static struct i2c_driver wm5100_i2c_driver = { - .driver = { - .name = "wm5100", - .owner = THIS_MODULE, - .pm = &wm5100_pm, - }, - .probe = wm5100_i2c_probe, - .remove = __devexit_p(wm5100_i2c_remove), - .id_table = wm5100_i2c_id, -}; - -static int __init wm5100_modinit(void) -{ - return i2c_add_driver(&wm5100_i2c_driver); -} -module_init(wm5100_modinit); - -static void __exit wm5100_exit(void) -{ - i2c_del_driver(&wm5100_i2c_driver); -} -module_exit(wm5100_exit); - -MODULE_DESCRIPTION("ASoC WM5100 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm5100.h b/ANDROID_3.4.5/sound/soc/codecs/wm5100.h deleted file mode 100644 index 25cb6016..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm5100.h +++ /dev/null @@ -1,5156 +0,0 @@ -/* - * wm5100.h -- WM5100 ALSA SoC Audio driver - * - * Copyright 2011 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef WM5100_ASOC_H -#define WM5100_ASOC_H - -#include -#include - -int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack); - -#define WM5100_CLK_AIF1 1 -#define WM5100_CLK_AIF2 2 -#define WM5100_CLK_AIF3 3 -#define WM5100_CLK_SYSCLK 4 -#define WM5100_CLK_ASYNCCLK 5 -#define WM5100_CLK_32KHZ 6 -#define WM5100_CLK_OPCLK 7 - -#define WM5100_CLKSRC_MCLK1 0 -#define WM5100_CLKSRC_MCLK2 1 -#define WM5100_CLKSRC_SYSCLK 2 -#define WM5100_CLKSRC_FLL1 4 -#define WM5100_CLKSRC_FLL2 5 -#define WM5100_CLKSRC_AIF1BCLK 8 -#define WM5100_CLKSRC_AIF2BCLK 9 -#define WM5100_CLKSRC_AIF3BCLK 10 -#define WM5100_CLKSRC_ASYNCCLK 0x100 - -#define WM5100_FLL1 1 -#define WM5100_FLL2 2 - -#define WM5100_FLL_SRC_MCLK1 0x0 -#define WM5100_FLL_SRC_MCLK2 0x1 -#define WM5100_FLL_SRC_FLL1 0x4 -#define WM5100_FLL_SRC_FLL2 0x5 -#define WM5100_FLL_SRC_AIF1BCLK 0x8 -#define WM5100_FLL_SRC_AIF2BCLK 0x9 -#define WM5100_FLL_SRC_AIF3BCLK 0xa - -/* - * Register values. - */ -#define WM5100_SOFTWARE_RESET 0x00 -#define WM5100_DEVICE_REVISION 0x01 -#define WM5100_CTRL_IF_1 0x10 -#define WM5100_TONE_GENERATOR_1 0x20 -#define WM5100_PWM_DRIVE_1 0x30 -#define WM5100_PWM_DRIVE_2 0x31 -#define WM5100_PWM_DRIVE_3 0x32 -#define WM5100_CLOCKING_1 0x100 -#define WM5100_CLOCKING_3 0x101 -#define WM5100_CLOCKING_4 0x102 -#define WM5100_CLOCKING_5 0x103 -#define WM5100_CLOCKING_6 0x104 -#define WM5100_CLOCKING_7 0x107 -#define WM5100_CLOCKING_8 0x108 -#define WM5100_ASRC_ENABLE 0x120 -#define WM5100_ASRC_STATUS 0x121 -#define WM5100_ASRC_RATE1 0x122 -#define WM5100_ISRC_1_CTRL_1 0x141 -#define WM5100_ISRC_1_CTRL_2 0x142 -#define WM5100_ISRC_2_CTRL1 0x143 -#define WM5100_ISRC_2_CTRL_2 0x144 -#define WM5100_FLL1_CONTROL_1 0x182 -#define WM5100_FLL1_CONTROL_2 0x183 -#define WM5100_FLL1_CONTROL_3 0x184 -#define WM5100_FLL1_CONTROL_5 0x186 -#define WM5100_FLL1_CONTROL_6 0x187 -#define WM5100_FLL1_EFS_1 0x188 -#define WM5100_FLL2_CONTROL_1 0x1A2 -#define WM5100_FLL2_CONTROL_2 0x1A3 -#define WM5100_FLL2_CONTROL_3 0x1A4 -#define WM5100_FLL2_CONTROL_5 0x1A6 -#define WM5100_FLL2_CONTROL_6 0x1A7 -#define WM5100_FLL2_EFS_1 0x1A8 -#define WM5100_MIC_CHARGE_PUMP_1 0x200 -#define WM5100_MIC_CHARGE_PUMP_2 0x201 -#define WM5100_HP_CHARGE_PUMP_1 0x202 -#define WM5100_LDO1_CONTROL 0x211 -#define WM5100_MIC_BIAS_CTRL_1 0x215 -#define WM5100_MIC_BIAS_CTRL_2 0x216 -#define WM5100_MIC_BIAS_CTRL_3 0x217 -#define WM5100_ACCESSORY_DETECT_MODE_1 0x280 -#define WM5100_HEADPHONE_DETECT_1 0x288 -#define WM5100_HEADPHONE_DETECT_2 0x289 -#define WM5100_MIC_DETECT_1 0x290 -#define WM5100_MIC_DETECT_2 0x291 -#define WM5100_MIC_DETECT_3 0x292 -#define WM5100_MISC_CONTROL 0x2BB -#define WM5100_INPUT_ENABLES 0x301 -#define WM5100_INPUT_ENABLES_STATUS 0x302 -#define WM5100_IN1L_CONTROL 0x310 -#define WM5100_IN1R_CONTROL 0x311 -#define WM5100_IN2L_CONTROL 0x312 -#define WM5100_IN2R_CONTROL 0x313 -#define WM5100_IN3L_CONTROL 0x314 -#define WM5100_IN3R_CONTROL 0x315 -#define WM5100_IN4L_CONTROL 0x316 -#define WM5100_IN4R_CONTROL 0x317 -#define WM5100_RXANC_SRC 0x318 -#define WM5100_INPUT_VOLUME_RAMP 0x319 -#define WM5100_ADC_DIGITAL_VOLUME_1L 0x320 -#define WM5100_ADC_DIGITAL_VOLUME_1R 0x321 -#define WM5100_ADC_DIGITAL_VOLUME_2L 0x322 -#define WM5100_ADC_DIGITAL_VOLUME_2R 0x323 -#define WM5100_ADC_DIGITAL_VOLUME_3L 0x324 -#define WM5100_ADC_DIGITAL_VOLUME_3R 0x325 -#define WM5100_ADC_DIGITAL_VOLUME_4L 0x326 -#define WM5100_ADC_DIGITAL_VOLUME_4R 0x327 -#define WM5100_OUTPUT_ENABLES_2 0x401 -#define WM5100_OUTPUT_STATUS_1 0x402 -#define WM5100_OUTPUT_STATUS_2 0x403 -#define WM5100_CHANNEL_ENABLES_1 0x408 -#define WM5100_OUT_VOLUME_1L 0x410 -#define WM5100_OUT_VOLUME_1R 0x411 -#define WM5100_DAC_VOLUME_LIMIT_1L 0x412 -#define WM5100_DAC_VOLUME_LIMIT_1R 0x413 -#define WM5100_OUT_VOLUME_2L 0x414 -#define WM5100_OUT_VOLUME_2R 0x415 -#define WM5100_DAC_VOLUME_LIMIT_2L 0x416 -#define WM5100_DAC_VOLUME_LIMIT_2R 0x417 -#define WM5100_OUT_VOLUME_3L 0x418 -#define WM5100_OUT_VOLUME_3R 0x419 -#define WM5100_DAC_VOLUME_LIMIT_3L 0x41A -#define WM5100_DAC_VOLUME_LIMIT_3R 0x41B -#define WM5100_OUT_VOLUME_4L 0x41C -#define WM5100_OUT_VOLUME_4R 0x41D -#define WM5100_DAC_VOLUME_LIMIT_5L 0x41E -#define WM5100_DAC_VOLUME_LIMIT_5R 0x41F -#define WM5100_DAC_VOLUME_LIMIT_6L 0x420 -#define WM5100_DAC_VOLUME_LIMIT_6R 0x421 -#define WM5100_DAC_AEC_CONTROL_1 0x440 -#define WM5100_OUTPUT_VOLUME_RAMP 0x441 -#define WM5100_DAC_DIGITAL_VOLUME_1L 0x480 -#define WM5100_DAC_DIGITAL_VOLUME_1R 0x481 -#define WM5100_DAC_DIGITAL_VOLUME_2L 0x482 -#define WM5100_DAC_DIGITAL_VOLUME_2R 0x483 -#define WM5100_DAC_DIGITAL_VOLUME_3L 0x484 -#define WM5100_DAC_DIGITAL_VOLUME_3R 0x485 -#define WM5100_DAC_DIGITAL_VOLUME_4L 0x486 -#define WM5100_DAC_DIGITAL_VOLUME_4R 0x487 -#define WM5100_DAC_DIGITAL_VOLUME_5L 0x488 -#define WM5100_DAC_DIGITAL_VOLUME_5R 0x489 -#define WM5100_DAC_DIGITAL_VOLUME_6L 0x48A -#define WM5100_DAC_DIGITAL_VOLUME_6R 0x48B -#define WM5100_PDM_SPK1_CTRL_1 0x4C0 -#define WM5100_PDM_SPK1_CTRL_2 0x4C1 -#define WM5100_PDM_SPK2_CTRL_1 0x4C2 -#define WM5100_PDM_SPK2_CTRL_2 0x4C3 -#define WM5100_AUDIO_IF_1_1 0x500 -#define WM5100_AUDIO_IF_1_2 0x501 -#define WM5100_AUDIO_IF_1_3 0x502 -#define WM5100_AUDIO_IF_1_4 0x503 -#define WM5100_AUDIO_IF_1_5 0x504 -#define WM5100_AUDIO_IF_1_6 0x505 -#define WM5100_AUDIO_IF_1_7 0x506 -#define WM5100_AUDIO_IF_1_8 0x507 -#define WM5100_AUDIO_IF_1_9 0x508 -#define WM5100_AUDIO_IF_1_10 0x509 -#define WM5100_AUDIO_IF_1_11 0x50A -#define WM5100_AUDIO_IF_1_12 0x50B -#define WM5100_AUDIO_IF_1_13 0x50C -#define WM5100_AUDIO_IF_1_14 0x50D -#define WM5100_AUDIO_IF_1_15 0x50E -#define WM5100_AUDIO_IF_1_16 0x50F -#define WM5100_AUDIO_IF_1_17 0x510 -#define WM5100_AUDIO_IF_1_18 0x511 -#define WM5100_AUDIO_IF_1_19 0x512 -#define WM5100_AUDIO_IF_1_20 0x513 -#define WM5100_AUDIO_IF_1_21 0x514 -#define WM5100_AUDIO_IF_1_22 0x515 -#define WM5100_AUDIO_IF_1_23 0x516 -#define WM5100_AUDIO_IF_1_24 0x517 -#define WM5100_AUDIO_IF_1_25 0x518 -#define WM5100_AUDIO_IF_1_26 0x519 -#define WM5100_AUDIO_IF_1_27 0x51A -#define WM5100_AUDIO_IF_2_1 0x540 -#define WM5100_AUDIO_IF_2_2 0x541 -#define WM5100_AUDIO_IF_2_3 0x542 -#define WM5100_AUDIO_IF_2_4 0x543 -#define WM5100_AUDIO_IF_2_5 0x544 -#define WM5100_AUDIO_IF_2_6 0x545 -#define WM5100_AUDIO_IF_2_7 0x546 -#define WM5100_AUDIO_IF_2_8 0x547 -#define WM5100_AUDIO_IF_2_9 0x548 -#define WM5100_AUDIO_IF_2_10 0x549 -#define WM5100_AUDIO_IF_2_11 0x54A -#define WM5100_AUDIO_IF_2_18 0x551 -#define WM5100_AUDIO_IF_2_19 0x552 -#define WM5100_AUDIO_IF_2_26 0x559 -#define WM5100_AUDIO_IF_2_27 0x55A -#define WM5100_AUDIO_IF_3_1 0x580 -#define WM5100_AUDIO_IF_3_2 0x581 -#define WM5100_AUDIO_IF_3_3 0x582 -#define WM5100_AUDIO_IF_3_4 0x583 -#define WM5100_AUDIO_IF_3_5 0x584 -#define WM5100_AUDIO_IF_3_6 0x585 -#define WM5100_AUDIO_IF_3_7 0x586 -#define WM5100_AUDIO_IF_3_8 0x587 -#define WM5100_AUDIO_IF_3_9 0x588 -#define WM5100_AUDIO_IF_3_10 0x589 -#define WM5100_AUDIO_IF_3_11 0x58A -#define WM5100_AUDIO_IF_3_18 0x591 -#define WM5100_AUDIO_IF_3_19 0x592 -#define WM5100_AUDIO_IF_3_26 0x599 -#define WM5100_AUDIO_IF_3_27 0x59A -#define WM5100_PWM1MIX_INPUT_1_SOURCE 0x640 -#define WM5100_PWM1MIX_INPUT_1_VOLUME 0x641 -#define WM5100_PWM1MIX_INPUT_2_SOURCE 0x642 -#define WM5100_PWM1MIX_INPUT_2_VOLUME 0x643 -#define WM5100_PWM1MIX_INPUT_3_SOURCE 0x644 -#define WM5100_PWM1MIX_INPUT_3_VOLUME 0x645 -#define WM5100_PWM1MIX_INPUT_4_SOURCE 0x646 -#define WM5100_PWM1MIX_INPUT_4_VOLUME 0x647 -#define WM5100_PWM2MIX_INPUT_1_SOURCE 0x648 -#define WM5100_PWM2MIX_INPUT_1_VOLUME 0x649 -#define WM5100_PWM2MIX_INPUT_2_SOURCE 0x64A -#define WM5100_PWM2MIX_INPUT_2_VOLUME 0x64B -#define WM5100_PWM2MIX_INPUT_3_SOURCE 0x64C -#define WM5100_PWM2MIX_INPUT_3_VOLUME 0x64D -#define WM5100_PWM2MIX_INPUT_4_SOURCE 0x64E -#define WM5100_PWM2MIX_INPUT_4_VOLUME 0x64F -#define WM5100_OUT1LMIX_INPUT_1_SOURCE 0x680 -#define WM5100_OUT1LMIX_INPUT_1_VOLUME 0x681 -#define WM5100_OUT1LMIX_INPUT_2_SOURCE 0x682 -#define WM5100_OUT1LMIX_INPUT_2_VOLUME 0x683 -#define WM5100_OUT1LMIX_INPUT_3_SOURCE 0x684 -#define WM5100_OUT1LMIX_INPUT_3_VOLUME 0x685 -#define WM5100_OUT1LMIX_INPUT_4_SOURCE 0x686 -#define WM5100_OUT1LMIX_INPUT_4_VOLUME 0x687 -#define WM5100_OUT1RMIX_INPUT_1_SOURCE 0x688 -#define WM5100_OUT1RMIX_INPUT_1_VOLUME 0x689 -#define WM5100_OUT1RMIX_INPUT_2_SOURCE 0x68A -#define WM5100_OUT1RMIX_INPUT_2_VOLUME 0x68B -#define WM5100_OUT1RMIX_INPUT_3_SOURCE 0x68C -#define WM5100_OUT1RMIX_INPUT_3_VOLUME 0x68D -#define WM5100_OUT1RMIX_INPUT_4_SOURCE 0x68E -#define WM5100_OUT1RMIX_INPUT_4_VOLUME 0x68F -#define WM5100_OUT2LMIX_INPUT_1_SOURCE 0x690 -#define WM5100_OUT2LMIX_INPUT_1_VOLUME 0x691 -#define WM5100_OUT2LMIX_INPUT_2_SOURCE 0x692 -#define WM5100_OUT2LMIX_INPUT_2_VOLUME 0x693 -#define WM5100_OUT2LMIX_INPUT_3_SOURCE 0x694 -#define WM5100_OUT2LMIX_INPUT_3_VOLUME 0x695 -#define WM5100_OUT2LMIX_INPUT_4_SOURCE 0x696 -#define WM5100_OUT2LMIX_INPUT_4_VOLUME 0x697 -#define WM5100_OUT2RMIX_INPUT_1_SOURCE 0x698 -#define WM5100_OUT2RMIX_INPUT_1_VOLUME 0x699 -#define WM5100_OUT2RMIX_INPUT_2_SOURCE 0x69A -#define WM5100_OUT2RMIX_INPUT_2_VOLUME 0x69B -#define WM5100_OUT2RMIX_INPUT_3_SOURCE 0x69C -#define WM5100_OUT2RMIX_INPUT_3_VOLUME 0x69D -#define WM5100_OUT2RMIX_INPUT_4_SOURCE 0x69E -#define WM5100_OUT2RMIX_INPUT_4_VOLUME 0x69F -#define WM5100_OUT3LMIX_INPUT_1_SOURCE 0x6A0 -#define WM5100_OUT3LMIX_INPUT_1_VOLUME 0x6A1 -#define WM5100_OUT3LMIX_INPUT_2_SOURCE 0x6A2 -#define WM5100_OUT3LMIX_INPUT_2_VOLUME 0x6A3 -#define WM5100_OUT3LMIX_INPUT_3_SOURCE 0x6A4 -#define WM5100_OUT3LMIX_INPUT_3_VOLUME 0x6A5 -#define WM5100_OUT3LMIX_INPUT_4_SOURCE 0x6A6 -#define WM5100_OUT3LMIX_INPUT_4_VOLUME 0x6A7 -#define WM5100_OUT3RMIX_INPUT_1_SOURCE 0x6A8 -#define WM5100_OUT3RMIX_INPUT_1_VOLUME 0x6A9 -#define WM5100_OUT3RMIX_INPUT_2_SOURCE 0x6AA -#define WM5100_OUT3RMIX_INPUT_2_VOLUME 0x6AB -#define WM5100_OUT3RMIX_INPUT_3_SOURCE 0x6AC -#define WM5100_OUT3RMIX_INPUT_3_VOLUME 0x6AD -#define WM5100_OUT3RMIX_INPUT_4_SOURCE 0x6AE -#define WM5100_OUT3RMIX_INPUT_4_VOLUME 0x6AF -#define WM5100_OUT4LMIX_INPUT_1_SOURCE 0x6B0 -#define WM5100_OUT4LMIX_INPUT_1_VOLUME 0x6B1 -#define WM5100_OUT4LMIX_INPUT_2_SOURCE 0x6B2 -#define WM5100_OUT4LMIX_INPUT_2_VOLUME 0x6B3 -#define WM5100_OUT4LMIX_INPUT_3_SOURCE 0x6B4 -#define WM5100_OUT4LMIX_INPUT_3_VOLUME 0x6B5 -#define WM5100_OUT4LMIX_INPUT_4_SOURCE 0x6B6 -#define WM5100_OUT4LMIX_INPUT_4_VOLUME 0x6B7 -#define WM5100_OUT4RMIX_INPUT_1_SOURCE 0x6B8 -#define WM5100_OUT4RMIX_INPUT_1_VOLUME 0x6B9 -#define WM5100_OUT4RMIX_INPUT_2_SOURCE 0x6BA -#define WM5100_OUT4RMIX_INPUT_2_VOLUME 0x6BB -#define WM5100_OUT4RMIX_INPUT_3_SOURCE 0x6BC -#define WM5100_OUT4RMIX_INPUT_3_VOLUME 0x6BD -#define WM5100_OUT4RMIX_INPUT_4_SOURCE 0x6BE -#define WM5100_OUT4RMIX_INPUT_4_VOLUME 0x6BF -#define WM5100_OUT5LMIX_INPUT_1_SOURCE 0x6C0 -#define WM5100_OUT5LMIX_INPUT_1_VOLUME 0x6C1 -#define WM5100_OUT5LMIX_INPUT_2_SOURCE 0x6C2 -#define WM5100_OUT5LMIX_INPUT_2_VOLUME 0x6C3 -#define WM5100_OUT5LMIX_INPUT_3_SOURCE 0x6C4 -#define WM5100_OUT5LMIX_INPUT_3_VOLUME 0x6C5 -#define WM5100_OUT5LMIX_INPUT_4_SOURCE 0x6C6 -#define WM5100_OUT5LMIX_INPUT_4_VOLUME 0x6C7 -#define WM5100_OUT5RMIX_INPUT_1_SOURCE 0x6C8 -#define WM5100_OUT5RMIX_INPUT_1_VOLUME 0x6C9 -#define WM5100_OUT5RMIX_INPUT_2_SOURCE 0x6CA -#define WM5100_OUT5RMIX_INPUT_2_VOLUME 0x6CB -#define WM5100_OUT5RMIX_INPUT_3_SOURCE 0x6CC -#define WM5100_OUT5RMIX_INPUT_3_VOLUME 0x6CD -#define WM5100_OUT5RMIX_INPUT_4_SOURCE 0x6CE -#define WM5100_OUT5RMIX_INPUT_4_VOLUME 0x6CF -#define WM5100_OUT6LMIX_INPUT_1_SOURCE 0x6D0 -#define WM5100_OUT6LMIX_INPUT_1_VOLUME 0x6D1 -#define WM5100_OUT6LMIX_INPUT_2_SOURCE 0x6D2 -#define WM5100_OUT6LMIX_INPUT_2_VOLUME 0x6D3 -#define WM5100_OUT6LMIX_INPUT_3_SOURCE 0x6D4 -#define WM5100_OUT6LMIX_INPUT_3_VOLUME 0x6D5 -#define WM5100_OUT6LMIX_INPUT_4_SOURCE 0x6D6 -#define WM5100_OUT6LMIX_INPUT_4_VOLUME 0x6D7 -#define WM5100_OUT6RMIX_INPUT_1_SOURCE 0x6D8 -#define WM5100_OUT6RMIX_INPUT_1_VOLUME 0x6D9 -#define WM5100_OUT6RMIX_INPUT_2_SOURCE 0x6DA -#define WM5100_OUT6RMIX_INPUT_2_VOLUME 0x6DB -#define WM5100_OUT6RMIX_INPUT_3_SOURCE 0x6DC -#define WM5100_OUT6RMIX_INPUT_3_VOLUME 0x6DD -#define WM5100_OUT6RMIX_INPUT_4_SOURCE 0x6DE -#define WM5100_OUT6RMIX_INPUT_4_VOLUME 0x6DF -#define WM5100_AIF1TX1MIX_INPUT_1_SOURCE 0x700 -#define WM5100_AIF1TX1MIX_INPUT_1_VOLUME 0x701 -#define WM5100_AIF1TX1MIX_INPUT_2_SOURCE 0x702 -#define WM5100_AIF1TX1MIX_INPUT_2_VOLUME 0x703 -#define WM5100_AIF1TX1MIX_INPUT_3_SOURCE 0x704 -#define WM5100_AIF1TX1MIX_INPUT_3_VOLUME 0x705 -#define WM5100_AIF1TX1MIX_INPUT_4_SOURCE 0x706 -#define WM5100_AIF1TX1MIX_INPUT_4_VOLUME 0x707 -#define WM5100_AIF1TX2MIX_INPUT_1_SOURCE 0x708 -#define WM5100_AIF1TX2MIX_INPUT_1_VOLUME 0x709 -#define WM5100_AIF1TX2MIX_INPUT_2_SOURCE 0x70A -#define WM5100_AIF1TX2MIX_INPUT_2_VOLUME 0x70B -#define WM5100_AIF1TX2MIX_INPUT_3_SOURCE 0x70C -#define WM5100_AIF1TX2MIX_INPUT_3_VOLUME 0x70D -#define WM5100_AIF1TX2MIX_INPUT_4_SOURCE 0x70E -#define WM5100_AIF1TX2MIX_INPUT_4_VOLUME 0x70F -#define WM5100_AIF1TX3MIX_INPUT_1_SOURCE 0x710 -#define WM5100_AIF1TX3MIX_INPUT_1_VOLUME 0x711 -#define WM5100_AIF1TX3MIX_INPUT_2_SOURCE 0x712 -#define WM5100_AIF1TX3MIX_INPUT_2_VOLUME 0x713 -#define WM5100_AIF1TX3MIX_INPUT_3_SOURCE 0x714 -#define WM5100_AIF1TX3MIX_INPUT_3_VOLUME 0x715 -#define WM5100_AIF1TX3MIX_INPUT_4_SOURCE 0x716 -#define WM5100_AIF1TX3MIX_INPUT_4_VOLUME 0x717 -#define WM5100_AIF1TX4MIX_INPUT_1_SOURCE 0x718 -#define WM5100_AIF1TX4MIX_INPUT_1_VOLUME 0x719 -#define WM5100_AIF1TX4MIX_INPUT_2_SOURCE 0x71A -#define WM5100_AIF1TX4MIX_INPUT_2_VOLUME 0x71B -#define WM5100_AIF1TX4MIX_INPUT_3_SOURCE 0x71C -#define WM5100_AIF1TX4MIX_INPUT_3_VOLUME 0x71D -#define WM5100_AIF1TX4MIX_INPUT_4_SOURCE 0x71E -#define WM5100_AIF1TX4MIX_INPUT_4_VOLUME 0x71F -#define WM5100_AIF1TX5MIX_INPUT_1_SOURCE 0x720 -#define WM5100_AIF1TX5MIX_INPUT_1_VOLUME 0x721 -#define WM5100_AIF1TX5MIX_INPUT_2_SOURCE 0x722 -#define WM5100_AIF1TX5MIX_INPUT_2_VOLUME 0x723 -#define WM5100_AIF1TX5MIX_INPUT_3_SOURCE 0x724 -#define WM5100_AIF1TX5MIX_INPUT_3_VOLUME 0x725 -#define WM5100_AIF1TX5MIX_INPUT_4_SOURCE 0x726 -#define WM5100_AIF1TX5MIX_INPUT_4_VOLUME 0x727 -#define WM5100_AIF1TX6MIX_INPUT_1_SOURCE 0x728 -#define WM5100_AIF1TX6MIX_INPUT_1_VOLUME 0x729 -#define WM5100_AIF1TX6MIX_INPUT_2_SOURCE 0x72A -#define WM5100_AIF1TX6MIX_INPUT_2_VOLUME 0x72B -#define WM5100_AIF1TX6MIX_INPUT_3_SOURCE 0x72C -#define WM5100_AIF1TX6MIX_INPUT_3_VOLUME 0x72D -#define WM5100_AIF1TX6MIX_INPUT_4_SOURCE 0x72E -#define WM5100_AIF1TX6MIX_INPUT_4_VOLUME 0x72F -#define WM5100_AIF1TX7MIX_INPUT_1_SOURCE 0x730 -#define WM5100_AIF1TX7MIX_INPUT_1_VOLUME 0x731 -#define WM5100_AIF1TX7MIX_INPUT_2_SOURCE 0x732 -#define WM5100_AIF1TX7MIX_INPUT_2_VOLUME 0x733 -#define WM5100_AIF1TX7MIX_INPUT_3_SOURCE 0x734 -#define WM5100_AIF1TX7MIX_INPUT_3_VOLUME 0x735 -#define WM5100_AIF1TX7MIX_INPUT_4_SOURCE 0x736 -#define WM5100_AIF1TX7MIX_INPUT_4_VOLUME 0x737 -#define WM5100_AIF1TX8MIX_INPUT_1_SOURCE 0x738 -#define WM5100_AIF1TX8MIX_INPUT_1_VOLUME 0x739 -#define WM5100_AIF1TX8MIX_INPUT_2_SOURCE 0x73A -#define WM5100_AIF1TX8MIX_INPUT_2_VOLUME 0x73B -#define WM5100_AIF1TX8MIX_INPUT_3_SOURCE 0x73C -#define WM5100_AIF1TX8MIX_INPUT_3_VOLUME 0x73D -#define WM5100_AIF1TX8MIX_INPUT_4_SOURCE 0x73E -#define WM5100_AIF1TX8MIX_INPUT_4_VOLUME 0x73F -#define WM5100_AIF2TX1MIX_INPUT_1_SOURCE 0x740 -#define WM5100_AIF2TX1MIX_INPUT_1_VOLUME 0x741 -#define WM5100_AIF2TX1MIX_INPUT_2_SOURCE 0x742 -#define WM5100_AIF2TX1MIX_INPUT_2_VOLUME 0x743 -#define WM5100_AIF2TX1MIX_INPUT_3_SOURCE 0x744 -#define WM5100_AIF2TX1MIX_INPUT_3_VOLUME 0x745 -#define WM5100_AIF2TX1MIX_INPUT_4_SOURCE 0x746 -#define WM5100_AIF2TX1MIX_INPUT_4_VOLUME 0x747 -#define WM5100_AIF2TX2MIX_INPUT_1_SOURCE 0x748 -#define WM5100_AIF2TX2MIX_INPUT_1_VOLUME 0x749 -#define WM5100_AIF2TX2MIX_INPUT_2_SOURCE 0x74A -#define WM5100_AIF2TX2MIX_INPUT_2_VOLUME 0x74B -#define WM5100_AIF2TX2MIX_INPUT_3_SOURCE 0x74C -#define WM5100_AIF2TX2MIX_INPUT_3_VOLUME 0x74D -#define WM5100_AIF2TX2MIX_INPUT_4_SOURCE 0x74E -#define WM5100_AIF2TX2MIX_INPUT_4_VOLUME 0x74F -#define WM5100_AIF3TX1MIX_INPUT_1_SOURCE 0x780 -#define WM5100_AIF3TX1MIX_INPUT_1_VOLUME 0x781 -#define WM5100_AIF3TX1MIX_INPUT_2_SOURCE 0x782 -#define WM5100_AIF3TX1MIX_INPUT_2_VOLUME 0x783 -#define WM5100_AIF3TX1MIX_INPUT_3_SOURCE 0x784 -#define WM5100_AIF3TX1MIX_INPUT_3_VOLUME 0x785 -#define WM5100_AIF3TX1MIX_INPUT_4_SOURCE 0x786 -#define WM5100_AIF3TX1MIX_INPUT_4_VOLUME 0x787 -#define WM5100_AIF3TX2MIX_INPUT_1_SOURCE 0x788 -#define WM5100_AIF3TX2MIX_INPUT_1_VOLUME 0x789 -#define WM5100_AIF3TX2MIX_INPUT_2_SOURCE 0x78A -#define WM5100_AIF3TX2MIX_INPUT_2_VOLUME 0x78B -#define WM5100_AIF3TX2MIX_INPUT_3_SOURCE 0x78C -#define WM5100_AIF3TX2MIX_INPUT_3_VOLUME 0x78D -#define WM5100_AIF3TX2MIX_INPUT_4_SOURCE 0x78E -#define WM5100_AIF3TX2MIX_INPUT_4_VOLUME 0x78F -#define WM5100_EQ1MIX_INPUT_1_SOURCE 0x880 -#define WM5100_EQ1MIX_INPUT_1_VOLUME 0x881 -#define WM5100_EQ1MIX_INPUT_2_SOURCE 0x882 -#define WM5100_EQ1MIX_INPUT_2_VOLUME 0x883 -#define WM5100_EQ1MIX_INPUT_3_SOURCE 0x884 -#define WM5100_EQ1MIX_INPUT_3_VOLUME 0x885 -#define WM5100_EQ1MIX_INPUT_4_SOURCE 0x886 -#define WM5100_EQ1MIX_INPUT_4_VOLUME 0x887 -#define WM5100_EQ2MIX_INPUT_1_SOURCE 0x888 -#define WM5100_EQ2MIX_INPUT_1_VOLUME 0x889 -#define WM5100_EQ2MIX_INPUT_2_SOURCE 0x88A -#define WM5100_EQ2MIX_INPUT_2_VOLUME 0x88B -#define WM5100_EQ2MIX_INPUT_3_SOURCE 0x88C -#define WM5100_EQ2MIX_INPUT_3_VOLUME 0x88D -#define WM5100_EQ2MIX_INPUT_4_SOURCE 0x88E -#define WM5100_EQ2MIX_INPUT_4_VOLUME 0x88F -#define WM5100_EQ3MIX_INPUT_1_SOURCE 0x890 -#define WM5100_EQ3MIX_INPUT_1_VOLUME 0x891 -#define WM5100_EQ3MIX_INPUT_2_SOURCE 0x892 -#define WM5100_EQ3MIX_INPUT_2_VOLUME 0x893 -#define WM5100_EQ3MIX_INPUT_3_SOURCE 0x894 -#define WM5100_EQ3MIX_INPUT_3_VOLUME 0x895 -#define WM5100_EQ3MIX_INPUT_4_SOURCE 0x896 -#define WM5100_EQ3MIX_INPUT_4_VOLUME 0x897 -#define WM5100_EQ4MIX_INPUT_1_SOURCE 0x898 -#define WM5100_EQ4MIX_INPUT_1_VOLUME 0x899 -#define WM5100_EQ4MIX_INPUT_2_SOURCE 0x89A -#define WM5100_EQ4MIX_INPUT_2_VOLUME 0x89B -#define WM5100_EQ4MIX_INPUT_3_SOURCE 0x89C -#define WM5100_EQ4MIX_INPUT_3_VOLUME 0x89D -#define WM5100_EQ4MIX_INPUT_4_SOURCE 0x89E -#define WM5100_EQ4MIX_INPUT_4_VOLUME 0x89F -#define WM5100_DRC1LMIX_INPUT_1_SOURCE 0x8C0 -#define WM5100_DRC1LMIX_INPUT_1_VOLUME 0x8C1 -#define WM5100_DRC1LMIX_INPUT_2_SOURCE 0x8C2 -#define WM5100_DRC1LMIX_INPUT_2_VOLUME 0x8C3 -#define WM5100_DRC1LMIX_INPUT_3_SOURCE 0x8C4 -#define WM5100_DRC1LMIX_INPUT_3_VOLUME 0x8C5 -#define WM5100_DRC1LMIX_INPUT_4_SOURCE 0x8C6 -#define WM5100_DRC1LMIX_INPUT_4_VOLUME 0x8C7 -#define WM5100_DRC1RMIX_INPUT_1_SOURCE 0x8C8 -#define WM5100_DRC1RMIX_INPUT_1_VOLUME 0x8C9 -#define WM5100_DRC1RMIX_INPUT_2_SOURCE 0x8CA -#define WM5100_DRC1RMIX_INPUT_2_VOLUME 0x8CB -#define WM5100_DRC1RMIX_INPUT_3_SOURCE 0x8CC -#define WM5100_DRC1RMIX_INPUT_3_VOLUME 0x8CD -#define WM5100_DRC1RMIX_INPUT_4_SOURCE 0x8CE -#define WM5100_DRC1RMIX_INPUT_4_VOLUME 0x8CF -#define WM5100_HPLP1MIX_INPUT_1_SOURCE 0x900 -#define WM5100_HPLP1MIX_INPUT_1_VOLUME 0x901 -#define WM5100_HPLP1MIX_INPUT_2_SOURCE 0x902 -#define WM5100_HPLP1MIX_INPUT_2_VOLUME 0x903 -#define WM5100_HPLP1MIX_INPUT_3_SOURCE 0x904 -#define WM5100_HPLP1MIX_INPUT_3_VOLUME 0x905 -#define WM5100_HPLP1MIX_INPUT_4_SOURCE 0x906 -#define WM5100_HPLP1MIX_INPUT_4_VOLUME 0x907 -#define WM5100_HPLP2MIX_INPUT_1_SOURCE 0x908 -#define WM5100_HPLP2MIX_INPUT_1_VOLUME 0x909 -#define WM5100_HPLP2MIX_INPUT_2_SOURCE 0x90A -#define WM5100_HPLP2MIX_INPUT_2_VOLUME 0x90B -#define WM5100_HPLP2MIX_INPUT_3_SOURCE 0x90C -#define WM5100_HPLP2MIX_INPUT_3_VOLUME 0x90D -#define WM5100_HPLP2MIX_INPUT_4_SOURCE 0x90E -#define WM5100_HPLP2MIX_INPUT_4_VOLUME 0x90F -#define WM5100_HPLP3MIX_INPUT_1_SOURCE 0x910 -#define WM5100_HPLP3MIX_INPUT_1_VOLUME 0x911 -#define WM5100_HPLP3MIX_INPUT_2_SOURCE 0x912 -#define WM5100_HPLP3MIX_INPUT_2_VOLUME 0x913 -#define WM5100_HPLP3MIX_INPUT_3_SOURCE 0x914 -#define WM5100_HPLP3MIX_INPUT_3_VOLUME 0x915 -#define WM5100_HPLP3MIX_INPUT_4_SOURCE 0x916 -#define WM5100_HPLP3MIX_INPUT_4_VOLUME 0x917 -#define WM5100_HPLP4MIX_INPUT_1_SOURCE 0x918 -#define WM5100_HPLP4MIX_INPUT_1_VOLUME 0x919 -#define WM5100_HPLP4MIX_INPUT_2_SOURCE 0x91A -#define WM5100_HPLP4MIX_INPUT_2_VOLUME 0x91B -#define WM5100_HPLP4MIX_INPUT_3_SOURCE 0x91C -#define WM5100_HPLP4MIX_INPUT_3_VOLUME 0x91D -#define WM5100_HPLP4MIX_INPUT_4_SOURCE 0x91E -#define WM5100_HPLP4MIX_INPUT_4_VOLUME 0x91F -#define WM5100_DSP1LMIX_INPUT_1_SOURCE 0x940 -#define WM5100_DSP1LMIX_INPUT_1_VOLUME 0x941 -#define WM5100_DSP1LMIX_INPUT_2_SOURCE 0x942 -#define WM5100_DSP1LMIX_INPUT_2_VOLUME 0x943 -#define WM5100_DSP1LMIX_INPUT_3_SOURCE 0x944 -#define WM5100_DSP1LMIX_INPUT_3_VOLUME 0x945 -#define WM5100_DSP1LMIX_INPUT_4_SOURCE 0x946 -#define WM5100_DSP1LMIX_INPUT_4_VOLUME 0x947 -#define WM5100_DSP1RMIX_INPUT_1_SOURCE 0x948 -#define WM5100_DSP1RMIX_INPUT_1_VOLUME 0x949 -#define WM5100_DSP1RMIX_INPUT_2_SOURCE 0x94A -#define WM5100_DSP1RMIX_INPUT_2_VOLUME 0x94B -#define WM5100_DSP1RMIX_INPUT_3_SOURCE 0x94C -#define WM5100_DSP1RMIX_INPUT_3_VOLUME 0x94D -#define WM5100_DSP1RMIX_INPUT_4_SOURCE 0x94E -#define WM5100_DSP1RMIX_INPUT_4_VOLUME 0x94F -#define WM5100_DSP1AUX1MIX_INPUT_1_SOURCE 0x950 -#define WM5100_DSP1AUX2MIX_INPUT_1_SOURCE 0x958 -#define WM5100_DSP1AUX3MIX_INPUT_1_SOURCE 0x960 -#define WM5100_DSP1AUX4MIX_INPUT_1_SOURCE 0x968 -#define WM5100_DSP1AUX5MIX_INPUT_1_SOURCE 0x970 -#define WM5100_DSP1AUX6MIX_INPUT_1_SOURCE 0x978 -#define WM5100_DSP2LMIX_INPUT_1_SOURCE 0x980 -#define WM5100_DSP2LMIX_INPUT_1_VOLUME 0x981 -#define WM5100_DSP2LMIX_INPUT_2_SOURCE 0x982 -#define WM5100_DSP2LMIX_INPUT_2_VOLUME 0x983 -#define WM5100_DSP2LMIX_INPUT_3_SOURCE 0x984 -#define WM5100_DSP2LMIX_INPUT_3_VOLUME 0x985 -#define WM5100_DSP2LMIX_INPUT_4_SOURCE 0x986 -#define WM5100_DSP2LMIX_INPUT_4_VOLUME 0x987 -#define WM5100_DSP2RMIX_INPUT_1_SOURCE 0x988 -#define WM5100_DSP2RMIX_INPUT_1_VOLUME 0x989 -#define WM5100_DSP2RMIX_INPUT_2_SOURCE 0x98A -#define WM5100_DSP2RMIX_INPUT_2_VOLUME 0x98B -#define WM5100_DSP2RMIX_INPUT_3_SOURCE 0x98C -#define WM5100_DSP2RMIX_INPUT_3_VOLUME 0x98D -#define WM5100_DSP2RMIX_INPUT_4_SOURCE 0x98E -#define WM5100_DSP2RMIX_INPUT_4_VOLUME 0x98F -#define WM5100_DSP2AUX1MIX_INPUT_1_SOURCE 0x990 -#define WM5100_DSP2AUX2MIX_INPUT_1_SOURCE 0x998 -#define WM5100_DSP2AUX3MIX_INPUT_1_SOURCE 0x9A0 -#define WM5100_DSP2AUX4MIX_INPUT_1_SOURCE 0x9A8 -#define WM5100_DSP2AUX5MIX_INPUT_1_SOURCE 0x9B0 -#define WM5100_DSP2AUX6MIX_INPUT_1_SOURCE 0x9B8 -#define WM5100_DSP3LMIX_INPUT_1_SOURCE 0x9C0 -#define WM5100_DSP3LMIX_INPUT_1_VOLUME 0x9C1 -#define WM5100_DSP3LMIX_INPUT_2_SOURCE 0x9C2 -#define WM5100_DSP3LMIX_INPUT_2_VOLUME 0x9C3 -#define WM5100_DSP3LMIX_INPUT_3_SOURCE 0x9C4 -#define WM5100_DSP3LMIX_INPUT_3_VOLUME 0x9C5 -#define WM5100_DSP3LMIX_INPUT_4_SOURCE 0x9C6 -#define WM5100_DSP3LMIX_INPUT_4_VOLUME 0x9C7 -#define WM5100_DSP3RMIX_INPUT_1_SOURCE 0x9C8 -#define WM5100_DSP3RMIX_INPUT_1_VOLUME 0x9C9 -#define WM5100_DSP3RMIX_INPUT_2_SOURCE 0x9CA -#define WM5100_DSP3RMIX_INPUT_2_VOLUME 0x9CB -#define WM5100_DSP3RMIX_INPUT_3_SOURCE 0x9CC -#define WM5100_DSP3RMIX_INPUT_3_VOLUME 0x9CD -#define WM5100_DSP3RMIX_INPUT_4_SOURCE 0x9CE -#define WM5100_DSP3RMIX_INPUT_4_VOLUME 0x9CF -#define WM5100_DSP3AUX1MIX_INPUT_1_SOURCE 0x9D0 -#define WM5100_DSP3AUX2MIX_INPUT_1_SOURCE 0x9D8 -#define WM5100_DSP3AUX3MIX_INPUT_1_SOURCE 0x9E0 -#define WM5100_DSP3AUX4MIX_INPUT_1_SOURCE 0x9E8 -#define WM5100_DSP3AUX5MIX_INPUT_1_SOURCE 0x9F0 -#define WM5100_DSP3AUX6MIX_INPUT_1_SOURCE 0x9F8 -#define WM5100_ASRC1LMIX_INPUT_1_SOURCE 0xA80 -#define WM5100_ASRC1RMIX_INPUT_1_SOURCE 0xA88 -#define WM5100_ASRC2LMIX_INPUT_1_SOURCE 0xA90 -#define WM5100_ASRC2RMIX_INPUT_1_SOURCE 0xA98 -#define WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE 0xB00 -#define WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE 0xB08 -#define WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE 0xB10 -#define WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE 0xB18 -#define WM5100_ISRC1INT1MIX_INPUT_1_SOURCE 0xB20 -#define WM5100_ISRC1INT2MIX_INPUT_1_SOURCE 0xB28 -#define WM5100_ISRC1INT3MIX_INPUT_1_SOURCE 0xB30 -#define WM5100_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38 -#define WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40 -#define WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48 -#define WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE 0xB50 -#define WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE 0xB58 -#define WM5100_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60 -#define WM5100_ISRC2INT2MIX_INPUT_1_SOURCE 0xB68 -#define WM5100_ISRC2INT3MIX_INPUT_1_SOURCE 0xB70 -#define WM5100_ISRC2INT4MIX_INPUT_1_SOURCE 0xB78 -#define WM5100_GPIO_CTRL_1 0xC00 -#define WM5100_GPIO_CTRL_2 0xC01 -#define WM5100_GPIO_CTRL_3 0xC02 -#define WM5100_GPIO_CTRL_4 0xC03 -#define WM5100_GPIO_CTRL_5 0xC04 -#define WM5100_GPIO_CTRL_6 0xC05 -#define WM5100_MISC_PAD_CTRL_1 0xC23 -#define WM5100_MISC_PAD_CTRL_2 0xC24 -#define WM5100_MISC_PAD_CTRL_3 0xC25 -#define WM5100_MISC_PAD_CTRL_4 0xC26 -#define WM5100_MISC_PAD_CTRL_5 0xC27 -#define WM5100_MISC_GPIO_1 0xC28 -#define WM5100_INTERRUPT_STATUS_1 0xD00 -#define WM5100_INTERRUPT_STATUS_2 0xD01 -#define WM5100_INTERRUPT_STATUS_3 0xD02 -#define WM5100_INTERRUPT_STATUS_4 0xD03 -#define WM5100_INTERRUPT_RAW_STATUS_2 0xD04 -#define WM5100_INTERRUPT_RAW_STATUS_3 0xD05 -#define WM5100_INTERRUPT_RAW_STATUS_4 0xD06 -#define WM5100_INTERRUPT_STATUS_1_MASK 0xD07 -#define WM5100_INTERRUPT_STATUS_2_MASK 0xD08 -#define WM5100_INTERRUPT_STATUS_3_MASK 0xD09 -#define WM5100_INTERRUPT_STATUS_4_MASK 0xD0A -#define WM5100_INTERRUPT_CONTROL 0xD1F -#define WM5100_IRQ_DEBOUNCE_1 0xD20 -#define WM5100_IRQ_DEBOUNCE_2 0xD21 -#define WM5100_FX_CTRL 0xE00 -#define WM5100_EQ1_1 0xE10 -#define WM5100_EQ1_2 0xE11 -#define WM5100_EQ1_3 0xE12 -#define WM5100_EQ1_4 0xE13 -#define WM5100_EQ1_5 0xE14 -#define WM5100_EQ1_6 0xE15 -#define WM5100_EQ1_7 0xE16 -#define WM5100_EQ1_8 0xE17 -#define WM5100_EQ1_9 0xE18 -#define WM5100_EQ1_10 0xE19 -#define WM5100_EQ1_11 0xE1A -#define WM5100_EQ1_12 0xE1B -#define WM5100_EQ1_13 0xE1C -#define WM5100_EQ1_14 0xE1D -#define WM5100_EQ1_15 0xE1E -#define WM5100_EQ1_16 0xE1F -#define WM5100_EQ1_17 0xE20 -#define WM5100_EQ1_18 0xE21 -#define WM5100_EQ1_19 0xE22 -#define WM5100_EQ1_20 0xE23 -#define WM5100_EQ2_1 0xE26 -#define WM5100_EQ2_2 0xE27 -#define WM5100_EQ2_3 0xE28 -#define WM5100_EQ2_4 0xE29 -#define WM5100_EQ2_5 0xE2A -#define WM5100_EQ2_6 0xE2B -#define WM5100_EQ2_7 0xE2C -#define WM5100_EQ2_8 0xE2D -#define WM5100_EQ2_9 0xE2E -#define WM5100_EQ2_10 0xE2F -#define WM5100_EQ2_11 0xE30 -#define WM5100_EQ2_12 0xE31 -#define WM5100_EQ2_13 0xE32 -#define WM5100_EQ2_14 0xE33 -#define WM5100_EQ2_15 0xE34 -#define WM5100_EQ2_16 0xE35 -#define WM5100_EQ2_17 0xE36 -#define WM5100_EQ2_18 0xE37 -#define WM5100_EQ2_19 0xE38 -#define WM5100_EQ2_20 0xE39 -#define WM5100_EQ3_1 0xE3C -#define WM5100_EQ3_2 0xE3D -#define WM5100_EQ3_3 0xE3E -#define WM5100_EQ3_4 0xE3F -#define WM5100_EQ3_5 0xE40 -#define WM5100_EQ3_6 0xE41 -#define WM5100_EQ3_7 0xE42 -#define WM5100_EQ3_8 0xE43 -#define WM5100_EQ3_9 0xE44 -#define WM5100_EQ3_10 0xE45 -#define WM5100_EQ3_11 0xE46 -#define WM5100_EQ3_12 0xE47 -#define WM5100_EQ3_13 0xE48 -#define WM5100_EQ3_14 0xE49 -#define WM5100_EQ3_15 0xE4A -#define WM5100_EQ3_16 0xE4B -#define WM5100_EQ3_17 0xE4C -#define WM5100_EQ3_18 0xE4D -#define WM5100_EQ3_19 0xE4E -#define WM5100_EQ3_20 0xE4F -#define WM5100_EQ4_1 0xE52 -#define WM5100_EQ4_2 0xE53 -#define WM5100_EQ4_3 0xE54 -#define WM5100_EQ4_4 0xE55 -#define WM5100_EQ4_5 0xE56 -#define WM5100_EQ4_6 0xE57 -#define WM5100_EQ4_7 0xE58 -#define WM5100_EQ4_8 0xE59 -#define WM5100_EQ4_9 0xE5A -#define WM5100_EQ4_10 0xE5B -#define WM5100_EQ4_11 0xE5C -#define WM5100_EQ4_12 0xE5D -#define WM5100_EQ4_13 0xE5E -#define WM5100_EQ4_14 0xE5F -#define WM5100_EQ4_15 0xE60 -#define WM5100_EQ4_16 0xE61 -#define WM5100_EQ4_17 0xE62 -#define WM5100_EQ4_18 0xE63 -#define WM5100_EQ4_19 0xE64 -#define WM5100_EQ4_20 0xE65 -#define WM5100_DRC1_CTRL1 0xE80 -#define WM5100_DRC1_CTRL2 0xE81 -#define WM5100_DRC1_CTRL3 0xE82 -#define WM5100_DRC1_CTRL4 0xE83 -#define WM5100_DRC1_CTRL5 0xE84 -#define WM5100_HPLPF1_1 0xEC0 -#define WM5100_HPLPF1_2 0xEC1 -#define WM5100_HPLPF2_1 0xEC4 -#define WM5100_HPLPF2_2 0xEC5 -#define WM5100_HPLPF3_1 0xEC8 -#define WM5100_HPLPF3_2 0xEC9 -#define WM5100_HPLPF4_1 0xECC -#define WM5100_HPLPF4_2 0xECD -#define WM5100_DSP1_DM_0 0x4000 -#define WM5100_DSP1_DM_1 0x4001 -#define WM5100_DSP1_DM_2 0x4002 -#define WM5100_DSP1_DM_3 0x4003 -#define WM5100_DSP1_DM_508 0x41FC -#define WM5100_DSP1_DM_509 0x41FD -#define WM5100_DSP1_DM_510 0x41FE -#define WM5100_DSP1_DM_511 0x41FF -#define WM5100_DSP1_PM_0 0x4800 -#define WM5100_DSP1_PM_1 0x4801 -#define WM5100_DSP1_PM_2 0x4802 -#define WM5100_DSP1_PM_3 0x4803 -#define WM5100_DSP1_PM_4 0x4804 -#define WM5100_DSP1_PM_5 0x4805 -#define WM5100_DSP1_PM_1530 0x4DFA -#define WM5100_DSP1_PM_1531 0x4DFB -#define WM5100_DSP1_PM_1532 0x4DFC -#define WM5100_DSP1_PM_1533 0x4DFD -#define WM5100_DSP1_PM_1534 0x4DFE -#define WM5100_DSP1_PM_1535 0x4DFF -#define WM5100_DSP1_ZM_0 0x5000 -#define WM5100_DSP1_ZM_1 0x5001 -#define WM5100_DSP1_ZM_2 0x5002 -#define WM5100_DSP1_ZM_3 0x5003 -#define WM5100_DSP1_ZM_2044 0x57FC -#define WM5100_DSP1_ZM_2045 0x57FD -#define WM5100_DSP1_ZM_2046 0x57FE -#define WM5100_DSP1_ZM_2047 0x57FF -#define WM5100_DSP2_DM_0 0x6000 -#define WM5100_DSP2_DM_1 0x6001 -#define WM5100_DSP2_DM_2 0x6002 -#define WM5100_DSP2_DM_3 0x6003 -#define WM5100_DSP2_DM_508 0x61FC -#define WM5100_DSP2_DM_509 0x61FD -#define WM5100_DSP2_DM_510 0x61FE -#define WM5100_DSP2_DM_511 0x61FF -#define WM5100_DSP2_PM_0 0x6800 -#define WM5100_DSP2_PM_1 0x6801 -#define WM5100_DSP2_PM_2 0x6802 -#define WM5100_DSP2_PM_3 0x6803 -#define WM5100_DSP2_PM_4 0x6804 -#define WM5100_DSP2_PM_5 0x6805 -#define WM5100_DSP2_PM_1530 0x6DFA -#define WM5100_DSP2_PM_1531 0x6DFB -#define WM5100_DSP2_PM_1532 0x6DFC -#define WM5100_DSP2_PM_1533 0x6DFD -#define WM5100_DSP2_PM_1534 0x6DFE -#define WM5100_DSP2_PM_1535 0x6DFF -#define WM5100_DSP2_ZM_0 0x7000 -#define WM5100_DSP2_ZM_1 0x7001 -#define WM5100_DSP2_ZM_2 0x7002 -#define WM5100_DSP2_ZM_3 0x7003 -#define WM5100_DSP2_ZM_2044 0x77FC -#define WM5100_DSP2_ZM_2045 0x77FD -#define WM5100_DSP2_ZM_2046 0x77FE -#define WM5100_DSP2_ZM_2047 0x77FF -#define WM5100_DSP3_DM_0 0x8000 -#define WM5100_DSP3_DM_1 0x8001 -#define WM5100_DSP3_DM_2 0x8002 -#define WM5100_DSP3_DM_3 0x8003 -#define WM5100_DSP3_DM_508 0x81FC -#define WM5100_DSP3_DM_509 0x81FD -#define WM5100_DSP3_DM_510 0x81FE -#define WM5100_DSP3_DM_511 0x81FF -#define WM5100_DSP3_PM_0 0x8800 -#define WM5100_DSP3_PM_1 0x8801 -#define WM5100_DSP3_PM_2 0x8802 -#define WM5100_DSP3_PM_3 0x8803 -#define WM5100_DSP3_PM_4 0x8804 -#define WM5100_DSP3_PM_5 0x8805 -#define WM5100_DSP3_PM_1530 0x8DFA -#define WM5100_DSP3_PM_1531 0x8DFB -#define WM5100_DSP3_PM_1532 0x8DFC -#define WM5100_DSP3_PM_1533 0x8DFD -#define WM5100_DSP3_PM_1534 0x8DFE -#define WM5100_DSP3_PM_1535 0x8DFF -#define WM5100_DSP3_ZM_0 0x9000 -#define WM5100_DSP3_ZM_1 0x9001 -#define WM5100_DSP3_ZM_2 0x9002 -#define WM5100_DSP3_ZM_3 0x9003 -#define WM5100_DSP3_ZM_2044 0x97FC -#define WM5100_DSP3_ZM_2045 0x97FD -#define WM5100_DSP3_ZM_2046 0x97FE -#define WM5100_DSP3_ZM_2047 0x97FF - -#define WM5100_REGISTER_COUNT 1435 -#define WM5100_MAX_REGISTER 0x97FF - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - software reset - */ -#define WM5100_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ -#define WM5100_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ -#define WM5100_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ - -/* - * R1 (0x01) - Device Revision - */ -#define WM5100_DEVICE_REVISION_MASK 0x000F /* DEVICE_REVISION - [3:0] */ -#define WM5100_DEVICE_REVISION_SHIFT 0 /* DEVICE_REVISION - [3:0] */ -#define WM5100_DEVICE_REVISION_WIDTH 4 /* DEVICE_REVISION - [3:0] */ - -/* - * R16 (0x10) - Ctrl IF 1 - */ -#define WM5100_AUTO_INC 0x0001 /* AUTO_INC */ -#define WM5100_AUTO_INC_MASK 0x0001 /* AUTO_INC */ -#define WM5100_AUTO_INC_SHIFT 0 /* AUTO_INC */ -#define WM5100_AUTO_INC_WIDTH 1 /* AUTO_INC */ - -/* - * R32 (0x20) - Tone Generator 1 - */ -#define WM5100_TONE_RATE_MASK 0x3000 /* TONE_RATE - [13:12] */ -#define WM5100_TONE_RATE_SHIFT 12 /* TONE_RATE - [13:12] */ -#define WM5100_TONE_RATE_WIDTH 2 /* TONE_RATE - [13:12] */ -#define WM5100_TONE_OFFSET_MASK 0x0300 /* TONE_OFFSET - [9:8] */ -#define WM5100_TONE_OFFSET_SHIFT 8 /* TONE_OFFSET - [9:8] */ -#define WM5100_TONE_OFFSET_WIDTH 2 /* TONE_OFFSET - [9:8] */ -#define WM5100_TONE2_ENA 0x0002 /* TONE2_ENA */ -#define WM5100_TONE2_ENA_MASK 0x0002 /* TONE2_ENA */ -#define WM5100_TONE2_ENA_SHIFT 1 /* TONE2_ENA */ -#define WM5100_TONE2_ENA_WIDTH 1 /* TONE2_ENA */ -#define WM5100_TONE1_ENA 0x0001 /* TONE1_ENA */ -#define WM5100_TONE1_ENA_MASK 0x0001 /* TONE1_ENA */ -#define WM5100_TONE1_ENA_SHIFT 0 /* TONE1_ENA */ -#define WM5100_TONE1_ENA_WIDTH 1 /* TONE1_ENA */ - -/* - * R48 (0x30) - PWM Drive 1 - */ -#define WM5100_PWM_RATE_MASK 0x3000 /* PWM_RATE - [13:12] */ -#define WM5100_PWM_RATE_SHIFT 12 /* PWM_RATE - [13:12] */ -#define WM5100_PWM_RATE_WIDTH 2 /* PWM_RATE - [13:12] */ -#define WM5100_PWM_CLK_SEL_MASK 0x0300 /* PWM_CLK_SEL - [9:8] */ -#define WM5100_PWM_CLK_SEL_SHIFT 8 /* PWM_CLK_SEL - [9:8] */ -#define WM5100_PWM_CLK_SEL_WIDTH 2 /* PWM_CLK_SEL - [9:8] */ -#define WM5100_PWM2_OVD 0x0020 /* PWM2_OVD */ -#define WM5100_PWM2_OVD_MASK 0x0020 /* PWM2_OVD */ -#define WM5100_PWM2_OVD_SHIFT 5 /* PWM2_OVD */ -#define WM5100_PWM2_OVD_WIDTH 1 /* PWM2_OVD */ -#define WM5100_PWM1_OVD 0x0010 /* PWM1_OVD */ -#define WM5100_PWM1_OVD_MASK 0x0010 /* PWM1_OVD */ -#define WM5100_PWM1_OVD_SHIFT 4 /* PWM1_OVD */ -#define WM5100_PWM1_OVD_WIDTH 1 /* PWM1_OVD */ -#define WM5100_PWM2_ENA 0x0002 /* PWM2_ENA */ -#define WM5100_PWM2_ENA_MASK 0x0002 /* PWM2_ENA */ -#define WM5100_PWM2_ENA_SHIFT 1 /* PWM2_ENA */ -#define WM5100_PWM2_ENA_WIDTH 1 /* PWM2_ENA */ -#define WM5100_PWM1_ENA 0x0001 /* PWM1_ENA */ -#define WM5100_PWM1_ENA_MASK 0x0001 /* PWM1_ENA */ -#define WM5100_PWM1_ENA_SHIFT 0 /* PWM1_ENA */ -#define WM5100_PWM1_ENA_WIDTH 1 /* PWM1_ENA */ - -/* - * R49 (0x31) - PWM Drive 2 - */ -#define WM5100_PWM1_LVL_MASK 0x03FF /* PWM1_LVL - [9:0] */ -#define WM5100_PWM1_LVL_SHIFT 0 /* PWM1_LVL - [9:0] */ -#define WM5100_PWM1_LVL_WIDTH 10 /* PWM1_LVL - [9:0] */ - -/* - * R50 (0x32) - PWM Drive 3 - */ -#define WM5100_PWM2_LVL_MASK 0x03FF /* PWM2_LVL - [9:0] */ -#define WM5100_PWM2_LVL_SHIFT 0 /* PWM2_LVL - [9:0] */ -#define WM5100_PWM2_LVL_WIDTH 10 /* PWM2_LVL - [9:0] */ - -/* - * R256 (0x100) - Clocking 1 - */ -#define WM5100_CLK_32K_SRC_MASK 0x000F /* CLK_32K_SRC - [3:0] */ -#define WM5100_CLK_32K_SRC_SHIFT 0 /* CLK_32K_SRC - [3:0] */ -#define WM5100_CLK_32K_SRC_WIDTH 4 /* CLK_32K_SRC - [3:0] */ - -/* - * R257 (0x101) - Clocking 3 - */ -#define WM5100_SYSCLK_FREQ_MASK 0x0700 /* SYSCLK_FREQ - [10:8] */ -#define WM5100_SYSCLK_FREQ_SHIFT 8 /* SYSCLK_FREQ - [10:8] */ -#define WM5100_SYSCLK_FREQ_WIDTH 3 /* SYSCLK_FREQ - [10:8] */ -#define WM5100_SYSCLK_ENA 0x0040 /* SYSCLK_ENA */ -#define WM5100_SYSCLK_ENA_MASK 0x0040 /* SYSCLK_ENA */ -#define WM5100_SYSCLK_ENA_SHIFT 6 /* SYSCLK_ENA */ -#define WM5100_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */ -#define WM5100_SYSCLK_SRC_MASK 0x000F /* SYSCLK_SRC - [3:0] */ -#define WM5100_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC - [3:0] */ -#define WM5100_SYSCLK_SRC_WIDTH 4 /* SYSCLK_SRC - [3:0] */ - -/* - * R258 (0x102) - Clocking 4 - */ -#define WM5100_SAMPLE_RATE_1_MASK 0x001F /* SAMPLE_RATE_1 - [4:0] */ -#define WM5100_SAMPLE_RATE_1_SHIFT 0 /* SAMPLE_RATE_1 - [4:0] */ -#define WM5100_SAMPLE_RATE_1_WIDTH 5 /* SAMPLE_RATE_1 - [4:0] */ - -/* - * R259 (0x103) - Clocking 5 - */ -#define WM5100_SAMPLE_RATE_2_MASK 0x001F /* SAMPLE_RATE_2 - [4:0] */ -#define WM5100_SAMPLE_RATE_2_SHIFT 0 /* SAMPLE_RATE_2 - [4:0] */ -#define WM5100_SAMPLE_RATE_2_WIDTH 5 /* SAMPLE_RATE_2 - [4:0] */ - -/* - * R260 (0x104) - Clocking 6 - */ -#define WM5100_SAMPLE_RATE_3_MASK 0x001F /* SAMPLE_RATE_3 - [4:0] */ -#define WM5100_SAMPLE_RATE_3_SHIFT 0 /* SAMPLE_RATE_3 - [4:0] */ -#define WM5100_SAMPLE_RATE_3_WIDTH 5 /* SAMPLE_RATE_3 - [4:0] */ - -/* - * R263 (0x107) - Clocking 7 - */ -#define WM5100_ASYNC_CLK_FREQ_MASK 0x0700 /* ASYNC_CLK_FREQ - [10:8] */ -#define WM5100_ASYNC_CLK_FREQ_SHIFT 8 /* ASYNC_CLK_FREQ - [10:8] */ -#define WM5100_ASYNC_CLK_FREQ_WIDTH 3 /* ASYNC_CLK_FREQ - [10:8] */ -#define WM5100_ASYNC_CLK_ENA 0x0040 /* ASYNC_CLK_ENA */ -#define WM5100_ASYNC_CLK_ENA_MASK 0x0040 /* ASYNC_CLK_ENA */ -#define WM5100_ASYNC_CLK_ENA_SHIFT 6 /* ASYNC_CLK_ENA */ -#define WM5100_ASYNC_CLK_ENA_WIDTH 1 /* ASYNC_CLK_ENA */ -#define WM5100_ASYNC_CLK_SRC_MASK 0x000F /* ASYNC_CLK_SRC - [3:0] */ -#define WM5100_ASYNC_CLK_SRC_SHIFT 0 /* ASYNC_CLK_SRC - [3:0] */ -#define WM5100_ASYNC_CLK_SRC_WIDTH 4 /* ASYNC_CLK_SRC - [3:0] */ - -/* - * R264 (0x108) - Clocking 8 - */ -#define WM5100_ASYNC_SAMPLE_RATE_MASK 0x001F /* ASYNC_SAMPLE_RATE - [4:0] */ -#define WM5100_ASYNC_SAMPLE_RATE_SHIFT 0 /* ASYNC_SAMPLE_RATE - [4:0] */ -#define WM5100_ASYNC_SAMPLE_RATE_WIDTH 5 /* ASYNC_SAMPLE_RATE - [4:0] */ - -/* - * R288 (0x120) - ASRC_ENABLE - */ -#define WM5100_ASRC2L_ENA 0x0008 /* ASRC2L_ENA */ -#define WM5100_ASRC2L_ENA_MASK 0x0008 /* ASRC2L_ENA */ -#define WM5100_ASRC2L_ENA_SHIFT 3 /* ASRC2L_ENA */ -#define WM5100_ASRC2L_ENA_WIDTH 1 /* ASRC2L_ENA */ -#define WM5100_ASRC2R_ENA 0x0004 /* ASRC2R_ENA */ -#define WM5100_ASRC2R_ENA_MASK 0x0004 /* ASRC2R_ENA */ -#define WM5100_ASRC2R_ENA_SHIFT 2 /* ASRC2R_ENA */ -#define WM5100_ASRC2R_ENA_WIDTH 1 /* ASRC2R_ENA */ -#define WM5100_ASRC1L_ENA 0x0002 /* ASRC1L_ENA */ -#define WM5100_ASRC1L_ENA_MASK 0x0002 /* ASRC1L_ENA */ -#define WM5100_ASRC1L_ENA_SHIFT 1 /* ASRC1L_ENA */ -#define WM5100_ASRC1L_ENA_WIDTH 1 /* ASRC1L_ENA */ -#define WM5100_ASRC1R_ENA 0x0001 /* ASRC1R_ENA */ -#define WM5100_ASRC1R_ENA_MASK 0x0001 /* ASRC1R_ENA */ -#define WM5100_ASRC1R_ENA_SHIFT 0 /* ASRC1R_ENA */ -#define WM5100_ASRC1R_ENA_WIDTH 1 /* ASRC1R_ENA */ - -/* - * R289 (0x121) - ASRC_STATUS - */ -#define WM5100_ASRC2L_ENA_STS 0x0008 /* ASRC2L_ENA_STS */ -#define WM5100_ASRC2L_ENA_STS_MASK 0x0008 /* ASRC2L_ENA_STS */ -#define WM5100_ASRC2L_ENA_STS_SHIFT 3 /* ASRC2L_ENA_STS */ -#define WM5100_ASRC2L_ENA_STS_WIDTH 1 /* ASRC2L_ENA_STS */ -#define WM5100_ASRC2R_ENA_STS 0x0004 /* ASRC2R_ENA_STS */ -#define WM5100_ASRC2R_ENA_STS_MASK 0x0004 /* ASRC2R_ENA_STS */ -#define WM5100_ASRC2R_ENA_STS_SHIFT 2 /* ASRC2R_ENA_STS */ -#define WM5100_ASRC2R_ENA_STS_WIDTH 1 /* ASRC2R_ENA_STS */ -#define WM5100_ASRC1L_ENA_STS 0x0002 /* ASRC1L_ENA_STS */ -#define WM5100_ASRC1L_ENA_STS_MASK 0x0002 /* ASRC1L_ENA_STS */ -#define WM5100_ASRC1L_ENA_STS_SHIFT 1 /* ASRC1L_ENA_STS */ -#define WM5100_ASRC1L_ENA_STS_WIDTH 1 /* ASRC1L_ENA_STS */ -#define WM5100_ASRC1R_ENA_STS 0x0001 /* ASRC1R_ENA_STS */ -#define WM5100_ASRC1R_ENA_STS_MASK 0x0001 /* ASRC1R_ENA_STS */ -#define WM5100_ASRC1R_ENA_STS_SHIFT 0 /* ASRC1R_ENA_STS */ -#define WM5100_ASRC1R_ENA_STS_WIDTH 1 /* ASRC1R_ENA_STS */ - -/* - * R290 (0x122) - ASRC_RATE1 - */ -#define WM5100_ASRC_RATE1_MASK 0x0006 /* ASRC_RATE1 - [2:1] */ -#define WM5100_ASRC_RATE1_SHIFT 1 /* ASRC_RATE1 - [2:1] */ -#define WM5100_ASRC_RATE1_WIDTH 2 /* ASRC_RATE1 - [2:1] */ - -/* - * R321 (0x141) - ISRC 1 CTRL 1 - */ -#define WM5100_ISRC1_DFS_ENA 0x2000 /* ISRC1_DFS_ENA */ -#define WM5100_ISRC1_DFS_ENA_MASK 0x2000 /* ISRC1_DFS_ENA */ -#define WM5100_ISRC1_DFS_ENA_SHIFT 13 /* ISRC1_DFS_ENA */ -#define WM5100_ISRC1_DFS_ENA_WIDTH 1 /* ISRC1_DFS_ENA */ -#define WM5100_ISRC1_CLK_SEL_MASK 0x0300 /* ISRC1_CLK_SEL - [9:8] */ -#define WM5100_ISRC1_CLK_SEL_SHIFT 8 /* ISRC1_CLK_SEL - [9:8] */ -#define WM5100_ISRC1_CLK_SEL_WIDTH 2 /* ISRC1_CLK_SEL - [9:8] */ -#define WM5100_ISRC1_FSH_MASK 0x000C /* ISRC1_FSH - [3:2] */ -#define WM5100_ISRC1_FSH_SHIFT 2 /* ISRC1_FSH - [3:2] */ -#define WM5100_ISRC1_FSH_WIDTH 2 /* ISRC1_FSH - [3:2] */ -#define WM5100_ISRC1_FSL_MASK 0x0003 /* ISRC1_FSL - [1:0] */ -#define WM5100_ISRC1_FSL_SHIFT 0 /* ISRC1_FSL - [1:0] */ -#define WM5100_ISRC1_FSL_WIDTH 2 /* ISRC1_FSL - [1:0] */ - -/* - * R322 (0x142) - ISRC 1 CTRL 2 - */ -#define WM5100_ISRC1_INT1_ENA 0x8000 /* ISRC1_INT1_ENA */ -#define WM5100_ISRC1_INT1_ENA_MASK 0x8000 /* ISRC1_INT1_ENA */ -#define WM5100_ISRC1_INT1_ENA_SHIFT 15 /* ISRC1_INT1_ENA */ -#define WM5100_ISRC1_INT1_ENA_WIDTH 1 /* ISRC1_INT1_ENA */ -#define WM5100_ISRC1_INT2_ENA 0x4000 /* ISRC1_INT2_ENA */ -#define WM5100_ISRC1_INT2_ENA_MASK 0x4000 /* ISRC1_INT2_ENA */ -#define WM5100_ISRC1_INT2_ENA_SHIFT 14 /* ISRC1_INT2_ENA */ -#define WM5100_ISRC1_INT2_ENA_WIDTH 1 /* ISRC1_INT2_ENA */ -#define WM5100_ISRC1_INT3_ENA 0x2000 /* ISRC1_INT3_ENA */ -#define WM5100_ISRC1_INT3_ENA_MASK 0x2000 /* ISRC1_INT3_ENA */ -#define WM5100_ISRC1_INT3_ENA_SHIFT 13 /* ISRC1_INT3_ENA */ -#define WM5100_ISRC1_INT3_ENA_WIDTH 1 /* ISRC1_INT3_ENA */ -#define WM5100_ISRC1_INT4_ENA 0x1000 /* ISRC1_INT4_ENA */ -#define WM5100_ISRC1_INT4_ENA_MASK 0x1000 /* ISRC1_INT4_ENA */ -#define WM5100_ISRC1_INT4_ENA_SHIFT 12 /* ISRC1_INT4_ENA */ -#define WM5100_ISRC1_INT4_ENA_WIDTH 1 /* ISRC1_INT4_ENA */ -#define WM5100_ISRC1_DEC1_ENA 0x0200 /* ISRC1_DEC1_ENA */ -#define WM5100_ISRC1_DEC1_ENA_MASK 0x0200 /* ISRC1_DEC1_ENA */ -#define WM5100_ISRC1_DEC1_ENA_SHIFT 9 /* ISRC1_DEC1_ENA */ -#define WM5100_ISRC1_DEC1_ENA_WIDTH 1 /* ISRC1_DEC1_ENA */ -#define WM5100_ISRC1_DEC2_ENA 0x0100 /* ISRC1_DEC2_ENA */ -#define WM5100_ISRC1_DEC2_ENA_MASK 0x0100 /* ISRC1_DEC2_ENA */ -#define WM5100_ISRC1_DEC2_ENA_SHIFT 8 /* ISRC1_DEC2_ENA */ -#define WM5100_ISRC1_DEC2_ENA_WIDTH 1 /* ISRC1_DEC2_ENA */ -#define WM5100_ISRC1_DEC3_ENA 0x0080 /* ISRC1_DEC3_ENA */ -#define WM5100_ISRC1_DEC3_ENA_MASK 0x0080 /* ISRC1_DEC3_ENA */ -#define WM5100_ISRC1_DEC3_ENA_SHIFT 7 /* ISRC1_DEC3_ENA */ -#define WM5100_ISRC1_DEC3_ENA_WIDTH 1 /* ISRC1_DEC3_ENA */ -#define WM5100_ISRC1_DEC4_ENA 0x0040 /* ISRC1_DEC4_ENA */ -#define WM5100_ISRC1_DEC4_ENA_MASK 0x0040 /* ISRC1_DEC4_ENA */ -#define WM5100_ISRC1_DEC4_ENA_SHIFT 6 /* ISRC1_DEC4_ENA */ -#define WM5100_ISRC1_DEC4_ENA_WIDTH 1 /* ISRC1_DEC4_ENA */ -#define WM5100_ISRC1_NOTCH_ENA 0x0001 /* ISRC1_NOTCH_ENA */ -#define WM5100_ISRC1_NOTCH_ENA_MASK 0x0001 /* ISRC1_NOTCH_ENA */ -#define WM5100_ISRC1_NOTCH_ENA_SHIFT 0 /* ISRC1_NOTCH_ENA */ -#define WM5100_ISRC1_NOTCH_ENA_WIDTH 1 /* ISRC1_NOTCH_ENA */ - -/* - * R323 (0x143) - ISRC 2 CTRL1 - */ -#define WM5100_ISRC2_DFS_ENA 0x2000 /* ISRC2_DFS_ENA */ -#define WM5100_ISRC2_DFS_ENA_MASK 0x2000 /* ISRC2_DFS_ENA */ -#define WM5100_ISRC2_DFS_ENA_SHIFT 13 /* ISRC2_DFS_ENA */ -#define WM5100_ISRC2_DFS_ENA_WIDTH 1 /* ISRC2_DFS_ENA */ -#define WM5100_ISRC2_CLK_SEL_MASK 0x0300 /* ISRC2_CLK_SEL - [9:8] */ -#define WM5100_ISRC2_CLK_SEL_SHIFT 8 /* ISRC2_CLK_SEL - [9:8] */ -#define WM5100_ISRC2_CLK_SEL_WIDTH 2 /* ISRC2_CLK_SEL - [9:8] */ -#define WM5100_ISRC2_FSH_MASK 0x000C /* ISRC2_FSH - [3:2] */ -#define WM5100_ISRC2_FSH_SHIFT 2 /* ISRC2_FSH - [3:2] */ -#define WM5100_ISRC2_FSH_WIDTH 2 /* ISRC2_FSH - [3:2] */ -#define WM5100_ISRC2_FSL_MASK 0x0003 /* ISRC2_FSL - [1:0] */ -#define WM5100_ISRC2_FSL_SHIFT 0 /* ISRC2_FSL - [1:0] */ -#define WM5100_ISRC2_FSL_WIDTH 2 /* ISRC2_FSL - [1:0] */ - -/* - * R324 (0x144) - ISRC 2 CTRL 2 - */ -#define WM5100_ISRC2_INT1_ENA 0x8000 /* ISRC2_INT1_ENA */ -#define WM5100_ISRC2_INT1_ENA_MASK 0x8000 /* ISRC2_INT1_ENA */ -#define WM5100_ISRC2_INT1_ENA_SHIFT 15 /* ISRC2_INT1_ENA */ -#define WM5100_ISRC2_INT1_ENA_WIDTH 1 /* ISRC2_INT1_ENA */ -#define WM5100_ISRC2_INT2_ENA 0x4000 /* ISRC2_INT2_ENA */ -#define WM5100_ISRC2_INT2_ENA_MASK 0x4000 /* ISRC2_INT2_ENA */ -#define WM5100_ISRC2_INT2_ENA_SHIFT 14 /* ISRC2_INT2_ENA */ -#define WM5100_ISRC2_INT2_ENA_WIDTH 1 /* ISRC2_INT2_ENA */ -#define WM5100_ISRC2_INT3_ENA 0x2000 /* ISRC2_INT3_ENA */ -#define WM5100_ISRC2_INT3_ENA_MASK 0x2000 /* ISRC2_INT3_ENA */ -#define WM5100_ISRC2_INT3_ENA_SHIFT 13 /* ISRC2_INT3_ENA */ -#define WM5100_ISRC2_INT3_ENA_WIDTH 1 /* ISRC2_INT3_ENA */ -#define WM5100_ISRC2_INT4_ENA 0x1000 /* ISRC2_INT4_ENA */ -#define WM5100_ISRC2_INT4_ENA_MASK 0x1000 /* ISRC2_INT4_ENA */ -#define WM5100_ISRC2_INT4_ENA_SHIFT 12 /* ISRC2_INT4_ENA */ -#define WM5100_ISRC2_INT4_ENA_WIDTH 1 /* ISRC2_INT4_ENA */ -#define WM5100_ISRC2_DEC1_ENA 0x0200 /* ISRC2_DEC1_ENA */ -#define WM5100_ISRC2_DEC1_ENA_MASK 0x0200 /* ISRC2_DEC1_ENA */ -#define WM5100_ISRC2_DEC1_ENA_SHIFT 9 /* ISRC2_DEC1_ENA */ -#define WM5100_ISRC2_DEC1_ENA_WIDTH 1 /* ISRC2_DEC1_ENA */ -#define WM5100_ISRC2_DEC2_ENA 0x0100 /* ISRC2_DEC2_ENA */ -#define WM5100_ISRC2_DEC2_ENA_MASK 0x0100 /* ISRC2_DEC2_ENA */ -#define WM5100_ISRC2_DEC2_ENA_SHIFT 8 /* ISRC2_DEC2_ENA */ -#define WM5100_ISRC2_DEC2_ENA_WIDTH 1 /* ISRC2_DEC2_ENA */ -#define WM5100_ISRC2_DEC3_ENA 0x0080 /* ISRC2_DEC3_ENA */ -#define WM5100_ISRC2_DEC3_ENA_MASK 0x0080 /* ISRC2_DEC3_ENA */ -#define WM5100_ISRC2_DEC3_ENA_SHIFT 7 /* ISRC2_DEC3_ENA */ -#define WM5100_ISRC2_DEC3_ENA_WIDTH 1 /* ISRC2_DEC3_ENA */ -#define WM5100_ISRC2_DEC4_ENA 0x0040 /* ISRC2_DEC4_ENA */ -#define WM5100_ISRC2_DEC4_ENA_MASK 0x0040 /* ISRC2_DEC4_ENA */ -#define WM5100_ISRC2_DEC4_ENA_SHIFT 6 /* ISRC2_DEC4_ENA */ -#define WM5100_ISRC2_DEC4_ENA_WIDTH 1 /* ISRC2_DEC4_ENA */ -#define WM5100_ISRC2_NOTCH_ENA 0x0001 /* ISRC2_NOTCH_ENA */ -#define WM5100_ISRC2_NOTCH_ENA_MASK 0x0001 /* ISRC2_NOTCH_ENA */ -#define WM5100_ISRC2_NOTCH_ENA_SHIFT 0 /* ISRC2_NOTCH_ENA */ -#define WM5100_ISRC2_NOTCH_ENA_WIDTH 1 /* ISRC2_NOTCH_ENA */ - -/* - * R386 (0x182) - FLL1 Control 1 - */ -#define WM5100_FLL1_ENA 0x0001 /* FLL1_ENA */ -#define WM5100_FLL1_ENA_MASK 0x0001 /* FLL1_ENA */ -#define WM5100_FLL1_ENA_SHIFT 0 /* FLL1_ENA */ -#define WM5100_FLL1_ENA_WIDTH 1 /* FLL1_ENA */ - -/* - * R387 (0x183) - FLL1 Control 2 - */ -#define WM5100_FLL1_OUTDIV_MASK 0x3F00 /* FLL1_OUTDIV - [13:8] */ -#define WM5100_FLL1_OUTDIV_SHIFT 8 /* FLL1_OUTDIV - [13:8] */ -#define WM5100_FLL1_OUTDIV_WIDTH 6 /* FLL1_OUTDIV - [13:8] */ -#define WM5100_FLL1_FRATIO_MASK 0x0007 /* FLL1_FRATIO - [2:0] */ -#define WM5100_FLL1_FRATIO_SHIFT 0 /* FLL1_FRATIO - [2:0] */ -#define WM5100_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [2:0] */ - -/* - * R388 (0x184) - FLL1 Control 3 - */ -#define WM5100_FLL1_THETA_MASK 0xFFFF /* FLL1_THETA - [15:0] */ -#define WM5100_FLL1_THETA_SHIFT 0 /* FLL1_THETA - [15:0] */ -#define WM5100_FLL1_THETA_WIDTH 16 /* FLL1_THETA - [15:0] */ - -/* - * R390 (0x186) - FLL1 Control 5 - */ -#define WM5100_FLL1_N_MASK 0x03FF /* FLL1_N - [9:0] */ -#define WM5100_FLL1_N_SHIFT 0 /* FLL1_N - [9:0] */ -#define WM5100_FLL1_N_WIDTH 10 /* FLL1_N - [9:0] */ - -/* - * R391 (0x187) - FLL1 Control 6 - */ -#define WM5100_FLL1_REFCLK_DIV_MASK 0x00C0 /* FLL1_REFCLK_DIV - [7:6] */ -#define WM5100_FLL1_REFCLK_DIV_SHIFT 6 /* FLL1_REFCLK_DIV - [7:6] */ -#define WM5100_FLL1_REFCLK_DIV_WIDTH 2 /* FLL1_REFCLK_DIV - [7:6] */ -#define WM5100_FLL1_REFCLK_SRC_MASK 0x000F /* FLL1_REFCLK_SRC - [3:0] */ -#define WM5100_FLL1_REFCLK_SRC_SHIFT 0 /* FLL1_REFCLK_SRC - [3:0] */ -#define WM5100_FLL1_REFCLK_SRC_WIDTH 4 /* FLL1_REFCLK_SRC - [3:0] */ - -/* - * R392 (0x188) - FLL1 EFS 1 - */ -#define WM5100_FLL1_LAMBDA_MASK 0xFFFF /* FLL1_LAMBDA - [15:0] */ -#define WM5100_FLL1_LAMBDA_SHIFT 0 /* FLL1_LAMBDA - [15:0] */ -#define WM5100_FLL1_LAMBDA_WIDTH 16 /* FLL1_LAMBDA - [15:0] */ - -/* - * R418 (0x1A2) - FLL2 Control 1 - */ -#define WM5100_FLL2_ENA 0x0001 /* FLL2_ENA */ -#define WM5100_FLL2_ENA_MASK 0x0001 /* FLL2_ENA */ -#define WM5100_FLL2_ENA_SHIFT 0 /* FLL2_ENA */ -#define WM5100_FLL2_ENA_WIDTH 1 /* FLL2_ENA */ - -/* - * R419 (0x1A3) - FLL2 Control 2 - */ -#define WM5100_FLL2_OUTDIV_MASK 0x3F00 /* FLL2_OUTDIV - [13:8] */ -#define WM5100_FLL2_OUTDIV_SHIFT 8 /* FLL2_OUTDIV - [13:8] */ -#define WM5100_FLL2_OUTDIV_WIDTH 6 /* FLL2_OUTDIV - [13:8] */ -#define WM5100_FLL2_FRATIO_MASK 0x0007 /* FLL2_FRATIO - [2:0] */ -#define WM5100_FLL2_FRATIO_SHIFT 0 /* FLL2_FRATIO - [2:0] */ -#define WM5100_FLL2_FRATIO_WIDTH 3 /* FLL2_FRATIO - [2:0] */ - -/* - * R420 (0x1A4) - FLL2 Control 3 - */ -#define WM5100_FLL2_THETA_MASK 0xFFFF /* FLL2_THETA - [15:0] */ -#define WM5100_FLL2_THETA_SHIFT 0 /* FLL2_THETA - [15:0] */ -#define WM5100_FLL2_THETA_WIDTH 16 /* FLL2_THETA - [15:0] */ - -/* - * R422 (0x1A6) - FLL2 Control 5 - */ -#define WM5100_FLL2_N_MASK 0x03FF /* FLL2_N - [9:0] */ -#define WM5100_FLL2_N_SHIFT 0 /* FLL2_N - [9:0] */ -#define WM5100_FLL2_N_WIDTH 10 /* FLL2_N - [9:0] */ - -/* - * R423 (0x1A7) - FLL2 Control 6 - */ -#define WM5100_FLL2_REFCLK_DIV_MASK 0x00C0 /* FLL2_REFCLK_DIV - [7:6] */ -#define WM5100_FLL2_REFCLK_DIV_SHIFT 6 /* FLL2_REFCLK_DIV - [7:6] */ -#define WM5100_FLL2_REFCLK_DIV_WIDTH 2 /* FLL2_REFCLK_DIV - [7:6] */ -#define WM5100_FLL2_REFCLK_SRC_MASK 0x000F /* FLL2_REFCLK_SRC - [3:0] */ -#define WM5100_FLL2_REFCLK_SRC_SHIFT 0 /* FLL2_REFCLK_SRC - [3:0] */ -#define WM5100_FLL2_REFCLK_SRC_WIDTH 4 /* FLL2_REFCLK_SRC - [3:0] */ - -/* - * R424 (0x1A8) - FLL2 EFS 1 - */ -#define WM5100_FLL2_LAMBDA_MASK 0xFFFF /* FLL2_LAMBDA - [15:0] */ -#define WM5100_FLL2_LAMBDA_SHIFT 0 /* FLL2_LAMBDA - [15:0] */ -#define WM5100_FLL2_LAMBDA_WIDTH 16 /* FLL2_LAMBDA - [15:0] */ - -/* - * R512 (0x200) - Mic Charge Pump 1 - */ -#define WM5100_CP2_BYPASS 0x0020 /* CP2_BYPASS */ -#define WM5100_CP2_BYPASS_MASK 0x0020 /* CP2_BYPASS */ -#define WM5100_CP2_BYPASS_SHIFT 5 /* CP2_BYPASS */ -#define WM5100_CP2_BYPASS_WIDTH 1 /* CP2_BYPASS */ -#define WM5100_CP2_ENA 0x0001 /* CP2_ENA */ -#define WM5100_CP2_ENA_MASK 0x0001 /* CP2_ENA */ -#define WM5100_CP2_ENA_SHIFT 0 /* CP2_ENA */ -#define WM5100_CP2_ENA_WIDTH 1 /* CP2_ENA */ - -/* - * R513 (0x201) - Mic Charge Pump 2 - */ -#define WM5100_LDO2_VSEL_MASK 0xF800 /* LDO2_VSEL - [15:11] */ -#define WM5100_LDO2_VSEL_SHIFT 11 /* LDO2_VSEL - [15:11] */ -#define WM5100_LDO2_VSEL_WIDTH 5 /* LDO2_VSEL - [15:11] */ - -/* - * R514 (0x202) - HP Charge Pump 1 - */ -#define WM5100_CP1_ENA 0x0001 /* CP1_ENA */ -#define WM5100_CP1_ENA_MASK 0x0001 /* CP1_ENA */ -#define WM5100_CP1_ENA_SHIFT 0 /* CP1_ENA */ -#define WM5100_CP1_ENA_WIDTH 1 /* CP1_ENA */ - -/* - * R529 (0x211) - LDO1 Control - */ -#define WM5100_LDO1_BYPASS 0x0002 /* LDO1_BYPASS */ -#define WM5100_LDO1_BYPASS_MASK 0x0002 /* LDO1_BYPASS */ -#define WM5100_LDO1_BYPASS_SHIFT 1 /* LDO1_BYPASS */ -#define WM5100_LDO1_BYPASS_WIDTH 1 /* LDO1_BYPASS */ - -/* - * R533 (0x215) - Mic Bias Ctrl 1 - */ -#define WM5100_MICB1_DISCH 0x0040 /* MICB1_DISCH */ -#define WM5100_MICB1_DISCH_MASK 0x0040 /* MICB1_DISCH */ -#define WM5100_MICB1_DISCH_SHIFT 6 /* MICB1_DISCH */ -#define WM5100_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */ -#define WM5100_MICB1_RATE 0x0020 /* MICB1_RATE */ -#define WM5100_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */ -#define WM5100_MICB1_RATE_SHIFT 5 /* MICB1_RATE */ -#define WM5100_MICB1_RATE_WIDTH 1 /* MICB1_RATE */ -#define WM5100_MICB1_LVL_MASK 0x001C /* MICB1_LVL - [4:2] */ -#define WM5100_MICB1_LVL_SHIFT 2 /* MICB1_LVL - [4:2] */ -#define WM5100_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [4:2] */ -#define WM5100_MICB1_BYPASS 0x0002 /* MICB1_BYPASS */ -#define WM5100_MICB1_BYPASS_MASK 0x0002 /* MICB1_BYPASS */ -#define WM5100_MICB1_BYPASS_SHIFT 1 /* MICB1_BYPASS */ -#define WM5100_MICB1_BYPASS_WIDTH 1 /* MICB1_BYPASS */ -#define WM5100_MICB1_ENA 0x0001 /* MICB1_ENA */ -#define WM5100_MICB1_ENA_MASK 0x0001 /* MICB1_ENA */ -#define WM5100_MICB1_ENA_SHIFT 0 /* MICB1_ENA */ -#define WM5100_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ - -/* - * R534 (0x216) - Mic Bias Ctrl 2 - */ -#define WM5100_MICB2_DISCH 0x0040 /* MICB2_DISCH */ -#define WM5100_MICB2_DISCH_MASK 0x0040 /* MICB2_DISCH */ -#define WM5100_MICB2_DISCH_SHIFT 6 /* MICB2_DISCH */ -#define WM5100_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ -#define WM5100_MICB2_RATE 0x0020 /* MICB2_RATE */ -#define WM5100_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */ -#define WM5100_MICB2_RATE_SHIFT 5 /* MICB2_RATE */ -#define WM5100_MICB2_RATE_WIDTH 1 /* MICB2_RATE */ -#define WM5100_MICB2_LVL_MASK 0x001C /* MICB2_LVL - [4:2] */ -#define WM5100_MICB2_LVL_SHIFT 2 /* MICB2_LVL - [4:2] */ -#define WM5100_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [4:2] */ -#define WM5100_MICB2_BYPASS 0x0002 /* MICB2_BYPASS */ -#define WM5100_MICB2_BYPASS_MASK 0x0002 /* MICB2_BYPASS */ -#define WM5100_MICB2_BYPASS_SHIFT 1 /* MICB2_BYPASS */ -#define WM5100_MICB2_BYPASS_WIDTH 1 /* MICB2_BYPASS */ -#define WM5100_MICB2_ENA 0x0001 /* MICB2_ENA */ -#define WM5100_MICB2_ENA_MASK 0x0001 /* MICB2_ENA */ -#define WM5100_MICB2_ENA_SHIFT 0 /* MICB2_ENA */ -#define WM5100_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ - -/* - * R535 (0x217) - Mic Bias Ctrl 3 - */ -#define WM5100_MICB3_DISCH 0x0040 /* MICB3_DISCH */ -#define WM5100_MICB3_DISCH_MASK 0x0040 /* MICB3_DISCH */ -#define WM5100_MICB3_DISCH_SHIFT 6 /* MICB3_DISCH */ -#define WM5100_MICB3_DISCH_WIDTH 1 /* MICB3_DISCH */ -#define WM5100_MICB3_RATE 0x0020 /* MICB3_RATE */ -#define WM5100_MICB3_RATE_MASK 0x0020 /* MICB3_RATE */ -#define WM5100_MICB3_RATE_SHIFT 5 /* MICB3_RATE */ -#define WM5100_MICB3_RATE_WIDTH 1 /* MICB3_RATE */ -#define WM5100_MICB3_LVL_MASK 0x001C /* MICB3_LVL - [4:2] */ -#define WM5100_MICB3_LVL_SHIFT 2 /* MICB3_LVL - [4:2] */ -#define WM5100_MICB3_LVL_WIDTH 3 /* MICB3_LVL - [4:2] */ -#define WM5100_MICB3_BYPASS 0x0002 /* MICB3_BYPASS */ -#define WM5100_MICB3_BYPASS_MASK 0x0002 /* MICB3_BYPASS */ -#define WM5100_MICB3_BYPASS_SHIFT 1 /* MICB3_BYPASS */ -#define WM5100_MICB3_BYPASS_WIDTH 1 /* MICB3_BYPASS */ -#define WM5100_MICB3_ENA 0x0001 /* MICB3_ENA */ -#define WM5100_MICB3_ENA_MASK 0x0001 /* MICB3_ENA */ -#define WM5100_MICB3_ENA_SHIFT 0 /* MICB3_ENA */ -#define WM5100_MICB3_ENA_WIDTH 1 /* MICB3_ENA */ - -/* - * R640 (0x280) - Accessory Detect Mode 1 - */ -#define WM5100_ACCDET_BIAS_SRC_MASK 0xC000 /* ACCDET_BIAS_SRC - [15:14] */ -#define WM5100_ACCDET_BIAS_SRC_SHIFT 14 /* ACCDET_BIAS_SRC - [15:14] */ -#define WM5100_ACCDET_BIAS_SRC_WIDTH 2 /* ACCDET_BIAS_SRC - [15:14] */ -#define WM5100_ACCDET_SRC 0x2000 /* ACCDET_SRC */ -#define WM5100_ACCDET_SRC_MASK 0x2000 /* ACCDET_SRC */ -#define WM5100_ACCDET_SRC_SHIFT 13 /* ACCDET_SRC */ -#define WM5100_ACCDET_SRC_WIDTH 1 /* ACCDET_SRC */ -#define WM5100_ACCDET_MODE_MASK 0x0003 /* ACCDET_MODE - [1:0] */ -#define WM5100_ACCDET_MODE_SHIFT 0 /* ACCDET_MODE - [1:0] */ -#define WM5100_ACCDET_MODE_WIDTH 2 /* ACCDET_MODE - [1:0] */ - -/* - * R648 (0x288) - Headphone Detect 1 - */ -#define WM5100_HP_HOLDTIME_MASK 0x00E0 /* HP_HOLDTIME - [7:5] */ -#define WM5100_HP_HOLDTIME_SHIFT 5 /* HP_HOLDTIME - [7:5] */ -#define WM5100_HP_HOLDTIME_WIDTH 3 /* HP_HOLDTIME - [7:5] */ -#define WM5100_HP_CLK_DIV_MASK 0x0018 /* HP_CLK_DIV - [4:3] */ -#define WM5100_HP_CLK_DIV_SHIFT 3 /* HP_CLK_DIV - [4:3] */ -#define WM5100_HP_CLK_DIV_WIDTH 2 /* HP_CLK_DIV - [4:3] */ -#define WM5100_HP_STEP_SIZE 0x0002 /* HP_STEP_SIZE */ -#define WM5100_HP_STEP_SIZE_MASK 0x0002 /* HP_STEP_SIZE */ -#define WM5100_HP_STEP_SIZE_SHIFT 1 /* HP_STEP_SIZE */ -#define WM5100_HP_STEP_SIZE_WIDTH 1 /* HP_STEP_SIZE */ -#define WM5100_HP_POLL 0x0001 /* HP_POLL */ -#define WM5100_HP_POLL_MASK 0x0001 /* HP_POLL */ -#define WM5100_HP_POLL_SHIFT 0 /* HP_POLL */ -#define WM5100_HP_POLL_WIDTH 1 /* HP_POLL */ - -/* - * R649 (0x289) - Headphone Detect 2 - */ -#define WM5100_HP_DONE 0x0080 /* HP_DONE */ -#define WM5100_HP_DONE_MASK 0x0080 /* HP_DONE */ -#define WM5100_HP_DONE_SHIFT 7 /* HP_DONE */ -#define WM5100_HP_DONE_WIDTH 1 /* HP_DONE */ -#define WM5100_HP_LVL_MASK 0x007F /* HP_LVL - [6:0] */ -#define WM5100_HP_LVL_SHIFT 0 /* HP_LVL - [6:0] */ -#define WM5100_HP_LVL_WIDTH 7 /* HP_LVL - [6:0] */ - -/* - * R656 (0x290) - Mic Detect 1 - */ -#define WM5100_ACCDET_BIAS_STARTTIME_MASK 0xF000 /* ACCDET_BIAS_STARTTIME - [15:12] */ -#define WM5100_ACCDET_BIAS_STARTTIME_SHIFT 12 /* ACCDET_BIAS_STARTTIME - [15:12] */ -#define WM5100_ACCDET_BIAS_STARTTIME_WIDTH 4 /* ACCDET_BIAS_STARTTIME - [15:12] */ -#define WM5100_ACCDET_RATE_MASK 0x0F00 /* ACCDET_RATE - [11:8] */ -#define WM5100_ACCDET_RATE_SHIFT 8 /* ACCDET_RATE - [11:8] */ -#define WM5100_ACCDET_RATE_WIDTH 4 /* ACCDET_RATE - [11:8] */ -#define WM5100_ACCDET_DBTIME 0x0002 /* ACCDET_DBTIME */ -#define WM5100_ACCDET_DBTIME_MASK 0x0002 /* ACCDET_DBTIME */ -#define WM5100_ACCDET_DBTIME_SHIFT 1 /* ACCDET_DBTIME */ -#define WM5100_ACCDET_DBTIME_WIDTH 1 /* ACCDET_DBTIME */ -#define WM5100_ACCDET_ENA 0x0001 /* ACCDET_ENA */ -#define WM5100_ACCDET_ENA_MASK 0x0001 /* ACCDET_ENA */ -#define WM5100_ACCDET_ENA_SHIFT 0 /* ACCDET_ENA */ -#define WM5100_ACCDET_ENA_WIDTH 1 /* ACCDET_ENA */ - -/* - * R657 (0x291) - Mic Detect 2 - */ -#define WM5100_ACCDET_LVL_SEL_MASK 0x00FF /* ACCDET_LVL_SEL - [7:0] */ -#define WM5100_ACCDET_LVL_SEL_SHIFT 0 /* ACCDET_LVL_SEL - [7:0] */ -#define WM5100_ACCDET_LVL_SEL_WIDTH 8 /* ACCDET_LVL_SEL - [7:0] */ - -/* - * R658 (0x292) - Mic Detect 3 - */ -#define WM5100_ACCDET_LVL_MASK 0x07FC /* ACCDET_LVL - [10:2] */ -#define WM5100_ACCDET_LVL_SHIFT 2 /* ACCDET_LVL - [10:2] */ -#define WM5100_ACCDET_LVL_WIDTH 9 /* ACCDET_LVL - [10:2] */ -#define WM5100_ACCDET_VALID 0x0002 /* ACCDET_VALID */ -#define WM5100_ACCDET_VALID_MASK 0x0002 /* ACCDET_VALID */ -#define WM5100_ACCDET_VALID_SHIFT 1 /* ACCDET_VALID */ -#define WM5100_ACCDET_VALID_WIDTH 1 /* ACCDET_VALID */ -#define WM5100_ACCDET_STS 0x0001 /* ACCDET_STS */ -#define WM5100_ACCDET_STS_MASK 0x0001 /* ACCDET_STS */ -#define WM5100_ACCDET_STS_SHIFT 0 /* ACCDET_STS */ -#define WM5100_ACCDET_STS_WIDTH 1 /* ACCDET_STS */ - -/* - * R699 (0x2BB) - Misc Control - */ -#define WM5100_HPCOM_SRC 0x200 /* HPCOM_SRC */ -#define WM5100_HPCOM_SRC_SHIFT 9 /* HPCOM_SRC */ - -/* - * R769 (0x301) - Input Enables - */ -#define WM5100_IN4L_ENA 0x0080 /* IN4L_ENA */ -#define WM5100_IN4L_ENA_MASK 0x0080 /* IN4L_ENA */ -#define WM5100_IN4L_ENA_SHIFT 7 /* IN4L_ENA */ -#define WM5100_IN4L_ENA_WIDTH 1 /* IN4L_ENA */ -#define WM5100_IN4R_ENA 0x0040 /* IN4R_ENA */ -#define WM5100_IN4R_ENA_MASK 0x0040 /* IN4R_ENA */ -#define WM5100_IN4R_ENA_SHIFT 6 /* IN4R_ENA */ -#define WM5100_IN4R_ENA_WIDTH 1 /* IN4R_ENA */ -#define WM5100_IN3L_ENA 0x0020 /* IN3L_ENA */ -#define WM5100_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */ -#define WM5100_IN3L_ENA_SHIFT 5 /* IN3L_ENA */ -#define WM5100_IN3L_ENA_WIDTH 1 /* IN3L_ENA */ -#define WM5100_IN3R_ENA 0x0010 /* IN3R_ENA */ -#define WM5100_IN3R_ENA_MASK 0x0010 /* IN3R_ENA */ -#define WM5100_IN3R_ENA_SHIFT 4 /* IN3R_ENA */ -#define WM5100_IN3R_ENA_WIDTH 1 /* IN3R_ENA */ -#define WM5100_IN2L_ENA 0x0008 /* IN2L_ENA */ -#define WM5100_IN2L_ENA_MASK 0x0008 /* IN2L_ENA */ -#define WM5100_IN2L_ENA_SHIFT 3 /* IN2L_ENA */ -#define WM5100_IN2L_ENA_WIDTH 1 /* IN2L_ENA */ -#define WM5100_IN2R_ENA 0x0004 /* IN2R_ENA */ -#define WM5100_IN2R_ENA_MASK 0x0004 /* IN2R_ENA */ -#define WM5100_IN2R_ENA_SHIFT 2 /* IN2R_ENA */ -#define WM5100_IN2R_ENA_WIDTH 1 /* IN2R_ENA */ -#define WM5100_IN1L_ENA 0x0002 /* IN1L_ENA */ -#define WM5100_IN1L_ENA_MASK 0x0002 /* IN1L_ENA */ -#define WM5100_IN1L_ENA_SHIFT 1 /* IN1L_ENA */ -#define WM5100_IN1L_ENA_WIDTH 1 /* IN1L_ENA */ -#define WM5100_IN1R_ENA 0x0001 /* IN1R_ENA */ -#define WM5100_IN1R_ENA_MASK 0x0001 /* IN1R_ENA */ -#define WM5100_IN1R_ENA_SHIFT 0 /* IN1R_ENA */ -#define WM5100_IN1R_ENA_WIDTH 1 /* IN1R_ENA */ - -/* - * R770 (0x302) - Input Enables Status - */ -#define WM5100_IN4L_ENA_STS 0x0080 /* IN4L_ENA_STS */ -#define WM5100_IN4L_ENA_STS_MASK 0x0080 /* IN4L_ENA_STS */ -#define WM5100_IN4L_ENA_STS_SHIFT 7 /* IN4L_ENA_STS */ -#define WM5100_IN4L_ENA_STS_WIDTH 1 /* IN4L_ENA_STS */ -#define WM5100_IN4R_ENA_STS 0x0040 /* IN4R_ENA_STS */ -#define WM5100_IN4R_ENA_STS_MASK 0x0040 /* IN4R_ENA_STS */ -#define WM5100_IN4R_ENA_STS_SHIFT 6 /* IN4R_ENA_STS */ -#define WM5100_IN4R_ENA_STS_WIDTH 1 /* IN4R_ENA_STS */ -#define WM5100_IN3L_ENA_STS 0x0020 /* IN3L_ENA_STS */ -#define WM5100_IN3L_ENA_STS_MASK 0x0020 /* IN3L_ENA_STS */ -#define WM5100_IN3L_ENA_STS_SHIFT 5 /* IN3L_ENA_STS */ -#define WM5100_IN3L_ENA_STS_WIDTH 1 /* IN3L_ENA_STS */ -#define WM5100_IN3R_ENA_STS 0x0010 /* IN3R_ENA_STS */ -#define WM5100_IN3R_ENA_STS_MASK 0x0010 /* IN3R_ENA_STS */ -#define WM5100_IN3R_ENA_STS_SHIFT 4 /* IN3R_ENA_STS */ -#define WM5100_IN3R_ENA_STS_WIDTH 1 /* IN3R_ENA_STS */ -#define WM5100_IN2L_ENA_STS 0x0008 /* IN2L_ENA_STS */ -#define WM5100_IN2L_ENA_STS_MASK 0x0008 /* IN2L_ENA_STS */ -#define WM5100_IN2L_ENA_STS_SHIFT 3 /* IN2L_ENA_STS */ -#define WM5100_IN2L_ENA_STS_WIDTH 1 /* IN2L_ENA_STS */ -#define WM5100_IN2R_ENA_STS 0x0004 /* IN2R_ENA_STS */ -#define WM5100_IN2R_ENA_STS_MASK 0x0004 /* IN2R_ENA_STS */ -#define WM5100_IN2R_ENA_STS_SHIFT 2 /* IN2R_ENA_STS */ -#define WM5100_IN2R_ENA_STS_WIDTH 1 /* IN2R_ENA_STS */ -#define WM5100_IN1L_ENA_STS 0x0002 /* IN1L_ENA_STS */ -#define WM5100_IN1L_ENA_STS_MASK 0x0002 /* IN1L_ENA_STS */ -#define WM5100_IN1L_ENA_STS_SHIFT 1 /* IN1L_ENA_STS */ -#define WM5100_IN1L_ENA_STS_WIDTH 1 /* IN1L_ENA_STS */ -#define WM5100_IN1R_ENA_STS 0x0001 /* IN1R_ENA_STS */ -#define WM5100_IN1R_ENA_STS_MASK 0x0001 /* IN1R_ENA_STS */ -#define WM5100_IN1R_ENA_STS_SHIFT 0 /* IN1R_ENA_STS */ -#define WM5100_IN1R_ENA_STS_WIDTH 1 /* IN1R_ENA_STS */ - -/* - * R784 (0x310) - IN1L Control - */ -#define WM5100_IN_RATE_MASK 0xC000 /* IN_RATE - [15:14] */ -#define WM5100_IN_RATE_SHIFT 14 /* IN_RATE - [15:14] */ -#define WM5100_IN_RATE_WIDTH 2 /* IN_RATE - [15:14] */ -#define WM5100_IN1_OSR 0x2000 /* IN1_OSR */ -#define WM5100_IN1_OSR_MASK 0x2000 /* IN1_OSR */ -#define WM5100_IN1_OSR_SHIFT 13 /* IN1_OSR */ -#define WM5100_IN1_OSR_WIDTH 1 /* IN1_OSR */ -#define WM5100_IN1_DMIC_SUP_MASK 0x1800 /* IN1_DMIC_SUP - [12:11] */ -#define WM5100_IN1_DMIC_SUP_SHIFT 11 /* IN1_DMIC_SUP - [12:11] */ -#define WM5100_IN1_DMIC_SUP_WIDTH 2 /* IN1_DMIC_SUP - [12:11] */ -#define WM5100_IN1_MODE_MASK 0x0600 /* IN1_MODE - [10:9] */ -#define WM5100_IN1_MODE_SHIFT 9 /* IN1_MODE - [10:9] */ -#define WM5100_IN1_MODE_WIDTH 2 /* IN1_MODE - [10:9] */ -#define WM5100_IN1L_PGA_VOL_MASK 0x00FE /* IN1L_PGA_VOL - [7:1] */ -#define WM5100_IN1L_PGA_VOL_SHIFT 1 /* IN1L_PGA_VOL - [7:1] */ -#define WM5100_IN1L_PGA_VOL_WIDTH 7 /* IN1L_PGA_VOL - [7:1] */ - -/* - * R785 (0x311) - IN1R Control - */ -#define WM5100_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */ -#define WM5100_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */ -#define WM5100_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */ - -/* - * R786 (0x312) - IN2L Control - */ -#define WM5100_IN2_OSR 0x2000 /* IN2_OSR */ -#define WM5100_IN2_OSR_MASK 0x2000 /* IN2_OSR */ -#define WM5100_IN2_OSR_SHIFT 13 /* IN2_OSR */ -#define WM5100_IN2_OSR_WIDTH 1 /* IN2_OSR */ -#define WM5100_IN2_DMIC_SUP_MASK 0x1800 /* IN2_DMIC_SUP - [12:11] */ -#define WM5100_IN2_DMIC_SUP_SHIFT 11 /* IN2_DMIC_SUP - [12:11] */ -#define WM5100_IN2_DMIC_SUP_WIDTH 2 /* IN2_DMIC_SUP - [12:11] */ -#define WM5100_IN2_MODE_MASK 0x0600 /* IN2_MODE - [10:9] */ -#define WM5100_IN2_MODE_SHIFT 9 /* IN2_MODE - [10:9] */ -#define WM5100_IN2_MODE_WIDTH 2 /* IN2_MODE - [10:9] */ -#define WM5100_IN2L_PGA_VOL_MASK 0x00FE /* IN2L_PGA_VOL - [7:1] */ -#define WM5100_IN2L_PGA_VOL_SHIFT 1 /* IN2L_PGA_VOL - [7:1] */ -#define WM5100_IN2L_PGA_VOL_WIDTH 7 /* IN2L_PGA_VOL - [7:1] */ - -/* - * R787 (0x313) - IN2R Control - */ -#define WM5100_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */ -#define WM5100_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */ -#define WM5100_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */ - -/* - * R788 (0x314) - IN3L Control - */ -#define WM5100_IN3_OSR 0x2000 /* IN3_OSR */ -#define WM5100_IN3_OSR_MASK 0x2000 /* IN3_OSR */ -#define WM5100_IN3_OSR_SHIFT 13 /* IN3_OSR */ -#define WM5100_IN3_OSR_WIDTH 1 /* IN3_OSR */ -#define WM5100_IN3_DMIC_SUP_MASK 0x1800 /* IN3_DMIC_SUP - [12:11] */ -#define WM5100_IN3_DMIC_SUP_SHIFT 11 /* IN3_DMIC_SUP - [12:11] */ -#define WM5100_IN3_DMIC_SUP_WIDTH 2 /* IN3_DMIC_SUP - [12:11] */ -#define WM5100_IN3_MODE_MASK 0x0600 /* IN3_MODE - [10:9] */ -#define WM5100_IN3_MODE_SHIFT 9 /* IN3_MODE - [10:9] */ -#define WM5100_IN3_MODE_WIDTH 2 /* IN3_MODE - [10:9] */ -#define WM5100_IN3L_PGA_VOL_MASK 0x00FE /* IN3L_PGA_VOL - [7:1] */ -#define WM5100_IN3L_PGA_VOL_SHIFT 1 /* IN3L_PGA_VOL - [7:1] */ -#define WM5100_IN3L_PGA_VOL_WIDTH 7 /* IN3L_PGA_VOL - [7:1] */ - -/* - * R789 (0x315) - IN3R Control - */ -#define WM5100_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */ -#define WM5100_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */ -#define WM5100_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */ - -/* - * R790 (0x316) - IN4L Control - */ -#define WM5100_IN4_OSR 0x2000 /* IN4_OSR */ -#define WM5100_IN4_OSR_MASK 0x2000 /* IN4_OSR */ -#define WM5100_IN4_OSR_SHIFT 13 /* IN4_OSR */ -#define WM5100_IN4_OSR_WIDTH 1 /* IN4_OSR */ -#define WM5100_IN4_DMIC_SUP_MASK 0x1800 /* IN4_DMIC_SUP - [12:11] */ -#define WM5100_IN4_DMIC_SUP_SHIFT 11 /* IN4_DMIC_SUP - [12:11] */ -#define WM5100_IN4_DMIC_SUP_WIDTH 2 /* IN4_DMIC_SUP - [12:11] */ -#define WM5100_IN4_MODE_MASK 0x0600 /* IN4_MODE - [10:9] */ -#define WM5100_IN4_MODE_SHIFT 9 /* IN4_MODE - [10:9] */ -#define WM5100_IN4_MODE_WIDTH 2 /* IN4_MODE - [10:9] */ -#define WM5100_IN4L_PGA_VOL_MASK 0x00FE /* IN4L_PGA_VOL - [7:1] */ -#define WM5100_IN4L_PGA_VOL_SHIFT 1 /* IN4L_PGA_VOL - [7:1] */ -#define WM5100_IN4L_PGA_VOL_WIDTH 7 /* IN4L_PGA_VOL - [7:1] */ - -/* - * R791 (0x317) - IN4R Control - */ -#define WM5100_IN4R_PGA_VOL_MASK 0x00FE /* IN4R_PGA_VOL - [7:1] */ -#define WM5100_IN4R_PGA_VOL_SHIFT 1 /* IN4R_PGA_VOL - [7:1] */ -#define WM5100_IN4R_PGA_VOL_WIDTH 7 /* IN4R_PGA_VOL - [7:1] */ - -/* - * R792 (0x318) - RXANC_SRC - */ -#define WM5100_IN_RXANC_SEL_MASK 0x0007 /* IN_RXANC_SEL - [2:0] */ -#define WM5100_IN_RXANC_SEL_SHIFT 0 /* IN_RXANC_SEL - [2:0] */ -#define WM5100_IN_RXANC_SEL_WIDTH 3 /* IN_RXANC_SEL - [2:0] */ - -/* - * R793 (0x319) - Input Volume Ramp - */ -#define WM5100_IN_VD_RAMP_MASK 0x0070 /* IN_VD_RAMP - [6:4] */ -#define WM5100_IN_VD_RAMP_SHIFT 4 /* IN_VD_RAMP - [6:4] */ -#define WM5100_IN_VD_RAMP_WIDTH 3 /* IN_VD_RAMP - [6:4] */ -#define WM5100_IN_VI_RAMP_MASK 0x0007 /* IN_VI_RAMP - [2:0] */ -#define WM5100_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */ -#define WM5100_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */ - -/* - * R800 (0x320) - ADC Digital Volume 1L - */ -#define WM5100_IN_VU 0x0200 /* IN_VU */ -#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ -#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ -#define WM5100_IN1L_MUTE 0x0100 /* IN1L_MUTE */ -#define WM5100_IN1L_MUTE_MASK 0x0100 /* IN1L_MUTE */ -#define WM5100_IN1L_MUTE_SHIFT 8 /* IN1L_MUTE */ -#define WM5100_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */ -#define WM5100_IN1L_VOL_MASK 0x00FF /* IN1L_VOL - [7:0] */ -#define WM5100_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [7:0] */ -#define WM5100_IN1L_VOL_WIDTH 8 /* IN1L_VOL - [7:0] */ - -/* - * R801 (0x321) - ADC Digital Volume 1R - */ -#define WM5100_IN_VU 0x0200 /* IN_VU */ -#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ -#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ -#define WM5100_IN1R_MUTE 0x0100 /* IN1R_MUTE */ -#define WM5100_IN1R_MUTE_MASK 0x0100 /* IN1R_MUTE */ -#define WM5100_IN1R_MUTE_SHIFT 8 /* IN1R_MUTE */ -#define WM5100_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */ -#define WM5100_IN1R_VOL_MASK 0x00FF /* IN1R_VOL - [7:0] */ -#define WM5100_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [7:0] */ -#define WM5100_IN1R_VOL_WIDTH 8 /* IN1R_VOL - [7:0] */ - -/* - * R802 (0x322) - ADC Digital Volume 2L - */ -#define WM5100_IN_VU 0x0200 /* IN_VU */ -#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ -#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ -#define WM5100_IN2L_MUTE 0x0100 /* IN2L_MUTE */ -#define WM5100_IN2L_MUTE_MASK 0x0100 /* IN2L_MUTE */ -#define WM5100_IN2L_MUTE_SHIFT 8 /* IN2L_MUTE */ -#define WM5100_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */ -#define WM5100_IN2L_VOL_MASK 0x00FF /* IN2L_VOL - [7:0] */ -#define WM5100_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [7:0] */ -#define WM5100_IN2L_VOL_WIDTH 8 /* IN2L_VOL - [7:0] */ - -/* - * R803 (0x323) - ADC Digital Volume 2R - */ -#define WM5100_IN_VU 0x0200 /* IN_VU */ -#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ -#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ -#define WM5100_IN2R_MUTE 0x0100 /* IN2R_MUTE */ -#define WM5100_IN2R_MUTE_MASK 0x0100 /* IN2R_MUTE */ -#define WM5100_IN2R_MUTE_SHIFT 8 /* IN2R_MUTE */ -#define WM5100_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */ -#define WM5100_IN2R_VOL_MASK 0x00FF /* IN2R_VOL - [7:0] */ -#define WM5100_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [7:0] */ -#define WM5100_IN2R_VOL_WIDTH 8 /* IN2R_VOL - [7:0] */ - -/* - * R804 (0x324) - ADC Digital Volume 3L - */ -#define WM5100_IN_VU 0x0200 /* IN_VU */ -#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ -#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ -#define WM5100_IN3L_MUTE 0x0100 /* IN3L_MUTE */ -#define WM5100_IN3L_MUTE_MASK 0x0100 /* IN3L_MUTE */ -#define WM5100_IN3L_MUTE_SHIFT 8 /* IN3L_MUTE */ -#define WM5100_IN3L_MUTE_WIDTH 1 /* IN3L_MUTE */ -#define WM5100_IN3L_VOL_MASK 0x00FF /* IN3L_VOL - [7:0] */ -#define WM5100_IN3L_VOL_SHIFT 0 /* IN3L_VOL - [7:0] */ -#define WM5100_IN3L_VOL_WIDTH 8 /* IN3L_VOL - [7:0] */ - -/* - * R805 (0x325) - ADC Digital Volume 3R - */ -#define WM5100_IN_VU 0x0200 /* IN_VU */ -#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ -#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ -#define WM5100_IN3R_MUTE 0x0100 /* IN3R_MUTE */ -#define WM5100_IN3R_MUTE_MASK 0x0100 /* IN3R_MUTE */ -#define WM5100_IN3R_MUTE_SHIFT 8 /* IN3R_MUTE */ -#define WM5100_IN3R_MUTE_WIDTH 1 /* IN3R_MUTE */ -#define WM5100_IN3R_VOL_MASK 0x00FF /* IN3R_VOL - [7:0] */ -#define WM5100_IN3R_VOL_SHIFT 0 /* IN3R_VOL - [7:0] */ -#define WM5100_IN3R_VOL_WIDTH 8 /* IN3R_VOL - [7:0] */ - -/* - * R806 (0x326) - ADC Digital Volume 4L - */ -#define WM5100_IN_VU 0x0200 /* IN_VU */ -#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ -#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ -#define WM5100_IN4L_MUTE 0x0100 /* IN4L_MUTE */ -#define WM5100_IN4L_MUTE_MASK 0x0100 /* IN4L_MUTE */ -#define WM5100_IN4L_MUTE_SHIFT 8 /* IN4L_MUTE */ -#define WM5100_IN4L_MUTE_WIDTH 1 /* IN4L_MUTE */ -#define WM5100_IN4L_VOL_MASK 0x00FF /* IN4L_VOL - [7:0] */ -#define WM5100_IN4L_VOL_SHIFT 0 /* IN4L_VOL - [7:0] */ -#define WM5100_IN4L_VOL_WIDTH 8 /* IN4L_VOL - [7:0] */ - -/* - * R807 (0x327) - ADC Digital Volume 4R - */ -#define WM5100_IN_VU 0x0200 /* IN_VU */ -#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */ -#define WM5100_IN_VU_SHIFT 9 /* IN_VU */ -#define WM5100_IN_VU_WIDTH 1 /* IN_VU */ -#define WM5100_IN4R_MUTE 0x0100 /* IN4R_MUTE */ -#define WM5100_IN4R_MUTE_MASK 0x0100 /* IN4R_MUTE */ -#define WM5100_IN4R_MUTE_SHIFT 8 /* IN4R_MUTE */ -#define WM5100_IN4R_MUTE_WIDTH 1 /* IN4R_MUTE */ -#define WM5100_IN4R_VOL_MASK 0x00FF /* IN4R_VOL - [7:0] */ -#define WM5100_IN4R_VOL_SHIFT 0 /* IN4R_VOL - [7:0] */ -#define WM5100_IN4R_VOL_WIDTH 8 /* IN4R_VOL - [7:0] */ - -/* - * R1025 (0x401) - Output Enables 2 - */ -#define WM5100_OUT6L_ENA 0x0800 /* OUT6L_ENA */ -#define WM5100_OUT6L_ENA_MASK 0x0800 /* OUT6L_ENA */ -#define WM5100_OUT6L_ENA_SHIFT 11 /* OUT6L_ENA */ -#define WM5100_OUT6L_ENA_WIDTH 1 /* OUT6L_ENA */ -#define WM5100_OUT6R_ENA 0x0400 /* OUT6R_ENA */ -#define WM5100_OUT6R_ENA_MASK 0x0400 /* OUT6R_ENA */ -#define WM5100_OUT6R_ENA_SHIFT 10 /* OUT6R_ENA */ -#define WM5100_OUT6R_ENA_WIDTH 1 /* OUT6R_ENA */ -#define WM5100_OUT5L_ENA 0x0200 /* OUT5L_ENA */ -#define WM5100_OUT5L_ENA_MASK 0x0200 /* OUT5L_ENA */ -#define WM5100_OUT5L_ENA_SHIFT 9 /* OUT5L_ENA */ -#define WM5100_OUT5L_ENA_WIDTH 1 /* OUT5L_ENA */ -#define WM5100_OUT5R_ENA 0x0100 /* OUT5R_ENA */ -#define WM5100_OUT5R_ENA_MASK 0x0100 /* OUT5R_ENA */ -#define WM5100_OUT5R_ENA_SHIFT 8 /* OUT5R_ENA */ -#define WM5100_OUT5R_ENA_WIDTH 1 /* OUT5R_ENA */ -#define WM5100_OUT4L_ENA 0x0080 /* OUT4L_ENA */ -#define WM5100_OUT4L_ENA_MASK 0x0080 /* OUT4L_ENA */ -#define WM5100_OUT4L_ENA_SHIFT 7 /* OUT4L_ENA */ -#define WM5100_OUT4L_ENA_WIDTH 1 /* OUT4L_ENA */ -#define WM5100_OUT4R_ENA 0x0040 /* OUT4R_ENA */ -#define WM5100_OUT4R_ENA_MASK 0x0040 /* OUT4R_ENA */ -#define WM5100_OUT4R_ENA_SHIFT 6 /* OUT4R_ENA */ -#define WM5100_OUT4R_ENA_WIDTH 1 /* OUT4R_ENA */ - -/* - * R1026 (0x402) - Output Status 1 - */ -#define WM5100_OUT3L_ENA_STS 0x0020 /* OUT3L_ENA_STS */ -#define WM5100_OUT3L_ENA_STS_MASK 0x0020 /* OUT3L_ENA_STS */ -#define WM5100_OUT3L_ENA_STS_SHIFT 5 /* OUT3L_ENA_STS */ -#define WM5100_OUT3L_ENA_STS_WIDTH 1 /* OUT3L_ENA_STS */ -#define WM5100_OUT3R_ENA_STS 0x0010 /* OUT3R_ENA_STS */ -#define WM5100_OUT3R_ENA_STS_MASK 0x0010 /* OUT3R_ENA_STS */ -#define WM5100_OUT3R_ENA_STS_SHIFT 4 /* OUT3R_ENA_STS */ -#define WM5100_OUT3R_ENA_STS_WIDTH 1 /* OUT3R_ENA_STS */ -#define WM5100_OUT2L_ENA_STS 0x0008 /* OUT2L_ENA_STS */ -#define WM5100_OUT2L_ENA_STS_MASK 0x0008 /* OUT2L_ENA_STS */ -#define WM5100_OUT2L_ENA_STS_SHIFT 3 /* OUT2L_ENA_STS */ -#define WM5100_OUT2L_ENA_STS_WIDTH 1 /* OUT2L_ENA_STS */ -#define WM5100_OUT2R_ENA_STS 0x0004 /* OUT2R_ENA_STS */ -#define WM5100_OUT2R_ENA_STS_MASK 0x0004 /* OUT2R_ENA_STS */ -#define WM5100_OUT2R_ENA_STS_SHIFT 2 /* OUT2R_ENA_STS */ -#define WM5100_OUT2R_ENA_STS_WIDTH 1 /* OUT2R_ENA_STS */ -#define WM5100_OUT1L_ENA_STS 0x0002 /* OUT1L_ENA_STS */ -#define WM5100_OUT1L_ENA_STS_MASK 0x0002 /* OUT1L_ENA_STS */ -#define WM5100_OUT1L_ENA_STS_SHIFT 1 /* OUT1L_ENA_STS */ -#define WM5100_OUT1L_ENA_STS_WIDTH 1 /* OUT1L_ENA_STS */ -#define WM5100_OUT1R_ENA_STS 0x0001 /* OUT1R_ENA_STS */ -#define WM5100_OUT1R_ENA_STS_MASK 0x0001 /* OUT1R_ENA_STS */ -#define WM5100_OUT1R_ENA_STS_SHIFT 0 /* OUT1R_ENA_STS */ -#define WM5100_OUT1R_ENA_STS_WIDTH 1 /* OUT1R_ENA_STS */ - -/* - * R1027 (0x403) - Output Status 2 - */ -#define WM5100_OUT6L_ENA_STS 0x0800 /* OUT6L_ENA_STS */ -#define WM5100_OUT6L_ENA_STS_MASK 0x0800 /* OUT6L_ENA_STS */ -#define WM5100_OUT6L_ENA_STS_SHIFT 11 /* OUT6L_ENA_STS */ -#define WM5100_OUT6L_ENA_STS_WIDTH 1 /* OUT6L_ENA_STS */ -#define WM5100_OUT6R_ENA_STS 0x0400 /* OUT6R_ENA_STS */ -#define WM5100_OUT6R_ENA_STS_MASK 0x0400 /* OUT6R_ENA_STS */ -#define WM5100_OUT6R_ENA_STS_SHIFT 10 /* OUT6R_ENA_STS */ -#define WM5100_OUT6R_ENA_STS_WIDTH 1 /* OUT6R_ENA_STS */ -#define WM5100_OUT5L_ENA_STS 0x0200 /* OUT5L_ENA_STS */ -#define WM5100_OUT5L_ENA_STS_MASK 0x0200 /* OUT5L_ENA_STS */ -#define WM5100_OUT5L_ENA_STS_SHIFT 9 /* OUT5L_ENA_STS */ -#define WM5100_OUT5L_ENA_STS_WIDTH 1 /* OUT5L_ENA_STS */ -#define WM5100_OUT5R_ENA_STS 0x0100 /* OUT5R_ENA_STS */ -#define WM5100_OUT5R_ENA_STS_MASK 0x0100 /* OUT5R_ENA_STS */ -#define WM5100_OUT5R_ENA_STS_SHIFT 8 /* OUT5R_ENA_STS */ -#define WM5100_OUT5R_ENA_STS_WIDTH 1 /* OUT5R_ENA_STS */ -#define WM5100_OUT4L_ENA_STS 0x0080 /* OUT4L_ENA_STS */ -#define WM5100_OUT4L_ENA_STS_MASK 0x0080 /* OUT4L_ENA_STS */ -#define WM5100_OUT4L_ENA_STS_SHIFT 7 /* OUT4L_ENA_STS */ -#define WM5100_OUT4L_ENA_STS_WIDTH 1 /* OUT4L_ENA_STS */ -#define WM5100_OUT4R_ENA_STS 0x0040 /* OUT4R_ENA_STS */ -#define WM5100_OUT4R_ENA_STS_MASK 0x0040 /* OUT4R_ENA_STS */ -#define WM5100_OUT4R_ENA_STS_SHIFT 6 /* OUT4R_ENA_STS */ -#define WM5100_OUT4R_ENA_STS_WIDTH 1 /* OUT4R_ENA_STS */ - -/* - * R1032 (0x408) - Channel Enables 1 - */ -#define WM5100_HP3L_ENA 0x0020 /* HP3L_ENA */ -#define WM5100_HP3L_ENA_MASK 0x0020 /* HP3L_ENA */ -#define WM5100_HP3L_ENA_SHIFT 5 /* HP3L_ENA */ -#define WM5100_HP3L_ENA_WIDTH 1 /* HP3L_ENA */ -#define WM5100_HP3R_ENA 0x0010 /* HP3R_ENA */ -#define WM5100_HP3R_ENA_MASK 0x0010 /* HP3R_ENA */ -#define WM5100_HP3R_ENA_SHIFT 4 /* HP3R_ENA */ -#define WM5100_HP3R_ENA_WIDTH 1 /* HP3R_ENA */ -#define WM5100_HP2L_ENA 0x0008 /* HP2L_ENA */ -#define WM5100_HP2L_ENA_MASK 0x0008 /* HP2L_ENA */ -#define WM5100_HP2L_ENA_SHIFT 3 /* HP2L_ENA */ -#define WM5100_HP2L_ENA_WIDTH 1 /* HP2L_ENA */ -#define WM5100_HP2R_ENA 0x0004 /* HP2R_ENA */ -#define WM5100_HP2R_ENA_MASK 0x0004 /* HP2R_ENA */ -#define WM5100_HP2R_ENA_SHIFT 2 /* HP2R_ENA */ -#define WM5100_HP2R_ENA_WIDTH 1 /* HP2R_ENA */ -#define WM5100_HP1L_ENA 0x0002 /* HP1L_ENA */ -#define WM5100_HP1L_ENA_MASK 0x0002 /* HP1L_ENA */ -#define WM5100_HP1L_ENA_SHIFT 1 /* HP1L_ENA */ -#define WM5100_HP1L_ENA_WIDTH 1 /* HP1L_ENA */ -#define WM5100_HP1R_ENA 0x0001 /* HP1R_ENA */ -#define WM5100_HP1R_ENA_MASK 0x0001 /* HP1R_ENA */ -#define WM5100_HP1R_ENA_SHIFT 0 /* HP1R_ENA */ -#define WM5100_HP1R_ENA_WIDTH 1 /* HP1R_ENA */ - -/* - * R1040 (0x410) - Out Volume 1L - */ -#define WM5100_OUT_RATE_MASK 0xC000 /* OUT_RATE - [15:14] */ -#define WM5100_OUT_RATE_SHIFT 14 /* OUT_RATE - [15:14] */ -#define WM5100_OUT_RATE_WIDTH 2 /* OUT_RATE - [15:14] */ -#define WM5100_OUT1_OSR 0x2000 /* OUT1_OSR */ -#define WM5100_OUT1_OSR_MASK 0x2000 /* OUT1_OSR */ -#define WM5100_OUT1_OSR_SHIFT 13 /* OUT1_OSR */ -#define WM5100_OUT1_OSR_WIDTH 1 /* OUT1_OSR */ -#define WM5100_OUT1_MONO 0x1000 /* OUT1_MONO */ -#define WM5100_OUT1_MONO_MASK 0x1000 /* OUT1_MONO */ -#define WM5100_OUT1_MONO_SHIFT 12 /* OUT1_MONO */ -#define WM5100_OUT1_MONO_WIDTH 1 /* OUT1_MONO */ -#define WM5100_OUT1L_ANC_SRC 0x0800 /* OUT1L_ANC_SRC */ -#define WM5100_OUT1L_ANC_SRC_MASK 0x0800 /* OUT1L_ANC_SRC */ -#define WM5100_OUT1L_ANC_SRC_SHIFT 11 /* OUT1L_ANC_SRC */ -#define WM5100_OUT1L_ANC_SRC_WIDTH 1 /* OUT1L_ANC_SRC */ -#define WM5100_OUT1L_PGA_VOL_MASK 0x00FE /* OUT1L_PGA_VOL - [7:1] */ -#define WM5100_OUT1L_PGA_VOL_SHIFT 1 /* OUT1L_PGA_VOL - [7:1] */ -#define WM5100_OUT1L_PGA_VOL_WIDTH 7 /* OUT1L_PGA_VOL - [7:1] */ - -/* - * R1041 (0x411) - Out Volume 1R - */ -#define WM5100_OUT1R_ANC_SRC 0x0800 /* OUT1R_ANC_SRC */ -#define WM5100_OUT1R_ANC_SRC_MASK 0x0800 /* OUT1R_ANC_SRC */ -#define WM5100_OUT1R_ANC_SRC_SHIFT 11 /* OUT1R_ANC_SRC */ -#define WM5100_OUT1R_ANC_SRC_WIDTH 1 /* OUT1R_ANC_SRC */ -#define WM5100_OUT1R_PGA_VOL_MASK 0x00FE /* OUT1R_PGA_VOL - [7:1] */ -#define WM5100_OUT1R_PGA_VOL_SHIFT 1 /* OUT1R_PGA_VOL - [7:1] */ -#define WM5100_OUT1R_PGA_VOL_WIDTH 7 /* OUT1R_PGA_VOL - [7:1] */ - -/* - * R1042 (0x412) - DAC Volume Limit 1L - */ -#define WM5100_OUT1L_VOL_LIM_MASK 0x00FF /* OUT1L_VOL_LIM - [7:0] */ -#define WM5100_OUT1L_VOL_LIM_SHIFT 0 /* OUT1L_VOL_LIM - [7:0] */ -#define WM5100_OUT1L_VOL_LIM_WIDTH 8 /* OUT1L_VOL_LIM - [7:0] */ - -/* - * R1043 (0x413) - DAC Volume Limit 1R - */ -#define WM5100_OUT1R_VOL_LIM_MASK 0x00FF /* OUT1R_VOL_LIM - [7:0] */ -#define WM5100_OUT1R_VOL_LIM_SHIFT 0 /* OUT1R_VOL_LIM - [7:0] */ -#define WM5100_OUT1R_VOL_LIM_WIDTH 8 /* OUT1R_VOL_LIM - [7:0] */ - -/* - * R1044 (0x414) - Out Volume 2L - */ -#define WM5100_OUT2_OSR 0x2000 /* OUT2_OSR */ -#define WM5100_OUT2_OSR_MASK 0x2000 /* OUT2_OSR */ -#define WM5100_OUT2_OSR_SHIFT 13 /* OUT2_OSR */ -#define WM5100_OUT2_OSR_WIDTH 1 /* OUT2_OSR */ -#define WM5100_OUT2_MONO 0x1000 /* OUT2_MONO */ -#define WM5100_OUT2_MONO_MASK 0x1000 /* OUT2_MONO */ -#define WM5100_OUT2_MONO_SHIFT 12 /* OUT2_MONO */ -#define WM5100_OUT2_MONO_WIDTH 1 /* OUT2_MONO */ -#define WM5100_OUT2L_ANC_SRC 0x0800 /* OUT2L_ANC_SRC */ -#define WM5100_OUT2L_ANC_SRC_MASK 0x0800 /* OUT2L_ANC_SRC */ -#define WM5100_OUT2L_ANC_SRC_SHIFT 11 /* OUT2L_ANC_SRC */ -#define WM5100_OUT2L_ANC_SRC_WIDTH 1 /* OUT2L_ANC_SRC */ -#define WM5100_OUT2L_PGA_VOL_MASK 0x00FE /* OUT2L_PGA_VOL - [7:1] */ -#define WM5100_OUT2L_PGA_VOL_SHIFT 1 /* OUT2L_PGA_VOL - [7:1] */ -#define WM5100_OUT2L_PGA_VOL_WIDTH 7 /* OUT2L_PGA_VOL - [7:1] */ - -/* - * R1045 (0x415) - Out Volume 2R - */ -#define WM5100_OUT2R_ANC_SRC 0x0800 /* OUT2R_ANC_SRC */ -#define WM5100_OUT2R_ANC_SRC_MASK 0x0800 /* OUT2R_ANC_SRC */ -#define WM5100_OUT2R_ANC_SRC_SHIFT 11 /* OUT2R_ANC_SRC */ -#define WM5100_OUT2R_ANC_SRC_WIDTH 1 /* OUT2R_ANC_SRC */ -#define WM5100_OUT2R_PGA_VOL_MASK 0x00FE /* OUT2R_PGA_VOL - [7:1] */ -#define WM5100_OUT2R_PGA_VOL_SHIFT 1 /* OUT2R_PGA_VOL - [7:1] */ -#define WM5100_OUT2R_PGA_VOL_WIDTH 7 /* OUT2R_PGA_VOL - [7:1] */ - -/* - * R1046 (0x416) - DAC Volume Limit 2L - */ -#define WM5100_OUT2L_VOL_LIM_MASK 0x00FF /* OUT2L_VOL_LIM - [7:0] */ -#define WM5100_OUT2L_VOL_LIM_SHIFT 0 /* OUT2L_VOL_LIM - [7:0] */ -#define WM5100_OUT2L_VOL_LIM_WIDTH 8 /* OUT2L_VOL_LIM - [7:0] */ - -/* - * R1047 (0x417) - DAC Volume Limit 2R - */ -#define WM5100_OUT2R_VOL_LIM_MASK 0x00FF /* OUT2R_VOL_LIM - [7:0] */ -#define WM5100_OUT2R_VOL_LIM_SHIFT 0 /* OUT2R_VOL_LIM - [7:0] */ -#define WM5100_OUT2R_VOL_LIM_WIDTH 8 /* OUT2R_VOL_LIM - [7:0] */ - -/* - * R1048 (0x418) - Out Volume 3L - */ -#define WM5100_OUT3_OSR 0x2000 /* OUT3_OSR */ -#define WM5100_OUT3_OSR_MASK 0x2000 /* OUT3_OSR */ -#define WM5100_OUT3_OSR_SHIFT 13 /* OUT3_OSR */ -#define WM5100_OUT3_OSR_WIDTH 1 /* OUT3_OSR */ -#define WM5100_OUT3_MONO 0x1000 /* OUT3_MONO */ -#define WM5100_OUT3_MONO_MASK 0x1000 /* OUT3_MONO */ -#define WM5100_OUT3_MONO_SHIFT 12 /* OUT3_MONO */ -#define WM5100_OUT3_MONO_WIDTH 1 /* OUT3_MONO */ -#define WM5100_OUT3L_ANC_SRC 0x0800 /* OUT3L_ANC_SRC */ -#define WM5100_OUT3L_ANC_SRC_MASK 0x0800 /* OUT3L_ANC_SRC */ -#define WM5100_OUT3L_ANC_SRC_SHIFT 11 /* OUT3L_ANC_SRC */ -#define WM5100_OUT3L_ANC_SRC_WIDTH 1 /* OUT3L_ANC_SRC */ -#define WM5100_OUT3L_PGA_VOL_MASK 0x00FE /* OUT3L_PGA_VOL - [7:1] */ -#define WM5100_OUT3L_PGA_VOL_SHIFT 1 /* OUT3L_PGA_VOL - [7:1] */ -#define WM5100_OUT3L_PGA_VOL_WIDTH 7 /* OUT3L_PGA_VOL - [7:1] */ - -/* - * R1049 (0x419) - Out Volume 3R - */ -#define WM5100_OUT3R_ANC_SRC 0x0800 /* OUT3R_ANC_SRC */ -#define WM5100_OUT3R_ANC_SRC_MASK 0x0800 /* OUT3R_ANC_SRC */ -#define WM5100_OUT3R_ANC_SRC_SHIFT 11 /* OUT3R_ANC_SRC */ -#define WM5100_OUT3R_ANC_SRC_WIDTH 1 /* OUT3R_ANC_SRC */ -#define WM5100_OUT3R_PGA_VOL_MASK 0x00FE /* OUT3R_PGA_VOL - [7:1] */ -#define WM5100_OUT3R_PGA_VOL_SHIFT 1 /* OUT3R_PGA_VOL - [7:1] */ -#define WM5100_OUT3R_PGA_VOL_WIDTH 7 /* OUT3R_PGA_VOL - [7:1] */ - -/* - * R1050 (0x41A) - DAC Volume Limit 3L - */ -#define WM5100_OUT3L_VOL_LIM_MASK 0x00FF /* OUT3L_VOL_LIM - [7:0] */ -#define WM5100_OUT3L_VOL_LIM_SHIFT 0 /* OUT3L_VOL_LIM - [7:0] */ -#define WM5100_OUT3L_VOL_LIM_WIDTH 8 /* OUT3L_VOL_LIM - [7:0] */ - -/* - * R1051 (0x41B) - DAC Volume Limit 3R - */ -#define WM5100_OUT3R_VOL_LIM_MASK 0x00FF /* OUT3R_VOL_LIM - [7:0] */ -#define WM5100_OUT3R_VOL_LIM_SHIFT 0 /* OUT3R_VOL_LIM - [7:0] */ -#define WM5100_OUT3R_VOL_LIM_WIDTH 8 /* OUT3R_VOL_LIM - [7:0] */ - -/* - * R1052 (0x41C) - Out Volume 4L - */ -#define WM5100_OUT4_OSR 0x2000 /* OUT4_OSR */ -#define WM5100_OUT4_OSR_MASK 0x2000 /* OUT4_OSR */ -#define WM5100_OUT4_OSR_SHIFT 13 /* OUT4_OSR */ -#define WM5100_OUT4_OSR_WIDTH 1 /* OUT4_OSR */ -#define WM5100_OUT4L_ANC_SRC 0x0800 /* OUT4L_ANC_SRC */ -#define WM5100_OUT4L_ANC_SRC_MASK 0x0800 /* OUT4L_ANC_SRC */ -#define WM5100_OUT4L_ANC_SRC_SHIFT 11 /* OUT4L_ANC_SRC */ -#define WM5100_OUT4L_ANC_SRC_WIDTH 1 /* OUT4L_ANC_SRC */ -#define WM5100_OUT4L_VOL_LIM_MASK 0x00FF /* OUT4L_VOL_LIM - [7:0] */ -#define WM5100_OUT4L_VOL_LIM_SHIFT 0 /* OUT4L_VOL_LIM - [7:0] */ -#define WM5100_OUT4L_VOL_LIM_WIDTH 8 /* OUT4L_VOL_LIM - [7:0] */ - -/* - * R1053 (0x41D) - Out Volume 4R - */ -#define WM5100_OUT4R_ANC_SRC 0x0800 /* OUT4R_ANC_SRC */ -#define WM5100_OUT4R_ANC_SRC_MASK 0x0800 /* OUT4R_ANC_SRC */ -#define WM5100_OUT4R_ANC_SRC_SHIFT 11 /* OUT4R_ANC_SRC */ -#define WM5100_OUT4R_ANC_SRC_WIDTH 1 /* OUT4R_ANC_SRC */ -#define WM5100_OUT4R_VOL_LIM_MASK 0x00FF /* OUT4R_VOL_LIM - [7:0] */ -#define WM5100_OUT4R_VOL_LIM_SHIFT 0 /* OUT4R_VOL_LIM - [7:0] */ -#define WM5100_OUT4R_VOL_LIM_WIDTH 8 /* OUT4R_VOL_LIM - [7:0] */ - -/* - * R1054 (0x41E) - DAC Volume Limit 5L - */ -#define WM5100_OUT5_OSR 0x2000 /* OUT5_OSR */ -#define WM5100_OUT5_OSR_MASK 0x2000 /* OUT5_OSR */ -#define WM5100_OUT5_OSR_SHIFT 13 /* OUT5_OSR */ -#define WM5100_OUT5_OSR_WIDTH 1 /* OUT5_OSR */ -#define WM5100_OUT5L_ANC_SRC 0x0800 /* OUT5L_ANC_SRC */ -#define WM5100_OUT5L_ANC_SRC_MASK 0x0800 /* OUT5L_ANC_SRC */ -#define WM5100_OUT5L_ANC_SRC_SHIFT 11 /* OUT5L_ANC_SRC */ -#define WM5100_OUT5L_ANC_SRC_WIDTH 1 /* OUT5L_ANC_SRC */ -#define WM5100_OUT5L_VOL_LIM_MASK 0x00FF /* OUT5L_VOL_LIM - [7:0] */ -#define WM5100_OUT5L_VOL_LIM_SHIFT 0 /* OUT5L_VOL_LIM - [7:0] */ -#define WM5100_OUT5L_VOL_LIM_WIDTH 8 /* OUT5L_VOL_LIM - [7:0] */ - -/* - * R1055 (0x41F) - DAC Volume Limit 5R - */ -#define WM5100_OUT5R_ANC_SRC 0x0800 /* OUT5R_ANC_SRC */ -#define WM5100_OUT5R_ANC_SRC_MASK 0x0800 /* OUT5R_ANC_SRC */ -#define WM5100_OUT5R_ANC_SRC_SHIFT 11 /* OUT5R_ANC_SRC */ -#define WM5100_OUT5R_ANC_SRC_WIDTH 1 /* OUT5R_ANC_SRC */ -#define WM5100_OUT5R_VOL_LIM_MASK 0x00FF /* OUT5R_VOL_LIM - [7:0] */ -#define WM5100_OUT5R_VOL_LIM_SHIFT 0 /* OUT5R_VOL_LIM - [7:0] */ -#define WM5100_OUT5R_VOL_LIM_WIDTH 8 /* OUT5R_VOL_LIM - [7:0] */ - -/* - * R1056 (0x420) - DAC Volume Limit 6L - */ -#define WM5100_OUT6_OSR 0x2000 /* OUT6_OSR */ -#define WM5100_OUT6_OSR_MASK 0x2000 /* OUT6_OSR */ -#define WM5100_OUT6_OSR_SHIFT 13 /* OUT6_OSR */ -#define WM5100_OUT6_OSR_WIDTH 1 /* OUT6_OSR */ -#define WM5100_OUT6L_ANC_SRC 0x0800 /* OUT6L_ANC_SRC */ -#define WM5100_OUT6L_ANC_SRC_MASK 0x0800 /* OUT6L_ANC_SRC */ -#define WM5100_OUT6L_ANC_SRC_SHIFT 11 /* OUT6L_ANC_SRC */ -#define WM5100_OUT6L_ANC_SRC_WIDTH 1 /* OUT6L_ANC_SRC */ -#define WM5100_OUT6L_VOL_LIM_MASK 0x00FF /* OUT6L_VOL_LIM - [7:0] */ -#define WM5100_OUT6L_VOL_LIM_SHIFT 0 /* OUT6L_VOL_LIM - [7:0] */ -#define WM5100_OUT6L_VOL_LIM_WIDTH 8 /* OUT6L_VOL_LIM - [7:0] */ - -/* - * R1057 (0x421) - DAC Volume Limit 6R - */ -#define WM5100_OUT6R_ANC_SRC 0x0800 /* OUT6R_ANC_SRC */ -#define WM5100_OUT6R_ANC_SRC_MASK 0x0800 /* OUT6R_ANC_SRC */ -#define WM5100_OUT6R_ANC_SRC_SHIFT 11 /* OUT6R_ANC_SRC */ -#define WM5100_OUT6R_ANC_SRC_WIDTH 1 /* OUT6R_ANC_SRC */ -#define WM5100_OUT6R_VOL_LIM_MASK 0x00FF /* OUT6R_VOL_LIM - [7:0] */ -#define WM5100_OUT6R_VOL_LIM_SHIFT 0 /* OUT6R_VOL_LIM - [7:0] */ -#define WM5100_OUT6R_VOL_LIM_WIDTH 8 /* OUT6R_VOL_LIM - [7:0] */ - -/* - * R1088 (0x440) - DAC AEC Control 1 - */ -#define WM5100_AEC_LOOPBACK_SRC_MASK 0x003C /* AEC_LOOPBACK_SRC - [5:2] */ -#define WM5100_AEC_LOOPBACK_SRC_SHIFT 2 /* AEC_LOOPBACK_SRC - [5:2] */ -#define WM5100_AEC_LOOPBACK_SRC_WIDTH 4 /* AEC_LOOPBACK_SRC - [5:2] */ -#define WM5100_AEC_ENA_STS 0x0002 /* AEC_ENA_STS */ -#define WM5100_AEC_ENA_STS_MASK 0x0002 /* AEC_ENA_STS */ -#define WM5100_AEC_ENA_STS_SHIFT 1 /* AEC_ENA_STS */ -#define WM5100_AEC_ENA_STS_WIDTH 1 /* AEC_ENA_STS */ -#define WM5100_AEC_LOOPBACK_ENA 0x0001 /* AEC_LOOPBACK_ENA */ -#define WM5100_AEC_LOOPBACK_ENA_MASK 0x0001 /* AEC_LOOPBACK_ENA */ -#define WM5100_AEC_LOOPBACK_ENA_SHIFT 0 /* AEC_LOOPBACK_ENA */ -#define WM5100_AEC_LOOPBACK_ENA_WIDTH 1 /* AEC_LOOPBACK_ENA */ - -/* - * R1089 (0x441) - Output Volume Ramp - */ -#define WM5100_OUT_VD_RAMP_MASK 0x0070 /* OUT_VD_RAMP - [6:4] */ -#define WM5100_OUT_VD_RAMP_SHIFT 4 /* OUT_VD_RAMP - [6:4] */ -#define WM5100_OUT_VD_RAMP_WIDTH 3 /* OUT_VD_RAMP - [6:4] */ -#define WM5100_OUT_VI_RAMP_MASK 0x0007 /* OUT_VI_RAMP - [2:0] */ -#define WM5100_OUT_VI_RAMP_SHIFT 0 /* OUT_VI_RAMP - [2:0] */ -#define WM5100_OUT_VI_RAMP_WIDTH 3 /* OUT_VI_RAMP - [2:0] */ - -/* - * R1152 (0x480) - DAC Digital Volume 1L - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT1L_MUTE 0x0100 /* OUT1L_MUTE */ -#define WM5100_OUT1L_MUTE_MASK 0x0100 /* OUT1L_MUTE */ -#define WM5100_OUT1L_MUTE_SHIFT 8 /* OUT1L_MUTE */ -#define WM5100_OUT1L_MUTE_WIDTH 1 /* OUT1L_MUTE */ -#define WM5100_OUT1L_VOL_MASK 0x00FF /* OUT1L_VOL - [7:0] */ -#define WM5100_OUT1L_VOL_SHIFT 0 /* OUT1L_VOL - [7:0] */ -#define WM5100_OUT1L_VOL_WIDTH 8 /* OUT1L_VOL - [7:0] */ - -/* - * R1153 (0x481) - DAC Digital Volume 1R - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT1R_MUTE 0x0100 /* OUT1R_MUTE */ -#define WM5100_OUT1R_MUTE_MASK 0x0100 /* OUT1R_MUTE */ -#define WM5100_OUT1R_MUTE_SHIFT 8 /* OUT1R_MUTE */ -#define WM5100_OUT1R_MUTE_WIDTH 1 /* OUT1R_MUTE */ -#define WM5100_OUT1R_VOL_MASK 0x00FF /* OUT1R_VOL - [7:0] */ -#define WM5100_OUT1R_VOL_SHIFT 0 /* OUT1R_VOL - [7:0] */ -#define WM5100_OUT1R_VOL_WIDTH 8 /* OUT1R_VOL - [7:0] */ - -/* - * R1154 (0x482) - DAC Digital Volume 2L - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT2L_MUTE 0x0100 /* OUT2L_MUTE */ -#define WM5100_OUT2L_MUTE_MASK 0x0100 /* OUT2L_MUTE */ -#define WM5100_OUT2L_MUTE_SHIFT 8 /* OUT2L_MUTE */ -#define WM5100_OUT2L_MUTE_WIDTH 1 /* OUT2L_MUTE */ -#define WM5100_OUT2L_VOL_MASK 0x00FF /* OUT2L_VOL - [7:0] */ -#define WM5100_OUT2L_VOL_SHIFT 0 /* OUT2L_VOL - [7:0] */ -#define WM5100_OUT2L_VOL_WIDTH 8 /* OUT2L_VOL - [7:0] */ - -/* - * R1155 (0x483) - DAC Digital Volume 2R - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT2R_MUTE 0x0100 /* OUT2R_MUTE */ -#define WM5100_OUT2R_MUTE_MASK 0x0100 /* OUT2R_MUTE */ -#define WM5100_OUT2R_MUTE_SHIFT 8 /* OUT2R_MUTE */ -#define WM5100_OUT2R_MUTE_WIDTH 1 /* OUT2R_MUTE */ -#define WM5100_OUT2R_VOL_MASK 0x00FF /* OUT2R_VOL - [7:0] */ -#define WM5100_OUT2R_VOL_SHIFT 0 /* OUT2R_VOL - [7:0] */ -#define WM5100_OUT2R_VOL_WIDTH 8 /* OUT2R_VOL - [7:0] */ - -/* - * R1156 (0x484) - DAC Digital Volume 3L - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT3L_MUTE 0x0100 /* OUT3L_MUTE */ -#define WM5100_OUT3L_MUTE_MASK 0x0100 /* OUT3L_MUTE */ -#define WM5100_OUT3L_MUTE_SHIFT 8 /* OUT3L_MUTE */ -#define WM5100_OUT3L_MUTE_WIDTH 1 /* OUT3L_MUTE */ -#define WM5100_OUT3L_VOL_MASK 0x00FF /* OUT3L_VOL - [7:0] */ -#define WM5100_OUT3L_VOL_SHIFT 0 /* OUT3L_VOL - [7:0] */ -#define WM5100_OUT3L_VOL_WIDTH 8 /* OUT3L_VOL - [7:0] */ - -/* - * R1157 (0x485) - DAC Digital Volume 3R - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT3R_MUTE 0x0100 /* OUT3R_MUTE */ -#define WM5100_OUT3R_MUTE_MASK 0x0100 /* OUT3R_MUTE */ -#define WM5100_OUT3R_MUTE_SHIFT 8 /* OUT3R_MUTE */ -#define WM5100_OUT3R_MUTE_WIDTH 1 /* OUT3R_MUTE */ -#define WM5100_OUT3R_VOL_MASK 0x00FF /* OUT3R_VOL - [7:0] */ -#define WM5100_OUT3R_VOL_SHIFT 0 /* OUT3R_VOL - [7:0] */ -#define WM5100_OUT3R_VOL_WIDTH 8 /* OUT3R_VOL - [7:0] */ - -/* - * R1158 (0x486) - DAC Digital Volume 4L - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT4L_MUTE 0x0100 /* OUT4L_MUTE */ -#define WM5100_OUT4L_MUTE_MASK 0x0100 /* OUT4L_MUTE */ -#define WM5100_OUT4L_MUTE_SHIFT 8 /* OUT4L_MUTE */ -#define WM5100_OUT4L_MUTE_WIDTH 1 /* OUT4L_MUTE */ -#define WM5100_OUT4L_VOL_MASK 0x00FF /* OUT4L_VOL - [7:0] */ -#define WM5100_OUT4L_VOL_SHIFT 0 /* OUT4L_VOL - [7:0] */ -#define WM5100_OUT4L_VOL_WIDTH 8 /* OUT4L_VOL - [7:0] */ - -/* - * R1159 (0x487) - DAC Digital Volume 4R - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT4R_MUTE 0x0100 /* OUT4R_MUTE */ -#define WM5100_OUT4R_MUTE_MASK 0x0100 /* OUT4R_MUTE */ -#define WM5100_OUT4R_MUTE_SHIFT 8 /* OUT4R_MUTE */ -#define WM5100_OUT4R_MUTE_WIDTH 1 /* OUT4R_MUTE */ -#define WM5100_OUT4R_VOL_MASK 0x00FF /* OUT4R_VOL - [7:0] */ -#define WM5100_OUT4R_VOL_SHIFT 0 /* OUT4R_VOL - [7:0] */ -#define WM5100_OUT4R_VOL_WIDTH 8 /* OUT4R_VOL - [7:0] */ - -/* - * R1160 (0x488) - DAC Digital Volume 5L - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT5L_MUTE 0x0100 /* OUT5L_MUTE */ -#define WM5100_OUT5L_MUTE_MASK 0x0100 /* OUT5L_MUTE */ -#define WM5100_OUT5L_MUTE_SHIFT 8 /* OUT5L_MUTE */ -#define WM5100_OUT5L_MUTE_WIDTH 1 /* OUT5L_MUTE */ -#define WM5100_OUT5L_VOL_MASK 0x00FF /* OUT5L_VOL - [7:0] */ -#define WM5100_OUT5L_VOL_SHIFT 0 /* OUT5L_VOL - [7:0] */ -#define WM5100_OUT5L_VOL_WIDTH 8 /* OUT5L_VOL - [7:0] */ - -/* - * R1161 (0x489) - DAC Digital Volume 5R - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT5R_MUTE 0x0100 /* OUT5R_MUTE */ -#define WM5100_OUT5R_MUTE_MASK 0x0100 /* OUT5R_MUTE */ -#define WM5100_OUT5R_MUTE_SHIFT 8 /* OUT5R_MUTE */ -#define WM5100_OUT5R_MUTE_WIDTH 1 /* OUT5R_MUTE */ -#define WM5100_OUT5R_VOL_MASK 0x00FF /* OUT5R_VOL - [7:0] */ -#define WM5100_OUT5R_VOL_SHIFT 0 /* OUT5R_VOL - [7:0] */ -#define WM5100_OUT5R_VOL_WIDTH 8 /* OUT5R_VOL - [7:0] */ - -/* - * R1162 (0x48A) - DAC Digital Volume 6L - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT6L_MUTE 0x0100 /* OUT6L_MUTE */ -#define WM5100_OUT6L_MUTE_MASK 0x0100 /* OUT6L_MUTE */ -#define WM5100_OUT6L_MUTE_SHIFT 8 /* OUT6L_MUTE */ -#define WM5100_OUT6L_MUTE_WIDTH 1 /* OUT6L_MUTE */ -#define WM5100_OUT6L_VOL_MASK 0x00FF /* OUT6L_VOL - [7:0] */ -#define WM5100_OUT6L_VOL_SHIFT 0 /* OUT6L_VOL - [7:0] */ -#define WM5100_OUT6L_VOL_WIDTH 8 /* OUT6L_VOL - [7:0] */ - -/* - * R1163 (0x48B) - DAC Digital Volume 6R - */ -#define WM5100_OUT_VU 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */ -#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */ -#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */ -#define WM5100_OUT6R_MUTE 0x0100 /* OUT6R_MUTE */ -#define WM5100_OUT6R_MUTE_MASK 0x0100 /* OUT6R_MUTE */ -#define WM5100_OUT6R_MUTE_SHIFT 8 /* OUT6R_MUTE */ -#define WM5100_OUT6R_MUTE_WIDTH 1 /* OUT6R_MUTE */ -#define WM5100_OUT6R_VOL_MASK 0x00FF /* OUT6R_VOL - [7:0] */ -#define WM5100_OUT6R_VOL_SHIFT 0 /* OUT6R_VOL - [7:0] */ -#define WM5100_OUT6R_VOL_WIDTH 8 /* OUT6R_VOL - [7:0] */ - -/* - * R1216 (0x4C0) - PDM SPK1 CTRL 1 - */ -#define WM5100_SPK1R_MUTE 0x2000 /* SPK1R_MUTE */ -#define WM5100_SPK1R_MUTE_MASK 0x2000 /* SPK1R_MUTE */ -#define WM5100_SPK1R_MUTE_SHIFT 13 /* SPK1R_MUTE */ -#define WM5100_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */ -#define WM5100_SPK1L_MUTE 0x1000 /* SPK1L_MUTE */ -#define WM5100_SPK1L_MUTE_MASK 0x1000 /* SPK1L_MUTE */ -#define WM5100_SPK1L_MUTE_SHIFT 12 /* SPK1L_MUTE */ -#define WM5100_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */ -#define WM5100_SPK1_MUTE_ENDIAN 0x0100 /* SPK1_MUTE_ENDIAN */ -#define WM5100_SPK1_MUTE_ENDIAN_MASK 0x0100 /* SPK1_MUTE_ENDIAN */ -#define WM5100_SPK1_MUTE_ENDIAN_SHIFT 8 /* SPK1_MUTE_ENDIAN */ -#define WM5100_SPK1_MUTE_ENDIAN_WIDTH 1 /* SPK1_MUTE_ENDIAN */ -#define WM5100_SPK1_MUTE_SEQ1_MASK 0x00FF /* SPK1_MUTE_SEQ1 - [7:0] */ -#define WM5100_SPK1_MUTE_SEQ1_SHIFT 0 /* SPK1_MUTE_SEQ1 - [7:0] */ -#define WM5100_SPK1_MUTE_SEQ1_WIDTH 8 /* SPK1_MUTE_SEQ1 - [7:0] */ - -/* - * R1217 (0x4C1) - PDM SPK1 CTRL 2 - */ -#define WM5100_SPK1_FMT 0x0001 /* SPK1_FMT */ -#define WM5100_SPK1_FMT_MASK 0x0001 /* SPK1_FMT */ -#define WM5100_SPK1_FMT_SHIFT 0 /* SPK1_FMT */ -#define WM5100_SPK1_FMT_WIDTH 1 /* SPK1_FMT */ - -/* - * R1218 (0x4C2) - PDM SPK2 CTRL 1 - */ -#define WM5100_SPK2R_MUTE 0x2000 /* SPK2R_MUTE */ -#define WM5100_SPK2R_MUTE_MASK 0x2000 /* SPK2R_MUTE */ -#define WM5100_SPK2R_MUTE_SHIFT 13 /* SPK2R_MUTE */ -#define WM5100_SPK2R_MUTE_WIDTH 1 /* SPK2R_MUTE */ -#define WM5100_SPK2L_MUTE 0x1000 /* SPK2L_MUTE */ -#define WM5100_SPK2L_MUTE_MASK 0x1000 /* SPK2L_MUTE */ -#define WM5100_SPK2L_MUTE_SHIFT 12 /* SPK2L_MUTE */ -#define WM5100_SPK2L_MUTE_WIDTH 1 /* SPK2L_MUTE */ -#define WM5100_SPK2_MUTE_ENDIAN 0x0100 /* SPK2_MUTE_ENDIAN */ -#define WM5100_SPK2_MUTE_ENDIAN_MASK 0x0100 /* SPK2_MUTE_ENDIAN */ -#define WM5100_SPK2_MUTE_ENDIAN_SHIFT 8 /* SPK2_MUTE_ENDIAN */ -#define WM5100_SPK2_MUTE_ENDIAN_WIDTH 1 /* SPK2_MUTE_ENDIAN */ -#define WM5100_SPK2_MUTE_SEQ1_MASK 0x00FF /* SPK2_MUTE_SEQ1 - [7:0] */ -#define WM5100_SPK2_MUTE_SEQ1_SHIFT 0 /* SPK2_MUTE_SEQ1 - [7:0] */ -#define WM5100_SPK2_MUTE_SEQ1_WIDTH 8 /* SPK2_MUTE_SEQ1 - [7:0] */ - -/* - * R1219 (0x4C3) - PDM SPK2 CTRL 2 - */ -#define WM5100_SPK2_FMT 0x0001 /* SPK2_FMT */ -#define WM5100_SPK2_FMT_MASK 0x0001 /* SPK2_FMT */ -#define WM5100_SPK2_FMT_SHIFT 0 /* SPK2_FMT */ -#define WM5100_SPK2_FMT_WIDTH 1 /* SPK2_FMT */ - -/* - * R1280 (0x500) - Audio IF 1_1 - */ -#define WM5100_AIF1_BCLK_INV 0x0080 /* AIF1_BCLK_INV */ -#define WM5100_AIF1_BCLK_INV_MASK 0x0080 /* AIF1_BCLK_INV */ -#define WM5100_AIF1_BCLK_INV_SHIFT 7 /* AIF1_BCLK_INV */ -#define WM5100_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */ -#define WM5100_AIF1_BCLK_FRC 0x0040 /* AIF1_BCLK_FRC */ -#define WM5100_AIF1_BCLK_FRC_MASK 0x0040 /* AIF1_BCLK_FRC */ -#define WM5100_AIF1_BCLK_FRC_SHIFT 6 /* AIF1_BCLK_FRC */ -#define WM5100_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */ -#define WM5100_AIF1_BCLK_MSTR 0x0020 /* AIF1_BCLK_MSTR */ -#define WM5100_AIF1_BCLK_MSTR_MASK 0x0020 /* AIF1_BCLK_MSTR */ -#define WM5100_AIF1_BCLK_MSTR_SHIFT 5 /* AIF1_BCLK_MSTR */ -#define WM5100_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */ -#define WM5100_AIF1_BCLK_FREQ_MASK 0x001F /* AIF1_BCLK_FREQ - [4:0] */ -#define WM5100_AIF1_BCLK_FREQ_SHIFT 0 /* AIF1_BCLK_FREQ - [4:0] */ -#define WM5100_AIF1_BCLK_FREQ_WIDTH 5 /* AIF1_BCLK_FREQ - [4:0] */ - -/* - * R1281 (0x501) - Audio IF 1_2 - */ -#define WM5100_AIF1TX_DAT_TRI 0x0020 /* AIF1TX_DAT_TRI */ -#define WM5100_AIF1TX_DAT_TRI_MASK 0x0020 /* AIF1TX_DAT_TRI */ -#define WM5100_AIF1TX_DAT_TRI_SHIFT 5 /* AIF1TX_DAT_TRI */ -#define WM5100_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */ -#define WM5100_AIF1TX_LRCLK_SRC 0x0008 /* AIF1TX_LRCLK_SRC */ -#define WM5100_AIF1TX_LRCLK_SRC_MASK 0x0008 /* AIF1TX_LRCLK_SRC */ -#define WM5100_AIF1TX_LRCLK_SRC_SHIFT 3 /* AIF1TX_LRCLK_SRC */ -#define WM5100_AIF1TX_LRCLK_SRC_WIDTH 1 /* AIF1TX_LRCLK_SRC */ -#define WM5100_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */ -#define WM5100_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */ -#define WM5100_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */ -#define WM5100_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */ -#define WM5100_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */ -#define WM5100_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */ -#define WM5100_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */ -#define WM5100_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */ -#define WM5100_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */ -#define WM5100_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */ -#define WM5100_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */ -#define WM5100_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */ - -/* - * R1282 (0x502) - Audio IF 1_3 - */ -#define WM5100_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */ -#define WM5100_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */ -#define WM5100_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */ -#define WM5100_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */ -#define WM5100_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */ -#define WM5100_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */ -#define WM5100_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */ -#define WM5100_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */ -#define WM5100_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */ -#define WM5100_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */ -#define WM5100_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */ -#define WM5100_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */ - -/* - * R1283 (0x503) - Audio IF 1_4 - */ -#define WM5100_AIF1_TRI 0x0040 /* AIF1_TRI */ -#define WM5100_AIF1_TRI_MASK 0x0040 /* AIF1_TRI */ -#define WM5100_AIF1_TRI_SHIFT 6 /* AIF1_TRI */ -#define WM5100_AIF1_TRI_WIDTH 1 /* AIF1_TRI */ -#define WM5100_AIF1_RATE_MASK 0x0003 /* AIF1_RATE - [1:0] */ -#define WM5100_AIF1_RATE_SHIFT 0 /* AIF1_RATE - [1:0] */ -#define WM5100_AIF1_RATE_WIDTH 2 /* AIF1_RATE - [1:0] */ - -/* - * R1284 (0x504) - Audio IF 1_5 - */ -#define WM5100_AIF1_FMT_MASK 0x0007 /* AIF1_FMT - [2:0] */ -#define WM5100_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [2:0] */ -#define WM5100_AIF1_FMT_WIDTH 3 /* AIF1_FMT - [2:0] */ - -/* - * R1285 (0x505) - Audio IF 1_6 - */ -#define WM5100_AIF1TX_BCPF_MASK 0x1FFF /* AIF1TX_BCPF - [12:0] */ -#define WM5100_AIF1TX_BCPF_SHIFT 0 /* AIF1TX_BCPF - [12:0] */ -#define WM5100_AIF1TX_BCPF_WIDTH 13 /* AIF1TX_BCPF - [12:0] */ - -/* - * R1286 (0x506) - Audio IF 1_7 - */ -#define WM5100_AIF1RX_BCPF_MASK 0x1FFF /* AIF1RX_BCPF - [12:0] */ -#define WM5100_AIF1RX_BCPF_SHIFT 0 /* AIF1RX_BCPF - [12:0] */ -#define WM5100_AIF1RX_BCPF_WIDTH 13 /* AIF1RX_BCPF - [12:0] */ - -/* - * R1287 (0x507) - Audio IF 1_8 - */ -#define WM5100_AIF1TX_WL_MASK 0x3F00 /* AIF1TX_WL - [13:8] */ -#define WM5100_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [13:8] */ -#define WM5100_AIF1TX_WL_WIDTH 6 /* AIF1TX_WL - [13:8] */ -#define WM5100_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */ -#define WM5100_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */ -#define WM5100_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */ - -/* - * R1288 (0x508) - Audio IF 1_9 - */ -#define WM5100_AIF1RX_WL_MASK 0x3F00 /* AIF1RX_WL - [13:8] */ -#define WM5100_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [13:8] */ -#define WM5100_AIF1RX_WL_WIDTH 6 /* AIF1RX_WL - [13:8] */ -#define WM5100_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */ -#define WM5100_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */ -#define WM5100_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */ - -/* - * R1289 (0x509) - Audio IF 1_10 - */ -#define WM5100_AIF1TX1_SLOT_MASK 0x003F /* AIF1TX1_SLOT - [5:0] */ -#define WM5100_AIF1TX1_SLOT_SHIFT 0 /* AIF1TX1_SLOT - [5:0] */ -#define WM5100_AIF1TX1_SLOT_WIDTH 6 /* AIF1TX1_SLOT - [5:0] */ - -/* - * R1290 (0x50A) - Audio IF 1_11 - */ -#define WM5100_AIF1TX2_SLOT_MASK 0x003F /* AIF1TX2_SLOT - [5:0] */ -#define WM5100_AIF1TX2_SLOT_SHIFT 0 /* AIF1TX2_SLOT - [5:0] */ -#define WM5100_AIF1TX2_SLOT_WIDTH 6 /* AIF1TX2_SLOT - [5:0] */ - -/* - * R1291 (0x50B) - Audio IF 1_12 - */ -#define WM5100_AIF1TX3_SLOT_MASK 0x003F /* AIF1TX3_SLOT - [5:0] */ -#define WM5100_AIF1TX3_SLOT_SHIFT 0 /* AIF1TX3_SLOT - [5:0] */ -#define WM5100_AIF1TX3_SLOT_WIDTH 6 /* AIF1TX3_SLOT - [5:0] */ - -/* - * R1292 (0x50C) - Audio IF 1_13 - */ -#define WM5100_AIF1TX4_SLOT_MASK 0x003F /* AIF1TX4_SLOT - [5:0] */ -#define WM5100_AIF1TX4_SLOT_SHIFT 0 /* AIF1TX4_SLOT - [5:0] */ -#define WM5100_AIF1TX4_SLOT_WIDTH 6 /* AIF1TX4_SLOT - [5:0] */ - -/* - * R1293 (0x50D) - Audio IF 1_14 - */ -#define WM5100_AIF1TX5_SLOT_MASK 0x003F /* AIF1TX5_SLOT - [5:0] */ -#define WM5100_AIF1TX5_SLOT_SHIFT 0 /* AIF1TX5_SLOT - [5:0] */ -#define WM5100_AIF1TX5_SLOT_WIDTH 6 /* AIF1TX5_SLOT - [5:0] */ - -/* - * R1294 (0x50E) - Audio IF 1_15 - */ -#define WM5100_AIF1TX6_SLOT_MASK 0x003F /* AIF1TX6_SLOT - [5:0] */ -#define WM5100_AIF1TX6_SLOT_SHIFT 0 /* AIF1TX6_SLOT - [5:0] */ -#define WM5100_AIF1TX6_SLOT_WIDTH 6 /* AIF1TX6_SLOT - [5:0] */ - -/* - * R1295 (0x50F) - Audio IF 1_16 - */ -#define WM5100_AIF1TX7_SLOT_MASK 0x003F /* AIF1TX7_SLOT - [5:0] */ -#define WM5100_AIF1TX7_SLOT_SHIFT 0 /* AIF1TX7_SLOT - [5:0] */ -#define WM5100_AIF1TX7_SLOT_WIDTH 6 /* AIF1TX7_SLOT - [5:0] */ - -/* - * R1296 (0x510) - Audio IF 1_17 - */ -#define WM5100_AIF1TX8_SLOT_MASK 0x003F /* AIF1TX8_SLOT - [5:0] */ -#define WM5100_AIF1TX8_SLOT_SHIFT 0 /* AIF1TX8_SLOT - [5:0] */ -#define WM5100_AIF1TX8_SLOT_WIDTH 6 /* AIF1TX8_SLOT - [5:0] */ - -/* - * R1297 (0x511) - Audio IF 1_18 - */ -#define WM5100_AIF1RX1_SLOT_MASK 0x003F /* AIF1RX1_SLOT - [5:0] */ -#define WM5100_AIF1RX1_SLOT_SHIFT 0 /* AIF1RX1_SLOT - [5:0] */ -#define WM5100_AIF1RX1_SLOT_WIDTH 6 /* AIF1RX1_SLOT - [5:0] */ - -/* - * R1298 (0x512) - Audio IF 1_19 - */ -#define WM5100_AIF1RX2_SLOT_MASK 0x003F /* AIF1RX2_SLOT - [5:0] */ -#define WM5100_AIF1RX2_SLOT_SHIFT 0 /* AIF1RX2_SLOT - [5:0] */ -#define WM5100_AIF1RX2_SLOT_WIDTH 6 /* AIF1RX2_SLOT - [5:0] */ - -/* - * R1299 (0x513) - Audio IF 1_20 - */ -#define WM5100_AIF1RX3_SLOT_MASK 0x003F /* AIF1RX3_SLOT - [5:0] */ -#define WM5100_AIF1RX3_SLOT_SHIFT 0 /* AIF1RX3_SLOT - [5:0] */ -#define WM5100_AIF1RX3_SLOT_WIDTH 6 /* AIF1RX3_SLOT - [5:0] */ - -/* - * R1300 (0x514) - Audio IF 1_21 - */ -#define WM5100_AIF1RX4_SLOT_MASK 0x003F /* AIF1RX4_SLOT - [5:0] */ -#define WM5100_AIF1RX4_SLOT_SHIFT 0 /* AIF1RX4_SLOT - [5:0] */ -#define WM5100_AIF1RX4_SLOT_WIDTH 6 /* AIF1RX4_SLOT - [5:0] */ - -/* - * R1301 (0x515) - Audio IF 1_22 - */ -#define WM5100_AIF1RX5_SLOT_MASK 0x003F /* AIF1RX5_SLOT - [5:0] */ -#define WM5100_AIF1RX5_SLOT_SHIFT 0 /* AIF1RX5_SLOT - [5:0] */ -#define WM5100_AIF1RX5_SLOT_WIDTH 6 /* AIF1RX5_SLOT - [5:0] */ - -/* - * R1302 (0x516) - Audio IF 1_23 - */ -#define WM5100_AIF1RX6_SLOT_MASK 0x003F /* AIF1RX6_SLOT - [5:0] */ -#define WM5100_AIF1RX6_SLOT_SHIFT 0 /* AIF1RX6_SLOT - [5:0] */ -#define WM5100_AIF1RX6_SLOT_WIDTH 6 /* AIF1RX6_SLOT - [5:0] */ - -/* - * R1303 (0x517) - Audio IF 1_24 - */ -#define WM5100_AIF1RX7_SLOT_MASK 0x003F /* AIF1RX7_SLOT - [5:0] */ -#define WM5100_AIF1RX7_SLOT_SHIFT 0 /* AIF1RX7_SLOT - [5:0] */ -#define WM5100_AIF1RX7_SLOT_WIDTH 6 /* AIF1RX7_SLOT - [5:0] */ - -/* - * R1304 (0x518) - Audio IF 1_25 - */ -#define WM5100_AIF1RX8_SLOT_MASK 0x003F /* AIF1RX8_SLOT - [5:0] */ -#define WM5100_AIF1RX8_SLOT_SHIFT 0 /* AIF1RX8_SLOT - [5:0] */ -#define WM5100_AIF1RX8_SLOT_WIDTH 6 /* AIF1RX8_SLOT - [5:0] */ - -/* - * R1305 (0x519) - Audio IF 1_26 - */ -#define WM5100_AIF1TX8_ENA 0x0080 /* AIF1TX8_ENA */ -#define WM5100_AIF1TX8_ENA_MASK 0x0080 /* AIF1TX8_ENA */ -#define WM5100_AIF1TX8_ENA_SHIFT 7 /* AIF1TX8_ENA */ -#define WM5100_AIF1TX8_ENA_WIDTH 1 /* AIF1TX8_ENA */ -#define WM5100_AIF1TX7_ENA 0x0040 /* AIF1TX7_ENA */ -#define WM5100_AIF1TX7_ENA_MASK 0x0040 /* AIF1TX7_ENA */ -#define WM5100_AIF1TX7_ENA_SHIFT 6 /* AIF1TX7_ENA */ -#define WM5100_AIF1TX7_ENA_WIDTH 1 /* AIF1TX7_ENA */ -#define WM5100_AIF1TX6_ENA 0x0020 /* AIF1TX6_ENA */ -#define WM5100_AIF1TX6_ENA_MASK 0x0020 /* AIF1TX6_ENA */ -#define WM5100_AIF1TX6_ENA_SHIFT 5 /* AIF1TX6_ENA */ -#define WM5100_AIF1TX6_ENA_WIDTH 1 /* AIF1TX6_ENA */ -#define WM5100_AIF1TX5_ENA 0x0010 /* AIF1TX5_ENA */ -#define WM5100_AIF1TX5_ENA_MASK 0x0010 /* AIF1TX5_ENA */ -#define WM5100_AIF1TX5_ENA_SHIFT 4 /* AIF1TX5_ENA */ -#define WM5100_AIF1TX5_ENA_WIDTH 1 /* AIF1TX5_ENA */ -#define WM5100_AIF1TX4_ENA 0x0008 /* AIF1TX4_ENA */ -#define WM5100_AIF1TX4_ENA_MASK 0x0008 /* AIF1TX4_ENA */ -#define WM5100_AIF1TX4_ENA_SHIFT 3 /* AIF1TX4_ENA */ -#define WM5100_AIF1TX4_ENA_WIDTH 1 /* AIF1TX4_ENA */ -#define WM5100_AIF1TX3_ENA 0x0004 /* AIF1TX3_ENA */ -#define WM5100_AIF1TX3_ENA_MASK 0x0004 /* AIF1TX3_ENA */ -#define WM5100_AIF1TX3_ENA_SHIFT 2 /* AIF1TX3_ENA */ -#define WM5100_AIF1TX3_ENA_WIDTH 1 /* AIF1TX3_ENA */ -#define WM5100_AIF1TX2_ENA 0x0002 /* AIF1TX2_ENA */ -#define WM5100_AIF1TX2_ENA_MASK 0x0002 /* AIF1TX2_ENA */ -#define WM5100_AIF1TX2_ENA_SHIFT 1 /* AIF1TX2_ENA */ -#define WM5100_AIF1TX2_ENA_WIDTH 1 /* AIF1TX2_ENA */ -#define WM5100_AIF1TX1_ENA 0x0001 /* AIF1TX1_ENA */ -#define WM5100_AIF1TX1_ENA_MASK 0x0001 /* AIF1TX1_ENA */ -#define WM5100_AIF1TX1_ENA_SHIFT 0 /* AIF1TX1_ENA */ -#define WM5100_AIF1TX1_ENA_WIDTH 1 /* AIF1TX1_ENA */ - -/* - * R1306 (0x51A) - Audio IF 1_27 - */ -#define WM5100_AIF1RX8_ENA 0x0080 /* AIF1RX8_ENA */ -#define WM5100_AIF1RX8_ENA_MASK 0x0080 /* AIF1RX8_ENA */ -#define WM5100_AIF1RX8_ENA_SHIFT 7 /* AIF1RX8_ENA */ -#define WM5100_AIF1RX8_ENA_WIDTH 1 /* AIF1RX8_ENA */ -#define WM5100_AIF1RX7_ENA 0x0040 /* AIF1RX7_ENA */ -#define WM5100_AIF1RX7_ENA_MASK 0x0040 /* AIF1RX7_ENA */ -#define WM5100_AIF1RX7_ENA_SHIFT 6 /* AIF1RX7_ENA */ -#define WM5100_AIF1RX7_ENA_WIDTH 1 /* AIF1RX7_ENA */ -#define WM5100_AIF1RX6_ENA 0x0020 /* AIF1RX6_ENA */ -#define WM5100_AIF1RX6_ENA_MASK 0x0020 /* AIF1RX6_ENA */ -#define WM5100_AIF1RX6_ENA_SHIFT 5 /* AIF1RX6_ENA */ -#define WM5100_AIF1RX6_ENA_WIDTH 1 /* AIF1RX6_ENA */ -#define WM5100_AIF1RX5_ENA 0x0010 /* AIF1RX5_ENA */ -#define WM5100_AIF1RX5_ENA_MASK 0x0010 /* AIF1RX5_ENA */ -#define WM5100_AIF1RX5_ENA_SHIFT 4 /* AIF1RX5_ENA */ -#define WM5100_AIF1RX5_ENA_WIDTH 1 /* AIF1RX5_ENA */ -#define WM5100_AIF1RX4_ENA 0x0008 /* AIF1RX4_ENA */ -#define WM5100_AIF1RX4_ENA_MASK 0x0008 /* AIF1RX4_ENA */ -#define WM5100_AIF1RX4_ENA_SHIFT 3 /* AIF1RX4_ENA */ -#define WM5100_AIF1RX4_ENA_WIDTH 1 /* AIF1RX4_ENA */ -#define WM5100_AIF1RX3_ENA 0x0004 /* AIF1RX3_ENA */ -#define WM5100_AIF1RX3_ENA_MASK 0x0004 /* AIF1RX3_ENA */ -#define WM5100_AIF1RX3_ENA_SHIFT 2 /* AIF1RX3_ENA */ -#define WM5100_AIF1RX3_ENA_WIDTH 1 /* AIF1RX3_ENA */ -#define WM5100_AIF1RX2_ENA 0x0002 /* AIF1RX2_ENA */ -#define WM5100_AIF1RX2_ENA_MASK 0x0002 /* AIF1RX2_ENA */ -#define WM5100_AIF1RX2_ENA_SHIFT 1 /* AIF1RX2_ENA */ -#define WM5100_AIF1RX2_ENA_WIDTH 1 /* AIF1RX2_ENA */ -#define WM5100_AIF1RX1_ENA 0x0001 /* AIF1RX1_ENA */ -#define WM5100_AIF1RX1_ENA_MASK 0x0001 /* AIF1RX1_ENA */ -#define WM5100_AIF1RX1_ENA_SHIFT 0 /* AIF1RX1_ENA */ -#define WM5100_AIF1RX1_ENA_WIDTH 1 /* AIF1RX1_ENA */ - -/* - * R1344 (0x540) - Audio IF 2_1 - */ -#define WM5100_AIF2_BCLK_INV 0x0080 /* AIF2_BCLK_INV */ -#define WM5100_AIF2_BCLK_INV_MASK 0x0080 /* AIF2_BCLK_INV */ -#define WM5100_AIF2_BCLK_INV_SHIFT 7 /* AIF2_BCLK_INV */ -#define WM5100_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */ -#define WM5100_AIF2_BCLK_FRC 0x0040 /* AIF2_BCLK_FRC */ -#define WM5100_AIF2_BCLK_FRC_MASK 0x0040 /* AIF2_BCLK_FRC */ -#define WM5100_AIF2_BCLK_FRC_SHIFT 6 /* AIF2_BCLK_FRC */ -#define WM5100_AIF2_BCLK_FRC_WIDTH 1 /* AIF2_BCLK_FRC */ -#define WM5100_AIF2_BCLK_MSTR 0x0020 /* AIF2_BCLK_MSTR */ -#define WM5100_AIF2_BCLK_MSTR_MASK 0x0020 /* AIF2_BCLK_MSTR */ -#define WM5100_AIF2_BCLK_MSTR_SHIFT 5 /* AIF2_BCLK_MSTR */ -#define WM5100_AIF2_BCLK_MSTR_WIDTH 1 /* AIF2_BCLK_MSTR */ -#define WM5100_AIF2_BCLK_FREQ_MASK 0x001F /* AIF2_BCLK_FREQ - [4:0] */ -#define WM5100_AIF2_BCLK_FREQ_SHIFT 0 /* AIF2_BCLK_FREQ - [4:0] */ -#define WM5100_AIF2_BCLK_FREQ_WIDTH 5 /* AIF2_BCLK_FREQ - [4:0] */ - -/* - * R1345 (0x541) - Audio IF 2_2 - */ -#define WM5100_AIF2TX_DAT_TRI 0x0020 /* AIF2TX_DAT_TRI */ -#define WM5100_AIF2TX_DAT_TRI_MASK 0x0020 /* AIF2TX_DAT_TRI */ -#define WM5100_AIF2TX_DAT_TRI_SHIFT 5 /* AIF2TX_DAT_TRI */ -#define WM5100_AIF2TX_DAT_TRI_WIDTH 1 /* AIF2TX_DAT_TRI */ -#define WM5100_AIF2TX_LRCLK_SRC 0x0008 /* AIF2TX_LRCLK_SRC */ -#define WM5100_AIF2TX_LRCLK_SRC_MASK 0x0008 /* AIF2TX_LRCLK_SRC */ -#define WM5100_AIF2TX_LRCLK_SRC_SHIFT 3 /* AIF2TX_LRCLK_SRC */ -#define WM5100_AIF2TX_LRCLK_SRC_WIDTH 1 /* AIF2TX_LRCLK_SRC */ -#define WM5100_AIF2TX_LRCLK_INV 0x0004 /* AIF2TX_LRCLK_INV */ -#define WM5100_AIF2TX_LRCLK_INV_MASK 0x0004 /* AIF2TX_LRCLK_INV */ -#define WM5100_AIF2TX_LRCLK_INV_SHIFT 2 /* AIF2TX_LRCLK_INV */ -#define WM5100_AIF2TX_LRCLK_INV_WIDTH 1 /* AIF2TX_LRCLK_INV */ -#define WM5100_AIF2TX_LRCLK_FRC 0x0002 /* AIF2TX_LRCLK_FRC */ -#define WM5100_AIF2TX_LRCLK_FRC_MASK 0x0002 /* AIF2TX_LRCLK_FRC */ -#define WM5100_AIF2TX_LRCLK_FRC_SHIFT 1 /* AIF2TX_LRCLK_FRC */ -#define WM5100_AIF2TX_LRCLK_FRC_WIDTH 1 /* AIF2TX_LRCLK_FRC */ -#define WM5100_AIF2TX_LRCLK_MSTR 0x0001 /* AIF2TX_LRCLK_MSTR */ -#define WM5100_AIF2TX_LRCLK_MSTR_MASK 0x0001 /* AIF2TX_LRCLK_MSTR */ -#define WM5100_AIF2TX_LRCLK_MSTR_SHIFT 0 /* AIF2TX_LRCLK_MSTR */ -#define WM5100_AIF2TX_LRCLK_MSTR_WIDTH 1 /* AIF2TX_LRCLK_MSTR */ - -/* - * R1346 (0x542) - Audio IF 2_3 - */ -#define WM5100_AIF2RX_LRCLK_INV 0x0004 /* AIF2RX_LRCLK_INV */ -#define WM5100_AIF2RX_LRCLK_INV_MASK 0x0004 /* AIF2RX_LRCLK_INV */ -#define WM5100_AIF2RX_LRCLK_INV_SHIFT 2 /* AIF2RX_LRCLK_INV */ -#define WM5100_AIF2RX_LRCLK_INV_WIDTH 1 /* AIF2RX_LRCLK_INV */ -#define WM5100_AIF2RX_LRCLK_FRC 0x0002 /* AIF2RX_LRCLK_FRC */ -#define WM5100_AIF2RX_LRCLK_FRC_MASK 0x0002 /* AIF2RX_LRCLK_FRC */ -#define WM5100_AIF2RX_LRCLK_FRC_SHIFT 1 /* AIF2RX_LRCLK_FRC */ -#define WM5100_AIF2RX_LRCLK_FRC_WIDTH 1 /* AIF2RX_LRCLK_FRC */ -#define WM5100_AIF2RX_LRCLK_MSTR 0x0001 /* AIF2RX_LRCLK_MSTR */ -#define WM5100_AIF2RX_LRCLK_MSTR_MASK 0x0001 /* AIF2RX_LRCLK_MSTR */ -#define WM5100_AIF2RX_LRCLK_MSTR_SHIFT 0 /* AIF2RX_LRCLK_MSTR */ -#define WM5100_AIF2RX_LRCLK_MSTR_WIDTH 1 /* AIF2RX_LRCLK_MSTR */ - -/* - * R1347 (0x543) - Audio IF 2_4 - */ -#define WM5100_AIF2_TRI 0x0040 /* AIF2_TRI */ -#define WM5100_AIF2_TRI_MASK 0x0040 /* AIF2_TRI */ -#define WM5100_AIF2_TRI_SHIFT 6 /* AIF2_TRI */ -#define WM5100_AIF2_TRI_WIDTH 1 /* AIF2_TRI */ -#define WM5100_AIF2_RATE_MASK 0x0003 /* AIF2_RATE - [1:0] */ -#define WM5100_AIF2_RATE_SHIFT 0 /* AIF2_RATE - [1:0] */ -#define WM5100_AIF2_RATE_WIDTH 2 /* AIF2_RATE - [1:0] */ - -/* - * R1348 (0x544) - Audio IF 2_5 - */ -#define WM5100_AIF2_FMT_MASK 0x0007 /* AIF2_FMT - [2:0] */ -#define WM5100_AIF2_FMT_SHIFT 0 /* AIF2_FMT - [2:0] */ -#define WM5100_AIF2_FMT_WIDTH 3 /* AIF2_FMT - [2:0] */ - -/* - * R1349 (0x545) - Audio IF 2_6 - */ -#define WM5100_AIF2TX_BCPF_MASK 0x1FFF /* AIF2TX_BCPF - [12:0] */ -#define WM5100_AIF2TX_BCPF_SHIFT 0 /* AIF2TX_BCPF - [12:0] */ -#define WM5100_AIF2TX_BCPF_WIDTH 13 /* AIF2TX_BCPF - [12:0] */ - -/* - * R1350 (0x546) - Audio IF 2_7 - */ -#define WM5100_AIF2RX_BCPF_MASK 0x1FFF /* AIF2RX_BCPF - [12:0] */ -#define WM5100_AIF2RX_BCPF_SHIFT 0 /* AIF2RX_BCPF - [12:0] */ -#define WM5100_AIF2RX_BCPF_WIDTH 13 /* AIF2RX_BCPF - [12:0] */ - -/* - * R1351 (0x547) - Audio IF 2_8 - */ -#define WM5100_AIF2TX_WL_MASK 0x3F00 /* AIF2TX_WL - [13:8] */ -#define WM5100_AIF2TX_WL_SHIFT 8 /* AIF2TX_WL - [13:8] */ -#define WM5100_AIF2TX_WL_WIDTH 6 /* AIF2TX_WL - [13:8] */ -#define WM5100_AIF2TX_SLOT_LEN_MASK 0x00FF /* AIF2TX_SLOT_LEN - [7:0] */ -#define WM5100_AIF2TX_SLOT_LEN_SHIFT 0 /* AIF2TX_SLOT_LEN - [7:0] */ -#define WM5100_AIF2TX_SLOT_LEN_WIDTH 8 /* AIF2TX_SLOT_LEN - [7:0] */ - -/* - * R1352 (0x548) - Audio IF 2_9 - */ -#define WM5100_AIF2RX_WL_MASK 0x3F00 /* AIF2RX_WL - [13:8] */ -#define WM5100_AIF2RX_WL_SHIFT 8 /* AIF2RX_WL - [13:8] */ -#define WM5100_AIF2RX_WL_WIDTH 6 /* AIF2RX_WL - [13:8] */ -#define WM5100_AIF2RX_SLOT_LEN_MASK 0x00FF /* AIF2RX_SLOT_LEN - [7:0] */ -#define WM5100_AIF2RX_SLOT_LEN_SHIFT 0 /* AIF2RX_SLOT_LEN - [7:0] */ -#define WM5100_AIF2RX_SLOT_LEN_WIDTH 8 /* AIF2RX_SLOT_LEN - [7:0] */ - -/* - * R1353 (0x549) - Audio IF 2_10 - */ -#define WM5100_AIF2TX1_SLOT_MASK 0x003F /* AIF2TX1_SLOT - [5:0] */ -#define WM5100_AIF2TX1_SLOT_SHIFT 0 /* AIF2TX1_SLOT - [5:0] */ -#define WM5100_AIF2TX1_SLOT_WIDTH 6 /* AIF2TX1_SLOT - [5:0] */ - -/* - * R1354 (0x54A) - Audio IF 2_11 - */ -#define WM5100_AIF2TX2_SLOT_MASK 0x003F /* AIF2TX2_SLOT - [5:0] */ -#define WM5100_AIF2TX2_SLOT_SHIFT 0 /* AIF2TX2_SLOT - [5:0] */ -#define WM5100_AIF2TX2_SLOT_WIDTH 6 /* AIF2TX2_SLOT - [5:0] */ - -/* - * R1361 (0x551) - Audio IF 2_18 - */ -#define WM5100_AIF2RX1_SLOT_MASK 0x003F /* AIF2RX1_SLOT - [5:0] */ -#define WM5100_AIF2RX1_SLOT_SHIFT 0 /* AIF2RX1_SLOT - [5:0] */ -#define WM5100_AIF2RX1_SLOT_WIDTH 6 /* AIF2RX1_SLOT - [5:0] */ - -/* - * R1362 (0x552) - Audio IF 2_19 - */ -#define WM5100_AIF2RX2_SLOT_MASK 0x003F /* AIF2RX2_SLOT - [5:0] */ -#define WM5100_AIF2RX2_SLOT_SHIFT 0 /* AIF2RX2_SLOT - [5:0] */ -#define WM5100_AIF2RX2_SLOT_WIDTH 6 /* AIF2RX2_SLOT - [5:0] */ - -/* - * R1369 (0x559) - Audio IF 2_26 - */ -#define WM5100_AIF2TX2_ENA 0x0002 /* AIF2TX2_ENA */ -#define WM5100_AIF2TX2_ENA_MASK 0x0002 /* AIF2TX2_ENA */ -#define WM5100_AIF2TX2_ENA_SHIFT 1 /* AIF2TX2_ENA */ -#define WM5100_AIF2TX2_ENA_WIDTH 1 /* AIF2TX2_ENA */ -#define WM5100_AIF2TX1_ENA 0x0001 /* AIF2TX1_ENA */ -#define WM5100_AIF2TX1_ENA_MASK 0x0001 /* AIF2TX1_ENA */ -#define WM5100_AIF2TX1_ENA_SHIFT 0 /* AIF2TX1_ENA */ -#define WM5100_AIF2TX1_ENA_WIDTH 1 /* AIF2TX1_ENA */ - -/* - * R1370 (0x55A) - Audio IF 2_27 - */ -#define WM5100_AIF2RX2_ENA 0x0002 /* AIF2RX2_ENA */ -#define WM5100_AIF2RX2_ENA_MASK 0x0002 /* AIF2RX2_ENA */ -#define WM5100_AIF2RX2_ENA_SHIFT 1 /* AIF2RX2_ENA */ -#define WM5100_AIF2RX2_ENA_WIDTH 1 /* AIF2RX2_ENA */ -#define WM5100_AIF2RX1_ENA 0x0001 /* AIF2RX1_ENA */ -#define WM5100_AIF2RX1_ENA_MASK 0x0001 /* AIF2RX1_ENA */ -#define WM5100_AIF2RX1_ENA_SHIFT 0 /* AIF2RX1_ENA */ -#define WM5100_AIF2RX1_ENA_WIDTH 1 /* AIF2RX1_ENA */ - -/* - * R1408 (0x580) - Audio IF 3_1 - */ -#define WM5100_AIF3_BCLK_INV 0x0080 /* AIF3_BCLK_INV */ -#define WM5100_AIF3_BCLK_INV_MASK 0x0080 /* AIF3_BCLK_INV */ -#define WM5100_AIF3_BCLK_INV_SHIFT 7 /* AIF3_BCLK_INV */ -#define WM5100_AIF3_BCLK_INV_WIDTH 1 /* AIF3_BCLK_INV */ -#define WM5100_AIF3_BCLK_FRC 0x0040 /* AIF3_BCLK_FRC */ -#define WM5100_AIF3_BCLK_FRC_MASK 0x0040 /* AIF3_BCLK_FRC */ -#define WM5100_AIF3_BCLK_FRC_SHIFT 6 /* AIF3_BCLK_FRC */ -#define WM5100_AIF3_BCLK_FRC_WIDTH 1 /* AIF3_BCLK_FRC */ -#define WM5100_AIF3_BCLK_MSTR 0x0020 /* AIF3_BCLK_MSTR */ -#define WM5100_AIF3_BCLK_MSTR_MASK 0x0020 /* AIF3_BCLK_MSTR */ -#define WM5100_AIF3_BCLK_MSTR_SHIFT 5 /* AIF3_BCLK_MSTR */ -#define WM5100_AIF3_BCLK_MSTR_WIDTH 1 /* AIF3_BCLK_MSTR */ -#define WM5100_AIF3_BCLK_FREQ_MASK 0x001F /* AIF3_BCLK_FREQ - [4:0] */ -#define WM5100_AIF3_BCLK_FREQ_SHIFT 0 /* AIF3_BCLK_FREQ - [4:0] */ -#define WM5100_AIF3_BCLK_FREQ_WIDTH 5 /* AIF3_BCLK_FREQ - [4:0] */ - -/* - * R1409 (0x581) - Audio IF 3_2 - */ -#define WM5100_AIF3TX_DAT_TRI 0x0020 /* AIF3TX_DAT_TRI */ -#define WM5100_AIF3TX_DAT_TRI_MASK 0x0020 /* AIF3TX_DAT_TRI */ -#define WM5100_AIF3TX_DAT_TRI_SHIFT 5 /* AIF3TX_DAT_TRI */ -#define WM5100_AIF3TX_DAT_TRI_WIDTH 1 /* AIF3TX_DAT_TRI */ -#define WM5100_AIF3TX_LRCLK_SRC 0x0008 /* AIF3TX_LRCLK_SRC */ -#define WM5100_AIF3TX_LRCLK_SRC_MASK 0x0008 /* AIF3TX_LRCLK_SRC */ -#define WM5100_AIF3TX_LRCLK_SRC_SHIFT 3 /* AIF3TX_LRCLK_SRC */ -#define WM5100_AIF3TX_LRCLK_SRC_WIDTH 1 /* AIF3TX_LRCLK_SRC */ -#define WM5100_AIF3TX_LRCLK_INV 0x0004 /* AIF3TX_LRCLK_INV */ -#define WM5100_AIF3TX_LRCLK_INV_MASK 0x0004 /* AIF3TX_LRCLK_INV */ -#define WM5100_AIF3TX_LRCLK_INV_SHIFT 2 /* AIF3TX_LRCLK_INV */ -#define WM5100_AIF3TX_LRCLK_INV_WIDTH 1 /* AIF3TX_LRCLK_INV */ -#define WM5100_AIF3TX_LRCLK_FRC 0x0002 /* AIF3TX_LRCLK_FRC */ -#define WM5100_AIF3TX_LRCLK_FRC_MASK 0x0002 /* AIF3TX_LRCLK_FRC */ -#define WM5100_AIF3TX_LRCLK_FRC_SHIFT 1 /* AIF3TX_LRCLK_FRC */ -#define WM5100_AIF3TX_LRCLK_FRC_WIDTH 1 /* AIF3TX_LRCLK_FRC */ -#define WM5100_AIF3TX_LRCLK_MSTR 0x0001 /* AIF3TX_LRCLK_MSTR */ -#define WM5100_AIF3TX_LRCLK_MSTR_MASK 0x0001 /* AIF3TX_LRCLK_MSTR */ -#define WM5100_AIF3TX_LRCLK_MSTR_SHIFT 0 /* AIF3TX_LRCLK_MSTR */ -#define WM5100_AIF3TX_LRCLK_MSTR_WIDTH 1 /* AIF3TX_LRCLK_MSTR */ - -/* - * R1410 (0x582) - Audio IF 3_3 - */ -#define WM5100_AIF3RX_LRCLK_INV 0x0004 /* AIF3RX_LRCLK_INV */ -#define WM5100_AIF3RX_LRCLK_INV_MASK 0x0004 /* AIF3RX_LRCLK_INV */ -#define WM5100_AIF3RX_LRCLK_INV_SHIFT 2 /* AIF3RX_LRCLK_INV */ -#define WM5100_AIF3RX_LRCLK_INV_WIDTH 1 /* AIF3RX_LRCLK_INV */ -#define WM5100_AIF3RX_LRCLK_FRC 0x0002 /* AIF3RX_LRCLK_FRC */ -#define WM5100_AIF3RX_LRCLK_FRC_MASK 0x0002 /* AIF3RX_LRCLK_FRC */ -#define WM5100_AIF3RX_LRCLK_FRC_SHIFT 1 /* AIF3RX_LRCLK_FRC */ -#define WM5100_AIF3RX_LRCLK_FRC_WIDTH 1 /* AIF3RX_LRCLK_FRC */ -#define WM5100_AIF3RX_LRCLK_MSTR 0x0001 /* AIF3RX_LRCLK_MSTR */ -#define WM5100_AIF3RX_LRCLK_MSTR_MASK 0x0001 /* AIF3RX_LRCLK_MSTR */ -#define WM5100_AIF3RX_LRCLK_MSTR_SHIFT 0 /* AIF3RX_LRCLK_MSTR */ -#define WM5100_AIF3RX_LRCLK_MSTR_WIDTH 1 /* AIF3RX_LRCLK_MSTR */ - -/* - * R1411 (0x583) - Audio IF 3_4 - */ -#define WM5100_AIF3_TRI 0x0040 /* AIF3_TRI */ -#define WM5100_AIF3_TRI_MASK 0x0040 /* AIF3_TRI */ -#define WM5100_AIF3_TRI_SHIFT 6 /* AIF3_TRI */ -#define WM5100_AIF3_TRI_WIDTH 1 /* AIF3_TRI */ -#define WM5100_AIF3_RATE_MASK 0x0003 /* AIF3_RATE - [1:0] */ -#define WM5100_AIF3_RATE_SHIFT 0 /* AIF3_RATE - [1:0] */ -#define WM5100_AIF3_RATE_WIDTH 2 /* AIF3_RATE - [1:0] */ - -/* - * R1412 (0x584) - Audio IF 3_5 - */ -#define WM5100_AIF3_FMT_MASK 0x0007 /* AIF3_FMT - [2:0] */ -#define WM5100_AIF3_FMT_SHIFT 0 /* AIF3_FMT - [2:0] */ -#define WM5100_AIF3_FMT_WIDTH 3 /* AIF3_FMT - [2:0] */ - -/* - * R1413 (0x585) - Audio IF 3_6 - */ -#define WM5100_AIF3TX_BCPF_MASK 0x1FFF /* AIF3TX_BCPF - [12:0] */ -#define WM5100_AIF3TX_BCPF_SHIFT 0 /* AIF3TX_BCPF - [12:0] */ -#define WM5100_AIF3TX_BCPF_WIDTH 13 /* AIF3TX_BCPF - [12:0] */ - -/* - * R1414 (0x586) - Audio IF 3_7 - */ -#define WM5100_AIF3RX_BCPF_MASK 0x1FFF /* AIF3RX_BCPF - [12:0] */ -#define WM5100_AIF3RX_BCPF_SHIFT 0 /* AIF3RX_BCPF - [12:0] */ -#define WM5100_AIF3RX_BCPF_WIDTH 13 /* AIF3RX_BCPF - [12:0] */ - -/* - * R1415 (0x587) - Audio IF 3_8 - */ -#define WM5100_AIF3TX_WL_MASK 0x3F00 /* AIF3TX_WL - [13:8] */ -#define WM5100_AIF3TX_WL_SHIFT 8 /* AIF3TX_WL - [13:8] */ -#define WM5100_AIF3TX_WL_WIDTH 6 /* AIF3TX_WL - [13:8] */ -#define WM5100_AIF3TX_SLOT_LEN_MASK 0x00FF /* AIF3TX_SLOT_LEN - [7:0] */ -#define WM5100_AIF3TX_SLOT_LEN_SHIFT 0 /* AIF3TX_SLOT_LEN - [7:0] */ -#define WM5100_AIF3TX_SLOT_LEN_WIDTH 8 /* AIF3TX_SLOT_LEN - [7:0] */ - -/* - * R1416 (0x588) - Audio IF 3_9 - */ -#define WM5100_AIF3RX_WL_MASK 0x3F00 /* AIF3RX_WL - [13:8] */ -#define WM5100_AIF3RX_WL_SHIFT 8 /* AIF3RX_WL - [13:8] */ -#define WM5100_AIF3RX_WL_WIDTH 6 /* AIF3RX_WL - [13:8] */ -#define WM5100_AIF3RX_SLOT_LEN_MASK 0x00FF /* AIF3RX_SLOT_LEN - [7:0] */ -#define WM5100_AIF3RX_SLOT_LEN_SHIFT 0 /* AIF3RX_SLOT_LEN - [7:0] */ -#define WM5100_AIF3RX_SLOT_LEN_WIDTH 8 /* AIF3RX_SLOT_LEN - [7:0] */ - -/* - * R1417 (0x589) - Audio IF 3_10 - */ -#define WM5100_AIF3TX1_SLOT_MASK 0x003F /* AIF3TX1_SLOT - [5:0] */ -#define WM5100_AIF3TX1_SLOT_SHIFT 0 /* AIF3TX1_SLOT - [5:0] */ -#define WM5100_AIF3TX1_SLOT_WIDTH 6 /* AIF3TX1_SLOT - [5:0] */ - -/* - * R1418 (0x58A) - Audio IF 3_11 - */ -#define WM5100_AIF3TX2_SLOT_MASK 0x003F /* AIF3TX2_SLOT - [5:0] */ -#define WM5100_AIF3TX2_SLOT_SHIFT 0 /* AIF3TX2_SLOT - [5:0] */ -#define WM5100_AIF3TX2_SLOT_WIDTH 6 /* AIF3TX2_SLOT - [5:0] */ - -/* - * R1425 (0x591) - Audio IF 3_18 - */ -#define WM5100_AIF3RX1_SLOT_MASK 0x003F /* AIF3RX1_SLOT - [5:0] */ -#define WM5100_AIF3RX1_SLOT_SHIFT 0 /* AIF3RX1_SLOT - [5:0] */ -#define WM5100_AIF3RX1_SLOT_WIDTH 6 /* AIF3RX1_SLOT - [5:0] */ - -/* - * R1426 (0x592) - Audio IF 3_19 - */ -#define WM5100_AIF3RX2_SLOT_MASK 0x003F /* AIF3RX2_SLOT - [5:0] */ -#define WM5100_AIF3RX2_SLOT_SHIFT 0 /* AIF3RX2_SLOT - [5:0] */ -#define WM5100_AIF3RX2_SLOT_WIDTH 6 /* AIF3RX2_SLOT - [5:0] */ - -/* - * R1433 (0x599) - Audio IF 3_26 - */ -#define WM5100_AIF3TX2_ENA 0x0002 /* AIF3TX2_ENA */ -#define WM5100_AIF3TX2_ENA_MASK 0x0002 /* AIF3TX2_ENA */ -#define WM5100_AIF3TX2_ENA_SHIFT 1 /* AIF3TX2_ENA */ -#define WM5100_AIF3TX2_ENA_WIDTH 1 /* AIF3TX2_ENA */ -#define WM5100_AIF3TX1_ENA 0x0001 /* AIF3TX1_ENA */ -#define WM5100_AIF3TX1_ENA_MASK 0x0001 /* AIF3TX1_ENA */ -#define WM5100_AIF3TX1_ENA_SHIFT 0 /* AIF3TX1_ENA */ -#define WM5100_AIF3TX1_ENA_WIDTH 1 /* AIF3TX1_ENA */ - -/* - * R1434 (0x59A) - Audio IF 3_27 - */ -#define WM5100_AIF3RX2_ENA 0x0002 /* AIF3RX2_ENA */ -#define WM5100_AIF3RX2_ENA_MASK 0x0002 /* AIF3RX2_ENA */ -#define WM5100_AIF3RX2_ENA_SHIFT 1 /* AIF3RX2_ENA */ -#define WM5100_AIF3RX2_ENA_WIDTH 1 /* AIF3RX2_ENA */ -#define WM5100_AIF3RX1_ENA 0x0001 /* AIF3RX1_ENA */ -#define WM5100_AIF3RX1_ENA_MASK 0x0001 /* AIF3RX1_ENA */ -#define WM5100_AIF3RX1_ENA_SHIFT 0 /* AIF3RX1_ENA */ -#define WM5100_AIF3RX1_ENA_WIDTH 1 /* AIF3RX1_ENA */ - -#define WM5100_MIXER_VOL_MASK 0x00FE /* MIXER_VOL - [7:1] */ -#define WM5100_MIXER_VOL_SHIFT 1 /* MIXER_VOL - [7:1] */ -#define WM5100_MIXER_VOL_WIDTH 7 /* MIXER_VOL - [7:1] */ - -/* - * R3072 (0xC00) - GPIO CTRL 1 - */ -#define WM5100_GP1_DIR 0x8000 /* GP1_DIR */ -#define WM5100_GP1_DIR_MASK 0x8000 /* GP1_DIR */ -#define WM5100_GP1_DIR_SHIFT 15 /* GP1_DIR */ -#define WM5100_GP1_DIR_WIDTH 1 /* GP1_DIR */ -#define WM5100_GP1_PU 0x4000 /* GP1_PU */ -#define WM5100_GP1_PU_MASK 0x4000 /* GP1_PU */ -#define WM5100_GP1_PU_SHIFT 14 /* GP1_PU */ -#define WM5100_GP1_PU_WIDTH 1 /* GP1_PU */ -#define WM5100_GP1_PD 0x2000 /* GP1_PD */ -#define WM5100_GP1_PD_MASK 0x2000 /* GP1_PD */ -#define WM5100_GP1_PD_SHIFT 13 /* GP1_PD */ -#define WM5100_GP1_PD_WIDTH 1 /* GP1_PD */ -#define WM5100_GP1_POL 0x0400 /* GP1_POL */ -#define WM5100_GP1_POL_MASK 0x0400 /* GP1_POL */ -#define WM5100_GP1_POL_SHIFT 10 /* GP1_POL */ -#define WM5100_GP1_POL_WIDTH 1 /* GP1_POL */ -#define WM5100_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */ -#define WM5100_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */ -#define WM5100_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */ -#define WM5100_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */ -#define WM5100_GP1_DB 0x0100 /* GP1_DB */ -#define WM5100_GP1_DB_MASK 0x0100 /* GP1_DB */ -#define WM5100_GP1_DB_SHIFT 8 /* GP1_DB */ -#define WM5100_GP1_DB_WIDTH 1 /* GP1_DB */ -#define WM5100_GP1_LVL 0x0040 /* GP1_LVL */ -#define WM5100_GP1_LVL_MASK 0x0040 /* GP1_LVL */ -#define WM5100_GP1_LVL_SHIFT 6 /* GP1_LVL */ -#define WM5100_GP1_LVL_WIDTH 1 /* GP1_LVL */ -#define WM5100_GP1_FN_MASK 0x003F /* GP1_FN - [5:0] */ -#define WM5100_GP1_FN_SHIFT 0 /* GP1_FN - [5:0] */ -#define WM5100_GP1_FN_WIDTH 6 /* GP1_FN - [5:0] */ - -/* - * R3073 (0xC01) - GPIO CTRL 2 - */ -#define WM5100_GP2_DIR 0x8000 /* GP2_DIR */ -#define WM5100_GP2_DIR_MASK 0x8000 /* GP2_DIR */ -#define WM5100_GP2_DIR_SHIFT 15 /* GP2_DIR */ -#define WM5100_GP2_DIR_WIDTH 1 /* GP2_DIR */ -#define WM5100_GP2_PU 0x4000 /* GP2_PU */ -#define WM5100_GP2_PU_MASK 0x4000 /* GP2_PU */ -#define WM5100_GP2_PU_SHIFT 14 /* GP2_PU */ -#define WM5100_GP2_PU_WIDTH 1 /* GP2_PU */ -#define WM5100_GP2_PD 0x2000 /* GP2_PD */ -#define WM5100_GP2_PD_MASK 0x2000 /* GP2_PD */ -#define WM5100_GP2_PD_SHIFT 13 /* GP2_PD */ -#define WM5100_GP2_PD_WIDTH 1 /* GP2_PD */ -#define WM5100_GP2_POL 0x0400 /* GP2_POL */ -#define WM5100_GP2_POL_MASK 0x0400 /* GP2_POL */ -#define WM5100_GP2_POL_SHIFT 10 /* GP2_POL */ -#define WM5100_GP2_POL_WIDTH 1 /* GP2_POL */ -#define WM5100_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */ -#define WM5100_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */ -#define WM5100_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */ -#define WM5100_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */ -#define WM5100_GP2_DB 0x0100 /* GP2_DB */ -#define WM5100_GP2_DB_MASK 0x0100 /* GP2_DB */ -#define WM5100_GP2_DB_SHIFT 8 /* GP2_DB */ -#define WM5100_GP2_DB_WIDTH 1 /* GP2_DB */ -#define WM5100_GP2_LVL 0x0040 /* GP2_LVL */ -#define WM5100_GP2_LVL_MASK 0x0040 /* GP2_LVL */ -#define WM5100_GP2_LVL_SHIFT 6 /* GP2_LVL */ -#define WM5100_GP2_LVL_WIDTH 1 /* GP2_LVL */ -#define WM5100_GP2_FN_MASK 0x003F /* GP2_FN - [5:0] */ -#define WM5100_GP2_FN_SHIFT 0 /* GP2_FN - [5:0] */ -#define WM5100_GP2_FN_WIDTH 6 /* GP2_FN - [5:0] */ - -/* - * R3074 (0xC02) - GPIO CTRL 3 - */ -#define WM5100_GP3_DIR 0x8000 /* GP3_DIR */ -#define WM5100_GP3_DIR_MASK 0x8000 /* GP3_DIR */ -#define WM5100_GP3_DIR_SHIFT 15 /* GP3_DIR */ -#define WM5100_GP3_DIR_WIDTH 1 /* GP3_DIR */ -#define WM5100_GP3_PU 0x4000 /* GP3_PU */ -#define WM5100_GP3_PU_MASK 0x4000 /* GP3_PU */ -#define WM5100_GP3_PU_SHIFT 14 /* GP3_PU */ -#define WM5100_GP3_PU_WIDTH 1 /* GP3_PU */ -#define WM5100_GP3_PD 0x2000 /* GP3_PD */ -#define WM5100_GP3_PD_MASK 0x2000 /* GP3_PD */ -#define WM5100_GP3_PD_SHIFT 13 /* GP3_PD */ -#define WM5100_GP3_PD_WIDTH 1 /* GP3_PD */ -#define WM5100_GP3_POL 0x0400 /* GP3_POL */ -#define WM5100_GP3_POL_MASK 0x0400 /* GP3_POL */ -#define WM5100_GP3_POL_SHIFT 10 /* GP3_POL */ -#define WM5100_GP3_POL_WIDTH 1 /* GP3_POL */ -#define WM5100_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */ -#define WM5100_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */ -#define WM5100_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */ -#define WM5100_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */ -#define WM5100_GP3_DB 0x0100 /* GP3_DB */ -#define WM5100_GP3_DB_MASK 0x0100 /* GP3_DB */ -#define WM5100_GP3_DB_SHIFT 8 /* GP3_DB */ -#define WM5100_GP3_DB_WIDTH 1 /* GP3_DB */ -#define WM5100_GP3_LVL 0x0040 /* GP3_LVL */ -#define WM5100_GP3_LVL_MASK 0x0040 /* GP3_LVL */ -#define WM5100_GP3_LVL_SHIFT 6 /* GP3_LVL */ -#define WM5100_GP3_LVL_WIDTH 1 /* GP3_LVL */ -#define WM5100_GP3_FN_MASK 0x003F /* GP3_FN - [5:0] */ -#define WM5100_GP3_FN_SHIFT 0 /* GP3_FN - [5:0] */ -#define WM5100_GP3_FN_WIDTH 6 /* GP3_FN - [5:0] */ - -/* - * R3075 (0xC03) - GPIO CTRL 4 - */ -#define WM5100_GP4_DIR 0x8000 /* GP4_DIR */ -#define WM5100_GP4_DIR_MASK 0x8000 /* GP4_DIR */ -#define WM5100_GP4_DIR_SHIFT 15 /* GP4_DIR */ -#define WM5100_GP4_DIR_WIDTH 1 /* GP4_DIR */ -#define WM5100_GP4_PU 0x4000 /* GP4_PU */ -#define WM5100_GP4_PU_MASK 0x4000 /* GP4_PU */ -#define WM5100_GP4_PU_SHIFT 14 /* GP4_PU */ -#define WM5100_GP4_PU_WIDTH 1 /* GP4_PU */ -#define WM5100_GP4_PD 0x2000 /* GP4_PD */ -#define WM5100_GP4_PD_MASK 0x2000 /* GP4_PD */ -#define WM5100_GP4_PD_SHIFT 13 /* GP4_PD */ -#define WM5100_GP4_PD_WIDTH 1 /* GP4_PD */ -#define WM5100_GP4_POL 0x0400 /* GP4_POL */ -#define WM5100_GP4_POL_MASK 0x0400 /* GP4_POL */ -#define WM5100_GP4_POL_SHIFT 10 /* GP4_POL */ -#define WM5100_GP4_POL_WIDTH 1 /* GP4_POL */ -#define WM5100_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */ -#define WM5100_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */ -#define WM5100_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */ -#define WM5100_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */ -#define WM5100_GP4_DB 0x0100 /* GP4_DB */ -#define WM5100_GP4_DB_MASK 0x0100 /* GP4_DB */ -#define WM5100_GP4_DB_SHIFT 8 /* GP4_DB */ -#define WM5100_GP4_DB_WIDTH 1 /* GP4_DB */ -#define WM5100_GP4_LVL 0x0040 /* GP4_LVL */ -#define WM5100_GP4_LVL_MASK 0x0040 /* GP4_LVL */ -#define WM5100_GP4_LVL_SHIFT 6 /* GP4_LVL */ -#define WM5100_GP4_LVL_WIDTH 1 /* GP4_LVL */ -#define WM5100_GP4_FN_MASK 0x003F /* GP4_FN - [5:0] */ -#define WM5100_GP4_FN_SHIFT 0 /* GP4_FN - [5:0] */ -#define WM5100_GP4_FN_WIDTH 6 /* GP4_FN - [5:0] */ - -/* - * R3076 (0xC04) - GPIO CTRL 5 - */ -#define WM5100_GP5_DIR 0x8000 /* GP5_DIR */ -#define WM5100_GP5_DIR_MASK 0x8000 /* GP5_DIR */ -#define WM5100_GP5_DIR_SHIFT 15 /* GP5_DIR */ -#define WM5100_GP5_DIR_WIDTH 1 /* GP5_DIR */ -#define WM5100_GP5_PU 0x4000 /* GP5_PU */ -#define WM5100_GP5_PU_MASK 0x4000 /* GP5_PU */ -#define WM5100_GP5_PU_SHIFT 14 /* GP5_PU */ -#define WM5100_GP5_PU_WIDTH 1 /* GP5_PU */ -#define WM5100_GP5_PD 0x2000 /* GP5_PD */ -#define WM5100_GP5_PD_MASK 0x2000 /* GP5_PD */ -#define WM5100_GP5_PD_SHIFT 13 /* GP5_PD */ -#define WM5100_GP5_PD_WIDTH 1 /* GP5_PD */ -#define WM5100_GP5_POL 0x0400 /* GP5_POL */ -#define WM5100_GP5_POL_MASK 0x0400 /* GP5_POL */ -#define WM5100_GP5_POL_SHIFT 10 /* GP5_POL */ -#define WM5100_GP5_POL_WIDTH 1 /* GP5_POL */ -#define WM5100_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */ -#define WM5100_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */ -#define WM5100_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */ -#define WM5100_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */ -#define WM5100_GP5_DB 0x0100 /* GP5_DB */ -#define WM5100_GP5_DB_MASK 0x0100 /* GP5_DB */ -#define WM5100_GP5_DB_SHIFT 8 /* GP5_DB */ -#define WM5100_GP5_DB_WIDTH 1 /* GP5_DB */ -#define WM5100_GP5_LVL 0x0040 /* GP5_LVL */ -#define WM5100_GP5_LVL_MASK 0x0040 /* GP5_LVL */ -#define WM5100_GP5_LVL_SHIFT 6 /* GP5_LVL */ -#define WM5100_GP5_LVL_WIDTH 1 /* GP5_LVL */ -#define WM5100_GP5_FN_MASK 0x003F /* GP5_FN - [5:0] */ -#define WM5100_GP5_FN_SHIFT 0 /* GP5_FN - [5:0] */ -#define WM5100_GP5_FN_WIDTH 6 /* GP5_FN - [5:0] */ - -/* - * R3077 (0xC05) - GPIO CTRL 6 - */ -#define WM5100_GP6_DIR 0x8000 /* GP6_DIR */ -#define WM5100_GP6_DIR_MASK 0x8000 /* GP6_DIR */ -#define WM5100_GP6_DIR_SHIFT 15 /* GP6_DIR */ -#define WM5100_GP6_DIR_WIDTH 1 /* GP6_DIR */ -#define WM5100_GP6_PU 0x4000 /* GP6_PU */ -#define WM5100_GP6_PU_MASK 0x4000 /* GP6_PU */ -#define WM5100_GP6_PU_SHIFT 14 /* GP6_PU */ -#define WM5100_GP6_PU_WIDTH 1 /* GP6_PU */ -#define WM5100_GP6_PD 0x2000 /* GP6_PD */ -#define WM5100_GP6_PD_MASK 0x2000 /* GP6_PD */ -#define WM5100_GP6_PD_SHIFT 13 /* GP6_PD */ -#define WM5100_GP6_PD_WIDTH 1 /* GP6_PD */ -#define WM5100_GP6_POL 0x0400 /* GP6_POL */ -#define WM5100_GP6_POL_MASK 0x0400 /* GP6_POL */ -#define WM5100_GP6_POL_SHIFT 10 /* GP6_POL */ -#define WM5100_GP6_POL_WIDTH 1 /* GP6_POL */ -#define WM5100_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */ -#define WM5100_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */ -#define WM5100_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */ -#define WM5100_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */ -#define WM5100_GP6_DB 0x0100 /* GP6_DB */ -#define WM5100_GP6_DB_MASK 0x0100 /* GP6_DB */ -#define WM5100_GP6_DB_SHIFT 8 /* GP6_DB */ -#define WM5100_GP6_DB_WIDTH 1 /* GP6_DB */ -#define WM5100_GP6_LVL 0x0040 /* GP6_LVL */ -#define WM5100_GP6_LVL_MASK 0x0040 /* GP6_LVL */ -#define WM5100_GP6_LVL_SHIFT 6 /* GP6_LVL */ -#define WM5100_GP6_LVL_WIDTH 1 /* GP6_LVL */ -#define WM5100_GP6_FN_MASK 0x003F /* GP6_FN - [5:0] */ -#define WM5100_GP6_FN_SHIFT 0 /* GP6_FN - [5:0] */ -#define WM5100_GP6_FN_WIDTH 6 /* GP6_FN - [5:0] */ - -/* - * R3107 (0xC23) - Misc Pad Ctrl 1 - */ -#define WM5100_LDO1ENA_PD 0x8000 /* LDO1ENA_PD */ -#define WM5100_LDO1ENA_PD_MASK 0x8000 /* LDO1ENA_PD */ -#define WM5100_LDO1ENA_PD_SHIFT 15 /* LDO1ENA_PD */ -#define WM5100_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */ -#define WM5100_MCLK2_PD 0x2000 /* MCLK2_PD */ -#define WM5100_MCLK2_PD_MASK 0x2000 /* MCLK2_PD */ -#define WM5100_MCLK2_PD_SHIFT 13 /* MCLK2_PD */ -#define WM5100_MCLK2_PD_WIDTH 1 /* MCLK2_PD */ -#define WM5100_MCLK1_PD 0x1000 /* MCLK1_PD */ -#define WM5100_MCLK1_PD_MASK 0x1000 /* MCLK1_PD */ -#define WM5100_MCLK1_PD_SHIFT 12 /* MCLK1_PD */ -#define WM5100_MCLK1_PD_WIDTH 1 /* MCLK1_PD */ -#define WM5100_RESET_PU 0x0002 /* RESET_PU */ -#define WM5100_RESET_PU_MASK 0x0002 /* RESET_PU */ -#define WM5100_RESET_PU_SHIFT 1 /* RESET_PU */ -#define WM5100_RESET_PU_WIDTH 1 /* RESET_PU */ -#define WM5100_ADDR_PD 0x0001 /* ADDR_PD */ -#define WM5100_ADDR_PD_MASK 0x0001 /* ADDR_PD */ -#define WM5100_ADDR_PD_SHIFT 0 /* ADDR_PD */ -#define WM5100_ADDR_PD_WIDTH 1 /* ADDR_PD */ - -/* - * R3108 (0xC24) - Misc Pad Ctrl 2 - */ -#define WM5100_DMICDAT4_PD 0x0008 /* DMICDAT4_PD */ -#define WM5100_DMICDAT4_PD_MASK 0x0008 /* DMICDAT4_PD */ -#define WM5100_DMICDAT4_PD_SHIFT 3 /* DMICDAT4_PD */ -#define WM5100_DMICDAT4_PD_WIDTH 1 /* DMICDAT4_PD */ -#define WM5100_DMICDAT3_PD 0x0004 /* DMICDAT3_PD */ -#define WM5100_DMICDAT3_PD_MASK 0x0004 /* DMICDAT3_PD */ -#define WM5100_DMICDAT3_PD_SHIFT 2 /* DMICDAT3_PD */ -#define WM5100_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */ -#define WM5100_DMICDAT2_PD 0x0002 /* DMICDAT2_PD */ -#define WM5100_DMICDAT2_PD_MASK 0x0002 /* DMICDAT2_PD */ -#define WM5100_DMICDAT2_PD_SHIFT 1 /* DMICDAT2_PD */ -#define WM5100_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */ -#define WM5100_DMICDAT1_PD 0x0001 /* DMICDAT1_PD */ -#define WM5100_DMICDAT1_PD_MASK 0x0001 /* DMICDAT1_PD */ -#define WM5100_DMICDAT1_PD_SHIFT 0 /* DMICDAT1_PD */ -#define WM5100_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */ - -/* - * R3109 (0xC25) - Misc Pad Ctrl 3 - */ -#define WM5100_AIF1RXLRCLK_PU 0x0020 /* AIF1RXLRCLK_PU */ -#define WM5100_AIF1RXLRCLK_PU_MASK 0x0020 /* AIF1RXLRCLK_PU */ -#define WM5100_AIF1RXLRCLK_PU_SHIFT 5 /* AIF1RXLRCLK_PU */ -#define WM5100_AIF1RXLRCLK_PU_WIDTH 1 /* AIF1RXLRCLK_PU */ -#define WM5100_AIF1RXLRCLK_PD 0x0010 /* AIF1RXLRCLK_PD */ -#define WM5100_AIF1RXLRCLK_PD_MASK 0x0010 /* AIF1RXLRCLK_PD */ -#define WM5100_AIF1RXLRCLK_PD_SHIFT 4 /* AIF1RXLRCLK_PD */ -#define WM5100_AIF1RXLRCLK_PD_WIDTH 1 /* AIF1RXLRCLK_PD */ -#define WM5100_AIF1BCLK_PU 0x0008 /* AIF1BCLK_PU */ -#define WM5100_AIF1BCLK_PU_MASK 0x0008 /* AIF1BCLK_PU */ -#define WM5100_AIF1BCLK_PU_SHIFT 3 /* AIF1BCLK_PU */ -#define WM5100_AIF1BCLK_PU_WIDTH 1 /* AIF1BCLK_PU */ -#define WM5100_AIF1BCLK_PD 0x0004 /* AIF1BCLK_PD */ -#define WM5100_AIF1BCLK_PD_MASK 0x0004 /* AIF1BCLK_PD */ -#define WM5100_AIF1BCLK_PD_SHIFT 2 /* AIF1BCLK_PD */ -#define WM5100_AIF1BCLK_PD_WIDTH 1 /* AIF1BCLK_PD */ -#define WM5100_AIF1RXDAT_PU 0x0002 /* AIF1RXDAT_PU */ -#define WM5100_AIF1RXDAT_PU_MASK 0x0002 /* AIF1RXDAT_PU */ -#define WM5100_AIF1RXDAT_PU_SHIFT 1 /* AIF1RXDAT_PU */ -#define WM5100_AIF1RXDAT_PU_WIDTH 1 /* AIF1RXDAT_PU */ -#define WM5100_AIF1RXDAT_PD 0x0001 /* AIF1RXDAT_PD */ -#define WM5100_AIF1RXDAT_PD_MASK 0x0001 /* AIF1RXDAT_PD */ -#define WM5100_AIF1RXDAT_PD_SHIFT 0 /* AIF1RXDAT_PD */ -#define WM5100_AIF1RXDAT_PD_WIDTH 1 /* AIF1RXDAT_PD */ - -/* - * R3110 (0xC26) - Misc Pad Ctrl 4 - */ -#define WM5100_AIF2RXLRCLK_PU 0x0020 /* AIF2RXLRCLK_PU */ -#define WM5100_AIF2RXLRCLK_PU_MASK 0x0020 /* AIF2RXLRCLK_PU */ -#define WM5100_AIF2RXLRCLK_PU_SHIFT 5 /* AIF2RXLRCLK_PU */ -#define WM5100_AIF2RXLRCLK_PU_WIDTH 1 /* AIF2RXLRCLK_PU */ -#define WM5100_AIF2RXLRCLK_PD 0x0010 /* AIF2RXLRCLK_PD */ -#define WM5100_AIF2RXLRCLK_PD_MASK 0x0010 /* AIF2RXLRCLK_PD */ -#define WM5100_AIF2RXLRCLK_PD_SHIFT 4 /* AIF2RXLRCLK_PD */ -#define WM5100_AIF2RXLRCLK_PD_WIDTH 1 /* AIF2RXLRCLK_PD */ -#define WM5100_AIF2BCLK_PU 0x0008 /* AIF2BCLK_PU */ -#define WM5100_AIF2BCLK_PU_MASK 0x0008 /* AIF2BCLK_PU */ -#define WM5100_AIF2BCLK_PU_SHIFT 3 /* AIF2BCLK_PU */ -#define WM5100_AIF2BCLK_PU_WIDTH 1 /* AIF2BCLK_PU */ -#define WM5100_AIF2BCLK_PD 0x0004 /* AIF2BCLK_PD */ -#define WM5100_AIF2BCLK_PD_MASK 0x0004 /* AIF2BCLK_PD */ -#define WM5100_AIF2BCLK_PD_SHIFT 2 /* AIF2BCLK_PD */ -#define WM5100_AIF2BCLK_PD_WIDTH 1 /* AIF2BCLK_PD */ -#define WM5100_AIF2RXDAT_PU 0x0002 /* AIF2RXDAT_PU */ -#define WM5100_AIF2RXDAT_PU_MASK 0x0002 /* AIF2RXDAT_PU */ -#define WM5100_AIF2RXDAT_PU_SHIFT 1 /* AIF2RXDAT_PU */ -#define WM5100_AIF2RXDAT_PU_WIDTH 1 /* AIF2RXDAT_PU */ -#define WM5100_AIF2RXDAT_PD 0x0001 /* AIF2RXDAT_PD */ -#define WM5100_AIF2RXDAT_PD_MASK 0x0001 /* AIF2RXDAT_PD */ -#define WM5100_AIF2RXDAT_PD_SHIFT 0 /* AIF2RXDAT_PD */ -#define WM5100_AIF2RXDAT_PD_WIDTH 1 /* AIF2RXDAT_PD */ - -/* - * R3111 (0xC27) - Misc Pad Ctrl 5 - */ -#define WM5100_AIF3RXLRCLK_PU 0x0020 /* AIF3RXLRCLK_PU */ -#define WM5100_AIF3RXLRCLK_PU_MASK 0x0020 /* AIF3RXLRCLK_PU */ -#define WM5100_AIF3RXLRCLK_PU_SHIFT 5 /* AIF3RXLRCLK_PU */ -#define WM5100_AIF3RXLRCLK_PU_WIDTH 1 /* AIF3RXLRCLK_PU */ -#define WM5100_AIF3RXLRCLK_PD 0x0010 /* AIF3RXLRCLK_PD */ -#define WM5100_AIF3RXLRCLK_PD_MASK 0x0010 /* AIF3RXLRCLK_PD */ -#define WM5100_AIF3RXLRCLK_PD_SHIFT 4 /* AIF3RXLRCLK_PD */ -#define WM5100_AIF3RXLRCLK_PD_WIDTH 1 /* AIF3RXLRCLK_PD */ -#define WM5100_AIF3BCLK_PU 0x0008 /* AIF3BCLK_PU */ -#define WM5100_AIF3BCLK_PU_MASK 0x0008 /* AIF3BCLK_PU */ -#define WM5100_AIF3BCLK_PU_SHIFT 3 /* AIF3BCLK_PU */ -#define WM5100_AIF3BCLK_PU_WIDTH 1 /* AIF3BCLK_PU */ -#define WM5100_AIF3BCLK_PD 0x0004 /* AIF3BCLK_PD */ -#define WM5100_AIF3BCLK_PD_MASK 0x0004 /* AIF3BCLK_PD */ -#define WM5100_AIF3BCLK_PD_SHIFT 2 /* AIF3BCLK_PD */ -#define WM5100_AIF3BCLK_PD_WIDTH 1 /* AIF3BCLK_PD */ -#define WM5100_AIF3RXDAT_PU 0x0002 /* AIF3RXDAT_PU */ -#define WM5100_AIF3RXDAT_PU_MASK 0x0002 /* AIF3RXDAT_PU */ -#define WM5100_AIF3RXDAT_PU_SHIFT 1 /* AIF3RXDAT_PU */ -#define WM5100_AIF3RXDAT_PU_WIDTH 1 /* AIF3RXDAT_PU */ -#define WM5100_AIF3RXDAT_PD 0x0001 /* AIF3RXDAT_PD */ -#define WM5100_AIF3RXDAT_PD_MASK 0x0001 /* AIF3RXDAT_PD */ -#define WM5100_AIF3RXDAT_PD_SHIFT 0 /* AIF3RXDAT_PD */ -#define WM5100_AIF3RXDAT_PD_WIDTH 1 /* AIF3RXDAT_PD */ - -/* - * R3112 (0xC28) - Misc GPIO 1 - */ -#define WM5100_OPCLK_SEL_MASK 0x0003 /* OPCLK_SEL - [1:0] */ -#define WM5100_OPCLK_SEL_SHIFT 0 /* OPCLK_SEL - [1:0] */ -#define WM5100_OPCLK_SEL_WIDTH 2 /* OPCLK_SEL - [1:0] */ - -/* - * R3328 (0xD00) - Interrupt Status 1 - */ -#define WM5100_GP6_EINT 0x0020 /* GP6_EINT */ -#define WM5100_GP6_EINT_MASK 0x0020 /* GP6_EINT */ -#define WM5100_GP6_EINT_SHIFT 5 /* GP6_EINT */ -#define WM5100_GP6_EINT_WIDTH 1 /* GP6_EINT */ -#define WM5100_GP5_EINT 0x0010 /* GP5_EINT */ -#define WM5100_GP5_EINT_MASK 0x0010 /* GP5_EINT */ -#define WM5100_GP5_EINT_SHIFT 4 /* GP5_EINT */ -#define WM5100_GP5_EINT_WIDTH 1 /* GP5_EINT */ -#define WM5100_GP4_EINT 0x0008 /* GP4_EINT */ -#define WM5100_GP4_EINT_MASK 0x0008 /* GP4_EINT */ -#define WM5100_GP4_EINT_SHIFT 3 /* GP4_EINT */ -#define WM5100_GP4_EINT_WIDTH 1 /* GP4_EINT */ -#define WM5100_GP3_EINT 0x0004 /* GP3_EINT */ -#define WM5100_GP3_EINT_MASK 0x0004 /* GP3_EINT */ -#define WM5100_GP3_EINT_SHIFT 2 /* GP3_EINT */ -#define WM5100_GP3_EINT_WIDTH 1 /* GP3_EINT */ -#define WM5100_GP2_EINT 0x0002 /* GP2_EINT */ -#define WM5100_GP2_EINT_MASK 0x0002 /* GP2_EINT */ -#define WM5100_GP2_EINT_SHIFT 1 /* GP2_EINT */ -#define WM5100_GP2_EINT_WIDTH 1 /* GP2_EINT */ -#define WM5100_GP1_EINT 0x0001 /* GP1_EINT */ -#define WM5100_GP1_EINT_MASK 0x0001 /* GP1_EINT */ -#define WM5100_GP1_EINT_SHIFT 0 /* GP1_EINT */ -#define WM5100_GP1_EINT_WIDTH 1 /* GP1_EINT */ - -/* - * R3329 (0xD01) - Interrupt Status 2 - */ -#define WM5100_DSP_IRQ6_EINT 0x0020 /* DSP_IRQ6_EINT */ -#define WM5100_DSP_IRQ6_EINT_MASK 0x0020 /* DSP_IRQ6_EINT */ -#define WM5100_DSP_IRQ6_EINT_SHIFT 5 /* DSP_IRQ6_EINT */ -#define WM5100_DSP_IRQ6_EINT_WIDTH 1 /* DSP_IRQ6_EINT */ -#define WM5100_DSP_IRQ5_EINT 0x0010 /* DSP_IRQ5_EINT */ -#define WM5100_DSP_IRQ5_EINT_MASK 0x0010 /* DSP_IRQ5_EINT */ -#define WM5100_DSP_IRQ5_EINT_SHIFT 4 /* DSP_IRQ5_EINT */ -#define WM5100_DSP_IRQ5_EINT_WIDTH 1 /* DSP_IRQ5_EINT */ -#define WM5100_DSP_IRQ4_EINT 0x0008 /* DSP_IRQ4_EINT */ -#define WM5100_DSP_IRQ4_EINT_MASK 0x0008 /* DSP_IRQ4_EINT */ -#define WM5100_DSP_IRQ4_EINT_SHIFT 3 /* DSP_IRQ4_EINT */ -#define WM5100_DSP_IRQ4_EINT_WIDTH 1 /* DSP_IRQ4_EINT */ -#define WM5100_DSP_IRQ3_EINT 0x0004 /* DSP_IRQ3_EINT */ -#define WM5100_DSP_IRQ3_EINT_MASK 0x0004 /* DSP_IRQ3_EINT */ -#define WM5100_DSP_IRQ3_EINT_SHIFT 2 /* DSP_IRQ3_EINT */ -#define WM5100_DSP_IRQ3_EINT_WIDTH 1 /* DSP_IRQ3_EINT */ -#define WM5100_DSP_IRQ2_EINT 0x0002 /* DSP_IRQ2_EINT */ -#define WM5100_DSP_IRQ2_EINT_MASK 0x0002 /* DSP_IRQ2_EINT */ -#define WM5100_DSP_IRQ2_EINT_SHIFT 1 /* DSP_IRQ2_EINT */ -#define WM5100_DSP_IRQ2_EINT_WIDTH 1 /* DSP_IRQ2_EINT */ -#define WM5100_DSP_IRQ1_EINT 0x0001 /* DSP_IRQ1_EINT */ -#define WM5100_DSP_IRQ1_EINT_MASK 0x0001 /* DSP_IRQ1_EINT */ -#define WM5100_DSP_IRQ1_EINT_SHIFT 0 /* DSP_IRQ1_EINT */ -#define WM5100_DSP_IRQ1_EINT_WIDTH 1 /* DSP_IRQ1_EINT */ - -/* - * R3330 (0xD02) - Interrupt Status 3 - */ -#define WM5100_SPK_SHUTDOWN_WARN_EINT 0x8000 /* SPK_SHUTDOWN_WARN_EINT */ -#define WM5100_SPK_SHUTDOWN_WARN_EINT_MASK 0x8000 /* SPK_SHUTDOWN_WARN_EINT */ -#define WM5100_SPK_SHUTDOWN_WARN_EINT_SHIFT 15 /* SPK_SHUTDOWN_WARN_EINT */ -#define WM5100_SPK_SHUTDOWN_WARN_EINT_WIDTH 1 /* SPK_SHUTDOWN_WARN_EINT */ -#define WM5100_SPK_SHUTDOWN_EINT 0x4000 /* SPK_SHUTDOWN_EINT */ -#define WM5100_SPK_SHUTDOWN_EINT_MASK 0x4000 /* SPK_SHUTDOWN_EINT */ -#define WM5100_SPK_SHUTDOWN_EINT_SHIFT 14 /* SPK_SHUTDOWN_EINT */ -#define WM5100_SPK_SHUTDOWN_EINT_WIDTH 1 /* SPK_SHUTDOWN_EINT */ -#define WM5100_HPDET_EINT 0x2000 /* HPDET_EINT */ -#define WM5100_HPDET_EINT_MASK 0x2000 /* HPDET_EINT */ -#define WM5100_HPDET_EINT_SHIFT 13 /* HPDET_EINT */ -#define WM5100_HPDET_EINT_WIDTH 1 /* HPDET_EINT */ -#define WM5100_ACCDET_EINT 0x1000 /* ACCDET_EINT */ -#define WM5100_ACCDET_EINT_MASK 0x1000 /* ACCDET_EINT */ -#define WM5100_ACCDET_EINT_SHIFT 12 /* ACCDET_EINT */ -#define WM5100_ACCDET_EINT_WIDTH 1 /* ACCDET_EINT */ -#define WM5100_DRC_SIG_DET_EINT 0x0200 /* DRC_SIG_DET_EINT */ -#define WM5100_DRC_SIG_DET_EINT_MASK 0x0200 /* DRC_SIG_DET_EINT */ -#define WM5100_DRC_SIG_DET_EINT_SHIFT 9 /* DRC_SIG_DET_EINT */ -#define WM5100_DRC_SIG_DET_EINT_WIDTH 1 /* DRC_SIG_DET_EINT */ -#define WM5100_ASRC2_LOCK_EINT 0x0100 /* ASRC2_LOCK_EINT */ -#define WM5100_ASRC2_LOCK_EINT_MASK 0x0100 /* ASRC2_LOCK_EINT */ -#define WM5100_ASRC2_LOCK_EINT_SHIFT 8 /* ASRC2_LOCK_EINT */ -#define WM5100_ASRC2_LOCK_EINT_WIDTH 1 /* ASRC2_LOCK_EINT */ -#define WM5100_ASRC1_LOCK_EINT 0x0080 /* ASRC1_LOCK_EINT */ -#define WM5100_ASRC1_LOCK_EINT_MASK 0x0080 /* ASRC1_LOCK_EINT */ -#define WM5100_ASRC1_LOCK_EINT_SHIFT 7 /* ASRC1_LOCK_EINT */ -#define WM5100_ASRC1_LOCK_EINT_WIDTH 1 /* ASRC1_LOCK_EINT */ -#define WM5100_FLL2_LOCK_EINT 0x0008 /* FLL2_LOCK_EINT */ -#define WM5100_FLL2_LOCK_EINT_MASK 0x0008 /* FLL2_LOCK_EINT */ -#define WM5100_FLL2_LOCK_EINT_SHIFT 3 /* FLL2_LOCK_EINT */ -#define WM5100_FLL2_LOCK_EINT_WIDTH 1 /* FLL2_LOCK_EINT */ -#define WM5100_FLL1_LOCK_EINT 0x0004 /* FLL1_LOCK_EINT */ -#define WM5100_FLL1_LOCK_EINT_MASK 0x0004 /* FLL1_LOCK_EINT */ -#define WM5100_FLL1_LOCK_EINT_SHIFT 2 /* FLL1_LOCK_EINT */ -#define WM5100_FLL1_LOCK_EINT_WIDTH 1 /* FLL1_LOCK_EINT */ -#define WM5100_CLKGEN_ERR_EINT 0x0002 /* CLKGEN_ERR_EINT */ -#define WM5100_CLKGEN_ERR_EINT_MASK 0x0002 /* CLKGEN_ERR_EINT */ -#define WM5100_CLKGEN_ERR_EINT_SHIFT 1 /* CLKGEN_ERR_EINT */ -#define WM5100_CLKGEN_ERR_EINT_WIDTH 1 /* CLKGEN_ERR_EINT */ -#define WM5100_CLKGEN_ERR_ASYNC_EINT 0x0001 /* CLKGEN_ERR_ASYNC_EINT */ -#define WM5100_CLKGEN_ERR_ASYNC_EINT_MASK 0x0001 /* CLKGEN_ERR_ASYNC_EINT */ -#define WM5100_CLKGEN_ERR_ASYNC_EINT_SHIFT 0 /* CLKGEN_ERR_ASYNC_EINT */ -#define WM5100_CLKGEN_ERR_ASYNC_EINT_WIDTH 1 /* CLKGEN_ERR_ASYNC_EINT */ - -/* - * R3331 (0xD03) - Interrupt Status 4 - */ -#define WM5100_AIF3_ERR_EINT 0x2000 /* AIF3_ERR_EINT */ -#define WM5100_AIF3_ERR_EINT_MASK 0x2000 /* AIF3_ERR_EINT */ -#define WM5100_AIF3_ERR_EINT_SHIFT 13 /* AIF3_ERR_EINT */ -#define WM5100_AIF3_ERR_EINT_WIDTH 1 /* AIF3_ERR_EINT */ -#define WM5100_AIF2_ERR_EINT 0x1000 /* AIF2_ERR_EINT */ -#define WM5100_AIF2_ERR_EINT_MASK 0x1000 /* AIF2_ERR_EINT */ -#define WM5100_AIF2_ERR_EINT_SHIFT 12 /* AIF2_ERR_EINT */ -#define WM5100_AIF2_ERR_EINT_WIDTH 1 /* AIF2_ERR_EINT */ -#define WM5100_AIF1_ERR_EINT 0x0800 /* AIF1_ERR_EINT */ -#define WM5100_AIF1_ERR_EINT_MASK 0x0800 /* AIF1_ERR_EINT */ -#define WM5100_AIF1_ERR_EINT_SHIFT 11 /* AIF1_ERR_EINT */ -#define WM5100_AIF1_ERR_EINT_WIDTH 1 /* AIF1_ERR_EINT */ -#define WM5100_CTRLIF_ERR_EINT 0x0400 /* CTRLIF_ERR_EINT */ -#define WM5100_CTRLIF_ERR_EINT_MASK 0x0400 /* CTRLIF_ERR_EINT */ -#define WM5100_CTRLIF_ERR_EINT_SHIFT 10 /* CTRLIF_ERR_EINT */ -#define WM5100_CTRLIF_ERR_EINT_WIDTH 1 /* CTRLIF_ERR_EINT */ -#define WM5100_ISRC2_UNDERCLOCKED_EINT 0x0200 /* ISRC2_UNDERCLOCKED_EINT */ -#define WM5100_ISRC2_UNDERCLOCKED_EINT_MASK 0x0200 /* ISRC2_UNDERCLOCKED_EINT */ -#define WM5100_ISRC2_UNDERCLOCKED_EINT_SHIFT 9 /* ISRC2_UNDERCLOCKED_EINT */ -#define WM5100_ISRC2_UNDERCLOCKED_EINT_WIDTH 1 /* ISRC2_UNDERCLOCKED_EINT */ -#define WM5100_ISRC1_UNDERCLOCKED_EINT 0x0100 /* ISRC1_UNDERCLOCKED_EINT */ -#define WM5100_ISRC1_UNDERCLOCKED_EINT_MASK 0x0100 /* ISRC1_UNDERCLOCKED_EINT */ -#define WM5100_ISRC1_UNDERCLOCKED_EINT_SHIFT 8 /* ISRC1_UNDERCLOCKED_EINT */ -#define WM5100_ISRC1_UNDERCLOCKED_EINT_WIDTH 1 /* ISRC1_UNDERCLOCKED_EINT */ -#define WM5100_FX_UNDERCLOCKED_EINT 0x0080 /* FX_UNDERCLOCKED_EINT */ -#define WM5100_FX_UNDERCLOCKED_EINT_MASK 0x0080 /* FX_UNDERCLOCKED_EINT */ -#define WM5100_FX_UNDERCLOCKED_EINT_SHIFT 7 /* FX_UNDERCLOCKED_EINT */ -#define WM5100_FX_UNDERCLOCKED_EINT_WIDTH 1 /* FX_UNDERCLOCKED_EINT */ -#define WM5100_AIF3_UNDERCLOCKED_EINT 0x0040 /* AIF3_UNDERCLOCKED_EINT */ -#define WM5100_AIF3_UNDERCLOCKED_EINT_MASK 0x0040 /* AIF3_UNDERCLOCKED_EINT */ -#define WM5100_AIF3_UNDERCLOCKED_EINT_SHIFT 6 /* AIF3_UNDERCLOCKED_EINT */ -#define WM5100_AIF3_UNDERCLOCKED_EINT_WIDTH 1 /* AIF3_UNDERCLOCKED_EINT */ -#define WM5100_AIF2_UNDERCLOCKED_EINT 0x0020 /* AIF2_UNDERCLOCKED_EINT */ -#define WM5100_AIF2_UNDERCLOCKED_EINT_MASK 0x0020 /* AIF2_UNDERCLOCKED_EINT */ -#define WM5100_AIF2_UNDERCLOCKED_EINT_SHIFT 5 /* AIF2_UNDERCLOCKED_EINT */ -#define WM5100_AIF2_UNDERCLOCKED_EINT_WIDTH 1 /* AIF2_UNDERCLOCKED_EINT */ -#define WM5100_AIF1_UNDERCLOCKED_EINT 0x0010 /* AIF1_UNDERCLOCKED_EINT */ -#define WM5100_AIF1_UNDERCLOCKED_EINT_MASK 0x0010 /* AIF1_UNDERCLOCKED_EINT */ -#define WM5100_AIF1_UNDERCLOCKED_EINT_SHIFT 4 /* AIF1_UNDERCLOCKED_EINT */ -#define WM5100_AIF1_UNDERCLOCKED_EINT_WIDTH 1 /* AIF1_UNDERCLOCKED_EINT */ -#define WM5100_ASRC_UNDERCLOCKED_EINT 0x0008 /* ASRC_UNDERCLOCKED_EINT */ -#define WM5100_ASRC_UNDERCLOCKED_EINT_MASK 0x0008 /* ASRC_UNDERCLOCKED_EINT */ -#define WM5100_ASRC_UNDERCLOCKED_EINT_SHIFT 3 /* ASRC_UNDERCLOCKED_EINT */ -#define WM5100_ASRC_UNDERCLOCKED_EINT_WIDTH 1 /* ASRC_UNDERCLOCKED_EINT */ -#define WM5100_DAC_UNDERCLOCKED_EINT 0x0004 /* DAC_UNDERCLOCKED_EINT */ -#define WM5100_DAC_UNDERCLOCKED_EINT_MASK 0x0004 /* DAC_UNDERCLOCKED_EINT */ -#define WM5100_DAC_UNDERCLOCKED_EINT_SHIFT 2 /* DAC_UNDERCLOCKED_EINT */ -#define WM5100_DAC_UNDERCLOCKED_EINT_WIDTH 1 /* DAC_UNDERCLOCKED_EINT */ -#define WM5100_ADC_UNDERCLOCKED_EINT 0x0002 /* ADC_UNDERCLOCKED_EINT */ -#define WM5100_ADC_UNDERCLOCKED_EINT_MASK 0x0002 /* ADC_UNDERCLOCKED_EINT */ -#define WM5100_ADC_UNDERCLOCKED_EINT_SHIFT 1 /* ADC_UNDERCLOCKED_EINT */ -#define WM5100_ADC_UNDERCLOCKED_EINT_WIDTH 1 /* ADC_UNDERCLOCKED_EINT */ -#define WM5100_MIXER_UNDERCLOCKED_EINT 0x0001 /* MIXER_UNDERCLOCKED_EINT */ -#define WM5100_MIXER_UNDERCLOCKED_EINT_MASK 0x0001 /* MIXER_UNDERCLOCKED_EINT */ -#define WM5100_MIXER_UNDERCLOCKED_EINT_SHIFT 0 /* MIXER_UNDERCLOCKED_EINT */ -#define WM5100_MIXER_UNDERCLOCKED_EINT_WIDTH 1 /* MIXER_UNDERCLOCKED_EINT */ - -/* - * R3332 (0xD04) - Interrupt Raw Status 2 - */ -#define WM5100_DSP_IRQ6_STS 0x0020 /* DSP_IRQ6_STS */ -#define WM5100_DSP_IRQ6_STS_MASK 0x0020 /* DSP_IRQ6_STS */ -#define WM5100_DSP_IRQ6_STS_SHIFT 5 /* DSP_IRQ6_STS */ -#define WM5100_DSP_IRQ6_STS_WIDTH 1 /* DSP_IRQ6_STS */ -#define WM5100_DSP_IRQ5_STS 0x0010 /* DSP_IRQ5_STS */ -#define WM5100_DSP_IRQ5_STS_MASK 0x0010 /* DSP_IRQ5_STS */ -#define WM5100_DSP_IRQ5_STS_SHIFT 4 /* DSP_IRQ5_STS */ -#define WM5100_DSP_IRQ5_STS_WIDTH 1 /* DSP_IRQ5_STS */ -#define WM5100_DSP_IRQ4_STS 0x0008 /* DSP_IRQ4_STS */ -#define WM5100_DSP_IRQ4_STS_MASK 0x0008 /* DSP_IRQ4_STS */ -#define WM5100_DSP_IRQ4_STS_SHIFT 3 /* DSP_IRQ4_STS */ -#define WM5100_DSP_IRQ4_STS_WIDTH 1 /* DSP_IRQ4_STS */ -#define WM5100_DSP_IRQ3_STS 0x0004 /* DSP_IRQ3_STS */ -#define WM5100_DSP_IRQ3_STS_MASK 0x0004 /* DSP_IRQ3_STS */ -#define WM5100_DSP_IRQ3_STS_SHIFT 2 /* DSP_IRQ3_STS */ -#define WM5100_DSP_IRQ3_STS_WIDTH 1 /* DSP_IRQ3_STS */ -#define WM5100_DSP_IRQ2_STS 0x0002 /* DSP_IRQ2_STS */ -#define WM5100_DSP_IRQ2_STS_MASK 0x0002 /* DSP_IRQ2_STS */ -#define WM5100_DSP_IRQ2_STS_SHIFT 1 /* DSP_IRQ2_STS */ -#define WM5100_DSP_IRQ2_STS_WIDTH 1 /* DSP_IRQ2_STS */ -#define WM5100_DSP_IRQ1_STS 0x0001 /* DSP_IRQ1_STS */ -#define WM5100_DSP_IRQ1_STS_MASK 0x0001 /* DSP_IRQ1_STS */ -#define WM5100_DSP_IRQ1_STS_SHIFT 0 /* DSP_IRQ1_STS */ -#define WM5100_DSP_IRQ1_STS_WIDTH 1 /* DSP_IRQ1_STS */ - -/* - * R3333 (0xD05) - Interrupt Raw Status 3 - */ -#define WM5100_SPK_SHUTDOWN_WARN_STS 0x8000 /* SPK_SHUTDOWN_WARN_STS */ -#define WM5100_SPK_SHUTDOWN_WARN_STS_MASK 0x8000 /* SPK_SHUTDOWN_WARN_STS */ -#define WM5100_SPK_SHUTDOWN_WARN_STS_SHIFT 15 /* SPK_SHUTDOWN_WARN_STS */ -#define WM5100_SPK_SHUTDOWN_WARN_STS_WIDTH 1 /* SPK_SHUTDOWN_WARN_STS */ -#define WM5100_SPK_SHUTDOWN_STS 0x4000 /* SPK_SHUTDOWN_STS */ -#define WM5100_SPK_SHUTDOWN_STS_MASK 0x4000 /* SPK_SHUTDOWN_STS */ -#define WM5100_SPK_SHUTDOWN_STS_SHIFT 14 /* SPK_SHUTDOWN_STS */ -#define WM5100_SPK_SHUTDOWN_STS_WIDTH 1 /* SPK_SHUTDOWN_STS */ -#define WM5100_HPDET_STS 0x2000 /* HPDET_STS */ -#define WM5100_HPDET_STS_MASK 0x2000 /* HPDET_STS */ -#define WM5100_HPDET_STS_SHIFT 13 /* HPDET_STS */ -#define WM5100_HPDET_STS_WIDTH 1 /* HPDET_STS */ -#define WM5100_DRC_SID_DET_STS 0x0200 /* DRC_SID_DET_STS */ -#define WM5100_DRC_SID_DET_STS_MASK 0x0200 /* DRC_SID_DET_STS */ -#define WM5100_DRC_SID_DET_STS_SHIFT 9 /* DRC_SID_DET_STS */ -#define WM5100_DRC_SID_DET_STS_WIDTH 1 /* DRC_SID_DET_STS */ -#define WM5100_ASRC2_LOCK_STS 0x0100 /* ASRC2_LOCK_STS */ -#define WM5100_ASRC2_LOCK_STS_MASK 0x0100 /* ASRC2_LOCK_STS */ -#define WM5100_ASRC2_LOCK_STS_SHIFT 8 /* ASRC2_LOCK_STS */ -#define WM5100_ASRC2_LOCK_STS_WIDTH 1 /* ASRC2_LOCK_STS */ -#define WM5100_ASRC1_LOCK_STS 0x0080 /* ASRC1_LOCK_STS */ -#define WM5100_ASRC1_LOCK_STS_MASK 0x0080 /* ASRC1_LOCK_STS */ -#define WM5100_ASRC1_LOCK_STS_SHIFT 7 /* ASRC1_LOCK_STS */ -#define WM5100_ASRC1_LOCK_STS_WIDTH 1 /* ASRC1_LOCK_STS */ -#define WM5100_FLL2_LOCK_STS 0x0008 /* FLL2_LOCK_STS */ -#define WM5100_FLL2_LOCK_STS_MASK 0x0008 /* FLL2_LOCK_STS */ -#define WM5100_FLL2_LOCK_STS_SHIFT 3 /* FLL2_LOCK_STS */ -#define WM5100_FLL2_LOCK_STS_WIDTH 1 /* FLL2_LOCK_STS */ -#define WM5100_FLL1_LOCK_STS 0x0004 /* FLL1_LOCK_STS */ -#define WM5100_FLL1_LOCK_STS_MASK 0x0004 /* FLL1_LOCK_STS */ -#define WM5100_FLL1_LOCK_STS_SHIFT 2 /* FLL1_LOCK_STS */ -#define WM5100_FLL1_LOCK_STS_WIDTH 1 /* FLL1_LOCK_STS */ -#define WM5100_CLKGEN_ERR_STS 0x0002 /* CLKGEN_ERR_STS */ -#define WM5100_CLKGEN_ERR_STS_MASK 0x0002 /* CLKGEN_ERR_STS */ -#define WM5100_CLKGEN_ERR_STS_SHIFT 1 /* CLKGEN_ERR_STS */ -#define WM5100_CLKGEN_ERR_STS_WIDTH 1 /* CLKGEN_ERR_STS */ -#define WM5100_CLKGEN_ERR_ASYNC_STS 0x0001 /* CLKGEN_ERR_ASYNC_STS */ -#define WM5100_CLKGEN_ERR_ASYNC_STS_MASK 0x0001 /* CLKGEN_ERR_ASYNC_STS */ -#define WM5100_CLKGEN_ERR_ASYNC_STS_SHIFT 0 /* CLKGEN_ERR_ASYNC_STS */ -#define WM5100_CLKGEN_ERR_ASYNC_STS_WIDTH 1 /* CLKGEN_ERR_ASYNC_STS */ - -/* - * R3334 (0xD06) - Interrupt Raw Status 4 - */ -#define WM5100_AIF3_ERR_STS 0x2000 /* AIF3_ERR_STS */ -#define WM5100_AIF3_ERR_STS_MASK 0x2000 /* AIF3_ERR_STS */ -#define WM5100_AIF3_ERR_STS_SHIFT 13 /* AIF3_ERR_STS */ -#define WM5100_AIF3_ERR_STS_WIDTH 1 /* AIF3_ERR_STS */ -#define WM5100_AIF2_ERR_STS 0x1000 /* AIF2_ERR_STS */ -#define WM5100_AIF2_ERR_STS_MASK 0x1000 /* AIF2_ERR_STS */ -#define WM5100_AIF2_ERR_STS_SHIFT 12 /* AIF2_ERR_STS */ -#define WM5100_AIF2_ERR_STS_WIDTH 1 /* AIF2_ERR_STS */ -#define WM5100_AIF1_ERR_STS 0x0800 /* AIF1_ERR_STS */ -#define WM5100_AIF1_ERR_STS_MASK 0x0800 /* AIF1_ERR_STS */ -#define WM5100_AIF1_ERR_STS_SHIFT 11 /* AIF1_ERR_STS */ -#define WM5100_AIF1_ERR_STS_WIDTH 1 /* AIF1_ERR_STS */ -#define WM5100_CTRLIF_ERR_STS 0x0400 /* CTRLIF_ERR_STS */ -#define WM5100_CTRLIF_ERR_STS_MASK 0x0400 /* CTRLIF_ERR_STS */ -#define WM5100_CTRLIF_ERR_STS_SHIFT 10 /* CTRLIF_ERR_STS */ -#define WM5100_CTRLIF_ERR_STS_WIDTH 1 /* CTRLIF_ERR_STS */ -#define WM5100_ISRC2_UNDERCLOCKED_STS 0x0200 /* ISRC2_UNDERCLOCKED_STS */ -#define WM5100_ISRC2_UNDERCLOCKED_STS_MASK 0x0200 /* ISRC2_UNDERCLOCKED_STS */ -#define WM5100_ISRC2_UNDERCLOCKED_STS_SHIFT 9 /* ISRC2_UNDERCLOCKED_STS */ -#define WM5100_ISRC2_UNDERCLOCKED_STS_WIDTH 1 /* ISRC2_UNDERCLOCKED_STS */ -#define WM5100_ISRC1_UNDERCLOCKED_STS 0x0100 /* ISRC1_UNDERCLOCKED_STS */ -#define WM5100_ISRC1_UNDERCLOCKED_STS_MASK 0x0100 /* ISRC1_UNDERCLOCKED_STS */ -#define WM5100_ISRC1_UNDERCLOCKED_STS_SHIFT 8 /* ISRC1_UNDERCLOCKED_STS */ -#define WM5100_ISRC1_UNDERCLOCKED_STS_WIDTH 1 /* ISRC1_UNDERCLOCKED_STS */ -#define WM5100_FX_UNDERCLOCKED_STS 0x0080 /* FX_UNDERCLOCKED_STS */ -#define WM5100_FX_UNDERCLOCKED_STS_MASK 0x0080 /* FX_UNDERCLOCKED_STS */ -#define WM5100_FX_UNDERCLOCKED_STS_SHIFT 7 /* FX_UNDERCLOCKED_STS */ -#define WM5100_FX_UNDERCLOCKED_STS_WIDTH 1 /* FX_UNDERCLOCKED_STS */ -#define WM5100_AIF3_UNDERCLOCKED_STS 0x0040 /* AIF3_UNDERCLOCKED_STS */ -#define WM5100_AIF3_UNDERCLOCKED_STS_MASK 0x0040 /* AIF3_UNDERCLOCKED_STS */ -#define WM5100_AIF3_UNDERCLOCKED_STS_SHIFT 6 /* AIF3_UNDERCLOCKED_STS */ -#define WM5100_AIF3_UNDERCLOCKED_STS_WIDTH 1 /* AIF3_UNDERCLOCKED_STS */ -#define WM5100_AIF2_UNDERCLOCKED_STS 0x0020 /* AIF2_UNDERCLOCKED_STS */ -#define WM5100_AIF2_UNDERCLOCKED_STS_MASK 0x0020 /* AIF2_UNDERCLOCKED_STS */ -#define WM5100_AIF2_UNDERCLOCKED_STS_SHIFT 5 /* AIF2_UNDERCLOCKED_STS */ -#define WM5100_AIF2_UNDERCLOCKED_STS_WIDTH 1 /* AIF2_UNDERCLOCKED_STS */ -#define WM5100_AIF1_UNDERCLOCKED_STS 0x0010 /* AIF1_UNDERCLOCKED_STS */ -#define WM5100_AIF1_UNDERCLOCKED_STS_MASK 0x0010 /* AIF1_UNDERCLOCKED_STS */ -#define WM5100_AIF1_UNDERCLOCKED_STS_SHIFT 4 /* AIF1_UNDERCLOCKED_STS */ -#define WM5100_AIF1_UNDERCLOCKED_STS_WIDTH 1 /* AIF1_UNDERCLOCKED_STS */ -#define WM5100_ASRC_UNDERCLOCKED_STS 0x0008 /* ASRC_UNDERCLOCKED_STS */ -#define WM5100_ASRC_UNDERCLOCKED_STS_MASK 0x0008 /* ASRC_UNDERCLOCKED_STS */ -#define WM5100_ASRC_UNDERCLOCKED_STS_SHIFT 3 /* ASRC_UNDERCLOCKED_STS */ -#define WM5100_ASRC_UNDERCLOCKED_STS_WIDTH 1 /* ASRC_UNDERCLOCKED_STS */ -#define WM5100_DAC_UNDERCLOCKED_STS 0x0004 /* DAC_UNDERCLOCKED_STS */ -#define WM5100_DAC_UNDERCLOCKED_STS_MASK 0x0004 /* DAC_UNDERCLOCKED_STS */ -#define WM5100_DAC_UNDERCLOCKED_STS_SHIFT 2 /* DAC_UNDERCLOCKED_STS */ -#define WM5100_DAC_UNDERCLOCKED_STS_WIDTH 1 /* DAC_UNDERCLOCKED_STS */ -#define WM5100_ADC_UNDERCLOCKED_STS 0x0002 /* ADC_UNDERCLOCKED_STS */ -#define WM5100_ADC_UNDERCLOCKED_STS_MASK 0x0002 /* ADC_UNDERCLOCKED_STS */ -#define WM5100_ADC_UNDERCLOCKED_STS_SHIFT 1 /* ADC_UNDERCLOCKED_STS */ -#define WM5100_ADC_UNDERCLOCKED_STS_WIDTH 1 /* ADC_UNDERCLOCKED_STS */ -#define WM5100_MIXER_UNDERCLOCKED_STS 0x0001 /* MIXER_UNDERCLOCKED_STS */ -#define WM5100_MIXER_UNDERCLOCKED_STS_MASK 0x0001 /* MIXER_UNDERCLOCKED_STS */ -#define WM5100_MIXER_UNDERCLOCKED_STS_SHIFT 0 /* MIXER_UNDERCLOCKED_STS */ -#define WM5100_MIXER_UNDERCLOCKED_STS_WIDTH 1 /* MIXER_UNDERCLOCKED_STS */ - -/* - * R3335 (0xD07) - Interrupt Status 1 Mask - */ -#define WM5100_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */ -#define WM5100_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */ -#define WM5100_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */ -#define WM5100_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */ -#define WM5100_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */ -#define WM5100_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */ -#define WM5100_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */ -#define WM5100_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */ -#define WM5100_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */ -#define WM5100_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */ -#define WM5100_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */ -#define WM5100_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */ -#define WM5100_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */ -#define WM5100_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */ -#define WM5100_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */ -#define WM5100_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */ -#define WM5100_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */ -#define WM5100_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */ -#define WM5100_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */ -#define WM5100_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */ -#define WM5100_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */ -#define WM5100_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */ -#define WM5100_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */ -#define WM5100_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */ - -/* - * R3336 (0xD08) - Interrupt Status 2 Mask - */ -#define WM5100_IM_DSP_IRQ6_EINT 0x0020 /* IM_DSP_IRQ6_EINT */ -#define WM5100_IM_DSP_IRQ6_EINT_MASK 0x0020 /* IM_DSP_IRQ6_EINT */ -#define WM5100_IM_DSP_IRQ6_EINT_SHIFT 5 /* IM_DSP_IRQ6_EINT */ -#define WM5100_IM_DSP_IRQ6_EINT_WIDTH 1 /* IM_DSP_IRQ6_EINT */ -#define WM5100_IM_DSP_IRQ5_EINT 0x0010 /* IM_DSP_IRQ5_EINT */ -#define WM5100_IM_DSP_IRQ5_EINT_MASK 0x0010 /* IM_DSP_IRQ5_EINT */ -#define WM5100_IM_DSP_IRQ5_EINT_SHIFT 4 /* IM_DSP_IRQ5_EINT */ -#define WM5100_IM_DSP_IRQ5_EINT_WIDTH 1 /* IM_DSP_IRQ5_EINT */ -#define WM5100_IM_DSP_IRQ4_EINT 0x0008 /* IM_DSP_IRQ4_EINT */ -#define WM5100_IM_DSP_IRQ4_EINT_MASK 0x0008 /* IM_DSP_IRQ4_EINT */ -#define WM5100_IM_DSP_IRQ4_EINT_SHIFT 3 /* IM_DSP_IRQ4_EINT */ -#define WM5100_IM_DSP_IRQ4_EINT_WIDTH 1 /* IM_DSP_IRQ4_EINT */ -#define WM5100_IM_DSP_IRQ3_EINT 0x0004 /* IM_DSP_IRQ3_EINT */ -#define WM5100_IM_DSP_IRQ3_EINT_MASK 0x0004 /* IM_DSP_IRQ3_EINT */ -#define WM5100_IM_DSP_IRQ3_EINT_SHIFT 2 /* IM_DSP_IRQ3_EINT */ -#define WM5100_IM_DSP_IRQ3_EINT_WIDTH 1 /* IM_DSP_IRQ3_EINT */ -#define WM5100_IM_DSP_IRQ2_EINT 0x0002 /* IM_DSP_IRQ2_EINT */ -#define WM5100_IM_DSP_IRQ2_EINT_MASK 0x0002 /* IM_DSP_IRQ2_EINT */ -#define WM5100_IM_DSP_IRQ2_EINT_SHIFT 1 /* IM_DSP_IRQ2_EINT */ -#define WM5100_IM_DSP_IRQ2_EINT_WIDTH 1 /* IM_DSP_IRQ2_EINT */ -#define WM5100_IM_DSP_IRQ1_EINT 0x0001 /* IM_DSP_IRQ1_EINT */ -#define WM5100_IM_DSP_IRQ1_EINT_MASK 0x0001 /* IM_DSP_IRQ1_EINT */ -#define WM5100_IM_DSP_IRQ1_EINT_SHIFT 0 /* IM_DSP_IRQ1_EINT */ -#define WM5100_IM_DSP_IRQ1_EINT_WIDTH 1 /* IM_DSP_IRQ1_EINT */ - -/* - * R3337 (0xD09) - Interrupt Status 3 Mask - */ -#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT */ -#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_MASK 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT */ -#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_SHIFT 15 /* IM_SPK_SHUTDOWN_WARN_EINT */ -#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_WIDTH 1 /* IM_SPK_SHUTDOWN_WARN_EINT */ -#define WM5100_IM_SPK_SHUTDOWN_EINT 0x4000 /* IM_SPK_SHUTDOWN_EINT */ -#define WM5100_IM_SPK_SHUTDOWN_EINT_MASK 0x4000 /* IM_SPK_SHUTDOWN_EINT */ -#define WM5100_IM_SPK_SHUTDOWN_EINT_SHIFT 14 /* IM_SPK_SHUTDOWN_EINT */ -#define WM5100_IM_SPK_SHUTDOWN_EINT_WIDTH 1 /* IM_SPK_SHUTDOWN_EINT */ -#define WM5100_IM_HPDET_EINT 0x2000 /* IM_HPDET_EINT */ -#define WM5100_IM_HPDET_EINT_MASK 0x2000 /* IM_HPDET_EINT */ -#define WM5100_IM_HPDET_EINT_SHIFT 13 /* IM_HPDET_EINT */ -#define WM5100_IM_HPDET_EINT_WIDTH 1 /* IM_HPDET_EINT */ -#define WM5100_IM_ACCDET_EINT 0x1000 /* IM_ACCDET_EINT */ -#define WM5100_IM_ACCDET_EINT_MASK 0x1000 /* IM_ACCDET_EINT */ -#define WM5100_IM_ACCDET_EINT_SHIFT 12 /* IM_ACCDET_EINT */ -#define WM5100_IM_ACCDET_EINT_WIDTH 1 /* IM_ACCDET_EINT */ -#define WM5100_IM_DRC_SIG_DET_EINT 0x0200 /* IM_DRC_SIG_DET_EINT */ -#define WM5100_IM_DRC_SIG_DET_EINT_MASK 0x0200 /* IM_DRC_SIG_DET_EINT */ -#define WM5100_IM_DRC_SIG_DET_EINT_SHIFT 9 /* IM_DRC_SIG_DET_EINT */ -#define WM5100_IM_DRC_SIG_DET_EINT_WIDTH 1 /* IM_DRC_SIG_DET_EINT */ -#define WM5100_IM_ASRC2_LOCK_EINT 0x0100 /* IM_ASRC2_LOCK_EINT */ -#define WM5100_IM_ASRC2_LOCK_EINT_MASK 0x0100 /* IM_ASRC2_LOCK_EINT */ -#define WM5100_IM_ASRC2_LOCK_EINT_SHIFT 8 /* IM_ASRC2_LOCK_EINT */ -#define WM5100_IM_ASRC2_LOCK_EINT_WIDTH 1 /* IM_ASRC2_LOCK_EINT */ -#define WM5100_IM_ASRC1_LOCK_EINT 0x0080 /* IM_ASRC1_LOCK_EINT */ -#define WM5100_IM_ASRC1_LOCK_EINT_MASK 0x0080 /* IM_ASRC1_LOCK_EINT */ -#define WM5100_IM_ASRC1_LOCK_EINT_SHIFT 7 /* IM_ASRC1_LOCK_EINT */ -#define WM5100_IM_ASRC1_LOCK_EINT_WIDTH 1 /* IM_ASRC1_LOCK_EINT */ -#define WM5100_IM_FLL2_LOCK_EINT 0x0008 /* IM_FLL2_LOCK_EINT */ -#define WM5100_IM_FLL2_LOCK_EINT_MASK 0x0008 /* IM_FLL2_LOCK_EINT */ -#define WM5100_IM_FLL2_LOCK_EINT_SHIFT 3 /* IM_FLL2_LOCK_EINT */ -#define WM5100_IM_FLL2_LOCK_EINT_WIDTH 1 /* IM_FLL2_LOCK_EINT */ -#define WM5100_IM_FLL1_LOCK_EINT 0x0004 /* IM_FLL1_LOCK_EINT */ -#define WM5100_IM_FLL1_LOCK_EINT_MASK 0x0004 /* IM_FLL1_LOCK_EINT */ -#define WM5100_IM_FLL1_LOCK_EINT_SHIFT 2 /* IM_FLL1_LOCK_EINT */ -#define WM5100_IM_FLL1_LOCK_EINT_WIDTH 1 /* IM_FLL1_LOCK_EINT */ -#define WM5100_IM_CLKGEN_ERR_EINT 0x0002 /* IM_CLKGEN_ERR_EINT */ -#define WM5100_IM_CLKGEN_ERR_EINT_MASK 0x0002 /* IM_CLKGEN_ERR_EINT */ -#define WM5100_IM_CLKGEN_ERR_EINT_SHIFT 1 /* IM_CLKGEN_ERR_EINT */ -#define WM5100_IM_CLKGEN_ERR_EINT_WIDTH 1 /* IM_CLKGEN_ERR_EINT */ -#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT */ -#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_MASK 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT */ -#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_SHIFT 0 /* IM_CLKGEN_ERR_ASYNC_EINT */ -#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_WIDTH 1 /* IM_CLKGEN_ERR_ASYNC_EINT */ - -/* - * R3338 (0xD0A) - Interrupt Status 4 Mask - */ -#define WM5100_IM_AIF3_ERR_EINT 0x2000 /* IM_AIF3_ERR_EINT */ -#define WM5100_IM_AIF3_ERR_EINT_MASK 0x2000 /* IM_AIF3_ERR_EINT */ -#define WM5100_IM_AIF3_ERR_EINT_SHIFT 13 /* IM_AIF3_ERR_EINT */ -#define WM5100_IM_AIF3_ERR_EINT_WIDTH 1 /* IM_AIF3_ERR_EINT */ -#define WM5100_IM_AIF2_ERR_EINT 0x1000 /* IM_AIF2_ERR_EINT */ -#define WM5100_IM_AIF2_ERR_EINT_MASK 0x1000 /* IM_AIF2_ERR_EINT */ -#define WM5100_IM_AIF2_ERR_EINT_SHIFT 12 /* IM_AIF2_ERR_EINT */ -#define WM5100_IM_AIF2_ERR_EINT_WIDTH 1 /* IM_AIF2_ERR_EINT */ -#define WM5100_IM_AIF1_ERR_EINT 0x0800 /* IM_AIF1_ERR_EINT */ -#define WM5100_IM_AIF1_ERR_EINT_MASK 0x0800 /* IM_AIF1_ERR_EINT */ -#define WM5100_IM_AIF1_ERR_EINT_SHIFT 11 /* IM_AIF1_ERR_EINT */ -#define WM5100_IM_AIF1_ERR_EINT_WIDTH 1 /* IM_AIF1_ERR_EINT */ -#define WM5100_IM_CTRLIF_ERR_EINT 0x0400 /* IM_CTRLIF_ERR_EINT */ -#define WM5100_IM_CTRLIF_ERR_EINT_MASK 0x0400 /* IM_CTRLIF_ERR_EINT */ -#define WM5100_IM_CTRLIF_ERR_EINT_SHIFT 10 /* IM_CTRLIF_ERR_EINT */ -#define WM5100_IM_CTRLIF_ERR_EINT_WIDTH 1 /* IM_CTRLIF_ERR_EINT */ -#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT 0x0200 /* IM_ISRC2_UNDERCLOCKED_EINT */ -#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_MASK 0x0200 /* IM_ISRC2_UNDERCLOCKED_EINT */ -#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_SHIFT 9 /* IM_ISRC2_UNDERCLOCKED_EINT */ -#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ISRC2_UNDERCLOCKED_EINT */ -#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT 0x0100 /* IM_ISRC1_UNDERCLOCKED_EINT */ -#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_MASK 0x0100 /* IM_ISRC1_UNDERCLOCKED_EINT */ -#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_SHIFT 8 /* IM_ISRC1_UNDERCLOCKED_EINT */ -#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ISRC1_UNDERCLOCKED_EINT */ -#define WM5100_IM_FX_UNDERCLOCKED_EINT 0x0080 /* IM_FX_UNDERCLOCKED_EINT */ -#define WM5100_IM_FX_UNDERCLOCKED_EINT_MASK 0x0080 /* IM_FX_UNDERCLOCKED_EINT */ -#define WM5100_IM_FX_UNDERCLOCKED_EINT_SHIFT 7 /* IM_FX_UNDERCLOCKED_EINT */ -#define WM5100_IM_FX_UNDERCLOCKED_EINT_WIDTH 1 /* IM_FX_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF3_UNDERCLOCKED_EINT 0x0040 /* IM_AIF3_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_MASK 0x0040 /* IM_AIF3_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_SHIFT 6 /* IM_AIF3_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF3_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF2_UNDERCLOCKED_EINT 0x0020 /* IM_AIF2_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_MASK 0x0020 /* IM_AIF2_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_SHIFT 5 /* IM_AIF2_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF2_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF1_UNDERCLOCKED_EINT 0x0010 /* IM_AIF1_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_MASK 0x0010 /* IM_AIF1_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_SHIFT 4 /* IM_AIF1_UNDERCLOCKED_EINT */ -#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF1_UNDERCLOCKED_EINT */ -#define WM5100_IM_ASRC_UNDERCLOCKED_EINT 0x0008 /* IM_ASRC_UNDERCLOCKED_EINT */ -#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_MASK 0x0008 /* IM_ASRC_UNDERCLOCKED_EINT */ -#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_SHIFT 3 /* IM_ASRC_UNDERCLOCKED_EINT */ -#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ASRC_UNDERCLOCKED_EINT */ -#define WM5100_IM_DAC_UNDERCLOCKED_EINT 0x0004 /* IM_DAC_UNDERCLOCKED_EINT */ -#define WM5100_IM_DAC_UNDERCLOCKED_EINT_MASK 0x0004 /* IM_DAC_UNDERCLOCKED_EINT */ -#define WM5100_IM_DAC_UNDERCLOCKED_EINT_SHIFT 2 /* IM_DAC_UNDERCLOCKED_EINT */ -#define WM5100_IM_DAC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_DAC_UNDERCLOCKED_EINT */ -#define WM5100_IM_ADC_UNDERCLOCKED_EINT 0x0002 /* IM_ADC_UNDERCLOCKED_EINT */ -#define WM5100_IM_ADC_UNDERCLOCKED_EINT_MASK 0x0002 /* IM_ADC_UNDERCLOCKED_EINT */ -#define WM5100_IM_ADC_UNDERCLOCKED_EINT_SHIFT 1 /* IM_ADC_UNDERCLOCKED_EINT */ -#define WM5100_IM_ADC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ADC_UNDERCLOCKED_EINT */ -#define WM5100_IM_MIXER_UNDERCLOCKED_EINT 0x0001 /* IM_MIXER_UNDERCLOCKED_EINT */ -#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_MASK 0x0001 /* IM_MIXER_UNDERCLOCKED_EINT */ -#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_SHIFT 0 /* IM_MIXER_UNDERCLOCKED_EINT */ -#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_WIDTH 1 /* IM_MIXER_UNDERCLOCKED_EINT */ - -/* - * R3359 (0xD1F) - Interrupt Control - */ -#define WM5100_IM_IRQ 0x0001 /* IM_IRQ */ -#define WM5100_IM_IRQ_MASK 0x0001 /* IM_IRQ */ -#define WM5100_IM_IRQ_SHIFT 0 /* IM_IRQ */ -#define WM5100_IM_IRQ_WIDTH 1 /* IM_IRQ */ - -/* - * R3360 (0xD20) - IRQ Debounce 1 - */ -#define WM5100_SPK_SHUTDOWN_WARN_DB 0x0200 /* SPK_SHUTDOWN_WARN_DB */ -#define WM5100_SPK_SHUTDOWN_WARN_DB_MASK 0x0200 /* SPK_SHUTDOWN_WARN_DB */ -#define WM5100_SPK_SHUTDOWN_WARN_DB_SHIFT 9 /* SPK_SHUTDOWN_WARN_DB */ -#define WM5100_SPK_SHUTDOWN_WARN_DB_WIDTH 1 /* SPK_SHUTDOWN_WARN_DB */ -#define WM5100_SPK_SHUTDOWN_DB 0x0100 /* SPK_SHUTDOWN_DB */ -#define WM5100_SPK_SHUTDOWN_DB_MASK 0x0100 /* SPK_SHUTDOWN_DB */ -#define WM5100_SPK_SHUTDOWN_DB_SHIFT 8 /* SPK_SHUTDOWN_DB */ -#define WM5100_SPK_SHUTDOWN_DB_WIDTH 1 /* SPK_SHUTDOWN_DB */ -#define WM5100_FLL1_LOCK_IRQ_DB 0x0008 /* FLL1_LOCK_IRQ_DB */ -#define WM5100_FLL1_LOCK_IRQ_DB_MASK 0x0008 /* FLL1_LOCK_IRQ_DB */ -#define WM5100_FLL1_LOCK_IRQ_DB_SHIFT 3 /* FLL1_LOCK_IRQ_DB */ -#define WM5100_FLL1_LOCK_IRQ_DB_WIDTH 1 /* FLL1_LOCK_IRQ_DB */ -#define WM5100_FLL2_LOCK_IRQ_DB 0x0004 /* FLL2_LOCK_IRQ_DB */ -#define WM5100_FLL2_LOCK_IRQ_DB_MASK 0x0004 /* FLL2_LOCK_IRQ_DB */ -#define WM5100_FLL2_LOCK_IRQ_DB_SHIFT 2 /* FLL2_LOCK_IRQ_DB */ -#define WM5100_FLL2_LOCK_IRQ_DB_WIDTH 1 /* FLL2_LOCK_IRQ_DB */ -#define WM5100_CLKGEN_ERR_IRQ_DB 0x0002 /* CLKGEN_ERR_IRQ_DB */ -#define WM5100_CLKGEN_ERR_IRQ_DB_MASK 0x0002 /* CLKGEN_ERR_IRQ_DB */ -#define WM5100_CLKGEN_ERR_IRQ_DB_SHIFT 1 /* CLKGEN_ERR_IRQ_DB */ -#define WM5100_CLKGEN_ERR_IRQ_DB_WIDTH 1 /* CLKGEN_ERR_IRQ_DB */ -#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB 0x0001 /* CLKGEN_ERR_ASYNC_IRQ_DB */ -#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_MASK 0x0001 /* CLKGEN_ERR_ASYNC_IRQ_DB */ -#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_SHIFT 0 /* CLKGEN_ERR_ASYNC_IRQ_DB */ -#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_WIDTH 1 /* CLKGEN_ERR_ASYNC_IRQ_DB */ - -/* - * R3361 (0xD21) - IRQ Debounce 2 - */ -#define WM5100_AIF_ERR_DB 0x0001 /* AIF_ERR_DB */ -#define WM5100_AIF_ERR_DB_MASK 0x0001 /* AIF_ERR_DB */ -#define WM5100_AIF_ERR_DB_SHIFT 0 /* AIF_ERR_DB */ -#define WM5100_AIF_ERR_DB_WIDTH 1 /* AIF_ERR_DB */ - -/* - * R3584 (0xE00) - FX_Ctrl - */ -#define WM5100_FX_STS_MASK 0xFFC0 /* FX_STS - [15:6] */ -#define WM5100_FX_STS_SHIFT 6 /* FX_STS - [15:6] */ -#define WM5100_FX_STS_WIDTH 10 /* FX_STS - [15:6] */ -#define WM5100_FX_RATE_MASK 0x0003 /* FX_RATE - [1:0] */ -#define WM5100_FX_RATE_SHIFT 0 /* FX_RATE - [1:0] */ -#define WM5100_FX_RATE_WIDTH 2 /* FX_RATE - [1:0] */ - -/* - * R3600 (0xE10) - EQ1_1 - */ -#define WM5100_EQ1_B1_GAIN_MASK 0xF800 /* EQ1_B1_GAIN - [15:11] */ -#define WM5100_EQ1_B1_GAIN_SHIFT 11 /* EQ1_B1_GAIN - [15:11] */ -#define WM5100_EQ1_B1_GAIN_WIDTH 5 /* EQ1_B1_GAIN - [15:11] */ -#define WM5100_EQ1_B2_GAIN_MASK 0x07C0 /* EQ1_B2_GAIN - [10:6] */ -#define WM5100_EQ1_B2_GAIN_SHIFT 6 /* EQ1_B2_GAIN - [10:6] */ -#define WM5100_EQ1_B2_GAIN_WIDTH 5 /* EQ1_B2_GAIN - [10:6] */ -#define WM5100_EQ1_B3_GAIN_MASK 0x003E /* EQ1_B3_GAIN - [5:1] */ -#define WM5100_EQ1_B3_GAIN_SHIFT 1 /* EQ1_B3_GAIN - [5:1] */ -#define WM5100_EQ1_B3_GAIN_WIDTH 5 /* EQ1_B3_GAIN - [5:1] */ -#define WM5100_EQ1_ENA 0x0001 /* EQ1_ENA */ -#define WM5100_EQ1_ENA_MASK 0x0001 /* EQ1_ENA */ -#define WM5100_EQ1_ENA_SHIFT 0 /* EQ1_ENA */ -#define WM5100_EQ1_ENA_WIDTH 1 /* EQ1_ENA */ - -/* - * R3601 (0xE11) - EQ1_2 - */ -#define WM5100_EQ1_B4_GAIN_MASK 0xF800 /* EQ1_B4_GAIN - [15:11] */ -#define WM5100_EQ1_B4_GAIN_SHIFT 11 /* EQ1_B4_GAIN - [15:11] */ -#define WM5100_EQ1_B4_GAIN_WIDTH 5 /* EQ1_B4_GAIN - [15:11] */ -#define WM5100_EQ1_B5_GAIN_MASK 0x07C0 /* EQ1_B5_GAIN - [10:6] */ -#define WM5100_EQ1_B5_GAIN_SHIFT 6 /* EQ1_B5_GAIN - [10:6] */ -#define WM5100_EQ1_B5_GAIN_WIDTH 5 /* EQ1_B5_GAIN - [10:6] */ - -/* - * R3602 (0xE12) - EQ1_3 - */ -#define WM5100_EQ1_B1_A_MASK 0xFFFF /* EQ1_B1_A - [15:0] */ -#define WM5100_EQ1_B1_A_SHIFT 0 /* EQ1_B1_A - [15:0] */ -#define WM5100_EQ1_B1_A_WIDTH 16 /* EQ1_B1_A - [15:0] */ - -/* - * R3603 (0xE13) - EQ1_4 - */ -#define WM5100_EQ1_B1_B_MASK 0xFFFF /* EQ1_B1_B - [15:0] */ -#define WM5100_EQ1_B1_B_SHIFT 0 /* EQ1_B1_B - [15:0] */ -#define WM5100_EQ1_B1_B_WIDTH 16 /* EQ1_B1_B - [15:0] */ - -/* - * R3604 (0xE14) - EQ1_5 - */ -#define WM5100_EQ1_B1_PG_MASK 0xFFFF /* EQ1_B1_PG - [15:0] */ -#define WM5100_EQ1_B1_PG_SHIFT 0 /* EQ1_B1_PG - [15:0] */ -#define WM5100_EQ1_B1_PG_WIDTH 16 /* EQ1_B1_PG - [15:0] */ - -/* - * R3605 (0xE15) - EQ1_6 - */ -#define WM5100_EQ1_B2_A_MASK 0xFFFF /* EQ1_B2_A - [15:0] */ -#define WM5100_EQ1_B2_A_SHIFT 0 /* EQ1_B2_A - [15:0] */ -#define WM5100_EQ1_B2_A_WIDTH 16 /* EQ1_B2_A - [15:0] */ - -/* - * R3606 (0xE16) - EQ1_7 - */ -#define WM5100_EQ1_B2_B_MASK 0xFFFF /* EQ1_B2_B - [15:0] */ -#define WM5100_EQ1_B2_B_SHIFT 0 /* EQ1_B2_B - [15:0] */ -#define WM5100_EQ1_B2_B_WIDTH 16 /* EQ1_B2_B - [15:0] */ - -/* - * R3607 (0xE17) - EQ1_8 - */ -#define WM5100_EQ1_B2_C_MASK 0xFFFF /* EQ1_B2_C - [15:0] */ -#define WM5100_EQ1_B2_C_SHIFT 0 /* EQ1_B2_C - [15:0] */ -#define WM5100_EQ1_B2_C_WIDTH 16 /* EQ1_B2_C - [15:0] */ - -/* - * R3608 (0xE18) - EQ1_9 - */ -#define WM5100_EQ1_B2_PG_MASK 0xFFFF /* EQ1_B2_PG - [15:0] */ -#define WM5100_EQ1_B2_PG_SHIFT 0 /* EQ1_B2_PG - [15:0] */ -#define WM5100_EQ1_B2_PG_WIDTH 16 /* EQ1_B2_PG - [15:0] */ - -/* - * R3609 (0xE19) - EQ1_10 - */ -#define WM5100_EQ1_B3_A_MASK 0xFFFF /* EQ1_B3_A - [15:0] */ -#define WM5100_EQ1_B3_A_SHIFT 0 /* EQ1_B3_A - [15:0] */ -#define WM5100_EQ1_B3_A_WIDTH 16 /* EQ1_B3_A - [15:0] */ - -/* - * R3610 (0xE1A) - EQ1_11 - */ -#define WM5100_EQ1_B3_B_MASK 0xFFFF /* EQ1_B3_B - [15:0] */ -#define WM5100_EQ1_B3_B_SHIFT 0 /* EQ1_B3_B - [15:0] */ -#define WM5100_EQ1_B3_B_WIDTH 16 /* EQ1_B3_B - [15:0] */ - -/* - * R3611 (0xE1B) - EQ1_12 - */ -#define WM5100_EQ1_B3_C_MASK 0xFFFF /* EQ1_B3_C - [15:0] */ -#define WM5100_EQ1_B3_C_SHIFT 0 /* EQ1_B3_C - [15:0] */ -#define WM5100_EQ1_B3_C_WIDTH 16 /* EQ1_B3_C - [15:0] */ - -/* - * R3612 (0xE1C) - EQ1_13 - */ -#define WM5100_EQ1_B3_PG_MASK 0xFFFF /* EQ1_B3_PG - [15:0] */ -#define WM5100_EQ1_B3_PG_SHIFT 0 /* EQ1_B3_PG - [15:0] */ -#define WM5100_EQ1_B3_PG_WIDTH 16 /* EQ1_B3_PG - [15:0] */ - -/* - * R3613 (0xE1D) - EQ1_14 - */ -#define WM5100_EQ1_B4_A_MASK 0xFFFF /* EQ1_B4_A - [15:0] */ -#define WM5100_EQ1_B4_A_SHIFT 0 /* EQ1_B4_A - [15:0] */ -#define WM5100_EQ1_B4_A_WIDTH 16 /* EQ1_B4_A - [15:0] */ - -/* - * R3614 (0xE1E) - EQ1_15 - */ -#define WM5100_EQ1_B4_B_MASK 0xFFFF /* EQ1_B4_B - [15:0] */ -#define WM5100_EQ1_B4_B_SHIFT 0 /* EQ1_B4_B - [15:0] */ -#define WM5100_EQ1_B4_B_WIDTH 16 /* EQ1_B4_B - [15:0] */ - -/* - * R3615 (0xE1F) - EQ1_16 - */ -#define WM5100_EQ1_B4_C_MASK 0xFFFF /* EQ1_B4_C - [15:0] */ -#define WM5100_EQ1_B4_C_SHIFT 0 /* EQ1_B4_C - [15:0] */ -#define WM5100_EQ1_B4_C_WIDTH 16 /* EQ1_B4_C - [15:0] */ - -/* - * R3616 (0xE20) - EQ1_17 - */ -#define WM5100_EQ1_B4_PG_MASK 0xFFFF /* EQ1_B4_PG - [15:0] */ -#define WM5100_EQ1_B4_PG_SHIFT 0 /* EQ1_B4_PG - [15:0] */ -#define WM5100_EQ1_B4_PG_WIDTH 16 /* EQ1_B4_PG - [15:0] */ - -/* - * R3617 (0xE21) - EQ1_18 - */ -#define WM5100_EQ1_B5_A_MASK 0xFFFF /* EQ1_B5_A - [15:0] */ -#define WM5100_EQ1_B5_A_SHIFT 0 /* EQ1_B5_A - [15:0] */ -#define WM5100_EQ1_B5_A_WIDTH 16 /* EQ1_B5_A - [15:0] */ - -/* - * R3618 (0xE22) - EQ1_19 - */ -#define WM5100_EQ1_B5_B_MASK 0xFFFF /* EQ1_B5_B - [15:0] */ -#define WM5100_EQ1_B5_B_SHIFT 0 /* EQ1_B5_B - [15:0] */ -#define WM5100_EQ1_B5_B_WIDTH 16 /* EQ1_B5_B - [15:0] */ - -/* - * R3619 (0xE23) - EQ1_20 - */ -#define WM5100_EQ1_B5_PG_MASK 0xFFFF /* EQ1_B5_PG - [15:0] */ -#define WM5100_EQ1_B5_PG_SHIFT 0 /* EQ1_B5_PG - [15:0] */ -#define WM5100_EQ1_B5_PG_WIDTH 16 /* EQ1_B5_PG - [15:0] */ - -/* - * R3622 (0xE26) - EQ2_1 - */ -#define WM5100_EQ2_B1_GAIN_MASK 0xF800 /* EQ2_B1_GAIN - [15:11] */ -#define WM5100_EQ2_B1_GAIN_SHIFT 11 /* EQ2_B1_GAIN - [15:11] */ -#define WM5100_EQ2_B1_GAIN_WIDTH 5 /* EQ2_B1_GAIN - [15:11] */ -#define WM5100_EQ2_B2_GAIN_MASK 0x07C0 /* EQ2_B2_GAIN - [10:6] */ -#define WM5100_EQ2_B2_GAIN_SHIFT 6 /* EQ2_B2_GAIN - [10:6] */ -#define WM5100_EQ2_B2_GAIN_WIDTH 5 /* EQ2_B2_GAIN - [10:6] */ -#define WM5100_EQ2_B3_GAIN_MASK 0x003E /* EQ2_B3_GAIN - [5:1] */ -#define WM5100_EQ2_B3_GAIN_SHIFT 1 /* EQ2_B3_GAIN - [5:1] */ -#define WM5100_EQ2_B3_GAIN_WIDTH 5 /* EQ2_B3_GAIN - [5:1] */ -#define WM5100_EQ2_ENA 0x0001 /* EQ2_ENA */ -#define WM5100_EQ2_ENA_MASK 0x0001 /* EQ2_ENA */ -#define WM5100_EQ2_ENA_SHIFT 0 /* EQ2_ENA */ -#define WM5100_EQ2_ENA_WIDTH 1 /* EQ2_ENA */ - -/* - * R3623 (0xE27) - EQ2_2 - */ -#define WM5100_EQ2_B4_GAIN_MASK 0xF800 /* EQ2_B4_GAIN - [15:11] */ -#define WM5100_EQ2_B4_GAIN_SHIFT 11 /* EQ2_B4_GAIN - [15:11] */ -#define WM5100_EQ2_B4_GAIN_WIDTH 5 /* EQ2_B4_GAIN - [15:11] */ -#define WM5100_EQ2_B5_GAIN_MASK 0x07C0 /* EQ2_B5_GAIN - [10:6] */ -#define WM5100_EQ2_B5_GAIN_SHIFT 6 /* EQ2_B5_GAIN - [10:6] */ -#define WM5100_EQ2_B5_GAIN_WIDTH 5 /* EQ2_B5_GAIN - [10:6] */ - -/* - * R3624 (0xE28) - EQ2_3 - */ -#define WM5100_EQ2_B1_A_MASK 0xFFFF /* EQ2_B1_A - [15:0] */ -#define WM5100_EQ2_B1_A_SHIFT 0 /* EQ2_B1_A - [15:0] */ -#define WM5100_EQ2_B1_A_WIDTH 16 /* EQ2_B1_A - [15:0] */ - -/* - * R3625 (0xE29) - EQ2_4 - */ -#define WM5100_EQ2_B1_B_MASK 0xFFFF /* EQ2_B1_B - [15:0] */ -#define WM5100_EQ2_B1_B_SHIFT 0 /* EQ2_B1_B - [15:0] */ -#define WM5100_EQ2_B1_B_WIDTH 16 /* EQ2_B1_B - [15:0] */ - -/* - * R3626 (0xE2A) - EQ2_5 - */ -#define WM5100_EQ2_B1_PG_MASK 0xFFFF /* EQ2_B1_PG - [15:0] */ -#define WM5100_EQ2_B1_PG_SHIFT 0 /* EQ2_B1_PG - [15:0] */ -#define WM5100_EQ2_B1_PG_WIDTH 16 /* EQ2_B1_PG - [15:0] */ - -/* - * R3627 (0xE2B) - EQ2_6 - */ -#define WM5100_EQ2_B2_A_MASK 0xFFFF /* EQ2_B2_A - [15:0] */ -#define WM5100_EQ2_B2_A_SHIFT 0 /* EQ2_B2_A - [15:0] */ -#define WM5100_EQ2_B2_A_WIDTH 16 /* EQ2_B2_A - [15:0] */ - -/* - * R3628 (0xE2C) - EQ2_7 - */ -#define WM5100_EQ2_B2_B_MASK 0xFFFF /* EQ2_B2_B - [15:0] */ -#define WM5100_EQ2_B2_B_SHIFT 0 /* EQ2_B2_B - [15:0] */ -#define WM5100_EQ2_B2_B_WIDTH 16 /* EQ2_B2_B - [15:0] */ - -/* - * R3629 (0xE2D) - EQ2_8 - */ -#define WM5100_EQ2_B2_C_MASK 0xFFFF /* EQ2_B2_C - [15:0] */ -#define WM5100_EQ2_B2_C_SHIFT 0 /* EQ2_B2_C - [15:0] */ -#define WM5100_EQ2_B2_C_WIDTH 16 /* EQ2_B2_C - [15:0] */ - -/* - * R3630 (0xE2E) - EQ2_9 - */ -#define WM5100_EQ2_B2_PG_MASK 0xFFFF /* EQ2_B2_PG - [15:0] */ -#define WM5100_EQ2_B2_PG_SHIFT 0 /* EQ2_B2_PG - [15:0] */ -#define WM5100_EQ2_B2_PG_WIDTH 16 /* EQ2_B2_PG - [15:0] */ - -/* - * R3631 (0xE2F) - EQ2_10 - */ -#define WM5100_EQ2_B3_A_MASK 0xFFFF /* EQ2_B3_A - [15:0] */ -#define WM5100_EQ2_B3_A_SHIFT 0 /* EQ2_B3_A - [15:0] */ -#define WM5100_EQ2_B3_A_WIDTH 16 /* EQ2_B3_A - [15:0] */ - -/* - * R3632 (0xE30) - EQ2_11 - */ -#define WM5100_EQ2_B3_B_MASK 0xFFFF /* EQ2_B3_B - [15:0] */ -#define WM5100_EQ2_B3_B_SHIFT 0 /* EQ2_B3_B - [15:0] */ -#define WM5100_EQ2_B3_B_WIDTH 16 /* EQ2_B3_B - [15:0] */ - -/* - * R3633 (0xE31) - EQ2_12 - */ -#define WM5100_EQ2_B3_C_MASK 0xFFFF /* EQ2_B3_C - [15:0] */ -#define WM5100_EQ2_B3_C_SHIFT 0 /* EQ2_B3_C - [15:0] */ -#define WM5100_EQ2_B3_C_WIDTH 16 /* EQ2_B3_C - [15:0] */ - -/* - * R3634 (0xE32) - EQ2_13 - */ -#define WM5100_EQ2_B3_PG_MASK 0xFFFF /* EQ2_B3_PG - [15:0] */ -#define WM5100_EQ2_B3_PG_SHIFT 0 /* EQ2_B3_PG - [15:0] */ -#define WM5100_EQ2_B3_PG_WIDTH 16 /* EQ2_B3_PG - [15:0] */ - -/* - * R3635 (0xE33) - EQ2_14 - */ -#define WM5100_EQ2_B4_A_MASK 0xFFFF /* EQ2_B4_A - [15:0] */ -#define WM5100_EQ2_B4_A_SHIFT 0 /* EQ2_B4_A - [15:0] */ -#define WM5100_EQ2_B4_A_WIDTH 16 /* EQ2_B4_A - [15:0] */ - -/* - * R3636 (0xE34) - EQ2_15 - */ -#define WM5100_EQ2_B4_B_MASK 0xFFFF /* EQ2_B4_B - [15:0] */ -#define WM5100_EQ2_B4_B_SHIFT 0 /* EQ2_B4_B - [15:0] */ -#define WM5100_EQ2_B4_B_WIDTH 16 /* EQ2_B4_B - [15:0] */ - -/* - * R3637 (0xE35) - EQ2_16 - */ -#define WM5100_EQ2_B4_C_MASK 0xFFFF /* EQ2_B4_C - [15:0] */ -#define WM5100_EQ2_B4_C_SHIFT 0 /* EQ2_B4_C - [15:0] */ -#define WM5100_EQ2_B4_C_WIDTH 16 /* EQ2_B4_C - [15:0] */ - -/* - * R3638 (0xE36) - EQ2_17 - */ -#define WM5100_EQ2_B4_PG_MASK 0xFFFF /* EQ2_B4_PG - [15:0] */ -#define WM5100_EQ2_B4_PG_SHIFT 0 /* EQ2_B4_PG - [15:0] */ -#define WM5100_EQ2_B4_PG_WIDTH 16 /* EQ2_B4_PG - [15:0] */ - -/* - * R3639 (0xE37) - EQ2_18 - */ -#define WM5100_EQ2_B5_A_MASK 0xFFFF /* EQ2_B5_A - [15:0] */ -#define WM5100_EQ2_B5_A_SHIFT 0 /* EQ2_B5_A - [15:0] */ -#define WM5100_EQ2_B5_A_WIDTH 16 /* EQ2_B5_A - [15:0] */ - -/* - * R3640 (0xE38) - EQ2_19 - */ -#define WM5100_EQ2_B5_B_MASK 0xFFFF /* EQ2_B5_B - [15:0] */ -#define WM5100_EQ2_B5_B_SHIFT 0 /* EQ2_B5_B - [15:0] */ -#define WM5100_EQ2_B5_B_WIDTH 16 /* EQ2_B5_B - [15:0] */ - -/* - * R3641 (0xE39) - EQ2_20 - */ -#define WM5100_EQ2_B5_PG_MASK 0xFFFF /* EQ2_B5_PG - [15:0] */ -#define WM5100_EQ2_B5_PG_SHIFT 0 /* EQ2_B5_PG - [15:0] */ -#define WM5100_EQ2_B5_PG_WIDTH 16 /* EQ2_B5_PG - [15:0] */ - -/* - * R3644 (0xE3C) - EQ3_1 - */ -#define WM5100_EQ3_B1_GAIN_MASK 0xF800 /* EQ3_B1_GAIN - [15:11] */ -#define WM5100_EQ3_B1_GAIN_SHIFT 11 /* EQ3_B1_GAIN - [15:11] */ -#define WM5100_EQ3_B1_GAIN_WIDTH 5 /* EQ3_B1_GAIN - [15:11] */ -#define WM5100_EQ3_B2_GAIN_MASK 0x07C0 /* EQ3_B2_GAIN - [10:6] */ -#define WM5100_EQ3_B2_GAIN_SHIFT 6 /* EQ3_B2_GAIN - [10:6] */ -#define WM5100_EQ3_B2_GAIN_WIDTH 5 /* EQ3_B2_GAIN - [10:6] */ -#define WM5100_EQ3_B3_GAIN_MASK 0x003E /* EQ3_B3_GAIN - [5:1] */ -#define WM5100_EQ3_B3_GAIN_SHIFT 1 /* EQ3_B3_GAIN - [5:1] */ -#define WM5100_EQ3_B3_GAIN_WIDTH 5 /* EQ3_B3_GAIN - [5:1] */ -#define WM5100_EQ3_ENA 0x0001 /* EQ3_ENA */ -#define WM5100_EQ3_ENA_MASK 0x0001 /* EQ3_ENA */ -#define WM5100_EQ3_ENA_SHIFT 0 /* EQ3_ENA */ -#define WM5100_EQ3_ENA_WIDTH 1 /* EQ3_ENA */ - -/* - * R3645 (0xE3D) - EQ3_2 - */ -#define WM5100_EQ3_B4_GAIN_MASK 0xF800 /* EQ3_B4_GAIN - [15:11] */ -#define WM5100_EQ3_B4_GAIN_SHIFT 11 /* EQ3_B4_GAIN - [15:11] */ -#define WM5100_EQ3_B4_GAIN_WIDTH 5 /* EQ3_B4_GAIN - [15:11] */ -#define WM5100_EQ3_B5_GAIN_MASK 0x07C0 /* EQ3_B5_GAIN - [10:6] */ -#define WM5100_EQ3_B5_GAIN_SHIFT 6 /* EQ3_B5_GAIN - [10:6] */ -#define WM5100_EQ3_B5_GAIN_WIDTH 5 /* EQ3_B5_GAIN - [10:6] */ - -/* - * R3646 (0xE3E) - EQ3_3 - */ -#define WM5100_EQ3_B1_A_MASK 0xFFFF /* EQ3_B1_A - [15:0] */ -#define WM5100_EQ3_B1_A_SHIFT 0 /* EQ3_B1_A - [15:0] */ -#define WM5100_EQ3_B1_A_WIDTH 16 /* EQ3_B1_A - [15:0] */ - -/* - * R3647 (0xE3F) - EQ3_4 - */ -#define WM5100_EQ3_B1_B_MASK 0xFFFF /* EQ3_B1_B - [15:0] */ -#define WM5100_EQ3_B1_B_SHIFT 0 /* EQ3_B1_B - [15:0] */ -#define WM5100_EQ3_B1_B_WIDTH 16 /* EQ3_B1_B - [15:0] */ - -/* - * R3648 (0xE40) - EQ3_5 - */ -#define WM5100_EQ3_B1_PG_MASK 0xFFFF /* EQ3_B1_PG - [15:0] */ -#define WM5100_EQ3_B1_PG_SHIFT 0 /* EQ3_B1_PG - [15:0] */ -#define WM5100_EQ3_B1_PG_WIDTH 16 /* EQ3_B1_PG - [15:0] */ - -/* - * R3649 (0xE41) - EQ3_6 - */ -#define WM5100_EQ3_B2_A_MASK 0xFFFF /* EQ3_B2_A - [15:0] */ -#define WM5100_EQ3_B2_A_SHIFT 0 /* EQ3_B2_A - [15:0] */ -#define WM5100_EQ3_B2_A_WIDTH 16 /* EQ3_B2_A - [15:0] */ - -/* - * R3650 (0xE42) - EQ3_7 - */ -#define WM5100_EQ3_B2_B_MASK 0xFFFF /* EQ3_B2_B - [15:0] */ -#define WM5100_EQ3_B2_B_SHIFT 0 /* EQ3_B2_B - [15:0] */ -#define WM5100_EQ3_B2_B_WIDTH 16 /* EQ3_B2_B - [15:0] */ - -/* - * R3651 (0xE43) - EQ3_8 - */ -#define WM5100_EQ3_B2_C_MASK 0xFFFF /* EQ3_B2_C - [15:0] */ -#define WM5100_EQ3_B2_C_SHIFT 0 /* EQ3_B2_C - [15:0] */ -#define WM5100_EQ3_B2_C_WIDTH 16 /* EQ3_B2_C - [15:0] */ - -/* - * R3652 (0xE44) - EQ3_9 - */ -#define WM5100_EQ3_B2_PG_MASK 0xFFFF /* EQ3_B2_PG - [15:0] */ -#define WM5100_EQ3_B2_PG_SHIFT 0 /* EQ3_B2_PG - [15:0] */ -#define WM5100_EQ3_B2_PG_WIDTH 16 /* EQ3_B2_PG - [15:0] */ - -/* - * R3653 (0xE45) - EQ3_10 - */ -#define WM5100_EQ3_B3_A_MASK 0xFFFF /* EQ3_B3_A - [15:0] */ -#define WM5100_EQ3_B3_A_SHIFT 0 /* EQ3_B3_A - [15:0] */ -#define WM5100_EQ3_B3_A_WIDTH 16 /* EQ3_B3_A - [15:0] */ - -/* - * R3654 (0xE46) - EQ3_11 - */ -#define WM5100_EQ3_B3_B_MASK 0xFFFF /* EQ3_B3_B - [15:0] */ -#define WM5100_EQ3_B3_B_SHIFT 0 /* EQ3_B3_B - [15:0] */ -#define WM5100_EQ3_B3_B_WIDTH 16 /* EQ3_B3_B - [15:0] */ - -/* - * R3655 (0xE47) - EQ3_12 - */ -#define WM5100_EQ3_B3_C_MASK 0xFFFF /* EQ3_B3_C - [15:0] */ -#define WM5100_EQ3_B3_C_SHIFT 0 /* EQ3_B3_C - [15:0] */ -#define WM5100_EQ3_B3_C_WIDTH 16 /* EQ3_B3_C - [15:0] */ - -/* - * R3656 (0xE48) - EQ3_13 - */ -#define WM5100_EQ3_B3_PG_MASK 0xFFFF /* EQ3_B3_PG - [15:0] */ -#define WM5100_EQ3_B3_PG_SHIFT 0 /* EQ3_B3_PG - [15:0] */ -#define WM5100_EQ3_B3_PG_WIDTH 16 /* EQ3_B3_PG - [15:0] */ - -/* - * R3657 (0xE49) - EQ3_14 - */ -#define WM5100_EQ3_B4_A_MASK 0xFFFF /* EQ3_B4_A - [15:0] */ -#define WM5100_EQ3_B4_A_SHIFT 0 /* EQ3_B4_A - [15:0] */ -#define WM5100_EQ3_B4_A_WIDTH 16 /* EQ3_B4_A - [15:0] */ - -/* - * R3658 (0xE4A) - EQ3_15 - */ -#define WM5100_EQ3_B4_B_MASK 0xFFFF /* EQ3_B4_B - [15:0] */ -#define WM5100_EQ3_B4_B_SHIFT 0 /* EQ3_B4_B - [15:0] */ -#define WM5100_EQ3_B4_B_WIDTH 16 /* EQ3_B4_B - [15:0] */ - -/* - * R3659 (0xE4B) - EQ3_16 - */ -#define WM5100_EQ3_B4_C_MASK 0xFFFF /* EQ3_B4_C - [15:0] */ -#define WM5100_EQ3_B4_C_SHIFT 0 /* EQ3_B4_C - [15:0] */ -#define WM5100_EQ3_B4_C_WIDTH 16 /* EQ3_B4_C - [15:0] */ - -/* - * R3660 (0xE4C) - EQ3_17 - */ -#define WM5100_EQ3_B4_PG_MASK 0xFFFF /* EQ3_B4_PG - [15:0] */ -#define WM5100_EQ3_B4_PG_SHIFT 0 /* EQ3_B4_PG - [15:0] */ -#define WM5100_EQ3_B4_PG_WIDTH 16 /* EQ3_B4_PG - [15:0] */ - -/* - * R3661 (0xE4D) - EQ3_18 - */ -#define WM5100_EQ3_B5_A_MASK 0xFFFF /* EQ3_B5_A - [15:0] */ -#define WM5100_EQ3_B5_A_SHIFT 0 /* EQ3_B5_A - [15:0] */ -#define WM5100_EQ3_B5_A_WIDTH 16 /* EQ3_B5_A - [15:0] */ - -/* - * R3662 (0xE4E) - EQ3_19 - */ -#define WM5100_EQ3_B5_B_MASK 0xFFFF /* EQ3_B5_B - [15:0] */ -#define WM5100_EQ3_B5_B_SHIFT 0 /* EQ3_B5_B - [15:0] */ -#define WM5100_EQ3_B5_B_WIDTH 16 /* EQ3_B5_B - [15:0] */ - -/* - * R3663 (0xE4F) - EQ3_20 - */ -#define WM5100_EQ3_B5_PG_MASK 0xFFFF /* EQ3_B5_PG - [15:0] */ -#define WM5100_EQ3_B5_PG_SHIFT 0 /* EQ3_B5_PG - [15:0] */ -#define WM5100_EQ3_B5_PG_WIDTH 16 /* EQ3_B5_PG - [15:0] */ - -/* - * R3666 (0xE52) - EQ4_1 - */ -#define WM5100_EQ4_B1_GAIN_MASK 0xF800 /* EQ4_B1_GAIN - [15:11] */ -#define WM5100_EQ4_B1_GAIN_SHIFT 11 /* EQ4_B1_GAIN - [15:11] */ -#define WM5100_EQ4_B1_GAIN_WIDTH 5 /* EQ4_B1_GAIN - [15:11] */ -#define WM5100_EQ4_B2_GAIN_MASK 0x07C0 /* EQ4_B2_GAIN - [10:6] */ -#define WM5100_EQ4_B2_GAIN_SHIFT 6 /* EQ4_B2_GAIN - [10:6] */ -#define WM5100_EQ4_B2_GAIN_WIDTH 5 /* EQ4_B2_GAIN - [10:6] */ -#define WM5100_EQ4_B3_GAIN_MASK 0x003E /* EQ4_B3_GAIN - [5:1] */ -#define WM5100_EQ4_B3_GAIN_SHIFT 1 /* EQ4_B3_GAIN - [5:1] */ -#define WM5100_EQ4_B3_GAIN_WIDTH 5 /* EQ4_B3_GAIN - [5:1] */ -#define WM5100_EQ4_ENA 0x0001 /* EQ4_ENA */ -#define WM5100_EQ4_ENA_MASK 0x0001 /* EQ4_ENA */ -#define WM5100_EQ4_ENA_SHIFT 0 /* EQ4_ENA */ -#define WM5100_EQ4_ENA_WIDTH 1 /* EQ4_ENA */ - -/* - * R3667 (0xE53) - EQ4_2 - */ -#define WM5100_EQ4_B4_GAIN_MASK 0xF800 /* EQ4_B4_GAIN - [15:11] */ -#define WM5100_EQ4_B4_GAIN_SHIFT 11 /* EQ4_B4_GAIN - [15:11] */ -#define WM5100_EQ4_B4_GAIN_WIDTH 5 /* EQ4_B4_GAIN - [15:11] */ -#define WM5100_EQ4_B5_GAIN_MASK 0x07C0 /* EQ4_B5_GAIN - [10:6] */ -#define WM5100_EQ4_B5_GAIN_SHIFT 6 /* EQ4_B5_GAIN - [10:6] */ -#define WM5100_EQ4_B5_GAIN_WIDTH 5 /* EQ4_B5_GAIN - [10:6] */ - -/* - * R3668 (0xE54) - EQ4_3 - */ -#define WM5100_EQ4_B1_A_MASK 0xFFFF /* EQ4_B1_A - [15:0] */ -#define WM5100_EQ4_B1_A_SHIFT 0 /* EQ4_B1_A - [15:0] */ -#define WM5100_EQ4_B1_A_WIDTH 16 /* EQ4_B1_A - [15:0] */ - -/* - * R3669 (0xE55) - EQ4_4 - */ -#define WM5100_EQ4_B1_B_MASK 0xFFFF /* EQ4_B1_B - [15:0] */ -#define WM5100_EQ4_B1_B_SHIFT 0 /* EQ4_B1_B - [15:0] */ -#define WM5100_EQ4_B1_B_WIDTH 16 /* EQ4_B1_B - [15:0] */ - -/* - * R3670 (0xE56) - EQ4_5 - */ -#define WM5100_EQ4_B1_PG_MASK 0xFFFF /* EQ4_B1_PG - [15:0] */ -#define WM5100_EQ4_B1_PG_SHIFT 0 /* EQ4_B1_PG - [15:0] */ -#define WM5100_EQ4_B1_PG_WIDTH 16 /* EQ4_B1_PG - [15:0] */ - -/* - * R3671 (0xE57) - EQ4_6 - */ -#define WM5100_EQ4_B2_A_MASK 0xFFFF /* EQ4_B2_A - [15:0] */ -#define WM5100_EQ4_B2_A_SHIFT 0 /* EQ4_B2_A - [15:0] */ -#define WM5100_EQ4_B2_A_WIDTH 16 /* EQ4_B2_A - [15:0] */ - -/* - * R3672 (0xE58) - EQ4_7 - */ -#define WM5100_EQ4_B2_B_MASK 0xFFFF /* EQ4_B2_B - [15:0] */ -#define WM5100_EQ4_B2_B_SHIFT 0 /* EQ4_B2_B - [15:0] */ -#define WM5100_EQ4_B2_B_WIDTH 16 /* EQ4_B2_B - [15:0] */ - -/* - * R3673 (0xE59) - EQ4_8 - */ -#define WM5100_EQ4_B2_C_MASK 0xFFFF /* EQ4_B2_C - [15:0] */ -#define WM5100_EQ4_B2_C_SHIFT 0 /* EQ4_B2_C - [15:0] */ -#define WM5100_EQ4_B2_C_WIDTH 16 /* EQ4_B2_C - [15:0] */ - -/* - * R3674 (0xE5A) - EQ4_9 - */ -#define WM5100_EQ4_B2_PG_MASK 0xFFFF /* EQ4_B2_PG - [15:0] */ -#define WM5100_EQ4_B2_PG_SHIFT 0 /* EQ4_B2_PG - [15:0] */ -#define WM5100_EQ4_B2_PG_WIDTH 16 /* EQ4_B2_PG - [15:0] */ - -/* - * R3675 (0xE5B) - EQ4_10 - */ -#define WM5100_EQ4_B3_A_MASK 0xFFFF /* EQ4_B3_A - [15:0] */ -#define WM5100_EQ4_B3_A_SHIFT 0 /* EQ4_B3_A - [15:0] */ -#define WM5100_EQ4_B3_A_WIDTH 16 /* EQ4_B3_A - [15:0] */ - -/* - * R3676 (0xE5C) - EQ4_11 - */ -#define WM5100_EQ4_B3_B_MASK 0xFFFF /* EQ4_B3_B - [15:0] */ -#define WM5100_EQ4_B3_B_SHIFT 0 /* EQ4_B3_B - [15:0] */ -#define WM5100_EQ4_B3_B_WIDTH 16 /* EQ4_B3_B - [15:0] */ - -/* - * R3677 (0xE5D) - EQ4_12 - */ -#define WM5100_EQ4_B3_C_MASK 0xFFFF /* EQ4_B3_C - [15:0] */ -#define WM5100_EQ4_B3_C_SHIFT 0 /* EQ4_B3_C - [15:0] */ -#define WM5100_EQ4_B3_C_WIDTH 16 /* EQ4_B3_C - [15:0] */ - -/* - * R3678 (0xE5E) - EQ4_13 - */ -#define WM5100_EQ4_B3_PG_MASK 0xFFFF /* EQ4_B3_PG - [15:0] */ -#define WM5100_EQ4_B3_PG_SHIFT 0 /* EQ4_B3_PG - [15:0] */ -#define WM5100_EQ4_B3_PG_WIDTH 16 /* EQ4_B3_PG - [15:0] */ - -/* - * R3679 (0xE5F) - EQ4_14 - */ -#define WM5100_EQ4_B4_A_MASK 0xFFFF /* EQ4_B4_A - [15:0] */ -#define WM5100_EQ4_B4_A_SHIFT 0 /* EQ4_B4_A - [15:0] */ -#define WM5100_EQ4_B4_A_WIDTH 16 /* EQ4_B4_A - [15:0] */ - -/* - * R3680 (0xE60) - EQ4_15 - */ -#define WM5100_EQ4_B4_B_MASK 0xFFFF /* EQ4_B4_B - [15:0] */ -#define WM5100_EQ4_B4_B_SHIFT 0 /* EQ4_B4_B - [15:0] */ -#define WM5100_EQ4_B4_B_WIDTH 16 /* EQ4_B4_B - [15:0] */ - -/* - * R3681 (0xE61) - EQ4_16 - */ -#define WM5100_EQ4_B4_C_MASK 0xFFFF /* EQ4_B4_C - [15:0] */ -#define WM5100_EQ4_B4_C_SHIFT 0 /* EQ4_B4_C - [15:0] */ -#define WM5100_EQ4_B4_C_WIDTH 16 /* EQ4_B4_C - [15:0] */ - -/* - * R3682 (0xE62) - EQ4_17 - */ -#define WM5100_EQ4_B4_PG_MASK 0xFFFF /* EQ4_B4_PG - [15:0] */ -#define WM5100_EQ4_B4_PG_SHIFT 0 /* EQ4_B4_PG - [15:0] */ -#define WM5100_EQ4_B4_PG_WIDTH 16 /* EQ4_B4_PG - [15:0] */ - -/* - * R3683 (0xE63) - EQ4_18 - */ -#define WM5100_EQ4_B5_A_MASK 0xFFFF /* EQ4_B5_A - [15:0] */ -#define WM5100_EQ4_B5_A_SHIFT 0 /* EQ4_B5_A - [15:0] */ -#define WM5100_EQ4_B5_A_WIDTH 16 /* EQ4_B5_A - [15:0] */ - -/* - * R3684 (0xE64) - EQ4_19 - */ -#define WM5100_EQ4_B5_B_MASK 0xFFFF /* EQ4_B5_B - [15:0] */ -#define WM5100_EQ4_B5_B_SHIFT 0 /* EQ4_B5_B - [15:0] */ -#define WM5100_EQ4_B5_B_WIDTH 16 /* EQ4_B5_B - [15:0] */ - -/* - * R3685 (0xE65) - EQ4_20 - */ -#define WM5100_EQ4_B5_PG_MASK 0xFFFF /* EQ4_B5_PG - [15:0] */ -#define WM5100_EQ4_B5_PG_SHIFT 0 /* EQ4_B5_PG - [15:0] */ -#define WM5100_EQ4_B5_PG_WIDTH 16 /* EQ4_B5_PG - [15:0] */ - -/* - * R3712 (0xE80) - DRC1 ctrl1 - */ -#define WM5100_DRC_SIG_DET_RMS_MASK 0xF800 /* DRC_SIG_DET_RMS - [15:11] */ -#define WM5100_DRC_SIG_DET_RMS_SHIFT 11 /* DRC_SIG_DET_RMS - [15:11] */ -#define WM5100_DRC_SIG_DET_RMS_WIDTH 5 /* DRC_SIG_DET_RMS - [15:11] */ -#define WM5100_DRC_SIG_DET_PK_MASK 0x0600 /* DRC_SIG_DET_PK - [10:9] */ -#define WM5100_DRC_SIG_DET_PK_SHIFT 9 /* DRC_SIG_DET_PK - [10:9] */ -#define WM5100_DRC_SIG_DET_PK_WIDTH 2 /* DRC_SIG_DET_PK - [10:9] */ -#define WM5100_DRC_NG_ENA 0x0100 /* DRC_NG_ENA */ -#define WM5100_DRC_NG_ENA_MASK 0x0100 /* DRC_NG_ENA */ -#define WM5100_DRC_NG_ENA_SHIFT 8 /* DRC_NG_ENA */ -#define WM5100_DRC_NG_ENA_WIDTH 1 /* DRC_NG_ENA */ -#define WM5100_DRC_SIG_DET_MODE 0x0080 /* DRC_SIG_DET_MODE */ -#define WM5100_DRC_SIG_DET_MODE_MASK 0x0080 /* DRC_SIG_DET_MODE */ -#define WM5100_DRC_SIG_DET_MODE_SHIFT 7 /* DRC_SIG_DET_MODE */ -#define WM5100_DRC_SIG_DET_MODE_WIDTH 1 /* DRC_SIG_DET_MODE */ -#define WM5100_DRC_SIG_DET 0x0040 /* DRC_SIG_DET */ -#define WM5100_DRC_SIG_DET_MASK 0x0040 /* DRC_SIG_DET */ -#define WM5100_DRC_SIG_DET_SHIFT 6 /* DRC_SIG_DET */ -#define WM5100_DRC_SIG_DET_WIDTH 1 /* DRC_SIG_DET */ -#define WM5100_DRC_KNEE2_OP_ENA 0x0020 /* DRC_KNEE2_OP_ENA */ -#define WM5100_DRC_KNEE2_OP_ENA_MASK 0x0020 /* DRC_KNEE2_OP_ENA */ -#define WM5100_DRC_KNEE2_OP_ENA_SHIFT 5 /* DRC_KNEE2_OP_ENA */ -#define WM5100_DRC_KNEE2_OP_ENA_WIDTH 1 /* DRC_KNEE2_OP_ENA */ -#define WM5100_DRC_QR 0x0010 /* DRC_QR */ -#define WM5100_DRC_QR_MASK 0x0010 /* DRC_QR */ -#define WM5100_DRC_QR_SHIFT 4 /* DRC_QR */ -#define WM5100_DRC_QR_WIDTH 1 /* DRC_QR */ -#define WM5100_DRC_ANTICLIP 0x0008 /* DRC_ANTICLIP */ -#define WM5100_DRC_ANTICLIP_MASK 0x0008 /* DRC_ANTICLIP */ -#define WM5100_DRC_ANTICLIP_SHIFT 3 /* DRC_ANTICLIP */ -#define WM5100_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */ -#define WM5100_DRCL_ENA 0x0002 /* DRCL_ENA */ -#define WM5100_DRCL_ENA_MASK 0x0002 /* DRCL_ENA */ -#define WM5100_DRCL_ENA_SHIFT 1 /* DRCL_ENA */ -#define WM5100_DRCL_ENA_WIDTH 1 /* DRCL_ENA */ -#define WM5100_DRCR_ENA 0x0001 /* DRCR_ENA */ -#define WM5100_DRCR_ENA_MASK 0x0001 /* DRCR_ENA */ -#define WM5100_DRCR_ENA_SHIFT 0 /* DRCR_ENA */ -#define WM5100_DRCR_ENA_WIDTH 1 /* DRCR_ENA */ - -/* - * R3713 (0xE81) - DRC1 ctrl2 - */ -#define WM5100_DRC_ATK_MASK 0x1E00 /* DRC_ATK - [12:9] */ -#define WM5100_DRC_ATK_SHIFT 9 /* DRC_ATK - [12:9] */ -#define WM5100_DRC_ATK_WIDTH 4 /* DRC_ATK - [12:9] */ -#define WM5100_DRC_DCY_MASK 0x01E0 /* DRC_DCY - [8:5] */ -#define WM5100_DRC_DCY_SHIFT 5 /* DRC_DCY - [8:5] */ -#define WM5100_DRC_DCY_WIDTH 4 /* DRC_DCY - [8:5] */ -#define WM5100_DRC_MINGAIN_MASK 0x001C /* DRC_MINGAIN - [4:2] */ -#define WM5100_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [4:2] */ -#define WM5100_DRC_MINGAIN_WIDTH 3 /* DRC_MINGAIN - [4:2] */ -#define WM5100_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ -#define WM5100_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ -#define WM5100_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ - -/* - * R3714 (0xE82) - DRC1 ctrl3 - */ -#define WM5100_DRC_NG_MINGAIN_MASK 0xF000 /* DRC_NG_MINGAIN - [15:12] */ -#define WM5100_DRC_NG_MINGAIN_SHIFT 12 /* DRC_NG_MINGAIN - [15:12] */ -#define WM5100_DRC_NG_MINGAIN_WIDTH 4 /* DRC_NG_MINGAIN - [15:12] */ -#define WM5100_DRC_NG_EXP_MASK 0x0C00 /* DRC_NG_EXP - [11:10] */ -#define WM5100_DRC_NG_EXP_SHIFT 10 /* DRC_NG_EXP - [11:10] */ -#define WM5100_DRC_NG_EXP_WIDTH 2 /* DRC_NG_EXP - [11:10] */ -#define WM5100_DRC_QR_THR_MASK 0x0300 /* DRC_QR_THR - [9:8] */ -#define WM5100_DRC_QR_THR_SHIFT 8 /* DRC_QR_THR - [9:8] */ -#define WM5100_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [9:8] */ -#define WM5100_DRC_QR_DCY_MASK 0x00C0 /* DRC_QR_DCY - [7:6] */ -#define WM5100_DRC_QR_DCY_SHIFT 6 /* DRC_QR_DCY - [7:6] */ -#define WM5100_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [7:6] */ -#define WM5100_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */ -#define WM5100_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */ -#define WM5100_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */ -#define WM5100_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */ -#define WM5100_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */ -#define WM5100_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */ - -/* - * R3715 (0xE83) - DRC1 ctrl4 - */ -#define WM5100_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */ -#define WM5100_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */ -#define WM5100_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */ -#define WM5100_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */ -#define WM5100_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */ -#define WM5100_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */ - -/* - * R3716 (0xE84) - DRC1 ctrl5 - */ -#define WM5100_DRC_KNEE2_IP_MASK 0x03E0 /* DRC_KNEE2_IP - [9:5] */ -#define WM5100_DRC_KNEE2_IP_SHIFT 5 /* DRC_KNEE2_IP - [9:5] */ -#define WM5100_DRC_KNEE2_IP_WIDTH 5 /* DRC_KNEE2_IP - [9:5] */ -#define WM5100_DRC_KNEE2_OP_MASK 0x001F /* DRC_KNEE2_OP - [4:0] */ -#define WM5100_DRC_KNEE2_OP_SHIFT 0 /* DRC_KNEE2_OP - [4:0] */ -#define WM5100_DRC_KNEE2_OP_WIDTH 5 /* DRC_KNEE2_OP - [4:0] */ - -/* - * R3776 (0xEC0) - HPLPF1_1 - */ -#define WM5100_LHPF1_MODE 0x0002 /* LHPF1_MODE */ -#define WM5100_LHPF1_MODE_MASK 0x0002 /* LHPF1_MODE */ -#define WM5100_LHPF1_MODE_SHIFT 1 /* LHPF1_MODE */ -#define WM5100_LHPF1_MODE_WIDTH 1 /* LHPF1_MODE */ -#define WM5100_LHPF1_ENA 0x0001 /* LHPF1_ENA */ -#define WM5100_LHPF1_ENA_MASK 0x0001 /* LHPF1_ENA */ -#define WM5100_LHPF1_ENA_SHIFT 0 /* LHPF1_ENA */ -#define WM5100_LHPF1_ENA_WIDTH 1 /* LHPF1_ENA */ - -/* - * R3777 (0xEC1) - HPLPF1_2 - */ -#define WM5100_LHPF1_COEFF_MASK 0xFFFF /* LHPF1_COEFF - [15:0] */ -#define WM5100_LHPF1_COEFF_SHIFT 0 /* LHPF1_COEFF - [15:0] */ -#define WM5100_LHPF1_COEFF_WIDTH 16 /* LHPF1_COEFF - [15:0] */ - -/* - * R3780 (0xEC4) - HPLPF2_1 - */ -#define WM5100_LHPF2_MODE 0x0002 /* LHPF2_MODE */ -#define WM5100_LHPF2_MODE_MASK 0x0002 /* LHPF2_MODE */ -#define WM5100_LHPF2_MODE_SHIFT 1 /* LHPF2_MODE */ -#define WM5100_LHPF2_MODE_WIDTH 1 /* LHPF2_MODE */ -#define WM5100_LHPF2_ENA 0x0001 /* LHPF2_ENA */ -#define WM5100_LHPF2_ENA_MASK 0x0001 /* LHPF2_ENA */ -#define WM5100_LHPF2_ENA_SHIFT 0 /* LHPF2_ENA */ -#define WM5100_LHPF2_ENA_WIDTH 1 /* LHPF2_ENA */ - -/* - * R3781 (0xEC5) - HPLPF2_2 - */ -#define WM5100_LHPF2_COEFF_MASK 0xFFFF /* LHPF2_COEFF - [15:0] */ -#define WM5100_LHPF2_COEFF_SHIFT 0 /* LHPF2_COEFF - [15:0] */ -#define WM5100_LHPF2_COEFF_WIDTH 16 /* LHPF2_COEFF - [15:0] */ - -/* - * R3784 (0xEC8) - HPLPF3_1 - */ -#define WM5100_LHPF3_MODE 0x0002 /* LHPF3_MODE */ -#define WM5100_LHPF3_MODE_MASK 0x0002 /* LHPF3_MODE */ -#define WM5100_LHPF3_MODE_SHIFT 1 /* LHPF3_MODE */ -#define WM5100_LHPF3_MODE_WIDTH 1 /* LHPF3_MODE */ -#define WM5100_LHPF3_ENA 0x0001 /* LHPF3_ENA */ -#define WM5100_LHPF3_ENA_MASK 0x0001 /* LHPF3_ENA */ -#define WM5100_LHPF3_ENA_SHIFT 0 /* LHPF3_ENA */ -#define WM5100_LHPF3_ENA_WIDTH 1 /* LHPF3_ENA */ - -/* - * R3785 (0xEC9) - HPLPF3_2 - */ -#define WM5100_LHPF3_COEFF_MASK 0xFFFF /* LHPF3_COEFF - [15:0] */ -#define WM5100_LHPF3_COEFF_SHIFT 0 /* LHPF3_COEFF - [15:0] */ -#define WM5100_LHPF3_COEFF_WIDTH 16 /* LHPF3_COEFF - [15:0] */ - -/* - * R3788 (0xECC) - HPLPF4_1 - */ -#define WM5100_LHPF4_MODE 0x0002 /* LHPF4_MODE */ -#define WM5100_LHPF4_MODE_MASK 0x0002 /* LHPF4_MODE */ -#define WM5100_LHPF4_MODE_SHIFT 1 /* LHPF4_MODE */ -#define WM5100_LHPF4_MODE_WIDTH 1 /* LHPF4_MODE */ -#define WM5100_LHPF4_ENA 0x0001 /* LHPF4_ENA */ -#define WM5100_LHPF4_ENA_MASK 0x0001 /* LHPF4_ENA */ -#define WM5100_LHPF4_ENA_SHIFT 0 /* LHPF4_ENA */ -#define WM5100_LHPF4_ENA_WIDTH 1 /* LHPF4_ENA */ - -/* - * R3789 (0xECD) - HPLPF4_2 - */ -#define WM5100_LHPF4_COEFF_MASK 0xFFFF /* LHPF4_COEFF - [15:0] */ -#define WM5100_LHPF4_COEFF_SHIFT 0 /* LHPF4_COEFF - [15:0] */ -#define WM5100_LHPF4_COEFF_WIDTH 16 /* LHPF4_COEFF - [15:0] */ - -/* - * R16384 (0x4000) - DSP1 DM 0 - */ -#define WM5100_DSP1_DM_START_1_MASK 0x00FF /* DSP1_DM_START - [7:0] */ -#define WM5100_DSP1_DM_START_1_SHIFT 0 /* DSP1_DM_START - [7:0] */ -#define WM5100_DSP1_DM_START_1_WIDTH 8 /* DSP1_DM_START - [7:0] */ - -/* - * R16385 (0x4001) - DSP1 DM 1 - */ -#define WM5100_DSP1_DM_START_MASK 0xFFFF /* DSP1_DM_START - [15:0] */ -#define WM5100_DSP1_DM_START_SHIFT 0 /* DSP1_DM_START - [15:0] */ -#define WM5100_DSP1_DM_START_WIDTH 16 /* DSP1_DM_START - [15:0] */ - -/* - * R16386 (0x4002) - DSP1 DM 2 - */ -#define WM5100_DSP1_DM_1_1_MASK 0x00FF /* DSP1_DM_1 - [7:0] */ -#define WM5100_DSP1_DM_1_1_SHIFT 0 /* DSP1_DM_1 - [7:0] */ -#define WM5100_DSP1_DM_1_1_WIDTH 8 /* DSP1_DM_1 - [7:0] */ - -/* - * R16387 (0x4003) - DSP1 DM 3 - */ -#define WM5100_DSP1_DM_1_MASK 0xFFFF /* DSP1_DM_1 - [15:0] */ -#define WM5100_DSP1_DM_1_SHIFT 0 /* DSP1_DM_1 - [15:0] */ -#define WM5100_DSP1_DM_1_WIDTH 16 /* DSP1_DM_1 - [15:0] */ - -/* - * R16892 (0x41FC) - DSP1 DM 508 - */ -#define WM5100_DSP1_DM_254_1_MASK 0x00FF /* DSP1_DM_254 - [7:0] */ -#define WM5100_DSP1_DM_254_1_SHIFT 0 /* DSP1_DM_254 - [7:0] */ -#define WM5100_DSP1_DM_254_1_WIDTH 8 /* DSP1_DM_254 - [7:0] */ - -/* - * R16893 (0x41FD) - DSP1 DM 509 - */ -#define WM5100_DSP1_DM_254_MASK 0xFFFF /* DSP1_DM_254 - [15:0] */ -#define WM5100_DSP1_DM_254_SHIFT 0 /* DSP1_DM_254 - [15:0] */ -#define WM5100_DSP1_DM_254_WIDTH 16 /* DSP1_DM_254 - [15:0] */ - -/* - * R16894 (0x41FE) - DSP1 DM 510 - */ -#define WM5100_DSP1_DM_END_1_MASK 0x00FF /* DSP1_DM_END - [7:0] */ -#define WM5100_DSP1_DM_END_1_SHIFT 0 /* DSP1_DM_END - [7:0] */ -#define WM5100_DSP1_DM_END_1_WIDTH 8 /* DSP1_DM_END - [7:0] */ - -/* - * R16895 (0x41FF) - DSP1 DM 511 - */ -#define WM5100_DSP1_DM_END_MASK 0xFFFF /* DSP1_DM_END - [15:0] */ -#define WM5100_DSP1_DM_END_SHIFT 0 /* DSP1_DM_END - [15:0] */ -#define WM5100_DSP1_DM_END_WIDTH 16 /* DSP1_DM_END - [15:0] */ - -/* - * R18432 (0x4800) - DSP1 PM 0 - */ -#define WM5100_DSP1_PM_START_2_MASK 0x00FF /* DSP1_PM_START - [7:0] */ -#define WM5100_DSP1_PM_START_2_SHIFT 0 /* DSP1_PM_START - [7:0] */ -#define WM5100_DSP1_PM_START_2_WIDTH 8 /* DSP1_PM_START - [7:0] */ - -/* - * R18433 (0x4801) - DSP1 PM 1 - */ -#define WM5100_DSP1_PM_START_1_MASK 0xFFFF /* DSP1_PM_START - [15:0] */ -#define WM5100_DSP1_PM_START_1_SHIFT 0 /* DSP1_PM_START - [15:0] */ -#define WM5100_DSP1_PM_START_1_WIDTH 16 /* DSP1_PM_START - [15:0] */ - -/* - * R18434 (0x4802) - DSP1 PM 2 - */ -#define WM5100_DSP1_PM_START_MASK 0xFFFF /* DSP1_PM_START - [15:0] */ -#define WM5100_DSP1_PM_START_SHIFT 0 /* DSP1_PM_START - [15:0] */ -#define WM5100_DSP1_PM_START_WIDTH 16 /* DSP1_PM_START - [15:0] */ - -/* - * R18435 (0x4803) - DSP1 PM 3 - */ -#define WM5100_DSP1_PM_1_2_MASK 0x00FF /* DSP1_PM_1 - [7:0] */ -#define WM5100_DSP1_PM_1_2_SHIFT 0 /* DSP1_PM_1 - [7:0] */ -#define WM5100_DSP1_PM_1_2_WIDTH 8 /* DSP1_PM_1 - [7:0] */ - -/* - * R18436 (0x4804) - DSP1 PM 4 - */ -#define WM5100_DSP1_PM_1_1_MASK 0xFFFF /* DSP1_PM_1 - [15:0] */ -#define WM5100_DSP1_PM_1_1_SHIFT 0 /* DSP1_PM_1 - [15:0] */ -#define WM5100_DSP1_PM_1_1_WIDTH 16 /* DSP1_PM_1 - [15:0] */ - -/* - * R18437 (0x4805) - DSP1 PM 5 - */ -#define WM5100_DSP1_PM_1_MASK 0xFFFF /* DSP1_PM_1 - [15:0] */ -#define WM5100_DSP1_PM_1_SHIFT 0 /* DSP1_PM_1 - [15:0] */ -#define WM5100_DSP1_PM_1_WIDTH 16 /* DSP1_PM_1 - [15:0] */ - -/* - * R19962 (0x4DFA) - DSP1 PM 1530 - */ -#define WM5100_DSP1_PM_510_2_MASK 0x00FF /* DSP1_PM_510 - [7:0] */ -#define WM5100_DSP1_PM_510_2_SHIFT 0 /* DSP1_PM_510 - [7:0] */ -#define WM5100_DSP1_PM_510_2_WIDTH 8 /* DSP1_PM_510 - [7:0] */ - -/* - * R19963 (0x4DFB) - DSP1 PM 1531 - */ -#define WM5100_DSP1_PM_510_1_MASK 0xFFFF /* DSP1_PM_510 - [15:0] */ -#define WM5100_DSP1_PM_510_1_SHIFT 0 /* DSP1_PM_510 - [15:0] */ -#define WM5100_DSP1_PM_510_1_WIDTH 16 /* DSP1_PM_510 - [15:0] */ - -/* - * R19964 (0x4DFC) - DSP1 PM 1532 - */ -#define WM5100_DSP1_PM_510_MASK 0xFFFF /* DSP1_PM_510 - [15:0] */ -#define WM5100_DSP1_PM_510_SHIFT 0 /* DSP1_PM_510 - [15:0] */ -#define WM5100_DSP1_PM_510_WIDTH 16 /* DSP1_PM_510 - [15:0] */ - -/* - * R19965 (0x4DFD) - DSP1 PM 1533 - */ -#define WM5100_DSP1_PM_END_2_MASK 0x00FF /* DSP1_PM_END - [7:0] */ -#define WM5100_DSP1_PM_END_2_SHIFT 0 /* DSP1_PM_END - [7:0] */ -#define WM5100_DSP1_PM_END_2_WIDTH 8 /* DSP1_PM_END - [7:0] */ - -/* - * R19966 (0x4DFE) - DSP1 PM 1534 - */ -#define WM5100_DSP1_PM_END_1_MASK 0xFFFF /* DSP1_PM_END - [15:0] */ -#define WM5100_DSP1_PM_END_1_SHIFT 0 /* DSP1_PM_END - [15:0] */ -#define WM5100_DSP1_PM_END_1_WIDTH 16 /* DSP1_PM_END - [15:0] */ - -/* - * R19967 (0x4DFF) - DSP1 PM 1535 - */ -#define WM5100_DSP1_PM_END_MASK 0xFFFF /* DSP1_PM_END - [15:0] */ -#define WM5100_DSP1_PM_END_SHIFT 0 /* DSP1_PM_END - [15:0] */ -#define WM5100_DSP1_PM_END_WIDTH 16 /* DSP1_PM_END - [15:0] */ - -/* - * R20480 (0x5000) - DSP1 ZM 0 - */ -#define WM5100_DSP1_ZM_START_1_MASK 0x00FF /* DSP1_ZM_START - [7:0] */ -#define WM5100_DSP1_ZM_START_1_SHIFT 0 /* DSP1_ZM_START - [7:0] */ -#define WM5100_DSP1_ZM_START_1_WIDTH 8 /* DSP1_ZM_START - [7:0] */ - -/* - * R20481 (0x5001) - DSP1 ZM 1 - */ -#define WM5100_DSP1_ZM_START_MASK 0xFFFF /* DSP1_ZM_START - [15:0] */ -#define WM5100_DSP1_ZM_START_SHIFT 0 /* DSP1_ZM_START - [15:0] */ -#define WM5100_DSP1_ZM_START_WIDTH 16 /* DSP1_ZM_START - [15:0] */ - -/* - * R20482 (0x5002) - DSP1 ZM 2 - */ -#define WM5100_DSP1_ZM_1_1_MASK 0x00FF /* DSP1_ZM_1 - [7:0] */ -#define WM5100_DSP1_ZM_1_1_SHIFT 0 /* DSP1_ZM_1 - [7:0] */ -#define WM5100_DSP1_ZM_1_1_WIDTH 8 /* DSP1_ZM_1 - [7:0] */ - -/* - * R20483 (0x5003) - DSP1 ZM 3 - */ -#define WM5100_DSP1_ZM_1_MASK 0xFFFF /* DSP1_ZM_1 - [15:0] */ -#define WM5100_DSP1_ZM_1_SHIFT 0 /* DSP1_ZM_1 - [15:0] */ -#define WM5100_DSP1_ZM_1_WIDTH 16 /* DSP1_ZM_1 - [15:0] */ - -/* - * R22524 (0x57FC) - DSP1 ZM 2044 - */ -#define WM5100_DSP1_ZM_1022_1_MASK 0x00FF /* DSP1_ZM_1022 - [7:0] */ -#define WM5100_DSP1_ZM_1022_1_SHIFT 0 /* DSP1_ZM_1022 - [7:0] */ -#define WM5100_DSP1_ZM_1022_1_WIDTH 8 /* DSP1_ZM_1022 - [7:0] */ - -/* - * R22525 (0x57FD) - DSP1 ZM 2045 - */ -#define WM5100_DSP1_ZM_1022_MASK 0xFFFF /* DSP1_ZM_1022 - [15:0] */ -#define WM5100_DSP1_ZM_1022_SHIFT 0 /* DSP1_ZM_1022 - [15:0] */ -#define WM5100_DSP1_ZM_1022_WIDTH 16 /* DSP1_ZM_1022 - [15:0] */ - -/* - * R22526 (0x57FE) - DSP1 ZM 2046 - */ -#define WM5100_DSP1_ZM_END_1_MASK 0x00FF /* DSP1_ZM_END - [7:0] */ -#define WM5100_DSP1_ZM_END_1_SHIFT 0 /* DSP1_ZM_END - [7:0] */ -#define WM5100_DSP1_ZM_END_1_WIDTH 8 /* DSP1_ZM_END - [7:0] */ - -/* - * R22527 (0x57FF) - DSP1 ZM 2047 - */ -#define WM5100_DSP1_ZM_END_MASK 0xFFFF /* DSP1_ZM_END - [15:0] */ -#define WM5100_DSP1_ZM_END_SHIFT 0 /* DSP1_ZM_END - [15:0] */ -#define WM5100_DSP1_ZM_END_WIDTH 16 /* DSP1_ZM_END - [15:0] */ - -/* - * R24576 (0x6000) - DSP2 DM 0 - */ -#define WM5100_DSP2_DM_START_1_MASK 0x00FF /* DSP2_DM_START - [7:0] */ -#define WM5100_DSP2_DM_START_1_SHIFT 0 /* DSP2_DM_START - [7:0] */ -#define WM5100_DSP2_DM_START_1_WIDTH 8 /* DSP2_DM_START - [7:0] */ - -/* - * R24577 (0x6001) - DSP2 DM 1 - */ -#define WM5100_DSP2_DM_START_MASK 0xFFFF /* DSP2_DM_START - [15:0] */ -#define WM5100_DSP2_DM_START_SHIFT 0 /* DSP2_DM_START - [15:0] */ -#define WM5100_DSP2_DM_START_WIDTH 16 /* DSP2_DM_START - [15:0] */ - -/* - * R24578 (0x6002) - DSP2 DM 2 - */ -#define WM5100_DSP2_DM_1_1_MASK 0x00FF /* DSP2_DM_1 - [7:0] */ -#define WM5100_DSP2_DM_1_1_SHIFT 0 /* DSP2_DM_1 - [7:0] */ -#define WM5100_DSP2_DM_1_1_WIDTH 8 /* DSP2_DM_1 - [7:0] */ - -/* - * R24579 (0x6003) - DSP2 DM 3 - */ -#define WM5100_DSP2_DM_1_MASK 0xFFFF /* DSP2_DM_1 - [15:0] */ -#define WM5100_DSP2_DM_1_SHIFT 0 /* DSP2_DM_1 - [15:0] */ -#define WM5100_DSP2_DM_1_WIDTH 16 /* DSP2_DM_1 - [15:0] */ - -/* - * R25084 (0x61FC) - DSP2 DM 508 - */ -#define WM5100_DSP2_DM_254_1_MASK 0x00FF /* DSP2_DM_254 - [7:0] */ -#define WM5100_DSP2_DM_254_1_SHIFT 0 /* DSP2_DM_254 - [7:0] */ -#define WM5100_DSP2_DM_254_1_WIDTH 8 /* DSP2_DM_254 - [7:0] */ - -/* - * R25085 (0x61FD) - DSP2 DM 509 - */ -#define WM5100_DSP2_DM_254_MASK 0xFFFF /* DSP2_DM_254 - [15:0] */ -#define WM5100_DSP2_DM_254_SHIFT 0 /* DSP2_DM_254 - [15:0] */ -#define WM5100_DSP2_DM_254_WIDTH 16 /* DSP2_DM_254 - [15:0] */ - -/* - * R25086 (0x61FE) - DSP2 DM 510 - */ -#define WM5100_DSP2_DM_END_1_MASK 0x00FF /* DSP2_DM_END - [7:0] */ -#define WM5100_DSP2_DM_END_1_SHIFT 0 /* DSP2_DM_END - [7:0] */ -#define WM5100_DSP2_DM_END_1_WIDTH 8 /* DSP2_DM_END - [7:0] */ - -/* - * R25087 (0x61FF) - DSP2 DM 511 - */ -#define WM5100_DSP2_DM_END_MASK 0xFFFF /* DSP2_DM_END - [15:0] */ -#define WM5100_DSP2_DM_END_SHIFT 0 /* DSP2_DM_END - [15:0] */ -#define WM5100_DSP2_DM_END_WIDTH 16 /* DSP2_DM_END - [15:0] */ - -/* - * R26624 (0x6800) - DSP2 PM 0 - */ -#define WM5100_DSP2_PM_START_2_MASK 0x00FF /* DSP2_PM_START - [7:0] */ -#define WM5100_DSP2_PM_START_2_SHIFT 0 /* DSP2_PM_START - [7:0] */ -#define WM5100_DSP2_PM_START_2_WIDTH 8 /* DSP2_PM_START - [7:0] */ - -/* - * R26625 (0x6801) - DSP2 PM 1 - */ -#define WM5100_DSP2_PM_START_1_MASK 0xFFFF /* DSP2_PM_START - [15:0] */ -#define WM5100_DSP2_PM_START_1_SHIFT 0 /* DSP2_PM_START - [15:0] */ -#define WM5100_DSP2_PM_START_1_WIDTH 16 /* DSP2_PM_START - [15:0] */ - -/* - * R26626 (0x6802) - DSP2 PM 2 - */ -#define WM5100_DSP2_PM_START_MASK 0xFFFF /* DSP2_PM_START - [15:0] */ -#define WM5100_DSP2_PM_START_SHIFT 0 /* DSP2_PM_START - [15:0] */ -#define WM5100_DSP2_PM_START_WIDTH 16 /* DSP2_PM_START - [15:0] */ - -/* - * R26627 (0x6803) - DSP2 PM 3 - */ -#define WM5100_DSP2_PM_1_2_MASK 0x00FF /* DSP2_PM_1 - [7:0] */ -#define WM5100_DSP2_PM_1_2_SHIFT 0 /* DSP2_PM_1 - [7:0] */ -#define WM5100_DSP2_PM_1_2_WIDTH 8 /* DSP2_PM_1 - [7:0] */ - -/* - * R26628 (0x6804) - DSP2 PM 4 - */ -#define WM5100_DSP2_PM_1_1_MASK 0xFFFF /* DSP2_PM_1 - [15:0] */ -#define WM5100_DSP2_PM_1_1_SHIFT 0 /* DSP2_PM_1 - [15:0] */ -#define WM5100_DSP2_PM_1_1_WIDTH 16 /* DSP2_PM_1 - [15:0] */ - -/* - * R26629 (0x6805) - DSP2 PM 5 - */ -#define WM5100_DSP2_PM_1_MASK 0xFFFF /* DSP2_PM_1 - [15:0] */ -#define WM5100_DSP2_PM_1_SHIFT 0 /* DSP2_PM_1 - [15:0] */ -#define WM5100_DSP2_PM_1_WIDTH 16 /* DSP2_PM_1 - [15:0] */ - -/* - * R28154 (0x6DFA) - DSP2 PM 1530 - */ -#define WM5100_DSP2_PM_510_2_MASK 0x00FF /* DSP2_PM_510 - [7:0] */ -#define WM5100_DSP2_PM_510_2_SHIFT 0 /* DSP2_PM_510 - [7:0] */ -#define WM5100_DSP2_PM_510_2_WIDTH 8 /* DSP2_PM_510 - [7:0] */ - -/* - * R28155 (0x6DFB) - DSP2 PM 1531 - */ -#define WM5100_DSP2_PM_510_1_MASK 0xFFFF /* DSP2_PM_510 - [15:0] */ -#define WM5100_DSP2_PM_510_1_SHIFT 0 /* DSP2_PM_510 - [15:0] */ -#define WM5100_DSP2_PM_510_1_WIDTH 16 /* DSP2_PM_510 - [15:0] */ - -/* - * R28156 (0x6DFC) - DSP2 PM 1532 - */ -#define WM5100_DSP2_PM_510_MASK 0xFFFF /* DSP2_PM_510 - [15:0] */ -#define WM5100_DSP2_PM_510_SHIFT 0 /* DSP2_PM_510 - [15:0] */ -#define WM5100_DSP2_PM_510_WIDTH 16 /* DSP2_PM_510 - [15:0] */ - -/* - * R28157 (0x6DFD) - DSP2 PM 1533 - */ -#define WM5100_DSP2_PM_END_2_MASK 0x00FF /* DSP2_PM_END - [7:0] */ -#define WM5100_DSP2_PM_END_2_SHIFT 0 /* DSP2_PM_END - [7:0] */ -#define WM5100_DSP2_PM_END_2_WIDTH 8 /* DSP2_PM_END - [7:0] */ - -/* - * R28158 (0x6DFE) - DSP2 PM 1534 - */ -#define WM5100_DSP2_PM_END_1_MASK 0xFFFF /* DSP2_PM_END - [15:0] */ -#define WM5100_DSP2_PM_END_1_SHIFT 0 /* DSP2_PM_END - [15:0] */ -#define WM5100_DSP2_PM_END_1_WIDTH 16 /* DSP2_PM_END - [15:0] */ - -/* - * R28159 (0x6DFF) - DSP2 PM 1535 - */ -#define WM5100_DSP2_PM_END_MASK 0xFFFF /* DSP2_PM_END - [15:0] */ -#define WM5100_DSP2_PM_END_SHIFT 0 /* DSP2_PM_END - [15:0] */ -#define WM5100_DSP2_PM_END_WIDTH 16 /* DSP2_PM_END - [15:0] */ - -/* - * R28672 (0x7000) - DSP2 ZM 0 - */ -#define WM5100_DSP2_ZM_START_1_MASK 0x00FF /* DSP2_ZM_START - [7:0] */ -#define WM5100_DSP2_ZM_START_1_SHIFT 0 /* DSP2_ZM_START - [7:0] */ -#define WM5100_DSP2_ZM_START_1_WIDTH 8 /* DSP2_ZM_START - [7:0] */ - -/* - * R28673 (0x7001) - DSP2 ZM 1 - */ -#define WM5100_DSP2_ZM_START_MASK 0xFFFF /* DSP2_ZM_START - [15:0] */ -#define WM5100_DSP2_ZM_START_SHIFT 0 /* DSP2_ZM_START - [15:0] */ -#define WM5100_DSP2_ZM_START_WIDTH 16 /* DSP2_ZM_START - [15:0] */ - -/* - * R28674 (0x7002) - DSP2 ZM 2 - */ -#define WM5100_DSP2_ZM_1_1_MASK 0x00FF /* DSP2_ZM_1 - [7:0] */ -#define WM5100_DSP2_ZM_1_1_SHIFT 0 /* DSP2_ZM_1 - [7:0] */ -#define WM5100_DSP2_ZM_1_1_WIDTH 8 /* DSP2_ZM_1 - [7:0] */ - -/* - * R28675 (0x7003) - DSP2 ZM 3 - */ -#define WM5100_DSP2_ZM_1_MASK 0xFFFF /* DSP2_ZM_1 - [15:0] */ -#define WM5100_DSP2_ZM_1_SHIFT 0 /* DSP2_ZM_1 - [15:0] */ -#define WM5100_DSP2_ZM_1_WIDTH 16 /* DSP2_ZM_1 - [15:0] */ - -/* - * R30716 (0x77FC) - DSP2 ZM 2044 - */ -#define WM5100_DSP2_ZM_1022_1_MASK 0x00FF /* DSP2_ZM_1022 - [7:0] */ -#define WM5100_DSP2_ZM_1022_1_SHIFT 0 /* DSP2_ZM_1022 - [7:0] */ -#define WM5100_DSP2_ZM_1022_1_WIDTH 8 /* DSP2_ZM_1022 - [7:0] */ - -/* - * R30717 (0x77FD) - DSP2 ZM 2045 - */ -#define WM5100_DSP2_ZM_1022_MASK 0xFFFF /* DSP2_ZM_1022 - [15:0] */ -#define WM5100_DSP2_ZM_1022_SHIFT 0 /* DSP2_ZM_1022 - [15:0] */ -#define WM5100_DSP2_ZM_1022_WIDTH 16 /* DSP2_ZM_1022 - [15:0] */ - -/* - * R30718 (0x77FE) - DSP2 ZM 2046 - */ -#define WM5100_DSP2_ZM_END_1_MASK 0x00FF /* DSP2_ZM_END - [7:0] */ -#define WM5100_DSP2_ZM_END_1_SHIFT 0 /* DSP2_ZM_END - [7:0] */ -#define WM5100_DSP2_ZM_END_1_WIDTH 8 /* DSP2_ZM_END - [7:0] */ - -/* - * R30719 (0x77FF) - DSP2 ZM 2047 - */ -#define WM5100_DSP2_ZM_END_MASK 0xFFFF /* DSP2_ZM_END - [15:0] */ -#define WM5100_DSP2_ZM_END_SHIFT 0 /* DSP2_ZM_END - [15:0] */ -#define WM5100_DSP2_ZM_END_WIDTH 16 /* DSP2_ZM_END - [15:0] */ - -/* - * R32768 (0x8000) - DSP3 DM 0 - */ -#define WM5100_DSP3_DM_START_1_MASK 0x00FF /* DSP3_DM_START - [7:0] */ -#define WM5100_DSP3_DM_START_1_SHIFT 0 /* DSP3_DM_START - [7:0] */ -#define WM5100_DSP3_DM_START_1_WIDTH 8 /* DSP3_DM_START - [7:0] */ - -/* - * R32769 (0x8001) - DSP3 DM 1 - */ -#define WM5100_DSP3_DM_START_MASK 0xFFFF /* DSP3_DM_START - [15:0] */ -#define WM5100_DSP3_DM_START_SHIFT 0 /* DSP3_DM_START - [15:0] */ -#define WM5100_DSP3_DM_START_WIDTH 16 /* DSP3_DM_START - [15:0] */ - -/* - * R32770 (0x8002) - DSP3 DM 2 - */ -#define WM5100_DSP3_DM_1_1_MASK 0x00FF /* DSP3_DM_1 - [7:0] */ -#define WM5100_DSP3_DM_1_1_SHIFT 0 /* DSP3_DM_1 - [7:0] */ -#define WM5100_DSP3_DM_1_1_WIDTH 8 /* DSP3_DM_1 - [7:0] */ - -/* - * R32771 (0x8003) - DSP3 DM 3 - */ -#define WM5100_DSP3_DM_1_MASK 0xFFFF /* DSP3_DM_1 - [15:0] */ -#define WM5100_DSP3_DM_1_SHIFT 0 /* DSP3_DM_1 - [15:0] */ -#define WM5100_DSP3_DM_1_WIDTH 16 /* DSP3_DM_1 - [15:0] */ - -/* - * R33276 (0x81FC) - DSP3 DM 508 - */ -#define WM5100_DSP3_DM_254_1_MASK 0x00FF /* DSP3_DM_254 - [7:0] */ -#define WM5100_DSP3_DM_254_1_SHIFT 0 /* DSP3_DM_254 - [7:0] */ -#define WM5100_DSP3_DM_254_1_WIDTH 8 /* DSP3_DM_254 - [7:0] */ - -/* - * R33277 (0x81FD) - DSP3 DM 509 - */ -#define WM5100_DSP3_DM_254_MASK 0xFFFF /* DSP3_DM_254 - [15:0] */ -#define WM5100_DSP3_DM_254_SHIFT 0 /* DSP3_DM_254 - [15:0] */ -#define WM5100_DSP3_DM_254_WIDTH 16 /* DSP3_DM_254 - [15:0] */ - -/* - * R33278 (0x81FE) - DSP3 DM 510 - */ -#define WM5100_DSP3_DM_END_1_MASK 0x00FF /* DSP3_DM_END - [7:0] */ -#define WM5100_DSP3_DM_END_1_SHIFT 0 /* DSP3_DM_END - [7:0] */ -#define WM5100_DSP3_DM_END_1_WIDTH 8 /* DSP3_DM_END - [7:0] */ - -/* - * R33279 (0x81FF) - DSP3 DM 511 - */ -#define WM5100_DSP3_DM_END_MASK 0xFFFF /* DSP3_DM_END - [15:0] */ -#define WM5100_DSP3_DM_END_SHIFT 0 /* DSP3_DM_END - [15:0] */ -#define WM5100_DSP3_DM_END_WIDTH 16 /* DSP3_DM_END - [15:0] */ - -/* - * R34816 (0x8800) - DSP3 PM 0 - */ -#define WM5100_DSP3_PM_START_2_MASK 0x00FF /* DSP3_PM_START - [7:0] */ -#define WM5100_DSP3_PM_START_2_SHIFT 0 /* DSP3_PM_START - [7:0] */ -#define WM5100_DSP3_PM_START_2_WIDTH 8 /* DSP3_PM_START - [7:0] */ - -/* - * R34817 (0x8801) - DSP3 PM 1 - */ -#define WM5100_DSP3_PM_START_1_MASK 0xFFFF /* DSP3_PM_START - [15:0] */ -#define WM5100_DSP3_PM_START_1_SHIFT 0 /* DSP3_PM_START - [15:0] */ -#define WM5100_DSP3_PM_START_1_WIDTH 16 /* DSP3_PM_START - [15:0] */ - -/* - * R34818 (0x8802) - DSP3 PM 2 - */ -#define WM5100_DSP3_PM_START_MASK 0xFFFF /* DSP3_PM_START - [15:0] */ -#define WM5100_DSP3_PM_START_SHIFT 0 /* DSP3_PM_START - [15:0] */ -#define WM5100_DSP3_PM_START_WIDTH 16 /* DSP3_PM_START - [15:0] */ - -/* - * R34819 (0x8803) - DSP3 PM 3 - */ -#define WM5100_DSP3_PM_1_2_MASK 0x00FF /* DSP3_PM_1 - [7:0] */ -#define WM5100_DSP3_PM_1_2_SHIFT 0 /* DSP3_PM_1 - [7:0] */ -#define WM5100_DSP3_PM_1_2_WIDTH 8 /* DSP3_PM_1 - [7:0] */ - -/* - * R34820 (0x8804) - DSP3 PM 4 - */ -#define WM5100_DSP3_PM_1_1_MASK 0xFFFF /* DSP3_PM_1 - [15:0] */ -#define WM5100_DSP3_PM_1_1_SHIFT 0 /* DSP3_PM_1 - [15:0] */ -#define WM5100_DSP3_PM_1_1_WIDTH 16 /* DSP3_PM_1 - [15:0] */ - -/* - * R34821 (0x8805) - DSP3 PM 5 - */ -#define WM5100_DSP3_PM_1_MASK 0xFFFF /* DSP3_PM_1 - [15:0] */ -#define WM5100_DSP3_PM_1_SHIFT 0 /* DSP3_PM_1 - [15:0] */ -#define WM5100_DSP3_PM_1_WIDTH 16 /* DSP3_PM_1 - [15:0] */ - -/* - * R36346 (0x8DFA) - DSP3 PM 1530 - */ -#define WM5100_DSP3_PM_510_2_MASK 0x00FF /* DSP3_PM_510 - [7:0] */ -#define WM5100_DSP3_PM_510_2_SHIFT 0 /* DSP3_PM_510 - [7:0] */ -#define WM5100_DSP3_PM_510_2_WIDTH 8 /* DSP3_PM_510 - [7:0] */ - -/* - * R36347 (0x8DFB) - DSP3 PM 1531 - */ -#define WM5100_DSP3_PM_510_1_MASK 0xFFFF /* DSP3_PM_510 - [15:0] */ -#define WM5100_DSP3_PM_510_1_SHIFT 0 /* DSP3_PM_510 - [15:0] */ -#define WM5100_DSP3_PM_510_1_WIDTH 16 /* DSP3_PM_510 - [15:0] */ - -/* - * R36348 (0x8DFC) - DSP3 PM 1532 - */ -#define WM5100_DSP3_PM_510_MASK 0xFFFF /* DSP3_PM_510 - [15:0] */ -#define WM5100_DSP3_PM_510_SHIFT 0 /* DSP3_PM_510 - [15:0] */ -#define WM5100_DSP3_PM_510_WIDTH 16 /* DSP3_PM_510 - [15:0] */ - -/* - * R36349 (0x8DFD) - DSP3 PM 1533 - */ -#define WM5100_DSP3_PM_END_2_MASK 0x00FF /* DSP3_PM_END - [7:0] */ -#define WM5100_DSP3_PM_END_2_SHIFT 0 /* DSP3_PM_END - [7:0] */ -#define WM5100_DSP3_PM_END_2_WIDTH 8 /* DSP3_PM_END - [7:0] */ - -/* - * R36350 (0x8DFE) - DSP3 PM 1534 - */ -#define WM5100_DSP3_PM_END_1_MASK 0xFFFF /* DSP3_PM_END - [15:0] */ -#define WM5100_DSP3_PM_END_1_SHIFT 0 /* DSP3_PM_END - [15:0] */ -#define WM5100_DSP3_PM_END_1_WIDTH 16 /* DSP3_PM_END - [15:0] */ - -/* - * R36351 (0x8DFF) - DSP3 PM 1535 - */ -#define WM5100_DSP3_PM_END_MASK 0xFFFF /* DSP3_PM_END - [15:0] */ -#define WM5100_DSP3_PM_END_SHIFT 0 /* DSP3_PM_END - [15:0] */ -#define WM5100_DSP3_PM_END_WIDTH 16 /* DSP3_PM_END - [15:0] */ - -/* - * R36864 (0x9000) - DSP3 ZM 0 - */ -#define WM5100_DSP3_ZM_START_1_MASK 0x00FF /* DSP3_ZM_START - [7:0] */ -#define WM5100_DSP3_ZM_START_1_SHIFT 0 /* DSP3_ZM_START - [7:0] */ -#define WM5100_DSP3_ZM_START_1_WIDTH 8 /* DSP3_ZM_START - [7:0] */ - -/* - * R36865 (0x9001) - DSP3 ZM 1 - */ -#define WM5100_DSP3_ZM_START_MASK 0xFFFF /* DSP3_ZM_START - [15:0] */ -#define WM5100_DSP3_ZM_START_SHIFT 0 /* DSP3_ZM_START - [15:0] */ -#define WM5100_DSP3_ZM_START_WIDTH 16 /* DSP3_ZM_START - [15:0] */ - -/* - * R36866 (0x9002) - DSP3 ZM 2 - */ -#define WM5100_DSP3_ZM_1_1_MASK 0x00FF /* DSP3_ZM_1 - [7:0] */ -#define WM5100_DSP3_ZM_1_1_SHIFT 0 /* DSP3_ZM_1 - [7:0] */ -#define WM5100_DSP3_ZM_1_1_WIDTH 8 /* DSP3_ZM_1 - [7:0] */ - -/* - * R36867 (0x9003) - DSP3 ZM 3 - */ -#define WM5100_DSP3_ZM_1_MASK 0xFFFF /* DSP3_ZM_1 - [15:0] */ -#define WM5100_DSP3_ZM_1_SHIFT 0 /* DSP3_ZM_1 - [15:0] */ -#define WM5100_DSP3_ZM_1_WIDTH 16 /* DSP3_ZM_1 - [15:0] */ - -/* - * R38908 (0x97FC) - DSP3 ZM 2044 - */ -#define WM5100_DSP3_ZM_1022_1_MASK 0x00FF /* DSP3_ZM_1022 - [7:0] */ -#define WM5100_DSP3_ZM_1022_1_SHIFT 0 /* DSP3_ZM_1022 - [7:0] */ -#define WM5100_DSP3_ZM_1022_1_WIDTH 8 /* DSP3_ZM_1022 - [7:0] */ - -/* - * R38909 (0x97FD) - DSP3 ZM 2045 - */ -#define WM5100_DSP3_ZM_1022_MASK 0xFFFF /* DSP3_ZM_1022 - [15:0] */ -#define WM5100_DSP3_ZM_1022_SHIFT 0 /* DSP3_ZM_1022 - [15:0] */ -#define WM5100_DSP3_ZM_1022_WIDTH 16 /* DSP3_ZM_1022 - [15:0] */ - -/* - * R38910 (0x97FE) - DSP3 ZM 2046 - */ -#define WM5100_DSP3_ZM_END_1_MASK 0x00FF /* DSP3_ZM_END - [7:0] */ -#define WM5100_DSP3_ZM_END_1_SHIFT 0 /* DSP3_ZM_END - [7:0] */ -#define WM5100_DSP3_ZM_END_1_WIDTH 8 /* DSP3_ZM_END - [7:0] */ - -/* - * R38911 (0x97FF) - DSP3 ZM 2047 - */ -#define WM5100_DSP3_ZM_END_MASK 0xFFFF /* DSP3_ZM_END - [15:0] */ -#define WM5100_DSP3_ZM_END_SHIFT 0 /* DSP3_ZM_END - [15:0] */ -#define WM5100_DSP3_ZM_END_WIDTH 16 /* DSP3_ZM_END - [15:0] */ - -bool wm5100_readable_register(struct device *dev, unsigned int reg); -bool wm5100_volatile_register(struct device *dev, unsigned int reg); - -extern struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT]; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8350.c b/ANDROID_3.4.5/sound/soc/codecs/wm8350.c deleted file mode 100644 index aa12c6b6..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8350.c +++ /dev/null @@ -1,1697 +0,0 @@ -/* - * wm8350.c -- WM8350 ALSA SoC audio driver - * - * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. - * - * Author: Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8350.h" - -#define WM8350_OUTn_0dB 0x39 - -#define WM8350_RAMP_NONE 0 -#define WM8350_RAMP_UP 1 -#define WM8350_RAMP_DOWN 2 - -/* We only include the analogue supplies here; the digital supplies - * need to be available well before this driver can be probed. - */ -static const char *supply_names[] = { - "AVDD", - "HPVDD", -}; - -struct wm8350_output { - u16 active; - u16 left_vol; - u16 right_vol; - u16 ramp; - u16 mute; -}; - -struct wm8350_jack_data { - struct snd_soc_jack *jack; - struct delayed_work work; - int report; - int short_report; -}; - -struct wm8350_data { - struct wm8350 *wm8350; - struct wm8350_output out1; - struct wm8350_output out2; - struct wm8350_jack_data hpl; - struct wm8350_jack_data hpr; - struct wm8350_jack_data mic; - struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; - int fll_freq_out; - int fll_freq_in; -}; - -static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct wm8350 *wm8350 = codec->control_data; - return wm8350->reg_cache[reg]; -} - -static unsigned int wm8350_codec_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct wm8350 *wm8350 = codec->control_data; - return wm8350_reg_read(wm8350, reg); -} - -static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct wm8350 *wm8350 = codec->control_data; - return wm8350_reg_write(wm8350, reg, value); -} - -/* - * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. - */ -static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec) -{ - struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); - struct wm8350_output *out1 = &wm8350_data->out1; - struct wm8350 *wm8350 = codec->control_data; - int left_complete = 0, right_complete = 0; - u16 reg, val; - - /* left channel */ - reg = wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME); - val = (reg & WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; - - if (out1->ramp == WM8350_RAMP_UP) { - /* ramp step up */ - if (val < out1->left_vol) { - val++; - reg &= ~WM8350_OUT1L_VOL_MASK; - wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, - reg | (val << WM8350_OUT1L_VOL_SHIFT)); - } else - left_complete = 1; - } else if (out1->ramp == WM8350_RAMP_DOWN) { - /* ramp step down */ - if (val > 0) { - val--; - reg &= ~WM8350_OUT1L_VOL_MASK; - wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, - reg | (val << WM8350_OUT1L_VOL_SHIFT)); - } else - left_complete = 1; - } else - return 1; - - /* right channel */ - reg = wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME); - val = (reg & WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; - if (out1->ramp == WM8350_RAMP_UP) { - /* ramp step up */ - if (val < out1->right_vol) { - val++; - reg &= ~WM8350_OUT1R_VOL_MASK; - wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, - reg | (val << WM8350_OUT1R_VOL_SHIFT)); - } else - right_complete = 1; - } else if (out1->ramp == WM8350_RAMP_DOWN) { - /* ramp step down */ - if (val > 0) { - val--; - reg &= ~WM8350_OUT1R_VOL_MASK; - wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, - reg | (val << WM8350_OUT1R_VOL_SHIFT)); - } else - right_complete = 1; - } - - /* only hit the update bit if either volume has changed this step */ - if (!left_complete || !right_complete) - wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME, WM8350_OUT1_VU); - - return left_complete & right_complete; -} - -/* - * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown. - */ -static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec) -{ - struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); - struct wm8350_output *out2 = &wm8350_data->out2; - struct wm8350 *wm8350 = codec->control_data; - int left_complete = 0, right_complete = 0; - u16 reg, val; - - /* left channel */ - reg = wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME); - val = (reg & WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; - if (out2->ramp == WM8350_RAMP_UP) { - /* ramp step up */ - if (val < out2->left_vol) { - val++; - reg &= ~WM8350_OUT2L_VOL_MASK; - wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, - reg | (val << WM8350_OUT1L_VOL_SHIFT)); - } else - left_complete = 1; - } else if (out2->ramp == WM8350_RAMP_DOWN) { - /* ramp step down */ - if (val > 0) { - val--; - reg &= ~WM8350_OUT2L_VOL_MASK; - wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, - reg | (val << WM8350_OUT1L_VOL_SHIFT)); - } else - left_complete = 1; - } else - return 1; - - /* right channel */ - reg = wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME); - val = (reg & WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; - if (out2->ramp == WM8350_RAMP_UP) { - /* ramp step up */ - if (val < out2->right_vol) { - val++; - reg &= ~WM8350_OUT2R_VOL_MASK; - wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, - reg | (val << WM8350_OUT1R_VOL_SHIFT)); - } else - right_complete = 1; - } else if (out2->ramp == WM8350_RAMP_DOWN) { - /* ramp step down */ - if (val > 0) { - val--; - reg &= ~WM8350_OUT2R_VOL_MASK; - wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, - reg | (val << WM8350_OUT1R_VOL_SHIFT)); - } else - right_complete = 1; - } - - /* only hit the update bit if either volume has changed this step */ - if (!left_complete || !right_complete) - wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME, WM8350_OUT2_VU); - - return left_complete & right_complete; -} - -/* - * This work ramps both output PGAs at stream start/stop time to - * minimise pop associated with DAPM power switching. - * It's best to enable Zero Cross when ramping occurs to minimise any - * zipper noises. - */ -static void wm8350_pga_work(struct work_struct *work) -{ - struct snd_soc_dapm_context *dapm = - container_of(work, struct snd_soc_dapm_context, delayed_work.work); - struct snd_soc_codec *codec = dapm->codec; - struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); - struct wm8350_output *out1 = &wm8350_data->out1, - *out2 = &wm8350_data->out2; - int i, out1_complete, out2_complete; - - /* do we need to ramp at all ? */ - if (out1->ramp == WM8350_RAMP_NONE && out2->ramp == WM8350_RAMP_NONE) - return; - - /* PGA volumes have 6 bits of resolution to ramp */ - for (i = 0; i <= 63; i++) { - out1_complete = 1, out2_complete = 1; - if (out1->ramp != WM8350_RAMP_NONE) - out1_complete = wm8350_out1_ramp_step(codec); - if (out2->ramp != WM8350_RAMP_NONE) - out2_complete = wm8350_out2_ramp_step(codec); - - /* ramp finished ? */ - if (out1_complete && out2_complete) - break; - - /* we need to delay longer on the up ramp */ - if (out1->ramp == WM8350_RAMP_UP || - out2->ramp == WM8350_RAMP_UP) { - /* delay is longer over 0dB as increases are larger */ - if (i >= WM8350_OUTn_0dB) - schedule_timeout_interruptible(msecs_to_jiffies - (2)); - else - schedule_timeout_interruptible(msecs_to_jiffies - (1)); - } else - udelay(50); /* doesn't matter if we delay longer */ - } - - out1->ramp = WM8350_RAMP_NONE; - out2->ramp = WM8350_RAMP_NONE; -} - -/* - * WM8350 Controls - */ - -static int pga_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); - struct wm8350_output *out; - - switch (w->shift) { - case 0: - case 1: - out = &wm8350_data->out1; - break; - case 2: - case 3: - out = &wm8350_data->out2; - break; - - default: - BUG(); - return -1; - } - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - out->ramp = WM8350_RAMP_UP; - out->active = 1; - - if (!delayed_work_pending(&codec->dapm.delayed_work)) - schedule_delayed_work(&codec->dapm.delayed_work, - msecs_to_jiffies(1)); - break; - - case SND_SOC_DAPM_PRE_PMD: - out->ramp = WM8350_RAMP_DOWN; - out->active = 0; - - if (!delayed_work_pending(&codec->dapm.delayed_work)) - schedule_delayed_work(&codec->dapm.delayed_work, - msecs_to_jiffies(1)); - break; - } - - return 0; -} - -static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8350_data *wm8350_priv = snd_soc_codec_get_drvdata(codec); - struct wm8350_output *out = NULL; - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int ret; - unsigned int reg = mc->reg; - u16 val; - - /* For OUT1 and OUT2 we shadow the values and only actually write - * them out when active in order to ensure the amplifier comes on - * as quietly as possible. */ - switch (reg) { - case WM8350_LOUT1_VOLUME: - out = &wm8350_priv->out1; - break; - case WM8350_LOUT2_VOLUME: - out = &wm8350_priv->out2; - break; - default: - break; - } - - if (out) { - out->left_vol = ucontrol->value.integer.value[0]; - out->right_vol = ucontrol->value.integer.value[1]; - if (!out->active) - return 1; - } - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret < 0) - return ret; - - /* now hit the volume update bits (always bit 8) */ - val = wm8350_codec_read(codec, reg); - wm8350_codec_write(codec, reg, val | WM8350_OUT1_VU); - return 1; -} - -static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8350_data *wm8350_priv = snd_soc_codec_get_drvdata(codec); - struct wm8350_output *out1 = &wm8350_priv->out1; - struct wm8350_output *out2 = &wm8350_priv->out2; - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - - /* If these are cached registers use the cache */ - switch (reg) { - case WM8350_LOUT1_VOLUME: - ucontrol->value.integer.value[0] = out1->left_vol; - ucontrol->value.integer.value[1] = out1->right_vol; - return 0; - - case WM8350_LOUT2_VOLUME: - ucontrol->value.integer.value[0] = out2->left_vol; - ucontrol->value.integer.value[1] = out2->right_vol; - return 0; - - default: - break; - } - - return snd_soc_get_volsw(kcontrol, ucontrol); -} - -static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; -static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; -static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; -static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; -static const char *wm8350_adcfilter[] = { "None", "High Pass" }; -static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; -static const char *wm8350_lr[] = { "Left", "Right" }; - -static const struct soc_enum wm8350_enum[] = { - SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 4, 4, wm8350_deemp), - SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol), - SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem), - SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes), - SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter), - SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp), - SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol), - SOC_ENUM_SINGLE(WM8350_INPUT_MIXER_VOLUME, 15, 2, wm8350_lr), -}; - -static DECLARE_TLV_DB_SCALE(pre_amp_tlv, -1200, 3525, 0); -static DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 600, 0); -static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1); -static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1); -static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1); - -static const unsigned int capture_sd_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 12, TLV_DB_SCALE_ITEM(-3600, 300, 1), - 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0), -}; - -static const struct snd_kcontrol_new wm8350_snd_controls[] = { - SOC_ENUM("Playback Deemphasis", wm8350_enum[0]), - SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]), - SOC_DOUBLE_R_EXT_TLV("Playback PCM Volume", - WM8350_DAC_DIGITAL_VOLUME_L, - WM8350_DAC_DIGITAL_VOLUME_R, - 0, 255, 0, wm8350_get_volsw_2r, - wm8350_put_volsw_2r_vu, dac_pcm_tlv), - SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), - SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), - SOC_ENUM("Capture PCM Filter", wm8350_enum[4]), - SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]), - SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]), - SOC_DOUBLE_R_EXT_TLV("Capture PCM Volume", - WM8350_ADC_DIGITAL_VOLUME_L, - WM8350_ADC_DIGITAL_VOLUME_R, - 0, 255, 0, wm8350_get_volsw_2r, - wm8350_put_volsw_2r_vu, adc_pcm_tlv), - SOC_DOUBLE_TLV("Capture Sidetone Volume", - WM8350_ADC_DIVIDER, - 8, 4, 15, 1, capture_sd_tlv), - SOC_DOUBLE_R_EXT_TLV("Capture Volume", - WM8350_LEFT_INPUT_VOLUME, - WM8350_RIGHT_INPUT_VOLUME, - 2, 63, 0, wm8350_get_volsw_2r, - wm8350_put_volsw_2r_vu, pre_amp_tlv), - SOC_DOUBLE_R("Capture ZC Switch", - WM8350_LEFT_INPUT_VOLUME, - WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0), - SOC_SINGLE_TLV("Left Input Left Sidetone Volume", - WM8350_OUTPUT_LEFT_MIXER_VOLUME, 1, 7, 0, out_mix_tlv), - SOC_SINGLE_TLV("Left Input Right Sidetone Volume", - WM8350_OUTPUT_LEFT_MIXER_VOLUME, - 5, 7, 0, out_mix_tlv), - SOC_SINGLE_TLV("Left Input Bypass Volume", - WM8350_OUTPUT_LEFT_MIXER_VOLUME, - 9, 7, 0, out_mix_tlv), - SOC_SINGLE_TLV("Right Input Left Sidetone Volume", - WM8350_OUTPUT_RIGHT_MIXER_VOLUME, - 1, 7, 0, out_mix_tlv), - SOC_SINGLE_TLV("Right Input Right Sidetone Volume", - WM8350_OUTPUT_RIGHT_MIXER_VOLUME, - 5, 7, 0, out_mix_tlv), - SOC_SINGLE_TLV("Right Input Bypass Volume", - WM8350_OUTPUT_RIGHT_MIXER_VOLUME, - 13, 7, 0, out_mix_tlv), - SOC_SINGLE("Left Input Mixer +20dB Switch", - WM8350_INPUT_MIXER_VOLUME_L, 0, 1, 0), - SOC_SINGLE("Right Input Mixer +20dB Switch", - WM8350_INPUT_MIXER_VOLUME_R, 0, 1, 0), - SOC_SINGLE_TLV("Out4 Capture Volume", - WM8350_INPUT_MIXER_VOLUME, - 1, 7, 0, out_mix_tlv), - SOC_DOUBLE_R_EXT_TLV("Out1 Playback Volume", - WM8350_LOUT1_VOLUME, - WM8350_ROUT1_VOLUME, - 2, 63, 0, wm8350_get_volsw_2r, - wm8350_put_volsw_2r_vu, out_pga_tlv), - SOC_DOUBLE_R("Out1 Playback ZC Switch", - WM8350_LOUT1_VOLUME, - WM8350_ROUT1_VOLUME, 13, 1, 0), - SOC_DOUBLE_R_EXT_TLV("Out2 Playback Volume", - WM8350_LOUT2_VOLUME, - WM8350_ROUT2_VOLUME, - 2, 63, 0, wm8350_get_volsw_2r, - wm8350_put_volsw_2r_vu, out_pga_tlv), - SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME, - WM8350_ROUT2_VOLUME, 13, 1, 0), - SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0), - SOC_SINGLE_TLV("Out2 Beep Volume", WM8350_BEEP_VOLUME, - 5, 7, 0, out_mix_tlv), - - SOC_DOUBLE_R("Out1 Playback Switch", - WM8350_LOUT1_VOLUME, - WM8350_ROUT1_VOLUME, - 14, 1, 1), - SOC_DOUBLE_R("Out2 Playback Switch", - WM8350_LOUT2_VOLUME, - WM8350_ROUT2_VOLUME, - 14, 1, 1), -}; - -/* - * DAPM Controls - */ - -/* Left Playback Mixer */ -static const struct snd_kcontrol_new wm8350_left_play_mixer_controls[] = { - SOC_DAPM_SINGLE("Playback Switch", - WM8350_LEFT_MIXER_CONTROL, 11, 1, 0), - SOC_DAPM_SINGLE("Left Bypass Switch", - WM8350_LEFT_MIXER_CONTROL, 2, 1, 0), - SOC_DAPM_SINGLE("Right Playback Switch", - WM8350_LEFT_MIXER_CONTROL, 12, 1, 0), - SOC_DAPM_SINGLE("Left Sidetone Switch", - WM8350_LEFT_MIXER_CONTROL, 0, 1, 0), - SOC_DAPM_SINGLE("Right Sidetone Switch", - WM8350_LEFT_MIXER_CONTROL, 1, 1, 0), -}; - -/* Right Playback Mixer */ -static const struct snd_kcontrol_new wm8350_right_play_mixer_controls[] = { - SOC_DAPM_SINGLE("Playback Switch", - WM8350_RIGHT_MIXER_CONTROL, 12, 1, 0), - SOC_DAPM_SINGLE("Right Bypass Switch", - WM8350_RIGHT_MIXER_CONTROL, 3, 1, 0), - SOC_DAPM_SINGLE("Left Playback Switch", - WM8350_RIGHT_MIXER_CONTROL, 11, 1, 0), - SOC_DAPM_SINGLE("Left Sidetone Switch", - WM8350_RIGHT_MIXER_CONTROL, 0, 1, 0), - SOC_DAPM_SINGLE("Right Sidetone Switch", - WM8350_RIGHT_MIXER_CONTROL, 1, 1, 0), -}; - -/* Out4 Mixer */ -static const struct snd_kcontrol_new wm8350_out4_mixer_controls[] = { - SOC_DAPM_SINGLE("Right Playback Switch", - WM8350_OUT4_MIXER_CONTROL, 12, 1, 0), - SOC_DAPM_SINGLE("Left Playback Switch", - WM8350_OUT4_MIXER_CONTROL, 11, 1, 0), - SOC_DAPM_SINGLE("Right Capture Switch", - WM8350_OUT4_MIXER_CONTROL, 9, 1, 0), - SOC_DAPM_SINGLE("Out3 Playback Switch", - WM8350_OUT4_MIXER_CONTROL, 2, 1, 0), - SOC_DAPM_SINGLE("Right Mixer Switch", - WM8350_OUT4_MIXER_CONTROL, 1, 1, 0), - SOC_DAPM_SINGLE("Left Mixer Switch", - WM8350_OUT4_MIXER_CONTROL, 0, 1, 0), -}; - -/* Out3 Mixer */ -static const struct snd_kcontrol_new wm8350_out3_mixer_controls[] = { - SOC_DAPM_SINGLE("Left Playback Switch", - WM8350_OUT3_MIXER_CONTROL, 11, 1, 0), - SOC_DAPM_SINGLE("Left Capture Switch", - WM8350_OUT3_MIXER_CONTROL, 8, 1, 0), - SOC_DAPM_SINGLE("Out4 Playback Switch", - WM8350_OUT3_MIXER_CONTROL, 3, 1, 0), - SOC_DAPM_SINGLE("Left Mixer Switch", - WM8350_OUT3_MIXER_CONTROL, 0, 1, 0), -}; - -/* Left Input Mixer */ -static const struct snd_kcontrol_new wm8350_left_capt_mixer_controls[] = { - SOC_DAPM_SINGLE_TLV("L2 Capture Volume", - WM8350_INPUT_MIXER_VOLUME_L, 1, 7, 0, out_mix_tlv), - SOC_DAPM_SINGLE_TLV("L3 Capture Volume", - WM8350_INPUT_MIXER_VOLUME_L, 9, 7, 0, out_mix_tlv), - SOC_DAPM_SINGLE("PGA Capture Switch", - WM8350_LEFT_INPUT_VOLUME, 14, 1, 1), -}; - -/* Right Input Mixer */ -static const struct snd_kcontrol_new wm8350_right_capt_mixer_controls[] = { - SOC_DAPM_SINGLE_TLV("L2 Capture Volume", - WM8350_INPUT_MIXER_VOLUME_R, 5, 7, 0, out_mix_tlv), - SOC_DAPM_SINGLE_TLV("L3 Capture Volume", - WM8350_INPUT_MIXER_VOLUME_R, 13, 7, 0, out_mix_tlv), - SOC_DAPM_SINGLE("PGA Capture Switch", - WM8350_RIGHT_INPUT_VOLUME, 14, 1, 1), -}; - -/* Left Mic Mixer */ -static const struct snd_kcontrol_new wm8350_left_mic_mixer_controls[] = { - SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 1, 1, 0), - SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 0, 1, 0), - SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 2, 1, 0), -}; - -/* Right Mic Mixer */ -static const struct snd_kcontrol_new wm8350_right_mic_mixer_controls[] = { - SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 9, 1, 0), - SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 8, 1, 0), - SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 10, 1, 0), -}; - -/* Beep Switch */ -static const struct snd_kcontrol_new wm8350_beep_switch_controls = -SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1); - -/* Out4 Capture Mux */ -static const struct snd_kcontrol_new wm8350_out4_capture_controls = -SOC_DAPM_ENUM("Route", wm8350_enum[7]); - -static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = { - - SND_SOC_DAPM_PGA("IN3R PGA", WM8350_POWER_MGMT_2, 11, 0, NULL, 0), - SND_SOC_DAPM_PGA("IN3L PGA", WM8350_POWER_MGMT_2, 10, 0, NULL, 0), - SND_SOC_DAPM_PGA_E("Right Out2 PGA", WM8350_POWER_MGMT_3, 3, 0, NULL, - 0, pga_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("Left Out2 PGA", WM8350_POWER_MGMT_3, 2, 0, NULL, 0, - pga_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("Right Out1 PGA", WM8350_POWER_MGMT_3, 1, 0, NULL, - 0, pga_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("Left Out1 PGA", WM8350_POWER_MGMT_3, 0, 0, NULL, 0, - pga_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_MIXER("Right Capture Mixer", WM8350_POWER_MGMT_2, - 7, 0, &wm8350_right_capt_mixer_controls[0], - ARRAY_SIZE(wm8350_right_capt_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left Capture Mixer", WM8350_POWER_MGMT_2, - 6, 0, &wm8350_left_capt_mixer_controls[0], - ARRAY_SIZE(wm8350_left_capt_mixer_controls)), - - SND_SOC_DAPM_MIXER("Out4 Mixer", WM8350_POWER_MGMT_2, 5, 0, - &wm8350_out4_mixer_controls[0], - ARRAY_SIZE(wm8350_out4_mixer_controls)), - - SND_SOC_DAPM_MIXER("Out3 Mixer", WM8350_POWER_MGMT_2, 4, 0, - &wm8350_out3_mixer_controls[0], - ARRAY_SIZE(wm8350_out3_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right Playback Mixer", WM8350_POWER_MGMT_2, 1, 0, - &wm8350_right_play_mixer_controls[0], - ARRAY_SIZE(wm8350_right_play_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left Playback Mixer", WM8350_POWER_MGMT_2, 0, 0, - &wm8350_left_play_mixer_controls[0], - ARRAY_SIZE(wm8350_left_play_mixer_controls)), - - SND_SOC_DAPM_MIXER("Left Mic Mixer", WM8350_POWER_MGMT_2, 8, 0, - &wm8350_left_mic_mixer_controls[0], - ARRAY_SIZE(wm8350_left_mic_mixer_controls)), - - SND_SOC_DAPM_MIXER("Right Mic Mixer", WM8350_POWER_MGMT_2, 9, 0, - &wm8350_right_mic_mixer_controls[0], - ARRAY_SIZE(wm8350_right_mic_mixer_controls)), - - /* virtual mixer for Beep and Out2R */ - SND_SOC_DAPM_MIXER("Out2 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_SWITCH("Beep", WM8350_POWER_MGMT_3, 7, 0, - &wm8350_beep_switch_controls), - - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", - WM8350_POWER_MGMT_4, 3, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", - WM8350_POWER_MGMT_4, 2, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", - WM8350_POWER_MGMT_4, 5, 0), - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", - WM8350_POWER_MGMT_4, 4, 0), - - SND_SOC_DAPM_MICBIAS("Mic Bias", WM8350_POWER_MGMT_1, 4, 0), - - SND_SOC_DAPM_MUX("Out4 Capture Channel", SND_SOC_NOPM, 0, 0, - &wm8350_out4_capture_controls), - - SND_SOC_DAPM_OUTPUT("OUT1R"), - SND_SOC_DAPM_OUTPUT("OUT1L"), - SND_SOC_DAPM_OUTPUT("OUT2R"), - SND_SOC_DAPM_OUTPUT("OUT2L"), - SND_SOC_DAPM_OUTPUT("OUT3"), - SND_SOC_DAPM_OUTPUT("OUT4"), - - SND_SOC_DAPM_INPUT("IN1RN"), - SND_SOC_DAPM_INPUT("IN1RP"), - SND_SOC_DAPM_INPUT("IN2R"), - SND_SOC_DAPM_INPUT("IN1LP"), - SND_SOC_DAPM_INPUT("IN1LN"), - SND_SOC_DAPM_INPUT("IN2L"), - SND_SOC_DAPM_INPUT("IN3R"), - SND_SOC_DAPM_INPUT("IN3L"), -}; - -static const struct snd_soc_dapm_route wm8350_dapm_routes[] = { - - /* left playback mixer */ - {"Left Playback Mixer", "Playback Switch", "Left DAC"}, - {"Left Playback Mixer", "Left Bypass Switch", "IN3L PGA"}, - {"Left Playback Mixer", "Right Playback Switch", "Right DAC"}, - {"Left Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"}, - {"Left Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"}, - - /* right playback mixer */ - {"Right Playback Mixer", "Playback Switch", "Right DAC"}, - {"Right Playback Mixer", "Right Bypass Switch", "IN3R PGA"}, - {"Right Playback Mixer", "Left Playback Switch", "Left DAC"}, - {"Right Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"}, - {"Right Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"}, - - /* out4 playback mixer */ - {"Out4 Mixer", "Right Playback Switch", "Right DAC"}, - {"Out4 Mixer", "Left Playback Switch", "Left DAC"}, - {"Out4 Mixer", "Right Capture Switch", "Right Capture Mixer"}, - {"Out4 Mixer", "Out3 Playback Switch", "Out3 Mixer"}, - {"Out4 Mixer", "Right Mixer Switch", "Right Playback Mixer"}, - {"Out4 Mixer", "Left Mixer Switch", "Left Playback Mixer"}, - {"OUT4", NULL, "Out4 Mixer"}, - - /* out3 playback mixer */ - {"Out3 Mixer", "Left Playback Switch", "Left DAC"}, - {"Out3 Mixer", "Left Capture Switch", "Left Capture Mixer"}, - {"Out3 Mixer", "Left Mixer Switch", "Left Playback Mixer"}, - {"Out3 Mixer", "Out4 Playback Switch", "Out4 Mixer"}, - {"OUT3", NULL, "Out3 Mixer"}, - - /* out2 */ - {"Right Out2 PGA", NULL, "Right Playback Mixer"}, - {"Left Out2 PGA", NULL, "Left Playback Mixer"}, - {"OUT2L", NULL, "Left Out2 PGA"}, - {"OUT2R", NULL, "Right Out2 PGA"}, - - /* out1 */ - {"Right Out1 PGA", NULL, "Right Playback Mixer"}, - {"Left Out1 PGA", NULL, "Left Playback Mixer"}, - {"OUT1L", NULL, "Left Out1 PGA"}, - {"OUT1R", NULL, "Right Out1 PGA"}, - - /* ADCs */ - {"Left ADC", NULL, "Left Capture Mixer"}, - {"Right ADC", NULL, "Right Capture Mixer"}, - - /* Left capture mixer */ - {"Left Capture Mixer", "L2 Capture Volume", "IN2L"}, - {"Left Capture Mixer", "L3 Capture Volume", "IN3L PGA"}, - {"Left Capture Mixer", "PGA Capture Switch", "Left Mic Mixer"}, - {"Left Capture Mixer", NULL, "Out4 Capture Channel"}, - - /* Right capture mixer */ - {"Right Capture Mixer", "L2 Capture Volume", "IN2R"}, - {"Right Capture Mixer", "L3 Capture Volume", "IN3R PGA"}, - {"Right Capture Mixer", "PGA Capture Switch", "Right Mic Mixer"}, - {"Right Capture Mixer", NULL, "Out4 Capture Channel"}, - - /* L3 Inputs */ - {"IN3L PGA", NULL, "IN3L"}, - {"IN3R PGA", NULL, "IN3R"}, - - /* Left Mic mixer */ - {"Left Mic Mixer", "INN Capture Switch", "IN1LN"}, - {"Left Mic Mixer", "INP Capture Switch", "IN1LP"}, - {"Left Mic Mixer", "IN2 Capture Switch", "IN2L"}, - - /* Right Mic mixer */ - {"Right Mic Mixer", "INN Capture Switch", "IN1RN"}, - {"Right Mic Mixer", "INP Capture Switch", "IN1RP"}, - {"Right Mic Mixer", "IN2 Capture Switch", "IN2R"}, - - /* out 4 capture */ - {"Out4 Capture Channel", NULL, "Out4 Mixer"}, - - /* Beep */ - {"Beep", NULL, "IN3R PGA"}, -}; - -static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8350 *wm8350 = codec->control_data; - u16 fll_4; - - switch (clk_id) { - case WM8350_MCLK_SEL_MCLK: - wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_1, - WM8350_MCLK_SEL); - break; - case WM8350_MCLK_SEL_PLL_MCLK: - case WM8350_MCLK_SEL_PLL_DAC: - case WM8350_MCLK_SEL_PLL_ADC: - case WM8350_MCLK_SEL_PLL_32K: - wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_1, - WM8350_MCLK_SEL); - fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) & - ~WM8350_FLL_CLK_SRC_MASK; - wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, fll_4 | clk_id); - break; - } - - /* MCLK direction */ - if (dir == SND_SOC_CLOCK_OUT) - wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2, - WM8350_MCLK_DIR); - else - wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_2, - WM8350_MCLK_DIR); - - return 0; -} - -static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 val; - - switch (div_id) { - case WM8350_ADC_CLKDIV: - val = wm8350_codec_read(codec, WM8350_ADC_DIVIDER) & - ~WM8350_ADC_CLKDIV_MASK; - wm8350_codec_write(codec, WM8350_ADC_DIVIDER, val | div); - break; - case WM8350_DAC_CLKDIV: - val = wm8350_codec_read(codec, WM8350_DAC_CLOCK_CONTROL) & - ~WM8350_DAC_CLKDIV_MASK; - wm8350_codec_write(codec, WM8350_DAC_CLOCK_CONTROL, val | div); - break; - case WM8350_BCLK_CLKDIV: - val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) & - ~WM8350_BCLK_DIV_MASK; - wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div); - break; - case WM8350_OPCLK_CLKDIV: - val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) & - ~WM8350_OPCLK_DIV_MASK; - wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div); - break; - case WM8350_SYS_CLKDIV: - val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) & - ~WM8350_MCLK_DIV_MASK; - wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div); - break; - case WM8350_DACLR_CLKDIV: - val = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) & - ~WM8350_DACLRC_RATE_MASK; - wm8350_codec_write(codec, WM8350_DAC_LR_RATE, val | div); - break; - case WM8350_ADCLR_CLKDIV: - val = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) & - ~WM8350_ADCLRC_RATE_MASK; - wm8350_codec_write(codec, WM8350_ADC_LR_RATE, val | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & - ~(WM8350_AIF_BCLK_INV | WM8350_AIF_LRCLK_INV | WM8350_AIF_FMT_MASK); - u16 master = wm8350_codec_read(codec, WM8350_AI_DAC_CONTROL) & - ~WM8350_BCLK_MSTR; - u16 dac_lrc = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) & - ~WM8350_DACLRC_ENA; - u16 adc_lrc = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) & - ~WM8350_ADCLRC_ENA; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - master |= WM8350_BCLK_MSTR; - dac_lrc |= WM8350_DACLRC_ENA; - adc_lrc |= WM8350_ADCLRC_ENA; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x2 << 8; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x1 << 8; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x3 << 8; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x3 << 8 | WM8350_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= WM8350_AIF_LRCLK_INV | WM8350_AIF_BCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= WM8350_AIF_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= WM8350_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - - wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); - wm8350_codec_write(codec, WM8350_AI_DAC_CONTROL, master); - wm8350_codec_write(codec, WM8350_DAC_LR_RATE, dac_lrc); - wm8350_codec_write(codec, WM8350_ADC_LR_RATE, adc_lrc); - return 0; -} - -static int wm8350_pcm_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *codec_dai) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int master = wm8350_codec_cache_read(codec, WM8350_AI_DAC_CONTROL) & - WM8350_BCLK_MSTR; - int enabled = 0; - - /* Check that the DACs or ADCs are enabled since they are - * required for LRC in master mode. The DACs or ADCs need a - * valid audio path i.e. pin -> ADC or DAC -> pin before - * the LRC will be enabled in master mode. */ - if (!master || cmd != SNDRV_PCM_TRIGGER_START) - return 0; - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) & - (WM8350_ADCR_ENA | WM8350_ADCL_ENA); - } else { - enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) & - (WM8350_DACR_ENA | WM8350_DACL_ENA); - } - - if (!enabled) { - dev_err(codec->dev, - "%s: invalid audio path - no clocks available\n", - __func__); - return -EINVAL; - } - return 0; -} - -static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *codec_dai) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8350 *wm8350 = codec->control_data; - u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & - ~WM8350_AIF_WL_MASK; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x1 << 10; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x2 << 10; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x3 << 10; - break; - } - - wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); - - /* The sloping stopband filter is recommended for use with - * lower sample rates to improve performance. - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (params_rate(params) < 24000) - wm8350_set_bits(wm8350, WM8350_DAC_MUTE_VOLUME, - WM8350_DAC_SB_FILT); - else - wm8350_clear_bits(wm8350, WM8350_DAC_MUTE_VOLUME, - WM8350_DAC_SB_FILT); - } - - return 0; -} - -static int wm8350_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8350 *wm8350 = codec->control_data; - - if (mute) - wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA); - else - wm8350_clear_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA); - return 0; -} - -/* FLL divisors */ -struct _fll_div { - int div; /* FLL_OUTDIV */ - int n; - int k; - int ratio; /* FLL_FRATIO */ -}; - -/* The size in bits of the fll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static inline int fll_factors(struct _fll_div *fll_div, unsigned int input, - unsigned int output) -{ - u64 Kpart; - unsigned int t1, t2, K, Nmod; - - if (output >= 2815250 && output <= 3125000) - fll_div->div = 0x4; - else if (output >= 5625000 && output <= 6250000) - fll_div->div = 0x3; - else if (output >= 11250000 && output <= 12500000) - fll_div->div = 0x2; - else if (output >= 22500000 && output <= 25000000) - fll_div->div = 0x1; - else { - printk(KERN_ERR "wm8350: fll freq %d out of range\n", output); - return -EINVAL; - } - - if (input > 48000) - fll_div->ratio = 1; - else - fll_div->ratio = 8; - - t1 = output * (1 << (fll_div->div + 1)); - t2 = input * fll_div->ratio; - - fll_div->n = t1 / t2; - Nmod = t1 % t2; - - if (Nmod) { - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - do_div(Kpart, t2); - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - fll_div->k = K; - } else - fll_div->k = 0; - - return 0; -} - -static int wm8350_set_fll(struct snd_soc_dai *codec_dai, - int pll_id, int source, unsigned int freq_in, - unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8350 *wm8350 = codec->control_data; - struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); - struct _fll_div fll_div; - int ret = 0; - u16 fll_1, fll_4; - - if (freq_in == priv->fll_freq_in && freq_out == priv->fll_freq_out) - return 0; - - /* power down FLL - we need to do this for reconfiguration */ - wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, - WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); - - if (freq_out == 0 || freq_in == 0) - return ret; - - ret = fll_factors(&fll_div, freq_in, freq_out); - if (ret < 0) - return ret; - dev_dbg(wm8350->dev, - "FLL in %u FLL out %u N 0x%x K 0x%x div %d ratio %d", - freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div, - fll_div.ratio); - - /* set up N.K & dividers */ - fll_1 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_1) & - ~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000); - wm8350_codec_write(codec, WM8350_FLL_CONTROL_1, - fll_1 | (fll_div.div << 8) | 0x50); - wm8350_codec_write(codec, WM8350_FLL_CONTROL_2, - (fll_div.ratio << 11) | (fll_div. - n & WM8350_FLL_N_MASK)); - wm8350_codec_write(codec, WM8350_FLL_CONTROL_3, fll_div.k); - fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) & - ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF); - wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, - fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) | - (fll_div.ratio == 8 ? WM8350_FLL_SLOW_LOCK_REF : 0)); - - /* power FLL on */ - wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); - wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); - - priv->fll_freq_out = freq_out; - priv->fll_freq_in = freq_in; - - return 0; -} - -static int wm8350_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8350 *wm8350 = codec->control_data; - struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); - struct wm8350_audio_platform_data *platform = - wm8350->codec.platform_data; - u16 pm1; - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & - ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK); - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, - pm1 | WM8350_VMID_50K | - platform->codec_current_on << 14); - break; - - case SND_SOC_BIAS_PREPARE: - pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1); - pm1 &= ~WM8350_VMID_MASK; - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, - pm1 | WM8350_VMID_50K); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), - priv->supplies); - if (ret != 0) - return ret; - - /* Enable the system clock */ - wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, - WM8350_SYSCLK_ENA); - - /* mute DAC & outputs */ - wm8350_set_bits(wm8350, WM8350_DAC_MUTE, - WM8350_DAC_MUTE_ENA); - - /* discharge cap memory */ - wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, - platform->dis_out1 | - (platform->dis_out2 << 2) | - (platform->dis_out3 << 4) | - (platform->dis_out4 << 6)); - - /* wait for discharge */ - schedule_timeout_interruptible(msecs_to_jiffies - (platform-> - cap_discharge_msecs)); - - /* enable antipop */ - wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, - (platform->vmid_s_curve << 8)); - - /* ramp up vmid */ - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, - (platform-> - codec_current_charge << 14) | - WM8350_VMID_5K | WM8350_VMIDEN | - WM8350_VBUFEN); - - /* wait for vmid */ - schedule_timeout_interruptible(msecs_to_jiffies - (platform-> - vmid_charge_msecs)); - - /* turn on vmid 300k */ - pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & - ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK); - pm1 |= WM8350_VMID_300K | - (platform->codec_current_standby << 14); - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, - pm1); - - - /* enable analogue bias */ - pm1 |= WM8350_BIASEN; - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1); - - /* disable antipop */ - wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0); - - } else { - /* turn on vmid 300k and reduce current */ - pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & - ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK); - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, - pm1 | WM8350_VMID_300K | - (platform-> - codec_current_standby << 14)); - - } - break; - - case SND_SOC_BIAS_OFF: - - /* mute DAC & enable outputs */ - wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA); - - wm8350_set_bits(wm8350, WM8350_POWER_MGMT_3, - WM8350_OUT1L_ENA | WM8350_OUT1R_ENA | - WM8350_OUT2L_ENA | WM8350_OUT2R_ENA); - - /* enable anti pop S curve */ - wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, - (platform->vmid_s_curve << 8)); - - /* turn off vmid */ - pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & - ~WM8350_VMIDEN; - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1); - - /* wait */ - schedule_timeout_interruptible(msecs_to_jiffies - (platform-> - vmid_discharge_msecs)); - - wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, - (platform->vmid_s_curve << 8) | - platform->dis_out1 | - (platform->dis_out2 << 2) | - (platform->dis_out3 << 4) | - (platform->dis_out4 << 6)); - - /* turn off VBuf and drain */ - pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & - ~(WM8350_VBUFEN | WM8350_VMID_MASK); - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, - pm1 | WM8350_OUTPUT_DRAIN_EN); - - /* wait */ - schedule_timeout_interruptible(msecs_to_jiffies - (platform->drain_msecs)); - - pm1 &= ~WM8350_BIASEN; - wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1); - - /* disable anti-pop */ - wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0); - - wm8350_clear_bits(wm8350, WM8350_LOUT1_VOLUME, - WM8350_OUT1L_ENA); - wm8350_clear_bits(wm8350, WM8350_ROUT1_VOLUME, - WM8350_OUT1R_ENA); - wm8350_clear_bits(wm8350, WM8350_LOUT2_VOLUME, - WM8350_OUT2L_ENA); - wm8350_clear_bits(wm8350, WM8350_ROUT2_VOLUME, - WM8350_OUT2R_ENA); - - /* disable clock gen */ - wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, - WM8350_SYSCLK_ENA); - - regulator_bulk_disable(ARRAY_SIZE(priv->supplies), - priv->supplies); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static int wm8350_suspend(struct snd_soc_codec *codec) -{ - wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8350_resume(struct snd_soc_codec *codec) -{ - wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static void wm8350_hp_work(struct wm8350_data *priv, - struct wm8350_jack_data *jack, - u16 mask) -{ - struct wm8350 *wm8350 = priv->wm8350; - u16 reg; - int report; - - reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); - if (reg & mask) - report = jack->report; - else - report = 0; - - snd_soc_jack_report(jack->jack, report, jack->report); - -} - -static void wm8350_hpl_work(struct work_struct *work) -{ - struct wm8350_data *priv = - container_of(work, struct wm8350_data, hpl.work.work); - - wm8350_hp_work(priv, &priv->hpl, WM8350_JACK_L_LVL); -} - -static void wm8350_hpr_work(struct work_struct *work) -{ - struct wm8350_data *priv = - container_of(work, struct wm8350_data, hpr.work.work); - - wm8350_hp_work(priv, &priv->hpr, WM8350_JACK_R_LVL); -} - -static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) -{ - struct wm8350_data *priv = data; - struct wm8350 *wm8350 = priv->wm8350; - struct wm8350_jack_data *jack = NULL; - - switch (irq - wm8350->irq_base) { - case WM8350_IRQ_CODEC_JCK_DET_L: -#ifndef CONFIG_SND_SOC_WM8350_MODULE - trace_snd_soc_jack_irq("WM8350 HPL"); -#endif - jack = &priv->hpl; - break; - - case WM8350_IRQ_CODEC_JCK_DET_R: -#ifndef CONFIG_SND_SOC_WM8350_MODULE - trace_snd_soc_jack_irq("WM8350 HPR"); -#endif - jack = &priv->hpr; - break; - - default: - BUG(); - } - - if (device_may_wakeup(wm8350->dev)) - pm_wakeup_event(wm8350->dev, 250); - - schedule_delayed_work(&jack->work, 200); - - return IRQ_HANDLED; -} - -/** - * wm8350_hp_jack_detect - Enable headphone jack detection. - * - * @codec: WM8350 codec - * @which: left or right jack detect signal - * @jack: jack to report detection events on - * @report: value to report - * - * Enables the headphone jack detection of the WM8350. If no report - * is specified then detection is disabled. - */ -int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, - struct snd_soc_jack *jack, int report) -{ - struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); - struct wm8350 *wm8350 = codec->control_data; - int irq; - int ena; - - switch (which) { - case WM8350_JDL: - priv->hpl.jack = jack; - priv->hpl.report = report; - irq = WM8350_IRQ_CODEC_JCK_DET_L; - ena = WM8350_JDL_ENA; - break; - - case WM8350_JDR: - priv->hpr.jack = jack; - priv->hpr.report = report; - irq = WM8350_IRQ_CODEC_JCK_DET_R; - ena = WM8350_JDR_ENA; - break; - - default: - return -EINVAL; - } - - if (report) { - wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); - wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); - } else { - wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, ena); - } - - /* Sync status */ - wm8350_hp_jack_handler(irq + wm8350->irq_base, priv); - - return 0; -} -EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); - -static irqreturn_t wm8350_mic_handler(int irq, void *data) -{ - struct wm8350_data *priv = data; - struct wm8350 *wm8350 = priv->wm8350; - u16 reg; - int report = 0; - -#ifndef CONFIG_SND_SOC_WM8350_MODULE - trace_snd_soc_jack_irq("WM8350 mic"); -#endif - - reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); - if (reg & WM8350_JACK_MICSCD_LVL) - report |= priv->mic.short_report; - if (reg & WM8350_JACK_MICSD_LVL) - report |= priv->mic.report; - - snd_soc_jack_report(priv->mic.jack, report, - priv->mic.report | priv->mic.short_report); - - return IRQ_HANDLED; -} - -/** - * wm8350_mic_jack_detect - Enable microphone jack detection. - * - * @codec: WM8350 codec - * @jack: jack to report detection events on - * @detect_report: value to report when presence detected - * @short_report: value to report when microphone short detected - * - * Enables the microphone jack detection of the WM8350. If both reports - * are specified as zero then detection is disabled. - */ -int wm8350_mic_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack, - int detect_report, int short_report) -{ - struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); - struct wm8350 *wm8350 = codec->control_data; - - priv->mic.jack = jack; - priv->mic.report = detect_report; - priv->mic.short_report = short_report; - - if (detect_report || short_report) { - wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); - wm8350_set_bits(wm8350, WM8350_POWER_MGMT_1, - WM8350_MIC_DET_ENA); - } else { - wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_1, - WM8350_MIC_DET_ENA); - } - - return 0; -} -EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); - -#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) - -#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8350_dai_ops = { - .hw_params = wm8350_pcm_hw_params, - .digital_mute = wm8350_mute, - .trigger = wm8350_pcm_trigger, - .set_fmt = wm8350_set_dai_fmt, - .set_sysclk = wm8350_set_dai_sysclk, - .set_pll = wm8350_set_fll, - .set_clkdiv = wm8350_set_clkdiv, -}; - -static struct snd_soc_dai_driver wm8350_dai = { - .name = "wm8350-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8350_RATES, - .formats = WM8350_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8350_RATES, - .formats = WM8350_FORMATS, - }, - .ops = &wm8350_dai_ops, -}; - -static int wm8350_codec_probe(struct snd_soc_codec *codec) -{ - struct wm8350 *wm8350 = dev_get_platdata(codec->dev); - struct wm8350_data *priv; - struct wm8350_output *out1; - struct wm8350_output *out2; - int ret, i; - - if (wm8350->codec.platform_data == NULL) { - dev_err(codec->dev, "No audio platform data supplied\n"); - return -EINVAL; - } - - priv = devm_kzalloc(codec->dev, sizeof(struct wm8350_data), - GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - snd_soc_codec_set_drvdata(codec, priv); - - priv->wm8350 = wm8350; - - for (i = 0; i < ARRAY_SIZE(supply_names); i++) - priv->supplies[i].supply = supply_names[i]; - - ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), - priv->supplies); - if (ret != 0) - return ret; - - codec->control_data = wm8350; - - /* Put the codec into reset if it wasn't already */ - wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); - - INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8350_pga_work); - INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work); - INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work); - - /* Enable the codec */ - wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); - - /* Enable robust clocking mode in ADC */ - wm8350_codec_write(codec, WM8350_SECURITY, 0xa7); - wm8350_codec_write(codec, 0xde, 0x13); - wm8350_codec_write(codec, WM8350_SECURITY, 0); - - /* read OUT1 & OUT2 volumes */ - out1 = &priv->out1; - out2 = &priv->out2; - out1->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME) & - WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; - out1->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME) & - WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; - out2->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME) & - WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; - out2->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME) & - WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; - wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, 0); - wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, 0); - wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, 0); - wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, 0); - - /* Latch VU bits & mute */ - wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME, - WM8350_OUT1_VU | WM8350_OUT1L_MUTE); - wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME, - WM8350_OUT2_VU | WM8350_OUT2L_MUTE); - wm8350_set_bits(wm8350, WM8350_ROUT1_VOLUME, - WM8350_OUT1_VU | WM8350_OUT1R_MUTE); - wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, - WM8350_OUT2_VU | WM8350_OUT2R_MUTE); - - /* Make sure AIF tristating is disabled by default */ - wm8350_clear_bits(wm8350, WM8350_AI_FORMATING, WM8350_AIF_TRI); - - /* Make sure we've got a sane companding setup too */ - wm8350_clear_bits(wm8350, WM8350_ADC_DAC_COMP, - WM8350_DAC_COMP | WM8350_LOOPBACK); - - /* Make sure jack detect is disabled to start off with */ - wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, - WM8350_JDL_ENA | WM8350_JDR_ENA); - - wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, - wm8350_hp_jack_handler, 0, "Left jack detect", - priv); - wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, - wm8350_hp_jack_handler, 0, "Right jack detect", - priv); - wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, - wm8350_mic_handler, 0, "Microphone short", priv); - wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, - wm8350_mic_handler, 0, "Microphone detect", priv); - - - wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int wm8350_codec_remove(struct snd_soc_codec *codec) -{ - struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); - struct wm8350 *wm8350 = dev_get_platdata(codec->dev); - - wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, - WM8350_JDL_ENA | WM8350_JDR_ENA); - wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); - - wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICD, priv); - wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, priv); - wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv); - wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv); - - priv->hpl.jack = NULL; - priv->hpr.jack = NULL; - priv->mic.jack = NULL; - - cancel_delayed_work_sync(&priv->hpl.work); - cancel_delayed_work_sync(&priv->hpr.work); - - /* if there was any work waiting then we run it now and - * wait for its completion */ - flush_delayed_work_sync(&codec->dapm.delayed_work); - - wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); - - wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); - - regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8350 = { - .probe = wm8350_codec_probe, - .remove = wm8350_codec_remove, - .suspend = wm8350_suspend, - .resume = wm8350_resume, - .read = wm8350_codec_read, - .write = wm8350_codec_write, - .set_bias_level = wm8350_set_bias_level, - - .controls = wm8350_snd_controls, - .num_controls = ARRAY_SIZE(wm8350_snd_controls), - .dapm_widgets = wm8350_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8350_dapm_widgets), - .dapm_routes = wm8350_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes), -}; - -static int __devinit wm8350_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350, - &wm8350_dai, 1); -} - -static int __devexit wm8350_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver wm8350_codec_driver = { - .driver = { - .name = "wm8350-codec", - .owner = THIS_MODULE, - }, - .probe = wm8350_probe, - .remove = __devexit_p(wm8350_remove), -}; - -module_platform_driver(wm8350_codec_driver); - -MODULE_DESCRIPTION("ASoC WM8350 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm8350-codec"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8350.h b/ANDROID_3.4.5/sound/soc/codecs/wm8350.h deleted file mode 100644 index 74108eb8..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8350.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * wm8350.h - WM8903 audio codec interface - * - * Copyright 2008 Wolfson Microelectronics PLC. - * - * 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. - */ - -#ifndef _WM8350_H -#define _WM8350_H - -#include -#include - -enum wm8350_jack { - WM8350_JDL = 1, - WM8350_JDR = 2, -}; - -int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, - struct snd_soc_jack *jack, int report); -int wm8350_mic_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack, - int detect_report, int short_report); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8400.c b/ANDROID_3.4.5/sound/soc/codecs/wm8400.c deleted file mode 100644 index 898979d2..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8400.c +++ /dev/null @@ -1,1469 +0,0 @@ -/* - * wm8400.c -- WM8400 ALSA Soc Audio driver - * - * Copyright 2008, 2009 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8400.h" - -/* Fake register for internal state */ -#define WM8400_INTDRIVBITS (WM8400_REGISTER_COUNT + 1) -#define WM8400_INMIXL_PWR 0 -#define WM8400_AINLMUX_PWR 1 -#define WM8400_INMIXR_PWR 2 -#define WM8400_AINRMUX_PWR 3 - -static struct regulator_bulk_data power[] = { - { - .supply = "I2S1VDD", - }, - { - .supply = "I2S2VDD", - }, - { - .supply = "DCVDD", - }, - { - .supply = "AVDD", - }, - { - .supply = "FLLVDD", - }, - { - .supply = "HPVDD", - }, - { - .supply = "SPKVDD", - }, -}; - -/* codec private data */ -struct wm8400_priv { - struct snd_soc_codec *codec; - struct wm8400 *wm8400; - u16 fake_register; - unsigned int sysclk; - unsigned int pcmclk; - struct work_struct work; - int fll_in, fll_out; -}; - -static inline unsigned int wm8400_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec); - - if (reg == WM8400_INTDRIVBITS) - return wm8400->fake_register; - else - return wm8400_reg_read(wm8400->wm8400, reg); -} - -/* - * write to the wm8400 register space - */ -static int wm8400_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec); - - if (reg == WM8400_INTDRIVBITS) { - wm8400->fake_register = value; - return 0; - } else - return wm8400_set_bits(wm8400->wm8400, reg, 0xffff, value); -} - -static void wm8400_codec_reset(struct snd_soc_codec *codec) -{ - struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec); - - wm8400_reset_codec_reg_cache(wm8400->wm8400); -} - -static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0); - -static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0); - -static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -2100, 0, 0); - -static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0); - -static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0); - -static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0); - -static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0); - -static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0); - -static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int reg = mc->reg; - int ret; - u16 val; - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret < 0) - return ret; - - /* now hit the volume update bits (always bit 8) */ - val = wm8400_read(codec, reg); - return wm8400_write(codec, reg, val | 0x0100); -} - -#define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = wm8400_outpga_put_volsw_vu, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - - -static const char *wm8400_digital_sidetone[] = - {"None", "Left ADC", "Right ADC", "Reserved"}; - -static const struct soc_enum wm8400_left_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, - WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone); - -static const struct soc_enum wm8400_right_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, - WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone); - -static const char *wm8400_adcmode[] = - {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; - -static const struct soc_enum wm8400_right_adcmode_enum = -SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode); - -static const struct snd_kcontrol_new wm8400_snd_controls[] = { -/* INMIXL */ -SOC_SINGLE("LIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L12MNBST_SHIFT, - 1, 0), -SOC_SINGLE("LIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L34MNBST_SHIFT, - 1, 0), -/* INMIXR */ -SOC_SINGLE("RIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R12MNBST_SHIFT, - 1, 0), -SOC_SINGLE("RIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R34MNBST_SHIFT, - 1, 0), - -/* LOMIX */ -SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER3, - WM8400_LLI3LOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3, - WM8400_LR12LOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3, - WM8400_LL12LOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER5, - WM8400_LRI3LOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER5, - WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER5, - WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv), - -/* ROMIX */ -SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER4, - WM8400_RRI3ROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4, - WM8400_RL12ROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4, - WM8400_RR12ROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER6, - WM8400_RLI3ROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER6, - WM8400_RLBROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER6, - WM8400_RRBROVOL_SHIFT, 7, 0, out_mix_tlv), - -/* LOUT */ -WM8400_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8400_LEFT_OUTPUT_VOLUME, - WM8400_LOUTVOL_SHIFT, WM8400_LOUTVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("LOUT ZC", WM8400_LEFT_OUTPUT_VOLUME, WM8400_LOZC_SHIFT, 1, 0), - -/* ROUT */ -WM8400_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8400_RIGHT_OUTPUT_VOLUME, - WM8400_ROUTVOL_SHIFT, WM8400_ROUTVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("ROUT ZC", WM8400_RIGHT_OUTPUT_VOLUME, WM8400_ROZC_SHIFT, 1, 0), - -/* LOPGA */ -WM8400_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8400_LEFT_OPGA_VOLUME, - WM8400_LOPGAVOL_SHIFT, WM8400_LOPGAVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("LOPGA ZC Switch", WM8400_LEFT_OPGA_VOLUME, - WM8400_LOPGAZC_SHIFT, 1, 0), - -/* ROPGA */ -WM8400_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8400_RIGHT_OPGA_VOLUME, - WM8400_ROPGAVOL_SHIFT, WM8400_ROPGAVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("ROPGA ZC Switch", WM8400_RIGHT_OPGA_VOLUME, - WM8400_ROPGAZC_SHIFT, 1, 0), - -SOC_SINGLE("LON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_LONMUTE_SHIFT, 1, 0), -SOC_SINGLE("LOP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_LOPMUTE_SHIFT, 1, 0), -SOC_SINGLE("LOP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_LOATTN_SHIFT, 1, 0), -SOC_SINGLE("RON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_RONMUTE_SHIFT, 1, 0), -SOC_SINGLE("ROP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_ROPMUTE_SHIFT, 1, 0), -SOC_SINGLE("ROP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_ROATTN_SHIFT, 1, 0), - -SOC_SINGLE("OUT3 Mute Switch", WM8400_OUT3_4_VOLUME, - WM8400_OUT3MUTE_SHIFT, 1, 0), -SOC_SINGLE("OUT3 Attenuation Switch", WM8400_OUT3_4_VOLUME, - WM8400_OUT3ATTN_SHIFT, 1, 0), - -SOC_SINGLE("OUT4 Mute Switch", WM8400_OUT3_4_VOLUME, - WM8400_OUT4MUTE_SHIFT, 1, 0), -SOC_SINGLE("OUT4 Attenuation Switch", WM8400_OUT3_4_VOLUME, - WM8400_OUT4ATTN_SHIFT, 1, 0), - -SOC_SINGLE("Speaker Mode Switch", WM8400_CLASSD1, - WM8400_CDMODE_SHIFT, 1, 0), - -SOC_SINGLE("Speaker Output Attenuation Volume", WM8400_SPEAKER_VOLUME, - WM8400_SPKATTN_SHIFT, WM8400_SPKATTN_MASK, 0), -SOC_SINGLE("Speaker DC Boost Volume", WM8400_CLASSD3, - WM8400_DCGAIN_SHIFT, 6, 0), -SOC_SINGLE("Speaker AC Boost Volume", WM8400_CLASSD3, - WM8400_ACGAIN_SHIFT, 6, 0), - -WM8400_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume", - WM8400_LEFT_DAC_DIGITAL_VOLUME, WM8400_DACL_VOL_SHIFT, - 127, 0, out_dac_tlv), - -WM8400_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume", - WM8400_RIGHT_DAC_DIGITAL_VOLUME, WM8400_DACR_VOL_SHIFT, - 127, 0, out_dac_tlv), - -SOC_ENUM("Left Digital Sidetone", wm8400_left_digital_sidetone_enum), -SOC_ENUM("Right Digital Sidetone", wm8400_right_digital_sidetone_enum), - -SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE, - WM8400_ADCL_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv), -SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE, - WM8400_ADCR_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv), - -SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8400_ADC_CTRL, - WM8400_ADC_HPF_ENA_SHIFT, 1, 0), - -SOC_ENUM("ADC HPF Mode", wm8400_right_adcmode_enum), - -WM8400_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume", - WM8400_LEFT_ADC_DIGITAL_VOLUME, - WM8400_ADCL_VOL_SHIFT, - WM8400_ADCL_VOL_MASK, - 0, - in_adc_tlv), - -WM8400_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume", - WM8400_RIGHT_ADC_DIGITAL_VOLUME, - WM8400_ADCR_VOL_SHIFT, - WM8400_ADCR_VOL_MASK, - 0, - in_adc_tlv), - -WM8400_OUTPGA_SINGLE_R_TLV("LIN12 Volume", - WM8400_LEFT_LINE_INPUT_1_2_VOLUME, - WM8400_LIN12VOL_SHIFT, - WM8400_LIN12VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("LIN12 ZC Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME, - WM8400_LI12ZC_SHIFT, 1, 0), - -SOC_SINGLE("LIN12 Mute Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME, - WM8400_LI12MUTE_SHIFT, 1, 0), - -WM8400_OUTPGA_SINGLE_R_TLV("LIN34 Volume", - WM8400_LEFT_LINE_INPUT_3_4_VOLUME, - WM8400_LIN34VOL_SHIFT, - WM8400_LIN34VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("LIN34 ZC Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME, - WM8400_LI34ZC_SHIFT, 1, 0), - -SOC_SINGLE("LIN34 Mute Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME, - WM8400_LI34MUTE_SHIFT, 1, 0), - -WM8400_OUTPGA_SINGLE_R_TLV("RIN12 Volume", - WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8400_RIN12VOL_SHIFT, - WM8400_RIN12VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("RIN12 ZC Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8400_RI12ZC_SHIFT, 1, 0), - -SOC_SINGLE("RIN12 Mute Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8400_RI12MUTE_SHIFT, 1, 0), - -WM8400_OUTPGA_SINGLE_R_TLV("RIN34 Volume", - WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8400_RIN34VOL_SHIFT, - WM8400_RIN34VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("RIN34 ZC Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8400_RI34ZC_SHIFT, 1, 0), - -SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8400_RI34MUTE_SHIFT, 1, 0), - -}; - -/* - * _DAPM_ Controls - */ - -static int inmixer_event (struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - u16 reg, fakepower; - - reg = wm8400_read(w->codec, WM8400_POWER_MANAGEMENT_2); - fakepower = wm8400_read(w->codec, WM8400_INTDRIVBITS); - - if (fakepower & ((1 << WM8400_INMIXL_PWR) | - (1 << WM8400_AINLMUX_PWR))) { - reg |= WM8400_AINL_ENA; - } else { - reg &= ~WM8400_AINL_ENA; - } - - if (fakepower & ((1 << WM8400_INMIXR_PWR) | - (1 << WM8400_AINRMUX_PWR))) { - reg |= WM8400_AINR_ENA; - } else { - reg &= ~WM8400_AINR_ENA; - } - wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg); - - return 0; -} - -static int outmixer_event (struct snd_soc_dapm_widget *w, - struct snd_kcontrol * kcontrol, int event) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - u32 reg_shift = mc->shift; - int ret = 0; - u16 reg; - - switch (reg_shift) { - case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) : - reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER1); - if (reg & WM8400_LDLO) { - printk(KERN_WARNING - "Cannot set as Output Mixer 1 LDLO Set\n"); - ret = -1; - } - break; - case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8): - reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER2); - if (reg & WM8400_RDRO) { - printk(KERN_WARNING - "Cannot set as Output Mixer 2 RDRO Set\n"); - ret = -1; - } - break; - case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8): - reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER); - if (reg & WM8400_LDSPK) { - printk(KERN_WARNING - "Cannot set as Speaker Mixer LDSPK Set\n"); - ret = -1; - } - break; - case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8): - reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER); - if (reg & WM8400_RDSPK) { - printk(KERN_WARNING - "Cannot set as Speaker Mixer RDSPK Set\n"); - ret = -1; - } - break; - } - - return ret; -} - -/* INMIX dB values */ -static const unsigned int in_mix_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0,7, TLV_DB_SCALE_ITEM(-1200, 600, 0), -}; - -/* Left In PGA Connections */ -static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = { -SOC_DAPM_SINGLE("LIN1 Switch", WM8400_INPUT_MIXER2, WM8400_LMN1_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LIN2 Switch", WM8400_INPUT_MIXER2, WM8400_LMP2_SHIFT, 1, 0), -}; - -static const struct snd_kcontrol_new wm8400_dapm_lin34_pga_controls[] = { -SOC_DAPM_SINGLE("LIN3 Switch", WM8400_INPUT_MIXER2, WM8400_LMN3_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LIN4 Switch", WM8400_INPUT_MIXER2, WM8400_LMP4_SHIFT, 1, 0), -}; - -/* Right In PGA Connections */ -static const struct snd_kcontrol_new wm8400_dapm_rin12_pga_controls[] = { -SOC_DAPM_SINGLE("RIN1 Switch", WM8400_INPUT_MIXER2, WM8400_RMN1_SHIFT, 1, 0), -SOC_DAPM_SINGLE("RIN2 Switch", WM8400_INPUT_MIXER2, WM8400_RMP2_SHIFT, 1, 0), -}; - -static const struct snd_kcontrol_new wm8400_dapm_rin34_pga_controls[] = { -SOC_DAPM_SINGLE("RIN3 Switch", WM8400_INPUT_MIXER2, WM8400_RMN3_SHIFT, 1, 0), -SOC_DAPM_SINGLE("RIN4 Switch", WM8400_INPUT_MIXER2, WM8400_RMP4_SHIFT, 1, 0), -}; - -/* INMIXL */ -static const struct snd_kcontrol_new wm8400_dapm_inmixl_controls[] = { -SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8400_INPUT_MIXER3, - WM8400_LDBVOL_SHIFT, WM8400_LDBVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8400_INPUT_MIXER5, WM8400_LI2BVOL_SHIFT, - 7, 0, in_mix_tlv), -SOC_DAPM_SINGLE("LINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT, - 1, 0), -SOC_DAPM_SINGLE("LINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, - 1, 0), -}; - -/* INMIXR */ -static const struct snd_kcontrol_new wm8400_dapm_inmixr_controls[] = { -SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8400_INPUT_MIXER4, - WM8400_RDBVOL_SHIFT, WM8400_RDBVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8400_INPUT_MIXER6, WM8400_RI2BVOL_SHIFT, - 7, 0, in_mix_tlv), -SOC_DAPM_SINGLE("RINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT, - 1, 0), -SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, - 1, 0), -}; - -/* AINLMUX */ -static const char *wm8400_ainlmux[] = - {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; - -static const struct soc_enum wm8400_ainlmux_enum = -SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT, - ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux); - -static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls = -SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); - -/* DIFFINL */ - -/* AINRMUX */ -static const char *wm8400_ainrmux[] = - {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; - -static const struct soc_enum wm8400_ainrmux_enum = -SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT, - ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux); - -static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = -SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); - -/* RXVOICE */ -static const struct snd_kcontrol_new wm8400_dapm_rxvoice_controls[] = { -SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8400_INPUT_MIXER5, WM8400_LR4BVOL_SHIFT, - WM8400_LR4BVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8400_INPUT_MIXER6, WM8400_RL4BVOL_SHIFT, - WM8400_RL4BVOL_MASK, 0, in_mix_tlv), -}; - -/* LOMIX */ -static const struct snd_kcontrol_new wm8400_dapm_lomix_controls[] = { -SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LRBLO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LLBLO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LRI3LO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LLI3LO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LR12LO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LL12LO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8400_OUTPUT_MIXER1, - WM8400_LDLO_SHIFT, 1, 0), -}; - -/* ROMIX */ -static const struct snd_kcontrol_new wm8400_dapm_romix_controls[] = { -SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RLBRO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RRBRO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RLI3RO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RRI3RO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RL12RO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RR12RO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8400_OUTPUT_MIXER2, - WM8400_RDRO_SHIFT, 1, 0), -}; - -/* LONMIX */ -static const struct snd_kcontrol_new wm8400_dapm_lonmix_controls[] = { -SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1, - WM8400_LLOPGALON_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER1, - WM8400_LROPGALON_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8400_LINE_MIXER1, - WM8400_LOPLON_SHIFT, 1, 0), -}; - -/* LOPMIX */ -static const struct snd_kcontrol_new wm8400_dapm_lopmix_controls[] = { -SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER1, - WM8400_LR12LOP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER1, - WM8400_LL12LOP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1, - WM8400_LLOPGALOP_SHIFT, 1, 0), -}; - -/* RONMIX */ -static const struct snd_kcontrol_new wm8400_dapm_ronmix_controls[] = { -SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2, - WM8400_RROPGARON_SHIFT, 1, 0), -SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER2, - WM8400_RLOPGARON_SHIFT, 1, 0), -SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8400_LINE_MIXER2, - WM8400_ROPRON_SHIFT, 1, 0), -}; - -/* ROPMIX */ -static const struct snd_kcontrol_new wm8400_dapm_ropmix_controls[] = { -SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER2, - WM8400_RL12ROP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER2, - WM8400_RR12ROP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2, - WM8400_RROPGAROP_SHIFT, 1, 0), -}; - -/* OUT3MIX */ -static const struct snd_kcontrol_new wm8400_dapm_out3mix_controls[] = { -SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER, - WM8400_LI4O3_SHIFT, 1, 0), -SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8400_OUT3_4_MIXER, - WM8400_LPGAO3_SHIFT, 1, 0), -}; - -/* OUT4MIX */ -static const struct snd_kcontrol_new wm8400_dapm_out4mix_controls[] = { -SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8400_OUT3_4_MIXER, - WM8400_RPGAO4_SHIFT, 1, 0), -SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER, - WM8400_RI4O4_SHIFT, 1, 0), -}; - -/* SPKMIX */ -static const struct snd_kcontrol_new wm8400_dapm_spkmix_controls[] = { -SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8400_SPEAKER_MIXER, - WM8400_LI2SPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8400_SPEAKER_MIXER, - WM8400_LB2SPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8400_SPEAKER_MIXER, - WM8400_LOPGASPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8400_SPEAKER_MIXER, - WM8400_LDSPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8400_SPEAKER_MIXER, - WM8400_RDSPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8400_SPEAKER_MIXER, - WM8400_ROPGASPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8400_SPEAKER_MIXER, - WM8400_RL12ROP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8400_SPEAKER_MIXER, - WM8400_RI2SPK_SHIFT, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8400_dapm_widgets[] = { -/* Input Side */ -/* Input Lines */ -SND_SOC_DAPM_INPUT("LIN1"), -SND_SOC_DAPM_INPUT("LIN2"), -SND_SOC_DAPM_INPUT("LIN3"), -SND_SOC_DAPM_INPUT("LIN4/RXN"), -SND_SOC_DAPM_INPUT("RIN3"), -SND_SOC_DAPM_INPUT("RIN4/RXP"), -SND_SOC_DAPM_INPUT("RIN1"), -SND_SOC_DAPM_INPUT("RIN2"), -SND_SOC_DAPM_INPUT("Internal ADC Source"), - -/* DACs */ -SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8400_POWER_MANAGEMENT_2, - WM8400_ADCL_ENA_SHIFT, 0), -SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8400_POWER_MANAGEMENT_2, - WM8400_ADCR_ENA_SHIFT, 0), - -/* Input PGAs */ -SND_SOC_DAPM_MIXER("LIN12 PGA", WM8400_POWER_MANAGEMENT_2, - WM8400_LIN12_ENA_SHIFT, - 0, &wm8400_dapm_lin12_pga_controls[0], - ARRAY_SIZE(wm8400_dapm_lin12_pga_controls)), -SND_SOC_DAPM_MIXER("LIN34 PGA", WM8400_POWER_MANAGEMENT_2, - WM8400_LIN34_ENA_SHIFT, - 0, &wm8400_dapm_lin34_pga_controls[0], - ARRAY_SIZE(wm8400_dapm_lin34_pga_controls)), -SND_SOC_DAPM_MIXER("RIN12 PGA", WM8400_POWER_MANAGEMENT_2, - WM8400_RIN12_ENA_SHIFT, - 0, &wm8400_dapm_rin12_pga_controls[0], - ARRAY_SIZE(wm8400_dapm_rin12_pga_controls)), -SND_SOC_DAPM_MIXER("RIN34 PGA", WM8400_POWER_MANAGEMENT_2, - WM8400_RIN34_ENA_SHIFT, - 0, &wm8400_dapm_rin34_pga_controls[0], - ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)), - -/* INMIXL */ -SND_SOC_DAPM_MIXER_E("INMIXL", WM8400_INTDRIVBITS, WM8400_INMIXL_PWR, 0, - &wm8400_dapm_inmixl_controls[0], - ARRAY_SIZE(wm8400_dapm_inmixl_controls), - inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* AINLMUX */ -SND_SOC_DAPM_MUX_E("AILNMUX", WM8400_INTDRIVBITS, WM8400_AINLMUX_PWR, 0, - &wm8400_dapm_ainlmux_controls, inmixer_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* INMIXR */ -SND_SOC_DAPM_MIXER_E("INMIXR", WM8400_INTDRIVBITS, WM8400_INMIXR_PWR, 0, - &wm8400_dapm_inmixr_controls[0], - ARRAY_SIZE(wm8400_dapm_inmixr_controls), - inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* AINRMUX */ -SND_SOC_DAPM_MUX_E("AIRNMUX", WM8400_INTDRIVBITS, WM8400_AINRMUX_PWR, 0, - &wm8400_dapm_ainrmux_controls, inmixer_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* Output Side */ -/* DACs */ -SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8400_POWER_MANAGEMENT_3, - WM8400_DACL_ENA_SHIFT, 0), -SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8400_POWER_MANAGEMENT_3, - WM8400_DACR_ENA_SHIFT, 0), - -/* LOMIX */ -SND_SOC_DAPM_MIXER_E("LOMIX", WM8400_POWER_MANAGEMENT_3, - WM8400_LOMIX_ENA_SHIFT, - 0, &wm8400_dapm_lomix_controls[0], - ARRAY_SIZE(wm8400_dapm_lomix_controls), - outmixer_event, SND_SOC_DAPM_PRE_REG), - -/* LONMIX */ -SND_SOC_DAPM_MIXER("LONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LON_ENA_SHIFT, - 0, &wm8400_dapm_lonmix_controls[0], - ARRAY_SIZE(wm8400_dapm_lonmix_controls)), - -/* LOPMIX */ -SND_SOC_DAPM_MIXER("LOPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LOP_ENA_SHIFT, - 0, &wm8400_dapm_lopmix_controls[0], - ARRAY_SIZE(wm8400_dapm_lopmix_controls)), - -/* OUT3MIX */ -SND_SOC_DAPM_MIXER("OUT3MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT3_ENA_SHIFT, - 0, &wm8400_dapm_out3mix_controls[0], - ARRAY_SIZE(wm8400_dapm_out3mix_controls)), - -/* SPKMIX */ -SND_SOC_DAPM_MIXER_E("SPKMIX", WM8400_POWER_MANAGEMENT_1, WM8400_SPK_ENA_SHIFT, - 0, &wm8400_dapm_spkmix_controls[0], - ARRAY_SIZE(wm8400_dapm_spkmix_controls), outmixer_event, - SND_SOC_DAPM_PRE_REG), - -/* OUT4MIX */ -SND_SOC_DAPM_MIXER("OUT4MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT4_ENA_SHIFT, - 0, &wm8400_dapm_out4mix_controls[0], - ARRAY_SIZE(wm8400_dapm_out4mix_controls)), - -/* ROPMIX */ -SND_SOC_DAPM_MIXER("ROPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_ROP_ENA_SHIFT, - 0, &wm8400_dapm_ropmix_controls[0], - ARRAY_SIZE(wm8400_dapm_ropmix_controls)), - -/* RONMIX */ -SND_SOC_DAPM_MIXER("RONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_RON_ENA_SHIFT, - 0, &wm8400_dapm_ronmix_controls[0], - ARRAY_SIZE(wm8400_dapm_ronmix_controls)), - -/* ROMIX */ -SND_SOC_DAPM_MIXER_E("ROMIX", WM8400_POWER_MANAGEMENT_3, - WM8400_ROMIX_ENA_SHIFT, - 0, &wm8400_dapm_romix_controls[0], - ARRAY_SIZE(wm8400_dapm_romix_controls), - outmixer_event, SND_SOC_DAPM_PRE_REG), - -/* LOUT PGA */ -SND_SOC_DAPM_PGA("LOUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_LOUT_ENA_SHIFT, - 0, NULL, 0), - -/* ROUT PGA */ -SND_SOC_DAPM_PGA("ROUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_ROUT_ENA_SHIFT, - 0, NULL, 0), - -/* LOPGA */ -SND_SOC_DAPM_PGA("LOPGA", WM8400_POWER_MANAGEMENT_3, WM8400_LOPGA_ENA_SHIFT, 0, - NULL, 0), - -/* ROPGA */ -SND_SOC_DAPM_PGA("ROPGA", WM8400_POWER_MANAGEMENT_3, WM8400_ROPGA_ENA_SHIFT, 0, - NULL, 0), - -/* MICBIAS */ -SND_SOC_DAPM_SUPPLY("MICBIAS", WM8400_POWER_MANAGEMENT_1, - WM8400_MIC1BIAS_ENA_SHIFT, 0, NULL, 0), - -SND_SOC_DAPM_OUTPUT("LON"), -SND_SOC_DAPM_OUTPUT("LOP"), -SND_SOC_DAPM_OUTPUT("OUT3"), -SND_SOC_DAPM_OUTPUT("LOUT"), -SND_SOC_DAPM_OUTPUT("SPKN"), -SND_SOC_DAPM_OUTPUT("SPKP"), -SND_SOC_DAPM_OUTPUT("ROUT"), -SND_SOC_DAPM_OUTPUT("OUT4"), -SND_SOC_DAPM_OUTPUT("ROP"), -SND_SOC_DAPM_OUTPUT("RON"), - -SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), -}; - -static const struct snd_soc_dapm_route wm8400_dapm_routes[] = { - /* Make DACs turn on when playing even if not mixed into any outputs */ - {"Internal DAC Sink", NULL, "Left DAC"}, - {"Internal DAC Sink", NULL, "Right DAC"}, - - /* Make ADCs turn on when recording - * even if not mixed from any inputs */ - {"Left ADC", NULL, "Internal ADC Source"}, - {"Right ADC", NULL, "Internal ADC Source"}, - - /* Input Side */ - /* LIN12 PGA */ - {"LIN12 PGA", "LIN1 Switch", "LIN1"}, - {"LIN12 PGA", "LIN2 Switch", "LIN2"}, - /* LIN34 PGA */ - {"LIN34 PGA", "LIN3 Switch", "LIN3"}, - {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"}, - /* INMIXL */ - {"INMIXL", "Record Left Volume", "LOMIX"}, - {"INMIXL", "LIN2 Volume", "LIN2"}, - {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, - {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, - /* AILNMUX */ - {"AILNMUX", "INMIXL Mix", "INMIXL"}, - {"AILNMUX", "DIFFINL Mix", "LIN12 PGA"}, - {"AILNMUX", "DIFFINL Mix", "LIN34 PGA"}, - {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"}, - {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"}, - /* ADC */ - {"Left ADC", NULL, "AILNMUX"}, - - /* RIN12 PGA */ - {"RIN12 PGA", "RIN1 Switch", "RIN1"}, - {"RIN12 PGA", "RIN2 Switch", "RIN2"}, - /* RIN34 PGA */ - {"RIN34 PGA", "RIN3 Switch", "RIN3"}, - {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"}, - /* INMIXL */ - {"INMIXR", "Record Right Volume", "ROMIX"}, - {"INMIXR", "RIN2 Volume", "RIN2"}, - {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, - {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, - /* AIRNMUX */ - {"AIRNMUX", "INMIXR Mix", "INMIXR"}, - {"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"}, - {"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"}, - {"AIRNMUX", "RXVOICE Mix", "LIN4/RXN"}, - {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"}, - /* ADC */ - {"Right ADC", NULL, "AIRNMUX"}, - - /* LOMIX */ - {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, - {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"}, - {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, - {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, - {"LOMIX", "LOMIX Right ADC Bypass Switch", "AIRNMUX"}, - {"LOMIX", "LOMIX Left ADC Bypass Switch", "AILNMUX"}, - {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"}, - - /* ROMIX */ - {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"}, - {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"}, - {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, - {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, - {"ROMIX", "ROMIX Right ADC Bypass Switch", "AIRNMUX"}, - {"ROMIX", "ROMIX Left ADC Bypass Switch", "AILNMUX"}, - {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"}, - - /* SPKMIX */ - {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"}, - {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"}, - {"SPKMIX", "SPKMIX LADC Bypass Switch", "AILNMUX"}, - {"SPKMIX", "SPKMIX RADC Bypass Switch", "AIRNMUX"}, - {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"}, - {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"}, - {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"}, - {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"}, - - /* LONMIX */ - {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"}, - {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"}, - {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"}, - - /* LOPMIX */ - {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"}, - {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"}, - {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, - - /* OUT3MIX */ - {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"}, - {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, - - /* OUT4MIX */ - {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"}, - {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"}, - - /* RONMIX */ - {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"}, - {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"}, - {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"}, - - /* ROPMIX */ - {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"}, - {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"}, - {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"}, - - /* Out Mixer PGAs */ - {"LOPGA", NULL, "LOMIX"}, - {"ROPGA", NULL, "ROMIX"}, - - {"LOUT PGA", NULL, "LOMIX"}, - {"ROUT PGA", NULL, "ROMIX"}, - - /* Output Pins */ - {"LON", NULL, "LONMIX"}, - {"LOP", NULL, "LOPMIX"}, - {"OUT3", NULL, "OUT3MIX"}, - {"LOUT", NULL, "LOUT PGA"}, - {"SPKN", NULL, "SPKMIX"}, - {"ROUT", NULL, "ROUT PGA"}, - {"OUT4", NULL, "OUT4MIX"}, - {"ROP", NULL, "ROPMIX"}, - {"RON", NULL, "RONMIX"}, -}; - -/* - * Clock after FLL and dividers - */ -static int wm8400_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec); - - wm8400->sysclk = freq; - return 0; -} - -struct fll_factors { - u16 n; - u16 k; - u16 outdiv; - u16 fratio; - u16 freq_ref; -}; - -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors, - unsigned int Fref, unsigned int Fout) -{ - u64 Kpart; - unsigned int K, Nmod, target; - - factors->outdiv = 2; - while (Fout * factors->outdiv < 90000000 || - Fout * factors->outdiv > 100000000) { - factors->outdiv *= 2; - if (factors->outdiv > 32) { - dev_err(wm8400->wm8400->dev, - "Unsupported FLL output frequency %uHz\n", - Fout); - return -EINVAL; - } - } - target = Fout * factors->outdiv; - factors->outdiv = factors->outdiv >> 2; - - if (Fref < 48000) - factors->freq_ref = 1; - else - factors->freq_ref = 0; - - if (Fref < 1000000) - factors->fratio = 9; - else - factors->fratio = 0; - - /* Ensure we have a fractional part */ - do { - if (Fref < 1000000) - factors->fratio--; - else - factors->fratio++; - - if (factors->fratio < 1 || factors->fratio > 8) { - dev_err(wm8400->wm8400->dev, - "Unable to calculate FRATIO\n"); - return -EINVAL; - } - - factors->n = target / (Fref * factors->fratio); - Nmod = target % (Fref * factors->fratio); - } while (Nmod == 0); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, (Fref * factors->fratio)); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - factors->k = K / 10; - - dev_dbg(wm8400->wm8400->dev, - "FLL: Fref=%u Fout=%u N=%x K=%x, FRATIO=%x OUTDIV=%x\n", - Fref, Fout, - factors->n, factors->k, factors->fratio, factors->outdiv); - - return 0; -} - -static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, - unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec); - struct fll_factors factors; - int ret; - u16 reg; - - if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out) - return 0; - - if (freq_out) { - ret = fll_factors(wm8400, &factors, freq_in, freq_out); - if (ret != 0) - return ret; - } else { - /* Bodge GCC 4.4.0 uninitialised variable warning - it - * doesn't seem capable of working out that we exit if - * freq_out is 0 before any of the uses. */ - memset(&factors, 0, sizeof(factors)); - } - - wm8400->fll_out = freq_out; - wm8400->fll_in = freq_in; - - /* We *must* disable the FLL before any changes */ - reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_2); - reg &= ~WM8400_FLL_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_2, reg); - - reg = wm8400_read(codec, WM8400_FLL_CONTROL_1); - reg &= ~WM8400_FLL_OSC_ENA; - wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); - - if (!freq_out) - return 0; - - reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK); - reg |= WM8400_FLL_FRAC | factors.fratio; - reg |= factors.freq_ref << WM8400_FLL_REF_FREQ_SHIFT; - wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); - - wm8400_write(codec, WM8400_FLL_CONTROL_2, factors.k); - wm8400_write(codec, WM8400_FLL_CONTROL_3, factors.n); - - reg = wm8400_read(codec, WM8400_FLL_CONTROL_4); - reg &= ~WM8400_FLL_OUTDIV_MASK; - reg |= factors.outdiv; - wm8400_write(codec, WM8400_FLL_CONTROL_4, reg); - - return 0; -} - -/* - * Sets ADC and Voice DAC format. - */ -static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 audio1, audio3; - - audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); - audio3 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_3); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - audio3 &= ~WM8400_AIF_MSTR1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - audio3 |= WM8400_AIF_MSTR1; - break; - default: - return -EINVAL; - } - - audio1 &= ~WM8400_AIF_FMT_MASK; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - audio1 |= WM8400_AIF_FMT_I2S; - audio1 &= ~WM8400_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_RIGHT_J: - audio1 |= WM8400_AIF_FMT_RIGHTJ; - audio1 &= ~WM8400_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_LEFT_J: - audio1 |= WM8400_AIF_FMT_LEFTJ; - audio1 &= ~WM8400_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_A: - audio1 |= WM8400_AIF_FMT_DSP; - audio1 &= ~WM8400_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_B: - audio1 |= WM8400_AIF_FMT_DSP | WM8400_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - - wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1); - wm8400_write(codec, WM8400_AUDIO_INTERFACE_3, audio3); - return 0; -} - -static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM8400_MCLK_DIV: - reg = wm8400_read(codec, WM8400_CLOCKING_2) & - ~WM8400_MCLK_DIV_MASK; - wm8400_write(codec, WM8400_CLOCKING_2, reg | div); - break; - case WM8400_DACCLK_DIV: - reg = wm8400_read(codec, WM8400_CLOCKING_2) & - ~WM8400_DAC_CLKDIV_MASK; - wm8400_write(codec, WM8400_CLOCKING_2, reg | div); - break; - case WM8400_ADCCLK_DIV: - reg = wm8400_read(codec, WM8400_CLOCKING_2) & - ~WM8400_ADC_CLKDIV_MASK; - wm8400_write(codec, WM8400_CLOCKING_2, reg | div); - break; - case WM8400_BCLK_DIV: - reg = wm8400_read(codec, WM8400_CLOCKING_1) & - ~WM8400_BCLK_DIV_MASK; - wm8400_write(codec, WM8400_CLOCKING_1, reg | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * Set PCM DAI bit size and sample rate. - */ -static int wm8400_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); - - audio1 &= ~WM8400_AIF_WL_MASK; - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - audio1 |= WM8400_AIF_WL_20BITS; - break; - case SNDRV_PCM_FORMAT_S24_LE: - audio1 |= WM8400_AIF_WL_24BITS; - break; - case SNDRV_PCM_FORMAT_S32_LE: - audio1 |= WM8400_AIF_WL_32BITS; - break; - } - - wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1); - return 0; -} - -static int wm8400_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 val = wm8400_read(codec, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE; - - if (mute) - wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); - else - wm8400_write(codec, WM8400_DAC_CTRL, val); - - return 0; -} - -/* TODO: set bias for best performance at standby */ -static int wm8400_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec); - u16 val; - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID=2*50k */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) & - ~WM8400_VMID_MODE_MASK; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x2); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(power), - &power[0]); - if (ret != 0) { - dev_err(wm8400->wm8400->dev, - "Failed to enable regulators: %d\n", - ret); - return ret; - } - - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, - WM8400_CODEC_ENA | WM8400_SYSCLK_ENA); - - /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | - WM8400_BUFDCOPEN | WM8400_POBCTRL); - - msleep(50); - - /* Enable VREF & VMID at 2x50k */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); - val |= 0x2 | WM8400_VREF_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - /* Enable BUFIOEN */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | - WM8400_BUFDCOPEN | WM8400_POBCTRL | - WM8400_BUFIOEN); - - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_BUFIOEN); - } - - /* VMID=2*300k */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) & - ~WM8400_VMID_MODE_MASK; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x4); - break; - - case SND_SOC_BIAS_OFF: - /* Enable POBCTRL and SOFT_ST */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | - WM8400_POBCTRL | WM8400_BUFIOEN); - - /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | - WM8400_BUFDCOPEN | WM8400_POBCTRL | - WM8400_BUFIOEN); - - /* mute DAC */ - val = wm8400_read(codec, WM8400_DAC_CTRL); - wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); - - /* Enable any disabled outputs */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); - val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | - WM8400_OUT4_ENA | WM8400_LOUT_ENA | - WM8400_ROUT_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - /* Disable VMID */ - val &= ~WM8400_VMID_MODE_MASK; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - msleep(300); - - /* Enable all output discharge bits */ - wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE | - WM8400_DIS_RLINE | WM8400_DIS_OUT3 | - WM8400_DIS_OUT4 | WM8400_DIS_LOUT | - WM8400_DIS_ROUT); - - /* Disable VREF */ - val &= ~WM8400_VREF_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - wm8400_write(codec, WM8400_ANTIPOP2, 0x0); - - ret = regulator_bulk_disable(ARRAY_SIZE(power), - &power[0]); - if (ret != 0) - return ret; - - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#define WM8400_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8400_dai_ops = { - .hw_params = wm8400_hw_params, - .digital_mute = wm8400_mute, - .set_fmt = wm8400_set_dai_fmt, - .set_clkdiv = wm8400_set_dai_clkdiv, - .set_sysclk = wm8400_set_dai_sysclk, - .set_pll = wm8400_set_dai_pll, -}; - -/* - * The WM8400 supports 2 different and mutually exclusive DAI - * configurations. - * - * 1. ADC/DAC on Primary Interface - * 2. ADC on Primary Interface/DAC on secondary - */ -static struct snd_soc_dai_driver wm8400_dai = { -/* ADC/DAC on primary */ - .name = "wm8400-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8400_RATES, - .formats = WM8400_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8400_RATES, - .formats = WM8400_FORMATS, - }, - .ops = &wm8400_dai_ops, -}; - -static int wm8400_suspend(struct snd_soc_codec *codec) -{ - wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8400_resume(struct snd_soc_codec *codec) -{ - wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static void wm8400_probe_deferred(struct work_struct *work) -{ - struct wm8400_priv *priv = container_of(work, struct wm8400_priv, - work); - struct snd_soc_codec *codec = priv->codec; - - /* charge output caps */ - wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); -} - -static int wm8400_codec_probe(struct snd_soc_codec *codec) -{ - struct wm8400 *wm8400 = dev_get_platdata(codec->dev); - struct wm8400_priv *priv; - int ret; - u16 reg; - - priv = devm_kzalloc(codec->dev, sizeof(struct wm8400_priv), - GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - - snd_soc_codec_set_drvdata(codec, priv); - codec->control_data = priv->wm8400 = wm8400; - priv->codec = codec; - - ret = regulator_bulk_get(wm8400->dev, - ARRAY_SIZE(power), &power[0]); - if (ret != 0) { - dev_err(codec->dev, "Failed to get regulators: %d\n", ret); - return ret; - } - - INIT_WORK(&priv->work, wm8400_probe_deferred); - - wm8400_codec_reset(codec); - - reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA); - - /* Latch volume update bits */ - reg = wm8400_read(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME); - wm8400_write(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME, - reg & WM8400_IPVU); - reg = wm8400_read(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME); - wm8400_write(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, - reg & WM8400_IPVU); - - wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); - wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); - - if (!schedule_work(&priv->work)) { - ret = -EINVAL; - goto err_regulator; - } - return 0; - -err_regulator: - regulator_bulk_free(ARRAY_SIZE(power), power); - return ret; -} - -static int wm8400_codec_remove(struct snd_soc_codec *codec) -{ - u16 reg; - - reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, - reg & (~WM8400_CODEC_ENA)); - - regulator_bulk_free(ARRAY_SIZE(power), power); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8400 = { - .probe = wm8400_codec_probe, - .remove = wm8400_codec_remove, - .suspend = wm8400_suspend, - .resume = wm8400_resume, - .read = wm8400_read, - .write = wm8400_write, - .set_bias_level = wm8400_set_bias_level, - - .controls = wm8400_snd_controls, - .num_controls = ARRAY_SIZE(wm8400_snd_controls), - .dapm_widgets = wm8400_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8400_dapm_widgets), - .dapm_routes = wm8400_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes), -}; - -static int __devinit wm8400_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400, - &wm8400_dai, 1); -} - -static int __devexit wm8400_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver wm8400_codec_driver = { - .driver = { - .name = "wm8400-codec", - .owner = THIS_MODULE, - }, - .probe = wm8400_probe, - .remove = __devexit_p(wm8400_remove), -}; - -module_platform_driver(wm8400_codec_driver); - -MODULE_DESCRIPTION("ASoC WM8400 driver"); -MODULE_AUTHOR("Mark Brown"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm8400-codec"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8400.h b/ANDROID_3.4.5/sound/soc/codecs/wm8400.h deleted file mode 100644 index 521adb19..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8400.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * wm8400.h -- audio driver for WM8400 - * - * Copyright 2008 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * 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. - * - */ - -#ifndef _WM8400_CODEC_H -#define _WM8400_CODEC_H - -#define WM8400_MCLK_DIV 0 -#define WM8400_DACCLK_DIV 1 -#define WM8400_ADCCLK_DIV 2 -#define WM8400_BCLK_DIV 3 - -#define WM8400_MCLK_DIV_1 0x400 -#define WM8400_MCLK_DIV_2 0x800 - -#define WM8400_DAC_CLKDIV_1 0x00 -#define WM8400_DAC_CLKDIV_1_5 0x04 -#define WM8400_DAC_CLKDIV_2 0x08 -#define WM8400_DAC_CLKDIV_3 0x0c -#define WM8400_DAC_CLKDIV_4 0x10 -#define WM8400_DAC_CLKDIV_5_5 0x14 -#define WM8400_DAC_CLKDIV_6 0x18 - -#define WM8400_ADC_CLKDIV_1 0x00 -#define WM8400_ADC_CLKDIV_1_5 0x20 -#define WM8400_ADC_CLKDIV_2 0x40 -#define WM8400_ADC_CLKDIV_3 0x60 -#define WM8400_ADC_CLKDIV_4 0x80 -#define WM8400_ADC_CLKDIV_5_5 0xa0 -#define WM8400_ADC_CLKDIV_6 0xc0 - - -#define WM8400_BCLK_DIV_1 (0x0 << 1) -#define WM8400_BCLK_DIV_1_5 (0x1 << 1) -#define WM8400_BCLK_DIV_2 (0x2 << 1) -#define WM8400_BCLK_DIV_3 (0x3 << 1) -#define WM8400_BCLK_DIV_4 (0x4 << 1) -#define WM8400_BCLK_DIV_5_5 (0x5 << 1) -#define WM8400_BCLK_DIV_6 (0x6 << 1) -#define WM8400_BCLK_DIV_8 (0x7 << 1) -#define WM8400_BCLK_DIV_11 (0x8 << 1) -#define WM8400_BCLK_DIV_12 (0x9 << 1) -#define WM8400_BCLK_DIV_16 (0xA << 1) -#define WM8400_BCLK_DIV_22 (0xB << 1) -#define WM8400_BCLK_DIV_24 (0xC << 1) -#define WM8400_BCLK_DIV_32 (0xD << 1) -#define WM8400_BCLK_DIV_44 (0xE << 1) -#define WM8400_BCLK_DIV_48 (0xF << 1) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8510.c b/ANDROID_3.4.5/sound/soc/codecs/wm8510.c deleted file mode 100644 index 9166126b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8510.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * wm8510.c -- WM8510 ALSA Soc Audio driver - * - * Copyright 2006 Wolfson Microelectronics PLC. - * - * Author: Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8510.h" - -/* - * wm8510 register cache - * We can't read the WM8510 register space when we are - * using 2 wire for device control, so we cache them instead. - */ -static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0050, 0x0000, 0x0140, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00ff, - 0x0000, 0x0000, 0x0100, 0x00ff, - 0x0000, 0x0000, 0x012c, 0x002c, - 0x002c, 0x002c, 0x002c, 0x0000, - 0x0032, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0038, 0x000b, 0x0032, 0x0000, - 0x0008, 0x000c, 0x0093, 0x00e9, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0003, 0x0010, 0x0000, 0x0000, - 0x0000, 0x0002, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0039, 0x0000, - 0x0001, -}; - -#define WM8510_POWER1_BIASEN 0x08 -#define WM8510_POWER1_BUFIOEN 0x10 - -#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) - -/* codec private data */ -struct wm8510_priv { - enum snd_soc_control_type control_type; -}; - -static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; -static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; -static const char *wm8510_alc[] = { "ALC", "Limiter" }; - -static const struct soc_enum wm8510_enum[] = { - SOC_ENUM_SINGLE(WM8510_COMP, 1, 4, wm8510_companding), /* adc */ - SOC_ENUM_SINGLE(WM8510_COMP, 3, 4, wm8510_companding), /* dac */ - SOC_ENUM_SINGLE(WM8510_DAC, 4, 4, wm8510_deemp), - SOC_ENUM_SINGLE(WM8510_ALC3, 8, 2, wm8510_alc), -}; - -static const struct snd_kcontrol_new wm8510_snd_controls[] = { - -SOC_SINGLE("Digital Loopback Switch", WM8510_COMP, 0, 1, 0), - -SOC_ENUM("DAC Companding", wm8510_enum[1]), -SOC_ENUM("ADC Companding", wm8510_enum[0]), - -SOC_ENUM("Playback De-emphasis", wm8510_enum[2]), -SOC_SINGLE("DAC Inversion Switch", WM8510_DAC, 0, 1, 0), - -SOC_SINGLE("Master Playback Volume", WM8510_DACVOL, 0, 127, 0), - -SOC_SINGLE("High Pass Filter Switch", WM8510_ADC, 8, 1, 0), -SOC_SINGLE("High Pass Cut Off", WM8510_ADC, 4, 7, 0), -SOC_SINGLE("ADC Inversion Switch", WM8510_COMP, 0, 1, 0), - -SOC_SINGLE("Capture Volume", WM8510_ADCVOL, 0, 127, 0), - -SOC_SINGLE("DAC Playback Limiter Switch", WM8510_DACLIM1, 8, 1, 0), -SOC_SINGLE("DAC Playback Limiter Decay", WM8510_DACLIM1, 4, 15, 0), -SOC_SINGLE("DAC Playback Limiter Attack", WM8510_DACLIM1, 0, 15, 0), - -SOC_SINGLE("DAC Playback Limiter Threshold", WM8510_DACLIM2, 4, 7, 0), -SOC_SINGLE("DAC Playback Limiter Boost", WM8510_DACLIM2, 0, 15, 0), - -SOC_SINGLE("ALC Enable Switch", WM8510_ALC1, 8, 1, 0), -SOC_SINGLE("ALC Capture Max Gain", WM8510_ALC1, 3, 7, 0), -SOC_SINGLE("ALC Capture Min Gain", WM8510_ALC1, 0, 7, 0), - -SOC_SINGLE("ALC Capture ZC Switch", WM8510_ALC2, 8, 1, 0), -SOC_SINGLE("ALC Capture Hold", WM8510_ALC2, 4, 7, 0), -SOC_SINGLE("ALC Capture Target", WM8510_ALC2, 0, 15, 0), - -SOC_ENUM("ALC Capture Mode", wm8510_enum[3]), -SOC_SINGLE("ALC Capture Decay", WM8510_ALC3, 4, 15, 0), -SOC_SINGLE("ALC Capture Attack", WM8510_ALC3, 0, 15, 0), - -SOC_SINGLE("ALC Capture Noise Gate Switch", WM8510_NGATE, 3, 1, 0), -SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8510_NGATE, 0, 7, 0), - -SOC_SINGLE("Capture PGA ZC Switch", WM8510_INPPGA, 7, 1, 0), -SOC_SINGLE("Capture PGA Volume", WM8510_INPPGA, 0, 63, 0), - -SOC_SINGLE("Speaker Playback ZC Switch", WM8510_SPKVOL, 7, 1, 0), -SOC_SINGLE("Speaker Playback Switch", WM8510_SPKVOL, 6, 1, 1), -SOC_SINGLE("Speaker Playback Volume", WM8510_SPKVOL, 0, 63, 0), -SOC_SINGLE("Speaker Boost", WM8510_OUTPUT, 2, 1, 0), - -SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST, 8, 1, 0), -SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1), -}; - -/* Speaker Output Mixer */ -static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0), -SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_SPKMIX, 5, 1, 0), -SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_SPKMIX, 0, 1, 0), -}; - -/* Mono Output Mixer */ -static const struct snd_kcontrol_new wm8510_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_MONOMIX, 1, 1, 0), -SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_MONOMIX, 2, 1, 0), -SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_MONOMIX, 0, 1, 0), -}; - -static const struct snd_kcontrol_new wm8510_boost_controls[] = { -SOC_DAPM_SINGLE("Mic PGA Switch", WM8510_INPPGA, 6, 1, 1), -SOC_DAPM_SINGLE("Aux Volume", WM8510_ADCBOOST, 0, 7, 0), -SOC_DAPM_SINGLE("Mic Volume", WM8510_ADCBOOST, 4, 7, 0), -}; - -static const struct snd_kcontrol_new wm8510_micpga_controls[] = { -SOC_DAPM_SINGLE("MICP Switch", WM8510_INPUT, 0, 1, 0), -SOC_DAPM_SINGLE("MICN Switch", WM8510_INPUT, 1, 1, 0), -SOC_DAPM_SINGLE("AUX Switch", WM8510_INPUT, 2, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8510_dapm_widgets[] = { -SND_SOC_DAPM_MIXER("Speaker Mixer", WM8510_POWER3, 2, 0, - &wm8510_speaker_mixer_controls[0], - ARRAY_SIZE(wm8510_speaker_mixer_controls)), -SND_SOC_DAPM_MIXER("Mono Mixer", WM8510_POWER3, 3, 0, - &wm8510_mono_mixer_controls[0], - ARRAY_SIZE(wm8510_mono_mixer_controls)), -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8510_POWER3, 0, 0), -SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8510_POWER2, 0, 0), -SND_SOC_DAPM_PGA("Aux Input", WM8510_POWER1, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("Mic PGA", WM8510_POWER2, 2, 0, - &wm8510_micpga_controls[0], - ARRAY_SIZE(wm8510_micpga_controls)), -SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0, - &wm8510_boost_controls[0], - ARRAY_SIZE(wm8510_boost_controls)), - -SND_SOC_DAPM_MICBIAS("Mic Bias", WM8510_POWER1, 4, 0), - -SND_SOC_DAPM_INPUT("MICN"), -SND_SOC_DAPM_INPUT("MICP"), -SND_SOC_DAPM_INPUT("AUX"), -SND_SOC_DAPM_OUTPUT("MONOOUT"), -SND_SOC_DAPM_OUTPUT("SPKOUTP"), -SND_SOC_DAPM_OUTPUT("SPKOUTN"), -}; - -static const struct snd_soc_dapm_route wm8510_dapm_routes[] = { - /* Mono output mixer */ - {"Mono Mixer", "PCM Playback Switch", "DAC"}, - {"Mono Mixer", "Aux Playback Switch", "Aux Input"}, - {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"}, - - /* Speaker output mixer */ - {"Speaker Mixer", "PCM Playback Switch", "DAC"}, - {"Speaker Mixer", "Aux Playback Switch", "Aux Input"}, - {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"}, - - /* Outputs */ - {"Mono Out", NULL, "Mono Mixer"}, - {"MONOOUT", NULL, "Mono Out"}, - {"SpkN Out", NULL, "Speaker Mixer"}, - {"SpkP Out", NULL, "Speaker Mixer"}, - {"SPKOUTN", NULL, "SpkN Out"}, - {"SPKOUTP", NULL, "SpkP Out"}, - - /* Microphone PGA */ - {"Mic PGA", "MICN Switch", "MICN"}, - {"Mic PGA", "MICP Switch", "MICP"}, - { "Mic PGA", "AUX Switch", "Aux Input" }, - - /* Boost Mixer */ - {"Boost Mixer", "Mic PGA Switch", "Mic PGA"}, - {"Boost Mixer", "Mic Volume", "MICP"}, - {"Boost Mixer", "Aux Volume", "Aux Input"}, - - {"ADC", NULL, "Boost Mixer"}, -}; - -struct pll_ { - unsigned int pre_div:4; /* prescale - 1 */ - unsigned int n:4; - unsigned int k; -}; - -static struct pll_ pll_div; - -/* The size in bits of the pll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 24) * 10) - -static void pll_factors(unsigned int target, unsigned int source) -{ - unsigned long long Kpart; - unsigned int K, Ndiv, Nmod; - - Ndiv = target / source; - if (Ndiv < 6) { - source >>= 1; - pll_div.pre_div = 1; - Ndiv = target / source; - } else - pll_div.pre_div = 0; - - if ((Ndiv < 6) || (Ndiv > 12)) - printk(KERN_WARNING - "WM8510 N value %u outwith recommended range!d\n", - Ndiv); - - pll_div.n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div.k = K; -} - -static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - if (freq_in == 0 || freq_out == 0) { - /* Clock CODEC directly from MCLK */ - reg = snd_soc_read(codec, WM8510_CLOCK); - snd_soc_write(codec, WM8510_CLOCK, reg & 0x0ff); - - /* Turn off PLL */ - reg = snd_soc_read(codec, WM8510_POWER1); - snd_soc_write(codec, WM8510_POWER1, reg & 0x1df); - return 0; - } - - pll_factors(freq_out*4, freq_in); - - snd_soc_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); - snd_soc_write(codec, WM8510_PLLK1, pll_div.k >> 18); - snd_soc_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff); - reg = snd_soc_read(codec, WM8510_POWER1); - snd_soc_write(codec, WM8510_POWER1, reg | 0x020); - - /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_read(codec, WM8510_CLOCK); - snd_soc_write(codec, WM8510_CLOCK, reg | 0x100); - - return 0; -} - -/* - * Configure WM8510 clock dividers. - */ -static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM8510_OPCLKDIV: - reg = snd_soc_read(codec, WM8510_GPIO) & 0x1cf; - snd_soc_write(codec, WM8510_GPIO, reg | div); - break; - case WM8510_MCLKDIV: - reg = snd_soc_read(codec, WM8510_CLOCK) & 0x11f; - snd_soc_write(codec, WM8510_CLOCK, reg | div); - break; - case WM8510_ADCCLK: - reg = snd_soc_read(codec, WM8510_ADC) & 0x1f7; - snd_soc_write(codec, WM8510_ADC, reg | div); - break; - case WM8510_DACCLK: - reg = snd_soc_read(codec, WM8510_DAC) & 0x1f7; - snd_soc_write(codec, WM8510_DAC, reg | div); - break; - case WM8510_BCLKDIV: - reg = snd_soc_read(codec, WM8510_CLOCK) & 0x1e3; - snd_soc_write(codec, WM8510_CLOCK, reg | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - u16 clk = snd_soc_read(codec, WM8510_CLOCK) & 0x1fe; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - clk |= 0x0001; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0010; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0008; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x00018; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0180; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0100; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0080; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8510_IFACE, iface); - snd_soc_write(codec, WM8510_CLOCK, clk); - return 0; -} - -static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; - u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0020; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0040; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x0060; - break; - } - - /* filter coefficient */ - switch (params_rate(params)) { - case 8000: - adn |= 0x5 << 1; - break; - case 11025: - adn |= 0x4 << 1; - break; - case 16000: - adn |= 0x3 << 1; - break; - case 22050: - adn |= 0x2 << 1; - break; - case 32000: - adn |= 0x1 << 1; - break; - case 44100: - case 48000: - break; - } - - snd_soc_write(codec, WM8510_IFACE, iface); - snd_soc_write(codec, WM8510_ADD, adn); - return 0; -} - -static int wm8510_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8510_DAC) & 0xffbf; - - if (mute) - snd_soc_write(codec, WM8510_DAC, mute_reg | 0x40); - else - snd_soc_write(codec, WM8510_DAC, mute_reg); - return 0; -} - -/* liam need to make this lower power with dapm */ -static int wm8510_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - power1 |= 0x1; /* VMID 50k */ - snd_soc_write(codec, WM8510_POWER1, power1); - break; - - case SND_SOC_BIAS_STANDBY: - power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; - - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); - - /* Initial cap charge at VMID 5k */ - snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); - mdelay(100); - } - - power1 |= 0x2; /* VMID 500k */ - snd_soc_write(codec, WM8510_POWER1, power1); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8510_POWER1, 0); - snd_soc_write(codec, WM8510_POWER2, 0); - snd_soc_write(codec, WM8510_POWER3, 0); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#define WM8510_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) - -#define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8510_dai_ops = { - .hw_params = wm8510_pcm_hw_params, - .digital_mute = wm8510_mute, - .set_fmt = wm8510_set_dai_fmt, - .set_clkdiv = wm8510_set_dai_clkdiv, - .set_pll = wm8510_set_dai_pll, -}; - -static struct snd_soc_dai_driver wm8510_dai = { - .name = "wm8510-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8510_RATES, - .formats = WM8510_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM8510_RATES, - .formats = WM8510_FORMATS,}, - .ops = &wm8510_dai_ops, - .symmetric_rates = 1, -}; - -static int wm8510_suspend(struct snd_soc_codec *codec) -{ - wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8510_resume(struct snd_soc_codec *codec) -{ - wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int wm8510_probe(struct snd_soc_codec *codec) -{ - struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); - if (ret < 0) { - printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); - return ret; - } - - wm8510_reset(codec); - - /* power on device */ - wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return ret; -} - -/* power down chip */ -static int wm8510_remove(struct snd_soc_codec *codec) -{ - struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); - - wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); - kfree(wm8510); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { - .probe = wm8510_probe, - .remove = wm8510_remove, - .suspend = wm8510_suspend, - .resume = wm8510_resume, - .set_bias_level = wm8510_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8510_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default =wm8510_reg, - - .controls = wm8510_snd_controls, - .num_controls = ARRAY_SIZE(wm8510_snd_controls), - .dapm_widgets = wm8510_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8510_dapm_widgets), - .dapm_routes = wm8510_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8510_dapm_routes), -}; - -static const struct of_device_id wm8510_of_match[] = { - { .compatible = "wlf,wm8510" }, - { }, -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8510_spi_probe(struct spi_device *spi) -{ - struct wm8510_priv *wm8510; - int ret; - - wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); - if (wm8510 == NULL) - return -ENOMEM; - - wm8510->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8510); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8510, &wm8510_dai, 1); - if (ret < 0) - kfree(wm8510); - return ret; -} - -static int __devexit wm8510_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver wm8510_spi_driver = { - .driver = { - .name = "wm8510", - .owner = THIS_MODULE, - .of_match_table = wm8510_of_match, - }, - .probe = wm8510_spi_probe, - .remove = __devexit_p(wm8510_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8510_priv *wm8510; - int ret; - - wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); - if (wm8510 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8510); - wm8510->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8510, &wm8510_dai, 1); - if (ret < 0) - kfree(wm8510); - return ret; -} - -static __devexit int wm8510_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id wm8510_i2c_id[] = { - { "wm8510", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); - -static struct i2c_driver wm8510_i2c_driver = { - .driver = { - .name = "wm8510", - .owner = THIS_MODULE, - .of_match_table = wm8510_of_match, - }, - .probe = wm8510_i2c_probe, - .remove = __devexit_p(wm8510_i2c_remove), - .id_table = wm8510_i2c_id, -}; -#endif - -static int __init wm8510_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8510_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8510_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8510_modinit); - -static void __exit wm8510_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8510_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8510_spi_driver); -#endif -} -module_exit(wm8510_exit); - -MODULE_DESCRIPTION("ASoC WM8510 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8510.h b/ANDROID_3.4.5/sound/soc/codecs/wm8510.h deleted file mode 100644 index b3e26ed9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8510.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * wm8510.h -- WM8510 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8510_H -#define _WM8510_H - -/* WM8510 register space */ - -#define WM8510_RESET 0x0 -#define WM8510_POWER1 0x1 -#define WM8510_POWER2 0x2 -#define WM8510_POWER3 0x3 -#define WM8510_IFACE 0x4 -#define WM8510_COMP 0x5 -#define WM8510_CLOCK 0x6 -#define WM8510_ADD 0x7 -#define WM8510_GPIO 0x8 -#define WM8510_DAC 0xa -#define WM8510_DACVOL 0xb -#define WM8510_ADC 0xe -#define WM8510_ADCVOL 0xf -#define WM8510_EQ1 0x12 -#define WM8510_EQ2 0x13 -#define WM8510_EQ3 0x14 -#define WM8510_EQ4 0x15 -#define WM8510_EQ5 0x16 -#define WM8510_DACLIM1 0x18 -#define WM8510_DACLIM2 0x19 -#define WM8510_NOTCH1 0x1b -#define WM8510_NOTCH2 0x1c -#define WM8510_NOTCH3 0x1d -#define WM8510_NOTCH4 0x1e -#define WM8510_ALC1 0x20 -#define WM8510_ALC2 0x21 -#define WM8510_ALC3 0x22 -#define WM8510_NGATE 0x23 -#define WM8510_PLLN 0x24 -#define WM8510_PLLK1 0x25 -#define WM8510_PLLK2 0x26 -#define WM8510_PLLK3 0x27 -#define WM8510_ATTEN 0x28 -#define WM8510_INPUT 0x2c -#define WM8510_INPPGA 0x2d -#define WM8510_ADCBOOST 0x2f -#define WM8510_OUTPUT 0x31 -#define WM8510_SPKMIX 0x32 -#define WM8510_SPKVOL 0x36 -#define WM8510_MONOMIX 0x38 - -#define WM8510_CACHEREGNUM 57 - -/* Clock divider Id's */ -#define WM8510_OPCLKDIV 0 -#define WM8510_MCLKDIV 1 -#define WM8510_ADCCLK 2 -#define WM8510_DACCLK 3 -#define WM8510_BCLKDIV 4 - -/* DAC clock dividers */ -#define WM8510_DACCLK_F2 (1 << 3) -#define WM8510_DACCLK_F4 (0 << 3) - -/* ADC clock dividers */ -#define WM8510_ADCCLK_F2 (1 << 3) -#define WM8510_ADCCLK_F4 (0 << 3) - -/* PLL Out dividers */ -#define WM8510_OPCLKDIV_1 (0 << 4) -#define WM8510_OPCLKDIV_2 (1 << 4) -#define WM8510_OPCLKDIV_3 (2 << 4) -#define WM8510_OPCLKDIV_4 (3 << 4) - -/* BCLK clock dividers */ -#define WM8510_BCLKDIV_1 (0 << 2) -#define WM8510_BCLKDIV_2 (1 << 2) -#define WM8510_BCLKDIV_4 (2 << 2) -#define WM8510_BCLKDIV_8 (3 << 2) -#define WM8510_BCLKDIV_16 (4 << 2) -#define WM8510_BCLKDIV_32 (5 << 2) - -/* MCLK clock dividers */ -#define WM8510_MCLKDIV_1 (0 << 5) -#define WM8510_MCLKDIV_1_5 (1 << 5) -#define WM8510_MCLKDIV_2 (2 << 5) -#define WM8510_MCLKDIV_3 (3 << 5) -#define WM8510_MCLKDIV_4 (4 << 5) -#define WM8510_MCLKDIV_6 (5 << 5) -#define WM8510_MCLKDIV_8 (6 << 5) -#define WM8510_MCLKDIV_12 (7 << 5) - -struct wm8510_setup_data { - int spi; - int i2c_bus; - unsigned short i2c_address; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8523.c b/ANDROID_3.4.5/sound/soc/codecs/wm8523.c deleted file mode 100644 index 7fea2c3b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8523.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * wm8523.c -- WM8523 ALSA SoC Audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8523.h" - -#define WM8523_NUM_SUPPLIES 2 -static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { - "AVDD", - "LINEVDD", -}; - -#define WM8523_NUM_RATES 7 - -/* codec private data */ -struct wm8523_priv { - enum snd_soc_control_type control_type; - struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; - unsigned int sysclk; - unsigned int rate_constraint_list[WM8523_NUM_RATES]; - struct snd_pcm_hw_constraint_list rate_constraint; -}; - -static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { - 0x8523, /* R0 - DEVICE_ID */ - 0x0001, /* R1 - REVISION */ - 0x0000, /* R2 - PSCTRL1 */ - 0x1812, /* R3 - AIF_CTRL1 */ - 0x0000, /* R4 - AIF_CTRL2 */ - 0x0001, /* R5 - DAC_CTRL3 */ - 0x0190, /* R6 - DAC_GAINL */ - 0x0190, /* R7 - DAC_GAINR */ - 0x0000, /* R8 - ZERO_DETECT */ -}; - -static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg) -{ - switch (reg) { - case WM8523_DEVICE_ID: - case WM8523_REVISION: - return 1; - default: - return 0; - } -} - -static int wm8523_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8523_DEVICE_ID, 0); -} - -static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); - -static const char *wm8523_zd_count_text[] = { - "1024", - "2048", -}; - -static const struct soc_enum wm8523_zc_count = - SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); - -static const struct snd_kcontrol_new wm8523_controls[] = { -SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, - 0, 448, 0, dac_tlv), -SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0), -SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0), -SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1), -SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0), -SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0), -SOC_ENUM("Zero Detect Count", wm8523_zc_count), -}; - -static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = { -SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_OUTPUT("LINEVOUTL"), -SND_SOC_DAPM_OUTPUT("LINEVOUTR"), -}; - -static const struct snd_soc_dapm_route wm8523_dapm_routes[] = { - { "LINEVOUTL", NULL, "DAC" }, - { "LINEVOUTR", NULL, "DAC" }, -}; - -static struct { - int value; - int ratio; -} lrclk_ratios[WM8523_NUM_RATES] = { - { 1, 128 }, - { 2, 192 }, - { 3, 256 }, - { 4, 384 }, - { 5, 512 }, - { 6, 768 }, - { 7, 1152 }, -}; - -static int wm8523_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - - /* The set of sample rates that can be supported depends on the - * MCLK supplied to the CODEC - enforce this. - */ - if (!wm8523->sysclk) { - dev_err(codec->dev, - "No MCLK configured, call set_sysclk() on init\n"); - return -EINVAL; - } - - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &wm8523->rate_constraint); - - return 0; -} - -static int wm8523_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - int i; - u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); - u16 aifctrl2 = snd_soc_read(codec, WM8523_AIF_CTRL2); - - /* Find a supported LRCLK ratio */ - for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { - if (wm8523->sysclk / params_rate(params) == - lrclk_ratios[i].ratio) - break; - } - - /* Should never happen, should be handled by constraints */ - if (i == ARRAY_SIZE(lrclk_ratios)) { - dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n", - wm8523->sysclk / params_rate(params)); - return -EINVAL; - } - - aifctrl2 &= ~WM8523_SR_MASK; - aifctrl2 |= lrclk_ratios[i].value; - - aifctrl1 &= ~WM8523_WL_MASK; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - aifctrl1 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S24_LE: - aifctrl1 |= 0x10; - break; - case SNDRV_PCM_FORMAT_S32_LE: - aifctrl1 |= 0x18; - break; - } - - snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1); - snd_soc_write(codec, WM8523_AIF_CTRL2, aifctrl2); - - return 0; -} - -static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - unsigned int val; - int i; - - wm8523->sysclk = freq; - - wm8523->rate_constraint.count = 0; - for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { - val = freq / lrclk_ratios[i].ratio; - /* Check that it's a standard rate since core can't - * cope with others and having the odd rates confuses - * constraint matching. - */ - switch (val) { - case 8000: - case 11025: - case 16000: - case 22050: - case 32000: - case 44100: - case 48000: - case 64000: - case 88200: - case 96000: - case 176400: - case 192000: - dev_dbg(codec->dev, "Supported sample rate: %dHz\n", - val); - wm8523->rate_constraint_list[i] = val; - wm8523->rate_constraint.count++; - break; - default: - dev_dbg(codec->dev, "Skipping sample rate: %dHz\n", - val); - } - } - - /* Need at least one supported rate... */ - if (wm8523->rate_constraint.count == 0) - return -EINVAL; - - return 0; -} - - -static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); - - aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK | - WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - aifctrl1 |= WM8523_AIF_MSTR; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - aifctrl1 |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aifctrl1 |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - aifctrl1 |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - aifctrl1 |= 0x0023; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aifctrl1 |= WM8523_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aifctrl1 |= WM8523_LRCLK_INV; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1); - - return 0; -} - -static int wm8523_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = codec->reg_cache; - int ret, i; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* Full power on */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 3); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - - /* Initial power up */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 1); - - /* Sync back default/cached values */ - for (i = WM8523_AIF_CTRL1; - i < WM8523_MAX_REGISTER; i++) - snd_soc_write(codec, i, reg_cache[i]); - - - msleep(100); - } - - /* Power up to mute */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 2); - - break; - - case SND_SOC_BIAS_OFF: - /* The chip runs through the power down sequence for us. */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 0); - msleep(100); - - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8523_RATES SNDRV_PCM_RATE_8000_192000 - -#define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8523_dai_ops = { - .startup = wm8523_startup, - .hw_params = wm8523_hw_params, - .set_sysclk = wm8523_set_dai_sysclk, - .set_fmt = wm8523_set_dai_fmt, -}; - -static struct snd_soc_dai_driver wm8523_dai = { - .name = "wm8523-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, /* Mono modes not yet supported */ - .channels_max = 2, - .rates = WM8523_RATES, - .formats = WM8523_FORMATS, - }, - .ops = &wm8523_dai_ops, -}; - -#ifdef CONFIG_PM -static int wm8523_suspend(struct snd_soc_codec *codec) -{ - wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8523_resume(struct snd_soc_codec *codec) -{ - wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define wm8523_suspend NULL -#define wm8523_resume NULL -#endif - -static int wm8523_probe(struct snd_soc_codec *codec) -{ - struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - int ret, i; - - wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; - wm8523->rate_constraint.count = - ARRAY_SIZE(wm8523->rate_constraint_list); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) - wm8523->supplies[i].supply = wm8523_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = snd_soc_read(codec, WM8523_DEVICE_ID); - if (ret < 0) { - dev_err(codec->dev, "Failed to read ID register\n"); - goto err_enable; - } - if (ret != wm8523_reg[WM8523_DEVICE_ID]) { - dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); - ret = -EINVAL; - goto err_enable; - } - - ret = snd_soc_read(codec, WM8523_REVISION); - if (ret < 0) { - dev_err(codec->dev, "Failed to read revision register\n"); - goto err_enable; - } - dev_info(codec->dev, "revision %c\n", - (ret & WM8523_CHIP_REV_MASK) + 'A'); - - ret = wm8523_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - - /* Change some default settings - latch VU and enable ZC */ - snd_soc_update_bits(codec, WM8523_DAC_GAINR, - WM8523_DACR_VU, WM8523_DACR_VU); - snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC); - - wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - - return 0; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - - return ret; -} - -static int wm8523_remove(struct snd_soc_codec *codec) -{ - struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); - - wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { - .probe = wm8523_probe, - .remove = wm8523_remove, - .suspend = wm8523_suspend, - .resume = wm8523_resume, - .set_bias_level = wm8523_set_bias_level, - .reg_cache_size = WM8523_REGISTER_COUNT, - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8523_reg, - .volatile_register = wm8523_volatile_register, - - .controls = wm8523_controls, - .num_controls = ARRAY_SIZE(wm8523_controls), - .dapm_widgets = wm8523_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets), - .dapm_routes = wm8523_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes), -}; - -static const struct of_device_id wm8523_of_match[] = { - { .compatible = "wlf,wm8523" }, - { }, -}; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8523_priv *wm8523; - int ret; - - wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); - if (wm8523 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8523); - wm8523->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8523, &wm8523_dai, 1); - if (ret < 0) - kfree(wm8523); - return ret; - -} - -static __devexit int wm8523_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8523_i2c_id[] = { - { "wm8523", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); - -static struct i2c_driver wm8523_i2c_driver = { - .driver = { - .name = "wm8523", - .owner = THIS_MODULE, - .of_match_table = wm8523_of_match, - }, - .probe = wm8523_i2c_probe, - .remove = __devexit_p(wm8523_i2c_remove), - .id_table = wm8523_i2c_id, -}; -#endif - -static int __init wm8523_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8523_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n", - ret); - } -#endif - return 0; -} -module_init(wm8523_modinit); - -static void __exit wm8523_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8523_i2c_driver); -#endif -} -module_exit(wm8523_exit); - -MODULE_DESCRIPTION("ASoC WM8523 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8523.h b/ANDROID_3.4.5/sound/soc/codecs/wm8523.h deleted file mode 100644 index 4d5b1eb8..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8523.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * wm8523.h -- WM8423 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics, plc - * - * Author: Mark Brown - * - * Based on wm8753.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8523_H -#define _WM8523_H - -/* - * Register values. - */ -#define WM8523_DEVICE_ID 0x00 -#define WM8523_REVISION 0x01 -#define WM8523_PSCTRL1 0x02 -#define WM8523_AIF_CTRL1 0x03 -#define WM8523_AIF_CTRL2 0x04 -#define WM8523_DAC_CTRL3 0x05 -#define WM8523_DAC_GAINL 0x06 -#define WM8523_DAC_GAINR 0x07 -#define WM8523_ZERO_DETECT 0x08 - -#define WM8523_REGISTER_COUNT 9 -#define WM8523_MAX_REGISTER 0x08 - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - DEVICE_ID - */ -#define WM8523_CHIP_ID_MASK 0xFFFF /* CHIP_ID - [15:0] */ -#define WM8523_CHIP_ID_SHIFT 0 /* CHIP_ID - [15:0] */ -#define WM8523_CHIP_ID_WIDTH 16 /* CHIP_ID - [15:0] */ - -/* - * R1 (0x01) - REVISION - */ -#define WM8523_CHIP_REV_MASK 0x0007 /* CHIP_REV - [2:0] */ -#define WM8523_CHIP_REV_SHIFT 0 /* CHIP_REV - [2:0] */ -#define WM8523_CHIP_REV_WIDTH 3 /* CHIP_REV - [2:0] */ - -/* - * R2 (0x02) - PSCTRL1 - */ -#define WM8523_SYS_ENA_MASK 0x0003 /* SYS_ENA - [1:0] */ -#define WM8523_SYS_ENA_SHIFT 0 /* SYS_ENA - [1:0] */ -#define WM8523_SYS_ENA_WIDTH 2 /* SYS_ENA - [1:0] */ - -/* - * R3 (0x03) - AIF_CTRL1 - */ -#define WM8523_TDM_MODE_MASK 0x1800 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_MODE_SHIFT 11 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_MODE_WIDTH 2 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_SLOT_MASK 0x0600 /* TDM_SLOT - [10:9] */ -#define WM8523_TDM_SLOT_SHIFT 9 /* TDM_SLOT - [10:9] */ -#define WM8523_TDM_SLOT_WIDTH 2 /* TDM_SLOT - [10:9] */ -#define WM8523_DEEMPH 0x0100 /* DEEMPH */ -#define WM8523_DEEMPH_MASK 0x0100 /* DEEMPH */ -#define WM8523_DEEMPH_SHIFT 8 /* DEEMPH */ -#define WM8523_DEEMPH_WIDTH 1 /* DEEMPH */ -#define WM8523_AIF_MSTR 0x0080 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_MASK 0x0080 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_SHIFT 7 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_WIDTH 1 /* AIF_MSTR */ -#define WM8523_LRCLK_INV 0x0040 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_MASK 0x0040 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_SHIFT 6 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_WIDTH 1 /* LRCLK_INV */ -#define WM8523_BCLK_INV 0x0020 /* BCLK_INV */ -#define WM8523_BCLK_INV_MASK 0x0020 /* BCLK_INV */ -#define WM8523_BCLK_INV_SHIFT 5 /* BCLK_INV */ -#define WM8523_BCLK_INV_WIDTH 1 /* BCLK_INV */ -#define WM8523_WL_MASK 0x0018 /* WL - [4:3] */ -#define WM8523_WL_SHIFT 3 /* WL - [4:3] */ -#define WM8523_WL_WIDTH 2 /* WL - [4:3] */ -#define WM8523_FMT_MASK 0x0007 /* FMT - [2:0] */ -#define WM8523_FMT_SHIFT 0 /* FMT - [2:0] */ -#define WM8523_FMT_WIDTH 3 /* FMT - [2:0] */ - -/* - * R4 (0x04) - AIF_CTRL2 - */ -#define WM8523_DAC_OP_MUX_MASK 0x00C0 /* DAC_OP_MUX - [7:6] */ -#define WM8523_DAC_OP_MUX_SHIFT 6 /* DAC_OP_MUX - [7:6] */ -#define WM8523_DAC_OP_MUX_WIDTH 2 /* DAC_OP_MUX - [7:6] */ -#define WM8523_BCLKDIV_MASK 0x0038 /* BCLKDIV - [5:3] */ -#define WM8523_BCLKDIV_SHIFT 3 /* BCLKDIV - [5:3] */ -#define WM8523_BCLKDIV_WIDTH 3 /* BCLKDIV - [5:3] */ -#define WM8523_SR_MASK 0x0007 /* SR - [2:0] */ -#define WM8523_SR_SHIFT 0 /* SR - [2:0] */ -#define WM8523_SR_WIDTH 3 /* SR - [2:0] */ - -/* - * R5 (0x05) - DAC_CTRL3 - */ -#define WM8523_ZC 0x0010 /* ZC */ -#define WM8523_ZC_MASK 0x0010 /* ZC */ -#define WM8523_ZC_SHIFT 4 /* ZC */ -#define WM8523_ZC_WIDTH 1 /* ZC */ -#define WM8523_DACR 0x0008 /* DACR */ -#define WM8523_DACR_MASK 0x0008 /* DACR */ -#define WM8523_DACR_SHIFT 3 /* DACR */ -#define WM8523_DACR_WIDTH 1 /* DACR */ -#define WM8523_DACL 0x0004 /* DACL */ -#define WM8523_DACL_MASK 0x0004 /* DACL */ -#define WM8523_DACL_SHIFT 2 /* DACL */ -#define WM8523_DACL_WIDTH 1 /* DACL */ -#define WM8523_VOL_UP_RAMP 0x0002 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_MASK 0x0002 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_SHIFT 1 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_WIDTH 1 /* VOL_UP_RAMP */ -#define WM8523_VOL_DOWN_RAMP 0x0001 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_MASK 0x0001 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_SHIFT 0 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_WIDTH 1 /* VOL_DOWN_RAMP */ - -/* - * R6 (0x06) - DAC_GAINL - */ -#define WM8523_DACL_VU 0x0200 /* DACL_VU */ -#define WM8523_DACL_VU_MASK 0x0200 /* DACL_VU */ -#define WM8523_DACL_VU_SHIFT 9 /* DACL_VU */ -#define WM8523_DACL_VU_WIDTH 1 /* DACL_VU */ -#define WM8523_DACL_VOL_MASK 0x01FF /* DACL_VOL - [8:0] */ -#define WM8523_DACL_VOL_SHIFT 0 /* DACL_VOL - [8:0] */ -#define WM8523_DACL_VOL_WIDTH 9 /* DACL_VOL - [8:0] */ - -/* - * R7 (0x07) - DAC_GAINR - */ -#define WM8523_DACR_VU 0x0200 /* DACR_VU */ -#define WM8523_DACR_VU_MASK 0x0200 /* DACR_VU */ -#define WM8523_DACR_VU_SHIFT 9 /* DACR_VU */ -#define WM8523_DACR_VU_WIDTH 1 /* DACR_VU */ -#define WM8523_DACR_VOL_MASK 0x01FF /* DACR_VOL - [8:0] */ -#define WM8523_DACR_VOL_SHIFT 0 /* DACR_VOL - [8:0] */ -#define WM8523_DACR_VOL_WIDTH 9 /* DACR_VOL - [8:0] */ - -/* - * R8 (0x08) - ZERO_DETECT - */ -#define WM8523_ZD_COUNT_MASK 0x0003 /* ZD_COUNT - [1:0] */ -#define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ -#define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8580.c b/ANDROID_3.4.5/sound/soc/codecs/wm8580.c deleted file mode 100644 index 21128516..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8580.c +++ /dev/null @@ -1,966 +0,0 @@ -/* - * wm8580.c -- WM8580 ALSA Soc Audio driver - * - * Copyright 2008, 2009 Wolfson Microelectronics PLC. - * - * 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. - * - * Notes: - * The WM8580 is a multichannel codec with S/PDIF support, featuring six - * DAC channels and two ADC channels. - * - * Currently only the primary audio interface is supported - S/PDIF and - * the secondary audio interfaces are not. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "wm8580.h" - -/* WM8580 register space */ -#define WM8580_PLLA1 0x00 -#define WM8580_PLLA2 0x01 -#define WM8580_PLLA3 0x02 -#define WM8580_PLLA4 0x03 -#define WM8580_PLLB1 0x04 -#define WM8580_PLLB2 0x05 -#define WM8580_PLLB3 0x06 -#define WM8580_PLLB4 0x07 -#define WM8580_CLKSEL 0x08 -#define WM8580_PAIF1 0x09 -#define WM8580_PAIF2 0x0A -#define WM8580_SAIF1 0x0B -#define WM8580_PAIF3 0x0C -#define WM8580_PAIF4 0x0D -#define WM8580_SAIF2 0x0E -#define WM8580_DAC_CONTROL1 0x0F -#define WM8580_DAC_CONTROL2 0x10 -#define WM8580_DAC_CONTROL3 0x11 -#define WM8580_DAC_CONTROL4 0x12 -#define WM8580_DAC_CONTROL5 0x13 -#define WM8580_DIGITAL_ATTENUATION_DACL1 0x14 -#define WM8580_DIGITAL_ATTENUATION_DACR1 0x15 -#define WM8580_DIGITAL_ATTENUATION_DACL2 0x16 -#define WM8580_DIGITAL_ATTENUATION_DACR2 0x17 -#define WM8580_DIGITAL_ATTENUATION_DACL3 0x18 -#define WM8580_DIGITAL_ATTENUATION_DACR3 0x19 -#define WM8580_MASTER_DIGITAL_ATTENUATION 0x1C -#define WM8580_ADC_CONTROL1 0x1D -#define WM8580_SPDTXCHAN0 0x1E -#define WM8580_SPDTXCHAN1 0x1F -#define WM8580_SPDTXCHAN2 0x20 -#define WM8580_SPDTXCHAN3 0x21 -#define WM8580_SPDTXCHAN4 0x22 -#define WM8580_SPDTXCHAN5 0x23 -#define WM8580_SPDMODE 0x24 -#define WM8580_INTMASK 0x25 -#define WM8580_GPO1 0x26 -#define WM8580_GPO2 0x27 -#define WM8580_GPO3 0x28 -#define WM8580_GPO4 0x29 -#define WM8580_GPO5 0x2A -#define WM8580_INTSTAT 0x2B -#define WM8580_SPDRXCHAN1 0x2C -#define WM8580_SPDRXCHAN2 0x2D -#define WM8580_SPDRXCHAN3 0x2E -#define WM8580_SPDRXCHAN4 0x2F -#define WM8580_SPDRXCHAN5 0x30 -#define WM8580_SPDSTAT 0x31 -#define WM8580_PWRDN1 0x32 -#define WM8580_PWRDN2 0x33 -#define WM8580_READBACK 0x34 -#define WM8580_RESET 0x35 - -#define WM8580_MAX_REGISTER 0x35 - -#define WM8580_DACOSR 0x40 - -/* PLLB4 (register 7h) */ -#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60 -#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20 -#define WM8580_PLLB4_MCLKOUTSRC_PLLB 0x40 -#define WM8580_PLLB4_MCLKOUTSRC_OSC 0x60 - -#define WM8580_PLLB4_CLKOUTSRC_MASK 0x180 -#define WM8580_PLLB4_CLKOUTSRC_PLLACLK 0x080 -#define WM8580_PLLB4_CLKOUTSRC_PLLBCLK 0x100 -#define WM8580_PLLB4_CLKOUTSRC_OSCCLK 0x180 - -/* CLKSEL (register 8h) */ -#define WM8580_CLKSEL_DAC_CLKSEL_MASK 0x03 -#define WM8580_CLKSEL_DAC_CLKSEL_PLLA 0x01 -#define WM8580_CLKSEL_DAC_CLKSEL_PLLB 0x02 - -/* AIF control 1 (registers 9h-bh) */ -#define WM8580_AIF_RATE_MASK 0x7 -#define WM8580_AIF_BCLKSEL_MASK 0x18 - -#define WM8580_AIF_MS 0x20 - -#define WM8580_AIF_CLKSRC_MASK 0xc0 -#define WM8580_AIF_CLKSRC_PLLA 0x40 -#define WM8580_AIF_CLKSRC_PLLB 0x40 -#define WM8580_AIF_CLKSRC_MCLK 0xc0 - -/* AIF control 2 (registers ch-eh) */ -#define WM8580_AIF_FMT_MASK 0x03 -#define WM8580_AIF_FMT_RIGHTJ 0x00 -#define WM8580_AIF_FMT_LEFTJ 0x01 -#define WM8580_AIF_FMT_I2S 0x02 -#define WM8580_AIF_FMT_DSP 0x03 - -#define WM8580_AIF_LENGTH_MASK 0x0c -#define WM8580_AIF_LENGTH_16 0x00 -#define WM8580_AIF_LENGTH_20 0x04 -#define WM8580_AIF_LENGTH_24 0x08 -#define WM8580_AIF_LENGTH_32 0x0c - -#define WM8580_AIF_LRP 0x10 -#define WM8580_AIF_BCP 0x20 - -/* Powerdown Register 1 (register 32h) */ -#define WM8580_PWRDN1_PWDN 0x001 -#define WM8580_PWRDN1_ALLDACPD 0x040 - -/* Powerdown Register 2 (register 33h) */ -#define WM8580_PWRDN2_OSSCPD 0x001 -#define WM8580_PWRDN2_PLLAPD 0x002 -#define WM8580_PWRDN2_PLLBPD 0x004 -#define WM8580_PWRDN2_SPDIFPD 0x008 -#define WM8580_PWRDN2_SPDIFTXD 0x010 -#define WM8580_PWRDN2_SPDIFRXD 0x020 - -#define WM8580_DAC_CONTROL5_MUTEALL 0x10 - -/* - * wm8580 register cache - * We can't read the WM8580 register space when we - * are using 2 wire for device control, so we cache them instead. - */ -static const u16 wm8580_reg[] = { - 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ - 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ - 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ - 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ - 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ - 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ - 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R27*/ - 0x01f0, 0x0040, 0x0000, 0x0000, /*R31(0x1F)*/ - 0x0000, 0x0000, 0x0031, 0x000b, /*R35*/ - 0x0039, 0x0000, 0x0010, 0x0032, /*R39*/ - 0x0054, 0x0076, 0x0098, 0x0000, /*R43(0x2B)*/ - 0x0000, 0x0000, 0x0000, 0x0000, /*R47*/ - 0x0000, 0x0000, 0x005e, 0x003e, /*R51(0x33)*/ - 0x0000, 0x0000 /*R53*/ -}; - -struct pll_state { - unsigned int in; - unsigned int out; -}; - -#define WM8580_NUM_SUPPLIES 3 -static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { - "AVDD", - "DVDD", - "PVDD", -}; - -/* codec private data */ -struct wm8580_priv { - enum snd_soc_control_type control_type; - struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; - struct pll_state a; - struct pll_state b; - int sysclk[2]; -}; - -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); - -static int wm8580_out_vu(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - int ret; - - /* Clear the register cache so we write without VU set */ - reg_cache[reg] = 0; - reg_cache[reg2] = 0; - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret < 0) - return ret; - - /* Now write again with the volume update bit set */ - snd_soc_update_bits(codec, reg, 0x100, 0x100); - snd_soc_update_bits(codec, reg2, 0x100, 0x100); - - return 0; -} - -static const struct snd_kcontrol_new wm8580_snd_controls[] = { -SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL1, - WM8580_DIGITAL_ATTENUATION_DACR1, - 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), -SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL2, - WM8580_DIGITAL_ATTENUATION_DACR2, - 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), -SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume", - WM8580_DIGITAL_ATTENUATION_DACL3, - WM8580_DIGITAL_ATTENUATION_DACR3, - 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv), - -SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0), -SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0), -SOC_SINGLE("DAC3 Deemphasis Switch", WM8580_DAC_CONTROL3, 2, 1, 0), - -SOC_DOUBLE("DAC1 Invert Switch", WM8580_DAC_CONTROL4, 0, 1, 1, 0), -SOC_DOUBLE("DAC2 Invert Switch", WM8580_DAC_CONTROL4, 2, 3, 1, 0), -SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4, 4, 5, 1, 0), - -SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0), -SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1), -SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1), -SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1), - -SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 1), -SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { -SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), -SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1), -SND_SOC_DAPM_DAC("DAC3", "Playback", WM8580_PWRDN1, 4, 1), - -SND_SOC_DAPM_OUTPUT("VOUT1L"), -SND_SOC_DAPM_OUTPUT("VOUT1R"), -SND_SOC_DAPM_OUTPUT("VOUT2L"), -SND_SOC_DAPM_OUTPUT("VOUT2R"), -SND_SOC_DAPM_OUTPUT("VOUT3L"), -SND_SOC_DAPM_OUTPUT("VOUT3R"), - -SND_SOC_DAPM_ADC("ADC", "Capture", WM8580_PWRDN1, 1, 1), - -SND_SOC_DAPM_INPUT("AINL"), -SND_SOC_DAPM_INPUT("AINR"), -}; - -static const struct snd_soc_dapm_route wm8580_dapm_routes[] = { - { "VOUT1L", NULL, "DAC1" }, - { "VOUT1R", NULL, "DAC1" }, - - { "VOUT2L", NULL, "DAC2" }, - { "VOUT2R", NULL, "DAC2" }, - - { "VOUT3L", NULL, "DAC3" }, - { "VOUT3R", NULL, "DAC3" }, - - { "ADC", NULL, "AINL" }, - { "ADC", NULL, "AINR" }, -}; - -/* PLL divisors */ -struct _pll_div { - u32 prescale:1; - u32 postscale:1; - u32 freqmode:2; - u32 n:4; - u32 k:24; -}; - -/* The size in bits of the pll divide */ -#define FIXED_PLL_SIZE (1 << 22) - -/* PLL rate to output rate divisions */ -static struct { - unsigned int div; - unsigned int freqmode; - unsigned int postscale; -} post_table[] = { - { 2, 0, 0 }, - { 4, 0, 1 }, - { 4, 1, 0 }, - { 8, 1, 1 }, - { 8, 2, 0 }, - { 16, 2, 1 }, - { 12, 3, 0 }, - { 24, 3, 1 } -}; - -static int pll_factors(struct _pll_div *pll_div, unsigned int target, - unsigned int source) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod; - int i; - - pr_debug("wm8580: PLL %uHz->%uHz\n", source, target); - - /* Scale the output frequency up; the PLL should run in the - * region of 90-100MHz. - */ - for (i = 0; i < ARRAY_SIZE(post_table); i++) { - if (target * post_table[i].div >= 90000000 && - target * post_table[i].div <= 100000000) { - pll_div->freqmode = post_table[i].freqmode; - pll_div->postscale = post_table[i].postscale; - target *= post_table[i].div; - break; - } - } - - if (i == ARRAY_SIZE(post_table)) { - printk(KERN_ERR "wm8580: Unable to scale output frequency " - "%u\n", target); - return -EINVAL; - } - - Ndiv = target / source; - - if (Ndiv < 5) { - source /= 2; - pll_div->prescale = 1; - Ndiv = target / source; - } else - pll_div->prescale = 0; - - if ((Ndiv < 5) || (Ndiv > 13)) { - printk(KERN_ERR - "WM8580 N=%u outside supported range\n", Ndiv); - return -EINVAL; - } - - pll_div->n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - pll_div->k = K; - - pr_debug("PLL %x.%x prescale %d freqmode %d postscale %d\n", - pll_div->n, pll_div->k, pll_div->prescale, pll_div->freqmode, - pll_div->postscale); - - return 0; -} - -static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - int offset; - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); - struct pll_state *state; - struct _pll_div pll_div; - unsigned int reg; - unsigned int pwr_mask; - int ret; - - /* GCC isn't able to work out the ifs below for initialising/using - * pll_div so suppress warnings. - */ - memset(&pll_div, 0, sizeof(pll_div)); - - switch (pll_id) { - case WM8580_PLLA: - state = &wm8580->a; - offset = 0; - pwr_mask = WM8580_PWRDN2_PLLAPD; - break; - case WM8580_PLLB: - state = &wm8580->b; - offset = 4; - pwr_mask = WM8580_PWRDN2_PLLBPD; - break; - default: - return -ENODEV; - } - - if (freq_in && freq_out) { - ret = pll_factors(&pll_div, freq_out, freq_in); - if (ret != 0) - return ret; - } - - state->in = freq_in; - state->out = freq_out; - - /* Always disable the PLL - it is not safe to leave it running - * while reprogramming it. - */ - snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, pwr_mask); - - if (!freq_in || !freq_out) - return 0; - - snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); - snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8580_PLLA3 + offset, - (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); - - reg = snd_soc_read(codec, WM8580_PLLA4 + offset); - reg &= ~0x1b; - reg |= pll_div.prescale | pll_div.postscale << 1 | - pll_div.freqmode << 3; - - snd_soc_write(codec, WM8580_PLLA4 + offset, reg); - - /* All done, turn it on */ - snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, 0); - - return 0; -} - -static const int wm8580_sysclk_ratios[] = { - 128, 192, 256, 384, 512, 768, 1152, -}; - -/* - * Set PCM DAI bit size and sample rate. - */ -static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); - u16 paifa = 0; - u16 paifb = 0; - int i, ratio, osr; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - paifa |= 0x8; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - paifa |= 0x0; - paifb |= WM8580_AIF_LENGTH_20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - paifa |= 0x0; - paifb |= WM8580_AIF_LENGTH_24; - break; - case SNDRV_PCM_FORMAT_S32_LE: - paifa |= 0x0; - paifb |= WM8580_AIF_LENGTH_32; - break; - default: - return -EINVAL; - } - - /* Look up the SYSCLK ratio; accept only exact matches */ - ratio = wm8580->sysclk[dai->driver->id] / params_rate(params); - for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++) - if (ratio == wm8580_sysclk_ratios[i]) - break; - if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) { - dev_err(codec->dev, "Invalid clock ratio %d/%d\n", - wm8580->sysclk[dai->driver->id], params_rate(params)); - return -EINVAL; - } - paifa |= i; - dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n", - wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - switch (ratio) { - case 128: - case 192: - osr = WM8580_DACOSR; - dev_dbg(codec->dev, "Selecting 64x OSR\n"); - break; - default: - osr = 0; - dev_dbg(codec->dev, "Selecting 128x OSR\n"); - break; - } - - snd_soc_update_bits(codec, WM8580_PAIF3, WM8580_DACOSR, osr); - } - - snd_soc_update_bits(codec, WM8580_PAIF1 + dai->driver->id, - WM8580_AIF_RATE_MASK | WM8580_AIF_BCLKSEL_MASK, - paifa); - snd_soc_update_bits(codec, WM8580_PAIF3 + dai->driver->id, - WM8580_AIF_LENGTH_MASK, paifb); - return 0; -} - -static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - unsigned int aifa; - unsigned int aifb; - int can_invert_lrclk; - - aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id); - aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id); - - aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - aifa &= ~WM8580_AIF_MS; - break; - case SND_SOC_DAIFMT_CBM_CFM: - aifa |= WM8580_AIF_MS; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - can_invert_lrclk = 1; - aifb |= WM8580_AIF_FMT_I2S; - break; - case SND_SOC_DAIFMT_RIGHT_J: - can_invert_lrclk = 1; - aifb |= WM8580_AIF_FMT_RIGHTJ; - break; - case SND_SOC_DAIFMT_LEFT_J: - can_invert_lrclk = 1; - aifb |= WM8580_AIF_FMT_LEFTJ; - break; - case SND_SOC_DAIFMT_DSP_A: - can_invert_lrclk = 0; - aifb |= WM8580_AIF_FMT_DSP; - break; - case SND_SOC_DAIFMT_DSP_B: - can_invert_lrclk = 0; - aifb |= WM8580_AIF_FMT_DSP; - aifb |= WM8580_AIF_LRP; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - - case SND_SOC_DAIFMT_IB_IF: - if (!can_invert_lrclk) - return -EINVAL; - aifb |= WM8580_AIF_BCP; - aifb |= WM8580_AIF_LRP; - break; - - case SND_SOC_DAIFMT_IB_NF: - aifb |= WM8580_AIF_BCP; - break; - - case SND_SOC_DAIFMT_NB_IF: - if (!can_invert_lrclk) - return -EINVAL; - aifb |= WM8580_AIF_LRP; - break; - - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa); - snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb); - - return 0; -} - -static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - unsigned int reg; - - switch (div_id) { - case WM8580_MCLK: - reg = snd_soc_read(codec, WM8580_PLLB4); - reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; - - switch (div) { - case WM8580_CLKSRC_MCLK: - /* Input */ - break; - - case WM8580_CLKSRC_PLLA: - reg |= WM8580_PLLB4_MCLKOUTSRC_PLLA; - break; - case WM8580_CLKSRC_PLLB: - reg |= WM8580_PLLB4_MCLKOUTSRC_PLLB; - break; - - case WM8580_CLKSRC_OSC: - reg |= WM8580_PLLB4_MCLKOUTSRC_OSC; - break; - - default: - return -EINVAL; - } - snd_soc_write(codec, WM8580_PLLB4, reg); - break; - - case WM8580_CLKOUTSRC: - reg = snd_soc_read(codec, WM8580_PLLB4); - reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; - - switch (div) { - case WM8580_CLKSRC_NONE: - break; - - case WM8580_CLKSRC_PLLA: - reg |= WM8580_PLLB4_CLKOUTSRC_PLLACLK; - break; - - case WM8580_CLKSRC_PLLB: - reg |= WM8580_PLLB4_CLKOUTSRC_PLLBCLK; - break; - - case WM8580_CLKSRC_OSC: - reg |= WM8580_PLLB4_CLKOUTSRC_OSCCLK; - break; - - default: - return -EINVAL; - } - snd_soc_write(codec, WM8580_PLLB4, reg); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); - int ret, sel, sel_mask, sel_shift; - - switch (dai->driver->id) { - case WM8580_DAI_PAIFRX: - sel_mask = 0x3; - sel_shift = 0; - break; - - case WM8580_DAI_PAIFTX: - sel_mask = 0xc; - sel_shift = 2; - break; - - default: - BUG_ON("Unknown DAI driver ID\n"); - return -EINVAL; - } - - switch (clk_id) { - case WM8580_CLKSRC_ADCMCLK: - if (dai->driver->id != WM8580_DAI_PAIFTX) - return -EINVAL; - sel = 0 << sel_shift; - break; - case WM8580_CLKSRC_PLLA: - sel = 1 << sel_shift; - break; - case WM8580_CLKSRC_PLLB: - sel = 2 << sel_shift; - break; - case WM8580_CLKSRC_MCLK: - sel = 3 << sel_shift; - break; - default: - dev_err(codec->dev, "Unknown clock %d\n", clk_id); - return -EINVAL; - } - - /* We really should validate PLL settings but not yet */ - wm8580->sysclk[dai->driver->id] = freq; - - ret = snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel); - if (ret < 0) - return ret; - - return 0; -} - -static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - unsigned int reg; - - reg = snd_soc_read(codec, WM8580_DAC_CONTROL5); - - if (mute) - reg |= WM8580_DAC_CONTROL5_MUTEALL; - else - reg &= ~WM8580_DAC_CONTROL5_MUTEALL; - - snd_soc_write(codec, WM8580_DAC_CONTROL5, reg); - - return 0; -} - -static int wm8580_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - /* Power up and get individual control of the DACs */ - snd_soc_update_bits(codec, WM8580_PWRDN1, - WM8580_PWRDN1_PWDN | - WM8580_PWRDN1_ALLDACPD, 0); - - /* Make VMID high impedance */ - snd_soc_update_bits(codec, WM8580_ADC_CONTROL1, - 0x100, 0); - } - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8580_PWRDN1, - WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8580_dai_ops_playback = { - .set_sysclk = wm8580_set_sysclk, - .hw_params = wm8580_paif_hw_params, - .set_fmt = wm8580_set_paif_dai_fmt, - .set_clkdiv = wm8580_set_dai_clkdiv, - .set_pll = wm8580_set_dai_pll, - .digital_mute = wm8580_digital_mute, -}; - -static const struct snd_soc_dai_ops wm8580_dai_ops_capture = { - .set_sysclk = wm8580_set_sysclk, - .hw_params = wm8580_paif_hw_params, - .set_fmt = wm8580_set_paif_dai_fmt, - .set_clkdiv = wm8580_set_dai_clkdiv, - .set_pll = wm8580_set_dai_pll, -}; - -static struct snd_soc_dai_driver wm8580_dai[] = { - { - .name = "wm8580-hifi-playback", - .id = WM8580_DAI_PAIFRX, - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 6, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = WM8580_FORMATS, - }, - .ops = &wm8580_dai_ops_playback, - }, - { - .name = "wm8580-hifi-capture", - .id = WM8580_DAI_PAIFTX, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = WM8580_FORMATS, - }, - .ops = &wm8580_dai_ops_capture, - }, -}; - -static int wm8580_probe(struct snd_soc_codec *codec) -{ - struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); - int ret = 0,i; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) - wm8580->supplies[i].supply = wm8580_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), - wm8580->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), - wm8580->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_regulator_get; - } - - /* Get the codec into a known state */ - ret = snd_soc_write(codec, WM8580_RESET, 0); - if (ret != 0) { - dev_err(codec->dev, "Failed to reset codec: %d\n", ret); - goto err_regulator_enable; - } - - wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; - -err_regulator_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); -err_regulator_get: - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); - return ret; -} - -/* power down chip */ -static int wm8580_remove(struct snd_soc_codec *codec) -{ - struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); - - wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); - - regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { - .probe = wm8580_probe, - .remove = wm8580_remove, - .set_bias_level = wm8580_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8580_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8580_reg, - - .controls = wm8580_snd_controls, - .num_controls = ARRAY_SIZE(wm8580_snd_controls), - .dapm_widgets = wm8580_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8580_dapm_widgets), - .dapm_routes = wm8580_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8580_dapm_routes), -}; - -static const struct of_device_id wm8580_of_match[] = { - { .compatible = "wlf,wm8580" }, - { }, -}; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int wm8580_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8580_priv *wm8580; - int ret; - - wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); - if (wm8580 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8580); - wm8580->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); - if (ret < 0) - kfree(wm8580); - return ret; -} - -static int wm8580_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8580_i2c_id[] = { - { "wm8580", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); - -static struct i2c_driver wm8580_i2c_driver = { - .driver = { - .name = "wm8580", - .owner = THIS_MODULE, - .of_match_table = wm8580_of_match, - }, - .probe = wm8580_i2c_probe, - .remove = wm8580_i2c_remove, - .id_table = wm8580_i2c_id, -}; -#endif - -static int __init wm8580_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8580_i2c_driver); - if (ret != 0) { - pr_err("Failed to register WM8580 I2C driver: %d\n", ret); - } -#endif - - return ret; -} -module_init(wm8580_modinit); - -static void __exit wm8580_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8580_i2c_driver); -#endif -} -module_exit(wm8580_exit); - -MODULE_DESCRIPTION("ASoC WM8580 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8580.h b/ANDROID_3.4.5/sound/soc/codecs/wm8580.h deleted file mode 100644 index 1d34656d..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8580.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * wm8580.h -- audio driver for WM8580 - * - * Copyright 2008 Samsung Electronics. - * Author: Ryu Euiyoul - * ryu.real@gmail.com - * - * 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. - * - */ - -#ifndef _WM8580_H -#define _WM8580_H - -#define WM8580_PLLA 1 -#define WM8580_PLLB 2 - -#define WM8580_MCLK 1 -#define WM8580_CLKOUTSRC 2 - -#define WM8580_CLKSRC_MCLK 1 -#define WM8580_CLKSRC_PLLA 2 -#define WM8580_CLKSRC_PLLB 3 -#define WM8580_CLKSRC_OSC 4 -#define WM8580_CLKSRC_NONE 5 -#define WM8580_CLKSRC_ADCMCLK 6 - -#define WM8580_DAI_PAIFRX 0 -#define WM8580_DAI_PAIFTX 1 - -#endif - diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8711.c b/ANDROID_3.4.5/sound/soc/codecs/wm8711.c deleted file mode 100644 index 0b76d1dc..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8711.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * wm8711.c -- WM8711 ALSA SoC Audio driver - * - * Copyright 2006 Wolfson Microelectronics - * - * Author: Mike Arthur - * - * Based on wm8731.c by Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8711.h" - -/* codec private data */ -struct wm8711_priv { - enum snd_soc_control_type bus_type; - unsigned int sysclk; -}; - -/* - * wm8711 register cache - * We can't read the WM8711 register space when we are - * using 2 wire for device control, so we cache them instead. - * There is no point in caching the reset register - */ -static const u16 wm8711_reg[WM8711_CACHEREGNUM] = { - 0x0079, 0x0079, 0x000a, 0x0008, - 0x009f, 0x000a, 0x0000, 0x0000 -}; - -#define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) - -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); - -static const struct snd_kcontrol_new wm8711_snd_controls[] = { - -SOC_DOUBLE_R_TLV("Master Playback Volume", WM8711_LOUT1V, WM8711_ROUT1V, - 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Master Playback ZC Switch", WM8711_LOUT1V, WM8711_ROUT1V, - 7, 1, 0), - -}; - -/* Output Mixer */ -static const struct snd_kcontrol_new wm8711_output_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", WM8711_APANA, 3, 1, 0), -SOC_DAPM_SINGLE("HiFi Playback Switch", WM8711_APANA, 4, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8711_dapm_widgets[] = { -SND_SOC_DAPM_MIXER("Output Mixer", WM8711_PWR, 4, 1, - &wm8711_output_mixer_controls[0], - ARRAY_SIZE(wm8711_output_mixer_controls)), -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8711_PWR, 3, 1), -SND_SOC_DAPM_OUTPUT("LOUT"), -SND_SOC_DAPM_OUTPUT("LHPOUT"), -SND_SOC_DAPM_OUTPUT("ROUT"), -SND_SOC_DAPM_OUTPUT("RHPOUT"), -}; - -static const struct snd_soc_dapm_route wm8711_intercon[] = { - /* output mixer */ - {"Output Mixer", "Line Bypass Switch", "Line Input"}, - {"Output Mixer", "HiFi Playback Switch", "DAC"}, - - /* outputs */ - {"RHPOUT", NULL, "Output Mixer"}, - {"ROUT", NULL, "Output Mixer"}, - {"LHPOUT", NULL, "Output Mixer"}, - {"LOUT", NULL, "Output Mixer"}, -}; - -struct _coeff_div { - u32 mclk; - u32 rate; - u16 fs; - u8 sr:4; - u8 bosr:1; - u8 usb:1; -}; - -/* codec mclk clock divider coefficients */ -static const struct _coeff_div coeff_div[] = { - /* 48k */ - {12288000, 48000, 256, 0x0, 0x0, 0x0}, - {18432000, 48000, 384, 0x0, 0x1, 0x0}, - {12000000, 48000, 250, 0x0, 0x0, 0x1}, - - /* 32k */ - {12288000, 32000, 384, 0x6, 0x0, 0x0}, - {18432000, 32000, 576, 0x6, 0x1, 0x0}, - {12000000, 32000, 375, 0x6, 0x0, 0x1}, - - /* 8k */ - {12288000, 8000, 1536, 0x3, 0x0, 0x0}, - {18432000, 8000, 2304, 0x3, 0x1, 0x0}, - {11289600, 8000, 1408, 0xb, 0x0, 0x0}, - {16934400, 8000, 2112, 0xb, 0x1, 0x0}, - {12000000, 8000, 1500, 0x3, 0x0, 0x1}, - - /* 96k */ - {12288000, 96000, 128, 0x7, 0x0, 0x0}, - {18432000, 96000, 192, 0x7, 0x1, 0x0}, - {12000000, 96000, 125, 0x7, 0x0, 0x1}, - - /* 44.1k */ - {11289600, 44100, 256, 0x8, 0x0, 0x0}, - {16934400, 44100, 384, 0x8, 0x1, 0x0}, - {12000000, 44100, 272, 0x8, 0x1, 0x1}, - - /* 88.2k */ - {11289600, 88200, 128, 0xf, 0x0, 0x0}, - {16934400, 88200, 192, 0xf, 0x1, 0x0}, - {12000000, 88200, 136, 0xf, 0x1, 0x1}, -}; - -static inline int get_coeff(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) - return i; - } - return 0; -} - -static int wm8711_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfff3; - int i = get_coeff(wm8711->sysclk, params_rate(params)); - u16 srate = (coeff_div[i].sr << 2) | - (coeff_div[i].bosr << 1) | coeff_div[i].usb; - - snd_soc_write(codec, WM8711_SRATE, srate); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - } - - snd_soc_write(codec, WM8711_IFACE, iface); - return 0; -} - -static int wm8711_pcm_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - - /* set active */ - snd_soc_write(codec, WM8711_ACTIVE, 0x0001); - - return 0; -} - -static void wm8711_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - - /* deactivate */ - if (!codec->active) { - udelay(50); - snd_soc_write(codec, WM8711_ACTIVE, 0x0); - } -} - -static int wm8711_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8711_APDIGI) & 0xfff7; - - if (mute) - snd_soc_write(codec, WM8711_APDIGI, mute_reg | 0x8); - else - snd_soc_write(codec, WM8711_APDIGI, mute_reg); - - return 0; -} - -static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - wm8711->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0x000c; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface |= 0x0040; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - /* set iface */ - snd_soc_write(codec, WM8711_IFACE, iface); - return 0; -} - -static int wm8711_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; - - switch (level) { - case SND_SOC_BIAS_ON: - snd_soc_write(codec, WM8711_PWR, reg); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - snd_soc_cache_sync(codec); - - snd_soc_write(codec, WM8711_PWR, reg | 0x0040); - break; - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8711_ACTIVE, 0x0); - snd_soc_write(codec, WM8711_PWR, 0xffff); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8711_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8711_ops = { - .prepare = wm8711_pcm_prepare, - .hw_params = wm8711_hw_params, - .shutdown = wm8711_shutdown, - .digital_mute = wm8711_mute, - .set_sysclk = wm8711_set_dai_sysclk, - .set_fmt = wm8711_set_dai_fmt, -}; - -static struct snd_soc_dai_driver wm8711_dai = { - .name = "wm8711-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8711_RATES, - .formats = WM8711_FORMATS, - }, - .ops = &wm8711_ops, -}; - -static int wm8711_suspend(struct snd_soc_codec *codec) -{ - snd_soc_write(codec, WM8711_ACTIVE, 0x0); - wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8711_resume(struct snd_soc_codec *codec) -{ - wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int wm8711_probe(struct snd_soc_codec *codec) -{ - struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = wm8711_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch the update bits */ - snd_soc_update_bits(codec, WM8711_LOUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8711_ROUT1V, 0x0100, 0x0100); - - return ret; - -} - -/* power down chip */ -static int wm8711_remove(struct snd_soc_codec *codec) -{ - wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { - .probe = wm8711_probe, - .remove = wm8711_remove, - .suspend = wm8711_suspend, - .resume = wm8711_resume, - .set_bias_level = wm8711_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8711_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8711_reg, - .controls = wm8711_snd_controls, - .num_controls = ARRAY_SIZE(wm8711_snd_controls), - .dapm_widgets = wm8711_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8711_dapm_widgets), - .dapm_routes = wm8711_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), -}; - -static const struct of_device_id wm8711_of_match[] = { - { .compatible = "wlf,wm8711", }, - { } -}; -MODULE_DEVICE_TABLE(of, wm8711_of_match); - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8711_spi_probe(struct spi_device *spi) -{ - struct wm8711_priv *wm8711; - int ret; - - wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); - if (wm8711 == NULL) - return -ENOMEM; - - spi_set_drvdata(spi, wm8711); - wm8711->bus_type = SND_SOC_SPI; - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8711, &wm8711_dai, 1); - if (ret < 0) - kfree(wm8711); - return ret; -} - -static int __devexit wm8711_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); - return 0; -} - -static struct spi_driver wm8711_spi_driver = { - .driver = { - .name = "wm8711", - .owner = THIS_MODULE, - .of_match_table = wm8711_of_match, - }, - .probe = wm8711_spi_probe, - .remove = __devexit_p(wm8711_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8711_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct wm8711_priv *wm8711; - int ret; - - wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); - if (wm8711 == NULL) - return -ENOMEM; - - i2c_set_clientdata(client, wm8711); - wm8711->bus_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&client->dev, - &soc_codec_dev_wm8711, &wm8711_dai, 1); - if (ret < 0) - kfree(wm8711); - return ret; -} - -static __devexit int wm8711_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8711_i2c_id[] = { - { "wm8711", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); - -static struct i2c_driver wm8711_i2c_driver = { - .driver = { - .name = "wm8711", - .owner = THIS_MODULE, - .of_match_table = wm8711_of_match, - }, - .probe = wm8711_i2c_probe, - .remove = __devexit_p(wm8711_i2c_remove), - .id_table = wm8711_i2c_id, -}; -#endif - -static int __init wm8711_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8711_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8711_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8711 SPI driver: %d\n", - ret); - } -#endif - return 0; -} -module_init(wm8711_modinit); - -static void __exit wm8711_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8711_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8711_spi_driver); -#endif -} -module_exit(wm8711_exit); - -MODULE_DESCRIPTION("ASoC WM8711 driver"); -MODULE_AUTHOR("Mike Arthur"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8711.h b/ANDROID_3.4.5/sound/soc/codecs/wm8711.h deleted file mode 100644 index a61db985..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8711.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * wm8711.h -- WM8711 Soc Audio driver - * - * Copyright 2006 Wolfson Microelectronics - * - * Author: Mike Arthur - * - * Based on wm8731.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8711_H -#define _WM8711_H - -/* WM8711 register space */ - -#define WM8711_LOUT1V 0x02 -#define WM8711_ROUT1V 0x03 -#define WM8711_APANA 0x04 -#define WM8711_APDIGI 0x05 -#define WM8711_PWR 0x06 -#define WM8711_IFACE 0x07 -#define WM8711_SRATE 0x08 -#define WM8711_ACTIVE 0x09 -#define WM8711_RESET 0x0f - -#define WM8711_CACHEREGNUM 8 - -#define WM8711_SYSCLK 0 -#define WM8711_DAI 0 - -struct wm8711_setup_data { - unsigned short i2c_address; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8727.c b/ANDROID_3.4.5/sound/soc/codecs/wm8727.c deleted file mode 100644 index e8170562..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8727.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * wm8727.c - * - * Created on: 15-Oct-2009 - * Author: neil.jones@imgtec.com - * - * Copyright (C) 2009 Imagination Technologies Ltd. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Note this is a simple chip with no configuration interface, sample rate is - * determined automatically by examining the Master clock and Bit clock ratios - */ -#define WM8727_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |\ - SNDRV_PCM_RATE_192000) - - -static struct snd_soc_dai_driver wm8727_dai = { - .name = "wm8727-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8727_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, - }, -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm8727; - -static __devinit int wm8727_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_wm8727, &wm8727_dai, 1); -} - -static int __devexit wm8727_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver wm8727_codec_driver = { - .driver = { - .name = "wm8727", - .owner = THIS_MODULE, - }, - - .probe = wm8727_probe, - .remove = __devexit_p(wm8727_remove), -}; - -module_platform_driver(wm8727_codec_driver); - -MODULE_DESCRIPTION("ASoC wm8727 driver"); -MODULE_AUTHOR("Neil Jones"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8728.c b/ANDROID_3.4.5/sound/soc/codecs/wm8728.c deleted file mode 100644 index fc3d59e4..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8728.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * wm8728.c -- WM8728 ALSA SoC Audio driver - * - * Copyright 2008 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8728.h" - -/* - * We can't read the WM8728 register space so we cache them instead. - * Note that the defaults here aren't the physical defaults, we latch - * the volume update bits, mute the output and enable infinite zero - * detect. - */ -static const u16 wm8728_reg_defaults[] = { - 0x1ff, - 0x1ff, - 0x001, - 0x100, -}; - -/* codec private data */ -struct wm8728_priv { - enum snd_soc_control_type control_type; -}; - -static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); - -static const struct snd_kcontrol_new wm8728_snd_controls[] = { - -SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL, - 0, 255, 0, wm8728_tlv), - -SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), -}; - -/* - * DAPM controls. - */ -static const struct snd_soc_dapm_widget wm8728_dapm_widgets[] = { -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_OUTPUT("VOUTL"), -SND_SOC_DAPM_OUTPUT("VOUTR"), -}; - -static const struct snd_soc_dapm_route wm8728_intercon[] = { - {"VOUTL", NULL, "DAC"}, - {"VOUTR", NULL, "DAC"}, -}; - -static int wm8728_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8728_DACCTL); - - if (mute) - snd_soc_write(codec, WM8728_DACCTL, mute_reg | 1); - else - snd_soc_write(codec, WM8728_DACCTL, mute_reg & ~1); - - return 0; -} - -static int wm8728_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 dac = snd_soc_read(codec, WM8728_DACCTL); - - dac &= ~0x18; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - dac |= 0x10; - break; - case SNDRV_PCM_FORMAT_S24_LE: - dac |= 0x08; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8728_DACCTL, dac); - - return 0; -} - -static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = snd_soc_read(codec, WM8728_IFCTL); - - /* Currently only I2S is supported by the driver, though the - * hardware is more flexible. - */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 1; - break; - default: - return -EINVAL; - } - - /* The hardware only support full slave mode */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - iface &= ~0x22; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x20; - iface &= ~0x02; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x02; - iface &= ~0x20; - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x22; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8728_IFCTL, iface); - return 0; -} - -static int wm8728_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 reg; - int i; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - /* Power everything up... */ - reg = snd_soc_read(codec, WM8728_DACCTL); - snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); - - /* ..then sync in the register cache. */ - for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) - snd_soc_write(codec, i, - snd_soc_read(codec, i)); - } - break; - - case SND_SOC_BIAS_OFF: - reg = snd_soc_read(codec, WM8728_DACCTL); - snd_soc_write(codec, WM8728_DACCTL, reg | 0x4); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8728_RATES (SNDRV_PCM_RATE_8000_192000) - -#define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8728_dai_ops = { - .hw_params = wm8728_hw_params, - .digital_mute = wm8728_mute, - .set_fmt = wm8728_set_dai_fmt, -}; - -static struct snd_soc_dai_driver wm8728_dai = { - .name = "wm8728-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8728_RATES, - .formats = WM8728_FORMATS, - }, - .ops = &wm8728_dai_ops, -}; - -static int wm8728_suspend(struct snd_soc_codec *codec) -{ - wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8728_resume(struct snd_soc_codec *codec) -{ - wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int wm8728_probe(struct snd_soc_codec *codec) -{ - struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); - if (ret < 0) { - printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", - ret); - return ret; - } - - /* power on device */ - wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return ret; -} - -static int wm8728_remove(struct snd_soc_codec *codec) -{ - wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { - .probe = wm8728_probe, - .remove = wm8728_remove, - .suspend = wm8728_suspend, - .resume = wm8728_resume, - .set_bias_level = wm8728_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8728_reg_defaults, - .controls = wm8728_snd_controls, - .num_controls = ARRAY_SIZE(wm8728_snd_controls), - .dapm_widgets = wm8728_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8728_dapm_widgets), - .dapm_routes = wm8728_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), -}; - -static const struct of_device_id wm8728_of_match[] = { - { .compatible = "wlf,wm8728", }, - { } -}; -MODULE_DEVICE_TABLE(of, wm8728_of_match); - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8728_spi_probe(struct spi_device *spi) -{ - struct wm8728_priv *wm8728; - int ret; - - wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); - if (wm8728 == NULL) - return -ENOMEM; - - wm8728->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8728); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8728, &wm8728_dai, 1); - if (ret < 0) - kfree(wm8728); - return ret; -} - -static int __devexit wm8728_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); - return 0; -} - -static struct spi_driver wm8728_spi_driver = { - .driver = { - .name = "wm8728", - .owner = THIS_MODULE, - .of_match_table = wm8728_of_match, - }, - .probe = wm8728_spi_probe, - .remove = __devexit_p(wm8728_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8728_priv *wm8728; - int ret; - - wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); - if (wm8728 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8728); - wm8728->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8728, &wm8728_dai, 1); - if (ret < 0) - kfree(wm8728); - return ret; -} - -static __devexit int wm8728_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8728_i2c_id[] = { - { "wm8728", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); - -static struct i2c_driver wm8728_i2c_driver = { - .driver = { - .name = "wm8728", - .owner = THIS_MODULE, - .of_match_table = wm8728_of_match, - }, - .probe = wm8728_i2c_probe, - .remove = __devexit_p(wm8728_i2c_remove), - .id_table = wm8728_i2c_id, -}; -#endif - -static int __init wm8728_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8728_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8728_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8728_modinit); - -static void __exit wm8728_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8728_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8728_spi_driver); -#endif -} -module_exit(wm8728_exit); - -MODULE_DESCRIPTION("ASoC WM8728 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8728.h b/ANDROID_3.4.5/sound/soc/codecs/wm8728.h deleted file mode 100644 index 8aea362f..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8728.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * wm8728.h -- WM8728 ASoC codec driver - * - * Copyright 2008 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8728_H -#define _WM8728_H - -#define WM8728_DACLVOL 0x00 -#define WM8728_DACRVOL 0x01 -#define WM8728_DACCTL 0x02 -#define WM8728_IFCTL 0x03 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8731.c b/ANDROID_3.4.5/sound/soc/codecs/wm8731.c deleted file mode 100644 index a32caa72..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8731.c +++ /dev/null @@ -1,787 +0,0 @@ -/* - * wm8731.c -- WM8731 ALSA SoC Audio driver - * - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie - * - * Based on wm8753.c by Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8731.h" - -#define WM8731_NUM_SUPPLIES 4 -static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { - "AVDD", - "HPVDD", - "DCVDD", - "DBVDD", -}; - -/* codec private data */ -struct wm8731_priv { - struct regmap *regmap; - struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; - unsigned int sysclk; - int sysclk_type; - int playback_fs; - bool deemph; -}; - - -/* - * wm8731 register cache - */ -static const struct reg_default wm8731_reg_defaults[] = { - { 0, 0x0097 }, - { 1, 0x0097 }, - { 2, 0x0079 }, - { 3, 0x0079 }, - { 4, 0x000a }, - { 5, 0x0008 }, - { 6, 0x009f }, - { 7, 0x000a }, - { 8, 0x0000 }, - { 9, 0x0000 }, -}; - -static bool wm8731_volatile(struct device *dev, unsigned int reg) -{ - return reg == WM8731_RESET; -} - -static bool wm8731_writeable(struct device *dev, unsigned int reg) -{ - return reg <= WM8731_RESET; -} - -#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0) - -static const char *wm8731_input_select[] = {"Line In", "Mic"}; - -static const struct soc_enum wm8731_insel_enum = - SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select); - -static int wm8731_deemph[] = { 0, 32000, 44100, 48000 }; - -static int wm8731_set_deemph(struct snd_soc_codec *codec) -{ - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - int val, i, best; - - /* If we're using deemphasis select the nearest available sample - * rate. - */ - if (wm8731->deemph) { - best = 1; - for (i = 2; i < ARRAY_SIZE(wm8731_deemph); i++) { - if (abs(wm8731_deemph[i] - wm8731->playback_fs) < - abs(wm8731_deemph[best] - wm8731->playback_fs)) - best = i; - } - - val = best << 1; - } else { - best = 0; - val = 0; - } - - dev_dbg(codec->dev, "Set deemphasis %d (%dHz)\n", - best, wm8731_deemph[best]); - - return snd_soc_update_bits(codec, WM8731_APDIGI, 0x6, val); -} - -static int wm8731_get_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8731->deemph; - - return 0; -} - -static int wm8731_put_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - int deemph = ucontrol->value.enumerated.item[0]; - int ret = 0; - - if (deemph > 1) - return -EINVAL; - - mutex_lock(&codec->mutex); - if (wm8731->deemph != deemph) { - wm8731->deemph = deemph; - - wm8731_set_deemph(codec); - - ret = 1; - } - mutex_unlock(&codec->mutex); - - return ret; -} - -static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 2000, 0); - -static const struct snd_kcontrol_new wm8731_snd_controls[] = { - -SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, - 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V, - 7, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0, - in_tlv), -SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1), - -SOC_SINGLE_TLV("Mic Boost Volume", WM8731_APANA, 0, 1, 0, mic_tlv), -SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1), - -SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1, - sidetone_tlv), - -SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1), -SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), - -SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, - wm8731_get_deemph, wm8731_put_deemph), -}; - -/* Output Mixer */ -static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), -SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0), -SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0), -}; - -/* Input mux */ -static const struct snd_kcontrol_new wm8731_input_mux_controls = -SOC_DAPM_ENUM("Input Select", wm8731_insel_enum); - -static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { -SND_SOC_DAPM_SUPPLY("ACTIVE",WM8731_ACTIVE, 0, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0), -SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, - &wm8731_output_mixer_controls[0], - ARRAY_SIZE(wm8731_output_mixer_controls)), -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8731_PWR, 3, 1), -SND_SOC_DAPM_OUTPUT("LOUT"), -SND_SOC_DAPM_OUTPUT("LHPOUT"), -SND_SOC_DAPM_OUTPUT("ROUT"), -SND_SOC_DAPM_OUTPUT("RHPOUT"), -SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8731_PWR, 2, 1), -SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &wm8731_input_mux_controls), -SND_SOC_DAPM_PGA("Line Input", WM8731_PWR, 0, 1, NULL, 0), -SND_SOC_DAPM_MICBIAS("Mic Bias", WM8731_PWR, 1, 1), -SND_SOC_DAPM_INPUT("MICIN"), -SND_SOC_DAPM_INPUT("RLINEIN"), -SND_SOC_DAPM_INPUT("LLINEIN"), -}; - -static int wm8731_check_osc(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec); - - return wm8731->sysclk_type == WM8731_SYSCLK_XTAL; -} - -static const struct snd_soc_dapm_route wm8731_intercon[] = { - {"DAC", NULL, "OSC", wm8731_check_osc}, - {"ADC", NULL, "OSC", wm8731_check_osc}, - {"DAC", NULL, "ACTIVE"}, - {"ADC", NULL, "ACTIVE"}, - - /* output mixer */ - {"Output Mixer", "Line Bypass Switch", "Line Input"}, - {"Output Mixer", "HiFi Playback Switch", "DAC"}, - {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, - - /* outputs */ - {"RHPOUT", NULL, "Output Mixer"}, - {"ROUT", NULL, "Output Mixer"}, - {"LHPOUT", NULL, "Output Mixer"}, - {"LOUT", NULL, "Output Mixer"}, - - /* input mux */ - {"Input Mux", "Line In", "Line Input"}, - {"Input Mux", "Mic", "Mic Bias"}, - {"ADC", NULL, "Input Mux"}, - - /* inputs */ - {"Line Input", NULL, "LLINEIN"}, - {"Line Input", NULL, "RLINEIN"}, - {"Mic Bias", NULL, "MICIN"}, -}; - -struct _coeff_div { - u32 mclk; - u32 rate; - u16 fs; - u8 sr:4; - u8 bosr:1; - u8 usb:1; -}; - -/* codec mclk clock divider coefficients */ -static const struct _coeff_div coeff_div[] = { - /* 48k */ - {12288000, 48000, 256, 0x0, 0x0, 0x0}, - {18432000, 48000, 384, 0x0, 0x1, 0x0}, - {12000000, 48000, 250, 0x0, 0x0, 0x1}, - - /* 32k */ - {12288000, 32000, 384, 0x6, 0x0, 0x0}, - {18432000, 32000, 576, 0x6, 0x1, 0x0}, - {12000000, 32000, 375, 0x6, 0x0, 0x1}, - - /* 8k */ - {12288000, 8000, 1536, 0x3, 0x0, 0x0}, - {18432000, 8000, 2304, 0x3, 0x1, 0x0}, - {11289600, 8000, 1408, 0xb, 0x0, 0x0}, - {16934400, 8000, 2112, 0xb, 0x1, 0x0}, - {12000000, 8000, 1500, 0x3, 0x0, 0x1}, - - /* 96k */ - {12288000, 96000, 128, 0x7, 0x0, 0x0}, - {18432000, 96000, 192, 0x7, 0x1, 0x0}, - {12000000, 96000, 125, 0x7, 0x0, 0x1}, - - /* 44.1k */ - {11289600, 44100, 256, 0x8, 0x0, 0x0}, - {16934400, 44100, 384, 0x8, 0x1, 0x0}, - {12000000, 44100, 272, 0x8, 0x1, 0x1}, - - /* 88.2k */ - {11289600, 88200, 128, 0xf, 0x0, 0x0}, - {16934400, 88200, 192, 0xf, 0x1, 0x0}, - {12000000, 88200, 136, 0xf, 0x1, 0x1}, -}; - -static inline int get_coeff(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) - return i; - } - return 0; -} - -static int wm8731_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; - int i = get_coeff(wm8731->sysclk, params_rate(params)); - u16 srate = (coeff_div[i].sr << 2) | - (coeff_div[i].bosr << 1) | coeff_div[i].usb; - - wm8731->playback_fs = params_rate(params); - - snd_soc_write(codec, WM8731_SRATE, srate); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - } - - wm8731_set_deemph(codec); - - snd_soc_write(codec, WM8731_IFACE, iface); - return 0; -} - -static int wm8731_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7; - - if (mute) - snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8); - else - snd_soc_write(codec, WM8731_APDIGI, mute_reg); - return 0; -} - -static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case WM8731_SYSCLK_XTAL: - case WM8731_SYSCLK_MCLK: - wm8731->sysclk_type = clk_id; - break; - default: - return -EINVAL; - } - - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - wm8731->sysclk = freq; - break; - default: - return -EINVAL; - } - - snd_soc_dapm_sync(&codec->dapm); - - return 0; -} - - -static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface |= 0x0040; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - /* set iface */ - snd_soc_write(codec, WM8731_IFACE, iface); - return 0; -} - -static int wm8731_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - int ret; - u16 reg; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), - wm8731->supplies); - if (ret != 0) - return ret; - - regcache_sync(wm8731->regmap); - } - - /* Clear PWROFF, gate CLKOUT, everything else as-is */ - reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f; - snd_soc_write(codec, WM8731_PWR, reg | 0x0040); - break; - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8731_PWR, 0xffff); - regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), - wm8731->supplies); - regcache_mark_dirty(wm8731->regmap); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8731_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8731_dai_ops = { - .hw_params = wm8731_hw_params, - .digital_mute = wm8731_mute, - .set_sysclk = wm8731_set_dai_sysclk, - .set_fmt = wm8731_set_dai_fmt, -}; - -static struct snd_soc_dai_driver wm8731_dai = { - .name = "wm8731-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8731_RATES, - .formats = WM8731_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8731_RATES, - .formats = WM8731_FORMATS,}, - .ops = &wm8731_dai_ops, - .symmetric_rates = 1, -}; - -#ifdef CONFIG_PM -static int wm8731_suspend(struct snd_soc_codec *codec) -{ - wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8731_resume(struct snd_soc_codec *codec) -{ - wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8731_suspend NULL -#define wm8731_resume NULL -#endif - -static int wm8731_probe(struct snd_soc_codec *codec) -{ - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - int ret = 0, i; - - codec->control_data = wm8731->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) - wm8731->supplies[i].supply = wm8731_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies), - wm8731->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), - wm8731->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_regulator_get; - } - - ret = wm8731_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err_regulator_enable; - } - - wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch the update bits */ - snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0); - snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0); - snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0); - snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0); - - /* Disable bypass path by default */ - snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0); - - /* Regulators will have been enabled by bias management */ - regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); - - return 0; - -err_regulator_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); -err_regulator_get: - regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); - - return ret; -} - -/* power down chip */ -static int wm8731_remove(struct snd_soc_codec *codec) -{ - struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - - wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); - - regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { - .probe = wm8731_probe, - .remove = wm8731_remove, - .suspend = wm8731_suspend, - .resume = wm8731_resume, - .set_bias_level = wm8731_set_bias_level, - .dapm_widgets = wm8731_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), - .dapm_routes = wm8731_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), - .controls = wm8731_snd_controls, - .num_controls = ARRAY_SIZE(wm8731_snd_controls), -}; - -static const struct of_device_id wm8731_of_match[] = { - { .compatible = "wlf,wm8731", }, - { } -}; - -MODULE_DEVICE_TABLE(of, wm8731_of_match); - -static const struct regmap_config wm8731_regmap = { - .reg_bits = 7, - .val_bits = 9, - - .max_register = WM8731_RESET, - .volatile_reg = wm8731_volatile, - .writeable_reg = wm8731_writeable, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8731_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8731_reg_defaults), -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8731_spi_probe(struct spi_device *spi) -{ - struct wm8731_priv *wm8731; - int ret; - - wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); - if (wm8731 == NULL) - return -ENOMEM; - - wm8731->regmap = regmap_init_spi(spi, &wm8731_regmap); - if (IS_ERR(wm8731->regmap)) { - ret = PTR_ERR(wm8731->regmap); - dev_err(&spi->dev, "Failed to allocate register map: %d\n", - ret); - goto err; - } - - spi_set_drvdata(spi, wm8731); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8731, &wm8731_dai, 1); - if (ret != 0) { - dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret); - goto err_regmap; - } - - return 0; - -err_regmap: - regmap_exit(wm8731->regmap); -err: - kfree(wm8731); - return ret; -} - -static int __devexit wm8731_spi_remove(struct spi_device *spi) -{ - struct wm8731_priv *wm8731 = spi_get_drvdata(spi); - - snd_soc_unregister_codec(&spi->dev); - regmap_exit(wm8731->regmap); - kfree(wm8731); - return 0; -} - -static struct spi_driver wm8731_spi_driver = { - .driver = { - .name = "wm8731", - .owner = THIS_MODULE, - .of_match_table = wm8731_of_match, - }, - .probe = wm8731_spi_probe, - .remove = __devexit_p(wm8731_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8731_priv *wm8731; - int ret; - - wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); - if (wm8731 == NULL) - return -ENOMEM; - - wm8731->regmap = regmap_init_i2c(i2c, &wm8731_regmap); - if (IS_ERR(wm8731->regmap)) { - ret = PTR_ERR(wm8731->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - goto err; - } - - i2c_set_clientdata(i2c, wm8731); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8731, &wm8731_dai, 1); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - goto err_regmap; - } - - return 0; - -err_regmap: - regmap_exit(wm8731->regmap); -err: - kfree(wm8731); - return ret; -} - -static __devexit int wm8731_i2c_remove(struct i2c_client *client) -{ - struct wm8731_priv *wm8731 = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8731->regmap); - kfree(wm8731); - return 0; -} - -static const struct i2c_device_id wm8731_i2c_id[] = { - { "wm8731", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); - -static struct i2c_driver wm8731_i2c_driver = { - .driver = { - .name = "wm8731", - .owner = THIS_MODULE, - .of_match_table = wm8731_of_match, - }, - .probe = wm8731_i2c_probe, - .remove = __devexit_p(wm8731_i2c_remove), - .id_table = wm8731_i2c_id, -}; -#endif - -static int __init wm8731_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8731_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8731_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8731 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8731_modinit); - -static void __exit wm8731_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8731_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8731_spi_driver); -#endif -} -module_exit(wm8731_exit); - -MODULE_DESCRIPTION("ASoC WM8731 driver"); -MODULE_AUTHOR("Richard Purdie"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8731.h b/ANDROID_3.4.5/sound/soc/codecs/wm8731.h deleted file mode 100644 index e9c0c76a..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8731.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * wm8731.h -- WM8731 Soc Audio driver - * - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie - * - * Based on wm8753.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8731_H -#define _WM8731_H - -/* WM8731 register space */ - -#define WM8731_LINVOL 0x00 -#define WM8731_RINVOL 0x01 -#define WM8731_LOUT1V 0x02 -#define WM8731_ROUT1V 0x03 -#define WM8731_APANA 0x04 -#define WM8731_APDIGI 0x05 -#define WM8731_PWR 0x06 -#define WM8731_IFACE 0x07 -#define WM8731_SRATE 0x08 -#define WM8731_ACTIVE 0x09 -#define WM8731_RESET 0x0f - -#define WM8731_CACHEREGNUM 10 - -#define WM8731_SYSCLK_XTAL 1 -#define WM8731_SYSCLK_MCLK 2 - -#define WM8731_DAI 0 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8737.c b/ANDROID_3.4.5/sound/soc/codecs/wm8737.c deleted file mode 100644 index 4fe9d191..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8737.c +++ /dev/null @@ -1,763 +0,0 @@ -/* - * wm8737.c -- WM8737 ALSA SoC Audio driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8737.h" - -#define WM8737_NUM_SUPPLIES 4 -static const char *wm8737_supply_names[WM8737_NUM_SUPPLIES] = { - "DCVDD", - "DBVDD", - "AVDD", - "MVDD", -}; - -/* codec private data */ -struct wm8737_priv { - enum snd_soc_control_type control_type; - struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES]; - unsigned int mclk; -}; - -static const u16 wm8737_reg[WM8737_REGISTER_COUNT] = { - 0x00C3, /* R0 - Left PGA volume */ - 0x00C3, /* R1 - Right PGA volume */ - 0x0007, /* R2 - AUDIO path L */ - 0x0007, /* R3 - AUDIO path R */ - 0x0000, /* R4 - 3D Enhance */ - 0x0000, /* R5 - ADC Control */ - 0x0000, /* R6 - Power Management */ - 0x000A, /* R7 - Audio Format */ - 0x0000, /* R8 - Clocking */ - 0x000F, /* R9 - MIC Preamp Control */ - 0x0003, /* R10 - Misc Bias Control */ - 0x0000, /* R11 - Noise Gate */ - 0x007C, /* R12 - ALC1 */ - 0x0000, /* R13 - ALC2 */ - 0x0032, /* R14 - ALC3 */ -}; - -static int wm8737_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8737_RESET, 0); -} - -static const unsigned int micboost_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 0, TLV_DB_SCALE_ITEM(1300, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(2800, 0, 0), - 3, 3, TLV_DB_SCALE_ITEM(3300, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(pga_tlv, -9750, 50, 1); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(ng_tlv, -7800, 600, 0); -static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(alc_target_tlv, -1800, 100, 0); - -static const char *micbias_enum_text[] = { - "25%", - "50%", - "75%", - "100%", -}; - -static const struct soc_enum micbias_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 0, 4, micbias_enum_text); - -static const char *low_cutoff_text[] = { - "Low", "High" -}; - -static const struct soc_enum low_3d = - SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 6, 2, low_cutoff_text); - -static const char *high_cutoff_text[] = { - "High", "Low" -}; - -static const struct soc_enum high_3d = - SOC_ENUM_SINGLE(WM8737_3D_ENHANCE, 5, 2, high_cutoff_text); - -static const char *alc_fn_text[] = { - "Disabled", "Right", "Left", "Stereo" -}; - -static const struct soc_enum alc_fn = - SOC_ENUM_SINGLE(WM8737_ALC1, 7, 4, alc_fn_text); - -static const char *alc_hold_text[] = { - "0", "2.67ms", "5.33ms", "10.66ms", "21.32ms", "42.64ms", "85.28ms", - "170.56ms", "341.12ms", "682.24ms", "1.364s", "2.728s", "5.458s", - "10.916s", "21.832s", "43.691s" -}; - -static const struct soc_enum alc_hold = - SOC_ENUM_SINGLE(WM8737_ALC2, 0, 16, alc_hold_text); - -static const char *alc_atk_text[] = { - "8.4ms", "16.8ms", "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", - "1.075s", "2.15s", "4.3s", "8.6s" -}; - -static const struct soc_enum alc_atk = - SOC_ENUM_SINGLE(WM8737_ALC3, 0, 11, alc_atk_text); - -static const char *alc_dcy_text[] = { - "33.6ms", "67.2ms", "134.4ms", "268.8ms", "537.6ms", "1.075s", "2.15s", - "4.3s", "8.6s", "17.2s", "34.41s" -}; - -static const struct soc_enum alc_dcy = - SOC_ENUM_SINGLE(WM8737_ALC3, 4, 11, alc_dcy_text); - -static const struct snd_kcontrol_new wm8737_snd_controls[] = { -SOC_DOUBLE_R_TLV("Mic Boost Volume", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, - 6, 3, 0, micboost_tlv), -SOC_DOUBLE_R("Mic Boost Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, - 4, 1, 0), -SOC_DOUBLE("Mic ZC Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, - 3, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8737_LEFT_PGA_VOLUME, - WM8737_RIGHT_PGA_VOLUME, 0, 255, 0, pga_tlv), -SOC_DOUBLE("Capture ZC Switch", WM8737_AUDIO_PATH_L, WM8737_AUDIO_PATH_R, - 2, 1, 0), - -SOC_DOUBLE("INPUT1 DC Bias Switch", WM8737_MISC_BIAS_CONTROL, 0, 1, 1, 0), - -SOC_ENUM("Mic PGA Bias", micbias_enum), -SOC_SINGLE("ADC Low Power Switch", WM8737_ADC_CONTROL, 2, 1, 0), -SOC_SINGLE("High Pass Filter Switch", WM8737_ADC_CONTROL, 0, 1, 1), -SOC_DOUBLE("Polarity Invert Switch", WM8737_ADC_CONTROL, 5, 6, 1, 0), - -SOC_SINGLE("3D Switch", WM8737_3D_ENHANCE, 0, 1, 0), -SOC_SINGLE("3D Depth", WM8737_3D_ENHANCE, 1, 15, 0), -SOC_ENUM("3D Low Cut-off", low_3d), -SOC_ENUM("3D High Cut-off", low_3d), -SOC_SINGLE_TLV("3D ADC Volume", WM8737_3D_ENHANCE, 7, 1, 1, adc_tlv), - -SOC_SINGLE("Noise Gate Switch", WM8737_NOISE_GATE, 0, 1, 0), -SOC_SINGLE_TLV("Noise Gate Threshold Volume", WM8737_NOISE_GATE, 2, 7, 0, - ng_tlv), - -SOC_ENUM("ALC", alc_fn), -SOC_SINGLE_TLV("ALC Max Gain Volume", WM8737_ALC1, 4, 7, 0, alc_max_tlv), -SOC_SINGLE_TLV("ALC Target Volume", WM8737_ALC1, 0, 15, 0, alc_target_tlv), -SOC_ENUM("ALC Hold Time", alc_hold), -SOC_SINGLE("ALC ZC Switch", WM8737_ALC2, 4, 1, 0), -SOC_ENUM("ALC Attack Time", alc_atk), -SOC_ENUM("ALC Decay Time", alc_dcy), -}; - -static const char *linsel_text[] = { - "LINPUT1", "LINPUT2", "LINPUT3", "LINPUT1 DC", -}; - -static const struct soc_enum linsel_enum = - SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_L, 7, 4, linsel_text); - -static const struct snd_kcontrol_new linsel_mux = - SOC_DAPM_ENUM("LINSEL", linsel_enum); - - -static const char *rinsel_text[] = { - "RINPUT1", "RINPUT2", "RINPUT3", "RINPUT1 DC", -}; - -static const struct soc_enum rinsel_enum = - SOC_ENUM_SINGLE(WM8737_AUDIO_PATH_R, 7, 4, rinsel_text); - -static const struct snd_kcontrol_new rinsel_mux = - SOC_DAPM_ENUM("RINSEL", rinsel_enum); - -static const char *bypass_text[] = { - "Direct", "Preamp" -}; - -static const struct soc_enum lbypass_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 2, 2, bypass_text); - -static const struct snd_kcontrol_new lbypass_mux = - SOC_DAPM_ENUM("Left Bypass", lbypass_enum); - - -static const struct soc_enum rbypass_enum = - SOC_ENUM_SINGLE(WM8737_MIC_PREAMP_CONTROL, 3, 2, bypass_text); - -static const struct snd_kcontrol_new rbypass_mux = - SOC_DAPM_ENUM("Left Bypass", rbypass_enum); - -static const struct snd_soc_dapm_widget wm8737_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("LINPUT1"), -SND_SOC_DAPM_INPUT("LINPUT2"), -SND_SOC_DAPM_INPUT("LINPUT3"), -SND_SOC_DAPM_INPUT("RINPUT1"), -SND_SOC_DAPM_INPUT("RINPUT2"), -SND_SOC_DAPM_INPUT("RINPUT3"), -SND_SOC_DAPM_INPUT("LACIN"), -SND_SOC_DAPM_INPUT("RACIN"), - -SND_SOC_DAPM_MUX("LINSEL", SND_SOC_NOPM, 0, 0, &linsel_mux), -SND_SOC_DAPM_MUX("RINSEL", SND_SOC_NOPM, 0, 0, &rinsel_mux), - -SND_SOC_DAPM_MUX("Left Preamp Mux", SND_SOC_NOPM, 0, 0, &lbypass_mux), -SND_SOC_DAPM_MUX("Right Preamp Mux", SND_SOC_NOPM, 0, 0, &rbypass_mux), - -SND_SOC_DAPM_PGA("PGAL", WM8737_POWER_MANAGEMENT, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("PGAR", WM8737_POWER_MANAGEMENT, 4, 0, NULL, 0), - -SND_SOC_DAPM_DAC("ADCL", NULL, WM8737_POWER_MANAGEMENT, 3, 0), -SND_SOC_DAPM_DAC("ADCR", NULL, WM8737_POWER_MANAGEMENT, 2, 0), - -SND_SOC_DAPM_AIF_OUT("AIF", "Capture", 0, WM8737_POWER_MANAGEMENT, 6, 0), -}; - -static const struct snd_soc_dapm_route intercon[] = { - { "LINSEL", "LINPUT1", "LINPUT1" }, - { "LINSEL", "LINPUT2", "LINPUT2" }, - { "LINSEL", "LINPUT3", "LINPUT3" }, - { "LINSEL", "LINPUT1 DC", "LINPUT1" }, - - { "RINSEL", "RINPUT1", "RINPUT1" }, - { "RINSEL", "RINPUT2", "RINPUT2" }, - { "RINSEL", "RINPUT3", "RINPUT3" }, - { "RINSEL", "RINPUT1 DC", "RINPUT1" }, - - { "Left Preamp Mux", "Preamp", "LINSEL" }, - { "Left Preamp Mux", "Direct", "LACIN" }, - - { "Right Preamp Mux", "Preamp", "RINSEL" }, - { "Right Preamp Mux", "Direct", "RACIN" }, - - { "PGAL", NULL, "Left Preamp Mux" }, - { "PGAR", NULL, "Right Preamp Mux" }, - - { "ADCL", NULL, "PGAL" }, - { "ADCR", NULL, "PGAR" }, - - { "AIF", NULL, "ADCL" }, - { "AIF", NULL, "ADCR" }, -}; - -static int wm8737_add_widgets(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, wm8737_dapm_widgets, - ARRAY_SIZE(wm8737_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - return 0; -} - -/* codec mclk clock divider coefficients */ -static const struct { - u32 mclk; - u32 rate; - u8 usb; - u8 sr; -} coeff_div[] = { - { 12288000, 8000, 0, 0x4 }, - { 12288000, 12000, 0, 0x8 }, - { 12288000, 16000, 0, 0xa }, - { 12288000, 24000, 0, 0x1c }, - { 12288000, 32000, 0, 0xc }, - { 12288000, 48000, 0, 0 }, - { 12288000, 96000, 0, 0xe }, - - { 11289600, 8000, 0, 0x14 }, - { 11289600, 11025, 0, 0x18 }, - { 11289600, 22050, 0, 0x1a }, - { 11289600, 44100, 0, 0x10 }, - { 11289600, 88200, 0, 0x1e }, - - { 18432000, 8000, 0, 0x5 }, - { 18432000, 12000, 0, 0x9 }, - { 18432000, 16000, 0, 0xb }, - { 18432000, 24000, 0, 0x1b }, - { 18432000, 32000, 0, 0xd }, - { 18432000, 48000, 0, 0x1 }, - { 18432000, 96000, 0, 0x1f }, - - { 16934400, 8000, 0, 0x15 }, - { 16934400, 11025, 0, 0x19 }, - { 16934400, 22050, 0, 0x1b }, - { 16934400, 44100, 0, 0x11 }, - { 16934400, 88200, 0, 0x1f }, - - { 12000000, 8000, 1, 0x4 }, - { 12000000, 11025, 1, 0x19 }, - { 12000000, 12000, 1, 0x8 }, - { 12000000, 16000, 1, 0xa }, - { 12000000, 22050, 1, 0x1b }, - { 12000000, 24000, 1, 0x1c }, - { 12000000, 32000, 1, 0xc }, - { 12000000, 44100, 1, 0x11 }, - { 12000000, 48000, 1, 0x0 }, - { 12000000, 88200, 1, 0x1f }, - { 12000000, 96000, 1, 0xe }, -}; - -static int wm8737_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - int i; - u16 clocking = 0; - u16 af = 0; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate != params_rate(params)) - continue; - - if (coeff_div[i].mclk == wm8737->mclk) - break; - - if (coeff_div[i].mclk == wm8737->mclk * 2) { - clocking |= WM8737_CLKDIV2; - break; - } - } - - if (i == ARRAY_SIZE(coeff_div)) { - dev_err(codec->dev, "%dHz MCLK can't support %dHz\n", - wm8737->mclk, params_rate(params)); - return -EINVAL; - } - - clocking |= coeff_div[i].usb | (coeff_div[i].sr << WM8737_SR_SHIFT); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - af |= 0x8; - break; - case SNDRV_PCM_FORMAT_S24_LE: - af |= 0x10; - break; - case SNDRV_PCM_FORMAT_S32_LE: - af |= 0x18; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8737_AUDIO_FORMAT, WM8737_WL_MASK, af); - snd_soc_update_bits(codec, WM8737_CLOCKING, - WM8737_USB_MODE | WM8737_CLKDIV2 | WM8737_SR_MASK, - clocking); - - return 0; -} - -static int wm8737_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (freq == coeff_div[i].mclk || - freq == coeff_div[i].mclk * 2) { - wm8737->mclk = freq; - return 0; - } - } - - dev_err(codec->dev, "MCLK rate %dHz not supported\n", freq); - - return -EINVAL; -} - - -static int wm8737_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 af = 0; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - af |= WM8737_MS; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - af |= 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - af |= 0x1; - break; - case SND_SOC_DAIFMT_DSP_A: - af |= 0x3; - break; - case SND_SOC_DAIFMT_DSP_B: - af |= 0x13; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - af |= WM8737_LRP; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8737_AUDIO_FORMAT, - WM8737_FORMAT_MASK | WM8737_LRP | WM8737_MS, af); - - return 0; -} - -static int wm8737_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID at 2*75k */ - snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, - WM8737_VMIDSEL_MASK, 0); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), - wm8737->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - - snd_soc_cache_sync(codec); - - /* Fast VMID ramp at 2*2.5k */ - snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, - WM8737_VMIDSEL_MASK, 0x4); - - /* Bring VMID up */ - snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT, - WM8737_VMID_MASK | - WM8737_VREF_MASK, - WM8737_VMID_MASK | - WM8737_VREF_MASK); - - msleep(500); - } - - /* VMID at 2*300k */ - snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, - WM8737_VMIDSEL_MASK, 2); - - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT, - WM8737_VMID_MASK | WM8737_VREF_MASK, 0); - - regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), - wm8737->supplies); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#define WM8737_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8737_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8737_dai_ops = { - .hw_params = wm8737_hw_params, - .set_sysclk = wm8737_set_dai_sysclk, - .set_fmt = wm8737_set_dai_fmt, -}; - -static struct snd_soc_dai_driver wm8737_dai = { - .name = "wm8737", - .capture = { - .stream_name = "Capture", - .channels_min = 2, /* Mono modes not yet supported */ - .channels_max = 2, - .rates = WM8737_RATES, - .formats = WM8737_FORMATS, - }, - .ops = &wm8737_dai_ops, -}; - -#ifdef CONFIG_PM -static int wm8737_suspend(struct snd_soc_codec *codec) -{ - wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8737_resume(struct snd_soc_codec *codec) -{ - wm8737_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define wm8737_suspend NULL -#define wm8737_resume NULL -#endif - -static int wm8737_probe(struct snd_soc_codec *codec) -{ - struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - int ret, i; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) - wm8737->supplies[i].supply = wm8737_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8737->supplies), - wm8737->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), - wm8737->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = wm8737_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - - snd_soc_update_bits(codec, WM8737_LEFT_PGA_VOLUME, WM8737_LVU, - WM8737_LVU); - snd_soc_update_bits(codec, WM8737_RIGHT_PGA_VOLUME, WM8737_RVU, - WM8737_RVU); - - wm8737_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); - - snd_soc_add_codec_controls(codec, wm8737_snd_controls, - ARRAY_SIZE(wm8737_snd_controls)); - wm8737_add_widgets(codec); - - return 0; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); - - return ret; -} - -static int wm8737_remove(struct snd_soc_codec *codec) -{ - struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); - - wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { - .probe = wm8737_probe, - .remove = wm8737_remove, - .suspend = wm8737_suspend, - .resume = wm8737_resume, - .set_bias_level = wm8737_set_bias_level, - - .reg_cache_size = WM8737_REGISTER_COUNT - 1, /* Skip reset */ - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8737_reg, -}; - -static const struct of_device_id wm8737_of_match[] = { - { .compatible = "wlf,wm8737", }, - { } -}; - -MODULE_DEVICE_TABLE(of, wm8737_of_match); - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8737_priv *wm8737; - int ret; - - wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); - if (wm8737 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8737); - wm8737->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8737, &wm8737_dai, 1); - if (ret < 0) - kfree(wm8737); - return ret; - -} - -static __devexit int wm8737_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8737_i2c_id[] = { - { "wm8737", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id); - -static struct i2c_driver wm8737_i2c_driver = { - .driver = { - .name = "wm8737", - .owner = THIS_MODULE, - .of_match_table = wm8737_of_match, - }, - .probe = wm8737_i2c_probe, - .remove = __devexit_p(wm8737_i2c_remove), - .id_table = wm8737_i2c_id, -}; -#endif - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8737_spi_probe(struct spi_device *spi) -{ - struct wm8737_priv *wm8737; - int ret; - - wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); - if (wm8737 == NULL) - return -ENOMEM; - - wm8737->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8737); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8737, &wm8737_dai, 1); - if (ret < 0) - kfree(wm8737); - return ret; -} - -static int __devexit wm8737_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); - return 0; -} - -static struct spi_driver wm8737_spi_driver = { - .driver = { - .name = "wm8737", - .owner = THIS_MODULE, - .of_match_table = wm8737_of_match, - }, - .probe = wm8737_spi_probe, - .remove = __devexit_p(wm8737_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -static int __init wm8737_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8737_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8737 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8737_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8737 SPI driver: %d\n", - ret); - } -#endif - return 0; -} -module_init(wm8737_modinit); - -static void __exit wm8737_exit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8737_spi_driver); -#endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8737_i2c_driver); -#endif -} -module_exit(wm8737_exit); - -MODULE_DESCRIPTION("ASoC WM8737 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8737.h b/ANDROID_3.4.5/sound/soc/codecs/wm8737.h deleted file mode 100644 index 23d14c8f..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8737.h +++ /dev/null @@ -1,322 +0,0 @@ -#ifndef _WM8737_H -#define _WM8737_H - -/* - * wm8737.c -- WM8523 ALSA SoC Audio driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * Register values. - */ -#define WM8737_LEFT_PGA_VOLUME 0x00 -#define WM8737_RIGHT_PGA_VOLUME 0x01 -#define WM8737_AUDIO_PATH_L 0x02 -#define WM8737_AUDIO_PATH_R 0x03 -#define WM8737_3D_ENHANCE 0x04 -#define WM8737_ADC_CONTROL 0x05 -#define WM8737_POWER_MANAGEMENT 0x06 -#define WM8737_AUDIO_FORMAT 0x07 -#define WM8737_CLOCKING 0x08 -#define WM8737_MIC_PREAMP_CONTROL 0x09 -#define WM8737_MISC_BIAS_CONTROL 0x0A -#define WM8737_NOISE_GATE 0x0B -#define WM8737_ALC1 0x0C -#define WM8737_ALC2 0x0D -#define WM8737_ALC3 0x0E -#define WM8737_RESET 0x0F - -#define WM8737_REGISTER_COUNT 16 -#define WM8737_MAX_REGISTER 0x0F - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Left PGA volume - */ -#define WM8737_LVU 0x0100 /* LVU */ -#define WM8737_LVU_MASK 0x0100 /* LVU */ -#define WM8737_LVU_SHIFT 8 /* LVU */ -#define WM8737_LVU_WIDTH 1 /* LVU */ -#define WM8737_LINVOL_MASK 0x00FF /* LINVOL - [7:0] */ -#define WM8737_LINVOL_SHIFT 0 /* LINVOL - [7:0] */ -#define WM8737_LINVOL_WIDTH 8 /* LINVOL - [7:0] */ - -/* - * R1 (0x01) - Right PGA volume - */ -#define WM8737_RVU 0x0100 /* RVU */ -#define WM8737_RVU_MASK 0x0100 /* RVU */ -#define WM8737_RVU_SHIFT 8 /* RVU */ -#define WM8737_RVU_WIDTH 1 /* RVU */ -#define WM8737_RINVOL_MASK 0x00FF /* RINVOL - [7:0] */ -#define WM8737_RINVOL_SHIFT 0 /* RINVOL - [7:0] */ -#define WM8737_RINVOL_WIDTH 8 /* RINVOL - [7:0] */ - -/* - * R2 (0x02) - AUDIO path L - */ -#define WM8737_LINSEL_MASK 0x0180 /* LINSEL - [8:7] */ -#define WM8737_LINSEL_SHIFT 7 /* LINSEL - [8:7] */ -#define WM8737_LINSEL_WIDTH 2 /* LINSEL - [8:7] */ -#define WM8737_LMICBOOST_MASK 0x0060 /* LMICBOOST - [6:5] */ -#define WM8737_LMICBOOST_SHIFT 5 /* LMICBOOST - [6:5] */ -#define WM8737_LMICBOOST_WIDTH 2 /* LMICBOOST - [6:5] */ -#define WM8737_LMBE 0x0010 /* LMBE */ -#define WM8737_LMBE_MASK 0x0010 /* LMBE */ -#define WM8737_LMBE_SHIFT 4 /* LMBE */ -#define WM8737_LMBE_WIDTH 1 /* LMBE */ -#define WM8737_LMZC 0x0008 /* LMZC */ -#define WM8737_LMZC_MASK 0x0008 /* LMZC */ -#define WM8737_LMZC_SHIFT 3 /* LMZC */ -#define WM8737_LMZC_WIDTH 1 /* LMZC */ -#define WM8737_LPZC 0x0004 /* LPZC */ -#define WM8737_LPZC_MASK 0x0004 /* LPZC */ -#define WM8737_LPZC_SHIFT 2 /* LPZC */ -#define WM8737_LPZC_WIDTH 1 /* LPZC */ -#define WM8737_LZCTO_MASK 0x0003 /* LZCTO - [1:0] */ -#define WM8737_LZCTO_SHIFT 0 /* LZCTO - [1:0] */ -#define WM8737_LZCTO_WIDTH 2 /* LZCTO - [1:0] */ - -/* - * R3 (0x03) - AUDIO path R - */ -#define WM8737_RINSEL_MASK 0x0180 /* RINSEL - [8:7] */ -#define WM8737_RINSEL_SHIFT 7 /* RINSEL - [8:7] */ -#define WM8737_RINSEL_WIDTH 2 /* RINSEL - [8:7] */ -#define WM8737_RMICBOOST_MASK 0x0060 /* RMICBOOST - [6:5] */ -#define WM8737_RMICBOOST_SHIFT 5 /* RMICBOOST - [6:5] */ -#define WM8737_RMICBOOST_WIDTH 2 /* RMICBOOST - [6:5] */ -#define WM8737_RMBE 0x0010 /* RMBE */ -#define WM8737_RMBE_MASK 0x0010 /* RMBE */ -#define WM8737_RMBE_SHIFT 4 /* RMBE */ -#define WM8737_RMBE_WIDTH 1 /* RMBE */ -#define WM8737_RMZC 0x0008 /* RMZC */ -#define WM8737_RMZC_MASK 0x0008 /* RMZC */ -#define WM8737_RMZC_SHIFT 3 /* RMZC */ -#define WM8737_RMZC_WIDTH 1 /* RMZC */ -#define WM8737_RPZC 0x0004 /* RPZC */ -#define WM8737_RPZC_MASK 0x0004 /* RPZC */ -#define WM8737_RPZC_SHIFT 2 /* RPZC */ -#define WM8737_RPZC_WIDTH 1 /* RPZC */ -#define WM8737_RZCTO_MASK 0x0003 /* RZCTO - [1:0] */ -#define WM8737_RZCTO_SHIFT 0 /* RZCTO - [1:0] */ -#define WM8737_RZCTO_WIDTH 2 /* RZCTO - [1:0] */ - -/* - * R4 (0x04) - 3D Enhance - */ -#define WM8737_DIV2 0x0080 /* DIV2 */ -#define WM8737_DIV2_MASK 0x0080 /* DIV2 */ -#define WM8737_DIV2_SHIFT 7 /* DIV2 */ -#define WM8737_DIV2_WIDTH 1 /* DIV2 */ -#define WM8737_3DLC 0x0040 /* 3DLC */ -#define WM8737_3DLC_MASK 0x0040 /* 3DLC */ -#define WM8737_3DLC_SHIFT 6 /* 3DLC */ -#define WM8737_3DLC_WIDTH 1 /* 3DLC */ -#define WM8737_3DUC 0x0020 /* 3DUC */ -#define WM8737_3DUC_MASK 0x0020 /* 3DUC */ -#define WM8737_3DUC_SHIFT 5 /* 3DUC */ -#define WM8737_3DUC_WIDTH 1 /* 3DUC */ -#define WM8737_3DDEPTH_MASK 0x001E /* 3DDEPTH - [4:1] */ -#define WM8737_3DDEPTH_SHIFT 1 /* 3DDEPTH - [4:1] */ -#define WM8737_3DDEPTH_WIDTH 4 /* 3DDEPTH - [4:1] */ -#define WM8737_3DE 0x0001 /* 3DE */ -#define WM8737_3DE_MASK 0x0001 /* 3DE */ -#define WM8737_3DE_SHIFT 0 /* 3DE */ -#define WM8737_3DE_WIDTH 1 /* 3DE */ - -/* - * R5 (0x05) - ADC Control - */ -#define WM8737_MONOMIX_MASK 0x0180 /* MONOMIX - [8:7] */ -#define WM8737_MONOMIX_SHIFT 7 /* MONOMIX - [8:7] */ -#define WM8737_MONOMIX_WIDTH 2 /* MONOMIX - [8:7] */ -#define WM8737_POLARITY_MASK 0x0060 /* POLARITY - [6:5] */ -#define WM8737_POLARITY_SHIFT 5 /* POLARITY - [6:5] */ -#define WM8737_POLARITY_WIDTH 2 /* POLARITY - [6:5] */ -#define WM8737_HPOR 0x0010 /* HPOR */ -#define WM8737_HPOR_MASK 0x0010 /* HPOR */ -#define WM8737_HPOR_SHIFT 4 /* HPOR */ -#define WM8737_HPOR_WIDTH 1 /* HPOR */ -#define WM8737_LP 0x0004 /* LP */ -#define WM8737_LP_MASK 0x0004 /* LP */ -#define WM8737_LP_SHIFT 2 /* LP */ -#define WM8737_LP_WIDTH 1 /* LP */ -#define WM8737_MONOUT 0x0002 /* MONOUT */ -#define WM8737_MONOUT_MASK 0x0002 /* MONOUT */ -#define WM8737_MONOUT_SHIFT 1 /* MONOUT */ -#define WM8737_MONOUT_WIDTH 1 /* MONOUT */ -#define WM8737_ADCHPD 0x0001 /* ADCHPD */ -#define WM8737_ADCHPD_MASK 0x0001 /* ADCHPD */ -#define WM8737_ADCHPD_SHIFT 0 /* ADCHPD */ -#define WM8737_ADCHPD_WIDTH 1 /* ADCHPD */ - -/* - * R6 (0x06) - Power Management - */ -#define WM8737_VMID 0x0100 /* VMID */ -#define WM8737_VMID_MASK 0x0100 /* VMID */ -#define WM8737_VMID_SHIFT 8 /* VMID */ -#define WM8737_VMID_WIDTH 1 /* VMID */ -#define WM8737_VREF 0x0080 /* VREF */ -#define WM8737_VREF_MASK 0x0080 /* VREF */ -#define WM8737_VREF_SHIFT 7 /* VREF */ -#define WM8737_VREF_WIDTH 1 /* VREF */ -#define WM8737_AI 0x0040 /* AI */ -#define WM8737_AI_MASK 0x0040 /* AI */ -#define WM8737_AI_SHIFT 6 /* AI */ -#define WM8737_AI_WIDTH 1 /* AI */ -#define WM8737_PGL 0x0020 /* PGL */ -#define WM8737_PGL_MASK 0x0020 /* PGL */ -#define WM8737_PGL_SHIFT 5 /* PGL */ -#define WM8737_PGL_WIDTH 1 /* PGL */ -#define WM8737_PGR 0x0010 /* PGR */ -#define WM8737_PGR_MASK 0x0010 /* PGR */ -#define WM8737_PGR_SHIFT 4 /* PGR */ -#define WM8737_PGR_WIDTH 1 /* PGR */ -#define WM8737_ADL 0x0008 /* ADL */ -#define WM8737_ADL_MASK 0x0008 /* ADL */ -#define WM8737_ADL_SHIFT 3 /* ADL */ -#define WM8737_ADL_WIDTH 1 /* ADL */ -#define WM8737_ADR 0x0004 /* ADR */ -#define WM8737_ADR_MASK 0x0004 /* ADR */ -#define WM8737_ADR_SHIFT 2 /* ADR */ -#define WM8737_ADR_WIDTH 1 /* ADR */ -#define WM8737_MICBIAS_MASK 0x0003 /* MICBIAS - [1:0] */ -#define WM8737_MICBIAS_SHIFT 0 /* MICBIAS - [1:0] */ -#define WM8737_MICBIAS_WIDTH 2 /* MICBIAS - [1:0] */ - -/* - * R7 (0x07) - Audio Format - */ -#define WM8737_SDODIS 0x0080 /* SDODIS */ -#define WM8737_SDODIS_MASK 0x0080 /* SDODIS */ -#define WM8737_SDODIS_SHIFT 7 /* SDODIS */ -#define WM8737_SDODIS_WIDTH 1 /* SDODIS */ -#define WM8737_MS 0x0040 /* MS */ -#define WM8737_MS_MASK 0x0040 /* MS */ -#define WM8737_MS_SHIFT 6 /* MS */ -#define WM8737_MS_WIDTH 1 /* MS */ -#define WM8737_LRP 0x0010 /* LRP */ -#define WM8737_LRP_MASK 0x0010 /* LRP */ -#define WM8737_LRP_SHIFT 4 /* LRP */ -#define WM8737_LRP_WIDTH 1 /* LRP */ -#define WM8737_WL_MASK 0x000C /* WL - [3:2] */ -#define WM8737_WL_SHIFT 2 /* WL - [3:2] */ -#define WM8737_WL_WIDTH 2 /* WL - [3:2] */ -#define WM8737_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */ -#define WM8737_FORMAT_SHIFT 0 /* FORMAT - [1:0] */ -#define WM8737_FORMAT_WIDTH 2 /* FORMAT - [1:0] */ - -/* - * R8 (0x08) - Clocking - */ -#define WM8737_AUTODETECT 0x0080 /* AUTODETECT */ -#define WM8737_AUTODETECT_MASK 0x0080 /* AUTODETECT */ -#define WM8737_AUTODETECT_SHIFT 7 /* AUTODETECT */ -#define WM8737_AUTODETECT_WIDTH 1 /* AUTODETECT */ -#define WM8737_CLKDIV2 0x0040 /* CLKDIV2 */ -#define WM8737_CLKDIV2_MASK 0x0040 /* CLKDIV2 */ -#define WM8737_CLKDIV2_SHIFT 6 /* CLKDIV2 */ -#define WM8737_CLKDIV2_WIDTH 1 /* CLKDIV2 */ -#define WM8737_SR_MASK 0x003E /* SR - [5:1] */ -#define WM8737_SR_SHIFT 1 /* SR - [5:1] */ -#define WM8737_SR_WIDTH 5 /* SR - [5:1] */ -#define WM8737_USB_MODE 0x0001 /* USB MODE */ -#define WM8737_USB_MODE_MASK 0x0001 /* USB MODE */ -#define WM8737_USB_MODE_SHIFT 0 /* USB MODE */ -#define WM8737_USB_MODE_WIDTH 1 /* USB MODE */ - -/* - * R9 (0x09) - MIC Preamp Control - */ -#define WM8737_RBYPEN 0x0008 /* RBYPEN */ -#define WM8737_RBYPEN_MASK 0x0008 /* RBYPEN */ -#define WM8737_RBYPEN_SHIFT 3 /* RBYPEN */ -#define WM8737_RBYPEN_WIDTH 1 /* RBYPEN */ -#define WM8737_LBYPEN 0x0004 /* LBYPEN */ -#define WM8737_LBYPEN_MASK 0x0004 /* LBYPEN */ -#define WM8737_LBYPEN_SHIFT 2 /* LBYPEN */ -#define WM8737_LBYPEN_WIDTH 1 /* LBYPEN */ -#define WM8737_MBCTRL_MASK 0x0003 /* MBCTRL - [1:0] */ -#define WM8737_MBCTRL_SHIFT 0 /* MBCTRL - [1:0] */ -#define WM8737_MBCTRL_WIDTH 2 /* MBCTRL - [1:0] */ - -/* - * R10 (0x0A) - Misc Bias Control - */ -#define WM8737_VMIDSEL_MASK 0x000C /* VMIDSEL - [3:2] */ -#define WM8737_VMIDSEL_SHIFT 2 /* VMIDSEL - [3:2] */ -#define WM8737_VMIDSEL_WIDTH 2 /* VMIDSEL - [3:2] */ -#define WM8737_LINPUT1_DC_BIAS_ENABLE 0x0002 /* LINPUT1 DC BIAS ENABLE */ -#define WM8737_LINPUT1_DC_BIAS_ENABLE_MASK 0x0002 /* LINPUT1 DC BIAS ENABLE */ -#define WM8737_LINPUT1_DC_BIAS_ENABLE_SHIFT 1 /* LINPUT1 DC BIAS ENABLE */ -#define WM8737_LINPUT1_DC_BIAS_ENABLE_WIDTH 1 /* LINPUT1 DC BIAS ENABLE */ -#define WM8737_RINPUT1_DC_BIAS_ENABLE 0x0001 /* RINPUT1 DC BIAS ENABLE */ -#define WM8737_RINPUT1_DC_BIAS_ENABLE_MASK 0x0001 /* RINPUT1 DC BIAS ENABLE */ -#define WM8737_RINPUT1_DC_BIAS_ENABLE_SHIFT 0 /* RINPUT1 DC BIAS ENABLE */ -#define WM8737_RINPUT1_DC_BIAS_ENABLE_WIDTH 1 /* RINPUT1 DC BIAS ENABLE */ - -/* - * R11 (0x0B) - Noise Gate - */ -#define WM8737_NGTH_MASK 0x001C /* NGTH - [4:2] */ -#define WM8737_NGTH_SHIFT 2 /* NGTH - [4:2] */ -#define WM8737_NGTH_WIDTH 3 /* NGTH - [4:2] */ -#define WM8737_NGAT 0x0001 /* NGAT */ -#define WM8737_NGAT_MASK 0x0001 /* NGAT */ -#define WM8737_NGAT_SHIFT 0 /* NGAT */ -#define WM8737_NGAT_WIDTH 1 /* NGAT */ - -/* - * R12 (0x0C) - ALC1 - */ -#define WM8737_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */ -#define WM8737_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */ -#define WM8737_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */ -#define WM8737_MAX_GAIN_MASK 0x0070 /* MAX GAIN - [6:4] */ -#define WM8737_MAX_GAIN_SHIFT 4 /* MAX GAIN - [6:4] */ -#define WM8737_MAX_GAIN_WIDTH 3 /* MAX GAIN - [6:4] */ -#define WM8737_ALCL_MASK 0x000F /* ALCL - [3:0] */ -#define WM8737_ALCL_SHIFT 0 /* ALCL - [3:0] */ -#define WM8737_ALCL_WIDTH 4 /* ALCL - [3:0] */ - -/* - * R13 (0x0D) - ALC2 - */ -#define WM8737_ALCZCE 0x0010 /* ALCZCE */ -#define WM8737_ALCZCE_MASK 0x0010 /* ALCZCE */ -#define WM8737_ALCZCE_SHIFT 4 /* ALCZCE */ -#define WM8737_ALCZCE_WIDTH 1 /* ALCZCE */ -#define WM8737_HLD_MASK 0x000F /* HLD - [3:0] */ -#define WM8737_HLD_SHIFT 0 /* HLD - [3:0] */ -#define WM8737_HLD_WIDTH 4 /* HLD - [3:0] */ - -/* - * R14 (0x0E) - ALC3 - */ -#define WM8737_DCY_MASK 0x00F0 /* DCY - [7:4] */ -#define WM8737_DCY_SHIFT 4 /* DCY - [7:4] */ -#define WM8737_DCY_WIDTH 4 /* DCY - [7:4] */ -#define WM8737_ATK_MASK 0x000F /* ATK - [3:0] */ -#define WM8737_ATK_SHIFT 0 /* ATK - [3:0] */ -#define WM8737_ATK_WIDTH 4 /* ATK - [3:0] */ - -/* - * R15 (0x0F) - Reset - */ -#define WM8737_RESET_MASK 0x01FF /* RESET - [8:0] */ -#define WM8737_RESET_SHIFT 0 /* RESET - [8:0] */ -#define WM8737_RESET_WIDTH 9 /* RESET - [8:0] */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8741.c b/ANDROID_3.4.5/sound/soc/codecs/wm8741.c deleted file mode 100644 index 3941f50b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8741.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - * wm8741.c -- WM8741 ALSA SoC Audio driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Ian Lartey - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8741.h" - -#define WM8741_NUM_SUPPLIES 2 -static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { - "AVDD", - "DVDD", -}; - -#define WM8741_NUM_RATES 6 - -/* codec private data */ -struct wm8741_priv { - enum snd_soc_control_type control_type; - struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; - unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; -}; - -static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = { - 0x0000, /* R0 - DACLLSB Attenuation */ - 0x0000, /* R1 - DACLMSB Attenuation */ - 0x0000, /* R2 - DACRLSB Attenuation */ - 0x0000, /* R3 - DACRMSB Attenuation */ - 0x0000, /* R4 - Volume Control */ - 0x000A, /* R5 - Format Control */ - 0x0000, /* R6 - Filter Control */ - 0x0000, /* R7 - Mode Control 1 */ - 0x0002, /* R8 - Mode Control 2 */ - 0x0000, /* R9 - Reset */ - 0x0002, /* R32 - ADDITONAL_CONTROL_1 */ -}; - - -static int wm8741_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8741_RESET, 0); -} - -static const DECLARE_TLV_DB_SCALE(dac_tlv_fine, -12700, 13, 0); -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 400, 0); - -static const struct snd_kcontrol_new wm8741_snd_controls[] = { -SOC_DOUBLE_R_TLV("Fine Playback Volume", WM8741_DACLLSB_ATTENUATION, - WM8741_DACRLSB_ATTENUATION, 1, 255, 1, dac_tlv_fine), -SOC_DOUBLE_R_TLV("Playback Volume", WM8741_DACLMSB_ATTENUATION, - WM8741_DACRMSB_ATTENUATION, 0, 511, 1, dac_tlv), -}; - -static const struct snd_soc_dapm_widget wm8741_dapm_widgets[] = { -SND_SOC_DAPM_DAC("DACL", "Playback", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_DAC("DACR", "Playback", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_OUTPUT("VOUTLP"), -SND_SOC_DAPM_OUTPUT("VOUTLN"), -SND_SOC_DAPM_OUTPUT("VOUTRP"), -SND_SOC_DAPM_OUTPUT("VOUTRN"), -}; - -static const struct snd_soc_dapm_route wm8741_dapm_routes[] = { - { "VOUTLP", NULL, "DACL" }, - { "VOUTLN", NULL, "DACL" }, - { "VOUTRP", NULL, "DACR" }, - { "VOUTRN", NULL, "DACR" }, -}; - -static struct { - int value; - int ratio; -} lrclk_ratios[WM8741_NUM_RATES] = { - { 1, 128 }, - { 2, 192 }, - { 3, 256 }, - { 4, 384 }, - { 5, 512 }, - { 6, 768 }, -}; - -static unsigned int rates_11289[] = { - 44100, 88235, -}; - -static struct snd_pcm_hw_constraint_list constraints_11289 = { - .count = ARRAY_SIZE(rates_11289), - .list = rates_11289, -}; - -static unsigned int rates_12288[] = { - 32000, 48000, 96000, -}; - -static struct snd_pcm_hw_constraint_list constraints_12288 = { - .count = ARRAY_SIZE(rates_12288), - .list = rates_12288, -}; - -static unsigned int rates_16384[] = { - 32000, -}; - -static struct snd_pcm_hw_constraint_list constraints_16384 = { - .count = ARRAY_SIZE(rates_16384), - .list = rates_16384, -}; - -static unsigned int rates_16934[] = { - 44100, 88235, -}; - -static struct snd_pcm_hw_constraint_list constraints_16934 = { - .count = ARRAY_SIZE(rates_16934), - .list = rates_16934, -}; - -static unsigned int rates_18432[] = { - 48000, 96000, -}; - -static struct snd_pcm_hw_constraint_list constraints_18432 = { - .count = ARRAY_SIZE(rates_18432), - .list = rates_18432, -}; - -static unsigned int rates_22579[] = { - 44100, 88235, 1764000 -}; - -static struct snd_pcm_hw_constraint_list constraints_22579 = { - .count = ARRAY_SIZE(rates_22579), - .list = rates_22579, -}; - -static unsigned int rates_24576[] = { - 32000, 48000, 96000, 192000 -}; - -static struct snd_pcm_hw_constraint_list constraints_24576 = { - .count = ARRAY_SIZE(rates_24576), - .list = rates_24576, -}; - -static unsigned int rates_36864[] = { - 48000, 96000, 19200 -}; - -static struct snd_pcm_hw_constraint_list constraints_36864 = { - .count = ARRAY_SIZE(rates_36864), - .list = rates_36864, -}; - - -static int wm8741_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); - - /* The set of sample rates that can be supported depends on the - * MCLK supplied to the CODEC - enforce this. - */ - if (!wm8741->sysclk) { - dev_err(codec->dev, - "No MCLK configured, call set_sysclk() on init\n"); - return -EINVAL; - } - - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - wm8741->sysclk_constraints); - - return 0; -} - -static int wm8741_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; - int i; - - /* Find a supported LRCLK ratio */ - for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { - if (wm8741->sysclk / params_rate(params) == - lrclk_ratios[i].ratio) - break; - } - - /* Should never happen, should be handled by constraints */ - if (i == ARRAY_SIZE(lrclk_ratios)) { - dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n", - wm8741->sysclk / params_rate(params)); - return -EINVAL; - } - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0001; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0002; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x0003; - break; - default: - dev_dbg(codec->dev, "wm8741_hw_params: Unsupported bit size param = %d", - params_format(params)); - return -EINVAL; - } - - dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d", - params_format(params)); - - snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface); - return 0; -} - -static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); - - dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq); - - switch (freq) { - case 11289600: - wm8741->sysclk_constraints = &constraints_11289; - wm8741->sysclk = freq; - return 0; - - case 12288000: - wm8741->sysclk_constraints = &constraints_12288; - wm8741->sysclk = freq; - return 0; - - case 16384000: - wm8741->sysclk_constraints = &constraints_16384; - wm8741->sysclk = freq; - return 0; - - case 16934400: - wm8741->sysclk_constraints = &constraints_16934; - wm8741->sysclk = freq; - return 0; - - case 18432000: - wm8741->sysclk_constraints = &constraints_18432; - wm8741->sysclk = freq; - return 0; - - case 22579200: - case 33868800: - wm8741->sysclk_constraints = &constraints_22579; - wm8741->sysclk = freq; - return 0; - - case 24576000: - wm8741->sysclk_constraints = &constraints_24576; - wm8741->sysclk = freq; - return 0; - - case 36864000: - wm8741->sysclk_constraints = &constraints_36864; - wm8741->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1C3; - - /* check master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0008; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0004; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x000C; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x001C; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0010; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0020; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0030; - break; - default: - return -EINVAL; - } - - - dev_dbg(codec->dev, "wm8741_set_dai_fmt: Format=%x, Clock Inv=%x\n", - fmt & SND_SOC_DAIFMT_FORMAT_MASK, - ((fmt & SND_SOC_DAIFMT_INV_MASK))); - - snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface); - return 0; -} - -#define WM8741_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ - SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \ - SNDRV_PCM_RATE_192000) - -#define WM8741_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8741_dai_ops = { - .startup = wm8741_startup, - .hw_params = wm8741_hw_params, - .set_sysclk = wm8741_set_dai_sysclk, - .set_fmt = wm8741_set_dai_fmt, -}; - -static struct snd_soc_dai_driver wm8741_dai = { - .name = "wm8741", - .playback = { - .stream_name = "Playback", - .channels_min = 2, /* Mono modes not yet supported */ - .channels_max = 2, - .rates = WM8741_RATES, - .formats = WM8741_FORMATS, - }, - .ops = &wm8741_dai_ops, -}; - -#ifdef CONFIG_PM -static int wm8741_resume(struct snd_soc_codec *codec) -{ - snd_soc_cache_sync(codec); - return 0; -} -#else -#define wm8741_suspend NULL -#define wm8741_resume NULL -#endif - -static int wm8741_probe(struct snd_soc_codec *codec) -{ - struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) - wm8741->supplies[i].supply = wm8741_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), - wm8741->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), - wm8741->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err_enable; - } - - ret = wm8741_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - - /* Change some default settings - latch VU */ - snd_soc_update_bits(codec, WM8741_DACLLSB_ATTENUATION, - WM8741_UPDATELL, WM8741_UPDATELL); - snd_soc_update_bits(codec, WM8741_DACLMSB_ATTENUATION, - WM8741_UPDATELM, WM8741_UPDATELM); - snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION, - WM8741_UPDATERL, WM8741_UPDATERL); - snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION, - WM8741_UPDATERM, WM8741_UPDATERM); - - dev_dbg(codec->dev, "Successful registration\n"); - return ret; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); -err: - return ret; -} - -static int wm8741_remove(struct snd_soc_codec *codec) -{ - struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); - - regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { - .probe = wm8741_probe, - .remove = wm8741_remove, - .resume = wm8741_resume, - .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8741_reg_defaults, - - .controls = wm8741_snd_controls, - .num_controls = ARRAY_SIZE(wm8741_snd_controls), - .dapm_widgets = wm8741_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets), - .dapm_routes = wm8741_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes), -}; - -static const struct of_device_id wm8741_of_match[] = { - { .compatible = "wlf,wm8741", }, - { } -}; -MODULE_DEVICE_TABLE(of, wm8741_of_match); - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int wm8741_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8741_priv *wm8741; - int ret; - - wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv), - GFP_KERNEL); - if (wm8741 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8741); - wm8741->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8741, &wm8741_dai, 1); - - return ret; -} - -static int wm8741_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id wm8741_i2c_id[] = { - { "wm8741", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); - -static struct i2c_driver wm8741_i2c_driver = { - .driver = { - .name = "wm8741", - .owner = THIS_MODULE, - .of_match_table = wm8741_of_match, - }, - .probe = wm8741_i2c_probe, - .remove = wm8741_i2c_remove, - .id_table = wm8741_i2c_id, -}; -#endif - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8741_spi_probe(struct spi_device *spi) -{ - struct wm8741_priv *wm8741; - int ret; - - wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv), - GFP_KERNEL); - if (wm8741 == NULL) - return -ENOMEM; - - wm8741->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8741); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8741, &wm8741_dai, 1); - return ret; -} - -static int __devexit wm8741_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver wm8741_spi_driver = { - .driver = { - .name = "wm8741", - .owner = THIS_MODULE, - .of_match_table = wm8741_of_match, - }, - .probe = wm8741_spi_probe, - .remove = __devexit_p(wm8741_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -static int __init wm8741_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8741_i2c_driver); - if (ret != 0) - pr_err("Failed to register WM8741 I2C driver: %d\n", ret); -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8741_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n", - ret); - } -#endif - - return ret; -} -module_init(wm8741_modinit); - -static void __exit wm8741_exit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8741_spi_driver); -#endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8741_i2c_driver); -#endif -} -module_exit(wm8741_exit); - -MODULE_DESCRIPTION("ASoC WM8741 driver"); -MODULE_AUTHOR("Ian Lartey "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8741.h b/ANDROID_3.4.5/sound/soc/codecs/wm8741.h deleted file mode 100644 index 56c1b1d4..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8741.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * wm8741.h -- WM8423 ASoC driver - * - * Copyright 2010 Wolfson Microelectronics, plc - * - * Author: Ian Lartey - * - * Based on wm8753.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8741_H -#define _WM8741_H - -/* - * Register values. - */ -#define WM8741_DACLLSB_ATTENUATION 0x00 -#define WM8741_DACLMSB_ATTENUATION 0x01 -#define WM8741_DACRLSB_ATTENUATION 0x02 -#define WM8741_DACRMSB_ATTENUATION 0x03 -#define WM8741_VOLUME_CONTROL 0x04 -#define WM8741_FORMAT_CONTROL 0x05 -#define WM8741_FILTER_CONTROL 0x06 -#define WM8741_MODE_CONTROL_1 0x07 -#define WM8741_MODE_CONTROL_2 0x08 -#define WM8741_RESET 0x09 -#define WM8741_ADDITIONAL_CONTROL_1 0x20 - -#define WM8741_REGISTER_COUNT 11 -#define WM8741_MAX_REGISTER 0x20 - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - DACLLSB_ATTENUATION - */ -#define WM8741_UPDATELL 0x0020 /* UPDATELL */ -#define WM8741_UPDATELL_MASK 0x0020 /* UPDATELL */ -#define WM8741_UPDATELL_SHIFT 5 /* UPDATELL */ -#define WM8741_UPDATELL_WIDTH 1 /* UPDATELL */ -#define WM8741_LAT_4_0_MASK 0x001F /* LAT[4:0] - [4:0] */ -#define WM8741_LAT_4_0_SHIFT 0 /* LAT[4:0] - [4:0] */ -#define WM8741_LAT_4_0_WIDTH 5 /* LAT[4:0] - [4:0] */ - -/* - * R1 (0x01) - DACLMSB_ATTENUATION - */ -#define WM8741_UPDATELM 0x0020 /* UPDATELM */ -#define WM8741_UPDATELM_MASK 0x0020 /* UPDATELM */ -#define WM8741_UPDATELM_SHIFT 5 /* UPDATELM */ -#define WM8741_UPDATELM_WIDTH 1 /* UPDATELM */ -#define WM8741_LAT_9_5_0_MASK 0x001F /* LAT[9:5] - [4:0] */ -#define WM8741_LAT_9_5_0_SHIFT 0 /* LAT[9:5] - [4:0] */ -#define WM8741_LAT_9_5_0_WIDTH 5 /* LAT[9:5] - [4:0] */ - -/* - * R2 (0x02) - DACRLSB_ATTENUATION - */ -#define WM8741_UPDATERL 0x0020 /* UPDATERL */ -#define WM8741_UPDATERL_MASK 0x0020 /* UPDATERL */ -#define WM8741_UPDATERL_SHIFT 5 /* UPDATERL */ -#define WM8741_UPDATERL_WIDTH 1 /* UPDATERL */ -#define WM8741_RAT_4_0_MASK 0x001F /* RAT[4:0] - [4:0] */ -#define WM8741_RAT_4_0_SHIFT 0 /* RAT[4:0] - [4:0] */ -#define WM8741_RAT_4_0_WIDTH 5 /* RAT[4:0] - [4:0] */ - -/* - * R3 (0x03) - DACRMSB_ATTENUATION - */ -#define WM8741_UPDATERM 0x0020 /* UPDATERM */ -#define WM8741_UPDATERM_MASK 0x0020 /* UPDATERM */ -#define WM8741_UPDATERM_SHIFT 5 /* UPDATERM */ -#define WM8741_UPDATERM_WIDTH 1 /* UPDATERM */ -#define WM8741_RAT_9_5_0_MASK 0x001F /* RAT[9:5] - [4:0] */ -#define WM8741_RAT_9_5_0_SHIFT 0 /* RAT[9:5] - [4:0] */ -#define WM8741_RAT_9_5_0_WIDTH 5 /* RAT[9:5] - [4:0] */ - -/* - * R4 (0x04) - VOLUME_CONTROL - */ -#define WM8741_AMUTE 0x0080 /* AMUTE */ -#define WM8741_AMUTE_MASK 0x0080 /* AMUTE */ -#define WM8741_AMUTE_SHIFT 7 /* AMUTE */ -#define WM8741_AMUTE_WIDTH 1 /* AMUTE */ -#define WM8741_ZFLAG_MASK 0x0060 /* ZFLAG - [6:5] */ -#define WM8741_ZFLAG_SHIFT 5 /* ZFLAG - [6:5] */ -#define WM8741_ZFLAG_WIDTH 2 /* ZFLAG - [6:5] */ -#define WM8741_IZD 0x0010 /* IZD */ -#define WM8741_IZD_MASK 0x0010 /* IZD */ -#define WM8741_IZD_SHIFT 4 /* IZD */ -#define WM8741_IZD_WIDTH 1 /* IZD */ -#define WM8741_SOFT 0x0008 /* SOFT MUTE */ -#define WM8741_SOFT_MASK 0x0008 /* SOFT MUTE */ -#define WM8741_SOFT_SHIFT 3 /* SOFT MUTE */ -#define WM8741_SOFT_WIDTH 1 /* SOFT MUTE */ -#define WM8741_ATC 0x0004 /* ATC */ -#define WM8741_ATC_MASK 0x0004 /* ATC */ -#define WM8741_ATC_SHIFT 2 /* ATC */ -#define WM8741_ATC_WIDTH 1 /* ATC */ -#define WM8741_ATT2DB 0x0002 /* ATT2DB */ -#define WM8741_ATT2DB_MASK 0x0002 /* ATT2DB */ -#define WM8741_ATT2DB_SHIFT 1 /* ATT2DB */ -#define WM8741_ATT2DB_WIDTH 1 /* ATT2DB */ -#define WM8741_VOL_RAMP 0x0001 /* VOL_RAMP */ -#define WM8741_VOL_RAMP_MASK 0x0001 /* VOL_RAMP */ -#define WM8741_VOL_RAMP_SHIFT 0 /* VOL_RAMP */ -#define WM8741_VOL_RAMP_WIDTH 1 /* VOL_RAMP */ - -/* - * R5 (0x05) - FORMAT_CONTROL - */ -#define WM8741_PWDN 0x0080 /* PWDN */ -#define WM8741_PWDN_MASK 0x0080 /* PWDN */ -#define WM8741_PWDN_SHIFT 7 /* PWDN */ -#define WM8741_PWDN_WIDTH 1 /* PWDN */ -#define WM8741_REV 0x0040 /* REV */ -#define WM8741_REV_MASK 0x0040 /* REV */ -#define WM8741_REV_SHIFT 6 /* REV */ -#define WM8741_REV_WIDTH 1 /* REV */ -#define WM8741_BCP 0x0020 /* BCP */ -#define WM8741_BCP_MASK 0x0020 /* BCP */ -#define WM8741_BCP_SHIFT 5 /* BCP */ -#define WM8741_BCP_WIDTH 1 /* BCP */ -#define WM8741_LRP 0x0010 /* LRP */ -#define WM8741_LRP_MASK 0x0010 /* LRP */ -#define WM8741_LRP_SHIFT 4 /* LRP */ -#define WM8741_LRP_WIDTH 1 /* LRP */ -#define WM8741_FMT_MASK 0x000C /* FMT - [3:2] */ -#define WM8741_FMT_SHIFT 2 /* FMT - [3:2] */ -#define WM8741_FMT_WIDTH 2 /* FMT - [3:2] */ -#define WM8741_IWL_MASK 0x0003 /* IWL - [1:0] */ -#define WM8741_IWL_SHIFT 0 /* IWL - [1:0] */ -#define WM8741_IWL_WIDTH 2 /* IWL - [1:0] */ - -/* - * R6 (0x06) - FILTER_CONTROL - */ -#define WM8741_ZFLAG_HI 0x0080 /* ZFLAG_HI */ -#define WM8741_ZFLAG_HI_MASK 0x0080 /* ZFLAG_HI */ -#define WM8741_ZFLAG_HI_SHIFT 7 /* ZFLAG_HI */ -#define WM8741_ZFLAG_HI_WIDTH 1 /* ZFLAG_HI */ -#define WM8741_DEEMPH_MASK 0x0060 /* DEEMPH - [6:5] */ -#define WM8741_DEEMPH_SHIFT 5 /* DEEMPH - [6:5] */ -#define WM8741_DEEMPH_WIDTH 2 /* DEEMPH - [6:5] */ -#define WM8741_DSDFILT_MASK 0x0018 /* DSDFILT - [4:3] */ -#define WM8741_DSDFILT_SHIFT 3 /* DSDFILT - [4:3] */ -#define WM8741_DSDFILT_WIDTH 2 /* DSDFILT - [4:3] */ -#define WM8741_FIRSEL_MASK 0x0007 /* FIRSEL - [2:0] */ -#define WM8741_FIRSEL_SHIFT 0 /* FIRSEL - [2:0] */ -#define WM8741_FIRSEL_WIDTH 3 /* FIRSEL - [2:0] */ - -/* - * R7 (0x07) - MODE_CONTROL_1 - */ -#define WM8741_MODE8X 0x0080 /* MODE8X */ -#define WM8741_MODE8X_MASK 0x0080 /* MODE8X */ -#define WM8741_MODE8X_SHIFT 7 /* MODE8X */ -#define WM8741_MODE8X_WIDTH 1 /* MODE8X */ -#define WM8741_OSR_MASK 0x0060 /* OSR - [6:5] */ -#define WM8741_OSR_SHIFT 5 /* OSR - [6:5] */ -#define WM8741_OSR_WIDTH 2 /* OSR - [6:5] */ -#define WM8741_SR_MASK 0x001C /* SR - [4:2] */ -#define WM8741_SR_SHIFT 2 /* SR - [4:2] */ -#define WM8741_SR_WIDTH 3 /* SR - [4:2] */ -#define WM8741_MODESEL_MASK 0x0003 /* MODESEL - [1:0] */ -#define WM8741_MODESEL_SHIFT 0 /* MODESEL - [1:0] */ -#define WM8741_MODESEL_WIDTH 2 /* MODESEL - [1:0] */ - -/* - * R8 (0x08) - MODE_CONTROL_2 - */ -#define WM8741_DSD_GAIN 0x0040 /* DSD_GAIN */ -#define WM8741_DSD_GAIN_MASK 0x0040 /* DSD_GAIN */ -#define WM8741_DSD_GAIN_SHIFT 6 /* DSD_GAIN */ -#define WM8741_DSD_GAIN_WIDTH 1 /* DSD_GAIN */ -#define WM8741_SDOUT 0x0020 /* SDOUT */ -#define WM8741_SDOUT_MASK 0x0020 /* SDOUT */ -#define WM8741_SDOUT_SHIFT 5 /* SDOUT */ -#define WM8741_SDOUT_WIDTH 1 /* SDOUT */ -#define WM8741_DOUT 0x0010 /* DOUT */ -#define WM8741_DOUT_MASK 0x0010 /* DOUT */ -#define WM8741_DOUT_SHIFT 4 /* DOUT */ -#define WM8741_DOUT_WIDTH 1 /* DOUT */ -#define WM8741_DIFF_MASK 0x000C /* DIFF - [3:2] */ -#define WM8741_DIFF_SHIFT 2 /* DIFF - [3:2] */ -#define WM8741_DIFF_WIDTH 2 /* DIFF - [3:2] */ -#define WM8741_DITHER_MASK 0x0003 /* DITHER - [1:0] */ -#define WM8741_DITHER_SHIFT 0 /* DITHER - [1:0] */ -#define WM8741_DITHER_WIDTH 2 /* DITHER - [1:0] */ - -/* - * R32 (0x20) - ADDITONAL_CONTROL_1 - */ -#define WM8741_DSD_LEVEL 0x0002 /* DSD_LEVEL */ -#define WM8741_DSD_LEVEL_MASK 0x0002 /* DSD_LEVEL */ -#define WM8741_DSD_LEVEL_SHIFT 1 /* DSD_LEVEL */ -#define WM8741_DSD_LEVEL_WIDTH 1 /* DSD_LEVEL */ -#define WM8741_DSD_NO_NOTCH 0x0001 /* DSD_NO_NOTCH */ -#define WM8741_DSD_NO_NOTCH_MASK 0x0001 /* DSD_NO_NOTCH */ -#define WM8741_DSD_NO_NOTCH_SHIFT 0 /* DSD_NO_NOTCH */ -#define WM8741_DSD_NO_NOTCH_WIDTH 1 /* DSD_NO_NOTCH */ - -#define WM8741_SYSCLK 0 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8750.c b/ANDROID_3.4.5/sound/soc/codecs/wm8750.c deleted file mode 100644 index e4c50ce7..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8750.c +++ /dev/null @@ -1,857 +0,0 @@ -/* - * wm8750.c -- WM8750 ALSA SoC audio driver - * - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie - * - * Based on WM8753.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8750.h" - -/* - * wm8750 register cache - * We can't read the WM8750 register space when we - * are using 2 wire for device control, so we cache them instead. - */ -static const u16 wm8750_reg[] = { - 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */ - 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */ - 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */ - 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */ - 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */ - 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ - 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */ - 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */ - 0x0079, 0x0079, 0x0079, /* 40 */ -}; - -/* codec private data */ -struct wm8750_priv { - unsigned int sysclk; - enum snd_soc_control_type control_type; -}; - -#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) - -/* - * WM8750 Controls - */ -static const char *wm8750_bass[] = {"Linear Control", "Adaptive Boost"}; -static const char *wm8750_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; -static const char *wm8750_treble[] = {"8kHz", "4kHz"}; -static const char *wm8750_3d_lc[] = {"200Hz", "500Hz"}; -static const char *wm8750_3d_uc[] = {"2.2kHz", "1.5kHz"}; -static const char *wm8750_3d_func[] = {"Capture", "Playback"}; -static const char *wm8750_alc_func[] = {"Off", "Right", "Left", "Stereo"}; -static const char *wm8750_ng_type[] = {"Constant PGA Gain", - "Mute ADC Output"}; -static const char *wm8750_line_mux[] = {"Line 1", "Line 2", "Line 3", "PGA", - "Differential"}; -static const char *wm8750_pga_sel[] = {"Line 1", "Line 2", "Line 3", - "Differential"}; -static const char *wm8750_out3[] = {"VREF", "ROUT1 + Vol", "MonoOut", - "ROUT1"}; -static const char *wm8750_diff_sel[] = {"Line 1", "Line 2"}; -static const char *wm8750_adcpol[] = {"Normal", "L Invert", "R Invert", - "L + R Invert"}; -static const char *wm8750_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const char *wm8750_mono_mux[] = {"Stereo", "Mono (Left)", - "Mono (Right)", "Digital Mono"}; - -static const struct soc_enum wm8750_enum[] = { -SOC_ENUM_SINGLE(WM8750_BASS, 7, 2, wm8750_bass), -SOC_ENUM_SINGLE(WM8750_BASS, 6, 2, wm8750_bass_filter), -SOC_ENUM_SINGLE(WM8750_TREBLE, 6, 2, wm8750_treble), -SOC_ENUM_SINGLE(WM8750_3D, 5, 2, wm8750_3d_lc), -SOC_ENUM_SINGLE(WM8750_3D, 6, 2, wm8750_3d_uc), -SOC_ENUM_SINGLE(WM8750_3D, 7, 2, wm8750_3d_func), -SOC_ENUM_SINGLE(WM8750_ALC1, 7, 4, wm8750_alc_func), -SOC_ENUM_SINGLE(WM8750_NGATE, 1, 2, wm8750_ng_type), -SOC_ENUM_SINGLE(WM8750_LOUTM1, 0, 5, wm8750_line_mux), -SOC_ENUM_SINGLE(WM8750_ROUTM1, 0, 5, wm8750_line_mux), -SOC_ENUM_SINGLE(WM8750_LADCIN, 6, 4, wm8750_pga_sel), /* 10 */ -SOC_ENUM_SINGLE(WM8750_RADCIN, 6, 4, wm8750_pga_sel), -SOC_ENUM_SINGLE(WM8750_ADCTL2, 7, 4, wm8750_out3), -SOC_ENUM_SINGLE(WM8750_ADCIN, 8, 2, wm8750_diff_sel), -SOC_ENUM_SINGLE(WM8750_ADCDAC, 5, 4, wm8750_adcpol), -SOC_ENUM_SINGLE(WM8750_ADCDAC, 1, 4, wm8750_deemph), -SOC_ENUM_SINGLE(WM8750_ADCIN, 6, 4, wm8750_mono_mux), /* 16 */ - -}; - -static const struct snd_kcontrol_new wm8750_snd_controls[] = { - -SOC_DOUBLE_R("Capture Volume", WM8750_LINVOL, WM8750_RINVOL, 0, 63, 0), -SOC_DOUBLE_R("Capture ZC Switch", WM8750_LINVOL, WM8750_RINVOL, 6, 1, 0), -SOC_DOUBLE_R("Capture Switch", WM8750_LINVOL, WM8750_RINVOL, 7, 1, 1), - -SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8750_LOUT1V, - WM8750_ROUT1V, 7, 1, 0), -SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8750_LOUT2V, - WM8750_ROUT2V, 7, 1, 0), - -SOC_ENUM("Playback De-emphasis", wm8750_enum[15]), - -SOC_ENUM("Capture Polarity", wm8750_enum[14]), -SOC_SINGLE("Playback 6dB Attenuate", WM8750_ADCDAC, 7, 1, 0), -SOC_SINGLE("Capture 6dB Attenuate", WM8750_ADCDAC, 8, 1, 0), - -SOC_DOUBLE_R("PCM Volume", WM8750_LDAC, WM8750_RDAC, 0, 255, 0), - -SOC_ENUM("Bass Boost", wm8750_enum[0]), -SOC_ENUM("Bass Filter", wm8750_enum[1]), -SOC_SINGLE("Bass Volume", WM8750_BASS, 0, 15, 1), - -SOC_SINGLE("Treble Volume", WM8750_TREBLE, 0, 15, 1), -SOC_ENUM("Treble Cut-off", wm8750_enum[2]), - -SOC_SINGLE("3D Switch", WM8750_3D, 0, 1, 0), -SOC_SINGLE("3D Volume", WM8750_3D, 1, 15, 0), -SOC_ENUM("3D Lower Cut-off", wm8750_enum[3]), -SOC_ENUM("3D Upper Cut-off", wm8750_enum[4]), -SOC_ENUM("3D Mode", wm8750_enum[5]), - -SOC_SINGLE("ALC Capture Target Volume", WM8750_ALC1, 0, 7, 0), -SOC_SINGLE("ALC Capture Max Volume", WM8750_ALC1, 4, 7, 0), -SOC_ENUM("ALC Capture Function", wm8750_enum[6]), -SOC_SINGLE("ALC Capture ZC Switch", WM8750_ALC2, 7, 1, 0), -SOC_SINGLE("ALC Capture Hold Time", WM8750_ALC2, 0, 15, 0), -SOC_SINGLE("ALC Capture Decay Time", WM8750_ALC3, 4, 15, 0), -SOC_SINGLE("ALC Capture Attack Time", WM8750_ALC3, 0, 15, 0), -SOC_SINGLE("ALC Capture NG Threshold", WM8750_NGATE, 3, 31, 0), -SOC_ENUM("ALC Capture NG Type", wm8750_enum[4]), -SOC_SINGLE("ALC Capture NG Switch", WM8750_NGATE, 0, 1, 0), - -SOC_SINGLE("Left ADC Capture Volume", WM8750_LADC, 0, 255, 0), -SOC_SINGLE("Right ADC Capture Volume", WM8750_RADC, 0, 255, 0), - -SOC_SINGLE("ZC Timeout Switch", WM8750_ADCTL1, 0, 1, 0), -SOC_SINGLE("Playback Invert Switch", WM8750_ADCTL1, 1, 1, 0), - -SOC_SINGLE("Right Speaker Playback Invert Switch", WM8750_ADCTL2, 4, 1, 0), - -/* Unimplemented */ -/* ADCDAC Bit 0 - ADCHPD */ -/* ADCDAC Bit 4 - HPOR */ -/* ADCTL1 Bit 2,3 - DATSEL */ -/* ADCTL1 Bit 4,5 - DMONOMIX */ -/* ADCTL1 Bit 6,7 - VSEL */ -/* ADCTL2 Bit 2 - LRCM */ -/* ADCTL2 Bit 3 - TRI */ -/* ADCTL3 Bit 5 - HPFLREN */ -/* ADCTL3 Bit 6 - VROI */ -/* ADCTL3 Bit 7,8 - ADCLRM */ -/* ADCIN Bit 4 - LDCM */ -/* ADCIN Bit 5 - RDCM */ - -SOC_DOUBLE_R("Mic Boost", WM8750_LADCIN, WM8750_RADCIN, 4, 3, 0), - -SOC_DOUBLE_R("Bypass Left Playback Volume", WM8750_LOUTM1, - WM8750_LOUTM2, 4, 7, 1), -SOC_DOUBLE_R("Bypass Right Playback Volume", WM8750_ROUTM1, - WM8750_ROUTM2, 4, 7, 1), -SOC_DOUBLE_R("Bypass Mono Playback Volume", WM8750_MOUTM1, - WM8750_MOUTM2, 4, 7, 1), - -SOC_SINGLE("Mono Playback ZC Switch", WM8750_MOUTV, 7, 1, 0), - -SOC_DOUBLE_R("Headphone Playback Volume", WM8750_LOUT1V, WM8750_ROUT1V, - 0, 127, 0), -SOC_DOUBLE_R("Speaker Playback Volume", WM8750_LOUT2V, WM8750_ROUT2V, - 0, 127, 0), - -SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0), - -}; - -/* - * DAPM Controls - */ - -/* Left Mixer */ -static const struct snd_kcontrol_new wm8750_left_mixer_controls[] = { -SOC_DAPM_SINGLE("Playback Switch", WM8750_LOUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_LOUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", WM8750_LOUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_LOUTM2, 7, 1, 0), -}; - -/* Right Mixer */ -static const struct snd_kcontrol_new wm8750_right_mixer_controls[] = { -SOC_DAPM_SINGLE("Left Playback Switch", WM8750_ROUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_ROUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Playback Switch", WM8750_ROUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_ROUTM2, 7, 1, 0), -}; - -/* Mono Mixer */ -static const struct snd_kcontrol_new wm8750_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("Left Playback Switch", WM8750_MOUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_MOUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", WM8750_MOUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_MOUTM2, 7, 1, 0), -}; - -/* Left Line Mux */ -static const struct snd_kcontrol_new wm8750_left_line_controls = -SOC_DAPM_ENUM("Route", wm8750_enum[8]); - -/* Right Line Mux */ -static const struct snd_kcontrol_new wm8750_right_line_controls = -SOC_DAPM_ENUM("Route", wm8750_enum[9]); - -/* Left PGA Mux */ -static const struct snd_kcontrol_new wm8750_left_pga_controls = -SOC_DAPM_ENUM("Route", wm8750_enum[10]); - -/* Right PGA Mux */ -static const struct snd_kcontrol_new wm8750_right_pga_controls = -SOC_DAPM_ENUM("Route", wm8750_enum[11]); - -/* Out 3 Mux */ -static const struct snd_kcontrol_new wm8750_out3_controls = -SOC_DAPM_ENUM("Route", wm8750_enum[12]); - -/* Differential Mux */ -static const struct snd_kcontrol_new wm8750_diffmux_controls = -SOC_DAPM_ENUM("Route", wm8750_enum[13]); - -/* Mono ADC Mux */ -static const struct snd_kcontrol_new wm8750_monomux_controls = -SOC_DAPM_ENUM("Route", wm8750_enum[16]); - -static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { - SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, - &wm8750_left_mixer_controls[0], - ARRAY_SIZE(wm8750_left_mixer_controls)), - SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, - &wm8750_right_mixer_controls[0], - ARRAY_SIZE(wm8750_right_mixer_controls)), - SND_SOC_DAPM_MIXER("Mono Mixer", WM8750_PWR2, 2, 0, - &wm8750_mono_mixer_controls[0], - ARRAY_SIZE(wm8750_mono_mixer_controls)), - - SND_SOC_DAPM_PGA("Right Out 2", WM8750_PWR2, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 2", WM8750_PWR2, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Out 1", WM8750_PWR2, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 1", WM8750_PWR2, 6, 0, NULL, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8750_PWR2, 7, 0), - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8750_PWR2, 8, 0), - - SND_SOC_DAPM_MICBIAS("Mic Bias", WM8750_PWR1, 1, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8750_PWR1, 2, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8750_PWR1, 3, 0), - - SND_SOC_DAPM_MUX("Left PGA Mux", WM8750_PWR1, 5, 0, - &wm8750_left_pga_controls), - SND_SOC_DAPM_MUX("Right PGA Mux", WM8750_PWR1, 4, 0, - &wm8750_right_pga_controls), - SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, - &wm8750_left_line_controls), - SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, - &wm8750_right_line_controls), - - SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8750_out3_controls), - SND_SOC_DAPM_PGA("Out 3", WM8750_PWR2, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mono Out 1", WM8750_PWR2, 2, 0, NULL, 0), - - SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, - &wm8750_diffmux_controls), - SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, - &wm8750_monomux_controls), - SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, - &wm8750_monomux_controls), - - SND_SOC_DAPM_OUTPUT("LOUT1"), - SND_SOC_DAPM_OUTPUT("ROUT1"), - SND_SOC_DAPM_OUTPUT("LOUT2"), - SND_SOC_DAPM_OUTPUT("ROUT2"), - SND_SOC_DAPM_OUTPUT("MONO1"), - SND_SOC_DAPM_OUTPUT("OUT3"), - SND_SOC_DAPM_OUTPUT("VREF"), - - SND_SOC_DAPM_INPUT("LINPUT1"), - SND_SOC_DAPM_INPUT("LINPUT2"), - SND_SOC_DAPM_INPUT("LINPUT3"), - SND_SOC_DAPM_INPUT("RINPUT1"), - SND_SOC_DAPM_INPUT("RINPUT2"), - SND_SOC_DAPM_INPUT("RINPUT3"), -}; - -static const struct snd_soc_dapm_route wm8750_dapm_routes[] = { - /* left mixer */ - {"Left Mixer", "Playback Switch", "Left DAC"}, - {"Left Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Left Mixer", "Right Playback Switch", "Right DAC"}, - {"Left Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* right mixer */ - {"Right Mixer", "Left Playback Switch", "Left DAC"}, - {"Right Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Right Mixer", "Playback Switch", "Right DAC"}, - {"Right Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* left out 1 */ - {"Left Out 1", NULL, "Left Mixer"}, - {"LOUT1", NULL, "Left Out 1"}, - - /* left out 2 */ - {"Left Out 2", NULL, "Left Mixer"}, - {"LOUT2", NULL, "Left Out 2"}, - - /* right out 1 */ - {"Right Out 1", NULL, "Right Mixer"}, - {"ROUT1", NULL, "Right Out 1"}, - - /* right out 2 */ - {"Right Out 2", NULL, "Right Mixer"}, - {"ROUT2", NULL, "Right Out 2"}, - - /* mono mixer */ - {"Mono Mixer", "Left Playback Switch", "Left DAC"}, - {"Mono Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Mono Mixer", "Right Playback Switch", "Right DAC"}, - {"Mono Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* mono out */ - {"Mono Out 1", NULL, "Mono Mixer"}, - {"MONO1", NULL, "Mono Out 1"}, - - /* out 3 */ - {"Out3 Mux", "VREF", "VREF"}, - {"Out3 Mux", "ROUT1 + Vol", "ROUT1"}, - {"Out3 Mux", "ROUT1", "Right Mixer"}, - {"Out3 Mux", "MonoOut", "MONO1"}, - {"Out 3", NULL, "Out3 Mux"}, - {"OUT3", NULL, "Out 3"}, - - /* Left Line Mux */ - {"Left Line Mux", "Line 1", "LINPUT1"}, - {"Left Line Mux", "Line 2", "LINPUT2"}, - {"Left Line Mux", "Line 3", "LINPUT3"}, - {"Left Line Mux", "PGA", "Left PGA Mux"}, - {"Left Line Mux", "Differential", "Differential Mux"}, - - /* Right Line Mux */ - {"Right Line Mux", "Line 1", "RINPUT1"}, - {"Right Line Mux", "Line 2", "RINPUT2"}, - {"Right Line Mux", "Line 3", "RINPUT3"}, - {"Right Line Mux", "PGA", "Right PGA Mux"}, - {"Right Line Mux", "Differential", "Differential Mux"}, - - /* Left PGA Mux */ - {"Left PGA Mux", "Line 1", "LINPUT1"}, - {"Left PGA Mux", "Line 2", "LINPUT2"}, - {"Left PGA Mux", "Line 3", "LINPUT3"}, - {"Left PGA Mux", "Differential", "Differential Mux"}, - - /* Right PGA Mux */ - {"Right PGA Mux", "Line 1", "RINPUT1"}, - {"Right PGA Mux", "Line 2", "RINPUT2"}, - {"Right PGA Mux", "Line 3", "RINPUT3"}, - {"Right PGA Mux", "Differential", "Differential Mux"}, - - /* Differential Mux */ - {"Differential Mux", "Line 1", "LINPUT1"}, - {"Differential Mux", "Line 1", "RINPUT1"}, - {"Differential Mux", "Line 2", "LINPUT2"}, - {"Differential Mux", "Line 2", "RINPUT2"}, - - /* Left ADC Mux */ - {"Left ADC Mux", "Stereo", "Left PGA Mux"}, - {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"}, - {"Left ADC Mux", "Digital Mono", "Left PGA Mux"}, - - /* Right ADC Mux */ - {"Right ADC Mux", "Stereo", "Right PGA Mux"}, - {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"}, - {"Right ADC Mux", "Digital Mono", "Right PGA Mux"}, - - /* ADC */ - {"Left ADC", NULL, "Left ADC Mux"}, - {"Right ADC", NULL, "Right ADC Mux"}, -}; - -struct _coeff_div { - u32 mclk; - u32 rate; - u16 fs; - u8 sr:5; - u8 usb:1; -}; - -/* codec hifi mclk clock divider coefficients */ -static const struct _coeff_div coeff_div[] = { - /* 8k */ - {12288000, 8000, 1536, 0x6, 0x0}, - {11289600, 8000, 1408, 0x16, 0x0}, - {18432000, 8000, 2304, 0x7, 0x0}, - {16934400, 8000, 2112, 0x17, 0x0}, - {12000000, 8000, 1500, 0x6, 0x1}, - - /* 11.025k */ - {11289600, 11025, 1024, 0x18, 0x0}, - {16934400, 11025, 1536, 0x19, 0x0}, - {12000000, 11025, 1088, 0x19, 0x1}, - - /* 16k */ - {12288000, 16000, 768, 0xa, 0x0}, - {18432000, 16000, 1152, 0xb, 0x0}, - {12000000, 16000, 750, 0xa, 0x1}, - - /* 22.05k */ - {11289600, 22050, 512, 0x1a, 0x0}, - {16934400, 22050, 768, 0x1b, 0x0}, - {12000000, 22050, 544, 0x1b, 0x1}, - - /* 32k */ - {12288000, 32000, 384, 0xc, 0x0}, - {18432000, 32000, 576, 0xd, 0x0}, - {12000000, 32000, 375, 0xa, 0x1}, - - /* 44.1k */ - {11289600, 44100, 256, 0x10, 0x0}, - {16934400, 44100, 384, 0x11, 0x0}, - {12000000, 44100, 272, 0x11, 0x1}, - - /* 48k */ - {12288000, 48000, 256, 0x0, 0x0}, - {18432000, 48000, 384, 0x1, 0x0}, - {12000000, 48000, 250, 0x0, 0x1}, - - /* 88.2k */ - {11289600, 88200, 128, 0x1e, 0x0}, - {16934400, 88200, 192, 0x1f, 0x0}, - {12000000, 88200, 136, 0x1f, 0x1}, - - /* 96k */ - {12288000, 96000, 128, 0xe, 0x0}, - {18432000, 96000, 192, 0xf, 0x0}, - {12000000, 96000, 125, 0xe, 0x1}, -}; - -static inline int get_coeff(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) - return i; - } - - printk(KERN_ERR "wm8750: could not get coeff for mclk %d @ rate %d\n", - mclk, rate); - return -EINVAL; -} - -static int wm8750_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - wm8750->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface = 0x0040; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8750_IFACE, iface); - return 0; -} - -static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; - u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; - int coeff = get_coeff(wm8750->sysclk, params_rate(params)); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x000c; - break; - } - - /* set iface & srate */ - snd_soc_write(codec, WM8750_IFACE, iface); - if (coeff >= 0) - snd_soc_write(codec, WM8750_SRATE, srate | - (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); - - return 0; -} - -static int wm8750_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7; - - if (mute) - snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8); - else - snd_soc_write(codec, WM8750_ADCDAC, mute_reg); - return 0; -} - -static int wm8750_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e; - - switch (level) { - case SND_SOC_BIAS_ON: - /* set vmid to 50k and unmute dac */ - snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); - - /* Set VMID to 5k */ - snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); - - /* ...and ramp */ - msleep(1000); - } - - /* mute dac and set vmid to 500k, enable VREF */ - snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141); - break; - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8750_PWR1, 0x0001); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) - -#define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8750_dai_ops = { - .hw_params = wm8750_pcm_hw_params, - .digital_mute = wm8750_mute, - .set_fmt = wm8750_set_dai_fmt, - .set_sysclk = wm8750_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver wm8750_dai = { - .name = "wm8750-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8750_RATES, - .formats = WM8750_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8750_RATES, - .formats = WM8750_FORMATS,}, - .ops = &wm8750_dai_ops, -}; - -static int wm8750_suspend(struct snd_soc_codec *codec) -{ - wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8750_resume(struct snd_soc_codec *codec) -{ - wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int wm8750_probe(struct snd_soc_codec *codec) -{ - struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type); - if (ret < 0) { - printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = wm8750_reset(codec); - if (ret < 0) { - printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); - return ret; - } - - /* charge output caps */ - wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* set the update bits */ - snd_soc_update_bits(codec, WM8750_LDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8750_RDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8750_LOUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8750_ROUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8750_LOUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8750_ROUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8750_LINVOL, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8750_RINVOL, 0x0100, 0x0100); - - return ret; -} - -static int wm8750_remove(struct snd_soc_codec *codec) -{ - wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { - .probe = wm8750_probe, - .remove = wm8750_remove, - .suspend = wm8750_suspend, - .resume = wm8750_resume, - .set_bias_level = wm8750_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8750_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8750_reg, - - .controls = wm8750_snd_controls, - .num_controls = ARRAY_SIZE(wm8750_snd_controls), - .dapm_widgets = wm8750_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), - .dapm_routes = wm8750_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8750_dapm_routes), -}; - -static const struct of_device_id wm8750_of_match[] = { - { .compatible = "wlf,wm8750", }, - { .compatible = "wlf,wm8987", }, - { } -}; -MODULE_DEVICE_TABLE(of, wm8750_of_match); - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8750_spi_probe(struct spi_device *spi) -{ - struct wm8750_priv *wm8750; - int ret; - - wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv), - GFP_KERNEL); - if (wm8750 == NULL) - return -ENOMEM; - - wm8750->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8750); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8750, &wm8750_dai, 1); - return ret; -} - -static int __devexit wm8750_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static const struct spi_device_id wm8750_spi_ids[] = { - { "wm8750", 0 }, - { "wm8987", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(spi, wm8750_spi_ids); - -static struct spi_driver wm8750_spi_driver = { - .driver = { - .name = "wm8750", - .owner = THIS_MODULE, - .of_match_table = wm8750_of_match, - }, - .id_table = wm8750_spi_ids, - .probe = wm8750_spi_probe, - .remove = __devexit_p(wm8750_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8750_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8750_priv *wm8750; - int ret; - - wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv), - GFP_KERNEL); - if (wm8750 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8750); - wm8750->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8750, &wm8750_dai, 1); - return ret; -} - -static __devexit int wm8750_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id wm8750_i2c_id[] = { - { "wm8750", 0 }, - { "wm8987", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); - -static struct i2c_driver wm8750_i2c_driver = { - .driver = { - .name = "wm8750", - .owner = THIS_MODULE, - .of_match_table = wm8750_of_match, - }, - .probe = wm8750_i2c_probe, - .remove = __devexit_p(wm8750_i2c_remove), - .id_table = wm8750_i2c_id, -}; -#endif - -static int __init wm8750_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8750_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8750_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8750_modinit); - -static void __exit wm8750_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8750_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8750_spi_driver); -#endif -} -module_exit(wm8750_exit); - -MODULE_DESCRIPTION("ASoC WM8750 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8750.h b/ANDROID_3.4.5/sound/soc/codecs/wm8750.h deleted file mode 100644 index 121427c0..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8750.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie - * - * Based on WM8753.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _WM8750_H -#define _WM8750_H - -/* WM8750 register space */ - -#define WM8750_LINVOL 0x00 -#define WM8750_RINVOL 0x01 -#define WM8750_LOUT1V 0x02 -#define WM8750_ROUT1V 0x03 -#define WM8750_ADCDAC 0x05 -#define WM8750_IFACE 0x07 -#define WM8750_SRATE 0x08 -#define WM8750_LDAC 0x0a -#define WM8750_RDAC 0x0b -#define WM8750_BASS 0x0c -#define WM8750_TREBLE 0x0d -#define WM8750_RESET 0x0f -#define WM8750_3D 0x10 -#define WM8750_ALC1 0x11 -#define WM8750_ALC2 0x12 -#define WM8750_ALC3 0x13 -#define WM8750_NGATE 0x14 -#define WM8750_LADC 0x15 -#define WM8750_RADC 0x16 -#define WM8750_ADCTL1 0x17 -#define WM8750_ADCTL2 0x18 -#define WM8750_PWR1 0x19 -#define WM8750_PWR2 0x1a -#define WM8750_ADCTL3 0x1b -#define WM8750_ADCIN 0x1f -#define WM8750_LADCIN 0x20 -#define WM8750_RADCIN 0x21 -#define WM8750_LOUTM1 0x22 -#define WM8750_LOUTM2 0x23 -#define WM8750_ROUTM1 0x24 -#define WM8750_ROUTM2 0x25 -#define WM8750_MOUTM1 0x26 -#define WM8750_MOUTM2 0x27 -#define WM8750_LOUT2V 0x28 -#define WM8750_ROUT2V 0x29 -#define WM8750_MOUTV 0x2a - -#define WM8750_CACHE_REGNUM 0x2a - -#define WM8750_SYSCLK 0 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8753.c b/ANDROID_3.4.5/sound/soc/codecs/wm8753.c deleted file mode 100644 index e27e7b62..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8753.c +++ /dev/null @@ -1,1709 +0,0 @@ -/* - * wm8753.c -- WM8753 ALSA Soc Audio driver - * - * Copyright 2003 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * - * 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. - * - * Notes: - * The WM8753 is a low power, high quality stereo codec with integrated PCM - * codec designed for portable digital telephony applications. - * - * Dual DAI:- - * - * This driver support 2 DAI PCM's. This makes the default PCM available for - * HiFi audio (e.g. MP3, ogg) playback/capture and the other PCM available for - * voice. - * - * Please note that the voice PCM can be connected directly to a Bluetooth - * codec or GSM modem and thus cannot be read or written to, although it is - * available to be configured with snd_hw_params(), etc and kcontrols in the - * normal alsa manner. - * - * Fast DAI switching:- - * - * The driver can now fast switch between the DAI configurations via a - * an alsa kcontrol. This allows the PCM to remain open. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8753.h" - -static int caps_charge = 2000; -module_param(caps_charge, int, 0); -MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); - -static int wm8753_hifi_write_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt); -static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt); - -/* - * wm8753 register cache - * We can't read the WM8753 register space when we - * are using 2 wire for device control, so we cache them instead. - */ -static const struct reg_default wm8753_reg_defaults[] = { - { 0x00, 0x0000 }, - { 0x01, 0x0008 }, - { 0x02, 0x0000 }, - { 0x03, 0x000a }, - { 0x04, 0x000a }, - { 0x05, 0x0033 }, - { 0x06, 0x0000 }, - { 0x07, 0x0007 }, - { 0x08, 0x00ff }, - { 0x09, 0x00ff }, - { 0x0a, 0x000f }, - { 0x0b, 0x000f }, - { 0x0c, 0x007b }, - { 0x0d, 0x0000 }, - { 0x0e, 0x0032 }, - { 0x0f, 0x0000 }, - { 0x10, 0x00c3 }, - { 0x11, 0x00c3 }, - { 0x12, 0x00c0 }, - { 0x13, 0x0000 }, - { 0x14, 0x0000 }, - { 0x15, 0x0000 }, - { 0x16, 0x0000 }, - { 0x17, 0x0000 }, - { 0x18, 0x0000 }, - { 0x19, 0x0000 }, - { 0x1a, 0x0000 }, - { 0x1b, 0x0000 }, - { 0x1c, 0x0000 }, - { 0x1d, 0x0000 }, - { 0x1e, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x20, 0x0055 }, - { 0x21, 0x0005 }, - { 0x22, 0x0050 }, - { 0x23, 0x0055 }, - { 0x24, 0x0050 }, - { 0x25, 0x0055 }, - { 0x26, 0x0050 }, - { 0x27, 0x0055 }, - { 0x28, 0x0079 }, - { 0x29, 0x0079 }, - { 0x2a, 0x0079 }, - { 0x2b, 0x0079 }, - { 0x2c, 0x0079 }, - { 0x2d, 0x0000 }, - { 0x2e, 0x0000 }, - { 0x2f, 0x0000 }, - { 0x30, 0x0000 }, - { 0x31, 0x0097 }, - { 0x32, 0x0097 }, - { 0x33, 0x0000 }, - { 0x34, 0x0004 }, - { 0x35, 0x0000 }, - { 0x36, 0x0083 }, - { 0x37, 0x0024 }, - { 0x38, 0x01ba }, - { 0x39, 0x0000 }, - { 0x3a, 0x0083 }, - { 0x3b, 0x0024 }, - { 0x3c, 0x01ba }, - { 0x3d, 0x0000 }, - { 0x3e, 0x0000 }, - { 0x3f, 0x0000 }, -}; - -static bool wm8753_volatile(struct device *dev, unsigned int reg) -{ - return reg == WM8753_RESET; -} - -static bool wm8753_writeable(struct device *dev, unsigned int reg) -{ - return reg <= WM8753_ADCTL2; -} - -/* codec private data */ -struct wm8753_priv { - struct regmap *regmap; - unsigned int sysclk; - unsigned int pcmclk; - - unsigned int voice_fmt; - unsigned int hifi_fmt; - - int dai_func; -}; - -#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0) - -/* - * WM8753 Controls - */ -static const char *wm8753_base[] = {"Linear Control", "Adaptive Boost"}; -static const char *wm8753_base_filter[] = - {"130Hz @ 48kHz", "200Hz @ 48kHz", "100Hz @ 16kHz", "400Hz @ 48kHz", - "100Hz @ 8kHz", "200Hz @ 8kHz"}; -static const char *wm8753_treble[] = {"8kHz", "4kHz"}; -static const char *wm8753_alc_func[] = {"Off", "Right", "Left", "Stereo"}; -static const char *wm8753_ng_type[] = {"Constant PGA Gain", "Mute ADC Output"}; -static const char *wm8753_3d_func[] = {"Capture", "Playback"}; -static const char *wm8753_3d_uc[] = {"2.2kHz", "1.5kHz"}; -static const char *wm8753_3d_lc[] = {"200Hz", "500Hz"}; -static const char *wm8753_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz"}; -static const char *wm8753_mono_mix[] = {"Stereo", "Left", "Right", "Mono"}; -static const char *wm8753_dac_phase[] = {"Non Inverted", "Inverted"}; -static const char *wm8753_line_mix[] = {"Line 1 + 2", "Line 1 - 2", - "Line 1", "Line 2"}; -static const char *wm8753_mono_mux[] = {"Line Mix", "Rx Mix"}; -static const char *wm8753_right_mux[] = {"Line 2", "Rx Mix"}; -static const char *wm8753_left_mux[] = {"Line 1", "Rx Mix"}; -static const char *wm8753_rxmsel[] = {"RXP - RXN", "RXP + RXN", "RXP", "RXN"}; -static const char *wm8753_sidetone_mux[] = {"Left PGA", "Mic 1", "Mic 2", - "Right PGA"}; -static const char *wm8753_mono2_src[] = {"Inverted Mono 1", "Left", "Right", - "Left + Right"}; -static const char *wm8753_out3[] = {"VREF", "ROUT2", "Left + Right"}; -static const char *wm8753_out4[] = {"VREF", "Capture ST", "LOUT2"}; -static const char *wm8753_radcsel[] = {"PGA", "Line or RXP-RXN", "Sidetone"}; -static const char *wm8753_ladcsel[] = {"PGA", "Line or RXP-RXN", "Line"}; -static const char *wm8753_mono_adc[] = {"Stereo", "Analogue Mix Left", - "Analogue Mix Right", "Digital Mono Mix"}; -static const char *wm8753_adc_hp[] = {"3.4Hz @ 48kHz", "82Hz @ 16k", - "82Hz @ 8kHz", "170Hz @ 8kHz"}; -static const char *wm8753_adc_filter[] = {"HiFi", "Voice"}; -static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"}; -static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"}; -static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC", - "Channel Swap"}; -static const char *wm8753_rout2_phase[] = {"Non Inverted", "Inverted"}; - -static const struct soc_enum wm8753_enum[] = { -SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base), -SOC_ENUM_SINGLE(WM8753_BASS, 4, 6, wm8753_base_filter), -SOC_ENUM_SINGLE(WM8753_TREBLE, 6, 2, wm8753_treble), -SOC_ENUM_SINGLE(WM8753_ALC1, 7, 4, wm8753_alc_func), -SOC_ENUM_SINGLE(WM8753_NGATE, 1, 2, wm8753_ng_type), -SOC_ENUM_SINGLE(WM8753_3D, 7, 2, wm8753_3d_func), -SOC_ENUM_SINGLE(WM8753_3D, 6, 2, wm8753_3d_uc), -SOC_ENUM_SINGLE(WM8753_3D, 5, 2, wm8753_3d_lc), -SOC_ENUM_SINGLE(WM8753_DAC, 1, 4, wm8753_deemp), -SOC_ENUM_SINGLE(WM8753_DAC, 4, 4, wm8753_mono_mix), -SOC_ENUM_SINGLE(WM8753_DAC, 6, 2, wm8753_dac_phase), -SOC_ENUM_SINGLE(WM8753_INCTL1, 3, 4, wm8753_line_mix), -SOC_ENUM_SINGLE(WM8753_INCTL1, 2, 2, wm8753_mono_mux), -SOC_ENUM_SINGLE(WM8753_INCTL1, 1, 2, wm8753_right_mux), -SOC_ENUM_SINGLE(WM8753_INCTL1, 0, 2, wm8753_left_mux), -SOC_ENUM_SINGLE(WM8753_INCTL2, 6, 4, wm8753_rxmsel), -SOC_ENUM_SINGLE(WM8753_INCTL2, 4, 4, wm8753_sidetone_mux), -SOC_ENUM_SINGLE(WM8753_OUTCTL, 7, 4, wm8753_mono2_src), -SOC_ENUM_SINGLE(WM8753_OUTCTL, 0, 3, wm8753_out3), -SOC_ENUM_SINGLE(WM8753_ADCTL2, 7, 3, wm8753_out4), -SOC_ENUM_SINGLE(WM8753_ADCIN, 2, 3, wm8753_radcsel), -SOC_ENUM_SINGLE(WM8753_ADCIN, 0, 3, wm8753_ladcsel), -SOC_ENUM_SINGLE(WM8753_ADCIN, 4, 4, wm8753_mono_adc), -SOC_ENUM_SINGLE(WM8753_ADC, 2, 4, wm8753_adc_hp), -SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter), -SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel), -SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode), -SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel), -SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase), -}; - - -static int wm8753_get_dai(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = wm8753->dai_func; - return 0; -} - -static int wm8753_set_dai(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 ioctl; - - if (wm8753->dai_func == ucontrol->value.integer.value[0]) - return 0; - - if (codec->active) - return -EBUSY; - - ioctl = snd_soc_read(codec, WM8753_IOCTL); - - wm8753->dai_func = ucontrol->value.integer.value[0]; - - if (((ioctl >> 2) & 0x3) == wm8753->dai_func) - return 1; - - ioctl = (ioctl & 0x1f3) | (wm8753->dai_func << 2); - snd_soc_write(codec, WM8753_IOCTL, ioctl); - - - wm8753_hifi_write_dai_fmt(codec, wm8753->hifi_fmt); - wm8753_voice_write_dai_fmt(codec, wm8753->voice_fmt); - - return 1; -} - -static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(mic_preamp_tlv, 1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); -static const unsigned int out_tlv[] = { - TLV_DB_RANGE_HEAD(2), - /* 0000000 - 0101111 = "Analogue mute" */ - 0, 48, TLV_DB_SCALE_ITEM(-25500, 0, 0), - 48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0), -}; -static const DECLARE_TLV_DB_SCALE(mix_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0); -static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); - -static const struct snd_kcontrol_new wm8753_snd_controls[] = { -SOC_DOUBLE_R_TLV("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0, dac_tlv), - -SOC_DOUBLE_R_TLV("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0, - adc_tlv), - -SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V, - 0, 127, 0, out_tlv), -SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0, - 127, 0, out_tlv), - -SOC_SINGLE_TLV("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0, out_tlv), - -SOC_DOUBLE_R_TLV("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7, - 1, mix_tlv), -SOC_DOUBLE_R_TLV("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4, - 7, 1, mix_tlv), -SOC_DOUBLE_R_TLV("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7, - 1, voice_mix_tlv), - -SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7, - 1, 0), -SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, - 1, 0), - -SOC_SINGLE_TLV("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1, mix_tlv), -SOC_SINGLE_TLV("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1, - mix_tlv), -SOC_SINGLE_TLV("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1, - voice_mix_tlv), -SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0), - -SOC_ENUM("Bass Boost", wm8753_enum[0]), -SOC_ENUM("Bass Filter", wm8753_enum[1]), -SOC_SINGLE("Bass Volume", WM8753_BASS, 0, 15, 1), - -SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 15, 1), -SOC_ENUM("Treble Cut-off", wm8753_enum[2]), - -SOC_DOUBLE_TLV("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1, - rec_mix_tlv), -SOC_SINGLE_TLV("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1, - rec_mix_tlv), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0, - pga_tlv), -SOC_DOUBLE_R("Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0), -SOC_DOUBLE_R("Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 1), - -SOC_ENUM("Capture Filter Select", wm8753_enum[23]), -SOC_ENUM("Capture Filter Cut-off", wm8753_enum[24]), -SOC_SINGLE("Capture Filter Switch", WM8753_ADC, 0, 1, 1), - -SOC_SINGLE("ALC Capture Target Volume", WM8753_ALC1, 0, 7, 0), -SOC_SINGLE("ALC Capture Max Volume", WM8753_ALC1, 4, 7, 0), -SOC_ENUM("ALC Capture Function", wm8753_enum[3]), -SOC_SINGLE("ALC Capture ZC Switch", WM8753_ALC2, 8, 1, 0), -SOC_SINGLE("ALC Capture Hold Time", WM8753_ALC2, 0, 15, 1), -SOC_SINGLE("ALC Capture Decay Time", WM8753_ALC3, 4, 15, 1), -SOC_SINGLE("ALC Capture Attack Time", WM8753_ALC3, 0, 15, 0), -SOC_SINGLE("ALC Capture NG Threshold", WM8753_NGATE, 3, 31, 0), -SOC_ENUM("ALC Capture NG Type", wm8753_enum[4]), -SOC_SINGLE("ALC Capture NG Switch", WM8753_NGATE, 0, 1, 0), - -SOC_ENUM("3D Function", wm8753_enum[5]), -SOC_ENUM("3D Upper Cut-off", wm8753_enum[6]), -SOC_ENUM("3D Lower Cut-off", wm8753_enum[7]), -SOC_SINGLE("3D Volume", WM8753_3D, 1, 15, 0), -SOC_SINGLE("3D Switch", WM8753_3D, 0, 1, 0), - -SOC_SINGLE("Capture 6dB Attenuate", WM8753_ADCTL1, 2, 1, 0), -SOC_SINGLE("Playback 6dB Attenuate", WM8753_ADCTL1, 1, 1, 0), - -SOC_ENUM("De-emphasis", wm8753_enum[8]), -SOC_ENUM("Playback Mono Mix", wm8753_enum[9]), -SOC_ENUM("Playback Phase", wm8753_enum[10]), - -SOC_SINGLE_TLV("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0, mic_preamp_tlv), -SOC_SINGLE_TLV("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0, mic_preamp_tlv), - -SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai), - -SOC_ENUM("ADC Data Select", wm8753_enum[27]), -SOC_ENUM("ROUT2 Phase", wm8753_enum[28]), -}; - -/* - * _DAPM_ Controls - */ - -/* Left Mixer */ -static const struct snd_kcontrol_new wm8753_left_mixer_controls[] = { -SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_LOUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_LOUTM2, 7, 1, 0), -SOC_DAPM_SINGLE("Left Playback Switch", WM8753_LOUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_LOUTM1, 7, 1, 0), -}; - -/* Right mixer */ -static const struct snd_kcontrol_new wm8753_right_mixer_controls[] = { -SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_ROUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_ROUTM2, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", WM8753_ROUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_ROUTM1, 7, 1, 0), -}; - -/* Mono mixer */ -static const struct snd_kcontrol_new wm8753_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("Left Playback Switch", WM8753_MOUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", WM8753_MOUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_MOUTM2, 3, 1, 0), -SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_MOUTM2, 7, 1, 0), -SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_MOUTM1, 7, 1, 0), -}; - -/* Mono 2 Mux */ -static const struct snd_kcontrol_new wm8753_mono2_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[17]); - -/* Out 3 Mux */ -static const struct snd_kcontrol_new wm8753_out3_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[18]); - -/* Out 4 Mux */ -static const struct snd_kcontrol_new wm8753_out4_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[19]); - -/* ADC Mono Mix */ -static const struct snd_kcontrol_new wm8753_adc_mono_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[22]); - -/* Record mixer */ -static const struct snd_kcontrol_new wm8753_record_mixer_controls[] = { -SOC_DAPM_SINGLE("Voice Capture Switch", WM8753_RECMIX2, 3, 1, 0), -SOC_DAPM_SINGLE("Left Capture Switch", WM8753_RECMIX1, 3, 1, 0), -SOC_DAPM_SINGLE("Right Capture Switch", WM8753_RECMIX1, 7, 1, 0), -}; - -/* Left ADC mux */ -static const struct snd_kcontrol_new wm8753_adc_left_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[21]); - -/* Right ADC mux */ -static const struct snd_kcontrol_new wm8753_adc_right_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[20]); - -/* MIC mux */ -static const struct snd_kcontrol_new wm8753_mic_mux_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[16]); - -/* ALC mixer */ -static const struct snd_kcontrol_new wm8753_alc_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Capture Switch", WM8753_INCTL2, 3, 1, 0), -SOC_DAPM_SINGLE("Mic2 Capture Switch", WM8753_INCTL2, 2, 1, 0), -SOC_DAPM_SINGLE("Mic1 Capture Switch", WM8753_INCTL2, 1, 1, 0), -SOC_DAPM_SINGLE("Rx Capture Switch", WM8753_INCTL2, 0, 1, 0), -}; - -/* Left Line mux */ -static const struct snd_kcontrol_new wm8753_line_left_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[14]); - -/* Right Line mux */ -static const struct snd_kcontrol_new wm8753_line_right_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[13]); - -/* Mono Line mux */ -static const struct snd_kcontrol_new wm8753_line_mono_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[12]); - -/* Line mux and mixer */ -static const struct snd_kcontrol_new wm8753_line_mux_mix_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[11]); - -/* Rx mux and mixer */ -static const struct snd_kcontrol_new wm8753_rx_mux_mix_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[15]); - -/* Mic Selector Mux */ -static const struct snd_kcontrol_new wm8753_mic_sel_mux_controls = -SOC_DAPM_ENUM("Route", wm8753_enum[25]); - -static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { -SND_SOC_DAPM_MICBIAS("Mic Bias", WM8753_PWR1, 5, 0), -SND_SOC_DAPM_MIXER("Left Mixer", WM8753_PWR4, 0, 0, - &wm8753_left_mixer_controls[0], ARRAY_SIZE(wm8753_left_mixer_controls)), -SND_SOC_DAPM_PGA("Left Out 1", WM8753_PWR3, 8, 0, NULL, 0), -SND_SOC_DAPM_PGA("Left Out 2", WM8753_PWR3, 6, 0, NULL, 0), -SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", WM8753_PWR1, 3, 0), -SND_SOC_DAPM_OUTPUT("LOUT1"), -SND_SOC_DAPM_OUTPUT("LOUT2"), -SND_SOC_DAPM_MIXER("Right Mixer", WM8753_PWR4, 1, 0, - &wm8753_right_mixer_controls[0], ARRAY_SIZE(wm8753_right_mixer_controls)), -SND_SOC_DAPM_PGA("Right Out 1", WM8753_PWR3, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Out 2", WM8753_PWR3, 5, 0, NULL, 0), -SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", WM8753_PWR1, 2, 0), -SND_SOC_DAPM_OUTPUT("ROUT1"), -SND_SOC_DAPM_OUTPUT("ROUT2"), -SND_SOC_DAPM_MIXER("Mono Mixer", WM8753_PWR4, 2, 0, - &wm8753_mono_mixer_controls[0], ARRAY_SIZE(wm8753_mono_mixer_controls)), -SND_SOC_DAPM_PGA("Mono Out 1", WM8753_PWR3, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA("Mono Out 2", WM8753_PWR3, 1, 0, NULL, 0), -SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", WM8753_PWR1, 4, 0), -SND_SOC_DAPM_OUTPUT("MONO1"), -SND_SOC_DAPM_MUX("Mono 2 Mux", SND_SOC_NOPM, 0, 0, &wm8753_mono2_controls), -SND_SOC_DAPM_OUTPUT("MONO2"), -SND_SOC_DAPM_MIXER("Out3 Left + Right", -1, 0, 0, NULL, 0), -SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out3_controls), -SND_SOC_DAPM_PGA("Out 3", WM8753_PWR3, 4, 0, NULL, 0), -SND_SOC_DAPM_OUTPUT("OUT3"), -SND_SOC_DAPM_MUX("Out4 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out4_controls), -SND_SOC_DAPM_PGA("Out 4", WM8753_PWR3, 3, 0, NULL, 0), -SND_SOC_DAPM_OUTPUT("OUT4"), -SND_SOC_DAPM_MIXER("Playback Mixer", WM8753_PWR4, 3, 0, - &wm8753_record_mixer_controls[0], - ARRAY_SIZE(wm8753_record_mixer_controls)), -SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8753_PWR2, 3, 0), -SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8753_PWR2, 2, 0), -SND_SOC_DAPM_MUX("Capture Left Mixer", SND_SOC_NOPM, 0, 0, - &wm8753_adc_mono_controls), -SND_SOC_DAPM_MUX("Capture Right Mixer", SND_SOC_NOPM, 0, 0, - &wm8753_adc_mono_controls), -SND_SOC_DAPM_MUX("Capture Left Mux", SND_SOC_NOPM, 0, 0, - &wm8753_adc_left_controls), -SND_SOC_DAPM_MUX("Capture Right Mux", SND_SOC_NOPM, 0, 0, - &wm8753_adc_right_controls), -SND_SOC_DAPM_MUX("Mic Sidetone Mux", SND_SOC_NOPM, 0, 0, - &wm8753_mic_mux_controls), -SND_SOC_DAPM_PGA("Left Capture Volume", WM8753_PWR2, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Capture Volume", WM8753_PWR2, 4, 0, NULL, 0), -SND_SOC_DAPM_MIXER("ALC Mixer", WM8753_PWR2, 6, 0, - &wm8753_alc_mixer_controls[0], ARRAY_SIZE(wm8753_alc_mixer_controls)), -SND_SOC_DAPM_MUX("Line Left Mux", SND_SOC_NOPM, 0, 0, - &wm8753_line_left_controls), -SND_SOC_DAPM_MUX("Line Right Mux", SND_SOC_NOPM, 0, 0, - &wm8753_line_right_controls), -SND_SOC_DAPM_MUX("Line Mono Mux", SND_SOC_NOPM, 0, 0, - &wm8753_line_mono_controls), -SND_SOC_DAPM_MUX("Line Mixer", WM8753_PWR2, 0, 0, - &wm8753_line_mux_mix_controls), -SND_SOC_DAPM_MUX("Rx Mixer", WM8753_PWR2, 1, 0, - &wm8753_rx_mux_mix_controls), -SND_SOC_DAPM_PGA("Mic 1 Volume", WM8753_PWR2, 8, 0, NULL, 0), -SND_SOC_DAPM_PGA("Mic 2 Volume", WM8753_PWR2, 7, 0, NULL, 0), -SND_SOC_DAPM_MUX("Mic Selection Mux", SND_SOC_NOPM, 0, 0, - &wm8753_mic_sel_mux_controls), -SND_SOC_DAPM_INPUT("LINE1"), -SND_SOC_DAPM_INPUT("LINE2"), -SND_SOC_DAPM_INPUT("RXP"), -SND_SOC_DAPM_INPUT("RXN"), -SND_SOC_DAPM_INPUT("ACIN"), -SND_SOC_DAPM_OUTPUT("ACOP"), -SND_SOC_DAPM_INPUT("MIC1N"), -SND_SOC_DAPM_INPUT("MIC1"), -SND_SOC_DAPM_INPUT("MIC2N"), -SND_SOC_DAPM_INPUT("MIC2"), -SND_SOC_DAPM_VMID("VREF"), -}; - -static const struct snd_soc_dapm_route wm8753_dapm_routes[] = { - /* left mixer */ - {"Left Mixer", "Left Playback Switch", "Left DAC"}, - {"Left Mixer", "Voice Playback Switch", "Voice DAC"}, - {"Left Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"}, - {"Left Mixer", "Bypass Playback Switch", "Line Left Mux"}, - - /* right mixer */ - {"Right Mixer", "Right Playback Switch", "Right DAC"}, - {"Right Mixer", "Voice Playback Switch", "Voice DAC"}, - {"Right Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"}, - {"Right Mixer", "Bypass Playback Switch", "Line Right Mux"}, - - /* mono mixer */ - {"Mono Mixer", "Voice Playback Switch", "Voice DAC"}, - {"Mono Mixer", "Left Playback Switch", "Left DAC"}, - {"Mono Mixer", "Right Playback Switch", "Right DAC"}, - {"Mono Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"}, - {"Mono Mixer", "Bypass Playback Switch", "Line Mono Mux"}, - - /* left out */ - {"Left Out 1", NULL, "Left Mixer"}, - {"Left Out 2", NULL, "Left Mixer"}, - {"LOUT1", NULL, "Left Out 1"}, - {"LOUT2", NULL, "Left Out 2"}, - - /* right out */ - {"Right Out 1", NULL, "Right Mixer"}, - {"Right Out 2", NULL, "Right Mixer"}, - {"ROUT1", NULL, "Right Out 1"}, - {"ROUT2", NULL, "Right Out 2"}, - - /* mono 1 out */ - {"Mono Out 1", NULL, "Mono Mixer"}, - {"MONO1", NULL, "Mono Out 1"}, - - /* mono 2 out */ - {"Mono 2 Mux", "Left + Right", "Out3 Left + Right"}, - {"Mono 2 Mux", "Inverted Mono 1", "MONO1"}, - {"Mono 2 Mux", "Left", "Left Mixer"}, - {"Mono 2 Mux", "Right", "Right Mixer"}, - {"Mono Out 2", NULL, "Mono 2 Mux"}, - {"MONO2", NULL, "Mono Out 2"}, - - /* out 3 */ - {"Out3 Left + Right", NULL, "Left Mixer"}, - {"Out3 Left + Right", NULL, "Right Mixer"}, - {"Out3 Mux", "VREF", "VREF"}, - {"Out3 Mux", "Left + Right", "Out3 Left + Right"}, - {"Out3 Mux", "ROUT2", "ROUT2"}, - {"Out 3", NULL, "Out3 Mux"}, - {"OUT3", NULL, "Out 3"}, - - /* out 4 */ - {"Out4 Mux", "VREF", "VREF"}, - {"Out4 Mux", "Capture ST", "Playback Mixer"}, - {"Out4 Mux", "LOUT2", "LOUT2"}, - {"Out 4", NULL, "Out4 Mux"}, - {"OUT4", NULL, "Out 4"}, - - /* record mixer */ - {"Playback Mixer", "Left Capture Switch", "Left Mixer"}, - {"Playback Mixer", "Voice Capture Switch", "Mono Mixer"}, - {"Playback Mixer", "Right Capture Switch", "Right Mixer"}, - - /* Mic/SideTone Mux */ - {"Mic Sidetone Mux", "Left PGA", "Left Capture Volume"}, - {"Mic Sidetone Mux", "Right PGA", "Right Capture Volume"}, - {"Mic Sidetone Mux", "Mic 1", "Mic 1 Volume"}, - {"Mic Sidetone Mux", "Mic 2", "Mic 2 Volume"}, - - /* Capture Left Mux */ - {"Capture Left Mux", "PGA", "Left Capture Volume"}, - {"Capture Left Mux", "Line or RXP-RXN", "Line Left Mux"}, - {"Capture Left Mux", "Line", "LINE1"}, - - /* Capture Right Mux */ - {"Capture Right Mux", "PGA", "Right Capture Volume"}, - {"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"}, - {"Capture Right Mux", "Sidetone", "Playback Mixer"}, - - /* Mono Capture mixer-mux */ - {"Capture Right Mixer", "Stereo", "Capture Right Mux"}, - {"Capture Left Mixer", "Stereo", "Capture Left Mux"}, - {"Capture Left Mixer", "Analogue Mix Left", "Capture Left Mux"}, - {"Capture Left Mixer", "Analogue Mix Left", "Capture Right Mux"}, - {"Capture Right Mixer", "Analogue Mix Right", "Capture Left Mux"}, - {"Capture Right Mixer", "Analogue Mix Right", "Capture Right Mux"}, - {"Capture Left Mixer", "Digital Mono Mix", "Capture Left Mux"}, - {"Capture Left Mixer", "Digital Mono Mix", "Capture Right Mux"}, - {"Capture Right Mixer", "Digital Mono Mix", "Capture Left Mux"}, - {"Capture Right Mixer", "Digital Mono Mix", "Capture Right Mux"}, - - /* ADC */ - {"Left ADC", NULL, "Capture Left Mixer"}, - {"Right ADC", NULL, "Capture Right Mixer"}, - - /* Left Capture Volume */ - {"Left Capture Volume", NULL, "ACIN"}, - - /* Right Capture Volume */ - {"Right Capture Volume", NULL, "Mic 2 Volume"}, - - /* ALC Mixer */ - {"ALC Mixer", "Line Capture Switch", "Line Mixer"}, - {"ALC Mixer", "Mic2 Capture Switch", "Mic 2 Volume"}, - {"ALC Mixer", "Mic1 Capture Switch", "Mic 1 Volume"}, - {"ALC Mixer", "Rx Capture Switch", "Rx Mixer"}, - - /* Line Left Mux */ - {"Line Left Mux", "Line 1", "LINE1"}, - {"Line Left Mux", "Rx Mix", "Rx Mixer"}, - - /* Line Right Mux */ - {"Line Right Mux", "Line 2", "LINE2"}, - {"Line Right Mux", "Rx Mix", "Rx Mixer"}, - - /* Line Mono Mux */ - {"Line Mono Mux", "Line Mix", "Line Mixer"}, - {"Line Mono Mux", "Rx Mix", "Rx Mixer"}, - - /* Line Mixer/Mux */ - {"Line Mixer", "Line 1 + 2", "LINE1"}, - {"Line Mixer", "Line 1 - 2", "LINE1"}, - {"Line Mixer", "Line 1 + 2", "LINE2"}, - {"Line Mixer", "Line 1 - 2", "LINE2"}, - {"Line Mixer", "Line 1", "LINE1"}, - {"Line Mixer", "Line 2", "LINE2"}, - - /* Rx Mixer/Mux */ - {"Rx Mixer", "RXP - RXN", "RXP"}, - {"Rx Mixer", "RXP + RXN", "RXP"}, - {"Rx Mixer", "RXP - RXN", "RXN"}, - {"Rx Mixer", "RXP + RXN", "RXN"}, - {"Rx Mixer", "RXP", "RXP"}, - {"Rx Mixer", "RXN", "RXN"}, - - /* Mic 1 Volume */ - {"Mic 1 Volume", NULL, "MIC1N"}, - {"Mic 1 Volume", NULL, "Mic Selection Mux"}, - - /* Mic 2 Volume */ - {"Mic 2 Volume", NULL, "MIC2N"}, - {"Mic 2 Volume", NULL, "MIC2"}, - - /* Mic Selector Mux */ - {"Mic Selection Mux", "Mic 1", "MIC1"}, - {"Mic Selection Mux", "Mic 2", "MIC2N"}, - {"Mic Selection Mux", "Mic 3", "MIC2"}, - - /* ACOP */ - {"ACOP", NULL, "ALC Mixer"}, -}; - -/* PLL divisors */ -struct _pll_div { - u32 div2:1; - u32 n:4; - u32 k:24; -}; - -/* The size in bits of the pll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 22) * 10) - -static void pll_factors(struct _pll_div *pll_div, unsigned int target, - unsigned int source) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod; - - Ndiv = target / source; - if (Ndiv < 6) { - source >>= 1; - pll_div->div2 = 1; - Ndiv = target / source; - } else - pll_div->div2 = 0; - - if ((Ndiv < 6) || (Ndiv > 12)) - printk(KERN_WARNING - "wm8753: unsupported N = %u\n", Ndiv); - - pll_div->n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div->k = K; -} - -static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - u16 reg, enable; - int offset; - struct snd_soc_codec *codec = codec_dai->codec; - - if (pll_id < WM8753_PLL1 || pll_id > WM8753_PLL2) - return -ENODEV; - - if (pll_id == WM8753_PLL1) { - offset = 0; - enable = 0x10; - reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef; - } else { - offset = 4; - enable = 0x8; - reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7; - } - - if (!freq_in || !freq_out) { - /* disable PLL */ - snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); - snd_soc_write(codec, WM8753_CLOCK, reg); - return 0; - } else { - u16 value = 0; - struct _pll_div pll_div; - - pll_factors(&pll_div, freq_out * 8, freq_in); - - /* set up N and K PLL divisor ratios */ - /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */ - value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); - snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value); - - /* bits 8:0 = PLL_K[17:9] */ - value = (pll_div.k & 0x03fe00) >> 9; - snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value); - - /* bits 8:0 = PLL_K[8:0] */ - value = pll_div.k & 0x0001ff; - snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value); - - /* set PLL as input and enable */ - snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | - (pll_div.div2 << 3)); - snd_soc_write(codec, WM8753_CLOCK, reg | enable); - } - return 0; -} - -struct _coeff_div { - u32 mclk; - u32 rate; - u8 sr:5; - u8 usb:1; -}; - -/* codec hifi mclk (after PLL) clock divider coefficients */ -static const struct _coeff_div coeff_div[] = { - /* 8k */ - {12288000, 8000, 0x6, 0x0}, - {11289600, 8000, 0x16, 0x0}, - {18432000, 8000, 0x7, 0x0}, - {16934400, 8000, 0x17, 0x0}, - {12000000, 8000, 0x6, 0x1}, - - /* 11.025k */ - {11289600, 11025, 0x18, 0x0}, - {16934400, 11025, 0x19, 0x0}, - {12000000, 11025, 0x19, 0x1}, - - /* 16k */ - {12288000, 16000, 0xa, 0x0}, - {18432000, 16000, 0xb, 0x0}, - {12000000, 16000, 0xa, 0x1}, - - /* 22.05k */ - {11289600, 22050, 0x1a, 0x0}, - {16934400, 22050, 0x1b, 0x0}, - {12000000, 22050, 0x1b, 0x1}, - - /* 32k */ - {12288000, 32000, 0xc, 0x0}, - {18432000, 32000, 0xd, 0x0}, - {12000000, 32000, 0xa, 0x1}, - - /* 44.1k */ - {11289600, 44100, 0x10, 0x0}, - {16934400, 44100, 0x11, 0x0}, - {12000000, 44100, 0x11, 0x1}, - - /* 48k */ - {12288000, 48000, 0x0, 0x0}, - {18432000, 48000, 0x1, 0x0}, - {12000000, 48000, 0x0, 0x1}, - - /* 88.2k */ - {11289600, 88200, 0x1e, 0x0}, - {16934400, 88200, 0x1f, 0x0}, - {12000000, 88200, 0x1f, 0x1}, - - /* 96k */ - {12288000, 96000, 0xe, 0x0}, - {18432000, 96000, 0xf, 0x0}, - {12000000, 96000, 0xe, 0x1}, -}; - -static int get_coeff(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) - return i; - } - return -EINVAL; -} - -/* - * Clock after PLL and dividers - */ -static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - if (clk_id == WM8753_MCLK) { - wm8753->sysclk = freq; - return 0; - } else if (clk_id == WM8753_PCMCLK) { - wm8753->pcmclk = freq; - return 0; - } - break; - } - return -EINVAL; -} - -/* - * Set's ADC and Voice DAC format. - */ -static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - voice |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - voice |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - voice |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - voice |= 0x0013; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8753_PCM, voice); - return 0; -} - -/* - * Set PCM DAI bit size and sample rate. - */ -static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3; - u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - voice |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - voice |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S32_LE: - voice |= 0x000c; - break; - } - - /* sample rate */ - if (params_rate(params) * 384 == wm8753->pcmclk) - srate |= 0x80; - snd_soc_write(codec, WM8753_SRATE1, srate); - - snd_soc_write(codec, WM8753_PCM, voice); - return 0; -} - -/* - * Set's PCM dai fmt and BCLK. - */ -static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - u16 voice, ioctl; - - voice = snd_soc_read(codec, WM8753_PCM) & 0x011f; - ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBM_CFM: - ioctl |= 0x2; - case SND_SOC_DAIFMT_CBM_CFS: - voice |= 0x0040; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - voice |= 0x0080; - break; - default: - return -EINVAL; - } - break; - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - voice &= ~0x0010; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - voice |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - voice |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - voice |= 0x0010; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8753_PCM, voice); - snd_soc_write(codec, WM8753_IOCTL, ioctl); - return 0; -} - -static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM8753_PCMDIV: - reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f; - snd_soc_write(codec, WM8753_CLOCK, reg | div); - break; - case WM8753_BCLKDIV: - reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7; - snd_soc_write(codec, WM8753_SRATE2, reg | div); - break; - case WM8753_VXCLKDIV: - reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f; - snd_soc_write(codec, WM8753_SRATE2, reg | div); - break; - default: - return -EINVAL; - } - return 0; -} - -/* - * Set's HiFi DAC format. - */ -static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - hifi |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - hifi |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - hifi |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - hifi |= 0x0013; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8753_HIFI, hifi); - return 0; -} - -/* - * Set's I2S DAI format. - */ -static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - u16 ioctl, hifi; - - hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f; - ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBM_CFM: - ioctl |= 0x1; - case SND_SOC_DAIFMT_CBM_CFS: - hifi |= 0x0040; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - hifi |= 0x0080; - break; - default: - return -EINVAL; - } - break; - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - hifi &= ~0x0010; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - hifi |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - hifi |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - hifi |= 0x0010; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8753_HIFI, hifi); - snd_soc_write(codec, WM8753_IOCTL, ioctl); - return 0; -} - -/* - * Set PCM DAI bit size and sample rate. - */ -static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0; - u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3; - int coeff; - - /* is digital filter coefficient valid ? */ - coeff = get_coeff(wm8753->sysclk, params_rate(params)); - if (coeff < 0) { - printk(KERN_ERR "wm8753 invalid MCLK or rate\n"); - return coeff; - } - snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | - coeff_div[coeff].usb); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - hifi |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - hifi |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S32_LE: - hifi |= 0x000c; - break; - } - - snd_soc_write(codec, WM8753_HIFI, hifi); - return 0; -} - -static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - u16 clock; - - /* set clk source as pcmclk */ - clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; - snd_soc_write(codec, WM8753_CLOCK, clock); - - return wm8753_vdac_adc_set_dai_fmt(codec, fmt); -} - -static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - return wm8753_hdac_set_dai_fmt(codec, fmt); -} - -static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - u16 clock; - - /* set clk source as pcmclk */ - clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; - snd_soc_write(codec, WM8753_CLOCK, clock); - - return wm8753_vdac_adc_set_dai_fmt(codec, fmt); -} - -static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - u16 clock; - - /* set clk source as mclk */ - clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; - snd_soc_write(codec, WM8753_CLOCK, clock | 0x4); - - if (wm8753_hdac_set_dai_fmt(codec, fmt) < 0) - return -EINVAL; - return wm8753_vdac_adc_set_dai_fmt(codec, fmt); -} - -static int wm8753_hifi_write_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - switch (wm8753->dai_func) { - case 0: - ret = wm8753_mode1h_set_dai_fmt(codec, fmt); - break; - case 1: - ret = wm8753_mode2_set_dai_fmt(codec, fmt); - break; - case 2: - case 3: - ret = wm8753_mode3_4_set_dai_fmt(codec, fmt); - break; - default: - break; - } - if (ret) - return ret; - - return wm8753_i2s_set_dai_fmt(codec, fmt); -} - -static int wm8753_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - - wm8753->hifi_fmt = fmt; - - return wm8753_hifi_write_dai_fmt(codec, fmt); -}; - -static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec, - unsigned int fmt) -{ - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - if (wm8753->dai_func != 0) - return 0; - - ret = wm8753_mode1v_set_dai_fmt(codec, fmt); - if (ret) - return ret; - ret = wm8753_pcm_set_dai_fmt(codec, fmt); - if (ret) - return ret; - - return 0; -}; - -static int wm8753_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - - wm8753->voice_fmt = fmt; - - return wm8753_voice_write_dai_fmt(codec, fmt); -}; - -static int wm8753_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7; - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - - /* the digital mute covers the HiFi and Voice DAC's on the WM8753. - * make sure we check if they are not both active when we mute */ - if (mute && wm8753->dai_func == 1) { - if (!codec->active) - snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); - } else { - if (mute) - snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); - else - snd_soc_write(codec, WM8753_DAC, mute_reg); - } - - return 0; -} - -static int wm8753_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e; - - switch (level) { - case SND_SOC_BIAS_ON: - /* set vmid to 50k and unmute dac */ - snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); - break; - case SND_SOC_BIAS_PREPARE: - /* set vmid to 5k for quick power up */ - snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); - break; - case SND_SOC_BIAS_STANDBY: - /* mute dac and set vmid to 500k, enable VREF */ - snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141); - break; - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8753_PWR1, 0x0001); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8753_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) - -#define WM8753_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -/* - * The WM8753 supports up to 4 different and mutually exclusive DAI - * configurations. This gives 2 PCM's available for use, hifi and voice. - * NOTE: The Voice PCM cannot play or capture audio to the CPU as it's DAI - * is connected between the wm8753 and a BT codec or GSM modem. - * - * 1. Voice over PCM DAI - HIFI DAC over HIFI DAI - * 2. Voice over HIFI DAI - HIFI disabled - * 3. Voice disabled - HIFI over HIFI - * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture - */ -static const struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = { - .hw_params = wm8753_i2s_hw_params, - .digital_mute = wm8753_mute, - .set_fmt = wm8753_hifi_set_dai_fmt, - .set_clkdiv = wm8753_set_dai_clkdiv, - .set_pll = wm8753_set_dai_pll, - .set_sysclk = wm8753_set_dai_sysclk, -}; - -static const struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = { - .hw_params = wm8753_pcm_hw_params, - .digital_mute = wm8753_mute, - .set_fmt = wm8753_voice_set_dai_fmt, - .set_clkdiv = wm8753_set_dai_clkdiv, - .set_pll = wm8753_set_dai_pll, - .set_sysclk = wm8753_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver wm8753_dai[] = { -/* DAI HiFi mode 1 */ -{ .name = "wm8753-hifi", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8753_RATES, - .formats = WM8753_FORMATS - }, - .capture = { /* dummy for fast DAI switching */ - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8753_RATES, - .formats = WM8753_FORMATS - }, - .ops = &wm8753_dai_ops_hifi_mode, -}, -/* DAI Voice mode 1 */ -{ .name = "wm8753-voice", - .playback = { - .stream_name = "Voice Playback", - .channels_min = 1, - .channels_max = 1, - .rates = WM8753_RATES, - .formats = WM8753_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8753_RATES, - .formats = WM8753_FORMATS, - }, - .ops = &wm8753_dai_ops_voice_mode, -}, -}; - -static void wm8753_work(struct work_struct *work) -{ - struct snd_soc_dapm_context *dapm = - container_of(work, struct snd_soc_dapm_context, - delayed_work.work); - struct snd_soc_codec *codec = dapm->codec; - wm8753_set_bias_level(codec, dapm->bias_level); -} - -static int wm8753_suspend(struct snd_soc_codec *codec) -{ - wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); - codec->cache_sync = 1; - return 0; -} - -static int wm8753_resume(struct snd_soc_codec *codec) -{ - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - - regcache_sync(wm8753->regmap); - - wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* charge wm8753 caps */ - if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { - wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - codec->dapm.bias_level = SND_SOC_BIAS_ON; - schedule_delayed_work(&codec->dapm.delayed_work, - msecs_to_jiffies(caps_charge)); - } - - return 0; -} - -static int wm8753_probe(struct snd_soc_codec *codec) -{ - struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - int ret; - - INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); - - codec->control_data = wm8753->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = wm8753_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - return ret; - } - - wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8753->dai_func = 0; - - /* charge output caps */ - wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - schedule_delayed_work(&codec->dapm.delayed_work, - msecs_to_jiffies(caps_charge)); - - /* set the update bits */ - snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_LADC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_RADC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100); - - return 0; -} - -/* power down chip */ -static int wm8753_remove(struct snd_soc_codec *codec) -{ - flush_delayed_work_sync(&codec->dapm.delayed_work); - wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { - .probe = wm8753_probe, - .remove = wm8753_remove, - .suspend = wm8753_suspend, - .resume = wm8753_resume, - .set_bias_level = wm8753_set_bias_level, - - .controls = wm8753_snd_controls, - .num_controls = ARRAY_SIZE(wm8753_snd_controls), - .dapm_widgets = wm8753_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets), - .dapm_routes = wm8753_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes), -}; - -static const struct of_device_id wm8753_of_match[] = { - { .compatible = "wlf,wm8753", }, - { } -}; -MODULE_DEVICE_TABLE(of, wm8753_of_match); - -static const struct regmap_config wm8753_regmap = { - .reg_bits = 7, - .val_bits = 9, - - .max_register = WM8753_ADCTL2, - .writeable_reg = wm8753_writeable, - .volatile_reg = wm8753_volatile, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8753_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8753_reg_defaults), -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8753_spi_probe(struct spi_device *spi) -{ - struct wm8753_priv *wm8753; - int ret; - - wm8753 = devm_kzalloc(&spi->dev, sizeof(struct wm8753_priv), - GFP_KERNEL); - if (wm8753 == NULL) - return -ENOMEM; - - spi_set_drvdata(spi, wm8753); - - wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap); - if (IS_ERR(wm8753->regmap)) { - ret = PTR_ERR(wm8753->regmap); - dev_err(&spi->dev, "Failed to allocate register map: %d\n", - ret); - goto err; - } - - ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753, - wm8753_dai, ARRAY_SIZE(wm8753_dai)); - if (ret != 0) { - dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret); - goto err_regmap; - } - - return 0; - -err_regmap: - regmap_exit(wm8753->regmap); -err: - return ret; -} - -static int __devexit wm8753_spi_remove(struct spi_device *spi) -{ - struct wm8753_priv *wm8753 = spi_get_drvdata(spi); - - snd_soc_unregister_codec(&spi->dev); - regmap_exit(wm8753->regmap); - kfree(wm8753); - return 0; -} - -static struct spi_driver wm8753_spi_driver = { - .driver = { - .name = "wm8753", - .owner = THIS_MODULE, - .of_match_table = wm8753_of_match, - }, - .probe = wm8753_spi_probe, - .remove = __devexit_p(wm8753_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8753_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8753_priv *wm8753; - int ret; - - wm8753 = devm_kzalloc(&i2c->dev, sizeof(struct wm8753_priv), - GFP_KERNEL); - if (wm8753 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8753); - - wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap); - if (IS_ERR(wm8753->regmap)) { - ret = PTR_ERR(wm8753->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - goto err; - } - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753, - wm8753_dai, ARRAY_SIZE(wm8753_dai)); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - goto err_regmap; - } - - return 0; - -err_regmap: - regmap_exit(wm8753->regmap); -err: - return ret; -} - -static __devexit int wm8753_i2c_remove(struct i2c_client *client) -{ - struct wm8753_priv *wm8753 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8753->regmap); - return 0; -} - -static const struct i2c_device_id wm8753_i2c_id[] = { - { "wm8753", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); - -static struct i2c_driver wm8753_i2c_driver = { - .driver = { - .name = "wm8753", - .owner = THIS_MODULE, - .of_match_table = wm8753_of_match, - }, - .probe = wm8753_i2c_probe, - .remove = __devexit_p(wm8753_i2c_remove), - .id_table = wm8753_i2c_id, -}; -#endif - -static int __init wm8753_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8753_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8753_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8753 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8753_modinit); - -static void __exit wm8753_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8753_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8753_spi_driver); -#endif -} -module_exit(wm8753_exit); - -MODULE_DESCRIPTION("ASoC WM8753 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8753.h b/ANDROID_3.4.5/sound/soc/codecs/wm8753.h deleted file mode 100644 index 94edac14..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8753.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * wm8753.h -- audio driver for WM8753 - * - * Copyright 2003 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * - * 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. - * - */ - -#ifndef _WM8753_H -#define _WM8753_H - -/* WM8753 register space */ - -#define WM8753_DAC 0x01 -#define WM8753_ADC 0x02 -#define WM8753_PCM 0x03 -#define WM8753_HIFI 0x04 -#define WM8753_IOCTL 0x05 -#define WM8753_SRATE1 0x06 -#define WM8753_SRATE2 0x07 -#define WM8753_LDAC 0x08 -#define WM8753_RDAC 0x09 -#define WM8753_BASS 0x0a -#define WM8753_TREBLE 0x0b -#define WM8753_ALC1 0x0c -#define WM8753_ALC2 0x0d -#define WM8753_ALC3 0x0e -#define WM8753_NGATE 0x0f -#define WM8753_LADC 0x10 -#define WM8753_RADC 0x11 -#define WM8753_ADCTL1 0x12 -#define WM8753_3D 0x13 -#define WM8753_PWR1 0x14 -#define WM8753_PWR2 0x15 -#define WM8753_PWR3 0x16 -#define WM8753_PWR4 0x17 -#define WM8753_ID 0x18 -#define WM8753_INTPOL 0x19 -#define WM8753_INTEN 0x1a -#define WM8753_GPIO1 0x1b -#define WM8753_GPIO2 0x1c -#define WM8753_RESET 0x1f -#define WM8753_RECMIX1 0x20 -#define WM8753_RECMIX2 0x21 -#define WM8753_LOUTM1 0x22 -#define WM8753_LOUTM2 0x23 -#define WM8753_ROUTM1 0x24 -#define WM8753_ROUTM2 0x25 -#define WM8753_MOUTM1 0x26 -#define WM8753_MOUTM2 0x27 -#define WM8753_LOUT1V 0x28 -#define WM8753_ROUT1V 0x29 -#define WM8753_LOUT2V 0x2a -#define WM8753_ROUT2V 0x2b -#define WM8753_MOUTV 0x2c -#define WM8753_OUTCTL 0x2d -#define WM8753_ADCIN 0x2e -#define WM8753_INCTL1 0x2f -#define WM8753_INCTL2 0x30 -#define WM8753_LINVOL 0x31 -#define WM8753_RINVOL 0x32 -#define WM8753_MICBIAS 0x33 -#define WM8753_CLOCK 0x34 -#define WM8753_PLL1CTL1 0x35 -#define WM8753_PLL1CTL2 0x36 -#define WM8753_PLL1CTL3 0x37 -#define WM8753_PLL1CTL4 0x38 -#define WM8753_PLL2CTL1 0x39 -#define WM8753_PLL2CTL2 0x3a -#define WM8753_PLL2CTL3 0x3b -#define WM8753_PLL2CTL4 0x3c -#define WM8753_BIASCTL 0x3d -#define WM8753_ADCTL2 0x3f - -#define WM8753_PLL1 0 -#define WM8753_PLL2 1 - -/* clock inputs */ -#define WM8753_MCLK 0 -#define WM8753_PCMCLK 1 - -/* clock divider id's */ -#define WM8753_PCMDIV 0 -#define WM8753_BCLKDIV 1 -#define WM8753_VXCLKDIV 2 - -/* PCM clock dividers */ -#define WM8753_PCM_DIV_1 (0 << 6) -#define WM8753_PCM_DIV_3 (2 << 6) -#define WM8753_PCM_DIV_5_5 (3 << 6) -#define WM8753_PCM_DIV_2 (4 << 6) -#define WM8753_PCM_DIV_4 (5 << 6) -#define WM8753_PCM_DIV_6 (6 << 6) -#define WM8753_PCM_DIV_8 (7 << 6) - -/* BCLK clock dividers */ -#define WM8753_BCLK_DIV_1 (0 << 3) -#define WM8753_BCLK_DIV_2 (1 << 3) -#define WM8753_BCLK_DIV_4 (2 << 3) -#define WM8753_BCLK_DIV_8 (3 << 3) -#define WM8753_BCLK_DIV_16 (4 << 3) - -/* VXCLK clock dividers */ -#define WM8753_VXCLK_DIV_1 (0 << 6) -#define WM8753_VXCLK_DIV_2 (1 << 6) -#define WM8753_VXCLK_DIV_4 (2 << 6) -#define WM8753_VXCLK_DIV_8 (3 << 6) -#define WM8753_VXCLK_DIV_16 (4 << 6) - -#define WM8753_DAI_HIFI 0 -#define WM8753_DAI_VOICE 1 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8770.c b/ANDROID_3.4.5/sound/soc/codecs/wm8770.c deleted file mode 100644 index a5127b4f..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8770.c +++ /dev/null @@ -1,748 +0,0 @@ -/* - * wm8770.c -- WM8770 ALSA SoC Audio driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8770.h" - -#define WM8770_NUM_SUPPLIES 3 -static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = { - "AVDD1", - "AVDD2", - "DVDD" -}; - -static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = { - 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0x7f, 0x7f, 0x7f, - 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0, 0x90, 0, - 0, 0x22, 0x22, 0x3e, - 0xc, 0xc, 0x100, 0x189, - 0x189, 0x8770 -}; - -struct wm8770_priv { - enum snd_soc_control_type control_type; - struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES]; - struct notifier_block disable_nb[WM8770_NUM_SUPPLIES]; - struct snd_soc_codec *codec; - int sysclk; -}; - -static int vout12supply_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event); -static int vout34supply_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event); - -/* - * We can't use the same notifier block for more than one supply and - * there's no way I can see to get from a callback to the caller - * except container_of(). - */ -#define WM8770_REGULATOR_EVENT(n) \ -static int wm8770_regulator_event_##n(struct notifier_block *nb, \ - unsigned long event, void *data) \ -{ \ - struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \ - disable_nb[n]); \ - if (event & REGULATOR_EVENT_DISABLE) { \ - wm8770->codec->cache_sync = 1; \ - } \ - return 0; \ -} - -WM8770_REGULATOR_EVENT(0) -WM8770_REGULATOR_EVENT(1) -WM8770_REGULATOR_EVENT(2) - -static const DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(dac_dig_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(dac_alg_tlv, -12700, 100, 1); - -static const char *dac_phase_text[][2] = { - { "DAC1 Normal", "DAC1 Inverted" }, - { "DAC2 Normal", "DAC2 Inverted" }, - { "DAC3 Normal", "DAC3 Inverted" }, - { "DAC4 Normal", "DAC4 Inverted" }, -}; - -static const struct soc_enum dac_phase[] = { - SOC_ENUM_DOUBLE(WM8770_DACPHASE, 0, 1, 2, dac_phase_text[0]), - SOC_ENUM_DOUBLE(WM8770_DACPHASE, 2, 3, 2, dac_phase_text[1]), - SOC_ENUM_DOUBLE(WM8770_DACPHASE, 4, 5, 2, dac_phase_text[2]), - SOC_ENUM_DOUBLE(WM8770_DACPHASE, 6, 7, 2, dac_phase_text[3]), -}; - -static const struct snd_kcontrol_new wm8770_snd_controls[] = { - /* global DAC playback controls */ - SOC_SINGLE_TLV("DAC Playback Volume", WM8770_MSDIGVOL, 0, 255, 0, - dac_dig_tlv), - SOC_SINGLE("DAC Playback Switch", WM8770_DACMUTE, 4, 1, 1), - SOC_SINGLE("DAC Playback ZC Switch", WM8770_DACCTRL1, 0, 1, 0), - - /* global VOUT playback controls */ - SOC_SINGLE_TLV("VOUT Playback Volume", WM8770_MSALGVOL, 0, 127, 0, - dac_alg_tlv), - SOC_SINGLE("VOUT Playback ZC Switch", WM8770_MSALGVOL, 7, 1, 0), - - /* VOUT1/2/3/4 specific controls */ - SOC_DOUBLE_R_TLV("VOUT1 Playback Volume", WM8770_VOUT1LVOL, - WM8770_VOUT1RVOL, 0, 127, 0, dac_alg_tlv), - SOC_DOUBLE_R("VOUT1 Playback ZC Switch", WM8770_VOUT1LVOL, - WM8770_VOUT1RVOL, 7, 1, 0), - SOC_DOUBLE_R_TLV("VOUT2 Playback Volume", WM8770_VOUT2LVOL, - WM8770_VOUT2RVOL, 0, 127, 0, dac_alg_tlv), - SOC_DOUBLE_R("VOUT2 Playback ZC Switch", WM8770_VOUT2LVOL, - WM8770_VOUT2RVOL, 7, 1, 0), - SOC_DOUBLE_R_TLV("VOUT3 Playback Volume", WM8770_VOUT3LVOL, - WM8770_VOUT3RVOL, 0, 127, 0, dac_alg_tlv), - SOC_DOUBLE_R("VOUT3 Playback ZC Switch", WM8770_VOUT3LVOL, - WM8770_VOUT3RVOL, 7, 1, 0), - SOC_DOUBLE_R_TLV("VOUT4 Playback Volume", WM8770_VOUT4LVOL, - WM8770_VOUT4RVOL, 0, 127, 0, dac_alg_tlv), - SOC_DOUBLE_R("VOUT4 Playback ZC Switch", WM8770_VOUT4LVOL, - WM8770_VOUT4RVOL, 7, 1, 0), - - /* DAC1/2/3/4 specific controls */ - SOC_DOUBLE_R_TLV("DAC1 Playback Volume", WM8770_DAC1LVOL, - WM8770_DAC1RVOL, 0, 255, 0, dac_dig_tlv), - SOC_SINGLE("DAC1 Deemphasis Switch", WM8770_DACCTRL2, 0, 1, 0), - SOC_ENUM("DAC1 Phase", dac_phase[0]), - SOC_DOUBLE_R_TLV("DAC2 Playback Volume", WM8770_DAC2LVOL, - WM8770_DAC2RVOL, 0, 255, 0, dac_dig_tlv), - SOC_SINGLE("DAC2 Deemphasis Switch", WM8770_DACCTRL2, 1, 1, 0), - SOC_ENUM("DAC2 Phase", dac_phase[1]), - SOC_DOUBLE_R_TLV("DAC3 Playback Volume", WM8770_DAC3LVOL, - WM8770_DAC3RVOL, 0, 255, 0, dac_dig_tlv), - SOC_SINGLE("DAC3 Deemphasis Switch", WM8770_DACCTRL2, 2, 1, 0), - SOC_ENUM("DAC3 Phase", dac_phase[2]), - SOC_DOUBLE_R_TLV("DAC4 Playback Volume", WM8770_DAC4LVOL, - WM8770_DAC4RVOL, 0, 255, 0, dac_dig_tlv), - SOC_SINGLE("DAC4 Deemphasis Switch", WM8770_DACCTRL2, 3, 1, 0), - SOC_ENUM("DAC4 Phase", dac_phase[3]), - - /* ADC specific controls */ - SOC_DOUBLE_R_TLV("Capture Volume", WM8770_ADCLCTRL, WM8770_ADCRCTRL, - 0, 31, 0, adc_tlv), - SOC_DOUBLE_R("Capture Switch", WM8770_ADCLCTRL, WM8770_ADCRCTRL, - 5, 1, 1), - - /* other controls */ - SOC_SINGLE("ADC 128x Oversampling Switch", WM8770_MSTRCTRL, 3, 1, 0), - SOC_SINGLE("ADC Highpass Filter Switch", WM8770_IFACECTRL, 8, 1, 1) -}; - -static const char *ain_text[] = { - "AIN1", "AIN2", "AIN3", "AIN4", - "AIN5", "AIN6", "AIN7", "AIN8" -}; - -static const struct soc_enum ain_enum = - SOC_ENUM_DOUBLE(WM8770_ADCMUX, 0, 4, 8, ain_text); - -static const struct snd_kcontrol_new ain_mux = - SOC_DAPM_ENUM("Capture Mux", ain_enum); - -static const struct snd_kcontrol_new vout1_mix_controls[] = { - SOC_DAPM_SINGLE("DAC1 Switch", WM8770_OUTMUX1, 0, 1, 0), - SOC_DAPM_SINGLE("AUX1 Switch", WM8770_OUTMUX1, 1, 1, 0), - SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 2, 1, 0) -}; - -static const struct snd_kcontrol_new vout2_mix_controls[] = { - SOC_DAPM_SINGLE("DAC2 Switch", WM8770_OUTMUX1, 3, 1, 0), - SOC_DAPM_SINGLE("AUX2 Switch", WM8770_OUTMUX1, 4, 1, 0), - SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX1, 5, 1, 0) -}; - -static const struct snd_kcontrol_new vout3_mix_controls[] = { - SOC_DAPM_SINGLE("DAC3 Switch", WM8770_OUTMUX2, 0, 1, 0), - SOC_DAPM_SINGLE("AUX3 Switch", WM8770_OUTMUX2, 1, 1, 0), - SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 2, 1, 0) -}; - -static const struct snd_kcontrol_new vout4_mix_controls[] = { - SOC_DAPM_SINGLE("DAC4 Switch", WM8770_OUTMUX2, 3, 1, 0), - SOC_DAPM_SINGLE("Bypass Switch", WM8770_OUTMUX2, 4, 1, 0) -}; - -static const struct snd_soc_dapm_widget wm8770_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("AUX1"), - SND_SOC_DAPM_INPUT("AUX2"), - SND_SOC_DAPM_INPUT("AUX3"), - - SND_SOC_DAPM_INPUT("AIN1"), - SND_SOC_DAPM_INPUT("AIN2"), - SND_SOC_DAPM_INPUT("AIN3"), - SND_SOC_DAPM_INPUT("AIN4"), - SND_SOC_DAPM_INPUT("AIN5"), - SND_SOC_DAPM_INPUT("AIN6"), - SND_SOC_DAPM_INPUT("AIN7"), - SND_SOC_DAPM_INPUT("AIN8"), - - SND_SOC_DAPM_MUX("Capture Mux", WM8770_ADCMUX, 8, 1, &ain_mux), - - SND_SOC_DAPM_ADC("ADC", "Capture", WM8770_PWDNCTRL, 1, 1), - - SND_SOC_DAPM_DAC("DAC1", "Playback", WM8770_PWDNCTRL, 2, 1), - SND_SOC_DAPM_DAC("DAC2", "Playback", WM8770_PWDNCTRL, 3, 1), - SND_SOC_DAPM_DAC("DAC3", "Playback", WM8770_PWDNCTRL, 4, 1), - SND_SOC_DAPM_DAC("DAC4", "Playback", WM8770_PWDNCTRL, 5, 1), - - SND_SOC_DAPM_SUPPLY("VOUT12 Supply", SND_SOC_NOPM, 0, 0, - vout12supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_SUPPLY("VOUT34 Supply", SND_SOC_NOPM, 0, 0, - vout34supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_MIXER("VOUT1 Mixer", SND_SOC_NOPM, 0, 0, - vout1_mix_controls, ARRAY_SIZE(vout1_mix_controls)), - SND_SOC_DAPM_MIXER("VOUT2 Mixer", SND_SOC_NOPM, 0, 0, - vout2_mix_controls, ARRAY_SIZE(vout2_mix_controls)), - SND_SOC_DAPM_MIXER("VOUT3 Mixer", SND_SOC_NOPM, 0, 0, - vout3_mix_controls, ARRAY_SIZE(vout3_mix_controls)), - SND_SOC_DAPM_MIXER("VOUT4 Mixer", SND_SOC_NOPM, 0, 0, - vout4_mix_controls, ARRAY_SIZE(vout4_mix_controls)), - - SND_SOC_DAPM_OUTPUT("VOUT1"), - SND_SOC_DAPM_OUTPUT("VOUT2"), - SND_SOC_DAPM_OUTPUT("VOUT3"), - SND_SOC_DAPM_OUTPUT("VOUT4") -}; - -static const struct snd_soc_dapm_route wm8770_intercon[] = { - { "Capture Mux", "AIN1", "AIN1" }, - { "Capture Mux", "AIN2", "AIN2" }, - { "Capture Mux", "AIN3", "AIN3" }, - { "Capture Mux", "AIN4", "AIN4" }, - { "Capture Mux", "AIN5", "AIN5" }, - { "Capture Mux", "AIN6", "AIN6" }, - { "Capture Mux", "AIN7", "AIN7" }, - { "Capture Mux", "AIN8", "AIN8" }, - - { "ADC", NULL, "Capture Mux" }, - - { "VOUT1 Mixer", NULL, "VOUT12 Supply" }, - { "VOUT1 Mixer", "DAC1 Switch", "DAC1" }, - { "VOUT1 Mixer", "AUX1 Switch", "AUX1" }, - { "VOUT1 Mixer", "Bypass Switch", "Capture Mux" }, - - { "VOUT2 Mixer", NULL, "VOUT12 Supply" }, - { "VOUT2 Mixer", "DAC2 Switch", "DAC2" }, - { "VOUT2 Mixer", "AUX2 Switch", "AUX2" }, - { "VOUT2 Mixer", "Bypass Switch", "Capture Mux" }, - - { "VOUT3 Mixer", NULL, "VOUT34 Supply" }, - { "VOUT3 Mixer", "DAC3 Switch", "DAC3" }, - { "VOUT3 Mixer", "AUX3 Switch", "AUX3" }, - { "VOUT3 Mixer", "Bypass Switch", "Capture Mux" }, - - { "VOUT4 Mixer", NULL, "VOUT34 Supply" }, - { "VOUT4 Mixer", "DAC4 Switch", "DAC4" }, - { "VOUT4 Mixer", "Bypass Switch", "Capture Mux" }, - - { "VOUT1", NULL, "VOUT1 Mixer" }, - { "VOUT2", NULL, "VOUT2 Mixer" }, - { "VOUT3", NULL, "VOUT3 Mixer" }, - { "VOUT4", NULL, "VOUT4 Mixer" } -}; - -static int vout12supply_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec; - - codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0); - break; - case SND_SOC_DAPM_POST_PMD: - snd_soc_update_bits(codec, WM8770_OUTMUX1, 0x180, 0x180); - break; - } - - return 0; -} - -static int vout34supply_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec; - - codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0); - break; - case SND_SOC_DAPM_POST_PMD: - snd_soc_update_bits(codec, WM8770_OUTMUX2, 0x180, 0x180); - break; - } - - return 0; -} - -static int wm8770_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8770_RESET, 0); -} - -static int wm8770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec; - int iface, master; - - codec = dai->codec; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - master = 0x100; - break; - case SND_SOC_DAIFMT_CBS_CFS: - master = 0; - break; - default: - return -EINVAL; - } - - iface = 0; - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0xc; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x8; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x4; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8770_IFACECTRL, 0xf, iface); - snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x100, master); - - return 0; -} - -static const int mclk_ratios[] = { - 128, - 192, - 256, - 384, - 512, - 768 -}; - -static int wm8770_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec; - struct wm8770_priv *wm8770; - int i; - int iface; - int shift; - int ratio; - - codec = dai->codec; - wm8770 = snd_soc_codec_get_drvdata(codec); - - iface = 0; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x10; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x20; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x30; - break; - } - - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - i = 0; - shift = 4; - break; - case SNDRV_PCM_STREAM_CAPTURE: - i = 2; - shift = 0; - break; - default: - return -EINVAL; - } - - /* Only need to set MCLK/LRCLK ratio if we're master */ - if (snd_soc_read(codec, WM8770_MSTRCTRL) & 0x100) { - for (; i < ARRAY_SIZE(mclk_ratios); ++i) { - ratio = wm8770->sysclk / params_rate(params); - if (ratio == mclk_ratios[i]) - break; - } - - if (i == ARRAY_SIZE(mclk_ratios)) { - dev_err(codec->dev, - "Unable to configure MCLK ratio %d/%d\n", - wm8770->sysclk, params_rate(params)); - return -EINVAL; - } - - dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]); - - snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x7 << shift, - i << shift); - } - - snd_soc_update_bits(codec, WM8770_IFACECTRL, 0x30, iface); - - return 0; -} - -static int wm8770_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec; - - codec = dai->codec; - return snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, - !!mute << 4); -} - -static int wm8770_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec; - struct wm8770_priv *wm8770; - - codec = dai->codec; - wm8770 = snd_soc_codec_get_drvdata(codec); - wm8770->sysclk = freq; - return 0; -} - -static void wm8770_sync_cache(struct snd_soc_codec *codec) -{ - int i; - u16 *cache; - - if (!codec->cache_sync) - return; - - codec->cache_only = 0; - cache = codec->reg_cache; - for (i = 0; i < codec->driver->reg_cache_size; i++) { - if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i]) - continue; - snd_soc_write(codec, i, cache[i]); - } - codec->cache_sync = 0; -} - -static int wm8770_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - struct wm8770_priv *wm8770; - - wm8770 = snd_soc_codec_get_drvdata(codec); - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), - wm8770->supplies); - if (ret) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - wm8770_sync_cache(codec); - /* global powerup */ - snd_soc_write(codec, WM8770_PWDNCTRL, 0); - } - break; - case SND_SOC_BIAS_OFF: - /* global powerdown */ - snd_soc_write(codec, WM8770_PWDNCTRL, 1); - regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), - wm8770->supplies); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#define WM8770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8770_dai_ops = { - .digital_mute = wm8770_mute, - .hw_params = wm8770_hw_params, - .set_fmt = wm8770_set_fmt, - .set_sysclk = wm8770_set_sysclk, -}; - -static struct snd_soc_dai_driver wm8770_dai = { - .name = "wm8770-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = WM8770_FORMATS - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = WM8770_FORMATS - }, - .ops = &wm8770_dai_ops, - .symmetric_rates = 1 -}; - -#ifdef CONFIG_PM -static int wm8770_suspend(struct snd_soc_codec *codec) -{ - wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8770_resume(struct snd_soc_codec *codec) -{ - wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define wm8770_suspend NULL -#define wm8770_resume NULL -#endif - -static int wm8770_probe(struct snd_soc_codec *codec) -{ - struct wm8770_priv *wm8770; - int ret; - int i; - - wm8770 = snd_soc_codec_get_drvdata(codec); - wm8770->codec = codec; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) - wm8770->supplies[i].supply = wm8770_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies), - wm8770->supplies); - if (ret) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0; - wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1; - wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2; - - /* This should really be moved into the regulator core */ - for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) { - ret = regulator_register_notifier(wm8770->supplies[i].consumer, - &wm8770->disable_nb[i]); - if (ret) { - dev_err(codec->dev, - "Failed to register regulator notifier: %d\n", - ret); - } - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), - wm8770->supplies); - if (ret) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_reg_get; - } - - ret = wm8770_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err_reg_enable; - } - - wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* latch the volume update bits */ - snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_VOUT1RVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_VOUT2RVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_VOUT3RVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_VOUT4RVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_DAC1RVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_DAC2RVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_DAC3RVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8770_DAC4RVOL, 0x100, 0x100); - - /* mute all DACs */ - snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10); - - snd_soc_add_codec_controls(codec, wm8770_snd_controls, - ARRAY_SIZE(wm8770_snd_controls)); - snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets, - ARRAY_SIZE(wm8770_dapm_widgets)); - snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon, - ARRAY_SIZE(wm8770_intercon)); - return 0; - -err_reg_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); -err_reg_get: - regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); - return ret; -} - -static int wm8770_remove(struct snd_soc_codec *codec) -{ - struct wm8770_priv *wm8770; - int i; - - wm8770 = snd_soc_codec_get_drvdata(codec); - wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF); - - for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i) - regulator_unregister_notifier(wm8770->supplies[i].consumer, - &wm8770->disable_nb[i]); - regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { - .probe = wm8770_probe, - .remove = wm8770_remove, - .suspend = wm8770_suspend, - .resume = wm8770_resume, - .set_bias_level = wm8770_set_bias_level, - .idle_bias_off = true, - .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs), - .reg_word_size = sizeof (u16), - .reg_cache_default = wm8770_reg_defs -}; - -static const struct of_device_id wm8770_of_match[] = { - { .compatible = "wlf,wm8770", }, - { } -}; -MODULE_DEVICE_TABLE(of, wm8770_of_match); - -static int __devinit wm8770_spi_probe(struct spi_device *spi) -{ - struct wm8770_priv *wm8770; - int ret; - - wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv), - GFP_KERNEL); - if (!wm8770) - return -ENOMEM; - - wm8770->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8770); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8770, &wm8770_dai, 1); - - return ret; -} - -static int __devexit wm8770_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver wm8770_spi_driver = { - .driver = { - .name = "wm8770", - .owner = THIS_MODULE, - .of_match_table = wm8770_of_match, - }, - .probe = wm8770_spi_probe, - .remove = __devexit_p(wm8770_spi_remove) -}; - -static int __init wm8770_modinit(void) -{ - int ret = 0; - - ret = spi_register_driver(&wm8770_spi_driver); - if (ret) { - printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n", - ret); - } - return ret; -} -module_init(wm8770_modinit); - -static void __exit wm8770_exit(void) -{ - spi_unregister_driver(&wm8770_spi_driver); -} -module_exit(wm8770_exit); - -MODULE_DESCRIPTION("ASoC WM8770 driver"); -MODULE_AUTHOR("Dimitris Papastamos "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8770.h b/ANDROID_3.4.5/sound/soc/codecs/wm8770.h deleted file mode 100644 index 5f1b3bda..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8770.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * wm8770.h -- WM8770 ASoC driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8770_H -#define _WM8770_H - -/* Registers */ -#define WM8770_VOUT1LVOL 0 -#define WM8770_VOUT1RVOL 0x1 -#define WM8770_VOUT2LVOL 0x2 -#define WM8770_VOUT2RVOL 0x3 -#define WM8770_VOUT3LVOL 0x4 -#define WM8770_VOUT3RVOL 0x5 -#define WM8770_VOUT4LVOL 0x6 -#define WM8770_VOUT4RVOL 0x7 -#define WM8770_MSALGVOL 0x8 -#define WM8770_DAC1LVOL 0x9 -#define WM8770_DAC1RVOL 0xa -#define WM8770_DAC2LVOL 0xb -#define WM8770_DAC2RVOL 0xc -#define WM8770_DAC3LVOL 0xd -#define WM8770_DAC3RVOL 0xe -#define WM8770_DAC4LVOL 0xf -#define WM8770_DAC4RVOL 0x10 -#define WM8770_MSDIGVOL 0x11 -#define WM8770_DACPHASE 0x12 -#define WM8770_DACCTRL1 0x13 -#define WM8770_DACMUTE 0x14 -#define WM8770_DACCTRL2 0x15 -#define WM8770_IFACECTRL 0x16 -#define WM8770_MSTRCTRL 0x17 -#define WM8770_PWDNCTRL 0x18 -#define WM8770_ADCLCTRL 0x19 -#define WM8770_ADCRCTRL 0x1a -#define WM8770_ADCMUX 0x1b -#define WM8770_OUTMUX1 0x1c -#define WM8770_OUTMUX2 0x1d -#define WM8770_RESET 0x31 - -#define WM8770_CACHEREGNUM 0x20 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8776.c b/ANDROID_3.4.5/sound/soc/codecs/wm8776.c deleted file mode 100644 index a19db5a0..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8776.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * wm8776.c -- WM8776 ALSA SoC Audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: Input ALC/limiter support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8776.h" - -enum wm8776_chip_type { - WM8775 = 1, - WM8776, -}; - -/* codec private data */ -struct wm8776_priv { - enum snd_soc_control_type control_type; - int sysclk[2]; -}; - -static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { - 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ - 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ - 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */ - 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */ - 0xa6, 0x01, 0x01 -}; - -static int wm8776_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8776_RESET, 0); -} - -static const DECLARE_TLV_DB_SCALE(hp_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1); - -static const struct snd_kcontrol_new wm8776_snd_controls[] = { -SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8776_HPLVOL, WM8776_HPRVOL, - 0, 127, 0, hp_tlv), -SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8776_DACLVOL, WM8776_DACRVOL, - 0, 255, 0, dac_tlv), -SOC_SINGLE("Digital Playback ZC Switch", WM8776_DACCTRL1, 0, 1, 0), - -SOC_SINGLE("Deemphasis Switch", WM8776_DACCTRL2, 0, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8776_ADCLVOL, WM8776_ADCRVOL, - 0, 255, 0, adc_tlv), -SOC_DOUBLE("Capture Switch", WM8776_ADCMUX, 7, 6, 1, 1), -SOC_DOUBLE_R("Capture ZC Switch", WM8776_ADCLVOL, WM8776_ADCRVOL, 8, 1, 0), -SOC_SINGLE("Capture HPF Switch", WM8776_ADCIFCTRL, 8, 1, 1), -}; - -static const struct snd_kcontrol_new inmix_controls[] = { -SOC_DAPM_SINGLE("AIN1 Switch", WM8776_ADCMUX, 0, 1, 0), -SOC_DAPM_SINGLE("AIN2 Switch", WM8776_ADCMUX, 1, 1, 0), -SOC_DAPM_SINGLE("AIN3 Switch", WM8776_ADCMUX, 2, 1, 0), -SOC_DAPM_SINGLE("AIN4 Switch", WM8776_ADCMUX, 3, 1, 0), -SOC_DAPM_SINGLE("AIN5 Switch", WM8776_ADCMUX, 4, 1, 0), -}; - -static const struct snd_kcontrol_new outmix_controls[] = { -SOC_DAPM_SINGLE("DAC Switch", WM8776_OUTMUX, 0, 1, 0), -SOC_DAPM_SINGLE("AUX Switch", WM8776_OUTMUX, 1, 1, 0), -SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("AUX"), - -SND_SOC_DAPM_INPUT("AIN1"), -SND_SOC_DAPM_INPUT("AIN2"), -SND_SOC_DAPM_INPUT("AIN3"), -SND_SOC_DAPM_INPUT("AIN4"), -SND_SOC_DAPM_INPUT("AIN5"), - -SND_SOC_DAPM_MIXER("Input Mixer", WM8776_PWRDOWN, 6, 1, - inmix_controls, ARRAY_SIZE(inmix_controls)), - -SND_SOC_DAPM_ADC("ADC", "Capture", WM8776_PWRDOWN, 1, 1), -SND_SOC_DAPM_DAC("DAC", "Playback", WM8776_PWRDOWN, 2, 1), - -SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, - outmix_controls, ARRAY_SIZE(outmix_controls)), - -SND_SOC_DAPM_PGA("Headphone PGA", WM8776_PWRDOWN, 3, 1, NULL, 0), - -SND_SOC_DAPM_OUTPUT("VOUT"), - -SND_SOC_DAPM_OUTPUT("HPOUTL"), -SND_SOC_DAPM_OUTPUT("HPOUTR"), -}; - -static const struct snd_soc_dapm_route routes[] = { - { "Input Mixer", "AIN1 Switch", "AIN1" }, - { "Input Mixer", "AIN2 Switch", "AIN2" }, - { "Input Mixer", "AIN3 Switch", "AIN3" }, - { "Input Mixer", "AIN4 Switch", "AIN4" }, - { "Input Mixer", "AIN5 Switch", "AIN5" }, - - { "ADC", NULL, "Input Mixer" }, - - { "Output Mixer", "DAC Switch", "DAC" }, - { "Output Mixer", "AUX Switch", "AUX" }, - { "Output Mixer", "Bypass Switch", "Input Mixer" }, - - { "VOUT", NULL, "Output Mixer" }, - - { "Headphone PGA", NULL, "Output Mixer" }, - - { "HPOUTL", NULL, "Headphone PGA" }, - { "HPOUTR", NULL, "Headphone PGA" }, -}; - -static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - int reg, iface, master; - - switch (dai->driver->id) { - case WM8776_DAI_DAC: - reg = WM8776_DACIFCTRL; - master = 0x80; - break; - case WM8776_DAI_ADC: - reg = WM8776_ADCIFCTRL; - master = 0x100; - break; - default: - return -EINVAL; - } - - iface = 0; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - case SND_SOC_DAIFMT_CBS_CFS: - master = 0; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x00c; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x008; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x004; - break; - default: - return -EINVAL; - } - - /* Finally, write out the values */ - snd_soc_update_bits(codec, reg, 0xf, iface); - snd_soc_update_bits(codec, WM8776_MSTRCTRL, 0x180, master); - - return 0; -} - -static int mclk_ratios[] = { - 128, - 192, - 256, - 384, - 512, - 768, -}; - -static int wm8776_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); - int iface_reg, iface; - int ratio_shift, master; - int i; - - switch (dai->driver->id) { - case WM8776_DAI_DAC: - iface_reg = WM8776_DACIFCTRL; - master = 0x80; - ratio_shift = 4; - break; - case WM8776_DAI_ADC: - iface_reg = WM8776_ADCIFCTRL; - master = 0x100; - ratio_shift = 0; - break; - default: - return -EINVAL; - } - - /* Set word length */ - switch (snd_pcm_format_width(params_format(params))) { - case 16: - iface = 0; - break; - case 20: - iface = 0x10; - break; - case 24: - iface = 0x20; - break; - case 32: - iface = 0x30; - break; - default: - dev_err(codec->dev, "Unsupported sample size: %i\n", - snd_pcm_format_width(params_format(params))); - return -EINVAL; - } - - /* Only need to set MCLK/LRCLK ratio if we're master */ - if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { - for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { - if (wm8776->sysclk[dai->driver->id] / params_rate(params) - == mclk_ratios[i]) - break; - } - - if (i == ARRAY_SIZE(mclk_ratios)) { - dev_err(codec->dev, - "Unable to configure MCLK ratio %d/%d\n", - wm8776->sysclk[dai->driver->id], params_rate(params)); - return -EINVAL; - } - - dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]); - - snd_soc_update_bits(codec, WM8776_MSTRCTRL, - 0x7 << ratio_shift, i << ratio_shift); - } else { - dev_dbg(codec->dev, "DAI in slave mode\n"); - } - - snd_soc_update_bits(codec, iface_reg, 0x30, iface); - - return 0; -} - -static int wm8776_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - return snd_soc_write(codec, WM8776_DACMUTE, !!mute); -} - -static int wm8776_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); - - BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk)); - - wm8776->sysclk[dai->driver->id] = freq; - - return 0; -} - -static int wm8776_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); - - /* Disable the global powerdown; DAPM does the rest */ - snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); - } - - break; - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8776_dac_ops = { - .digital_mute = wm8776_mute, - .hw_params = wm8776_hw_params, - .set_fmt = wm8776_set_fmt, - .set_sysclk = wm8776_set_sysclk, -}; - -static const struct snd_soc_dai_ops wm8776_adc_ops = { - .hw_params = wm8776_hw_params, - .set_fmt = wm8776_set_fmt, - .set_sysclk = wm8776_set_sysclk, -}; - -static struct snd_soc_dai_driver wm8776_dai[] = { - { - .name = "wm8776-hifi-playback", - .id = WM8776_DAI_DAC, - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 32000, - .rate_max = 192000, - .formats = WM8776_FORMATS, - }, - .ops = &wm8776_dac_ops, - }, - { - .name = "wm8776-hifi-capture", - .id = WM8776_DAI_ADC, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 32000, - .rate_max = 96000, - .formats = WM8776_FORMATS, - }, - .ops = &wm8776_adc_ops, - }, -}; - -#ifdef CONFIG_PM -static int wm8776_suspend(struct snd_soc_codec *codec) -{ - wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8776_resume(struct snd_soc_codec *codec) -{ - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define wm8776_suspend NULL -#define wm8776_resume NULL -#endif - -static int wm8776_probe(struct snd_soc_codec *codec) -{ - struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = wm8776_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - return ret; - } - - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch the update bits; right channel only since we always - * update both. */ - snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); - - return ret; -} - -/* power down chip */ -static int wm8776_remove(struct snd_soc_codec *codec) -{ - wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { - .probe = wm8776_probe, - .remove = wm8776_remove, - .suspend = wm8776_suspend, - .resume = wm8776_resume, - .set_bias_level = wm8776_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8776_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8776_reg, - - .controls = wm8776_snd_controls, - .num_controls = ARRAY_SIZE(wm8776_snd_controls), - .dapm_widgets = wm8776_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8776_dapm_widgets), - .dapm_routes = routes, - .num_dapm_routes = ARRAY_SIZE(routes), -}; - -static const struct of_device_id wm8776_of_match[] = { - { .compatible = "wlf,wm8776", }, - { } -}; -MODULE_DEVICE_TABLE(of, wm8776_of_match); - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8776_spi_probe(struct spi_device *spi) -{ - struct wm8776_priv *wm8776; - int ret; - - wm8776 = devm_kzalloc(&spi->dev, sizeof(struct wm8776_priv), - GFP_KERNEL); - if (wm8776 == NULL) - return -ENOMEM; - - wm8776->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8776); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); - - return ret; -} - -static int __devexit wm8776_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver wm8776_spi_driver = { - .driver = { - .name = "wm8776", - .owner = THIS_MODULE, - .of_match_table = wm8776_of_match, - }, - .probe = wm8776_spi_probe, - .remove = __devexit_p(wm8776_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8776_priv *wm8776; - int ret; - - wm8776 = devm_kzalloc(&i2c->dev, sizeof(struct wm8776_priv), - GFP_KERNEL); - if (wm8776 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8776); - wm8776->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); - - return ret; -} - -static __devexit int wm8776_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id wm8776_i2c_id[] = { - { "wm8775", WM8775 }, - { "wm8776", WM8776 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); - -static struct i2c_driver wm8776_i2c_driver = { - .driver = { - .name = "wm8776", - .owner = THIS_MODULE, - .of_match_table = wm8776_of_match, - }, - .probe = wm8776_i2c_probe, - .remove = __devexit_p(wm8776_i2c_remove), - .id_table = wm8776_i2c_id, -}; -#endif - -static int __init wm8776_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8776_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8776_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8776 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8776_modinit); - -static void __exit wm8776_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8776_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8776_spi_driver); -#endif -} -module_exit(wm8776_exit); - -MODULE_DESCRIPTION("ASoC WM8776 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8776.h b/ANDROID_3.4.5/sound/soc/codecs/wm8776.h deleted file mode 100644 index 4cf1c8e0..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8776.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * wm8776.h -- WM8776 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8776_H -#define _WM8776_H - -/* Registers */ - -#define WM8776_HPLVOL 0x00 -#define WM8776_HPRVOL 0x01 -#define WM8776_HPMASTER 0x02 -#define WM8776_DACLVOL 0x03 -#define WM8776_DACRVOL 0x04 -#define WM8776_DACMASTER 0x05 -#define WM8776_PHASESWAP 0x06 -#define WM8776_DACCTRL1 0x07 -#define WM8776_DACMUTE 0x08 -#define WM8776_DACCTRL2 0x09 -#define WM8776_DACIFCTRL 0x0a -#define WM8776_ADCIFCTRL 0x0b -#define WM8776_MSTRCTRL 0x0c -#define WM8776_PWRDOWN 0x0d -#define WM8776_ADCLVOL 0x0e -#define WM8776_ADCRVOL 0x0f -#define WM8776_ALCCTRL1 0x10 -#define WM8776_ALCCTRL2 0x11 -#define WM8776_ALCCTRL3 0x12 -#define WM8776_NOISEGATE 0x13 -#define WM8776_LIMITER 0x14 -#define WM8776_ADCMUX 0x15 -#define WM8776_OUTMUX 0x16 -#define WM8776_RESET 0x17 - -#define WM8776_CACHEREGNUM 0x17 - -#define WM8776_DAI_DAC 0 -#define WM8776_DAI_ADC 1 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8782.c b/ANDROID_3.4.5/sound/soc/codecs/wm8782.c deleted file mode 100644 index 3fdea98f..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8782.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * sound/soc/codecs/wm8782.c - * simple, strap-pin configured 24bit 2ch ADC - * - * Copyright: 2011 Raumfeld GmbH - * Author: Johannes Stezenbach - * - * based on ad73311.c - * Copyright: Analog Device Inc. - * Author: Cliff Cai - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct snd_soc_dai_driver wm8782_dai = { - .name = "wm8782", - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - /* For configurations with FSAMPEN=0 */ - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE, - }, -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm8782; - -static __devinit int wm8782_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_wm8782, &wm8782_dai, 1); -} - -static int __devexit wm8782_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver wm8782_codec_driver = { - .driver = { - .name = "wm8782", - .owner = THIS_MODULE, - }, - .probe = wm8782_probe, - .remove = __devexit_p(wm8782_remove), -}; - -module_platform_driver(wm8782_codec_driver); - -MODULE_DESCRIPTION("ASoC WM8782 driver"); -MODULE_AUTHOR("Johannes Stezenbach "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8804.c b/ANDROID_3.4.5/sound/soc/codecs/wm8804.c deleted file mode 100644 index 6bd1b767..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8804.c +++ /dev/null @@ -1,841 +0,0 @@ -/* - * wm8804.c -- WM8804 S/PDIF transceiver driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8804.h" - -#define WM8804_NUM_SUPPLIES 2 -static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = { - "PVDD", - "DVDD" -}; - -static const struct reg_default wm8804_reg_defaults[] = { - { 3, 0x21 }, /* R3 - PLL1 */ - { 4, 0xFD }, /* R4 - PLL2 */ - { 5, 0x36 }, /* R5 - PLL3 */ - { 6, 0x07 }, /* R6 - PLL4 */ - { 7, 0x16 }, /* R7 - PLL5 */ - { 8, 0x18 }, /* R8 - PLL6 */ - { 9, 0xFF }, /* R9 - SPDMODE */ - { 10, 0x00 }, /* R10 - INTMASK */ - { 18, 0x00 }, /* R18 - SPDTX1 */ - { 19, 0x00 }, /* R19 - SPDTX2 */ - { 20, 0x00 }, /* R20 - SPDTX3 */ - { 21, 0x71 }, /* R21 - SPDTX4 */ - { 22, 0x0B }, /* R22 - SPDTX5 */ - { 23, 0x70 }, /* R23 - GPO0 */ - { 24, 0x57 }, /* R24 - GPO1 */ - { 26, 0x42 }, /* R26 - GPO2 */ - { 27, 0x06 }, /* R27 - AIFTX */ - { 28, 0x06 }, /* R28 - AIFRX */ - { 29, 0x80 }, /* R29 - SPDRX1 */ - { 30, 0x07 }, /* R30 - PWRDN */ -}; - -struct wm8804_priv { - struct regmap *regmap; - struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES]; - struct notifier_block disable_nb[WM8804_NUM_SUPPLIES]; -}; - -static int txsrc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - -static int txsrc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - -/* - * We can't use the same notifier block for more than one supply and - * there's no way I can see to get from a callback to the caller - * except container_of(). - */ -#define WM8804_REGULATOR_EVENT(n) \ -static int wm8804_regulator_event_##n(struct notifier_block *nb, \ - unsigned long event, void *data) \ -{ \ - struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \ - disable_nb[n]); \ - if (event & REGULATOR_EVENT_DISABLE) { \ - regcache_mark_dirty(wm8804->regmap); \ - } \ - return 0; \ -} - -WM8804_REGULATOR_EVENT(0) -WM8804_REGULATOR_EVENT(1) - -static const char *txsrc_text[] = { "S/PDIF RX", "AIF" }; -static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text); - -static const struct snd_kcontrol_new wm8804_snd_controls[] = { - SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put), - SOC_SINGLE("TX Playback Switch", WM8804_PWRDN, 2, 1, 1), - SOC_SINGLE("AIF Playback Switch", WM8804_PWRDN, 4, 1, 1) -}; - -static int txsrc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec; - unsigned int src; - - codec = snd_kcontrol_chip(kcontrol); - src = snd_soc_read(codec, WM8804_SPDTX4); - if (src & 0x40) - ucontrol->value.integer.value[0] = 1; - else - ucontrol->value.integer.value[0] = 0; - - return 0; -} - -static int txsrc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec; - unsigned int src, txpwr; - - codec = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.integer.value[0] != 0 - && ucontrol->value.integer.value[0] != 1) - return -EINVAL; - - src = snd_soc_read(codec, WM8804_SPDTX4); - switch ((src & 0x40) >> 6) { - case 0: - if (!ucontrol->value.integer.value[0]) - return 0; - break; - case 1: - if (ucontrol->value.integer.value[1]) - return 0; - break; - } - - /* save the current power state of the transmitter */ - txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4; - /* power down the transmitter */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4); - /* set the tx source */ - snd_soc_update_bits(codec, WM8804_SPDTX4, 0x40, - ucontrol->value.integer.value[0] << 6); - - if (ucontrol->value.integer.value[0]) { - /* power down the receiver */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0x2); - /* power up the AIF */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x10, 0); - } else { - /* don't power down the AIF -- may be used as an output */ - /* power up the receiver */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0); - } - - /* restore the transmitter's configuration */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr); - - return 0; -} - -static bool wm8804_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8804_RST_DEVID1: - case WM8804_DEVID2: - case WM8804_DEVREV: - case WM8804_INTSTAT: - case WM8804_SPDSTAT: - case WM8804_RXCHAN1: - case WM8804_RXCHAN2: - case WM8804_RXCHAN3: - case WM8804_RXCHAN4: - case WM8804_RXCHAN5: - return true; - default: - return false; - } -} - -static int wm8804_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8804_RST_DEVID1, 0x0); -} - -static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec; - u16 format, master, bcp, lrp; - - codec = dai->codec; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - format = 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - format = 0x0; - break; - case SND_SOC_DAIFMT_LEFT_J: - format = 0x1; - break; - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - format = 0x3; - break; - default: - dev_err(dai->dev, "Unknown dai format\n"); - return -EINVAL; - } - - /* set data format */ - snd_soc_update_bits(codec, WM8804_AIFTX, 0x3, format); - snd_soc_update_bits(codec, WM8804_AIFRX, 0x3, format); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - master = 1; - break; - case SND_SOC_DAIFMT_CBS_CFS: - master = 0; - break; - default: - dev_err(dai->dev, "Unknown master/slave configuration\n"); - return -EINVAL; - } - - /* set master/slave mode */ - snd_soc_update_bits(codec, WM8804_AIFRX, 0x40, master << 6); - - bcp = lrp = 0; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - bcp = lrp = 1; - break; - case SND_SOC_DAIFMT_IB_NF: - bcp = 1; - break; - case SND_SOC_DAIFMT_NB_IF: - lrp = 1; - break; - default: - dev_err(dai->dev, "Unknown polarity configuration\n"); - return -EINVAL; - } - - /* set frame inversion */ - snd_soc_update_bits(codec, WM8804_AIFTX, 0x10 | 0x20, - (bcp << 4) | (lrp << 5)); - snd_soc_update_bits(codec, WM8804_AIFRX, 0x10 | 0x20, - (bcp << 4) | (lrp << 5)); - return 0; -} - -static int wm8804_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec; - u16 blen; - - codec = dai->codec; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - blen = 0x0; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - blen = 0x1; - break; - case SNDRV_PCM_FORMAT_S24_LE: - blen = 0x2; - break; - default: - dev_err(dai->dev, "Unsupported word length: %u\n", - params_format(params)); - return -EINVAL; - } - - /* set word length */ - snd_soc_update_bits(codec, WM8804_AIFTX, 0xc, blen << 2); - snd_soc_update_bits(codec, WM8804_AIFRX, 0xc, blen << 2); - - return 0; -} - -struct pll_div { - u32 prescale:1; - u32 mclkdiv:1; - u32 freqmode:2; - u32 n:4; - u32 k:22; -}; - -/* PLL rate to output rate divisions */ -static struct { - unsigned int div; - unsigned int freqmode; - unsigned int mclkdiv; -} post_table[] = { - { 2, 0, 0 }, - { 4, 0, 1 }, - { 4, 1, 0 }, - { 8, 1, 1 }, - { 8, 2, 0 }, - { 16, 2, 1 }, - { 12, 3, 0 }, - { 24, 3, 1 } -}; - -#define FIXED_PLL_SIZE ((1ULL << 22) * 10) -static int pll_factors(struct pll_div *pll_div, unsigned int target, - unsigned int source) -{ - u64 Kpart; - unsigned long int K, Ndiv, Nmod, tmp; - int i; - - /* - * Scale the output frequency up; the PLL should run in the - * region of 90-100MHz. - */ - for (i = 0; i < ARRAY_SIZE(post_table); i++) { - tmp = target * post_table[i].div; - if (tmp >= 90000000 && tmp <= 100000000) { - pll_div->freqmode = post_table[i].freqmode; - pll_div->mclkdiv = post_table[i].mclkdiv; - target *= post_table[i].div; - break; - } - } - - if (i == ARRAY_SIZE(post_table)) { - pr_err("%s: Unable to scale output frequency: %uHz\n", - __func__, target); - return -EINVAL; - } - - pll_div->prescale = 0; - Ndiv = target / source; - if (Ndiv < 5) { - source >>= 1; - pll_div->prescale = 1; - Ndiv = target / source; - } - - if (Ndiv < 5 || Ndiv > 13) { - pr_err("%s: WM8804 N value is not within the recommended range: %lu\n", - __func__, Ndiv); - return -EINVAL; - } - pll_div->n = Ndiv; - - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (u64)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xffffffff; - if ((K % 10) >= 5) - K += 5; - K /= 10; - pll_div->k = K; - - return 0; -} - -static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id, - int source, unsigned int freq_in, - unsigned int freq_out) -{ - struct snd_soc_codec *codec; - - codec = dai->codec; - if (!freq_in || !freq_out) { - /* disable the PLL */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1); - return 0; - } else { - int ret; - struct pll_div pll_div; - - ret = pll_factors(&pll_div, freq_out, freq_in); - if (ret) - return ret; - - /* power down the PLL before reprogramming it */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1); - - if (!freq_in || !freq_out) - return 0; - - /* set PLLN and PRESCALE */ - snd_soc_update_bits(codec, WM8804_PLL4, 0xf | 0x10, - pll_div.n | (pll_div.prescale << 4)); - /* set mclkdiv and freqmode */ - snd_soc_update_bits(codec, WM8804_PLL5, 0x3 | 0x8, - pll_div.freqmode | (pll_div.mclkdiv << 3)); - /* set PLLK */ - snd_soc_write(codec, WM8804_PLL1, pll_div.k & 0xff); - snd_soc_write(codec, WM8804_PLL2, (pll_div.k >> 8) & 0xff); - snd_soc_write(codec, WM8804_PLL3, pll_div.k >> 16); - - /* power up the PLL */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0); - } - - return 0; -} - -static int wm8804_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec; - - codec = dai->codec; - - switch (clk_id) { - case WM8804_TX_CLKSRC_MCLK: - if ((freq >= 10000000 && freq <= 14400000) - || (freq >= 16280000 && freq <= 27000000)) - snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0x80); - else { - dev_err(dai->dev, "OSCCLOCK is not within the " - "recommended range: %uHz\n", freq); - return -EINVAL; - } - break; - case WM8804_TX_CLKSRC_PLL: - snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0); - break; - case WM8804_CLKOUT_SRC_CLK1: - snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0); - break; - case WM8804_CLKOUT_SRC_OSCCLK: - snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0x8); - break; - default: - dev_err(dai->dev, "Unknown clock source: %d\n", clk_id); - return -EINVAL; - } - - return 0; -} - -static int wm8804_set_clkdiv(struct snd_soc_dai *dai, - int div_id, int div) -{ - struct snd_soc_codec *codec; - - codec = dai->codec; - switch (div_id) { - case WM8804_CLKOUT_DIV: - snd_soc_update_bits(codec, WM8804_PLL5, 0x30, - (div & 0x3) << 4); - break; - default: - dev_err(dai->dev, "Unknown clock divider: %d\n", div_id); - return -EINVAL; - } - return 0; -} - -static int wm8804_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - struct wm8804_priv *wm8804; - - wm8804 = snd_soc_codec_get_drvdata(codec); - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - /* power up the OSC and the PLL */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies), - wm8804->supplies); - if (ret) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - regcache_sync(wm8804->regmap); - } - /* power down the OSC and the PLL */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9); - break; - case SND_SOC_BIAS_OFF: - /* power down the OSC and the PLL */ - snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9); - regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), - wm8804->supplies); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#ifdef CONFIG_PM -static int wm8804_suspend(struct snd_soc_codec *codec) -{ - wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8804_resume(struct snd_soc_codec *codec) -{ - wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define wm8804_suspend NULL -#define wm8804_resume NULL -#endif - -static int wm8804_remove(struct snd_soc_codec *codec) -{ - struct wm8804_priv *wm8804; - int i; - - wm8804 = snd_soc_codec_get_drvdata(codec); - wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF); - - for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i) - regulator_unregister_notifier(wm8804->supplies[i].consumer, - &wm8804->disable_nb[i]); - regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies); - return 0; -} - -static int wm8804_probe(struct snd_soc_codec *codec) -{ - struct wm8804_priv *wm8804; - int i, id1, id2, ret; - - wm8804 = snd_soc_codec_get_drvdata(codec); - - codec->control_data = wm8804->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) - wm8804->supplies[i].supply = wm8804_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies), - wm8804->supplies); - if (ret) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0; - wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1; - - /* This should really be moved into the regulator core */ - for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) { - ret = regulator_register_notifier(wm8804->supplies[i].consumer, - &wm8804->disable_nb[i]); - if (ret != 0) { - dev_err(codec->dev, - "Failed to register regulator notifier: %d\n", - ret); - } - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies), - wm8804->supplies); - if (ret) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_reg_get; - } - - id1 = snd_soc_read(codec, WM8804_RST_DEVID1); - if (id1 < 0) { - dev_err(codec->dev, "Failed to read device ID: %d\n", id1); - ret = id1; - goto err_reg_enable; - } - - id2 = snd_soc_read(codec, WM8804_DEVID2); - if (id2 < 0) { - dev_err(codec->dev, "Failed to read device ID: %d\n", id2); - ret = id2; - goto err_reg_enable; - } - - id2 = (id2 << 8) | id1; - - if (id2 != 0x8805) { - dev_err(codec->dev, "Invalid device ID: %#x\n", id2); - ret = -EINVAL; - goto err_reg_enable; - } - - ret = snd_soc_read(codec, WM8804_DEVREV); - if (ret < 0) { - dev_err(codec->dev, "Failed to read device revision: %d\n", - ret); - goto err_reg_enable; - } - dev_info(codec->dev, "revision %c\n", ret + 'A'); - - ret = wm8804_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err_reg_enable; - } - - wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; - -err_reg_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies); -err_reg_get: - regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies); - return ret; -} - -static const struct snd_soc_dai_ops wm8804_dai_ops = { - .hw_params = wm8804_hw_params, - .set_fmt = wm8804_set_fmt, - .set_sysclk = wm8804_set_sysclk, - .set_clkdiv = wm8804_set_clkdiv, - .set_pll = wm8804_set_pll -}; - -#define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -#define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ - SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) - -static struct snd_soc_dai_driver wm8804_dai = { - .name = "wm8804-spdif", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8804_RATES, - .formats = WM8804_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM8804_RATES, - .formats = WM8804_FORMATS, - }, - .ops = &wm8804_dai_ops, - .symmetric_rates = 1 -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { - .probe = wm8804_probe, - .remove = wm8804_remove, - .suspend = wm8804_suspend, - .resume = wm8804_resume, - .set_bias_level = wm8804_set_bias_level, - .idle_bias_off = true, - - .controls = wm8804_snd_controls, - .num_controls = ARRAY_SIZE(wm8804_snd_controls), -}; - -static const struct of_device_id wm8804_of_match[] = { - { .compatible = "wlf,wm8804", }, - { } -}; -MODULE_DEVICE_TABLE(of, wm8804_of_match); - -static struct regmap_config wm8804_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = WM8804_MAX_REGISTER, - .volatile_reg = wm8804_volatile, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8804_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults), -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8804_spi_probe(struct spi_device *spi) -{ - struct wm8804_priv *wm8804; - int ret; - - wm8804 = devm_kzalloc(&spi->dev, sizeof *wm8804, GFP_KERNEL); - if (!wm8804) - return -ENOMEM; - - wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config); - if (IS_ERR(wm8804->regmap)) { - ret = PTR_ERR(wm8804->regmap); - return ret; - } - - spi_set_drvdata(spi, wm8804); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8804, &wm8804_dai, 1); - - return ret; -} - -static int __devexit wm8804_spi_remove(struct spi_device *spi) -{ - struct wm8804_priv *wm8804 = spi_get_drvdata(spi); - snd_soc_unregister_codec(&spi->dev); - regmap_exit(wm8804->regmap); - return 0; -} - -static struct spi_driver wm8804_spi_driver = { - .driver = { - .name = "wm8804", - .owner = THIS_MODULE, - .of_match_table = wm8804_of_match, - }, - .probe = wm8804_spi_probe, - .remove = __devexit_p(wm8804_spi_remove) -}; -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8804_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8804_priv *wm8804; - int ret; - - wm8804 = devm_kzalloc(&i2c->dev, sizeof *wm8804, GFP_KERNEL); - if (!wm8804) - return -ENOMEM; - - wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config); - if (IS_ERR(wm8804->regmap)) { - ret = PTR_ERR(wm8804->regmap); - return ret; - } - - i2c_set_clientdata(i2c, wm8804); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8804, &wm8804_dai, 1); - if (ret != 0) - goto err; - - return 0; - -err: - regmap_exit(wm8804->regmap); - return ret; -} - -static __devexit int wm8804_i2c_remove(struct i2c_client *i2c) -{ - struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c); - - snd_soc_unregister_codec(&i2c->dev); - regmap_exit(wm8804->regmap); - - return 0; -} - -static const struct i2c_device_id wm8804_i2c_id[] = { - { "wm8804", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id); - -static struct i2c_driver wm8804_i2c_driver = { - .driver = { - .name = "wm8804", - .owner = THIS_MODULE, - .of_match_table = wm8804_of_match, - }, - .probe = wm8804_i2c_probe, - .remove = __devexit_p(wm8804_i2c_remove), - .id_table = wm8804_i2c_id -}; -#endif - -static int __init wm8804_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8804_i2c_driver); - if (ret) { - printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8804_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8804 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8804_modinit); - -static void __exit wm8804_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8804_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8804_spi_driver); -#endif -} -module_exit(wm8804_exit); - -MODULE_DESCRIPTION("ASoC WM8804 driver"); -MODULE_AUTHOR("Dimitris Papastamos "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8804.h b/ANDROID_3.4.5/sound/soc/codecs/wm8804.h deleted file mode 100644 index 8ec14f55..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8804.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * wm8804.h -- WM8804 S/PDIF transceiver driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8804_H -#define _WM8804_H - -/* - * Register values. - */ -#define WM8804_RST_DEVID1 0x00 -#define WM8804_DEVID2 0x01 -#define WM8804_DEVREV 0x02 -#define WM8804_PLL1 0x03 -#define WM8804_PLL2 0x04 -#define WM8804_PLL3 0x05 -#define WM8804_PLL4 0x06 -#define WM8804_PLL5 0x07 -#define WM8804_PLL6 0x08 -#define WM8804_SPDMODE 0x09 -#define WM8804_INTMASK 0x0A -#define WM8804_INTSTAT 0x0B -#define WM8804_SPDSTAT 0x0C -#define WM8804_RXCHAN1 0x0D -#define WM8804_RXCHAN2 0x0E -#define WM8804_RXCHAN3 0x0F -#define WM8804_RXCHAN4 0x10 -#define WM8804_RXCHAN5 0x11 -#define WM8804_SPDTX1 0x12 -#define WM8804_SPDTX2 0x13 -#define WM8804_SPDTX3 0x14 -#define WM8804_SPDTX4 0x15 -#define WM8804_SPDTX5 0x16 -#define WM8804_GPO0 0x17 -#define WM8804_GPO1 0x18 -#define WM8804_GPO2 0x1A -#define WM8804_AIFTX 0x1B -#define WM8804_AIFRX 0x1C -#define WM8804_SPDRX1 0x1D -#define WM8804_PWRDN 0x1E - -#define WM8804_REGISTER_COUNT 30 -#define WM8804_MAX_REGISTER 0x1E - -#define WM8804_TX_CLKSRC_MCLK 1 -#define WM8804_TX_CLKSRC_PLL 2 - -#define WM8804_CLKOUT_SRC_CLK1 3 -#define WM8804_CLKOUT_SRC_OSCCLK 4 - -#define WM8804_CLKOUT_DIV 1 - -#endif /* _WM8804_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8900.c b/ANDROID_3.4.5/sound/soc/codecs/wm8900.c deleted file mode 100644 index f18c554e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8900.c +++ /dev/null @@ -1,1340 +0,0 @@ -/* - * wm8900.c -- WM8900 ALSA Soc Audio driver - * - * Copyright 2007, 2008 Wolfson Microelectronics PLC. - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: - * - Tristating. - * - TDM. - * - Jack detect. - * - FLL source configuration, currently only MCLK is supported. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8900.h" - -/* WM8900 register space */ -#define WM8900_REG_RESET 0x0 -#define WM8900_REG_ID 0x0 -#define WM8900_REG_POWER1 0x1 -#define WM8900_REG_POWER2 0x2 -#define WM8900_REG_POWER3 0x3 -#define WM8900_REG_AUDIO1 0x4 -#define WM8900_REG_AUDIO2 0x5 -#define WM8900_REG_CLOCKING1 0x6 -#define WM8900_REG_CLOCKING2 0x7 -#define WM8900_REG_AUDIO3 0x8 -#define WM8900_REG_AUDIO4 0x9 -#define WM8900_REG_DACCTRL 0xa -#define WM8900_REG_LDAC_DV 0xb -#define WM8900_REG_RDAC_DV 0xc -#define WM8900_REG_SIDETONE 0xd -#define WM8900_REG_ADCCTRL 0xe -#define WM8900_REG_LADC_DV 0xf -#define WM8900_REG_RADC_DV 0x10 -#define WM8900_REG_GPIO 0x12 -#define WM8900_REG_INCTL 0x15 -#define WM8900_REG_LINVOL 0x16 -#define WM8900_REG_RINVOL 0x17 -#define WM8900_REG_INBOOSTMIX1 0x18 -#define WM8900_REG_INBOOSTMIX2 0x19 -#define WM8900_REG_ADCPATH 0x1a -#define WM8900_REG_AUXBOOST 0x1b -#define WM8900_REG_ADDCTL 0x1e -#define WM8900_REG_FLLCTL1 0x24 -#define WM8900_REG_FLLCTL2 0x25 -#define WM8900_REG_FLLCTL3 0x26 -#define WM8900_REG_FLLCTL4 0x27 -#define WM8900_REG_FLLCTL5 0x28 -#define WM8900_REG_FLLCTL6 0x29 -#define WM8900_REG_LOUTMIXCTL1 0x2c -#define WM8900_REG_ROUTMIXCTL1 0x2d -#define WM8900_REG_BYPASS1 0x2e -#define WM8900_REG_BYPASS2 0x2f -#define WM8900_REG_AUXOUT_CTL 0x30 -#define WM8900_REG_LOUT1CTL 0x33 -#define WM8900_REG_ROUT1CTL 0x34 -#define WM8900_REG_LOUT2CTL 0x35 -#define WM8900_REG_ROUT2CTL 0x36 -#define WM8900_REG_HPCTL1 0x3a -#define WM8900_REG_OUTBIASCTL 0x73 - -#define WM8900_MAXREG 0x80 - -#define WM8900_REG_ADDCTL_OUT1_DIS 0x80 -#define WM8900_REG_ADDCTL_OUT2_DIS 0x40 -#define WM8900_REG_ADDCTL_VMID_DIS 0x20 -#define WM8900_REG_ADDCTL_BIAS_SRC 0x10 -#define WM8900_REG_ADDCTL_VMID_SOFTST 0x04 -#define WM8900_REG_ADDCTL_TEMP_SD 0x02 - -#define WM8900_REG_GPIO_TEMP_ENA 0x2 - -#define WM8900_REG_POWER1_STARTUP_BIAS_ENA 0x0100 -#define WM8900_REG_POWER1_BIAS_ENA 0x0008 -#define WM8900_REG_POWER1_VMID_BUF_ENA 0x0004 -#define WM8900_REG_POWER1_FLL_ENA 0x0040 - -#define WM8900_REG_POWER2_SYSCLK_ENA 0x8000 -#define WM8900_REG_POWER2_ADCL_ENA 0x0002 -#define WM8900_REG_POWER2_ADCR_ENA 0x0001 - -#define WM8900_REG_POWER3_DACL_ENA 0x0002 -#define WM8900_REG_POWER3_DACR_ENA 0x0001 - -#define WM8900_REG_AUDIO1_AIF_FMT_MASK 0x0018 -#define WM8900_REG_AUDIO1_LRCLK_INV 0x0080 -#define WM8900_REG_AUDIO1_BCLK_INV 0x0100 - -#define WM8900_REG_CLOCKING1_BCLK_DIR 0x1 -#define WM8900_REG_CLOCKING1_MCLK_SRC 0x100 -#define WM8900_REG_CLOCKING1_BCLK_MASK 0x01e -#define WM8900_REG_CLOCKING1_OPCLK_MASK 0x7000 - -#define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0 -#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c - -#define WM8900_REG_DACCTRL_MUTE 0x004 -#define WM8900_REG_DACCTRL_DAC_SB_FILT 0x100 -#define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400 - -#define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800 - -#define WM8900_REG_AUDIO4_DACLRC_DIR 0x0800 - -#define WM8900_REG_FLLCTL1_OSC_ENA 0x100 - -#define WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF 0x100 - -#define WM8900_REG_HPCTL1_HP_IPSTAGE_ENA 0x80 -#define WM8900_REG_HPCTL1_HP_OPSTAGE_ENA 0x40 -#define WM8900_REG_HPCTL1_HP_CLAMP_IP 0x20 -#define WM8900_REG_HPCTL1_HP_CLAMP_OP 0x10 -#define WM8900_REG_HPCTL1_HP_SHORT 0x08 -#define WM8900_REG_HPCTL1_HP_SHORT2 0x04 - -#define WM8900_LRC_MASK 0x03ff - -struct wm8900_priv { - enum snd_soc_control_type control_type; - - u32 fll_in; /* FLL input frequency */ - u32 fll_out; /* FLL output frequency */ -}; - -/* - * wm8900 register cache. We can't read the entire register space and we - * have slow control buses so we cache the registers. - */ -static const u16 wm8900_reg_defaults[WM8900_MAXREG] = { - 0x8900, 0x0000, - 0xc000, 0x0000, - 0x4050, 0x4000, - 0x0008, 0x0000, - 0x0040, 0x0040, - 0x1004, 0x00c0, - 0x00c0, 0x0000, - 0x0100, 0x00c0, - 0x00c0, 0x0000, - 0xb001, 0x0000, - 0x0000, 0x0044, - 0x004c, 0x004c, - 0x0044, 0x0044, - 0x0000, 0x0044, - 0x0000, 0x0000, - 0x0002, 0x0000, - 0x0000, 0x0000, - 0x0000, 0x0000, - 0x0008, 0x0000, - 0x0000, 0x0008, - 0x0097, 0x0100, - 0x0000, 0x0000, - 0x0050, 0x0050, - 0x0055, 0x0055, - 0x0055, 0x0000, - 0x0000, 0x0079, - 0x0079, 0x0079, - 0x0079, 0x0000, - /* Remaining registers all zero */ -}; - -static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg) -{ - switch (reg) { - case WM8900_REG_ID: - return 1; - default: - return 0; - } -} - -static void wm8900_reset(struct snd_soc_codec *codec) -{ - snd_soc_write(codec, WM8900_REG_RESET, 0); - - memcpy(codec->reg_cache, wm8900_reg_defaults, - sizeof(wm8900_reg_defaults)); -} - -static int wm8900_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - /* Clamp headphone outputs */ - hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP | - WM8900_REG_HPCTL1_HP_CLAMP_OP; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); - break; - - case SND_SOC_DAPM_POST_PMU: - /* Enable the input stage */ - hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_IP; - hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT | - WM8900_REG_HPCTL1_HP_SHORT2 | - WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); - - msleep(400); - - /* Enable the output stage */ - hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP; - hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); - - /* Remove the shorts */ - hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); - hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); - break; - - case SND_SOC_DAPM_PRE_PMD: - /* Short the output */ - hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); - - /* Disable the output stage */ - hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); - - /* Clamp the outputs and power down input */ - hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP | - WM8900_REG_HPCTL1_HP_CLAMP_OP; - hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); - break; - - case SND_SOC_DAPM_POST_PMD: - /* Disable everything */ - snd_soc_write(codec, WM8900_REG_HPCTL1, 0); - break; - - default: - BUG(); - } - - return 0; -} - -static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 100, 0); - -static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 0); - -static const DECLARE_TLV_DB_SCALE(in_boost_tlv, -1200, 600, 0); - -static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1200, 100, 0); - -static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); - -static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1); - -static const DECLARE_TLV_DB_SCALE(adc_svol_tlv, -3600, 300, 0); - -static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); - -static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" }; - -static const struct soc_enum mic_bias_level = -SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt); - -static const char *dac_mute_rate_txt[] = { "Fast", "Slow" }; - -static const struct soc_enum dac_mute_rate = -SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt); - -static const char *dac_deemphasis_txt[] = { - "Disabled", "32kHz", "44.1kHz", "48kHz" -}; - -static const struct soc_enum dac_deemphasis = -SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt); - -static const char *adc_hpf_cut_txt[] = { - "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3" -}; - -static const struct soc_enum adc_hpf_cut = -SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt); - -static const char *lr_txt[] = { - "Left", "Right" -}; - -static const struct soc_enum aifl_src = -SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt); - -static const struct soc_enum aifr_src = -SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt); - -static const struct soc_enum dacl_src = -SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt); - -static const struct soc_enum dacr_src = -SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt); - -static const char *sidetone_txt[] = { - "Disabled", "Left ADC", "Right ADC" -}; - -static const struct soc_enum dacl_sidetone = -SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt); - -static const struct soc_enum dacr_sidetone = -SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt); - -static const struct snd_kcontrol_new wm8900_snd_controls[] = { -SOC_ENUM("Mic Bias Level", mic_bias_level), - -SOC_SINGLE_TLV("Left Input PGA Volume", WM8900_REG_LINVOL, 0, 31, 0, - in_pga_tlv), -SOC_SINGLE("Left Input PGA Switch", WM8900_REG_LINVOL, 6, 1, 1), -SOC_SINGLE("Left Input PGA ZC Switch", WM8900_REG_LINVOL, 7, 1, 0), - -SOC_SINGLE_TLV("Right Input PGA Volume", WM8900_REG_RINVOL, 0, 31, 0, - in_pga_tlv), -SOC_SINGLE("Right Input PGA Switch", WM8900_REG_RINVOL, 6, 1, 1), -SOC_SINGLE("Right Input PGA ZC Switch", WM8900_REG_RINVOL, 7, 1, 0), - -SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1), -SOC_ENUM("DAC Mute Rate", dac_mute_rate), -SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0), -SOC_ENUM("DAC Deemphasis", dac_deemphasis), -SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL, - 12, 1, 0), - -SOC_SINGLE("ADC HPF Switch", WM8900_REG_ADCCTRL, 8, 1, 0), -SOC_ENUM("ADC HPF Cut-Off", adc_hpf_cut), -SOC_DOUBLE("ADC Invert Switch", WM8900_REG_ADCCTRL, 1, 0, 1, 0), -SOC_SINGLE_TLV("Left ADC Sidetone Volume", WM8900_REG_SIDETONE, 9, 12, 0, - adc_svol_tlv), -SOC_SINGLE_TLV("Right ADC Sidetone Volume", WM8900_REG_SIDETONE, 5, 12, 0, - adc_svol_tlv), -SOC_ENUM("Left Digital Audio Source", aifl_src), -SOC_ENUM("Right Digital Audio Source", aifr_src), - -SOC_SINGLE_TLV("DAC Input Boost Volume", WM8900_REG_AUDIO2, 10, 4, 0, - dac_boost_tlv), -SOC_ENUM("Left DAC Source", dacl_src), -SOC_ENUM("Right DAC Source", dacr_src), -SOC_ENUM("Left DAC Sidetone", dacl_sidetone), -SOC_ENUM("Right DAC Sidetone", dacr_sidetone), -SOC_DOUBLE("DAC Invert Switch", WM8900_REG_DACCTRL, 1, 0, 1, 0), - -SOC_DOUBLE_R_TLV("Digital Playback Volume", - WM8900_REG_LDAC_DV, WM8900_REG_RDAC_DV, - 1, 96, 0, dac_tlv), -SOC_DOUBLE_R_TLV("Digital Capture Volume", - WM8900_REG_LADC_DV, WM8900_REG_RADC_DV, 1, 119, 0, adc_tlv), - -SOC_SINGLE_TLV("LINPUT3 Bypass Volume", WM8900_REG_LOUTMIXCTL1, 4, 7, 0, - out_mix_tlv), -SOC_SINGLE_TLV("RINPUT3 Bypass Volume", WM8900_REG_ROUTMIXCTL1, 4, 7, 0, - out_mix_tlv), -SOC_SINGLE_TLV("Left AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 4, 7, 0, - out_mix_tlv), -SOC_SINGLE_TLV("Right AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 0, 7, 0, - out_mix_tlv), - -SOC_SINGLE_TLV("LeftIn to RightOut Mixer Volume", WM8900_REG_BYPASS1, 0, 7, 0, - out_mix_tlv), -SOC_SINGLE_TLV("LeftIn to LeftOut Mixer Volume", WM8900_REG_BYPASS1, 4, 7, 0, - out_mix_tlv), -SOC_SINGLE_TLV("RightIn to LeftOut Mixer Volume", WM8900_REG_BYPASS2, 0, 7, 0, - out_mix_tlv), -SOC_SINGLE_TLV("RightIn to RightOut Mixer Volume", WM8900_REG_BYPASS2, 4, 7, 0, - out_mix_tlv), - -SOC_SINGLE_TLV("IN2L Boost Volume", WM8900_REG_INBOOSTMIX1, 0, 3, 0, - in_boost_tlv), -SOC_SINGLE_TLV("IN3L Boost Volume", WM8900_REG_INBOOSTMIX1, 4, 3, 0, - in_boost_tlv), -SOC_SINGLE_TLV("IN2R Boost Volume", WM8900_REG_INBOOSTMIX2, 0, 3, 0, - in_boost_tlv), -SOC_SINGLE_TLV("IN3R Boost Volume", WM8900_REG_INBOOSTMIX2, 4, 3, 0, - in_boost_tlv), -SOC_SINGLE_TLV("Left AUX Boost Volume", WM8900_REG_AUXBOOST, 4, 3, 0, - in_boost_tlv), -SOC_SINGLE_TLV("Right AUX Boost Volume", WM8900_REG_AUXBOOST, 0, 3, 0, - in_boost_tlv), - -SOC_DOUBLE_R_TLV("LINEOUT1 Volume", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL, - 0, 63, 0, out_pga_tlv), -SOC_DOUBLE_R("LINEOUT1 Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL, - 6, 1, 1), -SOC_DOUBLE_R("LINEOUT1 ZC Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL, - 7, 1, 0), - -SOC_DOUBLE_R_TLV("LINEOUT2 Volume", - WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, - 0, 63, 0, out_pga_tlv), -SOC_DOUBLE_R("LINEOUT2 Switch", - WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 6, 1, 1), -SOC_DOUBLE_R("LINEOUT2 ZC Switch", - WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 7, 1, 0), -SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1, - 0, 1, 1), - -}; - -static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = -SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); - -static const struct snd_kcontrol_new wm8900_dapm_routput2_control = -SOC_DAPM_SINGLE("LINEOUT2R Switch", WM8900_REG_POWER3, 5, 1, 0); - -static const struct snd_kcontrol_new wm8900_loutmix_controls[] = { -SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0), -SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0), -SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 3, 1, 0), -SOC_DAPM_SINGLE("DACL Switch", WM8900_REG_LOUTMIXCTL1, 8, 1, 0), -}; - -static const struct snd_kcontrol_new wm8900_routmix_controls[] = { -SOC_DAPM_SINGLE("RINPUT3 Bypass Switch", WM8900_REG_ROUTMIXCTL1, 7, 1, 0), -SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 3, 1, 0), -SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 3, 1, 0), -SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 7, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8900_REG_ROUTMIXCTL1, 8, 1, 0), -}; - -static const struct snd_kcontrol_new wm8900_linmix_controls[] = { -SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INBOOSTMIX1, 2, 1, 1), -SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INBOOSTMIX1, 6, 1, 1), -SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 6, 1, 1), -SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 6, 1, 0), -}; - -static const struct snd_kcontrol_new wm8900_rinmix_controls[] = { -SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INBOOSTMIX2, 2, 1, 1), -SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INBOOSTMIX2, 6, 1, 1), -SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 2, 1, 1), -SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 2, 1, 0), -}; - -static const struct snd_kcontrol_new wm8900_linpga_controls[] = { -SOC_DAPM_SINGLE("LINPUT1 Switch", WM8900_REG_INCTL, 6, 1, 0), -SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INCTL, 5, 1, 0), -SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INCTL, 4, 1, 0), -}; - -static const struct snd_kcontrol_new wm8900_rinpga_controls[] = { -SOC_DAPM_SINGLE("RINPUT1 Switch", WM8900_REG_INCTL, 2, 1, 0), -SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0), -SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), -}; - -static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" }; - -static const struct soc_enum wm8900_lineout2_lp_mux = -SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux); - -static const struct snd_kcontrol_new wm8900_lineout2_lp = -SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); - -static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = { - -/* Externally visible pins */ -SND_SOC_DAPM_OUTPUT("LINEOUT1L"), -SND_SOC_DAPM_OUTPUT("LINEOUT1R"), -SND_SOC_DAPM_OUTPUT("LINEOUT2L"), -SND_SOC_DAPM_OUTPUT("LINEOUT2R"), -SND_SOC_DAPM_OUTPUT("HP_L"), -SND_SOC_DAPM_OUTPUT("HP_R"), - -SND_SOC_DAPM_INPUT("RINPUT1"), -SND_SOC_DAPM_INPUT("LINPUT1"), -SND_SOC_DAPM_INPUT("RINPUT2"), -SND_SOC_DAPM_INPUT("LINPUT2"), -SND_SOC_DAPM_INPUT("RINPUT3"), -SND_SOC_DAPM_INPUT("LINPUT3"), -SND_SOC_DAPM_INPUT("AUX"), - -SND_SOC_DAPM_VMID("VMID"), - -/* Input */ -SND_SOC_DAPM_MIXER("Left Input PGA", WM8900_REG_POWER2, 3, 0, - wm8900_linpga_controls, - ARRAY_SIZE(wm8900_linpga_controls)), -SND_SOC_DAPM_MIXER("Right Input PGA", WM8900_REG_POWER2, 2, 0, - wm8900_rinpga_controls, - ARRAY_SIZE(wm8900_rinpga_controls)), - -SND_SOC_DAPM_MIXER("Left Input Mixer", WM8900_REG_POWER2, 5, 0, - wm8900_linmix_controls, - ARRAY_SIZE(wm8900_linmix_controls)), -SND_SOC_DAPM_MIXER("Right Input Mixer", WM8900_REG_POWER2, 4, 0, - wm8900_rinmix_controls, - ARRAY_SIZE(wm8900_rinmix_controls)), - -SND_SOC_DAPM_SUPPLY("Mic Bias", WM8900_REG_POWER1, 4, 0, NULL, 0), - -SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0), -SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0), - -/* Output */ -SND_SOC_DAPM_DAC("DACL", "Left HiFi Playback", WM8900_REG_POWER3, 1, 0), -SND_SOC_DAPM_DAC("DACR", "Right HiFi Playback", WM8900_REG_POWER3, 0, 0), - -SND_SOC_DAPM_PGA_E("Headphone Amplifier", WM8900_REG_POWER3, 7, 0, NULL, 0, - wm8900_hp_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_PGA("LINEOUT1L PGA", WM8900_REG_POWER2, 8, 0, NULL, 0), -SND_SOC_DAPM_PGA("LINEOUT1R PGA", WM8900_REG_POWER2, 7, 0, NULL, 0), - -SND_SOC_DAPM_MUX("LINEOUT2 LP", SND_SOC_NOPM, 0, 0, &wm8900_lineout2_lp), -SND_SOC_DAPM_PGA("LINEOUT2L PGA", WM8900_REG_POWER3, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("LINEOUT2R PGA", WM8900_REG_POWER3, 5, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("Left Output Mixer", WM8900_REG_POWER3, 3, 0, - wm8900_loutmix_controls, - ARRAY_SIZE(wm8900_loutmix_controls)), -SND_SOC_DAPM_MIXER("Right Output Mixer", WM8900_REG_POWER3, 2, 0, - wm8900_routmix_controls, - ARRAY_SIZE(wm8900_routmix_controls)), -}; - -/* Target, Path, Source */ -static const struct snd_soc_dapm_route wm8900_dapm_routes[] = { -/* Inputs */ -{"Left Input PGA", "LINPUT1 Switch", "LINPUT1"}, -{"Left Input PGA", "LINPUT2 Switch", "LINPUT2"}, -{"Left Input PGA", "LINPUT3 Switch", "LINPUT3"}, - -{"Right Input PGA", "RINPUT1 Switch", "RINPUT1"}, -{"Right Input PGA", "RINPUT2 Switch", "RINPUT2"}, -{"Right Input PGA", "RINPUT3 Switch", "RINPUT3"}, - -{"Left Input Mixer", "LINPUT2 Switch", "LINPUT2"}, -{"Left Input Mixer", "LINPUT3 Switch", "LINPUT3"}, -{"Left Input Mixer", "AUX Switch", "AUX"}, -{"Left Input Mixer", "Input PGA Switch", "Left Input PGA"}, - -{"Right Input Mixer", "RINPUT2 Switch", "RINPUT2"}, -{"Right Input Mixer", "RINPUT3 Switch", "RINPUT3"}, -{"Right Input Mixer", "AUX Switch", "AUX"}, -{"Right Input Mixer", "Input PGA Switch", "Right Input PGA"}, - -{"ADCL", NULL, "Left Input Mixer"}, -{"ADCR", NULL, "Right Input Mixer"}, - -/* Outputs */ -{"LINEOUT1L", NULL, "LINEOUT1L PGA"}, -{"LINEOUT1L PGA", NULL, "Left Output Mixer"}, -{"LINEOUT1R", NULL, "LINEOUT1R PGA"}, -{"LINEOUT1R PGA", NULL, "Right Output Mixer"}, - -{"LINEOUT2L PGA", NULL, "Left Output Mixer"}, -{"LINEOUT2 LP", "Disabled", "LINEOUT2L PGA"}, -{"LINEOUT2 LP", "Enabled", "Left Output Mixer"}, -{"LINEOUT2L", NULL, "LINEOUT2 LP"}, - -{"LINEOUT2R PGA", NULL, "Right Output Mixer"}, -{"LINEOUT2 LP", "Disabled", "LINEOUT2R PGA"}, -{"LINEOUT2 LP", "Enabled", "Right Output Mixer"}, -{"LINEOUT2R", NULL, "LINEOUT2 LP"}, - -{"Left Output Mixer", "LINPUT3 Bypass Switch", "LINPUT3"}, -{"Left Output Mixer", "AUX Bypass Switch", "AUX"}, -{"Left Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"}, -{"Left Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"}, -{"Left Output Mixer", "DACL Switch", "DACL"}, - -{"Right Output Mixer", "RINPUT3 Bypass Switch", "RINPUT3"}, -{"Right Output Mixer", "AUX Bypass Switch", "AUX"}, -{"Right Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"}, -{"Right Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"}, -{"Right Output Mixer", "DACR Switch", "DACR"}, - -/* Note that the headphone output stage needs to be connected - * externally to LINEOUT2 via DC blocking capacitors. Other - * configurations are not supported. - * - * Note also that left and right headphone paths are treated as a - * mono path. - */ -{"Headphone Amplifier", NULL, "LINEOUT2 LP"}, -{"Headphone Amplifier", NULL, "LINEOUT2 LP"}, -{"HP_L", NULL, "Headphone Amplifier"}, -{"HP_R", NULL, "Headphone Amplifier"}, -}; - -static int wm8900_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 reg; - - reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - reg |= 0x20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - reg |= 0x40; - break; - case SNDRV_PCM_FORMAT_S32_LE: - reg |= 0x60; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8900_REG_AUDIO1, reg); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - reg = snd_soc_read(codec, WM8900_REG_DACCTRL); - - if (params_rate(params) <= 24000) - reg |= WM8900_REG_DACCTRL_DAC_SB_FILT; - else - reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT; - - snd_soc_write(codec, WM8900_REG_DACCTRL, reg); - } - - return 0; -} - -/* FLL divisors */ -struct _fll_div { - u16 fll_ratio; - u16 fllclk_div; - u16 fll_slow_lock_ref; - u16 n; - u16 k; -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod, target; - unsigned int div; - - BUG_ON(!Fout); - - /* The FLL must run at 90-100MHz which is then scaled down to - * the output value by FLLCLK_DIV. */ - target = Fout; - div = 1; - while (target < 90000000) { - div *= 2; - target *= 2; - } - - if (target > 100000000) - printk(KERN_WARNING "wm8900: FLL rate %u out of range, Fref=%u" - " Fout=%u\n", target, Fref, Fout); - if (div > 32) { - printk(KERN_ERR "wm8900: Invalid FLL division rate %u, " - "Fref=%u, Fout=%u, target=%u\n", - div, Fref, Fout, target); - return -EINVAL; - } - - fll_div->fllclk_div = div >> 2; - - if (Fref < 48000) - fll_div->fll_slow_lock_ref = 1; - else - fll_div->fll_slow_lock_ref = 0; - - Ndiv = target / Fref; - - if (Fref < 1000000) - fll_div->fll_ratio = 8; - else - fll_div->fll_ratio = 1; - - fll_div->n = Ndiv / fll_div->fll_ratio; - Nmod = (target / fll_div->fll_ratio) % Fref; - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, Fref); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - fll_div->k = K / 10; - - BUG_ON(target != Fout * (fll_div->fllclk_div << 2)); - BUG_ON(!K && target != Fref * fll_div->fll_ratio * fll_div->n); - - return 0; -} - -static int wm8900_set_fll(struct snd_soc_codec *codec, - int fll_id, unsigned int freq_in, unsigned int freq_out) -{ - struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); - struct _fll_div fll_div; - - if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out) - return 0; - - /* The digital side should be disabled during any change. */ - snd_soc_update_bits(codec, WM8900_REG_POWER1, - WM8900_REG_POWER1_FLL_ENA, 0); - - /* Disable the FLL? */ - if (!freq_in || !freq_out) { - snd_soc_update_bits(codec, WM8900_REG_CLOCKING1, - WM8900_REG_CLOCKING1_MCLK_SRC, 0); - snd_soc_update_bits(codec, WM8900_REG_FLLCTL1, - WM8900_REG_FLLCTL1_OSC_ENA, 0); - wm8900->fll_in = freq_in; - wm8900->fll_out = freq_out; - - return 0; - } - - if (fll_factors(&fll_div, freq_in, freq_out) != 0) - goto reenable; - - wm8900->fll_in = freq_in; - wm8900->fll_out = freq_out; - - /* The osclilator *MUST* be enabled before we enable the - * digital circuit. */ - snd_soc_write(codec, WM8900_REG_FLLCTL1, - fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA); - - snd_soc_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5); - snd_soc_write(codec, WM8900_REG_FLLCTL5, - (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f)); - - if (fll_div.k) { - snd_soc_write(codec, WM8900_REG_FLLCTL2, - (fll_div.k >> 8) | 0x100); - snd_soc_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff); - } else - snd_soc_write(codec, WM8900_REG_FLLCTL2, 0); - - if (fll_div.fll_slow_lock_ref) - snd_soc_write(codec, WM8900_REG_FLLCTL6, - WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF); - else - snd_soc_write(codec, WM8900_REG_FLLCTL6, 0); - - snd_soc_update_bits(codec, WM8900_REG_POWER1, - WM8900_REG_POWER1_FLL_ENA, - WM8900_REG_POWER1_FLL_ENA); - -reenable: - snd_soc_update_bits(codec, WM8900_REG_CLOCKING1, - WM8900_REG_CLOCKING1_MCLK_SRC, - WM8900_REG_CLOCKING1_MCLK_SRC); - return 0; -} - -static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); -} - -static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - - switch (div_id) { - case WM8900_BCLK_DIV: - snd_soc_update_bits(codec, WM8900_REG_CLOCKING1, - WM8900_REG_CLOCKING1_BCLK_MASK, div); - break; - case WM8900_OPCLK_DIV: - snd_soc_update_bits(codec, WM8900_REG_CLOCKING1, - WM8900_REG_CLOCKING1_OPCLK_MASK, div); - break; - case WM8900_DAC_LRCLK: - snd_soc_update_bits(codec, WM8900_REG_AUDIO4, - WM8900_LRC_MASK, div); - break; - case WM8900_ADC_LRCLK: - snd_soc_update_bits(codec, WM8900_REG_AUDIO3, - WM8900_LRC_MASK, div); - break; - case WM8900_DAC_CLKDIV: - snd_soc_update_bits(codec, WM8900_REG_CLOCKING2, - WM8900_REG_CLOCKING2_DAC_CLKDIV, div); - break; - case WM8900_ADC_CLKDIV: - snd_soc_update_bits(codec, WM8900_REG_CLOCKING2, - WM8900_REG_CLOCKING2_ADC_CLKDIV, div); - break; - case WM8900_LRCLK_MODE: - snd_soc_update_bits(codec, WM8900_REG_DACCTRL, - WM8900_REG_DACCTRL_AIF_LRCLKRATE, div); - break; - default: - return -EINVAL; - } - - return 0; -} - - -static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - unsigned int clocking1, aif1, aif3, aif4; - - clocking1 = snd_soc_read(codec, WM8900_REG_CLOCKING1); - aif1 = snd_soc_read(codec, WM8900_REG_AUDIO1); - aif3 = snd_soc_read(codec, WM8900_REG_AUDIO3); - aif4 = snd_soc_read(codec, WM8900_REG_AUDIO4); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR; - aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR; - aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR; - break; - case SND_SOC_DAIFMT_CBS_CFM: - clocking1 &= ~WM8900_REG_CLOCKING1_BCLK_DIR; - aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR; - aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR; - break; - case SND_SOC_DAIFMT_CBM_CFM: - clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR; - aif3 |= WM8900_REG_AUDIO3_ADCLRC_DIR; - aif4 |= WM8900_REG_AUDIO4_DACLRC_DIR; - break; - case SND_SOC_DAIFMT_CBM_CFS: - clocking1 |= WM8900_REG_CLOCKING1_BCLK_DIR; - aif3 &= ~WM8900_REG_AUDIO3_ADCLRC_DIR; - aif4 &= ~WM8900_REG_AUDIO4_DACLRC_DIR; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - aif1 |= WM8900_REG_AUDIO1_AIF_FMT_MASK; - aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_B: - aif1 |= WM8900_REG_AUDIO1_AIF_FMT_MASK; - aif1 |= WM8900_REG_AUDIO1_LRCLK_INV; - break; - case SND_SOC_DAIFMT_I2S: - aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK; - aif1 |= 0x10; - break; - case SND_SOC_DAIFMT_RIGHT_J: - aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK; - break; - case SND_SOC_DAIFMT_LEFT_J: - aif1 &= ~WM8900_REG_AUDIO1_AIF_FMT_MASK; - aif1 |= 0x8; - break; - default: - return -EINVAL; - } - - /* Clock inversion */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8900_REG_AUDIO1_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV; - aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_IF: - aif1 |= WM8900_REG_AUDIO1_BCLK_INV; - aif1 |= WM8900_REG_AUDIO1_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8900_REG_AUDIO1_BCLK_INV; - aif1 &= ~WM8900_REG_AUDIO1_LRCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif1 &= ~WM8900_REG_AUDIO1_BCLK_INV; - aif1 |= WM8900_REG_AUDIO1_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8900_REG_CLOCKING1, clocking1); - snd_soc_write(codec, WM8900_REG_AUDIO1, aif1); - snd_soc_write(codec, WM8900_REG_AUDIO3, aif3); - snd_soc_write(codec, WM8900_REG_AUDIO4, aif4); - - return 0; -} - -static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - reg = snd_soc_read(codec, WM8900_REG_DACCTRL); - - if (mute) - reg |= WM8900_REG_DACCTRL_MUTE; - else - reg &= ~WM8900_REG_DACCTRL_MUTE; - - snd_soc_write(codec, WM8900_REG_DACCTRL, reg); - - return 0; -} - -#define WM8900_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) - -#define WM8900_PCM_FORMATS \ - (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ - SNDRV_PCM_FORMAT_S24_LE) - -static const struct snd_soc_dai_ops wm8900_dai_ops = { - .hw_params = wm8900_hw_params, - .set_clkdiv = wm8900_set_dai_clkdiv, - .set_pll = wm8900_set_dai_pll, - .set_fmt = wm8900_set_dai_fmt, - .digital_mute = wm8900_digital_mute, -}; - -static struct snd_soc_dai_driver wm8900_dai = { - .name = "wm8900-hifi", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8900_RATES, - .formats = WM8900_PCM_FORMATS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8900_RATES, - .formats = WM8900_PCM_FORMATS, - }, - .ops = &wm8900_dai_ops, -}; - -static int wm8900_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 reg; - - switch (level) { - case SND_SOC_BIAS_ON: - /* Enable thermal shutdown */ - snd_soc_update_bits(codec, WM8900_REG_GPIO, - WM8900_REG_GPIO_TEMP_ENA, - WM8900_REG_GPIO_TEMP_ENA); - snd_soc_update_bits(codec, WM8900_REG_ADDCTL, - WM8900_REG_ADDCTL_TEMP_SD, - WM8900_REG_ADDCTL_TEMP_SD); - break; - - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - /* Charge capacitors if initial power up */ - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - /* STARTUP_BIAS_ENA on */ - snd_soc_write(codec, WM8900_REG_POWER1, - WM8900_REG_POWER1_STARTUP_BIAS_ENA); - - /* Startup bias mode */ - snd_soc_write(codec, WM8900_REG_ADDCTL, - WM8900_REG_ADDCTL_BIAS_SRC | - WM8900_REG_ADDCTL_VMID_SOFTST); - - /* VMID 2x50k */ - snd_soc_write(codec, WM8900_REG_POWER1, - WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1); - - /* Allow capacitors to charge */ - schedule_timeout_interruptible(msecs_to_jiffies(400)); - - /* Enable bias */ - snd_soc_write(codec, WM8900_REG_POWER1, - WM8900_REG_POWER1_STARTUP_BIAS_ENA | - WM8900_REG_POWER1_BIAS_ENA | 0x1); - - snd_soc_write(codec, WM8900_REG_ADDCTL, 0); - - snd_soc_write(codec, WM8900_REG_POWER1, - WM8900_REG_POWER1_BIAS_ENA | 0x1); - } - - reg = snd_soc_read(codec, WM8900_REG_POWER1); - snd_soc_write(codec, WM8900_REG_POWER1, - (reg & WM8900_REG_POWER1_FLL_ENA) | - WM8900_REG_POWER1_BIAS_ENA | 0x1); - snd_soc_write(codec, WM8900_REG_POWER2, - WM8900_REG_POWER2_SYSCLK_ENA); - snd_soc_write(codec, WM8900_REG_POWER3, 0); - break; - - case SND_SOC_BIAS_OFF: - /* Startup bias enable */ - reg = snd_soc_read(codec, WM8900_REG_POWER1); - snd_soc_write(codec, WM8900_REG_POWER1, - reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA); - snd_soc_write(codec, WM8900_REG_ADDCTL, - WM8900_REG_ADDCTL_BIAS_SRC | - WM8900_REG_ADDCTL_VMID_SOFTST); - - /* Discharge caps */ - snd_soc_write(codec, WM8900_REG_POWER1, - WM8900_REG_POWER1_STARTUP_BIAS_ENA); - schedule_timeout_interruptible(msecs_to_jiffies(500)); - - /* Remove clamp */ - snd_soc_write(codec, WM8900_REG_HPCTL1, 0); - - /* Power down */ - snd_soc_write(codec, WM8900_REG_ADDCTL, 0); - snd_soc_write(codec, WM8900_REG_POWER1, 0); - snd_soc_write(codec, WM8900_REG_POWER2, 0); - snd_soc_write(codec, WM8900_REG_POWER3, 0); - - /* Need to let things settle before stopping the clock - * to ensure that restart works, see "Stopping the - * master clock" in the datasheet. */ - schedule_timeout_interruptible(msecs_to_jiffies(1)); - snd_soc_write(codec, WM8900_REG_POWER2, - WM8900_REG_POWER2_SYSCLK_ENA); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static int wm8900_suspend(struct snd_soc_codec *codec) -{ - struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); - int fll_out = wm8900->fll_out; - int fll_in = wm8900->fll_in; - int ret; - - /* Stop the FLL in an orderly fashion */ - ret = wm8900_set_fll(codec, 0, 0, 0); - if (ret != 0) { - dev_err(codec->dev, "Failed to stop FLL\n"); - return ret; - } - - wm8900->fll_out = fll_out; - wm8900->fll_in = fll_in; - - wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8900_resume(struct snd_soc_codec *codec) -{ - struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); - u16 *cache; - int i, ret; - - cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults), - GFP_KERNEL); - - wm8900_reset(codec); - wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Restart the FLL? */ - if (wm8900->fll_out) { - int fll_out = wm8900->fll_out; - int fll_in = wm8900->fll_in; - - wm8900->fll_in = 0; - wm8900->fll_out = 0; - - ret = wm8900_set_fll(codec, 0, fll_in, fll_out); - if (ret != 0) { - dev_err(codec->dev, "Failed to restart FLL\n"); - kfree(cache); - return ret; - } - } - - if (cache) { - for (i = 0; i < WM8900_MAXREG; i++) - snd_soc_write(codec, i, cache[i]); - kfree(cache); - } else - dev_err(codec->dev, "Unable to allocate register cache\n"); - - return 0; -} - -static int wm8900_probe(struct snd_soc_codec *codec) -{ - struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); - int ret = 0, reg; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - reg = snd_soc_read(codec, WM8900_REG_ID); - if (reg != 0x8900) { - dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg); - return -ENODEV; - } - - wm8900_reset(codec); - - /* Turn the chip on */ - wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch the volume update bits */ - snd_soc_update_bits(codec, WM8900_REG_LINVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_RINVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_LOUT1CTL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_ROUT1CTL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_LOUT2CTL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_ROUT2CTL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_LDAC_DV, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_RDAC_DV, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_LADC_DV, 0x100, 0x100); - snd_soc_update_bits(codec, WM8900_REG_RADC_DV, 0x100, 0x100); - - /* Set the DAC and mixer output bias */ - snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); - - return 0; -} - -/* power down chip */ -static int wm8900_remove(struct snd_soc_codec *codec) -{ - wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { - .probe = wm8900_probe, - .remove = wm8900_remove, - .suspend = wm8900_suspend, - .resume = wm8900_resume, - .set_bias_level = wm8900_set_bias_level, - .volatile_register = wm8900_volatile_register, - .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8900_reg_defaults, - - .controls = wm8900_snd_controls, - .num_controls = ARRAY_SIZE(wm8900_snd_controls), - .dapm_widgets = wm8900_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8900_dapm_widgets), - .dapm_routes = wm8900_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8900_spi_probe(struct spi_device *spi) -{ - struct wm8900_priv *wm8900; - int ret; - - wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); - if (wm8900 == NULL) - return -ENOMEM; - - wm8900->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8900); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8900, &wm8900_dai, 1); - if (ret < 0) - kfree(wm8900); - return ret; -} - -static int __devexit wm8900_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); - return 0; -} - -static struct spi_driver wm8900_spi_driver = { - .driver = { - .name = "wm8900", - .owner = THIS_MODULE, - }, - .probe = wm8900_spi_probe, - .remove = __devexit_p(wm8900_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8900_priv *wm8900; - int ret; - - wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); - if (wm8900 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8900); - wm8900->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8900, &wm8900_dai, 1); - if (ret < 0) - kfree(wm8900); - return ret; -} - -static __devexit int wm8900_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8900_i2c_id[] = { - { "wm8900", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); - -static struct i2c_driver wm8900_i2c_driver = { - .driver = { - .name = "wm8900", - .owner = THIS_MODULE, - }, - .probe = wm8900_i2c_probe, - .remove = __devexit_p(wm8900_i2c_remove), - .id_table = wm8900_i2c_id, -}; -#endif - -static int __init wm8900_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8900_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8900_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8900_modinit); - -static void __exit wm8900_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8900_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8900_spi_driver); -#endif -} -module_exit(wm8900_exit); - -MODULE_DESCRIPTION("ASoC WM8900 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8900.h b/ANDROID_3.4.5/sound/soc/codecs/wm8900.h deleted file mode 100644 index 583f257e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8900.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * wm8900.h -- WM890 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8900_H -#define _WM8900_H - -#define WM8900_FLL 1 - -#define WM8900_BCLK_DIV 1 -#define WM8900_ADC_CLKDIV 2 -#define WM8900_DAC_CLKDIV 3 -#define WM8900_ADC_LRCLK 4 -#define WM8900_DAC_LRCLK 5 -#define WM8900_OPCLK_DIV 6 -#define WM8900_LRCLK_MODE 7 - -#define WM8900_BCLK_DIV_1 0x00 -#define WM8900_BCLK_DIV_1_5 0x02 -#define WM8900_BCLK_DIV_2 0x04 -#define WM8900_BCLK_DIV_3 0x06 -#define WM8900_BCLK_DIV_4 0x08 -#define WM8900_BCLK_DIV_5_5 0x0a -#define WM8900_BCLK_DIV_6 0x0c -#define WM8900_BCLK_DIV_8 0x0e -#define WM8900_BCLK_DIV_11 0x10 -#define WM8900_BCLK_DIV_12 0x12 -#define WM8900_BCLK_DIV_16 0x14 -#define WM8900_BCLK_DIV_22 0x16 -#define WM8900_BCLK_DIV_24 0x18 -#define WM8900_BCLK_DIV_32 0x1a -#define WM8900_BCLK_DIV_44 0x1c -#define WM8900_BCLK_DIV_48 0x1e - -#define WM8900_ADC_CLKDIV_1 0x00 -#define WM8900_ADC_CLKDIV_1_5 0x20 -#define WM8900_ADC_CLKDIV_2 0x40 -#define WM8900_ADC_CLKDIV_3 0x60 -#define WM8900_ADC_CLKDIV_4 0x80 -#define WM8900_ADC_CLKDIV_5_5 0xa0 -#define WM8900_ADC_CLKDIV_6 0xc0 - -#define WM8900_DAC_CLKDIV_1 0x00 -#define WM8900_DAC_CLKDIV_1_5 0x04 -#define WM8900_DAC_CLKDIV_2 0x08 -#define WM8900_DAC_CLKDIV_3 0x0c -#define WM8900_DAC_CLKDIV_4 0x10 -#define WM8900_DAC_CLKDIV_5_5 0x14 -#define WM8900_DAC_CLKDIV_6 0x18 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8903.c b/ANDROID_3.4.5/sound/soc/codecs/wm8903.c deleted file mode 100644 index c91fb2f9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8903.c +++ /dev/null @@ -1,2257 +0,0 @@ -/* - * wm8903.c -- WM8903 ALSA SoC Audio driver - * - * Copyright 2008 Wolfson Microelectronics - * Copyright 2011 NVIDIA, Inc. - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: - * - TDM mode configuration. - * - Digital microphone support. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8903.h" - -/* Register defaults at reset */ -static const struct reg_default wm8903_reg_defaults[] = { - { 4, 0x0018 }, /* R4 - Bias Control 0 */ - { 5, 0x0000 }, /* R5 - VMID Control 0 */ - { 6, 0x0000 }, /* R6 - Mic Bias Control 0 */ - { 8, 0x0001 }, /* R8 - Analogue DAC 0 */ - { 10, 0x0001 }, /* R10 - Analogue ADC 0 */ - { 12, 0x0000 }, /* R12 - Power Management 0 */ - { 13, 0x0000 }, /* R13 - Power Management 1 */ - { 14, 0x0000 }, /* R14 - Power Management 2 */ - { 15, 0x0000 }, /* R15 - Power Management 3 */ - { 16, 0x0000 }, /* R16 - Power Management 4 */ - { 17, 0x0000 }, /* R17 - Power Management 5 */ - { 18, 0x0000 }, /* R18 - Power Management 6 */ - { 20, 0x0400 }, /* R20 - Clock Rates 0 */ - { 21, 0x0D07 }, /* R21 - Clock Rates 1 */ - { 22, 0x0000 }, /* R22 - Clock Rates 2 */ - { 24, 0x0050 }, /* R24 - Audio Interface 0 */ - { 25, 0x0242 }, /* R25 - Audio Interface 1 */ - { 26, 0x0008 }, /* R26 - Audio Interface 2 */ - { 27, 0x0022 }, /* R27 - Audio Interface 3 */ - { 30, 0x00C0 }, /* R30 - DAC Digital Volume Left */ - { 31, 0x00C0 }, /* R31 - DAC Digital Volume Right */ - { 32, 0x0000 }, /* R32 - DAC Digital 0 */ - { 33, 0x0000 }, /* R33 - DAC Digital 1 */ - { 36, 0x00C0 }, /* R36 - ADC Digital Volume Left */ - { 37, 0x00C0 }, /* R37 - ADC Digital Volume Right */ - { 38, 0x0000 }, /* R38 - ADC Digital 0 */ - { 39, 0x0073 }, /* R39 - Digital Microphone 0 */ - { 40, 0x09BF }, /* R40 - DRC 0 */ - { 41, 0x3241 }, /* R41 - DRC 1 */ - { 42, 0x0020 }, /* R42 - DRC 2 */ - { 43, 0x0000 }, /* R43 - DRC 3 */ - { 44, 0x0085 }, /* R44 - Analogue Left Input 0 */ - { 45, 0x0085 }, /* R45 - Analogue Right Input 0 */ - { 46, 0x0044 }, /* R46 - Analogue Left Input 1 */ - { 47, 0x0044 }, /* R47 - Analogue Right Input 1 */ - { 50, 0x0008 }, /* R50 - Analogue Left Mix 0 */ - { 51, 0x0004 }, /* R51 - Analogue Right Mix 0 */ - { 52, 0x0000 }, /* R52 - Analogue Spk Mix Left 0 */ - { 53, 0x0000 }, /* R53 - Analogue Spk Mix Left 1 */ - { 54, 0x0000 }, /* R54 - Analogue Spk Mix Right 0 */ - { 55, 0x0000 }, /* R55 - Analogue Spk Mix Right 1 */ - { 57, 0x002D }, /* R57 - Analogue OUT1 Left */ - { 58, 0x002D }, /* R58 - Analogue OUT1 Right */ - { 59, 0x0039 }, /* R59 - Analogue OUT2 Left */ - { 60, 0x0039 }, /* R60 - Analogue OUT2 Right */ - { 62, 0x0139 }, /* R62 - Analogue OUT3 Left */ - { 63, 0x0139 }, /* R63 - Analogue OUT3 Right */ - { 64, 0x0000 }, /* R65 - Analogue SPK Output Control 0 */ - { 67, 0x0010 }, /* R67 - DC Servo 0 */ - { 69, 0x00A4 }, /* R69 - DC Servo 2 */ - { 90, 0x0000 }, /* R90 - Analogue HP 0 */ - { 94, 0x0000 }, /* R94 - Analogue Lineout 0 */ - { 98, 0x0000 }, /* R98 - Charge Pump 0 */ - { 104, 0x0000 }, /* R104 - Class W 0 */ - { 108, 0x0000 }, /* R108 - Write Sequencer 0 */ - { 109, 0x0000 }, /* R109 - Write Sequencer 1 */ - { 110, 0x0000 }, /* R110 - Write Sequencer 2 */ - { 111, 0x0000 }, /* R111 - Write Sequencer 3 */ - { 112, 0x0000 }, /* R112 - Write Sequencer 4 */ - { 114, 0x0000 }, /* R114 - Control Interface */ - { 116, 0x00A8 }, /* R116 - GPIO Control 1 */ - { 117, 0x00A8 }, /* R117 - GPIO Control 2 */ - { 118, 0x00A8 }, /* R118 - GPIO Control 3 */ - { 119, 0x0220 }, /* R119 - GPIO Control 4 */ - { 120, 0x01A0 }, /* R120 - GPIO Control 5 */ - { 122, 0xFFFF }, /* R122 - Interrupt Status 1 Mask */ - { 123, 0x0000 }, /* R123 - Interrupt Polarity 1 */ - { 126, 0x0000 }, /* R126 - Interrupt Control */ - { 129, 0x0000 }, /* R129 - Control Interface Test 1 */ - { 149, 0x6810 }, /* R149 - Charge Pump Test 1 */ - { 164, 0x0028 }, /* R164 - Clock Rate Test 4 */ - { 172, 0x0000 }, /* R172 - Analogue Output Bias 0 */ -}; - -struct wm8903_priv { - struct wm8903_platform_data *pdata; - struct snd_soc_codec *codec; - struct regmap *regmap; - - int sysclk; - int irq; - - int fs; - int deemph; - - int dcs_pending; - int dcs_cache[4]; - - /* Reference count */ - int class_w_users; - - struct snd_soc_jack *mic_jack; - int mic_det; - int mic_short; - int mic_last_report; - int mic_delay; - -#ifdef CONFIG_GPIOLIB - struct gpio_chip gpio_chip; -#endif -}; - -static bool wm8903_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8903_SW_RESET_AND_ID: - case WM8903_REVISION_NUMBER: - case WM8903_BIAS_CONTROL_0: - case WM8903_VMID_CONTROL_0: - case WM8903_MIC_BIAS_CONTROL_0: - case WM8903_ANALOGUE_DAC_0: - case WM8903_ANALOGUE_ADC_0: - case WM8903_POWER_MANAGEMENT_0: - case WM8903_POWER_MANAGEMENT_1: - case WM8903_POWER_MANAGEMENT_2: - case WM8903_POWER_MANAGEMENT_3: - case WM8903_POWER_MANAGEMENT_4: - case WM8903_POWER_MANAGEMENT_5: - case WM8903_POWER_MANAGEMENT_6: - case WM8903_CLOCK_RATES_0: - case WM8903_CLOCK_RATES_1: - case WM8903_CLOCK_RATES_2: - case WM8903_AUDIO_INTERFACE_0: - case WM8903_AUDIO_INTERFACE_1: - case WM8903_AUDIO_INTERFACE_2: - case WM8903_AUDIO_INTERFACE_3: - case WM8903_DAC_DIGITAL_VOLUME_LEFT: - case WM8903_DAC_DIGITAL_VOLUME_RIGHT: - case WM8903_DAC_DIGITAL_0: - case WM8903_DAC_DIGITAL_1: - case WM8903_ADC_DIGITAL_VOLUME_LEFT: - case WM8903_ADC_DIGITAL_VOLUME_RIGHT: - case WM8903_ADC_DIGITAL_0: - case WM8903_DIGITAL_MICROPHONE_0: - case WM8903_DRC_0: - case WM8903_DRC_1: - case WM8903_DRC_2: - case WM8903_DRC_3: - case WM8903_ANALOGUE_LEFT_INPUT_0: - case WM8903_ANALOGUE_RIGHT_INPUT_0: - case WM8903_ANALOGUE_LEFT_INPUT_1: - case WM8903_ANALOGUE_RIGHT_INPUT_1: - case WM8903_ANALOGUE_LEFT_MIX_0: - case WM8903_ANALOGUE_RIGHT_MIX_0: - case WM8903_ANALOGUE_SPK_MIX_LEFT_0: - case WM8903_ANALOGUE_SPK_MIX_LEFT_1: - case WM8903_ANALOGUE_SPK_MIX_RIGHT_0: - case WM8903_ANALOGUE_SPK_MIX_RIGHT_1: - case WM8903_ANALOGUE_OUT1_LEFT: - case WM8903_ANALOGUE_OUT1_RIGHT: - case WM8903_ANALOGUE_OUT2_LEFT: - case WM8903_ANALOGUE_OUT2_RIGHT: - case WM8903_ANALOGUE_OUT3_LEFT: - case WM8903_ANALOGUE_OUT3_RIGHT: - case WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0: - case WM8903_DC_SERVO_0: - case WM8903_DC_SERVO_2: - case WM8903_DC_SERVO_READBACK_1: - case WM8903_DC_SERVO_READBACK_2: - case WM8903_DC_SERVO_READBACK_3: - case WM8903_DC_SERVO_READBACK_4: - case WM8903_ANALOGUE_HP_0: - case WM8903_ANALOGUE_LINEOUT_0: - case WM8903_CHARGE_PUMP_0: - case WM8903_CLASS_W_0: - case WM8903_WRITE_SEQUENCER_0: - case WM8903_WRITE_SEQUENCER_1: - case WM8903_WRITE_SEQUENCER_2: - case WM8903_WRITE_SEQUENCER_3: - case WM8903_WRITE_SEQUENCER_4: - case WM8903_CONTROL_INTERFACE: - case WM8903_GPIO_CONTROL_1: - case WM8903_GPIO_CONTROL_2: - case WM8903_GPIO_CONTROL_3: - case WM8903_GPIO_CONTROL_4: - case WM8903_GPIO_CONTROL_5: - case WM8903_INTERRUPT_STATUS_1: - case WM8903_INTERRUPT_STATUS_1_MASK: - case WM8903_INTERRUPT_POLARITY_1: - case WM8903_INTERRUPT_CONTROL: - case WM8903_CLOCK_RATE_TEST_4: - case WM8903_ANALOGUE_OUTPUT_BIAS_0: - return true; - default: - return false; - } -} - -static bool wm8903_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8903_SW_RESET_AND_ID: - case WM8903_REVISION_NUMBER: - case WM8903_INTERRUPT_STATUS_1: - case WM8903_WRITE_SEQUENCER_4: - case WM8903_DC_SERVO_READBACK_1: - case WM8903_DC_SERVO_READBACK_2: - case WM8903_DC_SERVO_READBACK_3: - case WM8903_DC_SERVO_READBACK_4: - return 1; - - default: - return 0; - } -} - -static int wm8903_cp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - WARN_ON(event != SND_SOC_DAPM_POST_PMU); - mdelay(4); - - return 0; -} - -static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - wm8903->dcs_pending |= 1 << w->shift; - break; - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(codec, WM8903_DC_SERVO_0, - 1 << w->shift, 0); - break; - } - - return 0; -} - -#define WM8903_DCS_MODE_WRITE_STOP 0 -#define WM8903_DCS_MODE_START_STOP 2 - -static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, - enum snd_soc_dapm_type event, int subseq) -{ - struct snd_soc_codec *codec = container_of(dapm, - struct snd_soc_codec, dapm); - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int dcs_mode = WM8903_DCS_MODE_WRITE_STOP; - int i, val; - - /* Complete any pending DC servo starts */ - if (wm8903->dcs_pending) { - dev_dbg(codec->dev, "Starting DC servo for %x\n", - wm8903->dcs_pending); - - /* If we've no cached values then we need to do startup */ - for (i = 0; i < ARRAY_SIZE(wm8903->dcs_cache); i++) { - if (!(wm8903->dcs_pending & (1 << i))) - continue; - - if (wm8903->dcs_cache[i]) { - dev_dbg(codec->dev, - "Restore DC servo %d value %x\n", - 3 - i, wm8903->dcs_cache[i]); - - snd_soc_write(codec, WM8903_DC_SERVO_4 + i, - wm8903->dcs_cache[i] & 0xff); - } else { - dev_dbg(codec->dev, - "Calibrate DC servo %d\n", 3 - i); - dcs_mode = WM8903_DCS_MODE_START_STOP; - } - } - - /* Don't trust the cache for analogue */ - if (wm8903->class_w_users) - dcs_mode = WM8903_DCS_MODE_START_STOP; - - snd_soc_update_bits(codec, WM8903_DC_SERVO_2, - WM8903_DCS_MODE_MASK, dcs_mode); - - snd_soc_update_bits(codec, WM8903_DC_SERVO_0, - WM8903_DCS_ENA_MASK, wm8903->dcs_pending); - - switch (dcs_mode) { - case WM8903_DCS_MODE_WRITE_STOP: - break; - - case WM8903_DCS_MODE_START_STOP: - msleep(270); - - /* Cache the measured offsets for digital */ - if (wm8903->class_w_users) - break; - - for (i = 0; i < ARRAY_SIZE(wm8903->dcs_cache); i++) { - if (!(wm8903->dcs_pending & (1 << i))) - continue; - - val = snd_soc_read(codec, - WM8903_DC_SERVO_READBACK_1 + i); - dev_dbg(codec->dev, "DC servo %d: %x\n", - 3 - i, val); - wm8903->dcs_cache[i] = val; - } - break; - - default: - pr_warn("DCS mode %d delay not set\n", dcs_mode); - break; - } - - wm8903->dcs_pending = 0; - } -} - -/* - * When used with DAC outputs only the WM8903 charge pump supports - * operation in class W mode, providing very low power consumption - * when used with digital sources. Enable and disable this mode - * automatically depending on the mixer configuration. - * - * All the relevant controls are simple switches. - */ -static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - u16 reg; - int ret; - - reg = snd_soc_read(codec, WM8903_CLASS_W_0); - - /* Turn it off if we're about to enable bypass */ - if (ucontrol->value.integer.value[0]) { - if (wm8903->class_w_users == 0) { - dev_dbg(codec->dev, "Disabling Class W\n"); - snd_soc_write(codec, WM8903_CLASS_W_0, reg & - ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); - } - wm8903->class_w_users++; - } - - /* Implement the change */ - ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); - - /* If we've just disabled the last bypass path turn Class W on */ - if (!ucontrol->value.integer.value[0]) { - if (wm8903->class_w_users == 1) { - dev_dbg(codec->dev, "Enabling Class W\n"); - snd_soc_write(codec, WM8903_CLASS_W_0, reg | - WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); - } - wm8903->class_w_users--; - } - - dev_dbg(codec->dev, "Bypass use count now %d\n", - wm8903->class_w_users); - - return ret; -} - -#define SOC_DAPM_SINGLE_W(xname, reg, shift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = wm8903_class_w_put, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - - -static int wm8903_deemph[] = { 0, 32000, 44100, 48000 }; - -static int wm8903_set_deemph(struct snd_soc_codec *codec) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int val, i, best; - - /* If we're using deemphasis select the nearest available sample - * rate. - */ - if (wm8903->deemph) { - best = 1; - for (i = 2; i < ARRAY_SIZE(wm8903_deemph); i++) { - if (abs(wm8903_deemph[i] - wm8903->fs) < - abs(wm8903_deemph[best] - wm8903->fs)) - best = i; - } - - val = best << WM8903_DEEMPH_SHIFT; - } else { - best = 0; - val = 0; - } - - dev_dbg(codec->dev, "Set deemphasis %d (%dHz)\n", - best, wm8903_deemph[best]); - - return snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1, - WM8903_DEEMPH_MASK, val); -} - -static int wm8903_get_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8903->deemph; - - return 0; -} - -static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int deemph = ucontrol->value.enumerated.item[0]; - int ret = 0; - - if (deemph > 1) - return -EINVAL; - - mutex_lock(&codec->mutex); - if (wm8903->deemph != deemph) { - wm8903->deemph = deemph; - - wm8903_set_deemph(codec); - - ret = 1; - } - mutex_unlock(&codec->mutex); - - return ret; -} - -/* ALSA can only do steps of .01dB */ -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); - -static const DECLARE_TLV_DB_SCALE(digital_sidetone_tlv, -3600, 300, 0); -static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); - -static const DECLARE_TLV_DB_SCALE(drc_tlv_thresh, 0, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_tlv_amp, -2250, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_tlv_min, 0, 600, 0); -static const DECLARE_TLV_DB_SCALE(drc_tlv_max, 1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(drc_tlv_startup, -300, 50, 0); - -static const char *hpf_mode_text[] = { - "Hi-fi", "Voice 1", "Voice 2", "Voice 3" -}; - -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8903_ADC_DIGITAL_0, 5, 4, hpf_mode_text); - -static const char *osr_text[] = { - "Low power", "High performance" -}; - -static const struct soc_enum adc_osr = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_ADC_0, 0, 2, osr_text); - -static const struct soc_enum dac_osr = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 0, 2, osr_text); - -static const char *drc_slope_text[] = { - "1", "1/2", "1/4", "1/8", "1/16", "0" -}; - -static const struct soc_enum drc_slope_r0 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 3, 6, drc_slope_text); - -static const struct soc_enum drc_slope_r1 = - SOC_ENUM_SINGLE(WM8903_DRC_2, 0, 6, drc_slope_text); - -static const char *drc_attack_text[] = { - "instantaneous", - "363us", "762us", "1.45ms", "2.9ms", "5.8ms", "11.6ms", "23.2ms", - "46.4ms", "92.8ms", "185.6ms" -}; - -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8903_DRC_1, 12, 11, drc_attack_text); - -static const char *drc_decay_text[] = { - "186ms", "372ms", "743ms", "1.49s", "2.97s", "5.94s", "11.89s", - "23.87s", "47.56s" -}; - -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 8, 9, drc_decay_text); - -static const char *drc_ff_delay_text[] = { - "5 samples", "9 samples" -}; - -static const struct soc_enum drc_ff_delay = - SOC_ENUM_SINGLE(WM8903_DRC_0, 5, 2, drc_ff_delay_text); - -static const char *drc_qr_decay_text[] = { - "0.725ms", "1.45ms", "5.8ms" -}; - -static const struct soc_enum drc_qr_decay = - SOC_ENUM_SINGLE(WM8903_DRC_1, 4, 3, drc_qr_decay_text); - -static const char *drc_smoothing_text[] = { - "Low", "Medium", "High" -}; - -static const struct soc_enum drc_smoothing = - SOC_ENUM_SINGLE(WM8903_DRC_0, 11, 3, drc_smoothing_text); - -static const char *soft_mute_text[] = { - "Fast (fs/2)", "Slow (fs/32)" -}; - -static const struct soc_enum soft_mute = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 10, 2, soft_mute_text); - -static const char *mute_mode_text[] = { - "Hard", "Soft" -}; - -static const struct soc_enum mute_mode = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_1, 9, 2, mute_mode_text); - -static const char *companding_text[] = { - "ulaw", "alaw" -}; - -static const struct soc_enum dac_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 0, 2, companding_text); - -static const struct soc_enum adc_companding = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 2, 2, companding_text); - -static const char *input_mode_text[] = { - "Single-Ended", "Differential Line", "Differential Mic" -}; - -static const struct soc_enum linput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); - -static const struct soc_enum rinput_mode_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); - -static const char *linput_mux_text[] = { - "IN1L", "IN2L", "IN3L" -}; - -static const struct soc_enum linput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 2, 3, linput_mux_text); - -static const struct soc_enum linput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_LEFT_INPUT_1, 4, 3, linput_mux_text); - -static const char *rinput_mux_text[] = { - "IN1R", "IN2R", "IN3R" -}; - -static const struct soc_enum rinput_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 2, 3, rinput_mux_text); - -static const struct soc_enum rinput_inv_enum = - SOC_ENUM_SINGLE(WM8903_ANALOGUE_RIGHT_INPUT_1, 4, 3, rinput_mux_text); - - -static const char *sidetone_text[] = { - "None", "Left", "Right" -}; - -static const struct soc_enum lsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 2, 3, sidetone_text); - -static const struct soc_enum rsidetone_enum = - SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); - -static const char *adcinput_text[] = { - "ADC", "DMIC" -}; - -static const struct soc_enum adcinput_enum = - SOC_ENUM_SINGLE(WM8903_CLOCK_RATE_TEST_4, 9, 2, adcinput_text); - -static const char *aif_text[] = { - "Left", "Right" -}; - -static const struct soc_enum lcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text); - -static const struct soc_enum rcapture_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text); - -static const struct soc_enum lplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text); - -static const struct soc_enum rplay_enum = - SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text); - -static const struct snd_kcontrol_new wm8903_snd_controls[] = { - -/* Input PGAs - No TLV since the scale depends on PGA mode */ -SOC_SINGLE("Left Input PGA Switch", WM8903_ANALOGUE_LEFT_INPUT_0, - 7, 1, 1), -SOC_SINGLE("Left Input PGA Volume", WM8903_ANALOGUE_LEFT_INPUT_0, - 0, 31, 0), -SOC_SINGLE("Left Input PGA Common Mode Switch", WM8903_ANALOGUE_LEFT_INPUT_1, - 6, 1, 0), - -SOC_SINGLE("Right Input PGA Switch", WM8903_ANALOGUE_RIGHT_INPUT_0, - 7, 1, 1), -SOC_SINGLE("Right Input PGA Volume", WM8903_ANALOGUE_RIGHT_INPUT_0, - 0, 31, 0), -SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1, - 6, 1, 0), - -/* ADCs */ -SOC_ENUM("ADC OSR", adc_osr), -SOC_SINGLE("HPF Switch", WM8903_ADC_DIGITAL_0, 4, 1, 0), -SOC_ENUM("HPF Mode", hpf_mode), -SOC_SINGLE("DRC Switch", WM8903_DRC_0, 15, 1, 0), -SOC_ENUM("DRC Compressor Slope R0", drc_slope_r0), -SOC_ENUM("DRC Compressor Slope R1", drc_slope_r1), -SOC_SINGLE_TLV("DRC Compressor Threshold Volume", WM8903_DRC_3, 5, 124, 1, - drc_tlv_thresh), -SOC_SINGLE_TLV("DRC Volume", WM8903_DRC_3, 0, 30, 1, drc_tlv_amp), -SOC_SINGLE_TLV("DRC Minimum Gain Volume", WM8903_DRC_1, 2, 3, 1, drc_tlv_min), -SOC_SINGLE_TLV("DRC Maximum Gain Volume", WM8903_DRC_1, 0, 3, 0, drc_tlv_max), -SOC_ENUM("DRC Attack Rate", drc_attack), -SOC_ENUM("DRC Decay Rate", drc_decay), -SOC_ENUM("DRC FF Delay", drc_ff_delay), -SOC_SINGLE("DRC Anticlip Switch", WM8903_DRC_0, 1, 1, 0), -SOC_SINGLE("DRC QR Switch", WM8903_DRC_0, 2, 1, 0), -SOC_SINGLE_TLV("DRC QR Threshold Volume", WM8903_DRC_0, 6, 3, 0, drc_tlv_max), -SOC_ENUM("DRC QR Decay Rate", drc_qr_decay), -SOC_SINGLE("DRC Smoothing Switch", WM8903_DRC_0, 3, 1, 0), -SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8903_DRC_0, 0, 1, 0), -SOC_ENUM("DRC Smoothing Threshold", drc_smoothing), -SOC_SINGLE_TLV("DRC Startup Volume", WM8903_DRC_0, 6, 18, 0, drc_tlv_startup), - -SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8903_ADC_DIGITAL_VOLUME_LEFT, - WM8903_ADC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv), -SOC_ENUM("ADC Companding Mode", adc_companding), -SOC_SINGLE("ADC Companding Switch", WM8903_AUDIO_INTERFACE_0, 3, 1, 0), - -SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8903_DAC_DIGITAL_0, 4, 8, - 12, 0, digital_sidetone_tlv), - -/* DAC */ -SOC_ENUM("DAC OSR", dac_osr), -SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8903_DAC_DIGITAL_VOLUME_LEFT, - WM8903_DAC_DIGITAL_VOLUME_RIGHT, 1, 120, 0, digital_tlv), -SOC_ENUM("DAC Soft Mute Rate", soft_mute), -SOC_ENUM("DAC Mute Mode", mute_mode), -SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), -SOC_ENUM("DAC Companding Mode", dac_companding), -SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), -SOC_SINGLE_BOOL_EXT("Playback Deemphasis Switch", 0, - wm8903_get_deemph, wm8903_put_deemph), - -/* Headphones */ -SOC_DOUBLE_R("Headphone Switch", - WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT, - 8, 1, 1), -SOC_DOUBLE_R("Headphone ZC Switch", - WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT, - 6, 1, 0), -SOC_DOUBLE_R_TLV("Headphone Volume", - WM8903_ANALOGUE_OUT1_LEFT, WM8903_ANALOGUE_OUT1_RIGHT, - 0, 63, 0, out_tlv), - -/* Line out */ -SOC_DOUBLE_R("Line Out Switch", - WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT, - 8, 1, 1), -SOC_DOUBLE_R("Line Out ZC Switch", - WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT, - 6, 1, 0), -SOC_DOUBLE_R_TLV("Line Out Volume", - WM8903_ANALOGUE_OUT2_LEFT, WM8903_ANALOGUE_OUT2_RIGHT, - 0, 63, 0, out_tlv), - -/* Speaker */ -SOC_DOUBLE_R("Speaker Switch", - WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT, 8, 1, 1), -SOC_DOUBLE_R("Speaker ZC Switch", - WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT, 6, 1, 0), -SOC_DOUBLE_R_TLV("Speaker Volume", - WM8903_ANALOGUE_OUT3_LEFT, WM8903_ANALOGUE_OUT3_RIGHT, - 0, 63, 0, out_tlv), -}; - -static const struct snd_kcontrol_new linput_mode_mux = - SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum); - -static const struct snd_kcontrol_new rinput_mode_mux = - SOC_DAPM_ENUM("Right Input Mode Mux", rinput_mode_enum); - -static const struct snd_kcontrol_new linput_mux = - SOC_DAPM_ENUM("Left Input Mux", linput_enum); - -static const struct snd_kcontrol_new linput_inv_mux = - SOC_DAPM_ENUM("Left Inverting Input Mux", linput_inv_enum); - -static const struct snd_kcontrol_new rinput_mux = - SOC_DAPM_ENUM("Right Input Mux", rinput_enum); - -static const struct snd_kcontrol_new rinput_inv_mux = - SOC_DAPM_ENUM("Right Inverting Input Mux", rinput_inv_enum); - -static const struct snd_kcontrol_new lsidetone_mux = - SOC_DAPM_ENUM("DACL Sidetone Mux", lsidetone_enum); - -static const struct snd_kcontrol_new rsidetone_mux = - SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum); - -static const struct snd_kcontrol_new adcinput_mux = - SOC_DAPM_ENUM("ADC Input", adcinput_enum); - -static const struct snd_kcontrol_new lcapture_mux = - SOC_DAPM_ENUM("Left Capture Mux", lcapture_enum); - -static const struct snd_kcontrol_new rcapture_mux = - SOC_DAPM_ENUM("Right Capture Mux", rcapture_enum); - -static const struct snd_kcontrol_new lplay_mux = - SOC_DAPM_ENUM("Left Playback Mux", lplay_enum); - -static const struct snd_kcontrol_new rplay_mux = - SOC_DAPM_ENUM("Right Playback Mux", rplay_enum); - -static const struct snd_kcontrol_new left_output_mixer[] = { -SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), -SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), -SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_output_mixer[] = { -SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0), -SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), -SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 0, 1, 0), -}; - -static const struct snd_kcontrol_new left_speaker_mixer[] = { -SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 3, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_speaker_mixer[] = { -SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 3, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 2, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, - 1, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, - 0, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1L"), -SND_SOC_DAPM_INPUT("IN1R"), -SND_SOC_DAPM_INPUT("IN2L"), -SND_SOC_DAPM_INPUT("IN2R"), -SND_SOC_DAPM_INPUT("IN3L"), -SND_SOC_DAPM_INPUT("IN3R"), -SND_SOC_DAPM_INPUT("DMICDAT"), - -SND_SOC_DAPM_OUTPUT("HPOUTL"), -SND_SOC_DAPM_OUTPUT("HPOUTR"), -SND_SOC_DAPM_OUTPUT("LINEOUTL"), -SND_SOC_DAPM_OUTPUT("LINEOUTR"), -SND_SOC_DAPM_OUTPUT("LOP"), -SND_SOC_DAPM_OUTPUT("LON"), -SND_SOC_DAPM_OUTPUT("ROP"), -SND_SOC_DAPM_OUTPUT("RON"), - -SND_SOC_DAPM_SUPPLY("MICBIAS", WM8903_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0), - -SND_SOC_DAPM_MUX("Left Input Mux", SND_SOC_NOPM, 0, 0, &linput_mux), -SND_SOC_DAPM_MUX("Left Input Inverting Mux", SND_SOC_NOPM, 0, 0, - &linput_inv_mux), -SND_SOC_DAPM_MUX("Left Input Mode Mux", SND_SOC_NOPM, 0, 0, &linput_mode_mux), - -SND_SOC_DAPM_MUX("Right Input Mux", SND_SOC_NOPM, 0, 0, &rinput_mux), -SND_SOC_DAPM_MUX("Right Input Inverting Mux", SND_SOC_NOPM, 0, 0, - &rinput_inv_mux), -SND_SOC_DAPM_MUX("Right Input Mode Mux", SND_SOC_NOPM, 0, 0, &rinput_mode_mux), - -SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0), - -SND_SOC_DAPM_MUX("Left ADC Input", SND_SOC_NOPM, 0, 0, &adcinput_mux), -SND_SOC_DAPM_MUX("Right ADC Input", SND_SOC_NOPM, 0, 0, &adcinput_mux), - -SND_SOC_DAPM_ADC("ADCL", NULL, WM8903_POWER_MANAGEMENT_6, 1, 0), -SND_SOC_DAPM_ADC("ADCR", NULL, WM8903_POWER_MANAGEMENT_6, 0, 0), - -SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lcapture_mux), -SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rcapture_mux), - -SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux), -SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux), - -SND_SOC_DAPM_AIF_IN("AIFRXL", "Left Playback", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_IN("AIFRXR", "Right Playback", 0, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_MUX("Left Playback Mux", SND_SOC_NOPM, 0, 0, &lplay_mux), -SND_SOC_DAPM_MUX("Right Playback Mux", SND_SOC_NOPM, 0, 0, &rplay_mux), - -SND_SOC_DAPM_DAC("DACL", NULL, WM8903_POWER_MANAGEMENT_6, 3, 0), -SND_SOC_DAPM_DAC("DACR", NULL, WM8903_POWER_MANAGEMENT_6, 2, 0), - -SND_SOC_DAPM_MIXER("Left Output Mixer", WM8903_POWER_MANAGEMENT_1, 1, 0, - left_output_mixer, ARRAY_SIZE(left_output_mixer)), -SND_SOC_DAPM_MIXER("Right Output Mixer", WM8903_POWER_MANAGEMENT_1, 0, 0, - right_output_mixer, ARRAY_SIZE(right_output_mixer)), - -SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0, - left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), -SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, - right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), - -SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_POWER_MANAGEMENT_2, - 1, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_POWER_MANAGEMENT_2, - 0, 0, NULL, 0), - -SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_POWER_MANAGEMENT_3, 1, 0, - NULL, 0), -SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_POWER_MANAGEMENT_3, 0, 0, - NULL, 0), - -SND_SOC_DAPM_PGA_S("HPL_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPL_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 2, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPL_ENA", 1, WM8903_ANALOGUE_HP_0, 4, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPR_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 3, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPR_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 2, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPR_ENA", 1, WM8903_ANALOGUE_HP_0, 0, 0, NULL, 0), - -SND_SOC_DAPM_PGA_S("LINEOUTL_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 7, 0, - NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 6, 0, - NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 2, WM8903_ANALOGUE_LINEOUT_0, 5, 0, - NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTL_ENA", 1, WM8903_ANALOGUE_LINEOUT_0, 4, 0, - NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTR_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 3, 0, - NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 2, 0, - NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 2, WM8903_ANALOGUE_LINEOUT_0, 1, 0, - NULL, 0), -SND_SOC_DAPM_PGA_S("LINEOUTR_ENA", 1, WM8903_ANALOGUE_LINEOUT_0, 0, 0, - NULL, 0), - -SND_SOC_DAPM_SUPPLY("DCS Master", WM8903_DC_SERVO_0, 4, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPL_DCS", 3, SND_SOC_NOPM, 3, 0, wm8903_dcs_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_PGA_S("HPR_DCS", 3, SND_SOC_NOPM, 2, 0, wm8903_dcs_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_PGA_S("LINEOUTL_DCS", 3, SND_SOC_NOPM, 1, 0, wm8903_dcs_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_PGA_S("LINEOUTR_DCS", 3, SND_SOC_NOPM, 0, 0, wm8903_dcs_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, - NULL, 0), -SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0, - NULL, 0), - -SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0, - wm8903_cp_event, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_route wm8903_intercon[] = { - - { "CLK_DSP", NULL, "CLK_SYS" }, - { "MICBIAS", NULL, "CLK_SYS" }, - { "HPL_DCS", NULL, "CLK_SYS" }, - { "HPR_DCS", NULL, "CLK_SYS" }, - { "LINEOUTL_DCS", NULL, "CLK_SYS" }, - { "LINEOUTR_DCS", NULL, "CLK_SYS" }, - - { "Left Input Mux", "IN1L", "IN1L" }, - { "Left Input Mux", "IN2L", "IN2L" }, - { "Left Input Mux", "IN3L", "IN3L" }, - - { "Left Input Inverting Mux", "IN1L", "IN1L" }, - { "Left Input Inverting Mux", "IN2L", "IN2L" }, - { "Left Input Inverting Mux", "IN3L", "IN3L" }, - - { "Right Input Mux", "IN1R", "IN1R" }, - { "Right Input Mux", "IN2R", "IN2R" }, - { "Right Input Mux", "IN3R", "IN3R" }, - - { "Right Input Inverting Mux", "IN1R", "IN1R" }, - { "Right Input Inverting Mux", "IN2R", "IN2R" }, - { "Right Input Inverting Mux", "IN3R", "IN3R" }, - - { "Left Input Mode Mux", "Single-Ended", "Left Input Inverting Mux" }, - { "Left Input Mode Mux", "Differential Line", - "Left Input Mux" }, - { "Left Input Mode Mux", "Differential Line", - "Left Input Inverting Mux" }, - { "Left Input Mode Mux", "Differential Mic", - "Left Input Mux" }, - { "Left Input Mode Mux", "Differential Mic", - "Left Input Inverting Mux" }, - - { "Right Input Mode Mux", "Single-Ended", - "Right Input Inverting Mux" }, - { "Right Input Mode Mux", "Differential Line", - "Right Input Mux" }, - { "Right Input Mode Mux", "Differential Line", - "Right Input Inverting Mux" }, - { "Right Input Mode Mux", "Differential Mic", - "Right Input Mux" }, - { "Right Input Mode Mux", "Differential Mic", - "Right Input Inverting Mux" }, - - { "Left Input PGA", NULL, "Left Input Mode Mux" }, - { "Right Input PGA", NULL, "Right Input Mode Mux" }, - - { "Left ADC Input", "ADC", "Left Input PGA" }, - { "Left ADC Input", "DMIC", "DMICDAT" }, - { "Right ADC Input", "ADC", "Right Input PGA" }, - { "Right ADC Input", "DMIC", "DMICDAT" }, - - { "Left Capture Mux", "Left", "ADCL" }, - { "Left Capture Mux", "Right", "ADCR" }, - - { "Right Capture Mux", "Left", "ADCL" }, - { "Right Capture Mux", "Right", "ADCR" }, - - { "AIFTXL", NULL, "Left Capture Mux" }, - { "AIFTXR", NULL, "Right Capture Mux" }, - - { "ADCL", NULL, "Left ADC Input" }, - { "ADCL", NULL, "CLK_DSP" }, - { "ADCR", NULL, "Right ADC Input" }, - { "ADCR", NULL, "CLK_DSP" }, - - { "Left Playback Mux", "Left", "AIFRXL" }, - { "Left Playback Mux", "Right", "AIFRXR" }, - - { "Right Playback Mux", "Left", "AIFRXL" }, - { "Right Playback Mux", "Right", "AIFRXR" }, - - { "DACL Sidetone", "Left", "ADCL" }, - { "DACL Sidetone", "Right", "ADCR" }, - { "DACR Sidetone", "Left", "ADCL" }, - { "DACR Sidetone", "Right", "ADCR" }, - - { "DACL", NULL, "Left Playback Mux" }, - { "DACL", NULL, "DACL Sidetone" }, - { "DACL", NULL, "CLK_DSP" }, - - { "DACR", NULL, "Right Playback Mux" }, - { "DACR", NULL, "DACR Sidetone" }, - { "DACR", NULL, "CLK_DSP" }, - - { "Left Output Mixer", "Left Bypass Switch", "Left Input PGA" }, - { "Left Output Mixer", "Right Bypass Switch", "Right Input PGA" }, - { "Left Output Mixer", "DACL Switch", "DACL" }, - { "Left Output Mixer", "DACR Switch", "DACR" }, - - { "Right Output Mixer", "Left Bypass Switch", "Left Input PGA" }, - { "Right Output Mixer", "Right Bypass Switch", "Right Input PGA" }, - { "Right Output Mixer", "DACL Switch", "DACL" }, - { "Right Output Mixer", "DACR Switch", "DACR" }, - - { "Left Speaker Mixer", "Left Bypass Switch", "Left Input PGA" }, - { "Left Speaker Mixer", "Right Bypass Switch", "Right Input PGA" }, - { "Left Speaker Mixer", "DACL Switch", "DACL" }, - { "Left Speaker Mixer", "DACR Switch", "DACR" }, - - { "Right Speaker Mixer", "Left Bypass Switch", "Left Input PGA" }, - { "Right Speaker Mixer", "Right Bypass Switch", "Right Input PGA" }, - { "Right Speaker Mixer", "DACL Switch", "DACL" }, - { "Right Speaker Mixer", "DACR Switch", "DACR" }, - - { "Left Line Output PGA", NULL, "Left Output Mixer" }, - { "Right Line Output PGA", NULL, "Right Output Mixer" }, - - { "Left Headphone Output PGA", NULL, "Left Output Mixer" }, - { "Right Headphone Output PGA", NULL, "Right Output Mixer" }, - - { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, - { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, - - { "HPL_ENA", NULL, "Left Headphone Output PGA" }, - { "HPR_ENA", NULL, "Right Headphone Output PGA" }, - { "HPL_ENA_DLY", NULL, "HPL_ENA" }, - { "HPR_ENA_DLY", NULL, "HPR_ENA" }, - { "LINEOUTL_ENA", NULL, "Left Line Output PGA" }, - { "LINEOUTR_ENA", NULL, "Right Line Output PGA" }, - { "LINEOUTL_ENA_DLY", NULL, "LINEOUTL_ENA" }, - { "LINEOUTR_ENA_DLY", NULL, "LINEOUTR_ENA" }, - - { "HPL_DCS", NULL, "DCS Master" }, - { "HPR_DCS", NULL, "DCS Master" }, - { "LINEOUTL_DCS", NULL, "DCS Master" }, - { "LINEOUTR_DCS", NULL, "DCS Master" }, - - { "HPL_DCS", NULL, "HPL_ENA_DLY" }, - { "HPR_DCS", NULL, "HPR_ENA_DLY" }, - { "LINEOUTL_DCS", NULL, "LINEOUTL_ENA_DLY" }, - { "LINEOUTR_DCS", NULL, "LINEOUTR_ENA_DLY" }, - - { "HPL_ENA_OUTP", NULL, "HPL_DCS" }, - { "HPR_ENA_OUTP", NULL, "HPR_DCS" }, - { "LINEOUTL_ENA_OUTP", NULL, "LINEOUTL_DCS" }, - { "LINEOUTR_ENA_OUTP", NULL, "LINEOUTR_DCS" }, - - { "HPL_RMV_SHORT", NULL, "HPL_ENA_OUTP" }, - { "HPR_RMV_SHORT", NULL, "HPR_ENA_OUTP" }, - { "LINEOUTL_RMV_SHORT", NULL, "LINEOUTL_ENA_OUTP" }, - { "LINEOUTR_RMV_SHORT", NULL, "LINEOUTR_ENA_OUTP" }, - - { "HPOUTL", NULL, "HPL_RMV_SHORT" }, - { "HPOUTR", NULL, "HPR_RMV_SHORT" }, - { "LINEOUTL", NULL, "LINEOUTL_RMV_SHORT" }, - { "LINEOUTR", NULL, "LINEOUTR_RMV_SHORT" }, - - { "LOP", NULL, "Left Speaker PGA" }, - { "LON", NULL, "Left Speaker PGA" }, - - { "ROP", NULL, "Right Speaker PGA" }, - { "RON", NULL, "Right Speaker PGA" }, - - { "Left Headphone Output PGA", NULL, "Charge Pump" }, - { "Right Headphone Output PGA", NULL, "Charge Pump" }, - { "Left Line Output PGA", NULL, "Charge Pump" }, - { "Right Line Output PGA", NULL, "Charge Pump" }, -}; - -static int wm8903_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, - WM8903_VMID_RES_MASK, - WM8903_VMID_RES_50K); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, - WM8903_POBCTRL | WM8903_ISEL_MASK | - WM8903_STARTUP_BIAS_ENA | - WM8903_BIAS_ENA, - WM8903_POBCTRL | - (2 << WM8903_ISEL_SHIFT) | - WM8903_STARTUP_BIAS_ENA); - - snd_soc_update_bits(codec, - WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0, - WM8903_SPK_DISCHARGE, - WM8903_SPK_DISCHARGE); - - msleep(33); - - snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5, - WM8903_SPKL_ENA | WM8903_SPKR_ENA, - WM8903_SPKL_ENA | WM8903_SPKR_ENA); - - snd_soc_update_bits(codec, - WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0, - WM8903_SPK_DISCHARGE, 0); - - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, - WM8903_VMID_TIE_ENA | - WM8903_BUFIO_ENA | - WM8903_VMID_IO_ENA | - WM8903_VMID_SOFT_MASK | - WM8903_VMID_RES_MASK | - WM8903_VMID_BUF_ENA, - WM8903_VMID_TIE_ENA | - WM8903_BUFIO_ENA | - WM8903_VMID_IO_ENA | - (2 << WM8903_VMID_SOFT_SHIFT) | - WM8903_VMID_RES_250K | - WM8903_VMID_BUF_ENA); - - msleep(129); - - snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5, - WM8903_SPKL_ENA | WM8903_SPKR_ENA, - 0); - - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, - WM8903_VMID_SOFT_MASK, 0); - - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, - WM8903_VMID_RES_MASK, - WM8903_VMID_RES_50K); - - snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, - WM8903_BIAS_ENA | WM8903_POBCTRL, - WM8903_BIAS_ENA); - - /* By default no bypass paths are enabled so - * enable Class W support. - */ - dev_dbg(codec->dev, "Enabling Class W\n"); - snd_soc_update_bits(codec, WM8903_CLASS_W_0, - WM8903_CP_DYN_FREQ | - WM8903_CP_DYN_V, - WM8903_CP_DYN_FREQ | - WM8903_CP_DYN_V); - } - - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, - WM8903_VMID_RES_MASK, - WM8903_VMID_RES_250K); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, - WM8903_BIAS_ENA, 0); - - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, - WM8903_VMID_SOFT_MASK, - 2 << WM8903_VMID_SOFT_SHIFT); - - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, - WM8903_VMID_BUF_ENA, 0); - - msleep(290); - - snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, - WM8903_VMID_TIE_ENA | WM8903_BUFIO_ENA | - WM8903_VMID_IO_ENA | WM8903_VMID_RES_MASK | - WM8903_VMID_SOFT_MASK | - WM8903_VMID_BUF_ENA, 0); - - snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, - WM8903_STARTUP_BIAS_ENA, 0); - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static int wm8903_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - - wm8903->sysclk = freq; - - return 0; -} - -static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1); - - aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK | - WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBS_CFM: - aif1 |= WM8903_LRCLK_DIR; - break; - case SND_SOC_DAIFMT_CBM_CFM: - aif1 |= WM8903_LRCLK_DIR | WM8903_BCLK_DIR; - break; - case SND_SOC_DAIFMT_CBM_CFS: - aif1 |= WM8903_BCLK_DIR; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - aif1 |= 0x3; - break; - case SND_SOC_DAIFMT_DSP_B: - aif1 |= 0x3 | WM8903_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_I2S: - aif1 |= 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - aif1 |= 0x1; - break; - case SND_SOC_DAIFMT_LEFT_J: - break; - default: - return -EINVAL; - } - - /* Clock inversion */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8903_AIF_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif1 |= WM8903_AIF_BCLK_INV | WM8903_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8903_AIF_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif1 |= WM8903_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); - - return 0; -} - -static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - reg = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); - - if (mute) - reg |= WM8903_DAC_MUTE; - else - reg &= ~WM8903_DAC_MUTE; - - snd_soc_write(codec, WM8903_DAC_DIGITAL_1, reg); - - return 0; -} - -/* Lookup table for CLK_SYS/fs ratio. 256fs or more is recommended - * for optimal performance so we list the lower rates first and match - * on the last match we find. */ -static struct { - int div; - int rate; - int mode; - int mclk_div; -} clk_sys_ratios[] = { - { 64, 0x0, 0x0, 1 }, - { 68, 0x0, 0x1, 1 }, - { 125, 0x0, 0x2, 1 }, - { 128, 0x1, 0x0, 1 }, - { 136, 0x1, 0x1, 1 }, - { 192, 0x2, 0x0, 1 }, - { 204, 0x2, 0x1, 1 }, - - { 64, 0x0, 0x0, 2 }, - { 68, 0x0, 0x1, 2 }, - { 125, 0x0, 0x2, 2 }, - { 128, 0x1, 0x0, 2 }, - { 136, 0x1, 0x1, 2 }, - { 192, 0x2, 0x0, 2 }, - { 204, 0x2, 0x1, 2 }, - - { 250, 0x2, 0x2, 1 }, - { 256, 0x3, 0x0, 1 }, - { 272, 0x3, 0x1, 1 }, - { 384, 0x4, 0x0, 1 }, - { 408, 0x4, 0x1, 1 }, - { 375, 0x4, 0x2, 1 }, - { 512, 0x5, 0x0, 1 }, - { 544, 0x5, 0x1, 1 }, - { 500, 0x5, 0x2, 1 }, - { 768, 0x6, 0x0, 1 }, - { 816, 0x6, 0x1, 1 }, - { 750, 0x6, 0x2, 1 }, - { 1024, 0x7, 0x0, 1 }, - { 1088, 0x7, 0x1, 1 }, - { 1000, 0x7, 0x2, 1 }, - { 1408, 0x8, 0x0, 1 }, - { 1496, 0x8, 0x1, 1 }, - { 1536, 0x9, 0x0, 1 }, - { 1632, 0x9, 0x1, 1 }, - { 1500, 0x9, 0x2, 1 }, - - { 250, 0x2, 0x2, 2 }, - { 256, 0x3, 0x0, 2 }, - { 272, 0x3, 0x1, 2 }, - { 384, 0x4, 0x0, 2 }, - { 408, 0x4, 0x1, 2 }, - { 375, 0x4, 0x2, 2 }, - { 512, 0x5, 0x0, 2 }, - { 544, 0x5, 0x1, 2 }, - { 500, 0x5, 0x2, 2 }, - { 768, 0x6, 0x0, 2 }, - { 816, 0x6, 0x1, 2 }, - { 750, 0x6, 0x2, 2 }, - { 1024, 0x7, 0x0, 2 }, - { 1088, 0x7, 0x1, 2 }, - { 1000, 0x7, 0x2, 2 }, - { 1408, 0x8, 0x0, 2 }, - { 1496, 0x8, 0x1, 2 }, - { 1536, 0x9, 0x0, 2 }, - { 1632, 0x9, 0x1, 2 }, - { 1500, 0x9, 0x2, 2 }, -}; - -/* CLK_SYS/BCLK ratios - multiplied by 10 due to .5s */ -static struct { - int ratio; - int div; -} bclk_divs[] = { - { 10, 0 }, - { 20, 2 }, - { 30, 3 }, - { 40, 4 }, - { 50, 5 }, - { 60, 7 }, - { 80, 8 }, - { 100, 9 }, - { 120, 11 }, - { 160, 12 }, - { 200, 13 }, - { 220, 14 }, - { 240, 15 }, - { 300, 17 }, - { 320, 18 }, - { 440, 19 }, - { 480, 20 }, -}; - -/* Sample rates for DSP */ -static struct { - int rate; - int value; -} sample_rates[] = { - { 8000, 0 }, - { 11025, 1 }, - { 12000, 2 }, - { 16000, 3 }, - { 22050, 4 }, - { 24000, 5 }, - { 32000, 6 }, - { 44100, 7 }, - { 48000, 8 }, - { 88200, 9 }, - { 96000, 10 }, - { 0, 0 }, -}; - -static int wm8903_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec =rtd->codec; - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int fs = params_rate(params); - int bclk; - int bclk_div; - int i; - int dsp_config; - int clk_config; - int best_val; - int cur_val; - int clk_sys; - - u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1); - u16 aif2 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_2); - u16 aif3 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_3); - u16 clock0 = snd_soc_read(codec, WM8903_CLOCK_RATES_0); - u16 clock1 = snd_soc_read(codec, WM8903_CLOCK_RATES_1); - u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); - - /* Enable sloping stopband filter for low sample rates */ - if (fs <= 24000) - dac_digital1 |= WM8903_DAC_SB_FILT; - else - dac_digital1 &= ~WM8903_DAC_SB_FILT; - - /* Configure sample rate logic for DSP - choose nearest rate */ - dsp_config = 0; - best_val = abs(sample_rates[dsp_config].rate - fs); - for (i = 1; i < ARRAY_SIZE(sample_rates); i++) { - cur_val = abs(sample_rates[i].rate - fs); - if (cur_val <= best_val) { - dsp_config = i; - best_val = cur_val; - } - } - - dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); - clock1 &= ~WM8903_SAMPLE_RATE_MASK; - clock1 |= sample_rates[dsp_config].value; - - aif1 &= ~WM8903_AIF_WL_MASK; - bclk = 2 * fs; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - bclk *= 16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - bclk *= 20; - aif1 |= 0x4; - break; - case SNDRV_PCM_FORMAT_S24_LE: - bclk *= 24; - aif1 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S32_LE: - bclk *= 32; - aif1 |= 0xc; - break; - default: - return -EINVAL; - } - - dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n", - wm8903->sysclk, fs); - - /* We may not have an MCLK which allows us to generate exactly - * the clock we want, particularly with USB derived inputs, so - * approximate. - */ - clk_config = 0; - best_val = abs((wm8903->sysclk / - (clk_sys_ratios[0].mclk_div * - clk_sys_ratios[0].div)) - fs); - for (i = 1; i < ARRAY_SIZE(clk_sys_ratios); i++) { - cur_val = abs((wm8903->sysclk / - (clk_sys_ratios[i].mclk_div * - clk_sys_ratios[i].div)) - fs); - - if (cur_val <= best_val) { - clk_config = i; - best_val = cur_val; - } - } - - if (clk_sys_ratios[clk_config].mclk_div == 2) { - clock0 |= WM8903_MCLKDIV2; - clk_sys = wm8903->sysclk / 2; - } else { - clock0 &= ~WM8903_MCLKDIV2; - clk_sys = wm8903->sysclk; - } - - clock1 &= ~(WM8903_CLK_SYS_RATE_MASK | - WM8903_CLK_SYS_MODE_MASK); - clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; - clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; - - dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", - clk_sys_ratios[clk_config].rate, - clk_sys_ratios[clk_config].mode, - clk_sys_ratios[clk_config].div); - - dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys); - - /* We may not get quite the right frequency if using - * approximate clocks so look for the closest match that is - * higher than the target (we need to ensure that there enough - * BCLKs to clock out the samples). - */ - bclk_div = 0; - best_val = ((clk_sys * 10) / bclk_divs[0].ratio) - bclk; - i = 1; - while (i < ARRAY_SIZE(bclk_divs)) { - cur_val = ((clk_sys * 10) / bclk_divs[i].ratio) - bclk; - if (cur_val < 0) /* BCLK table is sorted */ - break; - bclk_div = i; - best_val = cur_val; - i++; - } - - aif2 &= ~WM8903_BCLK_DIV_MASK; - aif3 &= ~WM8903_LRCLK_RATE_MASK; - - dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", - bclk_divs[bclk_div].ratio / 10, bclk, - (clk_sys * 10) / bclk_divs[bclk_div].ratio); - - aif2 |= bclk_divs[bclk_div].div; - aif3 |= bclk / fs; - - wm8903->fs = params_rate(params); - wm8903_set_deemph(codec); - - snd_soc_write(codec, WM8903_CLOCK_RATES_0, clock0); - snd_soc_write(codec, WM8903_CLOCK_RATES_1, clock1); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); - snd_soc_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1); - - return 0; -} - -/** - * wm8903_mic_detect - Enable microphone detection via the WM8903 IRQ - * - * @codec: WM8903 codec - * @jack: jack to report detection events on - * @det: value to report for presence detection - * @shrt: value to report for short detection - * - * Enable microphone detection via IRQ on the WM8903. If GPIOs are - * being used to bring out signals to the processor then only platform - * data configuration is needed for WM8903 and processor GPIOs should - * be configured using snd_soc_jack_add_gpios() instead. - * - * The current threasholds for detection should be configured using - * micdet_cfg in the platform data. Using this function will force on - * the microphone bias for the device. - */ -int wm8903_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - int det, int shrt) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int irq_mask = WM8903_MICDET_EINT | WM8903_MICSHRT_EINT; - - dev_dbg(codec->dev, "Enabling microphone detection: %x %x\n", - det, shrt); - - /* Store the configuration */ - wm8903->mic_jack = jack; - wm8903->mic_det = det; - wm8903->mic_short = shrt; - - /* Enable interrupts we've got a report configured for */ - if (det) - irq_mask &= ~WM8903_MICDET_EINT; - if (shrt) - irq_mask &= ~WM8903_MICSHRT_EINT; - - snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK, - WM8903_MICDET_EINT | WM8903_MICSHRT_EINT, - irq_mask); - - if (det || shrt) { - /* Enable mic detection, this may not have been set through - * platform data (eg, if the defaults are OK). */ - snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, - WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); - snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0, - WM8903_MICDET_ENA, WM8903_MICDET_ENA); - } else { - snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0, - WM8903_MICDET_ENA, 0); - } - - return 0; -} -EXPORT_SYMBOL_GPL(wm8903_mic_detect); - -static irqreturn_t wm8903_irq(int irq, void *data) -{ - struct snd_soc_codec *codec = data; - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int mic_report; - int int_pol; - int int_val = 0; - int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK); - - int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; - - if (int_val & WM8903_WSEQ_BUSY_EINT) { - dev_warn(codec->dev, "Write sequencer done\n"); - } - - /* - * The rest is microphone jack detection. We need to manually - * invert the polarity of the interrupt after each event - to - * simplify the code keep track of the last state we reported - * and just invert the relevant bits in both the report and - * the polarity register. - */ - mic_report = wm8903->mic_last_report; - int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1); - -#ifndef CONFIG_SND_SOC_WM8903_MODULE - if (int_val & (WM8903_MICSHRT_EINT | WM8903_MICDET_EINT)) - trace_snd_soc_jack_irq(dev_name(codec->dev)); -#endif - - if (int_val & WM8903_MICSHRT_EINT) { - dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol); - - mic_report ^= wm8903->mic_short; - int_pol ^= WM8903_MICSHRT_INV; - } - - if (int_val & WM8903_MICDET_EINT) { - dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol); - - mic_report ^= wm8903->mic_det; - int_pol ^= WM8903_MICDET_INV; - - msleep(wm8903->mic_delay); - } - - snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1, - WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); - - snd_soc_jack_report(wm8903->mic_jack, mic_report, - wm8903->mic_short | wm8903->mic_det); - - wm8903->mic_last_report = mic_report; - - return IRQ_HANDLED; -} - -#define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ - SNDRV_PCM_RATE_11025 | \ - SNDRV_PCM_RATE_16000 | \ - SNDRV_PCM_RATE_22050 | \ - SNDRV_PCM_RATE_32000 | \ - SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | \ - SNDRV_PCM_RATE_88200 | \ - SNDRV_PCM_RATE_96000) - -#define WM8903_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\ - SNDRV_PCM_RATE_11025 | \ - SNDRV_PCM_RATE_16000 | \ - SNDRV_PCM_RATE_22050 | \ - SNDRV_PCM_RATE_32000 | \ - SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000) - -#define WM8903_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8903_dai_ops = { - .hw_params = wm8903_hw_params, - .digital_mute = wm8903_digital_mute, - .set_fmt = wm8903_set_dai_fmt, - .set_sysclk = wm8903_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver wm8903_dai = { - .name = "wm8903-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8903_PLAYBACK_RATES, - .formats = WM8903_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM8903_CAPTURE_RATES, - .formats = WM8903_FORMATS, - }, - .ops = &wm8903_dai_ops, - .symmetric_rates = 1, -}; - -static int wm8903_suspend(struct snd_soc_codec *codec) -{ - wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8903_resume(struct snd_soc_codec *codec) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - - regcache_sync(wm8903->regmap); - - wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -#ifdef CONFIG_GPIOLIB -static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8903_priv, gpio_chip); -} - -static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - if (offset >= WM8903_NUM_GPIO) - return -EINVAL; - - return 0; -} - -static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); - struct snd_soc_codec *codec = wm8903->codec; - unsigned int mask, val; - int ret; - - mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK; - val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) | - WM8903_GP1_DIR; - - ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, - mask, val); - if (ret < 0) - return ret; - - return 0; -} - -static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); - struct snd_soc_codec *codec = wm8903->codec; - int reg; - - reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset); - - return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; -} - -static int wm8903_gpio_direction_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); - struct snd_soc_codec *codec = wm8903->codec; - unsigned int mask, val; - int ret; - - mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK | WM8903_GP1_LVL_MASK; - val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) | - (value << WM8903_GP2_LVL_SHIFT); - - ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, - mask, val); - if (ret < 0) - return ret; - - return 0; -} - -static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); - struct snd_soc_codec *codec = wm8903->codec; - - snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, - WM8903_GP1_LVL_MASK, - !!value << WM8903_GP1_LVL_SHIFT); -} - -static struct gpio_chip wm8903_template_chip = { - .label = "wm8903", - .owner = THIS_MODULE, - .request = wm8903_gpio_request, - .direction_input = wm8903_gpio_direction_in, - .get = wm8903_gpio_get, - .direction_output = wm8903_gpio_direction_out, - .set = wm8903_gpio_set, - .can_sleep = 1, -}; - -static void wm8903_init_gpio(struct snd_soc_codec *codec) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - struct wm8903_platform_data *pdata = wm8903->pdata; - int ret; - - wm8903->gpio_chip = wm8903_template_chip; - wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; - wm8903->gpio_chip.dev = codec->dev; - - if (pdata->gpio_base) - wm8903->gpio_chip.base = pdata->gpio_base; - else - wm8903->gpio_chip.base = -1; - - ret = gpiochip_add(&wm8903->gpio_chip); - if (ret != 0) - dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); -} - -static void wm8903_free_gpio(struct snd_soc_codec *codec) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = gpiochip_remove(&wm8903->gpio_chip); - if (ret != 0) - dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); -} -#else -static void wm8903_init_gpio(struct snd_soc_codec *codec) -{ -} - -static void wm8903_free_gpio(struct snd_soc_codec *codec) -{ -} -#endif - -static int wm8903_probe(struct snd_soc_codec *codec) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - struct wm8903_platform_data *pdata = wm8903->pdata; - int ret, i; - int trigger, irq_pol; - u16 val; - bool mic_gpio = false; - - wm8903->codec = codec; - codec->control_data = wm8903->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* Set up GPIOs, detect if any are MIC detect outputs */ - for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { - if ((!pdata->gpio_cfg[i]) || - (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO)) - continue; - - snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, - pdata->gpio_cfg[i] & 0x7fff); - - val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) - >> WM8903_GP1_FN_SHIFT; - - switch (val) { - case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: - case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: - mic_gpio = true; - break; - default: - break; - } - } - - /* Set up microphone detection */ - snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, - pdata->micdet_cfg); - - /* Microphone detection needs the WSEQ clock */ - if (pdata->micdet_cfg) - snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, - WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); - - /* If microphone detection is enabled by pdata but - * detected via IRQ then interrupts can be lost before - * the machine driver has set up microphone detection - * IRQs as the IRQs are clear on read. The detection - * will be enabled when the machine driver configures. - */ - WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); - - wm8903->mic_delay = pdata->micdet_delay; - - if (wm8903->irq) { - if (pdata->irq_active_low) { - trigger = IRQF_TRIGGER_LOW; - irq_pol = WM8903_IRQ_POL; - } else { - trigger = IRQF_TRIGGER_HIGH; - irq_pol = 0; - } - - snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, - WM8903_IRQ_POL, irq_pol); - - ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq, - trigger | IRQF_ONESHOT, - "wm8903", codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to request IRQ: %d\n", - ret); - return ret; - } - - /* Enable write sequencer interrupts */ - snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK, - WM8903_IM_WSEQ_BUSY_EINT, 0); - } - - /* power on device */ - wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch volume update bits */ - val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); - val |= WM8903_ADCVU; - snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); - snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); - - val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); - val |= WM8903_DACVU; - snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); - snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); - - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT); - val |= WM8903_HPOUTVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); - - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT); - val |= WM8903_LINEOUTVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); - - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT); - val |= WM8903_SPKVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); - - /* Enable DAC soft mute by default */ - snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1, - WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, - WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); - - wm8903_init_gpio(codec); - - return ret; -} - -/* power down chip */ -static int wm8903_remove(struct snd_soc_codec *codec) -{ - struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); - - wm8903_free_gpio(codec); - wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); - if (wm8903->irq) - free_irq(wm8903->irq, codec); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { - .probe = wm8903_probe, - .remove = wm8903_remove, - .suspend = wm8903_suspend, - .resume = wm8903_resume, - .set_bias_level = wm8903_set_bias_level, - .seq_notifier = wm8903_seq_notifier, - .controls = wm8903_snd_controls, - .num_controls = ARRAY_SIZE(wm8903_snd_controls), - .dapm_widgets = wm8903_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets), - .dapm_routes = wm8903_intercon, - .num_dapm_routes = ARRAY_SIZE(wm8903_intercon), -}; - -static const struct regmap_config wm8903_regmap = { - .reg_bits = 8, - .val_bits = 16, - - .max_register = WM8903_MAX_REGISTER, - .volatile_reg = wm8903_volatile_register, - .readable_reg = wm8903_readable_register, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8903_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8903_reg_defaults), -}; - -static int wm8903_set_pdata_irq_trigger(struct i2c_client *i2c, - struct wm8903_platform_data *pdata) -{ - struct irq_data *irq_data = irq_get_irq_data(i2c->irq); - if (!irq_data) { - dev_err(&i2c->dev, "Invalid IRQ: %d\n", - i2c->irq); - return -EINVAL; - } - - switch (irqd_get_trigger_type(irq_data)) { - case IRQ_TYPE_NONE: - default: - /* - * We assume the controller imposes no restrictions, - * so we are able to select active-high - */ - /* Fall-through */ - case IRQ_TYPE_LEVEL_HIGH: - pdata->irq_active_low = false; - break; - case IRQ_TYPE_LEVEL_LOW: - pdata->irq_active_low = true; - break; - } - - return 0; -} - -static int wm8903_set_pdata_from_of(struct i2c_client *i2c, - struct wm8903_platform_data *pdata) -{ - const struct device_node *np = i2c->dev.of_node; - u32 val32; - int i; - - if (of_property_read_u32(np, "micdet-cfg", &val32) >= 0) - pdata->micdet_cfg = val32; - - if (of_property_read_u32(np, "micdet-delay", &val32) >= 0) - pdata->micdet_delay = val32; - - if (of_property_read_u32_array(np, "gpio-cfg", pdata->gpio_cfg, - ARRAY_SIZE(pdata->gpio_cfg)) >= 0) { - /* - * In device tree: 0 means "write 0", - * 0xffffffff means "don't touch". - * - * In platform data: 0 means "don't touch", - * 0x8000 means "write 0". - * - * Note: WM8903_GPIO_CONFIG_ZERO == 0x8000. - * - * Convert from DT to pdata representation here, - * so no other code needs to change. - */ - for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { - if (pdata->gpio_cfg[i] == 0) { - pdata->gpio_cfg[i] = WM8903_GPIO_CONFIG_ZERO; - } else if (pdata->gpio_cfg[i] == 0xffffffff) { - pdata->gpio_cfg[i] = 0; - } else if (pdata->gpio_cfg[i] > 0x7fff) { - dev_err(&i2c->dev, "Invalid gpio-cfg[%d] %x\n", - i, pdata->gpio_cfg[i]); - return -EINVAL; - } - } - } - - return 0; -} - -static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); - struct wm8903_priv *wm8903; - unsigned int val; - int ret; - - wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv), - GFP_KERNEL); - if (wm8903 == NULL) - return -ENOMEM; - - wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap); - if (IS_ERR(wm8903->regmap)) { - ret = PTR_ERR(wm8903->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - - i2c_set_clientdata(i2c, wm8903); - wm8903->irq = i2c->irq; - - /* If no platform data was supplied, create storage for defaults */ - if (pdata) { - wm8903->pdata = pdata; - } else { - wm8903->pdata = devm_kzalloc(&i2c->dev, - sizeof(struct wm8903_platform_data), - GFP_KERNEL); - if (wm8903->pdata == NULL) { - dev_err(&i2c->dev, "Failed to allocate pdata\n"); - return -ENOMEM; - } - - if (i2c->irq) { - ret = wm8903_set_pdata_irq_trigger(i2c, wm8903->pdata); - if (ret != 0) - return ret; - } - - if (i2c->dev.of_node) { - ret = wm8903_set_pdata_from_of(i2c, wm8903->pdata); - if (ret != 0) - return ret; - } - } - - ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); - goto err; - } - if (val != 0x8903) { - dev_err(&i2c->dev, "Device with ID %x is not a WM8903\n", val); - ret = -ENODEV; - goto err; - } - - ret = regmap_read(wm8903->regmap, WM8903_REVISION_NUMBER, &val); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret); - goto err; - } - dev_info(&i2c->dev, "WM8903 revision %c\n", - (val & WM8903_CHIP_REV_MASK) + 'A'); - - /* Reset the device */ - regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8903, &wm8903_dai, 1); - if (ret != 0) - goto err; - - return 0; -err: - regmap_exit(wm8903->regmap); - return ret; -} - -static __devexit int wm8903_i2c_remove(struct i2c_client *client) -{ - struct wm8903_priv *wm8903 = i2c_get_clientdata(client); - - regmap_exit(wm8903->regmap); - snd_soc_unregister_codec(&client->dev); - - return 0; -} - -static const struct of_device_id wm8903_of_match[] = { - { .compatible = "wlf,wm8903", }, - {}, -}; -MODULE_DEVICE_TABLE(of, wm8903_of_match); - -static const struct i2c_device_id wm8903_i2c_id[] = { - { "wm8903", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); - -static struct i2c_driver wm8903_i2c_driver = { - .driver = { - .name = "wm8903", - .owner = THIS_MODULE, - .of_match_table = wm8903_of_match, - }, - .probe = wm8903_i2c_probe, - .remove = __devexit_p(wm8903_i2c_remove), - .id_table = wm8903_i2c_id, -}; - -static int __init wm8903_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8903_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8903_modinit); - -static void __exit wm8903_exit(void) -{ - i2c_del_driver(&wm8903_i2c_driver); -} -module_exit(wm8903_exit); - -MODULE_DESCRIPTION("ASoC WM8903 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8903.h b/ANDROID_3.4.5/sound/soc/codecs/wm8903.h deleted file mode 100644 index db949311..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8903.h +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * wm8903.h - WM8903 audio codec interface - * - * Copyright 2008 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * 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. - */ - -#ifndef _WM8903_H -#define _WM8903_H - -#include - -extern int wm8903_mic_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *jack, - int det, int shrt); - - -/* - * Register values. - */ -#define WM8903_SW_RESET_AND_ID 0x00 -#define WM8903_REVISION_NUMBER 0x01 -#define WM8903_BIAS_CONTROL_0 0x04 -#define WM8903_VMID_CONTROL_0 0x05 -#define WM8903_MIC_BIAS_CONTROL_0 0x06 -#define WM8903_ANALOGUE_DAC_0 0x08 -#define WM8903_ANALOGUE_ADC_0 0x0A -#define WM8903_POWER_MANAGEMENT_0 0x0C -#define WM8903_POWER_MANAGEMENT_1 0x0D -#define WM8903_POWER_MANAGEMENT_2 0x0E -#define WM8903_POWER_MANAGEMENT_3 0x0F -#define WM8903_POWER_MANAGEMENT_4 0x10 -#define WM8903_POWER_MANAGEMENT_5 0x11 -#define WM8903_POWER_MANAGEMENT_6 0x12 -#define WM8903_CLOCK_RATES_0 0x14 -#define WM8903_CLOCK_RATES_1 0x15 -#define WM8903_CLOCK_RATES_2 0x16 -#define WM8903_AUDIO_INTERFACE_0 0x18 -#define WM8903_AUDIO_INTERFACE_1 0x19 -#define WM8903_AUDIO_INTERFACE_2 0x1A -#define WM8903_AUDIO_INTERFACE_3 0x1B -#define WM8903_DAC_DIGITAL_VOLUME_LEFT 0x1E -#define WM8903_DAC_DIGITAL_VOLUME_RIGHT 0x1F -#define WM8903_DAC_DIGITAL_0 0x20 -#define WM8903_DAC_DIGITAL_1 0x21 -#define WM8903_ADC_DIGITAL_VOLUME_LEFT 0x24 -#define WM8903_ADC_DIGITAL_VOLUME_RIGHT 0x25 -#define WM8903_ADC_DIGITAL_0 0x26 -#define WM8903_DIGITAL_MICROPHONE_0 0x27 -#define WM8903_DRC_0 0x28 -#define WM8903_DRC_1 0x29 -#define WM8903_DRC_2 0x2A -#define WM8903_DRC_3 0x2B -#define WM8903_ANALOGUE_LEFT_INPUT_0 0x2C -#define WM8903_ANALOGUE_RIGHT_INPUT_0 0x2D -#define WM8903_ANALOGUE_LEFT_INPUT_1 0x2E -#define WM8903_ANALOGUE_RIGHT_INPUT_1 0x2F -#define WM8903_ANALOGUE_LEFT_MIX_0 0x32 -#define WM8903_ANALOGUE_RIGHT_MIX_0 0x33 -#define WM8903_ANALOGUE_SPK_MIX_LEFT_0 0x34 -#define WM8903_ANALOGUE_SPK_MIX_LEFT_1 0x35 -#define WM8903_ANALOGUE_SPK_MIX_RIGHT_0 0x36 -#define WM8903_ANALOGUE_SPK_MIX_RIGHT_1 0x37 -#define WM8903_ANALOGUE_OUT1_LEFT 0x39 -#define WM8903_ANALOGUE_OUT1_RIGHT 0x3A -#define WM8903_ANALOGUE_OUT2_LEFT 0x3B -#define WM8903_ANALOGUE_OUT2_RIGHT 0x3C -#define WM8903_ANALOGUE_OUT3_LEFT 0x3E -#define WM8903_ANALOGUE_OUT3_RIGHT 0x3F -#define WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0 0x41 -#define WM8903_DC_SERVO_0 0x43 -#define WM8903_DC_SERVO_2 0x45 -#define WM8903_DC_SERVO_4 0x47 -#define WM8903_DC_SERVO_5 0x48 -#define WM8903_DC_SERVO_6 0x49 -#define WM8903_DC_SERVO_7 0x4A -#define WM8903_DC_SERVO_READBACK_1 0x51 -#define WM8903_DC_SERVO_READBACK_2 0x52 -#define WM8903_DC_SERVO_READBACK_3 0x53 -#define WM8903_DC_SERVO_READBACK_4 0x54 -#define WM8903_ANALOGUE_HP_0 0x5A -#define WM8903_ANALOGUE_LINEOUT_0 0x5E -#define WM8903_CHARGE_PUMP_0 0x62 -#define WM8903_CLASS_W_0 0x68 -#define WM8903_WRITE_SEQUENCER_0 0x6C -#define WM8903_WRITE_SEQUENCER_1 0x6D -#define WM8903_WRITE_SEQUENCER_2 0x6E -#define WM8903_WRITE_SEQUENCER_3 0x6F -#define WM8903_WRITE_SEQUENCER_4 0x70 -#define WM8903_CONTROL_INTERFACE 0x72 -#define WM8903_GPIO_CONTROL_1 0x74 -#define WM8903_GPIO_CONTROL_2 0x75 -#define WM8903_GPIO_CONTROL_3 0x76 -#define WM8903_GPIO_CONTROL_4 0x77 -#define WM8903_GPIO_CONTROL_5 0x78 -#define WM8903_INTERRUPT_STATUS_1 0x79 -#define WM8903_INTERRUPT_STATUS_1_MASK 0x7A -#define WM8903_INTERRUPT_POLARITY_1 0x7B -#define WM8903_INTERRUPT_CONTROL 0x7E -#define WM8903_CLOCK_RATE_TEST_4 0xA4 -#define WM8903_ANALOGUE_OUTPUT_BIAS_0 0xAC - -#define WM8903_REGISTER_COUNT 75 -#define WM8903_MAX_REGISTER 0xAC - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - SW Reset and ID - */ -#define WM8903_SW_RESET_DEV_ID1_MASK 0xFFFF /* SW_RESET_DEV_ID1 - [15:0] */ -#define WM8903_SW_RESET_DEV_ID1_SHIFT 0 /* SW_RESET_DEV_ID1 - [15:0] */ -#define WM8903_SW_RESET_DEV_ID1_WIDTH 16 /* SW_RESET_DEV_ID1 - [15:0] */ - -/* - * R1 (0x01) - Revision Number - */ -#define WM8903_CHIP_REV_MASK 0x000F /* CHIP_REV - [3:0] */ -#define WM8903_CHIP_REV_SHIFT 0 /* CHIP_REV - [3:0] */ -#define WM8903_CHIP_REV_WIDTH 4 /* CHIP_REV - [3:0] */ - -/* - * R4 (0x04) - Bias Control 0 - */ -#define WM8903_POBCTRL 0x0010 /* POBCTRL */ -#define WM8903_POBCTRL_MASK 0x0010 /* POBCTRL */ -#define WM8903_POBCTRL_SHIFT 4 /* POBCTRL */ -#define WM8903_POBCTRL_WIDTH 1 /* POBCTRL */ -#define WM8903_ISEL_MASK 0x000C /* ISEL - [3:2] */ -#define WM8903_ISEL_SHIFT 2 /* ISEL - [3:2] */ -#define WM8903_ISEL_WIDTH 2 /* ISEL - [3:2] */ -#define WM8903_STARTUP_BIAS_ENA 0x0002 /* STARTUP_BIAS_ENA */ -#define WM8903_STARTUP_BIAS_ENA_MASK 0x0002 /* STARTUP_BIAS_ENA */ -#define WM8903_STARTUP_BIAS_ENA_SHIFT 1 /* STARTUP_BIAS_ENA */ -#define WM8903_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ -#define WM8903_BIAS_ENA 0x0001 /* BIAS_ENA */ -#define WM8903_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */ -#define WM8903_BIAS_ENA_SHIFT 0 /* BIAS_ENA */ -#define WM8903_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ - -/* - * R5 (0x05) - VMID Control 0 - */ -#define WM8903_VMID_TIE_ENA 0x0080 /* VMID_TIE_ENA */ -#define WM8903_VMID_TIE_ENA_MASK 0x0080 /* VMID_TIE_ENA */ -#define WM8903_VMID_TIE_ENA_SHIFT 7 /* VMID_TIE_ENA */ -#define WM8903_VMID_TIE_ENA_WIDTH 1 /* VMID_TIE_ENA */ -#define WM8903_BUFIO_ENA 0x0040 /* BUFIO_ENA */ -#define WM8903_BUFIO_ENA_MASK 0x0040 /* BUFIO_ENA */ -#define WM8903_BUFIO_ENA_SHIFT 6 /* BUFIO_ENA */ -#define WM8903_BUFIO_ENA_WIDTH 1 /* BUFIO_ENA */ -#define WM8903_VMID_IO_ENA 0x0020 /* VMID_IO_ENA */ -#define WM8903_VMID_IO_ENA_MASK 0x0020 /* VMID_IO_ENA */ -#define WM8903_VMID_IO_ENA_SHIFT 5 /* VMID_IO_ENA */ -#define WM8903_VMID_IO_ENA_WIDTH 1 /* VMID_IO_ENA */ -#define WM8903_VMID_SOFT_MASK 0x0018 /* VMID_SOFT - [4:3] */ -#define WM8903_VMID_SOFT_SHIFT 3 /* VMID_SOFT - [4:3] */ -#define WM8903_VMID_SOFT_WIDTH 2 /* VMID_SOFT - [4:3] */ -#define WM8903_VMID_RES_MASK 0x0006 /* VMID_RES - [2:1] */ -#define WM8903_VMID_RES_SHIFT 1 /* VMID_RES - [2:1] */ -#define WM8903_VMID_RES_WIDTH 2 /* VMID_RES - [2:1] */ -#define WM8903_VMID_BUF_ENA 0x0001 /* VMID_BUF_ENA */ -#define WM8903_VMID_BUF_ENA_MASK 0x0001 /* VMID_BUF_ENA */ -#define WM8903_VMID_BUF_ENA_SHIFT 0 /* VMID_BUF_ENA */ -#define WM8903_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ - -#define WM8903_VMID_RES_50K 2 -#define WM8903_VMID_RES_250K 3 -#define WM8903_VMID_RES_5K 6 - -/* - * R8 (0x08) - Analogue DAC 0 - */ -#define WM8903_DACBIAS_SEL_MASK 0x0018 /* DACBIAS_SEL - [4:3] */ -#define WM8903_DACBIAS_SEL_SHIFT 3 /* DACBIAS_SEL - [4:3] */ -#define WM8903_DACBIAS_SEL_WIDTH 2 /* DACBIAS_SEL - [4:3] */ -#define WM8903_DACVMID_BIAS_SEL_MASK 0x0006 /* DACVMID_BIAS_SEL - [2:1] */ -#define WM8903_DACVMID_BIAS_SEL_SHIFT 1 /* DACVMID_BIAS_SEL - [2:1] */ -#define WM8903_DACVMID_BIAS_SEL_WIDTH 2 /* DACVMID_BIAS_SEL - [2:1] */ - -/* - * R10 (0x0A) - Analogue ADC 0 - */ -#define WM8903_ADC_OSR128 0x0001 /* ADC_OSR128 */ -#define WM8903_ADC_OSR128_MASK 0x0001 /* ADC_OSR128 */ -#define WM8903_ADC_OSR128_SHIFT 0 /* ADC_OSR128 */ -#define WM8903_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ - -/* - * R12 (0x0C) - Power Management 0 - */ -#define WM8903_INL_ENA 0x0002 /* INL_ENA */ -#define WM8903_INL_ENA_MASK 0x0002 /* INL_ENA */ -#define WM8903_INL_ENA_SHIFT 1 /* INL_ENA */ -#define WM8903_INL_ENA_WIDTH 1 /* INL_ENA */ -#define WM8903_INR_ENA 0x0001 /* INR_ENA */ -#define WM8903_INR_ENA_MASK 0x0001 /* INR_ENA */ -#define WM8903_INR_ENA_SHIFT 0 /* INR_ENA */ -#define WM8903_INR_ENA_WIDTH 1 /* INR_ENA */ - -/* - * R13 (0x0D) - Power Management 1 - */ -#define WM8903_MIXOUTL_ENA 0x0002 /* MIXOUTL_ENA */ -#define WM8903_MIXOUTL_ENA_MASK 0x0002 /* MIXOUTL_ENA */ -#define WM8903_MIXOUTL_ENA_SHIFT 1 /* MIXOUTL_ENA */ -#define WM8903_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */ -#define WM8903_MIXOUTR_ENA 0x0001 /* MIXOUTR_ENA */ -#define WM8903_MIXOUTR_ENA_MASK 0x0001 /* MIXOUTR_ENA */ -#define WM8903_MIXOUTR_ENA_SHIFT 0 /* MIXOUTR_ENA */ -#define WM8903_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */ - -/* - * R14 (0x0E) - Power Management 2 - */ -#define WM8903_HPL_PGA_ENA 0x0002 /* HPL_PGA_ENA */ -#define WM8903_HPL_PGA_ENA_MASK 0x0002 /* HPL_PGA_ENA */ -#define WM8903_HPL_PGA_ENA_SHIFT 1 /* HPL_PGA_ENA */ -#define WM8903_HPL_PGA_ENA_WIDTH 1 /* HPL_PGA_ENA */ -#define WM8903_HPR_PGA_ENA 0x0001 /* HPR_PGA_ENA */ -#define WM8903_HPR_PGA_ENA_MASK 0x0001 /* HPR_PGA_ENA */ -#define WM8903_HPR_PGA_ENA_SHIFT 0 /* HPR_PGA_ENA */ -#define WM8903_HPR_PGA_ENA_WIDTH 1 /* HPR_PGA_ENA */ - -/* - * R15 (0x0F) - Power Management 3 - */ -#define WM8903_LINEOUTL_PGA_ENA 0x0002 /* LINEOUTL_PGA_ENA */ -#define WM8903_LINEOUTL_PGA_ENA_MASK 0x0002 /* LINEOUTL_PGA_ENA */ -#define WM8903_LINEOUTL_PGA_ENA_SHIFT 1 /* LINEOUTL_PGA_ENA */ -#define WM8903_LINEOUTL_PGA_ENA_WIDTH 1 /* LINEOUTL_PGA_ENA */ -#define WM8903_LINEOUTR_PGA_ENA 0x0001 /* LINEOUTR_PGA_ENA */ -#define WM8903_LINEOUTR_PGA_ENA_MASK 0x0001 /* LINEOUTR_PGA_ENA */ -#define WM8903_LINEOUTR_PGA_ENA_SHIFT 0 /* LINEOUTR_PGA_ENA */ -#define WM8903_LINEOUTR_PGA_ENA_WIDTH 1 /* LINEOUTR_PGA_ENA */ - -/* - * R16 (0x10) - Power Management 4 - */ -#define WM8903_MIXSPKL_ENA 0x0002 /* MIXSPKL_ENA */ -#define WM8903_MIXSPKL_ENA_MASK 0x0002 /* MIXSPKL_ENA */ -#define WM8903_MIXSPKL_ENA_SHIFT 1 /* MIXSPKL_ENA */ -#define WM8903_MIXSPKL_ENA_WIDTH 1 /* MIXSPKL_ENA */ -#define WM8903_MIXSPKR_ENA 0x0001 /* MIXSPKR_ENA */ -#define WM8903_MIXSPKR_ENA_MASK 0x0001 /* MIXSPKR_ENA */ -#define WM8903_MIXSPKR_ENA_SHIFT 0 /* MIXSPKR_ENA */ -#define WM8903_MIXSPKR_ENA_WIDTH 1 /* MIXSPKR_ENA */ - -/* - * R17 (0x11) - Power Management 5 - */ -#define WM8903_SPKL_ENA 0x0002 /* SPKL_ENA */ -#define WM8903_SPKL_ENA_MASK 0x0002 /* SPKL_ENA */ -#define WM8903_SPKL_ENA_SHIFT 1 /* SPKL_ENA */ -#define WM8903_SPKL_ENA_WIDTH 1 /* SPKL_ENA */ -#define WM8903_SPKR_ENA 0x0001 /* SPKR_ENA */ -#define WM8903_SPKR_ENA_MASK 0x0001 /* SPKR_ENA */ -#define WM8903_SPKR_ENA_SHIFT 0 /* SPKR_ENA */ -#define WM8903_SPKR_ENA_WIDTH 1 /* SPKR_ENA */ - -/* - * R18 (0x12) - Power Management 6 - */ -#define WM8903_DACL_ENA 0x0008 /* DACL_ENA */ -#define WM8903_DACL_ENA_MASK 0x0008 /* DACL_ENA */ -#define WM8903_DACL_ENA_SHIFT 3 /* DACL_ENA */ -#define WM8903_DACL_ENA_WIDTH 1 /* DACL_ENA */ -#define WM8903_DACR_ENA 0x0004 /* DACR_ENA */ -#define WM8903_DACR_ENA_MASK 0x0004 /* DACR_ENA */ -#define WM8903_DACR_ENA_SHIFT 2 /* DACR_ENA */ -#define WM8903_DACR_ENA_WIDTH 1 /* DACR_ENA */ -#define WM8903_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8903_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ -#define WM8903_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ -#define WM8903_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ -#define WM8903_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8903_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ -#define WM8903_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ -#define WM8903_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ - -/* - * R20 (0x14) - Clock Rates 0 - */ -#define WM8903_MCLKDIV2 0x0001 /* MCLKDIV2 */ -#define WM8903_MCLKDIV2_MASK 0x0001 /* MCLKDIV2 */ -#define WM8903_MCLKDIV2_SHIFT 0 /* MCLKDIV2 */ -#define WM8903_MCLKDIV2_WIDTH 1 /* MCLKDIV2 */ - -/* - * R21 (0x15) - Clock Rates 1 - */ -#define WM8903_CLK_SYS_RATE_MASK 0x3C00 /* CLK_SYS_RATE - [13:10] */ -#define WM8903_CLK_SYS_RATE_SHIFT 10 /* CLK_SYS_RATE - [13:10] */ -#define WM8903_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [13:10] */ -#define WM8903_CLK_SYS_MODE_MASK 0x0300 /* CLK_SYS_MODE - [9:8] */ -#define WM8903_CLK_SYS_MODE_SHIFT 8 /* CLK_SYS_MODE - [9:8] */ -#define WM8903_CLK_SYS_MODE_WIDTH 2 /* CLK_SYS_MODE - [9:8] */ -#define WM8903_SAMPLE_RATE_MASK 0x000F /* SAMPLE_RATE - [3:0] */ -#define WM8903_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [3:0] */ -#define WM8903_SAMPLE_RATE_WIDTH 4 /* SAMPLE_RATE - [3:0] */ - -/* - * R22 (0x16) - Clock Rates 2 - */ -#define WM8903_CLK_SYS_ENA 0x0004 /* CLK_SYS_ENA */ -#define WM8903_CLK_SYS_ENA_MASK 0x0004 /* CLK_SYS_ENA */ -#define WM8903_CLK_SYS_ENA_SHIFT 2 /* CLK_SYS_ENA */ -#define WM8903_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ -#define WM8903_CLK_DSP_ENA 0x0002 /* CLK_DSP_ENA */ -#define WM8903_CLK_DSP_ENA_MASK 0x0002 /* CLK_DSP_ENA */ -#define WM8903_CLK_DSP_ENA_SHIFT 1 /* CLK_DSP_ENA */ -#define WM8903_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ -#define WM8903_TO_ENA 0x0001 /* TO_ENA */ -#define WM8903_TO_ENA_MASK 0x0001 /* TO_ENA */ -#define WM8903_TO_ENA_SHIFT 0 /* TO_ENA */ -#define WM8903_TO_ENA_WIDTH 1 /* TO_ENA */ - -/* - * R24 (0x18) - Audio Interface 0 - */ -#define WM8903_DACL_DATINV 0x1000 /* DACL_DATINV */ -#define WM8903_DACL_DATINV_MASK 0x1000 /* DACL_DATINV */ -#define WM8903_DACL_DATINV_SHIFT 12 /* DACL_DATINV */ -#define WM8903_DACL_DATINV_WIDTH 1 /* DACL_DATINV */ -#define WM8903_DACR_DATINV 0x0800 /* DACR_DATINV */ -#define WM8903_DACR_DATINV_MASK 0x0800 /* DACR_DATINV */ -#define WM8903_DACR_DATINV_SHIFT 11 /* DACR_DATINV */ -#define WM8903_DACR_DATINV_WIDTH 1 /* DACR_DATINV */ -#define WM8903_DAC_BOOST_MASK 0x0600 /* DAC_BOOST - [10:9] */ -#define WM8903_DAC_BOOST_SHIFT 9 /* DAC_BOOST - [10:9] */ -#define WM8903_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [10:9] */ -#define WM8903_LOOPBACK 0x0100 /* LOOPBACK */ -#define WM8903_LOOPBACK_MASK 0x0100 /* LOOPBACK */ -#define WM8903_LOOPBACK_SHIFT 8 /* LOOPBACK */ -#define WM8903_LOOPBACK_WIDTH 1 /* LOOPBACK */ -#define WM8903_AIFADCL_SRC 0x0080 /* AIFADCL_SRC */ -#define WM8903_AIFADCL_SRC_MASK 0x0080 /* AIFADCL_SRC */ -#define WM8903_AIFADCL_SRC_SHIFT 7 /* AIFADCL_SRC */ -#define WM8903_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */ -#define WM8903_AIFADCR_SRC 0x0040 /* AIFADCR_SRC */ -#define WM8903_AIFADCR_SRC_MASK 0x0040 /* AIFADCR_SRC */ -#define WM8903_AIFADCR_SRC_SHIFT 6 /* AIFADCR_SRC */ -#define WM8903_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */ -#define WM8903_AIFDACL_SRC 0x0020 /* AIFDACL_SRC */ -#define WM8903_AIFDACL_SRC_MASK 0x0020 /* AIFDACL_SRC */ -#define WM8903_AIFDACL_SRC_SHIFT 5 /* AIFDACL_SRC */ -#define WM8903_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */ -#define WM8903_AIFDACR_SRC 0x0010 /* AIFDACR_SRC */ -#define WM8903_AIFDACR_SRC_MASK 0x0010 /* AIFDACR_SRC */ -#define WM8903_AIFDACR_SRC_SHIFT 4 /* AIFDACR_SRC */ -#define WM8903_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */ -#define WM8903_ADC_COMP 0x0008 /* ADC_COMP */ -#define WM8903_ADC_COMP_MASK 0x0008 /* ADC_COMP */ -#define WM8903_ADC_COMP_SHIFT 3 /* ADC_COMP */ -#define WM8903_ADC_COMP_WIDTH 1 /* ADC_COMP */ -#define WM8903_ADC_COMPMODE 0x0004 /* ADC_COMPMODE */ -#define WM8903_ADC_COMPMODE_MASK 0x0004 /* ADC_COMPMODE */ -#define WM8903_ADC_COMPMODE_SHIFT 2 /* ADC_COMPMODE */ -#define WM8903_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */ -#define WM8903_DAC_COMP 0x0002 /* DAC_COMP */ -#define WM8903_DAC_COMP_MASK 0x0002 /* DAC_COMP */ -#define WM8903_DAC_COMP_SHIFT 1 /* DAC_COMP */ -#define WM8903_DAC_COMP_WIDTH 1 /* DAC_COMP */ -#define WM8903_DAC_COMPMODE 0x0001 /* DAC_COMPMODE */ -#define WM8903_DAC_COMPMODE_MASK 0x0001 /* DAC_COMPMODE */ -#define WM8903_DAC_COMPMODE_SHIFT 0 /* DAC_COMPMODE */ -#define WM8903_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ - -/* - * R25 (0x19) - Audio Interface 1 - */ -#define WM8903_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ -#define WM8903_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */ -#define WM8903_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */ -#define WM8903_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */ -#define WM8903_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8903_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8903_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */ -#define WM8903_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */ -#define WM8903_AIFADC_TDM 0x0800 /* AIFADC_TDM */ -#define WM8903_AIFADC_TDM_MASK 0x0800 /* AIFADC_TDM */ -#define WM8903_AIFADC_TDM_SHIFT 11 /* AIFADC_TDM */ -#define WM8903_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */ -#define WM8903_AIFADC_TDM_CHAN 0x0400 /* AIFADC_TDM_CHAN */ -#define WM8903_AIFADC_TDM_CHAN_MASK 0x0400 /* AIFADC_TDM_CHAN */ -#define WM8903_AIFADC_TDM_CHAN_SHIFT 10 /* AIFADC_TDM_CHAN */ -#define WM8903_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */ -#define WM8903_LRCLK_DIR 0x0200 /* LRCLK_DIR */ -#define WM8903_LRCLK_DIR_MASK 0x0200 /* LRCLK_DIR */ -#define WM8903_LRCLK_DIR_SHIFT 9 /* LRCLK_DIR */ -#define WM8903_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */ -#define WM8903_AIF_BCLK_INV 0x0080 /* AIF_BCLK_INV */ -#define WM8903_AIF_BCLK_INV_MASK 0x0080 /* AIF_BCLK_INV */ -#define WM8903_AIF_BCLK_INV_SHIFT 7 /* AIF_BCLK_INV */ -#define WM8903_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */ -#define WM8903_BCLK_DIR 0x0040 /* BCLK_DIR */ -#define WM8903_BCLK_DIR_MASK 0x0040 /* BCLK_DIR */ -#define WM8903_BCLK_DIR_SHIFT 6 /* BCLK_DIR */ -#define WM8903_BCLK_DIR_WIDTH 1 /* BCLK_DIR */ -#define WM8903_AIF_LRCLK_INV 0x0010 /* AIF_LRCLK_INV */ -#define WM8903_AIF_LRCLK_INV_MASK 0x0010 /* AIF_LRCLK_INV */ -#define WM8903_AIF_LRCLK_INV_SHIFT 4 /* AIF_LRCLK_INV */ -#define WM8903_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */ -#define WM8903_AIF_WL_MASK 0x000C /* AIF_WL - [3:2] */ -#define WM8903_AIF_WL_SHIFT 2 /* AIF_WL - [3:2] */ -#define WM8903_AIF_WL_WIDTH 2 /* AIF_WL - [3:2] */ -#define WM8903_AIF_FMT_MASK 0x0003 /* AIF_FMT - [1:0] */ -#define WM8903_AIF_FMT_SHIFT 0 /* AIF_FMT - [1:0] */ -#define WM8903_AIF_FMT_WIDTH 2 /* AIF_FMT - [1:0] */ - -/* - * R26 (0x1A) - Audio Interface 2 - */ -#define WM8903_BCLK_DIV_MASK 0x001F /* BCLK_DIV - [4:0] */ -#define WM8903_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [4:0] */ -#define WM8903_BCLK_DIV_WIDTH 5 /* BCLK_DIV - [4:0] */ - -/* - * R27 (0x1B) - Audio Interface 3 - */ -#define WM8903_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */ -#define WM8903_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */ -#define WM8903_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */ - -/* - * R30 (0x1E) - DAC Digital Volume Left - */ -#define WM8903_DACVU 0x0100 /* DACVU */ -#define WM8903_DACVU_MASK 0x0100 /* DACVU */ -#define WM8903_DACVU_SHIFT 8 /* DACVU */ -#define WM8903_DACVU_WIDTH 1 /* DACVU */ -#define WM8903_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ -#define WM8903_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */ -#define WM8903_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */ - -/* - * R31 (0x1F) - DAC Digital Volume Right - */ -#define WM8903_DACVU 0x0100 /* DACVU */ -#define WM8903_DACVU_MASK 0x0100 /* DACVU */ -#define WM8903_DACVU_SHIFT 8 /* DACVU */ -#define WM8903_DACVU_WIDTH 1 /* DACVU */ -#define WM8903_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ -#define WM8903_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */ -#define WM8903_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */ - -/* - * R32 (0x20) - DAC Digital 0 - */ -#define WM8903_ADCL_DAC_SVOL_MASK 0x0F00 /* ADCL_DAC_SVOL - [11:8] */ -#define WM8903_ADCL_DAC_SVOL_SHIFT 8 /* ADCL_DAC_SVOL - [11:8] */ -#define WM8903_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [11:8] */ -#define WM8903_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8903_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8903_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8903_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8903_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8903_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ -#define WM8903_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */ -#define WM8903_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */ -#define WM8903_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */ - -/* - * R33 (0x21) - DAC Digital 1 - */ -#define WM8903_DAC_MONO 0x1000 /* DAC_MONO */ -#define WM8903_DAC_MONO_MASK 0x1000 /* DAC_MONO */ -#define WM8903_DAC_MONO_SHIFT 12 /* DAC_MONO */ -#define WM8903_DAC_MONO_WIDTH 1 /* DAC_MONO */ -#define WM8903_DAC_SB_FILT 0x0800 /* DAC_SB_FILT */ -#define WM8903_DAC_SB_FILT_MASK 0x0800 /* DAC_SB_FILT */ -#define WM8903_DAC_SB_FILT_SHIFT 11 /* DAC_SB_FILT */ -#define WM8903_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */ -#define WM8903_DAC_MUTERATE 0x0400 /* DAC_MUTERATE */ -#define WM8903_DAC_MUTERATE_MASK 0x0400 /* DAC_MUTERATE */ -#define WM8903_DAC_MUTERATE_SHIFT 10 /* DAC_MUTERATE */ -#define WM8903_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ -#define WM8903_DAC_MUTEMODE 0x0200 /* DAC_MUTEMODE */ -#define WM8903_DAC_MUTEMODE_MASK 0x0200 /* DAC_MUTEMODE */ -#define WM8903_DAC_MUTEMODE_SHIFT 9 /* DAC_MUTEMODE */ -#define WM8903_DAC_MUTEMODE_WIDTH 1 /* DAC_MUTEMODE */ -#define WM8903_DAC_MUTE 0x0008 /* DAC_MUTE */ -#define WM8903_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */ -#define WM8903_DAC_MUTE_SHIFT 3 /* DAC_MUTE */ -#define WM8903_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ -#define WM8903_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ -#define WM8903_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ -#define WM8903_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ - -/* - * R36 (0x24) - ADC Digital Volume Left - */ -#define WM8903_ADCVU 0x0100 /* ADCVU */ -#define WM8903_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8903_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8903_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8903_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ -#define WM8903_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */ -#define WM8903_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */ - -/* - * R37 (0x25) - ADC Digital Volume Right - */ -#define WM8903_ADCVU 0x0100 /* ADCVU */ -#define WM8903_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8903_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8903_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8903_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ -#define WM8903_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */ -#define WM8903_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */ - -/* - * R38 (0x26) - ADC Digital 0 - */ -#define WM8903_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */ -#define WM8903_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */ -#define WM8903_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */ -#define WM8903_ADC_HPF_ENA 0x0010 /* ADC_HPF_ENA */ -#define WM8903_ADC_HPF_ENA_MASK 0x0010 /* ADC_HPF_ENA */ -#define WM8903_ADC_HPF_ENA_SHIFT 4 /* ADC_HPF_ENA */ -#define WM8903_ADC_HPF_ENA_WIDTH 1 /* ADC_HPF_ENA */ -#define WM8903_ADCL_DATINV 0x0002 /* ADCL_DATINV */ -#define WM8903_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */ -#define WM8903_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */ -#define WM8903_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */ -#define WM8903_ADCR_DATINV 0x0001 /* ADCR_DATINV */ -#define WM8903_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */ -#define WM8903_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */ -#define WM8903_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */ - -/* - * R39 (0x27) - Digital Microphone 0 - */ -#define WM8903_DIGMIC_MODE_SEL 0x0100 /* DIGMIC_MODE_SEL */ -#define WM8903_DIGMIC_MODE_SEL_MASK 0x0100 /* DIGMIC_MODE_SEL */ -#define WM8903_DIGMIC_MODE_SEL_SHIFT 8 /* DIGMIC_MODE_SEL */ -#define WM8903_DIGMIC_MODE_SEL_WIDTH 1 /* DIGMIC_MODE_SEL */ -#define WM8903_DIGMIC_CLK_SEL_L_MASK 0x00C0 /* DIGMIC_CLK_SEL_L - [7:6] */ -#define WM8903_DIGMIC_CLK_SEL_L_SHIFT 6 /* DIGMIC_CLK_SEL_L - [7:6] */ -#define WM8903_DIGMIC_CLK_SEL_L_WIDTH 2 /* DIGMIC_CLK_SEL_L - [7:6] */ -#define WM8903_DIGMIC_CLK_SEL_R_MASK 0x0030 /* DIGMIC_CLK_SEL_R - [5:4] */ -#define WM8903_DIGMIC_CLK_SEL_R_SHIFT 4 /* DIGMIC_CLK_SEL_R - [5:4] */ -#define WM8903_DIGMIC_CLK_SEL_R_WIDTH 2 /* DIGMIC_CLK_SEL_R - [5:4] */ -#define WM8903_DIGMIC_CLK_SEL_RT_MASK 0x000C /* DIGMIC_CLK_SEL_RT - [3:2] */ -#define WM8903_DIGMIC_CLK_SEL_RT_SHIFT 2 /* DIGMIC_CLK_SEL_RT - [3:2] */ -#define WM8903_DIGMIC_CLK_SEL_RT_WIDTH 2 /* DIGMIC_CLK_SEL_RT - [3:2] */ -#define WM8903_DIGMIC_CLK_SEL_MASK 0x0003 /* DIGMIC_CLK_SEL - [1:0] */ -#define WM8903_DIGMIC_CLK_SEL_SHIFT 0 /* DIGMIC_CLK_SEL - [1:0] */ -#define WM8903_DIGMIC_CLK_SEL_WIDTH 2 /* DIGMIC_CLK_SEL - [1:0] */ - -/* - * R40 (0x28) - DRC 0 - */ -#define WM8903_DRC_ENA 0x8000 /* DRC_ENA */ -#define WM8903_DRC_ENA_MASK 0x8000 /* DRC_ENA */ -#define WM8903_DRC_ENA_SHIFT 15 /* DRC_ENA */ -#define WM8903_DRC_ENA_WIDTH 1 /* DRC_ENA */ -#define WM8903_DRC_THRESH_HYST_MASK 0x1800 /* DRC_THRESH_HYST - [12:11] */ -#define WM8903_DRC_THRESH_HYST_SHIFT 11 /* DRC_THRESH_HYST - [12:11] */ -#define WM8903_DRC_THRESH_HYST_WIDTH 2 /* DRC_THRESH_HYST - [12:11] */ -#define WM8903_DRC_STARTUP_GAIN_MASK 0x07C0 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM8903_DRC_STARTUP_GAIN_SHIFT 6 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM8903_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM8903_DRC_FF_DELAY 0x0020 /* DRC_FF_DELAY */ -#define WM8903_DRC_FF_DELAY_MASK 0x0020 /* DRC_FF_DELAY */ -#define WM8903_DRC_FF_DELAY_SHIFT 5 /* DRC_FF_DELAY */ -#define WM8903_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */ -#define WM8903_DRC_SMOOTH_ENA 0x0008 /* DRC_SMOOTH_ENA */ -#define WM8903_DRC_SMOOTH_ENA_MASK 0x0008 /* DRC_SMOOTH_ENA */ -#define WM8903_DRC_SMOOTH_ENA_SHIFT 3 /* DRC_SMOOTH_ENA */ -#define WM8903_DRC_SMOOTH_ENA_WIDTH 1 /* DRC_SMOOTH_ENA */ -#define WM8903_DRC_QR_ENA 0x0004 /* DRC_QR_ENA */ -#define WM8903_DRC_QR_ENA_MASK 0x0004 /* DRC_QR_ENA */ -#define WM8903_DRC_QR_ENA_SHIFT 2 /* DRC_QR_ENA */ -#define WM8903_DRC_QR_ENA_WIDTH 1 /* DRC_QR_ENA */ -#define WM8903_DRC_ANTICLIP_ENA 0x0002 /* DRC_ANTICLIP_ENA */ -#define WM8903_DRC_ANTICLIP_ENA_MASK 0x0002 /* DRC_ANTICLIP_ENA */ -#define WM8903_DRC_ANTICLIP_ENA_SHIFT 1 /* DRC_ANTICLIP_ENA */ -#define WM8903_DRC_ANTICLIP_ENA_WIDTH 1 /* DRC_ANTICLIP_ENA */ -#define WM8903_DRC_HYST_ENA 0x0001 /* DRC_HYST_ENA */ -#define WM8903_DRC_HYST_ENA_MASK 0x0001 /* DRC_HYST_ENA */ -#define WM8903_DRC_HYST_ENA_SHIFT 0 /* DRC_HYST_ENA */ -#define WM8903_DRC_HYST_ENA_WIDTH 1 /* DRC_HYST_ENA */ - -/* - * R41 (0x29) - DRC 1 - */ -#define WM8903_DRC_ATTACK_RATE_MASK 0xF000 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8903_DRC_ATTACK_RATE_SHIFT 12 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8903_DRC_ATTACK_RATE_WIDTH 4 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8903_DRC_DECAY_RATE_MASK 0x0F00 /* DRC_DECAY_RATE - [11:8] */ -#define WM8903_DRC_DECAY_RATE_SHIFT 8 /* DRC_DECAY_RATE - [11:8] */ -#define WM8903_DRC_DECAY_RATE_WIDTH 4 /* DRC_DECAY_RATE - [11:8] */ -#define WM8903_DRC_THRESH_QR_MASK 0x00C0 /* DRC_THRESH_QR - [7:6] */ -#define WM8903_DRC_THRESH_QR_SHIFT 6 /* DRC_THRESH_QR - [7:6] */ -#define WM8903_DRC_THRESH_QR_WIDTH 2 /* DRC_THRESH_QR - [7:6] */ -#define WM8903_DRC_RATE_QR_MASK 0x0030 /* DRC_RATE_QR - [5:4] */ -#define WM8903_DRC_RATE_QR_SHIFT 4 /* DRC_RATE_QR - [5:4] */ -#define WM8903_DRC_RATE_QR_WIDTH 2 /* DRC_RATE_QR - [5:4] */ -#define WM8903_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */ -#define WM8903_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */ -#define WM8903_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */ -#define WM8903_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ -#define WM8903_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ -#define WM8903_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ - -/* - * R42 (0x2A) - DRC 2 - */ -#define WM8903_DRC_R0_SLOPE_COMP_MASK 0x0038 /* DRC_R0_SLOPE_COMP - [5:3] */ -#define WM8903_DRC_R0_SLOPE_COMP_SHIFT 3 /* DRC_R0_SLOPE_COMP - [5:3] */ -#define WM8903_DRC_R0_SLOPE_COMP_WIDTH 3 /* DRC_R0_SLOPE_COMP - [5:3] */ -#define WM8903_DRC_R1_SLOPE_COMP_MASK 0x0007 /* DRC_R1_SLOPE_COMP - [2:0] */ -#define WM8903_DRC_R1_SLOPE_COMP_SHIFT 0 /* DRC_R1_SLOPE_COMP - [2:0] */ -#define WM8903_DRC_R1_SLOPE_COMP_WIDTH 3 /* DRC_R1_SLOPE_COMP - [2:0] */ - -/* - * R43 (0x2B) - DRC 3 - */ -#define WM8903_DRC_THRESH_COMP_MASK 0x07E0 /* DRC_THRESH_COMP - [10:5] */ -#define WM8903_DRC_THRESH_COMP_SHIFT 5 /* DRC_THRESH_COMP - [10:5] */ -#define WM8903_DRC_THRESH_COMP_WIDTH 6 /* DRC_THRESH_COMP - [10:5] */ -#define WM8903_DRC_AMP_COMP_MASK 0x001F /* DRC_AMP_COMP - [4:0] */ -#define WM8903_DRC_AMP_COMP_SHIFT 0 /* DRC_AMP_COMP - [4:0] */ -#define WM8903_DRC_AMP_COMP_WIDTH 5 /* DRC_AMP_COMP - [4:0] */ - -/* - * R44 (0x2C) - Analogue Left Input 0 - */ -#define WM8903_LINMUTE 0x0080 /* LINMUTE */ -#define WM8903_LINMUTE_MASK 0x0080 /* LINMUTE */ -#define WM8903_LINMUTE_SHIFT 7 /* LINMUTE */ -#define WM8903_LINMUTE_WIDTH 1 /* LINMUTE */ -#define WM8903_LIN_VOL_MASK 0x001F /* LIN_VOL - [4:0] */ -#define WM8903_LIN_VOL_SHIFT 0 /* LIN_VOL - [4:0] */ -#define WM8903_LIN_VOL_WIDTH 5 /* LIN_VOL - [4:0] */ - -/* - * R45 (0x2D) - Analogue Right Input 0 - */ -#define WM8903_RINMUTE 0x0080 /* RINMUTE */ -#define WM8903_RINMUTE_MASK 0x0080 /* RINMUTE */ -#define WM8903_RINMUTE_SHIFT 7 /* RINMUTE */ -#define WM8903_RINMUTE_WIDTH 1 /* RINMUTE */ -#define WM8903_RIN_VOL_MASK 0x001F /* RIN_VOL - [4:0] */ -#define WM8903_RIN_VOL_SHIFT 0 /* RIN_VOL - [4:0] */ -#define WM8903_RIN_VOL_WIDTH 5 /* RIN_VOL - [4:0] */ - -/* - * R46 (0x2E) - Analogue Left Input 1 - */ -#define WM8903_INL_CM_ENA 0x0040 /* INL_CM_ENA */ -#define WM8903_INL_CM_ENA_MASK 0x0040 /* INL_CM_ENA */ -#define WM8903_INL_CM_ENA_SHIFT 6 /* INL_CM_ENA */ -#define WM8903_INL_CM_ENA_WIDTH 1 /* INL_CM_ENA */ -#define WM8903_L_IP_SEL_N_MASK 0x0030 /* L_IP_SEL_N - [5:4] */ -#define WM8903_L_IP_SEL_N_SHIFT 4 /* L_IP_SEL_N - [5:4] */ -#define WM8903_L_IP_SEL_N_WIDTH 2 /* L_IP_SEL_N - [5:4] */ -#define WM8903_L_IP_SEL_P_MASK 0x000C /* L_IP_SEL_P - [3:2] */ -#define WM8903_L_IP_SEL_P_SHIFT 2 /* L_IP_SEL_P - [3:2] */ -#define WM8903_L_IP_SEL_P_WIDTH 2 /* L_IP_SEL_P - [3:2] */ -#define WM8903_L_MODE_MASK 0x0003 /* L_MODE - [1:0] */ -#define WM8903_L_MODE_SHIFT 0 /* L_MODE - [1:0] */ -#define WM8903_L_MODE_WIDTH 2 /* L_MODE - [1:0] */ - -/* - * R47 (0x2F) - Analogue Right Input 1 - */ -#define WM8903_INR_CM_ENA 0x0040 /* INR_CM_ENA */ -#define WM8903_INR_CM_ENA_MASK 0x0040 /* INR_CM_ENA */ -#define WM8903_INR_CM_ENA_SHIFT 6 /* INR_CM_ENA */ -#define WM8903_INR_CM_ENA_WIDTH 1 /* INR_CM_ENA */ -#define WM8903_R_IP_SEL_N_MASK 0x0030 /* R_IP_SEL_N - [5:4] */ -#define WM8903_R_IP_SEL_N_SHIFT 4 /* R_IP_SEL_N - [5:4] */ -#define WM8903_R_IP_SEL_N_WIDTH 2 /* R_IP_SEL_N - [5:4] */ -#define WM8903_R_IP_SEL_P_MASK 0x000C /* R_IP_SEL_P - [3:2] */ -#define WM8903_R_IP_SEL_P_SHIFT 2 /* R_IP_SEL_P - [3:2] */ -#define WM8903_R_IP_SEL_P_WIDTH 2 /* R_IP_SEL_P - [3:2] */ -#define WM8903_R_MODE_MASK 0x0003 /* R_MODE - [1:0] */ -#define WM8903_R_MODE_SHIFT 0 /* R_MODE - [1:0] */ -#define WM8903_R_MODE_WIDTH 2 /* R_MODE - [1:0] */ - -/* - * R50 (0x32) - Analogue Left Mix 0 - */ -#define WM8903_DACL_TO_MIXOUTL 0x0008 /* DACL_TO_MIXOUTL */ -#define WM8903_DACL_TO_MIXOUTL_MASK 0x0008 /* DACL_TO_MIXOUTL */ -#define WM8903_DACL_TO_MIXOUTL_SHIFT 3 /* DACL_TO_MIXOUTL */ -#define WM8903_DACL_TO_MIXOUTL_WIDTH 1 /* DACL_TO_MIXOUTL */ -#define WM8903_DACR_TO_MIXOUTL 0x0004 /* DACR_TO_MIXOUTL */ -#define WM8903_DACR_TO_MIXOUTL_MASK 0x0004 /* DACR_TO_MIXOUTL */ -#define WM8903_DACR_TO_MIXOUTL_SHIFT 2 /* DACR_TO_MIXOUTL */ -#define WM8903_DACR_TO_MIXOUTL_WIDTH 1 /* DACR_TO_MIXOUTL */ -#define WM8903_BYPASSL_TO_MIXOUTL 0x0002 /* BYPASSL_TO_MIXOUTL */ -#define WM8903_BYPASSL_TO_MIXOUTL_MASK 0x0002 /* BYPASSL_TO_MIXOUTL */ -#define WM8903_BYPASSL_TO_MIXOUTL_SHIFT 1 /* BYPASSL_TO_MIXOUTL */ -#define WM8903_BYPASSL_TO_MIXOUTL_WIDTH 1 /* BYPASSL_TO_MIXOUTL */ -#define WM8903_BYPASSR_TO_MIXOUTL 0x0001 /* BYPASSR_TO_MIXOUTL */ -#define WM8903_BYPASSR_TO_MIXOUTL_MASK 0x0001 /* BYPASSR_TO_MIXOUTL */ -#define WM8903_BYPASSR_TO_MIXOUTL_SHIFT 0 /* BYPASSR_TO_MIXOUTL */ -#define WM8903_BYPASSR_TO_MIXOUTL_WIDTH 1 /* BYPASSR_TO_MIXOUTL */ - -/* - * R51 (0x33) - Analogue Right Mix 0 - */ -#define WM8903_DACL_TO_MIXOUTR 0x0008 /* DACL_TO_MIXOUTR */ -#define WM8903_DACL_TO_MIXOUTR_MASK 0x0008 /* DACL_TO_MIXOUTR */ -#define WM8903_DACL_TO_MIXOUTR_SHIFT 3 /* DACL_TO_MIXOUTR */ -#define WM8903_DACL_TO_MIXOUTR_WIDTH 1 /* DACL_TO_MIXOUTR */ -#define WM8903_DACR_TO_MIXOUTR 0x0004 /* DACR_TO_MIXOUTR */ -#define WM8903_DACR_TO_MIXOUTR_MASK 0x0004 /* DACR_TO_MIXOUTR */ -#define WM8903_DACR_TO_MIXOUTR_SHIFT 2 /* DACR_TO_MIXOUTR */ -#define WM8903_DACR_TO_MIXOUTR_WIDTH 1 /* DACR_TO_MIXOUTR */ -#define WM8903_BYPASSL_TO_MIXOUTR 0x0002 /* BYPASSL_TO_MIXOUTR */ -#define WM8903_BYPASSL_TO_MIXOUTR_MASK 0x0002 /* BYPASSL_TO_MIXOUTR */ -#define WM8903_BYPASSL_TO_MIXOUTR_SHIFT 1 /* BYPASSL_TO_MIXOUTR */ -#define WM8903_BYPASSL_TO_MIXOUTR_WIDTH 1 /* BYPASSL_TO_MIXOUTR */ -#define WM8903_BYPASSR_TO_MIXOUTR 0x0001 /* BYPASSR_TO_MIXOUTR */ -#define WM8903_BYPASSR_TO_MIXOUTR_MASK 0x0001 /* BYPASSR_TO_MIXOUTR */ -#define WM8903_BYPASSR_TO_MIXOUTR_SHIFT 0 /* BYPASSR_TO_MIXOUTR */ -#define WM8903_BYPASSR_TO_MIXOUTR_WIDTH 1 /* BYPASSR_TO_MIXOUTR */ - -/* - * R52 (0x34) - Analogue Spk Mix Left 0 - */ -#define WM8903_DACL_TO_MIXSPKL 0x0008 /* DACL_TO_MIXSPKL */ -#define WM8903_DACL_TO_MIXSPKL_MASK 0x0008 /* DACL_TO_MIXSPKL */ -#define WM8903_DACL_TO_MIXSPKL_SHIFT 3 /* DACL_TO_MIXSPKL */ -#define WM8903_DACL_TO_MIXSPKL_WIDTH 1 /* DACL_TO_MIXSPKL */ -#define WM8903_DACR_TO_MIXSPKL 0x0004 /* DACR_TO_MIXSPKL */ -#define WM8903_DACR_TO_MIXSPKL_MASK 0x0004 /* DACR_TO_MIXSPKL */ -#define WM8903_DACR_TO_MIXSPKL_SHIFT 2 /* DACR_TO_MIXSPKL */ -#define WM8903_DACR_TO_MIXSPKL_WIDTH 1 /* DACR_TO_MIXSPKL */ -#define WM8903_BYPASSL_TO_MIXSPKL 0x0002 /* BYPASSL_TO_MIXSPKL */ -#define WM8903_BYPASSL_TO_MIXSPKL_MASK 0x0002 /* BYPASSL_TO_MIXSPKL */ -#define WM8903_BYPASSL_TO_MIXSPKL_SHIFT 1 /* BYPASSL_TO_MIXSPKL */ -#define WM8903_BYPASSL_TO_MIXSPKL_WIDTH 1 /* BYPASSL_TO_MIXSPKL */ -#define WM8903_BYPASSR_TO_MIXSPKL 0x0001 /* BYPASSR_TO_MIXSPKL */ -#define WM8903_BYPASSR_TO_MIXSPKL_MASK 0x0001 /* BYPASSR_TO_MIXSPKL */ -#define WM8903_BYPASSR_TO_MIXSPKL_SHIFT 0 /* BYPASSR_TO_MIXSPKL */ -#define WM8903_BYPASSR_TO_MIXSPKL_WIDTH 1 /* BYPASSR_TO_MIXSPKL */ - -/* - * R53 (0x35) - Analogue Spk Mix Left 1 - */ -#define WM8903_DACL_MIXSPKL_VOL 0x0008 /* DACL_MIXSPKL_VOL */ -#define WM8903_DACL_MIXSPKL_VOL_MASK 0x0008 /* DACL_MIXSPKL_VOL */ -#define WM8903_DACL_MIXSPKL_VOL_SHIFT 3 /* DACL_MIXSPKL_VOL */ -#define WM8903_DACL_MIXSPKL_VOL_WIDTH 1 /* DACL_MIXSPKL_VOL */ -#define WM8903_DACR_MIXSPKL_VOL 0x0004 /* DACR_MIXSPKL_VOL */ -#define WM8903_DACR_MIXSPKL_VOL_MASK 0x0004 /* DACR_MIXSPKL_VOL */ -#define WM8903_DACR_MIXSPKL_VOL_SHIFT 2 /* DACR_MIXSPKL_VOL */ -#define WM8903_DACR_MIXSPKL_VOL_WIDTH 1 /* DACR_MIXSPKL_VOL */ -#define WM8903_BYPASSL_MIXSPKL_VOL 0x0002 /* BYPASSL_MIXSPKL_VOL */ -#define WM8903_BYPASSL_MIXSPKL_VOL_MASK 0x0002 /* BYPASSL_MIXSPKL_VOL */ -#define WM8903_BYPASSL_MIXSPKL_VOL_SHIFT 1 /* BYPASSL_MIXSPKL_VOL */ -#define WM8903_BYPASSL_MIXSPKL_VOL_WIDTH 1 /* BYPASSL_MIXSPKL_VOL */ -#define WM8903_BYPASSR_MIXSPKL_VOL 0x0001 /* BYPASSR_MIXSPKL_VOL */ -#define WM8903_BYPASSR_MIXSPKL_VOL_MASK 0x0001 /* BYPASSR_MIXSPKL_VOL */ -#define WM8903_BYPASSR_MIXSPKL_VOL_SHIFT 0 /* BYPASSR_MIXSPKL_VOL */ -#define WM8903_BYPASSR_MIXSPKL_VOL_WIDTH 1 /* BYPASSR_MIXSPKL_VOL */ - -/* - * R54 (0x36) - Analogue Spk Mix Right 0 - */ -#define WM8903_DACL_TO_MIXSPKR 0x0008 /* DACL_TO_MIXSPKR */ -#define WM8903_DACL_TO_MIXSPKR_MASK 0x0008 /* DACL_TO_MIXSPKR */ -#define WM8903_DACL_TO_MIXSPKR_SHIFT 3 /* DACL_TO_MIXSPKR */ -#define WM8903_DACL_TO_MIXSPKR_WIDTH 1 /* DACL_TO_MIXSPKR */ -#define WM8903_DACR_TO_MIXSPKR 0x0004 /* DACR_TO_MIXSPKR */ -#define WM8903_DACR_TO_MIXSPKR_MASK 0x0004 /* DACR_TO_MIXSPKR */ -#define WM8903_DACR_TO_MIXSPKR_SHIFT 2 /* DACR_TO_MIXSPKR */ -#define WM8903_DACR_TO_MIXSPKR_WIDTH 1 /* DACR_TO_MIXSPKR */ -#define WM8903_BYPASSL_TO_MIXSPKR 0x0002 /* BYPASSL_TO_MIXSPKR */ -#define WM8903_BYPASSL_TO_MIXSPKR_MASK 0x0002 /* BYPASSL_TO_MIXSPKR */ -#define WM8903_BYPASSL_TO_MIXSPKR_SHIFT 1 /* BYPASSL_TO_MIXSPKR */ -#define WM8903_BYPASSL_TO_MIXSPKR_WIDTH 1 /* BYPASSL_TO_MIXSPKR */ -#define WM8903_BYPASSR_TO_MIXSPKR 0x0001 /* BYPASSR_TO_MIXSPKR */ -#define WM8903_BYPASSR_TO_MIXSPKR_MASK 0x0001 /* BYPASSR_TO_MIXSPKR */ -#define WM8903_BYPASSR_TO_MIXSPKR_SHIFT 0 /* BYPASSR_TO_MIXSPKR */ -#define WM8903_BYPASSR_TO_MIXSPKR_WIDTH 1 /* BYPASSR_TO_MIXSPKR */ - -/* - * R55 (0x37) - Analogue Spk Mix Right 1 - */ -#define WM8903_DACL_MIXSPKR_VOL 0x0008 /* DACL_MIXSPKR_VOL */ -#define WM8903_DACL_MIXSPKR_VOL_MASK 0x0008 /* DACL_MIXSPKR_VOL */ -#define WM8903_DACL_MIXSPKR_VOL_SHIFT 3 /* DACL_MIXSPKR_VOL */ -#define WM8903_DACL_MIXSPKR_VOL_WIDTH 1 /* DACL_MIXSPKR_VOL */ -#define WM8903_DACR_MIXSPKR_VOL 0x0004 /* DACR_MIXSPKR_VOL */ -#define WM8903_DACR_MIXSPKR_VOL_MASK 0x0004 /* DACR_MIXSPKR_VOL */ -#define WM8903_DACR_MIXSPKR_VOL_SHIFT 2 /* DACR_MIXSPKR_VOL */ -#define WM8903_DACR_MIXSPKR_VOL_WIDTH 1 /* DACR_MIXSPKR_VOL */ -#define WM8903_BYPASSL_MIXSPKR_VOL 0x0002 /* BYPASSL_MIXSPKR_VOL */ -#define WM8903_BYPASSL_MIXSPKR_VOL_MASK 0x0002 /* BYPASSL_MIXSPKR_VOL */ -#define WM8903_BYPASSL_MIXSPKR_VOL_SHIFT 1 /* BYPASSL_MIXSPKR_VOL */ -#define WM8903_BYPASSL_MIXSPKR_VOL_WIDTH 1 /* BYPASSL_MIXSPKR_VOL */ -#define WM8903_BYPASSR_MIXSPKR_VOL 0x0001 /* BYPASSR_MIXSPKR_VOL */ -#define WM8903_BYPASSR_MIXSPKR_VOL_MASK 0x0001 /* BYPASSR_MIXSPKR_VOL */ -#define WM8903_BYPASSR_MIXSPKR_VOL_SHIFT 0 /* BYPASSR_MIXSPKR_VOL */ -#define WM8903_BYPASSR_MIXSPKR_VOL_WIDTH 1 /* BYPASSR_MIXSPKR_VOL */ - -/* - * R57 (0x39) - Analogue OUT1 Left - */ -#define WM8903_HPL_MUTE 0x0100 /* HPL_MUTE */ -#define WM8903_HPL_MUTE_MASK 0x0100 /* HPL_MUTE */ -#define WM8903_HPL_MUTE_SHIFT 8 /* HPL_MUTE */ -#define WM8903_HPL_MUTE_WIDTH 1 /* HPL_MUTE */ -#define WM8903_HPOUTVU 0x0080 /* HPOUTVU */ -#define WM8903_HPOUTVU_MASK 0x0080 /* HPOUTVU */ -#define WM8903_HPOUTVU_SHIFT 7 /* HPOUTVU */ -#define WM8903_HPOUTVU_WIDTH 1 /* HPOUTVU */ -#define WM8903_HPOUTLZC 0x0040 /* HPOUTLZC */ -#define WM8903_HPOUTLZC_MASK 0x0040 /* HPOUTLZC */ -#define WM8903_HPOUTLZC_SHIFT 6 /* HPOUTLZC */ -#define WM8903_HPOUTLZC_WIDTH 1 /* HPOUTLZC */ -#define WM8903_HPOUTL_VOL_MASK 0x003F /* HPOUTL_VOL - [5:0] */ -#define WM8903_HPOUTL_VOL_SHIFT 0 /* HPOUTL_VOL - [5:0] */ -#define WM8903_HPOUTL_VOL_WIDTH 6 /* HPOUTL_VOL - [5:0] */ - -/* - * R58 (0x3A) - Analogue OUT1 Right - */ -#define WM8903_HPR_MUTE 0x0100 /* HPR_MUTE */ -#define WM8903_HPR_MUTE_MASK 0x0100 /* HPR_MUTE */ -#define WM8903_HPR_MUTE_SHIFT 8 /* HPR_MUTE */ -#define WM8903_HPR_MUTE_WIDTH 1 /* HPR_MUTE */ -#define WM8903_HPOUTVU 0x0080 /* HPOUTVU */ -#define WM8903_HPOUTVU_MASK 0x0080 /* HPOUTVU */ -#define WM8903_HPOUTVU_SHIFT 7 /* HPOUTVU */ -#define WM8903_HPOUTVU_WIDTH 1 /* HPOUTVU */ -#define WM8903_HPOUTRZC 0x0040 /* HPOUTRZC */ -#define WM8903_HPOUTRZC_MASK 0x0040 /* HPOUTRZC */ -#define WM8903_HPOUTRZC_SHIFT 6 /* HPOUTRZC */ -#define WM8903_HPOUTRZC_WIDTH 1 /* HPOUTRZC */ -#define WM8903_HPOUTR_VOL_MASK 0x003F /* HPOUTR_VOL - [5:0] */ -#define WM8903_HPOUTR_VOL_SHIFT 0 /* HPOUTR_VOL - [5:0] */ -#define WM8903_HPOUTR_VOL_WIDTH 6 /* HPOUTR_VOL - [5:0] */ - -/* - * R59 (0x3B) - Analogue OUT2 Left - */ -#define WM8903_LINEOUTL_MUTE 0x0100 /* LINEOUTL_MUTE */ -#define WM8903_LINEOUTL_MUTE_MASK 0x0100 /* LINEOUTL_MUTE */ -#define WM8903_LINEOUTL_MUTE_SHIFT 8 /* LINEOUTL_MUTE */ -#define WM8903_LINEOUTL_MUTE_WIDTH 1 /* LINEOUTL_MUTE */ -#define WM8903_LINEOUTVU 0x0080 /* LINEOUTVU */ -#define WM8903_LINEOUTVU_MASK 0x0080 /* LINEOUTVU */ -#define WM8903_LINEOUTVU_SHIFT 7 /* LINEOUTVU */ -#define WM8903_LINEOUTVU_WIDTH 1 /* LINEOUTVU */ -#define WM8903_LINEOUTLZC 0x0040 /* LINEOUTLZC */ -#define WM8903_LINEOUTLZC_MASK 0x0040 /* LINEOUTLZC */ -#define WM8903_LINEOUTLZC_SHIFT 6 /* LINEOUTLZC */ -#define WM8903_LINEOUTLZC_WIDTH 1 /* LINEOUTLZC */ -#define WM8903_LINEOUTL_VOL_MASK 0x003F /* LINEOUTL_VOL - [5:0] */ -#define WM8903_LINEOUTL_VOL_SHIFT 0 /* LINEOUTL_VOL - [5:0] */ -#define WM8903_LINEOUTL_VOL_WIDTH 6 /* LINEOUTL_VOL - [5:0] */ - -/* - * R60 (0x3C) - Analogue OUT2 Right - */ -#define WM8903_LINEOUTR_MUTE 0x0100 /* LINEOUTR_MUTE */ -#define WM8903_LINEOUTR_MUTE_MASK 0x0100 /* LINEOUTR_MUTE */ -#define WM8903_LINEOUTR_MUTE_SHIFT 8 /* LINEOUTR_MUTE */ -#define WM8903_LINEOUTR_MUTE_WIDTH 1 /* LINEOUTR_MUTE */ -#define WM8903_LINEOUTVU 0x0080 /* LINEOUTVU */ -#define WM8903_LINEOUTVU_MASK 0x0080 /* LINEOUTVU */ -#define WM8903_LINEOUTVU_SHIFT 7 /* LINEOUTVU */ -#define WM8903_LINEOUTVU_WIDTH 1 /* LINEOUTVU */ -#define WM8903_LINEOUTRZC 0x0040 /* LINEOUTRZC */ -#define WM8903_LINEOUTRZC_MASK 0x0040 /* LINEOUTRZC */ -#define WM8903_LINEOUTRZC_SHIFT 6 /* LINEOUTRZC */ -#define WM8903_LINEOUTRZC_WIDTH 1 /* LINEOUTRZC */ -#define WM8903_LINEOUTR_VOL_MASK 0x003F /* LINEOUTR_VOL - [5:0] */ -#define WM8903_LINEOUTR_VOL_SHIFT 0 /* LINEOUTR_VOL - [5:0] */ -#define WM8903_LINEOUTR_VOL_WIDTH 6 /* LINEOUTR_VOL - [5:0] */ - -/* - * R62 (0x3E) - Analogue OUT3 Left - */ -#define WM8903_SPKL_MUTE 0x0100 /* SPKL_MUTE */ -#define WM8903_SPKL_MUTE_MASK 0x0100 /* SPKL_MUTE */ -#define WM8903_SPKL_MUTE_SHIFT 8 /* SPKL_MUTE */ -#define WM8903_SPKL_MUTE_WIDTH 1 /* SPKL_MUTE */ -#define WM8903_SPKVU 0x0080 /* SPKVU */ -#define WM8903_SPKVU_MASK 0x0080 /* SPKVU */ -#define WM8903_SPKVU_SHIFT 7 /* SPKVU */ -#define WM8903_SPKVU_WIDTH 1 /* SPKVU */ -#define WM8903_SPKLZC 0x0040 /* SPKLZC */ -#define WM8903_SPKLZC_MASK 0x0040 /* SPKLZC */ -#define WM8903_SPKLZC_SHIFT 6 /* SPKLZC */ -#define WM8903_SPKLZC_WIDTH 1 /* SPKLZC */ -#define WM8903_SPKL_VOL_MASK 0x003F /* SPKL_VOL - [5:0] */ -#define WM8903_SPKL_VOL_SHIFT 0 /* SPKL_VOL - [5:0] */ -#define WM8903_SPKL_VOL_WIDTH 6 /* SPKL_VOL - [5:0] */ - -/* - * R63 (0x3F) - Analogue OUT3 Right - */ -#define WM8903_SPKR_MUTE 0x0100 /* SPKR_MUTE */ -#define WM8903_SPKR_MUTE_MASK 0x0100 /* SPKR_MUTE */ -#define WM8903_SPKR_MUTE_SHIFT 8 /* SPKR_MUTE */ -#define WM8903_SPKR_MUTE_WIDTH 1 /* SPKR_MUTE */ -#define WM8903_SPKVU 0x0080 /* SPKVU */ -#define WM8903_SPKVU_MASK 0x0080 /* SPKVU */ -#define WM8903_SPKVU_SHIFT 7 /* SPKVU */ -#define WM8903_SPKVU_WIDTH 1 /* SPKVU */ -#define WM8903_SPKRZC 0x0040 /* SPKRZC */ -#define WM8903_SPKRZC_MASK 0x0040 /* SPKRZC */ -#define WM8903_SPKRZC_SHIFT 6 /* SPKRZC */ -#define WM8903_SPKRZC_WIDTH 1 /* SPKRZC */ -#define WM8903_SPKR_VOL_MASK 0x003F /* SPKR_VOL - [5:0] */ -#define WM8903_SPKR_VOL_SHIFT 0 /* SPKR_VOL - [5:0] */ -#define WM8903_SPKR_VOL_WIDTH 6 /* SPKR_VOL - [5:0] */ - -/* - * R65 (0x41) - Analogue SPK Output Control 0 - */ -#define WM8903_SPK_DISCHARGE 0x0002 /* SPK_DISCHARGE */ -#define WM8903_SPK_DISCHARGE_MASK 0x0002 /* SPK_DISCHARGE */ -#define WM8903_SPK_DISCHARGE_SHIFT 1 /* SPK_DISCHARGE */ -#define WM8903_SPK_DISCHARGE_WIDTH 1 /* SPK_DISCHARGE */ -#define WM8903_VROI 0x0001 /* VROI */ -#define WM8903_VROI_MASK 0x0001 /* VROI */ -#define WM8903_VROI_SHIFT 0 /* VROI */ -#define WM8903_VROI_WIDTH 1 /* VROI */ - -/* - * R67 (0x43) - DC Servo 0 - */ -#define WM8903_DCS_MASTER_ENA 0x0010 /* DCS_MASTER_ENA */ -#define WM8903_DCS_MASTER_ENA_MASK 0x0010 /* DCS_MASTER_ENA */ -#define WM8903_DCS_MASTER_ENA_SHIFT 4 /* DCS_MASTER_ENA */ -#define WM8903_DCS_MASTER_ENA_WIDTH 1 /* DCS_MASTER_ENA */ -#define WM8903_DCS_ENA_MASK 0x000F /* DCS_ENA - [3:0] */ -#define WM8903_DCS_ENA_SHIFT 0 /* DCS_ENA - [3:0] */ -#define WM8903_DCS_ENA_WIDTH 4 /* DCS_ENA - [3:0] */ - -/* - * R69 (0x45) - DC Servo 2 - */ -#define WM8903_DCS_MODE_MASK 0x0003 /* DCS_MODE - [1:0] */ -#define WM8903_DCS_MODE_SHIFT 0 /* DCS_MODE - [1:0] */ -#define WM8903_DCS_MODE_WIDTH 2 /* DCS_MODE - [1:0] */ - -/* - * R90 (0x5A) - Analogue HP 0 - */ -#define WM8903_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */ -#define WM8903_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */ -#define WM8903_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */ -#define WM8903_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */ -#define WM8903_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */ -#define WM8903_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */ -#define WM8903_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */ -#define WM8903_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */ -#define WM8903_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */ -#define WM8903_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */ -#define WM8903_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */ -#define WM8903_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */ -#define WM8903_HPL_ENA 0x0010 /* HPL_ENA */ -#define WM8903_HPL_ENA_MASK 0x0010 /* HPL_ENA */ -#define WM8903_HPL_ENA_SHIFT 4 /* HPL_ENA */ -#define WM8903_HPL_ENA_WIDTH 1 /* HPL_ENA */ -#define WM8903_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */ -#define WM8903_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */ -#define WM8903_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */ -#define WM8903_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */ -#define WM8903_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */ -#define WM8903_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */ -#define WM8903_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */ -#define WM8903_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */ -#define WM8903_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */ -#define WM8903_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */ -#define WM8903_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */ -#define WM8903_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */ -#define WM8903_HPR_ENA 0x0001 /* HPR_ENA */ -#define WM8903_HPR_ENA_MASK 0x0001 /* HPR_ENA */ -#define WM8903_HPR_ENA_SHIFT 0 /* HPR_ENA */ -#define WM8903_HPR_ENA_WIDTH 1 /* HPR_ENA */ - -/* - * R94 (0x5E) - Analogue Lineout 0 - */ -#define WM8903_LINEOUTL_RMV_SHORT 0x0080 /* LINEOUTL_RMV_SHORT */ -#define WM8903_LINEOUTL_RMV_SHORT_MASK 0x0080 /* LINEOUTL_RMV_SHORT */ -#define WM8903_LINEOUTL_RMV_SHORT_SHIFT 7 /* LINEOUTL_RMV_SHORT */ -#define WM8903_LINEOUTL_RMV_SHORT_WIDTH 1 /* LINEOUTL_RMV_SHORT */ -#define WM8903_LINEOUTL_ENA_OUTP 0x0040 /* LINEOUTL_ENA_OUTP */ -#define WM8903_LINEOUTL_ENA_OUTP_MASK 0x0040 /* LINEOUTL_ENA_OUTP */ -#define WM8903_LINEOUTL_ENA_OUTP_SHIFT 6 /* LINEOUTL_ENA_OUTP */ -#define WM8903_LINEOUTL_ENA_OUTP_WIDTH 1 /* LINEOUTL_ENA_OUTP */ -#define WM8903_LINEOUTL_ENA_DLY 0x0020 /* LINEOUTL_ENA_DLY */ -#define WM8903_LINEOUTL_ENA_DLY_MASK 0x0020 /* LINEOUTL_ENA_DLY */ -#define WM8903_LINEOUTL_ENA_DLY_SHIFT 5 /* LINEOUTL_ENA_DLY */ -#define WM8903_LINEOUTL_ENA_DLY_WIDTH 1 /* LINEOUTL_ENA_DLY */ -#define WM8903_LINEOUTL_ENA 0x0010 /* LINEOUTL_ENA */ -#define WM8903_LINEOUTL_ENA_MASK 0x0010 /* LINEOUTL_ENA */ -#define WM8903_LINEOUTL_ENA_SHIFT 4 /* LINEOUTL_ENA */ -#define WM8903_LINEOUTL_ENA_WIDTH 1 /* LINEOUTL_ENA */ -#define WM8903_LINEOUTR_RMV_SHORT 0x0008 /* LINEOUTR_RMV_SHORT */ -#define WM8903_LINEOUTR_RMV_SHORT_MASK 0x0008 /* LINEOUTR_RMV_SHORT */ -#define WM8903_LINEOUTR_RMV_SHORT_SHIFT 3 /* LINEOUTR_RMV_SHORT */ -#define WM8903_LINEOUTR_RMV_SHORT_WIDTH 1 /* LINEOUTR_RMV_SHORT */ -#define WM8903_LINEOUTR_ENA_OUTP 0x0004 /* LINEOUTR_ENA_OUTP */ -#define WM8903_LINEOUTR_ENA_OUTP_MASK 0x0004 /* LINEOUTR_ENA_OUTP */ -#define WM8903_LINEOUTR_ENA_OUTP_SHIFT 2 /* LINEOUTR_ENA_OUTP */ -#define WM8903_LINEOUTR_ENA_OUTP_WIDTH 1 /* LINEOUTR_ENA_OUTP */ -#define WM8903_LINEOUTR_ENA_DLY 0x0002 /* LINEOUTR_ENA_DLY */ -#define WM8903_LINEOUTR_ENA_DLY_MASK 0x0002 /* LINEOUTR_ENA_DLY */ -#define WM8903_LINEOUTR_ENA_DLY_SHIFT 1 /* LINEOUTR_ENA_DLY */ -#define WM8903_LINEOUTR_ENA_DLY_WIDTH 1 /* LINEOUTR_ENA_DLY */ -#define WM8903_LINEOUTR_ENA 0x0001 /* LINEOUTR_ENA */ -#define WM8903_LINEOUTR_ENA_MASK 0x0001 /* LINEOUTR_ENA */ -#define WM8903_LINEOUTR_ENA_SHIFT 0 /* LINEOUTR_ENA */ -#define WM8903_LINEOUTR_ENA_WIDTH 1 /* LINEOUTR_ENA */ - -/* - * R98 (0x62) - Charge Pump 0 - */ -#define WM8903_CP_ENA 0x0001 /* CP_ENA */ -#define WM8903_CP_ENA_MASK 0x0001 /* CP_ENA */ -#define WM8903_CP_ENA_SHIFT 0 /* CP_ENA */ -#define WM8903_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R104 (0x68) - Class W 0 - */ -#define WM8903_CP_DYN_FREQ 0x0002 /* CP_DYN_FREQ */ -#define WM8903_CP_DYN_FREQ_MASK 0x0002 /* CP_DYN_FREQ */ -#define WM8903_CP_DYN_FREQ_SHIFT 1 /* CP_DYN_FREQ */ -#define WM8903_CP_DYN_FREQ_WIDTH 1 /* CP_DYN_FREQ */ -#define WM8903_CP_DYN_V 0x0001 /* CP_DYN_V */ -#define WM8903_CP_DYN_V_MASK 0x0001 /* CP_DYN_V */ -#define WM8903_CP_DYN_V_SHIFT 0 /* CP_DYN_V */ -#define WM8903_CP_DYN_V_WIDTH 1 /* CP_DYN_V */ - -/* - * R108 (0x6C) - Write Sequencer 0 - */ -#define WM8903_WSEQ_ENA 0x0100 /* WSEQ_ENA */ -#define WM8903_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */ -#define WM8903_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */ -#define WM8903_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8903_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8903_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8903_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ - -/* - * R109 (0x6D) - Write Sequencer 1 - */ -#define WM8903_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8903_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8903_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8903_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */ -#define WM8903_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */ -#define WM8903_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */ -#define WM8903_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM8903_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM8903_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R110 (0x6E) - Write Sequencer 2 - */ -#define WM8903_WSEQ_EOS 0x4000 /* WSEQ_EOS */ -#define WM8903_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */ -#define WM8903_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */ -#define WM8903_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM8903_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */ -#define WM8903_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */ -#define WM8903_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */ -#define WM8903_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM8903_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM8903_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R111 (0x6F) - Write Sequencer 3 - */ -#define WM8903_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM8903_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM8903_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM8903_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8903_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM8903_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM8903_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM8903_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8903_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM8903_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM8903_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R112 (0x70) - Write Sequencer 4 - */ -#define WM8903_WSEQ_CURRENT_INDEX_MASK 0x03F0 /* WSEQ_CURRENT_INDEX - [9:4] */ -#define WM8903_WSEQ_CURRENT_INDEX_SHIFT 4 /* WSEQ_CURRENT_INDEX - [9:4] */ -#define WM8903_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [9:4] */ -#define WM8903_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8903_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8903_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8903_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R114 (0x72) - Control Interface - */ -#define WM8903_MASK_WRITE_ENA 0x0001 /* MASK_WRITE_ENA */ -#define WM8903_MASK_WRITE_ENA_MASK 0x0001 /* MASK_WRITE_ENA */ -#define WM8903_MASK_WRITE_ENA_SHIFT 0 /* MASK_WRITE_ENA */ -#define WM8903_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */ - -/* - * R121 (0x79) - Interrupt Status 1 - */ -#define WM8903_MICSHRT_EINT 0x8000 /* MICSHRT_EINT */ -#define WM8903_MICSHRT_EINT_MASK 0x8000 /* MICSHRT_EINT */ -#define WM8903_MICSHRT_EINT_SHIFT 15 /* MICSHRT_EINT */ -#define WM8903_MICSHRT_EINT_WIDTH 1 /* MICSHRT_EINT */ -#define WM8903_MICDET_EINT 0x4000 /* MICDET_EINT */ -#define WM8903_MICDET_EINT_MASK 0x4000 /* MICDET_EINT */ -#define WM8903_MICDET_EINT_SHIFT 14 /* MICDET_EINT */ -#define WM8903_MICDET_EINT_WIDTH 1 /* MICDET_EINT */ -#define WM8903_WSEQ_BUSY_EINT 0x2000 /* WSEQ_BUSY_EINT */ -#define WM8903_WSEQ_BUSY_EINT_MASK 0x2000 /* WSEQ_BUSY_EINT */ -#define WM8903_WSEQ_BUSY_EINT_SHIFT 13 /* WSEQ_BUSY_EINT */ -#define WM8903_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */ -#define WM8903_GP5_EINT 0x0010 /* GP5_EINT */ -#define WM8903_GP5_EINT_MASK 0x0010 /* GP5_EINT */ -#define WM8903_GP5_EINT_SHIFT 4 /* GP5_EINT */ -#define WM8903_GP5_EINT_WIDTH 1 /* GP5_EINT */ -#define WM8903_GP4_EINT 0x0008 /* GP4_EINT */ -#define WM8903_GP4_EINT_MASK 0x0008 /* GP4_EINT */ -#define WM8903_GP4_EINT_SHIFT 3 /* GP4_EINT */ -#define WM8903_GP4_EINT_WIDTH 1 /* GP4_EINT */ -#define WM8903_GP3_EINT 0x0004 /* GP3_EINT */ -#define WM8903_GP3_EINT_MASK 0x0004 /* GP3_EINT */ -#define WM8903_GP3_EINT_SHIFT 2 /* GP3_EINT */ -#define WM8903_GP3_EINT_WIDTH 1 /* GP3_EINT */ -#define WM8903_GP2_EINT 0x0002 /* GP2_EINT */ -#define WM8903_GP2_EINT_MASK 0x0002 /* GP2_EINT */ -#define WM8903_GP2_EINT_SHIFT 1 /* GP2_EINT */ -#define WM8903_GP2_EINT_WIDTH 1 /* GP2_EINT */ -#define WM8903_GP1_EINT 0x0001 /* GP1_EINT */ -#define WM8903_GP1_EINT_MASK 0x0001 /* GP1_EINT */ -#define WM8903_GP1_EINT_SHIFT 0 /* GP1_EINT */ -#define WM8903_GP1_EINT_WIDTH 1 /* GP1_EINT */ - -/* - * R122 (0x7A) - Interrupt Status 1 Mask - */ -#define WM8903_IM_MICSHRT_EINT 0x8000 /* IM_MICSHRT_EINT */ -#define WM8903_IM_MICSHRT_EINT_MASK 0x8000 /* IM_MICSHRT_EINT */ -#define WM8903_IM_MICSHRT_EINT_SHIFT 15 /* IM_MICSHRT_EINT */ -#define WM8903_IM_MICSHRT_EINT_WIDTH 1 /* IM_MICSHRT_EINT */ -#define WM8903_IM_MICDET_EINT 0x4000 /* IM_MICDET_EINT */ -#define WM8903_IM_MICDET_EINT_MASK 0x4000 /* IM_MICDET_EINT */ -#define WM8903_IM_MICDET_EINT_SHIFT 14 /* IM_MICDET_EINT */ -#define WM8903_IM_MICDET_EINT_WIDTH 1 /* IM_MICDET_EINT */ -#define WM8903_IM_WSEQ_BUSY_EINT 0x2000 /* IM_WSEQ_BUSY_EINT */ -#define WM8903_IM_WSEQ_BUSY_EINT_MASK 0x2000 /* IM_WSEQ_BUSY_EINT */ -#define WM8903_IM_WSEQ_BUSY_EINT_SHIFT 13 /* IM_WSEQ_BUSY_EINT */ -#define WM8903_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */ -#define WM8903_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */ -#define WM8903_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */ -#define WM8903_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */ -#define WM8903_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */ -#define WM8903_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */ -#define WM8903_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */ -#define WM8903_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */ -#define WM8903_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */ -#define WM8903_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */ -#define WM8903_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */ -#define WM8903_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */ -#define WM8903_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */ -#define WM8903_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */ -#define WM8903_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */ -#define WM8903_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */ -#define WM8903_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */ -#define WM8903_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */ -#define WM8903_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */ -#define WM8903_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */ -#define WM8903_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */ - -/* - * R123 (0x7B) - Interrupt Polarity 1 - */ -#define WM8903_MICSHRT_INV 0x8000 /* MICSHRT_INV */ -#define WM8903_MICSHRT_INV_MASK 0x8000 /* MICSHRT_INV */ -#define WM8903_MICSHRT_INV_SHIFT 15 /* MICSHRT_INV */ -#define WM8903_MICSHRT_INV_WIDTH 1 /* MICSHRT_INV */ -#define WM8903_MICDET_INV 0x4000 /* MICDET_INV */ -#define WM8903_MICDET_INV_MASK 0x4000 /* MICDET_INV */ -#define WM8903_MICDET_INV_SHIFT 14 /* MICDET_INV */ -#define WM8903_MICDET_INV_WIDTH 1 /* MICDET_INV */ - -/* - * R126 (0x7E) - Interrupt Control - */ -#define WM8903_IRQ_POL 0x0001 /* IRQ_POL */ -#define WM8903_IRQ_POL_MASK 0x0001 /* IRQ_POL */ -#define WM8903_IRQ_POL_SHIFT 0 /* IRQ_POL */ -#define WM8903_IRQ_POL_WIDTH 1 /* IRQ_POL */ - -/* - * R164 (0xA4) - Clock Rate Test 4 - */ -#define WM8903_ADC_DIG_MIC 0x0200 /* ADC_DIG_MIC */ -#define WM8903_ADC_DIG_MIC_MASK 0x0200 /* ADC_DIG_MIC */ -#define WM8903_ADC_DIG_MIC_SHIFT 9 /* ADC_DIG_MIC */ -#define WM8903_ADC_DIG_MIC_WIDTH 1 /* ADC_DIG_MIC */ - -/* - * R172 (0xAC) - Analogue Output Bias 0 - */ -#define WM8903_PGA_BIAS_MASK 0x0070 /* PGA_BIAS - [6:4] */ -#define WM8903_PGA_BIAS_SHIFT 4 /* PGA_BIAS - [6:4] */ -#define WM8903_PGA_BIAS_WIDTH 3 /* PGA_BIAS - [6:4] */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8904.c b/ANDROID_3.4.5/sound/soc/codecs/wm8904.c deleted file mode 100644 index 4e190b59..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8904.c +++ /dev/null @@ -1,2339 +0,0 @@ -/* - * wm8904.c -- WM8904 ALSA SoC Audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8904.h" - -enum wm8904_type { - WM8904, - WM8912, -}; - -#define WM8904_NUM_DCS_CHANNELS 4 - -#define WM8904_NUM_SUPPLIES 5 -static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { - "DCVDD", - "DBVDD", - "AVDD", - "CPVDD", - "MICVDD", -}; - -/* codec private data */ -struct wm8904_priv { - struct regmap *regmap; - - enum wm8904_type devtype; - - struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; - - struct wm8904_pdata *pdata; - - int deemph; - - /* Platform provided DRC configuration */ - const char **drc_texts; - int drc_cfg; - struct soc_enum drc_enum; - - /* Platform provided ReTune mobile configuration */ - int num_retune_mobile_texts; - const char **retune_mobile_texts; - int retune_mobile_cfg; - struct soc_enum retune_mobile_enum; - - /* FLL setup */ - int fll_src; - int fll_fref; - int fll_fout; - - /* Clocking configuration */ - unsigned int mclk_rate; - int sysclk_src; - unsigned int sysclk_rate; - - int tdm_width; - int tdm_slots; - int bclk; - int fs; - - /* DC servo configuration - cached offset values */ - int dcs_state[WM8904_NUM_DCS_CHANNELS]; -}; - -static const struct reg_default wm8904_reg_defaults[] = { - { 4, 0x0018 }, /* R4 - Bias Control 0 */ - { 5, 0x0000 }, /* R5 - VMID Control 0 */ - { 6, 0x0000 }, /* R6 - Mic Bias Control 0 */ - { 7, 0x0000 }, /* R7 - Mic Bias Control 1 */ - { 8, 0x0001 }, /* R8 - Analogue DAC 0 */ - { 9, 0x9696 }, /* R9 - mic Filter Control */ - { 10, 0x0001 }, /* R10 - Analogue ADC 0 */ - { 12, 0x0000 }, /* R12 - Power Management 0 */ - { 14, 0x0000 }, /* R14 - Power Management 2 */ - { 15, 0x0000 }, /* R15 - Power Management 3 */ - { 18, 0x0000 }, /* R18 - Power Management 6 */ - { 19, 0x945E }, /* R20 - Clock Rates 0 */ - { 21, 0x0C05 }, /* R21 - Clock Rates 1 */ - { 22, 0x0006 }, /* R22 - Clock Rates 2 */ - { 24, 0x0050 }, /* R24 - Audio Interface 0 */ - { 25, 0x000A }, /* R25 - Audio Interface 1 */ - { 26, 0x00E4 }, /* R26 - Audio Interface 2 */ - { 27, 0x0040 }, /* R27 - Audio Interface 3 */ - { 30, 0x00C0 }, /* R30 - DAC Digital Volume Left */ - { 31, 0x00C0 }, /* R31 - DAC Digital Volume Right */ - { 32, 0x0000 }, /* R32 - DAC Digital 0 */ - { 33, 0x0008 }, /* R33 - DAC Digital 1 */ - { 36, 0x00C0 }, /* R36 - ADC Digital Volume Left */ - { 37, 0x00C0 }, /* R37 - ADC Digital Volume Right */ - { 38, 0x0010 }, /* R38 - ADC Digital 0 */ - { 39, 0x0000 }, /* R39 - Digital Microphone 0 */ - { 40, 0x01AF }, /* R40 - DRC 0 */ - { 41, 0x3248 }, /* R41 - DRC 1 */ - { 42, 0x0000 }, /* R42 - DRC 2 */ - { 43, 0x0000 }, /* R43 - DRC 3 */ - { 44, 0x0085 }, /* R44 - Analogue Left Input 0 */ - { 45, 0x0085 }, /* R45 - Analogue Right Input 0 */ - { 46, 0x0044 }, /* R46 - Analogue Left Input 1 */ - { 47, 0x0044 }, /* R47 - Analogue Right Input 1 */ - { 57, 0x002D }, /* R57 - Analogue OUT1 Left */ - { 58, 0x002D }, /* R58 - Analogue OUT1 Right */ - { 59, 0x0039 }, /* R59 - Analogue OUT2 Left */ - { 60, 0x0039 }, /* R60 - Analogue OUT2 Right */ - { 61, 0x0000 }, /* R61 - Analogue OUT12 ZC */ - { 67, 0x0000 }, /* R67 - DC Servo 0 */ - { 69, 0xAAAA }, /* R69 - DC Servo 2 */ - { 71, 0xAAAA }, /* R71 - DC Servo 4 */ - { 72, 0xAAAA }, /* R72 - DC Servo 5 */ - { 90, 0x0000 }, /* R90 - Analogue HP 0 */ - { 94, 0x0000 }, /* R94 - Analogue Lineout 0 */ - { 98, 0x0000 }, /* R98 - Charge Pump 0 */ - { 104, 0x0004 }, /* R104 - Class W 0 */ - { 108, 0x0000 }, /* R108 - Write Sequencer 0 */ - { 109, 0x0000 }, /* R109 - Write Sequencer 1 */ - { 110, 0x0000 }, /* R110 - Write Sequencer 2 */ - { 111, 0x0000 }, /* R111 - Write Sequencer 3 */ - { 112, 0x0000 }, /* R112 - Write Sequencer 4 */ - { 116, 0x0000 }, /* R116 - FLL Control 1 */ - { 117, 0x0007 }, /* R117 - FLL Control 2 */ - { 118, 0x0000 }, /* R118 - FLL Control 3 */ - { 119, 0x2EE0 }, /* R119 - FLL Control 4 */ - { 120, 0x0004 }, /* R120 - FLL Control 5 */ - { 121, 0x0014 }, /* R121 - GPIO Control 1 */ - { 122, 0x0010 }, /* R122 - GPIO Control 2 */ - { 123, 0x0010 }, /* R123 - GPIO Control 3 */ - { 124, 0x0000 }, /* R124 - GPIO Control 4 */ - { 126, 0x0000 }, /* R126 - Digital Pulls */ - { 128, 0xFFFF }, /* R128 - Interrupt Status Mask */ - { 129, 0x0000 }, /* R129 - Interrupt Polarity */ - { 130, 0x0000 }, /* R130 - Interrupt Debounce */ - { 134, 0x0000 }, /* R134 - EQ1 */ - { 135, 0x000C }, /* R135 - EQ2 */ - { 136, 0x000C }, /* R136 - EQ3 */ - { 137, 0x000C }, /* R137 - EQ4 */ - { 138, 0x000C }, /* R138 - EQ5 */ - { 139, 0x000C }, /* R139 - EQ6 */ - { 140, 0x0FCA }, /* R140 - EQ7 */ - { 141, 0x0400 }, /* R141 - EQ8 */ - { 142, 0x00D8 }, /* R142 - EQ9 */ - { 143, 0x1EB5 }, /* R143 - EQ10 */ - { 144, 0xF145 }, /* R144 - EQ11 */ - { 145, 0x0B75 }, /* R145 - EQ12 */ - { 146, 0x01C5 }, /* R146 - EQ13 */ - { 147, 0x1C58 }, /* R147 - EQ14 */ - { 148, 0xF373 }, /* R148 - EQ15 */ - { 149, 0x0A54 }, /* R149 - EQ16 */ - { 150, 0x0558 }, /* R150 - EQ17 */ - { 151, 0x168E }, /* R151 - EQ18 */ - { 152, 0xF829 }, /* R152 - EQ19 */ - { 153, 0x07AD }, /* R153 - EQ20 */ - { 154, 0x1103 }, /* R154 - EQ21 */ - { 155, 0x0564 }, /* R155 - EQ22 */ - { 156, 0x0559 }, /* R156 - EQ23 */ - { 157, 0x4000 }, /* R157 - EQ24 */ - { 161, 0x0000 }, /* R161 - Control Interface Test 1 */ - { 204, 0x0000 }, /* R204 - Analogue Output Bias 0 */ - { 247, 0x0000 }, /* R247 - FLL NCO Test 0 */ - { 248, 0x0019 }, /* R248 - FLL NCO Test 1 */ -}; - -static bool wm8904_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8904_SW_RESET_AND_ID: - case WM8904_REVISION: - case WM8904_DC_SERVO_1: - case WM8904_DC_SERVO_6: - case WM8904_DC_SERVO_7: - case WM8904_DC_SERVO_8: - case WM8904_DC_SERVO_9: - case WM8904_DC_SERVO_READBACK_0: - case WM8904_INTERRUPT_STATUS: - return true; - default: - return false; - } -} - -static bool wm8904_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8904_SW_RESET_AND_ID: - case WM8904_REVISION: - case WM8904_BIAS_CONTROL_0: - case WM8904_VMID_CONTROL_0: - case WM8904_MIC_BIAS_CONTROL_0: - case WM8904_MIC_BIAS_CONTROL_1: - case WM8904_ANALOGUE_DAC_0: - case WM8904_MIC_FILTER_CONTROL: - case WM8904_ANALOGUE_ADC_0: - case WM8904_POWER_MANAGEMENT_0: - case WM8904_POWER_MANAGEMENT_2: - case WM8904_POWER_MANAGEMENT_3: - case WM8904_POWER_MANAGEMENT_6: - case WM8904_CLOCK_RATES_0: - case WM8904_CLOCK_RATES_1: - case WM8904_CLOCK_RATES_2: - case WM8904_AUDIO_INTERFACE_0: - case WM8904_AUDIO_INTERFACE_1: - case WM8904_AUDIO_INTERFACE_2: - case WM8904_AUDIO_INTERFACE_3: - case WM8904_DAC_DIGITAL_VOLUME_LEFT: - case WM8904_DAC_DIGITAL_VOLUME_RIGHT: - case WM8904_DAC_DIGITAL_0: - case WM8904_DAC_DIGITAL_1: - case WM8904_ADC_DIGITAL_VOLUME_LEFT: - case WM8904_ADC_DIGITAL_VOLUME_RIGHT: - case WM8904_ADC_DIGITAL_0: - case WM8904_DIGITAL_MICROPHONE_0: - case WM8904_DRC_0: - case WM8904_DRC_1: - case WM8904_DRC_2: - case WM8904_DRC_3: - case WM8904_ANALOGUE_LEFT_INPUT_0: - case WM8904_ANALOGUE_RIGHT_INPUT_0: - case WM8904_ANALOGUE_LEFT_INPUT_1: - case WM8904_ANALOGUE_RIGHT_INPUT_1: - case WM8904_ANALOGUE_OUT1_LEFT: - case WM8904_ANALOGUE_OUT1_RIGHT: - case WM8904_ANALOGUE_OUT2_LEFT: - case WM8904_ANALOGUE_OUT2_RIGHT: - case WM8904_ANALOGUE_OUT12_ZC: - case WM8904_DC_SERVO_0: - case WM8904_DC_SERVO_1: - case WM8904_DC_SERVO_2: - case WM8904_DC_SERVO_4: - case WM8904_DC_SERVO_5: - case WM8904_DC_SERVO_6: - case WM8904_DC_SERVO_7: - case WM8904_DC_SERVO_8: - case WM8904_DC_SERVO_9: - case WM8904_DC_SERVO_READBACK_0: - case WM8904_ANALOGUE_HP_0: - case WM8904_ANALOGUE_LINEOUT_0: - case WM8904_CHARGE_PUMP_0: - case WM8904_CLASS_W_0: - case WM8904_WRITE_SEQUENCER_0: - case WM8904_WRITE_SEQUENCER_1: - case WM8904_WRITE_SEQUENCER_2: - case WM8904_WRITE_SEQUENCER_3: - case WM8904_WRITE_SEQUENCER_4: - case WM8904_FLL_CONTROL_1: - case WM8904_FLL_CONTROL_2: - case WM8904_FLL_CONTROL_3: - case WM8904_FLL_CONTROL_4: - case WM8904_FLL_CONTROL_5: - case WM8904_GPIO_CONTROL_1: - case WM8904_GPIO_CONTROL_2: - case WM8904_GPIO_CONTROL_3: - case WM8904_GPIO_CONTROL_4: - case WM8904_DIGITAL_PULLS: - case WM8904_INTERRUPT_STATUS: - case WM8904_INTERRUPT_STATUS_MASK: - case WM8904_INTERRUPT_POLARITY: - case WM8904_INTERRUPT_DEBOUNCE: - case WM8904_EQ1: - case WM8904_EQ2: - case WM8904_EQ3: - case WM8904_EQ4: - case WM8904_EQ5: - case WM8904_EQ6: - case WM8904_EQ7: - case WM8904_EQ8: - case WM8904_EQ9: - case WM8904_EQ10: - case WM8904_EQ11: - case WM8904_EQ12: - case WM8904_EQ13: - case WM8904_EQ14: - case WM8904_EQ15: - case WM8904_EQ16: - case WM8904_EQ17: - case WM8904_EQ18: - case WM8904_EQ19: - case WM8904_EQ20: - case WM8904_EQ21: - case WM8904_EQ22: - case WM8904_EQ23: - case WM8904_EQ24: - case WM8904_CONTROL_INTERFACE_TEST_1: - case WM8904_ADC_TEST_0: - case WM8904_ANALOGUE_OUTPUT_BIAS_0: - case WM8904_FLL_NCO_TEST_0: - case WM8904_FLL_NCO_TEST_1: - return true; - default: - return true; - } -} - -static int wm8904_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8904_SW_RESET_AND_ID, 0); -} - -static int wm8904_configure_clocking(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - unsigned int clock0, clock2, rate; - - /* Gate the clock while we're updating to avoid misclocking */ - clock2 = snd_soc_read(codec, WM8904_CLOCK_RATES_2); - snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, - WM8904_SYSCLK_SRC, 0); - - /* This should be done on init() for bypass paths */ - switch (wm8904->sysclk_src) { - case WM8904_CLK_MCLK: - dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8904->mclk_rate); - - clock2 &= ~WM8904_SYSCLK_SRC; - rate = wm8904->mclk_rate; - - /* Ensure the FLL is stopped */ - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0); - break; - - case WM8904_CLK_FLL: - dev_dbg(codec->dev, "Using %dHz FLL clock\n", - wm8904->fll_fout); - - clock2 |= WM8904_SYSCLK_SRC; - rate = wm8904->fll_fout; - break; - - default: - dev_err(codec->dev, "System clock not configured\n"); - return -EINVAL; - } - - /* SYSCLK shouldn't be over 13.5MHz */ - if (rate > 13500000) { - clock0 = WM8904_MCLK_DIV; - wm8904->sysclk_rate = rate / 2; - } else { - clock0 = 0; - wm8904->sysclk_rate = rate; - } - - snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0, WM8904_MCLK_DIV, - clock0); - - snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, - WM8904_CLK_SYS_ENA | WM8904_SYSCLK_SRC, clock2); - - dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8904->sysclk_rate); - - return 0; -} - -static void wm8904_set_drc(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct wm8904_pdata *pdata = wm8904->pdata; - int save, i; - - /* Save any enables; the configuration should clear them. */ - save = snd_soc_read(codec, WM8904_DRC_0); - - for (i = 0; i < WM8904_DRC_REGS; i++) - snd_soc_update_bits(codec, WM8904_DRC_0 + i, 0xffff, - pdata->drc_cfgs[wm8904->drc_cfg].regs[i]); - - /* Reenable the DRC */ - snd_soc_update_bits(codec, WM8904_DRC_0, - WM8904_DRC_ENA | WM8904_DRC_DAC_PATH, save); -} - -static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct wm8904_pdata *pdata = wm8904->pdata; - int value = ucontrol->value.integer.value[0]; - - if (value >= pdata->num_drc_cfgs) - return -EINVAL; - - wm8904->drc_cfg = value; - - wm8904_set_drc(codec); - - return 0; -} - -static int wm8904_get_drc_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8904->drc_cfg; - - return 0; -} - -static void wm8904_set_retune_mobile(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct wm8904_pdata *pdata = wm8904->pdata; - int best, best_val, save, i, cfg; - - if (!pdata || !wm8904->num_retune_mobile_texts) - return; - - /* Find the version of the currently selected configuration - * with the nearest sample rate. */ - cfg = wm8904->retune_mobile_cfg; - best = 0; - best_val = INT_MAX; - for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { - if (strcmp(pdata->retune_mobile_cfgs[i].name, - wm8904->retune_mobile_texts[cfg]) == 0 && - abs(pdata->retune_mobile_cfgs[i].rate - - wm8904->fs) < best_val) { - best = i; - best_val = abs(pdata->retune_mobile_cfgs[i].rate - - wm8904->fs); - } - } - - dev_dbg(codec->dev, "ReTune Mobile %s/%dHz for %dHz sample rate\n", - pdata->retune_mobile_cfgs[best].name, - pdata->retune_mobile_cfgs[best].rate, - wm8904->fs); - - /* The EQ will be disabled while reconfiguring it, remember the - * current configuration. - */ - save = snd_soc_read(codec, WM8904_EQ1); - - for (i = 0; i < WM8904_EQ_REGS; i++) - snd_soc_update_bits(codec, WM8904_EQ1 + i, 0xffff, - pdata->retune_mobile_cfgs[best].regs[i]); - - snd_soc_update_bits(codec, WM8904_EQ1, WM8904_EQ_ENA, save); -} - -static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct wm8904_pdata *pdata = wm8904->pdata; - int value = ucontrol->value.integer.value[0]; - - if (value >= pdata->num_retune_mobile_cfgs) - return -EINVAL; - - wm8904->retune_mobile_cfg = value; - - wm8904_set_retune_mobile(codec); - - return 0; -} - -static int wm8904_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8904->retune_mobile_cfg; - - return 0; -} - -static int deemph_settings[] = { 0, 32000, 44100, 48000 }; - -static int wm8904_set_deemph(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int val, i, best; - - /* If we're using deemphasis select the nearest available sample - * rate. - */ - if (wm8904->deemph) { - best = 1; - for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { - if (abs(deemph_settings[i] - wm8904->fs) < - abs(deemph_settings[best] - wm8904->fs)) - best = i; - } - - val = best << WM8904_DEEMPH_SHIFT; - } else { - val = 0; - } - - dev_dbg(codec->dev, "Set deemphasis %d\n", val); - - return snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_1, - WM8904_DEEMPH_MASK, val); -} - -static int wm8904_get_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8904->deemph; - return 0; -} - -static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int deemph = ucontrol->value.enumerated.item[0]; - - if (deemph > 1) - return -EINVAL; - - wm8904->deemph = deemph; - - return wm8904_set_deemph(codec); -} - -static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); - -static const char *input_mode_text[] = { - "Single-Ended", "Differential Line", "Differential Mic" -}; - -static const struct soc_enum lin_mode = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 0, 3, input_mode_text); - -static const struct soc_enum rin_mode = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 0, 3, input_mode_text); - -static const char *hpf_mode_text[] = { - "Hi-fi", "Voice 1", "Voice 2", "Voice 3" -}; - -static const struct soc_enum hpf_mode = - SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text); - -static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int val; - int ret; - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret < 0) - return ret; - - if (ucontrol->value.integer.value[0]) - val = 0; - else - val = WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5; - - snd_soc_update_bits(codec, WM8904_ADC_TEST_0, - WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5, - val); - - return ret; -} - -static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = { -SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT, - WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv), - -SOC_ENUM("Left Caputure Mode", lin_mode), -SOC_ENUM("Right Capture Mode", rin_mode), - -/* No TLV since it depends on mode */ -SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0, - WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0), -SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0, - WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 1), - -SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0), -SOC_ENUM("High Pass Filter Mode", hpf_mode), - -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC 128x OSR Switch", - .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, - .put = wm8904_adc_osr_put, - .private_value = SOC_SINGLE_VALUE(WM8904_ANALOGUE_ADC_0, 0, 1, 0), -}, -}; - -static const char *drc_path_text[] = { - "ADC", "DAC" -}; - -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8904_DRC_0, 14, 2, drc_path_text); - -static const struct snd_kcontrol_new wm8904_dac_snd_controls[] = { -SOC_SINGLE_TLV("Digital Playback Boost Volume", - WM8904_AUDIO_INTERFACE_0, 9, 3, 0, dac_boost_tlv), -SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8904_DAC_DIGITAL_VOLUME_LEFT, - WM8904_DAC_DIGITAL_VOLUME_RIGHT, 1, 96, 0, digital_tlv), - -SOC_DOUBLE_R_TLV("Headphone Volume", WM8904_ANALOGUE_OUT1_LEFT, - WM8904_ANALOGUE_OUT1_RIGHT, 0, 63, 0, out_tlv), -SOC_DOUBLE_R("Headphone Switch", WM8904_ANALOGUE_OUT1_LEFT, - WM8904_ANALOGUE_OUT1_RIGHT, 8, 1, 1), -SOC_DOUBLE_R("Headphone ZC Switch", WM8904_ANALOGUE_OUT1_LEFT, - WM8904_ANALOGUE_OUT1_RIGHT, 6, 1, 0), - -SOC_DOUBLE_R_TLV("Line Output Volume", WM8904_ANALOGUE_OUT2_LEFT, - WM8904_ANALOGUE_OUT2_RIGHT, 0, 63, 0, out_tlv), -SOC_DOUBLE_R("Line Output Switch", WM8904_ANALOGUE_OUT2_LEFT, - WM8904_ANALOGUE_OUT2_RIGHT, 8, 1, 1), -SOC_DOUBLE_R("Line Output ZC Switch", WM8904_ANALOGUE_OUT2_LEFT, - WM8904_ANALOGUE_OUT2_RIGHT, 6, 1, 0), - -SOC_SINGLE("EQ Switch", WM8904_EQ1, 0, 1, 0), -SOC_SINGLE("DRC Switch", WM8904_DRC_0, 15, 1, 0), -SOC_ENUM("DRC Path", drc_path), -SOC_SINGLE("DAC OSRx2 Switch", WM8904_DAC_DIGITAL_1, 6, 1, 0), -SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, - wm8904_get_deemph, wm8904_put_deemph), -}; - -static const struct snd_kcontrol_new wm8904_snd_controls[] = { -SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8904_DAC_DIGITAL_0, 4, 8, 15, 0, - sidetone_tlv), -}; - -static const struct snd_kcontrol_new wm8904_eq_controls[] = { -SOC_SINGLE_TLV("EQ1 Volume", WM8904_EQ2, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Volume", WM8904_EQ3, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Volume", WM8904_EQ4, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Volume", WM8904_EQ5, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ5 Volume", WM8904_EQ6, 0, 24, 0, eq_tlv), -}; - -static int cp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - BUG_ON(event != SND_SOC_DAPM_POST_PMU); - - /* Maximum startup time */ - udelay(500); - - return 0; -} - -static int sysclk_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - /* If we're using the FLL then we only start it when - * required; we assume that the configuration has been - * done previously and all we need to do is kick it - * off. - */ - switch (wm8904->sysclk_src) { - case WM8904_CLK_FLL: - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_OSC_ENA, - WM8904_FLL_OSC_ENA); - - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_ENA, - WM8904_FLL_ENA); - break; - - default: - break; - } - break; - - case SND_SOC_DAPM_POST_PMD: - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0); - break; - } - - return 0; -} - -static int out_pga_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int reg, val; - int dcs_mask; - int dcs_l, dcs_r; - int dcs_l_reg, dcs_r_reg; - int timeout; - int pwr_reg; - - /* This code is shared between HP and LINEOUT; we do all our - * power management in stereo pairs to avoid latency issues so - * we reuse shift to identify which rather than strcmp() the - * name. */ - reg = w->shift; - - switch (reg) { - case WM8904_ANALOGUE_HP_0: - pwr_reg = WM8904_POWER_MANAGEMENT_2; - dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1; - dcs_r_reg = WM8904_DC_SERVO_8; - dcs_l_reg = WM8904_DC_SERVO_9; - dcs_l = 0; - dcs_r = 1; - break; - case WM8904_ANALOGUE_LINEOUT_0: - pwr_reg = WM8904_POWER_MANAGEMENT_3; - dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3; - dcs_r_reg = WM8904_DC_SERVO_6; - dcs_l_reg = WM8904_DC_SERVO_7; - dcs_l = 2; - dcs_r = 3; - break; - default: - BUG(); - return -EINVAL; - } - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - /* Power on the PGAs */ - snd_soc_update_bits(codec, pwr_reg, - WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA, - WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA); - - /* Power on the amplifier */ - snd_soc_update_bits(codec, reg, - WM8904_HPL_ENA | WM8904_HPR_ENA, - WM8904_HPL_ENA | WM8904_HPR_ENA); - - - /* Enable the first stage */ - snd_soc_update_bits(codec, reg, - WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY, - WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY); - - /* Power up the DC servo */ - snd_soc_update_bits(codec, WM8904_DC_SERVO_0, - dcs_mask, dcs_mask); - - /* Either calibrate the DC servo or restore cached state - * if we have that. - */ - if (wm8904->dcs_state[dcs_l] || wm8904->dcs_state[dcs_r]) { - dev_dbg(codec->dev, "Restoring DC servo state\n"); - - snd_soc_write(codec, dcs_l_reg, - wm8904->dcs_state[dcs_l]); - snd_soc_write(codec, dcs_r_reg, - wm8904->dcs_state[dcs_r]); - - snd_soc_write(codec, WM8904_DC_SERVO_1, dcs_mask); - - timeout = 20; - } else { - dev_dbg(codec->dev, "Calibrating DC servo\n"); - - snd_soc_write(codec, WM8904_DC_SERVO_1, - dcs_mask << WM8904_DCS_TRIG_STARTUP_0_SHIFT); - - timeout = 500; - } - - /* Wait for DC servo to complete */ - dcs_mask <<= WM8904_DCS_CAL_COMPLETE_SHIFT; - do { - val = snd_soc_read(codec, WM8904_DC_SERVO_READBACK_0); - if ((val & dcs_mask) == dcs_mask) - break; - - msleep(1); - } while (--timeout); - - if ((val & dcs_mask) != dcs_mask) - dev_warn(codec->dev, "DC servo timed out\n"); - else - dev_dbg(codec->dev, "DC servo ready\n"); - - /* Enable the output stage */ - snd_soc_update_bits(codec, reg, - WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP, - WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP); - break; - - case SND_SOC_DAPM_POST_PMU: - /* Unshort the output itself */ - snd_soc_update_bits(codec, reg, - WM8904_HPL_RMV_SHORT | - WM8904_HPR_RMV_SHORT, - WM8904_HPL_RMV_SHORT | - WM8904_HPR_RMV_SHORT); - - break; - - case SND_SOC_DAPM_PRE_PMD: - /* Short the output */ - snd_soc_update_bits(codec, reg, - WM8904_HPL_RMV_SHORT | - WM8904_HPR_RMV_SHORT, 0); - break; - - case SND_SOC_DAPM_POST_PMD: - /* Cache the DC servo configuration; this will be - * invalidated if we change the configuration. */ - wm8904->dcs_state[dcs_l] = snd_soc_read(codec, dcs_l_reg); - wm8904->dcs_state[dcs_r] = snd_soc_read(codec, dcs_r_reg); - - snd_soc_update_bits(codec, WM8904_DC_SERVO_0, - dcs_mask, 0); - - /* Disable the amplifier input and output stages */ - snd_soc_update_bits(codec, reg, - WM8904_HPL_ENA | WM8904_HPR_ENA | - WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY | - WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP, - 0); - - /* PGAs too */ - snd_soc_update_bits(codec, pwr_reg, - WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA, - 0); - break; - } - - return 0; -} - -static const char *lin_text[] = { - "IN1L", "IN2L", "IN3L" -}; - -static const struct soc_enum lin_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 2, 3, lin_text); - -static const struct snd_kcontrol_new lin_mux = - SOC_DAPM_ENUM("Left Capture Mux", lin_enum); - -static const struct soc_enum lin_inv_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_LEFT_INPUT_1, 4, 3, lin_text); - -static const struct snd_kcontrol_new lin_inv_mux = - SOC_DAPM_ENUM("Left Capture Inveting Mux", lin_inv_enum); - -static const char *rin_text[] = { - "IN1R", "IN2R", "IN3R" -}; - -static const struct soc_enum rin_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 2, 3, rin_text); - -static const struct snd_kcontrol_new rin_mux = - SOC_DAPM_ENUM("Right Capture Mux", rin_enum); - -static const struct soc_enum rin_inv_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_RIGHT_INPUT_1, 4, 3, rin_text); - -static const struct snd_kcontrol_new rin_inv_mux = - SOC_DAPM_ENUM("Right Capture Inveting Mux", rin_inv_enum); - -static const char *aif_text[] = { - "Left", "Right" -}; - -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 7, 2, aif_text); - -static const struct snd_kcontrol_new aifoutl_mux = - SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); - -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 6, 2, aif_text); - -static const struct snd_kcontrol_new aifoutr_mux = - SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); - -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 5, 2, aif_text); - -static const struct snd_kcontrol_new aifinl_mux = - SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); - -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8904_AUDIO_INTERFACE_0, 4, 2, aif_text); - -static const struct snd_kcontrol_new aifinr_mux = - SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); - -static const struct snd_soc_dapm_widget wm8904_core_dapm_widgets[] = { -SND_SOC_DAPM_SUPPLY("SYSCLK", WM8904_CLOCK_RATES_2, 2, 0, sysclk_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8904_CLOCK_RATES_2, 1, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("TOCLK", WM8904_CLOCK_RATES_2, 0, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_widget wm8904_adc_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1L"), -SND_SOC_DAPM_INPUT("IN1R"), -SND_SOC_DAPM_INPUT("IN2L"), -SND_SOC_DAPM_INPUT("IN2R"), -SND_SOC_DAPM_INPUT("IN3L"), -SND_SOC_DAPM_INPUT("IN3R"), - -SND_SOC_DAPM_SUPPLY("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0), - -SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lin_mux), -SND_SOC_DAPM_MUX("Left Capture Inverting Mux", SND_SOC_NOPM, 0, 0, - &lin_inv_mux), -SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rin_mux), -SND_SOC_DAPM_MUX("Right Capture Inverting Mux", SND_SOC_NOPM, 0, 0, - &rin_inv_mux), - -SND_SOC_DAPM_PGA("Left Capture PGA", WM8904_POWER_MANAGEMENT_0, 1, 0, - NULL, 0), -SND_SOC_DAPM_PGA("Right Capture PGA", WM8904_POWER_MANAGEMENT_0, 0, 0, - NULL, 0), - -SND_SOC_DAPM_ADC("ADCL", NULL, WM8904_POWER_MANAGEMENT_6, 1, 0), -SND_SOC_DAPM_ADC("ADCR", NULL, WM8904_POWER_MANAGEMENT_6, 0, 0), - -SND_SOC_DAPM_MUX("AIFOUTL Mux", SND_SOC_NOPM, 0, 0, &aifoutl_mux), -SND_SOC_DAPM_MUX("AIFOUTR Mux", SND_SOC_NOPM, 0, 0, &aifoutr_mux), - -SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0), -}; - -static const struct snd_soc_dapm_widget wm8904_dac_dapm_widgets[] = { -SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &aifinl_mux), -SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &aifinr_mux), - -SND_SOC_DAPM_DAC("DACL", NULL, WM8904_POWER_MANAGEMENT_6, 3, 0), -SND_SOC_DAPM_DAC("DACR", NULL, WM8904_POWER_MANAGEMENT_6, 2, 0), - -SND_SOC_DAPM_SUPPLY("Charge pump", WM8904_CHARGE_PUMP_0, 0, 0, cp_event, - SND_SOC_DAPM_POST_PMU), - -SND_SOC_DAPM_PGA("HPL PGA", SND_SOC_NOPM, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA("HPR PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_PGA("LINEL PGA", SND_SOC_NOPM, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA("LINER PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM, WM8904_ANALOGUE_HP_0, - 0, NULL, 0, out_pga_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_PGA_E("Line Output", SND_SOC_NOPM, WM8904_ANALOGUE_LINEOUT_0, - 0, NULL, 0, out_pga_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_OUTPUT("HPOUTL"), -SND_SOC_DAPM_OUTPUT("HPOUTR"), -SND_SOC_DAPM_OUTPUT("LINEOUTL"), -SND_SOC_DAPM_OUTPUT("LINEOUTR"), -}; - -static const char *out_mux_text[] = { - "DAC", "Bypass" -}; - -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 3, 2, out_mux_text); - -static const struct snd_kcontrol_new hpl_mux = - SOC_DAPM_ENUM("HPL Mux", hpl_enum); - -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 2, 2, out_mux_text); - -static const struct snd_kcontrol_new hpr_mux = - SOC_DAPM_ENUM("HPR Mux", hpr_enum); - -static const struct soc_enum linel_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 1, 2, out_mux_text); - -static const struct snd_kcontrol_new linel_mux = - SOC_DAPM_ENUM("LINEL Mux", linel_enum); - -static const struct soc_enum liner_enum = - SOC_ENUM_SINGLE(WM8904_ANALOGUE_OUT12_ZC, 0, 2, out_mux_text); - -static const struct snd_kcontrol_new liner_mux = - SOC_DAPM_ENUM("LINEL Mux", liner_enum); - -static const char *sidetone_text[] = { - "None", "Left", "Right" -}; - -static const struct soc_enum dacl_sidetone_enum = - SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 2, 3, sidetone_text); - -static const struct snd_kcontrol_new dacl_sidetone_mux = - SOC_DAPM_ENUM("Left Sidetone Mux", dacl_sidetone_enum); - -static const struct soc_enum dacr_sidetone_enum = - SOC_ENUM_SINGLE(WM8904_DAC_DIGITAL_0, 0, 3, sidetone_text); - -static const struct snd_kcontrol_new dacr_sidetone_mux = - SOC_DAPM_ENUM("Right Sidetone Mux", dacr_sidetone_enum); - -static const struct snd_soc_dapm_widget wm8904_dapm_widgets[] = { -SND_SOC_DAPM_SUPPLY("Class G", WM8904_CLASS_W_0, 0, 1, NULL, 0), -SND_SOC_DAPM_PGA("Left Bypass", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Bypass", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &dacl_sidetone_mux), -SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &dacr_sidetone_mux), - -SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), -SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), -SND_SOC_DAPM_MUX("LINEL Mux", SND_SOC_NOPM, 0, 0, &linel_mux), -SND_SOC_DAPM_MUX("LINER Mux", SND_SOC_NOPM, 0, 0, &liner_mux), -}; - -static const struct snd_soc_dapm_route core_intercon[] = { - { "CLK_DSP", NULL, "SYSCLK" }, - { "TOCLK", NULL, "SYSCLK" }, -}; - -static const struct snd_soc_dapm_route adc_intercon[] = { - { "Left Capture Mux", "IN1L", "IN1L" }, - { "Left Capture Mux", "IN2L", "IN2L" }, - { "Left Capture Mux", "IN3L", "IN3L" }, - - { "Left Capture Inverting Mux", "IN1L", "IN1L" }, - { "Left Capture Inverting Mux", "IN2L", "IN2L" }, - { "Left Capture Inverting Mux", "IN3L", "IN3L" }, - - { "Right Capture Mux", "IN1R", "IN1R" }, - { "Right Capture Mux", "IN2R", "IN2R" }, - { "Right Capture Mux", "IN3R", "IN3R" }, - - { "Right Capture Inverting Mux", "IN1R", "IN1R" }, - { "Right Capture Inverting Mux", "IN2R", "IN2R" }, - { "Right Capture Inverting Mux", "IN3R", "IN3R" }, - - { "Left Capture PGA", NULL, "Left Capture Mux" }, - { "Left Capture PGA", NULL, "Left Capture Inverting Mux" }, - - { "Right Capture PGA", NULL, "Right Capture Mux" }, - { "Right Capture PGA", NULL, "Right Capture Inverting Mux" }, - - { "AIFOUTL", "Left", "ADCL" }, - { "AIFOUTL", "Right", "ADCR" }, - { "AIFOUTR", "Left", "ADCL" }, - { "AIFOUTR", "Right", "ADCR" }, - - { "ADCL", NULL, "CLK_DSP" }, - { "ADCL", NULL, "Left Capture PGA" }, - - { "ADCR", NULL, "CLK_DSP" }, - { "ADCR", NULL, "Right Capture PGA" }, -}; - -static const struct snd_soc_dapm_route dac_intercon[] = { - { "DACL", "Right", "AIFINR" }, - { "DACL", "Left", "AIFINL" }, - { "DACL", NULL, "CLK_DSP" }, - - { "DACR", "Right", "AIFINR" }, - { "DACR", "Left", "AIFINL" }, - { "DACR", NULL, "CLK_DSP" }, - - { "Charge pump", NULL, "SYSCLK" }, - - { "Headphone Output", NULL, "HPL PGA" }, - { "Headphone Output", NULL, "HPR PGA" }, - { "Headphone Output", NULL, "Charge pump" }, - { "Headphone Output", NULL, "TOCLK" }, - - { "Line Output", NULL, "LINEL PGA" }, - { "Line Output", NULL, "LINER PGA" }, - { "Line Output", NULL, "Charge pump" }, - { "Line Output", NULL, "TOCLK" }, - - { "HPOUTL", NULL, "Headphone Output" }, - { "HPOUTR", NULL, "Headphone Output" }, - - { "LINEOUTL", NULL, "Line Output" }, - { "LINEOUTR", NULL, "Line Output" }, -}; - -static const struct snd_soc_dapm_route wm8904_intercon[] = { - { "Left Sidetone", "Left", "ADCL" }, - { "Left Sidetone", "Right", "ADCR" }, - { "DACL", NULL, "Left Sidetone" }, - - { "Right Sidetone", "Left", "ADCL" }, - { "Right Sidetone", "Right", "ADCR" }, - { "DACR", NULL, "Right Sidetone" }, - - { "Left Bypass", NULL, "Class G" }, - { "Left Bypass", NULL, "Left Capture PGA" }, - - { "Right Bypass", NULL, "Class G" }, - { "Right Bypass", NULL, "Right Capture PGA" }, - - { "HPL Mux", "DAC", "DACL" }, - { "HPL Mux", "Bypass", "Left Bypass" }, - - { "HPR Mux", "DAC", "DACR" }, - { "HPR Mux", "Bypass", "Right Bypass" }, - - { "LINEL Mux", "DAC", "DACL" }, - { "LINEL Mux", "Bypass", "Left Bypass" }, - - { "LINER Mux", "DAC", "DACR" }, - { "LINER Mux", "Bypass", "Right Bypass" }, - - { "HPL PGA", NULL, "HPL Mux" }, - { "HPR PGA", NULL, "HPR Mux" }, - - { "LINEL PGA", NULL, "LINEL Mux" }, - { "LINER PGA", NULL, "LINER Mux" }, -}; - -static const struct snd_soc_dapm_route wm8912_intercon[] = { - { "HPL PGA", NULL, "DACL" }, - { "HPR PGA", NULL, "DACR" }, - - { "LINEL PGA", NULL, "DACL" }, - { "LINER PGA", NULL, "DACR" }, -}; - -static int wm8904_add_widgets(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, wm8904_core_dapm_widgets, - ARRAY_SIZE(wm8904_core_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, core_intercon, - ARRAY_SIZE(core_intercon)); - - switch (wm8904->devtype) { - case WM8904: - snd_soc_add_codec_controls(codec, wm8904_adc_snd_controls, - ARRAY_SIZE(wm8904_adc_snd_controls)); - snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls, - ARRAY_SIZE(wm8904_dac_snd_controls)); - snd_soc_add_codec_controls(codec, wm8904_snd_controls, - ARRAY_SIZE(wm8904_snd_controls)); - - snd_soc_dapm_new_controls(dapm, wm8904_adc_dapm_widgets, - ARRAY_SIZE(wm8904_adc_dapm_widgets)); - snd_soc_dapm_new_controls(dapm, wm8904_dac_dapm_widgets, - ARRAY_SIZE(wm8904_dac_dapm_widgets)); - snd_soc_dapm_new_controls(dapm, wm8904_dapm_widgets, - ARRAY_SIZE(wm8904_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, core_intercon, - ARRAY_SIZE(core_intercon)); - snd_soc_dapm_add_routes(dapm, adc_intercon, - ARRAY_SIZE(adc_intercon)); - snd_soc_dapm_add_routes(dapm, dac_intercon, - ARRAY_SIZE(dac_intercon)); - snd_soc_dapm_add_routes(dapm, wm8904_intercon, - ARRAY_SIZE(wm8904_intercon)); - break; - - case WM8912: - snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls, - ARRAY_SIZE(wm8904_dac_snd_controls)); - - snd_soc_dapm_new_controls(dapm, wm8904_dac_dapm_widgets, - ARRAY_SIZE(wm8904_dac_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, dac_intercon, - ARRAY_SIZE(dac_intercon)); - snd_soc_dapm_add_routes(dapm, wm8912_intercon, - ARRAY_SIZE(wm8912_intercon)); - break; - } - - snd_soc_dapm_new_widgets(dapm); - return 0; -} - -static struct { - int ratio; - unsigned int clk_sys_rate; -} clk_sys_rates[] = { - { 64, 0 }, - { 128, 1 }, - { 192, 2 }, - { 256, 3 }, - { 384, 4 }, - { 512, 5 }, - { 786, 6 }, - { 1024, 7 }, - { 1408, 8 }, - { 1536, 9 }, -}; - -static struct { - int rate; - int sample_rate; -} sample_rates[] = { - { 8000, 0 }, - { 11025, 1 }, - { 12000, 1 }, - { 16000, 2 }, - { 22050, 3 }, - { 24000, 3 }, - { 32000, 4 }, - { 44100, 5 }, - { 48000, 5 }, -}; - -static struct { - int div; /* *10 due to .5s */ - int bclk_div; -} bclk_divs[] = { - { 10, 0 }, - { 15, 1 }, - { 20, 2 }, - { 30, 3 }, - { 40, 4 }, - { 50, 5 }, - { 55, 6 }, - { 60, 7 }, - { 80, 8 }, - { 100, 9 }, - { 110, 10 }, - { 120, 11 }, - { 160, 12 }, - { 200, 13 }, - { 220, 14 }, - { 240, 16 }, - { 200, 17 }, - { 320, 18 }, - { 440, 19 }, - { 480, 20 }, -}; - - -static int wm8904_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int ret, i, best, best_val, cur_val; - unsigned int aif1 = 0; - unsigned int aif2 = 0; - unsigned int aif3 = 0; - unsigned int clock1 = 0; - unsigned int dac_digital1 = 0; - - /* What BCLK do we need? */ - wm8904->fs = params_rate(params); - if (wm8904->tdm_slots) { - dev_dbg(codec->dev, "Configuring for %d %d bit TDM slots\n", - wm8904->tdm_slots, wm8904->tdm_width); - wm8904->bclk = snd_soc_calc_bclk(wm8904->fs, - wm8904->tdm_width, 2, - wm8904->tdm_slots); - } else { - wm8904->bclk = snd_soc_params_to_bclk(params); - } - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - aif1 |= 0x40; - break; - case SNDRV_PCM_FORMAT_S24_LE: - aif1 |= 0x80; - break; - case SNDRV_PCM_FORMAT_S32_LE: - aif1 |= 0xc0; - break; - default: - return -EINVAL; - } - - - dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8904->bclk); - - ret = wm8904_configure_clocking(codec); - if (ret != 0) - return ret; - - /* Select nearest CLK_SYS_RATE */ - best = 0; - best_val = abs((wm8904->sysclk_rate / clk_sys_rates[0].ratio) - - wm8904->fs); - for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) { - cur_val = abs((wm8904->sysclk_rate / - clk_sys_rates[i].ratio) - wm8904->fs); - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n", - clk_sys_rates[best].ratio); - clock1 |= (clk_sys_rates[best].clk_sys_rate - << WM8904_CLK_SYS_RATE_SHIFT); - - /* SAMPLE_RATE */ - best = 0; - best_val = abs(wm8904->fs - sample_rates[0].rate); - for (i = 1; i < ARRAY_SIZE(sample_rates); i++) { - /* Closest match */ - cur_val = abs(wm8904->fs - sample_rates[i].rate); - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n", - sample_rates[best].rate); - clock1 |= (sample_rates[best].sample_rate - << WM8904_SAMPLE_RATE_SHIFT); - - /* Enable sloping stopband filter for low sample rates */ - if (wm8904->fs <= 24000) - dac_digital1 |= WM8904_DAC_SB_FILT; - - /* BCLK_DIV */ - best = 0; - best_val = INT_MAX; - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - cur_val = ((wm8904->sysclk_rate * 10) / bclk_divs[i].div) - - wm8904->bclk; - if (cur_val < 0) /* Table is sorted */ - break; - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - wm8904->bclk = (wm8904->sysclk_rate * 10) / bclk_divs[best].div; - dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n", - bclk_divs[best].div, wm8904->bclk); - aif2 |= bclk_divs[best].bclk_div; - - /* LRCLK is a simple fraction of BCLK */ - dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8904->bclk / wm8904->fs); - aif3 |= wm8904->bclk / wm8904->fs; - - /* Apply the settings */ - snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_1, - WM8904_DAC_SB_FILT, dac_digital1); - snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_1, - WM8904_AIF_WL_MASK, aif1); - snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_2, - WM8904_BCLK_DIV_MASK, aif2); - snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_3, - WM8904_LRCLK_RATE_MASK, aif3); - snd_soc_update_bits(codec, WM8904_CLOCK_RATES_1, - WM8904_SAMPLE_RATE_MASK | - WM8904_CLK_SYS_RATE_MASK, clock1); - - /* Update filters for the new settings */ - wm8904_set_retune_mobile(codec); - wm8904_set_deemph(codec); - - return 0; -} - - -static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8904_priv *priv = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case WM8904_CLK_MCLK: - priv->sysclk_src = clk_id; - priv->mclk_rate = freq; - break; - - case WM8904_CLK_FLL: - priv->sysclk_src = clk_id; - break; - - default: - return -EINVAL; - } - - dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); - - wm8904_configure_clocking(codec); - - return 0; -} - -static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - unsigned int aif1 = 0; - unsigned int aif3 = 0; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBS_CFM: - aif3 |= WM8904_LRCLK_DIR; - break; - case SND_SOC_DAIFMT_CBM_CFS: - aif1 |= WM8904_BCLK_DIR; - break; - case SND_SOC_DAIFMT_CBM_CFM: - aif1 |= WM8904_BCLK_DIR; - aif3 |= WM8904_LRCLK_DIR; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif1 |= WM8904_AIF_LRCLK_INV; - case SND_SOC_DAIFMT_DSP_A: - aif1 |= 0x3; - break; - case SND_SOC_DAIFMT_I2S: - aif1 |= 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif1 |= 0x1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8904_AIF_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif1 |= WM8904_AIF_BCLK_INV | WM8904_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8904_AIF_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif1 |= WM8904_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_1, - WM8904_AIF_BCLK_INV | WM8904_AIF_LRCLK_INV | - WM8904_AIF_FMT_MASK | WM8904_BCLK_DIR, aif1); - snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_3, - WM8904_LRCLK_DIR, aif3); - - return 0; -} - - -static int wm8904_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, - unsigned int rx_mask, int slots, int slot_width) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int aif1 = 0; - - /* Don't need to validate anything if we're turning off TDM */ - if (slots == 0) - goto out; - - /* Note that we allow configurations we can't handle ourselves - - * for example, we can generate clocks for slots 2 and up even if - * we can't use those slots ourselves. - */ - aif1 |= WM8904_AIFADC_TDM | WM8904_AIFDAC_TDM; - - switch (rx_mask) { - case 3: - break; - case 0xc: - aif1 |= WM8904_AIFADC_TDM_CHAN; - break; - default: - return -EINVAL; - } - - - switch (tx_mask) { - case 3: - break; - case 0xc: - aif1 |= WM8904_AIFDAC_TDM_CHAN; - break; - default: - return -EINVAL; - } - -out: - wm8904->tdm_width = slot_width; - wm8904->tdm_slots = slots / 2; - - snd_soc_update_bits(codec, WM8904_AUDIO_INTERFACE_1, - WM8904_AIFADC_TDM | WM8904_AIFADC_TDM_CHAN | - WM8904_AIFDAC_TDM | WM8904_AIFDAC_TDM_CHAN, aif1); - - return 0; -} - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_clk_ref_div; - u16 n; - u16 k; -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod, target; - unsigned int div; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - fll_div->fll_clk_ref_div = 0; - while ((Fref / div) > 13500000) { - div *= 2; - fll_div->fll_clk_ref_div++; - - if (div > 8) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - - pr_debug("Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 4; - while (Fout * div < 90000000) { - div++; - if (div > 64) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - target = Fout * div; - fll_div->fll_outdiv = div - 1; - - pr_debug("Fvco=%dHz\n", target); - - /* Find an appropriate FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - target /= fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - /* Now, calculate N.K */ - Ndiv = target / Fref; - - fll_div->n = Ndiv; - Nmod = target % Fref; - pr_debug("Nmod=%d\n", Nmod); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, Fref); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - fll_div->k = K / 10; - - pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n", - fll_div->n, fll_div->k, - fll_div->fll_fratio, fll_div->fll_outdiv, - fll_div->fll_clk_ref_div); - - return 0; -} - -static int wm8904_set_fll(struct snd_soc_dai *dai, int fll_id, int source, - unsigned int Fref, unsigned int Fout) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct _fll_div fll_div; - int ret, val; - int clock2, fll1; - - /* Any change? */ - if (source == wm8904->fll_src && Fref == wm8904->fll_fref && - Fout == wm8904->fll_fout) - return 0; - - clock2 = snd_soc_read(codec, WM8904_CLOCK_RATES_2); - - if (Fout == 0) { - dev_dbg(codec->dev, "FLL disabled\n"); - - wm8904->fll_fref = 0; - wm8904->fll_fout = 0; - - /* Gate SYSCLK to avoid glitches */ - snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, - WM8904_CLK_SYS_ENA, 0); - - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0); - - goto out; - } - - /* Validate the FLL ID */ - switch (source) { - case WM8904_FLL_MCLK: - case WM8904_FLL_LRCLK: - case WM8904_FLL_BCLK: - ret = fll_factors(&fll_div, Fref, Fout); - if (ret != 0) - return ret; - break; - - case WM8904_FLL_FREE_RUNNING: - dev_dbg(codec->dev, "Using free running FLL\n"); - /* Force 12MHz and output/4 for now */ - Fout = 12000000; - Fref = 12000000; - - memset(&fll_div, 0, sizeof(fll_div)); - fll_div.fll_outdiv = 3; - break; - - default: - dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); - return -EINVAL; - } - - /* Save current state then disable the FLL and SYSCLK to avoid - * misclocking */ - fll1 = snd_soc_read(codec, WM8904_FLL_CONTROL_1); - snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, - WM8904_CLK_SYS_ENA, 0); - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0); - - /* Unlock forced oscilator control to switch it on/off */ - snd_soc_update_bits(codec, WM8904_CONTROL_INTERFACE_TEST_1, - WM8904_USER_KEY, WM8904_USER_KEY); - - if (fll_id == WM8904_FLL_FREE_RUNNING) { - val = WM8904_FLL_FRC_NCO; - } else { - val = 0; - } - - snd_soc_update_bits(codec, WM8904_FLL_NCO_TEST_1, WM8904_FLL_FRC_NCO, - val); - snd_soc_update_bits(codec, WM8904_CONTROL_INTERFACE_TEST_1, - WM8904_USER_KEY, 0); - - switch (fll_id) { - case WM8904_FLL_MCLK: - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_5, - WM8904_FLL_CLK_REF_SRC_MASK, 0); - break; - - case WM8904_FLL_LRCLK: - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_5, - WM8904_FLL_CLK_REF_SRC_MASK, 1); - break; - - case WM8904_FLL_BCLK: - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_5, - WM8904_FLL_CLK_REF_SRC_MASK, 2); - break; - } - - if (fll_div.k) - val = WM8904_FLL_FRACN_ENA; - else - val = 0; - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_FRACN_ENA, val); - - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_2, - WM8904_FLL_OUTDIV_MASK | WM8904_FLL_FRATIO_MASK, - (fll_div.fll_outdiv << WM8904_FLL_OUTDIV_SHIFT) | - (fll_div.fll_fratio << WM8904_FLL_FRATIO_SHIFT)); - - snd_soc_write(codec, WM8904_FLL_CONTROL_3, fll_div.k); - - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_4, WM8904_FLL_N_MASK, - fll_div.n << WM8904_FLL_N_SHIFT); - - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_5, - WM8904_FLL_CLK_REF_DIV_MASK, - fll_div.fll_clk_ref_div - << WM8904_FLL_CLK_REF_DIV_SHIFT); - - dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); - - wm8904->fll_fref = Fref; - wm8904->fll_fout = Fout; - wm8904->fll_src = source; - - /* Enable the FLL if it was previously active */ - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_OSC_ENA, fll1); - snd_soc_update_bits(codec, WM8904_FLL_CONTROL_1, - WM8904_FLL_ENA, fll1); - -out: - /* Reenable SYSCLK if it was previously active */ - snd_soc_update_bits(codec, WM8904_CLOCK_RATES_2, - WM8904_CLK_SYS_ENA, clock2); - - return 0; -} - -static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int val; - - if (mute) - val = WM8904_DAC_MUTE; - else - val = 0; - - snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_1, WM8904_DAC_MUTE, val); - - return 0; -} - -static int wm8904_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID resistance 2*50k */ - snd_soc_update_bits(codec, WM8904_VMID_CONTROL_0, - WM8904_VMID_RES_MASK, - 0x1 << WM8904_VMID_RES_SHIFT); - - /* Normal bias current */ - snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, - WM8904_ISEL_MASK, 2 << WM8904_ISEL_SHIFT); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), - wm8904->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - - regcache_sync(wm8904->regmap); - - /* Enable bias */ - snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, - WM8904_BIAS_ENA, WM8904_BIAS_ENA); - - /* Enable VMID, VMID buffering, 2*5k resistance */ - snd_soc_update_bits(codec, WM8904_VMID_CONTROL_0, - WM8904_VMID_ENA | - WM8904_VMID_RES_MASK, - WM8904_VMID_ENA | - 0x3 << WM8904_VMID_RES_SHIFT); - - /* Let VMID ramp */ - msleep(1); - } - - /* Maintain VMID with 2*250k */ - snd_soc_update_bits(codec, WM8904_VMID_CONTROL_0, - WM8904_VMID_RES_MASK, - 0x2 << WM8904_VMID_RES_SHIFT); - - /* Bias current *0.5 */ - snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, - WM8904_ISEL_MASK, 0); - break; - - case SND_SOC_BIAS_OFF: - /* Turn off VMID */ - snd_soc_update_bits(codec, WM8904_VMID_CONTROL_0, - WM8904_VMID_RES_MASK | WM8904_VMID_ENA, 0); - - /* Stop bias generation */ - snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, - WM8904_BIAS_ENA, 0); - -#ifdef CONFIG_REGULATOR - /* Post 2.6.34 we will be able to get a callback when - * the regulators are disabled which we can use but - * for now just assume that the power will be cut if - * the regulator API is in use. - */ - codec->cache_sync = 1; -#endif - - regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), - wm8904->supplies); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8904_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8904_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8904_dai_ops = { - .set_sysclk = wm8904_set_sysclk, - .set_fmt = wm8904_set_fmt, - .set_tdm_slot = wm8904_set_tdm_slot, - .set_pll = wm8904_set_fll, - .hw_params = wm8904_hw_params, - .digital_mute = wm8904_digital_mute, -}; - -static struct snd_soc_dai_driver wm8904_dai = { - .name = "wm8904-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8904_RATES, - .formats = WM8904_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM8904_RATES, - .formats = WM8904_FORMATS, - }, - .ops = &wm8904_dai_ops, - .symmetric_rates = 1, -}; - -#ifdef CONFIG_PM -static int wm8904_suspend(struct snd_soc_codec *codec) -{ - wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8904_resume(struct snd_soc_codec *codec) -{ - wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8904_suspend NULL -#define wm8904_resume NULL -#endif - -static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct wm8904_pdata *pdata = wm8904->pdata; - struct snd_kcontrol_new control = - SOC_ENUM_EXT("EQ Mode", - wm8904->retune_mobile_enum, - wm8904_get_retune_mobile_enum, - wm8904_put_retune_mobile_enum); - int ret, i, j; - const char **t; - - /* We need an array of texts for the enum API but the number - * of texts is likely to be less than the number of - * configurations due to the sample rate dependency of the - * configurations. */ - wm8904->num_retune_mobile_texts = 0; - wm8904->retune_mobile_texts = NULL; - for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { - for (j = 0; j < wm8904->num_retune_mobile_texts; j++) { - if (strcmp(pdata->retune_mobile_cfgs[i].name, - wm8904->retune_mobile_texts[j]) == 0) - break; - } - - if (j != wm8904->num_retune_mobile_texts) - continue; - - /* Expand the array... */ - t = krealloc(wm8904->retune_mobile_texts, - sizeof(char *) * - (wm8904->num_retune_mobile_texts + 1), - GFP_KERNEL); - if (t == NULL) - continue; - - /* ...store the new entry... */ - t[wm8904->num_retune_mobile_texts] = - pdata->retune_mobile_cfgs[i].name; - - /* ...and remember the new version. */ - wm8904->num_retune_mobile_texts++; - wm8904->retune_mobile_texts = t; - } - - dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", - wm8904->num_retune_mobile_texts); - - wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; - wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; - - ret = snd_soc_add_codec_controls(codec, &control, 1); - if (ret != 0) - dev_err(codec->dev, - "Failed to add ReTune Mobile control: %d\n", ret); -} - -static void wm8904_handle_pdata(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct wm8904_pdata *pdata = wm8904->pdata; - int ret, i; - - if (!pdata) { - snd_soc_add_codec_controls(codec, wm8904_eq_controls, - ARRAY_SIZE(wm8904_eq_controls)); - return; - } - - dev_dbg(codec->dev, "%d DRC configurations\n", pdata->num_drc_cfgs); - - if (pdata->num_drc_cfgs) { - struct snd_kcontrol_new control = - SOC_ENUM_EXT("DRC Mode", wm8904->drc_enum, - wm8904_get_drc_enum, wm8904_put_drc_enum); - - /* We need an array of texts for the enum API */ - wm8904->drc_texts = kmalloc(sizeof(char *) - * pdata->num_drc_cfgs, GFP_KERNEL); - if (!wm8904->drc_texts) { - dev_err(codec->dev, - "Failed to allocate %d DRC config texts\n", - pdata->num_drc_cfgs); - return; - } - - for (i = 0; i < pdata->num_drc_cfgs; i++) - wm8904->drc_texts[i] = pdata->drc_cfgs[i].name; - - wm8904->drc_enum.max = pdata->num_drc_cfgs; - wm8904->drc_enum.texts = wm8904->drc_texts; - - ret = snd_soc_add_codec_controls(codec, &control, 1); - if (ret != 0) - dev_err(codec->dev, - "Failed to add DRC mode control: %d\n", ret); - - wm8904_set_drc(codec); - } - - dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", - pdata->num_retune_mobile_cfgs); - - if (pdata->num_retune_mobile_cfgs) - wm8904_handle_retune_mobile_pdata(codec); - else - snd_soc_add_codec_controls(codec, wm8904_eq_controls, - ARRAY_SIZE(wm8904_eq_controls)); -} - - -static int wm8904_probe(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - struct wm8904_pdata *pdata = wm8904->pdata; - int ret, i; - - codec->cache_sync = 1; - codec->control_data = wm8904->regmap; - - switch (wm8904->devtype) { - case WM8904: - break; - case WM8912: - memset(&wm8904_dai.capture, 0, sizeof(wm8904_dai.capture)); - break; - default: - dev_err(codec->dev, "Unknown device type %d\n", - wm8904->devtype); - return -EINVAL; - } - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) - wm8904->supplies[i].supply = wm8904_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8904->supplies), - wm8904->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), - wm8904->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = snd_soc_read(codec, WM8904_SW_RESET_AND_ID); - if (ret < 0) { - dev_err(codec->dev, "Failed to read ID register\n"); - goto err_enable; - } - if (ret != 0x8904) { - dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret); - ret = -EINVAL; - goto err_enable; - } - - ret = snd_soc_read(codec, WM8904_REVISION); - if (ret < 0) { - dev_err(codec->dev, "Failed to read device revision: %d\n", - ret); - goto err_enable; - } - dev_info(codec->dev, "revision %c\n", ret + 'A'); - - ret = wm8904_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - - /* Change some default settings - latch VU and enable ZC */ - snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT, - WM8904_ADC_VU, WM8904_ADC_VU); - snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT, - WM8904_ADC_VU, WM8904_ADC_VU); - snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT, - WM8904_DAC_VU, WM8904_DAC_VU); - snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT, - WM8904_DAC_VU, WM8904_DAC_VU); - snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT, - WM8904_HPOUT_VU | WM8904_HPOUTLZC, - WM8904_HPOUT_VU | WM8904_HPOUTLZC); - snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT, - WM8904_HPOUT_VU | WM8904_HPOUTRZC, - WM8904_HPOUT_VU | WM8904_HPOUTRZC); - snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT, - WM8904_LINEOUT_VU | WM8904_LINEOUTLZC, - WM8904_LINEOUT_VU | WM8904_LINEOUTLZC); - snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT, - WM8904_LINEOUT_VU | WM8904_LINEOUTRZC, - WM8904_LINEOUT_VU | WM8904_LINEOUTRZC); - snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0, - WM8904_SR_MODE, 0); - - /* Apply configuration from the platform data. */ - if (wm8904->pdata) { - for (i = 0; i < WM8904_GPIO_REGS; i++) { - if (!pdata->gpio_cfg[i]) - continue; - - regmap_update_bits(wm8904->regmap, - WM8904_GPIO_CONTROL_1 + i, - 0xffff, - pdata->gpio_cfg[i]); - } - - /* Zero is the default value for these anyway */ - for (i = 0; i < WM8904_MIC_REGS; i++) - regmap_update_bits(wm8904->regmap, - WM8904_MIC_BIAS_CONTROL_0 + i, - 0xffff, - pdata->mic_cfg[i]); - } - - /* Set Class W by default - this will be managed by the Class - * G widget at runtime where bypass paths are available. - */ - snd_soc_update_bits(codec, WM8904_CLASS_W_0, - WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR); - - /* Use normal bias source */ - snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, - WM8904_POBCTRL, 0); - - wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); - - wm8904_handle_pdata(codec); - - wm8904_add_widgets(codec); - - return 0; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); - return ret; -} - -static int wm8904_remove(struct snd_soc_codec *codec) -{ - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - - wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); - kfree(wm8904->retune_mobile_texts); - kfree(wm8904->drc_texts); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8904 = { - .probe = wm8904_probe, - .remove = wm8904_remove, - .suspend = wm8904_suspend, - .resume = wm8904_resume, - .set_bias_level = wm8904_set_bias_level, - .idle_bias_off = true, -}; - -static const struct regmap_config wm8904_regmap = { - .reg_bits = 8, - .val_bits = 16, - - .max_register = WM8904_MAX_REGISTER, - .volatile_reg = wm8904_volatile_register, - .readable_reg = wm8904_readable_register, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8904_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults), -}; - -static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8904_priv *wm8904; - int ret; - - wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv), - GFP_KERNEL); - if (wm8904 == NULL) - return -ENOMEM; - - wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap); - if (IS_ERR(wm8904->regmap)) { - ret = PTR_ERR(wm8904->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - - wm8904->devtype = id->driver_data; - i2c_set_clientdata(i2c, wm8904); - wm8904->pdata = i2c->dev.platform_data; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8904, &wm8904_dai, 1); - if (ret != 0) - goto err; - - return 0; - -err: - regmap_exit(wm8904->regmap); - return ret; -} - -static __devexit int wm8904_i2c_remove(struct i2c_client *client) -{ - struct wm8904_priv *wm8904 = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8904->regmap); - return 0; -} - -static const struct i2c_device_id wm8904_i2c_id[] = { - { "wm8904", WM8904 }, - { "wm8912", WM8912 }, - { "wm8918", WM8904 }, /* Actually a subset, updates to follow */ - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); - -static struct i2c_driver wm8904_i2c_driver = { - .driver = { - .name = "wm8904", - .owner = THIS_MODULE, - }, - .probe = wm8904_i2c_probe, - .remove = __devexit_p(wm8904_i2c_remove), - .id_table = wm8904_i2c_id, -}; - -static int __init wm8904_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8904_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8904_modinit); - -static void __exit wm8904_exit(void) -{ - i2c_del_driver(&wm8904_i2c_driver); -} -module_exit(wm8904_exit); - -MODULE_DESCRIPTION("ASoC WM8904 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8904.h b/ANDROID_3.4.5/sound/soc/codecs/wm8904.h deleted file mode 100644 index c29a0e81..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8904.h +++ /dev/null @@ -1,1592 +0,0 @@ -/* - * wm8904.h -- WM8904 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics, plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8904_H -#define _WM8904_H - -#define WM8904_CLK_MCLK 1 -#define WM8904_CLK_FLL 2 - -#define WM8904_FLL_MCLK 1 -#define WM8904_FLL_BCLK 2 -#define WM8904_FLL_LRCLK 3 -#define WM8904_FLL_FREE_RUNNING 4 - -/* - * Register values. - */ -#define WM8904_SW_RESET_AND_ID 0x00 -#define WM8904_REVISION 0x01 -#define WM8904_BIAS_CONTROL_0 0x04 -#define WM8904_VMID_CONTROL_0 0x05 -#define WM8904_MIC_BIAS_CONTROL_0 0x06 -#define WM8904_MIC_BIAS_CONTROL_1 0x07 -#define WM8904_ANALOGUE_DAC_0 0x08 -#define WM8904_MIC_FILTER_CONTROL 0x09 -#define WM8904_ANALOGUE_ADC_0 0x0A -#define WM8904_POWER_MANAGEMENT_0 0x0C -#define WM8904_POWER_MANAGEMENT_2 0x0E -#define WM8904_POWER_MANAGEMENT_3 0x0F -#define WM8904_POWER_MANAGEMENT_6 0x12 -#define WM8904_CLOCK_RATES_0 0x14 -#define WM8904_CLOCK_RATES_1 0x15 -#define WM8904_CLOCK_RATES_2 0x16 -#define WM8904_AUDIO_INTERFACE_0 0x18 -#define WM8904_AUDIO_INTERFACE_1 0x19 -#define WM8904_AUDIO_INTERFACE_2 0x1A -#define WM8904_AUDIO_INTERFACE_3 0x1B -#define WM8904_DAC_DIGITAL_VOLUME_LEFT 0x1E -#define WM8904_DAC_DIGITAL_VOLUME_RIGHT 0x1F -#define WM8904_DAC_DIGITAL_0 0x20 -#define WM8904_DAC_DIGITAL_1 0x21 -#define WM8904_ADC_DIGITAL_VOLUME_LEFT 0x24 -#define WM8904_ADC_DIGITAL_VOLUME_RIGHT 0x25 -#define WM8904_ADC_DIGITAL_0 0x26 -#define WM8904_DIGITAL_MICROPHONE_0 0x27 -#define WM8904_DRC_0 0x28 -#define WM8904_DRC_1 0x29 -#define WM8904_DRC_2 0x2A -#define WM8904_DRC_3 0x2B -#define WM8904_ANALOGUE_LEFT_INPUT_0 0x2C -#define WM8904_ANALOGUE_RIGHT_INPUT_0 0x2D -#define WM8904_ANALOGUE_LEFT_INPUT_1 0x2E -#define WM8904_ANALOGUE_RIGHT_INPUT_1 0x2F -#define WM8904_ANALOGUE_OUT1_LEFT 0x39 -#define WM8904_ANALOGUE_OUT1_RIGHT 0x3A -#define WM8904_ANALOGUE_OUT2_LEFT 0x3B -#define WM8904_ANALOGUE_OUT2_RIGHT 0x3C -#define WM8904_ANALOGUE_OUT12_ZC 0x3D -#define WM8904_DC_SERVO_0 0x43 -#define WM8904_DC_SERVO_1 0x44 -#define WM8904_DC_SERVO_2 0x45 -#define WM8904_DC_SERVO_4 0x47 -#define WM8904_DC_SERVO_5 0x48 -#define WM8904_DC_SERVO_6 0x49 -#define WM8904_DC_SERVO_7 0x4A -#define WM8904_DC_SERVO_8 0x4B -#define WM8904_DC_SERVO_9 0x4C -#define WM8904_DC_SERVO_READBACK_0 0x4D -#define WM8904_ANALOGUE_HP_0 0x5A -#define WM8904_ANALOGUE_LINEOUT_0 0x5E -#define WM8904_CHARGE_PUMP_0 0x62 -#define WM8904_CLASS_W_0 0x68 -#define WM8904_WRITE_SEQUENCER_0 0x6C -#define WM8904_WRITE_SEQUENCER_1 0x6D -#define WM8904_WRITE_SEQUENCER_2 0x6E -#define WM8904_WRITE_SEQUENCER_3 0x6F -#define WM8904_WRITE_SEQUENCER_4 0x70 -#define WM8904_FLL_CONTROL_1 0x74 -#define WM8904_FLL_CONTROL_2 0x75 -#define WM8904_FLL_CONTROL_3 0x76 -#define WM8904_FLL_CONTROL_4 0x77 -#define WM8904_FLL_CONTROL_5 0x78 -#define WM8904_GPIO_CONTROL_1 0x79 -#define WM8904_GPIO_CONTROL_2 0x7A -#define WM8904_GPIO_CONTROL_3 0x7B -#define WM8904_GPIO_CONTROL_4 0x7C -#define WM8904_DIGITAL_PULLS 0x7E -#define WM8904_INTERRUPT_STATUS 0x7F -#define WM8904_INTERRUPT_STATUS_MASK 0x80 -#define WM8904_INTERRUPT_POLARITY 0x81 -#define WM8904_INTERRUPT_DEBOUNCE 0x82 -#define WM8904_EQ1 0x86 -#define WM8904_EQ2 0x87 -#define WM8904_EQ3 0x88 -#define WM8904_EQ4 0x89 -#define WM8904_EQ5 0x8A -#define WM8904_EQ6 0x8B -#define WM8904_EQ7 0x8C -#define WM8904_EQ8 0x8D -#define WM8904_EQ9 0x8E -#define WM8904_EQ10 0x8F -#define WM8904_EQ11 0x90 -#define WM8904_EQ12 0x91 -#define WM8904_EQ13 0x92 -#define WM8904_EQ14 0x93 -#define WM8904_EQ15 0x94 -#define WM8904_EQ16 0x95 -#define WM8904_EQ17 0x96 -#define WM8904_EQ18 0x97 -#define WM8904_EQ19 0x98 -#define WM8904_EQ20 0x99 -#define WM8904_EQ21 0x9A -#define WM8904_EQ22 0x9B -#define WM8904_EQ23 0x9C -#define WM8904_EQ24 0x9D -#define WM8904_CONTROL_INTERFACE_TEST_1 0xA1 -#define WM8904_ADC_TEST_0 0xC6 -#define WM8904_ANALOGUE_OUTPUT_BIAS_0 0xCC -#define WM8904_FLL_NCO_TEST_0 0xF7 -#define WM8904_FLL_NCO_TEST_1 0xF8 - -#define WM8904_REGISTER_COUNT 101 -#define WM8904_MAX_REGISTER 0xF8 - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - SW Reset and ID - */ -#define WM8904_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ -#define WM8904_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ -#define WM8904_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ - -/* - * R1 (0x01) - Revision - */ -#define WM8904_REVISION_MASK 0x000F /* REVISION - [3:0] */ -#define WM8904_REVISION_SHIFT 0 /* REVISION - [3:0] */ -#define WM8904_REVISION_WIDTH 16 /* REVISION - [3:0] */ - -/* - * R4 (0x04) - Bias Control 0 - */ -#define WM8904_POBCTRL 0x0010 /* POBCTRL */ -#define WM8904_POBCTRL_MASK 0x0010 /* POBCTRL */ -#define WM8904_POBCTRL_SHIFT 4 /* POBCTRL */ -#define WM8904_POBCTRL_WIDTH 1 /* POBCTRL */ -#define WM8904_ISEL_MASK 0x000C /* ISEL - [3:2] */ -#define WM8904_ISEL_SHIFT 2 /* ISEL - [3:2] */ -#define WM8904_ISEL_WIDTH 2 /* ISEL - [3:2] */ -#define WM8904_STARTUP_BIAS_ENA 0x0002 /* STARTUP_BIAS_ENA */ -#define WM8904_STARTUP_BIAS_ENA_MASK 0x0002 /* STARTUP_BIAS_ENA */ -#define WM8904_STARTUP_BIAS_ENA_SHIFT 1 /* STARTUP_BIAS_ENA */ -#define WM8904_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ -#define WM8904_BIAS_ENA 0x0001 /* BIAS_ENA */ -#define WM8904_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */ -#define WM8904_BIAS_ENA_SHIFT 0 /* BIAS_ENA */ -#define WM8904_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ - -/* - * R5 (0x05) - VMID Control 0 - */ -#define WM8904_VMID_BUF_ENA 0x0040 /* VMID_BUF_ENA */ -#define WM8904_VMID_BUF_ENA_MASK 0x0040 /* VMID_BUF_ENA */ -#define WM8904_VMID_BUF_ENA_SHIFT 6 /* VMID_BUF_ENA */ -#define WM8904_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ -#define WM8904_VMID_RES_MASK 0x0006 /* VMID_RES - [2:1] */ -#define WM8904_VMID_RES_SHIFT 1 /* VMID_RES - [2:1] */ -#define WM8904_VMID_RES_WIDTH 2 /* VMID_RES - [2:1] */ -#define WM8904_VMID_ENA 0x0001 /* VMID_ENA */ -#define WM8904_VMID_ENA_MASK 0x0001 /* VMID_ENA */ -#define WM8904_VMID_ENA_SHIFT 0 /* VMID_ENA */ -#define WM8904_VMID_ENA_WIDTH 1 /* VMID_ENA */ - -/* - * R8 (0x08) - Analogue DAC 0 - */ -#define WM8904_DAC_BIAS_SEL_MASK 0x0018 /* DAC_BIAS_SEL - [4:3] */ -#define WM8904_DAC_BIAS_SEL_SHIFT 3 /* DAC_BIAS_SEL - [4:3] */ -#define WM8904_DAC_BIAS_SEL_WIDTH 2 /* DAC_BIAS_SEL - [4:3] */ -#define WM8904_DAC_VMID_BIAS_SEL_MASK 0x0006 /* DAC_VMID_BIAS_SEL - [2:1] */ -#define WM8904_DAC_VMID_BIAS_SEL_SHIFT 1 /* DAC_VMID_BIAS_SEL - [2:1] */ -#define WM8904_DAC_VMID_BIAS_SEL_WIDTH 2 /* DAC_VMID_BIAS_SEL - [2:1] */ - -/* - * R9 (0x09) - mic Filter Control - */ -#define WM8904_MIC_DET_SET_THRESHOLD_MASK 0xF000 /* MIC_DET_SET_THRESHOLD - [15:12] */ -#define WM8904_MIC_DET_SET_THRESHOLD_SHIFT 12 /* MIC_DET_SET_THRESHOLD - [15:12] */ -#define WM8904_MIC_DET_SET_THRESHOLD_WIDTH 4 /* MIC_DET_SET_THRESHOLD - [15:12] */ -#define WM8904_MIC_DET_RESET_THRESHOLD_MASK 0x0F00 /* MIC_DET_RESET_THRESHOLD - [11:8] */ -#define WM8904_MIC_DET_RESET_THRESHOLD_SHIFT 8 /* MIC_DET_RESET_THRESHOLD - [11:8] */ -#define WM8904_MIC_DET_RESET_THRESHOLD_WIDTH 4 /* MIC_DET_RESET_THRESHOLD - [11:8] */ -#define WM8904_MIC_SHORT_SET_THRESHOLD_MASK 0x00F0 /* MIC_SHORT_SET_THRESHOLD - [7:4] */ -#define WM8904_MIC_SHORT_SET_THRESHOLD_SHIFT 4 /* MIC_SHORT_SET_THRESHOLD - [7:4] */ -#define WM8904_MIC_SHORT_SET_THRESHOLD_WIDTH 4 /* MIC_SHORT_SET_THRESHOLD - [7:4] */ -#define WM8904_MIC_SHORT_RESET_THRESHOLD_MASK 0x000F /* MIC_SHORT_RESET_THRESHOLD - [3:0] */ -#define WM8904_MIC_SHORT_RESET_THRESHOLD_SHIFT 0 /* MIC_SHORT_RESET_THRESHOLD - [3:0] */ -#define WM8904_MIC_SHORT_RESET_THRESHOLD_WIDTH 4 /* MIC_SHORT_RESET_THRESHOLD - [3:0] */ - -/* - * R10 (0x0A) - Analogue ADC 0 - */ -#define WM8904_ADC_OSR128 0x0001 /* ADC_OSR128 */ -#define WM8904_ADC_OSR128_MASK 0x0001 /* ADC_OSR128 */ -#define WM8904_ADC_OSR128_SHIFT 0 /* ADC_OSR128 */ -#define WM8904_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ - -/* - * R12 (0x0C) - Power Management 0 - */ -#define WM8904_INL_ENA 0x0002 /* INL_ENA */ -#define WM8904_INL_ENA_MASK 0x0002 /* INL_ENA */ -#define WM8904_INL_ENA_SHIFT 1 /* INL_ENA */ -#define WM8904_INL_ENA_WIDTH 1 /* INL_ENA */ -#define WM8904_INR_ENA 0x0001 /* INR_ENA */ -#define WM8904_INR_ENA_MASK 0x0001 /* INR_ENA */ -#define WM8904_INR_ENA_SHIFT 0 /* INR_ENA */ -#define WM8904_INR_ENA_WIDTH 1 /* INR_ENA */ - -/* - * R14 (0x0E) - Power Management 2 - */ -#define WM8904_HPL_PGA_ENA 0x0002 /* HPL_PGA_ENA */ -#define WM8904_HPL_PGA_ENA_MASK 0x0002 /* HPL_PGA_ENA */ -#define WM8904_HPL_PGA_ENA_SHIFT 1 /* HPL_PGA_ENA */ -#define WM8904_HPL_PGA_ENA_WIDTH 1 /* HPL_PGA_ENA */ -#define WM8904_HPR_PGA_ENA 0x0001 /* HPR_PGA_ENA */ -#define WM8904_HPR_PGA_ENA_MASK 0x0001 /* HPR_PGA_ENA */ -#define WM8904_HPR_PGA_ENA_SHIFT 0 /* HPR_PGA_ENA */ -#define WM8904_HPR_PGA_ENA_WIDTH 1 /* HPR_PGA_ENA */ - -/* - * R15 (0x0F) - Power Management 3 - */ -#define WM8904_LINEOUTL_PGA_ENA 0x0002 /* LINEOUTL_PGA_ENA */ -#define WM8904_LINEOUTL_PGA_ENA_MASK 0x0002 /* LINEOUTL_PGA_ENA */ -#define WM8904_LINEOUTL_PGA_ENA_SHIFT 1 /* LINEOUTL_PGA_ENA */ -#define WM8904_LINEOUTL_PGA_ENA_WIDTH 1 /* LINEOUTL_PGA_ENA */ -#define WM8904_LINEOUTR_PGA_ENA 0x0001 /* LINEOUTR_PGA_ENA */ -#define WM8904_LINEOUTR_PGA_ENA_MASK 0x0001 /* LINEOUTR_PGA_ENA */ -#define WM8904_LINEOUTR_PGA_ENA_SHIFT 0 /* LINEOUTR_PGA_ENA */ -#define WM8904_LINEOUTR_PGA_ENA_WIDTH 1 /* LINEOUTR_PGA_ENA */ - -/* - * R18 (0x12) - Power Management 6 - */ -#define WM8904_DACL_ENA 0x0008 /* DACL_ENA */ -#define WM8904_DACL_ENA_MASK 0x0008 /* DACL_ENA */ -#define WM8904_DACL_ENA_SHIFT 3 /* DACL_ENA */ -#define WM8904_DACL_ENA_WIDTH 1 /* DACL_ENA */ -#define WM8904_DACR_ENA 0x0004 /* DACR_ENA */ -#define WM8904_DACR_ENA_MASK 0x0004 /* DACR_ENA */ -#define WM8904_DACR_ENA_SHIFT 2 /* DACR_ENA */ -#define WM8904_DACR_ENA_WIDTH 1 /* DACR_ENA */ -#define WM8904_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8904_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ -#define WM8904_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ -#define WM8904_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ -#define WM8904_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8904_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ -#define WM8904_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ -#define WM8904_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ - -/* - * R20 (0x14) - Clock Rates 0 - */ -#define WM8904_TOCLK_RATE_DIV16 0x4000 /* TOCLK_RATE_DIV16 */ -#define WM8904_TOCLK_RATE_DIV16_MASK 0x4000 /* TOCLK_RATE_DIV16 */ -#define WM8904_TOCLK_RATE_DIV16_SHIFT 14 /* TOCLK_RATE_DIV16 */ -#define WM8904_TOCLK_RATE_DIV16_WIDTH 1 /* TOCLK_RATE_DIV16 */ -#define WM8904_TOCLK_RATE_X4 0x2000 /* TOCLK_RATE_X4 */ -#define WM8904_TOCLK_RATE_X4_MASK 0x2000 /* TOCLK_RATE_X4 */ -#define WM8904_TOCLK_RATE_X4_SHIFT 13 /* TOCLK_RATE_X4 */ -#define WM8904_TOCLK_RATE_X4_WIDTH 1 /* TOCLK_RATE_X4 */ -#define WM8904_SR_MODE 0x1000 /* SR_MODE */ -#define WM8904_SR_MODE_MASK 0x1000 /* SR_MODE */ -#define WM8904_SR_MODE_SHIFT 12 /* SR_MODE */ -#define WM8904_SR_MODE_WIDTH 1 /* SR_MODE */ -#define WM8904_MCLK_DIV 0x0001 /* MCLK_DIV */ -#define WM8904_MCLK_DIV_MASK 0x0001 /* MCLK_DIV */ -#define WM8904_MCLK_DIV_SHIFT 0 /* MCLK_DIV */ -#define WM8904_MCLK_DIV_WIDTH 1 /* MCLK_DIV */ - -/* - * R21 (0x15) - Clock Rates 1 - */ -#define WM8904_CLK_SYS_RATE_MASK 0x3C00 /* CLK_SYS_RATE - [13:10] */ -#define WM8904_CLK_SYS_RATE_SHIFT 10 /* CLK_SYS_RATE - [13:10] */ -#define WM8904_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [13:10] */ -#define WM8904_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */ -#define WM8904_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */ -#define WM8904_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */ - -/* - * R22 (0x16) - Clock Rates 2 - */ -#define WM8904_MCLK_INV 0x8000 /* MCLK_INV */ -#define WM8904_MCLK_INV_MASK 0x8000 /* MCLK_INV */ -#define WM8904_MCLK_INV_SHIFT 15 /* MCLK_INV */ -#define WM8904_MCLK_INV_WIDTH 1 /* MCLK_INV */ -#define WM8904_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */ -#define WM8904_SYSCLK_SRC_MASK 0x4000 /* SYSCLK_SRC */ -#define WM8904_SYSCLK_SRC_SHIFT 14 /* SYSCLK_SRC */ -#define WM8904_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */ -#define WM8904_TOCLK_RATE 0x1000 /* TOCLK_RATE */ -#define WM8904_TOCLK_RATE_MASK 0x1000 /* TOCLK_RATE */ -#define WM8904_TOCLK_RATE_SHIFT 12 /* TOCLK_RATE */ -#define WM8904_TOCLK_RATE_WIDTH 1 /* TOCLK_RATE */ -#define WM8904_OPCLK_ENA 0x0008 /* OPCLK_ENA */ -#define WM8904_OPCLK_ENA_MASK 0x0008 /* OPCLK_ENA */ -#define WM8904_OPCLK_ENA_SHIFT 3 /* OPCLK_ENA */ -#define WM8904_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ -#define WM8904_CLK_SYS_ENA 0x0004 /* CLK_SYS_ENA */ -#define WM8904_CLK_SYS_ENA_MASK 0x0004 /* CLK_SYS_ENA */ -#define WM8904_CLK_SYS_ENA_SHIFT 2 /* CLK_SYS_ENA */ -#define WM8904_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ -#define WM8904_CLK_DSP_ENA 0x0002 /* CLK_DSP_ENA */ -#define WM8904_CLK_DSP_ENA_MASK 0x0002 /* CLK_DSP_ENA */ -#define WM8904_CLK_DSP_ENA_SHIFT 1 /* CLK_DSP_ENA */ -#define WM8904_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ -#define WM8904_TOCLK_ENA 0x0001 /* TOCLK_ENA */ -#define WM8904_TOCLK_ENA_MASK 0x0001 /* TOCLK_ENA */ -#define WM8904_TOCLK_ENA_SHIFT 0 /* TOCLK_ENA */ -#define WM8904_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ - -/* - * R24 (0x18) - Audio Interface 0 - */ -#define WM8904_DACL_DATINV 0x1000 /* DACL_DATINV */ -#define WM8904_DACL_DATINV_MASK 0x1000 /* DACL_DATINV */ -#define WM8904_DACL_DATINV_SHIFT 12 /* DACL_DATINV */ -#define WM8904_DACL_DATINV_WIDTH 1 /* DACL_DATINV */ -#define WM8904_DACR_DATINV 0x0800 /* DACR_DATINV */ -#define WM8904_DACR_DATINV_MASK 0x0800 /* DACR_DATINV */ -#define WM8904_DACR_DATINV_SHIFT 11 /* DACR_DATINV */ -#define WM8904_DACR_DATINV_WIDTH 1 /* DACR_DATINV */ -#define WM8904_DAC_BOOST_MASK 0x0600 /* DAC_BOOST - [10:9] */ -#define WM8904_DAC_BOOST_SHIFT 9 /* DAC_BOOST - [10:9] */ -#define WM8904_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [10:9] */ -#define WM8904_LOOPBACK 0x0100 /* LOOPBACK */ -#define WM8904_LOOPBACK_MASK 0x0100 /* LOOPBACK */ -#define WM8904_LOOPBACK_SHIFT 8 /* LOOPBACK */ -#define WM8904_LOOPBACK_WIDTH 1 /* LOOPBACK */ -#define WM8904_AIFADCL_SRC 0x0080 /* AIFADCL_SRC */ -#define WM8904_AIFADCL_SRC_MASK 0x0080 /* AIFADCL_SRC */ -#define WM8904_AIFADCL_SRC_SHIFT 7 /* AIFADCL_SRC */ -#define WM8904_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */ -#define WM8904_AIFADCR_SRC 0x0040 /* AIFADCR_SRC */ -#define WM8904_AIFADCR_SRC_MASK 0x0040 /* AIFADCR_SRC */ -#define WM8904_AIFADCR_SRC_SHIFT 6 /* AIFADCR_SRC */ -#define WM8904_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */ -#define WM8904_AIFDACL_SRC 0x0020 /* AIFDACL_SRC */ -#define WM8904_AIFDACL_SRC_MASK 0x0020 /* AIFDACL_SRC */ -#define WM8904_AIFDACL_SRC_SHIFT 5 /* AIFDACL_SRC */ -#define WM8904_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */ -#define WM8904_AIFDACR_SRC 0x0010 /* AIFDACR_SRC */ -#define WM8904_AIFDACR_SRC_MASK 0x0010 /* AIFDACR_SRC */ -#define WM8904_AIFDACR_SRC_SHIFT 4 /* AIFDACR_SRC */ -#define WM8904_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */ -#define WM8904_ADC_COMP 0x0008 /* ADC_COMP */ -#define WM8904_ADC_COMP_MASK 0x0008 /* ADC_COMP */ -#define WM8904_ADC_COMP_SHIFT 3 /* ADC_COMP */ -#define WM8904_ADC_COMP_WIDTH 1 /* ADC_COMP */ -#define WM8904_ADC_COMPMODE 0x0004 /* ADC_COMPMODE */ -#define WM8904_ADC_COMPMODE_MASK 0x0004 /* ADC_COMPMODE */ -#define WM8904_ADC_COMPMODE_SHIFT 2 /* ADC_COMPMODE */ -#define WM8904_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */ -#define WM8904_DAC_COMP 0x0002 /* DAC_COMP */ -#define WM8904_DAC_COMP_MASK 0x0002 /* DAC_COMP */ -#define WM8904_DAC_COMP_SHIFT 1 /* DAC_COMP */ -#define WM8904_DAC_COMP_WIDTH 1 /* DAC_COMP */ -#define WM8904_DAC_COMPMODE 0x0001 /* DAC_COMPMODE */ -#define WM8904_DAC_COMPMODE_MASK 0x0001 /* DAC_COMPMODE */ -#define WM8904_DAC_COMPMODE_SHIFT 0 /* DAC_COMPMODE */ -#define WM8904_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ - -/* - * R25 (0x19) - Audio Interface 1 - */ -#define WM8904_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ -#define WM8904_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */ -#define WM8904_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */ -#define WM8904_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */ -#define WM8904_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8904_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8904_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */ -#define WM8904_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */ -#define WM8904_AIFADC_TDM 0x0800 /* AIFADC_TDM */ -#define WM8904_AIFADC_TDM_MASK 0x0800 /* AIFADC_TDM */ -#define WM8904_AIFADC_TDM_SHIFT 11 /* AIFADC_TDM */ -#define WM8904_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */ -#define WM8904_AIFADC_TDM_CHAN 0x0400 /* AIFADC_TDM_CHAN */ -#define WM8904_AIFADC_TDM_CHAN_MASK 0x0400 /* AIFADC_TDM_CHAN */ -#define WM8904_AIFADC_TDM_CHAN_SHIFT 10 /* AIFADC_TDM_CHAN */ -#define WM8904_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */ -#define WM8904_AIF_TRIS 0x0100 /* AIF_TRIS */ -#define WM8904_AIF_TRIS_MASK 0x0100 /* AIF_TRIS */ -#define WM8904_AIF_TRIS_SHIFT 8 /* AIF_TRIS */ -#define WM8904_AIF_TRIS_WIDTH 1 /* AIF_TRIS */ -#define WM8904_AIF_BCLK_INV 0x0080 /* AIF_BCLK_INV */ -#define WM8904_AIF_BCLK_INV_MASK 0x0080 /* AIF_BCLK_INV */ -#define WM8904_AIF_BCLK_INV_SHIFT 7 /* AIF_BCLK_INV */ -#define WM8904_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */ -#define WM8904_BCLK_DIR 0x0040 /* BCLK_DIR */ -#define WM8904_BCLK_DIR_MASK 0x0040 /* BCLK_DIR */ -#define WM8904_BCLK_DIR_SHIFT 6 /* BCLK_DIR */ -#define WM8904_BCLK_DIR_WIDTH 1 /* BCLK_DIR */ -#define WM8904_AIF_LRCLK_INV 0x0010 /* AIF_LRCLK_INV */ -#define WM8904_AIF_LRCLK_INV_MASK 0x0010 /* AIF_LRCLK_INV */ -#define WM8904_AIF_LRCLK_INV_SHIFT 4 /* AIF_LRCLK_INV */ -#define WM8904_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */ -#define WM8904_AIF_WL_MASK 0x000C /* AIF_WL - [3:2] */ -#define WM8904_AIF_WL_SHIFT 2 /* AIF_WL - [3:2] */ -#define WM8904_AIF_WL_WIDTH 2 /* AIF_WL - [3:2] */ -#define WM8904_AIF_FMT_MASK 0x0003 /* AIF_FMT - [1:0] */ -#define WM8904_AIF_FMT_SHIFT 0 /* AIF_FMT - [1:0] */ -#define WM8904_AIF_FMT_WIDTH 2 /* AIF_FMT - [1:0] */ - -/* - * R26 (0x1A) - Audio Interface 2 - */ -#define WM8904_OPCLK_DIV_MASK 0x0F00 /* OPCLK_DIV - [11:8] */ -#define WM8904_OPCLK_DIV_SHIFT 8 /* OPCLK_DIV - [11:8] */ -#define WM8904_OPCLK_DIV_WIDTH 4 /* OPCLK_DIV - [11:8] */ -#define WM8904_BCLK_DIV_MASK 0x001F /* BCLK_DIV - [4:0] */ -#define WM8904_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [4:0] */ -#define WM8904_BCLK_DIV_WIDTH 5 /* BCLK_DIV - [4:0] */ - -/* - * R27 (0x1B) - Audio Interface 3 - */ -#define WM8904_LRCLK_DIR 0x0800 /* LRCLK_DIR */ -#define WM8904_LRCLK_DIR_MASK 0x0800 /* LRCLK_DIR */ -#define WM8904_LRCLK_DIR_SHIFT 11 /* LRCLK_DIR */ -#define WM8904_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */ -#define WM8904_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */ -#define WM8904_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */ -#define WM8904_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */ - -/* - * R30 (0x1E) - DAC Digital Volume Left - */ -#define WM8904_DAC_VU 0x0100 /* DAC_VU */ -#define WM8904_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8904_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8904_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8904_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ -#define WM8904_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */ -#define WM8904_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */ - -/* - * R31 (0x1F) - DAC Digital Volume Right - */ -#define WM8904_DAC_VU 0x0100 /* DAC_VU */ -#define WM8904_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8904_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8904_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8904_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ -#define WM8904_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */ -#define WM8904_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */ - -/* - * R32 (0x20) - DAC Digital 0 - */ -#define WM8904_ADCL_DAC_SVOL_MASK 0x0F00 /* ADCL_DAC_SVOL - [11:8] */ -#define WM8904_ADCL_DAC_SVOL_SHIFT 8 /* ADCL_DAC_SVOL - [11:8] */ -#define WM8904_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [11:8] */ -#define WM8904_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8904_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8904_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8904_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8904_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8904_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ -#define WM8904_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */ -#define WM8904_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */ -#define WM8904_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */ - -/* - * R33 (0x21) - DAC Digital 1 - */ -#define WM8904_DAC_MONO 0x1000 /* DAC_MONO */ -#define WM8904_DAC_MONO_MASK 0x1000 /* DAC_MONO */ -#define WM8904_DAC_MONO_SHIFT 12 /* DAC_MONO */ -#define WM8904_DAC_MONO_WIDTH 1 /* DAC_MONO */ -#define WM8904_DAC_SB_FILT 0x0800 /* DAC_SB_FILT */ -#define WM8904_DAC_SB_FILT_MASK 0x0800 /* DAC_SB_FILT */ -#define WM8904_DAC_SB_FILT_SHIFT 11 /* DAC_SB_FILT */ -#define WM8904_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */ -#define WM8904_DAC_MUTERATE 0x0400 /* DAC_MUTERATE */ -#define WM8904_DAC_MUTERATE_MASK 0x0400 /* DAC_MUTERATE */ -#define WM8904_DAC_MUTERATE_SHIFT 10 /* DAC_MUTERATE */ -#define WM8904_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ -#define WM8904_DAC_UNMUTE_RAMP 0x0200 /* DAC_UNMUTE_RAMP */ -#define WM8904_DAC_UNMUTE_RAMP_MASK 0x0200 /* DAC_UNMUTE_RAMP */ -#define WM8904_DAC_UNMUTE_RAMP_SHIFT 9 /* DAC_UNMUTE_RAMP */ -#define WM8904_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */ -#define WM8904_DAC_OSR128 0x0040 /* DAC_OSR128 */ -#define WM8904_DAC_OSR128_MASK 0x0040 /* DAC_OSR128 */ -#define WM8904_DAC_OSR128_SHIFT 6 /* DAC_OSR128 */ -#define WM8904_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ -#define WM8904_DAC_MUTE 0x0008 /* DAC_MUTE */ -#define WM8904_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */ -#define WM8904_DAC_MUTE_SHIFT 3 /* DAC_MUTE */ -#define WM8904_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ -#define WM8904_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ -#define WM8904_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ -#define WM8904_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ - -/* - * R36 (0x24) - ADC Digital Volume Left - */ -#define WM8904_ADC_VU 0x0100 /* ADC_VU */ -#define WM8904_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8904_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8904_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8904_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ -#define WM8904_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */ -#define WM8904_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */ - -/* - * R37 (0x25) - ADC Digital Volume Right - */ -#define WM8904_ADC_VU 0x0100 /* ADC_VU */ -#define WM8904_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8904_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8904_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8904_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ -#define WM8904_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */ -#define WM8904_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */ - -/* - * R38 (0x26) - ADC Digital 0 - */ -#define WM8904_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */ -#define WM8904_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */ -#define WM8904_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */ -#define WM8904_ADC_HPF 0x0010 /* ADC_HPF */ -#define WM8904_ADC_HPF_MASK 0x0010 /* ADC_HPF */ -#define WM8904_ADC_HPF_SHIFT 4 /* ADC_HPF */ -#define WM8904_ADC_HPF_WIDTH 1 /* ADC_HPF */ -#define WM8904_ADCL_DATINV 0x0002 /* ADCL_DATINV */ -#define WM8904_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */ -#define WM8904_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */ -#define WM8904_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */ -#define WM8904_ADCR_DATINV 0x0001 /* ADCR_DATINV */ -#define WM8904_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */ -#define WM8904_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */ -#define WM8904_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */ - -/* - * R39 (0x27) - Digital Microphone 0 - */ -#define WM8904_DMIC_ENA 0x1000 /* DMIC_ENA */ -#define WM8904_DMIC_ENA_MASK 0x1000 /* DMIC_ENA */ -#define WM8904_DMIC_ENA_SHIFT 12 /* DMIC_ENA */ -#define WM8904_DMIC_ENA_WIDTH 1 /* DMIC_ENA */ -#define WM8904_DMIC_SRC 0x0800 /* DMIC_SRC */ -#define WM8904_DMIC_SRC_MASK 0x0800 /* DMIC_SRC */ -#define WM8904_DMIC_SRC_SHIFT 11 /* DMIC_SRC */ -#define WM8904_DMIC_SRC_WIDTH 1 /* DMIC_SRC */ - -/* - * R40 (0x28) - DRC 0 - */ -#define WM8904_DRC_ENA 0x8000 /* DRC_ENA */ -#define WM8904_DRC_ENA_MASK 0x8000 /* DRC_ENA */ -#define WM8904_DRC_ENA_SHIFT 15 /* DRC_ENA */ -#define WM8904_DRC_ENA_WIDTH 1 /* DRC_ENA */ -#define WM8904_DRC_DAC_PATH 0x4000 /* DRC_DAC_PATH */ -#define WM8904_DRC_DAC_PATH_MASK 0x4000 /* DRC_DAC_PATH */ -#define WM8904_DRC_DAC_PATH_SHIFT 14 /* DRC_DAC_PATH */ -#define WM8904_DRC_DAC_PATH_WIDTH 1 /* DRC_DAC_PATH */ -#define WM8904_DRC_GS_HYST_LVL_MASK 0x1800 /* DRC_GS_HYST_LVL - [12:11] */ -#define WM8904_DRC_GS_HYST_LVL_SHIFT 11 /* DRC_GS_HYST_LVL - [12:11] */ -#define WM8904_DRC_GS_HYST_LVL_WIDTH 2 /* DRC_GS_HYST_LVL - [12:11] */ -#define WM8904_DRC_STARTUP_GAIN_MASK 0x07C0 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM8904_DRC_STARTUP_GAIN_SHIFT 6 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM8904_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM8904_DRC_FF_DELAY 0x0020 /* DRC_FF_DELAY */ -#define WM8904_DRC_FF_DELAY_MASK 0x0020 /* DRC_FF_DELAY */ -#define WM8904_DRC_FF_DELAY_SHIFT 5 /* DRC_FF_DELAY */ -#define WM8904_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */ -#define WM8904_DRC_GS_ENA 0x0008 /* DRC_GS_ENA */ -#define WM8904_DRC_GS_ENA_MASK 0x0008 /* DRC_GS_ENA */ -#define WM8904_DRC_GS_ENA_SHIFT 3 /* DRC_GS_ENA */ -#define WM8904_DRC_GS_ENA_WIDTH 1 /* DRC_GS_ENA */ -#define WM8904_DRC_QR 0x0004 /* DRC_QR */ -#define WM8904_DRC_QR_MASK 0x0004 /* DRC_QR */ -#define WM8904_DRC_QR_SHIFT 2 /* DRC_QR */ -#define WM8904_DRC_QR_WIDTH 1 /* DRC_QR */ -#define WM8904_DRC_ANTICLIP 0x0002 /* DRC_ANTICLIP */ -#define WM8904_DRC_ANTICLIP_MASK 0x0002 /* DRC_ANTICLIP */ -#define WM8904_DRC_ANTICLIP_SHIFT 1 /* DRC_ANTICLIP */ -#define WM8904_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */ -#define WM8904_DRC_GS_HYST 0x0001 /* DRC_GS_HYST */ -#define WM8904_DRC_GS_HYST_MASK 0x0001 /* DRC_GS_HYST */ -#define WM8904_DRC_GS_HYST_SHIFT 0 /* DRC_GS_HYST */ -#define WM8904_DRC_GS_HYST_WIDTH 1 /* DRC_GS_HYST */ - -/* - * R41 (0x29) - DRC 1 - */ -#define WM8904_DRC_ATK_MASK 0xF000 /* DRC_ATK - [15:12] */ -#define WM8904_DRC_ATK_SHIFT 12 /* DRC_ATK - [15:12] */ -#define WM8904_DRC_ATK_WIDTH 4 /* DRC_ATK - [15:12] */ -#define WM8904_DRC_DCY_MASK 0x0F00 /* DRC_DCY - [11:8] */ -#define WM8904_DRC_DCY_SHIFT 8 /* DRC_DCY - [11:8] */ -#define WM8904_DRC_DCY_WIDTH 4 /* DRC_DCY - [11:8] */ -#define WM8904_DRC_QR_THR_MASK 0x00C0 /* DRC_QR_THR - [7:6] */ -#define WM8904_DRC_QR_THR_SHIFT 6 /* DRC_QR_THR - [7:6] */ -#define WM8904_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [7:6] */ -#define WM8904_DRC_QR_DCY_MASK 0x0030 /* DRC_QR_DCY - [5:4] */ -#define WM8904_DRC_QR_DCY_SHIFT 4 /* DRC_QR_DCY - [5:4] */ -#define WM8904_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [5:4] */ -#define WM8904_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */ -#define WM8904_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */ -#define WM8904_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */ -#define WM8904_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ -#define WM8904_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ -#define WM8904_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ - -/* - * R42 (0x2A) - DRC 2 - */ -#define WM8904_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */ -#define WM8904_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */ -#define WM8904_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */ -#define WM8904_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */ -#define WM8904_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */ -#define WM8904_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */ - -/* - * R43 (0x2B) - DRC 3 - */ -#define WM8904_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */ -#define WM8904_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */ -#define WM8904_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */ -#define WM8904_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */ -#define WM8904_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */ -#define WM8904_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */ - -/* - * R44 (0x2C) - Analogue Left Input 0 - */ -#define WM8904_LINMUTE 0x0080 /* LINMUTE */ -#define WM8904_LINMUTE_MASK 0x0080 /* LINMUTE */ -#define WM8904_LINMUTE_SHIFT 7 /* LINMUTE */ -#define WM8904_LINMUTE_WIDTH 1 /* LINMUTE */ -#define WM8904_LIN_VOL_MASK 0x001F /* LIN_VOL - [4:0] */ -#define WM8904_LIN_VOL_SHIFT 0 /* LIN_VOL - [4:0] */ -#define WM8904_LIN_VOL_WIDTH 5 /* LIN_VOL - [4:0] */ - -/* - * R45 (0x2D) - Analogue Right Input 0 - */ -#define WM8904_RINMUTE 0x0080 /* RINMUTE */ -#define WM8904_RINMUTE_MASK 0x0080 /* RINMUTE */ -#define WM8904_RINMUTE_SHIFT 7 /* RINMUTE */ -#define WM8904_RINMUTE_WIDTH 1 /* RINMUTE */ -#define WM8904_RIN_VOL_MASK 0x001F /* RIN_VOL - [4:0] */ -#define WM8904_RIN_VOL_SHIFT 0 /* RIN_VOL - [4:0] */ -#define WM8904_RIN_VOL_WIDTH 5 /* RIN_VOL - [4:0] */ - -/* - * R46 (0x2E) - Analogue Left Input 1 - */ -#define WM8904_INL_CM_ENA 0x0040 /* INL_CM_ENA */ -#define WM8904_INL_CM_ENA_MASK 0x0040 /* INL_CM_ENA */ -#define WM8904_INL_CM_ENA_SHIFT 6 /* INL_CM_ENA */ -#define WM8904_INL_CM_ENA_WIDTH 1 /* INL_CM_ENA */ -#define WM8904_L_IP_SEL_N_MASK 0x0030 /* L_IP_SEL_N - [5:4] */ -#define WM8904_L_IP_SEL_N_SHIFT 4 /* L_IP_SEL_N - [5:4] */ -#define WM8904_L_IP_SEL_N_WIDTH 2 /* L_IP_SEL_N - [5:4] */ -#define WM8904_L_IP_SEL_P_MASK 0x000C /* L_IP_SEL_P - [3:2] */ -#define WM8904_L_IP_SEL_P_SHIFT 2 /* L_IP_SEL_P - [3:2] */ -#define WM8904_L_IP_SEL_P_WIDTH 2 /* L_IP_SEL_P - [3:2] */ -#define WM8904_L_MODE_MASK 0x0003 /* L_MODE - [1:0] */ -#define WM8904_L_MODE_SHIFT 0 /* L_MODE - [1:0] */ -#define WM8904_L_MODE_WIDTH 2 /* L_MODE - [1:0] */ - -/* - * R47 (0x2F) - Analogue Right Input 1 - */ -#define WM8904_INR_CM_ENA 0x0040 /* INR_CM_ENA */ -#define WM8904_INR_CM_ENA_MASK 0x0040 /* INR_CM_ENA */ -#define WM8904_INR_CM_ENA_SHIFT 6 /* INR_CM_ENA */ -#define WM8904_INR_CM_ENA_WIDTH 1 /* INR_CM_ENA */ -#define WM8904_R_IP_SEL_N_MASK 0x0030 /* R_IP_SEL_N - [5:4] */ -#define WM8904_R_IP_SEL_N_SHIFT 4 /* R_IP_SEL_N - [5:4] */ -#define WM8904_R_IP_SEL_N_WIDTH 2 /* R_IP_SEL_N - [5:4] */ -#define WM8904_R_IP_SEL_P_MASK 0x000C /* R_IP_SEL_P - [3:2] */ -#define WM8904_R_IP_SEL_P_SHIFT 2 /* R_IP_SEL_P - [3:2] */ -#define WM8904_R_IP_SEL_P_WIDTH 2 /* R_IP_SEL_P - [3:2] */ -#define WM8904_R_MODE_MASK 0x0003 /* R_MODE - [1:0] */ -#define WM8904_R_MODE_SHIFT 0 /* R_MODE - [1:0] */ -#define WM8904_R_MODE_WIDTH 2 /* R_MODE - [1:0] */ - -/* - * R57 (0x39) - Analogue OUT1 Left - */ -#define WM8904_HPOUTL_MUTE 0x0100 /* HPOUTL_MUTE */ -#define WM8904_HPOUTL_MUTE_MASK 0x0100 /* HPOUTL_MUTE */ -#define WM8904_HPOUTL_MUTE_SHIFT 8 /* HPOUTL_MUTE */ -#define WM8904_HPOUTL_MUTE_WIDTH 1 /* HPOUTL_MUTE */ -#define WM8904_HPOUT_VU 0x0080 /* HPOUT_VU */ -#define WM8904_HPOUT_VU_MASK 0x0080 /* HPOUT_VU */ -#define WM8904_HPOUT_VU_SHIFT 7 /* HPOUT_VU */ -#define WM8904_HPOUT_VU_WIDTH 1 /* HPOUT_VU */ -#define WM8904_HPOUTLZC 0x0040 /* HPOUTLZC */ -#define WM8904_HPOUTLZC_MASK 0x0040 /* HPOUTLZC */ -#define WM8904_HPOUTLZC_SHIFT 6 /* HPOUTLZC */ -#define WM8904_HPOUTLZC_WIDTH 1 /* HPOUTLZC */ -#define WM8904_HPOUTL_VOL_MASK 0x003F /* HPOUTL_VOL - [5:0] */ -#define WM8904_HPOUTL_VOL_SHIFT 0 /* HPOUTL_VOL - [5:0] */ -#define WM8904_HPOUTL_VOL_WIDTH 6 /* HPOUTL_VOL - [5:0] */ - -/* - * R58 (0x3A) - Analogue OUT1 Right - */ -#define WM8904_HPOUTR_MUTE 0x0100 /* HPOUTR_MUTE */ -#define WM8904_HPOUTR_MUTE_MASK 0x0100 /* HPOUTR_MUTE */ -#define WM8904_HPOUTR_MUTE_SHIFT 8 /* HPOUTR_MUTE */ -#define WM8904_HPOUTR_MUTE_WIDTH 1 /* HPOUTR_MUTE */ -#define WM8904_HPOUT_VU 0x0080 /* HPOUT_VU */ -#define WM8904_HPOUT_VU_MASK 0x0080 /* HPOUT_VU */ -#define WM8904_HPOUT_VU_SHIFT 7 /* HPOUT_VU */ -#define WM8904_HPOUT_VU_WIDTH 1 /* HPOUT_VU */ -#define WM8904_HPOUTRZC 0x0040 /* HPOUTRZC */ -#define WM8904_HPOUTRZC_MASK 0x0040 /* HPOUTRZC */ -#define WM8904_HPOUTRZC_SHIFT 6 /* HPOUTRZC */ -#define WM8904_HPOUTRZC_WIDTH 1 /* HPOUTRZC */ -#define WM8904_HPOUTR_VOL_MASK 0x003F /* HPOUTR_VOL - [5:0] */ -#define WM8904_HPOUTR_VOL_SHIFT 0 /* HPOUTR_VOL - [5:0] */ -#define WM8904_HPOUTR_VOL_WIDTH 6 /* HPOUTR_VOL - [5:0] */ - -/* - * R59 (0x3B) - Analogue OUT2 Left - */ -#define WM8904_LINEOUTL_MUTE 0x0100 /* LINEOUTL_MUTE */ -#define WM8904_LINEOUTL_MUTE_MASK 0x0100 /* LINEOUTL_MUTE */ -#define WM8904_LINEOUTL_MUTE_SHIFT 8 /* LINEOUTL_MUTE */ -#define WM8904_LINEOUTL_MUTE_WIDTH 1 /* LINEOUTL_MUTE */ -#define WM8904_LINEOUT_VU 0x0080 /* LINEOUT_VU */ -#define WM8904_LINEOUT_VU_MASK 0x0080 /* LINEOUT_VU */ -#define WM8904_LINEOUT_VU_SHIFT 7 /* LINEOUT_VU */ -#define WM8904_LINEOUT_VU_WIDTH 1 /* LINEOUT_VU */ -#define WM8904_LINEOUTLZC 0x0040 /* LINEOUTLZC */ -#define WM8904_LINEOUTLZC_MASK 0x0040 /* LINEOUTLZC */ -#define WM8904_LINEOUTLZC_SHIFT 6 /* LINEOUTLZC */ -#define WM8904_LINEOUTLZC_WIDTH 1 /* LINEOUTLZC */ -#define WM8904_LINEOUTL_VOL_MASK 0x003F /* LINEOUTL_VOL - [5:0] */ -#define WM8904_LINEOUTL_VOL_SHIFT 0 /* LINEOUTL_VOL - [5:0] */ -#define WM8904_LINEOUTL_VOL_WIDTH 6 /* LINEOUTL_VOL - [5:0] */ - -/* - * R60 (0x3C) - Analogue OUT2 Right - */ -#define WM8904_LINEOUTR_MUTE 0x0100 /* LINEOUTR_MUTE */ -#define WM8904_LINEOUTR_MUTE_MASK 0x0100 /* LINEOUTR_MUTE */ -#define WM8904_LINEOUTR_MUTE_SHIFT 8 /* LINEOUTR_MUTE */ -#define WM8904_LINEOUTR_MUTE_WIDTH 1 /* LINEOUTR_MUTE */ -#define WM8904_LINEOUT_VU 0x0080 /* LINEOUT_VU */ -#define WM8904_LINEOUT_VU_MASK 0x0080 /* LINEOUT_VU */ -#define WM8904_LINEOUT_VU_SHIFT 7 /* LINEOUT_VU */ -#define WM8904_LINEOUT_VU_WIDTH 1 /* LINEOUT_VU */ -#define WM8904_LINEOUTRZC 0x0040 /* LINEOUTRZC */ -#define WM8904_LINEOUTRZC_MASK 0x0040 /* LINEOUTRZC */ -#define WM8904_LINEOUTRZC_SHIFT 6 /* LINEOUTRZC */ -#define WM8904_LINEOUTRZC_WIDTH 1 /* LINEOUTRZC */ -#define WM8904_LINEOUTR_VOL_MASK 0x003F /* LINEOUTR_VOL - [5:0] */ -#define WM8904_LINEOUTR_VOL_SHIFT 0 /* LINEOUTR_VOL - [5:0] */ -#define WM8904_LINEOUTR_VOL_WIDTH 6 /* LINEOUTR_VOL - [5:0] */ - -/* - * R61 (0x3D) - Analogue OUT12 ZC - */ -#define WM8904_HPL_BYP_ENA 0x0008 /* HPL_BYP_ENA */ -#define WM8904_HPL_BYP_ENA_MASK 0x0008 /* HPL_BYP_ENA */ -#define WM8904_HPL_BYP_ENA_SHIFT 3 /* HPL_BYP_ENA */ -#define WM8904_HPL_BYP_ENA_WIDTH 1 /* HPL_BYP_ENA */ -#define WM8904_HPR_BYP_ENA 0x0004 /* HPR_BYP_ENA */ -#define WM8904_HPR_BYP_ENA_MASK 0x0004 /* HPR_BYP_ENA */ -#define WM8904_HPR_BYP_ENA_SHIFT 2 /* HPR_BYP_ENA */ -#define WM8904_HPR_BYP_ENA_WIDTH 1 /* HPR_BYP_ENA */ -#define WM8904_LINEOUTL_BYP_ENA 0x0002 /* LINEOUTL_BYP_ENA */ -#define WM8904_LINEOUTL_BYP_ENA_MASK 0x0002 /* LINEOUTL_BYP_ENA */ -#define WM8904_LINEOUTL_BYP_ENA_SHIFT 1 /* LINEOUTL_BYP_ENA */ -#define WM8904_LINEOUTL_BYP_ENA_WIDTH 1 /* LINEOUTL_BYP_ENA */ -#define WM8904_LINEOUTR_BYP_ENA 0x0001 /* LINEOUTR_BYP_ENA */ -#define WM8904_LINEOUTR_BYP_ENA_MASK 0x0001 /* LINEOUTR_BYP_ENA */ -#define WM8904_LINEOUTR_BYP_ENA_SHIFT 0 /* LINEOUTR_BYP_ENA */ -#define WM8904_LINEOUTR_BYP_ENA_WIDTH 1 /* LINEOUTR_BYP_ENA */ - -/* - * R67 (0x43) - DC Servo 0 - */ -#define WM8904_DCS_ENA_CHAN_3 0x0008 /* DCS_ENA_CHAN_3 */ -#define WM8904_DCS_ENA_CHAN_3_MASK 0x0008 /* DCS_ENA_CHAN_3 */ -#define WM8904_DCS_ENA_CHAN_3_SHIFT 3 /* DCS_ENA_CHAN_3 */ -#define WM8904_DCS_ENA_CHAN_3_WIDTH 1 /* DCS_ENA_CHAN_3 */ -#define WM8904_DCS_ENA_CHAN_2 0x0004 /* DCS_ENA_CHAN_2 */ -#define WM8904_DCS_ENA_CHAN_2_MASK 0x0004 /* DCS_ENA_CHAN_2 */ -#define WM8904_DCS_ENA_CHAN_2_SHIFT 2 /* DCS_ENA_CHAN_2 */ -#define WM8904_DCS_ENA_CHAN_2_WIDTH 1 /* DCS_ENA_CHAN_2 */ -#define WM8904_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8904_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8904_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ -#define WM8904_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ -#define WM8904_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8904_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8904_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ -#define WM8904_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ - -/* - * R68 (0x44) - DC Servo 1 - */ -#define WM8904_DCS_TRIG_SINGLE_3 0x8000 /* DCS_TRIG_SINGLE_3 */ -#define WM8904_DCS_TRIG_SINGLE_3_MASK 0x8000 /* DCS_TRIG_SINGLE_3 */ -#define WM8904_DCS_TRIG_SINGLE_3_SHIFT 15 /* DCS_TRIG_SINGLE_3 */ -#define WM8904_DCS_TRIG_SINGLE_3_WIDTH 1 /* DCS_TRIG_SINGLE_3 */ -#define WM8904_DCS_TRIG_SINGLE_2 0x4000 /* DCS_TRIG_SINGLE_2 */ -#define WM8904_DCS_TRIG_SINGLE_2_MASK 0x4000 /* DCS_TRIG_SINGLE_2 */ -#define WM8904_DCS_TRIG_SINGLE_2_SHIFT 14 /* DCS_TRIG_SINGLE_2 */ -#define WM8904_DCS_TRIG_SINGLE_2_WIDTH 1 /* DCS_TRIG_SINGLE_2 */ -#define WM8904_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8904_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8904_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ -#define WM8904_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ -#define WM8904_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8904_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8904_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ -#define WM8904_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ -#define WM8904_DCS_TRIG_SERIES_3 0x0800 /* DCS_TRIG_SERIES_3 */ -#define WM8904_DCS_TRIG_SERIES_3_MASK 0x0800 /* DCS_TRIG_SERIES_3 */ -#define WM8904_DCS_TRIG_SERIES_3_SHIFT 11 /* DCS_TRIG_SERIES_3 */ -#define WM8904_DCS_TRIG_SERIES_3_WIDTH 1 /* DCS_TRIG_SERIES_3 */ -#define WM8904_DCS_TRIG_SERIES_2 0x0400 /* DCS_TRIG_SERIES_2 */ -#define WM8904_DCS_TRIG_SERIES_2_MASK 0x0400 /* DCS_TRIG_SERIES_2 */ -#define WM8904_DCS_TRIG_SERIES_2_SHIFT 10 /* DCS_TRIG_SERIES_2 */ -#define WM8904_DCS_TRIG_SERIES_2_WIDTH 1 /* DCS_TRIG_SERIES_2 */ -#define WM8904_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8904_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8904_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ -#define WM8904_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ -#define WM8904_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8904_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8904_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ -#define WM8904_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ -#define WM8904_DCS_TRIG_STARTUP_3 0x0080 /* DCS_TRIG_STARTUP_3 */ -#define WM8904_DCS_TRIG_STARTUP_3_MASK 0x0080 /* DCS_TRIG_STARTUP_3 */ -#define WM8904_DCS_TRIG_STARTUP_3_SHIFT 7 /* DCS_TRIG_STARTUP_3 */ -#define WM8904_DCS_TRIG_STARTUP_3_WIDTH 1 /* DCS_TRIG_STARTUP_3 */ -#define WM8904_DCS_TRIG_STARTUP_2 0x0040 /* DCS_TRIG_STARTUP_2 */ -#define WM8904_DCS_TRIG_STARTUP_2_MASK 0x0040 /* DCS_TRIG_STARTUP_2 */ -#define WM8904_DCS_TRIG_STARTUP_2_SHIFT 6 /* DCS_TRIG_STARTUP_2 */ -#define WM8904_DCS_TRIG_STARTUP_2_WIDTH 1 /* DCS_TRIG_STARTUP_2 */ -#define WM8904_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8904_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8904_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ -#define WM8904_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ -#define WM8904_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8904_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8904_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ -#define WM8904_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ -#define WM8904_DCS_TRIG_DAC_WR_3 0x0008 /* DCS_TRIG_DAC_WR_3 */ -#define WM8904_DCS_TRIG_DAC_WR_3_MASK 0x0008 /* DCS_TRIG_DAC_WR_3 */ -#define WM8904_DCS_TRIG_DAC_WR_3_SHIFT 3 /* DCS_TRIG_DAC_WR_3 */ -#define WM8904_DCS_TRIG_DAC_WR_3_WIDTH 1 /* DCS_TRIG_DAC_WR_3 */ -#define WM8904_DCS_TRIG_DAC_WR_2 0x0004 /* DCS_TRIG_DAC_WR_2 */ -#define WM8904_DCS_TRIG_DAC_WR_2_MASK 0x0004 /* DCS_TRIG_DAC_WR_2 */ -#define WM8904_DCS_TRIG_DAC_WR_2_SHIFT 2 /* DCS_TRIG_DAC_WR_2 */ -#define WM8904_DCS_TRIG_DAC_WR_2_WIDTH 1 /* DCS_TRIG_DAC_WR_2 */ -#define WM8904_DCS_TRIG_DAC_WR_1 0x0002 /* DCS_TRIG_DAC_WR_1 */ -#define WM8904_DCS_TRIG_DAC_WR_1_MASK 0x0002 /* DCS_TRIG_DAC_WR_1 */ -#define WM8904_DCS_TRIG_DAC_WR_1_SHIFT 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8904_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8904_DCS_TRIG_DAC_WR_0 0x0001 /* DCS_TRIG_DAC_WR_0 */ -#define WM8904_DCS_TRIG_DAC_WR_0_MASK 0x0001 /* DCS_TRIG_DAC_WR_0 */ -#define WM8904_DCS_TRIG_DAC_WR_0_SHIFT 0 /* DCS_TRIG_DAC_WR_0 */ -#define WM8904_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ - -/* - * R69 (0x45) - DC Servo 2 - */ -#define WM8904_DCS_TIMER_PERIOD_23_MASK 0x0F00 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8904_DCS_TIMER_PERIOD_23_SHIFT 8 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8904_DCS_TIMER_PERIOD_23_WIDTH 4 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8904_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8904_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8904_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ - -/* - * R71 (0x47) - DC Servo 4 - */ -#define WM8904_DCS_SERIES_NO_23_MASK 0x007F /* DCS_SERIES_NO_23 - [6:0] */ -#define WM8904_DCS_SERIES_NO_23_SHIFT 0 /* DCS_SERIES_NO_23 - [6:0] */ -#define WM8904_DCS_SERIES_NO_23_WIDTH 7 /* DCS_SERIES_NO_23 - [6:0] */ - -/* - * R72 (0x48) - DC Servo 5 - */ -#define WM8904_DCS_SERIES_NO_01_MASK 0x007F /* DCS_SERIES_NO_01 - [6:0] */ -#define WM8904_DCS_SERIES_NO_01_SHIFT 0 /* DCS_SERIES_NO_01 - [6:0] */ -#define WM8904_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [6:0] */ - -/* - * R73 (0x49) - DC Servo 6 - */ -#define WM8904_DCS_DAC_WR_VAL_3_MASK 0x00FF /* DCS_DAC_WR_VAL_3 - [7:0] */ -#define WM8904_DCS_DAC_WR_VAL_3_SHIFT 0 /* DCS_DAC_WR_VAL_3 - [7:0] */ -#define WM8904_DCS_DAC_WR_VAL_3_WIDTH 8 /* DCS_DAC_WR_VAL_3 - [7:0] */ - -/* - * R74 (0x4A) - DC Servo 7 - */ -#define WM8904_DCS_DAC_WR_VAL_2_MASK 0x00FF /* DCS_DAC_WR_VAL_2 - [7:0] */ -#define WM8904_DCS_DAC_WR_VAL_2_SHIFT 0 /* DCS_DAC_WR_VAL_2 - [7:0] */ -#define WM8904_DCS_DAC_WR_VAL_2_WIDTH 8 /* DCS_DAC_WR_VAL_2 - [7:0] */ - -/* - * R75 (0x4B) - DC Servo 8 - */ -#define WM8904_DCS_DAC_WR_VAL_1_MASK 0x00FF /* DCS_DAC_WR_VAL_1 - [7:0] */ -#define WM8904_DCS_DAC_WR_VAL_1_SHIFT 0 /* DCS_DAC_WR_VAL_1 - [7:0] */ -#define WM8904_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [7:0] */ - -/* - * R76 (0x4C) - DC Servo 9 - */ -#define WM8904_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8904_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8904_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ - -/* - * R77 (0x4D) - DC Servo Readback 0 - */ -#define WM8904_DCS_CAL_COMPLETE_MASK 0x0F00 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8904_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8904_DCS_CAL_COMPLETE_WIDTH 4 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8904_DCS_DAC_WR_COMPLETE_MASK 0x00F0 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8904_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8904_DCS_DAC_WR_COMPLETE_WIDTH 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8904_DCS_STARTUP_COMPLETE_MASK 0x000F /* DCS_STARTUP_COMPLETE - [3:0] */ -#define WM8904_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [3:0] */ -#define WM8904_DCS_STARTUP_COMPLETE_WIDTH 4 /* DCS_STARTUP_COMPLETE - [3:0] */ - -/* - * R90 (0x5A) - Analogue HP 0 - */ -#define WM8904_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */ -#define WM8904_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */ -#define WM8904_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */ -#define WM8904_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */ -#define WM8904_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */ -#define WM8904_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */ -#define WM8904_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */ -#define WM8904_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */ -#define WM8904_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */ -#define WM8904_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */ -#define WM8904_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */ -#define WM8904_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */ -#define WM8904_HPL_ENA 0x0010 /* HPL_ENA */ -#define WM8904_HPL_ENA_MASK 0x0010 /* HPL_ENA */ -#define WM8904_HPL_ENA_SHIFT 4 /* HPL_ENA */ -#define WM8904_HPL_ENA_WIDTH 1 /* HPL_ENA */ -#define WM8904_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */ -#define WM8904_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */ -#define WM8904_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */ -#define WM8904_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */ -#define WM8904_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */ -#define WM8904_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */ -#define WM8904_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */ -#define WM8904_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */ -#define WM8904_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */ -#define WM8904_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */ -#define WM8904_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */ -#define WM8904_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */ -#define WM8904_HPR_ENA 0x0001 /* HPR_ENA */ -#define WM8904_HPR_ENA_MASK 0x0001 /* HPR_ENA */ -#define WM8904_HPR_ENA_SHIFT 0 /* HPR_ENA */ -#define WM8904_HPR_ENA_WIDTH 1 /* HPR_ENA */ - -/* - * R94 (0x5E) - Analogue Lineout 0 - */ -#define WM8904_LINEOUTL_RMV_SHORT 0x0080 /* LINEOUTL_RMV_SHORT */ -#define WM8904_LINEOUTL_RMV_SHORT_MASK 0x0080 /* LINEOUTL_RMV_SHORT */ -#define WM8904_LINEOUTL_RMV_SHORT_SHIFT 7 /* LINEOUTL_RMV_SHORT */ -#define WM8904_LINEOUTL_RMV_SHORT_WIDTH 1 /* LINEOUTL_RMV_SHORT */ -#define WM8904_LINEOUTL_ENA_OUTP 0x0040 /* LINEOUTL_ENA_OUTP */ -#define WM8904_LINEOUTL_ENA_OUTP_MASK 0x0040 /* LINEOUTL_ENA_OUTP */ -#define WM8904_LINEOUTL_ENA_OUTP_SHIFT 6 /* LINEOUTL_ENA_OUTP */ -#define WM8904_LINEOUTL_ENA_OUTP_WIDTH 1 /* LINEOUTL_ENA_OUTP */ -#define WM8904_LINEOUTL_ENA_DLY 0x0020 /* LINEOUTL_ENA_DLY */ -#define WM8904_LINEOUTL_ENA_DLY_MASK 0x0020 /* LINEOUTL_ENA_DLY */ -#define WM8904_LINEOUTL_ENA_DLY_SHIFT 5 /* LINEOUTL_ENA_DLY */ -#define WM8904_LINEOUTL_ENA_DLY_WIDTH 1 /* LINEOUTL_ENA_DLY */ -#define WM8904_LINEOUTL_ENA 0x0010 /* LINEOUTL_ENA */ -#define WM8904_LINEOUTL_ENA_MASK 0x0010 /* LINEOUTL_ENA */ -#define WM8904_LINEOUTL_ENA_SHIFT 4 /* LINEOUTL_ENA */ -#define WM8904_LINEOUTL_ENA_WIDTH 1 /* LINEOUTL_ENA */ -#define WM8904_LINEOUTR_RMV_SHORT 0x0008 /* LINEOUTR_RMV_SHORT */ -#define WM8904_LINEOUTR_RMV_SHORT_MASK 0x0008 /* LINEOUTR_RMV_SHORT */ -#define WM8904_LINEOUTR_RMV_SHORT_SHIFT 3 /* LINEOUTR_RMV_SHORT */ -#define WM8904_LINEOUTR_RMV_SHORT_WIDTH 1 /* LINEOUTR_RMV_SHORT */ -#define WM8904_LINEOUTR_ENA_OUTP 0x0004 /* LINEOUTR_ENA_OUTP */ -#define WM8904_LINEOUTR_ENA_OUTP_MASK 0x0004 /* LINEOUTR_ENA_OUTP */ -#define WM8904_LINEOUTR_ENA_OUTP_SHIFT 2 /* LINEOUTR_ENA_OUTP */ -#define WM8904_LINEOUTR_ENA_OUTP_WIDTH 1 /* LINEOUTR_ENA_OUTP */ -#define WM8904_LINEOUTR_ENA_DLY 0x0002 /* LINEOUTR_ENA_DLY */ -#define WM8904_LINEOUTR_ENA_DLY_MASK 0x0002 /* LINEOUTR_ENA_DLY */ -#define WM8904_LINEOUTR_ENA_DLY_SHIFT 1 /* LINEOUTR_ENA_DLY */ -#define WM8904_LINEOUTR_ENA_DLY_WIDTH 1 /* LINEOUTR_ENA_DLY */ -#define WM8904_LINEOUTR_ENA 0x0001 /* LINEOUTR_ENA */ -#define WM8904_LINEOUTR_ENA_MASK 0x0001 /* LINEOUTR_ENA */ -#define WM8904_LINEOUTR_ENA_SHIFT 0 /* LINEOUTR_ENA */ -#define WM8904_LINEOUTR_ENA_WIDTH 1 /* LINEOUTR_ENA */ - -/* - * R98 (0x62) - Charge Pump 0 - */ -#define WM8904_CP_ENA 0x0001 /* CP_ENA */ -#define WM8904_CP_ENA_MASK 0x0001 /* CP_ENA */ -#define WM8904_CP_ENA_SHIFT 0 /* CP_ENA */ -#define WM8904_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R104 (0x68) - Class W 0 - */ -#define WM8904_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */ -#define WM8904_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */ -#define WM8904_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */ -#define WM8904_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */ - -/* - * R108 (0x6C) - Write Sequencer 0 - */ -#define WM8904_WSEQ_ENA 0x0100 /* WSEQ_ENA */ -#define WM8904_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */ -#define WM8904_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */ -#define WM8904_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8904_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8904_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8904_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ - -/* - * R109 (0x6D) - Write Sequencer 1 - */ -#define WM8904_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8904_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8904_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8904_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */ -#define WM8904_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */ -#define WM8904_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */ -#define WM8904_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM8904_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM8904_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R110 (0x6E) - Write Sequencer 2 - */ -#define WM8904_WSEQ_EOS 0x4000 /* WSEQ_EOS */ -#define WM8904_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */ -#define WM8904_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */ -#define WM8904_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM8904_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */ -#define WM8904_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */ -#define WM8904_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */ -#define WM8904_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM8904_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM8904_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R111 (0x6F) - Write Sequencer 3 - */ -#define WM8904_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM8904_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM8904_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM8904_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8904_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM8904_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM8904_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM8904_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8904_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM8904_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM8904_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R112 (0x70) - Write Sequencer 4 - */ -#define WM8904_WSEQ_CURRENT_INDEX_MASK 0x03F0 /* WSEQ_CURRENT_INDEX - [9:4] */ -#define WM8904_WSEQ_CURRENT_INDEX_SHIFT 4 /* WSEQ_CURRENT_INDEX - [9:4] */ -#define WM8904_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [9:4] */ -#define WM8904_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8904_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8904_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8904_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R116 (0x74) - FLL Control 1 - */ -#define WM8904_FLL_FRACN_ENA 0x0004 /* FLL_FRACN_ENA */ -#define WM8904_FLL_FRACN_ENA_MASK 0x0004 /* FLL_FRACN_ENA */ -#define WM8904_FLL_FRACN_ENA_SHIFT 2 /* FLL_FRACN_ENA */ -#define WM8904_FLL_FRACN_ENA_WIDTH 1 /* FLL_FRACN_ENA */ -#define WM8904_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ -#define WM8904_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ -#define WM8904_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ -#define WM8904_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ -#define WM8904_FLL_ENA 0x0001 /* FLL_ENA */ -#define WM8904_FLL_ENA_MASK 0x0001 /* FLL_ENA */ -#define WM8904_FLL_ENA_SHIFT 0 /* FLL_ENA */ -#define WM8904_FLL_ENA_WIDTH 1 /* FLL_ENA */ - -/* - * R117 (0x75) - FLL Control 2 - */ -#define WM8904_FLL_OUTDIV_MASK 0x3F00 /* FLL_OUTDIV - [13:8] */ -#define WM8904_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [13:8] */ -#define WM8904_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [13:8] */ -#define WM8904_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */ -#define WM8904_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */ -#define WM8904_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */ -#define WM8904_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ -#define WM8904_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ -#define WM8904_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ - -/* - * R118 (0x76) - FLL Control 3 - */ -#define WM8904_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */ -#define WM8904_FLL_K_SHIFT 0 /* FLL_K - [15:0] */ -#define WM8904_FLL_K_WIDTH 16 /* FLL_K - [15:0] */ - -/* - * R119 (0x77) - FLL Control 4 - */ -#define WM8904_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */ -#define WM8904_FLL_N_SHIFT 5 /* FLL_N - [14:5] */ -#define WM8904_FLL_N_WIDTH 10 /* FLL_N - [14:5] */ -#define WM8904_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */ -#define WM8904_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */ -#define WM8904_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */ - -/* - * R120 (0x78) - FLL Control 5 - */ -#define WM8904_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8904_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8904_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8904_FLL_CLK_REF_SRC_MASK 0x0003 /* FLL_CLK_REF_SRC - [1:0] */ -#define WM8904_FLL_CLK_REF_SRC_SHIFT 0 /* FLL_CLK_REF_SRC - [1:0] */ -#define WM8904_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */ - -/* - * R126 (0x7E) - Digital Pulls - */ -#define WM8904_MCLK_PU 0x0080 /* MCLK_PU */ -#define WM8904_MCLK_PU_MASK 0x0080 /* MCLK_PU */ -#define WM8904_MCLK_PU_SHIFT 7 /* MCLK_PU */ -#define WM8904_MCLK_PU_WIDTH 1 /* MCLK_PU */ -#define WM8904_MCLK_PD 0x0040 /* MCLK_PD */ -#define WM8904_MCLK_PD_MASK 0x0040 /* MCLK_PD */ -#define WM8904_MCLK_PD_SHIFT 6 /* MCLK_PD */ -#define WM8904_MCLK_PD_WIDTH 1 /* MCLK_PD */ -#define WM8904_DACDAT_PU 0x0020 /* DACDAT_PU */ -#define WM8904_DACDAT_PU_MASK 0x0020 /* DACDAT_PU */ -#define WM8904_DACDAT_PU_SHIFT 5 /* DACDAT_PU */ -#define WM8904_DACDAT_PU_WIDTH 1 /* DACDAT_PU */ -#define WM8904_DACDAT_PD 0x0010 /* DACDAT_PD */ -#define WM8904_DACDAT_PD_MASK 0x0010 /* DACDAT_PD */ -#define WM8904_DACDAT_PD_SHIFT 4 /* DACDAT_PD */ -#define WM8904_DACDAT_PD_WIDTH 1 /* DACDAT_PD */ -#define WM8904_LRCLK_PU 0x0008 /* LRCLK_PU */ -#define WM8904_LRCLK_PU_MASK 0x0008 /* LRCLK_PU */ -#define WM8904_LRCLK_PU_SHIFT 3 /* LRCLK_PU */ -#define WM8904_LRCLK_PU_WIDTH 1 /* LRCLK_PU */ -#define WM8904_LRCLK_PD 0x0004 /* LRCLK_PD */ -#define WM8904_LRCLK_PD_MASK 0x0004 /* LRCLK_PD */ -#define WM8904_LRCLK_PD_SHIFT 2 /* LRCLK_PD */ -#define WM8904_LRCLK_PD_WIDTH 1 /* LRCLK_PD */ -#define WM8904_BCLK_PU 0x0002 /* BCLK_PU */ -#define WM8904_BCLK_PU_MASK 0x0002 /* BCLK_PU */ -#define WM8904_BCLK_PU_SHIFT 1 /* BCLK_PU */ -#define WM8904_BCLK_PU_WIDTH 1 /* BCLK_PU */ -#define WM8904_BCLK_PD 0x0001 /* BCLK_PD */ -#define WM8904_BCLK_PD_MASK 0x0001 /* BCLK_PD */ -#define WM8904_BCLK_PD_SHIFT 0 /* BCLK_PD */ -#define WM8904_BCLK_PD_WIDTH 1 /* BCLK_PD */ - -/* - * R127 (0x7F) - Interrupt Status - */ -#define WM8904_IRQ 0x0400 /* IRQ */ -#define WM8904_IRQ_MASK 0x0400 /* IRQ */ -#define WM8904_IRQ_SHIFT 10 /* IRQ */ -#define WM8904_IRQ_WIDTH 1 /* IRQ */ -#define WM8904_GPIO_BCLK_EINT 0x0200 /* GPIO_BCLK_EINT */ -#define WM8904_GPIO_BCLK_EINT_MASK 0x0200 /* GPIO_BCLK_EINT */ -#define WM8904_GPIO_BCLK_EINT_SHIFT 9 /* GPIO_BCLK_EINT */ -#define WM8904_GPIO_BCLK_EINT_WIDTH 1 /* GPIO_BCLK_EINT */ -#define WM8904_WSEQ_EINT 0x0100 /* WSEQ_EINT */ -#define WM8904_WSEQ_EINT_MASK 0x0100 /* WSEQ_EINT */ -#define WM8904_WSEQ_EINT_SHIFT 8 /* WSEQ_EINT */ -#define WM8904_WSEQ_EINT_WIDTH 1 /* WSEQ_EINT */ -#define WM8904_GPIO3_EINT 0x0080 /* GPIO3_EINT */ -#define WM8904_GPIO3_EINT_MASK 0x0080 /* GPIO3_EINT */ -#define WM8904_GPIO3_EINT_SHIFT 7 /* GPIO3_EINT */ -#define WM8904_GPIO3_EINT_WIDTH 1 /* GPIO3_EINT */ -#define WM8904_GPIO2_EINT 0x0040 /* GPIO2_EINT */ -#define WM8904_GPIO2_EINT_MASK 0x0040 /* GPIO2_EINT */ -#define WM8904_GPIO2_EINT_SHIFT 6 /* GPIO2_EINT */ -#define WM8904_GPIO2_EINT_WIDTH 1 /* GPIO2_EINT */ -#define WM8904_GPIO1_EINT 0x0020 /* GPIO1_EINT */ -#define WM8904_GPIO1_EINT_MASK 0x0020 /* GPIO1_EINT */ -#define WM8904_GPIO1_EINT_SHIFT 5 /* GPIO1_EINT */ -#define WM8904_GPIO1_EINT_WIDTH 1 /* GPIO1_EINT */ -#define WM8904_GPI8_EINT 0x0010 /* GPI8_EINT */ -#define WM8904_GPI8_EINT_MASK 0x0010 /* GPI8_EINT */ -#define WM8904_GPI8_EINT_SHIFT 4 /* GPI8_EINT */ -#define WM8904_GPI8_EINT_WIDTH 1 /* GPI8_EINT */ -#define WM8904_GPI7_EINT 0x0008 /* GPI7_EINT */ -#define WM8904_GPI7_EINT_MASK 0x0008 /* GPI7_EINT */ -#define WM8904_GPI7_EINT_SHIFT 3 /* GPI7_EINT */ -#define WM8904_GPI7_EINT_WIDTH 1 /* GPI7_EINT */ -#define WM8904_FLL_LOCK_EINT 0x0004 /* FLL_LOCK_EINT */ -#define WM8904_FLL_LOCK_EINT_MASK 0x0004 /* FLL_LOCK_EINT */ -#define WM8904_FLL_LOCK_EINT_SHIFT 2 /* FLL_LOCK_EINT */ -#define WM8904_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ -#define WM8904_MIC_SHRT_EINT 0x0002 /* MIC_SHRT_EINT */ -#define WM8904_MIC_SHRT_EINT_MASK 0x0002 /* MIC_SHRT_EINT */ -#define WM8904_MIC_SHRT_EINT_SHIFT 1 /* MIC_SHRT_EINT */ -#define WM8904_MIC_SHRT_EINT_WIDTH 1 /* MIC_SHRT_EINT */ -#define WM8904_MIC_DET_EINT 0x0001 /* MIC_DET_EINT */ -#define WM8904_MIC_DET_EINT_MASK 0x0001 /* MIC_DET_EINT */ -#define WM8904_MIC_DET_EINT_SHIFT 0 /* MIC_DET_EINT */ -#define WM8904_MIC_DET_EINT_WIDTH 1 /* MIC_DET_EINT */ - -/* - * R128 (0x80) - Interrupt Status Mask - */ -#define WM8904_IM_GPIO_BCLK_EINT 0x0200 /* IM_GPIO_BCLK_EINT */ -#define WM8904_IM_GPIO_BCLK_EINT_MASK 0x0200 /* IM_GPIO_BCLK_EINT */ -#define WM8904_IM_GPIO_BCLK_EINT_SHIFT 9 /* IM_GPIO_BCLK_EINT */ -#define WM8904_IM_GPIO_BCLK_EINT_WIDTH 1 /* IM_GPIO_BCLK_EINT */ -#define WM8904_IM_WSEQ_EINT 0x0100 /* IM_WSEQ_EINT */ -#define WM8904_IM_WSEQ_EINT_MASK 0x0100 /* IM_WSEQ_EINT */ -#define WM8904_IM_WSEQ_EINT_SHIFT 8 /* IM_WSEQ_EINT */ -#define WM8904_IM_WSEQ_EINT_WIDTH 1 /* IM_WSEQ_EINT */ -#define WM8904_IM_GPIO3_EINT 0x0080 /* IM_GPIO3_EINT */ -#define WM8904_IM_GPIO3_EINT_MASK 0x0080 /* IM_GPIO3_EINT */ -#define WM8904_IM_GPIO3_EINT_SHIFT 7 /* IM_GPIO3_EINT */ -#define WM8904_IM_GPIO3_EINT_WIDTH 1 /* IM_GPIO3_EINT */ -#define WM8904_IM_GPIO2_EINT 0x0040 /* IM_GPIO2_EINT */ -#define WM8904_IM_GPIO2_EINT_MASK 0x0040 /* IM_GPIO2_EINT */ -#define WM8904_IM_GPIO2_EINT_SHIFT 6 /* IM_GPIO2_EINT */ -#define WM8904_IM_GPIO2_EINT_WIDTH 1 /* IM_GPIO2_EINT */ -#define WM8904_IM_GPIO1_EINT 0x0020 /* IM_GPIO1_EINT */ -#define WM8904_IM_GPIO1_EINT_MASK 0x0020 /* IM_GPIO1_EINT */ -#define WM8904_IM_GPIO1_EINT_SHIFT 5 /* IM_GPIO1_EINT */ -#define WM8904_IM_GPIO1_EINT_WIDTH 1 /* IM_GPIO1_EINT */ -#define WM8904_IM_GPI8_EINT 0x0010 /* IM_GPI8_EINT */ -#define WM8904_IM_GPI8_EINT_MASK 0x0010 /* IM_GPI8_EINT */ -#define WM8904_IM_GPI8_EINT_SHIFT 4 /* IM_GPI8_EINT */ -#define WM8904_IM_GPI8_EINT_WIDTH 1 /* IM_GPI8_EINT */ -#define WM8904_IM_GPI7_EINT 0x0008 /* IM_GPI7_EINT */ -#define WM8904_IM_GPI7_EINT_MASK 0x0008 /* IM_GPI7_EINT */ -#define WM8904_IM_GPI7_EINT_SHIFT 3 /* IM_GPI7_EINT */ -#define WM8904_IM_GPI7_EINT_WIDTH 1 /* IM_GPI7_EINT */ -#define WM8904_IM_FLL_LOCK_EINT 0x0004 /* IM_FLL_LOCK_EINT */ -#define WM8904_IM_FLL_LOCK_EINT_MASK 0x0004 /* IM_FLL_LOCK_EINT */ -#define WM8904_IM_FLL_LOCK_EINT_SHIFT 2 /* IM_FLL_LOCK_EINT */ -#define WM8904_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ -#define WM8904_IM_MIC_SHRT_EINT 0x0002 /* IM_MIC_SHRT_EINT */ -#define WM8904_IM_MIC_SHRT_EINT_MASK 0x0002 /* IM_MIC_SHRT_EINT */ -#define WM8904_IM_MIC_SHRT_EINT_SHIFT 1 /* IM_MIC_SHRT_EINT */ -#define WM8904_IM_MIC_SHRT_EINT_WIDTH 1 /* IM_MIC_SHRT_EINT */ -#define WM8904_IM_MIC_DET_EINT 0x0001 /* IM_MIC_DET_EINT */ -#define WM8904_IM_MIC_DET_EINT_MASK 0x0001 /* IM_MIC_DET_EINT */ -#define WM8904_IM_MIC_DET_EINT_SHIFT 0 /* IM_MIC_DET_EINT */ -#define WM8904_IM_MIC_DET_EINT_WIDTH 1 /* IM_MIC_DET_EINT */ - -/* - * R129 (0x81) - Interrupt Polarity - */ -#define WM8904_GPIO_BCLK_EINT_POL 0x0200 /* GPIO_BCLK_EINT_POL */ -#define WM8904_GPIO_BCLK_EINT_POL_MASK 0x0200 /* GPIO_BCLK_EINT_POL */ -#define WM8904_GPIO_BCLK_EINT_POL_SHIFT 9 /* GPIO_BCLK_EINT_POL */ -#define WM8904_GPIO_BCLK_EINT_POL_WIDTH 1 /* GPIO_BCLK_EINT_POL */ -#define WM8904_WSEQ_EINT_POL 0x0100 /* WSEQ_EINT_POL */ -#define WM8904_WSEQ_EINT_POL_MASK 0x0100 /* WSEQ_EINT_POL */ -#define WM8904_WSEQ_EINT_POL_SHIFT 8 /* WSEQ_EINT_POL */ -#define WM8904_WSEQ_EINT_POL_WIDTH 1 /* WSEQ_EINT_POL */ -#define WM8904_GPIO3_EINT_POL 0x0080 /* GPIO3_EINT_POL */ -#define WM8904_GPIO3_EINT_POL_MASK 0x0080 /* GPIO3_EINT_POL */ -#define WM8904_GPIO3_EINT_POL_SHIFT 7 /* GPIO3_EINT_POL */ -#define WM8904_GPIO3_EINT_POL_WIDTH 1 /* GPIO3_EINT_POL */ -#define WM8904_GPIO2_EINT_POL 0x0040 /* GPIO2_EINT_POL */ -#define WM8904_GPIO2_EINT_POL_MASK 0x0040 /* GPIO2_EINT_POL */ -#define WM8904_GPIO2_EINT_POL_SHIFT 6 /* GPIO2_EINT_POL */ -#define WM8904_GPIO2_EINT_POL_WIDTH 1 /* GPIO2_EINT_POL */ -#define WM8904_GPIO1_EINT_POL 0x0020 /* GPIO1_EINT_POL */ -#define WM8904_GPIO1_EINT_POL_MASK 0x0020 /* GPIO1_EINT_POL */ -#define WM8904_GPIO1_EINT_POL_SHIFT 5 /* GPIO1_EINT_POL */ -#define WM8904_GPIO1_EINT_POL_WIDTH 1 /* GPIO1_EINT_POL */ -#define WM8904_GPI8_EINT_POL 0x0010 /* GPI8_EINT_POL */ -#define WM8904_GPI8_EINT_POL_MASK 0x0010 /* GPI8_EINT_POL */ -#define WM8904_GPI8_EINT_POL_SHIFT 4 /* GPI8_EINT_POL */ -#define WM8904_GPI8_EINT_POL_WIDTH 1 /* GPI8_EINT_POL */ -#define WM8904_GPI7_EINT_POL 0x0008 /* GPI7_EINT_POL */ -#define WM8904_GPI7_EINT_POL_MASK 0x0008 /* GPI7_EINT_POL */ -#define WM8904_GPI7_EINT_POL_SHIFT 3 /* GPI7_EINT_POL */ -#define WM8904_GPI7_EINT_POL_WIDTH 1 /* GPI7_EINT_POL */ -#define WM8904_FLL_LOCK_EINT_POL 0x0004 /* FLL_LOCK_EINT_POL */ -#define WM8904_FLL_LOCK_EINT_POL_MASK 0x0004 /* FLL_LOCK_EINT_POL */ -#define WM8904_FLL_LOCK_EINT_POL_SHIFT 2 /* FLL_LOCK_EINT_POL */ -#define WM8904_FLL_LOCK_EINT_POL_WIDTH 1 /* FLL_LOCK_EINT_POL */ -#define WM8904_MIC_SHRT_EINT_POL 0x0002 /* MIC_SHRT_EINT_POL */ -#define WM8904_MIC_SHRT_EINT_POL_MASK 0x0002 /* MIC_SHRT_EINT_POL */ -#define WM8904_MIC_SHRT_EINT_POL_SHIFT 1 /* MIC_SHRT_EINT_POL */ -#define WM8904_MIC_SHRT_EINT_POL_WIDTH 1 /* MIC_SHRT_EINT_POL */ -#define WM8904_MIC_DET_EINT_POL 0x0001 /* MIC_DET_EINT_POL */ -#define WM8904_MIC_DET_EINT_POL_MASK 0x0001 /* MIC_DET_EINT_POL */ -#define WM8904_MIC_DET_EINT_POL_SHIFT 0 /* MIC_DET_EINT_POL */ -#define WM8904_MIC_DET_EINT_POL_WIDTH 1 /* MIC_DET_EINT_POL */ - -/* - * R130 (0x82) - Interrupt Debounce - */ -#define WM8904_GPIO_BCLK_EINT_DB 0x0200 /* GPIO_BCLK_EINT_DB */ -#define WM8904_GPIO_BCLK_EINT_DB_MASK 0x0200 /* GPIO_BCLK_EINT_DB */ -#define WM8904_GPIO_BCLK_EINT_DB_SHIFT 9 /* GPIO_BCLK_EINT_DB */ -#define WM8904_GPIO_BCLK_EINT_DB_WIDTH 1 /* GPIO_BCLK_EINT_DB */ -#define WM8904_WSEQ_EINT_DB 0x0100 /* WSEQ_EINT_DB */ -#define WM8904_WSEQ_EINT_DB_MASK 0x0100 /* WSEQ_EINT_DB */ -#define WM8904_WSEQ_EINT_DB_SHIFT 8 /* WSEQ_EINT_DB */ -#define WM8904_WSEQ_EINT_DB_WIDTH 1 /* WSEQ_EINT_DB */ -#define WM8904_GPIO3_EINT_DB 0x0080 /* GPIO3_EINT_DB */ -#define WM8904_GPIO3_EINT_DB_MASK 0x0080 /* GPIO3_EINT_DB */ -#define WM8904_GPIO3_EINT_DB_SHIFT 7 /* GPIO3_EINT_DB */ -#define WM8904_GPIO3_EINT_DB_WIDTH 1 /* GPIO3_EINT_DB */ -#define WM8904_GPIO2_EINT_DB 0x0040 /* GPIO2_EINT_DB */ -#define WM8904_GPIO2_EINT_DB_MASK 0x0040 /* GPIO2_EINT_DB */ -#define WM8904_GPIO2_EINT_DB_SHIFT 6 /* GPIO2_EINT_DB */ -#define WM8904_GPIO2_EINT_DB_WIDTH 1 /* GPIO2_EINT_DB */ -#define WM8904_GPIO1_EINT_DB 0x0020 /* GPIO1_EINT_DB */ -#define WM8904_GPIO1_EINT_DB_MASK 0x0020 /* GPIO1_EINT_DB */ -#define WM8904_GPIO1_EINT_DB_SHIFT 5 /* GPIO1_EINT_DB */ -#define WM8904_GPIO1_EINT_DB_WIDTH 1 /* GPIO1_EINT_DB */ -#define WM8904_GPI8_EINT_DB 0x0010 /* GPI8_EINT_DB */ -#define WM8904_GPI8_EINT_DB_MASK 0x0010 /* GPI8_EINT_DB */ -#define WM8904_GPI8_EINT_DB_SHIFT 4 /* GPI8_EINT_DB */ -#define WM8904_GPI8_EINT_DB_WIDTH 1 /* GPI8_EINT_DB */ -#define WM8904_GPI7_EINT_DB 0x0008 /* GPI7_EINT_DB */ -#define WM8904_GPI7_EINT_DB_MASK 0x0008 /* GPI7_EINT_DB */ -#define WM8904_GPI7_EINT_DB_SHIFT 3 /* GPI7_EINT_DB */ -#define WM8904_GPI7_EINT_DB_WIDTH 1 /* GPI7_EINT_DB */ -#define WM8904_FLL_LOCK_EINT_DB 0x0004 /* FLL_LOCK_EINT_DB */ -#define WM8904_FLL_LOCK_EINT_DB_MASK 0x0004 /* FLL_LOCK_EINT_DB */ -#define WM8904_FLL_LOCK_EINT_DB_SHIFT 2 /* FLL_LOCK_EINT_DB */ -#define WM8904_FLL_LOCK_EINT_DB_WIDTH 1 /* FLL_LOCK_EINT_DB */ -#define WM8904_MIC_SHRT_EINT_DB 0x0002 /* MIC_SHRT_EINT_DB */ -#define WM8904_MIC_SHRT_EINT_DB_MASK 0x0002 /* MIC_SHRT_EINT_DB */ -#define WM8904_MIC_SHRT_EINT_DB_SHIFT 1 /* MIC_SHRT_EINT_DB */ -#define WM8904_MIC_SHRT_EINT_DB_WIDTH 1 /* MIC_SHRT_EINT_DB */ -#define WM8904_MIC_DET_EINT_DB 0x0001 /* MIC_DET_EINT_DB */ -#define WM8904_MIC_DET_EINT_DB_MASK 0x0001 /* MIC_DET_EINT_DB */ -#define WM8904_MIC_DET_EINT_DB_SHIFT 0 /* MIC_DET_EINT_DB */ -#define WM8904_MIC_DET_EINT_DB_WIDTH 1 /* MIC_DET_EINT_DB */ - -/* - * R134 (0x86) - EQ1 - */ -#define WM8904_EQ_ENA 0x0001 /* EQ_ENA */ -#define WM8904_EQ_ENA_MASK 0x0001 /* EQ_ENA */ -#define WM8904_EQ_ENA_SHIFT 0 /* EQ_ENA */ -#define WM8904_EQ_ENA_WIDTH 1 /* EQ_ENA */ - -/* - * R135 (0x87) - EQ2 - */ -#define WM8904_EQ_B1_GAIN_MASK 0x001F /* EQ_B1_GAIN - [4:0] */ -#define WM8904_EQ_B1_GAIN_SHIFT 0 /* EQ_B1_GAIN - [4:0] */ -#define WM8904_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [4:0] */ - -/* - * R136 (0x88) - EQ3 - */ -#define WM8904_EQ_B2_GAIN_MASK 0x001F /* EQ_B2_GAIN - [4:0] */ -#define WM8904_EQ_B2_GAIN_SHIFT 0 /* EQ_B2_GAIN - [4:0] */ -#define WM8904_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [4:0] */ - -/* - * R137 (0x89) - EQ4 - */ -#define WM8904_EQ_B3_GAIN_MASK 0x001F /* EQ_B3_GAIN - [4:0] */ -#define WM8904_EQ_B3_GAIN_SHIFT 0 /* EQ_B3_GAIN - [4:0] */ -#define WM8904_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [4:0] */ - -/* - * R138 (0x8A) - EQ5 - */ -#define WM8904_EQ_B4_GAIN_MASK 0x001F /* EQ_B4_GAIN - [4:0] */ -#define WM8904_EQ_B4_GAIN_SHIFT 0 /* EQ_B4_GAIN - [4:0] */ -#define WM8904_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [4:0] */ - -/* - * R139 (0x8B) - EQ6 - */ -#define WM8904_EQ_B5_GAIN_MASK 0x001F /* EQ_B5_GAIN - [4:0] */ -#define WM8904_EQ_B5_GAIN_SHIFT 0 /* EQ_B5_GAIN - [4:0] */ -#define WM8904_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [4:0] */ - -/* - * R140 (0x8C) - EQ7 - */ -#define WM8904_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */ -#define WM8904_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */ -#define WM8904_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */ - -/* - * R141 (0x8D) - EQ8 - */ -#define WM8904_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */ -#define WM8904_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */ -#define WM8904_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */ - -/* - * R142 (0x8E) - EQ9 - */ -#define WM8904_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */ -#define WM8904_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */ -#define WM8904_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */ - -/* - * R143 (0x8F) - EQ10 - */ -#define WM8904_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */ -#define WM8904_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */ -#define WM8904_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */ - -/* - * R144 (0x90) - EQ11 - */ -#define WM8904_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */ -#define WM8904_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */ -#define WM8904_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */ - -/* - * R145 (0x91) - EQ12 - */ -#define WM8904_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */ -#define WM8904_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */ -#define WM8904_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */ - -/* - * R146 (0x92) - EQ13 - */ -#define WM8904_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */ -#define WM8904_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */ -#define WM8904_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */ - -/* - * R147 (0x93) - EQ14 - */ -#define WM8904_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */ -#define WM8904_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */ -#define WM8904_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */ - -/* - * R148 (0x94) - EQ15 - */ -#define WM8904_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */ -#define WM8904_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */ -#define WM8904_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */ - -/* - * R149 (0x95) - EQ16 - */ -#define WM8904_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */ -#define WM8904_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */ -#define WM8904_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */ - -/* - * R150 (0x96) - EQ17 - */ -#define WM8904_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */ -#define WM8904_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */ -#define WM8904_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */ - -/* - * R151 (0x97) - EQ18 - */ -#define WM8904_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */ -#define WM8904_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */ -#define WM8904_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */ - -/* - * R152 (0x98) - EQ19 - */ -#define WM8904_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */ -#define WM8904_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */ -#define WM8904_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */ - -/* - * R153 (0x99) - EQ20 - */ -#define WM8904_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */ -#define WM8904_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */ -#define WM8904_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */ - -/* - * R154 (0x9A) - EQ21 - */ -#define WM8904_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */ -#define WM8904_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */ -#define WM8904_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */ - -/* - * R155 (0x9B) - EQ22 - */ -#define WM8904_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */ -#define WM8904_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */ -#define WM8904_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */ - -/* - * R156 (0x9C) - EQ23 - */ -#define WM8904_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */ -#define WM8904_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */ -#define WM8904_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */ - -/* - * R157 (0x9D) - EQ24 - */ -#define WM8904_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */ -#define WM8904_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */ -#define WM8904_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */ - -/* - * R161 (0xA1) - Control Interface Test 1 - */ -#define WM8904_USER_KEY 0x0002 /* USER_KEY */ -#define WM8904_USER_KEY_MASK 0x0002 /* USER_KEY */ -#define WM8904_USER_KEY_SHIFT 1 /* USER_KEY */ -#define WM8904_USER_KEY_WIDTH 1 /* USER_KEY */ - -/* - * R198 (0xC6) - ADC Test 0 - */ -#define WM8904_ADC_128_OSR_TST_MODE 0x0004 /* ADC_128_OSR_TST_MODE */ -#define WM8904_ADC_128_OSR_TST_MODE_SHIFT 2 /* ADC_128_OSR_TST_MODE */ -#define WM8904_ADC_128_OSR_TST_MODE_WIDTH 1 /* ADC_128_OSR_TST_MODE */ -#define WM8904_ADC_BIASX1P5 0x0001 /* ADC_BIASX1P5 */ -#define WM8904_ADC_BIASX1P5_SHIFT 0 /* ADC_BIASX1P5 */ -#define WM8904_ADC_BIASX1P5_WIDTH 1 /* ADC_BIASX1P5 */ - -/* - * R204 (0xCC) - Analogue Output Bias 0 - */ -#define WM8904_PGA_BIAS_MASK 0x0070 /* PGA_BIAS - [6:4] */ -#define WM8904_PGA_BIAS_SHIFT 4 /* PGA_BIAS - [6:4] */ -#define WM8904_PGA_BIAS_WIDTH 3 /* PGA_BIAS - [6:4] */ - -/* - * R247 (0xF7) - FLL NCO Test 0 - */ -#define WM8904_FLL_FRC_NCO 0x0001 /* FLL_FRC_NCO */ -#define WM8904_FLL_FRC_NCO_MASK 0x0001 /* FLL_FRC_NCO */ -#define WM8904_FLL_FRC_NCO_SHIFT 0 /* FLL_FRC_NCO */ -#define WM8904_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ - -/* - * R248 (0xF8) - FLL NCO Test 1 - */ -#define WM8904_FLL_FRC_NCO_VAL_MASK 0x003F /* FLL_FRC_NCO_VAL - [5:0] */ -#define WM8904_FLL_FRC_NCO_VAL_SHIFT 0 /* FLL_FRC_NCO_VAL - [5:0] */ -#define WM8904_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [5:0] */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8940.c b/ANDROID_3.4.5/sound/soc/codecs/wm8940.c deleted file mode 100644 index d2883aff..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8940.c +++ /dev/null @@ -1,809 +0,0 @@ -/* - * wm8940.c -- WM8940 ALSA Soc Audio driver - * - * Author: Jonathan Cameron - * - * Based on wm8510.c - * Copyright 2006 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Not currently handled: - * Notch filter control - * AUXMode (inverting vs mixer) - * No means to obtain current gain if alc enabled. - * No use made of gpio - * Fast VMID discharge for power down - * Soft Start - * DLR and ALR Swaps not enabled - * Digital Sidetone not supported - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8940.h" - -struct wm8940_priv { - unsigned int sysclk; - enum snd_soc_control_type control_type; -}; - -static int wm8940_volatile_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - switch (reg) { - case WM8940_SOFTRESET: - return 1; - default: - return 0; - } -} - -static u16 wm8940_reg_defaults[] = { - 0x8940, /* Soft Reset */ - 0x0000, /* Power 1 */ - 0x0000, /* Power 2 */ - 0x0000, /* Power 3 */ - 0x0010, /* Interface Control */ - 0x0000, /* Companding Control */ - 0x0140, /* Clock Control */ - 0x0000, /* Additional Controls */ - 0x0000, /* GPIO Control */ - 0x0002, /* Auto Increment Control */ - 0x0000, /* DAC Control */ - 0x00FF, /* DAC Volume */ - 0, - 0, - 0x0100, /* ADC Control */ - 0x00FF, /* ADC Volume */ - 0x0000, /* Notch Filter 1 Control 1 */ - 0x0000, /* Notch Filter 1 Control 2 */ - 0x0000, /* Notch Filter 2 Control 1 */ - 0x0000, /* Notch Filter 2 Control 2 */ - 0x0000, /* Notch Filter 3 Control 1 */ - 0x0000, /* Notch Filter 3 Control 2 */ - 0x0000, /* Notch Filter 4 Control 1 */ - 0x0000, /* Notch Filter 4 Control 2 */ - 0x0032, /* DAC Limit Control 1 */ - 0x0000, /* DAC Limit Control 2 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0x0038, /* ALC Control 1 */ - 0x000B, /* ALC Control 2 */ - 0x0032, /* ALC Control 3 */ - 0x0000, /* Noise Gate */ - 0x0041, /* PLLN */ - 0x000C, /* PLLK1 */ - 0x0093, /* PLLK2 */ - 0x00E9, /* PLLK3 */ - 0, - 0, - 0x0030, /* ALC Control 4 */ - 0, - 0x0002, /* Input Control */ - 0x0050, /* PGA Gain */ - 0, - 0x0002, /* ADC Boost Control */ - 0, - 0x0002, /* Output Control */ - 0x0000, /* Speaker Mixer Control */ - 0, - 0, - 0, - 0x0079, /* Speaker Volume */ - 0, - 0x0000, /* Mono Mixer Control */ -}; - -static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; -static const struct soc_enum wm8940_adc_companding_enum -= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding); -static const struct soc_enum wm8940_dac_companding_enum -= SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 3, 4, wm8940_companding); - -static const char *wm8940_alc_mode_text[] = {"ALC", "Limiter"}; -static const struct soc_enum wm8940_alc_mode_enum -= SOC_ENUM_SINGLE(WM8940_ALC3, 8, 2, wm8940_alc_mode_text); - -static const char *wm8940_mic_bias_level_text[] = {"0.9", "0.65"}; -static const struct soc_enum wm8940_mic_bias_level_enum -= SOC_ENUM_SINGLE(WM8940_INPUTCTL, 8, 2, wm8940_mic_bias_level_text); - -static const char *wm8940_filter_mode_text[] = {"Audio", "Application"}; -static const struct soc_enum wm8940_filter_mode_enum -= SOC_ENUM_SINGLE(WM8940_ADC, 7, 2, wm8940_filter_mode_text); - -static DECLARE_TLV_DB_SCALE(wm8940_spk_vol_tlv, -5700, 100, 1); -static DECLARE_TLV_DB_SCALE(wm8940_att_tlv, -1000, 1000, 0); -static DECLARE_TLV_DB_SCALE(wm8940_pga_vol_tlv, -1200, 75, 0); -static DECLARE_TLV_DB_SCALE(wm8940_alc_min_tlv, -1200, 600, 0); -static DECLARE_TLV_DB_SCALE(wm8940_alc_max_tlv, 675, 600, 0); -static DECLARE_TLV_DB_SCALE(wm8940_alc_tar_tlv, -2250, 50, 0); -static DECLARE_TLV_DB_SCALE(wm8940_lim_boost_tlv, 0, 100, 0); -static DECLARE_TLV_DB_SCALE(wm8940_lim_thresh_tlv, -600, 100, 0); -static DECLARE_TLV_DB_SCALE(wm8940_adc_tlv, -12750, 50, 1); -static DECLARE_TLV_DB_SCALE(wm8940_capture_boost_vol_tlv, 0, 2000, 0); - -static const struct snd_kcontrol_new wm8940_snd_controls[] = { - SOC_SINGLE("Digital Loopback Switch", WM8940_COMPANDINGCTL, - 6, 1, 0), - SOC_ENUM("DAC Companding", wm8940_dac_companding_enum), - SOC_ENUM("ADC Companding", wm8940_adc_companding_enum), - - SOC_ENUM("ALC Mode", wm8940_alc_mode_enum), - SOC_SINGLE("ALC Switch", WM8940_ALC1, 8, 1, 0), - SOC_SINGLE_TLV("ALC Capture Max Gain", WM8940_ALC1, - 3, 7, 1, wm8940_alc_max_tlv), - SOC_SINGLE_TLV("ALC Capture Min Gain", WM8940_ALC1, - 0, 7, 0, wm8940_alc_min_tlv), - SOC_SINGLE_TLV("ALC Capture Target", WM8940_ALC2, - 0, 14, 0, wm8940_alc_tar_tlv), - SOC_SINGLE("ALC Capture Hold", WM8940_ALC2, 4, 10, 0), - SOC_SINGLE("ALC Capture Decay", WM8940_ALC3, 4, 10, 0), - SOC_SINGLE("ALC Capture Attach", WM8940_ALC3, 0, 10, 0), - SOC_SINGLE("ALC ZC Switch", WM8940_ALC4, 1, 1, 0), - SOC_SINGLE("ALC Capture Noise Gate Switch", WM8940_NOISEGATE, - 3, 1, 0), - SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8940_NOISEGATE, - 0, 7, 0), - - SOC_SINGLE("DAC Playback Limiter Switch", WM8940_DACLIM1, 8, 1, 0), - SOC_SINGLE("DAC Playback Limiter Attack", WM8940_DACLIM1, 0, 9, 0), - SOC_SINGLE("DAC Playback Limiter Decay", WM8940_DACLIM1, 4, 11, 0), - SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8940_DACLIM2, - 4, 9, 1, wm8940_lim_thresh_tlv), - SOC_SINGLE_TLV("DAC Playback Limiter Boost", WM8940_DACLIM2, - 0, 12, 0, wm8940_lim_boost_tlv), - - SOC_SINGLE("Capture PGA ZC Switch", WM8940_PGAGAIN, 7, 1, 0), - SOC_SINGLE_TLV("Capture PGA Volume", WM8940_PGAGAIN, - 0, 63, 0, wm8940_pga_vol_tlv), - SOC_SINGLE_TLV("Digital Playback Volume", WM8940_DACVOL, - 0, 255, 0, wm8940_adc_tlv), - SOC_SINGLE_TLV("Digital Capture Volume", WM8940_ADCVOL, - 0, 255, 0, wm8940_adc_tlv), - SOC_ENUM("Mic Bias Level", wm8940_mic_bias_level_enum), - SOC_SINGLE_TLV("Capture Boost Volue", WM8940_ADCBOOST, - 8, 1, 0, wm8940_capture_boost_vol_tlv), - SOC_SINGLE_TLV("Speaker Playback Volume", WM8940_SPKVOL, - 0, 63, 0, wm8940_spk_vol_tlv), - SOC_SINGLE("Speaker Playback Switch", WM8940_SPKVOL, 6, 1, 1), - - SOC_SINGLE_TLV("Speaker Mixer Line Bypass Volume", WM8940_SPKVOL, - 8, 1, 1, wm8940_att_tlv), - SOC_SINGLE("Speaker Playback ZC Switch", WM8940_SPKVOL, 7, 1, 0), - - SOC_SINGLE("Mono Out Switch", WM8940_MONOMIX, 6, 1, 1), - SOC_SINGLE_TLV("Mono Mixer Line Bypass Volume", WM8940_MONOMIX, - 7, 1, 1, wm8940_att_tlv), - - SOC_SINGLE("High Pass Filter Switch", WM8940_ADC, 8, 1, 0), - SOC_ENUM("High Pass Filter Mode", wm8940_filter_mode_enum), - SOC_SINGLE("High Pass Filter Cut Off", WM8940_ADC, 4, 7, 0), - SOC_SINGLE("ADC Inversion Switch", WM8940_ADC, 0, 1, 0), - SOC_SINGLE("DAC Inversion Switch", WM8940_DAC, 0, 1, 0), - SOC_SINGLE("DAC Auto Mute Switch", WM8940_DAC, 2, 1, 0), - SOC_SINGLE("ZC Timeout Clock Switch", WM8940_ADDCNTRL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new wm8940_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_SPKMIX, 1, 1, 0), - SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_SPKMIX, 5, 1, 0), - SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_SPKMIX, 0, 1, 0), -}; - -static const struct snd_kcontrol_new wm8940_mono_mixer_controls[] = { - SOC_DAPM_SINGLE("Line Bypass Switch", WM8940_MONOMIX, 1, 1, 0), - SOC_DAPM_SINGLE("Aux Playback Switch", WM8940_MONOMIX, 2, 1, 0), - SOC_DAPM_SINGLE("PCM Playback Switch", WM8940_MONOMIX, 0, 1, 0), -}; - -static DECLARE_TLV_DB_SCALE(wm8940_boost_vol_tlv, -1500, 300, 1); -static const struct snd_kcontrol_new wm8940_input_boost_controls[] = { - SOC_DAPM_SINGLE("Mic PGA Switch", WM8940_PGAGAIN, 6, 1, 1), - SOC_DAPM_SINGLE_TLV("Aux Volume", WM8940_ADCBOOST, - 0, 7, 0, wm8940_boost_vol_tlv), - SOC_DAPM_SINGLE_TLV("Mic Volume", WM8940_ADCBOOST, - 4, 7, 0, wm8940_boost_vol_tlv), -}; - -static const struct snd_kcontrol_new wm8940_micpga_controls[] = { - SOC_DAPM_SINGLE("AUX Switch", WM8940_INPUTCTL, 2, 1, 0), - SOC_DAPM_SINGLE("MICP Switch", WM8940_INPUTCTL, 0, 1, 0), - SOC_DAPM_SINGLE("MICN Switch", WM8940_INPUTCTL, 1, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = { - SND_SOC_DAPM_MIXER("Speaker Mixer", WM8940_POWER3, 2, 0, - &wm8940_speaker_mixer_controls[0], - ARRAY_SIZE(wm8940_speaker_mixer_controls)), - SND_SOC_DAPM_MIXER("Mono Mixer", WM8940_POWER3, 3, 0, - &wm8940_mono_mixer_controls[0], - ARRAY_SIZE(wm8940_mono_mixer_controls)), - SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8940_POWER3, 0, 0), - - SND_SOC_DAPM_PGA("SpkN Out", WM8940_POWER3, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("SpkP Out", WM8940_POWER3, 6, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mono Out", WM8940_POWER3, 7, 0, NULL, 0), - SND_SOC_DAPM_OUTPUT("MONOOUT"), - SND_SOC_DAPM_OUTPUT("SPKOUTP"), - SND_SOC_DAPM_OUTPUT("SPKOUTN"), - - SND_SOC_DAPM_PGA("Aux Input", WM8940_POWER1, 6, 0, NULL, 0), - SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8940_POWER2, 0, 0), - SND_SOC_DAPM_MIXER("Mic PGA", WM8940_POWER2, 2, 0, - &wm8940_micpga_controls[0], - ARRAY_SIZE(wm8940_micpga_controls)), - SND_SOC_DAPM_MIXER("Boost Mixer", WM8940_POWER2, 4, 0, - &wm8940_input_boost_controls[0], - ARRAY_SIZE(wm8940_input_boost_controls)), - SND_SOC_DAPM_MICBIAS("Mic Bias", WM8940_POWER1, 4, 0), - - SND_SOC_DAPM_INPUT("MICN"), - SND_SOC_DAPM_INPUT("MICP"), - SND_SOC_DAPM_INPUT("AUX"), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Mono output mixer */ - {"Mono Mixer", "PCM Playback Switch", "DAC"}, - {"Mono Mixer", "Aux Playback Switch", "Aux Input"}, - {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"}, - - /* Speaker output mixer */ - {"Speaker Mixer", "PCM Playback Switch", "DAC"}, - {"Speaker Mixer", "Aux Playback Switch", "Aux Input"}, - {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"}, - - /* Outputs */ - {"Mono Out", NULL, "Mono Mixer"}, - {"MONOOUT", NULL, "Mono Out"}, - {"SpkN Out", NULL, "Speaker Mixer"}, - {"SpkP Out", NULL, "Speaker Mixer"}, - {"SPKOUTN", NULL, "SpkN Out"}, - {"SPKOUTP", NULL, "SpkP Out"}, - - /* Microphone PGA */ - {"Mic PGA", "MICN Switch", "MICN"}, - {"Mic PGA", "MICP Switch", "MICP"}, - {"Mic PGA", "AUX Switch", "AUX"}, - - /* Boost Mixer */ - {"Boost Mixer", "Mic PGA Switch", "Mic PGA"}, - {"Boost Mixer", "Mic Volume", "MICP"}, - {"Boost Mixer", "Aux Volume", "Aux Input"}, - - {"ADC", NULL, "Boost Mixer"}, -}; - -static int wm8940_add_widgets(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - ret = snd_soc_dapm_new_controls(dapm, wm8940_dapm_widgets, - ARRAY_SIZE(wm8940_dapm_widgets)); - if (ret) - goto error_ret; - ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - -error_ret: - return ret; -} - -#define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0); - -static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFE67; - u16 clk = snd_soc_read(codec, WM8940_CLOCK) & 0x1fe; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - clk |= 1; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - snd_soc_write(codec, WM8940_CLOCK, clk); - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= (2 << 3); - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= (1 << 3); - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= (3 << 3); - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= (3 << 3) | (1 << 7); - break; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= (1 << 7); - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= (1 << 8); - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= (1 << 8) | (1 << 7); - break; - } - - snd_soc_write(codec, WM8940_IFACE, iface); - - return 0; -} - -static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; - u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; - u16 companding = snd_soc_read(codec, - WM8940_COMPANDINGCTL) & 0xFFDF; - int ret; - - /* LoutR control */ - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE - && params_channels(params) == 2) - iface |= (1 << 9); - - switch (params_rate(params)) { - case 8000: - addcntrl |= (0x5 << 1); - break; - case 11025: - addcntrl |= (0x4 << 1); - break; - case 16000: - addcntrl |= (0x3 << 1); - break; - case 22050: - addcntrl |= (0x2 << 1); - break; - case 32000: - addcntrl |= (0x1 << 1); - break; - case 44100: - case 48000: - break; - } - ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl); - if (ret) - goto error_ret; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - companding = companding | (1 << 5); - break; - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= (1 << 5); - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= (2 << 5); - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= (3 << 5); - break; - } - ret = snd_soc_write(codec, WM8940_COMPANDINGCTL, companding); - if (ret) - goto error_ret; - ret = snd_soc_write(codec, WM8940_IFACE, iface); - -error_ret: - return ret; -} - -static int wm8940_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8940_DAC) & 0xffbf; - - if (mute) - mute_reg |= 0x40; - - return snd_soc_write(codec, WM8940_DAC, mute_reg); -} - -static int wm8940_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 val; - u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0; - int ret = 0; - - switch (level) { - case SND_SOC_BIAS_ON: - /* ensure bufioen and biasen */ - pwr_reg |= (1 << 2) | (1 << 3); - /* Enable thermal shutdown */ - val = snd_soc_read(codec, WM8940_OUTPUTCTL); - ret = snd_soc_write(codec, WM8940_OUTPUTCTL, val | 0x2); - if (ret) - break; - /* set vmid to 75k */ - ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); - break; - case SND_SOC_BIAS_PREPARE: - /* ensure bufioen and biasen */ - pwr_reg |= (1 << 2) | (1 << 3); - ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to sync cache: %d\n", ret); - return ret; - } - } - - /* ensure bufioen and biasen */ - pwr_reg |= (1 << 2) | (1 << 3); - /* set vmid to 300k for standby */ - ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x2); - break; - case SND_SOC_BIAS_OFF: - ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg); - break; - } - - codec->dapm.bias_level = level; - - return ret; -} - -struct pll_ { - unsigned int pre_scale:2; - unsigned int n:4; - unsigned int k; -}; - -static struct pll_ pll_div; - -/* The size in bits of the pll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 24) * 10) -static void pll_factors(unsigned int target, unsigned int source) -{ - unsigned long long Kpart; - unsigned int K, Ndiv, Nmod; - /* The left shift ist to avoid accuracy loss when right shifting */ - Ndiv = target / source; - - if (Ndiv > 12) { - source <<= 1; - /* Multiply by 2 */ - pll_div.pre_scale = 0; - Ndiv = target / source; - } else if (Ndiv < 3) { - source >>= 2; - /* Divide by 4 */ - pll_div.pre_scale = 3; - Ndiv = target / source; - } else if (Ndiv < 6) { - source >>= 1; - /* divide by 2 */ - pll_div.pre_scale = 2; - Ndiv = target / source; - } else - pll_div.pre_scale = 1; - - if ((Ndiv < 6) || (Ndiv > 12)) - printk(KERN_WARNING - "WM8940 N value %d outwith recommended range!d\n", - Ndiv); - - pll_div.n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div.k = K; -} - -/* Untested at the moment */ -static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - /* Turn off PLL */ - reg = snd_soc_read(codec, WM8940_POWER1); - snd_soc_write(codec, WM8940_POWER1, reg & 0x1df); - - if (freq_in == 0 || freq_out == 0) { - /* Clock CODEC directly from MCLK */ - reg = snd_soc_read(codec, WM8940_CLOCK); - snd_soc_write(codec, WM8940_CLOCK, reg & 0x0ff); - /* Pll power down */ - snd_soc_write(codec, WM8940_PLLN, (1 << 7)); - return 0; - } - - /* Pll is followed by a frequency divide by 4 */ - pll_factors(freq_out*4, freq_in); - if (pll_div.k) - snd_soc_write(codec, WM8940_PLLN, - (pll_div.pre_scale << 4) | pll_div.n | (1 << 6)); - else /* No factional component */ - snd_soc_write(codec, WM8940_PLLN, - (pll_div.pre_scale << 4) | pll_div.n); - snd_soc_write(codec, WM8940_PLLK1, pll_div.k >> 18); - snd_soc_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff); - /* Enable the PLL */ - reg = snd_soc_read(codec, WM8940_POWER1); - snd_soc_write(codec, WM8940_POWER1, reg | 0x020); - - /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_read(codec, WM8940_CLOCK); - snd_soc_write(codec, WM8940_CLOCK, reg | 0x100); - - return 0; -} - -static int wm8940_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - wm8940->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - int ret = 0; - - switch (div_id) { - case WM8940_BCLKDIV: - reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFE3; - ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2)); - break; - case WM8940_MCLKDIV: - reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFF1F; - ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5)); - break; - case WM8940_OPCLKDIV: - reg = snd_soc_read(codec, WM8940_GPIO) & 0xFFCF; - ret = snd_soc_write(codec, WM8940_GPIO, reg | (div << 4)); - break; - } - return ret; -} - -#define WM8940_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM8940_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8940_dai_ops = { - .hw_params = wm8940_i2s_hw_params, - .set_sysclk = wm8940_set_dai_sysclk, - .digital_mute = wm8940_mute, - .set_fmt = wm8940_set_dai_fmt, - .set_clkdiv = wm8940_set_dai_clkdiv, - .set_pll = wm8940_set_dai_pll, -}; - -static struct snd_soc_dai_driver wm8940_dai = { - .name = "wm8940-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8940_RATES, - .formats = WM8940_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8940_RATES, - .formats = WM8940_FORMATS, - }, - .ops = &wm8940_dai_ops, - .symmetric_rates = 1, -}; - -static int wm8940_suspend(struct snd_soc_codec *codec) -{ - return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); -} - -static int wm8940_resume(struct snd_soc_codec *codec) -{ - wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int wm8940_probe(struct snd_soc_codec *codec) -{ - struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); - struct wm8940_setup_data *pdata = codec->dev->platform_data; - int ret; - u16 reg; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = wm8940_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - ret = snd_soc_write(codec, WM8940_POWER1, 0x180); - if (ret < 0) - return ret; - - if (!pdata) - dev_warn(codec->dev, "No platform data supplied\n"); - else { - reg = snd_soc_read(codec, WM8940_OUTPUTCTL); - ret = snd_soc_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi); - if (ret < 0) - return ret; - } - - ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls, - ARRAY_SIZE(wm8940_snd_controls)); - if (ret) - return ret; - ret = wm8940_add_widgets(codec); - return ret; -} - -static int wm8940_remove(struct snd_soc_codec *codec) -{ - wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { - .probe = wm8940_probe, - .remove = wm8940_remove, - .suspend = wm8940_suspend, - .resume = wm8940_resume, - .set_bias_level = wm8940_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8940_reg_defaults, - .volatile_register = wm8940_volatile_register, -}; - -static __devinit int wm8940_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8940_priv *wm8940; - int ret; - - wm8940 = devm_kzalloc(&i2c->dev, sizeof(struct wm8940_priv), - GFP_KERNEL); - if (wm8940 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8940); - wm8940->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8940, &wm8940_dai, 1); - - return ret; -} - -static __devexit int wm8940_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - - return 0; -} - -static const struct i2c_device_id wm8940_i2c_id[] = { - { "wm8940", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id); - -static struct i2c_driver wm8940_i2c_driver = { - .driver = { - .name = "wm8940", - .owner = THIS_MODULE, - }, - .probe = wm8940_i2c_probe, - .remove = __devexit_p(wm8940_i2c_remove), - .id_table = wm8940_i2c_id, -}; - -static int __init wm8940_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8940_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8940_modinit); - -static void __exit wm8940_exit(void) -{ - i2c_del_driver(&wm8940_i2c_driver); -} -module_exit(wm8940_exit); - -MODULE_DESCRIPTION("ASoC WM8940 driver"); -MODULE_AUTHOR("Jonathan Cameron"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8940.h b/ANDROID_3.4.5/sound/soc/codecs/wm8940.h deleted file mode 100644 index 907fe192..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8940.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * wm8940.h -- WM8940 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8940_H -#define _WM8940_H - -struct wm8940_setup_data { - /* Vref to analogue output resistance */ -#define WM8940_VROI_1K 0 -#define WM8940_VROI_30K 1 - unsigned int vroi:1; -}; - -/* WM8940 register space */ -#define WM8940_SOFTRESET 0x00 -#define WM8940_POWER1 0x01 -#define WM8940_POWER2 0x02 -#define WM8940_POWER3 0x03 -#define WM8940_IFACE 0x04 -#define WM8940_COMPANDINGCTL 0x05 -#define WM8940_CLOCK 0x06 -#define WM8940_ADDCNTRL 0x07 -#define WM8940_GPIO 0x08 -#define WM8940_CTLINT 0x09 -#define WM8940_DAC 0x0A -#define WM8940_DACVOL 0x0B - -#define WM8940_ADC 0x0E -#define WM8940_ADCVOL 0x0F -#define WM8940_NOTCH1 0x10 -#define WM8940_NOTCH2 0x11 -#define WM8940_NOTCH3 0x12 -#define WM8940_NOTCH4 0x13 -#define WM8940_NOTCH5 0x14 -#define WM8940_NOTCH6 0x15 -#define WM8940_NOTCH7 0x16 -#define WM8940_NOTCH8 0x17 -#define WM8940_DACLIM1 0x18 -#define WM8940_DACLIM2 0x19 - -#define WM8940_ALC1 0x20 -#define WM8940_ALC2 0x21 -#define WM8940_ALC3 0x22 -#define WM8940_NOISEGATE 0x23 -#define WM8940_PLLN 0x24 -#define WM8940_PLLK1 0x25 -#define WM8940_PLLK2 0x26 -#define WM8940_PLLK3 0x27 - -#define WM8940_ALC4 0x2A - -#define WM8940_INPUTCTL 0x2C -#define WM8940_PGAGAIN 0x2D - -#define WM8940_ADCBOOST 0x2F - -#define WM8940_OUTPUTCTL 0x31 -#define WM8940_SPKMIX 0x32 - -#define WM8940_SPKVOL 0x36 - -#define WM8940_MONOMIX 0x38 - -#define WM8940_CACHEREGNUM 0x57 - - -/* Clock divider Id's */ -#define WM8940_BCLKDIV 0 -#define WM8940_MCLKDIV 1 -#define WM8940_OPCLKDIV 2 - -/* MCLK clock dividers */ -#define WM8940_MCLKDIV_1 0 -#define WM8940_MCLKDIV_1_5 1 -#define WM8940_MCLKDIV_2 2 -#define WM8940_MCLKDIV_3 3 -#define WM8940_MCLKDIV_4 4 -#define WM8940_MCLKDIV_6 5 -#define WM8940_MCLKDIV_8 6 -#define WM8940_MCLKDIV_12 7 - -/* BCLK clock dividers */ -#define WM8940_BCLKDIV_1 0 -#define WM8940_BCLKDIV_2 1 -#define WM8940_BCLKDIV_4 2 -#define WM8940_BCLKDIV_8 3 -#define WM8940_BCLKDIV_16 4 -#define WM8940_BCLKDIV_32 5 - -/* PLL Out Dividers */ -#define WM8940_OPCLKDIV_1 0 -#define WM8940_OPCLKDIV_2 1 -#define WM8940_OPCLKDIV_3 2 -#define WM8940_OPCLKDIV_4 3 - -#endif /* _WM8940_H */ - diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8955.c b/ANDROID_3.4.5/sound/soc/codecs/wm8955.c deleted file mode 100644 index 61fe9743..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8955.c +++ /dev/null @@ -1,1094 +0,0 @@ -/* - * wm8955.c -- WM8955 ALSA SoC Audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8955.h" - -#define WM8955_NUM_SUPPLIES 4 -static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { - "DCVDD", - "DBVDD", - "HPVDD", - "AVDD", -}; - -/* codec private data */ -struct wm8955_priv { - struct regmap *regmap; - - unsigned int mclk_rate; - - int deemph; - int fs; - - struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; -}; - -static const struct reg_default wm8955_reg_defaults[] = { - { 2, 0x0079 }, /* R2 - LOUT1 volume */ - { 3, 0x0079 }, /* R3 - ROUT1 volume */ - { 5, 0x0008 }, /* R5 - DAC Control */ - { 7, 0x000A }, /* R7 - Audio Interface */ - { 8, 0x0000 }, /* R8 - Sample Rate */ - { 10, 0x00FF }, /* R10 - Left DAC volume */ - { 11, 0x00FF }, /* R11 - Right DAC volume */ - { 12, 0x000F }, /* R12 - Bass control */ - { 13, 0x000F }, /* R13 - Treble control */ - { 23, 0x00C1 }, /* R23 - Additional control (1) */ - { 24, 0x0000 }, /* R24 - Additional control (2) */ - { 25, 0x0000 }, /* R25 - Power Management (1) */ - { 26, 0x0000 }, /* R26 - Power Management (2) */ - { 27, 0x0000 }, /* R27 - Additional Control (3) */ - { 34, 0x0050 }, /* R34 - Left out Mix (1) */ - { 35, 0x0050 }, /* R35 - Left out Mix (2) */ - { 36, 0x0050 }, /* R36 - Right out Mix (1) */ - { 37, 0x0050 }, /* R37 - Right Out Mix (2) */ - { 38, 0x0050 }, /* R38 - Mono out Mix (1) */ - { 39, 0x0050 }, /* R39 - Mono out Mix (2) */ - { 40, 0x0079 }, /* R40 - LOUT2 volume */ - { 41, 0x0079 }, /* R41 - ROUT2 volume */ - { 42, 0x0079 }, /* R42 - MONOOUT volume */ - { 43, 0x0000 }, /* R43 - Clocking / PLL */ - { 44, 0x0103 }, /* R44 - PLL Control 1 */ - { 45, 0x0024 }, /* R45 - PLL Control 2 */ - { 46, 0x01BA }, /* R46 - PLL Control 3 */ - { 59, 0x0000 }, /* R59 - PLL Control 4 */ -}; - -static bool wm8955_writeable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8955_LOUT1_VOLUME: - case WM8955_ROUT1_VOLUME: - case WM8955_DAC_CONTROL: - case WM8955_AUDIO_INTERFACE: - case WM8955_SAMPLE_RATE: - case WM8955_LEFT_DAC_VOLUME: - case WM8955_RIGHT_DAC_VOLUME: - case WM8955_BASS_CONTROL: - case WM8955_TREBLE_CONTROL: - case WM8955_RESET: - case WM8955_ADDITIONAL_CONTROL_1: - case WM8955_ADDITIONAL_CONTROL_2: - case WM8955_POWER_MANAGEMENT_1: - case WM8955_POWER_MANAGEMENT_2: - case WM8955_ADDITIONAL_CONTROL_3: - case WM8955_LEFT_OUT_MIX_1: - case WM8955_LEFT_OUT_MIX_2: - case WM8955_RIGHT_OUT_MIX_1: - case WM8955_RIGHT_OUT_MIX_2: - case WM8955_MONO_OUT_MIX_1: - case WM8955_MONO_OUT_MIX_2: - case WM8955_LOUT2_VOLUME: - case WM8955_ROUT2_VOLUME: - case WM8955_MONOOUT_VOLUME: - case WM8955_CLOCKING_PLL: - case WM8955_PLL_CONTROL_1: - case WM8955_PLL_CONTROL_2: - case WM8955_PLL_CONTROL_3: - case WM8955_PLL_CONTROL_4: - return true; - default: - return false; - } -} - -static bool wm8955_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8955_RESET: - return true; - default: - return false; - } -} - -static int wm8955_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8955_RESET, 0); -} - -struct pll_factors { - int n; - int k; - int outdiv; -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 22) * 10) - -static int wm8995_pll_factors(struct device *dev, - int Fref, int Fout, struct pll_factors *pll) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod, target; - - dev_dbg(dev, "Fref=%u Fout=%u\n", Fref, Fout); - - /* The oscilator should run at should be 90-100MHz, and - * there's a divide by 4 plus an optional divide by 2 in the - * output path to generate the system clock. The clock table - * is sortd so we should always generate a suitable target. */ - target = Fout * 4; - if (target < 90000000) { - pll->outdiv = 1; - target *= 2; - } else { - pll->outdiv = 0; - } - - WARN_ON(target < 90000000 || target > 100000000); - - dev_dbg(dev, "Fvco=%dHz\n", target); - - /* Now, calculate N.K */ - Ndiv = target / Fref; - - pll->n = Ndiv; - Nmod = target % Fref; - dev_dbg(dev, "Nmod=%d\n", Nmod); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, Fref); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - pll->k = K / 10; - - dev_dbg(dev, "N=%x K=%x OUTDIV=%x\n", pll->n, pll->k, pll->outdiv); - - return 0; -} - -/* Lookup table specifying SRATE (table 25 in datasheet); some of the - * output frequencies have been rounded to the standard frequencies - * they are intended to match where the error is slight. */ -static struct { - int mclk; - int fs; - int usb; - int sr; -} clock_cfgs[] = { - { 18432000, 8000, 0, 3, }, - { 18432000, 12000, 0, 9, }, - { 18432000, 16000, 0, 11, }, - { 18432000, 24000, 0, 29, }, - { 18432000, 32000, 0, 13, }, - { 18432000, 48000, 0, 1, }, - { 18432000, 96000, 0, 15, }, - - { 16934400, 8018, 0, 19, }, - { 16934400, 11025, 0, 25, }, - { 16934400, 22050, 0, 27, }, - { 16934400, 44100, 0, 17, }, - { 16934400, 88200, 0, 31, }, - - { 12000000, 8000, 1, 2, }, - { 12000000, 11025, 1, 25, }, - { 12000000, 12000, 1, 8, }, - { 12000000, 16000, 1, 10, }, - { 12000000, 22050, 1, 27, }, - { 12000000, 24000, 1, 28, }, - { 12000000, 32000, 1, 12, }, - { 12000000, 44100, 1, 17, }, - { 12000000, 48000, 1, 0, }, - { 12000000, 88200, 1, 31, }, - { 12000000, 96000, 1, 14, }, - - { 12288000, 8000, 0, 2, }, - { 12288000, 12000, 0, 8, }, - { 12288000, 16000, 0, 10, }, - { 12288000, 24000, 0, 28, }, - { 12288000, 32000, 0, 12, }, - { 12288000, 48000, 0, 0, }, - { 12288000, 96000, 0, 14, }, - - { 12289600, 8018, 0, 18, }, - { 12289600, 11025, 0, 24, }, - { 12289600, 22050, 0, 26, }, - { 11289600, 44100, 0, 16, }, - { 11289600, 88200, 0, 31, }, -}; - -static int wm8955_configure_clocking(struct snd_soc_codec *codec) -{ - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - int i, ret, val; - int clocking = 0; - int srate = 0; - int sr = -1; - struct pll_factors pll; - - /* If we're not running a sample rate currently just pick one */ - if (wm8955->fs == 0) - wm8955->fs = 8000; - - /* Can we generate an exact output? */ - for (i = 0; i < ARRAY_SIZE(clock_cfgs); i++) { - if (wm8955->fs != clock_cfgs[i].fs) - continue; - sr = i; - - if (wm8955->mclk_rate == clock_cfgs[i].mclk) - break; - } - - /* We should never get here with an unsupported sample rate */ - if (sr == -1) { - dev_err(codec->dev, "Sample rate %dHz unsupported\n", - wm8955->fs); - WARN_ON(sr == -1); - return -EINVAL; - } - - if (i == ARRAY_SIZE(clock_cfgs)) { - /* If we can't generate the right clock from MCLK then - * we should configure the PLL to supply us with an - * appropriate clock. - */ - clocking |= WM8955_MCLKSEL; - - /* Use the last divider configuration we saw for the - * sample rate. */ - ret = wm8995_pll_factors(codec->dev, wm8955->mclk_rate, - clock_cfgs[sr].mclk, &pll); - if (ret != 0) { - dev_err(codec->dev, - "Unable to generate %dHz from %dHz MCLK\n", - wm8955->fs, wm8955->mclk_rate); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8955_PLL_CONTROL_1, - WM8955_N_MASK | WM8955_K_21_18_MASK, - (pll.n << WM8955_N_SHIFT) | - pll.k >> 18); - snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, - WM8955_K_17_9_MASK, - (pll.k >> 9) & WM8955_K_17_9_MASK); - snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, - WM8955_K_8_0_MASK, - pll.k & WM8955_K_8_0_MASK); - if (pll.k) - snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4, - WM8955_KEN, WM8955_KEN); - else - snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4, - WM8955_KEN, 0); - - if (pll.outdiv) - val = WM8955_PLL_RB | WM8955_PLLOUTDIV2; - else - val = WM8955_PLL_RB; - - /* Now start the PLL running */ - snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, - WM8955_PLL_RB | WM8955_PLLOUTDIV2, val); - snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, - WM8955_PLLEN, WM8955_PLLEN); - } - - srate = clock_cfgs[sr].usb | (clock_cfgs[sr].sr << WM8955_SR_SHIFT); - - snd_soc_update_bits(codec, WM8955_SAMPLE_RATE, - WM8955_USB | WM8955_SR_MASK, srate); - snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, - WM8955_MCLKSEL, clocking); - - return 0; -} - -static int wm8955_sysclk(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - int ret = 0; - - /* Always disable the clocks - if we're doing reconfiguration this - * avoids misclocking. - */ - snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, - WM8955_DIGENB, 0); - snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, - WM8955_PLL_RB | WM8955_PLLEN, 0); - - switch (event) { - case SND_SOC_DAPM_POST_PMD: - break; - case SND_SOC_DAPM_PRE_PMU: - ret = wm8955_configure_clocking(codec); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int deemph_settings[] = { 0, 32000, 44100, 48000 }; - -static int wm8955_set_deemph(struct snd_soc_codec *codec) -{ - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - int val, i, best; - - /* If we're using deemphasis select the nearest available sample - * rate. - */ - if (wm8955->deemph) { - best = 1; - for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { - if (abs(deemph_settings[i] - wm8955->fs) < - abs(deemph_settings[best] - wm8955->fs)) - best = i; - } - - val = best << WM8955_DEEMPH_SHIFT; - } else { - val = 0; - } - - dev_dbg(codec->dev, "Set deemphasis %d\n", val); - - return snd_soc_update_bits(codec, WM8955_DAC_CONTROL, - WM8955_DEEMPH_MASK, val); -} - -static int wm8955_get_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8955->deemph; - return 0; -} - -static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - int deemph = ucontrol->value.enumerated.item[0]; - - if (deemph > 1) - return -EINVAL; - - wm8955->deemph = deemph; - - return wm8955_set_deemph(codec); -} - -static const char *bass_mode_text[] = { - "Linear", "Adaptive", -}; - -static const struct soc_enum bass_mode = - SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text); - -static const char *bass_cutoff_text[] = { - "Low", "High" -}; - -static const struct soc_enum bass_cutoff = - SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text); - -static const char *treble_cutoff_text[] = { - "High", "Low" -}; - -static const struct soc_enum treble_cutoff = - SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text); - -static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(mono_tlv, -2100, 300, 0); -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(treble_tlv, -1200, 150, 1); - -static const struct snd_kcontrol_new wm8955_snd_controls[] = { -SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8955_LEFT_DAC_VOLUME, - WM8955_RIGHT_DAC_VOLUME, 0, 255, 0, digital_tlv), -SOC_SINGLE_TLV("Playback Attenuation Volume", WM8955_DAC_CONTROL, 7, 1, 1, - atten_tlv), -SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, - wm8955_get_deemph, wm8955_put_deemph), - -SOC_ENUM("Bass Mode", bass_mode), -SOC_ENUM("Bass Cutoff", bass_cutoff), -SOC_SINGLE("Bass Volume", WM8955_BASS_CONTROL, 0, 15, 1), - -SOC_ENUM("Treble Cutoff", treble_cutoff), -SOC_SINGLE_TLV("Treble Volume", WM8955_TREBLE_CONTROL, 0, 14, 1, treble_tlv), - -SOC_SINGLE_TLV("Left Bypass Volume", WM8955_LEFT_OUT_MIX_1, 4, 7, 1, - bypass_tlv), -SOC_SINGLE_TLV("Left Mono Volume", WM8955_LEFT_OUT_MIX_2, 4, 7, 1, - bypass_tlv), - -SOC_SINGLE_TLV("Right Mono Volume", WM8955_RIGHT_OUT_MIX_1, 4, 7, 1, - bypass_tlv), -SOC_SINGLE_TLV("Right Bypass Volume", WM8955_RIGHT_OUT_MIX_2, 4, 7, 1, - bypass_tlv), - -/* Not a stereo pair so they line up with the DAPM switches */ -SOC_SINGLE_TLV("Mono Left Bypass Volume", WM8955_MONO_OUT_MIX_1, 4, 7, 1, - mono_tlv), -SOC_SINGLE_TLV("Mono Right Bypass Volume", WM8955_MONO_OUT_MIX_2, 4, 7, 1, - mono_tlv), - -SOC_DOUBLE_R_TLV("Headphone Volume", WM8955_LOUT1_VOLUME, - WM8955_ROUT1_VOLUME, 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Headphone ZC Switch", WM8955_LOUT1_VOLUME, - WM8955_ROUT1_VOLUME, 7, 1, 0), - -SOC_DOUBLE_R_TLV("Speaker Volume", WM8955_LOUT2_VOLUME, - WM8955_ROUT2_VOLUME, 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Speaker ZC Switch", WM8955_LOUT2_VOLUME, - WM8955_ROUT2_VOLUME, 7, 1, 0), - -SOC_SINGLE_TLV("Mono Volume", WM8955_MONOOUT_VOLUME, 0, 127, 0, out_tlv), -SOC_SINGLE("Mono ZC Switch", WM8955_MONOOUT_VOLUME, 7, 1, 0), -}; - -static const struct snd_kcontrol_new lmixer[] = { -SOC_DAPM_SINGLE("Playback Switch", WM8955_LEFT_OUT_MIX_1, 8, 1, 0), -SOC_DAPM_SINGLE("Bypass Switch", WM8955_LEFT_OUT_MIX_1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", WM8955_LEFT_OUT_MIX_2, 8, 1, 0), -SOC_DAPM_SINGLE("Mono Switch", WM8955_LEFT_OUT_MIX_2, 7, 1, 0), -}; - -static const struct snd_kcontrol_new rmixer[] = { -SOC_DAPM_SINGLE("Left Playback Switch", WM8955_RIGHT_OUT_MIX_1, 8, 1, 0), -SOC_DAPM_SINGLE("Mono Switch", WM8955_RIGHT_OUT_MIX_1, 7, 1, 0), -SOC_DAPM_SINGLE("Playback Switch", WM8955_RIGHT_OUT_MIX_2, 8, 1, 0), -SOC_DAPM_SINGLE("Bypass Switch", WM8955_RIGHT_OUT_MIX_2, 7, 1, 0), -}; - -static const struct snd_kcontrol_new mmixer[] = { -SOC_DAPM_SINGLE("Left Playback Switch", WM8955_MONO_OUT_MIX_1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8955_MONO_OUT_MIX_1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", WM8955_MONO_OUT_MIX_2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8955_MONO_OUT_MIX_2, 7, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8955_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("MONOIN-"), -SND_SOC_DAPM_INPUT("MONOIN+"), -SND_SOC_DAPM_INPUT("LINEINR"), -SND_SOC_DAPM_INPUT("LINEINL"), - -SND_SOC_DAPM_PGA("Mono Input", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_SUPPLY("SYSCLK", WM8955_POWER_MANAGEMENT_1, 0, 1, wm8955_sysclk, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_SUPPLY("TSDEN", WM8955_ADDITIONAL_CONTROL_1, 8, 0, NULL, 0), - -SND_SOC_DAPM_DAC("DACL", "Playback", WM8955_POWER_MANAGEMENT_2, 8, 0), -SND_SOC_DAPM_DAC("DACR", "Playback", WM8955_POWER_MANAGEMENT_2, 7, 0), - -SND_SOC_DAPM_PGA("LOUT1 PGA", WM8955_POWER_MANAGEMENT_2, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("ROUT1 PGA", WM8955_POWER_MANAGEMENT_2, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("LOUT2 PGA", WM8955_POWER_MANAGEMENT_2, 4, 0, NULL, 0), -SND_SOC_DAPM_PGA("ROUT2 PGA", WM8955_POWER_MANAGEMENT_2, 3, 0, NULL, 0), -SND_SOC_DAPM_PGA("MOUT PGA", WM8955_POWER_MANAGEMENT_2, 2, 0, NULL, 0), -SND_SOC_DAPM_PGA("OUT3 PGA", WM8955_POWER_MANAGEMENT_2, 1, 0, NULL, 0), - -/* The names are chosen to make the control names nice */ -SND_SOC_DAPM_MIXER("Left", SND_SOC_NOPM, 0, 0, - lmixer, ARRAY_SIZE(lmixer)), -SND_SOC_DAPM_MIXER("Right", SND_SOC_NOPM, 0, 0, - rmixer, ARRAY_SIZE(rmixer)), -SND_SOC_DAPM_MIXER("Mono", SND_SOC_NOPM, 0, 0, - mmixer, ARRAY_SIZE(mmixer)), - -SND_SOC_DAPM_OUTPUT("LOUT1"), -SND_SOC_DAPM_OUTPUT("ROUT1"), -SND_SOC_DAPM_OUTPUT("LOUT2"), -SND_SOC_DAPM_OUTPUT("ROUT2"), -SND_SOC_DAPM_OUTPUT("MONOOUT"), -SND_SOC_DAPM_OUTPUT("OUT3"), -}; - -static const struct snd_soc_dapm_route wm8955_dapm_routes[] = { - { "DACL", NULL, "SYSCLK" }, - { "DACR", NULL, "SYSCLK" }, - - { "Mono Input", NULL, "MONOIN-" }, - { "Mono Input", NULL, "MONOIN+" }, - - { "Left", "Playback Switch", "DACL" }, - { "Left", "Right Playback Switch", "DACR" }, - { "Left", "Bypass Switch", "LINEINL" }, - { "Left", "Mono Switch", "Mono Input" }, - - { "Right", "Playback Switch", "DACR" }, - { "Right", "Left Playback Switch", "DACL" }, - { "Right", "Bypass Switch", "LINEINR" }, - { "Right", "Mono Switch", "Mono Input" }, - - { "Mono", "Left Playback Switch", "DACL" }, - { "Mono", "Right Playback Switch", "DACR" }, - { "Mono", "Left Bypass Switch", "LINEINL" }, - { "Mono", "Right Bypass Switch", "LINEINR" }, - - { "LOUT1 PGA", NULL, "Left" }, - { "LOUT1", NULL, "TSDEN" }, - { "LOUT1", NULL, "LOUT1 PGA" }, - - { "ROUT1 PGA", NULL, "Right" }, - { "ROUT1", NULL, "TSDEN" }, - { "ROUT1", NULL, "ROUT1 PGA" }, - - { "LOUT2 PGA", NULL, "Left" }, - { "LOUT2", NULL, "TSDEN" }, - { "LOUT2", NULL, "LOUT2 PGA" }, - - { "ROUT2 PGA", NULL, "Right" }, - { "ROUT2", NULL, "TSDEN" }, - { "ROUT2", NULL, "ROUT2 PGA" }, - - { "MOUT PGA", NULL, "Mono" }, - { "MONOOUT", NULL, "MOUT PGA" }, - - /* OUT3 not currently implemented */ - { "OUT3", NULL, "OUT3 PGA" }, -}; - -static int wm8955_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - int ret; - int wl; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - wl = 0; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - wl = 0x4; - break; - case SNDRV_PCM_FORMAT_S24_LE: - wl = 0x8; - break; - case SNDRV_PCM_FORMAT_S32_LE: - wl = 0xc; - break; - default: - return -EINVAL; - } - snd_soc_update_bits(codec, WM8955_AUDIO_INTERFACE, - WM8955_WL_MASK, wl); - - wm8955->fs = params_rate(params); - wm8955_set_deemph(codec); - - /* If the chip is clocked then disable the clocks and force a - * reconfiguration, otherwise DAPM will power up the - * clocks for us later. */ - ret = snd_soc_read(codec, WM8955_POWER_MANAGEMENT_1); - if (ret < 0) - return ret; - if (ret & WM8955_DIGENB) { - snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, - WM8955_DIGENB, 0); - snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, - WM8955_PLL_RB | WM8955_PLLEN, 0); - - wm8955_configure_clocking(codec); - } - - return 0; -} - - -static int wm8955_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8955_priv *priv = snd_soc_codec_get_drvdata(codec); - int div; - - switch (clk_id) { - case WM8955_CLK_MCLK: - if (freq > 15000000) { - priv->mclk_rate = freq /= 2; - div = WM8955_MCLKDIV2; - } else { - priv->mclk_rate = freq; - div = 0; - } - - snd_soc_update_bits(codec, WM8955_SAMPLE_RATE, - WM8955_MCLKDIV2, div); - break; - - default: - return -EINVAL; - } - - dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); - - return 0; -} - -static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - u16 aif = 0; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBM_CFM: - aif |= WM8955_MS; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif |= WM8955_LRP; - case SND_SOC_DAIFMT_DSP_A: - aif |= 0x3; - break; - case SND_SOC_DAIFMT_I2S: - aif |= 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif |= 0x1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif |= WM8955_BCLKINV; - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif |= WM8955_BCLKINV | WM8955_LRP; - break; - case SND_SOC_DAIFMT_IB_NF: - aif |= WM8955_BCLKINV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif |= WM8955_LRP; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8955_AUDIO_INTERFACE, - WM8955_MS | WM8955_FORMAT_MASK | WM8955_BCLKINV | - WM8955_LRP, aif); - - return 0; -} - - -static int wm8955_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int val; - - if (mute) - val = WM8955_DACMU; - else - val = 0; - - snd_soc_update_bits(codec, WM8955_DAC_CONTROL, WM8955_DACMU, val); - - return 0; -} - -static int wm8955_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID resistance 2*50k */ - snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, - WM8955_VMIDSEL_MASK, - 0x1 << WM8955_VMIDSEL_SHIFT); - - /* Default bias current */ - snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_1, - WM8955_VSEL_MASK, - 0x2 << WM8955_VSEL_SHIFT); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), - wm8955->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - - regcache_sync(wm8955->regmap); - - /* Enable VREF and VMID */ - snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, - WM8955_VREF | - WM8955_VMIDSEL_MASK, - WM8955_VREF | - 0x3 << WM8955_VREF_SHIFT); - - /* Let VMID ramp */ - msleep(500); - - /* High resistance VROI to maintain outputs */ - snd_soc_update_bits(codec, - WM8955_ADDITIONAL_CONTROL_3, - WM8955_VROI, WM8955_VROI); - } - - /* Maintain VMID with 2*250k */ - snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, - WM8955_VMIDSEL_MASK, - 0x2 << WM8955_VMIDSEL_SHIFT); - - /* Minimum bias current */ - snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_1, - WM8955_VSEL_MASK, 0); - break; - - case SND_SOC_BIAS_OFF: - /* Low resistance VROI to help discharge */ - snd_soc_update_bits(codec, - WM8955_ADDITIONAL_CONTROL_3, - WM8955_VROI, 0); - - /* Turn off VMID and VREF */ - snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, - WM8955_VREF | - WM8955_VMIDSEL_MASK, 0); - - regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), - wm8955->supplies); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8955_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8955_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8955_dai_ops = { - .set_sysclk = wm8955_set_sysclk, - .set_fmt = wm8955_set_fmt, - .hw_params = wm8955_hw_params, - .digital_mute = wm8955_digital_mute, -}; - -static struct snd_soc_dai_driver wm8955_dai = { - .name = "wm8955-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8955_RATES, - .formats = WM8955_FORMATS, - }, - .ops = &wm8955_dai_ops, -}; - -#ifdef CONFIG_PM -static int wm8955_suspend(struct snd_soc_codec *codec) -{ - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - - wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); - - regcache_mark_dirty(wm8955->regmap); - - return 0; -} - -static int wm8955_resume(struct snd_soc_codec *codec) -{ - wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8955_suspend NULL -#define wm8955_resume NULL -#endif - -static int wm8955_probe(struct snd_soc_codec *codec) -{ - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); - int ret, i; - - codec->control_data = wm8955->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) - wm8955->supplies[i].supply = wm8955_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8955->supplies), - wm8955->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), - wm8955->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = wm8955_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err_enable; - } - - /* Change some default settings - latch VU and enable ZC */ - snd_soc_update_bits(codec, WM8955_LEFT_DAC_VOLUME, - WM8955_LDVU, WM8955_LDVU); - snd_soc_update_bits(codec, WM8955_RIGHT_DAC_VOLUME, - WM8955_RDVU, WM8955_RDVU); - snd_soc_update_bits(codec, WM8955_LOUT1_VOLUME, - WM8955_LO1VU | WM8955_LO1ZC, - WM8955_LO1VU | WM8955_LO1ZC); - snd_soc_update_bits(codec, WM8955_ROUT1_VOLUME, - WM8955_RO1VU | WM8955_RO1ZC, - WM8955_RO1VU | WM8955_RO1ZC); - snd_soc_update_bits(codec, WM8955_LOUT2_VOLUME, - WM8955_LO2VU | WM8955_LO2ZC, - WM8955_LO2VU | WM8955_LO2ZC); - snd_soc_update_bits(codec, WM8955_ROUT2_VOLUME, - WM8955_RO2VU | WM8955_RO2ZC, - WM8955_RO2VU | WM8955_RO2ZC); - snd_soc_update_bits(codec, WM8955_MONOOUT_VOLUME, - WM8955_MOZC, WM8955_MOZC); - - /* Also enable adaptive bass boost by default */ - snd_soc_update_bits(codec, WM8955_BASS_CONTROL, WM8955_BB, WM8955_BB); - - /* Set platform data values */ - if (pdata) { - if (pdata->out2_speaker) - snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2, - WM8955_ROUT2INV, WM8955_ROUT2INV); - - if (pdata->monoin_diff) - snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1, - WM8955_DMEN, WM8955_DMEN); - } - - wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); - - return 0; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); - return ret; -} - -static int wm8955_remove(struct snd_soc_codec *codec) -{ - struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - - wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { - .probe = wm8955_probe, - .remove = wm8955_remove, - .suspend = wm8955_suspend, - .resume = wm8955_resume, - .set_bias_level = wm8955_set_bias_level, - - .controls = wm8955_snd_controls, - .num_controls = ARRAY_SIZE(wm8955_snd_controls), - .dapm_widgets = wm8955_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets), - .dapm_routes = wm8955_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes), -}; - -static const struct regmap_config wm8955_regmap = { - .reg_bits = 7, - .val_bits = 9, - - .max_register = WM8955_MAX_REGISTER, - .volatile_reg = wm8955_volatile, - .writeable_reg = wm8955_writeable, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8955_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults), -}; - -static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8955_priv *wm8955; - int ret; - - wm8955 = devm_kzalloc(&i2c->dev, sizeof(struct wm8955_priv), - GFP_KERNEL); - if (wm8955 == NULL) - return -ENOMEM; - - wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap); - if (IS_ERR(wm8955->regmap)) { - ret = PTR_ERR(wm8955->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - - i2c_set_clientdata(i2c, wm8955); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8955, &wm8955_dai, 1); - if (ret != 0) - goto err; - - return ret; - -err: - regmap_exit(wm8955->regmap); - return ret; -} - -static __devexit int wm8955_i2c_remove(struct i2c_client *client) -{ - struct wm8955_priv *wm8955 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8955->regmap); - - return 0; -} - -static const struct i2c_device_id wm8955_i2c_id[] = { - { "wm8955", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); - -static struct i2c_driver wm8955_i2c_driver = { - .driver = { - .name = "wm8955", - .owner = THIS_MODULE, - }, - .probe = wm8955_i2c_probe, - .remove = __devexit_p(wm8955_i2c_remove), - .id_table = wm8955_i2c_id, -}; - -static int __init wm8955_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8955_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8955_modinit); - -static void __exit wm8955_exit(void) -{ - i2c_del_driver(&wm8955_i2c_driver); -} -module_exit(wm8955_exit); - -MODULE_DESCRIPTION("ASoC WM8955 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8955.h b/ANDROID_3.4.5/sound/soc/codecs/wm8955.h deleted file mode 100644 index d13fd5c5..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8955.h +++ /dev/null @@ -1,486 +0,0 @@ -/* - * wm8955.h -- WM8904 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics, plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8955_H -#define _WM8955_H - -#define WM8955_CLK_MCLK 1 - -/* - * Register values. - */ -#define WM8955_LOUT1_VOLUME 0x02 -#define WM8955_ROUT1_VOLUME 0x03 -#define WM8955_DAC_CONTROL 0x05 -#define WM8955_AUDIO_INTERFACE 0x07 -#define WM8955_SAMPLE_RATE 0x08 -#define WM8955_LEFT_DAC_VOLUME 0x0A -#define WM8955_RIGHT_DAC_VOLUME 0x0B -#define WM8955_BASS_CONTROL 0x0C -#define WM8955_TREBLE_CONTROL 0x0D -#define WM8955_RESET 0x0F -#define WM8955_ADDITIONAL_CONTROL_1 0x17 -#define WM8955_ADDITIONAL_CONTROL_2 0x18 -#define WM8955_POWER_MANAGEMENT_1 0x19 -#define WM8955_POWER_MANAGEMENT_2 0x1A -#define WM8955_ADDITIONAL_CONTROL_3 0x1B -#define WM8955_LEFT_OUT_MIX_1 0x22 -#define WM8955_LEFT_OUT_MIX_2 0x23 -#define WM8955_RIGHT_OUT_MIX_1 0x24 -#define WM8955_RIGHT_OUT_MIX_2 0x25 -#define WM8955_MONO_OUT_MIX_1 0x26 -#define WM8955_MONO_OUT_MIX_2 0x27 -#define WM8955_LOUT2_VOLUME 0x28 -#define WM8955_ROUT2_VOLUME 0x29 -#define WM8955_MONOOUT_VOLUME 0x2A -#define WM8955_CLOCKING_PLL 0x2B -#define WM8955_PLL_CONTROL_1 0x2C -#define WM8955_PLL_CONTROL_2 0x2D -#define WM8955_PLL_CONTROL_3 0x2E -#define WM8955_PLL_CONTROL_4 0x3B - -#define WM8955_REGISTER_COUNT 29 -#define WM8955_MAX_REGISTER 0x3B - -/* - * Field Definitions. - */ - -/* - * R2 (0x02) - LOUT1 volume - */ -#define WM8955_LO1VU 0x0100 /* LO1VU */ -#define WM8955_LO1VU_MASK 0x0100 /* LO1VU */ -#define WM8955_LO1VU_SHIFT 8 /* LO1VU */ -#define WM8955_LO1VU_WIDTH 1 /* LO1VU */ -#define WM8955_LO1ZC 0x0080 /* LO1ZC */ -#define WM8955_LO1ZC_MASK 0x0080 /* LO1ZC */ -#define WM8955_LO1ZC_SHIFT 7 /* LO1ZC */ -#define WM8955_LO1ZC_WIDTH 1 /* LO1ZC */ -#define WM8955_LOUTVOL_MASK 0x007F /* LOUTVOL - [6:0] */ -#define WM8955_LOUTVOL_SHIFT 0 /* LOUTVOL - [6:0] */ -#define WM8955_LOUTVOL_WIDTH 7 /* LOUTVOL - [6:0] */ - -/* - * R3 (0x03) - ROUT1 volume - */ -#define WM8955_RO1VU 0x0100 /* RO1VU */ -#define WM8955_RO1VU_MASK 0x0100 /* RO1VU */ -#define WM8955_RO1VU_SHIFT 8 /* RO1VU */ -#define WM8955_RO1VU_WIDTH 1 /* RO1VU */ -#define WM8955_RO1ZC 0x0080 /* RO1ZC */ -#define WM8955_RO1ZC_MASK 0x0080 /* RO1ZC */ -#define WM8955_RO1ZC_SHIFT 7 /* RO1ZC */ -#define WM8955_RO1ZC_WIDTH 1 /* RO1ZC */ -#define WM8955_ROUTVOL_MASK 0x007F /* ROUTVOL - [6:0] */ -#define WM8955_ROUTVOL_SHIFT 0 /* ROUTVOL - [6:0] */ -#define WM8955_ROUTVOL_WIDTH 7 /* ROUTVOL - [6:0] */ - -/* - * R5 (0x05) - DAC Control - */ -#define WM8955_DAT 0x0080 /* DAT */ -#define WM8955_DAT_MASK 0x0080 /* DAT */ -#define WM8955_DAT_SHIFT 7 /* DAT */ -#define WM8955_DAT_WIDTH 1 /* DAT */ -#define WM8955_DACMU 0x0008 /* DACMU */ -#define WM8955_DACMU_MASK 0x0008 /* DACMU */ -#define WM8955_DACMU_SHIFT 3 /* DACMU */ -#define WM8955_DACMU_WIDTH 1 /* DACMU */ -#define WM8955_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ -#define WM8955_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ -#define WM8955_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ - -/* - * R7 (0x07) - Audio Interface - */ -#define WM8955_BCLKINV 0x0080 /* BCLKINV */ -#define WM8955_BCLKINV_MASK 0x0080 /* BCLKINV */ -#define WM8955_BCLKINV_SHIFT 7 /* BCLKINV */ -#define WM8955_BCLKINV_WIDTH 1 /* BCLKINV */ -#define WM8955_MS 0x0040 /* MS */ -#define WM8955_MS_MASK 0x0040 /* MS */ -#define WM8955_MS_SHIFT 6 /* MS */ -#define WM8955_MS_WIDTH 1 /* MS */ -#define WM8955_LRSWAP 0x0020 /* LRSWAP */ -#define WM8955_LRSWAP_MASK 0x0020 /* LRSWAP */ -#define WM8955_LRSWAP_SHIFT 5 /* LRSWAP */ -#define WM8955_LRSWAP_WIDTH 1 /* LRSWAP */ -#define WM8955_LRP 0x0010 /* LRP */ -#define WM8955_LRP_MASK 0x0010 /* LRP */ -#define WM8955_LRP_SHIFT 4 /* LRP */ -#define WM8955_LRP_WIDTH 1 /* LRP */ -#define WM8955_WL_MASK 0x000C /* WL - [3:2] */ -#define WM8955_WL_SHIFT 2 /* WL - [3:2] */ -#define WM8955_WL_WIDTH 2 /* WL - [3:2] */ -#define WM8955_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */ -#define WM8955_FORMAT_SHIFT 0 /* FORMAT - [1:0] */ -#define WM8955_FORMAT_WIDTH 2 /* FORMAT - [1:0] */ - -/* - * R8 (0x08) - Sample Rate - */ -#define WM8955_BCLKDIV2 0x0080 /* BCLKDIV2 */ -#define WM8955_BCLKDIV2_MASK 0x0080 /* BCLKDIV2 */ -#define WM8955_BCLKDIV2_SHIFT 7 /* BCLKDIV2 */ -#define WM8955_BCLKDIV2_WIDTH 1 /* BCLKDIV2 */ -#define WM8955_MCLKDIV2 0x0040 /* MCLKDIV2 */ -#define WM8955_MCLKDIV2_MASK 0x0040 /* MCLKDIV2 */ -#define WM8955_MCLKDIV2_SHIFT 6 /* MCLKDIV2 */ -#define WM8955_MCLKDIV2_WIDTH 1 /* MCLKDIV2 */ -#define WM8955_SR_MASK 0x003E /* SR - [5:1] */ -#define WM8955_SR_SHIFT 1 /* SR - [5:1] */ -#define WM8955_SR_WIDTH 5 /* SR - [5:1] */ -#define WM8955_USB 0x0001 /* USB */ -#define WM8955_USB_MASK 0x0001 /* USB */ -#define WM8955_USB_SHIFT 0 /* USB */ -#define WM8955_USB_WIDTH 1 /* USB */ - -/* - * R10 (0x0A) - Left DAC volume - */ -#define WM8955_LDVU 0x0100 /* LDVU */ -#define WM8955_LDVU_MASK 0x0100 /* LDVU */ -#define WM8955_LDVU_SHIFT 8 /* LDVU */ -#define WM8955_LDVU_WIDTH 1 /* LDVU */ -#define WM8955_LDACVOL_MASK 0x00FF /* LDACVOL - [7:0] */ -#define WM8955_LDACVOL_SHIFT 0 /* LDACVOL - [7:0] */ -#define WM8955_LDACVOL_WIDTH 8 /* LDACVOL - [7:0] */ - -/* - * R11 (0x0B) - Right DAC volume - */ -#define WM8955_RDVU 0x0100 /* RDVU */ -#define WM8955_RDVU_MASK 0x0100 /* RDVU */ -#define WM8955_RDVU_SHIFT 8 /* RDVU */ -#define WM8955_RDVU_WIDTH 1 /* RDVU */ -#define WM8955_RDACVOL_MASK 0x00FF /* RDACVOL - [7:0] */ -#define WM8955_RDACVOL_SHIFT 0 /* RDACVOL - [7:0] */ -#define WM8955_RDACVOL_WIDTH 8 /* RDACVOL - [7:0] */ - -/* - * R12 (0x0C) - Bass control - */ -#define WM8955_BB 0x0080 /* BB */ -#define WM8955_BB_MASK 0x0080 /* BB */ -#define WM8955_BB_SHIFT 7 /* BB */ -#define WM8955_BB_WIDTH 1 /* BB */ -#define WM8955_BC 0x0040 /* BC */ -#define WM8955_BC_MASK 0x0040 /* BC */ -#define WM8955_BC_SHIFT 6 /* BC */ -#define WM8955_BC_WIDTH 1 /* BC */ -#define WM8955_BASS_MASK 0x000F /* BASS - [3:0] */ -#define WM8955_BASS_SHIFT 0 /* BASS - [3:0] */ -#define WM8955_BASS_WIDTH 4 /* BASS - [3:0] */ - -/* - * R13 (0x0D) - Treble control - */ -#define WM8955_TC 0x0040 /* TC */ -#define WM8955_TC_MASK 0x0040 /* TC */ -#define WM8955_TC_SHIFT 6 /* TC */ -#define WM8955_TC_WIDTH 1 /* TC */ -#define WM8955_TRBL_MASK 0x000F /* TRBL - [3:0] */ -#define WM8955_TRBL_SHIFT 0 /* TRBL - [3:0] */ -#define WM8955_TRBL_WIDTH 4 /* TRBL - [3:0] */ - -/* - * R15 (0x0F) - Reset - */ -#define WM8955_RESET_MASK 0x01FF /* RESET - [8:0] */ -#define WM8955_RESET_SHIFT 0 /* RESET - [8:0] */ -#define WM8955_RESET_WIDTH 9 /* RESET - [8:0] */ - -/* - * R23 (0x17) - Additional control (1) - */ -#define WM8955_TSDEN 0x0100 /* TSDEN */ -#define WM8955_TSDEN_MASK 0x0100 /* TSDEN */ -#define WM8955_TSDEN_SHIFT 8 /* TSDEN */ -#define WM8955_TSDEN_WIDTH 1 /* TSDEN */ -#define WM8955_VSEL_MASK 0x00C0 /* VSEL - [7:6] */ -#define WM8955_VSEL_SHIFT 6 /* VSEL - [7:6] */ -#define WM8955_VSEL_WIDTH 2 /* VSEL - [7:6] */ -#define WM8955_DMONOMIX_MASK 0x0030 /* DMONOMIX - [5:4] */ -#define WM8955_DMONOMIX_SHIFT 4 /* DMONOMIX - [5:4] */ -#define WM8955_DMONOMIX_WIDTH 2 /* DMONOMIX - [5:4] */ -#define WM8955_DACINV 0x0002 /* DACINV */ -#define WM8955_DACINV_MASK 0x0002 /* DACINV */ -#define WM8955_DACINV_SHIFT 1 /* DACINV */ -#define WM8955_DACINV_WIDTH 1 /* DACINV */ -#define WM8955_TOEN 0x0001 /* TOEN */ -#define WM8955_TOEN_MASK 0x0001 /* TOEN */ -#define WM8955_TOEN_SHIFT 0 /* TOEN */ -#define WM8955_TOEN_WIDTH 1 /* TOEN */ - -/* - * R24 (0x18) - Additional control (2) - */ -#define WM8955_OUT3SW_MASK 0x0180 /* OUT3SW - [8:7] */ -#define WM8955_OUT3SW_SHIFT 7 /* OUT3SW - [8:7] */ -#define WM8955_OUT3SW_WIDTH 2 /* OUT3SW - [8:7] */ -#define WM8955_ROUT2INV 0x0010 /* ROUT2INV */ -#define WM8955_ROUT2INV_MASK 0x0010 /* ROUT2INV */ -#define WM8955_ROUT2INV_SHIFT 4 /* ROUT2INV */ -#define WM8955_ROUT2INV_WIDTH 1 /* ROUT2INV */ -#define WM8955_DACOSR 0x0001 /* DACOSR */ -#define WM8955_DACOSR_MASK 0x0001 /* DACOSR */ -#define WM8955_DACOSR_SHIFT 0 /* DACOSR */ -#define WM8955_DACOSR_WIDTH 1 /* DACOSR */ - -/* - * R25 (0x19) - Power Management (1) - */ -#define WM8955_VMIDSEL_MASK 0x0180 /* VMIDSEL - [8:7] */ -#define WM8955_VMIDSEL_SHIFT 7 /* VMIDSEL - [8:7] */ -#define WM8955_VMIDSEL_WIDTH 2 /* VMIDSEL - [8:7] */ -#define WM8955_VREF 0x0040 /* VREF */ -#define WM8955_VREF_MASK 0x0040 /* VREF */ -#define WM8955_VREF_SHIFT 6 /* VREF */ -#define WM8955_VREF_WIDTH 1 /* VREF */ -#define WM8955_DIGENB 0x0001 /* DIGENB */ -#define WM8955_DIGENB_MASK 0x0001 /* DIGENB */ -#define WM8955_DIGENB_SHIFT 0 /* DIGENB */ -#define WM8955_DIGENB_WIDTH 1 /* DIGENB */ - -/* - * R26 (0x1A) - Power Management (2) - */ -#define WM8955_DACL 0x0100 /* DACL */ -#define WM8955_DACL_MASK 0x0100 /* DACL */ -#define WM8955_DACL_SHIFT 8 /* DACL */ -#define WM8955_DACL_WIDTH 1 /* DACL */ -#define WM8955_DACR 0x0080 /* DACR */ -#define WM8955_DACR_MASK 0x0080 /* DACR */ -#define WM8955_DACR_SHIFT 7 /* DACR */ -#define WM8955_DACR_WIDTH 1 /* DACR */ -#define WM8955_LOUT1 0x0040 /* LOUT1 */ -#define WM8955_LOUT1_MASK 0x0040 /* LOUT1 */ -#define WM8955_LOUT1_SHIFT 6 /* LOUT1 */ -#define WM8955_LOUT1_WIDTH 1 /* LOUT1 */ -#define WM8955_ROUT1 0x0020 /* ROUT1 */ -#define WM8955_ROUT1_MASK 0x0020 /* ROUT1 */ -#define WM8955_ROUT1_SHIFT 5 /* ROUT1 */ -#define WM8955_ROUT1_WIDTH 1 /* ROUT1 */ -#define WM8955_LOUT2 0x0010 /* LOUT2 */ -#define WM8955_LOUT2_MASK 0x0010 /* LOUT2 */ -#define WM8955_LOUT2_SHIFT 4 /* LOUT2 */ -#define WM8955_LOUT2_WIDTH 1 /* LOUT2 */ -#define WM8955_ROUT2 0x0008 /* ROUT2 */ -#define WM8955_ROUT2_MASK 0x0008 /* ROUT2 */ -#define WM8955_ROUT2_SHIFT 3 /* ROUT2 */ -#define WM8955_ROUT2_WIDTH 1 /* ROUT2 */ -#define WM8955_MONO 0x0004 /* MONO */ -#define WM8955_MONO_MASK 0x0004 /* MONO */ -#define WM8955_MONO_SHIFT 2 /* MONO */ -#define WM8955_MONO_WIDTH 1 /* MONO */ -#define WM8955_OUT3 0x0002 /* OUT3 */ -#define WM8955_OUT3_MASK 0x0002 /* OUT3 */ -#define WM8955_OUT3_SHIFT 1 /* OUT3 */ -#define WM8955_OUT3_WIDTH 1 /* OUT3 */ - -/* - * R27 (0x1B) - Additional Control (3) - */ -#define WM8955_VROI 0x0040 /* VROI */ -#define WM8955_VROI_MASK 0x0040 /* VROI */ -#define WM8955_VROI_SHIFT 6 /* VROI */ -#define WM8955_VROI_WIDTH 1 /* VROI */ - -/* - * R34 (0x22) - Left out Mix (1) - */ -#define WM8955_LD2LO 0x0100 /* LD2LO */ -#define WM8955_LD2LO_MASK 0x0100 /* LD2LO */ -#define WM8955_LD2LO_SHIFT 8 /* LD2LO */ -#define WM8955_LD2LO_WIDTH 1 /* LD2LO */ -#define WM8955_LI2LO 0x0080 /* LI2LO */ -#define WM8955_LI2LO_MASK 0x0080 /* LI2LO */ -#define WM8955_LI2LO_SHIFT 7 /* LI2LO */ -#define WM8955_LI2LO_WIDTH 1 /* LI2LO */ -#define WM8955_LI2LOVOL_MASK 0x0070 /* LI2LOVOL - [6:4] */ -#define WM8955_LI2LOVOL_SHIFT 4 /* LI2LOVOL - [6:4] */ -#define WM8955_LI2LOVOL_WIDTH 3 /* LI2LOVOL - [6:4] */ - -/* - * R35 (0x23) - Left out Mix (2) - */ -#define WM8955_RD2LO 0x0100 /* RD2LO */ -#define WM8955_RD2LO_MASK 0x0100 /* RD2LO */ -#define WM8955_RD2LO_SHIFT 8 /* RD2LO */ -#define WM8955_RD2LO_WIDTH 1 /* RD2LO */ -#define WM8955_RI2LO 0x0080 /* RI2LO */ -#define WM8955_RI2LO_MASK 0x0080 /* RI2LO */ -#define WM8955_RI2LO_SHIFT 7 /* RI2LO */ -#define WM8955_RI2LO_WIDTH 1 /* RI2LO */ -#define WM8955_RI2LOVOL_MASK 0x0070 /* RI2LOVOL - [6:4] */ -#define WM8955_RI2LOVOL_SHIFT 4 /* RI2LOVOL - [6:4] */ -#define WM8955_RI2LOVOL_WIDTH 3 /* RI2LOVOL - [6:4] */ - -/* - * R36 (0x24) - Right out Mix (1) - */ -#define WM8955_LD2RO 0x0100 /* LD2RO */ -#define WM8955_LD2RO_MASK 0x0100 /* LD2RO */ -#define WM8955_LD2RO_SHIFT 8 /* LD2RO */ -#define WM8955_LD2RO_WIDTH 1 /* LD2RO */ -#define WM8955_LI2RO 0x0080 /* LI2RO */ -#define WM8955_LI2RO_MASK 0x0080 /* LI2RO */ -#define WM8955_LI2RO_SHIFT 7 /* LI2RO */ -#define WM8955_LI2RO_WIDTH 1 /* LI2RO */ -#define WM8955_LI2ROVOL_MASK 0x0070 /* LI2ROVOL - [6:4] */ -#define WM8955_LI2ROVOL_SHIFT 4 /* LI2ROVOL - [6:4] */ -#define WM8955_LI2ROVOL_WIDTH 3 /* LI2ROVOL - [6:4] */ - -/* - * R37 (0x25) - Right Out Mix (2) - */ -#define WM8955_RD2RO 0x0100 /* RD2RO */ -#define WM8955_RD2RO_MASK 0x0100 /* RD2RO */ -#define WM8955_RD2RO_SHIFT 8 /* RD2RO */ -#define WM8955_RD2RO_WIDTH 1 /* RD2RO */ -#define WM8955_RI2RO 0x0080 /* RI2RO */ -#define WM8955_RI2RO_MASK 0x0080 /* RI2RO */ -#define WM8955_RI2RO_SHIFT 7 /* RI2RO */ -#define WM8955_RI2RO_WIDTH 1 /* RI2RO */ -#define WM8955_RI2ROVOL_MASK 0x0070 /* RI2ROVOL - [6:4] */ -#define WM8955_RI2ROVOL_SHIFT 4 /* RI2ROVOL - [6:4] */ -#define WM8955_RI2ROVOL_WIDTH 3 /* RI2ROVOL - [6:4] */ - -/* - * R38 (0x26) - Mono out Mix (1) - */ -#define WM8955_LD2MO 0x0100 /* LD2MO */ -#define WM8955_LD2MO_MASK 0x0100 /* LD2MO */ -#define WM8955_LD2MO_SHIFT 8 /* LD2MO */ -#define WM8955_LD2MO_WIDTH 1 /* LD2MO */ -#define WM8955_LI2MO 0x0080 /* LI2MO */ -#define WM8955_LI2MO_MASK 0x0080 /* LI2MO */ -#define WM8955_LI2MO_SHIFT 7 /* LI2MO */ -#define WM8955_LI2MO_WIDTH 1 /* LI2MO */ -#define WM8955_LI2MOVOL_MASK 0x0070 /* LI2MOVOL - [6:4] */ -#define WM8955_LI2MOVOL_SHIFT 4 /* LI2MOVOL - [6:4] */ -#define WM8955_LI2MOVOL_WIDTH 3 /* LI2MOVOL - [6:4] */ -#define WM8955_DMEN 0x0001 /* DMEN */ -#define WM8955_DMEN_MASK 0x0001 /* DMEN */ -#define WM8955_DMEN_SHIFT 0 /* DMEN */ -#define WM8955_DMEN_WIDTH 1 /* DMEN */ - -/* - * R39 (0x27) - Mono out Mix (2) - */ -#define WM8955_RD2MO 0x0100 /* RD2MO */ -#define WM8955_RD2MO_MASK 0x0100 /* RD2MO */ -#define WM8955_RD2MO_SHIFT 8 /* RD2MO */ -#define WM8955_RD2MO_WIDTH 1 /* RD2MO */ -#define WM8955_RI2MO 0x0080 /* RI2MO */ -#define WM8955_RI2MO_MASK 0x0080 /* RI2MO */ -#define WM8955_RI2MO_SHIFT 7 /* RI2MO */ -#define WM8955_RI2MO_WIDTH 1 /* RI2MO */ -#define WM8955_RI2MOVOL_MASK 0x0070 /* RI2MOVOL - [6:4] */ -#define WM8955_RI2MOVOL_SHIFT 4 /* RI2MOVOL - [6:4] */ -#define WM8955_RI2MOVOL_WIDTH 3 /* RI2MOVOL - [6:4] */ - -/* - * R40 (0x28) - LOUT2 volume - */ -#define WM8955_LO2VU 0x0100 /* LO2VU */ -#define WM8955_LO2VU_MASK 0x0100 /* LO2VU */ -#define WM8955_LO2VU_SHIFT 8 /* LO2VU */ -#define WM8955_LO2VU_WIDTH 1 /* LO2VU */ -#define WM8955_LO2ZC 0x0080 /* LO2ZC */ -#define WM8955_LO2ZC_MASK 0x0080 /* LO2ZC */ -#define WM8955_LO2ZC_SHIFT 7 /* LO2ZC */ -#define WM8955_LO2ZC_WIDTH 1 /* LO2ZC */ -#define WM8955_LOUT2VOL_MASK 0x007F /* LOUT2VOL - [6:0] */ -#define WM8955_LOUT2VOL_SHIFT 0 /* LOUT2VOL - [6:0] */ -#define WM8955_LOUT2VOL_WIDTH 7 /* LOUT2VOL - [6:0] */ - -/* - * R41 (0x29) - ROUT2 volume - */ -#define WM8955_RO2VU 0x0100 /* RO2VU */ -#define WM8955_RO2VU_MASK 0x0100 /* RO2VU */ -#define WM8955_RO2VU_SHIFT 8 /* RO2VU */ -#define WM8955_RO2VU_WIDTH 1 /* RO2VU */ -#define WM8955_RO2ZC 0x0080 /* RO2ZC */ -#define WM8955_RO2ZC_MASK 0x0080 /* RO2ZC */ -#define WM8955_RO2ZC_SHIFT 7 /* RO2ZC */ -#define WM8955_RO2ZC_WIDTH 1 /* RO2ZC */ -#define WM8955_ROUT2VOL_MASK 0x007F /* ROUT2VOL - [6:0] */ -#define WM8955_ROUT2VOL_SHIFT 0 /* ROUT2VOL - [6:0] */ -#define WM8955_ROUT2VOL_WIDTH 7 /* ROUT2VOL - [6:0] */ - -/* - * R42 (0x2A) - MONOOUT volume - */ -#define WM8955_MOZC 0x0080 /* MOZC */ -#define WM8955_MOZC_MASK 0x0080 /* MOZC */ -#define WM8955_MOZC_SHIFT 7 /* MOZC */ -#define WM8955_MOZC_WIDTH 1 /* MOZC */ -#define WM8955_MOUTVOL_MASK 0x007F /* MOUTVOL - [6:0] */ -#define WM8955_MOUTVOL_SHIFT 0 /* MOUTVOL - [6:0] */ -#define WM8955_MOUTVOL_WIDTH 7 /* MOUTVOL - [6:0] */ - -/* - * R43 (0x2B) - Clocking / PLL - */ -#define WM8955_MCLKSEL 0x0100 /* MCLKSEL */ -#define WM8955_MCLKSEL_MASK 0x0100 /* MCLKSEL */ -#define WM8955_MCLKSEL_SHIFT 8 /* MCLKSEL */ -#define WM8955_MCLKSEL_WIDTH 1 /* MCLKSEL */ -#define WM8955_PLLOUTDIV2 0x0020 /* PLLOUTDIV2 */ -#define WM8955_PLLOUTDIV2_MASK 0x0020 /* PLLOUTDIV2 */ -#define WM8955_PLLOUTDIV2_SHIFT 5 /* PLLOUTDIV2 */ -#define WM8955_PLLOUTDIV2_WIDTH 1 /* PLLOUTDIV2 */ -#define WM8955_PLL_RB 0x0010 /* PLL_RB */ -#define WM8955_PLL_RB_MASK 0x0010 /* PLL_RB */ -#define WM8955_PLL_RB_SHIFT 4 /* PLL_RB */ -#define WM8955_PLL_RB_WIDTH 1 /* PLL_RB */ -#define WM8955_PLLEN 0x0008 /* PLLEN */ -#define WM8955_PLLEN_MASK 0x0008 /* PLLEN */ -#define WM8955_PLLEN_SHIFT 3 /* PLLEN */ -#define WM8955_PLLEN_WIDTH 1 /* PLLEN */ - -/* - * R44 (0x2C) - PLL Control 1 - */ -#define WM8955_N_MASK 0x01E0 /* N - [8:5] */ -#define WM8955_N_SHIFT 5 /* N - [8:5] */ -#define WM8955_N_WIDTH 4 /* N - [8:5] */ -#define WM8955_K_21_18_MASK 0x000F /* K(21:18) - [3:0] */ -#define WM8955_K_21_18_SHIFT 0 /* K(21:18) - [3:0] */ -#define WM8955_K_21_18_WIDTH 4 /* K(21:18) - [3:0] */ - -/* - * R45 (0x2D) - PLL Control 2 - */ -#define WM8955_K_17_9_MASK 0x01FF /* K(17:9) - [8:0] */ -#define WM8955_K_17_9_SHIFT 0 /* K(17:9) - [8:0] */ -#define WM8955_K_17_9_WIDTH 9 /* K(17:9) - [8:0] */ - -/* - * R46 (0x2E) - PLL Control 3 - */ -#define WM8955_K_8_0_MASK 0x01FF /* K(8:0) - [8:0] */ -#define WM8955_K_8_0_SHIFT 0 /* K(8:0) - [8:0] */ -#define WM8955_K_8_0_WIDTH 9 /* K(8:0) - [8:0] */ - -/* - * R59 (0x3B) - PLL Control 4 - */ -#define WM8955_KEN 0x0080 /* KEN */ -#define WM8955_KEN_MASK 0x0080 /* KEN */ -#define WM8955_KEN_SHIFT 7 /* KEN */ -#define WM8955_KEN_WIDTH 1 /* KEN */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8958-dsp2.c b/ANDROID_3.4.5/sound/soc/codecs/wm8958-dsp2.c deleted file mode 100644 index 1332692e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8958-dsp2.c +++ /dev/null @@ -1,1054 +0,0 @@ -/* - * wm8958-dsp2.c -- WM8958 DSP2 support - * - * Copyright 2011 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "wm8994.h" - -#define WM_FW_BLOCK_INFO 0xff -#define WM_FW_BLOCK_PM 0x00 -#define WM_FW_BLOCK_X 0x01 -#define WM_FW_BLOCK_Y 0x02 -#define WM_FW_BLOCK_Z 0x03 -#define WM_FW_BLOCK_I 0x06 -#define WM_FW_BLOCK_A 0x08 -#define WM_FW_BLOCK_C 0x0c - -static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name, - const struct firmware *fw, bool check) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - u64 data64; - u32 data32; - const u8 *data; - char *str; - size_t block_len, len; - int ret = 0; - - /* Suppress unneeded downloads */ - if (wm8994->cur_fw == fw) - return 0; - - if (fw->size < 32) { - dev_err(codec->dev, "%s: firmware too short (%zd bytes)\n", - name, fw->size); - goto err; - } - - if (memcmp(fw->data, "WMFW", 4) != 0) { - memcpy(&data32, fw->data, sizeof(data32)); - data32 = be32_to_cpu(data32); - dev_err(codec->dev, "%s: firmware has bad file magic %08x\n", - name, data32); - goto err; - } - - memcpy(&data32, fw->data + 4, sizeof(data32)); - len = be32_to_cpu(data32); - - memcpy(&data32, fw->data + 8, sizeof(data32)); - data32 = be32_to_cpu(data32); - if ((data32 >> 24) & 0xff) { - dev_err(codec->dev, "%s: unsupported firmware version %d\n", - name, (data32 >> 24) & 0xff); - goto err; - } - if ((data32 & 0xffff) != 8958) { - dev_err(codec->dev, "%s: unsupported target device %d\n", - name, data32 & 0xffff); - goto err; - } - if (((data32 >> 16) & 0xff) != 0xc) { - dev_err(codec->dev, "%s: unsupported target core %d\n", - name, (data32 >> 16) & 0xff); - goto err; - } - - if (check) { - memcpy(&data64, fw->data + 24, sizeof(u64)); - dev_info(codec->dev, "%s timestamp %llx\n", - name, be64_to_cpu(data64)); - } else { - snd_soc_write(codec, 0x102, 0x2); - snd_soc_write(codec, 0x900, 0x2); - } - - data = fw->data + len; - len = fw->size - len; - while (len) { - if (len < 12) { - dev_err(codec->dev, "%s short data block of %zd\n", - name, len); - goto err; - } - - memcpy(&data32, data + 4, sizeof(data32)); - block_len = be32_to_cpu(data32); - if (block_len + 8 > len) { - dev_err(codec->dev, "%zd byte block longer than file\n", - block_len); - goto err; - } - if (block_len == 0) { - dev_err(codec->dev, "Zero length block\n"); - goto err; - } - - memcpy(&data32, data, sizeof(data32)); - data32 = be32_to_cpu(data32); - - switch ((data32 >> 24) & 0xff) { - case WM_FW_BLOCK_INFO: - /* Informational text */ - if (!check) - break; - - str = kzalloc(block_len + 1, GFP_KERNEL); - if (str) { - memcpy(str, data + 8, block_len); - dev_info(codec->dev, "%s: %s\n", name, str); - kfree(str); - } else { - dev_err(codec->dev, "Out of memory\n"); - } - break; - case WM_FW_BLOCK_PM: - case WM_FW_BLOCK_X: - case WM_FW_BLOCK_Y: - case WM_FW_BLOCK_Z: - case WM_FW_BLOCK_I: - case WM_FW_BLOCK_A: - case WM_FW_BLOCK_C: - dev_dbg(codec->dev, "%s: %zd bytes of %x@%x\n", name, - block_len, (data32 >> 24) & 0xff, - data32 & 0xffffff); - - if (check) - break; - - data32 &= 0xffffff; - - wm8994_bulk_write(codec->control_data, - data32 & 0xffffff, - block_len / 2, - (void *)(data + 8)); - - break; - default: - dev_warn(codec->dev, "%s: unknown block type %d\n", - name, (data32 >> 24) & 0xff); - break; - } - - /* Round up to the next 32 bit word */ - block_len += block_len % 4; - - data += block_len + 8; - len -= block_len + 8; - } - - if (!check) { - dev_dbg(codec->dev, "%s: download done\n", name); - wm8994->cur_fw = fw; - } else { - dev_info(codec->dev, "%s: got firmware\n", name); - } - - goto ok; - -err: - ret = -EINVAL; -ok: - if (!check) { - snd_soc_write(codec, 0x900, 0x0); - snd_soc_write(codec, 0x102, 0x0); - } - - return ret; -} - -static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int i; - - /* If the DSP is already running then noop */ - if (snd_soc_read(codec, WM8958_DSP2_PROGRAM) & WM8958_DSP2_ENA) - return; - - /* If we have MBC firmware download it */ - if (wm8994->mbc) - wm8958_dsp2_fw(codec, "MBC", wm8994->mbc, false); - - snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, - WM8958_DSP2_ENA, WM8958_DSP2_ENA); - - /* If we've got user supplied MBC settings use them */ - if (pdata && pdata->num_mbc_cfgs) { - struct wm8958_mbc_cfg *cfg - = &pdata->mbc_cfgs[wm8994->mbc_cfg]; - - for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++) - snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1, - cfg->coeff_regs[i]); - - for (i = 0; i < ARRAY_SIZE(cfg->cutoff_regs); i++) - snd_soc_write(codec, - i + WM8958_MBC_BAND_2_LOWER_CUTOFF_C1_1, - cfg->cutoff_regs[i]); - } - - /* Run the DSP */ - snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, - WM8958_DSP2_RUNR); - - /* And we're off! */ - snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, - WM8958_MBC_ENA | - WM8958_MBC_SEL_MASK, - path << WM8958_MBC_SEL_SHIFT | - WM8958_MBC_ENA); -} - -static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int i, ena; - - if (wm8994->mbc_vss) - wm8958_dsp2_fw(codec, "MBC+VSS", wm8994->mbc_vss, false); - - snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, - WM8958_DSP2_ENA, WM8958_DSP2_ENA); - - /* If we've got user supplied settings use them */ - if (pdata && pdata->num_mbc_cfgs) { - struct wm8958_mbc_cfg *cfg - = &pdata->mbc_cfgs[wm8994->mbc_cfg]; - - for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++) - snd_soc_write(codec, i + 0x2800, - cfg->combined_regs[i]); - } - - if (pdata && pdata->num_vss_cfgs) { - struct wm8958_vss_cfg *cfg - = &pdata->vss_cfgs[wm8994->vss_cfg]; - - for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) - snd_soc_write(codec, i + 0x2600, cfg->regs[i]); - } - - if (pdata && pdata->num_vss_hpf_cfgs) { - struct wm8958_vss_hpf_cfg *cfg - = &pdata->vss_hpf_cfgs[wm8994->vss_hpf_cfg]; - - for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) - snd_soc_write(codec, i + 0x2400, cfg->regs[i]); - } - - /* Run the DSP */ - snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, - WM8958_DSP2_RUNR); - - /* Enable the algorithms we've selected */ - ena = 0; - if (wm8994->mbc_ena[path]) - ena |= 0x8; - if (wm8994->hpf2_ena[path]) - ena |= 0x4; - if (wm8994->hpf1_ena[path]) - ena |= 0x2; - if (wm8994->vss_ena[path]) - ena |= 0x1; - - snd_soc_write(codec, 0x2201, ena); - - /* Switch the DSP into the data path */ - snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, - WM8958_MBC_SEL_MASK | WM8958_MBC_ENA, - path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA); -} - -static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int i; - - wm8958_dsp2_fw(codec, "ENH_EQ", wm8994->enh_eq, false); - - snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, - WM8958_DSP2_ENA, WM8958_DSP2_ENA); - - /* If we've got user supplied settings use them */ - if (pdata && pdata->num_enh_eq_cfgs) { - struct wm8958_enh_eq_cfg *cfg - = &pdata->enh_eq_cfgs[wm8994->enh_eq_cfg]; - - for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) - snd_soc_write(codec, i + 0x2200, - cfg->regs[i]); - } - - /* Run the DSP */ - snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, - WM8958_DSP2_RUNR); - - /* Switch the DSP into the data path */ - snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, - WM8958_MBC_SEL_MASK | WM8958_MBC_ENA, - path << WM8958_MBC_SEL_SHIFT | WM8958_MBC_ENA); -} - -static void wm8958_dsp_apply(struct snd_soc_codec *codec, int path, int start) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int pwr_reg = snd_soc_read(codec, WM8994_POWER_MANAGEMENT_5); - int ena, reg, aif; - - switch (path) { - case 0: - pwr_reg &= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA); - aif = 0; - break; - case 1: - pwr_reg &= (WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); - aif = 0; - break; - case 2: - pwr_reg &= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA); - aif = 1; - break; - default: - BUG(); - return; - } - - /* Do we have both an active AIF and an active algorithm? */ - ena = wm8994->mbc_ena[path] || wm8994->vss_ena[path] || - wm8994->hpf1_ena[path] || wm8994->hpf2_ena[path] || - wm8994->enh_eq_ena[path]; - if (!pwr_reg) - ena = 0; - - reg = snd_soc_read(codec, WM8958_DSP2_PROGRAM); - - dev_dbg(codec->dev, "DSP path %d %d startup: %d, power: %x, DSP: %x\n", - path, wm8994->dsp_active, start, pwr_reg, reg); - - if (start && ena) { - /* If the DSP is already running then noop */ - if (reg & WM8958_DSP2_ENA) - return; - - /* If either AIFnCLK is not yet enabled postpone */ - if (!(snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) - & WM8994_AIF1CLK_ENA_MASK) && - !(snd_soc_read(codec, WM8994_AIF2_CLOCKING_1) - & WM8994_AIF2CLK_ENA_MASK)) - return; - - /* Switch the clock over to the appropriate AIF */ - snd_soc_update_bits(codec, WM8994_CLOCKING_1, - WM8958_DSP2CLK_SRC | WM8958_DSP2CLK_ENA, - aif << WM8958_DSP2CLK_SRC_SHIFT | - WM8958_DSP2CLK_ENA); - - if (wm8994->enh_eq_ena[path]) - wm8958_dsp_start_enh_eq(codec, path); - else if (wm8994->vss_ena[path] || wm8994->hpf1_ena[path] || - wm8994->hpf2_ena[path]) - wm8958_dsp_start_vss(codec, path); - else if (wm8994->mbc_ena[path]) - wm8958_dsp_start_mbc(codec, path); - - wm8994->dsp_active = path; - - dev_dbg(codec->dev, "DSP running in path %d\n", path); - } - - if (!start && wm8994->dsp_active == path) { - /* If the DSP is already stopped then noop */ - if (!(reg & WM8958_DSP2_ENA)) - return; - - snd_soc_update_bits(codec, WM8958_DSP2_CONFIG, - WM8958_MBC_ENA, 0); - snd_soc_write(codec, WM8958_DSP2_EXECCONTROL, - WM8958_DSP2_STOP); - snd_soc_update_bits(codec, WM8958_DSP2_PROGRAM, - WM8958_DSP2_ENA, 0); - snd_soc_update_bits(codec, WM8994_CLOCKING_1, - WM8958_DSP2CLK_ENA, 0); - - wm8994->dsp_active = -1; - - dev_dbg(codec->dev, "DSP stopped\n"); - } -} - -int wm8958_aif_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - int i; - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - case SND_SOC_DAPM_PRE_PMU: - for (i = 0; i < 3; i++) - wm8958_dsp_apply(codec, i, 1); - break; - case SND_SOC_DAPM_POST_PMD: - case SND_SOC_DAPM_PRE_PMD: - for (i = 0; i < 3; i++) - wm8958_dsp_apply(codec, i, 0); - break; - } - - return 0; -} - -/* Check if DSP2 is in use on another AIF */ -static int wm8958_dsp2_busy(struct wm8994_priv *wm8994, int aif) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(wm8994->mbc_ena); i++) { - if (i == aif) - continue; - if (wm8994->mbc_ena[i] || wm8994->vss_ena[i] || - wm8994->hpf1_ena[i] || wm8994->hpf2_ena[i]) - return 1; - } - - return 0; -} - -static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int value = ucontrol->value.integer.value[0]; - int reg; - - /* Don't allow on the fly reconfiguration */ - reg = snd_soc_read(codec, WM8994_CLOCKING_1); - if (reg < 0 || reg & WM8958_DSP2CLK_ENA) - return -EBUSY; - - if (value >= pdata->num_mbc_cfgs) - return -EINVAL; - - wm8994->mbc_cfg = value; - - return 0; -} - -static int wm8958_get_mbc_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8994->mbc_cfg; - - return 0; -} - -static int wm8958_mbc_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int wm8958_mbc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int mbc = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = wm8994->mbc_ena[mbc]; - - return 0; -} - -static int wm8958_mbc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int mbc = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (wm8994->mbc_ena[mbc] == ucontrol->value.integer.value[0]) - return 0; - - if (ucontrol->value.integer.value[0] > 1) - return -EINVAL; - - if (wm8958_dsp2_busy(wm8994, mbc)) { - dev_dbg(codec->dev, "DSP2 active on %d already\n", mbc); - return -EBUSY; - } - - if (wm8994->enh_eq_ena[mbc]) - return -EBUSY; - - wm8994->mbc_ena[mbc] = ucontrol->value.integer.value[0]; - - wm8958_dsp_apply(codec, mbc, wm8994->mbc_ena[mbc]); - - return 0; -} - -#define WM8958_MBC_SWITCH(xname, xval) {\ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .info = wm8958_mbc_info, \ - .get = wm8958_mbc_get, .put = wm8958_mbc_put, \ - .private_value = xval } - -static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int value = ucontrol->value.integer.value[0]; - int reg; - - /* Don't allow on the fly reconfiguration */ - reg = snd_soc_read(codec, WM8994_CLOCKING_1); - if (reg < 0 || reg & WM8958_DSP2CLK_ENA) - return -EBUSY; - - if (value >= pdata->num_vss_cfgs) - return -EINVAL; - - wm8994->vss_cfg = value; - - return 0; -} - -static int wm8958_get_vss_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8994->vss_cfg; - - return 0; -} - -static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int value = ucontrol->value.integer.value[0]; - int reg; - - /* Don't allow on the fly reconfiguration */ - reg = snd_soc_read(codec, WM8994_CLOCKING_1); - if (reg < 0 || reg & WM8958_DSP2CLK_ENA) - return -EBUSY; - - if (value >= pdata->num_vss_hpf_cfgs) - return -EINVAL; - - wm8994->vss_hpf_cfg = value; - - return 0; -} - -static int wm8958_get_vss_hpf_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8994->vss_hpf_cfg; - - return 0; -} - -static int wm8958_vss_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int wm8958_vss_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int vss = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = wm8994->vss_ena[vss]; - - return 0; -} - -static int wm8958_vss_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int vss = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (wm8994->vss_ena[vss] == ucontrol->value.integer.value[0]) - return 0; - - if (ucontrol->value.integer.value[0] > 1) - return -EINVAL; - - if (!wm8994->mbc_vss) - return -ENODEV; - - if (wm8958_dsp2_busy(wm8994, vss)) { - dev_dbg(codec->dev, "DSP2 active on %d already\n", vss); - return -EBUSY; - } - - if (wm8994->enh_eq_ena[vss]) - return -EBUSY; - - wm8994->vss_ena[vss] = ucontrol->value.integer.value[0]; - - wm8958_dsp_apply(codec, vss, wm8994->vss_ena[vss]); - - return 0; -} - - -#define WM8958_VSS_SWITCH(xname, xval) {\ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .info = wm8958_vss_info, \ - .get = wm8958_vss_get, .put = wm8958_vss_put, \ - .private_value = xval } - -static int wm8958_hpf_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int wm8958_hpf_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int hpf = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (hpf < 3) - ucontrol->value.integer.value[0] = wm8994->hpf1_ena[hpf % 3]; - else - ucontrol->value.integer.value[0] = wm8994->hpf2_ena[hpf % 3]; - - return 0; -} - -static int wm8958_hpf_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int hpf = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (hpf < 3) { - if (wm8994->hpf1_ena[hpf % 3] == - ucontrol->value.integer.value[0]) - return 0; - } else { - if (wm8994->hpf2_ena[hpf % 3] == - ucontrol->value.integer.value[0]) - return 0; - } - - if (ucontrol->value.integer.value[0] > 1) - return -EINVAL; - - if (!wm8994->mbc_vss) - return -ENODEV; - - if (wm8958_dsp2_busy(wm8994, hpf % 3)) { - dev_dbg(codec->dev, "DSP2 active on %d already\n", hpf); - return -EBUSY; - } - - if (wm8994->enh_eq_ena[hpf % 3]) - return -EBUSY; - - if (hpf < 3) - wm8994->hpf1_ena[hpf % 3] = ucontrol->value.integer.value[0]; - else - wm8994->hpf2_ena[hpf % 3] = ucontrol->value.integer.value[0]; - - wm8958_dsp_apply(codec, hpf % 3, ucontrol->value.integer.value[0]); - - return 0; -} - -#define WM8958_HPF_SWITCH(xname, xval) {\ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .info = wm8958_hpf_info, \ - .get = wm8958_hpf_get, .put = wm8958_hpf_put, \ - .private_value = xval } - -static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int value = ucontrol->value.integer.value[0]; - int reg; - - /* Don't allow on the fly reconfiguration */ - reg = snd_soc_read(codec, WM8994_CLOCKING_1); - if (reg < 0 || reg & WM8958_DSP2CLK_ENA) - return -EBUSY; - - if (value >= pdata->num_enh_eq_cfgs) - return -EINVAL; - - wm8994->enh_eq_cfg = value; - - return 0; -} - -static int wm8958_get_enh_eq_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8994->enh_eq_cfg; - - return 0; -} - -static int wm8958_enh_eq_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int wm8958_enh_eq_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int eq = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = wm8994->enh_eq_ena[eq]; - - return 0; -} - -static int wm8958_enh_eq_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int eq = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (wm8994->enh_eq_ena[eq] == ucontrol->value.integer.value[0]) - return 0; - - if (ucontrol->value.integer.value[0] > 1) - return -EINVAL; - - if (!wm8994->enh_eq) - return -ENODEV; - - if (wm8958_dsp2_busy(wm8994, eq)) { - dev_dbg(codec->dev, "DSP2 active on %d already\n", eq); - return -EBUSY; - } - - if (wm8994->mbc_ena[eq] || wm8994->vss_ena[eq] || - wm8994->hpf1_ena[eq] || wm8994->hpf2_ena[eq]) - return -EBUSY; - - wm8994->enh_eq_ena[eq] = ucontrol->value.integer.value[0]; - - wm8958_dsp_apply(codec, eq, ucontrol->value.integer.value[0]); - - return 0; -} - -#define WM8958_ENH_EQ_SWITCH(xname, xval) {\ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .info = wm8958_enh_eq_info, \ - .get = wm8958_enh_eq_get, .put = wm8958_enh_eq_put, \ - .private_value = xval } - -static const struct snd_kcontrol_new wm8958_mbc_snd_controls[] = { -WM8958_MBC_SWITCH("AIF1DAC1 MBC Switch", 0), -WM8958_MBC_SWITCH("AIF1DAC2 MBC Switch", 1), -WM8958_MBC_SWITCH("AIF2DAC MBC Switch", 2), -}; - -static const struct snd_kcontrol_new wm8958_vss_snd_controls[] = { -WM8958_VSS_SWITCH("AIF1DAC1 VSS Switch", 0), -WM8958_VSS_SWITCH("AIF1DAC2 VSS Switch", 1), -WM8958_VSS_SWITCH("AIF2DAC VSS Switch", 2), -WM8958_HPF_SWITCH("AIF1DAC1 HPF1 Switch", 0), -WM8958_HPF_SWITCH("AIF1DAC2 HPF1 Switch", 1), -WM8958_HPF_SWITCH("AIF2DAC HPF1 Switch", 2), -WM8958_HPF_SWITCH("AIF1DAC1 HPF2 Switch", 3), -WM8958_HPF_SWITCH("AIF1DAC2 HPF2 Switch", 4), -WM8958_HPF_SWITCH("AIF2DAC HPF2 Switch", 5), -}; - -static const struct snd_kcontrol_new wm8958_enh_eq_snd_controls[] = { -WM8958_ENH_EQ_SWITCH("AIF1DAC1 Enhanced EQ Switch", 0), -WM8958_ENH_EQ_SWITCH("AIF1DAC2 Enhanced EQ Switch", 1), -WM8958_ENH_EQ_SWITCH("AIF2DAC Enhanced EQ Switch", 2), -}; - -static void wm8958_enh_eq_loaded(const struct firmware *fw, void *context) -{ - struct snd_soc_codec *codec = context; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (fw && (wm8958_dsp2_fw(codec, "ENH_EQ", fw, true) == 0)) { - mutex_lock(&codec->mutex); - wm8994->enh_eq = fw; - mutex_unlock(&codec->mutex); - } -} - -static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context) -{ - struct snd_soc_codec *codec = context; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (fw && (wm8958_dsp2_fw(codec, "MBC+VSS", fw, true) == 0)) { - mutex_lock(&codec->mutex); - wm8994->mbc_vss = fw; - mutex_unlock(&codec->mutex); - } - - /* We can't have more than one request outstanding at once so - * we daisy chain. - */ - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL, - codec, wm8958_enh_eq_loaded); -} - -static void wm8958_mbc_loaded(const struct firmware *fw, void *context) -{ - struct snd_soc_codec *codec = context; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (wm8958_dsp2_fw(codec, "MBC", fw, true) != 0) - return; - - mutex_lock(&codec->mutex); - wm8994->mbc = fw; - mutex_unlock(&codec->mutex); - - /* We can't have more than one request outstanding at once so - * we daisy chain. - */ - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL, - codec, wm8958_mbc_vss_loaded); -} - -void wm8958_dsp2_init(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int ret, i; - - wm8994->dsp_active = -1; - - snd_soc_add_codec_controls(codec, wm8958_mbc_snd_controls, - ARRAY_SIZE(wm8958_mbc_snd_controls)); - snd_soc_add_codec_controls(codec, wm8958_vss_snd_controls, - ARRAY_SIZE(wm8958_vss_snd_controls)); - snd_soc_add_codec_controls(codec, wm8958_enh_eq_snd_controls, - ARRAY_SIZE(wm8958_enh_eq_snd_controls)); - - - /* We don't *require* firmware and don't want to delay boot */ - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - "wm8958_mbc.wfw", codec->dev, GFP_KERNEL, - codec, wm8958_mbc_loaded); - - if (!pdata) - return; - - if (pdata->num_mbc_cfgs) { - struct snd_kcontrol_new control[] = { - SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum, - wm8958_get_mbc_enum, wm8958_put_mbc_enum), - }; - - /* We need an array of texts for the enum API */ - wm8994->mbc_texts = kmalloc(sizeof(char *) - * pdata->num_mbc_cfgs, GFP_KERNEL); - if (!wm8994->mbc_texts) { - dev_err(wm8994->codec->dev, - "Failed to allocate %d MBC config texts\n", - pdata->num_mbc_cfgs); - return; - } - - for (i = 0; i < pdata->num_mbc_cfgs; i++) - wm8994->mbc_texts[i] = pdata->mbc_cfgs[i].name; - - wm8994->mbc_enum.max = pdata->num_mbc_cfgs; - wm8994->mbc_enum.texts = wm8994->mbc_texts; - - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); - if (ret != 0) - dev_err(wm8994->codec->dev, - "Failed to add MBC mode controls: %d\n", ret); - } - - if (pdata->num_vss_cfgs) { - struct snd_kcontrol_new control[] = { - SOC_ENUM_EXT("VSS Mode", wm8994->vss_enum, - wm8958_get_vss_enum, wm8958_put_vss_enum), - }; - - /* We need an array of texts for the enum API */ - wm8994->vss_texts = kmalloc(sizeof(char *) - * pdata->num_vss_cfgs, GFP_KERNEL); - if (!wm8994->vss_texts) { - dev_err(wm8994->codec->dev, - "Failed to allocate %d VSS config texts\n", - pdata->num_vss_cfgs); - return; - } - - for (i = 0; i < pdata->num_vss_cfgs; i++) - wm8994->vss_texts[i] = pdata->vss_cfgs[i].name; - - wm8994->vss_enum.max = pdata->num_vss_cfgs; - wm8994->vss_enum.texts = wm8994->vss_texts; - - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); - if (ret != 0) - dev_err(wm8994->codec->dev, - "Failed to add VSS mode controls: %d\n", ret); - } - - if (pdata->num_vss_hpf_cfgs) { - struct snd_kcontrol_new control[] = { - SOC_ENUM_EXT("VSS HPF Mode", wm8994->vss_hpf_enum, - wm8958_get_vss_hpf_enum, - wm8958_put_vss_hpf_enum), - }; - - /* We need an array of texts for the enum API */ - wm8994->vss_hpf_texts = kmalloc(sizeof(char *) - * pdata->num_vss_hpf_cfgs, GFP_KERNEL); - if (!wm8994->vss_hpf_texts) { - dev_err(wm8994->codec->dev, - "Failed to allocate %d VSS HPF config texts\n", - pdata->num_vss_hpf_cfgs); - return; - } - - for (i = 0; i < pdata->num_vss_hpf_cfgs; i++) - wm8994->vss_hpf_texts[i] = pdata->vss_hpf_cfgs[i].name; - - wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; - wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; - - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); - if (ret != 0) - dev_err(wm8994->codec->dev, - "Failed to add VSS HPFmode controls: %d\n", - ret); - } - - if (pdata->num_enh_eq_cfgs) { - struct snd_kcontrol_new control[] = { - SOC_ENUM_EXT("Enhanced EQ Mode", wm8994->enh_eq_enum, - wm8958_get_enh_eq_enum, - wm8958_put_enh_eq_enum), - }; - - /* We need an array of texts for the enum API */ - wm8994->enh_eq_texts = kmalloc(sizeof(char *) - * pdata->num_enh_eq_cfgs, GFP_KERNEL); - if (!wm8994->enh_eq_texts) { - dev_err(wm8994->codec->dev, - "Failed to allocate %d enhanced EQ config texts\n", - pdata->num_enh_eq_cfgs); - return; - } - - for (i = 0; i < pdata->num_enh_eq_cfgs; i++) - wm8994->enh_eq_texts[i] = pdata->enh_eq_cfgs[i].name; - - wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; - wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; - - ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); - if (ret != 0) - dev_err(wm8994->codec->dev, - "Failed to add enhanced EQ controls: %d\n", - ret); - } -} diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8960.c b/ANDROID_3.4.5/sound/soc/codecs/wm8960.c deleted file mode 100644 index 840d7208..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8960.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * wm8960.c -- WM8960 ALSA SoC Audio driver - * - * Author: Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8960.h" - -/* R25 - Power 1 */ -#define WM8960_VMID_MASK 0x180 -#define WM8960_VREF 0x40 - -/* R26 - Power 2 */ -#define WM8960_PWR2_LOUT1 0x40 -#define WM8960_PWR2_ROUT1 0x20 -#define WM8960_PWR2_OUT3 0x02 - -/* R28 - Anti-pop 1 */ -#define WM8960_POBCTRL 0x80 -#define WM8960_BUFDCOPEN 0x10 -#define WM8960_BUFIOEN 0x08 -#define WM8960_SOFT_ST 0x04 -#define WM8960_HPSTBY 0x01 - -/* R29 - Anti-pop 2 */ -#define WM8960_DISOP 0x40 -#define WM8960_DRES_MASK 0x30 - -/* - * wm8960 register cache - * We can't read the WM8960 register space when we are - * using 2 wire for device control, so we cache them instead. - */ -static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { - 0x0097, 0x0097, 0x0000, 0x0000, - 0x0000, 0x0008, 0x0000, 0x000a, - 0x01c0, 0x0000, 0x00ff, 0x00ff, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x007b, 0x0100, 0x0032, - 0x0000, 0x00c3, 0x00c3, 0x01c0, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0100, 0x0100, 0x0050, 0x0050, - 0x0050, 0x0050, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0040, 0x0000, - 0x0000, 0x0050, 0x0050, 0x0000, - 0x0002, 0x0037, 0x004d, 0x0080, - 0x0008, 0x0031, 0x0026, 0x00e9, -}; - -struct wm8960_priv { - enum snd_soc_control_type control_type; - int (*set_bias_level)(struct snd_soc_codec *, - enum snd_soc_bias_level level); - struct snd_soc_dapm_widget *lout1; - struct snd_soc_dapm_widget *rout1; - struct snd_soc_dapm_widget *out3; - bool deemph; - int playback_fs; -}; - -#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) - -/* enumerated controls */ -static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted", - "Right Inverted", "Stereo Inversion"}; -static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"}; -static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"}; -static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"}; -static const char *wm8960_alcmode[] = {"ALC", "Limiter"}; - -static const struct soc_enum wm8960_enum[] = { - SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity), - SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity), - SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff), - SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff), - SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc), - SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode), -}; - -static const int deemph_settings[] = { 0, 32000, 44100, 48000 }; - -static int wm8960_set_deemph(struct snd_soc_codec *codec) -{ - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int val, i, best; - - /* If we're using deemphasis select the nearest available sample - * rate. - */ - if (wm8960->deemph) { - best = 1; - for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { - if (abs(deemph_settings[i] - wm8960->playback_fs) < - abs(deemph_settings[best] - wm8960->playback_fs)) - best = i; - } - - val = best << 1; - } else { - val = 0; - } - - dev_dbg(codec->dev, "Set deemphasis %d\n", val); - - return snd_soc_update_bits(codec, WM8960_DACCTL1, - 0x6, val); -} - -static int wm8960_get_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.enumerated.item[0] = wm8960->deemph; - return 0; -} - -static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int deemph = ucontrol->value.enumerated.item[0]; - - if (deemph > 1) - return -EINVAL; - - wm8960->deemph = deemph; - - return wm8960_set_deemph(codec); -} - -static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0); -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); -static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); - -static const struct snd_kcontrol_new wm8960_snd_controls[] = { -SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL, - 0, 63, 0, adc_tlv), -SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL, - 6, 1, 0), -SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL, - 7, 1, 0), - -SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC, - 0, 255, 0, dac_tlv), - -SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8960_LOUT1, WM8960_ROUT1, - 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8960_LOUT1, WM8960_ROUT1, - 7, 1, 0), - -SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8960_LOUT2, WM8960_ROUT2, - 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8960_LOUT2, WM8960_ROUT2, - 7, 1, 0), -SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0), -SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0), - -SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0), -SOC_ENUM("ADC Polarity", wm8960_enum[0]), -SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0), - -SOC_ENUM("DAC Polarity", wm8960_enum[2]), -SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, - wm8960_get_deemph, wm8960_put_deemph), - -SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[2]), -SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[3]), -SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0), -SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0), - -SOC_ENUM("ALC Function", wm8960_enum[4]), -SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0), -SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1), -SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0), -SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0), -SOC_ENUM("ALC Mode", wm8960_enum[5]), -SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0), -SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0), - -SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0), -SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0), - -SOC_DOUBLE_R("ADC PCM Capture Volume", WM8960_LINPATH, WM8960_RINPATH, - 0, 127, 0), - -SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume", - WM8960_BYPASS1, 4, 7, 1, bypass_tlv), -SOC_SINGLE_TLV("Left Output Mixer LINPUT3 Volume", - WM8960_LOUTMIX, 4, 7, 1, bypass_tlv), -SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume", - WM8960_BYPASS2, 4, 7, 1, bypass_tlv), -SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume", - WM8960_ROUTMIX, 4, 7, 1, bypass_tlv), -}; - -static const struct snd_kcontrol_new wm8960_lin_boost[] = { -SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH, 6, 1, 0), -SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LINPATH, 7, 1, 0), -SOC_DAPM_SINGLE("LINPUT1 Switch", WM8960_LINPATH, 8, 1, 0), -}; - -static const struct snd_kcontrol_new wm8960_lin[] = { -SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH, 3, 1, 0), -}; - -static const struct snd_kcontrol_new wm8960_rin_boost[] = { -SOC_DAPM_SINGLE("RINPUT2 Switch", WM8960_RINPATH, 6, 1, 0), -SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_RINPATH, 7, 1, 0), -SOC_DAPM_SINGLE("RINPUT1 Switch", WM8960_RINPATH, 8, 1, 0), -}; - -static const struct snd_kcontrol_new wm8960_rin[] = { -SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH, 3, 1, 0), -}; - -static const struct snd_kcontrol_new wm8960_loutput_mixer[] = { -SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_LOUTMIX, 8, 1, 0), -SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LOUTMIX, 7, 1, 0), -SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1, 7, 1, 0), -}; - -static const struct snd_kcontrol_new wm8960_routput_mixer[] = { -SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_ROUTMIX, 8, 1, 0), -SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_ROUTMIX, 7, 1, 0), -SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2, 7, 1, 0), -}; - -static const struct snd_kcontrol_new wm8960_mono_out[] = { -SOC_DAPM_SINGLE("Left Switch", WM8960_MONOMIX1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Switch", WM8960_MONOMIX2, 7, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8960_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("LINPUT1"), -SND_SOC_DAPM_INPUT("RINPUT1"), -SND_SOC_DAPM_INPUT("LINPUT2"), -SND_SOC_DAPM_INPUT("RINPUT2"), -SND_SOC_DAPM_INPUT("LINPUT3"), -SND_SOC_DAPM_INPUT("RINPUT3"), - -SND_SOC_DAPM_SUPPLY("MICB", WM8960_POWER1, 1, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0, - wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)), -SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1, 4, 0, - wm8960_rin_boost, ARRAY_SIZE(wm8960_rin_boost)), - -SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3, 5, 0, - wm8960_lin, ARRAY_SIZE(wm8960_lin)), -SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3, 4, 0, - wm8960_rin, ARRAY_SIZE(wm8960_rin)), - -SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER2, 3, 0), -SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER2, 2, 0), - -SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2, 8, 0), -SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2, 7, 0), - -SND_SOC_DAPM_MIXER("Left Output Mixer", WM8960_POWER3, 3, 0, - &wm8960_loutput_mixer[0], - ARRAY_SIZE(wm8960_loutput_mixer)), -SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0, - &wm8960_routput_mixer[0], - ARRAY_SIZE(wm8960_routput_mixer)), - -SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), - -SND_SOC_DAPM_PGA("Left Speaker PGA", WM8960_POWER2, 4, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Speaker PGA", WM8960_POWER2, 3, 0, NULL, 0), - -SND_SOC_DAPM_PGA("Right Speaker Output", WM8960_CLASSD1, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Left Speaker Output", WM8960_CLASSD1, 6, 0, NULL, 0), - -SND_SOC_DAPM_OUTPUT("SPK_LP"), -SND_SOC_DAPM_OUTPUT("SPK_LN"), -SND_SOC_DAPM_OUTPUT("HP_L"), -SND_SOC_DAPM_OUTPUT("HP_R"), -SND_SOC_DAPM_OUTPUT("SPK_RP"), -SND_SOC_DAPM_OUTPUT("SPK_RN"), -SND_SOC_DAPM_OUTPUT("OUT3"), -}; - -static const struct snd_soc_dapm_widget wm8960_dapm_widgets_out3[] = { -SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0, - &wm8960_mono_out[0], - ARRAY_SIZE(wm8960_mono_out)), -}; - -/* Represent OUT3 as a PGA so that it gets turned on with LOUT1/ROUT1 */ -static const struct snd_soc_dapm_widget wm8960_dapm_widgets_capless[] = { -SND_SOC_DAPM_PGA("OUT3 VMID", WM8960_POWER2, 1, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_route audio_paths[] = { - { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" }, - { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" }, - { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" }, - - { "Left Input Mixer", "Boost Switch", "Left Boost Mixer", }, - { "Left Input Mixer", NULL, "LINPUT1", }, /* Really Boost Switch */ - { "Left Input Mixer", NULL, "LINPUT2" }, - { "Left Input Mixer", NULL, "LINPUT3" }, - - { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" }, - { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" }, - { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" }, - - { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", }, - { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */ - { "Right Input Mixer", NULL, "RINPUT2" }, - { "Right Input Mixer", NULL, "LINPUT3" }, - - { "Left ADC", NULL, "Left Input Mixer" }, - { "Right ADC", NULL, "Right Input Mixer" }, - - { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" }, - { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer"} , - { "Left Output Mixer", "PCM Playback Switch", "Left DAC" }, - - { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" }, - { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } , - { "Right Output Mixer", "PCM Playback Switch", "Right DAC" }, - - { "LOUT1 PGA", NULL, "Left Output Mixer" }, - { "ROUT1 PGA", NULL, "Right Output Mixer" }, - - { "HP_L", NULL, "LOUT1 PGA" }, - { "HP_R", NULL, "ROUT1 PGA" }, - - { "Left Speaker PGA", NULL, "Left Output Mixer" }, - { "Right Speaker PGA", NULL, "Right Output Mixer" }, - - { "Left Speaker Output", NULL, "Left Speaker PGA" }, - { "Right Speaker Output", NULL, "Right Speaker PGA" }, - - { "SPK_LN", NULL, "Left Speaker Output" }, - { "SPK_LP", NULL, "Left Speaker Output" }, - { "SPK_RN", NULL, "Right Speaker Output" }, - { "SPK_RP", NULL, "Right Speaker Output" }, -}; - -static const struct snd_soc_dapm_route audio_paths_out3[] = { - { "Mono Output Mixer", "Left Switch", "Left Output Mixer" }, - { "Mono Output Mixer", "Right Switch", "Right Output Mixer" }, - - { "OUT3", NULL, "Mono Output Mixer", } -}; - -static const struct snd_soc_dapm_route audio_paths_capless[] = { - { "HP_L", NULL, "OUT3 VMID" }, - { "HP_R", NULL, "OUT3 VMID" }, - - { "OUT3 VMID", NULL, "Left Output Mixer" }, - { "OUT3 VMID", NULL, "Right Output Mixer" }, -}; - -static int wm8960_add_widgets(struct snd_soc_codec *codec) -{ - struct wm8960_data *pdata = codec->dev->platform_data; - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - struct snd_soc_dapm_widget *w; - - snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets, - ARRAY_SIZE(wm8960_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); - - /* In capless mode OUT3 is used to provide VMID for the - * headphone outputs, otherwise it is used as a mono mixer. - */ - if (pdata && pdata->capless) { - snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets_capless, - ARRAY_SIZE(wm8960_dapm_widgets_capless)); - - snd_soc_dapm_add_routes(dapm, audio_paths_capless, - ARRAY_SIZE(audio_paths_capless)); - } else { - snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets_out3, - ARRAY_SIZE(wm8960_dapm_widgets_out3)); - - snd_soc_dapm_add_routes(dapm, audio_paths_out3, - ARRAY_SIZE(audio_paths_out3)); - } - - /* We need to power up the headphone output stage out of - * sequence for capless mode. To save scanning the widget - * list each time to find the desired power state do so now - * and save the result. - */ - list_for_each_entry(w, &codec->card->widgets, list) { - if (w->dapm != &codec->dapm) - continue; - if (strcmp(w->name, "LOUT1 PGA") == 0) - wm8960->lout1 = w; - if (strcmp(w->name, "ROUT1 PGA") == 0) - wm8960->rout1 = w; - if (strcmp(w->name, "OUT3 VMID") == 0) - wm8960->out3 = w; - } - - return 0; -} - -static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface |= 0x0040; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - /* set iface */ - snd_soc_write(codec, WM8960_IFACE1, iface); - return 0; -} - -static struct { - int rate; - unsigned int val; -} alc_rates[] = { - { 48000, 0 }, - { 44100, 0 }, - { 32000, 1 }, - { 22050, 2 }, - { 24000, 2 }, - { 16000, 3 }, - { 11250, 4 }, - { 12000, 4 }, - { 8000, 5 }, -}; - -static int wm8960_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; - int i; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - } - - /* Update filters for the new rate */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - wm8960->playback_fs = params_rate(params); - wm8960_set_deemph(codec); - } else { - for (i = 0; i < ARRAY_SIZE(alc_rates); i++) - if (alc_rates[i].rate == params_rate(params)) - snd_soc_update_bits(codec, - WM8960_ADDCTL3, 0x7, - alc_rates[i].val); - } - - /* set iface */ - snd_soc_write(codec, WM8960_IFACE1, iface); - return 0; -} - -static int wm8960_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - if (mute) - snd_soc_update_bits(codec, WM8960_DACCTL1, 0x8, 0x8); - else - snd_soc_update_bits(codec, WM8960_DACCTL1, 0x8, 0); - return 0; -} - -static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* Set VMID to 2x50k */ - snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); - - /* Enable anti-pop features */ - snd_soc_write(codec, WM8960_APOP1, - WM8960_POBCTRL | WM8960_SOFT_ST | - WM8960_BUFDCOPEN | WM8960_BUFIOEN); - - /* Enable & ramp VMID at 2x50k */ - snd_soc_update_bits(codec, WM8960_POWER1, 0x80, 0x80); - msleep(100); - - /* Enable VREF */ - snd_soc_update_bits(codec, WM8960_POWER1, WM8960_VREF, - WM8960_VREF); - - /* Disable anti-pop features */ - snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN); - } - - /* Set VMID to 2x250k */ - snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x100); - break; - - case SND_SOC_BIAS_OFF: - /* Enable anti-pop features */ - snd_soc_write(codec, WM8960_APOP1, - WM8960_POBCTRL | WM8960_SOFT_ST | - WM8960_BUFDCOPEN | WM8960_BUFIOEN); - - /* Disable VMID and VREF, let them discharge */ - snd_soc_write(codec, WM8960_POWER1, 0); - msleep(600); - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int reg; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - switch (codec->dapm.bias_level) { - case SND_SOC_BIAS_STANDBY: - /* Enable anti pop mode */ - snd_soc_update_bits(codec, WM8960_APOP1, - WM8960_POBCTRL | WM8960_SOFT_ST | - WM8960_BUFDCOPEN, - WM8960_POBCTRL | WM8960_SOFT_ST | - WM8960_BUFDCOPEN); - - /* Enable LOUT1, ROUT1 and OUT3 if they're enabled */ - reg = 0; - if (wm8960->lout1 && wm8960->lout1->power) - reg |= WM8960_PWR2_LOUT1; - if (wm8960->rout1 && wm8960->rout1->power) - reg |= WM8960_PWR2_ROUT1; - if (wm8960->out3 && wm8960->out3->power) - reg |= WM8960_PWR2_OUT3; - snd_soc_update_bits(codec, WM8960_POWER2, - WM8960_PWR2_LOUT1 | - WM8960_PWR2_ROUT1 | - WM8960_PWR2_OUT3, reg); - - /* Enable VMID at 2*50k */ - snd_soc_update_bits(codec, WM8960_POWER1, - WM8960_VMID_MASK, 0x80); - - /* Ramp */ - msleep(100); - - /* Enable VREF */ - snd_soc_update_bits(codec, WM8960_POWER1, - WM8960_VREF, WM8960_VREF); - - msleep(100); - break; - - case SND_SOC_BIAS_ON: - /* Enable anti-pop mode */ - snd_soc_update_bits(codec, WM8960_APOP1, - WM8960_POBCTRL | WM8960_SOFT_ST | - WM8960_BUFDCOPEN, - WM8960_POBCTRL | WM8960_SOFT_ST | - WM8960_BUFDCOPEN); - - /* Disable VMID and VREF */ - snd_soc_update_bits(codec, WM8960_POWER1, - WM8960_VREF | WM8960_VMID_MASK, 0); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_cache_sync(codec); - break; - default: - break; - } - break; - - case SND_SOC_BIAS_STANDBY: - switch (codec->dapm.bias_level) { - case SND_SOC_BIAS_PREPARE: - /* Disable HP discharge */ - snd_soc_update_bits(codec, WM8960_APOP2, - WM8960_DISOP | WM8960_DRES_MASK, - 0); - - /* Disable anti-pop features */ - snd_soc_update_bits(codec, WM8960_APOP1, - WM8960_POBCTRL | WM8960_SOFT_ST | - WM8960_BUFDCOPEN, - WM8960_POBCTRL | WM8960_SOFT_ST | - WM8960_BUFDCOPEN); - break; - - default: - break; - } - break; - - case SND_SOC_BIAS_OFF: - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -/* PLL divisors */ -struct _pll_div { - u32 pre_div:1; - u32 n:4; - u32 k:24; -}; - -/* The size in bits of the pll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 24) * 10) - -static int pll_factors(unsigned int source, unsigned int target, - struct _pll_div *pll_div) -{ - unsigned long long Kpart; - unsigned int K, Ndiv, Nmod; - - pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source, target); - - /* Scale up target to PLL operating frequency */ - target *= 4; - - Ndiv = target / source; - if (Ndiv < 6) { - source >>= 1; - pll_div->pre_div = 1; - Ndiv = target / source; - } else - pll_div->pre_div = 0; - - if ((Ndiv < 6) || (Ndiv > 12)) { - pr_err("WM8960 PLL: Unsupported N=%d\n", Ndiv); - return -EINVAL; - } - - pll_div->n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div->k = K; - - pr_debug("WM8960 PLL: N=%x K=%x pre_div=%d\n", - pll_div->n, pll_div->k, pll_div->pre_div); - - return 0; -} - -static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - static struct _pll_div pll_div; - int ret; - - if (freq_in && freq_out) { - ret = pll_factors(freq_in, freq_out, &pll_div); - if (ret != 0) - return ret; - } - - /* Disable the PLL: even if we are changing the frequency the - * PLL needs to be disabled while we do so. */ - snd_soc_update_bits(codec, WM8960_CLOCK1, 0x1, 0); - snd_soc_update_bits(codec, WM8960_POWER2, 0x1, 0); - - if (!freq_in || !freq_out) - return 0; - - reg = snd_soc_read(codec, WM8960_PLL1) & ~0x3f; - reg |= pll_div.pre_div << 4; - reg |= pll_div.n; - - if (pll_div.k) { - reg |= 0x20; - - snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); - snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); - } - snd_soc_write(codec, WM8960_PLL1, reg); - - /* Turn it on */ - snd_soc_update_bits(codec, WM8960_POWER2, 0x1, 0x1); - msleep(250); - snd_soc_update_bits(codec, WM8960_CLOCK1, 0x1, 0x1); - - return 0; -} - -static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM8960_SYSCLKDIV: - reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9; - snd_soc_write(codec, WM8960_CLOCK1, reg | div); - break; - case WM8960_DACDIV: - reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1c7; - snd_soc_write(codec, WM8960_CLOCK1, reg | div); - break; - case WM8960_OPCLKDIV: - reg = snd_soc_read(codec, WM8960_PLL1) & 0x03f; - snd_soc_write(codec, WM8960_PLL1, reg | div); - break; - case WM8960_DCLKDIV: - reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f; - snd_soc_write(codec, WM8960_CLOCK2, reg | div); - break; - case WM8960_TOCLKSEL: - reg = snd_soc_read(codec, WM8960_ADDCTL1) & 0x1fd; - snd_soc_write(codec, WM8960_ADDCTL1, reg | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int wm8960_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - - return wm8960->set_bias_level(codec, level); -} - -#define WM8960_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM8960_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8960_dai_ops = { - .hw_params = wm8960_hw_params, - .digital_mute = wm8960_mute, - .set_fmt = wm8960_set_dai_fmt, - .set_clkdiv = wm8960_set_dai_clkdiv, - .set_pll = wm8960_set_dai_pll, -}; - -static struct snd_soc_dai_driver wm8960_dai = { - .name = "wm8960-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8960_RATES, - .formats = WM8960_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8960_RATES, - .formats = WM8960_FORMATS,}, - .ops = &wm8960_dai_ops, - .symmetric_rates = 1, -}; - -static int wm8960_suspend(struct snd_soc_codec *codec) -{ - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - - wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8960_resume(struct snd_soc_codec *codec) -{ - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - - wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int wm8960_probe(struct snd_soc_codec *codec) -{ - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - struct wm8960_data *pdata = dev_get_platdata(codec->dev); - int ret; - - wm8960->set_bias_level = wm8960_set_bias_level_out3; - - if (!pdata) { - dev_warn(codec->dev, "No platform data supplied\n"); - } else { - if (pdata->dres > WM8960_DRES_MAX) { - dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); - pdata->dres = 0; - } - - if (pdata->capless) - wm8960->set_bias_level = wm8960_set_bias_level_capless; - } - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = wm8960_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch the update bits */ - snd_soc_update_bits(codec, WM8960_LINVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_RINVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_LADC, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_RADC, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_LDAC, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_RDAC, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_LOUT1, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_ROUT1, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100); - snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100); - - snd_soc_add_codec_controls(codec, wm8960_snd_controls, - ARRAY_SIZE(wm8960_snd_controls)); - wm8960_add_widgets(codec); - - return 0; -} - -/* power down chip */ -static int wm8960_remove(struct snd_soc_codec *codec) -{ - struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - - wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { - .probe = wm8960_probe, - .remove = wm8960_remove, - .suspend = wm8960_suspend, - .resume = wm8960_resume, - .set_bias_level = wm8960_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8960_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8960_reg, -}; - -static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8960_priv *wm8960; - int ret; - - wm8960 = devm_kzalloc(&i2c->dev, sizeof(struct wm8960_priv), - GFP_KERNEL); - if (wm8960 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8960); - wm8960->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8960, &wm8960_dai, 1); - - return ret; -} - -static __devexit int wm8960_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id wm8960_i2c_id[] = { - { "wm8960", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); - -static struct i2c_driver wm8960_i2c_driver = { - .driver = { - .name = "wm8960", - .owner = THIS_MODULE, - }, - .probe = wm8960_i2c_probe, - .remove = __devexit_p(wm8960_i2c_remove), - .id_table = wm8960_i2c_id, -}; - -static int __init wm8960_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8960_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8960_modinit); - -static void __exit wm8960_exit(void) -{ - i2c_del_driver(&wm8960_i2c_driver); -} -module_exit(wm8960_exit); - -MODULE_DESCRIPTION("ASoC WM8960 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8960.h b/ANDROID_3.4.5/sound/soc/codecs/wm8960.h deleted file mode 100644 index 2d8163d7..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8960.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * wm8960.h -- WM8960 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8960_H -#define _WM8960_H - -/* WM8960 register space */ - - -#define WM8960_CACHEREGNUM 56 - -#define WM8960_LINVOL 0x0 -#define WM8960_RINVOL 0x1 -#define WM8960_LOUT1 0x2 -#define WM8960_ROUT1 0x3 -#define WM8960_CLOCK1 0x4 -#define WM8960_DACCTL1 0x5 -#define WM8960_DACCTL2 0x6 -#define WM8960_IFACE1 0x7 -#define WM8960_CLOCK2 0x8 -#define WM8960_IFACE2 0x9 -#define WM8960_LDAC 0xa -#define WM8960_RDAC 0xb - -#define WM8960_RESET 0xf -#define WM8960_3D 0x10 -#define WM8960_ALC1 0x11 -#define WM8960_ALC2 0x12 -#define WM8960_ALC3 0x13 -#define WM8960_NOISEG 0x14 -#define WM8960_LADC 0x15 -#define WM8960_RADC 0x16 -#define WM8960_ADDCTL1 0x17 -#define WM8960_ADDCTL2 0x18 -#define WM8960_POWER1 0x19 -#define WM8960_POWER2 0x1a -#define WM8960_ADDCTL3 0x1b -#define WM8960_APOP1 0x1c -#define WM8960_APOP2 0x1d - -#define WM8960_LINPATH 0x20 -#define WM8960_RINPATH 0x21 -#define WM8960_LOUTMIX 0x22 - -#define WM8960_ROUTMIX 0x25 -#define WM8960_MONOMIX1 0x26 -#define WM8960_MONOMIX2 0x27 -#define WM8960_LOUT2 0x28 -#define WM8960_ROUT2 0x29 -#define WM8960_MONO 0x2a -#define WM8960_INBMIX1 0x2b -#define WM8960_INBMIX2 0x2c -#define WM8960_BYPASS1 0x2d -#define WM8960_BYPASS2 0x2e -#define WM8960_POWER3 0x2f -#define WM8960_ADDCTL4 0x30 -#define WM8960_CLASSD1 0x31 - -#define WM8960_CLASSD3 0x33 -#define WM8960_PLL1 0x34 -#define WM8960_PLL2 0x35 -#define WM8960_PLL3 0x36 -#define WM8960_PLL4 0x37 - - -/* - * WM8960 Clock dividers - */ -#define WM8960_SYSCLKDIV 0 -#define WM8960_DACDIV 1 -#define WM8960_OPCLKDIV 2 -#define WM8960_DCLKDIV 3 -#define WM8960_TOCLKSEL 4 - -#define WM8960_SYSCLK_DIV_1 (0 << 1) -#define WM8960_SYSCLK_DIV_2 (2 << 1) - -#define WM8960_SYSCLK_MCLK (0 << 0) -#define WM8960_SYSCLK_PLL (1 << 0) - -#define WM8960_DAC_DIV_1 (0 << 3) -#define WM8960_DAC_DIV_1_5 (1 << 3) -#define WM8960_DAC_DIV_2 (2 << 3) -#define WM8960_DAC_DIV_3 (3 << 3) -#define WM8960_DAC_DIV_4 (4 << 3) -#define WM8960_DAC_DIV_5_5 (5 << 3) -#define WM8960_DAC_DIV_6 (6 << 3) - -#define WM8960_DCLK_DIV_1_5 (0 << 6) -#define WM8960_DCLK_DIV_2 (1 << 6) -#define WM8960_DCLK_DIV_3 (2 << 6) -#define WM8960_DCLK_DIV_4 (3 << 6) -#define WM8960_DCLK_DIV_6 (4 << 6) -#define WM8960_DCLK_DIV_8 (5 << 6) -#define WM8960_DCLK_DIV_12 (6 << 6) -#define WM8960_DCLK_DIV_16 (7 << 6) - -#define WM8960_TOCLK_F19 (0 << 1) -#define WM8960_TOCLK_F21 (1 << 1) - -#define WM8960_OPCLK_DIV_1 (0 << 0) -#define WM8960_OPCLK_DIV_2 (1 << 0) -#define WM8960_OPCLK_DIV_3 (2 << 0) -#define WM8960_OPCLK_DIV_4 (3 << 0) -#define WM8960_OPCLK_DIV_5_5 (4 << 0) -#define WM8960_OPCLK_DIV_6 (5 << 0) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8961.c b/ANDROID_3.4.5/sound/soc/codecs/wm8961.c deleted file mode 100644 index 05ea7c27..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8961.c +++ /dev/null @@ -1,1135 +0,0 @@ -/* - * wm8961.c -- WM8961 ALSA SoC Audio driver - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Currently unimplemented features: - * - ALC - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8961.h" - -#define WM8961_MAX_REGISTER 0xFC - -static u16 wm8961_reg_defaults[] = { - 0x009F, /* R0 - Left Input volume */ - 0x009F, /* R1 - Right Input volume */ - 0x0000, /* R2 - LOUT1 volume */ - 0x0000, /* R3 - ROUT1 volume */ - 0x0020, /* R4 - Clocking1 */ - 0x0008, /* R5 - ADC & DAC Control 1 */ - 0x0000, /* R6 - ADC & DAC Control 2 */ - 0x000A, /* R7 - Audio Interface 0 */ - 0x01F4, /* R8 - Clocking2 */ - 0x0000, /* R9 - Audio Interface 1 */ - 0x00FF, /* R10 - Left DAC volume */ - 0x00FF, /* R11 - Right DAC volume */ - 0x0000, /* R12 */ - 0x0000, /* R13 */ - 0x0040, /* R14 - Audio Interface 2 */ - 0x0000, /* R15 - Software Reset */ - 0x0000, /* R16 */ - 0x007B, /* R17 - ALC1 */ - 0x0000, /* R18 - ALC2 */ - 0x0032, /* R19 - ALC3 */ - 0x0000, /* R20 - Noise Gate */ - 0x00C0, /* R21 - Left ADC volume */ - 0x00C0, /* R22 - Right ADC volume */ - 0x0120, /* R23 - Additional control(1) */ - 0x0000, /* R24 - Additional control(2) */ - 0x0000, /* R25 - Pwr Mgmt (1) */ - 0x0000, /* R26 - Pwr Mgmt (2) */ - 0x0000, /* R27 - Additional Control (3) */ - 0x0000, /* R28 - Anti-pop */ - 0x0000, /* R29 */ - 0x005F, /* R30 - Clocking 3 */ - 0x0000, /* R31 */ - 0x0000, /* R32 - ADCL signal path */ - 0x0000, /* R33 - ADCR signal path */ - 0x0000, /* R34 */ - 0x0000, /* R35 */ - 0x0000, /* R36 */ - 0x0000, /* R37 */ - 0x0000, /* R38 */ - 0x0000, /* R39 */ - 0x0000, /* R40 - LOUT2 volume */ - 0x0000, /* R41 - ROUT2 volume */ - 0x0000, /* R42 */ - 0x0000, /* R43 */ - 0x0000, /* R44 */ - 0x0000, /* R45 */ - 0x0000, /* R46 */ - 0x0000, /* R47 - Pwr Mgmt (3) */ - 0x0023, /* R48 - Additional Control (4) */ - 0x0000, /* R49 - Class D Control 1 */ - 0x0000, /* R50 */ - 0x0003, /* R51 - Class D Control 2 */ - 0x0000, /* R52 */ - 0x0000, /* R53 */ - 0x0000, /* R54 */ - 0x0000, /* R55 */ - 0x0106, /* R56 - Clocking 4 */ - 0x0000, /* R57 - DSP Sidetone 0 */ - 0x0000, /* R58 - DSP Sidetone 1 */ - 0x0000, /* R59 */ - 0x0000, /* R60 - DC Servo 0 */ - 0x0000, /* R61 - DC Servo 1 */ - 0x0000, /* R62 */ - 0x015E, /* R63 - DC Servo 3 */ - 0x0010, /* R64 */ - 0x0010, /* R65 - DC Servo 5 */ - 0x0000, /* R66 */ - 0x0001, /* R67 */ - 0x0003, /* R68 - Analogue PGA Bias */ - 0x0000, /* R69 - Analogue HP 0 */ - 0x0060, /* R70 */ - 0x01FB, /* R71 - Analogue HP 2 */ - 0x0000, /* R72 - Charge Pump 1 */ - 0x0065, /* R73 */ - 0x005F, /* R74 */ - 0x0059, /* R75 */ - 0x006B, /* R76 */ - 0x0038, /* R77 */ - 0x000C, /* R78 */ - 0x000A, /* R79 */ - 0x006B, /* R80 */ - 0x0000, /* R81 */ - 0x0000, /* R82 - Charge Pump B */ - 0x0087, /* R83 */ - 0x0000, /* R84 */ - 0x005C, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 - Write Sequencer 1 */ - 0x0000, /* R88 - Write Sequencer 2 */ - 0x0000, /* R89 - Write Sequencer 3 */ - 0x0000, /* R90 - Write Sequencer 4 */ - 0x0000, /* R91 - Write Sequencer 5 */ - 0x0000, /* R92 - Write Sequencer 6 */ - 0x0000, /* R93 - Write Sequencer 7 */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 */ - 0x0000, /* R97 */ - 0x0000, /* R98 */ - 0x0000, /* R99 */ - 0x0000, /* R100 */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x0000, /* R104 */ - 0x0000, /* R105 */ - 0x0000, /* R106 */ - 0x0000, /* R107 */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 */ - 0x0000, /* R112 */ - 0x0000, /* R113 */ - 0x0000, /* R114 */ - 0x0000, /* R115 */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x0000, /* R128 */ - 0x0000, /* R129 */ - 0x0000, /* R130 */ - 0x0000, /* R131 */ - 0x0000, /* R132 */ - 0x0000, /* R133 */ - 0x0000, /* R134 */ - 0x0000, /* R135 */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0000, /* R140 */ - 0x0000, /* R141 */ - 0x0000, /* R142 */ - 0x0000, /* R143 */ - 0x0000, /* R144 */ - 0x0000, /* R145 */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x0000, /* R152 */ - 0x0000, /* R153 */ - 0x0000, /* R154 */ - 0x0000, /* R155 */ - 0x0000, /* R156 */ - 0x0000, /* R157 */ - 0x0000, /* R158 */ - 0x0000, /* R159 */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 */ - 0x0000, /* R164 */ - 0x0000, /* R165 */ - 0x0000, /* R166 */ - 0x0000, /* R167 */ - 0x0000, /* R168 */ - 0x0000, /* R169 */ - 0x0000, /* R170 */ - 0x0000, /* R171 */ - 0x0000, /* R172 */ - 0x0000, /* R173 */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 */ - 0x0000, /* R177 */ - 0x0000, /* R178 */ - 0x0000, /* R179 */ - 0x0000, /* R180 */ - 0x0000, /* R181 */ - 0x0000, /* R182 */ - 0x0000, /* R183 */ - 0x0000, /* R184 */ - 0x0000, /* R185 */ - 0x0000, /* R186 */ - 0x0000, /* R187 */ - 0x0000, /* R188 */ - 0x0000, /* R189 */ - 0x0000, /* R190 */ - 0x0000, /* R191 */ - 0x0000, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0000, /* R195 */ - 0x0030, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0060, /* R199 */ - 0x0000, /* R200 */ - 0x003F, /* R201 */ - 0x0000, /* R202 */ - 0x0000, /* R203 */ - 0x0000, /* R204 */ - 0x0001, /* R205 */ - 0x0000, /* R206 */ - 0x0181, /* R207 */ - 0x0005, /* R208 */ - 0x0008, /* R209 */ - 0x0008, /* R210 */ - 0x0000, /* R211 */ - 0x013B, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 */ - 0x0000, /* R216 */ - 0x0070, /* R217 */ - 0x0000, /* R218 */ - 0x0000, /* R219 */ - 0x0000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0003, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 */ - 0x0001, /* R226 */ - 0x0008, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0x0000, /* R230 */ - 0x0000, /* R231 */ - 0x0004, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0080, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0052, /* R245 */ - 0x0110, /* R246 */ - 0x0040, /* R247 */ - 0x0000, /* R248 */ - 0x0030, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0001, /* R252 - General test 1 */ -}; - -struct wm8961_priv { - enum snd_soc_control_type control_type; - int sysclk; -}; - -static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg) -{ - switch (reg) { - case WM8961_SOFTWARE_RESET: - case WM8961_WRITE_SEQUENCER_7: - case WM8961_DC_SERVO_1: - return 1; - - default: - return 0; - } -} - -static int wm8961_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0); -} - -/* - * The headphone output supports special anti-pop sequences giving - * silent power up and power down. - */ -static int wm8961_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0); - u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1); - u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2); - u16 dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1); - int timeout = 500; - - if (event & SND_SOC_DAPM_POST_PMU) { - /* Make sure the output is shorted */ - hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT); - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Enable the charge pump */ - cp_reg |= WM8961_CP_ENA; - snd_soc_write(codec, WM8961_CHARGE_PUMP_1, cp_reg); - mdelay(5); - - /* Enable the PGA */ - pwr_reg |= WM8961_LOUT1_PGA | WM8961_ROUT1_PGA; - snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Enable the amplifier */ - hp_reg |= WM8961_HPR_ENA | WM8961_HPL_ENA; - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Second stage enable */ - hp_reg |= WM8961_HPR_ENA_DLY | WM8961_HPL_ENA_DLY; - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Enable the DC servo & trigger startup */ - dcs_reg |= - WM8961_DCS_ENA_CHAN_HPR | WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_ENA_CHAN_HPL | WM8961_DCS_TRIG_STARTUP_HPL; - dev_dbg(codec->dev, "Enabling DC servo\n"); - - snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg); - do { - msleep(1); - dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1); - } while (--timeout && - dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_TRIG_STARTUP_HPL)); - if (dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_TRIG_STARTUP_HPL)) - dev_err(codec->dev, "DC servo timed out\n"); - else - dev_dbg(codec->dev, "DC servo startup complete\n"); - - /* Enable the output stage */ - hp_reg |= WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP; - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Remove the short on the output stage */ - hp_reg |= WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT; - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - } - - if (event & SND_SOC_DAPM_PRE_PMD) { - /* Short the output */ - hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT); - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable the output stage */ - hp_reg &= ~(WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP); - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable DC offset cancellation */ - dcs_reg &= ~(WM8961_DCS_ENA_CHAN_HPR | - WM8961_DCS_ENA_CHAN_HPL); - snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg); - - /* Finish up */ - hp_reg &= ~(WM8961_HPR_ENA_DLY | WM8961_HPR_ENA | - WM8961_HPL_ENA_DLY | WM8961_HPL_ENA); - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable the PGA */ - pwr_reg &= ~(WM8961_LOUT1_PGA | WM8961_ROUT1_PGA); - snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Disable the charge pump */ - dev_dbg(codec->dev, "Disabling charge pump\n"); - snd_soc_write(codec, WM8961_CHARGE_PUMP_1, - cp_reg & ~WM8961_CP_ENA); - } - - return 0; -} - -static int wm8961_spk_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2); - u16 spk_reg = snd_soc_read(codec, WM8961_CLASS_D_CONTROL_1); - - if (event & SND_SOC_DAPM_POST_PMU) { - /* Enable the PGA */ - pwr_reg |= WM8961_SPKL_PGA | WM8961_SPKR_PGA; - snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Enable the amplifier */ - spk_reg |= WM8961_SPKL_ENA | WM8961_SPKR_ENA; - snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg); - } - - if (event & SND_SOC_DAPM_PRE_PMD) { - /* Disable the amplifier */ - spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA); - snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg); - - /* Disable the PGA */ - pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA); - snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - } - - return 0; -} - -static const char *adc_hpf_text[] = { - "Hi-fi", "Voice 1", "Voice 2", "Voice 3", -}; - -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text); - -static const char *dac_deemph_text[] = { - "None", "32kHz", "44.1kHz", "48kHz", -}; - -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text); - -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); -static unsigned int boost_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(13, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(20, 0, 0), - 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0); - -static const struct snd_kcontrol_new wm8961_snd_controls[] = { -SOC_DOUBLE_R_TLV("Headphone Volume", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME, - 0, 127, 0, out_tlv), -SOC_DOUBLE_TLV("Headphone Secondary Volume", WM8961_ANALOGUE_HP_2, - 6, 3, 7, 0, hp_sec_tlv), -SOC_DOUBLE_R("Headphone ZC Switch", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME, - 7, 1, 0), - -SOC_DOUBLE_R_TLV("Speaker Volume", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME, - 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Speaker ZC Switch", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME, - 7, 1, 0), -SOC_SINGLE("Speaker AC Gain", WM8961_CLASS_D_CONTROL_2, 0, 7, 0), - -SOC_SINGLE("DAC x128 OSR Switch", WM8961_ADC_DAC_CONTROL_2, 0, 1, 0), -SOC_ENUM("DAC Deemphasis", dac_deemph), -SOC_SINGLE("DAC Soft Mute Switch", WM8961_ADC_DAC_CONTROL_2, 3, 1, 0), - -SOC_DOUBLE_R_TLV("Sidetone Volume", WM8961_DSP_SIDETONE_0, - WM8961_DSP_SIDETONE_1, 4, 12, 0, sidetone_tlv), - -SOC_SINGLE("ADC High Pass Filter Switch", WM8961_ADC_DAC_CONTROL_1, 0, 1, 0), -SOC_ENUM("ADC High Pass Filter Mode", adc_hpf), - -SOC_DOUBLE_R_TLV("Capture Volume", - WM8961_LEFT_ADC_VOLUME, WM8961_RIGHT_ADC_VOLUME, - 1, 119, 0, adc_tlv), -SOC_DOUBLE_R_TLV("Capture Boost Volume", - WM8961_ADCL_SIGNAL_PATH, WM8961_ADCR_SIGNAL_PATH, - 4, 3, 0, boost_tlv), -SOC_DOUBLE_R_TLV("Capture PGA Volume", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 0, 62, 0, pga_tlv), -SOC_DOUBLE_R("Capture PGA ZC Switch", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 6, 1, 1), -SOC_DOUBLE_R("Capture PGA Switch", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 7, 1, 1), -}; - -static const char *sidetone_text[] = { - "None", "Left", "Right" -}; - -static const struct soc_enum dacl_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text); - -static const struct soc_enum dacr_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text); - -static const struct snd_kcontrol_new dacl_mux = - SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone); - -static const struct snd_kcontrol_new dacr_mux = - SOC_DAPM_ENUM("DACR Sidetone", dacr_sidetone); - -static const struct snd_soc_dapm_widget wm8961_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("LINPUT"), -SND_SOC_DAPM_INPUT("RINPUT"), - -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8961_CLOCKING2, 4, 0, NULL, 0), - -SND_SOC_DAPM_PGA("Left Input", WM8961_PWR_MGMT_1, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0), - -SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0), -SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0), - -SND_SOC_DAPM_SUPPLY("MICBIAS", WM8961_PWR_MGMT_1, 1, 0, NULL, 0), - -SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux), -SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux), - -SND_SOC_DAPM_DAC("DACL", "HiFi Playback", WM8961_PWR_MGMT_2, 8, 0), -SND_SOC_DAPM_DAC("DACR", "HiFi Playback", WM8961_PWR_MGMT_2, 7, 0), - -/* Handle as a mono path for DCS */ -SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM, - 4, 0, NULL, 0, wm8961_hp_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_PGA_E("Speaker Output", SND_SOC_NOPM, - 4, 0, NULL, 0, wm8961_spk_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_OUTPUT("HP_L"), -SND_SOC_DAPM_OUTPUT("HP_R"), -SND_SOC_DAPM_OUTPUT("SPK_LN"), -SND_SOC_DAPM_OUTPUT("SPK_LP"), -SND_SOC_DAPM_OUTPUT("SPK_RN"), -SND_SOC_DAPM_OUTPUT("SPK_RP"), -}; - - -static const struct snd_soc_dapm_route audio_paths[] = { - { "DACL", NULL, "CLK_DSP" }, - { "DACL", NULL, "DACL Sidetone" }, - { "DACR", NULL, "CLK_DSP" }, - { "DACR", NULL, "DACR Sidetone" }, - - { "DACL Sidetone", "Left", "ADCL" }, - { "DACL Sidetone", "Right", "ADCR" }, - - { "DACR Sidetone", "Left", "ADCL" }, - { "DACR Sidetone", "Right", "ADCR" }, - - { "HP_L", NULL, "Headphone Output" }, - { "HP_R", NULL, "Headphone Output" }, - { "Headphone Output", NULL, "DACL" }, - { "Headphone Output", NULL, "DACR" }, - - { "SPK_LN", NULL, "Speaker Output" }, - { "SPK_LP", NULL, "Speaker Output" }, - { "SPK_RN", NULL, "Speaker Output" }, - { "SPK_RP", NULL, "Speaker Output" }, - - { "Speaker Output", NULL, "DACL" }, - { "Speaker Output", NULL, "DACR" }, - - { "ADCL", NULL, "Left Input" }, - { "ADCL", NULL, "CLK_DSP" }, - { "ADCR", NULL, "Right Input" }, - { "ADCR", NULL, "CLK_DSP" }, - - { "Left Input", NULL, "LINPUT" }, - { "Right Input", NULL, "RINPUT" }, - -}; - -/* Values for CLK_SYS_RATE */ -static struct { - int ratio; - u16 val; -} wm8961_clk_sys_ratio[] = { - { 64, 0 }, - { 128, 1 }, - { 192, 2 }, - { 256, 3 }, - { 384, 4 }, - { 512, 5 }, - { 768, 6 }, - { 1024, 7 }, - { 1408, 8 }, - { 1536, 9 }, -}; - -/* Values for SAMPLE_RATE */ -static struct { - int rate; - u16 val; -} wm8961_srate[] = { - { 48000, 0 }, - { 44100, 0 }, - { 32000, 1 }, - { 22050, 2 }, - { 24000, 2 }, - { 16000, 3 }, - { 11250, 4 }, - { 12000, 4 }, - { 8000, 5 }, -}; - -static int wm8961_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); - int i, best, target, fs; - u16 reg; - - fs = params_rate(params); - - if (!wm8961->sysclk) { - dev_err(codec->dev, "MCLK has not been specified\n"); - return -EINVAL; - } - - /* Find the closest sample rate for the filters */ - best = 0; - for (i = 0; i < ARRAY_SIZE(wm8961_srate); i++) { - if (abs(wm8961_srate[i].rate - fs) < - abs(wm8961_srate[best].rate - fs)) - best = i; - } - reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_3); - reg &= ~WM8961_SAMPLE_RATE_MASK; - reg |= wm8961_srate[best].val; - snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_3, reg); - dev_dbg(codec->dev, "Selected SRATE %dHz for %dHz\n", - wm8961_srate[best].rate, fs); - - /* Select a CLK_SYS/fs ratio equal to or higher than required */ - target = wm8961->sysclk / fs; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && target < 64) { - dev_err(codec->dev, - "SYSCLK must be at least 64*fs for DAC\n"); - return -EINVAL; - } - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && target < 256) { - dev_err(codec->dev, - "SYSCLK must be at least 256*fs for ADC\n"); - return -EINVAL; - } - - for (i = 0; i < ARRAY_SIZE(wm8961_clk_sys_ratio); i++) { - if (wm8961_clk_sys_ratio[i].ratio >= target) - break; - } - if (i == ARRAY_SIZE(wm8961_clk_sys_ratio)) { - dev_err(codec->dev, "Unable to generate CLK_SYS_RATE\n"); - return -EINVAL; - } - dev_dbg(codec->dev, "Selected CLK_SYS_RATE of %d for %d/%d=%d\n", - wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs, - wm8961->sysclk / fs); - - reg = snd_soc_read(codec, WM8961_CLOCKING_4); - reg &= ~WM8961_CLK_SYS_RATE_MASK; - reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT; - snd_soc_write(codec, WM8961_CLOCKING_4, reg); - - reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0); - reg &= ~WM8961_WL_MASK; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - reg |= 1 << WM8961_WL_SHIFT; - break; - case SNDRV_PCM_FORMAT_S24_LE: - reg |= 2 << WM8961_WL_SHIFT; - break; - case SNDRV_PCM_FORMAT_S32_LE: - reg |= 3 << WM8961_WL_SHIFT; - break; - default: - return -EINVAL; - } - snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, reg); - - /* Sloping stop-band filter is recommended for <= 24kHz */ - reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2); - if (fs <= 24000) - reg |= WM8961_DACSLOPE; - else - reg &= ~WM8961_DACSLOPE; - snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); - - return 0; -} - -static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, - int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8961_priv *wm8961 = snd_soc_codec_get_drvdata(codec); - u16 reg = snd_soc_read(codec, WM8961_CLOCKING1); - - if (freq > 33000000) { - dev_err(codec->dev, "MCLK must be <33MHz\n"); - return -EINVAL; - } - - if (freq > 16500000) { - dev_dbg(codec->dev, "Using MCLK/2 for %dHz MCLK\n", freq); - reg |= WM8961_MCLKDIV; - freq /= 2; - } else { - dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq); - reg &= ~WM8961_MCLKDIV; - } - - snd_soc_write(codec, WM8961_CLOCKING1, reg); - - wm8961->sysclk = freq; - - return 0; -} - -static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - u16 aif = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0); - - aif &= ~(WM8961_BCLKINV | WM8961_LRP | - WM8961_MS | WM8961_FORMAT_MASK); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - aif |= WM8961_MS; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - break; - - case SND_SOC_DAIFMT_LEFT_J: - aif |= 1; - break; - - case SND_SOC_DAIFMT_I2S: - aif |= 2; - break; - - case SND_SOC_DAIFMT_DSP_B: - aif |= WM8961_LRP; - case SND_SOC_DAIFMT_DSP_A: - aif |= 3; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - case SND_SOC_DAIFMT_IB_NF: - break; - default: - return -EINVAL; - } - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - aif |= WM8961_LRP; - break; - case SND_SOC_DAIFMT_IB_NF: - aif |= WM8961_BCLKINV; - break; - case SND_SOC_DAIFMT_IB_IF: - aif |= WM8961_BCLKINV | WM8961_LRP; - break; - default: - return -EINVAL; - } - - return snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, aif); -} - -static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_2); - - if (tristate) - reg |= WM8961_TRIS; - else - reg &= ~WM8961_TRIS; - - return snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_2, reg); -} - -static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_1); - - if (mute) - reg |= WM8961_DACMU; - else - reg &= ~WM8961_DACMU; - - msleep(17); - - return snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_1, reg); -} - -static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg; - - switch (div_id) { - case WM8961_BCLK: - reg = snd_soc_read(codec, WM8961_CLOCKING2); - reg &= ~WM8961_BCLKDIV_MASK; - reg |= div; - snd_soc_write(codec, WM8961_CLOCKING2, reg); - break; - - case WM8961_LRCLK: - reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_2); - reg &= ~WM8961_LRCLK_RATE_MASK; - reg |= div; - snd_soc_write(codec, WM8961_AUDIO_INTERFACE_2, reg); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm8961_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 reg; - - /* This is all slightly unusual since we have no bypass paths - * and the output amplifier structure means we can just slam - * the biases straight up rather than having to ramp them - * slowly. - */ - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { - /* Enable bias generation */ - reg = snd_soc_read(codec, WM8961_ANTI_POP); - reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; - snd_soc_write(codec, WM8961_ANTI_POP, reg); - - /* VMID=2*50k, VREF */ - reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VMIDSEL_MASK; - reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF; - snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); - } - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { - /* VREF off */ - reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VREF; - snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); - - /* Bias generation off */ - reg = snd_soc_read(codec, WM8961_ANTI_POP); - reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN); - snd_soc_write(codec, WM8961_ANTI_POP, reg); - - /* VMID off */ - reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VMIDSEL_MASK; - snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); - } - break; - - case SND_SOC_BIAS_OFF: - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - - -#define WM8961_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM8961_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8961_dai_ops = { - .hw_params = wm8961_hw_params, - .set_sysclk = wm8961_set_sysclk, - .set_fmt = wm8961_set_fmt, - .digital_mute = wm8961_digital_mute, - .set_tristate = wm8961_set_tristate, - .set_clkdiv = wm8961_set_clkdiv, -}; - -static struct snd_soc_dai_driver wm8961_dai = { - .name = "wm8961-hifi", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8961_RATES, - .formats = WM8961_FORMATS,}, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8961_RATES, - .formats = WM8961_FORMATS,}, - .ops = &wm8961_dai_ops, -}; - -static int wm8961_probe(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret = 0; - u16 reg; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); - if (reg != 0x1801) { - dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); - return -EINVAL; - } - - /* This isn't volatile - readback doesn't correspond to write */ - codec->cache_bypass = 1; - reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); - codec->cache_bypass = 0; - dev_info(codec->dev, "WM8961 family %d revision %c\n", - (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, - ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) - + 'A'); - - ret = wm8961_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - /* Enable class W */ - reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); - reg |= WM8961_CP_DYN_PWR_MASK; - snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg); - - /* Latch volume update bits (right channel only, we always - * write both out) and default ZC on. */ - reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME); - snd_soc_write(codec, WM8961_ROUT1_VOLUME, - reg | WM8961_LO1ZC | WM8961_OUT1VU); - snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); - reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME); - snd_soc_write(codec, WM8961_ROUT2_VOLUME, - reg | WM8961_SPKRZC | WM8961_SPKVU); - snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); - - reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME); - snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); - reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); - snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); - - /* Use soft mute by default */ - reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2); - reg |= WM8961_DACSMM; - snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); - - /* Use automatic clocking mode by default; for now this is all - * we support. - */ - reg = snd_soc_read(codec, WM8961_CLOCKING_3); - reg &= ~WM8961_MANUAL_MODE; - snd_soc_write(codec, WM8961_CLOCKING_3, reg); - - wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - snd_soc_add_codec_controls(codec, wm8961_snd_controls, - ARRAY_SIZE(wm8961_snd_controls)); - snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets, - ARRAY_SIZE(wm8961_dapm_widgets)); - snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); - - return 0; -} - -static int wm8961_remove(struct snd_soc_codec *codec) -{ - wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -#ifdef CONFIG_PM -static int wm8961_suspend(struct snd_soc_codec *codec) -{ - wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8961_resume(struct snd_soc_codec *codec) -{ - snd_soc_cache_sync(codec); - - wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8961_suspend NULL -#define wm8961_resume NULL -#endif - -static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { - .probe = wm8961_probe, - .remove = wm8961_remove, - .suspend = wm8961_suspend, - .resume = wm8961_resume, - .set_bias_level = wm8961_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8961_reg_defaults), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8961_reg_defaults, - .volatile_register = wm8961_volatile_register, -}; - -static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8961_priv *wm8961; - int ret; - - wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv), - GFP_KERNEL); - if (wm8961 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8961); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8961, &wm8961_dai, 1); - - return ret; -} - -static __devexit int wm8961_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - - return 0; -} - -static const struct i2c_device_id wm8961_i2c_id[] = { - { "wm8961", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); - -static struct i2c_driver wm8961_i2c_driver = { - .driver = { - .name = "wm8961", - .owner = THIS_MODULE, - }, - .probe = wm8961_i2c_probe, - .remove = __devexit_p(wm8961_i2c_remove), - .id_table = wm8961_i2c_id, -}; - -static int __init wm8961_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8961_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8961_modinit); - -static void __exit wm8961_exit(void) -{ - i2c_del_driver(&wm8961_i2c_driver); -} -module_exit(wm8961_exit); - -MODULE_DESCRIPTION("ASoC WM8961 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8961.h b/ANDROID_3.4.5/sound/soc/codecs/wm8961.h deleted file mode 100644 index 1d736e57..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8961.h +++ /dev/null @@ -1,863 +0,0 @@ -/* - * wm8961.h -- WM8961 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8961_H -#define _WM8961_H - -#include - -#define WM8961_BCLK 1 -#define WM8961_LRCLK 2 - -#define WM8961_BCLK_DIV_1 0 -#define WM8961_BCLK_DIV_1_5 1 -#define WM8961_BCLK_DIV_2 2 -#define WM8961_BCLK_DIV_3 3 -#define WM8961_BCLK_DIV_4 4 -#define WM8961_BCLK_DIV_5_5 5 -#define WM8961_BCLK_DIV_6 6 -#define WM8961_BCLK_DIV_8 7 -#define WM8961_BCLK_DIV_11 8 -#define WM8961_BCLK_DIV_12 9 -#define WM8961_BCLK_DIV_16 10 -#define WM8961_BCLK_DIV_24 11 -#define WM8961_BCLK_DIV_32 13 - - -/* - * Register values. - */ -#define WM8961_LEFT_INPUT_VOLUME 0x00 -#define WM8961_RIGHT_INPUT_VOLUME 0x01 -#define WM8961_LOUT1_VOLUME 0x02 -#define WM8961_ROUT1_VOLUME 0x03 -#define WM8961_CLOCKING1 0x04 -#define WM8961_ADC_DAC_CONTROL_1 0x05 -#define WM8961_ADC_DAC_CONTROL_2 0x06 -#define WM8961_AUDIO_INTERFACE_0 0x07 -#define WM8961_CLOCKING2 0x08 -#define WM8961_AUDIO_INTERFACE_1 0x09 -#define WM8961_LEFT_DAC_VOLUME 0x0A -#define WM8961_RIGHT_DAC_VOLUME 0x0B -#define WM8961_AUDIO_INTERFACE_2 0x0E -#define WM8961_SOFTWARE_RESET 0x0F -#define WM8961_ALC1 0x11 -#define WM8961_ALC2 0x12 -#define WM8961_ALC3 0x13 -#define WM8961_NOISE_GATE 0x14 -#define WM8961_LEFT_ADC_VOLUME 0x15 -#define WM8961_RIGHT_ADC_VOLUME 0x16 -#define WM8961_ADDITIONAL_CONTROL_1 0x17 -#define WM8961_ADDITIONAL_CONTROL_2 0x18 -#define WM8961_PWR_MGMT_1 0x19 -#define WM8961_PWR_MGMT_2 0x1A -#define WM8961_ADDITIONAL_CONTROL_3 0x1B -#define WM8961_ANTI_POP 0x1C -#define WM8961_CLOCKING_3 0x1E -#define WM8961_ADCL_SIGNAL_PATH 0x20 -#define WM8961_ADCR_SIGNAL_PATH 0x21 -#define WM8961_LOUT2_VOLUME 0x28 -#define WM8961_ROUT2_VOLUME 0x29 -#define WM8961_PWR_MGMT_3 0x2F -#define WM8961_ADDITIONAL_CONTROL_4 0x30 -#define WM8961_CLASS_D_CONTROL_1 0x31 -#define WM8961_CLASS_D_CONTROL_2 0x33 -#define WM8961_CLOCKING_4 0x38 -#define WM8961_DSP_SIDETONE_0 0x39 -#define WM8961_DSP_SIDETONE_1 0x3A -#define WM8961_DC_SERVO_0 0x3C -#define WM8961_DC_SERVO_1 0x3D -#define WM8961_DC_SERVO_3 0x3F -#define WM8961_DC_SERVO_5 0x41 -#define WM8961_ANALOGUE_PGA_BIAS 0x44 -#define WM8961_ANALOGUE_HP_0 0x45 -#define WM8961_ANALOGUE_HP_2 0x47 -#define WM8961_CHARGE_PUMP_1 0x48 -#define WM8961_CHARGE_PUMP_B 0x52 -#define WM8961_WRITE_SEQUENCER_1 0x57 -#define WM8961_WRITE_SEQUENCER_2 0x58 -#define WM8961_WRITE_SEQUENCER_3 0x59 -#define WM8961_WRITE_SEQUENCER_4 0x5A -#define WM8961_WRITE_SEQUENCER_5 0x5B -#define WM8961_WRITE_SEQUENCER_6 0x5C -#define WM8961_WRITE_SEQUENCER_7 0x5D -#define WM8961_GENERAL_TEST_1 0xFC - - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Left Input volume - */ -#define WM8961_IPVU 0x0100 /* IPVU */ -#define WM8961_IPVU_MASK 0x0100 /* IPVU */ -#define WM8961_IPVU_SHIFT 8 /* IPVU */ -#define WM8961_IPVU_WIDTH 1 /* IPVU */ -#define WM8961_LINMUTE 0x0080 /* LINMUTE */ -#define WM8961_LINMUTE_MASK 0x0080 /* LINMUTE */ -#define WM8961_LINMUTE_SHIFT 7 /* LINMUTE */ -#define WM8961_LINMUTE_WIDTH 1 /* LINMUTE */ -#define WM8961_LIZC 0x0040 /* LIZC */ -#define WM8961_LIZC_MASK 0x0040 /* LIZC */ -#define WM8961_LIZC_SHIFT 6 /* LIZC */ -#define WM8961_LIZC_WIDTH 1 /* LIZC */ -#define WM8961_LINVOL_MASK 0x003F /* LINVOL - [5:0] */ -#define WM8961_LINVOL_SHIFT 0 /* LINVOL - [5:0] */ -#define WM8961_LINVOL_WIDTH 6 /* LINVOL - [5:0] */ - -/* - * R1 (0x01) - Right Input volume - */ -#define WM8961_DEVICE_ID_MASK 0xF000 /* DEVICE_ID - [15:12] */ -#define WM8961_DEVICE_ID_SHIFT 12 /* DEVICE_ID - [15:12] */ -#define WM8961_DEVICE_ID_WIDTH 4 /* DEVICE_ID - [15:12] */ -#define WM8961_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */ -#define WM8961_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */ -#define WM8961_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */ -#define WM8961_IPVU 0x0100 /* IPVU */ -#define WM8961_IPVU_MASK 0x0100 /* IPVU */ -#define WM8961_IPVU_SHIFT 8 /* IPVU */ -#define WM8961_IPVU_WIDTH 1 /* IPVU */ -#define WM8961_RINMUTE 0x0080 /* RINMUTE */ -#define WM8961_RINMUTE_MASK 0x0080 /* RINMUTE */ -#define WM8961_RINMUTE_SHIFT 7 /* RINMUTE */ -#define WM8961_RINMUTE_WIDTH 1 /* RINMUTE */ -#define WM8961_RIZC 0x0040 /* RIZC */ -#define WM8961_RIZC_MASK 0x0040 /* RIZC */ -#define WM8961_RIZC_SHIFT 6 /* RIZC */ -#define WM8961_RIZC_WIDTH 1 /* RIZC */ -#define WM8961_RINVOL_MASK 0x003F /* RINVOL - [5:0] */ -#define WM8961_RINVOL_SHIFT 0 /* RINVOL - [5:0] */ -#define WM8961_RINVOL_WIDTH 6 /* RINVOL - [5:0] */ - -/* - * R2 (0x02) - LOUT1 volume - */ -#define WM8961_OUT1VU 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8961_LO1ZC 0x0080 /* LO1ZC */ -#define WM8961_LO1ZC_MASK 0x0080 /* LO1ZC */ -#define WM8961_LO1ZC_SHIFT 7 /* LO1ZC */ -#define WM8961_LO1ZC_WIDTH 1 /* LO1ZC */ -#define WM8961_LOUT1VOL_MASK 0x007F /* LOUT1VOL - [6:0] */ -#define WM8961_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [6:0] */ -#define WM8961_LOUT1VOL_WIDTH 7 /* LOUT1VOL - [6:0] */ - -/* - * R3 (0x03) - ROUT1 volume - */ -#define WM8961_OUT1VU 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8961_RO1ZC 0x0080 /* RO1ZC */ -#define WM8961_RO1ZC_MASK 0x0080 /* RO1ZC */ -#define WM8961_RO1ZC_SHIFT 7 /* RO1ZC */ -#define WM8961_RO1ZC_WIDTH 1 /* RO1ZC */ -#define WM8961_ROUT1VOL_MASK 0x007F /* ROUT1VOL - [6:0] */ -#define WM8961_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [6:0] */ -#define WM8961_ROUT1VOL_WIDTH 7 /* ROUT1VOL - [6:0] */ - -/* - * R4 (0x04) - Clocking1 - */ -#define WM8961_ADCDIV_MASK 0x01C0 /* ADCDIV - [8:6] */ -#define WM8961_ADCDIV_SHIFT 6 /* ADCDIV - [8:6] */ -#define WM8961_ADCDIV_WIDTH 3 /* ADCDIV - [8:6] */ -#define WM8961_DACDIV_MASK 0x0038 /* DACDIV - [5:3] */ -#define WM8961_DACDIV_SHIFT 3 /* DACDIV - [5:3] */ -#define WM8961_DACDIV_WIDTH 3 /* DACDIV - [5:3] */ -#define WM8961_MCLKDIV 0x0004 /* MCLKDIV */ -#define WM8961_MCLKDIV_MASK 0x0004 /* MCLKDIV */ -#define WM8961_MCLKDIV_SHIFT 2 /* MCLKDIV */ -#define WM8961_MCLKDIV_WIDTH 1 /* MCLKDIV */ - -/* - * R5 (0x05) - ADC & DAC Control 1 - */ -#define WM8961_ADCPOL_MASK 0x0060 /* ADCPOL - [6:5] */ -#define WM8961_ADCPOL_SHIFT 5 /* ADCPOL - [6:5] */ -#define WM8961_ADCPOL_WIDTH 2 /* ADCPOL - [6:5] */ -#define WM8961_DACMU 0x0008 /* DACMU */ -#define WM8961_DACMU_MASK 0x0008 /* DACMU */ -#define WM8961_DACMU_SHIFT 3 /* DACMU */ -#define WM8961_DACMU_WIDTH 1 /* DACMU */ -#define WM8961_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ -#define WM8961_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ -#define WM8961_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ -#define WM8961_ADCHPD 0x0001 /* ADCHPD */ -#define WM8961_ADCHPD_MASK 0x0001 /* ADCHPD */ -#define WM8961_ADCHPD_SHIFT 0 /* ADCHPD */ -#define WM8961_ADCHPD_WIDTH 1 /* ADCHPD */ - -/* - * R6 (0x06) - ADC & DAC Control 2 - */ -#define WM8961_ADC_HPF_CUT_MASK 0x0180 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_DACPOL_MASK 0x0060 /* DACPOL - [6:5] */ -#define WM8961_DACPOL_SHIFT 5 /* DACPOL - [6:5] */ -#define WM8961_DACPOL_WIDTH 2 /* DACPOL - [6:5] */ -#define WM8961_DACSMM 0x0008 /* DACSMM */ -#define WM8961_DACSMM_MASK 0x0008 /* DACSMM */ -#define WM8961_DACSMM_SHIFT 3 /* DACSMM */ -#define WM8961_DACSMM_WIDTH 1 /* DACSMM */ -#define WM8961_DACMR 0x0004 /* DACMR */ -#define WM8961_DACMR_MASK 0x0004 /* DACMR */ -#define WM8961_DACMR_SHIFT 2 /* DACMR */ -#define WM8961_DACMR_WIDTH 1 /* DACMR */ -#define WM8961_DACSLOPE 0x0002 /* DACSLOPE */ -#define WM8961_DACSLOPE_MASK 0x0002 /* DACSLOPE */ -#define WM8961_DACSLOPE_SHIFT 1 /* DACSLOPE */ -#define WM8961_DACSLOPE_WIDTH 1 /* DACSLOPE */ -#define WM8961_DAC_OSR128 0x0001 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ - -/* - * R7 (0x07) - Audio Interface 0 - */ -#define WM8961_ALRSWAP 0x0100 /* ALRSWAP */ -#define WM8961_ALRSWAP_MASK 0x0100 /* ALRSWAP */ -#define WM8961_ALRSWAP_SHIFT 8 /* ALRSWAP */ -#define WM8961_ALRSWAP_WIDTH 1 /* ALRSWAP */ -#define WM8961_BCLKINV 0x0080 /* BCLKINV */ -#define WM8961_BCLKINV_MASK 0x0080 /* BCLKINV */ -#define WM8961_BCLKINV_SHIFT 7 /* BCLKINV */ -#define WM8961_BCLKINV_WIDTH 1 /* BCLKINV */ -#define WM8961_MS 0x0040 /* MS */ -#define WM8961_MS_MASK 0x0040 /* MS */ -#define WM8961_MS_SHIFT 6 /* MS */ -#define WM8961_MS_WIDTH 1 /* MS */ -#define WM8961_DLRSWAP 0x0020 /* DLRSWAP */ -#define WM8961_DLRSWAP_MASK 0x0020 /* DLRSWAP */ -#define WM8961_DLRSWAP_SHIFT 5 /* DLRSWAP */ -#define WM8961_DLRSWAP_WIDTH 1 /* DLRSWAP */ -#define WM8961_LRP 0x0010 /* LRP */ -#define WM8961_LRP_MASK 0x0010 /* LRP */ -#define WM8961_LRP_SHIFT 4 /* LRP */ -#define WM8961_LRP_WIDTH 1 /* LRP */ -#define WM8961_WL_MASK 0x000C /* WL - [3:2] */ -#define WM8961_WL_SHIFT 2 /* WL - [3:2] */ -#define WM8961_WL_WIDTH 2 /* WL - [3:2] */ -#define WM8961_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */ -#define WM8961_FORMAT_SHIFT 0 /* FORMAT - [1:0] */ -#define WM8961_FORMAT_WIDTH 2 /* FORMAT - [1:0] */ - -/* - * R8 (0x08) - Clocking2 - */ -#define WM8961_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */ -#define WM8961_DCLKDIV_SHIFT 6 /* DCLKDIV - [8:6] */ -#define WM8961_DCLKDIV_WIDTH 3 /* DCLKDIV - [8:6] */ -#define WM8961_CLK_SYS_ENA 0x0020 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_MASK 0x0020 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_SHIFT 5 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ -#define WM8961_CLK_DSP_ENA 0x0010 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_MASK 0x0010 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_SHIFT 4 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ -#define WM8961_BCLKDIV_MASK 0x000F /* BCLKDIV - [3:0] */ -#define WM8961_BCLKDIV_SHIFT 0 /* BCLKDIV - [3:0] */ -#define WM8961_BCLKDIV_WIDTH 4 /* BCLKDIV - [3:0] */ - -/* - * R9 (0x09) - Audio Interface 1 - */ -#define WM8961_DACCOMP_MASK 0x0018 /* DACCOMP - [4:3] */ -#define WM8961_DACCOMP_SHIFT 3 /* DACCOMP - [4:3] */ -#define WM8961_DACCOMP_WIDTH 2 /* DACCOMP - [4:3] */ -#define WM8961_ADCCOMP_MASK 0x0006 /* ADCCOMP - [2:1] */ -#define WM8961_ADCCOMP_SHIFT 1 /* ADCCOMP - [2:1] */ -#define WM8961_ADCCOMP_WIDTH 2 /* ADCCOMP - [2:1] */ -#define WM8961_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8961_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8961_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8961_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R10 (0x0A) - Left DAC volume - */ -#define WM8961_DACVU 0x0100 /* DACVU */ -#define WM8961_DACVU_MASK 0x0100 /* DACVU */ -#define WM8961_DACVU_SHIFT 8 /* DACVU */ -#define WM8961_DACVU_WIDTH 1 /* DACVU */ -#define WM8961_LDACVOL_MASK 0x00FF /* LDACVOL - [7:0] */ -#define WM8961_LDACVOL_SHIFT 0 /* LDACVOL - [7:0] */ -#define WM8961_LDACVOL_WIDTH 8 /* LDACVOL - [7:0] */ - -/* - * R11 (0x0B) - Right DAC volume - */ -#define WM8961_DACVU 0x0100 /* DACVU */ -#define WM8961_DACVU_MASK 0x0100 /* DACVU */ -#define WM8961_DACVU_SHIFT 8 /* DACVU */ -#define WM8961_DACVU_WIDTH 1 /* DACVU */ -#define WM8961_RDACVOL_MASK 0x00FF /* RDACVOL - [7:0] */ -#define WM8961_RDACVOL_SHIFT 0 /* RDACVOL - [7:0] */ -#define WM8961_RDACVOL_WIDTH 8 /* RDACVOL - [7:0] */ - -/* - * R14 (0x0E) - Audio Interface 2 - */ -#define WM8961_LRCLK_RATE_MASK 0x01FF /* LRCLK_RATE - [8:0] */ -#define WM8961_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [8:0] */ -#define WM8961_LRCLK_RATE_WIDTH 9 /* LRCLK_RATE - [8:0] */ - -/* - * R15 (0x0F) - Software Reset - */ -#define WM8961_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ -#define WM8961_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ -#define WM8961_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ - -/* - * R17 (0x11) - ALC1 - */ -#define WM8961_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */ -#define WM8961_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */ -#define WM8961_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */ -#define WM8961_MAXGAIN_MASK 0x0070 /* MAXGAIN - [6:4] */ -#define WM8961_MAXGAIN_SHIFT 4 /* MAXGAIN - [6:4] */ -#define WM8961_MAXGAIN_WIDTH 3 /* MAXGAIN - [6:4] */ -#define WM8961_ALCL_MASK 0x000F /* ALCL - [3:0] */ -#define WM8961_ALCL_SHIFT 0 /* ALCL - [3:0] */ -#define WM8961_ALCL_WIDTH 4 /* ALCL - [3:0] */ - -/* - * R18 (0x12) - ALC2 - */ -#define WM8961_ALCZC 0x0080 /* ALCZC */ -#define WM8961_ALCZC_MASK 0x0080 /* ALCZC */ -#define WM8961_ALCZC_SHIFT 7 /* ALCZC */ -#define WM8961_ALCZC_WIDTH 1 /* ALCZC */ -#define WM8961_MINGAIN_MASK 0x0070 /* MINGAIN - [6:4] */ -#define WM8961_MINGAIN_SHIFT 4 /* MINGAIN - [6:4] */ -#define WM8961_MINGAIN_WIDTH 3 /* MINGAIN - [6:4] */ -#define WM8961_HLD_MASK 0x000F /* HLD - [3:0] */ -#define WM8961_HLD_SHIFT 0 /* HLD - [3:0] */ -#define WM8961_HLD_WIDTH 4 /* HLD - [3:0] */ - -/* - * R19 (0x13) - ALC3 - */ -#define WM8961_ALCMODE 0x0100 /* ALCMODE */ -#define WM8961_ALCMODE_MASK 0x0100 /* ALCMODE */ -#define WM8961_ALCMODE_SHIFT 8 /* ALCMODE */ -#define WM8961_ALCMODE_WIDTH 1 /* ALCMODE */ -#define WM8961_DCY_MASK 0x00F0 /* DCY - [7:4] */ -#define WM8961_DCY_SHIFT 4 /* DCY - [7:4] */ -#define WM8961_DCY_WIDTH 4 /* DCY - [7:4] */ -#define WM8961_ATK_MASK 0x000F /* ATK - [3:0] */ -#define WM8961_ATK_SHIFT 0 /* ATK - [3:0] */ -#define WM8961_ATK_WIDTH 4 /* ATK - [3:0] */ - -/* - * R20 (0x14) - Noise Gate - */ -#define WM8961_NGTH_MASK 0x00F8 /* NGTH - [7:3] */ -#define WM8961_NGTH_SHIFT 3 /* NGTH - [7:3] */ -#define WM8961_NGTH_WIDTH 5 /* NGTH - [7:3] */ -#define WM8961_NGG 0x0002 /* NGG */ -#define WM8961_NGG_MASK 0x0002 /* NGG */ -#define WM8961_NGG_SHIFT 1 /* NGG */ -#define WM8961_NGG_WIDTH 1 /* NGG */ -#define WM8961_NGAT 0x0001 /* NGAT */ -#define WM8961_NGAT_MASK 0x0001 /* NGAT */ -#define WM8961_NGAT_SHIFT 0 /* NGAT */ -#define WM8961_NGAT_WIDTH 1 /* NGAT */ - -/* - * R21 (0x15) - Left ADC volume - */ -#define WM8961_ADCVU 0x0100 /* ADCVU */ -#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8961_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8961_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8961_LADCVOL_MASK 0x00FF /* LADCVOL - [7:0] */ -#define WM8961_LADCVOL_SHIFT 0 /* LADCVOL - [7:0] */ -#define WM8961_LADCVOL_WIDTH 8 /* LADCVOL - [7:0] */ - -/* - * R22 (0x16) - Right ADC volume - */ -#define WM8961_ADCVU 0x0100 /* ADCVU */ -#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8961_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8961_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8961_RADCVOL_MASK 0x00FF /* RADCVOL - [7:0] */ -#define WM8961_RADCVOL_SHIFT 0 /* RADCVOL - [7:0] */ -#define WM8961_RADCVOL_WIDTH 8 /* RADCVOL - [7:0] */ - -/* - * R23 (0x17) - Additional control(1) - */ -#define WM8961_TSDEN 0x0100 /* TSDEN */ -#define WM8961_TSDEN_MASK 0x0100 /* TSDEN */ -#define WM8961_TSDEN_SHIFT 8 /* TSDEN */ -#define WM8961_TSDEN_WIDTH 1 /* TSDEN */ -#define WM8961_DMONOMIX 0x0010 /* DMONOMIX */ -#define WM8961_DMONOMIX_MASK 0x0010 /* DMONOMIX */ -#define WM8961_DMONOMIX_SHIFT 4 /* DMONOMIX */ -#define WM8961_DMONOMIX_WIDTH 1 /* DMONOMIX */ -#define WM8961_TOEN 0x0001 /* TOEN */ -#define WM8961_TOEN_MASK 0x0001 /* TOEN */ -#define WM8961_TOEN_SHIFT 0 /* TOEN */ -#define WM8961_TOEN_WIDTH 1 /* TOEN */ - -/* - * R24 (0x18) - Additional control(2) - */ -#define WM8961_TRIS 0x0008 /* TRIS */ -#define WM8961_TRIS_MASK 0x0008 /* TRIS */ -#define WM8961_TRIS_SHIFT 3 /* TRIS */ -#define WM8961_TRIS_WIDTH 1 /* TRIS */ - -/* - * R25 (0x19) - Pwr Mgmt (1) - */ -#define WM8961_VMIDSEL_MASK 0x0180 /* VMIDSEL - [8:7] */ -#define WM8961_VMIDSEL_SHIFT 7 /* VMIDSEL - [8:7] */ -#define WM8961_VMIDSEL_WIDTH 2 /* VMIDSEL - [8:7] */ -#define WM8961_VREF 0x0040 /* VREF */ -#define WM8961_VREF_MASK 0x0040 /* VREF */ -#define WM8961_VREF_SHIFT 6 /* VREF */ -#define WM8961_VREF_WIDTH 1 /* VREF */ -#define WM8961_AINL 0x0020 /* AINL */ -#define WM8961_AINL_MASK 0x0020 /* AINL */ -#define WM8961_AINL_SHIFT 5 /* AINL */ -#define WM8961_AINL_WIDTH 1 /* AINL */ -#define WM8961_AINR 0x0010 /* AINR */ -#define WM8961_AINR_MASK 0x0010 /* AINR */ -#define WM8961_AINR_SHIFT 4 /* AINR */ -#define WM8961_AINR_WIDTH 1 /* AINR */ -#define WM8961_ADCL 0x0008 /* ADCL */ -#define WM8961_ADCL_MASK 0x0008 /* ADCL */ -#define WM8961_ADCL_SHIFT 3 /* ADCL */ -#define WM8961_ADCL_WIDTH 1 /* ADCL */ -#define WM8961_ADCR 0x0004 /* ADCR */ -#define WM8961_ADCR_MASK 0x0004 /* ADCR */ -#define WM8961_ADCR_SHIFT 2 /* ADCR */ -#define WM8961_ADCR_WIDTH 1 /* ADCR */ -#define WM8961_MICB 0x0002 /* MICB */ -#define WM8961_MICB_MASK 0x0002 /* MICB */ -#define WM8961_MICB_SHIFT 1 /* MICB */ -#define WM8961_MICB_WIDTH 1 /* MICB */ - -/* - * R26 (0x1A) - Pwr Mgmt (2) - */ -#define WM8961_DACL 0x0100 /* DACL */ -#define WM8961_DACL_MASK 0x0100 /* DACL */ -#define WM8961_DACL_SHIFT 8 /* DACL */ -#define WM8961_DACL_WIDTH 1 /* DACL */ -#define WM8961_DACR 0x0080 /* DACR */ -#define WM8961_DACR_MASK 0x0080 /* DACR */ -#define WM8961_DACR_SHIFT 7 /* DACR */ -#define WM8961_DACR_WIDTH 1 /* DACR */ -#define WM8961_LOUT1_PGA 0x0040 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_MASK 0x0040 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_SHIFT 6 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_WIDTH 1 /* LOUT1_PGA */ -#define WM8961_ROUT1_PGA 0x0020 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_MASK 0x0020 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_SHIFT 5 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_WIDTH 1 /* ROUT1_PGA */ -#define WM8961_SPKL_PGA 0x0010 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_MASK 0x0010 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_SHIFT 4 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_WIDTH 1 /* SPKL_PGA */ -#define WM8961_SPKR_PGA 0x0008 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_MASK 0x0008 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_SHIFT 3 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_WIDTH 1 /* SPKR_PGA */ - -/* - * R27 (0x1B) - Additional Control (3) - */ -#define WM8961_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */ -#define WM8961_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */ -#define WM8961_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */ - -/* - * R28 (0x1C) - Anti-pop - */ -#define WM8961_BUFDCOPEN 0x0010 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_MASK 0x0010 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_SHIFT 4 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */ -#define WM8961_BUFIOEN 0x0008 /* BUFIOEN */ -#define WM8961_BUFIOEN_MASK 0x0008 /* BUFIOEN */ -#define WM8961_BUFIOEN_SHIFT 3 /* BUFIOEN */ -#define WM8961_BUFIOEN_WIDTH 1 /* BUFIOEN */ -#define WM8961_SOFT_ST 0x0004 /* SOFT_ST */ -#define WM8961_SOFT_ST_MASK 0x0004 /* SOFT_ST */ -#define WM8961_SOFT_ST_SHIFT 2 /* SOFT_ST */ -#define WM8961_SOFT_ST_WIDTH 1 /* SOFT_ST */ - -/* - * R30 (0x1E) - Clocking 3 - */ -#define WM8961_CLK_TO_DIV_MASK 0x0180 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_TO_DIV_SHIFT 7 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */ -#define WM8961_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */ -#define WM8961_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */ -#define WM8961_MANUAL_MODE 0x0001 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_MASK 0x0001 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_SHIFT 0 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_WIDTH 1 /* MANUAL_MODE */ - -/* - * R32 (0x20) - ADCL signal path - */ -#define WM8961_LMICBOOST_MASK 0x0030 /* LMICBOOST - [5:4] */ -#define WM8961_LMICBOOST_SHIFT 4 /* LMICBOOST - [5:4] */ -#define WM8961_LMICBOOST_WIDTH 2 /* LMICBOOST - [5:4] */ - -/* - * R33 (0x21) - ADCR signal path - */ -#define WM8961_RMICBOOST_MASK 0x0030 /* RMICBOOST - [5:4] */ -#define WM8961_RMICBOOST_SHIFT 4 /* RMICBOOST - [5:4] */ -#define WM8961_RMICBOOST_WIDTH 2 /* RMICBOOST - [5:4] */ - -/* - * R40 (0x28) - LOUT2 volume - */ -#define WM8961_SPKVU 0x0100 /* SPKVU */ -#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */ -#define WM8961_SPKVU_SHIFT 8 /* SPKVU */ -#define WM8961_SPKVU_WIDTH 1 /* SPKVU */ -#define WM8961_SPKLZC 0x0080 /* SPKLZC */ -#define WM8961_SPKLZC_MASK 0x0080 /* SPKLZC */ -#define WM8961_SPKLZC_SHIFT 7 /* SPKLZC */ -#define WM8961_SPKLZC_WIDTH 1 /* SPKLZC */ -#define WM8961_SPKLVOL_MASK 0x007F /* SPKLVOL - [6:0] */ -#define WM8961_SPKLVOL_SHIFT 0 /* SPKLVOL - [6:0] */ -#define WM8961_SPKLVOL_WIDTH 7 /* SPKLVOL - [6:0] */ - -/* - * R41 (0x29) - ROUT2 volume - */ -#define WM8961_SPKVU 0x0100 /* SPKVU */ -#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */ -#define WM8961_SPKVU_SHIFT 8 /* SPKVU */ -#define WM8961_SPKVU_WIDTH 1 /* SPKVU */ -#define WM8961_SPKRZC 0x0080 /* SPKRZC */ -#define WM8961_SPKRZC_MASK 0x0080 /* SPKRZC */ -#define WM8961_SPKRZC_SHIFT 7 /* SPKRZC */ -#define WM8961_SPKRZC_WIDTH 1 /* SPKRZC */ -#define WM8961_SPKRVOL_MASK 0x007F /* SPKRVOL - [6:0] */ -#define WM8961_SPKRVOL_SHIFT 0 /* SPKRVOL - [6:0] */ -#define WM8961_SPKRVOL_WIDTH 7 /* SPKRVOL - [6:0] */ - -/* - * R47 (0x2F) - Pwr Mgmt (3) - */ -#define WM8961_TEMP_SHUT 0x0002 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_MASK 0x0002 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_SHIFT 1 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */ -#define WM8961_TEMP_WARN 0x0001 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_MASK 0x0001 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_SHIFT 0 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_WIDTH 1 /* TEMP_WARN */ - -/* - * R48 (0x30) - Additional Control (4) - */ -#define WM8961_TSENSEN 0x0002 /* TSENSEN */ -#define WM8961_TSENSEN_MASK 0x0002 /* TSENSEN */ -#define WM8961_TSENSEN_SHIFT 1 /* TSENSEN */ -#define WM8961_TSENSEN_WIDTH 1 /* TSENSEN */ -#define WM8961_MBSEL 0x0001 /* MBSEL */ -#define WM8961_MBSEL_MASK 0x0001 /* MBSEL */ -#define WM8961_MBSEL_SHIFT 0 /* MBSEL */ -#define WM8961_MBSEL_WIDTH 1 /* MBSEL */ - -/* - * R49 (0x31) - Class D Control 1 - */ -#define WM8961_SPKR_ENA 0x0080 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_MASK 0x0080 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_SHIFT 7 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_WIDTH 1 /* SPKR_ENA */ -#define WM8961_SPKL_ENA 0x0040 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_MASK 0x0040 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_SHIFT 6 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_WIDTH 1 /* SPKL_ENA */ - -/* - * R51 (0x33) - Class D Control 2 - */ -#define WM8961_CLASSD_ACGAIN_MASK 0x0007 /* CLASSD_ACGAIN - [2:0] */ -#define WM8961_CLASSD_ACGAIN_SHIFT 0 /* CLASSD_ACGAIN - [2:0] */ -#define WM8961_CLASSD_ACGAIN_WIDTH 3 /* CLASSD_ACGAIN - [2:0] */ - -/* - * R56 (0x38) - Clocking 4 - */ -#define WM8961_CLK_DCS_DIV_MASK 0x01E0 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_DCS_DIV_SHIFT 5 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */ -#define WM8961_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */ -#define WM8961_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */ - -/* - * R57 (0x39) - DSP Sidetone 0 - */ -#define WM8961_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */ -#define WM8961_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */ -#define WM8961_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */ - -/* - * R58 (0x3A) - DSP Sidetone 1 - */ -#define WM8961_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8961_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8961_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ - -/* - * R60 (0x3C) - DC Servo 0 - */ -#define WM8961_DCS_ENA_CHAN_INL 0x0080 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_MASK 0x0080 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_SHIFT 7 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_WIDTH 1 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL 0x0040 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_MASK 0x0040 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_SHIFT 6 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_WIDTH 1 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_SERIES_INL 0x0010 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_MASK 0x0010 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_SHIFT 4 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_WIDTH 1 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_ENA_CHAN_INR 0x0008 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_MASK 0x0008 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_SHIFT 3 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_WIDTH 1 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR 0x0004 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_MASK 0x0004 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_SHIFT 2 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_WIDTH 1 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_SERIES_INR 0x0001 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_MASK 0x0001 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_SHIFT 0 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_WIDTH 1 /* DCS_TRIG_SERIES_INR */ - -/* - * R61 (0x3D) - DC Servo 1 - */ -#define WM8961_DCS_ENA_CHAN_HPL 0x0080 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_MASK 0x0080 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_SHIFT 7 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_WIDTH 1 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL 0x0040 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_MASK 0x0040 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_SHIFT 6 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_WIDTH 1 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL 0x0010 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_MASK 0x0010 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_SHIFT 4 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_WIDTH 1 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_ENA_CHAN_HPR 0x0008 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_MASK 0x0008 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_SHIFT 3 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_WIDTH 1 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR 0x0004 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_MASK 0x0004 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_SHIFT 2 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_WIDTH 1 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR 0x0001 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_MASK 0x0001 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_SHIFT 0 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_WIDTH 1 /* DCS_TRIG_SERIES_HPR */ - -/* - * R63 (0x3F) - DC Servo 3 - */ -#define WM8961_DCS_FILT_BW_SERIES_MASK 0x0030 /* DCS_FILT_BW_SERIES - [5:4] */ -#define WM8961_DCS_FILT_BW_SERIES_SHIFT 4 /* DCS_FILT_BW_SERIES - [5:4] */ -#define WM8961_DCS_FILT_BW_SERIES_WIDTH 2 /* DCS_FILT_BW_SERIES - [5:4] */ - -/* - * R65 (0x41) - DC Servo 5 - */ -#define WM8961_DCS_SERIES_NO_HP_MASK 0x007F /* DCS_SERIES_NO_HP - [6:0] */ -#define WM8961_DCS_SERIES_NO_HP_SHIFT 0 /* DCS_SERIES_NO_HP - [6:0] */ -#define WM8961_DCS_SERIES_NO_HP_WIDTH 7 /* DCS_SERIES_NO_HP - [6:0] */ - -/* - * R68 (0x44) - Analogue PGA Bias - */ -#define WM8961_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */ -#define WM8961_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */ -#define WM8961_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */ - -/* - * R69 (0x45) - Analogue HP 0 - */ -#define WM8961_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */ -#define WM8961_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA 0x0010 /* HPL_ENA */ -#define WM8961_HPL_ENA_MASK 0x0010 /* HPL_ENA */ -#define WM8961_HPL_ENA_SHIFT 4 /* HPL_ENA */ -#define WM8961_HPL_ENA_WIDTH 1 /* HPL_ENA */ -#define WM8961_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */ -#define WM8961_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA 0x0001 /* HPR_ENA */ -#define WM8961_HPR_ENA_MASK 0x0001 /* HPR_ENA */ -#define WM8961_HPR_ENA_SHIFT 0 /* HPR_ENA */ -#define WM8961_HPR_ENA_WIDTH 1 /* HPR_ENA */ - -/* - * R71 (0x47) - Analogue HP 2 - */ -#define WM8961_HPL_VOL_MASK 0x01C0 /* HPL_VOL - [8:6] */ -#define WM8961_HPL_VOL_SHIFT 6 /* HPL_VOL - [8:6] */ -#define WM8961_HPL_VOL_WIDTH 3 /* HPL_VOL - [8:6] */ -#define WM8961_HPR_VOL_MASK 0x0038 /* HPR_VOL - [5:3] */ -#define WM8961_HPR_VOL_SHIFT 3 /* HPR_VOL - [5:3] */ -#define WM8961_HPR_VOL_WIDTH 3 /* HPR_VOL - [5:3] */ -#define WM8961_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */ -#define WM8961_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */ -#define WM8961_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */ - -/* - * R72 (0x48) - Charge Pump 1 - */ -#define WM8961_CP_ENA 0x0001 /* CP_ENA */ -#define WM8961_CP_ENA_MASK 0x0001 /* CP_ENA */ -#define WM8961_CP_ENA_SHIFT 0 /* CP_ENA */ -#define WM8961_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R82 (0x52) - Charge Pump B - */ -#define WM8961_CP_DYN_PWR_MASK 0x0003 /* CP_DYN_PWR - [1:0] */ -#define WM8961_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR - [1:0] */ -#define WM8961_CP_DYN_PWR_WIDTH 2 /* CP_DYN_PWR - [1:0] */ - -/* - * R87 (0x57) - Write Sequencer 1 - */ -#define WM8961_WSEQ_ENA 0x0020 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8961_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8961_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8961_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ - -/* - * R88 (0x58) - Write Sequencer 2 - */ -#define WM8961_WSEQ_EOS 0x0100 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_MASK 0x0100 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_SHIFT 8 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM8961_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM8961_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM8961_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R89 (0x59) - Write Sequencer 3 - */ -#define WM8961_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM8961_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM8961_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R90 (0x5A) - Write Sequencer 4 - */ -#define WM8961_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8961_WSEQ_START 0x0080 /* WSEQ_START */ -#define WM8961_WSEQ_START_MASK 0x0080 /* WSEQ_START */ -#define WM8961_WSEQ_START_SHIFT 7 /* WSEQ_START */ -#define WM8961_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8961_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM8961_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM8961_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R91 (0x5B) - Write Sequencer 5 - */ -#define WM8961_WSEQ_DATA_WIDTH_MASK 0x0070 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_WIDTH_SHIFT 4 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_START_MASK 0x000F /* WSEQ_DATA_START - [3:0] */ -#define WM8961_WSEQ_DATA_START_SHIFT 0 /* WSEQ_DATA_START - [3:0] */ -#define WM8961_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [3:0] */ - -/* - * R92 (0x5C) - Write Sequencer 6 - */ -#define WM8961_WSEQ_DELAY_MASK 0x000F /* WSEQ_DELAY - [3:0] */ -#define WM8961_WSEQ_DELAY_SHIFT 0 /* WSEQ_DELAY - [3:0] */ -#define WM8961_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [3:0] */ - -/* - * R93 (0x5D) - Write Sequencer 7 - */ -#define WM8961_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R252 (0xFC) - General test 1 - */ -#define WM8961_ARA_ENA 0x0002 /* ARA_ENA */ -#define WM8961_ARA_ENA_MASK 0x0002 /* ARA_ENA */ -#define WM8961_ARA_ENA_SHIFT 1 /* ARA_ENA */ -#define WM8961_ARA_ENA_WIDTH 1 /* ARA_ENA */ -#define WM8961_AUTO_INC 0x0001 /* AUTO_INC */ -#define WM8961_AUTO_INC_MASK 0x0001 /* AUTO_INC */ -#define WM8961_AUTO_INC_SHIFT 0 /* AUTO_INC */ -#define WM8961_AUTO_INC_WIDTH 1 /* AUTO_INC */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8962.c b/ANDROID_3.4.5/sound/soc/codecs/wm8962.c deleted file mode 100644 index 15d467ff..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8962.c +++ /dev/null @@ -1,3778 +0,0 @@ -/* - * wm8962.c -- WM8962 ALSA SoC Audio driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8962.h" - -#define WM8962_NUM_SUPPLIES 8 -static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { - "DCVDD", - "DBVDD", - "AVDD", - "CPVDD", - "MICVDD", - "PLLVDD", - "SPKVDD1", - "SPKVDD2", -}; - -/* codec private data */ -struct wm8962_priv { - struct regmap *regmap; - struct snd_soc_codec *codec; - - int sysclk; - int sysclk_rate; - - int bclk; /* Desired BCLK */ - int lrclk; - - struct completion fll_lock; - int fll_src; - int fll_fref; - int fll_fout; - - u16 dsp2_ena; - - struct delayed_work mic_work; - struct snd_soc_jack *jack; - - struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES]; - struct notifier_block disable_nb[WM8962_NUM_SUPPLIES]; - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) - struct input_dev *beep; - struct work_struct beep_work; - int beep_rate; -#endif - -#ifdef CONFIG_GPIOLIB - struct gpio_chip gpio_chip; -#endif - - int irq; -}; - -/* We can't use the same notifier block for more than one supply and - * there's no way I can see to get from a callback to the caller - * except container_of(). - */ -#define WM8962_REGULATOR_EVENT(n) \ -static int wm8962_regulator_event_##n(struct notifier_block *nb, \ - unsigned long event, void *data) \ -{ \ - struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \ - disable_nb[n]); \ - if (event & REGULATOR_EVENT_DISABLE) { \ - regcache_mark_dirty(wm8962->regmap); \ - } \ - return 0; \ -} - -WM8962_REGULATOR_EVENT(0) -WM8962_REGULATOR_EVENT(1) -WM8962_REGULATOR_EVENT(2) -WM8962_REGULATOR_EVENT(3) -WM8962_REGULATOR_EVENT(4) -WM8962_REGULATOR_EVENT(5) -WM8962_REGULATOR_EVENT(6) -WM8962_REGULATOR_EVENT(7) - -static struct reg_default wm8962_reg[] = { - { 0, 0x009F }, /* R0 - Left Input volume */ - { 1, 0x049F }, /* R1 - Right Input volume */ - { 2, 0x0000 }, /* R2 - HPOUTL volume */ - { 3, 0x0000 }, /* R3 - HPOUTR volume */ - - { 5, 0x0018 }, /* R5 - ADC & DAC Control 1 */ - { 6, 0x2008 }, /* R6 - ADC & DAC Control 2 */ - { 7, 0x000A }, /* R7 - Audio Interface 0 */ - - { 9, 0x0300 }, /* R9 - Audio Interface 1 */ - { 10, 0x00C0 }, /* R10 - Left DAC volume */ - { 11, 0x00C0 }, /* R11 - Right DAC volume */ - - { 14, 0x0040 }, /* R14 - Audio Interface 2 */ - { 15, 0x6243 }, /* R15 - Software Reset */ - - { 17, 0x007B }, /* R17 - ALC1 */ - - { 19, 0x1C32 }, /* R19 - ALC3 */ - { 20, 0x3200 }, /* R20 - Noise Gate */ - { 21, 0x00C0 }, /* R21 - Left ADC volume */ - { 22, 0x00C0 }, /* R22 - Right ADC volume */ - { 23, 0x0160 }, /* R23 - Additional control(1) */ - { 24, 0x0000 }, /* R24 - Additional control(2) */ - { 25, 0x0000 }, /* R25 - Pwr Mgmt (1) */ - { 26, 0x0000 }, /* R26 - Pwr Mgmt (2) */ - { 27, 0x0010 }, /* R27 - Additional Control (3) */ - { 28, 0x0000 }, /* R28 - Anti-pop */ - - { 30, 0x005E }, /* R30 - Clocking 3 */ - { 31, 0x0000 }, /* R31 - Input mixer control (1) */ - { 32, 0x0145 }, /* R32 - Left input mixer volume */ - { 33, 0x0145 }, /* R33 - Right input mixer volume */ - { 34, 0x0009 }, /* R34 - Input mixer control (2) */ - { 35, 0x0003 }, /* R35 - Input bias control */ - { 37, 0x0008 }, /* R37 - Left input PGA control */ - { 38, 0x0008 }, /* R38 - Right input PGA control */ - - { 40, 0x0000 }, /* R40 - SPKOUTL volume */ - { 41, 0x0000 }, /* R41 - SPKOUTR volume */ - - { 51, 0x0003 }, /* R51 - Class D Control 2 */ - - { 56, 0x0506 }, /* R56 - Clocking 4 */ - { 57, 0x0000 }, /* R57 - DAC DSP Mixing (1) */ - { 58, 0x0000 }, /* R58 - DAC DSP Mixing (2) */ - - { 60, 0x0300 }, /* R60 - DC Servo 0 */ - { 61, 0x0300 }, /* R61 - DC Servo 1 */ - - { 64, 0x0810 }, /* R64 - DC Servo 4 */ - - { 68, 0x001B }, /* R68 - Analogue PGA Bias */ - { 69, 0x0000 }, /* R69 - Analogue HP 0 */ - - { 71, 0x01FB }, /* R71 - Analogue HP 2 */ - { 72, 0x0000 }, /* R72 - Charge Pump 1 */ - - { 82, 0x0004 }, /* R82 - Charge Pump B */ - - { 87, 0x0000 }, /* R87 - Write Sequencer Control 1 */ - - { 90, 0x0000 }, /* R90 - Write Sequencer Control 2 */ - - { 93, 0x0000 }, /* R93 - Write Sequencer Control 3 */ - { 94, 0x0000 }, /* R94 - Control Interface */ - - { 99, 0x0000 }, /* R99 - Mixer Enables */ - { 100, 0x0000 }, /* R100 - Headphone Mixer (1) */ - { 101, 0x0000 }, /* R101 - Headphone Mixer (2) */ - { 102, 0x013F }, /* R102 - Headphone Mixer (3) */ - { 103, 0x013F }, /* R103 - Headphone Mixer (4) */ - - { 105, 0x0000 }, /* R105 - Speaker Mixer (1) */ - { 106, 0x0000 }, /* R106 - Speaker Mixer (2) */ - { 107, 0x013F }, /* R107 - Speaker Mixer (3) */ - { 108, 0x013F }, /* R108 - Speaker Mixer (4) */ - { 109, 0x0003 }, /* R109 - Speaker Mixer (5) */ - { 110, 0x0002 }, /* R110 - Beep Generator (1) */ - - { 115, 0x0006 }, /* R115 - Oscillator Trim (3) */ - { 116, 0x0026 }, /* R116 - Oscillator Trim (4) */ - - { 119, 0x0000 }, /* R119 - Oscillator Trim (7) */ - - { 124, 0x0011 }, /* R124 - Analogue Clocking1 */ - { 125, 0x004B }, /* R125 - Analogue Clocking2 */ - { 126, 0x000D }, /* R126 - Analogue Clocking3 */ - { 127, 0x0000 }, /* R127 - PLL Software Reset */ - - { 131, 0x0000 }, /* R131 - PLL 4 */ - - { 136, 0x0067 }, /* R136 - PLL 9 */ - { 137, 0x001C }, /* R137 - PLL 10 */ - { 138, 0x0071 }, /* R138 - PLL 11 */ - { 139, 0x00C7 }, /* R139 - PLL 12 */ - { 140, 0x0067 }, /* R140 - PLL 13 */ - { 141, 0x0048 }, /* R141 - PLL 14 */ - { 142, 0x0022 }, /* R142 - PLL 15 */ - { 143, 0x0097 }, /* R143 - PLL 16 */ - - { 155, 0x000C }, /* R155 - FLL Control (1) */ - { 156, 0x0039 }, /* R156 - FLL Control (2) */ - { 157, 0x0180 }, /* R157 - FLL Control (3) */ - - { 159, 0x0032 }, /* R159 - FLL Control (5) */ - { 160, 0x0018 }, /* R160 - FLL Control (6) */ - { 161, 0x007D }, /* R161 - FLL Control (7) */ - { 162, 0x0008 }, /* R162 - FLL Control (8) */ - - { 252, 0x0005 }, /* R252 - General test 1 */ - - { 256, 0x0000 }, /* R256 - DF1 */ - { 257, 0x0000 }, /* R257 - DF2 */ - { 258, 0x0000 }, /* R258 - DF3 */ - { 259, 0x0000 }, /* R259 - DF4 */ - { 260, 0x0000 }, /* R260 - DF5 */ - { 261, 0x0000 }, /* R261 - DF6 */ - { 262, 0x0000 }, /* R262 - DF7 */ - - { 264, 0x0000 }, /* R264 - LHPF1 */ - { 265, 0x0000 }, /* R265 - LHPF2 */ - - { 268, 0x0000 }, /* R268 - THREED1 */ - { 269, 0x0000 }, /* R269 - THREED2 */ - { 270, 0x0000 }, /* R270 - THREED3 */ - { 271, 0x0000 }, /* R271 - THREED4 */ - - { 276, 0x000C }, /* R276 - DRC 1 */ - { 277, 0x0925 }, /* R277 - DRC 2 */ - { 278, 0x0000 }, /* R278 - DRC 3 */ - { 279, 0x0000 }, /* R279 - DRC 4 */ - { 280, 0x0000 }, /* R280 - DRC 5 */ - - { 285, 0x0000 }, /* R285 - Tloopback */ - - { 335, 0x0004 }, /* R335 - EQ1 */ - { 336, 0x6318 }, /* R336 - EQ2 */ - { 337, 0x6300 }, /* R337 - EQ3 */ - { 338, 0x0FCA }, /* R338 - EQ4 */ - { 339, 0x0400 }, /* R339 - EQ5 */ - { 340, 0x00D8 }, /* R340 - EQ6 */ - { 341, 0x1EB5 }, /* R341 - EQ7 */ - { 342, 0xF145 }, /* R342 - EQ8 */ - { 343, 0x0B75 }, /* R343 - EQ9 */ - { 344, 0x01C5 }, /* R344 - EQ10 */ - { 345, 0x1C58 }, /* R345 - EQ11 */ - { 346, 0xF373 }, /* R346 - EQ12 */ - { 347, 0x0A54 }, /* R347 - EQ13 */ - { 348, 0x0558 }, /* R348 - EQ14 */ - { 349, 0x168E }, /* R349 - EQ15 */ - { 350, 0xF829 }, /* R350 - EQ16 */ - { 351, 0x07AD }, /* R351 - EQ17 */ - { 352, 0x1103 }, /* R352 - EQ18 */ - { 353, 0x0564 }, /* R353 - EQ19 */ - { 354, 0x0559 }, /* R354 - EQ20 */ - { 355, 0x4000 }, /* R355 - EQ21 */ - { 356, 0x6318 }, /* R356 - EQ22 */ - { 357, 0x6300 }, /* R357 - EQ23 */ - { 358, 0x0FCA }, /* R358 - EQ24 */ - { 359, 0x0400 }, /* R359 - EQ25 */ - { 360, 0x00D8 }, /* R360 - EQ26 */ - { 361, 0x1EB5 }, /* R361 - EQ27 */ - { 362, 0xF145 }, /* R362 - EQ28 */ - { 363, 0x0B75 }, /* R363 - EQ29 */ - { 364, 0x01C5 }, /* R364 - EQ30 */ - { 365, 0x1C58 }, /* R365 - EQ31 */ - { 366, 0xF373 }, /* R366 - EQ32 */ - { 367, 0x0A54 }, /* R367 - EQ33 */ - { 368, 0x0558 }, /* R368 - EQ34 */ - { 369, 0x168E }, /* R369 - EQ35 */ - { 370, 0xF829 }, /* R370 - EQ36 */ - { 371, 0x07AD }, /* R371 - EQ37 */ - { 372, 0x1103 }, /* R372 - EQ38 */ - { 373, 0x0564 }, /* R373 - EQ39 */ - { 374, 0x0559 }, /* R374 - EQ40 */ - { 375, 0x4000 }, /* R375 - EQ41 */ - - { 513, 0x0000 }, /* R513 - GPIO 2 */ - { 514, 0x0000 }, /* R514 - GPIO 3 */ - - { 516, 0x8100 }, /* R516 - GPIO 5 */ - { 517, 0x8100 }, /* R517 - GPIO 6 */ - - { 568, 0x0030 }, /* R568 - Interrupt Status 1 Mask */ - { 569, 0xFFED }, /* R569 - Interrupt Status 2 Mask */ - - { 576, 0x0000 }, /* R576 - Interrupt Control */ - - { 584, 0x002D }, /* R584 - IRQ Debounce */ - - { 586, 0x0000 }, /* R586 - MICINT Source Pol */ - - { 768, 0x1C00 }, /* R768 - DSP2 Power Management */ - - { 8192, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */ - - { 9216, 0x0030 }, /* R9216 - DSP2 Address RAM 2 */ - { 9217, 0x0000 }, /* R9217 - DSP2 Address RAM 1 */ - { 9218, 0x0000 }, /* R9218 - DSP2 Address RAM 0 */ - - { 12288, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */ - { 12289, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */ - - { 13312, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */ - { 13313, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */ - - { 14336, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */ - { 14337, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */ - - { 15360, 0x000A }, /* R15360 - DSP2 Coeff RAM 0 */ - - { 16384, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */ - { 16385, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */ - { 16386, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */ - { 16387, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */ - { 16388, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */ - { 16389, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */ - - { 16896, 0x0002 }, /* R16896 - HDBASS_AI_1 */ - { 16897, 0xBD12 }, /* R16897 - HDBASS_AI_0 */ - { 16898, 0x007C }, /* R16898 - HDBASS_AR_1 */ - { 16899, 0x586C }, /* R16899 - HDBASS_AR_0 */ - { 16900, 0x0053 }, /* R16900 - HDBASS_B_1 */ - { 16901, 0x8121 }, /* R16901 - HDBASS_B_0 */ - { 16902, 0x003F }, /* R16902 - HDBASS_K_1 */ - { 16903, 0x8BD8 }, /* R16903 - HDBASS_K_0 */ - { 16904, 0x0032 }, /* R16904 - HDBASS_N1_1 */ - { 16905, 0xF52D }, /* R16905 - HDBASS_N1_0 */ - { 16906, 0x0065 }, /* R16906 - HDBASS_N2_1 */ - { 16907, 0xAC8C }, /* R16907 - HDBASS_N2_0 */ - { 16908, 0x006B }, /* R16908 - HDBASS_N3_1 */ - { 16909, 0xE087 }, /* R16909 - HDBASS_N3_0 */ - { 16910, 0x0072 }, /* R16910 - HDBASS_N4_1 */ - { 16911, 0x1483 }, /* R16911 - HDBASS_N4_0 */ - { 16912, 0x0072 }, /* R16912 - HDBASS_N5_1 */ - { 16913, 0x1483 }, /* R16913 - HDBASS_N5_0 */ - { 16914, 0x0043 }, /* R16914 - HDBASS_X1_1 */ - { 16915, 0x3525 }, /* R16915 - HDBASS_X1_0 */ - { 16916, 0x0006 }, /* R16916 - HDBASS_X2_1 */ - { 16917, 0x6A4A }, /* R16917 - HDBASS_X2_0 */ - { 16918, 0x0043 }, /* R16918 - HDBASS_X3_1 */ - { 16919, 0x6079 }, /* R16919 - HDBASS_X3_0 */ - { 16920, 0x0008 }, /* R16920 - HDBASS_ATK_1 */ - { 16921, 0x0000 }, /* R16921 - HDBASS_ATK_0 */ - { 16922, 0x0001 }, /* R16922 - HDBASS_DCY_1 */ - { 16923, 0x0000 }, /* R16923 - HDBASS_DCY_0 */ - { 16924, 0x0059 }, /* R16924 - HDBASS_PG_1 */ - { 16925, 0x999A }, /* R16925 - HDBASS_PG_0 */ - - { 17048, 0x0083 }, /* R17408 - HPF_C_1 */ - { 17049, 0x98AD }, /* R17409 - HPF_C_0 */ - - { 17920, 0x007F }, /* R17920 - ADCL_RETUNE_C1_1 */ - { 17921, 0xFFFF }, /* R17921 - ADCL_RETUNE_C1_0 */ - { 17922, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */ - { 17923, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */ - { 17924, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */ - { 17925, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */ - { 17926, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */ - { 17927, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */ - { 17928, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */ - { 17929, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */ - { 17930, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */ - { 17931, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */ - { 17932, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */ - { 17933, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */ - { 17934, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */ - { 17935, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */ - { 17936, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */ - { 17937, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */ - { 17938, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */ - { 17939, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */ - { 17940, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */ - { 17941, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */ - { 17942, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */ - { 17943, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */ - { 17944, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */ - { 17945, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */ - { 17946, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */ - { 17947, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */ - { 17948, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */ - { 17949, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */ - { 17950, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */ - { 17951, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */ - { 17952, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */ - { 17953, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */ - { 17954, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */ - { 17955, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */ - { 17956, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */ - { 17957, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */ - { 17958, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */ - { 17959, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */ - { 17960, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */ - { 17961, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */ - { 17962, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */ - { 17963, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */ - { 17964, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */ - { 17965, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */ - { 17966, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */ - { 17967, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */ - { 17968, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */ - { 17969, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */ - { 17970, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */ - { 17971, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */ - { 17972, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */ - { 17973, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */ - { 17974, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */ - { 17975, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */ - { 17976, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */ - { 17977, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */ - { 17978, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */ - { 17979, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */ - { 17980, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */ - { 17981, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */ - { 17982, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */ - { 17983, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */ - - { 18432, 0x0020 }, /* R18432 - RETUNEADC_PG2_1 */ - { 18433, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */ - { 18434, 0x0040 }, /* R18434 - RETUNEADC_PG_1 */ - { 18435, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */ - - { 18944, 0x007F }, /* R18944 - ADCR_RETUNE_C1_1 */ - { 18945, 0xFFFF }, /* R18945 - ADCR_RETUNE_C1_0 */ - { 18946, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */ - { 18947, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */ - { 18948, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */ - { 18949, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */ - { 18950, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */ - { 18951, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */ - { 18952, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */ - { 18953, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */ - { 18954, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */ - { 18955, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */ - { 18956, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */ - { 18957, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */ - { 18958, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */ - { 18959, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */ - { 18960, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */ - { 18961, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */ - { 18962, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */ - { 18963, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */ - { 18964, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */ - { 18965, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */ - { 18966, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */ - { 18967, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */ - { 18968, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */ - { 18969, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */ - { 18970, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */ - { 18971, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */ - { 18972, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */ - { 18973, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */ - { 18974, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */ - { 18975, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */ - { 18976, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */ - { 18977, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */ - { 18978, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */ - { 18979, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */ - { 18980, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */ - { 18981, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */ - { 18982, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */ - { 18983, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */ - { 18984, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */ - { 18985, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */ - { 18986, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */ - { 18987, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */ - { 18988, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */ - { 18989, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */ - { 18990, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */ - { 18991, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */ - { 18992, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */ - { 18993, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */ - { 18994, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */ - { 18995, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */ - { 18996, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */ - { 18997, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */ - { 18998, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */ - { 18999, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */ - { 19000, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */ - { 19001, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */ - { 19002, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */ - { 19003, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */ - { 19004, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */ - { 19005, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */ - { 19006, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */ - { 19007, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */ - - { 19456, 0x007F }, /* R19456 - DACL_RETUNE_C1_1 */ - { 19457, 0xFFFF }, /* R19457 - DACL_RETUNE_C1_0 */ - { 19458, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */ - { 19459, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */ - { 19460, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */ - { 19461, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */ - { 19462, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */ - { 19463, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */ - { 19464, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */ - { 19465, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */ - { 19466, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */ - { 19467, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */ - { 19468, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */ - { 19469, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */ - { 19470, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */ - { 19471, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */ - { 19472, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */ - { 19473, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */ - { 19474, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */ - { 19475, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */ - { 19476, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */ - { 19477, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */ - { 19478, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */ - { 19479, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */ - { 19480, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */ - { 19481, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */ - { 19482, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */ - { 19483, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */ - { 19484, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */ - { 19485, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */ - { 19486, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */ - { 19487, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */ - { 19488, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */ - { 19489, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */ - { 19490, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */ - { 19491, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */ - { 19492, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */ - { 19493, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */ - { 19494, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */ - { 19495, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */ - { 19496, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */ - { 19497, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */ - { 19498, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */ - { 19499, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */ - { 19500, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */ - { 19501, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */ - { 19502, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */ - { 19503, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */ - { 19504, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */ - { 19505, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */ - { 19506, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */ - { 19507, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */ - { 19508, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */ - { 19509, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */ - { 19510, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */ - { 19511, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */ - { 19512, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */ - { 19513, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */ - { 19514, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */ - { 19515, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */ - { 19516, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */ - { 19517, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */ - { 19518, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */ - { 19519, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */ - - { 19968, 0x0020 }, /* R19968 - RETUNEDAC_PG2_1 */ - { 19969, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */ - { 19970, 0x0040 }, /* R19970 - RETUNEDAC_PG_1 */ - { 19971, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */ - - { 20480, 0x007F }, /* R20480 - DACR_RETUNE_C1_1 */ - { 20481, 0xFFFF }, /* R20481 - DACR_RETUNE_C1_0 */ - { 20482, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */ - { 20483, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */ - { 20484, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */ - { 20485, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */ - { 20486, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */ - { 20487, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */ - { 20488, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */ - { 20489, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */ - { 20490, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */ - { 20491, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */ - { 20492, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */ - { 20493, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */ - { 20494, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */ - { 20495, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */ - { 20496, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */ - { 20497, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */ - { 20498, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */ - { 20499, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */ - { 20500, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */ - { 20501, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */ - { 20502, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */ - { 20503, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */ - { 20504, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */ - { 20505, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */ - { 20506, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */ - { 20507, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */ - { 20508, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */ - { 20509, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */ - { 20510, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */ - { 20511, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */ - { 20512, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */ - { 20513, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */ - { 20514, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */ - { 20515, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */ - { 20516, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */ - { 20517, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */ - { 20518, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */ - { 20519, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */ - { 20520, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */ - { 20521, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */ - { 20522, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */ - { 20523, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */ - { 20524, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */ - { 20525, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */ - { 20526, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */ - { 20527, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */ - { 20528, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */ - { 20529, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */ - { 20530, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */ - { 20531, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */ - { 20532, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */ - { 20533, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */ - { 20534, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */ - { 20535, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */ - { 20536, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */ - { 20537, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */ - { 20538, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */ - { 20539, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */ - { 20540, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */ - { 20541, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */ - { 20542, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */ - { 20543, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */ - - { 20992, 0x008C }, /* R20992 - VSS_XHD2_1 */ - { 20993, 0x0200 }, /* R20993 - VSS_XHD2_0 */ - { 20994, 0x0035 }, /* R20994 - VSS_XHD3_1 */ - { 20995, 0x0700 }, /* R20995 - VSS_XHD3_0 */ - { 20996, 0x003A }, /* R20996 - VSS_XHN1_1 */ - { 20997, 0x4100 }, /* R20997 - VSS_XHN1_0 */ - { 20998, 0x008B }, /* R20998 - VSS_XHN2_1 */ - { 20999, 0x7D00 }, /* R20999 - VSS_XHN2_0 */ - { 21000, 0x003A }, /* R21000 - VSS_XHN3_1 */ - { 21001, 0x4100 }, /* R21001 - VSS_XHN3_0 */ - { 21002, 0x008C }, /* R21002 - VSS_XLA_1 */ - { 21003, 0xFEE8 }, /* R21003 - VSS_XLA_0 */ - { 21004, 0x0078 }, /* R21004 - VSS_XLB_1 */ - { 21005, 0x0000 }, /* R21005 - VSS_XLB_0 */ - { 21006, 0x003F }, /* R21006 - VSS_XLG_1 */ - { 21007, 0xB260 }, /* R21007 - VSS_XLG_0 */ - { 21008, 0x002D }, /* R21008 - VSS_PG2_1 */ - { 21009, 0x1818 }, /* R21009 - VSS_PG2_0 */ - { 21010, 0x0020 }, /* R21010 - VSS_PG_1 */ - { 21011, 0x0000 }, /* R21011 - VSS_PG_0 */ - { 21012, 0x00F1 }, /* R21012 - VSS_XTD1_1 */ - { 21013, 0x8340 }, /* R21013 - VSS_XTD1_0 */ - { 21014, 0x00FB }, /* R21014 - VSS_XTD2_1 */ - { 21015, 0x8300 }, /* R21015 - VSS_XTD2_0 */ - { 21016, 0x00EE }, /* R21016 - VSS_XTD3_1 */ - { 21017, 0xAEC0 }, /* R21017 - VSS_XTD3_0 */ - { 21018, 0x00FB }, /* R21018 - VSS_XTD4_1 */ - { 21019, 0xAC40 }, /* R21019 - VSS_XTD4_0 */ - { 21020, 0x00F1 }, /* R21020 - VSS_XTD5_1 */ - { 21021, 0x7F80 }, /* R21021 - VSS_XTD5_0 */ - { 21022, 0x00F4 }, /* R21022 - VSS_XTD6_1 */ - { 21023, 0x3B40 }, /* R21023 - VSS_XTD6_0 */ - { 21024, 0x00F5 }, /* R21024 - VSS_XTD7_1 */ - { 21025, 0xFB00 }, /* R21025 - VSS_XTD7_0 */ - { 21026, 0x00EA }, /* R21026 - VSS_XTD8_1 */ - { 21027, 0x10C0 }, /* R21027 - VSS_XTD8_0 */ - { 21028, 0x00FC }, /* R21028 - VSS_XTD9_1 */ - { 21029, 0xC580 }, /* R21029 - VSS_XTD9_0 */ - { 21030, 0x00E2 }, /* R21030 - VSS_XTD10_1 */ - { 21031, 0x75C0 }, /* R21031 - VSS_XTD10_0 */ - { 21032, 0x0004 }, /* R21032 - VSS_XTD11_1 */ - { 21033, 0xB480 }, /* R21033 - VSS_XTD11_0 */ - { 21034, 0x00D4 }, /* R21034 - VSS_XTD12_1 */ - { 21035, 0xF980 }, /* R21035 - VSS_XTD12_0 */ - { 21036, 0x0004 }, /* R21036 - VSS_XTD13_1 */ - { 21037, 0x9140 }, /* R21037 - VSS_XTD13_0 */ - { 21038, 0x00D8 }, /* R21038 - VSS_XTD14_1 */ - { 21039, 0xA480 }, /* R21039 - VSS_XTD14_0 */ - { 21040, 0x0002 }, /* R21040 - VSS_XTD15_1 */ - { 21041, 0x3DC0 }, /* R21041 - VSS_XTD15_0 */ - { 21042, 0x00CF }, /* R21042 - VSS_XTD16_1 */ - { 21043, 0x7A80 }, /* R21043 - VSS_XTD16_0 */ - { 21044, 0x00DC }, /* R21044 - VSS_XTD17_1 */ - { 21045, 0x0600 }, /* R21045 - VSS_XTD17_0 */ - { 21046, 0x00F2 }, /* R21046 - VSS_XTD18_1 */ - { 21047, 0xDAC0 }, /* R21047 - VSS_XTD18_0 */ - { 21048, 0x00BA }, /* R21048 - VSS_XTD19_1 */ - { 21049, 0xF340 }, /* R21049 - VSS_XTD19_0 */ - { 21050, 0x000A }, /* R21050 - VSS_XTD20_1 */ - { 21051, 0x7940 }, /* R21051 - VSS_XTD20_0 */ - { 21052, 0x001C }, /* R21052 - VSS_XTD21_1 */ - { 21053, 0x0680 }, /* R21053 - VSS_XTD21_0 */ - { 21054, 0x00FD }, /* R21054 - VSS_XTD22_1 */ - { 21055, 0x2D00 }, /* R21055 - VSS_XTD22_0 */ - { 21056, 0x001C }, /* R21056 - VSS_XTD23_1 */ - { 21057, 0xE840 }, /* R21057 - VSS_XTD23_0 */ - { 21058, 0x000D }, /* R21058 - VSS_XTD24_1 */ - { 21059, 0xDC40 }, /* R21059 - VSS_XTD24_0 */ - { 21060, 0x00FC }, /* R21060 - VSS_XTD25_1 */ - { 21061, 0x9D00 }, /* R21061 - VSS_XTD25_0 */ - { 21062, 0x0009 }, /* R21062 - VSS_XTD26_1 */ - { 21063, 0x5580 }, /* R21063 - VSS_XTD26_0 */ - { 21064, 0x00FE }, /* R21064 - VSS_XTD27_1 */ - { 21065, 0x7E80 }, /* R21065 - VSS_XTD27_0 */ - { 21066, 0x000E }, /* R21066 - VSS_XTD28_1 */ - { 21067, 0xAB40 }, /* R21067 - VSS_XTD28_0 */ - { 21068, 0x00F9 }, /* R21068 - VSS_XTD29_1 */ - { 21069, 0x9880 }, /* R21069 - VSS_XTD29_0 */ - { 21070, 0x0009 }, /* R21070 - VSS_XTD30_1 */ - { 21071, 0x87C0 }, /* R21071 - VSS_XTD30_0 */ - { 21072, 0x00FD }, /* R21072 - VSS_XTD31_1 */ - { 21073, 0x2C40 }, /* R21073 - VSS_XTD31_0 */ - { 21074, 0x0009 }, /* R21074 - VSS_XTD32_1 */ - { 21075, 0x4800 }, /* R21075 - VSS_XTD32_0 */ - { 21076, 0x0003 }, /* R21076 - VSS_XTS1_1 */ - { 21077, 0x5F40 }, /* R21077 - VSS_XTS1_0 */ - { 21078, 0x0000 }, /* R21078 - VSS_XTS2_1 */ - { 21079, 0x8700 }, /* R21079 - VSS_XTS2_0 */ - { 21080, 0x00FA }, /* R21080 - VSS_XTS3_1 */ - { 21081, 0xE4C0 }, /* R21081 - VSS_XTS3_0 */ - { 21082, 0x0000 }, /* R21082 - VSS_XTS4_1 */ - { 21083, 0x0B40 }, /* R21083 - VSS_XTS4_0 */ - { 21084, 0x0004 }, /* R21084 - VSS_XTS5_1 */ - { 21085, 0xE180 }, /* R21085 - VSS_XTS5_0 */ - { 21086, 0x0001 }, /* R21086 - VSS_XTS6_1 */ - { 21087, 0x1F40 }, /* R21087 - VSS_XTS6_0 */ - { 21088, 0x00F8 }, /* R21088 - VSS_XTS7_1 */ - { 21089, 0xB000 }, /* R21089 - VSS_XTS7_0 */ - { 21090, 0x00FB }, /* R21090 - VSS_XTS8_1 */ - { 21091, 0xCBC0 }, /* R21091 - VSS_XTS8_0 */ - { 21092, 0x0004 }, /* R21092 - VSS_XTS9_1 */ - { 21093, 0xF380 }, /* R21093 - VSS_XTS9_0 */ - { 21094, 0x0007 }, /* R21094 - VSS_XTS10_1 */ - { 21095, 0xDF40 }, /* R21095 - VSS_XTS10_0 */ - { 21096, 0x00FF }, /* R21096 - VSS_XTS11_1 */ - { 21097, 0x0700 }, /* R21097 - VSS_XTS11_0 */ - { 21098, 0x00EF }, /* R21098 - VSS_XTS12_1 */ - { 21099, 0xD700 }, /* R21099 - VSS_XTS12_0 */ - { 21100, 0x00FB }, /* R21100 - VSS_XTS13_1 */ - { 21101, 0xAF40 }, /* R21101 - VSS_XTS13_0 */ - { 21102, 0x0010 }, /* R21102 - VSS_XTS14_1 */ - { 21103, 0x8A80 }, /* R21103 - VSS_XTS14_0 */ - { 21104, 0x0011 }, /* R21104 - VSS_XTS15_1 */ - { 21105, 0x07C0 }, /* R21105 - VSS_XTS15_0 */ - { 21106, 0x00E0 }, /* R21106 - VSS_XTS16_1 */ - { 21107, 0x0800 }, /* R21107 - VSS_XTS16_0 */ - { 21108, 0x00D2 }, /* R21108 - VSS_XTS17_1 */ - { 21109, 0x7600 }, /* R21109 - VSS_XTS17_0 */ - { 21110, 0x0020 }, /* R21110 - VSS_XTS18_1 */ - { 21111, 0xCF40 }, /* R21111 - VSS_XTS18_0 */ - { 21112, 0x0030 }, /* R21112 - VSS_XTS19_1 */ - { 21113, 0x2340 }, /* R21113 - VSS_XTS19_0 */ - { 21114, 0x00FD }, /* R21114 - VSS_XTS20_1 */ - { 21115, 0x69C0 }, /* R21115 - VSS_XTS20_0 */ - { 21116, 0x0028 }, /* R21116 - VSS_XTS21_1 */ - { 21117, 0x3500 }, /* R21117 - VSS_XTS21_0 */ - { 21118, 0x0006 }, /* R21118 - VSS_XTS22_1 */ - { 21119, 0x3300 }, /* R21119 - VSS_XTS22_0 */ - { 21120, 0x00D9 }, /* R21120 - VSS_XTS23_1 */ - { 21121, 0xF6C0 }, /* R21121 - VSS_XTS23_0 */ - { 21122, 0x00F3 }, /* R21122 - VSS_XTS24_1 */ - { 21123, 0x3340 }, /* R21123 - VSS_XTS24_0 */ - { 21124, 0x000F }, /* R21124 - VSS_XTS25_1 */ - { 21125, 0x4200 }, /* R21125 - VSS_XTS25_0 */ - { 21126, 0x0004 }, /* R21126 - VSS_XTS26_1 */ - { 21127, 0x0C80 }, /* R21127 - VSS_XTS26_0 */ - { 21128, 0x00FB }, /* R21128 - VSS_XTS27_1 */ - { 21129, 0x3F80 }, /* R21129 - VSS_XTS27_0 */ - { 21130, 0x00F7 }, /* R21130 - VSS_XTS28_1 */ - { 21131, 0x57C0 }, /* R21131 - VSS_XTS28_0 */ - { 21132, 0x0003 }, /* R21132 - VSS_XTS29_1 */ - { 21133, 0x5400 }, /* R21133 - VSS_XTS29_0 */ - { 21134, 0x0000 }, /* R21134 - VSS_XTS30_1 */ - { 21135, 0xC6C0 }, /* R21135 - VSS_XTS30_0 */ - { 21136, 0x0003 }, /* R21136 - VSS_XTS31_1 */ - { 21137, 0x12C0 }, /* R21137 - VSS_XTS31_0 */ - { 21138, 0x00FD }, /* R21138 - VSS_XTS32_1 */ - { 21139, 0x8580 }, /* R21139 - VSS_XTS32_0 */ -}; - -static bool wm8962_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8962_CLOCKING1: - case WM8962_CLOCKING2: - case WM8962_SOFTWARE_RESET: - case WM8962_ALC2: - case WM8962_THERMAL_SHUTDOWN_STATUS: - case WM8962_ADDITIONAL_CONTROL_4: - case WM8962_CLASS_D_CONTROL_1: - case WM8962_DC_SERVO_6: - case WM8962_INTERRUPT_STATUS_1: - case WM8962_INTERRUPT_STATUS_2: - case WM8962_DSP2_EXECCONTROL: - return true; - default: - return false; - } -} - -static bool wm8962_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8962_LEFT_INPUT_VOLUME: - case WM8962_RIGHT_INPUT_VOLUME: - case WM8962_HPOUTL_VOLUME: - case WM8962_HPOUTR_VOLUME: - case WM8962_CLOCKING1: - case WM8962_ADC_DAC_CONTROL_1: - case WM8962_ADC_DAC_CONTROL_2: - case WM8962_AUDIO_INTERFACE_0: - case WM8962_CLOCKING2: - case WM8962_AUDIO_INTERFACE_1: - case WM8962_LEFT_DAC_VOLUME: - case WM8962_RIGHT_DAC_VOLUME: - case WM8962_AUDIO_INTERFACE_2: - case WM8962_SOFTWARE_RESET: - case WM8962_ALC1: - case WM8962_ALC2: - case WM8962_ALC3: - case WM8962_NOISE_GATE: - case WM8962_LEFT_ADC_VOLUME: - case WM8962_RIGHT_ADC_VOLUME: - case WM8962_ADDITIONAL_CONTROL_1: - case WM8962_ADDITIONAL_CONTROL_2: - case WM8962_PWR_MGMT_1: - case WM8962_PWR_MGMT_2: - case WM8962_ADDITIONAL_CONTROL_3: - case WM8962_ANTI_POP: - case WM8962_CLOCKING_3: - case WM8962_INPUT_MIXER_CONTROL_1: - case WM8962_LEFT_INPUT_MIXER_VOLUME: - case WM8962_RIGHT_INPUT_MIXER_VOLUME: - case WM8962_INPUT_MIXER_CONTROL_2: - case WM8962_INPUT_BIAS_CONTROL: - case WM8962_LEFT_INPUT_PGA_CONTROL: - case WM8962_RIGHT_INPUT_PGA_CONTROL: - case WM8962_SPKOUTL_VOLUME: - case WM8962_SPKOUTR_VOLUME: - case WM8962_THERMAL_SHUTDOWN_STATUS: - case WM8962_ADDITIONAL_CONTROL_4: - case WM8962_CLASS_D_CONTROL_1: - case WM8962_CLASS_D_CONTROL_2: - case WM8962_CLOCKING_4: - case WM8962_DAC_DSP_MIXING_1: - case WM8962_DAC_DSP_MIXING_2: - case WM8962_DC_SERVO_0: - case WM8962_DC_SERVO_1: - case WM8962_DC_SERVO_4: - case WM8962_DC_SERVO_6: - case WM8962_ANALOGUE_PGA_BIAS: - case WM8962_ANALOGUE_HP_0: - case WM8962_ANALOGUE_HP_2: - case WM8962_CHARGE_PUMP_1: - case WM8962_CHARGE_PUMP_B: - case WM8962_WRITE_SEQUENCER_CONTROL_1: - case WM8962_WRITE_SEQUENCER_CONTROL_2: - case WM8962_WRITE_SEQUENCER_CONTROL_3: - case WM8962_CONTROL_INTERFACE: - case WM8962_MIXER_ENABLES: - case WM8962_HEADPHONE_MIXER_1: - case WM8962_HEADPHONE_MIXER_2: - case WM8962_HEADPHONE_MIXER_3: - case WM8962_HEADPHONE_MIXER_4: - case WM8962_SPEAKER_MIXER_1: - case WM8962_SPEAKER_MIXER_2: - case WM8962_SPEAKER_MIXER_3: - case WM8962_SPEAKER_MIXER_4: - case WM8962_SPEAKER_MIXER_5: - case WM8962_BEEP_GENERATOR_1: - case WM8962_OSCILLATOR_TRIM_3: - case WM8962_OSCILLATOR_TRIM_4: - case WM8962_OSCILLATOR_TRIM_7: - case WM8962_ANALOGUE_CLOCKING1: - case WM8962_ANALOGUE_CLOCKING2: - case WM8962_ANALOGUE_CLOCKING3: - case WM8962_PLL_SOFTWARE_RESET: - case WM8962_PLL2: - case WM8962_PLL_4: - case WM8962_PLL_9: - case WM8962_PLL_10: - case WM8962_PLL_11: - case WM8962_PLL_12: - case WM8962_PLL_13: - case WM8962_PLL_14: - case WM8962_PLL_15: - case WM8962_PLL_16: - case WM8962_FLL_CONTROL_1: - case WM8962_FLL_CONTROL_2: - case WM8962_FLL_CONTROL_3: - case WM8962_FLL_CONTROL_5: - case WM8962_FLL_CONTROL_6: - case WM8962_FLL_CONTROL_7: - case WM8962_FLL_CONTROL_8: - case WM8962_GENERAL_TEST_1: - case WM8962_DF1: - case WM8962_DF2: - case WM8962_DF3: - case WM8962_DF4: - case WM8962_DF5: - case WM8962_DF6: - case WM8962_DF7: - case WM8962_LHPF1: - case WM8962_LHPF2: - case WM8962_THREED1: - case WM8962_THREED2: - case WM8962_THREED3: - case WM8962_THREED4: - case WM8962_DRC_1: - case WM8962_DRC_2: - case WM8962_DRC_3: - case WM8962_DRC_4: - case WM8962_DRC_5: - case WM8962_TLOOPBACK: - case WM8962_EQ1: - case WM8962_EQ2: - case WM8962_EQ3: - case WM8962_EQ4: - case WM8962_EQ5: - case WM8962_EQ6: - case WM8962_EQ7: - case WM8962_EQ8: - case WM8962_EQ9: - case WM8962_EQ10: - case WM8962_EQ11: - case WM8962_EQ12: - case WM8962_EQ13: - case WM8962_EQ14: - case WM8962_EQ15: - case WM8962_EQ16: - case WM8962_EQ17: - case WM8962_EQ18: - case WM8962_EQ19: - case WM8962_EQ20: - case WM8962_EQ21: - case WM8962_EQ22: - case WM8962_EQ23: - case WM8962_EQ24: - case WM8962_EQ25: - case WM8962_EQ26: - case WM8962_EQ27: - case WM8962_EQ28: - case WM8962_EQ29: - case WM8962_EQ30: - case WM8962_EQ31: - case WM8962_EQ32: - case WM8962_EQ33: - case WM8962_EQ34: - case WM8962_EQ35: - case WM8962_EQ36: - case WM8962_EQ37: - case WM8962_EQ38: - case WM8962_EQ39: - case WM8962_EQ40: - case WM8962_EQ41: - case WM8962_GPIO_BASE: - case WM8962_GPIO_2: - case WM8962_GPIO_3: - case WM8962_GPIO_5: - case WM8962_GPIO_6: - case WM8962_INTERRUPT_STATUS_1: - case WM8962_INTERRUPT_STATUS_2: - case WM8962_INTERRUPT_STATUS_1_MASK: - case WM8962_INTERRUPT_STATUS_2_MASK: - case WM8962_INTERRUPT_CONTROL: - case WM8962_IRQ_DEBOUNCE: - case WM8962_MICINT_SOURCE_POL: - case WM8962_DSP2_POWER_MANAGEMENT: - case WM8962_DSP2_EXECCONTROL: - case WM8962_DSP2_INSTRUCTION_RAM_0: - case WM8962_DSP2_ADDRESS_RAM_2: - case WM8962_DSP2_ADDRESS_RAM_1: - case WM8962_DSP2_ADDRESS_RAM_0: - case WM8962_DSP2_DATA1_RAM_1: - case WM8962_DSP2_DATA1_RAM_0: - case WM8962_DSP2_DATA2_RAM_1: - case WM8962_DSP2_DATA2_RAM_0: - case WM8962_DSP2_DATA3_RAM_1: - case WM8962_DSP2_DATA3_RAM_0: - case WM8962_DSP2_COEFF_RAM_0: - case WM8962_RETUNEADC_SHARED_COEFF_1: - case WM8962_RETUNEADC_SHARED_COEFF_0: - case WM8962_RETUNEDAC_SHARED_COEFF_1: - case WM8962_RETUNEDAC_SHARED_COEFF_0: - case WM8962_SOUNDSTAGE_ENABLES_1: - case WM8962_SOUNDSTAGE_ENABLES_0: - case WM8962_HDBASS_AI_1: - case WM8962_HDBASS_AI_0: - case WM8962_HDBASS_AR_1: - case WM8962_HDBASS_AR_0: - case WM8962_HDBASS_B_1: - case WM8962_HDBASS_B_0: - case WM8962_HDBASS_K_1: - case WM8962_HDBASS_K_0: - case WM8962_HDBASS_N1_1: - case WM8962_HDBASS_N1_0: - case WM8962_HDBASS_N2_1: - case WM8962_HDBASS_N2_0: - case WM8962_HDBASS_N3_1: - case WM8962_HDBASS_N3_0: - case WM8962_HDBASS_N4_1: - case WM8962_HDBASS_N4_0: - case WM8962_HDBASS_N5_1: - case WM8962_HDBASS_N5_0: - case WM8962_HDBASS_X1_1: - case WM8962_HDBASS_X1_0: - case WM8962_HDBASS_X2_1: - case WM8962_HDBASS_X2_0: - case WM8962_HDBASS_X3_1: - case WM8962_HDBASS_X3_0: - case WM8962_HDBASS_ATK_1: - case WM8962_HDBASS_ATK_0: - case WM8962_HDBASS_DCY_1: - case WM8962_HDBASS_DCY_0: - case WM8962_HDBASS_PG_1: - case WM8962_HDBASS_PG_0: - case WM8962_HPF_C_1: - case WM8962_HPF_C_0: - case WM8962_ADCL_RETUNE_C1_1: - case WM8962_ADCL_RETUNE_C1_0: - case WM8962_ADCL_RETUNE_C2_1: - case WM8962_ADCL_RETUNE_C2_0: - case WM8962_ADCL_RETUNE_C3_1: - case WM8962_ADCL_RETUNE_C3_0: - case WM8962_ADCL_RETUNE_C4_1: - case WM8962_ADCL_RETUNE_C4_0: - case WM8962_ADCL_RETUNE_C5_1: - case WM8962_ADCL_RETUNE_C5_0: - case WM8962_ADCL_RETUNE_C6_1: - case WM8962_ADCL_RETUNE_C6_0: - case WM8962_ADCL_RETUNE_C7_1: - case WM8962_ADCL_RETUNE_C7_0: - case WM8962_ADCL_RETUNE_C8_1: - case WM8962_ADCL_RETUNE_C8_0: - case WM8962_ADCL_RETUNE_C9_1: - case WM8962_ADCL_RETUNE_C9_0: - case WM8962_ADCL_RETUNE_C10_1: - case WM8962_ADCL_RETUNE_C10_0: - case WM8962_ADCL_RETUNE_C11_1: - case WM8962_ADCL_RETUNE_C11_0: - case WM8962_ADCL_RETUNE_C12_1: - case WM8962_ADCL_RETUNE_C12_0: - case WM8962_ADCL_RETUNE_C13_1: - case WM8962_ADCL_RETUNE_C13_0: - case WM8962_ADCL_RETUNE_C14_1: - case WM8962_ADCL_RETUNE_C14_0: - case WM8962_ADCL_RETUNE_C15_1: - case WM8962_ADCL_RETUNE_C15_0: - case WM8962_ADCL_RETUNE_C16_1: - case WM8962_ADCL_RETUNE_C16_0: - case WM8962_ADCL_RETUNE_C17_1: - case WM8962_ADCL_RETUNE_C17_0: - case WM8962_ADCL_RETUNE_C18_1: - case WM8962_ADCL_RETUNE_C18_0: - case WM8962_ADCL_RETUNE_C19_1: - case WM8962_ADCL_RETUNE_C19_0: - case WM8962_ADCL_RETUNE_C20_1: - case WM8962_ADCL_RETUNE_C20_0: - case WM8962_ADCL_RETUNE_C21_1: - case WM8962_ADCL_RETUNE_C21_0: - case WM8962_ADCL_RETUNE_C22_1: - case WM8962_ADCL_RETUNE_C22_0: - case WM8962_ADCL_RETUNE_C23_1: - case WM8962_ADCL_RETUNE_C23_0: - case WM8962_ADCL_RETUNE_C24_1: - case WM8962_ADCL_RETUNE_C24_0: - case WM8962_ADCL_RETUNE_C25_1: - case WM8962_ADCL_RETUNE_C25_0: - case WM8962_ADCL_RETUNE_C26_1: - case WM8962_ADCL_RETUNE_C26_0: - case WM8962_ADCL_RETUNE_C27_1: - case WM8962_ADCL_RETUNE_C27_0: - case WM8962_ADCL_RETUNE_C28_1: - case WM8962_ADCL_RETUNE_C28_0: - case WM8962_ADCL_RETUNE_C29_1: - case WM8962_ADCL_RETUNE_C29_0: - case WM8962_ADCL_RETUNE_C30_1: - case WM8962_ADCL_RETUNE_C30_0: - case WM8962_ADCL_RETUNE_C31_1: - case WM8962_ADCL_RETUNE_C31_0: - case WM8962_ADCL_RETUNE_C32_1: - case WM8962_ADCL_RETUNE_C32_0: - case WM8962_RETUNEADC_PG2_1: - case WM8962_RETUNEADC_PG2_0: - case WM8962_RETUNEADC_PG_1: - case WM8962_RETUNEADC_PG_0: - case WM8962_ADCR_RETUNE_C1_1: - case WM8962_ADCR_RETUNE_C1_0: - case WM8962_ADCR_RETUNE_C2_1: - case WM8962_ADCR_RETUNE_C2_0: - case WM8962_ADCR_RETUNE_C3_1: - case WM8962_ADCR_RETUNE_C3_0: - case WM8962_ADCR_RETUNE_C4_1: - case WM8962_ADCR_RETUNE_C4_0: - case WM8962_ADCR_RETUNE_C5_1: - case WM8962_ADCR_RETUNE_C5_0: - case WM8962_ADCR_RETUNE_C6_1: - case WM8962_ADCR_RETUNE_C6_0: - case WM8962_ADCR_RETUNE_C7_1: - case WM8962_ADCR_RETUNE_C7_0: - case WM8962_ADCR_RETUNE_C8_1: - case WM8962_ADCR_RETUNE_C8_0: - case WM8962_ADCR_RETUNE_C9_1: - case WM8962_ADCR_RETUNE_C9_0: - case WM8962_ADCR_RETUNE_C10_1: - case WM8962_ADCR_RETUNE_C10_0: - case WM8962_ADCR_RETUNE_C11_1: - case WM8962_ADCR_RETUNE_C11_0: - case WM8962_ADCR_RETUNE_C12_1: - case WM8962_ADCR_RETUNE_C12_0: - case WM8962_ADCR_RETUNE_C13_1: - case WM8962_ADCR_RETUNE_C13_0: - case WM8962_ADCR_RETUNE_C14_1: - case WM8962_ADCR_RETUNE_C14_0: - case WM8962_ADCR_RETUNE_C15_1: - case WM8962_ADCR_RETUNE_C15_0: - case WM8962_ADCR_RETUNE_C16_1: - case WM8962_ADCR_RETUNE_C16_0: - case WM8962_ADCR_RETUNE_C17_1: - case WM8962_ADCR_RETUNE_C17_0: - case WM8962_ADCR_RETUNE_C18_1: - case WM8962_ADCR_RETUNE_C18_0: - case WM8962_ADCR_RETUNE_C19_1: - case WM8962_ADCR_RETUNE_C19_0: - case WM8962_ADCR_RETUNE_C20_1: - case WM8962_ADCR_RETUNE_C20_0: - case WM8962_ADCR_RETUNE_C21_1: - case WM8962_ADCR_RETUNE_C21_0: - case WM8962_ADCR_RETUNE_C22_1: - case WM8962_ADCR_RETUNE_C22_0: - case WM8962_ADCR_RETUNE_C23_1: - case WM8962_ADCR_RETUNE_C23_0: - case WM8962_ADCR_RETUNE_C24_1: - case WM8962_ADCR_RETUNE_C24_0: - case WM8962_ADCR_RETUNE_C25_1: - case WM8962_ADCR_RETUNE_C25_0: - case WM8962_ADCR_RETUNE_C26_1: - case WM8962_ADCR_RETUNE_C26_0: - case WM8962_ADCR_RETUNE_C27_1: - case WM8962_ADCR_RETUNE_C27_0: - case WM8962_ADCR_RETUNE_C28_1: - case WM8962_ADCR_RETUNE_C28_0: - case WM8962_ADCR_RETUNE_C29_1: - case WM8962_ADCR_RETUNE_C29_0: - case WM8962_ADCR_RETUNE_C30_1: - case WM8962_ADCR_RETUNE_C30_0: - case WM8962_ADCR_RETUNE_C31_1: - case WM8962_ADCR_RETUNE_C31_0: - case WM8962_ADCR_RETUNE_C32_1: - case WM8962_ADCR_RETUNE_C32_0: - case WM8962_DACL_RETUNE_C1_1: - case WM8962_DACL_RETUNE_C1_0: - case WM8962_DACL_RETUNE_C2_1: - case WM8962_DACL_RETUNE_C2_0: - case WM8962_DACL_RETUNE_C3_1: - case WM8962_DACL_RETUNE_C3_0: - case WM8962_DACL_RETUNE_C4_1: - case WM8962_DACL_RETUNE_C4_0: - case WM8962_DACL_RETUNE_C5_1: - case WM8962_DACL_RETUNE_C5_0: - case WM8962_DACL_RETUNE_C6_1: - case WM8962_DACL_RETUNE_C6_0: - case WM8962_DACL_RETUNE_C7_1: - case WM8962_DACL_RETUNE_C7_0: - case WM8962_DACL_RETUNE_C8_1: - case WM8962_DACL_RETUNE_C8_0: - case WM8962_DACL_RETUNE_C9_1: - case WM8962_DACL_RETUNE_C9_0: - case WM8962_DACL_RETUNE_C10_1: - case WM8962_DACL_RETUNE_C10_0: - case WM8962_DACL_RETUNE_C11_1: - case WM8962_DACL_RETUNE_C11_0: - case WM8962_DACL_RETUNE_C12_1: - case WM8962_DACL_RETUNE_C12_0: - case WM8962_DACL_RETUNE_C13_1: - case WM8962_DACL_RETUNE_C13_0: - case WM8962_DACL_RETUNE_C14_1: - case WM8962_DACL_RETUNE_C14_0: - case WM8962_DACL_RETUNE_C15_1: - case WM8962_DACL_RETUNE_C15_0: - case WM8962_DACL_RETUNE_C16_1: - case WM8962_DACL_RETUNE_C16_0: - case WM8962_DACL_RETUNE_C17_1: - case WM8962_DACL_RETUNE_C17_0: - case WM8962_DACL_RETUNE_C18_1: - case WM8962_DACL_RETUNE_C18_0: - case WM8962_DACL_RETUNE_C19_1: - case WM8962_DACL_RETUNE_C19_0: - case WM8962_DACL_RETUNE_C20_1: - case WM8962_DACL_RETUNE_C20_0: - case WM8962_DACL_RETUNE_C21_1: - case WM8962_DACL_RETUNE_C21_0: - case WM8962_DACL_RETUNE_C22_1: - case WM8962_DACL_RETUNE_C22_0: - case WM8962_DACL_RETUNE_C23_1: - case WM8962_DACL_RETUNE_C23_0: - case WM8962_DACL_RETUNE_C24_1: - case WM8962_DACL_RETUNE_C24_0: - case WM8962_DACL_RETUNE_C25_1: - case WM8962_DACL_RETUNE_C25_0: - case WM8962_DACL_RETUNE_C26_1: - case WM8962_DACL_RETUNE_C26_0: - case WM8962_DACL_RETUNE_C27_1: - case WM8962_DACL_RETUNE_C27_0: - case WM8962_DACL_RETUNE_C28_1: - case WM8962_DACL_RETUNE_C28_0: - case WM8962_DACL_RETUNE_C29_1: - case WM8962_DACL_RETUNE_C29_0: - case WM8962_DACL_RETUNE_C30_1: - case WM8962_DACL_RETUNE_C30_0: - case WM8962_DACL_RETUNE_C31_1: - case WM8962_DACL_RETUNE_C31_0: - case WM8962_DACL_RETUNE_C32_1: - case WM8962_DACL_RETUNE_C32_0: - case WM8962_RETUNEDAC_PG2_1: - case WM8962_RETUNEDAC_PG2_0: - case WM8962_RETUNEDAC_PG_1: - case WM8962_RETUNEDAC_PG_0: - case WM8962_DACR_RETUNE_C1_1: - case WM8962_DACR_RETUNE_C1_0: - case WM8962_DACR_RETUNE_C2_1: - case WM8962_DACR_RETUNE_C2_0: - case WM8962_DACR_RETUNE_C3_1: - case WM8962_DACR_RETUNE_C3_0: - case WM8962_DACR_RETUNE_C4_1: - case WM8962_DACR_RETUNE_C4_0: - case WM8962_DACR_RETUNE_C5_1: - case WM8962_DACR_RETUNE_C5_0: - case WM8962_DACR_RETUNE_C6_1: - case WM8962_DACR_RETUNE_C6_0: - case WM8962_DACR_RETUNE_C7_1: - case WM8962_DACR_RETUNE_C7_0: - case WM8962_DACR_RETUNE_C8_1: - case WM8962_DACR_RETUNE_C8_0: - case WM8962_DACR_RETUNE_C9_1: - case WM8962_DACR_RETUNE_C9_0: - case WM8962_DACR_RETUNE_C10_1: - case WM8962_DACR_RETUNE_C10_0: - case WM8962_DACR_RETUNE_C11_1: - case WM8962_DACR_RETUNE_C11_0: - case WM8962_DACR_RETUNE_C12_1: - case WM8962_DACR_RETUNE_C12_0: - case WM8962_DACR_RETUNE_C13_1: - case WM8962_DACR_RETUNE_C13_0: - case WM8962_DACR_RETUNE_C14_1: - case WM8962_DACR_RETUNE_C14_0: - case WM8962_DACR_RETUNE_C15_1: - case WM8962_DACR_RETUNE_C15_0: - case WM8962_DACR_RETUNE_C16_1: - case WM8962_DACR_RETUNE_C16_0: - case WM8962_DACR_RETUNE_C17_1: - case WM8962_DACR_RETUNE_C17_0: - case WM8962_DACR_RETUNE_C18_1: - case WM8962_DACR_RETUNE_C18_0: - case WM8962_DACR_RETUNE_C19_1: - case WM8962_DACR_RETUNE_C19_0: - case WM8962_DACR_RETUNE_C20_1: - case WM8962_DACR_RETUNE_C20_0: - case WM8962_DACR_RETUNE_C21_1: - case WM8962_DACR_RETUNE_C21_0: - case WM8962_DACR_RETUNE_C22_1: - case WM8962_DACR_RETUNE_C22_0: - case WM8962_DACR_RETUNE_C23_1: - case WM8962_DACR_RETUNE_C23_0: - case WM8962_DACR_RETUNE_C24_1: - case WM8962_DACR_RETUNE_C24_0: - case WM8962_DACR_RETUNE_C25_1: - case WM8962_DACR_RETUNE_C25_0: - case WM8962_DACR_RETUNE_C26_1: - case WM8962_DACR_RETUNE_C26_0: - case WM8962_DACR_RETUNE_C27_1: - case WM8962_DACR_RETUNE_C27_0: - case WM8962_DACR_RETUNE_C28_1: - case WM8962_DACR_RETUNE_C28_0: - case WM8962_DACR_RETUNE_C29_1: - case WM8962_DACR_RETUNE_C29_0: - case WM8962_DACR_RETUNE_C30_1: - case WM8962_DACR_RETUNE_C30_0: - case WM8962_DACR_RETUNE_C31_1: - case WM8962_DACR_RETUNE_C31_0: - case WM8962_DACR_RETUNE_C32_1: - case WM8962_DACR_RETUNE_C32_0: - case WM8962_VSS_XHD2_1: - case WM8962_VSS_XHD2_0: - case WM8962_VSS_XHD3_1: - case WM8962_VSS_XHD3_0: - case WM8962_VSS_XHN1_1: - case WM8962_VSS_XHN1_0: - case WM8962_VSS_XHN2_1: - case WM8962_VSS_XHN2_0: - case WM8962_VSS_XHN3_1: - case WM8962_VSS_XHN3_0: - case WM8962_VSS_XLA_1: - case WM8962_VSS_XLA_0: - case WM8962_VSS_XLB_1: - case WM8962_VSS_XLB_0: - case WM8962_VSS_XLG_1: - case WM8962_VSS_XLG_0: - case WM8962_VSS_PG2_1: - case WM8962_VSS_PG2_0: - case WM8962_VSS_PG_1: - case WM8962_VSS_PG_0: - case WM8962_VSS_XTD1_1: - case WM8962_VSS_XTD1_0: - case WM8962_VSS_XTD2_1: - case WM8962_VSS_XTD2_0: - case WM8962_VSS_XTD3_1: - case WM8962_VSS_XTD3_0: - case WM8962_VSS_XTD4_1: - case WM8962_VSS_XTD4_0: - case WM8962_VSS_XTD5_1: - case WM8962_VSS_XTD5_0: - case WM8962_VSS_XTD6_1: - case WM8962_VSS_XTD6_0: - case WM8962_VSS_XTD7_1: - case WM8962_VSS_XTD7_0: - case WM8962_VSS_XTD8_1: - case WM8962_VSS_XTD8_0: - case WM8962_VSS_XTD9_1: - case WM8962_VSS_XTD9_0: - case WM8962_VSS_XTD10_1: - case WM8962_VSS_XTD10_0: - case WM8962_VSS_XTD11_1: - case WM8962_VSS_XTD11_0: - case WM8962_VSS_XTD12_1: - case WM8962_VSS_XTD12_0: - case WM8962_VSS_XTD13_1: - case WM8962_VSS_XTD13_0: - case WM8962_VSS_XTD14_1: - case WM8962_VSS_XTD14_0: - case WM8962_VSS_XTD15_1: - case WM8962_VSS_XTD15_0: - case WM8962_VSS_XTD16_1: - case WM8962_VSS_XTD16_0: - case WM8962_VSS_XTD17_1: - case WM8962_VSS_XTD17_0: - case WM8962_VSS_XTD18_1: - case WM8962_VSS_XTD18_0: - case WM8962_VSS_XTD19_1: - case WM8962_VSS_XTD19_0: - case WM8962_VSS_XTD20_1: - case WM8962_VSS_XTD20_0: - case WM8962_VSS_XTD21_1: - case WM8962_VSS_XTD21_0: - case WM8962_VSS_XTD22_1: - case WM8962_VSS_XTD22_0: - case WM8962_VSS_XTD23_1: - case WM8962_VSS_XTD23_0: - case WM8962_VSS_XTD24_1: - case WM8962_VSS_XTD24_0: - case WM8962_VSS_XTD25_1: - case WM8962_VSS_XTD25_0: - case WM8962_VSS_XTD26_1: - case WM8962_VSS_XTD26_0: - case WM8962_VSS_XTD27_1: - case WM8962_VSS_XTD27_0: - case WM8962_VSS_XTD28_1: - case WM8962_VSS_XTD28_0: - case WM8962_VSS_XTD29_1: - case WM8962_VSS_XTD29_0: - case WM8962_VSS_XTD30_1: - case WM8962_VSS_XTD30_0: - case WM8962_VSS_XTD31_1: - case WM8962_VSS_XTD31_0: - case WM8962_VSS_XTD32_1: - case WM8962_VSS_XTD32_0: - case WM8962_VSS_XTS1_1: - case WM8962_VSS_XTS1_0: - case WM8962_VSS_XTS2_1: - case WM8962_VSS_XTS2_0: - case WM8962_VSS_XTS3_1: - case WM8962_VSS_XTS3_0: - case WM8962_VSS_XTS4_1: - case WM8962_VSS_XTS4_0: - case WM8962_VSS_XTS5_1: - case WM8962_VSS_XTS5_0: - case WM8962_VSS_XTS6_1: - case WM8962_VSS_XTS6_0: - case WM8962_VSS_XTS7_1: - case WM8962_VSS_XTS7_0: - case WM8962_VSS_XTS8_1: - case WM8962_VSS_XTS8_0: - case WM8962_VSS_XTS9_1: - case WM8962_VSS_XTS9_0: - case WM8962_VSS_XTS10_1: - case WM8962_VSS_XTS10_0: - case WM8962_VSS_XTS11_1: - case WM8962_VSS_XTS11_0: - case WM8962_VSS_XTS12_1: - case WM8962_VSS_XTS12_0: - case WM8962_VSS_XTS13_1: - case WM8962_VSS_XTS13_0: - case WM8962_VSS_XTS14_1: - case WM8962_VSS_XTS14_0: - case WM8962_VSS_XTS15_1: - case WM8962_VSS_XTS15_0: - case WM8962_VSS_XTS16_1: - case WM8962_VSS_XTS16_0: - case WM8962_VSS_XTS17_1: - case WM8962_VSS_XTS17_0: - case WM8962_VSS_XTS18_1: - case WM8962_VSS_XTS18_0: - case WM8962_VSS_XTS19_1: - case WM8962_VSS_XTS19_0: - case WM8962_VSS_XTS20_1: - case WM8962_VSS_XTS20_0: - case WM8962_VSS_XTS21_1: - case WM8962_VSS_XTS21_0: - case WM8962_VSS_XTS22_1: - case WM8962_VSS_XTS22_0: - case WM8962_VSS_XTS23_1: - case WM8962_VSS_XTS23_0: - case WM8962_VSS_XTS24_1: - case WM8962_VSS_XTS24_0: - case WM8962_VSS_XTS25_1: - case WM8962_VSS_XTS25_0: - case WM8962_VSS_XTS26_1: - case WM8962_VSS_XTS26_0: - case WM8962_VSS_XTS27_1: - case WM8962_VSS_XTS27_0: - case WM8962_VSS_XTS28_1: - case WM8962_VSS_XTS28_0: - case WM8962_VSS_XTS29_1: - case WM8962_VSS_XTS29_0: - case WM8962_VSS_XTS30_1: - case WM8962_VSS_XTS30_0: - case WM8962_VSS_XTS31_1: - case WM8962_VSS_XTS31_0: - case WM8962_VSS_XTS32_1: - case WM8962_VSS_XTS32_0: - return true; - default: - return false; - } -} - -static int wm8962_reset(struct wm8962_priv *wm8962) -{ - int ret; - - ret = regmap_write(wm8962->regmap, WM8962_SOFTWARE_RESET, 0x6243); - if (ret != 0) - return ret; - - return regmap_write(wm8962->regmap, WM8962_PLL_SOFTWARE_RESET, 0); -} - -static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0); -static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0); -static const unsigned int mixinpga_tlv[] = { - TLV_DB_RANGE_HEAD(5), - 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0), - 2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0), - 3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0), - 5, 5, TLV_DB_SCALE_ITEM(2400, 0, 0), - 6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0), -}; -static const DECLARE_TLV_DB_SCALE(beep_tlv, -9600, 600, 1); -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); -static const DECLARE_TLV_DB_SCALE(inmix_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0); -static const unsigned int classd_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), - 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); - -static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) -{ - return 0; -} - -static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val) -{ - u16 adcl = snd_soc_read(codec, WM8962_LEFT_ADC_VOLUME); - u16 adcr = snd_soc_read(codec, WM8962_RIGHT_ADC_VOLUME); - u16 dac = snd_soc_read(codec, WM8962_ADC_DAC_CONTROL_1); - - /* Mute the ADCs and DACs */ - snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, 0); - snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, WM8962_ADC_VU); - snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, - WM8962_DAC_MUTE, WM8962_DAC_MUTE); - - snd_soc_write(codec, WM8962_SOUNDSTAGE_ENABLES_0, val); - - /* Restore the ADCs and DACs */ - snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, adcl); - snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, adcr); - snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, - WM8962_DAC_MUTE, dac); - - return 0; -} - -static int wm8962_dsp2_start(struct snd_soc_codec *codec) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - - wm8962_dsp2_write_config(codec); - - snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_RUNR); - - wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); - - return 0; -} - -static int wm8962_dsp2_stop(struct snd_soc_codec *codec) -{ - wm8962_dsp2_set_enable(codec, 0); - - snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_STOP); - - return 0; -} - -#define WM8962_DSP2_ENABLE(xname, xshift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = wm8962_dsp2_ena_info, \ - .get = wm8962_dsp2_ena_get, .put = wm8962_dsp2_ena_put, \ - .private_value = xshift } - -static int wm8962_dsp2_ena_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - - return 0; -} - -static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int shift = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - - ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift); - - return 0; -} - -static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int shift = kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int old = wm8962->dsp2_ena; - int ret = 0; - int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & - WM8962_DSP2_ENA; - - mutex_lock(&codec->mutex); - - if (ucontrol->value.integer.value[0]) - wm8962->dsp2_ena |= 1 << shift; - else - wm8962->dsp2_ena &= ~(1 << shift); - - if (wm8962->dsp2_ena == old) - goto out; - - ret = 1; - - if (dsp2_running) { - if (wm8962->dsp2_ena) - wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); - else - wm8962_dsp2_stop(codec); - } - -out: - mutex_unlock(&codec->mutex); - - return ret; -} - -/* The VU bits for the headphones are in a different register to the mute - * bits and only take effect on the PGA if it is actually powered. - */ -static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; - int ret; - - /* Apply the update (if any) */ - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret == 0) - return 0; - - /* If the left PGA is enabled hit that VU bit... */ - if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA) - return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, - reg_cache[WM8962_HPOUTL_VOLUME]); - - /* ...otherwise the right. The VU is stereo. */ - if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA) - return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, - reg_cache[WM8962_HPOUTR_VOLUME]); - - return 0; -} - -/* The VU bits for the speakers are in a different register to the mute - * bits and only take effect on the PGA if it is actually powered. - */ -static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int ret; - - /* Apply the update (if any) */ - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret == 0) - return 0; - - /* If the left PGA is enabled hit that VU bit... */ - ret = snd_soc_read(codec, WM8962_PWR_MGMT_2); - if (ret & WM8962_SPKOUTL_PGA_ENA) { - snd_soc_write(codec, WM8962_SPKOUTL_VOLUME, - snd_soc_read(codec, WM8962_SPKOUTL_VOLUME)); - return 1; - } - - /* ...otherwise the right. The VU is stereo. */ - if (ret & WM8962_SPKOUTR_PGA_ENA) - snd_soc_write(codec, WM8962_SPKOUTR_VOLUME, - snd_soc_read(codec, WM8962_SPKOUTR_VOLUME)); - - return 1; -} - -static const char *cap_hpf_mode_text[] = { - "Hi-fi", "Application" -}; - -static const struct soc_enum cap_hpf_mode = - SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); - - -static const char *cap_lhpf_mode_text[] = { - "LPF", "HPF" -}; - -static const struct soc_enum cap_lhpf_mode = - SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); - -static const struct snd_kcontrol_new wm8962_snd_controls[] = { -SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), - -SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 6, 7, 0, - mixin_tlv), -SOC_SINGLE_TLV("MIXINL PGA Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 3, 7, 0, - mixinpga_tlv), -SOC_SINGLE_TLV("MIXINL IN3L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 0, 7, 0, - mixin_tlv), - -SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 6, 7, 0, - mixin_tlv), -SOC_SINGLE_TLV("MIXINR PGA Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 3, 7, 0, - mixinpga_tlv), -SOC_SINGLE_TLV("MIXINR IN3R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 0, 7, 0, - mixin_tlv), - -SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8962_LEFT_ADC_VOLUME, - WM8962_RIGHT_ADC_VOLUME, 1, 127, 0, digital_tlv), -SOC_DOUBLE_R_TLV("Capture Volume", WM8962_LEFT_INPUT_VOLUME, - WM8962_RIGHT_INPUT_VOLUME, 0, 63, 0, inpga_tlv), -SOC_DOUBLE_R("Capture Switch", WM8962_LEFT_INPUT_VOLUME, - WM8962_RIGHT_INPUT_VOLUME, 7, 1, 1), -SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME, - WM8962_RIGHT_INPUT_VOLUME, 6, 1, 1), -SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), -SOC_ENUM("Capture HPF Mode", cap_hpf_mode), -SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), -SOC_SINGLE("Capture LHPF Switch", WM8962_LHPF1, 0, 1, 0), -SOC_ENUM("Capture LHPF Mode", cap_lhpf_mode), - -SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, - WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), - -SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME, - WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv), -SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0), -SOC_SINGLE("DAC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 5, 1, 0), -SOC_SINGLE("ADC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 8, 1, 0), - -SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1, - 5, 1, 0), - -SOC_SINGLE_TLV("Beep Volume", WM8962_BEEP_GENERATOR_1, 4, 15, 0, beep_tlv), - -SOC_DOUBLE_R_TLV("Headphone Volume", WM8962_HPOUTL_VOLUME, - WM8962_HPOUTR_VOLUME, 0, 127, 0, out_tlv), -SOC_DOUBLE_EXT("Headphone Switch", WM8962_PWR_MGMT_2, 1, 0, 1, 1, - snd_soc_get_volsw, wm8962_put_hp_sw), -SOC_DOUBLE_R("Headphone ZC Switch", WM8962_HPOUTL_VOLUME, WM8962_HPOUTR_VOLUME, - 7, 1, 0), -SOC_DOUBLE_TLV("Headphone Aux Volume", WM8962_ANALOGUE_HP_2, 3, 6, 7, 0, - hp_tlv), - -SOC_DOUBLE_R("Headphone Mixer Switch", WM8962_HEADPHONE_MIXER_3, - WM8962_HEADPHONE_MIXER_4, 8, 1, 1), - -SOC_SINGLE_TLV("HPMIXL IN4L Volume", WM8962_HEADPHONE_MIXER_3, - 3, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("HPMIXL IN4R Volume", WM8962_HEADPHONE_MIXER_3, - 0, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("HPMIXL MIXINL Volume", WM8962_HEADPHONE_MIXER_3, - 7, 1, 1, inmix_tlv), -SOC_SINGLE_TLV("HPMIXL MIXINR Volume", WM8962_HEADPHONE_MIXER_3, - 6, 1, 1, inmix_tlv), - -SOC_SINGLE_TLV("HPMIXR IN4L Volume", WM8962_HEADPHONE_MIXER_4, - 3, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("HPMIXR IN4R Volume", WM8962_HEADPHONE_MIXER_4, - 0, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("HPMIXR MIXINL Volume", WM8962_HEADPHONE_MIXER_4, - 7, 1, 1, inmix_tlv), -SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4, - 6, 1, 1, inmix_tlv), - -SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0, - classd_tlv), - -SOC_SINGLE("EQ Switch", WM8962_EQ1, WM8962_EQ_ENA_SHIFT, 1, 0), -SOC_DOUBLE_R_TLV("EQ1 Volume", WM8962_EQ2, WM8962_EQ22, - WM8962_EQL_B1_GAIN_SHIFT, 31, 0, eq_tlv), -SOC_DOUBLE_R_TLV("EQ2 Volume", WM8962_EQ2, WM8962_EQ22, - WM8962_EQL_B2_GAIN_SHIFT, 31, 0, eq_tlv), -SOC_DOUBLE_R_TLV("EQ3 Volume", WM8962_EQ2, WM8962_EQ22, - WM8962_EQL_B3_GAIN_SHIFT, 31, 0, eq_tlv), -SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23, - WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), -SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, - WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), - -WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT), -WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT), -WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT), -WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT), -}; - -static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { -SOC_SINGLE_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME, 0, 127, 0, out_tlv), -SOC_SINGLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 1, 1, - snd_soc_get_volsw, wm8962_put_spk_sw), -SOC_SINGLE("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, 7, 1, 0), - -SOC_SINGLE("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3, 8, 1, 1), -SOC_SINGLE_TLV("Speaker Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3, - 3, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("Speaker Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3, - 0, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("Speaker Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3, - 7, 1, 1, inmix_tlv), -SOC_SINGLE_TLV("Speaker Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3, - 6, 1, 1, inmix_tlv), -SOC_SINGLE_TLV("Speaker Mixer DACL Volume", WM8962_SPEAKER_MIXER_5, - 7, 1, 0, inmix_tlv), -SOC_SINGLE_TLV("Speaker Mixer DACR Volume", WM8962_SPEAKER_MIXER_5, - 6, 1, 0, inmix_tlv), -}; - -static const struct snd_kcontrol_new wm8962_spk_stereo_controls[] = { -SOC_DOUBLE_R_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME, - WM8962_SPKOUTR_VOLUME, 0, 127, 0, out_tlv), -SOC_DOUBLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 0, 1, 1, - snd_soc_get_volsw, wm8962_put_spk_sw), -SOC_DOUBLE_R("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, WM8962_SPKOUTR_VOLUME, - 7, 1, 0), - -SOC_DOUBLE_R("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3, - WM8962_SPEAKER_MIXER_4, 8, 1, 1), - -SOC_SINGLE_TLV("SPKOUTL Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3, - 3, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("SPKOUTL Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3, - 0, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("SPKOUTL Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3, - 7, 1, 1, inmix_tlv), -SOC_SINGLE_TLV("SPKOUTL Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3, - 6, 1, 1, inmix_tlv), -SOC_SINGLE_TLV("SPKOUTL Mixer DACL Volume", WM8962_SPEAKER_MIXER_5, - 7, 1, 0, inmix_tlv), -SOC_SINGLE_TLV("SPKOUTL Mixer DACR Volume", WM8962_SPEAKER_MIXER_5, - 6, 1, 0, inmix_tlv), - -SOC_SINGLE_TLV("SPKOUTR Mixer IN4L Volume", WM8962_SPEAKER_MIXER_4, - 3, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("SPKOUTR Mixer IN4R Volume", WM8962_SPEAKER_MIXER_4, - 0, 7, 0, bypass_tlv), -SOC_SINGLE_TLV("SPKOUTR Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_4, - 7, 1, 1, inmix_tlv), -SOC_SINGLE_TLV("SPKOUTR Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_4, - 6, 1, 1, inmix_tlv), -SOC_SINGLE_TLV("SPKOUTR Mixer DACL Volume", WM8962_SPEAKER_MIXER_5, - 5, 1, 0, inmix_tlv), -SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5, - 4, 1, 0, inmix_tlv), -}; - -static int cp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - switch (event) { - case SND_SOC_DAPM_POST_PMU: - msleep(5); - break; - - default: - BUG(); - return -EINVAL; - } - - return 0; -} - -static int hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - int timeout; - int reg; - int expected = (WM8962_DCS_STARTUP_DONE_HP1L | - WM8962_DCS_STARTUP_DONE_HP1R); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, - WM8962_HP1L_ENA | WM8962_HP1R_ENA, - WM8962_HP1L_ENA | WM8962_HP1R_ENA); - udelay(20); - - snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, - WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY, - WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY); - - /* Start the DC servo */ - snd_soc_update_bits(codec, WM8962_DC_SERVO_1, - WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA | - WM8962_HP1L_DCS_STARTUP | - WM8962_HP1R_DCS_STARTUP, - WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA | - WM8962_HP1L_DCS_STARTUP | - WM8962_HP1R_DCS_STARTUP); - - /* Wait for it to complete, should be well under 100ms */ - timeout = 0; - do { - msleep(1); - reg = snd_soc_read(codec, WM8962_DC_SERVO_6); - if (reg < 0) { - dev_err(codec->dev, - "Failed to read DCS status: %d\n", - reg); - continue; - } - dev_dbg(codec->dev, "DCS status: %x\n", reg); - } while (++timeout < 200 && (reg & expected) != expected); - - if ((reg & expected) != expected) - dev_err(codec->dev, "DC servo timed out\n"); - else - dev_dbg(codec->dev, "DC servo complete after %dms\n", - timeout); - - snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, - WM8962_HP1L_ENA_OUTP | - WM8962_HP1R_ENA_OUTP, - WM8962_HP1L_ENA_OUTP | - WM8962_HP1R_ENA_OUTP); - udelay(20); - - snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, - WM8962_HP1L_RMV_SHORT | - WM8962_HP1R_RMV_SHORT, - WM8962_HP1L_RMV_SHORT | - WM8962_HP1R_RMV_SHORT); - break; - - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, - WM8962_HP1L_RMV_SHORT | - WM8962_HP1R_RMV_SHORT, 0); - - udelay(20); - - snd_soc_update_bits(codec, WM8962_DC_SERVO_1, - WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA | - WM8962_HP1L_DCS_STARTUP | - WM8962_HP1R_DCS_STARTUP, - 0); - - snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0, - WM8962_HP1L_ENA | WM8962_HP1R_ENA | - WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY | - WM8962_HP1L_ENA_OUTP | - WM8962_HP1R_ENA_OUTP, 0); - - break; - - default: - BUG(); - return -EINVAL; - - } - - return 0; -} - -/* VU bits for the output PGAs only take effect while the PGA is powered */ -static int out_pga_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - int reg; - - switch (w->shift) { - case WM8962_HPOUTR_PGA_ENA_SHIFT: - reg = WM8962_HPOUTR_VOLUME; - break; - case WM8962_HPOUTL_PGA_ENA_SHIFT: - reg = WM8962_HPOUTL_VOLUME; - break; - case WM8962_SPKOUTR_PGA_ENA_SHIFT: - reg = WM8962_SPKOUTR_VOLUME; - break; - case WM8962_SPKOUTL_PGA_ENA_SHIFT: - reg = WM8962_SPKOUTL_VOLUME; - break; - default: - BUG(); - return -EINVAL; - } - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - return snd_soc_write(codec, reg, snd_soc_read(codec, reg)); - default: - BUG(); - return -EINVAL; - } -} - -static int dsp2_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - if (wm8962->dsp2_ena) - wm8962_dsp2_start(codec); - break; - - case SND_SOC_DAPM_PRE_PMD: - if (wm8962->dsp2_ena) - wm8962_dsp2_stop(codec); - break; - - default: - BUG(); - return -EINVAL; - } - - return 0; -} - -static const char *st_text[] = { "None", "Left", "Right" }; - -static const struct soc_enum str_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text); - -static const struct snd_kcontrol_new str_mux = - SOC_DAPM_ENUM("Right Sidetone", str_enum); - -static const struct soc_enum stl_enum = - SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text); - -static const struct snd_kcontrol_new stl_mux = - SOC_DAPM_ENUM("Left Sidetone", stl_enum); - -static const char *outmux_text[] = { "DAC", "Mixer" }; - -static const struct soc_enum spkoutr_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text); - -static const struct snd_kcontrol_new spkoutr_mux = - SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum); - -static const struct soc_enum spkoutl_enum = - SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text); - -static const struct snd_kcontrol_new spkoutl_mux = - SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum); - -static const struct soc_enum hpoutr_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text); - -static const struct snd_kcontrol_new hpoutr_mux = - SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum); - -static const struct soc_enum hpoutl_enum = - SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text); - -static const struct snd_kcontrol_new hpoutl_mux = - SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum); - -static const struct snd_kcontrol_new inpgal[] = { -SOC_DAPM_SINGLE("IN1L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 3, 1, 0), -SOC_DAPM_SINGLE("IN2L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 2, 1, 0), -SOC_DAPM_SINGLE("IN3L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 1, 1, 0), -SOC_DAPM_SINGLE("IN4L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new inpgar[] = { -SOC_DAPM_SINGLE("IN1R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 3, 1, 0), -SOC_DAPM_SINGLE("IN2R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 2, 1, 0), -SOC_DAPM_SINGLE("IN3R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 1, 1, 0), -SOC_DAPM_SINGLE("IN4R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new mixinl[] = { -SOC_DAPM_SINGLE("IN2L Switch", WM8962_INPUT_MIXER_CONTROL_2, 5, 1, 0), -SOC_DAPM_SINGLE("IN3L Switch", WM8962_INPUT_MIXER_CONTROL_2, 4, 1, 0), -SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 3, 1, 0), -}; - -static const struct snd_kcontrol_new mixinr[] = { -SOC_DAPM_SINGLE("IN2R Switch", WM8962_INPUT_MIXER_CONTROL_2, 2, 1, 0), -SOC_DAPM_SINGLE("IN3R Switch", WM8962_INPUT_MIXER_CONTROL_2, 1, 1, 0), -SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new hpmixl[] = { -SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_1, 5, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_1, 4, 1, 0), -SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_1, 3, 1, 0), -SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_1, 2, 1, 0), -SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_1, 1, 1, 0), -SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new hpmixr[] = { -SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_2, 5, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_2, 4, 1, 0), -SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_2, 3, 1, 0), -SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_2, 2, 1, 0), -SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_2, 1, 1, 0), -SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new spkmixl[] = { -SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_1, 5, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_1, 4, 1, 0), -SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_1, 3, 1, 0), -SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_1, 2, 1, 0), -SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_1, 1, 1, 0), -SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new spkmixr[] = { -SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_2, 5, 1, 0), -SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_2, 4, 1, 0), -SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_2, 3, 1, 0), -SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_2, 2, 1, 0), -SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_2, 1, 1, 0), -SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_2, 0, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8962_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1L"), -SND_SOC_DAPM_INPUT("IN1R"), -SND_SOC_DAPM_INPUT("IN2L"), -SND_SOC_DAPM_INPUT("IN2R"), -SND_SOC_DAPM_INPUT("IN3L"), -SND_SOC_DAPM_INPUT("IN3R"), -SND_SOC_DAPM_INPUT("IN4L"), -SND_SOC_DAPM_INPUT("IN4R"), -SND_SOC_DAPM_SIGGEN("Beep"), -SND_SOC_DAPM_INPUT("DMICDAT"), - -SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0), - -SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0), -SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, - SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT, - WM8962_DSP2_ENA_SHIFT, 0, dsp2_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_SUPPLY("TEMP_HP", WM8962_ADDITIONAL_CONTROL_4, 2, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("TEMP_SPK", WM8962_ADDITIONAL_CONTROL_4, 1, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, - inpgal, ARRAY_SIZE(inpgal)), -SND_SOC_DAPM_MIXER("INPGAR", WM8962_RIGHT_INPUT_PGA_CONTROL, 4, 0, - inpgar, ARRAY_SIZE(inpgar)), -SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0, - mixinl, ARRAY_SIZE(mixinl)), -SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0, - mixinr, ARRAY_SIZE(mixinr)), - -SND_SOC_DAPM_AIF_IN("DMIC_ENA", NULL, 0, WM8962_PWR_MGMT_1, 10, 0), - -SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0), -SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0), - -SND_SOC_DAPM_MUX("STL", SND_SOC_NOPM, 0, 0, &stl_mux), -SND_SOC_DAPM_MUX("STR", SND_SOC_NOPM, 0, 0, &str_mux), - -SND_SOC_DAPM_DAC("DACL", "Playback", WM8962_PWR_MGMT_2, 8, 0), -SND_SOC_DAPM_DAC("DACR", "Playback", WM8962_PWR_MGMT_2, 7, 0), - -SND_SOC_DAPM_PGA("Left Bypass", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Bypass", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("HPMIXL", WM8962_MIXER_ENABLES, 3, 0, - hpmixl, ARRAY_SIZE(hpmixl)), -SND_SOC_DAPM_MIXER("HPMIXR", WM8962_MIXER_ENABLES, 2, 0, - hpmixr, ARRAY_SIZE(hpmixr)), - -SND_SOC_DAPM_MUX_E("HPOUTL PGA", WM8962_PWR_MGMT_2, 6, 0, &hpoutl_mux, - out_pga_event, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_MUX_E("HPOUTR PGA", WM8962_PWR_MGMT_2, 5, 0, &hpoutr_mux, - out_pga_event, SND_SOC_DAPM_POST_PMU), - -SND_SOC_DAPM_PGA_E("HPOUT", SND_SOC_NOPM, 0, 0, NULL, 0, hp_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_OUTPUT("HPOUTL"), -SND_SOC_DAPM_OUTPUT("HPOUTR"), -}; - -static const struct snd_soc_dapm_widget wm8962_dapm_spk_mono_widgets[] = { -SND_SOC_DAPM_MIXER("Speaker Mixer", WM8962_MIXER_ENABLES, 1, 0, - spkmixl, ARRAY_SIZE(spkmixl)), -SND_SOC_DAPM_MUX_E("Speaker PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux, - out_pga_event, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA("Speaker Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0), -SND_SOC_DAPM_OUTPUT("SPKOUT"), -}; - -static const struct snd_soc_dapm_widget wm8962_dapm_spk_stereo_widgets[] = { -SND_SOC_DAPM_MIXER("SPKOUTL Mixer", WM8962_MIXER_ENABLES, 1, 0, - spkmixl, ARRAY_SIZE(spkmixl)), -SND_SOC_DAPM_MIXER("SPKOUTR Mixer", WM8962_MIXER_ENABLES, 0, 0, - spkmixr, ARRAY_SIZE(spkmixr)), - -SND_SOC_DAPM_MUX_E("SPKOUTL PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux, - out_pga_event, SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_MUX_E("SPKOUTR PGA", WM8962_PWR_MGMT_2, 3, 0, &spkoutr_mux, - out_pga_event, SND_SOC_DAPM_POST_PMU), - -SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0), - -SND_SOC_DAPM_OUTPUT("SPKOUTL"), -SND_SOC_DAPM_OUTPUT("SPKOUTR"), -}; - -static const struct snd_soc_dapm_route wm8962_intercon[] = { - { "INPGAL", "IN1L Switch", "IN1L" }, - { "INPGAL", "IN2L Switch", "IN2L" }, - { "INPGAL", "IN3L Switch", "IN3L" }, - { "INPGAL", "IN4L Switch", "IN4L" }, - - { "INPGAR", "IN1R Switch", "IN1R" }, - { "INPGAR", "IN2R Switch", "IN2R" }, - { "INPGAR", "IN3R Switch", "IN3R" }, - { "INPGAR", "IN4R Switch", "IN4R" }, - - { "MIXINL", "IN2L Switch", "IN2L" }, - { "MIXINL", "IN3L Switch", "IN3L" }, - { "MIXINL", "PGA Switch", "INPGAL" }, - - { "MIXINR", "IN2R Switch", "IN2R" }, - { "MIXINR", "IN3R Switch", "IN3R" }, - { "MIXINR", "PGA Switch", "INPGAR" }, - - { "MICBIAS", NULL, "SYSCLK" }, - - { "DMIC_ENA", NULL, "DMICDAT" }, - - { "ADCL", NULL, "SYSCLK" }, - { "ADCL", NULL, "TOCLK" }, - { "ADCL", NULL, "MIXINL" }, - { "ADCL", NULL, "DMIC_ENA" }, - { "ADCL", NULL, "DSP2" }, - - { "ADCR", NULL, "SYSCLK" }, - { "ADCR", NULL, "TOCLK" }, - { "ADCR", NULL, "MIXINR" }, - { "ADCR", NULL, "DMIC_ENA" }, - { "ADCR", NULL, "DSP2" }, - - { "STL", "Left", "ADCL" }, - { "STL", "Right", "ADCR" }, - { "STL", NULL, "Class G" }, - - { "STR", "Left", "ADCL" }, - { "STR", "Right", "ADCR" }, - { "STR", NULL, "Class G" }, - - { "DACL", NULL, "SYSCLK" }, - { "DACL", NULL, "TOCLK" }, - { "DACL", NULL, "Beep" }, - { "DACL", NULL, "STL" }, - { "DACL", NULL, "DSP2" }, - - { "DACR", NULL, "SYSCLK" }, - { "DACR", NULL, "TOCLK" }, - { "DACR", NULL, "Beep" }, - { "DACR", NULL, "STR" }, - { "DACR", NULL, "DSP2" }, - - { "HPMIXL", "IN4L Switch", "IN4L" }, - { "HPMIXL", "IN4R Switch", "IN4R" }, - { "HPMIXL", "DACL Switch", "DACL" }, - { "HPMIXL", "DACR Switch", "DACR" }, - { "HPMIXL", "MIXINL Switch", "MIXINL" }, - { "HPMIXL", "MIXINR Switch", "MIXINR" }, - - { "HPMIXR", "IN4L Switch", "IN4L" }, - { "HPMIXR", "IN4R Switch", "IN4R" }, - { "HPMIXR", "DACL Switch", "DACL" }, - { "HPMIXR", "DACR Switch", "DACR" }, - { "HPMIXR", "MIXINL Switch", "MIXINL" }, - { "HPMIXR", "MIXINR Switch", "MIXINR" }, - - { "Left Bypass", NULL, "HPMIXL" }, - { "Left Bypass", NULL, "Class G" }, - - { "Right Bypass", NULL, "HPMIXR" }, - { "Right Bypass", NULL, "Class G" }, - - { "HPOUTL PGA", "Mixer", "Left Bypass" }, - { "HPOUTL PGA", "DAC", "DACL" }, - - { "HPOUTR PGA", "Mixer", "Right Bypass" }, - { "HPOUTR PGA", "DAC", "DACR" }, - - { "HPOUT", NULL, "HPOUTL PGA" }, - { "HPOUT", NULL, "HPOUTR PGA" }, - { "HPOUT", NULL, "Charge Pump" }, - { "HPOUT", NULL, "SYSCLK" }, - { "HPOUT", NULL, "TOCLK" }, - - { "HPOUTL", NULL, "HPOUT" }, - { "HPOUTR", NULL, "HPOUT" }, - - { "HPOUTL", NULL, "TEMP_HP" }, - { "HPOUTR", NULL, "TEMP_HP" }, -}; - -static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = { - { "Speaker Mixer", "IN4L Switch", "IN4L" }, - { "Speaker Mixer", "IN4R Switch", "IN4R" }, - { "Speaker Mixer", "DACL Switch", "DACL" }, - { "Speaker Mixer", "DACR Switch", "DACR" }, - { "Speaker Mixer", "MIXINL Switch", "MIXINL" }, - { "Speaker Mixer", "MIXINR Switch", "MIXINR" }, - - { "Speaker PGA", "Mixer", "Speaker Mixer" }, - { "Speaker PGA", "DAC", "DACL" }, - - { "Speaker Output", NULL, "Speaker PGA" }, - { "Speaker Output", NULL, "SYSCLK" }, - { "Speaker Output", NULL, "TOCLK" }, - { "Speaker Output", NULL, "TEMP_SPK" }, - - { "SPKOUT", NULL, "Speaker Output" }, -}; - -static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = { - { "SPKOUTL Mixer", "IN4L Switch", "IN4L" }, - { "SPKOUTL Mixer", "IN4R Switch", "IN4R" }, - { "SPKOUTL Mixer", "DACL Switch", "DACL" }, - { "SPKOUTL Mixer", "DACR Switch", "DACR" }, - { "SPKOUTL Mixer", "MIXINL Switch", "MIXINL" }, - { "SPKOUTL Mixer", "MIXINR Switch", "MIXINR" }, - - { "SPKOUTR Mixer", "IN4L Switch", "IN4L" }, - { "SPKOUTR Mixer", "IN4R Switch", "IN4R" }, - { "SPKOUTR Mixer", "DACL Switch", "DACL" }, - { "SPKOUTR Mixer", "DACR Switch", "DACR" }, - { "SPKOUTR Mixer", "MIXINL Switch", "MIXINL" }, - { "SPKOUTR Mixer", "MIXINR Switch", "MIXINR" }, - - { "SPKOUTL PGA", "Mixer", "SPKOUTL Mixer" }, - { "SPKOUTL PGA", "DAC", "DACL" }, - - { "SPKOUTR PGA", "Mixer", "SPKOUTR Mixer" }, - { "SPKOUTR PGA", "DAC", "DACR" }, - - { "SPKOUTL Output", NULL, "SPKOUTL PGA" }, - { "SPKOUTL Output", NULL, "SYSCLK" }, - { "SPKOUTL Output", NULL, "TOCLK" }, - { "SPKOUTL Output", NULL, "TEMP_SPK" }, - - { "SPKOUTR Output", NULL, "SPKOUTR PGA" }, - { "SPKOUTR Output", NULL, "SYSCLK" }, - { "SPKOUTR Output", NULL, "TOCLK" }, - { "SPKOUTR Output", NULL, "TEMP_SPK" }, - - { "SPKOUTL", NULL, "SPKOUTL Output" }, - { "SPKOUTR", NULL, "SPKOUTR Output" }, -}; - -static int wm8962_add_widgets(struct snd_soc_codec *codec) -{ - struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_add_codec_controls(codec, wm8962_snd_controls, - ARRAY_SIZE(wm8962_snd_controls)); - if (pdata && pdata->spk_mono) - snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls, - ARRAY_SIZE(wm8962_spk_mono_controls)); - else - snd_soc_add_codec_controls(codec, wm8962_spk_stereo_controls, - ARRAY_SIZE(wm8962_spk_stereo_controls)); - - - snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets, - ARRAY_SIZE(wm8962_dapm_widgets)); - if (pdata && pdata->spk_mono) - snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets, - ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); - else - snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_stereo_widgets, - ARRAY_SIZE(wm8962_dapm_spk_stereo_widgets)); - - snd_soc_dapm_add_routes(dapm, wm8962_intercon, - ARRAY_SIZE(wm8962_intercon)); - if (pdata && pdata->spk_mono) - snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon, - ARRAY_SIZE(wm8962_spk_mono_intercon)); - else - snd_soc_dapm_add_routes(dapm, wm8962_spk_stereo_intercon, - ARRAY_SIZE(wm8962_spk_stereo_intercon)); - - - snd_soc_dapm_disable_pin(dapm, "Beep"); - - return 0; -} - -/* -1 for reserved values */ -static const int bclk_divs[] = { - 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32 -}; - -static const int sysclk_rates[] = { - 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, 3072, 6144 -}; - -static void wm8962_configure_bclk(struct snd_soc_codec *codec) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int dspclk, i; - int clocking2 = 0; - int clocking4 = 0; - int aif2 = 0; - - if (!wm8962->sysclk_rate) { - dev_dbg(codec->dev, "No SYSCLK configured\n"); - return; - } - - if (!wm8962->bclk || !wm8962->lrclk) { - dev_dbg(codec->dev, "No audio clocks configured\n"); - return; - } - - for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) { - if (sysclk_rates[i] == wm8962->sysclk_rate / wm8962->lrclk) { - clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT; - break; - } - } - - if (i == ARRAY_SIZE(sysclk_rates)) { - dev_err(codec->dev, "Unsupported sysclk ratio %d\n", - wm8962->sysclk_rate / wm8962->lrclk); - return; - } - - dev_dbg(codec->dev, "Selected sysclk ratio %d\n", sysclk_rates[i]); - - snd_soc_update_bits(codec, WM8962_CLOCKING_4, - WM8962_SYSCLK_RATE_MASK, clocking4); - - dspclk = snd_soc_read(codec, WM8962_CLOCKING1); - if (dspclk < 0) { - dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk); - return; - } - - dspclk = (dspclk & WM8962_DSPCLK_DIV_MASK) >> WM8962_DSPCLK_DIV_SHIFT; - switch (dspclk) { - case 0: - dspclk = wm8962->sysclk_rate; - break; - case 1: - dspclk = wm8962->sysclk_rate / 2; - break; - case 2: - dspclk = wm8962->sysclk_rate / 4; - break; - default: - dev_warn(codec->dev, "Unknown DSPCLK divisor read back\n"); - dspclk = wm8962->sysclk; - } - - dev_dbg(codec->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk); - - /* We're expecting an exact match */ - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - if (bclk_divs[i] < 0) - continue; - - if (dspclk / bclk_divs[i] == wm8962->bclk) { - dev_dbg(codec->dev, "Selected BCLK_DIV %d for %dHz\n", - bclk_divs[i], wm8962->bclk); - clocking2 |= i; - break; - } - } - if (i == ARRAY_SIZE(bclk_divs)) { - dev_err(codec->dev, "Unsupported BCLK ratio %d\n", - dspclk / wm8962->bclk); - return; - } - - aif2 |= wm8962->bclk / wm8962->lrclk; - dev_dbg(codec->dev, "Selected LRCLK divisor %d for %dHz\n", - wm8962->bclk / wm8962->lrclk, wm8962->lrclk); - - snd_soc_update_bits(codec, WM8962_CLOCKING2, - WM8962_BCLK_DIV_MASK, clocking2); - snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_2, - WM8962_AIF_RATE_MASK, aif2); -} - -static int wm8962_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - if (level == codec->dapm.bias_level) - return 0; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID 2*50k */ - snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, - WM8962_VMID_SEL_MASK, 0x80); - - wm8962_configure_bclk(codec); - break; - - case SND_SOC_BIAS_STANDBY: - /* VMID 2*250k */ - snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, - WM8962_VMID_SEL_MASK, 0x100); - break; - - case SND_SOC_BIAS_OFF: - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -static const struct { - int rate; - int reg; -} sr_vals[] = { - { 48000, 0 }, - { 44100, 0 }, - { 32000, 1 }, - { 22050, 2 }, - { 24000, 2 }, - { 16000, 3 }, - { 11025, 4 }, - { 12000, 4 }, - { 8000, 5 }, - { 88200, 6 }, - { 96000, 6 }, -}; - -static int wm8962_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int i; - int aif0 = 0; - int adctl3 = 0; - - wm8962->bclk = snd_soc_params_to_bclk(params); - if (params_channels(params) == 1) - wm8962->bclk *= 2; - - wm8962->lrclk = params_rate(params); - - for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { - if (sr_vals[i].rate == wm8962->lrclk) { - adctl3 |= sr_vals[i].reg; - break; - } - } - if (i == ARRAY_SIZE(sr_vals)) { - dev_err(codec->dev, "Unsupported rate %dHz\n", wm8962->lrclk); - return -EINVAL; - } - - if (wm8962->lrclk % 8000 == 0) - adctl3 |= WM8962_SAMPLE_RATE_INT_MODE; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - aif0 |= 0x4; - break; - case SNDRV_PCM_FORMAT_S24_LE: - aif0 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S32_LE: - aif0 |= 0xc; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0, - WM8962_WL_MASK, aif0); - snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3, - WM8962_SAMPLE_RATE_INT_MODE | - WM8962_SAMPLE_RATE_MASK, adctl3); - - if (codec->dapm.bias_level == SND_SOC_BIAS_ON) - wm8962_configure_bclk(codec); - - return 0; -} - -static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int src; - - switch (clk_id) { - case WM8962_SYSCLK_MCLK: - wm8962->sysclk = WM8962_SYSCLK_MCLK; - src = 0; - break; - case WM8962_SYSCLK_FLL: - wm8962->sysclk = WM8962_SYSCLK_FLL; - src = 1 << WM8962_SYSCLK_SRC_SHIFT; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_SRC_MASK, - src); - - wm8962->sysclk_rate = freq; - - wm8962_configure_bclk(codec); - - return 0; -} - -static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - int aif0 = 0; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif0 |= WM8962_LRCLK_INV | 3; - case SND_SOC_DAIFMT_DSP_A: - aif0 |= 3; - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - case SND_SOC_DAIFMT_IB_NF: - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif0 |= 1; - break; - case SND_SOC_DAIFMT_I2S: - aif0 |= 2; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif0 |= WM8962_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif0 |= WM8962_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_IF: - aif0 |= WM8962_BCLK_INV | WM8962_LRCLK_INV; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - aif0 |= WM8962_MSTR; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0, - WM8962_FMT_MASK | WM8962_BCLK_INV | WM8962_MSTR | - WM8962_LRCLK_INV, aif0); - - return 0; -} - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_refclk_div; - u16 n; - u16 theta; - u16 lambda; -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - unsigned int target; - unsigned int div; - unsigned int fratio, gcd_fll; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - fll_div->fll_refclk_div = 0; - while ((Fref / div) > 13500000) { - div *= 2; - fll_div->fll_refclk_div++; - - if (div > 4) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - - pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 2; - while (Fout * div < 90000000) { - div++; - if (div > 64) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - target = Fout * div; - fll_div->fll_outdiv = div - 1; - - pr_debug("FLL Fvco=%dHz\n", target); - - /* Find an appropriate FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - fratio = fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - fll_div->n = target / (fratio * Fref); - - if (target % Fref == 0) { - fll_div->theta = 0; - fll_div->lambda = 0; - } else { - gcd_fll = gcd(target, fratio * Fref); - - fll_div->theta = (target - (fll_div->n * fratio * Fref)) - / gcd_fll; - fll_div->lambda = (fratio * Fref) / gcd_fll; - } - - pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n", - fll_div->n, fll_div->theta, fll_div->lambda); - pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n", - fll_div->fll_fratio, fll_div->fll_outdiv, - fll_div->fll_refclk_div); - - return 0; -} - -static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source, - unsigned int Fref, unsigned int Fout) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - struct _fll_div fll_div; - unsigned long timeout; - int ret; - int fll1 = 0; - - /* Any change? */ - if (source == wm8962->fll_src && Fref == wm8962->fll_fref && - Fout == wm8962->fll_fout) - return 0; - - if (Fout == 0) { - dev_dbg(codec->dev, "FLL disabled\n"); - - wm8962->fll_fref = 0; - wm8962->fll_fout = 0; - - snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, - WM8962_FLL_ENA, 0); - - pm_runtime_put(codec->dev); - - return 0; - } - - ret = fll_factors(&fll_div, Fref, Fout); - if (ret != 0) - return ret; - - /* Parameters good, disable so we can reprogram */ - snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0); - - switch (fll_id) { - case WM8962_FLL_MCLK: - case WM8962_FLL_BCLK: - case WM8962_FLL_OSC: - fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT; - break; - case WM8962_FLL_INT: - snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, - WM8962_FLL_OSC_ENA, WM8962_FLL_OSC_ENA); - snd_soc_update_bits(codec, WM8962_FLL_CONTROL_5, - WM8962_FLL_FRC_NCO, WM8962_FLL_FRC_NCO); - break; - default: - dev_err(codec->dev, "Unknown FLL source %d\n", ret); - return -EINVAL; - } - - if (fll_div.theta || fll_div.lambda) - fll1 |= WM8962_FLL_FRAC; - - /* Stop the FLL while we reconfigure */ - snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0); - - snd_soc_update_bits(codec, WM8962_FLL_CONTROL_2, - WM8962_FLL_OUTDIV_MASK | - WM8962_FLL_REFCLK_DIV_MASK, - (fll_div.fll_outdiv << WM8962_FLL_OUTDIV_SHIFT) | - (fll_div.fll_refclk_div)); - - snd_soc_update_bits(codec, WM8962_FLL_CONTROL_3, - WM8962_FLL_FRATIO_MASK, fll_div.fll_fratio); - - snd_soc_write(codec, WM8962_FLL_CONTROL_6, fll_div.theta); - snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda); - snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n); - - try_wait_for_completion(&wm8962->fll_lock); - - pm_runtime_get_sync(codec->dev); - - snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, - WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK | - WM8962_FLL_ENA, fll1 | WM8962_FLL_ENA); - - dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); - - ret = 0; - - if (fll1 & WM8962_FLL_ENA) { - /* This should be a massive overestimate but go even - * higher if we'll error out - */ - if (wm8962->irq) - timeout = msecs_to_jiffies(5); - else - timeout = msecs_to_jiffies(1); - - timeout = wait_for_completion_timeout(&wm8962->fll_lock, - timeout); - - if (timeout == 0 && wm8962->irq) { - dev_err(codec->dev, "FLL lock timed out"); - ret = -ETIMEDOUT; - } - } - - wm8962->fll_fref = Fref; - wm8962->fll_fout = Fout; - wm8962->fll_src = source; - - return ret; -} - -static int wm8962_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - int val; - - if (mute) - val = WM8962_DAC_MUTE; - else - val = 0; - - return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, - WM8962_DAC_MUTE, val); -} - -#define WM8962_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8962_dai_ops = { - .hw_params = wm8962_hw_params, - .set_sysclk = wm8962_set_dai_sysclk, - .set_fmt = wm8962_set_dai_fmt, - .digital_mute = wm8962_mute, -}; - -static struct snd_soc_dai_driver wm8962_dai = { - .name = "wm8962", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8962_RATES, - .formats = WM8962_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8962_RATES, - .formats = WM8962_FORMATS, - }, - .ops = &wm8962_dai_ops, - .symmetric_rates = 1, -}; - -static void wm8962_mic_work(struct work_struct *work) -{ - struct wm8962_priv *wm8962 = container_of(work, - struct wm8962_priv, - mic_work.work); - struct snd_soc_codec *codec = wm8962->codec; - int status = 0; - int irq_pol = 0; - int reg; - - reg = snd_soc_read(codec, WM8962_ADDITIONAL_CONTROL_4); - - if (reg & WM8962_MICDET_STS) { - status |= SND_JACK_MICROPHONE; - irq_pol |= WM8962_MICD_IRQ_POL; - } - - if (reg & WM8962_MICSHORT_STS) { - status |= SND_JACK_BTN_0; - irq_pol |= WM8962_MICSCD_IRQ_POL; - } - - snd_soc_jack_report(wm8962->jack, status, - SND_JACK_MICROPHONE | SND_JACK_BTN_0); - - snd_soc_update_bits(codec, WM8962_MICINT_SOURCE_POL, - WM8962_MICSCD_IRQ_POL | - WM8962_MICD_IRQ_POL, irq_pol); -} - -static irqreturn_t wm8962_irq(int irq, void *data) -{ - struct device *dev = data; - struct wm8962_priv *wm8962 = dev_get_drvdata(dev); - unsigned int mask; - unsigned int active; - int reg, ret; - - ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK, - &mask); - if (ret != 0) { - dev_err(dev, "Failed to read interrupt mask: %d\n", - ret); - return IRQ_NONE; - } - - ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active); - if (ret != 0) { - dev_err(dev, "Failed to read interrupt: %d\n", ret); - return IRQ_NONE; - } - - active &= ~mask; - - if (!active) - return IRQ_NONE; - - /* Acknowledge the interrupts */ - ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active); - if (ret != 0) - dev_warn(dev, "Failed to ack interrupt: %d\n", ret); - - if (active & WM8962_FLL_LOCK_EINT) { - dev_dbg(dev, "FLL locked\n"); - complete(&wm8962->fll_lock); - } - - if (active & WM8962_FIFOS_ERR_EINT) - dev_err(dev, "FIFO error\n"); - - if (active & WM8962_TEMP_SHUT_EINT) { - dev_crit(dev, "Thermal shutdown\n"); - - ret = regmap_read(wm8962->regmap, - WM8962_THERMAL_SHUTDOWN_STATUS, ®); - if (ret != 0) { - dev_warn(dev, "Failed to read thermal status: %d\n", - ret); - reg = 0; - } - - if (reg & WM8962_TEMP_ERR_HP) - dev_crit(dev, "Headphone thermal error\n"); - if (reg & WM8962_TEMP_WARN_HP) - dev_crit(dev, "Headphone thermal warning\n"); - if (reg & WM8962_TEMP_ERR_SPK) - dev_crit(dev, "Speaker thermal error\n"); - if (reg & WM8962_TEMP_WARN_SPK) - dev_crit(dev, "Speaker thermal warning\n"); - } - - if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { - dev_dbg(dev, "Microphone event detected\n"); - -#ifndef CONFIG_SND_SOC_WM8962_MODULE - trace_snd_soc_jack_irq(dev_name(dev)); -#endif - - pm_wakeup_event(dev, 300); - - schedule_delayed_work(&wm8962->mic_work, - msecs_to_jiffies(250)); - } - - return IRQ_HANDLED; -} - -/** - * wm8962_mic_detect - Enable microphone detection via the WM8962 IRQ - * - * @codec: WM8962 codec - * @jack: jack to report detection events on - * - * Enable microphone detection via IRQ on the WM8962. If GPIOs are - * being used to bring out signals to the processor then only platform - * data configuration is needed for WM8962 and processor GPIOs should - * be configured using snd_soc_jack_add_gpios() instead. - * - * If no jack is supplied detection will be disabled. - */ -int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int irq_mask, enable; - - wm8962->jack = jack; - if (jack) { - irq_mask = 0; - enable = WM8962_MICDET_ENA; - } else { - irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT; - enable = 0; - } - - snd_soc_update_bits(codec, WM8962_INTERRUPT_STATUS_2_MASK, - WM8962_MICD_EINT | WM8962_MICSCD_EINT, irq_mask); - snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, - WM8962_MICDET_ENA, enable); - - /* Send an initial empty report */ - snd_soc_jack_report(wm8962->jack, 0, - SND_JACK_MICROPHONE | SND_JACK_BTN_0); - - if (jack) { - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS"); - } else { - snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK"); - snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS"); - } - - return 0; -} -EXPORT_SYMBOL_GPL(wm8962_mic_detect); - -#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) -static int beep_rates[] = { - 500, 1000, 2000, 4000, -}; - -static void wm8962_beep_work(struct work_struct *work) -{ - struct wm8962_priv *wm8962 = - container_of(work, struct wm8962_priv, beep_work); - struct snd_soc_codec *codec = wm8962->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int i; - int reg = 0; - int best = 0; - - if (wm8962->beep_rate) { - for (i = 0; i < ARRAY_SIZE(beep_rates); i++) { - if (abs(wm8962->beep_rate - beep_rates[i]) < - abs(wm8962->beep_rate - beep_rates[best])) - best = i; - } - - dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n", - beep_rates[best], wm8962->beep_rate); - - reg = WM8962_BEEP_ENA | (best << WM8962_BEEP_RATE_SHIFT); - - snd_soc_dapm_enable_pin(dapm, "Beep"); - } else { - dev_dbg(codec->dev, "Disabling beep\n"); - snd_soc_dapm_disable_pin(dapm, "Beep"); - } - - snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1, - WM8962_BEEP_ENA | WM8962_BEEP_RATE_MASK, reg); - - snd_soc_dapm_sync(dapm); -} - -/* For usability define a way of injecting beep events for the device - - * many systems will not have a keyboard. - */ -static int wm8962_beep_event(struct input_dev *dev, unsigned int type, - unsigned int code, int hz) -{ - struct snd_soc_codec *codec = input_get_drvdata(dev); - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - - dev_dbg(codec->dev, "Beep event %x %x\n", code, hz); - - switch (code) { - case SND_BELL: - if (hz) - hz = 1000; - case SND_TONE: - break; - default: - return -1; - } - - /* Kick the beep from a workqueue */ - wm8962->beep_rate = hz; - schedule_work(&wm8962->beep_work); - return 0; -} - -static ssize_t wm8962_beep_set(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct wm8962_priv *wm8962 = dev_get_drvdata(dev); - long int time; - int ret; - - ret = strict_strtol(buf, 10, &time); - if (ret != 0) - return ret; - - input_event(wm8962->beep, EV_SND, SND_TONE, time); - - return count; -} - -static DEVICE_ATTR(beep, 0200, NULL, wm8962_beep_set); - -static void wm8962_init_beep(struct snd_soc_codec *codec) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int ret; - - wm8962->beep = input_allocate_device(); - if (!wm8962->beep) { - dev_err(codec->dev, "Failed to allocate beep device\n"); - return; - } - - INIT_WORK(&wm8962->beep_work, wm8962_beep_work); - wm8962->beep_rate = 0; - - wm8962->beep->name = "WM8962 Beep Generator"; - wm8962->beep->phys = dev_name(codec->dev); - wm8962->beep->id.bustype = BUS_I2C; - - wm8962->beep->evbit[0] = BIT_MASK(EV_SND); - wm8962->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); - wm8962->beep->event = wm8962_beep_event; - wm8962->beep->dev.parent = codec->dev; - input_set_drvdata(wm8962->beep, codec); - - ret = input_register_device(wm8962->beep); - if (ret != 0) { - input_free_device(wm8962->beep); - wm8962->beep = NULL; - dev_err(codec->dev, "Failed to register beep device\n"); - } - - ret = device_create_file(codec->dev, &dev_attr_beep); - if (ret != 0) { - dev_err(codec->dev, "Failed to create keyclick file: %d\n", - ret); - } -} - -static void wm8962_free_beep(struct snd_soc_codec *codec) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - - device_remove_file(codec->dev, &dev_attr_beep); - input_unregister_device(wm8962->beep); - cancel_work_sync(&wm8962->beep_work); - wm8962->beep = NULL; - - snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1, WM8962_BEEP_ENA,0); -} -#else -static void wm8962_init_beep(struct snd_soc_codec *codec) -{ -} - -static void wm8962_free_beep(struct snd_soc_codec *codec) -{ -} -#endif - -static void wm8962_set_gpio_mode(struct snd_soc_codec *codec, int gpio) -{ - int mask = 0; - int val = 0; - - /* Some of the GPIOs are behind MFP configuration and need to - * be put into GPIO mode. */ - switch (gpio) { - case 2: - mask = WM8962_CLKOUT2_SEL_MASK; - val = 1 << WM8962_CLKOUT2_SEL_SHIFT; - break; - case 3: - mask = WM8962_CLKOUT3_SEL_MASK; - val = 1 << WM8962_CLKOUT3_SEL_SHIFT; - break; - default: - break; - } - - if (mask) - snd_soc_update_bits(codec, WM8962_ANALOGUE_CLOCKING1, - mask, val); -} - -#ifdef CONFIG_GPIOLIB -static inline struct wm8962_priv *gpio_to_wm8962(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8962_priv, gpio_chip); -} - -static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); - struct snd_soc_codec *codec = wm8962->codec; - - /* The WM8962 GPIOs aren't linearly numbered. For simplicity - * we export linear numbers and error out if the unsupported - * ones are requsted. - */ - switch (offset + 1) { - case 2: - case 3: - case 5: - case 6: - break; - default: - return -EINVAL; - } - - wm8962_set_gpio_mode(codec, offset + 1); - - return 0; -} - -static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); - struct snd_soc_codec *codec = wm8962->codec; - - snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset, - WM8962_GP2_LVL, !!value << WM8962_GP2_LVL_SHIFT); -} - -static int wm8962_gpio_direction_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct wm8962_priv *wm8962 = gpio_to_wm8962(chip); - struct snd_soc_codec *codec = wm8962->codec; - int ret, val; - - /* Force function 1 (logic output) */ - val = (1 << WM8962_GP2_FN_SHIFT) | (value << WM8962_GP2_LVL_SHIFT); - - ret = snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset, - WM8962_GP2_FN_MASK | WM8962_GP2_LVL, val); - if (ret < 0) - return ret; - - return 0; -} - -static struct gpio_chip wm8962_template_chip = { - .label = "wm8962", - .owner = THIS_MODULE, - .request = wm8962_gpio_request, - .direction_output = wm8962_gpio_direction_out, - .set = wm8962_gpio_set, - .can_sleep = 1, -}; - -static void wm8962_init_gpio(struct snd_soc_codec *codec) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); - int ret; - - wm8962->gpio_chip = wm8962_template_chip; - wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO; - wm8962->gpio_chip.dev = codec->dev; - - if (pdata && pdata->gpio_base) - wm8962->gpio_chip.base = pdata->gpio_base; - else - wm8962->gpio_chip.base = -1; - - ret = gpiochip_add(&wm8962->gpio_chip); - if (ret != 0) - dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); -} - -static void wm8962_free_gpio(struct snd_soc_codec *codec) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = gpiochip_remove(&wm8962->gpio_chip); - if (ret != 0) - dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); -} -#else -static void wm8962_init_gpio(struct snd_soc_codec *codec) -{ -} - -static void wm8962_free_gpio(struct snd_soc_codec *codec) -{ -} -#endif - -static int wm8962_probe(struct snd_soc_codec *codec) -{ - int ret; - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); - u16 *reg_cache = codec->reg_cache; - int i, trigger, irq_pol; - bool dmicclk, dmicdat; - - wm8962->codec = codec; - codec->control_data = wm8962->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0; - wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1; - wm8962->disable_nb[2].notifier_call = wm8962_regulator_event_2; - wm8962->disable_nb[3].notifier_call = wm8962_regulator_event_3; - wm8962->disable_nb[4].notifier_call = wm8962_regulator_event_4; - wm8962->disable_nb[5].notifier_call = wm8962_regulator_event_5; - wm8962->disable_nb[6].notifier_call = wm8962_regulator_event_6; - wm8962->disable_nb[7].notifier_call = wm8962_regulator_event_7; - - /* This should really be moved into the regulator core */ - for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) { - ret = regulator_register_notifier(wm8962->supplies[i].consumer, - &wm8962->disable_nb[i]); - if (ret != 0) { - dev_err(codec->dev, - "Failed to register regulator notifier: %d\n", - ret); - } - } - - /* SYSCLK defaults to on; make sure it is off so we can safely - * write to registers if the device is declocked. - */ - snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0); - - /* Ensure we have soft control over all registers */ - snd_soc_update_bits(codec, WM8962_CLOCKING2, - WM8962_CLKREG_OVD, WM8962_CLKREG_OVD); - - /* Ensure that the oscillator and PLLs are disabled */ - snd_soc_update_bits(codec, WM8962_PLL2, - WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, - 0); - - if (pdata) { - /* Apply static configuration for GPIOs */ - for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) - if (pdata->gpio_init[i]) { - wm8962_set_gpio_mode(codec, i + 1); - snd_soc_write(codec, 0x200 + i, - pdata->gpio_init[i] & 0xffff); - } - - /* Put the speakers into mono mode? */ - if (pdata->spk_mono) - reg_cache[WM8962_CLASS_D_CONTROL_2] - |= WM8962_SPK_MONO; - - /* Micbias setup, detection enable and detection - * threasholds. */ - if (pdata->mic_cfg) - snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, - WM8962_MICDET_ENA | - WM8962_MICDET_THR_MASK | - WM8962_MICSHORT_THR_MASK | - WM8962_MICBIAS_LVL, - pdata->mic_cfg); - } - - /* Latch volume update bits */ - snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, - WM8962_IN_VU, WM8962_IN_VU); - snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_VOLUME, - WM8962_IN_VU, WM8962_IN_VU); - snd_soc_update_bits(codec, WM8962_LEFT_ADC_VOLUME, - WM8962_ADC_VU, WM8962_ADC_VU); - snd_soc_update_bits(codec, WM8962_RIGHT_ADC_VOLUME, - WM8962_ADC_VU, WM8962_ADC_VU); - snd_soc_update_bits(codec, WM8962_LEFT_DAC_VOLUME, - WM8962_DAC_VU, WM8962_DAC_VU); - snd_soc_update_bits(codec, WM8962_RIGHT_DAC_VOLUME, - WM8962_DAC_VU, WM8962_DAC_VU); - snd_soc_update_bits(codec, WM8962_SPKOUTL_VOLUME, - WM8962_SPKOUT_VU, WM8962_SPKOUT_VU); - snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME, - WM8962_SPKOUT_VU, WM8962_SPKOUT_VU); - snd_soc_update_bits(codec, WM8962_HPOUTL_VOLUME, - WM8962_HPOUT_VU, WM8962_HPOUT_VU); - snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME, - WM8962_HPOUT_VU, WM8962_HPOUT_VU); - - /* Stereo control for EQ */ - snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0); - - /* Don't debouce interrupts so we don't need SYSCLK */ - snd_soc_update_bits(codec, WM8962_IRQ_DEBOUNCE, - WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB | - WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB, - 0); - - wm8962_add_widgets(codec); - - /* Save boards having to disable DMIC when not in use */ - dmicclk = false; - dmicdat = false; - for (i = 0; i < WM8962_MAX_GPIO; i++) { - switch (snd_soc_read(codec, WM8962_GPIO_BASE + i) - & WM8962_GP2_FN_MASK) { - case WM8962_GPIO_FN_DMICCLK: - dmicclk = true; - break; - case WM8962_GPIO_FN_DMICDAT: - dmicdat = true; - break; - default: - break; - } - } - if (!dmicclk || !dmicdat) { - dev_dbg(codec->dev, "DMIC not in use, disabling\n"); - snd_soc_dapm_nc_pin(&codec->dapm, "DMICDAT"); - } - if (dmicclk != dmicdat) - dev_warn(codec->dev, "DMIC GPIOs partially configured\n"); - - wm8962_init_beep(codec); - wm8962_init_gpio(codec); - - if (wm8962->irq) { - if (pdata && pdata->irq_active_low) { - trigger = IRQF_TRIGGER_LOW; - irq_pol = WM8962_IRQ_POL; - } else { - trigger = IRQF_TRIGGER_HIGH; - irq_pol = 0; - } - - snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL, - WM8962_IRQ_POL, irq_pol); - - ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq, - trigger | IRQF_ONESHOT, - "wm8962", codec->dev); - if (ret != 0) { - dev_err(codec->dev, "Failed to request IRQ %d: %d\n", - wm8962->irq, ret); - wm8962->irq = 0; - /* Non-fatal */ - } else { - /* Enable some IRQs by default */ - snd_soc_update_bits(codec, - WM8962_INTERRUPT_STATUS_2_MASK, - WM8962_FLL_LOCK_EINT | - WM8962_TEMP_SHUT_EINT | - WM8962_FIFOS_ERR_EINT, 0); - } - } - - return 0; -} - -static int wm8962_remove(struct snd_soc_codec *codec) -{ - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int i; - - if (wm8962->irq) - free_irq(wm8962->irq, codec); - - cancel_delayed_work_sync(&wm8962->mic_work); - - wm8962_free_gpio(codec); - wm8962_free_beep(codec); - for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) - regulator_unregister_notifier(wm8962->supplies[i].consumer, - &wm8962->disable_nb[i]); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { - .probe = wm8962_probe, - .remove = wm8962_remove, - .set_bias_level = wm8962_set_bias_level, - .set_pll = wm8962_set_fll, - .idle_bias_off = true, -}; - -/* Improve power consumption for IN4 DC measurement mode */ -static const struct reg_default wm8962_dc_measure[] = { - { 0xfd, 0x1 }, - { 0xcc, 0x40 }, - { 0xfd, 0 }, -}; - -static const struct regmap_config wm8962_regmap = { - .reg_bits = 16, - .val_bits = 16, - - .max_register = WM8962_MAX_REGISTER, - .reg_defaults = wm8962_reg, - .num_reg_defaults = ARRAY_SIZE(wm8962_reg), - .volatile_reg = wm8962_volatile_register, - .readable_reg = wm8962_readable_register, - .cache_type = REGCACHE_RBTREE, -}; - -static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev); - struct wm8962_priv *wm8962; - unsigned int reg; - int ret, i; - - wm8962 = devm_kzalloc(&i2c->dev, sizeof(struct wm8962_priv), - GFP_KERNEL); - if (wm8962 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8962); - - INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work); - init_completion(&wm8962->fll_lock); - wm8962->irq = i2c->irq; - - for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) - wm8962->supplies[i].supply = wm8962_supply_names[i]; - - ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies), - wm8962->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), - wm8962->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - wm8962->regmap = regmap_init_i2c(i2c, &wm8962_regmap); - if (IS_ERR(wm8962->regmap)) { - ret = PTR_ERR(wm8962->regmap); - dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); - goto err_enable; - } - - /* - * We haven't marked the chip revision as volatile due to - * sharing a register with the right input volume; explicitly - * bypass the cache to read it. - */ - regcache_cache_bypass(wm8962->regmap, true); - - ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, ®); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to read ID register\n"); - goto err_regmap; - } - if (reg != 0x6243) { - dev_err(&i2c->dev, - "Device is not a WM8962, ID %x != 0x6243\n", reg); - ret = -EINVAL; - goto err_regmap; - } - - ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, ®); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to read device revision: %d\n", - ret); - goto err_regmap; - } - - dev_info(&i2c->dev, "customer id %x revision %c\n", - (reg & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT, - ((reg & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT) - + 'A'); - - regcache_cache_bypass(wm8962->regmap, false); - - ret = wm8962_reset(wm8962); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to issue reset\n"); - goto err_regmap; - } - - if (pdata && pdata->in4_dc_measure) { - ret = regmap_register_patch(wm8962->regmap, - wm8962_dc_measure, - ARRAY_SIZE(wm8962_dc_measure)); - if (ret != 0) - dev_err(&i2c->dev, - "Failed to configure for DC mesurement: %d\n", - ret); - } - - pm_runtime_enable(&i2c->dev); - pm_request_idle(&i2c->dev); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8962, &wm8962_dai, 1); - if (ret < 0) - goto err_regmap; - - /* The drivers should power up as needed */ - regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); - - return 0; - -err_regmap: - regmap_exit(wm8962->regmap); -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); -err: - return ret; -} - -static __devexit int wm8962_i2c_remove(struct i2c_client *client) -{ - struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8962->regmap); - regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); - return 0; -} - -#ifdef CONFIG_PM_RUNTIME -static int wm8962_runtime_resume(struct device *dev) -{ - struct wm8962_priv *wm8962 = dev_get_drvdata(dev); - int ret; - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies), - wm8962->supplies); - if (ret != 0) { - dev_err(dev, - "Failed to enable supplies: %d\n", ret); - return ret; - } - - regcache_cache_only(wm8962->regmap, false); - regcache_sync(wm8962->regmap); - - regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, - WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA, - WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA); - - /* Bias enable at 2*50k for ramp */ - regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, - WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, - WM8962_BIAS_ENA | 0x180); - - msleep(5); - - /* VMID back to 2x250k for standby */ - regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, - WM8962_VMID_SEL_MASK, 0x100); - - return 0; -} - -static int wm8962_runtime_suspend(struct device *dev) -{ - struct wm8962_priv *wm8962 = dev_get_drvdata(dev); - - regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, - WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0); - - regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, - WM8962_STARTUP_BIAS_ENA | - WM8962_VMID_BUF_ENA, 0); - - regcache_cache_only(wm8962->regmap, true); - - regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), - wm8962->supplies); - - return 0; -} -#endif - -static struct dev_pm_ops wm8962_pm = { - SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL) -}; - -static const struct i2c_device_id wm8962_i2c_id[] = { - { "wm8962", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id); - -static struct i2c_driver wm8962_i2c_driver = { - .driver = { - .name = "wm8962", - .owner = THIS_MODULE, - .pm = &wm8962_pm, - }, - .probe = wm8962_i2c_probe, - .remove = __devexit_p(wm8962_i2c_remove), - .id_table = wm8962_i2c_id, -}; - -module_i2c_driver(wm8962_i2c_driver); - -MODULE_DESCRIPTION("ASoC WM8962 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8962.h b/ANDROID_3.4.5/sound/soc/codecs/wm8962.h deleted file mode 100644 index a1a5d529..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8962.h +++ /dev/null @@ -1,3780 +0,0 @@ -/* - * wm8962.h -- WM8962 ASoC driver - * - * Copyright 2010 Wolfson Microelectronics, plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8962_H -#define _WM8962_H - -#include -#include - -#define WM8962_SYSCLK_MCLK 1 -#define WM8962_SYSCLK_FLL 2 -#define WM8962_SYSCLK_PLL3 3 - -#define WM8962_FLL 1 - -#define WM8962_FLL_MCLK 1 -#define WM8962_FLL_BCLK 2 -#define WM8962_FLL_OSC 3 -#define WM8962_FLL_INT 4 - -/* - * Register values. - */ -#define WM8962_LEFT_INPUT_VOLUME 0x00 -#define WM8962_RIGHT_INPUT_VOLUME 0x01 -#define WM8962_HPOUTL_VOLUME 0x02 -#define WM8962_HPOUTR_VOLUME 0x03 -#define WM8962_CLOCKING1 0x04 -#define WM8962_ADC_DAC_CONTROL_1 0x05 -#define WM8962_ADC_DAC_CONTROL_2 0x06 -#define WM8962_AUDIO_INTERFACE_0 0x07 -#define WM8962_CLOCKING2 0x08 -#define WM8962_AUDIO_INTERFACE_1 0x09 -#define WM8962_LEFT_DAC_VOLUME 0x0A -#define WM8962_RIGHT_DAC_VOLUME 0x0B -#define WM8962_AUDIO_INTERFACE_2 0x0E -#define WM8962_SOFTWARE_RESET 0x0F -#define WM8962_ALC1 0x11 -#define WM8962_ALC2 0x12 -#define WM8962_ALC3 0x13 -#define WM8962_NOISE_GATE 0x14 -#define WM8962_LEFT_ADC_VOLUME 0x15 -#define WM8962_RIGHT_ADC_VOLUME 0x16 -#define WM8962_ADDITIONAL_CONTROL_1 0x17 -#define WM8962_ADDITIONAL_CONTROL_2 0x18 -#define WM8962_PWR_MGMT_1 0x19 -#define WM8962_PWR_MGMT_2 0x1A -#define WM8962_ADDITIONAL_CONTROL_3 0x1B -#define WM8962_ANTI_POP 0x1C -#define WM8962_CLOCKING_3 0x1E -#define WM8962_INPUT_MIXER_CONTROL_1 0x1F -#define WM8962_LEFT_INPUT_MIXER_VOLUME 0x20 -#define WM8962_RIGHT_INPUT_MIXER_VOLUME 0x21 -#define WM8962_INPUT_MIXER_CONTROL_2 0x22 -#define WM8962_INPUT_BIAS_CONTROL 0x23 -#define WM8962_LEFT_INPUT_PGA_CONTROL 0x25 -#define WM8962_RIGHT_INPUT_PGA_CONTROL 0x26 -#define WM8962_SPKOUTL_VOLUME 0x28 -#define WM8962_SPKOUTR_VOLUME 0x29 -#define WM8962_THERMAL_SHUTDOWN_STATUS 0x2F -#define WM8962_ADDITIONAL_CONTROL_4 0x30 -#define WM8962_CLASS_D_CONTROL_1 0x31 -#define WM8962_CLASS_D_CONTROL_2 0x33 -#define WM8962_CLOCKING_4 0x38 -#define WM8962_DAC_DSP_MIXING_1 0x39 -#define WM8962_DAC_DSP_MIXING_2 0x3A -#define WM8962_DC_SERVO_0 0x3C -#define WM8962_DC_SERVO_1 0x3D -#define WM8962_DC_SERVO_4 0x40 -#define WM8962_DC_SERVO_6 0x42 -#define WM8962_ANALOGUE_PGA_BIAS 0x44 -#define WM8962_ANALOGUE_HP_0 0x45 -#define WM8962_ANALOGUE_HP_2 0x47 -#define WM8962_CHARGE_PUMP_1 0x48 -#define WM8962_CHARGE_PUMP_B 0x52 -#define WM8962_WRITE_SEQUENCER_CONTROL_1 0x57 -#define WM8962_WRITE_SEQUENCER_CONTROL_2 0x5A -#define WM8962_WRITE_SEQUENCER_CONTROL_3 0x5D -#define WM8962_CONTROL_INTERFACE 0x5E -#define WM8962_MIXER_ENABLES 0x63 -#define WM8962_HEADPHONE_MIXER_1 0x64 -#define WM8962_HEADPHONE_MIXER_2 0x65 -#define WM8962_HEADPHONE_MIXER_3 0x66 -#define WM8962_HEADPHONE_MIXER_4 0x67 -#define WM8962_SPEAKER_MIXER_1 0x69 -#define WM8962_SPEAKER_MIXER_2 0x6A -#define WM8962_SPEAKER_MIXER_3 0x6B -#define WM8962_SPEAKER_MIXER_4 0x6C -#define WM8962_SPEAKER_MIXER_5 0x6D -#define WM8962_BEEP_GENERATOR_1 0x6E -#define WM8962_OSCILLATOR_TRIM_3 0x73 -#define WM8962_OSCILLATOR_TRIM_4 0x74 -#define WM8962_OSCILLATOR_TRIM_7 0x77 -#define WM8962_ANALOGUE_CLOCKING1 0x7C -#define WM8962_ANALOGUE_CLOCKING2 0x7D -#define WM8962_ANALOGUE_CLOCKING3 0x7E -#define WM8962_PLL_SOFTWARE_RESET 0x7F -#define WM8962_PLL2 0x81 -#define WM8962_PLL_4 0x83 -#define WM8962_PLL_9 0x88 -#define WM8962_PLL_10 0x89 -#define WM8962_PLL_11 0x8A -#define WM8962_PLL_12 0x8B -#define WM8962_PLL_13 0x8C -#define WM8962_PLL_14 0x8D -#define WM8962_PLL_15 0x8E -#define WM8962_PLL_16 0x8F -#define WM8962_FLL_CONTROL_1 0x9B -#define WM8962_FLL_CONTROL_2 0x9C -#define WM8962_FLL_CONTROL_3 0x9D -#define WM8962_FLL_CONTROL_5 0x9F -#define WM8962_FLL_CONTROL_6 0xA0 -#define WM8962_FLL_CONTROL_7 0xA1 -#define WM8962_FLL_CONTROL_8 0xA2 -#define WM8962_GENERAL_TEST_1 0xFC -#define WM8962_DF1 0x100 -#define WM8962_DF2 0x101 -#define WM8962_DF3 0x102 -#define WM8962_DF4 0x103 -#define WM8962_DF5 0x104 -#define WM8962_DF6 0x105 -#define WM8962_DF7 0x106 -#define WM8962_LHPF1 0x108 -#define WM8962_LHPF2 0x109 -#define WM8962_THREED1 0x10C -#define WM8962_THREED2 0x10D -#define WM8962_THREED3 0x10E -#define WM8962_THREED4 0x10F -#define WM8962_DRC_1 0x114 -#define WM8962_DRC_2 0x115 -#define WM8962_DRC_3 0x116 -#define WM8962_DRC_4 0x117 -#define WM8962_DRC_5 0x118 -#define WM8962_TLOOPBACK 0x11D -#define WM8962_EQ1 0x14F -#define WM8962_EQ2 0x150 -#define WM8962_EQ3 0x151 -#define WM8962_EQ4 0x152 -#define WM8962_EQ5 0x153 -#define WM8962_EQ6 0x154 -#define WM8962_EQ7 0x155 -#define WM8962_EQ8 0x156 -#define WM8962_EQ9 0x157 -#define WM8962_EQ10 0x158 -#define WM8962_EQ11 0x159 -#define WM8962_EQ12 0x15A -#define WM8962_EQ13 0x15B -#define WM8962_EQ14 0x15C -#define WM8962_EQ15 0x15D -#define WM8962_EQ16 0x15E -#define WM8962_EQ17 0x15F -#define WM8962_EQ18 0x160 -#define WM8962_EQ19 0x161 -#define WM8962_EQ20 0x162 -#define WM8962_EQ21 0x163 -#define WM8962_EQ22 0x164 -#define WM8962_EQ23 0x165 -#define WM8962_EQ24 0x166 -#define WM8962_EQ25 0x167 -#define WM8962_EQ26 0x168 -#define WM8962_EQ27 0x169 -#define WM8962_EQ28 0x16A -#define WM8962_EQ29 0x16B -#define WM8962_EQ30 0x16C -#define WM8962_EQ31 0x16D -#define WM8962_EQ32 0x16E -#define WM8962_EQ33 0x16F -#define WM8962_EQ34 0x170 -#define WM8962_EQ35 0x171 -#define WM8962_EQ36 0x172 -#define WM8962_EQ37 0x173 -#define WM8962_EQ38 0x174 -#define WM8962_EQ39 0x175 -#define WM8962_EQ40 0x176 -#define WM8962_EQ41 0x177 -#define WM8962_GPIO_BASE 0x200 -#define WM8962_GPIO_2 0x201 -#define WM8962_GPIO_3 0x202 -#define WM8962_GPIO_5 0x204 -#define WM8962_GPIO_6 0x205 -#define WM8962_INTERRUPT_STATUS_1 0x230 -#define WM8962_INTERRUPT_STATUS_2 0x231 -#define WM8962_INTERRUPT_STATUS_1_MASK 0x238 -#define WM8962_INTERRUPT_STATUS_2_MASK 0x239 -#define WM8962_INTERRUPT_CONTROL 0x240 -#define WM8962_IRQ_DEBOUNCE 0x248 -#define WM8962_MICINT_SOURCE_POL 0x24A -#define WM8962_DSP2_POWER_MANAGEMENT 0x300 -#define WM8962_DSP2_EXECCONTROL 0x40D -#define WM8962_WRITE_SEQUENCER_0 0x1000 -#define WM8962_WRITE_SEQUENCER_1 0x1001 -#define WM8962_WRITE_SEQUENCER_2 0x1002 -#define WM8962_WRITE_SEQUENCER_3 0x1003 -#define WM8962_WRITE_SEQUENCER_4 0x1004 -#define WM8962_WRITE_SEQUENCER_5 0x1005 -#define WM8962_WRITE_SEQUENCER_6 0x1006 -#define WM8962_WRITE_SEQUENCER_7 0x1007 -#define WM8962_WRITE_SEQUENCER_8 0x1008 -#define WM8962_WRITE_SEQUENCER_9 0x1009 -#define WM8962_WRITE_SEQUENCER_10 0x100A -#define WM8962_WRITE_SEQUENCER_11 0x100B -#define WM8962_WRITE_SEQUENCER_12 0x100C -#define WM8962_WRITE_SEQUENCER_13 0x100D -#define WM8962_WRITE_SEQUENCER_14 0x100E -#define WM8962_WRITE_SEQUENCER_15 0x100F -#define WM8962_WRITE_SEQUENCER_16 0x1010 -#define WM8962_WRITE_SEQUENCER_17 0x1011 -#define WM8962_WRITE_SEQUENCER_18 0x1012 -#define WM8962_WRITE_SEQUENCER_19 0x1013 -#define WM8962_WRITE_SEQUENCER_20 0x1014 -#define WM8962_WRITE_SEQUENCER_21 0x1015 -#define WM8962_WRITE_SEQUENCER_22 0x1016 -#define WM8962_WRITE_SEQUENCER_23 0x1017 -#define WM8962_WRITE_SEQUENCER_24 0x1018 -#define WM8962_WRITE_SEQUENCER_25 0x1019 -#define WM8962_WRITE_SEQUENCER_26 0x101A -#define WM8962_WRITE_SEQUENCER_27 0x101B -#define WM8962_WRITE_SEQUENCER_28 0x101C -#define WM8962_WRITE_SEQUENCER_29 0x101D -#define WM8962_WRITE_SEQUENCER_30 0x101E -#define WM8962_WRITE_SEQUENCER_31 0x101F -#define WM8962_WRITE_SEQUENCER_32 0x1020 -#define WM8962_WRITE_SEQUENCER_33 0x1021 -#define WM8962_WRITE_SEQUENCER_34 0x1022 -#define WM8962_WRITE_SEQUENCER_35 0x1023 -#define WM8962_WRITE_SEQUENCER_36 0x1024 -#define WM8962_WRITE_SEQUENCER_37 0x1025 -#define WM8962_WRITE_SEQUENCER_38 0x1026 -#define WM8962_WRITE_SEQUENCER_39 0x1027 -#define WM8962_WRITE_SEQUENCER_40 0x1028 -#define WM8962_WRITE_SEQUENCER_41 0x1029 -#define WM8962_WRITE_SEQUENCER_42 0x102A -#define WM8962_WRITE_SEQUENCER_43 0x102B -#define WM8962_WRITE_SEQUENCER_44 0x102C -#define WM8962_WRITE_SEQUENCER_45 0x102D -#define WM8962_WRITE_SEQUENCER_46 0x102E -#define WM8962_WRITE_SEQUENCER_47 0x102F -#define WM8962_WRITE_SEQUENCER_48 0x1030 -#define WM8962_WRITE_SEQUENCER_49 0x1031 -#define WM8962_WRITE_SEQUENCER_50 0x1032 -#define WM8962_WRITE_SEQUENCER_51 0x1033 -#define WM8962_WRITE_SEQUENCER_52 0x1034 -#define WM8962_WRITE_SEQUENCER_53 0x1035 -#define WM8962_WRITE_SEQUENCER_54 0x1036 -#define WM8962_WRITE_SEQUENCER_55 0x1037 -#define WM8962_WRITE_SEQUENCER_56 0x1038 -#define WM8962_WRITE_SEQUENCER_57 0x1039 -#define WM8962_WRITE_SEQUENCER_58 0x103A -#define WM8962_WRITE_SEQUENCER_59 0x103B -#define WM8962_WRITE_SEQUENCER_60 0x103C -#define WM8962_WRITE_SEQUENCER_61 0x103D -#define WM8962_WRITE_SEQUENCER_62 0x103E -#define WM8962_WRITE_SEQUENCER_63 0x103F -#define WM8962_WRITE_SEQUENCER_64 0x1040 -#define WM8962_WRITE_SEQUENCER_65 0x1041 -#define WM8962_WRITE_SEQUENCER_66 0x1042 -#define WM8962_WRITE_SEQUENCER_67 0x1043 -#define WM8962_WRITE_SEQUENCER_68 0x1044 -#define WM8962_WRITE_SEQUENCER_69 0x1045 -#define WM8962_WRITE_SEQUENCER_70 0x1046 -#define WM8962_WRITE_SEQUENCER_71 0x1047 -#define WM8962_WRITE_SEQUENCER_72 0x1048 -#define WM8962_WRITE_SEQUENCER_73 0x1049 -#define WM8962_WRITE_SEQUENCER_74 0x104A -#define WM8962_WRITE_SEQUENCER_75 0x104B -#define WM8962_WRITE_SEQUENCER_76 0x104C -#define WM8962_WRITE_SEQUENCER_77 0x104D -#define WM8962_WRITE_SEQUENCER_78 0x104E -#define WM8962_WRITE_SEQUENCER_79 0x104F -#define WM8962_WRITE_SEQUENCER_80 0x1050 -#define WM8962_WRITE_SEQUENCER_81 0x1051 -#define WM8962_WRITE_SEQUENCER_82 0x1052 -#define WM8962_WRITE_SEQUENCER_83 0x1053 -#define WM8962_WRITE_SEQUENCER_84 0x1054 -#define WM8962_WRITE_SEQUENCER_85 0x1055 -#define WM8962_WRITE_SEQUENCER_86 0x1056 -#define WM8962_WRITE_SEQUENCER_87 0x1057 -#define WM8962_WRITE_SEQUENCER_88 0x1058 -#define WM8962_WRITE_SEQUENCER_89 0x1059 -#define WM8962_WRITE_SEQUENCER_90 0x105A -#define WM8962_WRITE_SEQUENCER_91 0x105B -#define WM8962_WRITE_SEQUENCER_92 0x105C -#define WM8962_WRITE_SEQUENCER_93 0x105D -#define WM8962_WRITE_SEQUENCER_94 0x105E -#define WM8962_WRITE_SEQUENCER_95 0x105F -#define WM8962_WRITE_SEQUENCER_96 0x1060 -#define WM8962_WRITE_SEQUENCER_97 0x1061 -#define WM8962_WRITE_SEQUENCER_98 0x1062 -#define WM8962_WRITE_SEQUENCER_99 0x1063 -#define WM8962_WRITE_SEQUENCER_100 0x1064 -#define WM8962_WRITE_SEQUENCER_101 0x1065 -#define WM8962_WRITE_SEQUENCER_102 0x1066 -#define WM8962_WRITE_SEQUENCER_103 0x1067 -#define WM8962_WRITE_SEQUENCER_104 0x1068 -#define WM8962_WRITE_SEQUENCER_105 0x1069 -#define WM8962_WRITE_SEQUENCER_106 0x106A -#define WM8962_WRITE_SEQUENCER_107 0x106B -#define WM8962_WRITE_SEQUENCER_108 0x106C -#define WM8962_WRITE_SEQUENCER_109 0x106D -#define WM8962_WRITE_SEQUENCER_110 0x106E -#define WM8962_WRITE_SEQUENCER_111 0x106F -#define WM8962_WRITE_SEQUENCER_112 0x1070 -#define WM8962_WRITE_SEQUENCER_113 0x1071 -#define WM8962_WRITE_SEQUENCER_114 0x1072 -#define WM8962_WRITE_SEQUENCER_115 0x1073 -#define WM8962_WRITE_SEQUENCER_116 0x1074 -#define WM8962_WRITE_SEQUENCER_117 0x1075 -#define WM8962_WRITE_SEQUENCER_118 0x1076 -#define WM8962_WRITE_SEQUENCER_119 0x1077 -#define WM8962_WRITE_SEQUENCER_120 0x1078 -#define WM8962_WRITE_SEQUENCER_121 0x1079 -#define WM8962_WRITE_SEQUENCER_122 0x107A -#define WM8962_WRITE_SEQUENCER_123 0x107B -#define WM8962_WRITE_SEQUENCER_124 0x107C -#define WM8962_WRITE_SEQUENCER_125 0x107D -#define WM8962_WRITE_SEQUENCER_126 0x107E -#define WM8962_WRITE_SEQUENCER_127 0x107F -#define WM8962_WRITE_SEQUENCER_128 0x1080 -#define WM8962_WRITE_SEQUENCER_129 0x1081 -#define WM8962_WRITE_SEQUENCER_130 0x1082 -#define WM8962_WRITE_SEQUENCER_131 0x1083 -#define WM8962_WRITE_SEQUENCER_132 0x1084 -#define WM8962_WRITE_SEQUENCER_133 0x1085 -#define WM8962_WRITE_SEQUENCER_134 0x1086 -#define WM8962_WRITE_SEQUENCER_135 0x1087 -#define WM8962_WRITE_SEQUENCER_136 0x1088 -#define WM8962_WRITE_SEQUENCER_137 0x1089 -#define WM8962_WRITE_SEQUENCER_138 0x108A -#define WM8962_WRITE_SEQUENCER_139 0x108B -#define WM8962_WRITE_SEQUENCER_140 0x108C -#define WM8962_WRITE_SEQUENCER_141 0x108D -#define WM8962_WRITE_SEQUENCER_142 0x108E -#define WM8962_WRITE_SEQUENCER_143 0x108F -#define WM8962_WRITE_SEQUENCER_144 0x1090 -#define WM8962_WRITE_SEQUENCER_145 0x1091 -#define WM8962_WRITE_SEQUENCER_146 0x1092 -#define WM8962_WRITE_SEQUENCER_147 0x1093 -#define WM8962_WRITE_SEQUENCER_148 0x1094 -#define WM8962_WRITE_SEQUENCER_149 0x1095 -#define WM8962_WRITE_SEQUENCER_150 0x1096 -#define WM8962_WRITE_SEQUENCER_151 0x1097 -#define WM8962_WRITE_SEQUENCER_152 0x1098 -#define WM8962_WRITE_SEQUENCER_153 0x1099 -#define WM8962_WRITE_SEQUENCER_154 0x109A -#define WM8962_WRITE_SEQUENCER_155 0x109B -#define WM8962_WRITE_SEQUENCER_156 0x109C -#define WM8962_WRITE_SEQUENCER_157 0x109D -#define WM8962_WRITE_SEQUENCER_158 0x109E -#define WM8962_WRITE_SEQUENCER_159 0x109F -#define WM8962_WRITE_SEQUENCER_160 0x10A0 -#define WM8962_WRITE_SEQUENCER_161 0x10A1 -#define WM8962_WRITE_SEQUENCER_162 0x10A2 -#define WM8962_WRITE_SEQUENCER_163 0x10A3 -#define WM8962_WRITE_SEQUENCER_164 0x10A4 -#define WM8962_WRITE_SEQUENCER_165 0x10A5 -#define WM8962_WRITE_SEQUENCER_166 0x10A6 -#define WM8962_WRITE_SEQUENCER_167 0x10A7 -#define WM8962_WRITE_SEQUENCER_168 0x10A8 -#define WM8962_WRITE_SEQUENCER_169 0x10A9 -#define WM8962_WRITE_SEQUENCER_170 0x10AA -#define WM8962_WRITE_SEQUENCER_171 0x10AB -#define WM8962_WRITE_SEQUENCER_172 0x10AC -#define WM8962_WRITE_SEQUENCER_173 0x10AD -#define WM8962_WRITE_SEQUENCER_174 0x10AE -#define WM8962_WRITE_SEQUENCER_175 0x10AF -#define WM8962_WRITE_SEQUENCER_176 0x10B0 -#define WM8962_WRITE_SEQUENCER_177 0x10B1 -#define WM8962_WRITE_SEQUENCER_178 0x10B2 -#define WM8962_WRITE_SEQUENCER_179 0x10B3 -#define WM8962_WRITE_SEQUENCER_180 0x10B4 -#define WM8962_WRITE_SEQUENCER_181 0x10B5 -#define WM8962_WRITE_SEQUENCER_182 0x10B6 -#define WM8962_WRITE_SEQUENCER_183 0x10B7 -#define WM8962_WRITE_SEQUENCER_184 0x10B8 -#define WM8962_WRITE_SEQUENCER_185 0x10B9 -#define WM8962_WRITE_SEQUENCER_186 0x10BA -#define WM8962_WRITE_SEQUENCER_187 0x10BB -#define WM8962_WRITE_SEQUENCER_188 0x10BC -#define WM8962_WRITE_SEQUENCER_189 0x10BD -#define WM8962_WRITE_SEQUENCER_190 0x10BE -#define WM8962_WRITE_SEQUENCER_191 0x10BF -#define WM8962_WRITE_SEQUENCER_192 0x10C0 -#define WM8962_WRITE_SEQUENCER_193 0x10C1 -#define WM8962_WRITE_SEQUENCER_194 0x10C2 -#define WM8962_WRITE_SEQUENCER_195 0x10C3 -#define WM8962_WRITE_SEQUENCER_196 0x10C4 -#define WM8962_WRITE_SEQUENCER_197 0x10C5 -#define WM8962_WRITE_SEQUENCER_198 0x10C6 -#define WM8962_WRITE_SEQUENCER_199 0x10C7 -#define WM8962_WRITE_SEQUENCER_200 0x10C8 -#define WM8962_WRITE_SEQUENCER_201 0x10C9 -#define WM8962_WRITE_SEQUENCER_202 0x10CA -#define WM8962_WRITE_SEQUENCER_203 0x10CB -#define WM8962_WRITE_SEQUENCER_204 0x10CC -#define WM8962_WRITE_SEQUENCER_205 0x10CD -#define WM8962_WRITE_SEQUENCER_206 0x10CE -#define WM8962_WRITE_SEQUENCER_207 0x10CF -#define WM8962_WRITE_SEQUENCER_208 0x10D0 -#define WM8962_WRITE_SEQUENCER_209 0x10D1 -#define WM8962_WRITE_SEQUENCER_210 0x10D2 -#define WM8962_WRITE_SEQUENCER_211 0x10D3 -#define WM8962_WRITE_SEQUENCER_212 0x10D4 -#define WM8962_WRITE_SEQUENCER_213 0x10D5 -#define WM8962_WRITE_SEQUENCER_214 0x10D6 -#define WM8962_WRITE_SEQUENCER_215 0x10D7 -#define WM8962_WRITE_SEQUENCER_216 0x10D8 -#define WM8962_WRITE_SEQUENCER_217 0x10D9 -#define WM8962_WRITE_SEQUENCER_218 0x10DA -#define WM8962_WRITE_SEQUENCER_219 0x10DB -#define WM8962_WRITE_SEQUENCER_220 0x10DC -#define WM8962_WRITE_SEQUENCER_221 0x10DD -#define WM8962_WRITE_SEQUENCER_222 0x10DE -#define WM8962_WRITE_SEQUENCER_223 0x10DF -#define WM8962_WRITE_SEQUENCER_224 0x10E0 -#define WM8962_WRITE_SEQUENCER_225 0x10E1 -#define WM8962_WRITE_SEQUENCER_226 0x10E2 -#define WM8962_WRITE_SEQUENCER_227 0x10E3 -#define WM8962_WRITE_SEQUENCER_228 0x10E4 -#define WM8962_WRITE_SEQUENCER_229 0x10E5 -#define WM8962_WRITE_SEQUENCER_230 0x10E6 -#define WM8962_WRITE_SEQUENCER_231 0x10E7 -#define WM8962_WRITE_SEQUENCER_232 0x10E8 -#define WM8962_WRITE_SEQUENCER_233 0x10E9 -#define WM8962_WRITE_SEQUENCER_234 0x10EA -#define WM8962_WRITE_SEQUENCER_235 0x10EB -#define WM8962_WRITE_SEQUENCER_236 0x10EC -#define WM8962_WRITE_SEQUENCER_237 0x10ED -#define WM8962_WRITE_SEQUENCER_238 0x10EE -#define WM8962_WRITE_SEQUENCER_239 0x10EF -#define WM8962_WRITE_SEQUENCER_240 0x10F0 -#define WM8962_WRITE_SEQUENCER_241 0x10F1 -#define WM8962_WRITE_SEQUENCER_242 0x10F2 -#define WM8962_WRITE_SEQUENCER_243 0x10F3 -#define WM8962_WRITE_SEQUENCER_244 0x10F4 -#define WM8962_WRITE_SEQUENCER_245 0x10F5 -#define WM8962_WRITE_SEQUENCER_246 0x10F6 -#define WM8962_WRITE_SEQUENCER_247 0x10F7 -#define WM8962_WRITE_SEQUENCER_248 0x10F8 -#define WM8962_WRITE_SEQUENCER_249 0x10F9 -#define WM8962_WRITE_SEQUENCER_250 0x10FA -#define WM8962_WRITE_SEQUENCER_251 0x10FB -#define WM8962_WRITE_SEQUENCER_252 0x10FC -#define WM8962_WRITE_SEQUENCER_253 0x10FD -#define WM8962_WRITE_SEQUENCER_254 0x10FE -#define WM8962_WRITE_SEQUENCER_255 0x10FF -#define WM8962_WRITE_SEQUENCER_256 0x1100 -#define WM8962_WRITE_SEQUENCER_257 0x1101 -#define WM8962_WRITE_SEQUENCER_258 0x1102 -#define WM8962_WRITE_SEQUENCER_259 0x1103 -#define WM8962_WRITE_SEQUENCER_260 0x1104 -#define WM8962_WRITE_SEQUENCER_261 0x1105 -#define WM8962_WRITE_SEQUENCER_262 0x1106 -#define WM8962_WRITE_SEQUENCER_263 0x1107 -#define WM8962_WRITE_SEQUENCER_264 0x1108 -#define WM8962_WRITE_SEQUENCER_265 0x1109 -#define WM8962_WRITE_SEQUENCER_266 0x110A -#define WM8962_WRITE_SEQUENCER_267 0x110B -#define WM8962_WRITE_SEQUENCER_268 0x110C -#define WM8962_WRITE_SEQUENCER_269 0x110D -#define WM8962_WRITE_SEQUENCER_270 0x110E -#define WM8962_WRITE_SEQUENCER_271 0x110F -#define WM8962_WRITE_SEQUENCER_272 0x1110 -#define WM8962_WRITE_SEQUENCER_273 0x1111 -#define WM8962_WRITE_SEQUENCER_274 0x1112 -#define WM8962_WRITE_SEQUENCER_275 0x1113 -#define WM8962_WRITE_SEQUENCER_276 0x1114 -#define WM8962_WRITE_SEQUENCER_277 0x1115 -#define WM8962_WRITE_SEQUENCER_278 0x1116 -#define WM8962_WRITE_SEQUENCER_279 0x1117 -#define WM8962_WRITE_SEQUENCER_280 0x1118 -#define WM8962_WRITE_SEQUENCER_281 0x1119 -#define WM8962_WRITE_SEQUENCER_282 0x111A -#define WM8962_WRITE_SEQUENCER_283 0x111B -#define WM8962_WRITE_SEQUENCER_284 0x111C -#define WM8962_WRITE_SEQUENCER_285 0x111D -#define WM8962_WRITE_SEQUENCER_286 0x111E -#define WM8962_WRITE_SEQUENCER_287 0x111F -#define WM8962_WRITE_SEQUENCER_288 0x1120 -#define WM8962_WRITE_SEQUENCER_289 0x1121 -#define WM8962_WRITE_SEQUENCER_290 0x1122 -#define WM8962_WRITE_SEQUENCER_291 0x1123 -#define WM8962_WRITE_SEQUENCER_292 0x1124 -#define WM8962_WRITE_SEQUENCER_293 0x1125 -#define WM8962_WRITE_SEQUENCER_294 0x1126 -#define WM8962_WRITE_SEQUENCER_295 0x1127 -#define WM8962_WRITE_SEQUENCER_296 0x1128 -#define WM8962_WRITE_SEQUENCER_297 0x1129 -#define WM8962_WRITE_SEQUENCER_298 0x112A -#define WM8962_WRITE_SEQUENCER_299 0x112B -#define WM8962_WRITE_SEQUENCER_300 0x112C -#define WM8962_WRITE_SEQUENCER_301 0x112D -#define WM8962_WRITE_SEQUENCER_302 0x112E -#define WM8962_WRITE_SEQUENCER_303 0x112F -#define WM8962_WRITE_SEQUENCER_304 0x1130 -#define WM8962_WRITE_SEQUENCER_305 0x1131 -#define WM8962_WRITE_SEQUENCER_306 0x1132 -#define WM8962_WRITE_SEQUENCER_307 0x1133 -#define WM8962_WRITE_SEQUENCER_308 0x1134 -#define WM8962_WRITE_SEQUENCER_309 0x1135 -#define WM8962_WRITE_SEQUENCER_310 0x1136 -#define WM8962_WRITE_SEQUENCER_311 0x1137 -#define WM8962_WRITE_SEQUENCER_312 0x1138 -#define WM8962_WRITE_SEQUENCER_313 0x1139 -#define WM8962_WRITE_SEQUENCER_314 0x113A -#define WM8962_WRITE_SEQUENCER_315 0x113B -#define WM8962_WRITE_SEQUENCER_316 0x113C -#define WM8962_WRITE_SEQUENCER_317 0x113D -#define WM8962_WRITE_SEQUENCER_318 0x113E -#define WM8962_WRITE_SEQUENCER_319 0x113F -#define WM8962_WRITE_SEQUENCER_320 0x1140 -#define WM8962_WRITE_SEQUENCER_321 0x1141 -#define WM8962_WRITE_SEQUENCER_322 0x1142 -#define WM8962_WRITE_SEQUENCER_323 0x1143 -#define WM8962_WRITE_SEQUENCER_324 0x1144 -#define WM8962_WRITE_SEQUENCER_325 0x1145 -#define WM8962_WRITE_SEQUENCER_326 0x1146 -#define WM8962_WRITE_SEQUENCER_327 0x1147 -#define WM8962_WRITE_SEQUENCER_328 0x1148 -#define WM8962_WRITE_SEQUENCER_329 0x1149 -#define WM8962_WRITE_SEQUENCER_330 0x114A -#define WM8962_WRITE_SEQUENCER_331 0x114B -#define WM8962_WRITE_SEQUENCER_332 0x114C -#define WM8962_WRITE_SEQUENCER_333 0x114D -#define WM8962_WRITE_SEQUENCER_334 0x114E -#define WM8962_WRITE_SEQUENCER_335 0x114F -#define WM8962_WRITE_SEQUENCER_336 0x1150 -#define WM8962_WRITE_SEQUENCER_337 0x1151 -#define WM8962_WRITE_SEQUENCER_338 0x1152 -#define WM8962_WRITE_SEQUENCER_339 0x1153 -#define WM8962_WRITE_SEQUENCER_340 0x1154 -#define WM8962_WRITE_SEQUENCER_341 0x1155 -#define WM8962_WRITE_SEQUENCER_342 0x1156 -#define WM8962_WRITE_SEQUENCER_343 0x1157 -#define WM8962_WRITE_SEQUENCER_344 0x1158 -#define WM8962_WRITE_SEQUENCER_345 0x1159 -#define WM8962_WRITE_SEQUENCER_346 0x115A -#define WM8962_WRITE_SEQUENCER_347 0x115B -#define WM8962_WRITE_SEQUENCER_348 0x115C -#define WM8962_WRITE_SEQUENCER_349 0x115D -#define WM8962_WRITE_SEQUENCER_350 0x115E -#define WM8962_WRITE_SEQUENCER_351 0x115F -#define WM8962_WRITE_SEQUENCER_352 0x1160 -#define WM8962_WRITE_SEQUENCER_353 0x1161 -#define WM8962_WRITE_SEQUENCER_354 0x1162 -#define WM8962_WRITE_SEQUENCER_355 0x1163 -#define WM8962_WRITE_SEQUENCER_356 0x1164 -#define WM8962_WRITE_SEQUENCER_357 0x1165 -#define WM8962_WRITE_SEQUENCER_358 0x1166 -#define WM8962_WRITE_SEQUENCER_359 0x1167 -#define WM8962_WRITE_SEQUENCER_360 0x1168 -#define WM8962_WRITE_SEQUENCER_361 0x1169 -#define WM8962_WRITE_SEQUENCER_362 0x116A -#define WM8962_WRITE_SEQUENCER_363 0x116B -#define WM8962_WRITE_SEQUENCER_364 0x116C -#define WM8962_WRITE_SEQUENCER_365 0x116D -#define WM8962_WRITE_SEQUENCER_366 0x116E -#define WM8962_WRITE_SEQUENCER_367 0x116F -#define WM8962_WRITE_SEQUENCER_368 0x1170 -#define WM8962_WRITE_SEQUENCER_369 0x1171 -#define WM8962_WRITE_SEQUENCER_370 0x1172 -#define WM8962_WRITE_SEQUENCER_371 0x1173 -#define WM8962_WRITE_SEQUENCER_372 0x1174 -#define WM8962_WRITE_SEQUENCER_373 0x1175 -#define WM8962_WRITE_SEQUENCER_374 0x1176 -#define WM8962_WRITE_SEQUENCER_375 0x1177 -#define WM8962_WRITE_SEQUENCER_376 0x1178 -#define WM8962_WRITE_SEQUENCER_377 0x1179 -#define WM8962_WRITE_SEQUENCER_378 0x117A -#define WM8962_WRITE_SEQUENCER_379 0x117B -#define WM8962_WRITE_SEQUENCER_380 0x117C -#define WM8962_WRITE_SEQUENCER_381 0x117D -#define WM8962_WRITE_SEQUENCER_382 0x117E -#define WM8962_WRITE_SEQUENCER_383 0x117F -#define WM8962_WRITE_SEQUENCER_384 0x1180 -#define WM8962_WRITE_SEQUENCER_385 0x1181 -#define WM8962_WRITE_SEQUENCER_386 0x1182 -#define WM8962_WRITE_SEQUENCER_387 0x1183 -#define WM8962_WRITE_SEQUENCER_388 0x1184 -#define WM8962_WRITE_SEQUENCER_389 0x1185 -#define WM8962_WRITE_SEQUENCER_390 0x1186 -#define WM8962_WRITE_SEQUENCER_391 0x1187 -#define WM8962_WRITE_SEQUENCER_392 0x1188 -#define WM8962_WRITE_SEQUENCER_393 0x1189 -#define WM8962_WRITE_SEQUENCER_394 0x118A -#define WM8962_WRITE_SEQUENCER_395 0x118B -#define WM8962_WRITE_SEQUENCER_396 0x118C -#define WM8962_WRITE_SEQUENCER_397 0x118D -#define WM8962_WRITE_SEQUENCER_398 0x118E -#define WM8962_WRITE_SEQUENCER_399 0x118F -#define WM8962_WRITE_SEQUENCER_400 0x1190 -#define WM8962_WRITE_SEQUENCER_401 0x1191 -#define WM8962_WRITE_SEQUENCER_402 0x1192 -#define WM8962_WRITE_SEQUENCER_403 0x1193 -#define WM8962_WRITE_SEQUENCER_404 0x1194 -#define WM8962_WRITE_SEQUENCER_405 0x1195 -#define WM8962_WRITE_SEQUENCER_406 0x1196 -#define WM8962_WRITE_SEQUENCER_407 0x1197 -#define WM8962_WRITE_SEQUENCER_408 0x1198 -#define WM8962_WRITE_SEQUENCER_409 0x1199 -#define WM8962_WRITE_SEQUENCER_410 0x119A -#define WM8962_WRITE_SEQUENCER_411 0x119B -#define WM8962_WRITE_SEQUENCER_412 0x119C -#define WM8962_WRITE_SEQUENCER_413 0x119D -#define WM8962_WRITE_SEQUENCER_414 0x119E -#define WM8962_WRITE_SEQUENCER_415 0x119F -#define WM8962_WRITE_SEQUENCER_416 0x11A0 -#define WM8962_WRITE_SEQUENCER_417 0x11A1 -#define WM8962_WRITE_SEQUENCER_418 0x11A2 -#define WM8962_WRITE_SEQUENCER_419 0x11A3 -#define WM8962_WRITE_SEQUENCER_420 0x11A4 -#define WM8962_WRITE_SEQUENCER_421 0x11A5 -#define WM8962_WRITE_SEQUENCER_422 0x11A6 -#define WM8962_WRITE_SEQUENCER_423 0x11A7 -#define WM8962_WRITE_SEQUENCER_424 0x11A8 -#define WM8962_WRITE_SEQUENCER_425 0x11A9 -#define WM8962_WRITE_SEQUENCER_426 0x11AA -#define WM8962_WRITE_SEQUENCER_427 0x11AB -#define WM8962_WRITE_SEQUENCER_428 0x11AC -#define WM8962_WRITE_SEQUENCER_429 0x11AD -#define WM8962_WRITE_SEQUENCER_430 0x11AE -#define WM8962_WRITE_SEQUENCER_431 0x11AF -#define WM8962_WRITE_SEQUENCER_432 0x11B0 -#define WM8962_WRITE_SEQUENCER_433 0x11B1 -#define WM8962_WRITE_SEQUENCER_434 0x11B2 -#define WM8962_WRITE_SEQUENCER_435 0x11B3 -#define WM8962_WRITE_SEQUENCER_436 0x11B4 -#define WM8962_WRITE_SEQUENCER_437 0x11B5 -#define WM8962_WRITE_SEQUENCER_438 0x11B6 -#define WM8962_WRITE_SEQUENCER_439 0x11B7 -#define WM8962_WRITE_SEQUENCER_440 0x11B8 -#define WM8962_WRITE_SEQUENCER_441 0x11B9 -#define WM8962_WRITE_SEQUENCER_442 0x11BA -#define WM8962_WRITE_SEQUENCER_443 0x11BB -#define WM8962_WRITE_SEQUENCER_444 0x11BC -#define WM8962_WRITE_SEQUENCER_445 0x11BD -#define WM8962_WRITE_SEQUENCER_446 0x11BE -#define WM8962_WRITE_SEQUENCER_447 0x11BF -#define WM8962_WRITE_SEQUENCER_448 0x11C0 -#define WM8962_WRITE_SEQUENCER_449 0x11C1 -#define WM8962_WRITE_SEQUENCER_450 0x11C2 -#define WM8962_WRITE_SEQUENCER_451 0x11C3 -#define WM8962_WRITE_SEQUENCER_452 0x11C4 -#define WM8962_WRITE_SEQUENCER_453 0x11C5 -#define WM8962_WRITE_SEQUENCER_454 0x11C6 -#define WM8962_WRITE_SEQUENCER_455 0x11C7 -#define WM8962_WRITE_SEQUENCER_456 0x11C8 -#define WM8962_WRITE_SEQUENCER_457 0x11C9 -#define WM8962_WRITE_SEQUENCER_458 0x11CA -#define WM8962_WRITE_SEQUENCER_459 0x11CB -#define WM8962_WRITE_SEQUENCER_460 0x11CC -#define WM8962_WRITE_SEQUENCER_461 0x11CD -#define WM8962_WRITE_SEQUENCER_462 0x11CE -#define WM8962_WRITE_SEQUENCER_463 0x11CF -#define WM8962_WRITE_SEQUENCER_464 0x11D0 -#define WM8962_WRITE_SEQUENCER_465 0x11D1 -#define WM8962_WRITE_SEQUENCER_466 0x11D2 -#define WM8962_WRITE_SEQUENCER_467 0x11D3 -#define WM8962_WRITE_SEQUENCER_468 0x11D4 -#define WM8962_WRITE_SEQUENCER_469 0x11D5 -#define WM8962_WRITE_SEQUENCER_470 0x11D6 -#define WM8962_WRITE_SEQUENCER_471 0x11D7 -#define WM8962_WRITE_SEQUENCER_472 0x11D8 -#define WM8962_WRITE_SEQUENCER_473 0x11D9 -#define WM8962_WRITE_SEQUENCER_474 0x11DA -#define WM8962_WRITE_SEQUENCER_475 0x11DB -#define WM8962_WRITE_SEQUENCER_476 0x11DC -#define WM8962_WRITE_SEQUENCER_477 0x11DD -#define WM8962_WRITE_SEQUENCER_478 0x11DE -#define WM8962_WRITE_SEQUENCER_479 0x11DF -#define WM8962_WRITE_SEQUENCER_480 0x11E0 -#define WM8962_WRITE_SEQUENCER_481 0x11E1 -#define WM8962_WRITE_SEQUENCER_482 0x11E2 -#define WM8962_WRITE_SEQUENCER_483 0x11E3 -#define WM8962_WRITE_SEQUENCER_484 0x11E4 -#define WM8962_WRITE_SEQUENCER_485 0x11E5 -#define WM8962_WRITE_SEQUENCER_486 0x11E6 -#define WM8962_WRITE_SEQUENCER_487 0x11E7 -#define WM8962_WRITE_SEQUENCER_488 0x11E8 -#define WM8962_WRITE_SEQUENCER_489 0x11E9 -#define WM8962_WRITE_SEQUENCER_490 0x11EA -#define WM8962_WRITE_SEQUENCER_491 0x11EB -#define WM8962_WRITE_SEQUENCER_492 0x11EC -#define WM8962_WRITE_SEQUENCER_493 0x11ED -#define WM8962_WRITE_SEQUENCER_494 0x11EE -#define WM8962_WRITE_SEQUENCER_495 0x11EF -#define WM8962_WRITE_SEQUENCER_496 0x11F0 -#define WM8962_WRITE_SEQUENCER_497 0x11F1 -#define WM8962_WRITE_SEQUENCER_498 0x11F2 -#define WM8962_WRITE_SEQUENCER_499 0x11F3 -#define WM8962_WRITE_SEQUENCER_500 0x11F4 -#define WM8962_WRITE_SEQUENCER_501 0x11F5 -#define WM8962_WRITE_SEQUENCER_502 0x11F6 -#define WM8962_WRITE_SEQUENCER_503 0x11F7 -#define WM8962_WRITE_SEQUENCER_504 0x11F8 -#define WM8962_WRITE_SEQUENCER_505 0x11F9 -#define WM8962_WRITE_SEQUENCER_506 0x11FA -#define WM8962_WRITE_SEQUENCER_507 0x11FB -#define WM8962_WRITE_SEQUENCER_508 0x11FC -#define WM8962_WRITE_SEQUENCER_509 0x11FD -#define WM8962_WRITE_SEQUENCER_510 0x11FE -#define WM8962_WRITE_SEQUENCER_511 0x11FF -#define WM8962_DSP2_INSTRUCTION_RAM_0 0x2000 -#define WM8962_DSP2_ADDRESS_RAM_2 0x2400 -#define WM8962_DSP2_ADDRESS_RAM_1 0x2401 -#define WM8962_DSP2_ADDRESS_RAM_0 0x2402 -#define WM8962_DSP2_DATA1_RAM_1 0x3000 -#define WM8962_DSP2_DATA1_RAM_0 0x3001 -#define WM8962_DSP2_DATA2_RAM_1 0x3400 -#define WM8962_DSP2_DATA2_RAM_0 0x3401 -#define WM8962_DSP2_DATA3_RAM_1 0x3800 -#define WM8962_DSP2_DATA3_RAM_0 0x3801 -#define WM8962_DSP2_COEFF_RAM_0 0x3C00 -#define WM8962_RETUNEADC_SHARED_COEFF_1 0x4000 -#define WM8962_RETUNEADC_SHARED_COEFF_0 0x4001 -#define WM8962_RETUNEDAC_SHARED_COEFF_1 0x4002 -#define WM8962_RETUNEDAC_SHARED_COEFF_0 0x4003 -#define WM8962_SOUNDSTAGE_ENABLES_1 0x4004 -#define WM8962_SOUNDSTAGE_ENABLES_0 0x4005 -#define WM8962_HDBASS_AI_1 0x4200 -#define WM8962_HDBASS_AI_0 0x4201 -#define WM8962_HDBASS_AR_1 0x4202 -#define WM8962_HDBASS_AR_0 0x4203 -#define WM8962_HDBASS_B_1 0x4204 -#define WM8962_HDBASS_B_0 0x4205 -#define WM8962_HDBASS_K_1 0x4206 -#define WM8962_HDBASS_K_0 0x4207 -#define WM8962_HDBASS_N1_1 0x4208 -#define WM8962_HDBASS_N1_0 0x4209 -#define WM8962_HDBASS_N2_1 0x420A -#define WM8962_HDBASS_N2_0 0x420B -#define WM8962_HDBASS_N3_1 0x420C -#define WM8962_HDBASS_N3_0 0x420D -#define WM8962_HDBASS_N4_1 0x420E -#define WM8962_HDBASS_N4_0 0x420F -#define WM8962_HDBASS_N5_1 0x4210 -#define WM8962_HDBASS_N5_0 0x4211 -#define WM8962_HDBASS_X1_1 0x4212 -#define WM8962_HDBASS_X1_0 0x4213 -#define WM8962_HDBASS_X2_1 0x4214 -#define WM8962_HDBASS_X2_0 0x4215 -#define WM8962_HDBASS_X3_1 0x4216 -#define WM8962_HDBASS_X3_0 0x4217 -#define WM8962_HDBASS_ATK_1 0x4218 -#define WM8962_HDBASS_ATK_0 0x4219 -#define WM8962_HDBASS_DCY_1 0x421A -#define WM8962_HDBASS_DCY_0 0x421B -#define WM8962_HDBASS_PG_1 0x421C -#define WM8962_HDBASS_PG_0 0x421D -#define WM8962_HPF_C_1 0x4400 -#define WM8962_HPF_C_0 0x4401 -#define WM8962_ADCL_RETUNE_C1_1 0x4600 -#define WM8962_ADCL_RETUNE_C1_0 0x4601 -#define WM8962_ADCL_RETUNE_C2_1 0x4602 -#define WM8962_ADCL_RETUNE_C2_0 0x4603 -#define WM8962_ADCL_RETUNE_C3_1 0x4604 -#define WM8962_ADCL_RETUNE_C3_0 0x4605 -#define WM8962_ADCL_RETUNE_C4_1 0x4606 -#define WM8962_ADCL_RETUNE_C4_0 0x4607 -#define WM8962_ADCL_RETUNE_C5_1 0x4608 -#define WM8962_ADCL_RETUNE_C5_0 0x4609 -#define WM8962_ADCL_RETUNE_C6_1 0x460A -#define WM8962_ADCL_RETUNE_C6_0 0x460B -#define WM8962_ADCL_RETUNE_C7_1 0x460C -#define WM8962_ADCL_RETUNE_C7_0 0x460D -#define WM8962_ADCL_RETUNE_C8_1 0x460E -#define WM8962_ADCL_RETUNE_C8_0 0x460F -#define WM8962_ADCL_RETUNE_C9_1 0x4610 -#define WM8962_ADCL_RETUNE_C9_0 0x4611 -#define WM8962_ADCL_RETUNE_C10_1 0x4612 -#define WM8962_ADCL_RETUNE_C10_0 0x4613 -#define WM8962_ADCL_RETUNE_C11_1 0x4614 -#define WM8962_ADCL_RETUNE_C11_0 0x4615 -#define WM8962_ADCL_RETUNE_C12_1 0x4616 -#define WM8962_ADCL_RETUNE_C12_0 0x4617 -#define WM8962_ADCL_RETUNE_C13_1 0x4618 -#define WM8962_ADCL_RETUNE_C13_0 0x4619 -#define WM8962_ADCL_RETUNE_C14_1 0x461A -#define WM8962_ADCL_RETUNE_C14_0 0x461B -#define WM8962_ADCL_RETUNE_C15_1 0x461C -#define WM8962_ADCL_RETUNE_C15_0 0x461D -#define WM8962_ADCL_RETUNE_C16_1 0x461E -#define WM8962_ADCL_RETUNE_C16_0 0x461F -#define WM8962_ADCL_RETUNE_C17_1 0x4620 -#define WM8962_ADCL_RETUNE_C17_0 0x4621 -#define WM8962_ADCL_RETUNE_C18_1 0x4622 -#define WM8962_ADCL_RETUNE_C18_0 0x4623 -#define WM8962_ADCL_RETUNE_C19_1 0x4624 -#define WM8962_ADCL_RETUNE_C19_0 0x4625 -#define WM8962_ADCL_RETUNE_C20_1 0x4626 -#define WM8962_ADCL_RETUNE_C20_0 0x4627 -#define WM8962_ADCL_RETUNE_C21_1 0x4628 -#define WM8962_ADCL_RETUNE_C21_0 0x4629 -#define WM8962_ADCL_RETUNE_C22_1 0x462A -#define WM8962_ADCL_RETUNE_C22_0 0x462B -#define WM8962_ADCL_RETUNE_C23_1 0x462C -#define WM8962_ADCL_RETUNE_C23_0 0x462D -#define WM8962_ADCL_RETUNE_C24_1 0x462E -#define WM8962_ADCL_RETUNE_C24_0 0x462F -#define WM8962_ADCL_RETUNE_C25_1 0x4630 -#define WM8962_ADCL_RETUNE_C25_0 0x4631 -#define WM8962_ADCL_RETUNE_C26_1 0x4632 -#define WM8962_ADCL_RETUNE_C26_0 0x4633 -#define WM8962_ADCL_RETUNE_C27_1 0x4634 -#define WM8962_ADCL_RETUNE_C27_0 0x4635 -#define WM8962_ADCL_RETUNE_C28_1 0x4636 -#define WM8962_ADCL_RETUNE_C28_0 0x4637 -#define WM8962_ADCL_RETUNE_C29_1 0x4638 -#define WM8962_ADCL_RETUNE_C29_0 0x4639 -#define WM8962_ADCL_RETUNE_C30_1 0x463A -#define WM8962_ADCL_RETUNE_C30_0 0x463B -#define WM8962_ADCL_RETUNE_C31_1 0x463C -#define WM8962_ADCL_RETUNE_C31_0 0x463D -#define WM8962_ADCL_RETUNE_C32_1 0x463E -#define WM8962_ADCL_RETUNE_C32_0 0x463F -#define WM8962_RETUNEADC_PG2_1 0x4800 -#define WM8962_RETUNEADC_PG2_0 0x4801 -#define WM8962_RETUNEADC_PG_1 0x4802 -#define WM8962_RETUNEADC_PG_0 0x4803 -#define WM8962_ADCR_RETUNE_C1_1 0x4A00 -#define WM8962_ADCR_RETUNE_C1_0 0x4A01 -#define WM8962_ADCR_RETUNE_C2_1 0x4A02 -#define WM8962_ADCR_RETUNE_C2_0 0x4A03 -#define WM8962_ADCR_RETUNE_C3_1 0x4A04 -#define WM8962_ADCR_RETUNE_C3_0 0x4A05 -#define WM8962_ADCR_RETUNE_C4_1 0x4A06 -#define WM8962_ADCR_RETUNE_C4_0 0x4A07 -#define WM8962_ADCR_RETUNE_C5_1 0x4A08 -#define WM8962_ADCR_RETUNE_C5_0 0x4A09 -#define WM8962_ADCR_RETUNE_C6_1 0x4A0A -#define WM8962_ADCR_RETUNE_C6_0 0x4A0B -#define WM8962_ADCR_RETUNE_C7_1 0x4A0C -#define WM8962_ADCR_RETUNE_C7_0 0x4A0D -#define WM8962_ADCR_RETUNE_C8_1 0x4A0E -#define WM8962_ADCR_RETUNE_C8_0 0x4A0F -#define WM8962_ADCR_RETUNE_C9_1 0x4A10 -#define WM8962_ADCR_RETUNE_C9_0 0x4A11 -#define WM8962_ADCR_RETUNE_C10_1 0x4A12 -#define WM8962_ADCR_RETUNE_C10_0 0x4A13 -#define WM8962_ADCR_RETUNE_C11_1 0x4A14 -#define WM8962_ADCR_RETUNE_C11_0 0x4A15 -#define WM8962_ADCR_RETUNE_C12_1 0x4A16 -#define WM8962_ADCR_RETUNE_C12_0 0x4A17 -#define WM8962_ADCR_RETUNE_C13_1 0x4A18 -#define WM8962_ADCR_RETUNE_C13_0 0x4A19 -#define WM8962_ADCR_RETUNE_C14_1 0x4A1A -#define WM8962_ADCR_RETUNE_C14_0 0x4A1B -#define WM8962_ADCR_RETUNE_C15_1 0x4A1C -#define WM8962_ADCR_RETUNE_C15_0 0x4A1D -#define WM8962_ADCR_RETUNE_C16_1 0x4A1E -#define WM8962_ADCR_RETUNE_C16_0 0x4A1F -#define WM8962_ADCR_RETUNE_C17_1 0x4A20 -#define WM8962_ADCR_RETUNE_C17_0 0x4A21 -#define WM8962_ADCR_RETUNE_C18_1 0x4A22 -#define WM8962_ADCR_RETUNE_C18_0 0x4A23 -#define WM8962_ADCR_RETUNE_C19_1 0x4A24 -#define WM8962_ADCR_RETUNE_C19_0 0x4A25 -#define WM8962_ADCR_RETUNE_C20_1 0x4A26 -#define WM8962_ADCR_RETUNE_C20_0 0x4A27 -#define WM8962_ADCR_RETUNE_C21_1 0x4A28 -#define WM8962_ADCR_RETUNE_C21_0 0x4A29 -#define WM8962_ADCR_RETUNE_C22_1 0x4A2A -#define WM8962_ADCR_RETUNE_C22_0 0x4A2B -#define WM8962_ADCR_RETUNE_C23_1 0x4A2C -#define WM8962_ADCR_RETUNE_C23_0 0x4A2D -#define WM8962_ADCR_RETUNE_C24_1 0x4A2E -#define WM8962_ADCR_RETUNE_C24_0 0x4A2F -#define WM8962_ADCR_RETUNE_C25_1 0x4A30 -#define WM8962_ADCR_RETUNE_C25_0 0x4A31 -#define WM8962_ADCR_RETUNE_C26_1 0x4A32 -#define WM8962_ADCR_RETUNE_C26_0 0x4A33 -#define WM8962_ADCR_RETUNE_C27_1 0x4A34 -#define WM8962_ADCR_RETUNE_C27_0 0x4A35 -#define WM8962_ADCR_RETUNE_C28_1 0x4A36 -#define WM8962_ADCR_RETUNE_C28_0 0x4A37 -#define WM8962_ADCR_RETUNE_C29_1 0x4A38 -#define WM8962_ADCR_RETUNE_C29_0 0x4A39 -#define WM8962_ADCR_RETUNE_C30_1 0x4A3A -#define WM8962_ADCR_RETUNE_C30_0 0x4A3B -#define WM8962_ADCR_RETUNE_C31_1 0x4A3C -#define WM8962_ADCR_RETUNE_C31_0 0x4A3D -#define WM8962_ADCR_RETUNE_C32_1 0x4A3E -#define WM8962_ADCR_RETUNE_C32_0 0x4A3F -#define WM8962_DACL_RETUNE_C1_1 0x4C00 -#define WM8962_DACL_RETUNE_C1_0 0x4C01 -#define WM8962_DACL_RETUNE_C2_1 0x4C02 -#define WM8962_DACL_RETUNE_C2_0 0x4C03 -#define WM8962_DACL_RETUNE_C3_1 0x4C04 -#define WM8962_DACL_RETUNE_C3_0 0x4C05 -#define WM8962_DACL_RETUNE_C4_1 0x4C06 -#define WM8962_DACL_RETUNE_C4_0 0x4C07 -#define WM8962_DACL_RETUNE_C5_1 0x4C08 -#define WM8962_DACL_RETUNE_C5_0 0x4C09 -#define WM8962_DACL_RETUNE_C6_1 0x4C0A -#define WM8962_DACL_RETUNE_C6_0 0x4C0B -#define WM8962_DACL_RETUNE_C7_1 0x4C0C -#define WM8962_DACL_RETUNE_C7_0 0x4C0D -#define WM8962_DACL_RETUNE_C8_1 0x4C0E -#define WM8962_DACL_RETUNE_C8_0 0x4C0F -#define WM8962_DACL_RETUNE_C9_1 0x4C10 -#define WM8962_DACL_RETUNE_C9_0 0x4C11 -#define WM8962_DACL_RETUNE_C10_1 0x4C12 -#define WM8962_DACL_RETUNE_C10_0 0x4C13 -#define WM8962_DACL_RETUNE_C11_1 0x4C14 -#define WM8962_DACL_RETUNE_C11_0 0x4C15 -#define WM8962_DACL_RETUNE_C12_1 0x4C16 -#define WM8962_DACL_RETUNE_C12_0 0x4C17 -#define WM8962_DACL_RETUNE_C13_1 0x4C18 -#define WM8962_DACL_RETUNE_C13_0 0x4C19 -#define WM8962_DACL_RETUNE_C14_1 0x4C1A -#define WM8962_DACL_RETUNE_C14_0 0x4C1B -#define WM8962_DACL_RETUNE_C15_1 0x4C1C -#define WM8962_DACL_RETUNE_C15_0 0x4C1D -#define WM8962_DACL_RETUNE_C16_1 0x4C1E -#define WM8962_DACL_RETUNE_C16_0 0x4C1F -#define WM8962_DACL_RETUNE_C17_1 0x4C20 -#define WM8962_DACL_RETUNE_C17_0 0x4C21 -#define WM8962_DACL_RETUNE_C18_1 0x4C22 -#define WM8962_DACL_RETUNE_C18_0 0x4C23 -#define WM8962_DACL_RETUNE_C19_1 0x4C24 -#define WM8962_DACL_RETUNE_C19_0 0x4C25 -#define WM8962_DACL_RETUNE_C20_1 0x4C26 -#define WM8962_DACL_RETUNE_C20_0 0x4C27 -#define WM8962_DACL_RETUNE_C21_1 0x4C28 -#define WM8962_DACL_RETUNE_C21_0 0x4C29 -#define WM8962_DACL_RETUNE_C22_1 0x4C2A -#define WM8962_DACL_RETUNE_C22_0 0x4C2B -#define WM8962_DACL_RETUNE_C23_1 0x4C2C -#define WM8962_DACL_RETUNE_C23_0 0x4C2D -#define WM8962_DACL_RETUNE_C24_1 0x4C2E -#define WM8962_DACL_RETUNE_C24_0 0x4C2F -#define WM8962_DACL_RETUNE_C25_1 0x4C30 -#define WM8962_DACL_RETUNE_C25_0 0x4C31 -#define WM8962_DACL_RETUNE_C26_1 0x4C32 -#define WM8962_DACL_RETUNE_C26_0 0x4C33 -#define WM8962_DACL_RETUNE_C27_1 0x4C34 -#define WM8962_DACL_RETUNE_C27_0 0x4C35 -#define WM8962_DACL_RETUNE_C28_1 0x4C36 -#define WM8962_DACL_RETUNE_C28_0 0x4C37 -#define WM8962_DACL_RETUNE_C29_1 0x4C38 -#define WM8962_DACL_RETUNE_C29_0 0x4C39 -#define WM8962_DACL_RETUNE_C30_1 0x4C3A -#define WM8962_DACL_RETUNE_C30_0 0x4C3B -#define WM8962_DACL_RETUNE_C31_1 0x4C3C -#define WM8962_DACL_RETUNE_C31_0 0x4C3D -#define WM8962_DACL_RETUNE_C32_1 0x4C3E -#define WM8962_DACL_RETUNE_C32_0 0x4C3F -#define WM8962_RETUNEDAC_PG2_1 0x4E00 -#define WM8962_RETUNEDAC_PG2_0 0x4E01 -#define WM8962_RETUNEDAC_PG_1 0x4E02 -#define WM8962_RETUNEDAC_PG_0 0x4E03 -#define WM8962_DACR_RETUNE_C1_1 0x5000 -#define WM8962_DACR_RETUNE_C1_0 0x5001 -#define WM8962_DACR_RETUNE_C2_1 0x5002 -#define WM8962_DACR_RETUNE_C2_0 0x5003 -#define WM8962_DACR_RETUNE_C3_1 0x5004 -#define WM8962_DACR_RETUNE_C3_0 0x5005 -#define WM8962_DACR_RETUNE_C4_1 0x5006 -#define WM8962_DACR_RETUNE_C4_0 0x5007 -#define WM8962_DACR_RETUNE_C5_1 0x5008 -#define WM8962_DACR_RETUNE_C5_0 0x5009 -#define WM8962_DACR_RETUNE_C6_1 0x500A -#define WM8962_DACR_RETUNE_C6_0 0x500B -#define WM8962_DACR_RETUNE_C7_1 0x500C -#define WM8962_DACR_RETUNE_C7_0 0x500D -#define WM8962_DACR_RETUNE_C8_1 0x500E -#define WM8962_DACR_RETUNE_C8_0 0x500F -#define WM8962_DACR_RETUNE_C9_1 0x5010 -#define WM8962_DACR_RETUNE_C9_0 0x5011 -#define WM8962_DACR_RETUNE_C10_1 0x5012 -#define WM8962_DACR_RETUNE_C10_0 0x5013 -#define WM8962_DACR_RETUNE_C11_1 0x5014 -#define WM8962_DACR_RETUNE_C11_0 0x5015 -#define WM8962_DACR_RETUNE_C12_1 0x5016 -#define WM8962_DACR_RETUNE_C12_0 0x5017 -#define WM8962_DACR_RETUNE_C13_1 0x5018 -#define WM8962_DACR_RETUNE_C13_0 0x5019 -#define WM8962_DACR_RETUNE_C14_1 0x501A -#define WM8962_DACR_RETUNE_C14_0 0x501B -#define WM8962_DACR_RETUNE_C15_1 0x501C -#define WM8962_DACR_RETUNE_C15_0 0x501D -#define WM8962_DACR_RETUNE_C16_1 0x501E -#define WM8962_DACR_RETUNE_C16_0 0x501F -#define WM8962_DACR_RETUNE_C17_1 0x5020 -#define WM8962_DACR_RETUNE_C17_0 0x5021 -#define WM8962_DACR_RETUNE_C18_1 0x5022 -#define WM8962_DACR_RETUNE_C18_0 0x5023 -#define WM8962_DACR_RETUNE_C19_1 0x5024 -#define WM8962_DACR_RETUNE_C19_0 0x5025 -#define WM8962_DACR_RETUNE_C20_1 0x5026 -#define WM8962_DACR_RETUNE_C20_0 0x5027 -#define WM8962_DACR_RETUNE_C21_1 0x5028 -#define WM8962_DACR_RETUNE_C21_0 0x5029 -#define WM8962_DACR_RETUNE_C22_1 0x502A -#define WM8962_DACR_RETUNE_C22_0 0x502B -#define WM8962_DACR_RETUNE_C23_1 0x502C -#define WM8962_DACR_RETUNE_C23_0 0x502D -#define WM8962_DACR_RETUNE_C24_1 0x502E -#define WM8962_DACR_RETUNE_C24_0 0x502F -#define WM8962_DACR_RETUNE_C25_1 0x5030 -#define WM8962_DACR_RETUNE_C25_0 0x5031 -#define WM8962_DACR_RETUNE_C26_1 0x5032 -#define WM8962_DACR_RETUNE_C26_0 0x5033 -#define WM8962_DACR_RETUNE_C27_1 0x5034 -#define WM8962_DACR_RETUNE_C27_0 0x5035 -#define WM8962_DACR_RETUNE_C28_1 0x5036 -#define WM8962_DACR_RETUNE_C28_0 0x5037 -#define WM8962_DACR_RETUNE_C29_1 0x5038 -#define WM8962_DACR_RETUNE_C29_0 0x5039 -#define WM8962_DACR_RETUNE_C30_1 0x503A -#define WM8962_DACR_RETUNE_C30_0 0x503B -#define WM8962_DACR_RETUNE_C31_1 0x503C -#define WM8962_DACR_RETUNE_C31_0 0x503D -#define WM8962_DACR_RETUNE_C32_1 0x503E -#define WM8962_DACR_RETUNE_C32_0 0x503F -#define WM8962_VSS_XHD2_1 0x5200 -#define WM8962_VSS_XHD2_0 0x5201 -#define WM8962_VSS_XHD3_1 0x5202 -#define WM8962_VSS_XHD3_0 0x5203 -#define WM8962_VSS_XHN1_1 0x5204 -#define WM8962_VSS_XHN1_0 0x5205 -#define WM8962_VSS_XHN2_1 0x5206 -#define WM8962_VSS_XHN2_0 0x5207 -#define WM8962_VSS_XHN3_1 0x5208 -#define WM8962_VSS_XHN3_0 0x5209 -#define WM8962_VSS_XLA_1 0x520A -#define WM8962_VSS_XLA_0 0x520B -#define WM8962_VSS_XLB_1 0x520C -#define WM8962_VSS_XLB_0 0x520D -#define WM8962_VSS_XLG_1 0x520E -#define WM8962_VSS_XLG_0 0x520F -#define WM8962_VSS_PG2_1 0x5210 -#define WM8962_VSS_PG2_0 0x5211 -#define WM8962_VSS_PG_1 0x5212 -#define WM8962_VSS_PG_0 0x5213 -#define WM8962_VSS_XTD1_1 0x5214 -#define WM8962_VSS_XTD1_0 0x5215 -#define WM8962_VSS_XTD2_1 0x5216 -#define WM8962_VSS_XTD2_0 0x5217 -#define WM8962_VSS_XTD3_1 0x5218 -#define WM8962_VSS_XTD3_0 0x5219 -#define WM8962_VSS_XTD4_1 0x521A -#define WM8962_VSS_XTD4_0 0x521B -#define WM8962_VSS_XTD5_1 0x521C -#define WM8962_VSS_XTD5_0 0x521D -#define WM8962_VSS_XTD6_1 0x521E -#define WM8962_VSS_XTD6_0 0x521F -#define WM8962_VSS_XTD7_1 0x5220 -#define WM8962_VSS_XTD7_0 0x5221 -#define WM8962_VSS_XTD8_1 0x5222 -#define WM8962_VSS_XTD8_0 0x5223 -#define WM8962_VSS_XTD9_1 0x5224 -#define WM8962_VSS_XTD9_0 0x5225 -#define WM8962_VSS_XTD10_1 0x5226 -#define WM8962_VSS_XTD10_0 0x5227 -#define WM8962_VSS_XTD11_1 0x5228 -#define WM8962_VSS_XTD11_0 0x5229 -#define WM8962_VSS_XTD12_1 0x522A -#define WM8962_VSS_XTD12_0 0x522B -#define WM8962_VSS_XTD13_1 0x522C -#define WM8962_VSS_XTD13_0 0x522D -#define WM8962_VSS_XTD14_1 0x522E -#define WM8962_VSS_XTD14_0 0x522F -#define WM8962_VSS_XTD15_1 0x5230 -#define WM8962_VSS_XTD15_0 0x5231 -#define WM8962_VSS_XTD16_1 0x5232 -#define WM8962_VSS_XTD16_0 0x5233 -#define WM8962_VSS_XTD17_1 0x5234 -#define WM8962_VSS_XTD17_0 0x5235 -#define WM8962_VSS_XTD18_1 0x5236 -#define WM8962_VSS_XTD18_0 0x5237 -#define WM8962_VSS_XTD19_1 0x5238 -#define WM8962_VSS_XTD19_0 0x5239 -#define WM8962_VSS_XTD20_1 0x523A -#define WM8962_VSS_XTD20_0 0x523B -#define WM8962_VSS_XTD21_1 0x523C -#define WM8962_VSS_XTD21_0 0x523D -#define WM8962_VSS_XTD22_1 0x523E -#define WM8962_VSS_XTD22_0 0x523F -#define WM8962_VSS_XTD23_1 0x5240 -#define WM8962_VSS_XTD23_0 0x5241 -#define WM8962_VSS_XTD24_1 0x5242 -#define WM8962_VSS_XTD24_0 0x5243 -#define WM8962_VSS_XTD25_1 0x5244 -#define WM8962_VSS_XTD25_0 0x5245 -#define WM8962_VSS_XTD26_1 0x5246 -#define WM8962_VSS_XTD26_0 0x5247 -#define WM8962_VSS_XTD27_1 0x5248 -#define WM8962_VSS_XTD27_0 0x5249 -#define WM8962_VSS_XTD28_1 0x524A -#define WM8962_VSS_XTD28_0 0x524B -#define WM8962_VSS_XTD29_1 0x524C -#define WM8962_VSS_XTD29_0 0x524D -#define WM8962_VSS_XTD30_1 0x524E -#define WM8962_VSS_XTD30_0 0x524F -#define WM8962_VSS_XTD31_1 0x5250 -#define WM8962_VSS_XTD31_0 0x5251 -#define WM8962_VSS_XTD32_1 0x5252 -#define WM8962_VSS_XTD32_0 0x5253 -#define WM8962_VSS_XTS1_1 0x5254 -#define WM8962_VSS_XTS1_0 0x5255 -#define WM8962_VSS_XTS2_1 0x5256 -#define WM8962_VSS_XTS2_0 0x5257 -#define WM8962_VSS_XTS3_1 0x5258 -#define WM8962_VSS_XTS3_0 0x5259 -#define WM8962_VSS_XTS4_1 0x525A -#define WM8962_VSS_XTS4_0 0x525B -#define WM8962_VSS_XTS5_1 0x525C -#define WM8962_VSS_XTS5_0 0x525D -#define WM8962_VSS_XTS6_1 0x525E -#define WM8962_VSS_XTS6_0 0x525F -#define WM8962_VSS_XTS7_1 0x5260 -#define WM8962_VSS_XTS7_0 0x5261 -#define WM8962_VSS_XTS8_1 0x5262 -#define WM8962_VSS_XTS8_0 0x5263 -#define WM8962_VSS_XTS9_1 0x5264 -#define WM8962_VSS_XTS9_0 0x5265 -#define WM8962_VSS_XTS10_1 0x5266 -#define WM8962_VSS_XTS10_0 0x5267 -#define WM8962_VSS_XTS11_1 0x5268 -#define WM8962_VSS_XTS11_0 0x5269 -#define WM8962_VSS_XTS12_1 0x526A -#define WM8962_VSS_XTS12_0 0x526B -#define WM8962_VSS_XTS13_1 0x526C -#define WM8962_VSS_XTS13_0 0x526D -#define WM8962_VSS_XTS14_1 0x526E -#define WM8962_VSS_XTS14_0 0x526F -#define WM8962_VSS_XTS15_1 0x5270 -#define WM8962_VSS_XTS15_0 0x5271 -#define WM8962_VSS_XTS16_1 0x5272 -#define WM8962_VSS_XTS16_0 0x5273 -#define WM8962_VSS_XTS17_1 0x5274 -#define WM8962_VSS_XTS17_0 0x5275 -#define WM8962_VSS_XTS18_1 0x5276 -#define WM8962_VSS_XTS18_0 0x5277 -#define WM8962_VSS_XTS19_1 0x5278 -#define WM8962_VSS_XTS19_0 0x5279 -#define WM8962_VSS_XTS20_1 0x527A -#define WM8962_VSS_XTS20_0 0x527B -#define WM8962_VSS_XTS21_1 0x527C -#define WM8962_VSS_XTS21_0 0x527D -#define WM8962_VSS_XTS22_1 0x527E -#define WM8962_VSS_XTS22_0 0x527F -#define WM8962_VSS_XTS23_1 0x5280 -#define WM8962_VSS_XTS23_0 0x5281 -#define WM8962_VSS_XTS24_1 0x5282 -#define WM8962_VSS_XTS24_0 0x5283 -#define WM8962_VSS_XTS25_1 0x5284 -#define WM8962_VSS_XTS25_0 0x5285 -#define WM8962_VSS_XTS26_1 0x5286 -#define WM8962_VSS_XTS26_0 0x5287 -#define WM8962_VSS_XTS27_1 0x5288 -#define WM8962_VSS_XTS27_0 0x5289 -#define WM8962_VSS_XTS28_1 0x528A -#define WM8962_VSS_XTS28_0 0x528B -#define WM8962_VSS_XTS29_1 0x528C -#define WM8962_VSS_XTS29_0 0x528D -#define WM8962_VSS_XTS30_1 0x528E -#define WM8962_VSS_XTS30_0 0x528F -#define WM8962_VSS_XTS31_1 0x5290 -#define WM8962_VSS_XTS31_0 0x5291 -#define WM8962_VSS_XTS32_1 0x5292 -#define WM8962_VSS_XTS32_0 0x5293 - -#define WM8962_REGISTER_COUNT 1138 -#define WM8962_MAX_REGISTER 0x5293 - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Left Input volume - */ -#define WM8962_IN_VU 0x0100 /* IN_VU */ -#define WM8962_IN_VU_MASK 0x0100 /* IN_VU */ -#define WM8962_IN_VU_SHIFT 8 /* IN_VU */ -#define WM8962_IN_VU_WIDTH 1 /* IN_VU */ -#define WM8962_INPGAL_MUTE 0x0080 /* INPGAL_MUTE */ -#define WM8962_INPGAL_MUTE_MASK 0x0080 /* INPGAL_MUTE */ -#define WM8962_INPGAL_MUTE_SHIFT 7 /* INPGAL_MUTE */ -#define WM8962_INPGAL_MUTE_WIDTH 1 /* INPGAL_MUTE */ -#define WM8962_INL_ZC 0x0040 /* INL_ZC */ -#define WM8962_INL_ZC_MASK 0x0040 /* INL_ZC */ -#define WM8962_INL_ZC_SHIFT 6 /* INL_ZC */ -#define WM8962_INL_ZC_WIDTH 1 /* INL_ZC */ -#define WM8962_INL_VOL_MASK 0x003F /* INL_VOL - [5:0] */ -#define WM8962_INL_VOL_SHIFT 0 /* INL_VOL - [5:0] */ -#define WM8962_INL_VOL_WIDTH 6 /* INL_VOL - [5:0] */ - -/* - * R1 (0x01) - Right Input volume - */ -#define WM8962_CUST_ID_MASK 0xF000 /* CUST_ID - [15:12] */ -#define WM8962_CUST_ID_SHIFT 12 /* CUST_ID - [15:12] */ -#define WM8962_CUST_ID_WIDTH 4 /* CUST_ID - [15:12] */ -#define WM8962_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */ -#define WM8962_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */ -#define WM8962_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */ -#define WM8962_IN_VU 0x0100 /* IN_VU */ -#define WM8962_IN_VU_MASK 0x0100 /* IN_VU */ -#define WM8962_IN_VU_SHIFT 8 /* IN_VU */ -#define WM8962_IN_VU_WIDTH 1 /* IN_VU */ -#define WM8962_INPGAR_MUTE 0x0080 /* INPGAR_MUTE */ -#define WM8962_INPGAR_MUTE_MASK 0x0080 /* INPGAR_MUTE */ -#define WM8962_INPGAR_MUTE_SHIFT 7 /* INPGAR_MUTE */ -#define WM8962_INPGAR_MUTE_WIDTH 1 /* INPGAR_MUTE */ -#define WM8962_INR_ZC 0x0040 /* INR_ZC */ -#define WM8962_INR_ZC_MASK 0x0040 /* INR_ZC */ -#define WM8962_INR_ZC_SHIFT 6 /* INR_ZC */ -#define WM8962_INR_ZC_WIDTH 1 /* INR_ZC */ -#define WM8962_INR_VOL_MASK 0x003F /* INR_VOL - [5:0] */ -#define WM8962_INR_VOL_SHIFT 0 /* INR_VOL - [5:0] */ -#define WM8962_INR_VOL_WIDTH 6 /* INR_VOL - [5:0] */ - -/* - * R2 (0x02) - HPOUTL volume - */ -#define WM8962_HPOUT_VU 0x0100 /* HPOUT_VU */ -#define WM8962_HPOUT_VU_MASK 0x0100 /* HPOUT_VU */ -#define WM8962_HPOUT_VU_SHIFT 8 /* HPOUT_VU */ -#define WM8962_HPOUT_VU_WIDTH 1 /* HPOUT_VU */ -#define WM8962_HPOUTL_ZC 0x0080 /* HPOUTL_ZC */ -#define WM8962_HPOUTL_ZC_MASK 0x0080 /* HPOUTL_ZC */ -#define WM8962_HPOUTL_ZC_SHIFT 7 /* HPOUTL_ZC */ -#define WM8962_HPOUTL_ZC_WIDTH 1 /* HPOUTL_ZC */ -#define WM8962_HPOUTL_VOL_MASK 0x007F /* HPOUTL_VOL - [6:0] */ -#define WM8962_HPOUTL_VOL_SHIFT 0 /* HPOUTL_VOL - [6:0] */ -#define WM8962_HPOUTL_VOL_WIDTH 7 /* HPOUTL_VOL - [6:0] */ - -/* - * R3 (0x03) - HPOUTR volume - */ -#define WM8962_HPOUT_VU 0x0100 /* HPOUT_VU */ -#define WM8962_HPOUT_VU_MASK 0x0100 /* HPOUT_VU */ -#define WM8962_HPOUT_VU_SHIFT 8 /* HPOUT_VU */ -#define WM8962_HPOUT_VU_WIDTH 1 /* HPOUT_VU */ -#define WM8962_HPOUTR_ZC 0x0080 /* HPOUTR_ZC */ -#define WM8962_HPOUTR_ZC_MASK 0x0080 /* HPOUTR_ZC */ -#define WM8962_HPOUTR_ZC_SHIFT 7 /* HPOUTR_ZC */ -#define WM8962_HPOUTR_ZC_WIDTH 1 /* HPOUTR_ZC */ -#define WM8962_HPOUTR_VOL_MASK 0x007F /* HPOUTR_VOL - [6:0] */ -#define WM8962_HPOUTR_VOL_SHIFT 0 /* HPOUTR_VOL - [6:0] */ -#define WM8962_HPOUTR_VOL_WIDTH 7 /* HPOUTR_VOL - [6:0] */ - -/* - * R4 (0x04) - Clocking1 - */ -#define WM8962_DSPCLK_DIV_MASK 0x0600 /* DSPCLK_DIV - [10:9] */ -#define WM8962_DSPCLK_DIV_SHIFT 9 /* DSPCLK_DIV - [10:9] */ -#define WM8962_DSPCLK_DIV_WIDTH 2 /* DSPCLK_DIV - [10:9] */ -#define WM8962_ADCSYS_CLK_DIV_MASK 0x01C0 /* ADCSYS_CLK_DIV - [8:6] */ -#define WM8962_ADCSYS_CLK_DIV_SHIFT 6 /* ADCSYS_CLK_DIV - [8:6] */ -#define WM8962_ADCSYS_CLK_DIV_WIDTH 3 /* ADCSYS_CLK_DIV - [8:6] */ -#define WM8962_DACSYS_CLK_DIV_MASK 0x0038 /* DACSYS_CLK_DIV - [5:3] */ -#define WM8962_DACSYS_CLK_DIV_SHIFT 3 /* DACSYS_CLK_DIV - [5:3] */ -#define WM8962_DACSYS_CLK_DIV_WIDTH 3 /* DACSYS_CLK_DIV - [5:3] */ -#define WM8962_MCLKDIV_MASK 0x0006 /* MCLKDIV - [2:1] */ -#define WM8962_MCLKDIV_SHIFT 1 /* MCLKDIV - [2:1] */ -#define WM8962_MCLKDIV_WIDTH 2 /* MCLKDIV - [2:1] */ - -/* - * R5 (0x05) - ADC & DAC Control 1 - */ -#define WM8962_ADCR_DAT_INV 0x0040 /* ADCR_DAT_INV */ -#define WM8962_ADCR_DAT_INV_MASK 0x0040 /* ADCR_DAT_INV */ -#define WM8962_ADCR_DAT_INV_SHIFT 6 /* ADCR_DAT_INV */ -#define WM8962_ADCR_DAT_INV_WIDTH 1 /* ADCR_DAT_INV */ -#define WM8962_ADCL_DAT_INV 0x0020 /* ADCL_DAT_INV */ -#define WM8962_ADCL_DAT_INV_MASK 0x0020 /* ADCL_DAT_INV */ -#define WM8962_ADCL_DAT_INV_SHIFT 5 /* ADCL_DAT_INV */ -#define WM8962_ADCL_DAT_INV_WIDTH 1 /* ADCL_DAT_INV */ -#define WM8962_DAC_MUTE_RAMP 0x0010 /* DAC_MUTE_RAMP */ -#define WM8962_DAC_MUTE_RAMP_MASK 0x0010 /* DAC_MUTE_RAMP */ -#define WM8962_DAC_MUTE_RAMP_SHIFT 4 /* DAC_MUTE_RAMP */ -#define WM8962_DAC_MUTE_RAMP_WIDTH 1 /* DAC_MUTE_RAMP */ -#define WM8962_DAC_MUTE 0x0008 /* DAC_MUTE */ -#define WM8962_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */ -#define WM8962_DAC_MUTE_SHIFT 3 /* DAC_MUTE */ -#define WM8962_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ -#define WM8962_DAC_DEEMP_MASK 0x0006 /* DAC_DEEMP - [2:1] */ -#define WM8962_DAC_DEEMP_SHIFT 1 /* DAC_DEEMP - [2:1] */ -#define WM8962_DAC_DEEMP_WIDTH 2 /* DAC_DEEMP - [2:1] */ -#define WM8962_ADC_HPF_DIS 0x0001 /* ADC_HPF_DIS */ -#define WM8962_ADC_HPF_DIS_MASK 0x0001 /* ADC_HPF_DIS */ -#define WM8962_ADC_HPF_DIS_SHIFT 0 /* ADC_HPF_DIS */ -#define WM8962_ADC_HPF_DIS_WIDTH 1 /* ADC_HPF_DIS */ - -/* - * R6 (0x06) - ADC & DAC Control 2 - */ -#define WM8962_ADC_HPF_SR_MASK 0x3000 /* ADC_HPF_SR - [13:12] */ -#define WM8962_ADC_HPF_SR_SHIFT 12 /* ADC_HPF_SR - [13:12] */ -#define WM8962_ADC_HPF_SR_WIDTH 2 /* ADC_HPF_SR - [13:12] */ -#define WM8962_ADC_HPF_MODE 0x0400 /* ADC_HPF_MODE */ -#define WM8962_ADC_HPF_MODE_MASK 0x0400 /* ADC_HPF_MODE */ -#define WM8962_ADC_HPF_MODE_SHIFT 10 /* ADC_HPF_MODE */ -#define WM8962_ADC_HPF_MODE_WIDTH 1 /* ADC_HPF_MODE */ -#define WM8962_ADC_HPF_CUT_MASK 0x0380 /* ADC_HPF_CUT - [9:7] */ -#define WM8962_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [9:7] */ -#define WM8962_ADC_HPF_CUT_WIDTH 3 /* ADC_HPF_CUT - [9:7] */ -#define WM8962_DACR_DAT_INV 0x0040 /* DACR_DAT_INV */ -#define WM8962_DACR_DAT_INV_MASK 0x0040 /* DACR_DAT_INV */ -#define WM8962_DACR_DAT_INV_SHIFT 6 /* DACR_DAT_INV */ -#define WM8962_DACR_DAT_INV_WIDTH 1 /* DACR_DAT_INV */ -#define WM8962_DACL_DAT_INV 0x0020 /* DACL_DAT_INV */ -#define WM8962_DACL_DAT_INV_MASK 0x0020 /* DACL_DAT_INV */ -#define WM8962_DACL_DAT_INV_SHIFT 5 /* DACL_DAT_INV */ -#define WM8962_DACL_DAT_INV_WIDTH 1 /* DACL_DAT_INV */ -#define WM8962_DAC_UNMUTE_RAMP 0x0008 /* DAC_UNMUTE_RAMP */ -#define WM8962_DAC_UNMUTE_RAMP_MASK 0x0008 /* DAC_UNMUTE_RAMP */ -#define WM8962_DAC_UNMUTE_RAMP_SHIFT 3 /* DAC_UNMUTE_RAMP */ -#define WM8962_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */ -#define WM8962_DAC_MUTERATE 0x0004 /* DAC_MUTERATE */ -#define WM8962_DAC_MUTERATE_MASK 0x0004 /* DAC_MUTERATE */ -#define WM8962_DAC_MUTERATE_SHIFT 2 /* DAC_MUTERATE */ -#define WM8962_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ -#define WM8962_DAC_HP 0x0001 /* DAC_HP */ -#define WM8962_DAC_HP_MASK 0x0001 /* DAC_HP */ -#define WM8962_DAC_HP_SHIFT 0 /* DAC_HP */ -#define WM8962_DAC_HP_WIDTH 1 /* DAC_HP */ - -/* - * R7 (0x07) - Audio Interface 0 - */ -#define WM8962_AIFDAC_TDM_MODE 0x1000 /* AIFDAC_TDM_MODE */ -#define WM8962_AIFDAC_TDM_MODE_MASK 0x1000 /* AIFDAC_TDM_MODE */ -#define WM8962_AIFDAC_TDM_MODE_SHIFT 12 /* AIFDAC_TDM_MODE */ -#define WM8962_AIFDAC_TDM_MODE_WIDTH 1 /* AIFDAC_TDM_MODE */ -#define WM8962_AIFDAC_TDM_SLOT 0x0800 /* AIFDAC_TDM_SLOT */ -#define WM8962_AIFDAC_TDM_SLOT_MASK 0x0800 /* AIFDAC_TDM_SLOT */ -#define WM8962_AIFDAC_TDM_SLOT_SHIFT 11 /* AIFDAC_TDM_SLOT */ -#define WM8962_AIFDAC_TDM_SLOT_WIDTH 1 /* AIFDAC_TDM_SLOT */ -#define WM8962_AIFADC_TDM_MODE 0x0400 /* AIFADC_TDM_MODE */ -#define WM8962_AIFADC_TDM_MODE_MASK 0x0400 /* AIFADC_TDM_MODE */ -#define WM8962_AIFADC_TDM_MODE_SHIFT 10 /* AIFADC_TDM_MODE */ -#define WM8962_AIFADC_TDM_MODE_WIDTH 1 /* AIFADC_TDM_MODE */ -#define WM8962_AIFADC_TDM_SLOT 0x0200 /* AIFADC_TDM_SLOT */ -#define WM8962_AIFADC_TDM_SLOT_MASK 0x0200 /* AIFADC_TDM_SLOT */ -#define WM8962_AIFADC_TDM_SLOT_SHIFT 9 /* AIFADC_TDM_SLOT */ -#define WM8962_AIFADC_TDM_SLOT_WIDTH 1 /* AIFADC_TDM_SLOT */ -#define WM8962_ADC_LRSWAP 0x0100 /* ADC_LRSWAP */ -#define WM8962_ADC_LRSWAP_MASK 0x0100 /* ADC_LRSWAP */ -#define WM8962_ADC_LRSWAP_SHIFT 8 /* ADC_LRSWAP */ -#define WM8962_ADC_LRSWAP_WIDTH 1 /* ADC_LRSWAP */ -#define WM8962_BCLK_INV 0x0080 /* BCLK_INV */ -#define WM8962_BCLK_INV_MASK 0x0080 /* BCLK_INV */ -#define WM8962_BCLK_INV_SHIFT 7 /* BCLK_INV */ -#define WM8962_BCLK_INV_WIDTH 1 /* BCLK_INV */ -#define WM8962_MSTR 0x0040 /* MSTR */ -#define WM8962_MSTR_MASK 0x0040 /* MSTR */ -#define WM8962_MSTR_SHIFT 6 /* MSTR */ -#define WM8962_MSTR_WIDTH 1 /* MSTR */ -#define WM8962_DAC_LRSWAP 0x0020 /* DAC_LRSWAP */ -#define WM8962_DAC_LRSWAP_MASK 0x0020 /* DAC_LRSWAP */ -#define WM8962_DAC_LRSWAP_SHIFT 5 /* DAC_LRSWAP */ -#define WM8962_DAC_LRSWAP_WIDTH 1 /* DAC_LRSWAP */ -#define WM8962_LRCLK_INV 0x0010 /* LRCLK_INV */ -#define WM8962_LRCLK_INV_MASK 0x0010 /* LRCLK_INV */ -#define WM8962_LRCLK_INV_SHIFT 4 /* LRCLK_INV */ -#define WM8962_LRCLK_INV_WIDTH 1 /* LRCLK_INV */ -#define WM8962_WL_MASK 0x000C /* WL - [3:2] */ -#define WM8962_WL_SHIFT 2 /* WL - [3:2] */ -#define WM8962_WL_WIDTH 2 /* WL - [3:2] */ -#define WM8962_FMT_MASK 0x0003 /* FMT - [1:0] */ -#define WM8962_FMT_SHIFT 0 /* FMT - [1:0] */ -#define WM8962_FMT_WIDTH 2 /* FMT - [1:0] */ - -/* - * R8 (0x08) - Clocking2 - */ -#define WM8962_CLKREG_OVD 0x0800 /* CLKREG_OVD */ -#define WM8962_CLKREG_OVD_MASK 0x0800 /* CLKREG_OVD */ -#define WM8962_CLKREG_OVD_SHIFT 11 /* CLKREG_OVD */ -#define WM8962_CLKREG_OVD_WIDTH 1 /* CLKREG_OVD */ -#define WM8962_SYSCLK_SRC_MASK 0x0600 /* SYSCLK_SRC - [10:9] */ -#define WM8962_SYSCLK_SRC_SHIFT 9 /* SYSCLK_SRC - [10:9] */ -#define WM8962_SYSCLK_SRC_WIDTH 2 /* SYSCLK_SRC - [10:9] */ -#define WM8962_CLASSD_CLK_DIV_MASK 0x01C0 /* CLASSD_CLK_DIV - [8:6] */ -#define WM8962_CLASSD_CLK_DIV_SHIFT 6 /* CLASSD_CLK_DIV - [8:6] */ -#define WM8962_CLASSD_CLK_DIV_WIDTH 3 /* CLASSD_CLK_DIV - [8:6] */ -#define WM8962_SYSCLK_ENA 0x0020 /* SYSCLK_ENA */ -#define WM8962_SYSCLK_ENA_MASK 0x0020 /* SYSCLK_ENA */ -#define WM8962_SYSCLK_ENA_SHIFT 5 /* SYSCLK_ENA */ -#define WM8962_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */ -#define WM8962_BCLK_DIV_MASK 0x000F /* BCLK_DIV - [3:0] */ -#define WM8962_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [3:0] */ -#define WM8962_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [3:0] */ - -/* - * R9 (0x09) - Audio Interface 1 - */ -#define WM8962_AUTOMUTE_STS 0x0800 /* AUTOMUTE_STS */ -#define WM8962_AUTOMUTE_STS_MASK 0x0800 /* AUTOMUTE_STS */ -#define WM8962_AUTOMUTE_STS_SHIFT 11 /* AUTOMUTE_STS */ -#define WM8962_AUTOMUTE_STS_WIDTH 1 /* AUTOMUTE_STS */ -#define WM8962_DAC_AUTOMUTE_SAMPLES_MASK 0x0300 /* DAC_AUTOMUTE_SAMPLES - [9:8] */ -#define WM8962_DAC_AUTOMUTE_SAMPLES_SHIFT 8 /* DAC_AUTOMUTE_SAMPLES - [9:8] */ -#define WM8962_DAC_AUTOMUTE_SAMPLES_WIDTH 2 /* DAC_AUTOMUTE_SAMPLES - [9:8] */ -#define WM8962_DAC_AUTOMUTE 0x0080 /* DAC_AUTOMUTE */ -#define WM8962_DAC_AUTOMUTE_MASK 0x0080 /* DAC_AUTOMUTE */ -#define WM8962_DAC_AUTOMUTE_SHIFT 7 /* DAC_AUTOMUTE */ -#define WM8962_DAC_AUTOMUTE_WIDTH 1 /* DAC_AUTOMUTE */ -#define WM8962_DAC_COMP 0x0010 /* DAC_COMP */ -#define WM8962_DAC_COMP_MASK 0x0010 /* DAC_COMP */ -#define WM8962_DAC_COMP_SHIFT 4 /* DAC_COMP */ -#define WM8962_DAC_COMP_WIDTH 1 /* DAC_COMP */ -#define WM8962_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */ -#define WM8962_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */ -#define WM8962_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */ -#define WM8962_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ -#define WM8962_ADC_COMP 0x0004 /* ADC_COMP */ -#define WM8962_ADC_COMP_MASK 0x0004 /* ADC_COMP */ -#define WM8962_ADC_COMP_SHIFT 2 /* ADC_COMP */ -#define WM8962_ADC_COMP_WIDTH 1 /* ADC_COMP */ -#define WM8962_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */ -#define WM8962_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */ -#define WM8962_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */ -#define WM8962_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */ -#define WM8962_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8962_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8962_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8962_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R10 (0x0A) - Left DAC volume - */ -#define WM8962_DAC_VU 0x0100 /* DAC_VU */ -#define WM8962_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8962_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8962_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8962_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ -#define WM8962_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */ -#define WM8962_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */ - -/* - * R11 (0x0B) - Right DAC volume - */ -#define WM8962_DAC_VU 0x0100 /* DAC_VU */ -#define WM8962_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8962_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8962_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8962_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ -#define WM8962_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */ -#define WM8962_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */ - -/* - * R14 (0x0E) - Audio Interface 2 - */ -#define WM8962_AIF_RATE_MASK 0x07FF /* AIF_RATE - [10:0] */ -#define WM8962_AIF_RATE_SHIFT 0 /* AIF_RATE - [10:0] */ -#define WM8962_AIF_RATE_WIDTH 11 /* AIF_RATE - [10:0] */ - -/* - * R15 (0x0F) - Software Reset - */ -#define WM8962_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ -#define WM8962_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ -#define WM8962_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ - -/* - * R17 (0x11) - ALC1 - */ -#define WM8962_ALC_INACTIVE_ENA 0x0400 /* ALC_INACTIVE_ENA */ -#define WM8962_ALC_INACTIVE_ENA_MASK 0x0400 /* ALC_INACTIVE_ENA */ -#define WM8962_ALC_INACTIVE_ENA_SHIFT 10 /* ALC_INACTIVE_ENA */ -#define WM8962_ALC_INACTIVE_ENA_WIDTH 1 /* ALC_INACTIVE_ENA */ -#define WM8962_ALC_LVL_MODE 0x0200 /* ALC_LVL_MODE */ -#define WM8962_ALC_LVL_MODE_MASK 0x0200 /* ALC_LVL_MODE */ -#define WM8962_ALC_LVL_MODE_SHIFT 9 /* ALC_LVL_MODE */ -#define WM8962_ALC_LVL_MODE_WIDTH 1 /* ALC_LVL_MODE */ -#define WM8962_ALCL_ENA 0x0100 /* ALCL_ENA */ -#define WM8962_ALCL_ENA_MASK 0x0100 /* ALCL_ENA */ -#define WM8962_ALCL_ENA_SHIFT 8 /* ALCL_ENA */ -#define WM8962_ALCL_ENA_WIDTH 1 /* ALCL_ENA */ -#define WM8962_ALCR_ENA 0x0080 /* ALCR_ENA */ -#define WM8962_ALCR_ENA_MASK 0x0080 /* ALCR_ENA */ -#define WM8962_ALCR_ENA_SHIFT 7 /* ALCR_ENA */ -#define WM8962_ALCR_ENA_WIDTH 1 /* ALCR_ENA */ -#define WM8962_ALC_MAXGAIN_MASK 0x0070 /* ALC_MAXGAIN - [6:4] */ -#define WM8962_ALC_MAXGAIN_SHIFT 4 /* ALC_MAXGAIN - [6:4] */ -#define WM8962_ALC_MAXGAIN_WIDTH 3 /* ALC_MAXGAIN - [6:4] */ -#define WM8962_ALC_LVL_MASK 0x000F /* ALC_LVL - [3:0] */ -#define WM8962_ALC_LVL_SHIFT 0 /* ALC_LVL - [3:0] */ -#define WM8962_ALC_LVL_WIDTH 4 /* ALC_LVL - [3:0] */ - -/* - * R18 (0x12) - ALC2 - */ -#define WM8962_ALC_LOCK_STS 0x8000 /* ALC_LOCK_STS */ -#define WM8962_ALC_LOCK_STS_MASK 0x8000 /* ALC_LOCK_STS */ -#define WM8962_ALC_LOCK_STS_SHIFT 15 /* ALC_LOCK_STS */ -#define WM8962_ALC_LOCK_STS_WIDTH 1 /* ALC_LOCK_STS */ -#define WM8962_ALC_THRESH_STS 0x4000 /* ALC_THRESH_STS */ -#define WM8962_ALC_THRESH_STS_MASK 0x4000 /* ALC_THRESH_STS */ -#define WM8962_ALC_THRESH_STS_SHIFT 14 /* ALC_THRESH_STS */ -#define WM8962_ALC_THRESH_STS_WIDTH 1 /* ALC_THRESH_STS */ -#define WM8962_ALC_SAT_STS 0x2000 /* ALC_SAT_STS */ -#define WM8962_ALC_SAT_STS_MASK 0x2000 /* ALC_SAT_STS */ -#define WM8962_ALC_SAT_STS_SHIFT 13 /* ALC_SAT_STS */ -#define WM8962_ALC_SAT_STS_WIDTH 1 /* ALC_SAT_STS */ -#define WM8962_ALC_PKOVR_STS 0x1000 /* ALC_PKOVR_STS */ -#define WM8962_ALC_PKOVR_STS_MASK 0x1000 /* ALC_PKOVR_STS */ -#define WM8962_ALC_PKOVR_STS_SHIFT 12 /* ALC_PKOVR_STS */ -#define WM8962_ALC_PKOVR_STS_WIDTH 1 /* ALC_PKOVR_STS */ -#define WM8962_ALC_NGATE_STS 0x0800 /* ALC_NGATE_STS */ -#define WM8962_ALC_NGATE_STS_MASK 0x0800 /* ALC_NGATE_STS */ -#define WM8962_ALC_NGATE_STS_SHIFT 11 /* ALC_NGATE_STS */ -#define WM8962_ALC_NGATE_STS_WIDTH 1 /* ALC_NGATE_STS */ -#define WM8962_ALC_ZC 0x0080 /* ALC_ZC */ -#define WM8962_ALC_ZC_MASK 0x0080 /* ALC_ZC */ -#define WM8962_ALC_ZC_SHIFT 7 /* ALC_ZC */ -#define WM8962_ALC_ZC_WIDTH 1 /* ALC_ZC */ -#define WM8962_ALC_MINGAIN_MASK 0x0070 /* ALC_MINGAIN - [6:4] */ -#define WM8962_ALC_MINGAIN_SHIFT 4 /* ALC_MINGAIN - [6:4] */ -#define WM8962_ALC_MINGAIN_WIDTH 3 /* ALC_MINGAIN - [6:4] */ -#define WM8962_ALC_HLD_MASK 0x000F /* ALC_HLD - [3:0] */ -#define WM8962_ALC_HLD_SHIFT 0 /* ALC_HLD - [3:0] */ -#define WM8962_ALC_HLD_WIDTH 4 /* ALC_HLD - [3:0] */ - -/* - * R19 (0x13) - ALC3 - */ -#define WM8962_ALC_NGATE_GAIN_MASK 0x1C00 /* ALC_NGATE_GAIN - [12:10] */ -#define WM8962_ALC_NGATE_GAIN_SHIFT 10 /* ALC_NGATE_GAIN - [12:10] */ -#define WM8962_ALC_NGATE_GAIN_WIDTH 3 /* ALC_NGATE_GAIN - [12:10] */ -#define WM8962_ALC_MODE 0x0100 /* ALC_MODE */ -#define WM8962_ALC_MODE_MASK 0x0100 /* ALC_MODE */ -#define WM8962_ALC_MODE_SHIFT 8 /* ALC_MODE */ -#define WM8962_ALC_MODE_WIDTH 1 /* ALC_MODE */ -#define WM8962_ALC_DCY_MASK 0x00F0 /* ALC_DCY - [7:4] */ -#define WM8962_ALC_DCY_SHIFT 4 /* ALC_DCY - [7:4] */ -#define WM8962_ALC_DCY_WIDTH 4 /* ALC_DCY - [7:4] */ -#define WM8962_ALC_ATK_MASK 0x000F /* ALC_ATK - [3:0] */ -#define WM8962_ALC_ATK_SHIFT 0 /* ALC_ATK - [3:0] */ -#define WM8962_ALC_ATK_WIDTH 4 /* ALC_ATK - [3:0] */ - -/* - * R20 (0x14) - Noise Gate - */ -#define WM8962_ALC_NGATE_DCY_MASK 0xF000 /* ALC_NGATE_DCY - [15:12] */ -#define WM8962_ALC_NGATE_DCY_SHIFT 12 /* ALC_NGATE_DCY - [15:12] */ -#define WM8962_ALC_NGATE_DCY_WIDTH 4 /* ALC_NGATE_DCY - [15:12] */ -#define WM8962_ALC_NGATE_ATK_MASK 0x0F00 /* ALC_NGATE_ATK - [11:8] */ -#define WM8962_ALC_NGATE_ATK_SHIFT 8 /* ALC_NGATE_ATK - [11:8] */ -#define WM8962_ALC_NGATE_ATK_WIDTH 4 /* ALC_NGATE_ATK - [11:8] */ -#define WM8962_ALC_NGATE_THR_MASK 0x00F8 /* ALC_NGATE_THR - [7:3] */ -#define WM8962_ALC_NGATE_THR_SHIFT 3 /* ALC_NGATE_THR - [7:3] */ -#define WM8962_ALC_NGATE_THR_WIDTH 5 /* ALC_NGATE_THR - [7:3] */ -#define WM8962_ALC_NGATE_MODE_MASK 0x0006 /* ALC_NGATE_MODE - [2:1] */ -#define WM8962_ALC_NGATE_MODE_SHIFT 1 /* ALC_NGATE_MODE - [2:1] */ -#define WM8962_ALC_NGATE_MODE_WIDTH 2 /* ALC_NGATE_MODE - [2:1] */ -#define WM8962_ALC_NGATE_ENA 0x0001 /* ALC_NGATE_ENA */ -#define WM8962_ALC_NGATE_ENA_MASK 0x0001 /* ALC_NGATE_ENA */ -#define WM8962_ALC_NGATE_ENA_SHIFT 0 /* ALC_NGATE_ENA */ -#define WM8962_ALC_NGATE_ENA_WIDTH 1 /* ALC_NGATE_ENA */ - -/* - * R21 (0x15) - Left ADC volume - */ -#define WM8962_ADC_VU 0x0100 /* ADC_VU */ -#define WM8962_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8962_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8962_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8962_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ -#define WM8962_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */ -#define WM8962_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */ - -/* - * R22 (0x16) - Right ADC volume - */ -#define WM8962_ADC_VU 0x0100 /* ADC_VU */ -#define WM8962_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8962_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8962_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8962_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ -#define WM8962_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */ -#define WM8962_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */ - -/* - * R23 (0x17) - Additional control(1) - */ -#define WM8962_THERR_ACT 0x0100 /* THERR_ACT */ -#define WM8962_THERR_ACT_MASK 0x0100 /* THERR_ACT */ -#define WM8962_THERR_ACT_SHIFT 8 /* THERR_ACT */ -#define WM8962_THERR_ACT_WIDTH 1 /* THERR_ACT */ -#define WM8962_ADC_BIAS 0x0040 /* ADC_BIAS */ -#define WM8962_ADC_BIAS_MASK 0x0040 /* ADC_BIAS */ -#define WM8962_ADC_BIAS_SHIFT 6 /* ADC_BIAS */ -#define WM8962_ADC_BIAS_WIDTH 1 /* ADC_BIAS */ -#define WM8962_ADC_HP 0x0020 /* ADC_HP */ -#define WM8962_ADC_HP_MASK 0x0020 /* ADC_HP */ -#define WM8962_ADC_HP_SHIFT 5 /* ADC_HP */ -#define WM8962_ADC_HP_WIDTH 1 /* ADC_HP */ -#define WM8962_TOCLK_ENA 0x0001 /* TOCLK_ENA */ -#define WM8962_TOCLK_ENA_MASK 0x0001 /* TOCLK_ENA */ -#define WM8962_TOCLK_ENA_SHIFT 0 /* TOCLK_ENA */ -#define WM8962_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ - -/* - * R24 (0x18) - Additional control(2) - */ -#define WM8962_AIF_TRI 0x0008 /* AIF_TRI */ -#define WM8962_AIF_TRI_MASK 0x0008 /* AIF_TRI */ -#define WM8962_AIF_TRI_SHIFT 3 /* AIF_TRI */ -#define WM8962_AIF_TRI_WIDTH 1 /* AIF_TRI */ - -/* - * R25 (0x19) - Pwr Mgmt (1) - */ -#define WM8962_DMIC_ENA 0x0400 /* DMIC_ENA */ -#define WM8962_DMIC_ENA_MASK 0x0400 /* DMIC_ENA */ -#define WM8962_DMIC_ENA_SHIFT 10 /* DMIC_ENA */ -#define WM8962_DMIC_ENA_WIDTH 1 /* DMIC_ENA */ -#define WM8962_OPCLK_ENA 0x0200 /* OPCLK_ENA */ -#define WM8962_OPCLK_ENA_MASK 0x0200 /* OPCLK_ENA */ -#define WM8962_OPCLK_ENA_SHIFT 9 /* OPCLK_ENA */ -#define WM8962_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ -#define WM8962_VMID_SEL_MASK 0x0180 /* VMID_SEL - [8:7] */ -#define WM8962_VMID_SEL_SHIFT 7 /* VMID_SEL - [8:7] */ -#define WM8962_VMID_SEL_WIDTH 2 /* VMID_SEL - [8:7] */ -#define WM8962_BIAS_ENA 0x0040 /* BIAS_ENA */ -#define WM8962_BIAS_ENA_MASK 0x0040 /* BIAS_ENA */ -#define WM8962_BIAS_ENA_SHIFT 6 /* BIAS_ENA */ -#define WM8962_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ -#define WM8962_INL_ENA 0x0020 /* INL_ENA */ -#define WM8962_INL_ENA_MASK 0x0020 /* INL_ENA */ -#define WM8962_INL_ENA_SHIFT 5 /* INL_ENA */ -#define WM8962_INL_ENA_WIDTH 1 /* INL_ENA */ -#define WM8962_INR_ENA 0x0010 /* INR_ENA */ -#define WM8962_INR_ENA_MASK 0x0010 /* INR_ENA */ -#define WM8962_INR_ENA_SHIFT 4 /* INR_ENA */ -#define WM8962_INR_ENA_WIDTH 1 /* INR_ENA */ -#define WM8962_ADCL_ENA 0x0008 /* ADCL_ENA */ -#define WM8962_ADCL_ENA_MASK 0x0008 /* ADCL_ENA */ -#define WM8962_ADCL_ENA_SHIFT 3 /* ADCL_ENA */ -#define WM8962_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ -#define WM8962_ADCR_ENA 0x0004 /* ADCR_ENA */ -#define WM8962_ADCR_ENA_MASK 0x0004 /* ADCR_ENA */ -#define WM8962_ADCR_ENA_SHIFT 2 /* ADCR_ENA */ -#define WM8962_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ -#define WM8962_MICBIAS_ENA 0x0002 /* MICBIAS_ENA */ -#define WM8962_MICBIAS_ENA_MASK 0x0002 /* MICBIAS_ENA */ -#define WM8962_MICBIAS_ENA_SHIFT 1 /* MICBIAS_ENA */ -#define WM8962_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */ - -/* - * R26 (0x1A) - Pwr Mgmt (2) - */ -#define WM8962_DACL_ENA 0x0100 /* DACL_ENA */ -#define WM8962_DACL_ENA_MASK 0x0100 /* DACL_ENA */ -#define WM8962_DACL_ENA_SHIFT 8 /* DACL_ENA */ -#define WM8962_DACL_ENA_WIDTH 1 /* DACL_ENA */ -#define WM8962_DACR_ENA 0x0080 /* DACR_ENA */ -#define WM8962_DACR_ENA_MASK 0x0080 /* DACR_ENA */ -#define WM8962_DACR_ENA_SHIFT 7 /* DACR_ENA */ -#define WM8962_DACR_ENA_WIDTH 1 /* DACR_ENA */ -#define WM8962_HPOUTL_PGA_ENA 0x0040 /* HPOUTL_PGA_ENA */ -#define WM8962_HPOUTL_PGA_ENA_MASK 0x0040 /* HPOUTL_PGA_ENA */ -#define WM8962_HPOUTL_PGA_ENA_SHIFT 6 /* HPOUTL_PGA_ENA */ -#define WM8962_HPOUTL_PGA_ENA_WIDTH 1 /* HPOUTL_PGA_ENA */ -#define WM8962_HPOUTR_PGA_ENA 0x0020 /* HPOUTR_PGA_ENA */ -#define WM8962_HPOUTR_PGA_ENA_MASK 0x0020 /* HPOUTR_PGA_ENA */ -#define WM8962_HPOUTR_PGA_ENA_SHIFT 5 /* HPOUTR_PGA_ENA */ -#define WM8962_HPOUTR_PGA_ENA_WIDTH 1 /* HPOUTR_PGA_ENA */ -#define WM8962_SPKOUTL_PGA_ENA 0x0010 /* SPKOUTL_PGA_ENA */ -#define WM8962_SPKOUTL_PGA_ENA_MASK 0x0010 /* SPKOUTL_PGA_ENA */ -#define WM8962_SPKOUTL_PGA_ENA_SHIFT 4 /* SPKOUTL_PGA_ENA */ -#define WM8962_SPKOUTL_PGA_ENA_WIDTH 1 /* SPKOUTL_PGA_ENA */ -#define WM8962_SPKOUTR_PGA_ENA 0x0008 /* SPKOUTR_PGA_ENA */ -#define WM8962_SPKOUTR_PGA_ENA_MASK 0x0008 /* SPKOUTR_PGA_ENA */ -#define WM8962_SPKOUTR_PGA_ENA_SHIFT 3 /* SPKOUTR_PGA_ENA */ -#define WM8962_SPKOUTR_PGA_ENA_WIDTH 1 /* SPKOUTR_PGA_ENA */ -#define WM8962_HPOUTL_PGA_MUTE 0x0002 /* HPOUTL_PGA_MUTE */ -#define WM8962_HPOUTL_PGA_MUTE_MASK 0x0002 /* HPOUTL_PGA_MUTE */ -#define WM8962_HPOUTL_PGA_MUTE_SHIFT 1 /* HPOUTL_PGA_MUTE */ -#define WM8962_HPOUTL_PGA_MUTE_WIDTH 1 /* HPOUTL_PGA_MUTE */ -#define WM8962_HPOUTR_PGA_MUTE 0x0001 /* HPOUTR_PGA_MUTE */ -#define WM8962_HPOUTR_PGA_MUTE_MASK 0x0001 /* HPOUTR_PGA_MUTE */ -#define WM8962_HPOUTR_PGA_MUTE_SHIFT 0 /* HPOUTR_PGA_MUTE */ -#define WM8962_HPOUTR_PGA_MUTE_WIDTH 1 /* HPOUTR_PGA_MUTE */ - -/* - * R27 (0x1B) - Additional Control (3) - */ -#define WM8962_SAMPLE_RATE_INT_MODE 0x0010 /* SAMPLE_RATE_INT_MODE */ -#define WM8962_SAMPLE_RATE_INT_MODE_MASK 0x0010 /* SAMPLE_RATE_INT_MODE */ -#define WM8962_SAMPLE_RATE_INT_MODE_SHIFT 4 /* SAMPLE_RATE_INT_MODE */ -#define WM8962_SAMPLE_RATE_INT_MODE_WIDTH 1 /* SAMPLE_RATE_INT_MODE */ -#define WM8962_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */ -#define WM8962_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */ -#define WM8962_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */ - -/* - * R28 (0x1C) - Anti-pop - */ -#define WM8962_STARTUP_BIAS_ENA 0x0010 /* STARTUP_BIAS_ENA */ -#define WM8962_STARTUP_BIAS_ENA_MASK 0x0010 /* STARTUP_BIAS_ENA */ -#define WM8962_STARTUP_BIAS_ENA_SHIFT 4 /* STARTUP_BIAS_ENA */ -#define WM8962_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ -#define WM8962_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */ -#define WM8962_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */ -#define WM8962_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */ -#define WM8962_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ -#define WM8962_VMID_RAMP 0x0004 /* VMID_RAMP */ -#define WM8962_VMID_RAMP_MASK 0x0004 /* VMID_RAMP */ -#define WM8962_VMID_RAMP_SHIFT 2 /* VMID_RAMP */ -#define WM8962_VMID_RAMP_WIDTH 1 /* VMID_RAMP */ - -/* - * R30 (0x1E) - Clocking 3 - */ -#define WM8962_DBCLK_DIV_MASK 0xE000 /* DBCLK_DIV - [15:13] */ -#define WM8962_DBCLK_DIV_SHIFT 13 /* DBCLK_DIV - [15:13] */ -#define WM8962_DBCLK_DIV_WIDTH 3 /* DBCLK_DIV - [15:13] */ -#define WM8962_OPCLK_DIV_MASK 0x1C00 /* OPCLK_DIV - [12:10] */ -#define WM8962_OPCLK_DIV_SHIFT 10 /* OPCLK_DIV - [12:10] */ -#define WM8962_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [12:10] */ -#define WM8962_TOCLK_DIV_MASK 0x0380 /* TOCLK_DIV - [9:7] */ -#define WM8962_TOCLK_DIV_SHIFT 7 /* TOCLK_DIV - [9:7] */ -#define WM8962_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [9:7] */ -#define WM8962_F256KCLK_DIV_MASK 0x007E /* F256KCLK_DIV - [6:1] */ -#define WM8962_F256KCLK_DIV_SHIFT 1 /* F256KCLK_DIV - [6:1] */ -#define WM8962_F256KCLK_DIV_WIDTH 6 /* F256KCLK_DIV - [6:1] */ - -/* - * R31 (0x1F) - Input mixer control (1) - */ -#define WM8962_MIXINL_MUTE 0x0008 /* MIXINL_MUTE */ -#define WM8962_MIXINL_MUTE_MASK 0x0008 /* MIXINL_MUTE */ -#define WM8962_MIXINL_MUTE_SHIFT 3 /* MIXINL_MUTE */ -#define WM8962_MIXINL_MUTE_WIDTH 1 /* MIXINL_MUTE */ -#define WM8962_MIXINR_MUTE 0x0004 /* MIXINR_MUTE */ -#define WM8962_MIXINR_MUTE_MASK 0x0004 /* MIXINR_MUTE */ -#define WM8962_MIXINR_MUTE_SHIFT 2 /* MIXINR_MUTE */ -#define WM8962_MIXINR_MUTE_WIDTH 1 /* MIXINR_MUTE */ -#define WM8962_MIXINL_ENA 0x0002 /* MIXINL_ENA */ -#define WM8962_MIXINL_ENA_MASK 0x0002 /* MIXINL_ENA */ -#define WM8962_MIXINL_ENA_SHIFT 1 /* MIXINL_ENA */ -#define WM8962_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */ -#define WM8962_MIXINR_ENA 0x0001 /* MIXINR_ENA */ -#define WM8962_MIXINR_ENA_MASK 0x0001 /* MIXINR_ENA */ -#define WM8962_MIXINR_ENA_SHIFT 0 /* MIXINR_ENA */ -#define WM8962_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */ - -/* - * R32 (0x20) - Left input mixer volume - */ -#define WM8962_IN2L_MIXINL_VOL_MASK 0x01C0 /* IN2L_MIXINL_VOL - [8:6] */ -#define WM8962_IN2L_MIXINL_VOL_SHIFT 6 /* IN2L_MIXINL_VOL - [8:6] */ -#define WM8962_IN2L_MIXINL_VOL_WIDTH 3 /* IN2L_MIXINL_VOL - [8:6] */ -#define WM8962_INPGAL_MIXINL_VOL_MASK 0x0038 /* INPGAL_MIXINL_VOL - [5:3] */ -#define WM8962_INPGAL_MIXINL_VOL_SHIFT 3 /* INPGAL_MIXINL_VOL - [5:3] */ -#define WM8962_INPGAL_MIXINL_VOL_WIDTH 3 /* INPGAL_MIXINL_VOL - [5:3] */ -#define WM8962_IN3L_MIXINL_VOL_MASK 0x0007 /* IN3L_MIXINL_VOL - [2:0] */ -#define WM8962_IN3L_MIXINL_VOL_SHIFT 0 /* IN3L_MIXINL_VOL - [2:0] */ -#define WM8962_IN3L_MIXINL_VOL_WIDTH 3 /* IN3L_MIXINL_VOL - [2:0] */ - -/* - * R33 (0x21) - Right input mixer volume - */ -#define WM8962_IN2R_MIXINR_VOL_MASK 0x01C0 /* IN2R_MIXINR_VOL - [8:6] */ -#define WM8962_IN2R_MIXINR_VOL_SHIFT 6 /* IN2R_MIXINR_VOL - [8:6] */ -#define WM8962_IN2R_MIXINR_VOL_WIDTH 3 /* IN2R_MIXINR_VOL - [8:6] */ -#define WM8962_INPGAR_MIXINR_VOL_MASK 0x0038 /* INPGAR_MIXINR_VOL - [5:3] */ -#define WM8962_INPGAR_MIXINR_VOL_SHIFT 3 /* INPGAR_MIXINR_VOL - [5:3] */ -#define WM8962_INPGAR_MIXINR_VOL_WIDTH 3 /* INPGAR_MIXINR_VOL - [5:3] */ -#define WM8962_IN3R_MIXINR_VOL_MASK 0x0007 /* IN3R_MIXINR_VOL - [2:0] */ -#define WM8962_IN3R_MIXINR_VOL_SHIFT 0 /* IN3R_MIXINR_VOL - [2:0] */ -#define WM8962_IN3R_MIXINR_VOL_WIDTH 3 /* IN3R_MIXINR_VOL - [2:0] */ - -/* - * R34 (0x22) - Input mixer control (2) - */ -#define WM8962_IN2L_TO_MIXINL 0x0020 /* IN2L_TO_MIXINL */ -#define WM8962_IN2L_TO_MIXINL_MASK 0x0020 /* IN2L_TO_MIXINL */ -#define WM8962_IN2L_TO_MIXINL_SHIFT 5 /* IN2L_TO_MIXINL */ -#define WM8962_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */ -#define WM8962_IN3L_TO_MIXINL 0x0010 /* IN3L_TO_MIXINL */ -#define WM8962_IN3L_TO_MIXINL_MASK 0x0010 /* IN3L_TO_MIXINL */ -#define WM8962_IN3L_TO_MIXINL_SHIFT 4 /* IN3L_TO_MIXINL */ -#define WM8962_IN3L_TO_MIXINL_WIDTH 1 /* IN3L_TO_MIXINL */ -#define WM8962_INPGAL_TO_MIXINL 0x0008 /* INPGAL_TO_MIXINL */ -#define WM8962_INPGAL_TO_MIXINL_MASK 0x0008 /* INPGAL_TO_MIXINL */ -#define WM8962_INPGAL_TO_MIXINL_SHIFT 3 /* INPGAL_TO_MIXINL */ -#define WM8962_INPGAL_TO_MIXINL_WIDTH 1 /* INPGAL_TO_MIXINL */ -#define WM8962_IN2R_TO_MIXINR 0x0004 /* IN2R_TO_MIXINR */ -#define WM8962_IN2R_TO_MIXINR_MASK 0x0004 /* IN2R_TO_MIXINR */ -#define WM8962_IN2R_TO_MIXINR_SHIFT 2 /* IN2R_TO_MIXINR */ -#define WM8962_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */ -#define WM8962_IN3R_TO_MIXINR 0x0002 /* IN3R_TO_MIXINR */ -#define WM8962_IN3R_TO_MIXINR_MASK 0x0002 /* IN3R_TO_MIXINR */ -#define WM8962_IN3R_TO_MIXINR_SHIFT 1 /* IN3R_TO_MIXINR */ -#define WM8962_IN3R_TO_MIXINR_WIDTH 1 /* IN3R_TO_MIXINR */ -#define WM8962_INPGAR_TO_MIXINR 0x0001 /* INPGAR_TO_MIXINR */ -#define WM8962_INPGAR_TO_MIXINR_MASK 0x0001 /* INPGAR_TO_MIXINR */ -#define WM8962_INPGAR_TO_MIXINR_SHIFT 0 /* INPGAR_TO_MIXINR */ -#define WM8962_INPGAR_TO_MIXINR_WIDTH 1 /* INPGAR_TO_MIXINR */ - -/* - * R35 (0x23) - Input bias control - */ -#define WM8962_MIXIN_BIAS_MASK 0x0038 /* MIXIN_BIAS - [5:3] */ -#define WM8962_MIXIN_BIAS_SHIFT 3 /* MIXIN_BIAS - [5:3] */ -#define WM8962_MIXIN_BIAS_WIDTH 3 /* MIXIN_BIAS - [5:3] */ -#define WM8962_INPGA_BIAS_MASK 0x0007 /* INPGA_BIAS - [2:0] */ -#define WM8962_INPGA_BIAS_SHIFT 0 /* INPGA_BIAS - [2:0] */ -#define WM8962_INPGA_BIAS_WIDTH 3 /* INPGA_BIAS - [2:0] */ - -/* - * R37 (0x25) - Left input PGA control - */ -#define WM8962_INPGAL_ENA 0x0010 /* INPGAL_ENA */ -#define WM8962_INPGAL_ENA_MASK 0x0010 /* INPGAL_ENA */ -#define WM8962_INPGAL_ENA_SHIFT 4 /* INPGAL_ENA */ -#define WM8962_INPGAL_ENA_WIDTH 1 /* INPGAL_ENA */ -#define WM8962_IN1L_TO_INPGAL 0x0008 /* IN1L_TO_INPGAL */ -#define WM8962_IN1L_TO_INPGAL_MASK 0x0008 /* IN1L_TO_INPGAL */ -#define WM8962_IN1L_TO_INPGAL_SHIFT 3 /* IN1L_TO_INPGAL */ -#define WM8962_IN1L_TO_INPGAL_WIDTH 1 /* IN1L_TO_INPGAL */ -#define WM8962_IN2L_TO_INPGAL 0x0004 /* IN2L_TO_INPGAL */ -#define WM8962_IN2L_TO_INPGAL_MASK 0x0004 /* IN2L_TO_INPGAL */ -#define WM8962_IN2L_TO_INPGAL_SHIFT 2 /* IN2L_TO_INPGAL */ -#define WM8962_IN2L_TO_INPGAL_WIDTH 1 /* IN2L_TO_INPGAL */ -#define WM8962_IN3L_TO_INPGAL 0x0002 /* IN3L_TO_INPGAL */ -#define WM8962_IN3L_TO_INPGAL_MASK 0x0002 /* IN3L_TO_INPGAL */ -#define WM8962_IN3L_TO_INPGAL_SHIFT 1 /* IN3L_TO_INPGAL */ -#define WM8962_IN3L_TO_INPGAL_WIDTH 1 /* IN3L_TO_INPGAL */ -#define WM8962_IN4L_TO_INPGAL 0x0001 /* IN4L_TO_INPGAL */ -#define WM8962_IN4L_TO_INPGAL_MASK 0x0001 /* IN4L_TO_INPGAL */ -#define WM8962_IN4L_TO_INPGAL_SHIFT 0 /* IN4L_TO_INPGAL */ -#define WM8962_IN4L_TO_INPGAL_WIDTH 1 /* IN4L_TO_INPGAL */ - -/* - * R38 (0x26) - Right input PGA control - */ -#define WM8962_INPGAR_ENA 0x0010 /* INPGAR_ENA */ -#define WM8962_INPGAR_ENA_MASK 0x0010 /* INPGAR_ENA */ -#define WM8962_INPGAR_ENA_SHIFT 4 /* INPGAR_ENA */ -#define WM8962_INPGAR_ENA_WIDTH 1 /* INPGAR_ENA */ -#define WM8962_IN1R_TO_INPGAR 0x0008 /* IN1R_TO_INPGAR */ -#define WM8962_IN1R_TO_INPGAR_MASK 0x0008 /* IN1R_TO_INPGAR */ -#define WM8962_IN1R_TO_INPGAR_SHIFT 3 /* IN1R_TO_INPGAR */ -#define WM8962_IN1R_TO_INPGAR_WIDTH 1 /* IN1R_TO_INPGAR */ -#define WM8962_IN2R_TO_INPGAR 0x0004 /* IN2R_TO_INPGAR */ -#define WM8962_IN2R_TO_INPGAR_MASK 0x0004 /* IN2R_TO_INPGAR */ -#define WM8962_IN2R_TO_INPGAR_SHIFT 2 /* IN2R_TO_INPGAR */ -#define WM8962_IN2R_TO_INPGAR_WIDTH 1 /* IN2R_TO_INPGAR */ -#define WM8962_IN3R_TO_INPGAR 0x0002 /* IN3R_TO_INPGAR */ -#define WM8962_IN3R_TO_INPGAR_MASK 0x0002 /* IN3R_TO_INPGAR */ -#define WM8962_IN3R_TO_INPGAR_SHIFT 1 /* IN3R_TO_INPGAR */ -#define WM8962_IN3R_TO_INPGAR_WIDTH 1 /* IN3R_TO_INPGAR */ -#define WM8962_IN4R_TO_INPGAR 0x0001 /* IN4R_TO_INPGAR */ -#define WM8962_IN4R_TO_INPGAR_MASK 0x0001 /* IN4R_TO_INPGAR */ -#define WM8962_IN4R_TO_INPGAR_SHIFT 0 /* IN4R_TO_INPGAR */ -#define WM8962_IN4R_TO_INPGAR_WIDTH 1 /* IN4R_TO_INPGAR */ - -/* - * R40 (0x28) - SPKOUTL volume - */ -#define WM8962_SPKOUT_VU 0x0100 /* SPKOUT_VU */ -#define WM8962_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ -#define WM8962_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ -#define WM8962_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ -#define WM8962_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */ -#define WM8962_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */ -#define WM8962_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */ -#define WM8962_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */ -#define WM8962_SPKOUTL_VOL_MASK 0x007F /* SPKOUTL_VOL - [6:0] */ -#define WM8962_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [6:0] */ -#define WM8962_SPKOUTL_VOL_WIDTH 7 /* SPKOUTL_VOL - [6:0] */ - -/* - * R41 (0x29) - SPKOUTR volume - */ -#define WM8962_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */ -#define WM8962_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */ -#define WM8962_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */ -#define WM8962_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */ -#define WM8962_SPKOUTR_VOL_MASK 0x007F /* SPKOUTR_VOL - [6:0] */ -#define WM8962_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [6:0] */ -#define WM8962_SPKOUTR_VOL_WIDTH 7 /* SPKOUTR_VOL - [6:0] */ - -/* - * R47 (0x2F) - Thermal Shutdown Status - */ -#define WM8962_TEMP_ERR_HP 0x0008 /* TEMP_ERR_HP */ -#define WM8962_TEMP_ERR_HP_MASK 0x0008 /* TEMP_ERR_HP */ -#define WM8962_TEMP_ERR_HP_SHIFT 3 /* TEMP_ERR_HP */ -#define WM8962_TEMP_ERR_HP_WIDTH 1 /* TEMP_ERR_HP */ -#define WM8962_TEMP_WARN_HP 0x0004 /* TEMP_WARN_HP */ -#define WM8962_TEMP_WARN_HP_MASK 0x0004 /* TEMP_WARN_HP */ -#define WM8962_TEMP_WARN_HP_SHIFT 2 /* TEMP_WARN_HP */ -#define WM8962_TEMP_WARN_HP_WIDTH 1 /* TEMP_WARN_HP */ -#define WM8962_TEMP_ERR_SPK 0x0002 /* TEMP_ERR_SPK */ -#define WM8962_TEMP_ERR_SPK_MASK 0x0002 /* TEMP_ERR_SPK */ -#define WM8962_TEMP_ERR_SPK_SHIFT 1 /* TEMP_ERR_SPK */ -#define WM8962_TEMP_ERR_SPK_WIDTH 1 /* TEMP_ERR_SPK */ -#define WM8962_TEMP_WARN_SPK 0x0001 /* TEMP_WARN_SPK */ -#define WM8962_TEMP_WARN_SPK_MASK 0x0001 /* TEMP_WARN_SPK */ -#define WM8962_TEMP_WARN_SPK_SHIFT 0 /* TEMP_WARN_SPK */ -#define WM8962_TEMP_WARN_SPK_WIDTH 1 /* TEMP_WARN_SPK */ - -/* - * R48 (0x30) - Additional Control (4) - */ -#define WM8962_MICDET_THR_MASK 0x7000 /* MICDET_THR - [14:12] */ -#define WM8962_MICDET_THR_SHIFT 12 /* MICDET_THR - [14:12] */ -#define WM8962_MICDET_THR_WIDTH 3 /* MICDET_THR - [14:12] */ -#define WM8962_MICSHORT_THR_MASK 0x0C00 /* MICSHORT_THR - [11:10] */ -#define WM8962_MICSHORT_THR_SHIFT 10 /* MICSHORT_THR - [11:10] */ -#define WM8962_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [11:10] */ -#define WM8962_MICDET_ENA 0x0200 /* MICDET_ENA */ -#define WM8962_MICDET_ENA_MASK 0x0200 /* MICDET_ENA */ -#define WM8962_MICDET_ENA_SHIFT 9 /* MICDET_ENA */ -#define WM8962_MICDET_ENA_WIDTH 1 /* MICDET_ENA */ -#define WM8962_MICDET_STS 0x0080 /* MICDET_STS */ -#define WM8962_MICDET_STS_MASK 0x0080 /* MICDET_STS */ -#define WM8962_MICDET_STS_SHIFT 7 /* MICDET_STS */ -#define WM8962_MICDET_STS_WIDTH 1 /* MICDET_STS */ -#define WM8962_MICSHORT_STS 0x0040 /* MICSHORT_STS */ -#define WM8962_MICSHORT_STS_MASK 0x0040 /* MICSHORT_STS */ -#define WM8962_MICSHORT_STS_SHIFT 6 /* MICSHORT_STS */ -#define WM8962_MICSHORT_STS_WIDTH 1 /* MICSHORT_STS */ -#define WM8962_TEMP_ENA_HP 0x0004 /* TEMP_ENA_HP */ -#define WM8962_TEMP_ENA_HP_MASK 0x0004 /* TEMP_ENA_HP */ -#define WM8962_TEMP_ENA_HP_SHIFT 2 /* TEMP_ENA_HP */ -#define WM8962_TEMP_ENA_HP_WIDTH 1 /* TEMP_ENA_HP */ -#define WM8962_TEMP_ENA_SPK 0x0002 /* TEMP_ENA_SPK */ -#define WM8962_TEMP_ENA_SPK_MASK 0x0002 /* TEMP_ENA_SPK */ -#define WM8962_TEMP_ENA_SPK_SHIFT 1 /* TEMP_ENA_SPK */ -#define WM8962_TEMP_ENA_SPK_WIDTH 1 /* TEMP_ENA_SPK */ -#define WM8962_MICBIAS_LVL 0x0001 /* MICBIAS_LVL */ -#define WM8962_MICBIAS_LVL_MASK 0x0001 /* MICBIAS_LVL */ -#define WM8962_MICBIAS_LVL_SHIFT 0 /* MICBIAS_LVL */ -#define WM8962_MICBIAS_LVL_WIDTH 1 /* MICBIAS_LVL */ - -/* - * R49 (0x31) - Class D Control 1 - */ -#define WM8962_SPKOUTR_ENA 0x0080 /* SPKOUTR_ENA */ -#define WM8962_SPKOUTR_ENA_MASK 0x0080 /* SPKOUTR_ENA */ -#define WM8962_SPKOUTR_ENA_SHIFT 7 /* SPKOUTR_ENA */ -#define WM8962_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */ -#define WM8962_SPKOUTL_ENA 0x0040 /* SPKOUTL_ENA */ -#define WM8962_SPKOUTL_ENA_MASK 0x0040 /* SPKOUTL_ENA */ -#define WM8962_SPKOUTL_ENA_SHIFT 6 /* SPKOUTL_ENA */ -#define WM8962_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */ -#define WM8962_SPKOUTL_PGA_MUTE 0x0002 /* SPKOUTL_PGA_MUTE */ -#define WM8962_SPKOUTL_PGA_MUTE_MASK 0x0002 /* SPKOUTL_PGA_MUTE */ -#define WM8962_SPKOUTL_PGA_MUTE_SHIFT 1 /* SPKOUTL_PGA_MUTE */ -#define WM8962_SPKOUTL_PGA_MUTE_WIDTH 1 /* SPKOUTL_PGA_MUTE */ -#define WM8962_SPKOUTR_PGA_MUTE 0x0001 /* SPKOUTR_PGA_MUTE */ -#define WM8962_SPKOUTR_PGA_MUTE_MASK 0x0001 /* SPKOUTR_PGA_MUTE */ -#define WM8962_SPKOUTR_PGA_MUTE_SHIFT 0 /* SPKOUTR_PGA_MUTE */ -#define WM8962_SPKOUTR_PGA_MUTE_WIDTH 1 /* SPKOUTR_PGA_MUTE */ - -/* - * R51 (0x33) - Class D Control 2 - */ -#define WM8962_SPK_MONO 0x0040 /* SPK_MONO */ -#define WM8962_SPK_MONO_MASK 0x0040 /* SPK_MONO */ -#define WM8962_SPK_MONO_SHIFT 6 /* SPK_MONO */ -#define WM8962_SPK_MONO_WIDTH 1 /* SPK_MONO */ -#define WM8962_CLASSD_VOL_MASK 0x0007 /* CLASSD_VOL - [2:0] */ -#define WM8962_CLASSD_VOL_SHIFT 0 /* CLASSD_VOL - [2:0] */ -#define WM8962_CLASSD_VOL_WIDTH 3 /* CLASSD_VOL - [2:0] */ - -/* - * R56 (0x38) - Clocking 4 - */ -#define WM8962_SYSCLK_RATE_MASK 0x001E /* SYSCLK_RATE - [4:1] */ -#define WM8962_SYSCLK_RATE_SHIFT 1 /* SYSCLK_RATE - [4:1] */ -#define WM8962_SYSCLK_RATE_WIDTH 4 /* SYSCLK_RATE - [4:1] */ - -/* - * R57 (0x39) - DAC DSP Mixing (1) - */ -#define WM8962_DAC_MONOMIX 0x0200 /* DAC_MONOMIX */ -#define WM8962_DAC_MONOMIX_MASK 0x0200 /* DAC_MONOMIX */ -#define WM8962_DAC_MONOMIX_SHIFT 9 /* DAC_MONOMIX */ -#define WM8962_DAC_MONOMIX_WIDTH 1 /* DAC_MONOMIX */ -#define WM8962_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8962_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8962_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8962_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */ -#define WM8962_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */ -#define WM8962_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */ - -/* - * R58 (0x3A) - DAC DSP Mixing (2) - */ -#define WM8962_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8962_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8962_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8962_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8962_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8962_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ - -/* - * R60 (0x3C) - DC Servo 0 - */ -#define WM8962_INL_DCS_ENA 0x0080 /* INL_DCS_ENA */ -#define WM8962_INL_DCS_ENA_MASK 0x0080 /* INL_DCS_ENA */ -#define WM8962_INL_DCS_ENA_SHIFT 7 /* INL_DCS_ENA */ -#define WM8962_INL_DCS_ENA_WIDTH 1 /* INL_DCS_ENA */ -#define WM8962_INL_DCS_STARTUP 0x0040 /* INL_DCS_STARTUP */ -#define WM8962_INL_DCS_STARTUP_MASK 0x0040 /* INL_DCS_STARTUP */ -#define WM8962_INL_DCS_STARTUP_SHIFT 6 /* INL_DCS_STARTUP */ -#define WM8962_INL_DCS_STARTUP_WIDTH 1 /* INL_DCS_STARTUP */ -#define WM8962_INR_DCS_ENA 0x0008 /* INR_DCS_ENA */ -#define WM8962_INR_DCS_ENA_MASK 0x0008 /* INR_DCS_ENA */ -#define WM8962_INR_DCS_ENA_SHIFT 3 /* INR_DCS_ENA */ -#define WM8962_INR_DCS_ENA_WIDTH 1 /* INR_DCS_ENA */ -#define WM8962_INR_DCS_STARTUP 0x0004 /* INR_DCS_STARTUP */ -#define WM8962_INR_DCS_STARTUP_MASK 0x0004 /* INR_DCS_STARTUP */ -#define WM8962_INR_DCS_STARTUP_SHIFT 2 /* INR_DCS_STARTUP */ -#define WM8962_INR_DCS_STARTUP_WIDTH 1 /* INR_DCS_STARTUP */ - -/* - * R61 (0x3D) - DC Servo 1 - */ -#define WM8962_HP1L_DCS_ENA 0x0080 /* HP1L_DCS_ENA */ -#define WM8962_HP1L_DCS_ENA_MASK 0x0080 /* HP1L_DCS_ENA */ -#define WM8962_HP1L_DCS_ENA_SHIFT 7 /* HP1L_DCS_ENA */ -#define WM8962_HP1L_DCS_ENA_WIDTH 1 /* HP1L_DCS_ENA */ -#define WM8962_HP1L_DCS_STARTUP 0x0040 /* HP1L_DCS_STARTUP */ -#define WM8962_HP1L_DCS_STARTUP_MASK 0x0040 /* HP1L_DCS_STARTUP */ -#define WM8962_HP1L_DCS_STARTUP_SHIFT 6 /* HP1L_DCS_STARTUP */ -#define WM8962_HP1L_DCS_STARTUP_WIDTH 1 /* HP1L_DCS_STARTUP */ -#define WM8962_HP1L_DCS_SYNC 0x0010 /* HP1L_DCS_SYNC */ -#define WM8962_HP1L_DCS_SYNC_MASK 0x0010 /* HP1L_DCS_SYNC */ -#define WM8962_HP1L_DCS_SYNC_SHIFT 4 /* HP1L_DCS_SYNC */ -#define WM8962_HP1L_DCS_SYNC_WIDTH 1 /* HP1L_DCS_SYNC */ -#define WM8962_HP1R_DCS_ENA 0x0008 /* HP1R_DCS_ENA */ -#define WM8962_HP1R_DCS_ENA_MASK 0x0008 /* HP1R_DCS_ENA */ -#define WM8962_HP1R_DCS_ENA_SHIFT 3 /* HP1R_DCS_ENA */ -#define WM8962_HP1R_DCS_ENA_WIDTH 1 /* HP1R_DCS_ENA */ -#define WM8962_HP1R_DCS_STARTUP 0x0004 /* HP1R_DCS_STARTUP */ -#define WM8962_HP1R_DCS_STARTUP_MASK 0x0004 /* HP1R_DCS_STARTUP */ -#define WM8962_HP1R_DCS_STARTUP_SHIFT 2 /* HP1R_DCS_STARTUP */ -#define WM8962_HP1R_DCS_STARTUP_WIDTH 1 /* HP1R_DCS_STARTUP */ -#define WM8962_HP1R_DCS_SYNC 0x0001 /* HP1R_DCS_SYNC */ -#define WM8962_HP1R_DCS_SYNC_MASK 0x0001 /* HP1R_DCS_SYNC */ -#define WM8962_HP1R_DCS_SYNC_SHIFT 0 /* HP1R_DCS_SYNC */ -#define WM8962_HP1R_DCS_SYNC_WIDTH 1 /* HP1R_DCS_SYNC */ - -/* - * R64 (0x40) - DC Servo 4 - */ -#define WM8962_HP1_DCS_SYNC_STEPS_MASK 0x3F80 /* HP1_DCS_SYNC_STEPS - [13:7] */ -#define WM8962_HP1_DCS_SYNC_STEPS_SHIFT 7 /* HP1_DCS_SYNC_STEPS - [13:7] */ -#define WM8962_HP1_DCS_SYNC_STEPS_WIDTH 7 /* HP1_DCS_SYNC_STEPS - [13:7] */ - -/* - * R66 (0x42) - DC Servo 6 - */ -#define WM8962_DCS_STARTUP_DONE_INL 0x0400 /* DCS_STARTUP_DONE_INL */ -#define WM8962_DCS_STARTUP_DONE_INL_MASK 0x0400 /* DCS_STARTUP_DONE_INL */ -#define WM8962_DCS_STARTUP_DONE_INL_SHIFT 10 /* DCS_STARTUP_DONE_INL */ -#define WM8962_DCS_STARTUP_DONE_INL_WIDTH 1 /* DCS_STARTUP_DONE_INL */ -#define WM8962_DCS_STARTUP_DONE_INR 0x0200 /* DCS_STARTUP_DONE_INR */ -#define WM8962_DCS_STARTUP_DONE_INR_MASK 0x0200 /* DCS_STARTUP_DONE_INR */ -#define WM8962_DCS_STARTUP_DONE_INR_SHIFT 9 /* DCS_STARTUP_DONE_INR */ -#define WM8962_DCS_STARTUP_DONE_INR_WIDTH 1 /* DCS_STARTUP_DONE_INR */ -#define WM8962_DCS_STARTUP_DONE_HP1L 0x0100 /* DCS_STARTUP_DONE_HP1L */ -#define WM8962_DCS_STARTUP_DONE_HP1L_MASK 0x0100 /* DCS_STARTUP_DONE_HP1L */ -#define WM8962_DCS_STARTUP_DONE_HP1L_SHIFT 8 /* DCS_STARTUP_DONE_HP1L */ -#define WM8962_DCS_STARTUP_DONE_HP1L_WIDTH 1 /* DCS_STARTUP_DONE_HP1L */ -#define WM8962_DCS_STARTUP_DONE_HP1R 0x0080 /* DCS_STARTUP_DONE_HP1R */ -#define WM8962_DCS_STARTUP_DONE_HP1R_MASK 0x0080 /* DCS_STARTUP_DONE_HP1R */ -#define WM8962_DCS_STARTUP_DONE_HP1R_SHIFT 7 /* DCS_STARTUP_DONE_HP1R */ -#define WM8962_DCS_STARTUP_DONE_HP1R_WIDTH 1 /* DCS_STARTUP_DONE_HP1R */ - -/* - * R68 (0x44) - Analogue PGA Bias - */ -#define WM8962_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */ -#define WM8962_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */ -#define WM8962_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */ - -/* - * R69 (0x45) - Analogue HP 0 - */ -#define WM8962_HP1L_RMV_SHORT 0x0080 /* HP1L_RMV_SHORT */ -#define WM8962_HP1L_RMV_SHORT_MASK 0x0080 /* HP1L_RMV_SHORT */ -#define WM8962_HP1L_RMV_SHORT_SHIFT 7 /* HP1L_RMV_SHORT */ -#define WM8962_HP1L_RMV_SHORT_WIDTH 1 /* HP1L_RMV_SHORT */ -#define WM8962_HP1L_ENA_OUTP 0x0040 /* HP1L_ENA_OUTP */ -#define WM8962_HP1L_ENA_OUTP_MASK 0x0040 /* HP1L_ENA_OUTP */ -#define WM8962_HP1L_ENA_OUTP_SHIFT 6 /* HP1L_ENA_OUTP */ -#define WM8962_HP1L_ENA_OUTP_WIDTH 1 /* HP1L_ENA_OUTP */ -#define WM8962_HP1L_ENA_DLY 0x0020 /* HP1L_ENA_DLY */ -#define WM8962_HP1L_ENA_DLY_MASK 0x0020 /* HP1L_ENA_DLY */ -#define WM8962_HP1L_ENA_DLY_SHIFT 5 /* HP1L_ENA_DLY */ -#define WM8962_HP1L_ENA_DLY_WIDTH 1 /* HP1L_ENA_DLY */ -#define WM8962_HP1L_ENA 0x0010 /* HP1L_ENA */ -#define WM8962_HP1L_ENA_MASK 0x0010 /* HP1L_ENA */ -#define WM8962_HP1L_ENA_SHIFT 4 /* HP1L_ENA */ -#define WM8962_HP1L_ENA_WIDTH 1 /* HP1L_ENA */ -#define WM8962_HP1R_RMV_SHORT 0x0008 /* HP1R_RMV_SHORT */ -#define WM8962_HP1R_RMV_SHORT_MASK 0x0008 /* HP1R_RMV_SHORT */ -#define WM8962_HP1R_RMV_SHORT_SHIFT 3 /* HP1R_RMV_SHORT */ -#define WM8962_HP1R_RMV_SHORT_WIDTH 1 /* HP1R_RMV_SHORT */ -#define WM8962_HP1R_ENA_OUTP 0x0004 /* HP1R_ENA_OUTP */ -#define WM8962_HP1R_ENA_OUTP_MASK 0x0004 /* HP1R_ENA_OUTP */ -#define WM8962_HP1R_ENA_OUTP_SHIFT 2 /* HP1R_ENA_OUTP */ -#define WM8962_HP1R_ENA_OUTP_WIDTH 1 /* HP1R_ENA_OUTP */ -#define WM8962_HP1R_ENA_DLY 0x0002 /* HP1R_ENA_DLY */ -#define WM8962_HP1R_ENA_DLY_MASK 0x0002 /* HP1R_ENA_DLY */ -#define WM8962_HP1R_ENA_DLY_SHIFT 1 /* HP1R_ENA_DLY */ -#define WM8962_HP1R_ENA_DLY_WIDTH 1 /* HP1R_ENA_DLY */ -#define WM8962_HP1R_ENA 0x0001 /* HP1R_ENA */ -#define WM8962_HP1R_ENA_MASK 0x0001 /* HP1R_ENA */ -#define WM8962_HP1R_ENA_SHIFT 0 /* HP1R_ENA */ -#define WM8962_HP1R_ENA_WIDTH 1 /* HP1R_ENA */ - -/* - * R71 (0x47) - Analogue HP 2 - */ -#define WM8962_HP1L_VOL_MASK 0x01C0 /* HP1L_VOL - [8:6] */ -#define WM8962_HP1L_VOL_SHIFT 6 /* HP1L_VOL - [8:6] */ -#define WM8962_HP1L_VOL_WIDTH 3 /* HP1L_VOL - [8:6] */ -#define WM8962_HP1R_VOL_MASK 0x0038 /* HP1R_VOL - [5:3] */ -#define WM8962_HP1R_VOL_SHIFT 3 /* HP1R_VOL - [5:3] */ -#define WM8962_HP1R_VOL_WIDTH 3 /* HP1R_VOL - [5:3] */ -#define WM8962_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */ -#define WM8962_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */ -#define WM8962_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */ - -/* - * R72 (0x48) - Charge Pump 1 - */ -#define WM8962_CP_ENA 0x0001 /* CP_ENA */ -#define WM8962_CP_ENA_MASK 0x0001 /* CP_ENA */ -#define WM8962_CP_ENA_SHIFT 0 /* CP_ENA */ -#define WM8962_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R82 (0x52) - Charge Pump B - */ -#define WM8962_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */ -#define WM8962_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */ -#define WM8962_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */ -#define WM8962_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */ - -/* - * R87 (0x57) - Write Sequencer Control 1 - */ -#define WM8962_WSEQ_AUTOSEQ_ENA 0x0080 /* WSEQ_AUTOSEQ_ENA */ -#define WM8962_WSEQ_AUTOSEQ_ENA_MASK 0x0080 /* WSEQ_AUTOSEQ_ENA */ -#define WM8962_WSEQ_AUTOSEQ_ENA_SHIFT 7 /* WSEQ_AUTOSEQ_ENA */ -#define WM8962_WSEQ_AUTOSEQ_ENA_WIDTH 1 /* WSEQ_AUTOSEQ_ENA */ -#define WM8962_WSEQ_ENA 0x0020 /* WSEQ_ENA */ -#define WM8962_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */ -#define WM8962_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */ -#define WM8962_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ - -/* - * R90 (0x5A) - Write Sequencer Control 2 - */ -#define WM8962_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */ -#define WM8962_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */ -#define WM8962_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */ -#define WM8962_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8962_WSEQ_START 0x0080 /* WSEQ_START */ -#define WM8962_WSEQ_START_MASK 0x0080 /* WSEQ_START */ -#define WM8962_WSEQ_START_SHIFT 7 /* WSEQ_START */ -#define WM8962_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8962_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */ -#define WM8962_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */ -#define WM8962_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */ - -/* - * R93 (0x5D) - Write Sequencer Control 3 - */ -#define WM8962_WSEQ_CURRENT_INDEX_MASK 0x03F8 /* WSEQ_CURRENT_INDEX - [9:3] */ -#define WM8962_WSEQ_CURRENT_INDEX_SHIFT 3 /* WSEQ_CURRENT_INDEX - [9:3] */ -#define WM8962_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [9:3] */ -#define WM8962_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8962_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8962_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8962_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R94 (0x5E) - Control Interface - */ -#define WM8962_SPI_CONTRD 0x0040 /* SPI_CONTRD */ -#define WM8962_SPI_CONTRD_MASK 0x0040 /* SPI_CONTRD */ -#define WM8962_SPI_CONTRD_SHIFT 6 /* SPI_CONTRD */ -#define WM8962_SPI_CONTRD_WIDTH 1 /* SPI_CONTRD */ -#define WM8962_SPI_4WIRE 0x0020 /* SPI_4WIRE */ -#define WM8962_SPI_4WIRE_MASK 0x0020 /* SPI_4WIRE */ -#define WM8962_SPI_4WIRE_SHIFT 5 /* SPI_4WIRE */ -#define WM8962_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */ -#define WM8962_SPI_CFG 0x0010 /* SPI_CFG */ -#define WM8962_SPI_CFG_MASK 0x0010 /* SPI_CFG */ -#define WM8962_SPI_CFG_SHIFT 4 /* SPI_CFG */ -#define WM8962_SPI_CFG_WIDTH 1 /* SPI_CFG */ - -/* - * R99 (0x63) - Mixer Enables - */ -#define WM8962_HPMIXL_ENA 0x0008 /* HPMIXL_ENA */ -#define WM8962_HPMIXL_ENA_MASK 0x0008 /* HPMIXL_ENA */ -#define WM8962_HPMIXL_ENA_SHIFT 3 /* HPMIXL_ENA */ -#define WM8962_HPMIXL_ENA_WIDTH 1 /* HPMIXL_ENA */ -#define WM8962_HPMIXR_ENA 0x0004 /* HPMIXR_ENA */ -#define WM8962_HPMIXR_ENA_MASK 0x0004 /* HPMIXR_ENA */ -#define WM8962_HPMIXR_ENA_SHIFT 2 /* HPMIXR_ENA */ -#define WM8962_HPMIXR_ENA_WIDTH 1 /* HPMIXR_ENA */ -#define WM8962_SPKMIXL_ENA 0x0002 /* SPKMIXL_ENA */ -#define WM8962_SPKMIXL_ENA_MASK 0x0002 /* SPKMIXL_ENA */ -#define WM8962_SPKMIXL_ENA_SHIFT 1 /* SPKMIXL_ENA */ -#define WM8962_SPKMIXL_ENA_WIDTH 1 /* SPKMIXL_ENA */ -#define WM8962_SPKMIXR_ENA 0x0001 /* SPKMIXR_ENA */ -#define WM8962_SPKMIXR_ENA_MASK 0x0001 /* SPKMIXR_ENA */ -#define WM8962_SPKMIXR_ENA_SHIFT 0 /* SPKMIXR_ENA */ -#define WM8962_SPKMIXR_ENA_WIDTH 1 /* SPKMIXR_ENA */ - -/* - * R100 (0x64) - Headphone Mixer (1) - */ -#define WM8962_HPMIXL_TO_HPOUTL_PGA 0x0080 /* HPMIXL_TO_HPOUTL_PGA */ -#define WM8962_HPMIXL_TO_HPOUTL_PGA_MASK 0x0080 /* HPMIXL_TO_HPOUTL_PGA */ -#define WM8962_HPMIXL_TO_HPOUTL_PGA_SHIFT 7 /* HPMIXL_TO_HPOUTL_PGA */ -#define WM8962_HPMIXL_TO_HPOUTL_PGA_WIDTH 1 /* HPMIXL_TO_HPOUTL_PGA */ -#define WM8962_DACL_TO_HPMIXL 0x0020 /* DACL_TO_HPMIXL */ -#define WM8962_DACL_TO_HPMIXL_MASK 0x0020 /* DACL_TO_HPMIXL */ -#define WM8962_DACL_TO_HPMIXL_SHIFT 5 /* DACL_TO_HPMIXL */ -#define WM8962_DACL_TO_HPMIXL_WIDTH 1 /* DACL_TO_HPMIXL */ -#define WM8962_DACR_TO_HPMIXL 0x0010 /* DACR_TO_HPMIXL */ -#define WM8962_DACR_TO_HPMIXL_MASK 0x0010 /* DACR_TO_HPMIXL */ -#define WM8962_DACR_TO_HPMIXL_SHIFT 4 /* DACR_TO_HPMIXL */ -#define WM8962_DACR_TO_HPMIXL_WIDTH 1 /* DACR_TO_HPMIXL */ -#define WM8962_MIXINL_TO_HPMIXL 0x0008 /* MIXINL_TO_HPMIXL */ -#define WM8962_MIXINL_TO_HPMIXL_MASK 0x0008 /* MIXINL_TO_HPMIXL */ -#define WM8962_MIXINL_TO_HPMIXL_SHIFT 3 /* MIXINL_TO_HPMIXL */ -#define WM8962_MIXINL_TO_HPMIXL_WIDTH 1 /* MIXINL_TO_HPMIXL */ -#define WM8962_MIXINR_TO_HPMIXL 0x0004 /* MIXINR_TO_HPMIXL */ -#define WM8962_MIXINR_TO_HPMIXL_MASK 0x0004 /* MIXINR_TO_HPMIXL */ -#define WM8962_MIXINR_TO_HPMIXL_SHIFT 2 /* MIXINR_TO_HPMIXL */ -#define WM8962_MIXINR_TO_HPMIXL_WIDTH 1 /* MIXINR_TO_HPMIXL */ -#define WM8962_IN4L_TO_HPMIXL 0x0002 /* IN4L_TO_HPMIXL */ -#define WM8962_IN4L_TO_HPMIXL_MASK 0x0002 /* IN4L_TO_HPMIXL */ -#define WM8962_IN4L_TO_HPMIXL_SHIFT 1 /* IN4L_TO_HPMIXL */ -#define WM8962_IN4L_TO_HPMIXL_WIDTH 1 /* IN4L_TO_HPMIXL */ -#define WM8962_IN4R_TO_HPMIXL 0x0001 /* IN4R_TO_HPMIXL */ -#define WM8962_IN4R_TO_HPMIXL_MASK 0x0001 /* IN4R_TO_HPMIXL */ -#define WM8962_IN4R_TO_HPMIXL_SHIFT 0 /* IN4R_TO_HPMIXL */ -#define WM8962_IN4R_TO_HPMIXL_WIDTH 1 /* IN4R_TO_HPMIXL */ - -/* - * R101 (0x65) - Headphone Mixer (2) - */ -#define WM8962_HPMIXR_TO_HPOUTR_PGA 0x0080 /* HPMIXR_TO_HPOUTR_PGA */ -#define WM8962_HPMIXR_TO_HPOUTR_PGA_MASK 0x0080 /* HPMIXR_TO_HPOUTR_PGA */ -#define WM8962_HPMIXR_TO_HPOUTR_PGA_SHIFT 7 /* HPMIXR_TO_HPOUTR_PGA */ -#define WM8962_HPMIXR_TO_HPOUTR_PGA_WIDTH 1 /* HPMIXR_TO_HPOUTR_PGA */ -#define WM8962_DACL_TO_HPMIXR 0x0020 /* DACL_TO_HPMIXR */ -#define WM8962_DACL_TO_HPMIXR_MASK 0x0020 /* DACL_TO_HPMIXR */ -#define WM8962_DACL_TO_HPMIXR_SHIFT 5 /* DACL_TO_HPMIXR */ -#define WM8962_DACL_TO_HPMIXR_WIDTH 1 /* DACL_TO_HPMIXR */ -#define WM8962_DACR_TO_HPMIXR 0x0010 /* DACR_TO_HPMIXR */ -#define WM8962_DACR_TO_HPMIXR_MASK 0x0010 /* DACR_TO_HPMIXR */ -#define WM8962_DACR_TO_HPMIXR_SHIFT 4 /* DACR_TO_HPMIXR */ -#define WM8962_DACR_TO_HPMIXR_WIDTH 1 /* DACR_TO_HPMIXR */ -#define WM8962_MIXINL_TO_HPMIXR 0x0008 /* MIXINL_TO_HPMIXR */ -#define WM8962_MIXINL_TO_HPMIXR_MASK 0x0008 /* MIXINL_TO_HPMIXR */ -#define WM8962_MIXINL_TO_HPMIXR_SHIFT 3 /* MIXINL_TO_HPMIXR */ -#define WM8962_MIXINL_TO_HPMIXR_WIDTH 1 /* MIXINL_TO_HPMIXR */ -#define WM8962_MIXINR_TO_HPMIXR 0x0004 /* MIXINR_TO_HPMIXR */ -#define WM8962_MIXINR_TO_HPMIXR_MASK 0x0004 /* MIXINR_TO_HPMIXR */ -#define WM8962_MIXINR_TO_HPMIXR_SHIFT 2 /* MIXINR_TO_HPMIXR */ -#define WM8962_MIXINR_TO_HPMIXR_WIDTH 1 /* MIXINR_TO_HPMIXR */ -#define WM8962_IN4L_TO_HPMIXR 0x0002 /* IN4L_TO_HPMIXR */ -#define WM8962_IN4L_TO_HPMIXR_MASK 0x0002 /* IN4L_TO_HPMIXR */ -#define WM8962_IN4L_TO_HPMIXR_SHIFT 1 /* IN4L_TO_HPMIXR */ -#define WM8962_IN4L_TO_HPMIXR_WIDTH 1 /* IN4L_TO_HPMIXR */ -#define WM8962_IN4R_TO_HPMIXR 0x0001 /* IN4R_TO_HPMIXR */ -#define WM8962_IN4R_TO_HPMIXR_MASK 0x0001 /* IN4R_TO_HPMIXR */ -#define WM8962_IN4R_TO_HPMIXR_SHIFT 0 /* IN4R_TO_HPMIXR */ -#define WM8962_IN4R_TO_HPMIXR_WIDTH 1 /* IN4R_TO_HPMIXR */ - -/* - * R102 (0x66) - Headphone Mixer (3) - */ -#define WM8962_HPMIXL_MUTE 0x0100 /* HPMIXL_MUTE */ -#define WM8962_HPMIXL_MUTE_MASK 0x0100 /* HPMIXL_MUTE */ -#define WM8962_HPMIXL_MUTE_SHIFT 8 /* HPMIXL_MUTE */ -#define WM8962_HPMIXL_MUTE_WIDTH 1 /* HPMIXL_MUTE */ -#define WM8962_MIXINL_HPMIXL_VOL 0x0080 /* MIXINL_HPMIXL_VOL */ -#define WM8962_MIXINL_HPMIXL_VOL_MASK 0x0080 /* MIXINL_HPMIXL_VOL */ -#define WM8962_MIXINL_HPMIXL_VOL_SHIFT 7 /* MIXINL_HPMIXL_VOL */ -#define WM8962_MIXINL_HPMIXL_VOL_WIDTH 1 /* MIXINL_HPMIXL_VOL */ -#define WM8962_MIXINR_HPMIXL_VOL 0x0040 /* MIXINR_HPMIXL_VOL */ -#define WM8962_MIXINR_HPMIXL_VOL_MASK 0x0040 /* MIXINR_HPMIXL_VOL */ -#define WM8962_MIXINR_HPMIXL_VOL_SHIFT 6 /* MIXINR_HPMIXL_VOL */ -#define WM8962_MIXINR_HPMIXL_VOL_WIDTH 1 /* MIXINR_HPMIXL_VOL */ -#define WM8962_IN4L_HPMIXL_VOL_MASK 0x0038 /* IN4L_HPMIXL_VOL - [5:3] */ -#define WM8962_IN4L_HPMIXL_VOL_SHIFT 3 /* IN4L_HPMIXL_VOL - [5:3] */ -#define WM8962_IN4L_HPMIXL_VOL_WIDTH 3 /* IN4L_HPMIXL_VOL - [5:3] */ -#define WM8962_IN4R_HPMIXL_VOL_MASK 0x0007 /* IN4R_HPMIXL_VOL - [2:0] */ -#define WM8962_IN4R_HPMIXL_VOL_SHIFT 0 /* IN4R_HPMIXL_VOL - [2:0] */ -#define WM8962_IN4R_HPMIXL_VOL_WIDTH 3 /* IN4R_HPMIXL_VOL - [2:0] */ - -/* - * R103 (0x67) - Headphone Mixer (4) - */ -#define WM8962_HPMIXR_MUTE 0x0100 /* HPMIXR_MUTE */ -#define WM8962_HPMIXR_MUTE_MASK 0x0100 /* HPMIXR_MUTE */ -#define WM8962_HPMIXR_MUTE_SHIFT 8 /* HPMIXR_MUTE */ -#define WM8962_HPMIXR_MUTE_WIDTH 1 /* HPMIXR_MUTE */ -#define WM8962_MIXINL_HPMIXR_VOL 0x0080 /* MIXINL_HPMIXR_VOL */ -#define WM8962_MIXINL_HPMIXR_VOL_MASK 0x0080 /* MIXINL_HPMIXR_VOL */ -#define WM8962_MIXINL_HPMIXR_VOL_SHIFT 7 /* MIXINL_HPMIXR_VOL */ -#define WM8962_MIXINL_HPMIXR_VOL_WIDTH 1 /* MIXINL_HPMIXR_VOL */ -#define WM8962_MIXINR_HPMIXR_VOL 0x0040 /* MIXINR_HPMIXR_VOL */ -#define WM8962_MIXINR_HPMIXR_VOL_MASK 0x0040 /* MIXINR_HPMIXR_VOL */ -#define WM8962_MIXINR_HPMIXR_VOL_SHIFT 6 /* MIXINR_HPMIXR_VOL */ -#define WM8962_MIXINR_HPMIXR_VOL_WIDTH 1 /* MIXINR_HPMIXR_VOL */ -#define WM8962_IN4L_HPMIXR_VOL_MASK 0x0038 /* IN4L_HPMIXR_VOL - [5:3] */ -#define WM8962_IN4L_HPMIXR_VOL_SHIFT 3 /* IN4L_HPMIXR_VOL - [5:3] */ -#define WM8962_IN4L_HPMIXR_VOL_WIDTH 3 /* IN4L_HPMIXR_VOL - [5:3] */ -#define WM8962_IN4R_HPMIXR_VOL_MASK 0x0007 /* IN4R_HPMIXR_VOL - [2:0] */ -#define WM8962_IN4R_HPMIXR_VOL_SHIFT 0 /* IN4R_HPMIXR_VOL - [2:0] */ -#define WM8962_IN4R_HPMIXR_VOL_WIDTH 3 /* IN4R_HPMIXR_VOL - [2:0] */ - -/* - * R105 (0x69) - Speaker Mixer (1) - */ -#define WM8962_SPKMIXL_TO_SPKOUTL_PGA 0x0080 /* SPKMIXL_TO_SPKOUTL_PGA */ -#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_MASK 0x0080 /* SPKMIXL_TO_SPKOUTL_PGA */ -#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_SHIFT 7 /* SPKMIXL_TO_SPKOUTL_PGA */ -#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_WIDTH 1 /* SPKMIXL_TO_SPKOUTL_PGA */ -#define WM8962_DACL_TO_SPKMIXL 0x0020 /* DACL_TO_SPKMIXL */ -#define WM8962_DACL_TO_SPKMIXL_MASK 0x0020 /* DACL_TO_SPKMIXL */ -#define WM8962_DACL_TO_SPKMIXL_SHIFT 5 /* DACL_TO_SPKMIXL */ -#define WM8962_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */ -#define WM8962_DACR_TO_SPKMIXL 0x0010 /* DACR_TO_SPKMIXL */ -#define WM8962_DACR_TO_SPKMIXL_MASK 0x0010 /* DACR_TO_SPKMIXL */ -#define WM8962_DACR_TO_SPKMIXL_SHIFT 4 /* DACR_TO_SPKMIXL */ -#define WM8962_DACR_TO_SPKMIXL_WIDTH 1 /* DACR_TO_SPKMIXL */ -#define WM8962_MIXINL_TO_SPKMIXL 0x0008 /* MIXINL_TO_SPKMIXL */ -#define WM8962_MIXINL_TO_SPKMIXL_MASK 0x0008 /* MIXINL_TO_SPKMIXL */ -#define WM8962_MIXINL_TO_SPKMIXL_SHIFT 3 /* MIXINL_TO_SPKMIXL */ -#define WM8962_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */ -#define WM8962_MIXINR_TO_SPKMIXL 0x0004 /* MIXINR_TO_SPKMIXL */ -#define WM8962_MIXINR_TO_SPKMIXL_MASK 0x0004 /* MIXINR_TO_SPKMIXL */ -#define WM8962_MIXINR_TO_SPKMIXL_SHIFT 2 /* MIXINR_TO_SPKMIXL */ -#define WM8962_MIXINR_TO_SPKMIXL_WIDTH 1 /* MIXINR_TO_SPKMIXL */ -#define WM8962_IN4L_TO_SPKMIXL 0x0002 /* IN4L_TO_SPKMIXL */ -#define WM8962_IN4L_TO_SPKMIXL_MASK 0x0002 /* IN4L_TO_SPKMIXL */ -#define WM8962_IN4L_TO_SPKMIXL_SHIFT 1 /* IN4L_TO_SPKMIXL */ -#define WM8962_IN4L_TO_SPKMIXL_WIDTH 1 /* IN4L_TO_SPKMIXL */ -#define WM8962_IN4R_TO_SPKMIXL 0x0001 /* IN4R_TO_SPKMIXL */ -#define WM8962_IN4R_TO_SPKMIXL_MASK 0x0001 /* IN4R_TO_SPKMIXL */ -#define WM8962_IN4R_TO_SPKMIXL_SHIFT 0 /* IN4R_TO_SPKMIXL */ -#define WM8962_IN4R_TO_SPKMIXL_WIDTH 1 /* IN4R_TO_SPKMIXL */ - -/* - * R106 (0x6A) - Speaker Mixer (2) - */ -#define WM8962_SPKMIXR_TO_SPKOUTR_PGA 0x0080 /* SPKMIXR_TO_SPKOUTR_PGA */ -#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_MASK 0x0080 /* SPKMIXR_TO_SPKOUTR_PGA */ -#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_SHIFT 7 /* SPKMIXR_TO_SPKOUTR_PGA */ -#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_WIDTH 1 /* SPKMIXR_TO_SPKOUTR_PGA */ -#define WM8962_DACL_TO_SPKMIXR 0x0020 /* DACL_TO_SPKMIXR */ -#define WM8962_DACL_TO_SPKMIXR_MASK 0x0020 /* DACL_TO_SPKMIXR */ -#define WM8962_DACL_TO_SPKMIXR_SHIFT 5 /* DACL_TO_SPKMIXR */ -#define WM8962_DACL_TO_SPKMIXR_WIDTH 1 /* DACL_TO_SPKMIXR */ -#define WM8962_DACR_TO_SPKMIXR 0x0010 /* DACR_TO_SPKMIXR */ -#define WM8962_DACR_TO_SPKMIXR_MASK 0x0010 /* DACR_TO_SPKMIXR */ -#define WM8962_DACR_TO_SPKMIXR_SHIFT 4 /* DACR_TO_SPKMIXR */ -#define WM8962_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */ -#define WM8962_MIXINL_TO_SPKMIXR 0x0008 /* MIXINL_TO_SPKMIXR */ -#define WM8962_MIXINL_TO_SPKMIXR_MASK 0x0008 /* MIXINL_TO_SPKMIXR */ -#define WM8962_MIXINL_TO_SPKMIXR_SHIFT 3 /* MIXINL_TO_SPKMIXR */ -#define WM8962_MIXINL_TO_SPKMIXR_WIDTH 1 /* MIXINL_TO_SPKMIXR */ -#define WM8962_MIXINR_TO_SPKMIXR 0x0004 /* MIXINR_TO_SPKMIXR */ -#define WM8962_MIXINR_TO_SPKMIXR_MASK 0x0004 /* MIXINR_TO_SPKMIXR */ -#define WM8962_MIXINR_TO_SPKMIXR_SHIFT 2 /* MIXINR_TO_SPKMIXR */ -#define WM8962_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */ -#define WM8962_IN4L_TO_SPKMIXR 0x0002 /* IN4L_TO_SPKMIXR */ -#define WM8962_IN4L_TO_SPKMIXR_MASK 0x0002 /* IN4L_TO_SPKMIXR */ -#define WM8962_IN4L_TO_SPKMIXR_SHIFT 1 /* IN4L_TO_SPKMIXR */ -#define WM8962_IN4L_TO_SPKMIXR_WIDTH 1 /* IN4L_TO_SPKMIXR */ -#define WM8962_IN4R_TO_SPKMIXR 0x0001 /* IN4R_TO_SPKMIXR */ -#define WM8962_IN4R_TO_SPKMIXR_MASK 0x0001 /* IN4R_TO_SPKMIXR */ -#define WM8962_IN4R_TO_SPKMIXR_SHIFT 0 /* IN4R_TO_SPKMIXR */ -#define WM8962_IN4R_TO_SPKMIXR_WIDTH 1 /* IN4R_TO_SPKMIXR */ - -/* - * R107 (0x6B) - Speaker Mixer (3) - */ -#define WM8962_SPKMIXL_MUTE 0x0100 /* SPKMIXL_MUTE */ -#define WM8962_SPKMIXL_MUTE_MASK 0x0100 /* SPKMIXL_MUTE */ -#define WM8962_SPKMIXL_MUTE_SHIFT 8 /* SPKMIXL_MUTE */ -#define WM8962_SPKMIXL_MUTE_WIDTH 1 /* SPKMIXL_MUTE */ -#define WM8962_MIXINL_SPKMIXL_VOL 0x0080 /* MIXINL_SPKMIXL_VOL */ -#define WM8962_MIXINL_SPKMIXL_VOL_MASK 0x0080 /* MIXINL_SPKMIXL_VOL */ -#define WM8962_MIXINL_SPKMIXL_VOL_SHIFT 7 /* MIXINL_SPKMIXL_VOL */ -#define WM8962_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */ -#define WM8962_MIXINR_SPKMIXL_VOL 0x0040 /* MIXINR_SPKMIXL_VOL */ -#define WM8962_MIXINR_SPKMIXL_VOL_MASK 0x0040 /* MIXINR_SPKMIXL_VOL */ -#define WM8962_MIXINR_SPKMIXL_VOL_SHIFT 6 /* MIXINR_SPKMIXL_VOL */ -#define WM8962_MIXINR_SPKMIXL_VOL_WIDTH 1 /* MIXINR_SPKMIXL_VOL */ -#define WM8962_IN4L_SPKMIXL_VOL_MASK 0x0038 /* IN4L_SPKMIXL_VOL - [5:3] */ -#define WM8962_IN4L_SPKMIXL_VOL_SHIFT 3 /* IN4L_SPKMIXL_VOL - [5:3] */ -#define WM8962_IN4L_SPKMIXL_VOL_WIDTH 3 /* IN4L_SPKMIXL_VOL - [5:3] */ -#define WM8962_IN4R_SPKMIXL_VOL_MASK 0x0007 /* IN4R_SPKMIXL_VOL - [2:0] */ -#define WM8962_IN4R_SPKMIXL_VOL_SHIFT 0 /* IN4R_SPKMIXL_VOL - [2:0] */ -#define WM8962_IN4R_SPKMIXL_VOL_WIDTH 3 /* IN4R_SPKMIXL_VOL - [2:0] */ - -/* - * R108 (0x6C) - Speaker Mixer (4) - */ -#define WM8962_SPKMIXR_MUTE 0x0100 /* SPKMIXR_MUTE */ -#define WM8962_SPKMIXR_MUTE_MASK 0x0100 /* SPKMIXR_MUTE */ -#define WM8962_SPKMIXR_MUTE_SHIFT 8 /* SPKMIXR_MUTE */ -#define WM8962_SPKMIXR_MUTE_WIDTH 1 /* SPKMIXR_MUTE */ -#define WM8962_MIXINL_SPKMIXR_VOL 0x0080 /* MIXINL_SPKMIXR_VOL */ -#define WM8962_MIXINL_SPKMIXR_VOL_MASK 0x0080 /* MIXINL_SPKMIXR_VOL */ -#define WM8962_MIXINL_SPKMIXR_VOL_SHIFT 7 /* MIXINL_SPKMIXR_VOL */ -#define WM8962_MIXINL_SPKMIXR_VOL_WIDTH 1 /* MIXINL_SPKMIXR_VOL */ -#define WM8962_MIXINR_SPKMIXR_VOL 0x0040 /* MIXINR_SPKMIXR_VOL */ -#define WM8962_MIXINR_SPKMIXR_VOL_MASK 0x0040 /* MIXINR_SPKMIXR_VOL */ -#define WM8962_MIXINR_SPKMIXR_VOL_SHIFT 6 /* MIXINR_SPKMIXR_VOL */ -#define WM8962_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */ -#define WM8962_IN4L_SPKMIXR_VOL_MASK 0x0038 /* IN4L_SPKMIXR_VOL - [5:3] */ -#define WM8962_IN4L_SPKMIXR_VOL_SHIFT 3 /* IN4L_SPKMIXR_VOL - [5:3] */ -#define WM8962_IN4L_SPKMIXR_VOL_WIDTH 3 /* IN4L_SPKMIXR_VOL - [5:3] */ -#define WM8962_IN4R_SPKMIXR_VOL_MASK 0x0007 /* IN4R_SPKMIXR_VOL - [2:0] */ -#define WM8962_IN4R_SPKMIXR_VOL_SHIFT 0 /* IN4R_SPKMIXR_VOL - [2:0] */ -#define WM8962_IN4R_SPKMIXR_VOL_WIDTH 3 /* IN4R_SPKMIXR_VOL - [2:0] */ - -/* - * R109 (0x6D) - Speaker Mixer (5) - */ -#define WM8962_DACL_SPKMIXL_VOL 0x0080 /* DACL_SPKMIXL_VOL */ -#define WM8962_DACL_SPKMIXL_VOL_MASK 0x0080 /* DACL_SPKMIXL_VOL */ -#define WM8962_DACL_SPKMIXL_VOL_SHIFT 7 /* DACL_SPKMIXL_VOL */ -#define WM8962_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */ -#define WM8962_DACR_SPKMIXL_VOL 0x0040 /* DACR_SPKMIXL_VOL */ -#define WM8962_DACR_SPKMIXL_VOL_MASK 0x0040 /* DACR_SPKMIXL_VOL */ -#define WM8962_DACR_SPKMIXL_VOL_SHIFT 6 /* DACR_SPKMIXL_VOL */ -#define WM8962_DACR_SPKMIXL_VOL_WIDTH 1 /* DACR_SPKMIXL_VOL */ -#define WM8962_DACL_SPKMIXR_VOL 0x0020 /* DACL_SPKMIXR_VOL */ -#define WM8962_DACL_SPKMIXR_VOL_MASK 0x0020 /* DACL_SPKMIXR_VOL */ -#define WM8962_DACL_SPKMIXR_VOL_SHIFT 5 /* DACL_SPKMIXR_VOL */ -#define WM8962_DACL_SPKMIXR_VOL_WIDTH 1 /* DACL_SPKMIXR_VOL */ -#define WM8962_DACR_SPKMIXR_VOL 0x0010 /* DACR_SPKMIXR_VOL */ -#define WM8962_DACR_SPKMIXR_VOL_MASK 0x0010 /* DACR_SPKMIXR_VOL */ -#define WM8962_DACR_SPKMIXR_VOL_SHIFT 4 /* DACR_SPKMIXR_VOL */ -#define WM8962_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */ - -/* - * R110 (0x6E) - Beep Generator (1) - */ -#define WM8962_BEEP_GAIN_MASK 0x00F0 /* BEEP_GAIN - [7:4] */ -#define WM8962_BEEP_GAIN_SHIFT 4 /* BEEP_GAIN - [7:4] */ -#define WM8962_BEEP_GAIN_WIDTH 4 /* BEEP_GAIN - [7:4] */ -#define WM8962_BEEP_RATE_MASK 0x0006 /* BEEP_RATE - [2:1] */ -#define WM8962_BEEP_RATE_SHIFT 1 /* BEEP_RATE - [2:1] */ -#define WM8962_BEEP_RATE_WIDTH 2 /* BEEP_RATE - [2:1] */ -#define WM8962_BEEP_ENA 0x0001 /* BEEP_ENA */ -#define WM8962_BEEP_ENA_MASK 0x0001 /* BEEP_ENA */ -#define WM8962_BEEP_ENA_SHIFT 0 /* BEEP_ENA */ -#define WM8962_BEEP_ENA_WIDTH 1 /* BEEP_ENA */ - -/* - * R115 (0x73) - Oscillator Trim (3) - */ -#define WM8962_OSC_TRIM_XTI_MASK 0x001F /* OSC_TRIM_XTI - [4:0] */ -#define WM8962_OSC_TRIM_XTI_SHIFT 0 /* OSC_TRIM_XTI - [4:0] */ -#define WM8962_OSC_TRIM_XTI_WIDTH 5 /* OSC_TRIM_XTI - [4:0] */ - -/* - * R116 (0x74) - Oscillator Trim (4) - */ -#define WM8962_OSC_TRIM_XTO_MASK 0x001F /* OSC_TRIM_XTO - [4:0] */ -#define WM8962_OSC_TRIM_XTO_SHIFT 0 /* OSC_TRIM_XTO - [4:0] */ -#define WM8962_OSC_TRIM_XTO_WIDTH 5 /* OSC_TRIM_XTO - [4:0] */ - -/* - * R119 (0x77) - Oscillator Trim (7) - */ -#define WM8962_XTO_CAP_SEL_MASK 0x00F0 /* XTO_CAP_SEL - [7:4] */ -#define WM8962_XTO_CAP_SEL_SHIFT 4 /* XTO_CAP_SEL - [7:4] */ -#define WM8962_XTO_CAP_SEL_WIDTH 4 /* XTO_CAP_SEL - [7:4] */ -#define WM8962_XTI_CAP_SEL_MASK 0x000F /* XTI_CAP_SEL - [3:0] */ -#define WM8962_XTI_CAP_SEL_SHIFT 0 /* XTI_CAP_SEL - [3:0] */ -#define WM8962_XTI_CAP_SEL_WIDTH 4 /* XTI_CAP_SEL - [3:0] */ - -/* - * R124 (0x7C) - Analogue Clocking1 - */ -#define WM8962_CLKOUT2_SEL_MASK 0x0060 /* CLKOUT2_SEL - [6:5] */ -#define WM8962_CLKOUT2_SEL_SHIFT 5 /* CLKOUT2_SEL - [6:5] */ -#define WM8962_CLKOUT2_SEL_WIDTH 2 /* CLKOUT2_SEL - [6:5] */ -#define WM8962_CLKOUT3_SEL_MASK 0x0018 /* CLKOUT3_SEL - [4:3] */ -#define WM8962_CLKOUT3_SEL_SHIFT 3 /* CLKOUT3_SEL - [4:3] */ -#define WM8962_CLKOUT3_SEL_WIDTH 2 /* CLKOUT3_SEL - [4:3] */ -#define WM8962_CLKOUT5_SEL 0x0001 /* CLKOUT5_SEL */ -#define WM8962_CLKOUT5_SEL_MASK 0x0001 /* CLKOUT5_SEL */ -#define WM8962_CLKOUT5_SEL_SHIFT 0 /* CLKOUT5_SEL */ -#define WM8962_CLKOUT5_SEL_WIDTH 1 /* CLKOUT5_SEL */ - -/* - * R125 (0x7D) - Analogue Clocking2 - */ -#define WM8962_PLL2_OUTDIV 0x0080 /* PLL2_OUTDIV */ -#define WM8962_PLL2_OUTDIV_MASK 0x0080 /* PLL2_OUTDIV */ -#define WM8962_PLL2_OUTDIV_SHIFT 7 /* PLL2_OUTDIV */ -#define WM8962_PLL2_OUTDIV_WIDTH 1 /* PLL2_OUTDIV */ -#define WM8962_PLL3_OUTDIV 0x0040 /* PLL3_OUTDIV */ -#define WM8962_PLL3_OUTDIV_MASK 0x0040 /* PLL3_OUTDIV */ -#define WM8962_PLL3_OUTDIV_SHIFT 6 /* PLL3_OUTDIV */ -#define WM8962_PLL3_OUTDIV_WIDTH 1 /* PLL3_OUTDIV */ -#define WM8962_PLL_SYSCLK_DIV_MASK 0x0018 /* PLL_SYSCLK_DIV - [4:3] */ -#define WM8962_PLL_SYSCLK_DIV_SHIFT 3 /* PLL_SYSCLK_DIV - [4:3] */ -#define WM8962_PLL_SYSCLK_DIV_WIDTH 2 /* PLL_SYSCLK_DIV - [4:3] */ -#define WM8962_CLKOUT3_DIV 0x0004 /* CLKOUT3_DIV */ -#define WM8962_CLKOUT3_DIV_MASK 0x0004 /* CLKOUT3_DIV */ -#define WM8962_CLKOUT3_DIV_SHIFT 2 /* CLKOUT3_DIV */ -#define WM8962_CLKOUT3_DIV_WIDTH 1 /* CLKOUT3_DIV */ -#define WM8962_CLKOUT2_DIV 0x0002 /* CLKOUT2_DIV */ -#define WM8962_CLKOUT2_DIV_MASK 0x0002 /* CLKOUT2_DIV */ -#define WM8962_CLKOUT2_DIV_SHIFT 1 /* CLKOUT2_DIV */ -#define WM8962_CLKOUT2_DIV_WIDTH 1 /* CLKOUT2_DIV */ -#define WM8962_CLKOUT5_DIV 0x0001 /* CLKOUT5_DIV */ -#define WM8962_CLKOUT5_DIV_MASK 0x0001 /* CLKOUT5_DIV */ -#define WM8962_CLKOUT5_DIV_SHIFT 0 /* CLKOUT5_DIV */ -#define WM8962_CLKOUT5_DIV_WIDTH 1 /* CLKOUT5_DIV */ - -/* - * R126 (0x7E) - Analogue Clocking3 - */ -#define WM8962_CLKOUT2_OE 0x0008 /* CLKOUT2_OE */ -#define WM8962_CLKOUT2_OE_MASK 0x0008 /* CLKOUT2_OE */ -#define WM8962_CLKOUT2_OE_SHIFT 3 /* CLKOUT2_OE */ -#define WM8962_CLKOUT2_OE_WIDTH 1 /* CLKOUT2_OE */ -#define WM8962_CLKOUT3_OE 0x0004 /* CLKOUT3_OE */ -#define WM8962_CLKOUT3_OE_MASK 0x0004 /* CLKOUT3_OE */ -#define WM8962_CLKOUT3_OE_SHIFT 2 /* CLKOUT3_OE */ -#define WM8962_CLKOUT3_OE_WIDTH 1 /* CLKOUT3_OE */ -#define WM8962_CLKOUT5_OE 0x0001 /* CLKOUT5_OE */ -#define WM8962_CLKOUT5_OE_MASK 0x0001 /* CLKOUT5_OE */ -#define WM8962_CLKOUT5_OE_SHIFT 0 /* CLKOUT5_OE */ -#define WM8962_CLKOUT5_OE_WIDTH 1 /* CLKOUT5_OE */ - -/* - * R127 (0x7F) - PLL Software Reset - */ -#define WM8962_SW_RESET_PLL_MASK 0xFFFF /* SW_RESET_PLL - [15:0] */ -#define WM8962_SW_RESET_PLL_SHIFT 0 /* SW_RESET_PLL - [15:0] */ -#define WM8962_SW_RESET_PLL_WIDTH 16 /* SW_RESET_PLL - [15:0] */ - -/* - * R129 (0x81) - PLL2 - */ -#define WM8962_OSC_ENA 0x0080 /* OSC_ENA */ -#define WM8962_OSC_ENA_MASK 0x0080 /* OSC_ENA */ -#define WM8962_OSC_ENA_SHIFT 7 /* OSC_ENA */ -#define WM8962_OSC_ENA_WIDTH 1 /* OSC_ENA */ -#define WM8962_PLL2_ENA 0x0020 /* PLL2_ENA */ -#define WM8962_PLL2_ENA_MASK 0x0020 /* PLL2_ENA */ -#define WM8962_PLL2_ENA_SHIFT 5 /* PLL2_ENA */ -#define WM8962_PLL2_ENA_WIDTH 1 /* PLL2_ENA */ -#define WM8962_PLL3_ENA 0x0010 /* PLL3_ENA */ -#define WM8962_PLL3_ENA_MASK 0x0010 /* PLL3_ENA */ -#define WM8962_PLL3_ENA_SHIFT 4 /* PLL3_ENA */ -#define WM8962_PLL3_ENA_WIDTH 1 /* PLL3_ENA */ - -/* - * R131 (0x83) - PLL 4 - */ -#define WM8962_PLL_CLK_SRC 0x0002 /* PLL_CLK_SRC */ -#define WM8962_PLL_CLK_SRC_MASK 0x0002 /* PLL_CLK_SRC */ -#define WM8962_PLL_CLK_SRC_SHIFT 1 /* PLL_CLK_SRC */ -#define WM8962_PLL_CLK_SRC_WIDTH 1 /* PLL_CLK_SRC */ -#define WM8962_FLL_TO_PLL3 0x0001 /* FLL_TO_PLL3 */ -#define WM8962_FLL_TO_PLL3_MASK 0x0001 /* FLL_TO_PLL3 */ -#define WM8962_FLL_TO_PLL3_SHIFT 0 /* FLL_TO_PLL3 */ -#define WM8962_FLL_TO_PLL3_WIDTH 1 /* FLL_TO_PLL3 */ - -/* - * R136 (0x88) - PLL 9 - */ -#define WM8962_PLL2_FRAC 0x0040 /* PLL2_FRAC */ -#define WM8962_PLL2_FRAC_MASK 0x0040 /* PLL2_FRAC */ -#define WM8962_PLL2_FRAC_SHIFT 6 /* PLL2_FRAC */ -#define WM8962_PLL2_FRAC_WIDTH 1 /* PLL2_FRAC */ -#define WM8962_PLL2_N_MASK 0x001F /* PLL2_N - [4:0] */ -#define WM8962_PLL2_N_SHIFT 0 /* PLL2_N - [4:0] */ -#define WM8962_PLL2_N_WIDTH 5 /* PLL2_N - [4:0] */ - -/* - * R137 (0x89) - PLL 10 - */ -#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */ -#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */ -#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */ - -/* - * R138 (0x8A) - PLL 11 - */ -#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */ -#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */ -#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */ - -/* - * R139 (0x8B) - PLL 12 - */ -#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */ -#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */ -#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */ - -/* - * R140 (0x8C) - PLL 13 - */ -#define WM8962_PLL3_FRAC 0x0040 /* PLL3_FRAC */ -#define WM8962_PLL3_FRAC_MASK 0x0040 /* PLL3_FRAC */ -#define WM8962_PLL3_FRAC_SHIFT 6 /* PLL3_FRAC */ -#define WM8962_PLL3_FRAC_WIDTH 1 /* PLL3_FRAC */ -#define WM8962_PLL3_N_MASK 0x001F /* PLL3_N - [4:0] */ -#define WM8962_PLL3_N_SHIFT 0 /* PLL3_N - [4:0] */ -#define WM8962_PLL3_N_WIDTH 5 /* PLL3_N - [4:0] */ - -/* - * R141 (0x8D) - PLL 14 - */ -#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */ -#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */ -#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */ - -/* - * R142 (0x8E) - PLL 15 - */ -#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */ -#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */ -#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */ - -/* - * R143 (0x8F) - PLL 16 - */ -#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */ -#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */ -#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */ - -/* - * R155 (0x9B) - FLL Control (1) - */ -#define WM8962_FLL_REFCLK_SRC_MASK 0x0060 /* FLL_REFCLK_SRC - [6:5] */ -#define WM8962_FLL_REFCLK_SRC_SHIFT 5 /* FLL_REFCLK_SRC - [6:5] */ -#define WM8962_FLL_REFCLK_SRC_WIDTH 2 /* FLL_REFCLK_SRC - [6:5] */ -#define WM8962_FLL_FRAC 0x0004 /* FLL_FRAC */ -#define WM8962_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */ -#define WM8962_FLL_FRAC_SHIFT 2 /* FLL_FRAC */ -#define WM8962_FLL_FRAC_WIDTH 1 /* FLL_FRAC */ -#define WM8962_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ -#define WM8962_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ -#define WM8962_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ -#define WM8962_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ -#define WM8962_FLL_ENA 0x0001 /* FLL_ENA */ -#define WM8962_FLL_ENA_MASK 0x0001 /* FLL_ENA */ -#define WM8962_FLL_ENA_SHIFT 0 /* FLL_ENA */ -#define WM8962_FLL_ENA_WIDTH 1 /* FLL_ENA */ - -/* - * R156 (0x9C) - FLL Control (2) - */ -#define WM8962_FLL_OUTDIV_MASK 0x01F8 /* FLL_OUTDIV - [8:3] */ -#define WM8962_FLL_OUTDIV_SHIFT 3 /* FLL_OUTDIV - [8:3] */ -#define WM8962_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [8:3] */ -#define WM8962_FLL_REFCLK_DIV_MASK 0x0003 /* FLL_REFCLK_DIV - [1:0] */ -#define WM8962_FLL_REFCLK_DIV_SHIFT 0 /* FLL_REFCLK_DIV - [1:0] */ -#define WM8962_FLL_REFCLK_DIV_WIDTH 2 /* FLL_REFCLK_DIV - [1:0] */ - -/* - * R157 (0x9D) - FLL Control (3) - */ -#define WM8962_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ -#define WM8962_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ -#define WM8962_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ - -/* - * R159 (0x9F) - FLL Control (5) - */ -#define WM8962_FLL_FRC_NCO_VAL_MASK 0x007E /* FLL_FRC_NCO_VAL - [6:1] */ -#define WM8962_FLL_FRC_NCO_VAL_SHIFT 1 /* FLL_FRC_NCO_VAL - [6:1] */ -#define WM8962_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [6:1] */ -#define WM8962_FLL_FRC_NCO 0x0001 /* FLL_FRC_NCO */ -#define WM8962_FLL_FRC_NCO_MASK 0x0001 /* FLL_FRC_NCO */ -#define WM8962_FLL_FRC_NCO_SHIFT 0 /* FLL_FRC_NCO */ -#define WM8962_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ - -/* - * R160 (0xA0) - FLL Control (6) - */ -#define WM8962_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */ -#define WM8962_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */ -#define WM8962_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */ - -/* - * R161 (0xA1) - FLL Control (7) - */ -#define WM8962_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */ -#define WM8962_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */ -#define WM8962_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */ - -/* - * R162 (0xA2) - FLL Control (8) - */ -#define WM8962_FLL_N_MASK 0x03FF /* FLL_N - [9:0] */ -#define WM8962_FLL_N_SHIFT 0 /* FLL_N - [9:0] */ -#define WM8962_FLL_N_WIDTH 10 /* FLL_N - [9:0] */ - -/* - * R252 (0xFC) - General test 1 - */ -#define WM8962_REG_SYNC 0x0004 /* REG_SYNC */ -#define WM8962_REG_SYNC_MASK 0x0004 /* REG_SYNC */ -#define WM8962_REG_SYNC_SHIFT 2 /* REG_SYNC */ -#define WM8962_REG_SYNC_WIDTH 1 /* REG_SYNC */ -#define WM8962_AUTO_INC 0x0001 /* AUTO_INC */ -#define WM8962_AUTO_INC_MASK 0x0001 /* AUTO_INC */ -#define WM8962_AUTO_INC_SHIFT 0 /* AUTO_INC */ -#define WM8962_AUTO_INC_WIDTH 1 /* AUTO_INC */ - -/* - * R256 (0x100) - DF1 - */ -#define WM8962_DRC_DF1_ENA 0x0008 /* DRC_DF1_ENA */ -#define WM8962_DRC_DF1_ENA_MASK 0x0008 /* DRC_DF1_ENA */ -#define WM8962_DRC_DF1_ENA_SHIFT 3 /* DRC_DF1_ENA */ -#define WM8962_DRC_DF1_ENA_WIDTH 1 /* DRC_DF1_ENA */ -#define WM8962_DF1_SHARED_COEFF 0x0004 /* DF1_SHARED_COEFF */ -#define WM8962_DF1_SHARED_COEFF_MASK 0x0004 /* DF1_SHARED_COEFF */ -#define WM8962_DF1_SHARED_COEFF_SHIFT 2 /* DF1_SHARED_COEFF */ -#define WM8962_DF1_SHARED_COEFF_WIDTH 1 /* DF1_SHARED_COEFF */ -#define WM8962_DF1_SHARED_COEFF_SEL 0x0002 /* DF1_SHARED_COEFF_SEL */ -#define WM8962_DF1_SHARED_COEFF_SEL_MASK 0x0002 /* DF1_SHARED_COEFF_SEL */ -#define WM8962_DF1_SHARED_COEFF_SEL_SHIFT 1 /* DF1_SHARED_COEFF_SEL */ -#define WM8962_DF1_SHARED_COEFF_SEL_WIDTH 1 /* DF1_SHARED_COEFF_SEL */ -#define WM8962_DF1_ENA 0x0001 /* DF1_ENA */ -#define WM8962_DF1_ENA_MASK 0x0001 /* DF1_ENA */ -#define WM8962_DF1_ENA_SHIFT 0 /* DF1_ENA */ -#define WM8962_DF1_ENA_WIDTH 1 /* DF1_ENA */ - -/* - * R257 (0x101) - DF2 - */ -#define WM8962_DF1_COEFF_L0_MASK 0xFFFF /* DF1_COEFF_L0 - [15:0] */ -#define WM8962_DF1_COEFF_L0_SHIFT 0 /* DF1_COEFF_L0 - [15:0] */ -#define WM8962_DF1_COEFF_L0_WIDTH 16 /* DF1_COEFF_L0 - [15:0] */ - -/* - * R258 (0x102) - DF3 - */ -#define WM8962_DF1_COEFF_L1_MASK 0xFFFF /* DF1_COEFF_L1 - [15:0] */ -#define WM8962_DF1_COEFF_L1_SHIFT 0 /* DF1_COEFF_L1 - [15:0] */ -#define WM8962_DF1_COEFF_L1_WIDTH 16 /* DF1_COEFF_L1 - [15:0] */ - -/* - * R259 (0x103) - DF4 - */ -#define WM8962_DF1_COEFF_L2_MASK 0xFFFF /* DF1_COEFF_L2 - [15:0] */ -#define WM8962_DF1_COEFF_L2_SHIFT 0 /* DF1_COEFF_L2 - [15:0] */ -#define WM8962_DF1_COEFF_L2_WIDTH 16 /* DF1_COEFF_L2 - [15:0] */ - -/* - * R260 (0x104) - DF5 - */ -#define WM8962_DF1_COEFF_R0_MASK 0xFFFF /* DF1_COEFF_R0 - [15:0] */ -#define WM8962_DF1_COEFF_R0_SHIFT 0 /* DF1_COEFF_R0 - [15:0] */ -#define WM8962_DF1_COEFF_R0_WIDTH 16 /* DF1_COEFF_R0 - [15:0] */ - -/* - * R261 (0x105) - DF6 - */ -#define WM8962_DF1_COEFF_R1_MASK 0xFFFF /* DF1_COEFF_R1 - [15:0] */ -#define WM8962_DF1_COEFF_R1_SHIFT 0 /* DF1_COEFF_R1 - [15:0] */ -#define WM8962_DF1_COEFF_R1_WIDTH 16 /* DF1_COEFF_R1 - [15:0] */ - -/* - * R262 (0x106) - DF7 - */ -#define WM8962_DF1_COEFF_R2_MASK 0xFFFF /* DF1_COEFF_R2 - [15:0] */ -#define WM8962_DF1_COEFF_R2_SHIFT 0 /* DF1_COEFF_R2 - [15:0] */ -#define WM8962_DF1_COEFF_R2_WIDTH 16 /* DF1_COEFF_R2 - [15:0] */ - -/* - * R264 (0x108) - LHPF1 - */ -#define WM8962_LHPF_MODE 0x0002 /* LHPF_MODE */ -#define WM8962_LHPF_MODE_MASK 0x0002 /* LHPF_MODE */ -#define WM8962_LHPF_MODE_SHIFT 1 /* LHPF_MODE */ -#define WM8962_LHPF_MODE_WIDTH 1 /* LHPF_MODE */ -#define WM8962_LHPF_ENA 0x0001 /* LHPF_ENA */ -#define WM8962_LHPF_ENA_MASK 0x0001 /* LHPF_ENA */ -#define WM8962_LHPF_ENA_SHIFT 0 /* LHPF_ENA */ -#define WM8962_LHPF_ENA_WIDTH 1 /* LHPF_ENA */ - -/* - * R265 (0x109) - LHPF2 - */ -#define WM8962_LHPF_COEFF_MASK 0xFFFF /* LHPF_COEFF - [15:0] */ -#define WM8962_LHPF_COEFF_SHIFT 0 /* LHPF_COEFF - [15:0] */ -#define WM8962_LHPF_COEFF_WIDTH 16 /* LHPF_COEFF - [15:0] */ - -/* - * R268 (0x10C) - THREED1 - */ -#define WM8962_ADC_MONOMIX 0x0040 /* ADC_MONOMIX */ -#define WM8962_ADC_MONOMIX_MASK 0x0040 /* ADC_MONOMIX */ -#define WM8962_ADC_MONOMIX_SHIFT 6 /* ADC_MONOMIX */ -#define WM8962_ADC_MONOMIX_WIDTH 1 /* ADC_MONOMIX */ -#define WM8962_THREED_SIGN_L 0x0020 /* THREED_SIGN_L */ -#define WM8962_THREED_SIGN_L_MASK 0x0020 /* THREED_SIGN_L */ -#define WM8962_THREED_SIGN_L_SHIFT 5 /* THREED_SIGN_L */ -#define WM8962_THREED_SIGN_L_WIDTH 1 /* THREED_SIGN_L */ -#define WM8962_THREED_SIGN_R 0x0010 /* THREED_SIGN_R */ -#define WM8962_THREED_SIGN_R_MASK 0x0010 /* THREED_SIGN_R */ -#define WM8962_THREED_SIGN_R_SHIFT 4 /* THREED_SIGN_R */ -#define WM8962_THREED_SIGN_R_WIDTH 1 /* THREED_SIGN_R */ -#define WM8962_THREED_LHPF_MODE 0x0004 /* THREED_LHPF_MODE */ -#define WM8962_THREED_LHPF_MODE_MASK 0x0004 /* THREED_LHPF_MODE */ -#define WM8962_THREED_LHPF_MODE_SHIFT 2 /* THREED_LHPF_MODE */ -#define WM8962_THREED_LHPF_MODE_WIDTH 1 /* THREED_LHPF_MODE */ -#define WM8962_THREED_LHPF_ENA 0x0002 /* THREED_LHPF_ENA */ -#define WM8962_THREED_LHPF_ENA_MASK 0x0002 /* THREED_LHPF_ENA */ -#define WM8962_THREED_LHPF_ENA_SHIFT 1 /* THREED_LHPF_ENA */ -#define WM8962_THREED_LHPF_ENA_WIDTH 1 /* THREED_LHPF_ENA */ -#define WM8962_THREED_ENA 0x0001 /* THREED_ENA */ -#define WM8962_THREED_ENA_MASK 0x0001 /* THREED_ENA */ -#define WM8962_THREED_ENA_SHIFT 0 /* THREED_ENA */ -#define WM8962_THREED_ENA_WIDTH 1 /* THREED_ENA */ - -/* - * R269 (0x10D) - THREED2 - */ -#define WM8962_THREED_FGAINL_MASK 0xF800 /* THREED_FGAINL - [15:11] */ -#define WM8962_THREED_FGAINL_SHIFT 11 /* THREED_FGAINL - [15:11] */ -#define WM8962_THREED_FGAINL_WIDTH 5 /* THREED_FGAINL - [15:11] */ -#define WM8962_THREED_CGAINL_MASK 0x07C0 /* THREED_CGAINL - [10:6] */ -#define WM8962_THREED_CGAINL_SHIFT 6 /* THREED_CGAINL - [10:6] */ -#define WM8962_THREED_CGAINL_WIDTH 5 /* THREED_CGAINL - [10:6] */ -#define WM8962_THREED_DELAYL_MASK 0x003C /* THREED_DELAYL - [5:2] */ -#define WM8962_THREED_DELAYL_SHIFT 2 /* THREED_DELAYL - [5:2] */ -#define WM8962_THREED_DELAYL_WIDTH 4 /* THREED_DELAYL - [5:2] */ - -/* - * R270 (0x10E) - THREED3 - */ -#define WM8962_THREED_LHPF_COEFF_MASK 0xFFFF /* THREED_LHPF_COEFF - [15:0] */ -#define WM8962_THREED_LHPF_COEFF_SHIFT 0 /* THREED_LHPF_COEFF - [15:0] */ -#define WM8962_THREED_LHPF_COEFF_WIDTH 16 /* THREED_LHPF_COEFF - [15:0] */ - -/* - * R271 (0x10F) - THREED4 - */ -#define WM8962_THREED_FGAINR_MASK 0xF800 /* THREED_FGAINR - [15:11] */ -#define WM8962_THREED_FGAINR_SHIFT 11 /* THREED_FGAINR - [15:11] */ -#define WM8962_THREED_FGAINR_WIDTH 5 /* THREED_FGAINR - [15:11] */ -#define WM8962_THREED_CGAINR_MASK 0x07C0 /* THREED_CGAINR - [10:6] */ -#define WM8962_THREED_CGAINR_SHIFT 6 /* THREED_CGAINR - [10:6] */ -#define WM8962_THREED_CGAINR_WIDTH 5 /* THREED_CGAINR - [10:6] */ -#define WM8962_THREED_DELAYR_MASK 0x003C /* THREED_DELAYR - [5:2] */ -#define WM8962_THREED_DELAYR_SHIFT 2 /* THREED_DELAYR - [5:2] */ -#define WM8962_THREED_DELAYR_WIDTH 4 /* THREED_DELAYR - [5:2] */ - -/* - * R276 (0x114) - DRC 1 - */ -#define WM8962_DRC_SIG_DET_RMS_MASK 0x7C00 /* DRC_SIG_DET_RMS - [14:10] */ -#define WM8962_DRC_SIG_DET_RMS_SHIFT 10 /* DRC_SIG_DET_RMS - [14:10] */ -#define WM8962_DRC_SIG_DET_RMS_WIDTH 5 /* DRC_SIG_DET_RMS - [14:10] */ -#define WM8962_DRC_SIG_DET_PK_MASK 0x0300 /* DRC_SIG_DET_PK - [9:8] */ -#define WM8962_DRC_SIG_DET_PK_SHIFT 8 /* DRC_SIG_DET_PK - [9:8] */ -#define WM8962_DRC_SIG_DET_PK_WIDTH 2 /* DRC_SIG_DET_PK - [9:8] */ -#define WM8962_DRC_NG_ENA 0x0080 /* DRC_NG_ENA */ -#define WM8962_DRC_NG_ENA_MASK 0x0080 /* DRC_NG_ENA */ -#define WM8962_DRC_NG_ENA_SHIFT 7 /* DRC_NG_ENA */ -#define WM8962_DRC_NG_ENA_WIDTH 1 /* DRC_NG_ENA */ -#define WM8962_DRC_SIG_DET_MODE 0x0040 /* DRC_SIG_DET_MODE */ -#define WM8962_DRC_SIG_DET_MODE_MASK 0x0040 /* DRC_SIG_DET_MODE */ -#define WM8962_DRC_SIG_DET_MODE_SHIFT 6 /* DRC_SIG_DET_MODE */ -#define WM8962_DRC_SIG_DET_MODE_WIDTH 1 /* DRC_SIG_DET_MODE */ -#define WM8962_DRC_SIG_DET 0x0020 /* DRC_SIG_DET */ -#define WM8962_DRC_SIG_DET_MASK 0x0020 /* DRC_SIG_DET */ -#define WM8962_DRC_SIG_DET_SHIFT 5 /* DRC_SIG_DET */ -#define WM8962_DRC_SIG_DET_WIDTH 1 /* DRC_SIG_DET */ -#define WM8962_DRC_KNEE2_OP_ENA 0x0010 /* DRC_KNEE2_OP_ENA */ -#define WM8962_DRC_KNEE2_OP_ENA_MASK 0x0010 /* DRC_KNEE2_OP_ENA */ -#define WM8962_DRC_KNEE2_OP_ENA_SHIFT 4 /* DRC_KNEE2_OP_ENA */ -#define WM8962_DRC_KNEE2_OP_ENA_WIDTH 1 /* DRC_KNEE2_OP_ENA */ -#define WM8962_DRC_QR 0x0008 /* DRC_QR */ -#define WM8962_DRC_QR_MASK 0x0008 /* DRC_QR */ -#define WM8962_DRC_QR_SHIFT 3 /* DRC_QR */ -#define WM8962_DRC_QR_WIDTH 1 /* DRC_QR */ -#define WM8962_DRC_ANTICLIP 0x0004 /* DRC_ANTICLIP */ -#define WM8962_DRC_ANTICLIP_MASK 0x0004 /* DRC_ANTICLIP */ -#define WM8962_DRC_ANTICLIP_SHIFT 2 /* DRC_ANTICLIP */ -#define WM8962_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */ -#define WM8962_DRC_MODE 0x0002 /* DRC_MODE */ -#define WM8962_DRC_MODE_MASK 0x0002 /* DRC_MODE */ -#define WM8962_DRC_MODE_SHIFT 1 /* DRC_MODE */ -#define WM8962_DRC_MODE_WIDTH 1 /* DRC_MODE */ -#define WM8962_DRC_ENA 0x0001 /* DRC_ENA */ -#define WM8962_DRC_ENA_MASK 0x0001 /* DRC_ENA */ -#define WM8962_DRC_ENA_SHIFT 0 /* DRC_ENA */ -#define WM8962_DRC_ENA_WIDTH 1 /* DRC_ENA */ - -/* - * R277 (0x115) - DRC 2 - */ -#define WM8962_DRC_ATK_MASK 0x1E00 /* DRC_ATK - [12:9] */ -#define WM8962_DRC_ATK_SHIFT 9 /* DRC_ATK - [12:9] */ -#define WM8962_DRC_ATK_WIDTH 4 /* DRC_ATK - [12:9] */ -#define WM8962_DRC_DCY_MASK 0x01E0 /* DRC_DCY - [8:5] */ -#define WM8962_DRC_DCY_SHIFT 5 /* DRC_DCY - [8:5] */ -#define WM8962_DRC_DCY_WIDTH 4 /* DRC_DCY - [8:5] */ -#define WM8962_DRC_MINGAIN_MASK 0x001C /* DRC_MINGAIN - [4:2] */ -#define WM8962_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [4:2] */ -#define WM8962_DRC_MINGAIN_WIDTH 3 /* DRC_MINGAIN - [4:2] */ -#define WM8962_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ -#define WM8962_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ -#define WM8962_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ - -/* - * R278 (0x116) - DRC 3 - */ -#define WM8962_DRC_NG_MINGAIN_MASK 0xF000 /* DRC_NG_MINGAIN - [15:12] */ -#define WM8962_DRC_NG_MINGAIN_SHIFT 12 /* DRC_NG_MINGAIN - [15:12] */ -#define WM8962_DRC_NG_MINGAIN_WIDTH 4 /* DRC_NG_MINGAIN - [15:12] */ -#define WM8962_DRC_QR_THR_MASK 0x0C00 /* DRC_QR_THR - [11:10] */ -#define WM8962_DRC_QR_THR_SHIFT 10 /* DRC_QR_THR - [11:10] */ -#define WM8962_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [11:10] */ -#define WM8962_DRC_QR_DCY_MASK 0x0300 /* DRC_QR_DCY - [9:8] */ -#define WM8962_DRC_QR_DCY_SHIFT 8 /* DRC_QR_DCY - [9:8] */ -#define WM8962_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [9:8] */ -#define WM8962_DRC_NG_EXP_MASK 0x00C0 /* DRC_NG_EXP - [7:6] */ -#define WM8962_DRC_NG_EXP_SHIFT 6 /* DRC_NG_EXP - [7:6] */ -#define WM8962_DRC_NG_EXP_WIDTH 2 /* DRC_NG_EXP - [7:6] */ -#define WM8962_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */ -#define WM8962_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */ -#define WM8962_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */ -#define WM8962_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */ -#define WM8962_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */ -#define WM8962_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */ - -/* - * R279 (0x117) - DRC 4 - */ -#define WM8962_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */ -#define WM8962_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */ -#define WM8962_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */ -#define WM8962_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */ -#define WM8962_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */ -#define WM8962_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */ - -/* - * R280 (0x118) - DRC 5 - */ -#define WM8962_DRC_KNEE2_IP_MASK 0x03E0 /* DRC_KNEE2_IP - [9:5] */ -#define WM8962_DRC_KNEE2_IP_SHIFT 5 /* DRC_KNEE2_IP - [9:5] */ -#define WM8962_DRC_KNEE2_IP_WIDTH 5 /* DRC_KNEE2_IP - [9:5] */ -#define WM8962_DRC_KNEE2_OP_MASK 0x001F /* DRC_KNEE2_OP - [4:0] */ -#define WM8962_DRC_KNEE2_OP_SHIFT 0 /* DRC_KNEE2_OP - [4:0] */ -#define WM8962_DRC_KNEE2_OP_WIDTH 5 /* DRC_KNEE2_OP - [4:0] */ - -/* - * R285 (0x11D) - Tloopback - */ -#define WM8962_TLB_ENA 0x0002 /* TLB_ENA */ -#define WM8962_TLB_ENA_MASK 0x0002 /* TLB_ENA */ -#define WM8962_TLB_ENA_SHIFT 1 /* TLB_ENA */ -#define WM8962_TLB_ENA_WIDTH 1 /* TLB_ENA */ -#define WM8962_TLB_MODE 0x0001 /* TLB_MODE */ -#define WM8962_TLB_MODE_MASK 0x0001 /* TLB_MODE */ -#define WM8962_TLB_MODE_SHIFT 0 /* TLB_MODE */ -#define WM8962_TLB_MODE_WIDTH 1 /* TLB_MODE */ - -/* - * R335 (0x14F) - EQ1 - */ -#define WM8962_EQ_SHARED_COEFF 0x0004 /* EQ_SHARED_COEFF */ -#define WM8962_EQ_SHARED_COEFF_MASK 0x0004 /* EQ_SHARED_COEFF */ -#define WM8962_EQ_SHARED_COEFF_SHIFT 2 /* EQ_SHARED_COEFF */ -#define WM8962_EQ_SHARED_COEFF_WIDTH 1 /* EQ_SHARED_COEFF */ -#define WM8962_EQ_SHARED_COEFF_SEL 0x0002 /* EQ_SHARED_COEFF_SEL */ -#define WM8962_EQ_SHARED_COEFF_SEL_MASK 0x0002 /* EQ_SHARED_COEFF_SEL */ -#define WM8962_EQ_SHARED_COEFF_SEL_SHIFT 1 /* EQ_SHARED_COEFF_SEL */ -#define WM8962_EQ_SHARED_COEFF_SEL_WIDTH 1 /* EQ_SHARED_COEFF_SEL */ -#define WM8962_EQ_ENA 0x0001 /* EQ_ENA */ -#define WM8962_EQ_ENA_MASK 0x0001 /* EQ_ENA */ -#define WM8962_EQ_ENA_SHIFT 0 /* EQ_ENA */ -#define WM8962_EQ_ENA_WIDTH 1 /* EQ_ENA */ - -/* - * R336 (0x150) - EQ2 - */ -#define WM8962_EQL_B1_GAIN_MASK 0xF800 /* EQL_B1_GAIN - [15:11] */ -#define WM8962_EQL_B1_GAIN_SHIFT 11 /* EQL_B1_GAIN - [15:11] */ -#define WM8962_EQL_B1_GAIN_WIDTH 5 /* EQL_B1_GAIN - [15:11] */ -#define WM8962_EQL_B2_GAIN_MASK 0x07C0 /* EQL_B2_GAIN - [10:6] */ -#define WM8962_EQL_B2_GAIN_SHIFT 6 /* EQL_B2_GAIN - [10:6] */ -#define WM8962_EQL_B2_GAIN_WIDTH 5 /* EQL_B2_GAIN - [10:6] */ -#define WM8962_EQL_B3_GAIN_MASK 0x003E /* EQL_B3_GAIN - [5:1] */ -#define WM8962_EQL_B3_GAIN_SHIFT 1 /* EQL_B3_GAIN - [5:1] */ -#define WM8962_EQL_B3_GAIN_WIDTH 5 /* EQL_B3_GAIN - [5:1] */ - -/* - * R337 (0x151) - EQ3 - */ -#define WM8962_EQL_B4_GAIN_MASK 0xF800 /* EQL_B4_GAIN - [15:11] */ -#define WM8962_EQL_B4_GAIN_SHIFT 11 /* EQL_B4_GAIN - [15:11] */ -#define WM8962_EQL_B4_GAIN_WIDTH 5 /* EQL_B4_GAIN - [15:11] */ -#define WM8962_EQL_B5_GAIN_MASK 0x07C0 /* EQL_B5_GAIN - [10:6] */ -#define WM8962_EQL_B5_GAIN_SHIFT 6 /* EQL_B5_GAIN - [10:6] */ -#define WM8962_EQL_B5_GAIN_WIDTH 5 /* EQL_B5_GAIN - [10:6] */ - -/* - * R338 (0x152) - EQ4 - */ -#define WM8962_EQL_B1_A_MASK 0xFFFF /* EQL_B1_A - [15:0] */ -#define WM8962_EQL_B1_A_SHIFT 0 /* EQL_B1_A - [15:0] */ -#define WM8962_EQL_B1_A_WIDTH 16 /* EQL_B1_A - [15:0] */ - -/* - * R339 (0x153) - EQ5 - */ -#define WM8962_EQL_B1_B_MASK 0xFFFF /* EQL_B1_B - [15:0] */ -#define WM8962_EQL_B1_B_SHIFT 0 /* EQL_B1_B - [15:0] */ -#define WM8962_EQL_B1_B_WIDTH 16 /* EQL_B1_B - [15:0] */ - -/* - * R340 (0x154) - EQ6 - */ -#define WM8962_EQL_B1_PG_MASK 0xFFFF /* EQL_B1_PG - [15:0] */ -#define WM8962_EQL_B1_PG_SHIFT 0 /* EQL_B1_PG - [15:0] */ -#define WM8962_EQL_B1_PG_WIDTH 16 /* EQL_B1_PG - [15:0] */ - -/* - * R341 (0x155) - EQ7 - */ -#define WM8962_EQL_B2_A_MASK 0xFFFF /* EQL_B2_A - [15:0] */ -#define WM8962_EQL_B2_A_SHIFT 0 /* EQL_B2_A - [15:0] */ -#define WM8962_EQL_B2_A_WIDTH 16 /* EQL_B2_A - [15:0] */ - -/* - * R342 (0x156) - EQ8 - */ -#define WM8962_EQL_B2_B_MASK 0xFFFF /* EQL_B2_B - [15:0] */ -#define WM8962_EQL_B2_B_SHIFT 0 /* EQL_B2_B - [15:0] */ -#define WM8962_EQL_B2_B_WIDTH 16 /* EQL_B2_B - [15:0] */ - -/* - * R343 (0x157) - EQ9 - */ -#define WM8962_EQL_B2_C_MASK 0xFFFF /* EQL_B2_C - [15:0] */ -#define WM8962_EQL_B2_C_SHIFT 0 /* EQL_B2_C - [15:0] */ -#define WM8962_EQL_B2_C_WIDTH 16 /* EQL_B2_C - [15:0] */ - -/* - * R344 (0x158) - EQ10 - */ -#define WM8962_EQL_B2_PG_MASK 0xFFFF /* EQL_B2_PG - [15:0] */ -#define WM8962_EQL_B2_PG_SHIFT 0 /* EQL_B2_PG - [15:0] */ -#define WM8962_EQL_B2_PG_WIDTH 16 /* EQL_B2_PG - [15:0] */ - -/* - * R345 (0x159) - EQ11 - */ -#define WM8962_EQL_B3_A_MASK 0xFFFF /* EQL_B3_A - [15:0] */ -#define WM8962_EQL_B3_A_SHIFT 0 /* EQL_B3_A - [15:0] */ -#define WM8962_EQL_B3_A_WIDTH 16 /* EQL_B3_A - [15:0] */ - -/* - * R346 (0x15A) - EQ12 - */ -#define WM8962_EQL_B3_B_MASK 0xFFFF /* EQL_B3_B - [15:0] */ -#define WM8962_EQL_B3_B_SHIFT 0 /* EQL_B3_B - [15:0] */ -#define WM8962_EQL_B3_B_WIDTH 16 /* EQL_B3_B - [15:0] */ - -/* - * R347 (0x15B) - EQ13 - */ -#define WM8962_EQL_B3_C_MASK 0xFFFF /* EQL_B3_C - [15:0] */ -#define WM8962_EQL_B3_C_SHIFT 0 /* EQL_B3_C - [15:0] */ -#define WM8962_EQL_B3_C_WIDTH 16 /* EQL_B3_C - [15:0] */ - -/* - * R348 (0x15C) - EQ14 - */ -#define WM8962_EQL_B3_PG_MASK 0xFFFF /* EQL_B3_PG - [15:0] */ -#define WM8962_EQL_B3_PG_SHIFT 0 /* EQL_B3_PG - [15:0] */ -#define WM8962_EQL_B3_PG_WIDTH 16 /* EQL_B3_PG - [15:0] */ - -/* - * R349 (0x15D) - EQ15 - */ -#define WM8962_EQL_B4_A_MASK 0xFFFF /* EQL_B4_A - [15:0] */ -#define WM8962_EQL_B4_A_SHIFT 0 /* EQL_B4_A - [15:0] */ -#define WM8962_EQL_B4_A_WIDTH 16 /* EQL_B4_A - [15:0] */ - -/* - * R350 (0x15E) - EQ16 - */ -#define WM8962_EQL_B4_B_MASK 0xFFFF /* EQL_B4_B - [15:0] */ -#define WM8962_EQL_B4_B_SHIFT 0 /* EQL_B4_B - [15:0] */ -#define WM8962_EQL_B4_B_WIDTH 16 /* EQL_B4_B - [15:0] */ - -/* - * R351 (0x15F) - EQ17 - */ -#define WM8962_EQL_B4_C_MASK 0xFFFF /* EQL_B4_C - [15:0] */ -#define WM8962_EQL_B4_C_SHIFT 0 /* EQL_B4_C - [15:0] */ -#define WM8962_EQL_B4_C_WIDTH 16 /* EQL_B4_C - [15:0] */ - -/* - * R352 (0x160) - EQ18 - */ -#define WM8962_EQL_B4_PG_MASK 0xFFFF /* EQL_B4_PG - [15:0] */ -#define WM8962_EQL_B4_PG_SHIFT 0 /* EQL_B4_PG - [15:0] */ -#define WM8962_EQL_B4_PG_WIDTH 16 /* EQL_B4_PG - [15:0] */ - -/* - * R353 (0x161) - EQ19 - */ -#define WM8962_EQL_B5_A_MASK 0xFFFF /* EQL_B5_A - [15:0] */ -#define WM8962_EQL_B5_A_SHIFT 0 /* EQL_B5_A - [15:0] */ -#define WM8962_EQL_B5_A_WIDTH 16 /* EQL_B5_A - [15:0] */ - -/* - * R354 (0x162) - EQ20 - */ -#define WM8962_EQL_B5_B_MASK 0xFFFF /* EQL_B5_B - [15:0] */ -#define WM8962_EQL_B5_B_SHIFT 0 /* EQL_B5_B - [15:0] */ -#define WM8962_EQL_B5_B_WIDTH 16 /* EQL_B5_B - [15:0] */ - -/* - * R355 (0x163) - EQ21 - */ -#define WM8962_EQL_B5_PG_MASK 0xFFFF /* EQL_B5_PG - [15:0] */ -#define WM8962_EQL_B5_PG_SHIFT 0 /* EQL_B5_PG - [15:0] */ -#define WM8962_EQL_B5_PG_WIDTH 16 /* EQL_B5_PG - [15:0] */ - -/* - * R356 (0x164) - EQ22 - */ -#define WM8962_EQR_B1_GAIN_MASK 0xF800 /* EQR_B1_GAIN - [15:11] */ -#define WM8962_EQR_B1_GAIN_SHIFT 11 /* EQR_B1_GAIN - [15:11] */ -#define WM8962_EQR_B1_GAIN_WIDTH 5 /* EQR_B1_GAIN - [15:11] */ -#define WM8962_EQR_B2_GAIN_MASK 0x07C0 /* EQR_B2_GAIN - [10:6] */ -#define WM8962_EQR_B2_GAIN_SHIFT 6 /* EQR_B2_GAIN - [10:6] */ -#define WM8962_EQR_B2_GAIN_WIDTH 5 /* EQR_B2_GAIN - [10:6] */ -#define WM8962_EQR_B3_GAIN_MASK 0x003E /* EQR_B3_GAIN - [5:1] */ -#define WM8962_EQR_B3_GAIN_SHIFT 1 /* EQR_B3_GAIN - [5:1] */ -#define WM8962_EQR_B3_GAIN_WIDTH 5 /* EQR_B3_GAIN - [5:1] */ - -/* - * R357 (0x165) - EQ23 - */ -#define WM8962_EQR_B4_GAIN_MASK 0xF800 /* EQR_B4_GAIN - [15:11] */ -#define WM8962_EQR_B4_GAIN_SHIFT 11 /* EQR_B4_GAIN - [15:11] */ -#define WM8962_EQR_B4_GAIN_WIDTH 5 /* EQR_B4_GAIN - [15:11] */ -#define WM8962_EQR_B5_GAIN_MASK 0x07C0 /* EQR_B5_GAIN - [10:6] */ -#define WM8962_EQR_B5_GAIN_SHIFT 6 /* EQR_B5_GAIN - [10:6] */ -#define WM8962_EQR_B5_GAIN_WIDTH 5 /* EQR_B5_GAIN - [10:6] */ - -/* - * R358 (0x166) - EQ24 - */ -#define WM8962_EQR_B1_A_MASK 0xFFFF /* EQR_B1_A - [15:0] */ -#define WM8962_EQR_B1_A_SHIFT 0 /* EQR_B1_A - [15:0] */ -#define WM8962_EQR_B1_A_WIDTH 16 /* EQR_B1_A - [15:0] */ - -/* - * R359 (0x167) - EQ25 - */ -#define WM8962_EQR_B1_B_MASK 0xFFFF /* EQR_B1_B - [15:0] */ -#define WM8962_EQR_B1_B_SHIFT 0 /* EQR_B1_B - [15:0] */ -#define WM8962_EQR_B1_B_WIDTH 16 /* EQR_B1_B - [15:0] */ - -/* - * R360 (0x168) - EQ26 - */ -#define WM8962_EQR_B1_PG_MASK 0xFFFF /* EQR_B1_PG - [15:0] */ -#define WM8962_EQR_B1_PG_SHIFT 0 /* EQR_B1_PG - [15:0] */ -#define WM8962_EQR_B1_PG_WIDTH 16 /* EQR_B1_PG - [15:0] */ - -/* - * R361 (0x169) - EQ27 - */ -#define WM8962_EQR_B2_A_MASK 0xFFFF /* EQR_B2_A - [15:0] */ -#define WM8962_EQR_B2_A_SHIFT 0 /* EQR_B2_A - [15:0] */ -#define WM8962_EQR_B2_A_WIDTH 16 /* EQR_B2_A - [15:0] */ - -/* - * R362 (0x16A) - EQ28 - */ -#define WM8962_EQR_B2_B_MASK 0xFFFF /* EQR_B2_B - [15:0] */ -#define WM8962_EQR_B2_B_SHIFT 0 /* EQR_B2_B - [15:0] */ -#define WM8962_EQR_B2_B_WIDTH 16 /* EQR_B2_B - [15:0] */ - -/* - * R363 (0x16B) - EQ29 - */ -#define WM8962_EQR_B2_C_MASK 0xFFFF /* EQR_B2_C - [15:0] */ -#define WM8962_EQR_B2_C_SHIFT 0 /* EQR_B2_C - [15:0] */ -#define WM8962_EQR_B2_C_WIDTH 16 /* EQR_B2_C - [15:0] */ - -/* - * R364 (0x16C) - EQ30 - */ -#define WM8962_EQR_B2_PG_MASK 0xFFFF /* EQR_B2_PG - [15:0] */ -#define WM8962_EQR_B2_PG_SHIFT 0 /* EQR_B2_PG - [15:0] */ -#define WM8962_EQR_B2_PG_WIDTH 16 /* EQR_B2_PG - [15:0] */ - -/* - * R365 (0x16D) - EQ31 - */ -#define WM8962_EQR_B3_A_MASK 0xFFFF /* EQR_B3_A - [15:0] */ -#define WM8962_EQR_B3_A_SHIFT 0 /* EQR_B3_A - [15:0] */ -#define WM8962_EQR_B3_A_WIDTH 16 /* EQR_B3_A - [15:0] */ - -/* - * R366 (0x16E) - EQ32 - */ -#define WM8962_EQR_B3_B_MASK 0xFFFF /* EQR_B3_B - [15:0] */ -#define WM8962_EQR_B3_B_SHIFT 0 /* EQR_B3_B - [15:0] */ -#define WM8962_EQR_B3_B_WIDTH 16 /* EQR_B3_B - [15:0] */ - -/* - * R367 (0x16F) - EQ33 - */ -#define WM8962_EQR_B3_C_MASK 0xFFFF /* EQR_B3_C - [15:0] */ -#define WM8962_EQR_B3_C_SHIFT 0 /* EQR_B3_C - [15:0] */ -#define WM8962_EQR_B3_C_WIDTH 16 /* EQR_B3_C - [15:0] */ - -/* - * R368 (0x170) - EQ34 - */ -#define WM8962_EQR_B3_PG_MASK 0xFFFF /* EQR_B3_PG - [15:0] */ -#define WM8962_EQR_B3_PG_SHIFT 0 /* EQR_B3_PG - [15:0] */ -#define WM8962_EQR_B3_PG_WIDTH 16 /* EQR_B3_PG - [15:0] */ - -/* - * R369 (0x171) - EQ35 - */ -#define WM8962_EQR_B4_A_MASK 0xFFFF /* EQR_B4_A - [15:0] */ -#define WM8962_EQR_B4_A_SHIFT 0 /* EQR_B4_A - [15:0] */ -#define WM8962_EQR_B4_A_WIDTH 16 /* EQR_B4_A - [15:0] */ - -/* - * R370 (0x172) - EQ36 - */ -#define WM8962_EQR_B4_B_MASK 0xFFFF /* EQR_B4_B - [15:0] */ -#define WM8962_EQR_B4_B_SHIFT 0 /* EQR_B4_B - [15:0] */ -#define WM8962_EQR_B4_B_WIDTH 16 /* EQR_B4_B - [15:0] */ - -/* - * R371 (0x173) - EQ37 - */ -#define WM8962_EQR_B4_C_MASK 0xFFFF /* EQR_B4_C - [15:0] */ -#define WM8962_EQR_B4_C_SHIFT 0 /* EQR_B4_C - [15:0] */ -#define WM8962_EQR_B4_C_WIDTH 16 /* EQR_B4_C - [15:0] */ - -/* - * R372 (0x174) - EQ38 - */ -#define WM8962_EQR_B4_PG_MASK 0xFFFF /* EQR_B4_PG - [15:0] */ -#define WM8962_EQR_B4_PG_SHIFT 0 /* EQR_B4_PG - [15:0] */ -#define WM8962_EQR_B4_PG_WIDTH 16 /* EQR_B4_PG - [15:0] */ - -/* - * R373 (0x175) - EQ39 - */ -#define WM8962_EQR_B5_A_MASK 0xFFFF /* EQR_B5_A - [15:0] */ -#define WM8962_EQR_B5_A_SHIFT 0 /* EQR_B5_A - [15:0] */ -#define WM8962_EQR_B5_A_WIDTH 16 /* EQR_B5_A - [15:0] */ - -/* - * R374 (0x176) - EQ40 - */ -#define WM8962_EQR_B5_B_MASK 0xFFFF /* EQR_B5_B - [15:0] */ -#define WM8962_EQR_B5_B_SHIFT 0 /* EQR_B5_B - [15:0] */ -#define WM8962_EQR_B5_B_WIDTH 16 /* EQR_B5_B - [15:0] */ - -/* - * R375 (0x177) - EQ41 - */ -#define WM8962_EQR_B5_PG_MASK 0xFFFF /* EQR_B5_PG - [15:0] */ -#define WM8962_EQR_B5_PG_SHIFT 0 /* EQR_B5_PG - [15:0] */ -#define WM8962_EQR_B5_PG_WIDTH 16 /* EQR_B5_PG - [15:0] */ - -/* - * R513 (0x201) - GPIO 2 - */ -#define WM8962_GP2_POL 0x0400 /* GP2_POL */ -#define WM8962_GP2_POL_MASK 0x0400 /* GP2_POL */ -#define WM8962_GP2_POL_SHIFT 10 /* GP2_POL */ -#define WM8962_GP2_POL_WIDTH 1 /* GP2_POL */ -#define WM8962_GP2_LVL 0x0040 /* GP2_LVL */ -#define WM8962_GP2_LVL_MASK 0x0040 /* GP2_LVL */ -#define WM8962_GP2_LVL_SHIFT 6 /* GP2_LVL */ -#define WM8962_GP2_LVL_WIDTH 1 /* GP2_LVL */ -#define WM8962_GP2_FN_MASK 0x001F /* GP2_FN - [4:0] */ -#define WM8962_GP2_FN_SHIFT 0 /* GP2_FN - [4:0] */ -#define WM8962_GP2_FN_WIDTH 5 /* GP2_FN - [4:0] */ - -/* - * R514 (0x202) - GPIO 3 - */ -#define WM8962_GP3_POL 0x0400 /* GP3_POL */ -#define WM8962_GP3_POL_MASK 0x0400 /* GP3_POL */ -#define WM8962_GP3_POL_SHIFT 10 /* GP3_POL */ -#define WM8962_GP3_POL_WIDTH 1 /* GP3_POL */ -#define WM8962_GP3_LVL 0x0040 /* GP3_LVL */ -#define WM8962_GP3_LVL_MASK 0x0040 /* GP3_LVL */ -#define WM8962_GP3_LVL_SHIFT 6 /* GP3_LVL */ -#define WM8962_GP3_LVL_WIDTH 1 /* GP3_LVL */ -#define WM8962_GP3_FN_MASK 0x001F /* GP3_FN - [4:0] */ -#define WM8962_GP3_FN_SHIFT 0 /* GP3_FN - [4:0] */ -#define WM8962_GP3_FN_WIDTH 5 /* GP3_FN - [4:0] */ - -/* - * R516 (0x204) - GPIO 5 - */ -#define WM8962_GP5_DIR 0x8000 /* GP5_DIR */ -#define WM8962_GP5_DIR_MASK 0x8000 /* GP5_DIR */ -#define WM8962_GP5_DIR_SHIFT 15 /* GP5_DIR */ -#define WM8962_GP5_DIR_WIDTH 1 /* GP5_DIR */ -#define WM8962_GP5_PU 0x4000 /* GP5_PU */ -#define WM8962_GP5_PU_MASK 0x4000 /* GP5_PU */ -#define WM8962_GP5_PU_SHIFT 14 /* GP5_PU */ -#define WM8962_GP5_PU_WIDTH 1 /* GP5_PU */ -#define WM8962_GP5_PD 0x2000 /* GP5_PD */ -#define WM8962_GP5_PD_MASK 0x2000 /* GP5_PD */ -#define WM8962_GP5_PD_SHIFT 13 /* GP5_PD */ -#define WM8962_GP5_PD_WIDTH 1 /* GP5_PD */ -#define WM8962_GP5_POL 0x0400 /* GP5_POL */ -#define WM8962_GP5_POL_MASK 0x0400 /* GP5_POL */ -#define WM8962_GP5_POL_SHIFT 10 /* GP5_POL */ -#define WM8962_GP5_POL_WIDTH 1 /* GP5_POL */ -#define WM8962_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */ -#define WM8962_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */ -#define WM8962_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */ -#define WM8962_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */ -#define WM8962_GP5_DB 0x0100 /* GP5_DB */ -#define WM8962_GP5_DB_MASK 0x0100 /* GP5_DB */ -#define WM8962_GP5_DB_SHIFT 8 /* GP5_DB */ -#define WM8962_GP5_DB_WIDTH 1 /* GP5_DB */ -#define WM8962_GP5_LVL 0x0040 /* GP5_LVL */ -#define WM8962_GP5_LVL_MASK 0x0040 /* GP5_LVL */ -#define WM8962_GP5_LVL_SHIFT 6 /* GP5_LVL */ -#define WM8962_GP5_LVL_WIDTH 1 /* GP5_LVL */ -#define WM8962_GP5_FN_MASK 0x001F /* GP5_FN - [4:0] */ -#define WM8962_GP5_FN_SHIFT 0 /* GP5_FN - [4:0] */ -#define WM8962_GP5_FN_WIDTH 5 /* GP5_FN - [4:0] */ - -/* - * R517 (0x205) - GPIO 6 - */ -#define WM8962_GP6_DIR 0x8000 /* GP6_DIR */ -#define WM8962_GP6_DIR_MASK 0x8000 /* GP6_DIR */ -#define WM8962_GP6_DIR_SHIFT 15 /* GP6_DIR */ -#define WM8962_GP6_DIR_WIDTH 1 /* GP6_DIR */ -#define WM8962_GP6_PU 0x4000 /* GP6_PU */ -#define WM8962_GP6_PU_MASK 0x4000 /* GP6_PU */ -#define WM8962_GP6_PU_SHIFT 14 /* GP6_PU */ -#define WM8962_GP6_PU_WIDTH 1 /* GP6_PU */ -#define WM8962_GP6_PD 0x2000 /* GP6_PD */ -#define WM8962_GP6_PD_MASK 0x2000 /* GP6_PD */ -#define WM8962_GP6_PD_SHIFT 13 /* GP6_PD */ -#define WM8962_GP6_PD_WIDTH 1 /* GP6_PD */ -#define WM8962_GP6_POL 0x0400 /* GP6_POL */ -#define WM8962_GP6_POL_MASK 0x0400 /* GP6_POL */ -#define WM8962_GP6_POL_SHIFT 10 /* GP6_POL */ -#define WM8962_GP6_POL_WIDTH 1 /* GP6_POL */ -#define WM8962_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */ -#define WM8962_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */ -#define WM8962_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */ -#define WM8962_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */ -#define WM8962_GP6_DB 0x0100 /* GP6_DB */ -#define WM8962_GP6_DB_MASK 0x0100 /* GP6_DB */ -#define WM8962_GP6_DB_SHIFT 8 /* GP6_DB */ -#define WM8962_GP6_DB_WIDTH 1 /* GP6_DB */ -#define WM8962_GP6_LVL 0x0040 /* GP6_LVL */ -#define WM8962_GP6_LVL_MASK 0x0040 /* GP6_LVL */ -#define WM8962_GP6_LVL_SHIFT 6 /* GP6_LVL */ -#define WM8962_GP6_LVL_WIDTH 1 /* GP6_LVL */ -#define WM8962_GP6_FN_MASK 0x001F /* GP6_FN - [4:0] */ -#define WM8962_GP6_FN_SHIFT 0 /* GP6_FN - [4:0] */ -#define WM8962_GP6_FN_WIDTH 5 /* GP6_FN - [4:0] */ - -/* - * R560 (0x230) - Interrupt Status 1 - */ -#define WM8962_GP6_EINT 0x0020 /* GP6_EINT */ -#define WM8962_GP6_EINT_MASK 0x0020 /* GP6_EINT */ -#define WM8962_GP6_EINT_SHIFT 5 /* GP6_EINT */ -#define WM8962_GP6_EINT_WIDTH 1 /* GP6_EINT */ -#define WM8962_GP5_EINT 0x0010 /* GP5_EINT */ -#define WM8962_GP5_EINT_MASK 0x0010 /* GP5_EINT */ -#define WM8962_GP5_EINT_SHIFT 4 /* GP5_EINT */ -#define WM8962_GP5_EINT_WIDTH 1 /* GP5_EINT */ - -/* - * R561 (0x231) - Interrupt Status 2 - */ -#define WM8962_MICSCD_EINT 0x8000 /* MICSCD_EINT */ -#define WM8962_MICSCD_EINT_MASK 0x8000 /* MICSCD_EINT */ -#define WM8962_MICSCD_EINT_SHIFT 15 /* MICSCD_EINT */ -#define WM8962_MICSCD_EINT_WIDTH 1 /* MICSCD_EINT */ -#define WM8962_MICD_EINT 0x4000 /* MICD_EINT */ -#define WM8962_MICD_EINT_MASK 0x4000 /* MICD_EINT */ -#define WM8962_MICD_EINT_SHIFT 14 /* MICD_EINT */ -#define WM8962_MICD_EINT_WIDTH 1 /* MICD_EINT */ -#define WM8962_FIFOS_ERR_EINT 0x2000 /* FIFOS_ERR_EINT */ -#define WM8962_FIFOS_ERR_EINT_MASK 0x2000 /* FIFOS_ERR_EINT */ -#define WM8962_FIFOS_ERR_EINT_SHIFT 13 /* FIFOS_ERR_EINT */ -#define WM8962_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */ -#define WM8962_ALC_LOCK_EINT 0x1000 /* ALC_LOCK_EINT */ -#define WM8962_ALC_LOCK_EINT_MASK 0x1000 /* ALC_LOCK_EINT */ -#define WM8962_ALC_LOCK_EINT_SHIFT 12 /* ALC_LOCK_EINT */ -#define WM8962_ALC_LOCK_EINT_WIDTH 1 /* ALC_LOCK_EINT */ -#define WM8962_ALC_THRESH_EINT 0x0800 /* ALC_THRESH_EINT */ -#define WM8962_ALC_THRESH_EINT_MASK 0x0800 /* ALC_THRESH_EINT */ -#define WM8962_ALC_THRESH_EINT_SHIFT 11 /* ALC_THRESH_EINT */ -#define WM8962_ALC_THRESH_EINT_WIDTH 1 /* ALC_THRESH_EINT */ -#define WM8962_ALC_SAT_EINT 0x0400 /* ALC_SAT_EINT */ -#define WM8962_ALC_SAT_EINT_MASK 0x0400 /* ALC_SAT_EINT */ -#define WM8962_ALC_SAT_EINT_SHIFT 10 /* ALC_SAT_EINT */ -#define WM8962_ALC_SAT_EINT_WIDTH 1 /* ALC_SAT_EINT */ -#define WM8962_ALC_PKOVR_EINT 0x0200 /* ALC_PKOVR_EINT */ -#define WM8962_ALC_PKOVR_EINT_MASK 0x0200 /* ALC_PKOVR_EINT */ -#define WM8962_ALC_PKOVR_EINT_SHIFT 9 /* ALC_PKOVR_EINT */ -#define WM8962_ALC_PKOVR_EINT_WIDTH 1 /* ALC_PKOVR_EINT */ -#define WM8962_ALC_NGATE_EINT 0x0100 /* ALC_NGATE_EINT */ -#define WM8962_ALC_NGATE_EINT_MASK 0x0100 /* ALC_NGATE_EINT */ -#define WM8962_ALC_NGATE_EINT_SHIFT 8 /* ALC_NGATE_EINT */ -#define WM8962_ALC_NGATE_EINT_WIDTH 1 /* ALC_NGATE_EINT */ -#define WM8962_WSEQ_DONE_EINT 0x0080 /* WSEQ_DONE_EINT */ -#define WM8962_WSEQ_DONE_EINT_MASK 0x0080 /* WSEQ_DONE_EINT */ -#define WM8962_WSEQ_DONE_EINT_SHIFT 7 /* WSEQ_DONE_EINT */ -#define WM8962_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */ -#define WM8962_DRC_ACTDET_EINT 0x0040 /* DRC_ACTDET_EINT */ -#define WM8962_DRC_ACTDET_EINT_MASK 0x0040 /* DRC_ACTDET_EINT */ -#define WM8962_DRC_ACTDET_EINT_SHIFT 6 /* DRC_ACTDET_EINT */ -#define WM8962_DRC_ACTDET_EINT_WIDTH 1 /* DRC_ACTDET_EINT */ -#define WM8962_FLL_LOCK_EINT 0x0020 /* FLL_LOCK_EINT */ -#define WM8962_FLL_LOCK_EINT_MASK 0x0020 /* FLL_LOCK_EINT */ -#define WM8962_FLL_LOCK_EINT_SHIFT 5 /* FLL_LOCK_EINT */ -#define WM8962_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ -#define WM8962_PLL3_LOCK_EINT 0x0008 /* PLL3_LOCK_EINT */ -#define WM8962_PLL3_LOCK_EINT_MASK 0x0008 /* PLL3_LOCK_EINT */ -#define WM8962_PLL3_LOCK_EINT_SHIFT 3 /* PLL3_LOCK_EINT */ -#define WM8962_PLL3_LOCK_EINT_WIDTH 1 /* PLL3_LOCK_EINT */ -#define WM8962_PLL2_LOCK_EINT 0x0004 /* PLL2_LOCK_EINT */ -#define WM8962_PLL2_LOCK_EINT_MASK 0x0004 /* PLL2_LOCK_EINT */ -#define WM8962_PLL2_LOCK_EINT_SHIFT 2 /* PLL2_LOCK_EINT */ -#define WM8962_PLL2_LOCK_EINT_WIDTH 1 /* PLL2_LOCK_EINT */ -#define WM8962_TEMP_SHUT_EINT 0x0001 /* TEMP_SHUT_EINT */ -#define WM8962_TEMP_SHUT_EINT_MASK 0x0001 /* TEMP_SHUT_EINT */ -#define WM8962_TEMP_SHUT_EINT_SHIFT 0 /* TEMP_SHUT_EINT */ -#define WM8962_TEMP_SHUT_EINT_WIDTH 1 /* TEMP_SHUT_EINT */ - -/* - * R568 (0x238) - Interrupt Status 1 Mask - */ -#define WM8962_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */ -#define WM8962_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */ -#define WM8962_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */ -#define WM8962_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */ -#define WM8962_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */ -#define WM8962_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */ -#define WM8962_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */ -#define WM8962_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */ - -/* - * R569 (0x239) - Interrupt Status 2 Mask - */ -#define WM8962_IM_MICSCD_EINT 0x8000 /* IM_MICSCD_EINT */ -#define WM8962_IM_MICSCD_EINT_MASK 0x8000 /* IM_MICSCD_EINT */ -#define WM8962_IM_MICSCD_EINT_SHIFT 15 /* IM_MICSCD_EINT */ -#define WM8962_IM_MICSCD_EINT_WIDTH 1 /* IM_MICSCD_EINT */ -#define WM8962_IM_MICD_EINT 0x4000 /* IM_MICD_EINT */ -#define WM8962_IM_MICD_EINT_MASK 0x4000 /* IM_MICD_EINT */ -#define WM8962_IM_MICD_EINT_SHIFT 14 /* IM_MICD_EINT */ -#define WM8962_IM_MICD_EINT_WIDTH 1 /* IM_MICD_EINT */ -#define WM8962_IM_FIFOS_ERR_EINT 0x2000 /* IM_FIFOS_ERR_EINT */ -#define WM8962_IM_FIFOS_ERR_EINT_MASK 0x2000 /* IM_FIFOS_ERR_EINT */ -#define WM8962_IM_FIFOS_ERR_EINT_SHIFT 13 /* IM_FIFOS_ERR_EINT */ -#define WM8962_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */ -#define WM8962_IM_ALC_LOCK_EINT 0x1000 /* IM_ALC_LOCK_EINT */ -#define WM8962_IM_ALC_LOCK_EINT_MASK 0x1000 /* IM_ALC_LOCK_EINT */ -#define WM8962_IM_ALC_LOCK_EINT_SHIFT 12 /* IM_ALC_LOCK_EINT */ -#define WM8962_IM_ALC_LOCK_EINT_WIDTH 1 /* IM_ALC_LOCK_EINT */ -#define WM8962_IM_ALC_THRESH_EINT 0x0800 /* IM_ALC_THRESH_EINT */ -#define WM8962_IM_ALC_THRESH_EINT_MASK 0x0800 /* IM_ALC_THRESH_EINT */ -#define WM8962_IM_ALC_THRESH_EINT_SHIFT 11 /* IM_ALC_THRESH_EINT */ -#define WM8962_IM_ALC_THRESH_EINT_WIDTH 1 /* IM_ALC_THRESH_EINT */ -#define WM8962_IM_ALC_SAT_EINT 0x0400 /* IM_ALC_SAT_EINT */ -#define WM8962_IM_ALC_SAT_EINT_MASK 0x0400 /* IM_ALC_SAT_EINT */ -#define WM8962_IM_ALC_SAT_EINT_SHIFT 10 /* IM_ALC_SAT_EINT */ -#define WM8962_IM_ALC_SAT_EINT_WIDTH 1 /* IM_ALC_SAT_EINT */ -#define WM8962_IM_ALC_PKOVR_EINT 0x0200 /* IM_ALC_PKOVR_EINT */ -#define WM8962_IM_ALC_PKOVR_EINT_MASK 0x0200 /* IM_ALC_PKOVR_EINT */ -#define WM8962_IM_ALC_PKOVR_EINT_SHIFT 9 /* IM_ALC_PKOVR_EINT */ -#define WM8962_IM_ALC_PKOVR_EINT_WIDTH 1 /* IM_ALC_PKOVR_EINT */ -#define WM8962_IM_ALC_NGATE_EINT 0x0100 /* IM_ALC_NGATE_EINT */ -#define WM8962_IM_ALC_NGATE_EINT_MASK 0x0100 /* IM_ALC_NGATE_EINT */ -#define WM8962_IM_ALC_NGATE_EINT_SHIFT 8 /* IM_ALC_NGATE_EINT */ -#define WM8962_IM_ALC_NGATE_EINT_WIDTH 1 /* IM_ALC_NGATE_EINT */ -#define WM8962_IM_WSEQ_DONE_EINT 0x0080 /* IM_WSEQ_DONE_EINT */ -#define WM8962_IM_WSEQ_DONE_EINT_MASK 0x0080 /* IM_WSEQ_DONE_EINT */ -#define WM8962_IM_WSEQ_DONE_EINT_SHIFT 7 /* IM_WSEQ_DONE_EINT */ -#define WM8962_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */ -#define WM8962_IM_DRC_ACTDET_EINT 0x0040 /* IM_DRC_ACTDET_EINT */ -#define WM8962_IM_DRC_ACTDET_EINT_MASK 0x0040 /* IM_DRC_ACTDET_EINT */ -#define WM8962_IM_DRC_ACTDET_EINT_SHIFT 6 /* IM_DRC_ACTDET_EINT */ -#define WM8962_IM_DRC_ACTDET_EINT_WIDTH 1 /* IM_DRC_ACTDET_EINT */ -#define WM8962_IM_FLL_LOCK_EINT 0x0020 /* IM_FLL_LOCK_EINT */ -#define WM8962_IM_FLL_LOCK_EINT_MASK 0x0020 /* IM_FLL_LOCK_EINT */ -#define WM8962_IM_FLL_LOCK_EINT_SHIFT 5 /* IM_FLL_LOCK_EINT */ -#define WM8962_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ -#define WM8962_IM_PLL3_LOCK_EINT 0x0008 /* IM_PLL3_LOCK_EINT */ -#define WM8962_IM_PLL3_LOCK_EINT_MASK 0x0008 /* IM_PLL3_LOCK_EINT */ -#define WM8962_IM_PLL3_LOCK_EINT_SHIFT 3 /* IM_PLL3_LOCK_EINT */ -#define WM8962_IM_PLL3_LOCK_EINT_WIDTH 1 /* IM_PLL3_LOCK_EINT */ -#define WM8962_IM_PLL2_LOCK_EINT 0x0004 /* IM_PLL2_LOCK_EINT */ -#define WM8962_IM_PLL2_LOCK_EINT_MASK 0x0004 /* IM_PLL2_LOCK_EINT */ -#define WM8962_IM_PLL2_LOCK_EINT_SHIFT 2 /* IM_PLL2_LOCK_EINT */ -#define WM8962_IM_PLL2_LOCK_EINT_WIDTH 1 /* IM_PLL2_LOCK_EINT */ -#define WM8962_IM_TEMP_SHUT_EINT 0x0001 /* IM_TEMP_SHUT_EINT */ -#define WM8962_IM_TEMP_SHUT_EINT_MASK 0x0001 /* IM_TEMP_SHUT_EINT */ -#define WM8962_IM_TEMP_SHUT_EINT_SHIFT 0 /* IM_TEMP_SHUT_EINT */ -#define WM8962_IM_TEMP_SHUT_EINT_WIDTH 1 /* IM_TEMP_SHUT_EINT */ - -/* - * R576 (0x240) - Interrupt Control - */ -#define WM8962_IRQ_POL 0x0001 /* IRQ_POL */ -#define WM8962_IRQ_POL_MASK 0x0001 /* IRQ_POL */ -#define WM8962_IRQ_POL_SHIFT 0 /* IRQ_POL */ -#define WM8962_IRQ_POL_WIDTH 1 /* IRQ_POL */ - -/* - * R584 (0x248) - IRQ Debounce - */ -#define WM8962_FLL_LOCK_DB 0x0020 /* FLL_LOCK_DB */ -#define WM8962_FLL_LOCK_DB_MASK 0x0020 /* FLL_LOCK_DB */ -#define WM8962_FLL_LOCK_DB_SHIFT 5 /* FLL_LOCK_DB */ -#define WM8962_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */ -#define WM8962_PLL3_LOCK_DB 0x0008 /* PLL3_LOCK_DB */ -#define WM8962_PLL3_LOCK_DB_MASK 0x0008 /* PLL3_LOCK_DB */ -#define WM8962_PLL3_LOCK_DB_SHIFT 3 /* PLL3_LOCK_DB */ -#define WM8962_PLL3_LOCK_DB_WIDTH 1 /* PLL3_LOCK_DB */ -#define WM8962_PLL2_LOCK_DB 0x0004 /* PLL2_LOCK_DB */ -#define WM8962_PLL2_LOCK_DB_MASK 0x0004 /* PLL2_LOCK_DB */ -#define WM8962_PLL2_LOCK_DB_SHIFT 2 /* PLL2_LOCK_DB */ -#define WM8962_PLL2_LOCK_DB_WIDTH 1 /* PLL2_LOCK_DB */ -#define WM8962_TEMP_SHUT_DB 0x0001 /* TEMP_SHUT_DB */ -#define WM8962_TEMP_SHUT_DB_MASK 0x0001 /* TEMP_SHUT_DB */ -#define WM8962_TEMP_SHUT_DB_SHIFT 0 /* TEMP_SHUT_DB */ -#define WM8962_TEMP_SHUT_DB_WIDTH 1 /* TEMP_SHUT_DB */ - -/* - * R586 (0x24A) - MICINT Source Pol - */ -#define WM8962_MICSCD_IRQ_POL 0x8000 /* MICSCD_IRQ_POL */ -#define WM8962_MICSCD_IRQ_POL_MASK 0x8000 /* MICSCD_IRQ_POL */ -#define WM8962_MICSCD_IRQ_POL_SHIFT 15 /* MICSCD_IRQ_POL */ -#define WM8962_MICSCD_IRQ_POL_WIDTH 1 /* MICSCD_IRQ_POL */ -#define WM8962_MICD_IRQ_POL 0x4000 /* MICD_IRQ_POL */ -#define WM8962_MICD_IRQ_POL_MASK 0x4000 /* MICD_IRQ_POL */ -#define WM8962_MICD_IRQ_POL_SHIFT 14 /* MICD_IRQ_POL */ -#define WM8962_MICD_IRQ_POL_WIDTH 1 /* MICD_IRQ_POL */ - -/* - * R768 (0x300) - DSP2 Power Management - */ -#define WM8962_DSP2_ENA 0x0001 /* DSP2_ENA */ -#define WM8962_DSP2_ENA_MASK 0x0001 /* DSP2_ENA */ -#define WM8962_DSP2_ENA_SHIFT 0 /* DSP2_ENA */ -#define WM8962_DSP2_ENA_WIDTH 1 /* DSP2_ENA */ - -/* - * R1037 (0x40D) - DSP2_ExecControl - */ -#define WM8962_DSP2_STOPC 0x0020 /* DSP2_STOPC */ -#define WM8962_DSP2_STOPC_MASK 0x0020 /* DSP2_STOPC */ -#define WM8962_DSP2_STOPC_SHIFT 5 /* DSP2_STOPC */ -#define WM8962_DSP2_STOPC_WIDTH 1 /* DSP2_STOPC */ -#define WM8962_DSP2_STOPS 0x0010 /* DSP2_STOPS */ -#define WM8962_DSP2_STOPS_MASK 0x0010 /* DSP2_STOPS */ -#define WM8962_DSP2_STOPS_SHIFT 4 /* DSP2_STOPS */ -#define WM8962_DSP2_STOPS_WIDTH 1 /* DSP2_STOPS */ -#define WM8962_DSP2_STOPI 0x0008 /* DSP2_STOPI */ -#define WM8962_DSP2_STOPI_MASK 0x0008 /* DSP2_STOPI */ -#define WM8962_DSP2_STOPI_SHIFT 3 /* DSP2_STOPI */ -#define WM8962_DSP2_STOPI_WIDTH 1 /* DSP2_STOPI */ -#define WM8962_DSP2_STOP 0x0004 /* DSP2_STOP */ -#define WM8962_DSP2_STOP_MASK 0x0004 /* DSP2_STOP */ -#define WM8962_DSP2_STOP_SHIFT 2 /* DSP2_STOP */ -#define WM8962_DSP2_STOP_WIDTH 1 /* DSP2_STOP */ -#define WM8962_DSP2_RUNR 0x0002 /* DSP2_RUNR */ -#define WM8962_DSP2_RUNR_MASK 0x0002 /* DSP2_RUNR */ -#define WM8962_DSP2_RUNR_SHIFT 1 /* DSP2_RUNR */ -#define WM8962_DSP2_RUNR_WIDTH 1 /* DSP2_RUNR */ -#define WM8962_DSP2_RUN 0x0001 /* DSP2_RUN */ -#define WM8962_DSP2_RUN_MASK 0x0001 /* DSP2_RUN */ -#define WM8962_DSP2_RUN_SHIFT 0 /* DSP2_RUN */ -#define WM8962_DSP2_RUN_WIDTH 1 /* DSP2_RUN */ - -/* - * R8192 (0x2000) - DSP2 Instruction RAM 0 - */ -#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_MASK 0x03FF /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */ -#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_SHIFT 0 /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */ -#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_WIDTH 10 /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */ - -/* - * R9216 (0x2400) - DSP2 Address RAM 2 - */ -#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_MASK 0x003F /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */ -#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */ -#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_WIDTH 6 /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */ - -/* - * R9217 (0x2401) - DSP2 Address RAM 1 - */ -#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_MASK 0xFFFF /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */ -#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */ -#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_WIDTH 16 /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */ - -/* - * R9218 (0x2402) - DSP2 Address RAM 0 - */ -#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_MASK 0xFFFF /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */ -#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */ -#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_WIDTH 16 /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */ - -/* - * R12288 (0x3000) - DSP2 Data1 RAM 1 - */ -#define WM8962_DSP2_DATA1_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */ -#define WM8962_DSP2_DATA1_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */ -#define WM8962_DSP2_DATA1_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */ - -/* - * R12289 (0x3001) - DSP2 Data1 RAM 0 - */ -#define WM8962_DSP2_DATA1_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */ -#define WM8962_DSP2_DATA1_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */ -#define WM8962_DSP2_DATA1_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */ - -/* - * R13312 (0x3400) - DSP2 Data2 RAM 1 - */ -#define WM8962_DSP2_DATA2_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */ -#define WM8962_DSP2_DATA2_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */ -#define WM8962_DSP2_DATA2_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */ - -/* - * R13313 (0x3401) - DSP2 Data2 RAM 0 - */ -#define WM8962_DSP2_DATA2_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */ -#define WM8962_DSP2_DATA2_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */ -#define WM8962_DSP2_DATA2_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */ - -/* - * R14336 (0x3800) - DSP2 Data3 RAM 1 - */ -#define WM8962_DSP2_DATA3_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */ -#define WM8962_DSP2_DATA3_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */ -#define WM8962_DSP2_DATA3_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */ - -/* - * R14337 (0x3801) - DSP2 Data3 RAM 0 - */ -#define WM8962_DSP2_DATA3_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */ -#define WM8962_DSP2_DATA3_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */ -#define WM8962_DSP2_DATA3_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */ - -/* - * R15360 (0x3C00) - DSP2 Coeff RAM 0 - */ -#define WM8962_DSP2_CMAP_RAM_384_11_10_0_MASK 0x07FF /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */ -#define WM8962_DSP2_CMAP_RAM_384_11_10_0_SHIFT 0 /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */ -#define WM8962_DSP2_CMAP_RAM_384_11_10_0_WIDTH 11 /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */ - -/* - * R16384 (0x4000) - RETUNEADC_SHARED_COEFF_1 - */ -#define WM8962_ADC_RETUNE_SCV 0x0080 /* ADC_RETUNE_SCV */ -#define WM8962_ADC_RETUNE_SCV_MASK 0x0080 /* ADC_RETUNE_SCV */ -#define WM8962_ADC_RETUNE_SCV_SHIFT 7 /* ADC_RETUNE_SCV */ -#define WM8962_ADC_RETUNE_SCV_WIDTH 1 /* ADC_RETUNE_SCV */ -#define WM8962_RETUNEADC_SHARED_COEFF_22_16_MASK 0x007F /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */ -#define WM8962_RETUNEADC_SHARED_COEFF_22_16_SHIFT 0 /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */ -#define WM8962_RETUNEADC_SHARED_COEFF_22_16_WIDTH 7 /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */ - -/* - * R16385 (0x4001) - RETUNEADC_SHARED_COEFF_0 - */ -#define WM8962_RETUNEADC_SHARED_COEFF_15_00_MASK 0xFFFF /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */ -#define WM8962_RETUNEADC_SHARED_COEFF_15_00_SHIFT 0 /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */ -#define WM8962_RETUNEADC_SHARED_COEFF_15_00_WIDTH 16 /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */ - -/* - * R16386 (0x4002) - RETUNEDAC_SHARED_COEFF_1 - */ -#define WM8962_DAC_RETUNE_SCV 0x0080 /* DAC_RETUNE_SCV */ -#define WM8962_DAC_RETUNE_SCV_MASK 0x0080 /* DAC_RETUNE_SCV */ -#define WM8962_DAC_RETUNE_SCV_SHIFT 7 /* DAC_RETUNE_SCV */ -#define WM8962_DAC_RETUNE_SCV_WIDTH 1 /* DAC_RETUNE_SCV */ -#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_MASK 0x007F /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */ -#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_SHIFT 0 /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */ -#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_WIDTH 7 /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */ - -/* - * R16387 (0x4003) - RETUNEDAC_SHARED_COEFF_0 - */ -#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_MASK 0xFFFF /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */ -#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_SHIFT 0 /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */ -#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_WIDTH 16 /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */ - -/* - * R16388 (0x4004) - SOUNDSTAGE_ENABLES_1 - */ -#define WM8962_SOUNDSTAGE_ENABLES_23_16_MASK 0x00FF /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */ -#define WM8962_SOUNDSTAGE_ENABLES_23_16_SHIFT 0 /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */ -#define WM8962_SOUNDSTAGE_ENABLES_23_16_WIDTH 8 /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */ - -/* - * R16389 (0x4005) - SOUNDSTAGE_ENABLES_0 - */ -#define WM8962_SOUNDSTAGE_ENABLES_15_06_MASK 0xFFC0 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */ -#define WM8962_SOUNDSTAGE_ENABLES_15_06_SHIFT 6 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */ -#define WM8962_SOUNDSTAGE_ENABLES_15_06_WIDTH 10 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */ -#define WM8962_RTN_ADC_ENA 0x0020 /* RTN_ADC_ENA */ -#define WM8962_RTN_ADC_ENA_MASK 0x0020 /* RTN_ADC_ENA */ -#define WM8962_RTN_ADC_ENA_SHIFT 5 /* RTN_ADC_ENA */ -#define WM8962_RTN_ADC_ENA_WIDTH 1 /* RTN_ADC_ENA */ -#define WM8962_RTN_DAC_ENA 0x0010 /* RTN_DAC_ENA */ -#define WM8962_RTN_DAC_ENA_MASK 0x0010 /* RTN_DAC_ENA */ -#define WM8962_RTN_DAC_ENA_SHIFT 4 /* RTN_DAC_ENA */ -#define WM8962_RTN_DAC_ENA_WIDTH 1 /* RTN_DAC_ENA */ -#define WM8962_HDBASS_ENA 0x0008 /* HDBASS_ENA */ -#define WM8962_HDBASS_ENA_MASK 0x0008 /* HDBASS_ENA */ -#define WM8962_HDBASS_ENA_SHIFT 3 /* HDBASS_ENA */ -#define WM8962_HDBASS_ENA_WIDTH 1 /* HDBASS_ENA */ -#define WM8962_HPF2_ENA 0x0004 /* HPF2_ENA */ -#define WM8962_HPF2_ENA_MASK 0x0004 /* HPF2_ENA */ -#define WM8962_HPF2_ENA_SHIFT 2 /* HPF2_ENA */ -#define WM8962_HPF2_ENA_WIDTH 1 /* HPF2_ENA */ -#define WM8962_HPF1_ENA 0x0002 /* HPF1_ENA */ -#define WM8962_HPF1_ENA_MASK 0x0002 /* HPF1_ENA */ -#define WM8962_HPF1_ENA_SHIFT 1 /* HPF1_ENA */ -#define WM8962_HPF1_ENA_WIDTH 1 /* HPF1_ENA */ -#define WM8962_VSS_ENA 0x0001 /* VSS_ENA */ -#define WM8962_VSS_ENA_MASK 0x0001 /* VSS_ENA */ -#define WM8962_VSS_ENA_SHIFT 0 /* VSS_ENA */ -#define WM8962_VSS_ENA_WIDTH 1 /* VSS_ENA */ - -int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8971.c b/ANDROID_3.4.5/sound/soc/codecs/wm8971.c deleted file mode 100644 index 28fe59e3..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8971.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - * wm8971.c -- WM8971 ALSA SoC Audio driver - * - * Copyright 2005 Lab126, Inc. - * - * Author: Kenneth Kiraly - * - * Based on wm8753.c by Liam Girdwood - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8971.h" - -#define WM8971_REG_COUNT 43 - -static struct workqueue_struct *wm8971_workq = NULL; - -/* codec private data */ -struct wm8971_priv { - enum snd_soc_control_type control_type; - unsigned int sysclk; -}; - -/* - * wm8971 register cache - * We can't read the WM8971 register space when we - * are using 2 wire for device control, so we cache them instead. - */ -static const u16 wm8971_reg[] = { - 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */ - 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */ - 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */ - 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */ - 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */ - 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ - 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */ - 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */ - 0x0079, 0x0079, 0x0079, /* 40 */ -}; - -#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0) - -/* WM8971 Controls */ -static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; -static const char *wm8971_bass_filter[] = { "130Hz @ 48kHz", - "200Hz @ 48kHz" }; -static const char *wm8971_treble[] = { "8kHz", "4kHz" }; -static const char *wm8971_alc_func[] = { "Off", "Right", "Left", "Stereo" }; -static const char *wm8971_ng_type[] = { "Constant PGA Gain", - "Mute ADC Output" }; -static const char *wm8971_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; -static const char *wm8971_mono_mux[] = {"Stereo", "Mono (Left)", - "Mono (Right)", "Digital Mono"}; -static const char *wm8971_dac_phase[] = { "Non Inverted", "Inverted" }; -static const char *wm8971_lline_mux[] = {"Line", "NC", "NC", "PGA", - "Differential"}; -static const char *wm8971_rline_mux[] = {"Line", "Mic", "NC", "PGA", - "Differential"}; -static const char *wm8971_lpga_sel[] = {"Line", "NC", "NC", "Differential"}; -static const char *wm8971_rpga_sel[] = {"Line", "Mic", "NC", "Differential"}; -static const char *wm8971_adcpol[] = {"Normal", "L Invert", "R Invert", - "L + R Invert"}; - -static const struct soc_enum wm8971_enum[] = { - SOC_ENUM_SINGLE(WM8971_BASS, 7, 2, wm8971_bass), /* 0 */ - SOC_ENUM_SINGLE(WM8971_BASS, 6, 2, wm8971_bass_filter), - SOC_ENUM_SINGLE(WM8971_TREBLE, 6, 2, wm8971_treble), - SOC_ENUM_SINGLE(WM8971_ALC1, 7, 4, wm8971_alc_func), - SOC_ENUM_SINGLE(WM8971_NGATE, 1, 2, wm8971_ng_type), /* 4 */ - SOC_ENUM_SINGLE(WM8971_ADCDAC, 1, 4, wm8971_deemp), - SOC_ENUM_SINGLE(WM8971_ADCTL1, 4, 4, wm8971_mono_mux), - SOC_ENUM_SINGLE(WM8971_ADCTL1, 1, 2, wm8971_dac_phase), - SOC_ENUM_SINGLE(WM8971_LOUTM1, 0, 5, wm8971_lline_mux), /* 8 */ - SOC_ENUM_SINGLE(WM8971_ROUTM1, 0, 5, wm8971_rline_mux), - SOC_ENUM_SINGLE(WM8971_LADCIN, 6, 4, wm8971_lpga_sel), - SOC_ENUM_SINGLE(WM8971_RADCIN, 6, 4, wm8971_rpga_sel), - SOC_ENUM_SINGLE(WM8971_ADCDAC, 5, 4, wm8971_adcpol), /* 12 */ - SOC_ENUM_SINGLE(WM8971_ADCIN, 6, 4, wm8971_mono_mux), -}; - -static const struct snd_kcontrol_new wm8971_snd_controls[] = { - SOC_DOUBLE_R("Capture Volume", WM8971_LINVOL, WM8971_RINVOL, 0, 63, 0), - SOC_DOUBLE_R("Capture ZC Switch", WM8971_LINVOL, WM8971_RINVOL, - 6, 1, 0), - SOC_DOUBLE_R("Capture Switch", WM8971_LINVOL, WM8971_RINVOL, 7, 1, 1), - - SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8971_LOUT1V, - WM8971_ROUT1V, 7, 1, 0), - SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8971_LOUT2V, - WM8971_ROUT2V, 7, 1, 0), - SOC_SINGLE("Mono Playback ZC Switch", WM8971_MOUTV, 7, 1, 0), - - SOC_DOUBLE_R("PCM Volume", WM8971_LDAC, WM8971_RDAC, 0, 255, 0), - - SOC_DOUBLE_R("Bypass Left Playback Volume", WM8971_LOUTM1, - WM8971_LOUTM2, 4, 7, 1), - SOC_DOUBLE_R("Bypass Right Playback Volume", WM8971_ROUTM1, - WM8971_ROUTM2, 4, 7, 1), - SOC_DOUBLE_R("Bypass Mono Playback Volume", WM8971_MOUTM1, - WM8971_MOUTM2, 4, 7, 1), - - SOC_DOUBLE_R("Headphone Playback Volume", WM8971_LOUT1V, - WM8971_ROUT1V, 0, 127, 0), - SOC_DOUBLE_R("Speaker Playback Volume", WM8971_LOUT2V, - WM8971_ROUT2V, 0, 127, 0), - - SOC_ENUM("Bass Boost", wm8971_enum[0]), - SOC_ENUM("Bass Filter", wm8971_enum[1]), - SOC_SINGLE("Bass Volume", WM8971_BASS, 0, 7, 1), - - SOC_SINGLE("Treble Volume", WM8971_TREBLE, 0, 7, 0), - SOC_ENUM("Treble Cut-off", wm8971_enum[2]), - - SOC_SINGLE("Capture Filter Switch", WM8971_ADCDAC, 0, 1, 1), - - SOC_SINGLE("ALC Target Volume", WM8971_ALC1, 0, 7, 0), - SOC_SINGLE("ALC Max Volume", WM8971_ALC1, 4, 7, 0), - - SOC_SINGLE("ALC Capture Target Volume", WM8971_ALC1, 0, 7, 0), - SOC_SINGLE("ALC Capture Max Volume", WM8971_ALC1, 4, 7, 0), - SOC_ENUM("ALC Capture Function", wm8971_enum[3]), - SOC_SINGLE("ALC Capture ZC Switch", WM8971_ALC2, 7, 1, 0), - SOC_SINGLE("ALC Capture Hold Time", WM8971_ALC2, 0, 15, 0), - SOC_SINGLE("ALC Capture Decay Time", WM8971_ALC3, 4, 15, 0), - SOC_SINGLE("ALC Capture Attack Time", WM8971_ALC3, 0, 15, 0), - SOC_SINGLE("ALC Capture NG Threshold", WM8971_NGATE, 3, 31, 0), - SOC_ENUM("ALC Capture NG Type", wm8971_enum[4]), - SOC_SINGLE("ALC Capture NG Switch", WM8971_NGATE, 0, 1, 0), - - SOC_SINGLE("Capture 6dB Attenuate", WM8971_ADCDAC, 8, 1, 0), - SOC_SINGLE("Playback 6dB Attenuate", WM8971_ADCDAC, 7, 1, 0), - - SOC_ENUM("Playback De-emphasis", wm8971_enum[5]), - SOC_ENUM("Playback Function", wm8971_enum[6]), - SOC_ENUM("Playback Phase", wm8971_enum[7]), - - SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0), -}; - -/* - * DAPM Controls - */ - -/* Left Mixer */ -static const struct snd_kcontrol_new wm8971_left_mixer_controls[] = { -SOC_DAPM_SINGLE("Playback Switch", WM8971_LOUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_LOUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", WM8971_LOUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_LOUTM2, 7, 1, 0), -}; - -/* Right Mixer */ -static const struct snd_kcontrol_new wm8971_right_mixer_controls[] = { -SOC_DAPM_SINGLE("Left Playback Switch", WM8971_ROUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_ROUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Playback Switch", WM8971_ROUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_ROUTM2, 7, 1, 0), -}; - -/* Mono Mixer */ -static const struct snd_kcontrol_new wm8971_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("Left Playback Switch", WM8971_MOUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", WM8971_MOUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", WM8971_MOUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", WM8971_MOUTM2, 7, 1, 0), -}; - -/* Left Line Mux */ -static const struct snd_kcontrol_new wm8971_left_line_controls = -SOC_DAPM_ENUM("Route", wm8971_enum[8]); - -/* Right Line Mux */ -static const struct snd_kcontrol_new wm8971_right_line_controls = -SOC_DAPM_ENUM("Route", wm8971_enum[9]); - -/* Left PGA Mux */ -static const struct snd_kcontrol_new wm8971_left_pga_controls = -SOC_DAPM_ENUM("Route", wm8971_enum[10]); - -/* Right PGA Mux */ -static const struct snd_kcontrol_new wm8971_right_pga_controls = -SOC_DAPM_ENUM("Route", wm8971_enum[11]); - -/* Mono ADC Mux */ -static const struct snd_kcontrol_new wm8971_monomux_controls = -SOC_DAPM_ENUM("Route", wm8971_enum[13]); - -static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = { - SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, - &wm8971_left_mixer_controls[0], - ARRAY_SIZE(wm8971_left_mixer_controls)), - SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, - &wm8971_right_mixer_controls[0], - ARRAY_SIZE(wm8971_right_mixer_controls)), - SND_SOC_DAPM_MIXER("Mono Mixer", WM8971_PWR2, 2, 0, - &wm8971_mono_mixer_controls[0], - ARRAY_SIZE(wm8971_mono_mixer_controls)), - - SND_SOC_DAPM_PGA("Right Out 2", WM8971_PWR2, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 2", WM8971_PWR2, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Out 1", WM8971_PWR2, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 1", WM8971_PWR2, 6, 0, NULL, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8971_PWR2, 7, 0), - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8971_PWR2, 8, 0), - SND_SOC_DAPM_PGA("Mono Out 1", WM8971_PWR2, 2, 0, NULL, 0), - - SND_SOC_DAPM_SUPPLY("Mic Bias", WM8971_PWR1, 1, 0, NULL, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8971_PWR1, 2, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8971_PWR1, 3, 0), - - SND_SOC_DAPM_MUX("Left PGA Mux", WM8971_PWR1, 5, 0, - &wm8971_left_pga_controls), - SND_SOC_DAPM_MUX("Right PGA Mux", WM8971_PWR1, 4, 0, - &wm8971_right_pga_controls), - SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, - &wm8971_left_line_controls), - SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, - &wm8971_right_line_controls), - - SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, - &wm8971_monomux_controls), - SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, - &wm8971_monomux_controls), - - SND_SOC_DAPM_OUTPUT("LOUT1"), - SND_SOC_DAPM_OUTPUT("ROUT1"), - SND_SOC_DAPM_OUTPUT("LOUT2"), - SND_SOC_DAPM_OUTPUT("ROUT2"), - SND_SOC_DAPM_OUTPUT("MONO"), - - SND_SOC_DAPM_INPUT("LINPUT1"), - SND_SOC_DAPM_INPUT("RINPUT1"), - SND_SOC_DAPM_INPUT("MIC"), -}; - -static const struct snd_soc_dapm_route wm8971_dapm_routes[] = { - /* left mixer */ - {"Left Mixer", "Playback Switch", "Left DAC"}, - {"Left Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Left Mixer", "Right Playback Switch", "Right DAC"}, - {"Left Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* right mixer */ - {"Right Mixer", "Left Playback Switch", "Left DAC"}, - {"Right Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Right Mixer", "Playback Switch", "Right DAC"}, - {"Right Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* left out 1 */ - {"Left Out 1", NULL, "Left Mixer"}, - {"LOUT1", NULL, "Left Out 1"}, - - /* left out 2 */ - {"Left Out 2", NULL, "Left Mixer"}, - {"LOUT2", NULL, "Left Out 2"}, - - /* right out 1 */ - {"Right Out 1", NULL, "Right Mixer"}, - {"ROUT1", NULL, "Right Out 1"}, - - /* right out 2 */ - {"Right Out 2", NULL, "Right Mixer"}, - {"ROUT2", NULL, "Right Out 2"}, - - /* mono mixer */ - {"Mono Mixer", "Left Playback Switch", "Left DAC"}, - {"Mono Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Mono Mixer", "Right Playback Switch", "Right DAC"}, - {"Mono Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* mono out */ - {"Mono Out", NULL, "Mono Mixer"}, - {"MONO1", NULL, "Mono Out"}, - - /* Left Line Mux */ - {"Left Line Mux", "Line", "LINPUT1"}, - {"Left Line Mux", "PGA", "Left PGA Mux"}, - {"Left Line Mux", "Differential", "Differential Mux"}, - - /* Right Line Mux */ - {"Right Line Mux", "Line", "RINPUT1"}, - {"Right Line Mux", "Mic", "MIC"}, - {"Right Line Mux", "PGA", "Right PGA Mux"}, - {"Right Line Mux", "Differential", "Differential Mux"}, - - /* Left PGA Mux */ - {"Left PGA Mux", "Line", "LINPUT1"}, - {"Left PGA Mux", "Differential", "Differential Mux"}, - - /* Right PGA Mux */ - {"Right PGA Mux", "Line", "RINPUT1"}, - {"Right PGA Mux", "Differential", "Differential Mux"}, - - /* Differential Mux */ - {"Differential Mux", "Line", "LINPUT1"}, - {"Differential Mux", "Line", "RINPUT1"}, - - /* Left ADC Mux */ - {"Left ADC Mux", "Stereo", "Left PGA Mux"}, - {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"}, - {"Left ADC Mux", "Digital Mono", "Left PGA Mux"}, - - /* Right ADC Mux */ - {"Right ADC Mux", "Stereo", "Right PGA Mux"}, - {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"}, - {"Right ADC Mux", "Digital Mono", "Right PGA Mux"}, - - /* ADC */ - {"Left ADC", NULL, "Left ADC Mux"}, - {"Right ADC", NULL, "Right ADC Mux"}, -}; - -struct _coeff_div { - u32 mclk; - u32 rate; - u16 fs; - u8 sr:5; - u8 usb:1; -}; - -/* codec hifi mclk clock divider coefficients */ -static const struct _coeff_div coeff_div[] = { - /* 8k */ - {12288000, 8000, 1536, 0x6, 0x0}, - {11289600, 8000, 1408, 0x16, 0x0}, - {18432000, 8000, 2304, 0x7, 0x0}, - {16934400, 8000, 2112, 0x17, 0x0}, - {12000000, 8000, 1500, 0x6, 0x1}, - - /* 11.025k */ - {11289600, 11025, 1024, 0x18, 0x0}, - {16934400, 11025, 1536, 0x19, 0x0}, - {12000000, 11025, 1088, 0x19, 0x1}, - - /* 16k */ - {12288000, 16000, 768, 0xa, 0x0}, - {18432000, 16000, 1152, 0xb, 0x0}, - {12000000, 16000, 750, 0xa, 0x1}, - - /* 22.05k */ - {11289600, 22050, 512, 0x1a, 0x0}, - {16934400, 22050, 768, 0x1b, 0x0}, - {12000000, 22050, 544, 0x1b, 0x1}, - - /* 32k */ - {12288000, 32000, 384, 0xc, 0x0}, - {18432000, 32000, 576, 0xd, 0x0}, - {12000000, 32000, 375, 0xa, 0x1}, - - /* 44.1k */ - {11289600, 44100, 256, 0x10, 0x0}, - {16934400, 44100, 384, 0x11, 0x0}, - {12000000, 44100, 272, 0x11, 0x1}, - - /* 48k */ - {12288000, 48000, 256, 0x0, 0x0}, - {18432000, 48000, 384, 0x1, 0x0}, - {12000000, 48000, 250, 0x0, 0x1}, - - /* 88.2k */ - {11289600, 88200, 128, 0x1e, 0x0}, - {16934400, 88200, 192, 0x1f, 0x0}, - {12000000, 88200, 136, 0x1f, 0x1}, - - /* 96k */ - {12288000, 96000, 128, 0xe, 0x0}, - {18432000, 96000, 192, 0xf, 0x0}, - {12000000, 96000, 125, 0xe, 0x1}, -}; - -static int get_coeff(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) - return i; - } - return -EINVAL; -} - -static int wm8971_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - wm8971->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface = 0x0040; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8971_IFACE, iface); - return 0; -} - -static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; - u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; - int coeff = get_coeff(wm8971->sysclk, params_rate(params)); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x000c; - break; - } - - /* set iface & srate */ - snd_soc_write(codec, WM8971_IFACE, iface); - if (coeff >= 0) - snd_soc_write(codec, WM8971_SRATE, srate | - (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); - - return 0; -} - -static int wm8971_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7; - - if (mute) - snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8); - else - snd_soc_write(codec, WM8971_ADCDAC, mute_reg); - return 0; -} - -static int wm8971_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; - - switch (level) { - case SND_SOC_BIAS_ON: - /* set vmid to 50k and unmute dac */ - snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) - snd_soc_cache_sync(codec); - - /* mute dac and set vmid to 500k, enable VREF */ - snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); - break; - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8971_PWR1, 0x0001); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8971_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) - -#define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8971_dai_ops = { - .hw_params = wm8971_pcm_hw_params, - .digital_mute = wm8971_mute, - .set_fmt = wm8971_set_dai_fmt, - .set_sysclk = wm8971_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver wm8971_dai = { - .name = "wm8971-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8971_RATES, - .formats = WM8971_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8971_RATES, - .formats = WM8971_FORMATS,}, - .ops = &wm8971_dai_ops, -}; - -static void wm8971_work(struct work_struct *work) -{ - struct snd_soc_dapm_context *dapm = - container_of(work, struct snd_soc_dapm_context, - delayed_work.work); - struct snd_soc_codec *codec = dapm->codec; - wm8971_set_bias_level(codec, codec->dapm.bias_level); -} - -static int wm8971_suspend(struct snd_soc_codec *codec) -{ - wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8971_resume(struct snd_soc_codec *codec) -{ - u16 reg; - - wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* charge wm8971 caps */ - if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { - reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; - snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); - codec->dapm.bias_level = SND_SOC_BIAS_ON; - queue_delayed_work(wm8971_workq, &codec->dapm.delayed_work, - msecs_to_jiffies(1000)); - } - - return 0; -} - -static int wm8971_probe(struct snd_soc_codec *codec) -{ - struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - u16 reg; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type); - if (ret < 0) { - printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); - return ret; - } - - INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work); - wm8971_workq = create_workqueue("wm8971"); - if (wm8971_workq == NULL) - return -ENOMEM; - - wm8971_reset(codec); - - /* charge output caps - set vmid to 5k for quick power up */ - reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; - snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); - codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; - queue_delayed_work(wm8971_workq, &codec->dapm.delayed_work, - msecs_to_jiffies(1000)); - - /* set the update bits */ - snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8971_LOUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8971_ROUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8971_LOUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8971_ROUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100); - - return ret; -} - - -/* power down chip */ -static int wm8971_remove(struct snd_soc_codec *codec) -{ - wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); - - if (wm8971_workq) - destroy_workqueue(wm8971_workq); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { - .probe = wm8971_probe, - .remove = wm8971_remove, - .suspend = wm8971_suspend, - .resume = wm8971_resume, - .set_bias_level = wm8971_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8971_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8971_reg, - - .controls = wm8971_snd_controls, - .num_controls = ARRAY_SIZE(wm8971_snd_controls), - .dapm_widgets = wm8971_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets), - .dapm_routes = wm8971_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes), -}; - -static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8971_priv *wm8971; - int ret; - - wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv), - GFP_KERNEL); - if (wm8971 == NULL) - return -ENOMEM; - - wm8971->control_type = SND_SOC_I2C; - i2c_set_clientdata(i2c, wm8971); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8971, &wm8971_dai, 1); - - return ret; -} - -static __devexit int wm8971_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} - -static const struct i2c_device_id wm8971_i2c_id[] = { - { "wm8971", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id); - -static struct i2c_driver wm8971_i2c_driver = { - .driver = { - .name = "wm8971", - .owner = THIS_MODULE, - }, - .probe = wm8971_i2c_probe, - .remove = __devexit_p(wm8971_i2c_remove), - .id_table = wm8971_i2c_id, -}; - -static int __init wm8971_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8971_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8971_modinit); - -static void __exit wm8971_exit(void) -{ - i2c_del_driver(&wm8971_i2c_driver); -} -module_exit(wm8971_exit); - -MODULE_DESCRIPTION("ASoC WM8971 driver"); -MODULE_AUTHOR("Lab126"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8971.h b/ANDROID_3.4.5/sound/soc/codecs/wm8971.h deleted file mode 100644 index f31c38fd..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8971.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * wm8971.h -- audio driver for WM8971 - * - * Copyright 2005 Lab126, Inc. - * - * Author: Kenneth Kiraly - * - * 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. - * - */ - -#ifndef _WM8971_H -#define _WM8971_H - -#define WM8971_LINVOL 0x00 -#define WM8971_RINVOL 0x01 -#define WM8971_LOUT1V 0x02 -#define WM8971_ROUT1V 0x03 -#define WM8971_ADCDAC 0x05 -#define WM8971_IFACE 0x07 -#define WM8971_SRATE 0x08 -#define WM8971_LDAC 0x0a -#define WM8971_RDAC 0x0b -#define WM8971_BASS 0x0c -#define WM8971_TREBLE 0x0d -#define WM8971_RESET 0x0f -#define WM8971_ALC1 0x11 -#define WM8971_ALC2 0x12 -#define WM8971_ALC3 0x13 -#define WM8971_NGATE 0x14 -#define WM8971_LADC 0x15 -#define WM8971_RADC 0x16 -#define WM8971_ADCTL1 0x17 -#define WM8971_ADCTL2 0x18 -#define WM8971_PWR1 0x19 -#define WM8971_PWR2 0x1a -#define WM8971_ADCTL3 0x1b -#define WM8971_ADCIN 0x1f -#define WM8971_LADCIN 0x20 -#define WM8971_RADCIN 0x21 -#define WM8971_LOUTM1 0x22 -#define WM8971_LOUTM2 0x23 -#define WM8971_ROUTM1 0x24 -#define WM8971_ROUTM2 0x25 -#define WM8971_MOUTM1 0x26 -#define WM8971_MOUTM2 0x27 -#define WM8971_LOUT2V 0x28 -#define WM8971_ROUT2V 0x29 -#define WM8971_MOUTV 0x2A - -#define WM8971_SYSCLK 0 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8974.c b/ANDROID_3.4.5/sound/soc/codecs/wm8974.c deleted file mode 100644 index d93c03f8..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8974.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * wm8974.c -- WM8974 ALSA Soc Audio driver - * - * Copyright 2006-2009 Wolfson Microelectronics PLC. - * - * Author: Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8974.h" - -static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0050, 0x0000, 0x0140, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00ff, - 0x0000, 0x0000, 0x0100, 0x00ff, - 0x0000, 0x0000, 0x012c, 0x002c, - 0x002c, 0x002c, 0x002c, 0x0000, - 0x0032, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0038, 0x000b, 0x0032, 0x0000, - 0x0008, 0x000c, 0x0093, 0x00e9, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0003, 0x0010, 0x0000, 0x0000, - 0x0000, 0x0002, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0039, 0x0000, - 0x0000, -}; - -#define WM8974_POWER1_BIASEN 0x08 -#define WM8974_POWER1_BUFIOEN 0x04 - -#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) - -static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; -static const char *wm8974_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" }; -static const char *wm8974_eqmode[] = {"Capture", "Playback" }; -static const char *wm8974_bw[] = {"Narrow", "Wide" }; -static const char *wm8974_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz" }; -static const char *wm8974_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz" }; -static const char *wm8974_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz" }; -static const char *wm8974_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" }; -static const char *wm8974_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz" }; -static const char *wm8974_alc[] = {"ALC", "Limiter" }; - -static const struct soc_enum wm8974_enum[] = { - SOC_ENUM_SINGLE(WM8974_COMP, 1, 4, wm8974_companding), /* adc */ - SOC_ENUM_SINGLE(WM8974_COMP, 3, 4, wm8974_companding), /* dac */ - SOC_ENUM_SINGLE(WM8974_DAC, 4, 4, wm8974_deemp), - SOC_ENUM_SINGLE(WM8974_EQ1, 8, 2, wm8974_eqmode), - - SOC_ENUM_SINGLE(WM8974_EQ1, 5, 4, wm8974_eq1), - SOC_ENUM_SINGLE(WM8974_EQ2, 8, 2, wm8974_bw), - SOC_ENUM_SINGLE(WM8974_EQ2, 5, 4, wm8974_eq2), - SOC_ENUM_SINGLE(WM8974_EQ3, 8, 2, wm8974_bw), - - SOC_ENUM_SINGLE(WM8974_EQ3, 5, 4, wm8974_eq3), - SOC_ENUM_SINGLE(WM8974_EQ4, 8, 2, wm8974_bw), - SOC_ENUM_SINGLE(WM8974_EQ4, 5, 4, wm8974_eq4), - SOC_ENUM_SINGLE(WM8974_EQ5, 8, 2, wm8974_bw), - - SOC_ENUM_SINGLE(WM8974_EQ5, 5, 4, wm8974_eq5), - SOC_ENUM_SINGLE(WM8974_ALC3, 8, 2, wm8974_alc), -}; - -static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" }; - -static const struct soc_enum wm8974_auxmode = - SOC_ENUM_SINGLE(WM8974_INPUT, 3, 2, wm8974_auxmode_text); - -static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); -static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); - -static const struct snd_kcontrol_new wm8974_snd_controls[] = { - -SOC_SINGLE("Digital Loopback Switch", WM8974_COMP, 0, 1, 0), - -SOC_ENUM("DAC Companding", wm8974_enum[1]), -SOC_ENUM("ADC Companding", wm8974_enum[0]), - -SOC_ENUM("Playback De-emphasis", wm8974_enum[2]), -SOC_SINGLE("DAC Inversion Switch", WM8974_DAC, 0, 1, 0), - -SOC_SINGLE_TLV("PCM Volume", WM8974_DACVOL, 0, 255, 0, digital_tlv), - -SOC_SINGLE("High Pass Filter Switch", WM8974_ADC, 8, 1, 0), -SOC_SINGLE("High Pass Cut Off", WM8974_ADC, 4, 7, 0), -SOC_SINGLE("ADC Inversion Switch", WM8974_ADC, 0, 1, 0), - -SOC_SINGLE_TLV("Capture Volume", WM8974_ADCVOL, 0, 255, 0, digital_tlv), - -SOC_ENUM("Equaliser Function", wm8974_enum[3]), -SOC_ENUM("EQ1 Cut Off", wm8974_enum[4]), -SOC_SINGLE_TLV("EQ1 Volume", WM8974_EQ1, 0, 24, 1, eq_tlv), - -SOC_ENUM("Equaliser EQ2 Bandwith", wm8974_enum[5]), -SOC_ENUM("EQ2 Cut Off", wm8974_enum[6]), -SOC_SINGLE_TLV("EQ2 Volume", WM8974_EQ2, 0, 24, 1, eq_tlv), - -SOC_ENUM("Equaliser EQ3 Bandwith", wm8974_enum[7]), -SOC_ENUM("EQ3 Cut Off", wm8974_enum[8]), -SOC_SINGLE_TLV("EQ3 Volume", WM8974_EQ3, 0, 24, 1, eq_tlv), - -SOC_ENUM("Equaliser EQ4 Bandwith", wm8974_enum[9]), -SOC_ENUM("EQ4 Cut Off", wm8974_enum[10]), -SOC_SINGLE_TLV("EQ4 Volume", WM8974_EQ4, 0, 24, 1, eq_tlv), - -SOC_ENUM("Equaliser EQ5 Bandwith", wm8974_enum[11]), -SOC_ENUM("EQ5 Cut Off", wm8974_enum[12]), -SOC_SINGLE_TLV("EQ5 Volume", WM8974_EQ5, 0, 24, 1, eq_tlv), - -SOC_SINGLE("DAC Playback Limiter Switch", WM8974_DACLIM1, 8, 1, 0), -SOC_SINGLE("DAC Playback Limiter Decay", WM8974_DACLIM1, 4, 15, 0), -SOC_SINGLE("DAC Playback Limiter Attack", WM8974_DACLIM1, 0, 15, 0), - -SOC_SINGLE("DAC Playback Limiter Threshold", WM8974_DACLIM2, 4, 7, 0), -SOC_SINGLE("DAC Playback Limiter Boost", WM8974_DACLIM2, 0, 15, 0), - -SOC_SINGLE("ALC Enable Switch", WM8974_ALC1, 8, 1, 0), -SOC_SINGLE("ALC Capture Max Gain", WM8974_ALC1, 3, 7, 0), -SOC_SINGLE("ALC Capture Min Gain", WM8974_ALC1, 0, 7, 0), - -SOC_SINGLE("ALC Capture ZC Switch", WM8974_ALC2, 8, 1, 0), -SOC_SINGLE("ALC Capture Hold", WM8974_ALC2, 4, 7, 0), -SOC_SINGLE("ALC Capture Target", WM8974_ALC2, 0, 15, 0), - -SOC_ENUM("ALC Capture Mode", wm8974_enum[13]), -SOC_SINGLE("ALC Capture Decay", WM8974_ALC3, 4, 15, 0), -SOC_SINGLE("ALC Capture Attack", WM8974_ALC3, 0, 15, 0), - -SOC_SINGLE("ALC Capture Noise Gate Switch", WM8974_NGATE, 3, 1, 0), -SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8974_NGATE, 0, 7, 0), - -SOC_SINGLE("Capture PGA ZC Switch", WM8974_INPPGA, 7, 1, 0), -SOC_SINGLE_TLV("Capture PGA Volume", WM8974_INPPGA, 0, 63, 0, inpga_tlv), - -SOC_SINGLE("Speaker Playback ZC Switch", WM8974_SPKVOL, 7, 1, 0), -SOC_SINGLE("Speaker Playback Switch", WM8974_SPKVOL, 6, 1, 1), -SOC_SINGLE_TLV("Speaker Playback Volume", WM8974_SPKVOL, 0, 63, 0, spk_tlv), - -SOC_ENUM("Aux Mode", wm8974_auxmode), - -SOC_SINGLE("Capture Boost(+20dB)", WM8974_ADCBOOST, 8, 1, 0), -SOC_SINGLE("Mono Playback Switch", WM8974_MONOMIX, 6, 1, 1), - -/* DAC / ADC oversampling */ -SOC_SINGLE("DAC 128x Oversampling Switch", WM8974_DAC, 8, 1, 0), -SOC_SINGLE("ADC 128x Oversampling Switch", WM8974_ADC, 8, 1, 0), -}; - -/* Speaker Output Mixer */ -static const struct snd_kcontrol_new wm8974_speaker_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_SPKMIX, 1, 1, 0), -SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_SPKMIX, 5, 1, 0), -SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_SPKMIX, 0, 1, 0), -}; - -/* Mono Output Mixer */ -static const struct snd_kcontrol_new wm8974_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_MONOMIX, 1, 1, 0), -SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_MONOMIX, 2, 1, 0), -SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_MONOMIX, 0, 1, 0), -}; - -/* Boost mixer */ -static const struct snd_kcontrol_new wm8974_boost_mixer[] = { -SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 0), -}; - -/* Input PGA */ -static const struct snd_kcontrol_new wm8974_inpga[] = { -SOC_DAPM_SINGLE("Aux Switch", WM8974_INPUT, 2, 1, 0), -SOC_DAPM_SINGLE("MicN Switch", WM8974_INPUT, 1, 1, 0), -SOC_DAPM_SINGLE("MicP Switch", WM8974_INPUT, 0, 1, 0), -}; - -/* AUX Input boost vol */ -static const struct snd_kcontrol_new wm8974_aux_boost_controls = -SOC_DAPM_SINGLE("Aux Volume", WM8974_ADCBOOST, 0, 7, 0); - -/* Mic Input boost vol */ -static const struct snd_kcontrol_new wm8974_mic_boost_controls = -SOC_DAPM_SINGLE("Mic Volume", WM8974_ADCBOOST, 4, 7, 0); - -static const struct snd_soc_dapm_widget wm8974_dapm_widgets[] = { -SND_SOC_DAPM_MIXER("Speaker Mixer", WM8974_POWER3, 2, 0, - &wm8974_speaker_mixer_controls[0], - ARRAY_SIZE(wm8974_speaker_mixer_controls)), -SND_SOC_DAPM_MIXER("Mono Mixer", WM8974_POWER3, 3, 0, - &wm8974_mono_mixer_controls[0], - ARRAY_SIZE(wm8974_mono_mixer_controls)), -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8974_POWER3, 0, 0), -SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8974_POWER2, 0, 0), -SND_SOC_DAPM_PGA("Aux Input", WM8974_POWER1, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("SpkN Out", WM8974_POWER3, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("SpkP Out", WM8974_POWER3, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("Mono Out", WM8974_POWER3, 7, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("Input PGA", WM8974_POWER2, 2, 0, wm8974_inpga, - ARRAY_SIZE(wm8974_inpga)), -SND_SOC_DAPM_MIXER("Boost Mixer", WM8974_POWER2, 4, 0, - wm8974_boost_mixer, ARRAY_SIZE(wm8974_boost_mixer)), - -SND_SOC_DAPM_SUPPLY("Mic Bias", WM8974_POWER1, 4, 0, NULL, 0), - -SND_SOC_DAPM_INPUT("MICN"), -SND_SOC_DAPM_INPUT("MICP"), -SND_SOC_DAPM_INPUT("AUX"), -SND_SOC_DAPM_OUTPUT("MONOOUT"), -SND_SOC_DAPM_OUTPUT("SPKOUTP"), -SND_SOC_DAPM_OUTPUT("SPKOUTN"), -}; - -static const struct snd_soc_dapm_route wm8974_dapm_routes[] = { - /* Mono output mixer */ - {"Mono Mixer", "PCM Playback Switch", "DAC"}, - {"Mono Mixer", "Aux Playback Switch", "Aux Input"}, - {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"}, - - /* Speaker output mixer */ - {"Speaker Mixer", "PCM Playback Switch", "DAC"}, - {"Speaker Mixer", "Aux Playback Switch", "Aux Input"}, - {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"}, - - /* Outputs */ - {"Mono Out", NULL, "Mono Mixer"}, - {"MONOOUT", NULL, "Mono Out"}, - {"SpkN Out", NULL, "Speaker Mixer"}, - {"SpkP Out", NULL, "Speaker Mixer"}, - {"SPKOUTN", NULL, "SpkN Out"}, - {"SPKOUTP", NULL, "SpkP Out"}, - - /* Boost Mixer */ - {"ADC", NULL, "Boost Mixer"}, - {"Boost Mixer", "Aux Switch", "Aux Input"}, - {"Boost Mixer", NULL, "Input PGA"}, - {"Boost Mixer", NULL, "MICP"}, - - /* Input PGA */ - {"Input PGA", "Aux Switch", "Aux Input"}, - {"Input PGA", "MicN Switch", "MICN"}, - {"Input PGA", "MicP Switch", "MICP"}, - - /* Inputs */ - {"Aux Input", NULL, "AUX"}, -}; - -struct pll_ { - unsigned int pre_div:1; - unsigned int n:4; - unsigned int k; -}; - -/* The size in bits of the pll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 24) * 10) - -static void pll_factors(struct pll_ *pll_div, - unsigned int target, unsigned int source) -{ - unsigned long long Kpart; - unsigned int K, Ndiv, Nmod; - - /* There is a fixed divide by 4 in the output path */ - target *= 4; - - Ndiv = target / source; - if (Ndiv < 6) { - source /= 2; - pll_div->pre_div = 1; - Ndiv = target / source; - } else - pll_div->pre_div = 0; - - if ((Ndiv < 6) || (Ndiv > 12)) - printk(KERN_WARNING - "WM8974 N value %u outwith recommended range!\n", - Ndiv); - - pll_div->n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div->k = K; -} - -static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct pll_ pll_div; - u16 reg; - - if (freq_in == 0 || freq_out == 0) { - /* Clock CODEC directly from MCLK */ - reg = snd_soc_read(codec, WM8974_CLOCK); - snd_soc_write(codec, WM8974_CLOCK, reg & 0x0ff); - - /* Turn off PLL */ - reg = snd_soc_read(codec, WM8974_POWER1); - snd_soc_write(codec, WM8974_POWER1, reg & 0x1df); - return 0; - } - - pll_factors(&pll_div, freq_out, freq_in); - - snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); - snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18); - snd_soc_write(codec, WM8974_PLLK2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8974_PLLK3, pll_div.k & 0x1ff); - reg = snd_soc_read(codec, WM8974_POWER1); - snd_soc_write(codec, WM8974_POWER1, reg | 0x020); - - /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_read(codec, WM8974_CLOCK); - snd_soc_write(codec, WM8974_CLOCK, reg | 0x100); - - return 0; -} - -/* - * Configure WM8974 clock dividers. - */ -static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM8974_OPCLKDIV: - reg = snd_soc_read(codec, WM8974_GPIO) & 0x1cf; - snd_soc_write(codec, WM8974_GPIO, reg | div); - break; - case WM8974_MCLKDIV: - reg = snd_soc_read(codec, WM8974_CLOCK) & 0x11f; - snd_soc_write(codec, WM8974_CLOCK, reg | div); - break; - case WM8974_BCLKDIV: - reg = snd_soc_read(codec, WM8974_CLOCK) & 0x1e3; - snd_soc_write(codec, WM8974_CLOCK, reg | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - u16 clk = snd_soc_read(codec, WM8974_CLOCK) & 0x1fe; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - clk |= 0x0001; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0010; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0008; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x00018; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0180; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0100; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0080; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8974_IFACE, iface); - snd_soc_write(codec, WM8974_CLOCK, clk); - return 0; -} - -static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - u16 iface = snd_soc_read(codec, WM8974_IFACE) & 0x19f; - u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0020; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0040; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x0060; - break; - } - - /* filter coefficient */ - switch (params_rate(params)) { - case 8000: - adn |= 0x5 << 1; - break; - case 11025: - adn |= 0x4 << 1; - break; - case 16000: - adn |= 0x3 << 1; - break; - case 22050: - adn |= 0x2 << 1; - break; - case 32000: - adn |= 0x1 << 1; - break; - case 44100: - case 48000: - break; - } - - snd_soc_write(codec, WM8974_IFACE, iface); - snd_soc_write(codec, WM8974_ADD, adn); - return 0; -} - -static int wm8974_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf; - - if (mute) - snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40); - else - snd_soc_write(codec, WM8974_DAC, mute_reg); - return 0; -} - -/* liam need to make this lower power with dapm */ -static int wm8974_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 power1 = snd_soc_read(codec, WM8974_POWER1) & ~0x3; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - power1 |= 0x1; /* VMID 50k */ - snd_soc_write(codec, WM8974_POWER1, power1); - break; - - case SND_SOC_BIAS_STANDBY: - power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN; - - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); - - /* Initial cap charge at VMID 5k */ - snd_soc_write(codec, WM8974_POWER1, power1 | 0x3); - mdelay(100); - } - - power1 |= 0x2; /* VMID 500k */ - snd_soc_write(codec, WM8974_POWER1, power1); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8974_POWER1, 0); - snd_soc_write(codec, WM8974_POWER2, 0); - snd_soc_write(codec, WM8974_POWER3, 0); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#define WM8974_RATES (SNDRV_PCM_RATE_8000_48000) - -#define WM8974_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8974_ops = { - .hw_params = wm8974_pcm_hw_params, - .digital_mute = wm8974_mute, - .set_fmt = wm8974_set_dai_fmt, - .set_clkdiv = wm8974_set_dai_clkdiv, - .set_pll = wm8974_set_dai_pll, -}; - -static struct snd_soc_dai_driver wm8974_dai = { - .name = "wm8974-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, /* Only 1 channel of data */ - .rates = WM8974_RATES, - .formats = WM8974_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, /* Only 1 channel of data */ - .rates = WM8974_RATES, - .formats = WM8974_FORMATS,}, - .ops = &wm8974_ops, - .symmetric_rates = 1, -}; - -static int wm8974_suspend(struct snd_soc_codec *codec) -{ - wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8974_resume(struct snd_soc_codec *codec) -{ - wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int wm8974_probe(struct snd_soc_codec *codec) -{ - int ret = 0; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = wm8974_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return ret; -} - -/* power down chip */ -static int wm8974_remove(struct snd_soc_codec *codec) -{ - wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { - .probe = wm8974_probe, - .remove = wm8974_remove, - .suspend = wm8974_suspend, - .resume = wm8974_resume, - .set_bias_level = wm8974_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8974_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8974_reg, - - .controls = wm8974_snd_controls, - .num_controls = ARRAY_SIZE(wm8974_snd_controls), - .dapm_widgets = wm8974_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets), - .dapm_routes = wm8974_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes), -}; - -static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - int ret; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8974, &wm8974_dai, 1); - - return ret; -} - -static __devexit int wm8974_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - - return 0; -} - -static const struct i2c_device_id wm8974_i2c_id[] = { - { "wm8974", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id); - -static struct i2c_driver wm8974_i2c_driver = { - .driver = { - .name = "wm8974", - .owner = THIS_MODULE, - }, - .probe = wm8974_i2c_probe, - .remove = __devexit_p(wm8974_i2c_remove), - .id_table = wm8974_i2c_id, -}; - -static int __init wm8974_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8974_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8974_modinit); - -static void __exit wm8974_exit(void) -{ - i2c_del_driver(&wm8974_i2c_driver); -} -module_exit(wm8974_exit); - -MODULE_DESCRIPTION("ASoC WM8974 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8974.h b/ANDROID_3.4.5/sound/soc/codecs/wm8974.h deleted file mode 100644 index 3c94e7bb..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8974.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * wm8974.h -- WM8974 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8974_H -#define _WM8974_H - -/* WM8974 register space */ - -#define WM8974_RESET 0x0 -#define WM8974_POWER1 0x1 -#define WM8974_POWER2 0x2 -#define WM8974_POWER3 0x3 -#define WM8974_IFACE 0x4 -#define WM8974_COMP 0x5 -#define WM8974_CLOCK 0x6 -#define WM8974_ADD 0x7 -#define WM8974_GPIO 0x8 -#define WM8974_DAC 0xa -#define WM8974_DACVOL 0xb -#define WM8974_ADC 0xe -#define WM8974_ADCVOL 0xf -#define WM8974_EQ1 0x12 -#define WM8974_EQ2 0x13 -#define WM8974_EQ3 0x14 -#define WM8974_EQ4 0x15 -#define WM8974_EQ5 0x16 -#define WM8974_DACLIM1 0x18 -#define WM8974_DACLIM2 0x19 -#define WM8974_NOTCH1 0x1b -#define WM8974_NOTCH2 0x1c -#define WM8974_NOTCH3 0x1d -#define WM8974_NOTCH4 0x1e -#define WM8974_ALC1 0x20 -#define WM8974_ALC2 0x21 -#define WM8974_ALC3 0x22 -#define WM8974_NGATE 0x23 -#define WM8974_PLLN 0x24 -#define WM8974_PLLK1 0x25 -#define WM8974_PLLK2 0x26 -#define WM8974_PLLK3 0x27 -#define WM8974_ATTEN 0x28 -#define WM8974_INPUT 0x2c -#define WM8974_INPPGA 0x2d -#define WM8974_ADCBOOST 0x2f -#define WM8974_OUTPUT 0x31 -#define WM8974_SPKMIX 0x32 -#define WM8974_SPKVOL 0x36 -#define WM8974_MONOMIX 0x38 - -#define WM8974_CACHEREGNUM 57 - -/* Clock divider Id's */ -#define WM8974_OPCLKDIV 0 -#define WM8974_MCLKDIV 1 -#define WM8974_BCLKDIV 2 - -/* PLL Out dividers */ -#define WM8974_OPCLKDIV_1 (0 << 4) -#define WM8974_OPCLKDIV_2 (1 << 4) -#define WM8974_OPCLKDIV_3 (2 << 4) -#define WM8974_OPCLKDIV_4 (3 << 4) - -/* BCLK clock dividers */ -#define WM8974_BCLKDIV_1 (0 << 2) -#define WM8974_BCLKDIV_2 (1 << 2) -#define WM8974_BCLKDIV_4 (2 << 2) -#define WM8974_BCLKDIV_8 (3 << 2) -#define WM8974_BCLKDIV_16 (4 << 2) -#define WM8974_BCLKDIV_32 (5 << 2) - -/* MCLK clock dividers */ -#define WM8974_MCLKDIV_1 (0 << 5) -#define WM8974_MCLKDIV_1_5 (1 << 5) -#define WM8974_MCLKDIV_2 (2 << 5) -#define WM8974_MCLKDIV_3 (3 << 5) -#define WM8974_MCLKDIV_4 (4 << 5) -#define WM8974_MCLKDIV_6 (5 << 5) -#define WM8974_MCLKDIV_8 (6 << 5) -#define WM8974_MCLKDIV_12 (7 << 5) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8978.c b/ANDROID_3.4.5/sound/soc/codecs/wm8978.c deleted file mode 100644 index 72d5fdcd..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8978.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* - * wm8978.c -- WM8978 ALSA SoC Audio Codec driver - * - * Copyright (C) 2009-2010 Guennadi Liakhovetski - * Copyright (C) 2007 Carlos Munoz - * Copyright 2006-2009 Wolfson Microelectronics PLC. - * Based on wm8974 and wm8990 by Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8978.h" - -static const struct reg_default wm8978_reg_defaults[] = { - { 1, 0x0000 }, - { 2, 0x0000 }, - { 3, 0x0000 }, - { 4, 0x0050 }, - { 5, 0x0000 }, - { 6, 0x0140 }, - { 7, 0x0000 }, - { 8, 0x0000 }, - { 9, 0x0000 }, - { 10, 0x0000 }, - { 11, 0x00ff }, - { 12, 0x00ff }, - { 13, 0x0000 }, - { 14, 0x0100 }, - { 15, 0x00ff }, - { 16, 0x00ff }, - { 17, 0x0000 }, - { 18, 0x012c }, - { 19, 0x002c }, - { 20, 0x002c }, - { 21, 0x002c }, - { 22, 0x002c }, - { 23, 0x0000 }, - { 24, 0x0032 }, - { 25, 0x0000 }, - { 26, 0x0000 }, - { 27, 0x0000 }, - { 28, 0x0000 }, - { 29, 0x0000 }, - { 30, 0x0000 }, - { 31, 0x0000 }, - { 32, 0x0038 }, - { 33, 0x000b }, - { 34, 0x0032 }, - { 35, 0x0000 }, - { 36, 0x0008 }, - { 37, 0x000c }, - { 38, 0x0093 }, - { 39, 0x00e9 }, - { 40, 0x0000 }, - { 41, 0x0000 }, - { 42, 0x0000 }, - { 43, 0x0000 }, - { 44, 0x0033 }, - { 45, 0x0010 }, - { 46, 0x0010 }, - { 47, 0x0100 }, - { 48, 0x0100 }, - { 49, 0x0002 }, - { 50, 0x0001 }, - { 51, 0x0001 }, - { 52, 0x0039 }, - { 53, 0x0039 }, - { 54, 0x0039 }, - { 55, 0x0039 }, - { 56, 0x0001 }, - { 57, 0x0001 }, -}; - -static bool wm8978_volatile(struct device *dev, unsigned int reg) -{ - return reg == WM8978_RESET; -} - -/* codec private data */ -struct wm8978_priv { - struct regmap *regmap; - unsigned int f_pllout; - unsigned int f_mclk; - unsigned int f_256fs; - unsigned int f_opclk; - int mclk_idx; - enum wm8978_sysclk_src sysclk; -}; - -static const char *wm8978_companding[] = {"Off", "NC", "u-law", "A-law"}; -static const char *wm8978_eqmode[] = {"Capture", "Playback"}; -static const char *wm8978_bw[] = {"Narrow", "Wide"}; -static const char *wm8978_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz"}; -static const char *wm8978_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz"}; -static const char *wm8978_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz"}; -static const char *wm8978_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"}; -static const char *wm8978_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz"}; -static const char *wm8978_alc3[] = {"ALC", "Limiter"}; -static const char *wm8978_alc1[] = {"Off", "Right", "Left", "Both"}; - -static const SOC_ENUM_SINGLE_DECL(adc_compand, WM8978_COMPANDING_CONTROL, 1, - wm8978_companding); -static const SOC_ENUM_SINGLE_DECL(dac_compand, WM8978_COMPANDING_CONTROL, 3, - wm8978_companding); -static const SOC_ENUM_SINGLE_DECL(eqmode, WM8978_EQ1, 8, wm8978_eqmode); -static const SOC_ENUM_SINGLE_DECL(eq1, WM8978_EQ1, 5, wm8978_eq1); -static const SOC_ENUM_SINGLE_DECL(eq2bw, WM8978_EQ2, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq2, WM8978_EQ2, 5, wm8978_eq2); -static const SOC_ENUM_SINGLE_DECL(eq3bw, WM8978_EQ3, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq3, WM8978_EQ3, 5, wm8978_eq3); -static const SOC_ENUM_SINGLE_DECL(eq4bw, WM8978_EQ4, 8, wm8978_bw); -static const SOC_ENUM_SINGLE_DECL(eq4, WM8978_EQ4, 5, wm8978_eq4); -static const SOC_ENUM_SINGLE_DECL(eq5, WM8978_EQ5, 5, wm8978_eq5); -static const SOC_ENUM_SINGLE_DECL(alc3, WM8978_ALC_CONTROL_3, 8, wm8978_alc3); -static const SOC_ENUM_SINGLE_DECL(alc1, WM8978_ALC_CONTROL_1, 7, wm8978_alc1); - -static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); -static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); -static const DECLARE_TLV_DB_SCALE(boost_tlv, -1500, 300, 1); -static const DECLARE_TLV_DB_SCALE(limiter_tlv, 0, 100, 0); - -static const struct snd_kcontrol_new wm8978_snd_controls[] = { - - SOC_SINGLE("Digital Loopback Switch", - WM8978_COMPANDING_CONTROL, 0, 1, 0), - - SOC_ENUM("ADC Companding", adc_compand), - SOC_ENUM("DAC Companding", dac_compand), - - SOC_DOUBLE("DAC Inversion Switch", WM8978_DAC_CONTROL, 0, 1, 1, 0), - - SOC_DOUBLE_R_TLV("PCM Volume", - WM8978_LEFT_DAC_DIGITAL_VOLUME, WM8978_RIGHT_DAC_DIGITAL_VOLUME, - 0, 255, 0, digital_tlv), - - SOC_SINGLE("High Pass Filter Switch", WM8978_ADC_CONTROL, 8, 1, 0), - SOC_SINGLE("High Pass Cut Off", WM8978_ADC_CONTROL, 4, 7, 0), - SOC_DOUBLE("ADC Inversion Switch", WM8978_ADC_CONTROL, 0, 1, 1, 0), - - SOC_DOUBLE_R_TLV("ADC Volume", - WM8978_LEFT_ADC_DIGITAL_VOLUME, WM8978_RIGHT_ADC_DIGITAL_VOLUME, - 0, 255, 0, digital_tlv), - - SOC_ENUM("Equaliser Function", eqmode), - SOC_ENUM("EQ1 Cut Off", eq1), - SOC_SINGLE_TLV("EQ1 Volume", WM8978_EQ1, 0, 24, 1, eq_tlv), - - SOC_ENUM("Equaliser EQ2 Bandwith", eq2bw), - SOC_ENUM("EQ2 Cut Off", eq2), - SOC_SINGLE_TLV("EQ2 Volume", WM8978_EQ2, 0, 24, 1, eq_tlv), - - SOC_ENUM("Equaliser EQ3 Bandwith", eq3bw), - SOC_ENUM("EQ3 Cut Off", eq3), - SOC_SINGLE_TLV("EQ3 Volume", WM8978_EQ3, 0, 24, 1, eq_tlv), - - SOC_ENUM("Equaliser EQ4 Bandwith", eq4bw), - SOC_ENUM("EQ4 Cut Off", eq4), - SOC_SINGLE_TLV("EQ4 Volume", WM8978_EQ4, 0, 24, 1, eq_tlv), - - SOC_ENUM("EQ5 Cut Off", eq5), - SOC_SINGLE_TLV("EQ5 Volume", WM8978_EQ5, 0, 24, 1, eq_tlv), - - SOC_SINGLE("DAC Playback Limiter Switch", - WM8978_DAC_LIMITER_1, 8, 1, 0), - SOC_SINGLE("DAC Playback Limiter Decay", - WM8978_DAC_LIMITER_1, 4, 15, 0), - SOC_SINGLE("DAC Playback Limiter Attack", - WM8978_DAC_LIMITER_1, 0, 15, 0), - - SOC_SINGLE("DAC Playback Limiter Threshold", - WM8978_DAC_LIMITER_2, 4, 7, 0), - SOC_SINGLE_TLV("DAC Playback Limiter Volume", - WM8978_DAC_LIMITER_2, 0, 12, 0, limiter_tlv), - - SOC_ENUM("ALC Enable Switch", alc1), - SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0), - SOC_SINGLE("ALC Capture Max Gain", WM8978_ALC_CONTROL_1, 3, 7, 0), - - SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 10, 0), - SOC_SINGLE("ALC Capture Target", WM8978_ALC_CONTROL_2, 0, 15, 0), - - SOC_ENUM("ALC Capture Mode", alc3), - SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 10, 0), - SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 10, 0), - - SOC_SINGLE("ALC Capture Noise Gate Switch", WM8978_NOISE_GATE, 3, 1, 0), - SOC_SINGLE("ALC Capture Noise Gate Threshold", - WM8978_NOISE_GATE, 0, 7, 0), - - SOC_DOUBLE_R("Capture PGA ZC Switch", - WM8978_LEFT_INP_PGA_CONTROL, WM8978_RIGHT_INP_PGA_CONTROL, - 7, 1, 0), - - /* OUT1 - Headphones */ - SOC_DOUBLE_R("Headphone Playback ZC Switch", - WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL, 7, 1, 0), - - SOC_DOUBLE_R_TLV("Headphone Playback Volume", - WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL, - 0, 63, 0, spk_tlv), - - /* OUT2 - Speakers */ - SOC_DOUBLE_R("Speaker Playback ZC Switch", - WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 7, 1, 0), - - SOC_DOUBLE_R_TLV("Speaker Playback Volume", - WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, - 0, 63, 0, spk_tlv), - - /* OUT3/4 - Line Output */ - SOC_DOUBLE_R("Line Playback Switch", - WM8978_OUT3_MIXER_CONTROL, WM8978_OUT4_MIXER_CONTROL, 6, 1, 1), - - /* Mixer #3: Boost (Input) mixer */ - SOC_DOUBLE_R("PGA Boost (+20dB)", - WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL, - 8, 1, 0), - SOC_DOUBLE_R_TLV("L2/R2 Boost Volume", - WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL, - 4, 7, 0, boost_tlv), - SOC_DOUBLE_R_TLV("Aux Boost Volume", - WM8978_LEFT_ADC_BOOST_CONTROL, WM8978_RIGHT_ADC_BOOST_CONTROL, - 0, 7, 0, boost_tlv), - - /* Input PGA volume */ - SOC_DOUBLE_R_TLV("Input PGA Volume", - WM8978_LEFT_INP_PGA_CONTROL, WM8978_RIGHT_INP_PGA_CONTROL, - 0, 63, 0, inpga_tlv), - - /* Headphone */ - SOC_DOUBLE_R("Headphone Switch", - WM8978_LOUT1_HP_CONTROL, WM8978_ROUT1_HP_CONTROL, 6, 1, 1), - - /* Speaker */ - SOC_DOUBLE_R("Speaker Switch", - WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 6, 1, 1), - - /* DAC / ADC oversampling */ - SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, - 5, 1, 0), - SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, - 5, 1, 0), -}; - -/* Mixer #1: Output (OUT1, OUT2) Mixer: mix AUX, Input mixer output and DAC */ -static const struct snd_kcontrol_new wm8978_left_out_mixer[] = { - SOC_DAPM_SINGLE("Line Bypass Switch", WM8978_LEFT_MIXER_CONTROL, 1, 1, 0), - SOC_DAPM_SINGLE("Aux Playback Switch", WM8978_LEFT_MIXER_CONTROL, 5, 1, 0), - SOC_DAPM_SINGLE("PCM Playback Switch", WM8978_LEFT_MIXER_CONTROL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new wm8978_right_out_mixer[] = { - SOC_DAPM_SINGLE("Line Bypass Switch", WM8978_RIGHT_MIXER_CONTROL, 1, 1, 0), - SOC_DAPM_SINGLE("Aux Playback Switch", WM8978_RIGHT_MIXER_CONTROL, 5, 1, 0), - SOC_DAPM_SINGLE("PCM Playback Switch", WM8978_RIGHT_MIXER_CONTROL, 0, 1, 0), -}; - -/* OUT3/OUT4 Mixer not implemented */ - -/* Mixer #2: Input PGA Mute */ -static const struct snd_kcontrol_new wm8978_left_input_mixer[] = { - SOC_DAPM_SINGLE("L2 Switch", WM8978_INPUT_CONTROL, 2, 1, 0), - SOC_DAPM_SINGLE("MicN Switch", WM8978_INPUT_CONTROL, 1, 1, 0), - SOC_DAPM_SINGLE("MicP Switch", WM8978_INPUT_CONTROL, 0, 1, 0), -}; -static const struct snd_kcontrol_new wm8978_right_input_mixer[] = { - SOC_DAPM_SINGLE("R2 Switch", WM8978_INPUT_CONTROL, 6, 1, 0), - SOC_DAPM_SINGLE("MicN Switch", WM8978_INPUT_CONTROL, 5, 1, 0), - SOC_DAPM_SINGLE("MicP Switch", WM8978_INPUT_CONTROL, 4, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8978_dapm_widgets[] = { - SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", - WM8978_POWER_MANAGEMENT_3, 0, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", - WM8978_POWER_MANAGEMENT_3, 1, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", - WM8978_POWER_MANAGEMENT_2, 0, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", - WM8978_POWER_MANAGEMENT_2, 1, 0), - - /* Mixer #1: OUT1,2 */ - SOC_MIXER_ARRAY("Left Output Mixer", WM8978_POWER_MANAGEMENT_3, - 2, 0, wm8978_left_out_mixer), - SOC_MIXER_ARRAY("Right Output Mixer", WM8978_POWER_MANAGEMENT_3, - 3, 0, wm8978_right_out_mixer), - - SOC_MIXER_ARRAY("Left Input Mixer", WM8978_POWER_MANAGEMENT_2, - 2, 0, wm8978_left_input_mixer), - SOC_MIXER_ARRAY("Right Input Mixer", WM8978_POWER_MANAGEMENT_2, - 3, 0, wm8978_right_input_mixer), - - SND_SOC_DAPM_PGA("Left Boost Mixer", WM8978_POWER_MANAGEMENT_2, - 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Boost Mixer", WM8978_POWER_MANAGEMENT_2, - 5, 0, NULL, 0), - - SND_SOC_DAPM_PGA("Left Capture PGA", WM8978_LEFT_INP_PGA_CONTROL, - 6, 1, NULL, 0), - SND_SOC_DAPM_PGA("Right Capture PGA", WM8978_RIGHT_INP_PGA_CONTROL, - 6, 1, NULL, 0), - - SND_SOC_DAPM_PGA("Left Headphone Out", WM8978_POWER_MANAGEMENT_2, - 7, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Headphone Out", WM8978_POWER_MANAGEMENT_2, - 8, 0, NULL, 0), - - SND_SOC_DAPM_PGA("Left Speaker Out", WM8978_POWER_MANAGEMENT_3, - 6, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Speaker Out", WM8978_POWER_MANAGEMENT_3, - 5, 0, NULL, 0), - - SND_SOC_DAPM_MIXER("OUT4 VMID", WM8978_POWER_MANAGEMENT_3, - 8, 0, NULL, 0), - - SND_SOC_DAPM_MICBIAS("Mic Bias", WM8978_POWER_MANAGEMENT_1, 4, 0), - - SND_SOC_DAPM_INPUT("LMICN"), - SND_SOC_DAPM_INPUT("LMICP"), - SND_SOC_DAPM_INPUT("RMICN"), - SND_SOC_DAPM_INPUT("RMICP"), - SND_SOC_DAPM_INPUT("LAUX"), - SND_SOC_DAPM_INPUT("RAUX"), - SND_SOC_DAPM_INPUT("L2"), - SND_SOC_DAPM_INPUT("R2"), - SND_SOC_DAPM_OUTPUT("LHP"), - SND_SOC_DAPM_OUTPUT("RHP"), - SND_SOC_DAPM_OUTPUT("LSPK"), - SND_SOC_DAPM_OUTPUT("RSPK"), -}; - -static const struct snd_soc_dapm_route wm8978_dapm_routes[] = { - /* Output mixer */ - {"Right Output Mixer", "PCM Playback Switch", "Right DAC"}, - {"Right Output Mixer", "Aux Playback Switch", "RAUX"}, - {"Right Output Mixer", "Line Bypass Switch", "Right Boost Mixer"}, - - {"Left Output Mixer", "PCM Playback Switch", "Left DAC"}, - {"Left Output Mixer", "Aux Playback Switch", "LAUX"}, - {"Left Output Mixer", "Line Bypass Switch", "Left Boost Mixer"}, - - /* Outputs */ - {"Right Headphone Out", NULL, "Right Output Mixer"}, - {"RHP", NULL, "Right Headphone Out"}, - - {"Left Headphone Out", NULL, "Left Output Mixer"}, - {"LHP", NULL, "Left Headphone Out"}, - - {"Right Speaker Out", NULL, "Right Output Mixer"}, - {"RSPK", NULL, "Right Speaker Out"}, - - {"Left Speaker Out", NULL, "Left Output Mixer"}, - {"LSPK", NULL, "Left Speaker Out"}, - - /* Boost Mixer */ - {"Right ADC", NULL, "Right Boost Mixer"}, - - {"Right Boost Mixer", NULL, "RAUX"}, - {"Right Boost Mixer", NULL, "Right Capture PGA"}, - {"Right Boost Mixer", NULL, "R2"}, - - {"Left ADC", NULL, "Left Boost Mixer"}, - - {"Left Boost Mixer", NULL, "LAUX"}, - {"Left Boost Mixer", NULL, "Left Capture PGA"}, - {"Left Boost Mixer", NULL, "L2"}, - - /* Input PGA */ - {"Right Capture PGA", NULL, "Right Input Mixer"}, - {"Left Capture PGA", NULL, "Left Input Mixer"}, - - {"Right Input Mixer", "R2 Switch", "R2"}, - {"Right Input Mixer", "MicN Switch", "RMICN"}, - {"Right Input Mixer", "MicP Switch", "RMICP"}, - - {"Left Input Mixer", "L2 Switch", "L2"}, - {"Left Input Mixer", "MicN Switch", "LMICN"}, - {"Left Input Mixer", "MicP Switch", "LMICP"}, -}; - -/* PLL divisors */ -struct wm8978_pll_div { - u32 k; - u8 n; - u8 div2; -}; - -#define FIXED_PLL_SIZE (1 << 24) - -static void pll_factors(struct snd_soc_codec *codec, - struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source) -{ - u64 k_part; - unsigned int k, n_div, n_mod; - - n_div = target / source; - if (n_div < 6) { - source >>= 1; - pll_div->div2 = 1; - n_div = target / source; - } else { - pll_div->div2 = 0; - } - - if (n_div < 6 || n_div > 12) - dev_warn(codec->dev, - "WM8978 N value exceeds recommended range! N = %u\n", - n_div); - - pll_div->n = n_div; - n_mod = target - source * n_div; - k_part = FIXED_PLL_SIZE * (long long)n_mod + source / 2; - - do_div(k_part, source); - - k = k_part & 0xFFFFFFFF; - - pll_div->k = k; -} - -/* MCLK dividers */ -static const int mclk_numerator[] = {1, 3, 2, 3, 4, 6, 8, 12}; -static const int mclk_denominator[] = {1, 2, 1, 1, 1, 1, 1, 1}; - -/* - * find index >= idx, such that, for a given f_out, - * 3 * f_mclk / 4 <= f_PLLOUT < 13 * f_mclk / 4 - * f_out can be f_256fs or f_opclk, currently only used for f_256fs. Can be - * generalised for f_opclk with suitable coefficient arrays, but currently - * the OPCLK divisor is calculated directly, not iteratively. - */ -static int wm8978_enum_mclk(unsigned int f_out, unsigned int f_mclk, - unsigned int *f_pllout) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(mclk_numerator); i++) { - unsigned int f_pllout_x4 = 4 * f_out * mclk_numerator[i] / - mclk_denominator[i]; - if (3 * f_mclk <= f_pllout_x4 && f_pllout_x4 < 13 * f_mclk) { - *f_pllout = f_pllout_x4 / 4; - return i; - } - } - - return -EINVAL; -} - -/* - * Calculate internal frequencies and dividers, according to Figure 40 - * "PLL and Clock Select Circuit" in WM8978 datasheet Rev. 2.6 - */ -static int wm8978_configure_pll(struct snd_soc_codec *codec) -{ - struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - struct wm8978_pll_div pll_div; - unsigned int f_opclk = wm8978->f_opclk, f_mclk = wm8978->f_mclk, - f_256fs = wm8978->f_256fs; - unsigned int f2; - - if (!f_mclk) - return -EINVAL; - - if (f_opclk) { - unsigned int opclk_div; - /* Cannot set up MCLK divider now, do later */ - wm8978->mclk_idx = -1; - - /* - * The user needs OPCLK. Choose OPCLKDIV to put - * 6 <= R = f2 / f1 < 13, 1 <= OPCLKDIV <= 4. - * f_opclk = f_mclk * prescale * R / 4 / OPCLKDIV, where - * prescale = 1, or prescale = 2. Prescale is calculated inside - * pll_factors(). We have to select f_PLLOUT, such that - * f_mclk * 3 / 4 <= f_PLLOUT < f_mclk * 13 / 4. Must be - * f_mclk * 3 / 16 <= f_opclk < f_mclk * 13 / 4. - */ - if (16 * f_opclk < 3 * f_mclk || 4 * f_opclk >= 13 * f_mclk) - return -EINVAL; - - if (4 * f_opclk < 3 * f_mclk) - /* Have to use OPCLKDIV */ - opclk_div = (3 * f_mclk / 4 + f_opclk - 1) / f_opclk; - else - opclk_div = 1; - - dev_dbg(codec->dev, "%s: OPCLKDIV=%d\n", __func__, opclk_div); - - snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 0x30, - (opclk_div - 1) << 4); - - wm8978->f_pllout = f_opclk * opclk_div; - } else if (f_256fs) { - /* - * Not using OPCLK, but PLL is used for the codec, choose R: - * 6 <= R = f2 / f1 < 13, to put 1 <= MCLKDIV <= 12. - * f_256fs = f_mclk * prescale * R / 4 / MCLKDIV, where - * prescale = 1, or prescale = 2. Prescale is calculated inside - * pll_factors(). We have to select f_PLLOUT, such that - * f_mclk * 3 / 4 <= f_PLLOUT < f_mclk * 13 / 4. Must be - * f_mclk * 3 / 48 <= f_256fs < f_mclk * 13 / 4. This means MCLK - * must be 3.781MHz <= f_MCLK <= 32.768MHz - */ - int idx = wm8978_enum_mclk(f_256fs, f_mclk, &wm8978->f_pllout); - if (idx < 0) - return idx; - - wm8978->mclk_idx = idx; - - /* GPIO1 into default mode as input - before configuring PLL */ - snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 0); - } else { - return -EINVAL; - } - - f2 = wm8978->f_pllout * 4; - - dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, - wm8978->f_mclk, wm8978->f_pllout); - - pll_factors(codec, &pll_div, f2, wm8978->f_mclk); - - dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", - __func__, pll_div.n, pll_div.k, pll_div.div2); - - /* Turn PLL off for configuration... */ - snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, 0x20, 0); - - snd_soc_write(codec, WM8978_PLL_N, (pll_div.div2 << 4) | pll_div.n); - snd_soc_write(codec, WM8978_PLL_K1, pll_div.k >> 18); - snd_soc_write(codec, WM8978_PLL_K2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8978_PLL_K3, pll_div.k & 0x1ff); - - /* ...and on again */ - snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, 0x20, 0x20); - - if (f_opclk) - /* Output PLL (OPCLK) to GPIO1 */ - snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 4); - - return 0; -} - -/* - * Configure WM8978 clock dividers. - */ -static int wm8978_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - switch (div_id) { - case WM8978_OPCLKRATE: - wm8978->f_opclk = div; - - if (wm8978->f_mclk) - /* - * We know the MCLK frequency, the user has requested - * OPCLK, configure the PLL based on that and start it - * and OPCLK immediately. We will configure PLL to match - * user-requested OPCLK frquency as good as possible. - * In fact, it is likely, that matching the sampling - * rate, when it becomes known, is more important, and - * we will not be reconfiguring PLL then, because we - * must not interrupt OPCLK. But it should be fine, - * because typically the user will request OPCLK to run - * at 256fs or 512fs, and for these cases we will also - * find an exact MCLK divider configuration - it will - * be equal to or double the OPCLK divisor. - */ - ret = wm8978_configure_pll(codec); - break; - case WM8978_BCLKDIV: - if (div & ~0x1c) - return -EINVAL; - snd_soc_update_bits(codec, WM8978_CLOCKING, 0x1c, div); - break; - default: - return -EINVAL; - } - - dev_dbg(codec->dev, "%s: ID %d, value %u\n", __func__, div_id, div); - - return ret; -} - -/* - * @freq: when .set_pll() us not used, freq is codec MCLK input frequency - */ -static int wm8978_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, - unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - dev_dbg(codec->dev, "%s: ID %d, freq %u\n", __func__, clk_id, freq); - - if (freq) { - wm8978->f_mclk = freq; - - /* Even if MCLK is used for system clock, might have to drive OPCLK */ - if (wm8978->f_opclk) - ret = wm8978_configure_pll(codec); - - /* Our sysclk is fixed to 256 * fs, will configure in .hw_params() */ - - if (!ret) - wm8978->sysclk = clk_id; - } - - if (wm8978->sysclk == WM8978_PLL && (!freq || clk_id == WM8978_MCLK)) { - /* Clock CODEC directly from MCLK */ - snd_soc_update_bits(codec, WM8978_CLOCKING, 0x100, 0); - - /* GPIO1 into default mode as input - before configuring PLL */ - snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 0); - - /* Turn off PLL */ - snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, 0x20, 0); - wm8978->sysclk = WM8978_MCLK; - wm8978->f_pllout = 0; - wm8978->f_opclk = 0; - } - - return ret; -} - -/* - * Set ADC and Voice DAC format. - */ -static int wm8978_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - /* - * BCLK polarity mask = 0x100, LRC clock polarity mask = 0x80, - * Data Format mask = 0x18: all will be calculated anew - */ - u16 iface = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x198; - u16 clk = snd_soc_read(codec, WM8978_CLOCKING); - - dev_dbg(codec->dev, "%s\n", __func__); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - clk |= 1; - break; - case SND_SOC_DAIFMT_CBS_CFS: - clk &= ~1; - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x10; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x8; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x18; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x180; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x100; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x80; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8978_AUDIO_INTERFACE, iface); - snd_soc_write(codec, WM8978_CLOCKING, clk); - - return 0; -} - -/* - * Set PCM DAI bit size and sample rate. - */ -static int wm8978_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - /* Word length mask = 0x60 */ - u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; - /* Sampling rate mask = 0xe (for filters) */ - u16 add_ctl = snd_soc_read(codec, WM8978_ADDITIONAL_CONTROL) & ~0xe; - u16 clking = snd_soc_read(codec, WM8978_CLOCKING); - enum wm8978_sysclk_src current_clk_id = clking & 0x100 ? - WM8978_PLL : WM8978_MCLK; - unsigned int f_sel, diff, diff_best = INT_MAX; - int i, best = 0; - - if (!wm8978->f_mclk) - return -EINVAL; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface_ctl |= 0x20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface_ctl |= 0x40; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface_ctl |= 0x60; - break; - } - - /* filter coefficient */ - switch (params_rate(params)) { - case 8000: - add_ctl |= 0x5 << 1; - break; - case 11025: - add_ctl |= 0x4 << 1; - break; - case 16000: - add_ctl |= 0x3 << 1; - break; - case 22050: - add_ctl |= 0x2 << 1; - break; - case 32000: - add_ctl |= 0x1 << 1; - break; - case 44100: - case 48000: - break; - } - - /* Sampling rate is known now, can configure the MCLK divider */ - wm8978->f_256fs = params_rate(params) * 256; - - if (wm8978->sysclk == WM8978_MCLK) { - wm8978->mclk_idx = -1; - f_sel = wm8978->f_mclk; - } else { - if (!wm8978->f_pllout) { - /* We only enter here, if OPCLK is not used */ - int ret = wm8978_configure_pll(codec); - if (ret < 0) - return ret; - } - f_sel = wm8978->f_pllout; - } - - if (wm8978->mclk_idx < 0) { - /* Either MCLK is used directly, or OPCLK is used */ - if (f_sel < wm8978->f_256fs || f_sel > 12 * wm8978->f_256fs) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(mclk_numerator); i++) { - diff = abs(wm8978->f_256fs * 3 - - f_sel * 3 * mclk_denominator[i] / mclk_numerator[i]); - - if (diff < diff_best) { - diff_best = diff; - best = i; - } - - if (!diff) - break; - } - } else { - /* OPCLK not used, codec driven by PLL */ - best = wm8978->mclk_idx; - diff = 0; - } - - if (diff) - dev_warn(codec->dev, "Imprecise sampling rate: %uHz%s\n", - f_sel * mclk_denominator[best] / mclk_numerator[best] / 256, - wm8978->sysclk == WM8978_MCLK ? - ", consider using PLL" : ""); - - dev_dbg(codec->dev, "%s: fmt %d, rate %u, MCLK divisor #%d\n", __func__, - params_format(params), params_rate(params), best); - - /* MCLK divisor mask = 0xe0 */ - snd_soc_update_bits(codec, WM8978_CLOCKING, 0xe0, best << 5); - - snd_soc_write(codec, WM8978_AUDIO_INTERFACE, iface_ctl); - snd_soc_write(codec, WM8978_ADDITIONAL_CONTROL, add_ctl); - - if (wm8978->sysclk != current_clk_id) { - if (wm8978->sysclk == WM8978_PLL) - /* Run CODEC from PLL instead of MCLK */ - snd_soc_update_bits(codec, WM8978_CLOCKING, - 0x100, 0x100); - else - /* Clock CODEC directly from MCLK */ - snd_soc_update_bits(codec, WM8978_CLOCKING, 0x100, 0); - } - - return 0; -} - -static int wm8978_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - dev_dbg(codec->dev, "%s: %d\n", __func__, mute); - - if (mute) - snd_soc_update_bits(codec, WM8978_DAC_CONTROL, 0x40, 0x40); - else - snd_soc_update_bits(codec, WM8978_DAC_CONTROL, 0x40, 0); - - return 0; -} - -static int wm8978_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 power1 = snd_soc_read(codec, WM8978_POWER_MANAGEMENT_1) & ~3; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - power1 |= 1; /* VMID 75k */ - snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, power1); - break; - case SND_SOC_BIAS_STANDBY: - /* bit 3: enable bias, bit 2: enable I/O tie off buffer */ - power1 |= 0xc; - - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - /* Initial cap charge at VMID 5k */ - snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, - power1 | 0x3); - mdelay(100); - } - - power1 |= 0x2; /* VMID 500k */ - snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, power1); - break; - case SND_SOC_BIAS_OFF: - /* Preserve PLL - OPCLK may be used by someone */ - snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, ~0x20, 0); - snd_soc_write(codec, WM8978_POWER_MANAGEMENT_2, 0); - snd_soc_write(codec, WM8978_POWER_MANAGEMENT_3, 0); - break; - } - - dev_dbg(codec->dev, "%s: %d, %x\n", __func__, level, power1); - - codec->dapm.bias_level = level; - return 0; -} - -#define WM8978_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8978_dai_ops = { - .hw_params = wm8978_hw_params, - .digital_mute = wm8978_mute, - .set_fmt = wm8978_set_dai_fmt, - .set_clkdiv = wm8978_set_dai_clkdiv, - .set_sysclk = wm8978_set_dai_sysclk, -}; - -/* Also supports 12kHz */ -static struct snd_soc_dai_driver wm8978_dai = { - .name = "wm8978-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8978_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8978_FORMATS, - }, - .ops = &wm8978_dai_ops, -}; - -static int wm8978_suspend(struct snd_soc_codec *codec) -{ - struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - - wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); - /* Also switch PLL off */ - snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); - - regcache_mark_dirty(wm8978->regmap); - - return 0; -} - -static int wm8978_resume(struct snd_soc_codec *codec) -{ - struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - - /* Sync reg_cache with the hardware */ - regcache_sync(wm8978->regmap); - - wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - if (wm8978->f_pllout) - /* Switch PLL on */ - snd_soc_update_bits(codec, WM8978_POWER_MANAGEMENT_1, 0x20, 0x20); - - return 0; -} - -/* - * These registers contain an "update" bit - bit 8. This means, for example, - * that one can write new DAC digital volume for both channels, but only when - * the update bit is set, will also the volume be updated - simultaneously for - * both channels. - */ -static const int update_reg[] = { - WM8978_LEFT_DAC_DIGITAL_VOLUME, - WM8978_RIGHT_DAC_DIGITAL_VOLUME, - WM8978_LEFT_ADC_DIGITAL_VOLUME, - WM8978_RIGHT_ADC_DIGITAL_VOLUME, - WM8978_LEFT_INP_PGA_CONTROL, - WM8978_RIGHT_INP_PGA_CONTROL, - WM8978_LOUT1_HP_CONTROL, - WM8978_ROUT1_HP_CONTROL, - WM8978_LOUT2_SPK_CONTROL, - WM8978_ROUT2_SPK_CONTROL, -}; - -static int wm8978_probe(struct snd_soc_codec *codec) -{ - struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); - int ret = 0, i; - - /* - * Set default system clock to PLL, it is more precise, this is also the - * default hardware setting - */ - wm8978->sysclk = WM8978_PLL; - codec->control_data = wm8978->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* - * Set the update bit in all registers, that have one. This way all - * writes to those registers will also cause the update bit to be - * written. - */ - for (i = 0; i < ARRAY_SIZE(update_reg); i++) - snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100); - - wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -/* power down chip */ -static int wm8978_remove(struct snd_soc_codec *codec) -{ - wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8978 = { - .probe = wm8978_probe, - .remove = wm8978_remove, - .suspend = wm8978_suspend, - .resume = wm8978_resume, - .set_bias_level = wm8978_set_bias_level, - - .controls = wm8978_snd_controls, - .num_controls = ARRAY_SIZE(wm8978_snd_controls), - .dapm_widgets = wm8978_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets), - .dapm_routes = wm8978_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes), -}; - -static const struct regmap_config wm8978_regmap_config = { - .reg_bits = 7, - .val_bits = 9, - - .max_register = WM8978_MAX_REGISTER, - .volatile_reg = wm8978_volatile, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8978_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults), -}; - -static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8978_priv *wm8978; - int ret; - - wm8978 = devm_kzalloc(&i2c->dev, sizeof(struct wm8978_priv), - GFP_KERNEL); - if (wm8978 == NULL) - return -ENOMEM; - - wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config); - if (IS_ERR(wm8978->regmap)) { - ret = PTR_ERR(wm8978->regmap); - dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); - return ret; - } - - i2c_set_clientdata(i2c, wm8978); - - /* Reset the codec */ - ret = regmap_write(wm8978->regmap, WM8978_RESET, 0); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); - goto err; - } - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8978, &wm8978_dai, 1); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - goto err; - } - - return 0; - -err: - regmap_exit(wm8978->regmap); - return ret; -} - -static __devexit int wm8978_i2c_remove(struct i2c_client *client) -{ - struct wm8978_priv *wm8978 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8978->regmap); - - return 0; -} - -static const struct i2c_device_id wm8978_i2c_id[] = { - { "wm8978", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id); - -static struct i2c_driver wm8978_i2c_driver = { - .driver = { - .name = "wm8978", - .owner = THIS_MODULE, - }, - .probe = wm8978_i2c_probe, - .remove = __devexit_p(wm8978_i2c_remove), - .id_table = wm8978_i2c_id, -}; - -static int __init wm8978_modinit(void) -{ - int ret = 0; - ret = i2c_add_driver(&wm8978_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", - ret); - } - return ret; -} -module_init(wm8978_modinit); - -static void __exit wm8978_exit(void) -{ - i2c_del_driver(&wm8978_i2c_driver); -} -module_exit(wm8978_exit); - -MODULE_DESCRIPTION("ASoC WM8978 codec driver"); -MODULE_AUTHOR("Guennadi Liakhovetski "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8978.h b/ANDROID_3.4.5/sound/soc/codecs/wm8978.h deleted file mode 100644 index 6ae43495..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8978.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * wm8978.h -- codec driver for WM8978 - * - * Copyright 2009 Guennadi Liakhovetski - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __WM8978_H__ -#define __WM8978_H__ - -/* - * Register values. - */ -#define WM8978_RESET 0x00 -#define WM8978_POWER_MANAGEMENT_1 0x01 -#define WM8978_POWER_MANAGEMENT_2 0x02 -#define WM8978_POWER_MANAGEMENT_3 0x03 -#define WM8978_AUDIO_INTERFACE 0x04 -#define WM8978_COMPANDING_CONTROL 0x05 -#define WM8978_CLOCKING 0x06 -#define WM8978_ADDITIONAL_CONTROL 0x07 -#define WM8978_GPIO_CONTROL 0x08 -#define WM8978_JACK_DETECT_CONTROL_1 0x09 -#define WM8978_DAC_CONTROL 0x0A -#define WM8978_LEFT_DAC_DIGITAL_VOLUME 0x0B -#define WM8978_RIGHT_DAC_DIGITAL_VOLUME 0x0C -#define WM8978_JACK_DETECT_CONTROL_2 0x0D -#define WM8978_ADC_CONTROL 0x0E -#define WM8978_LEFT_ADC_DIGITAL_VOLUME 0x0F -#define WM8978_RIGHT_ADC_DIGITAL_VOLUME 0x10 -#define WM8978_EQ1 0x12 -#define WM8978_EQ2 0x13 -#define WM8978_EQ3 0x14 -#define WM8978_EQ4 0x15 -#define WM8978_EQ5 0x16 -#define WM8978_DAC_LIMITER_1 0x18 -#define WM8978_DAC_LIMITER_2 0x19 -#define WM8978_NOTCH_FILTER_1 0x1b -#define WM8978_NOTCH_FILTER_2 0x1c -#define WM8978_NOTCH_FILTER_3 0x1d -#define WM8978_NOTCH_FILTER_4 0x1e -#define WM8978_ALC_CONTROL_1 0x20 -#define WM8978_ALC_CONTROL_2 0x21 -#define WM8978_ALC_CONTROL_3 0x22 -#define WM8978_NOISE_GATE 0x23 -#define WM8978_PLL_N 0x24 -#define WM8978_PLL_K1 0x25 -#define WM8978_PLL_K2 0x26 -#define WM8978_PLL_K3 0x27 -#define WM8978_3D_CONTROL 0x29 -#define WM8978_BEEP_CONTROL 0x2b -#define WM8978_INPUT_CONTROL 0x2c -#define WM8978_LEFT_INP_PGA_CONTROL 0x2d -#define WM8978_RIGHT_INP_PGA_CONTROL 0x2e -#define WM8978_LEFT_ADC_BOOST_CONTROL 0x2f -#define WM8978_RIGHT_ADC_BOOST_CONTROL 0x30 -#define WM8978_OUTPUT_CONTROL 0x31 -#define WM8978_LEFT_MIXER_CONTROL 0x32 -#define WM8978_RIGHT_MIXER_CONTROL 0x33 -#define WM8978_LOUT1_HP_CONTROL 0x34 -#define WM8978_ROUT1_HP_CONTROL 0x35 -#define WM8978_LOUT2_SPK_CONTROL 0x36 -#define WM8978_ROUT2_SPK_CONTROL 0x37 -#define WM8978_OUT3_MIXER_CONTROL 0x38 -#define WM8978_OUT4_MIXER_CONTROL 0x39 - -#define WM8978_MAX_REGISTER 0x39 - -#define WM8978_CACHEREGNUM 58 - -/* Clock divider Id's */ -enum wm8978_clk_id { - WM8978_OPCLKRATE, - WM8978_BCLKDIV, -}; - -enum wm8978_sysclk_src { - WM8978_PLL, - WM8978_MCLK -}; - -#endif /* __WM8978_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8983.c b/ANDROID_3.4.5/sound/soc/codecs/wm8983.c deleted file mode 100644 index 367388fd..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8983.c +++ /dev/null @@ -1,1199 +0,0 @@ -/* - * wm8983.c -- WM8983 ALSA SoC Audio driver - * - * Copyright 2011 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8983.h" - -static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = { - [0x00] = 0x0000, /* R0 - Software Reset */ - [0x01] = 0x0000, /* R1 - Power management 1 */ - [0x02] = 0x0000, /* R2 - Power management 2 */ - [0x03] = 0x0000, /* R3 - Power management 3 */ - [0x04] = 0x0050, /* R4 - Audio Interface */ - [0x05] = 0x0000, /* R5 - Companding control */ - [0x06] = 0x0140, /* R6 - Clock Gen control */ - [0x07] = 0x0000, /* R7 - Additional control */ - [0x08] = 0x0000, /* R8 - GPIO Control */ - [0x09] = 0x0000, /* R9 - Jack Detect Control 1 */ - [0x0A] = 0x0000, /* R10 - DAC Control */ - [0x0B] = 0x00FF, /* R11 - Left DAC digital Vol */ - [0x0C] = 0x00FF, /* R12 - Right DAC digital vol */ - [0x0D] = 0x0000, /* R13 - Jack Detect Control 2 */ - [0x0E] = 0x0100, /* R14 - ADC Control */ - [0x0F] = 0x00FF, /* R15 - Left ADC Digital Vol */ - [0x10] = 0x00FF, /* R16 - Right ADC Digital Vol */ - [0x12] = 0x012C, /* R18 - EQ1 - low shelf */ - [0x13] = 0x002C, /* R19 - EQ2 - peak 1 */ - [0x14] = 0x002C, /* R20 - EQ3 - peak 2 */ - [0x15] = 0x002C, /* R21 - EQ4 - peak 3 */ - [0x16] = 0x002C, /* R22 - EQ5 - high shelf */ - [0x18] = 0x0032, /* R24 - DAC Limiter 1 */ - [0x19] = 0x0000, /* R25 - DAC Limiter 2 */ - [0x1B] = 0x0000, /* R27 - Notch Filter 1 */ - [0x1C] = 0x0000, /* R28 - Notch Filter 2 */ - [0x1D] = 0x0000, /* R29 - Notch Filter 3 */ - [0x1E] = 0x0000, /* R30 - Notch Filter 4 */ - [0x20] = 0x0038, /* R32 - ALC control 1 */ - [0x21] = 0x000B, /* R33 - ALC control 2 */ - [0x22] = 0x0032, /* R34 - ALC control 3 */ - [0x23] = 0x0000, /* R35 - Noise Gate */ - [0x24] = 0x0008, /* R36 - PLL N */ - [0x25] = 0x000C, /* R37 - PLL K 1 */ - [0x26] = 0x0093, /* R38 - PLL K 2 */ - [0x27] = 0x00E9, /* R39 - PLL K 3 */ - [0x29] = 0x0000, /* R41 - 3D control */ - [0x2A] = 0x0000, /* R42 - OUT4 to ADC */ - [0x2B] = 0x0000, /* R43 - Beep control */ - [0x2C] = 0x0033, /* R44 - Input ctrl */ - [0x2D] = 0x0010, /* R45 - Left INP PGA gain ctrl */ - [0x2E] = 0x0010, /* R46 - Right INP PGA gain ctrl */ - [0x2F] = 0x0100, /* R47 - Left ADC BOOST ctrl */ - [0x30] = 0x0100, /* R48 - Right ADC BOOST ctrl */ - [0x31] = 0x0002, /* R49 - Output ctrl */ - [0x32] = 0x0001, /* R50 - Left mixer ctrl */ - [0x33] = 0x0001, /* R51 - Right mixer ctrl */ - [0x34] = 0x0039, /* R52 - LOUT1 (HP) volume ctrl */ - [0x35] = 0x0039, /* R53 - ROUT1 (HP) volume ctrl */ - [0x36] = 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */ - [0x37] = 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */ - [0x38] = 0x0001, /* R56 - OUT3 mixer ctrl */ - [0x39] = 0x0001, /* R57 - OUT4 (MONO) mix ctrl */ - [0x3D] = 0x0000 /* R61 - BIAS CTRL */ -}; - -static const struct wm8983_reg_access { - u16 read; /* Mask of readable bits */ - u16 write; /* Mask of writable bits */ -} wm8983_access_masks[WM8983_MAX_REGISTER + 1] = { - [0x00] = { 0x0000, 0x01FF }, /* R0 - Software Reset */ - [0x01] = { 0x0000, 0x01FF }, /* R1 - Power management 1 */ - [0x02] = { 0x0000, 0x01FF }, /* R2 - Power management 2 */ - [0x03] = { 0x0000, 0x01EF }, /* R3 - Power management 3 */ - [0x04] = { 0x0000, 0x01FF }, /* R4 - Audio Interface */ - [0x05] = { 0x0000, 0x003F }, /* R5 - Companding control */ - [0x06] = { 0x0000, 0x01FD }, /* R6 - Clock Gen control */ - [0x07] = { 0x0000, 0x000F }, /* R7 - Additional control */ - [0x08] = { 0x0000, 0x003F }, /* R8 - GPIO Control */ - [0x09] = { 0x0000, 0x0070 }, /* R9 - Jack Detect Control 1 */ - [0x0A] = { 0x0000, 0x004F }, /* R10 - DAC Control */ - [0x0B] = { 0x0000, 0x01FF }, /* R11 - Left DAC digital Vol */ - [0x0C] = { 0x0000, 0x01FF }, /* R12 - Right DAC digital vol */ - [0x0D] = { 0x0000, 0x00FF }, /* R13 - Jack Detect Control 2 */ - [0x0E] = { 0x0000, 0x01FB }, /* R14 - ADC Control */ - [0x0F] = { 0x0000, 0x01FF }, /* R15 - Left ADC Digital Vol */ - [0x10] = { 0x0000, 0x01FF }, /* R16 - Right ADC Digital Vol */ - [0x12] = { 0x0000, 0x017F }, /* R18 - EQ1 - low shelf */ - [0x13] = { 0x0000, 0x017F }, /* R19 - EQ2 - peak 1 */ - [0x14] = { 0x0000, 0x017F }, /* R20 - EQ3 - peak 2 */ - [0x15] = { 0x0000, 0x017F }, /* R21 - EQ4 - peak 3 */ - [0x16] = { 0x0000, 0x007F }, /* R22 - EQ5 - high shelf */ - [0x18] = { 0x0000, 0x01FF }, /* R24 - DAC Limiter 1 */ - [0x19] = { 0x0000, 0x007F }, /* R25 - DAC Limiter 2 */ - [0x1B] = { 0x0000, 0x01FF }, /* R27 - Notch Filter 1 */ - [0x1C] = { 0x0000, 0x017F }, /* R28 - Notch Filter 2 */ - [0x1D] = { 0x0000, 0x017F }, /* R29 - Notch Filter 3 */ - [0x1E] = { 0x0000, 0x017F }, /* R30 - Notch Filter 4 */ - [0x20] = { 0x0000, 0x01BF }, /* R32 - ALC control 1 */ - [0x21] = { 0x0000, 0x00FF }, /* R33 - ALC control 2 */ - [0x22] = { 0x0000, 0x01FF }, /* R34 - ALC control 3 */ - [0x23] = { 0x0000, 0x000F }, /* R35 - Noise Gate */ - [0x24] = { 0x0000, 0x001F }, /* R36 - PLL N */ - [0x25] = { 0x0000, 0x003F }, /* R37 - PLL K 1 */ - [0x26] = { 0x0000, 0x01FF }, /* R38 - PLL K 2 */ - [0x27] = { 0x0000, 0x01FF }, /* R39 - PLL K 3 */ - [0x29] = { 0x0000, 0x000F }, /* R41 - 3D control */ - [0x2A] = { 0x0000, 0x01E7 }, /* R42 - OUT4 to ADC */ - [0x2B] = { 0x0000, 0x01BF }, /* R43 - Beep control */ - [0x2C] = { 0x0000, 0x0177 }, /* R44 - Input ctrl */ - [0x2D] = { 0x0000, 0x01FF }, /* R45 - Left INP PGA gain ctrl */ - [0x2E] = { 0x0000, 0x01FF }, /* R46 - Right INP PGA gain ctrl */ - [0x2F] = { 0x0000, 0x0177 }, /* R47 - Left ADC BOOST ctrl */ - [0x30] = { 0x0000, 0x0177 }, /* R48 - Right ADC BOOST ctrl */ - [0x31] = { 0x0000, 0x007F }, /* R49 - Output ctrl */ - [0x32] = { 0x0000, 0x01FF }, /* R50 - Left mixer ctrl */ - [0x33] = { 0x0000, 0x01FF }, /* R51 - Right mixer ctrl */ - [0x34] = { 0x0000, 0x01FF }, /* R52 - LOUT1 (HP) volume ctrl */ - [0x35] = { 0x0000, 0x01FF }, /* R53 - ROUT1 (HP) volume ctrl */ - [0x36] = { 0x0000, 0x01FF }, /* R54 - LOUT2 (SPK) volume ctrl */ - [0x37] = { 0x0000, 0x01FF }, /* R55 - ROUT2 (SPK) volume ctrl */ - [0x38] = { 0x0000, 0x004F }, /* R56 - OUT3 mixer ctrl */ - [0x39] = { 0x0000, 0x00FF }, /* R57 - OUT4 (MONO) mix ctrl */ - [0x3D] = { 0x0000, 0x0100 } /* R61 - BIAS CTRL */ -}; - -/* vol/gain update regs */ -static const int vol_update_regs[] = { - WM8983_LEFT_DAC_DIGITAL_VOL, - WM8983_RIGHT_DAC_DIGITAL_VOL, - WM8983_LEFT_ADC_DIGITAL_VOL, - WM8983_RIGHT_ADC_DIGITAL_VOL, - WM8983_LOUT1_HP_VOLUME_CTRL, - WM8983_ROUT1_HP_VOLUME_CTRL, - WM8983_LOUT2_SPK_VOLUME_CTRL, - WM8983_ROUT2_SPK_VOLUME_CTRL, - WM8983_LEFT_INP_PGA_GAIN_CTRL, - WM8983_RIGHT_INP_PGA_GAIN_CTRL -}; - -struct wm8983_priv { - enum snd_soc_control_type control_type; - u32 sysclk; - u32 bclk; -}; - -static const struct { - int div; - int ratio; -} fs_ratios[] = { - { 10, 128 }, - { 15, 192 }, - { 20, 256 }, - { 30, 384 }, - { 40, 512 }, - { 60, 768 }, - { 80, 1024 }, - { 120, 1536 } -}; - -static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 }; - -static const int bclk_divs[] = { - 1, 2, 4, 8, 16, 32 -}; - -static int eqmode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -static int eqmode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1); -static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); -static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0); -static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0); -static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0); -static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0); -static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0); -static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); - -static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; -static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, - alc_sel_text); - -static const char *alc_mode_text[] = { "ALC", "Limiter" }; -static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, - alc_mode_text); - -static const char *filter_mode_text[] = { "Audio", "Application" }; -static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7, - filter_mode_text); - -static const char *eq_bw_text[] = { "Narrow", "Wide" }; -static const char *eqmode_text[] = { "Capture", "Playback" }; -static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); - -static const char *eq1_cutoff_text[] = { - "80Hz", "105Hz", "135Hz", "175Hz" -}; -static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5, - eq1_cutoff_text); -static const char *eq2_cutoff_text[] = { - "230Hz", "300Hz", "385Hz", "500Hz" -}; -static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, - eq2_cutoff_text); -static const char *eq3_cutoff_text[] = { - "650Hz", "850Hz", "1.1kHz", "1.4kHz" -}; -static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, - eq3_cutoff_text); -static const char *eq4_cutoff_text[] = { - "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" -}; -static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, - eq4_cutoff_text); -static const char *eq5_cutoff_text[] = { - "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" -}; -static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5, - eq5_cutoff_text); - -static const char *depth_3d_text[] = { - "Off", - "6.67%", - "13.3%", - "20%", - "26.7%", - "33.3%", - "40%", - "46.6%", - "53.3%", - "60%", - "66.7%", - "73.3%", - "80%", - "86.7%", - "93.3%", - "100%" -}; -static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0, - depth_3d_text); - -static const struct snd_kcontrol_new wm8983_snd_controls[] = { - SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL, - 0, 1, 0), - - SOC_ENUM("ALC Capture Function", alc_sel), - SOC_SINGLE_TLV("ALC Capture Max Volume", WM8983_ALC_CONTROL_1, - 3, 7, 0, alc_max_tlv), - SOC_SINGLE_TLV("ALC Capture Min Volume", WM8983_ALC_CONTROL_1, - 0, 7, 0, alc_min_tlv), - SOC_SINGLE_TLV("ALC Capture Target Volume", WM8983_ALC_CONTROL_2, - 0, 15, 0, alc_tar_tlv), - SOC_SINGLE("ALC Capture Attack", WM8983_ALC_CONTROL_3, 0, 10, 0), - SOC_SINGLE("ALC Capture Hold", WM8983_ALC_CONTROL_2, 4, 10, 0), - SOC_SINGLE("ALC Capture Decay", WM8983_ALC_CONTROL_3, 4, 10, 0), - SOC_ENUM("ALC Mode", alc_mode), - SOC_SINGLE("ALC Capture NG Switch", WM8983_NOISE_GATE, - 3, 1, 0), - SOC_SINGLE("ALC Capture NG Threshold", WM8983_NOISE_GATE, - 0, 7, 1), - - SOC_DOUBLE_R_TLV("Capture Volume", WM8983_LEFT_ADC_DIGITAL_VOL, - WM8983_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv), - SOC_DOUBLE_R("Capture PGA ZC Switch", WM8983_LEFT_INP_PGA_GAIN_CTRL, - WM8983_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0), - SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8983_LEFT_INP_PGA_GAIN_CTRL, - WM8983_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv), - - SOC_DOUBLE_R_TLV("Capture PGA Boost Volume", - WM8983_LEFT_ADC_BOOST_CTRL, WM8983_RIGHT_ADC_BOOST_CTRL, - 8, 1, 0, pga_boost_tlv), - - SOC_DOUBLE("ADC Inversion Switch", WM8983_ADC_CONTROL, 0, 1, 1, 0), - SOC_SINGLE("ADC 128x Oversampling Switch", WM8983_ADC_CONTROL, 8, 1, 0), - - SOC_DOUBLE_R_TLV("Playback Volume", WM8983_LEFT_DAC_DIGITAL_VOL, - WM8983_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv), - - SOC_SINGLE("DAC Playback Limiter Switch", WM8983_DAC_LIMITER_1, 8, 1, 0), - SOC_SINGLE("DAC Playback Limiter Decay", WM8983_DAC_LIMITER_1, 4, 10, 0), - SOC_SINGLE("DAC Playback Limiter Attack", WM8983_DAC_LIMITER_1, 0, 11, 0), - SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8983_DAC_LIMITER_2, - 4, 7, 1, lim_thresh_tlv), - SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8983_DAC_LIMITER_2, - 0, 12, 0, lim_boost_tlv), - SOC_DOUBLE("DAC Inversion Switch", WM8983_DAC_CONTROL, 0, 1, 1, 0), - SOC_SINGLE("DAC Auto Mute Switch", WM8983_DAC_CONTROL, 2, 1, 0), - SOC_SINGLE("DAC 128x Oversampling Switch", WM8983_DAC_CONTROL, 3, 1, 0), - - SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8983_LOUT1_HP_VOLUME_CTRL, - WM8983_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv), - SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8983_LOUT1_HP_VOLUME_CTRL, - WM8983_ROUT1_HP_VOLUME_CTRL, 7, 1, 0), - SOC_DOUBLE_R("Headphone Switch", WM8983_LOUT1_HP_VOLUME_CTRL, - WM8983_ROUT1_HP_VOLUME_CTRL, 6, 1, 1), - - SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8983_LOUT2_SPK_VOLUME_CTRL, - WM8983_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv), - SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8983_LOUT2_SPK_VOLUME_CTRL, - WM8983_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0), - SOC_DOUBLE_R("Speaker Switch", WM8983_LOUT2_SPK_VOLUME_CTRL, - WM8983_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1), - - SOC_SINGLE("OUT3 Switch", WM8983_OUT3_MIXER_CTRL, - 6, 1, 1), - - SOC_SINGLE("OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, - 6, 1, 1), - - SOC_SINGLE("High Pass Filter Switch", WM8983_ADC_CONTROL, 8, 1, 0), - SOC_ENUM("High Pass Filter Mode", filter_mode), - SOC_SINGLE("High Pass Filter Cutoff", WM8983_ADC_CONTROL, 4, 7, 0), - - SOC_DOUBLE_R_TLV("Aux Bypass Volume", - WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 6, 7, 0, - aux_tlv), - - SOC_DOUBLE_R_TLV("Input PGA Bypass Volume", - WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 2, 7, 0, - bypass_tlv), - - SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put), - SOC_ENUM("EQ1 Cutoff", eq1_cutoff), - SOC_SINGLE_TLV("EQ1 Volume", WM8983_EQ1_LOW_SHELF, 0, 24, 1, eq_tlv), - SOC_ENUM("EQ2 Bandwith", eq2_bw), - SOC_ENUM("EQ2 Cutoff", eq2_cutoff), - SOC_SINGLE_TLV("EQ2 Volume", WM8983_EQ2_PEAK_1, 0, 24, 1, eq_tlv), - SOC_ENUM("EQ3 Bandwith", eq3_bw), - SOC_ENUM("EQ3 Cutoff", eq3_cutoff), - SOC_SINGLE_TLV("EQ3 Volume", WM8983_EQ3_PEAK_2, 0, 24, 1, eq_tlv), - SOC_ENUM("EQ4 Bandwith", eq4_bw), - SOC_ENUM("EQ4 Cutoff", eq4_cutoff), - SOC_SINGLE_TLV("EQ4 Volume", WM8983_EQ4_PEAK_3, 0, 24, 1, eq_tlv), - SOC_ENUM("EQ5 Cutoff", eq5_cutoff), - SOC_SINGLE_TLV("EQ5 Volume", WM8983_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv), - - SOC_ENUM("3D Depth", depth_3d), -}; - -static const struct snd_kcontrol_new left_out_mixer[] = { - SOC_DAPM_SINGLE("Line Switch", WM8983_LEFT_MIXER_CTRL, 1, 1, 0), - SOC_DAPM_SINGLE("Aux Switch", WM8983_LEFT_MIXER_CTRL, 5, 1, 0), - SOC_DAPM_SINGLE("PCM Switch", WM8983_LEFT_MIXER_CTRL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_out_mixer[] = { - SOC_DAPM_SINGLE("Line Switch", WM8983_RIGHT_MIXER_CTRL, 1, 1, 0), - SOC_DAPM_SINGLE("Aux Switch", WM8983_RIGHT_MIXER_CTRL, 5, 1, 0), - SOC_DAPM_SINGLE("PCM Switch", WM8983_RIGHT_MIXER_CTRL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new left_input_mixer[] = { - SOC_DAPM_SINGLE("L2 Switch", WM8983_INPUT_CTRL, 2, 1, 0), - SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 1, 1, 0), - SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_input_mixer[] = { - SOC_DAPM_SINGLE("R2 Switch", WM8983_INPUT_CTRL, 6, 1, 0), - SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 5, 1, 0), - SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 4, 1, 0), -}; - -static const struct snd_kcontrol_new left_boost_mixer[] = { - SOC_DAPM_SINGLE_TLV("L2 Volume", WM8983_LEFT_ADC_BOOST_CTRL, - 4, 7, 0, boost_tlv), - SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8983_LEFT_ADC_BOOST_CTRL, - 0, 7, 0, boost_tlv) -}; - -static const struct snd_kcontrol_new out3_mixer[] = { - SOC_DAPM_SINGLE("LMIX2OUT3 Switch", WM8983_OUT3_MIXER_CTRL, - 1, 1, 0), - SOC_DAPM_SINGLE("LDAC2OUT3 Switch", WM8983_OUT3_MIXER_CTRL, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new out4_mixer[] = { - SOC_DAPM_SINGLE("LMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, - 4, 1, 0), - SOC_DAPM_SINGLE("RMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, - 1, 1, 0), - SOC_DAPM_SINGLE("LDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, - 3, 1, 0), - SOC_DAPM_SINGLE("RDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_boost_mixer[] = { - SOC_DAPM_SINGLE_TLV("R2 Volume", WM8983_RIGHT_ADC_BOOST_CTRL, - 4, 7, 0, boost_tlv), - SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8983_RIGHT_ADC_BOOST_CTRL, - 0, 7, 0, boost_tlv) -}; - -static const struct snd_soc_dapm_widget wm8983_dapm_widgets[] = { - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8983_POWER_MANAGEMENT_3, - 0, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8983_POWER_MANAGEMENT_3, - 1, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8983_POWER_MANAGEMENT_2, - 0, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8983_POWER_MANAGEMENT_2, - 1, 0), - - SND_SOC_DAPM_MIXER("Left Output Mixer", WM8983_POWER_MANAGEMENT_3, - 2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)), - SND_SOC_DAPM_MIXER("Right Output Mixer", WM8983_POWER_MANAGEMENT_3, - 3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)), - - SND_SOC_DAPM_MIXER("Left Input Mixer", WM8983_POWER_MANAGEMENT_2, - 2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)), - SND_SOC_DAPM_MIXER("Right Input Mixer", WM8983_POWER_MANAGEMENT_2, - 3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)), - - SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8983_POWER_MANAGEMENT_2, - 4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)), - SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8983_POWER_MANAGEMENT_2, - 5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)), - - SND_SOC_DAPM_MIXER("OUT3 Mixer", WM8983_POWER_MANAGEMENT_1, - 6, 0, out3_mixer, ARRAY_SIZE(out3_mixer)), - - SND_SOC_DAPM_MIXER("OUT4 Mixer", WM8983_POWER_MANAGEMENT_1, - 7, 0, out4_mixer, ARRAY_SIZE(out4_mixer)), - - SND_SOC_DAPM_PGA("Left Capture PGA", WM8983_LEFT_INP_PGA_GAIN_CTRL, - 6, 1, NULL, 0), - SND_SOC_DAPM_PGA("Right Capture PGA", WM8983_RIGHT_INP_PGA_GAIN_CTRL, - 6, 1, NULL, 0), - - SND_SOC_DAPM_PGA("Left Headphone Out", WM8983_POWER_MANAGEMENT_2, - 7, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Headphone Out", WM8983_POWER_MANAGEMENT_2, - 8, 0, NULL, 0), - - SND_SOC_DAPM_PGA("Left Speaker Out", WM8983_POWER_MANAGEMENT_3, - 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Speaker Out", WM8983_POWER_MANAGEMENT_3, - 6, 0, NULL, 0), - - SND_SOC_DAPM_PGA("OUT3 Out", WM8983_POWER_MANAGEMENT_3, - 7, 0, NULL, 0), - - SND_SOC_DAPM_PGA("OUT4 Out", WM8983_POWER_MANAGEMENT_3, - 8, 0, NULL, 0), - - SND_SOC_DAPM_SUPPLY("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0, - NULL, 0), - - SND_SOC_DAPM_INPUT("LIN"), - SND_SOC_DAPM_INPUT("LIP"), - SND_SOC_DAPM_INPUT("RIN"), - SND_SOC_DAPM_INPUT("RIP"), - SND_SOC_DAPM_INPUT("AUXL"), - SND_SOC_DAPM_INPUT("AUXR"), - SND_SOC_DAPM_INPUT("L2"), - SND_SOC_DAPM_INPUT("R2"), - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - SND_SOC_DAPM_OUTPUT("SPKL"), - SND_SOC_DAPM_OUTPUT("SPKR"), - SND_SOC_DAPM_OUTPUT("OUT3"), - SND_SOC_DAPM_OUTPUT("OUT4") -}; - -static const struct snd_soc_dapm_route wm8983_audio_map[] = { - { "OUT3 Mixer", "LMIX2OUT3 Switch", "Left Output Mixer" }, - { "OUT3 Mixer", "LDAC2OUT3 Switch", "Left DAC" }, - - { "OUT3 Out", NULL, "OUT3 Mixer" }, - { "OUT3", NULL, "OUT3 Out" }, - - { "OUT4 Mixer", "LMIX2OUT4 Switch", "Left Output Mixer" }, - { "OUT4 Mixer", "RMIX2OUT4 Switch", "Right Output Mixer" }, - { "OUT4 Mixer", "LDAC2OUT4 Switch", "Left DAC" }, - { "OUT4 Mixer", "RDAC2OUT4 Switch", "Right DAC" }, - - { "OUT4 Out", NULL, "OUT4 Mixer" }, - { "OUT4", NULL, "OUT4 Out" }, - - { "Right Output Mixer", "PCM Switch", "Right DAC" }, - { "Right Output Mixer", "Aux Switch", "AUXR" }, - { "Right Output Mixer", "Line Switch", "Right Boost Mixer" }, - - { "Left Output Mixer", "PCM Switch", "Left DAC" }, - { "Left Output Mixer", "Aux Switch", "AUXL" }, - { "Left Output Mixer", "Line Switch", "Left Boost Mixer" }, - - { "Right Headphone Out", NULL, "Right Output Mixer" }, - { "HPR", NULL, "Right Headphone Out" }, - - { "Left Headphone Out", NULL, "Left Output Mixer" }, - { "HPL", NULL, "Left Headphone Out" }, - - { "Right Speaker Out", NULL, "Right Output Mixer" }, - { "SPKR", NULL, "Right Speaker Out" }, - - { "Left Speaker Out", NULL, "Left Output Mixer" }, - { "SPKL", NULL, "Left Speaker Out" }, - - { "Right ADC", NULL, "Right Boost Mixer" }, - - { "Right Boost Mixer", "AUXR Volume", "AUXR" }, - { "Right Boost Mixer", NULL, "Right Capture PGA" }, - { "Right Boost Mixer", "R2 Volume", "R2" }, - - { "Left ADC", NULL, "Left Boost Mixer" }, - - { "Left Boost Mixer", "AUXL Volume", "AUXL" }, - { "Left Boost Mixer", NULL, "Left Capture PGA" }, - { "Left Boost Mixer", "L2 Volume", "L2" }, - - { "Right Capture PGA", NULL, "Right Input Mixer" }, - { "Left Capture PGA", NULL, "Left Input Mixer" }, - - { "Right Input Mixer", "R2 Switch", "R2" }, - { "Right Input Mixer", "MicN Switch", "RIN" }, - { "Right Input Mixer", "MicP Switch", "RIP" }, - - { "Left Input Mixer", "L2 Switch", "L2" }, - { "Left Input Mixer", "MicN Switch", "LIN" }, - { "Left Input Mixer", "MicP Switch", "LIP" }, -}; - -static int eqmode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg; - - reg = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF); - if (reg & WM8983_EQ3DMODE) - ucontrol->value.integer.value[0] = 1; - else - ucontrol->value.integer.value[0] = 0; - - return 0; -} - -static int eqmode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int regpwr2, regpwr3; - unsigned int reg_eq; - - if (ucontrol->value.integer.value[0] != 0 - && ucontrol->value.integer.value[0] != 1) - return -EINVAL; - - reg_eq = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF); - switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) { - case 0: - if (!ucontrol->value.integer.value[0]) - return 0; - break; - case 1: - if (ucontrol->value.integer.value[0]) - return 0; - break; - } - - regpwr2 = snd_soc_read(codec, WM8983_POWER_MANAGEMENT_2); - regpwr3 = snd_soc_read(codec, WM8983_POWER_MANAGEMENT_3); - /* disable the DACs and ADCs */ - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_2, - WM8983_ADCENR_MASK | WM8983_ADCENL_MASK, 0); - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_3, - WM8983_DACENR_MASK | WM8983_DACENL_MASK, 0); - /* set the desired eqmode */ - snd_soc_update_bits(codec, WM8983_EQ1_LOW_SHELF, - WM8983_EQ3DMODE_MASK, - ucontrol->value.integer.value[0] - << WM8983_EQ3DMODE_SHIFT); - /* restore DAC/ADC configuration */ - snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, regpwr2); - snd_soc_write(codec, WM8983_POWER_MANAGEMENT_3, regpwr3); - return 0; -} - -static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg) -{ - if (reg > WM8983_MAX_REGISTER) - return 0; - - return wm8983_access_masks[reg].read != 0; -} - -static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - return snd_soc_update_bits(codec, WM8983_DAC_CONTROL, - WM8983_SOFTMUTE_MASK, - !!mute << WM8983_SOFTMUTE_SHIFT); -} - -static int wm8983_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - u16 format, master, bcp, lrp; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - format = 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - format = 0x0; - break; - case SND_SOC_DAIFMT_LEFT_J: - format = 0x1; - break; - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - format = 0x3; - break; - default: - dev_err(dai->dev, "Unknown dai format\n"); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, - WM8983_FMT_MASK, format << WM8983_FMT_SHIFT); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - master = 1; - break; - case SND_SOC_DAIFMT_CBS_CFS: - master = 0; - break; - default: - dev_err(dai->dev, "Unknown master/slave configuration\n"); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, - WM8983_MS_MASK, master << WM8983_MS_SHIFT); - - /* FIXME: We don't currently support DSP A/B modes */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - dev_err(dai->dev, "DSP A/B modes are not supported\n"); - return -EINVAL; - default: - break; - } - - bcp = lrp = 0; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - bcp = lrp = 1; - break; - case SND_SOC_DAIFMT_IB_NF: - bcp = 1; - break; - case SND_SOC_DAIFMT_NB_IF: - lrp = 1; - break; - default: - dev_err(dai->dev, "Unknown polarity configuration\n"); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, - WM8983_LRCP_MASK, lrp << WM8983_LRCP_SHIFT); - snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, - WM8983_BCP_MASK, bcp << WM8983_BCP_SHIFT); - return 0; -} - -static int wm8983_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int i; - struct snd_soc_codec *codec = dai->codec; - struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); - u16 blen, srate_idx; - u32 tmp; - int srate_best; - int ret; - - ret = snd_soc_params_to_bclk(params); - if (ret < 0) { - dev_err(codec->dev, "Failed to convert params to bclk: %d\n", ret); - return ret; - } - - wm8983->bclk = ret; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - blen = 0x0; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - blen = 0x1; - break; - case SNDRV_PCM_FORMAT_S24_LE: - blen = 0x2; - break; - case SNDRV_PCM_FORMAT_S32_LE: - blen = 0x3; - break; - default: - dev_err(dai->dev, "Unsupported word length %u\n", - params_format(params)); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8983_AUDIO_INTERFACE, - WM8983_WL_MASK, blen << WM8983_WL_SHIFT); - - /* - * match to the nearest possible sample rate and rely - * on the array index to configure the SR register - */ - srate_idx = 0; - srate_best = abs(srates[0] - params_rate(params)); - for (i = 1; i < ARRAY_SIZE(srates); ++i) { - if (abs(srates[i] - params_rate(params)) >= srate_best) - continue; - srate_idx = i; - srate_best = abs(srates[i] - params_rate(params)); - } - - dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]); - snd_soc_update_bits(codec, WM8983_ADDITIONAL_CONTROL, - WM8983_SR_MASK, srate_idx << WM8983_SR_SHIFT); - - dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8983->bclk); - dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8983->sysclk); - - for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) { - if (wm8983->sysclk / params_rate(params) - == fs_ratios[i].ratio) - break; - } - - if (i == ARRAY_SIZE(fs_ratios)) { - dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n", - wm8983->sysclk, params_rate(params)); - return -EINVAL; - } - - dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio); - snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, - WM8983_MCLKDIV_MASK, i << WM8983_MCLKDIV_SHIFT); - - /* select the appropriate bclk divider */ - tmp = (wm8983->sysclk / fs_ratios[i].div) * 10; - for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) { - if (wm8983->bclk == tmp / bclk_divs[i]) - break; - } - - if (i == ARRAY_SIZE(bclk_divs)) { - dev_err(dai->dev, "No matching BCLK divider found\n"); - return -EINVAL; - } - - dev_dbg(dai->dev, "BCLK div = %d\n", i); - snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, - WM8983_BCLKDIV_MASK, i << WM8983_BCLKDIV_SHIFT); - - return 0; -} - -struct pll_div { - u32 div2:1; - u32 n:4; - u32 k:24; -}; - -#define FIXED_PLL_SIZE ((1ULL << 24) * 10) -static int pll_factors(struct pll_div *pll_div, unsigned int target, - unsigned int source) -{ - u64 Kpart; - unsigned long int K, Ndiv, Nmod; - - pll_div->div2 = 0; - Ndiv = target / source; - if (Ndiv < 6) { - source >>= 1; - pll_div->div2 = 1; - Ndiv = target / source; - } - - if (Ndiv < 6 || Ndiv > 12) { - printk(KERN_ERR "%s: WM8983 N value is not within" - " the recommended range: %lu\n", __func__, Ndiv); - return -EINVAL; - } - pll_div->n = Ndiv; - - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (u64)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xffffffff; - if ((K % 10) >= 5) - K += 5; - K /= 10; - pll_div->k = K; - return 0; -} - -static int wm8983_set_pll(struct snd_soc_dai *dai, int pll_id, - int source, unsigned int freq_in, - unsigned int freq_out) -{ - int ret; - struct snd_soc_codec *codec; - struct pll_div pll_div; - - codec = dai->codec; - if (freq_in && freq_out) { - ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in); - if (ret) - return ret; - } - - /* disable the PLL before re-programming it */ - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, - WM8983_PLLEN_MASK, 0); - - if (!freq_in || !freq_out) - return 0; - - /* set PLLN and PRESCALE */ - snd_soc_write(codec, WM8983_PLL_N, - (pll_div.div2 << WM8983_PLL_PRESCALE_SHIFT) - | pll_div.n); - /* set PLLK */ - snd_soc_write(codec, WM8983_PLL_K_3, pll_div.k & 0x1ff); - snd_soc_write(codec, WM8983_PLL_K_2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8983_PLL_K_1, (pll_div.k >> 18)); - /* enable the PLL */ - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, - WM8983_PLLEN_MASK, WM8983_PLLEN); - return 0; -} - -static int wm8983_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case WM8983_CLKSRC_MCLK: - snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, - WM8983_CLKSEL_MASK, 0); - break; - case WM8983_CLKSRC_PLL: - snd_soc_update_bits(codec, WM8983_CLOCK_GEN_CONTROL, - WM8983_CLKSEL_MASK, WM8983_CLKSEL); - break; - default: - dev_err(dai->dev, "Unknown clock source: %d\n", clk_id); - return -EINVAL; - } - - wm8983->sysclk = freq; - return 0; -} - -static int wm8983_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - /* VMID at 100k */ - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, - WM8983_VMIDSEL_MASK, - 1 << WM8983_VMIDSEL_SHIFT); - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to sync cache: %d\n", ret); - return ret; - } - /* enable anti-pop features */ - snd_soc_update_bits(codec, WM8983_OUT4_TO_ADC, - WM8983_POBCTRL_MASK | WM8983_DELEN_MASK, - WM8983_POBCTRL | WM8983_DELEN); - /* enable thermal shutdown */ - snd_soc_update_bits(codec, WM8983_OUTPUT_CTRL, - WM8983_TSDEN_MASK, WM8983_TSDEN); - /* enable BIASEN */ - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, - WM8983_BIASEN_MASK, WM8983_BIASEN); - /* VMID at 100k */ - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, - WM8983_VMIDSEL_MASK, - 1 << WM8983_VMIDSEL_SHIFT); - msleep(250); - /* disable anti-pop features */ - snd_soc_update_bits(codec, WM8983_OUT4_TO_ADC, - WM8983_POBCTRL_MASK | - WM8983_DELEN_MASK, 0); - } - - /* VMID at 500k */ - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, - WM8983_VMIDSEL_MASK, - 2 << WM8983_VMIDSEL_SHIFT); - break; - case SND_SOC_BIAS_OFF: - /* disable thermal shutdown */ - snd_soc_update_bits(codec, WM8983_OUTPUT_CTRL, - WM8983_TSDEN_MASK, 0); - /* disable VMIDSEL and BIASEN */ - snd_soc_update_bits(codec, WM8983_POWER_MANAGEMENT_1, - WM8983_VMIDSEL_MASK | WM8983_BIASEN_MASK, - 0); - /* wait for VMID to discharge */ - msleep(100); - snd_soc_write(codec, WM8983_POWER_MANAGEMENT_1, 0); - snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, 0); - snd_soc_write(codec, WM8983_POWER_MANAGEMENT_3, 0); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#ifdef CONFIG_PM -static int wm8983_suspend(struct snd_soc_codec *codec) -{ - wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8983_resume(struct snd_soc_codec *codec) -{ - wm8983_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define wm8983_suspend NULL -#define wm8983_resume NULL -#endif - -static int wm8983_remove(struct snd_soc_codec *codec) -{ - wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8983_probe(struct snd_soc_codec *codec) -{ - int ret; - struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); - int i; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - - ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - return ret; - } - - /* set the vol/gain update bits */ - for (i = 0; i < ARRAY_SIZE(vol_update_regs); ++i) - snd_soc_update_bits(codec, vol_update_regs[i], - 0x100, 0x100); - - /* mute all outputs and set PGAs to minimum gain */ - for (i = WM8983_LOUT1_HP_VOLUME_CTRL; - i <= WM8983_OUT4_MONO_MIX_CTRL; ++i) - snd_soc_update_bits(codec, i, 0x40, 0x40); - - /* enable soft mute */ - snd_soc_update_bits(codec, WM8983_DAC_CONTROL, - WM8983_SOFTMUTE_MASK, - WM8983_SOFTMUTE); - - /* enable BIASCUT */ - snd_soc_update_bits(codec, WM8983_BIAS_CTRL, - WM8983_BIASCUT, WM8983_BIASCUT); - return 0; -} - -static const struct snd_soc_dai_ops wm8983_dai_ops = { - .digital_mute = wm8983_dac_mute, - .hw_params = wm8983_hw_params, - .set_fmt = wm8983_set_fmt, - .set_sysclk = wm8983_set_sysclk, - .set_pll = wm8983_set_pll -}; - -#define WM8983_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_driver wm8983_dai = { - .name = "wm8983-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8983_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8983_FORMATS, - }, - .ops = &wm8983_dai_ops, - .symmetric_rates = 1 -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { - .probe = wm8983_probe, - .remove = wm8983_remove, - .suspend = wm8983_suspend, - .resume = wm8983_resume, - .set_bias_level = wm8983_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8983_reg_defs), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8983_reg_defs, - .controls = wm8983_snd_controls, - .num_controls = ARRAY_SIZE(wm8983_snd_controls), - .dapm_widgets = wm8983_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), - .dapm_routes = wm8983_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), - .readable_register = wm8983_readable -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8983_spi_probe(struct spi_device *spi) -{ - struct wm8983_priv *wm8983; - int ret; - - wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); - if (!wm8983) - return -ENOMEM; - - wm8983->control_type = SND_SOC_SPI; - spi_set_drvdata(spi, wm8983); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8983, &wm8983_dai, 1); - if (ret < 0) - kfree(wm8983); - return ret; -} - -static int __devexit wm8983_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); - return 0; -} - -static struct spi_driver wm8983_spi_driver = { - .driver = { - .name = "wm8983", - .owner = THIS_MODULE, - }, - .probe = wm8983_spi_probe, - .remove = __devexit_p(wm8983_spi_remove) -}; -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8983_priv *wm8983; - int ret; - - wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); - if (!wm8983) - return -ENOMEM; - - wm8983->control_type = SND_SOC_I2C; - i2c_set_clientdata(i2c, wm8983); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8983, &wm8983_dai, 1); - if (ret < 0) - kfree(wm8983); - return ret; -} - -static __devexit int wm8983_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8983_i2c_id[] = { - { "wm8983", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id); - -static struct i2c_driver wm8983_i2c_driver = { - .driver = { - .name = "wm8983", - .owner = THIS_MODULE, - }, - .probe = wm8983_i2c_probe, - .remove = __devexit_p(wm8983_i2c_remove), - .id_table = wm8983_i2c_id -}; -#endif - -static int __init wm8983_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8983_i2c_driver); - if (ret) { - printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8983_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8983 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8983_modinit); - -static void __exit wm8983_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8983_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8983_spi_driver); -#endif -} -module_exit(wm8983_exit); - -MODULE_DESCRIPTION("ASoC WM8983 driver"); -MODULE_AUTHOR("Dimitris Papastamos "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8983.h b/ANDROID_3.4.5/sound/soc/codecs/wm8983.h deleted file mode 100644 index 71ee619c..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8983.h +++ /dev/null @@ -1,1029 +0,0 @@ -/* - * wm8983.h -- WM8983 ALSA SoC Audio driver - * - * Copyright 2011 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8983_H -#define _WM8983_H - -/* - * Register values. - */ -#define WM8983_SOFTWARE_RESET 0x00 -#define WM8983_POWER_MANAGEMENT_1 0x01 -#define WM8983_POWER_MANAGEMENT_2 0x02 -#define WM8983_POWER_MANAGEMENT_3 0x03 -#define WM8983_AUDIO_INTERFACE 0x04 -#define WM8983_COMPANDING_CONTROL 0x05 -#define WM8983_CLOCK_GEN_CONTROL 0x06 -#define WM8983_ADDITIONAL_CONTROL 0x07 -#define WM8983_GPIO_CONTROL 0x08 -#define WM8983_JACK_DETECT_CONTROL_1 0x09 -#define WM8983_DAC_CONTROL 0x0A -#define WM8983_LEFT_DAC_DIGITAL_VOL 0x0B -#define WM8983_RIGHT_DAC_DIGITAL_VOL 0x0C -#define WM8983_JACK_DETECT_CONTROL_2 0x0D -#define WM8983_ADC_CONTROL 0x0E -#define WM8983_LEFT_ADC_DIGITAL_VOL 0x0F -#define WM8983_RIGHT_ADC_DIGITAL_VOL 0x10 -#define WM8983_EQ1_LOW_SHELF 0x12 -#define WM8983_EQ2_PEAK_1 0x13 -#define WM8983_EQ3_PEAK_2 0x14 -#define WM8983_EQ4_PEAK_3 0x15 -#define WM8983_EQ5_HIGH_SHELF 0x16 -#define WM8983_DAC_LIMITER_1 0x18 -#define WM8983_DAC_LIMITER_2 0x19 -#define WM8983_NOTCH_FILTER_1 0x1B -#define WM8983_NOTCH_FILTER_2 0x1C -#define WM8983_NOTCH_FILTER_3 0x1D -#define WM8983_NOTCH_FILTER_4 0x1E -#define WM8983_ALC_CONTROL_1 0x20 -#define WM8983_ALC_CONTROL_2 0x21 -#define WM8983_ALC_CONTROL_3 0x22 -#define WM8983_NOISE_GATE 0x23 -#define WM8983_PLL_N 0x24 -#define WM8983_PLL_K_1 0x25 -#define WM8983_PLL_K_2 0x26 -#define WM8983_PLL_K_3 0x27 -#define WM8983_3D_CONTROL 0x29 -#define WM8983_OUT4_TO_ADC 0x2A -#define WM8983_BEEP_CONTROL 0x2B -#define WM8983_INPUT_CTRL 0x2C -#define WM8983_LEFT_INP_PGA_GAIN_CTRL 0x2D -#define WM8983_RIGHT_INP_PGA_GAIN_CTRL 0x2E -#define WM8983_LEFT_ADC_BOOST_CTRL 0x2F -#define WM8983_RIGHT_ADC_BOOST_CTRL 0x30 -#define WM8983_OUTPUT_CTRL 0x31 -#define WM8983_LEFT_MIXER_CTRL 0x32 -#define WM8983_RIGHT_MIXER_CTRL 0x33 -#define WM8983_LOUT1_HP_VOLUME_CTRL 0x34 -#define WM8983_ROUT1_HP_VOLUME_CTRL 0x35 -#define WM8983_LOUT2_SPK_VOLUME_CTRL 0x36 -#define WM8983_ROUT2_SPK_VOLUME_CTRL 0x37 -#define WM8983_OUT3_MIXER_CTRL 0x38 -#define WM8983_OUT4_MONO_MIX_CTRL 0x39 -#define WM8983_BIAS_CTRL 0x3D - -#define WM8983_REGISTER_COUNT 59 -#define WM8983_MAX_REGISTER 0x3F - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM8983_SOFTWARE_RESET_MASK 0x01FF /* SOFTWARE_RESET - [8:0] */ -#define WM8983_SOFTWARE_RESET_SHIFT 0 /* SOFTWARE_RESET - [8:0] */ -#define WM8983_SOFTWARE_RESET_WIDTH 9 /* SOFTWARE_RESET - [8:0] */ - -/* - * R1 (0x01) - Power management 1 - */ -#define WM8983_BUFDCOPEN 0x0100 /* BUFDCOPEN */ -#define WM8983_BUFDCOPEN_MASK 0x0100 /* BUFDCOPEN */ -#define WM8983_BUFDCOPEN_SHIFT 8 /* BUFDCOPEN */ -#define WM8983_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */ -#define WM8983_OUT4MIXEN 0x0080 /* OUT4MIXEN */ -#define WM8983_OUT4MIXEN_MASK 0x0080 /* OUT4MIXEN */ -#define WM8983_OUT4MIXEN_SHIFT 7 /* OUT4MIXEN */ -#define WM8983_OUT4MIXEN_WIDTH 1 /* OUT4MIXEN */ -#define WM8983_OUT3MIXEN 0x0040 /* OUT3MIXEN */ -#define WM8983_OUT3MIXEN_MASK 0x0040 /* OUT3MIXEN */ -#define WM8983_OUT3MIXEN_SHIFT 6 /* OUT3MIXEN */ -#define WM8983_OUT3MIXEN_WIDTH 1 /* OUT3MIXEN */ -#define WM8983_PLLEN 0x0020 /* PLLEN */ -#define WM8983_PLLEN_MASK 0x0020 /* PLLEN */ -#define WM8983_PLLEN_SHIFT 5 /* PLLEN */ -#define WM8983_PLLEN_WIDTH 1 /* PLLEN */ -#define WM8983_MICBEN 0x0010 /* MICBEN */ -#define WM8983_MICBEN_MASK 0x0010 /* MICBEN */ -#define WM8983_MICBEN_SHIFT 4 /* MICBEN */ -#define WM8983_MICBEN_WIDTH 1 /* MICBEN */ -#define WM8983_BIASEN 0x0008 /* BIASEN */ -#define WM8983_BIASEN_MASK 0x0008 /* BIASEN */ -#define WM8983_BIASEN_SHIFT 3 /* BIASEN */ -#define WM8983_BIASEN_WIDTH 1 /* BIASEN */ -#define WM8983_BUFIOEN 0x0004 /* BUFIOEN */ -#define WM8983_BUFIOEN_MASK 0x0004 /* BUFIOEN */ -#define WM8983_BUFIOEN_SHIFT 2 /* BUFIOEN */ -#define WM8983_BUFIOEN_WIDTH 1 /* BUFIOEN */ -#define WM8983_VMIDSEL_MASK 0x0003 /* VMIDSEL - [1:0] */ -#define WM8983_VMIDSEL_SHIFT 0 /* VMIDSEL - [1:0] */ -#define WM8983_VMIDSEL_WIDTH 2 /* VMIDSEL - [1:0] */ - -/* - * R2 (0x02) - Power management 2 - */ -#define WM8983_ROUT1EN 0x0100 /* ROUT1EN */ -#define WM8983_ROUT1EN_MASK 0x0100 /* ROUT1EN */ -#define WM8983_ROUT1EN_SHIFT 8 /* ROUT1EN */ -#define WM8983_ROUT1EN_WIDTH 1 /* ROUT1EN */ -#define WM8983_LOUT1EN 0x0080 /* LOUT1EN */ -#define WM8983_LOUT1EN_MASK 0x0080 /* LOUT1EN */ -#define WM8983_LOUT1EN_SHIFT 7 /* LOUT1EN */ -#define WM8983_LOUT1EN_WIDTH 1 /* LOUT1EN */ -#define WM8983_SLEEP 0x0040 /* SLEEP */ -#define WM8983_SLEEP_MASK 0x0040 /* SLEEP */ -#define WM8983_SLEEP_SHIFT 6 /* SLEEP */ -#define WM8983_SLEEP_WIDTH 1 /* SLEEP */ -#define WM8983_BOOSTENR 0x0020 /* BOOSTENR */ -#define WM8983_BOOSTENR_MASK 0x0020 /* BOOSTENR */ -#define WM8983_BOOSTENR_SHIFT 5 /* BOOSTENR */ -#define WM8983_BOOSTENR_WIDTH 1 /* BOOSTENR */ -#define WM8983_BOOSTENL 0x0010 /* BOOSTENL */ -#define WM8983_BOOSTENL_MASK 0x0010 /* BOOSTENL */ -#define WM8983_BOOSTENL_SHIFT 4 /* BOOSTENL */ -#define WM8983_BOOSTENL_WIDTH 1 /* BOOSTENL */ -#define WM8983_INPGAENR 0x0008 /* INPGAENR */ -#define WM8983_INPGAENR_MASK 0x0008 /* INPGAENR */ -#define WM8983_INPGAENR_SHIFT 3 /* INPGAENR */ -#define WM8983_INPGAENR_WIDTH 1 /* INPGAENR */ -#define WM8983_INPPGAENL 0x0004 /* INPPGAENL */ -#define WM8983_INPPGAENL_MASK 0x0004 /* INPPGAENL */ -#define WM8983_INPPGAENL_SHIFT 2 /* INPPGAENL */ -#define WM8983_INPPGAENL_WIDTH 1 /* INPPGAENL */ -#define WM8983_ADCENR 0x0002 /* ADCENR */ -#define WM8983_ADCENR_MASK 0x0002 /* ADCENR */ -#define WM8983_ADCENR_SHIFT 1 /* ADCENR */ -#define WM8983_ADCENR_WIDTH 1 /* ADCENR */ -#define WM8983_ADCENL 0x0001 /* ADCENL */ -#define WM8983_ADCENL_MASK 0x0001 /* ADCENL */ -#define WM8983_ADCENL_SHIFT 0 /* ADCENL */ -#define WM8983_ADCENL_WIDTH 1 /* ADCENL */ - -/* - * R3 (0x03) - Power management 3 - */ -#define WM8983_OUT4EN 0x0100 /* OUT4EN */ -#define WM8983_OUT4EN_MASK 0x0100 /* OUT4EN */ -#define WM8983_OUT4EN_SHIFT 8 /* OUT4EN */ -#define WM8983_OUT4EN_WIDTH 1 /* OUT4EN */ -#define WM8983_OUT3EN 0x0080 /* OUT3EN */ -#define WM8983_OUT3EN_MASK 0x0080 /* OUT3EN */ -#define WM8983_OUT3EN_SHIFT 7 /* OUT3EN */ -#define WM8983_OUT3EN_WIDTH 1 /* OUT3EN */ -#define WM8983_LOUT2EN 0x0040 /* LOUT2EN */ -#define WM8983_LOUT2EN_MASK 0x0040 /* LOUT2EN */ -#define WM8983_LOUT2EN_SHIFT 6 /* LOUT2EN */ -#define WM8983_LOUT2EN_WIDTH 1 /* LOUT2EN */ -#define WM8983_ROUT2EN 0x0020 /* ROUT2EN */ -#define WM8983_ROUT2EN_MASK 0x0020 /* ROUT2EN */ -#define WM8983_ROUT2EN_SHIFT 5 /* ROUT2EN */ -#define WM8983_ROUT2EN_WIDTH 1 /* ROUT2EN */ -#define WM8983_RMIXEN 0x0008 /* RMIXEN */ -#define WM8983_RMIXEN_MASK 0x0008 /* RMIXEN */ -#define WM8983_RMIXEN_SHIFT 3 /* RMIXEN */ -#define WM8983_RMIXEN_WIDTH 1 /* RMIXEN */ -#define WM8983_LMIXEN 0x0004 /* LMIXEN */ -#define WM8983_LMIXEN_MASK 0x0004 /* LMIXEN */ -#define WM8983_LMIXEN_SHIFT 2 /* LMIXEN */ -#define WM8983_LMIXEN_WIDTH 1 /* LMIXEN */ -#define WM8983_DACENR 0x0002 /* DACENR */ -#define WM8983_DACENR_MASK 0x0002 /* DACENR */ -#define WM8983_DACENR_SHIFT 1 /* DACENR */ -#define WM8983_DACENR_WIDTH 1 /* DACENR */ -#define WM8983_DACENL 0x0001 /* DACENL */ -#define WM8983_DACENL_MASK 0x0001 /* DACENL */ -#define WM8983_DACENL_SHIFT 0 /* DACENL */ -#define WM8983_DACENL_WIDTH 1 /* DACENL */ - -/* - * R4 (0x04) - Audio Interface - */ -#define WM8983_BCP 0x0100 /* BCP */ -#define WM8983_BCP_MASK 0x0100 /* BCP */ -#define WM8983_BCP_SHIFT 8 /* BCP */ -#define WM8983_BCP_WIDTH 1 /* BCP */ -#define WM8983_LRCP 0x0080 /* LRCP */ -#define WM8983_LRCP_MASK 0x0080 /* LRCP */ -#define WM8983_LRCP_SHIFT 7 /* LRCP */ -#define WM8983_LRCP_WIDTH 1 /* LRCP */ -#define WM8983_WL_MASK 0x0060 /* WL - [6:5] */ -#define WM8983_WL_SHIFT 5 /* WL - [6:5] */ -#define WM8983_WL_WIDTH 2 /* WL - [6:5] */ -#define WM8983_FMT_MASK 0x0018 /* FMT - [4:3] */ -#define WM8983_FMT_SHIFT 3 /* FMT - [4:3] */ -#define WM8983_FMT_WIDTH 2 /* FMT - [4:3] */ -#define WM8983_DLRSWAP 0x0004 /* DLRSWAP */ -#define WM8983_DLRSWAP_MASK 0x0004 /* DLRSWAP */ -#define WM8983_DLRSWAP_SHIFT 2 /* DLRSWAP */ -#define WM8983_DLRSWAP_WIDTH 1 /* DLRSWAP */ -#define WM8983_ALRSWAP 0x0002 /* ALRSWAP */ -#define WM8983_ALRSWAP_MASK 0x0002 /* ALRSWAP */ -#define WM8983_ALRSWAP_SHIFT 1 /* ALRSWAP */ -#define WM8983_ALRSWAP_WIDTH 1 /* ALRSWAP */ -#define WM8983_MONO 0x0001 /* MONO */ -#define WM8983_MONO_MASK 0x0001 /* MONO */ -#define WM8983_MONO_SHIFT 0 /* MONO */ -#define WM8983_MONO_WIDTH 1 /* MONO */ - -/* - * R5 (0x05) - Companding control - */ -#define WM8983_WL8 0x0020 /* WL8 */ -#define WM8983_WL8_MASK 0x0020 /* WL8 */ -#define WM8983_WL8_SHIFT 5 /* WL8 */ -#define WM8983_WL8_WIDTH 1 /* WL8 */ -#define WM8983_DAC_COMP_MASK 0x0018 /* DAC_COMP - [4:3] */ -#define WM8983_DAC_COMP_SHIFT 3 /* DAC_COMP - [4:3] */ -#define WM8983_DAC_COMP_WIDTH 2 /* DAC_COMP - [4:3] */ -#define WM8983_ADC_COMP_MASK 0x0006 /* ADC_COMP - [2:1] */ -#define WM8983_ADC_COMP_SHIFT 1 /* ADC_COMP - [2:1] */ -#define WM8983_ADC_COMP_WIDTH 2 /* ADC_COMP - [2:1] */ -#define WM8983_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8983_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8983_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8983_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R6 (0x06) - Clock Gen control - */ -#define WM8983_CLKSEL 0x0100 /* CLKSEL */ -#define WM8983_CLKSEL_MASK 0x0100 /* CLKSEL */ -#define WM8983_CLKSEL_SHIFT 8 /* CLKSEL */ -#define WM8983_CLKSEL_WIDTH 1 /* CLKSEL */ -#define WM8983_MCLKDIV_MASK 0x00E0 /* MCLKDIV - [7:5] */ -#define WM8983_MCLKDIV_SHIFT 5 /* MCLKDIV - [7:5] */ -#define WM8983_MCLKDIV_WIDTH 3 /* MCLKDIV - [7:5] */ -#define WM8983_BCLKDIV_MASK 0x001C /* BCLKDIV - [4:2] */ -#define WM8983_BCLKDIV_SHIFT 2 /* BCLKDIV - [4:2] */ -#define WM8983_BCLKDIV_WIDTH 3 /* BCLKDIV - [4:2] */ -#define WM8983_MS 0x0001 /* MS */ -#define WM8983_MS_MASK 0x0001 /* MS */ -#define WM8983_MS_SHIFT 0 /* MS */ -#define WM8983_MS_WIDTH 1 /* MS */ - -/* - * R7 (0x07) - Additional control - */ -#define WM8983_SR_MASK 0x000E /* SR - [3:1] */ -#define WM8983_SR_SHIFT 1 /* SR - [3:1] */ -#define WM8983_SR_WIDTH 3 /* SR - [3:1] */ -#define WM8983_SLOWCLKEN 0x0001 /* SLOWCLKEN */ -#define WM8983_SLOWCLKEN_MASK 0x0001 /* SLOWCLKEN */ -#define WM8983_SLOWCLKEN_SHIFT 0 /* SLOWCLKEN */ -#define WM8983_SLOWCLKEN_WIDTH 1 /* SLOWCLKEN */ - -/* - * R8 (0x08) - GPIO Control - */ -#define WM8983_OPCLKDIV_MASK 0x0030 /* OPCLKDIV - [5:4] */ -#define WM8983_OPCLKDIV_SHIFT 4 /* OPCLKDIV - [5:4] */ -#define WM8983_OPCLKDIV_WIDTH 2 /* OPCLKDIV - [5:4] */ -#define WM8983_GPIO1POL 0x0008 /* GPIO1POL */ -#define WM8983_GPIO1POL_MASK 0x0008 /* GPIO1POL */ -#define WM8983_GPIO1POL_SHIFT 3 /* GPIO1POL */ -#define WM8983_GPIO1POL_WIDTH 1 /* GPIO1POL */ -#define WM8983_GPIO1SEL_MASK 0x0007 /* GPIO1SEL - [2:0] */ -#define WM8983_GPIO1SEL_SHIFT 0 /* GPIO1SEL - [2:0] */ -#define WM8983_GPIO1SEL_WIDTH 3 /* GPIO1SEL - [2:0] */ - -/* - * R9 (0x09) - Jack Detect Control 1 - */ -#define WM8983_JD_VMID1 0x0100 /* JD_VMID1 */ -#define WM8983_JD_VMID1_MASK 0x0100 /* JD_VMID1 */ -#define WM8983_JD_VMID1_SHIFT 8 /* JD_VMID1 */ -#define WM8983_JD_VMID1_WIDTH 1 /* JD_VMID1 */ -#define WM8983_JD_VMID0 0x0080 /* JD_VMID0 */ -#define WM8983_JD_VMID0_MASK 0x0080 /* JD_VMID0 */ -#define WM8983_JD_VMID0_SHIFT 7 /* JD_VMID0 */ -#define WM8983_JD_VMID0_WIDTH 1 /* JD_VMID0 */ -#define WM8983_JD_EN 0x0040 /* JD_EN */ -#define WM8983_JD_EN_MASK 0x0040 /* JD_EN */ -#define WM8983_JD_EN_SHIFT 6 /* JD_EN */ -#define WM8983_JD_EN_WIDTH 1 /* JD_EN */ -#define WM8983_JD_SEL_MASK 0x0030 /* JD_SEL - [5:4] */ -#define WM8983_JD_SEL_SHIFT 4 /* JD_SEL - [5:4] */ -#define WM8983_JD_SEL_WIDTH 2 /* JD_SEL - [5:4] */ - -/* - * R10 (0x0A) - DAC Control - */ -#define WM8983_SOFTMUTE 0x0040 /* SOFTMUTE */ -#define WM8983_SOFTMUTE_MASK 0x0040 /* SOFTMUTE */ -#define WM8983_SOFTMUTE_SHIFT 6 /* SOFTMUTE */ -#define WM8983_SOFTMUTE_WIDTH 1 /* SOFTMUTE */ -#define WM8983_DACOSR128 0x0008 /* DACOSR128 */ -#define WM8983_DACOSR128_MASK 0x0008 /* DACOSR128 */ -#define WM8983_DACOSR128_SHIFT 3 /* DACOSR128 */ -#define WM8983_DACOSR128_WIDTH 1 /* DACOSR128 */ -#define WM8983_AMUTE 0x0004 /* AMUTE */ -#define WM8983_AMUTE_MASK 0x0004 /* AMUTE */ -#define WM8983_AMUTE_SHIFT 2 /* AMUTE */ -#define WM8983_AMUTE_WIDTH 1 /* AMUTE */ -#define WM8983_DACRPOL 0x0002 /* DACRPOL */ -#define WM8983_DACRPOL_MASK 0x0002 /* DACRPOL */ -#define WM8983_DACRPOL_SHIFT 1 /* DACRPOL */ -#define WM8983_DACRPOL_WIDTH 1 /* DACRPOL */ -#define WM8983_DACLPOL 0x0001 /* DACLPOL */ -#define WM8983_DACLPOL_MASK 0x0001 /* DACLPOL */ -#define WM8983_DACLPOL_SHIFT 0 /* DACLPOL */ -#define WM8983_DACLPOL_WIDTH 1 /* DACLPOL */ - -/* - * R11 (0x0B) - Left DAC digital Vol - */ -#define WM8983_DACVU 0x0100 /* DACVU */ -#define WM8983_DACVU_MASK 0x0100 /* DACVU */ -#define WM8983_DACVU_SHIFT 8 /* DACVU */ -#define WM8983_DACVU_WIDTH 1 /* DACVU */ -#define WM8983_DACLVOL_MASK 0x00FF /* DACLVOL - [7:0] */ -#define WM8983_DACLVOL_SHIFT 0 /* DACLVOL - [7:0] */ -#define WM8983_DACLVOL_WIDTH 8 /* DACLVOL - [7:0] */ - -/* - * R12 (0x0C) - Right DAC digital vol - */ -#define WM8983_DACVU 0x0100 /* DACVU */ -#define WM8983_DACVU_MASK 0x0100 /* DACVU */ -#define WM8983_DACVU_SHIFT 8 /* DACVU */ -#define WM8983_DACVU_WIDTH 1 /* DACVU */ -#define WM8983_DACRVOL_MASK 0x00FF /* DACRVOL - [7:0] */ -#define WM8983_DACRVOL_SHIFT 0 /* DACRVOL - [7:0] */ -#define WM8983_DACRVOL_WIDTH 8 /* DACRVOL - [7:0] */ - -/* - * R13 (0x0D) - Jack Detect Control 2 - */ -#define WM8983_JD_EN1_MASK 0x00F0 /* JD_EN1 - [7:4] */ -#define WM8983_JD_EN1_SHIFT 4 /* JD_EN1 - [7:4] */ -#define WM8983_JD_EN1_WIDTH 4 /* JD_EN1 - [7:4] */ -#define WM8983_JD_EN0_MASK 0x000F /* JD_EN0 - [3:0] */ -#define WM8983_JD_EN0_SHIFT 0 /* JD_EN0 - [3:0] */ -#define WM8983_JD_EN0_WIDTH 4 /* JD_EN0 - [3:0] */ - -/* - * R14 (0x0E) - ADC Control - */ -#define WM8983_HPFEN 0x0100 /* HPFEN */ -#define WM8983_HPFEN_MASK 0x0100 /* HPFEN */ -#define WM8983_HPFEN_SHIFT 8 /* HPFEN */ -#define WM8983_HPFEN_WIDTH 1 /* HPFEN */ -#define WM8983_HPFAPP 0x0080 /* HPFAPP */ -#define WM8983_HPFAPP_MASK 0x0080 /* HPFAPP */ -#define WM8983_HPFAPP_SHIFT 7 /* HPFAPP */ -#define WM8983_HPFAPP_WIDTH 1 /* HPFAPP */ -#define WM8983_HPFCUT_MASK 0x0070 /* HPFCUT - [6:4] */ -#define WM8983_HPFCUT_SHIFT 4 /* HPFCUT - [6:4] */ -#define WM8983_HPFCUT_WIDTH 3 /* HPFCUT - [6:4] */ -#define WM8983_ADCOSR128 0x0008 /* ADCOSR128 */ -#define WM8983_ADCOSR128_MASK 0x0008 /* ADCOSR128 */ -#define WM8983_ADCOSR128_SHIFT 3 /* ADCOSR128 */ -#define WM8983_ADCOSR128_WIDTH 1 /* ADCOSR128 */ -#define WM8983_ADCRPOL 0x0002 /* ADCRPOL */ -#define WM8983_ADCRPOL_MASK 0x0002 /* ADCRPOL */ -#define WM8983_ADCRPOL_SHIFT 1 /* ADCRPOL */ -#define WM8983_ADCRPOL_WIDTH 1 /* ADCRPOL */ -#define WM8983_ADCLPOL 0x0001 /* ADCLPOL */ -#define WM8983_ADCLPOL_MASK 0x0001 /* ADCLPOL */ -#define WM8983_ADCLPOL_SHIFT 0 /* ADCLPOL */ -#define WM8983_ADCLPOL_WIDTH 1 /* ADCLPOL */ - -/* - * R15 (0x0F) - Left ADC Digital Vol - */ -#define WM8983_ADCVU 0x0100 /* ADCVU */ -#define WM8983_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8983_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8983_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8983_ADCLVOL_MASK 0x00FF /* ADCLVOL - [7:0] */ -#define WM8983_ADCLVOL_SHIFT 0 /* ADCLVOL - [7:0] */ -#define WM8983_ADCLVOL_WIDTH 8 /* ADCLVOL - [7:0] */ - -/* - * R16 (0x10) - Right ADC Digital Vol - */ -#define WM8983_ADCVU 0x0100 /* ADCVU */ -#define WM8983_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8983_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8983_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8983_ADCRVOL_MASK 0x00FF /* ADCRVOL - [7:0] */ -#define WM8983_ADCRVOL_SHIFT 0 /* ADCRVOL - [7:0] */ -#define WM8983_ADCRVOL_WIDTH 8 /* ADCRVOL - [7:0] */ - -/* - * R18 (0x12) - EQ1 - low shelf - */ -#define WM8983_EQ3DMODE 0x0100 /* EQ3DMODE */ -#define WM8983_EQ3DMODE_MASK 0x0100 /* EQ3DMODE */ -#define WM8983_EQ3DMODE_SHIFT 8 /* EQ3DMODE */ -#define WM8983_EQ3DMODE_WIDTH 1 /* EQ3DMODE */ -#define WM8983_EQ1C_MASK 0x0060 /* EQ1C - [6:5] */ -#define WM8983_EQ1C_SHIFT 5 /* EQ1C - [6:5] */ -#define WM8983_EQ1C_WIDTH 2 /* EQ1C - [6:5] */ -#define WM8983_EQ1G_MASK 0x001F /* EQ1G - [4:0] */ -#define WM8983_EQ1G_SHIFT 0 /* EQ1G - [4:0] */ -#define WM8983_EQ1G_WIDTH 5 /* EQ1G - [4:0] */ - -/* - * R19 (0x13) - EQ2 - peak 1 - */ -#define WM8983_EQ2BW 0x0100 /* EQ2BW */ -#define WM8983_EQ2BW_MASK 0x0100 /* EQ2BW */ -#define WM8983_EQ2BW_SHIFT 8 /* EQ2BW */ -#define WM8983_EQ2BW_WIDTH 1 /* EQ2BW */ -#define WM8983_EQ2C_MASK 0x0060 /* EQ2C - [6:5] */ -#define WM8983_EQ2C_SHIFT 5 /* EQ2C - [6:5] */ -#define WM8983_EQ2C_WIDTH 2 /* EQ2C - [6:5] */ -#define WM8983_EQ2G_MASK 0x001F /* EQ2G - [4:0] */ -#define WM8983_EQ2G_SHIFT 0 /* EQ2G - [4:0] */ -#define WM8983_EQ2G_WIDTH 5 /* EQ2G - [4:0] */ - -/* - * R20 (0x14) - EQ3 - peak 2 - */ -#define WM8983_EQ3BW 0x0100 /* EQ3BW */ -#define WM8983_EQ3BW_MASK 0x0100 /* EQ3BW */ -#define WM8983_EQ3BW_SHIFT 8 /* EQ3BW */ -#define WM8983_EQ3BW_WIDTH 1 /* EQ3BW */ -#define WM8983_EQ3C_MASK 0x0060 /* EQ3C - [6:5] */ -#define WM8983_EQ3C_SHIFT 5 /* EQ3C - [6:5] */ -#define WM8983_EQ3C_WIDTH 2 /* EQ3C - [6:5] */ -#define WM8983_EQ3G_MASK 0x001F /* EQ3G - [4:0] */ -#define WM8983_EQ3G_SHIFT 0 /* EQ3G - [4:0] */ -#define WM8983_EQ3G_WIDTH 5 /* EQ3G - [4:0] */ - -/* - * R21 (0x15) - EQ4 - peak 3 - */ -#define WM8983_EQ4BW 0x0100 /* EQ4BW */ -#define WM8983_EQ4BW_MASK 0x0100 /* EQ4BW */ -#define WM8983_EQ4BW_SHIFT 8 /* EQ4BW */ -#define WM8983_EQ4BW_WIDTH 1 /* EQ4BW */ -#define WM8983_EQ4C_MASK 0x0060 /* EQ4C - [6:5] */ -#define WM8983_EQ4C_SHIFT 5 /* EQ4C - [6:5] */ -#define WM8983_EQ4C_WIDTH 2 /* EQ4C - [6:5] */ -#define WM8983_EQ4G_MASK 0x001F /* EQ4G - [4:0] */ -#define WM8983_EQ4G_SHIFT 0 /* EQ4G - [4:0] */ -#define WM8983_EQ4G_WIDTH 5 /* EQ4G - [4:0] */ - -/* - * R22 (0x16) - EQ5 - high shelf - */ -#define WM8983_EQ5C_MASK 0x0060 /* EQ5C - [6:5] */ -#define WM8983_EQ5C_SHIFT 5 /* EQ5C - [6:5] */ -#define WM8983_EQ5C_WIDTH 2 /* EQ5C - [6:5] */ -#define WM8983_EQ5G_MASK 0x001F /* EQ5G - [4:0] */ -#define WM8983_EQ5G_SHIFT 0 /* EQ5G - [4:0] */ -#define WM8983_EQ5G_WIDTH 5 /* EQ5G - [4:0] */ - -/* - * R24 (0x18) - DAC Limiter 1 - */ -#define WM8983_LIMEN 0x0100 /* LIMEN */ -#define WM8983_LIMEN_MASK 0x0100 /* LIMEN */ -#define WM8983_LIMEN_SHIFT 8 /* LIMEN */ -#define WM8983_LIMEN_WIDTH 1 /* LIMEN */ -#define WM8983_LIMDCY_MASK 0x00F0 /* LIMDCY - [7:4] */ -#define WM8983_LIMDCY_SHIFT 4 /* LIMDCY - [7:4] */ -#define WM8983_LIMDCY_WIDTH 4 /* LIMDCY - [7:4] */ -#define WM8983_LIMATK_MASK 0x000F /* LIMATK - [3:0] */ -#define WM8983_LIMATK_SHIFT 0 /* LIMATK - [3:0] */ -#define WM8983_LIMATK_WIDTH 4 /* LIMATK - [3:0] */ - -/* - * R25 (0x19) - DAC Limiter 2 - */ -#define WM8983_LIMLVL_MASK 0x0070 /* LIMLVL - [6:4] */ -#define WM8983_LIMLVL_SHIFT 4 /* LIMLVL - [6:4] */ -#define WM8983_LIMLVL_WIDTH 3 /* LIMLVL - [6:4] */ -#define WM8983_LIMBOOST_MASK 0x000F /* LIMBOOST - [3:0] */ -#define WM8983_LIMBOOST_SHIFT 0 /* LIMBOOST - [3:0] */ -#define WM8983_LIMBOOST_WIDTH 4 /* LIMBOOST - [3:0] */ - -/* - * R27 (0x1B) - Notch Filter 1 - */ -#define WM8983_NFU 0x0100 /* NFU */ -#define WM8983_NFU_MASK 0x0100 /* NFU */ -#define WM8983_NFU_SHIFT 8 /* NFU */ -#define WM8983_NFU_WIDTH 1 /* NFU */ -#define WM8983_NFEN 0x0080 /* NFEN */ -#define WM8983_NFEN_MASK 0x0080 /* NFEN */ -#define WM8983_NFEN_SHIFT 7 /* NFEN */ -#define WM8983_NFEN_WIDTH 1 /* NFEN */ -#define WM8983_NFA0_13_7_MASK 0x007F /* NFA0(13:7) - [6:0] */ -#define WM8983_NFA0_13_7_SHIFT 0 /* NFA0(13:7) - [6:0] */ -#define WM8983_NFA0_13_7_WIDTH 7 /* NFA0(13:7) - [6:0] */ - -/* - * R28 (0x1C) - Notch Filter 2 - */ -#define WM8983_NFU 0x0100 /* NFU */ -#define WM8983_NFU_MASK 0x0100 /* NFU */ -#define WM8983_NFU_SHIFT 8 /* NFU */ -#define WM8983_NFU_WIDTH 1 /* NFU */ -#define WM8983_NFA0_6_0_MASK 0x007F /* NFA0(6:0) - [6:0] */ -#define WM8983_NFA0_6_0_SHIFT 0 /* NFA0(6:0) - [6:0] */ -#define WM8983_NFA0_6_0_WIDTH 7 /* NFA0(6:0) - [6:0] */ - -/* - * R29 (0x1D) - Notch Filter 3 - */ -#define WM8983_NFU 0x0100 /* NFU */ -#define WM8983_NFU_MASK 0x0100 /* NFU */ -#define WM8983_NFU_SHIFT 8 /* NFU */ -#define WM8983_NFU_WIDTH 1 /* NFU */ -#define WM8983_NFA1_13_7_MASK 0x007F /* NFA1(13:7) - [6:0] */ -#define WM8983_NFA1_13_7_SHIFT 0 /* NFA1(13:7) - [6:0] */ -#define WM8983_NFA1_13_7_WIDTH 7 /* NFA1(13:7) - [6:0] */ - -/* - * R30 (0x1E) - Notch Filter 4 - */ -#define WM8983_NFU 0x0100 /* NFU */ -#define WM8983_NFU_MASK 0x0100 /* NFU */ -#define WM8983_NFU_SHIFT 8 /* NFU */ -#define WM8983_NFU_WIDTH 1 /* NFU */ -#define WM8983_NFA1_6_0_MASK 0x007F /* NFA1(6:0) - [6:0] */ -#define WM8983_NFA1_6_0_SHIFT 0 /* NFA1(6:0) - [6:0] */ -#define WM8983_NFA1_6_0_WIDTH 7 /* NFA1(6:0) - [6:0] */ - -/* - * R32 (0x20) - ALC control 1 - */ -#define WM8983_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */ -#define WM8983_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */ -#define WM8983_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */ -#define WM8983_ALCMAX_MASK 0x0038 /* ALCMAX - [5:3] */ -#define WM8983_ALCMAX_SHIFT 3 /* ALCMAX - [5:3] */ -#define WM8983_ALCMAX_WIDTH 3 /* ALCMAX - [5:3] */ -#define WM8983_ALCMIN_MASK 0x0007 /* ALCMIN - [2:0] */ -#define WM8983_ALCMIN_SHIFT 0 /* ALCMIN - [2:0] */ -#define WM8983_ALCMIN_WIDTH 3 /* ALCMIN - [2:0] */ - -/* - * R33 (0x21) - ALC control 2 - */ -#define WM8983_ALCHLD_MASK 0x00F0 /* ALCHLD - [7:4] */ -#define WM8983_ALCHLD_SHIFT 4 /* ALCHLD - [7:4] */ -#define WM8983_ALCHLD_WIDTH 4 /* ALCHLD - [7:4] */ -#define WM8983_ALCLVL_MASK 0x000F /* ALCLVL - [3:0] */ -#define WM8983_ALCLVL_SHIFT 0 /* ALCLVL - [3:0] */ -#define WM8983_ALCLVL_WIDTH 4 /* ALCLVL - [3:0] */ - -/* - * R34 (0x22) - ALC control 3 - */ -#define WM8983_ALCMODE 0x0100 /* ALCMODE */ -#define WM8983_ALCMODE_MASK 0x0100 /* ALCMODE */ -#define WM8983_ALCMODE_SHIFT 8 /* ALCMODE */ -#define WM8983_ALCMODE_WIDTH 1 /* ALCMODE */ -#define WM8983_ALCDCY_MASK 0x00F0 /* ALCDCY - [7:4] */ -#define WM8983_ALCDCY_SHIFT 4 /* ALCDCY - [7:4] */ -#define WM8983_ALCDCY_WIDTH 4 /* ALCDCY - [7:4] */ -#define WM8983_ALCATK_MASK 0x000F /* ALCATK - [3:0] */ -#define WM8983_ALCATK_SHIFT 0 /* ALCATK - [3:0] */ -#define WM8983_ALCATK_WIDTH 4 /* ALCATK - [3:0] */ - -/* - * R35 (0x23) - Noise Gate - */ -#define WM8983_NGEN 0x0008 /* NGEN */ -#define WM8983_NGEN_MASK 0x0008 /* NGEN */ -#define WM8983_NGEN_SHIFT 3 /* NGEN */ -#define WM8983_NGEN_WIDTH 1 /* NGEN */ -#define WM8983_NGTH_MASK 0x0007 /* NGTH - [2:0] */ -#define WM8983_NGTH_SHIFT 0 /* NGTH - [2:0] */ -#define WM8983_NGTH_WIDTH 3 /* NGTH - [2:0] */ - -/* - * R36 (0x24) - PLL N - */ -#define WM8983_PLL_PRESCALE 0x0010 /* PLL_PRESCALE */ -#define WM8983_PLL_PRESCALE_MASK 0x0010 /* PLL_PRESCALE */ -#define WM8983_PLL_PRESCALE_SHIFT 4 /* PLL_PRESCALE */ -#define WM8983_PLL_PRESCALE_WIDTH 1 /* PLL_PRESCALE */ -#define WM8983_PLLN_MASK 0x000F /* PLLN - [3:0] */ -#define WM8983_PLLN_SHIFT 0 /* PLLN - [3:0] */ -#define WM8983_PLLN_WIDTH 4 /* PLLN - [3:0] */ - -/* - * R37 (0x25) - PLL K 1 - */ -#define WM8983_PLLK_23_18_MASK 0x003F /* PLLK(23:18) - [5:0] */ -#define WM8983_PLLK_23_18_SHIFT 0 /* PLLK(23:18) - [5:0] */ -#define WM8983_PLLK_23_18_WIDTH 6 /* PLLK(23:18) - [5:0] */ - -/* - * R38 (0x26) - PLL K 2 - */ -#define WM8983_PLLK_17_9_MASK 0x01FF /* PLLK(17:9) - [8:0] */ -#define WM8983_PLLK_17_9_SHIFT 0 /* PLLK(17:9) - [8:0] */ -#define WM8983_PLLK_17_9_WIDTH 9 /* PLLK(17:9) - [8:0] */ - -/* - * R39 (0x27) - PLL K 3 - */ -#define WM8983_PLLK_8_0_MASK 0x01FF /* PLLK(8:0) - [8:0] */ -#define WM8983_PLLK_8_0_SHIFT 0 /* PLLK(8:0) - [8:0] */ -#define WM8983_PLLK_8_0_WIDTH 9 /* PLLK(8:0) - [8:0] */ - -/* - * R41 (0x29) - 3D control - */ -#define WM8983_DEPTH3D_MASK 0x000F /* DEPTH3D - [3:0] */ -#define WM8983_DEPTH3D_SHIFT 0 /* DEPTH3D - [3:0] */ -#define WM8983_DEPTH3D_WIDTH 4 /* DEPTH3D - [3:0] */ - -/* - * R42 (0x2A) - OUT4 to ADC - */ -#define WM8983_OUT4_2ADCVOL_MASK 0x01C0 /* OUT4_2ADCVOL - [8:6] */ -#define WM8983_OUT4_2ADCVOL_SHIFT 6 /* OUT4_2ADCVOL - [8:6] */ -#define WM8983_OUT4_2ADCVOL_WIDTH 3 /* OUT4_2ADCVOL - [8:6] */ -#define WM8983_OUT4_2LNR 0x0020 /* OUT4_2LNR */ -#define WM8983_OUT4_2LNR_MASK 0x0020 /* OUT4_2LNR */ -#define WM8983_OUT4_2LNR_SHIFT 5 /* OUT4_2LNR */ -#define WM8983_OUT4_2LNR_WIDTH 1 /* OUT4_2LNR */ -#define WM8983_POBCTRL 0x0004 /* POBCTRL */ -#define WM8983_POBCTRL_MASK 0x0004 /* POBCTRL */ -#define WM8983_POBCTRL_SHIFT 2 /* POBCTRL */ -#define WM8983_POBCTRL_WIDTH 1 /* POBCTRL */ -#define WM8983_DELEN 0x0002 /* DELEN */ -#define WM8983_DELEN_MASK 0x0002 /* DELEN */ -#define WM8983_DELEN_SHIFT 1 /* DELEN */ -#define WM8983_DELEN_WIDTH 1 /* DELEN */ -#define WM8983_OUT1DEL 0x0001 /* OUT1DEL */ -#define WM8983_OUT1DEL_MASK 0x0001 /* OUT1DEL */ -#define WM8983_OUT1DEL_SHIFT 0 /* OUT1DEL */ -#define WM8983_OUT1DEL_WIDTH 1 /* OUT1DEL */ - -/* - * R43 (0x2B) - Beep control - */ -#define WM8983_BYPL2RMIX 0x0100 /* BYPL2RMIX */ -#define WM8983_BYPL2RMIX_MASK 0x0100 /* BYPL2RMIX */ -#define WM8983_BYPL2RMIX_SHIFT 8 /* BYPL2RMIX */ -#define WM8983_BYPL2RMIX_WIDTH 1 /* BYPL2RMIX */ -#define WM8983_BYPR2LMIX 0x0080 /* BYPR2LMIX */ -#define WM8983_BYPR2LMIX_MASK 0x0080 /* BYPR2LMIX */ -#define WM8983_BYPR2LMIX_SHIFT 7 /* BYPR2LMIX */ -#define WM8983_BYPR2LMIX_WIDTH 1 /* BYPR2LMIX */ -#define WM8983_MUTERPGA2INV 0x0020 /* MUTERPGA2INV */ -#define WM8983_MUTERPGA2INV_MASK 0x0020 /* MUTERPGA2INV */ -#define WM8983_MUTERPGA2INV_SHIFT 5 /* MUTERPGA2INV */ -#define WM8983_MUTERPGA2INV_WIDTH 1 /* MUTERPGA2INV */ -#define WM8983_INVROUT2 0x0010 /* INVROUT2 */ -#define WM8983_INVROUT2_MASK 0x0010 /* INVROUT2 */ -#define WM8983_INVROUT2_SHIFT 4 /* INVROUT2 */ -#define WM8983_INVROUT2_WIDTH 1 /* INVROUT2 */ -#define WM8983_BEEPVOL_MASK 0x000E /* BEEPVOL - [3:1] */ -#define WM8983_BEEPVOL_SHIFT 1 /* BEEPVOL - [3:1] */ -#define WM8983_BEEPVOL_WIDTH 3 /* BEEPVOL - [3:1] */ -#define WM8983_BEEPEN 0x0001 /* BEEPEN */ -#define WM8983_BEEPEN_MASK 0x0001 /* BEEPEN */ -#define WM8983_BEEPEN_SHIFT 0 /* BEEPEN */ -#define WM8983_BEEPEN_WIDTH 1 /* BEEPEN */ - -/* - * R44 (0x2C) - Input ctrl - */ -#define WM8983_MBVSEL 0x0100 /* MBVSEL */ -#define WM8983_MBVSEL_MASK 0x0100 /* MBVSEL */ -#define WM8983_MBVSEL_SHIFT 8 /* MBVSEL */ -#define WM8983_MBVSEL_WIDTH 1 /* MBVSEL */ -#define WM8983_R2_2INPPGA 0x0040 /* R2_2INPPGA */ -#define WM8983_R2_2INPPGA_MASK 0x0040 /* R2_2INPPGA */ -#define WM8983_R2_2INPPGA_SHIFT 6 /* R2_2INPPGA */ -#define WM8983_R2_2INPPGA_WIDTH 1 /* R2_2INPPGA */ -#define WM8983_RIN2INPPGA 0x0020 /* RIN2INPPGA */ -#define WM8983_RIN2INPPGA_MASK 0x0020 /* RIN2INPPGA */ -#define WM8983_RIN2INPPGA_SHIFT 5 /* RIN2INPPGA */ -#define WM8983_RIN2INPPGA_WIDTH 1 /* RIN2INPPGA */ -#define WM8983_RIP2INPPGA 0x0010 /* RIP2INPPGA */ -#define WM8983_RIP2INPPGA_MASK 0x0010 /* RIP2INPPGA */ -#define WM8983_RIP2INPPGA_SHIFT 4 /* RIP2INPPGA */ -#define WM8983_RIP2INPPGA_WIDTH 1 /* RIP2INPPGA */ -#define WM8983_L2_2INPPGA 0x0004 /* L2_2INPPGA */ -#define WM8983_L2_2INPPGA_MASK 0x0004 /* L2_2INPPGA */ -#define WM8983_L2_2INPPGA_SHIFT 2 /* L2_2INPPGA */ -#define WM8983_L2_2INPPGA_WIDTH 1 /* L2_2INPPGA */ -#define WM8983_LIN2INPPGA 0x0002 /* LIN2INPPGA */ -#define WM8983_LIN2INPPGA_MASK 0x0002 /* LIN2INPPGA */ -#define WM8983_LIN2INPPGA_SHIFT 1 /* LIN2INPPGA */ -#define WM8983_LIN2INPPGA_WIDTH 1 /* LIN2INPPGA */ -#define WM8983_LIP2INPPGA 0x0001 /* LIP2INPPGA */ -#define WM8983_LIP2INPPGA_MASK 0x0001 /* LIP2INPPGA */ -#define WM8983_LIP2INPPGA_SHIFT 0 /* LIP2INPPGA */ -#define WM8983_LIP2INPPGA_WIDTH 1 /* LIP2INPPGA */ - -/* - * R45 (0x2D) - Left INP PGA gain ctrl - */ -#define WM8983_INPGAVU 0x0100 /* INPGAVU */ -#define WM8983_INPGAVU_MASK 0x0100 /* INPGAVU */ -#define WM8983_INPGAVU_SHIFT 8 /* INPGAVU */ -#define WM8983_INPGAVU_WIDTH 1 /* INPGAVU */ -#define WM8983_INPPGAZCL 0x0080 /* INPPGAZCL */ -#define WM8983_INPPGAZCL_MASK 0x0080 /* INPPGAZCL */ -#define WM8983_INPPGAZCL_SHIFT 7 /* INPPGAZCL */ -#define WM8983_INPPGAZCL_WIDTH 1 /* INPPGAZCL */ -#define WM8983_INPPGAMUTEL 0x0040 /* INPPGAMUTEL */ -#define WM8983_INPPGAMUTEL_MASK 0x0040 /* INPPGAMUTEL */ -#define WM8983_INPPGAMUTEL_SHIFT 6 /* INPPGAMUTEL */ -#define WM8983_INPPGAMUTEL_WIDTH 1 /* INPPGAMUTEL */ -#define WM8983_INPPGAVOLL_MASK 0x003F /* INPPGAVOLL - [5:0] */ -#define WM8983_INPPGAVOLL_SHIFT 0 /* INPPGAVOLL - [5:0] */ -#define WM8983_INPPGAVOLL_WIDTH 6 /* INPPGAVOLL - [5:0] */ - -/* - * R46 (0x2E) - Right INP PGA gain ctrl - */ -#define WM8983_INPGAVU 0x0100 /* INPGAVU */ -#define WM8983_INPGAVU_MASK 0x0100 /* INPGAVU */ -#define WM8983_INPGAVU_SHIFT 8 /* INPGAVU */ -#define WM8983_INPGAVU_WIDTH 1 /* INPGAVU */ -#define WM8983_INPPGAZCR 0x0080 /* INPPGAZCR */ -#define WM8983_INPPGAZCR_MASK 0x0080 /* INPPGAZCR */ -#define WM8983_INPPGAZCR_SHIFT 7 /* INPPGAZCR */ -#define WM8983_INPPGAZCR_WIDTH 1 /* INPPGAZCR */ -#define WM8983_INPPGAMUTER 0x0040 /* INPPGAMUTER */ -#define WM8983_INPPGAMUTER_MASK 0x0040 /* INPPGAMUTER */ -#define WM8983_INPPGAMUTER_SHIFT 6 /* INPPGAMUTER */ -#define WM8983_INPPGAMUTER_WIDTH 1 /* INPPGAMUTER */ -#define WM8983_INPPGAVOLR_MASK 0x003F /* INPPGAVOLR - [5:0] */ -#define WM8983_INPPGAVOLR_SHIFT 0 /* INPPGAVOLR - [5:0] */ -#define WM8983_INPPGAVOLR_WIDTH 6 /* INPPGAVOLR - [5:0] */ - -/* - * R47 (0x2F) - Left ADC BOOST ctrl - */ -#define WM8983_PGABOOSTL 0x0100 /* PGABOOSTL */ -#define WM8983_PGABOOSTL_MASK 0x0100 /* PGABOOSTL */ -#define WM8983_PGABOOSTL_SHIFT 8 /* PGABOOSTL */ -#define WM8983_PGABOOSTL_WIDTH 1 /* PGABOOSTL */ -#define WM8983_L2_2BOOSTVOL_MASK 0x0070 /* L2_2BOOSTVOL - [6:4] */ -#define WM8983_L2_2BOOSTVOL_SHIFT 4 /* L2_2BOOSTVOL - [6:4] */ -#define WM8983_L2_2BOOSTVOL_WIDTH 3 /* L2_2BOOSTVOL - [6:4] */ -#define WM8983_AUXL2BOOSTVOL_MASK 0x0007 /* AUXL2BOOSTVOL - [2:0] */ -#define WM8983_AUXL2BOOSTVOL_SHIFT 0 /* AUXL2BOOSTVOL - [2:0] */ -#define WM8983_AUXL2BOOSTVOL_WIDTH 3 /* AUXL2BOOSTVOL - [2:0] */ - -/* - * R48 (0x30) - Right ADC BOOST ctrl - */ -#define WM8983_PGABOOSTR 0x0100 /* PGABOOSTR */ -#define WM8983_PGABOOSTR_MASK 0x0100 /* PGABOOSTR */ -#define WM8983_PGABOOSTR_SHIFT 8 /* PGABOOSTR */ -#define WM8983_PGABOOSTR_WIDTH 1 /* PGABOOSTR */ -#define WM8983_R2_2BOOSTVOL_MASK 0x0070 /* R2_2BOOSTVOL - [6:4] */ -#define WM8983_R2_2BOOSTVOL_SHIFT 4 /* R2_2BOOSTVOL - [6:4] */ -#define WM8983_R2_2BOOSTVOL_WIDTH 3 /* R2_2BOOSTVOL - [6:4] */ -#define WM8983_AUXR2BOOSTVOL_MASK 0x0007 /* AUXR2BOOSTVOL - [2:0] */ -#define WM8983_AUXR2BOOSTVOL_SHIFT 0 /* AUXR2BOOSTVOL - [2:0] */ -#define WM8983_AUXR2BOOSTVOL_WIDTH 3 /* AUXR2BOOSTVOL - [2:0] */ - -/* - * R49 (0x31) - Output ctrl - */ -#define WM8983_DACL2RMIX 0x0040 /* DACL2RMIX */ -#define WM8983_DACL2RMIX_MASK 0x0040 /* DACL2RMIX */ -#define WM8983_DACL2RMIX_SHIFT 6 /* DACL2RMIX */ -#define WM8983_DACL2RMIX_WIDTH 1 /* DACL2RMIX */ -#define WM8983_DACR2LMIX 0x0020 /* DACR2LMIX */ -#define WM8983_DACR2LMIX_MASK 0x0020 /* DACR2LMIX */ -#define WM8983_DACR2LMIX_SHIFT 5 /* DACR2LMIX */ -#define WM8983_DACR2LMIX_WIDTH 1 /* DACR2LMIX */ -#define WM8983_OUT4BOOST 0x0010 /* OUT4BOOST */ -#define WM8983_OUT4BOOST_MASK 0x0010 /* OUT4BOOST */ -#define WM8983_OUT4BOOST_SHIFT 4 /* OUT4BOOST */ -#define WM8983_OUT4BOOST_WIDTH 1 /* OUT4BOOST */ -#define WM8983_OUT3BOOST 0x0008 /* OUT3BOOST */ -#define WM8983_OUT3BOOST_MASK 0x0008 /* OUT3BOOST */ -#define WM8983_OUT3BOOST_SHIFT 3 /* OUT3BOOST */ -#define WM8983_OUT3BOOST_WIDTH 1 /* OUT3BOOST */ -#define WM8983_SPKBOOST 0x0004 /* SPKBOOST */ -#define WM8983_SPKBOOST_MASK 0x0004 /* SPKBOOST */ -#define WM8983_SPKBOOST_SHIFT 2 /* SPKBOOST */ -#define WM8983_SPKBOOST_WIDTH 1 /* SPKBOOST */ -#define WM8983_TSDEN 0x0002 /* TSDEN */ -#define WM8983_TSDEN_MASK 0x0002 /* TSDEN */ -#define WM8983_TSDEN_SHIFT 1 /* TSDEN */ -#define WM8983_TSDEN_WIDTH 1 /* TSDEN */ -#define WM8983_VROI 0x0001 /* VROI */ -#define WM8983_VROI_MASK 0x0001 /* VROI */ -#define WM8983_VROI_SHIFT 0 /* VROI */ -#define WM8983_VROI_WIDTH 1 /* VROI */ - -/* - * R50 (0x32) - Left mixer ctrl - */ -#define WM8983_AUXLMIXVOL_MASK 0x01C0 /* AUXLMIXVOL - [8:6] */ -#define WM8983_AUXLMIXVOL_SHIFT 6 /* AUXLMIXVOL - [8:6] */ -#define WM8983_AUXLMIXVOL_WIDTH 3 /* AUXLMIXVOL - [8:6] */ -#define WM8983_AUXL2LMIX 0x0020 /* AUXL2LMIX */ -#define WM8983_AUXL2LMIX_MASK 0x0020 /* AUXL2LMIX */ -#define WM8983_AUXL2LMIX_SHIFT 5 /* AUXL2LMIX */ -#define WM8983_AUXL2LMIX_WIDTH 1 /* AUXL2LMIX */ -#define WM8983_BYPLMIXVOL_MASK 0x001C /* BYPLMIXVOL - [4:2] */ -#define WM8983_BYPLMIXVOL_SHIFT 2 /* BYPLMIXVOL - [4:2] */ -#define WM8983_BYPLMIXVOL_WIDTH 3 /* BYPLMIXVOL - [4:2] */ -#define WM8983_BYPL2LMIX 0x0002 /* BYPL2LMIX */ -#define WM8983_BYPL2LMIX_MASK 0x0002 /* BYPL2LMIX */ -#define WM8983_BYPL2LMIX_SHIFT 1 /* BYPL2LMIX */ -#define WM8983_BYPL2LMIX_WIDTH 1 /* BYPL2LMIX */ -#define WM8983_DACL2LMIX 0x0001 /* DACL2LMIX */ -#define WM8983_DACL2LMIX_MASK 0x0001 /* DACL2LMIX */ -#define WM8983_DACL2LMIX_SHIFT 0 /* DACL2LMIX */ -#define WM8983_DACL2LMIX_WIDTH 1 /* DACL2LMIX */ - -/* - * R51 (0x33) - Right mixer ctrl - */ -#define WM8983_AUXRMIXVOL_MASK 0x01C0 /* AUXRMIXVOL - [8:6] */ -#define WM8983_AUXRMIXVOL_SHIFT 6 /* AUXRMIXVOL - [8:6] */ -#define WM8983_AUXRMIXVOL_WIDTH 3 /* AUXRMIXVOL - [8:6] */ -#define WM8983_AUXR2RMIX 0x0020 /* AUXR2RMIX */ -#define WM8983_AUXR2RMIX_MASK 0x0020 /* AUXR2RMIX */ -#define WM8983_AUXR2RMIX_SHIFT 5 /* AUXR2RMIX */ -#define WM8983_AUXR2RMIX_WIDTH 1 /* AUXR2RMIX */ -#define WM8983_BYPRMIXVOL_MASK 0x001C /* BYPRMIXVOL - [4:2] */ -#define WM8983_BYPRMIXVOL_SHIFT 2 /* BYPRMIXVOL - [4:2] */ -#define WM8983_BYPRMIXVOL_WIDTH 3 /* BYPRMIXVOL - [4:2] */ -#define WM8983_BYPR2RMIX 0x0002 /* BYPR2RMIX */ -#define WM8983_BYPR2RMIX_MASK 0x0002 /* BYPR2RMIX */ -#define WM8983_BYPR2RMIX_SHIFT 1 /* BYPR2RMIX */ -#define WM8983_BYPR2RMIX_WIDTH 1 /* BYPR2RMIX */ -#define WM8983_DACR2RMIX 0x0001 /* DACR2RMIX */ -#define WM8983_DACR2RMIX_MASK 0x0001 /* DACR2RMIX */ -#define WM8983_DACR2RMIX_SHIFT 0 /* DACR2RMIX */ -#define WM8983_DACR2RMIX_WIDTH 1 /* DACR2RMIX */ - -/* - * R52 (0x34) - LOUT1 (HP) volume ctrl - */ -#define WM8983_OUT1VU 0x0100 /* OUT1VU */ -#define WM8983_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8983_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8983_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8983_LOUT1ZC 0x0080 /* LOUT1ZC */ -#define WM8983_LOUT1ZC_MASK 0x0080 /* LOUT1ZC */ -#define WM8983_LOUT1ZC_SHIFT 7 /* LOUT1ZC */ -#define WM8983_LOUT1ZC_WIDTH 1 /* LOUT1ZC */ -#define WM8983_LOUT1MUTE 0x0040 /* LOUT1MUTE */ -#define WM8983_LOUT1MUTE_MASK 0x0040 /* LOUT1MUTE */ -#define WM8983_LOUT1MUTE_SHIFT 6 /* LOUT1MUTE */ -#define WM8983_LOUT1MUTE_WIDTH 1 /* LOUT1MUTE */ -#define WM8983_LOUT1VOL_MASK 0x003F /* LOUT1VOL - [5:0] */ -#define WM8983_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [5:0] */ -#define WM8983_LOUT1VOL_WIDTH 6 /* LOUT1VOL - [5:0] */ - -/* - * R53 (0x35) - ROUT1 (HP) volume ctrl - */ -#define WM8983_OUT1VU 0x0100 /* OUT1VU */ -#define WM8983_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8983_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8983_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8983_ROUT1ZC 0x0080 /* ROUT1ZC */ -#define WM8983_ROUT1ZC_MASK 0x0080 /* ROUT1ZC */ -#define WM8983_ROUT1ZC_SHIFT 7 /* ROUT1ZC */ -#define WM8983_ROUT1ZC_WIDTH 1 /* ROUT1ZC */ -#define WM8983_ROUT1MUTE 0x0040 /* ROUT1MUTE */ -#define WM8983_ROUT1MUTE_MASK 0x0040 /* ROUT1MUTE */ -#define WM8983_ROUT1MUTE_SHIFT 6 /* ROUT1MUTE */ -#define WM8983_ROUT1MUTE_WIDTH 1 /* ROUT1MUTE */ -#define WM8983_ROUT1VOL_MASK 0x003F /* ROUT1VOL - [5:0] */ -#define WM8983_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [5:0] */ -#define WM8983_ROUT1VOL_WIDTH 6 /* ROUT1VOL - [5:0] */ - -/* - * R54 (0x36) - LOUT2 (SPK) volume ctrl - */ -#define WM8983_OUT2VU 0x0100 /* OUT2VU */ -#define WM8983_OUT2VU_MASK 0x0100 /* OUT2VU */ -#define WM8983_OUT2VU_SHIFT 8 /* OUT2VU */ -#define WM8983_OUT2VU_WIDTH 1 /* OUT2VU */ -#define WM8983_LOUT2ZC 0x0080 /* LOUT2ZC */ -#define WM8983_LOUT2ZC_MASK 0x0080 /* LOUT2ZC */ -#define WM8983_LOUT2ZC_SHIFT 7 /* LOUT2ZC */ -#define WM8983_LOUT2ZC_WIDTH 1 /* LOUT2ZC */ -#define WM8983_LOUT2MUTE 0x0040 /* LOUT2MUTE */ -#define WM8983_LOUT2MUTE_MASK 0x0040 /* LOUT2MUTE */ -#define WM8983_LOUT2MUTE_SHIFT 6 /* LOUT2MUTE */ -#define WM8983_LOUT2MUTE_WIDTH 1 /* LOUT2MUTE */ -#define WM8983_LOUT2VOL_MASK 0x003F /* LOUT2VOL - [5:0] */ -#define WM8983_LOUT2VOL_SHIFT 0 /* LOUT2VOL - [5:0] */ -#define WM8983_LOUT2VOL_WIDTH 6 /* LOUT2VOL - [5:0] */ - -/* - * R55 (0x37) - ROUT2 (SPK) volume ctrl - */ -#define WM8983_OUT2VU 0x0100 /* OUT2VU */ -#define WM8983_OUT2VU_MASK 0x0100 /* OUT2VU */ -#define WM8983_OUT2VU_SHIFT 8 /* OUT2VU */ -#define WM8983_OUT2VU_WIDTH 1 /* OUT2VU */ -#define WM8983_ROUT2ZC 0x0080 /* ROUT2ZC */ -#define WM8983_ROUT2ZC_MASK 0x0080 /* ROUT2ZC */ -#define WM8983_ROUT2ZC_SHIFT 7 /* ROUT2ZC */ -#define WM8983_ROUT2ZC_WIDTH 1 /* ROUT2ZC */ -#define WM8983_ROUT2MUTE 0x0040 /* ROUT2MUTE */ -#define WM8983_ROUT2MUTE_MASK 0x0040 /* ROUT2MUTE */ -#define WM8983_ROUT2MUTE_SHIFT 6 /* ROUT2MUTE */ -#define WM8983_ROUT2MUTE_WIDTH 1 /* ROUT2MUTE */ -#define WM8983_ROUT2VOL_MASK 0x003F /* ROUT2VOL - [5:0] */ -#define WM8983_ROUT2VOL_SHIFT 0 /* ROUT2VOL - [5:0] */ -#define WM8983_ROUT2VOL_WIDTH 6 /* ROUT2VOL - [5:0] */ - -/* - * R56 (0x38) - OUT3 mixer ctrl - */ -#define WM8983_OUT3MUTE 0x0040 /* OUT3MUTE */ -#define WM8983_OUT3MUTE_MASK 0x0040 /* OUT3MUTE */ -#define WM8983_OUT3MUTE_SHIFT 6 /* OUT3MUTE */ -#define WM8983_OUT3MUTE_WIDTH 1 /* OUT3MUTE */ -#define WM8983_OUT4_2OUT3 0x0008 /* OUT4_2OUT3 */ -#define WM8983_OUT4_2OUT3_MASK 0x0008 /* OUT4_2OUT3 */ -#define WM8983_OUT4_2OUT3_SHIFT 3 /* OUT4_2OUT3 */ -#define WM8983_OUT4_2OUT3_WIDTH 1 /* OUT4_2OUT3 */ -#define WM8983_BYPL2OUT3 0x0004 /* BYPL2OUT3 */ -#define WM8983_BYPL2OUT3_MASK 0x0004 /* BYPL2OUT3 */ -#define WM8983_BYPL2OUT3_SHIFT 2 /* BYPL2OUT3 */ -#define WM8983_BYPL2OUT3_WIDTH 1 /* BYPL2OUT3 */ -#define WM8983_LMIX2OUT3 0x0002 /* LMIX2OUT3 */ -#define WM8983_LMIX2OUT3_MASK 0x0002 /* LMIX2OUT3 */ -#define WM8983_LMIX2OUT3_SHIFT 1 /* LMIX2OUT3 */ -#define WM8983_LMIX2OUT3_WIDTH 1 /* LMIX2OUT3 */ -#define WM8983_LDAC2OUT3 0x0001 /* LDAC2OUT3 */ -#define WM8983_LDAC2OUT3_MASK 0x0001 /* LDAC2OUT3 */ -#define WM8983_LDAC2OUT3_SHIFT 0 /* LDAC2OUT3 */ -#define WM8983_LDAC2OUT3_WIDTH 1 /* LDAC2OUT3 */ - -/* - * R57 (0x39) - OUT4 (MONO) mix ctrl - */ -#define WM8983_OUT3_2OUT4 0x0080 /* OUT3_2OUT4 */ -#define WM8983_OUT3_2OUT4_MASK 0x0080 /* OUT3_2OUT4 */ -#define WM8983_OUT3_2OUT4_SHIFT 7 /* OUT3_2OUT4 */ -#define WM8983_OUT3_2OUT4_WIDTH 1 /* OUT3_2OUT4 */ -#define WM8983_OUT4MUTE 0x0040 /* OUT4MUTE */ -#define WM8983_OUT4MUTE_MASK 0x0040 /* OUT4MUTE */ -#define WM8983_OUT4MUTE_SHIFT 6 /* OUT4MUTE */ -#define WM8983_OUT4MUTE_WIDTH 1 /* OUT4MUTE */ -#define WM8983_OUT4ATTN 0x0020 /* OUT4ATTN */ -#define WM8983_OUT4ATTN_MASK 0x0020 /* OUT4ATTN */ -#define WM8983_OUT4ATTN_SHIFT 5 /* OUT4ATTN */ -#define WM8983_OUT4ATTN_WIDTH 1 /* OUT4ATTN */ -#define WM8983_LMIX2OUT4 0x0010 /* LMIX2OUT4 */ -#define WM8983_LMIX2OUT4_MASK 0x0010 /* LMIX2OUT4 */ -#define WM8983_LMIX2OUT4_SHIFT 4 /* LMIX2OUT4 */ -#define WM8983_LMIX2OUT4_WIDTH 1 /* LMIX2OUT4 */ -#define WM8983_LDAC2OUT4 0x0008 /* LDAC2OUT4 */ -#define WM8983_LDAC2OUT4_MASK 0x0008 /* LDAC2OUT4 */ -#define WM8983_LDAC2OUT4_SHIFT 3 /* LDAC2OUT4 */ -#define WM8983_LDAC2OUT4_WIDTH 1 /* LDAC2OUT4 */ -#define WM8983_BYPR2OUT4 0x0004 /* BYPR2OUT4 */ -#define WM8983_BYPR2OUT4_MASK 0x0004 /* BYPR2OUT4 */ -#define WM8983_BYPR2OUT4_SHIFT 2 /* BYPR2OUT4 */ -#define WM8983_BYPR2OUT4_WIDTH 1 /* BYPR2OUT4 */ -#define WM8983_RMIX2OUT4 0x0002 /* RMIX2OUT4 */ -#define WM8983_RMIX2OUT4_MASK 0x0002 /* RMIX2OUT4 */ -#define WM8983_RMIX2OUT4_SHIFT 1 /* RMIX2OUT4 */ -#define WM8983_RMIX2OUT4_WIDTH 1 /* RMIX2OUT4 */ -#define WM8983_RDAC2OUT4 0x0001 /* RDAC2OUT4 */ -#define WM8983_RDAC2OUT4_MASK 0x0001 /* RDAC2OUT4 */ -#define WM8983_RDAC2OUT4_SHIFT 0 /* RDAC2OUT4 */ -#define WM8983_RDAC2OUT4_WIDTH 1 /* RDAC2OUT4 */ - -/* - * R61 (0x3D) - BIAS CTRL - */ -#define WM8983_BIASCUT 0x0100 /* BIASCUT */ -#define WM8983_BIASCUT_MASK 0x0100 /* BIASCUT */ -#define WM8983_BIASCUT_SHIFT 8 /* BIASCUT */ -#define WM8983_BIASCUT_WIDTH 1 /* BIASCUT */ -#define WM8983_HALFIPBIAS 0x0080 /* HALFIPBIAS */ -#define WM8983_HALFIPBIAS_MASK 0x0080 /* HALFIPBIAS */ -#define WM8983_HALFIPBIAS_SHIFT 7 /* HALFIPBIAS */ -#define WM8983_HALFIPBIAS_WIDTH 1 /* HALFIPBIAS */ -#define WM8983_VBBIASTST_MASK 0x0060 /* VBBIASTST - [6:5] */ -#define WM8983_VBBIASTST_SHIFT 5 /* VBBIASTST - [6:5] */ -#define WM8983_VBBIASTST_WIDTH 2 /* VBBIASTST - [6:5] */ -#define WM8983_BUFBIAS_MASK 0x0018 /* BUFBIAS - [4:3] */ -#define WM8983_BUFBIAS_SHIFT 3 /* BUFBIAS - [4:3] */ -#define WM8983_BUFBIAS_WIDTH 2 /* BUFBIAS - [4:3] */ -#define WM8983_ADCBIAS_MASK 0x0006 /* ADCBIAS - [2:1] */ -#define WM8983_ADCBIAS_SHIFT 1 /* ADCBIAS - [2:1] */ -#define WM8983_ADCBIAS_WIDTH 2 /* ADCBIAS - [2:1] */ -#define WM8983_HALFOPBIAS 0x0001 /* HALFOPBIAS */ -#define WM8983_HALFOPBIAS_MASK 0x0001 /* HALFOPBIAS */ -#define WM8983_HALFOPBIAS_SHIFT 0 /* HALFOPBIAS */ -#define WM8983_HALFOPBIAS_WIDTH 1 /* HALFOPBIAS */ - -enum clk_src { - WM8983_CLKSRC_MCLK, - WM8983_CLKSRC_PLL -}; - -#endif /* _WM8983_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8985.c b/ANDROID_3.4.5/sound/soc/codecs/wm8985.c deleted file mode 100644 index 14f66639..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8985.c +++ /dev/null @@ -1,1260 +0,0 @@ -/* - * wm8985.c -- WM8985 ALSA SoC Audio driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: - * o Add OUT3/OUT4 mixer controls. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8985.h" - -#define WM8985_NUM_SUPPLIES 4 -static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = { - "DCVDD", - "DBVDD", - "AVDD1", - "AVDD2" -}; - -static const struct reg_default wm8985_reg_defaults[] = { - { 1, 0x0000 }, /* R1 - Power management 1 */ - { 2, 0x0000 }, /* R2 - Power management 2 */ - { 3, 0x0000 }, /* R3 - Power management 3 */ - { 4, 0x0050 }, /* R4 - Audio Interface */ - { 5, 0x0000 }, /* R5 - Companding control */ - { 6, 0x0140 }, /* R6 - Clock Gen control */ - { 7, 0x0000 }, /* R7 - Additional control */ - { 8, 0x0000 }, /* R8 - GPIO Control */ - { 9, 0x0000 }, /* R9 - Jack Detect Control 1 */ - { 10, 0x0000 }, /* R10 - DAC Control */ - { 11, 0x00FF }, /* R11 - Left DAC digital Vol */ - { 12, 0x00FF }, /* R12 - Right DAC digital vol */ - { 13, 0x0000 }, /* R13 - Jack Detect Control 2 */ - { 14, 0x0100 }, /* R14 - ADC Control */ - { 15, 0x00FF }, /* R15 - Left ADC Digital Vol */ - { 16, 0x00FF }, /* R16 - Right ADC Digital Vol */ - { 18, 0x012C }, /* R18 - EQ1 - low shelf */ - { 19, 0x002C }, /* R19 - EQ2 - peak 1 */ - { 20, 0x002C }, /* R20 - EQ3 - peak 2 */ - { 21, 0x002C }, /* R21 - EQ4 - peak 3 */ - { 22, 0x002C }, /* R22 - EQ5 - high shelf */ - { 24, 0x0032 }, /* R24 - DAC Limiter 1 */ - { 25, 0x0000 }, /* R25 - DAC Limiter 2 */ - { 27, 0x0000 }, /* R27 - Notch Filter 1 */ - { 28, 0x0000 }, /* R28 - Notch Filter 2 */ - { 29, 0x0000 }, /* R29 - Notch Filter 3 */ - { 30, 0x0000 }, /* R30 - Notch Filter 4 */ - { 32, 0x0038 }, /* R32 - ALC control 1 */ - { 33, 0x000B }, /* R33 - ALC control 2 */ - { 34, 0x0032 }, /* R34 - ALC control 3 */ - { 35, 0x0000 }, /* R35 - Noise Gate */ - { 36, 0x0008 }, /* R36 - PLL N */ - { 37, 0x000C }, /* R37 - PLL K 1 */ - { 38, 0x0093 }, /* R38 - PLL K 2 */ - { 39, 0x00E9 }, /* R39 - PLL K 3 */ - { 41, 0x0000 }, /* R41 - 3D control */ - { 42, 0x0000 }, /* R42 - OUT4 to ADC */ - { 43, 0x0000 }, /* R43 - Beep control */ - { 44, 0x0033 }, /* R44 - Input ctrl */ - { 45, 0x0010 }, /* R45 - Left INP PGA gain ctrl */ - { 46, 0x0010 }, /* R46 - Right INP PGA gain ctrl */ - { 47, 0x0100 }, /* R47 - Left ADC BOOST ctrl */ - { 48, 0x0100 }, /* R48 - Right ADC BOOST ctrl */ - { 49, 0x0002 }, /* R49 - Output ctrl */ - { 50, 0x0001 }, /* R50 - Left mixer ctrl */ - { 51, 0x0001 }, /* R51 - Right mixer ctrl */ - { 52, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */ - { 53, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */ - { 54, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */ - { 55, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */ - { 56, 0x0001 }, /* R56 - OUT3 mixer ctrl */ - { 57, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */ - { 60, 0x0004 }, /* R60 - OUTPUT ctrl */ - { 61, 0x0000 }, /* R61 - BIAS CTRL */ -}; - -static bool wm8985_writeable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8985_SOFTWARE_RESET: - case WM8985_POWER_MANAGEMENT_1: - case WM8985_POWER_MANAGEMENT_2: - case WM8985_POWER_MANAGEMENT_3: - case WM8985_AUDIO_INTERFACE: - case WM8985_COMPANDING_CONTROL: - case WM8985_CLOCK_GEN_CONTROL: - case WM8985_ADDITIONAL_CONTROL: - case WM8985_GPIO_CONTROL: - case WM8985_JACK_DETECT_CONTROL_1: - case WM8985_DAC_CONTROL: - case WM8985_LEFT_DAC_DIGITAL_VOL: - case WM8985_RIGHT_DAC_DIGITAL_VOL: - case WM8985_JACK_DETECT_CONTROL_2: - case WM8985_ADC_CONTROL: - case WM8985_LEFT_ADC_DIGITAL_VOL: - case WM8985_RIGHT_ADC_DIGITAL_VOL: - case WM8985_EQ1_LOW_SHELF: - case WM8985_EQ2_PEAK_1: - case WM8985_EQ3_PEAK_2: - case WM8985_EQ4_PEAK_3: - case WM8985_EQ5_HIGH_SHELF: - case WM8985_DAC_LIMITER_1: - case WM8985_DAC_LIMITER_2: - case WM8985_NOTCH_FILTER_1: - case WM8985_NOTCH_FILTER_2: - case WM8985_NOTCH_FILTER_3: - case WM8985_NOTCH_FILTER_4: - case WM8985_ALC_CONTROL_1: - case WM8985_ALC_CONTROL_2: - case WM8985_ALC_CONTROL_3: - case WM8985_NOISE_GATE: - case WM8985_PLL_N: - case WM8985_PLL_K_1: - case WM8985_PLL_K_2: - case WM8985_PLL_K_3: - case WM8985_3D_CONTROL: - case WM8985_OUT4_TO_ADC: - case WM8985_BEEP_CONTROL: - case WM8985_INPUT_CTRL: - case WM8985_LEFT_INP_PGA_GAIN_CTRL: - case WM8985_RIGHT_INP_PGA_GAIN_CTRL: - case WM8985_LEFT_ADC_BOOST_CTRL: - case WM8985_RIGHT_ADC_BOOST_CTRL: - case WM8985_OUTPUT_CTRL0: - case WM8985_LEFT_MIXER_CTRL: - case WM8985_RIGHT_MIXER_CTRL: - case WM8985_LOUT1_HP_VOLUME_CTRL: - case WM8985_ROUT1_HP_VOLUME_CTRL: - case WM8985_LOUT2_SPK_VOLUME_CTRL: - case WM8985_ROUT2_SPK_VOLUME_CTRL: - case WM8985_OUT3_MIXER_CTRL: - case WM8985_OUT4_MONO_MIX_CTRL: - case WM8985_OUTPUT_CTRL1: - case WM8985_BIAS_CTRL: - return true; - default: - return false; - } -} - -/* - * latch bit 8 of these registers to ensure instant - * volume updates - */ -static const int volume_update_regs[] = { - WM8985_LEFT_DAC_DIGITAL_VOL, - WM8985_RIGHT_DAC_DIGITAL_VOL, - WM8985_LEFT_ADC_DIGITAL_VOL, - WM8985_RIGHT_ADC_DIGITAL_VOL, - WM8985_LOUT2_SPK_VOLUME_CTRL, - WM8985_ROUT2_SPK_VOLUME_CTRL, - WM8985_LOUT1_HP_VOLUME_CTRL, - WM8985_ROUT1_HP_VOLUME_CTRL, - WM8985_LEFT_INP_PGA_GAIN_CTRL, - WM8985_RIGHT_INP_PGA_GAIN_CTRL -}; - -struct wm8985_priv { - struct regmap *regmap; - struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES]; - unsigned int sysclk; - unsigned int bclk; -}; - -static const struct { - int div; - int ratio; -} fs_ratios[] = { - { 10, 128 }, - { 15, 192 }, - { 20, 256 }, - { 30, 384 }, - { 40, 512 }, - { 60, 768 }, - { 80, 1024 }, - { 120, 1536 } -}; - -static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 }; - -static const int bclk_divs[] = { - 1, 2, 4, 8, 16, 32 -}; - -static int eqmode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -static int eqmode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1); -static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); -static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0); -static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0); -static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0); -static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0); -static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0); -static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0); - -static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" }; -static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7, - alc_sel_text); - -static const char *alc_mode_text[] = { "ALC", "Limiter" }; -static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8, - alc_mode_text); - -static const char *filter_mode_text[] = { "Audio", "Application" }; -static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7, - filter_mode_text); - -static const char *eq_bw_text[] = { "Narrow", "Wide" }; -static const char *eqmode_text[] = { "Capture", "Playback" }; -static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text); - -static const char *eq1_cutoff_text[] = { - "80Hz", "105Hz", "135Hz", "175Hz" -}; -static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5, - eq1_cutoff_text); -static const char *eq2_cutoff_text[] = { - "230Hz", "300Hz", "385Hz", "500Hz" -}; -static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5, - eq2_cutoff_text); -static const char *eq3_cutoff_text[] = { - "650Hz", "850Hz", "1.1kHz", "1.4kHz" -}; -static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5, - eq3_cutoff_text); -static const char *eq4_cutoff_text[] = { - "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" -}; -static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text); -static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5, - eq4_cutoff_text); -static const char *eq5_cutoff_text[] = { - "5.3kHz", "6.9kHz", "9kHz", "11.7kHz" -}; -static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5, - eq5_cutoff_text); - -static const char *speaker_mode_text[] = { "Class A/B", "Class D" }; -static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text); - -static const char *depth_3d_text[] = { - "Off", - "6.67%", - "13.3%", - "20%", - "26.7%", - "33.3%", - "40%", - "46.6%", - "53.3%", - "60%", - "66.7%", - "73.3%", - "80%", - "86.7%", - "93.3%", - "100%" -}; -static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0, - depth_3d_text); - -static const struct snd_kcontrol_new wm8985_snd_controls[] = { - SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL, - 0, 1, 0), - - SOC_ENUM("ALC Capture Function", alc_sel), - SOC_SINGLE_TLV("ALC Capture Max Volume", WM8985_ALC_CONTROL_1, - 3, 7, 0, alc_max_tlv), - SOC_SINGLE_TLV("ALC Capture Min Volume", WM8985_ALC_CONTROL_1, - 0, 7, 0, alc_min_tlv), - SOC_SINGLE_TLV("ALC Capture Target Volume", WM8985_ALC_CONTROL_2, - 0, 15, 0, alc_tar_tlv), - SOC_SINGLE("ALC Capture Attack", WM8985_ALC_CONTROL_3, 0, 10, 0), - SOC_SINGLE("ALC Capture Hold", WM8985_ALC_CONTROL_2, 4, 10, 0), - SOC_SINGLE("ALC Capture Decay", WM8985_ALC_CONTROL_3, 4, 10, 0), - SOC_ENUM("ALC Mode", alc_mode), - SOC_SINGLE("ALC Capture NG Switch", WM8985_NOISE_GATE, - 3, 1, 0), - SOC_SINGLE("ALC Capture NG Threshold", WM8985_NOISE_GATE, - 0, 7, 1), - - SOC_DOUBLE_R_TLV("Capture Volume", WM8985_LEFT_ADC_DIGITAL_VOL, - WM8985_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv), - SOC_DOUBLE_R("Capture PGA ZC Switch", WM8985_LEFT_INP_PGA_GAIN_CTRL, - WM8985_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0), - SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8985_LEFT_INP_PGA_GAIN_CTRL, - WM8985_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv), - - SOC_DOUBLE_R_TLV("Capture PGA Boost Volume", - WM8985_LEFT_ADC_BOOST_CTRL, WM8985_RIGHT_ADC_BOOST_CTRL, - 8, 1, 0, pga_boost_tlv), - - SOC_DOUBLE("ADC Inversion Switch", WM8985_ADC_CONTROL, 0, 1, 1, 0), - SOC_SINGLE("ADC 128x Oversampling Switch", WM8985_ADC_CONTROL, 8, 1, 0), - - SOC_DOUBLE_R_TLV("Playback Volume", WM8985_LEFT_DAC_DIGITAL_VOL, - WM8985_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv), - - SOC_SINGLE("DAC Playback Limiter Switch", WM8985_DAC_LIMITER_1, 8, 1, 0), - SOC_SINGLE("DAC Playback Limiter Decay", WM8985_DAC_LIMITER_1, 4, 10, 0), - SOC_SINGLE("DAC Playback Limiter Attack", WM8985_DAC_LIMITER_1, 0, 11, 0), - SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8985_DAC_LIMITER_2, - 4, 7, 1, lim_thresh_tlv), - SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8985_DAC_LIMITER_2, - 0, 12, 0, lim_boost_tlv), - SOC_DOUBLE("DAC Inversion Switch", WM8985_DAC_CONTROL, 0, 1, 1, 0), - SOC_SINGLE("DAC Auto Mute Switch", WM8985_DAC_CONTROL, 2, 1, 0), - SOC_SINGLE("DAC 128x Oversampling Switch", WM8985_DAC_CONTROL, 3, 1, 0), - - SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8985_LOUT1_HP_VOLUME_CTRL, - WM8985_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv), - SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8985_LOUT1_HP_VOLUME_CTRL, - WM8985_ROUT1_HP_VOLUME_CTRL, 7, 1, 0), - SOC_DOUBLE_R("Headphone Switch", WM8985_LOUT1_HP_VOLUME_CTRL, - WM8985_ROUT1_HP_VOLUME_CTRL, 6, 1, 1), - - SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8985_LOUT2_SPK_VOLUME_CTRL, - WM8985_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv), - SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8985_LOUT2_SPK_VOLUME_CTRL, - WM8985_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0), - SOC_DOUBLE_R("Speaker Switch", WM8985_LOUT2_SPK_VOLUME_CTRL, - WM8985_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1), - - SOC_SINGLE("High Pass Filter Switch", WM8985_ADC_CONTROL, 8, 1, 0), - SOC_ENUM("High Pass Filter Mode", filter_mode), - SOC_SINGLE("High Pass Filter Cutoff", WM8985_ADC_CONTROL, 4, 7, 0), - - SOC_DOUBLE_R_TLV("Aux Bypass Volume", - WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 6, 7, 0, - aux_tlv), - - SOC_DOUBLE_R_TLV("Input PGA Bypass Volume", - WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 2, 7, 0, - bypass_tlv), - - SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put), - SOC_ENUM("EQ1 Cutoff", eq1_cutoff), - SOC_SINGLE_TLV("EQ1 Volume", WM8985_EQ1_LOW_SHELF, 0, 24, 1, eq_tlv), - SOC_ENUM("EQ2 Bandwith", eq2_bw), - SOC_ENUM("EQ2 Cutoff", eq2_cutoff), - SOC_SINGLE_TLV("EQ2 Volume", WM8985_EQ2_PEAK_1, 0, 24, 1, eq_tlv), - SOC_ENUM("EQ3 Bandwith", eq3_bw), - SOC_ENUM("EQ3 Cutoff", eq3_cutoff), - SOC_SINGLE_TLV("EQ3 Volume", WM8985_EQ3_PEAK_2, 0, 24, 1, eq_tlv), - SOC_ENUM("EQ4 Bandwith", eq4_bw), - SOC_ENUM("EQ4 Cutoff", eq4_cutoff), - SOC_SINGLE_TLV("EQ4 Volume", WM8985_EQ4_PEAK_3, 0, 24, 1, eq_tlv), - SOC_ENUM("EQ5 Cutoff", eq5_cutoff), - SOC_SINGLE_TLV("EQ5 Volume", WM8985_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv), - - SOC_ENUM("3D Depth", depth_3d), - - SOC_ENUM("Speaker Mode", speaker_mode) -}; - -static const struct snd_kcontrol_new left_out_mixer[] = { - SOC_DAPM_SINGLE("Line Switch", WM8985_LEFT_MIXER_CTRL, 1, 1, 0), - SOC_DAPM_SINGLE("Aux Switch", WM8985_LEFT_MIXER_CTRL, 5, 1, 0), - SOC_DAPM_SINGLE("PCM Switch", WM8985_LEFT_MIXER_CTRL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_out_mixer[] = { - SOC_DAPM_SINGLE("Line Switch", WM8985_RIGHT_MIXER_CTRL, 1, 1, 0), - SOC_DAPM_SINGLE("Aux Switch", WM8985_RIGHT_MIXER_CTRL, 5, 1, 0), - SOC_DAPM_SINGLE("PCM Switch", WM8985_RIGHT_MIXER_CTRL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new left_input_mixer[] = { - SOC_DAPM_SINGLE("L2 Switch", WM8985_INPUT_CTRL, 2, 1, 0), - SOC_DAPM_SINGLE("MicN Switch", WM8985_INPUT_CTRL, 1, 1, 0), - SOC_DAPM_SINGLE("MicP Switch", WM8985_INPUT_CTRL, 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_input_mixer[] = { - SOC_DAPM_SINGLE("R2 Switch", WM8985_INPUT_CTRL, 6, 1, 0), - SOC_DAPM_SINGLE("MicN Switch", WM8985_INPUT_CTRL, 5, 1, 0), - SOC_DAPM_SINGLE("MicP Switch", WM8985_INPUT_CTRL, 4, 1, 0), -}; - -static const struct snd_kcontrol_new left_boost_mixer[] = { - SOC_DAPM_SINGLE_TLV("L2 Volume", WM8985_LEFT_ADC_BOOST_CTRL, - 4, 7, 0, boost_tlv), - SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8985_LEFT_ADC_BOOST_CTRL, - 0, 7, 0, boost_tlv) -}; - -static const struct snd_kcontrol_new right_boost_mixer[] = { - SOC_DAPM_SINGLE_TLV("R2 Volume", WM8985_RIGHT_ADC_BOOST_CTRL, - 4, 7, 0, boost_tlv), - SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8985_RIGHT_ADC_BOOST_CTRL, - 0, 7, 0, boost_tlv) -}; - -static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = { - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8985_POWER_MANAGEMENT_3, - 0, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8985_POWER_MANAGEMENT_3, - 1, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8985_POWER_MANAGEMENT_2, - 0, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8985_POWER_MANAGEMENT_2, - 1, 0), - - SND_SOC_DAPM_MIXER("Left Output Mixer", WM8985_POWER_MANAGEMENT_3, - 2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)), - SND_SOC_DAPM_MIXER("Right Output Mixer", WM8985_POWER_MANAGEMENT_3, - 3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)), - - SND_SOC_DAPM_MIXER("Left Input Mixer", WM8985_POWER_MANAGEMENT_2, - 2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)), - SND_SOC_DAPM_MIXER("Right Input Mixer", WM8985_POWER_MANAGEMENT_2, - 3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)), - - SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8985_POWER_MANAGEMENT_2, - 4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)), - SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8985_POWER_MANAGEMENT_2, - 5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)), - - SND_SOC_DAPM_PGA("Left Capture PGA", WM8985_LEFT_INP_PGA_GAIN_CTRL, - 6, 1, NULL, 0), - SND_SOC_DAPM_PGA("Right Capture PGA", WM8985_RIGHT_INP_PGA_GAIN_CTRL, - 6, 1, NULL, 0), - - SND_SOC_DAPM_PGA("Left Headphone Out", WM8985_POWER_MANAGEMENT_2, - 7, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Headphone Out", WM8985_POWER_MANAGEMENT_2, - 8, 0, NULL, 0), - - SND_SOC_DAPM_PGA("Left Speaker Out", WM8985_POWER_MANAGEMENT_3, - 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Speaker Out", WM8985_POWER_MANAGEMENT_3, - 6, 0, NULL, 0), - - SND_SOC_DAPM_SUPPLY("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0, - NULL, 0), - - SND_SOC_DAPM_INPUT("LIN"), - SND_SOC_DAPM_INPUT("LIP"), - SND_SOC_DAPM_INPUT("RIN"), - SND_SOC_DAPM_INPUT("RIP"), - SND_SOC_DAPM_INPUT("AUXL"), - SND_SOC_DAPM_INPUT("AUXR"), - SND_SOC_DAPM_INPUT("L2"), - SND_SOC_DAPM_INPUT("R2"), - SND_SOC_DAPM_OUTPUT("HPL"), - SND_SOC_DAPM_OUTPUT("HPR"), - SND_SOC_DAPM_OUTPUT("SPKL"), - SND_SOC_DAPM_OUTPUT("SPKR") -}; - -static const struct snd_soc_dapm_route wm8985_dapm_routes[] = { - { "Right Output Mixer", "PCM Switch", "Right DAC" }, - { "Right Output Mixer", "Aux Switch", "AUXR" }, - { "Right Output Mixer", "Line Switch", "Right Boost Mixer" }, - - { "Left Output Mixer", "PCM Switch", "Left DAC" }, - { "Left Output Mixer", "Aux Switch", "AUXL" }, - { "Left Output Mixer", "Line Switch", "Left Boost Mixer" }, - - { "Right Headphone Out", NULL, "Right Output Mixer" }, - { "HPR", NULL, "Right Headphone Out" }, - - { "Left Headphone Out", NULL, "Left Output Mixer" }, - { "HPL", NULL, "Left Headphone Out" }, - - { "Right Speaker Out", NULL, "Right Output Mixer" }, - { "SPKR", NULL, "Right Speaker Out" }, - - { "Left Speaker Out", NULL, "Left Output Mixer" }, - { "SPKL", NULL, "Left Speaker Out" }, - - { "Right ADC", NULL, "Right Boost Mixer" }, - - { "Right Boost Mixer", "AUXR Volume", "AUXR" }, - { "Right Boost Mixer", NULL, "Right Capture PGA" }, - { "Right Boost Mixer", "R2 Volume", "R2" }, - - { "Left ADC", NULL, "Left Boost Mixer" }, - - { "Left Boost Mixer", "AUXL Volume", "AUXL" }, - { "Left Boost Mixer", NULL, "Left Capture PGA" }, - { "Left Boost Mixer", "L2 Volume", "L2" }, - - { "Right Capture PGA", NULL, "Right Input Mixer" }, - { "Left Capture PGA", NULL, "Left Input Mixer" }, - - { "Right Input Mixer", "R2 Switch", "R2" }, - { "Right Input Mixer", "MicN Switch", "RIN" }, - { "Right Input Mixer", "MicP Switch", "RIP" }, - - { "Left Input Mixer", "L2 Switch", "L2" }, - { "Left Input Mixer", "MicN Switch", "LIN" }, - { "Left Input Mixer", "MicP Switch", "LIP" }, -}; - -static int eqmode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg; - - reg = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF); - if (reg & WM8985_EQ3DMODE) - ucontrol->value.integer.value[0] = 1; - else - ucontrol->value.integer.value[0] = 0; - - return 0; -} - -static int eqmode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int regpwr2, regpwr3; - unsigned int reg_eq; - - if (ucontrol->value.integer.value[0] != 0 - && ucontrol->value.integer.value[0] != 1) - return -EINVAL; - - reg_eq = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF); - switch ((reg_eq & WM8985_EQ3DMODE) >> WM8985_EQ3DMODE_SHIFT) { - case 0: - if (!ucontrol->value.integer.value[0]) - return 0; - break; - case 1: - if (ucontrol->value.integer.value[0]) - return 0; - break; - } - - regpwr2 = snd_soc_read(codec, WM8985_POWER_MANAGEMENT_2); - regpwr3 = snd_soc_read(codec, WM8985_POWER_MANAGEMENT_3); - /* disable the DACs and ADCs */ - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_2, - WM8985_ADCENR_MASK | WM8985_ADCENL_MASK, 0); - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_3, - WM8985_DACENR_MASK | WM8985_DACENL_MASK, 0); - snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL, - WM8985_M128ENB_MASK, WM8985_M128ENB); - /* set the desired eqmode */ - snd_soc_update_bits(codec, WM8985_EQ1_LOW_SHELF, - WM8985_EQ3DMODE_MASK, - ucontrol->value.integer.value[0] - << WM8985_EQ3DMODE_SHIFT); - /* restore DAC/ADC configuration */ - snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, regpwr2); - snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, regpwr3); - return 0; -} - -static int wm8985_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8985_SOFTWARE_RESET, 0x0); -} - -static int wm8985_dac_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - return snd_soc_update_bits(codec, WM8985_DAC_CONTROL, - WM8985_SOFTMUTE_MASK, - !!mute << WM8985_SOFTMUTE_SHIFT); -} - -static int wm8985_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec; - u16 format, master, bcp, lrp; - - codec = dai->codec; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - format = 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - format = 0x0; - break; - case SND_SOC_DAIFMT_LEFT_J: - format = 0x1; - break; - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - format = 0x3; - break; - default: - dev_err(dai->dev, "Unknown dai format\n"); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE, - WM8985_FMT_MASK, format << WM8985_FMT_SHIFT); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - master = 1; - break; - case SND_SOC_DAIFMT_CBS_CFS: - master = 0; - break; - default: - dev_err(dai->dev, "Unknown master/slave configuration\n"); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, - WM8985_MS_MASK, master << WM8985_MS_SHIFT); - - /* frame inversion is not valid for dsp modes */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - case SND_SOC_DAIFMT_NB_IF: - return -EINVAL; - default: - break; - } - break; - default: - break; - } - - bcp = lrp = 0; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - bcp = lrp = 1; - break; - case SND_SOC_DAIFMT_IB_NF: - bcp = 1; - break; - case SND_SOC_DAIFMT_NB_IF: - lrp = 1; - break; - default: - dev_err(dai->dev, "Unknown polarity configuration\n"); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE, - WM8985_LRP_MASK, lrp << WM8985_LRP_SHIFT); - snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE, - WM8985_BCP_MASK, bcp << WM8985_BCP_SHIFT); - return 0; -} - -static int wm8985_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int i; - struct snd_soc_codec *codec; - struct wm8985_priv *wm8985; - u16 blen, srate_idx; - unsigned int tmp; - int srate_best; - - codec = dai->codec; - wm8985 = snd_soc_codec_get_drvdata(codec); - - wm8985->bclk = snd_soc_params_to_bclk(params); - if ((int)wm8985->bclk < 0) - return wm8985->bclk; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - blen = 0x0; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - blen = 0x1; - break; - case SNDRV_PCM_FORMAT_S24_LE: - blen = 0x2; - break; - case SNDRV_PCM_FORMAT_S32_LE: - blen = 0x3; - break; - default: - dev_err(dai->dev, "Unsupported word length %u\n", - params_format(params)); - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE, - WM8985_WL_MASK, blen << WM8985_WL_SHIFT); - - /* - * match to the nearest possible sample rate and rely - * on the array index to configure the SR register - */ - srate_idx = 0; - srate_best = abs(srates[0] - params_rate(params)); - for (i = 1; i < ARRAY_SIZE(srates); ++i) { - if (abs(srates[i] - params_rate(params)) >= srate_best) - continue; - srate_idx = i; - srate_best = abs(srates[i] - params_rate(params)); - } - - dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]); - snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL, - WM8985_SR_MASK, srate_idx << WM8985_SR_SHIFT); - - dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8985->bclk); - dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8985->sysclk); - - for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) { - if (wm8985->sysclk / params_rate(params) - == fs_ratios[i].ratio) - break; - } - - if (i == ARRAY_SIZE(fs_ratios)) { - dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n", - wm8985->sysclk, params_rate(params)); - return -EINVAL; - } - - dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio); - snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, - WM8985_MCLKDIV_MASK, i << WM8985_MCLKDIV_SHIFT); - - /* select the appropriate bclk divider */ - tmp = (wm8985->sysclk / fs_ratios[i].div) * 10; - for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) { - if (wm8985->bclk == tmp / bclk_divs[i]) - break; - } - - if (i == ARRAY_SIZE(bclk_divs)) { - dev_err(dai->dev, "No matching BCLK divider found\n"); - return -EINVAL; - } - - dev_dbg(dai->dev, "BCLK div = %d\n", i); - snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, - WM8985_BCLKDIV_MASK, i << WM8985_BCLKDIV_SHIFT); - return 0; -} - -struct pll_div { - u32 div2:1; - u32 n:4; - u32 k:24; -}; - -#define FIXED_PLL_SIZE ((1ULL << 24) * 10) -static int pll_factors(struct pll_div *pll_div, unsigned int target, - unsigned int source) -{ - u64 Kpart; - unsigned long int K, Ndiv, Nmod; - - pll_div->div2 = 0; - Ndiv = target / source; - if (Ndiv < 6) { - source >>= 1; - pll_div->div2 = 1; - Ndiv = target / source; - } - - if (Ndiv < 6 || Ndiv > 12) { - printk(KERN_ERR "%s: WM8985 N value is not within" - " the recommended range: %lu\n", __func__, Ndiv); - return -EINVAL; - } - pll_div->n = Ndiv; - - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (u64)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xffffffff; - if ((K % 10) >= 5) - K += 5; - K /= 10; - pll_div->k = K; - - return 0; -} - -static int wm8985_set_pll(struct snd_soc_dai *dai, int pll_id, - int source, unsigned int freq_in, - unsigned int freq_out) -{ - int ret; - struct snd_soc_codec *codec; - struct pll_div pll_div; - - codec = dai->codec; - if (freq_in && freq_out) { - ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in); - if (ret) - return ret; - } - - /* disable the PLL before reprogramming it */ - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1, - WM8985_PLLEN_MASK, 0); - - if (!freq_in || !freq_out) - return 0; - - /* set PLLN and PRESCALE */ - snd_soc_write(codec, WM8985_PLL_N, - (pll_div.div2 << WM8985_PLL_PRESCALE_SHIFT) - | pll_div.n); - /* set PLLK */ - snd_soc_write(codec, WM8985_PLL_K_3, pll_div.k & 0x1ff); - snd_soc_write(codec, WM8985_PLL_K_2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8985_PLL_K_1, (pll_div.k >> 18)); - /* set the source of the clock to be the PLL */ - snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, - WM8985_CLKSEL_MASK, WM8985_CLKSEL); - /* enable the PLL */ - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1, - WM8985_PLLEN_MASK, WM8985_PLLEN); - return 0; -} - -static int wm8985_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec; - struct wm8985_priv *wm8985; - - codec = dai->codec; - wm8985 = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case WM8985_CLKSRC_MCLK: - snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, - WM8985_CLKSEL_MASK, 0); - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1, - WM8985_PLLEN_MASK, 0); - break; - case WM8985_CLKSRC_PLL: - snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL, - WM8985_CLKSEL_MASK, WM8985_CLKSEL); - break; - default: - dev_err(dai->dev, "Unknown clock source %d\n", clk_id); - return -EINVAL; - } - - wm8985->sysclk = freq; - return 0; -} - -static int wm8985_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - struct wm8985_priv *wm8985; - - wm8985 = snd_soc_codec_get_drvdata(codec); - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - /* VMID at 75k */ - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1, - WM8985_VMIDSEL_MASK, - 1 << WM8985_VMIDSEL_SHIFT); - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies), - wm8985->supplies); - if (ret) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - - regcache_sync(wm8985->regmap); - - /* enable anti-pop features */ - snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC, - WM8985_POBCTRL_MASK, - WM8985_POBCTRL); - /* enable thermal shutdown */ - snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0, - WM8985_TSDEN_MASK, WM8985_TSDEN); - snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0, - WM8985_TSOPCTRL_MASK, - WM8985_TSOPCTRL); - /* enable BIASEN */ - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1, - WM8985_BIASEN_MASK, WM8985_BIASEN); - /* VMID at 75k */ - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1, - WM8985_VMIDSEL_MASK, - 1 << WM8985_VMIDSEL_SHIFT); - msleep(500); - /* disable anti-pop features */ - snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC, - WM8985_POBCTRL_MASK, 0); - } - /* VMID at 300k */ - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1, - WM8985_VMIDSEL_MASK, - 2 << WM8985_VMIDSEL_SHIFT); - break; - case SND_SOC_BIAS_OFF: - /* disable thermal shutdown */ - snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0, - WM8985_TSOPCTRL_MASK, 0); - snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0, - WM8985_TSDEN_MASK, 0); - /* disable VMIDSEL and BIASEN */ - snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1, - WM8985_VMIDSEL_MASK | WM8985_BIASEN_MASK, - 0); - snd_soc_write(codec, WM8985_POWER_MANAGEMENT_1, 0); - snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, 0); - snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, 0); - - regcache_mark_dirty(wm8985->regmap); - - regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies), - wm8985->supplies); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#ifdef CONFIG_PM -static int wm8985_suspend(struct snd_soc_codec *codec) -{ - wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8985_resume(struct snd_soc_codec *codec) -{ - wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define wm8985_suspend NULL -#define wm8985_resume NULL -#endif - -static int wm8985_remove(struct snd_soc_codec *codec) -{ - struct wm8985_priv *wm8985; - - wm8985 = snd_soc_codec_get_drvdata(codec); - wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies); - return 0; -} - -static int wm8985_probe(struct snd_soc_codec *codec) -{ - size_t i; - struct wm8985_priv *wm8985; - int ret; - - wm8985 = snd_soc_codec_get_drvdata(codec); - codec->control_data = wm8985->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++) - wm8985->supplies[i].supply = wm8985_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8985->supplies), - wm8985->supplies); - if (ret) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies), - wm8985->supplies); - if (ret) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_reg_get; - } - - ret = wm8985_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err_reg_enable; - } - - /* latch volume update bits */ - for (i = 0; i < ARRAY_SIZE(volume_update_regs); ++i) - snd_soc_update_bits(codec, volume_update_regs[i], - 0x100, 0x100); - /* enable BIASCUT */ - snd_soc_update_bits(codec, WM8985_BIAS_CTRL, WM8985_BIASCUT, - WM8985_BIASCUT); - - wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; - -err_reg_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies), wm8985->supplies); -err_reg_get: - regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies); - return ret; -} - -static const struct snd_soc_dai_ops wm8985_dai_ops = { - .digital_mute = wm8985_dac_mute, - .hw_params = wm8985_hw_params, - .set_fmt = wm8985_set_fmt, - .set_sysclk = wm8985_set_sysclk, - .set_pll = wm8985_set_pll -}; - -#define WM8985_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_driver wm8985_dai = { - .name = "wm8985-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8985_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8985_FORMATS, - }, - .ops = &wm8985_dai_ops, - .symmetric_rates = 1 -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm8985 = { - .probe = wm8985_probe, - .remove = wm8985_remove, - .suspend = wm8985_suspend, - .resume = wm8985_resume, - .set_bias_level = wm8985_set_bias_level, - - .controls = wm8985_snd_controls, - .num_controls = ARRAY_SIZE(wm8985_snd_controls), - .dapm_widgets = wm8985_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8985_dapm_widgets), - .dapm_routes = wm8985_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8985_dapm_routes), -}; - -static const struct regmap_config wm8985_regmap = { - .reg_bits = 7, - .val_bits = 9, - - .max_register = WM8985_MAX_REGISTER, - .writeable_reg = wm8985_writeable, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8985_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8985_reg_defaults), -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8985_spi_probe(struct spi_device *spi) -{ - struct wm8985_priv *wm8985; - int ret; - - wm8985 = devm_kzalloc(&spi->dev, sizeof *wm8985, GFP_KERNEL); - if (!wm8985) - return -ENOMEM; - - spi_set_drvdata(spi, wm8985); - - wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap); - if (IS_ERR(wm8985->regmap)) { - ret = PTR_ERR(wm8985->regmap); - dev_err(&spi->dev, "Failed to allocate register map: %d\n", - ret); - goto err; - } - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8985, &wm8985_dai, 1); - if (ret != 0) - goto err; - - return 0; - -err: - regmap_exit(wm8985->regmap); - return ret; -} - -static int __devexit wm8985_spi_remove(struct spi_device *spi) -{ - struct wm8985_priv *wm8985 = spi_get_drvdata(spi); - - snd_soc_unregister_codec(&spi->dev); - regmap_exit(wm8985->regmap); - - return 0; -} - -static struct spi_driver wm8985_spi_driver = { - .driver = { - .name = "wm8985", - .owner = THIS_MODULE, - }, - .probe = wm8985_spi_probe, - .remove = __devexit_p(wm8985_spi_remove) -}; -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8985_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8985_priv *wm8985; - int ret; - - wm8985 = devm_kzalloc(&i2c->dev, sizeof *wm8985, GFP_KERNEL); - if (!wm8985) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8985); - - wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap); - if (IS_ERR(wm8985->regmap)) { - ret = PTR_ERR(wm8985->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - goto err; - } - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8985, &wm8985_dai, 1); - if (ret != 0) - goto err; - - return 0; - -err: - regmap_exit(wm8985->regmap); - return ret; -} - -static __devexit int wm8985_i2c_remove(struct i2c_client *i2c) -{ - struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c); - - snd_soc_unregister_codec(&i2c->dev); - regmap_exit(wm8985->regmap); - - return 0; -} - -static const struct i2c_device_id wm8985_i2c_id[] = { - { "wm8985", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id); - -static struct i2c_driver wm8985_i2c_driver = { - .driver = { - .name = "wm8985", - .owner = THIS_MODULE, - }, - .probe = wm8985_i2c_probe, - .remove = __devexit_p(wm8985_i2c_remove), - .id_table = wm8985_i2c_id -}; -#endif - -static int __init wm8985_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8985_i2c_driver); - if (ret) { - printk(KERN_ERR "Failed to register wm8985 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8985_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8985 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8985_modinit); - -static void __exit wm8985_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8985_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8985_spi_driver); -#endif -} -module_exit(wm8985_exit); - -MODULE_DESCRIPTION("ASoC WM8985 driver"); -MODULE_AUTHOR("Dimitris Papastamos "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8985.h b/ANDROID_3.4.5/sound/soc/codecs/wm8985.h deleted file mode 100644 index 2e71ff50..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8985.h +++ /dev/null @@ -1,1045 +0,0 @@ -/* - * wm8985.h -- WM8985 ASoC driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8985_H -#define _WM8985_H - -#define WM8985_SOFTWARE_RESET 0x00 -#define WM8985_POWER_MANAGEMENT_1 0x01 -#define WM8985_POWER_MANAGEMENT_2 0x02 -#define WM8985_POWER_MANAGEMENT_3 0x03 -#define WM8985_AUDIO_INTERFACE 0x04 -#define WM8985_COMPANDING_CONTROL 0x05 -#define WM8985_CLOCK_GEN_CONTROL 0x06 -#define WM8985_ADDITIONAL_CONTROL 0x07 -#define WM8985_GPIO_CONTROL 0x08 -#define WM8985_JACK_DETECT_CONTROL_1 0x09 -#define WM8985_DAC_CONTROL 0x0A -#define WM8985_LEFT_DAC_DIGITAL_VOL 0x0B -#define WM8985_RIGHT_DAC_DIGITAL_VOL 0x0C -#define WM8985_JACK_DETECT_CONTROL_2 0x0D -#define WM8985_ADC_CONTROL 0x0E -#define WM8985_LEFT_ADC_DIGITAL_VOL 0x0F -#define WM8985_RIGHT_ADC_DIGITAL_VOL 0x10 -#define WM8985_EQ1_LOW_SHELF 0x12 -#define WM8985_EQ2_PEAK_1 0x13 -#define WM8985_EQ3_PEAK_2 0x14 -#define WM8985_EQ4_PEAK_3 0x15 -#define WM8985_EQ5_HIGH_SHELF 0x16 -#define WM8985_DAC_LIMITER_1 0x18 -#define WM8985_DAC_LIMITER_2 0x19 -#define WM8985_NOTCH_FILTER_1 0x1B -#define WM8985_NOTCH_FILTER_2 0x1C -#define WM8985_NOTCH_FILTER_3 0x1D -#define WM8985_NOTCH_FILTER_4 0x1E -#define WM8985_ALC_CONTROL_1 0x20 -#define WM8985_ALC_CONTROL_2 0x21 -#define WM8985_ALC_CONTROL_3 0x22 -#define WM8985_NOISE_GATE 0x23 -#define WM8985_PLL_N 0x24 -#define WM8985_PLL_K_1 0x25 -#define WM8985_PLL_K_2 0x26 -#define WM8985_PLL_K_3 0x27 -#define WM8985_3D_CONTROL 0x29 -#define WM8985_OUT4_TO_ADC 0x2A -#define WM8985_BEEP_CONTROL 0x2B -#define WM8985_INPUT_CTRL 0x2C -#define WM8985_LEFT_INP_PGA_GAIN_CTRL 0x2D -#define WM8985_RIGHT_INP_PGA_GAIN_CTRL 0x2E -#define WM8985_LEFT_ADC_BOOST_CTRL 0x2F -#define WM8985_RIGHT_ADC_BOOST_CTRL 0x30 -#define WM8985_OUTPUT_CTRL0 0x31 -#define WM8985_LEFT_MIXER_CTRL 0x32 -#define WM8985_RIGHT_MIXER_CTRL 0x33 -#define WM8985_LOUT1_HP_VOLUME_CTRL 0x34 -#define WM8985_ROUT1_HP_VOLUME_CTRL 0x35 -#define WM8985_LOUT2_SPK_VOLUME_CTRL 0x36 -#define WM8985_ROUT2_SPK_VOLUME_CTRL 0x37 -#define WM8985_OUT3_MIXER_CTRL 0x38 -#define WM8985_OUT4_MONO_MIX_CTRL 0x39 -#define WM8985_OUTPUT_CTRL1 0x3C -#define WM8985_BIAS_CTRL 0x3D - -#define WM8985_REGISTER_COUNT 59 -#define WM8985_MAX_REGISTER 0x3F - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM8985_SOFTWARE_RESET_MASK 0x01FF /* SOFTWARE_RESET - [8:0] */ -#define WM8985_SOFTWARE_RESET_SHIFT 0 /* SOFTWARE_RESET - [8:0] */ -#define WM8985_SOFTWARE_RESET_WIDTH 9 /* SOFTWARE_RESET - [8:0] */ - -/* - * R1 (0x01) - Power management 1 - */ -#define WM8985_OUT4MIXEN 0x0080 /* OUT4MIXEN */ -#define WM8985_OUT4MIXEN_MASK 0x0080 /* OUT4MIXEN */ -#define WM8985_OUT4MIXEN_SHIFT 7 /* OUT4MIXEN */ -#define WM8985_OUT4MIXEN_WIDTH 1 /* OUT4MIXEN */ -#define WM8985_OUT3MIXEN 0x0040 /* OUT3MIXEN */ -#define WM8985_OUT3MIXEN_MASK 0x0040 /* OUT3MIXEN */ -#define WM8985_OUT3MIXEN_SHIFT 6 /* OUT3MIXEN */ -#define WM8985_OUT3MIXEN_WIDTH 1 /* OUT3MIXEN */ -#define WM8985_PLLEN 0x0020 /* PLLEN */ -#define WM8985_PLLEN_MASK 0x0020 /* PLLEN */ -#define WM8985_PLLEN_SHIFT 5 /* PLLEN */ -#define WM8985_PLLEN_WIDTH 1 /* PLLEN */ -#define WM8985_MICBEN 0x0010 /* MICBEN */ -#define WM8985_MICBEN_MASK 0x0010 /* MICBEN */ -#define WM8985_MICBEN_SHIFT 4 /* MICBEN */ -#define WM8985_MICBEN_WIDTH 1 /* MICBEN */ -#define WM8985_BIASEN 0x0008 /* BIASEN */ -#define WM8985_BIASEN_MASK 0x0008 /* BIASEN */ -#define WM8985_BIASEN_SHIFT 3 /* BIASEN */ -#define WM8985_BIASEN_WIDTH 1 /* BIASEN */ -#define WM8985_BUFIOEN 0x0004 /* BUFIOEN */ -#define WM8985_BUFIOEN_MASK 0x0004 /* BUFIOEN */ -#define WM8985_BUFIOEN_SHIFT 2 /* BUFIOEN */ -#define WM8985_BUFIOEN_WIDTH 1 /* BUFIOEN */ -#define WM8985_VMIDSEL 0x0003 /* VMIDSEL */ -#define WM8985_VMIDSEL_MASK 0x0003 /* VMIDSEL - [1:0] */ -#define WM8985_VMIDSEL_SHIFT 0 /* VMIDSEL - [1:0] */ -#define WM8985_VMIDSEL_WIDTH 2 /* VMIDSEL - [1:0] */ - -/* - * R2 (0x02) - Power management 2 - */ -#define WM8985_ROUT1EN 0x0100 /* ROUT1EN */ -#define WM8985_ROUT1EN_MASK 0x0100 /* ROUT1EN */ -#define WM8985_ROUT1EN_SHIFT 8 /* ROUT1EN */ -#define WM8985_ROUT1EN_WIDTH 1 /* ROUT1EN */ -#define WM8985_LOUT1EN 0x0080 /* LOUT1EN */ -#define WM8985_LOUT1EN_MASK 0x0080 /* LOUT1EN */ -#define WM8985_LOUT1EN_SHIFT 7 /* LOUT1EN */ -#define WM8985_LOUT1EN_WIDTH 1 /* LOUT1EN */ -#define WM8985_SLEEP 0x0040 /* SLEEP */ -#define WM8985_SLEEP_MASK 0x0040 /* SLEEP */ -#define WM8985_SLEEP_SHIFT 6 /* SLEEP */ -#define WM8985_SLEEP_WIDTH 1 /* SLEEP */ -#define WM8985_BOOSTENR 0x0020 /* BOOSTENR */ -#define WM8985_BOOSTENR_MASK 0x0020 /* BOOSTENR */ -#define WM8985_BOOSTENR_SHIFT 5 /* BOOSTENR */ -#define WM8985_BOOSTENR_WIDTH 1 /* BOOSTENR */ -#define WM8985_BOOSTENL 0x0010 /* BOOSTENL */ -#define WM8985_BOOSTENL_MASK 0x0010 /* BOOSTENL */ -#define WM8985_BOOSTENL_SHIFT 4 /* BOOSTENL */ -#define WM8985_BOOSTENL_WIDTH 1 /* BOOSTENL */ -#define WM8985_INPGAENR 0x0008 /* INPGAENR */ -#define WM8985_INPGAENR_MASK 0x0008 /* INPGAENR */ -#define WM8985_INPGAENR_SHIFT 3 /* INPGAENR */ -#define WM8985_INPGAENR_WIDTH 1 /* INPGAENR */ -#define WM8985_INPPGAENL 0x0004 /* INPPGAENL */ -#define WM8985_INPPGAENL_MASK 0x0004 /* INPPGAENL */ -#define WM8985_INPPGAENL_SHIFT 2 /* INPPGAENL */ -#define WM8985_INPPGAENL_WIDTH 1 /* INPPGAENL */ -#define WM8985_ADCENR 0x0002 /* ADCENR */ -#define WM8985_ADCENR_MASK 0x0002 /* ADCENR */ -#define WM8985_ADCENR_SHIFT 1 /* ADCENR */ -#define WM8985_ADCENR_WIDTH 1 /* ADCENR */ -#define WM8985_ADCENL 0x0001 /* ADCENL */ -#define WM8985_ADCENL_MASK 0x0001 /* ADCENL */ -#define WM8985_ADCENL_SHIFT 0 /* ADCENL */ -#define WM8985_ADCENL_WIDTH 1 /* ADCENL */ - -/* - * R3 (0x03) - Power management 3 - */ -#define WM8985_OUT4EN 0x0100 /* OUT4EN */ -#define WM8985_OUT4EN_MASK 0x0100 /* OUT4EN */ -#define WM8985_OUT4EN_SHIFT 8 /* OUT4EN */ -#define WM8985_OUT4EN_WIDTH 1 /* OUT4EN */ -#define WM8985_OUT3EN 0x0080 /* OUT3EN */ -#define WM8985_OUT3EN_MASK 0x0080 /* OUT3EN */ -#define WM8985_OUT3EN_SHIFT 7 /* OUT3EN */ -#define WM8985_OUT3EN_WIDTH 1 /* OUT3EN */ -#define WM8985_ROUT2EN 0x0040 /* ROUT2EN */ -#define WM8985_ROUT2EN_MASK 0x0040 /* ROUT2EN */ -#define WM8985_ROUT2EN_SHIFT 6 /* ROUT2EN */ -#define WM8985_ROUT2EN_WIDTH 1 /* ROUT2EN */ -#define WM8985_LOUT2EN 0x0020 /* LOUT2EN */ -#define WM8985_LOUT2EN_MASK 0x0020 /* LOUT2EN */ -#define WM8985_LOUT2EN_SHIFT 5 /* LOUT2EN */ -#define WM8985_LOUT2EN_WIDTH 1 /* LOUT2EN */ -#define WM8985_RMIXEN 0x0008 /* RMIXEN */ -#define WM8985_RMIXEN_MASK 0x0008 /* RMIXEN */ -#define WM8985_RMIXEN_SHIFT 3 /* RMIXEN */ -#define WM8985_RMIXEN_WIDTH 1 /* RMIXEN */ -#define WM8985_LMIXEN 0x0004 /* LMIXEN */ -#define WM8985_LMIXEN_MASK 0x0004 /* LMIXEN */ -#define WM8985_LMIXEN_SHIFT 2 /* LMIXEN */ -#define WM8985_LMIXEN_WIDTH 1 /* LMIXEN */ -#define WM8985_DACENR 0x0002 /* DACENR */ -#define WM8985_DACENR_MASK 0x0002 /* DACENR */ -#define WM8985_DACENR_SHIFT 1 /* DACENR */ -#define WM8985_DACENR_WIDTH 1 /* DACENR */ -#define WM8985_DACENL 0x0001 /* DACENL */ -#define WM8985_DACENL_MASK 0x0001 /* DACENL */ -#define WM8985_DACENL_SHIFT 0 /* DACENL */ -#define WM8985_DACENL_WIDTH 1 /* DACENL */ - -/* - * R4 (0x04) - Audio Interface - */ -#define WM8985_BCP 0x0100 /* BCP */ -#define WM8985_BCP_MASK 0x0100 /* BCP */ -#define WM8985_BCP_SHIFT 8 /* BCP */ -#define WM8985_BCP_WIDTH 1 /* BCP */ -#define WM8985_LRP 0x0080 /* LRP */ -#define WM8985_LRP_MASK 0x0080 /* LRP */ -#define WM8985_LRP_SHIFT 7 /* LRP */ -#define WM8985_LRP_WIDTH 1 /* LRP */ -#define WM8985_WL_MASK 0x0060 /* WL - [6:5] */ -#define WM8985_WL_SHIFT 5 /* WL - [6:5] */ -#define WM8985_WL_WIDTH 2 /* WL - [6:5] */ -#define WM8985_FMT_MASK 0x0018 /* FMT - [4:3] */ -#define WM8985_FMT_SHIFT 3 /* FMT - [4:3] */ -#define WM8985_FMT_WIDTH 2 /* FMT - [4:3] */ -#define WM8985_DLRSWAP 0x0004 /* DLRSWAP */ -#define WM8985_DLRSWAP_MASK 0x0004 /* DLRSWAP */ -#define WM8985_DLRSWAP_SHIFT 2 /* DLRSWAP */ -#define WM8985_DLRSWAP_WIDTH 1 /* DLRSWAP */ -#define WM8985_ALRSWAP 0x0002 /* ALRSWAP */ -#define WM8985_ALRSWAP_MASK 0x0002 /* ALRSWAP */ -#define WM8985_ALRSWAP_SHIFT 1 /* ALRSWAP */ -#define WM8985_ALRSWAP_WIDTH 1 /* ALRSWAP */ -#define WM8985_MONO 0x0001 /* MONO */ -#define WM8985_MONO_MASK 0x0001 /* MONO */ -#define WM8985_MONO_SHIFT 0 /* MONO */ -#define WM8985_MONO_WIDTH 1 /* MONO */ - -/* - * R5 (0x05) - Companding control - */ -#define WM8985_WL8 0x0020 /* WL8 */ -#define WM8985_WL8_MASK 0x0020 /* WL8 */ -#define WM8985_WL8_SHIFT 5 /* WL8 */ -#define WM8985_WL8_WIDTH 1 /* WL8 */ -#define WM8985_DAC_COMP_MASK 0x0018 /* DAC_COMP - [4:3] */ -#define WM8985_DAC_COMP_SHIFT 3 /* DAC_COMP - [4:3] */ -#define WM8985_DAC_COMP_WIDTH 2 /* DAC_COMP - [4:3] */ -#define WM8985_ADC_COMP_MASK 0x0006 /* ADC_COMP - [2:1] */ -#define WM8985_ADC_COMP_SHIFT 1 /* ADC_COMP - [2:1] */ -#define WM8985_ADC_COMP_WIDTH 2 /* ADC_COMP - [2:1] */ -#define WM8985_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8985_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8985_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8985_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R6 (0x06) - Clock Gen control - */ -#define WM8985_CLKSEL 0x0100 /* CLKSEL */ -#define WM8985_CLKSEL_MASK 0x0100 /* CLKSEL */ -#define WM8985_CLKSEL_SHIFT 8 /* CLKSEL */ -#define WM8985_CLKSEL_WIDTH 1 /* CLKSEL */ -#define WM8985_MCLKDIV_MASK 0x00E0 /* MCLKDIV - [7:5] */ -#define WM8985_MCLKDIV_SHIFT 5 /* MCLKDIV - [7:5] */ -#define WM8985_MCLKDIV_WIDTH 3 /* MCLKDIV - [7:5] */ -#define WM8985_BCLKDIV_MASK 0x001C /* BCLKDIV - [4:2] */ -#define WM8985_BCLKDIV_SHIFT 2 /* BCLKDIV - [4:2] */ -#define WM8985_BCLKDIV_WIDTH 3 /* BCLKDIV - [4:2] */ -#define WM8985_MS 0x0001 /* MS */ -#define WM8985_MS_MASK 0x0001 /* MS */ -#define WM8985_MS_SHIFT 0 /* MS */ -#define WM8985_MS_WIDTH 1 /* MS */ - -/* - * R7 (0x07) - Additional control - */ -#define WM8985_M128ENB 0x0100 /* M128ENB */ -#define WM8985_M128ENB_MASK 0x0100 /* M128ENB */ -#define WM8985_M128ENB_SHIFT 8 /* M128ENB */ -#define WM8985_M128ENB_WIDTH 1 /* M128ENB */ -#define WM8985_DCLKDIV_MASK 0x00F0 /* DCLKDIV - [7:4] */ -#define WM8985_DCLKDIV_SHIFT 4 /* DCLKDIV - [7:4] */ -#define WM8985_DCLKDIV_WIDTH 4 /* DCLKDIV - [7:4] */ -#define WM8985_SR_MASK 0x000E /* SR - [3:1] */ -#define WM8985_SR_SHIFT 1 /* SR - [3:1] */ -#define WM8985_SR_WIDTH 3 /* SR - [3:1] */ -#define WM8985_SLOWCLKEN 0x0001 /* SLOWCLKEN */ -#define WM8985_SLOWCLKEN_MASK 0x0001 /* SLOWCLKEN */ -#define WM8985_SLOWCLKEN_SHIFT 0 /* SLOWCLKEN */ -#define WM8985_SLOWCLKEN_WIDTH 1 /* SLOWCLKEN */ - -/* - * R8 (0x08) - GPIO Control - */ -#define WM8985_GPIO1GP 0x0100 /* GPIO1GP */ -#define WM8985_GPIO1GP_MASK 0x0100 /* GPIO1GP */ -#define WM8985_GPIO1GP_SHIFT 8 /* GPIO1GP */ -#define WM8985_GPIO1GP_WIDTH 1 /* GPIO1GP */ -#define WM8985_GPIO1GPU 0x0080 /* GPIO1GPU */ -#define WM8985_GPIO1GPU_MASK 0x0080 /* GPIO1GPU */ -#define WM8985_GPIO1GPU_SHIFT 7 /* GPIO1GPU */ -#define WM8985_GPIO1GPU_WIDTH 1 /* GPIO1GPU */ -#define WM8985_GPIO1GPD 0x0040 /* GPIO1GPD */ -#define WM8985_GPIO1GPD_MASK 0x0040 /* GPIO1GPD */ -#define WM8985_GPIO1GPD_SHIFT 6 /* GPIO1GPD */ -#define WM8985_GPIO1GPD_WIDTH 1 /* GPIO1GPD */ -#define WM8985_GPIO1POL 0x0008 /* GPIO1POL */ -#define WM8985_GPIO1POL_MASK 0x0008 /* GPIO1POL */ -#define WM8985_GPIO1POL_SHIFT 3 /* GPIO1POL */ -#define WM8985_GPIO1POL_WIDTH 1 /* GPIO1POL */ -#define WM8985_GPIO1SEL_MASK 0x0007 /* GPIO1SEL - [2:0] */ -#define WM8985_GPIO1SEL_SHIFT 0 /* GPIO1SEL - [2:0] */ -#define WM8985_GPIO1SEL_WIDTH 3 /* GPIO1SEL - [2:0] */ - -/* - * R9 (0x09) - Jack Detect Control 1 - */ -#define WM8985_JD_EN 0x0040 /* JD_EN */ -#define WM8985_JD_EN_MASK 0x0040 /* JD_EN */ -#define WM8985_JD_EN_SHIFT 6 /* JD_EN */ -#define WM8985_JD_EN_WIDTH 1 /* JD_EN */ -#define WM8985_JD_SEL_MASK 0x0030 /* JD_SEL - [5:4] */ -#define WM8985_JD_SEL_SHIFT 4 /* JD_SEL - [5:4] */ -#define WM8985_JD_SEL_WIDTH 2 /* JD_SEL - [5:4] */ - -/* - * R10 (0x0A) - DAC Control - */ -#define WM8985_SOFTMUTE 0x0040 /* SOFTMUTE */ -#define WM8985_SOFTMUTE_MASK 0x0040 /* SOFTMUTE */ -#define WM8985_SOFTMUTE_SHIFT 6 /* SOFTMUTE */ -#define WM8985_SOFTMUTE_WIDTH 1 /* SOFTMUTE */ -#define WM8985_DACOSR128 0x0008 /* DACOSR128 */ -#define WM8985_DACOSR128_MASK 0x0008 /* DACOSR128 */ -#define WM8985_DACOSR128_SHIFT 3 /* DACOSR128 */ -#define WM8985_DACOSR128_WIDTH 1 /* DACOSR128 */ -#define WM8985_AMUTE 0x0004 /* AMUTE */ -#define WM8985_AMUTE_MASK 0x0004 /* AMUTE */ -#define WM8985_AMUTE_SHIFT 2 /* AMUTE */ -#define WM8985_AMUTE_WIDTH 1 /* AMUTE */ -#define WM8985_DACPOLR 0x0002 /* DACPOLR */ -#define WM8985_DACPOLR_MASK 0x0002 /* DACPOLR */ -#define WM8985_DACPOLR_SHIFT 1 /* DACPOLR */ -#define WM8985_DACPOLR_WIDTH 1 /* DACPOLR */ -#define WM8985_DACPOLL 0x0001 /* DACPOLL */ -#define WM8985_DACPOLL_MASK 0x0001 /* DACPOLL */ -#define WM8985_DACPOLL_SHIFT 0 /* DACPOLL */ -#define WM8985_DACPOLL_WIDTH 1 /* DACPOLL */ - -/* - * R11 (0x0B) - Left DAC digital Vol - */ -#define WM8985_DACVU 0x0100 /* DACVU */ -#define WM8985_DACVU_MASK 0x0100 /* DACVU */ -#define WM8985_DACVU_SHIFT 8 /* DACVU */ -#define WM8985_DACVU_WIDTH 1 /* DACVU */ -#define WM8985_DACVOLL_MASK 0x00FF /* DACVOLL - [7:0] */ -#define WM8985_DACVOLL_SHIFT 0 /* DACVOLL - [7:0] */ -#define WM8985_DACVOLL_WIDTH 8 /* DACVOLL - [7:0] */ - -/* - * R12 (0x0C) - Right DAC digital vol - */ -#define WM8985_DACVU 0x0100 /* DACVU */ -#define WM8985_DACVU_MASK 0x0100 /* DACVU */ -#define WM8985_DACVU_SHIFT 8 /* DACVU */ -#define WM8985_DACVU_WIDTH 1 /* DACVU */ -#define WM8985_DACVOLR_MASK 0x00FF /* DACVOLR - [7:0] */ -#define WM8985_DACVOLR_SHIFT 0 /* DACVOLR - [7:0] */ -#define WM8985_DACVOLR_WIDTH 8 /* DACVOLR - [7:0] */ - -/* - * R13 (0x0D) - Jack Detect Control 2 - */ -#define WM8985_JD_EN1_MASK 0x00F0 /* JD_EN1 - [7:4] */ -#define WM8985_JD_EN1_SHIFT 4 /* JD_EN1 - [7:4] */ -#define WM8985_JD_EN1_WIDTH 4 /* JD_EN1 - [7:4] */ -#define WM8985_JD_EN0_MASK 0x000F /* JD_EN0 - [3:0] */ -#define WM8985_JD_EN0_SHIFT 0 /* JD_EN0 - [3:0] */ -#define WM8985_JD_EN0_WIDTH 4 /* JD_EN0 - [3:0] */ - -/* - * R14 (0x0E) - ADC Control - */ -#define WM8985_HPFEN 0x0100 /* HPFEN */ -#define WM8985_HPFEN_MASK 0x0100 /* HPFEN */ -#define WM8985_HPFEN_SHIFT 8 /* HPFEN */ -#define WM8985_HPFEN_WIDTH 1 /* HPFEN */ -#define WM8985_HPFAPP 0x0080 /* HPFAPP */ -#define WM8985_HPFAPP_MASK 0x0080 /* HPFAPP */ -#define WM8985_HPFAPP_SHIFT 7 /* HPFAPP */ -#define WM8985_HPFAPP_WIDTH 1 /* HPFAPP */ -#define WM8985_HPFCUT_MASK 0x0070 /* HPFCUT - [6:4] */ -#define WM8985_HPFCUT_SHIFT 4 /* HPFCUT - [6:4] */ -#define WM8985_HPFCUT_WIDTH 3 /* HPFCUT - [6:4] */ -#define WM8985_ADCOSR128 0x0008 /* ADCOSR128 */ -#define WM8985_ADCOSR128_MASK 0x0008 /* ADCOSR128 */ -#define WM8985_ADCOSR128_SHIFT 3 /* ADCOSR128 */ -#define WM8985_ADCOSR128_WIDTH 1 /* ADCOSR128 */ -#define WM8985_ADCRPOL 0x0002 /* ADCRPOL */ -#define WM8985_ADCRPOL_MASK 0x0002 /* ADCRPOL */ -#define WM8985_ADCRPOL_SHIFT 1 /* ADCRPOL */ -#define WM8985_ADCRPOL_WIDTH 1 /* ADCRPOL */ -#define WM8985_ADCLPOL 0x0001 /* ADCLPOL */ -#define WM8985_ADCLPOL_MASK 0x0001 /* ADCLPOL */ -#define WM8985_ADCLPOL_SHIFT 0 /* ADCLPOL */ -#define WM8985_ADCLPOL_WIDTH 1 /* ADCLPOL */ - -/* - * R15 (0x0F) - Left ADC Digital Vol - */ -#define WM8985_ADCVU 0x0100 /* ADCVU */ -#define WM8985_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8985_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8985_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8985_ADCVOLL_MASK 0x00FF /* ADCVOLL - [7:0] */ -#define WM8985_ADCVOLL_SHIFT 0 /* ADCVOLL - [7:0] */ -#define WM8985_ADCVOLL_WIDTH 8 /* ADCVOLL - [7:0] */ - -/* - * R16 (0x10) - Right ADC Digital Vol - */ -#define WM8985_ADCVU 0x0100 /* ADCVU */ -#define WM8985_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8985_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8985_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8985_ADCVOLR_MASK 0x00FF /* ADCVOLR - [7:0] */ -#define WM8985_ADCVOLR_SHIFT 0 /* ADCVOLR - [7:0] */ -#define WM8985_ADCVOLR_WIDTH 8 /* ADCVOLR - [7:0] */ - -/* - * R18 (0x12) - EQ1 - low shelf - */ -#define WM8985_EQ3DMODE 0x0100 /* EQ3DMODE */ -#define WM8985_EQ3DMODE_MASK 0x0100 /* EQ3DMODE */ -#define WM8985_EQ3DMODE_SHIFT 8 /* EQ3DMODE */ -#define WM8985_EQ3DMODE_WIDTH 1 /* EQ3DMODE */ -#define WM8985_EQ1C_MASK 0x0060 /* EQ1C - [6:5] */ -#define WM8985_EQ1C_SHIFT 5 /* EQ1C - [6:5] */ -#define WM8985_EQ1C_WIDTH 2 /* EQ1C - [6:5] */ -#define WM8985_EQ1G_MASK 0x001F /* EQ1G - [4:0] */ -#define WM8985_EQ1G_SHIFT 0 /* EQ1G - [4:0] */ -#define WM8985_EQ1G_WIDTH 5 /* EQ1G - [4:0] */ - -/* - * R19 (0x13) - EQ2 - peak 1 - */ -#define WM8985_EQ2BW 0x0100 /* EQ2BW */ -#define WM8985_EQ2BW_MASK 0x0100 /* EQ2BW */ -#define WM8985_EQ2BW_SHIFT 8 /* EQ2BW */ -#define WM8985_EQ2BW_WIDTH 1 /* EQ2BW */ -#define WM8985_EQ2C_MASK 0x0060 /* EQ2C - [6:5] */ -#define WM8985_EQ2C_SHIFT 5 /* EQ2C - [6:5] */ -#define WM8985_EQ2C_WIDTH 2 /* EQ2C - [6:5] */ -#define WM8985_EQ2G_MASK 0x001F /* EQ2G - [4:0] */ -#define WM8985_EQ2G_SHIFT 0 /* EQ2G - [4:0] */ -#define WM8985_EQ2G_WIDTH 5 /* EQ2G - [4:0] */ - -/* - * R20 (0x14) - EQ3 - peak 2 - */ -#define WM8985_EQ3BW 0x0100 /* EQ3BW */ -#define WM8985_EQ3BW_MASK 0x0100 /* EQ3BW */ -#define WM8985_EQ3BW_SHIFT 8 /* EQ3BW */ -#define WM8985_EQ3BW_WIDTH 1 /* EQ3BW */ -#define WM8985_EQ3C_MASK 0x0060 /* EQ3C - [6:5] */ -#define WM8985_EQ3C_SHIFT 5 /* EQ3C - [6:5] */ -#define WM8985_EQ3C_WIDTH 2 /* EQ3C - [6:5] */ -#define WM8985_EQ3G_MASK 0x001F /* EQ3G - [4:0] */ -#define WM8985_EQ3G_SHIFT 0 /* EQ3G - [4:0] */ -#define WM8985_EQ3G_WIDTH 5 /* EQ3G - [4:0] */ - -/* - * R21 (0x15) - EQ4 - peak 3 - */ -#define WM8985_EQ4BW 0x0100 /* EQ4BW */ -#define WM8985_EQ4BW_MASK 0x0100 /* EQ4BW */ -#define WM8985_EQ4BW_SHIFT 8 /* EQ4BW */ -#define WM8985_EQ4BW_WIDTH 1 /* EQ4BW */ -#define WM8985_EQ4C_MASK 0x0060 /* EQ4C - [6:5] */ -#define WM8985_EQ4C_SHIFT 5 /* EQ4C - [6:5] */ -#define WM8985_EQ4C_WIDTH 2 /* EQ4C - [6:5] */ -#define WM8985_EQ4G_MASK 0x001F /* EQ4G - [4:0] */ -#define WM8985_EQ4G_SHIFT 0 /* EQ4G - [4:0] */ -#define WM8985_EQ4G_WIDTH 5 /* EQ4G - [4:0] */ - -/* - * R22 (0x16) - EQ5 - high shelf - */ -#define WM8985_EQ5C_MASK 0x0060 /* EQ5C - [6:5] */ -#define WM8985_EQ5C_SHIFT 5 /* EQ5C - [6:5] */ -#define WM8985_EQ5C_WIDTH 2 /* EQ5C - [6:5] */ -#define WM8985_EQ5G_MASK 0x001F /* EQ5G - [4:0] */ -#define WM8985_EQ5G_SHIFT 0 /* EQ5G - [4:0] */ -#define WM8985_EQ5G_WIDTH 5 /* EQ5G - [4:0] */ - -/* - * R24 (0x18) - DAC Limiter 1 - */ -#define WM8985_LIMEN 0x0100 /* LIMEN */ -#define WM8985_LIMEN_MASK 0x0100 /* LIMEN */ -#define WM8985_LIMEN_SHIFT 8 /* LIMEN */ -#define WM8985_LIMEN_WIDTH 1 /* LIMEN */ -#define WM8985_LIMDCY_MASK 0x00F0 /* LIMDCY - [7:4] */ -#define WM8985_LIMDCY_SHIFT 4 /* LIMDCY - [7:4] */ -#define WM8985_LIMDCY_WIDTH 4 /* LIMDCY - [7:4] */ -#define WM8985_LIMATK_MASK 0x000F /* LIMATK - [3:0] */ -#define WM8985_LIMATK_SHIFT 0 /* LIMATK - [3:0] */ -#define WM8985_LIMATK_WIDTH 4 /* LIMATK - [3:0] */ - -/* - * R25 (0x19) - DAC Limiter 2 - */ -#define WM8985_LIMLVL_MASK 0x0070 /* LIMLVL - [6:4] */ -#define WM8985_LIMLVL_SHIFT 4 /* LIMLVL - [6:4] */ -#define WM8985_LIMLVL_WIDTH 3 /* LIMLVL - [6:4] */ -#define WM8985_LIMBOOST_MASK 0x000F /* LIMBOOST - [3:0] */ -#define WM8985_LIMBOOST_SHIFT 0 /* LIMBOOST - [3:0] */ -#define WM8985_LIMBOOST_WIDTH 4 /* LIMBOOST - [3:0] */ - -/* - * R27 (0x1B) - Notch Filter 1 - */ -#define WM8985_NFU 0x0100 /* NFU */ -#define WM8985_NFU_MASK 0x0100 /* NFU */ -#define WM8985_NFU_SHIFT 8 /* NFU */ -#define WM8985_NFU_WIDTH 1 /* NFU */ -#define WM8985_NFEN 0x0080 /* NFEN */ -#define WM8985_NFEN_MASK 0x0080 /* NFEN */ -#define WM8985_NFEN_SHIFT 7 /* NFEN */ -#define WM8985_NFEN_WIDTH 1 /* NFEN */ -#define WM8985_NFA0_13_7_MASK 0x007F /* NFA0(13:7) - [6:0] */ -#define WM8985_NFA0_13_7_SHIFT 0 /* NFA0(13:7) - [6:0] */ -#define WM8985_NFA0_13_7_WIDTH 7 /* NFA0(13:7) - [6:0] */ - -/* - * R28 (0x1C) - Notch Filter 2 - */ -#define WM8985_NFU 0x0100 /* NFU */ -#define WM8985_NFU_MASK 0x0100 /* NFU */ -#define WM8985_NFU_SHIFT 8 /* NFU */ -#define WM8985_NFU_WIDTH 1 /* NFU */ -#define WM8985_NFA0_6_0_MASK 0x007F /* NFA0(6:0) - [6:0] */ -#define WM8985_NFA0_6_0_SHIFT 0 /* NFA0(6:0) - [6:0] */ -#define WM8985_NFA0_6_0_WIDTH 7 /* NFA0(6:0) - [6:0] */ - -/* - * R29 (0x1D) - Notch Filter 3 - */ -#define WM8985_NFU 0x0100 /* NFU */ -#define WM8985_NFU_MASK 0x0100 /* NFU */ -#define WM8985_NFU_SHIFT 8 /* NFU */ -#define WM8985_NFU_WIDTH 1 /* NFU */ -#define WM8985_NFA1_13_7_MASK 0x007F /* NFA1(13:7) - [6:0] */ -#define WM8985_NFA1_13_7_SHIFT 0 /* NFA1(13:7) - [6:0] */ -#define WM8985_NFA1_13_7_WIDTH 7 /* NFA1(13:7) - [6:0] */ - -/* - * R30 (0x1E) - Notch Filter 4 - */ -#define WM8985_NFU 0x0100 /* NFU */ -#define WM8985_NFU_MASK 0x0100 /* NFU */ -#define WM8985_NFU_SHIFT 8 /* NFU */ -#define WM8985_NFU_WIDTH 1 /* NFU */ -#define WM8985_NFA1_6_0_MASK 0x007F /* NFA1(6:0) - [6:0] */ -#define WM8985_NFA1_6_0_SHIFT 0 /* NFA1(6:0) - [6:0] */ -#define WM8985_NFA1_6_0_WIDTH 7 /* NFA1(6:0) - [6:0] */ - -/* - * R32 (0x20) - ALC control 1 - */ -#define WM8985_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */ -#define WM8985_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */ -#define WM8985_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */ -#define WM8985_ALCMAX_MASK 0x0038 /* ALCMAX - [5:3] */ -#define WM8985_ALCMAX_SHIFT 3 /* ALCMAX - [5:3] */ -#define WM8985_ALCMAX_WIDTH 3 /* ALCMAX - [5:3] */ -#define WM8985_ALCMIN_MASK 0x0007 /* ALCMIN - [2:0] */ -#define WM8985_ALCMIN_SHIFT 0 /* ALCMIN - [2:0] */ -#define WM8985_ALCMIN_WIDTH 3 /* ALCMIN - [2:0] */ - -/* - * R33 (0x21) - ALC control 2 - */ -#define WM8985_ALCHLD_MASK 0x00F0 /* ALCHLD - [7:4] */ -#define WM8985_ALCHLD_SHIFT 4 /* ALCHLD - [7:4] */ -#define WM8985_ALCHLD_WIDTH 4 /* ALCHLD - [7:4] */ -#define WM8985_ALCLVL_MASK 0x000F /* ALCLVL - [3:0] */ -#define WM8985_ALCLVL_SHIFT 0 /* ALCLVL - [3:0] */ -#define WM8985_ALCLVL_WIDTH 4 /* ALCLVL - [3:0] */ - -/* - * R34 (0x22) - ALC control 3 - */ -#define WM8985_ALCMODE 0x0100 /* ALCMODE */ -#define WM8985_ALCMODE_MASK 0x0100 /* ALCMODE */ -#define WM8985_ALCMODE_SHIFT 8 /* ALCMODE */ -#define WM8985_ALCMODE_WIDTH 1 /* ALCMODE */ -#define WM8985_ALCDCY_MASK 0x00F0 /* ALCDCY - [7:4] */ -#define WM8985_ALCDCY_SHIFT 4 /* ALCDCY - [7:4] */ -#define WM8985_ALCDCY_WIDTH 4 /* ALCDCY - [7:4] */ -#define WM8985_ALCATK_MASK 0x000F /* ALCATK - [3:0] */ -#define WM8985_ALCATK_SHIFT 0 /* ALCATK - [3:0] */ -#define WM8985_ALCATK_WIDTH 4 /* ALCATK - [3:0] */ - -/* - * R35 (0x23) - Noise Gate - */ -#define WM8985_NGEN 0x0008 /* NGEN */ -#define WM8985_NGEN_MASK 0x0008 /* NGEN */ -#define WM8985_NGEN_SHIFT 3 /* NGEN */ -#define WM8985_NGEN_WIDTH 1 /* NGEN */ -#define WM8985_NGTH_MASK 0x0007 /* NGTH - [2:0] */ -#define WM8985_NGTH_SHIFT 0 /* NGTH - [2:0] */ -#define WM8985_NGTH_WIDTH 3 /* NGTH - [2:0] */ - -/* - * R36 (0x24) - PLL N - */ -#define WM8985_PLL_PRESCALE 0x0010 /* PLL_PRESCALE */ -#define WM8985_PLL_PRESCALE_MASK 0x0010 /* PLL_PRESCALE */ -#define WM8985_PLL_PRESCALE_SHIFT 4 /* PLL_PRESCALE */ -#define WM8985_PLL_PRESCALE_WIDTH 1 /* PLL_PRESCALE */ -#define WM8985_PLLN_MASK 0x000F /* PLLN - [3:0] */ -#define WM8985_PLLN_SHIFT 0 /* PLLN - [3:0] */ -#define WM8985_PLLN_WIDTH 4 /* PLLN - [3:0] */ - -/* - * R37 (0x25) - PLL K 1 - */ -#define WM8985_PLLK_23_18_MASK 0x003F /* PLLK(23:18) - [5:0] */ -#define WM8985_PLLK_23_18_SHIFT 0 /* PLLK(23:18) - [5:0] */ -#define WM8985_PLLK_23_18_WIDTH 6 /* PLLK(23:18) - [5:0] */ - -/* - * R38 (0x26) - PLL K 2 - */ -#define WM8985_PLLK_17_9_MASK 0x01FF /* PLLK(17:9) - [8:0] */ -#define WM8985_PLLK_17_9_SHIFT 0 /* PLLK(17:9) - [8:0] */ -#define WM8985_PLLK_17_9_WIDTH 9 /* PLLK(17:9) - [8:0] */ - -/* - * R39 (0x27) - PLL K 3 - */ -#define WM8985_PLLK_8_0_MASK 0x01FF /* PLLK(8:0) - [8:0] */ -#define WM8985_PLLK_8_0_SHIFT 0 /* PLLK(8:0) - [8:0] */ -#define WM8985_PLLK_8_0_WIDTH 9 /* PLLK(8:0) - [8:0] */ - -/* - * R41 (0x29) - 3D control - */ -#define WM8985_DEPTH3D_MASK 0x000F /* DEPTH3D - [3:0] */ -#define WM8985_DEPTH3D_SHIFT 0 /* DEPTH3D - [3:0] */ -#define WM8985_DEPTH3D_WIDTH 4 /* DEPTH3D - [3:0] */ - -/* - * R42 (0x2A) - OUT4 to ADC - */ -#define WM8985_OUT4_2ADCVOL_MASK 0x01C0 /* OUT4_2ADCVOL - [8:6] */ -#define WM8985_OUT4_2ADCVOL_SHIFT 6 /* OUT4_2ADCVOL - [8:6] */ -#define WM8985_OUT4_2ADCVOL_WIDTH 3 /* OUT4_2ADCVOL - [8:6] */ -#define WM8985_OUT4_2LNR 0x0020 /* OUT4_2LNR */ -#define WM8985_OUT4_2LNR_MASK 0x0020 /* OUT4_2LNR */ -#define WM8985_OUT4_2LNR_SHIFT 5 /* OUT4_2LNR */ -#define WM8985_OUT4_2LNR_WIDTH 1 /* OUT4_2LNR */ -#define WM8985_POBCTRL 0x0004 /* POBCTRL */ -#define WM8985_POBCTRL_MASK 0x0004 /* POBCTRL */ -#define WM8985_POBCTRL_SHIFT 2 /* POBCTRL */ -#define WM8985_POBCTRL_WIDTH 1 /* POBCTRL */ -#define WM8985_DELEN 0x0002 /* DELEN */ -#define WM8985_DELEN_MASK 0x0002 /* DELEN */ -#define WM8985_DELEN_SHIFT 1 /* DELEN */ -#define WM8985_DELEN_WIDTH 1 /* DELEN */ -#define WM8985_OUT1DEL 0x0001 /* OUT1DEL */ -#define WM8985_OUT1DEL_MASK 0x0001 /* OUT1DEL */ -#define WM8985_OUT1DEL_SHIFT 0 /* OUT1DEL */ -#define WM8985_OUT1DEL_WIDTH 1 /* OUT1DEL */ - -/* - * R43 (0x2B) - Beep control - */ -#define WM8985_BYPL2RMIX 0x0100 /* BYPL2RMIX */ -#define WM8985_BYPL2RMIX_MASK 0x0100 /* BYPL2RMIX */ -#define WM8985_BYPL2RMIX_SHIFT 8 /* BYPL2RMIX */ -#define WM8985_BYPL2RMIX_WIDTH 1 /* BYPL2RMIX */ -#define WM8985_BYPR2LMIX 0x0080 /* BYPR2LMIX */ -#define WM8985_BYPR2LMIX_MASK 0x0080 /* BYPR2LMIX */ -#define WM8985_BYPR2LMIX_SHIFT 7 /* BYPR2LMIX */ -#define WM8985_BYPR2LMIX_WIDTH 1 /* BYPR2LMIX */ -#define WM8985_MUTERPGA2INV 0x0020 /* MUTERPGA2INV */ -#define WM8985_MUTERPGA2INV_MASK 0x0020 /* MUTERPGA2INV */ -#define WM8985_MUTERPGA2INV_SHIFT 5 /* MUTERPGA2INV */ -#define WM8985_MUTERPGA2INV_WIDTH 1 /* MUTERPGA2INV */ -#define WM8985_INVROUT2 0x0010 /* INVROUT2 */ -#define WM8985_INVROUT2_MASK 0x0010 /* INVROUT2 */ -#define WM8985_INVROUT2_SHIFT 4 /* INVROUT2 */ -#define WM8985_INVROUT2_WIDTH 1 /* INVROUT2 */ -#define WM8985_BEEPVOL_MASK 0x000E /* BEEPVOL - [3:1] */ -#define WM8985_BEEPVOL_SHIFT 1 /* BEEPVOL - [3:1] */ -#define WM8985_BEEPVOL_WIDTH 3 /* BEEPVOL - [3:1] */ -#define WM8985_BEEPEN 0x0001 /* BEEPEN */ -#define WM8985_BEEPEN_MASK 0x0001 /* BEEPEN */ -#define WM8985_BEEPEN_SHIFT 0 /* BEEPEN */ -#define WM8985_BEEPEN_WIDTH 1 /* BEEPEN */ - -/* - * R44 (0x2C) - Input ctrl - */ -#define WM8985_MBVSEL 0x0100 /* MBVSEL */ -#define WM8985_MBVSEL_MASK 0x0100 /* MBVSEL */ -#define WM8985_MBVSEL_SHIFT 8 /* MBVSEL */ -#define WM8985_MBVSEL_WIDTH 1 /* MBVSEL */ -#define WM8985_R2_2INPPGA 0x0040 /* R2_2INPPGA */ -#define WM8985_R2_2INPPGA_MASK 0x0040 /* R2_2INPPGA */ -#define WM8985_R2_2INPPGA_SHIFT 6 /* R2_2INPPGA */ -#define WM8985_R2_2INPPGA_WIDTH 1 /* R2_2INPPGA */ -#define WM8985_RIN2INPPGA 0x0020 /* RIN2INPPGA */ -#define WM8985_RIN2INPPGA_MASK 0x0020 /* RIN2INPPGA */ -#define WM8985_RIN2INPPGA_SHIFT 5 /* RIN2INPPGA */ -#define WM8985_RIN2INPPGA_WIDTH 1 /* RIN2INPPGA */ -#define WM8985_RIP2INPPGA 0x0010 /* RIP2INPPGA */ -#define WM8985_RIP2INPPGA_MASK 0x0010 /* RIP2INPPGA */ -#define WM8985_RIP2INPPGA_SHIFT 4 /* RIP2INPPGA */ -#define WM8985_RIP2INPPGA_WIDTH 1 /* RIP2INPPGA */ -#define WM8985_L2_2INPPGA 0x0004 /* L2_2INPPGA */ -#define WM8985_L2_2INPPGA_MASK 0x0004 /* L2_2INPPGA */ -#define WM8985_L2_2INPPGA_SHIFT 2 /* L2_2INPPGA */ -#define WM8985_L2_2INPPGA_WIDTH 1 /* L2_2INPPGA */ -#define WM8985_LIN2INPPGA 0x0002 /* LIN2INPPGA */ -#define WM8985_LIN2INPPGA_MASK 0x0002 /* LIN2INPPGA */ -#define WM8985_LIN2INPPGA_SHIFT 1 /* LIN2INPPGA */ -#define WM8985_LIN2INPPGA_WIDTH 1 /* LIN2INPPGA */ -#define WM8985_LIP2INPPGA 0x0001 /* LIP2INPPGA */ -#define WM8985_LIP2INPPGA_MASK 0x0001 /* LIP2INPPGA */ -#define WM8985_LIP2INPPGA_SHIFT 0 /* LIP2INPPGA */ -#define WM8985_LIP2INPPGA_WIDTH 1 /* LIP2INPPGA */ - -/* - * R45 (0x2D) - Left INP PGA gain ctrl - */ -#define WM8985_INPGAVU 0x0100 /* INPGAVU */ -#define WM8985_INPGAVU_MASK 0x0100 /* INPGAVU */ -#define WM8985_INPGAVU_SHIFT 8 /* INPGAVU */ -#define WM8985_INPGAVU_WIDTH 1 /* INPGAVU */ -#define WM8985_INPPGAZCL 0x0080 /* INPPGAZCL */ -#define WM8985_INPPGAZCL_MASK 0x0080 /* INPPGAZCL */ -#define WM8985_INPPGAZCL_SHIFT 7 /* INPPGAZCL */ -#define WM8985_INPPGAZCL_WIDTH 1 /* INPPGAZCL */ -#define WM8985_INPPGAMUTEL 0x0040 /* INPPGAMUTEL */ -#define WM8985_INPPGAMUTEL_MASK 0x0040 /* INPPGAMUTEL */ -#define WM8985_INPPGAMUTEL_SHIFT 6 /* INPPGAMUTEL */ -#define WM8985_INPPGAMUTEL_WIDTH 1 /* INPPGAMUTEL */ -#define WM8985_INPPGAVOLL_MASK 0x003F /* INPPGAVOLL - [5:0] */ -#define WM8985_INPPGAVOLL_SHIFT 0 /* INPPGAVOLL - [5:0] */ -#define WM8985_INPPGAVOLL_WIDTH 6 /* INPPGAVOLL - [5:0] */ - -/* - * R46 (0x2E) - Right INP PGA gain ctrl - */ -#define WM8985_INPGAVU 0x0100 /* INPGAVU */ -#define WM8985_INPGAVU_MASK 0x0100 /* INPGAVU */ -#define WM8985_INPGAVU_SHIFT 8 /* INPGAVU */ -#define WM8985_INPGAVU_WIDTH 1 /* INPGAVU */ -#define WM8985_INPPGAZCR 0x0080 /* INPPGAZCR */ -#define WM8985_INPPGAZCR_MASK 0x0080 /* INPPGAZCR */ -#define WM8985_INPPGAZCR_SHIFT 7 /* INPPGAZCR */ -#define WM8985_INPPGAZCR_WIDTH 1 /* INPPGAZCR */ -#define WM8985_INPPGAMUTER 0x0040 /* INPPGAMUTER */ -#define WM8985_INPPGAMUTER_MASK 0x0040 /* INPPGAMUTER */ -#define WM8985_INPPGAMUTER_SHIFT 6 /* INPPGAMUTER */ -#define WM8985_INPPGAMUTER_WIDTH 1 /* INPPGAMUTER */ -#define WM8985_INPPGAVOLR_MASK 0x003F /* INPPGAVOLR - [5:0] */ -#define WM8985_INPPGAVOLR_SHIFT 0 /* INPPGAVOLR - [5:0] */ -#define WM8985_INPPGAVOLR_WIDTH 6 /* INPPGAVOLR - [5:0] */ - -/* - * R47 (0x2F) - Left ADC BOOST ctrl - */ -#define WM8985_PGABOOSTL 0x0100 /* PGABOOSTL */ -#define WM8985_PGABOOSTL_MASK 0x0100 /* PGABOOSTL */ -#define WM8985_PGABOOSTL_SHIFT 8 /* PGABOOSTL */ -#define WM8985_PGABOOSTL_WIDTH 1 /* PGABOOSTL */ -#define WM8985_L2_2BOOSTVOL_MASK 0x0070 /* L2_2BOOSTVOL - [6:4] */ -#define WM8985_L2_2BOOSTVOL_SHIFT 4 /* L2_2BOOSTVOL - [6:4] */ -#define WM8985_L2_2BOOSTVOL_WIDTH 3 /* L2_2BOOSTVOL - [6:4] */ -#define WM8985_AUXL2BOOSTVOL_MASK 0x0007 /* AUXL2BOOSTVOL - [2:0] */ -#define WM8985_AUXL2BOOSTVOL_SHIFT 0 /* AUXL2BOOSTVOL - [2:0] */ -#define WM8985_AUXL2BOOSTVOL_WIDTH 3 /* AUXL2BOOSTVOL - [2:0] */ - -/* - * R48 (0x30) - Right ADC BOOST ctrl - */ -#define WM8985_PGABOOSTR 0x0100 /* PGABOOSTR */ -#define WM8985_PGABOOSTR_MASK 0x0100 /* PGABOOSTR */ -#define WM8985_PGABOOSTR_SHIFT 8 /* PGABOOSTR */ -#define WM8985_PGABOOSTR_WIDTH 1 /* PGABOOSTR */ -#define WM8985_R2_2BOOSTVOL_MASK 0x0070 /* R2_2BOOSTVOL - [6:4] */ -#define WM8985_R2_2BOOSTVOL_SHIFT 4 /* R2_2BOOSTVOL - [6:4] */ -#define WM8985_R2_2BOOSTVOL_WIDTH 3 /* R2_2BOOSTVOL - [6:4] */ -#define WM8985_AUXR2BOOSTVOL_MASK 0x0007 /* AUXR2BOOSTVOL - [2:0] */ -#define WM8985_AUXR2BOOSTVOL_SHIFT 0 /* AUXR2BOOSTVOL - [2:0] */ -#define WM8985_AUXR2BOOSTVOL_WIDTH 3 /* AUXR2BOOSTVOL - [2:0] */ - -/* - * R49 (0x31) - Output ctrl - */ -#define WM8985_DACL2RMIX 0x0040 /* DACL2RMIX */ -#define WM8985_DACL2RMIX_MASK 0x0040 /* DACL2RMIX */ -#define WM8985_DACL2RMIX_SHIFT 6 /* DACL2RMIX */ -#define WM8985_DACL2RMIX_WIDTH 1 /* DACL2RMIX */ -#define WM8985_DACR2LMIX 0x0020 /* DACR2LMIX */ -#define WM8985_DACR2LMIX_MASK 0x0020 /* DACR2LMIX */ -#define WM8985_DACR2LMIX_SHIFT 5 /* DACR2LMIX */ -#define WM8985_DACR2LMIX_WIDTH 1 /* DACR2LMIX */ -#define WM8985_OUT4BOOST 0x0010 /* OUT4BOOST */ -#define WM8985_OUT4BOOST_MASK 0x0010 /* OUT4BOOST */ -#define WM8985_OUT4BOOST_SHIFT 4 /* OUT4BOOST */ -#define WM8985_OUT4BOOST_WIDTH 1 /* OUT4BOOST */ -#define WM8985_OUT3BOOST 0x0008 /* OUT3BOOST */ -#define WM8985_OUT3BOOST_MASK 0x0008 /* OUT3BOOST */ -#define WM8985_OUT3BOOST_SHIFT 3 /* OUT3BOOST */ -#define WM8985_OUT3BOOST_WIDTH 1 /* OUT3BOOST */ -#define WM8985_TSOPCTRL 0x0004 /* TSOPCTRL */ -#define WM8985_TSOPCTRL_MASK 0x0004 /* TSOPCTRL */ -#define WM8985_TSOPCTRL_SHIFT 2 /* TSOPCTRL */ -#define WM8985_TSOPCTRL_WIDTH 1 /* TSOPCTRL */ -#define WM8985_TSDEN 0x0002 /* TSDEN */ -#define WM8985_TSDEN_MASK 0x0002 /* TSDEN */ -#define WM8985_TSDEN_SHIFT 1 /* TSDEN */ -#define WM8985_TSDEN_WIDTH 1 /* TSDEN */ -#define WM8985_VROI 0x0001 /* VROI */ -#define WM8985_VROI_MASK 0x0001 /* VROI */ -#define WM8985_VROI_SHIFT 0 /* VROI */ -#define WM8985_VROI_WIDTH 1 /* VROI */ - -/* - * R50 (0x32) - Left mixer ctrl - */ -#define WM8985_AUXLMIXVOL_MASK 0x01C0 /* AUXLMIXVOL - [8:6] */ -#define WM8985_AUXLMIXVOL_SHIFT 6 /* AUXLMIXVOL - [8:6] */ -#define WM8985_AUXLMIXVOL_WIDTH 3 /* AUXLMIXVOL - [8:6] */ -#define WM8985_AUXL2LMIX 0x0020 /* AUXL2LMIX */ -#define WM8985_AUXL2LMIX_MASK 0x0020 /* AUXL2LMIX */ -#define WM8985_AUXL2LMIX_SHIFT 5 /* AUXL2LMIX */ -#define WM8985_AUXL2LMIX_WIDTH 1 /* AUXL2LMIX */ -#define WM8985_BYPLMIXVOL_MASK 0x001C /* BYPLMIXVOL - [4:2] */ -#define WM8985_BYPLMIXVOL_SHIFT 2 /* BYPLMIXVOL - [4:2] */ -#define WM8985_BYPLMIXVOL_WIDTH 3 /* BYPLMIXVOL - [4:2] */ -#define WM8985_BYPL2LMIX 0x0002 /* BYPL2LMIX */ -#define WM8985_BYPL2LMIX_MASK 0x0002 /* BYPL2LMIX */ -#define WM8985_BYPL2LMIX_SHIFT 1 /* BYPL2LMIX */ -#define WM8985_BYPL2LMIX_WIDTH 1 /* BYPL2LMIX */ -#define WM8985_DACL2LMIX 0x0001 /* DACL2LMIX */ -#define WM8985_DACL2LMIX_MASK 0x0001 /* DACL2LMIX */ -#define WM8985_DACL2LMIX_SHIFT 0 /* DACL2LMIX */ -#define WM8985_DACL2LMIX_WIDTH 1 /* DACL2LMIX */ - -/* - * R51 (0x33) - Right mixer ctrl - */ -#define WM8985_AUXRMIXVOL_MASK 0x01C0 /* AUXRMIXVOL - [8:6] */ -#define WM8985_AUXRMIXVOL_SHIFT 6 /* AUXRMIXVOL - [8:6] */ -#define WM8985_AUXRMIXVOL_WIDTH 3 /* AUXRMIXVOL - [8:6] */ -#define WM8985_AUXR2RMIX 0x0020 /* AUXR2RMIX */ -#define WM8985_AUXR2RMIX_MASK 0x0020 /* AUXR2RMIX */ -#define WM8985_AUXR2RMIX_SHIFT 5 /* AUXR2RMIX */ -#define WM8985_AUXR2RMIX_WIDTH 1 /* AUXR2RMIX */ -#define WM8985_BYPRMIXVOL_MASK 0x001C /* BYPRMIXVOL - [4:2] */ -#define WM8985_BYPRMIXVOL_SHIFT 2 /* BYPRMIXVOL - [4:2] */ -#define WM8985_BYPRMIXVOL_WIDTH 3 /* BYPRMIXVOL - [4:2] */ -#define WM8985_BYPR2RMIX 0x0002 /* BYPR2RMIX */ -#define WM8985_BYPR2RMIX_MASK 0x0002 /* BYPR2RMIX */ -#define WM8985_BYPR2RMIX_SHIFT 1 /* BYPR2RMIX */ -#define WM8985_BYPR2RMIX_WIDTH 1 /* BYPR2RMIX */ -#define WM8985_DACR2RMIX 0x0001 /* DACR2RMIX */ -#define WM8985_DACR2RMIX_MASK 0x0001 /* DACR2RMIX */ -#define WM8985_DACR2RMIX_SHIFT 0 /* DACR2RMIX */ -#define WM8985_DACR2RMIX_WIDTH 1 /* DACR2RMIX */ - -/* - * R52 (0x34) - LOUT1 (HP) volume ctrl - */ -#define WM8985_OUT1VU 0x0100 /* OUT1VU */ -#define WM8985_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8985_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8985_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8985_LOUT1ZC 0x0080 /* LOUT1ZC */ -#define WM8985_LOUT1ZC_MASK 0x0080 /* LOUT1ZC */ -#define WM8985_LOUT1ZC_SHIFT 7 /* LOUT1ZC */ -#define WM8985_LOUT1ZC_WIDTH 1 /* LOUT1ZC */ -#define WM8985_LOUT1MUTE 0x0040 /* LOUT1MUTE */ -#define WM8985_LOUT1MUTE_MASK 0x0040 /* LOUT1MUTE */ -#define WM8985_LOUT1MUTE_SHIFT 6 /* LOUT1MUTE */ -#define WM8985_LOUT1MUTE_WIDTH 1 /* LOUT1MUTE */ -#define WM8985_LOUT1VOL_MASK 0x003F /* LOUT1VOL - [5:0] */ -#define WM8985_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [5:0] */ -#define WM8985_LOUT1VOL_WIDTH 6 /* LOUT1VOL - [5:0] */ - -/* - * R53 (0x35) - ROUT1 (HP) volume ctrl - */ -#define WM8985_OUT1VU 0x0100 /* OUT1VU */ -#define WM8985_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8985_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8985_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8985_ROUT1ZC 0x0080 /* ROUT1ZC */ -#define WM8985_ROUT1ZC_MASK 0x0080 /* ROUT1ZC */ -#define WM8985_ROUT1ZC_SHIFT 7 /* ROUT1ZC */ -#define WM8985_ROUT1ZC_WIDTH 1 /* ROUT1ZC */ -#define WM8985_ROUT1MUTE 0x0040 /* ROUT1MUTE */ -#define WM8985_ROUT1MUTE_MASK 0x0040 /* ROUT1MUTE */ -#define WM8985_ROUT1MUTE_SHIFT 6 /* ROUT1MUTE */ -#define WM8985_ROUT1MUTE_WIDTH 1 /* ROUT1MUTE */ -#define WM8985_ROUT1VOL_MASK 0x003F /* ROUT1VOL - [5:0] */ -#define WM8985_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [5:0] */ -#define WM8985_ROUT1VOL_WIDTH 6 /* ROUT1VOL - [5:0] */ - -/* - * R54 (0x36) - LOUT2 (SPK) volume ctrl - */ -#define WM8985_OUT2VU 0x0100 /* OUT2VU */ -#define WM8985_OUT2VU_MASK 0x0100 /* OUT2VU */ -#define WM8985_OUT2VU_SHIFT 8 /* OUT2VU */ -#define WM8985_OUT2VU_WIDTH 1 /* OUT2VU */ -#define WM8985_LOUT2ZC 0x0080 /* LOUT2ZC */ -#define WM8985_LOUT2ZC_MASK 0x0080 /* LOUT2ZC */ -#define WM8985_LOUT2ZC_SHIFT 7 /* LOUT2ZC */ -#define WM8985_LOUT2ZC_WIDTH 1 /* LOUT2ZC */ -#define WM8985_LOUT2MUTE 0x0040 /* LOUT2MUTE */ -#define WM8985_LOUT2MUTE_MASK 0x0040 /* LOUT2MUTE */ -#define WM8985_LOUT2MUTE_SHIFT 6 /* LOUT2MUTE */ -#define WM8985_LOUT2MUTE_WIDTH 1 /* LOUT2MUTE */ -#define WM8985_LOUT2VOL_MASK 0x003F /* LOUT2VOL - [5:0] */ -#define WM8985_LOUT2VOL_SHIFT 0 /* LOUT2VOL - [5:0] */ -#define WM8985_LOUT2VOL_WIDTH 6 /* LOUT2VOL - [5:0] */ - -/* - * R55 (0x37) - ROUT2 (SPK) volume ctrl - */ -#define WM8985_OUT2VU 0x0100 /* OUT2VU */ -#define WM8985_OUT2VU_MASK 0x0100 /* OUT2VU */ -#define WM8985_OUT2VU_SHIFT 8 /* OUT2VU */ -#define WM8985_OUT2VU_WIDTH 1 /* OUT2VU */ -#define WM8985_ROUT2ZC 0x0080 /* ROUT2ZC */ -#define WM8985_ROUT2ZC_MASK 0x0080 /* ROUT2ZC */ -#define WM8985_ROUT2ZC_SHIFT 7 /* ROUT2ZC */ -#define WM8985_ROUT2ZC_WIDTH 1 /* ROUT2ZC */ -#define WM8985_ROUT2MUTE 0x0040 /* ROUT2MUTE */ -#define WM8985_ROUT2MUTE_MASK 0x0040 /* ROUT2MUTE */ -#define WM8985_ROUT2MUTE_SHIFT 6 /* ROUT2MUTE */ -#define WM8985_ROUT2MUTE_WIDTH 1 /* ROUT2MUTE */ -#define WM8985_ROUT2VOL_MASK 0x003F /* ROUT2VOL - [5:0] */ -#define WM8985_ROUT2VOL_SHIFT 0 /* ROUT2VOL - [5:0] */ -#define WM8985_ROUT2VOL_WIDTH 6 /* ROUT2VOL - [5:0] */ - -/* - * R56 (0x38) - OUT3 mixer ctrl - */ -#define WM8985_OUT3MUTE 0x0040 /* OUT3MUTE */ -#define WM8985_OUT3MUTE_MASK 0x0040 /* OUT3MUTE */ -#define WM8985_OUT3MUTE_SHIFT 6 /* OUT3MUTE */ -#define WM8985_OUT3MUTE_WIDTH 1 /* OUT3MUTE */ -#define WM8985_OUT4_2OUT3 0x0008 /* OUT4_2OUT3 */ -#define WM8985_OUT4_2OUT3_MASK 0x0008 /* OUT4_2OUT3 */ -#define WM8985_OUT4_2OUT3_SHIFT 3 /* OUT4_2OUT3 */ -#define WM8985_OUT4_2OUT3_WIDTH 1 /* OUT4_2OUT3 */ -#define WM8985_BYPL2OUT3 0x0004 /* BYPL2OUT3 */ -#define WM8985_BYPL2OUT3_MASK 0x0004 /* BYPL2OUT3 */ -#define WM8985_BYPL2OUT3_SHIFT 2 /* BYPL2OUT3 */ -#define WM8985_BYPL2OUT3_WIDTH 1 /* BYPL2OUT3 */ -#define WM8985_LMIX2OUT3 0x0002 /* LMIX2OUT3 */ -#define WM8985_LMIX2OUT3_MASK 0x0002 /* LMIX2OUT3 */ -#define WM8985_LMIX2OUT3_SHIFT 1 /* LMIX2OUT3 */ -#define WM8985_LMIX2OUT3_WIDTH 1 /* LMIX2OUT3 */ -#define WM8985_LDAC2OUT3 0x0001 /* LDAC2OUT3 */ -#define WM8985_LDAC2OUT3_MASK 0x0001 /* LDAC2OUT3 */ -#define WM8985_LDAC2OUT3_SHIFT 0 /* LDAC2OUT3 */ -#define WM8985_LDAC2OUT3_WIDTH 1 /* LDAC2OUT3 */ - -/* - * R57 (0x39) - OUT4 (MONO) mix ctrl - */ -#define WM8985_OUT3_2OUT4 0x0080 /* OUT3_2OUT4 */ -#define WM8985_OUT3_2OUT4_MASK 0x0080 /* OUT3_2OUT4 */ -#define WM8985_OUT3_2OUT4_SHIFT 7 /* OUT3_2OUT4 */ -#define WM8985_OUT3_2OUT4_WIDTH 1 /* OUT3_2OUT4 */ -#define WM8985_OUT4MUTE 0x0040 /* OUT4MUTE */ -#define WM8985_OUT4MUTE_MASK 0x0040 /* OUT4MUTE */ -#define WM8985_OUT4MUTE_SHIFT 6 /* OUT4MUTE */ -#define WM8985_OUT4MUTE_WIDTH 1 /* OUT4MUTE */ -#define WM8985_OUT4ATTN 0x0020 /* OUT4ATTN */ -#define WM8985_OUT4ATTN_MASK 0x0020 /* OUT4ATTN */ -#define WM8985_OUT4ATTN_SHIFT 5 /* OUT4ATTN */ -#define WM8985_OUT4ATTN_WIDTH 1 /* OUT4ATTN */ -#define WM8985_LMIX2OUT4 0x0010 /* LMIX2OUT4 */ -#define WM8985_LMIX2OUT4_MASK 0x0010 /* LMIX2OUT4 */ -#define WM8985_LMIX2OUT4_SHIFT 4 /* LMIX2OUT4 */ -#define WM8985_LMIX2OUT4_WIDTH 1 /* LMIX2OUT4 */ -#define WM8985_LDAC2OUT4 0x0008 /* LDAC2OUT4 */ -#define WM8985_LDAC2OUT4_MASK 0x0008 /* LDAC2OUT4 */ -#define WM8985_LDAC2OUT4_SHIFT 3 /* LDAC2OUT4 */ -#define WM8985_LDAC2OUT4_WIDTH 1 /* LDAC2OUT4 */ -#define WM8985_BYPR2OUT4 0x0004 /* BYPR2OUT4 */ -#define WM8985_BYPR2OUT4_MASK 0x0004 /* BYPR2OUT4 */ -#define WM8985_BYPR2OUT4_SHIFT 2 /* BYPR2OUT4 */ -#define WM8985_BYPR2OUT4_WIDTH 1 /* BYPR2OUT4 */ -#define WM8985_RMIX2OUT4 0x0002 /* RMIX2OUT4 */ -#define WM8985_RMIX2OUT4_MASK 0x0002 /* RMIX2OUT4 */ -#define WM8985_RMIX2OUT4_SHIFT 1 /* RMIX2OUT4 */ -#define WM8985_RMIX2OUT4_WIDTH 1 /* RMIX2OUT4 */ -#define WM8985_RDAC2OUT4 0x0001 /* RDAC2OUT4 */ -#define WM8985_RDAC2OUT4_MASK 0x0001 /* RDAC2OUT4 */ -#define WM8985_RDAC2OUT4_SHIFT 0 /* RDAC2OUT4 */ -#define WM8985_RDAC2OUT4_WIDTH 1 /* RDAC2OUT4 */ - -/* - * R60 (0x3C) - OUTPUT ctrl - */ -#define WM8985_VIDBUFFTST_MASK 0x01E0 /* VIDBUFFTST - [8:5] */ -#define WM8985_VIDBUFFTST_SHIFT 5 /* VIDBUFFTST - [8:5] */ -#define WM8985_VIDBUFFTST_WIDTH 4 /* VIDBUFFTST - [8:5] */ -#define WM8985_HPTOG 0x0008 /* HPTOG */ -#define WM8985_HPTOG_MASK 0x0008 /* HPTOG */ -#define WM8985_HPTOG_SHIFT 3 /* HPTOG */ -#define WM8985_HPTOG_WIDTH 1 /* HPTOG */ - -/* - * R61 (0x3D) - BIAS CTRL - */ -#define WM8985_BIASCUT 0x0100 /* BIASCUT */ -#define WM8985_BIASCUT_MASK 0x0100 /* BIASCUT */ -#define WM8985_BIASCUT_SHIFT 8 /* BIASCUT */ -#define WM8985_BIASCUT_WIDTH 1 /* BIASCUT */ -#define WM8985_HALFIPBIAS 0x0080 /* HALFIPBIAS */ -#define WM8985_HALFIPBIAS_MASK 0x0080 /* HALFIPBIAS */ -#define WM8985_HALFIPBIAS_SHIFT 7 /* HALFIPBIAS */ -#define WM8985_HALFIPBIAS_WIDTH 1 /* HALFIPBIAS */ -#define WM8985_VBBIASTST_MASK 0x0060 /* VBBIASTST - [6:5] */ -#define WM8985_VBBIASTST_SHIFT 5 /* VBBIASTST - [6:5] */ -#define WM8985_VBBIASTST_WIDTH 2 /* VBBIASTST - [6:5] */ -#define WM8985_BUFBIAS_MASK 0x0018 /* BUFBIAS - [4:3] */ -#define WM8985_BUFBIAS_SHIFT 3 /* BUFBIAS - [4:3] */ -#define WM8985_BUFBIAS_WIDTH 2 /* BUFBIAS - [4:3] */ -#define WM8985_ADCBIAS_MASK 0x0006 /* ADCBIAS - [2:1] */ -#define WM8985_ADCBIAS_SHIFT 1 /* ADCBIAS - [2:1] */ -#define WM8985_ADCBIAS_WIDTH 2 /* ADCBIAS - [2:1] */ -#define WM8985_HALFOPBIAS 0x0001 /* HALFOPBIAS */ -#define WM8985_HALFOPBIAS_MASK 0x0001 /* HALFOPBIAS */ -#define WM8985_HALFOPBIAS_SHIFT 0 /* HALFOPBIAS */ -#define WM8985_HALFOPBIAS_WIDTH 1 /* HALFOPBIAS */ - -enum clk_src { - WM8985_CLKSRC_MCLK, - WM8985_CLKSRC_PLL -}; - -#define WM8985_PLL 0 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8988.c b/ANDROID_3.4.5/sound/soc/codecs/wm8988.c deleted file mode 100644 index 6cdf6a2b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8988.c +++ /dev/null @@ -1,1010 +0,0 @@ -/* - * wm8988.c -- WM8988 ALSA SoC audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * Copyright 2005 Openedhand Ltd. - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8988.h" - -/* - * wm8988 register cache - * We can't read the WM8988 register space when we - * are using 2 wire for device control, so we cache them instead. - */ -static const struct reg_default wm8988_reg_defaults[] = { - { 0, 0x0097 }, - { 1, 0x0097 }, - { 2, 0x0079 }, - { 3, 0x0079 }, - { 5, 0x0008 }, - { 7, 0x000a }, - { 8, 0x0000 }, - { 10, 0x00ff }, - { 11, 0x00ff }, - { 12, 0x000f }, - { 13, 0x000f }, - { 16, 0x0000 }, - { 17, 0x007b }, - { 18, 0x0000 }, - { 19, 0x0032 }, - { 20, 0x0000 }, - { 21, 0x00c3 }, - { 22, 0x00c3 }, - { 23, 0x00c0 }, - { 24, 0x0000 }, - { 25, 0x0000 }, - { 26, 0x0000 }, - { 27, 0x0000 }, - { 31, 0x0000 }, - { 32, 0x0000 }, - { 33, 0x0000 }, - { 34, 0x0050 }, - { 35, 0x0050 }, - { 36, 0x0050 }, - { 37, 0x0050 }, - { 40, 0x0079 }, - { 41, 0x0079 }, - { 42, 0x0079 }, -}; - -static bool wm8988_writeable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8988_LINVOL: - case WM8988_RINVOL: - case WM8988_LOUT1V: - case WM8988_ROUT1V: - case WM8988_ADCDAC: - case WM8988_IFACE: - case WM8988_SRATE: - case WM8988_LDAC: - case WM8988_RDAC: - case WM8988_BASS: - case WM8988_TREBLE: - case WM8988_RESET: - case WM8988_3D: - case WM8988_ALC1: - case WM8988_ALC2: - case WM8988_ALC3: - case WM8988_NGATE: - case WM8988_LADC: - case WM8988_RADC: - case WM8988_ADCTL1: - case WM8988_ADCTL2: - case WM8988_PWR1: - case WM8988_PWR2: - case WM8988_ADCTL3: - case WM8988_ADCIN: - case WM8988_LADCIN: - case WM8988_RADCIN: - case WM8988_LOUTM1: - case WM8988_LOUTM2: - case WM8988_ROUTM1: - case WM8988_ROUTM2: - case WM8988_LOUT2V: - case WM8988_ROUT2V: - case WM8988_LPPB: - return true; - default: - return false; - } -} - -/* codec private data */ -struct wm8988_priv { - struct regmap *regmap; - unsigned int sysclk; - struct snd_pcm_hw_constraint_list *sysclk_constraints; -}; - -#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) - -/* - * WM8988 Controls - */ - -static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"}; -static const struct soc_enum bass_boost = - SOC_ENUM_SINGLE(WM8988_BASS, 7, 2, bass_boost_txt); - -static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; -static const struct soc_enum bass_filter = - SOC_ENUM_SINGLE(WM8988_BASS, 6, 2, bass_filter_txt); - -static const char *treble_txt[] = {"8kHz", "4kHz"}; -static const struct soc_enum treble = - SOC_ENUM_SINGLE(WM8988_TREBLE, 6, 2, treble_txt); - -static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"}; -static const struct soc_enum stereo_3d_lc = - SOC_ENUM_SINGLE(WM8988_3D, 5, 2, stereo_3d_lc_txt); - -static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"}; -static const struct soc_enum stereo_3d_uc = - SOC_ENUM_SINGLE(WM8988_3D, 6, 2, stereo_3d_uc_txt); - -static const char *stereo_3d_func_txt[] = {"Capture", "Playback"}; -static const struct soc_enum stereo_3d_func = - SOC_ENUM_SINGLE(WM8988_3D, 7, 2, stereo_3d_func_txt); - -static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"}; -static const struct soc_enum alc_func = - SOC_ENUM_SINGLE(WM8988_ALC1, 7, 4, alc_func_txt); - -static const char *ng_type_txt[] = {"Constant PGA Gain", - "Mute ADC Output"}; -static const struct soc_enum ng_type = - SOC_ENUM_SINGLE(WM8988_NGATE, 1, 2, ng_type_txt); - -static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum deemph = - SOC_ENUM_SINGLE(WM8988_ADCDAC, 1, 4, deemph_txt); - -static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert", - "L + R Invert"}; -static const struct soc_enum adcpol = - SOC_ENUM_SINGLE(WM8988_ADCDAC, 5, 4, adcpol_txt); - -static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1); -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); - -static const struct snd_kcontrol_new wm8988_snd_controls[] = { - -SOC_ENUM("Bass Boost", bass_boost), -SOC_ENUM("Bass Filter", bass_filter), -SOC_SINGLE("Bass Volume", WM8988_BASS, 0, 15, 1), - -SOC_SINGLE("Treble Volume", WM8988_TREBLE, 0, 15, 0), -SOC_ENUM("Treble Cut-off", treble), - -SOC_SINGLE("3D Switch", WM8988_3D, 0, 1, 0), -SOC_SINGLE("3D Volume", WM8988_3D, 1, 15, 0), -SOC_ENUM("3D Lower Cut-off", stereo_3d_lc), -SOC_ENUM("3D Upper Cut-off", stereo_3d_uc), -SOC_ENUM("3D Mode", stereo_3d_func), - -SOC_SINGLE("ALC Capture Target Volume", WM8988_ALC1, 0, 7, 0), -SOC_SINGLE("ALC Capture Max Volume", WM8988_ALC1, 4, 7, 0), -SOC_ENUM("ALC Capture Function", alc_func), -SOC_SINGLE("ALC Capture ZC Switch", WM8988_ALC2, 7, 1, 0), -SOC_SINGLE("ALC Capture Hold Time", WM8988_ALC2, 0, 15, 0), -SOC_SINGLE("ALC Capture Decay Time", WM8988_ALC3, 4, 15, 0), -SOC_SINGLE("ALC Capture Attack Time", WM8988_ALC3, 0, 15, 0), -SOC_SINGLE("ALC Capture NG Threshold", WM8988_NGATE, 3, 31, 0), -SOC_ENUM("ALC Capture NG Type", ng_type), -SOC_SINGLE("ALC Capture NG Switch", WM8988_NGATE, 0, 1, 0), - -SOC_SINGLE("ZC Timeout Switch", WM8988_ADCTL1, 0, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Digital Volume", WM8988_LADC, WM8988_RADC, - 0, 255, 0, adc_tlv), -SOC_DOUBLE_R_TLV("Capture Volume", WM8988_LINVOL, WM8988_RINVOL, - 0, 63, 0, pga_tlv), -SOC_DOUBLE_R("Capture ZC Switch", WM8988_LINVOL, WM8988_RINVOL, 6, 1, 0), -SOC_DOUBLE_R("Capture Switch", WM8988_LINVOL, WM8988_RINVOL, 7, 1, 1), - -SOC_ENUM("Playback De-emphasis", deemph), - -SOC_ENUM("Capture Polarity", adcpol), -SOC_SINGLE("Playback 6dB Attenuate", WM8988_ADCDAC, 7, 1, 0), -SOC_SINGLE("Capture 6dB Attenuate", WM8988_ADCDAC, 8, 1, 0), - -SOC_DOUBLE_R_TLV("PCM Volume", WM8988_LDAC, WM8988_RDAC, 0, 255, 0, dac_tlv), - -SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", WM8988_LOUTM1, 4, 7, 1, - bypass_tlv), -SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", WM8988_LOUTM2, 4, 7, 1, - bypass_tlv), -SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", WM8988_ROUTM1, 4, 7, 1, - bypass_tlv), -SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", WM8988_ROUTM2, 4, 7, 1, - bypass_tlv), - -SOC_DOUBLE_R("Output 1 Playback ZC Switch", WM8988_LOUT1V, - WM8988_ROUT1V, 7, 1, 0), -SOC_DOUBLE_R_TLV("Output 1 Playback Volume", WM8988_LOUT1V, WM8988_ROUT1V, - 0, 127, 0, out_tlv), - -SOC_DOUBLE_R("Output 2 Playback ZC Switch", WM8988_LOUT2V, - WM8988_ROUT2V, 7, 1, 0), -SOC_DOUBLE_R_TLV("Output 2 Playback Volume", WM8988_LOUT2V, WM8988_ROUT2V, - 0, 127, 0, out_tlv), - -}; - -/* - * DAPM Controls - */ - -static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2); - - /* Use the DAC to gate LRC if active, otherwise use ADC */ - if (snd_soc_read(codec, WM8988_PWR2) & 0x180) - adctl2 &= ~0x4; - else - adctl2 |= 0x4; - - return snd_soc_write(codec, WM8988_ADCTL2, adctl2); -} - -static const char *wm8988_line_texts[] = { - "Line 1", "Line 2", "PGA", "Differential"}; - -static const unsigned int wm8988_line_values[] = { - 0, 1, 3, 4}; - -static const struct soc_enum wm8988_lline_enum = - SOC_VALUE_ENUM_SINGLE(WM8988_LOUTM1, 0, 7, - ARRAY_SIZE(wm8988_line_texts), - wm8988_line_texts, - wm8988_line_values); -static const struct snd_kcontrol_new wm8988_left_line_controls = - SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum); - -static const struct soc_enum wm8988_rline_enum = - SOC_VALUE_ENUM_SINGLE(WM8988_ROUTM1, 0, 7, - ARRAY_SIZE(wm8988_line_texts), - wm8988_line_texts, - wm8988_line_values); -static const struct snd_kcontrol_new wm8988_right_line_controls = - SOC_DAPM_VALUE_ENUM("Route", wm8988_lline_enum); - -/* Left Mixer */ -static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = { - SOC_DAPM_SINGLE("Playback Switch", WM8988_LOUTM1, 8, 1, 0), - SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_LOUTM1, 7, 1, 0), - SOC_DAPM_SINGLE("Right Playback Switch", WM8988_LOUTM2, 8, 1, 0), - SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_LOUTM2, 7, 1, 0), -}; - -/* Right Mixer */ -static const struct snd_kcontrol_new wm8988_right_mixer_controls[] = { - SOC_DAPM_SINGLE("Left Playback Switch", WM8988_ROUTM1, 8, 1, 0), - SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_ROUTM1, 7, 1, 0), - SOC_DAPM_SINGLE("Playback Switch", WM8988_ROUTM2, 8, 1, 0), - SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_ROUTM2, 7, 1, 0), -}; - -static const char *wm8988_pga_sel[] = {"Line 1", "Line 2", "Differential"}; -static const unsigned int wm8988_pga_val[] = { 0, 1, 3 }; - -/* Left PGA Mux */ -static const struct soc_enum wm8988_lpga_enum = - SOC_VALUE_ENUM_SINGLE(WM8988_LADCIN, 6, 3, - ARRAY_SIZE(wm8988_pga_sel), - wm8988_pga_sel, - wm8988_pga_val); -static const struct snd_kcontrol_new wm8988_left_pga_controls = - SOC_DAPM_VALUE_ENUM("Route", wm8988_lpga_enum); - -/* Right PGA Mux */ -static const struct soc_enum wm8988_rpga_enum = - SOC_VALUE_ENUM_SINGLE(WM8988_RADCIN, 6, 3, - ARRAY_SIZE(wm8988_pga_sel), - wm8988_pga_sel, - wm8988_pga_val); -static const struct snd_kcontrol_new wm8988_right_pga_controls = - SOC_DAPM_VALUE_ENUM("Route", wm8988_rpga_enum); - -/* Differential Mux */ -static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"}; -static const struct soc_enum diffmux = - SOC_ENUM_SINGLE(WM8988_ADCIN, 8, 2, wm8988_diff_sel); -static const struct snd_kcontrol_new wm8988_diffmux_controls = - SOC_DAPM_ENUM("Route", diffmux); - -/* Mono ADC Mux */ -static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)", - "Mono (Right)", "Digital Mono"}; -static const struct soc_enum monomux = - SOC_ENUM_SINGLE(WM8988_ADCIN, 6, 4, wm8988_mono_mux); -static const struct snd_kcontrol_new wm8988_monomux_controls = - SOC_DAPM_ENUM("Route", monomux); - -static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = { - SND_SOC_DAPM_SUPPLY("Mic Bias", WM8988_PWR1, 1, 0, NULL, 0), - - SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, - &wm8988_diffmux_controls), - SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, - &wm8988_monomux_controls), - SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, - &wm8988_monomux_controls), - - SND_SOC_DAPM_MUX("Left PGA Mux", WM8988_PWR1, 5, 0, - &wm8988_left_pga_controls), - SND_SOC_DAPM_MUX("Right PGA Mux", WM8988_PWR1, 4, 0, - &wm8988_right_pga_controls), - - SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, - &wm8988_left_line_controls), - SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, - &wm8988_right_line_controls), - - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8988_PWR1, 2, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8988_PWR1, 3, 0), - - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8988_PWR2, 7, 0), - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8988_PWR2, 8, 0), - - SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, - &wm8988_left_mixer_controls[0], - ARRAY_SIZE(wm8988_left_mixer_controls)), - SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, - &wm8988_right_mixer_controls[0], - ARRAY_SIZE(wm8988_right_mixer_controls)), - - SND_SOC_DAPM_PGA("Right Out 2", WM8988_PWR2, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 2", WM8988_PWR2, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Out 1", WM8988_PWR2, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 1", WM8988_PWR2, 6, 0, NULL, 0), - - SND_SOC_DAPM_POST("LRC control", wm8988_lrc_control), - - SND_SOC_DAPM_OUTPUT("LOUT1"), - SND_SOC_DAPM_OUTPUT("ROUT1"), - SND_SOC_DAPM_OUTPUT("LOUT2"), - SND_SOC_DAPM_OUTPUT("ROUT2"), - SND_SOC_DAPM_OUTPUT("VREF"), - - SND_SOC_DAPM_INPUT("LINPUT1"), - SND_SOC_DAPM_INPUT("LINPUT2"), - SND_SOC_DAPM_INPUT("RINPUT1"), - SND_SOC_DAPM_INPUT("RINPUT2"), -}; - -static const struct snd_soc_dapm_route wm8988_dapm_routes[] = { - - { "Left Line Mux", "Line 1", "LINPUT1" }, - { "Left Line Mux", "Line 2", "LINPUT2" }, - { "Left Line Mux", "PGA", "Left PGA Mux" }, - { "Left Line Mux", "Differential", "Differential Mux" }, - - { "Right Line Mux", "Line 1", "RINPUT1" }, - { "Right Line Mux", "Line 2", "RINPUT2" }, - { "Right Line Mux", "PGA", "Right PGA Mux" }, - { "Right Line Mux", "Differential", "Differential Mux" }, - - { "Left PGA Mux", "Line 1", "LINPUT1" }, - { "Left PGA Mux", "Line 2", "LINPUT2" }, - { "Left PGA Mux", "Differential", "Differential Mux" }, - - { "Right PGA Mux", "Line 1", "RINPUT1" }, - { "Right PGA Mux", "Line 2", "RINPUT2" }, - { "Right PGA Mux", "Differential", "Differential Mux" }, - - { "Differential Mux", "Line 1", "LINPUT1" }, - { "Differential Mux", "Line 1", "RINPUT1" }, - { "Differential Mux", "Line 2", "LINPUT2" }, - { "Differential Mux", "Line 2", "RINPUT2" }, - - { "Left ADC Mux", "Stereo", "Left PGA Mux" }, - { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" }, - { "Left ADC Mux", "Digital Mono", "Left PGA Mux" }, - - { "Right ADC Mux", "Stereo", "Right PGA Mux" }, - { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" }, - { "Right ADC Mux", "Digital Mono", "Right PGA Mux" }, - - { "Left ADC", NULL, "Left ADC Mux" }, - { "Right ADC", NULL, "Right ADC Mux" }, - - { "Left Line Mux", "Line 1", "LINPUT1" }, - { "Left Line Mux", "Line 2", "LINPUT2" }, - { "Left Line Mux", "PGA", "Left PGA Mux" }, - { "Left Line Mux", "Differential", "Differential Mux" }, - - { "Right Line Mux", "Line 1", "RINPUT1" }, - { "Right Line Mux", "Line 2", "RINPUT2" }, - { "Right Line Mux", "PGA", "Right PGA Mux" }, - { "Right Line Mux", "Differential", "Differential Mux" }, - - { "Left Mixer", "Playback Switch", "Left DAC" }, - { "Left Mixer", "Left Bypass Switch", "Left Line Mux" }, - { "Left Mixer", "Right Playback Switch", "Right DAC" }, - { "Left Mixer", "Right Bypass Switch", "Right Line Mux" }, - - { "Right Mixer", "Left Playback Switch", "Left DAC" }, - { "Right Mixer", "Left Bypass Switch", "Left Line Mux" }, - { "Right Mixer", "Playback Switch", "Right DAC" }, - { "Right Mixer", "Right Bypass Switch", "Right Line Mux" }, - - { "Left Out 1", NULL, "Left Mixer" }, - { "LOUT1", NULL, "Left Out 1" }, - { "Right Out 1", NULL, "Right Mixer" }, - { "ROUT1", NULL, "Right Out 1" }, - - { "Left Out 2", NULL, "Left Mixer" }, - { "LOUT2", NULL, "Left Out 2" }, - { "Right Out 2", NULL, "Right Mixer" }, - { "ROUT2", NULL, "Right Out 2" }, -}; - -struct _coeff_div { - u32 mclk; - u32 rate; - u16 fs; - u8 sr:5; - u8 usb:1; -}; - -/* codec hifi mclk clock divider coefficients */ -static const struct _coeff_div coeff_div[] = { - /* 8k */ - {12288000, 8000, 1536, 0x6, 0x0}, - {11289600, 8000, 1408, 0x16, 0x0}, - {18432000, 8000, 2304, 0x7, 0x0}, - {16934400, 8000, 2112, 0x17, 0x0}, - {12000000, 8000, 1500, 0x6, 0x1}, - - /* 11.025k */ - {11289600, 11025, 1024, 0x18, 0x0}, - {16934400, 11025, 1536, 0x19, 0x0}, - {12000000, 11025, 1088, 0x19, 0x1}, - - /* 16k */ - {12288000, 16000, 768, 0xa, 0x0}, - {18432000, 16000, 1152, 0xb, 0x0}, - {12000000, 16000, 750, 0xa, 0x1}, - - /* 22.05k */ - {11289600, 22050, 512, 0x1a, 0x0}, - {16934400, 22050, 768, 0x1b, 0x0}, - {12000000, 22050, 544, 0x1b, 0x1}, - - /* 32k */ - {12288000, 32000, 384, 0xc, 0x0}, - {18432000, 32000, 576, 0xd, 0x0}, - {12000000, 32000, 375, 0xa, 0x1}, - - /* 44.1k */ - {11289600, 44100, 256, 0x10, 0x0}, - {16934400, 44100, 384, 0x11, 0x0}, - {12000000, 44100, 272, 0x11, 0x1}, - - /* 48k */ - {12288000, 48000, 256, 0x0, 0x0}, - {18432000, 48000, 384, 0x1, 0x0}, - {12000000, 48000, 250, 0x0, 0x1}, - - /* 88.2k */ - {11289600, 88200, 128, 0x1e, 0x0}, - {16934400, 88200, 192, 0x1f, 0x0}, - {12000000, 88200, 136, 0x1f, 0x1}, - - /* 96k */ - {12288000, 96000, 128, 0xe, 0x0}, - {18432000, 96000, 192, 0xf, 0x0}, - {12000000, 96000, 125, 0xe, 0x1}, -}; - -static inline int get_coeff(int mclk, int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) - return i; - } - - return -EINVAL; -} - -/* The set of rates we can generate from the above for each SYSCLK */ - -static unsigned int rates_12288[] = { - 8000, 12000, 16000, 24000, 24000, 32000, 48000, 96000, -}; - -static struct snd_pcm_hw_constraint_list constraints_12288 = { - .count = ARRAY_SIZE(rates_12288), - .list = rates_12288, -}; - -static unsigned int rates_112896[] = { - 8000, 11025, 22050, 44100, -}; - -static struct snd_pcm_hw_constraint_list constraints_112896 = { - .count = ARRAY_SIZE(rates_112896), - .list = rates_112896, -}; - -static unsigned int rates_12[] = { - 8000, 11025, 12000, 16000, 22050, 2400, 32000, 41100, 48000, - 48000, 88235, 96000, -}; - -static struct snd_pcm_hw_constraint_list constraints_12 = { - .count = ARRAY_SIZE(rates_12), - .list = rates_12, -}; - -/* - * Note that this should be called from init rather than from hw_params. - */ -static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); - - switch (freq) { - case 11289600: - case 18432000: - case 22579200: - case 36864000: - wm8988->sysclk_constraints = &constraints_112896; - wm8988->sysclk = freq; - return 0; - - case 12288000: - case 16934400: - case 24576000: - case 33868800: - wm8988->sysclk_constraints = &constraints_12288; - wm8988->sysclk = freq; - return 0; - - case 12000000: - case 24000000: - wm8988->sysclk_constraints = &constraints_12; - wm8988->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface = 0x0040; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8988_IFACE, iface); - return 0; -} - -static int wm8988_pcm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); - - /* The set of sample rates that can be supported depends on the - * MCLK supplied to the CODEC - enforce this. - */ - if (!wm8988->sysclk) { - dev_err(codec->dev, - "No MCLK configured, call set_sysclk() on init\n"); - return -EINVAL; - } - - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - wm8988->sysclk_constraints); - - return 0; -} - -static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); - u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; - u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; - int coeff; - - coeff = get_coeff(wm8988->sysclk, params_rate(params)); - if (coeff < 0) { - coeff = get_coeff(wm8988->sysclk / 2, params_rate(params)); - srate |= 0x40; - } - if (coeff < 0) { - dev_err(codec->dev, - "Unable to configure sample rate %dHz with %dHz MCLK\n", - params_rate(params), wm8988->sysclk); - return coeff; - } - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x000c; - break; - } - - /* set iface & srate */ - snd_soc_write(codec, WM8988_IFACE, iface); - if (coeff >= 0) - snd_soc_write(codec, WM8988_SRATE, srate | - (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); - - return 0; -} - -static int wm8988_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7; - - if (mute) - snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8); - else - snd_soc_write(codec, WM8988_ADCDAC, mute_reg); - return 0; -} - -static int wm8988_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); - u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VREF, VMID=2x50k, digital enabled */ - snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - regcache_sync(wm8988->regmap); - - /* VREF, VMID=2x5k */ - snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); - - /* Charge caps */ - msleep(100); - } - - /* VREF, VMID=2*500k, digital stopped */ - snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8988_PWR1, 0x0000); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -#define WM8988_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8988_ops = { - .startup = wm8988_pcm_startup, - .hw_params = wm8988_pcm_hw_params, - .set_fmt = wm8988_set_dai_fmt, - .set_sysclk = wm8988_set_dai_sysclk, - .digital_mute = wm8988_mute, -}; - -static struct snd_soc_dai_driver wm8988_dai = { - .name = "wm8988-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8988_RATES, - .formats = WM8988_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8988_RATES, - .formats = WM8988_FORMATS, - }, - .ops = &wm8988_ops, - .symmetric_rates = 1, -}; - -static int wm8988_suspend(struct snd_soc_codec *codec) -{ - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); - - wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); - regcache_mark_dirty(wm8988->regmap); - return 0; -} - -static int wm8988_resume(struct snd_soc_codec *codec) -{ - wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -static int wm8988_probe(struct snd_soc_codec *codec) -{ - struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); - int ret = 0; - - codec->control_data = wm8988->regmap; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = wm8988_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - /* set the update bits (we always update left then right) */ - snd_soc_update_bits(codec, WM8988_RADC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8988_RDAC, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8988_ROUT1V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100); - snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100); - - wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static int wm8988_remove(struct snd_soc_codec *codec) -{ - wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { - .probe = wm8988_probe, - .remove = wm8988_remove, - .suspend = wm8988_suspend, - .resume = wm8988_resume, - .set_bias_level = wm8988_set_bias_level, - - .controls = wm8988_snd_controls, - .num_controls = ARRAY_SIZE(wm8988_snd_controls), - .dapm_widgets = wm8988_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets), - .dapm_routes = wm8988_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes), -}; - -static struct regmap_config wm8988_regmap = { - .reg_bits = 7, - .val_bits = 9, - - .max_register = WM8988_LPPB, - .writeable_reg = wm8988_writeable, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8988_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults), -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8988_spi_probe(struct spi_device *spi) -{ - struct wm8988_priv *wm8988; - int ret; - - wm8988 = devm_kzalloc(&spi->dev, sizeof(struct wm8988_priv), - GFP_KERNEL); - if (wm8988 == NULL) - return -ENOMEM; - - wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap); - if (IS_ERR(wm8988->regmap)) { - ret = PTR_ERR(wm8988->regmap); - dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); - return ret; - } - - spi_set_drvdata(spi, wm8988); - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8988, &wm8988_dai, 1); - if (ret != 0) - regmap_exit(wm8988->regmap); - - return ret; -} - -static int __devexit wm8988_spi_remove(struct spi_device *spi) -{ - struct wm8988_priv *wm8988 = spi_get_drvdata(spi); - snd_soc_unregister_codec(&spi->dev); - regmap_exit(wm8988->regmap); - return 0; -} - -static struct spi_driver wm8988_spi_driver = { - .driver = { - .name = "wm8988", - .owner = THIS_MODULE, - }, - .probe = wm8988_spi_probe, - .remove = __devexit_p(wm8988_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8988_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8988_priv *wm8988; - int ret; - - wm8988 = devm_kzalloc(&i2c->dev, sizeof(struct wm8988_priv), - GFP_KERNEL); - if (wm8988 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8988); - - wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap); - if (IS_ERR(wm8988->regmap)) { - ret = PTR_ERR(wm8988->regmap); - dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); - return ret; - } - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8988, &wm8988_dai, 1); - if (ret != 0) - regmap_exit(wm8988->regmap); - - return ret; -} - -static __devexit int wm8988_i2c_remove(struct i2c_client *client) -{ - struct wm8988_priv *wm8988 = i2c_get_clientdata(client); - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8988->regmap); - return 0; -} - -static const struct i2c_device_id wm8988_i2c_id[] = { - { "wm8988", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); - -static struct i2c_driver wm8988_i2c_driver = { - .driver = { - .name = "wm8988", - .owner = THIS_MODULE, - }, - .probe = wm8988_i2c_probe, - .remove = __devexit_p(wm8988_i2c_remove), - .id_table = wm8988_i2c_id, -}; -#endif - -static int __init wm8988_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8988_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8988_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8988_modinit); - -static void __exit wm8988_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8988_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8988_spi_driver); -#endif -} -module_exit(wm8988_exit); - - -MODULE_DESCRIPTION("ASoC WM8988 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8988.h b/ANDROID_3.4.5/sound/soc/codecs/wm8988.h deleted file mode 100644 index 5c04024e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8988.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie - * - * Based on WM8753.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _WM8988_H -#define _WM8988_H - -/* WM8988 register space */ - -#define WM8988_LINVOL 0x00 -#define WM8988_RINVOL 0x01 -#define WM8988_LOUT1V 0x02 -#define WM8988_ROUT1V 0x03 -#define WM8988_ADCDAC 0x05 -#define WM8988_IFACE 0x07 -#define WM8988_SRATE 0x08 -#define WM8988_LDAC 0x0a -#define WM8988_RDAC 0x0b -#define WM8988_BASS 0x0c -#define WM8988_TREBLE 0x0d -#define WM8988_RESET 0x0f -#define WM8988_3D 0x10 -#define WM8988_ALC1 0x11 -#define WM8988_ALC2 0x12 -#define WM8988_ALC3 0x13 -#define WM8988_NGATE 0x14 -#define WM8988_LADC 0x15 -#define WM8988_RADC 0x16 -#define WM8988_ADCTL1 0x17 -#define WM8988_ADCTL2 0x18 -#define WM8988_PWR1 0x19 -#define WM8988_PWR2 0x1a -#define WM8988_ADCTL3 0x1b -#define WM8988_ADCIN 0x1f -#define WM8988_LADCIN 0x20 -#define WM8988_RADCIN 0x21 -#define WM8988_LOUTM1 0x22 -#define WM8988_LOUTM2 0x23 -#define WM8988_ROUTM1 0x24 -#define WM8988_ROUTM2 0x25 -#define WM8988_LOUT2V 0x28 -#define WM8988_ROUT2V 0x29 -#define WM8988_LPPB 0x43 -#define WM8988_NUM_REG 0x44 - -#define WM8988_SYSCLK 0 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8990.c b/ANDROID_3.4.5/sound/soc/codecs/wm8990.c deleted file mode 100644 index 9d242351..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8990.c +++ /dev/null @@ -1,1453 +0,0 @@ -/* - * wm8990.c -- WM8990 ALSA Soc Audio driver - * - * Copyright 2008 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8990.h" - -/* codec private data */ -struct wm8990_priv { - enum snd_soc_control_type control_type; - unsigned int sysclk; - unsigned int pcmclk; -}; - -static int wm8990_volatile_register(struct snd_soc_codec *codec, - unsigned int reg) -{ - switch (reg) { - case WM8990_RESET: - return 1; - default: - return 0; - } -} - -static const u16 wm8990_reg[] = { - 0x8990, /* R0 - Reset */ - 0x0000, /* R1 - Power Management (1) */ - 0x6000, /* R2 - Power Management (2) */ - 0x0000, /* R3 - Power Management (3) */ - 0x4050, /* R4 - Audio Interface (1) */ - 0x4000, /* R5 - Audio Interface (2) */ - 0x01C8, /* R6 - Clocking (1) */ - 0x0000, /* R7 - Clocking (2) */ - 0x0040, /* R8 - Audio Interface (3) */ - 0x0040, /* R9 - Audio Interface (4) */ - 0x0004, /* R10 - DAC CTRL */ - 0x00C0, /* R11 - Left DAC Digital Volume */ - 0x00C0, /* R12 - Right DAC Digital Volume */ - 0x0000, /* R13 - Digital Side Tone */ - 0x0100, /* R14 - ADC CTRL */ - 0x00C0, /* R15 - Left ADC Digital Volume */ - 0x00C0, /* R16 - Right ADC Digital Volume */ - 0x0000, /* R17 */ - 0x0000, /* R18 - GPIO CTRL 1 */ - 0x1000, /* R19 - GPIO1 & GPIO2 */ - 0x1010, /* R20 - GPIO3 & GPIO4 */ - 0x1010, /* R21 - GPIO5 & GPIO6 */ - 0x8000, /* R22 - GPIOCTRL 2 */ - 0x0800, /* R23 - GPIO_POL */ - 0x008B, /* R24 - Left Line Input 1&2 Volume */ - 0x008B, /* R25 - Left Line Input 3&4 Volume */ - 0x008B, /* R26 - Right Line Input 1&2 Volume */ - 0x008B, /* R27 - Right Line Input 3&4 Volume */ - 0x0000, /* R28 - Left Output Volume */ - 0x0000, /* R29 - Right Output Volume */ - 0x0066, /* R30 - Line Outputs Volume */ - 0x0022, /* R31 - Out3/4 Volume */ - 0x0079, /* R32 - Left OPGA Volume */ - 0x0079, /* R33 - Right OPGA Volume */ - 0x0003, /* R34 - Speaker Volume */ - 0x0003, /* R35 - ClassD1 */ - 0x0000, /* R36 */ - 0x0100, /* R37 - ClassD3 */ - 0x0079, /* R38 - ClassD4 */ - 0x0000, /* R39 - Input Mixer1 */ - 0x0000, /* R40 - Input Mixer2 */ - 0x0000, /* R41 - Input Mixer3 */ - 0x0000, /* R42 - Input Mixer4 */ - 0x0000, /* R43 - Input Mixer5 */ - 0x0000, /* R44 - Input Mixer6 */ - 0x0000, /* R45 - Output Mixer1 */ - 0x0000, /* R46 - Output Mixer2 */ - 0x0000, /* R47 - Output Mixer3 */ - 0x0000, /* R48 - Output Mixer4 */ - 0x0000, /* R49 - Output Mixer5 */ - 0x0000, /* R50 - Output Mixer6 */ - 0x0180, /* R51 - Out3/4 Mixer */ - 0x0000, /* R52 - Line Mixer1 */ - 0x0000, /* R53 - Line Mixer2 */ - 0x0000, /* R54 - Speaker Mixer */ - 0x0000, /* R55 - Additional Control */ - 0x0000, /* R56 - AntiPOP1 */ - 0x0000, /* R57 - AntiPOP2 */ - 0x0000, /* R58 - MICBIAS */ - 0x0000, /* R59 */ - 0x0008, /* R60 - PLL1 */ - 0x0031, /* R61 - PLL2 */ - 0x0026, /* R62 - PLL3 */ - 0x0000, /* R63 - Driver internal */ -}; - -#define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0) - -static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 600, 0); - -static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0); - -static const DECLARE_TLV_DB_SCALE(out_mix_tlv, 0, -2100, 0); - -static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0); - -static const DECLARE_TLV_DB_SCALE(out_omix_tlv, -600, 0, 0); - -static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0); - -static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0); - -static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0); - -static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int reg = mc->reg; - int ret; - u16 val; - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret < 0) - return ret; - - /* now hit the volume update bits (always bit 8) */ - val = snd_soc_read(codec, reg); - return snd_soc_write(codec, reg, val | 0x0100); -} - -#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ - tlv_array) {\ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - - -static const char *wm8990_digital_sidetone[] = - {"None", "Left ADC", "Right ADC", "Reserved"}; - -static const struct soc_enum wm8990_left_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, - WM8990_ADC_TO_DACL_SHIFT, - WM8990_ADC_TO_DACL_MASK, - wm8990_digital_sidetone); - -static const struct soc_enum wm8990_right_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, - WM8990_ADC_TO_DACR_SHIFT, - WM8990_ADC_TO_DACR_MASK, - wm8990_digital_sidetone); - -static const char *wm8990_adcmode[] = - {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; - -static const struct soc_enum wm8990_right_adcmode_enum = -SOC_ENUM_SINGLE(WM8990_ADC_CTRL, - WM8990_ADC_HPF_CUT_SHIFT, - WM8990_ADC_HPF_CUT_MASK, - wm8990_adcmode); - -static const struct snd_kcontrol_new wm8990_snd_controls[] = { -/* INMIXL */ -SOC_SINGLE("LIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L12MNBST_BIT, 1, 0), -SOC_SINGLE("LIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L34MNBST_BIT, 1, 0), -/* INMIXR */ -SOC_SINGLE("RIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R12MNBST_BIT, 1, 0), -SOC_SINGLE("RIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R34MNBST_BIT, 1, 0), - -/* LOMIX */ -SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER3, - WM8990_LLI3LOVOL_SHIFT, WM8990_LLI3LOVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3, - WM8990_LR12LOVOL_SHIFT, WM8990_LR12LOVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3, - WM8990_LL12LOVOL_SHIFT, WM8990_LL12LOVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER5, - WM8990_LRI3LOVOL_SHIFT, WM8990_LRI3LOVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER5, - WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER5, - WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv), - -/* ROMIX */ -SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER4, - WM8990_RRI3ROVOL_SHIFT, WM8990_RRI3ROVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4, - WM8990_RL12ROVOL_SHIFT, WM8990_RL12ROVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4, - WM8990_RR12ROVOL_SHIFT, WM8990_RR12ROVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER6, - WM8990_RLI3ROVOL_SHIFT, WM8990_RLI3ROVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER6, - WM8990_RLBROVOL_SHIFT, WM8990_RLBROVOL_MASK, 1, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER6, - WM8990_RRBROVOL_SHIFT, WM8990_RRBROVOL_MASK, 1, out_mix_tlv), - -/* LOUT */ -SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8990_LEFT_OUTPUT_VOLUME, - WM8990_LOUTVOL_SHIFT, WM8990_LOUTVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("LOUT ZC", WM8990_LEFT_OUTPUT_VOLUME, WM8990_LOZC_BIT, 1, 0), - -/* ROUT */ -SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8990_RIGHT_OUTPUT_VOLUME, - WM8990_ROUTVOL_SHIFT, WM8990_ROUTVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("ROUT ZC", WM8990_RIGHT_OUTPUT_VOLUME, WM8990_ROZC_BIT, 1, 0), - -/* LOPGA */ -SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8990_LEFT_OPGA_VOLUME, - WM8990_LOPGAVOL_SHIFT, WM8990_LOPGAVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("LOPGA ZC Switch", WM8990_LEFT_OPGA_VOLUME, - WM8990_LOPGAZC_BIT, 1, 0), - -/* ROPGA */ -SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8990_RIGHT_OPGA_VOLUME, - WM8990_ROPGAVOL_SHIFT, WM8990_ROPGAVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("ROPGA ZC Switch", WM8990_RIGHT_OPGA_VOLUME, - WM8990_ROPGAZC_BIT, 1, 0), - -SOC_SINGLE("LON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME, - WM8990_LONMUTE_BIT, 1, 0), -SOC_SINGLE("LOP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME, - WM8990_LOPMUTE_BIT, 1, 0), -SOC_SINGLE("LOP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME, - WM8990_LOATTN_BIT, 1, 0), -SOC_SINGLE("RON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME, - WM8990_RONMUTE_BIT, 1, 0), -SOC_SINGLE("ROP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME, - WM8990_ROPMUTE_BIT, 1, 0), -SOC_SINGLE("ROP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME, - WM8990_ROATTN_BIT, 1, 0), - -SOC_SINGLE("OUT3 Mute Switch", WM8990_OUT3_4_VOLUME, - WM8990_OUT3MUTE_BIT, 1, 0), -SOC_SINGLE("OUT3 Attenuation Switch", WM8990_OUT3_4_VOLUME, - WM8990_OUT3ATTN_BIT, 1, 0), - -SOC_SINGLE("OUT4 Mute Switch", WM8990_OUT3_4_VOLUME, - WM8990_OUT4MUTE_BIT, 1, 0), -SOC_SINGLE("OUT4 Attenuation Switch", WM8990_OUT3_4_VOLUME, - WM8990_OUT4ATTN_BIT, 1, 0), - -SOC_SINGLE("Speaker Mode Switch", WM8990_CLASSD1, - WM8990_CDMODE_BIT, 1, 0), - -SOC_SINGLE("Speaker Output Attenuation Volume", WM8990_SPEAKER_VOLUME, - WM8990_SPKATTN_SHIFT, WM8990_SPKATTN_MASK, 0), -SOC_SINGLE("Speaker DC Boost Volume", WM8990_CLASSD3, - WM8990_DCGAIN_SHIFT, WM8990_DCGAIN_MASK, 0), -SOC_SINGLE("Speaker AC Boost Volume", WM8990_CLASSD3, - WM8990_ACGAIN_SHIFT, WM8990_ACGAIN_MASK, 0), -SOC_SINGLE_TLV("Speaker Volume", WM8990_CLASSD4, - WM8990_SPKVOL_SHIFT, WM8990_SPKVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("Speaker ZC Switch", WM8990_CLASSD4, - WM8990_SPKZC_SHIFT, WM8990_SPKZC_MASK, 0), - -SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume", - WM8990_LEFT_DAC_DIGITAL_VOLUME, - WM8990_DACL_VOL_SHIFT, - WM8990_DACL_VOL_MASK, - 0, - out_dac_tlv), - -SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume", - WM8990_RIGHT_DAC_DIGITAL_VOLUME, - WM8990_DACR_VOL_SHIFT, - WM8990_DACR_VOL_MASK, - 0, - out_dac_tlv), - -SOC_ENUM("Left Digital Sidetone", wm8990_left_digital_sidetone_enum), -SOC_ENUM("Right Digital Sidetone", wm8990_right_digital_sidetone_enum), - -SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE, - WM8990_ADCL_DAC_SVOL_SHIFT, WM8990_ADCL_DAC_SVOL_MASK, 0, - out_sidetone_tlv), -SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE, - WM8990_ADCR_DAC_SVOL_SHIFT, WM8990_ADCR_DAC_SVOL_MASK, 0, - out_sidetone_tlv), - -SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8990_ADC_CTRL, - WM8990_ADC_HPF_ENA_BIT, 1, 0), - -SOC_ENUM("ADC HPF Mode", wm8990_right_adcmode_enum), - -SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume", - WM8990_LEFT_ADC_DIGITAL_VOLUME, - WM8990_ADCL_VOL_SHIFT, - WM8990_ADCL_VOL_MASK, - 0, - in_adc_tlv), - -SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume", - WM8990_RIGHT_ADC_DIGITAL_VOLUME, - WM8990_ADCR_VOL_SHIFT, - WM8990_ADCR_VOL_MASK, - 0, - in_adc_tlv), - -SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume", - WM8990_LEFT_LINE_INPUT_1_2_VOLUME, - WM8990_LIN12VOL_SHIFT, - WM8990_LIN12VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("LIN12 ZC Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME, - WM8990_LI12ZC_BIT, 1, 0), - -SOC_SINGLE("LIN12 Mute Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME, - WM8990_LI12MUTE_BIT, 1, 0), - -SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume", - WM8990_LEFT_LINE_INPUT_3_4_VOLUME, - WM8990_LIN34VOL_SHIFT, - WM8990_LIN34VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("LIN34 ZC Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME, - WM8990_LI34ZC_BIT, 1, 0), - -SOC_SINGLE("LIN34 Mute Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME, - WM8990_LI34MUTE_BIT, 1, 0), - -SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume", - WM8990_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8990_RIN12VOL_SHIFT, - WM8990_RIN12VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("RIN12 ZC Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8990_RI12ZC_BIT, 1, 0), - -SOC_SINGLE("RIN12 Mute Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8990_RI12MUTE_BIT, 1, 0), - -SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume", - WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8990_RIN34VOL_SHIFT, - WM8990_RIN34VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("RIN34 ZC Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8990_RI34ZC_BIT, 1, 0), - -SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8990_RI34MUTE_BIT, 1, 0), - -}; - -/* - * _DAPM_ Controls - */ - -static int inmixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - u16 reg, fakepower; - - reg = snd_soc_read(w->codec, WM8990_POWER_MANAGEMENT_2); - fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS); - - if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) | - (1 << WM8990_AINLMUX_PWR_BIT))) { - reg |= WM8990_AINL_ENA; - } else { - reg &= ~WM8990_AINL_ENA; - } - - if (fakepower & ((1 << WM8990_INMIXR_PWR_BIT) | - (1 << WM8990_AINRMUX_PWR_BIT))) { - reg |= WM8990_AINR_ENA; - } else { - reg &= ~WM8990_AINR_ENA; - } - snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg); - - return 0; -} - -static int outmixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - u32 reg_shift = kcontrol->private_value & 0xfff; - int ret = 0; - u16 reg; - - switch (reg_shift) { - case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : - reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER1); - if (reg & WM8990_LDLO) { - printk(KERN_WARNING - "Cannot set as Output Mixer 1 LDLO Set\n"); - ret = -1; - } - break; - case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): - reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER2); - if (reg & WM8990_RDRO) { - printk(KERN_WARNING - "Cannot set as Output Mixer 2 RDRO Set\n"); - ret = -1; - } - break; - case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): - reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER); - if (reg & WM8990_LDSPK) { - printk(KERN_WARNING - "Cannot set as Speaker Mixer LDSPK Set\n"); - ret = -1; - } - break; - case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): - reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER); - if (reg & WM8990_RDSPK) { - printk(KERN_WARNING - "Cannot set as Speaker Mixer RDSPK Set\n"); - ret = -1; - } - break; - } - - return ret; -} - -/* INMIX dB values */ -static const unsigned int in_mix_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 7, TLV_DB_SCALE_ITEM(-1200, 600, 0), -}; - -/* Left In PGA Connections */ -static const struct snd_kcontrol_new wm8990_dapm_lin12_pga_controls[] = { -SOC_DAPM_SINGLE("LIN1 Switch", WM8990_INPUT_MIXER2, WM8990_LMN1_BIT, 1, 0), -SOC_DAPM_SINGLE("LIN2 Switch", WM8990_INPUT_MIXER2, WM8990_LMP2_BIT, 1, 0), -}; - -static const struct snd_kcontrol_new wm8990_dapm_lin34_pga_controls[] = { -SOC_DAPM_SINGLE("LIN3 Switch", WM8990_INPUT_MIXER2, WM8990_LMN3_BIT, 1, 0), -SOC_DAPM_SINGLE("LIN4 Switch", WM8990_INPUT_MIXER2, WM8990_LMP4_BIT, 1, 0), -}; - -/* Right In PGA Connections */ -static const struct snd_kcontrol_new wm8990_dapm_rin12_pga_controls[] = { -SOC_DAPM_SINGLE("RIN1 Switch", WM8990_INPUT_MIXER2, WM8990_RMN1_BIT, 1, 0), -SOC_DAPM_SINGLE("RIN2 Switch", WM8990_INPUT_MIXER2, WM8990_RMP2_BIT, 1, 0), -}; - -static const struct snd_kcontrol_new wm8990_dapm_rin34_pga_controls[] = { -SOC_DAPM_SINGLE("RIN3 Switch", WM8990_INPUT_MIXER2, WM8990_RMN3_BIT, 1, 0), -SOC_DAPM_SINGLE("RIN4 Switch", WM8990_INPUT_MIXER2, WM8990_RMP4_BIT, 1, 0), -}; - -/* INMIXL */ -static const struct snd_kcontrol_new wm8990_dapm_inmixl_controls[] = { -SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8990_INPUT_MIXER3, - WM8990_LDBVOL_SHIFT, WM8990_LDBVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8990_INPUT_MIXER5, WM8990_LI2BVOL_SHIFT, - 7, 0, in_mix_tlv), -SOC_DAPM_SINGLE("LINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT, - 1, 0), -SOC_DAPM_SINGLE("LINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT, - 1, 0), -}; - -/* INMIXR */ -static const struct snd_kcontrol_new wm8990_dapm_inmixr_controls[] = { -SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8990_INPUT_MIXER4, - WM8990_RDBVOL_SHIFT, WM8990_RDBVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8990_INPUT_MIXER6, WM8990_RI2BVOL_SHIFT, - 7, 0, in_mix_tlv), -SOC_DAPM_SINGLE("RINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT, - 1, 0), -SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT, - 1, 0), -}; - -/* AINLMUX */ -static const char *wm8990_ainlmux[] = - {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; - -static const struct soc_enum wm8990_ainlmux_enum = -SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, - ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux); - -static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls = -SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); - -/* DIFFINL */ - -/* AINRMUX */ -static const char *wm8990_ainrmux[] = - {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; - -static const struct soc_enum wm8990_ainrmux_enum = -SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, - ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux); - -static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls = -SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum); - -/* RXVOICE */ -static const struct snd_kcontrol_new wm8990_dapm_rxvoice_controls[] = { -SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8990_INPUT_MIXER5, WM8990_LR4BVOL_SHIFT, - WM8990_LR4BVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8990_INPUT_MIXER6, WM8990_RL4BVOL_SHIFT, - WM8990_RL4BVOL_MASK, 0, in_mix_tlv), -}; - -/* LOMIX */ -static const struct snd_kcontrol_new wm8990_dapm_lomix_controls[] = { -SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER1, - WM8990_LRBLO_BIT, 1, 0), -SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER1, - WM8990_LLBLO_BIT, 1, 0), -SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER1, - WM8990_LRI3LO_BIT, 1, 0), -SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER1, - WM8990_LLI3LO_BIT, 1, 0), -SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1, - WM8990_LR12LO_BIT, 1, 0), -SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1, - WM8990_LL12LO_BIT, 1, 0), -SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8990_OUTPUT_MIXER1, - WM8990_LDLO_BIT, 1, 0), -}; - -/* ROMIX */ -static const struct snd_kcontrol_new wm8990_dapm_romix_controls[] = { -SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER2, - WM8990_RLBRO_BIT, 1, 0), -SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER2, - WM8990_RRBRO_BIT, 1, 0), -SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER2, - WM8990_RLI3RO_BIT, 1, 0), -SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER2, - WM8990_RRI3RO_BIT, 1, 0), -SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2, - WM8990_RL12RO_BIT, 1, 0), -SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2, - WM8990_RR12RO_BIT, 1, 0), -SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8990_OUTPUT_MIXER2, - WM8990_RDRO_BIT, 1, 0), -}; - -/* LONMIX */ -static const struct snd_kcontrol_new wm8990_dapm_lonmix_controls[] = { -SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1, - WM8990_LLOPGALON_BIT, 1, 0), -SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER1, - WM8990_LROPGALON_BIT, 1, 0), -SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8990_LINE_MIXER1, - WM8990_LOPLON_BIT, 1, 0), -}; - -/* LOPMIX */ -static const struct snd_kcontrol_new wm8990_dapm_lopmix_controls[] = { -SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER1, - WM8990_LR12LOP_BIT, 1, 0), -SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER1, - WM8990_LL12LOP_BIT, 1, 0), -SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1, - WM8990_LLOPGALOP_BIT, 1, 0), -}; - -/* RONMIX */ -static const struct snd_kcontrol_new wm8990_dapm_ronmix_controls[] = { -SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2, - WM8990_RROPGARON_BIT, 1, 0), -SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER2, - WM8990_RLOPGARON_BIT, 1, 0), -SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8990_LINE_MIXER2, - WM8990_ROPRON_BIT, 1, 0), -}; - -/* ROPMIX */ -static const struct snd_kcontrol_new wm8990_dapm_ropmix_controls[] = { -SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER2, - WM8990_RL12ROP_BIT, 1, 0), -SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER2, - WM8990_RR12ROP_BIT, 1, 0), -SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2, - WM8990_RROPGAROP_BIT, 1, 0), -}; - -/* OUT3MIX */ -static const struct snd_kcontrol_new wm8990_dapm_out3mix_controls[] = { -SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER, - WM8990_LI4O3_BIT, 1, 0), -SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8990_OUT3_4_MIXER, - WM8990_LPGAO3_BIT, 1, 0), -}; - -/* OUT4MIX */ -static const struct snd_kcontrol_new wm8990_dapm_out4mix_controls[] = { -SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8990_OUT3_4_MIXER, - WM8990_RPGAO4_BIT, 1, 0), -SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER, - WM8990_RI4O4_BIT, 1, 0), -}; - -/* SPKMIX */ -static const struct snd_kcontrol_new wm8990_dapm_spkmix_controls[] = { -SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8990_SPEAKER_MIXER, - WM8990_LI2SPK_BIT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8990_SPEAKER_MIXER, - WM8990_LB2SPK_BIT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8990_SPEAKER_MIXER, - WM8990_LOPGASPK_BIT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8990_SPEAKER_MIXER, - WM8990_LDSPK_BIT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8990_SPEAKER_MIXER, - WM8990_RDSPK_BIT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8990_SPEAKER_MIXER, - WM8990_ROPGASPK_BIT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8990_SPEAKER_MIXER, - WM8990_RL12ROP_BIT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8990_SPEAKER_MIXER, - WM8990_RI2SPK_BIT, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8990_dapm_widgets[] = { -/* Input Side */ -/* Input Lines */ -SND_SOC_DAPM_INPUT("LIN1"), -SND_SOC_DAPM_INPUT("LIN2"), -SND_SOC_DAPM_INPUT("LIN3"), -SND_SOC_DAPM_INPUT("LIN4/RXN"), -SND_SOC_DAPM_INPUT("RIN3"), -SND_SOC_DAPM_INPUT("RIN4/RXP"), -SND_SOC_DAPM_INPUT("RIN1"), -SND_SOC_DAPM_INPUT("RIN2"), -SND_SOC_DAPM_INPUT("Internal ADC Source"), - -/* DACs */ -SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2, - WM8990_ADCL_ENA_BIT, 0), -SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8990_POWER_MANAGEMENT_2, - WM8990_ADCR_ENA_BIT, 0), - -/* Input PGAs */ -SND_SOC_DAPM_MIXER("LIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN12_ENA_BIT, - 0, &wm8990_dapm_lin12_pga_controls[0], - ARRAY_SIZE(wm8990_dapm_lin12_pga_controls)), -SND_SOC_DAPM_MIXER("LIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN34_ENA_BIT, - 0, &wm8990_dapm_lin34_pga_controls[0], - ARRAY_SIZE(wm8990_dapm_lin34_pga_controls)), -SND_SOC_DAPM_MIXER("RIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN12_ENA_BIT, - 0, &wm8990_dapm_rin12_pga_controls[0], - ARRAY_SIZE(wm8990_dapm_rin12_pga_controls)), -SND_SOC_DAPM_MIXER("RIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN34_ENA_BIT, - 0, &wm8990_dapm_rin34_pga_controls[0], - ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)), - -/* INMIXL */ -SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0, - &wm8990_dapm_inmixl_controls[0], - ARRAY_SIZE(wm8990_dapm_inmixl_controls), - inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* AINLMUX */ -SND_SOC_DAPM_MUX_E("AINLMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0, - &wm8990_dapm_ainlmux_controls, inmixer_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* INMIXR */ -SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0, - &wm8990_dapm_inmixr_controls[0], - ARRAY_SIZE(wm8990_dapm_inmixr_controls), - inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* AINRMUX */ -SND_SOC_DAPM_MUX_E("AINRMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0, - &wm8990_dapm_ainrmux_controls, inmixer_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* Output Side */ -/* DACs */ -SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8990_POWER_MANAGEMENT_3, - WM8990_DACL_ENA_BIT, 0), -SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8990_POWER_MANAGEMENT_3, - WM8990_DACR_ENA_BIT, 0), - -/* LOMIX */ -SND_SOC_DAPM_MIXER_E("LOMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOMIX_ENA_BIT, - 0, &wm8990_dapm_lomix_controls[0], - ARRAY_SIZE(wm8990_dapm_lomix_controls), - outmixer_event, SND_SOC_DAPM_PRE_REG), - -/* LONMIX */ -SND_SOC_DAPM_MIXER("LONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LON_ENA_BIT, 0, - &wm8990_dapm_lonmix_controls[0], - ARRAY_SIZE(wm8990_dapm_lonmix_controls)), - -/* LOPMIX */ -SND_SOC_DAPM_MIXER("LOPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOP_ENA_BIT, 0, - &wm8990_dapm_lopmix_controls[0], - ARRAY_SIZE(wm8990_dapm_lopmix_controls)), - -/* OUT3MIX */ -SND_SOC_DAPM_MIXER("OUT3MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT3_ENA_BIT, 0, - &wm8990_dapm_out3mix_controls[0], - ARRAY_SIZE(wm8990_dapm_out3mix_controls)), - -/* SPKMIX */ -SND_SOC_DAPM_MIXER_E("SPKMIX", WM8990_POWER_MANAGEMENT_1, WM8990_SPK_ENA_BIT, 0, - &wm8990_dapm_spkmix_controls[0], - ARRAY_SIZE(wm8990_dapm_spkmix_controls), outmixer_event, - SND_SOC_DAPM_PRE_REG), - -/* OUT4MIX */ -SND_SOC_DAPM_MIXER("OUT4MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT4_ENA_BIT, 0, - &wm8990_dapm_out4mix_controls[0], - ARRAY_SIZE(wm8990_dapm_out4mix_controls)), - -/* ROPMIX */ -SND_SOC_DAPM_MIXER("ROPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROP_ENA_BIT, 0, - &wm8990_dapm_ropmix_controls[0], - ARRAY_SIZE(wm8990_dapm_ropmix_controls)), - -/* RONMIX */ -SND_SOC_DAPM_MIXER("RONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_RON_ENA_BIT, 0, - &wm8990_dapm_ronmix_controls[0], - ARRAY_SIZE(wm8990_dapm_ronmix_controls)), - -/* ROMIX */ -SND_SOC_DAPM_MIXER_E("ROMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROMIX_ENA_BIT, - 0, &wm8990_dapm_romix_controls[0], - ARRAY_SIZE(wm8990_dapm_romix_controls), - outmixer_event, SND_SOC_DAPM_PRE_REG), - -/* LOUT PGA */ -SND_SOC_DAPM_PGA("LOUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_LOUT_ENA_BIT, 0, - NULL, 0), - -/* ROUT PGA */ -SND_SOC_DAPM_PGA("ROUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_ROUT_ENA_BIT, 0, - NULL, 0), - -/* LOPGA */ -SND_SOC_DAPM_PGA("LOPGA", WM8990_POWER_MANAGEMENT_3, WM8990_LOPGA_ENA_BIT, 0, - NULL, 0), - -/* ROPGA */ -SND_SOC_DAPM_PGA("ROPGA", WM8990_POWER_MANAGEMENT_3, WM8990_ROPGA_ENA_BIT, 0, - NULL, 0), - -/* MICBIAS */ -SND_SOC_DAPM_SUPPLY("MICBIAS", WM8990_POWER_MANAGEMENT_1, - WM8990_MICBIAS_ENA_BIT, 0, NULL, 0), - -SND_SOC_DAPM_OUTPUT("LON"), -SND_SOC_DAPM_OUTPUT("LOP"), -SND_SOC_DAPM_OUTPUT("OUT3"), -SND_SOC_DAPM_OUTPUT("LOUT"), -SND_SOC_DAPM_OUTPUT("SPKN"), -SND_SOC_DAPM_OUTPUT("SPKP"), -SND_SOC_DAPM_OUTPUT("ROUT"), -SND_SOC_DAPM_OUTPUT("OUT4"), -SND_SOC_DAPM_OUTPUT("ROP"), -SND_SOC_DAPM_OUTPUT("RON"), - -SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Make DACs turn on when playing even if not mixed into any outputs */ - {"Internal DAC Sink", NULL, "Left DAC"}, - {"Internal DAC Sink", NULL, "Right DAC"}, - - /* Make ADCs turn on when recording even if not mixed from any inputs */ - {"Left ADC", NULL, "Internal ADC Source"}, - {"Right ADC", NULL, "Internal ADC Source"}, - - /* Input Side */ - /* LIN12 PGA */ - {"LIN12 PGA", "LIN1 Switch", "LIN1"}, - {"LIN12 PGA", "LIN2 Switch", "LIN2"}, - /* LIN34 PGA */ - {"LIN34 PGA", "LIN3 Switch", "LIN3"}, - {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"}, - /* INMIXL */ - {"INMIXL", "Record Left Volume", "LOMIX"}, - {"INMIXL", "LIN2 Volume", "LIN2"}, - {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, - {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, - /* AINLMUX */ - {"AINLMUX", "INMIXL Mix", "INMIXL"}, - {"AINLMUX", "DIFFINL Mix", "LIN12 PGA"}, - {"AINLMUX", "DIFFINL Mix", "LIN34 PGA"}, - {"AINLMUX", "RXVOICE Mix", "LIN4/RXN"}, - {"AINLMUX", "RXVOICE Mix", "RIN4/RXP"}, - /* ADC */ - {"Left ADC", NULL, "AINLMUX"}, - - /* RIN12 PGA */ - {"RIN12 PGA", "RIN1 Switch", "RIN1"}, - {"RIN12 PGA", "RIN2 Switch", "RIN2"}, - /* RIN34 PGA */ - {"RIN34 PGA", "RIN3 Switch", "RIN3"}, - {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"}, - /* INMIXL */ - {"INMIXR", "Record Right Volume", "ROMIX"}, - {"INMIXR", "RIN2 Volume", "RIN2"}, - {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, - {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, - /* AINRMUX */ - {"AINRMUX", "INMIXR Mix", "INMIXR"}, - {"AINRMUX", "DIFFINR Mix", "RIN12 PGA"}, - {"AINRMUX", "DIFFINR Mix", "RIN34 PGA"}, - {"AINRMUX", "RXVOICE Mix", "LIN4/RXN"}, - {"AINRMUX", "RXVOICE Mix", "RIN4/RXP"}, - /* ADC */ - {"Right ADC", NULL, "AINRMUX"}, - - /* LOMIX */ - {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, - {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"}, - {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, - {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, - {"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"}, - {"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"}, - {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"}, - - /* ROMIX */ - {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"}, - {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"}, - {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, - {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, - {"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"}, - {"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"}, - {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"}, - - /* SPKMIX */ - {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"}, - {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"}, - {"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"}, - {"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"}, - {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"}, - {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"}, - {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"}, - {"SPKMIX", "SPKMIX Left DAC Switch", "Left DAC"}, - - /* LONMIX */ - {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"}, - {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"}, - {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"}, - - /* LOPMIX */ - {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"}, - {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"}, - {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, - - /* OUT3MIX */ - {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"}, - {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, - - /* OUT4MIX */ - {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"}, - {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"}, - - /* RONMIX */ - {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"}, - {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"}, - {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"}, - - /* ROPMIX */ - {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"}, - {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"}, - {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"}, - - /* Out Mixer PGAs */ - {"LOPGA", NULL, "LOMIX"}, - {"ROPGA", NULL, "ROMIX"}, - - {"LOUT PGA", NULL, "LOMIX"}, - {"ROUT PGA", NULL, "ROMIX"}, - - /* Output Pins */ - {"LON", NULL, "LONMIX"}, - {"LOP", NULL, "LOPMIX"}, - {"OUT3", NULL, "OUT3MIX"}, - {"LOUT", NULL, "LOUT PGA"}, - {"SPKN", NULL, "SPKMIX"}, - {"ROUT", NULL, "ROUT PGA"}, - {"OUT4", NULL, "OUT4MIX"}, - {"ROP", NULL, "ROPMIX"}, - {"RON", NULL, "RONMIX"}, -}; - -static int wm8990_add_widgets(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, wm8990_dapm_widgets, - ARRAY_SIZE(wm8990_dapm_widgets)); - /* set up the WM8990 audio map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - -/* PLL divisors */ -struct _pll_div { - u32 div2; - u32 n; - u32 k; -}; - -/* The size in bits of the pll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 16) * 10) - -static void pll_factors(struct _pll_div *pll_div, unsigned int target, - unsigned int source) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod; - - - Ndiv = target / source; - if (Ndiv < 6) { - source >>= 1; - pll_div->div2 = 1; - Ndiv = target / source; - } else - pll_div->div2 = 0; - - if ((Ndiv < 6) || (Ndiv > 12)) - printk(KERN_WARNING - "WM8990 N value outwith recommended range! N = %u\n", Ndiv); - - pll_div->n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div->k = K; -} - -static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct _pll_div pll_div; - - if (freq_in && freq_out) { - pll_factors(&pll_div, freq_out * 4, freq_in); - - /* Turn on PLL */ - snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2, - WM8990_PLL_ENA, WM8990_PLL_ENA); - - /* sysclk comes from PLL */ - snd_soc_update_bits(codec, WM8990_CLOCKING_2, - WM8990_SYSCLK_SRC, WM8990_SYSCLK_SRC); - - /* set up N , fractional mode and pre-divisor if necessary */ - snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | - (pll_div.div2?WM8990_PRESCALE:0)); - snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); - snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF)); - } else { - /* Turn off PLL */ - snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2, - WM8990_PLL_ENA, 0); - } - return 0; -} - -/* - * Clock after PLL and dividers - */ -static int wm8990_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec); - - wm8990->sysclk = freq; - return 0; -} - -/* - * Set's ADC and Voice DAC format. - */ -static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 audio1, audio3; - - audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); - audio3 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_3); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - audio3 &= ~WM8990_AIF_MSTR1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - audio3 |= WM8990_AIF_MSTR1; - break; - default: - return -EINVAL; - } - - audio1 &= ~WM8990_AIF_FMT_MASK; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - audio1 |= WM8990_AIF_TMF_I2S; - audio1 &= ~WM8990_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_RIGHT_J: - audio1 |= WM8990_AIF_TMF_RIGHTJ; - audio1 &= ~WM8990_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_LEFT_J: - audio1 |= WM8990_AIF_TMF_LEFTJ; - audio1 &= ~WM8990_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_A: - audio1 |= WM8990_AIF_TMF_DSP; - audio1 &= ~WM8990_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_B: - audio1 |= WM8990_AIF_TMF_DSP | WM8990_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); - snd_soc_write(codec, WM8990_AUDIO_INTERFACE_3, audio3); - return 0; -} - -static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - - switch (div_id) { - case WM8990_MCLK_DIV: - snd_soc_update_bits(codec, WM8990_CLOCKING_2, - WM8990_MCLK_DIV_MASK, div); - break; - case WM8990_DACCLK_DIV: - snd_soc_update_bits(codec, WM8990_CLOCKING_2, - WM8990_DAC_CLKDIV_MASK, div); - break; - case WM8990_ADCCLK_DIV: - snd_soc_update_bits(codec, WM8990_CLOCKING_2, - WM8990_ADC_CLKDIV_MASK, div); - break; - case WM8990_BCLK_DIV: - snd_soc_update_bits(codec, WM8990_CLOCKING_1, - WM8990_BCLK_DIV_MASK, div); - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * Set PCM DAI bit size and sample rate. - */ -static int wm8990_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); - - audio1 &= ~WM8990_AIF_WL_MASK; - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - audio1 |= WM8990_AIF_WL_20BITS; - break; - case SNDRV_PCM_FORMAT_S24_LE: - audio1 |= WM8990_AIF_WL_24BITS; - break; - case SNDRV_PCM_FORMAT_S32_LE: - audio1 |= WM8990_AIF_WL_32BITS; - break; - } - - snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); - return 0; -} - -static int wm8990_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 val; - - val = snd_soc_read(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; - - if (mute) - snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); - else - snd_soc_write(codec, WM8990_DAC_CTRL, val); - - return 0; -} - -static int wm8990_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID=2*50k */ - snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1, - WM8990_VMID_MODE_MASK, 0x2); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = snd_soc_cache_sync(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to sync cache: %d\n", ret); - return ret; - } - - /* Enable all output discharge bits */ - snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | - WM8990_DIS_RLINE | WM8990_DIS_OUT3 | - WM8990_DIS_OUT4 | WM8990_DIS_LOUT | - WM8990_DIS_ROUT); - - /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | - WM8990_BUFDCOPEN | WM8990_POBCTRL | - WM8990_VMIDTOG); - - /* Delay to allow output caps to discharge */ - msleep(300); - - /* Disable VMIDTOG */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | - WM8990_BUFDCOPEN | WM8990_POBCTRL); - - /* disable all output discharge bits */ - snd_soc_write(codec, WM8990_ANTIPOP1, 0); - - /* Enable outputs */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00); - - msleep(50); - - /* Enable VMID at 2x50k */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02); - - msleep(100); - - /* Enable VREF */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); - - msleep(600); - - /* Enable BUFIOEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | - WM8990_BUFDCOPEN | WM8990_POBCTRL | - WM8990_BUFIOEN); - - /* Disable outputs */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3); - - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); - - /* Enable workaround for ADC clocking issue. */ - snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0x2); - snd_soc_write(codec, WM8990_EXT_CTL1, 0xa003); - snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0); - } - - /* VMID=2*250k */ - snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1, - WM8990_VMID_MODE_MASK, 0x4); - break; - - case SND_SOC_BIAS_OFF: - /* Enable POBCTRL and SOFT_ST */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | - WM8990_POBCTRL | WM8990_BUFIOEN); - - /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | - WM8990_BUFDCOPEN | WM8990_POBCTRL | - WM8990_BUFIOEN); - - /* mute DAC */ - snd_soc_update_bits(codec, WM8990_DAC_CTRL, - WM8990_DAC_MUTE, WM8990_DAC_MUTE); - - /* Enable any disabled outputs */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); - - /* Disable VMID */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01); - - msleep(300); - - /* Enable all output discharge bits */ - snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | - WM8990_DIS_RLINE | WM8990_DIS_OUT3 | - WM8990_DIS_OUT4 | WM8990_DIS_LOUT | - WM8990_DIS_ROUT); - - /* Disable VREF */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0); - - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, 0x0); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#define WM8990_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000) - -#define WM8990_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -/* - * The WM8990 supports 2 different and mutually exclusive DAI - * configurations. - * - * 1. ADC/DAC on Primary Interface - * 2. ADC on Primary Interface/DAC on secondary - */ -static const struct snd_soc_dai_ops wm8990_dai_ops = { - .hw_params = wm8990_hw_params, - .digital_mute = wm8990_mute, - .set_fmt = wm8990_set_dai_fmt, - .set_clkdiv = wm8990_set_dai_clkdiv, - .set_pll = wm8990_set_dai_pll, - .set_sysclk = wm8990_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver wm8990_dai = { -/* ADC/DAC on primary */ - .name = "wm8990-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8990_RATES, - .formats = WM8990_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8990_RATES, - .formats = WM8990_FORMATS,}, - .ops = &wm8990_dai_ops, -}; - -static int wm8990_suspend(struct snd_soc_codec *codec) -{ - wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8990_resume(struct snd_soc_codec *codec) -{ - wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -/* - * initialise the WM8990 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8990_probe(struct snd_soc_codec *codec) -{ - int ret; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret < 0) { - printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); - return ret; - } - - wm8990_reset(codec); - - /* charge output caps */ - wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - snd_soc_update_bits(codec, WM8990_AUDIO_INTERFACE_4, - WM8990_ALRCGPIO1, WM8990_ALRCGPIO1); - - snd_soc_update_bits(codec, WM8990_GPIO1_GPIO2, - WM8990_GPIO1_SEL_MASK, 1); - - snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2, - WM8990_OPCLK_ENA, WM8990_OPCLK_ENA); - - snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); - snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); - - snd_soc_add_codec_controls(codec, wm8990_snd_controls, - ARRAY_SIZE(wm8990_snd_controls)); - wm8990_add_widgets(codec); - - return 0; -} - -/* power down chip */ -static int wm8990_remove(struct snd_soc_codec *codec) -{ - wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { - .probe = wm8990_probe, - .remove = wm8990_remove, - .suspend = wm8990_suspend, - .resume = wm8990_resume, - .set_bias_level = wm8990_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm8990_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8990_reg, - .volatile_register = wm8990_volatile_register, -}; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8990_priv *wm8990; - int ret; - - wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); - if (wm8990 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8990); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8990, &wm8990_dai, 1); - if (ret < 0) - kfree(wm8990); - return ret; -} - -static __devexit int wm8990_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8990_i2c_id[] = { - { "wm8990", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id); - -static struct i2c_driver wm8990_i2c_driver = { - .driver = { - .name = "wm8990", - .owner = THIS_MODULE, - }, - .probe = wm8990_i2c_probe, - .remove = __devexit_p(wm8990_i2c_remove), - .id_table = wm8990_i2c_id, -}; -#endif - -static int __init wm8990_modinit(void) -{ - int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8990_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(wm8990_modinit); - -static void __exit wm8990_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8990_i2c_driver); -#endif -} -module_exit(wm8990_exit); - -MODULE_DESCRIPTION("ASoC WM8990 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8990.h b/ANDROID_3.4.5/sound/soc/codecs/wm8990.h deleted file mode 100644 index 77c98a4b..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8990.h +++ /dev/null @@ -1,835 +0,0 @@ -/* - * wm8990.h -- audio driver for WM8990 - * - * Copyright 2007 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com - * - * 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. - * - */ - -#ifndef __WM8990REGISTERDEFS_H__ -#define __WM8990REGISTERDEFS_H__ - -/* - * Register values. - */ -#define WM8990_RESET 0x00 -#define WM8990_POWER_MANAGEMENT_1 0x01 -#define WM8990_POWER_MANAGEMENT_2 0x02 -#define WM8990_POWER_MANAGEMENT_3 0x03 -#define WM8990_AUDIO_INTERFACE_1 0x04 -#define WM8990_AUDIO_INTERFACE_2 0x05 -#define WM8990_CLOCKING_1 0x06 -#define WM8990_CLOCKING_2 0x07 -#define WM8990_AUDIO_INTERFACE_3 0x08 -#define WM8990_AUDIO_INTERFACE_4 0x09 -#define WM8990_DAC_CTRL 0x0A -#define WM8990_LEFT_DAC_DIGITAL_VOLUME 0x0B -#define WM8990_RIGHT_DAC_DIGITAL_VOLUME 0x0C -#define WM8990_DIGITAL_SIDE_TONE 0x0D -#define WM8990_ADC_CTRL 0x0E -#define WM8990_LEFT_ADC_DIGITAL_VOLUME 0x0F -#define WM8990_RIGHT_ADC_DIGITAL_VOLUME 0x10 -#define WM8990_GPIO_CTRL_1 0x12 -#define WM8990_GPIO1_GPIO2 0x13 -#define WM8990_GPIO3_GPIO4 0x14 -#define WM8990_GPIO5_GPIO6 0x15 -#define WM8990_GPIOCTRL_2 0x16 -#define WM8990_GPIO_POL 0x17 -#define WM8990_LEFT_LINE_INPUT_1_2_VOLUME 0x18 -#define WM8990_LEFT_LINE_INPUT_3_4_VOLUME 0x19 -#define WM8990_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A -#define WM8990_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B -#define WM8990_LEFT_OUTPUT_VOLUME 0x1C -#define WM8990_RIGHT_OUTPUT_VOLUME 0x1D -#define WM8990_LINE_OUTPUTS_VOLUME 0x1E -#define WM8990_OUT3_4_VOLUME 0x1F -#define WM8990_LEFT_OPGA_VOLUME 0x20 -#define WM8990_RIGHT_OPGA_VOLUME 0x21 -#define WM8990_SPEAKER_VOLUME 0x22 -#define WM8990_CLASSD1 0x23 -#define WM8990_CLASSD3 0x25 -#define WM8990_CLASSD4 0x26 -#define WM8990_INPUT_MIXER1 0x27 -#define WM8990_INPUT_MIXER2 0x28 -#define WM8990_INPUT_MIXER3 0x29 -#define WM8990_INPUT_MIXER4 0x2A -#define WM8990_INPUT_MIXER5 0x2B -#define WM8990_INPUT_MIXER6 0x2C -#define WM8990_OUTPUT_MIXER1 0x2D -#define WM8990_OUTPUT_MIXER2 0x2E -#define WM8990_OUTPUT_MIXER3 0x2F -#define WM8990_OUTPUT_MIXER4 0x30 -#define WM8990_OUTPUT_MIXER5 0x31 -#define WM8990_OUTPUT_MIXER6 0x32 -#define WM8990_OUT3_4_MIXER 0x33 -#define WM8990_LINE_MIXER1 0x34 -#define WM8990_LINE_MIXER2 0x35 -#define WM8990_SPEAKER_MIXER 0x36 -#define WM8990_ADDITIONAL_CONTROL 0x37 -#define WM8990_ANTIPOP1 0x38 -#define WM8990_ANTIPOP2 0x39 -#define WM8990_MICBIAS 0x3A -#define WM8990_PLL1 0x3C -#define WM8990_PLL2 0x3D -#define WM8990_PLL3 0x3E -#define WM8990_INTDRIVBITS 0x3F - -#define WM8990_EXT_ACCESS_ENA 0x75 -#define WM8990_EXT_CTL1 0x7a - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Reset - */ -#define WM8990_SW_RESET_CHIP_ID_MASK 0xFFFF /* SW_RESET_CHIP_ID */ - -/* - * R1 (0x01) - Power Management (1) - */ -#define WM8990_SPK_ENA 0x1000 /* SPK_ENA */ -#define WM8990_SPK_ENA_BIT 12 -#define WM8990_OUT3_ENA 0x0800 /* OUT3_ENA */ -#define WM8990_OUT3_ENA_BIT 11 -#define WM8990_OUT4_ENA 0x0400 /* OUT4_ENA */ -#define WM8990_OUT4_ENA_BIT 10 -#define WM8990_LOUT_ENA 0x0200 /* LOUT_ENA */ -#define WM8990_LOUT_ENA_BIT 9 -#define WM8990_ROUT_ENA 0x0100 /* ROUT_ENA */ -#define WM8990_ROUT_ENA_BIT 8 -#define WM8990_MICBIAS_ENA 0x0010 /* MICBIAS_ENA */ -#define WM8990_MICBIAS_ENA_BIT 4 -#define WM8990_VMID_MODE_MASK 0x0006 /* VMID_MODE - [2:1] */ -#define WM8990_VREF_ENA 0x0001 /* VREF_ENA */ -#define WM8990_VREF_ENA_BIT 0 - -/* - * R2 (0x02) - Power Management (2) - */ -#define WM8990_PLL_ENA 0x8000 /* PLL_ENA */ -#define WM8990_PLL_ENA_BIT 15 -#define WM8990_TSHUT_ENA 0x4000 /* TSHUT_ENA */ -#define WM8990_TSHUT_ENA_BIT 14 -#define WM8990_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */ -#define WM8990_TSHUT_OPDIS_BIT 13 -#define WM8990_OPCLK_ENA 0x0800 /* OPCLK_ENA */ -#define WM8990_OPCLK_ENA_BIT 11 -#define WM8990_AINL_ENA 0x0200 /* AINL_ENA */ -#define WM8990_AINL_ENA_BIT 9 -#define WM8990_AINR_ENA 0x0100 /* AINR_ENA */ -#define WM8990_AINR_ENA_BIT 8 -#define WM8990_LIN34_ENA 0x0080 /* LIN34_ENA */ -#define WM8990_LIN34_ENA_BIT 7 -#define WM8990_LIN12_ENA 0x0040 /* LIN12_ENA */ -#define WM8990_LIN12_ENA_BIT 6 -#define WM8990_RIN34_ENA 0x0020 /* RIN34_ENA */ -#define WM8990_RIN34_ENA_BIT 5 -#define WM8990_RIN12_ENA 0x0010 /* RIN12_ENA */ -#define WM8990_RIN12_ENA_BIT 4 -#define WM8990_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8990_ADCL_ENA_BIT 1 -#define WM8990_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8990_ADCR_ENA_BIT 0 - -/* - * R3 (0x03) - Power Management (3) - */ -#define WM8990_LON_ENA 0x2000 /* LON_ENA */ -#define WM8990_LON_ENA_BIT 13 -#define WM8990_LOP_ENA 0x1000 /* LOP_ENA */ -#define WM8990_LOP_ENA_BIT 12 -#define WM8990_RON_ENA 0x0800 /* RON_ENA */ -#define WM8990_RON_ENA_BIT 11 -#define WM8990_ROP_ENA 0x0400 /* ROP_ENA */ -#define WM8990_ROP_ENA_BIT 10 -#define WM8990_LOPGA_ENA 0x0080 /* LOPGA_ENA */ -#define WM8990_LOPGA_ENA_BIT 7 -#define WM8990_ROPGA_ENA 0x0040 /* ROPGA_ENA */ -#define WM8990_ROPGA_ENA_BIT 6 -#define WM8990_LOMIX_ENA 0x0020 /* LOMIX_ENA */ -#define WM8990_LOMIX_ENA_BIT 5 -#define WM8990_ROMIX_ENA 0x0010 /* ROMIX_ENA */ -#define WM8990_ROMIX_ENA_BIT 4 -#define WM8990_DACL_ENA 0x0002 /* DACL_ENA */ -#define WM8990_DACL_ENA_BIT 1 -#define WM8990_DACR_ENA 0x0001 /* DACR_ENA */ -#define WM8990_DACR_ENA_BIT 0 - -/* - * R4 (0x04) - Audio Interface (1) - */ -#define WM8990_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */ -#define WM8990_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */ -#define WM8990_AIFADC_TDM 0x2000 /* AIFADC_TDM */ -#define WM8990_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */ -#define WM8990_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */ -#define WM8990_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */ -#define WM8990_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */ -#define WM8990_AIF_WL_16BITS (0 << 5) -#define WM8990_AIF_WL_20BITS (1 << 5) -#define WM8990_AIF_WL_24BITS (2 << 5) -#define WM8990_AIF_WL_32BITS (3 << 5) -#define WM8990_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */ -#define WM8990_AIF_TMF_RIGHTJ (0 << 3) -#define WM8990_AIF_TMF_LEFTJ (1 << 3) -#define WM8990_AIF_TMF_I2S (2 << 3) -#define WM8990_AIF_TMF_DSP (3 << 3) - -/* - * R5 (0x05) - Audio Interface (2) - */ -#define WM8990_DACL_SRC 0x8000 /* DACL_SRC */ -#define WM8990_DACR_SRC 0x4000 /* DACR_SRC */ -#define WM8990_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ -#define WM8990_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8990_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST */ -#define WM8990_DAC_COMP 0x0010 /* DAC_COMP */ -#define WM8990_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */ -#define WM8990_ADC_COMP 0x0004 /* ADC_COMP */ -#define WM8990_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */ -#define WM8990_LOOPBACK 0x0001 /* LOOPBACK */ - -/* - * R6 (0x06) - Clocking (1) - */ -#define WM8990_TOCLK_RATE 0x8000 /* TOCLK_RATE */ -#define WM8990_TOCLK_ENA 0x4000 /* TOCLK_ENA */ -#define WM8990_OPCLKDIV_MASK 0x1E00 /* OPCLKDIV - [12:9] */ -#define WM8990_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */ -#define WM8990_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */ -#define WM8990_BCLK_DIV_1 (0x0 << 1) -#define WM8990_BCLK_DIV_1_5 (0x1 << 1) -#define WM8990_BCLK_DIV_2 (0x2 << 1) -#define WM8990_BCLK_DIV_3 (0x3 << 1) -#define WM8990_BCLK_DIV_4 (0x4 << 1) -#define WM8990_BCLK_DIV_5_5 (0x5 << 1) -#define WM8990_BCLK_DIV_6 (0x6 << 1) -#define WM8990_BCLK_DIV_8 (0x7 << 1) -#define WM8990_BCLK_DIV_11 (0x8 << 1) -#define WM8990_BCLK_DIV_12 (0x9 << 1) -#define WM8990_BCLK_DIV_16 (0xA << 1) -#define WM8990_BCLK_DIV_22 (0xB << 1) -#define WM8990_BCLK_DIV_24 (0xC << 1) -#define WM8990_BCLK_DIV_32 (0xD << 1) -#define WM8990_BCLK_DIV_44 (0xE << 1) -#define WM8990_BCLK_DIV_48 (0xF << 1) - -/* - * R7 (0x07) - Clocking (2) - */ -#define WM8990_MCLK_SRC 0x8000 /* MCLK_SRC */ -#define WM8990_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */ -#define WM8990_CLK_FORCE 0x2000 /* CLK_FORCE */ -#define WM8990_MCLK_DIV_MASK 0x1800 /* MCLK_DIV - [12:11] */ -#define WM8990_MCLK_DIV_1 (0 << 11) -#define WM8990_MCLK_DIV_2 (2 << 11) -#define WM8990_MCLK_INV 0x0400 /* MCLK_INV */ -#define WM8990_ADC_CLKDIV_MASK 0x00E0 /* ADC_CLKDIV */ -#define WM8990_ADC_CLKDIV_1 (0 << 5) -#define WM8990_ADC_CLKDIV_1_5 (1 << 5) -#define WM8990_ADC_CLKDIV_2 (2 << 5) -#define WM8990_ADC_CLKDIV_3 (3 << 5) -#define WM8990_ADC_CLKDIV_4 (4 << 5) -#define WM8990_ADC_CLKDIV_5_5 (5 << 5) -#define WM8990_ADC_CLKDIV_6 (6 << 5) -#define WM8990_DAC_CLKDIV_MASK 0x001C /* DAC_CLKDIV - [4:2] */ -#define WM8990_DAC_CLKDIV_1 (0 << 2) -#define WM8990_DAC_CLKDIV_1_5 (1 << 2) -#define WM8990_DAC_CLKDIV_2 (2 << 2) -#define WM8990_DAC_CLKDIV_3 (3 << 2) -#define WM8990_DAC_CLKDIV_4 (4 << 2) -#define WM8990_DAC_CLKDIV_5_5 (5 << 2) -#define WM8990_DAC_CLKDIV_6 (6 << 2) - -/* - * R8 (0x08) - Audio Interface (3) - */ -#define WM8990_AIF_MSTR1 0x8000 /* AIF_MSTR1 */ -#define WM8990_AIF_MSTR2 0x4000 /* AIF_MSTR2 */ -#define WM8990_AIF_SEL 0x2000 /* AIF_SEL */ -#define WM8990_ADCLRC_DIR 0x0800 /* ADCLRC_DIR */ -#define WM8990_ADCLRC_RATE_MASK 0x07FF /* ADCLRC_RATE */ - -/* - * R9 (0x09) - Audio Interface (4) - */ -#define WM8990_ALRCGPIO1 0x8000 /* ALRCGPIO1 */ -#define WM8990_ALRCBGPIO6 0x4000 /* ALRCBGPIO6 */ -#define WM8990_AIF_TRIS 0x2000 /* AIF_TRIS */ -#define WM8990_DACLRC_DIR 0x0800 /* DACLRC_DIR */ -#define WM8990_DACLRC_RATE_MASK 0x07FF /* DACLRC_RATE */ - -/* - * R10 (0x0A) - DAC CTRL - */ -#define WM8990_AIF_LRCLKRATE 0x0400 /* AIF_LRCLKRATE */ -#define WM8990_DAC_MONO 0x0200 /* DAC_MONO */ -#define WM8990_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */ -#define WM8990_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */ -#define WM8990_DAC_MUTEMODE 0x0040 /* DAC_MUTEMODE */ -#define WM8990_DEEMP_MASK 0x0030 /* DEEMP - [5:4] */ -#define WM8990_DAC_MUTE 0x0004 /* DAC_MUTE */ -#define WM8990_DACL_DATINV 0x0002 /* DACL_DATINV */ -#define WM8990_DACR_DATINV 0x0001 /* DACR_DATINV */ - -/* - * R11 (0x0B) - Left DAC Digital Volume - */ -#define WM8990_DAC_VU 0x0100 /* DAC_VU */ -#define WM8990_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ -#define WM8990_DACL_VOL_SHIFT 0 -/* - * R12 (0x0C) - Right DAC Digital Volume - */ -#define WM8990_DAC_VU 0x0100 /* DAC_VU */ -#define WM8990_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ -#define WM8990_DACR_VOL_SHIFT 0 -/* - * R13 (0x0D) - Digital Side Tone - */ -#define WM8990_ADCL_DAC_SVOL_MASK 0x0F /* ADCL_DAC_SVOL */ -#define WM8990_ADCL_DAC_SVOL_SHIFT 9 -#define WM8990_ADCR_DAC_SVOL_MASK 0x0F /* ADCR_DAC_SVOL */ -#define WM8990_ADCR_DAC_SVOL_SHIFT 5 -#define WM8990_ADC_TO_DACL_MASK 0x03 /* ADC_TO_DACL - [3:2] */ -#define WM8990_ADC_TO_DACL_SHIFT 2 -#define WM8990_ADC_TO_DACR_MASK 0x03 /* ADC_TO_DACR - [1:0] */ -#define WM8990_ADC_TO_DACR_SHIFT 0 - -/* - * R14 (0x0E) - ADC CTRL - */ -#define WM8990_ADC_HPF_ENA 0x0100 /* ADC_HPF_ENA */ -#define WM8990_ADC_HPF_ENA_BIT 8 -#define WM8990_ADC_HPF_CUT_MASK 0x03 /* ADC_HPF_CUT - [6:5] */ -#define WM8990_ADC_HPF_CUT_SHIFT 5 -#define WM8990_ADCL_DATINV 0x0002 /* ADCL_DATINV */ -#define WM8990_ADCL_DATINV_BIT 1 -#define WM8990_ADCR_DATINV 0x0001 /* ADCR_DATINV */ -#define WM8990_ADCR_DATINV_BIT 0 - -/* - * R15 (0x0F) - Left ADC Digital Volume - */ -#define WM8990_ADC_VU 0x0100 /* ADC_VU */ -#define WM8990_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ -#define WM8990_ADCL_VOL_SHIFT 0 - -/* - * R16 (0x10) - Right ADC Digital Volume - */ -#define WM8990_ADC_VU 0x0100 /* ADC_VU */ -#define WM8990_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ -#define WM8990_ADCR_VOL_SHIFT 0 - -/* - * R18 (0x12) - GPIO CTRL 1 - */ -#define WM8990_IRQ 0x1000 /* IRQ */ -#define WM8990_TEMPOK 0x0800 /* TEMPOK */ -#define WM8990_MICSHRT 0x0400 /* MICSHRT */ -#define WM8990_MICDET 0x0200 /* MICDET */ -#define WM8990_PLL_LCK 0x0100 /* PLL_LCK */ -#define WM8990_GPI8_STATUS 0x0080 /* GPI8_STATUS */ -#define WM8990_GPI7_STATUS 0x0040 /* GPI7_STATUS */ -#define WM8990_GPIO6_STATUS 0x0020 /* GPIO6_STATUS */ -#define WM8990_GPIO5_STATUS 0x0010 /* GPIO5_STATUS */ -#define WM8990_GPIO4_STATUS 0x0008 /* GPIO4_STATUS */ -#define WM8990_GPIO3_STATUS 0x0004 /* GPIO3_STATUS */ -#define WM8990_GPIO2_STATUS 0x0002 /* GPIO2_STATUS */ -#define WM8990_GPIO1_STATUS 0x0001 /* GPIO1_STATUS */ - -/* - * R19 (0x13) - GPIO1 & GPIO2 - */ -#define WM8990_GPIO2_DEB_ENA 0x8000 /* GPIO2_DEB_ENA */ -#define WM8990_GPIO2_IRQ_ENA 0x4000 /* GPIO2_IRQ_ENA */ -#define WM8990_GPIO2_PU 0x2000 /* GPIO2_PU */ -#define WM8990_GPIO2_PD 0x1000 /* GPIO2_PD */ -#define WM8990_GPIO2_SEL_MASK 0x0F00 /* GPIO2_SEL - [11:8] */ -#define WM8990_GPIO1_DEB_ENA 0x0080 /* GPIO1_DEB_ENA */ -#define WM8990_GPIO1_IRQ_ENA 0x0040 /* GPIO1_IRQ_ENA */ -#define WM8990_GPIO1_PU 0x0020 /* GPIO1_PU */ -#define WM8990_GPIO1_PD 0x0010 /* GPIO1_PD */ -#define WM8990_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */ - -/* - * R20 (0x14) - GPIO3 & GPIO4 - */ -#define WM8990_GPIO4_DEB_ENA 0x8000 /* GPIO4_DEB_ENA */ -#define WM8990_GPIO4_IRQ_ENA 0x4000 /* GPIO4_IRQ_ENA */ -#define WM8990_GPIO4_PU 0x2000 /* GPIO4_PU */ -#define WM8990_GPIO4_PD 0x1000 /* GPIO4_PD */ -#define WM8990_GPIO4_SEL_MASK 0x0F00 /* GPIO4_SEL - [11:8] */ -#define WM8990_GPIO3_DEB_ENA 0x0080 /* GPIO3_DEB_ENA */ -#define WM8990_GPIO3_IRQ_ENA 0x0040 /* GPIO3_IRQ_ENA */ -#define WM8990_GPIO3_PU 0x0020 /* GPIO3_PU */ -#define WM8990_GPIO3_PD 0x0010 /* GPIO3_PD */ -#define WM8990_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */ - -/* - * R21 (0x15) - GPIO5 & GPIO6 - */ -#define WM8990_GPIO6_DEB_ENA 0x8000 /* GPIO6_DEB_ENA */ -#define WM8990_GPIO6_IRQ_ENA 0x4000 /* GPIO6_IRQ_ENA */ -#define WM8990_GPIO6_PU 0x2000 /* GPIO6_PU */ -#define WM8990_GPIO6_PD 0x1000 /* GPIO6_PD */ -#define WM8990_GPIO6_SEL_MASK 0x0F00 /* GPIO6_SEL - [11:8] */ -#define WM8990_GPIO5_DEB_ENA 0x0080 /* GPIO5_DEB_ENA */ -#define WM8990_GPIO5_IRQ_ENA 0x0040 /* GPIO5_IRQ_ENA */ -#define WM8990_GPIO5_PU 0x0020 /* GPIO5_PU */ -#define WM8990_GPIO5_PD 0x0010 /* GPIO5_PD */ -#define WM8990_GPIO5_SEL_MASK 0x000F /* GPIO5_SEL - [3:0] */ - -/* - * R22 (0x16) - GPIOCTRL 2 - */ -#define WM8990_RD_3W_ENA 0x8000 /* RD_3W_ENA */ -#define WM8990_MODE_3W4W 0x4000 /* MODE_3W4W */ -#define WM8990_TEMPOK_IRQ_ENA 0x0800 /* TEMPOK_IRQ_ENA */ -#define WM8990_MICSHRT_IRQ_ENA 0x0400 /* MICSHRT_IRQ_ENA */ -#define WM8990_MICDET_IRQ_ENA 0x0200 /* MICDET_IRQ_ENA */ -#define WM8990_PLL_LCK_IRQ_ENA 0x0100 /* PLL_LCK_IRQ_ENA */ -#define WM8990_GPI8_DEB_ENA 0x0080 /* GPI8_DEB_ENA */ -#define WM8990_GPI8_IRQ_ENA 0x0040 /* GPI8_IRQ_ENA */ -#define WM8990_GPI8_ENA 0x0010 /* GPI8_ENA */ -#define WM8990_GPI7_DEB_ENA 0x0008 /* GPI7_DEB_ENA */ -#define WM8990_GPI7_IRQ_ENA 0x0004 /* GPI7_IRQ_ENA */ -#define WM8990_GPI7_ENA 0x0001 /* GPI7_ENA */ - -/* - * R23 (0x17) - GPIO_POL - */ -#define WM8990_IRQ_INV 0x1000 /* IRQ_INV */ -#define WM8990_TEMPOK_POL 0x0800 /* TEMPOK_POL */ -#define WM8990_MICSHRT_POL 0x0400 /* MICSHRT_POL */ -#define WM8990_MICDET_POL 0x0200 /* MICDET_POL */ -#define WM8990_PLL_LCK_POL 0x0100 /* PLL_LCK_POL */ -#define WM8990_GPI8_POL 0x0080 /* GPI8_POL */ -#define WM8990_GPI7_POL 0x0040 /* GPI7_POL */ -#define WM8990_GPIO6_POL 0x0020 /* GPIO6_POL */ -#define WM8990_GPIO5_POL 0x0010 /* GPIO5_POL */ -#define WM8990_GPIO4_POL 0x0008 /* GPIO4_POL */ -#define WM8990_GPIO3_POL 0x0004 /* GPIO3_POL */ -#define WM8990_GPIO2_POL 0x0002 /* GPIO2_POL */ -#define WM8990_GPIO1_POL 0x0001 /* GPIO1_POL */ - -/* - * R24 (0x18) - Left Line Input 1&2 Volume - */ -#define WM8990_IPVU 0x0100 /* IPVU */ -#define WM8990_LI12MUTE 0x0080 /* LI12MUTE */ -#define WM8990_LI12MUTE_BIT 7 -#define WM8990_LI12ZC 0x0040 /* LI12ZC */ -#define WM8990_LI12ZC_BIT 6 -#define WM8990_LIN12VOL_MASK 0x001F /* LIN12VOL - [4:0] */ -#define WM8990_LIN12VOL_SHIFT 0 -/* - * R25 (0x19) - Left Line Input 3&4 Volume - */ -#define WM8990_IPVU 0x0100 /* IPVU */ -#define WM8990_LI34MUTE 0x0080 /* LI34MUTE */ -#define WM8990_LI34MUTE_BIT 7 -#define WM8990_LI34ZC 0x0040 /* LI34ZC */ -#define WM8990_LI34ZC_BIT 6 -#define WM8990_LIN34VOL_MASK 0x001F /* LIN34VOL - [4:0] */ -#define WM8990_LIN34VOL_SHIFT 0 - -/* - * R26 (0x1A) - Right Line Input 1&2 Volume - */ -#define WM8990_IPVU 0x0100 /* IPVU */ -#define WM8990_RI12MUTE 0x0080 /* RI12MUTE */ -#define WM8990_RI12MUTE_BIT 7 -#define WM8990_RI12ZC 0x0040 /* RI12ZC */ -#define WM8990_RI12ZC_BIT 6 -#define WM8990_RIN12VOL_MASK 0x001F /* RIN12VOL - [4:0] */ -#define WM8990_RIN12VOL_SHIFT 0 - -/* - * R27 (0x1B) - Right Line Input 3&4 Volume - */ -#define WM8990_IPVU 0x0100 /* IPVU */ -#define WM8990_RI34MUTE 0x0080 /* RI34MUTE */ -#define WM8990_RI34MUTE_BIT 7 -#define WM8990_RI34ZC 0x0040 /* RI34ZC */ -#define WM8990_RI34ZC_BIT 6 -#define WM8990_RIN34VOL_MASK 0x001F /* RIN34VOL - [4:0] */ -#define WM8990_RIN34VOL_SHIFT 0 - -/* - * R28 (0x1C) - Left Output Volume - */ -#define WM8990_OPVU 0x0100 /* OPVU */ -#define WM8990_LOZC 0x0080 /* LOZC */ -#define WM8990_LOZC_BIT 7 -#define WM8990_LOUTVOL_MASK 0x007F /* LOUTVOL - [6:0] */ -#define WM8990_LOUTVOL_SHIFT 0 -/* - * R29 (0x1D) - Right Output Volume - */ -#define WM8990_OPVU 0x0100 /* OPVU */ -#define WM8990_ROZC 0x0080 /* ROZC */ -#define WM8990_ROZC_BIT 7 -#define WM8990_ROUTVOL_MASK 0x007F /* ROUTVOL - [6:0] */ -#define WM8990_ROUTVOL_SHIFT 0 -/* - * R30 (0x1E) - Line Outputs Volume - */ -#define WM8990_LONMUTE 0x0040 /* LONMUTE */ -#define WM8990_LONMUTE_BIT 6 -#define WM8990_LOPMUTE 0x0020 /* LOPMUTE */ -#define WM8990_LOPMUTE_BIT 5 -#define WM8990_LOATTN 0x0010 /* LOATTN */ -#define WM8990_LOATTN_BIT 4 -#define WM8990_RONMUTE 0x0004 /* RONMUTE */ -#define WM8990_RONMUTE_BIT 2 -#define WM8990_ROPMUTE 0x0002 /* ROPMUTE */ -#define WM8990_ROPMUTE_BIT 1 -#define WM8990_ROATTN 0x0001 /* ROATTN */ -#define WM8990_ROATTN_BIT 0 - -/* - * R31 (0x1F) - Out3/4 Volume - */ -#define WM8990_OUT3MUTE 0x0020 /* OUT3MUTE */ -#define WM8990_OUT3MUTE_BIT 5 -#define WM8990_OUT3ATTN 0x0010 /* OUT3ATTN */ -#define WM8990_OUT3ATTN_BIT 4 -#define WM8990_OUT4MUTE 0x0002 /* OUT4MUTE */ -#define WM8990_OUT4MUTE_BIT 1 -#define WM8990_OUT4ATTN 0x0001 /* OUT4ATTN */ -#define WM8990_OUT4ATTN_BIT 0 - -/* - * R32 (0x20) - Left OPGA Volume - */ -#define WM8990_OPVU 0x0100 /* OPVU */ -#define WM8990_LOPGAZC 0x0080 /* LOPGAZC */ -#define WM8990_LOPGAZC_BIT 7 -#define WM8990_LOPGAVOL_MASK 0x007F /* LOPGAVOL - [6:0] */ -#define WM8990_LOPGAVOL_SHIFT 0 - -/* - * R33 (0x21) - Right OPGA Volume - */ -#define WM8990_OPVU 0x0100 /* OPVU */ -#define WM8990_ROPGAZC 0x0080 /* ROPGAZC */ -#define WM8990_ROPGAZC_BIT 7 -#define WM8990_ROPGAVOL_MASK 0x007F /* ROPGAVOL - [6:0] */ -#define WM8990_ROPGAVOL_SHIFT 0 -/* - * R34 (0x22) - Speaker Volume - */ -#define WM8990_SPKATTN_MASK 0x0003 /* SPKATTN - [1:0] */ -#define WM8990_SPKATTN_SHIFT 0 - -/* - * R35 (0x23) - ClassD1 - */ -#define WM8990_CDMODE 0x0100 /* CDMODE */ -#define WM8990_CDMODE_BIT 8 - -/* - * R37 (0x25) - ClassD3 - */ -#define WM8990_DCGAIN_MASK 0x0007 /* DCGAIN - [5:3] */ -#define WM8990_DCGAIN_SHIFT 3 -#define WM8990_ACGAIN_MASK 0x0007 /* ACGAIN - [2:0] */ -#define WM8990_ACGAIN_SHIFT 0 - -/* - * R38 (0x26) - ClassD4 - */ -#define WM8990_SPKZC_MASK 0x0001 /* SPKZC */ -#define WM8990_SPKZC_SHIFT 7 /* SPKZC */ -#define WM8990_SPKVOL_MASK 0x007F /* SPKVOL - [6:0] */ -#define WM8990_SPKVOL_SHIFT 0 /* SPKVOL - [6:0] */ - -/* - * R39 (0x27) - Input Mixer1 - */ -#define WM8990_AINLMODE_MASK 0x000C /* AINLMODE - [3:2] */ -#define WM8990_AINLMODE_SHIFT 2 -#define WM8990_AINRMODE_MASK 0x0003 /* AINRMODE - [1:0] */ -#define WM8990_AINRMODE_SHIFT 0 - -/* - * R40 (0x28) - Input Mixer2 - */ -#define WM8990_LMP4 0x0080 /* LMP4 */ -#define WM8990_LMP4_BIT 7 /* LMP4 */ -#define WM8990_LMN3 0x0040 /* LMN3 */ -#define WM8990_LMN3_BIT 6 /* LMN3 */ -#define WM8990_LMP2 0x0020 /* LMP2 */ -#define WM8990_LMP2_BIT 5 /* LMP2 */ -#define WM8990_LMN1 0x0010 /* LMN1 */ -#define WM8990_LMN1_BIT 4 /* LMN1 */ -#define WM8990_RMP4 0x0008 /* RMP4 */ -#define WM8990_RMP4_BIT 3 /* RMP4 */ -#define WM8990_RMN3 0x0004 /* RMN3 */ -#define WM8990_RMN3_BIT 2 /* RMN3 */ -#define WM8990_RMP2 0x0002 /* RMP2 */ -#define WM8990_RMP2_BIT 1 /* RMP2 */ -#define WM8990_RMN1 0x0001 /* RMN1 */ -#define WM8990_RMN1_BIT 0 /* RMN1 */ - -/* - * R41 (0x29) - Input Mixer3 - */ -#define WM8990_L34MNB 0x0100 /* L34MNB */ -#define WM8990_L34MNB_BIT 8 -#define WM8990_L34MNBST 0x0080 /* L34MNBST */ -#define WM8990_L34MNBST_BIT 7 -#define WM8990_L12MNB 0x0020 /* L12MNB */ -#define WM8990_L12MNB_BIT 5 -#define WM8990_L12MNBST 0x0010 /* L12MNBST */ -#define WM8990_L12MNBST_BIT 4 -#define WM8990_LDBVOL_MASK 0x0007 /* LDBVOL - [2:0] */ -#define WM8990_LDBVOL_SHIFT 0 - -/* - * R42 (0x2A) - Input Mixer4 - */ -#define WM8990_R34MNB 0x0100 /* R34MNB */ -#define WM8990_R34MNB_BIT 8 -#define WM8990_R34MNBST 0x0080 /* R34MNBST */ -#define WM8990_R34MNBST_BIT 7 -#define WM8990_R12MNB 0x0020 /* R12MNB */ -#define WM8990_R12MNB_BIT 5 -#define WM8990_R12MNBST 0x0010 /* R12MNBST */ -#define WM8990_R12MNBST_BIT 4 -#define WM8990_RDBVOL_MASK 0x0007 /* RDBVOL - [2:0] */ -#define WM8990_RDBVOL_SHIFT 0 - -/* - * R43 (0x2B) - Input Mixer5 - */ -#define WM8990_LI2BVOL_MASK 0x07 /* LI2BVOL - [8:6] */ -#define WM8990_LI2BVOL_SHIFT 6 -#define WM8990_LR4BVOL_MASK 0x07 /* LR4BVOL - [5:3] */ -#define WM8990_LR4BVOL_SHIFT 3 -#define WM8990_LL4BVOL_MASK 0x07 /* LL4BVOL - [2:0] */ -#define WM8990_LL4BVOL_SHIFT 0 - -/* - * R44 (0x2C) - Input Mixer6 - */ -#define WM8990_RI2BVOL_MASK 0x07 /* RI2BVOL - [8:6] */ -#define WM8990_RI2BVOL_SHIFT 6 -#define WM8990_RL4BVOL_MASK 0x07 /* RL4BVOL - [5:3] */ -#define WM8990_RL4BVOL_SHIFT 3 -#define WM8990_RR4BVOL_MASK 0x07 /* RR4BVOL - [2:0] */ -#define WM8990_RR4BVOL_SHIFT 0 - -/* - * R45 (0x2D) - Output Mixer1 - */ -#define WM8990_LRBLO 0x0080 /* LRBLO */ -#define WM8990_LRBLO_BIT 7 -#define WM8990_LLBLO 0x0040 /* LLBLO */ -#define WM8990_LLBLO_BIT 6 -#define WM8990_LRI3LO 0x0020 /* LRI3LO */ -#define WM8990_LRI3LO_BIT 5 -#define WM8990_LLI3LO 0x0010 /* LLI3LO */ -#define WM8990_LLI3LO_BIT 4 -#define WM8990_LR12LO 0x0008 /* LR12LO */ -#define WM8990_LR12LO_BIT 3 -#define WM8990_LL12LO 0x0004 /* LL12LO */ -#define WM8990_LL12LO_BIT 2 -#define WM8990_LDLO 0x0001 /* LDLO */ -#define WM8990_LDLO_BIT 0 - -/* - * R46 (0x2E) - Output Mixer2 - */ -#define WM8990_RLBRO 0x0080 /* RLBRO */ -#define WM8990_RLBRO_BIT 7 -#define WM8990_RRBRO 0x0040 /* RRBRO */ -#define WM8990_RRBRO_BIT 6 -#define WM8990_RLI3RO 0x0020 /* RLI3RO */ -#define WM8990_RLI3RO_BIT 5 -#define WM8990_RRI3RO 0x0010 /* RRI3RO */ -#define WM8990_RRI3RO_BIT 4 -#define WM8990_RL12RO 0x0008 /* RL12RO */ -#define WM8990_RL12RO_BIT 3 -#define WM8990_RR12RO 0x0004 /* RR12RO */ -#define WM8990_RR12RO_BIT 2 -#define WM8990_RDRO 0x0001 /* RDRO */ -#define WM8990_RDRO_BIT 0 - -/* - * R47 (0x2F) - Output Mixer3 - */ -#define WM8990_LLI3LOVOL_MASK 0x07 /* LLI3LOVOL - [8:6] */ -#define WM8990_LLI3LOVOL_SHIFT 6 -#define WM8990_LR12LOVOL_MASK 0x07 /* LR12LOVOL - [5:3] */ -#define WM8990_LR12LOVOL_SHIFT 3 -#define WM8990_LL12LOVOL_MASK 0x07 /* LL12LOVOL - [2:0] */ -#define WM8990_LL12LOVOL_SHIFT 0 - -/* - * R48 (0x30) - Output Mixer4 - */ -#define WM8990_RRI3ROVOL_MASK 0x07 /* RRI3ROVOL - [8:6] */ -#define WM8990_RRI3ROVOL_SHIFT 6 -#define WM8990_RL12ROVOL_MASK 0x07 /* RL12ROVOL - [5:3] */ -#define WM8990_RL12ROVOL_SHIFT 3 -#define WM8990_RR12ROVOL_MASK 0x07 /* RR12ROVOL - [2:0] */ -#define WM8990_RR12ROVOL_SHIFT 0 - -/* - * R49 (0x31) - Output Mixer5 - */ -#define WM8990_LRI3LOVOL_MASK 0x07 /* LRI3LOVOL - [8:6] */ -#define WM8990_LRI3LOVOL_SHIFT 6 -#define WM8990_LRBLOVOL_MASK 0x07 /* LRBLOVOL - [5:3] */ -#define WM8990_LRBLOVOL_SHIFT 3 -#define WM8990_LLBLOVOL_MASK 0x07 /* LLBLOVOL - [2:0] */ -#define WM8990_LLBLOVOL_SHIFT 0 - -/* - * R50 (0x32) - Output Mixer6 - */ -#define WM8990_RLI3ROVOL_MASK 0x07 /* RLI3ROVOL - [8:6] */ -#define WM8990_RLI3ROVOL_SHIFT 6 -#define WM8990_RLBROVOL_MASK 0x07 /* RLBROVOL - [5:3] */ -#define WM8990_RLBROVOL_SHIFT 3 -#define WM8990_RRBROVOL_MASK 0x07 /* RRBROVOL - [2:0] */ -#define WM8990_RRBROVOL_SHIFT 0 - -/* - * R51 (0x33) - Out3/4 Mixer - */ -#define WM8990_VSEL_MASK 0x0180 /* VSEL - [8:7] */ -#define WM8990_LI4O3 0x0020 /* LI4O3 */ -#define WM8990_LI4O3_BIT 5 -#define WM8990_LPGAO3 0x0010 /* LPGAO3 */ -#define WM8990_LPGAO3_BIT 4 -#define WM8990_RI4O4 0x0002 /* RI4O4 */ -#define WM8990_RI4O4_BIT 1 -#define WM8990_RPGAO4 0x0001 /* RPGAO4 */ -#define WM8990_RPGAO4_BIT 0 -/* - * R52 (0x34) - Line Mixer1 - */ -#define WM8990_LLOPGALON 0x0040 /* LLOPGALON */ -#define WM8990_LLOPGALON_BIT 6 -#define WM8990_LROPGALON 0x0020 /* LROPGALON */ -#define WM8990_LROPGALON_BIT 5 -#define WM8990_LOPLON 0x0010 /* LOPLON */ -#define WM8990_LOPLON_BIT 4 -#define WM8990_LR12LOP 0x0004 /* LR12LOP */ -#define WM8990_LR12LOP_BIT 2 -#define WM8990_LL12LOP 0x0002 /* LL12LOP */ -#define WM8990_LL12LOP_BIT 1 -#define WM8990_LLOPGALOP 0x0001 /* LLOPGALOP */ -#define WM8990_LLOPGALOP_BIT 0 -/* - * R53 (0x35) - Line Mixer2 - */ -#define WM8990_RROPGARON 0x0040 /* RROPGARON */ -#define WM8990_RROPGARON_BIT 6 -#define WM8990_RLOPGARON 0x0020 /* RLOPGARON */ -#define WM8990_RLOPGARON_BIT 5 -#define WM8990_ROPRON 0x0010 /* ROPRON */ -#define WM8990_ROPRON_BIT 4 -#define WM8990_RL12ROP 0x0004 /* RL12ROP */ -#define WM8990_RL12ROP_BIT 2 -#define WM8990_RR12ROP 0x0002 /* RR12ROP */ -#define WM8990_RR12ROP_BIT 1 -#define WM8990_RROPGAROP 0x0001 /* RROPGAROP */ -#define WM8990_RROPGAROP_BIT 0 - -/* - * R54 (0x36) - Speaker Mixer - */ -#define WM8990_LB2SPK 0x0080 /* LB2SPK */ -#define WM8990_LB2SPK_BIT 7 -#define WM8990_RB2SPK 0x0040 /* RB2SPK */ -#define WM8990_RB2SPK_BIT 6 -#define WM8990_LI2SPK 0x0020 /* LI2SPK */ -#define WM8990_LI2SPK_BIT 5 -#define WM8990_RI2SPK 0x0010 /* RI2SPK */ -#define WM8990_RI2SPK_BIT 4 -#define WM8990_LOPGASPK 0x0008 /* LOPGASPK */ -#define WM8990_LOPGASPK_BIT 3 -#define WM8990_ROPGASPK 0x0004 /* ROPGASPK */ -#define WM8990_ROPGASPK_BIT 2 -#define WM8990_LDSPK 0x0002 /* LDSPK */ -#define WM8990_LDSPK_BIT 1 -#define WM8990_RDSPK 0x0001 /* RDSPK */ -#define WM8990_RDSPK_BIT 0 - -/* - * R55 (0x37) - Additional Control - */ -#define WM8990_VROI 0x0001 /* VROI */ - -/* - * R56 (0x38) - AntiPOP1 - */ -#define WM8990_DIS_LLINE 0x0020 /* DIS_LLINE */ -#define WM8990_DIS_RLINE 0x0010 /* DIS_RLINE */ -#define WM8990_DIS_OUT3 0x0008 /* DIS_OUT3 */ -#define WM8990_DIS_OUT4 0x0004 /* DIS_OUT4 */ -#define WM8990_DIS_LOUT 0x0002 /* DIS_LOUT */ -#define WM8990_DIS_ROUT 0x0001 /* DIS_ROUT */ - -/* - * R57 (0x39) - AntiPOP2 - */ -#define WM8990_SOFTST 0x0040 /* SOFTST */ -#define WM8990_BUFIOEN 0x0008 /* BUFIOEN */ -#define WM8990_BUFDCOPEN 0x0004 /* BUFDCOPEN */ -#define WM8990_POBCTRL 0x0002 /* POBCTRL */ -#define WM8990_VMIDTOG 0x0001 /* VMIDTOG */ - -/* - * R58 (0x3A) - MICBIAS - */ -#define WM8990_MCDSCTH_MASK 0x00C0 /* MCDSCTH - [7:6] */ -#define WM8990_MCDTHR_MASK 0x0038 /* MCDTHR - [5:3] */ -#define WM8990_MCD 0x0004 /* MCD */ -#define WM8990_MBSEL 0x0001 /* MBSEL */ - -/* - * R60 (0x3C) - PLL1 - */ -#define WM8990_SDM 0x0080 /* SDM */ -#define WM8990_PRESCALE 0x0040 /* PRESCALE */ -#define WM8990_PLLN_MASK 0x000F /* PLLN - [3:0] */ - -/* - * R61 (0x3D) - PLL2 - */ -#define WM8990_PLLK1_MASK 0x00FF /* PLLK1 - [7:0] */ - -/* - * R62 (0x3E) - PLL3 - */ -#define WM8990_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */ - -/* - * R63 (0x3F) - Internal Driver Bits - */ -#define WM8990_INMIXL_PWR_BIT 0 -#define WM8990_AINLMUX_PWR_BIT 1 -#define WM8990_INMIXR_PWR_BIT 2 -#define WM8990_AINRMUX_PWR_BIT 3 - -#define WM8990_MCLK_DIV 0 -#define WM8990_DACCLK_DIV 1 -#define WM8990_ADCCLK_DIV 2 -#define WM8990_BCLK_DIV 3 - -#endif /* __WM8990REGISTERDEFS_H__ */ -/*------------------------------ END OF FILE ---------------------------------*/ diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8991.c b/ANDROID_3.4.5/sound/soc/codecs/wm8991.c deleted file mode 100644 index 9ac31ba9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8991.c +++ /dev/null @@ -1,1423 +0,0 @@ -/* - * wm8991.c -- WM8991 ALSA Soc Audio driver - * - * Copyright 2007-2010 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * Graeme.Gregory@wolfsonmicro.com - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8991.h" - -struct wm8991_priv { - enum snd_soc_control_type control_type; - unsigned int pcmclk; -}; - -static const u16 wm8991_reg_defs[] = { - 0x8991, /* R0 - Reset */ - 0x0000, /* R1 - Power Management (1) */ - 0x6000, /* R2 - Power Management (2) */ - 0x0000, /* R3 - Power Management (3) */ - 0x4050, /* R4 - Audio Interface (1) */ - 0x4000, /* R5 - Audio Interface (2) */ - 0x01C8, /* R6 - Clocking (1) */ - 0x0000, /* R7 - Clocking (2) */ - 0x0040, /* R8 - Audio Interface (3) */ - 0x0040, /* R9 - Audio Interface (4) */ - 0x0004, /* R10 - DAC CTRL */ - 0x00C0, /* R11 - Left DAC Digital Volume */ - 0x00C0, /* R12 - Right DAC Digital Volume */ - 0x0000, /* R13 - Digital Side Tone */ - 0x0100, /* R14 - ADC CTRL */ - 0x00C0, /* R15 - Left ADC Digital Volume */ - 0x00C0, /* R16 - Right ADC Digital Volume */ - 0x0000, /* R17 */ - 0x0000, /* R18 - GPIO CTRL 1 */ - 0x1000, /* R19 - GPIO1 & GPIO2 */ - 0x1010, /* R20 - GPIO3 & GPIO4 */ - 0x1010, /* R21 - GPIO5 & GPIO6 */ - 0x8000, /* R22 - GPIOCTRL 2 */ - 0x0800, /* R23 - GPIO_POL */ - 0x008B, /* R24 - Left Line Input 1&2 Volume */ - 0x008B, /* R25 - Left Line Input 3&4 Volume */ - 0x008B, /* R26 - Right Line Input 1&2 Volume */ - 0x008B, /* R27 - Right Line Input 3&4 Volume */ - 0x0000, /* R28 - Left Output Volume */ - 0x0000, /* R29 - Right Output Volume */ - 0x0066, /* R30 - Line Outputs Volume */ - 0x0022, /* R31 - Out3/4 Volume */ - 0x0079, /* R32 - Left OPGA Volume */ - 0x0079, /* R33 - Right OPGA Volume */ - 0x0003, /* R34 - Speaker Volume */ - 0x0003, /* R35 - ClassD1 */ - 0x0000, /* R36 */ - 0x0100, /* R37 - ClassD3 */ - 0x0000, /* R38 */ - 0x0000, /* R39 - Input Mixer1 */ - 0x0000, /* R40 - Input Mixer2 */ - 0x0000, /* R41 - Input Mixer3 */ - 0x0000, /* R42 - Input Mixer4 */ - 0x0000, /* R43 - Input Mixer5 */ - 0x0000, /* R44 - Input Mixer6 */ - 0x0000, /* R45 - Output Mixer1 */ - 0x0000, /* R46 - Output Mixer2 */ - 0x0000, /* R47 - Output Mixer3 */ - 0x0000, /* R48 - Output Mixer4 */ - 0x0000, /* R49 - Output Mixer5 */ - 0x0000, /* R50 - Output Mixer6 */ - 0x0180, /* R51 - Out3/4 Mixer */ - 0x0000, /* R52 - Line Mixer1 */ - 0x0000, /* R53 - Line Mixer2 */ - 0x0000, /* R54 - Speaker Mixer */ - 0x0000, /* R55 - Additional Control */ - 0x0000, /* R56 - AntiPOP1 */ - 0x0000, /* R57 - AntiPOP2 */ - 0x0000, /* R58 - MICBIAS */ - 0x0000, /* R59 */ - 0x0008, /* R60 - PLL1 */ - 0x0031, /* R61 - PLL2 */ - 0x0026, /* R62 - PLL3 */ -}; - -#define wm8991_reset(c) snd_soc_write(c, WM8991_RESET, 0) - -static const unsigned int rec_mix_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 7, TLV_DB_LINEAR_ITEM(-1500, 600), -}; - -static const unsigned int in_pga_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 0x1F, TLV_DB_LINEAR_ITEM(-1650, 3000), -}; - -static const unsigned int out_mix_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 7, TLV_DB_LINEAR_ITEM(0, -2100), -}; - -static const unsigned int out_pga_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 127, TLV_DB_LINEAR_ITEM(-7300, 600), -}; - -static const unsigned int out_omix_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 7, TLV_DB_LINEAR_ITEM(-600, 0), -}; - -static const unsigned int out_dac_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 255, TLV_DB_LINEAR_ITEM(-7163, 0), -}; - -static const unsigned int in_adc_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 255, TLV_DB_LINEAR_ITEM(-7163, 1763), -}; - -static const unsigned int out_sidetone_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 31, TLV_DB_LINEAR_ITEM(-3600, 0), -}; - -static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int ret; - u16 val; - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret < 0) - return ret; - - /* now hit the volume update bits (always bit 8) */ - val = snd_soc_read(codec, reg); - return snd_soc_write(codec, reg, val | 0x0100); -} - -static const char *wm8991_digital_sidetone[] = -{"None", "Left ADC", "Right ADC", "Reserved"}; - -static const struct soc_enum wm8991_left_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACL_SHIFT, - WM8991_ADC_TO_DACL_MASK, - wm8991_digital_sidetone); - -static const struct soc_enum wm8991_right_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACR_SHIFT, - WM8991_ADC_TO_DACR_MASK, - wm8991_digital_sidetone); - -static const char *wm8991_adcmode[] = -{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; - -static const struct soc_enum wm8991_right_adcmode_enum = - SOC_ENUM_SINGLE(WM8991_ADC_CTRL, - WM8991_ADC_HPF_CUT_SHIFT, - WM8991_ADC_HPF_CUT_MASK, - wm8991_adcmode); - -static const struct snd_kcontrol_new wm8991_snd_controls[] = { - /* INMIXL */ - SOC_SINGLE("LIN12 PGA Boost", WM8991_INPUT_MIXER3, WM8991_L12MNBST_BIT, 1, 0), - SOC_SINGLE("LIN34 PGA Boost", WM8991_INPUT_MIXER3, WM8991_L34MNBST_BIT, 1, 0), - /* INMIXR */ - SOC_SINGLE("RIN12 PGA Boost", WM8991_INPUT_MIXER3, WM8991_R12MNBST_BIT, 1, 0), - SOC_SINGLE("RIN34 PGA Boost", WM8991_INPUT_MIXER3, WM8991_R34MNBST_BIT, 1, 0), - - /* LOMIX */ - SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8991_OUTPUT_MIXER3, - WM8991_LLI3LOVOL_SHIFT, WM8991_LLI3LOVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER3, - WM8991_LR12LOVOL_SHIFT, WM8991_LR12LOVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER3, - WM8991_LL12LOVOL_SHIFT, WM8991_LL12LOVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8991_OUTPUT_MIXER5, - WM8991_LRI3LOVOL_SHIFT, WM8991_LRI3LOVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8991_OUTPUT_MIXER5, - WM8991_LRBLOVOL_SHIFT, WM8991_LRBLOVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8991_OUTPUT_MIXER5, - WM8991_LRBLOVOL_SHIFT, WM8991_LRBLOVOL_MASK, 1, out_mix_tlv), - - /* ROMIX */ - SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8991_OUTPUT_MIXER4, - WM8991_RRI3ROVOL_SHIFT, WM8991_RRI3ROVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER4, - WM8991_RL12ROVOL_SHIFT, WM8991_RL12ROVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER4, - WM8991_RR12ROVOL_SHIFT, WM8991_RR12ROVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8991_OUTPUT_MIXER6, - WM8991_RLI3ROVOL_SHIFT, WM8991_RLI3ROVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8991_OUTPUT_MIXER6, - WM8991_RLBROVOL_SHIFT, WM8991_RLBROVOL_MASK, 1, out_mix_tlv), - SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8991_OUTPUT_MIXER6, - WM8991_RRBROVOL_SHIFT, WM8991_RRBROVOL_MASK, 1, out_mix_tlv), - - /* LOUT */ - SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8991_LEFT_OUTPUT_VOLUME, - WM8991_LOUTVOL_SHIFT, WM8991_LOUTVOL_MASK, 0, out_pga_tlv), - SOC_SINGLE("LOUT ZC", WM8991_LEFT_OUTPUT_VOLUME, WM8991_LOZC_BIT, 1, 0), - - /* ROUT */ - SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8991_RIGHT_OUTPUT_VOLUME, - WM8991_ROUTVOL_SHIFT, WM8991_ROUTVOL_MASK, 0, out_pga_tlv), - SOC_SINGLE("ROUT ZC", WM8991_RIGHT_OUTPUT_VOLUME, WM8991_ROZC_BIT, 1, 0), - - /* LOPGA */ - SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8991_LEFT_OPGA_VOLUME, - WM8991_LOPGAVOL_SHIFT, WM8991_LOPGAVOL_MASK, 0, out_pga_tlv), - SOC_SINGLE("LOPGA ZC Switch", WM8991_LEFT_OPGA_VOLUME, - WM8991_LOPGAZC_BIT, 1, 0), - - /* ROPGA */ - SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8991_RIGHT_OPGA_VOLUME, - WM8991_ROPGAVOL_SHIFT, WM8991_ROPGAVOL_MASK, 0, out_pga_tlv), - SOC_SINGLE("ROPGA ZC Switch", WM8991_RIGHT_OPGA_VOLUME, - WM8991_ROPGAZC_BIT, 1, 0), - - SOC_SINGLE("LON Mute Switch", WM8991_LINE_OUTPUTS_VOLUME, - WM8991_LONMUTE_BIT, 1, 0), - SOC_SINGLE("LOP Mute Switch", WM8991_LINE_OUTPUTS_VOLUME, - WM8991_LOPMUTE_BIT, 1, 0), - SOC_SINGLE("LOP Attenuation Switch", WM8991_LINE_OUTPUTS_VOLUME, - WM8991_LOATTN_BIT, 1, 0), - SOC_SINGLE("RON Mute Switch", WM8991_LINE_OUTPUTS_VOLUME, - WM8991_RONMUTE_BIT, 1, 0), - SOC_SINGLE("ROP Mute Switch", WM8991_LINE_OUTPUTS_VOLUME, - WM8991_ROPMUTE_BIT, 1, 0), - SOC_SINGLE("ROP Attenuation Switch", WM8991_LINE_OUTPUTS_VOLUME, - WM8991_ROATTN_BIT, 1, 0), - - SOC_SINGLE("OUT3 Mute Switch", WM8991_OUT3_4_VOLUME, - WM8991_OUT3MUTE_BIT, 1, 0), - SOC_SINGLE("OUT3 Attenuation Switch", WM8991_OUT3_4_VOLUME, - WM8991_OUT3ATTN_BIT, 1, 0), - - SOC_SINGLE("OUT4 Mute Switch", WM8991_OUT3_4_VOLUME, - WM8991_OUT4MUTE_BIT, 1, 0), - SOC_SINGLE("OUT4 Attenuation Switch", WM8991_OUT3_4_VOLUME, - WM8991_OUT4ATTN_BIT, 1, 0), - - SOC_SINGLE("Speaker Mode Switch", WM8991_CLASSD1, - WM8991_CDMODE_BIT, 1, 0), - - SOC_SINGLE("Speaker Output Attenuation Volume", WM8991_SPEAKER_VOLUME, - WM8991_SPKVOL_SHIFT, WM8991_SPKVOL_MASK, 0), - SOC_SINGLE("Speaker DC Boost Volume", WM8991_CLASSD3, - WM8991_DCGAIN_SHIFT, WM8991_DCGAIN_MASK, 0), - SOC_SINGLE("Speaker AC Boost Volume", WM8991_CLASSD3, - WM8991_ACGAIN_SHIFT, WM8991_ACGAIN_MASK, 0), - - SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume", - WM8991_LEFT_DAC_DIGITAL_VOLUME, - WM8991_DACL_VOL_SHIFT, - WM8991_DACL_VOL_MASK, - 0, - out_dac_tlv), - - SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume", - WM8991_RIGHT_DAC_DIGITAL_VOLUME, - WM8991_DACR_VOL_SHIFT, - WM8991_DACR_VOL_MASK, - 0, - out_dac_tlv), - - SOC_ENUM("Left Digital Sidetone", wm8991_left_digital_sidetone_enum), - SOC_ENUM("Right Digital Sidetone", wm8991_right_digital_sidetone_enum), - - SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8991_DIGITAL_SIDE_TONE, - WM8991_ADCL_DAC_SVOL_SHIFT, WM8991_ADCL_DAC_SVOL_MASK, 0, - out_sidetone_tlv), - SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8991_DIGITAL_SIDE_TONE, - WM8991_ADCR_DAC_SVOL_SHIFT, WM8991_ADCR_DAC_SVOL_MASK, 0, - out_sidetone_tlv), - - SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8991_ADC_CTRL, - WM8991_ADC_HPF_ENA_BIT, 1, 0), - - SOC_ENUM("ADC HPF Mode", wm8991_right_adcmode_enum), - - SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume", - WM8991_LEFT_ADC_DIGITAL_VOLUME, - WM8991_ADCL_VOL_SHIFT, - WM8991_ADCL_VOL_MASK, - 0, - in_adc_tlv), - - SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume", - WM8991_RIGHT_ADC_DIGITAL_VOLUME, - WM8991_ADCR_VOL_SHIFT, - WM8991_ADCR_VOL_MASK, - 0, - in_adc_tlv), - - SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume", - WM8991_LEFT_LINE_INPUT_1_2_VOLUME, - WM8991_LIN12VOL_SHIFT, - WM8991_LIN12VOL_MASK, - 0, - in_pga_tlv), - - SOC_SINGLE("LIN12 ZC Switch", WM8991_LEFT_LINE_INPUT_1_2_VOLUME, - WM8991_LI12ZC_BIT, 1, 0), - - SOC_SINGLE("LIN12 Mute Switch", WM8991_LEFT_LINE_INPUT_1_2_VOLUME, - WM8991_LI12MUTE_BIT, 1, 0), - - SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume", - WM8991_LEFT_LINE_INPUT_3_4_VOLUME, - WM8991_LIN34VOL_SHIFT, - WM8991_LIN34VOL_MASK, - 0, - in_pga_tlv), - - SOC_SINGLE("LIN34 ZC Switch", WM8991_LEFT_LINE_INPUT_3_4_VOLUME, - WM8991_LI34ZC_BIT, 1, 0), - - SOC_SINGLE("LIN34 Mute Switch", WM8991_LEFT_LINE_INPUT_3_4_VOLUME, - WM8991_LI34MUTE_BIT, 1, 0), - - SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume", - WM8991_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8991_RIN12VOL_SHIFT, - WM8991_RIN12VOL_MASK, - 0, - in_pga_tlv), - - SOC_SINGLE("RIN12 ZC Switch", WM8991_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8991_RI12ZC_BIT, 1, 0), - - SOC_SINGLE("RIN12 Mute Switch", WM8991_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8991_RI12MUTE_BIT, 1, 0), - - SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume", - WM8991_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8991_RIN34VOL_SHIFT, - WM8991_RIN34VOL_MASK, - 0, - in_pga_tlv), - - SOC_SINGLE("RIN34 ZC Switch", WM8991_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8991_RI34ZC_BIT, 1, 0), - - SOC_SINGLE("RIN34 Mute Switch", WM8991_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8991_RI34MUTE_BIT, 1, 0), -}; - -/* - * _DAPM_ Controls - */ -static int inmixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - u16 reg, fakepower; - - reg = snd_soc_read(w->codec, WM8991_POWER_MANAGEMENT_2); - fakepower = snd_soc_read(w->codec, WM8991_INTDRIVBITS); - - if (fakepower & ((1 << WM8991_INMIXL_PWR_BIT) | - (1 << WM8991_AINLMUX_PWR_BIT))) - reg |= WM8991_AINL_ENA; - else - reg &= ~WM8991_AINL_ENA; - - if (fakepower & ((1 << WM8991_INMIXR_PWR_BIT) | - (1 << WM8991_AINRMUX_PWR_BIT))) - reg |= WM8991_AINR_ENA; - else - reg &= ~WM8991_AINR_ENA; - - snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg); - return 0; -} - -static int outmixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - u32 reg_shift = kcontrol->private_value & 0xfff; - int ret = 0; - u16 reg; - - switch (reg_shift) { - case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8): - reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER1); - if (reg & WM8991_LDLO) { - printk(KERN_WARNING - "Cannot set as Output Mixer 1 LDLO Set\n"); - ret = -1; - } - break; - - case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8): - reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER2); - if (reg & WM8991_RDRO) { - printk(KERN_WARNING - "Cannot set as Output Mixer 2 RDRO Set\n"); - ret = -1; - } - break; - - case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8): - reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER); - if (reg & WM8991_LDSPK) { - printk(KERN_WARNING - "Cannot set as Speaker Mixer LDSPK Set\n"); - ret = -1; - } - break; - - case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8): - reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER); - if (reg & WM8991_RDSPK) { - printk(KERN_WARNING - "Cannot set as Speaker Mixer RDSPK Set\n"); - ret = -1; - } - break; - } - - return ret; -} - -/* INMIX dB values */ -static const unsigned int in_mix_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0, 7, TLV_DB_LINEAR_ITEM(-1200, 600), -}; - -/* Left In PGA Connections */ -static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = { - SOC_DAPM_SINGLE("LIN1 Switch", WM8991_INPUT_MIXER2, WM8991_LMN1_BIT, 1, 0), - SOC_DAPM_SINGLE("LIN2 Switch", WM8991_INPUT_MIXER2, WM8991_LMP2_BIT, 1, 0), -}; - -static const struct snd_kcontrol_new wm8991_dapm_lin34_pga_controls[] = { - SOC_DAPM_SINGLE("LIN3 Switch", WM8991_INPUT_MIXER2, WM8991_LMN3_BIT, 1, 0), - SOC_DAPM_SINGLE("LIN4 Switch", WM8991_INPUT_MIXER2, WM8991_LMP4_BIT, 1, 0), -}; - -/* Right In PGA Connections */ -static const struct snd_kcontrol_new wm8991_dapm_rin12_pga_controls[] = { - SOC_DAPM_SINGLE("RIN1 Switch", WM8991_INPUT_MIXER2, WM8991_RMN1_BIT, 1, 0), - SOC_DAPM_SINGLE("RIN2 Switch", WM8991_INPUT_MIXER2, WM8991_RMP2_BIT, 1, 0), -}; - -static const struct snd_kcontrol_new wm8991_dapm_rin34_pga_controls[] = { - SOC_DAPM_SINGLE("RIN3 Switch", WM8991_INPUT_MIXER2, WM8991_RMN3_BIT, 1, 0), - SOC_DAPM_SINGLE("RIN4 Switch", WM8991_INPUT_MIXER2, WM8991_RMP4_BIT, 1, 0), -}; - -/* INMIXL */ -static const struct snd_kcontrol_new wm8991_dapm_inmixl_controls[] = { - SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8991_INPUT_MIXER3, - WM8991_LDBVOL_SHIFT, WM8991_LDBVOL_MASK, 0, in_mix_tlv), - SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8991_INPUT_MIXER5, WM8991_LI2BVOL_SHIFT, - 7, 0, in_mix_tlv), - SOC_DAPM_SINGLE("LINPGA12 Switch", WM8991_INPUT_MIXER3, WM8991_L12MNB_BIT, - 1, 0), - SOC_DAPM_SINGLE("LINPGA34 Switch", WM8991_INPUT_MIXER3, WM8991_L34MNB_BIT, - 1, 0), -}; - -/* INMIXR */ -static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = { - SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8991_INPUT_MIXER4, - WM8991_RDBVOL_SHIFT, WM8991_RDBVOL_MASK, 0, in_mix_tlv), - SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8991_INPUT_MIXER6, WM8991_RI2BVOL_SHIFT, - 7, 0, in_mix_tlv), - SOC_DAPM_SINGLE("RINPGA12 Switch", WM8991_INPUT_MIXER3, WM8991_L12MNB_BIT, - 1, 0), - SOC_DAPM_SINGLE("RINPGA34 Switch", WM8991_INPUT_MIXER3, WM8991_L34MNB_BIT, - 1, 0), -}; - -/* AINLMUX */ -static const char *wm8991_ainlmux[] = -{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; - -static const struct soc_enum wm8991_ainlmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, - ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux); - -static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = - SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); - -/* DIFFINL */ - -/* AINRMUX */ -static const char *wm8991_ainrmux[] = -{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; - -static const struct soc_enum wm8991_ainrmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, - ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux); - -static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = - SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); - -/* RXVOICE */ -static const struct snd_kcontrol_new wm8991_dapm_rxvoice_controls[] = { - SOC_DAPM_SINGLE_TLV("LIN4RXN", WM8991_INPUT_MIXER5, WM8991_LR4BVOL_SHIFT, - WM8991_LR4BVOL_MASK, 0, in_mix_tlv), - SOC_DAPM_SINGLE_TLV("RIN4RXP", WM8991_INPUT_MIXER6, WM8991_RL4BVOL_SHIFT, - WM8991_RL4BVOL_MASK, 0, in_mix_tlv), -}; - -/* LOMIX */ -static const struct snd_kcontrol_new wm8991_dapm_lomix_controls[] = { - SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER1, - WM8991_LRBLO_BIT, 1, 0), - SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8991_OUTPUT_MIXER1, - WM8991_LLBLO_BIT, 1, 0), - SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8991_OUTPUT_MIXER1, - WM8991_LRI3LO_BIT, 1, 0), - SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8991_OUTPUT_MIXER1, - WM8991_LLI3LO_BIT, 1, 0), - SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER1, - WM8991_LR12LO_BIT, 1, 0), - SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER1, - WM8991_LL12LO_BIT, 1, 0), - SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8991_OUTPUT_MIXER1, - WM8991_LDLO_BIT, 1, 0), -}; - -/* ROMIX */ -static const struct snd_kcontrol_new wm8991_dapm_romix_controls[] = { - SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8991_OUTPUT_MIXER2, - WM8991_RLBRO_BIT, 1, 0), - SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER2, - WM8991_RRBRO_BIT, 1, 0), - SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8991_OUTPUT_MIXER2, - WM8991_RLI3RO_BIT, 1, 0), - SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8991_OUTPUT_MIXER2, - WM8991_RRI3RO_BIT, 1, 0), - SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER2, - WM8991_RL12RO_BIT, 1, 0), - SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER2, - WM8991_RR12RO_BIT, 1, 0), - SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8991_OUTPUT_MIXER2, - WM8991_RDRO_BIT, 1, 0), -}; - -/* LONMIX */ -static const struct snd_kcontrol_new wm8991_dapm_lonmix_controls[] = { - SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8991_LINE_MIXER1, - WM8991_LLOPGALON_BIT, 1, 0), - SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8991_LINE_MIXER1, - WM8991_LROPGALON_BIT, 1, 0), - SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8991_LINE_MIXER1, - WM8991_LOPLON_BIT, 1, 0), -}; - -/* LOPMIX */ -static const struct snd_kcontrol_new wm8991_dapm_lopmix_controls[] = { - SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8991_LINE_MIXER1, - WM8991_LR12LOP_BIT, 1, 0), - SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8991_LINE_MIXER1, - WM8991_LL12LOP_BIT, 1, 0), - SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8991_LINE_MIXER1, - WM8991_LLOPGALOP_BIT, 1, 0), -}; - -/* RONMIX */ -static const struct snd_kcontrol_new wm8991_dapm_ronmix_controls[] = { - SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8991_LINE_MIXER2, - WM8991_RROPGARON_BIT, 1, 0), - SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8991_LINE_MIXER2, - WM8991_RLOPGARON_BIT, 1, 0), - SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8991_LINE_MIXER2, - WM8991_ROPRON_BIT, 1, 0), -}; - -/* ROPMIX */ -static const struct snd_kcontrol_new wm8991_dapm_ropmix_controls[] = { - SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8991_LINE_MIXER2, - WM8991_RL12ROP_BIT, 1, 0), - SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8991_LINE_MIXER2, - WM8991_RR12ROP_BIT, 1, 0), - SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8991_LINE_MIXER2, - WM8991_RROPGAROP_BIT, 1, 0), -}; - -/* OUT3MIX */ -static const struct snd_kcontrol_new wm8991_dapm_out3mix_controls[] = { - SOC_DAPM_SINGLE("OUT3MIX LIN4RXN Bypass Switch", WM8991_OUT3_4_MIXER, - WM8991_LI4O3_BIT, 1, 0), - SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8991_OUT3_4_MIXER, - WM8991_LPGAO3_BIT, 1, 0), -}; - -/* OUT4MIX */ -static const struct snd_kcontrol_new wm8991_dapm_out4mix_controls[] = { - SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8991_OUT3_4_MIXER, - WM8991_RPGAO4_BIT, 1, 0), - SOC_DAPM_SINGLE("OUT4MIX RIN4RXP Bypass Switch", WM8991_OUT3_4_MIXER, - WM8991_RI4O4_BIT, 1, 0), -}; - -/* SPKMIX */ -static const struct snd_kcontrol_new wm8991_dapm_spkmix_controls[] = { - SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8991_SPEAKER_MIXER, - WM8991_LI2SPK_BIT, 1, 0), - SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8991_SPEAKER_MIXER, - WM8991_LB2SPK_BIT, 1, 0), - SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8991_SPEAKER_MIXER, - WM8991_LOPGASPK_BIT, 1, 0), - SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8991_SPEAKER_MIXER, - WM8991_LDSPK_BIT, 1, 0), - SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8991_SPEAKER_MIXER, - WM8991_RDSPK_BIT, 1, 0), - SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8991_SPEAKER_MIXER, - WM8991_ROPGASPK_BIT, 1, 0), - SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8991_SPEAKER_MIXER, - WM8991_RL12ROP_BIT, 1, 0), - SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8991_SPEAKER_MIXER, - WM8991_RI2SPK_BIT, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = { - /* Input Side */ - /* Input Lines */ - SND_SOC_DAPM_INPUT("LIN1"), - SND_SOC_DAPM_INPUT("LIN2"), - SND_SOC_DAPM_INPUT("LIN3"), - SND_SOC_DAPM_INPUT("LIN4RXN"), - SND_SOC_DAPM_INPUT("RIN3"), - SND_SOC_DAPM_INPUT("RIN4RXP"), - SND_SOC_DAPM_INPUT("RIN1"), - SND_SOC_DAPM_INPUT("RIN2"), - SND_SOC_DAPM_INPUT("Internal ADC Source"), - - /* DACs */ - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2, - WM8991_ADCL_ENA_BIT, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8991_POWER_MANAGEMENT_2, - WM8991_ADCR_ENA_BIT, 0), - - /* Input PGAs */ - SND_SOC_DAPM_MIXER("LIN12 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_LIN12_ENA_BIT, - 0, &wm8991_dapm_lin12_pga_controls[0], - ARRAY_SIZE(wm8991_dapm_lin12_pga_controls)), - SND_SOC_DAPM_MIXER("LIN34 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_LIN34_ENA_BIT, - 0, &wm8991_dapm_lin34_pga_controls[0], - ARRAY_SIZE(wm8991_dapm_lin34_pga_controls)), - SND_SOC_DAPM_MIXER("RIN12 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_RIN12_ENA_BIT, - 0, &wm8991_dapm_rin12_pga_controls[0], - ARRAY_SIZE(wm8991_dapm_rin12_pga_controls)), - SND_SOC_DAPM_MIXER("RIN34 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_RIN34_ENA_BIT, - 0, &wm8991_dapm_rin34_pga_controls[0], - ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)), - - /* INMIXL */ - SND_SOC_DAPM_MIXER_E("INMIXL", WM8991_INTDRIVBITS, WM8991_INMIXL_PWR_BIT, 0, - &wm8991_dapm_inmixl_controls[0], - ARRAY_SIZE(wm8991_dapm_inmixl_controls), - inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - /* AINLMUX */ - SND_SOC_DAPM_MUX_E("AINLMUX", WM8991_INTDRIVBITS, WM8991_AINLMUX_PWR_BIT, 0, - &wm8991_dapm_ainlmux_controls, inmixer_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - /* INMIXR */ - SND_SOC_DAPM_MIXER_E("INMIXR", WM8991_INTDRIVBITS, WM8991_INMIXR_PWR_BIT, 0, - &wm8991_dapm_inmixr_controls[0], - ARRAY_SIZE(wm8991_dapm_inmixr_controls), - inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - /* AINRMUX */ - SND_SOC_DAPM_MUX_E("AINRMUX", WM8991_INTDRIVBITS, WM8991_AINRMUX_PWR_BIT, 0, - &wm8991_dapm_ainrmux_controls, inmixer_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - - /* Output Side */ - /* DACs */ - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8991_POWER_MANAGEMENT_3, - WM8991_DACL_ENA_BIT, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8991_POWER_MANAGEMENT_3, - WM8991_DACR_ENA_BIT, 0), - - /* LOMIX */ - SND_SOC_DAPM_MIXER_E("LOMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LOMIX_ENA_BIT, - 0, &wm8991_dapm_lomix_controls[0], - ARRAY_SIZE(wm8991_dapm_lomix_controls), - outmixer_event, SND_SOC_DAPM_PRE_REG), - - /* LONMIX */ - SND_SOC_DAPM_MIXER("LONMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LON_ENA_BIT, 0, - &wm8991_dapm_lonmix_controls[0], - ARRAY_SIZE(wm8991_dapm_lonmix_controls)), - - /* LOPMIX */ - SND_SOC_DAPM_MIXER("LOPMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LOP_ENA_BIT, 0, - &wm8991_dapm_lopmix_controls[0], - ARRAY_SIZE(wm8991_dapm_lopmix_controls)), - - /* OUT3MIX */ - SND_SOC_DAPM_MIXER("OUT3MIX", WM8991_POWER_MANAGEMENT_1, WM8991_OUT3_ENA_BIT, 0, - &wm8991_dapm_out3mix_controls[0], - ARRAY_SIZE(wm8991_dapm_out3mix_controls)), - - /* SPKMIX */ - SND_SOC_DAPM_MIXER_E("SPKMIX", WM8991_POWER_MANAGEMENT_1, WM8991_SPK_ENA_BIT, 0, - &wm8991_dapm_spkmix_controls[0], - ARRAY_SIZE(wm8991_dapm_spkmix_controls), outmixer_event, - SND_SOC_DAPM_PRE_REG), - - /* OUT4MIX */ - SND_SOC_DAPM_MIXER("OUT4MIX", WM8991_POWER_MANAGEMENT_1, WM8991_OUT4_ENA_BIT, 0, - &wm8991_dapm_out4mix_controls[0], - ARRAY_SIZE(wm8991_dapm_out4mix_controls)), - - /* ROPMIX */ - SND_SOC_DAPM_MIXER("ROPMIX", WM8991_POWER_MANAGEMENT_3, WM8991_ROP_ENA_BIT, 0, - &wm8991_dapm_ropmix_controls[0], - ARRAY_SIZE(wm8991_dapm_ropmix_controls)), - - /* RONMIX */ - SND_SOC_DAPM_MIXER("RONMIX", WM8991_POWER_MANAGEMENT_3, WM8991_RON_ENA_BIT, 0, - &wm8991_dapm_ronmix_controls[0], - ARRAY_SIZE(wm8991_dapm_ronmix_controls)), - - /* ROMIX */ - SND_SOC_DAPM_MIXER_E("ROMIX", WM8991_POWER_MANAGEMENT_3, WM8991_ROMIX_ENA_BIT, - 0, &wm8991_dapm_romix_controls[0], - ARRAY_SIZE(wm8991_dapm_romix_controls), - outmixer_event, SND_SOC_DAPM_PRE_REG), - - /* LOUT PGA */ - SND_SOC_DAPM_PGA("LOUT PGA", WM8991_POWER_MANAGEMENT_1, WM8991_LOUT_ENA_BIT, 0, - NULL, 0), - - /* ROUT PGA */ - SND_SOC_DAPM_PGA("ROUT PGA", WM8991_POWER_MANAGEMENT_1, WM8991_ROUT_ENA_BIT, 0, - NULL, 0), - - /* LOPGA */ - SND_SOC_DAPM_PGA("LOPGA", WM8991_POWER_MANAGEMENT_3, WM8991_LOPGA_ENA_BIT, 0, - NULL, 0), - - /* ROPGA */ - SND_SOC_DAPM_PGA("ROPGA", WM8991_POWER_MANAGEMENT_3, WM8991_ROPGA_ENA_BIT, 0, - NULL, 0), - - /* MICBIAS */ - SND_SOC_DAPM_SUPPLY("MICBIAS", WM8991_POWER_MANAGEMENT_1, - WM8991_MICBIAS_ENA_BIT, 0, NULL, 0), - - SND_SOC_DAPM_OUTPUT("LON"), - SND_SOC_DAPM_OUTPUT("LOP"), - SND_SOC_DAPM_OUTPUT("OUT3"), - SND_SOC_DAPM_OUTPUT("LOUT"), - SND_SOC_DAPM_OUTPUT("SPKN"), - SND_SOC_DAPM_OUTPUT("SPKP"), - SND_SOC_DAPM_OUTPUT("ROUT"), - SND_SOC_DAPM_OUTPUT("OUT4"), - SND_SOC_DAPM_OUTPUT("ROP"), - SND_SOC_DAPM_OUTPUT("RON"), - SND_SOC_DAPM_OUTPUT("OUT"), - - SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Make DACs turn on when playing even if not mixed into any outputs */ - {"Internal DAC Sink", NULL, "Left DAC"}, - {"Internal DAC Sink", NULL, "Right DAC"}, - - /* Make ADCs turn on when recording even if not mixed from any inputs */ - {"Left ADC", NULL, "Internal ADC Source"}, - {"Right ADC", NULL, "Internal ADC Source"}, - - /* Input Side */ - /* LIN12 PGA */ - {"LIN12 PGA", "LIN1 Switch", "LIN1"}, - {"LIN12 PGA", "LIN2 Switch", "LIN2"}, - /* LIN34 PGA */ - {"LIN34 PGA", "LIN3 Switch", "LIN3"}, - {"LIN34 PGA", "LIN4 Switch", "LIN4RXN"}, - /* INMIXL */ - {"INMIXL", "Record Left Volume", "LOMIX"}, - {"INMIXL", "LIN2 Volume", "LIN2"}, - {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, - {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, - /* AINLMUX */ - {"AINLMUX", "INMIXL Mix", "INMIXL"}, - {"AINLMUX", "DIFFINL Mix", "LIN12 PGA"}, - {"AINLMUX", "DIFFINL Mix", "LIN34 PGA"}, - {"AINLMUX", "RXVOICE Mix", "LIN4RXN"}, - {"AINLMUX", "RXVOICE Mix", "RIN4RXP"}, - /* ADC */ - {"Left ADC", NULL, "AINLMUX"}, - - /* RIN12 PGA */ - {"RIN12 PGA", "RIN1 Switch", "RIN1"}, - {"RIN12 PGA", "RIN2 Switch", "RIN2"}, - /* RIN34 PGA */ - {"RIN34 PGA", "RIN3 Switch", "RIN3"}, - {"RIN34 PGA", "RIN4 Switch", "RIN4RXP"}, - /* INMIXL */ - {"INMIXR", "Record Right Volume", "ROMIX"}, - {"INMIXR", "RIN2 Volume", "RIN2"}, - {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, - {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, - /* AINRMUX */ - {"AINRMUX", "INMIXR Mix", "INMIXR"}, - {"AINRMUX", "DIFFINR Mix", "RIN12 PGA"}, - {"AINRMUX", "DIFFINR Mix", "RIN34 PGA"}, - {"AINRMUX", "RXVOICE Mix", "LIN4RXN"}, - {"AINRMUX", "RXVOICE Mix", "RIN4RXP"}, - /* ADC */ - {"Right ADC", NULL, "AINRMUX"}, - - /* LOMIX */ - {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, - {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"}, - {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, - {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, - {"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"}, - {"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"}, - {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"}, - - /* ROMIX */ - {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"}, - {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"}, - {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, - {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, - {"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"}, - {"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"}, - {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"}, - - /* SPKMIX */ - {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"}, - {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"}, - {"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"}, - {"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"}, - {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"}, - {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"}, - {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"}, - {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"}, - - /* LONMIX */ - {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"}, - {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"}, - {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"}, - - /* LOPMIX */ - {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"}, - {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"}, - {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, - - /* OUT3MIX */ - {"OUT3MIX", "OUT3MIX LIN4RXN Bypass Switch", "LIN4RXN"}, - {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, - - /* OUT4MIX */ - {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"}, - {"OUT4MIX", "OUT4MIX RIN4RXP Bypass Switch", "RIN4RXP"}, - - /* RONMIX */ - {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"}, - {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"}, - {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"}, - - /* ROPMIX */ - {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"}, - {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"}, - {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"}, - - /* Out Mixer PGAs */ - {"LOPGA", NULL, "LOMIX"}, - {"ROPGA", NULL, "ROMIX"}, - - {"LOUT PGA", NULL, "LOMIX"}, - {"ROUT PGA", NULL, "ROMIX"}, - - /* Output Pins */ - {"LON", NULL, "LONMIX"}, - {"LOP", NULL, "LOPMIX"}, - {"OUT", NULL, "OUT3MIX"}, - {"LOUT", NULL, "LOUT PGA"}, - {"SPKN", NULL, "SPKMIX"}, - {"ROUT", NULL, "ROUT PGA"}, - {"OUT4", NULL, "OUT4MIX"}, - {"ROP", NULL, "ROPMIX"}, - {"RON", NULL, "RONMIX"}, -}; - -/* PLL divisors */ -struct _pll_div { - u32 div2; - u32 n; - u32 k; -}; - -/* The size in bits of the pll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 16) * 10) - -static void pll_factors(struct _pll_div *pll_div, unsigned int target, - unsigned int source) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod; - - - Ndiv = target / source; - if (Ndiv < 6) { - source >>= 1; - pll_div->div2 = 1; - Ndiv = target / source; - } else - pll_div->div2 = 0; - - if ((Ndiv < 6) || (Ndiv > 12)) - printk(KERN_WARNING - "WM8991 N value outwith recommended range! N = %d\n", Ndiv); - - pll_div->n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div->k = K; -} - -static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai, - int pll_id, int src, unsigned int freq_in, unsigned int freq_out) -{ - u16 reg; - struct snd_soc_codec *codec = codec_dai->codec; - struct _pll_div pll_div; - - if (freq_in && freq_out) { - pll_factors(&pll_div, freq_out * 4, freq_in); - - /* Turn on PLL */ - reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2); - reg |= WM8991_PLL_ENA; - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg); - - /* sysclk comes from PLL */ - reg = snd_soc_read(codec, WM8991_CLOCKING_2); - snd_soc_write(codec, WM8991_CLOCKING_2, reg | WM8991_SYSCLK_SRC); - - /* set up N , fractional mode and pre-divisor if necessary */ - snd_soc_write(codec, WM8991_PLL1, pll_div.n | WM8991_SDM | - (pll_div.div2 ? WM8991_PRESCALE : 0)); - snd_soc_write(codec, WM8991_PLL2, (u8)(pll_div.k>>8)); - snd_soc_write(codec, WM8991_PLL3, (u8)(pll_div.k & 0xFF)); - } else { - /* Turn on PLL */ - reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2); - reg &= ~WM8991_PLL_ENA; - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg); - } - return 0; -} - -/* - * Set's ADC and Voice DAC format. - */ -static int wm8991_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 audio1, audio3; - - audio1 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_1); - audio3 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_3); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - audio3 &= ~WM8991_AIF_MSTR1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - audio3 |= WM8991_AIF_MSTR1; - break; - default: - return -EINVAL; - } - - audio1 &= ~WM8991_AIF_FMT_MASK; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - audio1 |= WM8991_AIF_TMF_I2S; - audio1 &= ~WM8991_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_RIGHT_J: - audio1 |= WM8991_AIF_TMF_RIGHTJ; - audio1 &= ~WM8991_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_LEFT_J: - audio1 |= WM8991_AIF_TMF_LEFTJ; - audio1 &= ~WM8991_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_A: - audio1 |= WM8991_AIF_TMF_DSP; - audio1 &= ~WM8991_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_B: - audio1 |= WM8991_AIF_TMF_DSP | WM8991_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8991_AUDIO_INTERFACE_1, audio1); - snd_soc_write(codec, WM8991_AUDIO_INTERFACE_3, audio3); - return 0; -} - -static int wm8991_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM8991_MCLK_DIV: - reg = snd_soc_read(codec, WM8991_CLOCKING_2) & - ~WM8991_MCLK_DIV_MASK; - snd_soc_write(codec, WM8991_CLOCKING_2, reg | div); - break; - case WM8991_DACCLK_DIV: - reg = snd_soc_read(codec, WM8991_CLOCKING_2) & - ~WM8991_DAC_CLKDIV_MASK; - snd_soc_write(codec, WM8991_CLOCKING_2, reg | div); - break; - case WM8991_ADCCLK_DIV: - reg = snd_soc_read(codec, WM8991_CLOCKING_2) & - ~WM8991_ADC_CLKDIV_MASK; - snd_soc_write(codec, WM8991_CLOCKING_2, reg | div); - break; - case WM8991_BCLK_DIV: - reg = snd_soc_read(codec, WM8991_CLOCKING_1) & - ~WM8991_BCLK_DIV_MASK; - snd_soc_write(codec, WM8991_CLOCKING_1, reg | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * Set PCM DAI bit size and sample rate. - */ -static int wm8991_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - u16 audio1 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_1); - - audio1 &= ~WM8991_AIF_WL_MASK; - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - audio1 |= WM8991_AIF_WL_20BITS; - break; - case SNDRV_PCM_FORMAT_S24_LE: - audio1 |= WM8991_AIF_WL_24BITS; - break; - case SNDRV_PCM_FORMAT_S32_LE: - audio1 |= WM8991_AIF_WL_32BITS; - break; - } - - snd_soc_write(codec, WM8991_AUDIO_INTERFACE_1, audio1); - return 0; -} - -static int wm8991_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 val; - - val = snd_soc_read(codec, WM8991_DAC_CTRL) & ~WM8991_DAC_MUTE; - if (mute) - snd_soc_write(codec, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE); - else - snd_soc_write(codec, WM8991_DAC_CTRL, val); - return 0; -} - -static int wm8991_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 val; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID=2*50k */ - val = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1) & - ~WM8991_VMID_MODE_MASK; - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, val | 0x2); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - snd_soc_cache_sync(codec); - /* Enable all output discharge bits */ - snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | - WM8991_DIS_RLINE | WM8991_DIS_OUT3 | - WM8991_DIS_OUT4 | WM8991_DIS_LOUT | - WM8991_DIS_ROUT); - - /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ - snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | - WM8991_BUFDCOPEN | WM8991_POBCTRL | - WM8991_VMIDTOG); - - /* Delay to allow output caps to discharge */ - msleep(300); - - /* Disable VMIDTOG */ - snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | - WM8991_BUFDCOPEN | WM8991_POBCTRL); - - /* disable all output discharge bits */ - snd_soc_write(codec, WM8991_ANTIPOP1, 0); - - /* Enable outputs */ - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1b00); - - msleep(50); - - /* Enable VMID at 2x50k */ - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f02); - - msleep(100); - - /* Enable VREF */ - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f03); - - msleep(600); - - /* Enable BUFIOEN */ - snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | - WM8991_BUFDCOPEN | WM8991_POBCTRL | - WM8991_BUFIOEN); - - /* Disable outputs */ - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x3); - - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_BUFIOEN); - } - - /* VMID=2*250k */ - val = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1) & - ~WM8991_VMID_MODE_MASK; - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, val | 0x4); - break; - - case SND_SOC_BIAS_OFF: - /* Enable POBCTRL and SOFT_ST */ - snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | - WM8991_POBCTRL | WM8991_BUFIOEN); - - /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | - WM8991_BUFDCOPEN | WM8991_POBCTRL | - WM8991_BUFIOEN); - - /* mute DAC */ - val = snd_soc_read(codec, WM8991_DAC_CTRL); - snd_soc_write(codec, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE); - - /* Enable any disabled outputs */ - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f03); - - /* Disable VMID */ - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f01); - - msleep(300); - - /* Enable all output discharge bits */ - snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | - WM8991_DIS_RLINE | WM8991_DIS_OUT3 | - WM8991_DIS_OUT4 | WM8991_DIS_LOUT | - WM8991_DIS_ROUT); - - /* Disable VREF */ - snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x0); - - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8991_ANTIPOP2, 0x0); - codec->cache_sync = 1; - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -static int wm8991_suspend(struct snd_soc_codec *codec) -{ - wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8991_resume(struct snd_soc_codec *codec) -{ - wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} - -/* power down chip */ -static int wm8991_remove(struct snd_soc_codec *codec) -{ - wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8991_probe(struct snd_soc_codec *codec) -{ - struct wm8991_priv *wm8991; - int ret; - - wm8991 = snd_soc_codec_get_drvdata(codec); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8991->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - - ret = wm8991_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4, - WM8991_ALRCGPIO1, WM8991_ALRCGPIO1); - - snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2, - WM8991_GPIO1_SEL_MASK, 1); - - snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1, - WM8991_VREF_ENA | WM8991_VMID_MODE_MASK, - WM8991_VREF_ENA | WM8991_VMID_MODE_MASK); - - snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2, - WM8991_OPCLK_ENA, WM8991_OPCLK_ENA); - - snd_soc_write(codec, WM8991_DAC_CTRL, 0); - snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); - snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); - - snd_soc_add_codec_controls(codec, wm8991_snd_controls, - ARRAY_SIZE(wm8991_snd_controls)); - - snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets, - ARRAY_SIZE(wm8991_dapm_widgets)); - snd_soc_dapm_add_routes(&codec->dapm, audio_map, - ARRAY_SIZE(audio_map)); - return 0; -} - -#define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops wm8991_ops = { - .hw_params = wm8991_hw_params, - .digital_mute = wm8991_mute, - .set_fmt = wm8991_set_dai_fmt, - .set_clkdiv = wm8991_set_dai_clkdiv, - .set_pll = wm8991_set_dai_pll -}; - -/* - * The WM8991 supports 2 different and mutually exclusive DAI - * configurations. - * - * 1. ADC/DAC on Primary Interface - * 2. ADC on Primary Interface/DAC on secondary - */ -static struct snd_soc_dai_driver wm8991_dai = { - /* ADC/DAC on primary */ - .name = "wm8991", - .id = 1, - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = WM8991_FORMATS - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = WM8991_FORMATS - }, - .ops = &wm8991_ops -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { - .probe = wm8991_probe, - .remove = wm8991_remove, - .suspend = wm8991_suspend, - .resume = wm8991_resume, - .set_bias_level = wm8991_set_bias_level, - .reg_cache_size = WM8991_MAX_REGISTER + 1, - .reg_word_size = sizeof(u16), - .reg_cache_default = wm8991_reg_defs -}; - -static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8991_priv *wm8991; - int ret; - - wm8991 = kzalloc(sizeof *wm8991, GFP_KERNEL); - if (!wm8991) - return -ENOMEM; - - wm8991->control_type = SND_SOC_I2C; - i2c_set_clientdata(i2c, wm8991); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8991, &wm8991_dai, 1); - if (ret < 0) - kfree(wm8991); - return ret; -} - -static __devexit int wm8991_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id wm8991_i2c_id[] = { - { "wm8991", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id); - -static struct i2c_driver wm8991_i2c_driver = { - .driver = { - .name = "wm8991", - .owner = THIS_MODULE, - }, - .probe = wm8991_i2c_probe, - .remove = __devexit_p(wm8991_i2c_remove), - .id_table = wm8991_i2c_id, -}; - -static int __init wm8991_modinit(void) -{ - int ret; - ret = i2c_add_driver(&wm8991_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n", - ret); - } - return 0; -} -module_init(wm8991_modinit); - -static void __exit wm8991_exit(void) -{ - i2c_del_driver(&wm8991_i2c_driver); -} -module_exit(wm8991_exit); - -MODULE_DESCRIPTION("ASoC WM8991 driver"); -MODULE_AUTHOR("Graeme Gregory"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8991.h b/ANDROID_3.4.5/sound/soc/codecs/wm8991.h deleted file mode 100644 index 8a942efd..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8991.h +++ /dev/null @@ -1,833 +0,0 @@ -/* - * wm8991.h -- audio driver for WM8991 - * - * Copyright 2007 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com - * - * 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. - */ - -#ifndef _WM8991_H -#define _WM8991_H - -/* - * Register values. - */ -#define WM8991_RESET 0x00 -#define WM8991_POWER_MANAGEMENT_1 0x01 -#define WM8991_POWER_MANAGEMENT_2 0x02 -#define WM8991_POWER_MANAGEMENT_3 0x03 -#define WM8991_AUDIO_INTERFACE_1 0x04 -#define WM8991_AUDIO_INTERFACE_2 0x05 -#define WM8991_CLOCKING_1 0x06 -#define WM8991_CLOCKING_2 0x07 -#define WM8991_AUDIO_INTERFACE_3 0x08 -#define WM8991_AUDIO_INTERFACE_4 0x09 -#define WM8991_DAC_CTRL 0x0A -#define WM8991_LEFT_DAC_DIGITAL_VOLUME 0x0B -#define WM8991_RIGHT_DAC_DIGITAL_VOLUME 0x0C -#define WM8991_DIGITAL_SIDE_TONE 0x0D -#define WM8991_ADC_CTRL 0x0E -#define WM8991_LEFT_ADC_DIGITAL_VOLUME 0x0F -#define WM8991_RIGHT_ADC_DIGITAL_VOLUME 0x10 -#define WM8991_GPIO_CTRL_1 0x12 -#define WM8991_GPIO1_GPIO2 0x13 -#define WM8991_GPIO3_GPIO4 0x14 -#define WM8991_GPIO5_GPIO6 0x15 -#define WM8991_GPIOCTRL_2 0x16 -#define WM8991_GPIO_POL 0x17 -#define WM8991_LEFT_LINE_INPUT_1_2_VOLUME 0x18 -#define WM8991_LEFT_LINE_INPUT_3_4_VOLUME 0x19 -#define WM8991_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A -#define WM8991_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B -#define WM8991_LEFT_OUTPUT_VOLUME 0x1C -#define WM8991_RIGHT_OUTPUT_VOLUME 0x1D -#define WM8991_LINE_OUTPUTS_VOLUME 0x1E -#define WM8991_OUT3_4_VOLUME 0x1F -#define WM8991_LEFT_OPGA_VOLUME 0x20 -#define WM8991_RIGHT_OPGA_VOLUME 0x21 -#define WM8991_SPEAKER_VOLUME 0x22 -#define WM8991_CLASSD1 0x23 -#define WM8991_CLASSD3 0x25 -#define WM8991_INPUT_MIXER1 0x27 -#define WM8991_INPUT_MIXER2 0x28 -#define WM8991_INPUT_MIXER3 0x29 -#define WM8991_INPUT_MIXER4 0x2A -#define WM8991_INPUT_MIXER5 0x2B -#define WM8991_INPUT_MIXER6 0x2C -#define WM8991_OUTPUT_MIXER1 0x2D -#define WM8991_OUTPUT_MIXER2 0x2E -#define WM8991_OUTPUT_MIXER3 0x2F -#define WM8991_OUTPUT_MIXER4 0x30 -#define WM8991_OUTPUT_MIXER5 0x31 -#define WM8991_OUTPUT_MIXER6 0x32 -#define WM8991_OUT3_4_MIXER 0x33 -#define WM8991_LINE_MIXER1 0x34 -#define WM8991_LINE_MIXER2 0x35 -#define WM8991_SPEAKER_MIXER 0x36 -#define WM8991_ADDITIONAL_CONTROL 0x37 -#define WM8991_ANTIPOP1 0x38 -#define WM8991_ANTIPOP2 0x39 -#define WM8991_MICBIAS 0x3A -#define WM8991_PLL1 0x3C -#define WM8991_PLL2 0x3D -#define WM8991_PLL3 0x3E -#define WM8991_INTDRIVBITS 0x3F - -#define WM8991_REGISTER_COUNT 60 -#define WM8991_MAX_REGISTER 0x3F - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Reset - */ -#define WM8991_SW_RESET_CHIP_ID_MASK 0xFFFF /* SW_RESET_CHIP_ID - [15:0] */ - -/* - * R1 (0x01) - Power Management (1) - */ -#define WM8991_SPK_ENA 0x1000 /* SPK_ENA */ -#define WM8991_SPK_ENA_BIT 12 -#define WM8991_OUT3_ENA 0x0800 /* OUT3_ENA */ -#define WM8991_OUT3_ENA_BIT 11 -#define WM8991_OUT4_ENA 0x0400 /* OUT4_ENA */ -#define WM8991_OUT4_ENA_BIT 10 -#define WM8991_LOUT_ENA 0x0200 /* LOUT_ENA */ -#define WM8991_LOUT_ENA_BIT 9 -#define WM8991_ROUT_ENA 0x0100 /* ROUT_ENA */ -#define WM8991_ROUT_ENA_BIT 8 -#define WM8991_MICBIAS_ENA 0x0010 /* MICBIAS_ENA */ -#define WM8991_MICBIAS_ENA_BIT 4 -#define WM8991_VMID_MODE_MASK 0x0006 /* VMID_MODE - [2:1] */ -#define WM8991_VREF_ENA 0x0001 /* VREF_ENA */ -#define WM8991_VREF_ENA_BIT 0 - -/* - * R2 (0x02) - Power Management (2) - */ -#define WM8991_PLL_ENA 0x8000 /* PLL_ENA */ -#define WM8991_PLL_ENA_BIT 15 -#define WM8991_TSHUT_ENA 0x4000 /* TSHUT_ENA */ -#define WM8991_TSHUT_ENA_BIT 14 -#define WM8991_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */ -#define WM8991_TSHUT_OPDIS_BIT 13 -#define WM8991_OPCLK_ENA 0x0800 /* OPCLK_ENA */ -#define WM8991_OPCLK_ENA_BIT 11 -#define WM8991_AINL_ENA 0x0200 /* AINL_ENA */ -#define WM8991_AINL_ENA_BIT 9 -#define WM8991_AINR_ENA 0x0100 /* AINR_ENA */ -#define WM8991_AINR_ENA_BIT 8 -#define WM8991_LIN34_ENA 0x0080 /* LIN34_ENA */ -#define WM8991_LIN34_ENA_BIT 7 -#define WM8991_LIN12_ENA 0x0040 /* LIN12_ENA */ -#define WM8991_LIN12_ENA_BIT 6 -#define WM8991_RIN34_ENA 0x0020 /* RIN34_ENA */ -#define WM8991_RIN34_ENA_BIT 5 -#define WM8991_RIN12_ENA 0x0010 /* RIN12_ENA */ -#define WM8991_RIN12_ENA_BIT 4 -#define WM8991_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8991_ADCL_ENA_BIT 1 -#define WM8991_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8991_ADCR_ENA_BIT 0 - -/* - * R3 (0x03) - Power Management (3) - */ -#define WM8991_LON_ENA 0x2000 /* LON_ENA */ -#define WM8991_LON_ENA_BIT 13 -#define WM8991_LOP_ENA 0x1000 /* LOP_ENA */ -#define WM8991_LOP_ENA_BIT 12 -#define WM8991_RON_ENA 0x0800 /* RON_ENA */ -#define WM8991_RON_ENA_BIT 11 -#define WM8991_ROP_ENA 0x0400 /* ROP_ENA */ -#define WM8991_ROP_ENA_BIT 10 -#define WM8991_LOPGA_ENA 0x0080 /* LOPGA_ENA */ -#define WM8991_LOPGA_ENA_BIT 7 -#define WM8991_ROPGA_ENA 0x0040 /* ROPGA_ENA */ -#define WM8991_ROPGA_ENA_BIT 6 -#define WM8991_LOMIX_ENA 0x0020 /* LOMIX_ENA */ -#define WM8991_LOMIX_ENA_BIT 5 -#define WM8991_ROMIX_ENA 0x0010 /* ROMIX_ENA */ -#define WM8991_ROMIX_ENA_BIT 4 -#define WM8991_DACL_ENA 0x0002 /* DACL_ENA */ -#define WM8991_DACL_ENA_BIT 1 -#define WM8991_DACR_ENA 0x0001 /* DACR_ENA */ -#define WM8991_DACR_ENA_BIT 0 - -/* - * R4 (0x04) - Audio Interface (1) - */ -#define WM8991_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */ -#define WM8991_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */ -#define WM8991_AIFADC_TDM 0x2000 /* AIFADC_TDM */ -#define WM8991_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */ -#define WM8991_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */ -#define WM8991_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */ -#define WM8991_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */ -#define WM8991_AIF_WL_16BITS (0 << 5) -#define WM8991_AIF_WL_20BITS (1 << 5) -#define WM8991_AIF_WL_24BITS (2 << 5) -#define WM8991_AIF_WL_32BITS (3 << 5) -#define WM8991_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */ -#define WM8991_AIF_TMF_RIGHTJ (0 << 3) -#define WM8991_AIF_TMF_LEFTJ (1 << 3) -#define WM8991_AIF_TMF_I2S (2 << 3) -#define WM8991_AIF_TMF_DSP (3 << 3) - -/* - * R5 (0x05) - Audio Interface (2) - */ -#define WM8991_DACL_SRC 0x8000 /* DACL_SRC */ -#define WM8991_DACR_SRC 0x4000 /* DACR_SRC */ -#define WM8991_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ -#define WM8991_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8991_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */ -#define WM8991_DAC_COMP 0x0010 /* DAC_COMP */ -#define WM8991_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */ -#define WM8991_ADC_COMP 0x0004 /* ADC_COMP */ -#define WM8991_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */ -#define WM8991_LOOPBACK 0x0001 /* LOOPBACK */ - -/* - * R6 (0x06) - Clocking (1) - */ -#define WM8991_TOCLK_RATE 0x8000 /* TOCLK_RATE */ -#define WM8991_TOCLK_ENA 0x4000 /* TOCLK_ENA */ -#define WM8991_OPCLKDIV_MASK 0x1E00 /* OPCLKDIV - [12:9] */ -#define WM8991_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */ -#define WM8991_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */ -#define WM8991_BCLK_DIV_1 (0x0 << 1) -#define WM8991_BCLK_DIV_1_5 (0x1 << 1) -#define WM8991_BCLK_DIV_2 (0x2 << 1) -#define WM8991_BCLK_DIV_3 (0x3 << 1) -#define WM8991_BCLK_DIV_4 (0x4 << 1) -#define WM8991_BCLK_DIV_5_5 (0x5 << 1) -#define WM8991_BCLK_DIV_6 (0x6 << 1) -#define WM8991_BCLK_DIV_8 (0x7 << 1) -#define WM8991_BCLK_DIV_11 (0x8 << 1) -#define WM8991_BCLK_DIV_12 (0x9 << 1) -#define WM8991_BCLK_DIV_16 (0xA << 1) -#define WM8991_BCLK_DIV_22 (0xB << 1) -#define WM8991_BCLK_DIV_24 (0xC << 1) -#define WM8991_BCLK_DIV_32 (0xD << 1) -#define WM8991_BCLK_DIV_44 (0xE << 1) -#define WM8991_BCLK_DIV_48 (0xF << 1) - -/* - * R7 (0x07) - Clocking (2) - */ -#define WM8991_MCLK_SRC 0x8000 /* MCLK_SRC */ -#define WM8991_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */ -#define WM8991_CLK_FORCE 0x2000 /* CLK_FORCE */ -#define WM8991_MCLK_DIV_MASK 0x1800 /* MCLK_DIV - [12:11] */ -#define WM8991_MCLK_DIV_1 (0 << 11) -#define WM8991_MCLK_DIV_2 ( 2 << 11) -#define WM8991_MCLK_INV 0x0400 /* MCLK_INV */ -#define WM8991_ADC_CLKDIV_MASK 0x00E0 /* ADC_CLKDIV - [7:5] */ -#define WM8991_ADC_CLKDIV_1 (0 << 5) -#define WM8991_ADC_CLKDIV_1_5 (1 << 5) -#define WM8991_ADC_CLKDIV_2 (2 << 5) -#define WM8991_ADC_CLKDIV_3 (3 << 5) -#define WM8991_ADC_CLKDIV_4 (4 << 5) -#define WM8991_ADC_CLKDIV_5_5 (5 << 5) -#define WM8991_ADC_CLKDIV_6 (6 << 5) -#define WM8991_DAC_CLKDIV_MASK 0x001C /* DAC_CLKDIV - [4:2] */ -#define WM8991_DAC_CLKDIV_1 (0 << 2) -#define WM8991_DAC_CLKDIV_1_5 (1 << 2) -#define WM8991_DAC_CLKDIV_2 (2 << 2) -#define WM8991_DAC_CLKDIV_3 (3 << 2) -#define WM8991_DAC_CLKDIV_4 (4 << 2) -#define WM8991_DAC_CLKDIV_5_5 (5 << 2) -#define WM8991_DAC_CLKDIV_6 (6 << 2) - -/* - * R8 (0x08) - Audio Interface (3) - */ -#define WM8991_AIF_MSTR1 0x8000 /* AIF_MSTR1 */ -#define WM8991_AIF_MSTR2 0x4000 /* AIF_MSTR2 */ -#define WM8991_AIF_SEL 0x2000 /* AIF_SEL */ -#define WM8991_ADCLRC_DIR 0x0800 /* ADCLRC_DIR */ -#define WM8991_ADCLRC_RATE_MASK 0x07FF /* ADCLRC_RATE - [10:0] */ - -/* - * R9 (0x09) - Audio Interface (4) - */ -#define WM8991_ALRCGPIO1 0x8000 /* ALRCGPIO1 */ -#define WM8991_ALRCBGPIO6 0x4000 /* ALRCBGPIO6 */ -#define WM8991_AIF_TRIS 0x2000 /* AIF_TRIS */ -#define WM8991_DACLRC_DIR 0x0800 /* DACLRC_DIR */ -#define WM8991_DACLRC_RATE_MASK 0x07FF /* DACLRC_RATE - [10:0] */ - -/* - * R10 (0x0A) - DAC CTRL - */ -#define WM8991_AIF_LRCLKRATE 0x0400 /* AIF_LRCLKRATE */ -#define WM8991_DAC_MONO 0x0200 /* DAC_MONO */ -#define WM8991_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */ -#define WM8991_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */ -#define WM8991_DAC_MUTEMODE 0x0040 /* DAC_MUTEMODE */ -#define WM8991_DEEMP_MASK 0x0030 /* DEEMP - [5:4] */ -#define WM8991_DAC_MUTE 0x0004 /* DAC_MUTE */ -#define WM8991_DACL_DATINV 0x0002 /* DACL_DATINV */ -#define WM8991_DACR_DATINV 0x0001 /* DACR_DATINV */ - -/* - * R11 (0x0B) - Left DAC Digital Volume - */ -#define WM8991_DAC_VU 0x0100 /* DAC_VU */ -#define WM8991_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ -#define WM8991_DACL_VOL_SHIFT 0 -/* - * R12 (0x0C) - Right DAC Digital Volume - */ -#define WM8991_DAC_VU 0x0100 /* DAC_VU */ -#define WM8991_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ -#define WM8991_DACR_VOL_SHIFT 0 -/* - * R13 (0x0D) - Digital Side Tone - */ -#define WM8991_ADCL_DAC_SVOL_MASK 0x0F /* ADCL_DAC_SVOL - [12:9] */ -#define WM8991_ADCL_DAC_SVOL_SHIFT 9 -#define WM8991_ADCR_DAC_SVOL_MASK 0x0F /* ADCR_DAC_SVOL - [8:5] */ -#define WM8991_ADCR_DAC_SVOL_SHIFT 5 -#define WM8991_ADC_TO_DACL_MASK 0x03 /* ADC_TO_DACL - [3:2] */ -#define WM8991_ADC_TO_DACL_SHIFT 2 -#define WM8991_ADC_TO_DACR_MASK 0x03 /* ADC_TO_DACR - [1:0] */ -#define WM8991_ADC_TO_DACR_SHIFT 0 - -/* - * R14 (0x0E) - ADC CTRL - */ -#define WM8991_ADC_HPF_ENA 0x0100 /* ADC_HPF_ENA */ -#define WM8991_ADC_HPF_ENA_BIT 8 -#define WM8991_ADC_HPF_CUT_MASK 0x03 /* ADC_HPF_CUT - [6:5] */ -#define WM8991_ADC_HPF_CUT_SHIFT 5 -#define WM8991_ADCL_DATINV 0x0002 /* ADCL_DATINV */ -#define WM8991_ADCL_DATINV_BIT 1 -#define WM8991_ADCR_DATINV 0x0001 /* ADCR_DATINV */ -#define WM8991_ADCR_DATINV_BIT 0 - -/* - * R15 (0x0F) - Left ADC Digital Volume - */ -#define WM8991_ADC_VU 0x0100 /* ADC_VU */ -#define WM8991_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ -#define WM8991_ADCL_VOL_SHIFT 0 - -/* - * R16 (0x10) - Right ADC Digital Volume - */ -#define WM8991_ADC_VU 0x0100 /* ADC_VU */ -#define WM8991_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ -#define WM8991_ADCR_VOL_SHIFT 0 - -/* - * R18 (0x12) - GPIO CTRL 1 - */ -#define WM8991_IRQ 0x1000 /* IRQ */ -#define WM8991_TEMPOK 0x0800 /* TEMPOK */ -#define WM8991_MICSHRT 0x0400 /* MICSHRT */ -#define WM8991_MICDET 0x0200 /* MICDET */ -#define WM8991_PLL_LCK 0x0100 /* PLL_LCK */ -#define WM8991_GPI8_STATUS 0x0080 /* GPI8_STATUS */ -#define WM8991_GPI7_STATUS 0x0040 /* GPI7_STATUS */ -#define WM8991_GPIO6_STATUS 0x0020 /* GPIO6_STATUS */ -#define WM8991_GPIO5_STATUS 0x0010 /* GPIO5_STATUS */ -#define WM8991_GPIO4_STATUS 0x0008 /* GPIO4_STATUS */ -#define WM8991_GPIO3_STATUS 0x0004 /* GPIO3_STATUS */ -#define WM8991_GPIO2_STATUS 0x0002 /* GPIO2_STATUS */ -#define WM8991_GPIO1_STATUS 0x0001 /* GPIO1_STATUS */ - -/* - * R19 (0x13) - GPIO1 & GPIO2 - */ -#define WM8991_GPIO2_DEB_ENA 0x8000 /* GPIO2_DEB_ENA */ -#define WM8991_GPIO2_IRQ_ENA 0x4000 /* GPIO2_IRQ_ENA */ -#define WM8991_GPIO2_PU 0x2000 /* GPIO2_PU */ -#define WM8991_GPIO2_PD 0x1000 /* GPIO2_PD */ -#define WM8991_GPIO2_SEL_MASK 0x0F00 /* GPIO2_SEL - [11:8] */ -#define WM8991_GPIO1_DEB_ENA 0x0080 /* GPIO1_DEB_ENA */ -#define WM8991_GPIO1_IRQ_ENA 0x0040 /* GPIO1_IRQ_ENA */ -#define WM8991_GPIO1_PU 0x0020 /* GPIO1_PU */ -#define WM8991_GPIO1_PD 0x0010 /* GPIO1_PD */ -#define WM8991_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */ - -/* - * R20 (0x14) - GPIO3 & GPIO4 - */ -#define WM8991_GPIO4_DEB_ENA 0x8000 /* GPIO4_DEB_ENA */ -#define WM8991_GPIO4_IRQ_ENA 0x4000 /* GPIO4_IRQ_ENA */ -#define WM8991_GPIO4_PU 0x2000 /* GPIO4_PU */ -#define WM8991_GPIO4_PD 0x1000 /* GPIO4_PD */ -#define WM8991_GPIO4_SEL_MASK 0x0F00 /* GPIO4_SEL - [11:8] */ -#define WM8991_GPIO3_DEB_ENA 0x0080 /* GPIO3_DEB_ENA */ -#define WM8991_GPIO3_IRQ_ENA 0x0040 /* GPIO3_IRQ_ENA */ -#define WM8991_GPIO3_PU 0x0020 /* GPIO3_PU */ -#define WM8991_GPIO3_PD 0x0010 /* GPIO3_PD */ -#define WM8991_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */ - -/* - * R21 (0x15) - GPIO5 & GPIO6 - */ -#define WM8991_GPIO6_DEB_ENA 0x8000 /* GPIO6_DEB_ENA */ -#define WM8991_GPIO6_IRQ_ENA 0x4000 /* GPIO6_IRQ_ENA */ -#define WM8991_GPIO6_PU 0x2000 /* GPIO6_PU */ -#define WM8991_GPIO6_PD 0x1000 /* GPIO6_PD */ -#define WM8991_GPIO6_SEL_MASK 0x0F00 /* GPIO6_SEL - [11:8] */ -#define WM8991_GPIO5_DEB_ENA 0x0080 /* GPIO5_DEB_ENA */ -#define WM8991_GPIO5_IRQ_ENA 0x0040 /* GPIO5_IRQ_ENA */ -#define WM8991_GPIO5_PU 0x0020 /* GPIO5_PU */ -#define WM8991_GPIO5_PD 0x0010 /* GPIO5_PD */ -#define WM8991_GPIO5_SEL_MASK 0x000F /* GPIO5_SEL - [3:0] */ - -/* - * R22 (0x16) - GPIOCTRL 2 - */ -#define WM8991_RD_3W_ENA 0x8000 /* RD_3W_ENA */ -#define WM8991_MODE_3W4W 0x4000 /* MODE_3W4W */ -#define WM8991_TEMPOK_IRQ_ENA 0x0800 /* TEMPOK_IRQ_ENA */ -#define WM8991_MICSHRT_IRQ_ENA 0x0400 /* MICSHRT_IRQ_ENA */ -#define WM8991_MICDET_IRQ_ENA 0x0200 /* MICDET_IRQ_ENA */ -#define WM8991_PLL_LCK_IRQ_ENA 0x0100 /* PLL_LCK_IRQ_ENA */ -#define WM8991_GPI8_DEB_ENA 0x0080 /* GPI8_DEB_ENA */ -#define WM8991_GPI8_IRQ_ENA 0x0040 /* GPI8_IRQ_ENA */ -#define WM8991_GPI8_ENA 0x0010 /* GPI8_ENA */ -#define WM8991_GPI7_DEB_ENA 0x0008 /* GPI7_DEB_ENA */ -#define WM8991_GPI7_IRQ_ENA 0x0004 /* GPI7_IRQ_ENA */ -#define WM8991_GPI7_ENA 0x0001 /* GPI7_ENA */ - -/* - * R23 (0x17) - GPIO_POL - */ -#define WM8991_IRQ_INV 0x1000 /* IRQ_INV */ -#define WM8991_TEMPOK_POL 0x0800 /* TEMPOK_POL */ -#define WM8991_MICSHRT_POL 0x0400 /* MICSHRT_POL */ -#define WM8991_MICDET_POL 0x0200 /* MICDET_POL */ -#define WM8991_PLL_LCK_POL 0x0100 /* PLL_LCK_POL */ -#define WM8991_GPI8_POL 0x0080 /* GPI8_POL */ -#define WM8991_GPI7_POL 0x0040 /* GPI7_POL */ -#define WM8991_GPIO6_POL 0x0020 /* GPIO6_POL */ -#define WM8991_GPIO5_POL 0x0010 /* GPIO5_POL */ -#define WM8991_GPIO4_POL 0x0008 /* GPIO4_POL */ -#define WM8991_GPIO3_POL 0x0004 /* GPIO3_POL */ -#define WM8991_GPIO2_POL 0x0002 /* GPIO2_POL */ -#define WM8991_GPIO1_POL 0x0001 /* GPIO1_POL */ - -/* - * R24 (0x18) - Left Line Input 1&2 Volume - */ -#define WM8991_IPVU 0x0100 /* IPVU */ -#define WM8991_LI12MUTE 0x0080 /* LI12MUTE */ -#define WM8991_LI12MUTE_BIT 7 -#define WM8991_LI12ZC 0x0040 /* LI12ZC */ -#define WM8991_LI12ZC_BIT 6 -#define WM8991_LIN12VOL_MASK 0x001F /* LIN12VOL - [4:0] */ -#define WM8991_LIN12VOL_SHIFT 0 -/* - * R25 (0x19) - Left Line Input 3&4 Volume - */ -#define WM8991_IPVU 0x0100 /* IPVU */ -#define WM8991_LI34MUTE 0x0080 /* LI34MUTE */ -#define WM8991_LI34MUTE_BIT 7 -#define WM8991_LI34ZC 0x0040 /* LI34ZC */ -#define WM8991_LI34ZC_BIT 6 -#define WM8991_LIN34VOL_MASK 0x001F /* LIN34VOL - [4:0] */ -#define WM8991_LIN34VOL_SHIFT 0 - -/* - * R26 (0x1A) - Right Line Input 1&2 Volume - */ -#define WM8991_IPVU 0x0100 /* IPVU */ -#define WM8991_RI12MUTE 0x0080 /* RI12MUTE */ -#define WM8991_RI12MUTE_BIT 7 -#define WM8991_RI12ZC 0x0040 /* RI12ZC */ -#define WM8991_RI12ZC_BIT 6 -#define WM8991_RIN12VOL_MASK 0x001F /* RIN12VOL - [4:0] */ -#define WM8991_RIN12VOL_SHIFT 0 - -/* - * R27 (0x1B) - Right Line Input 3&4 Volume - */ -#define WM8991_IPVU 0x0100 /* IPVU */ -#define WM8991_RI34MUTE 0x0080 /* RI34MUTE */ -#define WM8991_RI34MUTE_BIT 7 -#define WM8991_RI34ZC 0x0040 /* RI34ZC */ -#define WM8991_RI34ZC_BIT 6 -#define WM8991_RIN34VOL_MASK 0x001F /* RIN34VOL - [4:0] */ -#define WM8991_RIN34VOL_SHIFT 0 - -/* - * R28 (0x1C) - Left Output Volume - */ -#define WM8991_OPVU 0x0100 /* OPVU */ -#define WM8991_LOZC 0x0080 /* LOZC */ -#define WM8991_LOZC_BIT 7 -#define WM8991_LOUTVOL_MASK 0x007F /* LOUTVOL - [6:0] */ -#define WM8991_LOUTVOL_SHIFT 0 -/* - * R29 (0x1D) - Right Output Volume - */ -#define WM8991_OPVU 0x0100 /* OPVU */ -#define WM8991_ROZC 0x0080 /* ROZC */ -#define WM8991_ROZC_BIT 7 -#define WM8991_ROUTVOL_MASK 0x007F /* ROUTVOL - [6:0] */ -#define WM8991_ROUTVOL_SHIFT 0 -/* - * R30 (0x1E) - Line Outputs Volume - */ -#define WM8991_LONMUTE 0x0040 /* LONMUTE */ -#define WM8991_LONMUTE_BIT 6 -#define WM8991_LOPMUTE 0x0020 /* LOPMUTE */ -#define WM8991_LOPMUTE_BIT 5 -#define WM8991_LOATTN 0x0010 /* LOATTN */ -#define WM8991_LOATTN_BIT 4 -#define WM8991_RONMUTE 0x0004 /* RONMUTE */ -#define WM8991_RONMUTE_BIT 2 -#define WM8991_ROPMUTE 0x0002 /* ROPMUTE */ -#define WM8991_ROPMUTE_BIT 1 -#define WM8991_ROATTN 0x0001 /* ROATTN */ -#define WM8991_ROATTN_BIT 0 - -/* - * R31 (0x1F) - Out3/4 Volume - */ -#define WM8991_OUT3MUTE 0x0020 /* OUT3MUTE */ -#define WM8991_OUT3MUTE_BIT 5 -#define WM8991_OUT3ATTN 0x0010 /* OUT3ATTN */ -#define WM8991_OUT3ATTN_BIT 4 -#define WM8991_OUT4MUTE 0x0002 /* OUT4MUTE */ -#define WM8991_OUT4MUTE_BIT 1 -#define WM8991_OUT4ATTN 0x0001 /* OUT4ATTN */ -#define WM8991_OUT4ATTN_BIT 0 - -/* - * R32 (0x20) - Left OPGA Volume - */ -#define WM8991_OPVU 0x0100 /* OPVU */ -#define WM8991_LOPGAZC 0x0080 /* LOPGAZC */ -#define WM8991_LOPGAZC_BIT 7 -#define WM8991_LOPGAVOL_MASK 0x007F /* LOPGAVOL - [6:0] */ -#define WM8991_LOPGAVOL_SHIFT 0 - -/* - * R33 (0x21) - Right OPGA Volume - */ -#define WM8991_OPVU 0x0100 /* OPVU */ -#define WM8991_ROPGAZC 0x0080 /* ROPGAZC */ -#define WM8991_ROPGAZC_BIT 7 -#define WM8991_ROPGAVOL_MASK 0x007F /* ROPGAVOL - [6:0] */ -#define WM8991_ROPGAVOL_SHIFT 0 -/* - * R34 (0x22) - Speaker Volume - */ -#define WM8991_SPKVOL_MASK 0x0003 /* SPKVOL - [1:0] */ -#define WM8991_SPKVOL_SHIFT 0 - -/* - * R35 (0x23) - ClassD1 - */ -#define WM8991_CDMODE 0x0100 /* CDMODE */ -#define WM8991_CDMODE_BIT 8 - -/* - * R37 (0x25) - ClassD3 - */ -#define WM8991_DCGAIN_MASK 0x0007 /* DCGAIN - [5:3] */ -#define WM8991_DCGAIN_SHIFT 3 -#define WM8991_ACGAIN_MASK 0x0007 /* ACGAIN - [2:0] */ -#define WM8991_ACGAIN_SHIFT 0 -/* - * R39 (0x27) - Input Mixer1 - */ -#define WM8991_AINLMODE_MASK 0x000C /* AINLMODE - [3:2] */ -#define WM8991_AINLMODE_SHIFT 2 -#define WM8991_AINRMODE_MASK 0x0003 /* AINRMODE - [1:0] */ -#define WM8991_AINRMODE_SHIFT 0 - -/* - * R40 (0x28) - Input Mixer2 - */ -#define WM8991_LMP4 0x0080 /* LMP4 */ -#define WM8991_LMP4_BIT 7 /* LMP4 */ -#define WM8991_LMN3 0x0040 /* LMN3 */ -#define WM8991_LMN3_BIT 6 /* LMN3 */ -#define WM8991_LMP2 0x0020 /* LMP2 */ -#define WM8991_LMP2_BIT 5 /* LMP2 */ -#define WM8991_LMN1 0x0010 /* LMN1 */ -#define WM8991_LMN1_BIT 4 /* LMN1 */ -#define WM8991_RMP4 0x0008 /* RMP4 */ -#define WM8991_RMP4_BIT 3 /* RMP4 */ -#define WM8991_RMN3 0x0004 /* RMN3 */ -#define WM8991_RMN3_BIT 2 /* RMN3 */ -#define WM8991_RMP2 0x0002 /* RMP2 */ -#define WM8991_RMP2_BIT 1 /* RMP2 */ -#define WM8991_RMN1 0x0001 /* RMN1 */ -#define WM8991_RMN1_BIT 0 /* RMN1 */ - -/* - * R41 (0x29) - Input Mixer3 - */ -#define WM8991_L34MNB 0x0100 /* L34MNB */ -#define WM8991_L34MNB_BIT 8 -#define WM8991_L34MNBST 0x0080 /* L34MNBST */ -#define WM8991_L34MNBST_BIT 7 -#define WM8991_L12MNB 0x0020 /* L12MNB */ -#define WM8991_L12MNB_BIT 5 -#define WM8991_L12MNBST 0x0010 /* L12MNBST */ -#define WM8991_L12MNBST_BIT 4 -#define WM8991_LDBVOL_MASK 0x0007 /* LDBVOL - [2:0] */ -#define WM8991_LDBVOL_SHIFT 0 - -/* - * R42 (0x2A) - Input Mixer4 - */ -#define WM8991_R34MNB 0x0100 /* R34MNB */ -#define WM8991_R34MNB_BIT 8 -#define WM8991_R34MNBST 0x0080 /* R34MNBST */ -#define WM8991_R34MNBST_BIT 7 -#define WM8991_R12MNB 0x0020 /* R12MNB */ -#define WM8991_R12MNB_BIT 5 -#define WM8991_R12MNBST 0x0010 /* R12MNBST */ -#define WM8991_R12MNBST_BIT 4 -#define WM8991_RDBVOL_MASK 0x0007 /* RDBVOL - [2:0] */ -#define WM8991_RDBVOL_SHIFT 0 - -/* - * R43 (0x2B) - Input Mixer5 - */ -#define WM8991_LI2BVOL_MASK 0x07 /* LI2BVOL - [8:6] */ -#define WM8991_LI2BVOL_SHIFT 6 -#define WM8991_LR4BVOL_MASK 0x07 /* LR4BVOL - [5:3] */ -#define WM8991_LR4BVOL_SHIFT 3 -#define WM8991_LL4BVOL_MASK 0x07 /* LL4BVOL - [2:0] */ -#define WM8991_LL4BVOL_SHIFT 0 - -/* - * R44 (0x2C) - Input Mixer6 - */ -#define WM8991_RI2BVOL_MASK 0x07 /* RI2BVOL - [8:6] */ -#define WM8991_RI2BVOL_SHIFT 6 -#define WM8991_RL4BVOL_MASK 0x07 /* RL4BVOL - [5:3] */ -#define WM8991_RL4BVOL_SHIFT 3 -#define WM8991_RR4BVOL_MASK 0x07 /* RR4BVOL - [2:0] */ -#define WM8991_RR4BVOL_SHIFT 0 - -/* - * R45 (0x2D) - Output Mixer1 - */ -#define WM8991_LRBLO 0x0080 /* LRBLO */ -#define WM8991_LRBLO_BIT 7 -#define WM8991_LLBLO 0x0040 /* LLBLO */ -#define WM8991_LLBLO_BIT 6 -#define WM8991_LRI3LO 0x0020 /* LRI3LO */ -#define WM8991_LRI3LO_BIT 5 -#define WM8991_LLI3LO 0x0010 /* LLI3LO */ -#define WM8991_LLI3LO_BIT 4 -#define WM8991_LR12LO 0x0008 /* LR12LO */ -#define WM8991_LR12LO_BIT 3 -#define WM8991_LL12LO 0x0004 /* LL12LO */ -#define WM8991_LL12LO_BIT 2 -#define WM8991_LDLO 0x0001 /* LDLO */ -#define WM8991_LDLO_BIT 0 - -/* - * R46 (0x2E) - Output Mixer2 - */ -#define WM8991_RLBRO 0x0080 /* RLBRO */ -#define WM8991_RLBRO_BIT 7 -#define WM8991_RRBRO 0x0040 /* RRBRO */ -#define WM8991_RRBRO_BIT 6 -#define WM8991_RLI3RO 0x0020 /* RLI3RO */ -#define WM8991_RLI3RO_BIT 5 -#define WM8991_RRI3RO 0x0010 /* RRI3RO */ -#define WM8991_RRI3RO_BIT 4 -#define WM8991_RL12RO 0x0008 /* RL12RO */ -#define WM8991_RL12RO_BIT 3 -#define WM8991_RR12RO 0x0004 /* RR12RO */ -#define WM8991_RR12RO_BIT 2 -#define WM8991_RDRO 0x0001 /* RDRO */ -#define WM8991_RDRO_BIT 0 - -/* - * R47 (0x2F) - Output Mixer3 - */ -#define WM8991_LLI3LOVOL_MASK 0x07 /* LLI3LOVOL - [8:6] */ -#define WM8991_LLI3LOVOL_SHIFT 6 -#define WM8991_LR12LOVOL_MASK 0x07 /* LR12LOVOL - [5:3] */ -#define WM8991_LR12LOVOL_SHIFT 3 -#define WM8991_LL12LOVOL_MASK 0x07 /* LL12LOVOL - [2:0] */ -#define WM8991_LL12LOVOL_SHIFT 0 - -/* - * R48 (0x30) - Output Mixer4 - */ -#define WM8991_RRI3ROVOL_MASK 0x07 /* RRI3ROVOL - [8:6] */ -#define WM8991_RRI3ROVOL_SHIFT 6 -#define WM8991_RL12ROVOL_MASK 0x07 /* RL12ROVOL - [5:3] */ -#define WM8991_RL12ROVOL_SHIFT 3 -#define WM8991_RR12ROVOL_MASK 0x07 /* RR12ROVOL - [2:0] */ -#define WM8991_RR12ROVOL_SHIFT 0 - -/* - * R49 (0x31) - Output Mixer5 - */ -#define WM8991_LRI3LOVOL_MASK 0x07 /* LRI3LOVOL - [8:6] */ -#define WM8991_LRI3LOVOL_SHIFT 6 -#define WM8991_LRBLOVOL_MASK 0x07 /* LRBLOVOL - [5:3] */ -#define WM8991_LRBLOVOL_SHIFT 3 -#define WM8991_LLBLOVOL_MASK 0x07 /* LLBLOVOL - [2:0] */ -#define WM8991_LLBLOVOL_SHIFT 0 - -/* - * R50 (0x32) - Output Mixer6 - */ -#define WM8991_RLI3ROVOL_MASK 0x07 /* RLI3ROVOL - [8:6] */ -#define WM8991_RLI3ROVOL_SHIFT 6 -#define WM8991_RLBROVOL_MASK 0x07 /* RLBROVOL - [5:3] */ -#define WM8991_RLBROVOL_SHIFT 3 -#define WM8991_RRBROVOL_MASK 0x07 /* RRBROVOL - [2:0] */ -#define WM8991_RRBROVOL_SHIFT 0 - -/* - * R51 (0x33) - Out3/4 Mixer - */ -#define WM8991_VSEL_MASK 0x0180 /* VSEL - [8:7] */ -#define WM8991_LI4O3 0x0020 /* LI4O3 */ -#define WM8991_LI4O3_BIT 5 -#define WM8991_LPGAO3 0x0010 /* LPGAO3 */ -#define WM8991_LPGAO3_BIT 4 -#define WM8991_RI4O4 0x0002 /* RI4O4 */ -#define WM8991_RI4O4_BIT 1 -#define WM8991_RPGAO4 0x0001 /* RPGAO4 */ -#define WM8991_RPGAO4_BIT 0 -/* - * R52 (0x34) - Line Mixer1 - */ -#define WM8991_LLOPGALON 0x0040 /* LLOPGALON */ -#define WM8991_LLOPGALON_BIT 6 -#define WM8991_LROPGALON 0x0020 /* LROPGALON */ -#define WM8991_LROPGALON_BIT 5 -#define WM8991_LOPLON 0x0010 /* LOPLON */ -#define WM8991_LOPLON_BIT 4 -#define WM8991_LR12LOP 0x0004 /* LR12LOP */ -#define WM8991_LR12LOP_BIT 2 -#define WM8991_LL12LOP 0x0002 /* LL12LOP */ -#define WM8991_LL12LOP_BIT 1 -#define WM8991_LLOPGALOP 0x0001 /* LLOPGALOP */ -#define WM8991_LLOPGALOP_BIT 0 -/* - * R53 (0x35) - Line Mixer2 - */ -#define WM8991_RROPGARON 0x0040 /* RROPGARON */ -#define WM8991_RROPGARON_BIT 6 -#define WM8991_RLOPGARON 0x0020 /* RLOPGARON */ -#define WM8991_RLOPGARON_BIT 5 -#define WM8991_ROPRON 0x0010 /* ROPRON */ -#define WM8991_ROPRON_BIT 4 -#define WM8991_RL12ROP 0x0004 /* RL12ROP */ -#define WM8991_RL12ROP_BIT 2 -#define WM8991_RR12ROP 0x0002 /* RR12ROP */ -#define WM8991_RR12ROP_BIT 1 -#define WM8991_RROPGAROP 0x0001 /* RROPGAROP */ -#define WM8991_RROPGAROP_BIT 0 - -/* - * R54 (0x36) - Speaker Mixer - */ -#define WM8991_LB2SPK 0x0080 /* LB2SPK */ -#define WM8991_LB2SPK_BIT 7 -#define WM8991_RB2SPK 0x0040 /* RB2SPK */ -#define WM8991_RB2SPK_BIT 6 -#define WM8991_LI2SPK 0x0020 /* LI2SPK */ -#define WM8991_LI2SPK_BIT 5 -#define WM8991_RI2SPK 0x0010 /* RI2SPK */ -#define WM8991_RI2SPK_BIT 4 -#define WM8991_LOPGASPK 0x0008 /* LOPGASPK */ -#define WM8991_LOPGASPK_BIT 3 -#define WM8991_ROPGASPK 0x0004 /* ROPGASPK */ -#define WM8991_ROPGASPK_BIT 2 -#define WM8991_LDSPK 0x0002 /* LDSPK */ -#define WM8991_LDSPK_BIT 1 -#define WM8991_RDSPK 0x0001 /* RDSPK */ -#define WM8991_RDSPK_BIT 0 - -/* - * R55 (0x37) - Additional Control - */ -#define WM8991_VROI 0x0001 /* VROI */ - -/* - * R56 (0x38) - AntiPOP1 - */ -#define WM8991_DIS_LLINE 0x0020 /* DIS_LLINE */ -#define WM8991_DIS_RLINE 0x0010 /* DIS_RLINE */ -#define WM8991_DIS_OUT3 0x0008 /* DIS_OUT3 */ -#define WM8991_DIS_OUT4 0x0004 /* DIS_OUT4 */ -#define WM8991_DIS_LOUT 0x0002 /* DIS_LOUT */ -#define WM8991_DIS_ROUT 0x0001 /* DIS_ROUT */ - -/* - * R57 (0x39) - AntiPOP2 - */ -#define WM8991_SOFTST 0x0040 /* SOFTST */ -#define WM8991_BUFIOEN 0x0008 /* BUFIOEN */ -#define WM8991_BUFDCOPEN 0x0004 /* BUFDCOPEN */ -#define WM8991_POBCTRL 0x0002 /* POBCTRL */ -#define WM8991_VMIDTOG 0x0001 /* VMIDTOG */ - -/* - * R58 (0x3A) - MICBIAS - */ -#define WM8991_MCDSCTH_MASK 0x00C0 /* MCDSCTH - [7:6] */ -#define WM8991_MCDTHR_MASK 0x0038 /* MCDTHR - [5:3] */ -#define WM8991_MCD 0x0004 /* MCD */ -#define WM8991_MBSEL 0x0001 /* MBSEL */ - -/* - * R60 (0x3C) - PLL1 - */ -#define WM8991_SDM 0x0080 /* SDM */ -#define WM8991_PRESCALE 0x0040 /* PRESCALE */ -#define WM8991_PLLN_MASK 0x000F /* PLLN - [3:0] */ - -/* - * R61 (0x3D) - PLL2 - */ -#define WM8991_PLLK1_MASK 0x00FF /* PLLK1 - [7:0] */ - -/* - * R62 (0x3E) - PLL3 - */ -#define WM8991_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */ - -/* - * R63 (0x3F) - Internal Driver Bits - */ -#define WM8991_INMIXL_PWR_BIT 0 -#define WM8991_AINLMUX_PWR_BIT 1 -#define WM8991_INMIXR_PWR_BIT 2 -#define WM8991_AINRMUX_PWR_BIT 3 - -#define WM8991_MCLK_DIV 0 -#define WM8991_DACCLK_DIV 1 -#define WM8991_ADCCLK_DIV 2 -#define WM8991_BCLK_DIV 3 - -#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ - tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - -#endif /* _WM8991_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8993.c b/ANDROID_3.4.5/sound/soc/codecs/wm8993.c deleted file mode 100644 index d256a934..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8993.c +++ /dev/null @@ -1,1866 +0,0 @@ -/* - * wm8993.c -- WM8993 ALSA SoC audio driver - * - * Copyright 2009, 2010 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8993.h" -#include "wm_hubs.h" - -#define WM8993_NUM_SUPPLIES 6 -static const char *wm8993_supply_names[WM8993_NUM_SUPPLIES] = { - "DCVDD", - "DBVDD", - "AVDD1", - "AVDD2", - "CPVDD", - "SPKVDD", -}; - -static struct reg_default wm8993_reg_defaults[] = { - { 1, 0x0000 }, /* R1 - Power Management (1) */ - { 2, 0x6000 }, /* R2 - Power Management (2) */ - { 3, 0x0000 }, /* R3 - Power Management (3) */ - { 4, 0x4050 }, /* R4 - Audio Interface (1) */ - { 5, 0x4000 }, /* R5 - Audio Interface (2) */ - { 6, 0x01C8 }, /* R6 - Clocking 1 */ - { 7, 0x0000 }, /* R7 - Clocking 2 */ - { 8, 0x0000 }, /* R8 - Audio Interface (3) */ - { 9, 0x0040 }, /* R9 - Audio Interface (4) */ - { 10, 0x0004 }, /* R10 - DAC CTRL */ - { 11, 0x00C0 }, /* R11 - Left DAC Digital Volume */ - { 12, 0x00C0 }, /* R12 - Right DAC Digital Volume */ - { 13, 0x0000 }, /* R13 - Digital Side Tone */ - { 14, 0x0300 }, /* R14 - ADC CTRL */ - { 15, 0x00C0 }, /* R15 - Left ADC Digital Volume */ - { 16, 0x00C0 }, /* R16 - Right ADC Digital Volume */ - { 18, 0x0000 }, /* R18 - GPIO CTRL 1 */ - { 19, 0x0010 }, /* R19 - GPIO1 */ - { 20, 0x0000 }, /* R20 - IRQ_DEBOUNCE */ - { 21, 0x0000 }, /* R21 - Inputs Clamp */ - { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */ - { 23, 0x0800 }, /* R23 - GPIO_POL */ - { 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */ - { 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */ - { 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */ - { 27, 0x008B }, /* R27 - Right Line Input 3&4 Volume */ - { 28, 0x006D }, /* R28 - Left Output Volume */ - { 29, 0x006D }, /* R29 - Right Output Volume */ - { 30, 0x0066 }, /* R30 - Line Outputs Volume */ - { 31, 0x0020 }, /* R31 - HPOUT2 Volume */ - { 32, 0x0079 }, /* R32 - Left OPGA Volume */ - { 33, 0x0079 }, /* R33 - Right OPGA Volume */ - { 34, 0x0003 }, /* R34 - SPKMIXL Attenuation */ - { 35, 0x0003 }, /* R35 - SPKMIXR Attenuation */ - { 36, 0x0011 }, /* R36 - SPKOUT Mixers */ - { 37, 0x0100 }, /* R37 - SPKOUT Boost */ - { 38, 0x0079 }, /* R38 - Speaker Volume Left */ - { 39, 0x0079 }, /* R39 - Speaker Volume Right */ - { 40, 0x0000 }, /* R40 - Input Mixer2 */ - { 41, 0x0000 }, /* R41 - Input Mixer3 */ - { 42, 0x0000 }, /* R42 - Input Mixer4 */ - { 43, 0x0000 }, /* R43 - Input Mixer5 */ - { 44, 0x0000 }, /* R44 - Input Mixer6 */ - { 45, 0x0000 }, /* R45 - Output Mixer1 */ - { 46, 0x0000 }, /* R46 - Output Mixer2 */ - { 47, 0x0000 }, /* R47 - Output Mixer3 */ - { 48, 0x0000 }, /* R48 - Output Mixer4 */ - { 49, 0x0000 }, /* R49 - Output Mixer5 */ - { 50, 0x0000 }, /* R50 - Output Mixer6 */ - { 51, 0x0000 }, /* R51 - HPOUT2 Mixer */ - { 52, 0x0000 }, /* R52 - Line Mixer1 */ - { 53, 0x0000 }, /* R53 - Line Mixer2 */ - { 54, 0x0000 }, /* R54 - Speaker Mixer */ - { 55, 0x0000 }, /* R55 - Additional Control */ - { 56, 0x0000 }, /* R56 - AntiPOP1 */ - { 57, 0x0000 }, /* R57 - AntiPOP2 */ - { 58, 0x0000 }, /* R58 - MICBIAS */ - { 60, 0x0000 }, /* R60 - FLL Control 1 */ - { 61, 0x0000 }, /* R61 - FLL Control 2 */ - { 62, 0x0000 }, /* R62 - FLL Control 3 */ - { 63, 0x2EE0 }, /* R63 - FLL Control 4 */ - { 64, 0x0002 }, /* R64 - FLL Control 5 */ - { 65, 0x2287 }, /* R65 - Clocking 3 */ - { 66, 0x025F }, /* R66 - Clocking 4 */ - { 67, 0x0000 }, /* R67 - MW Slave Control */ - { 69, 0x0002 }, /* R69 - Bus Control 1 */ - { 70, 0x0000 }, /* R70 - Write Sequencer 0 */ - { 71, 0x0000 }, /* R71 - Write Sequencer 1 */ - { 72, 0x0000 }, /* R72 - Write Sequencer 2 */ - { 73, 0x0000 }, /* R73 - Write Sequencer 3 */ - { 74, 0x0000 }, /* R74 - Write Sequencer 4 */ - { 75, 0x0000 }, /* R75 - Write Sequencer 5 */ - { 76, 0x1F25 }, /* R76 - Charge Pump 1 */ - { 81, 0x0000 }, /* R81 - Class W 0 */ - { 85, 0x054A }, /* R85 - DC Servo 1 */ - { 87, 0x0000 }, /* R87 - DC Servo 3 */ - { 96, 0x0100 }, /* R96 - Analogue HP 0 */ - { 98, 0x0000 }, /* R98 - EQ1 */ - { 99, 0x000C }, /* R99 - EQ2 */ - { 100, 0x000C }, /* R100 - EQ3 */ - { 101, 0x000C }, /* R101 - EQ4 */ - { 102, 0x000C }, /* R102 - EQ5 */ - { 103, 0x000C }, /* R103 - EQ6 */ - { 104, 0x0FCA }, /* R104 - EQ7 */ - { 105, 0x0400 }, /* R105 - EQ8 */ - { 106, 0x00D8 }, /* R106 - EQ9 */ - { 107, 0x1EB5 }, /* R107 - EQ10 */ - { 108, 0xF145 }, /* R108 - EQ11 */ - { 109, 0x0B75 }, /* R109 - EQ12 */ - { 110, 0x01C5 }, /* R110 - EQ13 */ - { 111, 0x1C58 }, /* R111 - EQ14 */ - { 112, 0xF373 }, /* R112 - EQ15 */ - { 113, 0x0A54 }, /* R113 - EQ16 */ - { 114, 0x0558 }, /* R114 - EQ17 */ - { 115, 0x168E }, /* R115 - EQ18 */ - { 116, 0xF829 }, /* R116 - EQ19 */ - { 117, 0x07AD }, /* R117 - EQ20 */ - { 118, 0x1103 }, /* R118 - EQ21 */ - { 119, 0x0564 }, /* R119 - EQ22 */ - { 120, 0x0559 }, /* R120 - EQ23 */ - { 121, 0x4000 }, /* R121 - EQ24 */ - { 122, 0x0000 }, /* R122 - Digital Pulls */ - { 123, 0x0F08 }, /* R123 - DRC Control 1 */ - { 124, 0x0000 }, /* R124 - DRC Control 2 */ - { 125, 0x0080 }, /* R125 - DRC Control 3 */ - { 126, 0x0000 }, /* R126 - DRC Control 4 */ -}; - -static struct { - int ratio; - int clk_sys_rate; -} clk_sys_rates[] = { - { 64, 0 }, - { 128, 1 }, - { 192, 2 }, - { 256, 3 }, - { 384, 4 }, - { 512, 5 }, - { 768, 6 }, - { 1024, 7 }, - { 1408, 8 }, - { 1536, 9 }, -}; - -static struct { - int rate; - int sample_rate; -} sample_rates[] = { - { 8000, 0 }, - { 11025, 1 }, - { 12000, 1 }, - { 16000, 2 }, - { 22050, 3 }, - { 24000, 3 }, - { 32000, 4 }, - { 44100, 5 }, - { 48000, 5 }, -}; - -static struct { - int div; /* *10 due to .5s */ - int bclk_div; -} bclk_divs[] = { - { 10, 0 }, - { 15, 1 }, - { 20, 2 }, - { 30, 3 }, - { 40, 4 }, - { 55, 5 }, - { 60, 6 }, - { 80, 7 }, - { 110, 8 }, - { 120, 9 }, - { 160, 10 }, - { 220, 11 }, - { 240, 12 }, - { 320, 13 }, - { 440, 14 }, - { 480, 15 }, -}; - -struct wm8993_priv { - struct wm_hubs_data hubs_data; - struct device *dev; - struct regmap *regmap; - struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; - struct wm8993_platform_data pdata; - struct completion fll_lock; - int master; - int sysclk_source; - int tdm_slots; - int tdm_width; - unsigned int mclk_rate; - unsigned int sysclk_rate; - unsigned int fs; - unsigned int bclk; - int class_w_users; - unsigned int fll_fref; - unsigned int fll_fout; - int fll_src; -}; - -static bool wm8993_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8993_SOFTWARE_RESET: - case WM8993_GPIO_CTRL_1: - case WM8993_DC_SERVO_0: - case WM8993_DC_SERVO_READBACK_0: - case WM8993_DC_SERVO_READBACK_1: - case WM8993_DC_SERVO_READBACK_2: - return true; - default: - return false; - } -} - -static bool wm8993_readable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8993_SOFTWARE_RESET: - case WM8993_POWER_MANAGEMENT_1: - case WM8993_POWER_MANAGEMENT_2: - case WM8993_POWER_MANAGEMENT_3: - case WM8993_AUDIO_INTERFACE_1: - case WM8993_AUDIO_INTERFACE_2: - case WM8993_CLOCKING_1: - case WM8993_CLOCKING_2: - case WM8993_AUDIO_INTERFACE_3: - case WM8993_AUDIO_INTERFACE_4: - case WM8993_DAC_CTRL: - case WM8993_LEFT_DAC_DIGITAL_VOLUME: - case WM8993_RIGHT_DAC_DIGITAL_VOLUME: - case WM8993_DIGITAL_SIDE_TONE: - case WM8993_ADC_CTRL: - case WM8993_LEFT_ADC_DIGITAL_VOLUME: - case WM8993_RIGHT_ADC_DIGITAL_VOLUME: - case WM8993_GPIO_CTRL_1: - case WM8993_GPIO1: - case WM8993_IRQ_DEBOUNCE: - case WM8993_GPIOCTRL_2: - case WM8993_GPIO_POL: - case WM8993_LEFT_LINE_INPUT_1_2_VOLUME: - case WM8993_LEFT_LINE_INPUT_3_4_VOLUME: - case WM8993_RIGHT_LINE_INPUT_1_2_VOLUME: - case WM8993_RIGHT_LINE_INPUT_3_4_VOLUME: - case WM8993_LEFT_OUTPUT_VOLUME: - case WM8993_RIGHT_OUTPUT_VOLUME: - case WM8993_LINE_OUTPUTS_VOLUME: - case WM8993_HPOUT2_VOLUME: - case WM8993_LEFT_OPGA_VOLUME: - case WM8993_RIGHT_OPGA_VOLUME: - case WM8993_SPKMIXL_ATTENUATION: - case WM8993_SPKMIXR_ATTENUATION: - case WM8993_SPKOUT_MIXERS: - case WM8993_SPKOUT_BOOST: - case WM8993_SPEAKER_VOLUME_LEFT: - case WM8993_SPEAKER_VOLUME_RIGHT: - case WM8993_INPUT_MIXER2: - case WM8993_INPUT_MIXER3: - case WM8993_INPUT_MIXER4: - case WM8993_INPUT_MIXER5: - case WM8993_INPUT_MIXER6: - case WM8993_OUTPUT_MIXER1: - case WM8993_OUTPUT_MIXER2: - case WM8993_OUTPUT_MIXER3: - case WM8993_OUTPUT_MIXER4: - case WM8993_OUTPUT_MIXER5: - case WM8993_OUTPUT_MIXER6: - case WM8993_HPOUT2_MIXER: - case WM8993_LINE_MIXER1: - case WM8993_LINE_MIXER2: - case WM8993_SPEAKER_MIXER: - case WM8993_ADDITIONAL_CONTROL: - case WM8993_ANTIPOP1: - case WM8993_ANTIPOP2: - case WM8993_MICBIAS: - case WM8993_FLL_CONTROL_1: - case WM8993_FLL_CONTROL_2: - case WM8993_FLL_CONTROL_3: - case WM8993_FLL_CONTROL_4: - case WM8993_FLL_CONTROL_5: - case WM8993_CLOCKING_3: - case WM8993_CLOCKING_4: - case WM8993_MW_SLAVE_CONTROL: - case WM8993_BUS_CONTROL_1: - case WM8993_WRITE_SEQUENCER_0: - case WM8993_WRITE_SEQUENCER_1: - case WM8993_WRITE_SEQUENCER_2: - case WM8993_WRITE_SEQUENCER_3: - case WM8993_WRITE_SEQUENCER_4: - case WM8993_WRITE_SEQUENCER_5: - case WM8993_CHARGE_PUMP_1: - case WM8993_CLASS_W_0: - case WM8993_DC_SERVO_0: - case WM8993_DC_SERVO_1: - case WM8993_DC_SERVO_3: - case WM8993_DC_SERVO_READBACK_0: - case WM8993_DC_SERVO_READBACK_1: - case WM8993_DC_SERVO_READBACK_2: - case WM8993_ANALOGUE_HP_0: - case WM8993_EQ1: - case WM8993_EQ2: - case WM8993_EQ3: - case WM8993_EQ4: - case WM8993_EQ5: - case WM8993_EQ6: - case WM8993_EQ7: - case WM8993_EQ8: - case WM8993_EQ9: - case WM8993_EQ10: - case WM8993_EQ11: - case WM8993_EQ12: - case WM8993_EQ13: - case WM8993_EQ14: - case WM8993_EQ15: - case WM8993_EQ16: - case WM8993_EQ17: - case WM8993_EQ18: - case WM8993_EQ19: - case WM8993_EQ20: - case WM8993_EQ21: - case WM8993_EQ22: - case WM8993_EQ23: - case WM8993_EQ24: - case WM8993_DIGITAL_PULLS: - case WM8993_DRC_CONTROL_1: - case WM8993_DRC_CONTROL_2: - case WM8993_DRC_CONTROL_3: - case WM8993_DRC_CONTROL_4: - return true; - default: - return false; - } -} - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_clk_ref_div; - u16 n; - u16 k; -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod, target; - unsigned int div; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - fll_div->fll_clk_ref_div = 0; - while ((Fref / div) > 13500000) { - div *= 2; - fll_div->fll_clk_ref_div++; - - if (div > 8) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - - pr_debug("Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 0; - target = Fout * 2; - while (target < 90000000) { - div++; - target *= 2; - if (div > 7) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - fll_div->fll_outdiv = div; - - pr_debug("Fvco=%dHz\n", target); - - /* Find an appropriate FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - target /= fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - /* Now, calculate N.K */ - Ndiv = target / Fref; - - fll_div->n = Ndiv; - Nmod = target % Fref; - pr_debug("Nmod=%d\n", Nmod); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, Fref); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - fll_div->k = K / 10; - - pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n", - fll_div->n, fll_div->k, - fll_div->fll_fratio, fll_div->fll_outdiv, - fll_div->fll_clk_ref_div); - - return 0; -} - -static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source, - unsigned int Fref, unsigned int Fout) -{ - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c = to_i2c_client(codec->dev); - u16 reg1, reg4, reg5; - struct _fll_div fll_div; - unsigned int timeout; - int ret; - - /* Any change? */ - if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout) - return 0; - - /* Disable the FLL */ - if (Fout == 0) { - dev_dbg(codec->dev, "FLL disabled\n"); - wm8993->fll_fref = 0; - wm8993->fll_fout = 0; - - reg1 = snd_soc_read(codec, WM8993_FLL_CONTROL_1); - reg1 &= ~WM8993_FLL_ENA; - snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); - - return 0; - } - - ret = fll_factors(&fll_div, Fref, Fout); - if (ret != 0) - return ret; - - reg5 = snd_soc_read(codec, WM8993_FLL_CONTROL_5); - reg5 &= ~WM8993_FLL_CLK_SRC_MASK; - - switch (fll_id) { - case WM8993_FLL_MCLK: - break; - - case WM8993_FLL_LRCLK: - reg5 |= 1; - break; - - case WM8993_FLL_BCLK: - reg5 |= 2; - break; - - default: - dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); - return -EINVAL; - } - - /* Any FLL configuration change requires that the FLL be - * disabled first. */ - reg1 = snd_soc_read(codec, WM8993_FLL_CONTROL_1); - reg1 &= ~WM8993_FLL_ENA; - snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); - - /* Apply the configuration */ - if (fll_div.k) - reg1 |= WM8993_FLL_FRAC_MASK; - else - reg1 &= ~WM8993_FLL_FRAC_MASK; - snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); - - snd_soc_write(codec, WM8993_FLL_CONTROL_2, - (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) | - (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); - snd_soc_write(codec, WM8993_FLL_CONTROL_3, fll_div.k); - - reg4 = snd_soc_read(codec, WM8993_FLL_CONTROL_4); - reg4 &= ~WM8993_FLL_N_MASK; - reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; - snd_soc_write(codec, WM8993_FLL_CONTROL_4, reg4); - - reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK; - reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT; - snd_soc_write(codec, WM8993_FLL_CONTROL_5, reg5); - - /* If we've got an interrupt wired up make sure we get it */ - if (i2c->irq) - timeout = msecs_to_jiffies(20); - else if (Fref < 1000000) - timeout = msecs_to_jiffies(3); - else - timeout = msecs_to_jiffies(1); - - try_wait_for_completion(&wm8993->fll_lock); - - /* Enable the FLL */ - snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA); - - timeout = wait_for_completion_timeout(&wm8993->fll_lock, timeout); - if (i2c->irq && !timeout) - dev_warn(codec->dev, "Timed out waiting for FLL\n"); - - dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); - - wm8993->fll_fref = Fref; - wm8993->fll_fout = Fout; - wm8993->fll_src = source; - - return 0; -} - -static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, - unsigned int Fref, unsigned int Fout) -{ - return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout); -} - -static int configure_clock(struct snd_soc_codec *codec) -{ - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - unsigned int reg; - - /* This should be done on init() for bypass paths */ - switch (wm8993->sysclk_source) { - case WM8993_SYSCLK_MCLK: - dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate); - - reg = snd_soc_read(codec, WM8993_CLOCKING_2); - reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC); - if (wm8993->mclk_rate > 13500000) { - reg |= WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->mclk_rate / 2; - } else { - reg &= ~WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->mclk_rate; - } - snd_soc_write(codec, WM8993_CLOCKING_2, reg); - break; - - case WM8993_SYSCLK_FLL: - dev_dbg(codec->dev, "Using %dHz FLL clock\n", - wm8993->fll_fout); - - reg = snd_soc_read(codec, WM8993_CLOCKING_2); - reg |= WM8993_SYSCLK_SRC; - if (wm8993->fll_fout > 13500000) { - reg |= WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->fll_fout / 2; - } else { - reg &= ~WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->fll_fout; - } - snd_soc_write(codec, WM8993_CLOCKING_2, reg); - break; - - default: - dev_err(codec->dev, "System clock not configured\n"); - return -EINVAL; - } - - dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8993->sysclk_rate); - - return 0; -} - -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); -static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); -static const unsigned int drc_max_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), - 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); - -static const char *dac_deemph_text[] = { - "None", - "32kHz", - "44.1kHz", - "48kHz", -}; - -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text); - -static const char *adc_hpf_text[] = { - "Hi-Fi", - "Voice 1", - "Voice 2", - "Voice 3", -}; - -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text); - -static const char *drc_path_text[] = { - "ADC", - "DAC" -}; - -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text); - -static const char *drc_r0_text[] = { - "1", - "1/2", - "1/4", - "1/8", - "1/16", - "0", -}; - -static const struct soc_enum drc_r0 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text); - -static const char *drc_r1_text[] = { - "1", - "1/2", - "1/4", - "1/8", - "0", -}; - -static const struct soc_enum drc_r1 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text); - -static const char *drc_attack_text[] = { - "Reserved", - "181us", - "363us", - "726us", - "1.45ms", - "2.9ms", - "5.8ms", - "11.6ms", - "23.2ms", - "46.4ms", - "92.8ms", - "185.6ms", -}; - -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text); - -static const char *drc_decay_text[] = { - "186ms", - "372ms", - "743ms", - "1.49s", - "2.97ms", - "5.94ms", - "11.89ms", - "23.78ms", - "47.56ms", -}; - -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text); - -static const char *drc_ff_text[] = { - "5 samples", - "9 samples", -}; - -static const struct soc_enum drc_ff = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text); - -static const char *drc_qr_rate_text[] = { - "0.725ms", - "1.45ms", - "5.8ms", -}; - -static const struct soc_enum drc_qr_rate = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text); - -static const char *drc_smooth_text[] = { - "Low", - "Medium", - "High", -}; - -static const struct soc_enum drc_smooth = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text); - -static const struct snd_kcontrol_new wm8993_snd_controls[] = { -SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, - 5, 9, 12, 0, sidetone_tlv), - -SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0), -SOC_ENUM("DRC Path", drc_path), -SOC_SINGLE_TLV("DRC Compressor Threshold Volume", WM8993_DRC_CONTROL_2, - 2, 60, 1, drc_comp_threash), -SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3, - 11, 30, 1, drc_comp_amp), -SOC_ENUM("DRC R0", drc_r0), -SOC_ENUM("DRC R1", drc_r1), -SOC_SINGLE_TLV("DRC Minimum Volume", WM8993_DRC_CONTROL_1, 2, 3, 1, - drc_min_tlv), -SOC_SINGLE_TLV("DRC Maximum Volume", WM8993_DRC_CONTROL_1, 0, 3, 0, - drc_max_tlv), -SOC_ENUM("DRC Attack Rate", drc_attack), -SOC_ENUM("DRC Decay Rate", drc_decay), -SOC_ENUM("DRC FF Delay", drc_ff), -SOC_SINGLE("DRC Anti-clip Switch", WM8993_DRC_CONTROL_1, 9, 1, 0), -SOC_SINGLE("DRC Quick Release Switch", WM8993_DRC_CONTROL_1, 10, 1, 0), -SOC_SINGLE_TLV("DRC Quick Release Volume", WM8993_DRC_CONTROL_3, 2, 3, 0, - drc_qr_tlv), -SOC_ENUM("DRC Quick Release Rate", drc_qr_rate), -SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0), -SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0), -SOC_ENUM("DRC Smoothing Hysteresis Threshold", drc_smooth), -SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0, - drc_startup_tlv), - -SOC_SINGLE("EQ Switch", WM8993_EQ1, 0, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8993_LEFT_ADC_DIGITAL_VOLUME, - WM8993_RIGHT_ADC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv), -SOC_SINGLE("ADC High Pass Filter Switch", WM8993_ADC_CTRL, 8, 1, 0), -SOC_ENUM("ADC High Pass Filter Mode", adc_hpf), - -SOC_DOUBLE_R_TLV("Playback Volume", WM8993_LEFT_DAC_DIGITAL_VOLUME, - WM8993_RIGHT_DAC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv), -SOC_SINGLE_TLV("Playback Boost Volume", WM8993_AUDIO_INTERFACE_2, 10, 3, 0, - dac_boost_tlv), -SOC_ENUM("DAC Deemphasis", dac_deemph), - -SOC_SINGLE_TLV("SPKL DAC Volume", WM8993_SPKMIXL_ATTENUATION, - 2, 1, 1, wm_hubs_spkmix_tlv), - -SOC_SINGLE_TLV("SPKR DAC Volume", WM8993_SPKMIXR_ATTENUATION, - 2, 1, 1, wm_hubs_spkmix_tlv), -}; - -static const struct snd_kcontrol_new wm8993_eq_controls[] = { -SOC_SINGLE_TLV("EQ1 Volume", WM8993_EQ2, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Volume", WM8993_EQ3, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Volume", WM8993_EQ4, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Volume", WM8993_EQ5, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv), -}; - -static int clk_sys_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - return configure_clock(codec); - - case SND_SOC_DAPM_POST_PMD: - break; - } - - return 0; -} - -/* - * When used with DAC outputs only the WM8993 charge pump supports - * operation in class W mode, providing very low power consumption - * when used with digital sources. Enable and disable this mode - * automatically depending on the mixer configuration. - * - * Currently the only supported paths are the direct DAC->headphone - * paths (which provide minimum power consumption anyway). - */ -static int class_w_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct snd_soc_codec *codec = widget->codec; - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - int ret; - - /* Turn it off if we're using the main output mixer */ - if (ucontrol->value.integer.value[0] == 0) { - if (wm8993->class_w_users == 0) { - dev_dbg(codec->dev, "Disabling Class W\n"); - snd_soc_update_bits(codec, WM8993_CLASS_W_0, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V, - 0); - } - wm8993->class_w_users++; - wm8993->hubs_data.class_w = true; - } - - /* Implement the change */ - ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); - - /* Enable it if we're using the direct DAC path */ - if (ucontrol->value.integer.value[0] == 1) { - if (wm8993->class_w_users == 1) { - dev_dbg(codec->dev, "Enabling Class W\n"); - snd_soc_update_bits(codec, WM8993_CLASS_W_0, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V); - } - wm8993->class_w_users--; - wm8993->hubs_data.class_w = false; - } - - dev_dbg(codec->dev, "Indirect DAC use count now %d\n", - wm8993->class_w_users); - - return ret; -} - -#define SOC_DAPM_ENUM_W(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_double, \ - .put = class_w_put, \ - .private_value = (unsigned long)&xenum } - -static const char *hp_mux_text[] = { - "Mixer", - "DAC", -}; - -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpl_mux = - SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum); - -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpr_mux = - SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum); - -static const struct snd_kcontrol_new left_speaker_mixer[] = { -SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0), -SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 3, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 6, 1, 0), -}; - -static const struct snd_kcontrol_new right_speaker_mixer[] = { -SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 6, 1, 0), -SOC_DAPM_SINGLE("IN1RP Switch", WM8993_SPEAKER_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0), -}; - -static const char *aif_text[] = { - "Left", "Right" -}; - -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); - -static const struct snd_kcontrol_new aifoutl_mux = - SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); - -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); - -static const struct snd_kcontrol_new aifoutr_mux = - SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); - -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); - -static const struct snd_kcontrol_new aifinl_mux = - SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); - -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); - -static const struct snd_kcontrol_new aifinr_mux = - SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); - -static const char *sidetone_text[] = { - "None", "Left", "Right" -}; - -static const struct soc_enum sidetonel_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); - -static const struct snd_kcontrol_new sidetonel_mux = - SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); - -static const struct soc_enum sidetoner_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); - -static const struct snd_kcontrol_new sidetoner_mux = - SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); - -static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = { -SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), -SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), - -SND_SOC_DAPM_MUX("AIFOUTL Mux", SND_SOC_NOPM, 0, 0, &aifoutl_mux), -SND_SOC_DAPM_MUX("AIFOUTR Mux", SND_SOC_NOPM, 0, 0, &aifoutr_mux), - -SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &aifinl_mux), -SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &aifinr_mux), - -SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &sidetonel_mux), -SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux), - -SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0), -SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0), - -SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), -SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), - -SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0, - left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), -SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0, - right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), -SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_route routes[] = { - { "MICBIAS1", NULL, "VMID" }, - { "MICBIAS2", NULL, "VMID" }, - - { "ADCL", NULL, "CLK_SYS" }, - { "ADCL", NULL, "CLK_DSP" }, - { "ADCR", NULL, "CLK_SYS" }, - { "ADCR", NULL, "CLK_DSP" }, - - { "AIFOUTL Mux", "Left", "ADCL" }, - { "AIFOUTL Mux", "Right", "ADCR" }, - { "AIFOUTR Mux", "Left", "ADCL" }, - { "AIFOUTR Mux", "Right", "ADCR" }, - - { "AIFOUTL", NULL, "AIFOUTL Mux" }, - { "AIFOUTR", NULL, "AIFOUTR Mux" }, - - { "DACL Mux", "Left", "AIFINL" }, - { "DACL Mux", "Right", "AIFINR" }, - { "DACR Mux", "Left", "AIFINL" }, - { "DACR Mux", "Right", "AIFINR" }, - - { "DACL Sidetone", "Left", "ADCL" }, - { "DACL Sidetone", "Right", "ADCR" }, - { "DACR Sidetone", "Left", "ADCL" }, - { "DACR Sidetone", "Right", "ADCR" }, - - { "DACL", NULL, "CLK_SYS" }, - { "DACL", NULL, "CLK_DSP" }, - { "DACL", NULL, "DACL Mux" }, - { "DACL", NULL, "DACL Sidetone" }, - { "DACR", NULL, "CLK_SYS" }, - { "DACR", NULL, "CLK_DSP" }, - { "DACR", NULL, "DACR Mux" }, - { "DACR", NULL, "DACR Sidetone" }, - - { "Left Output Mixer", "DAC Switch", "DACL" }, - - { "Right Output Mixer", "DAC Switch", "DACR" }, - - { "Left Output PGA", NULL, "CLK_SYS" }, - - { "Right Output PGA", NULL, "CLK_SYS" }, - - { "SPKL", "DAC Switch", "DACL" }, - { "SPKL", NULL, "CLK_SYS" }, - - { "SPKR", "DAC Switch", "DACR" }, - { "SPKR", NULL, "CLK_SYS" }, - - { "Left Headphone Mux", "DAC", "DACL" }, - { "Right Headphone Mux", "DAC", "DACR" }, -}; - -static int wm8993_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - int ret; - - wm_hubs_set_bias_level(codec, level); - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - /* VMID=2*40k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK, 0x2); - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2, - WM8993_TSHUT_ENA, WM8993_TSHUT_ENA); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), - wm8993->supplies); - if (ret != 0) - return ret; - - regcache_cache_only(wm8993->regmap, false); - regcache_sync(wm8993->regmap); - - wm_hubs_vmid_ena(codec); - - /* Bring up VMID with fast soft start */ - snd_soc_update_bits(codec, WM8993_ANTIPOP2, - WM8993_STARTUP_BIAS_ENA | - WM8993_VMID_BUF_ENA | - WM8993_VMID_RAMP_MASK | - WM8993_BIAS_SRC, - WM8993_STARTUP_BIAS_ENA | - WM8993_VMID_BUF_ENA | - WM8993_VMID_RAMP_MASK | - WM8993_BIAS_SRC); - - /* If either line output is single ended we - * need the VMID buffer */ - if (!wm8993->pdata.lineout1_diff || - !wm8993->pdata.lineout2_diff) - snd_soc_update_bits(codec, WM8993_ANTIPOP1, - WM8993_LINEOUT_VMID_BUF_ENA, - WM8993_LINEOUT_VMID_BUF_ENA); - - /* VMID=2*40k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK | - WM8993_BIAS_ENA, - WM8993_BIAS_ENA | 0x2); - msleep(32); - - /* Switch to normal bias */ - snd_soc_update_bits(codec, WM8993_ANTIPOP2, - WM8993_BIAS_SRC | - WM8993_STARTUP_BIAS_ENA, 0); - } - - /* VMID=2*240k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK, 0x4); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2, - WM8993_TSHUT_ENA, 0); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8993_ANTIPOP1, - WM8993_LINEOUT_VMID_BUF_ENA, 0); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA, - 0); - - snd_soc_update_bits(codec, WM8993_ANTIPOP2, - WM8993_STARTUP_BIAS_ENA | - WM8993_VMID_BUF_ENA | - WM8993_VMID_RAMP_MASK | - WM8993_BIAS_SRC, 0); - - regcache_cache_only(wm8993->regmap, true); - regcache_mark_dirty(wm8993->regmap); - - regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), - wm8993->supplies); - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case WM8993_SYSCLK_MCLK: - wm8993->mclk_rate = freq; - case WM8993_SYSCLK_FLL: - wm8993->sysclk_source = clk_id; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - unsigned int aif1 = snd_soc_read(codec, WM8993_AUDIO_INTERFACE_1); - unsigned int aif4 = snd_soc_read(codec, WM8993_AUDIO_INTERFACE_4); - - aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV | - WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK); - aif4 &= ~WM8993_LRCLK_DIR; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - wm8993->master = 0; - break; - case SND_SOC_DAIFMT_CBS_CFM: - aif4 |= WM8993_LRCLK_DIR; - wm8993->master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFS: - aif1 |= WM8993_BCLK_DIR; - wm8993->master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - aif1 |= WM8993_BCLK_DIR; - aif4 |= WM8993_LRCLK_DIR; - wm8993->master = 1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif1 |= WM8993_AIF_LRCLK_INV; - case SND_SOC_DAIFMT_DSP_A: - aif1 |= 0x18; - break; - case SND_SOC_DAIFMT_I2S: - aif1 |= 0x10; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif1 |= 0x8; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8993_AIF_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif1 |= WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8993_AIF_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif1 |= WM8993_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); - snd_soc_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); - - return 0; -} - -static int wm8993_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - int ret, i, best, best_val, cur_val; - unsigned int clocking1, clocking3, aif1, aif4; - - clocking1 = snd_soc_read(codec, WM8993_CLOCKING_1); - clocking1 &= ~WM8993_BCLK_DIV_MASK; - - clocking3 = snd_soc_read(codec, WM8993_CLOCKING_3); - clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK); - - aif1 = snd_soc_read(codec, WM8993_AUDIO_INTERFACE_1); - aif1 &= ~WM8993_AIF_WL_MASK; - - aif4 = snd_soc_read(codec, WM8993_AUDIO_INTERFACE_4); - aif4 &= ~WM8993_LRCLK_RATE_MASK; - - /* What BCLK do we need? */ - wm8993->fs = params_rate(params); - wm8993->bclk = 2 * wm8993->fs; - if (wm8993->tdm_slots) { - dev_dbg(codec->dev, "Configuring for %d %d bit TDM slots\n", - wm8993->tdm_slots, wm8993->tdm_width); - wm8993->bclk *= wm8993->tdm_width * wm8993->tdm_slots; - } else { - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - wm8993->bclk *= 16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - wm8993->bclk *= 20; - aif1 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S24_LE: - wm8993->bclk *= 24; - aif1 |= 0x10; - break; - case SNDRV_PCM_FORMAT_S32_LE: - wm8993->bclk *= 32; - aif1 |= 0x18; - break; - default: - return -EINVAL; - } - } - - dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8993->bclk); - - ret = configure_clock(codec); - if (ret != 0) - return ret; - - /* Select nearest CLK_SYS_RATE */ - best = 0; - best_val = abs((wm8993->sysclk_rate / clk_sys_rates[0].ratio) - - wm8993->fs); - for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) { - cur_val = abs((wm8993->sysclk_rate / - clk_sys_rates[i].ratio) - wm8993->fs); - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n", - clk_sys_rates[best].ratio); - clocking3 |= (clk_sys_rates[best].clk_sys_rate - << WM8993_CLK_SYS_RATE_SHIFT); - - /* SAMPLE_RATE */ - best = 0; - best_val = abs(wm8993->fs - sample_rates[0].rate); - for (i = 1; i < ARRAY_SIZE(sample_rates); i++) { - /* Closest match */ - cur_val = abs(wm8993->fs - sample_rates[i].rate); - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n", - sample_rates[best].rate); - clocking3 |= (sample_rates[best].sample_rate - << WM8993_SAMPLE_RATE_SHIFT); - - /* BCLK_DIV */ - best = 0; - best_val = INT_MAX; - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - cur_val = ((wm8993->sysclk_rate * 10) / bclk_divs[i].div) - - wm8993->bclk; - if (cur_val < 0) /* Table is sorted */ - break; - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - wm8993->bclk = (wm8993->sysclk_rate * 10) / bclk_divs[best].div; - dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n", - bclk_divs[best].div, wm8993->bclk); - clocking1 |= bclk_divs[best].bclk_div << WM8993_BCLK_DIV_SHIFT; - - /* LRCLK is a simple fraction of BCLK */ - dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs); - aif4 |= wm8993->bclk / wm8993->fs; - - snd_soc_write(codec, WM8993_CLOCKING_1, clocking1); - snd_soc_write(codec, WM8993_CLOCKING_3, clocking3); - snd_soc_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); - snd_soc_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); - - /* ReTune Mobile? */ - if (wm8993->pdata.num_retune_configs) { - u16 eq1 = snd_soc_read(codec, WM8993_EQ1); - struct wm8993_retune_mobile_setting *s; - - best = 0; - best_val = abs(wm8993->pdata.retune_configs[0].rate - - wm8993->fs); - for (i = 0; i < wm8993->pdata.num_retune_configs; i++) { - cur_val = abs(wm8993->pdata.retune_configs[i].rate - - wm8993->fs); - if (cur_val < best_val) { - best_val = cur_val; - best = i; - } - } - s = &wm8993->pdata.retune_configs[best]; - - dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", - s->name, s->rate); - - /* Disable EQ while we reconfigure */ - snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0); - - for (i = 1; i < ARRAY_SIZE(s->config); i++) - snd_soc_write(codec, WM8993_EQ1 + i, s->config[i]); - - snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1); - } - - return 0; -} - -static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - unsigned int reg; - - reg = snd_soc_read(codec, WM8993_DAC_CTRL); - - if (mute) - reg |= WM8993_DAC_MUTE; - else - reg &= ~WM8993_DAC_MUTE; - - snd_soc_write(codec, WM8993_DAC_CTRL, reg); - - return 0; -} - -static int wm8993_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, - unsigned int rx_mask, int slots, int slot_width) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - int aif1 = 0; - int aif2 = 0; - - /* Don't need to validate anything if we're turning off TDM */ - if (slots == 0) { - wm8993->tdm_slots = 0; - goto out; - } - - /* Note that we allow configurations we can't handle ourselves - - * for example, we can generate clocks for slots 2 and up even if - * we can't use those slots ourselves. - */ - aif1 |= WM8993_AIFADC_TDM; - aif2 |= WM8993_AIFDAC_TDM; - - switch (rx_mask) { - case 3: - break; - case 0xc: - aif1 |= WM8993_AIFADC_TDM_CHAN; - break; - default: - return -EINVAL; - } - - - switch (tx_mask) { - case 3: - break; - case 0xc: - aif2 |= WM8993_AIFDAC_TDM_CHAN; - break; - default: - return -EINVAL; - } - -out: - wm8993->tdm_width = slot_width; - wm8993->tdm_slots = slots / 2; - - snd_soc_update_bits(codec, WM8993_AUDIO_INTERFACE_1, - WM8993_AIFADC_TDM | WM8993_AIFADC_TDM_CHAN, aif1); - snd_soc_update_bits(codec, WM8993_AUDIO_INTERFACE_2, - WM8993_AIFDAC_TDM | WM8993_AIFDAC_TDM_CHAN, aif2); - - return 0; -} - -static irqreturn_t wm8993_irq(int irq, void *data) -{ - struct wm8993_priv *wm8993 = data; - int mask, val, ret; - - ret = regmap_read(wm8993->regmap, WM8993_GPIO_CTRL_1, &val); - if (ret != 0) { - dev_err(wm8993->dev, "Failed to read interrupt status: %d\n", - ret); - return IRQ_NONE; - } - - ret = regmap_read(wm8993->regmap, WM8993_GPIOCTRL_2, &mask); - if (ret != 0) { - dev_err(wm8993->dev, "Failed to read interrupt mask: %d\n", - ret); - return IRQ_NONE; - } - - /* The IRQ pin status is visible in the register too */ - val &= ~(mask | WM8993_IRQ); - if (!val) - return IRQ_NONE; - - if (val & WM8993_TEMPOK_EINT) - dev_crit(wm8993->dev, "Thermal warning\n"); - - if (val & WM8993_FLL_LOCK_EINT) { - dev_dbg(wm8993->dev, "FLL locked\n"); - complete(&wm8993->fll_lock); - } - - ret = regmap_write(wm8993->regmap, WM8993_GPIO_CTRL_1, val); - if (ret != 0) - dev_err(wm8993->dev, "Failed to ack interrupt: %d\n", ret); - - return IRQ_HANDLED; -} - -static const struct snd_soc_dai_ops wm8993_ops = { - .set_sysclk = wm8993_set_sysclk, - .set_fmt = wm8993_set_dai_fmt, - .hw_params = wm8993_hw_params, - .digital_mute = wm8993_digital_mute, - .set_pll = wm8993_set_fll, - .set_tdm_slot = wm8993_set_tdm_slot, -}; - -#define WM8993_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM8993_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_driver wm8993_dai = { - .name = "wm8993-hifi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8993_RATES, - .formats = WM8993_FORMATS, - .sig_bits = 24, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8993_RATES, - .formats = WM8993_FORMATS, - .sig_bits = 24, - }, - .ops = &wm8993_ops, - .symmetric_rates = 1, -}; - -static int wm8993_probe(struct snd_soc_codec *codec) -{ - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - wm8993->hubs_data.hp_startup_mode = 1; - wm8993->hubs_data.dcs_codes_l = -2; - wm8993->hubs_data.dcs_codes_r = -2; - wm8993->hubs_data.series_startup = 1; - - codec->control_data = wm8993->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* By default we're using the output mixers */ - wm8993->class_w_users = 2; - - /* Latch volume update bits and default ZC on */ - snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, - WM8993_DAC_VU, WM8993_DAC_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, - WM8993_ADC_VU, WM8993_ADC_VU); - - /* Manualy manage the HPOUT sequencing for independent stereo - * control. */ - snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, - WM8993_HPOUT1_AUTO_PU, 0); - - /* Use automatic clock configuration */ - snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); - - wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff, - wm8993->pdata.lineout2_diff, - wm8993->pdata.lineout1fb, - wm8993->pdata.lineout2fb, - wm8993->pdata.jd_scthr, - wm8993->pdata.jd_thr, - wm8993->pdata.micbias1_lvl, - wm8993->pdata.micbias2_lvl); - - ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - if (ret != 0) - return ret; - - snd_soc_add_codec_controls(codec, wm8993_snd_controls, - ARRAY_SIZE(wm8993_snd_controls)); - if (wm8993->pdata.num_retune_configs != 0) { - dev_dbg(codec->dev, "Using ReTune Mobile\n"); - } else { - dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n"); - snd_soc_add_codec_controls(codec, wm8993_eq_controls, - ARRAY_SIZE(wm8993_eq_controls)); - } - - snd_soc_dapm_new_controls(dapm, wm8993_dapm_widgets, - ARRAY_SIZE(wm8993_dapm_widgets)); - wm_hubs_add_analogue_controls(codec); - - snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes)); - wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, - wm8993->pdata.lineout2_diff); - - /* If the line outputs are differential then we aren't presenting - * VMID as an output and can disable it. - */ - if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff) - codec->dapm.idle_bias_off = 1; - - return 0; - -} - -static int wm8993_remove(struct snd_soc_codec *codec) -{ - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); - return 0; -} - -#ifdef CONFIG_PM -static int wm8993_suspend(struct snd_soc_codec *codec) -{ - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - int fll_fout = wm8993->fll_fout; - int fll_fref = wm8993->fll_fref; - int ret; - - /* Stop the FLL in an orderly fashion */ - ret = _wm8993_set_fll(codec, 0, 0, 0, 0); - if (ret != 0) { - dev_err(codec->dev, "Failed to stop FLL\n"); - return ret; - } - - wm8993->fll_fout = fll_fout; - wm8993->fll_fref = fll_fref; - - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8993_resume(struct snd_soc_codec *codec) -{ - struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); - int ret; - - wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Restart the FLL? */ - if (wm8993->fll_fout) { - int fll_fout = wm8993->fll_fout; - int fll_fref = wm8993->fll_fref; - - wm8993->fll_fref = 0; - wm8993->fll_fout = 0; - - ret = _wm8993_set_fll(codec, 0, wm8993->fll_src, - fll_fref, fll_fout); - if (ret != 0) - dev_err(codec->dev, "Failed to restart FLL\n"); - } - - return 0; -} -#else -#define wm8993_suspend NULL -#define wm8993_resume NULL -#endif - -/* Tune DC servo configuration */ -static struct reg_default wm8993_regmap_patch[] = { - { 0x44, 3 }, - { 0x56, 3 }, - { 0x44, 0 }, -}; - -static const struct regmap_config wm8993_regmap = { - .reg_bits = 8, - .val_bits = 16, - - .max_register = WM8993_MAX_REGISTER, - .volatile_reg = wm8993_volatile, - .readable_reg = wm8993_readable, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm8993_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8993_reg_defaults), -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm8993 = { - .probe = wm8993_probe, - .remove = wm8993_remove, - .suspend = wm8993_suspend, - .resume = wm8993_resume, - .set_bias_level = wm8993_set_bias_level, -}; - -static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8993_priv *wm8993; - unsigned int reg; - int ret, i; - - wm8993 = devm_kzalloc(&i2c->dev, sizeof(struct wm8993_priv), - GFP_KERNEL); - if (wm8993 == NULL) - return -ENOMEM; - - wm8993->dev = &i2c->dev; - init_completion(&wm8993->fll_lock); - - wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap); - if (IS_ERR(wm8993->regmap)) { - ret = PTR_ERR(wm8993->regmap); - dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); - return ret; - } - - i2c_set_clientdata(i2c, wm8993); - - for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) - wm8993->supplies[i].supply = wm8993_supply_names[i]; - - ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies), - wm8993->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), - wm8993->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, ®); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); - goto err_enable; - } - - if (reg != 0x8993) { - dev_err(&i2c->dev, "Invalid ID register value %x\n", reg); - ret = -EINVAL; - goto err_enable; - } - - ret = regmap_write(wm8993->regmap, WM8993_SOFTWARE_RESET, 0xffff); - if (ret != 0) - goto err_enable; - - ret = regmap_register_patch(wm8993->regmap, wm8993_regmap_patch, - ARRAY_SIZE(wm8993_regmap_patch)); - if (ret != 0) - dev_warn(wm8993->dev, "Failed to apply regmap patch: %d\n", - ret); - - if (i2c->irq) { - /* Put GPIO1 into interrupt mode (only GPIO1 can output IRQ) */ - ret = regmap_update_bits(wm8993->regmap, WM8993_GPIO1, - WM8993_GPIO1_PD | - WM8993_GPIO1_SEL_MASK, 7); - if (ret != 0) - goto err_enable; - - ret = request_threaded_irq(i2c->irq, NULL, wm8993_irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "wm8993", wm8993); - if (ret != 0) - goto err_enable; - - } - - regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); - - regcache_cache_only(wm8993->regmap, true); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8993, &wm8993_dai, 1); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - goto err_irq; - } - - return 0; - -err_irq: - if (i2c->irq) - free_irq(i2c->irq, wm8993); -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); -err: - regmap_exit(wm8993->regmap); - return ret; -} - -static __devexit int wm8993_i2c_remove(struct i2c_client *i2c) -{ - struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c); - - snd_soc_unregister_codec(&i2c->dev); - if (i2c->irq) - free_irq(i2c->irq, wm8993); - regmap_exit(wm8993->regmap); - regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); - - return 0; -} - -static const struct i2c_device_id wm8993_i2c_id[] = { - { "wm8993", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); - -static struct i2c_driver wm8993_i2c_driver = { - .driver = { - .name = "wm8993", - .owner = THIS_MODULE, - }, - .probe = wm8993_i2c_probe, - .remove = __devexit_p(wm8993_i2c_remove), - .id_table = wm8993_i2c_id, -}; - -module_i2c_driver(wm8993_i2c_driver); - -MODULE_DESCRIPTION("ASoC WM8993 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8993.h b/ANDROID_3.4.5/sound/soc/codecs/wm8993.h deleted file mode 100644 index 4478b40c..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8993.h +++ /dev/null @@ -1,2138 +0,0 @@ -#ifndef WM8993_H -#define WM8993_H - -#define WM8993_SYSCLK_MCLK 1 -#define WM8993_SYSCLK_FLL 2 - -#define WM8993_FLL_MCLK 1 -#define WM8993_FLL_BCLK 2 -#define WM8993_FLL_LRCLK 3 - -/* - * Register values. - */ -#define WM8993_SOFTWARE_RESET 0x00 -#define WM8993_POWER_MANAGEMENT_1 0x01 -#define WM8993_POWER_MANAGEMENT_2 0x02 -#define WM8993_POWER_MANAGEMENT_3 0x03 -#define WM8993_AUDIO_INTERFACE_1 0x04 -#define WM8993_AUDIO_INTERFACE_2 0x05 -#define WM8993_CLOCKING_1 0x06 -#define WM8993_CLOCKING_2 0x07 -#define WM8993_AUDIO_INTERFACE_3 0x08 -#define WM8993_AUDIO_INTERFACE_4 0x09 -#define WM8993_DAC_CTRL 0x0A -#define WM8993_LEFT_DAC_DIGITAL_VOLUME 0x0B -#define WM8993_RIGHT_DAC_DIGITAL_VOLUME 0x0C -#define WM8993_DIGITAL_SIDE_TONE 0x0D -#define WM8993_ADC_CTRL 0x0E -#define WM8993_LEFT_ADC_DIGITAL_VOLUME 0x0F -#define WM8993_RIGHT_ADC_DIGITAL_VOLUME 0x10 -#define WM8993_GPIO_CTRL_1 0x12 -#define WM8993_GPIO1 0x13 -#define WM8993_IRQ_DEBOUNCE 0x14 -#define WM8993_INPUTS_CLAMP_REG 0x15 -#define WM8993_GPIOCTRL_2 0x16 -#define WM8993_GPIO_POL 0x17 -#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME 0x18 -#define WM8993_LEFT_LINE_INPUT_3_4_VOLUME 0x19 -#define WM8993_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A -#define WM8993_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B -#define WM8993_LEFT_OUTPUT_VOLUME 0x1C -#define WM8993_RIGHT_OUTPUT_VOLUME 0x1D -#define WM8993_LINE_OUTPUTS_VOLUME 0x1E -#define WM8993_HPOUT2_VOLUME 0x1F -#define WM8993_LEFT_OPGA_VOLUME 0x20 -#define WM8993_RIGHT_OPGA_VOLUME 0x21 -#define WM8993_SPKMIXL_ATTENUATION 0x22 -#define WM8993_SPKMIXR_ATTENUATION 0x23 -#define WM8993_SPKOUT_MIXERS 0x24 -#define WM8993_SPKOUT_BOOST 0x25 -#define WM8993_SPEAKER_VOLUME_LEFT 0x26 -#define WM8993_SPEAKER_VOLUME_RIGHT 0x27 -#define WM8993_INPUT_MIXER2 0x28 -#define WM8993_INPUT_MIXER3 0x29 -#define WM8993_INPUT_MIXER4 0x2A -#define WM8993_INPUT_MIXER5 0x2B -#define WM8993_INPUT_MIXER6 0x2C -#define WM8993_OUTPUT_MIXER1 0x2D -#define WM8993_OUTPUT_MIXER2 0x2E -#define WM8993_OUTPUT_MIXER3 0x2F -#define WM8993_OUTPUT_MIXER4 0x30 -#define WM8993_OUTPUT_MIXER5 0x31 -#define WM8993_OUTPUT_MIXER6 0x32 -#define WM8993_HPOUT2_MIXER 0x33 -#define WM8993_LINE_MIXER1 0x34 -#define WM8993_LINE_MIXER2 0x35 -#define WM8993_SPEAKER_MIXER 0x36 -#define WM8993_ADDITIONAL_CONTROL 0x37 -#define WM8993_ANTIPOP1 0x38 -#define WM8993_ANTIPOP2 0x39 -#define WM8993_MICBIAS 0x3A -#define WM8993_FLL_CONTROL_1 0x3C -#define WM8993_FLL_CONTROL_2 0x3D -#define WM8993_FLL_CONTROL_3 0x3E -#define WM8993_FLL_CONTROL_4 0x3F -#define WM8993_FLL_CONTROL_5 0x40 -#define WM8993_CLOCKING_3 0x41 -#define WM8993_CLOCKING_4 0x42 -#define WM8993_MW_SLAVE_CONTROL 0x43 -#define WM8993_BUS_CONTROL_1 0x45 -#define WM8993_WRITE_SEQUENCER_0 0x46 -#define WM8993_WRITE_SEQUENCER_1 0x47 -#define WM8993_WRITE_SEQUENCER_2 0x48 -#define WM8993_WRITE_SEQUENCER_3 0x49 -#define WM8993_WRITE_SEQUENCER_4 0x4A -#define WM8993_WRITE_SEQUENCER_5 0x4B -#define WM8993_CHARGE_PUMP_1 0x4C -#define WM8993_CLASS_W_0 0x51 -#define WM8993_DC_SERVO_0 0x54 -#define WM8993_DC_SERVO_1 0x55 -#define WM8993_DC_SERVO_3 0x57 -#define WM8993_DC_SERVO_READBACK_0 0x58 -#define WM8993_DC_SERVO_READBACK_1 0x59 -#define WM8993_DC_SERVO_READBACK_2 0x5A -#define WM8993_ANALOGUE_HP_0 0x60 -#define WM8993_EQ1 0x62 -#define WM8993_EQ2 0x63 -#define WM8993_EQ3 0x64 -#define WM8993_EQ4 0x65 -#define WM8993_EQ5 0x66 -#define WM8993_EQ6 0x67 -#define WM8993_EQ7 0x68 -#define WM8993_EQ8 0x69 -#define WM8993_EQ9 0x6A -#define WM8993_EQ10 0x6B -#define WM8993_EQ11 0x6C -#define WM8993_EQ12 0x6D -#define WM8993_EQ13 0x6E -#define WM8993_EQ14 0x6F -#define WM8993_EQ15 0x70 -#define WM8993_EQ16 0x71 -#define WM8993_EQ17 0x72 -#define WM8993_EQ18 0x73 -#define WM8993_EQ19 0x74 -#define WM8993_EQ20 0x75 -#define WM8993_EQ21 0x76 -#define WM8993_EQ22 0x77 -#define WM8993_EQ23 0x78 -#define WM8993_EQ24 0x79 -#define WM8993_DIGITAL_PULLS 0x7A -#define WM8993_DRC_CONTROL_1 0x7B -#define WM8993_DRC_CONTROL_2 0x7C -#define WM8993_DRC_CONTROL_3 0x7D -#define WM8993_DRC_CONTROL_4 0x7E - -#define WM8993_REGISTER_COUNT 0x7F -#define WM8993_MAX_REGISTER 0x7E - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM8993_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ -#define WM8993_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ -#define WM8993_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ - -/* - * R1 (0x01) - Power Management (1) - */ -#define WM8993_SPKOUTR_ENA 0x2000 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_MASK 0x2000 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_SHIFT 13 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTL_ENA 0x1000 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_MASK 0x1000 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_SHIFT 12 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */ -#define WM8993_HPOUT2_ENA 0x0800 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_MASK 0x0800 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_SHIFT 11 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_WIDTH 1 /* HPOUT2_ENA */ -#define WM8993_HPOUT1L_ENA 0x0200 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_MASK 0x0200 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_SHIFT 9 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1R_ENA 0x0100 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_MASK 0x0100 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_SHIFT 8 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */ -#define WM8993_MICB2_ENA 0x0020 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_MASK 0x0020 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_SHIFT 5 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ -#define WM8993_MICB1_ENA 0x0010 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_MASK 0x0010 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_SHIFT 4 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ -#define WM8993_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */ -#define WM8993_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */ -#define WM8993_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */ -#define WM8993_BIAS_ENA 0x0001 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_SHIFT 0 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ - -/* - * R2 (0x02) - Power Management (2) - */ -#define WM8993_TSHUT_ENA 0x4000 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_MASK 0x4000 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_SHIFT 14 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */ -#define WM8993_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_MASK 0x2000 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_SHIFT 13 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_WIDTH 1 /* TSHUT_OPDIS */ -#define WM8993_OPCLK_ENA 0x0800 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ -#define WM8993_MIXINL_ENA 0x0200 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_MASK 0x0200 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_SHIFT 9 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */ -#define WM8993_MIXINR_ENA 0x0100 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_MASK 0x0100 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_SHIFT 8 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */ -#define WM8993_IN2L_ENA 0x0080 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_MASK 0x0080 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_SHIFT 7 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_WIDTH 1 /* IN2L_ENA */ -#define WM8993_IN1L_ENA 0x0040 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_MASK 0x0040 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_SHIFT 6 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_WIDTH 1 /* IN1L_ENA */ -#define WM8993_IN2R_ENA 0x0020 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_MASK 0x0020 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_SHIFT 5 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_WIDTH 1 /* IN2R_ENA */ -#define WM8993_IN1R_ENA 0x0010 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_MASK 0x0010 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_SHIFT 4 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_WIDTH 1 /* IN1R_ENA */ -#define WM8993_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ -#define WM8993_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ - -/* - * R3 (0x03) - Power Management (3) - */ -#define WM8993_LINEOUT1N_ENA 0x2000 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_MASK 0x2000 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_SHIFT 13 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_WIDTH 1 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1P_ENA 0x1000 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_MASK 0x1000 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_SHIFT 12 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_WIDTH 1 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT2N_ENA 0x0800 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_MASK 0x0800 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_SHIFT 11 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_WIDTH 1 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2P_ENA 0x0400 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_MASK 0x0400 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_SHIFT 10 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_WIDTH 1 /* LINEOUT2P_ENA */ -#define WM8993_SPKRVOL_ENA 0x0200 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_MASK 0x0200 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_SHIFT 9 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_WIDTH 1 /* SPKRVOL_ENA */ -#define WM8993_SPKLVOL_ENA 0x0100 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_MASK 0x0100 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_SHIFT 8 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_WIDTH 1 /* SPKLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA 0x0080 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_MASK 0x0080 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_SHIFT 7 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_WIDTH 1 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA 0x0040 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_MASK 0x0040 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_SHIFT 6 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_WIDTH 1 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTL_ENA 0x0020 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_MASK 0x0020 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_SHIFT 5 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTR_ENA 0x0010 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_MASK 0x0010 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_SHIFT 4 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */ -#define WM8993_DACL_ENA 0x0002 /* DACL_ENA */ -#define WM8993_DACL_ENA_MASK 0x0002 /* DACL_ENA */ -#define WM8993_DACL_ENA_SHIFT 1 /* DACL_ENA */ -#define WM8993_DACL_ENA_WIDTH 1 /* DACL_ENA */ -#define WM8993_DACR_ENA 0x0001 /* DACR_ENA */ -#define WM8993_DACR_ENA_MASK 0x0001 /* DACR_ENA */ -#define WM8993_DACR_ENA_SHIFT 0 /* DACR_ENA */ -#define WM8993_DACR_ENA_WIDTH 1 /* DACR_ENA */ - -/* - * R4 (0x04) - Audio Interface (1) - */ -#define WM8993_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_MASK 0x8000 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_SHIFT 15 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */ -#define WM8993_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_MASK 0x4000 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_SHIFT 14 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */ -#define WM8993_AIFADC_TDM 0x2000 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_MASK 0x2000 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_SHIFT 13 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_MASK 0x1000 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_SHIFT 12 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */ -#define WM8993_BCLK_DIR 0x0200 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_MASK 0x0200 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_SHIFT 9 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_WIDTH 1 /* BCLK_DIR */ -#define WM8993_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_MASK 0x0100 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_SHIFT 8 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */ -#define WM8993_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_MASK 0x0080 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_SHIFT 7 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */ -#define WM8993_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */ -#define WM8993_AIF_WL_SHIFT 5 /* AIF_WL - [6:5] */ -#define WM8993_AIF_WL_WIDTH 2 /* AIF_WL - [6:5] */ -#define WM8993_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */ -#define WM8993_AIF_FMT_SHIFT 3 /* AIF_FMT - [4:3] */ -#define WM8993_AIF_FMT_WIDTH 2 /* AIF_FMT - [4:3] */ - -/* - * R5 (0x05) - Audio Interface (2) - */ -#define WM8993_AIFDACL_SRC 0x8000 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_MASK 0x8000 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_SHIFT 15 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */ -#define WM8993_AIFDACR_SRC 0x4000 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_MASK 0x4000 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_SHIFT 14 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */ -#define WM8993_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */ -#define WM8993_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_BOOST_SHIFT 10 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_COMP 0x0010 /* DAC_COMP */ -#define WM8993_DAC_COMP_MASK 0x0010 /* DAC_COMP */ -#define WM8993_DAC_COMP_SHIFT 4 /* DAC_COMP */ -#define WM8993_DAC_COMP_WIDTH 1 /* DAC_COMP */ -#define WM8993_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ -#define WM8993_ADC_COMP 0x0004 /* ADC_COMP */ -#define WM8993_ADC_COMP_MASK 0x0004 /* ADC_COMP */ -#define WM8993_ADC_COMP_SHIFT 2 /* ADC_COMP */ -#define WM8993_ADC_COMP_WIDTH 1 /* ADC_COMP */ -#define WM8993_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */ -#define WM8993_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8993_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8993_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8993_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R6 (0x06) - Clocking 1 - */ -#define WM8993_TOCLK_RATE 0x8000 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_MASK 0x8000 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_SHIFT 15 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_WIDTH 1 /* TOCLK_RATE */ -#define WM8993_TOCLK_ENA 0x4000 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_MASK 0x4000 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_SHIFT 14 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ -#define WM8993_OPCLK_DIV_MASK 0x1E00 /* OPCLK_DIV - [12:9] */ -#define WM8993_OPCLK_DIV_SHIFT 9 /* OPCLK_DIV - [12:9] */ -#define WM8993_OPCLK_DIV_WIDTH 4 /* OPCLK_DIV - [12:9] */ -#define WM8993_DCLK_DIV_MASK 0x01C0 /* DCLK_DIV - [8:6] */ -#define WM8993_DCLK_DIV_SHIFT 6 /* DCLK_DIV - [8:6] */ -#define WM8993_DCLK_DIV_WIDTH 3 /* DCLK_DIV - [8:6] */ -#define WM8993_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */ -#define WM8993_BCLK_DIV_SHIFT 1 /* BCLK_DIV - [4:1] */ -#define WM8993_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [4:1] */ - -/* - * R7 (0x07) - Clocking 2 - */ -#define WM8993_MCLK_SRC 0x8000 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_MASK 0x8000 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_SHIFT 15 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_WIDTH 1 /* MCLK_SRC */ -#define WM8993_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_MASK 0x4000 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_SHIFT 14 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */ -#define WM8993_MCLK_DIV 0x1000 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_MASK 0x1000 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_SHIFT 12 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_WIDTH 1 /* MCLK_DIV */ -#define WM8993_MCLK_INV 0x0400 /* MCLK_INV */ -#define WM8993_MCLK_INV_MASK 0x0400 /* MCLK_INV */ -#define WM8993_MCLK_INV_SHIFT 10 /* MCLK_INV */ -#define WM8993_MCLK_INV_WIDTH 1 /* MCLK_INV */ -#define WM8993_ADC_DIV_MASK 0x00E0 /* ADC_DIV - [7:5] */ -#define WM8993_ADC_DIV_SHIFT 5 /* ADC_DIV - [7:5] */ -#define WM8993_ADC_DIV_WIDTH 3 /* ADC_DIV - [7:5] */ -#define WM8993_DAC_DIV_MASK 0x001C /* DAC_DIV - [4:2] */ -#define WM8993_DAC_DIV_SHIFT 2 /* DAC_DIV - [4:2] */ -#define WM8993_DAC_DIV_WIDTH 3 /* DAC_DIV - [4:2] */ - -/* - * R8 (0x08) - Audio Interface (3) - */ -#define WM8993_AIF_MSTR1 0x8000 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_MASK 0x8000 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_SHIFT 15 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_WIDTH 1 /* AIF_MSTR1 */ - -/* - * R9 (0x09) - Audio Interface (4) - */ -#define WM8993_AIF_TRIS 0x2000 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_MASK 0x2000 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_SHIFT 13 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_WIDTH 1 /* AIF_TRIS */ -#define WM8993_LRCLK_DIR 0x0800 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_MASK 0x0800 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_SHIFT 11 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */ -#define WM8993_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */ -#define WM8993_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */ -#define WM8993_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */ - -/* - * R10 (0x0A) - DAC CTRL - */ -#define WM8993_DAC_OSR128 0x2000 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_MASK 0x2000 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_SHIFT 13 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ -#define WM8993_DAC_MONO 0x0200 /* DAC_MONO */ -#define WM8993_DAC_MONO_MASK 0x0200 /* DAC_MONO */ -#define WM8993_DAC_MONO_SHIFT 9 /* DAC_MONO */ -#define WM8993_DAC_MONO_WIDTH 1 /* DAC_MONO */ -#define WM8993_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_MASK 0x0100 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_SHIFT 8 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */ -#define WM8993_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_MASK 0x0080 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_SHIFT 7 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ -#define WM8993_DAC_UNMUTE_RAMP 0x0040 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_MASK 0x0040 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_SHIFT 6 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */ -#define WM8993_DEEMPH_MASK 0x0030 /* DEEMPH - [5:4] */ -#define WM8993_DEEMPH_SHIFT 4 /* DEEMPH - [5:4] */ -#define WM8993_DEEMPH_WIDTH 2 /* DEEMPH - [5:4] */ -#define WM8993_DAC_MUTE 0x0004 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_MASK 0x0004 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_SHIFT 2 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ -#define WM8993_DACL_DATINV 0x0002 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_MASK 0x0002 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_SHIFT 1 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_WIDTH 1 /* DACL_DATINV */ -#define WM8993_DACR_DATINV 0x0001 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_MASK 0x0001 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_SHIFT 0 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_WIDTH 1 /* DACR_DATINV */ - -/* - * R11 (0x0B) - Left DAC Digital Volume - */ -#define WM8993_DAC_VU 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8993_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ -#define WM8993_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */ -#define WM8993_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */ - -/* - * R12 (0x0C) - Right DAC Digital Volume - */ -#define WM8993_DAC_VU 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8993_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ -#define WM8993_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */ -#define WM8993_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */ - -/* - * R13 (0x0D) - Digital Side Tone - */ -#define WM8993_ADCL_DAC_SVOL_MASK 0x1E00 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCL_DAC_SVOL_SHIFT 9 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCR_DAC_SVOL_MASK 0x01E0 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADCR_DAC_SVOL_SHIFT 5 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */ -#define WM8993_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */ -#define WM8993_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */ - -/* - * R14 (0x0E) - ADC CTRL - */ -#define WM8993_ADC_OSR128 0x0200 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_MASK 0x0200 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_SHIFT 9 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ -#define WM8993_ADC_HPF 0x0100 /* ADC_HPF */ -#define WM8993_ADC_HPF_MASK 0x0100 /* ADC_HPF */ -#define WM8993_ADC_HPF_SHIFT 8 /* ADC_HPF */ -#define WM8993_ADC_HPF_WIDTH 1 /* ADC_HPF */ -#define WM8993_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADCL_DATINV 0x0002 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */ -#define WM8993_ADCR_DATINV 0x0001 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */ - -/* - * R15 (0x0F) - Left ADC Digital Volume - */ -#define WM8993_ADC_VU 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8993_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ -#define WM8993_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */ -#define WM8993_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */ - -/* - * R16 (0x10) - Right ADC Digital Volume - */ -#define WM8993_ADC_VU 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8993_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ -#define WM8993_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */ -#define WM8993_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */ - -/* - * R18 (0x12) - GPIO CTRL 1 - */ -#define WM8993_JD2_SC_EINT 0x8000 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_MASK 0x8000 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_SHIFT 15 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_WIDTH 1 /* JD2_SC_EINT */ -#define WM8993_JD2_EINT 0x4000 /* JD2_EINT */ -#define WM8993_JD2_EINT_MASK 0x4000 /* JD2_EINT */ -#define WM8993_JD2_EINT_SHIFT 14 /* JD2_EINT */ -#define WM8993_JD2_EINT_WIDTH 1 /* JD2_EINT */ -#define WM8993_WSEQ_EINT 0x2000 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_MASK 0x2000 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_SHIFT 13 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_WIDTH 1 /* WSEQ_EINT */ -#define WM8993_IRQ 0x1000 /* IRQ */ -#define WM8993_IRQ_MASK 0x1000 /* IRQ */ -#define WM8993_IRQ_SHIFT 12 /* IRQ */ -#define WM8993_IRQ_WIDTH 1 /* IRQ */ -#define WM8993_TEMPOK_EINT 0x0800 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_MASK 0x0800 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_SHIFT 11 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_WIDTH 1 /* TEMPOK_EINT */ -#define WM8993_JD1_SC_EINT 0x0400 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_MASK 0x0400 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_SHIFT 10 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_WIDTH 1 /* JD1_SC_EINT */ -#define WM8993_JD1_EINT 0x0200 /* JD1_EINT */ -#define WM8993_JD1_EINT_MASK 0x0200 /* JD1_EINT */ -#define WM8993_JD1_EINT_SHIFT 9 /* JD1_EINT */ -#define WM8993_JD1_EINT_WIDTH 1 /* JD1_EINT */ -#define WM8993_FLL_LOCK_EINT 0x0100 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_MASK 0x0100 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_SHIFT 8 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ -#define WM8993_GPI8_EINT 0x0080 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_MASK 0x0080 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_SHIFT 7 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_WIDTH 1 /* GPI8_EINT */ -#define WM8993_GPI7_EINT 0x0040 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_MASK 0x0040 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_SHIFT 6 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_WIDTH 1 /* GPI7_EINT */ -#define WM8993_GPIO1_EINT 0x0001 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_MASK 0x0001 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_SHIFT 0 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_WIDTH 1 /* GPIO1_EINT */ - -/* - * R19 (0x13) - GPIO1 - */ -#define WM8993_GPIO1_PU 0x0020 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_SHIFT 5 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_WIDTH 1 /* GPIO1_PU */ -#define WM8993_GPIO1_PD 0x0010 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_SHIFT 4 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_WIDTH 1 /* GPIO1_PD */ -#define WM8993_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */ -#define WM8993_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */ -#define WM8993_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */ - -/* - * R20 (0x14) - IRQ_DEBOUNCE - */ -#define WM8993_JD2_SC_DB 0x8000 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_MASK 0x8000 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_SHIFT 15 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_WIDTH 1 /* JD2_SC_DB */ -#define WM8993_JD2_DB 0x4000 /* JD2_DB */ -#define WM8993_JD2_DB_MASK 0x4000 /* JD2_DB */ -#define WM8993_JD2_DB_SHIFT 14 /* JD2_DB */ -#define WM8993_JD2_DB_WIDTH 1 /* JD2_DB */ -#define WM8993_WSEQ_DB 0x2000 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_MASK 0x2000 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_SHIFT 13 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_WIDTH 1 /* WSEQ_DB */ -#define WM8993_TEMPOK_DB 0x0800 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_MASK 0x0800 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_SHIFT 11 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_WIDTH 1 /* TEMPOK_DB */ -#define WM8993_JD1_SC_DB 0x0400 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_MASK 0x0400 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_SHIFT 10 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_WIDTH 1 /* JD1_SC_DB */ -#define WM8993_JD1_DB 0x0200 /* JD1_DB */ -#define WM8993_JD1_DB_MASK 0x0200 /* JD1_DB */ -#define WM8993_JD1_DB_SHIFT 9 /* JD1_DB */ -#define WM8993_JD1_DB_WIDTH 1 /* JD1_DB */ -#define WM8993_FLL_LOCK_DB 0x0100 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_MASK 0x0100 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_SHIFT 8 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */ -#define WM8993_GPI8_DB 0x0080 /* GPI8_DB */ -#define WM8993_GPI8_DB_MASK 0x0080 /* GPI8_DB */ -#define WM8993_GPI8_DB_SHIFT 7 /* GPI8_DB */ -#define WM8993_GPI8_DB_WIDTH 1 /* GPI8_DB */ -#define WM8993_GPI7_DB 0x0008 /* GPI7_DB */ -#define WM8993_GPI7_DB_MASK 0x0008 /* GPI7_DB */ -#define WM8993_GPI7_DB_SHIFT 3 /* GPI7_DB */ -#define WM8993_GPI7_DB_WIDTH 1 /* GPI7_DB */ -#define WM8993_GPIO1_DB 0x0001 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_MASK 0x0001 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_SHIFT 0 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_WIDTH 1 /* GPIO1_DB */ - -/* - * R21 (0x15) - Inputs Clamp - */ -#define WM8993_INPUTS_CLAMP 0x0040 /* INPUTS_CLAMP */ -#define WM8993_INPUTS_CLAMP_MASK 0x0040 /* INPUTS_CLAMP */ -#define WM8993_INPUTS_CLAMP_SHIFT 7 /* INPUTS_CLAMP */ -#define WM8993_INPUTS_CLAMP_WIDTH 1 /* INPUTS_CLAMP */ - -/* - * R22 (0x16) - GPIOCTRL 2 - */ -#define WM8993_IM_JD2_EINT 0x2000 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_MASK 0x2000 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_SHIFT 13 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_WIDTH 1 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_SC_EINT 0x1000 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_MASK 0x1000 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_SHIFT 12 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_WIDTH 1 /* IM_JD2_SC_EINT */ -#define WM8993_IM_TEMPOK_EINT 0x0800 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_MASK 0x0800 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_SHIFT 11 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_WIDTH 1 /* IM_TEMPOK_EINT */ -#define WM8993_IM_JD1_SC_EINT 0x0400 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_MASK 0x0400 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_SHIFT 10 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_WIDTH 1 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_EINT 0x0200 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_MASK 0x0200 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_SHIFT 9 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_WIDTH 1 /* IM_JD1_EINT */ -#define WM8993_IM_FLL_LOCK_EINT 0x0100 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_MASK 0x0100 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_SHIFT 8 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_GPI8_EINT 0x0040 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_MASK 0x0040 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_SHIFT 6 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_WIDTH 1 /* IM_GPI8_EINT */ -#define WM8993_IM_GPIO1_EINT 0x0020 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_MASK 0x0020 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_SHIFT 5 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_WIDTH 1 /* IM_GPIO1_EINT */ -#define WM8993_GPI8_ENA 0x0010 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_MASK 0x0010 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_SHIFT 4 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_WIDTH 1 /* GPI8_ENA */ -#define WM8993_IM_GPI7_EINT 0x0004 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_MASK 0x0004 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_SHIFT 2 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_WIDTH 1 /* IM_GPI7_EINT */ -#define WM8993_IM_WSEQ_EINT 0x0002 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_MASK 0x0002 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_SHIFT 1 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_WIDTH 1 /* IM_WSEQ_EINT */ -#define WM8993_GPI7_ENA 0x0001 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_MASK 0x0001 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_SHIFT 0 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_WIDTH 1 /* GPI7_ENA */ - -/* - * R23 (0x17) - GPIO_POL - */ -#define WM8993_JD2_SC_POL 0x8000 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_MASK 0x8000 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_SHIFT 15 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_WIDTH 1 /* JD2_SC_POL */ -#define WM8993_JD2_POL 0x4000 /* JD2_POL */ -#define WM8993_JD2_POL_MASK 0x4000 /* JD2_POL */ -#define WM8993_JD2_POL_SHIFT 14 /* JD2_POL */ -#define WM8993_JD2_POL_WIDTH 1 /* JD2_POL */ -#define WM8993_WSEQ_POL 0x2000 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_MASK 0x2000 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_SHIFT 13 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_WIDTH 1 /* WSEQ_POL */ -#define WM8993_IRQ_POL 0x1000 /* IRQ_POL */ -#define WM8993_IRQ_POL_MASK 0x1000 /* IRQ_POL */ -#define WM8993_IRQ_POL_SHIFT 12 /* IRQ_POL */ -#define WM8993_IRQ_POL_WIDTH 1 /* IRQ_POL */ -#define WM8993_TEMPOK_POL 0x0800 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_MASK 0x0800 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_SHIFT 11 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_WIDTH 1 /* TEMPOK_POL */ -#define WM8993_JD1_SC_POL 0x0400 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_MASK 0x0400 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_SHIFT 10 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_WIDTH 1 /* JD1_SC_POL */ -#define WM8993_JD1_POL 0x0200 /* JD1_POL */ -#define WM8993_JD1_POL_MASK 0x0200 /* JD1_POL */ -#define WM8993_JD1_POL_SHIFT 9 /* JD1_POL */ -#define WM8993_JD1_POL_WIDTH 1 /* JD1_POL */ -#define WM8993_FLL_LOCK_POL 0x0100 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_MASK 0x0100 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_SHIFT 8 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_WIDTH 1 /* FLL_LOCK_POL */ -#define WM8993_GPI8_POL 0x0080 /* GPI8_POL */ -#define WM8993_GPI8_POL_MASK 0x0080 /* GPI8_POL */ -#define WM8993_GPI8_POL_SHIFT 7 /* GPI8_POL */ -#define WM8993_GPI8_POL_WIDTH 1 /* GPI8_POL */ -#define WM8993_GPI7_POL 0x0040 /* GPI7_POL */ -#define WM8993_GPI7_POL_MASK 0x0040 /* GPI7_POL */ -#define WM8993_GPI7_POL_SHIFT 6 /* GPI7_POL */ -#define WM8993_GPI7_POL_WIDTH 1 /* GPI7_POL */ -#define WM8993_GPIO1_POL 0x0001 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_MASK 0x0001 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_SHIFT 0 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_WIDTH 1 /* GPIO1_POL */ - -/* - * R24 (0x18) - Left Line Input 1&2 Volume - */ -#define WM8993_IN1_VU 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */ -#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8993_IN1L_MUTE 0x0080 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_MASK 0x0080 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_SHIFT 7 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */ -#define WM8993_IN1L_ZC 0x0040 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_MASK 0x0040 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_SHIFT 6 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_WIDTH 1 /* IN1L_ZC */ -#define WM8993_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */ -#define WM8993_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */ -#define WM8993_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */ - -/* - * R25 (0x19) - Left Line Input 3&4 Volume - */ -#define WM8993_IN2_VU 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */ -#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */ -#define WM8993_IN2L_MUTE 0x0080 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_MASK 0x0080 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_SHIFT 7 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */ -#define WM8993_IN2L_ZC 0x0040 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_MASK 0x0040 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_SHIFT 6 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_WIDTH 1 /* IN2L_ZC */ -#define WM8993_IN2L_VOL_MASK 0x001F /* IN2L_VOL - [4:0] */ -#define WM8993_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [4:0] */ -#define WM8993_IN2L_VOL_WIDTH 5 /* IN2L_VOL - [4:0] */ - -/* - * R26 (0x1A) - Right Line Input 1&2 Volume - */ -#define WM8993_IN1_VU 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */ -#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8993_IN1R_MUTE 0x0080 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_MASK 0x0080 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_SHIFT 7 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */ -#define WM8993_IN1R_ZC 0x0040 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_MASK 0x0040 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_SHIFT 6 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_WIDTH 1 /* IN1R_ZC */ -#define WM8993_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */ -#define WM8993_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */ -#define WM8993_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */ - -/* - * R27 (0x1B) - Right Line Input 3&4 Volume - */ -#define WM8993_IN2_VU 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */ -#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */ -#define WM8993_IN2R_MUTE 0x0080 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_MASK 0x0080 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_SHIFT 7 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */ -#define WM8993_IN2R_ZC 0x0040 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_MASK 0x0040 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_SHIFT 6 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_WIDTH 1 /* IN2R_ZC */ -#define WM8993_IN2R_VOL_MASK 0x001F /* IN2R_VOL - [4:0] */ -#define WM8993_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [4:0] */ -#define WM8993_IN2R_VOL_WIDTH 5 /* IN2R_VOL - [4:0] */ - -/* - * R28 (0x1C) - Left Output Volume - */ -#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */ -#define WM8993_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_MUTE_N 0x0040 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_MASK 0x0040 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_SHIFT 6 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_WIDTH 1 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_VOL_MASK 0x003F /* HPOUT1L_VOL - [5:0] */ -#define WM8993_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [5:0] */ -#define WM8993_HPOUT1L_VOL_WIDTH 6 /* HPOUT1L_VOL - [5:0] */ - -/* - * R29 (0x1D) - Right Output Volume - */ -#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */ -#define WM8993_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_MUTE_N 0x0040 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_MASK 0x0040 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_SHIFT 6 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_WIDTH 1 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_VOL_MASK 0x003F /* HPOUT1R_VOL - [5:0] */ -#define WM8993_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [5:0] */ -#define WM8993_HPOUT1R_VOL_WIDTH 6 /* HPOUT1R_VOL - [5:0] */ - -/* - * R30 (0x1E) - Line Outputs Volume - */ -#define WM8993_LINEOUT1N_MUTE 0x0040 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_MASK 0x0040 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_SHIFT 6 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_WIDTH 1 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1P_MUTE 0x0020 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_MASK 0x0020 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_SHIFT 5 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_WIDTH 1 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1_VOL 0x0010 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_MASK 0x0010 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_SHIFT 4 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_WIDTH 1 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT2N_MUTE 0x0004 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_MASK 0x0004 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_SHIFT 2 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_WIDTH 1 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2P_MUTE 0x0002 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_MASK 0x0002 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_SHIFT 1 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_WIDTH 1 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2_VOL 0x0001 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_MASK 0x0001 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_SHIFT 0 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_WIDTH 1 /* LINEOUT2_VOL */ - -/* - * R31 (0x1F) - HPOUT2 Volume - */ -#define WM8993_HPOUT2_MUTE 0x0020 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_MASK 0x0020 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_SHIFT 5 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_WIDTH 1 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_VOL 0x0010 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_MASK 0x0010 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_SHIFT 4 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_WIDTH 1 /* HPOUT2_VOL */ - -/* - * R32 (0x20) - Left OPGA Volume - */ -#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */ -#define WM8993_MIXOUTL_ZC 0x0080 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_MASK 0x0080 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_SHIFT 7 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_WIDTH 1 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_MUTE_N 0x0040 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_MASK 0x0040 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_SHIFT 6 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_WIDTH 1 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_VOL_MASK 0x003F /* MIXOUTL_VOL - [5:0] */ -#define WM8993_MIXOUTL_VOL_SHIFT 0 /* MIXOUTL_VOL - [5:0] */ -#define WM8993_MIXOUTL_VOL_WIDTH 6 /* MIXOUTL_VOL - [5:0] */ - -/* - * R33 (0x21) - Right OPGA Volume - */ -#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */ -#define WM8993_MIXOUTR_ZC 0x0080 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_MASK 0x0080 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_SHIFT 7 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_WIDTH 1 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_MUTE_N 0x0040 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_MASK 0x0040 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_SHIFT 6 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_WIDTH 1 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_VOL_MASK 0x003F /* MIXOUTR_VOL - [5:0] */ -#define WM8993_MIXOUTR_VOL_SHIFT 0 /* MIXOUTR_VOL - [5:0] */ -#define WM8993_MIXOUTR_VOL_WIDTH 6 /* MIXOUTR_VOL - [5:0] */ - -/* - * R34 (0x22) - SPKMIXL Attenuation - */ -#define WM8993_MIXINL_SPKMIXL_VOL 0x0020 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_MASK 0x0020 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_SHIFT 5 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL 0x0010 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_MASK 0x0010 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_SHIFT 4 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_WIDTH 1 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL 0x0008 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_MASK 0x0008 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_SHIFT 3 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_WIDTH 1 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL 0x0004 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_MASK 0x0004 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_SHIFT 2 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */ -#define WM8993_SPKMIXL_VOL_MASK 0x0003 /* SPKMIXL_VOL - [1:0] */ -#define WM8993_SPKMIXL_VOL_SHIFT 0 /* SPKMIXL_VOL - [1:0] */ -#define WM8993_SPKMIXL_VOL_WIDTH 2 /* SPKMIXL_VOL - [1:0] */ - -/* - * R35 (0x23) - SPKMIXR Attenuation - */ -#define WM8993_SPKOUT_CLASSAB_MODE 0x0100 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_MASK 0x0100 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_SHIFT 8 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_WIDTH 1 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_MIXINR_SPKMIXR_VOL 0x0020 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_MASK 0x0020 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_SHIFT 5 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL 0x0010 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_MASK 0x0010 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_SHIFT 4 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_WIDTH 1 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL 0x0008 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_MASK 0x0008 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_SHIFT 3 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_WIDTH 1 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL 0x0004 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_MASK 0x0004 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_SHIFT 2 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */ -#define WM8993_SPKMIXR_VOL_MASK 0x0003 /* SPKMIXR_VOL - [1:0] */ -#define WM8993_SPKMIXR_VOL_SHIFT 0 /* SPKMIXR_VOL - [1:0] */ -#define WM8993_SPKMIXR_VOL_WIDTH 2 /* SPKMIXR_VOL - [1:0] */ - -/* - * R36 (0x24) - SPKOUT Mixers - */ -#define WM8993_VRX_TO_SPKOUTL 0x0020 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_MASK 0x0020 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_SHIFT 5 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_WIDTH 1 /* VRX_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL 0x0010 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_MASK 0x0010 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_SHIFT 4 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_WIDTH 1 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL 0x0008 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_MASK 0x0008 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_SHIFT 3 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_WIDTH 1 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTR 0x0004 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_MASK 0x0004 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_SHIFT 2 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_WIDTH 1 /* VRX_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR 0x0002 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_MASK 0x0002 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_SHIFT 1 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_WIDTH 1 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR 0x0001 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_MASK 0x0001 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_SHIFT 0 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_WIDTH 1 /* SPKMIXR_TO_SPKOUTR */ - -/* - * R37 (0x25) - SPKOUT Boost - */ -#define WM8993_SPKOUTL_BOOST_MASK 0x0038 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTL_BOOST_SHIFT 3 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTL_BOOST_WIDTH 3 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTR_BOOST_MASK 0x0007 /* SPKOUTR_BOOST - [2:0] */ -#define WM8993_SPKOUTR_BOOST_SHIFT 0 /* SPKOUTR_BOOST - [2:0] */ -#define WM8993_SPKOUTR_BOOST_WIDTH 3 /* SPKOUTR_BOOST - [2:0] */ - -/* - * R38 (0x26) - Speaker Volume Left - */ -#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ -#define WM8993_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_MUTE_N 0x0040 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_MASK 0x0040 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_SHIFT 6 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_WIDTH 1 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_VOL_MASK 0x003F /* SPKOUTL_VOL - [5:0] */ -#define WM8993_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [5:0] */ -#define WM8993_SPKOUTL_VOL_WIDTH 6 /* SPKOUTL_VOL - [5:0] */ - -/* - * R39 (0x27) - Speaker Volume Right - */ -#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ -#define WM8993_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_MUTE_N 0x0040 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_MASK 0x0040 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_SHIFT 6 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_WIDTH 1 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_VOL_MASK 0x003F /* SPKOUTR_VOL - [5:0] */ -#define WM8993_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [5:0] */ -#define WM8993_SPKOUTR_VOL_WIDTH 6 /* SPKOUTR_VOL - [5:0] */ - -/* - * R40 (0x28) - Input Mixer2 - */ -#define WM8993_IN2LP_TO_IN2L 0x0080 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_MASK 0x0080 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_SHIFT 7 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_WIDTH 1 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L 0x0040 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_MASK 0x0040 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_SHIFT 6 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_WIDTH 1 /* IN2LN_TO_IN2L */ -#define WM8993_IN1LP_TO_IN1L 0x0020 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_MASK 0x0020 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_SHIFT 5 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_WIDTH 1 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L 0x0010 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_MASK 0x0010 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_SHIFT 4 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_WIDTH 1 /* IN1LN_TO_IN1L */ -#define WM8993_IN2RP_TO_IN2R 0x0008 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_MASK 0x0008 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_SHIFT 3 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_WIDTH 1 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R 0x0004 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_MASK 0x0004 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_SHIFT 2 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_WIDTH 1 /* IN2RN_TO_IN2R */ -#define WM8993_IN1RP_TO_IN1R 0x0002 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_MASK 0x0002 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_SHIFT 1 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_WIDTH 1 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R 0x0001 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_MASK 0x0001 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_SHIFT 0 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_WIDTH 1 /* IN1RN_TO_IN1R */ - -/* - * R41 (0x29) - Input Mixer3 - */ -#define WM8993_IN2L_TO_MIXINL 0x0100 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_MASK 0x0100 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_SHIFT 8 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_MIXINL_VOL 0x0080 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_MASK 0x0080 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_SHIFT 7 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_WIDTH 1 /* IN2L_MIXINL_VOL */ -#define WM8993_IN1L_TO_MIXINL 0x0020 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_MASK 0x0020 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_SHIFT 5 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_WIDTH 1 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_MIXINL_VOL 0x0010 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_MASK 0x0010 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_SHIFT 4 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_WIDTH 1 /* IN1L_MIXINL_VOL */ -#define WM8993_MIXOUTL_MIXINL_VOL_MASK 0x0007 /* MIXOUTL_MIXINL_VOL - [2:0] */ -#define WM8993_MIXOUTL_MIXINL_VOL_SHIFT 0 /* MIXOUTL_MIXINL_VOL - [2:0] */ -#define WM8993_MIXOUTL_MIXINL_VOL_WIDTH 3 /* MIXOUTL_MIXINL_VOL - [2:0] */ - -/* - * R42 (0x2A) - Input Mixer4 - */ -#define WM8993_IN2R_TO_MIXINR 0x0100 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_MASK 0x0100 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_SHIFT 8 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_MIXINR_VOL 0x0080 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_MASK 0x0080 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_SHIFT 7 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_WIDTH 1 /* IN2R_MIXINR_VOL */ -#define WM8993_IN1R_TO_MIXINR 0x0020 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_MASK 0x0020 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_SHIFT 5 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_WIDTH 1 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_MIXINR_VOL 0x0010 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_MASK 0x0010 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_SHIFT 4 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_WIDTH 1 /* IN1R_MIXINR_VOL */ -#define WM8993_MIXOUTR_MIXINR_VOL_MASK 0x0007 /* MIXOUTR_MIXINR_VOL - [2:0] */ -#define WM8993_MIXOUTR_MIXINR_VOL_SHIFT 0 /* MIXOUTR_MIXINR_VOL - [2:0] */ -#define WM8993_MIXOUTR_MIXINR_VOL_WIDTH 3 /* MIXOUTR_MIXINR_VOL - [2:0] */ - -/* - * R43 (0x2B) - Input Mixer5 - */ -#define WM8993_IN1LP_MIXINL_VOL_MASK 0x01C0 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_IN1LP_MIXINL_VOL_SHIFT 6 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_IN1LP_MIXINL_VOL_WIDTH 3 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_VRX_MIXINL_VOL_MASK 0x0007 /* VRX_MIXINL_VOL - [2:0] */ -#define WM8993_VRX_MIXINL_VOL_SHIFT 0 /* VRX_MIXINL_VOL - [2:0] */ -#define WM8993_VRX_MIXINL_VOL_WIDTH 3 /* VRX_MIXINL_VOL - [2:0] */ - -/* - * R44 (0x2C) - Input Mixer6 - */ -#define WM8993_IN1RP_MIXINR_VOL_MASK 0x01C0 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_IN1RP_MIXINR_VOL_SHIFT 6 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_IN1RP_MIXINR_VOL_WIDTH 3 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_VRX_MIXINR_VOL_MASK 0x0007 /* VRX_MIXINR_VOL - [2:0] */ -#define WM8993_VRX_MIXINR_VOL_SHIFT 0 /* VRX_MIXINR_VOL - [2:0] */ -#define WM8993_VRX_MIXINR_VOL_WIDTH 3 /* VRX_MIXINR_VOL - [2:0] */ - -/* - * R45 (0x2D) - Output Mixer1 - */ -#define WM8993_DACL_TO_HPOUT1L 0x0100 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_MASK 0x0100 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_SHIFT 8 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_WIDTH 1 /* DACL_TO_HPOUT1L */ -#define WM8993_MIXINR_TO_MIXOUTL 0x0080 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_MASK 0x0080 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_SHIFT 7 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_WIDTH 1 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL 0x0040 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_MASK 0x0040 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_SHIFT 6 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_WIDTH 1 /* MIXINL_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL 0x0020 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_MASK 0x0020 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_SHIFT 5 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_WIDTH 1 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL 0x0010 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_MASK 0x0010 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_SHIFT 4 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_WIDTH 1 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL 0x0008 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_MASK 0x0008 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_SHIFT 3 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_WIDTH 1 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL 0x0004 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_MASK 0x0004 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_SHIFT 2 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_WIDTH 1 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL 0x0002 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_MASK 0x0002 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_SHIFT 1 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_WIDTH 1 /* IN2LP_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL 0x0001 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_MASK 0x0001 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_SHIFT 0 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_WIDTH 1 /* DACL_TO_MIXOUTL */ - -/* - * R46 (0x2E) - Output Mixer2 - */ -#define WM8993_DACR_TO_HPOUT1R 0x0100 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_MASK 0x0100 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_SHIFT 8 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_WIDTH 1 /* DACR_TO_HPOUT1R */ -#define WM8993_MIXINL_TO_MIXOUTR 0x0080 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_MASK 0x0080 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_SHIFT 7 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_WIDTH 1 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR 0x0040 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_MASK 0x0040 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_SHIFT 6 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_WIDTH 1 /* MIXINR_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR 0x0020 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_MASK 0x0020 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_SHIFT 5 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_WIDTH 1 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR 0x0010 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_MASK 0x0010 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_SHIFT 4 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_WIDTH 1 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR 0x0008 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_MASK 0x0008 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_SHIFT 3 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_WIDTH 1 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR 0x0004 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_MASK 0x0004 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_SHIFT 2 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_WIDTH 1 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR 0x0002 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_MASK 0x0002 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_SHIFT 1 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_WIDTH 1 /* IN2RP_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR 0x0001 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_MASK 0x0001 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_SHIFT 0 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_WIDTH 1 /* DACR_TO_MIXOUTR */ - -/* - * R47 (0x2F) - Output Mixer3 - */ -#define WM8993_IN2LP_MIXOUTL_VOL_MASK 0x0E00 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LP_MIXOUTL_VOL_SHIFT 9 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LP_MIXOUTL_VOL_WIDTH 3 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LN_MIXOUTL_VOL_MASK 0x01C0 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTL_VOL_SHIFT 6 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTL_VOL_WIDTH 3 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN1R_MIXOUTL_VOL_MASK 0x0038 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTL_VOL_SHIFT 3 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTL_VOL_WIDTH 3 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTL_VOL_MASK 0x0007 /* IN1L_MIXOUTL_VOL - [2:0] */ -#define WM8993_IN1L_MIXOUTL_VOL_SHIFT 0 /* IN1L_MIXOUTL_VOL - [2:0] */ -#define WM8993_IN1L_MIXOUTL_VOL_WIDTH 3 /* IN1L_MIXOUTL_VOL - [2:0] */ - -/* - * R48 (0x30) - Output Mixer4 - */ -#define WM8993_IN2RP_MIXOUTR_VOL_MASK 0x0E00 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RP_MIXOUTR_VOL_SHIFT 9 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RP_MIXOUTR_VOL_WIDTH 3 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RN_MIXOUTR_VOL_MASK 0x01C0 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTR_VOL_SHIFT 6 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTR_VOL_WIDTH 3 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN1L_MIXOUTR_VOL_MASK 0x0038 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTR_VOL_SHIFT 3 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTR_VOL_WIDTH 3 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTR_VOL_MASK 0x0007 /* IN1R_MIXOUTR_VOL - [2:0] */ -#define WM8993_IN1R_MIXOUTR_VOL_SHIFT 0 /* IN1R_MIXOUTR_VOL - [2:0] */ -#define WM8993_IN1R_MIXOUTR_VOL_WIDTH 3 /* IN1R_MIXOUTR_VOL - [2:0] */ - -/* - * R49 (0x31) - Output Mixer5 - */ -#define WM8993_DACL_MIXOUTL_VOL_MASK 0x0E00 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_DACL_MIXOUTL_VOL_SHIFT 9 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_DACL_MIXOUTL_VOL_WIDTH 3 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2RN_MIXOUTL_VOL_MASK 0x01C0 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTL_VOL_SHIFT 6 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTL_VOL_WIDTH 3 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_MIXINR_MIXOUTL_VOL_MASK 0x0038 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTL_VOL_SHIFT 3 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTL_VOL_WIDTH 3 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTL_VOL_MASK 0x0007 /* MIXINL_MIXOUTL_VOL - [2:0] */ -#define WM8993_MIXINL_MIXOUTL_VOL_SHIFT 0 /* MIXINL_MIXOUTL_VOL - [2:0] */ -#define WM8993_MIXINL_MIXOUTL_VOL_WIDTH 3 /* MIXINL_MIXOUTL_VOL - [2:0] */ - -/* - * R50 (0x32) - Output Mixer6 - */ -#define WM8993_DACR_MIXOUTR_VOL_MASK 0x0E00 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_DACR_MIXOUTR_VOL_SHIFT 9 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_DACR_MIXOUTR_VOL_WIDTH 3 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2LN_MIXOUTR_VOL_MASK 0x01C0 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTR_VOL_SHIFT 6 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTR_VOL_WIDTH 3 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_MIXINL_MIXOUTR_VOL_MASK 0x0038 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTR_VOL_SHIFT 3 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTR_VOL_WIDTH 3 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTR_VOL_MASK 0x0007 /* MIXINR_MIXOUTR_VOL - [2:0] */ -#define WM8993_MIXINR_MIXOUTR_VOL_SHIFT 0 /* MIXINR_MIXOUTR_VOL - [2:0] */ -#define WM8993_MIXINR_MIXOUTR_VOL_WIDTH 3 /* MIXINR_MIXOUTR_VOL - [2:0] */ - -/* - * R51 (0x33) - HPOUT2 Mixer - */ -#define WM8993_VRX_TO_HPOUT2 0x0020 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_MASK 0x0020 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_SHIFT 5 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_WIDTH 1 /* VRX_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_MASK 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_SHIFT 4 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_MASK 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_SHIFT 3 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTRVOL_TO_HPOUT2 */ - -/* - * R52 (0x34) - Line Mixer1 - */ -#define WM8993_MIXOUTL_TO_LINEOUT1N 0x0040 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_MASK 0x0040 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_SHIFT 6 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_WIDTH 1 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N 0x0020 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_MASK 0x0020 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_SHIFT 5 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_WIDTH 1 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_LINEOUT1_MODE 0x0010 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_MASK 0x0010 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_SHIFT 4 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_WIDTH 1 /* LINEOUT1_MODE */ -#define WM8993_IN1R_TO_LINEOUT1P 0x0004 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_MASK 0x0004 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_SHIFT 2 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_WIDTH 1 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P 0x0002 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_MASK 0x0002 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_SHIFT 1 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_WIDTH 1 /* IN1L_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P 0x0001 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_MASK 0x0001 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_SHIFT 0 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_WIDTH 1 /* MIXOUTL_TO_LINEOUT1P */ - -/* - * R53 (0x35) - Line Mixer2 - */ -#define WM8993_MIXOUTR_TO_LINEOUT2N 0x0040 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_MASK 0x0040 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_SHIFT 6 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_WIDTH 1 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N 0x0020 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_MASK 0x0020 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_SHIFT 5 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_WIDTH 1 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_LINEOUT2_MODE 0x0010 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_MASK 0x0010 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_SHIFT 4 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_WIDTH 1 /* LINEOUT2_MODE */ -#define WM8993_IN1L_TO_LINEOUT2P 0x0004 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_MASK 0x0004 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_SHIFT 2 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_WIDTH 1 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P 0x0002 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_MASK 0x0002 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_SHIFT 1 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_WIDTH 1 /* IN1R_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P 0x0001 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_MASK 0x0001 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_SHIFT 0 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_WIDTH 1 /* MIXOUTR_TO_LINEOUT2P */ - -/* - * R54 (0x36) - Speaker Mixer - */ -#define WM8993_SPKAB_REF_SEL 0x0100 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_MASK 0x0100 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_SHIFT 8 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_WIDTH 1 /* SPKAB_REF_SEL */ -#define WM8993_MIXINL_TO_SPKMIXL 0x0080 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_MASK 0x0080 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_SHIFT 7 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINR_TO_SPKMIXR 0x0040 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_MASK 0x0040 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_SHIFT 6 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */ -#define WM8993_IN1LP_TO_SPKMIXL 0x0020 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_MASK 0x0020 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_SHIFT 5 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_WIDTH 1 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1RP_TO_SPKMIXR 0x0010 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_MASK 0x0010 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_SHIFT 4 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_WIDTH 1 /* IN1RP_TO_SPKMIXR */ -#define WM8993_MIXOUTL_TO_SPKMIXL 0x0008 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_MASK 0x0008 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_SHIFT 3 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_WIDTH 1 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTR_TO_SPKMIXR 0x0004 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_MASK 0x0004 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_SHIFT 2 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_WIDTH 1 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_DACL_TO_SPKMIXL 0x0002 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_MASK 0x0002 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_SHIFT 1 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */ -#define WM8993_DACR_TO_SPKMIXR 0x0001 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_MASK 0x0001 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_SHIFT 0 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */ - -/* - * R55 (0x37) - Additional Control - */ -#define WM8993_LINEOUT1_FB 0x0080 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_MASK 0x0080 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_SHIFT 7 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_WIDTH 1 /* LINEOUT1_FB */ -#define WM8993_LINEOUT2_FB 0x0040 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_MASK 0x0040 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_SHIFT 6 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_WIDTH 1 /* LINEOUT2_FB */ -#define WM8993_VROI 0x0001 /* VROI */ -#define WM8993_VROI_MASK 0x0001 /* VROI */ -#define WM8993_VROI_SHIFT 0 /* VROI */ -#define WM8993_VROI_WIDTH 1 /* VROI */ - -/* - * R56 (0x38) - AntiPOP1 - */ -#define WM8993_LINEOUT_VMID_BUF_ENA 0x0080 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_MASK 0x0080 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_SHIFT 7 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_WIDTH 1 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_HPOUT2_IN_ENA 0x0040 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_MASK 0x0040 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_SHIFT 6 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_WIDTH 1 /* HPOUT2_IN_ENA */ -#define WM8993_LINEOUT1_DISCH 0x0020 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_MASK 0x0020 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_SHIFT 5 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_WIDTH 1 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT2_DISCH 0x0010 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_MASK 0x0010 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_SHIFT 4 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_WIDTH 1 /* LINEOUT2_DISCH */ - -/* - * R57 (0x39) - AntiPOP2 - */ -#define WM8993_VMID_RAMP_MASK 0x0060 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_RAMP_SHIFT 5 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_RAMP_WIDTH 2 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ -#define WM8993_STARTUP_BIAS_ENA 0x0004 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_MASK 0x0004 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_SHIFT 2 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ -#define WM8993_BIAS_SRC 0x0002 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_MASK 0x0002 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_SHIFT 1 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_WIDTH 1 /* BIAS_SRC */ -#define WM8993_VMID_DISCH 0x0001 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_MASK 0x0001 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_SHIFT 0 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_WIDTH 1 /* VMID_DISCH */ - -/* - * R58 (0x3A) - MICBIAS - */ -#define WM8993_JD_SCTHR_MASK 0x00C0 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_SCTHR_SHIFT 6 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_SCTHR_WIDTH 2 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_THR_MASK 0x0030 /* JD_THR - [5:4] */ -#define WM8993_JD_THR_SHIFT 4 /* JD_THR - [5:4] */ -#define WM8993_JD_THR_WIDTH 2 /* JD_THR - [5:4] */ -#define WM8993_JD_ENA 0x0004 /* JD_ENA */ -#define WM8993_JD_ENA_MASK 0x0004 /* JD_ENA */ -#define WM8993_JD_ENA_SHIFT 2 /* JD_ENA */ -#define WM8993_JD_ENA_WIDTH 1 /* JD_ENA */ -#define WM8993_MICB2_LVL 0x0002 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_MASK 0x0002 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_SHIFT 1 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_WIDTH 1 /* MICB2_LVL */ -#define WM8993_MICB1_LVL 0x0001 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_MASK 0x0001 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_SHIFT 0 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_WIDTH 1 /* MICB1_LVL */ - -/* - * R60 (0x3C) - FLL Control 1 - */ -#define WM8993_FLL_FRAC 0x0004 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_SHIFT 2 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_WIDTH 1 /* FLL_FRAC */ -#define WM8993_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ -#define WM8993_FLL_ENA 0x0001 /* FLL_ENA */ -#define WM8993_FLL_ENA_MASK 0x0001 /* FLL_ENA */ -#define WM8993_FLL_ENA_SHIFT 0 /* FLL_ENA */ -#define WM8993_FLL_ENA_WIDTH 1 /* FLL_ENA */ - -/* - * R61 (0x3D) - FLL Control 2 - */ -#define WM8993_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ -#define WM8993_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ -#define WM8993_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ - -/* - * R62 (0x3E) - FLL Control 3 - */ -#define WM8993_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */ -#define WM8993_FLL_K_SHIFT 0 /* FLL_K - [15:0] */ -#define WM8993_FLL_K_WIDTH 16 /* FLL_K - [15:0] */ - -/* - * R63 (0x3F) - FLL Control 4 - */ -#define WM8993_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */ -#define WM8993_FLL_N_SHIFT 5 /* FLL_N - [14:5] */ -#define WM8993_FLL_N_WIDTH 10 /* FLL_N - [14:5] */ -#define WM8993_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */ -#define WM8993_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */ -#define WM8993_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */ - -/* - * R64 (0x40) - FLL Control 5 - */ -#define WM8993_FLL_FRC_NCO_VAL_MASK 0x1F80 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO_VAL_SHIFT 7 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO 0x0040 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_MASK 0x0040 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_SHIFT 6 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ -#define WM8993_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */ -#define WM8993_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */ -#define WM8993_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */ - -/* - * R65 (0x41) - Clocking 3 - */ -#define WM8993_CLK_DCS_DIV_MASK 0x3C00 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_CLK_DCS_DIV_SHIFT 10 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_SAMPLE_RATE_MASK 0x0380 /* SAMPLE_RATE - [9:7] */ -#define WM8993_SAMPLE_RATE_SHIFT 7 /* SAMPLE_RATE - [9:7] */ -#define WM8993_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [9:7] */ -#define WM8993_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_DSP_ENA 0x0001 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_MASK 0x0001 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_SHIFT 0 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ - -/* - * R66 (0x42) - Clocking 4 - */ -#define WM8993_DAC_DIV4 0x0200 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_MASK 0x0200 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_SHIFT 9 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_WIDTH 1 /* DAC_DIV4 */ -#define WM8993_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */ -#define WM8993_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */ -#define WM8993_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */ -#define WM8993_SR_MODE 0x0001 /* SR_MODE */ -#define WM8993_SR_MODE_MASK 0x0001 /* SR_MODE */ -#define WM8993_SR_MODE_SHIFT 0 /* SR_MODE */ -#define WM8993_SR_MODE_WIDTH 1 /* SR_MODE */ - -/* - * R67 (0x43) - MW Slave Control - */ -#define WM8993_MASK_WRITE_ENA 0x0001 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_MASK 0x0001 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_SHIFT 0 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */ - -/* - * R69 (0x45) - Bus Control 1 - */ -#define WM8993_CLK_SYS_ENA 0x0002 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_MASK 0x0002 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_SHIFT 1 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ - -/* - * R70 (0x46) - Write Sequencer 0 - */ -#define WM8993_WSEQ_ENA 0x0100 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8993_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8993_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8993_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ - -/* - * R71 (0x47) - Write Sequencer 1 - */ -#define WM8993_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM8993_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM8993_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R72 (0x48) - Write Sequencer 2 - */ -#define WM8993_WSEQ_EOS 0x4000 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM8993_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM8993_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM8993_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R73 (0x49) - Write Sequencer 3 - */ -#define WM8993_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8993_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM8993_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM8993_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM8993_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8993_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM8993_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM8993_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R74 (0x4A) - Write Sequencer 4 - */ -#define WM8993_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R75 (0x4B) - Write Sequencer 5 - */ -#define WM8993_WSEQ_CURRENT_INDEX_MASK 0x003F /* WSEQ_CURRENT_INDEX - [5:0] */ -#define WM8993_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [5:0] */ -#define WM8993_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [5:0] */ - -/* - * R76 (0x4C) - Charge Pump 1 - */ -#define WM8993_CP_ENA 0x8000 /* CP_ENA */ -#define WM8993_CP_ENA_MASK 0x8000 /* CP_ENA */ -#define WM8993_CP_ENA_SHIFT 15 /* CP_ENA */ -#define WM8993_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R81 (0x51) - Class W 0 - */ -#define WM8993_CP_DYN_FREQ 0x0002 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_MASK 0x0002 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_SHIFT 1 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_WIDTH 1 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_V 0x0001 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_MASK 0x0001 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_SHIFT 0 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_WIDTH 1 /* CP_DYN_V */ - -/* - * R84 (0x54) - DC Servo 0 - */ -#define WM8993_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_DAC_WR_1 0x0008 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_MASK 0x0008 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_SHIFT 3 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_0 0x0004 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_MASK 0x0004 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_SHIFT 2 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ - -/* - * R85 (0x55) - DC Servo 1 - */ -#define WM8993_DCS_SERIES_NO_01_MASK 0x0FE0 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_SERIES_NO_01_SHIFT 5 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8993_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8993_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ - -/* - * R87 (0x57) - DC Servo 3 - */ -#define WM8993_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8993_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8993_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ - -/* - * R88 (0x58) - DC Servo Readback 0 - */ -#define WM8993_DCS_DATAPATH_BUSY 0x4000 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_MASK 0x4000 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_SHIFT 14 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_WIDTH 1 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_CHANNEL_MASK 0x3000 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CHANNEL_SHIFT 12 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CHANNEL_WIDTH 2 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CAL_COMPLETE_MASK 0x0300 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_CAL_COMPLETE_WIDTH 2 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_DAC_WR_COMPLETE_MASK 0x0030 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_DAC_WR_COMPLETE_WIDTH 2 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_STARTUP_COMPLETE_MASK 0x0003 /* DCS_STARTUP_COMPLETE - [1:0] */ -#define WM8993_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [1:0] */ -#define WM8993_DCS_STARTUP_COMPLETE_WIDTH 2 /* DCS_STARTUP_COMPLETE - [1:0] */ - -/* - * R89 (0x59) - DC Servo Readback 1 - */ -#define WM8993_DCS_INTEG_CHAN_1_MASK 0x00FF /* DCS_INTEG_CHAN_1 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_1_SHIFT 0 /* DCS_INTEG_CHAN_1 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_1_WIDTH 8 /* DCS_INTEG_CHAN_1 - [7:0] */ - -/* - * R90 (0x5A) - DC Servo Readback 2 - */ -#define WM8993_DCS_INTEG_CHAN_0_MASK 0x00FF /* DCS_INTEG_CHAN_0 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_0_SHIFT 0 /* DCS_INTEG_CHAN_0 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_0_WIDTH 8 /* DCS_INTEG_CHAN_0 - [7:0] */ - -/* - * R96 (0x60) - Analogue HP 0 - */ -#define WM8993_HPOUT1_AUTO_PU 0x0100 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_MASK 0x0100 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_SHIFT 8 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_WIDTH 1 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */ - -/* - * R98 (0x62) - EQ1 - */ -#define WM8993_EQ_ENA 0x0001 /* EQ_ENA */ -#define WM8993_EQ_ENA_MASK 0x0001 /* EQ_ENA */ -#define WM8993_EQ_ENA_SHIFT 0 /* EQ_ENA */ -#define WM8993_EQ_ENA_WIDTH 1 /* EQ_ENA */ - -/* - * R99 (0x63) - EQ2 - */ -#define WM8993_EQ_B1_GAIN_MASK 0x001F /* EQ_B1_GAIN - [4:0] */ -#define WM8993_EQ_B1_GAIN_SHIFT 0 /* EQ_B1_GAIN - [4:0] */ -#define WM8993_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [4:0] */ - -/* - * R100 (0x64) - EQ3 - */ -#define WM8993_EQ_B2_GAIN_MASK 0x001F /* EQ_B2_GAIN - [4:0] */ -#define WM8993_EQ_B2_GAIN_SHIFT 0 /* EQ_B2_GAIN - [4:0] */ -#define WM8993_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [4:0] */ - -/* - * R101 (0x65) - EQ4 - */ -#define WM8993_EQ_B3_GAIN_MASK 0x001F /* EQ_B3_GAIN - [4:0] */ -#define WM8993_EQ_B3_GAIN_SHIFT 0 /* EQ_B3_GAIN - [4:0] */ -#define WM8993_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [4:0] */ - -/* - * R102 (0x66) - EQ5 - */ -#define WM8993_EQ_B4_GAIN_MASK 0x001F /* EQ_B4_GAIN - [4:0] */ -#define WM8993_EQ_B4_GAIN_SHIFT 0 /* EQ_B4_GAIN - [4:0] */ -#define WM8993_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [4:0] */ - -/* - * R103 (0x67) - EQ6 - */ -#define WM8993_EQ_B5_GAIN_MASK 0x001F /* EQ_B5_GAIN - [4:0] */ -#define WM8993_EQ_B5_GAIN_SHIFT 0 /* EQ_B5_GAIN - [4:0] */ -#define WM8993_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [4:0] */ - -/* - * R104 (0x68) - EQ7 - */ -#define WM8993_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */ -#define WM8993_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */ -#define WM8993_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */ - -/* - * R105 (0x69) - EQ8 - */ -#define WM8993_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */ -#define WM8993_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */ -#define WM8993_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */ - -/* - * R106 (0x6A) - EQ9 - */ -#define WM8993_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */ -#define WM8993_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */ -#define WM8993_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */ - -/* - * R107 (0x6B) - EQ10 - */ -#define WM8993_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */ -#define WM8993_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */ -#define WM8993_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */ - -/* - * R108 (0x6C) - EQ11 - */ -#define WM8993_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */ -#define WM8993_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */ -#define WM8993_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */ - -/* - * R109 (0x6D) - EQ12 - */ -#define WM8993_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */ -#define WM8993_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */ -#define WM8993_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */ - -/* - * R110 (0x6E) - EQ13 - */ -#define WM8993_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */ -#define WM8993_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */ -#define WM8993_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */ - -/* - * R111 (0x6F) - EQ14 - */ -#define WM8993_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */ -#define WM8993_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */ -#define WM8993_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */ - -/* - * R112 (0x70) - EQ15 - */ -#define WM8993_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */ -#define WM8993_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */ -#define WM8993_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */ - -/* - * R113 (0x71) - EQ16 - */ -#define WM8993_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */ -#define WM8993_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */ -#define WM8993_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */ - -/* - * R114 (0x72) - EQ17 - */ -#define WM8993_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */ -#define WM8993_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */ -#define WM8993_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */ - -/* - * R115 (0x73) - EQ18 - */ -#define WM8993_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */ -#define WM8993_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */ -#define WM8993_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */ - -/* - * R116 (0x74) - EQ19 - */ -#define WM8993_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */ -#define WM8993_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */ -#define WM8993_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */ - -/* - * R117 (0x75) - EQ20 - */ -#define WM8993_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */ -#define WM8993_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */ -#define WM8993_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */ - -/* - * R118 (0x76) - EQ21 - */ -#define WM8993_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */ -#define WM8993_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */ -#define WM8993_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */ - -/* - * R119 (0x77) - EQ22 - */ -#define WM8993_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */ -#define WM8993_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */ -#define WM8993_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */ - -/* - * R120 (0x78) - EQ23 - */ -#define WM8993_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */ -#define WM8993_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */ -#define WM8993_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */ - -/* - * R121 (0x79) - EQ24 - */ -#define WM8993_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */ -#define WM8993_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */ -#define WM8993_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */ - -/* - * R122 (0x7A) - Digital Pulls - */ -#define WM8993_MCLK_PU 0x0080 /* MCLK_PU */ -#define WM8993_MCLK_PU_MASK 0x0080 /* MCLK_PU */ -#define WM8993_MCLK_PU_SHIFT 7 /* MCLK_PU */ -#define WM8993_MCLK_PU_WIDTH 1 /* MCLK_PU */ -#define WM8993_MCLK_PD 0x0040 /* MCLK_PD */ -#define WM8993_MCLK_PD_MASK 0x0040 /* MCLK_PD */ -#define WM8993_MCLK_PD_SHIFT 6 /* MCLK_PD */ -#define WM8993_MCLK_PD_WIDTH 1 /* MCLK_PD */ -#define WM8993_DACDAT_PU 0x0020 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_MASK 0x0020 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_SHIFT 5 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_WIDTH 1 /* DACDAT_PU */ -#define WM8993_DACDAT_PD 0x0010 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_MASK 0x0010 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_SHIFT 4 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_WIDTH 1 /* DACDAT_PD */ -#define WM8993_LRCLK_PU 0x0008 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_MASK 0x0008 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_SHIFT 3 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_WIDTH 1 /* LRCLK_PU */ -#define WM8993_LRCLK_PD 0x0004 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_MASK 0x0004 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_SHIFT 2 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_WIDTH 1 /* LRCLK_PD */ -#define WM8993_BCLK_PU 0x0002 /* BCLK_PU */ -#define WM8993_BCLK_PU_MASK 0x0002 /* BCLK_PU */ -#define WM8993_BCLK_PU_SHIFT 1 /* BCLK_PU */ -#define WM8993_BCLK_PU_WIDTH 1 /* BCLK_PU */ -#define WM8993_BCLK_PD 0x0001 /* BCLK_PD */ -#define WM8993_BCLK_PD_MASK 0x0001 /* BCLK_PD */ -#define WM8993_BCLK_PD_SHIFT 0 /* BCLK_PD */ -#define WM8993_BCLK_PD_WIDTH 1 /* BCLK_PD */ - -/* - * R123 (0x7B) - DRC Control 1 - */ -#define WM8993_DRC_ENA 0x8000 /* DRC_ENA */ -#define WM8993_DRC_ENA_MASK 0x8000 /* DRC_ENA */ -#define WM8993_DRC_ENA_SHIFT 15 /* DRC_ENA */ -#define WM8993_DRC_ENA_WIDTH 1 /* DRC_ENA */ -#define WM8993_DRC_DAC_PATH 0x4000 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_MASK 0x4000 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_SHIFT 14 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_WIDTH 1 /* DRC_DAC_PATH */ -#define WM8993_DRC_SMOOTH_ENA 0x0800 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_MASK 0x0800 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_SHIFT 11 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_WIDTH 1 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_QR_ENA 0x0400 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_MASK 0x0400 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_SHIFT 10 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_WIDTH 1 /* DRC_QR_ENA */ -#define WM8993_DRC_ANTICLIP_ENA 0x0200 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_MASK 0x0200 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_SHIFT 9 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_WIDTH 1 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_HYST_ENA 0x0100 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_MASK 0x0100 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_SHIFT 8 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_WIDTH 1 /* DRC_HYST_ENA */ -#define WM8993_DRC_THRESH_HYST_MASK 0x0030 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_THRESH_HYST_SHIFT 4 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_THRESH_HYST_WIDTH 2 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ -#define WM8993_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ -#define WM8993_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ - -/* - * R124 (0x7C) - DRC Control 2 - */ -#define WM8993_DRC_ATTACK_RATE_MASK 0xF000 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_ATTACK_RATE_SHIFT 12 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_ATTACK_RATE_WIDTH 4 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_DECAY_RATE_MASK 0x0F00 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_DECAY_RATE_SHIFT 8 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_DECAY_RATE_WIDTH 4 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_THRESH_COMP_MASK 0x00FC /* DRC_THRESH_COMP - [7:2] */ -#define WM8993_DRC_THRESH_COMP_SHIFT 2 /* DRC_THRESH_COMP - [7:2] */ -#define WM8993_DRC_THRESH_COMP_WIDTH 6 /* DRC_THRESH_COMP - [7:2] */ - -/* - * R125 (0x7D) - DRC Control 3 - */ -#define WM8993_DRC_AMP_COMP_MASK 0xF800 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_AMP_COMP_SHIFT 11 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_AMP_COMP_WIDTH 5 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_R0_SLOPE_COMP_MASK 0x0700 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_R0_SLOPE_COMP_SHIFT 8 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_R0_SLOPE_COMP_WIDTH 3 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_FF_DELAY 0x0080 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_MASK 0x0080 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_SHIFT 7 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */ -#define WM8993_DRC_THRESH_QR_MASK 0x000C /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_THRESH_QR_SHIFT 2 /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_THRESH_QR_WIDTH 2 /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_RATE_QR_MASK 0x0003 /* DRC_RATE_QR - [1:0] */ -#define WM8993_DRC_RATE_QR_SHIFT 0 /* DRC_RATE_QR - [1:0] */ -#define WM8993_DRC_RATE_QR_WIDTH 2 /* DRC_RATE_QR - [1:0] */ - -/* - * R126 (0x7E) - DRC Control 4 - */ -#define WM8993_DRC_R1_SLOPE_COMP_MASK 0xE000 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_R1_SLOPE_COMP_SHIFT 13 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_R1_SLOPE_COMP_WIDTH 3 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_STARTUP_GAIN_MASK 0x1F00 /* DRC_STARTUP_GAIN - [12:8] */ -#define WM8993_DRC_STARTUP_GAIN_SHIFT 8 /* DRC_STARTUP_GAIN - [12:8] */ -#define WM8993_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [12:8] */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8994.c b/ANDROID_3.4.5/sound/soc/codecs/wm8994.c deleted file mode 100644 index ab30c796..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8994.c +++ /dev/null @@ -1,4391 +0,0 @@ -/* - * wm8994.c -- WM8994 ALSA SoC Audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "wm8994.h" -#include "wm_hubs.h" - -#define WM1811_JACKDET_MODE_NONE 0x0000 -#define WM1811_JACKDET_MODE_JACK 0x0100 -#define WM1811_JACKDET_MODE_MIC 0x0080 -#define WM1811_JACKDET_MODE_AUDIO 0x0180 - -#define WM8994_NUM_DRC 3 -#define WM8994_NUM_EQ 3 - -static int aif1clk_on = 1; -static struct proc_dir_entry *wm8994_proc; - -static struct { - unsigned int reg; - unsigned int mask; -} wm8994_vu_bits[] = { - { WM8994_LEFT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, - { WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, - { WM8994_LEFT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, - { WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, - { WM8994_SPEAKER_VOLUME_LEFT, WM8994_SPKOUT_VU }, - { WM8994_SPEAKER_VOLUME_RIGHT, WM8994_SPKOUT_VU }, - { WM8994_LEFT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, - { WM8994_RIGHT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, - { WM8994_LEFT_OPGA_VOLUME, WM8994_MIXOUT_VU }, - { WM8994_RIGHT_OPGA_VOLUME, WM8994_MIXOUT_VU }, - - { WM8994_AIF1_DAC1_LEFT_VOLUME, WM8994_AIF1DAC1_VU }, - { WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU }, - { WM8994_AIF1_DAC2_LEFT_VOLUME, WM8994_AIF1DAC2_VU }, - { WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU }, - { WM8994_AIF2_DAC_LEFT_VOLUME, WM8994_AIF2DAC_VU }, - { WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU }, - { WM8994_AIF1_ADC1_LEFT_VOLUME, WM8994_AIF1ADC1_VU }, - { WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU }, - { WM8994_AIF1_ADC2_LEFT_VOLUME, WM8994_AIF1ADC2_VU }, - { WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, - { WM8994_AIF2_ADC_LEFT_VOLUME, WM8994_AIF2ADC_VU }, - { WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, - { WM8994_DAC1_LEFT_VOLUME, WM8994_DAC1_VU }, - { WM8994_DAC1_RIGHT_VOLUME, WM8994_DAC1_VU }, - { WM8994_DAC2_LEFT_VOLUME, WM8994_DAC2_VU }, - { WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU }, -}; - -static int wm8994_drc_base[] = { - WM8994_AIF1_DRC1_1, - WM8994_AIF1_DRC2_1, - WM8994_AIF2_DRC_1, -}; - -static int wm8994_retune_mobile_base[] = { - WM8994_AIF1_DAC1_EQ_GAINS_1, - WM8994_AIF1_DAC2_EQ_GAINS_1, - WM8994_AIF2_EQ_GAINS_1, -}; - -static void wm8958_default_micdet(u16 status, void *data); - -static const struct wm8958_micd_rate micdet_rates[] = { - { 32768, true, 1, 4 }, - { 32768, false, 1, 1 }, - { 44100 * 256, true, 7, 10 }, - { 44100 * 256, false, 7, 10 }, -}; - -static const struct wm8958_micd_rate jackdet_rates[] = { - { 32768, true, 0, 1 }, - { 32768, false, 0, 1 }, - { 44100 * 256, true, 7, 10 }, - { 44100 * 256, false, 7, 10 }, -}; - -static void wm8958_micd_set_rate(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int best, i, sysclk, val; - bool idle; - const struct wm8958_micd_rate *rates; - int num_rates; - - if (wm8994->jack_cb != wm8958_default_micdet) - return; - - idle = !wm8994->jack_mic; - - sysclk = snd_soc_read(codec, WM8994_CLOCKING_1); - if (sysclk & WM8994_SYSCLK_SRC) - sysclk = wm8994->aifclk[1]; - else - sysclk = wm8994->aifclk[0]; - - if (wm8994->pdata && wm8994->pdata->micd_rates) { - rates = wm8994->pdata->micd_rates; - num_rates = wm8994->pdata->num_micd_rates; - } else if (wm8994->jackdet) { - rates = jackdet_rates; - num_rates = ARRAY_SIZE(jackdet_rates); - } else { - rates = micdet_rates; - num_rates = ARRAY_SIZE(micdet_rates); - } - - best = 0; - for (i = 0; i < num_rates; i++) { - if (rates[i].idle != idle) - continue; - if (abs(rates[i].sysclk - sysclk) < - abs(rates[best].sysclk - sysclk)) - best = i; - else if (rates[best].idle != idle) - best = i; - } - - val = rates[best].start << WM8958_MICD_BIAS_STARTTIME_SHIFT - | rates[best].rate << WM8958_MICD_RATE_SHIFT; - - snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, - WM8958_MICD_BIAS_STARTTIME_MASK | - WM8958_MICD_RATE_MASK, val); -} - -static int configure_aif_clock(struct snd_soc_codec *codec, int aif) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int rate; - int reg1 = 0; - int offset; - - if (aif) - offset = 4; - else - offset = 0; - - switch (wm8994->sysclk[aif]) { - case WM8994_SYSCLK_MCLK1: - rate = wm8994->mclk[0]; - break; - - case WM8994_SYSCLK_MCLK2: - reg1 |= 0x8; - rate = wm8994->mclk[1]; - break; - - case WM8994_SYSCLK_FLL1: - reg1 |= 0x10; - rate = wm8994->fll[0].out; - break; - - case WM8994_SYSCLK_FLL2: - reg1 |= 0x18; - rate = wm8994->fll[1].out; - break; - - default: - return -EINVAL; - } - - if (rate >= 13500000) { - rate /= 2; - reg1 |= WM8994_AIF1CLK_DIV; - - dev_dbg(codec->dev, "Dividing AIF%d clock to %dHz\n", - aif + 1, rate); - } - - wm8994->aifclk[aif] = rate; - - snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1 + offset, - WM8994_AIF1CLK_SRC_MASK | WM8994_AIF1CLK_DIV, - reg1); - - return 0; -} - -static int configure_clock(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int change, new; - - /* Bring up the AIF clocks first */ - configure_aif_clock(codec, 0); - configure_aif_clock(codec, 1); - - /* Then switch CLK_SYS over to the higher of them; a change - * can only happen as a result of a clocking change which can - * only be made outside of DAPM so we can safely redo the - * clocking. - */ - - /* If they're equal it doesn't matter which is used */ - if (wm8994->aifclk[0] == wm8994->aifclk[1]) { - wm8958_micd_set_rate(codec); - return 0; - } - - if (wm8994->aifclk[0] < wm8994->aifclk[1]) - new = WM8994_SYSCLK_SRC; - else - new = 0; - - change = snd_soc_update_bits(codec, WM8994_CLOCKING_1, - WM8994_SYSCLK_SRC, new); - if (change) - snd_soc_dapm_sync(&codec->dapm); - - wm8958_micd_set_rate(codec); - - return 0; -} - -static int check_clk_sys(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - int reg = snd_soc_read(source->codec, WM8994_CLOCKING_1); - const char *clk; - - /* Check what we're currently using for CLK_SYS */ - if (reg & WM8994_SYSCLK_SRC) - clk = "AIF2CLK"; - else - clk = "AIF1CLK"; - - return strcmp(source->name, clk) == 0; -} - -static const char *sidetone_hpf_text[] = { - "2.7kHz", "1.35kHz", "675Hz", "370Hz", "180Hz", "90Hz", "45Hz" -}; - -static const struct soc_enum sidetone_hpf = - SOC_ENUM_SINGLE(WM8994_SIDETONE, 7, 7, sidetone_hpf_text); - -static const char *adc_hpf_text[] = { - "HiFi", "Voice 1", "Voice 2", "Voice 3" -}; - -static const struct soc_enum aif1adc1_hpf = - SOC_ENUM_SINGLE(WM8994_AIF1_ADC1_FILTERS, 13, 4, adc_hpf_text); - -static const struct soc_enum aif1adc2_hpf = - SOC_ENUM_SINGLE(WM8994_AIF1_ADC2_FILTERS, 13, 4, adc_hpf_text); - -static const struct soc_enum aif2adc_hpf = - SOC_ENUM_SINGLE(WM8994_AIF2_ADC_FILTERS, 13, 4, adc_hpf_text); - -static const DECLARE_TLV_DB_SCALE(aif_tlv, 0, 600, 0); -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); -static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); -static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0); - -#define WM8994_DRC_SWITCH(xname, reg, shift) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ - .put = wm8994_put_drc_sw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, 1, 0) } - -static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int mask, ret; - - /* Can't enable both ADC and DAC paths simultaneously */ - if (mc->shift == WM8994_AIF1DAC1_DRC_ENA_SHIFT) - mask = WM8994_AIF1ADC1L_DRC_ENA_MASK | - WM8994_AIF1ADC1R_DRC_ENA_MASK; - else - mask = WM8994_AIF1DAC1_DRC_ENA_MASK; - - ret = snd_soc_read(codec, mc->reg); - if (ret < 0) - return ret; - if (ret & mask) - return -EINVAL; - - return snd_soc_put_volsw(kcontrol, ucontrol); -} - -static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int base = wm8994_drc_base[drc]; - int cfg = wm8994->drc_cfg[drc]; - int save, i; - - /* Save any enables; the configuration should clear them. */ - save = snd_soc_read(codec, base); - save &= WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | - WM8994_AIF1ADC1R_DRC_ENA; - - for (i = 0; i < WM8994_DRC_REGS; i++) - snd_soc_update_bits(codec, base + i, 0xffff, - pdata->drc_cfgs[cfg].regs[i]); - - snd_soc_update_bits(codec, base, WM8994_AIF1DAC1_DRC_ENA | - WM8994_AIF1ADC1L_DRC_ENA | - WM8994_AIF1ADC1R_DRC_ENA, save); -} - -/* Icky as hell but saves code duplication */ -static int wm8994_get_drc(const char *name) -{ - if (strcmp(name, "AIF1DRC1 Mode") == 0) - return 0; - if (strcmp(name, "AIF1DRC2 Mode") == 0) - return 1; - if (strcmp(name, "AIF2DRC Mode") == 0) - return 2; - return -EINVAL; -} - -static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int drc = wm8994_get_drc(kcontrol->id.name); - int value = ucontrol->value.integer.value[0]; - - if (drc < 0) - return drc; - - if (value >= pdata->num_drc_cfgs) - return -EINVAL; - - wm8994->drc_cfg[drc] = value; - - wm8994_set_drc(codec, drc); - - return 0; -} - -static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int drc = wm8994_get_drc(kcontrol->id.name); - - ucontrol->value.enumerated.item[0] = wm8994->drc_cfg[drc]; - - return 0; -} - -static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int base = wm8994_retune_mobile_base[block]; - int iface, best, best_val, save, i, cfg; - - if (!pdata || !wm8994->num_retune_mobile_texts) - return; - - switch (block) { - case 0: - case 1: - iface = 0; - break; - case 2: - iface = 1; - break; - default: - return; - } - - /* Find the version of the currently selected configuration - * with the nearest sample rate. */ - cfg = wm8994->retune_mobile_cfg[block]; - best = 0; - best_val = INT_MAX; - for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { - if (strcmp(pdata->retune_mobile_cfgs[i].name, - wm8994->retune_mobile_texts[cfg]) == 0 && - abs(pdata->retune_mobile_cfgs[i].rate - - wm8994->dac_rates[iface]) < best_val) { - best = i; - best_val = abs(pdata->retune_mobile_cfgs[i].rate - - wm8994->dac_rates[iface]); - } - } - - dev_dbg(codec->dev, "ReTune Mobile %d %s/%dHz for %dHz sample rate\n", - block, - pdata->retune_mobile_cfgs[best].name, - pdata->retune_mobile_cfgs[best].rate, - wm8994->dac_rates[iface]); - - /* The EQ will be disabled while reconfiguring it, remember the - * current configuration. - */ - save = snd_soc_read(codec, base); - save &= WM8994_AIF1DAC1_EQ_ENA; - - for (i = 0; i < WM8994_EQ_REGS; i++) - snd_soc_update_bits(codec, base + i, 0xffff, - pdata->retune_mobile_cfgs[best].regs[i]); - - snd_soc_update_bits(codec, base, WM8994_AIF1DAC1_EQ_ENA, save); -} - -/* Icky as hell but saves code duplication */ -static int wm8994_get_retune_mobile_block(const char *name) -{ - if (strcmp(name, "AIF1.1 EQ Mode") == 0) - return 0; - if (strcmp(name, "AIF1.2 EQ Mode") == 0) - return 1; - if (strcmp(name, "AIF2 EQ Mode") == 0) - return 2; - return -EINVAL; -} - -static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_pdata *pdata = wm8994->pdata; - int block = wm8994_get_retune_mobile_block(kcontrol->id.name); - int value = ucontrol->value.integer.value[0]; - - if (block < 0) - return block; - - if (value >= pdata->num_retune_mobile_cfgs) - return -EINVAL; - - wm8994->retune_mobile_cfg[block] = value; - - wm8994_set_retune_mobile(codec, block); - - return 0; -} - -static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int block = wm8994_get_retune_mobile_block(kcontrol->id.name); - - ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; - - return 0; -} - -static const char *aif_chan_src_text[] = { - "Left", "Right" -}; - -static const char *aif_mono_text[] = { - "Stereo", "Mono" -}; - -static const struct soc_enum aif1adcl_src = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 15, 2, aif_chan_src_text); - -static const struct soc_enum aif1adcr_src = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_1, 14, 2, aif_chan_src_text); - -static const struct soc_enum aif2adcl_src = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 15, 2, aif_chan_src_text); - -static const struct soc_enum aif2adcr_src = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_1, 14, 2, aif_chan_src_text); - -static const struct soc_enum aif1dacl_src = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aif_chan_src_text); - -static const struct soc_enum aif1dacr_src = - SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aif_chan_src_text); - -static const struct soc_enum aif2dacl_src = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aif_chan_src_text); - -static const struct soc_enum aif2dacr_src = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aif_chan_src_text); - -static const struct soc_enum aif2dac_mono = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 8, 2, aif_mono_text); - -static const char *osr_text[] = { - "Low Power", "High Performance", -}; - -static const struct soc_enum dac_osr = - SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 0, 2, osr_text); - -static const struct soc_enum adc_osr = - SOC_ENUM_SINGLE(WM8994_OVERSAMPLING, 1, 2, osr_text); - -static const char *compand_mode_text[] = { - "u-law", "a-law", -}; - -static const struct soc_enum aif2dac_compand_mode = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 3, 2, compand_mode_text); - -static const struct soc_enum aif2adc_compand_mode = - SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 1, 2, compand_mode_text); - -static const struct snd_kcontrol_new wm8994_snd_controls[] = { -SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, - WM8994_AIF1_ADC1_RIGHT_VOLUME, - 1, 119, 0, digital_tlv), -SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME, - WM8994_AIF1_ADC2_RIGHT_VOLUME, - 1, 119, 0, digital_tlv), -SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME, - WM8994_AIF2_ADC_RIGHT_VOLUME, - 1, 119, 0, digital_tlv), - -SOC_ENUM("AIF1ADCL Source", aif1adcl_src), -SOC_ENUM("AIF1ADCR Source", aif1adcr_src), -SOC_ENUM("AIF2ADCL Source", aif2adcl_src), -SOC_ENUM("AIF2ADCR Source", aif2adcr_src), - -SOC_ENUM("AIF1DACL Source", aif1dacl_src), -SOC_ENUM("AIF1DACR Source", aif1dacr_src), -SOC_ENUM("AIF2DACL Source", aif2dacl_src), -SOC_ENUM("AIF2DACR Source", aif2dacr_src), - -SOC_ENUM("AIF2DAC Mono", aif2dac_mono), - -SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME, - WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv), -SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME, - WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv), -SOC_DOUBLE_R_TLV("AIF2DAC Volume", WM8994_AIF2_DAC_LEFT_VOLUME, - WM8994_AIF2_DAC_RIGHT_VOLUME, 1, 96, 0, digital_tlv), - -SOC_SINGLE_TLV("AIF1 Boost Volume", WM8994_AIF1_CONTROL_2, 10, 3, 0, aif_tlv), -SOC_SINGLE_TLV("AIF2 Boost Volume", WM8994_AIF2_CONTROL_2, 10, 3, 0, aif_tlv), - -SOC_SINGLE("AIF1DAC1 EQ Switch", WM8994_AIF1_DAC1_EQ_GAINS_1, 0, 1, 0), -SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0), -SOC_SINGLE("AIF2 EQ Switch", WM8994_AIF2_EQ_GAINS_1, 0, 1, 0), - -WM8994_DRC_SWITCH("AIF1DAC1 DRC Switch", WM8994_AIF1_DRC1_1, 2), -WM8994_DRC_SWITCH("AIF1ADC1L DRC Switch", WM8994_AIF1_DRC1_1, 1), -WM8994_DRC_SWITCH("AIF1ADC1R DRC Switch", WM8994_AIF1_DRC1_1, 0), - -WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2), -WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1), -WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0), - -WM8994_DRC_SWITCH("AIF2DAC DRC Switch", WM8994_AIF2_DRC_1, 2), -WM8994_DRC_SWITCH("AIF2ADCL DRC Switch", WM8994_AIF2_DRC_1, 1), -WM8994_DRC_SWITCH("AIF2ADCR DRC Switch", WM8994_AIF2_DRC_1, 0), - -SOC_SINGLE_TLV("DAC1 Right Sidetone Volume", WM8994_DAC1_MIXER_VOLUMES, - 5, 12, 0, st_tlv), -SOC_SINGLE_TLV("DAC1 Left Sidetone Volume", WM8994_DAC1_MIXER_VOLUMES, - 0, 12, 0, st_tlv), -SOC_SINGLE_TLV("DAC2 Right Sidetone Volume", WM8994_DAC2_MIXER_VOLUMES, - 5, 12, 0, st_tlv), -SOC_SINGLE_TLV("DAC2 Left Sidetone Volume", WM8994_DAC2_MIXER_VOLUMES, - 0, 12, 0, st_tlv), -SOC_ENUM("Sidetone HPF Mux", sidetone_hpf), -SOC_SINGLE("Sidetone HPF Switch", WM8994_SIDETONE, 6, 1, 0), - -SOC_ENUM("AIF1ADC1 HPF Mode", aif1adc1_hpf), -SOC_DOUBLE("AIF1ADC1 HPF Switch", WM8994_AIF1_ADC1_FILTERS, 12, 11, 1, 0), - -SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf), -SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0), - -SOC_ENUM("AIF2ADC HPF Mode", aif2adc_hpf), -SOC_DOUBLE("AIF2ADC HPF Switch", WM8994_AIF2_ADC_FILTERS, 12, 11, 1, 0), - -SOC_ENUM("ADC OSR", adc_osr), -SOC_ENUM("DAC OSR", dac_osr), - -SOC_DOUBLE_R_TLV("DAC1 Volume", WM8994_DAC1_LEFT_VOLUME, - WM8994_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv), -SOC_DOUBLE_R("DAC1 Switch", WM8994_DAC1_LEFT_VOLUME, - WM8994_DAC1_RIGHT_VOLUME, 9, 1, 1), - -SOC_DOUBLE_R_TLV("DAC2 Volume", WM8994_DAC2_LEFT_VOLUME, - WM8994_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv), -SOC_DOUBLE_R("DAC2 Switch", WM8994_DAC2_LEFT_VOLUME, - WM8994_DAC2_RIGHT_VOLUME, 9, 1, 1), - -SOC_SINGLE_TLV("SPKL DAC2 Volume", WM8994_SPKMIXL_ATTENUATION, - 6, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKL DAC1 Volume", WM8994_SPKMIXL_ATTENUATION, - 2, 1, 1, wm_hubs_spkmix_tlv), - -SOC_SINGLE_TLV("SPKR DAC2 Volume", WM8994_SPKMIXR_ATTENUATION, - 6, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKR DAC1 Volume", WM8994_SPKMIXR_ATTENUATION, - 2, 1, 1, wm_hubs_spkmix_tlv), - -SOC_SINGLE_TLV("AIF1DAC1 3D Stereo Volume", WM8994_AIF1_DAC1_FILTERS_2, - 10, 15, 0, wm8994_3d_tlv), -SOC_SINGLE("AIF1DAC1 3D Stereo Switch", WM8994_AIF1_DAC1_FILTERS_2, - 8, 1, 0), -SOC_SINGLE_TLV("AIF1DAC2 3D Stereo Volume", WM8994_AIF1_DAC2_FILTERS_2, - 10, 15, 0, wm8994_3d_tlv), -SOC_SINGLE("AIF1DAC2 3D Stereo Switch", WM8994_AIF1_DAC2_FILTERS_2, - 8, 1, 0), -SOC_SINGLE_TLV("AIF2DAC 3D Stereo Volume", WM8994_AIF2_DAC_FILTERS_2, - 10, 15, 0, wm8994_3d_tlv), -SOC_SINGLE("AIF2DAC 3D Stereo Switch", WM8994_AIF2_DAC_FILTERS_2, - 8, 1, 0), - -SOC_SINGLE("MICBIAS2 Switch", WM8994_POWER_MANAGEMENT_1, 5, 1, 0), -SOC_SINGLE("MICBIAS1 Switch", WM8994_POWER_MANAGEMENT_1, 4, 1, 0), - -SOC_SINGLE("AIF2DAC Compand Switch", WM8994_AIF2_CONTROL_2, 4, 1, 0), -SOC_SINGLE("AIF2ADC Compand Switch", WM8994_AIF2_CONTROL_2, 2, 1, 0), - -SOC_ENUM("AIF2DAC Compand Mode", aif2dac_compand_mode), -SOC_ENUM("AIF2ADC Compand Mode", aif2adc_compand_mode), -}; - -static const struct snd_kcontrol_new wm8994_eq_controls[] = { -SOC_SINGLE_TLV("AIF1DAC1 EQ1 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF1DAC1 EQ2 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 6, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF1DAC1 EQ3 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 1, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF1DAC1 EQ4 Volume", WM8994_AIF1_DAC1_EQ_GAINS_2, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF1DAC1 EQ5 Volume", WM8994_AIF1_DAC1_EQ_GAINS_2, 6, 31, 0, - eq_tlv), - -SOC_SINGLE_TLV("AIF1DAC2 EQ1 Volume", WM8994_AIF1_DAC2_EQ_GAINS_1, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF1DAC2 EQ2 Volume", WM8994_AIF1_DAC2_EQ_GAINS_1, 6, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF1DAC2 EQ3 Volume", WM8994_AIF1_DAC2_EQ_GAINS_1, 1, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF1DAC2 EQ4 Volume", WM8994_AIF1_DAC2_EQ_GAINS_2, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF1DAC2 EQ5 Volume", WM8994_AIF1_DAC2_EQ_GAINS_2, 6, 31, 0, - eq_tlv), - -SOC_SINGLE_TLV("AIF2 EQ1 Volume", WM8994_AIF2_EQ_GAINS_1, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF2 EQ2 Volume", WM8994_AIF2_EQ_GAINS_1, 6, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF2 EQ3 Volume", WM8994_AIF2_EQ_GAINS_1, 1, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF2 EQ4 Volume", WM8994_AIF2_EQ_GAINS_2, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, - eq_tlv), -}; - -static const char *wm8958_ng_text[] = { - "30ms", "125ms", "250ms", "500ms", -}; - -static const struct soc_enum wm8958_aif1dac1_ng_hold = - SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE, - WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text); - -static const struct soc_enum wm8958_aif1dac2_ng_hold = - SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE, - WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text); - -static const struct soc_enum wm8958_aif2dac_ng_hold = - SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE, - WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text); - -static const struct snd_kcontrol_new wm8958_snd_controls[] = { -SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), - -SOC_SINGLE("AIF1DAC1 Noise Gate Switch", WM8958_AIF1_DAC1_NOISE_GATE, - WM8958_AIF1DAC1_NG_ENA_SHIFT, 1, 0), -SOC_ENUM("AIF1DAC1 Noise Gate Hold Time", wm8958_aif1dac1_ng_hold), -SOC_SINGLE_TLV("AIF1DAC1 Noise Gate Threshold Volume", - WM8958_AIF1_DAC1_NOISE_GATE, WM8958_AIF1DAC1_NG_THR_SHIFT, - 7, 1, ng_tlv), - -SOC_SINGLE("AIF1DAC2 Noise Gate Switch", WM8958_AIF1_DAC2_NOISE_GATE, - WM8958_AIF1DAC2_NG_ENA_SHIFT, 1, 0), -SOC_ENUM("AIF1DAC2 Noise Gate Hold Time", wm8958_aif1dac2_ng_hold), -SOC_SINGLE_TLV("AIF1DAC2 Noise Gate Threshold Volume", - WM8958_AIF1_DAC2_NOISE_GATE, WM8958_AIF1DAC2_NG_THR_SHIFT, - 7, 1, ng_tlv), - -SOC_SINGLE("AIF2DAC Noise Gate Switch", WM8958_AIF2_DAC_NOISE_GATE, - WM8958_AIF2DAC_NG_ENA_SHIFT, 1, 0), -SOC_ENUM("AIF2DAC Noise Gate Hold Time", wm8958_aif2dac_ng_hold), -SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume", - WM8958_AIF2_DAC_NOISE_GATE, WM8958_AIF2DAC_NG_THR_SHIFT, - 7, 1, ng_tlv), -}; - -static const struct snd_kcontrol_new wm1811_snd_controls[] = { -SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0, - mixin_boost_tlv), -SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0, - mixin_boost_tlv), -}; - -/* We run all mode setting through a function to enforce audio mode */ -static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - if (!wm8994->jackdet || !wm8994->jack_cb) - return; - - if (wm8994->active_refcount) - mode = WM1811_JACKDET_MODE_AUDIO; - - if (mode == wm8994->jackdet_mode) - return; - - wm8994->jackdet_mode = mode; - - /* Always use audio mode to detect while the system is active */ - if (mode != WM1811_JACKDET_MODE_NONE) - mode = WM1811_JACKDET_MODE_AUDIO; - - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM1811_JACKDET_MODE_MASK, mode); -} - -static void active_reference(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - mutex_lock(&wm8994->accdet_lock); - - wm8994->active_refcount++; - - dev_dbg(codec->dev, "Active refcount incremented, now %d\n", - wm8994->active_refcount); - - /* If we're using jack detection go into audio mode */ - wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_AUDIO); - - mutex_unlock(&wm8994->accdet_lock); -} - -static void active_dereference(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - u16 mode; - - mutex_lock(&wm8994->accdet_lock); - - wm8994->active_refcount--; - - dev_dbg(codec->dev, "Active refcount decremented, now %d\n", - wm8994->active_refcount); - - if (wm8994->active_refcount == 0) { - /* Go into appropriate detection only mode */ - if (wm8994->jack_mic || wm8994->mic_detecting) - mode = WM1811_JACKDET_MODE_MIC; - else - mode = WM1811_JACKDET_MODE_JACK; - - wm1811_jackdet_set_mode(codec, mode); - } - - mutex_unlock(&wm8994->accdet_lock); -} - -static int clk_sys_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - return configure_clock(codec); - - case SND_SOC_DAPM_POST_PMD: - configure_clock(codec); - break; - } - - return 0; -} - -static void vmid_reference(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - pm_runtime_get_sync(codec->dev); - - wm8994->vmid_refcount++; - - dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n", - wm8994->vmid_refcount); - - if (wm8994->vmid_refcount == 1) { - snd_soc_update_bits(codec, WM8994_ANTIPOP_1, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH, 0); - - wm_hubs_vmid_ena(codec); - - switch (wm8994->vmid_mode) { - default: - WARN_ON(0 == "Invalid VMID mode"); - case WM8994_VMID_NORMAL: - /* Startup bias, VMID ramp & buffer */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_BIAS_SRC | - WM8994_VMID_DISCH | - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - WM8994_VMID_RAMP_MASK, - WM8994_BIAS_SRC | - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - (0x3 << WM8994_VMID_RAMP_SHIFT)); - - /* Main bias enable, VMID=2x40k */ - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, - WM8994_BIAS_ENA | - WM8994_VMID_SEL_MASK, - WM8994_BIAS_ENA | 0x2); - - msleep(50); - - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_VMID_RAMP_MASK | - WM8994_BIAS_SRC, - 0); - break; - - case WM8994_VMID_FORCE: - /* Startup bias, slow VMID ramp & buffer */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_BIAS_SRC | - WM8994_VMID_DISCH | - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - WM8994_VMID_RAMP_MASK, - WM8994_BIAS_SRC | - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - (0x2 << WM8994_VMID_RAMP_SHIFT)); - - /* Main bias enable, VMID=2x40k */ - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, - WM8994_BIAS_ENA | - WM8994_VMID_SEL_MASK, - WM8994_BIAS_ENA | 0x2); - - msleep(400); - - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_VMID_RAMP_MASK | - WM8994_BIAS_SRC, - 0); - break; - } - } -} - -static void vmid_dereference(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - wm8994->vmid_refcount--; - - dev_dbg(codec->dev, "Dereferencing VMID, refcount is now %d\n", - wm8994->vmid_refcount); - - if (wm8994->vmid_refcount == 0) { - if (wm8994->hubs.lineout1_se) - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3, - WM8994_LINEOUT1N_ENA | - WM8994_LINEOUT1P_ENA, - WM8994_LINEOUT1N_ENA | - WM8994_LINEOUT1P_ENA); - - if (wm8994->hubs.lineout2_se) - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3, - WM8994_LINEOUT2N_ENA | - WM8994_LINEOUT2P_ENA, - WM8994_LINEOUT2N_ENA | - WM8994_LINEOUT2P_ENA); - - /* Start discharging VMID */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_BIAS_SRC | - WM8994_VMID_DISCH, - WM8994_BIAS_SRC | - WM8994_VMID_DISCH); - - switch (wm8994->vmid_mode) { - case WM8994_VMID_FORCE: - msleep(350); - break; - default: - break; - } - - snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL, - WM8994_VROI, WM8994_VROI); - - /* Active discharge */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_1, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH); - - msleep(150); - - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3, - WM8994_LINEOUT1N_ENA | - WM8994_LINEOUT1P_ENA | - WM8994_LINEOUT2N_ENA | - WM8994_LINEOUT2P_ENA, 0); - - snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL, - WM8994_VROI, 0); - - /* Switch off startup biases */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_BIAS_SRC | - WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - WM8994_VMID_RAMP_MASK, 0); - - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, - WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0); - - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_VMID_RAMP_MASK, 0); - } - - pm_runtime_put(codec->dev); -} - -static int vmid_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - vmid_reference(codec); - break; - - case SND_SOC_DAPM_POST_PMD: - vmid_dereference(codec); - break; - } - - return 0; -} - -static void wm8994_update_class_w(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int enable = 1; - int source = 0; /* GCC flow analysis can't track enable */ - int reg, reg_r; - - /* Only support direct DAC->headphone paths */ - reg = snd_soc_read(codec, WM8994_OUTPUT_MIXER_1); - if (!(reg & WM8994_DAC1L_TO_HPOUT1L)) { - dev_vdbg(codec->dev, "HPL connected to output mixer\n"); - enable = 0; - } - - reg = snd_soc_read(codec, WM8994_OUTPUT_MIXER_2); - if (!(reg & WM8994_DAC1R_TO_HPOUT1R)) { - dev_vdbg(codec->dev, "HPR connected to output mixer\n"); - enable = 0; - } - - /* We also need the same setting for L/R and only one path */ - reg = snd_soc_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); - switch (reg) { - case WM8994_AIF2DACL_TO_DAC1L: - dev_vdbg(codec->dev, "Class W source AIF2DAC\n"); - source = 2 << WM8994_CP_DYN_SRC_SEL_SHIFT; - break; - case WM8994_AIF1DAC2L_TO_DAC1L: - dev_vdbg(codec->dev, "Class W source AIF1DAC2\n"); - source = 1 << WM8994_CP_DYN_SRC_SEL_SHIFT; - break; - case WM8994_AIF1DAC1L_TO_DAC1L: - dev_vdbg(codec->dev, "Class W source AIF1DAC1\n"); - source = 0 << WM8994_CP_DYN_SRC_SEL_SHIFT; - break; - default: - dev_vdbg(codec->dev, "DAC mixer setting: %x\n", reg); - enable = 0; - break; - } - - reg_r = snd_soc_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); - if (reg_r != reg) { - dev_vdbg(codec->dev, "Left and right DAC mixers different\n"); - enable = 0; - } - - if (enable) { - dev_dbg(codec->dev, "Class W enabled\n"); - snd_soc_update_bits(codec, WM8994_CLASS_W_1, - WM8994_CP_DYN_PWR | - WM8994_CP_DYN_SRC_SEL_MASK, - source | WM8994_CP_DYN_PWR); - wm8994->hubs.class_w = true; - - } else { - dev_dbg(codec->dev, "Class W disabled\n"); - snd_soc_update_bits(codec, WM8994_CLASS_W_1, - WM8994_CP_DYN_PWR, 0); - wm8994->hubs.class_w = false; - } -} - -static int aif1clk_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8994 *control = codec->control_data; - int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; - int i; - int dac; - int adc; - int val; - - switch (control->type) { - case WM8994: - case WM8958: - mask |= WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA; - break; - default: - break; - } - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1); - if ((val & WM8994_AIF1ADCL_SRC) && - (val & WM8994_AIF1ADCR_SRC)) - adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA; - else if (!(val & WM8994_AIF1ADCL_SRC) && - !(val & WM8994_AIF1ADCR_SRC)) - adc = WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; - else - adc = WM8994_AIF1ADC1R_ENA | WM8994_AIF1ADC2R_ENA | - WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC2L_ENA; - - val = snd_soc_read(codec, WM8994_AIF1_CONTROL_2); - if ((val & WM8994_AIF1DACL_SRC) && - (val & WM8994_AIF1DACR_SRC)) - dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA; - else if (!(val & WM8994_AIF1DACL_SRC) && - !(val & WM8994_AIF1DACR_SRC)) - dac = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC2L_ENA; - else - dac = WM8994_AIF1DAC1R_ENA | WM8994_AIF1DAC2R_ENA | - WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC2L_ENA; - - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, - mask, adc); - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, - mask, dac); - snd_soc_update_bits(codec, WM8994_CLOCKING_1, - WM8994_AIF1DSPCLK_ENA | - WM8994_SYSDSPCLK_ENA, - WM8994_AIF1DSPCLK_ENA | - WM8994_SYSDSPCLK_ENA); - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, mask, - WM8994_AIF1ADC1R_ENA | - WM8994_AIF1ADC1L_ENA | - WM8994_AIF1ADC2R_ENA | - WM8994_AIF1ADC2L_ENA); - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, mask, - WM8994_AIF1DAC1R_ENA | - WM8994_AIF1DAC1L_ENA | - WM8994_AIF1DAC2R_ENA | - WM8994_AIF1DAC2L_ENA); - break; - - case SND_SOC_DAPM_POST_PMU: - for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) - snd_soc_write(codec, wm8994_vu_bits[i].reg, - snd_soc_read(codec, - wm8994_vu_bits[i].reg)); - break; - - case SND_SOC_DAPM_PRE_PMD: - case SND_SOC_DAPM_POST_PMD: - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, - mask, 0); - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, - mask, 0); - - val = snd_soc_read(codec, WM8994_CLOCKING_1); - if (val & WM8994_AIF2DSPCLK_ENA) - val = WM8994_SYSDSPCLK_ENA; - else - val = 0; - snd_soc_update_bits(codec, WM8994_CLOCKING_1, - WM8994_SYSDSPCLK_ENA | - WM8994_AIF1DSPCLK_ENA, val); - break; - } - - return 0; -} - -static int aif2clk_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - int i; - int dac; - int adc; - int val; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - val = snd_soc_read(codec, WM8994_AIF2_CONTROL_1); - if ((val & WM8994_AIF2ADCL_SRC) && - (val & WM8994_AIF2ADCR_SRC)) - adc = WM8994_AIF2ADCR_ENA; - else if (!(val & WM8994_AIF2ADCL_SRC) && - !(val & WM8994_AIF2ADCR_SRC)) - adc = WM8994_AIF2ADCL_ENA; - else - adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA; - - - val = snd_soc_read(codec, WM8994_AIF2_CONTROL_2); - if ((val & WM8994_AIF2DACL_SRC) && - (val & WM8994_AIF2DACR_SRC)) - dac = WM8994_AIF2DACR_ENA; - else if (!(val & WM8994_AIF2DACL_SRC) && - !(val & WM8994_AIF2DACR_SRC)) - dac = WM8994_AIF2DACL_ENA; - else - dac = WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA; - - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, - WM8994_AIF2ADCL_ENA | - WM8994_AIF2ADCR_ENA, adc); - /*snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, - WM8994_AIF2DACL_ENA | - WM8994_AIF2DACR_ENA, dac);*/ - snd_soc_update_bits(codec, WM8994_CLOCKING_1, - WM8994_AIF2DSPCLK_ENA | - WM8994_SYSDSPCLK_ENA, - WM8994_AIF2DSPCLK_ENA | - WM8994_SYSDSPCLK_ENA); - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, - WM8994_AIF2ADCL_ENA | - WM8994_AIF2ADCR_ENA, - WM8994_AIF2ADCL_ENA | - WM8994_AIF2ADCR_ENA); - /*snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, - WM8994_AIF2DACL_ENA | - WM8994_AIF2DACR_ENA, - WM8994_AIF2DACL_ENA | - WM8994_AIF2DACR_ENA);*/ - break; - - case SND_SOC_DAPM_POST_PMU: - for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) - snd_soc_write(codec, wm8994_vu_bits[i].reg, - snd_soc_read(codec, - wm8994_vu_bits[i].reg)); - break; - - case SND_SOC_DAPM_PRE_PMD: - case SND_SOC_DAPM_POST_PMD: - /*snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, - WM8994_AIF2DACL_ENA | - WM8994_AIF2DACR_ENA, 0);*/ - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_4, - WM8994_AIF2ADCL_ENA | - WM8994_AIF2ADCR_ENA, 0); - - val = snd_soc_read(codec, WM8994_CLOCKING_1); - if (val & WM8994_AIF1DSPCLK_ENA) - val = WM8994_SYSDSPCLK_ENA; - else - val = 0; - snd_soc_update_bits(codec, WM8994_CLOCKING_1, - WM8994_SYSDSPCLK_ENA | - WM8994_AIF2DSPCLK_ENA, val); - break; - } - - return 0; -} - -static int aif1clk_late_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - wm8994->aif1clk_enable = 1; - break; - case SND_SOC_DAPM_POST_PMD: - wm8994->aif1clk_disable = 1; - break; - } - - return 0; -} - -static int aif2clk_late_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - wm8994->aif2clk_enable = 1; - break; - case SND_SOC_DAPM_POST_PMD: - wm8994->aif2clk_disable = 1; - break; - } - - return 0; -} - -static int late_enable_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - if (wm8994->aif1clk_enable) { - aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); - snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, - WM8994_AIF1CLK_ENA_MASK, - WM8994_AIF1CLK_ENA); - aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); - wm8994->aif1clk_enable = 0; - } - if (wm8994->aif2clk_enable) { - aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); - snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, - WM8994_AIF2CLK_ENA_MASK, - WM8994_AIF2CLK_ENA); - aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); - wm8994->aif2clk_enable = 0; - } - break; - } - - /* We may also have postponed startup of DSP, handle that. */ - wm8958_aif_ev(w, kcontrol, event); - - return 0; -} - -static int late_disable_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_POST_PMD: - if (wm8994->aif1clk_disable) { - - aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); - if (!aif1clk_on){ - snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, - WM8994_AIF1CLK_ENA_MASK, 0); - } - aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); - - wm8994->aif1clk_disable = 0; - } - if (wm8994->aif2clk_disable) { - aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); - snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, - WM8994_AIF2CLK_ENA_MASK, 0); - aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); - wm8994->aif2clk_disable = 0; - } - break; - } - - return 0; -} - -static int adc_mux_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - late_enable_ev(w, kcontrol, event); - return 0; -} - -static int micbias_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - late_enable_ev(w, kcontrol, event); - return 0; -} - -static int dac_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - unsigned int mask = 1 << w->shift; - - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, - mask, mask); - return 0; -} - -static const char *hp_mux_text[] = { - "Mixer", - "DAC", -}; - -#define WM8994_HP_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_double, \ - .put = wm8994_put_hp_enum, \ - .private_value = (unsigned long)&xenum } - -static int wm8994_put_hp_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *w = wlist->widgets[0]; - struct snd_soc_codec *codec = w->codec; - int ret; - - ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); - - wm8994_update_class_w(codec); - - return ret; -} - -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_1, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpl_mux = - WM8994_HP_ENUM("Left Headphone Mux", hpl_enum); - -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_2, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpr_mux = - WM8994_HP_ENUM("Right Headphone Mux", hpr_enum); - -static const char *adc_mux_text[] = { - "ADC", - "DMIC", -}; - -static const struct soc_enum adc_enum = - SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); - -static const struct snd_kcontrol_new adcl_mux = - SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); - -static const struct snd_kcontrol_new adcr_mux = - SOC_DAPM_ENUM_VIRT("ADCR Mux", adc_enum); - -static const struct snd_kcontrol_new left_speaker_mixer[] = { -SOC_DAPM_SINGLE("DAC2 Switch", WM8994_SPEAKER_MIXER, 9, 1, 0), -SOC_DAPM_SINGLE("Input Switch", WM8994_SPEAKER_MIXER, 7, 1, 0), -SOC_DAPM_SINGLE("IN1LP Switch", WM8994_SPEAKER_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8994_SPEAKER_MIXER, 3, 1, 0), -SOC_DAPM_SINGLE("DAC1 Switch", WM8994_SPEAKER_MIXER, 1, 1, 0), -}; - -static const struct snd_kcontrol_new right_speaker_mixer[] = { -SOC_DAPM_SINGLE("DAC2 Switch", WM8994_SPEAKER_MIXER, 8, 1, 0), -SOC_DAPM_SINGLE("Input Switch", WM8994_SPEAKER_MIXER, 6, 1, 0), -SOC_DAPM_SINGLE("IN1RP Switch", WM8994_SPEAKER_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8994_SPEAKER_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("DAC1 Switch", WM8994_SPEAKER_MIXER, 0, 1, 0), -}; - -/* Debugging; dump chip status after DAPM transitions */ -static int post_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - dev_dbg(codec->dev, "SRC status: %x\n", - snd_soc_read(codec, - WM8994_RATE_STATUS)); - return 0; -} - -static const struct snd_kcontrol_new aif1adc1l_mix[] = { -SOC_DAPM_SINGLE("ADC/DMIC Switch", WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif1adc1r_mix[] = { -SOC_DAPM_SINGLE("ADC/DMIC Switch", WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif1adc2l_mix[] = { -SOC_DAPM_SINGLE("DMIC Switch", WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif1adc2r_mix[] = { -SOC_DAPM_SINGLE("DMIC Switch", WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif2dac2l_mix[] = { -SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, - 5, 1, 0), -SOC_DAPM_SINGLE("Left Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, - 4, 1, 0), -SOC_DAPM_SINGLE("AIF2 Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, - 2, 1, 0), -SOC_DAPM_SINGLE("AIF1.2 Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif2dac2r_mix[] = { -SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, - 5, 1, 0), -SOC_DAPM_SINGLE("Left Sidetone Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, - 4, 1, 0), -SOC_DAPM_SINGLE("AIF2 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, - 2, 1, 0), -SOC_DAPM_SINGLE("AIF1.2 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -#define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = wm8994_put_class_w, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - -static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *w = wlist->widgets[0]; - struct snd_soc_codec *codec = w->codec; - int ret; - - ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); - - wm8994_update_class_w(codec); - - return ret; -} - -static const struct snd_kcontrol_new dac1l_mix[] = { -WM8994_CLASS_W_SWITCH("Right Sidetone Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, - 5, 1, 0), -WM8994_CLASS_W_SWITCH("Left Sidetone Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, - 4, 1, 0), -WM8994_CLASS_W_SWITCH("AIF2 Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, - 2, 1, 0), -WM8994_CLASS_W_SWITCH("AIF1.2 Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, - 1, 1, 0), -WM8994_CLASS_W_SWITCH("AIF1.1 Switch", WM8994_DAC1_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new dac1r_mix[] = { -WM8994_CLASS_W_SWITCH("Right Sidetone Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, - 5, 1, 0), -WM8994_CLASS_W_SWITCH("Left Sidetone Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, - 4, 1, 0), -WM8994_CLASS_W_SWITCH("AIF2 Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, - 2, 1, 0), -WM8994_CLASS_W_SWITCH("AIF1.2 Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, - 1, 1, 0), -WM8994_CLASS_W_SWITCH("AIF1.1 Switch", WM8994_DAC1_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const char *sidetone_text[] = { - "ADC/DMIC1", "DMIC2", -}; - -static const struct soc_enum sidetone1_enum = - SOC_ENUM_SINGLE(WM8994_SIDETONE, 0, 2, sidetone_text); - -static const struct snd_kcontrol_new sidetone1_mux = - SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); - -static const struct soc_enum sidetone2_enum = - SOC_ENUM_SINGLE(WM8994_SIDETONE, 1, 2, sidetone_text); - -static const struct snd_kcontrol_new sidetone2_mux = - SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); - -static const char *aif1dac_text[] = { - "AIF1DACDAT", "AIF3DACDAT", -}; - -static const struct soc_enum aif1dac_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); - -static const struct snd_kcontrol_new aif1dac_mux = - SOC_DAPM_ENUM("AIF1DAC Mux", aif1dac_enum); - -static const char *aif2dac_text[] = { - "AIF2DACDAT", "AIF3DACDAT", -}; - -static const struct soc_enum aif2dac_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 1, 2, aif2dac_text); - -static const struct snd_kcontrol_new aif2dac_mux = - SOC_DAPM_ENUM("AIF2DAC Mux", aif2dac_enum); - -static const char *aif2adc_text[] = { - "AIF2ADCDAT", "AIF3DACDAT", -}; - -static const struct soc_enum aif2adc_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 2, 2, aif2adc_text); - -static const struct snd_kcontrol_new aif2adc_mux = - SOC_DAPM_ENUM("AIF2ADC Mux", aif2adc_enum); - -static const char *aif3adc_text[] = { - "AIF1ADCDAT", "AIF2ADCDAT", "AIF2DACDAT", "Mono PCM", -}; - -static const struct soc_enum wm8994_aif3adc_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 3, aif3adc_text); - -static const struct snd_kcontrol_new wm8994_aif3adc_mux = - SOC_DAPM_ENUM("AIF3ADC Mux", wm8994_aif3adc_enum); - -static const struct soc_enum wm8958_aif3adc_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 3, 4, aif3adc_text); - -static const struct snd_kcontrol_new wm8958_aif3adc_mux = - SOC_DAPM_ENUM("AIF3ADC Mux", wm8958_aif3adc_enum); - -static const char *mono_pcm_out_text[] = { - "None", "AIF2ADCL", "AIF2ADCR", -}; - -static const struct soc_enum mono_pcm_out_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 9, 3, mono_pcm_out_text); - -static const struct snd_kcontrol_new mono_pcm_out_mux = - SOC_DAPM_ENUM("Mono PCM Out Mux", mono_pcm_out_enum); - -static const char *aif2dac_src_text[] = { - "AIF2", "AIF3", -}; - -/* Note that these two control shouldn't be simultaneously switched to AIF3 */ -static const struct soc_enum aif2dacl_src_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 7, 2, aif2dac_src_text); - -static const struct snd_kcontrol_new aif2dacl_src_mux = - SOC_DAPM_ENUM("AIF2DACL Mux", aif2dacl_src_enum); - -static const struct soc_enum aif2dacr_src_enum = - SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 8, 2, aif2dac_src_text); - -static const struct snd_kcontrol_new aif2dacr_src_mux = - SOC_DAPM_ENUM("AIF2DACR Mux", aif2dacr_src_enum); - -static const struct snd_soc_dapm_widget wm8994_lateclk_revd_widgets[] = { -SND_SOC_DAPM_SUPPLY("AIF1CLK", SND_SOC_NOPM, 0, 0, aif1clk_late_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_SUPPLY("AIF2CLK", SND_SOC_NOPM, 0, 0, aif2clk_late_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_PGA_E("Late DAC1L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, - late_enable_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_PGA_E("Late DAC1R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, - late_enable_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_PGA_E("Late DAC2L Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, - late_enable_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_PGA_E("Late DAC2R Enable PGA", SND_SOC_NOPM, 0, 0, NULL, 0, - late_enable_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_PGA_E("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0, - late_enable_ev, SND_SOC_DAPM_PRE_PMU), - -SND_SOC_DAPM_MIXER_E("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, - left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer), - late_enable_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, - right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer), - late_enable_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux, - late_enable_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux, - late_enable_ev, SND_SOC_DAPM_PRE_PMU), - -SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) -}; - -static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { -SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, - left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), -SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, - right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), -SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), -SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), -}; - -static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { -SND_SOC_DAPM_DAC_E("DAC2L", NULL, SND_SOC_NOPM, 3, 0, - dac_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_DAC_E("DAC2R", NULL, SND_SOC_NOPM, 2, 0, - dac_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_DAC_E("DAC1L", NULL, SND_SOC_NOPM, 1, 0, - dac_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_DAC_E("DAC1R", NULL, SND_SOC_NOPM, 0, 0, - dac_ev, SND_SOC_DAPM_PRE_PMU), -}; - -static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = { -SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), -SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), -SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), -SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), -}; - -static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = { -SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux, - adc_mux_ev, SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux, - adc_mux_ev, SND_SOC_DAPM_PRE_PMU), -}; - -static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = { -SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux), -SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux), -}; - -static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("DMIC1DAT"), -SND_SOC_DAPM_INPUT("DMIC2DAT"), -SND_SOC_DAPM_INPUT("Clock"), - -SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, - SND_SOC_DAPM_PRE_PMU), -SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPINTCLK", SND_SOC_NOPM, 1, 0, NULL, 0), - -SND_SOC_DAPM_AIF_OUT("AIF1ADC1L", NULL, - 0, SND_SOC_NOPM, 9, 0), -SND_SOC_DAPM_AIF_OUT("AIF1ADC1R", NULL, - 0, SND_SOC_NOPM, 8, 0), -SND_SOC_DAPM_AIF_IN_E("AIF1DAC1L", NULL, 0, - SND_SOC_NOPM, 9, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_AIF_IN_E("AIF1DAC1R", NULL, 0, - SND_SOC_NOPM, 8, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_AIF_OUT("AIF1ADC2L", NULL, - 0, SND_SOC_NOPM, 11, 0), -SND_SOC_DAPM_AIF_OUT("AIF1ADC2R", NULL, - 0, SND_SOC_NOPM, 10, 0), -SND_SOC_DAPM_AIF_IN_E("AIF1DAC2L", NULL, 0, - SND_SOC_NOPM, 11, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_AIF_IN_E("AIF1DAC2R", NULL, 0, - SND_SOC_NOPM, 10, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer", SND_SOC_NOPM, 0, 0, - aif1adc1l_mix, ARRAY_SIZE(aif1adc1l_mix)), -SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer", SND_SOC_NOPM, 0, 0, - aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)), - -SND_SOC_DAPM_MIXER("AIF1ADC2L Mixer", SND_SOC_NOPM, 0, 0, - aif1adc2l_mix, ARRAY_SIZE(aif1adc2l_mix)), -SND_SOC_DAPM_MIXER("AIF1ADC2R Mixer", SND_SOC_NOPM, 0, 0, - aif1adc2r_mix, ARRAY_SIZE(aif1adc2r_mix)), - -SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer", SND_SOC_NOPM, 0, 0, - aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)), -SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0, - aif2dac2r_mix, ARRAY_SIZE(aif2dac2r_mix)), - -SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &sidetone1_mux), -SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &sidetone2_mux), - -SND_SOC_DAPM_MIXER("DAC1L Mixer", SND_SOC_NOPM, 0, 0, - dac1l_mix, ARRAY_SIZE(dac1l_mix)), -SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SOC_NOPM, 0, 0, - dac1r_mix, ARRAY_SIZE(dac1r_mix)), - -SND_SOC_DAPM_AIF_OUT("AIF2ADCL", NULL, 0, - SND_SOC_NOPM, 13, 0), -SND_SOC_DAPM_AIF_OUT("AIF2ADCR", NULL, 0, - SND_SOC_NOPM, 12, 0), -SND_SOC_DAPM_AIF_IN_E("AIF2DACL", NULL, 0, - SND_SOC_NOPM, 13, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_AIF_IN_E("AIF2DACR", NULL, 0, - SND_SOC_NOPM, 12, 0, wm8958_aif_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_AIF_IN("AIF1DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_IN("AIF2DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_MUX("AIF1DAC Mux", SND_SOC_NOPM, 0, 0, &aif1dac_mux), -SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux), -SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux), - -SND_SOC_DAPM_AIF_IN("AIF3DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0), - -SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8994_POWER_MANAGEMENT_4, 5, 0), -SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8994_POWER_MANAGEMENT_4, 4, 0), -SND_SOC_DAPM_ADC("DMIC1L", NULL, WM8994_POWER_MANAGEMENT_4, 3, 0), -SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0), - -/* Power is done with the muxes since the ADC power also controls the - * downsampling chain, the chip will automatically manage the analogue - * specific portions. - */ -SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), -SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_POST("Debug log", post_ev), -}; - -static const struct snd_soc_dapm_widget wm8994_specific_dapm_widgets[] = { -SND_SOC_DAPM_MUX("AIF3ADC Mux", SND_SOC_NOPM, 0, 0, &wm8994_aif3adc_mux), -}; - -static const struct snd_soc_dapm_widget wm8958_dapm_widgets[] = { -SND_SOC_DAPM_MUX("Mono PCM Out Mux", SND_SOC_NOPM, 0, 0, &mono_pcm_out_mux), -SND_SOC_DAPM_MUX("AIF2DACL Mux", SND_SOC_NOPM, 0, 0, &aif2dacl_src_mux), -SND_SOC_DAPM_MUX("AIF2DACR Mux", SND_SOC_NOPM, 0, 0, &aif2dacr_src_mux), -SND_SOC_DAPM_MUX("AIF3ADC Mux", SND_SOC_NOPM, 0, 0, &wm8958_aif3adc_mux), -}; - -static const struct snd_soc_dapm_route intercon[] = { - { "CLK_SYS", NULL, "AIF1CLK", check_clk_sys }, - { "CLK_SYS", NULL, "AIF2CLK", check_clk_sys }, - - { "DSP1CLK", NULL, "CLK_SYS" }, - { "DSP2CLK", NULL, "CLK_SYS" }, - { "DSPINTCLK", NULL, "CLK_SYS" }, - - { "AIF1ADC1L", NULL, "AIF1CLK" }, - { "AIF1ADC1L", NULL, "DSP1CLK" }, - { "AIF1ADC1R", NULL, "AIF1CLK" }, - { "AIF1ADC1R", NULL, "DSP1CLK" }, - { "AIF1ADC1R", NULL, "DSPINTCLK" }, - - { "AIF1DAC1L", NULL, "AIF1CLK" }, - { "AIF1DAC1L", NULL, "DSP1CLK" }, - { "AIF1DAC1R", NULL, "AIF1CLK" }, - { "AIF1DAC1R", NULL, "DSP1CLK" }, - { "AIF1DAC1R", NULL, "DSPINTCLK" }, - - { "AIF1ADC2L", NULL, "AIF1CLK" }, - { "AIF1ADC2L", NULL, "DSP1CLK" }, - { "AIF1ADC2R", NULL, "AIF1CLK" }, - { "AIF1ADC2R", NULL, "DSP1CLK" }, - { "AIF1ADC2R", NULL, "DSPINTCLK" }, - - { "AIF1DAC2L", NULL, "AIF1CLK" }, - { "AIF1DAC2L", NULL, "DSP1CLK" }, - { "AIF1DAC2R", NULL, "AIF1CLK" }, - { "AIF1DAC2R", NULL, "DSP1CLK" }, - { "AIF1DAC2R", NULL, "DSPINTCLK" }, - - { "AIF2ADCL", NULL, "AIF2CLK" }, - { "AIF2ADCL", NULL, "DSP2CLK" }, - { "AIF2ADCR", NULL, "AIF2CLK" }, - { "AIF2ADCR", NULL, "DSP2CLK" }, - { "AIF2ADCR", NULL, "DSPINTCLK" }, - - { "AIF2DACL", NULL, "AIF2CLK" }, - { "AIF2DACL", NULL, "DSP2CLK" }, - { "AIF2DACR", NULL, "AIF2CLK" }, - { "AIF2DACR", NULL, "DSP2CLK" }, - { "AIF2DACR", NULL, "DSPINTCLK" }, - - { "DMIC1L", NULL, "DMIC1DAT" }, - { "DMIC1L", NULL, "CLK_SYS" }, - { "DMIC1R", NULL, "DMIC1DAT" }, - { "DMIC1R", NULL, "CLK_SYS" }, - { "DMIC2L", NULL, "DMIC2DAT" }, - { "DMIC2L", NULL, "CLK_SYS" }, - { "DMIC2R", NULL, "DMIC2DAT" }, - { "DMIC2R", NULL, "CLK_SYS" }, - - { "ADCL", NULL, "AIF1CLK" }, - { "ADCL", NULL, "DSP1CLK" }, - { "ADCL", NULL, "DSPINTCLK" }, - - { "ADCR", NULL, "AIF1CLK" }, - { "ADCR", NULL, "DSP1CLK" }, - { "ADCR", NULL, "DSPINTCLK" }, - - { "ADCL Mux", "ADC", "ADCL" }, - { "ADCL Mux", "DMIC", "DMIC1L" }, - { "ADCR Mux", "ADC", "ADCR" }, - { "ADCR Mux", "DMIC", "DMIC1R" }, - - { "DAC1L", NULL, "AIF1CLK" }, - { "DAC1L", NULL, "DSP1CLK" }, - { "DAC1L", NULL, "DSPINTCLK" }, - - { "DAC1R", NULL, "AIF1CLK" }, - { "DAC1R", NULL, "DSP1CLK" }, - { "DAC1R", NULL, "DSPINTCLK" }, - - { "DAC2L", NULL, "AIF2CLK" }, - { "DAC2L", NULL, "DSP2CLK" }, - { "DAC2L", NULL, "DSPINTCLK" }, - - { "DAC2R", NULL, "AIF2DACR" }, - { "DAC2R", NULL, "AIF2CLK" }, - { "DAC2R", NULL, "DSP2CLK" }, - { "DAC2R", NULL, "DSPINTCLK" }, - - { "TOCLK", NULL, "CLK_SYS" }, - - { "AIF1DACDAT", NULL, "AIF1 Playback" }, - { "AIF2DACDAT", NULL, "AIF2 Playback" }, - { "AIF3DACDAT", NULL, "AIF3 Playback" }, - - { "AIF1 Capture", NULL, "AIF1ADCDAT" }, - { "AIF2 Capture", NULL, "AIF2ADCDAT" }, - { "AIF3 Capture", NULL, "AIF3ADCDAT" }, - - /* AIF1 outputs */ - { "AIF1ADC1L", NULL, "AIF1ADC1L Mixer" }, - { "AIF1ADC1L Mixer", "ADC/DMIC Switch", "ADCL Mux" }, - { "AIF1ADC1L Mixer", "AIF2 Switch", "AIF2DACL" }, - - { "AIF1ADC1R", NULL, "AIF1ADC1R Mixer" }, - { "AIF1ADC1R Mixer", "ADC/DMIC Switch", "ADCR Mux" }, - { "AIF1ADC1R Mixer", "AIF2 Switch", "AIF2DACR" }, - - { "AIF1ADC2L", NULL, "AIF1ADC2L Mixer" }, - { "AIF1ADC2L Mixer", "DMIC Switch", "DMIC2L" }, - { "AIF1ADC2L Mixer", "AIF2 Switch", "AIF2DACL" }, - - { "AIF1ADC2R", NULL, "AIF1ADC2R Mixer" }, - { "AIF1ADC2R Mixer", "DMIC Switch", "DMIC2R" }, - { "AIF1ADC2R Mixer", "AIF2 Switch", "AIF2DACR" }, - - /* Pin level routing for AIF3 */ - { "AIF1DAC1L", NULL, "AIF1DAC Mux" }, - { "AIF1DAC1R", NULL, "AIF1DAC Mux" }, - { "AIF1DAC2L", NULL, "AIF1DAC Mux" }, - { "AIF1DAC2R", NULL, "AIF1DAC Mux" }, - - { "AIF1DAC Mux", "AIF1DACDAT", "AIF1DACDAT" }, - { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, - { "AIF2DAC Mux", "AIF2DACDAT", "AIF2DACDAT" }, - { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, - { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, - { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, - { "AIF2ADC Mux", "AIF3DACDAT", "AIF3ADCDAT" }, - - { "AIF3ADC Mux", "AIF1ADCDAT", "AIF1ADCDAT" }, - { "AIF3ADC Mux", "AIF2ADCDAT", "AIF2ADCDAT" }, - { "AIF3ADC Mux", "AIF2DACDAT", "AIF2ADCDAT" }, - - /* DAC1 inputs */ - { "DAC1L Mixer", "AIF2 Switch", "AIF2DACL" }, - { "DAC1L Mixer", "AIF1.2 Switch", "AIF1DAC2L" }, - { "DAC1L Mixer", "AIF1.1 Switch", "AIF1DAC1L" }, - { "DAC1L Mixer", "Left Sidetone Switch", "Left Sidetone" }, - { "DAC1L Mixer", "Right Sidetone Switch", "Right Sidetone" }, - - { "DAC1R Mixer", "AIF2 Switch", "AIF2DACR" }, - { "DAC1R Mixer", "AIF1.2 Switch", "AIF1DAC2R" }, - { "DAC1R Mixer", "AIF1.1 Switch", "AIF1DAC1R" }, - { "DAC1R Mixer", "Left Sidetone Switch", "Left Sidetone" }, - { "DAC1R Mixer", "Right Sidetone Switch", "Right Sidetone" }, - - /* DAC2/AIF2 outputs */ - { "AIF2ADCL", NULL, "AIF2DAC2L Mixer" }, - { "AIF2DAC2L Mixer", "AIF2 Switch", "AIF2DACL" }, - { "AIF2DAC2L Mixer", "AIF1.2 Switch", "AIF1DAC2L" }, - { "AIF2DAC2L Mixer", "AIF1.1 Switch", "AIF1DAC1L" }, - { "AIF2DAC2L Mixer", "Left Sidetone Switch", "Left Sidetone" }, - { "AIF2DAC2L Mixer", "Right Sidetone Switch", "Right Sidetone" }, - - { "AIF2ADCR", NULL, "AIF2DAC2R Mixer" }, - { "AIF2DAC2R Mixer", "AIF2 Switch", "AIF2DACR" }, - { "AIF2DAC2R Mixer", "AIF1.2 Switch", "AIF1DAC2R" }, - { "AIF2DAC2R Mixer", "AIF1.1 Switch", "AIF1DAC1R" }, - { "AIF2DAC2R Mixer", "Left Sidetone Switch", "Left Sidetone" }, - { "AIF2DAC2R Mixer", "Right Sidetone Switch", "Right Sidetone" }, - - { "AIF1ADCDAT", NULL, "AIF1ADC1L" }, - { "AIF1ADCDAT", NULL, "AIF1ADC1R" }, - { "AIF1ADCDAT", NULL, "AIF1ADC2L" }, - { "AIF1ADCDAT", NULL, "AIF1ADC2R" }, - - { "AIF2ADCDAT", NULL, "AIF2ADC Mux" }, - - /* AIF3 output */ - { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC1L" }, - { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC1R" }, - { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC2L" }, - { "AIF3ADCDAT", "AIF1ADCDAT", "AIF1ADC2R" }, - { "AIF3ADCDAT", "AIF2ADCDAT", "AIF2ADCL" }, - { "AIF3ADCDAT", "AIF2ADCDAT", "AIF2ADCR" }, - { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, - { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, - - /* Sidetone */ - { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" }, - { "Left Sidetone", "DMIC2", "DMIC2L" }, - { "Right Sidetone", "ADC/DMIC1", "ADCR Mux" }, - { "Right Sidetone", "DMIC2", "DMIC2R" }, - - /* Output stages */ - { "Left Output Mixer", "DAC Switch", "DAC1L" }, - { "Right Output Mixer", "DAC Switch", "DAC1R" }, - - { "SPKL", "DAC1 Switch", "DAC1L" }, - { "SPKL", "DAC2 Switch", "DAC2L" }, - - { "SPKR", "DAC1 Switch", "DAC1R" }, - { "SPKR", "DAC2 Switch", "DAC2R" }, - - { "Left Headphone Mux", "DAC", "DAC1L" }, - { "Right Headphone Mux", "DAC", "DAC1R" }, -}; - -static const struct snd_soc_dapm_route wm8994_lateclk_revd_intercon[] = { - { "DAC1L", NULL, "Late DAC1L Enable PGA" }, - { "Late DAC1L Enable PGA", NULL, "DAC1L Mixer" }, - { "DAC1R", NULL, "Late DAC1R Enable PGA" }, - { "Late DAC1R Enable PGA", NULL, "DAC1R Mixer" }, - { "DAC2L", NULL, "Late DAC2L Enable PGA" }, - { "Late DAC2L Enable PGA", NULL, "AIF2DAC2L Mixer" }, - { "DAC2R", NULL, "Late DAC2R Enable PGA" }, - { "Late DAC2R Enable PGA", NULL, "AIF2DAC2R Mixer" } -}; - -static const struct snd_soc_dapm_route wm8994_lateclk_intercon[] = { - { "DAC1L", NULL, "DAC1L Mixer" }, - { "DAC1R", NULL, "DAC1R Mixer" }, - { "DAC2L", NULL, "AIF2DAC2L Mixer" }, - { "DAC2R", NULL, "AIF2DAC2R Mixer" }, -}; - -static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { - { "AIF1DACDAT", NULL, "AIF2DACDAT" }, - { "AIF2DACDAT", NULL, "AIF1DACDAT" }, - { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, - { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, - { "MICBIAS1", NULL, "CLK_SYS" }, - { "MICBIAS1", NULL, "MICBIAS Supply" }, - { "MICBIAS2", NULL, "CLK_SYS" }, - { "MICBIAS2", NULL, "MICBIAS Supply" }, -}; - -static const struct snd_soc_dapm_route wm8994_intercon[] = { - { "AIF2DACL", NULL, "AIF2DAC Mux" }, - { "AIF2DACR", NULL, "AIF2DAC Mux" }, - { "MICBIAS1", NULL, "VMID" }, - { "MICBIAS2", NULL, "VMID" }, -}; - -static const struct snd_soc_dapm_route wm8958_intercon[] = { - { "AIF2DACL", NULL, "AIF2DACL Mux" }, - { "AIF2DACR", NULL, "AIF2DACR Mux" }, - - { "AIF2DACL Mux", "AIF2", "AIF2DAC Mux" }, - { "AIF2DACL Mux", "AIF3", "AIF3DACDAT" }, - { "AIF2DACR Mux", "AIF2", "AIF2DAC Mux" }, - { "AIF2DACR Mux", "AIF3", "AIF3DACDAT" }, - - { "Mono PCM Out Mux", "AIF2ADCL", "AIF2ADCL" }, - { "Mono PCM Out Mux", "AIF2ADCR", "AIF2ADCR" }, - - { "AIF3ADC Mux", "Mono PCM", "Mono PCM Out Mux" }, -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -struct fll_div { - u16 outdiv; - u16 n; - u16 k; - u16 clk_ref_div; - u16 fll_fratio; -}; - -static int wm8994_get_fll_config(struct fll_div *fll, - int freq_in, int freq_out) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod; - - pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out); - - /* Scale the input frequency down to <= 13.5MHz */ - fll->clk_ref_div = 0; - while (freq_in > 13500000) { - fll->clk_ref_div++; - freq_in /= 2; - - if (fll->clk_ref_div > 3) - return -EINVAL; - } - pr_debug("CLK_REF_DIV=%d, Fref=%dHz\n", fll->clk_ref_div, freq_in); - - /* Scale the output to give 90MHz<=Fvco<=100MHz */ - fll->outdiv = 3; - while (freq_out * (fll->outdiv + 1) < 90000000) { - fll->outdiv++; - if (fll->outdiv > 63) - return -EINVAL; - } - freq_out *= fll->outdiv + 1; - pr_debug("OUTDIV=%d, Fvco=%dHz\n", fll->outdiv, freq_out); - - if (freq_in > 1000000) { - fll->fll_fratio = 0; - } else if (freq_in > 256000) { - fll->fll_fratio = 1; - freq_in *= 2; - } else if (freq_in > 128000) { - fll->fll_fratio = 2; - freq_in *= 4; - } else if (freq_in > 64000) { - fll->fll_fratio = 3; - freq_in *= 8; - } else { - fll->fll_fratio = 4; - freq_in *= 16; - } - pr_debug("FLL_FRATIO=%d, Fref=%dHz\n", fll->fll_fratio, freq_in); - - /* Now, calculate N.K */ - Ndiv = freq_out / freq_in; - - fll->n = Ndiv; - Nmod = freq_out % freq_in; - pr_debug("Nmod=%d\n", Nmod); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, freq_in); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - fll->k = K / 10; - - pr_debug("N=%x K=%x\n", fll->n, fll->k); - - return 0; -} - -static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, - unsigned int freq_in, unsigned int freq_out) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->wm8994; - int reg_offset, ret; - struct fll_div fll; - u16 reg, aif1, aif2; - unsigned long timeout; - bool was_enabled; - - aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) - & WM8994_AIF1CLK_ENA; - - aif2 = snd_soc_read(codec, WM8994_AIF2_CLOCKING_1) - & WM8994_AIF2CLK_ENA; - - switch (id) { - case WM8994_FLL1: - reg_offset = 0; - id = 0; - break; - case WM8994_FLL2: - reg_offset = 0x20; - id = 1; - break; - default: - return -EINVAL; - } - - reg = snd_soc_read(codec, WM8994_FLL1_CONTROL_1 + reg_offset); - was_enabled = reg & WM8994_FLL1_ENA; - - switch (src) { - case 0: - /* Allow no source specification when stopping */ - if (freq_out) - return -EINVAL; - src = wm8994->fll[id].src; - break; - case WM8994_FLL_SRC_MCLK1: - case WM8994_FLL_SRC_MCLK2: - case WM8994_FLL_SRC_LRCLK: - case WM8994_FLL_SRC_BCLK: - break; - default: - return -EINVAL; - } - - /* Are we changing anything? */ - if (wm8994->fll[id].src == src && - wm8994->fll[id].in == freq_in && wm8994->fll[id].out == freq_out) - return 0; - - /* If we're stopping the FLL redo the old config - no - * registers will actually be written but we avoid GCC flow - * analysis bugs spewing warnings. - */ - if (freq_out) - ret = wm8994_get_fll_config(&fll, freq_in, freq_out); - else - ret = wm8994_get_fll_config(&fll, wm8994->fll[id].in, - wm8994->fll[id].out); - if (ret < 0) - return ret; - - /* Gate the AIF clocks while we reclock */ - snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, - WM8994_AIF1CLK_ENA, 0); - snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, - WM8994_AIF2CLK_ENA, 0); - - /* We always need to disable the FLL while reconfiguring */ - snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, - WM8994_FLL1_ENA, 0); - - reg = (fll.outdiv << WM8994_FLL1_OUTDIV_SHIFT) | - (fll.fll_fratio << WM8994_FLL1_FRATIO_SHIFT); - snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_2 + reg_offset, - WM8994_FLL1_OUTDIV_MASK | - WM8994_FLL1_FRATIO_MASK, reg); - - snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_3 + reg_offset, - WM8994_FLL1_K_MASK, fll.k); - - snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, - WM8994_FLL1_N_MASK, - fll.n << WM8994_FLL1_N_SHIFT); - - snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, - WM8994_FLL1_REFCLK_DIV_MASK | - WM8994_FLL1_REFCLK_SRC_MASK, - (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | - (src - 1)); - - /* Clear any pending completion from a previous failure */ - try_wait_for_completion(&wm8994->fll_locked[id]); - - /* Enable (with fractional mode if required) */ - if (freq_out) { - /* Enable VMID if we need it */ - if (!was_enabled) { - active_reference(codec); - - switch (control->type) { - case WM8994: - vmid_reference(codec); - break; - case WM8958: - if (wm8994->revision < 1) - vmid_reference(codec); - break; - default: - break; - } - } - - if (fll.k) - reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; - else - reg = WM8994_FLL1_ENA; - snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, - WM8994_FLL1_ENA | WM8994_FLL1_FRAC, - reg); - - if (wm8994->fll_locked_irq) { - timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], - msecs_to_jiffies(10)); - if (timeout == 0) - dev_warn(codec->dev, - "Timed out waiting for FLL lock\n"); - } else { - msleep(5); - } - } else { - if (was_enabled) { - switch (control->type) { - case WM8994: - vmid_dereference(codec); - break; - case WM8958: - if (wm8994->revision < 1) - vmid_dereference(codec); - break; - default: - break; - } - - active_dereference(codec); - } - } - - wm8994->fll[id].in = freq_in; - wm8994->fll[id].out = freq_out; - wm8994->fll[id].src = src; - - /* Enable any gated AIF clocks */ - snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, - WM8994_AIF1CLK_ENA, aif1); - snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, - WM8994_AIF2CLK_ENA, aif2); - - configure_clock(codec); - - return 0; -} - -static irqreturn_t wm8994_fll_locked_irq(int irq, void *data) -{ - struct completion *completion = data; - - complete(completion); - - return IRQ_HANDLED; -} - -static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; - -static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, - unsigned int freq_in, unsigned int freq_out) -{ - return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out); -} - -static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int i; - - switch (dai->id) { - case 1: - case 2: - break; - - default: - /* AIF3 shares clocking with AIF1/2 */ - return -EINVAL; - } - - switch (clk_id) { - case WM8994_SYSCLK_MCLK1: - wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1; - wm8994->mclk[0] = freq; - dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n", - dai->id, freq); - break; - - case WM8994_SYSCLK_MCLK2: - /* TODO: Set GPIO AF */ - wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2; - wm8994->mclk[1] = freq; - dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n", - dai->id, freq); - break; - - case WM8994_SYSCLK_FLL1: - wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_FLL1; - dev_dbg(dai->dev, "AIF%d using FLL1\n", dai->id); - break; - - case WM8994_SYSCLK_FLL2: - wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_FLL2; - dev_dbg(dai->dev, "AIF%d using FLL2\n", dai->id); - break; - - case WM8994_SYSCLK_OPCLK: - /* Special case - a division (times 10) is given and - * no effect on main clocking. - */ - if (freq) { - for (i = 0; i < ARRAY_SIZE(opclk_divs); i++) - if (opclk_divs[i] == freq) - break; - if (i == ARRAY_SIZE(opclk_divs)) - return -EINVAL; - snd_soc_update_bits(codec, WM8994_CLOCKING_2, - WM8994_OPCLK_DIV_MASK, i); - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2, - WM8994_OPCLK_ENA, WM8994_OPCLK_ENA); - } else { - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2, - WM8994_OPCLK_ENA, 0); - } - - default: - return -EINVAL; - } - - configure_clock(codec); - - return 0; -} - -static int wm8994_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->wm8994; - - wm_hubs_set_bias_level(codec, level); - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* MICBIAS into regulating mode */ - switch (control->type) { - case WM8958: - case WM1811: - snd_soc_update_bits(codec, WM8958_MICBIAS1, - WM8958_MICB1_MODE, 0); - snd_soc_update_bits(codec, WM8958_MICBIAS2, - WM8958_MICB2_MODE, 0); - break; - default: - break; - } - - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) - active_reference(codec); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - switch (control->type) { - case WM8958: - if (wm8994->revision == 0) { - /* Optimise performance for rev A */ - snd_soc_update_bits(codec, - WM8958_CHARGE_PUMP_2, - WM8958_CP_DISCH, - WM8958_CP_DISCH); - } - break; - - default: - break; - } - - /* Discharge LINEOUT1 & 2 */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_1, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH); - } - - if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) - active_dereference(codec); - - /* MICBIAS into bypass mode on newer devices */ - switch (control->type) { - case WM8958: - case WM1811: - snd_soc_update_bits(codec, WM8958_MICBIAS1, - WM8958_MICB1_MODE, - WM8958_MICB1_MODE); - snd_soc_update_bits(codec, WM8958_MICBIAS2, - WM8958_MICB2_MODE, - WM8958_MICB2_MODE); - break; - default: - break; - } - break; - - case SND_SOC_BIAS_OFF: - if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) - wm8994->cur_fw = NULL; - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - - switch (mode) { - case WM8994_VMID_NORMAL: - if (wm8994->hubs.lineout1_se) { - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT1N Driver"); - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT1P Driver"); - } - if (wm8994->hubs.lineout2_se) { - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT2N Driver"); - snd_soc_dapm_disable_pin(&codec->dapm, - "LINEOUT2P Driver"); - } - - /* Do the sync with the old mode to allow it to clean up */ - snd_soc_dapm_sync(&codec->dapm); - wm8994->vmid_mode = mode; - break; - - case WM8994_VMID_FORCE: - if (wm8994->hubs.lineout1_se) { - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT1N Driver"); - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT1P Driver"); - } - if (wm8994->hubs.lineout2_se) { - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT2N Driver"); - snd_soc_dapm_force_enable_pin(&codec->dapm, - "LINEOUT2P Driver"); - } - - wm8994->vmid_mode = mode; - snd_soc_dapm_sync(&codec->dapm); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->wm8994; - int ms_reg; - int aif1_reg; - int ms = 0; - int aif1 = 0; - - switch (dai->id) { - case 1: - ms_reg = WM8994_AIF1_MASTER_SLAVE; - aif1_reg = WM8994_AIF1_CONTROL_1; - break; - case 2: - ms_reg = WM8994_AIF2_MASTER_SLAVE; - aif1_reg = WM8994_AIF2_CONTROL_1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBM_CFM: - ms = WM8994_AIF1_MSTR; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif1 |= WM8994_AIF1_LRCLK_INV; - case SND_SOC_DAIFMT_DSP_A: - aif1 |= 0x18; - break; - case SND_SOC_DAIFMT_I2S: - aif1 |= 0x10; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif1 |= 0x8; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8994_AIF1_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8994_AIF1_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif1 |= WM8994_AIF1_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - /* The AIF2 format configuration needs to be mirrored to AIF3 - * on WM8958 if it's in use so just do it all the time. */ - switch (control->type) { - case WM1811: - case WM8958: - if (dai->id == 2) - snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1, - WM8994_AIF1_LRCLK_INV | - WM8958_AIF3_FMT_MASK, aif1); - break; - - default: - break; - } - - snd_soc_update_bits(codec, aif1_reg, - WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV | - WM8994_AIF1_FMT_MASK, - aif1); - snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR, - ms); - - return 0; -} - -static struct { - int val, rate; -} srs[] = { - { 0, 8000 }, - { 1, 11025 }, - { 2, 12000 }, - { 3, 16000 }, - { 4, 22050 }, - { 5, 24000 }, - { 6, 32000 }, - { 7, 44100 }, - { 8, 48000 }, - { 9, 88200 }, - { 10, 96000 }, -}; - -static int fs_ratios[] = { - 64, 128, 192, 256, 348, 512, 768, 1024, 1408, 1536 -}; - -static int bclk_divs[] = { - 10, 15, 20, 30, 40, 50, 60, 80, 110, 120, 160, 220, 240, 320, 440, 480, - 640, 880, 960, 1280, 1760, 1920 -}; - -static int wm8994_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int aif1_reg; - int aif2_reg; - int bclk_reg; - int lrclk_reg; - int rate_reg; - int aif1 = 0; - int aif2 = 0; - int bclk = 0; - int lrclk = 0; - int rate_val = 0; - int id = dai->id - 1; - - int i, cur_val, best_val, bclk_rate, best; - - switch (dai->id) { - case 1: - aif1_reg = WM8994_AIF1_CONTROL_1; - aif2_reg = WM8994_AIF1_CONTROL_2; - bclk_reg = WM8994_AIF1_BCLK; - rate_reg = WM8994_AIF1_RATE; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - wm8994->lrclk_shared[0]) { - lrclk_reg = WM8994_AIF1DAC_LRCLK; - } else { - lrclk_reg = WM8994_AIF1ADC_LRCLK; - dev_dbg(codec->dev, "AIF1 using split LRCLK\n"); - } - break; - case 2: - aif1_reg = WM8994_AIF2_CONTROL_1; - aif2_reg = WM8994_AIF2_CONTROL_2; - bclk_reg = WM8994_AIF2_BCLK; - rate_reg = WM8994_AIF2_RATE; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - wm8994->lrclk_shared[1]) { - lrclk_reg = WM8994_AIF2DAC_LRCLK; - } else { - lrclk_reg = WM8994_AIF2ADC_LRCLK; - dev_dbg(codec->dev, "AIF2 using split LRCLK\n"); - } - break; - default: - return -EINVAL; - } - - bclk_rate = params_rate(params) * 4; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - bclk_rate *= 16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - bclk_rate *= 20; - aif1 |= 0x20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - bclk_rate *= 24; - aif1 |= 0x40; - break; - case SNDRV_PCM_FORMAT_S32_LE: - bclk_rate *= 32; - aif1 |= 0x60; - break; - default: - return -EINVAL; - } - - /* Try to find an appropriate sample rate; look for an exact match. */ - for (i = 0; i < ARRAY_SIZE(srs); i++) - if (srs[i].rate == params_rate(params)) - break; - if (i == ARRAY_SIZE(srs)) - return -EINVAL; - rate_val |= srs[i].val << WM8994_AIF1_SR_SHIFT; - - dev_dbg(dai->dev, "Sample rate is %dHz\n", srs[i].rate); - dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n", - dai->id, wm8994->aifclk[id], bclk_rate); - - if (params_channels(params) == 1 && - (snd_soc_read(codec, aif1_reg) & 0x18) == 0x18) - aif2 |= WM8994_AIF1_MONO; - - if (wm8994->aifclk[id] == 0) { - dev_err(dai->dev, "AIF%dCLK not configured\n", dai->id); - return -EINVAL; - } - - /* AIFCLK/fs ratio; look for a close match in either direction */ - best = 0; - best_val = abs((fs_ratios[0] * params_rate(params)) - - wm8994->aifclk[id]); - for (i = 1; i < ARRAY_SIZE(fs_ratios); i++) { - cur_val = abs((fs_ratios[i] * params_rate(params)) - - wm8994->aifclk[id]); - if (cur_val >= best_val) - continue; - best = i; - best_val = cur_val; - } - dev_dbg(dai->dev, "Selected AIF%dCLK/fs = %d\n", - dai->id, fs_ratios[best]); - rate_val |= best; - - /* We may not get quite the right frequency if using - * approximate clocks so look for the closest match that is - * higher than the target (we need to ensure that there enough - * BCLKs to clock out the samples). - */ - best = 0; - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - cur_val = (wm8994->aifclk[id] * 10 / bclk_divs[i]) - bclk_rate; - if (cur_val < 0) /* BCLK table is sorted */ - break; - best = i; - } - bclk_rate = wm8994->aifclk[id] * 10 / bclk_divs[best]; - dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", - bclk_divs[best], bclk_rate); - bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT; - - lrclk = bclk_rate / params_rate(params); - if (!lrclk) { - dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n", - bclk_rate); - return -EINVAL; - } - dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", - lrclk, bclk_rate / lrclk); - - snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1); - //snd_soc_update_bits(codec, aif2_reg, WM8994_AIF1_MONO, aif2); - snd_soc_update_bits(codec, bclk_reg, WM8994_AIF1_BCLK_DIV_MASK, bclk); - snd_soc_update_bits(codec, lrclk_reg, WM8994_AIF1DAC_RATE_MASK, - lrclk); - snd_soc_update_bits(codec, rate_reg, WM8994_AIF1_SR_MASK | - WM8994_AIF1CLK_RATE_MASK, rate_val); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - switch (dai->id) { - case 1: - wm8994->dac_rates[0] = params_rate(params); - wm8994_set_retune_mobile(codec, 0); - wm8994_set_retune_mobile(codec, 1); - break; - case 2: - wm8994->dac_rates[1] = params_rate(params); - wm8994_set_retune_mobile(codec, 2); - break; - } - } - - return 0; -} - -static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->wm8994; - int aif1_reg; - int aif1 = 0; - - switch (dai->id) { - case 3: - switch (control->type) { - case WM1811: - case WM8958: - aif1_reg = WM8958_AIF3_CONTROL_1; - break; - default: - return 0; - } - default: - return 0; - } - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - aif1 |= 0x20; - break; - case SNDRV_PCM_FORMAT_S24_LE: - aif1 |= 0x40; - break; - case SNDRV_PCM_FORMAT_S32_LE: - aif1 |= 0x60; - break; - default: - return -EINVAL; - } - - return snd_soc_update_bits(codec, aif1_reg, WM8994_AIF1_WL_MASK, aif1); -} - -static void wm8994_aif_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - int rate_reg = 0; - - switch (dai->id) { - case 1: - rate_reg = WM8994_AIF1_RATE; - break; - case 2: - rate_reg = WM8994_AIF2_RATE; - break; - default: - break; - } - - /* If the DAI is idle then configure the divider tree for the - * lowest output rate to save a little power if the clock is - * still active (eg, because it is system clock). - */ - if (rate_reg && !dai->playback_active && !dai->capture_active) - snd_soc_update_bits(codec, rate_reg, - WM8994_AIF1_SR_MASK | - WM8994_AIF1CLK_RATE_MASK, 0x9); -} - -static int wm8994_aif_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int mute_reg; - int reg; - - switch (codec_dai->id) { - case 1: - mute_reg = WM8994_AIF1_DAC1_FILTERS_1; - break; - case 2: - mute_reg = WM8994_AIF2_DAC_FILTERS_1; - break; - default: - return -EINVAL; - } - - if (mute) - reg = WM8994_AIF1DAC1_MUTE; - else - reg = 0; - - snd_soc_update_bits(codec, mute_reg, WM8994_AIF1DAC1_MUTE, reg); - - return 0; -} - -static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int reg, val, mask; - - switch (codec_dai->id) { - case 1: - reg = WM8994_AIF1_MASTER_SLAVE; - mask = WM8994_AIF1_TRI; - break; - case 2: - reg = WM8994_AIF2_MASTER_SLAVE; - mask = WM8994_AIF2_TRI; - break; - case 3: - reg = WM8994_POWER_MANAGEMENT_6; - mask = WM8994_AIF3_TRI; - break; - default: - return -EINVAL; - } - - if (tristate) - val = mask; - else - val = 0; - - return snd_soc_update_bits(codec, reg, mask, val); -} - -static int wm8994_aif2_probe(struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - - /* Disable the pulls on the AIF if we're using it to save power. */ - snd_soc_update_bits(codec, WM8994_GPIO_3, - WM8994_GPN_PU | WM8994_GPN_PD, 0); - snd_soc_update_bits(codec, WM8994_GPIO_4, - WM8994_GPN_PU | WM8994_GPN_PD, 0); - snd_soc_update_bits(codec, WM8994_GPIO_5, - WM8994_GPN_PU | WM8994_GPN_PD, 0); - - return 0; -} - -#define WM8994_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8994_aif1_dai_ops = { - .set_sysclk = wm8994_set_dai_sysclk, - .set_fmt = wm8994_set_dai_fmt, - .hw_params = wm8994_hw_params, - .shutdown = wm8994_aif_shutdown, - .digital_mute = wm8994_aif_mute, - .set_pll = wm8994_set_fll, - .set_tristate = wm8994_set_tristate, -}; - -static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = { - .set_sysclk = wm8994_set_dai_sysclk, - .set_fmt = wm8994_set_dai_fmt, - .hw_params = wm8994_hw_params, - .shutdown = wm8994_aif_shutdown, - .digital_mute = wm8994_aif_mute, - .set_pll = wm8994_set_fll, - .set_tristate = wm8994_set_tristate, -}; - -static const struct snd_soc_dai_ops wm8994_aif3_dai_ops = { - .hw_params = wm8994_aif3_hw_params, - .set_tristate = wm8994_set_tristate, -}; - -static struct snd_soc_dai_driver wm8994_dai[] = { - { - .name = "wm8994-aif1", - .id = 1, - .playback = { - .stream_name = "AIF1 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8994_RATES, - .formats = WM8994_FORMATS, - .sig_bits = 24, - }, - .capture = { - .stream_name = "AIF1 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8994_RATES, - .formats = WM8994_FORMATS, - .sig_bits = 24, - }, - .ops = &wm8994_aif1_dai_ops, - }, - { - .name = "wm8994-aif2", - .id = 2, - .playback = { - .stream_name = "AIF2 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8994_RATES, - .formats = WM8994_FORMATS, - .sig_bits = 24, - }, - .capture = { - .stream_name = "AIF2 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8994_RATES, - .formats = WM8994_FORMATS, - .sig_bits = 24, - }, - .probe = wm8994_aif2_probe, - .ops = &wm8994_aif2_dai_ops, - }, - { - .name = "wm8994-aif3", - .id = 3, - .playback = { - .stream_name = "AIF3 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8994_RATES, - .formats = WM8994_FORMATS, - .sig_bits = 24, - }, - .capture = { - .stream_name = "AIF3 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8994_RATES, - .formats = WM8994_FORMATS, - .sig_bits = 24, - }, - .ops = &wm8994_aif3_dai_ops, - } -}; - -#ifdef CONFIG_PM -static int wm8994_codec_suspend(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->wm8994; - int i, ret; - - switch (control->type) { - case WM8994: - snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); - if (aif1clk_on){ - snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, - WM8994_AIF1CLK_ENA_MASK, 0); - //printk("<<<<%s\n", __FUNCTION__); - } //add 2013-7-11 - break; - case WM1811: - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM1811_JACKDET_MODE_MASK, 0); - /* Fall through */ - case WM8958: - snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, - WM8958_MICD_ENA, 0); - break; - } - - for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { - memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], - sizeof(struct wm8994_fll_config)); - ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0); - if (ret < 0) - dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", - i + 1, ret); - } - - wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8994_codec_resume(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->wm8994; - int i, ret; - unsigned int val, mask; - - if (wm8994->revision < 4) { - /* force a HW read */ - ret = regmap_read(control->regmap, - WM8994_POWER_MANAGEMENT_5, &val); - - /* modify the cache only */ - codec->cache_only = 1; - mask = WM8994_DAC1R_ENA | WM8994_DAC1L_ENA | - WM8994_DAC2R_ENA | WM8994_DAC2L_ENA; - val &= mask; - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, - mask, val); - codec->cache_only = 0; - } - - for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { - if (!wm8994->fll_suspend[i].out) - continue; - - ret = _wm8994_set_fll(codec, i + 1, - wm8994->fll_suspend[i].src, - wm8994->fll_suspend[i].in, - wm8994->fll_suspend[i].out); - if (ret < 0) - dev_warn(codec->dev, "Failed to restore FLL%d: %d\n", - i + 1, ret); - } - - switch (control->type) { - case WM8994: - if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) - snd_soc_update_bits(codec, WM8994_MICBIAS, - WM8994_MICD_ENA, WM8994_MICD_ENA); - break; - case WM1811: - if (wm8994->jackdet && wm8994->jack_cb) { - /* Restart from idle */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM1811_JACKDET_MODE_MASK, - WM1811_JACKDET_MODE_JACK); - break; - } - break; - case WM8958: - if (wm8994->jack_cb) - snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, - WM8958_MICD_ENA, WM8958_MICD_ENA); - break; - } - - return 0; -} -#else -#define wm8994_codec_suspend NULL -#define wm8994_codec_resume NULL -#endif - -static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) -{ - struct snd_soc_codec *codec = wm8994->codec; - struct wm8994_pdata *pdata = wm8994->pdata; - struct snd_kcontrol_new controls[] = { - SOC_ENUM_EXT("AIF1.1 EQ Mode", - wm8994->retune_mobile_enum, - wm8994_get_retune_mobile_enum, - wm8994_put_retune_mobile_enum), - SOC_ENUM_EXT("AIF1.2 EQ Mode", - wm8994->retune_mobile_enum, - wm8994_get_retune_mobile_enum, - wm8994_put_retune_mobile_enum), - SOC_ENUM_EXT("AIF2 EQ Mode", - wm8994->retune_mobile_enum, - wm8994_get_retune_mobile_enum, - wm8994_put_retune_mobile_enum), - }; - int ret, i, j; - const char **t; - - /* We need an array of texts for the enum API but the number - * of texts is likely to be less than the number of - * configurations due to the sample rate dependency of the - * configurations. */ - wm8994->num_retune_mobile_texts = 0; - wm8994->retune_mobile_texts = NULL; - for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { - for (j = 0; j < wm8994->num_retune_mobile_texts; j++) { - if (strcmp(pdata->retune_mobile_cfgs[i].name, - wm8994->retune_mobile_texts[j]) == 0) - break; - } - - if (j != wm8994->num_retune_mobile_texts) - continue; - - /* Expand the array... */ - t = krealloc(wm8994->retune_mobile_texts, - sizeof(char *) * - (wm8994->num_retune_mobile_texts + 1), - GFP_KERNEL); - if (t == NULL) - continue; - - /* ...store the new entry... */ - t[wm8994->num_retune_mobile_texts] = - pdata->retune_mobile_cfgs[i].name; - - /* ...and remember the new version. */ - wm8994->num_retune_mobile_texts++; - wm8994->retune_mobile_texts = t; - } - - dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", - wm8994->num_retune_mobile_texts); - - wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; - wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; - - ret = snd_soc_add_codec_controls(wm8994->codec, controls, - ARRAY_SIZE(controls)); - if (ret != 0) - dev_err(wm8994->codec->dev, - "Failed to add ReTune Mobile controls: %d\n", ret); -} - -static void wm8994_handle_pdata(struct wm8994_priv *wm8994) -{ - struct snd_soc_codec *codec = wm8994->codec; - struct wm8994_pdata *pdata = wm8994->pdata; - int ret, i; - - if (!pdata) - return; - - wm_hubs_handle_analogue_pdata(codec, pdata->lineout1_diff, - pdata->lineout2_diff, - pdata->lineout1fb, - pdata->lineout2fb, - pdata->jd_scthr, - pdata->jd_thr, - pdata->micbias1_lvl, - pdata->micbias2_lvl); - - dev_dbg(codec->dev, "%d DRC configurations\n", pdata->num_drc_cfgs); - - if (pdata->num_drc_cfgs) { - struct snd_kcontrol_new controls[] = { - SOC_ENUM_EXT("AIF1DRC1 Mode", wm8994->drc_enum, - wm8994_get_drc_enum, wm8994_put_drc_enum), - SOC_ENUM_EXT("AIF1DRC2 Mode", wm8994->drc_enum, - wm8994_get_drc_enum, wm8994_put_drc_enum), - SOC_ENUM_EXT("AIF2DRC Mode", wm8994->drc_enum, - wm8994_get_drc_enum, wm8994_put_drc_enum), - }; - - /* We need an array of texts for the enum API */ - wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev, - sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); - if (!wm8994->drc_texts) { - dev_err(wm8994->codec->dev, - "Failed to allocate %d DRC config texts\n", - pdata->num_drc_cfgs); - return; - } - - for (i = 0; i < pdata->num_drc_cfgs; i++) - wm8994->drc_texts[i] = pdata->drc_cfgs[i].name; - - wm8994->drc_enum.max = pdata->num_drc_cfgs; - wm8994->drc_enum.texts = wm8994->drc_texts; - - ret = snd_soc_add_codec_controls(wm8994->codec, controls, - ARRAY_SIZE(controls)); - if (ret != 0) - dev_err(wm8994->codec->dev, - "Failed to add DRC mode controls: %d\n", ret); - - for (i = 0; i < WM8994_NUM_DRC; i++) - wm8994_set_drc(codec, i); - } - - dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", - pdata->num_retune_mobile_cfgs); - - if (pdata->num_retune_mobile_cfgs) - wm8994_handle_retune_mobile_pdata(wm8994); - else - snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls, - ARRAY_SIZE(wm8994_eq_controls)); - - for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { - if (pdata->micbias[i]) { - snd_soc_write(codec, WM8958_MICBIAS1 + i, - pdata->micbias[i] & 0xffff); - } - } -} - -/** - * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ - * - * @codec: WM8994 codec - * @jack: jack to report detection events on - * @micbias: microphone bias to detect on - * - * Enable microphone detection via IRQ on the WM8994. If GPIOs are - * being used to bring out signals to the processor then only platform - * data configuration is needed for WM8994 and processor GPIOs should - * be configured using snd_soc_jack_add_gpios() instead. - * - * Configuration of detection levels is available via the micbias1_lvl - * and micbias2_lvl platform data members. - */ -int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - int micbias) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994_micdet *micdet; - struct wm8994 *control = wm8994->wm8994; - int reg, ret; - - if (control->type != WM8994) { - dev_warn(codec->dev, "Not a WM8994\n"); - return -EINVAL; - } - - switch (micbias) { - case 1: - micdet = &wm8994->micdet[0]; - if (jack) - ret = snd_soc_dapm_force_enable_pin(&codec->dapm, - "MICBIAS1"); - else - ret = snd_soc_dapm_disable_pin(&codec->dapm, - "MICBIAS1"); - break; - case 2: - micdet = &wm8994->micdet[1]; - if (jack) - ret = snd_soc_dapm_force_enable_pin(&codec->dapm, - "MICBIAS1"); - else - ret = snd_soc_dapm_disable_pin(&codec->dapm, - "MICBIAS1"); - break; - default: - dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias); - return -EINVAL; - } - - if (ret != 0) - dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n", - micbias, ret); - - dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n", - micbias, jack); - - /* Store the configuration */ - micdet->jack = jack; - micdet->detecting = true; - - /* If either of the jacks is set up then enable detection */ - if (wm8994->micdet[0].jack || wm8994->micdet[1].jack) - reg = WM8994_MICD_ENA; - else - reg = 0; - - snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); - - snd_soc_dapm_sync(&codec->dapm); - - return 0; -} -EXPORT_SYMBOL_GPL(wm8994_mic_detect); - -static irqreturn_t wm8994_mic_irq(int irq, void *data) -{ - struct wm8994_priv *priv = data; - struct snd_soc_codec *codec = priv->codec; - int reg; - int report; - -#ifndef CONFIG_SND_SOC_WM8994_MODULE - trace_snd_soc_jack_irq(dev_name(codec->dev)); -#endif - - reg = snd_soc_read(codec, WM8994_INTERRUPT_RAW_STATUS_2); - if (reg < 0) { - dev_err(codec->dev, "Failed to read microphone status: %d\n", - reg); - return IRQ_HANDLED; - } - - dev_dbg(codec->dev, "Microphone status: %x\n", reg); - - report = 0; - if (reg & WM8994_MIC1_DET_STS) { - if (priv->micdet[0].detecting) - report = SND_JACK_HEADSET; - } - if (reg & WM8994_MIC1_SHRT_STS) { - if (priv->micdet[0].detecting) - report = SND_JACK_HEADPHONE; - else - report |= SND_JACK_BTN_0; - } - if (report) - priv->micdet[0].detecting = false; - else - priv->micdet[0].detecting = true; - - snd_soc_jack_report(priv->micdet[0].jack, report, - SND_JACK_HEADSET | SND_JACK_BTN_0); - - report = 0; - if (reg & WM8994_MIC2_DET_STS) { - if (priv->micdet[1].detecting) - report = SND_JACK_HEADSET; - } - if (reg & WM8994_MIC2_SHRT_STS) { - if (priv->micdet[1].detecting) - report = SND_JACK_HEADPHONE; - else - report |= SND_JACK_BTN_0; - } - if (report) - priv->micdet[1].detecting = false; - else - priv->micdet[1].detecting = true; - - snd_soc_jack_report(priv->micdet[1].jack, report, - SND_JACK_HEADSET | SND_JACK_BTN_0); - - return IRQ_HANDLED; -} - -/* Default microphone detection handler for WM8958 - the user can - * override this if they wish. - */ -static void wm8958_default_micdet(u16 status, void *data) -{ - struct snd_soc_codec *codec = data; - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - int report; - - dev_dbg(codec->dev, "MICDET %x\n", status); - - /* Either nothing present or just starting detection */ - if (!(status & WM8958_MICD_STS)) { - if (!wm8994->jackdet) { - /* If nothing present then clear our statuses */ - dev_dbg(codec->dev, "Detected open circuit\n"); - wm8994->jack_mic = false; - wm8994->mic_detecting = true; - - wm8958_micd_set_rate(codec); - - snd_soc_jack_report(wm8994->micdet[0].jack, 0, - wm8994->btn_mask | - SND_JACK_HEADSET); - } - return; - } - - /* If the measurement is showing a high impedence we've got a - * microphone. - */ - if (wm8994->mic_detecting && (status & 0x600)) { - dev_dbg(codec->dev, "Detected microphone\n"); - - wm8994->mic_detecting = false; - wm8994->jack_mic = true; - - wm8958_micd_set_rate(codec); - - snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADSET, - SND_JACK_HEADSET); - } - - - if (wm8994->mic_detecting && status & 0xfc) { - dev_dbg(codec->dev, "Detected headphone\n"); - wm8994->mic_detecting = false; - - wm8958_micd_set_rate(codec); - - snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE, - SND_JACK_HEADSET); - - /* If we have jackdet that will detect removal */ - if (wm8994->jackdet) { - mutex_lock(&wm8994->accdet_lock); - - snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, - WM8958_MICD_ENA, 0); - - wm1811_jackdet_set_mode(codec, - WM1811_JACKDET_MODE_JACK); - - mutex_unlock(&wm8994->accdet_lock); - - if (wm8994->pdata->jd_ext_cap) { - mutex_lock(&codec->mutex); - snd_soc_dapm_disable_pin(&codec->dapm, - "MICBIAS2"); - snd_soc_dapm_sync(&codec->dapm); - mutex_unlock(&codec->mutex); - } - } - } - - /* Report short circuit as a button */ - if (wm8994->jack_mic) { - report = 0; - if (status & 0x4) - report |= SND_JACK_BTN_0; - - if (status & 0x8) - report |= SND_JACK_BTN_1; - - if (status & 0x10) - report |= SND_JACK_BTN_2; - - if (status & 0x20) - report |= SND_JACK_BTN_3; - - if (status & 0x40) - report |= SND_JACK_BTN_4; - - if (status & 0x80) - report |= SND_JACK_BTN_5; - - snd_soc_jack_report(wm8994->micdet[0].jack, report, - wm8994->btn_mask); - } -} - -static irqreturn_t wm1811_jackdet_irq(int irq, void *data) -{ - struct wm8994_priv *wm8994 = data; - struct snd_soc_codec *codec = wm8994->codec; - int reg; - bool present; - - mutex_lock(&wm8994->accdet_lock); - - reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); - if (reg < 0) { - dev_err(codec->dev, "Failed to read jack status: %d\n", reg); - mutex_unlock(&wm8994->accdet_lock); - return IRQ_NONE; - } - - dev_dbg(codec->dev, "JACKDET %x\n", reg); - - present = reg & WM1811_JACKDET_LVL; - - if (present) { - dev_dbg(codec->dev, "Jack detected\n"); - - snd_soc_update_bits(codec, WM8958_MICBIAS2, - WM8958_MICB2_DISCH, 0); - - /* Disable debounce while inserted */ - snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, - WM1811_JACKDET_DB, 0); - - /* - * Start off measument of microphone impedence to find - * out what's actually there. - */ - wm8994->mic_detecting = true; - wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC); - - snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, - WM8958_MICD_ENA, WM8958_MICD_ENA); - } else { - dev_dbg(codec->dev, "Jack not detected\n"); - - snd_soc_update_bits(codec, WM8958_MICBIAS2, - WM8958_MICB2_DISCH, WM8958_MICB2_DISCH); - - /* Enable debounce while removed */ - snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, - WM1811_JACKDET_DB, WM1811_JACKDET_DB); - - wm8994->mic_detecting = false; - wm8994->jack_mic = false; - snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, - WM8958_MICD_ENA, 0); - wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); - } - - mutex_unlock(&wm8994->accdet_lock); - - /* If required for an external cap force MICBIAS on */ - if (wm8994->pdata->jd_ext_cap) { - mutex_lock(&codec->mutex); - - if (present) - snd_soc_dapm_force_enable_pin(&codec->dapm, - "MICBIAS2"); - else - snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2"); - - snd_soc_dapm_sync(&codec->dapm); - mutex_unlock(&codec->mutex); - } - - if (present) - snd_soc_jack_report(wm8994->micdet[0].jack, - SND_JACK_MECHANICAL, SND_JACK_MECHANICAL); - else - snd_soc_jack_report(wm8994->micdet[0].jack, 0, - SND_JACK_MECHANICAL | SND_JACK_HEADSET | - wm8994->btn_mask); - - return IRQ_HANDLED; -} - -/** - * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ - * - * @codec: WM8958 codec - * @jack: jack to report detection events on - * - * Enable microphone detection functionality for the WM8958. By - * default simple detection which supports the detection of up to 6 - * buttons plus video and microphone functionality is supported. - * - * The WM8958 has an advanced jack detection facility which is able to - * support complex accessory detection, especially when used in - * conjunction with external circuitry. In order to provide maximum - * flexiblity a callback is provided which allows a completely custom - * detection algorithm. - */ -int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - wm8958_micdet_cb cb, void *cb_data) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->wm8994; - u16 micd_lvl_sel; - - switch (control->type) { - case WM1811: - case WM8958: - break; - default: - return -EINVAL; - } - - if (jack) { - if (!cb) { - dev_dbg(codec->dev, "Using default micdet callback\n"); - cb = wm8958_default_micdet; - cb_data = codec; - } - - snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS"); - snd_soc_dapm_sync(&codec->dapm); - - wm8994->micdet[0].jack = jack; - wm8994->jack_cb = cb; - wm8994->jack_cb_data = cb_data; - - wm8994->mic_detecting = true; - wm8994->jack_mic = false; - - wm8958_micd_set_rate(codec); - - /* Detect microphones and short circuits by default */ - if (wm8994->pdata->micd_lvl_sel) - micd_lvl_sel = wm8994->pdata->micd_lvl_sel; - else - micd_lvl_sel = 0x41; - - wm8994->btn_mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3 | - SND_JACK_BTN_4 | SND_JACK_BTN_5; - - snd_soc_update_bits(codec, WM8958_MIC_DETECT_2, - WM8958_MICD_LVL_SEL_MASK, micd_lvl_sel); - - WARN_ON(codec->dapm.bias_level > SND_SOC_BIAS_STANDBY); - - /* - * If we can use jack detection start off with that, - * otherwise jump straight to microphone detection. - */ - if (wm8994->jackdet) { - snd_soc_update_bits(codec, WM8958_MICBIAS2, - WM8958_MICB2_DISCH, - WM8958_MICB2_DISCH); - snd_soc_update_bits(codec, WM8994_LDO_1, - WM8994_LDO1_DISCH, 0); - wm1811_jackdet_set_mode(codec, - WM1811_JACKDET_MODE_JACK); - } else { - snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, - WM8958_MICD_ENA, WM8958_MICD_ENA); - } - - } else { - snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, - WM8958_MICD_ENA, 0); - wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_NONE); - snd_soc_dapm_disable_pin(&codec->dapm, "CLK_SYS"); - snd_soc_dapm_sync(&codec->dapm); - } - - return 0; -} -EXPORT_SYMBOL_GPL(wm8958_mic_detect); - -static irqreturn_t wm8958_mic_irq(int irq, void *data) -{ - struct wm8994_priv *wm8994 = data; - struct snd_soc_codec *codec = wm8994->codec; - int reg, count; - - /* - * Jack detection may have detected a removal simulataneously - * with an update of the MICDET status; if so it will have - * stopped detection and we can ignore this interrupt. - */ - if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) - return IRQ_HANDLED; - - /* We may occasionally read a detection without an impedence - * range being provided - if that happens loop again. - */ - count = 10; - do { - reg = snd_soc_read(codec, WM8958_MIC_DETECT_3); - if (reg < 0) { - dev_err(codec->dev, - "Failed to read mic detect status: %d\n", - reg); - return IRQ_NONE; - } - - if (!(reg & WM8958_MICD_VALID)) { - dev_dbg(codec->dev, "Mic detect data not valid\n"); - goto out; - } - - if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK)) - break; - - msleep(1); - } while (count--); - - if (count == 0) - dev_warn(codec->dev, "No impedence range reported for jack\n"); - -#ifndef CONFIG_SND_SOC_WM8994_MODULE - trace_snd_soc_jack_irq(dev_name(codec->dev)); -#endif - - if (wm8994->jack_cb) - wm8994->jack_cb(reg, wm8994->jack_cb_data); - else - dev_warn(codec->dev, "Accessory detection with no callback\n"); - -out: - return IRQ_HANDLED; -} - -static irqreturn_t wm8994_fifo_error(int irq, void *data) -{ - struct snd_soc_codec *codec = data; - - dev_err(codec->dev, "FIFO error\n"); - - return IRQ_HANDLED; -} - -static irqreturn_t wm8994_temp_warn(int irq, void *data) -{ - struct snd_soc_codec *codec = data; - - dev_err(codec->dev, "Thermal warning\n"); - - return IRQ_HANDLED; -} - -static irqreturn_t wm8994_temp_shut(int irq, void *data) -{ - struct snd_soc_codec *codec = data; - - dev_crit(codec->dev, "Thermal shutdown\n"); - - return IRQ_HANDLED; -} - -static int wm8994_readproc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ -#define WM8994_CACHE_SIZE 1570 - - int ret; - unsigned short reg; - struct wm8994_priv *wm8994 = data; - - printk(KERN_INFO "\nwm8994 regs dump:\n"); - printk(KERN_INFO "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - for (reg = 0; reg < WM8994_CACHE_SIZE; reg++) { - ret = wm8994_reg_read(wm8994->wm8994, reg); - if (ret < 0) { - printk(KERN_INFO "\nwm8994_reg_read reg[%04x] error\n", reg); - goto out; - } - if (reg%4 == 0) printk("\n"); - printk("reg[%04x]=%04x ", reg, ret); - } - - printk("\n\nGPIO Pin settings:\n"); - for (reg = WM8994_GPIO_1; reg < WM8994_GPIO_1+11; reg++) { - ret = wm8994_reg_read(wm8994->wm8994, reg); - if (ret < 0) { - printk(KERN_INFO "\nwm8994_reg_read reg[%04x] error\n", reg); - goto out; - } - if (reg%4 == 0) printk("\n"); - printk("reg[%04x]=%04x ", reg, ret); - } - -out: - printk(KERN_INFO "\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n"); - return 0; -} - -static int wm8994_codec_probe(struct snd_soc_codec *codec) -{ - struct wm8994 *control = dev_get_drvdata(codec->dev->parent); - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - unsigned int reg; - int ret, i; - - wm8994->codec = codec; - codec->control_data = control->regmap; - - snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - - wm8994->codec = codec; - - mutex_init(&wm8994->accdet_lock); - - for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) - init_completion(&wm8994->fll_locked[i]); - - if (wm8994->pdata && wm8994->pdata->micdet_irq) - wm8994->micdet_irq = wm8994->pdata->micdet_irq; - else if (wm8994->pdata && wm8994->pdata->irq_base) - wm8994->micdet_irq = wm8994->pdata->irq_base + - WM8994_IRQ_MIC1_DET; - - pm_runtime_enable(codec->dev); - pm_runtime_idle(codec->dev); - - /* By default use idle_bias_off, will override for WM8994 */ - codec->dapm.idle_bias_off = 1; - - /* Set revision-specific configuration */ - wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION); - switch (control->type) { - case WM8994: - /* Single ended line outputs should have VMID on. */ - if (!wm8994->pdata->lineout1_diff || - !wm8994->pdata->lineout2_diff) - codec->dapm.idle_bias_off = 0; - - switch (wm8994->revision) { - case 2: - case 3: - wm8994->hubs.dcs_codes_l = -5; - wm8994->hubs.dcs_codes_r = -5; - wm8994->hubs.hp_startup_mode = 1; - wm8994->hubs.dcs_readback_mode = 1; - wm8994->hubs.series_startup = 1; - break; - default: - wm8994->hubs.dcs_readback_mode = 2; - break; - } - break; - - case WM8958: - wm8994->hubs.dcs_readback_mode = 1; - wm8994->hubs.hp_startup_mode = 1; - break; - - case WM1811: - wm8994->hubs.dcs_readback_mode = 2; - wm8994->hubs.no_series_update = 1; - wm8994->hubs.hp_startup_mode = 1; - wm8994->hubs.no_cache_class_w = true; - - switch (wm8994->revision) { - case 0: - case 1: - case 2: - case 3: - wm8994->hubs.dcs_codes_l = -9; - wm8994->hubs.dcs_codes_r = -7; - break; - default: - break; - } - - snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1, - WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); - break; - - default: - break; - } - - wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, - wm8994_fifo_error, "FIFO error", codec); - wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, - wm8994_temp_warn, "Thermal warning", codec); - wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, - wm8994_temp_shut, "Thermal shutdown", codec); - - ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE, - wm_hubs_dcs_done, "DC servo done", - &wm8994->hubs); - if (ret == 0) - wm8994->hubs.dcs_done_irq = true; - - switch (control->type) { - case WM8994: - if (wm8994->micdet_irq) { - ret = request_threaded_irq(wm8994->micdet_irq, NULL, - wm8994_mic_irq, - IRQF_TRIGGER_RISING, - "Mic1 detect", - wm8994); - if (ret != 0) - dev_warn(codec->dev, - "Failed to request Mic1 detect IRQ: %d\n", - ret); - } - - ret = wm8994_request_irq(wm8994->wm8994, - WM8994_IRQ_MIC1_SHRT, - wm8994_mic_irq, "Mic 1 short", - wm8994); - if (ret != 0) - dev_warn(codec->dev, - "Failed to request Mic1 short IRQ: %d\n", - ret); - - ret = wm8994_request_irq(wm8994->wm8994, - WM8994_IRQ_MIC2_DET, - wm8994_mic_irq, "Mic 2 detect", - wm8994); - if (ret != 0) - dev_warn(codec->dev, - "Failed to request Mic2 detect IRQ: %d\n", - ret); - - ret = wm8994_request_irq(wm8994->wm8994, - WM8994_IRQ_MIC2_SHRT, - wm8994_mic_irq, "Mic 2 short", - wm8994); - if (ret != 0) - dev_warn(codec->dev, - "Failed to request Mic2 short IRQ: %d\n", - ret); - break; - - case WM8958: - case WM1811: - if (wm8994->micdet_irq) { - ret = request_threaded_irq(wm8994->micdet_irq, NULL, - wm8958_mic_irq, - IRQF_TRIGGER_RISING, - "Mic detect", - wm8994); - if (ret != 0) - dev_warn(codec->dev, - "Failed to request Mic detect IRQ: %d\n", - ret); - } - } - - switch (control->type) { - case WM1811: - if (wm8994->revision > 1) { - ret = wm8994_request_irq(wm8994->wm8994, - WM8994_IRQ_GPIO(6), - wm1811_jackdet_irq, "JACKDET", - wm8994); - if (ret == 0) - wm8994->jackdet = true; - } - break; - default: - break; - } - - wm8994->fll_locked_irq = true; - for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) { - ret = wm8994_request_irq(wm8994->wm8994, - WM8994_IRQ_FLL1_LOCK + i, - wm8994_fll_locked_irq, "FLL lock", - &wm8994->fll_locked[i]); - if (ret != 0) - wm8994->fll_locked_irq = false; - } - - /* Make sure we can read from the GPIOs if they're inputs */ - pm_runtime_get_sync(codec->dev); - - /* Remember if AIFnLRCLK is configured as a GPIO. This should be - * configured on init - if a system wants to do this dynamically - * at runtime we can deal with that then. - */ - ret = regmap_read(control->regmap, WM8994_GPIO_1, ®); - if (ret < 0) { - dev_err(codec->dev, "Failed to read GPIO1 state: %d\n", ret); - goto err_irq; - } - if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { - wm8994->lrclk_shared[0] = 1; - wm8994_dai[0].symmetric_rates = 1; - } else { - wm8994->lrclk_shared[0] = 0; - } - - ret = regmap_read(control->regmap, WM8994_GPIO_6, ®); - if (ret < 0) { - dev_err(codec->dev, "Failed to read GPIO6 state: %d\n", ret); - goto err_irq; - } - if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) { - wm8994->lrclk_shared[1] = 1; - wm8994_dai[1].symmetric_rates = 1; - } else { - wm8994->lrclk_shared[1] = 0; - } - - pm_runtime_put(codec->dev); - - /* Latch volume update bits */ - for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) - snd_soc_update_bits(codec, wm8994_vu_bits[i].reg, - wm8994_vu_bits[i].mask, - wm8994_vu_bits[i].mask); - - /* Set the low bit of the 3D stereo depth so TLV matches */ - snd_soc_update_bits(codec, WM8994_AIF1_DAC1_FILTERS_2, - 1 << WM8994_AIF1DAC1_3D_GAIN_SHIFT, - 1 << WM8994_AIF1DAC1_3D_GAIN_SHIFT); - snd_soc_update_bits(codec, WM8994_AIF1_DAC2_FILTERS_2, - 1 << WM8994_AIF1DAC2_3D_GAIN_SHIFT, - 1 << WM8994_AIF1DAC2_3D_GAIN_SHIFT); - snd_soc_update_bits(codec, WM8994_AIF2_DAC_FILTERS_2, - 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, - 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); - - /* Unconditionally enable AIF1 ADC TDM mode on chips which can - * use this; it only affects behaviour on idle TDM clock - * cycles. */ - switch (control->type) { - case WM8994: - case WM8958: - snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1, - WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM); - break; - default: - break; - } - - /* Put MICBIAS into bypass mode by default on newer devices */ - switch (control->type) { - case WM8958: - case WM1811: - snd_soc_update_bits(codec, WM8958_MICBIAS1, - WM8958_MICB1_MODE, WM8958_MICB1_MODE); - snd_soc_update_bits(codec, WM8958_MICBIAS2, - WM8958_MICB2_MODE, WM8958_MICB2_MODE); - break; - default: - break; - } - - wm8994_update_class_w(codec); - - wm8994_handle_pdata(wm8994); - - wm_hubs_add_analogue_controls(codec); - snd_soc_add_codec_controls(codec, wm8994_snd_controls, - ARRAY_SIZE(wm8994_snd_controls)); - snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets, - ARRAY_SIZE(wm8994_dapm_widgets)); - - switch (control->type) { - case WM8994: - snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets, - ARRAY_SIZE(wm8994_specific_dapm_widgets)); - if (wm8994->revision < 4) { - snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, - ARRAY_SIZE(wm8994_lateclk_revd_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, - ARRAY_SIZE(wm8994_adc_revd_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_dac_revd_widgets, - ARRAY_SIZE(wm8994_dac_revd_widgets)); - } else { - snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, - ARRAY_SIZE(wm8994_lateclk_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, - ARRAY_SIZE(wm8994_adc_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, - ARRAY_SIZE(wm8994_dac_widgets)); - } - break; - case WM8958: - snd_soc_add_codec_controls(codec, wm8958_snd_controls, - ARRAY_SIZE(wm8958_snd_controls)); - snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, - ARRAY_SIZE(wm8958_dapm_widgets)); - if (wm8994->revision < 1) { - snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets, - ARRAY_SIZE(wm8994_lateclk_revd_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_adc_revd_widgets, - ARRAY_SIZE(wm8994_adc_revd_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_dac_revd_widgets, - ARRAY_SIZE(wm8994_dac_revd_widgets)); - } else { - snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, - ARRAY_SIZE(wm8994_lateclk_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, - ARRAY_SIZE(wm8994_adc_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, - ARRAY_SIZE(wm8994_dac_widgets)); - } - break; - - case WM1811: - snd_soc_add_codec_controls(codec, wm8958_snd_controls, - ARRAY_SIZE(wm8958_snd_controls)); - snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, - ARRAY_SIZE(wm8958_dapm_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, - ARRAY_SIZE(wm8994_lateclk_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, - ARRAY_SIZE(wm8994_adc_widgets)); - snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, - ARRAY_SIZE(wm8994_dac_widgets)); - break; - } - - - wm_hubs_add_analogue_routes(codec, 0, 0); - snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); - - switch (control->type) { - case WM8994: - snd_soc_dapm_add_routes(dapm, wm8994_intercon, - ARRAY_SIZE(wm8994_intercon)); - - if (wm8994->revision < 4) { - snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, - ARRAY_SIZE(wm8994_revd_intercon)); - snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, - ARRAY_SIZE(wm8994_lateclk_revd_intercon)); - } else { - snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, - ARRAY_SIZE(wm8994_lateclk_intercon)); - } - break; - case WM8958: - if (wm8994->revision < 1) { - snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon, - ARRAY_SIZE(wm8994_revd_intercon)); - snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, - ARRAY_SIZE(wm8994_lateclk_revd_intercon)); - } else { - snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, - ARRAY_SIZE(wm8994_lateclk_intercon)); - snd_soc_dapm_add_routes(dapm, wm8958_intercon, - ARRAY_SIZE(wm8958_intercon)); - } - - wm8958_dsp2_init(codec); - break; - case WM1811: - snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, - ARRAY_SIZE(wm8994_lateclk_intercon)); - snd_soc_dapm_add_routes(dapm, wm8958_intercon, - ARRAY_SIZE(wm8958_intercon)); - break; - } - - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, - WM8994_AIF2DACL_ENA | - WM8994_AIF2DACR_ENA, - WM8994_AIF2DACL_ENA | - WM8994_AIF2DACR_ENA); - - wm8994_proc = create_proc_read_entry("wm8994_dumpregs", 0666, NULL, - wm8994_readproc, wm8994); - - return 0; - -err_irq: - if (wm8994->jackdet) - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_SHRT, wm8994); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET, wm8994); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, wm8994); - if (wm8994->micdet_irq) - free_irq(wm8994->micdet_irq, wm8994); - for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i, - &wm8994->fll_locked[i]); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE, - &wm8994->hubs); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, codec); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec); - - return ret; -} - -static int wm8994_codec_remove(struct snd_soc_codec *codec) -{ - struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); - struct wm8994 *control = wm8994->wm8994; - int i; - - wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); - - pm_runtime_disable(codec->dev); - - for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i, - &wm8994->fll_locked[i]); - - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE, - &wm8994->hubs); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, codec); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec); - - if (wm8994->jackdet) - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994); - - switch (control->type) { - case WM8994: - if (wm8994->micdet_irq) - free_irq(wm8994->micdet_irq, wm8994); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET, - wm8994); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, - wm8994); - wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_DET, - wm8994); - break; - - case WM1811: - case WM8958: - if (wm8994->micdet_irq) - free_irq(wm8994->micdet_irq, wm8994); - break; - } - if (wm8994->mbc) - release_firmware(wm8994->mbc); - if (wm8994->mbc_vss) - release_firmware(wm8994->mbc_vss); - if (wm8994->enh_eq) - release_firmware(wm8994->enh_eq); - kfree(wm8994->retune_mobile_texts); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { - .probe = wm8994_codec_probe, - .remove = wm8994_codec_remove, - .suspend = wm8994_codec_suspend, - .resume = wm8994_codec_resume, - .set_bias_level = wm8994_set_bias_level, -}; - -static int __devinit wm8994_probe(struct platform_device *pdev) -{ - struct wm8994_priv *wm8994; - - wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv), - GFP_KERNEL); - if (wm8994 == NULL) - return -ENOMEM; - platform_set_drvdata(pdev, wm8994); - - wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); - wm8994->pdata = dev_get_platdata(pdev->dev.parent); - - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, - wm8994_dai, ARRAY_SIZE(wm8994_dai)); -} - -static int __devexit wm8994_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int wm8994_suspend(struct device *dev) -{ - struct wm8994_priv *wm8994 = dev_get_drvdata(dev); - - /* Drop down to power saving mode when system is suspended */ - if (wm8994->jackdet && !wm8994->active_refcount) - regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2, - WM1811_JACKDET_MODE_MASK, - wm8994->jackdet_mode); - - return 0; -} - -static int wm8994_resume(struct device *dev) -{ - struct wm8994_priv *wm8994 = dev_get_drvdata(dev); - - if (wm8994->jackdet && wm8994->jack_cb) - regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2, - WM1811_JACKDET_MODE_MASK, - WM1811_JACKDET_MODE_AUDIO); - - return 0; -} -#endif - -static const struct dev_pm_ops wm8994_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume) -}; - -static struct platform_driver wm8994_codec_driver = { - .driver = { - .name = "wm8994-codec", - .owner = THIS_MODULE, - .pm = &wm8994_pm_ops, - }, - .probe = wm8994_probe, - .remove = __devexit_p(wm8994_remove), -}; - -module_platform_driver(wm8994_codec_driver); - -MODULE_DESCRIPTION("ASoC WM8994 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm8994-codec"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8994.h b/ANDROID_3.4.5/sound/soc/codecs/wm8994.h deleted file mode 100644 index c7241129..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8994.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * wm8994.h -- WM8994 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8994_H -#define _WM8994_H - -#include -#include -#include - -#include "wm_hubs.h" - -/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ -#define WM8994_SYSCLK_MCLK1 1 -#define WM8994_SYSCLK_MCLK2 2 -#define WM8994_SYSCLK_FLL1 3 -#define WM8994_SYSCLK_FLL2 4 - -/* OPCLK is also configured with set_dai_sysclk, specify division*10 as rate. */ -#define WM8994_SYSCLK_OPCLK 5 - -#define WM8994_FLL1 1 -#define WM8994_FLL2 2 - -#define WM8994_FLL_SRC_MCLK1 1 -#define WM8994_FLL_SRC_MCLK2 2 -#define WM8994_FLL_SRC_LRCLK 3 -#define WM8994_FLL_SRC_BCLK 4 - -enum wm8994_vmid_mode { - WM8994_VMID_NORMAL, - WM8994_VMID_FORCE, -}; - -typedef void (*wm8958_micdet_cb)(u16 status, void *data); - -int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - int micbias); -int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - wm8958_micdet_cb cb, void *cb_data); - -int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode); - -int wm8958_aif_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event); - -void wm8958_dsp2_init(struct snd_soc_codec *codec); - -struct wm8994_micdet { - struct snd_soc_jack *jack; - bool detecting; -}; - -/* codec private data */ -struct wm8994_fll_config { - int src; - int in; - int out; -}; - -#define WM8994_NUM_DRC 3 -#define WM8994_NUM_EQ 3 - -struct wm8994; - -struct wm8994_priv { - struct wm_hubs_data hubs; - struct wm8994 *wm8994; - struct snd_soc_codec *codec; - int sysclk[2]; - int sysclk_rate[2]; - int mclk[2]; - int aifclk[2]; - struct wm8994_fll_config fll[2], fll_suspend[2]; - struct completion fll_locked[2]; - bool fll_locked_irq; - - int vmid_refcount; - int active_refcount; - enum wm8994_vmid_mode vmid_mode; - - int dac_rates[2]; - int lrclk_shared[2]; - - int mbc_ena[3]; - int hpf1_ena[3]; - int hpf2_ena[3]; - int vss_ena[3]; - int enh_eq_ena[3]; - - /* Platform dependant DRC configuration */ - const char **drc_texts; - int drc_cfg[WM8994_NUM_DRC]; - struct soc_enum drc_enum; - - /* Platform dependant ReTune mobile configuration */ - int num_retune_mobile_texts; - const char **retune_mobile_texts; - int retune_mobile_cfg[WM8994_NUM_EQ]; - struct soc_enum retune_mobile_enum; - - /* Platform dependant MBC configuration */ - int mbc_cfg; - const char **mbc_texts; - struct soc_enum mbc_enum; - - /* Platform dependant VSS configuration */ - int vss_cfg; - const char **vss_texts; - struct soc_enum vss_enum; - - /* Platform dependant VSS HPF configuration */ - int vss_hpf_cfg; - const char **vss_hpf_texts; - struct soc_enum vss_hpf_enum; - - /* Platform dependant enhanced EQ configuration */ - int enh_eq_cfg; - const char **enh_eq_texts; - struct soc_enum enh_eq_enum; - - struct mutex accdet_lock; - struct wm8994_micdet micdet[2]; - bool mic_detecting; - bool jack_mic; - int btn_mask; - bool jackdet; - int jackdet_mode; - - wm8958_micdet_cb jack_cb; - void *jack_cb_data; - int micdet_irq; - - int revision; - struct wm8994_pdata *pdata; - - unsigned int aif1clk_enable:1; - unsigned int aif2clk_enable:1; - - unsigned int aif1clk_disable:1; - unsigned int aif2clk_disable:1; - - int dsp_active; - const struct firmware *cur_fw; - const struct firmware *mbc; - const struct firmware *mbc_vss; - const struct firmware *enh_eq; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8995.c b/ANDROID_3.4.5/sound/soc/codecs/wm8995.c deleted file mode 100644 index 28c89b09..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8995.c +++ /dev/null @@ -1,2415 +0,0 @@ -/* - * wm8995.c -- WM8995 ALSA SoC Audio driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * Based on wm8994.c and wm_hubs.c by Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8995.h" - -#define WM8995_NUM_SUPPLIES 8 -static const char *wm8995_supply_names[WM8995_NUM_SUPPLIES] = { - "DCVDD", - "DBVDD1", - "DBVDD2", - "DBVDD3", - "AVDD1", - "AVDD2", - "CPVDD", - "MICVDD" -}; - -static struct reg_default wm8995_reg_defaults[] = { - { 0, 0x8995 }, - { 5, 0x0100 }, - { 16, 0x000b }, - { 17, 0x000b }, - { 24, 0x02c0 }, - { 25, 0x02c0 }, - { 26, 0x02c0 }, - { 27, 0x02c0 }, - { 28, 0x000f }, - { 32, 0x0005 }, - { 33, 0x0005 }, - { 40, 0x0003 }, - { 41, 0x0013 }, - { 48, 0x0004 }, - { 56, 0x09f8 }, - { 64, 0x1f25 }, - { 69, 0x0004 }, - { 82, 0xaaaa }, - { 84, 0x2a2a }, - { 146, 0x0060 }, - { 256, 0x0002 }, - { 257, 0x8004 }, - { 520, 0x0010 }, - { 528, 0x0083 }, - { 529, 0x0083 }, - { 548, 0x0c80 }, - { 580, 0x0c80 }, - { 768, 0x4050 }, - { 769, 0x4000 }, - { 771, 0x0040 }, - { 772, 0x0040 }, - { 773, 0x0040 }, - { 774, 0x0004 }, - { 775, 0x0100 }, - { 784, 0x4050 }, - { 785, 0x4000 }, - { 787, 0x0040 }, - { 788, 0x0040 }, - { 789, 0x0040 }, - { 1024, 0x00c0 }, - { 1025, 0x00c0 }, - { 1026, 0x00c0 }, - { 1027, 0x00c0 }, - { 1028, 0x00c0 }, - { 1029, 0x00c0 }, - { 1030, 0x00c0 }, - { 1031, 0x00c0 }, - { 1056, 0x0200 }, - { 1057, 0x0010 }, - { 1058, 0x0200 }, - { 1059, 0x0010 }, - { 1088, 0x0098 }, - { 1089, 0x0845 }, - { 1104, 0x0098 }, - { 1105, 0x0845 }, - { 1152, 0x6318 }, - { 1153, 0x6300 }, - { 1154, 0x0fca }, - { 1155, 0x0400 }, - { 1156, 0x00d8 }, - { 1157, 0x1eb5 }, - { 1158, 0xf145 }, - { 1159, 0x0b75 }, - { 1160, 0x01c5 }, - { 1161, 0x1c58 }, - { 1162, 0xf373 }, - { 1163, 0x0a54 }, - { 1164, 0x0558 }, - { 1165, 0x168e }, - { 1166, 0xf829 }, - { 1167, 0x07ad }, - { 1168, 0x1103 }, - { 1169, 0x0564 }, - { 1170, 0x0559 }, - { 1171, 0x4000 }, - { 1184, 0x6318 }, - { 1185, 0x6300 }, - { 1186, 0x0fca }, - { 1187, 0x0400 }, - { 1188, 0x00d8 }, - { 1189, 0x1eb5 }, - { 1190, 0xf145 }, - { 1191, 0x0b75 }, - { 1192, 0x01c5 }, - { 1193, 0x1c58 }, - { 1194, 0xf373 }, - { 1195, 0x0a54 }, - { 1196, 0x0558 }, - { 1197, 0x168e }, - { 1198, 0xf829 }, - { 1199, 0x07ad }, - { 1200, 0x1103 }, - { 1201, 0x0564 }, - { 1202, 0x0559 }, - { 1203, 0x4000 }, - { 1280, 0x00c0 }, - { 1281, 0x00c0 }, - { 1282, 0x00c0 }, - { 1283, 0x00c0 }, - { 1312, 0x0200 }, - { 1313, 0x0010 }, - { 1344, 0x0098 }, - { 1345, 0x0845 }, - { 1408, 0x6318 }, - { 1409, 0x6300 }, - { 1410, 0x0fca }, - { 1411, 0x0400 }, - { 1412, 0x00d8 }, - { 1413, 0x1eb5 }, - { 1414, 0xf145 }, - { 1415, 0x0b75 }, - { 1416, 0x01c5 }, - { 1417, 0x1c58 }, - { 1418, 0xf373 }, - { 1419, 0x0a54 }, - { 1420, 0x0558 }, - { 1421, 0x168e }, - { 1422, 0xf829 }, - { 1423, 0x07ad }, - { 1424, 0x1103 }, - { 1425, 0x0564 }, - { 1426, 0x0559 }, - { 1427, 0x4000 }, - { 1568, 0x0002 }, - { 1792, 0xa100 }, - { 1793, 0xa101 }, - { 1794, 0xa101 }, - { 1795, 0xa101 }, - { 1796, 0xa101 }, - { 1797, 0xa101 }, - { 1798, 0xa101 }, - { 1799, 0xa101 }, - { 1800, 0xa101 }, - { 1801, 0xa101 }, - { 1802, 0xa101 }, - { 1803, 0xa101 }, - { 1804, 0xa101 }, - { 1805, 0xa101 }, - { 1825, 0x0055 }, - { 1848, 0x3fff }, - { 1849, 0x1fff }, - { 2049, 0x0001 }, - { 2050, 0x0069 }, - { 2056, 0x0002 }, - { 2057, 0x0003 }, - { 2058, 0x0069 }, - { 12288, 0x0001 }, - { 12289, 0x0001 }, - { 12291, 0x0006 }, - { 12292, 0x0040 }, - { 12293, 0x0001 }, - { 12294, 0x000f }, - { 12295, 0x0006 }, - { 12296, 0x0001 }, - { 12297, 0x0003 }, - { 12298, 0x0104 }, - { 12300, 0x0060 }, - { 12301, 0x0011 }, - { 12302, 0x0401 }, - { 12304, 0x0050 }, - { 12305, 0x0003 }, - { 12306, 0x0100 }, - { 12308, 0x0051 }, - { 12309, 0x0003 }, - { 12310, 0x0104 }, - { 12311, 0x000a }, - { 12312, 0x0060 }, - { 12313, 0x003b }, - { 12314, 0x0502 }, - { 12315, 0x0100 }, - { 12316, 0x2fff }, - { 12320, 0x2fff }, - { 12324, 0x2fff }, - { 12328, 0x2fff }, - { 12332, 0x2fff }, - { 12336, 0x2fff }, - { 12340, 0x2fff }, - { 12344, 0x2fff }, - { 12348, 0x2fff }, - { 12352, 0x0001 }, - { 12353, 0x0001 }, - { 12355, 0x0006 }, - { 12356, 0x0040 }, - { 12357, 0x0001 }, - { 12358, 0x000f }, - { 12359, 0x0006 }, - { 12360, 0x0001 }, - { 12361, 0x0003 }, - { 12362, 0x0104 }, - { 12364, 0x0060 }, - { 12365, 0x0011 }, - { 12366, 0x0401 }, - { 12368, 0x0050 }, - { 12369, 0x0003 }, - { 12370, 0x0100 }, - { 12372, 0x0060 }, - { 12373, 0x003b }, - { 12374, 0x0502 }, - { 12375, 0x0100 }, - { 12376, 0x2fff }, - { 12380, 0x2fff }, - { 12384, 0x2fff }, - { 12388, 0x2fff }, - { 12392, 0x2fff }, - { 12396, 0x2fff }, - { 12400, 0x2fff }, - { 12404, 0x2fff }, - { 12408, 0x2fff }, - { 12412, 0x2fff }, - { 12416, 0x0001 }, - { 12417, 0x0001 }, - { 12419, 0x0006 }, - { 12420, 0x0040 }, - { 12421, 0x0001 }, - { 12422, 0x000f }, - { 12423, 0x0006 }, - { 12424, 0x0001 }, - { 12425, 0x0003 }, - { 12426, 0x0106 }, - { 12428, 0x0061 }, - { 12429, 0x0011 }, - { 12430, 0x0401 }, - { 12432, 0x0050 }, - { 12433, 0x0003 }, - { 12434, 0x0102 }, - { 12436, 0x0051 }, - { 12437, 0x0003 }, - { 12438, 0x0106 }, - { 12439, 0x000a }, - { 12440, 0x0061 }, - { 12441, 0x003b }, - { 12442, 0x0502 }, - { 12443, 0x0100 }, - { 12444, 0x2fff }, - { 12448, 0x2fff }, - { 12452, 0x2fff }, - { 12456, 0x2fff }, - { 12460, 0x2fff }, - { 12464, 0x2fff }, - { 12468, 0x2fff }, - { 12472, 0x2fff }, - { 12476, 0x2fff }, - { 12480, 0x0001 }, - { 12481, 0x0001 }, - { 12483, 0x0006 }, - { 12484, 0x0040 }, - { 12485, 0x0001 }, - { 12486, 0x000f }, - { 12487, 0x0006 }, - { 12488, 0x0001 }, - { 12489, 0x0003 }, - { 12490, 0x0106 }, - { 12492, 0x0061 }, - { 12493, 0x0011 }, - { 12494, 0x0401 }, - { 12496, 0x0050 }, - { 12497, 0x0003 }, - { 12498, 0x0102 }, - { 12500, 0x0061 }, - { 12501, 0x003b }, - { 12502, 0x0502 }, - { 12503, 0x0100 }, - { 12504, 0x2fff }, - { 12508, 0x2fff }, - { 12512, 0x2fff }, - { 12516, 0x2fff }, - { 12520, 0x2fff }, - { 12524, 0x2fff }, - { 12528, 0x2fff }, - { 12532, 0x2fff }, - { 12536, 0x2fff }, - { 12540, 0x2fff }, - { 12544, 0x0060 }, - { 12546, 0x0601 }, - { 12548, 0x0050 }, - { 12550, 0x0100 }, - { 12552, 0x0001 }, - { 12554, 0x0104 }, - { 12555, 0x0100 }, - { 12556, 0x2fff }, - { 12560, 0x2fff }, - { 12564, 0x2fff }, - { 12568, 0x2fff }, - { 12572, 0x2fff }, - { 12576, 0x2fff }, - { 12580, 0x2fff }, - { 12584, 0x2fff }, - { 12588, 0x2fff }, - { 12592, 0x2fff }, - { 12596, 0x2fff }, - { 12600, 0x2fff }, - { 12604, 0x2fff }, - { 12608, 0x0061 }, - { 12610, 0x0601 }, - { 12612, 0x0050 }, - { 12614, 0x0102 }, - { 12616, 0x0001 }, - { 12618, 0x0106 }, - { 12619, 0x0100 }, - { 12620, 0x2fff }, - { 12624, 0x2fff }, - { 12628, 0x2fff }, - { 12632, 0x2fff }, - { 12636, 0x2fff }, - { 12640, 0x2fff }, - { 12644, 0x2fff }, - { 12648, 0x2fff }, - { 12652, 0x2fff }, - { 12656, 0x2fff }, - { 12660, 0x2fff }, - { 12664, 0x2fff }, - { 12668, 0x2fff }, - { 12672, 0x0060 }, - { 12674, 0x0601 }, - { 12676, 0x0061 }, - { 12678, 0x0601 }, - { 12680, 0x0050 }, - { 12682, 0x0300 }, - { 12684, 0x0001 }, - { 12686, 0x0304 }, - { 12688, 0x0040 }, - { 12690, 0x000f }, - { 12692, 0x0001 }, - { 12695, 0x0100 }, -}; - -struct fll_config { - int src; - int in; - int out; -}; - -struct wm8995_priv { - struct regmap *regmap; - int sysclk[2]; - int mclk[2]; - int aifclk[2]; - struct fll_config fll[2], fll_suspend[2]; - struct regulator_bulk_data supplies[WM8995_NUM_SUPPLIES]; - struct notifier_block disable_nb[WM8995_NUM_SUPPLIES]; - struct snd_soc_codec *codec; -}; - -/* - * We can't use the same notifier block for more than one supply and - * there's no way I can see to get from a callback to the caller - * except container_of(). - */ -#define WM8995_REGULATOR_EVENT(n) \ -static int wm8995_regulator_event_##n(struct notifier_block *nb, \ - unsigned long event, void *data) \ -{ \ - struct wm8995_priv *wm8995 = container_of(nb, struct wm8995_priv, \ - disable_nb[n]); \ - if (event & REGULATOR_EVENT_DISABLE) { \ - regcache_mark_dirty(wm8995->regmap); \ - } \ - return 0; \ -} - -WM8995_REGULATOR_EVENT(0) -WM8995_REGULATOR_EVENT(1) -WM8995_REGULATOR_EVENT(2) -WM8995_REGULATOR_EVENT(3) -WM8995_REGULATOR_EVENT(4) -WM8995_REGULATOR_EVENT(5) -WM8995_REGULATOR_EVENT(6) -WM8995_REGULATOR_EVENT(7) - -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(in1lr_pga_tlv, -1650, 150, 0); -static const DECLARE_TLV_DB_SCALE(in1l_boost_tlv, 0, 600, 0); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 150, 0); - -static const char *in1l_text[] = { - "Differential", "Single-ended IN1LN", "Single-ended IN1LP" -}; - -static const SOC_ENUM_SINGLE_DECL(in1l_enum, WM8995_LEFT_LINE_INPUT_CONTROL, - 2, in1l_text); - -static const char *in1r_text[] = { - "Differential", "Single-ended IN1RN", "Single-ended IN1RP" -}; - -static const SOC_ENUM_SINGLE_DECL(in1r_enum, WM8995_LEFT_LINE_INPUT_CONTROL, - 0, in1r_text); - -static const char *dmic_src_text[] = { - "DMICDAT1", "DMICDAT2", "DMICDAT3" -}; - -static const SOC_ENUM_SINGLE_DECL(dmic_src1_enum, WM8995_POWER_MANAGEMENT_5, - 8, dmic_src_text); -static const SOC_ENUM_SINGLE_DECL(dmic_src2_enum, WM8995_POWER_MANAGEMENT_5, - 6, dmic_src_text); - -static const struct snd_kcontrol_new wm8995_snd_controls[] = { - SOC_DOUBLE_R_TLV("DAC1 Volume", WM8995_DAC1_LEFT_VOLUME, - WM8995_DAC1_RIGHT_VOLUME, 0, 96, 0, digital_tlv), - SOC_DOUBLE_R("DAC1 Switch", WM8995_DAC1_LEFT_VOLUME, - WM8995_DAC1_RIGHT_VOLUME, 9, 1, 1), - - SOC_DOUBLE_R_TLV("DAC2 Volume", WM8995_DAC2_LEFT_VOLUME, - WM8995_DAC2_RIGHT_VOLUME, 0, 96, 0, digital_tlv), - SOC_DOUBLE_R("DAC2 Switch", WM8995_DAC2_LEFT_VOLUME, - WM8995_DAC2_RIGHT_VOLUME, 9, 1, 1), - - SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8995_AIF1_DAC1_LEFT_VOLUME, - WM8995_AIF1_DAC1_RIGHT_VOLUME, 0, 96, 0, digital_tlv), - SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8995_AIF1_DAC2_LEFT_VOLUME, - WM8995_AIF1_DAC2_RIGHT_VOLUME, 0, 96, 0, digital_tlv), - SOC_DOUBLE_R_TLV("AIF2DAC Volume", WM8995_AIF2_DAC_LEFT_VOLUME, - WM8995_AIF2_DAC_RIGHT_VOLUME, 0, 96, 0, digital_tlv), - - SOC_DOUBLE_R_TLV("IN1LR Volume", WM8995_LEFT_LINE_INPUT_1_VOLUME, - WM8995_RIGHT_LINE_INPUT_1_VOLUME, 0, 31, 0, in1lr_pga_tlv), - - SOC_SINGLE_TLV("IN1L Boost", WM8995_LEFT_LINE_INPUT_CONTROL, - 4, 3, 0, in1l_boost_tlv), - - SOC_ENUM("IN1L Mode", in1l_enum), - SOC_ENUM("IN1R Mode", in1r_enum), - - SOC_ENUM("DMIC1 SRC", dmic_src1_enum), - SOC_ENUM("DMIC2 SRC", dmic_src2_enum), - - SOC_DOUBLE_TLV("DAC1 Sidetone Volume", WM8995_DAC1_MIXER_VOLUMES, 0, 5, - 24, 0, sidetone_tlv), - SOC_DOUBLE_TLV("DAC2 Sidetone Volume", WM8995_DAC2_MIXER_VOLUMES, 0, 5, - 24, 0, sidetone_tlv), - - SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8995_AIF1_ADC1_LEFT_VOLUME, - WM8995_AIF1_ADC1_RIGHT_VOLUME, 0, 96, 0, digital_tlv), - SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8995_AIF1_ADC2_LEFT_VOLUME, - WM8995_AIF1_ADC2_RIGHT_VOLUME, 0, 96, 0, digital_tlv), - SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8995_AIF2_ADC_LEFT_VOLUME, - WM8995_AIF2_ADC_RIGHT_VOLUME, 0, 96, 0, digital_tlv) -}; - -static void wm8995_update_class_w(struct snd_soc_codec *codec) -{ - int enable = 1; - int source = 0; /* GCC flow analysis can't track enable */ - int reg, reg_r; - - /* We also need the same setting for L/R and only one path */ - reg = snd_soc_read(codec, WM8995_DAC1_LEFT_MIXER_ROUTING); - switch (reg) { - case WM8995_AIF2DACL_TO_DAC1L: - dev_dbg(codec->dev, "Class W source AIF2DAC\n"); - source = 2 << WM8995_CP_DYN_SRC_SEL_SHIFT; - break; - case WM8995_AIF1DAC2L_TO_DAC1L: - dev_dbg(codec->dev, "Class W source AIF1DAC2\n"); - source = 1 << WM8995_CP_DYN_SRC_SEL_SHIFT; - break; - case WM8995_AIF1DAC1L_TO_DAC1L: - dev_dbg(codec->dev, "Class W source AIF1DAC1\n"); - source = 0 << WM8995_CP_DYN_SRC_SEL_SHIFT; - break; - default: - dev_dbg(codec->dev, "DAC mixer setting: %x\n", reg); - enable = 0; - break; - } - - reg_r = snd_soc_read(codec, WM8995_DAC1_RIGHT_MIXER_ROUTING); - if (reg_r != reg) { - dev_dbg(codec->dev, "Left and right DAC mixers different\n"); - enable = 0; - } - - if (enable) { - dev_dbg(codec->dev, "Class W enabled\n"); - snd_soc_update_bits(codec, WM8995_CLASS_W_1, - WM8995_CP_DYN_PWR_MASK | - WM8995_CP_DYN_SRC_SEL_MASK, - source | WM8995_CP_DYN_PWR); - } else { - dev_dbg(codec->dev, "Class W disabled\n"); - snd_soc_update_bits(codec, WM8995_CLASS_W_1, - WM8995_CP_DYN_PWR_MASK, 0); - } -} - -static int check_clk_sys(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) -{ - unsigned int reg; - const char *clk; - - reg = snd_soc_read(source->codec, WM8995_CLOCKING_1); - /* Check what we're currently using for CLK_SYS */ - if (reg & WM8995_SYSCLK_SRC) - clk = "AIF2CLK"; - else - clk = "AIF1CLK"; - return !strcmp(source->name, clk); -} - -static int wm8995_put_class_w(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_widget *w = wlist->widgets[0]; - struct snd_soc_codec *codec; - int ret; - - codec = w->codec; - ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); - wm8995_update_class_w(codec); - return ret; -} - -static int hp_supply_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec; - struct wm8995_priv *wm8995; - - codec = w->codec; - wm8995 = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - /* Enable the headphone amp */ - snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, - WM8995_HPOUT1L_ENA_MASK | - WM8995_HPOUT1R_ENA_MASK, - WM8995_HPOUT1L_ENA | - WM8995_HPOUT1R_ENA); - - /* Enable the second stage */ - snd_soc_update_bits(codec, WM8995_ANALOGUE_HP_1, - WM8995_HPOUT1L_DLY_MASK | - WM8995_HPOUT1R_DLY_MASK, - WM8995_HPOUT1L_DLY | - WM8995_HPOUT1R_DLY); - break; - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(codec, WM8995_CHARGE_PUMP_1, - WM8995_CP_ENA_MASK, 0); - break; - } - - return 0; -} - -static void dc_servo_cmd(struct snd_soc_codec *codec, - unsigned int reg, unsigned int val, unsigned int mask) -{ - int timeout = 10; - - dev_dbg(codec->dev, "%s: reg = %#x, val = %#x, mask = %#x\n", - __func__, reg, val, mask); - - snd_soc_write(codec, reg, val); - while (timeout--) { - msleep(10); - val = snd_soc_read(codec, WM8995_DC_SERVO_READBACK_0); - if ((val & mask) == mask) - return; - } - - dev_err(codec->dev, "Timed out waiting for DC Servo\n"); -} - -static int hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec; - unsigned int reg; - - codec = w->codec; - reg = snd_soc_read(codec, WM8995_ANALOGUE_HP_1); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(codec, WM8995_CHARGE_PUMP_1, - WM8995_CP_ENA_MASK, WM8995_CP_ENA); - - msleep(5); - - snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, - WM8995_HPOUT1L_ENA_MASK | - WM8995_HPOUT1R_ENA_MASK, - WM8995_HPOUT1L_ENA | WM8995_HPOUT1R_ENA); - - udelay(20); - - reg |= WM8995_HPOUT1L_DLY | WM8995_HPOUT1R_DLY; - snd_soc_write(codec, WM8995_ANALOGUE_HP_1, reg); - - snd_soc_write(codec, WM8995_DC_SERVO_1, WM8995_DCS_ENA_CHAN_0 | - WM8995_DCS_ENA_CHAN_1); - - dc_servo_cmd(codec, WM8995_DC_SERVO_2, - WM8995_DCS_TRIG_STARTUP_0 | - WM8995_DCS_TRIG_STARTUP_1, - WM8995_DCS_TRIG_DAC_WR_0 | - WM8995_DCS_TRIG_DAC_WR_1); - - reg |= WM8995_HPOUT1R_OUTP | WM8995_HPOUT1R_RMV_SHORT | - WM8995_HPOUT1L_OUTP | WM8995_HPOUT1L_RMV_SHORT; - snd_soc_write(codec, WM8995_ANALOGUE_HP_1, reg); - - break; - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(codec, WM8995_ANALOGUE_HP_1, - WM8995_HPOUT1L_OUTP_MASK | - WM8995_HPOUT1R_OUTP_MASK | - WM8995_HPOUT1L_RMV_SHORT_MASK | - WM8995_HPOUT1R_RMV_SHORT_MASK, 0); - - snd_soc_update_bits(codec, WM8995_ANALOGUE_HP_1, - WM8995_HPOUT1L_DLY_MASK | - WM8995_HPOUT1R_DLY_MASK, 0); - - snd_soc_write(codec, WM8995_DC_SERVO_1, 0); - - snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, - WM8995_HPOUT1L_ENA_MASK | - WM8995_HPOUT1R_ENA_MASK, - 0); - break; - } - - return 0; -} - -static int configure_aif_clock(struct snd_soc_codec *codec, int aif) -{ - struct wm8995_priv *wm8995; - int rate; - int reg1 = 0; - int offset; - - wm8995 = snd_soc_codec_get_drvdata(codec); - - if (aif) - offset = 4; - else - offset = 0; - - switch (wm8995->sysclk[aif]) { - case WM8995_SYSCLK_MCLK1: - rate = wm8995->mclk[0]; - break; - case WM8995_SYSCLK_MCLK2: - reg1 |= 0x8; - rate = wm8995->mclk[1]; - break; - case WM8995_SYSCLK_FLL1: - reg1 |= 0x10; - rate = wm8995->fll[0].out; - break; - case WM8995_SYSCLK_FLL2: - reg1 |= 0x18; - rate = wm8995->fll[1].out; - break; - default: - return -EINVAL; - } - - if (rate >= 13500000) { - rate /= 2; - reg1 |= WM8995_AIF1CLK_DIV; - - dev_dbg(codec->dev, "Dividing AIF%d clock to %dHz\n", - aif + 1, rate); - } - - wm8995->aifclk[aif] = rate; - - snd_soc_update_bits(codec, WM8995_AIF1_CLOCKING_1 + offset, - WM8995_AIF1CLK_SRC_MASK | WM8995_AIF1CLK_DIV_MASK, - reg1); - return 0; -} - -static int configure_clock(struct snd_soc_codec *codec) -{ - struct wm8995_priv *wm8995; - int change, new; - - wm8995 = snd_soc_codec_get_drvdata(codec); - - /* Bring up the AIF clocks first */ - configure_aif_clock(codec, 0); - configure_aif_clock(codec, 1); - - /* - * Then switch CLK_SYS over to the higher of them; a change - * can only happen as a result of a clocking change which can - * only be made outside of DAPM so we can safely redo the - * clocking. - */ - - /* If they're equal it doesn't matter which is used */ - if (wm8995->aifclk[0] == wm8995->aifclk[1]) - return 0; - - if (wm8995->aifclk[0] < wm8995->aifclk[1]) - new = WM8995_SYSCLK_SRC; - else - new = 0; - - change = snd_soc_update_bits(codec, WM8995_CLOCKING_1, - WM8995_SYSCLK_SRC_MASK, new); - if (!change) - return 0; - - snd_soc_dapm_sync(&codec->dapm); - - return 0; -} - -static int clk_sys_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec; - - codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - return configure_clock(codec); - - case SND_SOC_DAPM_POST_PMD: - configure_clock(codec); - break; - } - - return 0; -} - -static const char *sidetone_text[] = { - "ADC/DMIC1", "DMIC2", -}; - -static const struct soc_enum sidetone1_enum = - SOC_ENUM_SINGLE(WM8995_SIDETONE, 0, 2, sidetone_text); - -static const struct snd_kcontrol_new sidetone1_mux = - SOC_DAPM_ENUM("Left Sidetone Mux", sidetone1_enum); - -static const struct soc_enum sidetone2_enum = - SOC_ENUM_SINGLE(WM8995_SIDETONE, 1, 2, sidetone_text); - -static const struct snd_kcontrol_new sidetone2_mux = - SOC_DAPM_ENUM("Right Sidetone Mux", sidetone2_enum); - -static const struct snd_kcontrol_new aif1adc1l_mix[] = { - SOC_DAPM_SINGLE("ADC/DMIC Switch", WM8995_AIF1_ADC1_LEFT_MIXER_ROUTING, - 1, 1, 0), - SOC_DAPM_SINGLE("AIF2 Switch", WM8995_AIF1_ADC1_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif1adc1r_mix[] = { - SOC_DAPM_SINGLE("ADC/DMIC Switch", WM8995_AIF1_ADC1_RIGHT_MIXER_ROUTING, - 1, 1, 0), - SOC_DAPM_SINGLE("AIF2 Switch", WM8995_AIF1_ADC1_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif1adc2l_mix[] = { - SOC_DAPM_SINGLE("DMIC Switch", WM8995_AIF1_ADC2_LEFT_MIXER_ROUTING, - 1, 1, 0), - SOC_DAPM_SINGLE("AIF2 Switch", WM8995_AIF1_ADC2_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif1adc2r_mix[] = { - SOC_DAPM_SINGLE("DMIC Switch", WM8995_AIF1_ADC2_RIGHT_MIXER_ROUTING, - 1, 1, 0), - SOC_DAPM_SINGLE("AIF2 Switch", WM8995_AIF1_ADC2_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new dac1l_mix[] = { - WM8995_CLASS_W_SWITCH("Right Sidetone Switch", WM8995_DAC1_LEFT_MIXER_ROUTING, - 5, 1, 0), - WM8995_CLASS_W_SWITCH("Left Sidetone Switch", WM8995_DAC1_LEFT_MIXER_ROUTING, - 4, 1, 0), - WM8995_CLASS_W_SWITCH("AIF2 Switch", WM8995_DAC1_LEFT_MIXER_ROUTING, - 2, 1, 0), - WM8995_CLASS_W_SWITCH("AIF1.2 Switch", WM8995_DAC1_LEFT_MIXER_ROUTING, - 1, 1, 0), - WM8995_CLASS_W_SWITCH("AIF1.1 Switch", WM8995_DAC1_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new dac1r_mix[] = { - WM8995_CLASS_W_SWITCH("Right Sidetone Switch", WM8995_DAC1_RIGHT_MIXER_ROUTING, - 5, 1, 0), - WM8995_CLASS_W_SWITCH("Left Sidetone Switch", WM8995_DAC1_RIGHT_MIXER_ROUTING, - 4, 1, 0), - WM8995_CLASS_W_SWITCH("AIF2 Switch", WM8995_DAC1_RIGHT_MIXER_ROUTING, - 2, 1, 0), - WM8995_CLASS_W_SWITCH("AIF1.2 Switch", WM8995_DAC1_RIGHT_MIXER_ROUTING, - 1, 1, 0), - WM8995_CLASS_W_SWITCH("AIF1.1 Switch", WM8995_DAC1_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif2dac2l_mix[] = { - SOC_DAPM_SINGLE("Right Sidetone Switch", WM8995_DAC2_LEFT_MIXER_ROUTING, - 5, 1, 0), - SOC_DAPM_SINGLE("Left Sidetone Switch", WM8995_DAC2_LEFT_MIXER_ROUTING, - 4, 1, 0), - SOC_DAPM_SINGLE("AIF2 Switch", WM8995_DAC2_LEFT_MIXER_ROUTING, - 2, 1, 0), - SOC_DAPM_SINGLE("AIF1.2 Switch", WM8995_DAC2_LEFT_MIXER_ROUTING, - 1, 1, 0), - SOC_DAPM_SINGLE("AIF1.1 Switch", WM8995_DAC2_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new aif2dac2r_mix[] = { - SOC_DAPM_SINGLE("Right Sidetone Switch", WM8995_DAC2_RIGHT_MIXER_ROUTING, - 5, 1, 0), - SOC_DAPM_SINGLE("Left Sidetone Switch", WM8995_DAC2_RIGHT_MIXER_ROUTING, - 4, 1, 0), - SOC_DAPM_SINGLE("AIF2 Switch", WM8995_DAC2_RIGHT_MIXER_ROUTING, - 2, 1, 0), - SOC_DAPM_SINGLE("AIF1.2 Switch", WM8995_DAC2_RIGHT_MIXER_ROUTING, - 1, 1, 0), - SOC_DAPM_SINGLE("AIF1.1 Switch", WM8995_DAC2_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new in1l_pga = - SOC_DAPM_SINGLE("IN1L Switch", WM8995_POWER_MANAGEMENT_2, 5, 1, 0); - -static const struct snd_kcontrol_new in1r_pga = - SOC_DAPM_SINGLE("IN1R Switch", WM8995_POWER_MANAGEMENT_2, 4, 1, 0); - -static const char *adc_mux_text[] = { - "ADC", - "DMIC", -}; - -static const struct soc_enum adc_enum = - SOC_ENUM_SINGLE(0, 0, 2, adc_mux_text); - -static const struct snd_kcontrol_new adcl_mux = - SOC_DAPM_ENUM_VIRT("ADCL Mux", adc_enum); - -static const struct snd_kcontrol_new adcr_mux = - SOC_DAPM_ENUM_VIRT("ADCR Mux", adc_enum); - -static const char *spk_src_text[] = { - "DAC1L", "DAC1R", "DAC2L", "DAC2R" -}; - -static const SOC_ENUM_SINGLE_DECL(spk1l_src_enum, WM8995_LEFT_PDM_SPEAKER_1, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk1r_src_enum, WM8995_RIGHT_PDM_SPEAKER_1, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk2l_src_enum, WM8995_LEFT_PDM_SPEAKER_2, - 0, spk_src_text); -static const SOC_ENUM_SINGLE_DECL(spk2r_src_enum, WM8995_RIGHT_PDM_SPEAKER_2, - 0, spk_src_text); - -static const struct snd_kcontrol_new spk1l_mux = - SOC_DAPM_ENUM("SPK1L SRC", spk1l_src_enum); -static const struct snd_kcontrol_new spk1r_mux = - SOC_DAPM_ENUM("SPK1R SRC", spk1r_src_enum); -static const struct snd_kcontrol_new spk2l_mux = - SOC_DAPM_ENUM("SPK2L SRC", spk2l_src_enum); -static const struct snd_kcontrol_new spk2r_mux = - SOC_DAPM_ENUM("SPK2R SRC", spk2r_src_enum); - -static const struct snd_soc_dapm_widget wm8995_dapm_widgets[] = { - SND_SOC_DAPM_INPUT("DMIC1DAT"), - SND_SOC_DAPM_INPUT("DMIC2DAT"), - - SND_SOC_DAPM_INPUT("IN1L"), - SND_SOC_DAPM_INPUT("IN1R"), - - SND_SOC_DAPM_MIXER("IN1L PGA", SND_SOC_NOPM, 0, 0, - &in1l_pga, 1), - SND_SOC_DAPM_MIXER("IN1R PGA", SND_SOC_NOPM, 0, 0, - &in1r_pga, 1), - - SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8995_POWER_MANAGEMENT_1, 8, 0, - NULL, 0), - SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8995_POWER_MANAGEMENT_1, 9, 0, - NULL, 0), - - SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8995_AIF1_CLOCKING_1, 0, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8995_AIF2_CLOCKING_1, 0, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("DSP1CLK", WM8995_CLOCKING_1, 3, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("DSP2CLK", WM8995_CLOCKING_1, 2, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("SYSDSPCLK", WM8995_CLOCKING_1, 1, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_AIF_OUT("AIF1ADC1L", "AIF1 Capture", 0, - WM8995_POWER_MANAGEMENT_3, 9, 0), - SND_SOC_DAPM_AIF_OUT("AIF1ADC1R", "AIF1 Capture", 0, - WM8995_POWER_MANAGEMENT_3, 8, 0), - SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", "AIF1 Capture", 0, - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_OUT("AIF1ADC2L", "AIF1 Capture", - 0, WM8995_POWER_MANAGEMENT_3, 11, 0), - SND_SOC_DAPM_AIF_OUT("AIF1ADC2R", "AIF1 Capture", - 0, WM8995_POWER_MANAGEMENT_3, 10, 0), - - SND_SOC_DAPM_VIRT_MUX("ADCL Mux", SND_SOC_NOPM, 1, 0, - &adcl_mux), - SND_SOC_DAPM_VIRT_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0, - &adcr_mux), - - SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8995_POWER_MANAGEMENT_3, 5, 0), - SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8995_POWER_MANAGEMENT_3, 4, 0), - SND_SOC_DAPM_ADC("DMIC1L", NULL, WM8995_POWER_MANAGEMENT_3, 3, 0), - SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8995_POWER_MANAGEMENT_3, 2, 0), - - SND_SOC_DAPM_ADC("ADCL", NULL, WM8995_POWER_MANAGEMENT_3, 1, 0), - SND_SOC_DAPM_ADC("ADCR", NULL, WM8995_POWER_MANAGEMENT_3, 0, 0), - - SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer", SND_SOC_NOPM, 0, 0, - aif1adc1l_mix, ARRAY_SIZE(aif1adc1l_mix)), - SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer", SND_SOC_NOPM, 0, 0, - aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)), - SND_SOC_DAPM_MIXER("AIF1ADC2L Mixer", SND_SOC_NOPM, 0, 0, - aif1adc2l_mix, ARRAY_SIZE(aif1adc2l_mix)), - SND_SOC_DAPM_MIXER("AIF1ADC2R Mixer", SND_SOC_NOPM, 0, 0, - aif1adc2r_mix, ARRAY_SIZE(aif1adc2r_mix)), - - SND_SOC_DAPM_AIF_IN("AIF1DAC1L", NULL, 0, WM8995_POWER_MANAGEMENT_4, - 9, 0), - SND_SOC_DAPM_AIF_IN("AIF1DAC1R", NULL, 0, WM8995_POWER_MANAGEMENT_4, - 8, 0), - SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, - 0, 0), - - SND_SOC_DAPM_AIF_IN("AIF1DAC2L", NULL, 0, WM8995_POWER_MANAGEMENT_4, - 11, 0), - SND_SOC_DAPM_AIF_IN("AIF1DAC2R", NULL, 0, WM8995_POWER_MANAGEMENT_4, - 10, 0), - - SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer", SND_SOC_NOPM, 0, 0, - aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)), - SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0, - aif2dac2r_mix, ARRAY_SIZE(aif2dac2r_mix)), - - SND_SOC_DAPM_DAC("DAC2L", NULL, WM8995_POWER_MANAGEMENT_4, 3, 0), - SND_SOC_DAPM_DAC("DAC2R", NULL, WM8995_POWER_MANAGEMENT_4, 2, 0), - SND_SOC_DAPM_DAC("DAC1L", NULL, WM8995_POWER_MANAGEMENT_4, 1, 0), - SND_SOC_DAPM_DAC("DAC1R", NULL, WM8995_POWER_MANAGEMENT_4, 0, 0), - - SND_SOC_DAPM_MIXER("DAC1L Mixer", SND_SOC_NOPM, 0, 0, dac1l_mix, - ARRAY_SIZE(dac1l_mix)), - SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SOC_NOPM, 0, 0, dac1r_mix, - ARRAY_SIZE(dac1r_mix)), - - SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &sidetone1_mux), - SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &sidetone2_mux), - - SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0, - hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, - hp_supply_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - - SND_SOC_DAPM_MUX("SPK1L Driver", WM8995_LEFT_PDM_SPEAKER_1, - 4, 0, &spk1l_mux), - SND_SOC_DAPM_MUX("SPK1R Driver", WM8995_RIGHT_PDM_SPEAKER_1, - 4, 0, &spk1r_mux), - SND_SOC_DAPM_MUX("SPK2L Driver", WM8995_LEFT_PDM_SPEAKER_2, - 4, 0, &spk2l_mux), - SND_SOC_DAPM_MUX("SPK2R Driver", WM8995_RIGHT_PDM_SPEAKER_2, - 4, 0, &spk2r_mux), - - SND_SOC_DAPM_SUPPLY("LDO2", WM8995_POWER_MANAGEMENT_2, 1, 0, NULL, 0), - - SND_SOC_DAPM_OUTPUT("HP1L"), - SND_SOC_DAPM_OUTPUT("HP1R"), - SND_SOC_DAPM_OUTPUT("SPK1L"), - SND_SOC_DAPM_OUTPUT("SPK1R"), - SND_SOC_DAPM_OUTPUT("SPK2L"), - SND_SOC_DAPM_OUTPUT("SPK2R") -}; - -static const struct snd_soc_dapm_route wm8995_intercon[] = { - { "CLK_SYS", NULL, "AIF1CLK", check_clk_sys }, - { "CLK_SYS", NULL, "AIF2CLK", check_clk_sys }, - - { "DSP1CLK", NULL, "CLK_SYS" }, - { "DSP2CLK", NULL, "CLK_SYS" }, - { "SYSDSPCLK", NULL, "CLK_SYS" }, - - { "AIF1ADC1L", NULL, "AIF1CLK" }, - { "AIF1ADC1L", NULL, "DSP1CLK" }, - { "AIF1ADC1R", NULL, "AIF1CLK" }, - { "AIF1ADC1R", NULL, "DSP1CLK" }, - { "AIF1ADC1R", NULL, "SYSDSPCLK" }, - - { "AIF1ADC2L", NULL, "AIF1CLK" }, - { "AIF1ADC2L", NULL, "DSP1CLK" }, - { "AIF1ADC2R", NULL, "AIF1CLK" }, - { "AIF1ADC2R", NULL, "DSP1CLK" }, - { "AIF1ADC2R", NULL, "SYSDSPCLK" }, - - { "DMIC1L", NULL, "DMIC1DAT" }, - { "DMIC1L", NULL, "CLK_SYS" }, - { "DMIC1R", NULL, "DMIC1DAT" }, - { "DMIC1R", NULL, "CLK_SYS" }, - { "DMIC2L", NULL, "DMIC2DAT" }, - { "DMIC2L", NULL, "CLK_SYS" }, - { "DMIC2R", NULL, "DMIC2DAT" }, - { "DMIC2R", NULL, "CLK_SYS" }, - - { "ADCL", NULL, "AIF1CLK" }, - { "ADCL", NULL, "DSP1CLK" }, - { "ADCL", NULL, "SYSDSPCLK" }, - - { "ADCR", NULL, "AIF1CLK" }, - { "ADCR", NULL, "DSP1CLK" }, - { "ADCR", NULL, "SYSDSPCLK" }, - - { "IN1L PGA", "IN1L Switch", "IN1L" }, - { "IN1R PGA", "IN1R Switch", "IN1R" }, - { "IN1L PGA", NULL, "LDO2" }, - { "IN1R PGA", NULL, "LDO2" }, - - { "ADCL", NULL, "IN1L PGA" }, - { "ADCR", NULL, "IN1R PGA" }, - - { "ADCL Mux", "ADC", "ADCL" }, - { "ADCL Mux", "DMIC", "DMIC1L" }, - { "ADCR Mux", "ADC", "ADCR" }, - { "ADCR Mux", "DMIC", "DMIC1R" }, - - /* AIF1 outputs */ - { "AIF1ADC1L", NULL, "AIF1ADC1L Mixer" }, - { "AIF1ADC1L Mixer", "ADC/DMIC Switch", "ADCL Mux" }, - - { "AIF1ADC1R", NULL, "AIF1ADC1R Mixer" }, - { "AIF1ADC1R Mixer", "ADC/DMIC Switch", "ADCR Mux" }, - - { "AIF1ADC2L", NULL, "AIF1ADC2L Mixer" }, - { "AIF1ADC2L Mixer", "DMIC Switch", "DMIC2L" }, - - { "AIF1ADC2R", NULL, "AIF1ADC2R Mixer" }, - { "AIF1ADC2R Mixer", "DMIC Switch", "DMIC2R" }, - - /* Sidetone */ - { "Left Sidetone", "ADC/DMIC1", "AIF1ADC1L" }, - { "Left Sidetone", "DMIC2", "AIF1ADC2L" }, - { "Right Sidetone", "ADC/DMIC1", "AIF1ADC1R" }, - { "Right Sidetone", "DMIC2", "AIF1ADC2R" }, - - { "AIF1DAC1L", NULL, "AIF1CLK" }, - { "AIF1DAC1L", NULL, "DSP1CLK" }, - { "AIF1DAC1R", NULL, "AIF1CLK" }, - { "AIF1DAC1R", NULL, "DSP1CLK" }, - { "AIF1DAC1R", NULL, "SYSDSPCLK" }, - - { "AIF1DAC2L", NULL, "AIF1CLK" }, - { "AIF1DAC2L", NULL, "DSP1CLK" }, - { "AIF1DAC2R", NULL, "AIF1CLK" }, - { "AIF1DAC2R", NULL, "DSP1CLK" }, - { "AIF1DAC2R", NULL, "SYSDSPCLK" }, - - { "DAC1L", NULL, "AIF1CLK" }, - { "DAC1L", NULL, "DSP1CLK" }, - { "DAC1L", NULL, "SYSDSPCLK" }, - - { "DAC1R", NULL, "AIF1CLK" }, - { "DAC1R", NULL, "DSP1CLK" }, - { "DAC1R", NULL, "SYSDSPCLK" }, - - { "AIF1DAC1L", NULL, "AIF1DACDAT" }, - { "AIF1DAC1R", NULL, "AIF1DACDAT" }, - { "AIF1DAC2L", NULL, "AIF1DACDAT" }, - { "AIF1DAC2R", NULL, "AIF1DACDAT" }, - - /* DAC1 inputs */ - { "DAC1L", NULL, "DAC1L Mixer" }, - { "DAC1L Mixer", "AIF1.1 Switch", "AIF1DAC1L" }, - { "DAC1L Mixer", "AIF1.2 Switch", "AIF1DAC2L" }, - { "DAC1L Mixer", "Left Sidetone Switch", "Left Sidetone" }, - { "DAC1L Mixer", "Right Sidetone Switch", "Right Sidetone" }, - - { "DAC1R", NULL, "DAC1R Mixer" }, - { "DAC1R Mixer", "AIF1.1 Switch", "AIF1DAC1R" }, - { "DAC1R Mixer", "AIF1.2 Switch", "AIF1DAC2R" }, - { "DAC1R Mixer", "Left Sidetone Switch", "Left Sidetone" }, - { "DAC1R Mixer", "Right Sidetone Switch", "Right Sidetone" }, - - /* DAC2/AIF2 outputs */ - { "DAC2L", NULL, "AIF2DAC2L Mixer" }, - { "AIF2DAC2L Mixer", "AIF1.2 Switch", "AIF1DAC2L" }, - { "AIF2DAC2L Mixer", "AIF1.1 Switch", "AIF1DAC1L" }, - - { "DAC2R", NULL, "AIF2DAC2R Mixer" }, - { "AIF2DAC2R Mixer", "AIF1.2 Switch", "AIF1DAC2R" }, - { "AIF2DAC2R Mixer", "AIF1.1 Switch", "AIF1DAC1R" }, - - /* Output stages */ - { "Headphone PGA", NULL, "DAC1L" }, - { "Headphone PGA", NULL, "DAC1R" }, - - { "Headphone PGA", NULL, "DAC2L" }, - { "Headphone PGA", NULL, "DAC2R" }, - - { "Headphone PGA", NULL, "Headphone Supply" }, - { "Headphone PGA", NULL, "CLK_SYS" }, - { "Headphone PGA", NULL, "LDO2" }, - - { "HP1L", NULL, "Headphone PGA" }, - { "HP1R", NULL, "Headphone PGA" }, - - { "SPK1L Driver", "DAC1L", "DAC1L" }, - { "SPK1L Driver", "DAC1R", "DAC1R" }, - { "SPK1L Driver", "DAC2L", "DAC2L" }, - { "SPK1L Driver", "DAC2R", "DAC2R" }, - { "SPK1L Driver", NULL, "CLK_SYS" }, - - { "SPK1R Driver", "DAC1L", "DAC1L" }, - { "SPK1R Driver", "DAC1R", "DAC1R" }, - { "SPK1R Driver", "DAC2L", "DAC2L" }, - { "SPK1R Driver", "DAC2R", "DAC2R" }, - { "SPK1R Driver", NULL, "CLK_SYS" }, - - { "SPK2L Driver", "DAC1L", "DAC1L" }, - { "SPK2L Driver", "DAC1R", "DAC1R" }, - { "SPK2L Driver", "DAC2L", "DAC2L" }, - { "SPK2L Driver", "DAC2R", "DAC2R" }, - { "SPK2L Driver", NULL, "CLK_SYS" }, - - { "SPK2R Driver", "DAC1L", "DAC1L" }, - { "SPK2R Driver", "DAC1R", "DAC1R" }, - { "SPK2R Driver", "DAC2L", "DAC2L" }, - { "SPK2R Driver", "DAC2R", "DAC2R" }, - { "SPK2R Driver", NULL, "CLK_SYS" }, - - { "SPK1L", NULL, "SPK1L Driver" }, - { "SPK1R", NULL, "SPK1R Driver" }, - { "SPK2L", NULL, "SPK2L Driver" }, - { "SPK2R", NULL, "SPK2R Driver" } -}; - -static bool wm8995_readable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8995_SOFTWARE_RESET: - case WM8995_POWER_MANAGEMENT_1: - case WM8995_POWER_MANAGEMENT_2: - case WM8995_POWER_MANAGEMENT_3: - case WM8995_POWER_MANAGEMENT_4: - case WM8995_POWER_MANAGEMENT_5: - case WM8995_LEFT_LINE_INPUT_1_VOLUME: - case WM8995_RIGHT_LINE_INPUT_1_VOLUME: - case WM8995_LEFT_LINE_INPUT_CONTROL: - case WM8995_DAC1_LEFT_VOLUME: - case WM8995_DAC1_RIGHT_VOLUME: - case WM8995_DAC2_LEFT_VOLUME: - case WM8995_DAC2_RIGHT_VOLUME: - case WM8995_OUTPUT_VOLUME_ZC_1: - case WM8995_MICBIAS_1: - case WM8995_MICBIAS_2: - case WM8995_LDO_1: - case WM8995_LDO_2: - case WM8995_ACCESSORY_DETECT_MODE1: - case WM8995_ACCESSORY_DETECT_MODE2: - case WM8995_HEADPHONE_DETECT1: - case WM8995_HEADPHONE_DETECT2: - case WM8995_MIC_DETECT_1: - case WM8995_MIC_DETECT_2: - case WM8995_CHARGE_PUMP_1: - case WM8995_CLASS_W_1: - case WM8995_DC_SERVO_1: - case WM8995_DC_SERVO_2: - case WM8995_DC_SERVO_3: - case WM8995_DC_SERVO_5: - case WM8995_DC_SERVO_6: - case WM8995_DC_SERVO_7: - case WM8995_DC_SERVO_READBACK_0: - case WM8995_ANALOGUE_HP_1: - case WM8995_ANALOGUE_HP_2: - case WM8995_CHIP_REVISION: - case WM8995_CONTROL_INTERFACE_1: - case WM8995_CONTROL_INTERFACE_2: - case WM8995_WRITE_SEQUENCER_CTRL_1: - case WM8995_WRITE_SEQUENCER_CTRL_2: - case WM8995_AIF1_CLOCKING_1: - case WM8995_AIF1_CLOCKING_2: - case WM8995_AIF2_CLOCKING_1: - case WM8995_AIF2_CLOCKING_2: - case WM8995_CLOCKING_1: - case WM8995_CLOCKING_2: - case WM8995_AIF1_RATE: - case WM8995_AIF2_RATE: - case WM8995_RATE_STATUS: - case WM8995_FLL1_CONTROL_1: - case WM8995_FLL1_CONTROL_2: - case WM8995_FLL1_CONTROL_3: - case WM8995_FLL1_CONTROL_4: - case WM8995_FLL1_CONTROL_5: - case WM8995_FLL2_CONTROL_1: - case WM8995_FLL2_CONTROL_2: - case WM8995_FLL2_CONTROL_3: - case WM8995_FLL2_CONTROL_4: - case WM8995_FLL2_CONTROL_5: - case WM8995_AIF1_CONTROL_1: - case WM8995_AIF1_CONTROL_2: - case WM8995_AIF1_MASTER_SLAVE: - case WM8995_AIF1_BCLK: - case WM8995_AIF1ADC_LRCLK: - case WM8995_AIF1DAC_LRCLK: - case WM8995_AIF1DAC_DATA: - case WM8995_AIF1ADC_DATA: - case WM8995_AIF2_CONTROL_1: - case WM8995_AIF2_CONTROL_2: - case WM8995_AIF2_MASTER_SLAVE: - case WM8995_AIF2_BCLK: - case WM8995_AIF2ADC_LRCLK: - case WM8995_AIF2DAC_LRCLK: - case WM8995_AIF2DAC_DATA: - case WM8995_AIF2ADC_DATA: - case WM8995_AIF1_ADC1_LEFT_VOLUME: - case WM8995_AIF1_ADC1_RIGHT_VOLUME: - case WM8995_AIF1_DAC1_LEFT_VOLUME: - case WM8995_AIF1_DAC1_RIGHT_VOLUME: - case WM8995_AIF1_ADC2_LEFT_VOLUME: - case WM8995_AIF1_ADC2_RIGHT_VOLUME: - case WM8995_AIF1_DAC2_LEFT_VOLUME: - case WM8995_AIF1_DAC2_RIGHT_VOLUME: - case WM8995_AIF1_ADC1_FILTERS: - case WM8995_AIF1_ADC2_FILTERS: - case WM8995_AIF1_DAC1_FILTERS_1: - case WM8995_AIF1_DAC1_FILTERS_2: - case WM8995_AIF1_DAC2_FILTERS_1: - case WM8995_AIF1_DAC2_FILTERS_2: - case WM8995_AIF1_DRC1_1: - case WM8995_AIF1_DRC1_2: - case WM8995_AIF1_DRC1_3: - case WM8995_AIF1_DRC1_4: - case WM8995_AIF1_DRC1_5: - case WM8995_AIF1_DRC2_1: - case WM8995_AIF1_DRC2_2: - case WM8995_AIF1_DRC2_3: - case WM8995_AIF1_DRC2_4: - case WM8995_AIF1_DRC2_5: - case WM8995_AIF1_DAC1_EQ_GAINS_1: - case WM8995_AIF1_DAC1_EQ_GAINS_2: - case WM8995_AIF1_DAC1_EQ_BAND_1_A: - case WM8995_AIF1_DAC1_EQ_BAND_1_B: - case WM8995_AIF1_DAC1_EQ_BAND_1_PG: - case WM8995_AIF1_DAC1_EQ_BAND_2_A: - case WM8995_AIF1_DAC1_EQ_BAND_2_B: - case WM8995_AIF1_DAC1_EQ_BAND_2_C: - case WM8995_AIF1_DAC1_EQ_BAND_2_PG: - case WM8995_AIF1_DAC1_EQ_BAND_3_A: - case WM8995_AIF1_DAC1_EQ_BAND_3_B: - case WM8995_AIF1_DAC1_EQ_BAND_3_C: - case WM8995_AIF1_DAC1_EQ_BAND_3_PG: - case WM8995_AIF1_DAC1_EQ_BAND_4_A: - case WM8995_AIF1_DAC1_EQ_BAND_4_B: - case WM8995_AIF1_DAC1_EQ_BAND_4_C: - case WM8995_AIF1_DAC1_EQ_BAND_4_PG: - case WM8995_AIF1_DAC1_EQ_BAND_5_A: - case WM8995_AIF1_DAC1_EQ_BAND_5_B: - case WM8995_AIF1_DAC1_EQ_BAND_5_PG: - case WM8995_AIF1_DAC2_EQ_GAINS_1: - case WM8995_AIF1_DAC2_EQ_GAINS_2: - case WM8995_AIF1_DAC2_EQ_BAND_1_A: - case WM8995_AIF1_DAC2_EQ_BAND_1_B: - case WM8995_AIF1_DAC2_EQ_BAND_1_PG: - case WM8995_AIF1_DAC2_EQ_BAND_2_A: - case WM8995_AIF1_DAC2_EQ_BAND_2_B: - case WM8995_AIF1_DAC2_EQ_BAND_2_C: - case WM8995_AIF1_DAC2_EQ_BAND_2_PG: - case WM8995_AIF1_DAC2_EQ_BAND_3_A: - case WM8995_AIF1_DAC2_EQ_BAND_3_B: - case WM8995_AIF1_DAC2_EQ_BAND_3_C: - case WM8995_AIF1_DAC2_EQ_BAND_3_PG: - case WM8995_AIF1_DAC2_EQ_BAND_4_A: - case WM8995_AIF1_DAC2_EQ_BAND_4_B: - case WM8995_AIF1_DAC2_EQ_BAND_4_C: - case WM8995_AIF1_DAC2_EQ_BAND_4_PG: - case WM8995_AIF1_DAC2_EQ_BAND_5_A: - case WM8995_AIF1_DAC2_EQ_BAND_5_B: - case WM8995_AIF1_DAC2_EQ_BAND_5_PG: - case WM8995_AIF2_ADC_LEFT_VOLUME: - case WM8995_AIF2_ADC_RIGHT_VOLUME: - case WM8995_AIF2_DAC_LEFT_VOLUME: - case WM8995_AIF2_DAC_RIGHT_VOLUME: - case WM8995_AIF2_ADC_FILTERS: - case WM8995_AIF2_DAC_FILTERS_1: - case WM8995_AIF2_DAC_FILTERS_2: - case WM8995_AIF2_DRC_1: - case WM8995_AIF2_DRC_2: - case WM8995_AIF2_DRC_3: - case WM8995_AIF2_DRC_4: - case WM8995_AIF2_DRC_5: - case WM8995_AIF2_EQ_GAINS_1: - case WM8995_AIF2_EQ_GAINS_2: - case WM8995_AIF2_EQ_BAND_1_A: - case WM8995_AIF2_EQ_BAND_1_B: - case WM8995_AIF2_EQ_BAND_1_PG: - case WM8995_AIF2_EQ_BAND_2_A: - case WM8995_AIF2_EQ_BAND_2_B: - case WM8995_AIF2_EQ_BAND_2_C: - case WM8995_AIF2_EQ_BAND_2_PG: - case WM8995_AIF2_EQ_BAND_3_A: - case WM8995_AIF2_EQ_BAND_3_B: - case WM8995_AIF2_EQ_BAND_3_C: - case WM8995_AIF2_EQ_BAND_3_PG: - case WM8995_AIF2_EQ_BAND_4_A: - case WM8995_AIF2_EQ_BAND_4_B: - case WM8995_AIF2_EQ_BAND_4_C: - case WM8995_AIF2_EQ_BAND_4_PG: - case WM8995_AIF2_EQ_BAND_5_A: - case WM8995_AIF2_EQ_BAND_5_B: - case WM8995_AIF2_EQ_BAND_5_PG: - case WM8995_DAC1_MIXER_VOLUMES: - case WM8995_DAC1_LEFT_MIXER_ROUTING: - case WM8995_DAC1_RIGHT_MIXER_ROUTING: - case WM8995_DAC2_MIXER_VOLUMES: - case WM8995_DAC2_LEFT_MIXER_ROUTING: - case WM8995_DAC2_RIGHT_MIXER_ROUTING: - case WM8995_AIF1_ADC1_LEFT_MIXER_ROUTING: - case WM8995_AIF1_ADC1_RIGHT_MIXER_ROUTING: - case WM8995_AIF1_ADC2_LEFT_MIXER_ROUTING: - case WM8995_AIF1_ADC2_RIGHT_MIXER_ROUTING: - case WM8995_DAC_SOFTMUTE: - case WM8995_OVERSAMPLING: - case WM8995_SIDETONE: - case WM8995_GPIO_1: - case WM8995_GPIO_2: - case WM8995_GPIO_3: - case WM8995_GPIO_4: - case WM8995_GPIO_5: - case WM8995_GPIO_6: - case WM8995_GPIO_7: - case WM8995_GPIO_8: - case WM8995_GPIO_9: - case WM8995_GPIO_10: - case WM8995_GPIO_11: - case WM8995_GPIO_12: - case WM8995_GPIO_13: - case WM8995_GPIO_14: - case WM8995_PULL_CONTROL_1: - case WM8995_PULL_CONTROL_2: - case WM8995_INTERRUPT_STATUS_1: - case WM8995_INTERRUPT_STATUS_2: - case WM8995_INTERRUPT_RAW_STATUS_2: - case WM8995_INTERRUPT_STATUS_1_MASK: - case WM8995_INTERRUPT_STATUS_2_MASK: - case WM8995_INTERRUPT_CONTROL: - case WM8995_LEFT_PDM_SPEAKER_1: - case WM8995_RIGHT_PDM_SPEAKER_1: - case WM8995_PDM_SPEAKER_1_MUTE_SEQUENCE: - case WM8995_LEFT_PDM_SPEAKER_2: - case WM8995_RIGHT_PDM_SPEAKER_2: - case WM8995_PDM_SPEAKER_2_MUTE_SEQUENCE: - return true; - default: - return false; - } -} - -static bool wm8995_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8995_SOFTWARE_RESET: - case WM8995_DC_SERVO_READBACK_0: - case WM8995_INTERRUPT_STATUS_1: - case WM8995_INTERRUPT_STATUS_2: - case WM8995_INTERRUPT_CONTROL: - case WM8995_ACCESSORY_DETECT_MODE1: - case WM8995_ACCESSORY_DETECT_MODE2: - case WM8995_HEADPHONE_DETECT1: - case WM8995_HEADPHONE_DETECT2: - case WM8995_RATE_STATUS: - return true; - default: - return false; - } -} - -static int wm8995_aif_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - int mute_reg; - - switch (dai->id) { - case 0: - mute_reg = WM8995_AIF1_DAC1_FILTERS_1; - break; - case 1: - mute_reg = WM8995_AIF2_DAC_FILTERS_1; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, mute_reg, WM8995_AIF1DAC1_MUTE_MASK, - !!mute << WM8995_AIF1DAC1_MUTE_SHIFT); - return 0; -} - -static int wm8995_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec; - int master; - int aif; - - codec = dai->codec; - - master = 0; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBM_CFM: - master = WM8995_AIF1_MSTR; - break; - default: - dev_err(dai->dev, "Unknown master/slave configuration\n"); - return -EINVAL; - } - - aif = 0; - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif |= WM8995_AIF1_LRCLK_INV; - case SND_SOC_DAIFMT_DSP_A: - aif |= (0x3 << WM8995_AIF1_FMT_SHIFT); - break; - case SND_SOC_DAIFMT_I2S: - aif |= (0x2 << WM8995_AIF1_FMT_SHIFT); - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif |= (0x1 << WM8995_AIF1_FMT_SHIFT); - break; - default: - dev_err(dai->dev, "Unknown dai format\n"); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif |= WM8995_AIF1_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif |= WM8995_AIF1_BCLK_INV | WM8995_AIF1_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif |= WM8995_AIF1_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif |= WM8995_AIF1_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, WM8995_AIF1_CONTROL_1, - WM8995_AIF1_BCLK_INV_MASK | - WM8995_AIF1_LRCLK_INV_MASK | - WM8995_AIF1_FMT_MASK, aif); - snd_soc_update_bits(codec, WM8995_AIF1_MASTER_SLAVE, - WM8995_AIF1_MSTR_MASK, master); - return 0; -} - -static const int srs[] = { - 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, - 48000, 88200, 96000 -}; - -static const int fs_ratios[] = { - -1 /* reserved */, - 128, 192, 256, 384, 512, 768, 1024, 1408, 1536 -}; - -static const int bclk_divs[] = { - 10, 15, 20, 30, 40, 55, 60, 80, 110, 120, 160, 220, 240, 320, 440, 480 -}; - -static int wm8995_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec; - struct wm8995_priv *wm8995; - int aif1_reg; - int bclk_reg; - int lrclk_reg; - int rate_reg; - int bclk_rate; - int aif1; - int lrclk, bclk; - int i, rate_val, best, best_val, cur_val; - - codec = dai->codec; - wm8995 = snd_soc_codec_get_drvdata(codec); - - switch (dai->id) { - case 0: - aif1_reg = WM8995_AIF1_CONTROL_1; - bclk_reg = WM8995_AIF1_BCLK; - rate_reg = WM8995_AIF1_RATE; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK /* || - wm8995->lrclk_shared[0] */) { - lrclk_reg = WM8995_AIF1DAC_LRCLK; - } else { - lrclk_reg = WM8995_AIF1ADC_LRCLK; - dev_dbg(codec->dev, "AIF1 using split LRCLK\n"); - } - break; - case 1: - aif1_reg = WM8995_AIF2_CONTROL_1; - bclk_reg = WM8995_AIF2_BCLK; - rate_reg = WM8995_AIF2_RATE; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK /* || - wm8995->lrclk_shared[1] */) { - lrclk_reg = WM8995_AIF2DAC_LRCLK; - } else { - lrclk_reg = WM8995_AIF2ADC_LRCLK; - dev_dbg(codec->dev, "AIF2 using split LRCLK\n"); - } - break; - default: - return -EINVAL; - } - - bclk_rate = snd_soc_params_to_bclk(params); - if (bclk_rate < 0) - return bclk_rate; - - aif1 = 0; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - aif1 |= (0x1 << WM8995_AIF1_WL_SHIFT); - break; - case SNDRV_PCM_FORMAT_S24_LE: - aif1 |= (0x2 << WM8995_AIF1_WL_SHIFT); - break; - case SNDRV_PCM_FORMAT_S32_LE: - aif1 |= (0x3 << WM8995_AIF1_WL_SHIFT); - break; - default: - dev_err(dai->dev, "Unsupported word length %u\n", - params_format(params)); - return -EINVAL; - } - - /* try to find a suitable sample rate */ - for (i = 0; i < ARRAY_SIZE(srs); ++i) - if (srs[i] == params_rate(params)) - break; - if (i == ARRAY_SIZE(srs)) { - dev_err(dai->dev, "Sample rate %d is not supported\n", - params_rate(params)); - return -EINVAL; - } - rate_val = i << WM8995_AIF1_SR_SHIFT; - - dev_dbg(dai->dev, "Sample rate is %dHz\n", srs[i]); - dev_dbg(dai->dev, "AIF%dCLK is %dHz, target BCLK %dHz\n", - dai->id + 1, wm8995->aifclk[dai->id], bclk_rate); - - /* AIFCLK/fs ratio; look for a close match in either direction */ - best = 1; - best_val = abs((fs_ratios[1] * params_rate(params)) - - wm8995->aifclk[dai->id]); - for (i = 2; i < ARRAY_SIZE(fs_ratios); i++) { - cur_val = abs((fs_ratios[i] * params_rate(params)) - - wm8995->aifclk[dai->id]); - if (cur_val >= best_val) - continue; - best = i; - best_val = cur_val; - } - rate_val |= best; - - dev_dbg(dai->dev, "Selected AIF%dCLK/fs = %d\n", - dai->id + 1, fs_ratios[best]); - - /* - * We may not get quite the right frequency if using - * approximate clocks so look for the closest match that is - * higher than the target (we need to ensure that there enough - * BCLKs to clock out the samples). - */ - best = 0; - bclk = 0; - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - cur_val = (wm8995->aifclk[dai->id] * 10 / bclk_divs[i]) - bclk_rate; - if (cur_val < 0) /* BCLK table is sorted */ - break; - best = i; - } - bclk |= best << WM8995_AIF1_BCLK_DIV_SHIFT; - - bclk_rate = wm8995->aifclk[dai->id] * 10 / bclk_divs[best]; - dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", - bclk_divs[best], bclk_rate); - - lrclk = bclk_rate / params_rate(params); - dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", - lrclk, bclk_rate / lrclk); - - snd_soc_update_bits(codec, aif1_reg, - WM8995_AIF1_WL_MASK, aif1); - snd_soc_update_bits(codec, bclk_reg, - WM8995_AIF1_BCLK_DIV_MASK, bclk); - snd_soc_update_bits(codec, lrclk_reg, - WM8995_AIF1DAC_RATE_MASK, lrclk); - snd_soc_update_bits(codec, rate_reg, - WM8995_AIF1_SR_MASK | - WM8995_AIF1CLK_RATE_MASK, rate_val); - return 0; -} - -static int wm8995_set_tristate(struct snd_soc_dai *codec_dai, int tristate) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int reg, val, mask; - - switch (codec_dai->id) { - case 0: - reg = WM8995_AIF1_MASTER_SLAVE; - mask = WM8995_AIF1_TRI; - break; - case 1: - reg = WM8995_AIF2_MASTER_SLAVE; - mask = WM8995_AIF2_TRI; - break; - case 2: - reg = WM8995_POWER_MANAGEMENT_5; - mask = WM8995_AIF3_TRI; - break; - default: - return -EINVAL; - } - - if (tristate) - val = mask; - else - val = 0; - - return snd_soc_update_bits(codec, reg, mask, val); -} - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -struct fll_div { - u16 outdiv; - u16 n; - u16 k; - u16 clk_ref_div; - u16 fll_fratio; -}; - -static int wm8995_get_fll_config(struct fll_div *fll, - int freq_in, int freq_out) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod; - - pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out); - - /* Scale the input frequency down to <= 13.5MHz */ - fll->clk_ref_div = 0; - while (freq_in > 13500000) { - fll->clk_ref_div++; - freq_in /= 2; - - if (fll->clk_ref_div > 3) - return -EINVAL; - } - pr_debug("CLK_REF_DIV=%d, Fref=%dHz\n", fll->clk_ref_div, freq_in); - - /* Scale the output to give 90MHz<=Fvco<=100MHz */ - fll->outdiv = 3; - while (freq_out * (fll->outdiv + 1) < 90000000) { - fll->outdiv++; - if (fll->outdiv > 63) - return -EINVAL; - } - freq_out *= fll->outdiv + 1; - pr_debug("OUTDIV=%d, Fvco=%dHz\n", fll->outdiv, freq_out); - - if (freq_in > 1000000) { - fll->fll_fratio = 0; - } else if (freq_in > 256000) { - fll->fll_fratio = 1; - freq_in *= 2; - } else if (freq_in > 128000) { - fll->fll_fratio = 2; - freq_in *= 4; - } else if (freq_in > 64000) { - fll->fll_fratio = 3; - freq_in *= 8; - } else { - fll->fll_fratio = 4; - freq_in *= 16; - } - pr_debug("FLL_FRATIO=%d, Fref=%dHz\n", fll->fll_fratio, freq_in); - - /* Now, calculate N.K */ - Ndiv = freq_out / freq_in; - - fll->n = Ndiv; - Nmod = freq_out % freq_in; - pr_debug("Nmod=%d\n", Nmod); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, freq_in); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - fll->k = K / 10; - - pr_debug("N=%x K=%x\n", fll->n, fll->k); - - return 0; -} - -static int wm8995_set_fll(struct snd_soc_dai *dai, int id, - int src, unsigned int freq_in, - unsigned int freq_out) -{ - struct snd_soc_codec *codec; - struct wm8995_priv *wm8995; - int reg_offset, ret; - struct fll_div fll; - u16 reg, aif1, aif2; - - codec = dai->codec; - wm8995 = snd_soc_codec_get_drvdata(codec); - - aif1 = snd_soc_read(codec, WM8995_AIF1_CLOCKING_1) - & WM8995_AIF1CLK_ENA; - - aif2 = snd_soc_read(codec, WM8995_AIF2_CLOCKING_1) - & WM8995_AIF2CLK_ENA; - - switch (id) { - case WM8995_FLL1: - reg_offset = 0; - id = 0; - break; - case WM8995_FLL2: - reg_offset = 0x20; - id = 1; - break; - default: - return -EINVAL; - } - - switch (src) { - case 0: - /* Allow no source specification when stopping */ - if (freq_out) - return -EINVAL; - break; - case WM8995_FLL_SRC_MCLK1: - case WM8995_FLL_SRC_MCLK2: - case WM8995_FLL_SRC_LRCLK: - case WM8995_FLL_SRC_BCLK: - break; - default: - return -EINVAL; - } - - /* Are we changing anything? */ - if (wm8995->fll[id].src == src && - wm8995->fll[id].in == freq_in && wm8995->fll[id].out == freq_out) - return 0; - - /* If we're stopping the FLL redo the old config - no - * registers will actually be written but we avoid GCC flow - * analysis bugs spewing warnings. - */ - if (freq_out) - ret = wm8995_get_fll_config(&fll, freq_in, freq_out); - else - ret = wm8995_get_fll_config(&fll, wm8995->fll[id].in, - wm8995->fll[id].out); - if (ret < 0) - return ret; - - /* Gate the AIF clocks while we reclock */ - snd_soc_update_bits(codec, WM8995_AIF1_CLOCKING_1, - WM8995_AIF1CLK_ENA_MASK, 0); - snd_soc_update_bits(codec, WM8995_AIF2_CLOCKING_1, - WM8995_AIF2CLK_ENA_MASK, 0); - - /* We always need to disable the FLL while reconfiguring */ - snd_soc_update_bits(codec, WM8995_FLL1_CONTROL_1 + reg_offset, - WM8995_FLL1_ENA_MASK, 0); - - reg = (fll.outdiv << WM8995_FLL1_OUTDIV_SHIFT) | - (fll.fll_fratio << WM8995_FLL1_FRATIO_SHIFT); - snd_soc_update_bits(codec, WM8995_FLL1_CONTROL_2 + reg_offset, - WM8995_FLL1_OUTDIV_MASK | - WM8995_FLL1_FRATIO_MASK, reg); - - snd_soc_write(codec, WM8995_FLL1_CONTROL_3 + reg_offset, fll.k); - - snd_soc_update_bits(codec, WM8995_FLL1_CONTROL_4 + reg_offset, - WM8995_FLL1_N_MASK, - fll.n << WM8995_FLL1_N_SHIFT); - - snd_soc_update_bits(codec, WM8995_FLL1_CONTROL_5 + reg_offset, - WM8995_FLL1_REFCLK_DIV_MASK | - WM8995_FLL1_REFCLK_SRC_MASK, - (fll.clk_ref_div << WM8995_FLL1_REFCLK_DIV_SHIFT) | - (src - 1)); - - if (freq_out) - snd_soc_update_bits(codec, WM8995_FLL1_CONTROL_1 + reg_offset, - WM8995_FLL1_ENA_MASK, WM8995_FLL1_ENA); - - wm8995->fll[id].in = freq_in; - wm8995->fll[id].out = freq_out; - wm8995->fll[id].src = src; - - /* Enable any gated AIF clocks */ - snd_soc_update_bits(codec, WM8995_AIF1_CLOCKING_1, - WM8995_AIF1CLK_ENA_MASK, aif1); - snd_soc_update_bits(codec, WM8995_AIF2_CLOCKING_1, - WM8995_AIF2CLK_ENA_MASK, aif2); - - configure_clock(codec); - - return 0; -} - -static int wm8995_set_dai_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec; - struct wm8995_priv *wm8995; - - codec = dai->codec; - wm8995 = snd_soc_codec_get_drvdata(codec); - - switch (dai->id) { - case 0: - case 1: - break; - default: - /* AIF3 shares clocking with AIF1/2 */ - return -EINVAL; - } - - switch (clk_id) { - case WM8995_SYSCLK_MCLK1: - wm8995->sysclk[dai->id] = WM8995_SYSCLK_MCLK1; - wm8995->mclk[0] = freq; - dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n", - dai->id + 1, freq); - break; - case WM8995_SYSCLK_MCLK2: - wm8995->sysclk[dai->id] = WM8995_SYSCLK_MCLK1; - wm8995->mclk[1] = freq; - dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n", - dai->id + 1, freq); - break; - case WM8995_SYSCLK_FLL1: - wm8995->sysclk[dai->id] = WM8995_SYSCLK_FLL1; - dev_dbg(dai->dev, "AIF%d using FLL1\n", dai->id + 1); - break; - case WM8995_SYSCLK_FLL2: - wm8995->sysclk[dai->id] = WM8995_SYSCLK_FLL2; - dev_dbg(dai->dev, "AIF%d using FLL2\n", dai->id + 1); - break; - case WM8995_SYSCLK_OPCLK: - default: - dev_err(dai->dev, "Unknown clock source %d\n", clk_id); - return -EINVAL; - } - - configure_clock(codec); - - return 0; -} - -static int wm8995_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8995_priv *wm8995; - int ret; - - wm8995 = snd_soc_codec_get_drvdata(codec); - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies), - wm8995->supplies); - if (ret) - return ret; - - ret = regcache_sync(wm8995->regmap); - if (ret) { - dev_err(codec->dev, - "Failed to sync cache: %d\n", ret); - return ret; - } - - snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, - WM8995_BG_ENA_MASK, WM8995_BG_ENA); - } - break; - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, - WM8995_BG_ENA_MASK, 0); - regulator_bulk_disable(ARRAY_SIZE(wm8995->supplies), - wm8995->supplies); - break; - } - - codec->dapm.bias_level = level; - return 0; -} - -#ifdef CONFIG_PM -static int wm8995_suspend(struct snd_soc_codec *codec) -{ - wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8995_resume(struct snd_soc_codec *codec) -{ - wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} -#else -#define wm8995_suspend NULL -#define wm8995_resume NULL -#endif - -static int wm8995_remove(struct snd_soc_codec *codec) -{ - struct wm8995_priv *wm8995; - int i; - - wm8995 = snd_soc_codec_get_drvdata(codec); - wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); - - for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i) - regulator_unregister_notifier(wm8995->supplies[i].consumer, - &wm8995->disable_nb[i]); - - regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies); - return 0; -} - -static int wm8995_probe(struct snd_soc_codec *codec) -{ - struct wm8995_priv *wm8995; - int i; - int ret; - - wm8995 = snd_soc_codec_get_drvdata(codec); - wm8995->codec = codec; - - codec->control_data = wm8995->regmap; - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); - return ret; - } - - for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) - wm8995->supplies[i].supply = wm8995_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8995->supplies), - wm8995->supplies); - if (ret) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - return ret; - } - - wm8995->disable_nb[0].notifier_call = wm8995_regulator_event_0; - wm8995->disable_nb[1].notifier_call = wm8995_regulator_event_1; - wm8995->disable_nb[2].notifier_call = wm8995_regulator_event_2; - wm8995->disable_nb[3].notifier_call = wm8995_regulator_event_3; - wm8995->disable_nb[4].notifier_call = wm8995_regulator_event_4; - wm8995->disable_nb[5].notifier_call = wm8995_regulator_event_5; - wm8995->disable_nb[6].notifier_call = wm8995_regulator_event_6; - wm8995->disable_nb[7].notifier_call = wm8995_regulator_event_7; - - /* This should really be moved into the regulator core */ - for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) { - ret = regulator_register_notifier(wm8995->supplies[i].consumer, - &wm8995->disable_nb[i]); - if (ret) { - dev_err(codec->dev, - "Failed to register regulator notifier: %d\n", - ret); - } - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies), - wm8995->supplies); - if (ret) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_reg_get; - } - - ret = snd_soc_read(codec, WM8995_SOFTWARE_RESET); - if (ret < 0) { - dev_err(codec->dev, "Failed to read device ID: %d\n", ret); - goto err_reg_enable; - } - - if (ret != 0x8995) { - dev_err(codec->dev, "Invalid device ID: %#x\n", ret); - ret = -EINVAL; - goto err_reg_enable; - } - - ret = snd_soc_write(codec, WM8995_SOFTWARE_RESET, 0); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err_reg_enable; - } - - wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch volume updates (right only; we always do left then right). */ - snd_soc_update_bits(codec, WM8995_AIF1_DAC1_RIGHT_VOLUME, - WM8995_AIF1DAC1_VU_MASK, WM8995_AIF1DAC1_VU); - snd_soc_update_bits(codec, WM8995_AIF1_DAC2_RIGHT_VOLUME, - WM8995_AIF1DAC2_VU_MASK, WM8995_AIF1DAC2_VU); - snd_soc_update_bits(codec, WM8995_AIF2_DAC_RIGHT_VOLUME, - WM8995_AIF2DAC_VU_MASK, WM8995_AIF2DAC_VU); - snd_soc_update_bits(codec, WM8995_AIF1_ADC1_RIGHT_VOLUME, - WM8995_AIF1ADC1_VU_MASK, WM8995_AIF1ADC1_VU); - snd_soc_update_bits(codec, WM8995_AIF1_ADC2_RIGHT_VOLUME, - WM8995_AIF1ADC2_VU_MASK, WM8995_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8995_AIF2_ADC_RIGHT_VOLUME, - WM8995_AIF2ADC_VU_MASK, WM8995_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8995_DAC1_RIGHT_VOLUME, - WM8995_DAC1_VU_MASK, WM8995_DAC1_VU); - snd_soc_update_bits(codec, WM8995_DAC2_RIGHT_VOLUME, - WM8995_DAC2_VU_MASK, WM8995_DAC2_VU); - snd_soc_update_bits(codec, WM8995_RIGHT_LINE_INPUT_1_VOLUME, - WM8995_IN1_VU_MASK, WM8995_IN1_VU); - - wm8995_update_class_w(codec); - - snd_soc_add_codec_controls(codec, wm8995_snd_controls, - ARRAY_SIZE(wm8995_snd_controls)); - snd_soc_dapm_new_controls(&codec->dapm, wm8995_dapm_widgets, - ARRAY_SIZE(wm8995_dapm_widgets)); - snd_soc_dapm_add_routes(&codec->dapm, wm8995_intercon, - ARRAY_SIZE(wm8995_intercon)); - - return 0; - -err_reg_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8995->supplies), wm8995->supplies); -err_reg_get: - regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies); - return ret; -} - -#define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8995_aif1_dai_ops = { - .set_sysclk = wm8995_set_dai_sysclk, - .set_fmt = wm8995_set_dai_fmt, - .hw_params = wm8995_hw_params, - .digital_mute = wm8995_aif_mute, - .set_pll = wm8995_set_fll, - .set_tristate = wm8995_set_tristate, -}; - -static const struct snd_soc_dai_ops wm8995_aif2_dai_ops = { - .set_sysclk = wm8995_set_dai_sysclk, - .set_fmt = wm8995_set_dai_fmt, - .hw_params = wm8995_hw_params, - .digital_mute = wm8995_aif_mute, - .set_pll = wm8995_set_fll, - .set_tristate = wm8995_set_tristate, -}; - -static const struct snd_soc_dai_ops wm8995_aif3_dai_ops = { - .set_tristate = wm8995_set_tristate, -}; - -static struct snd_soc_dai_driver wm8995_dai[] = { - { - .name = "wm8995-aif1", - .playback = { - .stream_name = "AIF1 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = WM8995_FORMATS - }, - .capture = { - .stream_name = "AIF1 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8995_FORMATS - }, - .ops = &wm8995_aif1_dai_ops - }, - { - .name = "wm8995-aif2", - .playback = { - .stream_name = "AIF2 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = WM8995_FORMATS - }, - .capture = { - .stream_name = "AIF2 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8995_FORMATS - }, - .ops = &wm8995_aif2_dai_ops - }, - { - .name = "wm8995-aif3", - .playback = { - .stream_name = "AIF3 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = WM8995_FORMATS - }, - .capture = { - .stream_name = "AIF3 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = WM8995_FORMATS - }, - .ops = &wm8995_aif3_dai_ops - } -}; - -static struct snd_soc_codec_driver soc_codec_dev_wm8995 = { - .probe = wm8995_probe, - .remove = wm8995_remove, - .suspend = wm8995_suspend, - .resume = wm8995_resume, - .set_bias_level = wm8995_set_bias_level, - .idle_bias_off = true, -}; - -static struct regmap_config wm8995_regmap = { - .reg_bits = 16, - .val_bits = 16, - - .max_register = WM8995_MAX_REGISTER, - .reg_defaults = wm8995_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm8995_reg_defaults), - .volatile_reg = wm8995_volatile, - .readable_reg = wm8995_readable, - .cache_type = REGCACHE_RBTREE, -}; - -#if defined(CONFIG_SPI_MASTER) -static int __devinit wm8995_spi_probe(struct spi_device *spi) -{ - struct wm8995_priv *wm8995; - int ret; - - wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL); - if (!wm8995) - return -ENOMEM; - - spi_set_drvdata(spi, wm8995); - - wm8995->regmap = regmap_init_spi(spi, &wm8995_regmap); - if (IS_ERR(wm8995->regmap)) { - ret = PTR_ERR(wm8995->regmap); - dev_err(&spi->dev, "Failed to register regmap: %d\n", ret); - goto err_alloc; - } - - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_wm8995, wm8995_dai, - ARRAY_SIZE(wm8995_dai)); - if (ret < 0) - goto err_regmap; - - return ret; - -err_regmap: - regmap_exit(wm8995->regmap); -err_alloc: - kfree(wm8995); - - return ret; -} - -static int __devexit wm8995_spi_remove(struct spi_device *spi) -{ - struct wm8995_priv *wm8995 = spi_get_drvdata(spi); - snd_soc_unregister_codec(&spi->dev); - regmap_exit(wm8995->regmap); - kfree(wm8995); - return 0; -} - -static struct spi_driver wm8995_spi_driver = { - .driver = { - .name = "wm8995", - .owner = THIS_MODULE, - }, - .probe = wm8995_spi_probe, - .remove = __devexit_p(wm8995_spi_remove) -}; -#endif - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8995_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8995_priv *wm8995; - int ret; - - wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL); - if (!wm8995) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8995); - - wm8995->regmap = regmap_init_i2c(i2c, &wm8995_regmap); - if (IS_ERR(wm8995->regmap)) { - ret = PTR_ERR(wm8995->regmap); - dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret); - goto err_alloc; - } - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8995, wm8995_dai, - ARRAY_SIZE(wm8995_dai)); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - goto err_regmap; - } - - return ret; - -err_regmap: - regmap_exit(wm8995->regmap); -err_alloc: - kfree(wm8995); - - return ret; -} - -static __devexit int wm8995_i2c_remove(struct i2c_client *client) -{ - struct wm8995_priv *wm8995 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm8995->regmap); - kfree(wm8995); - return 0; -} - -static const struct i2c_device_id wm8995_i2c_id[] = { - {"wm8995", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, wm8995_i2c_id); - -static struct i2c_driver wm8995_i2c_driver = { - .driver = { - .name = "wm8995", - .owner = THIS_MODULE, - }, - .probe = wm8995_i2c_probe, - .remove = __devexit_p(wm8995_i2c_remove), - .id_table = wm8995_i2c_id -}; -#endif - -static int __init wm8995_modinit(void) -{ - int ret = 0; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8995_i2c_driver); - if (ret) { - printk(KERN_ERR "Failed to register wm8995 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8995_spi_driver); - if (ret) { - printk(KERN_ERR "Failed to register wm8995 SPI driver: %d\n", - ret); - } -#endif - return ret; -} - -module_init(wm8995_modinit); - -static void __exit wm8995_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8995_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8995_spi_driver); -#endif -} - -module_exit(wm8995_exit); - -MODULE_DESCRIPTION("ASoC WM8995 driver"); -MODULE_AUTHOR("Dimitris Papastamos "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8995.h b/ANDROID_3.4.5/sound/soc/codecs/wm8995.h deleted file mode 100644 index 5642121c..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8995.h +++ /dev/null @@ -1,4269 +0,0 @@ -/* - * wm8995.h -- WM8995 ALSA SoC Audio driver - * - * Copyright 2010 Wolfson Microelectronics plc - * - * Author: Dimitris Papastamos - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8995_H -#define _WM8995_H - -#include - -/* - * Register values. - */ -#define WM8995_SOFTWARE_RESET 0x00 -#define WM8995_POWER_MANAGEMENT_1 0x01 -#define WM8995_POWER_MANAGEMENT_2 0x02 -#define WM8995_POWER_MANAGEMENT_3 0x03 -#define WM8995_POWER_MANAGEMENT_4 0x04 -#define WM8995_POWER_MANAGEMENT_5 0x05 -#define WM8995_LEFT_LINE_INPUT_1_VOLUME 0x10 -#define WM8995_RIGHT_LINE_INPUT_1_VOLUME 0x11 -#define WM8995_LEFT_LINE_INPUT_CONTROL 0x12 -#define WM8995_DAC1_LEFT_VOLUME 0x18 -#define WM8995_DAC1_RIGHT_VOLUME 0x19 -#define WM8995_DAC2_LEFT_VOLUME 0x1A -#define WM8995_DAC2_RIGHT_VOLUME 0x1B -#define WM8995_OUTPUT_VOLUME_ZC_1 0x1C -#define WM8995_MICBIAS_1 0x20 -#define WM8995_MICBIAS_2 0x21 -#define WM8995_LDO_1 0x28 -#define WM8995_LDO_2 0x29 -#define WM8995_ACCESSORY_DETECT_MODE1 0x30 -#define WM8995_ACCESSORY_DETECT_MODE2 0x31 -#define WM8995_HEADPHONE_DETECT1 0x34 -#define WM8995_HEADPHONE_DETECT2 0x35 -#define WM8995_MIC_DETECT_1 0x38 -#define WM8995_MIC_DETECT_2 0x39 -#define WM8995_CHARGE_PUMP_1 0x40 -#define WM8995_CLASS_W_1 0x45 -#define WM8995_DC_SERVO_1 0x50 -#define WM8995_DC_SERVO_2 0x51 -#define WM8995_DC_SERVO_3 0x52 -#define WM8995_DC_SERVO_5 0x54 -#define WM8995_DC_SERVO_6 0x55 -#define WM8995_DC_SERVO_7 0x56 -#define WM8995_DC_SERVO_READBACK_0 0x57 -#define WM8995_ANALOGUE_HP_1 0x60 -#define WM8995_ANALOGUE_HP_2 0x61 -#define WM8995_CHIP_REVISION 0x100 -#define WM8995_CONTROL_INTERFACE_1 0x101 -#define WM8995_CONTROL_INTERFACE_2 0x102 -#define WM8995_WRITE_SEQUENCER_CTRL_1 0x110 -#define WM8995_WRITE_SEQUENCER_CTRL_2 0x111 -#define WM8995_AIF1_CLOCKING_1 0x200 -#define WM8995_AIF1_CLOCKING_2 0x201 -#define WM8995_AIF2_CLOCKING_1 0x204 -#define WM8995_AIF2_CLOCKING_2 0x205 -#define WM8995_CLOCKING_1 0x208 -#define WM8995_CLOCKING_2 0x209 -#define WM8995_AIF1_RATE 0x210 -#define WM8995_AIF2_RATE 0x211 -#define WM8995_RATE_STATUS 0x212 -#define WM8995_FLL1_CONTROL_1 0x220 -#define WM8995_FLL1_CONTROL_2 0x221 -#define WM8995_FLL1_CONTROL_3 0x222 -#define WM8995_FLL1_CONTROL_4 0x223 -#define WM8995_FLL1_CONTROL_5 0x224 -#define WM8995_FLL2_CONTROL_1 0x240 -#define WM8995_FLL2_CONTROL_2 0x241 -#define WM8995_FLL2_CONTROL_3 0x242 -#define WM8995_FLL2_CONTROL_4 0x243 -#define WM8995_FLL2_CONTROL_5 0x244 -#define WM8995_AIF1_CONTROL_1 0x300 -#define WM8995_AIF1_CONTROL_2 0x301 -#define WM8995_AIF1_MASTER_SLAVE 0x302 -#define WM8995_AIF1_BCLK 0x303 -#define WM8995_AIF1ADC_LRCLK 0x304 -#define WM8995_AIF1DAC_LRCLK 0x305 -#define WM8995_AIF1DAC_DATA 0x306 -#define WM8995_AIF1ADC_DATA 0x307 -#define WM8995_AIF2_CONTROL_1 0x310 -#define WM8995_AIF2_CONTROL_2 0x311 -#define WM8995_AIF2_MASTER_SLAVE 0x312 -#define WM8995_AIF2_BCLK 0x313 -#define WM8995_AIF2ADC_LRCLK 0x314 -#define WM8995_AIF2DAC_LRCLK 0x315 -#define WM8995_AIF2DAC_DATA 0x316 -#define WM8995_AIF2ADC_DATA 0x317 -#define WM8995_AIF1_ADC1_LEFT_VOLUME 0x400 -#define WM8995_AIF1_ADC1_RIGHT_VOLUME 0x401 -#define WM8995_AIF1_DAC1_LEFT_VOLUME 0x402 -#define WM8995_AIF1_DAC1_RIGHT_VOLUME 0x403 -#define WM8995_AIF1_ADC2_LEFT_VOLUME 0x404 -#define WM8995_AIF1_ADC2_RIGHT_VOLUME 0x405 -#define WM8995_AIF1_DAC2_LEFT_VOLUME 0x406 -#define WM8995_AIF1_DAC2_RIGHT_VOLUME 0x407 -#define WM8995_AIF1_ADC1_FILTERS 0x410 -#define WM8995_AIF1_ADC2_FILTERS 0x411 -#define WM8995_AIF1_DAC1_FILTERS_1 0x420 -#define WM8995_AIF1_DAC1_FILTERS_2 0x421 -#define WM8995_AIF1_DAC2_FILTERS_1 0x422 -#define WM8995_AIF1_DAC2_FILTERS_2 0x423 -#define WM8995_AIF1_DRC1_1 0x440 -#define WM8995_AIF1_DRC1_2 0x441 -#define WM8995_AIF1_DRC1_3 0x442 -#define WM8995_AIF1_DRC1_4 0x443 -#define WM8995_AIF1_DRC1_5 0x444 -#define WM8995_AIF1_DRC2_1 0x450 -#define WM8995_AIF1_DRC2_2 0x451 -#define WM8995_AIF1_DRC2_3 0x452 -#define WM8995_AIF1_DRC2_4 0x453 -#define WM8995_AIF1_DRC2_5 0x454 -#define WM8995_AIF1_DAC1_EQ_GAINS_1 0x480 -#define WM8995_AIF1_DAC1_EQ_GAINS_2 0x481 -#define WM8995_AIF1_DAC1_EQ_BAND_1_A 0x482 -#define WM8995_AIF1_DAC1_EQ_BAND_1_B 0x483 -#define WM8995_AIF1_DAC1_EQ_BAND_1_PG 0x484 -#define WM8995_AIF1_DAC1_EQ_BAND_2_A 0x485 -#define WM8995_AIF1_DAC1_EQ_BAND_2_B 0x486 -#define WM8995_AIF1_DAC1_EQ_BAND_2_C 0x487 -#define WM8995_AIF1_DAC1_EQ_BAND_2_PG 0x488 -#define WM8995_AIF1_DAC1_EQ_BAND_3_A 0x489 -#define WM8995_AIF1_DAC1_EQ_BAND_3_B 0x48A -#define WM8995_AIF1_DAC1_EQ_BAND_3_C 0x48B -#define WM8995_AIF1_DAC1_EQ_BAND_3_PG 0x48C -#define WM8995_AIF1_DAC1_EQ_BAND_4_A 0x48D -#define WM8995_AIF1_DAC1_EQ_BAND_4_B 0x48E -#define WM8995_AIF1_DAC1_EQ_BAND_4_C 0x48F -#define WM8995_AIF1_DAC1_EQ_BAND_4_PG 0x490 -#define WM8995_AIF1_DAC1_EQ_BAND_5_A 0x491 -#define WM8995_AIF1_DAC1_EQ_BAND_5_B 0x492 -#define WM8995_AIF1_DAC1_EQ_BAND_5_PG 0x493 -#define WM8995_AIF1_DAC2_EQ_GAINS_1 0x4A0 -#define WM8995_AIF1_DAC2_EQ_GAINS_2 0x4A1 -#define WM8995_AIF1_DAC2_EQ_BAND_1_A 0x4A2 -#define WM8995_AIF1_DAC2_EQ_BAND_1_B 0x4A3 -#define WM8995_AIF1_DAC2_EQ_BAND_1_PG 0x4A4 -#define WM8995_AIF1_DAC2_EQ_BAND_2_A 0x4A5 -#define WM8995_AIF1_DAC2_EQ_BAND_2_B 0x4A6 -#define WM8995_AIF1_DAC2_EQ_BAND_2_C 0x4A7 -#define WM8995_AIF1_DAC2_EQ_BAND_2_PG 0x4A8 -#define WM8995_AIF1_DAC2_EQ_BAND_3_A 0x4A9 -#define WM8995_AIF1_DAC2_EQ_BAND_3_B 0x4AA -#define WM8995_AIF1_DAC2_EQ_BAND_3_C 0x4AB -#define WM8995_AIF1_DAC2_EQ_BAND_3_PG 0x4AC -#define WM8995_AIF1_DAC2_EQ_BAND_4_A 0x4AD -#define WM8995_AIF1_DAC2_EQ_BAND_4_B 0x4AE -#define WM8995_AIF1_DAC2_EQ_BAND_4_C 0x4AF -#define WM8995_AIF1_DAC2_EQ_BAND_4_PG 0x4B0 -#define WM8995_AIF1_DAC2_EQ_BAND_5_A 0x4B1 -#define WM8995_AIF1_DAC2_EQ_BAND_5_B 0x4B2 -#define WM8995_AIF1_DAC2_EQ_BAND_5_PG 0x4B3 -#define WM8995_AIF2_ADC_LEFT_VOLUME 0x500 -#define WM8995_AIF2_ADC_RIGHT_VOLUME 0x501 -#define WM8995_AIF2_DAC_LEFT_VOLUME 0x502 -#define WM8995_AIF2_DAC_RIGHT_VOLUME 0x503 -#define WM8995_AIF2_ADC_FILTERS 0x510 -#define WM8995_AIF2_DAC_FILTERS_1 0x520 -#define WM8995_AIF2_DAC_FILTERS_2 0x521 -#define WM8995_AIF2_DRC_1 0x540 -#define WM8995_AIF2_DRC_2 0x541 -#define WM8995_AIF2_DRC_3 0x542 -#define WM8995_AIF2_DRC_4 0x543 -#define WM8995_AIF2_DRC_5 0x544 -#define WM8995_AIF2_EQ_GAINS_1 0x580 -#define WM8995_AIF2_EQ_GAINS_2 0x581 -#define WM8995_AIF2_EQ_BAND_1_A 0x582 -#define WM8995_AIF2_EQ_BAND_1_B 0x583 -#define WM8995_AIF2_EQ_BAND_1_PG 0x584 -#define WM8995_AIF2_EQ_BAND_2_A 0x585 -#define WM8995_AIF2_EQ_BAND_2_B 0x586 -#define WM8995_AIF2_EQ_BAND_2_C 0x587 -#define WM8995_AIF2_EQ_BAND_2_PG 0x588 -#define WM8995_AIF2_EQ_BAND_3_A 0x589 -#define WM8995_AIF2_EQ_BAND_3_B 0x58A -#define WM8995_AIF2_EQ_BAND_3_C 0x58B -#define WM8995_AIF2_EQ_BAND_3_PG 0x58C -#define WM8995_AIF2_EQ_BAND_4_A 0x58D -#define WM8995_AIF2_EQ_BAND_4_B 0x58E -#define WM8995_AIF2_EQ_BAND_4_C 0x58F -#define WM8995_AIF2_EQ_BAND_4_PG 0x590 -#define WM8995_AIF2_EQ_BAND_5_A 0x591 -#define WM8995_AIF2_EQ_BAND_5_B 0x592 -#define WM8995_AIF2_EQ_BAND_5_PG 0x593 -#define WM8995_DAC1_MIXER_VOLUMES 0x600 -#define WM8995_DAC1_LEFT_MIXER_ROUTING 0x601 -#define WM8995_DAC1_RIGHT_MIXER_ROUTING 0x602 -#define WM8995_DAC2_MIXER_VOLUMES 0x603 -#define WM8995_DAC2_LEFT_MIXER_ROUTING 0x604 -#define WM8995_DAC2_RIGHT_MIXER_ROUTING 0x605 -#define WM8995_AIF1_ADC1_LEFT_MIXER_ROUTING 0x606 -#define WM8995_AIF1_ADC1_RIGHT_MIXER_ROUTING 0x607 -#define WM8995_AIF1_ADC2_LEFT_MIXER_ROUTING 0x608 -#define WM8995_AIF1_ADC2_RIGHT_MIXER_ROUTING 0x609 -#define WM8995_DAC_SOFTMUTE 0x610 -#define WM8995_OVERSAMPLING 0x620 -#define WM8995_SIDETONE 0x621 -#define WM8995_GPIO_1 0x700 -#define WM8995_GPIO_2 0x701 -#define WM8995_GPIO_3 0x702 -#define WM8995_GPIO_4 0x703 -#define WM8995_GPIO_5 0x704 -#define WM8995_GPIO_6 0x705 -#define WM8995_GPIO_7 0x706 -#define WM8995_GPIO_8 0x707 -#define WM8995_GPIO_9 0x708 -#define WM8995_GPIO_10 0x709 -#define WM8995_GPIO_11 0x70A -#define WM8995_GPIO_12 0x70B -#define WM8995_GPIO_13 0x70C -#define WM8995_GPIO_14 0x70D -#define WM8995_PULL_CONTROL_1 0x720 -#define WM8995_PULL_CONTROL_2 0x721 -#define WM8995_INTERRUPT_STATUS_1 0x730 -#define WM8995_INTERRUPT_STATUS_2 0x731 -#define WM8995_INTERRUPT_RAW_STATUS_2 0x732 -#define WM8995_INTERRUPT_STATUS_1_MASK 0x738 -#define WM8995_INTERRUPT_STATUS_2_MASK 0x739 -#define WM8995_INTERRUPT_CONTROL 0x740 -#define WM8995_LEFT_PDM_SPEAKER_1 0x800 -#define WM8995_RIGHT_PDM_SPEAKER_1 0x801 -#define WM8995_PDM_SPEAKER_1_MUTE_SEQUENCE 0x802 -#define WM8995_LEFT_PDM_SPEAKER_2 0x808 -#define WM8995_RIGHT_PDM_SPEAKER_2 0x809 -#define WM8995_PDM_SPEAKER_2_MUTE_SEQUENCE 0x80A -#define WM8995_WRITE_SEQUENCER_0 0x3000 -#define WM8995_WRITE_SEQUENCER_1 0x3001 -#define WM8995_WRITE_SEQUENCER_2 0x3002 -#define WM8995_WRITE_SEQUENCER_3 0x3003 -#define WM8995_WRITE_SEQUENCER_4 0x3004 -#define WM8995_WRITE_SEQUENCER_5 0x3005 -#define WM8995_WRITE_SEQUENCER_6 0x3006 -#define WM8995_WRITE_SEQUENCER_7 0x3007 -#define WM8995_WRITE_SEQUENCER_8 0x3008 -#define WM8995_WRITE_SEQUENCER_9 0x3009 -#define WM8995_WRITE_SEQUENCER_10 0x300A -#define WM8995_WRITE_SEQUENCER_11 0x300B -#define WM8995_WRITE_SEQUENCER_12 0x300C -#define WM8995_WRITE_SEQUENCER_13 0x300D -#define WM8995_WRITE_SEQUENCER_14 0x300E -#define WM8995_WRITE_SEQUENCER_15 0x300F -#define WM8995_WRITE_SEQUENCER_16 0x3010 -#define WM8995_WRITE_SEQUENCER_17 0x3011 -#define WM8995_WRITE_SEQUENCER_18 0x3012 -#define WM8995_WRITE_SEQUENCER_19 0x3013 -#define WM8995_WRITE_SEQUENCER_20 0x3014 -#define WM8995_WRITE_SEQUENCER_21 0x3015 -#define WM8995_WRITE_SEQUENCER_22 0x3016 -#define WM8995_WRITE_SEQUENCER_23 0x3017 -#define WM8995_WRITE_SEQUENCER_24 0x3018 -#define WM8995_WRITE_SEQUENCER_25 0x3019 -#define WM8995_WRITE_SEQUENCER_26 0x301A -#define WM8995_WRITE_SEQUENCER_27 0x301B -#define WM8995_WRITE_SEQUENCER_28 0x301C -#define WM8995_WRITE_SEQUENCER_29 0x301D -#define WM8995_WRITE_SEQUENCER_30 0x301E -#define WM8995_WRITE_SEQUENCER_31 0x301F -#define WM8995_WRITE_SEQUENCER_32 0x3020 -#define WM8995_WRITE_SEQUENCER_33 0x3021 -#define WM8995_WRITE_SEQUENCER_34 0x3022 -#define WM8995_WRITE_SEQUENCER_35 0x3023 -#define WM8995_WRITE_SEQUENCER_36 0x3024 -#define WM8995_WRITE_SEQUENCER_37 0x3025 -#define WM8995_WRITE_SEQUENCER_38 0x3026 -#define WM8995_WRITE_SEQUENCER_39 0x3027 -#define WM8995_WRITE_SEQUENCER_40 0x3028 -#define WM8995_WRITE_SEQUENCER_41 0x3029 -#define WM8995_WRITE_SEQUENCER_42 0x302A -#define WM8995_WRITE_SEQUENCER_43 0x302B -#define WM8995_WRITE_SEQUENCER_44 0x302C -#define WM8995_WRITE_SEQUENCER_45 0x302D -#define WM8995_WRITE_SEQUENCER_46 0x302E -#define WM8995_WRITE_SEQUENCER_47 0x302F -#define WM8995_WRITE_SEQUENCER_48 0x3030 -#define WM8995_WRITE_SEQUENCER_49 0x3031 -#define WM8995_WRITE_SEQUENCER_50 0x3032 -#define WM8995_WRITE_SEQUENCER_51 0x3033 -#define WM8995_WRITE_SEQUENCER_52 0x3034 -#define WM8995_WRITE_SEQUENCER_53 0x3035 -#define WM8995_WRITE_SEQUENCER_54 0x3036 -#define WM8995_WRITE_SEQUENCER_55 0x3037 -#define WM8995_WRITE_SEQUENCER_56 0x3038 -#define WM8995_WRITE_SEQUENCER_57 0x3039 -#define WM8995_WRITE_SEQUENCER_58 0x303A -#define WM8995_WRITE_SEQUENCER_59 0x303B -#define WM8995_WRITE_SEQUENCER_60 0x303C -#define WM8995_WRITE_SEQUENCER_61 0x303D -#define WM8995_WRITE_SEQUENCER_62 0x303E -#define WM8995_WRITE_SEQUENCER_63 0x303F -#define WM8995_WRITE_SEQUENCER_64 0x3040 -#define WM8995_WRITE_SEQUENCER_65 0x3041 -#define WM8995_WRITE_SEQUENCER_66 0x3042 -#define WM8995_WRITE_SEQUENCER_67 0x3043 -#define WM8995_WRITE_SEQUENCER_68 0x3044 -#define WM8995_WRITE_SEQUENCER_69 0x3045 -#define WM8995_WRITE_SEQUENCER_70 0x3046 -#define WM8995_WRITE_SEQUENCER_71 0x3047 -#define WM8995_WRITE_SEQUENCER_72 0x3048 -#define WM8995_WRITE_SEQUENCER_73 0x3049 -#define WM8995_WRITE_SEQUENCER_74 0x304A -#define WM8995_WRITE_SEQUENCER_75 0x304B -#define WM8995_WRITE_SEQUENCER_76 0x304C -#define WM8995_WRITE_SEQUENCER_77 0x304D -#define WM8995_WRITE_SEQUENCER_78 0x304E -#define WM8995_WRITE_SEQUENCER_79 0x304F -#define WM8995_WRITE_SEQUENCER_80 0x3050 -#define WM8995_WRITE_SEQUENCER_81 0x3051 -#define WM8995_WRITE_SEQUENCER_82 0x3052 -#define WM8995_WRITE_SEQUENCER_83 0x3053 -#define WM8995_WRITE_SEQUENCER_84 0x3054 -#define WM8995_WRITE_SEQUENCER_85 0x3055 -#define WM8995_WRITE_SEQUENCER_86 0x3056 -#define WM8995_WRITE_SEQUENCER_87 0x3057 -#define WM8995_WRITE_SEQUENCER_88 0x3058 -#define WM8995_WRITE_SEQUENCER_89 0x3059 -#define WM8995_WRITE_SEQUENCER_90 0x305A -#define WM8995_WRITE_SEQUENCER_91 0x305B -#define WM8995_WRITE_SEQUENCER_92 0x305C -#define WM8995_WRITE_SEQUENCER_93 0x305D -#define WM8995_WRITE_SEQUENCER_94 0x305E -#define WM8995_WRITE_SEQUENCER_95 0x305F -#define WM8995_WRITE_SEQUENCER_96 0x3060 -#define WM8995_WRITE_SEQUENCER_97 0x3061 -#define WM8995_WRITE_SEQUENCER_98 0x3062 -#define WM8995_WRITE_SEQUENCER_99 0x3063 -#define WM8995_WRITE_SEQUENCER_100 0x3064 -#define WM8995_WRITE_SEQUENCER_101 0x3065 -#define WM8995_WRITE_SEQUENCER_102 0x3066 -#define WM8995_WRITE_SEQUENCER_103 0x3067 -#define WM8995_WRITE_SEQUENCER_104 0x3068 -#define WM8995_WRITE_SEQUENCER_105 0x3069 -#define WM8995_WRITE_SEQUENCER_106 0x306A -#define WM8995_WRITE_SEQUENCER_107 0x306B -#define WM8995_WRITE_SEQUENCER_108 0x306C -#define WM8995_WRITE_SEQUENCER_109 0x306D -#define WM8995_WRITE_SEQUENCER_110 0x306E -#define WM8995_WRITE_SEQUENCER_111 0x306F -#define WM8995_WRITE_SEQUENCER_112 0x3070 -#define WM8995_WRITE_SEQUENCER_113 0x3071 -#define WM8995_WRITE_SEQUENCER_114 0x3072 -#define WM8995_WRITE_SEQUENCER_115 0x3073 -#define WM8995_WRITE_SEQUENCER_116 0x3074 -#define WM8995_WRITE_SEQUENCER_117 0x3075 -#define WM8995_WRITE_SEQUENCER_118 0x3076 -#define WM8995_WRITE_SEQUENCER_119 0x3077 -#define WM8995_WRITE_SEQUENCER_120 0x3078 -#define WM8995_WRITE_SEQUENCER_121 0x3079 -#define WM8995_WRITE_SEQUENCER_122 0x307A -#define WM8995_WRITE_SEQUENCER_123 0x307B -#define WM8995_WRITE_SEQUENCER_124 0x307C -#define WM8995_WRITE_SEQUENCER_125 0x307D -#define WM8995_WRITE_SEQUENCER_126 0x307E -#define WM8995_WRITE_SEQUENCER_127 0x307F -#define WM8995_WRITE_SEQUENCER_128 0x3080 -#define WM8995_WRITE_SEQUENCER_129 0x3081 -#define WM8995_WRITE_SEQUENCER_130 0x3082 -#define WM8995_WRITE_SEQUENCER_131 0x3083 -#define WM8995_WRITE_SEQUENCER_132 0x3084 -#define WM8995_WRITE_SEQUENCER_133 0x3085 -#define WM8995_WRITE_SEQUENCER_134 0x3086 -#define WM8995_WRITE_SEQUENCER_135 0x3087 -#define WM8995_WRITE_SEQUENCER_136 0x3088 -#define WM8995_WRITE_SEQUENCER_137 0x3089 -#define WM8995_WRITE_SEQUENCER_138 0x308A -#define WM8995_WRITE_SEQUENCER_139 0x308B -#define WM8995_WRITE_SEQUENCER_140 0x308C -#define WM8995_WRITE_SEQUENCER_141 0x308D -#define WM8995_WRITE_SEQUENCER_142 0x308E -#define WM8995_WRITE_SEQUENCER_143 0x308F -#define WM8995_WRITE_SEQUENCER_144 0x3090 -#define WM8995_WRITE_SEQUENCER_145 0x3091 -#define WM8995_WRITE_SEQUENCER_146 0x3092 -#define WM8995_WRITE_SEQUENCER_147 0x3093 -#define WM8995_WRITE_SEQUENCER_148 0x3094 -#define WM8995_WRITE_SEQUENCER_149 0x3095 -#define WM8995_WRITE_SEQUENCER_150 0x3096 -#define WM8995_WRITE_SEQUENCER_151 0x3097 -#define WM8995_WRITE_SEQUENCER_152 0x3098 -#define WM8995_WRITE_SEQUENCER_153 0x3099 -#define WM8995_WRITE_SEQUENCER_154 0x309A -#define WM8995_WRITE_SEQUENCER_155 0x309B -#define WM8995_WRITE_SEQUENCER_156 0x309C -#define WM8995_WRITE_SEQUENCER_157 0x309D -#define WM8995_WRITE_SEQUENCER_158 0x309E -#define WM8995_WRITE_SEQUENCER_159 0x309F -#define WM8995_WRITE_SEQUENCER_160 0x30A0 -#define WM8995_WRITE_SEQUENCER_161 0x30A1 -#define WM8995_WRITE_SEQUENCER_162 0x30A2 -#define WM8995_WRITE_SEQUENCER_163 0x30A3 -#define WM8995_WRITE_SEQUENCER_164 0x30A4 -#define WM8995_WRITE_SEQUENCER_165 0x30A5 -#define WM8995_WRITE_SEQUENCER_166 0x30A6 -#define WM8995_WRITE_SEQUENCER_167 0x30A7 -#define WM8995_WRITE_SEQUENCER_168 0x30A8 -#define WM8995_WRITE_SEQUENCER_169 0x30A9 -#define WM8995_WRITE_SEQUENCER_170 0x30AA -#define WM8995_WRITE_SEQUENCER_171 0x30AB -#define WM8995_WRITE_SEQUENCER_172 0x30AC -#define WM8995_WRITE_SEQUENCER_173 0x30AD -#define WM8995_WRITE_SEQUENCER_174 0x30AE -#define WM8995_WRITE_SEQUENCER_175 0x30AF -#define WM8995_WRITE_SEQUENCER_176 0x30B0 -#define WM8995_WRITE_SEQUENCER_177 0x30B1 -#define WM8995_WRITE_SEQUENCER_178 0x30B2 -#define WM8995_WRITE_SEQUENCER_179 0x30B3 -#define WM8995_WRITE_SEQUENCER_180 0x30B4 -#define WM8995_WRITE_SEQUENCER_181 0x30B5 -#define WM8995_WRITE_SEQUENCER_182 0x30B6 -#define WM8995_WRITE_SEQUENCER_183 0x30B7 -#define WM8995_WRITE_SEQUENCER_184 0x30B8 -#define WM8995_WRITE_SEQUENCER_185 0x30B9 -#define WM8995_WRITE_SEQUENCER_186 0x30BA -#define WM8995_WRITE_SEQUENCER_187 0x30BB -#define WM8995_WRITE_SEQUENCER_188 0x30BC -#define WM8995_WRITE_SEQUENCER_189 0x30BD -#define WM8995_WRITE_SEQUENCER_190 0x30BE -#define WM8995_WRITE_SEQUENCER_191 0x30BF -#define WM8995_WRITE_SEQUENCER_192 0x30C0 -#define WM8995_WRITE_SEQUENCER_193 0x30C1 -#define WM8995_WRITE_SEQUENCER_194 0x30C2 -#define WM8995_WRITE_SEQUENCER_195 0x30C3 -#define WM8995_WRITE_SEQUENCER_196 0x30C4 -#define WM8995_WRITE_SEQUENCER_197 0x30C5 -#define WM8995_WRITE_SEQUENCER_198 0x30C6 -#define WM8995_WRITE_SEQUENCER_199 0x30C7 -#define WM8995_WRITE_SEQUENCER_200 0x30C8 -#define WM8995_WRITE_SEQUENCER_201 0x30C9 -#define WM8995_WRITE_SEQUENCER_202 0x30CA -#define WM8995_WRITE_SEQUENCER_203 0x30CB -#define WM8995_WRITE_SEQUENCER_204 0x30CC -#define WM8995_WRITE_SEQUENCER_205 0x30CD -#define WM8995_WRITE_SEQUENCER_206 0x30CE -#define WM8995_WRITE_SEQUENCER_207 0x30CF -#define WM8995_WRITE_SEQUENCER_208 0x30D0 -#define WM8995_WRITE_SEQUENCER_209 0x30D1 -#define WM8995_WRITE_SEQUENCER_210 0x30D2 -#define WM8995_WRITE_SEQUENCER_211 0x30D3 -#define WM8995_WRITE_SEQUENCER_212 0x30D4 -#define WM8995_WRITE_SEQUENCER_213 0x30D5 -#define WM8995_WRITE_SEQUENCER_214 0x30D6 -#define WM8995_WRITE_SEQUENCER_215 0x30D7 -#define WM8995_WRITE_SEQUENCER_216 0x30D8 -#define WM8995_WRITE_SEQUENCER_217 0x30D9 -#define WM8995_WRITE_SEQUENCER_218 0x30DA -#define WM8995_WRITE_SEQUENCER_219 0x30DB -#define WM8995_WRITE_SEQUENCER_220 0x30DC -#define WM8995_WRITE_SEQUENCER_221 0x30DD -#define WM8995_WRITE_SEQUENCER_222 0x30DE -#define WM8995_WRITE_SEQUENCER_223 0x30DF -#define WM8995_WRITE_SEQUENCER_224 0x30E0 -#define WM8995_WRITE_SEQUENCER_225 0x30E1 -#define WM8995_WRITE_SEQUENCER_226 0x30E2 -#define WM8995_WRITE_SEQUENCER_227 0x30E3 -#define WM8995_WRITE_SEQUENCER_228 0x30E4 -#define WM8995_WRITE_SEQUENCER_229 0x30E5 -#define WM8995_WRITE_SEQUENCER_230 0x30E6 -#define WM8995_WRITE_SEQUENCER_231 0x30E7 -#define WM8995_WRITE_SEQUENCER_232 0x30E8 -#define WM8995_WRITE_SEQUENCER_233 0x30E9 -#define WM8995_WRITE_SEQUENCER_234 0x30EA -#define WM8995_WRITE_SEQUENCER_235 0x30EB -#define WM8995_WRITE_SEQUENCER_236 0x30EC -#define WM8995_WRITE_SEQUENCER_237 0x30ED -#define WM8995_WRITE_SEQUENCER_238 0x30EE -#define WM8995_WRITE_SEQUENCER_239 0x30EF -#define WM8995_WRITE_SEQUENCER_240 0x30F0 -#define WM8995_WRITE_SEQUENCER_241 0x30F1 -#define WM8995_WRITE_SEQUENCER_242 0x30F2 -#define WM8995_WRITE_SEQUENCER_243 0x30F3 -#define WM8995_WRITE_SEQUENCER_244 0x30F4 -#define WM8995_WRITE_SEQUENCER_245 0x30F5 -#define WM8995_WRITE_SEQUENCER_246 0x30F6 -#define WM8995_WRITE_SEQUENCER_247 0x30F7 -#define WM8995_WRITE_SEQUENCER_248 0x30F8 -#define WM8995_WRITE_SEQUENCER_249 0x30F9 -#define WM8995_WRITE_SEQUENCER_250 0x30FA -#define WM8995_WRITE_SEQUENCER_251 0x30FB -#define WM8995_WRITE_SEQUENCER_252 0x30FC -#define WM8995_WRITE_SEQUENCER_253 0x30FD -#define WM8995_WRITE_SEQUENCER_254 0x30FE -#define WM8995_WRITE_SEQUENCER_255 0x30FF -#define WM8995_WRITE_SEQUENCER_256 0x3100 -#define WM8995_WRITE_SEQUENCER_257 0x3101 -#define WM8995_WRITE_SEQUENCER_258 0x3102 -#define WM8995_WRITE_SEQUENCER_259 0x3103 -#define WM8995_WRITE_SEQUENCER_260 0x3104 -#define WM8995_WRITE_SEQUENCER_261 0x3105 -#define WM8995_WRITE_SEQUENCER_262 0x3106 -#define WM8995_WRITE_SEQUENCER_263 0x3107 -#define WM8995_WRITE_SEQUENCER_264 0x3108 -#define WM8995_WRITE_SEQUENCER_265 0x3109 -#define WM8995_WRITE_SEQUENCER_266 0x310A -#define WM8995_WRITE_SEQUENCER_267 0x310B -#define WM8995_WRITE_SEQUENCER_268 0x310C -#define WM8995_WRITE_SEQUENCER_269 0x310D -#define WM8995_WRITE_SEQUENCER_270 0x310E -#define WM8995_WRITE_SEQUENCER_271 0x310F -#define WM8995_WRITE_SEQUENCER_272 0x3110 -#define WM8995_WRITE_SEQUENCER_273 0x3111 -#define WM8995_WRITE_SEQUENCER_274 0x3112 -#define WM8995_WRITE_SEQUENCER_275 0x3113 -#define WM8995_WRITE_SEQUENCER_276 0x3114 -#define WM8995_WRITE_SEQUENCER_277 0x3115 -#define WM8995_WRITE_SEQUENCER_278 0x3116 -#define WM8995_WRITE_SEQUENCER_279 0x3117 -#define WM8995_WRITE_SEQUENCER_280 0x3118 -#define WM8995_WRITE_SEQUENCER_281 0x3119 -#define WM8995_WRITE_SEQUENCER_282 0x311A -#define WM8995_WRITE_SEQUENCER_283 0x311B -#define WM8995_WRITE_SEQUENCER_284 0x311C -#define WM8995_WRITE_SEQUENCER_285 0x311D -#define WM8995_WRITE_SEQUENCER_286 0x311E -#define WM8995_WRITE_SEQUENCER_287 0x311F -#define WM8995_WRITE_SEQUENCER_288 0x3120 -#define WM8995_WRITE_SEQUENCER_289 0x3121 -#define WM8995_WRITE_SEQUENCER_290 0x3122 -#define WM8995_WRITE_SEQUENCER_291 0x3123 -#define WM8995_WRITE_SEQUENCER_292 0x3124 -#define WM8995_WRITE_SEQUENCER_293 0x3125 -#define WM8995_WRITE_SEQUENCER_294 0x3126 -#define WM8995_WRITE_SEQUENCER_295 0x3127 -#define WM8995_WRITE_SEQUENCER_296 0x3128 -#define WM8995_WRITE_SEQUENCER_297 0x3129 -#define WM8995_WRITE_SEQUENCER_298 0x312A -#define WM8995_WRITE_SEQUENCER_299 0x312B -#define WM8995_WRITE_SEQUENCER_300 0x312C -#define WM8995_WRITE_SEQUENCER_301 0x312D -#define WM8995_WRITE_SEQUENCER_302 0x312E -#define WM8995_WRITE_SEQUENCER_303 0x312F -#define WM8995_WRITE_SEQUENCER_304 0x3130 -#define WM8995_WRITE_SEQUENCER_305 0x3131 -#define WM8995_WRITE_SEQUENCER_306 0x3132 -#define WM8995_WRITE_SEQUENCER_307 0x3133 -#define WM8995_WRITE_SEQUENCER_308 0x3134 -#define WM8995_WRITE_SEQUENCER_309 0x3135 -#define WM8995_WRITE_SEQUENCER_310 0x3136 -#define WM8995_WRITE_SEQUENCER_311 0x3137 -#define WM8995_WRITE_SEQUENCER_312 0x3138 -#define WM8995_WRITE_SEQUENCER_313 0x3139 -#define WM8995_WRITE_SEQUENCER_314 0x313A -#define WM8995_WRITE_SEQUENCER_315 0x313B -#define WM8995_WRITE_SEQUENCER_316 0x313C -#define WM8995_WRITE_SEQUENCER_317 0x313D -#define WM8995_WRITE_SEQUENCER_318 0x313E -#define WM8995_WRITE_SEQUENCER_319 0x313F -#define WM8995_WRITE_SEQUENCER_320 0x3140 -#define WM8995_WRITE_SEQUENCER_321 0x3141 -#define WM8995_WRITE_SEQUENCER_322 0x3142 -#define WM8995_WRITE_SEQUENCER_323 0x3143 -#define WM8995_WRITE_SEQUENCER_324 0x3144 -#define WM8995_WRITE_SEQUENCER_325 0x3145 -#define WM8995_WRITE_SEQUENCER_326 0x3146 -#define WM8995_WRITE_SEQUENCER_327 0x3147 -#define WM8995_WRITE_SEQUENCER_328 0x3148 -#define WM8995_WRITE_SEQUENCER_329 0x3149 -#define WM8995_WRITE_SEQUENCER_330 0x314A -#define WM8995_WRITE_SEQUENCER_331 0x314B -#define WM8995_WRITE_SEQUENCER_332 0x314C -#define WM8995_WRITE_SEQUENCER_333 0x314D -#define WM8995_WRITE_SEQUENCER_334 0x314E -#define WM8995_WRITE_SEQUENCER_335 0x314F -#define WM8995_WRITE_SEQUENCER_336 0x3150 -#define WM8995_WRITE_SEQUENCER_337 0x3151 -#define WM8995_WRITE_SEQUENCER_338 0x3152 -#define WM8995_WRITE_SEQUENCER_339 0x3153 -#define WM8995_WRITE_SEQUENCER_340 0x3154 -#define WM8995_WRITE_SEQUENCER_341 0x3155 -#define WM8995_WRITE_SEQUENCER_342 0x3156 -#define WM8995_WRITE_SEQUENCER_343 0x3157 -#define WM8995_WRITE_SEQUENCER_344 0x3158 -#define WM8995_WRITE_SEQUENCER_345 0x3159 -#define WM8995_WRITE_SEQUENCER_346 0x315A -#define WM8995_WRITE_SEQUENCER_347 0x315B -#define WM8995_WRITE_SEQUENCER_348 0x315C -#define WM8995_WRITE_SEQUENCER_349 0x315D -#define WM8995_WRITE_SEQUENCER_350 0x315E -#define WM8995_WRITE_SEQUENCER_351 0x315F -#define WM8995_WRITE_SEQUENCER_352 0x3160 -#define WM8995_WRITE_SEQUENCER_353 0x3161 -#define WM8995_WRITE_SEQUENCER_354 0x3162 -#define WM8995_WRITE_SEQUENCER_355 0x3163 -#define WM8995_WRITE_SEQUENCER_356 0x3164 -#define WM8995_WRITE_SEQUENCER_357 0x3165 -#define WM8995_WRITE_SEQUENCER_358 0x3166 -#define WM8995_WRITE_SEQUENCER_359 0x3167 -#define WM8995_WRITE_SEQUENCER_360 0x3168 -#define WM8995_WRITE_SEQUENCER_361 0x3169 -#define WM8995_WRITE_SEQUENCER_362 0x316A -#define WM8995_WRITE_SEQUENCER_363 0x316B -#define WM8995_WRITE_SEQUENCER_364 0x316C -#define WM8995_WRITE_SEQUENCER_365 0x316D -#define WM8995_WRITE_SEQUENCER_366 0x316E -#define WM8995_WRITE_SEQUENCER_367 0x316F -#define WM8995_WRITE_SEQUENCER_368 0x3170 -#define WM8995_WRITE_SEQUENCER_369 0x3171 -#define WM8995_WRITE_SEQUENCER_370 0x3172 -#define WM8995_WRITE_SEQUENCER_371 0x3173 -#define WM8995_WRITE_SEQUENCER_372 0x3174 -#define WM8995_WRITE_SEQUENCER_373 0x3175 -#define WM8995_WRITE_SEQUENCER_374 0x3176 -#define WM8995_WRITE_SEQUENCER_375 0x3177 -#define WM8995_WRITE_SEQUENCER_376 0x3178 -#define WM8995_WRITE_SEQUENCER_377 0x3179 -#define WM8995_WRITE_SEQUENCER_378 0x317A -#define WM8995_WRITE_SEQUENCER_379 0x317B -#define WM8995_WRITE_SEQUENCER_380 0x317C -#define WM8995_WRITE_SEQUENCER_381 0x317D -#define WM8995_WRITE_SEQUENCER_382 0x317E -#define WM8995_WRITE_SEQUENCER_383 0x317F -#define WM8995_WRITE_SEQUENCER_384 0x3180 -#define WM8995_WRITE_SEQUENCER_385 0x3181 -#define WM8995_WRITE_SEQUENCER_386 0x3182 -#define WM8995_WRITE_SEQUENCER_387 0x3183 -#define WM8995_WRITE_SEQUENCER_388 0x3184 -#define WM8995_WRITE_SEQUENCER_389 0x3185 -#define WM8995_WRITE_SEQUENCER_390 0x3186 -#define WM8995_WRITE_SEQUENCER_391 0x3187 -#define WM8995_WRITE_SEQUENCER_392 0x3188 -#define WM8995_WRITE_SEQUENCER_393 0x3189 -#define WM8995_WRITE_SEQUENCER_394 0x318A -#define WM8995_WRITE_SEQUENCER_395 0x318B -#define WM8995_WRITE_SEQUENCER_396 0x318C -#define WM8995_WRITE_SEQUENCER_397 0x318D -#define WM8995_WRITE_SEQUENCER_398 0x318E -#define WM8995_WRITE_SEQUENCER_399 0x318F -#define WM8995_WRITE_SEQUENCER_400 0x3190 -#define WM8995_WRITE_SEQUENCER_401 0x3191 -#define WM8995_WRITE_SEQUENCER_402 0x3192 -#define WM8995_WRITE_SEQUENCER_403 0x3193 -#define WM8995_WRITE_SEQUENCER_404 0x3194 -#define WM8995_WRITE_SEQUENCER_405 0x3195 -#define WM8995_WRITE_SEQUENCER_406 0x3196 -#define WM8995_WRITE_SEQUENCER_407 0x3197 -#define WM8995_WRITE_SEQUENCER_408 0x3198 -#define WM8995_WRITE_SEQUENCER_409 0x3199 -#define WM8995_WRITE_SEQUENCER_410 0x319A -#define WM8995_WRITE_SEQUENCER_411 0x319B -#define WM8995_WRITE_SEQUENCER_412 0x319C -#define WM8995_WRITE_SEQUENCER_413 0x319D -#define WM8995_WRITE_SEQUENCER_414 0x319E -#define WM8995_WRITE_SEQUENCER_415 0x319F -#define WM8995_WRITE_SEQUENCER_416 0x31A0 -#define WM8995_WRITE_SEQUENCER_417 0x31A1 -#define WM8995_WRITE_SEQUENCER_418 0x31A2 -#define WM8995_WRITE_SEQUENCER_419 0x31A3 -#define WM8995_WRITE_SEQUENCER_420 0x31A4 -#define WM8995_WRITE_SEQUENCER_421 0x31A5 -#define WM8995_WRITE_SEQUENCER_422 0x31A6 -#define WM8995_WRITE_SEQUENCER_423 0x31A7 -#define WM8995_WRITE_SEQUENCER_424 0x31A8 -#define WM8995_WRITE_SEQUENCER_425 0x31A9 -#define WM8995_WRITE_SEQUENCER_426 0x31AA -#define WM8995_WRITE_SEQUENCER_427 0x31AB -#define WM8995_WRITE_SEQUENCER_428 0x31AC -#define WM8995_WRITE_SEQUENCER_429 0x31AD -#define WM8995_WRITE_SEQUENCER_430 0x31AE -#define WM8995_WRITE_SEQUENCER_431 0x31AF -#define WM8995_WRITE_SEQUENCER_432 0x31B0 -#define WM8995_WRITE_SEQUENCER_433 0x31B1 -#define WM8995_WRITE_SEQUENCER_434 0x31B2 -#define WM8995_WRITE_SEQUENCER_435 0x31B3 -#define WM8995_WRITE_SEQUENCER_436 0x31B4 -#define WM8995_WRITE_SEQUENCER_437 0x31B5 -#define WM8995_WRITE_SEQUENCER_438 0x31B6 -#define WM8995_WRITE_SEQUENCER_439 0x31B7 -#define WM8995_WRITE_SEQUENCER_440 0x31B8 -#define WM8995_WRITE_SEQUENCER_441 0x31B9 -#define WM8995_WRITE_SEQUENCER_442 0x31BA -#define WM8995_WRITE_SEQUENCER_443 0x31BB -#define WM8995_WRITE_SEQUENCER_444 0x31BC -#define WM8995_WRITE_SEQUENCER_445 0x31BD -#define WM8995_WRITE_SEQUENCER_446 0x31BE -#define WM8995_WRITE_SEQUENCER_447 0x31BF -#define WM8995_WRITE_SEQUENCER_448 0x31C0 -#define WM8995_WRITE_SEQUENCER_449 0x31C1 -#define WM8995_WRITE_SEQUENCER_450 0x31C2 -#define WM8995_WRITE_SEQUENCER_451 0x31C3 -#define WM8995_WRITE_SEQUENCER_452 0x31C4 -#define WM8995_WRITE_SEQUENCER_453 0x31C5 -#define WM8995_WRITE_SEQUENCER_454 0x31C6 -#define WM8995_WRITE_SEQUENCER_455 0x31C7 -#define WM8995_WRITE_SEQUENCER_456 0x31C8 -#define WM8995_WRITE_SEQUENCER_457 0x31C9 -#define WM8995_WRITE_SEQUENCER_458 0x31CA -#define WM8995_WRITE_SEQUENCER_459 0x31CB -#define WM8995_WRITE_SEQUENCER_460 0x31CC -#define WM8995_WRITE_SEQUENCER_461 0x31CD -#define WM8995_WRITE_SEQUENCER_462 0x31CE -#define WM8995_WRITE_SEQUENCER_463 0x31CF -#define WM8995_WRITE_SEQUENCER_464 0x31D0 -#define WM8995_WRITE_SEQUENCER_465 0x31D1 -#define WM8995_WRITE_SEQUENCER_466 0x31D2 -#define WM8995_WRITE_SEQUENCER_467 0x31D3 -#define WM8995_WRITE_SEQUENCER_468 0x31D4 -#define WM8995_WRITE_SEQUENCER_469 0x31D5 -#define WM8995_WRITE_SEQUENCER_470 0x31D6 -#define WM8995_WRITE_SEQUENCER_471 0x31D7 -#define WM8995_WRITE_SEQUENCER_472 0x31D8 -#define WM8995_WRITE_SEQUENCER_473 0x31D9 -#define WM8995_WRITE_SEQUENCER_474 0x31DA -#define WM8995_WRITE_SEQUENCER_475 0x31DB -#define WM8995_WRITE_SEQUENCER_476 0x31DC -#define WM8995_WRITE_SEQUENCER_477 0x31DD -#define WM8995_WRITE_SEQUENCER_478 0x31DE -#define WM8995_WRITE_SEQUENCER_479 0x31DF -#define WM8995_WRITE_SEQUENCER_480 0x31E0 -#define WM8995_WRITE_SEQUENCER_481 0x31E1 -#define WM8995_WRITE_SEQUENCER_482 0x31E2 -#define WM8995_WRITE_SEQUENCER_483 0x31E3 -#define WM8995_WRITE_SEQUENCER_484 0x31E4 -#define WM8995_WRITE_SEQUENCER_485 0x31E5 -#define WM8995_WRITE_SEQUENCER_486 0x31E6 -#define WM8995_WRITE_SEQUENCER_487 0x31E7 -#define WM8995_WRITE_SEQUENCER_488 0x31E8 -#define WM8995_WRITE_SEQUENCER_489 0x31E9 -#define WM8995_WRITE_SEQUENCER_490 0x31EA -#define WM8995_WRITE_SEQUENCER_491 0x31EB -#define WM8995_WRITE_SEQUENCER_492 0x31EC -#define WM8995_WRITE_SEQUENCER_493 0x31ED -#define WM8995_WRITE_SEQUENCER_494 0x31EE -#define WM8995_WRITE_SEQUENCER_495 0x31EF -#define WM8995_WRITE_SEQUENCER_496 0x31F0 -#define WM8995_WRITE_SEQUENCER_497 0x31F1 -#define WM8995_WRITE_SEQUENCER_498 0x31F2 -#define WM8995_WRITE_SEQUENCER_499 0x31F3 -#define WM8995_WRITE_SEQUENCER_500 0x31F4 -#define WM8995_WRITE_SEQUENCER_501 0x31F5 -#define WM8995_WRITE_SEQUENCER_502 0x31F6 -#define WM8995_WRITE_SEQUENCER_503 0x31F7 -#define WM8995_WRITE_SEQUENCER_504 0x31F8 -#define WM8995_WRITE_SEQUENCER_505 0x31F9 -#define WM8995_WRITE_SEQUENCER_506 0x31FA -#define WM8995_WRITE_SEQUENCER_507 0x31FB -#define WM8995_WRITE_SEQUENCER_508 0x31FC -#define WM8995_WRITE_SEQUENCER_509 0x31FD -#define WM8995_WRITE_SEQUENCER_510 0x31FE -#define WM8995_WRITE_SEQUENCER_511 0x31FF - -#define WM8995_REGISTER_COUNT 725 -#define WM8995_MAX_REGISTER 0x31FF - -#define WM8995_MAX_CACHED_REGISTER WM8995_MAX_REGISTER - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM8995_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ -#define WM8995_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ -#define WM8995_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ - -/* - * R1 (0x01) - Power Management (1) - */ -#define WM8995_MICB2_ENA 0x0200 /* MICB2_ENA */ -#define WM8995_MICB2_ENA_MASK 0x0200 /* MICB2_ENA */ -#define WM8995_MICB2_ENA_SHIFT 9 /* MICB2_ENA */ -#define WM8995_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ -#define WM8995_MICB1_ENA 0x0100 /* MICB1_ENA */ -#define WM8995_MICB1_ENA_MASK 0x0100 /* MICB1_ENA */ -#define WM8995_MICB1_ENA_SHIFT 8 /* MICB1_ENA */ -#define WM8995_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ -#define WM8995_HPOUT2L_ENA 0x0080 /* HPOUT2L_ENA */ -#define WM8995_HPOUT2L_ENA_MASK 0x0080 /* HPOUT2L_ENA */ -#define WM8995_HPOUT2L_ENA_SHIFT 7 /* HPOUT2L_ENA */ -#define WM8995_HPOUT2L_ENA_WIDTH 1 /* HPOUT2L_ENA */ -#define WM8995_HPOUT2R_ENA 0x0040 /* HPOUT2R_ENA */ -#define WM8995_HPOUT2R_ENA_MASK 0x0040 /* HPOUT2R_ENA */ -#define WM8995_HPOUT2R_ENA_SHIFT 6 /* HPOUT2R_ENA */ -#define WM8995_HPOUT2R_ENA_WIDTH 1 /* HPOUT2R_ENA */ -#define WM8995_HPOUT1L_ENA 0x0020 /* HPOUT1L_ENA */ -#define WM8995_HPOUT1L_ENA_MASK 0x0020 /* HPOUT1L_ENA */ -#define WM8995_HPOUT1L_ENA_SHIFT 5 /* HPOUT1L_ENA */ -#define WM8995_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */ -#define WM8995_HPOUT1R_ENA 0x0010 /* HPOUT1R_ENA */ -#define WM8995_HPOUT1R_ENA_MASK 0x0010 /* HPOUT1R_ENA */ -#define WM8995_HPOUT1R_ENA_SHIFT 4 /* HPOUT1R_ENA */ -#define WM8995_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */ -#define WM8995_BG_ENA 0x0001 /* BG_ENA */ -#define WM8995_BG_ENA_MASK 0x0001 /* BG_ENA */ -#define WM8995_BG_ENA_SHIFT 0 /* BG_ENA */ -#define WM8995_BG_ENA_WIDTH 1 /* BG_ENA */ - -/* - * R2 (0x02) - Power Management (2) - */ -#define WM8995_OPCLK_ENA 0x0800 /* OPCLK_ENA */ -#define WM8995_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */ -#define WM8995_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */ -#define WM8995_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ -#define WM8995_IN1L_ENA 0x0020 /* IN1L_ENA */ -#define WM8995_IN1L_ENA_MASK 0x0020 /* IN1L_ENA */ -#define WM8995_IN1L_ENA_SHIFT 5 /* IN1L_ENA */ -#define WM8995_IN1L_ENA_WIDTH 1 /* IN1L_ENA */ -#define WM8995_IN1R_ENA 0x0010 /* IN1R_ENA */ -#define WM8995_IN1R_ENA_MASK 0x0010 /* IN1R_ENA */ -#define WM8995_IN1R_ENA_SHIFT 4 /* IN1R_ENA */ -#define WM8995_IN1R_ENA_WIDTH 1 /* IN1R_ENA */ -#define WM8995_LDO2_ENA 0x0002 /* LDO2_ENA */ -#define WM8995_LDO2_ENA_MASK 0x0002 /* LDO2_ENA */ -#define WM8995_LDO2_ENA_SHIFT 1 /* LDO2_ENA */ -#define WM8995_LDO2_ENA_WIDTH 1 /* LDO2_ENA */ - -/* - * R3 (0x03) - Power Management (3) - */ -#define WM8995_AIF2ADCL_ENA 0x2000 /* AIF2ADCL_ENA */ -#define WM8995_AIF2ADCL_ENA_MASK 0x2000 /* AIF2ADCL_ENA */ -#define WM8995_AIF2ADCL_ENA_SHIFT 13 /* AIF2ADCL_ENA */ -#define WM8995_AIF2ADCL_ENA_WIDTH 1 /* AIF2ADCL_ENA */ -#define WM8995_AIF2ADCR_ENA 0x1000 /* AIF2ADCR_ENA */ -#define WM8995_AIF2ADCR_ENA_MASK 0x1000 /* AIF2ADCR_ENA */ -#define WM8995_AIF2ADCR_ENA_SHIFT 12 /* AIF2ADCR_ENA */ -#define WM8995_AIF2ADCR_ENA_WIDTH 1 /* AIF2ADCR_ENA */ -#define WM8995_AIF1ADC2L_ENA 0x0800 /* AIF1ADC2L_ENA */ -#define WM8995_AIF1ADC2L_ENA_MASK 0x0800 /* AIF1ADC2L_ENA */ -#define WM8995_AIF1ADC2L_ENA_SHIFT 11 /* AIF1ADC2L_ENA */ -#define WM8995_AIF1ADC2L_ENA_WIDTH 1 /* AIF1ADC2L_ENA */ -#define WM8995_AIF1ADC2R_ENA 0x0400 /* AIF1ADC2R_ENA */ -#define WM8995_AIF1ADC2R_ENA_MASK 0x0400 /* AIF1ADC2R_ENA */ -#define WM8995_AIF1ADC2R_ENA_SHIFT 10 /* AIF1ADC2R_ENA */ -#define WM8995_AIF1ADC2R_ENA_WIDTH 1 /* AIF1ADC2R_ENA */ -#define WM8995_AIF1ADC1L_ENA 0x0200 /* AIF1ADC1L_ENA */ -#define WM8995_AIF1ADC1L_ENA_MASK 0x0200 /* AIF1ADC1L_ENA */ -#define WM8995_AIF1ADC1L_ENA_SHIFT 9 /* AIF1ADC1L_ENA */ -#define WM8995_AIF1ADC1L_ENA_WIDTH 1 /* AIF1ADC1L_ENA */ -#define WM8995_AIF1ADC1R_ENA 0x0100 /* AIF1ADC1R_ENA */ -#define WM8995_AIF1ADC1R_ENA_MASK 0x0100 /* AIF1ADC1R_ENA */ -#define WM8995_AIF1ADC1R_ENA_SHIFT 8 /* AIF1ADC1R_ENA */ -#define WM8995_AIF1ADC1R_ENA_WIDTH 1 /* AIF1ADC1R_ENA */ -#define WM8995_DMIC3L_ENA 0x0080 /* DMIC3L_ENA */ -#define WM8995_DMIC3L_ENA_MASK 0x0080 /* DMIC3L_ENA */ -#define WM8995_DMIC3L_ENA_SHIFT 7 /* DMIC3L_ENA */ -#define WM8995_DMIC3L_ENA_WIDTH 1 /* DMIC3L_ENA */ -#define WM8995_DMIC3R_ENA 0x0040 /* DMIC3R_ENA */ -#define WM8995_DMIC3R_ENA_MASK 0x0040 /* DMIC3R_ENA */ -#define WM8995_DMIC3R_ENA_SHIFT 6 /* DMIC3R_ENA */ -#define WM8995_DMIC3R_ENA_WIDTH 1 /* DMIC3R_ENA */ -#define WM8995_DMIC2L_ENA 0x0020 /* DMIC2L_ENA */ -#define WM8995_DMIC2L_ENA_MASK 0x0020 /* DMIC2L_ENA */ -#define WM8995_DMIC2L_ENA_SHIFT 5 /* DMIC2L_ENA */ -#define WM8995_DMIC2L_ENA_WIDTH 1 /* DMIC2L_ENA */ -#define WM8995_DMIC2R_ENA 0x0010 /* DMIC2R_ENA */ -#define WM8995_DMIC2R_ENA_MASK 0x0010 /* DMIC2R_ENA */ -#define WM8995_DMIC2R_ENA_SHIFT 4 /* DMIC2R_ENA */ -#define WM8995_DMIC2R_ENA_WIDTH 1 /* DMIC2R_ENA */ -#define WM8995_DMIC1L_ENA 0x0008 /* DMIC1L_ENA */ -#define WM8995_DMIC1L_ENA_MASK 0x0008 /* DMIC1L_ENA */ -#define WM8995_DMIC1L_ENA_SHIFT 3 /* DMIC1L_ENA */ -#define WM8995_DMIC1L_ENA_WIDTH 1 /* DMIC1L_ENA */ -#define WM8995_DMIC1R_ENA 0x0004 /* DMIC1R_ENA */ -#define WM8995_DMIC1R_ENA_MASK 0x0004 /* DMIC1R_ENA */ -#define WM8995_DMIC1R_ENA_SHIFT 2 /* DMIC1R_ENA */ -#define WM8995_DMIC1R_ENA_WIDTH 1 /* DMIC1R_ENA */ -#define WM8995_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8995_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ -#define WM8995_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ -#define WM8995_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ -#define WM8995_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8995_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ -#define WM8995_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ -#define WM8995_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ - -/* - * R4 (0x04) - Power Management (4) - */ -#define WM8995_AIF2DACL_ENA 0x2000 /* AIF2DACL_ENA */ -#define WM8995_AIF2DACL_ENA_MASK 0x2000 /* AIF2DACL_ENA */ -#define WM8995_AIF2DACL_ENA_SHIFT 13 /* AIF2DACL_ENA */ -#define WM8995_AIF2DACL_ENA_WIDTH 1 /* AIF2DACL_ENA */ -#define WM8995_AIF2DACR_ENA 0x1000 /* AIF2DACR_ENA */ -#define WM8995_AIF2DACR_ENA_MASK 0x1000 /* AIF2DACR_ENA */ -#define WM8995_AIF2DACR_ENA_SHIFT 12 /* AIF2DACR_ENA */ -#define WM8995_AIF2DACR_ENA_WIDTH 1 /* AIF2DACR_ENA */ -#define WM8995_AIF1DAC2L_ENA 0x0800 /* AIF1DAC2L_ENA */ -#define WM8995_AIF1DAC2L_ENA_MASK 0x0800 /* AIF1DAC2L_ENA */ -#define WM8995_AIF1DAC2L_ENA_SHIFT 11 /* AIF1DAC2L_ENA */ -#define WM8995_AIF1DAC2L_ENA_WIDTH 1 /* AIF1DAC2L_ENA */ -#define WM8995_AIF1DAC2R_ENA 0x0400 /* AIF1DAC2R_ENA */ -#define WM8995_AIF1DAC2R_ENA_MASK 0x0400 /* AIF1DAC2R_ENA */ -#define WM8995_AIF1DAC2R_ENA_SHIFT 10 /* AIF1DAC2R_ENA */ -#define WM8995_AIF1DAC2R_ENA_WIDTH 1 /* AIF1DAC2R_ENA */ -#define WM8995_AIF1DAC1L_ENA 0x0200 /* AIF1DAC1L_ENA */ -#define WM8995_AIF1DAC1L_ENA_MASK 0x0200 /* AIF1DAC1L_ENA */ -#define WM8995_AIF1DAC1L_ENA_SHIFT 9 /* AIF1DAC1L_ENA */ -#define WM8995_AIF1DAC1L_ENA_WIDTH 1 /* AIF1DAC1L_ENA */ -#define WM8995_AIF1DAC1R_ENA 0x0100 /* AIF1DAC1R_ENA */ -#define WM8995_AIF1DAC1R_ENA_MASK 0x0100 /* AIF1DAC1R_ENA */ -#define WM8995_AIF1DAC1R_ENA_SHIFT 8 /* AIF1DAC1R_ENA */ -#define WM8995_AIF1DAC1R_ENA_WIDTH 1 /* AIF1DAC1R_ENA */ -#define WM8995_DAC2L_ENA 0x0008 /* DAC2L_ENA */ -#define WM8995_DAC2L_ENA_MASK 0x0008 /* DAC2L_ENA */ -#define WM8995_DAC2L_ENA_SHIFT 3 /* DAC2L_ENA */ -#define WM8995_DAC2L_ENA_WIDTH 1 /* DAC2L_ENA */ -#define WM8995_DAC2R_ENA 0x0004 /* DAC2R_ENA */ -#define WM8995_DAC2R_ENA_MASK 0x0004 /* DAC2R_ENA */ -#define WM8995_DAC2R_ENA_SHIFT 2 /* DAC2R_ENA */ -#define WM8995_DAC2R_ENA_WIDTH 1 /* DAC2R_ENA */ -#define WM8995_DAC1L_ENA 0x0002 /* DAC1L_ENA */ -#define WM8995_DAC1L_ENA_MASK 0x0002 /* DAC1L_ENA */ -#define WM8995_DAC1L_ENA_SHIFT 1 /* DAC1L_ENA */ -#define WM8995_DAC1L_ENA_WIDTH 1 /* DAC1L_ENA */ -#define WM8995_DAC1R_ENA 0x0001 /* DAC1R_ENA */ -#define WM8995_DAC1R_ENA_MASK 0x0001 /* DAC1R_ENA */ -#define WM8995_DAC1R_ENA_SHIFT 0 /* DAC1R_ENA */ -#define WM8995_DAC1R_ENA_WIDTH 1 /* DAC1R_ENA */ - -/* - * R5 (0x05) - Power Management (5) - */ -#define WM8995_DMIC_SRC2_MASK 0x0300 /* DMIC_SRC2 - [9:8] */ -#define WM8995_DMIC_SRC2_SHIFT 8 /* DMIC_SRC2 - [9:8] */ -#define WM8995_DMIC_SRC2_WIDTH 2 /* DMIC_SRC2 - [9:8] */ -#define WM8995_DMIC_SRC1_MASK 0x00C0 /* DMIC_SRC1 - [7:6] */ -#define WM8995_DMIC_SRC1_SHIFT 6 /* DMIC_SRC1 - [7:6] */ -#define WM8995_DMIC_SRC1_WIDTH 2 /* DMIC_SRC1 - [7:6] */ -#define WM8995_AIF3_TRI 0x0020 /* AIF3_TRI */ -#define WM8995_AIF3_TRI_MASK 0x0020 /* AIF3_TRI */ -#define WM8995_AIF3_TRI_SHIFT 5 /* AIF3_TRI */ -#define WM8995_AIF3_TRI_WIDTH 1 /* AIF3_TRI */ -#define WM8995_AIF3_ADCDAT_SRC_MASK 0x0018 /* AIF3_ADCDAT_SRC - [4:3] */ -#define WM8995_AIF3_ADCDAT_SRC_SHIFT 3 /* AIF3_ADCDAT_SRC - [4:3] */ -#define WM8995_AIF3_ADCDAT_SRC_WIDTH 2 /* AIF3_ADCDAT_SRC - [4:3] */ -#define WM8995_AIF2_ADCDAT_SRC 0x0004 /* AIF2_ADCDAT_SRC */ -#define WM8995_AIF2_ADCDAT_SRC_MASK 0x0004 /* AIF2_ADCDAT_SRC */ -#define WM8995_AIF2_ADCDAT_SRC_SHIFT 2 /* AIF2_ADCDAT_SRC */ -#define WM8995_AIF2_ADCDAT_SRC_WIDTH 1 /* AIF2_ADCDAT_SRC */ -#define WM8995_AIF2_DACDAT_SRC 0x0002 /* AIF2_DACDAT_SRC */ -#define WM8995_AIF2_DACDAT_SRC_MASK 0x0002 /* AIF2_DACDAT_SRC */ -#define WM8995_AIF2_DACDAT_SRC_SHIFT 1 /* AIF2_DACDAT_SRC */ -#define WM8995_AIF2_DACDAT_SRC_WIDTH 1 /* AIF2_DACDAT_SRC */ -#define WM8995_AIF1_DACDAT_SRC 0x0001 /* AIF1_DACDAT_SRC */ -#define WM8995_AIF1_DACDAT_SRC_MASK 0x0001 /* AIF1_DACDAT_SRC */ -#define WM8995_AIF1_DACDAT_SRC_SHIFT 0 /* AIF1_DACDAT_SRC */ -#define WM8995_AIF1_DACDAT_SRC_WIDTH 1 /* AIF1_DACDAT_SRC */ - -/* - * R16 (0x10) - Left Line Input 1 Volume - */ -#define WM8995_IN1_VU 0x0080 /* IN1_VU */ -#define WM8995_IN1_VU_MASK 0x0080 /* IN1_VU */ -#define WM8995_IN1_VU_SHIFT 7 /* IN1_VU */ -#define WM8995_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8995_IN1L_ZC 0x0020 /* IN1L_ZC */ -#define WM8995_IN1L_ZC_MASK 0x0020 /* IN1L_ZC */ -#define WM8995_IN1L_ZC_SHIFT 5 /* IN1L_ZC */ -#define WM8995_IN1L_ZC_WIDTH 1 /* IN1L_ZC */ -#define WM8995_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */ -#define WM8995_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */ -#define WM8995_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */ - -/* - * R17 (0x11) - Right Line Input 1 Volume - */ -#define WM8995_IN1_VU 0x0080 /* IN1_VU */ -#define WM8995_IN1_VU_MASK 0x0080 /* IN1_VU */ -#define WM8995_IN1_VU_SHIFT 7 /* IN1_VU */ -#define WM8995_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8995_IN1R_ZC 0x0020 /* IN1R_ZC */ -#define WM8995_IN1R_ZC_MASK 0x0020 /* IN1R_ZC */ -#define WM8995_IN1R_ZC_SHIFT 5 /* IN1R_ZC */ -#define WM8995_IN1R_ZC_WIDTH 1 /* IN1R_ZC */ -#define WM8995_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */ -#define WM8995_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */ -#define WM8995_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */ - -/* - * R18 (0x12) - Left Line Input Control - */ -#define WM8995_IN1L_BOOST_MASK 0x0030 /* IN1L_BOOST - [5:4] */ -#define WM8995_IN1L_BOOST_SHIFT 4 /* IN1L_BOOST - [5:4] */ -#define WM8995_IN1L_BOOST_WIDTH 2 /* IN1L_BOOST - [5:4] */ -#define WM8995_IN1L_MODE_MASK 0x000C /* IN1L_MODE - [3:2] */ -#define WM8995_IN1L_MODE_SHIFT 2 /* IN1L_MODE - [3:2] */ -#define WM8995_IN1L_MODE_WIDTH 2 /* IN1L_MODE - [3:2] */ -#define WM8995_IN1R_MODE_MASK 0x0003 /* IN1R_MODE - [1:0] */ -#define WM8995_IN1R_MODE_SHIFT 0 /* IN1R_MODE - [1:0] */ -#define WM8995_IN1R_MODE_WIDTH 2 /* IN1R_MODE - [1:0] */ - -/* - * R24 (0x18) - DAC1 Left Volume - */ -#define WM8995_DAC1L_MUTE 0x0200 /* DAC1L_MUTE */ -#define WM8995_DAC1L_MUTE_MASK 0x0200 /* DAC1L_MUTE */ -#define WM8995_DAC1L_MUTE_SHIFT 9 /* DAC1L_MUTE */ -#define WM8995_DAC1L_MUTE_WIDTH 1 /* DAC1L_MUTE */ -#define WM8995_DAC1_VU 0x0100 /* DAC1_VU */ -#define WM8995_DAC1_VU_MASK 0x0100 /* DAC1_VU */ -#define WM8995_DAC1_VU_SHIFT 8 /* DAC1_VU */ -#define WM8995_DAC1_VU_WIDTH 1 /* DAC1_VU */ -#define WM8995_DAC1L_VOL_MASK 0x00FF /* DAC1L_VOL - [7:0] */ -#define WM8995_DAC1L_VOL_SHIFT 0 /* DAC1L_VOL - [7:0] */ -#define WM8995_DAC1L_VOL_WIDTH 8 /* DAC1L_VOL - [7:0] */ - -/* - * R25 (0x19) - DAC1 Right Volume - */ -#define WM8995_DAC1R_MUTE 0x0200 /* DAC1R_MUTE */ -#define WM8995_DAC1R_MUTE_MASK 0x0200 /* DAC1R_MUTE */ -#define WM8995_DAC1R_MUTE_SHIFT 9 /* DAC1R_MUTE */ -#define WM8995_DAC1R_MUTE_WIDTH 1 /* DAC1R_MUTE */ -#define WM8995_DAC1_VU 0x0100 /* DAC1_VU */ -#define WM8995_DAC1_VU_MASK 0x0100 /* DAC1_VU */ -#define WM8995_DAC1_VU_SHIFT 8 /* DAC1_VU */ -#define WM8995_DAC1_VU_WIDTH 1 /* DAC1_VU */ -#define WM8995_DAC1R_VOL_MASK 0x00FF /* DAC1R_VOL - [7:0] */ -#define WM8995_DAC1R_VOL_SHIFT 0 /* DAC1R_VOL - [7:0] */ -#define WM8995_DAC1R_VOL_WIDTH 8 /* DAC1R_VOL - [7:0] */ - -/* - * R26 (0x1A) - DAC2 Left Volume - */ -#define WM8995_DAC2L_MUTE 0x0200 /* DAC2L_MUTE */ -#define WM8995_DAC2L_MUTE_MASK 0x0200 /* DAC2L_MUTE */ -#define WM8995_DAC2L_MUTE_SHIFT 9 /* DAC2L_MUTE */ -#define WM8995_DAC2L_MUTE_WIDTH 1 /* DAC2L_MUTE */ -#define WM8995_DAC2_VU 0x0100 /* DAC2_VU */ -#define WM8995_DAC2_VU_MASK 0x0100 /* DAC2_VU */ -#define WM8995_DAC2_VU_SHIFT 8 /* DAC2_VU */ -#define WM8995_DAC2_VU_WIDTH 1 /* DAC2_VU */ -#define WM8995_DAC2L_VOL_MASK 0x00FF /* DAC2L_VOL - [7:0] */ -#define WM8995_DAC2L_VOL_SHIFT 0 /* DAC2L_VOL - [7:0] */ -#define WM8995_DAC2L_VOL_WIDTH 8 /* DAC2L_VOL - [7:0] */ - -/* - * R27 (0x1B) - DAC2 Right Volume - */ -#define WM8995_DAC2R_MUTE 0x0200 /* DAC2R_MUTE */ -#define WM8995_DAC2R_MUTE_MASK 0x0200 /* DAC2R_MUTE */ -#define WM8995_DAC2R_MUTE_SHIFT 9 /* DAC2R_MUTE */ -#define WM8995_DAC2R_MUTE_WIDTH 1 /* DAC2R_MUTE */ -#define WM8995_DAC2_VU 0x0100 /* DAC2_VU */ -#define WM8995_DAC2_VU_MASK 0x0100 /* DAC2_VU */ -#define WM8995_DAC2_VU_SHIFT 8 /* DAC2_VU */ -#define WM8995_DAC2_VU_WIDTH 1 /* DAC2_VU */ -#define WM8995_DAC2R_VOL_MASK 0x00FF /* DAC2R_VOL - [7:0] */ -#define WM8995_DAC2R_VOL_SHIFT 0 /* DAC2R_VOL - [7:0] */ -#define WM8995_DAC2R_VOL_WIDTH 8 /* DAC2R_VOL - [7:0] */ - -/* - * R28 (0x1C) - Output Volume ZC (1) - */ -#define WM8995_HPOUT2L_ZC 0x0008 /* HPOUT2L_ZC */ -#define WM8995_HPOUT2L_ZC_MASK 0x0008 /* HPOUT2L_ZC */ -#define WM8995_HPOUT2L_ZC_SHIFT 3 /* HPOUT2L_ZC */ -#define WM8995_HPOUT2L_ZC_WIDTH 1 /* HPOUT2L_ZC */ -#define WM8995_HPOUT2R_ZC 0x0004 /* HPOUT2R_ZC */ -#define WM8995_HPOUT2R_ZC_MASK 0x0004 /* HPOUT2R_ZC */ -#define WM8995_HPOUT2R_ZC_SHIFT 2 /* HPOUT2R_ZC */ -#define WM8995_HPOUT2R_ZC_WIDTH 1 /* HPOUT2R_ZC */ -#define WM8995_HPOUT1L_ZC 0x0002 /* HPOUT1L_ZC */ -#define WM8995_HPOUT1L_ZC_MASK 0x0002 /* HPOUT1L_ZC */ -#define WM8995_HPOUT1L_ZC_SHIFT 1 /* HPOUT1L_ZC */ -#define WM8995_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */ -#define WM8995_HPOUT1R_ZC 0x0001 /* HPOUT1R_ZC */ -#define WM8995_HPOUT1R_ZC_MASK 0x0001 /* HPOUT1R_ZC */ -#define WM8995_HPOUT1R_ZC_SHIFT 0 /* HPOUT1R_ZC */ -#define WM8995_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */ - -/* - * R32 (0x20) - MICBIAS (1) - */ -#define WM8995_MICB1_MODE 0x0008 /* MICB1_MODE */ -#define WM8995_MICB1_MODE_MASK 0x0008 /* MICB1_MODE */ -#define WM8995_MICB1_MODE_SHIFT 3 /* MICB1_MODE */ -#define WM8995_MICB1_MODE_WIDTH 1 /* MICB1_MODE */ -#define WM8995_MICB1_LVL_MASK 0x0006 /* MICB1_LVL - [2:1] */ -#define WM8995_MICB1_LVL_SHIFT 1 /* MICB1_LVL - [2:1] */ -#define WM8995_MICB1_LVL_WIDTH 2 /* MICB1_LVL - [2:1] */ -#define WM8995_MICB1_DISCH 0x0001 /* MICB1_DISCH */ -#define WM8995_MICB1_DISCH_MASK 0x0001 /* MICB1_DISCH */ -#define WM8995_MICB1_DISCH_SHIFT 0 /* MICB1_DISCH */ -#define WM8995_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */ - -/* - * R33 (0x21) - MICBIAS (2) - */ -#define WM8995_MICB2_MODE 0x0008 /* MICB2_MODE */ -#define WM8995_MICB2_MODE_MASK 0x0008 /* MICB2_MODE */ -#define WM8995_MICB2_MODE_SHIFT 3 /* MICB2_MODE */ -#define WM8995_MICB2_MODE_WIDTH 1 /* MICB2_MODE */ -#define WM8995_MICB2_LVL_MASK 0x0006 /* MICB2_LVL - [2:1] */ -#define WM8995_MICB2_LVL_SHIFT 1 /* MICB2_LVL - [2:1] */ -#define WM8995_MICB2_LVL_WIDTH 2 /* MICB2_LVL - [2:1] */ -#define WM8995_MICB2_DISCH 0x0001 /* MICB2_DISCH */ -#define WM8995_MICB2_DISCH_MASK 0x0001 /* MICB2_DISCH */ -#define WM8995_MICB2_DISCH_SHIFT 0 /* MICB2_DISCH */ -#define WM8995_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ - -/* - * R40 (0x28) - LDO 1 - */ -#define WM8995_LDO1_MODE 0x0020 /* LDO1_MODE */ -#define WM8995_LDO1_MODE_MASK 0x0020 /* LDO1_MODE */ -#define WM8995_LDO1_MODE_SHIFT 5 /* LDO1_MODE */ -#define WM8995_LDO1_MODE_WIDTH 1 /* LDO1_MODE */ -#define WM8995_LDO1_VSEL_MASK 0x0006 /* LDO1_VSEL - [2:1] */ -#define WM8995_LDO1_VSEL_SHIFT 1 /* LDO1_VSEL - [2:1] */ -#define WM8995_LDO1_VSEL_WIDTH 2 /* LDO1_VSEL - [2:1] */ -#define WM8995_LDO1_DISCH 0x0001 /* LDO1_DISCH */ -#define WM8995_LDO1_DISCH_MASK 0x0001 /* LDO1_DISCH */ -#define WM8995_LDO1_DISCH_SHIFT 0 /* LDO1_DISCH */ -#define WM8995_LDO1_DISCH_WIDTH 1 /* LDO1_DISCH */ - -/* - * R41 (0x29) - LDO 2 - */ -#define WM8995_LDO2_MODE 0x0020 /* LDO2_MODE */ -#define WM8995_LDO2_MODE_MASK 0x0020 /* LDO2_MODE */ -#define WM8995_LDO2_MODE_SHIFT 5 /* LDO2_MODE */ -#define WM8995_LDO2_MODE_WIDTH 1 /* LDO2_MODE */ -#define WM8995_LDO2_VSEL_MASK 0x001E /* LDO2_VSEL - [4:1] */ -#define WM8995_LDO2_VSEL_SHIFT 1 /* LDO2_VSEL - [4:1] */ -#define WM8995_LDO2_VSEL_WIDTH 4 /* LDO2_VSEL - [4:1] */ -#define WM8995_LDO2_DISCH 0x0001 /* LDO2_DISCH */ -#define WM8995_LDO2_DISCH_MASK 0x0001 /* LDO2_DISCH */ -#define WM8995_LDO2_DISCH_SHIFT 0 /* LDO2_DISCH */ -#define WM8995_LDO2_DISCH_WIDTH 1 /* LDO2_DISCH */ - -/* - * R48 (0x30) - Accessory Detect Mode1 - */ -#define WM8995_JD_MODE_MASK 0x0003 /* JD_MODE - [1:0] */ -#define WM8995_JD_MODE_SHIFT 0 /* JD_MODE - [1:0] */ -#define WM8995_JD_MODE_WIDTH 2 /* JD_MODE - [1:0] */ - -/* - * R49 (0x31) - Accessory Detect Mode2 - */ -#define WM8995_VID_ENA 0x0001 /* VID_ENA */ -#define WM8995_VID_ENA_MASK 0x0001 /* VID_ENA */ -#define WM8995_VID_ENA_SHIFT 0 /* VID_ENA */ -#define WM8995_VID_ENA_WIDTH 1 /* VID_ENA */ - -/* - * R52 (0x34) - Headphone Detect1 - */ -#define WM8995_HP_RAMPRATE 0x0002 /* HP_RAMPRATE */ -#define WM8995_HP_RAMPRATE_MASK 0x0002 /* HP_RAMPRATE */ -#define WM8995_HP_RAMPRATE_SHIFT 1 /* HP_RAMPRATE */ -#define WM8995_HP_RAMPRATE_WIDTH 1 /* HP_RAMPRATE */ -#define WM8995_HP_POLL 0x0001 /* HP_POLL */ -#define WM8995_HP_POLL_MASK 0x0001 /* HP_POLL */ -#define WM8995_HP_POLL_SHIFT 0 /* HP_POLL */ -#define WM8995_HP_POLL_WIDTH 1 /* HP_POLL */ - -/* - * R53 (0x35) - Headphone Detect2 - */ -#define WM8995_HP_DONE 0x0080 /* HP_DONE */ -#define WM8995_HP_DONE_MASK 0x0080 /* HP_DONE */ -#define WM8995_HP_DONE_SHIFT 7 /* HP_DONE */ -#define WM8995_HP_DONE_WIDTH 1 /* HP_DONE */ -#define WM8995_HP_LVL_MASK 0x007F /* HP_LVL - [6:0] */ -#define WM8995_HP_LVL_SHIFT 0 /* HP_LVL - [6:0] */ -#define WM8995_HP_LVL_WIDTH 7 /* HP_LVL - [6:0] */ - -/* - * R56 (0x38) - Mic Detect (1) - */ -#define WM8995_MICD_RATE_MASK 0x7800 /* MICD_RATE - [14:11] */ -#define WM8995_MICD_RATE_SHIFT 11 /* MICD_RATE - [14:11] */ -#define WM8995_MICD_RATE_WIDTH 4 /* MICD_RATE - [14:11] */ -#define WM8995_MICD_LVL_SEL_MASK 0x01F8 /* MICD_LVL_SEL - [8:3] */ -#define WM8995_MICD_LVL_SEL_SHIFT 3 /* MICD_LVL_SEL - [8:3] */ -#define WM8995_MICD_LVL_SEL_WIDTH 6 /* MICD_LVL_SEL - [8:3] */ -#define WM8995_MICD_DBTIME 0x0002 /* MICD_DBTIME */ -#define WM8995_MICD_DBTIME_MASK 0x0002 /* MICD_DBTIME */ -#define WM8995_MICD_DBTIME_SHIFT 1 /* MICD_DBTIME */ -#define WM8995_MICD_DBTIME_WIDTH 1 /* MICD_DBTIME */ -#define WM8995_MICD_ENA 0x0001 /* MICD_ENA */ -#define WM8995_MICD_ENA_MASK 0x0001 /* MICD_ENA */ -#define WM8995_MICD_ENA_SHIFT 0 /* MICD_ENA */ -#define WM8995_MICD_ENA_WIDTH 1 /* MICD_ENA */ - -/* - * R57 (0x39) - Mic Detect (2) - */ -#define WM8995_MICD_LVL_MASK 0x01FC /* MICD_LVL - [8:2] */ -#define WM8995_MICD_LVL_SHIFT 2 /* MICD_LVL - [8:2] */ -#define WM8995_MICD_LVL_WIDTH 7 /* MICD_LVL - [8:2] */ -#define WM8995_MICD_VALID 0x0002 /* MICD_VALID */ -#define WM8995_MICD_VALID_MASK 0x0002 /* MICD_VALID */ -#define WM8995_MICD_VALID_SHIFT 1 /* MICD_VALID */ -#define WM8995_MICD_VALID_WIDTH 1 /* MICD_VALID */ -#define WM8995_MICD_STS 0x0001 /* MICD_STS */ -#define WM8995_MICD_STS_MASK 0x0001 /* MICD_STS */ -#define WM8995_MICD_STS_SHIFT 0 /* MICD_STS */ -#define WM8995_MICD_STS_WIDTH 1 /* MICD_STS */ - -/* - * R64 (0x40) - Charge Pump (1) - */ -#define WM8995_CP_ENA 0x8000 /* CP_ENA */ -#define WM8995_CP_ENA_MASK 0x8000 /* CP_ENA */ -#define WM8995_CP_ENA_SHIFT 15 /* CP_ENA */ -#define WM8995_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R69 (0x45) - Class W (1) - */ -#define WM8995_CP_DYN_SRC_SEL_MASK 0x0300 /* CP_DYN_SRC_SEL - [9:8] */ -#define WM8995_CP_DYN_SRC_SEL_SHIFT 8 /* CP_DYN_SRC_SEL - [9:8] */ -#define WM8995_CP_DYN_SRC_SEL_WIDTH 2 /* CP_DYN_SRC_SEL - [9:8] */ -#define WM8995_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */ -#define WM8995_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */ -#define WM8995_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */ -#define WM8995_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */ - -/* - * R80 (0x50) - DC Servo (1) - */ -#define WM8995_DCS_ENA_CHAN_3 0x0008 /* DCS_ENA_CHAN_3 */ -#define WM8995_DCS_ENA_CHAN_3_MASK 0x0008 /* DCS_ENA_CHAN_3 */ -#define WM8995_DCS_ENA_CHAN_3_SHIFT 3 /* DCS_ENA_CHAN_3 */ -#define WM8995_DCS_ENA_CHAN_3_WIDTH 1 /* DCS_ENA_CHAN_3 */ -#define WM8995_DCS_ENA_CHAN_2 0x0004 /* DCS_ENA_CHAN_2 */ -#define WM8995_DCS_ENA_CHAN_2_MASK 0x0004 /* DCS_ENA_CHAN_2 */ -#define WM8995_DCS_ENA_CHAN_2_SHIFT 2 /* DCS_ENA_CHAN_2 */ -#define WM8995_DCS_ENA_CHAN_2_WIDTH 1 /* DCS_ENA_CHAN_2 */ -#define WM8995_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8995_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8995_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ -#define WM8995_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ -#define WM8995_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8995_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8995_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ -#define WM8995_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ - -/* - * R81 (0x51) - DC Servo (2) - */ -#define WM8995_DCS_TRIG_SINGLE_3 0x8000 /* DCS_TRIG_SINGLE_3 */ -#define WM8995_DCS_TRIG_SINGLE_3_MASK 0x8000 /* DCS_TRIG_SINGLE_3 */ -#define WM8995_DCS_TRIG_SINGLE_3_SHIFT 15 /* DCS_TRIG_SINGLE_3 */ -#define WM8995_DCS_TRIG_SINGLE_3_WIDTH 1 /* DCS_TRIG_SINGLE_3 */ -#define WM8995_DCS_TRIG_SINGLE_2 0x4000 /* DCS_TRIG_SINGLE_2 */ -#define WM8995_DCS_TRIG_SINGLE_2_MASK 0x4000 /* DCS_TRIG_SINGLE_2 */ -#define WM8995_DCS_TRIG_SINGLE_2_SHIFT 14 /* DCS_TRIG_SINGLE_2 */ -#define WM8995_DCS_TRIG_SINGLE_2_WIDTH 1 /* DCS_TRIG_SINGLE_2 */ -#define WM8995_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8995_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8995_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ -#define WM8995_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ -#define WM8995_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8995_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8995_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ -#define WM8995_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ -#define WM8995_DCS_TRIG_SERIES_3 0x0800 /* DCS_TRIG_SERIES_3 */ -#define WM8995_DCS_TRIG_SERIES_3_MASK 0x0800 /* DCS_TRIG_SERIES_3 */ -#define WM8995_DCS_TRIG_SERIES_3_SHIFT 11 /* DCS_TRIG_SERIES_3 */ -#define WM8995_DCS_TRIG_SERIES_3_WIDTH 1 /* DCS_TRIG_SERIES_3 */ -#define WM8995_DCS_TRIG_SERIES_2 0x0400 /* DCS_TRIG_SERIES_2 */ -#define WM8995_DCS_TRIG_SERIES_2_MASK 0x0400 /* DCS_TRIG_SERIES_2 */ -#define WM8995_DCS_TRIG_SERIES_2_SHIFT 10 /* DCS_TRIG_SERIES_2 */ -#define WM8995_DCS_TRIG_SERIES_2_WIDTH 1 /* DCS_TRIG_SERIES_2 */ -#define WM8995_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8995_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8995_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ -#define WM8995_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ -#define WM8995_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8995_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8995_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ -#define WM8995_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ -#define WM8995_DCS_TRIG_STARTUP_3 0x0080 /* DCS_TRIG_STARTUP_3 */ -#define WM8995_DCS_TRIG_STARTUP_3_MASK 0x0080 /* DCS_TRIG_STARTUP_3 */ -#define WM8995_DCS_TRIG_STARTUP_3_SHIFT 7 /* DCS_TRIG_STARTUP_3 */ -#define WM8995_DCS_TRIG_STARTUP_3_WIDTH 1 /* DCS_TRIG_STARTUP_3 */ -#define WM8995_DCS_TRIG_STARTUP_2 0x0040 /* DCS_TRIG_STARTUP_2 */ -#define WM8995_DCS_TRIG_STARTUP_2_MASK 0x0040 /* DCS_TRIG_STARTUP_2 */ -#define WM8995_DCS_TRIG_STARTUP_2_SHIFT 6 /* DCS_TRIG_STARTUP_2 */ -#define WM8995_DCS_TRIG_STARTUP_2_WIDTH 1 /* DCS_TRIG_STARTUP_2 */ -#define WM8995_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8995_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8995_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ -#define WM8995_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ -#define WM8995_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8995_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8995_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ -#define WM8995_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ -#define WM8995_DCS_TRIG_DAC_WR_3 0x0008 /* DCS_TRIG_DAC_WR_3 */ -#define WM8995_DCS_TRIG_DAC_WR_3_MASK 0x0008 /* DCS_TRIG_DAC_WR_3 */ -#define WM8995_DCS_TRIG_DAC_WR_3_SHIFT 3 /* DCS_TRIG_DAC_WR_3 */ -#define WM8995_DCS_TRIG_DAC_WR_3_WIDTH 1 /* DCS_TRIG_DAC_WR_3 */ -#define WM8995_DCS_TRIG_DAC_WR_2 0x0004 /* DCS_TRIG_DAC_WR_2 */ -#define WM8995_DCS_TRIG_DAC_WR_2_MASK 0x0004 /* DCS_TRIG_DAC_WR_2 */ -#define WM8995_DCS_TRIG_DAC_WR_2_SHIFT 2 /* DCS_TRIG_DAC_WR_2 */ -#define WM8995_DCS_TRIG_DAC_WR_2_WIDTH 1 /* DCS_TRIG_DAC_WR_2 */ -#define WM8995_DCS_TRIG_DAC_WR_1 0x0002 /* DCS_TRIG_DAC_WR_1 */ -#define WM8995_DCS_TRIG_DAC_WR_1_MASK 0x0002 /* DCS_TRIG_DAC_WR_1 */ -#define WM8995_DCS_TRIG_DAC_WR_1_SHIFT 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8995_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8995_DCS_TRIG_DAC_WR_0 0x0001 /* DCS_TRIG_DAC_WR_0 */ -#define WM8995_DCS_TRIG_DAC_WR_0_MASK 0x0001 /* DCS_TRIG_DAC_WR_0 */ -#define WM8995_DCS_TRIG_DAC_WR_0_SHIFT 0 /* DCS_TRIG_DAC_WR_0 */ -#define WM8995_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ - -/* - * R82 (0x52) - DC Servo (3) - */ -#define WM8995_DCS_TIMER_PERIOD_23_MASK 0x0F00 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8995_DCS_TIMER_PERIOD_23_SHIFT 8 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8995_DCS_TIMER_PERIOD_23_WIDTH 4 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8995_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8995_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8995_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ - -/* - * R84 (0x54) - DC Servo (5) - */ -#define WM8995_DCS_SERIES_NO_23_MASK 0x7F00 /* DCS_SERIES_NO_23 - [14:8] */ -#define WM8995_DCS_SERIES_NO_23_SHIFT 8 /* DCS_SERIES_NO_23 - [14:8] */ -#define WM8995_DCS_SERIES_NO_23_WIDTH 7 /* DCS_SERIES_NO_23 - [14:8] */ -#define WM8995_DCS_SERIES_NO_01_MASK 0x007F /* DCS_SERIES_NO_01 - [6:0] */ -#define WM8995_DCS_SERIES_NO_01_SHIFT 0 /* DCS_SERIES_NO_01 - [6:0] */ -#define WM8995_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [6:0] */ - -/* - * R85 (0x55) - DC Servo (6) - */ -#define WM8995_DCS_DAC_WR_VAL_3_MASK 0xFF00 /* DCS_DAC_WR_VAL_3 - [15:8] */ -#define WM8995_DCS_DAC_WR_VAL_3_SHIFT 8 /* DCS_DAC_WR_VAL_3 - [15:8] */ -#define WM8995_DCS_DAC_WR_VAL_3_WIDTH 8 /* DCS_DAC_WR_VAL_3 - [15:8] */ -#define WM8995_DCS_DAC_WR_VAL_2_MASK 0x00FF /* DCS_DAC_WR_VAL_2 - [7:0] */ -#define WM8995_DCS_DAC_WR_VAL_2_SHIFT 0 /* DCS_DAC_WR_VAL_2 - [7:0] */ -#define WM8995_DCS_DAC_WR_VAL_2_WIDTH 8 /* DCS_DAC_WR_VAL_2 - [7:0] */ - -/* - * R86 (0x56) - DC Servo (7) - */ -#define WM8995_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8995_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8995_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8995_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8995_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8995_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ - -/* - * R87 (0x57) - DC Servo Readback 0 - */ -#define WM8995_DCS_CAL_COMPLETE_MASK 0x0F00 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8995_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8995_DCS_CAL_COMPLETE_WIDTH 4 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8995_DCS_DAC_WR_COMPLETE_MASK 0x00F0 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8995_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8995_DCS_DAC_WR_COMPLETE_WIDTH 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8995_DCS_STARTUP_COMPLETE_MASK 0x000F /* DCS_STARTUP_COMPLETE - [3:0] */ -#define WM8995_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [3:0] */ -#define WM8995_DCS_STARTUP_COMPLETE_WIDTH 4 /* DCS_STARTUP_COMPLETE - [3:0] */ - -/* - * R96 (0x60) - Analogue HP (1) - */ -#define WM8995_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8995_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8995_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */ -#define WM8995_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */ -#define WM8995_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */ -#define WM8995_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */ -#define WM8995_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */ -#define WM8995_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */ -#define WM8995_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */ -#define WM8995_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */ -#define WM8995_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */ -#define WM8995_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */ -#define WM8995_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8995_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8995_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */ -#define WM8995_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */ -#define WM8995_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */ -#define WM8995_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */ -#define WM8995_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */ -#define WM8995_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */ -#define WM8995_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */ -#define WM8995_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */ -#define WM8995_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */ -#define WM8995_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */ - -/* - * R97 (0x61) - Analogue HP (2) - */ -#define WM8995_HPOUT2L_RMV_SHORT 0x0080 /* HPOUT2L_RMV_SHORT */ -#define WM8995_HPOUT2L_RMV_SHORT_MASK 0x0080 /* HPOUT2L_RMV_SHORT */ -#define WM8995_HPOUT2L_RMV_SHORT_SHIFT 7 /* HPOUT2L_RMV_SHORT */ -#define WM8995_HPOUT2L_RMV_SHORT_WIDTH 1 /* HPOUT2L_RMV_SHORT */ -#define WM8995_HPOUT2L_OUTP 0x0040 /* HPOUT2L_OUTP */ -#define WM8995_HPOUT2L_OUTP_MASK 0x0040 /* HPOUT2L_OUTP */ -#define WM8995_HPOUT2L_OUTP_SHIFT 6 /* HPOUT2L_OUTP */ -#define WM8995_HPOUT2L_OUTP_WIDTH 1 /* HPOUT2L_OUTP */ -#define WM8995_HPOUT2L_DLY 0x0020 /* HPOUT2L_DLY */ -#define WM8995_HPOUT2L_DLY_MASK 0x0020 /* HPOUT2L_DLY */ -#define WM8995_HPOUT2L_DLY_SHIFT 5 /* HPOUT2L_DLY */ -#define WM8995_HPOUT2L_DLY_WIDTH 1 /* HPOUT2L_DLY */ -#define WM8995_HPOUT2R_RMV_SHORT 0x0008 /* HPOUT2R_RMV_SHORT */ -#define WM8995_HPOUT2R_RMV_SHORT_MASK 0x0008 /* HPOUT2R_RMV_SHORT */ -#define WM8995_HPOUT2R_RMV_SHORT_SHIFT 3 /* HPOUT2R_RMV_SHORT */ -#define WM8995_HPOUT2R_RMV_SHORT_WIDTH 1 /* HPOUT2R_RMV_SHORT */ -#define WM8995_HPOUT2R_OUTP 0x0004 /* HPOUT2R_OUTP */ -#define WM8995_HPOUT2R_OUTP_MASK 0x0004 /* HPOUT2R_OUTP */ -#define WM8995_HPOUT2R_OUTP_SHIFT 2 /* HPOUT2R_OUTP */ -#define WM8995_HPOUT2R_OUTP_WIDTH 1 /* HPOUT2R_OUTP */ -#define WM8995_HPOUT2R_DLY 0x0002 /* HPOUT2R_DLY */ -#define WM8995_HPOUT2R_DLY_MASK 0x0002 /* HPOUT2R_DLY */ -#define WM8995_HPOUT2R_DLY_SHIFT 1 /* HPOUT2R_DLY */ -#define WM8995_HPOUT2R_DLY_WIDTH 1 /* HPOUT2R_DLY */ - -/* - * R256 (0x100) - Chip Revision - */ -#define WM8995_CHIP_REV_MASK 0x000F /* CHIP_REV - [3:0] */ -#define WM8995_CHIP_REV_SHIFT 0 /* CHIP_REV - [3:0] */ -#define WM8995_CHIP_REV_WIDTH 4 /* CHIP_REV - [3:0] */ - -/* - * R257 (0x101) - Control Interface (1) - */ -#define WM8995_REG_SYNC 0x8000 /* REG_SYNC */ -#define WM8995_REG_SYNC_MASK 0x8000 /* REG_SYNC */ -#define WM8995_REG_SYNC_SHIFT 15 /* REG_SYNC */ -#define WM8995_REG_SYNC_WIDTH 1 /* REG_SYNC */ -#define WM8995_SPI_CONTRD 0x0040 /* SPI_CONTRD */ -#define WM8995_SPI_CONTRD_MASK 0x0040 /* SPI_CONTRD */ -#define WM8995_SPI_CONTRD_SHIFT 6 /* SPI_CONTRD */ -#define WM8995_SPI_CONTRD_WIDTH 1 /* SPI_CONTRD */ -#define WM8995_SPI_4WIRE 0x0020 /* SPI_4WIRE */ -#define WM8995_SPI_4WIRE_MASK 0x0020 /* SPI_4WIRE */ -#define WM8995_SPI_4WIRE_SHIFT 5 /* SPI_4WIRE */ -#define WM8995_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */ -#define WM8995_SPI_CFG 0x0010 /* SPI_CFG */ -#define WM8995_SPI_CFG_MASK 0x0010 /* SPI_CFG */ -#define WM8995_SPI_CFG_SHIFT 4 /* SPI_CFG */ -#define WM8995_SPI_CFG_WIDTH 1 /* SPI_CFG */ -#define WM8995_AUTO_INC 0x0004 /* AUTO_INC */ -#define WM8995_AUTO_INC_MASK 0x0004 /* AUTO_INC */ -#define WM8995_AUTO_INC_SHIFT 2 /* AUTO_INC */ -#define WM8995_AUTO_INC_WIDTH 1 /* AUTO_INC */ - -/* - * R258 (0x102) - Control Interface (2) - */ -#define WM8995_CTRL_IF_SRC 0x0001 /* CTRL_IF_SRC */ -#define WM8995_CTRL_IF_SRC_MASK 0x0001 /* CTRL_IF_SRC */ -#define WM8995_CTRL_IF_SRC_SHIFT 0 /* CTRL_IF_SRC */ -#define WM8995_CTRL_IF_SRC_WIDTH 1 /* CTRL_IF_SRC */ - -/* - * R272 (0x110) - Write Sequencer Ctrl (1) - */ -#define WM8995_WSEQ_ENA 0x8000 /* WSEQ_ENA */ -#define WM8995_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */ -#define WM8995_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */ -#define WM8995_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8995_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM8995_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM8995_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM8995_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8995_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM8995_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM8995_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM8995_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8995_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */ -#define WM8995_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */ -#define WM8995_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */ - -/* - * R273 (0x111) - Write Sequencer Ctrl (2) - */ -#define WM8995_WSEQ_BUSY 0x0100 /* WSEQ_BUSY */ -#define WM8995_WSEQ_BUSY_MASK 0x0100 /* WSEQ_BUSY */ -#define WM8995_WSEQ_BUSY_SHIFT 8 /* WSEQ_BUSY */ -#define WM8995_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ -#define WM8995_WSEQ_CURRENT_INDEX_MASK 0x007F /* WSEQ_CURRENT_INDEX - [6:0] */ -#define WM8995_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [6:0] */ -#define WM8995_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [6:0] */ - -/* - * R512 (0x200) - AIF1 Clocking (1) - */ -#define WM8995_AIF1CLK_SRC_MASK 0x0018 /* AIF1CLK_SRC - [4:3] */ -#define WM8995_AIF1CLK_SRC_SHIFT 3 /* AIF1CLK_SRC - [4:3] */ -#define WM8995_AIF1CLK_SRC_WIDTH 2 /* AIF1CLK_SRC - [4:3] */ -#define WM8995_AIF1CLK_INV 0x0004 /* AIF1CLK_INV */ -#define WM8995_AIF1CLK_INV_MASK 0x0004 /* AIF1CLK_INV */ -#define WM8995_AIF1CLK_INV_SHIFT 2 /* AIF1CLK_INV */ -#define WM8995_AIF1CLK_INV_WIDTH 1 /* AIF1CLK_INV */ -#define WM8995_AIF1CLK_DIV 0x0002 /* AIF1CLK_DIV */ -#define WM8995_AIF1CLK_DIV_MASK 0x0002 /* AIF1CLK_DIV */ -#define WM8995_AIF1CLK_DIV_SHIFT 1 /* AIF1CLK_DIV */ -#define WM8995_AIF1CLK_DIV_WIDTH 1 /* AIF1CLK_DIV */ -#define WM8995_AIF1CLK_ENA 0x0001 /* AIF1CLK_ENA */ -#define WM8995_AIF1CLK_ENA_MASK 0x0001 /* AIF1CLK_ENA */ -#define WM8995_AIF1CLK_ENA_SHIFT 0 /* AIF1CLK_ENA */ -#define WM8995_AIF1CLK_ENA_WIDTH 1 /* AIF1CLK_ENA */ - -/* - * R513 (0x201) - AIF1 Clocking (2) - */ -#define WM8995_AIF1DAC_DIV_MASK 0x0038 /* AIF1DAC_DIV - [5:3] */ -#define WM8995_AIF1DAC_DIV_SHIFT 3 /* AIF1DAC_DIV - [5:3] */ -#define WM8995_AIF1DAC_DIV_WIDTH 3 /* AIF1DAC_DIV - [5:3] */ -#define WM8995_AIF1ADC_DIV_MASK 0x0007 /* AIF1ADC_DIV - [2:0] */ -#define WM8995_AIF1ADC_DIV_SHIFT 0 /* AIF1ADC_DIV - [2:0] */ -#define WM8995_AIF1ADC_DIV_WIDTH 3 /* AIF1ADC_DIV - [2:0] */ - -/* - * R516 (0x204) - AIF2 Clocking (1) - */ -#define WM8995_AIF2CLK_SRC_MASK 0x0018 /* AIF2CLK_SRC - [4:3] */ -#define WM8995_AIF2CLK_SRC_SHIFT 3 /* AIF2CLK_SRC - [4:3] */ -#define WM8995_AIF2CLK_SRC_WIDTH 2 /* AIF2CLK_SRC - [4:3] */ -#define WM8995_AIF2CLK_INV 0x0004 /* AIF2CLK_INV */ -#define WM8995_AIF2CLK_INV_MASK 0x0004 /* AIF2CLK_INV */ -#define WM8995_AIF2CLK_INV_SHIFT 2 /* AIF2CLK_INV */ -#define WM8995_AIF2CLK_INV_WIDTH 1 /* AIF2CLK_INV */ -#define WM8995_AIF2CLK_DIV 0x0002 /* AIF2CLK_DIV */ -#define WM8995_AIF2CLK_DIV_MASK 0x0002 /* AIF2CLK_DIV */ -#define WM8995_AIF2CLK_DIV_SHIFT 1 /* AIF2CLK_DIV */ -#define WM8995_AIF2CLK_DIV_WIDTH 1 /* AIF2CLK_DIV */ -#define WM8995_AIF2CLK_ENA 0x0001 /* AIF2CLK_ENA */ -#define WM8995_AIF2CLK_ENA_MASK 0x0001 /* AIF2CLK_ENA */ -#define WM8995_AIF2CLK_ENA_SHIFT 0 /* AIF2CLK_ENA */ -#define WM8995_AIF2CLK_ENA_WIDTH 1 /* AIF2CLK_ENA */ - -/* - * R517 (0x205) - AIF2 Clocking (2) - */ -#define WM8995_AIF2DAC_DIV_MASK 0x0038 /* AIF2DAC_DIV - [5:3] */ -#define WM8995_AIF2DAC_DIV_SHIFT 3 /* AIF2DAC_DIV - [5:3] */ -#define WM8995_AIF2DAC_DIV_WIDTH 3 /* AIF2DAC_DIV - [5:3] */ -#define WM8995_AIF2ADC_DIV_MASK 0x0007 /* AIF2ADC_DIV - [2:0] */ -#define WM8995_AIF2ADC_DIV_SHIFT 0 /* AIF2ADC_DIV - [2:0] */ -#define WM8995_AIF2ADC_DIV_WIDTH 3 /* AIF2ADC_DIV - [2:0] */ - -/* - * R520 (0x208) - Clocking (1) - */ -#define WM8995_LFCLK_ENA 0x0020 /* LFCLK_ENA */ -#define WM8995_LFCLK_ENA_MASK 0x0020 /* LFCLK_ENA */ -#define WM8995_LFCLK_ENA_SHIFT 5 /* LFCLK_ENA */ -#define WM8995_LFCLK_ENA_WIDTH 1 /* LFCLK_ENA */ -#define WM8995_TOCLK_ENA 0x0010 /* TOCLK_ENA */ -#define WM8995_TOCLK_ENA_MASK 0x0010 /* TOCLK_ENA */ -#define WM8995_TOCLK_ENA_SHIFT 4 /* TOCLK_ENA */ -#define WM8995_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ -#define WM8995_AIF1DSPCLK_ENA 0x0008 /* AIF1DSPCLK_ENA */ -#define WM8995_AIF1DSPCLK_ENA_MASK 0x0008 /* AIF1DSPCLK_ENA */ -#define WM8995_AIF1DSPCLK_ENA_SHIFT 3 /* AIF1DSPCLK_ENA */ -#define WM8995_AIF1DSPCLK_ENA_WIDTH 1 /* AIF1DSPCLK_ENA */ -#define WM8995_AIF2DSPCLK_ENA 0x0004 /* AIF2DSPCLK_ENA */ -#define WM8995_AIF2DSPCLK_ENA_MASK 0x0004 /* AIF2DSPCLK_ENA */ -#define WM8995_AIF2DSPCLK_ENA_SHIFT 2 /* AIF2DSPCLK_ENA */ -#define WM8995_AIF2DSPCLK_ENA_WIDTH 1 /* AIF2DSPCLK_ENA */ -#define WM8995_SYSDSPCLK_ENA 0x0002 /* SYSDSPCLK_ENA */ -#define WM8995_SYSDSPCLK_ENA_MASK 0x0002 /* SYSDSPCLK_ENA */ -#define WM8995_SYSDSPCLK_ENA_SHIFT 1 /* SYSDSPCLK_ENA */ -#define WM8995_SYSDSPCLK_ENA_WIDTH 1 /* SYSDSPCLK_ENA */ -#define WM8995_SYSCLK_SRC 0x0001 /* SYSCLK_SRC */ -#define WM8995_SYSCLK_SRC_MASK 0x0001 /* SYSCLK_SRC */ -#define WM8995_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC */ -#define WM8995_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */ - -/* - * R521 (0x209) - Clocking (2) - */ -#define WM8995_TOCLK_DIV_MASK 0x0700 /* TOCLK_DIV - [10:8] */ -#define WM8995_TOCLK_DIV_SHIFT 8 /* TOCLK_DIV - [10:8] */ -#define WM8995_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [10:8] */ -#define WM8995_DBCLK_DIV_MASK 0x00F0 /* DBCLK_DIV - [7:4] */ -#define WM8995_DBCLK_DIV_SHIFT 4 /* DBCLK_DIV - [7:4] */ -#define WM8995_DBCLK_DIV_WIDTH 4 /* DBCLK_DIV - [7:4] */ -#define WM8995_OPCLK_DIV_MASK 0x0007 /* OPCLK_DIV - [2:0] */ -#define WM8995_OPCLK_DIV_SHIFT 0 /* OPCLK_DIV - [2:0] */ -#define WM8995_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [2:0] */ - -/* - * R528 (0x210) - AIF1 Rate - */ -#define WM8995_AIF1_SR_MASK 0x00F0 /* AIF1_SR - [7:4] */ -#define WM8995_AIF1_SR_SHIFT 4 /* AIF1_SR - [7:4] */ -#define WM8995_AIF1_SR_WIDTH 4 /* AIF1_SR - [7:4] */ -#define WM8995_AIF1CLK_RATE_MASK 0x000F /* AIF1CLK_RATE - [3:0] */ -#define WM8995_AIF1CLK_RATE_SHIFT 0 /* AIF1CLK_RATE - [3:0] */ -#define WM8995_AIF1CLK_RATE_WIDTH 4 /* AIF1CLK_RATE - [3:0] */ - -/* - * R529 (0x211) - AIF2 Rate - */ -#define WM8995_AIF2_SR_MASK 0x00F0 /* AIF2_SR - [7:4] */ -#define WM8995_AIF2_SR_SHIFT 4 /* AIF2_SR - [7:4] */ -#define WM8995_AIF2_SR_WIDTH 4 /* AIF2_SR - [7:4] */ -#define WM8995_AIF2CLK_RATE_MASK 0x000F /* AIF2CLK_RATE - [3:0] */ -#define WM8995_AIF2CLK_RATE_SHIFT 0 /* AIF2CLK_RATE - [3:0] */ -#define WM8995_AIF2CLK_RATE_WIDTH 4 /* AIF2CLK_RATE - [3:0] */ - -/* - * R530 (0x212) - Rate Status - */ -#define WM8995_SR_ERROR_MASK 0x000F /* SR_ERROR - [3:0] */ -#define WM8995_SR_ERROR_SHIFT 0 /* SR_ERROR - [3:0] */ -#define WM8995_SR_ERROR_WIDTH 4 /* SR_ERROR - [3:0] */ - -/* - * R544 (0x220) - FLL1 Control (1) - */ -#define WM8995_FLL1_OSC_ENA 0x0002 /* FLL1_OSC_ENA */ -#define WM8995_FLL1_OSC_ENA_MASK 0x0002 /* FLL1_OSC_ENA */ -#define WM8995_FLL1_OSC_ENA_SHIFT 1 /* FLL1_OSC_ENA */ -#define WM8995_FLL1_OSC_ENA_WIDTH 1 /* FLL1_OSC_ENA */ -#define WM8995_FLL1_ENA 0x0001 /* FLL1_ENA */ -#define WM8995_FLL1_ENA_MASK 0x0001 /* FLL1_ENA */ -#define WM8995_FLL1_ENA_SHIFT 0 /* FLL1_ENA */ -#define WM8995_FLL1_ENA_WIDTH 1 /* FLL1_ENA */ - -/* - * R545 (0x221) - FLL1 Control (2) - */ -#define WM8995_FLL1_OUTDIV_MASK 0x3F00 /* FLL1_OUTDIV - [13:8] */ -#define WM8995_FLL1_OUTDIV_SHIFT 8 /* FLL1_OUTDIV - [13:8] */ -#define WM8995_FLL1_OUTDIV_WIDTH 6 /* FLL1_OUTDIV - [13:8] */ -#define WM8995_FLL1_CTRL_RATE_MASK 0x0070 /* FLL1_CTRL_RATE - [6:4] */ -#define WM8995_FLL1_CTRL_RATE_SHIFT 4 /* FLL1_CTRL_RATE - [6:4] */ -#define WM8995_FLL1_CTRL_RATE_WIDTH 3 /* FLL1_CTRL_RATE - [6:4] */ -#define WM8995_FLL1_FRATIO_MASK 0x0007 /* FLL1_FRATIO - [2:0] */ -#define WM8995_FLL1_FRATIO_SHIFT 0 /* FLL1_FRATIO - [2:0] */ -#define WM8995_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [2:0] */ - -/* - * R546 (0x222) - FLL1 Control (3) - */ -#define WM8995_FLL1_K_MASK 0xFFFF /* FLL1_K - [15:0] */ -#define WM8995_FLL1_K_SHIFT 0 /* FLL1_K - [15:0] */ -#define WM8995_FLL1_K_WIDTH 16 /* FLL1_K - [15:0] */ - -/* - * R547 (0x223) - FLL1 Control (4) - */ -#define WM8995_FLL1_N_MASK 0x7FE0 /* FLL1_N - [14:5] */ -#define WM8995_FLL1_N_SHIFT 5 /* FLL1_N - [14:5] */ -#define WM8995_FLL1_N_WIDTH 10 /* FLL1_N - [14:5] */ -#define WM8995_FLL1_LOOP_GAIN_MASK 0x000F /* FLL1_LOOP_GAIN - [3:0] */ -#define WM8995_FLL1_LOOP_GAIN_SHIFT 0 /* FLL1_LOOP_GAIN - [3:0] */ -#define WM8995_FLL1_LOOP_GAIN_WIDTH 4 /* FLL1_LOOP_GAIN - [3:0] */ - -/* - * R548 (0x224) - FLL1 Control (5) - */ -#define WM8995_FLL1_FRC_NCO_VAL_MASK 0x1F80 /* FLL1_FRC_NCO_VAL - [12:7] */ -#define WM8995_FLL1_FRC_NCO_VAL_SHIFT 7 /* FLL1_FRC_NCO_VAL - [12:7] */ -#define WM8995_FLL1_FRC_NCO_VAL_WIDTH 6 /* FLL1_FRC_NCO_VAL - [12:7] */ -#define WM8995_FLL1_FRC_NCO 0x0040 /* FLL1_FRC_NCO */ -#define WM8995_FLL1_FRC_NCO_MASK 0x0040 /* FLL1_FRC_NCO */ -#define WM8995_FLL1_FRC_NCO_SHIFT 6 /* FLL1_FRC_NCO */ -#define WM8995_FLL1_FRC_NCO_WIDTH 1 /* FLL1_FRC_NCO */ -#define WM8995_FLL1_REFCLK_DIV_MASK 0x0018 /* FLL1_REFCLK_DIV - [4:3] */ -#define WM8995_FLL1_REFCLK_DIV_SHIFT 3 /* FLL1_REFCLK_DIV - [4:3] */ -#define WM8995_FLL1_REFCLK_DIV_WIDTH 2 /* FLL1_REFCLK_DIV - [4:3] */ -#define WM8995_FLL1_REFCLK_SRC_MASK 0x0003 /* FLL1_REFCLK_SRC - [1:0] */ -#define WM8995_FLL1_REFCLK_SRC_SHIFT 0 /* FLL1_REFCLK_SRC - [1:0] */ -#define WM8995_FLL1_REFCLK_SRC_WIDTH 2 /* FLL1_REFCLK_SRC - [1:0] */ - -/* - * R576 (0x240) - FLL2 Control (1) - */ -#define WM8995_FLL2_OSC_ENA 0x0002 /* FLL2_OSC_ENA */ -#define WM8995_FLL2_OSC_ENA_MASK 0x0002 /* FLL2_OSC_ENA */ -#define WM8995_FLL2_OSC_ENA_SHIFT 1 /* FLL2_OSC_ENA */ -#define WM8995_FLL2_OSC_ENA_WIDTH 1 /* FLL2_OSC_ENA */ -#define WM8995_FLL2_ENA 0x0001 /* FLL2_ENA */ -#define WM8995_FLL2_ENA_MASK 0x0001 /* FLL2_ENA */ -#define WM8995_FLL2_ENA_SHIFT 0 /* FLL2_ENA */ -#define WM8995_FLL2_ENA_WIDTH 1 /* FLL2_ENA */ - -/* - * R577 (0x241) - FLL2 Control (2) - */ -#define WM8995_FLL2_OUTDIV_MASK 0x3F00 /* FLL2_OUTDIV - [13:8] */ -#define WM8995_FLL2_OUTDIV_SHIFT 8 /* FLL2_OUTDIV - [13:8] */ -#define WM8995_FLL2_OUTDIV_WIDTH 6 /* FLL2_OUTDIV - [13:8] */ -#define WM8995_FLL2_CTRL_RATE_MASK 0x0070 /* FLL2_CTRL_RATE - [6:4] */ -#define WM8995_FLL2_CTRL_RATE_SHIFT 4 /* FLL2_CTRL_RATE - [6:4] */ -#define WM8995_FLL2_CTRL_RATE_WIDTH 3 /* FLL2_CTRL_RATE - [6:4] */ -#define WM8995_FLL2_FRATIO_MASK 0x0007 /* FLL2_FRATIO - [2:0] */ -#define WM8995_FLL2_FRATIO_SHIFT 0 /* FLL2_FRATIO - [2:0] */ -#define WM8995_FLL2_FRATIO_WIDTH 3 /* FLL2_FRATIO - [2:0] */ - -/* - * R578 (0x242) - FLL2 Control (3) - */ -#define WM8995_FLL2_K_MASK 0xFFFF /* FLL2_K - [15:0] */ -#define WM8995_FLL2_K_SHIFT 0 /* FLL2_K - [15:0] */ -#define WM8995_FLL2_K_WIDTH 16 /* FLL2_K - [15:0] */ - -/* - * R579 (0x243) - FLL2 Control (4) - */ -#define WM8995_FLL2_N_MASK 0x7FE0 /* FLL2_N - [14:5] */ -#define WM8995_FLL2_N_SHIFT 5 /* FLL2_N - [14:5] */ -#define WM8995_FLL2_N_WIDTH 10 /* FLL2_N - [14:5] */ -#define WM8995_FLL2_LOOP_GAIN_MASK 0x000F /* FLL2_LOOP_GAIN - [3:0] */ -#define WM8995_FLL2_LOOP_GAIN_SHIFT 0 /* FLL2_LOOP_GAIN - [3:0] */ -#define WM8995_FLL2_LOOP_GAIN_WIDTH 4 /* FLL2_LOOP_GAIN - [3:0] */ - -/* - * R580 (0x244) - FLL2 Control (5) - */ -#define WM8995_FLL2_FRC_NCO_VAL_MASK 0x1F80 /* FLL2_FRC_NCO_VAL - [12:7] */ -#define WM8995_FLL2_FRC_NCO_VAL_SHIFT 7 /* FLL2_FRC_NCO_VAL - [12:7] */ -#define WM8995_FLL2_FRC_NCO_VAL_WIDTH 6 /* FLL2_FRC_NCO_VAL - [12:7] */ -#define WM8995_FLL2_FRC_NCO 0x0040 /* FLL2_FRC_NCO */ -#define WM8995_FLL2_FRC_NCO_MASK 0x0040 /* FLL2_FRC_NCO */ -#define WM8995_FLL2_FRC_NCO_SHIFT 6 /* FLL2_FRC_NCO */ -#define WM8995_FLL2_FRC_NCO_WIDTH 1 /* FLL2_FRC_NCO */ -#define WM8995_FLL2_REFCLK_DIV_MASK 0x0018 /* FLL2_REFCLK_DIV - [4:3] */ -#define WM8995_FLL2_REFCLK_DIV_SHIFT 3 /* FLL2_REFCLK_DIV - [4:3] */ -#define WM8995_FLL2_REFCLK_DIV_WIDTH 2 /* FLL2_REFCLK_DIV - [4:3] */ -#define WM8995_FLL2_REFCLK_SRC_MASK 0x0003 /* FLL2_REFCLK_SRC - [1:0] */ -#define WM8995_FLL2_REFCLK_SRC_SHIFT 0 /* FLL2_REFCLK_SRC - [1:0] */ -#define WM8995_FLL2_REFCLK_SRC_WIDTH 2 /* FLL2_REFCLK_SRC - [1:0] */ - -/* - * R768 (0x300) - AIF1 Control (1) - */ -#define WM8995_AIF1ADCL_SRC 0x8000 /* AIF1ADCL_SRC */ -#define WM8995_AIF1ADCL_SRC_MASK 0x8000 /* AIF1ADCL_SRC */ -#define WM8995_AIF1ADCL_SRC_SHIFT 15 /* AIF1ADCL_SRC */ -#define WM8995_AIF1ADCL_SRC_WIDTH 1 /* AIF1ADCL_SRC */ -#define WM8995_AIF1ADCR_SRC 0x4000 /* AIF1ADCR_SRC */ -#define WM8995_AIF1ADCR_SRC_MASK 0x4000 /* AIF1ADCR_SRC */ -#define WM8995_AIF1ADCR_SRC_SHIFT 14 /* AIF1ADCR_SRC */ -#define WM8995_AIF1ADCR_SRC_WIDTH 1 /* AIF1ADCR_SRC */ -#define WM8995_AIF1ADC_TDM 0x2000 /* AIF1ADC_TDM */ -#define WM8995_AIF1ADC_TDM_MASK 0x2000 /* AIF1ADC_TDM */ -#define WM8995_AIF1ADC_TDM_SHIFT 13 /* AIF1ADC_TDM */ -#define WM8995_AIF1ADC_TDM_WIDTH 1 /* AIF1ADC_TDM */ -#define WM8995_AIF1_BCLK_INV 0x0100 /* AIF1_BCLK_INV */ -#define WM8995_AIF1_BCLK_INV_MASK 0x0100 /* AIF1_BCLK_INV */ -#define WM8995_AIF1_BCLK_INV_SHIFT 8 /* AIF1_BCLK_INV */ -#define WM8995_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */ -#define WM8995_AIF1_LRCLK_INV 0x0080 /* AIF1_LRCLK_INV */ -#define WM8995_AIF1_LRCLK_INV_MASK 0x0080 /* AIF1_LRCLK_INV */ -#define WM8995_AIF1_LRCLK_INV_SHIFT 7 /* AIF1_LRCLK_INV */ -#define WM8995_AIF1_LRCLK_INV_WIDTH 1 /* AIF1_LRCLK_INV */ -#define WM8995_AIF1_WL_MASK 0x0060 /* AIF1_WL - [6:5] */ -#define WM8995_AIF1_WL_SHIFT 5 /* AIF1_WL - [6:5] */ -#define WM8995_AIF1_WL_WIDTH 2 /* AIF1_WL - [6:5] */ -#define WM8995_AIF1_FMT_MASK 0x0018 /* AIF1_FMT - [4:3] */ -#define WM8995_AIF1_FMT_SHIFT 3 /* AIF1_FMT - [4:3] */ -#define WM8995_AIF1_FMT_WIDTH 2 /* AIF1_FMT - [4:3] */ - -/* - * R769 (0x301) - AIF1 Control (2) - */ -#define WM8995_AIF1DACL_SRC 0x8000 /* AIF1DACL_SRC */ -#define WM8995_AIF1DACL_SRC_MASK 0x8000 /* AIF1DACL_SRC */ -#define WM8995_AIF1DACL_SRC_SHIFT 15 /* AIF1DACL_SRC */ -#define WM8995_AIF1DACL_SRC_WIDTH 1 /* AIF1DACL_SRC */ -#define WM8995_AIF1DACR_SRC 0x4000 /* AIF1DACR_SRC */ -#define WM8995_AIF1DACR_SRC_MASK 0x4000 /* AIF1DACR_SRC */ -#define WM8995_AIF1DACR_SRC_SHIFT 14 /* AIF1DACR_SRC */ -#define WM8995_AIF1DACR_SRC_WIDTH 1 /* AIF1DACR_SRC */ -#define WM8995_AIF1DAC_BOOST_MASK 0x0C00 /* AIF1DAC_BOOST - [11:10] */ -#define WM8995_AIF1DAC_BOOST_SHIFT 10 /* AIF1DAC_BOOST - [11:10] */ -#define WM8995_AIF1DAC_BOOST_WIDTH 2 /* AIF1DAC_BOOST - [11:10] */ -#define WM8995_AIF1DAC_COMP 0x0010 /* AIF1DAC_COMP */ -#define WM8995_AIF1DAC_COMP_MASK 0x0010 /* AIF1DAC_COMP */ -#define WM8995_AIF1DAC_COMP_SHIFT 4 /* AIF1DAC_COMP */ -#define WM8995_AIF1DAC_COMP_WIDTH 1 /* AIF1DAC_COMP */ -#define WM8995_AIF1DAC_COMPMODE 0x0008 /* AIF1DAC_COMPMODE */ -#define WM8995_AIF1DAC_COMPMODE_MASK 0x0008 /* AIF1DAC_COMPMODE */ -#define WM8995_AIF1DAC_COMPMODE_SHIFT 3 /* AIF1DAC_COMPMODE */ -#define WM8995_AIF1DAC_COMPMODE_WIDTH 1 /* AIF1DAC_COMPMODE */ -#define WM8995_AIF1ADC_COMP 0x0004 /* AIF1ADC_COMP */ -#define WM8995_AIF1ADC_COMP_MASK 0x0004 /* AIF1ADC_COMP */ -#define WM8995_AIF1ADC_COMP_SHIFT 2 /* AIF1ADC_COMP */ -#define WM8995_AIF1ADC_COMP_WIDTH 1 /* AIF1ADC_COMP */ -#define WM8995_AIF1ADC_COMPMODE 0x0002 /* AIF1ADC_COMPMODE */ -#define WM8995_AIF1ADC_COMPMODE_MASK 0x0002 /* AIF1ADC_COMPMODE */ -#define WM8995_AIF1ADC_COMPMODE_SHIFT 1 /* AIF1ADC_COMPMODE */ -#define WM8995_AIF1ADC_COMPMODE_WIDTH 1 /* AIF1ADC_COMPMODE */ -#define WM8995_AIF1_LOOPBACK 0x0001 /* AIF1_LOOPBACK */ -#define WM8995_AIF1_LOOPBACK_MASK 0x0001 /* AIF1_LOOPBACK */ -#define WM8995_AIF1_LOOPBACK_SHIFT 0 /* AIF1_LOOPBACK */ -#define WM8995_AIF1_LOOPBACK_WIDTH 1 /* AIF1_LOOPBACK */ - -/* - * R770 (0x302) - AIF1 Master/Slave - */ -#define WM8995_AIF1_TRI 0x8000 /* AIF1_TRI */ -#define WM8995_AIF1_TRI_MASK 0x8000 /* AIF1_TRI */ -#define WM8995_AIF1_TRI_SHIFT 15 /* AIF1_TRI */ -#define WM8995_AIF1_TRI_WIDTH 1 /* AIF1_TRI */ -#define WM8995_AIF1_MSTR 0x4000 /* AIF1_MSTR */ -#define WM8995_AIF1_MSTR_MASK 0x4000 /* AIF1_MSTR */ -#define WM8995_AIF1_MSTR_SHIFT 14 /* AIF1_MSTR */ -#define WM8995_AIF1_MSTR_WIDTH 1 /* AIF1_MSTR */ -#define WM8995_AIF1_CLK_FRC 0x2000 /* AIF1_CLK_FRC */ -#define WM8995_AIF1_CLK_FRC_MASK 0x2000 /* AIF1_CLK_FRC */ -#define WM8995_AIF1_CLK_FRC_SHIFT 13 /* AIF1_CLK_FRC */ -#define WM8995_AIF1_CLK_FRC_WIDTH 1 /* AIF1_CLK_FRC */ -#define WM8995_AIF1_LRCLK_FRC 0x1000 /* AIF1_LRCLK_FRC */ -#define WM8995_AIF1_LRCLK_FRC_MASK 0x1000 /* AIF1_LRCLK_FRC */ -#define WM8995_AIF1_LRCLK_FRC_SHIFT 12 /* AIF1_LRCLK_FRC */ -#define WM8995_AIF1_LRCLK_FRC_WIDTH 1 /* AIF1_LRCLK_FRC */ - -/* - * R771 (0x303) - AIF1 BCLK - */ -#define WM8995_AIF1_BCLK_DIV_MASK 0x00F0 /* AIF1_BCLK_DIV - [7:4] */ -#define WM8995_AIF1_BCLK_DIV_SHIFT 4 /* AIF1_BCLK_DIV - [7:4] */ -#define WM8995_AIF1_BCLK_DIV_WIDTH 4 /* AIF1_BCLK_DIV - [7:4] */ - -/* - * R772 (0x304) - AIF1ADC LRCLK - */ -#define WM8995_AIF1ADC_LRCLK_DIR 0x0800 /* AIF1ADC_LRCLK_DIR */ -#define WM8995_AIF1ADC_LRCLK_DIR_MASK 0x0800 /* AIF1ADC_LRCLK_DIR */ -#define WM8995_AIF1ADC_LRCLK_DIR_SHIFT 11 /* AIF1ADC_LRCLK_DIR */ -#define WM8995_AIF1ADC_LRCLK_DIR_WIDTH 1 /* AIF1ADC_LRCLK_DIR */ -#define WM8995_AIF1ADC_RATE_MASK 0x07FF /* AIF1ADC_RATE - [10:0] */ -#define WM8995_AIF1ADC_RATE_SHIFT 0 /* AIF1ADC_RATE - [10:0] */ -#define WM8995_AIF1ADC_RATE_WIDTH 11 /* AIF1ADC_RATE - [10:0] */ - -/* - * R773 (0x305) - AIF1DAC LRCLK - */ -#define WM8995_AIF1DAC_LRCLK_DIR 0x0800 /* AIF1DAC_LRCLK_DIR */ -#define WM8995_AIF1DAC_LRCLK_DIR_MASK 0x0800 /* AIF1DAC_LRCLK_DIR */ -#define WM8995_AIF1DAC_LRCLK_DIR_SHIFT 11 /* AIF1DAC_LRCLK_DIR */ -#define WM8995_AIF1DAC_LRCLK_DIR_WIDTH 1 /* AIF1DAC_LRCLK_DIR */ -#define WM8995_AIF1DAC_RATE_MASK 0x07FF /* AIF1DAC_RATE - [10:0] */ -#define WM8995_AIF1DAC_RATE_SHIFT 0 /* AIF1DAC_RATE - [10:0] */ -#define WM8995_AIF1DAC_RATE_WIDTH 11 /* AIF1DAC_RATE - [10:0] */ - -/* - * R774 (0x306) - AIF1DAC Data - */ -#define WM8995_AIF1DACL_DAT_INV 0x0002 /* AIF1DACL_DAT_INV */ -#define WM8995_AIF1DACL_DAT_INV_MASK 0x0002 /* AIF1DACL_DAT_INV */ -#define WM8995_AIF1DACL_DAT_INV_SHIFT 1 /* AIF1DACL_DAT_INV */ -#define WM8995_AIF1DACL_DAT_INV_WIDTH 1 /* AIF1DACL_DAT_INV */ -#define WM8995_AIF1DACR_DAT_INV 0x0001 /* AIF1DACR_DAT_INV */ -#define WM8995_AIF1DACR_DAT_INV_MASK 0x0001 /* AIF1DACR_DAT_INV */ -#define WM8995_AIF1DACR_DAT_INV_SHIFT 0 /* AIF1DACR_DAT_INV */ -#define WM8995_AIF1DACR_DAT_INV_WIDTH 1 /* AIF1DACR_DAT_INV */ - -/* - * R775 (0x307) - AIF1ADC Data - */ -#define WM8995_AIF1ADCL_DAT_INV 0x0002 /* AIF1ADCL_DAT_INV */ -#define WM8995_AIF1ADCL_DAT_INV_MASK 0x0002 /* AIF1ADCL_DAT_INV */ -#define WM8995_AIF1ADCL_DAT_INV_SHIFT 1 /* AIF1ADCL_DAT_INV */ -#define WM8995_AIF1ADCL_DAT_INV_WIDTH 1 /* AIF1ADCL_DAT_INV */ -#define WM8995_AIF1ADCR_DAT_INV 0x0001 /* AIF1ADCR_DAT_INV */ -#define WM8995_AIF1ADCR_DAT_INV_MASK 0x0001 /* AIF1ADCR_DAT_INV */ -#define WM8995_AIF1ADCR_DAT_INV_SHIFT 0 /* AIF1ADCR_DAT_INV */ -#define WM8995_AIF1ADCR_DAT_INV_WIDTH 1 /* AIF1ADCR_DAT_INV */ - -/* - * R784 (0x310) - AIF2 Control (1) - */ -#define WM8995_AIF2ADCL_SRC 0x8000 /* AIF2ADCL_SRC */ -#define WM8995_AIF2ADCL_SRC_MASK 0x8000 /* AIF2ADCL_SRC */ -#define WM8995_AIF2ADCL_SRC_SHIFT 15 /* AIF2ADCL_SRC */ -#define WM8995_AIF2ADCL_SRC_WIDTH 1 /* AIF2ADCL_SRC */ -#define WM8995_AIF2ADCR_SRC 0x4000 /* AIF2ADCR_SRC */ -#define WM8995_AIF2ADCR_SRC_MASK 0x4000 /* AIF2ADCR_SRC */ -#define WM8995_AIF2ADCR_SRC_SHIFT 14 /* AIF2ADCR_SRC */ -#define WM8995_AIF2ADCR_SRC_WIDTH 1 /* AIF2ADCR_SRC */ -#define WM8995_AIF2ADC_TDM 0x2000 /* AIF2ADC_TDM */ -#define WM8995_AIF2ADC_TDM_MASK 0x2000 /* AIF2ADC_TDM */ -#define WM8995_AIF2ADC_TDM_SHIFT 13 /* AIF2ADC_TDM */ -#define WM8995_AIF2ADC_TDM_WIDTH 1 /* AIF2ADC_TDM */ -#define WM8995_AIF2ADC_TDM_CHAN 0x1000 /* AIF2ADC_TDM_CHAN */ -#define WM8995_AIF2ADC_TDM_CHAN_MASK 0x1000 /* AIF2ADC_TDM_CHAN */ -#define WM8995_AIF2ADC_TDM_CHAN_SHIFT 12 /* AIF2ADC_TDM_CHAN */ -#define WM8995_AIF2ADC_TDM_CHAN_WIDTH 1 /* AIF2ADC_TDM_CHAN */ -#define WM8995_AIF2_BCLK_INV 0x0100 /* AIF2_BCLK_INV */ -#define WM8995_AIF2_BCLK_INV_MASK 0x0100 /* AIF2_BCLK_INV */ -#define WM8995_AIF2_BCLK_INV_SHIFT 8 /* AIF2_BCLK_INV */ -#define WM8995_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */ -#define WM8995_AIF2_LRCLK_INV 0x0080 /* AIF2_LRCLK_INV */ -#define WM8995_AIF2_LRCLK_INV_MASK 0x0080 /* AIF2_LRCLK_INV */ -#define WM8995_AIF2_LRCLK_INV_SHIFT 7 /* AIF2_LRCLK_INV */ -#define WM8995_AIF2_LRCLK_INV_WIDTH 1 /* AIF2_LRCLK_INV */ -#define WM8995_AIF2_WL_MASK 0x0060 /* AIF2_WL - [6:5] */ -#define WM8995_AIF2_WL_SHIFT 5 /* AIF2_WL - [6:5] */ -#define WM8995_AIF2_WL_WIDTH 2 /* AIF2_WL - [6:5] */ -#define WM8995_AIF2_FMT_MASK 0x0018 /* AIF2_FMT - [4:3] */ -#define WM8995_AIF2_FMT_SHIFT 3 /* AIF2_FMT - [4:3] */ -#define WM8995_AIF2_FMT_WIDTH 2 /* AIF2_FMT - [4:3] */ - -/* - * R785 (0x311) - AIF2 Control (2) - */ -#define WM8995_AIF2DACL_SRC 0x8000 /* AIF2DACL_SRC */ -#define WM8995_AIF2DACL_SRC_MASK 0x8000 /* AIF2DACL_SRC */ -#define WM8995_AIF2DACL_SRC_SHIFT 15 /* AIF2DACL_SRC */ -#define WM8995_AIF2DACL_SRC_WIDTH 1 /* AIF2DACL_SRC */ -#define WM8995_AIF2DACR_SRC 0x4000 /* AIF2DACR_SRC */ -#define WM8995_AIF2DACR_SRC_MASK 0x4000 /* AIF2DACR_SRC */ -#define WM8995_AIF2DACR_SRC_SHIFT 14 /* AIF2DACR_SRC */ -#define WM8995_AIF2DACR_SRC_WIDTH 1 /* AIF2DACR_SRC */ -#define WM8995_AIF2DAC_TDM 0x2000 /* AIF2DAC_TDM */ -#define WM8995_AIF2DAC_TDM_MASK 0x2000 /* AIF2DAC_TDM */ -#define WM8995_AIF2DAC_TDM_SHIFT 13 /* AIF2DAC_TDM */ -#define WM8995_AIF2DAC_TDM_WIDTH 1 /* AIF2DAC_TDM */ -#define WM8995_AIF2DAC_TDM_CHAN 0x1000 /* AIF2DAC_TDM_CHAN */ -#define WM8995_AIF2DAC_TDM_CHAN_MASK 0x1000 /* AIF2DAC_TDM_CHAN */ -#define WM8995_AIF2DAC_TDM_CHAN_SHIFT 12 /* AIF2DAC_TDM_CHAN */ -#define WM8995_AIF2DAC_TDM_CHAN_WIDTH 1 /* AIF2DAC_TDM_CHAN */ -#define WM8995_AIF2DAC_BOOST_MASK 0x0C00 /* AIF2DAC_BOOST - [11:10] */ -#define WM8995_AIF2DAC_BOOST_SHIFT 10 /* AIF2DAC_BOOST - [11:10] */ -#define WM8995_AIF2DAC_BOOST_WIDTH 2 /* AIF2DAC_BOOST - [11:10] */ -#define WM8995_AIF2DAC_COMP 0x0010 /* AIF2DAC_COMP */ -#define WM8995_AIF2DAC_COMP_MASK 0x0010 /* AIF2DAC_COMP */ -#define WM8995_AIF2DAC_COMP_SHIFT 4 /* AIF2DAC_COMP */ -#define WM8995_AIF2DAC_COMP_WIDTH 1 /* AIF2DAC_COMP */ -#define WM8995_AIF2DAC_COMPMODE 0x0008 /* AIF2DAC_COMPMODE */ -#define WM8995_AIF2DAC_COMPMODE_MASK 0x0008 /* AIF2DAC_COMPMODE */ -#define WM8995_AIF2DAC_COMPMODE_SHIFT 3 /* AIF2DAC_COMPMODE */ -#define WM8995_AIF2DAC_COMPMODE_WIDTH 1 /* AIF2DAC_COMPMODE */ -#define WM8995_AIF2ADC_COMP 0x0004 /* AIF2ADC_COMP */ -#define WM8995_AIF2ADC_COMP_MASK 0x0004 /* AIF2ADC_COMP */ -#define WM8995_AIF2ADC_COMP_SHIFT 2 /* AIF2ADC_COMP */ -#define WM8995_AIF2ADC_COMP_WIDTH 1 /* AIF2ADC_COMP */ -#define WM8995_AIF2ADC_COMPMODE 0x0002 /* AIF2ADC_COMPMODE */ -#define WM8995_AIF2ADC_COMPMODE_MASK 0x0002 /* AIF2ADC_COMPMODE */ -#define WM8995_AIF2ADC_COMPMODE_SHIFT 1 /* AIF2ADC_COMPMODE */ -#define WM8995_AIF2ADC_COMPMODE_WIDTH 1 /* AIF2ADC_COMPMODE */ -#define WM8995_AIF2_LOOPBACK 0x0001 /* AIF2_LOOPBACK */ -#define WM8995_AIF2_LOOPBACK_MASK 0x0001 /* AIF2_LOOPBACK */ -#define WM8995_AIF2_LOOPBACK_SHIFT 0 /* AIF2_LOOPBACK */ -#define WM8995_AIF2_LOOPBACK_WIDTH 1 /* AIF2_LOOPBACK */ - -/* - * R786 (0x312) - AIF2 Master/Slave - */ -#define WM8995_AIF2_TRI 0x8000 /* AIF2_TRI */ -#define WM8995_AIF2_TRI_MASK 0x8000 /* AIF2_TRI */ -#define WM8995_AIF2_TRI_SHIFT 15 /* AIF2_TRI */ -#define WM8995_AIF2_TRI_WIDTH 1 /* AIF2_TRI */ -#define WM8995_AIF2_MSTR 0x4000 /* AIF2_MSTR */ -#define WM8995_AIF2_MSTR_MASK 0x4000 /* AIF2_MSTR */ -#define WM8995_AIF2_MSTR_SHIFT 14 /* AIF2_MSTR */ -#define WM8995_AIF2_MSTR_WIDTH 1 /* AIF2_MSTR */ -#define WM8995_AIF2_CLK_FRC 0x2000 /* AIF2_CLK_FRC */ -#define WM8995_AIF2_CLK_FRC_MASK 0x2000 /* AIF2_CLK_FRC */ -#define WM8995_AIF2_CLK_FRC_SHIFT 13 /* AIF2_CLK_FRC */ -#define WM8995_AIF2_CLK_FRC_WIDTH 1 /* AIF2_CLK_FRC */ -#define WM8995_AIF2_LRCLK_FRC 0x1000 /* AIF2_LRCLK_FRC */ -#define WM8995_AIF2_LRCLK_FRC_MASK 0x1000 /* AIF2_LRCLK_FRC */ -#define WM8995_AIF2_LRCLK_FRC_SHIFT 12 /* AIF2_LRCLK_FRC */ -#define WM8995_AIF2_LRCLK_FRC_WIDTH 1 /* AIF2_LRCLK_FRC */ - -/* - * R787 (0x313) - AIF2 BCLK - */ -#define WM8995_AIF2_BCLK_DIV_MASK 0x00F0 /* AIF2_BCLK_DIV - [7:4] */ -#define WM8995_AIF2_BCLK_DIV_SHIFT 4 /* AIF2_BCLK_DIV - [7:4] */ -#define WM8995_AIF2_BCLK_DIV_WIDTH 4 /* AIF2_BCLK_DIV - [7:4] */ - -/* - * R788 (0x314) - AIF2ADC LRCLK - */ -#define WM8995_AIF2ADC_LRCLK_DIR 0x0800 /* AIF2ADC_LRCLK_DIR */ -#define WM8995_AIF2ADC_LRCLK_DIR_MASK 0x0800 /* AIF2ADC_LRCLK_DIR */ -#define WM8995_AIF2ADC_LRCLK_DIR_SHIFT 11 /* AIF2ADC_LRCLK_DIR */ -#define WM8995_AIF2ADC_LRCLK_DIR_WIDTH 1 /* AIF2ADC_LRCLK_DIR */ -#define WM8995_AIF2ADC_RATE_MASK 0x07FF /* AIF2ADC_RATE - [10:0] */ -#define WM8995_AIF2ADC_RATE_SHIFT 0 /* AIF2ADC_RATE - [10:0] */ -#define WM8995_AIF2ADC_RATE_WIDTH 11 /* AIF2ADC_RATE - [10:0] */ - -/* - * R789 (0x315) - AIF2DAC LRCLK - */ -#define WM8995_AIF2DAC_LRCLK_DIR 0x0800 /* AIF2DAC_LRCLK_DIR */ -#define WM8995_AIF2DAC_LRCLK_DIR_MASK 0x0800 /* AIF2DAC_LRCLK_DIR */ -#define WM8995_AIF2DAC_LRCLK_DIR_SHIFT 11 /* AIF2DAC_LRCLK_DIR */ -#define WM8995_AIF2DAC_LRCLK_DIR_WIDTH 1 /* AIF2DAC_LRCLK_DIR */ -#define WM8995_AIF2DAC_RATE_MASK 0x07FF /* AIF2DAC_RATE - [10:0] */ -#define WM8995_AIF2DAC_RATE_SHIFT 0 /* AIF2DAC_RATE - [10:0] */ -#define WM8995_AIF2DAC_RATE_WIDTH 11 /* AIF2DAC_RATE - [10:0] */ - -/* - * R790 (0x316) - AIF2DAC Data - */ -#define WM8995_AIF2DACL_DAT_INV 0x0002 /* AIF2DACL_DAT_INV */ -#define WM8995_AIF2DACL_DAT_INV_MASK 0x0002 /* AIF2DACL_DAT_INV */ -#define WM8995_AIF2DACL_DAT_INV_SHIFT 1 /* AIF2DACL_DAT_INV */ -#define WM8995_AIF2DACL_DAT_INV_WIDTH 1 /* AIF2DACL_DAT_INV */ -#define WM8995_AIF2DACR_DAT_INV 0x0001 /* AIF2DACR_DAT_INV */ -#define WM8995_AIF2DACR_DAT_INV_MASK 0x0001 /* AIF2DACR_DAT_INV */ -#define WM8995_AIF2DACR_DAT_INV_SHIFT 0 /* AIF2DACR_DAT_INV */ -#define WM8995_AIF2DACR_DAT_INV_WIDTH 1 /* AIF2DACR_DAT_INV */ - -/* - * R791 (0x317) - AIF2ADC Data - */ -#define WM8995_AIF2ADCL_DAT_INV 0x0002 /* AIF2ADCL_DAT_INV */ -#define WM8995_AIF2ADCL_DAT_INV_MASK 0x0002 /* AIF2ADCL_DAT_INV */ -#define WM8995_AIF2ADCL_DAT_INV_SHIFT 1 /* AIF2ADCL_DAT_INV */ -#define WM8995_AIF2ADCL_DAT_INV_WIDTH 1 /* AIF2ADCL_DAT_INV */ -#define WM8995_AIF2ADCR_DAT_INV 0x0001 /* AIF2ADCR_DAT_INV */ -#define WM8995_AIF2ADCR_DAT_INV_MASK 0x0001 /* AIF2ADCR_DAT_INV */ -#define WM8995_AIF2ADCR_DAT_INV_SHIFT 0 /* AIF2ADCR_DAT_INV */ -#define WM8995_AIF2ADCR_DAT_INV_WIDTH 1 /* AIF2ADCR_DAT_INV */ - -/* - * R1024 (0x400) - AIF1 ADC1 Left Volume - */ -#define WM8995_AIF1ADC1_VU 0x0100 /* AIF1ADC1_VU */ -#define WM8995_AIF1ADC1_VU_MASK 0x0100 /* AIF1ADC1_VU */ -#define WM8995_AIF1ADC1_VU_SHIFT 8 /* AIF1ADC1_VU */ -#define WM8995_AIF1ADC1_VU_WIDTH 1 /* AIF1ADC1_VU */ -#define WM8995_AIF1ADC1L_VOL_MASK 0x00FF /* AIF1ADC1L_VOL - [7:0] */ -#define WM8995_AIF1ADC1L_VOL_SHIFT 0 /* AIF1ADC1L_VOL - [7:0] */ -#define WM8995_AIF1ADC1L_VOL_WIDTH 8 /* AIF1ADC1L_VOL - [7:0] */ - -/* - * R1025 (0x401) - AIF1 ADC1 Right Volume - */ -#define WM8995_AIF1ADC1_VU 0x0100 /* AIF1ADC1_VU */ -#define WM8995_AIF1ADC1_VU_MASK 0x0100 /* AIF1ADC1_VU */ -#define WM8995_AIF1ADC1_VU_SHIFT 8 /* AIF1ADC1_VU */ -#define WM8995_AIF1ADC1_VU_WIDTH 1 /* AIF1ADC1_VU */ -#define WM8995_AIF1ADC1R_VOL_MASK 0x00FF /* AIF1ADC1R_VOL - [7:0] */ -#define WM8995_AIF1ADC1R_VOL_SHIFT 0 /* AIF1ADC1R_VOL - [7:0] */ -#define WM8995_AIF1ADC1R_VOL_WIDTH 8 /* AIF1ADC1R_VOL - [7:0] */ - -/* - * R1026 (0x402) - AIF1 DAC1 Left Volume - */ -#define WM8995_AIF1DAC1_VU 0x0100 /* AIF1DAC1_VU */ -#define WM8995_AIF1DAC1_VU_MASK 0x0100 /* AIF1DAC1_VU */ -#define WM8995_AIF1DAC1_VU_SHIFT 8 /* AIF1DAC1_VU */ -#define WM8995_AIF1DAC1_VU_WIDTH 1 /* AIF1DAC1_VU */ -#define WM8995_AIF1DAC1L_VOL_MASK 0x00FF /* AIF1DAC1L_VOL - [7:0] */ -#define WM8995_AIF1DAC1L_VOL_SHIFT 0 /* AIF1DAC1L_VOL - [7:0] */ -#define WM8995_AIF1DAC1L_VOL_WIDTH 8 /* AIF1DAC1L_VOL - [7:0] */ - -/* - * R1027 (0x403) - AIF1 DAC1 Right Volume - */ -#define WM8995_AIF1DAC1_VU 0x0100 /* AIF1DAC1_VU */ -#define WM8995_AIF1DAC1_VU_MASK 0x0100 /* AIF1DAC1_VU */ -#define WM8995_AIF1DAC1_VU_SHIFT 8 /* AIF1DAC1_VU */ -#define WM8995_AIF1DAC1_VU_WIDTH 1 /* AIF1DAC1_VU */ -#define WM8995_AIF1DAC1R_VOL_MASK 0x00FF /* AIF1DAC1R_VOL - [7:0] */ -#define WM8995_AIF1DAC1R_VOL_SHIFT 0 /* AIF1DAC1R_VOL - [7:0] */ -#define WM8995_AIF1DAC1R_VOL_WIDTH 8 /* AIF1DAC1R_VOL - [7:0] */ - -/* - * R1028 (0x404) - AIF1 ADC2 Left Volume - */ -#define WM8995_AIF1ADC2_VU 0x0100 /* AIF1ADC2_VU */ -#define WM8995_AIF1ADC2_VU_MASK 0x0100 /* AIF1ADC2_VU */ -#define WM8995_AIF1ADC2_VU_SHIFT 8 /* AIF1ADC2_VU */ -#define WM8995_AIF1ADC2_VU_WIDTH 1 /* AIF1ADC2_VU */ -#define WM8995_AIF1ADC2L_VOL_MASK 0x00FF /* AIF1ADC2L_VOL - [7:0] */ -#define WM8995_AIF1ADC2L_VOL_SHIFT 0 /* AIF1ADC2L_VOL - [7:0] */ -#define WM8995_AIF1ADC2L_VOL_WIDTH 8 /* AIF1ADC2L_VOL - [7:0] */ - -/* - * R1029 (0x405) - AIF1 ADC2 Right Volume - */ -#define WM8995_AIF1ADC2_VU 0x0100 /* AIF1ADC2_VU */ -#define WM8995_AIF1ADC2_VU_MASK 0x0100 /* AIF1ADC2_VU */ -#define WM8995_AIF1ADC2_VU_SHIFT 8 /* AIF1ADC2_VU */ -#define WM8995_AIF1ADC2_VU_WIDTH 1 /* AIF1ADC2_VU */ -#define WM8995_AIF1ADC2R_VOL_MASK 0x00FF /* AIF1ADC2R_VOL - [7:0] */ -#define WM8995_AIF1ADC2R_VOL_SHIFT 0 /* AIF1ADC2R_VOL - [7:0] */ -#define WM8995_AIF1ADC2R_VOL_WIDTH 8 /* AIF1ADC2R_VOL - [7:0] */ - -/* - * R1030 (0x406) - AIF1 DAC2 Left Volume - */ -#define WM8995_AIF1DAC2_VU 0x0100 /* AIF1DAC2_VU */ -#define WM8995_AIF1DAC2_VU_MASK 0x0100 /* AIF1DAC2_VU */ -#define WM8995_AIF1DAC2_VU_SHIFT 8 /* AIF1DAC2_VU */ -#define WM8995_AIF1DAC2_VU_WIDTH 1 /* AIF1DAC2_VU */ -#define WM8995_AIF1DAC2L_VOL_MASK 0x00FF /* AIF1DAC2L_VOL - [7:0] */ -#define WM8995_AIF1DAC2L_VOL_SHIFT 0 /* AIF1DAC2L_VOL - [7:0] */ -#define WM8995_AIF1DAC2L_VOL_WIDTH 8 /* AIF1DAC2L_VOL - [7:0] */ - -/* - * R1031 (0x407) - AIF1 DAC2 Right Volume - */ -#define WM8995_AIF1DAC2_VU 0x0100 /* AIF1DAC2_VU */ -#define WM8995_AIF1DAC2_VU_MASK 0x0100 /* AIF1DAC2_VU */ -#define WM8995_AIF1DAC2_VU_SHIFT 8 /* AIF1DAC2_VU */ -#define WM8995_AIF1DAC2_VU_WIDTH 1 /* AIF1DAC2_VU */ -#define WM8995_AIF1DAC2R_VOL_MASK 0x00FF /* AIF1DAC2R_VOL - [7:0] */ -#define WM8995_AIF1DAC2R_VOL_SHIFT 0 /* AIF1DAC2R_VOL - [7:0] */ -#define WM8995_AIF1DAC2R_VOL_WIDTH 8 /* AIF1DAC2R_VOL - [7:0] */ - -/* - * R1040 (0x410) - AIF1 ADC1 Filters - */ -#define WM8995_AIF1ADC_4FS 0x8000 /* AIF1ADC_4FS */ -#define WM8995_AIF1ADC_4FS_MASK 0x8000 /* AIF1ADC_4FS */ -#define WM8995_AIF1ADC_4FS_SHIFT 15 /* AIF1ADC_4FS */ -#define WM8995_AIF1ADC_4FS_WIDTH 1 /* AIF1ADC_4FS */ -#define WM8995_AIF1ADC1L_HPF 0x1000 /* AIF1ADC1L_HPF */ -#define WM8995_AIF1ADC1L_HPF_MASK 0x1000 /* AIF1ADC1L_HPF */ -#define WM8995_AIF1ADC1L_HPF_SHIFT 12 /* AIF1ADC1L_HPF */ -#define WM8995_AIF1ADC1L_HPF_WIDTH 1 /* AIF1ADC1L_HPF */ -#define WM8995_AIF1ADC1R_HPF 0x0800 /* AIF1ADC1R_HPF */ -#define WM8995_AIF1ADC1R_HPF_MASK 0x0800 /* AIF1ADC1R_HPF */ -#define WM8995_AIF1ADC1R_HPF_SHIFT 11 /* AIF1ADC1R_HPF */ -#define WM8995_AIF1ADC1R_HPF_WIDTH 1 /* AIF1ADC1R_HPF */ -#define WM8995_AIF1ADC1_HPF_MODE 0x0008 /* AIF1ADC1_HPF_MODE */ -#define WM8995_AIF1ADC1_HPF_MODE_MASK 0x0008 /* AIF1ADC1_HPF_MODE */ -#define WM8995_AIF1ADC1_HPF_MODE_SHIFT 3 /* AIF1ADC1_HPF_MODE */ -#define WM8995_AIF1ADC1_HPF_MODE_WIDTH 1 /* AIF1ADC1_HPF_MODE */ -#define WM8995_AIF1ADC1_HPF_CUT_MASK 0x0007 /* AIF1ADC1_HPF_CUT - [2:0] */ -#define WM8995_AIF1ADC1_HPF_CUT_SHIFT 0 /* AIF1ADC1_HPF_CUT - [2:0] */ -#define WM8995_AIF1ADC1_HPF_CUT_WIDTH 3 /* AIF1ADC1_HPF_CUT - [2:0] */ - -/* - * R1041 (0x411) - AIF1 ADC2 Filters - */ -#define WM8995_AIF1ADC2L_HPF 0x1000 /* AIF1ADC2L_HPF */ -#define WM8995_AIF1ADC2L_HPF_MASK 0x1000 /* AIF1ADC2L_HPF */ -#define WM8995_AIF1ADC2L_HPF_SHIFT 12 /* AIF1ADC2L_HPF */ -#define WM8995_AIF1ADC2L_HPF_WIDTH 1 /* AIF1ADC2L_HPF */ -#define WM8995_AIF1ADC2R_HPF 0x0800 /* AIF1ADC2R_HPF */ -#define WM8995_AIF1ADC2R_HPF_MASK 0x0800 /* AIF1ADC2R_HPF */ -#define WM8995_AIF1ADC2R_HPF_SHIFT 11 /* AIF1ADC2R_HPF */ -#define WM8995_AIF1ADC2R_HPF_WIDTH 1 /* AIF1ADC2R_HPF */ -#define WM8995_AIF1ADC2_HPF_MODE 0x0008 /* AIF1ADC2_HPF_MODE */ -#define WM8995_AIF1ADC2_HPF_MODE_MASK 0x0008 /* AIF1ADC2_HPF_MODE */ -#define WM8995_AIF1ADC2_HPF_MODE_SHIFT 3 /* AIF1ADC2_HPF_MODE */ -#define WM8995_AIF1ADC2_HPF_MODE_WIDTH 1 /* AIF1ADC2_HPF_MODE */ -#define WM8995_AIF1ADC2_HPF_CUT_MASK 0x0007 /* AIF1ADC2_HPF_CUT - [2:0] */ -#define WM8995_AIF1ADC2_HPF_CUT_SHIFT 0 /* AIF1ADC2_HPF_CUT - [2:0] */ -#define WM8995_AIF1ADC2_HPF_CUT_WIDTH 3 /* AIF1ADC2_HPF_CUT - [2:0] */ - -/* - * R1056 (0x420) - AIF1 DAC1 Filters (1) - */ -#define WM8995_AIF1DAC1_MUTE 0x0200 /* AIF1DAC1_MUTE */ -#define WM8995_AIF1DAC1_MUTE_MASK 0x0200 /* AIF1DAC1_MUTE */ -#define WM8995_AIF1DAC1_MUTE_SHIFT 9 /* AIF1DAC1_MUTE */ -#define WM8995_AIF1DAC1_MUTE_WIDTH 1 /* AIF1DAC1_MUTE */ -#define WM8995_AIF1DAC1_MONO 0x0080 /* AIF1DAC1_MONO */ -#define WM8995_AIF1DAC1_MONO_MASK 0x0080 /* AIF1DAC1_MONO */ -#define WM8995_AIF1DAC1_MONO_SHIFT 7 /* AIF1DAC1_MONO */ -#define WM8995_AIF1DAC1_MONO_WIDTH 1 /* AIF1DAC1_MONO */ -#define WM8995_AIF1DAC1_MUTERATE 0x0020 /* AIF1DAC1_MUTERATE */ -#define WM8995_AIF1DAC1_MUTERATE_MASK 0x0020 /* AIF1DAC1_MUTERATE */ -#define WM8995_AIF1DAC1_MUTERATE_SHIFT 5 /* AIF1DAC1_MUTERATE */ -#define WM8995_AIF1DAC1_MUTERATE_WIDTH 1 /* AIF1DAC1_MUTERATE */ -#define WM8995_AIF1DAC1_UNMUTE_RAMP 0x0010 /* AIF1DAC1_UNMUTE_RAMP */ -#define WM8995_AIF1DAC1_UNMUTE_RAMP_MASK 0x0010 /* AIF1DAC1_UNMUTE_RAMP */ -#define WM8995_AIF1DAC1_UNMUTE_RAMP_SHIFT 4 /* AIF1DAC1_UNMUTE_RAMP */ -#define WM8995_AIF1DAC1_UNMUTE_RAMP_WIDTH 1 /* AIF1DAC1_UNMUTE_RAMP */ -#define WM8995_AIF1DAC1_DEEMP_MASK 0x0006 /* AIF1DAC1_DEEMP - [2:1] */ -#define WM8995_AIF1DAC1_DEEMP_SHIFT 1 /* AIF1DAC1_DEEMP - [2:1] */ -#define WM8995_AIF1DAC1_DEEMP_WIDTH 2 /* AIF1DAC1_DEEMP - [2:1] */ - -/* - * R1057 (0x421) - AIF1 DAC1 Filters (2) - */ -#define WM8995_AIF1DAC1_3D_GAIN_MASK 0x3E00 /* AIF1DAC1_3D_GAIN - [13:9] */ -#define WM8995_AIF1DAC1_3D_GAIN_SHIFT 9 /* AIF1DAC1_3D_GAIN - [13:9] */ -#define WM8995_AIF1DAC1_3D_GAIN_WIDTH 5 /* AIF1DAC1_3D_GAIN - [13:9] */ -#define WM8995_AIF1DAC1_3D_ENA 0x0100 /* AIF1DAC1_3D_ENA */ -#define WM8995_AIF1DAC1_3D_ENA_MASK 0x0100 /* AIF1DAC1_3D_ENA */ -#define WM8995_AIF1DAC1_3D_ENA_SHIFT 8 /* AIF1DAC1_3D_ENA */ -#define WM8995_AIF1DAC1_3D_ENA_WIDTH 1 /* AIF1DAC1_3D_ENA */ - -/* - * R1058 (0x422) - AIF1 DAC2 Filters (1) - */ -#define WM8995_AIF1DAC2_MUTE 0x0200 /* AIF1DAC2_MUTE */ -#define WM8995_AIF1DAC2_MUTE_MASK 0x0200 /* AIF1DAC2_MUTE */ -#define WM8995_AIF1DAC2_MUTE_SHIFT 9 /* AIF1DAC2_MUTE */ -#define WM8995_AIF1DAC2_MUTE_WIDTH 1 /* AIF1DAC2_MUTE */ -#define WM8995_AIF1DAC2_MONO 0x0080 /* AIF1DAC2_MONO */ -#define WM8995_AIF1DAC2_MONO_MASK 0x0080 /* AIF1DAC2_MONO */ -#define WM8995_AIF1DAC2_MONO_SHIFT 7 /* AIF1DAC2_MONO */ -#define WM8995_AIF1DAC2_MONO_WIDTH 1 /* AIF1DAC2_MONO */ -#define WM8995_AIF1DAC2_MUTERATE 0x0020 /* AIF1DAC2_MUTERATE */ -#define WM8995_AIF1DAC2_MUTERATE_MASK 0x0020 /* AIF1DAC2_MUTERATE */ -#define WM8995_AIF1DAC2_MUTERATE_SHIFT 5 /* AIF1DAC2_MUTERATE */ -#define WM8995_AIF1DAC2_MUTERATE_WIDTH 1 /* AIF1DAC2_MUTERATE */ -#define WM8995_AIF1DAC2_UNMUTE_RAMP 0x0010 /* AIF1DAC2_UNMUTE_RAMP */ -#define WM8995_AIF1DAC2_UNMUTE_RAMP_MASK 0x0010 /* AIF1DAC2_UNMUTE_RAMP */ -#define WM8995_AIF1DAC2_UNMUTE_RAMP_SHIFT 4 /* AIF1DAC2_UNMUTE_RAMP */ -#define WM8995_AIF1DAC2_UNMUTE_RAMP_WIDTH 1 /* AIF1DAC2_UNMUTE_RAMP */ -#define WM8995_AIF1DAC2_DEEMP_MASK 0x0006 /* AIF1DAC2_DEEMP - [2:1] */ -#define WM8995_AIF1DAC2_DEEMP_SHIFT 1 /* AIF1DAC2_DEEMP - [2:1] */ -#define WM8995_AIF1DAC2_DEEMP_WIDTH 2 /* AIF1DAC2_DEEMP - [2:1] */ - -/* - * R1059 (0x423) - AIF1 DAC2 Filters (2) - */ -#define WM8995_AIF1DAC2_3D_GAIN_MASK 0x3E00 /* AIF1DAC2_3D_GAIN - [13:9] */ -#define WM8995_AIF1DAC2_3D_GAIN_SHIFT 9 /* AIF1DAC2_3D_GAIN - [13:9] */ -#define WM8995_AIF1DAC2_3D_GAIN_WIDTH 5 /* AIF1DAC2_3D_GAIN - [13:9] */ -#define WM8995_AIF1DAC2_3D_ENA 0x0100 /* AIF1DAC2_3D_ENA */ -#define WM8995_AIF1DAC2_3D_ENA_MASK 0x0100 /* AIF1DAC2_3D_ENA */ -#define WM8995_AIF1DAC2_3D_ENA_SHIFT 8 /* AIF1DAC2_3D_ENA */ -#define WM8995_AIF1DAC2_3D_ENA_WIDTH 1 /* AIF1DAC2_3D_ENA */ - -/* - * R1088 (0x440) - AIF1 DRC1 (1) - */ -#define WM8995_AIF1DRC1_SIG_DET_RMS_MASK 0xF800 /* AIF1DRC1_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF1DRC1_SIG_DET_RMS_SHIFT 11 /* AIF1DRC1_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF1DRC1_SIG_DET_RMS_WIDTH 5 /* AIF1DRC1_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF1DRC1_SIG_DET_PK_MASK 0x0600 /* AIF1DRC1_SIG_DET_PK - [10:9] */ -#define WM8995_AIF1DRC1_SIG_DET_PK_SHIFT 9 /* AIF1DRC1_SIG_DET_PK - [10:9] */ -#define WM8995_AIF1DRC1_SIG_DET_PK_WIDTH 2 /* AIF1DRC1_SIG_DET_PK - [10:9] */ -#define WM8995_AIF1DRC1_NG_ENA 0x0100 /* AIF1DRC1_NG_ENA */ -#define WM8995_AIF1DRC1_NG_ENA_MASK 0x0100 /* AIF1DRC1_NG_ENA */ -#define WM8995_AIF1DRC1_NG_ENA_SHIFT 8 /* AIF1DRC1_NG_ENA */ -#define WM8995_AIF1DRC1_NG_ENA_WIDTH 1 /* AIF1DRC1_NG_ENA */ -#define WM8995_AIF1DRC1_SIG_DET_MODE 0x0080 /* AIF1DRC1_SIG_DET_MODE */ -#define WM8995_AIF1DRC1_SIG_DET_MODE_MASK 0x0080 /* AIF1DRC1_SIG_DET_MODE */ -#define WM8995_AIF1DRC1_SIG_DET_MODE_SHIFT 7 /* AIF1DRC1_SIG_DET_MODE */ -#define WM8995_AIF1DRC1_SIG_DET_MODE_WIDTH 1 /* AIF1DRC1_SIG_DET_MODE */ -#define WM8995_AIF1DRC1_SIG_DET 0x0040 /* AIF1DRC1_SIG_DET */ -#define WM8995_AIF1DRC1_SIG_DET_MASK 0x0040 /* AIF1DRC1_SIG_DET */ -#define WM8995_AIF1DRC1_SIG_DET_SHIFT 6 /* AIF1DRC1_SIG_DET */ -#define WM8995_AIF1DRC1_SIG_DET_WIDTH 1 /* AIF1DRC1_SIG_DET */ -#define WM8995_AIF1DRC1_KNEE2_OP_ENA 0x0020 /* AIF1DRC1_KNEE2_OP_ENA */ -#define WM8995_AIF1DRC1_KNEE2_OP_ENA_MASK 0x0020 /* AIF1DRC1_KNEE2_OP_ENA */ -#define WM8995_AIF1DRC1_KNEE2_OP_ENA_SHIFT 5 /* AIF1DRC1_KNEE2_OP_ENA */ -#define WM8995_AIF1DRC1_KNEE2_OP_ENA_WIDTH 1 /* AIF1DRC1_KNEE2_OP_ENA */ -#define WM8995_AIF1DRC1_QR 0x0010 /* AIF1DRC1_QR */ -#define WM8995_AIF1DRC1_QR_MASK 0x0010 /* AIF1DRC1_QR */ -#define WM8995_AIF1DRC1_QR_SHIFT 4 /* AIF1DRC1_QR */ -#define WM8995_AIF1DRC1_QR_WIDTH 1 /* AIF1DRC1_QR */ -#define WM8995_AIF1DRC1_ANTICLIP 0x0008 /* AIF1DRC1_ANTICLIP */ -#define WM8995_AIF1DRC1_ANTICLIP_MASK 0x0008 /* AIF1DRC1_ANTICLIP */ -#define WM8995_AIF1DRC1_ANTICLIP_SHIFT 3 /* AIF1DRC1_ANTICLIP */ -#define WM8995_AIF1DRC1_ANTICLIP_WIDTH 1 /* AIF1DRC1_ANTICLIP */ -#define WM8995_AIF1DAC1_DRC_ENA 0x0004 /* AIF1DAC1_DRC_ENA */ -#define WM8995_AIF1DAC1_DRC_ENA_MASK 0x0004 /* AIF1DAC1_DRC_ENA */ -#define WM8995_AIF1DAC1_DRC_ENA_SHIFT 2 /* AIF1DAC1_DRC_ENA */ -#define WM8995_AIF1DAC1_DRC_ENA_WIDTH 1 /* AIF1DAC1_DRC_ENA */ -#define WM8995_AIF1ADC1L_DRC_ENA 0x0002 /* AIF1ADC1L_DRC_ENA */ -#define WM8995_AIF1ADC1L_DRC_ENA_MASK 0x0002 /* AIF1ADC1L_DRC_ENA */ -#define WM8995_AIF1ADC1L_DRC_ENA_SHIFT 1 /* AIF1ADC1L_DRC_ENA */ -#define WM8995_AIF1ADC1L_DRC_ENA_WIDTH 1 /* AIF1ADC1L_DRC_ENA */ -#define WM8995_AIF1ADC1R_DRC_ENA 0x0001 /* AIF1ADC1R_DRC_ENA */ -#define WM8995_AIF1ADC1R_DRC_ENA_MASK 0x0001 /* AIF1ADC1R_DRC_ENA */ -#define WM8995_AIF1ADC1R_DRC_ENA_SHIFT 0 /* AIF1ADC1R_DRC_ENA */ -#define WM8995_AIF1ADC1R_DRC_ENA_WIDTH 1 /* AIF1ADC1R_DRC_ENA */ - -/* - * R1089 (0x441) - AIF1 DRC1 (2) - */ -#define WM8995_AIF1DRC1_ATK_MASK 0x1E00 /* AIF1DRC1_ATK - [12:9] */ -#define WM8995_AIF1DRC1_ATK_SHIFT 9 /* AIF1DRC1_ATK - [12:9] */ -#define WM8995_AIF1DRC1_ATK_WIDTH 4 /* AIF1DRC1_ATK - [12:9] */ -#define WM8995_AIF1DRC1_DCY_MASK 0x01E0 /* AIF1DRC1_DCY - [8:5] */ -#define WM8995_AIF1DRC1_DCY_SHIFT 5 /* AIF1DRC1_DCY - [8:5] */ -#define WM8995_AIF1DRC1_DCY_WIDTH 4 /* AIF1DRC1_DCY - [8:5] */ -#define WM8995_AIF1DRC1_MINGAIN_MASK 0x001C /* AIF1DRC1_MINGAIN - [4:2] */ -#define WM8995_AIF1DRC1_MINGAIN_SHIFT 2 /* AIF1DRC1_MINGAIN - [4:2] */ -#define WM8995_AIF1DRC1_MINGAIN_WIDTH 3 /* AIF1DRC1_MINGAIN - [4:2] */ -#define WM8995_AIF1DRC1_MAXGAIN_MASK 0x0003 /* AIF1DRC1_MAXGAIN - [1:0] */ -#define WM8995_AIF1DRC1_MAXGAIN_SHIFT 0 /* AIF1DRC1_MAXGAIN - [1:0] */ -#define WM8995_AIF1DRC1_MAXGAIN_WIDTH 2 /* AIF1DRC1_MAXGAIN - [1:0] */ - -/* - * R1090 (0x442) - AIF1 DRC1 (3) - */ -#define WM8995_AIF1DRC1_NG_MINGAIN_MASK 0xF000 /* AIF1DRC1_NG_MINGAIN - [15:12] */ -#define WM8995_AIF1DRC1_NG_MINGAIN_SHIFT 12 /* AIF1DRC1_NG_MINGAIN - [15:12] */ -#define WM8995_AIF1DRC1_NG_MINGAIN_WIDTH 4 /* AIF1DRC1_NG_MINGAIN - [15:12] */ -#define WM8995_AIF1DRC1_NG_EXP_MASK 0x0C00 /* AIF1DRC1_NG_EXP - [11:10] */ -#define WM8995_AIF1DRC1_NG_EXP_SHIFT 10 /* AIF1DRC1_NG_EXP - [11:10] */ -#define WM8995_AIF1DRC1_NG_EXP_WIDTH 2 /* AIF1DRC1_NG_EXP - [11:10] */ -#define WM8995_AIF1DRC1_QR_THR_MASK 0x0300 /* AIF1DRC1_QR_THR - [9:8] */ -#define WM8995_AIF1DRC1_QR_THR_SHIFT 8 /* AIF1DRC1_QR_THR - [9:8] */ -#define WM8995_AIF1DRC1_QR_THR_WIDTH 2 /* AIF1DRC1_QR_THR - [9:8] */ -#define WM8995_AIF1DRC1_QR_DCY_MASK 0x00C0 /* AIF1DRC1_QR_DCY - [7:6] */ -#define WM8995_AIF1DRC1_QR_DCY_SHIFT 6 /* AIF1DRC1_QR_DCY - [7:6] */ -#define WM8995_AIF1DRC1_QR_DCY_WIDTH 2 /* AIF1DRC1_QR_DCY - [7:6] */ -#define WM8995_AIF1DRC1_HI_COMP_MASK 0x0038 /* AIF1DRC1_HI_COMP - [5:3] */ -#define WM8995_AIF1DRC1_HI_COMP_SHIFT 3 /* AIF1DRC1_HI_COMP - [5:3] */ -#define WM8995_AIF1DRC1_HI_COMP_WIDTH 3 /* AIF1DRC1_HI_COMP - [5:3] */ -#define WM8995_AIF1DRC1_LO_COMP_MASK 0x0007 /* AIF1DRC1_LO_COMP - [2:0] */ -#define WM8995_AIF1DRC1_LO_COMP_SHIFT 0 /* AIF1DRC1_LO_COMP - [2:0] */ -#define WM8995_AIF1DRC1_LO_COMP_WIDTH 3 /* AIF1DRC1_LO_COMP - [2:0] */ - -/* - * R1091 (0x443) - AIF1 DRC1 (4) - */ -#define WM8995_AIF1DRC1_KNEE_IP_MASK 0x07E0 /* AIF1DRC1_KNEE_IP - [10:5] */ -#define WM8995_AIF1DRC1_KNEE_IP_SHIFT 5 /* AIF1DRC1_KNEE_IP - [10:5] */ -#define WM8995_AIF1DRC1_KNEE_IP_WIDTH 6 /* AIF1DRC1_KNEE_IP - [10:5] */ -#define WM8995_AIF1DRC1_KNEE_OP_MASK 0x001F /* AIF1DRC1_KNEE_OP - [4:0] */ -#define WM8995_AIF1DRC1_KNEE_OP_SHIFT 0 /* AIF1DRC1_KNEE_OP - [4:0] */ -#define WM8995_AIF1DRC1_KNEE_OP_WIDTH 5 /* AIF1DRC1_KNEE_OP - [4:0] */ - -/* - * R1092 (0x444) - AIF1 DRC1 (5) - */ -#define WM8995_AIF1DRC1_KNEE2_IP_MASK 0x03E0 /* AIF1DRC1_KNEE2_IP - [9:5] */ -#define WM8995_AIF1DRC1_KNEE2_IP_SHIFT 5 /* AIF1DRC1_KNEE2_IP - [9:5] */ -#define WM8995_AIF1DRC1_KNEE2_IP_WIDTH 5 /* AIF1DRC1_KNEE2_IP - [9:5] */ -#define WM8995_AIF1DRC1_KNEE2_OP_MASK 0x001F /* AIF1DRC1_KNEE2_OP - [4:0] */ -#define WM8995_AIF1DRC1_KNEE2_OP_SHIFT 0 /* AIF1DRC1_KNEE2_OP - [4:0] */ -#define WM8995_AIF1DRC1_KNEE2_OP_WIDTH 5 /* AIF1DRC1_KNEE2_OP - [4:0] */ - -/* - * R1104 (0x450) - AIF1 DRC2 (1) - */ -#define WM8995_AIF1DRC2_SIG_DET_RMS_MASK 0xF800 /* AIF1DRC2_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF1DRC2_SIG_DET_RMS_SHIFT 11 /* AIF1DRC2_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF1DRC2_SIG_DET_RMS_WIDTH 5 /* AIF1DRC2_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF1DRC2_SIG_DET_PK_MASK 0x0600 /* AIF1DRC2_SIG_DET_PK - [10:9] */ -#define WM8995_AIF1DRC2_SIG_DET_PK_SHIFT 9 /* AIF1DRC2_SIG_DET_PK - [10:9] */ -#define WM8995_AIF1DRC2_SIG_DET_PK_WIDTH 2 /* AIF1DRC2_SIG_DET_PK - [10:9] */ -#define WM8995_AIF1DRC2_NG_ENA 0x0100 /* AIF1DRC2_NG_ENA */ -#define WM8995_AIF1DRC2_NG_ENA_MASK 0x0100 /* AIF1DRC2_NG_ENA */ -#define WM8995_AIF1DRC2_NG_ENA_SHIFT 8 /* AIF1DRC2_NG_ENA */ -#define WM8995_AIF1DRC2_NG_ENA_WIDTH 1 /* AIF1DRC2_NG_ENA */ -#define WM8995_AIF1DRC2_SIG_DET_MODE 0x0080 /* AIF1DRC2_SIG_DET_MODE */ -#define WM8995_AIF1DRC2_SIG_DET_MODE_MASK 0x0080 /* AIF1DRC2_SIG_DET_MODE */ -#define WM8995_AIF1DRC2_SIG_DET_MODE_SHIFT 7 /* AIF1DRC2_SIG_DET_MODE */ -#define WM8995_AIF1DRC2_SIG_DET_MODE_WIDTH 1 /* AIF1DRC2_SIG_DET_MODE */ -#define WM8995_AIF1DRC2_SIG_DET 0x0040 /* AIF1DRC2_SIG_DET */ -#define WM8995_AIF1DRC2_SIG_DET_MASK 0x0040 /* AIF1DRC2_SIG_DET */ -#define WM8995_AIF1DRC2_SIG_DET_SHIFT 6 /* AIF1DRC2_SIG_DET */ -#define WM8995_AIF1DRC2_SIG_DET_WIDTH 1 /* AIF1DRC2_SIG_DET */ -#define WM8995_AIF1DRC2_KNEE2_OP_ENA 0x0020 /* AIF1DRC2_KNEE2_OP_ENA */ -#define WM8995_AIF1DRC2_KNEE2_OP_ENA_MASK 0x0020 /* AIF1DRC2_KNEE2_OP_ENA */ -#define WM8995_AIF1DRC2_KNEE2_OP_ENA_SHIFT 5 /* AIF1DRC2_KNEE2_OP_ENA */ -#define WM8995_AIF1DRC2_KNEE2_OP_ENA_WIDTH 1 /* AIF1DRC2_KNEE2_OP_ENA */ -#define WM8995_AIF1DRC2_QR 0x0010 /* AIF1DRC2_QR */ -#define WM8995_AIF1DRC2_QR_MASK 0x0010 /* AIF1DRC2_QR */ -#define WM8995_AIF1DRC2_QR_SHIFT 4 /* AIF1DRC2_QR */ -#define WM8995_AIF1DRC2_QR_WIDTH 1 /* AIF1DRC2_QR */ -#define WM8995_AIF1DRC2_ANTICLIP 0x0008 /* AIF1DRC2_ANTICLIP */ -#define WM8995_AIF1DRC2_ANTICLIP_MASK 0x0008 /* AIF1DRC2_ANTICLIP */ -#define WM8995_AIF1DRC2_ANTICLIP_SHIFT 3 /* AIF1DRC2_ANTICLIP */ -#define WM8995_AIF1DRC2_ANTICLIP_WIDTH 1 /* AIF1DRC2_ANTICLIP */ -#define WM8995_AIF1DAC2_DRC_ENA 0x0004 /* AIF1DAC2_DRC_ENA */ -#define WM8995_AIF1DAC2_DRC_ENA_MASK 0x0004 /* AIF1DAC2_DRC_ENA */ -#define WM8995_AIF1DAC2_DRC_ENA_SHIFT 2 /* AIF1DAC2_DRC_ENA */ -#define WM8995_AIF1DAC2_DRC_ENA_WIDTH 1 /* AIF1DAC2_DRC_ENA */ -#define WM8995_AIF1ADC2L_DRC_ENA 0x0002 /* AIF1ADC2L_DRC_ENA */ -#define WM8995_AIF1ADC2L_DRC_ENA_MASK 0x0002 /* AIF1ADC2L_DRC_ENA */ -#define WM8995_AIF1ADC2L_DRC_ENA_SHIFT 1 /* AIF1ADC2L_DRC_ENA */ -#define WM8995_AIF1ADC2L_DRC_ENA_WIDTH 1 /* AIF1ADC2L_DRC_ENA */ -#define WM8995_AIF1ADC2R_DRC_ENA 0x0001 /* AIF1ADC2R_DRC_ENA */ -#define WM8995_AIF1ADC2R_DRC_ENA_MASK 0x0001 /* AIF1ADC2R_DRC_ENA */ -#define WM8995_AIF1ADC2R_DRC_ENA_SHIFT 0 /* AIF1ADC2R_DRC_ENA */ -#define WM8995_AIF1ADC2R_DRC_ENA_WIDTH 1 /* AIF1ADC2R_DRC_ENA */ - -/* - * R1105 (0x451) - AIF1 DRC2 (2) - */ -#define WM8995_AIF1DRC2_ATK_MASK 0x1E00 /* AIF1DRC2_ATK - [12:9] */ -#define WM8995_AIF1DRC2_ATK_SHIFT 9 /* AIF1DRC2_ATK - [12:9] */ -#define WM8995_AIF1DRC2_ATK_WIDTH 4 /* AIF1DRC2_ATK - [12:9] */ -#define WM8995_AIF1DRC2_DCY_MASK 0x01E0 /* AIF1DRC2_DCY - [8:5] */ -#define WM8995_AIF1DRC2_DCY_SHIFT 5 /* AIF1DRC2_DCY - [8:5] */ -#define WM8995_AIF1DRC2_DCY_WIDTH 4 /* AIF1DRC2_DCY - [8:5] */ -#define WM8995_AIF1DRC2_MINGAIN_MASK 0x001C /* AIF1DRC2_MINGAIN - [4:2] */ -#define WM8995_AIF1DRC2_MINGAIN_SHIFT 2 /* AIF1DRC2_MINGAIN - [4:2] */ -#define WM8995_AIF1DRC2_MINGAIN_WIDTH 3 /* AIF1DRC2_MINGAIN - [4:2] */ -#define WM8995_AIF1DRC2_MAXGAIN_MASK 0x0003 /* AIF1DRC2_MAXGAIN - [1:0] */ -#define WM8995_AIF1DRC2_MAXGAIN_SHIFT 0 /* AIF1DRC2_MAXGAIN - [1:0] */ -#define WM8995_AIF1DRC2_MAXGAIN_WIDTH 2 /* AIF1DRC2_MAXGAIN - [1:0] */ - -/* - * R1106 (0x452) - AIF1 DRC2 (3) - */ -#define WM8995_AIF1DRC2_NG_MINGAIN_MASK 0xF000 /* AIF1DRC2_NG_MINGAIN - [15:12] */ -#define WM8995_AIF1DRC2_NG_MINGAIN_SHIFT 12 /* AIF1DRC2_NG_MINGAIN - [15:12] */ -#define WM8995_AIF1DRC2_NG_MINGAIN_WIDTH 4 /* AIF1DRC2_NG_MINGAIN - [15:12] */ -#define WM8995_AIF1DRC2_NG_EXP_MASK 0x0C00 /* AIF1DRC2_NG_EXP - [11:10] */ -#define WM8995_AIF1DRC2_NG_EXP_SHIFT 10 /* AIF1DRC2_NG_EXP - [11:10] */ -#define WM8995_AIF1DRC2_NG_EXP_WIDTH 2 /* AIF1DRC2_NG_EXP - [11:10] */ -#define WM8995_AIF1DRC2_QR_THR_MASK 0x0300 /* AIF1DRC2_QR_THR - [9:8] */ -#define WM8995_AIF1DRC2_QR_THR_SHIFT 8 /* AIF1DRC2_QR_THR - [9:8] */ -#define WM8995_AIF1DRC2_QR_THR_WIDTH 2 /* AIF1DRC2_QR_THR - [9:8] */ -#define WM8995_AIF1DRC2_QR_DCY_MASK 0x00C0 /* AIF1DRC2_QR_DCY - [7:6] */ -#define WM8995_AIF1DRC2_QR_DCY_SHIFT 6 /* AIF1DRC2_QR_DCY - [7:6] */ -#define WM8995_AIF1DRC2_QR_DCY_WIDTH 2 /* AIF1DRC2_QR_DCY - [7:6] */ -#define WM8995_AIF1DRC2_HI_COMP_MASK 0x0038 /* AIF1DRC2_HI_COMP - [5:3] */ -#define WM8995_AIF1DRC2_HI_COMP_SHIFT 3 /* AIF1DRC2_HI_COMP - [5:3] */ -#define WM8995_AIF1DRC2_HI_COMP_WIDTH 3 /* AIF1DRC2_HI_COMP - [5:3] */ -#define WM8995_AIF1DRC2_LO_COMP_MASK 0x0007 /* AIF1DRC2_LO_COMP - [2:0] */ -#define WM8995_AIF1DRC2_LO_COMP_SHIFT 0 /* AIF1DRC2_LO_COMP - [2:0] */ -#define WM8995_AIF1DRC2_LO_COMP_WIDTH 3 /* AIF1DRC2_LO_COMP - [2:0] */ - -/* - * R1107 (0x453) - AIF1 DRC2 (4) - */ -#define WM8995_AIF1DRC2_KNEE_IP_MASK 0x07E0 /* AIF1DRC2_KNEE_IP - [10:5] */ -#define WM8995_AIF1DRC2_KNEE_IP_SHIFT 5 /* AIF1DRC2_KNEE_IP - [10:5] */ -#define WM8995_AIF1DRC2_KNEE_IP_WIDTH 6 /* AIF1DRC2_KNEE_IP - [10:5] */ -#define WM8995_AIF1DRC2_KNEE_OP_MASK 0x001F /* AIF1DRC2_KNEE_OP - [4:0] */ -#define WM8995_AIF1DRC2_KNEE_OP_SHIFT 0 /* AIF1DRC2_KNEE_OP - [4:0] */ -#define WM8995_AIF1DRC2_KNEE_OP_WIDTH 5 /* AIF1DRC2_KNEE_OP - [4:0] */ - -/* - * R1108 (0x454) - AIF1 DRC2 (5) - */ -#define WM8995_AIF1DRC2_KNEE2_IP_MASK 0x03E0 /* AIF1DRC2_KNEE2_IP - [9:5] */ -#define WM8995_AIF1DRC2_KNEE2_IP_SHIFT 5 /* AIF1DRC2_KNEE2_IP - [9:5] */ -#define WM8995_AIF1DRC2_KNEE2_IP_WIDTH 5 /* AIF1DRC2_KNEE2_IP - [9:5] */ -#define WM8995_AIF1DRC2_KNEE2_OP_MASK 0x001F /* AIF1DRC2_KNEE2_OP - [4:0] */ -#define WM8995_AIF1DRC2_KNEE2_OP_SHIFT 0 /* AIF1DRC2_KNEE2_OP - [4:0] */ -#define WM8995_AIF1DRC2_KNEE2_OP_WIDTH 5 /* AIF1DRC2_KNEE2_OP - [4:0] */ - -/* - * R1152 (0x480) - AIF1 DAC1 EQ Gains (1) - */ -#define WM8995_AIF1DAC1_EQ_B1_GAIN_MASK 0xF800 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF1DAC1_EQ_B1_GAIN_SHIFT 11 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF1DAC1_EQ_B1_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF1DAC1_EQ_B2_GAIN_MASK 0x07C0 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF1DAC1_EQ_B2_GAIN_SHIFT 6 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF1DAC1_EQ_B2_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF1DAC1_EQ_B3_GAIN_MASK 0x003E /* AIF1DAC1_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF1DAC1_EQ_B3_GAIN_SHIFT 1 /* AIF1DAC1_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF1DAC1_EQ_B3_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF1DAC1_EQ_ENA 0x0001 /* AIF1DAC1_EQ_ENA */ -#define WM8995_AIF1DAC1_EQ_ENA_MASK 0x0001 /* AIF1DAC1_EQ_ENA */ -#define WM8995_AIF1DAC1_EQ_ENA_SHIFT 0 /* AIF1DAC1_EQ_ENA */ -#define WM8995_AIF1DAC1_EQ_ENA_WIDTH 1 /* AIF1DAC1_EQ_ENA */ - -/* - * R1153 (0x481) - AIF1 DAC1 EQ Gains (2) - */ -#define WM8995_AIF1DAC1_EQ_B4_GAIN_MASK 0xF800 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF1DAC1_EQ_B4_GAIN_SHIFT 11 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF1DAC1_EQ_B4_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF1DAC1_EQ_B5_GAIN_MASK 0x07C0 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */ -#define WM8995_AIF1DAC1_EQ_B5_GAIN_SHIFT 6 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */ -#define WM8995_AIF1DAC1_EQ_B5_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */ - -/* - * R1154 (0x482) - AIF1 DAC1 EQ Band 1 A - */ -#define WM8995_AIF1DAC1_EQ_B1_A_MASK 0xFFFF /* AIF1DAC1_EQ_B1_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B1_A_SHIFT 0 /* AIF1DAC1_EQ_B1_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B1_A_WIDTH 16 /* AIF1DAC1_EQ_B1_A - [15:0] */ - -/* - * R1155 (0x483) - AIF1 DAC1 EQ Band 1 B - */ -#define WM8995_AIF1DAC1_EQ_B1_B_MASK 0xFFFF /* AIF1DAC1_EQ_B1_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B1_B_SHIFT 0 /* AIF1DAC1_EQ_B1_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B1_B_WIDTH 16 /* AIF1DAC1_EQ_B1_B - [15:0] */ - -/* - * R1156 (0x484) - AIF1 DAC1 EQ Band 1 PG - */ -#define WM8995_AIF1DAC1_EQ_B1_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B1_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B1_PG_SHIFT 0 /* AIF1DAC1_EQ_B1_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B1_PG_WIDTH 16 /* AIF1DAC1_EQ_B1_PG - [15:0] */ - -/* - * R1157 (0x485) - AIF1 DAC1 EQ Band 2 A - */ -#define WM8995_AIF1DAC1_EQ_B2_A_MASK 0xFFFF /* AIF1DAC1_EQ_B2_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B2_A_SHIFT 0 /* AIF1DAC1_EQ_B2_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B2_A_WIDTH 16 /* AIF1DAC1_EQ_B2_A - [15:0] */ - -/* - * R1158 (0x486) - AIF1 DAC1 EQ Band 2 B - */ -#define WM8995_AIF1DAC1_EQ_B2_B_MASK 0xFFFF /* AIF1DAC1_EQ_B2_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B2_B_SHIFT 0 /* AIF1DAC1_EQ_B2_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B2_B_WIDTH 16 /* AIF1DAC1_EQ_B2_B - [15:0] */ - -/* - * R1159 (0x487) - AIF1 DAC1 EQ Band 2 C - */ -#define WM8995_AIF1DAC1_EQ_B2_C_MASK 0xFFFF /* AIF1DAC1_EQ_B2_C - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B2_C_SHIFT 0 /* AIF1DAC1_EQ_B2_C - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B2_C_WIDTH 16 /* AIF1DAC1_EQ_B2_C - [15:0] */ - -/* - * R1160 (0x488) - AIF1 DAC1 EQ Band 2 PG - */ -#define WM8995_AIF1DAC1_EQ_B2_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B2_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B2_PG_SHIFT 0 /* AIF1DAC1_EQ_B2_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B2_PG_WIDTH 16 /* AIF1DAC1_EQ_B2_PG - [15:0] */ - -/* - * R1161 (0x489) - AIF1 DAC1 EQ Band 3 A - */ -#define WM8995_AIF1DAC1_EQ_B3_A_MASK 0xFFFF /* AIF1DAC1_EQ_B3_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B3_A_SHIFT 0 /* AIF1DAC1_EQ_B3_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B3_A_WIDTH 16 /* AIF1DAC1_EQ_B3_A - [15:0] */ - -/* - * R1162 (0x48A) - AIF1 DAC1 EQ Band 3 B - */ -#define WM8995_AIF1DAC1_EQ_B3_B_MASK 0xFFFF /* AIF1DAC1_EQ_B3_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B3_B_SHIFT 0 /* AIF1DAC1_EQ_B3_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B3_B_WIDTH 16 /* AIF1DAC1_EQ_B3_B - [15:0] */ - -/* - * R1163 (0x48B) - AIF1 DAC1 EQ Band 3 C - */ -#define WM8995_AIF1DAC1_EQ_B3_C_MASK 0xFFFF /* AIF1DAC1_EQ_B3_C - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B3_C_SHIFT 0 /* AIF1DAC1_EQ_B3_C - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B3_C_WIDTH 16 /* AIF1DAC1_EQ_B3_C - [15:0] */ - -/* - * R1164 (0x48C) - AIF1 DAC1 EQ Band 3 PG - */ -#define WM8995_AIF1DAC1_EQ_B3_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B3_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B3_PG_SHIFT 0 /* AIF1DAC1_EQ_B3_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B3_PG_WIDTH 16 /* AIF1DAC1_EQ_B3_PG - [15:0] */ - -/* - * R1165 (0x48D) - AIF1 DAC1 EQ Band 4 A - */ -#define WM8995_AIF1DAC1_EQ_B4_A_MASK 0xFFFF /* AIF1DAC1_EQ_B4_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B4_A_SHIFT 0 /* AIF1DAC1_EQ_B4_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B4_A_WIDTH 16 /* AIF1DAC1_EQ_B4_A - [15:0] */ - -/* - * R1166 (0x48E) - AIF1 DAC1 EQ Band 4 B - */ -#define WM8995_AIF1DAC1_EQ_B4_B_MASK 0xFFFF /* AIF1DAC1_EQ_B4_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B4_B_SHIFT 0 /* AIF1DAC1_EQ_B4_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B4_B_WIDTH 16 /* AIF1DAC1_EQ_B4_B - [15:0] */ - -/* - * R1167 (0x48F) - AIF1 DAC1 EQ Band 4 C - */ -#define WM8995_AIF1DAC1_EQ_B4_C_MASK 0xFFFF /* AIF1DAC1_EQ_B4_C - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B4_C_SHIFT 0 /* AIF1DAC1_EQ_B4_C - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B4_C_WIDTH 16 /* AIF1DAC1_EQ_B4_C - [15:0] */ - -/* - * R1168 (0x490) - AIF1 DAC1 EQ Band 4 PG - */ -#define WM8995_AIF1DAC1_EQ_B4_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B4_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B4_PG_SHIFT 0 /* AIF1DAC1_EQ_B4_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B4_PG_WIDTH 16 /* AIF1DAC1_EQ_B4_PG - [15:0] */ - -/* - * R1169 (0x491) - AIF1 DAC1 EQ Band 5 A - */ -#define WM8995_AIF1DAC1_EQ_B5_A_MASK 0xFFFF /* AIF1DAC1_EQ_B5_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B5_A_SHIFT 0 /* AIF1DAC1_EQ_B5_A - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B5_A_WIDTH 16 /* AIF1DAC1_EQ_B5_A - [15:0] */ - -/* - * R1170 (0x492) - AIF1 DAC1 EQ Band 5 B - */ -#define WM8995_AIF1DAC1_EQ_B5_B_MASK 0xFFFF /* AIF1DAC1_EQ_B5_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B5_B_SHIFT 0 /* AIF1DAC1_EQ_B5_B - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B5_B_WIDTH 16 /* AIF1DAC1_EQ_B5_B - [15:0] */ - -/* - * R1171 (0x493) - AIF1 DAC1 EQ Band 5 PG - */ -#define WM8995_AIF1DAC1_EQ_B5_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B5_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B5_PG_SHIFT 0 /* AIF1DAC1_EQ_B5_PG - [15:0] */ -#define WM8995_AIF1DAC1_EQ_B5_PG_WIDTH 16 /* AIF1DAC1_EQ_B5_PG - [15:0] */ - -/* - * R1184 (0x4A0) - AIF1 DAC2 EQ Gains (1) - */ -#define WM8995_AIF1DAC2_EQ_B1_GAIN_MASK 0xF800 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF1DAC2_EQ_B1_GAIN_SHIFT 11 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF1DAC2_EQ_B1_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF1DAC2_EQ_B2_GAIN_MASK 0x07C0 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF1DAC2_EQ_B2_GAIN_SHIFT 6 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF1DAC2_EQ_B2_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF1DAC2_EQ_B3_GAIN_MASK 0x003E /* AIF1DAC2_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF1DAC2_EQ_B3_GAIN_SHIFT 1 /* AIF1DAC2_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF1DAC2_EQ_B3_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF1DAC2_EQ_ENA 0x0001 /* AIF1DAC2_EQ_ENA */ -#define WM8995_AIF1DAC2_EQ_ENA_MASK 0x0001 /* AIF1DAC2_EQ_ENA */ -#define WM8995_AIF1DAC2_EQ_ENA_SHIFT 0 /* AIF1DAC2_EQ_ENA */ -#define WM8995_AIF1DAC2_EQ_ENA_WIDTH 1 /* AIF1DAC2_EQ_ENA */ - -/* - * R1185 (0x4A1) - AIF1 DAC2 EQ Gains (2) - */ -#define WM8995_AIF1DAC2_EQ_B4_GAIN_MASK 0xF800 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF1DAC2_EQ_B4_GAIN_SHIFT 11 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF1DAC2_EQ_B4_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF1DAC2_EQ_B5_GAIN_MASK 0x07C0 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */ -#define WM8995_AIF1DAC2_EQ_B5_GAIN_SHIFT 6 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */ -#define WM8995_AIF1DAC2_EQ_B5_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */ - -/* - * R1186 (0x4A2) - AIF1 DAC2 EQ Band 1 A - */ -#define WM8995_AIF1DAC2_EQ_B1_A_MASK 0xFFFF /* AIF1DAC2_EQ_B1_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B1_A_SHIFT 0 /* AIF1DAC2_EQ_B1_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B1_A_WIDTH 16 /* AIF1DAC2_EQ_B1_A - [15:0] */ - -/* - * R1187 (0x4A3) - AIF1 DAC2 EQ Band 1 B - */ -#define WM8995_AIF1DAC2_EQ_B1_B_MASK 0xFFFF /* AIF1DAC2_EQ_B1_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B1_B_SHIFT 0 /* AIF1DAC2_EQ_B1_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B1_B_WIDTH 16 /* AIF1DAC2_EQ_B1_B - [15:0] */ - -/* - * R1188 (0x4A4) - AIF1 DAC2 EQ Band 1 PG - */ -#define WM8995_AIF1DAC2_EQ_B1_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B1_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B1_PG_SHIFT 0 /* AIF1DAC2_EQ_B1_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B1_PG_WIDTH 16 /* AIF1DAC2_EQ_B1_PG - [15:0] */ - -/* - * R1189 (0x4A5) - AIF1 DAC2 EQ Band 2 A - */ -#define WM8995_AIF1DAC2_EQ_B2_A_MASK 0xFFFF /* AIF1DAC2_EQ_B2_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B2_A_SHIFT 0 /* AIF1DAC2_EQ_B2_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B2_A_WIDTH 16 /* AIF1DAC2_EQ_B2_A - [15:0] */ - -/* - * R1190 (0x4A6) - AIF1 DAC2 EQ Band 2 B - */ -#define WM8995_AIF1DAC2_EQ_B2_B_MASK 0xFFFF /* AIF1DAC2_EQ_B2_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B2_B_SHIFT 0 /* AIF1DAC2_EQ_B2_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B2_B_WIDTH 16 /* AIF1DAC2_EQ_B2_B - [15:0] */ - -/* - * R1191 (0x4A7) - AIF1 DAC2 EQ Band 2 C - */ -#define WM8995_AIF1DAC2_EQ_B2_C_MASK 0xFFFF /* AIF1DAC2_EQ_B2_C - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B2_C_SHIFT 0 /* AIF1DAC2_EQ_B2_C - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B2_C_WIDTH 16 /* AIF1DAC2_EQ_B2_C - [15:0] */ - -/* - * R1192 (0x4A8) - AIF1 DAC2 EQ Band 2 PG - */ -#define WM8995_AIF1DAC2_EQ_B2_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B2_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B2_PG_SHIFT 0 /* AIF1DAC2_EQ_B2_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B2_PG_WIDTH 16 /* AIF1DAC2_EQ_B2_PG - [15:0] */ - -/* - * R1193 (0x4A9) - AIF1 DAC2 EQ Band 3 A - */ -#define WM8995_AIF1DAC2_EQ_B3_A_MASK 0xFFFF /* AIF1DAC2_EQ_B3_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B3_A_SHIFT 0 /* AIF1DAC2_EQ_B3_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B3_A_WIDTH 16 /* AIF1DAC2_EQ_B3_A - [15:0] */ - -/* - * R1194 (0x4AA) - AIF1 DAC2 EQ Band 3 B - */ -#define WM8995_AIF1DAC2_EQ_B3_B_MASK 0xFFFF /* AIF1DAC2_EQ_B3_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B3_B_SHIFT 0 /* AIF1DAC2_EQ_B3_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B3_B_WIDTH 16 /* AIF1DAC2_EQ_B3_B - [15:0] */ - -/* - * R1195 (0x4AB) - AIF1 DAC2 EQ Band 3 C - */ -#define WM8995_AIF1DAC2_EQ_B3_C_MASK 0xFFFF /* AIF1DAC2_EQ_B3_C - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B3_C_SHIFT 0 /* AIF1DAC2_EQ_B3_C - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B3_C_WIDTH 16 /* AIF1DAC2_EQ_B3_C - [15:0] */ - -/* - * R1196 (0x4AC) - AIF1 DAC2 EQ Band 3 PG - */ -#define WM8995_AIF1DAC2_EQ_B3_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B3_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B3_PG_SHIFT 0 /* AIF1DAC2_EQ_B3_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B3_PG_WIDTH 16 /* AIF1DAC2_EQ_B3_PG - [15:0] */ - -/* - * R1197 (0x4AD) - AIF1 DAC2 EQ Band 4 A - */ -#define WM8995_AIF1DAC2_EQ_B4_A_MASK 0xFFFF /* AIF1DAC2_EQ_B4_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B4_A_SHIFT 0 /* AIF1DAC2_EQ_B4_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B4_A_WIDTH 16 /* AIF1DAC2_EQ_B4_A - [15:0] */ - -/* - * R1198 (0x4AE) - AIF1 DAC2 EQ Band 4 B - */ -#define WM8995_AIF1DAC2_EQ_B4_B_MASK 0xFFFF /* AIF1DAC2_EQ_B4_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B4_B_SHIFT 0 /* AIF1DAC2_EQ_B4_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B4_B_WIDTH 16 /* AIF1DAC2_EQ_B4_B - [15:0] */ - -/* - * R1199 (0x4AF) - AIF1 DAC2 EQ Band 4 C - */ -#define WM8995_AIF1DAC2_EQ_B4_C_MASK 0xFFFF /* AIF1DAC2_EQ_B4_C - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B4_C_SHIFT 0 /* AIF1DAC2_EQ_B4_C - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B4_C_WIDTH 16 /* AIF1DAC2_EQ_B4_C - [15:0] */ - -/* - * R1200 (0x4B0) - AIF1 DAC2 EQ Band 4 PG - */ -#define WM8995_AIF1DAC2_EQ_B4_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B4_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B4_PG_SHIFT 0 /* AIF1DAC2_EQ_B4_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B4_PG_WIDTH 16 /* AIF1DAC2_EQ_B4_PG - [15:0] */ - -/* - * R1201 (0x4B1) - AIF1 DAC2 EQ Band 5 A - */ -#define WM8995_AIF1DAC2_EQ_B5_A_MASK 0xFFFF /* AIF1DAC2_EQ_B5_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B5_A_SHIFT 0 /* AIF1DAC2_EQ_B5_A - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B5_A_WIDTH 16 /* AIF1DAC2_EQ_B5_A - [15:0] */ - -/* - * R1202 (0x4B2) - AIF1 DAC2 EQ Band 5 B - */ -#define WM8995_AIF1DAC2_EQ_B5_B_MASK 0xFFFF /* AIF1DAC2_EQ_B5_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B5_B_SHIFT 0 /* AIF1DAC2_EQ_B5_B - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B5_B_WIDTH 16 /* AIF1DAC2_EQ_B5_B - [15:0] */ - -/* - * R1203 (0x4B3) - AIF1 DAC2 EQ Band 5 PG - */ -#define WM8995_AIF1DAC2_EQ_B5_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B5_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B5_PG_SHIFT 0 /* AIF1DAC2_EQ_B5_PG - [15:0] */ -#define WM8995_AIF1DAC2_EQ_B5_PG_WIDTH 16 /* AIF1DAC2_EQ_B5_PG - [15:0] */ - -/* - * R1280 (0x500) - AIF2 ADC Left Volume - */ -#define WM8995_AIF2ADC_VU 0x0100 /* AIF2ADC_VU */ -#define WM8995_AIF2ADC_VU_MASK 0x0100 /* AIF2ADC_VU */ -#define WM8995_AIF2ADC_VU_SHIFT 8 /* AIF2ADC_VU */ -#define WM8995_AIF2ADC_VU_WIDTH 1 /* AIF2ADC_VU */ -#define WM8995_AIF2ADCL_VOL_MASK 0x00FF /* AIF2ADCL_VOL - [7:0] */ -#define WM8995_AIF2ADCL_VOL_SHIFT 0 /* AIF2ADCL_VOL - [7:0] */ -#define WM8995_AIF2ADCL_VOL_WIDTH 8 /* AIF2ADCL_VOL - [7:0] */ - -/* - * R1281 (0x501) - AIF2 ADC Right Volume - */ -#define WM8995_AIF2ADC_VU 0x0100 /* AIF2ADC_VU */ -#define WM8995_AIF2ADC_VU_MASK 0x0100 /* AIF2ADC_VU */ -#define WM8995_AIF2ADC_VU_SHIFT 8 /* AIF2ADC_VU */ -#define WM8995_AIF2ADC_VU_WIDTH 1 /* AIF2ADC_VU */ -#define WM8995_AIF2ADCR_VOL_MASK 0x00FF /* AIF2ADCR_VOL - [7:0] */ -#define WM8995_AIF2ADCR_VOL_SHIFT 0 /* AIF2ADCR_VOL - [7:0] */ -#define WM8995_AIF2ADCR_VOL_WIDTH 8 /* AIF2ADCR_VOL - [7:0] */ - -/* - * R1282 (0x502) - AIF2 DAC Left Volume - */ -#define WM8995_AIF2DAC_VU 0x0100 /* AIF2DAC_VU */ -#define WM8995_AIF2DAC_VU_MASK 0x0100 /* AIF2DAC_VU */ -#define WM8995_AIF2DAC_VU_SHIFT 8 /* AIF2DAC_VU */ -#define WM8995_AIF2DAC_VU_WIDTH 1 /* AIF2DAC_VU */ -#define WM8995_AIF2DACL_VOL_MASK 0x00FF /* AIF2DACL_VOL - [7:0] */ -#define WM8995_AIF2DACL_VOL_SHIFT 0 /* AIF2DACL_VOL - [7:0] */ -#define WM8995_AIF2DACL_VOL_WIDTH 8 /* AIF2DACL_VOL - [7:0] */ - -/* - * R1283 (0x503) - AIF2 DAC Right Volume - */ -#define WM8995_AIF2DAC_VU 0x0100 /* AIF2DAC_VU */ -#define WM8995_AIF2DAC_VU_MASK 0x0100 /* AIF2DAC_VU */ -#define WM8995_AIF2DAC_VU_SHIFT 8 /* AIF2DAC_VU */ -#define WM8995_AIF2DAC_VU_WIDTH 1 /* AIF2DAC_VU */ -#define WM8995_AIF2DACR_VOL_MASK 0x00FF /* AIF2DACR_VOL - [7:0] */ -#define WM8995_AIF2DACR_VOL_SHIFT 0 /* AIF2DACR_VOL - [7:0] */ -#define WM8995_AIF2DACR_VOL_WIDTH 8 /* AIF2DACR_VOL - [7:0] */ - -/* - * R1296 (0x510) - AIF2 ADC Filters - */ -#define WM8995_AIF2ADC_4FS 0x8000 /* AIF2ADC_4FS */ -#define WM8995_AIF2ADC_4FS_MASK 0x8000 /* AIF2ADC_4FS */ -#define WM8995_AIF2ADC_4FS_SHIFT 15 /* AIF2ADC_4FS */ -#define WM8995_AIF2ADC_4FS_WIDTH 1 /* AIF2ADC_4FS */ -#define WM8995_AIF2ADCL_HPF 0x1000 /* AIF2ADCL_HPF */ -#define WM8995_AIF2ADCL_HPF_MASK 0x1000 /* AIF2ADCL_HPF */ -#define WM8995_AIF2ADCL_HPF_SHIFT 12 /* AIF2ADCL_HPF */ -#define WM8995_AIF2ADCL_HPF_WIDTH 1 /* AIF2ADCL_HPF */ -#define WM8995_AIF2ADCR_HPF 0x0800 /* AIF2ADCR_HPF */ -#define WM8995_AIF2ADCR_HPF_MASK 0x0800 /* AIF2ADCR_HPF */ -#define WM8995_AIF2ADCR_HPF_SHIFT 11 /* AIF2ADCR_HPF */ -#define WM8995_AIF2ADCR_HPF_WIDTH 1 /* AIF2ADCR_HPF */ -#define WM8995_AIF2ADC_HPF_MODE 0x0008 /* AIF2ADC_HPF_MODE */ -#define WM8995_AIF2ADC_HPF_MODE_MASK 0x0008 /* AIF2ADC_HPF_MODE */ -#define WM8995_AIF2ADC_HPF_MODE_SHIFT 3 /* AIF2ADC_HPF_MODE */ -#define WM8995_AIF2ADC_HPF_MODE_WIDTH 1 /* AIF2ADC_HPF_MODE */ -#define WM8995_AIF2ADC_HPF_CUT_MASK 0x0007 /* AIF2ADC_HPF_CUT - [2:0] */ -#define WM8995_AIF2ADC_HPF_CUT_SHIFT 0 /* AIF2ADC_HPF_CUT - [2:0] */ -#define WM8995_AIF2ADC_HPF_CUT_WIDTH 3 /* AIF2ADC_HPF_CUT - [2:0] */ - -/* - * R1312 (0x520) - AIF2 DAC Filters (1) - */ -#define WM8995_AIF2DAC_MUTE 0x0200 /* AIF2DAC_MUTE */ -#define WM8995_AIF2DAC_MUTE_MASK 0x0200 /* AIF2DAC_MUTE */ -#define WM8995_AIF2DAC_MUTE_SHIFT 9 /* AIF2DAC_MUTE */ -#define WM8995_AIF2DAC_MUTE_WIDTH 1 /* AIF2DAC_MUTE */ -#define WM8995_AIF2DAC_MONO 0x0080 /* AIF2DAC_MONO */ -#define WM8995_AIF2DAC_MONO_MASK 0x0080 /* AIF2DAC_MONO */ -#define WM8995_AIF2DAC_MONO_SHIFT 7 /* AIF2DAC_MONO */ -#define WM8995_AIF2DAC_MONO_WIDTH 1 /* AIF2DAC_MONO */ -#define WM8995_AIF2DAC_MUTERATE 0x0020 /* AIF2DAC_MUTERATE */ -#define WM8995_AIF2DAC_MUTERATE_MASK 0x0020 /* AIF2DAC_MUTERATE */ -#define WM8995_AIF2DAC_MUTERATE_SHIFT 5 /* AIF2DAC_MUTERATE */ -#define WM8995_AIF2DAC_MUTERATE_WIDTH 1 /* AIF2DAC_MUTERATE */ -#define WM8995_AIF2DAC_UNMUTE_RAMP 0x0010 /* AIF2DAC_UNMUTE_RAMP */ -#define WM8995_AIF2DAC_UNMUTE_RAMP_MASK 0x0010 /* AIF2DAC_UNMUTE_RAMP */ -#define WM8995_AIF2DAC_UNMUTE_RAMP_SHIFT 4 /* AIF2DAC_UNMUTE_RAMP */ -#define WM8995_AIF2DAC_UNMUTE_RAMP_WIDTH 1 /* AIF2DAC_UNMUTE_RAMP */ -#define WM8995_AIF2DAC_DEEMP_MASK 0x0006 /* AIF2DAC_DEEMP - [2:1] */ -#define WM8995_AIF2DAC_DEEMP_SHIFT 1 /* AIF2DAC_DEEMP - [2:1] */ -#define WM8995_AIF2DAC_DEEMP_WIDTH 2 /* AIF2DAC_DEEMP - [2:1] */ - -/* - * R1313 (0x521) - AIF2 DAC Filters (2) - */ -#define WM8995_AIF2DAC_3D_GAIN_MASK 0x3E00 /* AIF2DAC_3D_GAIN - [13:9] */ -#define WM8995_AIF2DAC_3D_GAIN_SHIFT 9 /* AIF2DAC_3D_GAIN - [13:9] */ -#define WM8995_AIF2DAC_3D_GAIN_WIDTH 5 /* AIF2DAC_3D_GAIN - [13:9] */ -#define WM8995_AIF2DAC_3D_ENA 0x0100 /* AIF2DAC_3D_ENA */ -#define WM8995_AIF2DAC_3D_ENA_MASK 0x0100 /* AIF2DAC_3D_ENA */ -#define WM8995_AIF2DAC_3D_ENA_SHIFT 8 /* AIF2DAC_3D_ENA */ -#define WM8995_AIF2DAC_3D_ENA_WIDTH 1 /* AIF2DAC_3D_ENA */ - -/* - * R1344 (0x540) - AIF2 DRC (1) - */ -#define WM8995_AIF2DRC_SIG_DET_RMS_MASK 0xF800 /* AIF2DRC_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF2DRC_SIG_DET_RMS_SHIFT 11 /* AIF2DRC_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF2DRC_SIG_DET_RMS_WIDTH 5 /* AIF2DRC_SIG_DET_RMS - [15:11] */ -#define WM8995_AIF2DRC_SIG_DET_PK_MASK 0x0600 /* AIF2DRC_SIG_DET_PK - [10:9] */ -#define WM8995_AIF2DRC_SIG_DET_PK_SHIFT 9 /* AIF2DRC_SIG_DET_PK - [10:9] */ -#define WM8995_AIF2DRC_SIG_DET_PK_WIDTH 2 /* AIF2DRC_SIG_DET_PK - [10:9] */ -#define WM8995_AIF2DRC_NG_ENA 0x0100 /* AIF2DRC_NG_ENA */ -#define WM8995_AIF2DRC_NG_ENA_MASK 0x0100 /* AIF2DRC_NG_ENA */ -#define WM8995_AIF2DRC_NG_ENA_SHIFT 8 /* AIF2DRC_NG_ENA */ -#define WM8995_AIF2DRC_NG_ENA_WIDTH 1 /* AIF2DRC_NG_ENA */ -#define WM8995_AIF2DRC_SIG_DET_MODE 0x0080 /* AIF2DRC_SIG_DET_MODE */ -#define WM8995_AIF2DRC_SIG_DET_MODE_MASK 0x0080 /* AIF2DRC_SIG_DET_MODE */ -#define WM8995_AIF2DRC_SIG_DET_MODE_SHIFT 7 /* AIF2DRC_SIG_DET_MODE */ -#define WM8995_AIF2DRC_SIG_DET_MODE_WIDTH 1 /* AIF2DRC_SIG_DET_MODE */ -#define WM8995_AIF2DRC_SIG_DET 0x0040 /* AIF2DRC_SIG_DET */ -#define WM8995_AIF2DRC_SIG_DET_MASK 0x0040 /* AIF2DRC_SIG_DET */ -#define WM8995_AIF2DRC_SIG_DET_SHIFT 6 /* AIF2DRC_SIG_DET */ -#define WM8995_AIF2DRC_SIG_DET_WIDTH 1 /* AIF2DRC_SIG_DET */ -#define WM8995_AIF2DRC_KNEE2_OP_ENA 0x0020 /* AIF2DRC_KNEE2_OP_ENA */ -#define WM8995_AIF2DRC_KNEE2_OP_ENA_MASK 0x0020 /* AIF2DRC_KNEE2_OP_ENA */ -#define WM8995_AIF2DRC_KNEE2_OP_ENA_SHIFT 5 /* AIF2DRC_KNEE2_OP_ENA */ -#define WM8995_AIF2DRC_KNEE2_OP_ENA_WIDTH 1 /* AIF2DRC_KNEE2_OP_ENA */ -#define WM8995_AIF2DRC_QR 0x0010 /* AIF2DRC_QR */ -#define WM8995_AIF2DRC_QR_MASK 0x0010 /* AIF2DRC_QR */ -#define WM8995_AIF2DRC_QR_SHIFT 4 /* AIF2DRC_QR */ -#define WM8995_AIF2DRC_QR_WIDTH 1 /* AIF2DRC_QR */ -#define WM8995_AIF2DRC_ANTICLIP 0x0008 /* AIF2DRC_ANTICLIP */ -#define WM8995_AIF2DRC_ANTICLIP_MASK 0x0008 /* AIF2DRC_ANTICLIP */ -#define WM8995_AIF2DRC_ANTICLIP_SHIFT 3 /* AIF2DRC_ANTICLIP */ -#define WM8995_AIF2DRC_ANTICLIP_WIDTH 1 /* AIF2DRC_ANTICLIP */ -#define WM8995_AIF2DAC_DRC_ENA 0x0004 /* AIF2DAC_DRC_ENA */ -#define WM8995_AIF2DAC_DRC_ENA_MASK 0x0004 /* AIF2DAC_DRC_ENA */ -#define WM8995_AIF2DAC_DRC_ENA_SHIFT 2 /* AIF2DAC_DRC_ENA */ -#define WM8995_AIF2DAC_DRC_ENA_WIDTH 1 /* AIF2DAC_DRC_ENA */ -#define WM8995_AIF2ADCL_DRC_ENA 0x0002 /* AIF2ADCL_DRC_ENA */ -#define WM8995_AIF2ADCL_DRC_ENA_MASK 0x0002 /* AIF2ADCL_DRC_ENA */ -#define WM8995_AIF2ADCL_DRC_ENA_SHIFT 1 /* AIF2ADCL_DRC_ENA */ -#define WM8995_AIF2ADCL_DRC_ENA_WIDTH 1 /* AIF2ADCL_DRC_ENA */ -#define WM8995_AIF2ADCR_DRC_ENA 0x0001 /* AIF2ADCR_DRC_ENA */ -#define WM8995_AIF2ADCR_DRC_ENA_MASK 0x0001 /* AIF2ADCR_DRC_ENA */ -#define WM8995_AIF2ADCR_DRC_ENA_SHIFT 0 /* AIF2ADCR_DRC_ENA */ -#define WM8995_AIF2ADCR_DRC_ENA_WIDTH 1 /* AIF2ADCR_DRC_ENA */ - -/* - * R1345 (0x541) - AIF2 DRC (2) - */ -#define WM8995_AIF2DRC_ATK_MASK 0x1E00 /* AIF2DRC_ATK - [12:9] */ -#define WM8995_AIF2DRC_ATK_SHIFT 9 /* AIF2DRC_ATK - [12:9] */ -#define WM8995_AIF2DRC_ATK_WIDTH 4 /* AIF2DRC_ATK - [12:9] */ -#define WM8995_AIF2DRC_DCY_MASK 0x01E0 /* AIF2DRC_DCY - [8:5] */ -#define WM8995_AIF2DRC_DCY_SHIFT 5 /* AIF2DRC_DCY - [8:5] */ -#define WM8995_AIF2DRC_DCY_WIDTH 4 /* AIF2DRC_DCY - [8:5] */ -#define WM8995_AIF2DRC_MINGAIN_MASK 0x001C /* AIF2DRC_MINGAIN - [4:2] */ -#define WM8995_AIF2DRC_MINGAIN_SHIFT 2 /* AIF2DRC_MINGAIN - [4:2] */ -#define WM8995_AIF2DRC_MINGAIN_WIDTH 3 /* AIF2DRC_MINGAIN - [4:2] */ -#define WM8995_AIF2DRC_MAXGAIN_MASK 0x0003 /* AIF2DRC_MAXGAIN - [1:0] */ -#define WM8995_AIF2DRC_MAXGAIN_SHIFT 0 /* AIF2DRC_MAXGAIN - [1:0] */ -#define WM8995_AIF2DRC_MAXGAIN_WIDTH 2 /* AIF2DRC_MAXGAIN - [1:0] */ - -/* - * R1346 (0x542) - AIF2 DRC (3) - */ -#define WM8995_AIF2DRC_NG_MINGAIN_MASK 0xF000 /* AIF2DRC_NG_MINGAIN - [15:12] */ -#define WM8995_AIF2DRC_NG_MINGAIN_SHIFT 12 /* AIF2DRC_NG_MINGAIN - [15:12] */ -#define WM8995_AIF2DRC_NG_MINGAIN_WIDTH 4 /* AIF2DRC_NG_MINGAIN - [15:12] */ -#define WM8995_AIF2DRC_NG_EXP_MASK 0x0C00 /* AIF2DRC_NG_EXP - [11:10] */ -#define WM8995_AIF2DRC_NG_EXP_SHIFT 10 /* AIF2DRC_NG_EXP - [11:10] */ -#define WM8995_AIF2DRC_NG_EXP_WIDTH 2 /* AIF2DRC_NG_EXP - [11:10] */ -#define WM8995_AIF2DRC_QR_THR_MASK 0x0300 /* AIF2DRC_QR_THR - [9:8] */ -#define WM8995_AIF2DRC_QR_THR_SHIFT 8 /* AIF2DRC_QR_THR - [9:8] */ -#define WM8995_AIF2DRC_QR_THR_WIDTH 2 /* AIF2DRC_QR_THR - [9:8] */ -#define WM8995_AIF2DRC_QR_DCY_MASK 0x00C0 /* AIF2DRC_QR_DCY - [7:6] */ -#define WM8995_AIF2DRC_QR_DCY_SHIFT 6 /* AIF2DRC_QR_DCY - [7:6] */ -#define WM8995_AIF2DRC_QR_DCY_WIDTH 2 /* AIF2DRC_QR_DCY - [7:6] */ -#define WM8995_AIF2DRC_HI_COMP_MASK 0x0038 /* AIF2DRC_HI_COMP - [5:3] */ -#define WM8995_AIF2DRC_HI_COMP_SHIFT 3 /* AIF2DRC_HI_COMP - [5:3] */ -#define WM8995_AIF2DRC_HI_COMP_WIDTH 3 /* AIF2DRC_HI_COMP - [5:3] */ -#define WM8995_AIF2DRC_LO_COMP_MASK 0x0007 /* AIF2DRC_LO_COMP - [2:0] */ -#define WM8995_AIF2DRC_LO_COMP_SHIFT 0 /* AIF2DRC_LO_COMP - [2:0] */ -#define WM8995_AIF2DRC_LO_COMP_WIDTH 3 /* AIF2DRC_LO_COMP - [2:0] */ - -/* - * R1347 (0x543) - AIF2 DRC (4) - */ -#define WM8995_AIF2DRC_KNEE_IP_MASK 0x07E0 /* AIF2DRC_KNEE_IP - [10:5] */ -#define WM8995_AIF2DRC_KNEE_IP_SHIFT 5 /* AIF2DRC_KNEE_IP - [10:5] */ -#define WM8995_AIF2DRC_KNEE_IP_WIDTH 6 /* AIF2DRC_KNEE_IP - [10:5] */ -#define WM8995_AIF2DRC_KNEE_OP_MASK 0x001F /* AIF2DRC_KNEE_OP - [4:0] */ -#define WM8995_AIF2DRC_KNEE_OP_SHIFT 0 /* AIF2DRC_KNEE_OP - [4:0] */ -#define WM8995_AIF2DRC_KNEE_OP_WIDTH 5 /* AIF2DRC_KNEE_OP - [4:0] */ - -/* - * R1348 (0x544) - AIF2 DRC (5) - */ -#define WM8995_AIF2DRC_KNEE2_IP_MASK 0x03E0 /* AIF2DRC_KNEE2_IP - [9:5] */ -#define WM8995_AIF2DRC_KNEE2_IP_SHIFT 5 /* AIF2DRC_KNEE2_IP - [9:5] */ -#define WM8995_AIF2DRC_KNEE2_IP_WIDTH 5 /* AIF2DRC_KNEE2_IP - [9:5] */ -#define WM8995_AIF2DRC_KNEE2_OP_MASK 0x001F /* AIF2DRC_KNEE2_OP - [4:0] */ -#define WM8995_AIF2DRC_KNEE2_OP_SHIFT 0 /* AIF2DRC_KNEE2_OP - [4:0] */ -#define WM8995_AIF2DRC_KNEE2_OP_WIDTH 5 /* AIF2DRC_KNEE2_OP - [4:0] */ - -/* - * R1408 (0x580) - AIF2 EQ Gains (1) - */ -#define WM8995_AIF2DAC_EQ_B1_GAIN_MASK 0xF800 /* AIF2DAC_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF2DAC_EQ_B1_GAIN_SHIFT 11 /* AIF2DAC_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF2DAC_EQ_B1_GAIN_WIDTH 5 /* AIF2DAC_EQ_B1_GAIN - [15:11] */ -#define WM8995_AIF2DAC_EQ_B2_GAIN_MASK 0x07C0 /* AIF2DAC_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF2DAC_EQ_B2_GAIN_SHIFT 6 /* AIF2DAC_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF2DAC_EQ_B2_GAIN_WIDTH 5 /* AIF2DAC_EQ_B2_GAIN - [10:6] */ -#define WM8995_AIF2DAC_EQ_B3_GAIN_MASK 0x003E /* AIF2DAC_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF2DAC_EQ_B3_GAIN_SHIFT 1 /* AIF2DAC_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF2DAC_EQ_B3_GAIN_WIDTH 5 /* AIF2DAC_EQ_B3_GAIN - [5:1] */ -#define WM8995_AIF2DAC_EQ_ENA 0x0001 /* AIF2DAC_EQ_ENA */ -#define WM8995_AIF2DAC_EQ_ENA_MASK 0x0001 /* AIF2DAC_EQ_ENA */ -#define WM8995_AIF2DAC_EQ_ENA_SHIFT 0 /* AIF2DAC_EQ_ENA */ -#define WM8995_AIF2DAC_EQ_ENA_WIDTH 1 /* AIF2DAC_EQ_ENA */ - -/* - * R1409 (0x581) - AIF2 EQ Gains (2) - */ -#define WM8995_AIF2DAC_EQ_B4_GAIN_MASK 0xF800 /* AIF2DAC_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF2DAC_EQ_B4_GAIN_SHIFT 11 /* AIF2DAC_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF2DAC_EQ_B4_GAIN_WIDTH 5 /* AIF2DAC_EQ_B4_GAIN - [15:11] */ -#define WM8995_AIF2DAC_EQ_B5_GAIN_MASK 0x07C0 /* AIF2DAC_EQ_B5_GAIN - [10:6] */ -#define WM8995_AIF2DAC_EQ_B5_GAIN_SHIFT 6 /* AIF2DAC_EQ_B5_GAIN - [10:6] */ -#define WM8995_AIF2DAC_EQ_B5_GAIN_WIDTH 5 /* AIF2DAC_EQ_B5_GAIN - [10:6] */ - -/* - * R1410 (0x582) - AIF2 EQ Band 1 A - */ -#define WM8995_AIF2DAC_EQ_B1_A_MASK 0xFFFF /* AIF2DAC_EQ_B1_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B1_A_SHIFT 0 /* AIF2DAC_EQ_B1_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B1_A_WIDTH 16 /* AIF2DAC_EQ_B1_A - [15:0] */ - -/* - * R1411 (0x583) - AIF2 EQ Band 1 B - */ -#define WM8995_AIF2DAC_EQ_B1_B_MASK 0xFFFF /* AIF2DAC_EQ_B1_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B1_B_SHIFT 0 /* AIF2DAC_EQ_B1_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B1_B_WIDTH 16 /* AIF2DAC_EQ_B1_B - [15:0] */ - -/* - * R1412 (0x584) - AIF2 EQ Band 1 PG - */ -#define WM8995_AIF2DAC_EQ_B1_PG_MASK 0xFFFF /* AIF2DAC_EQ_B1_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B1_PG_SHIFT 0 /* AIF2DAC_EQ_B1_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B1_PG_WIDTH 16 /* AIF2DAC_EQ_B1_PG - [15:0] */ - -/* - * R1413 (0x585) - AIF2 EQ Band 2 A - */ -#define WM8995_AIF2DAC_EQ_B2_A_MASK 0xFFFF /* AIF2DAC_EQ_B2_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B2_A_SHIFT 0 /* AIF2DAC_EQ_B2_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B2_A_WIDTH 16 /* AIF2DAC_EQ_B2_A - [15:0] */ - -/* - * R1414 (0x586) - AIF2 EQ Band 2 B - */ -#define WM8995_AIF2DAC_EQ_B2_B_MASK 0xFFFF /* AIF2DAC_EQ_B2_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B2_B_SHIFT 0 /* AIF2DAC_EQ_B2_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B2_B_WIDTH 16 /* AIF2DAC_EQ_B2_B - [15:0] */ - -/* - * R1415 (0x587) - AIF2 EQ Band 2 C - */ -#define WM8995_AIF2DAC_EQ_B2_C_MASK 0xFFFF /* AIF2DAC_EQ_B2_C - [15:0] */ -#define WM8995_AIF2DAC_EQ_B2_C_SHIFT 0 /* AIF2DAC_EQ_B2_C - [15:0] */ -#define WM8995_AIF2DAC_EQ_B2_C_WIDTH 16 /* AIF2DAC_EQ_B2_C - [15:0] */ - -/* - * R1416 (0x588) - AIF2 EQ Band 2 PG - */ -#define WM8995_AIF2DAC_EQ_B2_PG_MASK 0xFFFF /* AIF2DAC_EQ_B2_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B2_PG_SHIFT 0 /* AIF2DAC_EQ_B2_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B2_PG_WIDTH 16 /* AIF2DAC_EQ_B2_PG - [15:0] */ - -/* - * R1417 (0x589) - AIF2 EQ Band 3 A - */ -#define WM8995_AIF2DAC_EQ_B3_A_MASK 0xFFFF /* AIF2DAC_EQ_B3_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B3_A_SHIFT 0 /* AIF2DAC_EQ_B3_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B3_A_WIDTH 16 /* AIF2DAC_EQ_B3_A - [15:0] */ - -/* - * R1418 (0x58A) - AIF2 EQ Band 3 B - */ -#define WM8995_AIF2DAC_EQ_B3_B_MASK 0xFFFF /* AIF2DAC_EQ_B3_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B3_B_SHIFT 0 /* AIF2DAC_EQ_B3_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B3_B_WIDTH 16 /* AIF2DAC_EQ_B3_B - [15:0] */ - -/* - * R1419 (0x58B) - AIF2 EQ Band 3 C - */ -#define WM8995_AIF2DAC_EQ_B3_C_MASK 0xFFFF /* AIF2DAC_EQ_B3_C - [15:0] */ -#define WM8995_AIF2DAC_EQ_B3_C_SHIFT 0 /* AIF2DAC_EQ_B3_C - [15:0] */ -#define WM8995_AIF2DAC_EQ_B3_C_WIDTH 16 /* AIF2DAC_EQ_B3_C - [15:0] */ - -/* - * R1420 (0x58C) - AIF2 EQ Band 3 PG - */ -#define WM8995_AIF2DAC_EQ_B3_PG_MASK 0xFFFF /* AIF2DAC_EQ_B3_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B3_PG_SHIFT 0 /* AIF2DAC_EQ_B3_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B3_PG_WIDTH 16 /* AIF2DAC_EQ_B3_PG - [15:0] */ - -/* - * R1421 (0x58D) - AIF2 EQ Band 4 A - */ -#define WM8995_AIF2DAC_EQ_B4_A_MASK 0xFFFF /* AIF2DAC_EQ_B4_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B4_A_SHIFT 0 /* AIF2DAC_EQ_B4_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B4_A_WIDTH 16 /* AIF2DAC_EQ_B4_A - [15:0] */ - -/* - * R1422 (0x58E) - AIF2 EQ Band 4 B - */ -#define WM8995_AIF2DAC_EQ_B4_B_MASK 0xFFFF /* AIF2DAC_EQ_B4_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B4_B_SHIFT 0 /* AIF2DAC_EQ_B4_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B4_B_WIDTH 16 /* AIF2DAC_EQ_B4_B - [15:0] */ - -/* - * R1423 (0x58F) - AIF2 EQ Band 4 C - */ -#define WM8995_AIF2DAC_EQ_B4_C_MASK 0xFFFF /* AIF2DAC_EQ_B4_C - [15:0] */ -#define WM8995_AIF2DAC_EQ_B4_C_SHIFT 0 /* AIF2DAC_EQ_B4_C - [15:0] */ -#define WM8995_AIF2DAC_EQ_B4_C_WIDTH 16 /* AIF2DAC_EQ_B4_C - [15:0] */ - -/* - * R1424 (0x590) - AIF2 EQ Band 4 PG - */ -#define WM8995_AIF2DAC_EQ_B4_PG_MASK 0xFFFF /* AIF2DAC_EQ_B4_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B4_PG_SHIFT 0 /* AIF2DAC_EQ_B4_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B4_PG_WIDTH 16 /* AIF2DAC_EQ_B4_PG - [15:0] */ - -/* - * R1425 (0x591) - AIF2 EQ Band 5 A - */ -#define WM8995_AIF2DAC_EQ_B5_A_MASK 0xFFFF /* AIF2DAC_EQ_B5_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B5_A_SHIFT 0 /* AIF2DAC_EQ_B5_A - [15:0] */ -#define WM8995_AIF2DAC_EQ_B5_A_WIDTH 16 /* AIF2DAC_EQ_B5_A - [15:0] */ - -/* - * R1426 (0x592) - AIF2 EQ Band 5 B - */ -#define WM8995_AIF2DAC_EQ_B5_B_MASK 0xFFFF /* AIF2DAC_EQ_B5_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B5_B_SHIFT 0 /* AIF2DAC_EQ_B5_B - [15:0] */ -#define WM8995_AIF2DAC_EQ_B5_B_WIDTH 16 /* AIF2DAC_EQ_B5_B - [15:0] */ - -/* - * R1427 (0x593) - AIF2 EQ Band 5 PG - */ -#define WM8995_AIF2DAC_EQ_B5_PG_MASK 0xFFFF /* AIF2DAC_EQ_B5_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B5_PG_SHIFT 0 /* AIF2DAC_EQ_B5_PG - [15:0] */ -#define WM8995_AIF2DAC_EQ_B5_PG_WIDTH 16 /* AIF2DAC_EQ_B5_PG - [15:0] */ - -/* - * R1536 (0x600) - DAC1 Mixer Volumes - */ -#define WM8995_ADCR_DAC1_VOL_MASK 0x03E0 /* ADCR_DAC1_VOL - [9:5] */ -#define WM8995_ADCR_DAC1_VOL_SHIFT 5 /* ADCR_DAC1_VOL - [9:5] */ -#define WM8995_ADCR_DAC1_VOL_WIDTH 5 /* ADCR_DAC1_VOL - [9:5] */ -#define WM8995_ADCL_DAC1_VOL_MASK 0x001F /* ADCL_DAC1_VOL - [4:0] */ -#define WM8995_ADCL_DAC1_VOL_SHIFT 0 /* ADCL_DAC1_VOL - [4:0] */ -#define WM8995_ADCL_DAC1_VOL_WIDTH 5 /* ADCL_DAC1_VOL - [4:0] */ - -/* - * R1537 (0x601) - DAC1 Left Mixer Routing - */ -#define WM8995_ADCR_TO_DAC1L 0x0020 /* ADCR_TO_DAC1L */ -#define WM8995_ADCR_TO_DAC1L_MASK 0x0020 /* ADCR_TO_DAC1L */ -#define WM8995_ADCR_TO_DAC1L_SHIFT 5 /* ADCR_TO_DAC1L */ -#define WM8995_ADCR_TO_DAC1L_WIDTH 1 /* ADCR_TO_DAC1L */ -#define WM8995_ADCL_TO_DAC1L 0x0010 /* ADCL_TO_DAC1L */ -#define WM8995_ADCL_TO_DAC1L_MASK 0x0010 /* ADCL_TO_DAC1L */ -#define WM8995_ADCL_TO_DAC1L_SHIFT 4 /* ADCL_TO_DAC1L */ -#define WM8995_ADCL_TO_DAC1L_WIDTH 1 /* ADCL_TO_DAC1L */ -#define WM8995_AIF2DACL_TO_DAC1L 0x0004 /* AIF2DACL_TO_DAC1L */ -#define WM8995_AIF2DACL_TO_DAC1L_MASK 0x0004 /* AIF2DACL_TO_DAC1L */ -#define WM8995_AIF2DACL_TO_DAC1L_SHIFT 2 /* AIF2DACL_TO_DAC1L */ -#define WM8995_AIF2DACL_TO_DAC1L_WIDTH 1 /* AIF2DACL_TO_DAC1L */ -#define WM8995_AIF1DAC2L_TO_DAC1L 0x0002 /* AIF1DAC2L_TO_DAC1L */ -#define WM8995_AIF1DAC2L_TO_DAC1L_MASK 0x0002 /* AIF1DAC2L_TO_DAC1L */ -#define WM8995_AIF1DAC2L_TO_DAC1L_SHIFT 1 /* AIF1DAC2L_TO_DAC1L */ -#define WM8995_AIF1DAC2L_TO_DAC1L_WIDTH 1 /* AIF1DAC2L_TO_DAC1L */ -#define WM8995_AIF1DAC1L_TO_DAC1L 0x0001 /* AIF1DAC1L_TO_DAC1L */ -#define WM8995_AIF1DAC1L_TO_DAC1L_MASK 0x0001 /* AIF1DAC1L_TO_DAC1L */ -#define WM8995_AIF1DAC1L_TO_DAC1L_SHIFT 0 /* AIF1DAC1L_TO_DAC1L */ -#define WM8995_AIF1DAC1L_TO_DAC1L_WIDTH 1 /* AIF1DAC1L_TO_DAC1L */ - -/* - * R1538 (0x602) - DAC1 Right Mixer Routing - */ -#define WM8995_ADCR_TO_DAC1R 0x0020 /* ADCR_TO_DAC1R */ -#define WM8995_ADCR_TO_DAC1R_MASK 0x0020 /* ADCR_TO_DAC1R */ -#define WM8995_ADCR_TO_DAC1R_SHIFT 5 /* ADCR_TO_DAC1R */ -#define WM8995_ADCR_TO_DAC1R_WIDTH 1 /* ADCR_TO_DAC1R */ -#define WM8995_ADCL_TO_DAC1R 0x0010 /* ADCL_TO_DAC1R */ -#define WM8995_ADCL_TO_DAC1R_MASK 0x0010 /* ADCL_TO_DAC1R */ -#define WM8995_ADCL_TO_DAC1R_SHIFT 4 /* ADCL_TO_DAC1R */ -#define WM8995_ADCL_TO_DAC1R_WIDTH 1 /* ADCL_TO_DAC1R */ -#define WM8995_AIF2DACR_TO_DAC1R 0x0004 /* AIF2DACR_TO_DAC1R */ -#define WM8995_AIF2DACR_TO_DAC1R_MASK 0x0004 /* AIF2DACR_TO_DAC1R */ -#define WM8995_AIF2DACR_TO_DAC1R_SHIFT 2 /* AIF2DACR_TO_DAC1R */ -#define WM8995_AIF2DACR_TO_DAC1R_WIDTH 1 /* AIF2DACR_TO_DAC1R */ -#define WM8995_AIF1DAC2R_TO_DAC1R 0x0002 /* AIF1DAC2R_TO_DAC1R */ -#define WM8995_AIF1DAC2R_TO_DAC1R_MASK 0x0002 /* AIF1DAC2R_TO_DAC1R */ -#define WM8995_AIF1DAC2R_TO_DAC1R_SHIFT 1 /* AIF1DAC2R_TO_DAC1R */ -#define WM8995_AIF1DAC2R_TO_DAC1R_WIDTH 1 /* AIF1DAC2R_TO_DAC1R */ -#define WM8995_AIF1DAC1R_TO_DAC1R 0x0001 /* AIF1DAC1R_TO_DAC1R */ -#define WM8995_AIF1DAC1R_TO_DAC1R_MASK 0x0001 /* AIF1DAC1R_TO_DAC1R */ -#define WM8995_AIF1DAC1R_TO_DAC1R_SHIFT 0 /* AIF1DAC1R_TO_DAC1R */ -#define WM8995_AIF1DAC1R_TO_DAC1R_WIDTH 1 /* AIF1DAC1R_TO_DAC1R */ - -/* - * R1539 (0x603) - DAC2 Mixer Volumes - */ -#define WM8995_ADCR_DAC2_VOL_MASK 0x03E0 /* ADCR_DAC2_VOL - [9:5] */ -#define WM8995_ADCR_DAC2_VOL_SHIFT 5 /* ADCR_DAC2_VOL - [9:5] */ -#define WM8995_ADCR_DAC2_VOL_WIDTH 5 /* ADCR_DAC2_VOL - [9:5] */ -#define WM8995_ADCL_DAC2_VOL_MASK 0x001F /* ADCL_DAC2_VOL - [4:0] */ -#define WM8995_ADCL_DAC2_VOL_SHIFT 0 /* ADCL_DAC2_VOL - [4:0] */ -#define WM8995_ADCL_DAC2_VOL_WIDTH 5 /* ADCL_DAC2_VOL - [4:0] */ - -/* - * R1540 (0x604) - DAC2 Left Mixer Routing - */ -#define WM8995_ADCR_TO_DAC2L 0x0020 /* ADCR_TO_DAC2L */ -#define WM8995_ADCR_TO_DAC2L_MASK 0x0020 /* ADCR_TO_DAC2L */ -#define WM8995_ADCR_TO_DAC2L_SHIFT 5 /* ADCR_TO_DAC2L */ -#define WM8995_ADCR_TO_DAC2L_WIDTH 1 /* ADCR_TO_DAC2L */ -#define WM8995_ADCL_TO_DAC2L 0x0010 /* ADCL_TO_DAC2L */ -#define WM8995_ADCL_TO_DAC2L_MASK 0x0010 /* ADCL_TO_DAC2L */ -#define WM8995_ADCL_TO_DAC2L_SHIFT 4 /* ADCL_TO_DAC2L */ -#define WM8995_ADCL_TO_DAC2L_WIDTH 1 /* ADCL_TO_DAC2L */ -#define WM8995_AIF2DACL_TO_DAC2L 0x0004 /* AIF2DACL_TO_DAC2L */ -#define WM8995_AIF2DACL_TO_DAC2L_MASK 0x0004 /* AIF2DACL_TO_DAC2L */ -#define WM8995_AIF2DACL_TO_DAC2L_SHIFT 2 /* AIF2DACL_TO_DAC2L */ -#define WM8995_AIF2DACL_TO_DAC2L_WIDTH 1 /* AIF2DACL_TO_DAC2L */ -#define WM8995_AIF1DAC2L_TO_DAC2L 0x0002 /* AIF1DAC2L_TO_DAC2L */ -#define WM8995_AIF1DAC2L_TO_DAC2L_MASK 0x0002 /* AIF1DAC2L_TO_DAC2L */ -#define WM8995_AIF1DAC2L_TO_DAC2L_SHIFT 1 /* AIF1DAC2L_TO_DAC2L */ -#define WM8995_AIF1DAC2L_TO_DAC2L_WIDTH 1 /* AIF1DAC2L_TO_DAC2L */ -#define WM8995_AIF1DAC1L_TO_DAC2L 0x0001 /* AIF1DAC1L_TO_DAC2L */ -#define WM8995_AIF1DAC1L_TO_DAC2L_MASK 0x0001 /* AIF1DAC1L_TO_DAC2L */ -#define WM8995_AIF1DAC1L_TO_DAC2L_SHIFT 0 /* AIF1DAC1L_TO_DAC2L */ -#define WM8995_AIF1DAC1L_TO_DAC2L_WIDTH 1 /* AIF1DAC1L_TO_DAC2L */ - -/* - * R1541 (0x605) - DAC2 Right Mixer Routing - */ -#define WM8995_ADCR_TO_DAC2R 0x0020 /* ADCR_TO_DAC2R */ -#define WM8995_ADCR_TO_DAC2R_MASK 0x0020 /* ADCR_TO_DAC2R */ -#define WM8995_ADCR_TO_DAC2R_SHIFT 5 /* ADCR_TO_DAC2R */ -#define WM8995_ADCR_TO_DAC2R_WIDTH 1 /* ADCR_TO_DAC2R */ -#define WM8995_ADCL_TO_DAC2R 0x0010 /* ADCL_TO_DAC2R */ -#define WM8995_ADCL_TO_DAC2R_MASK 0x0010 /* ADCL_TO_DAC2R */ -#define WM8995_ADCL_TO_DAC2R_SHIFT 4 /* ADCL_TO_DAC2R */ -#define WM8995_ADCL_TO_DAC2R_WIDTH 1 /* ADCL_TO_DAC2R */ -#define WM8995_AIF2DACR_TO_DAC2R 0x0004 /* AIF2DACR_TO_DAC2R */ -#define WM8995_AIF2DACR_TO_DAC2R_MASK 0x0004 /* AIF2DACR_TO_DAC2R */ -#define WM8995_AIF2DACR_TO_DAC2R_SHIFT 2 /* AIF2DACR_TO_DAC2R */ -#define WM8995_AIF2DACR_TO_DAC2R_WIDTH 1 /* AIF2DACR_TO_DAC2R */ -#define WM8995_AIF1DAC2R_TO_DAC2R 0x0002 /* AIF1DAC2R_TO_DAC2R */ -#define WM8995_AIF1DAC2R_TO_DAC2R_MASK 0x0002 /* AIF1DAC2R_TO_DAC2R */ -#define WM8995_AIF1DAC2R_TO_DAC2R_SHIFT 1 /* AIF1DAC2R_TO_DAC2R */ -#define WM8995_AIF1DAC2R_TO_DAC2R_WIDTH 1 /* AIF1DAC2R_TO_DAC2R */ -#define WM8995_AIF1DAC1R_TO_DAC2R 0x0001 /* AIF1DAC1R_TO_DAC2R */ -#define WM8995_AIF1DAC1R_TO_DAC2R_MASK 0x0001 /* AIF1DAC1R_TO_DAC2R */ -#define WM8995_AIF1DAC1R_TO_DAC2R_SHIFT 0 /* AIF1DAC1R_TO_DAC2R */ -#define WM8995_AIF1DAC1R_TO_DAC2R_WIDTH 1 /* AIF1DAC1R_TO_DAC2R */ - -/* - * R1542 (0x606) - AIF1 ADC1 Left Mixer Routing - */ -#define WM8995_ADC1L_TO_AIF1ADC1L 0x0002 /* ADC1L_TO_AIF1ADC1L */ -#define WM8995_ADC1L_TO_AIF1ADC1L_MASK 0x0002 /* ADC1L_TO_AIF1ADC1L */ -#define WM8995_ADC1L_TO_AIF1ADC1L_SHIFT 1 /* ADC1L_TO_AIF1ADC1L */ -#define WM8995_ADC1L_TO_AIF1ADC1L_WIDTH 1 /* ADC1L_TO_AIF1ADC1L */ -#define WM8995_AIF2DACL_TO_AIF1ADC1L 0x0001 /* AIF2DACL_TO_AIF1ADC1L */ -#define WM8995_AIF2DACL_TO_AIF1ADC1L_MASK 0x0001 /* AIF2DACL_TO_AIF1ADC1L */ -#define WM8995_AIF2DACL_TO_AIF1ADC1L_SHIFT 0 /* AIF2DACL_TO_AIF1ADC1L */ -#define WM8995_AIF2DACL_TO_AIF1ADC1L_WIDTH 1 /* AIF2DACL_TO_AIF1ADC1L */ - -/* - * R1543 (0x607) - AIF1 ADC1 Right Mixer Routing - */ -#define WM8995_ADC1R_TO_AIF1ADC1R 0x0002 /* ADC1R_TO_AIF1ADC1R */ -#define WM8995_ADC1R_TO_AIF1ADC1R_MASK 0x0002 /* ADC1R_TO_AIF1ADC1R */ -#define WM8995_ADC1R_TO_AIF1ADC1R_SHIFT 1 /* ADC1R_TO_AIF1ADC1R */ -#define WM8995_ADC1R_TO_AIF1ADC1R_WIDTH 1 /* ADC1R_TO_AIF1ADC1R */ -#define WM8995_AIF2DACR_TO_AIF1ADC1R 0x0001 /* AIF2DACR_TO_AIF1ADC1R */ -#define WM8995_AIF2DACR_TO_AIF1ADC1R_MASK 0x0001 /* AIF2DACR_TO_AIF1ADC1R */ -#define WM8995_AIF2DACR_TO_AIF1ADC1R_SHIFT 0 /* AIF2DACR_TO_AIF1ADC1R */ -#define WM8995_AIF2DACR_TO_AIF1ADC1R_WIDTH 1 /* AIF2DACR_TO_AIF1ADC1R */ - -/* - * R1544 (0x608) - AIF1 ADC2 Left Mixer Routing - */ -#define WM8995_ADC2L_TO_AIF1ADC2L 0x0002 /* ADC2L_TO_AIF1ADC2L */ -#define WM8995_ADC2L_TO_AIF1ADC2L_MASK 0x0002 /* ADC2L_TO_AIF1ADC2L */ -#define WM8995_ADC2L_TO_AIF1ADC2L_SHIFT 1 /* ADC2L_TO_AIF1ADC2L */ -#define WM8995_ADC2L_TO_AIF1ADC2L_WIDTH 1 /* ADC2L_TO_AIF1ADC2L */ -#define WM8995_AIF2DACL_TO_AIF1ADC2L 0x0001 /* AIF2DACL_TO_AIF1ADC2L */ -#define WM8995_AIF2DACL_TO_AIF1ADC2L_MASK 0x0001 /* AIF2DACL_TO_AIF1ADC2L */ -#define WM8995_AIF2DACL_TO_AIF1ADC2L_SHIFT 0 /* AIF2DACL_TO_AIF1ADC2L */ -#define WM8995_AIF2DACL_TO_AIF1ADC2L_WIDTH 1 /* AIF2DACL_TO_AIF1ADC2L */ - -/* - * R1545 (0x609) - AIF1 ADC2 Right mixer Routing - */ -#define WM8995_ADC2R_TO_AIF1ADC2R 0x0002 /* ADC2R_TO_AIF1ADC2R */ -#define WM8995_ADC2R_TO_AIF1ADC2R_MASK 0x0002 /* ADC2R_TO_AIF1ADC2R */ -#define WM8995_ADC2R_TO_AIF1ADC2R_SHIFT 1 /* ADC2R_TO_AIF1ADC2R */ -#define WM8995_ADC2R_TO_AIF1ADC2R_WIDTH 1 /* ADC2R_TO_AIF1ADC2R */ -#define WM8995_AIF2DACR_TO_AIF1ADC2R 0x0001 /* AIF2DACR_TO_AIF1ADC2R */ -#define WM8995_AIF2DACR_TO_AIF1ADC2R_MASK 0x0001 /* AIF2DACR_TO_AIF1ADC2R */ -#define WM8995_AIF2DACR_TO_AIF1ADC2R_SHIFT 0 /* AIF2DACR_TO_AIF1ADC2R */ -#define WM8995_AIF2DACR_TO_AIF1ADC2R_WIDTH 1 /* AIF2DACR_TO_AIF1ADC2R */ - -/* - * R1552 (0x610) - DAC Softmute - */ -#define WM8995_DAC_SOFTMUTEMODE 0x0002 /* DAC_SOFTMUTEMODE */ -#define WM8995_DAC_SOFTMUTEMODE_MASK 0x0002 /* DAC_SOFTMUTEMODE */ -#define WM8995_DAC_SOFTMUTEMODE_SHIFT 1 /* DAC_SOFTMUTEMODE */ -#define WM8995_DAC_SOFTMUTEMODE_WIDTH 1 /* DAC_SOFTMUTEMODE */ -#define WM8995_DAC_MUTERATE 0x0001 /* DAC_MUTERATE */ -#define WM8995_DAC_MUTERATE_MASK 0x0001 /* DAC_MUTERATE */ -#define WM8995_DAC_MUTERATE_SHIFT 0 /* DAC_MUTERATE */ -#define WM8995_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ - -/* - * R1568 (0x620) - Oversampling - */ -#define WM8995_ADC_OSR128 0x0002 /* ADC_OSR128 */ -#define WM8995_ADC_OSR128_MASK 0x0002 /* ADC_OSR128 */ -#define WM8995_ADC_OSR128_SHIFT 1 /* ADC_OSR128 */ -#define WM8995_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ -#define WM8995_DAC_OSR128 0x0001 /* DAC_OSR128 */ -#define WM8995_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */ -#define WM8995_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */ -#define WM8995_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ - -/* - * R1569 (0x621) - Sidetone - */ -#define WM8995_ST_LPF 0x1000 /* ST_LPF */ -#define WM8995_ST_LPF_MASK 0x1000 /* ST_LPF */ -#define WM8995_ST_LPF_SHIFT 12 /* ST_LPF */ -#define WM8995_ST_LPF_WIDTH 1 /* ST_LPF */ -#define WM8995_ST_HPF_CUT_MASK 0x0380 /* ST_HPF_CUT - [9:7] */ -#define WM8995_ST_HPF_CUT_SHIFT 7 /* ST_HPF_CUT - [9:7] */ -#define WM8995_ST_HPF_CUT_WIDTH 3 /* ST_HPF_CUT - [9:7] */ -#define WM8995_ST_HPF 0x0040 /* ST_HPF */ -#define WM8995_ST_HPF_MASK 0x0040 /* ST_HPF */ -#define WM8995_ST_HPF_SHIFT 6 /* ST_HPF */ -#define WM8995_ST_HPF_WIDTH 1 /* ST_HPF */ -#define WM8995_STR_SEL 0x0002 /* STR_SEL */ -#define WM8995_STR_SEL_MASK 0x0002 /* STR_SEL */ -#define WM8995_STR_SEL_SHIFT 1 /* STR_SEL */ -#define WM8995_STR_SEL_WIDTH 1 /* STR_SEL */ -#define WM8995_STL_SEL 0x0001 /* STL_SEL */ -#define WM8995_STL_SEL_MASK 0x0001 /* STL_SEL */ -#define WM8995_STL_SEL_SHIFT 0 /* STL_SEL */ -#define WM8995_STL_SEL_WIDTH 1 /* STL_SEL */ - -/* - * R1792 (0x700) - GPIO 1 - */ -#define WM8995_GP1_DIR 0x8000 /* GP1_DIR */ -#define WM8995_GP1_DIR_MASK 0x8000 /* GP1_DIR */ -#define WM8995_GP1_DIR_SHIFT 15 /* GP1_DIR */ -#define WM8995_GP1_DIR_WIDTH 1 /* GP1_DIR */ -#define WM8995_GP1_PU 0x4000 /* GP1_PU */ -#define WM8995_GP1_PU_MASK 0x4000 /* GP1_PU */ -#define WM8995_GP1_PU_SHIFT 14 /* GP1_PU */ -#define WM8995_GP1_PU_WIDTH 1 /* GP1_PU */ -#define WM8995_GP1_PD 0x2000 /* GP1_PD */ -#define WM8995_GP1_PD_MASK 0x2000 /* GP1_PD */ -#define WM8995_GP1_PD_SHIFT 13 /* GP1_PD */ -#define WM8995_GP1_PD_WIDTH 1 /* GP1_PD */ -#define WM8995_GP1_POL 0x0400 /* GP1_POL */ -#define WM8995_GP1_POL_MASK 0x0400 /* GP1_POL */ -#define WM8995_GP1_POL_SHIFT 10 /* GP1_POL */ -#define WM8995_GP1_POL_WIDTH 1 /* GP1_POL */ -#define WM8995_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */ -#define WM8995_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */ -#define WM8995_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */ -#define WM8995_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */ -#define WM8995_GP1_DB 0x0100 /* GP1_DB */ -#define WM8995_GP1_DB_MASK 0x0100 /* GP1_DB */ -#define WM8995_GP1_DB_SHIFT 8 /* GP1_DB */ -#define WM8995_GP1_DB_WIDTH 1 /* GP1_DB */ -#define WM8995_GP1_LVL 0x0040 /* GP1_LVL */ -#define WM8995_GP1_LVL_MASK 0x0040 /* GP1_LVL */ -#define WM8995_GP1_LVL_SHIFT 6 /* GP1_LVL */ -#define WM8995_GP1_LVL_WIDTH 1 /* GP1_LVL */ -#define WM8995_GP1_FN_MASK 0x001F /* GP1_FN - [4:0] */ -#define WM8995_GP1_FN_SHIFT 0 /* GP1_FN - [4:0] */ -#define WM8995_GP1_FN_WIDTH 5 /* GP1_FN - [4:0] */ - -/* - * R1793 (0x701) - GPIO 2 - */ -#define WM8995_GP2_DIR 0x8000 /* GP2_DIR */ -#define WM8995_GP2_DIR_MASK 0x8000 /* GP2_DIR */ -#define WM8995_GP2_DIR_SHIFT 15 /* GP2_DIR */ -#define WM8995_GP2_DIR_WIDTH 1 /* GP2_DIR */ -#define WM8995_GP2_PU 0x4000 /* GP2_PU */ -#define WM8995_GP2_PU_MASK 0x4000 /* GP2_PU */ -#define WM8995_GP2_PU_SHIFT 14 /* GP2_PU */ -#define WM8995_GP2_PU_WIDTH 1 /* GP2_PU */ -#define WM8995_GP2_PD 0x2000 /* GP2_PD */ -#define WM8995_GP2_PD_MASK 0x2000 /* GP2_PD */ -#define WM8995_GP2_PD_SHIFT 13 /* GP2_PD */ -#define WM8995_GP2_PD_WIDTH 1 /* GP2_PD */ -#define WM8995_GP2_POL 0x0400 /* GP2_POL */ -#define WM8995_GP2_POL_MASK 0x0400 /* GP2_POL */ -#define WM8995_GP2_POL_SHIFT 10 /* GP2_POL */ -#define WM8995_GP2_POL_WIDTH 1 /* GP2_POL */ -#define WM8995_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */ -#define WM8995_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */ -#define WM8995_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */ -#define WM8995_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */ -#define WM8995_GP2_DB 0x0100 /* GP2_DB */ -#define WM8995_GP2_DB_MASK 0x0100 /* GP2_DB */ -#define WM8995_GP2_DB_SHIFT 8 /* GP2_DB */ -#define WM8995_GP2_DB_WIDTH 1 /* GP2_DB */ -#define WM8995_GP2_LVL 0x0040 /* GP2_LVL */ -#define WM8995_GP2_LVL_MASK 0x0040 /* GP2_LVL */ -#define WM8995_GP2_LVL_SHIFT 6 /* GP2_LVL */ -#define WM8995_GP2_LVL_WIDTH 1 /* GP2_LVL */ -#define WM8995_GP2_FN_MASK 0x001F /* GP2_FN - [4:0] */ -#define WM8995_GP2_FN_SHIFT 0 /* GP2_FN - [4:0] */ -#define WM8995_GP2_FN_WIDTH 5 /* GP2_FN - [4:0] */ - -/* - * R1794 (0x702) - GPIO 3 - */ -#define WM8995_GP3_DIR 0x8000 /* GP3_DIR */ -#define WM8995_GP3_DIR_MASK 0x8000 /* GP3_DIR */ -#define WM8995_GP3_DIR_SHIFT 15 /* GP3_DIR */ -#define WM8995_GP3_DIR_WIDTH 1 /* GP3_DIR */ -#define WM8995_GP3_PU 0x4000 /* GP3_PU */ -#define WM8995_GP3_PU_MASK 0x4000 /* GP3_PU */ -#define WM8995_GP3_PU_SHIFT 14 /* GP3_PU */ -#define WM8995_GP3_PU_WIDTH 1 /* GP3_PU */ -#define WM8995_GP3_PD 0x2000 /* GP3_PD */ -#define WM8995_GP3_PD_MASK 0x2000 /* GP3_PD */ -#define WM8995_GP3_PD_SHIFT 13 /* GP3_PD */ -#define WM8995_GP3_PD_WIDTH 1 /* GP3_PD */ -#define WM8995_GP3_POL 0x0400 /* GP3_POL */ -#define WM8995_GP3_POL_MASK 0x0400 /* GP3_POL */ -#define WM8995_GP3_POL_SHIFT 10 /* GP3_POL */ -#define WM8995_GP3_POL_WIDTH 1 /* GP3_POL */ -#define WM8995_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */ -#define WM8995_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */ -#define WM8995_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */ -#define WM8995_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */ -#define WM8995_GP3_DB 0x0100 /* GP3_DB */ -#define WM8995_GP3_DB_MASK 0x0100 /* GP3_DB */ -#define WM8995_GP3_DB_SHIFT 8 /* GP3_DB */ -#define WM8995_GP3_DB_WIDTH 1 /* GP3_DB */ -#define WM8995_GP3_LVL 0x0040 /* GP3_LVL */ -#define WM8995_GP3_LVL_MASK 0x0040 /* GP3_LVL */ -#define WM8995_GP3_LVL_SHIFT 6 /* GP3_LVL */ -#define WM8995_GP3_LVL_WIDTH 1 /* GP3_LVL */ -#define WM8995_GP3_FN_MASK 0x001F /* GP3_FN - [4:0] */ -#define WM8995_GP3_FN_SHIFT 0 /* GP3_FN - [4:0] */ -#define WM8995_GP3_FN_WIDTH 5 /* GP3_FN - [4:0] */ - -/* - * R1795 (0x703) - GPIO 4 - */ -#define WM8995_GP4_DIR 0x8000 /* GP4_DIR */ -#define WM8995_GP4_DIR_MASK 0x8000 /* GP4_DIR */ -#define WM8995_GP4_DIR_SHIFT 15 /* GP4_DIR */ -#define WM8995_GP4_DIR_WIDTH 1 /* GP4_DIR */ -#define WM8995_GP4_PU 0x4000 /* GP4_PU */ -#define WM8995_GP4_PU_MASK 0x4000 /* GP4_PU */ -#define WM8995_GP4_PU_SHIFT 14 /* GP4_PU */ -#define WM8995_GP4_PU_WIDTH 1 /* GP4_PU */ -#define WM8995_GP4_PD 0x2000 /* GP4_PD */ -#define WM8995_GP4_PD_MASK 0x2000 /* GP4_PD */ -#define WM8995_GP4_PD_SHIFT 13 /* GP4_PD */ -#define WM8995_GP4_PD_WIDTH 1 /* GP4_PD */ -#define WM8995_GP4_POL 0x0400 /* GP4_POL */ -#define WM8995_GP4_POL_MASK 0x0400 /* GP4_POL */ -#define WM8995_GP4_POL_SHIFT 10 /* GP4_POL */ -#define WM8995_GP4_POL_WIDTH 1 /* GP4_POL */ -#define WM8995_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */ -#define WM8995_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */ -#define WM8995_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */ -#define WM8995_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */ -#define WM8995_GP4_DB 0x0100 /* GP4_DB */ -#define WM8995_GP4_DB_MASK 0x0100 /* GP4_DB */ -#define WM8995_GP4_DB_SHIFT 8 /* GP4_DB */ -#define WM8995_GP4_DB_WIDTH 1 /* GP4_DB */ -#define WM8995_GP4_LVL 0x0040 /* GP4_LVL */ -#define WM8995_GP4_LVL_MASK 0x0040 /* GP4_LVL */ -#define WM8995_GP4_LVL_SHIFT 6 /* GP4_LVL */ -#define WM8995_GP4_LVL_WIDTH 1 /* GP4_LVL */ -#define WM8995_GP4_FN_MASK 0x001F /* GP4_FN - [4:0] */ -#define WM8995_GP4_FN_SHIFT 0 /* GP4_FN - [4:0] */ -#define WM8995_GP4_FN_WIDTH 5 /* GP4_FN - [4:0] */ - -/* - * R1796 (0x704) - GPIO 5 - */ -#define WM8995_GP5_DIR 0x8000 /* GP5_DIR */ -#define WM8995_GP5_DIR_MASK 0x8000 /* GP5_DIR */ -#define WM8995_GP5_DIR_SHIFT 15 /* GP5_DIR */ -#define WM8995_GP5_DIR_WIDTH 1 /* GP5_DIR */ -#define WM8995_GP5_PU 0x4000 /* GP5_PU */ -#define WM8995_GP5_PU_MASK 0x4000 /* GP5_PU */ -#define WM8995_GP5_PU_SHIFT 14 /* GP5_PU */ -#define WM8995_GP5_PU_WIDTH 1 /* GP5_PU */ -#define WM8995_GP5_PD 0x2000 /* GP5_PD */ -#define WM8995_GP5_PD_MASK 0x2000 /* GP5_PD */ -#define WM8995_GP5_PD_SHIFT 13 /* GP5_PD */ -#define WM8995_GP5_PD_WIDTH 1 /* GP5_PD */ -#define WM8995_GP5_POL 0x0400 /* GP5_POL */ -#define WM8995_GP5_POL_MASK 0x0400 /* GP5_POL */ -#define WM8995_GP5_POL_SHIFT 10 /* GP5_POL */ -#define WM8995_GP5_POL_WIDTH 1 /* GP5_POL */ -#define WM8995_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */ -#define WM8995_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */ -#define WM8995_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */ -#define WM8995_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */ -#define WM8995_GP5_DB 0x0100 /* GP5_DB */ -#define WM8995_GP5_DB_MASK 0x0100 /* GP5_DB */ -#define WM8995_GP5_DB_SHIFT 8 /* GP5_DB */ -#define WM8995_GP5_DB_WIDTH 1 /* GP5_DB */ -#define WM8995_GP5_LVL 0x0040 /* GP5_LVL */ -#define WM8995_GP5_LVL_MASK 0x0040 /* GP5_LVL */ -#define WM8995_GP5_LVL_SHIFT 6 /* GP5_LVL */ -#define WM8995_GP5_LVL_WIDTH 1 /* GP5_LVL */ -#define WM8995_GP5_FN_MASK 0x001F /* GP5_FN - [4:0] */ -#define WM8995_GP5_FN_SHIFT 0 /* GP5_FN - [4:0] */ -#define WM8995_GP5_FN_WIDTH 5 /* GP5_FN - [4:0] */ - -/* - * R1797 (0x705) - GPIO 6 - */ -#define WM8995_GP6_DIR 0x8000 /* GP6_DIR */ -#define WM8995_GP6_DIR_MASK 0x8000 /* GP6_DIR */ -#define WM8995_GP6_DIR_SHIFT 15 /* GP6_DIR */ -#define WM8995_GP6_DIR_WIDTH 1 /* GP6_DIR */ -#define WM8995_GP6_PU 0x4000 /* GP6_PU */ -#define WM8995_GP6_PU_MASK 0x4000 /* GP6_PU */ -#define WM8995_GP6_PU_SHIFT 14 /* GP6_PU */ -#define WM8995_GP6_PU_WIDTH 1 /* GP6_PU */ -#define WM8995_GP6_PD 0x2000 /* GP6_PD */ -#define WM8995_GP6_PD_MASK 0x2000 /* GP6_PD */ -#define WM8995_GP6_PD_SHIFT 13 /* GP6_PD */ -#define WM8995_GP6_PD_WIDTH 1 /* GP6_PD */ -#define WM8995_GP6_POL 0x0400 /* GP6_POL */ -#define WM8995_GP6_POL_MASK 0x0400 /* GP6_POL */ -#define WM8995_GP6_POL_SHIFT 10 /* GP6_POL */ -#define WM8995_GP6_POL_WIDTH 1 /* GP6_POL */ -#define WM8995_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */ -#define WM8995_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */ -#define WM8995_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */ -#define WM8995_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */ -#define WM8995_GP6_DB 0x0100 /* GP6_DB */ -#define WM8995_GP6_DB_MASK 0x0100 /* GP6_DB */ -#define WM8995_GP6_DB_SHIFT 8 /* GP6_DB */ -#define WM8995_GP6_DB_WIDTH 1 /* GP6_DB */ -#define WM8995_GP6_LVL 0x0040 /* GP6_LVL */ -#define WM8995_GP6_LVL_MASK 0x0040 /* GP6_LVL */ -#define WM8995_GP6_LVL_SHIFT 6 /* GP6_LVL */ -#define WM8995_GP6_LVL_WIDTH 1 /* GP6_LVL */ -#define WM8995_GP6_FN_MASK 0x001F /* GP6_FN - [4:0] */ -#define WM8995_GP6_FN_SHIFT 0 /* GP6_FN - [4:0] */ -#define WM8995_GP6_FN_WIDTH 5 /* GP6_FN - [4:0] */ - -/* - * R1798 (0x706) - GPIO 7 - */ -#define WM8995_GP7_DIR 0x8000 /* GP7_DIR */ -#define WM8995_GP7_DIR_MASK 0x8000 /* GP7_DIR */ -#define WM8995_GP7_DIR_SHIFT 15 /* GP7_DIR */ -#define WM8995_GP7_DIR_WIDTH 1 /* GP7_DIR */ -#define WM8995_GP7_PU 0x4000 /* GP7_PU */ -#define WM8995_GP7_PU_MASK 0x4000 /* GP7_PU */ -#define WM8995_GP7_PU_SHIFT 14 /* GP7_PU */ -#define WM8995_GP7_PU_WIDTH 1 /* GP7_PU */ -#define WM8995_GP7_PD 0x2000 /* GP7_PD */ -#define WM8995_GP7_PD_MASK 0x2000 /* GP7_PD */ -#define WM8995_GP7_PD_SHIFT 13 /* GP7_PD */ -#define WM8995_GP7_PD_WIDTH 1 /* GP7_PD */ -#define WM8995_GP7_POL 0x0400 /* GP7_POL */ -#define WM8995_GP7_POL_MASK 0x0400 /* GP7_POL */ -#define WM8995_GP7_POL_SHIFT 10 /* GP7_POL */ -#define WM8995_GP7_POL_WIDTH 1 /* GP7_POL */ -#define WM8995_GP7_OP_CFG 0x0200 /* GP7_OP_CFG */ -#define WM8995_GP7_OP_CFG_MASK 0x0200 /* GP7_OP_CFG */ -#define WM8995_GP7_OP_CFG_SHIFT 9 /* GP7_OP_CFG */ -#define WM8995_GP7_OP_CFG_WIDTH 1 /* GP7_OP_CFG */ -#define WM8995_GP7_DB 0x0100 /* GP7_DB */ -#define WM8995_GP7_DB_MASK 0x0100 /* GP7_DB */ -#define WM8995_GP7_DB_SHIFT 8 /* GP7_DB */ -#define WM8995_GP7_DB_WIDTH 1 /* GP7_DB */ -#define WM8995_GP7_LVL 0x0040 /* GP7_LVL */ -#define WM8995_GP7_LVL_MASK 0x0040 /* GP7_LVL */ -#define WM8995_GP7_LVL_SHIFT 6 /* GP7_LVL */ -#define WM8995_GP7_LVL_WIDTH 1 /* GP7_LVL */ -#define WM8995_GP7_FN_MASK 0x001F /* GP7_FN - [4:0] */ -#define WM8995_GP7_FN_SHIFT 0 /* GP7_FN - [4:0] */ -#define WM8995_GP7_FN_WIDTH 5 /* GP7_FN - [4:0] */ - -/* - * R1799 (0x707) - GPIO 8 - */ -#define WM8995_GP8_DIR 0x8000 /* GP8_DIR */ -#define WM8995_GP8_DIR_MASK 0x8000 /* GP8_DIR */ -#define WM8995_GP8_DIR_SHIFT 15 /* GP8_DIR */ -#define WM8995_GP8_DIR_WIDTH 1 /* GP8_DIR */ -#define WM8995_GP8_PU 0x4000 /* GP8_PU */ -#define WM8995_GP8_PU_MASK 0x4000 /* GP8_PU */ -#define WM8995_GP8_PU_SHIFT 14 /* GP8_PU */ -#define WM8995_GP8_PU_WIDTH 1 /* GP8_PU */ -#define WM8995_GP8_PD 0x2000 /* GP8_PD */ -#define WM8995_GP8_PD_MASK 0x2000 /* GP8_PD */ -#define WM8995_GP8_PD_SHIFT 13 /* GP8_PD */ -#define WM8995_GP8_PD_WIDTH 1 /* GP8_PD */ -#define WM8995_GP8_POL 0x0400 /* GP8_POL */ -#define WM8995_GP8_POL_MASK 0x0400 /* GP8_POL */ -#define WM8995_GP8_POL_SHIFT 10 /* GP8_POL */ -#define WM8995_GP8_POL_WIDTH 1 /* GP8_POL */ -#define WM8995_GP8_OP_CFG 0x0200 /* GP8_OP_CFG */ -#define WM8995_GP8_OP_CFG_MASK 0x0200 /* GP8_OP_CFG */ -#define WM8995_GP8_OP_CFG_SHIFT 9 /* GP8_OP_CFG */ -#define WM8995_GP8_OP_CFG_WIDTH 1 /* GP8_OP_CFG */ -#define WM8995_GP8_DB 0x0100 /* GP8_DB */ -#define WM8995_GP8_DB_MASK 0x0100 /* GP8_DB */ -#define WM8995_GP8_DB_SHIFT 8 /* GP8_DB */ -#define WM8995_GP8_DB_WIDTH 1 /* GP8_DB */ -#define WM8995_GP8_LVL 0x0040 /* GP8_LVL */ -#define WM8995_GP8_LVL_MASK 0x0040 /* GP8_LVL */ -#define WM8995_GP8_LVL_SHIFT 6 /* GP8_LVL */ -#define WM8995_GP8_LVL_WIDTH 1 /* GP8_LVL */ -#define WM8995_GP8_FN_MASK 0x001F /* GP8_FN - [4:0] */ -#define WM8995_GP8_FN_SHIFT 0 /* GP8_FN - [4:0] */ -#define WM8995_GP8_FN_WIDTH 5 /* GP8_FN - [4:0] */ - -/* - * R1800 (0x708) - GPIO 9 - */ -#define WM8995_GP9_DIR 0x8000 /* GP9_DIR */ -#define WM8995_GP9_DIR_MASK 0x8000 /* GP9_DIR */ -#define WM8995_GP9_DIR_SHIFT 15 /* GP9_DIR */ -#define WM8995_GP9_DIR_WIDTH 1 /* GP9_DIR */ -#define WM8995_GP9_PU 0x4000 /* GP9_PU */ -#define WM8995_GP9_PU_MASK 0x4000 /* GP9_PU */ -#define WM8995_GP9_PU_SHIFT 14 /* GP9_PU */ -#define WM8995_GP9_PU_WIDTH 1 /* GP9_PU */ -#define WM8995_GP9_PD 0x2000 /* GP9_PD */ -#define WM8995_GP9_PD_MASK 0x2000 /* GP9_PD */ -#define WM8995_GP9_PD_SHIFT 13 /* GP9_PD */ -#define WM8995_GP9_PD_WIDTH 1 /* GP9_PD */ -#define WM8995_GP9_POL 0x0400 /* GP9_POL */ -#define WM8995_GP9_POL_MASK 0x0400 /* GP9_POL */ -#define WM8995_GP9_POL_SHIFT 10 /* GP9_POL */ -#define WM8995_GP9_POL_WIDTH 1 /* GP9_POL */ -#define WM8995_GP9_OP_CFG 0x0200 /* GP9_OP_CFG */ -#define WM8995_GP9_OP_CFG_MASK 0x0200 /* GP9_OP_CFG */ -#define WM8995_GP9_OP_CFG_SHIFT 9 /* GP9_OP_CFG */ -#define WM8995_GP9_OP_CFG_WIDTH 1 /* GP9_OP_CFG */ -#define WM8995_GP9_DB 0x0100 /* GP9_DB */ -#define WM8995_GP9_DB_MASK 0x0100 /* GP9_DB */ -#define WM8995_GP9_DB_SHIFT 8 /* GP9_DB */ -#define WM8995_GP9_DB_WIDTH 1 /* GP9_DB */ -#define WM8995_GP9_LVL 0x0040 /* GP9_LVL */ -#define WM8995_GP9_LVL_MASK 0x0040 /* GP9_LVL */ -#define WM8995_GP9_LVL_SHIFT 6 /* GP9_LVL */ -#define WM8995_GP9_LVL_WIDTH 1 /* GP9_LVL */ -#define WM8995_GP9_FN_MASK 0x001F /* GP9_FN - [4:0] */ -#define WM8995_GP9_FN_SHIFT 0 /* GP9_FN - [4:0] */ -#define WM8995_GP9_FN_WIDTH 5 /* GP9_FN - [4:0] */ - -/* - * R1801 (0x709) - GPIO 10 - */ -#define WM8995_GP10_DIR 0x8000 /* GP10_DIR */ -#define WM8995_GP10_DIR_MASK 0x8000 /* GP10_DIR */ -#define WM8995_GP10_DIR_SHIFT 15 /* GP10_DIR */ -#define WM8995_GP10_DIR_WIDTH 1 /* GP10_DIR */ -#define WM8995_GP10_PU 0x4000 /* GP10_PU */ -#define WM8995_GP10_PU_MASK 0x4000 /* GP10_PU */ -#define WM8995_GP10_PU_SHIFT 14 /* GP10_PU */ -#define WM8995_GP10_PU_WIDTH 1 /* GP10_PU */ -#define WM8995_GP10_PD 0x2000 /* GP10_PD */ -#define WM8995_GP10_PD_MASK 0x2000 /* GP10_PD */ -#define WM8995_GP10_PD_SHIFT 13 /* GP10_PD */ -#define WM8995_GP10_PD_WIDTH 1 /* GP10_PD */ -#define WM8995_GP10_POL 0x0400 /* GP10_POL */ -#define WM8995_GP10_POL_MASK 0x0400 /* GP10_POL */ -#define WM8995_GP10_POL_SHIFT 10 /* GP10_POL */ -#define WM8995_GP10_POL_WIDTH 1 /* GP10_POL */ -#define WM8995_GP10_OP_CFG 0x0200 /* GP10_OP_CFG */ -#define WM8995_GP10_OP_CFG_MASK 0x0200 /* GP10_OP_CFG */ -#define WM8995_GP10_OP_CFG_SHIFT 9 /* GP10_OP_CFG */ -#define WM8995_GP10_OP_CFG_WIDTH 1 /* GP10_OP_CFG */ -#define WM8995_GP10_DB 0x0100 /* GP10_DB */ -#define WM8995_GP10_DB_MASK 0x0100 /* GP10_DB */ -#define WM8995_GP10_DB_SHIFT 8 /* GP10_DB */ -#define WM8995_GP10_DB_WIDTH 1 /* GP10_DB */ -#define WM8995_GP10_LVL 0x0040 /* GP10_LVL */ -#define WM8995_GP10_LVL_MASK 0x0040 /* GP10_LVL */ -#define WM8995_GP10_LVL_SHIFT 6 /* GP10_LVL */ -#define WM8995_GP10_LVL_WIDTH 1 /* GP10_LVL */ -#define WM8995_GP10_FN_MASK 0x001F /* GP10_FN - [4:0] */ -#define WM8995_GP10_FN_SHIFT 0 /* GP10_FN - [4:0] */ -#define WM8995_GP10_FN_WIDTH 5 /* GP10_FN - [4:0] */ - -/* - * R1802 (0x70A) - GPIO 11 - */ -#define WM8995_GP11_DIR 0x8000 /* GP11_DIR */ -#define WM8995_GP11_DIR_MASK 0x8000 /* GP11_DIR */ -#define WM8995_GP11_DIR_SHIFT 15 /* GP11_DIR */ -#define WM8995_GP11_DIR_WIDTH 1 /* GP11_DIR */ -#define WM8995_GP11_PU 0x4000 /* GP11_PU */ -#define WM8995_GP11_PU_MASK 0x4000 /* GP11_PU */ -#define WM8995_GP11_PU_SHIFT 14 /* GP11_PU */ -#define WM8995_GP11_PU_WIDTH 1 /* GP11_PU */ -#define WM8995_GP11_PD 0x2000 /* GP11_PD */ -#define WM8995_GP11_PD_MASK 0x2000 /* GP11_PD */ -#define WM8995_GP11_PD_SHIFT 13 /* GP11_PD */ -#define WM8995_GP11_PD_WIDTH 1 /* GP11_PD */ -#define WM8995_GP11_POL 0x0400 /* GP11_POL */ -#define WM8995_GP11_POL_MASK 0x0400 /* GP11_POL */ -#define WM8995_GP11_POL_SHIFT 10 /* GP11_POL */ -#define WM8995_GP11_POL_WIDTH 1 /* GP11_POL */ -#define WM8995_GP11_OP_CFG 0x0200 /* GP11_OP_CFG */ -#define WM8995_GP11_OP_CFG_MASK 0x0200 /* GP11_OP_CFG */ -#define WM8995_GP11_OP_CFG_SHIFT 9 /* GP11_OP_CFG */ -#define WM8995_GP11_OP_CFG_WIDTH 1 /* GP11_OP_CFG */ -#define WM8995_GP11_DB 0x0100 /* GP11_DB */ -#define WM8995_GP11_DB_MASK 0x0100 /* GP11_DB */ -#define WM8995_GP11_DB_SHIFT 8 /* GP11_DB */ -#define WM8995_GP11_DB_WIDTH 1 /* GP11_DB */ -#define WM8995_GP11_LVL 0x0040 /* GP11_LVL */ -#define WM8995_GP11_LVL_MASK 0x0040 /* GP11_LVL */ -#define WM8995_GP11_LVL_SHIFT 6 /* GP11_LVL */ -#define WM8995_GP11_LVL_WIDTH 1 /* GP11_LVL */ -#define WM8995_GP11_FN_MASK 0x001F /* GP11_FN - [4:0] */ -#define WM8995_GP11_FN_SHIFT 0 /* GP11_FN - [4:0] */ -#define WM8995_GP11_FN_WIDTH 5 /* GP11_FN - [4:0] */ - -/* - * R1803 (0x70B) - GPIO 12 - */ -#define WM8995_GP12_DIR 0x8000 /* GP12_DIR */ -#define WM8995_GP12_DIR_MASK 0x8000 /* GP12_DIR */ -#define WM8995_GP12_DIR_SHIFT 15 /* GP12_DIR */ -#define WM8995_GP12_DIR_WIDTH 1 /* GP12_DIR */ -#define WM8995_GP12_PU 0x4000 /* GP12_PU */ -#define WM8995_GP12_PU_MASK 0x4000 /* GP12_PU */ -#define WM8995_GP12_PU_SHIFT 14 /* GP12_PU */ -#define WM8995_GP12_PU_WIDTH 1 /* GP12_PU */ -#define WM8995_GP12_PD 0x2000 /* GP12_PD */ -#define WM8995_GP12_PD_MASK 0x2000 /* GP12_PD */ -#define WM8995_GP12_PD_SHIFT 13 /* GP12_PD */ -#define WM8995_GP12_PD_WIDTH 1 /* GP12_PD */ -#define WM8995_GP12_POL 0x0400 /* GP12_POL */ -#define WM8995_GP12_POL_MASK 0x0400 /* GP12_POL */ -#define WM8995_GP12_POL_SHIFT 10 /* GP12_POL */ -#define WM8995_GP12_POL_WIDTH 1 /* GP12_POL */ -#define WM8995_GP12_OP_CFG 0x0200 /* GP12_OP_CFG */ -#define WM8995_GP12_OP_CFG_MASK 0x0200 /* GP12_OP_CFG */ -#define WM8995_GP12_OP_CFG_SHIFT 9 /* GP12_OP_CFG */ -#define WM8995_GP12_OP_CFG_WIDTH 1 /* GP12_OP_CFG */ -#define WM8995_GP12_DB 0x0100 /* GP12_DB */ -#define WM8995_GP12_DB_MASK 0x0100 /* GP12_DB */ -#define WM8995_GP12_DB_SHIFT 8 /* GP12_DB */ -#define WM8995_GP12_DB_WIDTH 1 /* GP12_DB */ -#define WM8995_GP12_LVL 0x0040 /* GP12_LVL */ -#define WM8995_GP12_LVL_MASK 0x0040 /* GP12_LVL */ -#define WM8995_GP12_LVL_SHIFT 6 /* GP12_LVL */ -#define WM8995_GP12_LVL_WIDTH 1 /* GP12_LVL */ -#define WM8995_GP12_FN_MASK 0x001F /* GP12_FN - [4:0] */ -#define WM8995_GP12_FN_SHIFT 0 /* GP12_FN - [4:0] */ -#define WM8995_GP12_FN_WIDTH 5 /* GP12_FN - [4:0] */ - -/* - * R1804 (0x70C) - GPIO 13 - */ -#define WM8995_GP13_DIR 0x8000 /* GP13_DIR */ -#define WM8995_GP13_DIR_MASK 0x8000 /* GP13_DIR */ -#define WM8995_GP13_DIR_SHIFT 15 /* GP13_DIR */ -#define WM8995_GP13_DIR_WIDTH 1 /* GP13_DIR */ -#define WM8995_GP13_PU 0x4000 /* GP13_PU */ -#define WM8995_GP13_PU_MASK 0x4000 /* GP13_PU */ -#define WM8995_GP13_PU_SHIFT 14 /* GP13_PU */ -#define WM8995_GP13_PU_WIDTH 1 /* GP13_PU */ -#define WM8995_GP13_PD 0x2000 /* GP13_PD */ -#define WM8995_GP13_PD_MASK 0x2000 /* GP13_PD */ -#define WM8995_GP13_PD_SHIFT 13 /* GP13_PD */ -#define WM8995_GP13_PD_WIDTH 1 /* GP13_PD */ -#define WM8995_GP13_POL 0x0400 /* GP13_POL */ -#define WM8995_GP13_POL_MASK 0x0400 /* GP13_POL */ -#define WM8995_GP13_POL_SHIFT 10 /* GP13_POL */ -#define WM8995_GP13_POL_WIDTH 1 /* GP13_POL */ -#define WM8995_GP13_OP_CFG 0x0200 /* GP13_OP_CFG */ -#define WM8995_GP13_OP_CFG_MASK 0x0200 /* GP13_OP_CFG */ -#define WM8995_GP13_OP_CFG_SHIFT 9 /* GP13_OP_CFG */ -#define WM8995_GP13_OP_CFG_WIDTH 1 /* GP13_OP_CFG */ -#define WM8995_GP13_DB 0x0100 /* GP13_DB */ -#define WM8995_GP13_DB_MASK 0x0100 /* GP13_DB */ -#define WM8995_GP13_DB_SHIFT 8 /* GP13_DB */ -#define WM8995_GP13_DB_WIDTH 1 /* GP13_DB */ -#define WM8995_GP13_LVL 0x0040 /* GP13_LVL */ -#define WM8995_GP13_LVL_MASK 0x0040 /* GP13_LVL */ -#define WM8995_GP13_LVL_SHIFT 6 /* GP13_LVL */ -#define WM8995_GP13_LVL_WIDTH 1 /* GP13_LVL */ -#define WM8995_GP13_FN_MASK 0x001F /* GP13_FN - [4:0] */ -#define WM8995_GP13_FN_SHIFT 0 /* GP13_FN - [4:0] */ -#define WM8995_GP13_FN_WIDTH 5 /* GP13_FN - [4:0] */ - -/* - * R1805 (0x70D) - GPIO 14 - */ -#define WM8995_GP14_DIR 0x8000 /* GP14_DIR */ -#define WM8995_GP14_DIR_MASK 0x8000 /* GP14_DIR */ -#define WM8995_GP14_DIR_SHIFT 15 /* GP14_DIR */ -#define WM8995_GP14_DIR_WIDTH 1 /* GP14_DIR */ -#define WM8995_GP14_PU 0x4000 /* GP14_PU */ -#define WM8995_GP14_PU_MASK 0x4000 /* GP14_PU */ -#define WM8995_GP14_PU_SHIFT 14 /* GP14_PU */ -#define WM8995_GP14_PU_WIDTH 1 /* GP14_PU */ -#define WM8995_GP14_PD 0x2000 /* GP14_PD */ -#define WM8995_GP14_PD_MASK 0x2000 /* GP14_PD */ -#define WM8995_GP14_PD_SHIFT 13 /* GP14_PD */ -#define WM8995_GP14_PD_WIDTH 1 /* GP14_PD */ -#define WM8995_GP14_POL 0x0400 /* GP14_POL */ -#define WM8995_GP14_POL_MASK 0x0400 /* GP14_POL */ -#define WM8995_GP14_POL_SHIFT 10 /* GP14_POL */ -#define WM8995_GP14_POL_WIDTH 1 /* GP14_POL */ -#define WM8995_GP14_OP_CFG 0x0200 /* GP14_OP_CFG */ -#define WM8995_GP14_OP_CFG_MASK 0x0200 /* GP14_OP_CFG */ -#define WM8995_GP14_OP_CFG_SHIFT 9 /* GP14_OP_CFG */ -#define WM8995_GP14_OP_CFG_WIDTH 1 /* GP14_OP_CFG */ -#define WM8995_GP14_DB 0x0100 /* GP14_DB */ -#define WM8995_GP14_DB_MASK 0x0100 /* GP14_DB */ -#define WM8995_GP14_DB_SHIFT 8 /* GP14_DB */ -#define WM8995_GP14_DB_WIDTH 1 /* GP14_DB */ -#define WM8995_GP14_LVL 0x0040 /* GP14_LVL */ -#define WM8995_GP14_LVL_MASK 0x0040 /* GP14_LVL */ -#define WM8995_GP14_LVL_SHIFT 6 /* GP14_LVL */ -#define WM8995_GP14_LVL_WIDTH 1 /* GP14_LVL */ -#define WM8995_GP14_FN_MASK 0x001F /* GP14_FN - [4:0] */ -#define WM8995_GP14_FN_SHIFT 0 /* GP14_FN - [4:0] */ -#define WM8995_GP14_FN_WIDTH 5 /* GP14_FN - [4:0] */ - -/* - * R1824 (0x720) - Pull Control (1) - */ -#define WM8995_DMICDAT3_PD 0x4000 /* DMICDAT3_PD */ -#define WM8995_DMICDAT3_PD_MASK 0x4000 /* DMICDAT3_PD */ -#define WM8995_DMICDAT3_PD_SHIFT 14 /* DMICDAT3_PD */ -#define WM8995_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */ -#define WM8995_DMICDAT2_PD 0x1000 /* DMICDAT2_PD */ -#define WM8995_DMICDAT2_PD_MASK 0x1000 /* DMICDAT2_PD */ -#define WM8995_DMICDAT2_PD_SHIFT 12 /* DMICDAT2_PD */ -#define WM8995_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */ -#define WM8995_DMICDAT1_PD 0x0400 /* DMICDAT1_PD */ -#define WM8995_DMICDAT1_PD_MASK 0x0400 /* DMICDAT1_PD */ -#define WM8995_DMICDAT1_PD_SHIFT 10 /* DMICDAT1_PD */ -#define WM8995_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */ -#define WM8995_MCLK2_PU 0x0200 /* MCLK2_PU */ -#define WM8995_MCLK2_PU_MASK 0x0200 /* MCLK2_PU */ -#define WM8995_MCLK2_PU_SHIFT 9 /* MCLK2_PU */ -#define WM8995_MCLK2_PU_WIDTH 1 /* MCLK2_PU */ -#define WM8995_MCLK2_PD 0x0100 /* MCLK2_PD */ -#define WM8995_MCLK2_PD_MASK 0x0100 /* MCLK2_PD */ -#define WM8995_MCLK2_PD_SHIFT 8 /* MCLK2_PD */ -#define WM8995_MCLK2_PD_WIDTH 1 /* MCLK2_PD */ -#define WM8995_MCLK1_PU 0x0080 /* MCLK1_PU */ -#define WM8995_MCLK1_PU_MASK 0x0080 /* MCLK1_PU */ -#define WM8995_MCLK1_PU_SHIFT 7 /* MCLK1_PU */ -#define WM8995_MCLK1_PU_WIDTH 1 /* MCLK1_PU */ -#define WM8995_MCLK1_PD 0x0040 /* MCLK1_PD */ -#define WM8995_MCLK1_PD_MASK 0x0040 /* MCLK1_PD */ -#define WM8995_MCLK1_PD_SHIFT 6 /* MCLK1_PD */ -#define WM8995_MCLK1_PD_WIDTH 1 /* MCLK1_PD */ -#define WM8995_DACDAT1_PU 0x0020 /* DACDAT1_PU */ -#define WM8995_DACDAT1_PU_MASK 0x0020 /* DACDAT1_PU */ -#define WM8995_DACDAT1_PU_SHIFT 5 /* DACDAT1_PU */ -#define WM8995_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */ -#define WM8995_DACDAT1_PD 0x0010 /* DACDAT1_PD */ -#define WM8995_DACDAT1_PD_MASK 0x0010 /* DACDAT1_PD */ -#define WM8995_DACDAT1_PD_SHIFT 4 /* DACDAT1_PD */ -#define WM8995_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */ -#define WM8995_DACLRCLK1_PU 0x0008 /* DACLRCLK1_PU */ -#define WM8995_DACLRCLK1_PU_MASK 0x0008 /* DACLRCLK1_PU */ -#define WM8995_DACLRCLK1_PU_SHIFT 3 /* DACLRCLK1_PU */ -#define WM8995_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */ -#define WM8995_DACLRCLK1_PD 0x0004 /* DACLRCLK1_PD */ -#define WM8995_DACLRCLK1_PD_MASK 0x0004 /* DACLRCLK1_PD */ -#define WM8995_DACLRCLK1_PD_SHIFT 2 /* DACLRCLK1_PD */ -#define WM8995_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */ -#define WM8995_BCLK1_PU 0x0002 /* BCLK1_PU */ -#define WM8995_BCLK1_PU_MASK 0x0002 /* BCLK1_PU */ -#define WM8995_BCLK1_PU_SHIFT 1 /* BCLK1_PU */ -#define WM8995_BCLK1_PU_WIDTH 1 /* BCLK1_PU */ -#define WM8995_BCLK1_PD 0x0001 /* BCLK1_PD */ -#define WM8995_BCLK1_PD_MASK 0x0001 /* BCLK1_PD */ -#define WM8995_BCLK1_PD_SHIFT 0 /* BCLK1_PD */ -#define WM8995_BCLK1_PD_WIDTH 1 /* BCLK1_PD */ - -/* - * R1825 (0x721) - Pull Control (2) - */ -#define WM8995_LDO1ENA_PD 0x0010 /* LDO1ENA_PD */ -#define WM8995_LDO1ENA_PD_MASK 0x0010 /* LDO1ENA_PD */ -#define WM8995_LDO1ENA_PD_SHIFT 4 /* LDO1ENA_PD */ -#define WM8995_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */ -#define WM8995_MODE_PD 0x0004 /* MODE_PD */ -#define WM8995_MODE_PD_MASK 0x0004 /* MODE_PD */ -#define WM8995_MODE_PD_SHIFT 2 /* MODE_PD */ -#define WM8995_MODE_PD_WIDTH 1 /* MODE_PD */ -#define WM8995_CSNADDR_PD 0x0001 /* CSNADDR_PD */ -#define WM8995_CSNADDR_PD_MASK 0x0001 /* CSNADDR_PD */ -#define WM8995_CSNADDR_PD_SHIFT 0 /* CSNADDR_PD */ -#define WM8995_CSNADDR_PD_WIDTH 1 /* CSNADDR_PD */ - -/* - * R1840 (0x730) - Interrupt Status 1 - */ -#define WM8995_GP14_EINT 0x2000 /* GP14_EINT */ -#define WM8995_GP14_EINT_MASK 0x2000 /* GP14_EINT */ -#define WM8995_GP14_EINT_SHIFT 13 /* GP14_EINT */ -#define WM8995_GP14_EINT_WIDTH 1 /* GP14_EINT */ -#define WM8995_GP13_EINT 0x1000 /* GP13_EINT */ -#define WM8995_GP13_EINT_MASK 0x1000 /* GP13_EINT */ -#define WM8995_GP13_EINT_SHIFT 12 /* GP13_EINT */ -#define WM8995_GP13_EINT_WIDTH 1 /* GP13_EINT */ -#define WM8995_GP12_EINT 0x0800 /* GP12_EINT */ -#define WM8995_GP12_EINT_MASK 0x0800 /* GP12_EINT */ -#define WM8995_GP12_EINT_SHIFT 11 /* GP12_EINT */ -#define WM8995_GP12_EINT_WIDTH 1 /* GP12_EINT */ -#define WM8995_GP11_EINT 0x0400 /* GP11_EINT */ -#define WM8995_GP11_EINT_MASK 0x0400 /* GP11_EINT */ -#define WM8995_GP11_EINT_SHIFT 10 /* GP11_EINT */ -#define WM8995_GP11_EINT_WIDTH 1 /* GP11_EINT */ -#define WM8995_GP10_EINT 0x0200 /* GP10_EINT */ -#define WM8995_GP10_EINT_MASK 0x0200 /* GP10_EINT */ -#define WM8995_GP10_EINT_SHIFT 9 /* GP10_EINT */ -#define WM8995_GP10_EINT_WIDTH 1 /* GP10_EINT */ -#define WM8995_GP9_EINT 0x0100 /* GP9_EINT */ -#define WM8995_GP9_EINT_MASK 0x0100 /* GP9_EINT */ -#define WM8995_GP9_EINT_SHIFT 8 /* GP9_EINT */ -#define WM8995_GP9_EINT_WIDTH 1 /* GP9_EINT */ -#define WM8995_GP8_EINT 0x0080 /* GP8_EINT */ -#define WM8995_GP8_EINT_MASK 0x0080 /* GP8_EINT */ -#define WM8995_GP8_EINT_SHIFT 7 /* GP8_EINT */ -#define WM8995_GP8_EINT_WIDTH 1 /* GP8_EINT */ -#define WM8995_GP7_EINT 0x0040 /* GP7_EINT */ -#define WM8995_GP7_EINT_MASK 0x0040 /* GP7_EINT */ -#define WM8995_GP7_EINT_SHIFT 6 /* GP7_EINT */ -#define WM8995_GP7_EINT_WIDTH 1 /* GP7_EINT */ -#define WM8995_GP6_EINT 0x0020 /* GP6_EINT */ -#define WM8995_GP6_EINT_MASK 0x0020 /* GP6_EINT */ -#define WM8995_GP6_EINT_SHIFT 5 /* GP6_EINT */ -#define WM8995_GP6_EINT_WIDTH 1 /* GP6_EINT */ -#define WM8995_GP5_EINT 0x0010 /* GP5_EINT */ -#define WM8995_GP5_EINT_MASK 0x0010 /* GP5_EINT */ -#define WM8995_GP5_EINT_SHIFT 4 /* GP5_EINT */ -#define WM8995_GP5_EINT_WIDTH 1 /* GP5_EINT */ -#define WM8995_GP4_EINT 0x0008 /* GP4_EINT */ -#define WM8995_GP4_EINT_MASK 0x0008 /* GP4_EINT */ -#define WM8995_GP4_EINT_SHIFT 3 /* GP4_EINT */ -#define WM8995_GP4_EINT_WIDTH 1 /* GP4_EINT */ -#define WM8995_GP3_EINT 0x0004 /* GP3_EINT */ -#define WM8995_GP3_EINT_MASK 0x0004 /* GP3_EINT */ -#define WM8995_GP3_EINT_SHIFT 2 /* GP3_EINT */ -#define WM8995_GP3_EINT_WIDTH 1 /* GP3_EINT */ -#define WM8995_GP2_EINT 0x0002 /* GP2_EINT */ -#define WM8995_GP2_EINT_MASK 0x0002 /* GP2_EINT */ -#define WM8995_GP2_EINT_SHIFT 1 /* GP2_EINT */ -#define WM8995_GP2_EINT_WIDTH 1 /* GP2_EINT */ -#define WM8995_GP1_EINT 0x0001 /* GP1_EINT */ -#define WM8995_GP1_EINT_MASK 0x0001 /* GP1_EINT */ -#define WM8995_GP1_EINT_SHIFT 0 /* GP1_EINT */ -#define WM8995_GP1_EINT_WIDTH 1 /* GP1_EINT */ - -/* - * R1841 (0x731) - Interrupt Status 2 - */ -#define WM8995_DCS_DONE_23_EINT 0x1000 /* DCS_DONE_23_EINT */ -#define WM8995_DCS_DONE_23_EINT_MASK 0x1000 /* DCS_DONE_23_EINT */ -#define WM8995_DCS_DONE_23_EINT_SHIFT 12 /* DCS_DONE_23_EINT */ -#define WM8995_DCS_DONE_23_EINT_WIDTH 1 /* DCS_DONE_23_EINT */ -#define WM8995_DCS_DONE_01_EINT 0x0800 /* DCS_DONE_01_EINT */ -#define WM8995_DCS_DONE_01_EINT_MASK 0x0800 /* DCS_DONE_01_EINT */ -#define WM8995_DCS_DONE_01_EINT_SHIFT 11 /* DCS_DONE_01_EINT */ -#define WM8995_DCS_DONE_01_EINT_WIDTH 1 /* DCS_DONE_01_EINT */ -#define WM8995_WSEQ_DONE_EINT 0x0400 /* WSEQ_DONE_EINT */ -#define WM8995_WSEQ_DONE_EINT_MASK 0x0400 /* WSEQ_DONE_EINT */ -#define WM8995_WSEQ_DONE_EINT_SHIFT 10 /* WSEQ_DONE_EINT */ -#define WM8995_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */ -#define WM8995_FIFOS_ERR_EINT 0x0200 /* FIFOS_ERR_EINT */ -#define WM8995_FIFOS_ERR_EINT_MASK 0x0200 /* FIFOS_ERR_EINT */ -#define WM8995_FIFOS_ERR_EINT_SHIFT 9 /* FIFOS_ERR_EINT */ -#define WM8995_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */ -#define WM8995_AIF2DRC_SIG_DET_EINT 0x0100 /* AIF2DRC_SIG_DET_EINT */ -#define WM8995_AIF2DRC_SIG_DET_EINT_MASK 0x0100 /* AIF2DRC_SIG_DET_EINT */ -#define WM8995_AIF2DRC_SIG_DET_EINT_SHIFT 8 /* AIF2DRC_SIG_DET_EINT */ -#define WM8995_AIF2DRC_SIG_DET_EINT_WIDTH 1 /* AIF2DRC_SIG_DET_EINT */ -#define WM8995_AIF1DRC2_SIG_DET_EINT 0x0080 /* AIF1DRC2_SIG_DET_EINT */ -#define WM8995_AIF1DRC2_SIG_DET_EINT_MASK 0x0080 /* AIF1DRC2_SIG_DET_EINT */ -#define WM8995_AIF1DRC2_SIG_DET_EINT_SHIFT 7 /* AIF1DRC2_SIG_DET_EINT */ -#define WM8995_AIF1DRC2_SIG_DET_EINT_WIDTH 1 /* AIF1DRC2_SIG_DET_EINT */ -#define WM8995_AIF1DRC1_SIG_DET_EINT 0x0040 /* AIF1DRC1_SIG_DET_EINT */ -#define WM8995_AIF1DRC1_SIG_DET_EINT_MASK 0x0040 /* AIF1DRC1_SIG_DET_EINT */ -#define WM8995_AIF1DRC1_SIG_DET_EINT_SHIFT 6 /* AIF1DRC1_SIG_DET_EINT */ -#define WM8995_AIF1DRC1_SIG_DET_EINT_WIDTH 1 /* AIF1DRC1_SIG_DET_EINT */ -#define WM8995_SRC2_LOCK_EINT 0x0020 /* SRC2_LOCK_EINT */ -#define WM8995_SRC2_LOCK_EINT_MASK 0x0020 /* SRC2_LOCK_EINT */ -#define WM8995_SRC2_LOCK_EINT_SHIFT 5 /* SRC2_LOCK_EINT */ -#define WM8995_SRC2_LOCK_EINT_WIDTH 1 /* SRC2_LOCK_EINT */ -#define WM8995_SRC1_LOCK_EINT 0x0010 /* SRC1_LOCK_EINT */ -#define WM8995_SRC1_LOCK_EINT_MASK 0x0010 /* SRC1_LOCK_EINT */ -#define WM8995_SRC1_LOCK_EINT_SHIFT 4 /* SRC1_LOCK_EINT */ -#define WM8995_SRC1_LOCK_EINT_WIDTH 1 /* SRC1_LOCK_EINT */ -#define WM8995_FLL2_LOCK_EINT 0x0008 /* FLL2_LOCK_EINT */ -#define WM8995_FLL2_LOCK_EINT_MASK 0x0008 /* FLL2_LOCK_EINT */ -#define WM8995_FLL2_LOCK_EINT_SHIFT 3 /* FLL2_LOCK_EINT */ -#define WM8995_FLL2_LOCK_EINT_WIDTH 1 /* FLL2_LOCK_EINT */ -#define WM8995_FLL1_LOCK_EINT 0x0004 /* FLL1_LOCK_EINT */ -#define WM8995_FLL1_LOCK_EINT_MASK 0x0004 /* FLL1_LOCK_EINT */ -#define WM8995_FLL1_LOCK_EINT_SHIFT 2 /* FLL1_LOCK_EINT */ -#define WM8995_FLL1_LOCK_EINT_WIDTH 1 /* FLL1_LOCK_EINT */ -#define WM8995_HP_DONE_EINT 0x0002 /* HP_DONE_EINT */ -#define WM8995_HP_DONE_EINT_MASK 0x0002 /* HP_DONE_EINT */ -#define WM8995_HP_DONE_EINT_SHIFT 1 /* HP_DONE_EINT */ -#define WM8995_HP_DONE_EINT_WIDTH 1 /* HP_DONE_EINT */ -#define WM8995_MICD_EINT 0x0001 /* MICD_EINT */ -#define WM8995_MICD_EINT_MASK 0x0001 /* MICD_EINT */ -#define WM8995_MICD_EINT_SHIFT 0 /* MICD_EINT */ -#define WM8995_MICD_EINT_WIDTH 1 /* MICD_EINT */ - -/* - * R1842 (0x732) - Interrupt Raw Status 2 - */ -#define WM8995_DCS_DONE_23_STS 0x1000 /* DCS_DONE_23_STS */ -#define WM8995_DCS_DONE_23_STS_MASK 0x1000 /* DCS_DONE_23_STS */ -#define WM8995_DCS_DONE_23_STS_SHIFT 12 /* DCS_DONE_23_STS */ -#define WM8995_DCS_DONE_23_STS_WIDTH 1 /* DCS_DONE_23_STS */ -#define WM8995_DCS_DONE_01_STS 0x0800 /* DCS_DONE_01_STS */ -#define WM8995_DCS_DONE_01_STS_MASK 0x0800 /* DCS_DONE_01_STS */ -#define WM8995_DCS_DONE_01_STS_SHIFT 11 /* DCS_DONE_01_STS */ -#define WM8995_DCS_DONE_01_STS_WIDTH 1 /* DCS_DONE_01_STS */ -#define WM8995_WSEQ_DONE_STS 0x0400 /* WSEQ_DONE_STS */ -#define WM8995_WSEQ_DONE_STS_MASK 0x0400 /* WSEQ_DONE_STS */ -#define WM8995_WSEQ_DONE_STS_SHIFT 10 /* WSEQ_DONE_STS */ -#define WM8995_WSEQ_DONE_STS_WIDTH 1 /* WSEQ_DONE_STS */ -#define WM8995_FIFOS_ERR_STS 0x0200 /* FIFOS_ERR_STS */ -#define WM8995_FIFOS_ERR_STS_MASK 0x0200 /* FIFOS_ERR_STS */ -#define WM8995_FIFOS_ERR_STS_SHIFT 9 /* FIFOS_ERR_STS */ -#define WM8995_FIFOS_ERR_STS_WIDTH 1 /* FIFOS_ERR_STS */ -#define WM8995_AIF2DRC_SIG_DET_STS 0x0100 /* AIF2DRC_SIG_DET_STS */ -#define WM8995_AIF2DRC_SIG_DET_STS_MASK 0x0100 /* AIF2DRC_SIG_DET_STS */ -#define WM8995_AIF2DRC_SIG_DET_STS_SHIFT 8 /* AIF2DRC_SIG_DET_STS */ -#define WM8995_AIF2DRC_SIG_DET_STS_WIDTH 1 /* AIF2DRC_SIG_DET_STS */ -#define WM8995_AIF1DRC2_SIG_DET_STS 0x0080 /* AIF1DRC2_SIG_DET_STS */ -#define WM8995_AIF1DRC2_SIG_DET_STS_MASK 0x0080 /* AIF1DRC2_SIG_DET_STS */ -#define WM8995_AIF1DRC2_SIG_DET_STS_SHIFT 7 /* AIF1DRC2_SIG_DET_STS */ -#define WM8995_AIF1DRC2_SIG_DET_STS_WIDTH 1 /* AIF1DRC2_SIG_DET_STS */ -#define WM8995_AIF1DRC1_SIG_DET_STS 0x0040 /* AIF1DRC1_SIG_DET_STS */ -#define WM8995_AIF1DRC1_SIG_DET_STS_MASK 0x0040 /* AIF1DRC1_SIG_DET_STS */ -#define WM8995_AIF1DRC1_SIG_DET_STS_SHIFT 6 /* AIF1DRC1_SIG_DET_STS */ -#define WM8995_AIF1DRC1_SIG_DET_STS_WIDTH 1 /* AIF1DRC1_SIG_DET_STS */ -#define WM8995_SRC2_LOCK_STS 0x0020 /* SRC2_LOCK_STS */ -#define WM8995_SRC2_LOCK_STS_MASK 0x0020 /* SRC2_LOCK_STS */ -#define WM8995_SRC2_LOCK_STS_SHIFT 5 /* SRC2_LOCK_STS */ -#define WM8995_SRC2_LOCK_STS_WIDTH 1 /* SRC2_LOCK_STS */ -#define WM8995_SRC1_LOCK_STS 0x0010 /* SRC1_LOCK_STS */ -#define WM8995_SRC1_LOCK_STS_MASK 0x0010 /* SRC1_LOCK_STS */ -#define WM8995_SRC1_LOCK_STS_SHIFT 4 /* SRC1_LOCK_STS */ -#define WM8995_SRC1_LOCK_STS_WIDTH 1 /* SRC1_LOCK_STS */ -#define WM8995_FLL2_LOCK_STS 0x0008 /* FLL2_LOCK_STS */ -#define WM8995_FLL2_LOCK_STS_MASK 0x0008 /* FLL2_LOCK_STS */ -#define WM8995_FLL2_LOCK_STS_SHIFT 3 /* FLL2_LOCK_STS */ -#define WM8995_FLL2_LOCK_STS_WIDTH 1 /* FLL2_LOCK_STS */ -#define WM8995_FLL1_LOCK_STS 0x0004 /* FLL1_LOCK_STS */ -#define WM8995_FLL1_LOCK_STS_MASK 0x0004 /* FLL1_LOCK_STS */ -#define WM8995_FLL1_LOCK_STS_SHIFT 2 /* FLL1_LOCK_STS */ -#define WM8995_FLL1_LOCK_STS_WIDTH 1 /* FLL1_LOCK_STS */ - -/* - * R1848 (0x738) - Interrupt Status 1 Mask - */ -#define WM8995_IM_GP14_EINT 0x2000 /* IM_GP14_EINT */ -#define WM8995_IM_GP14_EINT_MASK 0x2000 /* IM_GP14_EINT */ -#define WM8995_IM_GP14_EINT_SHIFT 13 /* IM_GP14_EINT */ -#define WM8995_IM_GP14_EINT_WIDTH 1 /* IM_GP14_EINT */ -#define WM8995_IM_GP13_EINT 0x1000 /* IM_GP13_EINT */ -#define WM8995_IM_GP13_EINT_MASK 0x1000 /* IM_GP13_EINT */ -#define WM8995_IM_GP13_EINT_SHIFT 12 /* IM_GP13_EINT */ -#define WM8995_IM_GP13_EINT_WIDTH 1 /* IM_GP13_EINT */ -#define WM8995_IM_GP12_EINT 0x0800 /* IM_GP12_EINT */ -#define WM8995_IM_GP12_EINT_MASK 0x0800 /* IM_GP12_EINT */ -#define WM8995_IM_GP12_EINT_SHIFT 11 /* IM_GP12_EINT */ -#define WM8995_IM_GP12_EINT_WIDTH 1 /* IM_GP12_EINT */ -#define WM8995_IM_GP11_EINT 0x0400 /* IM_GP11_EINT */ -#define WM8995_IM_GP11_EINT_MASK 0x0400 /* IM_GP11_EINT */ -#define WM8995_IM_GP11_EINT_SHIFT 10 /* IM_GP11_EINT */ -#define WM8995_IM_GP11_EINT_WIDTH 1 /* IM_GP11_EINT */ -#define WM8995_IM_GP10_EINT 0x0200 /* IM_GP10_EINT */ -#define WM8995_IM_GP10_EINT_MASK 0x0200 /* IM_GP10_EINT */ -#define WM8995_IM_GP10_EINT_SHIFT 9 /* IM_GP10_EINT */ -#define WM8995_IM_GP10_EINT_WIDTH 1 /* IM_GP10_EINT */ -#define WM8995_IM_GP9_EINT 0x0100 /* IM_GP9_EINT */ -#define WM8995_IM_GP9_EINT_MASK 0x0100 /* IM_GP9_EINT */ -#define WM8995_IM_GP9_EINT_SHIFT 8 /* IM_GP9_EINT */ -#define WM8995_IM_GP9_EINT_WIDTH 1 /* IM_GP9_EINT */ -#define WM8995_IM_GP8_EINT 0x0080 /* IM_GP8_EINT */ -#define WM8995_IM_GP8_EINT_MASK 0x0080 /* IM_GP8_EINT */ -#define WM8995_IM_GP8_EINT_SHIFT 7 /* IM_GP8_EINT */ -#define WM8995_IM_GP8_EINT_WIDTH 1 /* IM_GP8_EINT */ -#define WM8995_IM_GP7_EINT 0x0040 /* IM_GP7_EINT */ -#define WM8995_IM_GP7_EINT_MASK 0x0040 /* IM_GP7_EINT */ -#define WM8995_IM_GP7_EINT_SHIFT 6 /* IM_GP7_EINT */ -#define WM8995_IM_GP7_EINT_WIDTH 1 /* IM_GP7_EINT */ -#define WM8995_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */ -#define WM8995_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */ -#define WM8995_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */ -#define WM8995_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */ -#define WM8995_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */ -#define WM8995_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */ -#define WM8995_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */ -#define WM8995_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */ -#define WM8995_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */ -#define WM8995_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */ -#define WM8995_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */ -#define WM8995_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */ -#define WM8995_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */ -#define WM8995_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */ -#define WM8995_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */ -#define WM8995_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */ -#define WM8995_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */ -#define WM8995_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */ -#define WM8995_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */ -#define WM8995_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */ -#define WM8995_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */ -#define WM8995_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */ -#define WM8995_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */ -#define WM8995_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */ - -/* - * R1849 (0x739) - Interrupt Status 2 Mask - */ -#define WM8995_IM_DCS_DONE_23_EINT 0x1000 /* IM_DCS_DONE_23_EINT */ -#define WM8995_IM_DCS_DONE_23_EINT_MASK 0x1000 /* IM_DCS_DONE_23_EINT */ -#define WM8995_IM_DCS_DONE_23_EINT_SHIFT 12 /* IM_DCS_DONE_23_EINT */ -#define WM8995_IM_DCS_DONE_23_EINT_WIDTH 1 /* IM_DCS_DONE_23_EINT */ -#define WM8995_IM_DCS_DONE_01_EINT 0x0800 /* IM_DCS_DONE_01_EINT */ -#define WM8995_IM_DCS_DONE_01_EINT_MASK 0x0800 /* IM_DCS_DONE_01_EINT */ -#define WM8995_IM_DCS_DONE_01_EINT_SHIFT 11 /* IM_DCS_DONE_01_EINT */ -#define WM8995_IM_DCS_DONE_01_EINT_WIDTH 1 /* IM_DCS_DONE_01_EINT */ -#define WM8995_IM_WSEQ_DONE_EINT 0x0400 /* IM_WSEQ_DONE_EINT */ -#define WM8995_IM_WSEQ_DONE_EINT_MASK 0x0400 /* IM_WSEQ_DONE_EINT */ -#define WM8995_IM_WSEQ_DONE_EINT_SHIFT 10 /* IM_WSEQ_DONE_EINT */ -#define WM8995_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */ -#define WM8995_IM_FIFOS_ERR_EINT 0x0200 /* IM_FIFOS_ERR_EINT */ -#define WM8995_IM_FIFOS_ERR_EINT_MASK 0x0200 /* IM_FIFOS_ERR_EINT */ -#define WM8995_IM_FIFOS_ERR_EINT_SHIFT 9 /* IM_FIFOS_ERR_EINT */ -#define WM8995_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */ -#define WM8995_IM_AIF2DRC_SIG_DET_EINT 0x0100 /* IM_AIF2DRC_SIG_DET_EINT */ -#define WM8995_IM_AIF2DRC_SIG_DET_EINT_MASK 0x0100 /* IM_AIF2DRC_SIG_DET_EINT */ -#define WM8995_IM_AIF2DRC_SIG_DET_EINT_SHIFT 8 /* IM_AIF2DRC_SIG_DET_EINT */ -#define WM8995_IM_AIF2DRC_SIG_DET_EINT_WIDTH 1 /* IM_AIF2DRC_SIG_DET_EINT */ -#define WM8995_IM_AIF1DRC2_SIG_DET_EINT 0x0080 /* IM_AIF1DRC2_SIG_DET_EINT */ -#define WM8995_IM_AIF1DRC2_SIG_DET_EINT_MASK 0x0080 /* IM_AIF1DRC2_SIG_DET_EINT */ -#define WM8995_IM_AIF1DRC2_SIG_DET_EINT_SHIFT 7 /* IM_AIF1DRC2_SIG_DET_EINT */ -#define WM8995_IM_AIF1DRC2_SIG_DET_EINT_WIDTH 1 /* IM_AIF1DRC2_SIG_DET_EINT */ -#define WM8995_IM_AIF1DRC1_SIG_DET_EINT 0x0040 /* IM_AIF1DRC1_SIG_DET_EINT */ -#define WM8995_IM_AIF1DRC1_SIG_DET_EINT_MASK 0x0040 /* IM_AIF1DRC1_SIG_DET_EINT */ -#define WM8995_IM_AIF1DRC1_SIG_DET_EINT_SHIFT 6 /* IM_AIF1DRC1_SIG_DET_EINT */ -#define WM8995_IM_AIF1DRC1_SIG_DET_EINT_WIDTH 1 /* IM_AIF1DRC1_SIG_DET_EINT */ -#define WM8995_IM_SRC2_LOCK_EINT 0x0020 /* IM_SRC2_LOCK_EINT */ -#define WM8995_IM_SRC2_LOCK_EINT_MASK 0x0020 /* IM_SRC2_LOCK_EINT */ -#define WM8995_IM_SRC2_LOCK_EINT_SHIFT 5 /* IM_SRC2_LOCK_EINT */ -#define WM8995_IM_SRC2_LOCK_EINT_WIDTH 1 /* IM_SRC2_LOCK_EINT */ -#define WM8995_IM_SRC1_LOCK_EINT 0x0010 /* IM_SRC1_LOCK_EINT */ -#define WM8995_IM_SRC1_LOCK_EINT_MASK 0x0010 /* IM_SRC1_LOCK_EINT */ -#define WM8995_IM_SRC1_LOCK_EINT_SHIFT 4 /* IM_SRC1_LOCK_EINT */ -#define WM8995_IM_SRC1_LOCK_EINT_WIDTH 1 /* IM_SRC1_LOCK_EINT */ -#define WM8995_IM_FLL2_LOCK_EINT 0x0008 /* IM_FLL2_LOCK_EINT */ -#define WM8995_IM_FLL2_LOCK_EINT_MASK 0x0008 /* IM_FLL2_LOCK_EINT */ -#define WM8995_IM_FLL2_LOCK_EINT_SHIFT 3 /* IM_FLL2_LOCK_EINT */ -#define WM8995_IM_FLL2_LOCK_EINT_WIDTH 1 /* IM_FLL2_LOCK_EINT */ -#define WM8995_IM_FLL1_LOCK_EINT 0x0004 /* IM_FLL1_LOCK_EINT */ -#define WM8995_IM_FLL1_LOCK_EINT_MASK 0x0004 /* IM_FLL1_LOCK_EINT */ -#define WM8995_IM_FLL1_LOCK_EINT_SHIFT 2 /* IM_FLL1_LOCK_EINT */ -#define WM8995_IM_FLL1_LOCK_EINT_WIDTH 1 /* IM_FLL1_LOCK_EINT */ -#define WM8995_IM_HP_DONE_EINT 0x0002 /* IM_HP_DONE_EINT */ -#define WM8995_IM_HP_DONE_EINT_MASK 0x0002 /* IM_HP_DONE_EINT */ -#define WM8995_IM_HP_DONE_EINT_SHIFT 1 /* IM_HP_DONE_EINT */ -#define WM8995_IM_HP_DONE_EINT_WIDTH 1 /* IM_HP_DONE_EINT */ -#define WM8995_IM_MICD_EINT 0x0001 /* IM_MICD_EINT */ -#define WM8995_IM_MICD_EINT_MASK 0x0001 /* IM_MICD_EINT */ -#define WM8995_IM_MICD_EINT_SHIFT 0 /* IM_MICD_EINT */ -#define WM8995_IM_MICD_EINT_WIDTH 1 /* IM_MICD_EINT */ - -/* - * R1856 (0x740) - Interrupt Control - */ -#define WM8995_IM_IRQ 0x0001 /* IM_IRQ */ -#define WM8995_IM_IRQ_MASK 0x0001 /* IM_IRQ */ -#define WM8995_IM_IRQ_SHIFT 0 /* IM_IRQ */ -#define WM8995_IM_IRQ_WIDTH 1 /* IM_IRQ */ - -/* - * R2048 (0x800) - Left PDM Speaker 1 - */ -#define WM8995_SPK1L_ENA 0x0010 /* SPK1L_ENA */ -#define WM8995_SPK1L_ENA_MASK 0x0010 /* SPK1L_ENA */ -#define WM8995_SPK1L_ENA_SHIFT 4 /* SPK1L_ENA */ -#define WM8995_SPK1L_ENA_WIDTH 1 /* SPK1L_ENA */ -#define WM8995_SPK1L_MUTE 0x0008 /* SPK1L_MUTE */ -#define WM8995_SPK1L_MUTE_MASK 0x0008 /* SPK1L_MUTE */ -#define WM8995_SPK1L_MUTE_SHIFT 3 /* SPK1L_MUTE */ -#define WM8995_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */ -#define WM8995_SPK1L_MUTE_ZC 0x0004 /* SPK1L_MUTE_ZC */ -#define WM8995_SPK1L_MUTE_ZC_MASK 0x0004 /* SPK1L_MUTE_ZC */ -#define WM8995_SPK1L_MUTE_ZC_SHIFT 2 /* SPK1L_MUTE_ZC */ -#define WM8995_SPK1L_MUTE_ZC_WIDTH 1 /* SPK1L_MUTE_ZC */ -#define WM8995_SPK1L_SRC_MASK 0x0003 /* SPK1L_SRC - [1:0] */ -#define WM8995_SPK1L_SRC_SHIFT 0 /* SPK1L_SRC - [1:0] */ -#define WM8995_SPK1L_SRC_WIDTH 2 /* SPK1L_SRC - [1:0] */ - -/* - * R2049 (0x801) - Right PDM Speaker 1 - */ -#define WM8995_SPK1R_ENA 0x0010 /* SPK1R_ENA */ -#define WM8995_SPK1R_ENA_MASK 0x0010 /* SPK1R_ENA */ -#define WM8995_SPK1R_ENA_SHIFT 4 /* SPK1R_ENA */ -#define WM8995_SPK1R_ENA_WIDTH 1 /* SPK1R_ENA */ -#define WM8995_SPK1R_MUTE 0x0008 /* SPK1R_MUTE */ -#define WM8995_SPK1R_MUTE_MASK 0x0008 /* SPK1R_MUTE */ -#define WM8995_SPK1R_MUTE_SHIFT 3 /* SPK1R_MUTE */ -#define WM8995_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */ -#define WM8995_SPK1R_MUTE_ZC 0x0004 /* SPK1R_MUTE_ZC */ -#define WM8995_SPK1R_MUTE_ZC_MASK 0x0004 /* SPK1R_MUTE_ZC */ -#define WM8995_SPK1R_MUTE_ZC_SHIFT 2 /* SPK1R_MUTE_ZC */ -#define WM8995_SPK1R_MUTE_ZC_WIDTH 1 /* SPK1R_MUTE_ZC */ -#define WM8995_SPK1R_SRC_MASK 0x0003 /* SPK1R_SRC - [1:0] */ -#define WM8995_SPK1R_SRC_SHIFT 0 /* SPK1R_SRC - [1:0] */ -#define WM8995_SPK1R_SRC_WIDTH 2 /* SPK1R_SRC - [1:0] */ - -/* - * R2050 (0x802) - PDM Speaker 1 Mute Sequence - */ -#define WM8995_SPK1_MUTE_SEQ1_MASK 0x00FF /* SPK1_MUTE_SEQ1 - [7:0] */ -#define WM8995_SPK1_MUTE_SEQ1_SHIFT 0 /* SPK1_MUTE_SEQ1 - [7:0] */ -#define WM8995_SPK1_MUTE_SEQ1_WIDTH 8 /* SPK1_MUTE_SEQ1 - [7:0] */ - -/* - * R2056 (0x808) - Left PDM Speaker 2 - */ -#define WM8995_SPK2L_ENA 0x0010 /* SPK2L_ENA */ -#define WM8995_SPK2L_ENA_MASK 0x0010 /* SPK2L_ENA */ -#define WM8995_SPK2L_ENA_SHIFT 4 /* SPK2L_ENA */ -#define WM8995_SPK2L_ENA_WIDTH 1 /* SPK2L_ENA */ -#define WM8995_SPK2L_MUTE 0x0008 /* SPK2L_MUTE */ -#define WM8995_SPK2L_MUTE_MASK 0x0008 /* SPK2L_MUTE */ -#define WM8995_SPK2L_MUTE_SHIFT 3 /* SPK2L_MUTE */ -#define WM8995_SPK2L_MUTE_WIDTH 1 /* SPK2L_MUTE */ -#define WM8995_SPK2L_MUTE_ZC 0x0004 /* SPK2L_MUTE_ZC */ -#define WM8995_SPK2L_MUTE_ZC_MASK 0x0004 /* SPK2L_MUTE_ZC */ -#define WM8995_SPK2L_MUTE_ZC_SHIFT 2 /* SPK2L_MUTE_ZC */ -#define WM8995_SPK2L_MUTE_ZC_WIDTH 1 /* SPK2L_MUTE_ZC */ -#define WM8995_SPK2L_SRC_MASK 0x0003 /* SPK2L_SRC - [1:0] */ -#define WM8995_SPK2L_SRC_SHIFT 0 /* SPK2L_SRC - [1:0] */ -#define WM8995_SPK2L_SRC_WIDTH 2 /* SPK2L_SRC - [1:0] */ - -/* - * R2057 (0x809) - Right PDM Speaker 2 - */ -#define WM8995_SPK2R_ENA 0x0010 /* SPK2R_ENA */ -#define WM8995_SPK2R_ENA_MASK 0x0010 /* SPK2R_ENA */ -#define WM8995_SPK2R_ENA_SHIFT 4 /* SPK2R_ENA */ -#define WM8995_SPK2R_ENA_WIDTH 1 /* SPK2R_ENA */ -#define WM8995_SPK2R_MUTE 0x0008 /* SPK2R_MUTE */ -#define WM8995_SPK2R_MUTE_MASK 0x0008 /* SPK2R_MUTE */ -#define WM8995_SPK2R_MUTE_SHIFT 3 /* SPK2R_MUTE */ -#define WM8995_SPK2R_MUTE_WIDTH 1 /* SPK2R_MUTE */ -#define WM8995_SPK2R_MUTE_ZC 0x0004 /* SPK2R_MUTE_ZC */ -#define WM8995_SPK2R_MUTE_ZC_MASK 0x0004 /* SPK2R_MUTE_ZC */ -#define WM8995_SPK2R_MUTE_ZC_SHIFT 2 /* SPK2R_MUTE_ZC */ -#define WM8995_SPK2R_MUTE_ZC_WIDTH 1 /* SPK2R_MUTE_ZC */ -#define WM8995_SPK2R_SRC_MASK 0x0003 /* SPK2R_SRC - [1:0] */ -#define WM8995_SPK2R_SRC_SHIFT 0 /* SPK2R_SRC - [1:0] */ -#define WM8995_SPK2R_SRC_WIDTH 2 /* SPK2R_SRC - [1:0] */ - -/* - * R2058 (0x80A) - PDM Speaker 2 Mute Sequence - */ -#define WM8995_SPK2_MUTE_SEQ1_MASK 0x00FF /* SPK2_MUTE_SEQ1 - [7:0] */ -#define WM8995_SPK2_MUTE_SEQ1_SHIFT 0 /* SPK2_MUTE_SEQ1 - [7:0] */ -#define WM8995_SPK2_MUTE_SEQ1_WIDTH 8 /* SPK2_MUTE_SEQ1 - [7:0] */ - -#define WM8995_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = wm8995_put_class_w, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) \ -} - -struct wm8995_reg_access { - u16 read; - u16 write; - u16 vol; -}; - -/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ -enum clk_src { - WM8995_SYSCLK_MCLK1 = 1, - WM8995_SYSCLK_MCLK2, - WM8995_SYSCLK_FLL1, - WM8995_SYSCLK_FLL2, - WM8995_SYSCLK_OPCLK -}; - -#define WM8995_FLL1 1 -#define WM8995_FLL2 2 - -#define WM8995_FLL_SRC_MCLK1 1 -#define WM8995_FLL_SRC_MCLK2 2 -#define WM8995_FLL_SRC_LRCLK 3 -#define WM8995_FLL_SRC_BCLK 4 - -#endif /* _WM8995_H */ diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8996.c b/ANDROID_3.4.5/sound/soc/codecs/wm8996.c deleted file mode 100644 index 1fd63549..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8996.c +++ /dev/null @@ -1,3265 +0,0 @@ -/* - * wm8996.c - WM8996 audio codec interface - * - * Copyright 2011 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "wm8996.h" - -#define WM8996_AIFS 2 - -#define HPOUT1L 1 -#define HPOUT1R 2 -#define HPOUT2L 4 -#define HPOUT2R 8 - -#define WM8996_NUM_SUPPLIES 3 -static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = { - "DBVDD", - "AVDD1", - "AVDD2", -}; - -struct wm8996_priv { - struct device *dev; - struct regmap *regmap; - struct snd_soc_codec *codec; - - int ldo1ena; - - int sysclk; - int sysclk_src; - - int fll_src; - int fll_fref; - int fll_fout; - - struct completion fll_lock; - - u16 dcs_pending; - struct completion dcs_done; - - u16 hpout_ena; - u16 hpout_pending; - - struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; - struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; - int bg_ena; - - struct wm8996_pdata pdata; - - int rx_rate[WM8996_AIFS]; - int bclk_rate[WM8996_AIFS]; - - /* Platform dependant ReTune mobile configuration */ - int num_retune_mobile_texts; - const char **retune_mobile_texts; - int retune_mobile_cfg[2]; - struct soc_enum retune_mobile_enum; - - struct snd_soc_jack *jack; - bool detecting; - bool jack_mic; - int jack_flips; - wm8996_polarity_fn polarity_cb; - -#ifdef CONFIG_GPIOLIB - struct gpio_chip gpio_chip; -#endif -}; - -/* We can't use the same notifier block for more than one supply and - * there's no way I can see to get from a callback to the caller - * except container_of(). - */ -#define WM8996_REGULATOR_EVENT(n) \ -static int wm8996_regulator_event_##n(struct notifier_block *nb, \ - unsigned long event, void *data) \ -{ \ - struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \ - disable_nb[n]); \ - if (event & REGULATOR_EVENT_DISABLE) { \ - regcache_mark_dirty(wm8996->regmap); \ - } \ - return 0; \ -} - -WM8996_REGULATOR_EVENT(0) -WM8996_REGULATOR_EVENT(1) -WM8996_REGULATOR_EVENT(2) - -static struct reg_default wm8996_reg[] = { - { WM8996_POWER_MANAGEMENT_1, 0x0 }, - { WM8996_POWER_MANAGEMENT_2, 0x0 }, - { WM8996_POWER_MANAGEMENT_3, 0x0 }, - { WM8996_POWER_MANAGEMENT_4, 0x0 }, - { WM8996_POWER_MANAGEMENT_5, 0x0 }, - { WM8996_POWER_MANAGEMENT_6, 0x0 }, - { WM8996_POWER_MANAGEMENT_7, 0x10 }, - { WM8996_POWER_MANAGEMENT_8, 0x0 }, - { WM8996_LEFT_LINE_INPUT_VOLUME, 0x0 }, - { WM8996_RIGHT_LINE_INPUT_VOLUME, 0x0 }, - { WM8996_LINE_INPUT_CONTROL, 0x0 }, - { WM8996_DAC1_HPOUT1_VOLUME, 0x88 }, - { WM8996_DAC2_HPOUT2_VOLUME, 0x88 }, - { WM8996_DAC1_LEFT_VOLUME, 0x2c0 }, - { WM8996_DAC1_RIGHT_VOLUME, 0x2c0 }, - { WM8996_DAC2_LEFT_VOLUME, 0x2c0 }, - { WM8996_DAC2_RIGHT_VOLUME, 0x2c0 }, - { WM8996_OUTPUT1_LEFT_VOLUME, 0x80 }, - { WM8996_OUTPUT1_RIGHT_VOLUME, 0x80 }, - { WM8996_OUTPUT2_LEFT_VOLUME, 0x80 }, - { WM8996_OUTPUT2_RIGHT_VOLUME, 0x80 }, - { WM8996_MICBIAS_1, 0x39 }, - { WM8996_MICBIAS_2, 0x39 }, - { WM8996_LDO_1, 0x3 }, - { WM8996_LDO_2, 0x13 }, - { WM8996_ACCESSORY_DETECT_MODE_1, 0x4 }, - { WM8996_ACCESSORY_DETECT_MODE_2, 0x0 }, - { WM8996_HEADPHONE_DETECT_1, 0x20 }, - { WM8996_HEADPHONE_DETECT_2, 0x0 }, - { WM8996_MIC_DETECT_1, 0x7600 }, - { WM8996_MIC_DETECT_2, 0xbf }, - { WM8996_CHARGE_PUMP_1, 0x1f25 }, - { WM8996_CHARGE_PUMP_2, 0xab19 }, - { WM8996_DC_SERVO_1, 0x0 }, - { WM8996_DC_SERVO_3, 0x0 }, - { WM8996_DC_SERVO_5, 0x2a2a }, - { WM8996_DC_SERVO_6, 0x0 }, - { WM8996_DC_SERVO_7, 0x0 }, - { WM8996_ANALOGUE_HP_1, 0x0 }, - { WM8996_ANALOGUE_HP_2, 0x0 }, - { WM8996_CONTROL_INTERFACE_1, 0x8004 }, - { WM8996_WRITE_SEQUENCER_CTRL_1, 0x0 }, - { WM8996_WRITE_SEQUENCER_CTRL_2, 0x0 }, - { WM8996_AIF_CLOCKING_1, 0x0 }, - { WM8996_AIF_CLOCKING_2, 0x0 }, - { WM8996_CLOCKING_1, 0x10 }, - { WM8996_CLOCKING_2, 0x0 }, - { WM8996_AIF_RATE, 0x83 }, - { WM8996_FLL_CONTROL_1, 0x0 }, - { WM8996_FLL_CONTROL_2, 0x0 }, - { WM8996_FLL_CONTROL_3, 0x0 }, - { WM8996_FLL_CONTROL_4, 0x5dc0 }, - { WM8996_FLL_CONTROL_5, 0xc84 }, - { WM8996_FLL_EFS_1, 0x0 }, - { WM8996_FLL_EFS_2, 0x2 }, - { WM8996_AIF1_CONTROL, 0x0 }, - { WM8996_AIF1_BCLK, 0x0 }, - { WM8996_AIF1_TX_LRCLK_1, 0x80 }, - { WM8996_AIF1_TX_LRCLK_2, 0x8 }, - { WM8996_AIF1_RX_LRCLK_1, 0x80 }, - { WM8996_AIF1_RX_LRCLK_2, 0x0 }, - { WM8996_AIF1TX_DATA_CONFIGURATION_1, 0x1818 }, - { WM8996_AIF1TX_DATA_CONFIGURATION_2, 0 }, - { WM8996_AIF1RX_DATA_CONFIGURATION, 0x1818 }, - { WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, 0x0 }, - { WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, 0x0 }, - { WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, 0x0 }, - { WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, 0x0 }, - { WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, 0x0 }, - { WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, 0x0 }, - { WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, 0x0 }, - { WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, 0x0 }, - { WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, 0x0 }, - { WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, 0x0 }, - { WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, 0x0 }, - { WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, 0x0 }, - { WM8996_AIF1RX_MONO_CONFIGURATION, 0x0 }, - { WM8996_AIF1TX_TEST, 0x7 }, - { WM8996_AIF2_CONTROL, 0x0 }, - { WM8996_AIF2_BCLK, 0x0 }, - { WM8996_AIF2_TX_LRCLK_1, 0x80 }, - { WM8996_AIF2_TX_LRCLK_2, 0x8 }, - { WM8996_AIF2_RX_LRCLK_1, 0x80 }, - { WM8996_AIF2_RX_LRCLK_2, 0x0 }, - { WM8996_AIF2TX_DATA_CONFIGURATION_1, 0x1818 }, - { WM8996_AIF2RX_DATA_CONFIGURATION, 0x1818 }, - { WM8996_AIF2RX_DATA_CONFIGURATION, 0x0 }, - { WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, 0x0 }, - { WM8996_AIF2TX_CHANNEL_1_CONFIGURATION, 0x0 }, - { WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, 0x0 }, - { WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, 0x0 }, - { WM8996_AIF2RX_MONO_CONFIGURATION, 0x0 }, - { WM8996_AIF2TX_TEST, 0x1 }, - { WM8996_DSP1_TX_LEFT_VOLUME, 0xc0 }, - { WM8996_DSP1_TX_RIGHT_VOLUME, 0xc0 }, - { WM8996_DSP1_RX_LEFT_VOLUME, 0xc0 }, - { WM8996_DSP1_RX_RIGHT_VOLUME, 0xc0 }, - { WM8996_DSP1_TX_FILTERS, 0x2000 }, - { WM8996_DSP1_RX_FILTERS_1, 0x200 }, - { WM8996_DSP1_RX_FILTERS_2, 0x10 }, - { WM8996_DSP1_DRC_1, 0x98 }, - { WM8996_DSP1_DRC_2, 0x845 }, - { WM8996_DSP1_RX_EQ_GAINS_1, 0x6318 }, - { WM8996_DSP1_RX_EQ_GAINS_2, 0x6300 }, - { WM8996_DSP1_RX_EQ_BAND_1_A, 0xfca }, - { WM8996_DSP1_RX_EQ_BAND_1_B, 0x400 }, - { WM8996_DSP1_RX_EQ_BAND_1_PG, 0xd8 }, - { WM8996_DSP1_RX_EQ_BAND_2_A, 0x1eb5 }, - { WM8996_DSP1_RX_EQ_BAND_2_B, 0xf145 }, - { WM8996_DSP1_RX_EQ_BAND_2_C, 0xb75 }, - { WM8996_DSP1_RX_EQ_BAND_2_PG, 0x1c5 }, - { WM8996_DSP1_RX_EQ_BAND_3_A, 0x1c58 }, - { WM8996_DSP1_RX_EQ_BAND_3_B, 0xf373 }, - { WM8996_DSP1_RX_EQ_BAND_3_C, 0xa54 }, - { WM8996_DSP1_RX_EQ_BAND_3_PG, 0x558 }, - { WM8996_DSP1_RX_EQ_BAND_4_A, 0x168e }, - { WM8996_DSP1_RX_EQ_BAND_4_B, 0xf829 }, - { WM8996_DSP1_RX_EQ_BAND_4_C, 0x7ad }, - { WM8996_DSP1_RX_EQ_BAND_4_PG, 0x1103 }, - { WM8996_DSP1_RX_EQ_BAND_5_A, 0x564 }, - { WM8996_DSP1_RX_EQ_BAND_5_B, 0x559 }, - { WM8996_DSP1_RX_EQ_BAND_5_PG, 0x4000 }, - { WM8996_DSP2_TX_LEFT_VOLUME, 0xc0 }, - { WM8996_DSP2_TX_RIGHT_VOLUME, 0xc0 }, - { WM8996_DSP2_RX_LEFT_VOLUME, 0xc0 }, - { WM8996_DSP2_RX_RIGHT_VOLUME, 0xc0 }, - { WM8996_DSP2_TX_FILTERS, 0x2000 }, - { WM8996_DSP2_RX_FILTERS_1, 0x200 }, - { WM8996_DSP2_RX_FILTERS_2, 0x10 }, - { WM8996_DSP2_DRC_1, 0x98 }, - { WM8996_DSP2_DRC_2, 0x845 }, - { WM8996_DSP2_RX_EQ_GAINS_1, 0x6318 }, - { WM8996_DSP2_RX_EQ_GAINS_2, 0x6300 }, - { WM8996_DSP2_RX_EQ_BAND_1_A, 0xfca }, - { WM8996_DSP2_RX_EQ_BAND_1_B, 0x400 }, - { WM8996_DSP2_RX_EQ_BAND_1_PG, 0xd8 }, - { WM8996_DSP2_RX_EQ_BAND_2_A, 0x1eb5 }, - { WM8996_DSP2_RX_EQ_BAND_2_B, 0xf145 }, - { WM8996_DSP2_RX_EQ_BAND_2_C, 0xb75 }, - { WM8996_DSP2_RX_EQ_BAND_2_PG, 0x1c5 }, - { WM8996_DSP2_RX_EQ_BAND_3_A, 0x1c58 }, - { WM8996_DSP2_RX_EQ_BAND_3_B, 0xf373 }, - { WM8996_DSP2_RX_EQ_BAND_3_C, 0xa54 }, - { WM8996_DSP2_RX_EQ_BAND_3_PG, 0x558 }, - { WM8996_DSP2_RX_EQ_BAND_4_A, 0x168e }, - { WM8996_DSP2_RX_EQ_BAND_4_B, 0xf829 }, - { WM8996_DSP2_RX_EQ_BAND_4_C, 0x7ad }, - { WM8996_DSP2_RX_EQ_BAND_4_PG, 0x1103 }, - { WM8996_DSP2_RX_EQ_BAND_5_A, 0x564 }, - { WM8996_DSP2_RX_EQ_BAND_5_B, 0x559 }, - { WM8996_DSP2_RX_EQ_BAND_5_PG, 0x4000 }, - { WM8996_DAC1_MIXER_VOLUMES, 0x0 }, - { WM8996_DAC1_LEFT_MIXER_ROUTING, 0x0 }, - { WM8996_DAC1_RIGHT_MIXER_ROUTING, 0x0 }, - { WM8996_DAC2_MIXER_VOLUMES, 0x0 }, - { WM8996_DAC2_LEFT_MIXER_ROUTING, 0x0 }, - { WM8996_DAC2_RIGHT_MIXER_ROUTING, 0x0 }, - { WM8996_DSP1_TX_LEFT_MIXER_ROUTING, 0x0 }, - { WM8996_DSP1_TX_RIGHT_MIXER_ROUTING, 0x0 }, - { WM8996_DSP2_TX_LEFT_MIXER_ROUTING, 0x0 }, - { WM8996_DSP2_TX_RIGHT_MIXER_ROUTING, 0x0 }, - { WM8996_DSP_TX_MIXER_SELECT, 0x0 }, - { WM8996_DAC_SOFTMUTE, 0x0 }, - { WM8996_OVERSAMPLING, 0xd }, - { WM8996_SIDETONE, 0x1040 }, - { WM8996_GPIO_1, 0xa101 }, - { WM8996_GPIO_2, 0xa101 }, - { WM8996_GPIO_3, 0xa101 }, - { WM8996_GPIO_4, 0xa101 }, - { WM8996_GPIO_5, 0xa101 }, - { WM8996_PULL_CONTROL_1, 0x0 }, - { WM8996_PULL_CONTROL_2, 0x140 }, - { WM8996_INTERRUPT_STATUS_1_MASK, 0x1f }, - { WM8996_INTERRUPT_STATUS_2_MASK, 0x1ecf }, - { WM8996_LEFT_PDM_SPEAKER, 0x0 }, - { WM8996_RIGHT_PDM_SPEAKER, 0x1 }, - { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 }, - { WM8996_PDM_SPEAKER_VOLUME, 0x66 }, - { WM8996_WRITE_SEQUENCER_0, 0x1 }, - { WM8996_WRITE_SEQUENCER_1, 0x1 }, - { WM8996_WRITE_SEQUENCER_3, 0x6 }, - { WM8996_WRITE_SEQUENCER_4, 0x40 }, - { WM8996_WRITE_SEQUENCER_5, 0x1 }, - { WM8996_WRITE_SEQUENCER_6, 0xf }, - { WM8996_WRITE_SEQUENCER_7, 0x6 }, - { WM8996_WRITE_SEQUENCER_8, 0x1 }, - { WM8996_WRITE_SEQUENCER_9, 0x3 }, - { WM8996_WRITE_SEQUENCER_10, 0x104 }, - { WM8996_WRITE_SEQUENCER_12, 0x60 }, - { WM8996_WRITE_SEQUENCER_13, 0x11 }, - { WM8996_WRITE_SEQUENCER_14, 0x401 }, - { WM8996_WRITE_SEQUENCER_16, 0x50 }, - { WM8996_WRITE_SEQUENCER_17, 0x3 }, - { WM8996_WRITE_SEQUENCER_18, 0x100 }, - { WM8996_WRITE_SEQUENCER_20, 0x51 }, - { WM8996_WRITE_SEQUENCER_21, 0x3 }, - { WM8996_WRITE_SEQUENCER_22, 0x104 }, - { WM8996_WRITE_SEQUENCER_23, 0xa }, - { WM8996_WRITE_SEQUENCER_24, 0x60 }, - { WM8996_WRITE_SEQUENCER_25, 0x3b }, - { WM8996_WRITE_SEQUENCER_26, 0x502 }, - { WM8996_WRITE_SEQUENCER_27, 0x100 }, - { WM8996_WRITE_SEQUENCER_28, 0x2fff }, - { WM8996_WRITE_SEQUENCER_32, 0x2fff }, - { WM8996_WRITE_SEQUENCER_36, 0x2fff }, - { WM8996_WRITE_SEQUENCER_40, 0x2fff }, - { WM8996_WRITE_SEQUENCER_44, 0x2fff }, - { WM8996_WRITE_SEQUENCER_48, 0x2fff }, - { WM8996_WRITE_SEQUENCER_52, 0x2fff }, - { WM8996_WRITE_SEQUENCER_56, 0x2fff }, - { WM8996_WRITE_SEQUENCER_60, 0x2fff }, - { WM8996_WRITE_SEQUENCER_64, 0x1 }, - { WM8996_WRITE_SEQUENCER_65, 0x1 }, - { WM8996_WRITE_SEQUENCER_67, 0x6 }, - { WM8996_WRITE_SEQUENCER_68, 0x40 }, - { WM8996_WRITE_SEQUENCER_69, 0x1 }, - { WM8996_WRITE_SEQUENCER_70, 0xf }, - { WM8996_WRITE_SEQUENCER_71, 0x6 }, - { WM8996_WRITE_SEQUENCER_72, 0x1 }, - { WM8996_WRITE_SEQUENCER_73, 0x3 }, - { WM8996_WRITE_SEQUENCER_74, 0x104 }, - { WM8996_WRITE_SEQUENCER_76, 0x60 }, - { WM8996_WRITE_SEQUENCER_77, 0x11 }, - { WM8996_WRITE_SEQUENCER_78, 0x401 }, - { WM8996_WRITE_SEQUENCER_80, 0x50 }, - { WM8996_WRITE_SEQUENCER_81, 0x3 }, - { WM8996_WRITE_SEQUENCER_82, 0x100 }, - { WM8996_WRITE_SEQUENCER_84, 0x60 }, - { WM8996_WRITE_SEQUENCER_85, 0x3b }, - { WM8996_WRITE_SEQUENCER_86, 0x502 }, - { WM8996_WRITE_SEQUENCER_87, 0x100 }, - { WM8996_WRITE_SEQUENCER_88, 0x2fff }, - { WM8996_WRITE_SEQUENCER_92, 0x2fff }, - { WM8996_WRITE_SEQUENCER_96, 0x2fff }, - { WM8996_WRITE_SEQUENCER_100, 0x2fff }, - { WM8996_WRITE_SEQUENCER_104, 0x2fff }, - { WM8996_WRITE_SEQUENCER_108, 0x2fff }, - { WM8996_WRITE_SEQUENCER_112, 0x2fff }, - { WM8996_WRITE_SEQUENCER_116, 0x2fff }, - { WM8996_WRITE_SEQUENCER_120, 0x2fff }, - { WM8996_WRITE_SEQUENCER_124, 0x2fff }, - { WM8996_WRITE_SEQUENCER_128, 0x1 }, - { WM8996_WRITE_SEQUENCER_129, 0x1 }, - { WM8996_WRITE_SEQUENCER_131, 0x6 }, - { WM8996_WRITE_SEQUENCER_132, 0x40 }, - { WM8996_WRITE_SEQUENCER_133, 0x1 }, - { WM8996_WRITE_SEQUENCER_134, 0xf }, - { WM8996_WRITE_SEQUENCER_135, 0x6 }, - { WM8996_WRITE_SEQUENCER_136, 0x1 }, - { WM8996_WRITE_SEQUENCER_137, 0x3 }, - { WM8996_WRITE_SEQUENCER_138, 0x106 }, - { WM8996_WRITE_SEQUENCER_140, 0x61 }, - { WM8996_WRITE_SEQUENCER_141, 0x11 }, - { WM8996_WRITE_SEQUENCER_142, 0x401 }, - { WM8996_WRITE_SEQUENCER_144, 0x50 }, - { WM8996_WRITE_SEQUENCER_145, 0x3 }, - { WM8996_WRITE_SEQUENCER_146, 0x102 }, - { WM8996_WRITE_SEQUENCER_148, 0x51 }, - { WM8996_WRITE_SEQUENCER_149, 0x3 }, - { WM8996_WRITE_SEQUENCER_150, 0x106 }, - { WM8996_WRITE_SEQUENCER_151, 0xa }, - { WM8996_WRITE_SEQUENCER_152, 0x61 }, - { WM8996_WRITE_SEQUENCER_153, 0x3b }, - { WM8996_WRITE_SEQUENCER_154, 0x502 }, - { WM8996_WRITE_SEQUENCER_155, 0x100 }, - { WM8996_WRITE_SEQUENCER_156, 0x2fff }, - { WM8996_WRITE_SEQUENCER_160, 0x2fff }, - { WM8996_WRITE_SEQUENCER_164, 0x2fff }, - { WM8996_WRITE_SEQUENCER_168, 0x2fff }, - { WM8996_WRITE_SEQUENCER_172, 0x2fff }, - { WM8996_WRITE_SEQUENCER_176, 0x2fff }, - { WM8996_WRITE_SEQUENCER_180, 0x2fff }, - { WM8996_WRITE_SEQUENCER_184, 0x2fff }, - { WM8996_WRITE_SEQUENCER_188, 0x2fff }, - { WM8996_WRITE_SEQUENCER_192, 0x1 }, - { WM8996_WRITE_SEQUENCER_193, 0x1 }, - { WM8996_WRITE_SEQUENCER_195, 0x6 }, - { WM8996_WRITE_SEQUENCER_196, 0x40 }, - { WM8996_WRITE_SEQUENCER_197, 0x1 }, - { WM8996_WRITE_SEQUENCER_198, 0xf }, - { WM8996_WRITE_SEQUENCER_199, 0x6 }, - { WM8996_WRITE_SEQUENCER_200, 0x1 }, - { WM8996_WRITE_SEQUENCER_201, 0x3 }, - { WM8996_WRITE_SEQUENCER_202, 0x106 }, - { WM8996_WRITE_SEQUENCER_204, 0x61 }, - { WM8996_WRITE_SEQUENCER_205, 0x11 }, - { WM8996_WRITE_SEQUENCER_206, 0x401 }, - { WM8996_WRITE_SEQUENCER_208, 0x50 }, - { WM8996_WRITE_SEQUENCER_209, 0x3 }, - { WM8996_WRITE_SEQUENCER_210, 0x102 }, - { WM8996_WRITE_SEQUENCER_212, 0x61 }, - { WM8996_WRITE_SEQUENCER_213, 0x3b }, - { WM8996_WRITE_SEQUENCER_214, 0x502 }, - { WM8996_WRITE_SEQUENCER_215, 0x100 }, - { WM8996_WRITE_SEQUENCER_216, 0x2fff }, - { WM8996_WRITE_SEQUENCER_220, 0x2fff }, - { WM8996_WRITE_SEQUENCER_224, 0x2fff }, - { WM8996_WRITE_SEQUENCER_228, 0x2fff }, - { WM8996_WRITE_SEQUENCER_232, 0x2fff }, - { WM8996_WRITE_SEQUENCER_236, 0x2fff }, - { WM8996_WRITE_SEQUENCER_240, 0x2fff }, - { WM8996_WRITE_SEQUENCER_244, 0x2fff }, - { WM8996_WRITE_SEQUENCER_248, 0x2fff }, - { WM8996_WRITE_SEQUENCER_252, 0x2fff }, - { WM8996_WRITE_SEQUENCER_256, 0x60 }, - { WM8996_WRITE_SEQUENCER_258, 0x601 }, - { WM8996_WRITE_SEQUENCER_260, 0x50 }, - { WM8996_WRITE_SEQUENCER_262, 0x100 }, - { WM8996_WRITE_SEQUENCER_264, 0x1 }, - { WM8996_WRITE_SEQUENCER_266, 0x104 }, - { WM8996_WRITE_SEQUENCER_267, 0x100 }, - { WM8996_WRITE_SEQUENCER_268, 0x2fff }, - { WM8996_WRITE_SEQUENCER_272, 0x2fff }, - { WM8996_WRITE_SEQUENCER_276, 0x2fff }, - { WM8996_WRITE_SEQUENCER_280, 0x2fff }, - { WM8996_WRITE_SEQUENCER_284, 0x2fff }, - { WM8996_WRITE_SEQUENCER_288, 0x2fff }, - { WM8996_WRITE_SEQUENCER_292, 0x2fff }, - { WM8996_WRITE_SEQUENCER_296, 0x2fff }, - { WM8996_WRITE_SEQUENCER_300, 0x2fff }, - { WM8996_WRITE_SEQUENCER_304, 0x2fff }, - { WM8996_WRITE_SEQUENCER_308, 0x2fff }, - { WM8996_WRITE_SEQUENCER_312, 0x2fff }, - { WM8996_WRITE_SEQUENCER_316, 0x2fff }, - { WM8996_WRITE_SEQUENCER_320, 0x61 }, - { WM8996_WRITE_SEQUENCER_322, 0x601 }, - { WM8996_WRITE_SEQUENCER_324, 0x50 }, - { WM8996_WRITE_SEQUENCER_326, 0x102 }, - { WM8996_WRITE_SEQUENCER_328, 0x1 }, - { WM8996_WRITE_SEQUENCER_330, 0x106 }, - { WM8996_WRITE_SEQUENCER_331, 0x100 }, - { WM8996_WRITE_SEQUENCER_332, 0x2fff }, - { WM8996_WRITE_SEQUENCER_336, 0x2fff }, - { WM8996_WRITE_SEQUENCER_340, 0x2fff }, - { WM8996_WRITE_SEQUENCER_344, 0x2fff }, - { WM8996_WRITE_SEQUENCER_348, 0x2fff }, - { WM8996_WRITE_SEQUENCER_352, 0x2fff }, - { WM8996_WRITE_SEQUENCER_356, 0x2fff }, - { WM8996_WRITE_SEQUENCER_360, 0x2fff }, - { WM8996_WRITE_SEQUENCER_364, 0x2fff }, - { WM8996_WRITE_SEQUENCER_368, 0x2fff }, - { WM8996_WRITE_SEQUENCER_372, 0x2fff }, - { WM8996_WRITE_SEQUENCER_376, 0x2fff }, - { WM8996_WRITE_SEQUENCER_380, 0x2fff }, - { WM8996_WRITE_SEQUENCER_384, 0x60 }, - { WM8996_WRITE_SEQUENCER_386, 0x601 }, - { WM8996_WRITE_SEQUENCER_388, 0x61 }, - { WM8996_WRITE_SEQUENCER_390, 0x601 }, - { WM8996_WRITE_SEQUENCER_392, 0x50 }, - { WM8996_WRITE_SEQUENCER_394, 0x300 }, - { WM8996_WRITE_SEQUENCER_396, 0x1 }, - { WM8996_WRITE_SEQUENCER_398, 0x304 }, - { WM8996_WRITE_SEQUENCER_400, 0x40 }, - { WM8996_WRITE_SEQUENCER_402, 0xf }, - { WM8996_WRITE_SEQUENCER_404, 0x1 }, - { WM8996_WRITE_SEQUENCER_407, 0x100 }, -}; - -static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 150, 0); -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0); -static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0); -static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(threedstereo_tlv, -1600, 183, 1); - -static const char *sidetone_hpf_text[] = { - "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" -}; - -static const struct soc_enum sidetone_hpf = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 7, 7, sidetone_hpf_text); - -static const char *hpf_mode_text[] = { - "HiFi", "Custom", "Voice" -}; - -static const struct soc_enum dsp1tx_hpf_mode = - SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 3, 3, hpf_mode_text); - -static const struct soc_enum dsp2tx_hpf_mode = - SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 3, 3, hpf_mode_text); - -static const char *hpf_cutoff_text[] = { - "50Hz", "75Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" -}; - -static const struct soc_enum dsp1tx_hpf_cutoff = - SOC_ENUM_SINGLE(WM8996_DSP1_TX_FILTERS, 0, 7, hpf_cutoff_text); - -static const struct soc_enum dsp2tx_hpf_cutoff = - SOC_ENUM_SINGLE(WM8996_DSP2_TX_FILTERS, 0, 7, hpf_cutoff_text); - -static void wm8996_set_retune_mobile(struct snd_soc_codec *codec, int block) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - struct wm8996_pdata *pdata = &wm8996->pdata; - int base, best, best_val, save, i, cfg, iface; - - if (!wm8996->num_retune_mobile_texts) - return; - - switch (block) { - case 0: - base = WM8996_DSP1_RX_EQ_GAINS_1; - if (snd_soc_read(codec, WM8996_POWER_MANAGEMENT_8) & - WM8996_DSP1RX_SRC) - iface = 1; - else - iface = 0; - break; - case 1: - base = WM8996_DSP1_RX_EQ_GAINS_2; - if (snd_soc_read(codec, WM8996_POWER_MANAGEMENT_8) & - WM8996_DSP2RX_SRC) - iface = 1; - else - iface = 0; - break; - default: - return; - } - - /* Find the version of the currently selected configuration - * with the nearest sample rate. */ - cfg = wm8996->retune_mobile_cfg[block]; - best = 0; - best_val = INT_MAX; - for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { - if (strcmp(pdata->retune_mobile_cfgs[i].name, - wm8996->retune_mobile_texts[cfg]) == 0 && - abs(pdata->retune_mobile_cfgs[i].rate - - wm8996->rx_rate[iface]) < best_val) { - best = i; - best_val = abs(pdata->retune_mobile_cfgs[i].rate - - wm8996->rx_rate[iface]); - } - } - - dev_dbg(codec->dev, "ReTune Mobile %d %s/%dHz for %dHz sample rate\n", - block, - pdata->retune_mobile_cfgs[best].name, - pdata->retune_mobile_cfgs[best].rate, - wm8996->rx_rate[iface]); - - /* The EQ will be disabled while reconfiguring it, remember the - * current configuration. - */ - save = snd_soc_read(codec, base); - save &= WM8996_DSP1RX_EQ_ENA; - - for (i = 0; i < ARRAY_SIZE(pdata->retune_mobile_cfgs[best].regs); i++) - snd_soc_update_bits(codec, base + i, 0xffff, - pdata->retune_mobile_cfgs[best].regs[i]); - - snd_soc_update_bits(codec, base, WM8996_DSP1RX_EQ_ENA, save); -} - -/* Icky as hell but saves code duplication */ -static int wm8996_get_retune_mobile_block(const char *name) -{ - if (strcmp(name, "DSP1 EQ Mode") == 0) - return 0; - if (strcmp(name, "DSP2 EQ Mode") == 0) - return 1; - return -EINVAL; -} - -static int wm8996_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - struct wm8996_pdata *pdata = &wm8996->pdata; - int block = wm8996_get_retune_mobile_block(kcontrol->id.name); - int value = ucontrol->value.integer.value[0]; - - if (block < 0) - return block; - - if (value >= pdata->num_retune_mobile_cfgs) - return -EINVAL; - - wm8996->retune_mobile_cfg[block] = value; - - wm8996_set_retune_mobile(codec, block); - - return 0; -} - -static int wm8996_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int block = wm8996_get_retune_mobile_block(kcontrol->id.name); - - ucontrol->value.enumerated.item[0] = wm8996->retune_mobile_cfg[block]; - - return 0; -} - -static const struct snd_kcontrol_new wm8996_snd_controls[] = { -SOC_DOUBLE_R_TLV("Capture Volume", WM8996_LEFT_LINE_INPUT_VOLUME, - WM8996_RIGHT_LINE_INPUT_VOLUME, 0, 31, 0, inpga_tlv), -SOC_DOUBLE_R("Capture ZC Switch", WM8996_LEFT_LINE_INPUT_VOLUME, - WM8996_RIGHT_LINE_INPUT_VOLUME, 5, 1, 0), - -SOC_DOUBLE_TLV("DAC1 Sidetone Volume", WM8996_DAC1_MIXER_VOLUMES, - 0, 5, 24, 0, sidetone_tlv), -SOC_DOUBLE_TLV("DAC2 Sidetone Volume", WM8996_DAC2_MIXER_VOLUMES, - 0, 5, 24, 0, sidetone_tlv), -SOC_SINGLE("Sidetone LPF Switch", WM8996_SIDETONE, 12, 1, 0), -SOC_ENUM("Sidetone HPF Cut-off", sidetone_hpf), -SOC_SINGLE("Sidetone HPF Switch", WM8996_SIDETONE, 6, 1, 0), - -SOC_DOUBLE_R_TLV("DSP1 Capture Volume", WM8996_DSP1_TX_LEFT_VOLUME, - WM8996_DSP1_TX_RIGHT_VOLUME, 1, 96, 0, digital_tlv), -SOC_DOUBLE_R_TLV("DSP2 Capture Volume", WM8996_DSP2_TX_LEFT_VOLUME, - WM8996_DSP2_TX_RIGHT_VOLUME, 1, 96, 0, digital_tlv), - -SOC_SINGLE("DSP1 Capture Notch Filter Switch", WM8996_DSP1_TX_FILTERS, - 13, 1, 0), -SOC_DOUBLE("DSP1 Capture HPF Switch", WM8996_DSP1_TX_FILTERS, 12, 11, 1, 0), -SOC_ENUM("DSP1 Capture HPF Mode", dsp1tx_hpf_mode), -SOC_ENUM("DSP1 Capture HPF Cutoff", dsp1tx_hpf_cutoff), - -SOC_SINGLE("DSP2 Capture Notch Filter Switch", WM8996_DSP2_TX_FILTERS, - 13, 1, 0), -SOC_DOUBLE("DSP2 Capture HPF Switch", WM8996_DSP2_TX_FILTERS, 12, 11, 1, 0), -SOC_ENUM("DSP2 Capture HPF Mode", dsp2tx_hpf_mode), -SOC_ENUM("DSP2 Capture HPF Cutoff", dsp2tx_hpf_cutoff), - -SOC_DOUBLE_R_TLV("DSP1 Playback Volume", WM8996_DSP1_RX_LEFT_VOLUME, - WM8996_DSP1_RX_RIGHT_VOLUME, 1, 112, 0, digital_tlv), -SOC_SINGLE("DSP1 Playback Switch", WM8996_DSP1_RX_FILTERS_1, 9, 1, 1), - -SOC_DOUBLE_R_TLV("DSP2 Playback Volume", WM8996_DSP2_RX_LEFT_VOLUME, - WM8996_DSP2_RX_RIGHT_VOLUME, 1, 112, 0, digital_tlv), -SOC_SINGLE("DSP2 Playback Switch", WM8996_DSP2_RX_FILTERS_1, 9, 1, 1), - -SOC_DOUBLE_R_TLV("DAC1 Volume", WM8996_DAC1_LEFT_VOLUME, - WM8996_DAC1_RIGHT_VOLUME, 1, 112, 0, digital_tlv), -SOC_DOUBLE_R("DAC1 Switch", WM8996_DAC1_LEFT_VOLUME, - WM8996_DAC1_RIGHT_VOLUME, 9, 1, 1), - -SOC_DOUBLE_R_TLV("DAC2 Volume", WM8996_DAC2_LEFT_VOLUME, - WM8996_DAC2_RIGHT_VOLUME, 1, 112, 0, digital_tlv), -SOC_DOUBLE_R("DAC2 Switch", WM8996_DAC2_LEFT_VOLUME, - WM8996_DAC2_RIGHT_VOLUME, 9, 1, 1), - -SOC_SINGLE("Speaker High Performance Switch", WM8996_OVERSAMPLING, 3, 1, 0), -SOC_SINGLE("DMIC High Performance Switch", WM8996_OVERSAMPLING, 2, 1, 0), -SOC_SINGLE("ADC High Performance Switch", WM8996_OVERSAMPLING, 1, 1, 0), -SOC_SINGLE("DAC High Performance Switch", WM8996_OVERSAMPLING, 0, 1, 0), - -SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0), -SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0), - -SOC_SINGLE("DSP1 3D Stereo Switch", WM8996_DSP1_RX_FILTERS_2, 8, 1, 0), -SOC_SINGLE("DSP2 3D Stereo Switch", WM8996_DSP2_RX_FILTERS_2, 8, 1, 0), - -SOC_SINGLE_TLV("DSP1 3D Stereo Volume", WM8996_DSP1_RX_FILTERS_2, 10, 15, - 0, threedstereo_tlv), -SOC_SINGLE_TLV("DSP2 3D Stereo Volume", WM8996_DSP2_RX_FILTERS_2, 10, 15, - 0, threedstereo_tlv), - -SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4, - 8, 0, out_digital_tlv), -SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4, - 8, 0, out_digital_tlv), - -SOC_DOUBLE_R_TLV("Output 1 Volume", WM8996_OUTPUT1_LEFT_VOLUME, - WM8996_OUTPUT1_RIGHT_VOLUME, 0, 12, 0, out_tlv), -SOC_DOUBLE_R("Output 1 ZC Switch", WM8996_OUTPUT1_LEFT_VOLUME, - WM8996_OUTPUT1_RIGHT_VOLUME, 7, 1, 0), - -SOC_DOUBLE_R_TLV("Output 2 Volume", WM8996_OUTPUT2_LEFT_VOLUME, - WM8996_OUTPUT2_RIGHT_VOLUME, 0, 12, 0, out_tlv), -SOC_DOUBLE_R("Output 2 ZC Switch", WM8996_OUTPUT2_LEFT_VOLUME, - WM8996_OUTPUT2_RIGHT_VOLUME, 7, 1, 0), - -SOC_DOUBLE_TLV("Speaker Volume", WM8996_PDM_SPEAKER_VOLUME, 0, 4, 8, 0, - spk_tlv), -SOC_DOUBLE_R("Speaker Switch", WM8996_LEFT_PDM_SPEAKER, - WM8996_RIGHT_PDM_SPEAKER, 3, 1, 1), -SOC_DOUBLE_R("Speaker ZC Switch", WM8996_LEFT_PDM_SPEAKER, - WM8996_RIGHT_PDM_SPEAKER, 2, 1, 0), - -SOC_SINGLE("DSP1 EQ Switch", WM8996_DSP1_RX_EQ_GAINS_1, 0, 1, 0), -SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0), - -SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0), -SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0), -SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0), -SND_SOC_BYTES_MASK("DSP1 DRC", WM8996_DSP1_DRC_1, 5, - WM8996_DSP1RX_DRC_ENA | WM8996_DSP1TXL_DRC_ENA | - WM8996_DSP1TXR_DRC_ENA), - -SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0), -SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0), -SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0), -SND_SOC_BYTES_MASK("DSP2 DRC", WM8996_DSP2_DRC_1, 5, - WM8996_DSP2RX_DRC_ENA | WM8996_DSP2TXL_DRC_ENA | - WM8996_DSP2TXR_DRC_ENA), -}; - -static const struct snd_kcontrol_new wm8996_eq_controls[] = { -SOC_SINGLE_TLV("DSP1 EQ B1 Volume", WM8996_DSP1_RX_EQ_GAINS_1, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("DSP1 EQ B2 Volume", WM8996_DSP1_RX_EQ_GAINS_1, 6, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("DSP1 EQ B3 Volume", WM8996_DSP1_RX_EQ_GAINS_1, 1, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("DSP1 EQ B4 Volume", WM8996_DSP1_RX_EQ_GAINS_2, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("DSP1 EQ B5 Volume", WM8996_DSP1_RX_EQ_GAINS_2, 6, 31, 0, - eq_tlv), - -SOC_SINGLE_TLV("DSP2 EQ B1 Volume", WM8996_DSP2_RX_EQ_GAINS_1, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("DSP2 EQ B2 Volume", WM8996_DSP2_RX_EQ_GAINS_1, 6, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("DSP2 EQ B3 Volume", WM8996_DSP2_RX_EQ_GAINS_1, 1, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("DSP2 EQ B4 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 11, 31, 0, - eq_tlv), -SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 6, 31, 0, - eq_tlv), -}; - -static void wm8996_bg_enable(struct snd_soc_codec *codec) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - - wm8996->bg_ena++; - if (wm8996->bg_ena == 1) { - snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, - WM8996_BG_ENA, WM8996_BG_ENA); - msleep(2); - } -} - -static void wm8996_bg_disable(struct snd_soc_codec *codec) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - - wm8996->bg_ena--; - if (!wm8996->bg_ena) - snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, - WM8996_BG_ENA, 0); -} - -static int bg_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - int ret = 0; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - wm8996_bg_enable(codec); - break; - case SND_SOC_DAPM_POST_PMD: - wm8996_bg_disable(codec); - break; - default: - BUG(); - ret = -EINVAL; - } - - return ret; -} - -static int cp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - int ret = 0; - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - msleep(5); - break; - default: - BUG(); - ret = -EINVAL; - } - - return 0; -} - -static int rmv_short_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(w->codec); - - /* Record which outputs we enabled */ - switch (event) { - case SND_SOC_DAPM_PRE_PMD: - wm8996->hpout_pending &= ~w->shift; - break; - case SND_SOC_DAPM_PRE_PMU: - wm8996->hpout_pending |= w->shift; - break; - default: - BUG(); - return -EINVAL; - } - - return 0; -} - -static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) -{ - struct i2c_client *i2c = to_i2c_client(codec->dev); - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int ret; - unsigned long timeout = 200; - - snd_soc_write(codec, WM8996_DC_SERVO_2, mask); - - /* Use the interrupt if possible */ - do { - if (i2c->irq) { - timeout = wait_for_completion_timeout(&wm8996->dcs_done, - msecs_to_jiffies(200)); - if (timeout == 0) - dev_err(codec->dev, "DC servo timed out\n"); - - } else { - msleep(1); - timeout--; - } - - ret = snd_soc_read(codec, WM8996_DC_SERVO_2); - dev_dbg(codec->dev, "DC servo state: %x\n", ret); - } while (timeout && ret & mask); - - if (timeout == 0) - dev_err(codec->dev, "DC servo timed out for %x\n", mask); - else - dev_dbg(codec->dev, "DC servo complete for %x\n", mask); -} - -static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, - enum snd_soc_dapm_type event, int subseq) -{ - struct snd_soc_codec *codec = container_of(dapm, - struct snd_soc_codec, dapm); - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - u16 val, mask; - - /* Complete any pending DC servo starts */ - if (wm8996->dcs_pending) { - dev_dbg(codec->dev, "Starting DC servo for %x\n", - wm8996->dcs_pending); - - /* Trigger a startup sequence */ - wait_for_dc_servo(codec, wm8996->dcs_pending - << WM8996_DCS_TRIG_STARTUP_0_SHIFT); - - wm8996->dcs_pending = 0; - } - - if (wm8996->hpout_pending != wm8996->hpout_ena) { - dev_dbg(codec->dev, "Applying RMV_SHORTs %x->%x\n", - wm8996->hpout_ena, wm8996->hpout_pending); - - val = 0; - mask = 0; - if (wm8996->hpout_pending & HPOUT1L) { - val |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP; - mask |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP; - } else { - mask |= WM8996_HPOUT1L_RMV_SHORT | - WM8996_HPOUT1L_OUTP | - WM8996_HPOUT1L_DLY; - } - - if (wm8996->hpout_pending & HPOUT1R) { - val |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP; - mask |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP; - } else { - mask |= WM8996_HPOUT1R_RMV_SHORT | - WM8996_HPOUT1R_OUTP | - WM8996_HPOUT1R_DLY; - } - - snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, mask, val); - - val = 0; - mask = 0; - if (wm8996->hpout_pending & HPOUT2L) { - val |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP; - mask |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP; - } else { - mask |= WM8996_HPOUT2L_RMV_SHORT | - WM8996_HPOUT2L_OUTP | - WM8996_HPOUT2L_DLY; - } - - if (wm8996->hpout_pending & HPOUT2R) { - val |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP; - mask |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP; - } else { - mask |= WM8996_HPOUT2R_RMV_SHORT | - WM8996_HPOUT2R_OUTP | - WM8996_HPOUT2R_DLY; - } - - snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_2, mask, val); - - wm8996->hpout_ena = wm8996->hpout_pending; - } -} - -static int dcs_start(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(w->codec); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - wm8996->dcs_pending |= 1 << w->shift; - break; - default: - BUG(); - return -EINVAL; - } - - return 0; -} - -static const char *sidetone_text[] = { - "IN1", "IN2", -}; - -static const struct soc_enum left_sidetone_enum = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 0, 2, sidetone_text); - -static const struct snd_kcontrol_new left_sidetone = - SOC_DAPM_ENUM("Left Sidetone", left_sidetone_enum); - -static const struct soc_enum right_sidetone_enum = - SOC_ENUM_SINGLE(WM8996_SIDETONE, 1, 2, sidetone_text); - -static const struct snd_kcontrol_new right_sidetone = - SOC_DAPM_ENUM("Right Sidetone", right_sidetone_enum); - -static const char *spk_text[] = { - "DAC1L", "DAC1R", "DAC2L", "DAC2R" -}; - -static const struct soc_enum spkl_enum = - SOC_ENUM_SINGLE(WM8996_LEFT_PDM_SPEAKER, 0, 4, spk_text); - -static const struct snd_kcontrol_new spkl_mux = - SOC_DAPM_ENUM("SPKL", spkl_enum); - -static const struct soc_enum spkr_enum = - SOC_ENUM_SINGLE(WM8996_RIGHT_PDM_SPEAKER, 0, 4, spk_text); - -static const struct snd_kcontrol_new spkr_mux = - SOC_DAPM_ENUM("SPKR", spkr_enum); - -static const char *dsp1rx_text[] = { - "AIF1", "AIF2" -}; - -static const struct soc_enum dsp1rx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 0, 2, dsp1rx_text); - -static const struct snd_kcontrol_new dsp1rx = - SOC_DAPM_ENUM("DSP1RX", dsp1rx_enum); - -static const char *dsp2rx_text[] = { - "AIF2", "AIF1" -}; - -static const struct soc_enum dsp2rx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 4, 2, dsp2rx_text); - -static const struct snd_kcontrol_new dsp2rx = - SOC_DAPM_ENUM("DSP2RX", dsp2rx_enum); - -static const char *aif2tx_text[] = { - "DSP2", "DSP1", "AIF1" -}; - -static const struct soc_enum aif2tx_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_8, 6, 3, aif2tx_text); - -static const struct snd_kcontrol_new aif2tx = - SOC_DAPM_ENUM("AIF2TX", aif2tx_enum); - -static const char *inmux_text[] = { - "ADC", "DMIC1", "DMIC2" -}; - -static const struct soc_enum in1_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 0, 3, inmux_text); - -static const struct snd_kcontrol_new in1_mux = - SOC_DAPM_ENUM("IN1 Mux", in1_enum); - -static const struct soc_enum in2_enum = - SOC_ENUM_SINGLE(WM8996_POWER_MANAGEMENT_7, 4, 3, inmux_text); - -static const struct snd_kcontrol_new in2_mux = - SOC_DAPM_ENUM("IN2 Mux", in2_enum); - -static const struct snd_kcontrol_new dac2r_mix[] = { -SOC_DAPM_SINGLE("Right Sidetone Switch", WM8996_DAC2_RIGHT_MIXER_ROUTING, - 5, 1, 0), -SOC_DAPM_SINGLE("Left Sidetone Switch", WM8996_DAC2_RIGHT_MIXER_ROUTING, - 4, 1, 0), -SOC_DAPM_SINGLE("DSP2 Switch", WM8996_DAC2_RIGHT_MIXER_ROUTING, 1, 1, 0), -SOC_DAPM_SINGLE("DSP1 Switch", WM8996_DAC2_RIGHT_MIXER_ROUTING, 0, 1, 0), -}; - -static const struct snd_kcontrol_new dac2l_mix[] = { -SOC_DAPM_SINGLE("Right Sidetone Switch", WM8996_DAC2_LEFT_MIXER_ROUTING, - 5, 1, 0), -SOC_DAPM_SINGLE("Left Sidetone Switch", WM8996_DAC2_LEFT_MIXER_ROUTING, - 4, 1, 0), -SOC_DAPM_SINGLE("DSP2 Switch", WM8996_DAC2_LEFT_MIXER_ROUTING, 1, 1, 0), -SOC_DAPM_SINGLE("DSP1 Switch", WM8996_DAC2_LEFT_MIXER_ROUTING, 0, 1, 0), -}; - -static const struct snd_kcontrol_new dac1r_mix[] = { -SOC_DAPM_SINGLE("Right Sidetone Switch", WM8996_DAC1_RIGHT_MIXER_ROUTING, - 5, 1, 0), -SOC_DAPM_SINGLE("Left Sidetone Switch", WM8996_DAC1_RIGHT_MIXER_ROUTING, - 4, 1, 0), -SOC_DAPM_SINGLE("DSP2 Switch", WM8996_DAC1_RIGHT_MIXER_ROUTING, 1, 1, 0), -SOC_DAPM_SINGLE("DSP1 Switch", WM8996_DAC1_RIGHT_MIXER_ROUTING, 0, 1, 0), -}; - -static const struct snd_kcontrol_new dac1l_mix[] = { -SOC_DAPM_SINGLE("Right Sidetone Switch", WM8996_DAC1_LEFT_MIXER_ROUTING, - 5, 1, 0), -SOC_DAPM_SINGLE("Left Sidetone Switch", WM8996_DAC1_LEFT_MIXER_ROUTING, - 4, 1, 0), -SOC_DAPM_SINGLE("DSP2 Switch", WM8996_DAC1_LEFT_MIXER_ROUTING, 1, 1, 0), -SOC_DAPM_SINGLE("DSP1 Switch", WM8996_DAC1_LEFT_MIXER_ROUTING, 0, 1, 0), -}; - -static const struct snd_kcontrol_new dsp1txl[] = { -SOC_DAPM_SINGLE("IN1 Switch", WM8996_DSP1_TX_LEFT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8996_DSP1_TX_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new dsp1txr[] = { -SOC_DAPM_SINGLE("IN1 Switch", WM8996_DSP1_TX_RIGHT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8996_DSP1_TX_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new dsp2txl[] = { -SOC_DAPM_SINGLE("IN1 Switch", WM8996_DSP2_TX_LEFT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8996_DSP2_TX_LEFT_MIXER_ROUTING, - 0, 1, 0), -}; - -static const struct snd_kcontrol_new dsp2txr[] = { -SOC_DAPM_SINGLE("IN1 Switch", WM8996_DSP2_TX_RIGHT_MIXER_ROUTING, - 1, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8996_DSP2_TX_RIGHT_MIXER_ROUTING, - 0, 1, 0), -}; - - -static const struct snd_soc_dapm_widget wm8996_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1LN"), -SND_SOC_DAPM_INPUT("IN1LP"), -SND_SOC_DAPM_INPUT("IN1RN"), -SND_SOC_DAPM_INPUT("IN1RP"), - -SND_SOC_DAPM_INPUT("IN2LN"), -SND_SOC_DAPM_INPUT("IN2LP"), -SND_SOC_DAPM_INPUT("IN2RN"), -SND_SOC_DAPM_INPUT("IN2RP"), - -SND_SOC_DAPM_INPUT("DMIC1DAT"), -SND_SOC_DAPM_INPUT("DMIC2DAT"), - -SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), -SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, - SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0), -SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0), -SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0), - -SND_SOC_DAPM_PGA("IN1L PGA", WM8996_POWER_MANAGEMENT_2, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("IN1R PGA", WM8996_POWER_MANAGEMENT_2, 4, 0, NULL, 0), - -SND_SOC_DAPM_MUX("IN1L Mux", WM8996_POWER_MANAGEMENT_7, 2, 0, &in1_mux), -SND_SOC_DAPM_MUX("IN1R Mux", WM8996_POWER_MANAGEMENT_7, 3, 0, &in1_mux), -SND_SOC_DAPM_MUX("IN2L Mux", WM8996_POWER_MANAGEMENT_7, 6, 0, &in2_mux), -SND_SOC_DAPM_MUX("IN2R Mux", WM8996_POWER_MANAGEMENT_7, 7, 0, &in2_mux), - -SND_SOC_DAPM_SUPPLY("DMIC2", WM8996_POWER_MANAGEMENT_7, 9, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DMIC1", WM8996_POWER_MANAGEMENT_7, 8, 0, NULL, 0), - -SND_SOC_DAPM_ADC("DMIC2L", NULL, WM8996_POWER_MANAGEMENT_3, 5, 0), -SND_SOC_DAPM_ADC("DMIC2R", NULL, WM8996_POWER_MANAGEMENT_3, 4, 0), -SND_SOC_DAPM_ADC("DMIC1L", NULL, WM8996_POWER_MANAGEMENT_3, 3, 0), -SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8996_POWER_MANAGEMENT_3, 2, 0), - -SND_SOC_DAPM_ADC("ADCL", NULL, WM8996_POWER_MANAGEMENT_3, 1, 0), -SND_SOC_DAPM_ADC("ADCR", NULL, WM8996_POWER_MANAGEMENT_3, 0, 0), - -SND_SOC_DAPM_MUX("Left Sidetone", SND_SOC_NOPM, 0, 0, &left_sidetone), -SND_SOC_DAPM_MUX("Right Sidetone", SND_SOC_NOPM, 0, 0, &right_sidetone), - -SND_SOC_DAPM_AIF_IN("DSP2RXL", NULL, 0, WM8996_POWER_MANAGEMENT_3, 11, 0), -SND_SOC_DAPM_AIF_IN("DSP2RXR", NULL, 1, WM8996_POWER_MANAGEMENT_3, 10, 0), -SND_SOC_DAPM_AIF_IN("DSP1RXL", NULL, 0, WM8996_POWER_MANAGEMENT_3, 9, 0), -SND_SOC_DAPM_AIF_IN("DSP1RXR", NULL, 1, WM8996_POWER_MANAGEMENT_3, 8, 0), - -SND_SOC_DAPM_MIXER("DSP2TXL", WM8996_POWER_MANAGEMENT_5, 11, 0, - dsp2txl, ARRAY_SIZE(dsp2txl)), -SND_SOC_DAPM_MIXER("DSP2TXR", WM8996_POWER_MANAGEMENT_5, 10, 0, - dsp2txr, ARRAY_SIZE(dsp2txr)), -SND_SOC_DAPM_MIXER("DSP1TXL", WM8996_POWER_MANAGEMENT_5, 9, 0, - dsp1txl, ARRAY_SIZE(dsp1txl)), -SND_SOC_DAPM_MIXER("DSP1TXR", WM8996_POWER_MANAGEMENT_5, 8, 0, - dsp1txr, ARRAY_SIZE(dsp1txr)), - -SND_SOC_DAPM_MIXER("DAC2L Mixer", SND_SOC_NOPM, 0, 0, - dac2l_mix, ARRAY_SIZE(dac2l_mix)), -SND_SOC_DAPM_MIXER("DAC2R Mixer", SND_SOC_NOPM, 0, 0, - dac2r_mix, ARRAY_SIZE(dac2r_mix)), -SND_SOC_DAPM_MIXER("DAC1L Mixer", SND_SOC_NOPM, 0, 0, - dac1l_mix, ARRAY_SIZE(dac1l_mix)), -SND_SOC_DAPM_MIXER("DAC1R Mixer", SND_SOC_NOPM, 0, 0, - dac1r_mix, ARRAY_SIZE(dac1r_mix)), - -SND_SOC_DAPM_DAC("DAC2L", NULL, WM8996_POWER_MANAGEMENT_5, 3, 0), -SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0), -SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0), -SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0), - -SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, WM8996_POWER_MANAGEMENT_4, 9, 0), -SND_SOC_DAPM_AIF_IN("AIF2RX0", NULL, 1, WM8996_POWER_MANAGEMENT_4, 8, 0), - -SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, WM8996_POWER_MANAGEMENT_6, 9, 0), -SND_SOC_DAPM_AIF_OUT("AIF2TX0", NULL, 1, WM8996_POWER_MANAGEMENT_6, 8, 0), - -SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 5, WM8996_POWER_MANAGEMENT_4, 5, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 4, WM8996_POWER_MANAGEMENT_4, 4, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 3, WM8996_POWER_MANAGEMENT_4, 3, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 2, WM8996_POWER_MANAGEMENT_4, 2, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 1, WM8996_POWER_MANAGEMENT_4, 1, 0), -SND_SOC_DAPM_AIF_IN("AIF1RX0", NULL, 0, WM8996_POWER_MANAGEMENT_4, 0, 0), - -SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 5, WM8996_POWER_MANAGEMENT_6, 5, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 4, WM8996_POWER_MANAGEMENT_6, 4, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 3, WM8996_POWER_MANAGEMENT_6, 3, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 2, WM8996_POWER_MANAGEMENT_6, 2, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 1, WM8996_POWER_MANAGEMENT_6, 1, 0), -SND_SOC_DAPM_AIF_OUT("AIF1TX0", NULL, 0, WM8996_POWER_MANAGEMENT_6, 0, 0), - -/* We route as stereo pairs so define some dummy widgets to squash - * things down for now. RXA = 0,1, RXB = 2,3 and so on */ -SND_SOC_DAPM_PGA("AIF1RXA", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_PGA("AIF1RXB", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_PGA("AIF1RXC", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_PGA("AIF2RX", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_PGA("DSP2TX", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_MUX("DSP1RX", SND_SOC_NOPM, 0, 0, &dsp1rx), -SND_SOC_DAPM_MUX("DSP2RX", SND_SOC_NOPM, 0, 0, &dsp2rx), -SND_SOC_DAPM_MUX("AIF2TX", SND_SOC_NOPM, 0, 0, &aif2tx), - -SND_SOC_DAPM_MUX("SPKL", SND_SOC_NOPM, 0, 0, &spkl_mux), -SND_SOC_DAPM_MUX("SPKR", SND_SOC_NOPM, 0, 0, &spkr_mux), -SND_SOC_DAPM_PGA("SPKL PGA", WM8996_LEFT_PDM_SPEAKER, 4, 0, NULL, 0), -SND_SOC_DAPM_PGA("SPKR PGA", WM8996_RIGHT_PDM_SPEAKER, 4, 0, NULL, 0), - -SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8996_POWER_MANAGEMENT_1, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8996_ANALOGUE_HP_2, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8996_DC_SERVO_1, 2, 0, dcs_start, - SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0, - rmv_short_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8996_POWER_MANAGEMENT_1, 6, 0,NULL, 0), -SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8996_ANALOGUE_HP_2, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8996_DC_SERVO_1, 3, 0, dcs_start, - SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0, - rmv_short_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8996_POWER_MANAGEMENT_1, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8996_ANALOGUE_HP_1, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8996_DC_SERVO_1, 0, 0, dcs_start, - SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0, - rmv_short_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8996_POWER_MANAGEMENT_1, 4, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8996_ANALOGUE_HP_1, 1, 0, NULL, 0), -SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8996_DC_SERVO_1, 1, 0, dcs_start, - SND_SOC_DAPM_POST_PMU), -SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0, - rmv_short_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_OUTPUT("HPOUT1L"), -SND_SOC_DAPM_OUTPUT("HPOUT1R"), -SND_SOC_DAPM_OUTPUT("HPOUT2L"), -SND_SOC_DAPM_OUTPUT("HPOUT2R"), -SND_SOC_DAPM_OUTPUT("SPKDAT"), -}; - -static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { - { "AIFCLK", NULL, "SYSCLK" }, - { "SYSDSPCLK", NULL, "SYSCLK" }, - { "Charge Pump", NULL, "SYSCLK" }, - { "Charge Pump", NULL, "CPVDD" }, - - { "MICB1", NULL, "LDO2" }, - { "MICB1", NULL, "MICB1 Audio" }, - { "MICB1", NULL, "Bandgap" }, - { "MICB2", NULL, "LDO2" }, - { "MICB2", NULL, "MICB2 Audio" }, - { "MICB2", NULL, "Bandgap" }, - - { "AIF1RX0", NULL, "AIF1 Playback" }, - { "AIF1RX1", NULL, "AIF1 Playback" }, - { "AIF1RX2", NULL, "AIF1 Playback" }, - { "AIF1RX3", NULL, "AIF1 Playback" }, - { "AIF1RX4", NULL, "AIF1 Playback" }, - { "AIF1RX5", NULL, "AIF1 Playback" }, - - { "AIF2RX0", NULL, "AIF2 Playback" }, - { "AIF2RX1", NULL, "AIF2 Playback" }, - - { "AIF1 Capture", NULL, "AIF1TX0" }, - { "AIF1 Capture", NULL, "AIF1TX1" }, - { "AIF1 Capture", NULL, "AIF1TX2" }, - { "AIF1 Capture", NULL, "AIF1TX3" }, - { "AIF1 Capture", NULL, "AIF1TX4" }, - { "AIF1 Capture", NULL, "AIF1TX5" }, - - { "AIF2 Capture", NULL, "AIF2TX0" }, - { "AIF2 Capture", NULL, "AIF2TX1" }, - - { "IN1L PGA", NULL, "IN2LN" }, - { "IN1L PGA", NULL, "IN2LP" }, - { "IN1L PGA", NULL, "IN1LN" }, - { "IN1L PGA", NULL, "IN1LP" }, - { "IN1L PGA", NULL, "Bandgap" }, - - { "IN1R PGA", NULL, "IN2RN" }, - { "IN1R PGA", NULL, "IN2RP" }, - { "IN1R PGA", NULL, "IN1RN" }, - { "IN1R PGA", NULL, "IN1RP" }, - { "IN1R PGA", NULL, "Bandgap" }, - - { "ADCL", NULL, "IN1L PGA" }, - - { "ADCR", NULL, "IN1R PGA" }, - - { "DMIC1L", NULL, "DMIC1DAT" }, - { "DMIC1R", NULL, "DMIC1DAT" }, - { "DMIC2L", NULL, "DMIC2DAT" }, - { "DMIC2R", NULL, "DMIC2DAT" }, - - { "DMIC2L", NULL, "DMIC2" }, - { "DMIC2R", NULL, "DMIC2" }, - { "DMIC1L", NULL, "DMIC1" }, - { "DMIC1R", NULL, "DMIC1" }, - - { "IN1L Mux", "ADC", "ADCL" }, - { "IN1L Mux", "DMIC1", "DMIC1L" }, - { "IN1L Mux", "DMIC2", "DMIC2L" }, - - { "IN1R Mux", "ADC", "ADCR" }, - { "IN1R Mux", "DMIC1", "DMIC1R" }, - { "IN1R Mux", "DMIC2", "DMIC2R" }, - - { "IN2L Mux", "ADC", "ADCL" }, - { "IN2L Mux", "DMIC1", "DMIC1L" }, - { "IN2L Mux", "DMIC2", "DMIC2L" }, - - { "IN2R Mux", "ADC", "ADCR" }, - { "IN2R Mux", "DMIC1", "DMIC1R" }, - { "IN2R Mux", "DMIC2", "DMIC2R" }, - - { "Left Sidetone", "IN1", "IN1L Mux" }, - { "Left Sidetone", "IN2", "IN2L Mux" }, - - { "Right Sidetone", "IN1", "IN1R Mux" }, - { "Right Sidetone", "IN2", "IN2R Mux" }, - - { "DSP1TXL", "IN1 Switch", "IN1L Mux" }, - { "DSP1TXR", "IN1 Switch", "IN1R Mux" }, - - { "DSP2TXL", "IN1 Switch", "IN2L Mux" }, - { "DSP2TXR", "IN1 Switch", "IN2R Mux" }, - - { "AIF1TX0", NULL, "DSP1TXL" }, - { "AIF1TX1", NULL, "DSP1TXR" }, - { "AIF1TX2", NULL, "DSP2TXL" }, - { "AIF1TX3", NULL, "DSP2TXR" }, - { "AIF1TX4", NULL, "AIF2RX0" }, - { "AIF1TX5", NULL, "AIF2RX1" }, - - { "AIF1RX0", NULL, "AIFCLK" }, - { "AIF1RX1", NULL, "AIFCLK" }, - { "AIF1RX2", NULL, "AIFCLK" }, - { "AIF1RX3", NULL, "AIFCLK" }, - { "AIF1RX4", NULL, "AIFCLK" }, - { "AIF1RX5", NULL, "AIFCLK" }, - - { "AIF2RX0", NULL, "AIFCLK" }, - { "AIF2RX1", NULL, "AIFCLK" }, - - { "AIF1TX0", NULL, "AIFCLK" }, - { "AIF1TX1", NULL, "AIFCLK" }, - { "AIF1TX2", NULL, "AIFCLK" }, - { "AIF1TX3", NULL, "AIFCLK" }, - { "AIF1TX4", NULL, "AIFCLK" }, - { "AIF1TX5", NULL, "AIFCLK" }, - - { "AIF2TX0", NULL, "AIFCLK" }, - { "AIF2TX1", NULL, "AIFCLK" }, - - { "DSP1RXL", NULL, "SYSDSPCLK" }, - { "DSP1RXR", NULL, "SYSDSPCLK" }, - { "DSP2RXL", NULL, "SYSDSPCLK" }, - { "DSP2RXR", NULL, "SYSDSPCLK" }, - { "DSP1TXL", NULL, "SYSDSPCLK" }, - { "DSP1TXR", NULL, "SYSDSPCLK" }, - { "DSP2TXL", NULL, "SYSDSPCLK" }, - { "DSP2TXR", NULL, "SYSDSPCLK" }, - - { "AIF1RXA", NULL, "AIF1RX0" }, - { "AIF1RXA", NULL, "AIF1RX1" }, - { "AIF1RXB", NULL, "AIF1RX2" }, - { "AIF1RXB", NULL, "AIF1RX3" }, - { "AIF1RXC", NULL, "AIF1RX4" }, - { "AIF1RXC", NULL, "AIF1RX5" }, - - { "AIF2RX", NULL, "AIF2RX0" }, - { "AIF2RX", NULL, "AIF2RX1" }, - - { "AIF2TX", "DSP2", "DSP2TX" }, - { "AIF2TX", "DSP1", "DSP1RX" }, - { "AIF2TX", "AIF1", "AIF1RXC" }, - - { "DSP1RXL", NULL, "DSP1RX" }, - { "DSP1RXR", NULL, "DSP1RX" }, - { "DSP2RXL", NULL, "DSP2RX" }, - { "DSP2RXR", NULL, "DSP2RX" }, - - { "DSP2TX", NULL, "DSP2TXL" }, - { "DSP2TX", NULL, "DSP2TXR" }, - - { "DSP1RX", "AIF1", "AIF1RXA" }, - { "DSP1RX", "AIF2", "AIF2RX" }, - - { "DSP2RX", "AIF1", "AIF1RXB" }, - { "DSP2RX", "AIF2", "AIF2RX" }, - - { "DAC2L Mixer", "DSP2 Switch", "DSP2RXL" }, - { "DAC2L Mixer", "DSP1 Switch", "DSP1RXL" }, - { "DAC2L Mixer", "Right Sidetone Switch", "Right Sidetone" }, - { "DAC2L Mixer", "Left Sidetone Switch", "Left Sidetone" }, - - { "DAC2R Mixer", "DSP2 Switch", "DSP2RXR" }, - { "DAC2R Mixer", "DSP1 Switch", "DSP1RXR" }, - { "DAC2R Mixer", "Right Sidetone Switch", "Right Sidetone" }, - { "DAC2R Mixer", "Left Sidetone Switch", "Left Sidetone" }, - - { "DAC1L Mixer", "DSP2 Switch", "DSP2RXL" }, - { "DAC1L Mixer", "DSP1 Switch", "DSP1RXL" }, - { "DAC1L Mixer", "Right Sidetone Switch", "Right Sidetone" }, - { "DAC1L Mixer", "Left Sidetone Switch", "Left Sidetone" }, - - { "DAC1R Mixer", "DSP2 Switch", "DSP2RXR" }, - { "DAC1R Mixer", "DSP1 Switch", "DSP1RXR" }, - { "DAC1R Mixer", "Right Sidetone Switch", "Right Sidetone" }, - { "DAC1R Mixer", "Left Sidetone Switch", "Left Sidetone" }, - - { "DAC1L", NULL, "DAC1L Mixer" }, - { "DAC1R", NULL, "DAC1R Mixer" }, - { "DAC2L", NULL, "DAC2L Mixer" }, - { "DAC2R", NULL, "DAC2R Mixer" }, - - { "HPOUT2L PGA", NULL, "Charge Pump" }, - { "HPOUT2L PGA", NULL, "Bandgap" }, - { "HPOUT2L PGA", NULL, "DAC2L" }, - { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, - { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, - { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_DCS" }, - - { "HPOUT2R PGA", NULL, "Charge Pump" }, - { "HPOUT2R PGA", NULL, "Bandgap" }, - { "HPOUT2R PGA", NULL, "DAC2R" }, - { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, - { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, - { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_DCS" }, - - { "HPOUT1L PGA", NULL, "Charge Pump" }, - { "HPOUT1L PGA", NULL, "Bandgap" }, - { "HPOUT1L PGA", NULL, "DAC1L" }, - { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, - { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, - { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_DCS" }, - - { "HPOUT1R PGA", NULL, "Charge Pump" }, - { "HPOUT1R PGA", NULL, "Bandgap" }, - { "HPOUT1R PGA", NULL, "DAC1R" }, - { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, - { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, - { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_DCS" }, - - { "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" }, - { "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" }, - { "HPOUT1L", NULL, "HPOUT1L_RMV_SHORT" }, - { "HPOUT1R", NULL, "HPOUT1R_RMV_SHORT" }, - - { "SPKL", "DAC1L", "DAC1L" }, - { "SPKL", "DAC1R", "DAC1R" }, - { "SPKL", "DAC2L", "DAC2L" }, - { "SPKL", "DAC2R", "DAC2R" }, - - { "SPKR", "DAC1L", "DAC1L" }, - { "SPKR", "DAC1R", "DAC1R" }, - { "SPKR", "DAC2L", "DAC2L" }, - { "SPKR", "DAC2R", "DAC2R" }, - - { "SPKL PGA", NULL, "SPKL" }, - { "SPKR PGA", NULL, "SPKR" }, - - { "SPKDAT", NULL, "SPKL PGA" }, - { "SPKDAT", NULL, "SPKR PGA" }, -}; - -static bool wm8996_readable_register(struct device *dev, unsigned int reg) -{ - /* Due to the sparseness of the register map the compiler - * output from an explicit switch statement ends up being much - * more efficient than a table. - */ - switch (reg) { - case WM8996_SOFTWARE_RESET: - case WM8996_POWER_MANAGEMENT_1: - case WM8996_POWER_MANAGEMENT_2: - case WM8996_POWER_MANAGEMENT_3: - case WM8996_POWER_MANAGEMENT_4: - case WM8996_POWER_MANAGEMENT_5: - case WM8996_POWER_MANAGEMENT_6: - case WM8996_POWER_MANAGEMENT_7: - case WM8996_POWER_MANAGEMENT_8: - case WM8996_LEFT_LINE_INPUT_VOLUME: - case WM8996_RIGHT_LINE_INPUT_VOLUME: - case WM8996_LINE_INPUT_CONTROL: - case WM8996_DAC1_HPOUT1_VOLUME: - case WM8996_DAC2_HPOUT2_VOLUME: - case WM8996_DAC1_LEFT_VOLUME: - case WM8996_DAC1_RIGHT_VOLUME: - case WM8996_DAC2_LEFT_VOLUME: - case WM8996_DAC2_RIGHT_VOLUME: - case WM8996_OUTPUT1_LEFT_VOLUME: - case WM8996_OUTPUT1_RIGHT_VOLUME: - case WM8996_OUTPUT2_LEFT_VOLUME: - case WM8996_OUTPUT2_RIGHT_VOLUME: - case WM8996_MICBIAS_1: - case WM8996_MICBIAS_2: - case WM8996_LDO_1: - case WM8996_LDO_2: - case WM8996_ACCESSORY_DETECT_MODE_1: - case WM8996_ACCESSORY_DETECT_MODE_2: - case WM8996_HEADPHONE_DETECT_1: - case WM8996_HEADPHONE_DETECT_2: - case WM8996_MIC_DETECT_1: - case WM8996_MIC_DETECT_2: - case WM8996_MIC_DETECT_3: - case WM8996_CHARGE_PUMP_1: - case WM8996_CHARGE_PUMP_2: - case WM8996_DC_SERVO_1: - case WM8996_DC_SERVO_2: - case WM8996_DC_SERVO_3: - case WM8996_DC_SERVO_5: - case WM8996_DC_SERVO_6: - case WM8996_DC_SERVO_7: - case WM8996_DC_SERVO_READBACK_0: - case WM8996_ANALOGUE_HP_1: - case WM8996_ANALOGUE_HP_2: - case WM8996_CHIP_REVISION: - case WM8996_CONTROL_INTERFACE_1: - case WM8996_WRITE_SEQUENCER_CTRL_1: - case WM8996_WRITE_SEQUENCER_CTRL_2: - case WM8996_AIF_CLOCKING_1: - case WM8996_AIF_CLOCKING_2: - case WM8996_CLOCKING_1: - case WM8996_CLOCKING_2: - case WM8996_AIF_RATE: - case WM8996_FLL_CONTROL_1: - case WM8996_FLL_CONTROL_2: - case WM8996_FLL_CONTROL_3: - case WM8996_FLL_CONTROL_4: - case WM8996_FLL_CONTROL_5: - case WM8996_FLL_CONTROL_6: - case WM8996_FLL_EFS_1: - case WM8996_FLL_EFS_2: - case WM8996_AIF1_CONTROL: - case WM8996_AIF1_BCLK: - case WM8996_AIF1_TX_LRCLK_1: - case WM8996_AIF1_TX_LRCLK_2: - case WM8996_AIF1_RX_LRCLK_1: - case WM8996_AIF1_RX_LRCLK_2: - case WM8996_AIF1TX_DATA_CONFIGURATION_1: - case WM8996_AIF1TX_DATA_CONFIGURATION_2: - case WM8996_AIF1RX_DATA_CONFIGURATION: - case WM8996_AIF1TX_CHANNEL_0_CONFIGURATION: - case WM8996_AIF1TX_CHANNEL_1_CONFIGURATION: - case WM8996_AIF1TX_CHANNEL_2_CONFIGURATION: - case WM8996_AIF1TX_CHANNEL_3_CONFIGURATION: - case WM8996_AIF1TX_CHANNEL_4_CONFIGURATION: - case WM8996_AIF1TX_CHANNEL_5_CONFIGURATION: - case WM8996_AIF1RX_CHANNEL_0_CONFIGURATION: - case WM8996_AIF1RX_CHANNEL_1_CONFIGURATION: - case WM8996_AIF1RX_CHANNEL_2_CONFIGURATION: - case WM8996_AIF1RX_CHANNEL_3_CONFIGURATION: - case WM8996_AIF1RX_CHANNEL_4_CONFIGURATION: - case WM8996_AIF1RX_CHANNEL_5_CONFIGURATION: - case WM8996_AIF1RX_MONO_CONFIGURATION: - case WM8996_AIF1TX_TEST: - case WM8996_AIF2_CONTROL: - case WM8996_AIF2_BCLK: - case WM8996_AIF2_TX_LRCLK_1: - case WM8996_AIF2_TX_LRCLK_2: - case WM8996_AIF2_RX_LRCLK_1: - case WM8996_AIF2_RX_LRCLK_2: - case WM8996_AIF2TX_DATA_CONFIGURATION_1: - case WM8996_AIF2TX_DATA_CONFIGURATION_2: - case WM8996_AIF2RX_DATA_CONFIGURATION: - case WM8996_AIF2TX_CHANNEL_0_CONFIGURATION: - case WM8996_AIF2TX_CHANNEL_1_CONFIGURATION: - case WM8996_AIF2RX_CHANNEL_0_CONFIGURATION: - case WM8996_AIF2RX_CHANNEL_1_CONFIGURATION: - case WM8996_AIF2RX_MONO_CONFIGURATION: - case WM8996_AIF2TX_TEST: - case WM8996_DSP1_TX_LEFT_VOLUME: - case WM8996_DSP1_TX_RIGHT_VOLUME: - case WM8996_DSP1_RX_LEFT_VOLUME: - case WM8996_DSP1_RX_RIGHT_VOLUME: - case WM8996_DSP1_TX_FILTERS: - case WM8996_DSP1_RX_FILTERS_1: - case WM8996_DSP1_RX_FILTERS_2: - case WM8996_DSP1_DRC_1: - case WM8996_DSP1_DRC_2: - case WM8996_DSP1_DRC_3: - case WM8996_DSP1_DRC_4: - case WM8996_DSP1_DRC_5: - case WM8996_DSP1_RX_EQ_GAINS_1: - case WM8996_DSP1_RX_EQ_GAINS_2: - case WM8996_DSP1_RX_EQ_BAND_1_A: - case WM8996_DSP1_RX_EQ_BAND_1_B: - case WM8996_DSP1_RX_EQ_BAND_1_PG: - case WM8996_DSP1_RX_EQ_BAND_2_A: - case WM8996_DSP1_RX_EQ_BAND_2_B: - case WM8996_DSP1_RX_EQ_BAND_2_C: - case WM8996_DSP1_RX_EQ_BAND_2_PG: - case WM8996_DSP1_RX_EQ_BAND_3_A: - case WM8996_DSP1_RX_EQ_BAND_3_B: - case WM8996_DSP1_RX_EQ_BAND_3_C: - case WM8996_DSP1_RX_EQ_BAND_3_PG: - case WM8996_DSP1_RX_EQ_BAND_4_A: - case WM8996_DSP1_RX_EQ_BAND_4_B: - case WM8996_DSP1_RX_EQ_BAND_4_C: - case WM8996_DSP1_RX_EQ_BAND_4_PG: - case WM8996_DSP1_RX_EQ_BAND_5_A: - case WM8996_DSP1_RX_EQ_BAND_5_B: - case WM8996_DSP1_RX_EQ_BAND_5_PG: - case WM8996_DSP2_TX_LEFT_VOLUME: - case WM8996_DSP2_TX_RIGHT_VOLUME: - case WM8996_DSP2_RX_LEFT_VOLUME: - case WM8996_DSP2_RX_RIGHT_VOLUME: - case WM8996_DSP2_TX_FILTERS: - case WM8996_DSP2_RX_FILTERS_1: - case WM8996_DSP2_RX_FILTERS_2: - case WM8996_DSP2_DRC_1: - case WM8996_DSP2_DRC_2: - case WM8996_DSP2_DRC_3: - case WM8996_DSP2_DRC_4: - case WM8996_DSP2_DRC_5: - case WM8996_DSP2_RX_EQ_GAINS_1: - case WM8996_DSP2_RX_EQ_GAINS_2: - case WM8996_DSP2_RX_EQ_BAND_1_A: - case WM8996_DSP2_RX_EQ_BAND_1_B: - case WM8996_DSP2_RX_EQ_BAND_1_PG: - case WM8996_DSP2_RX_EQ_BAND_2_A: - case WM8996_DSP2_RX_EQ_BAND_2_B: - case WM8996_DSP2_RX_EQ_BAND_2_C: - case WM8996_DSP2_RX_EQ_BAND_2_PG: - case WM8996_DSP2_RX_EQ_BAND_3_A: - case WM8996_DSP2_RX_EQ_BAND_3_B: - case WM8996_DSP2_RX_EQ_BAND_3_C: - case WM8996_DSP2_RX_EQ_BAND_3_PG: - case WM8996_DSP2_RX_EQ_BAND_4_A: - case WM8996_DSP2_RX_EQ_BAND_4_B: - case WM8996_DSP2_RX_EQ_BAND_4_C: - case WM8996_DSP2_RX_EQ_BAND_4_PG: - case WM8996_DSP2_RX_EQ_BAND_5_A: - case WM8996_DSP2_RX_EQ_BAND_5_B: - case WM8996_DSP2_RX_EQ_BAND_5_PG: - case WM8996_DAC1_MIXER_VOLUMES: - case WM8996_DAC1_LEFT_MIXER_ROUTING: - case WM8996_DAC1_RIGHT_MIXER_ROUTING: - case WM8996_DAC2_MIXER_VOLUMES: - case WM8996_DAC2_LEFT_MIXER_ROUTING: - case WM8996_DAC2_RIGHT_MIXER_ROUTING: - case WM8996_DSP1_TX_LEFT_MIXER_ROUTING: - case WM8996_DSP1_TX_RIGHT_MIXER_ROUTING: - case WM8996_DSP2_TX_LEFT_MIXER_ROUTING: - case WM8996_DSP2_TX_RIGHT_MIXER_ROUTING: - case WM8996_DSP_TX_MIXER_SELECT: - case WM8996_DAC_SOFTMUTE: - case WM8996_OVERSAMPLING: - case WM8996_SIDETONE: - case WM8996_GPIO_1: - case WM8996_GPIO_2: - case WM8996_GPIO_3: - case WM8996_GPIO_4: - case WM8996_GPIO_5: - case WM8996_PULL_CONTROL_1: - case WM8996_PULL_CONTROL_2: - case WM8996_INTERRUPT_STATUS_1: - case WM8996_INTERRUPT_STATUS_2: - case WM8996_INTERRUPT_RAW_STATUS_2: - case WM8996_INTERRUPT_STATUS_1_MASK: - case WM8996_INTERRUPT_STATUS_2_MASK: - case WM8996_INTERRUPT_CONTROL: - case WM8996_LEFT_PDM_SPEAKER: - case WM8996_RIGHT_PDM_SPEAKER: - case WM8996_PDM_SPEAKER_MUTE_SEQUENCE: - case WM8996_PDM_SPEAKER_VOLUME: - return 1; - default: - return 0; - } -} - -static bool wm8996_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM8996_SOFTWARE_RESET: - case WM8996_CHIP_REVISION: - case WM8996_LDO_1: - case WM8996_LDO_2: - case WM8996_INTERRUPT_STATUS_1: - case WM8996_INTERRUPT_STATUS_2: - case WM8996_INTERRUPT_RAW_STATUS_2: - case WM8996_DC_SERVO_READBACK_0: - case WM8996_DC_SERVO_2: - case WM8996_DC_SERVO_6: - case WM8996_DC_SERVO_7: - case WM8996_FLL_CONTROL_6: - case WM8996_MIC_DETECT_3: - case WM8996_HEADPHONE_DETECT_1: - case WM8996_HEADPHONE_DETECT_2: - return 1; - default: - return 0; - } -} - -static int wm8996_reset(struct wm8996_priv *wm8996) -{ - if (wm8996->pdata.ldo_ena > 0) { - gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); - gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1); - return 0; - } else { - return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, - 0x8915); - } -} - -static const int bclk_divs[] = { - 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96 -}; - -static void wm8996_update_bclk(struct snd_soc_codec *codec) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int aif, best, cur_val, bclk_rate, bclk_reg, i; - - /* Don't bother if we're in a low frequency idle mode that - * can't support audio. - */ - if (wm8996->sysclk < 64000) - return; - - for (aif = 0; aif < WM8996_AIFS; aif++) { - switch (aif) { - case 0: - bclk_reg = WM8996_AIF1_BCLK; - break; - case 1: - bclk_reg = WM8996_AIF2_BCLK; - break; - } - - bclk_rate = wm8996->bclk_rate[aif]; - - /* Pick a divisor for BCLK as close as we can get to ideal */ - best = 0; - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - cur_val = (wm8996->sysclk / bclk_divs[i]) - bclk_rate; - if (cur_val < 0) /* BCLK table is sorted */ - break; - best = i; - } - bclk_rate = wm8996->sysclk / bclk_divs[best]; - dev_dbg(codec->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n", - bclk_divs[best], bclk_rate); - - snd_soc_update_bits(codec, bclk_reg, - WM8996_AIF1_BCLK_DIV_MASK, best); - } -} - -static int wm8996_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), - wm8996->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - - if (wm8996->pdata.ldo_ena >= 0) { - gpio_set_value_cansleep(wm8996->pdata.ldo_ena, - 1); - msleep(5); - } - - regcache_cache_only(codec->control_data, false); - regcache_sync(codec->control_data); - } - break; - - case SND_SOC_BIAS_OFF: - regcache_cache_only(codec->control_data, true); - if (wm8996->pdata.ldo_ena >= 0) - gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); - regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), - wm8996->supplies); - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static int wm8996_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - int aifctrl = 0; - int bclk = 0; - int lrclk_tx = 0; - int lrclk_rx = 0; - int aifctrl_reg, bclk_reg, lrclk_tx_reg, lrclk_rx_reg; - - switch (dai->id) { - case 0: - aifctrl_reg = WM8996_AIF1_CONTROL; - bclk_reg = WM8996_AIF1_BCLK; - lrclk_tx_reg = WM8996_AIF1_TX_LRCLK_2; - lrclk_rx_reg = WM8996_AIF1_RX_LRCLK_2; - break; - case 1: - aifctrl_reg = WM8996_AIF2_CONTROL; - bclk_reg = WM8996_AIF2_BCLK; - lrclk_tx_reg = WM8996_AIF2_TX_LRCLK_2; - lrclk_rx_reg = WM8996_AIF2_RX_LRCLK_2; - break; - default: - BUG(); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - bclk |= WM8996_AIF1_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - lrclk_tx |= WM8996_AIF1TX_LRCLK_INV; - lrclk_rx |= WM8996_AIF1RX_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_IF: - bclk |= WM8996_AIF1_BCLK_INV; - lrclk_tx |= WM8996_AIF1TX_LRCLK_INV; - lrclk_rx |= WM8996_AIF1RX_LRCLK_INV; - break; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBS_CFM: - lrclk_tx |= WM8996_AIF1TX_LRCLK_MSTR; - lrclk_rx |= WM8996_AIF1RX_LRCLK_MSTR; - break; - case SND_SOC_DAIFMT_CBM_CFS: - bclk |= WM8996_AIF1_BCLK_MSTR; - break; - case SND_SOC_DAIFMT_CBM_CFM: - bclk |= WM8996_AIF1_BCLK_MSTR; - lrclk_tx |= WM8996_AIF1TX_LRCLK_MSTR; - lrclk_rx |= WM8996_AIF1RX_LRCLK_MSTR; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - break; - case SND_SOC_DAIFMT_DSP_B: - aifctrl |= 1; - break; - case SND_SOC_DAIFMT_I2S: - aifctrl |= 2; - break; - case SND_SOC_DAIFMT_LEFT_J: - aifctrl |= 3; - break; - default: - return -EINVAL; - } - - snd_soc_update_bits(codec, aifctrl_reg, WM8996_AIF1_FMT_MASK, aifctrl); - snd_soc_update_bits(codec, bclk_reg, - WM8996_AIF1_BCLK_INV | WM8996_AIF1_BCLK_MSTR, - bclk); - snd_soc_update_bits(codec, lrclk_tx_reg, - WM8996_AIF1TX_LRCLK_INV | - WM8996_AIF1TX_LRCLK_MSTR, - lrclk_tx); - snd_soc_update_bits(codec, lrclk_rx_reg, - WM8996_AIF1RX_LRCLK_INV | - WM8996_AIF1RX_LRCLK_MSTR, - lrclk_rx); - - return 0; -} - -static const int dsp_divs[] = { - 48000, 32000, 16000, 8000 -}; - -static int wm8996_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int bits, i, bclk_rate, best; - int aifdata = 0; - int lrclk = 0; - int dsp = 0; - int aifdata_reg, lrclk_reg, dsp_shift; - - switch (dai->id) { - case 0: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - (snd_soc_read(codec, WM8996_GPIO_1)) & WM8996_GP1_FN_MASK) { - aifdata_reg = WM8996_AIF1RX_DATA_CONFIGURATION; - lrclk_reg = WM8996_AIF1_RX_LRCLK_1; - } else { - aifdata_reg = WM8996_AIF1TX_DATA_CONFIGURATION_1; - lrclk_reg = WM8996_AIF1_TX_LRCLK_1; - } - dsp_shift = 0; - break; - case 1: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || - (snd_soc_read(codec, WM8996_GPIO_2)) & WM8996_GP2_FN_MASK) { - aifdata_reg = WM8996_AIF2RX_DATA_CONFIGURATION; - lrclk_reg = WM8996_AIF2_RX_LRCLK_1; - } else { - aifdata_reg = WM8996_AIF2TX_DATA_CONFIGURATION_1; - lrclk_reg = WM8996_AIF2_TX_LRCLK_1; - } - dsp_shift = WM8996_DSP2_DIV_SHIFT; - break; - default: - BUG(); - return -EINVAL; - } - - bclk_rate = snd_soc_params_to_bclk(params); - if (bclk_rate < 0) { - dev_err(codec->dev, "Unsupported BCLK rate: %d\n", bclk_rate); - return bclk_rate; - } - - wm8996->bclk_rate[dai->id] = bclk_rate; - wm8996->rx_rate[dai->id] = params_rate(params); - - /* Needs looking at for TDM */ - bits = snd_pcm_format_width(params_format(params)); - if (bits < 0) - return bits; - aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits; - - best = 0; - for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) { - if (abs(dsp_divs[i] - params_rate(params)) < - abs(dsp_divs[best] - params_rate(params))) - best = i; - } - dsp |= i << dsp_shift; - - wm8996_update_bclk(codec); - - lrclk = bclk_rate / params_rate(params); - dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", - lrclk, bclk_rate / lrclk); - - snd_soc_update_bits(codec, aifdata_reg, - WM8996_AIF1TX_WL_MASK | - WM8996_AIF1TX_SLOT_LEN_MASK, - aifdata); - snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK, - lrclk); - snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2, - WM8996_DSP1_DIV_MASK << dsp_shift, dsp); - - return 0; -} - -static int wm8996_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int lfclk = 0; - int ratediv = 0; - int sync = WM8996_REG_SYNC; - int src; - int old; - - if (freq == wm8996->sysclk && clk_id == wm8996->sysclk_src) - return 0; - - /* Disable SYSCLK while we reconfigure */ - old = snd_soc_read(codec, WM8996_AIF_CLOCKING_1) & WM8996_SYSCLK_ENA; - snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1, - WM8996_SYSCLK_ENA, 0); - - switch (clk_id) { - case WM8996_SYSCLK_MCLK1: - wm8996->sysclk = freq; - src = 0; - break; - case WM8996_SYSCLK_MCLK2: - wm8996->sysclk = freq; - src = 1; - break; - case WM8996_SYSCLK_FLL: - wm8996->sysclk = freq; - src = 2; - break; - default: - dev_err(codec->dev, "Unsupported clock source %d\n", clk_id); - return -EINVAL; - } - - switch (wm8996->sysclk) { - case 5644800: - case 6144000: - snd_soc_update_bits(codec, WM8996_AIF_RATE, - WM8996_SYSCLK_RATE, 0); - break; - case 22579200: - case 24576000: - ratediv = WM8996_SYSCLK_DIV; - wm8996->sysclk /= 2; - case 11289600: - case 12288000: - snd_soc_update_bits(codec, WM8996_AIF_RATE, - WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE); - break; - case 32000: - case 32768: - lfclk = WM8996_LFCLK_ENA; - sync = 0; - break; - default: - dev_warn(codec->dev, "Unsupported clock rate %dHz\n", - wm8996->sysclk); - return -EINVAL; - } - - wm8996_update_bclk(codec); - - snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1, - WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK, - src << WM8996_SYSCLK_SRC_SHIFT | ratediv); - snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk); - snd_soc_update_bits(codec, WM8996_CONTROL_INTERFACE_1, - WM8996_REG_SYNC, sync); - snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1, - WM8996_SYSCLK_ENA, old); - - wm8996->sysclk_src = clk_id; - - return 0; -} - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_refclk_div; - u16 fll_loop_gain; - u16 fll_ref_freq; - u16 n; - u16 theta; - u16 lambda; -}; - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - unsigned int target; - unsigned int div; - unsigned int fratio, gcd_fll; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - fll_div->fll_refclk_div = 0; - while ((Fref / div) > 13500000) { - div *= 2; - fll_div->fll_refclk_div++; - - if (div > 8) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - - pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - if (Fref >= 3000000) - fll_div->fll_loop_gain = 5; - else - fll_div->fll_loop_gain = 0; - - if (Fref >= 48000) - fll_div->fll_ref_freq = 0; - else - fll_div->fll_ref_freq = 1; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 2; - while (Fout * div < 90000000) { - div++; - if (div > 64) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - target = Fout * div; - fll_div->fll_outdiv = div - 1; - - pr_debug("FLL Fvco=%dHz\n", target); - - /* Find an appropraite FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - fratio = fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - fll_div->n = target / (fratio * Fref); - - if (target % Fref == 0) { - fll_div->theta = 0; - fll_div->lambda = 0; - } else { - gcd_fll = gcd(target, fratio * Fref); - - fll_div->theta = (target - (fll_div->n * fratio * Fref)) - / gcd_fll; - fll_div->lambda = (fratio * Fref) / gcd_fll; - } - - pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n", - fll_div->n, fll_div->theta, fll_div->lambda); - pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n", - fll_div->fll_fratio, fll_div->fll_outdiv, - fll_div->fll_refclk_div); - - return 0; -} - -static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, - unsigned int Fref, unsigned int Fout) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c = to_i2c_client(codec->dev); - struct _fll_div fll_div; - unsigned long timeout; - int ret, reg, retry; - - /* Any change? */ - if (source == wm8996->fll_src && Fref == wm8996->fll_fref && - Fout == wm8996->fll_fout) - return 0; - - if (Fout == 0) { - dev_dbg(codec->dev, "FLL disabled\n"); - - wm8996->fll_fref = 0; - wm8996->fll_fout = 0; - - snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, - WM8996_FLL_ENA, 0); - - wm8996_bg_disable(codec); - - return 0; - } - - ret = fll_factors(&fll_div, Fref, Fout); - if (ret != 0) - return ret; - - switch (source) { - case WM8996_FLL_MCLK1: - reg = 0; - break; - case WM8996_FLL_MCLK2: - reg = 1; - break; - case WM8996_FLL_DACLRCLK1: - reg = 2; - break; - case WM8996_FLL_BCLK1: - reg = 3; - break; - default: - dev_err(codec->dev, "Unknown FLL source %d\n", ret); - return -EINVAL; - } - - reg |= fll_div.fll_refclk_div << WM8996_FLL_REFCLK_DIV_SHIFT; - reg |= fll_div.fll_ref_freq << WM8996_FLL_REF_FREQ_SHIFT; - - snd_soc_update_bits(codec, WM8996_FLL_CONTROL_5, - WM8996_FLL_REFCLK_DIV_MASK | WM8996_FLL_REF_FREQ | - WM8996_FLL_REFCLK_SRC_MASK, reg); - - reg = 0; - if (fll_div.theta || fll_div.lambda) - reg |= WM8996_FLL_EFS_ENA | (3 << WM8996_FLL_LFSR_SEL_SHIFT); - else - reg |= 1 << WM8996_FLL_LFSR_SEL_SHIFT; - snd_soc_write(codec, WM8996_FLL_EFS_2, reg); - - snd_soc_update_bits(codec, WM8996_FLL_CONTROL_2, - WM8996_FLL_OUTDIV_MASK | - WM8996_FLL_FRATIO_MASK, - (fll_div.fll_outdiv << WM8996_FLL_OUTDIV_SHIFT) | - (fll_div.fll_fratio)); - - snd_soc_write(codec, WM8996_FLL_CONTROL_3, fll_div.theta); - - snd_soc_update_bits(codec, WM8996_FLL_CONTROL_4, - WM8996_FLL_N_MASK | WM8996_FLL_LOOP_GAIN_MASK, - (fll_div.n << WM8996_FLL_N_SHIFT) | - fll_div.fll_loop_gain); - - snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); - - /* Enable the bandgap if it's not already enabled */ - ret = snd_soc_read(codec, WM8996_FLL_CONTROL_1); - if (!(ret & WM8996_FLL_ENA)) - wm8996_bg_enable(codec); - - /* Clear any pending completions (eg, from failed startups) */ - try_wait_for_completion(&wm8996->fll_lock); - - snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, - WM8996_FLL_ENA, WM8996_FLL_ENA); - - /* The FLL supports live reconfiguration - kick that in case we were - * already enabled. - */ - snd_soc_write(codec, WM8996_FLL_CONTROL_6, WM8996_FLL_SWITCH_CLK); - - /* Wait for the FLL to lock, using the interrupt if possible */ - if (Fref > 1000000) - timeout = usecs_to_jiffies(300); - else - timeout = msecs_to_jiffies(2); - - /* Allow substantially longer if we've actually got the IRQ, poll - * at a slightly higher rate if we don't. - */ - if (i2c->irq) - timeout *= 10; - else - timeout /= 2; - - for (retry = 0; retry < 10; retry++) { - ret = wait_for_completion_timeout(&wm8996->fll_lock, - timeout); - if (ret != 0) { - WARN_ON(!i2c->irq); - break; - } - - ret = snd_soc_read(codec, WM8996_INTERRUPT_RAW_STATUS_2); - if (ret & WM8996_FLL_LOCK_STS) - break; - } - if (retry == 10) { - dev_err(codec->dev, "Timed out waiting for FLL\n"); - ret = -ETIMEDOUT; - } - - dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); - - wm8996->fll_fref = Fref; - wm8996->fll_fout = Fout; - wm8996->fll_src = source; - - return ret; -} - -#ifdef CONFIG_GPIOLIB -static inline struct wm8996_priv *gpio_to_wm8996(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8996_priv, gpio_chip); -} - -static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); - - regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset, - WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT); -} - -static int wm8996_gpio_direction_out(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); - int val; - - val = (1 << WM8996_GP1_FN_SHIFT) | (!!value << WM8996_GP1_LVL_SHIFT); - - return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset, - WM8996_GP1_FN_MASK | WM8996_GP1_DIR | - WM8996_GP1_LVL, val); -} - -static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); - unsigned int reg; - int ret; - - ret = regmap_read(wm8996->regmap, WM8996_GPIO_1 + offset, ®); - if (ret < 0) - return ret; - - return (reg & WM8996_GP1_LVL) != 0; -} - -static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct wm8996_priv *wm8996 = gpio_to_wm8996(chip); - - return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset, - WM8996_GP1_FN_MASK | WM8996_GP1_DIR, - (1 << WM8996_GP1_FN_SHIFT) | - (1 << WM8996_GP1_DIR_SHIFT)); -} - -static struct gpio_chip wm8996_template_chip = { - .label = "wm8996", - .owner = THIS_MODULE, - .direction_output = wm8996_gpio_direction_out, - .set = wm8996_gpio_set, - .direction_input = wm8996_gpio_direction_in, - .get = wm8996_gpio_get, - .can_sleep = 1, -}; - -static void wm8996_init_gpio(struct wm8996_priv *wm8996) -{ - int ret; - - wm8996->gpio_chip = wm8996_template_chip; - wm8996->gpio_chip.ngpio = 5; - wm8996->gpio_chip.dev = wm8996->dev; - - if (wm8996->pdata.gpio_base) - wm8996->gpio_chip.base = wm8996->pdata.gpio_base; - else - wm8996->gpio_chip.base = -1; - - ret = gpiochip_add(&wm8996->gpio_chip); - if (ret != 0) - dev_err(wm8996->dev, "Failed to add GPIOs: %d\n", ret); -} - -static void wm8996_free_gpio(struct wm8996_priv *wm8996) -{ - int ret; - - ret = gpiochip_remove(&wm8996->gpio_chip); - if (ret != 0) - dev_err(wm8996->dev, "Failed to remove GPIOs: %d\n", ret); -} -#else -static void wm8996_init_gpio(struct wm8996_priv *wm8996) -{ -} - -static void wm8996_free_gpio(struct wm8996_priv *wm8996) -{ -} -#endif - -/** - * wm8996_detect - Enable default WM8996 jack detection - * - * The WM8996 has advanced accessory detection support for headsets. - * This function provides a default implementation which integrates - * the majority of this functionality with minimal user configuration. - * - * This will detect headset, headphone and short circuit button and - * will also detect inverted microphone ground connections and update - * the polarity of the connections. - */ -int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - wm8996_polarity_fn polarity_cb) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - - wm8996->jack = jack; - wm8996->detecting = true; - wm8996->polarity_cb = polarity_cb; - wm8996->jack_flips = 0; - - if (wm8996->polarity_cb) - wm8996->polarity_cb(codec, 0); - - /* Clear discarge to avoid noise during detection */ - snd_soc_update_bits(codec, WM8996_MICBIAS_1, - WM8996_MICB1_DISCH, 0); - snd_soc_update_bits(codec, WM8996_MICBIAS_2, - WM8996_MICB2_DISCH, 0); - - /* LDO2 powers the microphones, SYSCLK clocks detection */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK"); - - /* We start off just enabling microphone detection - even a - * plain headphone will trigger detection. - */ - snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, - WM8996_MICD_ENA, WM8996_MICD_ENA); - - /* Slowest detection rate, gives debounce for initial detection */ - snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, - WM8996_MICD_RATE_MASK, - WM8996_MICD_RATE_MASK); - - /* Enable interrupts and we're off */ - snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK, - WM8996_IM_MICD_EINT | WM8996_HP_DONE_EINT, 0); - - return 0; -} -EXPORT_SYMBOL_GPL(wm8996_detect); - -static void wm8996_hpdet_irq(struct snd_soc_codec *codec) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int val, reg, report; - - /* Assume headphone in error conditions; we need to report - * something or we stall our state machine. - */ - report = SND_JACK_HEADPHONE; - - reg = snd_soc_read(codec, WM8996_HEADPHONE_DETECT_2); - if (reg < 0) { - dev_err(codec->dev, "Failed to read HPDET status\n"); - goto out; - } - - if (!(reg & WM8996_HP_DONE)) { - dev_err(codec->dev, "Got HPDET IRQ but HPDET is busy\n"); - goto out; - } - - val = reg & WM8996_HP_LVL_MASK; - - dev_dbg(codec->dev, "HPDET measured %d ohms\n", val); - - /* If we've got high enough impedence then report as line, - * otherwise assume headphone. - */ - if (val >= 126) - report = SND_JACK_LINEOUT; - else - report = SND_JACK_HEADPHONE; - -out: - if (wm8996->jack_mic) - report |= SND_JACK_MICROPHONE; - - snd_soc_jack_report(wm8996->jack, report, - SND_JACK_LINEOUT | SND_JACK_HEADSET); - - wm8996->detecting = false; - - /* If the output isn't running re-clamp it */ - if (!(snd_soc_read(codec, WM8996_POWER_MANAGEMENT_1) & - (WM8996_HPOUT1L_ENA | WM8996_HPOUT1R_RMV_SHORT))) - snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, - WM8996_HPOUT1L_RMV_SHORT | - WM8996_HPOUT1R_RMV_SHORT, 0); - - /* Go back to looking at the microphone */ - snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1, - WM8996_JD_MODE_MASK, 0); - snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, - WM8996_MICD_ENA); - - snd_soc_dapm_disable_pin(&codec->dapm, "Bandgap"); - snd_soc_dapm_sync(&codec->dapm); -} - -static void wm8996_hpdet_start(struct snd_soc_codec *codec) -{ - /* Unclamp the output, we can't measure while we're shorting it */ - snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, - WM8996_HPOUT1L_RMV_SHORT | - WM8996_HPOUT1R_RMV_SHORT, - WM8996_HPOUT1L_RMV_SHORT | - WM8996_HPOUT1R_RMV_SHORT); - - /* We need bandgap for HPDET */ - snd_soc_dapm_force_enable_pin(&codec->dapm, "Bandgap"); - snd_soc_dapm_sync(&codec->dapm); - - /* Go into headphone detect left mode */ - snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, 0); - snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1, - WM8996_JD_MODE_MASK, 1); - - /* Trigger a measurement */ - snd_soc_update_bits(codec, WM8996_HEADPHONE_DETECT_1, - WM8996_HP_POLL, WM8996_HP_POLL); -} - -static void wm8996_report_headphone(struct snd_soc_codec *codec) -{ - dev_dbg(codec->dev, "Headphone detected\n"); - wm8996_hpdet_start(codec); - - /* Increase the detection rate a bit for responsiveness. */ - snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, - WM8996_MICD_RATE_MASK | - WM8996_MICD_BIAS_STARTTIME_MASK, - 7 << WM8996_MICD_RATE_SHIFT | - 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT); -} - -static void wm8996_micd(struct snd_soc_codec *codec) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int val, reg; - - val = snd_soc_read(codec, WM8996_MIC_DETECT_3); - - dev_dbg(codec->dev, "Microphone event: %x\n", val); - - if (!(val & WM8996_MICD_VALID)) { - dev_warn(codec->dev, "Microphone detection state invalid\n"); - return; - } - - /* No accessory, reset everything and report removal */ - if (!(val & WM8996_MICD_STS)) { - dev_dbg(codec->dev, "Jack removal detected\n"); - wm8996->jack_mic = false; - wm8996->detecting = true; - wm8996->jack_flips = 0; - snd_soc_jack_report(wm8996->jack, 0, - SND_JACK_LINEOUT | SND_JACK_HEADSET | - SND_JACK_BTN_0); - - snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, - WM8996_MICD_RATE_MASK | - WM8996_MICD_BIAS_STARTTIME_MASK, - WM8996_MICD_RATE_MASK | - 9 << WM8996_MICD_BIAS_STARTTIME_SHIFT); - return; - } - - /* If the measurement is very high we've got a microphone, - * either we just detected one or if we already reported then - * we've got a button release event. - */ - if (val & 0x400) { - if (wm8996->detecting) { - dev_dbg(codec->dev, "Microphone detected\n"); - wm8996->jack_mic = true; - wm8996_hpdet_start(codec); - - /* Increase poll rate to give better responsiveness - * for buttons */ - snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, - WM8996_MICD_RATE_MASK | - WM8996_MICD_BIAS_STARTTIME_MASK, - 5 << WM8996_MICD_RATE_SHIFT | - 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT); - } else { - dev_dbg(codec->dev, "Mic button up\n"); - snd_soc_jack_report(wm8996->jack, 0, SND_JACK_BTN_0); - } - - return; - } - - /* If we detected a lower impedence during initial startup - * then we probably have the wrong polarity, flip it. Don't - * do this for the lowest impedences to speed up detection of - * plain headphones. If both polarities report a low - * impedence then give up and report headphones. - */ - if (wm8996->detecting && (val & 0x3f0)) { - wm8996->jack_flips++; - - if (wm8996->jack_flips > 1) { - wm8996_report_headphone(codec); - return; - } - - reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2); - reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC | - WM8996_MICD_BIAS_SRC; - snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2, - WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC | - WM8996_MICD_BIAS_SRC, reg); - - if (wm8996->polarity_cb) - wm8996->polarity_cb(codec, - (reg & WM8996_MICD_SRC) != 0); - - dev_dbg(codec->dev, "Set microphone polarity to %d\n", - (reg & WM8996_MICD_SRC) != 0); - - return; - } - - /* Don't distinguish between buttons, just report any low - * impedence as BTN_0. - */ - if (val & 0x3fc) { - if (wm8996->jack_mic) { - dev_dbg(codec->dev, "Mic button detected\n"); - snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0, - SND_JACK_BTN_0); - } else if (wm8996->detecting) { - wm8996_report_headphone(codec); - } - } -} - -static irqreturn_t wm8996_irq(int irq, void *data) -{ - struct snd_soc_codec *codec = data; - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - int irq_val; - - irq_val = snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2); - if (irq_val < 0) { - dev_err(codec->dev, "Failed to read IRQ status: %d\n", - irq_val); - return IRQ_NONE; - } - irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK); - - if (!irq_val) - return IRQ_NONE; - - snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val); - - if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) { - dev_dbg(codec->dev, "DC servo IRQ\n"); - complete(&wm8996->dcs_done); - } - - if (irq_val & WM8996_FIFOS_ERR_EINT) - dev_err(codec->dev, "Digital core FIFO error\n"); - - if (irq_val & WM8996_FLL_LOCK_EINT) { - dev_dbg(codec->dev, "FLL locked\n"); - complete(&wm8996->fll_lock); - } - - if (irq_val & WM8996_MICD_EINT) - wm8996_micd(codec); - - if (irq_val & WM8996_HP_DONE_EINT) - wm8996_hpdet_irq(codec); - - return IRQ_HANDLED; -} - -static irqreturn_t wm8996_edge_irq(int irq, void *data) -{ - irqreturn_t ret = IRQ_NONE; - irqreturn_t val; - - do { - val = wm8996_irq(irq, data); - if (val != IRQ_NONE) - ret = val; - } while (val != IRQ_NONE); - - return ret; -} - -static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - struct wm8996_pdata *pdata = &wm8996->pdata; - - struct snd_kcontrol_new controls[] = { - SOC_ENUM_EXT("DSP1 EQ Mode", - wm8996->retune_mobile_enum, - wm8996_get_retune_mobile_enum, - wm8996_put_retune_mobile_enum), - SOC_ENUM_EXT("DSP2 EQ Mode", - wm8996->retune_mobile_enum, - wm8996_get_retune_mobile_enum, - wm8996_put_retune_mobile_enum), - }; - int ret, i, j; - const char **t; - - /* We need an array of texts for the enum API but the number - * of texts is likely to be less than the number of - * configurations due to the sample rate dependency of the - * configurations. */ - wm8996->num_retune_mobile_texts = 0; - wm8996->retune_mobile_texts = NULL; - for (i = 0; i < pdata->num_retune_mobile_cfgs; i++) { - for (j = 0; j < wm8996->num_retune_mobile_texts; j++) { - if (strcmp(pdata->retune_mobile_cfgs[i].name, - wm8996->retune_mobile_texts[j]) == 0) - break; - } - - if (j != wm8996->num_retune_mobile_texts) - continue; - - /* Expand the array... */ - t = krealloc(wm8996->retune_mobile_texts, - sizeof(char *) * - (wm8996->num_retune_mobile_texts + 1), - GFP_KERNEL); - if (t == NULL) - continue; - - /* ...store the new entry... */ - t[wm8996->num_retune_mobile_texts] = - pdata->retune_mobile_cfgs[i].name; - - /* ...and remember the new version. */ - wm8996->num_retune_mobile_texts++; - wm8996->retune_mobile_texts = t; - } - - dev_dbg(codec->dev, "Allocated %d unique ReTune Mobile names\n", - wm8996->num_retune_mobile_texts); - - wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts; - wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts; - - ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); - if (ret != 0) - dev_err(codec->dev, - "Failed to add ReTune Mobile controls: %d\n", ret); -} - -static const struct regmap_config wm8996_regmap = { - .reg_bits = 16, - .val_bits = 16, - - .max_register = WM8996_MAX_REGISTER, - .reg_defaults = wm8996_reg, - .num_reg_defaults = ARRAY_SIZE(wm8996_reg), - .volatile_reg = wm8996_volatile_register, - .readable_reg = wm8996_readable_register, - .cache_type = REGCACHE_RBTREE, -}; - -static int wm8996_probe(struct snd_soc_codec *codec) -{ - int ret; - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c = to_i2c_client(codec->dev); - int i, irq_flags; - - wm8996->codec = codec; - - init_completion(&wm8996->dcs_done); - init_completion(&wm8996->fll_lock); - - codec->control_data = wm8996->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; - wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; - wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; - - /* This should really be moved into the regulator core */ - for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { - ret = regulator_register_notifier(wm8996->supplies[i].consumer, - &wm8996->disable_nb[i]); - if (ret != 0) { - dev_err(codec->dev, - "Failed to register regulator notifier: %d\n", - ret); - } - } - - regcache_cache_only(codec->control_data, true); - - /* Apply platform data settings */ - snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL, - WM8996_INL_MODE_MASK | WM8996_INR_MODE_MASK, - wm8996->pdata.inl_mode << WM8996_INL_MODE_SHIFT | - wm8996->pdata.inr_mode); - - for (i = 0; i < ARRAY_SIZE(wm8996->pdata.gpio_default); i++) { - if (!wm8996->pdata.gpio_default[i]) - continue; - - snd_soc_write(codec, WM8996_GPIO_1 + i, - wm8996->pdata.gpio_default[i] & 0xffff); - } - - if (wm8996->pdata.spkmute_seq) - snd_soc_update_bits(codec, WM8996_PDM_SPEAKER_MUTE_SEQUENCE, - WM8996_SPK_MUTE_ENDIAN | - WM8996_SPK_MUTE_SEQ1_MASK, - wm8996->pdata.spkmute_seq); - - snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_2, - WM8996_MICD_BIAS_SRC | WM8996_HPOUT1FB_SRC | - WM8996_MICD_SRC, wm8996->pdata.micdet_def); - - /* Latch volume update bits */ - snd_soc_update_bits(codec, WM8996_LEFT_LINE_INPUT_VOLUME, - WM8996_IN1_VU, WM8996_IN1_VU); - snd_soc_update_bits(codec, WM8996_RIGHT_LINE_INPUT_VOLUME, - WM8996_IN1_VU, WM8996_IN1_VU); - - snd_soc_update_bits(codec, WM8996_DAC1_LEFT_VOLUME, - WM8996_DAC1_VU, WM8996_DAC1_VU); - snd_soc_update_bits(codec, WM8996_DAC1_RIGHT_VOLUME, - WM8996_DAC1_VU, WM8996_DAC1_VU); - snd_soc_update_bits(codec, WM8996_DAC2_LEFT_VOLUME, - WM8996_DAC2_VU, WM8996_DAC2_VU); - snd_soc_update_bits(codec, WM8996_DAC2_RIGHT_VOLUME, - WM8996_DAC2_VU, WM8996_DAC2_VU); - - snd_soc_update_bits(codec, WM8996_OUTPUT1_LEFT_VOLUME, - WM8996_DAC1_VU, WM8996_DAC1_VU); - snd_soc_update_bits(codec, WM8996_OUTPUT1_RIGHT_VOLUME, - WM8996_DAC1_VU, WM8996_DAC1_VU); - snd_soc_update_bits(codec, WM8996_OUTPUT2_LEFT_VOLUME, - WM8996_DAC2_VU, WM8996_DAC2_VU); - snd_soc_update_bits(codec, WM8996_OUTPUT2_RIGHT_VOLUME, - WM8996_DAC2_VU, WM8996_DAC2_VU); - - snd_soc_update_bits(codec, WM8996_DSP1_TX_LEFT_VOLUME, - WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); - snd_soc_update_bits(codec, WM8996_DSP1_TX_RIGHT_VOLUME, - WM8996_DSP1TX_VU, WM8996_DSP1TX_VU); - snd_soc_update_bits(codec, WM8996_DSP2_TX_LEFT_VOLUME, - WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); - snd_soc_update_bits(codec, WM8996_DSP2_TX_RIGHT_VOLUME, - WM8996_DSP2TX_VU, WM8996_DSP2TX_VU); - - snd_soc_update_bits(codec, WM8996_DSP1_RX_LEFT_VOLUME, - WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); - snd_soc_update_bits(codec, WM8996_DSP1_RX_RIGHT_VOLUME, - WM8996_DSP1RX_VU, WM8996_DSP1RX_VU); - snd_soc_update_bits(codec, WM8996_DSP2_RX_LEFT_VOLUME, - WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); - snd_soc_update_bits(codec, WM8996_DSP2_RX_RIGHT_VOLUME, - WM8996_DSP2RX_VU, WM8996_DSP2RX_VU); - - /* No support currently for the underclocked TDM modes and - * pick a default TDM layout with each channel pair working with - * slots 0 and 1. */ - snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, - WM8996_AIF1RX_CHAN0_SLOTS_MASK | - WM8996_AIF1RX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1RX_CHAN0_SLOTS_SHIFT | 0); - snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, - WM8996_AIF1RX_CHAN1_SLOTS_MASK | - WM8996_AIF1RX_CHAN1_START_SLOT_MASK, - 1 << WM8996_AIF1RX_CHAN1_SLOTS_SHIFT | 1); - snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, - WM8996_AIF1RX_CHAN2_SLOTS_MASK | - WM8996_AIF1RX_CHAN2_START_SLOT_MASK, - 1 << WM8996_AIF1RX_CHAN2_SLOTS_SHIFT | 0); - snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, - WM8996_AIF1RX_CHAN3_SLOTS_MASK | - WM8996_AIF1RX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1RX_CHAN3_SLOTS_SHIFT | 1); - snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, - WM8996_AIF1RX_CHAN4_SLOTS_MASK | - WM8996_AIF1RX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1RX_CHAN4_SLOTS_SHIFT | 0); - snd_soc_update_bits(codec, WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, - WM8996_AIF1RX_CHAN5_SLOTS_MASK | - WM8996_AIF1RX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1RX_CHAN5_SLOTS_SHIFT | 1); - - snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, - WM8996_AIF2RX_CHAN0_SLOTS_MASK | - WM8996_AIF2RX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF2RX_CHAN0_SLOTS_SHIFT | 0); - snd_soc_update_bits(codec, WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, - WM8996_AIF2RX_CHAN1_SLOTS_MASK | - WM8996_AIF2RX_CHAN1_START_SLOT_MASK, - 1 << WM8996_AIF2RX_CHAN1_SLOTS_SHIFT | 1); - - snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, - WM8996_AIF1TX_CHAN0_SLOTS_MASK | - WM8996_AIF1TX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1TX_CHAN0_SLOTS_SHIFT | 0); - snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, - WM8996_AIF1TX_CHAN1_SLOTS_MASK | - WM8996_AIF1TX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); - snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, - WM8996_AIF1TX_CHAN2_SLOTS_MASK | - WM8996_AIF1TX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1TX_CHAN2_SLOTS_SHIFT | 0); - snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, - WM8996_AIF1TX_CHAN3_SLOTS_MASK | - WM8996_AIF1TX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1TX_CHAN3_SLOTS_SHIFT | 1); - snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, - WM8996_AIF1TX_CHAN4_SLOTS_MASK | - WM8996_AIF1TX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1TX_CHAN4_SLOTS_SHIFT | 0); - snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, - WM8996_AIF1TX_CHAN5_SLOTS_MASK | - WM8996_AIF1TX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF1TX_CHAN5_SLOTS_SHIFT | 1); - - snd_soc_update_bits(codec, WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, - WM8996_AIF2TX_CHAN0_SLOTS_MASK | - WM8996_AIF2TX_CHAN0_START_SLOT_MASK, - 1 << WM8996_AIF2TX_CHAN0_SLOTS_SHIFT | 0); - snd_soc_update_bits(codec, WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, - WM8996_AIF2TX_CHAN1_SLOTS_MASK | - WM8996_AIF2TX_CHAN1_START_SLOT_MASK, - 1 << WM8996_AIF1TX_CHAN1_SLOTS_SHIFT | 1); - - if (wm8996->pdata.num_retune_mobile_cfgs) - wm8996_retune_mobile_pdata(codec); - else - snd_soc_add_codec_controls(codec, wm8996_eq_controls, - ARRAY_SIZE(wm8996_eq_controls)); - - /* If the TX LRCLK pins are not in LRCLK mode configure the - * AIFs to source their clocks from the RX LRCLKs. - */ - if ((snd_soc_read(codec, WM8996_GPIO_1))) - snd_soc_update_bits(codec, WM8996_AIF1_TX_LRCLK_2, - WM8996_AIF1TX_LRCLK_MODE, - WM8996_AIF1TX_LRCLK_MODE); - - if ((snd_soc_read(codec, WM8996_GPIO_2))) - snd_soc_update_bits(codec, WM8996_AIF2_TX_LRCLK_2, - WM8996_AIF2TX_LRCLK_MODE, - WM8996_AIF2TX_LRCLK_MODE); - - if (i2c->irq) { - if (wm8996->pdata.irq_flags) - irq_flags = wm8996->pdata.irq_flags; - else - irq_flags = IRQF_TRIGGER_LOW; - - irq_flags |= IRQF_ONESHOT; - - if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) - ret = request_threaded_irq(i2c->irq, NULL, - wm8996_edge_irq, - irq_flags, "wm8996", codec); - else - ret = request_threaded_irq(i2c->irq, NULL, wm8996_irq, - irq_flags, "wm8996", codec); - - if (ret == 0) { - /* Unmask the interrupt */ - snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL, - WM8996_IM_IRQ, 0); - - /* Enable error reporting and DC servo status */ - snd_soc_update_bits(codec, - WM8996_INTERRUPT_STATUS_2_MASK, - WM8996_IM_DCS_DONE_23_EINT | - WM8996_IM_DCS_DONE_01_EINT | - WM8996_IM_FLL_LOCK_EINT | - WM8996_IM_FIFOS_ERR_EINT, - 0); - } else { - dev_err(codec->dev, "Failed to request IRQ: %d\n", - ret); - } - } - - return 0; - -err: - return ret; -} - -static int wm8996_remove(struct snd_soc_codec *codec) -{ - struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); - struct i2c_client *i2c = to_i2c_client(codec->dev); - int i; - - snd_soc_update_bits(codec, WM8996_INTERRUPT_CONTROL, - WM8996_IM_IRQ, WM8996_IM_IRQ); - - if (i2c->irq) - free_irq(i2c->irq, codec); - - for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) - regulator_unregister_notifier(wm8996->supplies[i].consumer, - &wm8996->disable_nb[i]); - regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm8996 = { - .probe = wm8996_probe, - .remove = wm8996_remove, - .set_bias_level = wm8996_set_bias_level, - .idle_bias_off = true, - .seq_notifier = wm8996_seq_notifier, - .controls = wm8996_snd_controls, - .num_controls = ARRAY_SIZE(wm8996_snd_controls), - .dapm_widgets = wm8996_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8996_dapm_widgets), - .dapm_routes = wm8996_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes), - .set_pll = wm8996_set_fll, -}; - -#define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000) -#define WM8996_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm8996_dai_ops = { - .set_fmt = wm8996_set_fmt, - .hw_params = wm8996_hw_params, - .set_sysclk = wm8996_set_sysclk, -}; - -static struct snd_soc_dai_driver wm8996_dai[] = { - { - .name = "wm8996-aif1", - .playback = { - .stream_name = "AIF1 Playback", - .channels_min = 1, - .channels_max = 6, - .rates = WM8996_RATES, - .formats = WM8996_FORMATS, - .sig_bits = 24, - }, - .capture = { - .stream_name = "AIF1 Capture", - .channels_min = 1, - .channels_max = 6, - .rates = WM8996_RATES, - .formats = WM8996_FORMATS, - .sig_bits = 24, - }, - .ops = &wm8996_dai_ops, - }, - { - .name = "wm8996-aif2", - .playback = { - .stream_name = "AIF2 Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8996_RATES, - .formats = WM8996_FORMATS, - .sig_bits = 24, - }, - .capture = { - .stream_name = "AIF2 Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8996_RATES, - .formats = WM8996_FORMATS, - .sig_bits = 24, - }, - .ops = &wm8996_dai_ops, - }, -}; - -static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8996_priv *wm8996; - int ret, i; - unsigned int reg; - - wm8996 = devm_kzalloc(&i2c->dev, sizeof(struct wm8996_priv), - GFP_KERNEL); - if (wm8996 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm8996); - wm8996->dev = &i2c->dev; - - if (dev_get_platdata(&i2c->dev)) - memcpy(&wm8996->pdata, dev_get_platdata(&i2c->dev), - sizeof(wm8996->pdata)); - - if (wm8996->pdata.ldo_ena > 0) { - ret = gpio_request_one(wm8996->pdata.ldo_ena, - GPIOF_OUT_INIT_LOW, "WM8996 ENA"); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to request GPIO %d: %d\n", - wm8996->pdata.ldo_ena, ret); - goto err; - } - } - - for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) - wm8996->supplies[i].supply = wm8996_supply_names[i]; - - ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies), - wm8996->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); - goto err_gpio; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), - wm8996->supplies); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); - goto err_gpio; - } - - if (wm8996->pdata.ldo_ena > 0) { - gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1); - msleep(5); - } - - wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap); - if (IS_ERR(wm8996->regmap)) { - ret = PTR_ERR(wm8996->regmap); - dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); - goto err_enable; - } - - ret = regmap_read(wm8996->regmap, WM8996_SOFTWARE_RESET, ®); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); - goto err_regmap; - } - if (reg != 0x8915) { - dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", reg); - ret = -EINVAL; - goto err_regmap; - } - - ret = regmap_read(wm8996->regmap, WM8996_CHIP_REVISION, ®); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to read device revision: %d\n", - ret); - goto err_regmap; - } - - dev_info(&i2c->dev, "revision %c\n", - (reg & WM8996_CHIP_REV_MASK) + 'A'); - - regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); - - ret = wm8996_reset(wm8996); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to issue reset\n"); - goto err_regmap; - } - - wm8996_init_gpio(wm8996); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm8996, wm8996_dai, - ARRAY_SIZE(wm8996_dai)); - if (ret < 0) - goto err_gpiolib; - - return ret; - -err_gpiolib: - wm8996_free_gpio(wm8996); -err_regmap: - regmap_exit(wm8996->regmap); -err_enable: - if (wm8996->pdata.ldo_ena > 0) - gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); - regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); -err_gpio: - if (wm8996->pdata.ldo_ena > 0) - gpio_free(wm8996->pdata.ldo_ena); -err: - - return ret; -} - -static __devexit int wm8996_i2c_remove(struct i2c_client *client) -{ - struct wm8996_priv *wm8996 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - wm8996_free_gpio(wm8996); - regmap_exit(wm8996->regmap); - if (wm8996->pdata.ldo_ena > 0) { - gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); - gpio_free(wm8996->pdata.ldo_ena); - } - return 0; -} - -static const struct i2c_device_id wm8996_i2c_id[] = { - { "wm8996", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8996_i2c_id); - -static struct i2c_driver wm8996_i2c_driver = { - .driver = { - .name = "wm8996", - .owner = THIS_MODULE, - }, - .probe = wm8996_i2c_probe, - .remove = __devexit_p(wm8996_i2c_remove), - .id_table = wm8996_i2c_id, -}; - -module_i2c_driver(wm8996_i2c_driver); - -MODULE_DESCRIPTION("ASoC WM8996 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm8996.h b/ANDROID_3.4.5/sound/soc/codecs/wm8996.h deleted file mode 100644 index de9ac3e4..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm8996.h +++ /dev/null @@ -1,3721 +0,0 @@ -/* - * wm8996.h - WM8996 audio codec interface - * - * Copyright 2011 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * 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. - */ - -#ifndef _WM8996_H -#define _WM8996_H - -#define WM8996_SYSCLK_MCLK1 1 -#define WM8996_SYSCLK_MCLK2 2 -#define WM8996_SYSCLK_FLL 3 - -#define WM8996_FLL_MCLK1 1 -#define WM8996_FLL_MCLK2 2 -#define WM8996_FLL_DACLRCLK1 3 -#define WM8996_FLL_BCLK1 4 - -typedef void (*wm8996_polarity_fn)(struct snd_soc_codec *codec, int polarity); - -int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, - wm8996_polarity_fn polarity_cb); - -/* - * Register values. - */ -#define WM8996_SOFTWARE_RESET 0x00 -#define WM8996_POWER_MANAGEMENT_1 0x01 -#define WM8996_POWER_MANAGEMENT_2 0x02 -#define WM8996_POWER_MANAGEMENT_3 0x03 -#define WM8996_POWER_MANAGEMENT_4 0x04 -#define WM8996_POWER_MANAGEMENT_5 0x05 -#define WM8996_POWER_MANAGEMENT_6 0x06 -#define WM8996_POWER_MANAGEMENT_7 0x07 -#define WM8996_POWER_MANAGEMENT_8 0x08 -#define WM8996_LEFT_LINE_INPUT_VOLUME 0x10 -#define WM8996_RIGHT_LINE_INPUT_VOLUME 0x11 -#define WM8996_LINE_INPUT_CONTROL 0x12 -#define WM8996_DAC1_HPOUT1_VOLUME 0x15 -#define WM8996_DAC2_HPOUT2_VOLUME 0x16 -#define WM8996_DAC1_LEFT_VOLUME 0x18 -#define WM8996_DAC1_RIGHT_VOLUME 0x19 -#define WM8996_DAC2_LEFT_VOLUME 0x1A -#define WM8996_DAC2_RIGHT_VOLUME 0x1B -#define WM8996_OUTPUT1_LEFT_VOLUME 0x1C -#define WM8996_OUTPUT1_RIGHT_VOLUME 0x1D -#define WM8996_OUTPUT2_LEFT_VOLUME 0x1E -#define WM8996_OUTPUT2_RIGHT_VOLUME 0x1F -#define WM8996_MICBIAS_1 0x20 -#define WM8996_MICBIAS_2 0x21 -#define WM8996_LDO_1 0x28 -#define WM8996_LDO_2 0x29 -#define WM8996_ACCESSORY_DETECT_MODE_1 0x30 -#define WM8996_ACCESSORY_DETECT_MODE_2 0x31 -#define WM8996_HEADPHONE_DETECT_1 0x34 -#define WM8996_HEADPHONE_DETECT_2 0x35 -#define WM8996_MIC_DETECT_1 0x38 -#define WM8996_MIC_DETECT_2 0x39 -#define WM8996_MIC_DETECT_3 0x3A -#define WM8996_CHARGE_PUMP_1 0x40 -#define WM8996_CHARGE_PUMP_2 0x41 -#define WM8996_DC_SERVO_1 0x50 -#define WM8996_DC_SERVO_2 0x51 -#define WM8996_DC_SERVO_3 0x52 -#define WM8996_DC_SERVO_5 0x54 -#define WM8996_DC_SERVO_6 0x55 -#define WM8996_DC_SERVO_7 0x56 -#define WM8996_DC_SERVO_READBACK_0 0x57 -#define WM8996_ANALOGUE_HP_1 0x60 -#define WM8996_ANALOGUE_HP_2 0x61 -#define WM8996_CHIP_REVISION 0x100 -#define WM8996_CONTROL_INTERFACE_1 0x101 -#define WM8996_WRITE_SEQUENCER_CTRL_1 0x110 -#define WM8996_WRITE_SEQUENCER_CTRL_2 0x111 -#define WM8996_AIF_CLOCKING_1 0x200 -#define WM8996_AIF_CLOCKING_2 0x201 -#define WM8996_CLOCKING_1 0x208 -#define WM8996_CLOCKING_2 0x209 -#define WM8996_AIF_RATE 0x210 -#define WM8996_FLL_CONTROL_1 0x220 -#define WM8996_FLL_CONTROL_2 0x221 -#define WM8996_FLL_CONTROL_3 0x222 -#define WM8996_FLL_CONTROL_4 0x223 -#define WM8996_FLL_CONTROL_5 0x224 -#define WM8996_FLL_CONTROL_6 0x225 -#define WM8996_FLL_EFS_1 0x226 -#define WM8996_FLL_EFS_2 0x227 -#define WM8996_AIF1_CONTROL 0x300 -#define WM8996_AIF1_BCLK 0x301 -#define WM8996_AIF1_TX_LRCLK_1 0x302 -#define WM8996_AIF1_TX_LRCLK_2 0x303 -#define WM8996_AIF1_RX_LRCLK_1 0x304 -#define WM8996_AIF1_RX_LRCLK_2 0x305 -#define WM8996_AIF1TX_DATA_CONFIGURATION_1 0x306 -#define WM8996_AIF1TX_DATA_CONFIGURATION_2 0x307 -#define WM8996_AIF1RX_DATA_CONFIGURATION 0x308 -#define WM8996_AIF1TX_CHANNEL_0_CONFIGURATION 0x309 -#define WM8996_AIF1TX_CHANNEL_1_CONFIGURATION 0x30A -#define WM8996_AIF1TX_CHANNEL_2_CONFIGURATION 0x30B -#define WM8996_AIF1TX_CHANNEL_3_CONFIGURATION 0x30C -#define WM8996_AIF1TX_CHANNEL_4_CONFIGURATION 0x30D -#define WM8996_AIF1TX_CHANNEL_5_CONFIGURATION 0x30E -#define WM8996_AIF1RX_CHANNEL_0_CONFIGURATION 0x30F -#define WM8996_AIF1RX_CHANNEL_1_CONFIGURATION 0x310 -#define WM8996_AIF1RX_CHANNEL_2_CONFIGURATION 0x311 -#define WM8996_AIF1RX_CHANNEL_3_CONFIGURATION 0x312 -#define WM8996_AIF1RX_CHANNEL_4_CONFIGURATION 0x313 -#define WM8996_AIF1RX_CHANNEL_5_CONFIGURATION 0x314 -#define WM8996_AIF1RX_MONO_CONFIGURATION 0x315 -#define WM8996_AIF1TX_TEST 0x31A -#define WM8996_AIF2_CONTROL 0x320 -#define WM8996_AIF2_BCLK 0x321 -#define WM8996_AIF2_TX_LRCLK_1 0x322 -#define WM8996_AIF2_TX_LRCLK_2 0x323 -#define WM8996_AIF2_RX_LRCLK_1 0x324 -#define WM8996_AIF2_RX_LRCLK_2 0x325 -#define WM8996_AIF2TX_DATA_CONFIGURATION_1 0x326 -#define WM8996_AIF2TX_DATA_CONFIGURATION_2 0x327 -#define WM8996_AIF2RX_DATA_CONFIGURATION 0x328 -#define WM8996_AIF2TX_CHANNEL_0_CONFIGURATION 0x329 -#define WM8996_AIF2TX_CHANNEL_1_CONFIGURATION 0x32A -#define WM8996_AIF2RX_CHANNEL_0_CONFIGURATION 0x32B -#define WM8996_AIF2RX_CHANNEL_1_CONFIGURATION 0x32C -#define WM8996_AIF2RX_MONO_CONFIGURATION 0x32D -#define WM8996_AIF2TX_TEST 0x32F -#define WM8996_DSP1_TX_LEFT_VOLUME 0x400 -#define WM8996_DSP1_TX_RIGHT_VOLUME 0x401 -#define WM8996_DSP1_RX_LEFT_VOLUME 0x402 -#define WM8996_DSP1_RX_RIGHT_VOLUME 0x403 -#define WM8996_DSP1_TX_FILTERS 0x410 -#define WM8996_DSP1_RX_FILTERS_1 0x420 -#define WM8996_DSP1_RX_FILTERS_2 0x421 -#define WM8996_DSP1_DRC_1 0x440 -#define WM8996_DSP1_DRC_2 0x441 -#define WM8996_DSP1_DRC_3 0x442 -#define WM8996_DSP1_DRC_4 0x443 -#define WM8996_DSP1_DRC_5 0x444 -#define WM8996_DSP1_RX_EQ_GAINS_1 0x480 -#define WM8996_DSP1_RX_EQ_GAINS_2 0x481 -#define WM8996_DSP1_RX_EQ_BAND_1_A 0x482 -#define WM8996_DSP1_RX_EQ_BAND_1_B 0x483 -#define WM8996_DSP1_RX_EQ_BAND_1_PG 0x484 -#define WM8996_DSP1_RX_EQ_BAND_2_A 0x485 -#define WM8996_DSP1_RX_EQ_BAND_2_B 0x486 -#define WM8996_DSP1_RX_EQ_BAND_2_C 0x487 -#define WM8996_DSP1_RX_EQ_BAND_2_PG 0x488 -#define WM8996_DSP1_RX_EQ_BAND_3_A 0x489 -#define WM8996_DSP1_RX_EQ_BAND_3_B 0x48A -#define WM8996_DSP1_RX_EQ_BAND_3_C 0x48B -#define WM8996_DSP1_RX_EQ_BAND_3_PG 0x48C -#define WM8996_DSP1_RX_EQ_BAND_4_A 0x48D -#define WM8996_DSP1_RX_EQ_BAND_4_B 0x48E -#define WM8996_DSP1_RX_EQ_BAND_4_C 0x48F -#define WM8996_DSP1_RX_EQ_BAND_4_PG 0x490 -#define WM8996_DSP1_RX_EQ_BAND_5_A 0x491 -#define WM8996_DSP1_RX_EQ_BAND_5_B 0x492 -#define WM8996_DSP1_RX_EQ_BAND_5_PG 0x493 -#define WM8996_DSP2_TX_LEFT_VOLUME 0x500 -#define WM8996_DSP2_TX_RIGHT_VOLUME 0x501 -#define WM8996_DSP2_RX_LEFT_VOLUME 0x502 -#define WM8996_DSP2_RX_RIGHT_VOLUME 0x503 -#define WM8996_DSP2_TX_FILTERS 0x510 -#define WM8996_DSP2_RX_FILTERS_1 0x520 -#define WM8996_DSP2_RX_FILTERS_2 0x521 -#define WM8996_DSP2_DRC_1 0x540 -#define WM8996_DSP2_DRC_2 0x541 -#define WM8996_DSP2_DRC_3 0x542 -#define WM8996_DSP2_DRC_4 0x543 -#define WM8996_DSP2_DRC_5 0x544 -#define WM8996_DSP2_RX_EQ_GAINS_1 0x580 -#define WM8996_DSP2_RX_EQ_GAINS_2 0x581 -#define WM8996_DSP2_RX_EQ_BAND_1_A 0x582 -#define WM8996_DSP2_RX_EQ_BAND_1_B 0x583 -#define WM8996_DSP2_RX_EQ_BAND_1_PG 0x584 -#define WM8996_DSP2_RX_EQ_BAND_2_A 0x585 -#define WM8996_DSP2_RX_EQ_BAND_2_B 0x586 -#define WM8996_DSP2_RX_EQ_BAND_2_C 0x587 -#define WM8996_DSP2_RX_EQ_BAND_2_PG 0x588 -#define WM8996_DSP2_RX_EQ_BAND_3_A 0x589 -#define WM8996_DSP2_RX_EQ_BAND_3_B 0x58A -#define WM8996_DSP2_RX_EQ_BAND_3_C 0x58B -#define WM8996_DSP2_RX_EQ_BAND_3_PG 0x58C -#define WM8996_DSP2_RX_EQ_BAND_4_A 0x58D -#define WM8996_DSP2_RX_EQ_BAND_4_B 0x58E -#define WM8996_DSP2_RX_EQ_BAND_4_C 0x58F -#define WM8996_DSP2_RX_EQ_BAND_4_PG 0x590 -#define WM8996_DSP2_RX_EQ_BAND_5_A 0x591 -#define WM8996_DSP2_RX_EQ_BAND_5_B 0x592 -#define WM8996_DSP2_RX_EQ_BAND_5_PG 0x593 -#define WM8996_DAC1_MIXER_VOLUMES 0x600 -#define WM8996_DAC1_LEFT_MIXER_ROUTING 0x601 -#define WM8996_DAC1_RIGHT_MIXER_ROUTING 0x602 -#define WM8996_DAC2_MIXER_VOLUMES 0x603 -#define WM8996_DAC2_LEFT_MIXER_ROUTING 0x604 -#define WM8996_DAC2_RIGHT_MIXER_ROUTING 0x605 -#define WM8996_DSP1_TX_LEFT_MIXER_ROUTING 0x606 -#define WM8996_DSP1_TX_RIGHT_MIXER_ROUTING 0x607 -#define WM8996_DSP2_TX_LEFT_MIXER_ROUTING 0x608 -#define WM8996_DSP2_TX_RIGHT_MIXER_ROUTING 0x609 -#define WM8996_DSP_TX_MIXER_SELECT 0x60A -#define WM8996_DAC_SOFTMUTE 0x610 -#define WM8996_OVERSAMPLING 0x620 -#define WM8996_SIDETONE 0x621 -#define WM8996_GPIO_1 0x700 -#define WM8996_GPIO_2 0x701 -#define WM8996_GPIO_3 0x702 -#define WM8996_GPIO_4 0x703 -#define WM8996_GPIO_5 0x704 -#define WM8996_PULL_CONTROL_1 0x720 -#define WM8996_PULL_CONTROL_2 0x721 -#define WM8996_INTERRUPT_STATUS_1 0x730 -#define WM8996_INTERRUPT_STATUS_2 0x731 -#define WM8996_INTERRUPT_RAW_STATUS_2 0x732 -#define WM8996_INTERRUPT_STATUS_1_MASK 0x738 -#define WM8996_INTERRUPT_STATUS_2_MASK 0x739 -#define WM8996_INTERRUPT_CONTROL 0x740 -#define WM8996_LEFT_PDM_SPEAKER 0x800 -#define WM8996_RIGHT_PDM_SPEAKER 0x801 -#define WM8996_PDM_SPEAKER_MUTE_SEQUENCE 0x802 -#define WM8996_PDM_SPEAKER_VOLUME 0x803 -#define WM8996_WRITE_SEQUENCER_0 0x3000 -#define WM8996_WRITE_SEQUENCER_1 0x3001 -#define WM8996_WRITE_SEQUENCER_2 0x3002 -#define WM8996_WRITE_SEQUENCER_3 0x3003 -#define WM8996_WRITE_SEQUENCER_4 0x3004 -#define WM8996_WRITE_SEQUENCER_5 0x3005 -#define WM8996_WRITE_SEQUENCER_6 0x3006 -#define WM8996_WRITE_SEQUENCER_7 0x3007 -#define WM8996_WRITE_SEQUENCER_8 0x3008 -#define WM8996_WRITE_SEQUENCER_9 0x3009 -#define WM8996_WRITE_SEQUENCER_10 0x300A -#define WM8996_WRITE_SEQUENCER_11 0x300B -#define WM8996_WRITE_SEQUENCER_12 0x300C -#define WM8996_WRITE_SEQUENCER_13 0x300D -#define WM8996_WRITE_SEQUENCER_14 0x300E -#define WM8996_WRITE_SEQUENCER_15 0x300F -#define WM8996_WRITE_SEQUENCER_16 0x3010 -#define WM8996_WRITE_SEQUENCER_17 0x3011 -#define WM8996_WRITE_SEQUENCER_18 0x3012 -#define WM8996_WRITE_SEQUENCER_19 0x3013 -#define WM8996_WRITE_SEQUENCER_20 0x3014 -#define WM8996_WRITE_SEQUENCER_21 0x3015 -#define WM8996_WRITE_SEQUENCER_22 0x3016 -#define WM8996_WRITE_SEQUENCER_23 0x3017 -#define WM8996_WRITE_SEQUENCER_24 0x3018 -#define WM8996_WRITE_SEQUENCER_25 0x3019 -#define WM8996_WRITE_SEQUENCER_26 0x301A -#define WM8996_WRITE_SEQUENCER_27 0x301B -#define WM8996_WRITE_SEQUENCER_28 0x301C -#define WM8996_WRITE_SEQUENCER_29 0x301D -#define WM8996_WRITE_SEQUENCER_30 0x301E -#define WM8996_WRITE_SEQUENCER_31 0x301F -#define WM8996_WRITE_SEQUENCER_32 0x3020 -#define WM8996_WRITE_SEQUENCER_33 0x3021 -#define WM8996_WRITE_SEQUENCER_34 0x3022 -#define WM8996_WRITE_SEQUENCER_35 0x3023 -#define WM8996_WRITE_SEQUENCER_36 0x3024 -#define WM8996_WRITE_SEQUENCER_37 0x3025 -#define WM8996_WRITE_SEQUENCER_38 0x3026 -#define WM8996_WRITE_SEQUENCER_39 0x3027 -#define WM8996_WRITE_SEQUENCER_40 0x3028 -#define WM8996_WRITE_SEQUENCER_41 0x3029 -#define WM8996_WRITE_SEQUENCER_42 0x302A -#define WM8996_WRITE_SEQUENCER_43 0x302B -#define WM8996_WRITE_SEQUENCER_44 0x302C -#define WM8996_WRITE_SEQUENCER_45 0x302D -#define WM8996_WRITE_SEQUENCER_46 0x302E -#define WM8996_WRITE_SEQUENCER_47 0x302F -#define WM8996_WRITE_SEQUENCER_48 0x3030 -#define WM8996_WRITE_SEQUENCER_49 0x3031 -#define WM8996_WRITE_SEQUENCER_50 0x3032 -#define WM8996_WRITE_SEQUENCER_51 0x3033 -#define WM8996_WRITE_SEQUENCER_52 0x3034 -#define WM8996_WRITE_SEQUENCER_53 0x3035 -#define WM8996_WRITE_SEQUENCER_54 0x3036 -#define WM8996_WRITE_SEQUENCER_55 0x3037 -#define WM8996_WRITE_SEQUENCER_56 0x3038 -#define WM8996_WRITE_SEQUENCER_57 0x3039 -#define WM8996_WRITE_SEQUENCER_58 0x303A -#define WM8996_WRITE_SEQUENCER_59 0x303B -#define WM8996_WRITE_SEQUENCER_60 0x303C -#define WM8996_WRITE_SEQUENCER_61 0x303D -#define WM8996_WRITE_SEQUENCER_62 0x303E -#define WM8996_WRITE_SEQUENCER_63 0x303F -#define WM8996_WRITE_SEQUENCER_64 0x3040 -#define WM8996_WRITE_SEQUENCER_65 0x3041 -#define WM8996_WRITE_SEQUENCER_66 0x3042 -#define WM8996_WRITE_SEQUENCER_67 0x3043 -#define WM8996_WRITE_SEQUENCER_68 0x3044 -#define WM8996_WRITE_SEQUENCER_69 0x3045 -#define WM8996_WRITE_SEQUENCER_70 0x3046 -#define WM8996_WRITE_SEQUENCER_71 0x3047 -#define WM8996_WRITE_SEQUENCER_72 0x3048 -#define WM8996_WRITE_SEQUENCER_73 0x3049 -#define WM8996_WRITE_SEQUENCER_74 0x304A -#define WM8996_WRITE_SEQUENCER_75 0x304B -#define WM8996_WRITE_SEQUENCER_76 0x304C -#define WM8996_WRITE_SEQUENCER_77 0x304D -#define WM8996_WRITE_SEQUENCER_78 0x304E -#define WM8996_WRITE_SEQUENCER_79 0x304F -#define WM8996_WRITE_SEQUENCER_80 0x3050 -#define WM8996_WRITE_SEQUENCER_81 0x3051 -#define WM8996_WRITE_SEQUENCER_82 0x3052 -#define WM8996_WRITE_SEQUENCER_83 0x3053 -#define WM8996_WRITE_SEQUENCER_84 0x3054 -#define WM8996_WRITE_SEQUENCER_85 0x3055 -#define WM8996_WRITE_SEQUENCER_86 0x3056 -#define WM8996_WRITE_SEQUENCER_87 0x3057 -#define WM8996_WRITE_SEQUENCER_88 0x3058 -#define WM8996_WRITE_SEQUENCER_89 0x3059 -#define WM8996_WRITE_SEQUENCER_90 0x305A -#define WM8996_WRITE_SEQUENCER_91 0x305B -#define WM8996_WRITE_SEQUENCER_92 0x305C -#define WM8996_WRITE_SEQUENCER_93 0x305D -#define WM8996_WRITE_SEQUENCER_94 0x305E -#define WM8996_WRITE_SEQUENCER_95 0x305F -#define WM8996_WRITE_SEQUENCER_96 0x3060 -#define WM8996_WRITE_SEQUENCER_97 0x3061 -#define WM8996_WRITE_SEQUENCER_98 0x3062 -#define WM8996_WRITE_SEQUENCER_99 0x3063 -#define WM8996_WRITE_SEQUENCER_100 0x3064 -#define WM8996_WRITE_SEQUENCER_101 0x3065 -#define WM8996_WRITE_SEQUENCER_102 0x3066 -#define WM8996_WRITE_SEQUENCER_103 0x3067 -#define WM8996_WRITE_SEQUENCER_104 0x3068 -#define WM8996_WRITE_SEQUENCER_105 0x3069 -#define WM8996_WRITE_SEQUENCER_106 0x306A -#define WM8996_WRITE_SEQUENCER_107 0x306B -#define WM8996_WRITE_SEQUENCER_108 0x306C -#define WM8996_WRITE_SEQUENCER_109 0x306D -#define WM8996_WRITE_SEQUENCER_110 0x306E -#define WM8996_WRITE_SEQUENCER_111 0x306F -#define WM8996_WRITE_SEQUENCER_112 0x3070 -#define WM8996_WRITE_SEQUENCER_113 0x3071 -#define WM8996_WRITE_SEQUENCER_114 0x3072 -#define WM8996_WRITE_SEQUENCER_115 0x3073 -#define WM8996_WRITE_SEQUENCER_116 0x3074 -#define WM8996_WRITE_SEQUENCER_117 0x3075 -#define WM8996_WRITE_SEQUENCER_118 0x3076 -#define WM8996_WRITE_SEQUENCER_119 0x3077 -#define WM8996_WRITE_SEQUENCER_120 0x3078 -#define WM8996_WRITE_SEQUENCER_121 0x3079 -#define WM8996_WRITE_SEQUENCER_122 0x307A -#define WM8996_WRITE_SEQUENCER_123 0x307B -#define WM8996_WRITE_SEQUENCER_124 0x307C -#define WM8996_WRITE_SEQUENCER_125 0x307D -#define WM8996_WRITE_SEQUENCER_126 0x307E -#define WM8996_WRITE_SEQUENCER_127 0x307F -#define WM8996_WRITE_SEQUENCER_128 0x3080 -#define WM8996_WRITE_SEQUENCER_129 0x3081 -#define WM8996_WRITE_SEQUENCER_130 0x3082 -#define WM8996_WRITE_SEQUENCER_131 0x3083 -#define WM8996_WRITE_SEQUENCER_132 0x3084 -#define WM8996_WRITE_SEQUENCER_133 0x3085 -#define WM8996_WRITE_SEQUENCER_134 0x3086 -#define WM8996_WRITE_SEQUENCER_135 0x3087 -#define WM8996_WRITE_SEQUENCER_136 0x3088 -#define WM8996_WRITE_SEQUENCER_137 0x3089 -#define WM8996_WRITE_SEQUENCER_138 0x308A -#define WM8996_WRITE_SEQUENCER_139 0x308B -#define WM8996_WRITE_SEQUENCER_140 0x308C -#define WM8996_WRITE_SEQUENCER_141 0x308D -#define WM8996_WRITE_SEQUENCER_142 0x308E -#define WM8996_WRITE_SEQUENCER_143 0x308F -#define WM8996_WRITE_SEQUENCER_144 0x3090 -#define WM8996_WRITE_SEQUENCER_145 0x3091 -#define WM8996_WRITE_SEQUENCER_146 0x3092 -#define WM8996_WRITE_SEQUENCER_147 0x3093 -#define WM8996_WRITE_SEQUENCER_148 0x3094 -#define WM8996_WRITE_SEQUENCER_149 0x3095 -#define WM8996_WRITE_SEQUENCER_150 0x3096 -#define WM8996_WRITE_SEQUENCER_151 0x3097 -#define WM8996_WRITE_SEQUENCER_152 0x3098 -#define WM8996_WRITE_SEQUENCER_153 0x3099 -#define WM8996_WRITE_SEQUENCER_154 0x309A -#define WM8996_WRITE_SEQUENCER_155 0x309B -#define WM8996_WRITE_SEQUENCER_156 0x309C -#define WM8996_WRITE_SEQUENCER_157 0x309D -#define WM8996_WRITE_SEQUENCER_158 0x309E -#define WM8996_WRITE_SEQUENCER_159 0x309F -#define WM8996_WRITE_SEQUENCER_160 0x30A0 -#define WM8996_WRITE_SEQUENCER_161 0x30A1 -#define WM8996_WRITE_SEQUENCER_162 0x30A2 -#define WM8996_WRITE_SEQUENCER_163 0x30A3 -#define WM8996_WRITE_SEQUENCER_164 0x30A4 -#define WM8996_WRITE_SEQUENCER_165 0x30A5 -#define WM8996_WRITE_SEQUENCER_166 0x30A6 -#define WM8996_WRITE_SEQUENCER_167 0x30A7 -#define WM8996_WRITE_SEQUENCER_168 0x30A8 -#define WM8996_WRITE_SEQUENCER_169 0x30A9 -#define WM8996_WRITE_SEQUENCER_170 0x30AA -#define WM8996_WRITE_SEQUENCER_171 0x30AB -#define WM8996_WRITE_SEQUENCER_172 0x30AC -#define WM8996_WRITE_SEQUENCER_173 0x30AD -#define WM8996_WRITE_SEQUENCER_174 0x30AE -#define WM8996_WRITE_SEQUENCER_175 0x30AF -#define WM8996_WRITE_SEQUENCER_176 0x30B0 -#define WM8996_WRITE_SEQUENCER_177 0x30B1 -#define WM8996_WRITE_SEQUENCER_178 0x30B2 -#define WM8996_WRITE_SEQUENCER_179 0x30B3 -#define WM8996_WRITE_SEQUENCER_180 0x30B4 -#define WM8996_WRITE_SEQUENCER_181 0x30B5 -#define WM8996_WRITE_SEQUENCER_182 0x30B6 -#define WM8996_WRITE_SEQUENCER_183 0x30B7 -#define WM8996_WRITE_SEQUENCER_184 0x30B8 -#define WM8996_WRITE_SEQUENCER_185 0x30B9 -#define WM8996_WRITE_SEQUENCER_186 0x30BA -#define WM8996_WRITE_SEQUENCER_187 0x30BB -#define WM8996_WRITE_SEQUENCER_188 0x30BC -#define WM8996_WRITE_SEQUENCER_189 0x30BD -#define WM8996_WRITE_SEQUENCER_190 0x30BE -#define WM8996_WRITE_SEQUENCER_191 0x30BF -#define WM8996_WRITE_SEQUENCER_192 0x30C0 -#define WM8996_WRITE_SEQUENCER_193 0x30C1 -#define WM8996_WRITE_SEQUENCER_194 0x30C2 -#define WM8996_WRITE_SEQUENCER_195 0x30C3 -#define WM8996_WRITE_SEQUENCER_196 0x30C4 -#define WM8996_WRITE_SEQUENCER_197 0x30C5 -#define WM8996_WRITE_SEQUENCER_198 0x30C6 -#define WM8996_WRITE_SEQUENCER_199 0x30C7 -#define WM8996_WRITE_SEQUENCER_200 0x30C8 -#define WM8996_WRITE_SEQUENCER_201 0x30C9 -#define WM8996_WRITE_SEQUENCER_202 0x30CA -#define WM8996_WRITE_SEQUENCER_203 0x30CB -#define WM8996_WRITE_SEQUENCER_204 0x30CC -#define WM8996_WRITE_SEQUENCER_205 0x30CD -#define WM8996_WRITE_SEQUENCER_206 0x30CE -#define WM8996_WRITE_SEQUENCER_207 0x30CF -#define WM8996_WRITE_SEQUENCER_208 0x30D0 -#define WM8996_WRITE_SEQUENCER_209 0x30D1 -#define WM8996_WRITE_SEQUENCER_210 0x30D2 -#define WM8996_WRITE_SEQUENCER_211 0x30D3 -#define WM8996_WRITE_SEQUENCER_212 0x30D4 -#define WM8996_WRITE_SEQUENCER_213 0x30D5 -#define WM8996_WRITE_SEQUENCER_214 0x30D6 -#define WM8996_WRITE_SEQUENCER_215 0x30D7 -#define WM8996_WRITE_SEQUENCER_216 0x30D8 -#define WM8996_WRITE_SEQUENCER_217 0x30D9 -#define WM8996_WRITE_SEQUENCER_218 0x30DA -#define WM8996_WRITE_SEQUENCER_219 0x30DB -#define WM8996_WRITE_SEQUENCER_220 0x30DC -#define WM8996_WRITE_SEQUENCER_221 0x30DD -#define WM8996_WRITE_SEQUENCER_222 0x30DE -#define WM8996_WRITE_SEQUENCER_223 0x30DF -#define WM8996_WRITE_SEQUENCER_224 0x30E0 -#define WM8996_WRITE_SEQUENCER_225 0x30E1 -#define WM8996_WRITE_SEQUENCER_226 0x30E2 -#define WM8996_WRITE_SEQUENCER_227 0x30E3 -#define WM8996_WRITE_SEQUENCER_228 0x30E4 -#define WM8996_WRITE_SEQUENCER_229 0x30E5 -#define WM8996_WRITE_SEQUENCER_230 0x30E6 -#define WM8996_WRITE_SEQUENCER_231 0x30E7 -#define WM8996_WRITE_SEQUENCER_232 0x30E8 -#define WM8996_WRITE_SEQUENCER_233 0x30E9 -#define WM8996_WRITE_SEQUENCER_234 0x30EA -#define WM8996_WRITE_SEQUENCER_235 0x30EB -#define WM8996_WRITE_SEQUENCER_236 0x30EC -#define WM8996_WRITE_SEQUENCER_237 0x30ED -#define WM8996_WRITE_SEQUENCER_238 0x30EE -#define WM8996_WRITE_SEQUENCER_239 0x30EF -#define WM8996_WRITE_SEQUENCER_240 0x30F0 -#define WM8996_WRITE_SEQUENCER_241 0x30F1 -#define WM8996_WRITE_SEQUENCER_242 0x30F2 -#define WM8996_WRITE_SEQUENCER_243 0x30F3 -#define WM8996_WRITE_SEQUENCER_244 0x30F4 -#define WM8996_WRITE_SEQUENCER_245 0x30F5 -#define WM8996_WRITE_SEQUENCER_246 0x30F6 -#define WM8996_WRITE_SEQUENCER_247 0x30F7 -#define WM8996_WRITE_SEQUENCER_248 0x30F8 -#define WM8996_WRITE_SEQUENCER_249 0x30F9 -#define WM8996_WRITE_SEQUENCER_250 0x30FA -#define WM8996_WRITE_SEQUENCER_251 0x30FB -#define WM8996_WRITE_SEQUENCER_252 0x30FC -#define WM8996_WRITE_SEQUENCER_253 0x30FD -#define WM8996_WRITE_SEQUENCER_254 0x30FE -#define WM8996_WRITE_SEQUENCER_255 0x30FF -#define WM8996_WRITE_SEQUENCER_256 0x3100 -#define WM8996_WRITE_SEQUENCER_257 0x3101 -#define WM8996_WRITE_SEQUENCER_258 0x3102 -#define WM8996_WRITE_SEQUENCER_259 0x3103 -#define WM8996_WRITE_SEQUENCER_260 0x3104 -#define WM8996_WRITE_SEQUENCER_261 0x3105 -#define WM8996_WRITE_SEQUENCER_262 0x3106 -#define WM8996_WRITE_SEQUENCER_263 0x3107 -#define WM8996_WRITE_SEQUENCER_264 0x3108 -#define WM8996_WRITE_SEQUENCER_265 0x3109 -#define WM8996_WRITE_SEQUENCER_266 0x310A -#define WM8996_WRITE_SEQUENCER_267 0x310B -#define WM8996_WRITE_SEQUENCER_268 0x310C -#define WM8996_WRITE_SEQUENCER_269 0x310D -#define WM8996_WRITE_SEQUENCER_270 0x310E -#define WM8996_WRITE_SEQUENCER_271 0x310F -#define WM8996_WRITE_SEQUENCER_272 0x3110 -#define WM8996_WRITE_SEQUENCER_273 0x3111 -#define WM8996_WRITE_SEQUENCER_274 0x3112 -#define WM8996_WRITE_SEQUENCER_275 0x3113 -#define WM8996_WRITE_SEQUENCER_276 0x3114 -#define WM8996_WRITE_SEQUENCER_277 0x3115 -#define WM8996_WRITE_SEQUENCER_278 0x3116 -#define WM8996_WRITE_SEQUENCER_279 0x3117 -#define WM8996_WRITE_SEQUENCER_280 0x3118 -#define WM8996_WRITE_SEQUENCER_281 0x3119 -#define WM8996_WRITE_SEQUENCER_282 0x311A -#define WM8996_WRITE_SEQUENCER_283 0x311B -#define WM8996_WRITE_SEQUENCER_284 0x311C -#define WM8996_WRITE_SEQUENCER_285 0x311D -#define WM8996_WRITE_SEQUENCER_286 0x311E -#define WM8996_WRITE_SEQUENCER_287 0x311F -#define WM8996_WRITE_SEQUENCER_288 0x3120 -#define WM8996_WRITE_SEQUENCER_289 0x3121 -#define WM8996_WRITE_SEQUENCER_290 0x3122 -#define WM8996_WRITE_SEQUENCER_291 0x3123 -#define WM8996_WRITE_SEQUENCER_292 0x3124 -#define WM8996_WRITE_SEQUENCER_293 0x3125 -#define WM8996_WRITE_SEQUENCER_294 0x3126 -#define WM8996_WRITE_SEQUENCER_295 0x3127 -#define WM8996_WRITE_SEQUENCER_296 0x3128 -#define WM8996_WRITE_SEQUENCER_297 0x3129 -#define WM8996_WRITE_SEQUENCER_298 0x312A -#define WM8996_WRITE_SEQUENCER_299 0x312B -#define WM8996_WRITE_SEQUENCER_300 0x312C -#define WM8996_WRITE_SEQUENCER_301 0x312D -#define WM8996_WRITE_SEQUENCER_302 0x312E -#define WM8996_WRITE_SEQUENCER_303 0x312F -#define WM8996_WRITE_SEQUENCER_304 0x3130 -#define WM8996_WRITE_SEQUENCER_305 0x3131 -#define WM8996_WRITE_SEQUENCER_306 0x3132 -#define WM8996_WRITE_SEQUENCER_307 0x3133 -#define WM8996_WRITE_SEQUENCER_308 0x3134 -#define WM8996_WRITE_SEQUENCER_309 0x3135 -#define WM8996_WRITE_SEQUENCER_310 0x3136 -#define WM8996_WRITE_SEQUENCER_311 0x3137 -#define WM8996_WRITE_SEQUENCER_312 0x3138 -#define WM8996_WRITE_SEQUENCER_313 0x3139 -#define WM8996_WRITE_SEQUENCER_314 0x313A -#define WM8996_WRITE_SEQUENCER_315 0x313B -#define WM8996_WRITE_SEQUENCER_316 0x313C -#define WM8996_WRITE_SEQUENCER_317 0x313D -#define WM8996_WRITE_SEQUENCER_318 0x313E -#define WM8996_WRITE_SEQUENCER_319 0x313F -#define WM8996_WRITE_SEQUENCER_320 0x3140 -#define WM8996_WRITE_SEQUENCER_321 0x3141 -#define WM8996_WRITE_SEQUENCER_322 0x3142 -#define WM8996_WRITE_SEQUENCER_323 0x3143 -#define WM8996_WRITE_SEQUENCER_324 0x3144 -#define WM8996_WRITE_SEQUENCER_325 0x3145 -#define WM8996_WRITE_SEQUENCER_326 0x3146 -#define WM8996_WRITE_SEQUENCER_327 0x3147 -#define WM8996_WRITE_SEQUENCER_328 0x3148 -#define WM8996_WRITE_SEQUENCER_329 0x3149 -#define WM8996_WRITE_SEQUENCER_330 0x314A -#define WM8996_WRITE_SEQUENCER_331 0x314B -#define WM8996_WRITE_SEQUENCER_332 0x314C -#define WM8996_WRITE_SEQUENCER_333 0x314D -#define WM8996_WRITE_SEQUENCER_334 0x314E -#define WM8996_WRITE_SEQUENCER_335 0x314F -#define WM8996_WRITE_SEQUENCER_336 0x3150 -#define WM8996_WRITE_SEQUENCER_337 0x3151 -#define WM8996_WRITE_SEQUENCER_338 0x3152 -#define WM8996_WRITE_SEQUENCER_339 0x3153 -#define WM8996_WRITE_SEQUENCER_340 0x3154 -#define WM8996_WRITE_SEQUENCER_341 0x3155 -#define WM8996_WRITE_SEQUENCER_342 0x3156 -#define WM8996_WRITE_SEQUENCER_343 0x3157 -#define WM8996_WRITE_SEQUENCER_344 0x3158 -#define WM8996_WRITE_SEQUENCER_345 0x3159 -#define WM8996_WRITE_SEQUENCER_346 0x315A -#define WM8996_WRITE_SEQUENCER_347 0x315B -#define WM8996_WRITE_SEQUENCER_348 0x315C -#define WM8996_WRITE_SEQUENCER_349 0x315D -#define WM8996_WRITE_SEQUENCER_350 0x315E -#define WM8996_WRITE_SEQUENCER_351 0x315F -#define WM8996_WRITE_SEQUENCER_352 0x3160 -#define WM8996_WRITE_SEQUENCER_353 0x3161 -#define WM8996_WRITE_SEQUENCER_354 0x3162 -#define WM8996_WRITE_SEQUENCER_355 0x3163 -#define WM8996_WRITE_SEQUENCER_356 0x3164 -#define WM8996_WRITE_SEQUENCER_357 0x3165 -#define WM8996_WRITE_SEQUENCER_358 0x3166 -#define WM8996_WRITE_SEQUENCER_359 0x3167 -#define WM8996_WRITE_SEQUENCER_360 0x3168 -#define WM8996_WRITE_SEQUENCER_361 0x3169 -#define WM8996_WRITE_SEQUENCER_362 0x316A -#define WM8996_WRITE_SEQUENCER_363 0x316B -#define WM8996_WRITE_SEQUENCER_364 0x316C -#define WM8996_WRITE_SEQUENCER_365 0x316D -#define WM8996_WRITE_SEQUENCER_366 0x316E -#define WM8996_WRITE_SEQUENCER_367 0x316F -#define WM8996_WRITE_SEQUENCER_368 0x3170 -#define WM8996_WRITE_SEQUENCER_369 0x3171 -#define WM8996_WRITE_SEQUENCER_370 0x3172 -#define WM8996_WRITE_SEQUENCER_371 0x3173 -#define WM8996_WRITE_SEQUENCER_372 0x3174 -#define WM8996_WRITE_SEQUENCER_373 0x3175 -#define WM8996_WRITE_SEQUENCER_374 0x3176 -#define WM8996_WRITE_SEQUENCER_375 0x3177 -#define WM8996_WRITE_SEQUENCER_376 0x3178 -#define WM8996_WRITE_SEQUENCER_377 0x3179 -#define WM8996_WRITE_SEQUENCER_378 0x317A -#define WM8996_WRITE_SEQUENCER_379 0x317B -#define WM8996_WRITE_SEQUENCER_380 0x317C -#define WM8996_WRITE_SEQUENCER_381 0x317D -#define WM8996_WRITE_SEQUENCER_382 0x317E -#define WM8996_WRITE_SEQUENCER_383 0x317F -#define WM8996_WRITE_SEQUENCER_384 0x3180 -#define WM8996_WRITE_SEQUENCER_385 0x3181 -#define WM8996_WRITE_SEQUENCER_386 0x3182 -#define WM8996_WRITE_SEQUENCER_387 0x3183 -#define WM8996_WRITE_SEQUENCER_388 0x3184 -#define WM8996_WRITE_SEQUENCER_389 0x3185 -#define WM8996_WRITE_SEQUENCER_390 0x3186 -#define WM8996_WRITE_SEQUENCER_391 0x3187 -#define WM8996_WRITE_SEQUENCER_392 0x3188 -#define WM8996_WRITE_SEQUENCER_393 0x3189 -#define WM8996_WRITE_SEQUENCER_394 0x318A -#define WM8996_WRITE_SEQUENCER_395 0x318B -#define WM8996_WRITE_SEQUENCER_396 0x318C -#define WM8996_WRITE_SEQUENCER_397 0x318D -#define WM8996_WRITE_SEQUENCER_398 0x318E -#define WM8996_WRITE_SEQUENCER_399 0x318F -#define WM8996_WRITE_SEQUENCER_400 0x3190 -#define WM8996_WRITE_SEQUENCER_401 0x3191 -#define WM8996_WRITE_SEQUENCER_402 0x3192 -#define WM8996_WRITE_SEQUENCER_403 0x3193 -#define WM8996_WRITE_SEQUENCER_404 0x3194 -#define WM8996_WRITE_SEQUENCER_405 0x3195 -#define WM8996_WRITE_SEQUENCER_406 0x3196 -#define WM8996_WRITE_SEQUENCER_407 0x3197 -#define WM8996_WRITE_SEQUENCER_408 0x3198 -#define WM8996_WRITE_SEQUENCER_409 0x3199 -#define WM8996_WRITE_SEQUENCER_410 0x319A -#define WM8996_WRITE_SEQUENCER_411 0x319B -#define WM8996_WRITE_SEQUENCER_412 0x319C -#define WM8996_WRITE_SEQUENCER_413 0x319D -#define WM8996_WRITE_SEQUENCER_414 0x319E -#define WM8996_WRITE_SEQUENCER_415 0x319F -#define WM8996_WRITE_SEQUENCER_416 0x31A0 -#define WM8996_WRITE_SEQUENCER_417 0x31A1 -#define WM8996_WRITE_SEQUENCER_418 0x31A2 -#define WM8996_WRITE_SEQUENCER_419 0x31A3 -#define WM8996_WRITE_SEQUENCER_420 0x31A4 -#define WM8996_WRITE_SEQUENCER_421 0x31A5 -#define WM8996_WRITE_SEQUENCER_422 0x31A6 -#define WM8996_WRITE_SEQUENCER_423 0x31A7 -#define WM8996_WRITE_SEQUENCER_424 0x31A8 -#define WM8996_WRITE_SEQUENCER_425 0x31A9 -#define WM8996_WRITE_SEQUENCER_426 0x31AA -#define WM8996_WRITE_SEQUENCER_427 0x31AB -#define WM8996_WRITE_SEQUENCER_428 0x31AC -#define WM8996_WRITE_SEQUENCER_429 0x31AD -#define WM8996_WRITE_SEQUENCER_430 0x31AE -#define WM8996_WRITE_SEQUENCER_431 0x31AF -#define WM8996_WRITE_SEQUENCER_432 0x31B0 -#define WM8996_WRITE_SEQUENCER_433 0x31B1 -#define WM8996_WRITE_SEQUENCER_434 0x31B2 -#define WM8996_WRITE_SEQUENCER_435 0x31B3 -#define WM8996_WRITE_SEQUENCER_436 0x31B4 -#define WM8996_WRITE_SEQUENCER_437 0x31B5 -#define WM8996_WRITE_SEQUENCER_438 0x31B6 -#define WM8996_WRITE_SEQUENCER_439 0x31B7 -#define WM8996_WRITE_SEQUENCER_440 0x31B8 -#define WM8996_WRITE_SEQUENCER_441 0x31B9 -#define WM8996_WRITE_SEQUENCER_442 0x31BA -#define WM8996_WRITE_SEQUENCER_443 0x31BB -#define WM8996_WRITE_SEQUENCER_444 0x31BC -#define WM8996_WRITE_SEQUENCER_445 0x31BD -#define WM8996_WRITE_SEQUENCER_446 0x31BE -#define WM8996_WRITE_SEQUENCER_447 0x31BF -#define WM8996_WRITE_SEQUENCER_448 0x31C0 -#define WM8996_WRITE_SEQUENCER_449 0x31C1 -#define WM8996_WRITE_SEQUENCER_450 0x31C2 -#define WM8996_WRITE_SEQUENCER_451 0x31C3 -#define WM8996_WRITE_SEQUENCER_452 0x31C4 -#define WM8996_WRITE_SEQUENCER_453 0x31C5 -#define WM8996_WRITE_SEQUENCER_454 0x31C6 -#define WM8996_WRITE_SEQUENCER_455 0x31C7 -#define WM8996_WRITE_SEQUENCER_456 0x31C8 -#define WM8996_WRITE_SEQUENCER_457 0x31C9 -#define WM8996_WRITE_SEQUENCER_458 0x31CA -#define WM8996_WRITE_SEQUENCER_459 0x31CB -#define WM8996_WRITE_SEQUENCER_460 0x31CC -#define WM8996_WRITE_SEQUENCER_461 0x31CD -#define WM8996_WRITE_SEQUENCER_462 0x31CE -#define WM8996_WRITE_SEQUENCER_463 0x31CF -#define WM8996_WRITE_SEQUENCER_464 0x31D0 -#define WM8996_WRITE_SEQUENCER_465 0x31D1 -#define WM8996_WRITE_SEQUENCER_466 0x31D2 -#define WM8996_WRITE_SEQUENCER_467 0x31D3 -#define WM8996_WRITE_SEQUENCER_468 0x31D4 -#define WM8996_WRITE_SEQUENCER_469 0x31D5 -#define WM8996_WRITE_SEQUENCER_470 0x31D6 -#define WM8996_WRITE_SEQUENCER_471 0x31D7 -#define WM8996_WRITE_SEQUENCER_472 0x31D8 -#define WM8996_WRITE_SEQUENCER_473 0x31D9 -#define WM8996_WRITE_SEQUENCER_474 0x31DA -#define WM8996_WRITE_SEQUENCER_475 0x31DB -#define WM8996_WRITE_SEQUENCER_476 0x31DC -#define WM8996_WRITE_SEQUENCER_477 0x31DD -#define WM8996_WRITE_SEQUENCER_478 0x31DE -#define WM8996_WRITE_SEQUENCER_479 0x31DF -#define WM8996_WRITE_SEQUENCER_480 0x31E0 -#define WM8996_WRITE_SEQUENCER_481 0x31E1 -#define WM8996_WRITE_SEQUENCER_482 0x31E2 -#define WM8996_WRITE_SEQUENCER_483 0x31E3 -#define WM8996_WRITE_SEQUENCER_484 0x31E4 -#define WM8996_WRITE_SEQUENCER_485 0x31E5 -#define WM8996_WRITE_SEQUENCER_486 0x31E6 -#define WM8996_WRITE_SEQUENCER_487 0x31E7 -#define WM8996_WRITE_SEQUENCER_488 0x31E8 -#define WM8996_WRITE_SEQUENCER_489 0x31E9 -#define WM8996_WRITE_SEQUENCER_490 0x31EA -#define WM8996_WRITE_SEQUENCER_491 0x31EB -#define WM8996_WRITE_SEQUENCER_492 0x31EC -#define WM8996_WRITE_SEQUENCER_493 0x31ED -#define WM8996_WRITE_SEQUENCER_494 0x31EE -#define WM8996_WRITE_SEQUENCER_495 0x31EF -#define WM8996_WRITE_SEQUENCER_496 0x31F0 -#define WM8996_WRITE_SEQUENCER_497 0x31F1 -#define WM8996_WRITE_SEQUENCER_498 0x31F2 -#define WM8996_WRITE_SEQUENCER_499 0x31F3 -#define WM8996_WRITE_SEQUENCER_500 0x31F4 -#define WM8996_WRITE_SEQUENCER_501 0x31F5 -#define WM8996_WRITE_SEQUENCER_502 0x31F6 -#define WM8996_WRITE_SEQUENCER_503 0x31F7 -#define WM8996_WRITE_SEQUENCER_504 0x31F8 -#define WM8996_WRITE_SEQUENCER_505 0x31F9 -#define WM8996_WRITE_SEQUENCER_506 0x31FA -#define WM8996_WRITE_SEQUENCER_507 0x31FB -#define WM8996_WRITE_SEQUENCER_508 0x31FC -#define WM8996_WRITE_SEQUENCER_509 0x31FD -#define WM8996_WRITE_SEQUENCER_510 0x31FE -#define WM8996_WRITE_SEQUENCER_511 0x31FF - -#define WM8996_REGISTER_COUNT 706 -#define WM8996_MAX_REGISTER 0x31FF - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM8996_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ -#define WM8996_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ -#define WM8996_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ - -/* - * R1 (0x01) - Power Management (1) - */ -#define WM8996_MICB2_ENA 0x0200 /* MICB2_ENA */ -#define WM8996_MICB2_ENA_MASK 0x0200 /* MICB2_ENA */ -#define WM8996_MICB2_ENA_SHIFT 9 /* MICB2_ENA */ -#define WM8996_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ -#define WM8996_MICB1_ENA 0x0100 /* MICB1_ENA */ -#define WM8996_MICB1_ENA_MASK 0x0100 /* MICB1_ENA */ -#define WM8996_MICB1_ENA_SHIFT 8 /* MICB1_ENA */ -#define WM8996_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ -#define WM8996_HPOUT2L_ENA 0x0080 /* HPOUT2L_ENA */ -#define WM8996_HPOUT2L_ENA_MASK 0x0080 /* HPOUT2L_ENA */ -#define WM8996_HPOUT2L_ENA_SHIFT 7 /* HPOUT2L_ENA */ -#define WM8996_HPOUT2L_ENA_WIDTH 1 /* HPOUT2L_ENA */ -#define WM8996_HPOUT2R_ENA 0x0040 /* HPOUT2R_ENA */ -#define WM8996_HPOUT2R_ENA_MASK 0x0040 /* HPOUT2R_ENA */ -#define WM8996_HPOUT2R_ENA_SHIFT 6 /* HPOUT2R_ENA */ -#define WM8996_HPOUT2R_ENA_WIDTH 1 /* HPOUT2R_ENA */ -#define WM8996_HPOUT1L_ENA 0x0020 /* HPOUT1L_ENA */ -#define WM8996_HPOUT1L_ENA_MASK 0x0020 /* HPOUT1L_ENA */ -#define WM8996_HPOUT1L_ENA_SHIFT 5 /* HPOUT1L_ENA */ -#define WM8996_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */ -#define WM8996_HPOUT1R_ENA 0x0010 /* HPOUT1R_ENA */ -#define WM8996_HPOUT1R_ENA_MASK 0x0010 /* HPOUT1R_ENA */ -#define WM8996_HPOUT1R_ENA_SHIFT 4 /* HPOUT1R_ENA */ -#define WM8996_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */ -#define WM8996_BG_ENA 0x0001 /* BG_ENA */ -#define WM8996_BG_ENA_MASK 0x0001 /* BG_ENA */ -#define WM8996_BG_ENA_SHIFT 0 /* BG_ENA */ -#define WM8996_BG_ENA_WIDTH 1 /* BG_ENA */ - -/* - * R2 (0x02) - Power Management (2) - */ -#define WM8996_OPCLK_ENA 0x0800 /* OPCLK_ENA */ -#define WM8996_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */ -#define WM8996_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */ -#define WM8996_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ -#define WM8996_INL_ENA 0x0020 /* INL_ENA */ -#define WM8996_INL_ENA_MASK 0x0020 /* INL_ENA */ -#define WM8996_INL_ENA_SHIFT 5 /* INL_ENA */ -#define WM8996_INL_ENA_WIDTH 1 /* INL_ENA */ -#define WM8996_INR_ENA 0x0010 /* INR_ENA */ -#define WM8996_INR_ENA_MASK 0x0010 /* INR_ENA */ -#define WM8996_INR_ENA_SHIFT 4 /* INR_ENA */ -#define WM8996_INR_ENA_WIDTH 1 /* INR_ENA */ -#define WM8996_LDO2_ENA 0x0002 /* LDO2_ENA */ -#define WM8996_LDO2_ENA_MASK 0x0002 /* LDO2_ENA */ -#define WM8996_LDO2_ENA_SHIFT 1 /* LDO2_ENA */ -#define WM8996_LDO2_ENA_WIDTH 1 /* LDO2_ENA */ - -/* - * R3 (0x03) - Power Management (3) - */ -#define WM8996_DSP2RXL_ENA 0x0800 /* DSP2RXL_ENA */ -#define WM8996_DSP2RXL_ENA_MASK 0x0800 /* DSP2RXL_ENA */ -#define WM8996_DSP2RXL_ENA_SHIFT 11 /* DSP2RXL_ENA */ -#define WM8996_DSP2RXL_ENA_WIDTH 1 /* DSP2RXL_ENA */ -#define WM8996_DSP2RXR_ENA 0x0400 /* DSP2RXR_ENA */ -#define WM8996_DSP2RXR_ENA_MASK 0x0400 /* DSP2RXR_ENA */ -#define WM8996_DSP2RXR_ENA_SHIFT 10 /* DSP2RXR_ENA */ -#define WM8996_DSP2RXR_ENA_WIDTH 1 /* DSP2RXR_ENA */ -#define WM8996_DSP1RXL_ENA 0x0200 /* DSP1RXL_ENA */ -#define WM8996_DSP1RXL_ENA_MASK 0x0200 /* DSP1RXL_ENA */ -#define WM8996_DSP1RXL_ENA_SHIFT 9 /* DSP1RXL_ENA */ -#define WM8996_DSP1RXL_ENA_WIDTH 1 /* DSP1RXL_ENA */ -#define WM8996_DSP1RXR_ENA 0x0100 /* DSP1RXR_ENA */ -#define WM8996_DSP1RXR_ENA_MASK 0x0100 /* DSP1RXR_ENA */ -#define WM8996_DSP1RXR_ENA_SHIFT 8 /* DSP1RXR_ENA */ -#define WM8996_DSP1RXR_ENA_WIDTH 1 /* DSP1RXR_ENA */ -#define WM8996_DMIC2L_ENA 0x0020 /* DMIC2L_ENA */ -#define WM8996_DMIC2L_ENA_MASK 0x0020 /* DMIC2L_ENA */ -#define WM8996_DMIC2L_ENA_SHIFT 5 /* DMIC2L_ENA */ -#define WM8996_DMIC2L_ENA_WIDTH 1 /* DMIC2L_ENA */ -#define WM8996_DMIC2R_ENA 0x0010 /* DMIC2R_ENA */ -#define WM8996_DMIC2R_ENA_MASK 0x0010 /* DMIC2R_ENA */ -#define WM8996_DMIC2R_ENA_SHIFT 4 /* DMIC2R_ENA */ -#define WM8996_DMIC2R_ENA_WIDTH 1 /* DMIC2R_ENA */ -#define WM8996_DMIC1L_ENA 0x0008 /* DMIC1L_ENA */ -#define WM8996_DMIC1L_ENA_MASK 0x0008 /* DMIC1L_ENA */ -#define WM8996_DMIC1L_ENA_SHIFT 3 /* DMIC1L_ENA */ -#define WM8996_DMIC1L_ENA_WIDTH 1 /* DMIC1L_ENA */ -#define WM8996_DMIC1R_ENA 0x0004 /* DMIC1R_ENA */ -#define WM8996_DMIC1R_ENA_MASK 0x0004 /* DMIC1R_ENA */ -#define WM8996_DMIC1R_ENA_SHIFT 2 /* DMIC1R_ENA */ -#define WM8996_DMIC1R_ENA_WIDTH 1 /* DMIC1R_ENA */ -#define WM8996_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8996_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ -#define WM8996_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ -#define WM8996_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ -#define WM8996_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8996_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ -#define WM8996_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ -#define WM8996_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ - -/* - * R4 (0x04) - Power Management (4) - */ -#define WM8996_AIF2RX_CHAN1_ENA 0x0200 /* AIF2RX_CHAN1_ENA */ -#define WM8996_AIF2RX_CHAN1_ENA_MASK 0x0200 /* AIF2RX_CHAN1_ENA */ -#define WM8996_AIF2RX_CHAN1_ENA_SHIFT 9 /* AIF2RX_CHAN1_ENA */ -#define WM8996_AIF2RX_CHAN1_ENA_WIDTH 1 /* AIF2RX_CHAN1_ENA */ -#define WM8996_AIF2RX_CHAN0_ENA 0x0100 /* AIF2RX_CHAN0_ENA */ -#define WM8996_AIF2RX_CHAN0_ENA_MASK 0x0100 /* AIF2RX_CHAN0_ENA */ -#define WM8996_AIF2RX_CHAN0_ENA_SHIFT 8 /* AIF2RX_CHAN0_ENA */ -#define WM8996_AIF2RX_CHAN0_ENA_WIDTH 1 /* AIF2RX_CHAN0_ENA */ -#define WM8996_AIF1RX_CHAN5_ENA 0x0020 /* AIF1RX_CHAN5_ENA */ -#define WM8996_AIF1RX_CHAN5_ENA_MASK 0x0020 /* AIF1RX_CHAN5_ENA */ -#define WM8996_AIF1RX_CHAN5_ENA_SHIFT 5 /* AIF1RX_CHAN5_ENA */ -#define WM8996_AIF1RX_CHAN5_ENA_WIDTH 1 /* AIF1RX_CHAN5_ENA */ -#define WM8996_AIF1RX_CHAN4_ENA 0x0010 /* AIF1RX_CHAN4_ENA */ -#define WM8996_AIF1RX_CHAN4_ENA_MASK 0x0010 /* AIF1RX_CHAN4_ENA */ -#define WM8996_AIF1RX_CHAN4_ENA_SHIFT 4 /* AIF1RX_CHAN4_ENA */ -#define WM8996_AIF1RX_CHAN4_ENA_WIDTH 1 /* AIF1RX_CHAN4_ENA */ -#define WM8996_AIF1RX_CHAN3_ENA 0x0008 /* AIF1RX_CHAN3_ENA */ -#define WM8996_AIF1RX_CHAN3_ENA_MASK 0x0008 /* AIF1RX_CHAN3_ENA */ -#define WM8996_AIF1RX_CHAN3_ENA_SHIFT 3 /* AIF1RX_CHAN3_ENA */ -#define WM8996_AIF1RX_CHAN3_ENA_WIDTH 1 /* AIF1RX_CHAN3_ENA */ -#define WM8996_AIF1RX_CHAN2_ENA 0x0004 /* AIF1RX_CHAN2_ENA */ -#define WM8996_AIF1RX_CHAN2_ENA_MASK 0x0004 /* AIF1RX_CHAN2_ENA */ -#define WM8996_AIF1RX_CHAN2_ENA_SHIFT 2 /* AIF1RX_CHAN2_ENA */ -#define WM8996_AIF1RX_CHAN2_ENA_WIDTH 1 /* AIF1RX_CHAN2_ENA */ -#define WM8996_AIF1RX_CHAN1_ENA 0x0002 /* AIF1RX_CHAN1_ENA */ -#define WM8996_AIF1RX_CHAN1_ENA_MASK 0x0002 /* AIF1RX_CHAN1_ENA */ -#define WM8996_AIF1RX_CHAN1_ENA_SHIFT 1 /* AIF1RX_CHAN1_ENA */ -#define WM8996_AIF1RX_CHAN1_ENA_WIDTH 1 /* AIF1RX_CHAN1_ENA */ -#define WM8996_AIF1RX_CHAN0_ENA 0x0001 /* AIF1RX_CHAN0_ENA */ -#define WM8996_AIF1RX_CHAN0_ENA_MASK 0x0001 /* AIF1RX_CHAN0_ENA */ -#define WM8996_AIF1RX_CHAN0_ENA_SHIFT 0 /* AIF1RX_CHAN0_ENA */ -#define WM8996_AIF1RX_CHAN0_ENA_WIDTH 1 /* AIF1RX_CHAN0_ENA */ - -/* - * R5 (0x05) - Power Management (5) - */ -#define WM8996_DSP2TXL_ENA 0x0800 /* DSP2TXL_ENA */ -#define WM8996_DSP2TXL_ENA_MASK 0x0800 /* DSP2TXL_ENA */ -#define WM8996_DSP2TXL_ENA_SHIFT 11 /* DSP2TXL_ENA */ -#define WM8996_DSP2TXL_ENA_WIDTH 1 /* DSP2TXL_ENA */ -#define WM8996_DSP2TXR_ENA 0x0400 /* DSP2TXR_ENA */ -#define WM8996_DSP2TXR_ENA_MASK 0x0400 /* DSP2TXR_ENA */ -#define WM8996_DSP2TXR_ENA_SHIFT 10 /* DSP2TXR_ENA */ -#define WM8996_DSP2TXR_ENA_WIDTH 1 /* DSP2TXR_ENA */ -#define WM8996_DSP1TXL_ENA 0x0200 /* DSP1TXL_ENA */ -#define WM8996_DSP1TXL_ENA_MASK 0x0200 /* DSP1TXL_ENA */ -#define WM8996_DSP1TXL_ENA_SHIFT 9 /* DSP1TXL_ENA */ -#define WM8996_DSP1TXL_ENA_WIDTH 1 /* DSP1TXL_ENA */ -#define WM8996_DSP1TXR_ENA 0x0100 /* DSP1TXR_ENA */ -#define WM8996_DSP1TXR_ENA_MASK 0x0100 /* DSP1TXR_ENA */ -#define WM8996_DSP1TXR_ENA_SHIFT 8 /* DSP1TXR_ENA */ -#define WM8996_DSP1TXR_ENA_WIDTH 1 /* DSP1TXR_ENA */ -#define WM8996_DAC2L_ENA 0x0008 /* DAC2L_ENA */ -#define WM8996_DAC2L_ENA_MASK 0x0008 /* DAC2L_ENA */ -#define WM8996_DAC2L_ENA_SHIFT 3 /* DAC2L_ENA */ -#define WM8996_DAC2L_ENA_WIDTH 1 /* DAC2L_ENA */ -#define WM8996_DAC2R_ENA 0x0004 /* DAC2R_ENA */ -#define WM8996_DAC2R_ENA_MASK 0x0004 /* DAC2R_ENA */ -#define WM8996_DAC2R_ENA_SHIFT 2 /* DAC2R_ENA */ -#define WM8996_DAC2R_ENA_WIDTH 1 /* DAC2R_ENA */ -#define WM8996_DAC1L_ENA 0x0002 /* DAC1L_ENA */ -#define WM8996_DAC1L_ENA_MASK 0x0002 /* DAC1L_ENA */ -#define WM8996_DAC1L_ENA_SHIFT 1 /* DAC1L_ENA */ -#define WM8996_DAC1L_ENA_WIDTH 1 /* DAC1L_ENA */ -#define WM8996_DAC1R_ENA 0x0001 /* DAC1R_ENA */ -#define WM8996_DAC1R_ENA_MASK 0x0001 /* DAC1R_ENA */ -#define WM8996_DAC1R_ENA_SHIFT 0 /* DAC1R_ENA */ -#define WM8996_DAC1R_ENA_WIDTH 1 /* DAC1R_ENA */ - -/* - * R6 (0x06) - Power Management (6) - */ -#define WM8996_AIF2TX_CHAN1_ENA 0x0200 /* AIF2TX_CHAN1_ENA */ -#define WM8996_AIF2TX_CHAN1_ENA_MASK 0x0200 /* AIF2TX_CHAN1_ENA */ -#define WM8996_AIF2TX_CHAN1_ENA_SHIFT 9 /* AIF2TX_CHAN1_ENA */ -#define WM8996_AIF2TX_CHAN1_ENA_WIDTH 1 /* AIF2TX_CHAN1_ENA */ -#define WM8996_AIF2TX_CHAN0_ENA 0x0100 /* AIF2TX_CHAN0_ENA */ -#define WM8996_AIF2TX_CHAN0_ENA_MASK 0x0100 /* AIF2TX_CHAN0_ENA */ -#define WM8996_AIF2TX_CHAN0_ENA_SHIFT 8 /* AIF2TX_CHAN0_ENA */ -#define WM8996_AIF2TX_CHAN0_ENA_WIDTH 1 /* AIF2TX_CHAN0_ENA */ -#define WM8996_AIF1TX_CHAN5_ENA 0x0020 /* AIF1TX_CHAN5_ENA */ -#define WM8996_AIF1TX_CHAN5_ENA_MASK 0x0020 /* AIF1TX_CHAN5_ENA */ -#define WM8996_AIF1TX_CHAN5_ENA_SHIFT 5 /* AIF1TX_CHAN5_ENA */ -#define WM8996_AIF1TX_CHAN5_ENA_WIDTH 1 /* AIF1TX_CHAN5_ENA */ -#define WM8996_AIF1TX_CHAN4_ENA 0x0010 /* AIF1TX_CHAN4_ENA */ -#define WM8996_AIF1TX_CHAN4_ENA_MASK 0x0010 /* AIF1TX_CHAN4_ENA */ -#define WM8996_AIF1TX_CHAN4_ENA_SHIFT 4 /* AIF1TX_CHAN4_ENA */ -#define WM8996_AIF1TX_CHAN4_ENA_WIDTH 1 /* AIF1TX_CHAN4_ENA */ -#define WM8996_AIF1TX_CHAN3_ENA 0x0008 /* AIF1TX_CHAN3_ENA */ -#define WM8996_AIF1TX_CHAN3_ENA_MASK 0x0008 /* AIF1TX_CHAN3_ENA */ -#define WM8996_AIF1TX_CHAN3_ENA_SHIFT 3 /* AIF1TX_CHAN3_ENA */ -#define WM8996_AIF1TX_CHAN3_ENA_WIDTH 1 /* AIF1TX_CHAN3_ENA */ -#define WM8996_AIF1TX_CHAN2_ENA 0x0004 /* AIF1TX_CHAN2_ENA */ -#define WM8996_AIF1TX_CHAN2_ENA_MASK 0x0004 /* AIF1TX_CHAN2_ENA */ -#define WM8996_AIF1TX_CHAN2_ENA_SHIFT 2 /* AIF1TX_CHAN2_ENA */ -#define WM8996_AIF1TX_CHAN2_ENA_WIDTH 1 /* AIF1TX_CHAN2_ENA */ -#define WM8996_AIF1TX_CHAN1_ENA 0x0002 /* AIF1TX_CHAN1_ENA */ -#define WM8996_AIF1TX_CHAN1_ENA_MASK 0x0002 /* AIF1TX_CHAN1_ENA */ -#define WM8996_AIF1TX_CHAN1_ENA_SHIFT 1 /* AIF1TX_CHAN1_ENA */ -#define WM8996_AIF1TX_CHAN1_ENA_WIDTH 1 /* AIF1TX_CHAN1_ENA */ -#define WM8996_AIF1TX_CHAN0_ENA 0x0001 /* AIF1TX_CHAN0_ENA */ -#define WM8996_AIF1TX_CHAN0_ENA_MASK 0x0001 /* AIF1TX_CHAN0_ENA */ -#define WM8996_AIF1TX_CHAN0_ENA_SHIFT 0 /* AIF1TX_CHAN0_ENA */ -#define WM8996_AIF1TX_CHAN0_ENA_WIDTH 1 /* AIF1TX_CHAN0_ENA */ - -/* - * R7 (0x07) - Power Management (7) - */ -#define WM8996_DMIC2_FN 0x0200 /* DMIC2_FN */ -#define WM8996_DMIC2_FN_MASK 0x0200 /* DMIC2_FN */ -#define WM8996_DMIC2_FN_SHIFT 9 /* DMIC2_FN */ -#define WM8996_DMIC2_FN_WIDTH 1 /* DMIC2_FN */ -#define WM8996_DMIC1_FN 0x0100 /* DMIC1_FN */ -#define WM8996_DMIC1_FN_MASK 0x0100 /* DMIC1_FN */ -#define WM8996_DMIC1_FN_SHIFT 8 /* DMIC1_FN */ -#define WM8996_DMIC1_FN_WIDTH 1 /* DMIC1_FN */ -#define WM8996_ADC_DMIC_DSP2R_ENA 0x0080 /* ADC_DMIC_DSP2R_ENA */ -#define WM8996_ADC_DMIC_DSP2R_ENA_MASK 0x0080 /* ADC_DMIC_DSP2R_ENA */ -#define WM8996_ADC_DMIC_DSP2R_ENA_SHIFT 7 /* ADC_DMIC_DSP2R_ENA */ -#define WM8996_ADC_DMIC_DSP2R_ENA_WIDTH 1 /* ADC_DMIC_DSP2R_ENA */ -#define WM8996_ADC_DMIC_DSP2L_ENA 0x0040 /* ADC_DMIC_DSP2L_ENA */ -#define WM8996_ADC_DMIC_DSP2L_ENA_MASK 0x0040 /* ADC_DMIC_DSP2L_ENA */ -#define WM8996_ADC_DMIC_DSP2L_ENA_SHIFT 6 /* ADC_DMIC_DSP2L_ENA */ -#define WM8996_ADC_DMIC_DSP2L_ENA_WIDTH 1 /* ADC_DMIC_DSP2L_ENA */ -#define WM8996_ADC_DMIC_SRC2_MASK 0x0030 /* ADC_DMIC_SRC2 - [5:4] */ -#define WM8996_ADC_DMIC_SRC2_SHIFT 4 /* ADC_DMIC_SRC2 - [5:4] */ -#define WM8996_ADC_DMIC_SRC2_WIDTH 2 /* ADC_DMIC_SRC2 - [5:4] */ -#define WM8996_ADC_DMIC_DSP1R_ENA 0x0008 /* ADC_DMIC_DSP1R_ENA */ -#define WM8996_ADC_DMIC_DSP1R_ENA_MASK 0x0008 /* ADC_DMIC_DSP1R_ENA */ -#define WM8996_ADC_DMIC_DSP1R_ENA_SHIFT 3 /* ADC_DMIC_DSP1R_ENA */ -#define WM8996_ADC_DMIC_DSP1R_ENA_WIDTH 1 /* ADC_DMIC_DSP1R_ENA */ -#define WM8996_ADC_DMIC_DSP1L_ENA 0x0004 /* ADC_DMIC_DSP1L_ENA */ -#define WM8996_ADC_DMIC_DSP1L_ENA_MASK 0x0004 /* ADC_DMIC_DSP1L_ENA */ -#define WM8996_ADC_DMIC_DSP1L_ENA_SHIFT 2 /* ADC_DMIC_DSP1L_ENA */ -#define WM8996_ADC_DMIC_DSP1L_ENA_WIDTH 1 /* ADC_DMIC_DSP1L_ENA */ -#define WM8996_ADC_DMIC_SRC1_MASK 0x0003 /* ADC_DMIC_SRC1 - [1:0] */ -#define WM8996_ADC_DMIC_SRC1_SHIFT 0 /* ADC_DMIC_SRC1 - [1:0] */ -#define WM8996_ADC_DMIC_SRC1_WIDTH 2 /* ADC_DMIC_SRC1 - [1:0] */ - -/* - * R8 (0x08) - Power Management (8) - */ -#define WM8996_AIF2TX_SRC_MASK 0x00C0 /* AIF2TX_SRC - [7:6] */ -#define WM8996_AIF2TX_SRC_SHIFT 6 /* AIF2TX_SRC - [7:6] */ -#define WM8996_AIF2TX_SRC_WIDTH 2 /* AIF2TX_SRC - [7:6] */ -#define WM8996_DSP2RX_SRC 0x0010 /* DSP2RX_SRC */ -#define WM8996_DSP2RX_SRC_MASK 0x0010 /* DSP2RX_SRC */ -#define WM8996_DSP2RX_SRC_SHIFT 4 /* DSP2RX_SRC */ -#define WM8996_DSP2RX_SRC_WIDTH 1 /* DSP2RX_SRC */ -#define WM8996_DSP1RX_SRC 0x0001 /* DSP1RX_SRC */ -#define WM8996_DSP1RX_SRC_MASK 0x0001 /* DSP1RX_SRC */ -#define WM8996_DSP1RX_SRC_SHIFT 0 /* DSP1RX_SRC */ -#define WM8996_DSP1RX_SRC_WIDTH 1 /* DSP1RX_SRC */ - -/* - * R16 (0x10) - Left Line Input Volume - */ -#define WM8996_IN1_VU 0x0080 /* IN1_VU */ -#define WM8996_IN1_VU_MASK 0x0080 /* IN1_VU */ -#define WM8996_IN1_VU_SHIFT 7 /* IN1_VU */ -#define WM8996_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8996_IN1L_ZC 0x0020 /* IN1L_ZC */ -#define WM8996_IN1L_ZC_MASK 0x0020 /* IN1L_ZC */ -#define WM8996_IN1L_ZC_SHIFT 5 /* IN1L_ZC */ -#define WM8996_IN1L_ZC_WIDTH 1 /* IN1L_ZC */ -#define WM8996_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */ -#define WM8996_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */ -#define WM8996_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */ - -/* - * R17 (0x11) - Right Line Input Volume - */ -#define WM8996_IN1_VU 0x0080 /* IN1_VU */ -#define WM8996_IN1_VU_MASK 0x0080 /* IN1_VU */ -#define WM8996_IN1_VU_SHIFT 7 /* IN1_VU */ -#define WM8996_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8996_IN1R_ZC 0x0020 /* IN1R_ZC */ -#define WM8996_IN1R_ZC_MASK 0x0020 /* IN1R_ZC */ -#define WM8996_IN1R_ZC_SHIFT 5 /* IN1R_ZC */ -#define WM8996_IN1R_ZC_WIDTH 1 /* IN1R_ZC */ -#define WM8996_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */ -#define WM8996_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */ -#define WM8996_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */ - -/* - * R18 (0x12) - Line Input Control - */ -#define WM8996_INL_MODE_MASK 0x000C /* INL_MODE - [3:2] */ -#define WM8996_INL_MODE_SHIFT 2 /* INL_MODE - [3:2] */ -#define WM8996_INL_MODE_WIDTH 2 /* INL_MODE - [3:2] */ -#define WM8996_INR_MODE_MASK 0x0003 /* INR_MODE - [1:0] */ -#define WM8996_INR_MODE_SHIFT 0 /* INR_MODE - [1:0] */ -#define WM8996_INR_MODE_WIDTH 2 /* INR_MODE - [1:0] */ - -/* - * R21 (0x15) - DAC1 HPOUT1 Volume - */ -#define WM8996_DAC1R_HPOUT1R_VOL_MASK 0x00F0 /* DAC1R_HPOUT1R_VOL - [7:4] */ -#define WM8996_DAC1R_HPOUT1R_VOL_SHIFT 4 /* DAC1R_HPOUT1R_VOL - [7:4] */ -#define WM8996_DAC1R_HPOUT1R_VOL_WIDTH 4 /* DAC1R_HPOUT1R_VOL - [7:4] */ -#define WM8996_DAC1L_HPOUT1L_VOL_MASK 0x000F /* DAC1L_HPOUT1L_VOL - [3:0] */ -#define WM8996_DAC1L_HPOUT1L_VOL_SHIFT 0 /* DAC1L_HPOUT1L_VOL - [3:0] */ -#define WM8996_DAC1L_HPOUT1L_VOL_WIDTH 4 /* DAC1L_HPOUT1L_VOL - [3:0] */ - -/* - * R22 (0x16) - DAC2 HPOUT2 Volume - */ -#define WM8996_DAC2R_HPOUT2R_VOL_MASK 0x00F0 /* DAC2R_HPOUT2R_VOL - [7:4] */ -#define WM8996_DAC2R_HPOUT2R_VOL_SHIFT 4 /* DAC2R_HPOUT2R_VOL - [7:4] */ -#define WM8996_DAC2R_HPOUT2R_VOL_WIDTH 4 /* DAC2R_HPOUT2R_VOL - [7:4] */ -#define WM8996_DAC2L_HPOUT2L_VOL_MASK 0x000F /* DAC2L_HPOUT2L_VOL - [3:0] */ -#define WM8996_DAC2L_HPOUT2L_VOL_SHIFT 0 /* DAC2L_HPOUT2L_VOL - [3:0] */ -#define WM8996_DAC2L_HPOUT2L_VOL_WIDTH 4 /* DAC2L_HPOUT2L_VOL - [3:0] */ - -/* - * R24 (0x18) - DAC1 Left Volume - */ -#define WM8996_DAC1L_MUTE 0x0200 /* DAC1L_MUTE */ -#define WM8996_DAC1L_MUTE_MASK 0x0200 /* DAC1L_MUTE */ -#define WM8996_DAC1L_MUTE_SHIFT 9 /* DAC1L_MUTE */ -#define WM8996_DAC1L_MUTE_WIDTH 1 /* DAC1L_MUTE */ -#define WM8996_DAC1_VU 0x0100 /* DAC1_VU */ -#define WM8996_DAC1_VU_MASK 0x0100 /* DAC1_VU */ -#define WM8996_DAC1_VU_SHIFT 8 /* DAC1_VU */ -#define WM8996_DAC1_VU_WIDTH 1 /* DAC1_VU */ -#define WM8996_DAC1L_VOL_MASK 0x00FF /* DAC1L_VOL - [7:0] */ -#define WM8996_DAC1L_VOL_SHIFT 0 /* DAC1L_VOL - [7:0] */ -#define WM8996_DAC1L_VOL_WIDTH 8 /* DAC1L_VOL - [7:0] */ - -/* - * R25 (0x19) - DAC1 Right Volume - */ -#define WM8996_DAC1R_MUTE 0x0200 /* DAC1R_MUTE */ -#define WM8996_DAC1R_MUTE_MASK 0x0200 /* DAC1R_MUTE */ -#define WM8996_DAC1R_MUTE_SHIFT 9 /* DAC1R_MUTE */ -#define WM8996_DAC1R_MUTE_WIDTH 1 /* DAC1R_MUTE */ -#define WM8996_DAC1_VU 0x0100 /* DAC1_VU */ -#define WM8996_DAC1_VU_MASK 0x0100 /* DAC1_VU */ -#define WM8996_DAC1_VU_SHIFT 8 /* DAC1_VU */ -#define WM8996_DAC1_VU_WIDTH 1 /* DAC1_VU */ -#define WM8996_DAC1R_VOL_MASK 0x00FF /* DAC1R_VOL - [7:0] */ -#define WM8996_DAC1R_VOL_SHIFT 0 /* DAC1R_VOL - [7:0] */ -#define WM8996_DAC1R_VOL_WIDTH 8 /* DAC1R_VOL - [7:0] */ - -/* - * R26 (0x1A) - DAC2 Left Volume - */ -#define WM8996_DAC2L_MUTE 0x0200 /* DAC2L_MUTE */ -#define WM8996_DAC2L_MUTE_MASK 0x0200 /* DAC2L_MUTE */ -#define WM8996_DAC2L_MUTE_SHIFT 9 /* DAC2L_MUTE */ -#define WM8996_DAC2L_MUTE_WIDTH 1 /* DAC2L_MUTE */ -#define WM8996_DAC2_VU 0x0100 /* DAC2_VU */ -#define WM8996_DAC2_VU_MASK 0x0100 /* DAC2_VU */ -#define WM8996_DAC2_VU_SHIFT 8 /* DAC2_VU */ -#define WM8996_DAC2_VU_WIDTH 1 /* DAC2_VU */ -#define WM8996_DAC2L_VOL_MASK 0x00FF /* DAC2L_VOL - [7:0] */ -#define WM8996_DAC2L_VOL_SHIFT 0 /* DAC2L_VOL - [7:0] */ -#define WM8996_DAC2L_VOL_WIDTH 8 /* DAC2L_VOL - [7:0] */ - -/* - * R27 (0x1B) - DAC2 Right Volume - */ -#define WM8996_DAC2R_MUTE 0x0200 /* DAC2R_MUTE */ -#define WM8996_DAC2R_MUTE_MASK 0x0200 /* DAC2R_MUTE */ -#define WM8996_DAC2R_MUTE_SHIFT 9 /* DAC2R_MUTE */ -#define WM8996_DAC2R_MUTE_WIDTH 1 /* DAC2R_MUTE */ -#define WM8996_DAC2_VU 0x0100 /* DAC2_VU */ -#define WM8996_DAC2_VU_MASK 0x0100 /* DAC2_VU */ -#define WM8996_DAC2_VU_SHIFT 8 /* DAC2_VU */ -#define WM8996_DAC2_VU_WIDTH 1 /* DAC2_VU */ -#define WM8996_DAC2R_VOL_MASK 0x00FF /* DAC2R_VOL - [7:0] */ -#define WM8996_DAC2R_VOL_SHIFT 0 /* DAC2R_VOL - [7:0] */ -#define WM8996_DAC2R_VOL_WIDTH 8 /* DAC2R_VOL - [7:0] */ - -/* - * R28 (0x1C) - Output1 Left Volume - */ -#define WM8996_DAC1_VU 0x0100 /* DAC1_VU */ -#define WM8996_DAC1_VU_MASK 0x0100 /* DAC1_VU */ -#define WM8996_DAC1_VU_SHIFT 8 /* DAC1_VU */ -#define WM8996_DAC1_VU_WIDTH 1 /* DAC1_VU */ -#define WM8996_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */ -#define WM8996_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */ -#define WM8996_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */ -#define WM8996_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */ -#define WM8996_HPOUT1L_VOL_MASK 0x000F /* HPOUT1L_VOL - [3:0] */ -#define WM8996_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [3:0] */ -#define WM8996_HPOUT1L_VOL_WIDTH 4 /* HPOUT1L_VOL - [3:0] */ - -/* - * R29 (0x1D) - Output1 Right Volume - */ -#define WM8996_DAC1_VU 0x0100 /* DAC1_VU */ -#define WM8996_DAC1_VU_MASK 0x0100 /* DAC1_VU */ -#define WM8996_DAC1_VU_SHIFT 8 /* DAC1_VU */ -#define WM8996_DAC1_VU_WIDTH 1 /* DAC1_VU */ -#define WM8996_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */ -#define WM8996_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */ -#define WM8996_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */ -#define WM8996_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */ -#define WM8996_HPOUT1R_VOL_MASK 0x000F /* HPOUT1R_VOL - [3:0] */ -#define WM8996_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [3:0] */ -#define WM8996_HPOUT1R_VOL_WIDTH 4 /* HPOUT1R_VOL - [3:0] */ - -/* - * R30 (0x1E) - Output2 Left Volume - */ -#define WM8996_DAC2_VU 0x0100 /* DAC2_VU */ -#define WM8996_DAC2_VU_MASK 0x0100 /* DAC2_VU */ -#define WM8996_DAC2_VU_SHIFT 8 /* DAC2_VU */ -#define WM8996_DAC2_VU_WIDTH 1 /* DAC2_VU */ -#define WM8996_HPOUT2L_ZC 0x0080 /* HPOUT2L_ZC */ -#define WM8996_HPOUT2L_ZC_MASK 0x0080 /* HPOUT2L_ZC */ -#define WM8996_HPOUT2L_ZC_SHIFT 7 /* HPOUT2L_ZC */ -#define WM8996_HPOUT2L_ZC_WIDTH 1 /* HPOUT2L_ZC */ -#define WM8996_HPOUT2L_VOL_MASK 0x000F /* HPOUT2L_VOL - [3:0] */ -#define WM8996_HPOUT2L_VOL_SHIFT 0 /* HPOUT2L_VOL - [3:0] */ -#define WM8996_HPOUT2L_VOL_WIDTH 4 /* HPOUT2L_VOL - [3:0] */ - -/* - * R31 (0x1F) - Output2 Right Volume - */ -#define WM8996_DAC2_VU 0x0100 /* DAC2_VU */ -#define WM8996_DAC2_VU_MASK 0x0100 /* DAC2_VU */ -#define WM8996_DAC2_VU_SHIFT 8 /* DAC2_VU */ -#define WM8996_DAC2_VU_WIDTH 1 /* DAC2_VU */ -#define WM8996_HPOUT2R_ZC 0x0080 /* HPOUT2R_ZC */ -#define WM8996_HPOUT2R_ZC_MASK 0x0080 /* HPOUT2R_ZC */ -#define WM8996_HPOUT2R_ZC_SHIFT 7 /* HPOUT2R_ZC */ -#define WM8996_HPOUT2R_ZC_WIDTH 1 /* HPOUT2R_ZC */ -#define WM8996_HPOUT2R_VOL_MASK 0x000F /* HPOUT2R_VOL - [3:0] */ -#define WM8996_HPOUT2R_VOL_SHIFT 0 /* HPOUT2R_VOL - [3:0] */ -#define WM8996_HPOUT2R_VOL_WIDTH 4 /* HPOUT2R_VOL - [3:0] */ - -/* - * R32 (0x20) - MICBIAS (1) - */ -#define WM8996_MICB1_RATE 0x0020 /* MICB1_RATE */ -#define WM8996_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */ -#define WM8996_MICB1_RATE_SHIFT 5 /* MICB1_RATE */ -#define WM8996_MICB1_RATE_WIDTH 1 /* MICB1_RATE */ -#define WM8996_MICB1_MODE 0x0010 /* MICB1_MODE */ -#define WM8996_MICB1_MODE_MASK 0x0010 /* MICB1_MODE */ -#define WM8996_MICB1_MODE_SHIFT 4 /* MICB1_MODE */ -#define WM8996_MICB1_MODE_WIDTH 1 /* MICB1_MODE */ -#define WM8996_MICB1_LVL_MASK 0x000E /* MICB1_LVL - [3:1] */ -#define WM8996_MICB1_LVL_SHIFT 1 /* MICB1_LVL - [3:1] */ -#define WM8996_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [3:1] */ -#define WM8996_MICB1_DISCH 0x0001 /* MICB1_DISCH */ -#define WM8996_MICB1_DISCH_MASK 0x0001 /* MICB1_DISCH */ -#define WM8996_MICB1_DISCH_SHIFT 0 /* MICB1_DISCH */ -#define WM8996_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */ - -/* - * R33 (0x21) - MICBIAS (2) - */ -#define WM8996_MICB2_RATE 0x0020 /* MICB2_RATE */ -#define WM8996_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */ -#define WM8996_MICB2_RATE_SHIFT 5 /* MICB2_RATE */ -#define WM8996_MICB2_RATE_WIDTH 1 /* MICB2_RATE */ -#define WM8996_MICB2_MODE 0x0010 /* MICB2_MODE */ -#define WM8996_MICB2_MODE_MASK 0x0010 /* MICB2_MODE */ -#define WM8996_MICB2_MODE_SHIFT 4 /* MICB2_MODE */ -#define WM8996_MICB2_MODE_WIDTH 1 /* MICB2_MODE */ -#define WM8996_MICB2_LVL_MASK 0x000E /* MICB2_LVL - [3:1] */ -#define WM8996_MICB2_LVL_SHIFT 1 /* MICB2_LVL - [3:1] */ -#define WM8996_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [3:1] */ -#define WM8996_MICB2_DISCH 0x0001 /* MICB2_DISCH */ -#define WM8996_MICB2_DISCH_MASK 0x0001 /* MICB2_DISCH */ -#define WM8996_MICB2_DISCH_SHIFT 0 /* MICB2_DISCH */ -#define WM8996_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ - -/* - * R40 (0x28) - LDO 1 - */ -#define WM8996_LDO1_MODE 0x0020 /* LDO1_MODE */ -#define WM8996_LDO1_MODE_MASK 0x0020 /* LDO1_MODE */ -#define WM8996_LDO1_MODE_SHIFT 5 /* LDO1_MODE */ -#define WM8996_LDO1_MODE_WIDTH 1 /* LDO1_MODE */ -#define WM8996_LDO1_VSEL_MASK 0x0006 /* LDO1_VSEL - [2:1] */ -#define WM8996_LDO1_VSEL_SHIFT 1 /* LDO1_VSEL - [2:1] */ -#define WM8996_LDO1_VSEL_WIDTH 2 /* LDO1_VSEL - [2:1] */ -#define WM8996_LDO1_DISCH 0x0001 /* LDO1_DISCH */ -#define WM8996_LDO1_DISCH_MASK 0x0001 /* LDO1_DISCH */ -#define WM8996_LDO1_DISCH_SHIFT 0 /* LDO1_DISCH */ -#define WM8996_LDO1_DISCH_WIDTH 1 /* LDO1_DISCH */ - -/* - * R41 (0x29) - LDO 2 - */ -#define WM8996_LDO2_MODE 0x0020 /* LDO2_MODE */ -#define WM8996_LDO2_MODE_MASK 0x0020 /* LDO2_MODE */ -#define WM8996_LDO2_MODE_SHIFT 5 /* LDO2_MODE */ -#define WM8996_LDO2_MODE_WIDTH 1 /* LDO2_MODE */ -#define WM8996_LDO2_VSEL_MASK 0x001E /* LDO2_VSEL - [4:1] */ -#define WM8996_LDO2_VSEL_SHIFT 1 /* LDO2_VSEL - [4:1] */ -#define WM8996_LDO2_VSEL_WIDTH 4 /* LDO2_VSEL - [4:1] */ -#define WM8996_LDO2_DISCH 0x0001 /* LDO2_DISCH */ -#define WM8996_LDO2_DISCH_MASK 0x0001 /* LDO2_DISCH */ -#define WM8996_LDO2_DISCH_SHIFT 0 /* LDO2_DISCH */ -#define WM8996_LDO2_DISCH_WIDTH 1 /* LDO2_DISCH */ - -/* - * R48 (0x30) - Accessory Detect Mode 1 - */ -#define WM8996_JD_MODE_MASK 0x0003 /* JD_MODE - [1:0] */ -#define WM8996_JD_MODE_SHIFT 0 /* JD_MODE - [1:0] */ -#define WM8996_JD_MODE_WIDTH 2 /* JD_MODE - [1:0] */ - -/* - * R49 (0x31) - Accessory Detect Mode 2 - */ -#define WM8996_HPOUT1FB_SRC 0x0004 /* HPOUT1FB_SRC */ -#define WM8996_HPOUT1FB_SRC_MASK 0x0004 /* HPOUT1FB_SRC */ -#define WM8996_HPOUT1FB_SRC_SHIFT 2 /* HPOUT1FB_SRC */ -#define WM8996_HPOUT1FB_SRC_WIDTH 1 /* HPOUT1FB_SRC */ -#define WM8996_MICD_SRC 0x0002 /* MICD_SRC */ -#define WM8996_MICD_SRC_MASK 0x0002 /* MICD_SRC */ -#define WM8996_MICD_SRC_SHIFT 1 /* MICD_SRC */ -#define WM8996_MICD_SRC_WIDTH 1 /* MICD_SRC */ -#define WM8996_MICD_BIAS_SRC 0x0001 /* MICD_BIAS_SRC */ -#define WM8996_MICD_BIAS_SRC_MASK 0x0001 /* MICD_BIAS_SRC */ -#define WM8996_MICD_BIAS_SRC_SHIFT 0 /* MICD_BIAS_SRC */ -#define WM8996_MICD_BIAS_SRC_WIDTH 1 /* MICD_BIAS_SRC */ - -/* - * R52 (0x34) - Headphone Detect 1 - */ -#define WM8996_HP_HOLDTIME_MASK 0x00E0 /* HP_HOLDTIME - [7:5] */ -#define WM8996_HP_HOLDTIME_SHIFT 5 /* HP_HOLDTIME - [7:5] */ -#define WM8996_HP_HOLDTIME_WIDTH 3 /* HP_HOLDTIME - [7:5] */ -#define WM8996_HP_CLK_DIV_MASK 0x0018 /* HP_CLK_DIV - [4:3] */ -#define WM8996_HP_CLK_DIV_SHIFT 3 /* HP_CLK_DIV - [4:3] */ -#define WM8996_HP_CLK_DIV_WIDTH 2 /* HP_CLK_DIV - [4:3] */ -#define WM8996_HP_STEP_SIZE 0x0002 /* HP_STEP_SIZE */ -#define WM8996_HP_STEP_SIZE_MASK 0x0002 /* HP_STEP_SIZE */ -#define WM8996_HP_STEP_SIZE_SHIFT 1 /* HP_STEP_SIZE */ -#define WM8996_HP_STEP_SIZE_WIDTH 1 /* HP_STEP_SIZE */ -#define WM8996_HP_POLL 0x0001 /* HP_POLL */ -#define WM8996_HP_POLL_MASK 0x0001 /* HP_POLL */ -#define WM8996_HP_POLL_SHIFT 0 /* HP_POLL */ -#define WM8996_HP_POLL_WIDTH 1 /* HP_POLL */ - -/* - * R53 (0x35) - Headphone Detect 2 - */ -#define WM8996_HP_DONE 0x0080 /* HP_DONE */ -#define WM8996_HP_DONE_MASK 0x0080 /* HP_DONE */ -#define WM8996_HP_DONE_SHIFT 7 /* HP_DONE */ -#define WM8996_HP_DONE_WIDTH 1 /* HP_DONE */ -#define WM8996_HP_LVL_MASK 0x007F /* HP_LVL - [6:0] */ -#define WM8996_HP_LVL_SHIFT 0 /* HP_LVL - [6:0] */ -#define WM8996_HP_LVL_WIDTH 7 /* HP_LVL - [6:0] */ - -/* - * R56 (0x38) - Mic Detect 1 - */ -#define WM8996_MICD_BIAS_STARTTIME_MASK 0xF000 /* MICD_BIAS_STARTTIME - [15:12] */ -#define WM8996_MICD_BIAS_STARTTIME_SHIFT 12 /* MICD_BIAS_STARTTIME - [15:12] */ -#define WM8996_MICD_BIAS_STARTTIME_WIDTH 4 /* MICD_BIAS_STARTTIME - [15:12] */ -#define WM8996_MICD_RATE_MASK 0x0F00 /* MICD_RATE - [11:8] */ -#define WM8996_MICD_RATE_SHIFT 8 /* MICD_RATE - [11:8] */ -#define WM8996_MICD_RATE_WIDTH 4 /* MICD_RATE - [11:8] */ -#define WM8996_MICD_DBTIME 0x0002 /* MICD_DBTIME */ -#define WM8996_MICD_DBTIME_MASK 0x0002 /* MICD_DBTIME */ -#define WM8996_MICD_DBTIME_SHIFT 1 /* MICD_DBTIME */ -#define WM8996_MICD_DBTIME_WIDTH 1 /* MICD_DBTIME */ -#define WM8996_MICD_ENA 0x0001 /* MICD_ENA */ -#define WM8996_MICD_ENA_MASK 0x0001 /* MICD_ENA */ -#define WM8996_MICD_ENA_SHIFT 0 /* MICD_ENA */ -#define WM8996_MICD_ENA_WIDTH 1 /* MICD_ENA */ - -/* - * R57 (0x39) - Mic Detect 2 - */ -#define WM8996_MICD_LVL_SEL_MASK 0x00FF /* MICD_LVL_SEL - [7:0] */ -#define WM8996_MICD_LVL_SEL_SHIFT 0 /* MICD_LVL_SEL - [7:0] */ -#define WM8996_MICD_LVL_SEL_WIDTH 8 /* MICD_LVL_SEL - [7:0] */ - -/* - * R58 (0x3A) - Mic Detect 3 - */ -#define WM8996_MICD_LVL_MASK 0x07FC /* MICD_LVL - [10:2] */ -#define WM8996_MICD_LVL_SHIFT 2 /* MICD_LVL - [10:2] */ -#define WM8996_MICD_LVL_WIDTH 9 /* MICD_LVL - [10:2] */ -#define WM8996_MICD_VALID 0x0002 /* MICD_VALID */ -#define WM8996_MICD_VALID_MASK 0x0002 /* MICD_VALID */ -#define WM8996_MICD_VALID_SHIFT 1 /* MICD_VALID */ -#define WM8996_MICD_VALID_WIDTH 1 /* MICD_VALID */ -#define WM8996_MICD_STS 0x0001 /* MICD_STS */ -#define WM8996_MICD_STS_MASK 0x0001 /* MICD_STS */ -#define WM8996_MICD_STS_SHIFT 0 /* MICD_STS */ -#define WM8996_MICD_STS_WIDTH 1 /* MICD_STS */ - -/* - * R64 (0x40) - Charge Pump (1) - */ -#define WM8996_CP_ENA 0x8000 /* CP_ENA */ -#define WM8996_CP_ENA_MASK 0x8000 /* CP_ENA */ -#define WM8996_CP_ENA_SHIFT 15 /* CP_ENA */ -#define WM8996_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R65 (0x41) - Charge Pump (2) - */ -#define WM8996_CP_DISCH 0x8000 /* CP_DISCH */ -#define WM8996_CP_DISCH_MASK 0x8000 /* CP_DISCH */ -#define WM8996_CP_DISCH_SHIFT 15 /* CP_DISCH */ -#define WM8996_CP_DISCH_WIDTH 1 /* CP_DISCH */ - -/* - * R80 (0x50) - DC Servo (1) - */ -#define WM8996_DCS_ENA_CHAN_3 0x0008 /* DCS_ENA_CHAN_3 */ -#define WM8996_DCS_ENA_CHAN_3_MASK 0x0008 /* DCS_ENA_CHAN_3 */ -#define WM8996_DCS_ENA_CHAN_3_SHIFT 3 /* DCS_ENA_CHAN_3 */ -#define WM8996_DCS_ENA_CHAN_3_WIDTH 1 /* DCS_ENA_CHAN_3 */ -#define WM8996_DCS_ENA_CHAN_2 0x0004 /* DCS_ENA_CHAN_2 */ -#define WM8996_DCS_ENA_CHAN_2_MASK 0x0004 /* DCS_ENA_CHAN_2 */ -#define WM8996_DCS_ENA_CHAN_2_SHIFT 2 /* DCS_ENA_CHAN_2 */ -#define WM8996_DCS_ENA_CHAN_2_WIDTH 1 /* DCS_ENA_CHAN_2 */ -#define WM8996_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8996_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8996_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ -#define WM8996_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ -#define WM8996_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8996_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8996_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ -#define WM8996_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ - -/* - * R81 (0x51) - DC Servo (2) - */ -#define WM8996_DCS_TRIG_SINGLE_3 0x8000 /* DCS_TRIG_SINGLE_3 */ -#define WM8996_DCS_TRIG_SINGLE_3_MASK 0x8000 /* DCS_TRIG_SINGLE_3 */ -#define WM8996_DCS_TRIG_SINGLE_3_SHIFT 15 /* DCS_TRIG_SINGLE_3 */ -#define WM8996_DCS_TRIG_SINGLE_3_WIDTH 1 /* DCS_TRIG_SINGLE_3 */ -#define WM8996_DCS_TRIG_SINGLE_2 0x4000 /* DCS_TRIG_SINGLE_2 */ -#define WM8996_DCS_TRIG_SINGLE_2_MASK 0x4000 /* DCS_TRIG_SINGLE_2 */ -#define WM8996_DCS_TRIG_SINGLE_2_SHIFT 14 /* DCS_TRIG_SINGLE_2 */ -#define WM8996_DCS_TRIG_SINGLE_2_WIDTH 1 /* DCS_TRIG_SINGLE_2 */ -#define WM8996_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8996_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8996_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ -#define WM8996_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ -#define WM8996_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8996_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8996_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ -#define WM8996_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ -#define WM8996_DCS_TRIG_SERIES_3 0x0800 /* DCS_TRIG_SERIES_3 */ -#define WM8996_DCS_TRIG_SERIES_3_MASK 0x0800 /* DCS_TRIG_SERIES_3 */ -#define WM8996_DCS_TRIG_SERIES_3_SHIFT 11 /* DCS_TRIG_SERIES_3 */ -#define WM8996_DCS_TRIG_SERIES_3_WIDTH 1 /* DCS_TRIG_SERIES_3 */ -#define WM8996_DCS_TRIG_SERIES_2 0x0400 /* DCS_TRIG_SERIES_2 */ -#define WM8996_DCS_TRIG_SERIES_2_MASK 0x0400 /* DCS_TRIG_SERIES_2 */ -#define WM8996_DCS_TRIG_SERIES_2_SHIFT 10 /* DCS_TRIG_SERIES_2 */ -#define WM8996_DCS_TRIG_SERIES_2_WIDTH 1 /* DCS_TRIG_SERIES_2 */ -#define WM8996_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8996_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8996_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ -#define WM8996_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ -#define WM8996_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8996_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8996_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ -#define WM8996_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ -#define WM8996_DCS_TRIG_STARTUP_3 0x0080 /* DCS_TRIG_STARTUP_3 */ -#define WM8996_DCS_TRIG_STARTUP_3_MASK 0x0080 /* DCS_TRIG_STARTUP_3 */ -#define WM8996_DCS_TRIG_STARTUP_3_SHIFT 7 /* DCS_TRIG_STARTUP_3 */ -#define WM8996_DCS_TRIG_STARTUP_3_WIDTH 1 /* DCS_TRIG_STARTUP_3 */ -#define WM8996_DCS_TRIG_STARTUP_2 0x0040 /* DCS_TRIG_STARTUP_2 */ -#define WM8996_DCS_TRIG_STARTUP_2_MASK 0x0040 /* DCS_TRIG_STARTUP_2 */ -#define WM8996_DCS_TRIG_STARTUP_2_SHIFT 6 /* DCS_TRIG_STARTUP_2 */ -#define WM8996_DCS_TRIG_STARTUP_2_WIDTH 1 /* DCS_TRIG_STARTUP_2 */ -#define WM8996_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8996_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8996_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ -#define WM8996_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ -#define WM8996_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8996_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8996_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ -#define WM8996_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ -#define WM8996_DCS_TRIG_DAC_WR_3 0x0008 /* DCS_TRIG_DAC_WR_3 */ -#define WM8996_DCS_TRIG_DAC_WR_3_MASK 0x0008 /* DCS_TRIG_DAC_WR_3 */ -#define WM8996_DCS_TRIG_DAC_WR_3_SHIFT 3 /* DCS_TRIG_DAC_WR_3 */ -#define WM8996_DCS_TRIG_DAC_WR_3_WIDTH 1 /* DCS_TRIG_DAC_WR_3 */ -#define WM8996_DCS_TRIG_DAC_WR_2 0x0004 /* DCS_TRIG_DAC_WR_2 */ -#define WM8996_DCS_TRIG_DAC_WR_2_MASK 0x0004 /* DCS_TRIG_DAC_WR_2 */ -#define WM8996_DCS_TRIG_DAC_WR_2_SHIFT 2 /* DCS_TRIG_DAC_WR_2 */ -#define WM8996_DCS_TRIG_DAC_WR_2_WIDTH 1 /* DCS_TRIG_DAC_WR_2 */ -#define WM8996_DCS_TRIG_DAC_WR_1 0x0002 /* DCS_TRIG_DAC_WR_1 */ -#define WM8996_DCS_TRIG_DAC_WR_1_MASK 0x0002 /* DCS_TRIG_DAC_WR_1 */ -#define WM8996_DCS_TRIG_DAC_WR_1_SHIFT 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8996_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8996_DCS_TRIG_DAC_WR_0 0x0001 /* DCS_TRIG_DAC_WR_0 */ -#define WM8996_DCS_TRIG_DAC_WR_0_MASK 0x0001 /* DCS_TRIG_DAC_WR_0 */ -#define WM8996_DCS_TRIG_DAC_WR_0_SHIFT 0 /* DCS_TRIG_DAC_WR_0 */ -#define WM8996_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ - -/* - * R82 (0x52) - DC Servo (3) - */ -#define WM8996_DCS_TIMER_PERIOD_23_MASK 0x0F00 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8996_DCS_TIMER_PERIOD_23_SHIFT 8 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8996_DCS_TIMER_PERIOD_23_WIDTH 4 /* DCS_TIMER_PERIOD_23 - [11:8] */ -#define WM8996_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8996_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8996_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ - -/* - * R84 (0x54) - DC Servo (5) - */ -#define WM8996_DCS_SERIES_NO_23_MASK 0x7F00 /* DCS_SERIES_NO_23 - [14:8] */ -#define WM8996_DCS_SERIES_NO_23_SHIFT 8 /* DCS_SERIES_NO_23 - [14:8] */ -#define WM8996_DCS_SERIES_NO_23_WIDTH 7 /* DCS_SERIES_NO_23 - [14:8] */ -#define WM8996_DCS_SERIES_NO_01_MASK 0x007F /* DCS_SERIES_NO_01 - [6:0] */ -#define WM8996_DCS_SERIES_NO_01_SHIFT 0 /* DCS_SERIES_NO_01 - [6:0] */ -#define WM8996_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [6:0] */ - -/* - * R85 (0x55) - DC Servo (6) - */ -#define WM8996_DCS_DAC_WR_VAL_3_MASK 0xFF00 /* DCS_DAC_WR_VAL_3 - [15:8] */ -#define WM8996_DCS_DAC_WR_VAL_3_SHIFT 8 /* DCS_DAC_WR_VAL_3 - [15:8] */ -#define WM8996_DCS_DAC_WR_VAL_3_WIDTH 8 /* DCS_DAC_WR_VAL_3 - [15:8] */ -#define WM8996_DCS_DAC_WR_VAL_2_MASK 0x00FF /* DCS_DAC_WR_VAL_2 - [7:0] */ -#define WM8996_DCS_DAC_WR_VAL_2_SHIFT 0 /* DCS_DAC_WR_VAL_2 - [7:0] */ -#define WM8996_DCS_DAC_WR_VAL_2_WIDTH 8 /* DCS_DAC_WR_VAL_2 - [7:0] */ - -/* - * R86 (0x56) - DC Servo (7) - */ -#define WM8996_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8996_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8996_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8996_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8996_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8996_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ - -/* - * R87 (0x57) - DC Servo Readback 0 - */ -#define WM8996_DCS_CAL_COMPLETE_MASK 0x0F00 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8996_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8996_DCS_CAL_COMPLETE_WIDTH 4 /* DCS_CAL_COMPLETE - [11:8] */ -#define WM8996_DCS_DAC_WR_COMPLETE_MASK 0x00F0 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8996_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8996_DCS_DAC_WR_COMPLETE_WIDTH 4 /* DCS_DAC_WR_COMPLETE - [7:4] */ -#define WM8996_DCS_STARTUP_COMPLETE_MASK 0x000F /* DCS_STARTUP_COMPLETE - [3:0] */ -#define WM8996_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [3:0] */ -#define WM8996_DCS_STARTUP_COMPLETE_WIDTH 4 /* DCS_STARTUP_COMPLETE - [3:0] */ - -/* - * R96 (0x60) - Analogue HP (1) - */ -#define WM8996_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8996_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8996_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */ -#define WM8996_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */ -#define WM8996_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */ -#define WM8996_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */ -#define WM8996_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */ -#define WM8996_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */ -#define WM8996_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */ -#define WM8996_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */ -#define WM8996_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */ -#define WM8996_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */ -#define WM8996_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8996_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8996_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */ -#define WM8996_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */ -#define WM8996_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */ -#define WM8996_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */ -#define WM8996_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */ -#define WM8996_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */ -#define WM8996_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */ -#define WM8996_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */ -#define WM8996_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */ -#define WM8996_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */ - -/* - * R97 (0x61) - Analogue HP (2) - */ -#define WM8996_HPOUT2L_RMV_SHORT 0x0080 /* HPOUT2L_RMV_SHORT */ -#define WM8996_HPOUT2L_RMV_SHORT_MASK 0x0080 /* HPOUT2L_RMV_SHORT */ -#define WM8996_HPOUT2L_RMV_SHORT_SHIFT 7 /* HPOUT2L_RMV_SHORT */ -#define WM8996_HPOUT2L_RMV_SHORT_WIDTH 1 /* HPOUT2L_RMV_SHORT */ -#define WM8996_HPOUT2L_OUTP 0x0040 /* HPOUT2L_OUTP */ -#define WM8996_HPOUT2L_OUTP_MASK 0x0040 /* HPOUT2L_OUTP */ -#define WM8996_HPOUT2L_OUTP_SHIFT 6 /* HPOUT2L_OUTP */ -#define WM8996_HPOUT2L_OUTP_WIDTH 1 /* HPOUT2L_OUTP */ -#define WM8996_HPOUT2L_DLY 0x0020 /* HPOUT2L_DLY */ -#define WM8996_HPOUT2L_DLY_MASK 0x0020 /* HPOUT2L_DLY */ -#define WM8996_HPOUT2L_DLY_SHIFT 5 /* HPOUT2L_DLY */ -#define WM8996_HPOUT2L_DLY_WIDTH 1 /* HPOUT2L_DLY */ -#define WM8996_HPOUT2R_RMV_SHORT 0x0008 /* HPOUT2R_RMV_SHORT */ -#define WM8996_HPOUT2R_RMV_SHORT_MASK 0x0008 /* HPOUT2R_RMV_SHORT */ -#define WM8996_HPOUT2R_RMV_SHORT_SHIFT 3 /* HPOUT2R_RMV_SHORT */ -#define WM8996_HPOUT2R_RMV_SHORT_WIDTH 1 /* HPOUT2R_RMV_SHORT */ -#define WM8996_HPOUT2R_OUTP 0x0004 /* HPOUT2R_OUTP */ -#define WM8996_HPOUT2R_OUTP_MASK 0x0004 /* HPOUT2R_OUTP */ -#define WM8996_HPOUT2R_OUTP_SHIFT 2 /* HPOUT2R_OUTP */ -#define WM8996_HPOUT2R_OUTP_WIDTH 1 /* HPOUT2R_OUTP */ -#define WM8996_HPOUT2R_DLY 0x0002 /* HPOUT2R_DLY */ -#define WM8996_HPOUT2R_DLY_MASK 0x0002 /* HPOUT2R_DLY */ -#define WM8996_HPOUT2R_DLY_SHIFT 1 /* HPOUT2R_DLY */ -#define WM8996_HPOUT2R_DLY_WIDTH 1 /* HPOUT2R_DLY */ - -/* - * R256 (0x100) - Chip Revision - */ -#define WM8996_CHIP_REV_MASK 0x000F /* CHIP_REV - [3:0] */ -#define WM8996_CHIP_REV_SHIFT 0 /* CHIP_REV - [3:0] */ -#define WM8996_CHIP_REV_WIDTH 4 /* CHIP_REV - [3:0] */ - -/* - * R257 (0x101) - Control Interface (1) - */ -#define WM8996_REG_SYNC 0x8000 /* REG_SYNC */ -#define WM8996_REG_SYNC_MASK 0x8000 /* REG_SYNC */ -#define WM8996_REG_SYNC_SHIFT 15 /* REG_SYNC */ -#define WM8996_REG_SYNC_WIDTH 1 /* REG_SYNC */ -#define WM8996_AUTO_INC 0x0004 /* AUTO_INC */ -#define WM8996_AUTO_INC_MASK 0x0004 /* AUTO_INC */ -#define WM8996_AUTO_INC_SHIFT 2 /* AUTO_INC */ -#define WM8996_AUTO_INC_WIDTH 1 /* AUTO_INC */ - -/* - * R272 (0x110) - Write Sequencer Ctrl (1) - */ -#define WM8996_WSEQ_ENA 0x8000 /* WSEQ_ENA */ -#define WM8996_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */ -#define WM8996_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */ -#define WM8996_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8996_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM8996_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM8996_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM8996_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8996_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM8996_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM8996_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM8996_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8996_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */ -#define WM8996_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */ -#define WM8996_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */ - -/* - * R273 (0x111) - Write Sequencer Ctrl (2) - */ -#define WM8996_WSEQ_BUSY 0x0100 /* WSEQ_BUSY */ -#define WM8996_WSEQ_BUSY_MASK 0x0100 /* WSEQ_BUSY */ -#define WM8996_WSEQ_BUSY_SHIFT 8 /* WSEQ_BUSY */ -#define WM8996_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ -#define WM8996_WSEQ_CURRENT_INDEX_MASK 0x007F /* WSEQ_CURRENT_INDEX - [6:0] */ -#define WM8996_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [6:0] */ -#define WM8996_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [6:0] */ - -/* - * R512 (0x200) - AIF Clocking (1) - */ -#define WM8996_SYSCLK_SRC_MASK 0x0018 /* SYSCLK_SRC - [4:3] */ -#define WM8996_SYSCLK_SRC_SHIFT 3 /* SYSCLK_SRC - [4:3] */ -#define WM8996_SYSCLK_SRC_WIDTH 2 /* SYSCLK_SRC - [4:3] */ -#define WM8996_SYSCLK_INV 0x0004 /* SYSCLK_INV */ -#define WM8996_SYSCLK_INV_MASK 0x0004 /* SYSCLK_INV */ -#define WM8996_SYSCLK_INV_SHIFT 2 /* SYSCLK_INV */ -#define WM8996_SYSCLK_INV_WIDTH 1 /* SYSCLK_INV */ -#define WM8996_SYSCLK_DIV 0x0002 /* SYSCLK_DIV */ -#define WM8996_SYSCLK_DIV_MASK 0x0002 /* SYSCLK_DIV */ -#define WM8996_SYSCLK_DIV_SHIFT 1 /* SYSCLK_DIV */ -#define WM8996_SYSCLK_DIV_WIDTH 1 /* SYSCLK_DIV */ -#define WM8996_SYSCLK_ENA 0x0001 /* SYSCLK_ENA */ -#define WM8996_SYSCLK_ENA_MASK 0x0001 /* SYSCLK_ENA */ -#define WM8996_SYSCLK_ENA_SHIFT 0 /* SYSCLK_ENA */ -#define WM8996_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */ - -/* - * R513 (0x201) - AIF Clocking (2) - */ -#define WM8996_DSP2_DIV_MASK 0x0018 /* DSP2_DIV - [4:3] */ -#define WM8996_DSP2_DIV_SHIFT 3 /* DSP2_DIV - [4:3] */ -#define WM8996_DSP2_DIV_WIDTH 2 /* DSP2_DIV - [4:3] */ -#define WM8996_DSP1_DIV_MASK 0x0003 /* DSP1_DIV - [1:0] */ -#define WM8996_DSP1_DIV_SHIFT 0 /* DSP1_DIV - [1:0] */ -#define WM8996_DSP1_DIV_WIDTH 2 /* DSP1_DIV - [1:0] */ - -/* - * R520 (0x208) - Clocking (1) - */ -#define WM8996_LFCLK_ENA 0x0020 /* LFCLK_ENA */ -#define WM8996_LFCLK_ENA_MASK 0x0020 /* LFCLK_ENA */ -#define WM8996_LFCLK_ENA_SHIFT 5 /* LFCLK_ENA */ -#define WM8996_LFCLK_ENA_WIDTH 1 /* LFCLK_ENA */ -#define WM8996_TOCLK_ENA 0x0010 /* TOCLK_ENA */ -#define WM8996_TOCLK_ENA_MASK 0x0010 /* TOCLK_ENA */ -#define WM8996_TOCLK_ENA_SHIFT 4 /* TOCLK_ENA */ -#define WM8996_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ -#define WM8996_AIFCLK_ENA 0x0004 /* AIFCLK_ENA */ -#define WM8996_AIFCLK_ENA_MASK 0x0004 /* AIFCLK_ENA */ -#define WM8996_AIFCLK_ENA_SHIFT 2 /* AIFCLK_ENA */ -#define WM8996_AIFCLK_ENA_WIDTH 1 /* AIFCLK_ENA */ -#define WM8996_SYSDSPCLK_ENA 0x0002 /* SYSDSPCLK_ENA */ -#define WM8996_SYSDSPCLK_ENA_MASK 0x0002 /* SYSDSPCLK_ENA */ -#define WM8996_SYSDSPCLK_ENA_SHIFT 1 /* SYSDSPCLK_ENA */ -#define WM8996_SYSDSPCLK_ENA_WIDTH 1 /* SYSDSPCLK_ENA */ - -/* - * R521 (0x209) - Clocking (2) - */ -#define WM8996_TOCLK_DIV_MASK 0x0700 /* TOCLK_DIV - [10:8] */ -#define WM8996_TOCLK_DIV_SHIFT 8 /* TOCLK_DIV - [10:8] */ -#define WM8996_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [10:8] */ -#define WM8996_DBCLK_DIV_MASK 0x00F0 /* DBCLK_DIV - [7:4] */ -#define WM8996_DBCLK_DIV_SHIFT 4 /* DBCLK_DIV - [7:4] */ -#define WM8996_DBCLK_DIV_WIDTH 4 /* DBCLK_DIV - [7:4] */ -#define WM8996_OPCLK_DIV_MASK 0x0007 /* OPCLK_DIV - [2:0] */ -#define WM8996_OPCLK_DIV_SHIFT 0 /* OPCLK_DIV - [2:0] */ -#define WM8996_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [2:0] */ - -/* - * R528 (0x210) - AIF Rate - */ -#define WM8996_SYSCLK_RATE 0x0001 /* SYSCLK_RATE */ -#define WM8996_SYSCLK_RATE_MASK 0x0001 /* SYSCLK_RATE */ -#define WM8996_SYSCLK_RATE_SHIFT 0 /* SYSCLK_RATE */ -#define WM8996_SYSCLK_RATE_WIDTH 1 /* SYSCLK_RATE */ - -/* - * R544 (0x220) - FLL Control (1) - */ -#define WM8996_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ -#define WM8996_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ -#define WM8996_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ -#define WM8996_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ -#define WM8996_FLL_ENA 0x0001 /* FLL_ENA */ -#define WM8996_FLL_ENA_MASK 0x0001 /* FLL_ENA */ -#define WM8996_FLL_ENA_SHIFT 0 /* FLL_ENA */ -#define WM8996_FLL_ENA_WIDTH 1 /* FLL_ENA */ - -/* - * R545 (0x221) - FLL Control (2) - */ -#define WM8996_FLL_OUTDIV_MASK 0x3F00 /* FLL_OUTDIV - [13:8] */ -#define WM8996_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [13:8] */ -#define WM8996_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [13:8] */ -#define WM8996_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ -#define WM8996_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ -#define WM8996_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ - -/* - * R546 (0x222) - FLL Control (3) - */ -#define WM8996_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */ -#define WM8996_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */ -#define WM8996_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */ - -/* - * R547 (0x223) - FLL Control (4) - */ -#define WM8996_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */ -#define WM8996_FLL_N_SHIFT 5 /* FLL_N - [14:5] */ -#define WM8996_FLL_N_WIDTH 10 /* FLL_N - [14:5] */ -#define WM8996_FLL_LOOP_GAIN_MASK 0x000F /* FLL_LOOP_GAIN - [3:0] */ -#define WM8996_FLL_LOOP_GAIN_SHIFT 0 /* FLL_LOOP_GAIN - [3:0] */ -#define WM8996_FLL_LOOP_GAIN_WIDTH 4 /* FLL_LOOP_GAIN - [3:0] */ - -/* - * R548 (0x224) - FLL Control (5) - */ -#define WM8996_FLL_FRC_NCO_VAL_MASK 0x1F80 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8996_FLL_FRC_NCO_VAL_SHIFT 7 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8996_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8996_FLL_FRC_NCO 0x0040 /* FLL_FRC_NCO */ -#define WM8996_FLL_FRC_NCO_MASK 0x0040 /* FLL_FRC_NCO */ -#define WM8996_FLL_FRC_NCO_SHIFT 6 /* FLL_FRC_NCO */ -#define WM8996_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ -#define WM8996_FLL_REFCLK_DIV_MASK 0x0018 /* FLL_REFCLK_DIV - [4:3] */ -#define WM8996_FLL_REFCLK_DIV_SHIFT 3 /* FLL_REFCLK_DIV - [4:3] */ -#define WM8996_FLL_REFCLK_DIV_WIDTH 2 /* FLL_REFCLK_DIV - [4:3] */ -#define WM8996_FLL_REF_FREQ 0x0004 /* FLL_REF_FREQ */ -#define WM8996_FLL_REF_FREQ_MASK 0x0004 /* FLL_REF_FREQ */ -#define WM8996_FLL_REF_FREQ_SHIFT 2 /* FLL_REF_FREQ */ -#define WM8996_FLL_REF_FREQ_WIDTH 1 /* FLL_REF_FREQ */ -#define WM8996_FLL_REFCLK_SRC_MASK 0x0003 /* FLL_REFCLK_SRC - [1:0] */ -#define WM8996_FLL_REFCLK_SRC_SHIFT 0 /* FLL_REFCLK_SRC - [1:0] */ -#define WM8996_FLL_REFCLK_SRC_WIDTH 2 /* FLL_REFCLK_SRC - [1:0] */ - -/* - * R549 (0x225) - FLL Control (6) - */ -#define WM8996_FLL_REFCLK_SRC_STS_MASK 0x000C /* FLL_REFCLK_SRC_STS - [3:2] */ -#define WM8996_FLL_REFCLK_SRC_STS_SHIFT 2 /* FLL_REFCLK_SRC_STS - [3:2] */ -#define WM8996_FLL_REFCLK_SRC_STS_WIDTH 2 /* FLL_REFCLK_SRC_STS - [3:2] */ -#define WM8996_FLL_SWITCH_CLK 0x0001 /* FLL_SWITCH_CLK */ -#define WM8996_FLL_SWITCH_CLK_MASK 0x0001 /* FLL_SWITCH_CLK */ -#define WM8996_FLL_SWITCH_CLK_SHIFT 0 /* FLL_SWITCH_CLK */ -#define WM8996_FLL_SWITCH_CLK_WIDTH 1 /* FLL_SWITCH_CLK */ - -/* - * R550 (0x226) - FLL EFS 1 - */ -#define WM8996_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */ -#define WM8996_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */ -#define WM8996_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */ - -/* - * R551 (0x227) - FLL EFS 2 - */ -#define WM8996_FLL_LFSR_SEL_MASK 0x0006 /* FLL_LFSR_SEL - [2:1] */ -#define WM8996_FLL_LFSR_SEL_SHIFT 1 /* FLL_LFSR_SEL - [2:1] */ -#define WM8996_FLL_LFSR_SEL_WIDTH 2 /* FLL_LFSR_SEL - [2:1] */ -#define WM8996_FLL_EFS_ENA 0x0001 /* FLL_EFS_ENA */ -#define WM8996_FLL_EFS_ENA_MASK 0x0001 /* FLL_EFS_ENA */ -#define WM8996_FLL_EFS_ENA_SHIFT 0 /* FLL_EFS_ENA */ -#define WM8996_FLL_EFS_ENA_WIDTH 1 /* FLL_EFS_ENA */ - -/* - * R768 (0x300) - AIF1 Control - */ -#define WM8996_AIF1_TRI 0x0004 /* AIF1_TRI */ -#define WM8996_AIF1_TRI_MASK 0x0004 /* AIF1_TRI */ -#define WM8996_AIF1_TRI_SHIFT 2 /* AIF1_TRI */ -#define WM8996_AIF1_TRI_WIDTH 1 /* AIF1_TRI */ -#define WM8996_AIF1_FMT_MASK 0x0003 /* AIF1_FMT - [1:0] */ -#define WM8996_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [1:0] */ -#define WM8996_AIF1_FMT_WIDTH 2 /* AIF1_FMT - [1:0] */ - -/* - * R769 (0x301) - AIF1 BCLK - */ -#define WM8996_AIF1_BCLK_INV 0x0400 /* AIF1_BCLK_INV */ -#define WM8996_AIF1_BCLK_INV_MASK 0x0400 /* AIF1_BCLK_INV */ -#define WM8996_AIF1_BCLK_INV_SHIFT 10 /* AIF1_BCLK_INV */ -#define WM8996_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */ -#define WM8996_AIF1_BCLK_FRC 0x0200 /* AIF1_BCLK_FRC */ -#define WM8996_AIF1_BCLK_FRC_MASK 0x0200 /* AIF1_BCLK_FRC */ -#define WM8996_AIF1_BCLK_FRC_SHIFT 9 /* AIF1_BCLK_FRC */ -#define WM8996_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */ -#define WM8996_AIF1_BCLK_MSTR 0x0100 /* AIF1_BCLK_MSTR */ -#define WM8996_AIF1_BCLK_MSTR_MASK 0x0100 /* AIF1_BCLK_MSTR */ -#define WM8996_AIF1_BCLK_MSTR_SHIFT 8 /* AIF1_BCLK_MSTR */ -#define WM8996_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */ -#define WM8996_AIF1_BCLK_DIV_MASK 0x000F /* AIF1_BCLK_DIV - [3:0] */ -#define WM8996_AIF1_BCLK_DIV_SHIFT 0 /* AIF1_BCLK_DIV - [3:0] */ -#define WM8996_AIF1_BCLK_DIV_WIDTH 4 /* AIF1_BCLK_DIV - [3:0] */ - -/* - * R770 (0x302) - AIF1 TX LRCLK(1) - */ -#define WM8996_AIF1TX_RATE_MASK 0x07FF /* AIF1TX_RATE - [10:0] */ -#define WM8996_AIF1TX_RATE_SHIFT 0 /* AIF1TX_RATE - [10:0] */ -#define WM8996_AIF1TX_RATE_WIDTH 11 /* AIF1TX_RATE - [10:0] */ - -/* - * R771 (0x303) - AIF1 TX LRCLK(2) - */ -#define WM8996_AIF1TX_LRCLK_MODE 0x0008 /* AIF1TX_LRCLK_MODE */ -#define WM8996_AIF1TX_LRCLK_MODE_MASK 0x0008 /* AIF1TX_LRCLK_MODE */ -#define WM8996_AIF1TX_LRCLK_MODE_SHIFT 3 /* AIF1TX_LRCLK_MODE */ -#define WM8996_AIF1TX_LRCLK_MODE_WIDTH 1 /* AIF1TX_LRCLK_MODE */ -#define WM8996_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */ -#define WM8996_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */ -#define WM8996_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */ -#define WM8996_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */ -#define WM8996_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */ -#define WM8996_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */ -#define WM8996_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */ -#define WM8996_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */ -#define WM8996_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */ -#define WM8996_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */ -#define WM8996_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */ -#define WM8996_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */ - -/* - * R772 (0x304) - AIF1 RX LRCLK(1) - */ -#define WM8996_AIF1RX_RATE_MASK 0x07FF /* AIF1RX_RATE - [10:0] */ -#define WM8996_AIF1RX_RATE_SHIFT 0 /* AIF1RX_RATE - [10:0] */ -#define WM8996_AIF1RX_RATE_WIDTH 11 /* AIF1RX_RATE - [10:0] */ - -/* - * R773 (0x305) - AIF1 RX LRCLK(2) - */ -#define WM8996_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */ -#define WM8996_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */ -#define WM8996_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */ -#define WM8996_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */ -#define WM8996_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */ -#define WM8996_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */ -#define WM8996_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */ -#define WM8996_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */ -#define WM8996_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */ -#define WM8996_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */ -#define WM8996_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */ -#define WM8996_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */ - -/* - * R774 (0x306) - AIF1TX Data Configuration (1) - */ -#define WM8996_AIF1TX_WL_MASK 0xFF00 /* AIF1TX_WL - [15:8] */ -#define WM8996_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [15:8] */ -#define WM8996_AIF1TX_WL_WIDTH 8 /* AIF1TX_WL - [15:8] */ -#define WM8996_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */ -#define WM8996_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */ -#define WM8996_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */ - -/* - * R775 (0x307) - AIF1TX Data Configuration (2) - */ -#define WM8996_AIF1TX_DAT_TRI 0x0001 /* AIF1TX_DAT_TRI */ -#define WM8996_AIF1TX_DAT_TRI_MASK 0x0001 /* AIF1TX_DAT_TRI */ -#define WM8996_AIF1TX_DAT_TRI_SHIFT 0 /* AIF1TX_DAT_TRI */ -#define WM8996_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */ - -/* - * R776 (0x308) - AIF1RX Data Configuration - */ -#define WM8996_AIF1RX_WL_MASK 0xFF00 /* AIF1RX_WL - [15:8] */ -#define WM8996_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [15:8] */ -#define WM8996_AIF1RX_WL_WIDTH 8 /* AIF1RX_WL - [15:8] */ -#define WM8996_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */ -#define WM8996_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */ -#define WM8996_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */ - -/* - * R777 (0x309) - AIF1TX Channel 0 Configuration - */ -#define WM8996_AIF1TX_CHAN0_DAT_INV 0x8000 /* AIF1TX_CHAN0_DAT_INV */ -#define WM8996_AIF1TX_CHAN0_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN0_DAT_INV */ -#define WM8996_AIF1TX_CHAN0_DAT_INV_SHIFT 15 /* AIF1TX_CHAN0_DAT_INV */ -#define WM8996_AIF1TX_CHAN0_DAT_INV_WIDTH 1 /* AIF1TX_CHAN0_DAT_INV */ -#define WM8996_AIF1TX_CHAN0_SPACING_MASK 0x7E00 /* AIF1TX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN0_SPACING_SHIFT 9 /* AIF1TX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN0_SPACING_WIDTH 6 /* AIF1TX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN0_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN0_SLOTS_SHIFT 6 /* AIF1TX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN0_SLOTS_WIDTH 3 /* AIF1TX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN0_START_SLOT_MASK 0x003F /* AIF1TX_CHAN0_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN0_START_SLOT_SHIFT 0 /* AIF1TX_CHAN0_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN0_START_SLOT_WIDTH 6 /* AIF1TX_CHAN0_START_SLOT - [5:0] */ - -/* - * R778 (0x30A) - AIF1TX Channel 1 Configuration - */ -#define WM8996_AIF1TX_CHAN1_DAT_INV 0x8000 /* AIF1TX_CHAN1_DAT_INV */ -#define WM8996_AIF1TX_CHAN1_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN1_DAT_INV */ -#define WM8996_AIF1TX_CHAN1_DAT_INV_SHIFT 15 /* AIF1TX_CHAN1_DAT_INV */ -#define WM8996_AIF1TX_CHAN1_DAT_INV_WIDTH 1 /* AIF1TX_CHAN1_DAT_INV */ -#define WM8996_AIF1TX_CHAN1_SPACING_MASK 0x7E00 /* AIF1TX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN1_SPACING_SHIFT 9 /* AIF1TX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN1_SPACING_WIDTH 6 /* AIF1TX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN1_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN1_SLOTS_SHIFT 6 /* AIF1TX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN1_SLOTS_WIDTH 3 /* AIF1TX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN1_START_SLOT_MASK 0x003F /* AIF1TX_CHAN1_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN1_START_SLOT_SHIFT 0 /* AIF1TX_CHAN1_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN1_START_SLOT_WIDTH 6 /* AIF1TX_CHAN1_START_SLOT - [5:0] */ - -/* - * R779 (0x30B) - AIF1TX Channel 2 Configuration - */ -#define WM8996_AIF1TX_CHAN2_DAT_INV 0x8000 /* AIF1TX_CHAN2_DAT_INV */ -#define WM8996_AIF1TX_CHAN2_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN2_DAT_INV */ -#define WM8996_AIF1TX_CHAN2_DAT_INV_SHIFT 15 /* AIF1TX_CHAN2_DAT_INV */ -#define WM8996_AIF1TX_CHAN2_DAT_INV_WIDTH 1 /* AIF1TX_CHAN2_DAT_INV */ -#define WM8996_AIF1TX_CHAN2_SPACING_MASK 0x7E00 /* AIF1TX_CHAN2_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN2_SPACING_SHIFT 9 /* AIF1TX_CHAN2_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN2_SPACING_WIDTH 6 /* AIF1TX_CHAN2_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN2_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN2_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN2_SLOTS_SHIFT 6 /* AIF1TX_CHAN2_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN2_SLOTS_WIDTH 3 /* AIF1TX_CHAN2_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN2_START_SLOT_MASK 0x003F /* AIF1TX_CHAN2_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN2_START_SLOT_SHIFT 0 /* AIF1TX_CHAN2_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN2_START_SLOT_WIDTH 6 /* AIF1TX_CHAN2_START_SLOT - [5:0] */ - -/* - * R780 (0x30C) - AIF1TX Channel 3 Configuration - */ -#define WM8996_AIF1TX_CHAN3_DAT_INV 0x8000 /* AIF1TX_CHAN3_DAT_INV */ -#define WM8996_AIF1TX_CHAN3_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN3_DAT_INV */ -#define WM8996_AIF1TX_CHAN3_DAT_INV_SHIFT 15 /* AIF1TX_CHAN3_DAT_INV */ -#define WM8996_AIF1TX_CHAN3_DAT_INV_WIDTH 1 /* AIF1TX_CHAN3_DAT_INV */ -#define WM8996_AIF1TX_CHAN3_SPACING_MASK 0x7E00 /* AIF1TX_CHAN3_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN3_SPACING_SHIFT 9 /* AIF1TX_CHAN3_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN3_SPACING_WIDTH 6 /* AIF1TX_CHAN3_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN3_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN3_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN3_SLOTS_SHIFT 6 /* AIF1TX_CHAN3_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN3_SLOTS_WIDTH 3 /* AIF1TX_CHAN3_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN3_START_SLOT_MASK 0x003F /* AIF1TX_CHAN3_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN3_START_SLOT_SHIFT 0 /* AIF1TX_CHAN3_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN3_START_SLOT_WIDTH 6 /* AIF1TX_CHAN3_START_SLOT - [5:0] */ - -/* - * R781 (0x30D) - AIF1TX Channel 4 Configuration - */ -#define WM8996_AIF1TX_CHAN4_DAT_INV 0x8000 /* AIF1TX_CHAN4_DAT_INV */ -#define WM8996_AIF1TX_CHAN4_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN4_DAT_INV */ -#define WM8996_AIF1TX_CHAN4_DAT_INV_SHIFT 15 /* AIF1TX_CHAN4_DAT_INV */ -#define WM8996_AIF1TX_CHAN4_DAT_INV_WIDTH 1 /* AIF1TX_CHAN4_DAT_INV */ -#define WM8996_AIF1TX_CHAN4_SPACING_MASK 0x7E00 /* AIF1TX_CHAN4_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN4_SPACING_SHIFT 9 /* AIF1TX_CHAN4_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN4_SPACING_WIDTH 6 /* AIF1TX_CHAN4_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN4_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN4_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN4_SLOTS_SHIFT 6 /* AIF1TX_CHAN4_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN4_SLOTS_WIDTH 3 /* AIF1TX_CHAN4_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN4_START_SLOT_MASK 0x003F /* AIF1TX_CHAN4_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN4_START_SLOT_SHIFT 0 /* AIF1TX_CHAN4_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN4_START_SLOT_WIDTH 6 /* AIF1TX_CHAN4_START_SLOT - [5:0] */ - -/* - * R782 (0x30E) - AIF1TX Channel 5 Configuration - */ -#define WM8996_AIF1TX_CHAN5_DAT_INV 0x8000 /* AIF1TX_CHAN5_DAT_INV */ -#define WM8996_AIF1TX_CHAN5_DAT_INV_MASK 0x8000 /* AIF1TX_CHAN5_DAT_INV */ -#define WM8996_AIF1TX_CHAN5_DAT_INV_SHIFT 15 /* AIF1TX_CHAN5_DAT_INV */ -#define WM8996_AIF1TX_CHAN5_DAT_INV_WIDTH 1 /* AIF1TX_CHAN5_DAT_INV */ -#define WM8996_AIF1TX_CHAN5_SPACING_MASK 0x7E00 /* AIF1TX_CHAN5_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN5_SPACING_SHIFT 9 /* AIF1TX_CHAN5_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN5_SPACING_WIDTH 6 /* AIF1TX_CHAN5_SPACING - [14:9] */ -#define WM8996_AIF1TX_CHAN5_SLOTS_MASK 0x01C0 /* AIF1TX_CHAN5_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN5_SLOTS_SHIFT 6 /* AIF1TX_CHAN5_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN5_SLOTS_WIDTH 3 /* AIF1TX_CHAN5_SLOTS - [8:6] */ -#define WM8996_AIF1TX_CHAN5_START_SLOT_MASK 0x003F /* AIF1TX_CHAN5_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN5_START_SLOT_SHIFT 0 /* AIF1TX_CHAN5_START_SLOT - [5:0] */ -#define WM8996_AIF1TX_CHAN5_START_SLOT_WIDTH 6 /* AIF1TX_CHAN5_START_SLOT - [5:0] */ - -/* - * R783 (0x30F) - AIF1RX Channel 0 Configuration - */ -#define WM8996_AIF1RX_CHAN0_DAT_INV 0x8000 /* AIF1RX_CHAN0_DAT_INV */ -#define WM8996_AIF1RX_CHAN0_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN0_DAT_INV */ -#define WM8996_AIF1RX_CHAN0_DAT_INV_SHIFT 15 /* AIF1RX_CHAN0_DAT_INV */ -#define WM8996_AIF1RX_CHAN0_DAT_INV_WIDTH 1 /* AIF1RX_CHAN0_DAT_INV */ -#define WM8996_AIF1RX_CHAN0_SPACING_MASK 0x7E00 /* AIF1RX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN0_SPACING_SHIFT 9 /* AIF1RX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN0_SPACING_WIDTH 6 /* AIF1RX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN0_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN0_SLOTS_SHIFT 6 /* AIF1RX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN0_SLOTS_WIDTH 3 /* AIF1RX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN0_START_SLOT_MASK 0x003F /* AIF1RX_CHAN0_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN0_START_SLOT_SHIFT 0 /* AIF1RX_CHAN0_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN0_START_SLOT_WIDTH 6 /* AIF1RX_CHAN0_START_SLOT - [5:0] */ - -/* - * R784 (0x310) - AIF1RX Channel 1 Configuration - */ -#define WM8996_AIF1RX_CHAN1_DAT_INV 0x8000 /* AIF1RX_CHAN1_DAT_INV */ -#define WM8996_AIF1RX_CHAN1_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN1_DAT_INV */ -#define WM8996_AIF1RX_CHAN1_DAT_INV_SHIFT 15 /* AIF1RX_CHAN1_DAT_INV */ -#define WM8996_AIF1RX_CHAN1_DAT_INV_WIDTH 1 /* AIF1RX_CHAN1_DAT_INV */ -#define WM8996_AIF1RX_CHAN1_SPACING_MASK 0x7E00 /* AIF1RX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN1_SPACING_SHIFT 9 /* AIF1RX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN1_SPACING_WIDTH 6 /* AIF1RX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN1_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN1_SLOTS_SHIFT 6 /* AIF1RX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN1_SLOTS_WIDTH 3 /* AIF1RX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN1_START_SLOT_MASK 0x003F /* AIF1RX_CHAN1_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN1_START_SLOT_SHIFT 0 /* AIF1RX_CHAN1_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN1_START_SLOT_WIDTH 6 /* AIF1RX_CHAN1_START_SLOT - [5:0] */ - -/* - * R785 (0x311) - AIF1RX Channel 2 Configuration - */ -#define WM8996_AIF1RX_CHAN2_DAT_INV 0x8000 /* AIF1RX_CHAN2_DAT_INV */ -#define WM8996_AIF1RX_CHAN2_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN2_DAT_INV */ -#define WM8996_AIF1RX_CHAN2_DAT_INV_SHIFT 15 /* AIF1RX_CHAN2_DAT_INV */ -#define WM8996_AIF1RX_CHAN2_DAT_INV_WIDTH 1 /* AIF1RX_CHAN2_DAT_INV */ -#define WM8996_AIF1RX_CHAN2_SPACING_MASK 0x7E00 /* AIF1RX_CHAN2_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN2_SPACING_SHIFT 9 /* AIF1RX_CHAN2_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN2_SPACING_WIDTH 6 /* AIF1RX_CHAN2_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN2_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN2_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN2_SLOTS_SHIFT 6 /* AIF1RX_CHAN2_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN2_SLOTS_WIDTH 3 /* AIF1RX_CHAN2_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN2_START_SLOT_MASK 0x003F /* AIF1RX_CHAN2_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN2_START_SLOT_SHIFT 0 /* AIF1RX_CHAN2_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN2_START_SLOT_WIDTH 6 /* AIF1RX_CHAN2_START_SLOT - [5:0] */ - -/* - * R786 (0x312) - AIF1RX Channel 3 Configuration - */ -#define WM8996_AIF1RX_CHAN3_DAT_INV 0x8000 /* AIF1RX_CHAN3_DAT_INV */ -#define WM8996_AIF1RX_CHAN3_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN3_DAT_INV */ -#define WM8996_AIF1RX_CHAN3_DAT_INV_SHIFT 15 /* AIF1RX_CHAN3_DAT_INV */ -#define WM8996_AIF1RX_CHAN3_DAT_INV_WIDTH 1 /* AIF1RX_CHAN3_DAT_INV */ -#define WM8996_AIF1RX_CHAN3_SPACING_MASK 0x7E00 /* AIF1RX_CHAN3_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN3_SPACING_SHIFT 9 /* AIF1RX_CHAN3_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN3_SPACING_WIDTH 6 /* AIF1RX_CHAN3_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN3_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN3_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN3_SLOTS_SHIFT 6 /* AIF1RX_CHAN3_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN3_SLOTS_WIDTH 3 /* AIF1RX_CHAN3_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN3_START_SLOT_MASK 0x003F /* AIF1RX_CHAN3_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN3_START_SLOT_SHIFT 0 /* AIF1RX_CHAN3_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN3_START_SLOT_WIDTH 6 /* AIF1RX_CHAN3_START_SLOT - [5:0] */ - -/* - * R787 (0x313) - AIF1RX Channel 4 Configuration - */ -#define WM8996_AIF1RX_CHAN4_DAT_INV 0x8000 /* AIF1RX_CHAN4_DAT_INV */ -#define WM8996_AIF1RX_CHAN4_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN4_DAT_INV */ -#define WM8996_AIF1RX_CHAN4_DAT_INV_SHIFT 15 /* AIF1RX_CHAN4_DAT_INV */ -#define WM8996_AIF1RX_CHAN4_DAT_INV_WIDTH 1 /* AIF1RX_CHAN4_DAT_INV */ -#define WM8996_AIF1RX_CHAN4_SPACING_MASK 0x7E00 /* AIF1RX_CHAN4_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN4_SPACING_SHIFT 9 /* AIF1RX_CHAN4_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN4_SPACING_WIDTH 6 /* AIF1RX_CHAN4_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN4_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN4_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN4_SLOTS_SHIFT 6 /* AIF1RX_CHAN4_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN4_SLOTS_WIDTH 3 /* AIF1RX_CHAN4_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN4_START_SLOT_MASK 0x003F /* AIF1RX_CHAN4_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN4_START_SLOT_SHIFT 0 /* AIF1RX_CHAN4_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN4_START_SLOT_WIDTH 6 /* AIF1RX_CHAN4_START_SLOT - [5:0] */ - -/* - * R788 (0x314) - AIF1RX Channel 5 Configuration - */ -#define WM8996_AIF1RX_CHAN5_DAT_INV 0x8000 /* AIF1RX_CHAN5_DAT_INV */ -#define WM8996_AIF1RX_CHAN5_DAT_INV_MASK 0x8000 /* AIF1RX_CHAN5_DAT_INV */ -#define WM8996_AIF1RX_CHAN5_DAT_INV_SHIFT 15 /* AIF1RX_CHAN5_DAT_INV */ -#define WM8996_AIF1RX_CHAN5_DAT_INV_WIDTH 1 /* AIF1RX_CHAN5_DAT_INV */ -#define WM8996_AIF1RX_CHAN5_SPACING_MASK 0x7E00 /* AIF1RX_CHAN5_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN5_SPACING_SHIFT 9 /* AIF1RX_CHAN5_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN5_SPACING_WIDTH 6 /* AIF1RX_CHAN5_SPACING - [14:9] */ -#define WM8996_AIF1RX_CHAN5_SLOTS_MASK 0x01C0 /* AIF1RX_CHAN5_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN5_SLOTS_SHIFT 6 /* AIF1RX_CHAN5_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN5_SLOTS_WIDTH 3 /* AIF1RX_CHAN5_SLOTS - [8:6] */ -#define WM8996_AIF1RX_CHAN5_START_SLOT_MASK 0x003F /* AIF1RX_CHAN5_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN5_START_SLOT_SHIFT 0 /* AIF1RX_CHAN5_START_SLOT - [5:0] */ -#define WM8996_AIF1RX_CHAN5_START_SLOT_WIDTH 6 /* AIF1RX_CHAN5_START_SLOT - [5:0] */ - -/* - * R789 (0x315) - AIF1RX Mono Configuration - */ -#define WM8996_AIF1RX_CHAN4_MONO_MODE 0x0004 /* AIF1RX_CHAN4_MONO_MODE */ -#define WM8996_AIF1RX_CHAN4_MONO_MODE_MASK 0x0004 /* AIF1RX_CHAN4_MONO_MODE */ -#define WM8996_AIF1RX_CHAN4_MONO_MODE_SHIFT 2 /* AIF1RX_CHAN4_MONO_MODE */ -#define WM8996_AIF1RX_CHAN4_MONO_MODE_WIDTH 1 /* AIF1RX_CHAN4_MONO_MODE */ -#define WM8996_AIF1RX_CHAN2_MONO_MODE 0x0002 /* AIF1RX_CHAN2_MONO_MODE */ -#define WM8996_AIF1RX_CHAN2_MONO_MODE_MASK 0x0002 /* AIF1RX_CHAN2_MONO_MODE */ -#define WM8996_AIF1RX_CHAN2_MONO_MODE_SHIFT 1 /* AIF1RX_CHAN2_MONO_MODE */ -#define WM8996_AIF1RX_CHAN2_MONO_MODE_WIDTH 1 /* AIF1RX_CHAN2_MONO_MODE */ -#define WM8996_AIF1RX_CHAN0_MONO_MODE 0x0001 /* AIF1RX_CHAN0_MONO_MODE */ -#define WM8996_AIF1RX_CHAN0_MONO_MODE_MASK 0x0001 /* AIF1RX_CHAN0_MONO_MODE */ -#define WM8996_AIF1RX_CHAN0_MONO_MODE_SHIFT 0 /* AIF1RX_CHAN0_MONO_MODE */ -#define WM8996_AIF1RX_CHAN0_MONO_MODE_WIDTH 1 /* AIF1RX_CHAN0_MONO_MODE */ - -/* - * R794 (0x31A) - AIF1TX Test - */ -#define WM8996_AIF1TX45_DITHER_ENA 0x0004 /* AIF1TX45_DITHER_ENA */ -#define WM8996_AIF1TX45_DITHER_ENA_MASK 0x0004 /* AIF1TX45_DITHER_ENA */ -#define WM8996_AIF1TX45_DITHER_ENA_SHIFT 2 /* AIF1TX45_DITHER_ENA */ -#define WM8996_AIF1TX45_DITHER_ENA_WIDTH 1 /* AIF1TX45_DITHER_ENA */ -#define WM8996_AIF1TX23_DITHER_ENA 0x0002 /* AIF1TX23_DITHER_ENA */ -#define WM8996_AIF1TX23_DITHER_ENA_MASK 0x0002 /* AIF1TX23_DITHER_ENA */ -#define WM8996_AIF1TX23_DITHER_ENA_SHIFT 1 /* AIF1TX23_DITHER_ENA */ -#define WM8996_AIF1TX23_DITHER_ENA_WIDTH 1 /* AIF1TX23_DITHER_ENA */ -#define WM8996_AIF1TX01_DITHER_ENA 0x0001 /* AIF1TX01_DITHER_ENA */ -#define WM8996_AIF1TX01_DITHER_ENA_MASK 0x0001 /* AIF1TX01_DITHER_ENA */ -#define WM8996_AIF1TX01_DITHER_ENA_SHIFT 0 /* AIF1TX01_DITHER_ENA */ -#define WM8996_AIF1TX01_DITHER_ENA_WIDTH 1 /* AIF1TX01_DITHER_ENA */ - -/* - * R800 (0x320) - AIF2 Control - */ -#define WM8996_AIF2_TRI 0x0004 /* AIF2_TRI */ -#define WM8996_AIF2_TRI_MASK 0x0004 /* AIF2_TRI */ -#define WM8996_AIF2_TRI_SHIFT 2 /* AIF2_TRI */ -#define WM8996_AIF2_TRI_WIDTH 1 /* AIF2_TRI */ -#define WM8996_AIF2_FMT_MASK 0x0003 /* AIF2_FMT - [1:0] */ -#define WM8996_AIF2_FMT_SHIFT 0 /* AIF2_FMT - [1:0] */ -#define WM8996_AIF2_FMT_WIDTH 2 /* AIF2_FMT - [1:0] */ - -/* - * R801 (0x321) - AIF2 BCLK - */ -#define WM8996_AIF2_BCLK_INV 0x0400 /* AIF2_BCLK_INV */ -#define WM8996_AIF2_BCLK_INV_MASK 0x0400 /* AIF2_BCLK_INV */ -#define WM8996_AIF2_BCLK_INV_SHIFT 10 /* AIF2_BCLK_INV */ -#define WM8996_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */ -#define WM8996_AIF2_BCLK_FRC 0x0200 /* AIF2_BCLK_FRC */ -#define WM8996_AIF2_BCLK_FRC_MASK 0x0200 /* AIF2_BCLK_FRC */ -#define WM8996_AIF2_BCLK_FRC_SHIFT 9 /* AIF2_BCLK_FRC */ -#define WM8996_AIF2_BCLK_FRC_WIDTH 1 /* AIF2_BCLK_FRC */ -#define WM8996_AIF2_BCLK_MSTR 0x0100 /* AIF2_BCLK_MSTR */ -#define WM8996_AIF2_BCLK_MSTR_MASK 0x0100 /* AIF2_BCLK_MSTR */ -#define WM8996_AIF2_BCLK_MSTR_SHIFT 8 /* AIF2_BCLK_MSTR */ -#define WM8996_AIF2_BCLK_MSTR_WIDTH 1 /* AIF2_BCLK_MSTR */ -#define WM8996_AIF2_BCLK_DIV_MASK 0x000F /* AIF2_BCLK_DIV - [3:0] */ -#define WM8996_AIF2_BCLK_DIV_SHIFT 0 /* AIF2_BCLK_DIV - [3:0] */ -#define WM8996_AIF2_BCLK_DIV_WIDTH 4 /* AIF2_BCLK_DIV - [3:0] */ - -/* - * R802 (0x322) - AIF2 TX LRCLK(1) - */ -#define WM8996_AIF2TX_RATE_MASK 0x07FF /* AIF2TX_RATE - [10:0] */ -#define WM8996_AIF2TX_RATE_SHIFT 0 /* AIF2TX_RATE - [10:0] */ -#define WM8996_AIF2TX_RATE_WIDTH 11 /* AIF2TX_RATE - [10:0] */ - -/* - * R803 (0x323) - AIF2 TX LRCLK(2) - */ -#define WM8996_AIF2TX_LRCLK_MODE 0x0008 /* AIF2TX_LRCLK_MODE */ -#define WM8996_AIF2TX_LRCLK_MODE_MASK 0x0008 /* AIF2TX_LRCLK_MODE */ -#define WM8996_AIF2TX_LRCLK_MODE_SHIFT 3 /* AIF2TX_LRCLK_MODE */ -#define WM8996_AIF2TX_LRCLK_MODE_WIDTH 1 /* AIF2TX_LRCLK_MODE */ -#define WM8996_AIF2TX_LRCLK_INV 0x0004 /* AIF2TX_LRCLK_INV */ -#define WM8996_AIF2TX_LRCLK_INV_MASK 0x0004 /* AIF2TX_LRCLK_INV */ -#define WM8996_AIF2TX_LRCLK_INV_SHIFT 2 /* AIF2TX_LRCLK_INV */ -#define WM8996_AIF2TX_LRCLK_INV_WIDTH 1 /* AIF2TX_LRCLK_INV */ -#define WM8996_AIF2TX_LRCLK_FRC 0x0002 /* AIF2TX_LRCLK_FRC */ -#define WM8996_AIF2TX_LRCLK_FRC_MASK 0x0002 /* AIF2TX_LRCLK_FRC */ -#define WM8996_AIF2TX_LRCLK_FRC_SHIFT 1 /* AIF2TX_LRCLK_FRC */ -#define WM8996_AIF2TX_LRCLK_FRC_WIDTH 1 /* AIF2TX_LRCLK_FRC */ -#define WM8996_AIF2TX_LRCLK_MSTR 0x0001 /* AIF2TX_LRCLK_MSTR */ -#define WM8996_AIF2TX_LRCLK_MSTR_MASK 0x0001 /* AIF2TX_LRCLK_MSTR */ -#define WM8996_AIF2TX_LRCLK_MSTR_SHIFT 0 /* AIF2TX_LRCLK_MSTR */ -#define WM8996_AIF2TX_LRCLK_MSTR_WIDTH 1 /* AIF2TX_LRCLK_MSTR */ - -/* - * R804 (0x324) - AIF2 RX LRCLK(1) - */ -#define WM8996_AIF2RX_RATE_MASK 0x07FF /* AIF2RX_RATE - [10:0] */ -#define WM8996_AIF2RX_RATE_SHIFT 0 /* AIF2RX_RATE - [10:0] */ -#define WM8996_AIF2RX_RATE_WIDTH 11 /* AIF2RX_RATE - [10:0] */ - -/* - * R805 (0x325) - AIF2 RX LRCLK(2) - */ -#define WM8996_AIF2RX_LRCLK_INV 0x0004 /* AIF2RX_LRCLK_INV */ -#define WM8996_AIF2RX_LRCLK_INV_MASK 0x0004 /* AIF2RX_LRCLK_INV */ -#define WM8996_AIF2RX_LRCLK_INV_SHIFT 2 /* AIF2RX_LRCLK_INV */ -#define WM8996_AIF2RX_LRCLK_INV_WIDTH 1 /* AIF2RX_LRCLK_INV */ -#define WM8996_AIF2RX_LRCLK_FRC 0x0002 /* AIF2RX_LRCLK_FRC */ -#define WM8996_AIF2RX_LRCLK_FRC_MASK 0x0002 /* AIF2RX_LRCLK_FRC */ -#define WM8996_AIF2RX_LRCLK_FRC_SHIFT 1 /* AIF2RX_LRCLK_FRC */ -#define WM8996_AIF2RX_LRCLK_FRC_WIDTH 1 /* AIF2RX_LRCLK_FRC */ -#define WM8996_AIF2RX_LRCLK_MSTR 0x0001 /* AIF2RX_LRCLK_MSTR */ -#define WM8996_AIF2RX_LRCLK_MSTR_MASK 0x0001 /* AIF2RX_LRCLK_MSTR */ -#define WM8996_AIF2RX_LRCLK_MSTR_SHIFT 0 /* AIF2RX_LRCLK_MSTR */ -#define WM8996_AIF2RX_LRCLK_MSTR_WIDTH 1 /* AIF2RX_LRCLK_MSTR */ - -/* - * R806 (0x326) - AIF2TX Data Configuration (1) - */ -#define WM8996_AIF2TX_WL_MASK 0xFF00 /* AIF2TX_WL - [15:8] */ -#define WM8996_AIF2TX_WL_SHIFT 8 /* AIF2TX_WL - [15:8] */ -#define WM8996_AIF2TX_WL_WIDTH 8 /* AIF2TX_WL - [15:8] */ -#define WM8996_AIF2TX_SLOT_LEN_MASK 0x00FF /* AIF2TX_SLOT_LEN - [7:0] */ -#define WM8996_AIF2TX_SLOT_LEN_SHIFT 0 /* AIF2TX_SLOT_LEN - [7:0] */ -#define WM8996_AIF2TX_SLOT_LEN_WIDTH 8 /* AIF2TX_SLOT_LEN - [7:0] */ - -/* - * R807 (0x327) - AIF2TX Data Configuration (2) - */ -#define WM8996_AIF2TX_DAT_TRI 0x0001 /* AIF2TX_DAT_TRI */ -#define WM8996_AIF2TX_DAT_TRI_MASK 0x0001 /* AIF2TX_DAT_TRI */ -#define WM8996_AIF2TX_DAT_TRI_SHIFT 0 /* AIF2TX_DAT_TRI */ -#define WM8996_AIF2TX_DAT_TRI_WIDTH 1 /* AIF2TX_DAT_TRI */ - -/* - * R808 (0x328) - AIF2RX Data Configuration - */ -#define WM8996_AIF2RX_WL_MASK 0xFF00 /* AIF2RX_WL - [15:8] */ -#define WM8996_AIF2RX_WL_SHIFT 8 /* AIF2RX_WL - [15:8] */ -#define WM8996_AIF2RX_WL_WIDTH 8 /* AIF2RX_WL - [15:8] */ -#define WM8996_AIF2RX_SLOT_LEN_MASK 0x00FF /* AIF2RX_SLOT_LEN - [7:0] */ -#define WM8996_AIF2RX_SLOT_LEN_SHIFT 0 /* AIF2RX_SLOT_LEN - [7:0] */ -#define WM8996_AIF2RX_SLOT_LEN_WIDTH 8 /* AIF2RX_SLOT_LEN - [7:0] */ - -/* - * R809 (0x329) - AIF2TX Channel 0 Configuration - */ -#define WM8996_AIF2TX_CHAN0_DAT_INV 0x8000 /* AIF2TX_CHAN0_DAT_INV */ -#define WM8996_AIF2TX_CHAN0_DAT_INV_MASK 0x8000 /* AIF2TX_CHAN0_DAT_INV */ -#define WM8996_AIF2TX_CHAN0_DAT_INV_SHIFT 15 /* AIF2TX_CHAN0_DAT_INV */ -#define WM8996_AIF2TX_CHAN0_DAT_INV_WIDTH 1 /* AIF2TX_CHAN0_DAT_INV */ -#define WM8996_AIF2TX_CHAN0_SPACING_MASK 0x7E00 /* AIF2TX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF2TX_CHAN0_SPACING_SHIFT 9 /* AIF2TX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF2TX_CHAN0_SPACING_WIDTH 6 /* AIF2TX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF2TX_CHAN0_SLOTS_MASK 0x01C0 /* AIF2TX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF2TX_CHAN0_SLOTS_SHIFT 6 /* AIF2TX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF2TX_CHAN0_SLOTS_WIDTH 3 /* AIF2TX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF2TX_CHAN0_START_SLOT_MASK 0x003F /* AIF2TX_CHAN0_START_SLOT - [5:0] */ -#define WM8996_AIF2TX_CHAN0_START_SLOT_SHIFT 0 /* AIF2TX_CHAN0_START_SLOT - [5:0] */ -#define WM8996_AIF2TX_CHAN0_START_SLOT_WIDTH 6 /* AIF2TX_CHAN0_START_SLOT - [5:0] */ - -/* - * R810 (0x32A) - AIF2TX Channel 1 Configuration - */ -#define WM8996_AIF2TX_CHAN1_DAT_INV 0x8000 /* AIF2TX_CHAN1_DAT_INV */ -#define WM8996_AIF2TX_CHAN1_DAT_INV_MASK 0x8000 /* AIF2TX_CHAN1_DAT_INV */ -#define WM8996_AIF2TX_CHAN1_DAT_INV_SHIFT 15 /* AIF2TX_CHAN1_DAT_INV */ -#define WM8996_AIF2TX_CHAN1_DAT_INV_WIDTH 1 /* AIF2TX_CHAN1_DAT_INV */ -#define WM8996_AIF2TX_CHAN1_SPACING_MASK 0x7E00 /* AIF2TX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF2TX_CHAN1_SPACING_SHIFT 9 /* AIF2TX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF2TX_CHAN1_SPACING_WIDTH 6 /* AIF2TX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF2TX_CHAN1_SLOTS_MASK 0x01C0 /* AIF2TX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF2TX_CHAN1_SLOTS_SHIFT 6 /* AIF2TX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF2TX_CHAN1_SLOTS_WIDTH 3 /* AIF2TX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF2TX_CHAN1_START_SLOT_MASK 0x003F /* AIF2TX_CHAN1_START_SLOT - [5:0] */ -#define WM8996_AIF2TX_CHAN1_START_SLOT_SHIFT 0 /* AIF2TX_CHAN1_START_SLOT - [5:0] */ -#define WM8996_AIF2TX_CHAN1_START_SLOT_WIDTH 6 /* AIF2TX_CHAN1_START_SLOT - [5:0] */ - -/* - * R811 (0x32B) - AIF2RX Channel 0 Configuration - */ -#define WM8996_AIF2RX_CHAN0_DAT_INV 0x8000 /* AIF2RX_CHAN0_DAT_INV */ -#define WM8996_AIF2RX_CHAN0_DAT_INV_MASK 0x8000 /* AIF2RX_CHAN0_DAT_INV */ -#define WM8996_AIF2RX_CHAN0_DAT_INV_SHIFT 15 /* AIF2RX_CHAN0_DAT_INV */ -#define WM8996_AIF2RX_CHAN0_DAT_INV_WIDTH 1 /* AIF2RX_CHAN0_DAT_INV */ -#define WM8996_AIF2RX_CHAN0_SPACING_MASK 0x7E00 /* AIF2RX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF2RX_CHAN0_SPACING_SHIFT 9 /* AIF2RX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF2RX_CHAN0_SPACING_WIDTH 6 /* AIF2RX_CHAN0_SPACING - [14:9] */ -#define WM8996_AIF2RX_CHAN0_SLOTS_MASK 0x01C0 /* AIF2RX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF2RX_CHAN0_SLOTS_SHIFT 6 /* AIF2RX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF2RX_CHAN0_SLOTS_WIDTH 3 /* AIF2RX_CHAN0_SLOTS - [8:6] */ -#define WM8996_AIF2RX_CHAN0_START_SLOT_MASK 0x003F /* AIF2RX_CHAN0_START_SLOT - [5:0] */ -#define WM8996_AIF2RX_CHAN0_START_SLOT_SHIFT 0 /* AIF2RX_CHAN0_START_SLOT - [5:0] */ -#define WM8996_AIF2RX_CHAN0_START_SLOT_WIDTH 6 /* AIF2RX_CHAN0_START_SLOT - [5:0] */ - -/* - * R812 (0x32C) - AIF2RX Channel 1 Configuration - */ -#define WM8996_AIF2RX_CHAN1_DAT_INV 0x8000 /* AIF2RX_CHAN1_DAT_INV */ -#define WM8996_AIF2RX_CHAN1_DAT_INV_MASK 0x8000 /* AIF2RX_CHAN1_DAT_INV */ -#define WM8996_AIF2RX_CHAN1_DAT_INV_SHIFT 15 /* AIF2RX_CHAN1_DAT_INV */ -#define WM8996_AIF2RX_CHAN1_DAT_INV_WIDTH 1 /* AIF2RX_CHAN1_DAT_INV */ -#define WM8996_AIF2RX_CHAN1_SPACING_MASK 0x7E00 /* AIF2RX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF2RX_CHAN1_SPACING_SHIFT 9 /* AIF2RX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF2RX_CHAN1_SPACING_WIDTH 6 /* AIF2RX_CHAN1_SPACING - [14:9] */ -#define WM8996_AIF2RX_CHAN1_SLOTS_MASK 0x01C0 /* AIF2RX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF2RX_CHAN1_SLOTS_SHIFT 6 /* AIF2RX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF2RX_CHAN1_SLOTS_WIDTH 3 /* AIF2RX_CHAN1_SLOTS - [8:6] */ -#define WM8996_AIF2RX_CHAN1_START_SLOT_MASK 0x003F /* AIF2RX_CHAN1_START_SLOT - [5:0] */ -#define WM8996_AIF2RX_CHAN1_START_SLOT_SHIFT 0 /* AIF2RX_CHAN1_START_SLOT - [5:0] */ -#define WM8996_AIF2RX_CHAN1_START_SLOT_WIDTH 6 /* AIF2RX_CHAN1_START_SLOT - [5:0] */ - -/* - * R813 (0x32D) - AIF2RX Mono Configuration - */ -#define WM8996_AIF2RX_CHAN0_MONO_MODE 0x0001 /* AIF2RX_CHAN0_MONO_MODE */ -#define WM8996_AIF2RX_CHAN0_MONO_MODE_MASK 0x0001 /* AIF2RX_CHAN0_MONO_MODE */ -#define WM8996_AIF2RX_CHAN0_MONO_MODE_SHIFT 0 /* AIF2RX_CHAN0_MONO_MODE */ -#define WM8996_AIF2RX_CHAN0_MONO_MODE_WIDTH 1 /* AIF2RX_CHAN0_MONO_MODE */ - -/* - * R815 (0x32F) - AIF2TX Test - */ -#define WM8996_AIF2TX_DITHER_ENA 0x0001 /* AIF2TX_DITHER_ENA */ -#define WM8996_AIF2TX_DITHER_ENA_MASK 0x0001 /* AIF2TX_DITHER_ENA */ -#define WM8996_AIF2TX_DITHER_ENA_SHIFT 0 /* AIF2TX_DITHER_ENA */ -#define WM8996_AIF2TX_DITHER_ENA_WIDTH 1 /* AIF2TX_DITHER_ENA */ - -/* - * R1024 (0x400) - DSP1 TX Left Volume - */ -#define WM8996_DSP1TX_VU 0x0100 /* DSP1TX_VU */ -#define WM8996_DSP1TX_VU_MASK 0x0100 /* DSP1TX_VU */ -#define WM8996_DSP1TX_VU_SHIFT 8 /* DSP1TX_VU */ -#define WM8996_DSP1TX_VU_WIDTH 1 /* DSP1TX_VU */ -#define WM8996_DSP1TXL_VOL_MASK 0x00FF /* DSP1TXL_VOL - [7:0] */ -#define WM8996_DSP1TXL_VOL_SHIFT 0 /* DSP1TXL_VOL - [7:0] */ -#define WM8996_DSP1TXL_VOL_WIDTH 8 /* DSP1TXL_VOL - [7:0] */ - -/* - * R1025 (0x401) - DSP1 TX Right Volume - */ -#define WM8996_DSP1TX_VU 0x0100 /* DSP1TX_VU */ -#define WM8996_DSP1TX_VU_MASK 0x0100 /* DSP1TX_VU */ -#define WM8996_DSP1TX_VU_SHIFT 8 /* DSP1TX_VU */ -#define WM8996_DSP1TX_VU_WIDTH 1 /* DSP1TX_VU */ -#define WM8996_DSP1TXR_VOL_MASK 0x00FF /* DSP1TXR_VOL - [7:0] */ -#define WM8996_DSP1TXR_VOL_SHIFT 0 /* DSP1TXR_VOL - [7:0] */ -#define WM8996_DSP1TXR_VOL_WIDTH 8 /* DSP1TXR_VOL - [7:0] */ - -/* - * R1026 (0x402) - DSP1 RX Left Volume - */ -#define WM8996_DSP1RX_VU 0x0100 /* DSP1RX_VU */ -#define WM8996_DSP1RX_VU_MASK 0x0100 /* DSP1RX_VU */ -#define WM8996_DSP1RX_VU_SHIFT 8 /* DSP1RX_VU */ -#define WM8996_DSP1RX_VU_WIDTH 1 /* DSP1RX_VU */ -#define WM8996_DSP1RXL_VOL_MASK 0x00FF /* DSP1RXL_VOL - [7:0] */ -#define WM8996_DSP1RXL_VOL_SHIFT 0 /* DSP1RXL_VOL - [7:0] */ -#define WM8996_DSP1RXL_VOL_WIDTH 8 /* DSP1RXL_VOL - [7:0] */ - -/* - * R1027 (0x403) - DSP1 RX Right Volume - */ -#define WM8996_DSP1RX_VU 0x0100 /* DSP1RX_VU */ -#define WM8996_DSP1RX_VU_MASK 0x0100 /* DSP1RX_VU */ -#define WM8996_DSP1RX_VU_SHIFT 8 /* DSP1RX_VU */ -#define WM8996_DSP1RX_VU_WIDTH 1 /* DSP1RX_VU */ -#define WM8996_DSP1RXR_VOL_MASK 0x00FF /* DSP1RXR_VOL - [7:0] */ -#define WM8996_DSP1RXR_VOL_SHIFT 0 /* DSP1RXR_VOL - [7:0] */ -#define WM8996_DSP1RXR_VOL_WIDTH 8 /* DSP1RXR_VOL - [7:0] */ - -/* - * R1040 (0x410) - DSP1 TX Filters - */ -#define WM8996_DSP1TX_NF 0x2000 /* DSP1TX_NF */ -#define WM8996_DSP1TX_NF_MASK 0x2000 /* DSP1TX_NF */ -#define WM8996_DSP1TX_NF_SHIFT 13 /* DSP1TX_NF */ -#define WM8996_DSP1TX_NF_WIDTH 1 /* DSP1TX_NF */ -#define WM8996_DSP1TXL_HPF 0x1000 /* DSP1TXL_HPF */ -#define WM8996_DSP1TXL_HPF_MASK 0x1000 /* DSP1TXL_HPF */ -#define WM8996_DSP1TXL_HPF_SHIFT 12 /* DSP1TXL_HPF */ -#define WM8996_DSP1TXL_HPF_WIDTH 1 /* DSP1TXL_HPF */ -#define WM8996_DSP1TXR_HPF 0x0800 /* DSP1TXR_HPF */ -#define WM8996_DSP1TXR_HPF_MASK 0x0800 /* DSP1TXR_HPF */ -#define WM8996_DSP1TXR_HPF_SHIFT 11 /* DSP1TXR_HPF */ -#define WM8996_DSP1TXR_HPF_WIDTH 1 /* DSP1TXR_HPF */ -#define WM8996_DSP1TX_HPF_MODE_MASK 0x0018 /* DSP1TX_HPF_MODE - [4:3] */ -#define WM8996_DSP1TX_HPF_MODE_SHIFT 3 /* DSP1TX_HPF_MODE - [4:3] */ -#define WM8996_DSP1TX_HPF_MODE_WIDTH 2 /* DSP1TX_HPF_MODE - [4:3] */ -#define WM8996_DSP1TX_HPF_CUT_MASK 0x0007 /* DSP1TX_HPF_CUT - [2:0] */ -#define WM8996_DSP1TX_HPF_CUT_SHIFT 0 /* DSP1TX_HPF_CUT - [2:0] */ -#define WM8996_DSP1TX_HPF_CUT_WIDTH 3 /* DSP1TX_HPF_CUT - [2:0] */ - -/* - * R1056 (0x420) - DSP1 RX Filters (1) - */ -#define WM8996_DSP1RX_MUTE 0x0200 /* DSP1RX_MUTE */ -#define WM8996_DSP1RX_MUTE_MASK 0x0200 /* DSP1RX_MUTE */ -#define WM8996_DSP1RX_MUTE_SHIFT 9 /* DSP1RX_MUTE */ -#define WM8996_DSP1RX_MUTE_WIDTH 1 /* DSP1RX_MUTE */ -#define WM8996_DSP1RX_MONO 0x0080 /* DSP1RX_MONO */ -#define WM8996_DSP1RX_MONO_MASK 0x0080 /* DSP1RX_MONO */ -#define WM8996_DSP1RX_MONO_SHIFT 7 /* DSP1RX_MONO */ -#define WM8996_DSP1RX_MONO_WIDTH 1 /* DSP1RX_MONO */ -#define WM8996_DSP1RX_MUTERATE 0x0020 /* DSP1RX_MUTERATE */ -#define WM8996_DSP1RX_MUTERATE_MASK 0x0020 /* DSP1RX_MUTERATE */ -#define WM8996_DSP1RX_MUTERATE_SHIFT 5 /* DSP1RX_MUTERATE */ -#define WM8996_DSP1RX_MUTERATE_WIDTH 1 /* DSP1RX_MUTERATE */ -#define WM8996_DSP1RX_UNMUTE_RAMP 0x0010 /* DSP1RX_UNMUTE_RAMP */ -#define WM8996_DSP1RX_UNMUTE_RAMP_MASK 0x0010 /* DSP1RX_UNMUTE_RAMP */ -#define WM8996_DSP1RX_UNMUTE_RAMP_SHIFT 4 /* DSP1RX_UNMUTE_RAMP */ -#define WM8996_DSP1RX_UNMUTE_RAMP_WIDTH 1 /* DSP1RX_UNMUTE_RAMP */ - -/* - * R1057 (0x421) - DSP1 RX Filters (2) - */ -#define WM8996_DSP1RX_3D_GAIN_MASK 0x3E00 /* DSP1RX_3D_GAIN - [13:9] */ -#define WM8996_DSP1RX_3D_GAIN_SHIFT 9 /* DSP1RX_3D_GAIN - [13:9] */ -#define WM8996_DSP1RX_3D_GAIN_WIDTH 5 /* DSP1RX_3D_GAIN - [13:9] */ -#define WM8996_DSP1RX_3D_ENA 0x0100 /* DSP1RX_3D_ENA */ -#define WM8996_DSP1RX_3D_ENA_MASK 0x0100 /* DSP1RX_3D_ENA */ -#define WM8996_DSP1RX_3D_ENA_SHIFT 8 /* DSP1RX_3D_ENA */ -#define WM8996_DSP1RX_3D_ENA_WIDTH 1 /* DSP1RX_3D_ENA */ - -/* - * R1088 (0x440) - DSP1 DRC (1) - */ -#define WM8996_DSP1DRC_SIG_DET_RMS_MASK 0xF800 /* DSP1DRC_SIG_DET_RMS - [15:11] */ -#define WM8996_DSP1DRC_SIG_DET_RMS_SHIFT 11 /* DSP1DRC_SIG_DET_RMS - [15:11] */ -#define WM8996_DSP1DRC_SIG_DET_RMS_WIDTH 5 /* DSP1DRC_SIG_DET_RMS - [15:11] */ -#define WM8996_DSP1DRC_SIG_DET_PK_MASK 0x0600 /* DSP1DRC_SIG_DET_PK - [10:9] */ -#define WM8996_DSP1DRC_SIG_DET_PK_SHIFT 9 /* DSP1DRC_SIG_DET_PK - [10:9] */ -#define WM8996_DSP1DRC_SIG_DET_PK_WIDTH 2 /* DSP1DRC_SIG_DET_PK - [10:9] */ -#define WM8996_DSP1DRC_NG_ENA 0x0100 /* DSP1DRC_NG_ENA */ -#define WM8996_DSP1DRC_NG_ENA_MASK 0x0100 /* DSP1DRC_NG_ENA */ -#define WM8996_DSP1DRC_NG_ENA_SHIFT 8 /* DSP1DRC_NG_ENA */ -#define WM8996_DSP1DRC_NG_ENA_WIDTH 1 /* DSP1DRC_NG_ENA */ -#define WM8996_DSP1DRC_SIG_DET_MODE 0x0080 /* DSP1DRC_SIG_DET_MODE */ -#define WM8996_DSP1DRC_SIG_DET_MODE_MASK 0x0080 /* DSP1DRC_SIG_DET_MODE */ -#define WM8996_DSP1DRC_SIG_DET_MODE_SHIFT 7 /* DSP1DRC_SIG_DET_MODE */ -#define WM8996_DSP1DRC_SIG_DET_MODE_WIDTH 1 /* DSP1DRC_SIG_DET_MODE */ -#define WM8996_DSP1DRC_SIG_DET 0x0040 /* DSP1DRC_SIG_DET */ -#define WM8996_DSP1DRC_SIG_DET_MASK 0x0040 /* DSP1DRC_SIG_DET */ -#define WM8996_DSP1DRC_SIG_DET_SHIFT 6 /* DSP1DRC_SIG_DET */ -#define WM8996_DSP1DRC_SIG_DET_WIDTH 1 /* DSP1DRC_SIG_DET */ -#define WM8996_DSP1DRC_KNEE2_OP_ENA 0x0020 /* DSP1DRC_KNEE2_OP_ENA */ -#define WM8996_DSP1DRC_KNEE2_OP_ENA_MASK 0x0020 /* DSP1DRC_KNEE2_OP_ENA */ -#define WM8996_DSP1DRC_KNEE2_OP_ENA_SHIFT 5 /* DSP1DRC_KNEE2_OP_ENA */ -#define WM8996_DSP1DRC_KNEE2_OP_ENA_WIDTH 1 /* DSP1DRC_KNEE2_OP_ENA */ -#define WM8996_DSP1DRC_QR 0x0010 /* DSP1DRC_QR */ -#define WM8996_DSP1DRC_QR_MASK 0x0010 /* DSP1DRC_QR */ -#define WM8996_DSP1DRC_QR_SHIFT 4 /* DSP1DRC_QR */ -#define WM8996_DSP1DRC_QR_WIDTH 1 /* DSP1DRC_QR */ -#define WM8996_DSP1DRC_ANTICLIP 0x0008 /* DSP1DRC_ANTICLIP */ -#define WM8996_DSP1DRC_ANTICLIP_MASK 0x0008 /* DSP1DRC_ANTICLIP */ -#define WM8996_DSP1DRC_ANTICLIP_SHIFT 3 /* DSP1DRC_ANTICLIP */ -#define WM8996_DSP1DRC_ANTICLIP_WIDTH 1 /* DSP1DRC_ANTICLIP */ -#define WM8996_DSP1RX_DRC_ENA 0x0004 /* DSP1RX_DRC_ENA */ -#define WM8996_DSP1RX_DRC_ENA_MASK 0x0004 /* DSP1RX_DRC_ENA */ -#define WM8996_DSP1RX_DRC_ENA_SHIFT 2 /* DSP1RX_DRC_ENA */ -#define WM8996_DSP1RX_DRC_ENA_WIDTH 1 /* DSP1RX_DRC_ENA */ -#define WM8996_DSP1TXL_DRC_ENA 0x0002 /* DSP1TXL_DRC_ENA */ -#define WM8996_DSP1TXL_DRC_ENA_MASK 0x0002 /* DSP1TXL_DRC_ENA */ -#define WM8996_DSP1TXL_DRC_ENA_SHIFT 1 /* DSP1TXL_DRC_ENA */ -#define WM8996_DSP1TXL_DRC_ENA_WIDTH 1 /* DSP1TXL_DRC_ENA */ -#define WM8996_DSP1TXR_DRC_ENA 0x0001 /* DSP1TXR_DRC_ENA */ -#define WM8996_DSP1TXR_DRC_ENA_MASK 0x0001 /* DSP1TXR_DRC_ENA */ -#define WM8996_DSP1TXR_DRC_ENA_SHIFT 0 /* DSP1TXR_DRC_ENA */ -#define WM8996_DSP1TXR_DRC_ENA_WIDTH 1 /* DSP1TXR_DRC_ENA */ - -/* - * R1089 (0x441) - DSP1 DRC (2) - */ -#define WM8996_DSP1DRC_ATK_MASK 0x1E00 /* DSP1DRC_ATK - [12:9] */ -#define WM8996_DSP1DRC_ATK_SHIFT 9 /* DSP1DRC_ATK - [12:9] */ -#define WM8996_DSP1DRC_ATK_WIDTH 4 /* DSP1DRC_ATK - [12:9] */ -#define WM8996_DSP1DRC_DCY_MASK 0x01E0 /* DSP1DRC_DCY - [8:5] */ -#define WM8996_DSP1DRC_DCY_SHIFT 5 /* DSP1DRC_DCY - [8:5] */ -#define WM8996_DSP1DRC_DCY_WIDTH 4 /* DSP1DRC_DCY - [8:5] */ -#define WM8996_DSP1DRC_MINGAIN_MASK 0x001C /* DSP1DRC_MINGAIN - [4:2] */ -#define WM8996_DSP1DRC_MINGAIN_SHIFT 2 /* DSP1DRC_MINGAIN - [4:2] */ -#define WM8996_DSP1DRC_MINGAIN_WIDTH 3 /* DSP1DRC_MINGAIN - [4:2] */ -#define WM8996_DSP1DRC_MAXGAIN_MASK 0x0003 /* DSP1DRC_MAXGAIN - [1:0] */ -#define WM8996_DSP1DRC_MAXGAIN_SHIFT 0 /* DSP1DRC_MAXGAIN - [1:0] */ -#define WM8996_DSP1DRC_MAXGAIN_WIDTH 2 /* DSP1DRC_MAXGAIN - [1:0] */ - -/* - * R1090 (0x442) - DSP1 DRC (3) - */ -#define WM8996_DSP1DRC_NG_MINGAIN_MASK 0xF000 /* DSP1DRC_NG_MINGAIN - [15:12] */ -#define WM8996_DSP1DRC_NG_MINGAIN_SHIFT 12 /* DSP1DRC_NG_MINGAIN - [15:12] */ -#define WM8996_DSP1DRC_NG_MINGAIN_WIDTH 4 /* DSP1DRC_NG_MINGAIN - [15:12] */ -#define WM8996_DSP1DRC_NG_EXP_MASK 0x0C00 /* DSP1DRC_NG_EXP - [11:10] */ -#define WM8996_DSP1DRC_NG_EXP_SHIFT 10 /* DSP1DRC_NG_EXP - [11:10] */ -#define WM8996_DSP1DRC_NG_EXP_WIDTH 2 /* DSP1DRC_NG_EXP - [11:10] */ -#define WM8996_DSP1DRC_QR_THR_MASK 0x0300 /* DSP1DRC_QR_THR - [9:8] */ -#define WM8996_DSP1DRC_QR_THR_SHIFT 8 /* DSP1DRC_QR_THR - [9:8] */ -#define WM8996_DSP1DRC_QR_THR_WIDTH 2 /* DSP1DRC_QR_THR - [9:8] */ -#define WM8996_DSP1DRC_QR_DCY_MASK 0x00C0 /* DSP1DRC_QR_DCY - [7:6] */ -#define WM8996_DSP1DRC_QR_DCY_SHIFT 6 /* DSP1DRC_QR_DCY - [7:6] */ -#define WM8996_DSP1DRC_QR_DCY_WIDTH 2 /* DSP1DRC_QR_DCY - [7:6] */ -#define WM8996_DSP1DRC_HI_COMP_MASK 0x0038 /* DSP1DRC_HI_COMP - [5:3] */ -#define WM8996_DSP1DRC_HI_COMP_SHIFT 3 /* DSP1DRC_HI_COMP - [5:3] */ -#define WM8996_DSP1DRC_HI_COMP_WIDTH 3 /* DSP1DRC_HI_COMP - [5:3] */ -#define WM8996_DSP1DRC_LO_COMP_MASK 0x0007 /* DSP1DRC_LO_COMP - [2:0] */ -#define WM8996_DSP1DRC_LO_COMP_SHIFT 0 /* DSP1DRC_LO_COMP - [2:0] */ -#define WM8996_DSP1DRC_LO_COMP_WIDTH 3 /* DSP1DRC_LO_COMP - [2:0] */ - -/* - * R1091 (0x443) - DSP1 DRC (4) - */ -#define WM8996_DSP1DRC_KNEE_IP_MASK 0x07E0 /* DSP1DRC_KNEE_IP - [10:5] */ -#define WM8996_DSP1DRC_KNEE_IP_SHIFT 5 /* DSP1DRC_KNEE_IP - [10:5] */ -#define WM8996_DSP1DRC_KNEE_IP_WIDTH 6 /* DSP1DRC_KNEE_IP - [10:5] */ -#define WM8996_DSP1DRC_KNEE_OP_MASK 0x001F /* DSP1DRC_KNEE_OP - [4:0] */ -#define WM8996_DSP1DRC_KNEE_OP_SHIFT 0 /* DSP1DRC_KNEE_OP - [4:0] */ -#define WM8996_DSP1DRC_KNEE_OP_WIDTH 5 /* DSP1DRC_KNEE_OP - [4:0] */ - -/* - * R1092 (0x444) - DSP1 DRC (5) - */ -#define WM8996_DSP1DRC_KNEE2_IP_MASK 0x03E0 /* DSP1DRC_KNEE2_IP - [9:5] */ -#define WM8996_DSP1DRC_KNEE2_IP_SHIFT 5 /* DSP1DRC_KNEE2_IP - [9:5] */ -#define WM8996_DSP1DRC_KNEE2_IP_WIDTH 5 /* DSP1DRC_KNEE2_IP - [9:5] */ -#define WM8996_DSP1DRC_KNEE2_OP_MASK 0x001F /* DSP1DRC_KNEE2_OP - [4:0] */ -#define WM8996_DSP1DRC_KNEE2_OP_SHIFT 0 /* DSP1DRC_KNEE2_OP - [4:0] */ -#define WM8996_DSP1DRC_KNEE2_OP_WIDTH 5 /* DSP1DRC_KNEE2_OP - [4:0] */ - -/* - * R1152 (0x480) - DSP1 RX EQ Gains (1) - */ -#define WM8996_DSP1RX_EQ_B1_GAIN_MASK 0xF800 /* DSP1RX_EQ_B1_GAIN - [15:11] */ -#define WM8996_DSP1RX_EQ_B1_GAIN_SHIFT 11 /* DSP1RX_EQ_B1_GAIN - [15:11] */ -#define WM8996_DSP1RX_EQ_B1_GAIN_WIDTH 5 /* DSP1RX_EQ_B1_GAIN - [15:11] */ -#define WM8996_DSP1RX_EQ_B2_GAIN_MASK 0x07C0 /* DSP1RX_EQ_B2_GAIN - [10:6] */ -#define WM8996_DSP1RX_EQ_B2_GAIN_SHIFT 6 /* DSP1RX_EQ_B2_GAIN - [10:6] */ -#define WM8996_DSP1RX_EQ_B2_GAIN_WIDTH 5 /* DSP1RX_EQ_B2_GAIN - [10:6] */ -#define WM8996_DSP1RX_EQ_B3_GAIN_MASK 0x003E /* DSP1RX_EQ_B3_GAIN - [5:1] */ -#define WM8996_DSP1RX_EQ_B3_GAIN_SHIFT 1 /* DSP1RX_EQ_B3_GAIN - [5:1] */ -#define WM8996_DSP1RX_EQ_B3_GAIN_WIDTH 5 /* DSP1RX_EQ_B3_GAIN - [5:1] */ -#define WM8996_DSP1RX_EQ_ENA 0x0001 /* DSP1RX_EQ_ENA */ -#define WM8996_DSP1RX_EQ_ENA_MASK 0x0001 /* DSP1RX_EQ_ENA */ -#define WM8996_DSP1RX_EQ_ENA_SHIFT 0 /* DSP1RX_EQ_ENA */ -#define WM8996_DSP1RX_EQ_ENA_WIDTH 1 /* DSP1RX_EQ_ENA */ - -/* - * R1153 (0x481) - DSP1 RX EQ Gains (2) - */ -#define WM8996_DSP1RX_EQ_B4_GAIN_MASK 0xF800 /* DSP1RX_EQ_B4_GAIN - [15:11] */ -#define WM8996_DSP1RX_EQ_B4_GAIN_SHIFT 11 /* DSP1RX_EQ_B4_GAIN - [15:11] */ -#define WM8996_DSP1RX_EQ_B4_GAIN_WIDTH 5 /* DSP1RX_EQ_B4_GAIN - [15:11] */ -#define WM8996_DSP1RX_EQ_B5_GAIN_MASK 0x07C0 /* DSP1RX_EQ_B5_GAIN - [10:6] */ -#define WM8996_DSP1RX_EQ_B5_GAIN_SHIFT 6 /* DSP1RX_EQ_B5_GAIN - [10:6] */ -#define WM8996_DSP1RX_EQ_B5_GAIN_WIDTH 5 /* DSP1RX_EQ_B5_GAIN - [10:6] */ - -/* - * R1154 (0x482) - DSP1 RX EQ Band 1 A - */ -#define WM8996_DSP1RX_EQ_B1_A_MASK 0xFFFF /* DSP1RX_EQ_B1_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B1_A_SHIFT 0 /* DSP1RX_EQ_B1_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B1_A_WIDTH 16 /* DSP1RX_EQ_B1_A - [15:0] */ - -/* - * R1155 (0x483) - DSP1 RX EQ Band 1 B - */ -#define WM8996_DSP1RX_EQ_B1_B_MASK 0xFFFF /* DSP1RX_EQ_B1_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B1_B_SHIFT 0 /* DSP1RX_EQ_B1_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B1_B_WIDTH 16 /* DSP1RX_EQ_B1_B - [15:0] */ - -/* - * R1156 (0x484) - DSP1 RX EQ Band 1 PG - */ -#define WM8996_DSP1RX_EQ_B1_PG_MASK 0xFFFF /* DSP1RX_EQ_B1_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B1_PG_SHIFT 0 /* DSP1RX_EQ_B1_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B1_PG_WIDTH 16 /* DSP1RX_EQ_B1_PG - [15:0] */ - -/* - * R1157 (0x485) - DSP1 RX EQ Band 2 A - */ -#define WM8996_DSP1RX_EQ_B2_A_MASK 0xFFFF /* DSP1RX_EQ_B2_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B2_A_SHIFT 0 /* DSP1RX_EQ_B2_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B2_A_WIDTH 16 /* DSP1RX_EQ_B2_A - [15:0] */ - -/* - * R1158 (0x486) - DSP1 RX EQ Band 2 B - */ -#define WM8996_DSP1RX_EQ_B2_B_MASK 0xFFFF /* DSP1RX_EQ_B2_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B2_B_SHIFT 0 /* DSP1RX_EQ_B2_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B2_B_WIDTH 16 /* DSP1RX_EQ_B2_B - [15:0] */ - -/* - * R1159 (0x487) - DSP1 RX EQ Band 2 C - */ -#define WM8996_DSP1RX_EQ_B2_C_MASK 0xFFFF /* DSP1RX_EQ_B2_C - [15:0] */ -#define WM8996_DSP1RX_EQ_B2_C_SHIFT 0 /* DSP1RX_EQ_B2_C - [15:0] */ -#define WM8996_DSP1RX_EQ_B2_C_WIDTH 16 /* DSP1RX_EQ_B2_C - [15:0] */ - -/* - * R1160 (0x488) - DSP1 RX EQ Band 2 PG - */ -#define WM8996_DSP1RX_EQ_B2_PG_MASK 0xFFFF /* DSP1RX_EQ_B2_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B2_PG_SHIFT 0 /* DSP1RX_EQ_B2_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B2_PG_WIDTH 16 /* DSP1RX_EQ_B2_PG - [15:0] */ - -/* - * R1161 (0x489) - DSP1 RX EQ Band 3 A - */ -#define WM8996_DSP1RX_EQ_B3_A_MASK 0xFFFF /* DSP1RX_EQ_B3_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B3_A_SHIFT 0 /* DSP1RX_EQ_B3_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B3_A_WIDTH 16 /* DSP1RX_EQ_B3_A - [15:0] */ - -/* - * R1162 (0x48A) - DSP1 RX EQ Band 3 B - */ -#define WM8996_DSP1RX_EQ_B3_B_MASK 0xFFFF /* DSP1RX_EQ_B3_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B3_B_SHIFT 0 /* DSP1RX_EQ_B3_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B3_B_WIDTH 16 /* DSP1RX_EQ_B3_B - [15:0] */ - -/* - * R1163 (0x48B) - DSP1 RX EQ Band 3 C - */ -#define WM8996_DSP1RX_EQ_B3_C_MASK 0xFFFF /* DSP1RX_EQ_B3_C - [15:0] */ -#define WM8996_DSP1RX_EQ_B3_C_SHIFT 0 /* DSP1RX_EQ_B3_C - [15:0] */ -#define WM8996_DSP1RX_EQ_B3_C_WIDTH 16 /* DSP1RX_EQ_B3_C - [15:0] */ - -/* - * R1164 (0x48C) - DSP1 RX EQ Band 3 PG - */ -#define WM8996_DSP1RX_EQ_B3_PG_MASK 0xFFFF /* DSP1RX_EQ_B3_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B3_PG_SHIFT 0 /* DSP1RX_EQ_B3_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B3_PG_WIDTH 16 /* DSP1RX_EQ_B3_PG - [15:0] */ - -/* - * R1165 (0x48D) - DSP1 RX EQ Band 4 A - */ -#define WM8996_DSP1RX_EQ_B4_A_MASK 0xFFFF /* DSP1RX_EQ_B4_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B4_A_SHIFT 0 /* DSP1RX_EQ_B4_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B4_A_WIDTH 16 /* DSP1RX_EQ_B4_A - [15:0] */ - -/* - * R1166 (0x48E) - DSP1 RX EQ Band 4 B - */ -#define WM8996_DSP1RX_EQ_B4_B_MASK 0xFFFF /* DSP1RX_EQ_B4_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B4_B_SHIFT 0 /* DSP1RX_EQ_B4_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B4_B_WIDTH 16 /* DSP1RX_EQ_B4_B - [15:0] */ - -/* - * R1167 (0x48F) - DSP1 RX EQ Band 4 C - */ -#define WM8996_DSP1RX_EQ_B4_C_MASK 0xFFFF /* DSP1RX_EQ_B4_C - [15:0] */ -#define WM8996_DSP1RX_EQ_B4_C_SHIFT 0 /* DSP1RX_EQ_B4_C - [15:0] */ -#define WM8996_DSP1RX_EQ_B4_C_WIDTH 16 /* DSP1RX_EQ_B4_C - [15:0] */ - -/* - * R1168 (0x490) - DSP1 RX EQ Band 4 PG - */ -#define WM8996_DSP1RX_EQ_B4_PG_MASK 0xFFFF /* DSP1RX_EQ_B4_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B4_PG_SHIFT 0 /* DSP1RX_EQ_B4_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B4_PG_WIDTH 16 /* DSP1RX_EQ_B4_PG - [15:0] */ - -/* - * R1169 (0x491) - DSP1 RX EQ Band 5 A - */ -#define WM8996_DSP1RX_EQ_B5_A_MASK 0xFFFF /* DSP1RX_EQ_B5_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B5_A_SHIFT 0 /* DSP1RX_EQ_B5_A - [15:0] */ -#define WM8996_DSP1RX_EQ_B5_A_WIDTH 16 /* DSP1RX_EQ_B5_A - [15:0] */ - -/* - * R1170 (0x492) - DSP1 RX EQ Band 5 B - */ -#define WM8996_DSP1RX_EQ_B5_B_MASK 0xFFFF /* DSP1RX_EQ_B5_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B5_B_SHIFT 0 /* DSP1RX_EQ_B5_B - [15:0] */ -#define WM8996_DSP1RX_EQ_B5_B_WIDTH 16 /* DSP1RX_EQ_B5_B - [15:0] */ - -/* - * R1171 (0x493) - DSP1 RX EQ Band 5 PG - */ -#define WM8996_DSP1RX_EQ_B5_PG_MASK 0xFFFF /* DSP1RX_EQ_B5_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B5_PG_SHIFT 0 /* DSP1RX_EQ_B5_PG - [15:0] */ -#define WM8996_DSP1RX_EQ_B5_PG_WIDTH 16 /* DSP1RX_EQ_B5_PG - [15:0] */ - -/* - * R1280 (0x500) - DSP2 TX Left Volume - */ -#define WM8996_DSP2TX_VU 0x0100 /* DSP2TX_VU */ -#define WM8996_DSP2TX_VU_MASK 0x0100 /* DSP2TX_VU */ -#define WM8996_DSP2TX_VU_SHIFT 8 /* DSP2TX_VU */ -#define WM8996_DSP2TX_VU_WIDTH 1 /* DSP2TX_VU */ -#define WM8996_DSP2TXL_VOL_MASK 0x00FF /* DSP2TXL_VOL - [7:0] */ -#define WM8996_DSP2TXL_VOL_SHIFT 0 /* DSP2TXL_VOL - [7:0] */ -#define WM8996_DSP2TXL_VOL_WIDTH 8 /* DSP2TXL_VOL - [7:0] */ - -/* - * R1281 (0x501) - DSP2 TX Right Volume - */ -#define WM8996_DSP2TX_VU 0x0100 /* DSP2TX_VU */ -#define WM8996_DSP2TX_VU_MASK 0x0100 /* DSP2TX_VU */ -#define WM8996_DSP2TX_VU_SHIFT 8 /* DSP2TX_VU */ -#define WM8996_DSP2TX_VU_WIDTH 1 /* DSP2TX_VU */ -#define WM8996_DSP2TXR_VOL_MASK 0x00FF /* DSP2TXR_VOL - [7:0] */ -#define WM8996_DSP2TXR_VOL_SHIFT 0 /* DSP2TXR_VOL - [7:0] */ -#define WM8996_DSP2TXR_VOL_WIDTH 8 /* DSP2TXR_VOL - [7:0] */ - -/* - * R1282 (0x502) - DSP2 RX Left Volume - */ -#define WM8996_DSP2RX_VU 0x0100 /* DSP2RX_VU */ -#define WM8996_DSP2RX_VU_MASK 0x0100 /* DSP2RX_VU */ -#define WM8996_DSP2RX_VU_SHIFT 8 /* DSP2RX_VU */ -#define WM8996_DSP2RX_VU_WIDTH 1 /* DSP2RX_VU */ -#define WM8996_DSP2RXL_VOL_MASK 0x00FF /* DSP2RXL_VOL - [7:0] */ -#define WM8996_DSP2RXL_VOL_SHIFT 0 /* DSP2RXL_VOL - [7:0] */ -#define WM8996_DSP2RXL_VOL_WIDTH 8 /* DSP2RXL_VOL - [7:0] */ - -/* - * R1283 (0x503) - DSP2 RX Right Volume - */ -#define WM8996_DSP2RX_VU 0x0100 /* DSP2RX_VU */ -#define WM8996_DSP2RX_VU_MASK 0x0100 /* DSP2RX_VU */ -#define WM8996_DSP2RX_VU_SHIFT 8 /* DSP2RX_VU */ -#define WM8996_DSP2RX_VU_WIDTH 1 /* DSP2RX_VU */ -#define WM8996_DSP2RXR_VOL_MASK 0x00FF /* DSP2RXR_VOL - [7:0] */ -#define WM8996_DSP2RXR_VOL_SHIFT 0 /* DSP2RXR_VOL - [7:0] */ -#define WM8996_DSP2RXR_VOL_WIDTH 8 /* DSP2RXR_VOL - [7:0] */ - -/* - * R1296 (0x510) - DSP2 TX Filters - */ -#define WM8996_DSP2TX_NF 0x2000 /* DSP2TX_NF */ -#define WM8996_DSP2TX_NF_MASK 0x2000 /* DSP2TX_NF */ -#define WM8996_DSP2TX_NF_SHIFT 13 /* DSP2TX_NF */ -#define WM8996_DSP2TX_NF_WIDTH 1 /* DSP2TX_NF */ -#define WM8996_DSP2TXL_HPF 0x1000 /* DSP2TXL_HPF */ -#define WM8996_DSP2TXL_HPF_MASK 0x1000 /* DSP2TXL_HPF */ -#define WM8996_DSP2TXL_HPF_SHIFT 12 /* DSP2TXL_HPF */ -#define WM8996_DSP2TXL_HPF_WIDTH 1 /* DSP2TXL_HPF */ -#define WM8996_DSP2TXR_HPF 0x0800 /* DSP2TXR_HPF */ -#define WM8996_DSP2TXR_HPF_MASK 0x0800 /* DSP2TXR_HPF */ -#define WM8996_DSP2TXR_HPF_SHIFT 11 /* DSP2TXR_HPF */ -#define WM8996_DSP2TXR_HPF_WIDTH 1 /* DSP2TXR_HPF */ -#define WM8996_DSP2TX_HPF_MODE_MASK 0x0018 /* DSP2TX_HPF_MODE - [4:3] */ -#define WM8996_DSP2TX_HPF_MODE_SHIFT 3 /* DSP2TX_HPF_MODE - [4:3] */ -#define WM8996_DSP2TX_HPF_MODE_WIDTH 2 /* DSP2TX_HPF_MODE - [4:3] */ -#define WM8996_DSP2TX_HPF_CUT_MASK 0x0007 /* DSP2TX_HPF_CUT - [2:0] */ -#define WM8996_DSP2TX_HPF_CUT_SHIFT 0 /* DSP2TX_HPF_CUT - [2:0] */ -#define WM8996_DSP2TX_HPF_CUT_WIDTH 3 /* DSP2TX_HPF_CUT - [2:0] */ - -/* - * R1312 (0x520) - DSP2 RX Filters (1) - */ -#define WM8996_DSP2RX_MUTE 0x0200 /* DSP2RX_MUTE */ -#define WM8996_DSP2RX_MUTE_MASK 0x0200 /* DSP2RX_MUTE */ -#define WM8996_DSP2RX_MUTE_SHIFT 9 /* DSP2RX_MUTE */ -#define WM8996_DSP2RX_MUTE_WIDTH 1 /* DSP2RX_MUTE */ -#define WM8996_DSP2RX_MONO 0x0080 /* DSP2RX_MONO */ -#define WM8996_DSP2RX_MONO_MASK 0x0080 /* DSP2RX_MONO */ -#define WM8996_DSP2RX_MONO_SHIFT 7 /* DSP2RX_MONO */ -#define WM8996_DSP2RX_MONO_WIDTH 1 /* DSP2RX_MONO */ -#define WM8996_DSP2RX_MUTERATE 0x0020 /* DSP2RX_MUTERATE */ -#define WM8996_DSP2RX_MUTERATE_MASK 0x0020 /* DSP2RX_MUTERATE */ -#define WM8996_DSP2RX_MUTERATE_SHIFT 5 /* DSP2RX_MUTERATE */ -#define WM8996_DSP2RX_MUTERATE_WIDTH 1 /* DSP2RX_MUTERATE */ -#define WM8996_DSP2RX_UNMUTE_RAMP 0x0010 /* DSP2RX_UNMUTE_RAMP */ -#define WM8996_DSP2RX_UNMUTE_RAMP_MASK 0x0010 /* DSP2RX_UNMUTE_RAMP */ -#define WM8996_DSP2RX_UNMUTE_RAMP_SHIFT 4 /* DSP2RX_UNMUTE_RAMP */ -#define WM8996_DSP2RX_UNMUTE_RAMP_WIDTH 1 /* DSP2RX_UNMUTE_RAMP */ - -/* - * R1313 (0x521) - DSP2 RX Filters (2) - */ -#define WM8996_DSP2RX_3D_GAIN_MASK 0x3E00 /* DSP2RX_3D_GAIN - [13:9] */ -#define WM8996_DSP2RX_3D_GAIN_SHIFT 9 /* DSP2RX_3D_GAIN - [13:9] */ -#define WM8996_DSP2RX_3D_GAIN_WIDTH 5 /* DSP2RX_3D_GAIN - [13:9] */ -#define WM8996_DSP2RX_3D_ENA 0x0100 /* DSP2RX_3D_ENA */ -#define WM8996_DSP2RX_3D_ENA_MASK 0x0100 /* DSP2RX_3D_ENA */ -#define WM8996_DSP2RX_3D_ENA_SHIFT 8 /* DSP2RX_3D_ENA */ -#define WM8996_DSP2RX_3D_ENA_WIDTH 1 /* DSP2RX_3D_ENA */ - -/* - * R1344 (0x540) - DSP2 DRC (1) - */ -#define WM8996_DSP2DRC_SIG_DET_RMS_MASK 0xF800 /* DSP2DRC_SIG_DET_RMS - [15:11] */ -#define WM8996_DSP2DRC_SIG_DET_RMS_SHIFT 11 /* DSP2DRC_SIG_DET_RMS - [15:11] */ -#define WM8996_DSP2DRC_SIG_DET_RMS_WIDTH 5 /* DSP2DRC_SIG_DET_RMS - [15:11] */ -#define WM8996_DSP2DRC_SIG_DET_PK_MASK 0x0600 /* DSP2DRC_SIG_DET_PK - [10:9] */ -#define WM8996_DSP2DRC_SIG_DET_PK_SHIFT 9 /* DSP2DRC_SIG_DET_PK - [10:9] */ -#define WM8996_DSP2DRC_SIG_DET_PK_WIDTH 2 /* DSP2DRC_SIG_DET_PK - [10:9] */ -#define WM8996_DSP2DRC_NG_ENA 0x0100 /* DSP2DRC_NG_ENA */ -#define WM8996_DSP2DRC_NG_ENA_MASK 0x0100 /* DSP2DRC_NG_ENA */ -#define WM8996_DSP2DRC_NG_ENA_SHIFT 8 /* DSP2DRC_NG_ENA */ -#define WM8996_DSP2DRC_NG_ENA_WIDTH 1 /* DSP2DRC_NG_ENA */ -#define WM8996_DSP2DRC_SIG_DET_MODE 0x0080 /* DSP2DRC_SIG_DET_MODE */ -#define WM8996_DSP2DRC_SIG_DET_MODE_MASK 0x0080 /* DSP2DRC_SIG_DET_MODE */ -#define WM8996_DSP2DRC_SIG_DET_MODE_SHIFT 7 /* DSP2DRC_SIG_DET_MODE */ -#define WM8996_DSP2DRC_SIG_DET_MODE_WIDTH 1 /* DSP2DRC_SIG_DET_MODE */ -#define WM8996_DSP2DRC_SIG_DET 0x0040 /* DSP2DRC_SIG_DET */ -#define WM8996_DSP2DRC_SIG_DET_MASK 0x0040 /* DSP2DRC_SIG_DET */ -#define WM8996_DSP2DRC_SIG_DET_SHIFT 6 /* DSP2DRC_SIG_DET */ -#define WM8996_DSP2DRC_SIG_DET_WIDTH 1 /* DSP2DRC_SIG_DET */ -#define WM8996_DSP2DRC_KNEE2_OP_ENA 0x0020 /* DSP2DRC_KNEE2_OP_ENA */ -#define WM8996_DSP2DRC_KNEE2_OP_ENA_MASK 0x0020 /* DSP2DRC_KNEE2_OP_ENA */ -#define WM8996_DSP2DRC_KNEE2_OP_ENA_SHIFT 5 /* DSP2DRC_KNEE2_OP_ENA */ -#define WM8996_DSP2DRC_KNEE2_OP_ENA_WIDTH 1 /* DSP2DRC_KNEE2_OP_ENA */ -#define WM8996_DSP2DRC_QR 0x0010 /* DSP2DRC_QR */ -#define WM8996_DSP2DRC_QR_MASK 0x0010 /* DSP2DRC_QR */ -#define WM8996_DSP2DRC_QR_SHIFT 4 /* DSP2DRC_QR */ -#define WM8996_DSP2DRC_QR_WIDTH 1 /* DSP2DRC_QR */ -#define WM8996_DSP2DRC_ANTICLIP 0x0008 /* DSP2DRC_ANTICLIP */ -#define WM8996_DSP2DRC_ANTICLIP_MASK 0x0008 /* DSP2DRC_ANTICLIP */ -#define WM8996_DSP2DRC_ANTICLIP_SHIFT 3 /* DSP2DRC_ANTICLIP */ -#define WM8996_DSP2DRC_ANTICLIP_WIDTH 1 /* DSP2DRC_ANTICLIP */ -#define WM8996_DSP2RX_DRC_ENA 0x0004 /* DSP2RX_DRC_ENA */ -#define WM8996_DSP2RX_DRC_ENA_MASK 0x0004 /* DSP2RX_DRC_ENA */ -#define WM8996_DSP2RX_DRC_ENA_SHIFT 2 /* DSP2RX_DRC_ENA */ -#define WM8996_DSP2RX_DRC_ENA_WIDTH 1 /* DSP2RX_DRC_ENA */ -#define WM8996_DSP2TXL_DRC_ENA 0x0002 /* DSP2TXL_DRC_ENA */ -#define WM8996_DSP2TXL_DRC_ENA_MASK 0x0002 /* DSP2TXL_DRC_ENA */ -#define WM8996_DSP2TXL_DRC_ENA_SHIFT 1 /* DSP2TXL_DRC_ENA */ -#define WM8996_DSP2TXL_DRC_ENA_WIDTH 1 /* DSP2TXL_DRC_ENA */ -#define WM8996_DSP2TXR_DRC_ENA 0x0001 /* DSP2TXR_DRC_ENA */ -#define WM8996_DSP2TXR_DRC_ENA_MASK 0x0001 /* DSP2TXR_DRC_ENA */ -#define WM8996_DSP2TXR_DRC_ENA_SHIFT 0 /* DSP2TXR_DRC_ENA */ -#define WM8996_DSP2TXR_DRC_ENA_WIDTH 1 /* DSP2TXR_DRC_ENA */ - -/* - * R1345 (0x541) - DSP2 DRC (2) - */ -#define WM8996_DSP2DRC_ATK_MASK 0x1E00 /* DSP2DRC_ATK - [12:9] */ -#define WM8996_DSP2DRC_ATK_SHIFT 9 /* DSP2DRC_ATK - [12:9] */ -#define WM8996_DSP2DRC_ATK_WIDTH 4 /* DSP2DRC_ATK - [12:9] */ -#define WM8996_DSP2DRC_DCY_MASK 0x01E0 /* DSP2DRC_DCY - [8:5] */ -#define WM8996_DSP2DRC_DCY_SHIFT 5 /* DSP2DRC_DCY - [8:5] */ -#define WM8996_DSP2DRC_DCY_WIDTH 4 /* DSP2DRC_DCY - [8:5] */ -#define WM8996_DSP2DRC_MINGAIN_MASK 0x001C /* DSP2DRC_MINGAIN - [4:2] */ -#define WM8996_DSP2DRC_MINGAIN_SHIFT 2 /* DSP2DRC_MINGAIN - [4:2] */ -#define WM8996_DSP2DRC_MINGAIN_WIDTH 3 /* DSP2DRC_MINGAIN - [4:2] */ -#define WM8996_DSP2DRC_MAXGAIN_MASK 0x0003 /* DSP2DRC_MAXGAIN - [1:0] */ -#define WM8996_DSP2DRC_MAXGAIN_SHIFT 0 /* DSP2DRC_MAXGAIN - [1:0] */ -#define WM8996_DSP2DRC_MAXGAIN_WIDTH 2 /* DSP2DRC_MAXGAIN - [1:0] */ - -/* - * R1346 (0x542) - DSP2 DRC (3) - */ -#define WM8996_DSP2DRC_NG_MINGAIN_MASK 0xF000 /* DSP2DRC_NG_MINGAIN - [15:12] */ -#define WM8996_DSP2DRC_NG_MINGAIN_SHIFT 12 /* DSP2DRC_NG_MINGAIN - [15:12] */ -#define WM8996_DSP2DRC_NG_MINGAIN_WIDTH 4 /* DSP2DRC_NG_MINGAIN - [15:12] */ -#define WM8996_DSP2DRC_NG_EXP_MASK 0x0C00 /* DSP2DRC_NG_EXP - [11:10] */ -#define WM8996_DSP2DRC_NG_EXP_SHIFT 10 /* DSP2DRC_NG_EXP - [11:10] */ -#define WM8996_DSP2DRC_NG_EXP_WIDTH 2 /* DSP2DRC_NG_EXP - [11:10] */ -#define WM8996_DSP2DRC_QR_THR_MASK 0x0300 /* DSP2DRC_QR_THR - [9:8] */ -#define WM8996_DSP2DRC_QR_THR_SHIFT 8 /* DSP2DRC_QR_THR - [9:8] */ -#define WM8996_DSP2DRC_QR_THR_WIDTH 2 /* DSP2DRC_QR_THR - [9:8] */ -#define WM8996_DSP2DRC_QR_DCY_MASK 0x00C0 /* DSP2DRC_QR_DCY - [7:6] */ -#define WM8996_DSP2DRC_QR_DCY_SHIFT 6 /* DSP2DRC_QR_DCY - [7:6] */ -#define WM8996_DSP2DRC_QR_DCY_WIDTH 2 /* DSP2DRC_QR_DCY - [7:6] */ -#define WM8996_DSP2DRC_HI_COMP_MASK 0x0038 /* DSP2DRC_HI_COMP - [5:3] */ -#define WM8996_DSP2DRC_HI_COMP_SHIFT 3 /* DSP2DRC_HI_COMP - [5:3] */ -#define WM8996_DSP2DRC_HI_COMP_WIDTH 3 /* DSP2DRC_HI_COMP - [5:3] */ -#define WM8996_DSP2DRC_LO_COMP_MASK 0x0007 /* DSP2DRC_LO_COMP - [2:0] */ -#define WM8996_DSP2DRC_LO_COMP_SHIFT 0 /* DSP2DRC_LO_COMP - [2:0] */ -#define WM8996_DSP2DRC_LO_COMP_WIDTH 3 /* DSP2DRC_LO_COMP - [2:0] */ - -/* - * R1347 (0x543) - DSP2 DRC (4) - */ -#define WM8996_DSP2DRC_KNEE_IP_MASK 0x07E0 /* DSP2DRC_KNEE_IP - [10:5] */ -#define WM8996_DSP2DRC_KNEE_IP_SHIFT 5 /* DSP2DRC_KNEE_IP - [10:5] */ -#define WM8996_DSP2DRC_KNEE_IP_WIDTH 6 /* DSP2DRC_KNEE_IP - [10:5] */ -#define WM8996_DSP2DRC_KNEE_OP_MASK 0x001F /* DSP2DRC_KNEE_OP - [4:0] */ -#define WM8996_DSP2DRC_KNEE_OP_SHIFT 0 /* DSP2DRC_KNEE_OP - [4:0] */ -#define WM8996_DSP2DRC_KNEE_OP_WIDTH 5 /* DSP2DRC_KNEE_OP - [4:0] */ - -/* - * R1348 (0x544) - DSP2 DRC (5) - */ -#define WM8996_DSP2DRC_KNEE2_IP_MASK 0x03E0 /* DSP2DRC_KNEE2_IP - [9:5] */ -#define WM8996_DSP2DRC_KNEE2_IP_SHIFT 5 /* DSP2DRC_KNEE2_IP - [9:5] */ -#define WM8996_DSP2DRC_KNEE2_IP_WIDTH 5 /* DSP2DRC_KNEE2_IP - [9:5] */ -#define WM8996_DSP2DRC_KNEE2_OP_MASK 0x001F /* DSP2DRC_KNEE2_OP - [4:0] */ -#define WM8996_DSP2DRC_KNEE2_OP_SHIFT 0 /* DSP2DRC_KNEE2_OP - [4:0] */ -#define WM8996_DSP2DRC_KNEE2_OP_WIDTH 5 /* DSP2DRC_KNEE2_OP - [4:0] */ - -/* - * R1408 (0x580) - DSP2 RX EQ Gains (1) - */ -#define WM8996_DSP2RX_EQ_B1_GAIN_MASK 0xF800 /* DSP2RX_EQ_B1_GAIN - [15:11] */ -#define WM8996_DSP2RX_EQ_B1_GAIN_SHIFT 11 /* DSP2RX_EQ_B1_GAIN - [15:11] */ -#define WM8996_DSP2RX_EQ_B1_GAIN_WIDTH 5 /* DSP2RX_EQ_B1_GAIN - [15:11] */ -#define WM8996_DSP2RX_EQ_B2_GAIN_MASK 0x07C0 /* DSP2RX_EQ_B2_GAIN - [10:6] */ -#define WM8996_DSP2RX_EQ_B2_GAIN_SHIFT 6 /* DSP2RX_EQ_B2_GAIN - [10:6] */ -#define WM8996_DSP2RX_EQ_B2_GAIN_WIDTH 5 /* DSP2RX_EQ_B2_GAIN - [10:6] */ -#define WM8996_DSP2RX_EQ_B3_GAIN_MASK 0x003E /* DSP2RX_EQ_B3_GAIN - [5:1] */ -#define WM8996_DSP2RX_EQ_B3_GAIN_SHIFT 1 /* DSP2RX_EQ_B3_GAIN - [5:1] */ -#define WM8996_DSP2RX_EQ_B3_GAIN_WIDTH 5 /* DSP2RX_EQ_B3_GAIN - [5:1] */ -#define WM8996_DSP2RX_EQ_ENA 0x0001 /* DSP2RX_EQ_ENA */ -#define WM8996_DSP2RX_EQ_ENA_MASK 0x0001 /* DSP2RX_EQ_ENA */ -#define WM8996_DSP2RX_EQ_ENA_SHIFT 0 /* DSP2RX_EQ_ENA */ -#define WM8996_DSP2RX_EQ_ENA_WIDTH 1 /* DSP2RX_EQ_ENA */ - -/* - * R1409 (0x581) - DSP2 RX EQ Gains (2) - */ -#define WM8996_DSP2RX_EQ_B4_GAIN_MASK 0xF800 /* DSP2RX_EQ_B4_GAIN - [15:11] */ -#define WM8996_DSP2RX_EQ_B4_GAIN_SHIFT 11 /* DSP2RX_EQ_B4_GAIN - [15:11] */ -#define WM8996_DSP2RX_EQ_B4_GAIN_WIDTH 5 /* DSP2RX_EQ_B4_GAIN - [15:11] */ -#define WM8996_DSP2RX_EQ_B5_GAIN_MASK 0x07C0 /* DSP2RX_EQ_B5_GAIN - [10:6] */ -#define WM8996_DSP2RX_EQ_B5_GAIN_SHIFT 6 /* DSP2RX_EQ_B5_GAIN - [10:6] */ -#define WM8996_DSP2RX_EQ_B5_GAIN_WIDTH 5 /* DSP2RX_EQ_B5_GAIN - [10:6] */ - -/* - * R1410 (0x582) - DSP2 RX EQ Band 1 A - */ -#define WM8996_DSP2RX_EQ_B1_A_MASK 0xFFFF /* DSP2RX_EQ_B1_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B1_A_SHIFT 0 /* DSP2RX_EQ_B1_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B1_A_WIDTH 16 /* DSP2RX_EQ_B1_A - [15:0] */ - -/* - * R1411 (0x583) - DSP2 RX EQ Band 1 B - */ -#define WM8996_DSP2RX_EQ_B1_B_MASK 0xFFFF /* DSP2RX_EQ_B1_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B1_B_SHIFT 0 /* DSP2RX_EQ_B1_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B1_B_WIDTH 16 /* DSP2RX_EQ_B1_B - [15:0] */ - -/* - * R1412 (0x584) - DSP2 RX EQ Band 1 PG - */ -#define WM8996_DSP2RX_EQ_B1_PG_MASK 0xFFFF /* DSP2RX_EQ_B1_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B1_PG_SHIFT 0 /* DSP2RX_EQ_B1_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B1_PG_WIDTH 16 /* DSP2RX_EQ_B1_PG - [15:0] */ - -/* - * R1413 (0x585) - DSP2 RX EQ Band 2 A - */ -#define WM8996_DSP2RX_EQ_B2_A_MASK 0xFFFF /* DSP2RX_EQ_B2_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B2_A_SHIFT 0 /* DSP2RX_EQ_B2_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B2_A_WIDTH 16 /* DSP2RX_EQ_B2_A - [15:0] */ - -/* - * R1414 (0x586) - DSP2 RX EQ Band 2 B - */ -#define WM8996_DSP2RX_EQ_B2_B_MASK 0xFFFF /* DSP2RX_EQ_B2_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B2_B_SHIFT 0 /* DSP2RX_EQ_B2_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B2_B_WIDTH 16 /* DSP2RX_EQ_B2_B - [15:0] */ - -/* - * R1415 (0x587) - DSP2 RX EQ Band 2 C - */ -#define WM8996_DSP2RX_EQ_B2_C_MASK 0xFFFF /* DSP2RX_EQ_B2_C - [15:0] */ -#define WM8996_DSP2RX_EQ_B2_C_SHIFT 0 /* DSP2RX_EQ_B2_C - [15:0] */ -#define WM8996_DSP2RX_EQ_B2_C_WIDTH 16 /* DSP2RX_EQ_B2_C - [15:0] */ - -/* - * R1416 (0x588) - DSP2 RX EQ Band 2 PG - */ -#define WM8996_DSP2RX_EQ_B2_PG_MASK 0xFFFF /* DSP2RX_EQ_B2_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B2_PG_SHIFT 0 /* DSP2RX_EQ_B2_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B2_PG_WIDTH 16 /* DSP2RX_EQ_B2_PG - [15:0] */ - -/* - * R1417 (0x589) - DSP2 RX EQ Band 3 A - */ -#define WM8996_DSP2RX_EQ_B3_A_MASK 0xFFFF /* DSP2RX_EQ_B3_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B3_A_SHIFT 0 /* DSP2RX_EQ_B3_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B3_A_WIDTH 16 /* DSP2RX_EQ_B3_A - [15:0] */ - -/* - * R1418 (0x58A) - DSP2 RX EQ Band 3 B - */ -#define WM8996_DSP2RX_EQ_B3_B_MASK 0xFFFF /* DSP2RX_EQ_B3_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B3_B_SHIFT 0 /* DSP2RX_EQ_B3_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B3_B_WIDTH 16 /* DSP2RX_EQ_B3_B - [15:0] */ - -/* - * R1419 (0x58B) - DSP2 RX EQ Band 3 C - */ -#define WM8996_DSP2RX_EQ_B3_C_MASK 0xFFFF /* DSP2RX_EQ_B3_C - [15:0] */ -#define WM8996_DSP2RX_EQ_B3_C_SHIFT 0 /* DSP2RX_EQ_B3_C - [15:0] */ -#define WM8996_DSP2RX_EQ_B3_C_WIDTH 16 /* DSP2RX_EQ_B3_C - [15:0] */ - -/* - * R1420 (0x58C) - DSP2 RX EQ Band 3 PG - */ -#define WM8996_DSP2RX_EQ_B3_PG_MASK 0xFFFF /* DSP2RX_EQ_B3_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B3_PG_SHIFT 0 /* DSP2RX_EQ_B3_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B3_PG_WIDTH 16 /* DSP2RX_EQ_B3_PG - [15:0] */ - -/* - * R1421 (0x58D) - DSP2 RX EQ Band 4 A - */ -#define WM8996_DSP2RX_EQ_B4_A_MASK 0xFFFF /* DSP2RX_EQ_B4_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B4_A_SHIFT 0 /* DSP2RX_EQ_B4_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B4_A_WIDTH 16 /* DSP2RX_EQ_B4_A - [15:0] */ - -/* - * R1422 (0x58E) - DSP2 RX EQ Band 4 B - */ -#define WM8996_DSP2RX_EQ_B4_B_MASK 0xFFFF /* DSP2RX_EQ_B4_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B4_B_SHIFT 0 /* DSP2RX_EQ_B4_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B4_B_WIDTH 16 /* DSP2RX_EQ_B4_B - [15:0] */ - -/* - * R1423 (0x58F) - DSP2 RX EQ Band 4 C - */ -#define WM8996_DSP2RX_EQ_B4_C_MASK 0xFFFF /* DSP2RX_EQ_B4_C - [15:0] */ -#define WM8996_DSP2RX_EQ_B4_C_SHIFT 0 /* DSP2RX_EQ_B4_C - [15:0] */ -#define WM8996_DSP2RX_EQ_B4_C_WIDTH 16 /* DSP2RX_EQ_B4_C - [15:0] */ - -/* - * R1424 (0x590) - DSP2 RX EQ Band 4 PG - */ -#define WM8996_DSP2RX_EQ_B4_PG_MASK 0xFFFF /* DSP2RX_EQ_B4_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B4_PG_SHIFT 0 /* DSP2RX_EQ_B4_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B4_PG_WIDTH 16 /* DSP2RX_EQ_B4_PG - [15:0] */ - -/* - * R1425 (0x591) - DSP2 RX EQ Band 5 A - */ -#define WM8996_DSP2RX_EQ_B5_A_MASK 0xFFFF /* DSP2RX_EQ_B5_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B5_A_SHIFT 0 /* DSP2RX_EQ_B5_A - [15:0] */ -#define WM8996_DSP2RX_EQ_B5_A_WIDTH 16 /* DSP2RX_EQ_B5_A - [15:0] */ - -/* - * R1426 (0x592) - DSP2 RX EQ Band 5 B - */ -#define WM8996_DSP2RX_EQ_B5_B_MASK 0xFFFF /* DSP2RX_EQ_B5_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B5_B_SHIFT 0 /* DSP2RX_EQ_B5_B - [15:0] */ -#define WM8996_DSP2RX_EQ_B5_B_WIDTH 16 /* DSP2RX_EQ_B5_B - [15:0] */ - -/* - * R1427 (0x593) - DSP2 RX EQ Band 5 PG - */ -#define WM8996_DSP2RX_EQ_B5_PG_MASK 0xFFFF /* DSP2RX_EQ_B5_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B5_PG_SHIFT 0 /* DSP2RX_EQ_B5_PG - [15:0] */ -#define WM8996_DSP2RX_EQ_B5_PG_WIDTH 16 /* DSP2RX_EQ_B5_PG - [15:0] */ - -/* - * R1536 (0x600) - DAC1 Mixer Volumes - */ -#define WM8996_ADCR_DAC1_VOL_MASK 0x03E0 /* ADCR_DAC1_VOL - [9:5] */ -#define WM8996_ADCR_DAC1_VOL_SHIFT 5 /* ADCR_DAC1_VOL - [9:5] */ -#define WM8996_ADCR_DAC1_VOL_WIDTH 5 /* ADCR_DAC1_VOL - [9:5] */ -#define WM8996_ADCL_DAC1_VOL_MASK 0x001F /* ADCL_DAC1_VOL - [4:0] */ -#define WM8996_ADCL_DAC1_VOL_SHIFT 0 /* ADCL_DAC1_VOL - [4:0] */ -#define WM8996_ADCL_DAC1_VOL_WIDTH 5 /* ADCL_DAC1_VOL - [4:0] */ - -/* - * R1537 (0x601) - DAC1 Left Mixer Routing - */ -#define WM8996_ADCR_TO_DAC1L 0x0020 /* ADCR_TO_DAC1L */ -#define WM8996_ADCR_TO_DAC1L_MASK 0x0020 /* ADCR_TO_DAC1L */ -#define WM8996_ADCR_TO_DAC1L_SHIFT 5 /* ADCR_TO_DAC1L */ -#define WM8996_ADCR_TO_DAC1L_WIDTH 1 /* ADCR_TO_DAC1L */ -#define WM8996_ADCL_TO_DAC1L 0x0010 /* ADCL_TO_DAC1L */ -#define WM8996_ADCL_TO_DAC1L_MASK 0x0010 /* ADCL_TO_DAC1L */ -#define WM8996_ADCL_TO_DAC1L_SHIFT 4 /* ADCL_TO_DAC1L */ -#define WM8996_ADCL_TO_DAC1L_WIDTH 1 /* ADCL_TO_DAC1L */ -#define WM8996_DSP2RXL_TO_DAC1L 0x0002 /* DSP2RXL_TO_DAC1L */ -#define WM8996_DSP2RXL_TO_DAC1L_MASK 0x0002 /* DSP2RXL_TO_DAC1L */ -#define WM8996_DSP2RXL_TO_DAC1L_SHIFT 1 /* DSP2RXL_TO_DAC1L */ -#define WM8996_DSP2RXL_TO_DAC1L_WIDTH 1 /* DSP2RXL_TO_DAC1L */ -#define WM8996_DSP1RXL_TO_DAC1L 0x0001 /* DSP1RXL_TO_DAC1L */ -#define WM8996_DSP1RXL_TO_DAC1L_MASK 0x0001 /* DSP1RXL_TO_DAC1L */ -#define WM8996_DSP1RXL_TO_DAC1L_SHIFT 0 /* DSP1RXL_TO_DAC1L */ -#define WM8996_DSP1RXL_TO_DAC1L_WIDTH 1 /* DSP1RXL_TO_DAC1L */ - -/* - * R1538 (0x602) - DAC1 Right Mixer Routing - */ -#define WM8996_ADCR_TO_DAC1R 0x0020 /* ADCR_TO_DAC1R */ -#define WM8996_ADCR_TO_DAC1R_MASK 0x0020 /* ADCR_TO_DAC1R */ -#define WM8996_ADCR_TO_DAC1R_SHIFT 5 /* ADCR_TO_DAC1R */ -#define WM8996_ADCR_TO_DAC1R_WIDTH 1 /* ADCR_TO_DAC1R */ -#define WM8996_ADCL_TO_DAC1R 0x0010 /* ADCL_TO_DAC1R */ -#define WM8996_ADCL_TO_DAC1R_MASK 0x0010 /* ADCL_TO_DAC1R */ -#define WM8996_ADCL_TO_DAC1R_SHIFT 4 /* ADCL_TO_DAC1R */ -#define WM8996_ADCL_TO_DAC1R_WIDTH 1 /* ADCL_TO_DAC1R */ -#define WM8996_DSP2RXR_TO_DAC1R 0x0002 /* DSP2RXR_TO_DAC1R */ -#define WM8996_DSP2RXR_TO_DAC1R_MASK 0x0002 /* DSP2RXR_TO_DAC1R */ -#define WM8996_DSP2RXR_TO_DAC1R_SHIFT 1 /* DSP2RXR_TO_DAC1R */ -#define WM8996_DSP2RXR_TO_DAC1R_WIDTH 1 /* DSP2RXR_TO_DAC1R */ -#define WM8996_DSP1RXR_TO_DAC1R 0x0001 /* DSP1RXR_TO_DAC1R */ -#define WM8996_DSP1RXR_TO_DAC1R_MASK 0x0001 /* DSP1RXR_TO_DAC1R */ -#define WM8996_DSP1RXR_TO_DAC1R_SHIFT 0 /* DSP1RXR_TO_DAC1R */ -#define WM8996_DSP1RXR_TO_DAC1R_WIDTH 1 /* DSP1RXR_TO_DAC1R */ - -/* - * R1539 (0x603) - DAC2 Mixer Volumes - */ -#define WM8996_ADCR_DAC2_VOL_MASK 0x03E0 /* ADCR_DAC2_VOL - [9:5] */ -#define WM8996_ADCR_DAC2_VOL_SHIFT 5 /* ADCR_DAC2_VOL - [9:5] */ -#define WM8996_ADCR_DAC2_VOL_WIDTH 5 /* ADCR_DAC2_VOL - [9:5] */ -#define WM8996_ADCL_DAC2_VOL_MASK 0x001F /* ADCL_DAC2_VOL - [4:0] */ -#define WM8996_ADCL_DAC2_VOL_SHIFT 0 /* ADCL_DAC2_VOL - [4:0] */ -#define WM8996_ADCL_DAC2_VOL_WIDTH 5 /* ADCL_DAC2_VOL - [4:0] */ - -/* - * R1540 (0x604) - DAC2 Left Mixer Routing - */ -#define WM8996_ADCR_TO_DAC2L 0x0020 /* ADCR_TO_DAC2L */ -#define WM8996_ADCR_TO_DAC2L_MASK 0x0020 /* ADCR_TO_DAC2L */ -#define WM8996_ADCR_TO_DAC2L_SHIFT 5 /* ADCR_TO_DAC2L */ -#define WM8996_ADCR_TO_DAC2L_WIDTH 1 /* ADCR_TO_DAC2L */ -#define WM8996_ADCL_TO_DAC2L 0x0010 /* ADCL_TO_DAC2L */ -#define WM8996_ADCL_TO_DAC2L_MASK 0x0010 /* ADCL_TO_DAC2L */ -#define WM8996_ADCL_TO_DAC2L_SHIFT 4 /* ADCL_TO_DAC2L */ -#define WM8996_ADCL_TO_DAC2L_WIDTH 1 /* ADCL_TO_DAC2L */ -#define WM8996_DSP2RXL_TO_DAC2L 0x0002 /* DSP2RXL_TO_DAC2L */ -#define WM8996_DSP2RXL_TO_DAC2L_MASK 0x0002 /* DSP2RXL_TO_DAC2L */ -#define WM8996_DSP2RXL_TO_DAC2L_SHIFT 1 /* DSP2RXL_TO_DAC2L */ -#define WM8996_DSP2RXL_TO_DAC2L_WIDTH 1 /* DSP2RXL_TO_DAC2L */ -#define WM8996_DSP1RXL_TO_DAC2L 0x0001 /* DSP1RXL_TO_DAC2L */ -#define WM8996_DSP1RXL_TO_DAC2L_MASK 0x0001 /* DSP1RXL_TO_DAC2L */ -#define WM8996_DSP1RXL_TO_DAC2L_SHIFT 0 /* DSP1RXL_TO_DAC2L */ -#define WM8996_DSP1RXL_TO_DAC2L_WIDTH 1 /* DSP1RXL_TO_DAC2L */ - -/* - * R1541 (0x605) - DAC2 Right Mixer Routing - */ -#define WM8996_ADCR_TO_DAC2R 0x0020 /* ADCR_TO_DAC2R */ -#define WM8996_ADCR_TO_DAC2R_MASK 0x0020 /* ADCR_TO_DAC2R */ -#define WM8996_ADCR_TO_DAC2R_SHIFT 5 /* ADCR_TO_DAC2R */ -#define WM8996_ADCR_TO_DAC2R_WIDTH 1 /* ADCR_TO_DAC2R */ -#define WM8996_ADCL_TO_DAC2R 0x0010 /* ADCL_TO_DAC2R */ -#define WM8996_ADCL_TO_DAC2R_MASK 0x0010 /* ADCL_TO_DAC2R */ -#define WM8996_ADCL_TO_DAC2R_SHIFT 4 /* ADCL_TO_DAC2R */ -#define WM8996_ADCL_TO_DAC2R_WIDTH 1 /* ADCL_TO_DAC2R */ -#define WM8996_DSP2RXR_TO_DAC2R 0x0002 /* DSP2RXR_TO_DAC2R */ -#define WM8996_DSP2RXR_TO_DAC2R_MASK 0x0002 /* DSP2RXR_TO_DAC2R */ -#define WM8996_DSP2RXR_TO_DAC2R_SHIFT 1 /* DSP2RXR_TO_DAC2R */ -#define WM8996_DSP2RXR_TO_DAC2R_WIDTH 1 /* DSP2RXR_TO_DAC2R */ -#define WM8996_DSP1RXR_TO_DAC2R 0x0001 /* DSP1RXR_TO_DAC2R */ -#define WM8996_DSP1RXR_TO_DAC2R_MASK 0x0001 /* DSP1RXR_TO_DAC2R */ -#define WM8996_DSP1RXR_TO_DAC2R_SHIFT 0 /* DSP1RXR_TO_DAC2R */ -#define WM8996_DSP1RXR_TO_DAC2R_WIDTH 1 /* DSP1RXR_TO_DAC2R */ - -/* - * R1542 (0x606) - DSP1 TX Left Mixer Routing - */ -#define WM8996_ADC1L_TO_DSP1TXL 0x0002 /* ADC1L_TO_DSP1TXL */ -#define WM8996_ADC1L_TO_DSP1TXL_MASK 0x0002 /* ADC1L_TO_DSP1TXL */ -#define WM8996_ADC1L_TO_DSP1TXL_SHIFT 1 /* ADC1L_TO_DSP1TXL */ -#define WM8996_ADC1L_TO_DSP1TXL_WIDTH 1 /* ADC1L_TO_DSP1TXL */ -#define WM8996_DACL_TO_DSP1TXL 0x0001 /* DACL_TO_DSP1TXL */ -#define WM8996_DACL_TO_DSP1TXL_MASK 0x0001 /* DACL_TO_DSP1TXL */ -#define WM8996_DACL_TO_DSP1TXL_SHIFT 0 /* DACL_TO_DSP1TXL */ -#define WM8996_DACL_TO_DSP1TXL_WIDTH 1 /* DACL_TO_DSP1TXL */ - -/* - * R1543 (0x607) - DSP1 TX Right Mixer Routing - */ -#define WM8996_ADC1R_TO_DSP1TXR 0x0002 /* ADC1R_TO_DSP1TXR */ -#define WM8996_ADC1R_TO_DSP1TXR_MASK 0x0002 /* ADC1R_TO_DSP1TXR */ -#define WM8996_ADC1R_TO_DSP1TXR_SHIFT 1 /* ADC1R_TO_DSP1TXR */ -#define WM8996_ADC1R_TO_DSP1TXR_WIDTH 1 /* ADC1R_TO_DSP1TXR */ -#define WM8996_DACR_TO_DSP1TXR 0x0001 /* DACR_TO_DSP1TXR */ -#define WM8996_DACR_TO_DSP1TXR_MASK 0x0001 /* DACR_TO_DSP1TXR */ -#define WM8996_DACR_TO_DSP1TXR_SHIFT 0 /* DACR_TO_DSP1TXR */ -#define WM8996_DACR_TO_DSP1TXR_WIDTH 1 /* DACR_TO_DSP1TXR */ - -/* - * R1544 (0x608) - DSP2 TX Left Mixer Routing - */ -#define WM8996_ADC2L_TO_DSP2TXL 0x0002 /* ADC2L_TO_DSP2TXL */ -#define WM8996_ADC2L_TO_DSP2TXL_MASK 0x0002 /* ADC2L_TO_DSP2TXL */ -#define WM8996_ADC2L_TO_DSP2TXL_SHIFT 1 /* ADC2L_TO_DSP2TXL */ -#define WM8996_ADC2L_TO_DSP2TXL_WIDTH 1 /* ADC2L_TO_DSP2TXL */ -#define WM8996_DACL_TO_DSP2TXL 0x0001 /* DACL_TO_DSP2TXL */ -#define WM8996_DACL_TO_DSP2TXL_MASK 0x0001 /* DACL_TO_DSP2TXL */ -#define WM8996_DACL_TO_DSP2TXL_SHIFT 0 /* DACL_TO_DSP2TXL */ -#define WM8996_DACL_TO_DSP2TXL_WIDTH 1 /* DACL_TO_DSP2TXL */ - -/* - * R1545 (0x609) - DSP2 TX Right Mixer Routing - */ -#define WM8996_ADC2R_TO_DSP2TXR 0x0002 /* ADC2R_TO_DSP2TXR */ -#define WM8996_ADC2R_TO_DSP2TXR_MASK 0x0002 /* ADC2R_TO_DSP2TXR */ -#define WM8996_ADC2R_TO_DSP2TXR_SHIFT 1 /* ADC2R_TO_DSP2TXR */ -#define WM8996_ADC2R_TO_DSP2TXR_WIDTH 1 /* ADC2R_TO_DSP2TXR */ -#define WM8996_DACR_TO_DSP2TXR 0x0001 /* DACR_TO_DSP2TXR */ -#define WM8996_DACR_TO_DSP2TXR_MASK 0x0001 /* DACR_TO_DSP2TXR */ -#define WM8996_DACR_TO_DSP2TXR_SHIFT 0 /* DACR_TO_DSP2TXR */ -#define WM8996_DACR_TO_DSP2TXR_WIDTH 1 /* DACR_TO_DSP2TXR */ - -/* - * R1546 (0x60A) - DSP TX Mixer Select - */ -#define WM8996_DAC_TO_DSPTX_SRC 0x0001 /* DAC_TO_DSPTX_SRC */ -#define WM8996_DAC_TO_DSPTX_SRC_MASK 0x0001 /* DAC_TO_DSPTX_SRC */ -#define WM8996_DAC_TO_DSPTX_SRC_SHIFT 0 /* DAC_TO_DSPTX_SRC */ -#define WM8996_DAC_TO_DSPTX_SRC_WIDTH 1 /* DAC_TO_DSPTX_SRC */ - -/* - * R1552 (0x610) - DAC Softmute - */ -#define WM8996_DAC_SOFTMUTEMODE 0x0002 /* DAC_SOFTMUTEMODE */ -#define WM8996_DAC_SOFTMUTEMODE_MASK 0x0002 /* DAC_SOFTMUTEMODE */ -#define WM8996_DAC_SOFTMUTEMODE_SHIFT 1 /* DAC_SOFTMUTEMODE */ -#define WM8996_DAC_SOFTMUTEMODE_WIDTH 1 /* DAC_SOFTMUTEMODE */ -#define WM8996_DAC_MUTERATE 0x0001 /* DAC_MUTERATE */ -#define WM8996_DAC_MUTERATE_MASK 0x0001 /* DAC_MUTERATE */ -#define WM8996_DAC_MUTERATE_SHIFT 0 /* DAC_MUTERATE */ -#define WM8996_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ - -/* - * R1568 (0x620) - Oversampling - */ -#define WM8996_SPK_OSR128 0x0008 /* SPK_OSR128 */ -#define WM8996_SPK_OSR128_MASK 0x0008 /* SPK_OSR128 */ -#define WM8996_SPK_OSR128_SHIFT 3 /* SPK_OSR128 */ -#define WM8996_SPK_OSR128_WIDTH 1 /* SPK_OSR128 */ -#define WM8996_DMIC_OSR64 0x0004 /* DMIC_OSR64 */ -#define WM8996_DMIC_OSR64_MASK 0x0004 /* DMIC_OSR64 */ -#define WM8996_DMIC_OSR64_SHIFT 2 /* DMIC_OSR64 */ -#define WM8996_DMIC_OSR64_WIDTH 1 /* DMIC_OSR64 */ -#define WM8996_ADC_OSR128 0x0002 /* ADC_OSR128 */ -#define WM8996_ADC_OSR128_MASK 0x0002 /* ADC_OSR128 */ -#define WM8996_ADC_OSR128_SHIFT 1 /* ADC_OSR128 */ -#define WM8996_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ -#define WM8996_DAC_OSR128 0x0001 /* DAC_OSR128 */ -#define WM8996_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */ -#define WM8996_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */ -#define WM8996_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ - -/* - * R1569 (0x621) - Sidetone - */ -#define WM8996_ST_LPF 0x1000 /* ST_LPF */ -#define WM8996_ST_LPF_MASK 0x1000 /* ST_LPF */ -#define WM8996_ST_LPF_SHIFT 12 /* ST_LPF */ -#define WM8996_ST_LPF_WIDTH 1 /* ST_LPF */ -#define WM8996_ST_HPF_CUT_MASK 0x0380 /* ST_HPF_CUT - [9:7] */ -#define WM8996_ST_HPF_CUT_SHIFT 7 /* ST_HPF_CUT - [9:7] */ -#define WM8996_ST_HPF_CUT_WIDTH 3 /* ST_HPF_CUT - [9:7] */ -#define WM8996_ST_HPF 0x0040 /* ST_HPF */ -#define WM8996_ST_HPF_MASK 0x0040 /* ST_HPF */ -#define WM8996_ST_HPF_SHIFT 6 /* ST_HPF */ -#define WM8996_ST_HPF_WIDTH 1 /* ST_HPF */ -#define WM8996_STR_SEL 0x0002 /* STR_SEL */ -#define WM8996_STR_SEL_MASK 0x0002 /* STR_SEL */ -#define WM8996_STR_SEL_SHIFT 1 /* STR_SEL */ -#define WM8996_STR_SEL_WIDTH 1 /* STR_SEL */ -#define WM8996_STL_SEL 0x0001 /* STL_SEL */ -#define WM8996_STL_SEL_MASK 0x0001 /* STL_SEL */ -#define WM8996_STL_SEL_SHIFT 0 /* STL_SEL */ -#define WM8996_STL_SEL_WIDTH 1 /* STL_SEL */ - -/* - * R1792 (0x700) - GPIO 1 - */ -#define WM8996_GP1_DIR 0x8000 /* GP1_DIR */ -#define WM8996_GP1_DIR_MASK 0x8000 /* GP1_DIR */ -#define WM8996_GP1_DIR_SHIFT 15 /* GP1_DIR */ -#define WM8996_GP1_DIR_WIDTH 1 /* GP1_DIR */ -#define WM8996_GP1_PU 0x4000 /* GP1_PU */ -#define WM8996_GP1_PU_MASK 0x4000 /* GP1_PU */ -#define WM8996_GP1_PU_SHIFT 14 /* GP1_PU */ -#define WM8996_GP1_PU_WIDTH 1 /* GP1_PU */ -#define WM8996_GP1_PD 0x2000 /* GP1_PD */ -#define WM8996_GP1_PD_MASK 0x2000 /* GP1_PD */ -#define WM8996_GP1_PD_SHIFT 13 /* GP1_PD */ -#define WM8996_GP1_PD_WIDTH 1 /* GP1_PD */ -#define WM8996_GP1_POL 0x0400 /* GP1_POL */ -#define WM8996_GP1_POL_MASK 0x0400 /* GP1_POL */ -#define WM8996_GP1_POL_SHIFT 10 /* GP1_POL */ -#define WM8996_GP1_POL_WIDTH 1 /* GP1_POL */ -#define WM8996_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */ -#define WM8996_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */ -#define WM8996_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */ -#define WM8996_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */ -#define WM8996_GP1_DB 0x0100 /* GP1_DB */ -#define WM8996_GP1_DB_MASK 0x0100 /* GP1_DB */ -#define WM8996_GP1_DB_SHIFT 8 /* GP1_DB */ -#define WM8996_GP1_DB_WIDTH 1 /* GP1_DB */ -#define WM8996_GP1_LVL 0x0040 /* GP1_LVL */ -#define WM8996_GP1_LVL_MASK 0x0040 /* GP1_LVL */ -#define WM8996_GP1_LVL_SHIFT 6 /* GP1_LVL */ -#define WM8996_GP1_LVL_WIDTH 1 /* GP1_LVL */ -#define WM8996_GP1_FN_MASK 0x000F /* GP1_FN - [3:0] */ -#define WM8996_GP1_FN_SHIFT 0 /* GP1_FN - [3:0] */ -#define WM8996_GP1_FN_WIDTH 4 /* GP1_FN - [3:0] */ - -/* - * R1793 (0x701) - GPIO 2 - */ -#define WM8996_GP2_DIR 0x8000 /* GP2_DIR */ -#define WM8996_GP2_DIR_MASK 0x8000 /* GP2_DIR */ -#define WM8996_GP2_DIR_SHIFT 15 /* GP2_DIR */ -#define WM8996_GP2_DIR_WIDTH 1 /* GP2_DIR */ -#define WM8996_GP2_PU 0x4000 /* GP2_PU */ -#define WM8996_GP2_PU_MASK 0x4000 /* GP2_PU */ -#define WM8996_GP2_PU_SHIFT 14 /* GP2_PU */ -#define WM8996_GP2_PU_WIDTH 1 /* GP2_PU */ -#define WM8996_GP2_PD 0x2000 /* GP2_PD */ -#define WM8996_GP2_PD_MASK 0x2000 /* GP2_PD */ -#define WM8996_GP2_PD_SHIFT 13 /* GP2_PD */ -#define WM8996_GP2_PD_WIDTH 1 /* GP2_PD */ -#define WM8996_GP2_POL 0x0400 /* GP2_POL */ -#define WM8996_GP2_POL_MASK 0x0400 /* GP2_POL */ -#define WM8996_GP2_POL_SHIFT 10 /* GP2_POL */ -#define WM8996_GP2_POL_WIDTH 1 /* GP2_POL */ -#define WM8996_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */ -#define WM8996_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */ -#define WM8996_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */ -#define WM8996_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */ -#define WM8996_GP2_DB 0x0100 /* GP2_DB */ -#define WM8996_GP2_DB_MASK 0x0100 /* GP2_DB */ -#define WM8996_GP2_DB_SHIFT 8 /* GP2_DB */ -#define WM8996_GP2_DB_WIDTH 1 /* GP2_DB */ -#define WM8996_GP2_LVL 0x0040 /* GP2_LVL */ -#define WM8996_GP2_LVL_MASK 0x0040 /* GP2_LVL */ -#define WM8996_GP2_LVL_SHIFT 6 /* GP2_LVL */ -#define WM8996_GP2_LVL_WIDTH 1 /* GP2_LVL */ -#define WM8996_GP2_FN_MASK 0x000F /* GP2_FN - [3:0] */ -#define WM8996_GP2_FN_SHIFT 0 /* GP2_FN - [3:0] */ -#define WM8996_GP2_FN_WIDTH 4 /* GP2_FN - [3:0] */ - -/* - * R1794 (0x702) - GPIO 3 - */ -#define WM8996_GP3_DIR 0x8000 /* GP3_DIR */ -#define WM8996_GP3_DIR_MASK 0x8000 /* GP3_DIR */ -#define WM8996_GP3_DIR_SHIFT 15 /* GP3_DIR */ -#define WM8996_GP3_DIR_WIDTH 1 /* GP3_DIR */ -#define WM8996_GP3_PU 0x4000 /* GP3_PU */ -#define WM8996_GP3_PU_MASK 0x4000 /* GP3_PU */ -#define WM8996_GP3_PU_SHIFT 14 /* GP3_PU */ -#define WM8996_GP3_PU_WIDTH 1 /* GP3_PU */ -#define WM8996_GP3_PD 0x2000 /* GP3_PD */ -#define WM8996_GP3_PD_MASK 0x2000 /* GP3_PD */ -#define WM8996_GP3_PD_SHIFT 13 /* GP3_PD */ -#define WM8996_GP3_PD_WIDTH 1 /* GP3_PD */ -#define WM8996_GP3_POL 0x0400 /* GP3_POL */ -#define WM8996_GP3_POL_MASK 0x0400 /* GP3_POL */ -#define WM8996_GP3_POL_SHIFT 10 /* GP3_POL */ -#define WM8996_GP3_POL_WIDTH 1 /* GP3_POL */ -#define WM8996_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */ -#define WM8996_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */ -#define WM8996_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */ -#define WM8996_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */ -#define WM8996_GP3_DB 0x0100 /* GP3_DB */ -#define WM8996_GP3_DB_MASK 0x0100 /* GP3_DB */ -#define WM8996_GP3_DB_SHIFT 8 /* GP3_DB */ -#define WM8996_GP3_DB_WIDTH 1 /* GP3_DB */ -#define WM8996_GP3_LVL 0x0040 /* GP3_LVL */ -#define WM8996_GP3_LVL_MASK 0x0040 /* GP3_LVL */ -#define WM8996_GP3_LVL_SHIFT 6 /* GP3_LVL */ -#define WM8996_GP3_LVL_WIDTH 1 /* GP3_LVL */ -#define WM8996_GP3_FN_MASK 0x000F /* GP3_FN - [3:0] */ -#define WM8996_GP3_FN_SHIFT 0 /* GP3_FN - [3:0] */ -#define WM8996_GP3_FN_WIDTH 4 /* GP3_FN - [3:0] */ - -/* - * R1795 (0x703) - GPIO 4 - */ -#define WM8996_GP4_DIR 0x8000 /* GP4_DIR */ -#define WM8996_GP4_DIR_MASK 0x8000 /* GP4_DIR */ -#define WM8996_GP4_DIR_SHIFT 15 /* GP4_DIR */ -#define WM8996_GP4_DIR_WIDTH 1 /* GP4_DIR */ -#define WM8996_GP4_PU 0x4000 /* GP4_PU */ -#define WM8996_GP4_PU_MASK 0x4000 /* GP4_PU */ -#define WM8996_GP4_PU_SHIFT 14 /* GP4_PU */ -#define WM8996_GP4_PU_WIDTH 1 /* GP4_PU */ -#define WM8996_GP4_PD 0x2000 /* GP4_PD */ -#define WM8996_GP4_PD_MASK 0x2000 /* GP4_PD */ -#define WM8996_GP4_PD_SHIFT 13 /* GP4_PD */ -#define WM8996_GP4_PD_WIDTH 1 /* GP4_PD */ -#define WM8996_GP4_POL 0x0400 /* GP4_POL */ -#define WM8996_GP4_POL_MASK 0x0400 /* GP4_POL */ -#define WM8996_GP4_POL_SHIFT 10 /* GP4_POL */ -#define WM8996_GP4_POL_WIDTH 1 /* GP4_POL */ -#define WM8996_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */ -#define WM8996_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */ -#define WM8996_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */ -#define WM8996_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */ -#define WM8996_GP4_DB 0x0100 /* GP4_DB */ -#define WM8996_GP4_DB_MASK 0x0100 /* GP4_DB */ -#define WM8996_GP4_DB_SHIFT 8 /* GP4_DB */ -#define WM8996_GP4_DB_WIDTH 1 /* GP4_DB */ -#define WM8996_GP4_LVL 0x0040 /* GP4_LVL */ -#define WM8996_GP4_LVL_MASK 0x0040 /* GP4_LVL */ -#define WM8996_GP4_LVL_SHIFT 6 /* GP4_LVL */ -#define WM8996_GP4_LVL_WIDTH 1 /* GP4_LVL */ -#define WM8996_GP4_FN_MASK 0x000F /* GP4_FN - [3:0] */ -#define WM8996_GP4_FN_SHIFT 0 /* GP4_FN - [3:0] */ -#define WM8996_GP4_FN_WIDTH 4 /* GP4_FN - [3:0] */ - -/* - * R1796 (0x704) - GPIO 5 - */ -#define WM8996_GP5_DIR 0x8000 /* GP5_DIR */ -#define WM8996_GP5_DIR_MASK 0x8000 /* GP5_DIR */ -#define WM8996_GP5_DIR_SHIFT 15 /* GP5_DIR */ -#define WM8996_GP5_DIR_WIDTH 1 /* GP5_DIR */ -#define WM8996_GP5_PU 0x4000 /* GP5_PU */ -#define WM8996_GP5_PU_MASK 0x4000 /* GP5_PU */ -#define WM8996_GP5_PU_SHIFT 14 /* GP5_PU */ -#define WM8996_GP5_PU_WIDTH 1 /* GP5_PU */ -#define WM8996_GP5_PD 0x2000 /* GP5_PD */ -#define WM8996_GP5_PD_MASK 0x2000 /* GP5_PD */ -#define WM8996_GP5_PD_SHIFT 13 /* GP5_PD */ -#define WM8996_GP5_PD_WIDTH 1 /* GP5_PD */ -#define WM8996_GP5_POL 0x0400 /* GP5_POL */ -#define WM8996_GP5_POL_MASK 0x0400 /* GP5_POL */ -#define WM8996_GP5_POL_SHIFT 10 /* GP5_POL */ -#define WM8996_GP5_POL_WIDTH 1 /* GP5_POL */ -#define WM8996_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */ -#define WM8996_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */ -#define WM8996_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */ -#define WM8996_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */ -#define WM8996_GP5_DB 0x0100 /* GP5_DB */ -#define WM8996_GP5_DB_MASK 0x0100 /* GP5_DB */ -#define WM8996_GP5_DB_SHIFT 8 /* GP5_DB */ -#define WM8996_GP5_DB_WIDTH 1 /* GP5_DB */ -#define WM8996_GP5_LVL 0x0040 /* GP5_LVL */ -#define WM8996_GP5_LVL_MASK 0x0040 /* GP5_LVL */ -#define WM8996_GP5_LVL_SHIFT 6 /* GP5_LVL */ -#define WM8996_GP5_LVL_WIDTH 1 /* GP5_LVL */ -#define WM8996_GP5_FN_MASK 0x000F /* GP5_FN - [3:0] */ -#define WM8996_GP5_FN_SHIFT 0 /* GP5_FN - [3:0] */ -#define WM8996_GP5_FN_WIDTH 4 /* GP5_FN - [3:0] */ - -/* - * R1824 (0x720) - Pull Control (1) - */ -#define WM8996_DMICDAT2_PD 0x1000 /* DMICDAT2_PD */ -#define WM8996_DMICDAT2_PD_MASK 0x1000 /* DMICDAT2_PD */ -#define WM8996_DMICDAT2_PD_SHIFT 12 /* DMICDAT2_PD */ -#define WM8996_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */ -#define WM8996_DMICDAT1_PD 0x0400 /* DMICDAT1_PD */ -#define WM8996_DMICDAT1_PD_MASK 0x0400 /* DMICDAT1_PD */ -#define WM8996_DMICDAT1_PD_SHIFT 10 /* DMICDAT1_PD */ -#define WM8996_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */ -#define WM8996_MCLK2_PU 0x0200 /* MCLK2_PU */ -#define WM8996_MCLK2_PU_MASK 0x0200 /* MCLK2_PU */ -#define WM8996_MCLK2_PU_SHIFT 9 /* MCLK2_PU */ -#define WM8996_MCLK2_PU_WIDTH 1 /* MCLK2_PU */ -#define WM8996_MCLK2_PD 0x0100 /* MCLK2_PD */ -#define WM8996_MCLK2_PD_MASK 0x0100 /* MCLK2_PD */ -#define WM8996_MCLK2_PD_SHIFT 8 /* MCLK2_PD */ -#define WM8996_MCLK2_PD_WIDTH 1 /* MCLK2_PD */ -#define WM8996_MCLK1_PU 0x0080 /* MCLK1_PU */ -#define WM8996_MCLK1_PU_MASK 0x0080 /* MCLK1_PU */ -#define WM8996_MCLK1_PU_SHIFT 7 /* MCLK1_PU */ -#define WM8996_MCLK1_PU_WIDTH 1 /* MCLK1_PU */ -#define WM8996_MCLK1_PD 0x0040 /* MCLK1_PD */ -#define WM8996_MCLK1_PD_MASK 0x0040 /* MCLK1_PD */ -#define WM8996_MCLK1_PD_SHIFT 6 /* MCLK1_PD */ -#define WM8996_MCLK1_PD_WIDTH 1 /* MCLK1_PD */ -#define WM8996_DACDAT1_PU 0x0020 /* DACDAT1_PU */ -#define WM8996_DACDAT1_PU_MASK 0x0020 /* DACDAT1_PU */ -#define WM8996_DACDAT1_PU_SHIFT 5 /* DACDAT1_PU */ -#define WM8996_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */ -#define WM8996_DACDAT1_PD 0x0010 /* DACDAT1_PD */ -#define WM8996_DACDAT1_PD_MASK 0x0010 /* DACDAT1_PD */ -#define WM8996_DACDAT1_PD_SHIFT 4 /* DACDAT1_PD */ -#define WM8996_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */ -#define WM8996_DACLRCLK1_PU 0x0008 /* DACLRCLK1_PU */ -#define WM8996_DACLRCLK1_PU_MASK 0x0008 /* DACLRCLK1_PU */ -#define WM8996_DACLRCLK1_PU_SHIFT 3 /* DACLRCLK1_PU */ -#define WM8996_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */ -#define WM8996_DACLRCLK1_PD 0x0004 /* DACLRCLK1_PD */ -#define WM8996_DACLRCLK1_PD_MASK 0x0004 /* DACLRCLK1_PD */ -#define WM8996_DACLRCLK1_PD_SHIFT 2 /* DACLRCLK1_PD */ -#define WM8996_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */ -#define WM8996_BCLK1_PU 0x0002 /* BCLK1_PU */ -#define WM8996_BCLK1_PU_MASK 0x0002 /* BCLK1_PU */ -#define WM8996_BCLK1_PU_SHIFT 1 /* BCLK1_PU */ -#define WM8996_BCLK1_PU_WIDTH 1 /* BCLK1_PU */ -#define WM8996_BCLK1_PD 0x0001 /* BCLK1_PD */ -#define WM8996_BCLK1_PD_MASK 0x0001 /* BCLK1_PD */ -#define WM8996_BCLK1_PD_SHIFT 0 /* BCLK1_PD */ -#define WM8996_BCLK1_PD_WIDTH 1 /* BCLK1_PD */ - -/* - * R1825 (0x721) - Pull Control (2) - */ -#define WM8996_LDO1ENA_PD 0x0100 /* LDO1ENA_PD */ -#define WM8996_LDO1ENA_PD_MASK 0x0100 /* LDO1ENA_PD */ -#define WM8996_LDO1ENA_PD_SHIFT 8 /* LDO1ENA_PD */ -#define WM8996_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */ -#define WM8996_ADDR_PD 0x0040 /* ADDR_PD */ -#define WM8996_ADDR_PD_MASK 0x0040 /* ADDR_PD */ -#define WM8996_ADDR_PD_SHIFT 6 /* ADDR_PD */ -#define WM8996_ADDR_PD_WIDTH 1 /* ADDR_PD */ -#define WM8996_DACDAT2_PU 0x0020 /* DACDAT2_PU */ -#define WM8996_DACDAT2_PU_MASK 0x0020 /* DACDAT2_PU */ -#define WM8996_DACDAT2_PU_SHIFT 5 /* DACDAT2_PU */ -#define WM8996_DACDAT2_PU_WIDTH 1 /* DACDAT2_PU */ -#define WM8996_DACDAT2_PD 0x0010 /* DACDAT2_PD */ -#define WM8996_DACDAT2_PD_MASK 0x0010 /* DACDAT2_PD */ -#define WM8996_DACDAT2_PD_SHIFT 4 /* DACDAT2_PD */ -#define WM8996_DACDAT2_PD_WIDTH 1 /* DACDAT2_PD */ -#define WM8996_DACLRCLK2_PU 0x0008 /* DACLRCLK2_PU */ -#define WM8996_DACLRCLK2_PU_MASK 0x0008 /* DACLRCLK2_PU */ -#define WM8996_DACLRCLK2_PU_SHIFT 3 /* DACLRCLK2_PU */ -#define WM8996_DACLRCLK2_PU_WIDTH 1 /* DACLRCLK2_PU */ -#define WM8996_DACLRCLK2_PD 0x0004 /* DACLRCLK2_PD */ -#define WM8996_DACLRCLK2_PD_MASK 0x0004 /* DACLRCLK2_PD */ -#define WM8996_DACLRCLK2_PD_SHIFT 2 /* DACLRCLK2_PD */ -#define WM8996_DACLRCLK2_PD_WIDTH 1 /* DACLRCLK2_PD */ -#define WM8996_BCLK2_PU 0x0002 /* BCLK2_PU */ -#define WM8996_BCLK2_PU_MASK 0x0002 /* BCLK2_PU */ -#define WM8996_BCLK2_PU_SHIFT 1 /* BCLK2_PU */ -#define WM8996_BCLK2_PU_WIDTH 1 /* BCLK2_PU */ -#define WM8996_BCLK2_PD 0x0001 /* BCLK2_PD */ -#define WM8996_BCLK2_PD_MASK 0x0001 /* BCLK2_PD */ -#define WM8996_BCLK2_PD_SHIFT 0 /* BCLK2_PD */ -#define WM8996_BCLK2_PD_WIDTH 1 /* BCLK2_PD */ - -/* - * R1840 (0x730) - Interrupt Status 1 - */ -#define WM8996_GP5_EINT 0x0010 /* GP5_EINT */ -#define WM8996_GP5_EINT_MASK 0x0010 /* GP5_EINT */ -#define WM8996_GP5_EINT_SHIFT 4 /* GP5_EINT */ -#define WM8996_GP5_EINT_WIDTH 1 /* GP5_EINT */ -#define WM8996_GP4_EINT 0x0008 /* GP4_EINT */ -#define WM8996_GP4_EINT_MASK 0x0008 /* GP4_EINT */ -#define WM8996_GP4_EINT_SHIFT 3 /* GP4_EINT */ -#define WM8996_GP4_EINT_WIDTH 1 /* GP4_EINT */ -#define WM8996_GP3_EINT 0x0004 /* GP3_EINT */ -#define WM8996_GP3_EINT_MASK 0x0004 /* GP3_EINT */ -#define WM8996_GP3_EINT_SHIFT 2 /* GP3_EINT */ -#define WM8996_GP3_EINT_WIDTH 1 /* GP3_EINT */ -#define WM8996_GP2_EINT 0x0002 /* GP2_EINT */ -#define WM8996_GP2_EINT_MASK 0x0002 /* GP2_EINT */ -#define WM8996_GP2_EINT_SHIFT 1 /* GP2_EINT */ -#define WM8996_GP2_EINT_WIDTH 1 /* GP2_EINT */ -#define WM8996_GP1_EINT 0x0001 /* GP1_EINT */ -#define WM8996_GP1_EINT_MASK 0x0001 /* GP1_EINT */ -#define WM8996_GP1_EINT_SHIFT 0 /* GP1_EINT */ -#define WM8996_GP1_EINT_WIDTH 1 /* GP1_EINT */ - -/* - * R1841 (0x731) - Interrupt Status 2 - */ -#define WM8996_DCS_DONE_23_EINT 0x1000 /* DCS_DONE_23_EINT */ -#define WM8996_DCS_DONE_23_EINT_MASK 0x1000 /* DCS_DONE_23_EINT */ -#define WM8996_DCS_DONE_23_EINT_SHIFT 12 /* DCS_DONE_23_EINT */ -#define WM8996_DCS_DONE_23_EINT_WIDTH 1 /* DCS_DONE_23_EINT */ -#define WM8996_DCS_DONE_01_EINT 0x0800 /* DCS_DONE_01_EINT */ -#define WM8996_DCS_DONE_01_EINT_MASK 0x0800 /* DCS_DONE_01_EINT */ -#define WM8996_DCS_DONE_01_EINT_SHIFT 11 /* DCS_DONE_01_EINT */ -#define WM8996_DCS_DONE_01_EINT_WIDTH 1 /* DCS_DONE_01_EINT */ -#define WM8996_WSEQ_DONE_EINT 0x0400 /* WSEQ_DONE_EINT */ -#define WM8996_WSEQ_DONE_EINT_MASK 0x0400 /* WSEQ_DONE_EINT */ -#define WM8996_WSEQ_DONE_EINT_SHIFT 10 /* WSEQ_DONE_EINT */ -#define WM8996_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */ -#define WM8996_FIFOS_ERR_EINT 0x0200 /* FIFOS_ERR_EINT */ -#define WM8996_FIFOS_ERR_EINT_MASK 0x0200 /* FIFOS_ERR_EINT */ -#define WM8996_FIFOS_ERR_EINT_SHIFT 9 /* FIFOS_ERR_EINT */ -#define WM8996_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */ -#define WM8996_DSP2DRC_SIG_DET_EINT 0x0080 /* DSP2DRC_SIG_DET_EINT */ -#define WM8996_DSP2DRC_SIG_DET_EINT_MASK 0x0080 /* DSP2DRC_SIG_DET_EINT */ -#define WM8996_DSP2DRC_SIG_DET_EINT_SHIFT 7 /* DSP2DRC_SIG_DET_EINT */ -#define WM8996_DSP2DRC_SIG_DET_EINT_WIDTH 1 /* DSP2DRC_SIG_DET_EINT */ -#define WM8996_DSP1DRC_SIG_DET_EINT 0x0040 /* DSP1DRC_SIG_DET_EINT */ -#define WM8996_DSP1DRC_SIG_DET_EINT_MASK 0x0040 /* DSP1DRC_SIG_DET_EINT */ -#define WM8996_DSP1DRC_SIG_DET_EINT_SHIFT 6 /* DSP1DRC_SIG_DET_EINT */ -#define WM8996_DSP1DRC_SIG_DET_EINT_WIDTH 1 /* DSP1DRC_SIG_DET_EINT */ -#define WM8996_FLL_SW_CLK_DONE_EINT 0x0008 /* FLL_SW_CLK_DONE_EINT */ -#define WM8996_FLL_SW_CLK_DONE_EINT_MASK 0x0008 /* FLL_SW_CLK_DONE_EINT */ -#define WM8996_FLL_SW_CLK_DONE_EINT_SHIFT 3 /* FLL_SW_CLK_DONE_EINT */ -#define WM8996_FLL_SW_CLK_DONE_EINT_WIDTH 1 /* FLL_SW_CLK_DONE_EINT */ -#define WM8996_FLL_LOCK_EINT 0x0004 /* FLL_LOCK_EINT */ -#define WM8996_FLL_LOCK_EINT_MASK 0x0004 /* FLL_LOCK_EINT */ -#define WM8996_FLL_LOCK_EINT_SHIFT 2 /* FLL_LOCK_EINT */ -#define WM8996_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ -#define WM8996_HP_DONE_EINT 0x0002 /* HP_DONE_EINT */ -#define WM8996_HP_DONE_EINT_MASK 0x0002 /* HP_DONE_EINT */ -#define WM8996_HP_DONE_EINT_SHIFT 1 /* HP_DONE_EINT */ -#define WM8996_HP_DONE_EINT_WIDTH 1 /* HP_DONE_EINT */ -#define WM8996_MICD_EINT 0x0001 /* MICD_EINT */ -#define WM8996_MICD_EINT_MASK 0x0001 /* MICD_EINT */ -#define WM8996_MICD_EINT_SHIFT 0 /* MICD_EINT */ -#define WM8996_MICD_EINT_WIDTH 1 /* MICD_EINT */ - -/* - * R1842 (0x732) - Interrupt Raw Status 2 - */ -#define WM8996_DCS_DONE_23_STS 0x1000 /* DCS_DONE_23_STS */ -#define WM8996_DCS_DONE_23_STS_MASK 0x1000 /* DCS_DONE_23_STS */ -#define WM8996_DCS_DONE_23_STS_SHIFT 12 /* DCS_DONE_23_STS */ -#define WM8996_DCS_DONE_23_STS_WIDTH 1 /* DCS_DONE_23_STS */ -#define WM8996_DCS_DONE_01_STS 0x0800 /* DCS_DONE_01_STS */ -#define WM8996_DCS_DONE_01_STS_MASK 0x0800 /* DCS_DONE_01_STS */ -#define WM8996_DCS_DONE_01_STS_SHIFT 11 /* DCS_DONE_01_STS */ -#define WM8996_DCS_DONE_01_STS_WIDTH 1 /* DCS_DONE_01_STS */ -#define WM8996_WSEQ_DONE_STS 0x0400 /* WSEQ_DONE_STS */ -#define WM8996_WSEQ_DONE_STS_MASK 0x0400 /* WSEQ_DONE_STS */ -#define WM8996_WSEQ_DONE_STS_SHIFT 10 /* WSEQ_DONE_STS */ -#define WM8996_WSEQ_DONE_STS_WIDTH 1 /* WSEQ_DONE_STS */ -#define WM8996_FIFOS_ERR_STS 0x0200 /* FIFOS_ERR_STS */ -#define WM8996_FIFOS_ERR_STS_MASK 0x0200 /* FIFOS_ERR_STS */ -#define WM8996_FIFOS_ERR_STS_SHIFT 9 /* FIFOS_ERR_STS */ -#define WM8996_FIFOS_ERR_STS_WIDTH 1 /* FIFOS_ERR_STS */ -#define WM8996_DSP2DRC_SIG_DET_STS 0x0080 /* DSP2DRC_SIG_DET_STS */ -#define WM8996_DSP2DRC_SIG_DET_STS_MASK 0x0080 /* DSP2DRC_SIG_DET_STS */ -#define WM8996_DSP2DRC_SIG_DET_STS_SHIFT 7 /* DSP2DRC_SIG_DET_STS */ -#define WM8996_DSP2DRC_SIG_DET_STS_WIDTH 1 /* DSP2DRC_SIG_DET_STS */ -#define WM8996_DSP1DRC_SIG_DET_STS 0x0040 /* DSP1DRC_SIG_DET_STS */ -#define WM8996_DSP1DRC_SIG_DET_STS_MASK 0x0040 /* DSP1DRC_SIG_DET_STS */ -#define WM8996_DSP1DRC_SIG_DET_STS_SHIFT 6 /* DSP1DRC_SIG_DET_STS */ -#define WM8996_DSP1DRC_SIG_DET_STS_WIDTH 1 /* DSP1DRC_SIG_DET_STS */ -#define WM8996_FLL_LOCK_STS 0x0004 /* FLL_LOCK_STS */ -#define WM8996_FLL_LOCK_STS_MASK 0x0004 /* FLL_LOCK_STS */ -#define WM8996_FLL_LOCK_STS_SHIFT 2 /* FLL_LOCK_STS */ -#define WM8996_FLL_LOCK_STS_WIDTH 1 /* FLL_LOCK_STS */ - -/* - * R1848 (0x738) - Interrupt Status 1 Mask - */ -#define WM8996_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */ -#define WM8996_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */ -#define WM8996_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */ -#define WM8996_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */ -#define WM8996_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */ -#define WM8996_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */ -#define WM8996_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */ -#define WM8996_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */ -#define WM8996_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */ -#define WM8996_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */ -#define WM8996_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */ -#define WM8996_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */ -#define WM8996_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */ -#define WM8996_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */ -#define WM8996_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */ -#define WM8996_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */ -#define WM8996_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */ -#define WM8996_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */ -#define WM8996_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */ -#define WM8996_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */ - -/* - * R1849 (0x739) - Interrupt Status 2 Mask - */ -#define WM8996_IM_DCS_DONE_23_EINT 0x1000 /* IM_DCS_DONE_23_EINT */ -#define WM8996_IM_DCS_DONE_23_EINT_MASK 0x1000 /* IM_DCS_DONE_23_EINT */ -#define WM8996_IM_DCS_DONE_23_EINT_SHIFT 12 /* IM_DCS_DONE_23_EINT */ -#define WM8996_IM_DCS_DONE_23_EINT_WIDTH 1 /* IM_DCS_DONE_23_EINT */ -#define WM8996_IM_DCS_DONE_01_EINT 0x0800 /* IM_DCS_DONE_01_EINT */ -#define WM8996_IM_DCS_DONE_01_EINT_MASK 0x0800 /* IM_DCS_DONE_01_EINT */ -#define WM8996_IM_DCS_DONE_01_EINT_SHIFT 11 /* IM_DCS_DONE_01_EINT */ -#define WM8996_IM_DCS_DONE_01_EINT_WIDTH 1 /* IM_DCS_DONE_01_EINT */ -#define WM8996_IM_WSEQ_DONE_EINT 0x0400 /* IM_WSEQ_DONE_EINT */ -#define WM8996_IM_WSEQ_DONE_EINT_MASK 0x0400 /* IM_WSEQ_DONE_EINT */ -#define WM8996_IM_WSEQ_DONE_EINT_SHIFT 10 /* IM_WSEQ_DONE_EINT */ -#define WM8996_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */ -#define WM8996_IM_FIFOS_ERR_EINT 0x0200 /* IM_FIFOS_ERR_EINT */ -#define WM8996_IM_FIFOS_ERR_EINT_MASK 0x0200 /* IM_FIFOS_ERR_EINT */ -#define WM8996_IM_FIFOS_ERR_EINT_SHIFT 9 /* IM_FIFOS_ERR_EINT */ -#define WM8996_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */ -#define WM8996_IM_DSP2DRC_SIG_DET_EINT 0x0080 /* IM_DSP2DRC_SIG_DET_EINT */ -#define WM8996_IM_DSP2DRC_SIG_DET_EINT_MASK 0x0080 /* IM_DSP2DRC_SIG_DET_EINT */ -#define WM8996_IM_DSP2DRC_SIG_DET_EINT_SHIFT 7 /* IM_DSP2DRC_SIG_DET_EINT */ -#define WM8996_IM_DSP2DRC_SIG_DET_EINT_WIDTH 1 /* IM_DSP2DRC_SIG_DET_EINT */ -#define WM8996_IM_DSP1DRC_SIG_DET_EINT 0x0040 /* IM_DSP1DRC_SIG_DET_EINT */ -#define WM8996_IM_DSP1DRC_SIG_DET_EINT_MASK 0x0040 /* IM_DSP1DRC_SIG_DET_EINT */ -#define WM8996_IM_DSP1DRC_SIG_DET_EINT_SHIFT 6 /* IM_DSP1DRC_SIG_DET_EINT */ -#define WM8996_IM_DSP1DRC_SIG_DET_EINT_WIDTH 1 /* IM_DSP1DRC_SIG_DET_EINT */ -#define WM8996_IM_FLL_SW_CLK_DONE_EINT 0x0008 /* IM_FLL_SW_CLK_DONE_EINT */ -#define WM8996_IM_FLL_SW_CLK_DONE_EINT_MASK 0x0008 /* IM_FLL_SW_CLK_DONE_EINT */ -#define WM8996_IM_FLL_SW_CLK_DONE_EINT_SHIFT 3 /* IM_FLL_SW_CLK_DONE_EINT */ -#define WM8996_IM_FLL_SW_CLK_DONE_EINT_WIDTH 1 /* IM_FLL_SW_CLK_DONE_EINT */ -#define WM8996_IM_FLL_LOCK_EINT 0x0004 /* IM_FLL_LOCK_EINT */ -#define WM8996_IM_FLL_LOCK_EINT_MASK 0x0004 /* IM_FLL_LOCK_EINT */ -#define WM8996_IM_FLL_LOCK_EINT_SHIFT 2 /* IM_FLL_LOCK_EINT */ -#define WM8996_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ -#define WM8996_IM_HP_DONE_EINT 0x0002 /* IM_HP_DONE_EINT */ -#define WM8996_IM_HP_DONE_EINT_MASK 0x0002 /* IM_HP_DONE_EINT */ -#define WM8996_IM_HP_DONE_EINT_SHIFT 1 /* IM_HP_DONE_EINT */ -#define WM8996_IM_HP_DONE_EINT_WIDTH 1 /* IM_HP_DONE_EINT */ -#define WM8996_IM_MICD_EINT 0x0001 /* IM_MICD_EINT */ -#define WM8996_IM_MICD_EINT_MASK 0x0001 /* IM_MICD_EINT */ -#define WM8996_IM_MICD_EINT_SHIFT 0 /* IM_MICD_EINT */ -#define WM8996_IM_MICD_EINT_WIDTH 1 /* IM_MICD_EINT */ - -/* - * R1856 (0x740) - Interrupt Control - */ -#define WM8996_IM_IRQ 0x0001 /* IM_IRQ */ -#define WM8996_IM_IRQ_MASK 0x0001 /* IM_IRQ */ -#define WM8996_IM_IRQ_SHIFT 0 /* IM_IRQ */ -#define WM8996_IM_IRQ_WIDTH 1 /* IM_IRQ */ - -/* - * R2048 (0x800) - Left PDM Speaker - */ -#define WM8996_SPKL_ENA 0x0010 /* SPKL_ENA */ -#define WM8996_SPKL_ENA_MASK 0x0010 /* SPKL_ENA */ -#define WM8996_SPKL_ENA_SHIFT 4 /* SPKL_ENA */ -#define WM8996_SPKL_ENA_WIDTH 1 /* SPKL_ENA */ -#define WM8996_SPKL_MUTE 0x0008 /* SPKL_MUTE */ -#define WM8996_SPKL_MUTE_MASK 0x0008 /* SPKL_MUTE */ -#define WM8996_SPKL_MUTE_SHIFT 3 /* SPKL_MUTE */ -#define WM8996_SPKL_MUTE_WIDTH 1 /* SPKL_MUTE */ -#define WM8996_SPKL_MUTE_ZC 0x0004 /* SPKL_MUTE_ZC */ -#define WM8996_SPKL_MUTE_ZC_MASK 0x0004 /* SPKL_MUTE_ZC */ -#define WM8996_SPKL_MUTE_ZC_SHIFT 2 /* SPKL_MUTE_ZC */ -#define WM8996_SPKL_MUTE_ZC_WIDTH 1 /* SPKL_MUTE_ZC */ -#define WM8996_SPKL_SRC_MASK 0x0003 /* SPKL_SRC - [1:0] */ -#define WM8996_SPKL_SRC_SHIFT 0 /* SPKL_SRC - [1:0] */ -#define WM8996_SPKL_SRC_WIDTH 2 /* SPKL_SRC - [1:0] */ - -/* - * R2049 (0x801) - Right PDM Speaker - */ -#define WM8996_SPKR_ENA 0x0010 /* SPKR_ENA */ -#define WM8996_SPKR_ENA_MASK 0x0010 /* SPKR_ENA */ -#define WM8996_SPKR_ENA_SHIFT 4 /* SPKR_ENA */ -#define WM8996_SPKR_ENA_WIDTH 1 /* SPKR_ENA */ -#define WM8996_SPKR_MUTE 0x0008 /* SPKR_MUTE */ -#define WM8996_SPKR_MUTE_MASK 0x0008 /* SPKR_MUTE */ -#define WM8996_SPKR_MUTE_SHIFT 3 /* SPKR_MUTE */ -#define WM8996_SPKR_MUTE_WIDTH 1 /* SPKR_MUTE */ -#define WM8996_SPKR_MUTE_ZC 0x0004 /* SPKR_MUTE_ZC */ -#define WM8996_SPKR_MUTE_ZC_MASK 0x0004 /* SPKR_MUTE_ZC */ -#define WM8996_SPKR_MUTE_ZC_SHIFT 2 /* SPKR_MUTE_ZC */ -#define WM8996_SPKR_MUTE_ZC_WIDTH 1 /* SPKR_MUTE_ZC */ -#define WM8996_SPKR_SRC_MASK 0x0003 /* SPKR_SRC - [1:0] */ -#define WM8996_SPKR_SRC_SHIFT 0 /* SPKR_SRC - [1:0] */ -#define WM8996_SPKR_SRC_WIDTH 2 /* SPKR_SRC - [1:0] */ - -/* - * R2050 (0x802) - PDM Speaker Mute Sequence - */ -#define WM8996_SPK_MUTE_ENDIAN 0x0100 /* SPK_MUTE_ENDIAN */ -#define WM8996_SPK_MUTE_ENDIAN_MASK 0x0100 /* SPK_MUTE_ENDIAN */ -#define WM8996_SPK_MUTE_ENDIAN_SHIFT 8 /* SPK_MUTE_ENDIAN */ -#define WM8996_SPK_MUTE_ENDIAN_WIDTH 1 /* SPK_MUTE_ENDIAN */ -#define WM8996_SPK_MUTE_SEQ1_MASK 0x00FF /* SPK_MUTE_SEQ1 - [7:0] */ -#define WM8996_SPK_MUTE_SEQ1_SHIFT 0 /* SPK_MUTE_SEQ1 - [7:0] */ -#define WM8996_SPK_MUTE_SEQ1_WIDTH 8 /* SPK_MUTE_SEQ1 - [7:0] */ - -/* - * R2051 (0x803) - PDM Speaker Volume - */ -#define WM8996_SPKR_VOL_MASK 0x00F0 /* SPKR_VOL - [7:4] */ -#define WM8996_SPKR_VOL_SHIFT 4 /* SPKR_VOL - [7:4] */ -#define WM8996_SPKR_VOL_WIDTH 4 /* SPKR_VOL - [7:4] */ -#define WM8996_SPKL_VOL_MASK 0x000F /* SPKL_VOL - [3:0] */ -#define WM8996_SPKL_VOL_SHIFT 0 /* SPKL_VOL - [3:0] */ -#define WM8996_SPKL_VOL_WIDTH 4 /* SPKL_VOL - [3:0] */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9081.c b/ANDROID_3.4.5/sound/soc/codecs/wm9081.c deleted file mode 100644 index 076c126e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9081.c +++ /dev/null @@ -1,1425 +0,0 @@ -/* - * wm9081.c -- WM9081 ALSA SoC Audio driver - * - * Author: Mark Brown - * - * Copyright 2009 Wolfson Microelectronics plc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "wm9081.h" - -static struct reg_default wm9081_reg[] = { - { 2, 0x00B9 }, /* R2 - Analogue Lineout */ - { 3, 0x00B9 }, /* R3 - Analogue Speaker PGA */ - { 4, 0x0001 }, /* R4 - VMID Control */ - { 5, 0x0068 }, /* R5 - Bias Control 1 */ - { 7, 0x0000 }, /* R7 - Analogue Mixer */ - { 8, 0x0000 }, /* R8 - Anti Pop Control */ - { 9, 0x01DB }, /* R9 - Analogue Speaker 1 */ - { 10, 0x0018 }, /* R10 - Analogue Speaker 2 */ - { 11, 0x0180 }, /* R11 - Power Management */ - { 12, 0x0000 }, /* R12 - Clock Control 1 */ - { 13, 0x0038 }, /* R13 - Clock Control 2 */ - { 14, 0x4000 }, /* R14 - Clock Control 3 */ - { 16, 0x0000 }, /* R16 - FLL Control 1 */ - { 17, 0x0200 }, /* R17 - FLL Control 2 */ - { 18, 0x0000 }, /* R18 - FLL Control 3 */ - { 19, 0x0204 }, /* R19 - FLL Control 4 */ - { 20, 0x0000 }, /* R20 - FLL Control 5 */ - { 22, 0x0000 }, /* R22 - Audio Interface 1 */ - { 23, 0x0002 }, /* R23 - Audio Interface 2 */ - { 24, 0x0008 }, /* R24 - Audio Interface 3 */ - { 25, 0x0022 }, /* R25 - Audio Interface 4 */ - { 27, 0x0006 }, /* R27 - Interrupt Status Mask */ - { 28, 0x0000 }, /* R28 - Interrupt Polarity */ - { 29, 0x0000 }, /* R29 - Interrupt Control */ - { 30, 0x00C0 }, /* R30 - DAC Digital 1 */ - { 31, 0x0008 }, /* R31 - DAC Digital 2 */ - { 32, 0x09AF }, /* R32 - DRC 1 */ - { 33, 0x4201 }, /* R33 - DRC 2 */ - { 34, 0x0000 }, /* R34 - DRC 3 */ - { 35, 0x0000 }, /* R35 - DRC 4 */ - { 38, 0x0000 }, /* R38 - Write Sequencer 1 */ - { 39, 0x0000 }, /* R39 - Write Sequencer 2 */ - { 40, 0x0002 }, /* R40 - MW Slave 1 */ - { 42, 0x0000 }, /* R42 - EQ 1 */ - { 43, 0x0000 }, /* R43 - EQ 2 */ - { 44, 0x0FCA }, /* R44 - EQ 3 */ - { 45, 0x0400 }, /* R45 - EQ 4 */ - { 46, 0x00B8 }, /* R46 - EQ 5 */ - { 47, 0x1EB5 }, /* R47 - EQ 6 */ - { 48, 0xF145 }, /* R48 - EQ 7 */ - { 49, 0x0B75 }, /* R49 - EQ 8 */ - { 50, 0x01C5 }, /* R50 - EQ 9 */ - { 51, 0x169E }, /* R51 - EQ 10 */ - { 52, 0xF829 }, /* R52 - EQ 11 */ - { 53, 0x07AD }, /* R53 - EQ 12 */ - { 54, 0x1103 }, /* R54 - EQ 13 */ - { 55, 0x1C58 }, /* R55 - EQ 14 */ - { 56, 0xF373 }, /* R56 - EQ 15 */ - { 57, 0x0A54 }, /* R57 - EQ 16 */ - { 58, 0x0558 }, /* R58 - EQ 17 */ - { 59, 0x0564 }, /* R59 - EQ 18 */ - { 60, 0x0559 }, /* R60 - EQ 19 */ - { 61, 0x4000 }, /* R61 - EQ 20 */ -}; - -static struct { - int ratio; - int clk_sys_rate; -} clk_sys_rates[] = { - { 64, 0 }, - { 128, 1 }, - { 192, 2 }, - { 256, 3 }, - { 384, 4 }, - { 512, 5 }, - { 768, 6 }, - { 1024, 7 }, - { 1408, 8 }, - { 1536, 9 }, -}; - -static struct { - int rate; - int sample_rate; -} sample_rates[] = { - { 8000, 0 }, - { 11025, 1 }, - { 12000, 2 }, - { 16000, 3 }, - { 22050, 4 }, - { 24000, 5 }, - { 32000, 6 }, - { 44100, 7 }, - { 48000, 8 }, - { 88200, 9 }, - { 96000, 10 }, -}; - -static struct { - int div; /* *10 due to .5s */ - int bclk_div; -} bclk_divs[] = { - { 10, 0 }, - { 15, 1 }, - { 20, 2 }, - { 30, 3 }, - { 40, 4 }, - { 50, 5 }, - { 55, 6 }, - { 60, 7 }, - { 80, 8 }, - { 100, 9 }, - { 110, 10 }, - { 120, 11 }, - { 160, 12 }, - { 200, 13 }, - { 220, 14 }, - { 240, 15 }, - { 250, 16 }, - { 300, 17 }, - { 320, 18 }, - { 440, 19 }, - { 480, 20 }, -}; - -struct wm9081_priv { - struct regmap *regmap; - int sysclk_source; - int mclk_rate; - int sysclk_rate; - int fs; - int bclk; - int master; - int fll_fref; - int fll_fout; - int tdm_width; - struct wm9081_pdata pdata; -}; - -static bool wm9081_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM9081_SOFTWARE_RESET: - case WM9081_INTERRUPT_STATUS: - return true; - default: - return false; - } -} - -static bool wm9081_readable_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM9081_SOFTWARE_RESET: - case WM9081_ANALOGUE_LINEOUT: - case WM9081_ANALOGUE_SPEAKER_PGA: - case WM9081_VMID_CONTROL: - case WM9081_BIAS_CONTROL_1: - case WM9081_ANALOGUE_MIXER: - case WM9081_ANTI_POP_CONTROL: - case WM9081_ANALOGUE_SPEAKER_1: - case WM9081_ANALOGUE_SPEAKER_2: - case WM9081_POWER_MANAGEMENT: - case WM9081_CLOCK_CONTROL_1: - case WM9081_CLOCK_CONTROL_2: - case WM9081_CLOCK_CONTROL_3: - case WM9081_FLL_CONTROL_1: - case WM9081_FLL_CONTROL_2: - case WM9081_FLL_CONTROL_3: - case WM9081_FLL_CONTROL_4: - case WM9081_FLL_CONTROL_5: - case WM9081_AUDIO_INTERFACE_1: - case WM9081_AUDIO_INTERFACE_2: - case WM9081_AUDIO_INTERFACE_3: - case WM9081_AUDIO_INTERFACE_4: - case WM9081_INTERRUPT_STATUS: - case WM9081_INTERRUPT_STATUS_MASK: - case WM9081_INTERRUPT_POLARITY: - case WM9081_INTERRUPT_CONTROL: - case WM9081_DAC_DIGITAL_1: - case WM9081_DAC_DIGITAL_2: - case WM9081_DRC_1: - case WM9081_DRC_2: - case WM9081_DRC_3: - case WM9081_DRC_4: - case WM9081_WRITE_SEQUENCER_1: - case WM9081_WRITE_SEQUENCER_2: - case WM9081_MW_SLAVE_1: - case WM9081_EQ_1: - case WM9081_EQ_2: - case WM9081_EQ_3: - case WM9081_EQ_4: - case WM9081_EQ_5: - case WM9081_EQ_6: - case WM9081_EQ_7: - case WM9081_EQ_8: - case WM9081_EQ_9: - case WM9081_EQ_10: - case WM9081_EQ_11: - case WM9081_EQ_12: - case WM9081_EQ_13: - case WM9081_EQ_14: - case WM9081_EQ_15: - case WM9081_EQ_16: - case WM9081_EQ_17: - case WM9081_EQ_18: - case WM9081_EQ_19: - case WM9081_EQ_20: - return true; - default: - return false; - } -} - -static int wm9081_reset(struct regmap *map) -{ - return regmap_write(map, WM9081_SOFTWARE_RESET, 0x9081); -} - -static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); -static unsigned int drc_max_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0), - 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0); - -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); - -static const DECLARE_TLV_DB_SCALE(in_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); - -static const char *drc_high_text[] = { - "1", - "1/2", - "1/4", - "1/8", - "1/16", - "0", -}; - -static const struct soc_enum drc_high = - SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text); - -static const char *drc_low_text[] = { - "1", - "1/2", - "1/4", - "1/8", - "0", -}; - -static const struct soc_enum drc_low = - SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text); - -static const char *drc_atk_text[] = { - "181us", - "181us", - "363us", - "726us", - "1.45ms", - "2.9ms", - "5.8ms", - "11.6ms", - "23.2ms", - "46.4ms", - "92.8ms", - "185.6ms", -}; - -static const struct soc_enum drc_atk = - SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text); - -static const char *drc_dcy_text[] = { - "186ms", - "372ms", - "743ms", - "1.49s", - "2.97s", - "5.94s", - "11.89s", - "23.78s", - "47.56s", -}; - -static const struct soc_enum drc_dcy = - SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text); - -static const char *drc_qr_dcy_text[] = { - "0.725ms", - "1.45ms", - "5.8ms", -}; - -static const struct soc_enum drc_qr_dcy = - SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text); - -static const char *dac_deemph_text[] = { - "None", - "32kHz", - "44.1kHz", - "48kHz", -}; - -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text); - -static const char *speaker_mode_text[] = { - "Class D", - "Class AB", -}; - -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text); - -static int speaker_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg; - - reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2); - if (reg & WM9081_SPK_MODE) - ucontrol->value.integer.value[0] = 1; - else - ucontrol->value.integer.value[0] = 0; - - return 0; -} - -/* - * Stop any attempts to change speaker mode while the speaker is enabled. - * - * We also have some special anti-pop controls dependent on speaker - * mode which must be changed along with the mode. - */ -static int speaker_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg_pwr = snd_soc_read(codec, WM9081_POWER_MANAGEMENT); - unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2); - - /* Are we changing anything? */ - if (ucontrol->value.integer.value[0] == - ((reg2 & WM9081_SPK_MODE) != 0)) - return 0; - - /* Don't try to change modes while enabled */ - if (reg_pwr & WM9081_SPK_ENA) - return -EINVAL; - - if (ucontrol->value.integer.value[0]) { - /* Class AB */ - reg2 &= ~(WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL); - reg2 |= WM9081_SPK_MODE; - } else { - /* Class D */ - reg2 |= WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL; - reg2 &= ~WM9081_SPK_MODE; - } - - snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2); - - return 0; -} - -static const struct snd_kcontrol_new wm9081_snd_controls[] = { -SOC_SINGLE_TLV("IN1 Volume", WM9081_ANALOGUE_MIXER, 1, 1, 1, in_tlv), -SOC_SINGLE_TLV("IN2 Volume", WM9081_ANALOGUE_MIXER, 3, 1, 1, in_tlv), - -SOC_SINGLE_TLV("Playback Volume", WM9081_DAC_DIGITAL_1, 1, 96, 0, dac_tlv), - -SOC_SINGLE("LINEOUT Switch", WM9081_ANALOGUE_LINEOUT, 7, 1, 1), -SOC_SINGLE("LINEOUT ZC Switch", WM9081_ANALOGUE_LINEOUT, 6, 1, 0), -SOC_SINGLE_TLV("LINEOUT Volume", WM9081_ANALOGUE_LINEOUT, 0, 63, 0, out_tlv), - -SOC_SINGLE("DRC Switch", WM9081_DRC_1, 15, 1, 0), -SOC_ENUM("DRC High Slope", drc_high), -SOC_ENUM("DRC Low Slope", drc_low), -SOC_SINGLE_TLV("DRC Input Volume", WM9081_DRC_4, 5, 60, 1, drc_in_tlv), -SOC_SINGLE_TLV("DRC Output Volume", WM9081_DRC_4, 0, 30, 1, drc_out_tlv), -SOC_SINGLE_TLV("DRC Minimum Volume", WM9081_DRC_2, 2, 3, 1, drc_min_tlv), -SOC_SINGLE_TLV("DRC Maximum Volume", WM9081_DRC_2, 0, 3, 0, drc_max_tlv), -SOC_ENUM("DRC Attack", drc_atk), -SOC_ENUM("DRC Decay", drc_dcy), -SOC_SINGLE("DRC Quick Release Switch", WM9081_DRC_1, 2, 1, 0), -SOC_SINGLE_TLV("DRC Quick Release Volume", WM9081_DRC_2, 6, 3, 0, drc_qr_tlv), -SOC_ENUM("DRC Quick Release Decay", drc_qr_dcy), -SOC_SINGLE_TLV("DRC Startup Volume", WM9081_DRC_1, 6, 18, 0, drc_startup_tlv), - -SOC_SINGLE("EQ Switch", WM9081_EQ_1, 0, 1, 0), - -SOC_SINGLE("Speaker DC Volume", WM9081_ANALOGUE_SPEAKER_1, 3, 5, 0), -SOC_SINGLE("Speaker AC Volume", WM9081_ANALOGUE_SPEAKER_1, 0, 5, 0), -SOC_SINGLE("Speaker Switch", WM9081_ANALOGUE_SPEAKER_PGA, 7, 1, 1), -SOC_SINGLE("Speaker ZC Switch", WM9081_ANALOGUE_SPEAKER_PGA, 6, 1, 0), -SOC_SINGLE_TLV("Speaker Volume", WM9081_ANALOGUE_SPEAKER_PGA, 0, 63, 0, - out_tlv), -SOC_ENUM("DAC Deemphasis", dac_deemph), -SOC_ENUM_EXT("Speaker Mode", speaker_mode, speaker_mode_get, speaker_mode_put), -}; - -static const struct snd_kcontrol_new wm9081_eq_controls[] = { -SOC_SINGLE_TLV("EQ1 Volume", WM9081_EQ_1, 11, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Volume", WM9081_EQ_1, 6, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Volume", WM9081_EQ_1, 1, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Volume", WM9081_EQ_2, 11, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ5 Volume", WM9081_EQ_2, 6, 24, 0, eq_tlv), -}; - -static const struct snd_kcontrol_new mixer[] = { -SOC_DAPM_SINGLE("IN1 Switch", WM9081_ANALOGUE_MIXER, 0, 1, 0), -SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0), -}; - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_clk_ref_div; - u16 n; - u16 k; -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod, target; - unsigned int div; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - while ((Fref / div) > 13500000) { - div *= 2; - - if (div > 8) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - fll_div->fll_clk_ref_div = div / 2; - - pr_debug("Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 0; - target = Fout * 2; - while (target < 90000000) { - div++; - target *= 2; - if (div > 7) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - fll_div->fll_outdiv = div; - - pr_debug("Fvco=%dHz\n", target); - - /* Find an appropriate FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - target /= fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - /* Now, calculate N.K */ - Ndiv = target / Fref; - - fll_div->n = Ndiv; - Nmod = target % Fref; - pr_debug("Nmod=%d\n", Nmod); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, Fref); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - fll_div->k = K / 10; - - pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n", - fll_div->n, fll_div->k, - fll_div->fll_fratio, fll_div->fll_outdiv, - fll_div->fll_clk_ref_div); - - return 0; -} - -static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id, - unsigned int Fref, unsigned int Fout) -{ - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - u16 reg1, reg4, reg5; - struct _fll_div fll_div; - int ret; - int clk_sys_reg; - - /* Any change? */ - if (Fref == wm9081->fll_fref && Fout == wm9081->fll_fout) - return 0; - - /* Disable the FLL */ - if (Fout == 0) { - dev_dbg(codec->dev, "FLL disabled\n"); - wm9081->fll_fref = 0; - wm9081->fll_fout = 0; - - return 0; - } - - ret = fll_factors(&fll_div, Fref, Fout); - if (ret != 0) - return ret; - - reg5 = snd_soc_read(codec, WM9081_FLL_CONTROL_5); - reg5 &= ~WM9081_FLL_CLK_SRC_MASK; - - switch (fll_id) { - case WM9081_SYSCLK_FLL_MCLK: - reg5 |= 0x1; - break; - - default: - dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); - return -EINVAL; - } - - /* Disable CLK_SYS while we reconfigure */ - clk_sys_reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3); - if (clk_sys_reg & WM9081_CLK_SYS_ENA) - snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, - clk_sys_reg & ~WM9081_CLK_SYS_ENA); - - /* Any FLL configuration change requires that the FLL be - * disabled first. */ - reg1 = snd_soc_read(codec, WM9081_FLL_CONTROL_1); - reg1 &= ~WM9081_FLL_ENA; - snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1); - - /* Apply the configuration */ - if (fll_div.k) - reg1 |= WM9081_FLL_FRAC_MASK; - else - reg1 &= ~WM9081_FLL_FRAC_MASK; - snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1); - - snd_soc_write(codec, WM9081_FLL_CONTROL_2, - (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) | - (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT)); - snd_soc_write(codec, WM9081_FLL_CONTROL_3, fll_div.k); - - reg4 = snd_soc_read(codec, WM9081_FLL_CONTROL_4); - reg4 &= ~WM9081_FLL_N_MASK; - reg4 |= fll_div.n << WM9081_FLL_N_SHIFT; - snd_soc_write(codec, WM9081_FLL_CONTROL_4, reg4); - - reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK; - reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT; - snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5); - - /* Set gain to the recommended value */ - snd_soc_update_bits(codec, WM9081_FLL_CONTROL_4, - WM9081_FLL_GAIN_MASK, 0); - - /* Enable the FLL */ - snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA); - - /* Then bring CLK_SYS up again if it was disabled */ - if (clk_sys_reg & WM9081_CLK_SYS_ENA) - snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg); - - dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); - - wm9081->fll_fref = Fref; - wm9081->fll_fout = Fout; - - return 0; -} - -static int configure_clock(struct snd_soc_codec *codec) -{ - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - int new_sysclk, i, target; - unsigned int reg; - int ret = 0; - int mclkdiv = 0; - int fll = 0; - - switch (wm9081->sysclk_source) { - case WM9081_SYSCLK_MCLK: - if (wm9081->mclk_rate > 12225000) { - mclkdiv = 1; - wm9081->sysclk_rate = wm9081->mclk_rate / 2; - } else { - wm9081->sysclk_rate = wm9081->mclk_rate; - } - wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK, 0, 0); - break; - - case WM9081_SYSCLK_FLL_MCLK: - /* If we have a sample rate calculate a CLK_SYS that - * gives us a suitable DAC configuration, plus BCLK. - * Ideally we would check to see if we can clock - * directly from MCLK and only use the FLL if this is - * not the case, though care must be taken with free - * running mode. - */ - if (wm9081->master && wm9081->bclk) { - /* Make sure we can generate CLK_SYS and BCLK - * and that we've got 3MHz for optimal - * performance. */ - for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) { - target = wm9081->fs * clk_sys_rates[i].ratio; - new_sysclk = target; - if (target >= wm9081->bclk && - target > 3000000) - break; - } - - if (i == ARRAY_SIZE(clk_sys_rates)) - return -EINVAL; - - } else if (wm9081->fs) { - for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) { - new_sysclk = clk_sys_rates[i].ratio - * wm9081->fs; - if (new_sysclk > 3000000) - break; - } - - if (i == ARRAY_SIZE(clk_sys_rates)) - return -EINVAL; - - } else { - new_sysclk = 12288000; - } - - ret = wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK, - wm9081->mclk_rate, new_sysclk); - if (ret == 0) { - wm9081->sysclk_rate = new_sysclk; - - /* Switch SYSCLK over to FLL */ - fll = 1; - } else { - wm9081->sysclk_rate = wm9081->mclk_rate; - } - break; - - default: - return -EINVAL; - } - - reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_1); - if (mclkdiv) - reg |= WM9081_MCLKDIV2; - else - reg &= ~WM9081_MCLKDIV2; - snd_soc_write(codec, WM9081_CLOCK_CONTROL_1, reg); - - reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3); - if (fll) - reg |= WM9081_CLK_SRC_SEL; - else - reg &= ~WM9081_CLK_SRC_SEL; - snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, reg); - - dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate); - - return ret; -} - -static int clk_sys_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - - /* This should be done on init() for bypass paths */ - switch (wm9081->sysclk_source) { - case WM9081_SYSCLK_MCLK: - dev_dbg(codec->dev, "Using %dHz MCLK\n", wm9081->mclk_rate); - break; - case WM9081_SYSCLK_FLL_MCLK: - dev_dbg(codec->dev, "Using %dHz MCLK with FLL\n", - wm9081->mclk_rate); - break; - default: - dev_err(codec->dev, "System clock not configured\n"); - return -EINVAL; - } - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - configure_clock(codec); - break; - - case SND_SOC_DAPM_POST_PMD: - /* Disable the FLL if it's running */ - wm9081_set_fll(codec, 0, 0, 0); - break; - } - - return 0; -} - -static const struct snd_soc_dapm_widget wm9081_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1"), -SND_SOC_DAPM_INPUT("IN2"), - -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM9081_POWER_MANAGEMENT, 0, 0), - -SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0, - mixer, ARRAY_SIZE(mixer)), - -SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), - -SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0), -SND_SOC_DAPM_OUT_DRV("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0), - -SND_SOC_DAPM_OUTPUT("LINEOUT"), -SND_SOC_DAPM_OUTPUT("SPKN"), -SND_SOC_DAPM_OUTPUT("SPKP"), - -SND_SOC_DAPM_SUPPLY("CLK_SYS", WM9081_CLOCK_CONTROL_3, 0, 0, clk_sys_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("TSENSE", WM9081_POWER_MANAGEMENT, 7, 0, NULL, 0), -}; - - -static const struct snd_soc_dapm_route wm9081_audio_paths[] = { - { "DAC", NULL, "CLK_SYS" }, - { "DAC", NULL, "CLK_DSP" }, - - { "Mixer", "IN1 Switch", "IN1" }, - { "Mixer", "IN2 Switch", "IN2" }, - { "Mixer", "Playback Switch", "DAC" }, - - { "LINEOUT PGA", NULL, "Mixer" }, - { "LINEOUT PGA", NULL, "TOCLK" }, - { "LINEOUT PGA", NULL, "CLK_SYS" }, - - { "LINEOUT", NULL, "LINEOUT PGA" }, - - { "Speaker PGA", NULL, "Mixer" }, - { "Speaker PGA", NULL, "TOCLK" }, - { "Speaker PGA", NULL, "CLK_SYS" }, - - { "Speaker", NULL, "Speaker PGA" }, - { "Speaker", NULL, "TSENSE" }, - - { "SPKN", NULL, "Speaker" }, - { "SPKP", NULL, "Speaker" }, -}; - -static int wm9081_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID=2*40k */ - snd_soc_update_bits(codec, WM9081_VMID_CONTROL, - WM9081_VMID_SEL_MASK, 0x2); - - /* Normal bias current */ - snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, - WM9081_STBY_BIAS_ENA, 0); - break; - - case SND_SOC_BIAS_STANDBY: - /* Initial cold start */ - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - regcache_cache_only(wm9081->regmap, false); - regcache_sync(wm9081->regmap); - - /* Disable LINEOUT discharge */ - snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL, - WM9081_LINEOUT_DISCH, 0); - - /* Select startup bias source */ - snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, - WM9081_BIAS_SRC | WM9081_BIAS_ENA, - WM9081_BIAS_SRC | WM9081_BIAS_ENA); - - /* VMID 2*4k; Soft VMID ramp enable */ - snd_soc_update_bits(codec, WM9081_VMID_CONTROL, - WM9081_VMID_RAMP | - WM9081_VMID_SEL_MASK, - WM9081_VMID_RAMP | 0x6); - - mdelay(100); - - /* Normal bias enable & soft start off */ - snd_soc_update_bits(codec, WM9081_VMID_CONTROL, - WM9081_VMID_RAMP, 0); - - /* Standard bias source */ - snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, - WM9081_BIAS_SRC, 0); - } - - /* VMID 2*240k */ - snd_soc_update_bits(codec, WM9081_VMID_CONTROL, - WM9081_VMID_SEL_MASK, 0x04); - - /* Standby bias current on */ - snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, - WM9081_STBY_BIAS_ENA, - WM9081_STBY_BIAS_ENA); - break; - - case SND_SOC_BIAS_OFF: - /* Startup bias source and disable bias */ - snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, - WM9081_BIAS_SRC | WM9081_BIAS_ENA, - WM9081_BIAS_SRC); - - /* Disable VMID with soft ramping */ - snd_soc_update_bits(codec, WM9081_VMID_CONTROL, - WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK, - WM9081_VMID_RAMP); - - /* Actively discharge LINEOUT */ - snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL, - WM9081_LINEOUT_DISCH, - WM9081_LINEOUT_DISCH); - - regcache_cache_only(wm9081->regmap, true); - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - unsigned int aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2); - - aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV | - WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - wm9081->master = 0; - break; - case SND_SOC_DAIFMT_CBS_CFM: - aif2 |= WM9081_LRCLK_DIR; - wm9081->master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFS: - aif2 |= WM9081_BCLK_DIR; - wm9081->master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - aif2 |= WM9081_LRCLK_DIR | WM9081_BCLK_DIR; - wm9081->master = 1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif2 |= WM9081_AIF_LRCLK_INV; - case SND_SOC_DAIFMT_DSP_A: - aif2 |= 0x3; - break; - case SND_SOC_DAIFMT_I2S: - aif2 |= 0x2; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif2 |= 0x1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif2 |= WM9081_AIF_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif2 |= WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif2 |= WM9081_AIF_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif2 |= WM9081_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2); - - return 0; -} - -static int wm9081_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - int ret, i, best, best_val, cur_val; - unsigned int clk_ctrl2, aif1, aif2, aif3, aif4; - - clk_ctrl2 = snd_soc_read(codec, WM9081_CLOCK_CONTROL_2); - clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK); - - aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1); - - aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2); - aif2 &= ~WM9081_AIF_WL_MASK; - - aif3 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_3); - aif3 &= ~WM9081_BCLK_DIV_MASK; - - aif4 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_4); - aif4 &= ~WM9081_LRCLK_RATE_MASK; - - wm9081->fs = params_rate(params); - - if (wm9081->tdm_width) { - /* If TDM is set up then that fixes our BCLK. */ - int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >> - WM9081_AIFDAC_TDM_MODE_SHIFT) + 1; - - wm9081->bclk = wm9081->fs * wm9081->tdm_width * slots; - } else { - /* Otherwise work out a BCLK from the sample size */ - wm9081->bclk = 2 * wm9081->fs; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - wm9081->bclk *= 16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - wm9081->bclk *= 20; - aif2 |= 0x4; - break; - case SNDRV_PCM_FORMAT_S24_LE: - wm9081->bclk *= 24; - aif2 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S32_LE: - wm9081->bclk *= 32; - aif2 |= 0xc; - break; - default: - return -EINVAL; - } - } - - dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk); - - ret = configure_clock(codec); - if (ret != 0) - return ret; - - /* Select nearest CLK_SYS_RATE */ - best = 0; - best_val = abs((wm9081->sysclk_rate / clk_sys_rates[0].ratio) - - wm9081->fs); - for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) { - cur_val = abs((wm9081->sysclk_rate / - clk_sys_rates[i].ratio) - wm9081->fs); - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n", - clk_sys_rates[best].ratio); - clk_ctrl2 |= (clk_sys_rates[best].clk_sys_rate - << WM9081_CLK_SYS_RATE_SHIFT); - - /* SAMPLE_RATE */ - best = 0; - best_val = abs(wm9081->fs - sample_rates[0].rate); - for (i = 1; i < ARRAY_SIZE(sample_rates); i++) { - /* Closest match */ - cur_val = abs(wm9081->fs - sample_rates[i].rate); - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n", - sample_rates[best].rate); - clk_ctrl2 |= (sample_rates[best].sample_rate - << WM9081_SAMPLE_RATE_SHIFT); - - /* BCLK_DIV */ - best = 0; - best_val = INT_MAX; - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - cur_val = ((wm9081->sysclk_rate * 10) / bclk_divs[i].div) - - wm9081->bclk; - if (cur_val < 0) /* Table is sorted */ - break; - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - wm9081->bclk = (wm9081->sysclk_rate * 10) / bclk_divs[best].div; - dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n", - bclk_divs[best].div, wm9081->bclk); - aif3 |= bclk_divs[best].bclk_div; - - /* LRCLK is a simple fraction of BCLK */ - dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm9081->bclk / wm9081->fs); - aif4 |= wm9081->bclk / wm9081->fs; - - /* Apply a ReTune Mobile configuration if it's in use */ - if (wm9081->pdata.num_retune_configs) { - struct wm9081_pdata *pdata = &wm9081->pdata; - struct wm9081_retune_mobile_setting *s; - int eq1; - - best = 0; - best_val = abs(pdata->retune_configs[0].rate - wm9081->fs); - for (i = 0; i < pdata->num_retune_configs; i++) { - cur_val = abs(pdata->retune_configs[i].rate - - wm9081->fs); - if (cur_val < best_val) { - best_val = cur_val; - best = i; - } - } - s = &pdata->retune_configs[best]; - - dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", - s->name, s->rate); - - /* If the EQ is enabled then disable it while we write out */ - eq1 = snd_soc_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA; - if (eq1 & WM9081_EQ_ENA) - snd_soc_write(codec, WM9081_EQ_1, 0); - - /* Write out the other values */ - for (i = 1; i < ARRAY_SIZE(s->config); i++) - snd_soc_write(codec, WM9081_EQ_1 + i, s->config[i]); - - eq1 |= (s->config[0] & ~WM9081_EQ_ENA); - snd_soc_write(codec, WM9081_EQ_1, eq1); - } - - snd_soc_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2); - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2); - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_3, aif3); - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_4, aif4); - - return 0; -} - -static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - unsigned int reg; - - reg = snd_soc_read(codec, WM9081_DAC_DIGITAL_2); - - if (mute) - reg |= WM9081_DAC_MUTE; - else - reg &= ~WM9081_DAC_MUTE; - - snd_soc_write(codec, WM9081_DAC_DIGITAL_2, reg); - - return 0; -} - -static int wm9081_set_sysclk(struct snd_soc_codec *codec, int clk_id, - int source, unsigned int freq, int dir) -{ - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - - switch (clk_id) { - case WM9081_SYSCLK_MCLK: - case WM9081_SYSCLK_FLL_MCLK: - wm9081->sysclk_source = clk_id; - wm9081->mclk_rate = freq; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - unsigned int aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1); - - aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK); - - if (slots < 0 || slots > 4) - return -EINVAL; - - wm9081->tdm_width = slot_width; - - if (slots == 0) - slots = 1; - - aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT; - - switch (rx_mask) { - case 1: - break; - case 2: - aif1 |= 0x10; - break; - case 4: - aif1 |= 0x20; - break; - case 8: - aif1 |= 0x30; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_1, aif1); - - return 0; -} - -#define WM9081_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM9081_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static const struct snd_soc_dai_ops wm9081_dai_ops = { - .hw_params = wm9081_hw_params, - .set_fmt = wm9081_set_dai_fmt, - .digital_mute = wm9081_digital_mute, - .set_tdm_slot = wm9081_set_tdm_slot, -}; - -/* We report two channels because the CODEC processes a stereo signal, even - * though it is only capable of handling a mono output. - */ -static struct snd_soc_dai_driver wm9081_dai = { - .name = "wm9081-hifi", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM9081_RATES, - .formats = WM9081_FORMATS, - }, - .ops = &wm9081_dai_ops, -}; - -static int wm9081_probe(struct snd_soc_codec *codec) -{ - struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); - int ret; - - codec->control_data = wm9081->regmap; - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* Enable zero cross by default */ - snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT, - WM9081_LINEOUTZC, WM9081_LINEOUTZC); - snd_soc_update_bits(codec, WM9081_ANALOGUE_SPEAKER_PGA, - WM9081_SPKPGAZC, WM9081_SPKPGAZC); - - if (!wm9081->pdata.num_retune_configs) { - dev_dbg(codec->dev, - "No ReTune Mobile data, using normal EQ\n"); - snd_soc_add_codec_controls(codec, wm9081_eq_controls, - ARRAY_SIZE(wm9081_eq_controls)); - } - - return ret; -} - -static int wm9081_remove(struct snd_soc_codec *codec) -{ - wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { - .probe = wm9081_probe, - .remove = wm9081_remove, - - .set_sysclk = wm9081_set_sysclk, - .set_bias_level = wm9081_set_bias_level, - - .idle_bias_off = true, - - .controls = wm9081_snd_controls, - .num_controls = ARRAY_SIZE(wm9081_snd_controls), - .dapm_widgets = wm9081_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets), - .dapm_routes = wm9081_audio_paths, - .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths), -}; - -static const struct regmap_config wm9081_regmap = { - .reg_bits = 8, - .val_bits = 16, - - .max_register = WM9081_MAX_REGISTER, - .reg_defaults = wm9081_reg, - .num_reg_defaults = ARRAY_SIZE(wm9081_reg), - .volatile_reg = wm9081_volatile_register, - .readable_reg = wm9081_readable_register, - .cache_type = REGCACHE_RBTREE, -}; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm9081_priv *wm9081; - unsigned int reg; - int ret; - - wm9081 = devm_kzalloc(&i2c->dev, sizeof(struct wm9081_priv), - GFP_KERNEL); - if (wm9081 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, wm9081); - - wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap); - if (IS_ERR(wm9081->regmap)) { - ret = PTR_ERR(wm9081->regmap); - dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); - goto err; - } - - ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, ®); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); - goto err_regmap; - } - if (reg != 0x9081) { - dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg); - ret = -EINVAL; - goto err_regmap; - } - - ret = wm9081_reset(wm9081->regmap); - if (ret < 0) { - dev_err(&i2c->dev, "Failed to issue reset\n"); - goto err_regmap; - } - - if (dev_get_platdata(&i2c->dev)) - memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev), - sizeof(wm9081->pdata)); - - reg = 0; - if (wm9081->pdata.irq_high) - reg |= WM9081_IRQ_POL; - if (!wm9081->pdata.irq_cmos) - reg |= WM9081_IRQ_OP_CTRL; - regmap_update_bits(wm9081->regmap, WM9081_INTERRUPT_CONTROL, - WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg); - - regcache_cache_only(wm9081->regmap, true); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm9081, &wm9081_dai, 1); - if (ret < 0) - goto err_regmap; - - return 0; - -err_regmap: - regmap_exit(wm9081->regmap); -err: - - return ret; -} - -static __devexit int wm9081_i2c_remove(struct i2c_client *client) -{ - struct wm9081_priv *wm9081 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&client->dev); - regmap_exit(wm9081->regmap); - return 0; -} - -static const struct i2c_device_id wm9081_i2c_id[] = { - { "wm9081", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); - -static struct i2c_driver wm9081_i2c_driver = { - .driver = { - .name = "wm9081", - .owner = THIS_MODULE, - }, - .probe = wm9081_i2c_probe, - .remove = __devexit_p(wm9081_i2c_remove), - .id_table = wm9081_i2c_id, -}; -#endif - -module_i2c_driver(wm9081_i2c_driver); - -MODULE_DESCRIPTION("ASoC WM9081 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9081.h b/ANDROID_3.4.5/sound/soc/codecs/wm9081.h deleted file mode 100644 index 871cccb0..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9081.h +++ /dev/null @@ -1,784 +0,0 @@ -#ifndef WM9081_H -#define WM9081_H - -/* - * wm9081.c -- WM9081 ALSA SoC Audio driver - * - * Author: Mark Brown - * - * Copyright 2009 Wolfson Microelectronics plc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include - -/* - * SYSCLK sources - */ -#define WM9081_SYSCLK_MCLK 1 /* Use MCLK without FLL */ -#define WM9081_SYSCLK_FLL_MCLK 2 /* Use MCLK, enabling FLL if required */ - -/* - * Register values. - */ -#define WM9081_SOFTWARE_RESET 0x00 -#define WM9081_ANALOGUE_LINEOUT 0x02 -#define WM9081_ANALOGUE_SPEAKER_PGA 0x03 -#define WM9081_VMID_CONTROL 0x04 -#define WM9081_BIAS_CONTROL_1 0x05 -#define WM9081_ANALOGUE_MIXER 0x07 -#define WM9081_ANTI_POP_CONTROL 0x08 -#define WM9081_ANALOGUE_SPEAKER_1 0x09 -#define WM9081_ANALOGUE_SPEAKER_2 0x0A -#define WM9081_POWER_MANAGEMENT 0x0B -#define WM9081_CLOCK_CONTROL_1 0x0C -#define WM9081_CLOCK_CONTROL_2 0x0D -#define WM9081_CLOCK_CONTROL_3 0x0E -#define WM9081_FLL_CONTROL_1 0x10 -#define WM9081_FLL_CONTROL_2 0x11 -#define WM9081_FLL_CONTROL_3 0x12 -#define WM9081_FLL_CONTROL_4 0x13 -#define WM9081_FLL_CONTROL_5 0x14 -#define WM9081_AUDIO_INTERFACE_1 0x16 -#define WM9081_AUDIO_INTERFACE_2 0x17 -#define WM9081_AUDIO_INTERFACE_3 0x18 -#define WM9081_AUDIO_INTERFACE_4 0x19 -#define WM9081_INTERRUPT_STATUS 0x1A -#define WM9081_INTERRUPT_STATUS_MASK 0x1B -#define WM9081_INTERRUPT_POLARITY 0x1C -#define WM9081_INTERRUPT_CONTROL 0x1D -#define WM9081_DAC_DIGITAL_1 0x1E -#define WM9081_DAC_DIGITAL_2 0x1F -#define WM9081_DRC_1 0x20 -#define WM9081_DRC_2 0x21 -#define WM9081_DRC_3 0x22 -#define WM9081_DRC_4 0x23 -#define WM9081_WRITE_SEQUENCER_1 0x26 -#define WM9081_WRITE_SEQUENCER_2 0x27 -#define WM9081_MW_SLAVE_1 0x28 -#define WM9081_EQ_1 0x2A -#define WM9081_EQ_2 0x2B -#define WM9081_EQ_3 0x2C -#define WM9081_EQ_4 0x2D -#define WM9081_EQ_5 0x2E -#define WM9081_EQ_6 0x2F -#define WM9081_EQ_7 0x30 -#define WM9081_EQ_8 0x31 -#define WM9081_EQ_9 0x32 -#define WM9081_EQ_10 0x33 -#define WM9081_EQ_11 0x34 -#define WM9081_EQ_12 0x35 -#define WM9081_EQ_13 0x36 -#define WM9081_EQ_14 0x37 -#define WM9081_EQ_15 0x38 -#define WM9081_EQ_16 0x39 -#define WM9081_EQ_17 0x3A -#define WM9081_EQ_18 0x3B -#define WM9081_EQ_19 0x3C -#define WM9081_EQ_20 0x3D - -#define WM9081_REGISTER_COUNT 55 -#define WM9081_MAX_REGISTER 0x3D - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM9081_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ -#define WM9081_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ -#define WM9081_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ - -/* - * R2 (0x02) - Analogue Lineout - */ -#define WM9081_LINEOUT_MUTE 0x0080 /* LINEOUT_MUTE */ -#define WM9081_LINEOUT_MUTE_MASK 0x0080 /* LINEOUT_MUTE */ -#define WM9081_LINEOUT_MUTE_SHIFT 7 /* LINEOUT_MUTE */ -#define WM9081_LINEOUT_MUTE_WIDTH 1 /* LINEOUT_MUTE */ -#define WM9081_LINEOUTZC 0x0040 /* LINEOUTZC */ -#define WM9081_LINEOUTZC_MASK 0x0040 /* LINEOUTZC */ -#define WM9081_LINEOUTZC_SHIFT 6 /* LINEOUTZC */ -#define WM9081_LINEOUTZC_WIDTH 1 /* LINEOUTZC */ -#define WM9081_LINEOUT_VOL_MASK 0x003F /* LINEOUT_VOL - [5:0] */ -#define WM9081_LINEOUT_VOL_SHIFT 0 /* LINEOUT_VOL - [5:0] */ -#define WM9081_LINEOUT_VOL_WIDTH 6 /* LINEOUT_VOL - [5:0] */ - -/* - * R3 (0x03) - Analogue Speaker PGA - */ -#define WM9081_SPKPGA_MUTE 0x0080 /* SPKPGA_MUTE */ -#define WM9081_SPKPGA_MUTE_MASK 0x0080 /* SPKPGA_MUTE */ -#define WM9081_SPKPGA_MUTE_SHIFT 7 /* SPKPGA_MUTE */ -#define WM9081_SPKPGA_MUTE_WIDTH 1 /* SPKPGA_MUTE */ -#define WM9081_SPKPGAZC 0x0040 /* SPKPGAZC */ -#define WM9081_SPKPGAZC_MASK 0x0040 /* SPKPGAZC */ -#define WM9081_SPKPGAZC_SHIFT 6 /* SPKPGAZC */ -#define WM9081_SPKPGAZC_WIDTH 1 /* SPKPGAZC */ -#define WM9081_SPKPGA_VOL_MASK 0x003F /* SPKPGA_VOL - [5:0] */ -#define WM9081_SPKPGA_VOL_SHIFT 0 /* SPKPGA_VOL - [5:0] */ -#define WM9081_SPKPGA_VOL_WIDTH 6 /* SPKPGA_VOL - [5:0] */ - -/* - * R4 (0x04) - VMID Control - */ -#define WM9081_VMID_BUF_ENA 0x0020 /* VMID_BUF_ENA */ -#define WM9081_VMID_BUF_ENA_MASK 0x0020 /* VMID_BUF_ENA */ -#define WM9081_VMID_BUF_ENA_SHIFT 5 /* VMID_BUF_ENA */ -#define WM9081_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ -#define WM9081_VMID_RAMP 0x0008 /* VMID_RAMP */ -#define WM9081_VMID_RAMP_MASK 0x0008 /* VMID_RAMP */ -#define WM9081_VMID_RAMP_SHIFT 3 /* VMID_RAMP */ -#define WM9081_VMID_RAMP_WIDTH 1 /* VMID_RAMP */ -#define WM9081_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */ -#define WM9081_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */ -#define WM9081_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */ -#define WM9081_VMID_FAST_ST 0x0001 /* VMID_FAST_ST */ -#define WM9081_VMID_FAST_ST_MASK 0x0001 /* VMID_FAST_ST */ -#define WM9081_VMID_FAST_ST_SHIFT 0 /* VMID_FAST_ST */ -#define WM9081_VMID_FAST_ST_WIDTH 1 /* VMID_FAST_ST */ - -/* - * R5 (0x05) - Bias Control 1 - */ -#define WM9081_BIAS_SRC 0x0040 /* BIAS_SRC */ -#define WM9081_BIAS_SRC_MASK 0x0040 /* BIAS_SRC */ -#define WM9081_BIAS_SRC_SHIFT 6 /* BIAS_SRC */ -#define WM9081_BIAS_SRC_WIDTH 1 /* BIAS_SRC */ -#define WM9081_STBY_BIAS_LVL 0x0020 /* STBY_BIAS_LVL */ -#define WM9081_STBY_BIAS_LVL_MASK 0x0020 /* STBY_BIAS_LVL */ -#define WM9081_STBY_BIAS_LVL_SHIFT 5 /* STBY_BIAS_LVL */ -#define WM9081_STBY_BIAS_LVL_WIDTH 1 /* STBY_BIAS_LVL */ -#define WM9081_STBY_BIAS_ENA 0x0010 /* STBY_BIAS_ENA */ -#define WM9081_STBY_BIAS_ENA_MASK 0x0010 /* STBY_BIAS_ENA */ -#define WM9081_STBY_BIAS_ENA_SHIFT 4 /* STBY_BIAS_ENA */ -#define WM9081_STBY_BIAS_ENA_WIDTH 1 /* STBY_BIAS_ENA */ -#define WM9081_BIAS_LVL_MASK 0x000C /* BIAS_LVL - [3:2] */ -#define WM9081_BIAS_LVL_SHIFT 2 /* BIAS_LVL - [3:2] */ -#define WM9081_BIAS_LVL_WIDTH 2 /* BIAS_LVL - [3:2] */ -#define WM9081_BIAS_ENA 0x0002 /* BIAS_ENA */ -#define WM9081_BIAS_ENA_MASK 0x0002 /* BIAS_ENA */ -#define WM9081_BIAS_ENA_SHIFT 1 /* BIAS_ENA */ -#define WM9081_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ -#define WM9081_STARTUP_BIAS_ENA 0x0001 /* STARTUP_BIAS_ENA */ -#define WM9081_STARTUP_BIAS_ENA_MASK 0x0001 /* STARTUP_BIAS_ENA */ -#define WM9081_STARTUP_BIAS_ENA_SHIFT 0 /* STARTUP_BIAS_ENA */ -#define WM9081_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ - -/* - * R7 (0x07) - Analogue Mixer - */ -#define WM9081_DAC_SEL 0x0010 /* DAC_SEL */ -#define WM9081_DAC_SEL_MASK 0x0010 /* DAC_SEL */ -#define WM9081_DAC_SEL_SHIFT 4 /* DAC_SEL */ -#define WM9081_DAC_SEL_WIDTH 1 /* DAC_SEL */ -#define WM9081_IN2_VOL 0x0008 /* IN2_VOL */ -#define WM9081_IN2_VOL_MASK 0x0008 /* IN2_VOL */ -#define WM9081_IN2_VOL_SHIFT 3 /* IN2_VOL */ -#define WM9081_IN2_VOL_WIDTH 1 /* IN2_VOL */ -#define WM9081_IN2_ENA 0x0004 /* IN2_ENA */ -#define WM9081_IN2_ENA_MASK 0x0004 /* IN2_ENA */ -#define WM9081_IN2_ENA_SHIFT 2 /* IN2_ENA */ -#define WM9081_IN2_ENA_WIDTH 1 /* IN2_ENA */ -#define WM9081_IN1_VOL 0x0002 /* IN1_VOL */ -#define WM9081_IN1_VOL_MASK 0x0002 /* IN1_VOL */ -#define WM9081_IN1_VOL_SHIFT 1 /* IN1_VOL */ -#define WM9081_IN1_VOL_WIDTH 1 /* IN1_VOL */ -#define WM9081_IN1_ENA 0x0001 /* IN1_ENA */ -#define WM9081_IN1_ENA_MASK 0x0001 /* IN1_ENA */ -#define WM9081_IN1_ENA_SHIFT 0 /* IN1_ENA */ -#define WM9081_IN1_ENA_WIDTH 1 /* IN1_ENA */ - -/* - * R8 (0x08) - Anti Pop Control - */ -#define WM9081_LINEOUT_DISCH 0x0004 /* LINEOUT_DISCH */ -#define WM9081_LINEOUT_DISCH_MASK 0x0004 /* LINEOUT_DISCH */ -#define WM9081_LINEOUT_DISCH_SHIFT 2 /* LINEOUT_DISCH */ -#define WM9081_LINEOUT_DISCH_WIDTH 1 /* LINEOUT_DISCH */ -#define WM9081_LINEOUT_VROI 0x0002 /* LINEOUT_VROI */ -#define WM9081_LINEOUT_VROI_MASK 0x0002 /* LINEOUT_VROI */ -#define WM9081_LINEOUT_VROI_SHIFT 1 /* LINEOUT_VROI */ -#define WM9081_LINEOUT_VROI_WIDTH 1 /* LINEOUT_VROI */ -#define WM9081_LINEOUT_CLAMP 0x0001 /* LINEOUT_CLAMP */ -#define WM9081_LINEOUT_CLAMP_MASK 0x0001 /* LINEOUT_CLAMP */ -#define WM9081_LINEOUT_CLAMP_SHIFT 0 /* LINEOUT_CLAMP */ -#define WM9081_LINEOUT_CLAMP_WIDTH 1 /* LINEOUT_CLAMP */ - -/* - * R9 (0x09) - Analogue Speaker 1 - */ -#define WM9081_SPK_DCGAIN_MASK 0x0038 /* SPK_DCGAIN - [5:3] */ -#define WM9081_SPK_DCGAIN_SHIFT 3 /* SPK_DCGAIN - [5:3] */ -#define WM9081_SPK_DCGAIN_WIDTH 3 /* SPK_DCGAIN - [5:3] */ -#define WM9081_SPK_ACGAIN_MASK 0x0007 /* SPK_ACGAIN - [2:0] */ -#define WM9081_SPK_ACGAIN_SHIFT 0 /* SPK_ACGAIN - [2:0] */ -#define WM9081_SPK_ACGAIN_WIDTH 3 /* SPK_ACGAIN - [2:0] */ - -/* - * R10 (0x0A) - Analogue Speaker 2 - */ -#define WM9081_SPK_MODE 0x0040 /* SPK_MODE */ -#define WM9081_SPK_MODE_MASK 0x0040 /* SPK_MODE */ -#define WM9081_SPK_MODE_SHIFT 6 /* SPK_MODE */ -#define WM9081_SPK_MODE_WIDTH 1 /* SPK_MODE */ -#define WM9081_SPK_INV_MUTE 0x0010 /* SPK_INV_MUTE */ -#define WM9081_SPK_INV_MUTE_MASK 0x0010 /* SPK_INV_MUTE */ -#define WM9081_SPK_INV_MUTE_SHIFT 4 /* SPK_INV_MUTE */ -#define WM9081_SPK_INV_MUTE_WIDTH 1 /* SPK_INV_MUTE */ -#define WM9081_OUT_SPK_CTRL 0x0008 /* OUT_SPK_CTRL */ -#define WM9081_OUT_SPK_CTRL_MASK 0x0008 /* OUT_SPK_CTRL */ -#define WM9081_OUT_SPK_CTRL_SHIFT 3 /* OUT_SPK_CTRL */ -#define WM9081_OUT_SPK_CTRL_WIDTH 1 /* OUT_SPK_CTRL */ - -/* - * R11 (0x0B) - Power Management - */ -#define WM9081_TSHUT_ENA 0x0100 /* TSHUT_ENA */ -#define WM9081_TSHUT_ENA_MASK 0x0100 /* TSHUT_ENA */ -#define WM9081_TSHUT_ENA_SHIFT 8 /* TSHUT_ENA */ -#define WM9081_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */ -#define WM9081_TSENSE_ENA 0x0080 /* TSENSE_ENA */ -#define WM9081_TSENSE_ENA_MASK 0x0080 /* TSENSE_ENA */ -#define WM9081_TSENSE_ENA_SHIFT 7 /* TSENSE_ENA */ -#define WM9081_TSENSE_ENA_WIDTH 1 /* TSENSE_ENA */ -#define WM9081_TEMP_SHUT 0x0040 /* TEMP_SHUT */ -#define WM9081_TEMP_SHUT_MASK 0x0040 /* TEMP_SHUT */ -#define WM9081_TEMP_SHUT_SHIFT 6 /* TEMP_SHUT */ -#define WM9081_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */ -#define WM9081_LINEOUT_ENA 0x0010 /* LINEOUT_ENA */ -#define WM9081_LINEOUT_ENA_MASK 0x0010 /* LINEOUT_ENA */ -#define WM9081_LINEOUT_ENA_SHIFT 4 /* LINEOUT_ENA */ -#define WM9081_LINEOUT_ENA_WIDTH 1 /* LINEOUT_ENA */ -#define WM9081_SPKPGA_ENA 0x0004 /* SPKPGA_ENA */ -#define WM9081_SPKPGA_ENA_MASK 0x0004 /* SPKPGA_ENA */ -#define WM9081_SPKPGA_ENA_SHIFT 2 /* SPKPGA_ENA */ -#define WM9081_SPKPGA_ENA_WIDTH 1 /* SPKPGA_ENA */ -#define WM9081_SPK_ENA 0x0002 /* SPK_ENA */ -#define WM9081_SPK_ENA_MASK 0x0002 /* SPK_ENA */ -#define WM9081_SPK_ENA_SHIFT 1 /* SPK_ENA */ -#define WM9081_SPK_ENA_WIDTH 1 /* SPK_ENA */ -#define WM9081_DAC_ENA 0x0001 /* DAC_ENA */ -#define WM9081_DAC_ENA_MASK 0x0001 /* DAC_ENA */ -#define WM9081_DAC_ENA_SHIFT 0 /* DAC_ENA */ -#define WM9081_DAC_ENA_WIDTH 1 /* DAC_ENA */ - -/* - * R12 (0x0C) - Clock Control 1 - */ -#define WM9081_CLK_OP_DIV_MASK 0x1C00 /* CLK_OP_DIV - [12:10] */ -#define WM9081_CLK_OP_DIV_SHIFT 10 /* CLK_OP_DIV - [12:10] */ -#define WM9081_CLK_OP_DIV_WIDTH 3 /* CLK_OP_DIV - [12:10] */ -#define WM9081_CLK_TO_DIV_MASK 0x0300 /* CLK_TO_DIV - [9:8] */ -#define WM9081_CLK_TO_DIV_SHIFT 8 /* CLK_TO_DIV - [9:8] */ -#define WM9081_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [9:8] */ -#define WM9081_MCLKDIV2 0x0080 /* MCLKDIV2 */ -#define WM9081_MCLKDIV2_MASK 0x0080 /* MCLKDIV2 */ -#define WM9081_MCLKDIV2_SHIFT 7 /* MCLKDIV2 */ -#define WM9081_MCLKDIV2_WIDTH 1 /* MCLKDIV2 */ - -/* - * R13 (0x0D) - Clock Control 2 - */ -#define WM9081_CLK_SYS_RATE_MASK 0x00F0 /* CLK_SYS_RATE - [7:4] */ -#define WM9081_CLK_SYS_RATE_SHIFT 4 /* CLK_SYS_RATE - [7:4] */ -#define WM9081_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [7:4] */ -#define WM9081_SAMPLE_RATE_MASK 0x000F /* SAMPLE_RATE - [3:0] */ -#define WM9081_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [3:0] */ -#define WM9081_SAMPLE_RATE_WIDTH 4 /* SAMPLE_RATE - [3:0] */ - -/* - * R14 (0x0E) - Clock Control 3 - */ -#define WM9081_CLK_SRC_SEL 0x2000 /* CLK_SRC_SEL */ -#define WM9081_CLK_SRC_SEL_MASK 0x2000 /* CLK_SRC_SEL */ -#define WM9081_CLK_SRC_SEL_SHIFT 13 /* CLK_SRC_SEL */ -#define WM9081_CLK_SRC_SEL_WIDTH 1 /* CLK_SRC_SEL */ -#define WM9081_CLK_OP_ENA 0x0020 /* CLK_OP_ENA */ -#define WM9081_CLK_OP_ENA_MASK 0x0020 /* CLK_OP_ENA */ -#define WM9081_CLK_OP_ENA_SHIFT 5 /* CLK_OP_ENA */ -#define WM9081_CLK_OP_ENA_WIDTH 1 /* CLK_OP_ENA */ -#define WM9081_CLK_TO_ENA 0x0004 /* CLK_TO_ENA */ -#define WM9081_CLK_TO_ENA_MASK 0x0004 /* CLK_TO_ENA */ -#define WM9081_CLK_TO_ENA_SHIFT 2 /* CLK_TO_ENA */ -#define WM9081_CLK_TO_ENA_WIDTH 1 /* CLK_TO_ENA */ -#define WM9081_CLK_DSP_ENA 0x0002 /* CLK_DSP_ENA */ -#define WM9081_CLK_DSP_ENA_MASK 0x0002 /* CLK_DSP_ENA */ -#define WM9081_CLK_DSP_ENA_SHIFT 1 /* CLK_DSP_ENA */ -#define WM9081_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ -#define WM9081_CLK_SYS_ENA 0x0001 /* CLK_SYS_ENA */ -#define WM9081_CLK_SYS_ENA_MASK 0x0001 /* CLK_SYS_ENA */ -#define WM9081_CLK_SYS_ENA_SHIFT 0 /* CLK_SYS_ENA */ -#define WM9081_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ - -/* - * R16 (0x10) - FLL Control 1 - */ -#define WM9081_FLL_HOLD 0x0008 /* FLL_HOLD */ -#define WM9081_FLL_HOLD_MASK 0x0008 /* FLL_HOLD */ -#define WM9081_FLL_HOLD_SHIFT 3 /* FLL_HOLD */ -#define WM9081_FLL_HOLD_WIDTH 1 /* FLL_HOLD */ -#define WM9081_FLL_FRAC 0x0004 /* FLL_FRAC */ -#define WM9081_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */ -#define WM9081_FLL_FRAC_SHIFT 2 /* FLL_FRAC */ -#define WM9081_FLL_FRAC_WIDTH 1 /* FLL_FRAC */ -#define WM9081_FLL_ENA 0x0001 /* FLL_ENA */ -#define WM9081_FLL_ENA_MASK 0x0001 /* FLL_ENA */ -#define WM9081_FLL_ENA_SHIFT 0 /* FLL_ENA */ -#define WM9081_FLL_ENA_WIDTH 1 /* FLL_ENA */ - -/* - * R17 (0x11) - FLL Control 2 - */ -#define WM9081_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */ -#define WM9081_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */ -#define WM9081_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */ -#define WM9081_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */ -#define WM9081_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */ -#define WM9081_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */ -#define WM9081_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ -#define WM9081_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ -#define WM9081_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ - -/* - * R18 (0x12) - FLL Control 3 - */ -#define WM9081_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */ -#define WM9081_FLL_K_SHIFT 0 /* FLL_K - [15:0] */ -#define WM9081_FLL_K_WIDTH 16 /* FLL_K - [15:0] */ - -/* - * R19 (0x13) - FLL Control 4 - */ -#define WM9081_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */ -#define WM9081_FLL_N_SHIFT 5 /* FLL_N - [14:5] */ -#define WM9081_FLL_N_WIDTH 10 /* FLL_N - [14:5] */ -#define WM9081_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */ -#define WM9081_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */ -#define WM9081_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */ - -/* - * R20 (0x14) - FLL Control 5 - */ -#define WM9081_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM9081_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM9081_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM9081_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */ -#define WM9081_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */ -#define WM9081_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */ - -/* - * R22 (0x16) - Audio Interface 1 - */ -#define WM9081_AIFDAC_CHAN 0x0040 /* AIFDAC_CHAN */ -#define WM9081_AIFDAC_CHAN_MASK 0x0040 /* AIFDAC_CHAN */ -#define WM9081_AIFDAC_CHAN_SHIFT 6 /* AIFDAC_CHAN */ -#define WM9081_AIFDAC_CHAN_WIDTH 1 /* AIFDAC_CHAN */ -#define WM9081_AIFDAC_TDM_SLOT_MASK 0x0030 /* AIFDAC_TDM_SLOT - [5:4] */ -#define WM9081_AIFDAC_TDM_SLOT_SHIFT 4 /* AIFDAC_TDM_SLOT - [5:4] */ -#define WM9081_AIFDAC_TDM_SLOT_WIDTH 2 /* AIFDAC_TDM_SLOT - [5:4] */ -#define WM9081_AIFDAC_TDM_MODE_MASK 0x000C /* AIFDAC_TDM_MODE - [3:2] */ -#define WM9081_AIFDAC_TDM_MODE_SHIFT 2 /* AIFDAC_TDM_MODE - [3:2] */ -#define WM9081_AIFDAC_TDM_MODE_WIDTH 2 /* AIFDAC_TDM_MODE - [3:2] */ -#define WM9081_DAC_COMP 0x0002 /* DAC_COMP */ -#define WM9081_DAC_COMP_MASK 0x0002 /* DAC_COMP */ -#define WM9081_DAC_COMP_SHIFT 1 /* DAC_COMP */ -#define WM9081_DAC_COMP_WIDTH 1 /* DAC_COMP */ -#define WM9081_DAC_COMPMODE 0x0001 /* DAC_COMPMODE */ -#define WM9081_DAC_COMPMODE_MASK 0x0001 /* DAC_COMPMODE */ -#define WM9081_DAC_COMPMODE_SHIFT 0 /* DAC_COMPMODE */ -#define WM9081_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ - -/* - * R23 (0x17) - Audio Interface 2 - */ -#define WM9081_AIF_TRIS 0x0200 /* AIF_TRIS */ -#define WM9081_AIF_TRIS_MASK 0x0200 /* AIF_TRIS */ -#define WM9081_AIF_TRIS_SHIFT 9 /* AIF_TRIS */ -#define WM9081_AIF_TRIS_WIDTH 1 /* AIF_TRIS */ -#define WM9081_DAC_DAT_INV 0x0100 /* DAC_DAT_INV */ -#define WM9081_DAC_DAT_INV_MASK 0x0100 /* DAC_DAT_INV */ -#define WM9081_DAC_DAT_INV_SHIFT 8 /* DAC_DAT_INV */ -#define WM9081_DAC_DAT_INV_WIDTH 1 /* DAC_DAT_INV */ -#define WM9081_AIF_BCLK_INV 0x0080 /* AIF_BCLK_INV */ -#define WM9081_AIF_BCLK_INV_MASK 0x0080 /* AIF_BCLK_INV */ -#define WM9081_AIF_BCLK_INV_SHIFT 7 /* AIF_BCLK_INV */ -#define WM9081_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */ -#define WM9081_BCLK_DIR 0x0040 /* BCLK_DIR */ -#define WM9081_BCLK_DIR_MASK 0x0040 /* BCLK_DIR */ -#define WM9081_BCLK_DIR_SHIFT 6 /* BCLK_DIR */ -#define WM9081_BCLK_DIR_WIDTH 1 /* BCLK_DIR */ -#define WM9081_LRCLK_DIR 0x0020 /* LRCLK_DIR */ -#define WM9081_LRCLK_DIR_MASK 0x0020 /* LRCLK_DIR */ -#define WM9081_LRCLK_DIR_SHIFT 5 /* LRCLK_DIR */ -#define WM9081_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */ -#define WM9081_AIF_LRCLK_INV 0x0010 /* AIF_LRCLK_INV */ -#define WM9081_AIF_LRCLK_INV_MASK 0x0010 /* AIF_LRCLK_INV */ -#define WM9081_AIF_LRCLK_INV_SHIFT 4 /* AIF_LRCLK_INV */ -#define WM9081_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */ -#define WM9081_AIF_WL_MASK 0x000C /* AIF_WL - [3:2] */ -#define WM9081_AIF_WL_SHIFT 2 /* AIF_WL - [3:2] */ -#define WM9081_AIF_WL_WIDTH 2 /* AIF_WL - [3:2] */ -#define WM9081_AIF_FMT_MASK 0x0003 /* AIF_FMT - [1:0] */ -#define WM9081_AIF_FMT_SHIFT 0 /* AIF_FMT - [1:0] */ -#define WM9081_AIF_FMT_WIDTH 2 /* AIF_FMT - [1:0] */ - -/* - * R24 (0x18) - Audio Interface 3 - */ -#define WM9081_BCLK_DIV_MASK 0x001F /* BCLK_DIV - [4:0] */ -#define WM9081_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [4:0] */ -#define WM9081_BCLK_DIV_WIDTH 5 /* BCLK_DIV - [4:0] */ - -/* - * R25 (0x19) - Audio Interface 4 - */ -#define WM9081_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */ -#define WM9081_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */ -#define WM9081_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */ - -/* - * R26 (0x1A) - Interrupt Status - */ -#define WM9081_WSEQ_BUSY_EINT 0x0004 /* WSEQ_BUSY_EINT */ -#define WM9081_WSEQ_BUSY_EINT_MASK 0x0004 /* WSEQ_BUSY_EINT */ -#define WM9081_WSEQ_BUSY_EINT_SHIFT 2 /* WSEQ_BUSY_EINT */ -#define WM9081_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */ -#define WM9081_TSHUT_EINT 0x0001 /* TSHUT_EINT */ -#define WM9081_TSHUT_EINT_MASK 0x0001 /* TSHUT_EINT */ -#define WM9081_TSHUT_EINT_SHIFT 0 /* TSHUT_EINT */ -#define WM9081_TSHUT_EINT_WIDTH 1 /* TSHUT_EINT */ - -/* - * R27 (0x1B) - Interrupt Status Mask - */ -#define WM9081_IM_WSEQ_BUSY_EINT 0x0004 /* IM_WSEQ_BUSY_EINT */ -#define WM9081_IM_WSEQ_BUSY_EINT_MASK 0x0004 /* IM_WSEQ_BUSY_EINT */ -#define WM9081_IM_WSEQ_BUSY_EINT_SHIFT 2 /* IM_WSEQ_BUSY_EINT */ -#define WM9081_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */ -#define WM9081_IM_TSHUT_EINT 0x0001 /* IM_TSHUT_EINT */ -#define WM9081_IM_TSHUT_EINT_MASK 0x0001 /* IM_TSHUT_EINT */ -#define WM9081_IM_TSHUT_EINT_SHIFT 0 /* IM_TSHUT_EINT */ -#define WM9081_IM_TSHUT_EINT_WIDTH 1 /* IM_TSHUT_EINT */ - -/* - * R28 (0x1C) - Interrupt Polarity - */ -#define WM9081_TSHUT_INV 0x0001 /* TSHUT_INV */ -#define WM9081_TSHUT_INV_MASK 0x0001 /* TSHUT_INV */ -#define WM9081_TSHUT_INV_SHIFT 0 /* TSHUT_INV */ -#define WM9081_TSHUT_INV_WIDTH 1 /* TSHUT_INV */ - -/* - * R29 (0x1D) - Interrupt Control - */ -#define WM9081_IRQ_POL 0x8000 /* IRQ_POL */ -#define WM9081_IRQ_POL_MASK 0x8000 /* IRQ_POL */ -#define WM9081_IRQ_POL_SHIFT 15 /* IRQ_POL */ -#define WM9081_IRQ_POL_WIDTH 1 /* IRQ_POL */ -#define WM9081_IRQ_OP_CTRL 0x0001 /* IRQ_OP_CTRL */ -#define WM9081_IRQ_OP_CTRL_MASK 0x0001 /* IRQ_OP_CTRL */ -#define WM9081_IRQ_OP_CTRL_SHIFT 0 /* IRQ_OP_CTRL */ -#define WM9081_IRQ_OP_CTRL_WIDTH 1 /* IRQ_OP_CTRL */ - -/* - * R30 (0x1E) - DAC Digital 1 - */ -#define WM9081_DAC_VOL_MASK 0x00FF /* DAC_VOL - [7:0] */ -#define WM9081_DAC_VOL_SHIFT 0 /* DAC_VOL - [7:0] */ -#define WM9081_DAC_VOL_WIDTH 8 /* DAC_VOL - [7:0] */ - -/* - * R31 (0x1F) - DAC Digital 2 - */ -#define WM9081_DAC_MUTERATE 0x0400 /* DAC_MUTERATE */ -#define WM9081_DAC_MUTERATE_MASK 0x0400 /* DAC_MUTERATE */ -#define WM9081_DAC_MUTERATE_SHIFT 10 /* DAC_MUTERATE */ -#define WM9081_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ -#define WM9081_DAC_MUTEMODE 0x0200 /* DAC_MUTEMODE */ -#define WM9081_DAC_MUTEMODE_MASK 0x0200 /* DAC_MUTEMODE */ -#define WM9081_DAC_MUTEMODE_SHIFT 9 /* DAC_MUTEMODE */ -#define WM9081_DAC_MUTEMODE_WIDTH 1 /* DAC_MUTEMODE */ -#define WM9081_DAC_MUTE 0x0008 /* DAC_MUTE */ -#define WM9081_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */ -#define WM9081_DAC_MUTE_SHIFT 3 /* DAC_MUTE */ -#define WM9081_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ -#define WM9081_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ -#define WM9081_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ -#define WM9081_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ - -/* - * R32 (0x20) - DRC 1 - */ -#define WM9081_DRC_ENA 0x8000 /* DRC_ENA */ -#define WM9081_DRC_ENA_MASK 0x8000 /* DRC_ENA */ -#define WM9081_DRC_ENA_SHIFT 15 /* DRC_ENA */ -#define WM9081_DRC_ENA_WIDTH 1 /* DRC_ENA */ -#define WM9081_DRC_STARTUP_GAIN_MASK 0x07C0 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM9081_DRC_STARTUP_GAIN_SHIFT 6 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM9081_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [10:6] */ -#define WM9081_DRC_FF_DLY 0x0020 /* DRC_FF_DLY */ -#define WM9081_DRC_FF_DLY_MASK 0x0020 /* DRC_FF_DLY */ -#define WM9081_DRC_FF_DLY_SHIFT 5 /* DRC_FF_DLY */ -#define WM9081_DRC_FF_DLY_WIDTH 1 /* DRC_FF_DLY */ -#define WM9081_DRC_QR 0x0004 /* DRC_QR */ -#define WM9081_DRC_QR_MASK 0x0004 /* DRC_QR */ -#define WM9081_DRC_QR_SHIFT 2 /* DRC_QR */ -#define WM9081_DRC_QR_WIDTH 1 /* DRC_QR */ -#define WM9081_DRC_ANTICLIP 0x0002 /* DRC_ANTICLIP */ -#define WM9081_DRC_ANTICLIP_MASK 0x0002 /* DRC_ANTICLIP */ -#define WM9081_DRC_ANTICLIP_SHIFT 1 /* DRC_ANTICLIP */ -#define WM9081_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */ - -/* - * R33 (0x21) - DRC 2 - */ -#define WM9081_DRC_ATK_MASK 0xF000 /* DRC_ATK - [15:12] */ -#define WM9081_DRC_ATK_SHIFT 12 /* DRC_ATK - [15:12] */ -#define WM9081_DRC_ATK_WIDTH 4 /* DRC_ATK - [15:12] */ -#define WM9081_DRC_DCY_MASK 0x0F00 /* DRC_DCY - [11:8] */ -#define WM9081_DRC_DCY_SHIFT 8 /* DRC_DCY - [11:8] */ -#define WM9081_DRC_DCY_WIDTH 4 /* DRC_DCY - [11:8] */ -#define WM9081_DRC_QR_THR_MASK 0x00C0 /* DRC_QR_THR - [7:6] */ -#define WM9081_DRC_QR_THR_SHIFT 6 /* DRC_QR_THR - [7:6] */ -#define WM9081_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [7:6] */ -#define WM9081_DRC_QR_DCY_MASK 0x0030 /* DRC_QR_DCY - [5:4] */ -#define WM9081_DRC_QR_DCY_SHIFT 4 /* DRC_QR_DCY - [5:4] */ -#define WM9081_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [5:4] */ -#define WM9081_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */ -#define WM9081_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */ -#define WM9081_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */ -#define WM9081_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ -#define WM9081_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ -#define WM9081_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ - -/* - * R34 (0x22) - DRC 3 - */ -#define WM9081_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */ -#define WM9081_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */ -#define WM9081_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */ -#define WM9081_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */ -#define WM9081_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */ -#define WM9081_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */ - -/* - * R35 (0x23) - DRC 4 - */ -#define WM9081_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */ -#define WM9081_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */ -#define WM9081_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */ -#define WM9081_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */ -#define WM9081_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */ -#define WM9081_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */ - -/* - * R38 (0x26) - Write Sequencer 1 - */ -#define WM9081_WSEQ_ENA 0x8000 /* WSEQ_ENA */ -#define WM9081_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */ -#define WM9081_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */ -#define WM9081_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM9081_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM9081_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM9081_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM9081_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM9081_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM9081_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM9081_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM9081_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM9081_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */ -#define WM9081_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */ -#define WM9081_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */ - -/* - * R39 (0x27) - Write Sequencer 2 - */ -#define WM9081_WSEQ_CURRENT_INDEX_MASK 0x07F0 /* WSEQ_CURRENT_INDEX - [10:4] */ -#define WM9081_WSEQ_CURRENT_INDEX_SHIFT 4 /* WSEQ_CURRENT_INDEX - [10:4] */ -#define WM9081_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [10:4] */ -#define WM9081_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM9081_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM9081_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM9081_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R40 (0x28) - MW Slave 1 - */ -#define WM9081_SPI_CFG 0x0020 /* SPI_CFG */ -#define WM9081_SPI_CFG_MASK 0x0020 /* SPI_CFG */ -#define WM9081_SPI_CFG_SHIFT 5 /* SPI_CFG */ -#define WM9081_SPI_CFG_WIDTH 1 /* SPI_CFG */ -#define WM9081_SPI_4WIRE 0x0010 /* SPI_4WIRE */ -#define WM9081_SPI_4WIRE_MASK 0x0010 /* SPI_4WIRE */ -#define WM9081_SPI_4WIRE_SHIFT 4 /* SPI_4WIRE */ -#define WM9081_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */ -#define WM9081_ARA_ENA 0x0008 /* ARA_ENA */ -#define WM9081_ARA_ENA_MASK 0x0008 /* ARA_ENA */ -#define WM9081_ARA_ENA_SHIFT 3 /* ARA_ENA */ -#define WM9081_ARA_ENA_WIDTH 1 /* ARA_ENA */ -#define WM9081_AUTO_INC 0x0002 /* AUTO_INC */ -#define WM9081_AUTO_INC_MASK 0x0002 /* AUTO_INC */ -#define WM9081_AUTO_INC_SHIFT 1 /* AUTO_INC */ -#define WM9081_AUTO_INC_WIDTH 1 /* AUTO_INC */ - -/* - * R42 (0x2A) - EQ 1 - */ -#define WM9081_EQ_B1_GAIN_MASK 0xF800 /* EQ_B1_GAIN - [15:11] */ -#define WM9081_EQ_B1_GAIN_SHIFT 11 /* EQ_B1_GAIN - [15:11] */ -#define WM9081_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [15:11] */ -#define WM9081_EQ_B2_GAIN_MASK 0x07C0 /* EQ_B2_GAIN - [10:6] */ -#define WM9081_EQ_B2_GAIN_SHIFT 6 /* EQ_B2_GAIN - [10:6] */ -#define WM9081_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [10:6] */ -#define WM9081_EQ_B4_GAIN_MASK 0x003E /* EQ_B4_GAIN - [5:1] */ -#define WM9081_EQ_B4_GAIN_SHIFT 1 /* EQ_B4_GAIN - [5:1] */ -#define WM9081_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [5:1] */ -#define WM9081_EQ_ENA 0x0001 /* EQ_ENA */ -#define WM9081_EQ_ENA_MASK 0x0001 /* EQ_ENA */ -#define WM9081_EQ_ENA_SHIFT 0 /* EQ_ENA */ -#define WM9081_EQ_ENA_WIDTH 1 /* EQ_ENA */ - -/* - * R43 (0x2B) - EQ 2 - */ -#define WM9081_EQ_B3_GAIN_MASK 0xF800 /* EQ_B3_GAIN - [15:11] */ -#define WM9081_EQ_B3_GAIN_SHIFT 11 /* EQ_B3_GAIN - [15:11] */ -#define WM9081_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [15:11] */ -#define WM9081_EQ_B5_GAIN_MASK 0x07C0 /* EQ_B5_GAIN - [10:6] */ -#define WM9081_EQ_B5_GAIN_SHIFT 6 /* EQ_B5_GAIN - [10:6] */ -#define WM9081_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [10:6] */ - -/* - * R44 (0x2C) - EQ 3 - */ -#define WM9081_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */ -#define WM9081_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */ -#define WM9081_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */ - -/* - * R45 (0x2D) - EQ 4 - */ -#define WM9081_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */ -#define WM9081_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */ -#define WM9081_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */ - -/* - * R46 (0x2E) - EQ 5 - */ -#define WM9081_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */ -#define WM9081_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */ -#define WM9081_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */ - -/* - * R47 (0x2F) - EQ 6 - */ -#define WM9081_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */ -#define WM9081_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */ -#define WM9081_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */ - -/* - * R48 (0x30) - EQ 7 - */ -#define WM9081_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */ -#define WM9081_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */ -#define WM9081_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */ - -/* - * R49 (0x31) - EQ 8 - */ -#define WM9081_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */ -#define WM9081_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */ -#define WM9081_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */ - -/* - * R50 (0x32) - EQ 9 - */ -#define WM9081_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */ -#define WM9081_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */ -#define WM9081_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */ - -/* - * R51 (0x33) - EQ 10 - */ -#define WM9081_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */ -#define WM9081_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */ -#define WM9081_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */ - -/* - * R52 (0x34) - EQ 11 - */ -#define WM9081_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */ -#define WM9081_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */ -#define WM9081_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */ - -/* - * R53 (0x35) - EQ 12 - */ -#define WM9081_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */ -#define WM9081_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */ -#define WM9081_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */ - -/* - * R54 (0x36) - EQ 13 - */ -#define WM9081_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */ -#define WM9081_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */ -#define WM9081_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */ - -/* - * R55 (0x37) - EQ 14 - */ -#define WM9081_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */ -#define WM9081_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */ -#define WM9081_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */ - -/* - * R56 (0x38) - EQ 15 - */ -#define WM9081_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */ -#define WM9081_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */ -#define WM9081_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */ - -/* - * R57 (0x39) - EQ 16 - */ -#define WM9081_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */ -#define WM9081_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */ -#define WM9081_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */ - -/* - * R58 (0x3A) - EQ 17 - */ -#define WM9081_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */ -#define WM9081_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */ -#define WM9081_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */ - -/* - * R59 (0x3B) - EQ 18 - */ -#define WM9081_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */ -#define WM9081_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */ -#define WM9081_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */ - -/* - * R60 (0x3C) - EQ 19 - */ -#define WM9081_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */ -#define WM9081_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */ -#define WM9081_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */ - -/* - * R61 (0x3D) - EQ 20 - */ -#define WM9081_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */ -#define WM9081_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */ -#define WM9081_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */ - - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9090.c b/ANDROID_3.4.5/sound/soc/codecs/wm9090.c deleted file mode 100644 index 4b263b6e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9090.c +++ /dev/null @@ -1,712 +0,0 @@ -/* - * ALSA SoC WM9090 driver - * - * Copyright 2009, 2010 Wolfson Microelectronics - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm9090.h" - -static const struct reg_default wm9090_reg_defaults[] = { - { 1, 0x0006 }, /* R1 - Power Management (1) */ - { 2, 0x6000 }, /* R2 - Power Management (2) */ - { 3, 0x0000 }, /* R3 - Power Management (3) */ - { 6, 0x01C0 }, /* R6 - Clocking 1 */ - { 22, 0x0003 }, /* R22 - IN1 Line Control */ - { 23, 0x0003 }, /* R23 - IN2 Line Control */ - { 24, 0x0083 }, /* R24 - IN1 Line Input A Volume */ - { 25, 0x0083 }, /* R25 - IN1 Line Input B Volume */ - { 26, 0x0083 }, /* R26 - IN2 Line Input A Volume */ - { 27, 0x0083 }, /* R27 - IN2 Line Input B Volume */ - { 28, 0x002D }, /* R28 - Left Output Volume */ - { 29, 0x002D }, /* R29 - Right Output Volume */ - { 34, 0x0100 }, /* R34 - SPKMIXL Attenuation */ - { 35, 0x0010 }, /* R36 - SPKOUT Mixers */ - { 37, 0x0140 }, /* R37 - ClassD3 */ - { 38, 0x0039 }, /* R38 - Speaker Volume Left */ - { 45, 0x0000 }, /* R45 - Output Mixer1 */ - { 46, 0x0000 }, /* R46 - Output Mixer2 */ - { 47, 0x0100 }, /* R47 - Output Mixer3 */ - { 48, 0x0100 }, /* R48 - Output Mixer4 */ - { 54, 0x0000 }, /* R54 - Speaker Mixer */ - { 57, 0x000D }, /* R57 - AntiPOP2 */ - { 70, 0x0000 }, /* R70 - Write Sequencer 0 */ - { 71, 0x0000 }, /* R71 - Write Sequencer 1 */ - { 72, 0x0000 }, /* R72 - Write Sequencer 2 */ - { 73, 0x0000 }, /* R73 - Write Sequencer 3 */ - { 74, 0x0000 }, /* R74 - Write Sequencer 4 */ - { 75, 0x0000 }, /* R75 - Write Sequencer 5 */ - { 76, 0x1F25 }, /* R76 - Charge Pump 1 */ - { 85, 0x054A }, /* R85 - DC Servo 1 */ - { 87, 0x0000 }, /* R87 - DC Servo 3 */ - { 96, 0x0100 }, /* R96 - Analogue HP 0 */ - { 98, 0x8640 }, /* R98 - AGC Control 0 */ - { 99, 0xC000 }, /* R99 - AGC Control 1 */ - { 100, 0x0200 }, /* R100 - AGC Control 2 */ -}; - -/* This struct is used to save the context */ -struct wm9090_priv { - struct wm9090_platform_data pdata; - struct regmap *regmap; -}; - -static bool wm9090_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM9090_SOFTWARE_RESET: - case WM9090_DC_SERVO_0: - case WM9090_DC_SERVO_READBACK_0: - case WM9090_DC_SERVO_READBACK_1: - case WM9090_DC_SERVO_READBACK_2: - return true; - - default: - return false; - } -} - -static bool wm9090_readable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case WM9090_SOFTWARE_RESET: - case WM9090_POWER_MANAGEMENT_1: - case WM9090_POWER_MANAGEMENT_2: - case WM9090_POWER_MANAGEMENT_3: - case WM9090_CLOCKING_1: - case WM9090_IN1_LINE_CONTROL: - case WM9090_IN2_LINE_CONTROL: - case WM9090_IN1_LINE_INPUT_A_VOLUME: - case WM9090_IN1_LINE_INPUT_B_VOLUME: - case WM9090_IN2_LINE_INPUT_A_VOLUME: - case WM9090_IN2_LINE_INPUT_B_VOLUME: - case WM9090_LEFT_OUTPUT_VOLUME: - case WM9090_RIGHT_OUTPUT_VOLUME: - case WM9090_SPKMIXL_ATTENUATION: - case WM9090_SPKOUT_MIXERS: - case WM9090_CLASSD3: - case WM9090_SPEAKER_VOLUME_LEFT: - case WM9090_OUTPUT_MIXER1: - case WM9090_OUTPUT_MIXER2: - case WM9090_OUTPUT_MIXER3: - case WM9090_OUTPUT_MIXER4: - case WM9090_SPEAKER_MIXER: - case WM9090_ANTIPOP2: - case WM9090_WRITE_SEQUENCER_0: - case WM9090_WRITE_SEQUENCER_1: - case WM9090_WRITE_SEQUENCER_2: - case WM9090_WRITE_SEQUENCER_3: - case WM9090_WRITE_SEQUENCER_4: - case WM9090_WRITE_SEQUENCER_5: - case WM9090_CHARGE_PUMP_1: - case WM9090_DC_SERVO_0: - case WM9090_DC_SERVO_1: - case WM9090_DC_SERVO_3: - case WM9090_DC_SERVO_READBACK_0: - case WM9090_DC_SERVO_READBACK_1: - case WM9090_DC_SERVO_READBACK_2: - case WM9090_ANALOGUE_HP_0: - case WM9090_AGC_CONTROL_0: - case WM9090_AGC_CONTROL_1: - case WM9090_AGC_CONTROL_2: - return true; - - default: - return false; - } -} - -static void wait_for_dc_servo(struct snd_soc_codec *codec) -{ - unsigned int reg; - int count = 0; - - dev_dbg(codec->dev, "Waiting for DC servo...\n"); - do { - count++; - msleep(1); - reg = snd_soc_read(codec, WM9090_DC_SERVO_READBACK_0); - dev_dbg(codec->dev, "DC servo status: %x\n", reg); - } while ((reg & WM9090_DCS_CAL_COMPLETE_MASK) - != WM9090_DCS_CAL_COMPLETE_MASK && count < 1000); - - if ((reg & WM9090_DCS_CAL_COMPLETE_MASK) - != WM9090_DCS_CAL_COMPLETE_MASK) - dev_err(codec->dev, "Timed out waiting for DC Servo\n"); -} - -static const unsigned int in_tlv[] = { - TLV_DB_RANGE_HEAD(3), - 0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0), - 1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0), - 4, 6, TLV_DB_SCALE_ITEM(600, 600, 0), -}; -static const unsigned int mix_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0), - 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0); -static const unsigned int spkboost_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), - 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), -}; - -static const struct snd_kcontrol_new wm9090_controls[] = { -SOC_SINGLE_TLV("IN1A Volume", WM9090_IN1_LINE_INPUT_A_VOLUME, 0, 6, 0, - in_tlv), -SOC_SINGLE("IN1A Switch", WM9090_IN1_LINE_INPUT_A_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1A ZC Switch", WM9090_IN1_LINE_INPUT_A_VOLUME, 6, 1, 0), - -SOC_SINGLE_TLV("IN2A Volume", WM9090_IN2_LINE_INPUT_A_VOLUME, 0, 6, 0, - in_tlv), -SOC_SINGLE("IN2A Switch", WM9090_IN2_LINE_INPUT_A_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2A ZC Switch", WM9090_IN2_LINE_INPUT_A_VOLUME, 6, 1, 0), - -SOC_SINGLE("MIXOUTL Switch", WM9090_OUTPUT_MIXER3, 8, 1, 1), -SOC_SINGLE_TLV("MIXOUTL IN1A Volume", WM9090_OUTPUT_MIXER3, 6, 3, 1, - mix_tlv), -SOC_SINGLE_TLV("MIXOUTL IN2A Volume", WM9090_OUTPUT_MIXER3, 2, 3, 1, - mix_tlv), - -SOC_SINGLE("MIXOUTR Switch", WM9090_OUTPUT_MIXER4, 8, 1, 1), -SOC_SINGLE_TLV("MIXOUTR IN1A Volume", WM9090_OUTPUT_MIXER4, 6, 3, 1, - mix_tlv), -SOC_SINGLE_TLV("MIXOUTR IN2A Volume", WM9090_OUTPUT_MIXER4, 2, 3, 1, - mix_tlv), - -SOC_SINGLE("SPKMIX Switch", WM9090_SPKMIXL_ATTENUATION, 8, 1, 1), -SOC_SINGLE_TLV("SPKMIX IN1A Volume", WM9090_SPKMIXL_ATTENUATION, 6, 3, 1, - mix_tlv), -SOC_SINGLE_TLV("SPKMIX IN2A Volume", WM9090_SPKMIXL_ATTENUATION, 2, 3, 1, - mix_tlv), - -SOC_DOUBLE_R_TLV("Headphone Volume", WM9090_LEFT_OUTPUT_VOLUME, - WM9090_RIGHT_OUTPUT_VOLUME, 0, 63, 0, out_tlv), -SOC_DOUBLE_R("Headphone Switch", WM9090_LEFT_OUTPUT_VOLUME, - WM9090_RIGHT_OUTPUT_VOLUME, 6, 1, 1), -SOC_DOUBLE_R("Headphone ZC Switch", WM9090_LEFT_OUTPUT_VOLUME, - WM9090_RIGHT_OUTPUT_VOLUME, 7, 1, 0), - -SOC_SINGLE_TLV("Speaker Volume", WM9090_SPEAKER_VOLUME_LEFT, 0, 63, 0, - out_tlv), -SOC_SINGLE("Speaker Switch", WM9090_SPEAKER_VOLUME_LEFT, 6, 1, 1), -SOC_SINGLE("Speaker ZC Switch", WM9090_SPEAKER_VOLUME_LEFT, 7, 1, 0), -SOC_SINGLE_TLV("Speaker Boost Volume", WM9090_CLASSD3, 3, 7, 0, spkboost_tlv), -}; - -static const struct snd_kcontrol_new wm9090_in1_se_controls[] = { -SOC_SINGLE_TLV("IN1B Volume", WM9090_IN1_LINE_INPUT_B_VOLUME, 0, 6, 0, - in_tlv), -SOC_SINGLE("IN1B Switch", WM9090_IN1_LINE_INPUT_B_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1B ZC Switch", WM9090_IN1_LINE_INPUT_B_VOLUME, 6, 1, 0), - -SOC_SINGLE_TLV("SPKMIX IN1B Volume", WM9090_SPKMIXL_ATTENUATION, 4, 3, 1, - mix_tlv), -SOC_SINGLE_TLV("MIXOUTL IN1B Volume", WM9090_OUTPUT_MIXER3, 4, 3, 1, - mix_tlv), -SOC_SINGLE_TLV("MIXOUTR IN1B Volume", WM9090_OUTPUT_MIXER4, 4, 3, 1, - mix_tlv), -}; - -static const struct snd_kcontrol_new wm9090_in2_se_controls[] = { -SOC_SINGLE_TLV("IN2B Volume", WM9090_IN2_LINE_INPUT_B_VOLUME, 0, 6, 0, - in_tlv), -SOC_SINGLE("IN2B Switch", WM9090_IN2_LINE_INPUT_B_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2B ZC Switch", WM9090_IN2_LINE_INPUT_B_VOLUME, 6, 1, 0), - -SOC_SINGLE_TLV("SPKMIX IN2B Volume", WM9090_SPKMIXL_ATTENUATION, 0, 3, 1, - mix_tlv), -SOC_SINGLE_TLV("MIXOUTL IN2B Volume", WM9090_OUTPUT_MIXER3, 0, 3, 1, - mix_tlv), -SOC_SINGLE_TLV("MIXOUTR IN2B Volume", WM9090_OUTPUT_MIXER4, 0, 3, 1, - mix_tlv), -}; - -static int hp_ev(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - unsigned int reg = snd_soc_read(codec, WM9090_ANALOGUE_HP_0); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(codec, WM9090_CHARGE_PUMP_1, - WM9090_CP_ENA, WM9090_CP_ENA); - - msleep(5); - - snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_1, - WM9090_HPOUT1L_ENA | WM9090_HPOUT1R_ENA, - WM9090_HPOUT1L_ENA | WM9090_HPOUT1R_ENA); - - reg |= WM9090_HPOUT1L_DLY | WM9090_HPOUT1R_DLY; - snd_soc_write(codec, WM9090_ANALOGUE_HP_0, reg); - - /* Start the DC servo. We don't currently use the - * ability to save the state since we don't have full - * control of the analogue paths and they can change - * DC offsets; see the WM8904 driver for an example of - * doing so. - */ - snd_soc_write(codec, WM9090_DC_SERVO_0, - WM9090_DCS_ENA_CHAN_0 | - WM9090_DCS_ENA_CHAN_1 | - WM9090_DCS_TRIG_STARTUP_1 | - WM9090_DCS_TRIG_STARTUP_0); - wait_for_dc_servo(codec); - - reg |= WM9090_HPOUT1R_OUTP | WM9090_HPOUT1R_RMV_SHORT | - WM9090_HPOUT1L_OUTP | WM9090_HPOUT1L_RMV_SHORT; - snd_soc_write(codec, WM9090_ANALOGUE_HP_0, reg); - break; - - case SND_SOC_DAPM_PRE_PMD: - reg &= ~(WM9090_HPOUT1L_RMV_SHORT | - WM9090_HPOUT1L_DLY | - WM9090_HPOUT1L_OUTP | - WM9090_HPOUT1R_RMV_SHORT | - WM9090_HPOUT1R_DLY | - WM9090_HPOUT1R_OUTP); - - snd_soc_write(codec, WM9090_ANALOGUE_HP_0, reg); - - snd_soc_write(codec, WM9090_DC_SERVO_0, 0); - - snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_1, - WM9090_HPOUT1L_ENA | WM9090_HPOUT1R_ENA, - 0); - - snd_soc_update_bits(codec, WM9090_CHARGE_PUMP_1, - WM9090_CP_ENA, 0); - break; - } - - return 0; -} - -static const struct snd_kcontrol_new spkmix[] = { -SOC_DAPM_SINGLE("IN1A Switch", WM9090_SPEAKER_MIXER, 6, 1, 0), -SOC_DAPM_SINGLE("IN1B Switch", WM9090_SPEAKER_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("IN2A Switch", WM9090_SPEAKER_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("IN2B Switch", WM9090_SPEAKER_MIXER, 0, 1, 0), -}; - -static const struct snd_kcontrol_new spkout[] = { -SOC_DAPM_SINGLE("Mixer Switch", WM9090_SPKOUT_MIXERS, 4, 1, 0), -}; - -static const struct snd_kcontrol_new mixoutl[] = { -SOC_DAPM_SINGLE("IN1A Switch", WM9090_OUTPUT_MIXER1, 6, 1, 0), -SOC_DAPM_SINGLE("IN1B Switch", WM9090_OUTPUT_MIXER1, 4, 1, 0), -SOC_DAPM_SINGLE("IN2A Switch", WM9090_OUTPUT_MIXER1, 2, 1, 0), -SOC_DAPM_SINGLE("IN2B Switch", WM9090_OUTPUT_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new mixoutr[] = { -SOC_DAPM_SINGLE("IN1A Switch", WM9090_OUTPUT_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("IN1B Switch", WM9090_OUTPUT_MIXER2, 4, 1, 0), -SOC_DAPM_SINGLE("IN2A Switch", WM9090_OUTPUT_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN2B Switch", WM9090_OUTPUT_MIXER2, 0, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm9090_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1+"), -SND_SOC_DAPM_INPUT("IN1-"), -SND_SOC_DAPM_INPUT("IN2+"), -SND_SOC_DAPM_INPUT("IN2-"), - -SND_SOC_DAPM_SUPPLY("OSC", WM9090_POWER_MANAGEMENT_1, 3, 0, NULL, 0), - -SND_SOC_DAPM_PGA("IN1A PGA", WM9090_POWER_MANAGEMENT_2, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("IN1B PGA", WM9090_POWER_MANAGEMENT_2, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("IN2A PGA", WM9090_POWER_MANAGEMENT_2, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("IN2B PGA", WM9090_POWER_MANAGEMENT_2, 4, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("SPKMIX", WM9090_POWER_MANAGEMENT_3, 3, 0, - spkmix, ARRAY_SIZE(spkmix)), -SND_SOC_DAPM_MIXER("MIXOUTL", WM9090_POWER_MANAGEMENT_3, 5, 0, - mixoutl, ARRAY_SIZE(mixoutl)), -SND_SOC_DAPM_MIXER("MIXOUTR", WM9090_POWER_MANAGEMENT_3, 4, 0, - mixoutr, ARRAY_SIZE(mixoutr)), - -SND_SOC_DAPM_PGA_E("HP PGA", SND_SOC_NOPM, 0, 0, NULL, 0, - hp_ev, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_PGA("SPKPGA", WM9090_POWER_MANAGEMENT_3, 8, 0, NULL, 0), -SND_SOC_DAPM_MIXER("SPKOUT", WM9090_POWER_MANAGEMENT_1, 12, 0, - spkout, ARRAY_SIZE(spkout)), - -SND_SOC_DAPM_OUTPUT("HPR"), -SND_SOC_DAPM_OUTPUT("HPL"), -SND_SOC_DAPM_OUTPUT("Speaker"), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - { "IN1A PGA", NULL, "IN1+" }, - { "IN2A PGA", NULL, "IN2+" }, - - { "SPKMIX", "IN1A Switch", "IN1A PGA" }, - { "SPKMIX", "IN2A Switch", "IN2A PGA" }, - - { "MIXOUTL", "IN1A Switch", "IN1A PGA" }, - { "MIXOUTL", "IN2A Switch", "IN2A PGA" }, - - { "MIXOUTR", "IN1A Switch", "IN1A PGA" }, - { "MIXOUTR", "IN2A Switch", "IN2A PGA" }, - - { "HP PGA", NULL, "OSC" }, - { "HP PGA", NULL, "MIXOUTL" }, - { "HP PGA", NULL, "MIXOUTR" }, - - { "HPL", NULL, "HP PGA" }, - { "HPR", NULL, "HP PGA" }, - - { "SPKPGA", NULL, "OSC" }, - { "SPKPGA", NULL, "SPKMIX" }, - - { "SPKOUT", "Mixer Switch", "SPKPGA" }, - - { "Speaker", NULL, "SPKOUT" }, -}; - -static const struct snd_soc_dapm_route audio_map_in1_se[] = { - { "IN1B PGA", NULL, "IN1-" }, - - { "SPKMIX", "IN1B Switch", "IN1B PGA" }, - { "MIXOUTL", "IN1B Switch", "IN1B PGA" }, - { "MIXOUTR", "IN1B Switch", "IN1B PGA" }, -}; - -static const struct snd_soc_dapm_route audio_map_in1_diff[] = { - { "IN1A PGA", NULL, "IN1-" }, -}; - -static const struct snd_soc_dapm_route audio_map_in2_se[] = { - { "IN2B PGA", NULL, "IN2-" }, - - { "SPKMIX", "IN2B Switch", "IN2B PGA" }, - { "MIXOUTL", "IN2B Switch", "IN2B PGA" }, - { "MIXOUTR", "IN2B Switch", "IN2B PGA" }, -}; - -static const struct snd_soc_dapm_route audio_map_in2_diff[] = { - { "IN2A PGA", NULL, "IN2-" }, -}; - -static int wm9090_add_controls(struct snd_soc_codec *codec) -{ - struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - int i; - - snd_soc_dapm_new_controls(dapm, wm9090_dapm_widgets, - ARRAY_SIZE(wm9090_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_add_codec_controls(codec, wm9090_controls, - ARRAY_SIZE(wm9090_controls)); - - if (wm9090->pdata.lin1_diff) { - snd_soc_dapm_add_routes(dapm, audio_map_in1_diff, - ARRAY_SIZE(audio_map_in1_diff)); - } else { - snd_soc_dapm_add_routes(dapm, audio_map_in1_se, - ARRAY_SIZE(audio_map_in1_se)); - snd_soc_add_codec_controls(codec, wm9090_in1_se_controls, - ARRAY_SIZE(wm9090_in1_se_controls)); - } - - if (wm9090->pdata.lin2_diff) { - snd_soc_dapm_add_routes(dapm, audio_map_in2_diff, - ARRAY_SIZE(audio_map_in2_diff)); - } else { - snd_soc_dapm_add_routes(dapm, audio_map_in2_se, - ARRAY_SIZE(audio_map_in2_se)); - snd_soc_add_codec_controls(codec, wm9090_in2_se_controls, - ARRAY_SIZE(wm9090_in2_se_controls)); - } - - if (wm9090->pdata.agc_ena) { - for (i = 0; i < ARRAY_SIZE(wm9090->pdata.agc); i++) - snd_soc_write(codec, WM9090_AGC_CONTROL_0 + i, - wm9090->pdata.agc[i]); - snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_3, - WM9090_AGC_ENA, WM9090_AGC_ENA); - } else { - snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_3, - WM9090_AGC_ENA, 0); - } - - return 0; - -} - -/* - * The machine driver should call this from their set_bias_level; if there - * isn't one then this can just be set as the set_bias_level function. - */ -static int wm9090_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - snd_soc_update_bits(codec, WM9090_ANTIPOP2, WM9090_VMID_ENA, - WM9090_VMID_ENA); - snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_1, - WM9090_BIAS_ENA | - WM9090_VMID_RES_MASK, - WM9090_BIAS_ENA | - 1 << WM9090_VMID_RES_SHIFT); - msleep(1); /* Probably an overestimate */ - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { - /* Restore the register cache */ - regcache_sync(wm9090->regmap); - } - - /* We keep VMID off during standby since the combination of - * ground referenced outputs and class D speaker mean that - * latency is not an issue. - */ - snd_soc_update_bits(codec, WM9090_POWER_MANAGEMENT_1, - WM9090_BIAS_ENA | WM9090_VMID_RES_MASK, 0); - snd_soc_update_bits(codec, WM9090_ANTIPOP2, - WM9090_VMID_ENA, 0); - break; - - case SND_SOC_BIAS_OFF: - break; - } - - codec->dapm.bias_level = level; - - return 0; -} - -static int wm9090_probe(struct snd_soc_codec *codec) -{ - struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev); - int ret; - - codec->control_data = wm9090->regmap; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - /* Configure some defaults; they will be written out when we - * bring the bias up. - */ - snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_A_VOLUME, - WM9090_IN1_VU | WM9090_IN1A_ZC, - WM9090_IN1_VU | WM9090_IN1A_ZC); - snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_B_VOLUME, - WM9090_IN1_VU | WM9090_IN1B_ZC, - WM9090_IN1_VU | WM9090_IN1B_ZC); - snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_A_VOLUME, - WM9090_IN2_VU | WM9090_IN2A_ZC, - WM9090_IN2_VU | WM9090_IN2A_ZC); - snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_B_VOLUME, - WM9090_IN2_VU | WM9090_IN2B_ZC, - WM9090_IN2_VU | WM9090_IN2B_ZC); - snd_soc_update_bits(codec, WM9090_SPEAKER_VOLUME_LEFT, - WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC, - WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC); - snd_soc_update_bits(codec, WM9090_LEFT_OUTPUT_VOLUME, - WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC, - WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC); - snd_soc_update_bits(codec, WM9090_RIGHT_OUTPUT_VOLUME, - WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC, - WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC); - - snd_soc_update_bits(codec, WM9090_CLOCKING_1, - WM9090_TOCLK_ENA, WM9090_TOCLK_ENA); - - wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - wm9090_add_controls(codec); - - return 0; -} - -#ifdef CONFIG_PM -static int wm9090_suspend(struct snd_soc_codec *codec) -{ - wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm9090_resume(struct snd_soc_codec *codec) -{ - wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm9090_suspend NULL -#define wm9090_resume NULL -#endif - -static int wm9090_remove(struct snd_soc_codec *codec) -{ - wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm9090 = { - .probe = wm9090_probe, - .remove = wm9090_remove, - .suspend = wm9090_suspend, - .resume = wm9090_resume, - .set_bias_level = wm9090_set_bias_level, -}; - -static const struct regmap_config wm9090_regmap = { - .reg_bits = 8, - .val_bits = 16, - - .max_register = WM9090_MAX_REGISTER, - .volatile_reg = wm9090_volatile, - .readable_reg = wm9090_readable, - - .cache_type = REGCACHE_RBTREE, - .reg_defaults = wm9090_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(wm9090_reg_defaults), -}; - - -static int wm9090_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm9090_priv *wm9090; - unsigned int reg; - int ret; - - wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL); - if (wm9090 == NULL) { - dev_err(&i2c->dev, "Can not allocate memory\n"); - return -ENOMEM; - } - - wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap); - if (IS_ERR(wm9090->regmap)) { - ret = PTR_ERR(wm9090->regmap); - dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); - return ret; - } - - ret = regmap_read(wm9090->regmap, WM9090_SOFTWARE_RESET, ®); - if (ret < 0) - goto err; - if (reg != 0x9093) { - dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg); - ret = -ENODEV; - goto err; - } - - ret = regmap_write(wm9090->regmap, WM9090_SOFTWARE_RESET, 0); - if (ret < 0) - goto err; - - if (i2c->dev.platform_data) - memcpy(&wm9090->pdata, i2c->dev.platform_data, - sizeof(wm9090->pdata)); - - i2c_set_clientdata(i2c, wm9090); - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_wm9090, NULL, 0); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - goto err; - } - - return 0; - -err: - regmap_exit(wm9090->regmap); - return ret; -} - -static int __devexit wm9090_i2c_remove(struct i2c_client *i2c) -{ - struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); - - snd_soc_unregister_codec(&i2c->dev); - regmap_exit(wm9090->regmap); - - return 0; -} - -static const struct i2c_device_id wm9090_id[] = { - { "wm9090", 0 }, - { "wm9093", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm9090_id); - -static struct i2c_driver wm9090_i2c_driver = { - .driver = { - .name = "wm9090", - .owner = THIS_MODULE, - }, - .probe = wm9090_i2c_probe, - .remove = __devexit_p(wm9090_i2c_remove), - .id_table = wm9090_id, -}; - -static int __init wm9090_init(void) -{ - return i2c_add_driver(&wm9090_i2c_driver); -} -module_init(wm9090_init); - -static void __exit wm9090_exit(void) -{ - i2c_del_driver(&wm9090_i2c_driver); -} -module_exit(wm9090_exit); - -MODULE_AUTHOR("Mark Brown "); -MODULE_DESCRIPTION("WM9090 ASoC driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9090.h b/ANDROID_3.4.5/sound/soc/codecs/wm9090.h deleted file mode 100644 index 29b9d9fc..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9090.h +++ /dev/null @@ -1,713 +0,0 @@ -/* - * ALSA SoC WM9090 driver - * - * Copyright 2009 Wolfson Microelectronics - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#ifndef __WM9090_H -#define __WM9090_H - -/* - * Register values. - */ -#define WM9090_SOFTWARE_RESET 0x00 -#define WM9090_POWER_MANAGEMENT_1 0x01 -#define WM9090_POWER_MANAGEMENT_2 0x02 -#define WM9090_POWER_MANAGEMENT_3 0x03 -#define WM9090_CLOCKING_1 0x06 -#define WM9090_IN1_LINE_CONTROL 0x16 -#define WM9090_IN2_LINE_CONTROL 0x17 -#define WM9090_IN1_LINE_INPUT_A_VOLUME 0x18 -#define WM9090_IN1_LINE_INPUT_B_VOLUME 0x19 -#define WM9090_IN2_LINE_INPUT_A_VOLUME 0x1A -#define WM9090_IN2_LINE_INPUT_B_VOLUME 0x1B -#define WM9090_LEFT_OUTPUT_VOLUME 0x1C -#define WM9090_RIGHT_OUTPUT_VOLUME 0x1D -#define WM9090_SPKMIXL_ATTENUATION 0x22 -#define WM9090_SPKOUT_MIXERS 0x24 -#define WM9090_CLASSD3 0x25 -#define WM9090_SPEAKER_VOLUME_LEFT 0x26 -#define WM9090_OUTPUT_MIXER1 0x2D -#define WM9090_OUTPUT_MIXER2 0x2E -#define WM9090_OUTPUT_MIXER3 0x2F -#define WM9090_OUTPUT_MIXER4 0x30 -#define WM9090_SPEAKER_MIXER 0x36 -#define WM9090_ANTIPOP2 0x39 -#define WM9090_WRITE_SEQUENCER_0 0x46 -#define WM9090_WRITE_SEQUENCER_1 0x47 -#define WM9090_WRITE_SEQUENCER_2 0x48 -#define WM9090_WRITE_SEQUENCER_3 0x49 -#define WM9090_WRITE_SEQUENCER_4 0x4A -#define WM9090_WRITE_SEQUENCER_5 0x4B -#define WM9090_CHARGE_PUMP_1 0x4C -#define WM9090_DC_SERVO_0 0x54 -#define WM9090_DC_SERVO_1 0x55 -#define WM9090_DC_SERVO_3 0x57 -#define WM9090_DC_SERVO_READBACK_0 0x58 -#define WM9090_DC_SERVO_READBACK_1 0x59 -#define WM9090_DC_SERVO_READBACK_2 0x5A -#define WM9090_ANALOGUE_HP_0 0x60 -#define WM9090_AGC_CONTROL_0 0x62 -#define WM9090_AGC_CONTROL_1 0x63 -#define WM9090_AGC_CONTROL_2 0x64 - -#define WM9090_REGISTER_COUNT 40 -#define WM9090_MAX_REGISTER 0x64 - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM9090_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ -#define WM9090_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ -#define WM9090_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ - -/* - * R1 (0x01) - Power Management (1) - */ -#define WM9090_SPKOUTL_ENA 0x1000 /* SPKOUTL_ENA */ -#define WM9090_SPKOUTL_ENA_MASK 0x1000 /* SPKOUTL_ENA */ -#define WM9090_SPKOUTL_ENA_SHIFT 12 /* SPKOUTL_ENA */ -#define WM9090_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */ -#define WM9090_HPOUT1L_ENA 0x0200 /* HPOUT1L_ENA */ -#define WM9090_HPOUT1L_ENA_MASK 0x0200 /* HPOUT1L_ENA */ -#define WM9090_HPOUT1L_ENA_SHIFT 9 /* HPOUT1L_ENA */ -#define WM9090_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */ -#define WM9090_HPOUT1R_ENA 0x0100 /* HPOUT1R_ENA */ -#define WM9090_HPOUT1R_ENA_MASK 0x0100 /* HPOUT1R_ENA */ -#define WM9090_HPOUT1R_ENA_SHIFT 8 /* HPOUT1R_ENA */ -#define WM9090_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */ -#define WM9090_OSC_ENA 0x0008 /* OSC_ENA */ -#define WM9090_OSC_ENA_MASK 0x0008 /* OSC_ENA */ -#define WM9090_OSC_ENA_SHIFT 3 /* OSC_ENA */ -#define WM9090_OSC_ENA_WIDTH 1 /* OSC_ENA */ -#define WM9090_VMID_RES_MASK 0x0006 /* VMID_RES - [2:1] */ -#define WM9090_VMID_RES_SHIFT 1 /* VMID_RES - [2:1] */ -#define WM9090_VMID_RES_WIDTH 2 /* VMID_RES - [2:1] */ -#define WM9090_BIAS_ENA 0x0001 /* BIAS_ENA */ -#define WM9090_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */ -#define WM9090_BIAS_ENA_SHIFT 0 /* BIAS_ENA */ -#define WM9090_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ - -/* - * R2 (0x02) - Power Management (2) - */ -#define WM9090_TSHUT 0x8000 /* TSHUT */ -#define WM9090_TSHUT_MASK 0x8000 /* TSHUT */ -#define WM9090_TSHUT_SHIFT 15 /* TSHUT */ -#define WM9090_TSHUT_WIDTH 1 /* TSHUT */ -#define WM9090_TSHUT_ENA 0x4000 /* TSHUT_ENA */ -#define WM9090_TSHUT_ENA_MASK 0x4000 /* TSHUT_ENA */ -#define WM9090_TSHUT_ENA_SHIFT 14 /* TSHUT_ENA */ -#define WM9090_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */ -#define WM9090_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */ -#define WM9090_TSHUT_OPDIS_MASK 0x2000 /* TSHUT_OPDIS */ -#define WM9090_TSHUT_OPDIS_SHIFT 13 /* TSHUT_OPDIS */ -#define WM9090_TSHUT_OPDIS_WIDTH 1 /* TSHUT_OPDIS */ -#define WM9090_IN1A_ENA 0x0080 /* IN1A_ENA */ -#define WM9090_IN1A_ENA_MASK 0x0080 /* IN1A_ENA */ -#define WM9090_IN1A_ENA_SHIFT 7 /* IN1A_ENA */ -#define WM9090_IN1A_ENA_WIDTH 1 /* IN1A_ENA */ -#define WM9090_IN1B_ENA 0x0040 /* IN1B_ENA */ -#define WM9090_IN1B_ENA_MASK 0x0040 /* IN1B_ENA */ -#define WM9090_IN1B_ENA_SHIFT 6 /* IN1B_ENA */ -#define WM9090_IN1B_ENA_WIDTH 1 /* IN1B_ENA */ -#define WM9090_IN2A_ENA 0x0020 /* IN2A_ENA */ -#define WM9090_IN2A_ENA_MASK 0x0020 /* IN2A_ENA */ -#define WM9090_IN2A_ENA_SHIFT 5 /* IN2A_ENA */ -#define WM9090_IN2A_ENA_WIDTH 1 /* IN2A_ENA */ -#define WM9090_IN2B_ENA 0x0010 /* IN2B_ENA */ -#define WM9090_IN2B_ENA_MASK 0x0010 /* IN2B_ENA */ -#define WM9090_IN2B_ENA_SHIFT 4 /* IN2B_ENA */ -#define WM9090_IN2B_ENA_WIDTH 1 /* IN2B_ENA */ - -/* - * R3 (0x03) - Power Management (3) - */ -#define WM9090_AGC_ENA 0x4000 /* AGC_ENA */ -#define WM9090_AGC_ENA_MASK 0x4000 /* AGC_ENA */ -#define WM9090_AGC_ENA_SHIFT 14 /* AGC_ENA */ -#define WM9090_AGC_ENA_WIDTH 1 /* AGC_ENA */ -#define WM9090_SPKLVOL_ENA 0x0100 /* SPKLVOL_ENA */ -#define WM9090_SPKLVOL_ENA_MASK 0x0100 /* SPKLVOL_ENA */ -#define WM9090_SPKLVOL_ENA_SHIFT 8 /* SPKLVOL_ENA */ -#define WM9090_SPKLVOL_ENA_WIDTH 1 /* SPKLVOL_ENA */ -#define WM9090_MIXOUTL_ENA 0x0020 /* MIXOUTL_ENA */ -#define WM9090_MIXOUTL_ENA_MASK 0x0020 /* MIXOUTL_ENA */ -#define WM9090_MIXOUTL_ENA_SHIFT 5 /* MIXOUTL_ENA */ -#define WM9090_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */ -#define WM9090_MIXOUTR_ENA 0x0010 /* MIXOUTR_ENA */ -#define WM9090_MIXOUTR_ENA_MASK 0x0010 /* MIXOUTR_ENA */ -#define WM9090_MIXOUTR_ENA_SHIFT 4 /* MIXOUTR_ENA */ -#define WM9090_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */ -#define WM9090_SPKMIX_ENA 0x0008 /* SPKMIX_ENA */ -#define WM9090_SPKMIX_ENA_MASK 0x0008 /* SPKMIX_ENA */ -#define WM9090_SPKMIX_ENA_SHIFT 3 /* SPKMIX_ENA */ -#define WM9090_SPKMIX_ENA_WIDTH 1 /* SPKMIX_ENA */ - -/* - * R6 (0x06) - Clocking 1 - */ -#define WM9090_TOCLK_RATE 0x8000 /* TOCLK_RATE */ -#define WM9090_TOCLK_RATE_MASK 0x8000 /* TOCLK_RATE */ -#define WM9090_TOCLK_RATE_SHIFT 15 /* TOCLK_RATE */ -#define WM9090_TOCLK_RATE_WIDTH 1 /* TOCLK_RATE */ -#define WM9090_TOCLK_ENA 0x4000 /* TOCLK_ENA */ -#define WM9090_TOCLK_ENA_MASK 0x4000 /* TOCLK_ENA */ -#define WM9090_TOCLK_ENA_SHIFT 14 /* TOCLK_ENA */ -#define WM9090_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ - -/* - * R22 (0x16) - IN1 Line Control - */ -#define WM9090_IN1_DIFF 0x0002 /* IN1_DIFF */ -#define WM9090_IN1_DIFF_MASK 0x0002 /* IN1_DIFF */ -#define WM9090_IN1_DIFF_SHIFT 1 /* IN1_DIFF */ -#define WM9090_IN1_DIFF_WIDTH 1 /* IN1_DIFF */ -#define WM9090_IN1_CLAMP 0x0001 /* IN1_CLAMP */ -#define WM9090_IN1_CLAMP_MASK 0x0001 /* IN1_CLAMP */ -#define WM9090_IN1_CLAMP_SHIFT 0 /* IN1_CLAMP */ -#define WM9090_IN1_CLAMP_WIDTH 1 /* IN1_CLAMP */ - -/* - * R23 (0x17) - IN2 Line Control - */ -#define WM9090_IN2_DIFF 0x0002 /* IN2_DIFF */ -#define WM9090_IN2_DIFF_MASK 0x0002 /* IN2_DIFF */ -#define WM9090_IN2_DIFF_SHIFT 1 /* IN2_DIFF */ -#define WM9090_IN2_DIFF_WIDTH 1 /* IN2_DIFF */ -#define WM9090_IN2_CLAMP 0x0001 /* IN2_CLAMP */ -#define WM9090_IN2_CLAMP_MASK 0x0001 /* IN2_CLAMP */ -#define WM9090_IN2_CLAMP_SHIFT 0 /* IN2_CLAMP */ -#define WM9090_IN2_CLAMP_WIDTH 1 /* IN2_CLAMP */ - -/* - * R24 (0x18) - IN1 Line Input A Volume - */ -#define WM9090_IN1_VU 0x0100 /* IN1_VU */ -#define WM9090_IN1_VU_MASK 0x0100 /* IN1_VU */ -#define WM9090_IN1_VU_SHIFT 8 /* IN1_VU */ -#define WM9090_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM9090_IN1A_MUTE 0x0080 /* IN1A_MUTE */ -#define WM9090_IN1A_MUTE_MASK 0x0080 /* IN1A_MUTE */ -#define WM9090_IN1A_MUTE_SHIFT 7 /* IN1A_MUTE */ -#define WM9090_IN1A_MUTE_WIDTH 1 /* IN1A_MUTE */ -#define WM9090_IN1A_ZC 0x0040 /* IN1A_ZC */ -#define WM9090_IN1A_ZC_MASK 0x0040 /* IN1A_ZC */ -#define WM9090_IN1A_ZC_SHIFT 6 /* IN1A_ZC */ -#define WM9090_IN1A_ZC_WIDTH 1 /* IN1A_ZC */ -#define WM9090_IN1A_VOL_MASK 0x0007 /* IN1A_VOL - [2:0] */ -#define WM9090_IN1A_VOL_SHIFT 0 /* IN1A_VOL - [2:0] */ -#define WM9090_IN1A_VOL_WIDTH 3 /* IN1A_VOL - [2:0] */ - -/* - * R25 (0x19) - IN1 Line Input B Volume - */ -#define WM9090_IN1_VU 0x0100 /* IN1_VU */ -#define WM9090_IN1_VU_MASK 0x0100 /* IN1_VU */ -#define WM9090_IN1_VU_SHIFT 8 /* IN1_VU */ -#define WM9090_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM9090_IN1B_MUTE 0x0080 /* IN1B_MUTE */ -#define WM9090_IN1B_MUTE_MASK 0x0080 /* IN1B_MUTE */ -#define WM9090_IN1B_MUTE_SHIFT 7 /* IN1B_MUTE */ -#define WM9090_IN1B_MUTE_WIDTH 1 /* IN1B_MUTE */ -#define WM9090_IN1B_ZC 0x0040 /* IN1B_ZC */ -#define WM9090_IN1B_ZC_MASK 0x0040 /* IN1B_ZC */ -#define WM9090_IN1B_ZC_SHIFT 6 /* IN1B_ZC */ -#define WM9090_IN1B_ZC_WIDTH 1 /* IN1B_ZC */ -#define WM9090_IN1B_VOL_MASK 0x0007 /* IN1B_VOL - [2:0] */ -#define WM9090_IN1B_VOL_SHIFT 0 /* IN1B_VOL - [2:0] */ -#define WM9090_IN1B_VOL_WIDTH 3 /* IN1B_VOL - [2:0] */ - -/* - * R26 (0x1A) - IN2 Line Input A Volume - */ -#define WM9090_IN2_VU 0x0100 /* IN2_VU */ -#define WM9090_IN2_VU_MASK 0x0100 /* IN2_VU */ -#define WM9090_IN2_VU_SHIFT 8 /* IN2_VU */ -#define WM9090_IN2_VU_WIDTH 1 /* IN2_VU */ -#define WM9090_IN2A_MUTE 0x0080 /* IN2A_MUTE */ -#define WM9090_IN2A_MUTE_MASK 0x0080 /* IN2A_MUTE */ -#define WM9090_IN2A_MUTE_SHIFT 7 /* IN2A_MUTE */ -#define WM9090_IN2A_MUTE_WIDTH 1 /* IN2A_MUTE */ -#define WM9090_IN2A_ZC 0x0040 /* IN2A_ZC */ -#define WM9090_IN2A_ZC_MASK 0x0040 /* IN2A_ZC */ -#define WM9090_IN2A_ZC_SHIFT 6 /* IN2A_ZC */ -#define WM9090_IN2A_ZC_WIDTH 1 /* IN2A_ZC */ -#define WM9090_IN2A_VOL_MASK 0x0007 /* IN2A_VOL - [2:0] */ -#define WM9090_IN2A_VOL_SHIFT 0 /* IN2A_VOL - [2:0] */ -#define WM9090_IN2A_VOL_WIDTH 3 /* IN2A_VOL - [2:0] */ - -/* - * R27 (0x1B) - IN2 Line Input B Volume - */ -#define WM9090_IN2_VU 0x0100 /* IN2_VU */ -#define WM9090_IN2_VU_MASK 0x0100 /* IN2_VU */ -#define WM9090_IN2_VU_SHIFT 8 /* IN2_VU */ -#define WM9090_IN2_VU_WIDTH 1 /* IN2_VU */ -#define WM9090_IN2B_MUTE 0x0080 /* IN2B_MUTE */ -#define WM9090_IN2B_MUTE_MASK 0x0080 /* IN2B_MUTE */ -#define WM9090_IN2B_MUTE_SHIFT 7 /* IN2B_MUTE */ -#define WM9090_IN2B_MUTE_WIDTH 1 /* IN2B_MUTE */ -#define WM9090_IN2B_ZC 0x0040 /* IN2B_ZC */ -#define WM9090_IN2B_ZC_MASK 0x0040 /* IN2B_ZC */ -#define WM9090_IN2B_ZC_SHIFT 6 /* IN2B_ZC */ -#define WM9090_IN2B_ZC_WIDTH 1 /* IN2B_ZC */ -#define WM9090_IN2B_VOL_MASK 0x0007 /* IN2B_VOL - [2:0] */ -#define WM9090_IN2B_VOL_SHIFT 0 /* IN2B_VOL - [2:0] */ -#define WM9090_IN2B_VOL_WIDTH 3 /* IN2B_VOL - [2:0] */ - -/* - * R28 (0x1C) - Left Output Volume - */ -#define WM9090_HPOUT1_VU 0x0100 /* HPOUT1_VU */ -#define WM9090_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */ -#define WM9090_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */ -#define WM9090_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */ -#define WM9090_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */ -#define WM9090_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */ -#define WM9090_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */ -#define WM9090_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */ -#define WM9090_HPOUT1L_MUTE 0x0040 /* HPOUT1L_MUTE */ -#define WM9090_HPOUT1L_MUTE_MASK 0x0040 /* HPOUT1L_MUTE */ -#define WM9090_HPOUT1L_MUTE_SHIFT 6 /* HPOUT1L_MUTE */ -#define WM9090_HPOUT1L_MUTE_WIDTH 1 /* HPOUT1L_MUTE */ -#define WM9090_HPOUT1L_VOL_MASK 0x003F /* HPOUT1L_VOL - [5:0] */ -#define WM9090_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [5:0] */ -#define WM9090_HPOUT1L_VOL_WIDTH 6 /* HPOUT1L_VOL - [5:0] */ - -/* - * R29 (0x1D) - Right Output Volume - */ -#define WM9090_HPOUT1_VU 0x0100 /* HPOUT1_VU */ -#define WM9090_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */ -#define WM9090_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */ -#define WM9090_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */ -#define WM9090_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */ -#define WM9090_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */ -#define WM9090_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */ -#define WM9090_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */ -#define WM9090_HPOUT1R_MUTE 0x0040 /* HPOUT1R_MUTE */ -#define WM9090_HPOUT1R_MUTE_MASK 0x0040 /* HPOUT1R_MUTE */ -#define WM9090_HPOUT1R_MUTE_SHIFT 6 /* HPOUT1R_MUTE */ -#define WM9090_HPOUT1R_MUTE_WIDTH 1 /* HPOUT1R_MUTE */ -#define WM9090_HPOUT1R_VOL_MASK 0x003F /* HPOUT1R_VOL - [5:0] */ -#define WM9090_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [5:0] */ -#define WM9090_HPOUT1R_VOL_WIDTH 6 /* HPOUT1R_VOL - [5:0] */ - -/* - * R34 (0x22) - SPKMIXL Attenuation - */ -#define WM9090_SPKMIX_MUTE 0x0100 /* SPKMIX_MUTE */ -#define WM9090_SPKMIX_MUTE_MASK 0x0100 /* SPKMIX_MUTE */ -#define WM9090_SPKMIX_MUTE_SHIFT 8 /* SPKMIX_MUTE */ -#define WM9090_SPKMIX_MUTE_WIDTH 1 /* SPKMIX_MUTE */ -#define WM9090_IN1A_SPKMIX_VOL_MASK 0x00C0 /* IN1A_SPKMIX_VOL - [7:6] */ -#define WM9090_IN1A_SPKMIX_VOL_SHIFT 6 /* IN1A_SPKMIX_VOL - [7:6] */ -#define WM9090_IN1A_SPKMIX_VOL_WIDTH 2 /* IN1A_SPKMIX_VOL - [7:6] */ -#define WM9090_IN1B_SPKMIX_VOL_MASK 0x0030 /* IN1B_SPKMIX_VOL - [5:4] */ -#define WM9090_IN1B_SPKMIX_VOL_SHIFT 4 /* IN1B_SPKMIX_VOL - [5:4] */ -#define WM9090_IN1B_SPKMIX_VOL_WIDTH 2 /* IN1B_SPKMIX_VOL - [5:4] */ -#define WM9090_IN2A_SPKMIX_VOL_MASK 0x000C /* IN2A_SPKMIX_VOL - [3:2] */ -#define WM9090_IN2A_SPKMIX_VOL_SHIFT 2 /* IN2A_SPKMIX_VOL - [3:2] */ -#define WM9090_IN2A_SPKMIX_VOL_WIDTH 2 /* IN2A_SPKMIX_VOL - [3:2] */ -#define WM9090_IN2B_SPKMIX_VOL_MASK 0x0003 /* IN2B_SPKMIX_VOL - [1:0] */ -#define WM9090_IN2B_SPKMIX_VOL_SHIFT 0 /* IN2B_SPKMIX_VOL - [1:0] */ -#define WM9090_IN2B_SPKMIX_VOL_WIDTH 2 /* IN2B_SPKMIX_VOL - [1:0] */ - -/* - * R36 (0x24) - SPKOUT Mixers - */ -#define WM9090_SPKMIXL_TO_SPKOUTL 0x0010 /* SPKMIXL_TO_SPKOUTL */ -#define WM9090_SPKMIXL_TO_SPKOUTL_MASK 0x0010 /* SPKMIXL_TO_SPKOUTL */ -#define WM9090_SPKMIXL_TO_SPKOUTL_SHIFT 4 /* SPKMIXL_TO_SPKOUTL */ -#define WM9090_SPKMIXL_TO_SPKOUTL_WIDTH 1 /* SPKMIXL_TO_SPKOUTL */ - -/* - * R37 (0x25) - ClassD3 - */ -#define WM9090_SPKOUTL_BOOST_MASK 0x0038 /* SPKOUTL_BOOST - [5:3] */ -#define WM9090_SPKOUTL_BOOST_SHIFT 3 /* SPKOUTL_BOOST - [5:3] */ -#define WM9090_SPKOUTL_BOOST_WIDTH 3 /* SPKOUTL_BOOST - [5:3] */ - -/* - * R38 (0x26) - Speaker Volume Left - */ -#define WM9090_SPKOUT_VU 0x0100 /* SPKOUT_VU */ -#define WM9090_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ -#define WM9090_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ -#define WM9090_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ -#define WM9090_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */ -#define WM9090_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */ -#define WM9090_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */ -#define WM9090_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */ -#define WM9090_SPKOUTL_MUTE 0x0040 /* SPKOUTL_MUTE */ -#define WM9090_SPKOUTL_MUTE_MASK 0x0040 /* SPKOUTL_MUTE */ -#define WM9090_SPKOUTL_MUTE_SHIFT 6 /* SPKOUTL_MUTE */ -#define WM9090_SPKOUTL_MUTE_WIDTH 1 /* SPKOUTL_MUTE */ -#define WM9090_SPKOUTL_VOL_MASK 0x003F /* SPKOUTL_VOL - [5:0] */ -#define WM9090_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [5:0] */ -#define WM9090_SPKOUTL_VOL_WIDTH 6 /* SPKOUTL_VOL - [5:0] */ - -/* - * R45 (0x2D) - Output Mixer1 - */ -#define WM9090_IN1A_TO_MIXOUTL 0x0040 /* IN1A_TO_MIXOUTL */ -#define WM9090_IN1A_TO_MIXOUTL_MASK 0x0040 /* IN1A_TO_MIXOUTL */ -#define WM9090_IN1A_TO_MIXOUTL_SHIFT 6 /* IN1A_TO_MIXOUTL */ -#define WM9090_IN1A_TO_MIXOUTL_WIDTH 1 /* IN1A_TO_MIXOUTL */ -#define WM9090_IN2A_TO_MIXOUTL 0x0004 /* IN2A_TO_MIXOUTL */ -#define WM9090_IN2A_TO_MIXOUTL_MASK 0x0004 /* IN2A_TO_MIXOUTL */ -#define WM9090_IN2A_TO_MIXOUTL_SHIFT 2 /* IN2A_TO_MIXOUTL */ -#define WM9090_IN2A_TO_MIXOUTL_WIDTH 1 /* IN2A_TO_MIXOUTL */ - -/* - * R46 (0x2E) - Output Mixer2 - */ -#define WM9090_IN1A_TO_MIXOUTR 0x0040 /* IN1A_TO_MIXOUTR */ -#define WM9090_IN1A_TO_MIXOUTR_MASK 0x0040 /* IN1A_TO_MIXOUTR */ -#define WM9090_IN1A_TO_MIXOUTR_SHIFT 6 /* IN1A_TO_MIXOUTR */ -#define WM9090_IN1A_TO_MIXOUTR_WIDTH 1 /* IN1A_TO_MIXOUTR */ -#define WM9090_IN1B_TO_MIXOUTR 0x0010 /* IN1B_TO_MIXOUTR */ -#define WM9090_IN1B_TO_MIXOUTR_MASK 0x0010 /* IN1B_TO_MIXOUTR */ -#define WM9090_IN1B_TO_MIXOUTR_SHIFT 4 /* IN1B_TO_MIXOUTR */ -#define WM9090_IN1B_TO_MIXOUTR_WIDTH 1 /* IN1B_TO_MIXOUTR */ -#define WM9090_IN2A_TO_MIXOUTR 0x0004 /* IN2A_TO_MIXOUTR */ -#define WM9090_IN2A_TO_MIXOUTR_MASK 0x0004 /* IN2A_TO_MIXOUTR */ -#define WM9090_IN2A_TO_MIXOUTR_SHIFT 2 /* IN2A_TO_MIXOUTR */ -#define WM9090_IN2A_TO_MIXOUTR_WIDTH 1 /* IN2A_TO_MIXOUTR */ -#define WM9090_IN2B_TO_MIXOUTR 0x0001 /* IN2B_TO_MIXOUTR */ -#define WM9090_IN2B_TO_MIXOUTR_MASK 0x0001 /* IN2B_TO_MIXOUTR */ -#define WM9090_IN2B_TO_MIXOUTR_SHIFT 0 /* IN2B_TO_MIXOUTR */ -#define WM9090_IN2B_TO_MIXOUTR_WIDTH 1 /* IN2B_TO_MIXOUTR */ - -/* - * R47 (0x2F) - Output Mixer3 - */ -#define WM9090_MIXOUTL_MUTE 0x0100 /* MIXOUTL_MUTE */ -#define WM9090_MIXOUTL_MUTE_MASK 0x0100 /* MIXOUTL_MUTE */ -#define WM9090_MIXOUTL_MUTE_SHIFT 8 /* MIXOUTL_MUTE */ -#define WM9090_MIXOUTL_MUTE_WIDTH 1 /* MIXOUTL_MUTE */ -#define WM9090_IN1A_MIXOUTL_VOL_MASK 0x00C0 /* IN1A_MIXOUTL_VOL - [7:6] */ -#define WM9090_IN1A_MIXOUTL_VOL_SHIFT 6 /* IN1A_MIXOUTL_VOL - [7:6] */ -#define WM9090_IN1A_MIXOUTL_VOL_WIDTH 2 /* IN1A_MIXOUTL_VOL - [7:6] */ -#define WM9090_IN2A_MIXOUTL_VOL_MASK 0x000C /* IN2A_MIXOUTL_VOL - [3:2] */ -#define WM9090_IN2A_MIXOUTL_VOL_SHIFT 2 /* IN2A_MIXOUTL_VOL - [3:2] */ -#define WM9090_IN2A_MIXOUTL_VOL_WIDTH 2 /* IN2A_MIXOUTL_VOL - [3:2] */ - -/* - * R48 (0x30) - Output Mixer4 - */ -#define WM9090_MIXOUTR_MUTE 0x0100 /* MIXOUTR_MUTE */ -#define WM9090_MIXOUTR_MUTE_MASK 0x0100 /* MIXOUTR_MUTE */ -#define WM9090_MIXOUTR_MUTE_SHIFT 8 /* MIXOUTR_MUTE */ -#define WM9090_MIXOUTR_MUTE_WIDTH 1 /* MIXOUTR_MUTE */ -#define WM9090_IN1A_MIXOUTR_VOL_MASK 0x00C0 /* IN1A_MIXOUTR_VOL - [7:6] */ -#define WM9090_IN1A_MIXOUTR_VOL_SHIFT 6 /* IN1A_MIXOUTR_VOL - [7:6] */ -#define WM9090_IN1A_MIXOUTR_VOL_WIDTH 2 /* IN1A_MIXOUTR_VOL - [7:6] */ -#define WM9090_IN1B_MIXOUTR_VOL_MASK 0x0030 /* IN1B_MIXOUTR_VOL - [5:4] */ -#define WM9090_IN1B_MIXOUTR_VOL_SHIFT 4 /* IN1B_MIXOUTR_VOL - [5:4] */ -#define WM9090_IN1B_MIXOUTR_VOL_WIDTH 2 /* IN1B_MIXOUTR_VOL - [5:4] */ -#define WM9090_IN2A_MIXOUTR_VOL_MASK 0x000C /* IN2A_MIXOUTR_VOL - [3:2] */ -#define WM9090_IN2A_MIXOUTR_VOL_SHIFT 2 /* IN2A_MIXOUTR_VOL - [3:2] */ -#define WM9090_IN2A_MIXOUTR_VOL_WIDTH 2 /* IN2A_MIXOUTR_VOL - [3:2] */ -#define WM9090_IN2B_MIXOUTR_VOL_MASK 0x0003 /* IN2B_MIXOUTR_VOL - [1:0] */ -#define WM9090_IN2B_MIXOUTR_VOL_SHIFT 0 /* IN2B_MIXOUTR_VOL - [1:0] */ -#define WM9090_IN2B_MIXOUTR_VOL_WIDTH 2 /* IN2B_MIXOUTR_VOL - [1:0] */ - -/* - * R54 (0x36) - Speaker Mixer - */ -#define WM9090_IN1A_TO_SPKMIX 0x0040 /* IN1A_TO_SPKMIX */ -#define WM9090_IN1A_TO_SPKMIX_MASK 0x0040 /* IN1A_TO_SPKMIX */ -#define WM9090_IN1A_TO_SPKMIX_SHIFT 6 /* IN1A_TO_SPKMIX */ -#define WM9090_IN1A_TO_SPKMIX_WIDTH 1 /* IN1A_TO_SPKMIX */ -#define WM9090_IN1B_TO_SPKMIX 0x0010 /* IN1B_TO_SPKMIX */ -#define WM9090_IN1B_TO_SPKMIX_MASK 0x0010 /* IN1B_TO_SPKMIX */ -#define WM9090_IN1B_TO_SPKMIX_SHIFT 4 /* IN1B_TO_SPKMIX */ -#define WM9090_IN1B_TO_SPKMIX_WIDTH 1 /* IN1B_TO_SPKMIX */ -#define WM9090_IN2A_TO_SPKMIX 0x0004 /* IN2A_TO_SPKMIX */ -#define WM9090_IN2A_TO_SPKMIX_MASK 0x0004 /* IN2A_TO_SPKMIX */ -#define WM9090_IN2A_TO_SPKMIX_SHIFT 2 /* IN2A_TO_SPKMIX */ -#define WM9090_IN2A_TO_SPKMIX_WIDTH 1 /* IN2A_TO_SPKMIX */ -#define WM9090_IN2B_TO_SPKMIX 0x0001 /* IN2B_TO_SPKMIX */ -#define WM9090_IN2B_TO_SPKMIX_MASK 0x0001 /* IN2B_TO_SPKMIX */ -#define WM9090_IN2B_TO_SPKMIX_SHIFT 0 /* IN2B_TO_SPKMIX */ -#define WM9090_IN2B_TO_SPKMIX_WIDTH 1 /* IN2B_TO_SPKMIX */ - -/* - * R57 (0x39) - AntiPOP2 - */ -#define WM9090_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */ -#define WM9090_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */ -#define WM9090_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */ -#define WM9090_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ -#define WM9090_VMID_ENA 0x0001 /* VMID_ENA */ -#define WM9090_VMID_ENA_MASK 0x0001 /* VMID_ENA */ -#define WM9090_VMID_ENA_SHIFT 0 /* VMID_ENA */ -#define WM9090_VMID_ENA_WIDTH 1 /* VMID_ENA */ - -/* - * R70 (0x46) - Write Sequencer 0 - */ -#define WM9090_WSEQ_ENA 0x0100 /* WSEQ_ENA */ -#define WM9090_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */ -#define WM9090_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */ -#define WM9090_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM9090_WSEQ_WRITE_INDEX_MASK 0x000F /* WSEQ_WRITE_INDEX - [3:0] */ -#define WM9090_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [3:0] */ -#define WM9090_WSEQ_WRITE_INDEX_WIDTH 4 /* WSEQ_WRITE_INDEX - [3:0] */ - -/* - * R71 (0x47) - Write Sequencer 1 - */ -#define WM9090_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM9090_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM9090_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM9090_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */ -#define WM9090_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */ -#define WM9090_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */ -#define WM9090_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM9090_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM9090_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R72 (0x48) - Write Sequencer 2 - */ -#define WM9090_WSEQ_EOS 0x4000 /* WSEQ_EOS */ -#define WM9090_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */ -#define WM9090_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */ -#define WM9090_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM9090_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */ -#define WM9090_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */ -#define WM9090_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */ -#define WM9090_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM9090_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM9090_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R73 (0x49) - Write Sequencer 3 - */ -#define WM9090_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM9090_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM9090_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM9090_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM9090_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM9090_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM9090_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM9090_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM9090_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM9090_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM9090_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R74 (0x4A) - Write Sequencer 4 - */ -#define WM9090_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM9090_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM9090_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM9090_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R75 (0x4B) - Write Sequencer 5 - */ -#define WM9090_WSEQ_CURRENT_INDEX_MASK 0x003F /* WSEQ_CURRENT_INDEX - [5:0] */ -#define WM9090_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [5:0] */ -#define WM9090_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [5:0] */ - -/* - * R76 (0x4C) - Charge Pump 1 - */ -#define WM9090_CP_ENA 0x8000 /* CP_ENA */ -#define WM9090_CP_ENA_MASK 0x8000 /* CP_ENA */ -#define WM9090_CP_ENA_SHIFT 15 /* CP_ENA */ -#define WM9090_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R84 (0x54) - DC Servo 0 - */ -#define WM9090_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM9090_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM9090_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ -#define WM9090_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ -#define WM9090_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM9090_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM9090_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ -#define WM9090_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ -#define WM9090_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM9090_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM9090_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ -#define WM9090_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ -#define WM9090_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM9090_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM9090_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ -#define WM9090_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ -#define WM9090_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM9090_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM9090_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ -#define WM9090_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ -#define WM9090_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM9090_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM9090_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ -#define WM9090_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ -#define WM9090_DCS_TRIG_DAC_WR_1 0x0008 /* DCS_TRIG_DAC_WR_1 */ -#define WM9090_DCS_TRIG_DAC_WR_1_MASK 0x0008 /* DCS_TRIG_DAC_WR_1 */ -#define WM9090_DCS_TRIG_DAC_WR_1_SHIFT 3 /* DCS_TRIG_DAC_WR_1 */ -#define WM9090_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM9090_DCS_TRIG_DAC_WR_0 0x0004 /* DCS_TRIG_DAC_WR_0 */ -#define WM9090_DCS_TRIG_DAC_WR_0_MASK 0x0004 /* DCS_TRIG_DAC_WR_0 */ -#define WM9090_DCS_TRIG_DAC_WR_0_SHIFT 2 /* DCS_TRIG_DAC_WR_0 */ -#define WM9090_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ -#define WM9090_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM9090_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM9090_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ -#define WM9090_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ -#define WM9090_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM9090_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM9090_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ -#define WM9090_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ - -/* - * R85 (0x55) - DC Servo 1 - */ -#define WM9090_DCS_SERIES_NO_01_MASK 0x0FE0 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM9090_DCS_SERIES_NO_01_SHIFT 5 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM9090_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM9090_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM9090_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM9090_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ - -/* - * R87 (0x57) - DC Servo 3 - */ -#define WM9090_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM9090_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM9090_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM9090_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM9090_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM9090_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ - -/* - * R88 (0x58) - DC Servo Readback 0 - */ -#define WM9090_DCS_CAL_COMPLETE_MASK 0x0300 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM9090_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM9090_DCS_CAL_COMPLETE_WIDTH 2 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM9090_DCS_DAC_WR_COMPLETE_MASK 0x0030 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM9090_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM9090_DCS_DAC_WR_COMPLETE_WIDTH 2 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM9090_DCS_STARTUP_COMPLETE_MASK 0x0003 /* DCS_STARTUP_COMPLETE - [1:0] */ -#define WM9090_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [1:0] */ -#define WM9090_DCS_STARTUP_COMPLETE_WIDTH 2 /* DCS_STARTUP_COMPLETE - [1:0] */ - -/* - * R89 (0x59) - DC Servo Readback 1 - */ -#define WM9090_DCS_DAC_WR_VAL_1_RD_MASK 0x00FF /* DCS_DAC_WR_VAL_1_RD - [7:0] */ -#define WM9090_DCS_DAC_WR_VAL_1_RD_SHIFT 0 /* DCS_DAC_WR_VAL_1_RD - [7:0] */ -#define WM9090_DCS_DAC_WR_VAL_1_RD_WIDTH 8 /* DCS_DAC_WR_VAL_1_RD - [7:0] */ - -/* - * R90 (0x5A) - DC Servo Readback 2 - */ -#define WM9090_DCS_DAC_WR_VAL_0_RD_MASK 0x00FF /* DCS_DAC_WR_VAL_0_RD - [7:0] */ -#define WM9090_DCS_DAC_WR_VAL_0_RD_SHIFT 0 /* DCS_DAC_WR_VAL_0_RD - [7:0] */ -#define WM9090_DCS_DAC_WR_VAL_0_RD_WIDTH 8 /* DCS_DAC_WR_VAL_0_RD - [7:0] */ - -/* - * R96 (0x60) - Analogue HP 0 - */ -#define WM9090_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM9090_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM9090_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */ -#define WM9090_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */ -#define WM9090_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */ -#define WM9090_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */ -#define WM9090_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */ -#define WM9090_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */ -#define WM9090_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */ -#define WM9090_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */ -#define WM9090_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */ -#define WM9090_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */ -#define WM9090_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM9090_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM9090_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */ -#define WM9090_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */ -#define WM9090_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */ -#define WM9090_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */ -#define WM9090_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */ -#define WM9090_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */ -#define WM9090_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */ -#define WM9090_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */ -#define WM9090_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */ -#define WM9090_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */ - -/* - * R98 (0x62) - AGC Control 0 - */ -#define WM9090_AGC_CLIP_ENA 0x8000 /* AGC_CLIP_ENA */ -#define WM9090_AGC_CLIP_ENA_MASK 0x8000 /* AGC_CLIP_ENA */ -#define WM9090_AGC_CLIP_ENA_SHIFT 15 /* AGC_CLIP_ENA */ -#define WM9090_AGC_CLIP_ENA_WIDTH 1 /* AGC_CLIP_ENA */ -#define WM9090_AGC_CLIP_THR_MASK 0x0F00 /* AGC_CLIP_THR - [11:8] */ -#define WM9090_AGC_CLIP_THR_SHIFT 8 /* AGC_CLIP_THR - [11:8] */ -#define WM9090_AGC_CLIP_THR_WIDTH 4 /* AGC_CLIP_THR - [11:8] */ -#define WM9090_AGC_CLIP_ATK_MASK 0x0070 /* AGC_CLIP_ATK - [6:4] */ -#define WM9090_AGC_CLIP_ATK_SHIFT 4 /* AGC_CLIP_ATK - [6:4] */ -#define WM9090_AGC_CLIP_ATK_WIDTH 3 /* AGC_CLIP_ATK - [6:4] */ -#define WM9090_AGC_CLIP_DCY_MASK 0x0007 /* AGC_CLIP_DCY - [2:0] */ -#define WM9090_AGC_CLIP_DCY_SHIFT 0 /* AGC_CLIP_DCY - [2:0] */ -#define WM9090_AGC_CLIP_DCY_WIDTH 3 /* AGC_CLIP_DCY - [2:0] */ - -/* - * R99 (0x63) - AGC Control 1 - */ -#define WM9090_AGC_PWR_ENA 0x8000 /* AGC_PWR_ENA */ -#define WM9090_AGC_PWR_ENA_MASK 0x8000 /* AGC_PWR_ENA */ -#define WM9090_AGC_PWR_ENA_SHIFT 15 /* AGC_PWR_ENA */ -#define WM9090_AGC_PWR_ENA_WIDTH 1 /* AGC_PWR_ENA */ -#define WM9090_AGC_PWR_AVG 0x1000 /* AGC_PWR_AVG */ -#define WM9090_AGC_PWR_AVG_MASK 0x1000 /* AGC_PWR_AVG */ -#define WM9090_AGC_PWR_AVG_SHIFT 12 /* AGC_PWR_AVG */ -#define WM9090_AGC_PWR_AVG_WIDTH 1 /* AGC_PWR_AVG */ -#define WM9090_AGC_PWR_THR_MASK 0x0F00 /* AGC_PWR_THR - [11:8] */ -#define WM9090_AGC_PWR_THR_SHIFT 8 /* AGC_PWR_THR - [11:8] */ -#define WM9090_AGC_PWR_THR_WIDTH 4 /* AGC_PWR_THR - [11:8] */ -#define WM9090_AGC_PWR_ATK_MASK 0x0070 /* AGC_PWR_ATK - [6:4] */ -#define WM9090_AGC_PWR_ATK_SHIFT 4 /* AGC_PWR_ATK - [6:4] */ -#define WM9090_AGC_PWR_ATK_WIDTH 3 /* AGC_PWR_ATK - [6:4] */ -#define WM9090_AGC_PWR_DCY_MASK 0x0007 /* AGC_PWR_DCY - [2:0] */ -#define WM9090_AGC_PWR_DCY_SHIFT 0 /* AGC_PWR_DCY - [2:0] */ -#define WM9090_AGC_PWR_DCY_WIDTH 3 /* AGC_PWR_DCY - [2:0] */ - -/* - * R100 (0x64) - AGC Control 2 - */ -#define WM9090_AGC_RAMP 0x0100 /* AGC_RAMP */ -#define WM9090_AGC_RAMP_MASK 0x0100 /* AGC_RAMP */ -#define WM9090_AGC_RAMP_SHIFT 8 /* AGC_RAMP */ -#define WM9090_AGC_RAMP_WIDTH 1 /* AGC_RAMP */ -#define WM9090_AGC_MINGAIN_MASK 0x003F /* AGC_MINGAIN - [5:0] */ -#define WM9090_AGC_MINGAIN_SHIFT 0 /* AGC_MINGAIN - [5:0] */ -#define WM9090_AGC_MINGAIN_WIDTH 6 /* AGC_MINGAIN - [5:0] */ - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9705.c b/ANDROID_3.4.5/sound/soc/codecs/wm9705.c deleted file mode 100644 index cacc6a86..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9705.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * wm9705.c -- ALSA Soc WM9705 codec support - * - * Copyright 2008 Ian Molton - * - * 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; Version 2 of the License only. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm9705.h" - -/* - * WM9705 register cache - */ -static const u16 wm9705_reg[] = { - 0x6150, 0x8000, 0x8000, 0x8000, /* 0x0 */ - 0x0000, 0x8000, 0x8008, 0x8008, /* 0x8 */ - 0x8808, 0x8808, 0x8808, 0x8808, /* 0x10 */ - 0x8808, 0x0000, 0x8000, 0x0000, /* 0x18 */ - 0x0000, 0x0000, 0x0000, 0x000f, /* 0x20 */ - 0x0605, 0x0000, 0xbb80, 0x0000, /* 0x28 */ - 0x0000, 0xbb80, 0x0000, 0x0000, /* 0x30 */ - 0x0000, 0x2000, 0x0000, 0x0000, /* 0x38 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 0x40 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 0x48 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 0x50 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 0x58 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 0x60 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 0x68 */ - 0x0000, 0x0808, 0x0000, 0x0006, /* 0x70 */ - 0x0000, 0x0000, 0x574d, 0x4c05, /* 0x78 */ -}; - -static const struct snd_kcontrol_new wm9705_snd_ac97_controls[] = { - SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1), - SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1), - SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1), - SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1), - SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1), - SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1), - SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1), - SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), - SOC_SINGLE("PCBeep Playback Volume", AC97_PC_BEEP, 1, 15, 1), - SOC_SINGLE("Phone Playback Volume", AC97_PHONE, 0, 31, 1), - SOC_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1), - SOC_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1), - SOC_SINGLE("Mic Playback Volume", AC97_MIC, 0, 31, 1), - SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 6, 1, 0), - SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0), - SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), -}; - -static const char *wm9705_mic[] = {"Mic 1", "Mic 2"}; -static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC", - "Line", "Stereo Mix", "Mono Mix", "Phone"}; - -static const struct soc_enum wm9705_enum_mic = - SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic); -static const struct soc_enum wm9705_enum_rec_l = - SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel); -static const struct soc_enum wm9705_enum_rec_r = - SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel); - -/* Headphone Mixer */ -static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = { - SOC_DAPM_SINGLE("PCBeep Playback Switch", AC97_PC_BEEP, 15, 1, 1), - SOC_DAPM_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1), - SOC_DAPM_SINGLE("Mic Playback Switch", AC97_MIC, 15, 1, 1), - SOC_DAPM_SINGLE("Phone Playback Switch", AC97_PHONE, 15, 1, 1), - SOC_DAPM_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1), -}; - -/* Mic source */ -static const struct snd_kcontrol_new wm9705_mic_src_controls = - SOC_DAPM_ENUM("Route", wm9705_enum_mic); - -/* Capture source */ -static const struct snd_kcontrol_new wm9705_capture_selectl_controls = - SOC_DAPM_ENUM("Route", wm9705_enum_rec_l); -static const struct snd_kcontrol_new wm9705_capture_selectr_controls = - SOC_DAPM_ENUM("Route", wm9705_enum_rec_r); - -/* DAPM widgets */ -static const struct snd_soc_dapm_widget wm9705_dapm_widgets[] = { - SND_SOC_DAPM_MUX("Mic Source", SND_SOC_NOPM, 0, 0, - &wm9705_mic_src_controls), - SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0, - &wm9705_capture_selectl_controls), - SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0, - &wm9705_capture_selectr_controls), - SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", - SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_MIXER_NAMED_CTL("HP Mixer", SND_SOC_NOPM, 0, 0, - &wm9705_hp_mixer_controls[0], - ARRAY_SIZE(wm9705_hp_mixer_controls)), - SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_PGA("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Speaker PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Line PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Line out PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mono PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Phone PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mic PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("PCBEEP PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("CD PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("ADC PGA", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_OUTPUT("HPOUTL"), - SND_SOC_DAPM_OUTPUT("HPOUTR"), - SND_SOC_DAPM_OUTPUT("LOUT"), - SND_SOC_DAPM_OUTPUT("ROUT"), - SND_SOC_DAPM_OUTPUT("MONOOUT"), - SND_SOC_DAPM_INPUT("PHONE"), - SND_SOC_DAPM_INPUT("LINEINL"), - SND_SOC_DAPM_INPUT("LINEINR"), - SND_SOC_DAPM_INPUT("CDINL"), - SND_SOC_DAPM_INPUT("CDINR"), - SND_SOC_DAPM_INPUT("PCBEEP"), - SND_SOC_DAPM_INPUT("MIC1"), - SND_SOC_DAPM_INPUT("MIC2"), -}; - -/* Audio map - * WM9705 has no switches to disable the route from the inputs to the HP mixer - * so in order to prevent active inputs from forcing the audio outputs to be - * constantly enabled, we use the mutes on those inputs to simulate such - * controls. - */ -static const struct snd_soc_dapm_route wm9705_audio_map[] = { - /* HP mixer */ - {"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"}, - {"HP Mixer", "CD Playback Switch", "CD PGA"}, - {"HP Mixer", "Mic Playback Switch", "Mic PGA"}, - {"HP Mixer", "Phone Playback Switch", "Phone PGA"}, - {"HP Mixer", "Line Playback Switch", "Line PGA"}, - {"HP Mixer", NULL, "Left DAC"}, - {"HP Mixer", NULL, "Right DAC"}, - - /* mono mixer */ - {"Mono Mixer", NULL, "HP Mixer"}, - - /* outputs */ - {"Headphone PGA", NULL, "HP Mixer"}, - {"HPOUTL", NULL, "Headphone PGA"}, - {"HPOUTR", NULL, "Headphone PGA"}, - {"Line out PGA", NULL, "HP Mixer"}, - {"LOUT", NULL, "Line out PGA"}, - {"ROUT", NULL, "Line out PGA"}, - {"Mono PGA", NULL, "Mono Mixer"}, - {"MONOOUT", NULL, "Mono PGA"}, - - /* inputs */ - {"CD PGA", NULL, "CDINL"}, - {"CD PGA", NULL, "CDINR"}, - {"Line PGA", NULL, "LINEINL"}, - {"Line PGA", NULL, "LINEINR"}, - {"Phone PGA", NULL, "PHONE"}, - {"Mic Source", "Mic 1", "MIC1"}, - {"Mic Source", "Mic 2", "MIC2"}, - {"Mic PGA", NULL, "Mic Source"}, - {"PCBEEP PGA", NULL, "PCBEEP"}, - - /* Left capture selector */ - {"Left Capture Source", "Mic", "Mic Source"}, - {"Left Capture Source", "CD", "CDINL"}, - {"Left Capture Source", "Line", "LINEINL"}, - {"Left Capture Source", "Stereo Mix", "HP Mixer"}, - {"Left Capture Source", "Mono Mix", "HP Mixer"}, - {"Left Capture Source", "Phone", "PHONE"}, - - /* Right capture source */ - {"Right Capture Source", "Mic", "Mic Source"}, - {"Right Capture Source", "CD", "CDINR"}, - {"Right Capture Source", "Line", "LINEINR"}, - {"Right Capture Source", "Stereo Mix", "HP Mixer"}, - {"Right Capture Source", "Mono Mix", "HP Mixer"}, - {"Right Capture Source", "Phone", "PHONE"}, - - {"ADC PGA", NULL, "Left Capture Source"}, - {"ADC PGA", NULL, "Right Capture Source"}, - - /* ADC's */ - {"Left ADC", NULL, "ADC PGA"}, - {"Right ADC", NULL, "ADC PGA"}, -}; - -/* We use a register cache to enhance read performance. */ -static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) -{ - u16 *cache = codec->reg_cache; - - switch (reg) { - case AC97_RESET: - case AC97_VENDOR_ID1: - case AC97_VENDOR_ID2: - return soc_ac97_ops.read(codec->ac97, reg); - default: - reg = reg >> 1; - - if (reg >= (ARRAY_SIZE(wm9705_reg))) - return -EIO; - - return cache[reg]; - } -} - -static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int val) -{ - u16 *cache = codec->reg_cache; - - soc_ac97_ops.write(codec->ac97, reg, val); - reg = reg >> 1; - if (reg < (ARRAY_SIZE(wm9705_reg))) - cache[reg] = val; - - return 0; -} - -static int ac97_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - int reg; - u16 vra; - - vra = ac97_read(codec, AC97_EXTENDED_STATUS); - ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - reg = AC97_PCM_FRONT_DAC_RATE; - else - reg = AC97_PCM_LR_ADC_RATE; - - return ac97_write(codec, reg, runtime->rate); -} - -#define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000) - -static const struct snd_soc_dai_ops wm9705_dai_ops = { - .prepare = ac97_prepare, -}; - -static struct snd_soc_dai_driver wm9705_dai[] = { - { - .name = "wm9705-hifi", - .ac97_control = 1, - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM9705_AC97_RATES, - .formats = SND_SOC_STD_AC97_FMTS, - }, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM9705_AC97_RATES, - .formats = SND_SOC_STD_AC97_FMTS, - }, - .ops = &wm9705_dai_ops, - }, - { - .name = "wm9705-aux", - .playback = { - .stream_name = "Aux Playback", - .channels_min = 1, - .channels_max = 1, - .rates = WM9705_AC97_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - } -}; - -static int wm9705_reset(struct snd_soc_codec *codec) -{ - if (soc_ac97_ops.reset) { - soc_ac97_ops.reset(codec->ac97); - if (ac97_read(codec, 0) == wm9705_reg[0]) - return 0; /* Success */ - } - - return -EIO; -} - -#ifdef CONFIG_PM -static int wm9705_soc_suspend(struct snd_soc_codec *codec) -{ - soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); - - return 0; -} - -static int wm9705_soc_resume(struct snd_soc_codec *codec) -{ - int i, ret; - u16 *cache = codec->reg_cache; - - ret = wm9705_reset(codec); - if (ret < 0) { - printk(KERN_ERR "could not reset AC97 codec\n"); - return ret; - } - - for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { - soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); - } - - return 0; -} -#else -#define wm9705_soc_suspend NULL -#define wm9705_soc_resume NULL -#endif - -static int wm9705_soc_probe(struct snd_soc_codec *codec) -{ - int ret = 0; - - printk(KERN_INFO "WM9705 SoC Audio Codec\n"); - - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); - if (ret < 0) { - printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); - return ret; - } - - ret = wm9705_reset(codec); - if (ret) - goto reset_err; - - snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls, - ARRAY_SIZE(wm9705_snd_ac97_controls)); - - return 0; - -reset_err: - snd_soc_free_ac97_codec(codec); - return ret; -} - -static int wm9705_soc_remove(struct snd_soc_codec *codec) -{ - snd_soc_free_ac97_codec(codec); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { - .probe = wm9705_soc_probe, - .remove = wm9705_soc_remove, - .suspend = wm9705_soc_suspend, - .resume = wm9705_soc_resume, - .read = ac97_read, - .write = ac97_write, - .reg_cache_size = ARRAY_SIZE(wm9705_reg), - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, - .reg_cache_default = wm9705_reg, - .dapm_widgets = wm9705_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), - .dapm_routes = wm9705_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9705_audio_map), -}; - -static __devinit int wm9705_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai)); -} - -static int __devexit wm9705_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver wm9705_codec_driver = { - .driver = { - .name = "wm9705-codec", - .owner = THIS_MODULE, - }, - - .probe = wm9705_probe, - .remove = __devexit_p(wm9705_remove), -}; - -module_platform_driver(wm9705_codec_driver); - -MODULE_DESCRIPTION("ASoC WM9705 driver"); -MODULE_AUTHOR("Ian Molton"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9705.h b/ANDROID_3.4.5/sound/soc/codecs/wm9705.h deleted file mode 100644 index 23ea9ce4..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9705.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * wm9705.h -- WM9705 Soc Audio driver - */ - -#ifndef _WM9705_H -#define _WM9705_H - -#define WM9705_DAI_AC97_HIFI 0 -#define WM9705_DAI_AC97_AUX 1 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9712.c b/ANDROID_3.4.5/sound/soc/codecs/wm9712.c deleted file mode 100644 index b342ae50..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9712.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * wm9712.c -- ALSA Soc WM9712 codec support - * - * Copyright 2006 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "wm9712.h" - -static unsigned int ac97_read(struct snd_soc_codec *codec, - unsigned int reg); -static int ac97_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int val); - -/* - * WM9712 register cache - */ -static const u16 wm9712_reg[] = { - 0x6174, 0x8000, 0x8000, 0x8000, /* 6 */ - 0x0f0f, 0xaaa0, 0xc008, 0x6808, /* e */ - 0xe808, 0xaaa0, 0xad00, 0x8000, /* 16 */ - 0xe808, 0x3000, 0x8000, 0x0000, /* 1e */ - 0x0000, 0x0000, 0x0000, 0x000f, /* 26 */ - 0x0405, 0x0410, 0xbb80, 0xbb80, /* 2e */ - 0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */ - 0x0000, 0x2000, 0x0000, 0x0000, /* 3e */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 46 */ - 0x0000, 0x0000, 0xf83e, 0xffff, /* 4e */ - 0x0000, 0x0000, 0x0000, 0xf83e, /* 56 */ - 0x0008, 0x0000, 0x0000, 0x0000, /* 5e */ - 0xb032, 0x3e00, 0x0000, 0x0000, /* 66 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ - 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ - 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */ - 0x0000, 0x0000 /* virtual hp mixers */ -}; - -/* virtual HP mixers regs */ -#define HPL_MIXER 0x80 -#define HPR_MIXER 0x82 - -static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"}; -static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"}; -static const char *wm9712_out3_src[] = {"Left", "VREF", "Left + Right", - "Mono"}; -static const char *wm9712_spk_src[] = {"Speaker Mix", "Headphone Mix"}; -static const char *wm9712_rec_adc[] = {"Stereo", "Left", "Right", "Mute"}; -static const char *wm9712_base[] = {"Linear Control", "Adaptive Boost"}; -static const char *wm9712_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"}; -static const char *wm9712_mic[] = {"Mic 1", "Differential", "Mic 2", - "Stereo"}; -static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer", - "Line", "Headphone Mixer", "Phone Mixer", "Phone"}; -static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"}; -static const char *wm9712_diff_sel[] = {"Mic", "Line"}; - -static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 2000, 0); - -static const struct soc_enum wm9712_enum[] = { -SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select), -SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux), -SOC_ENUM_SINGLE(AC97_AUX, 9, 4, wm9712_out3_src), -SOC_ENUM_SINGLE(AC97_AUX, 8, 2, wm9712_spk_src), -SOC_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9712_rec_adc), -SOC_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9712_base), -SOC_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9712_rec_gain), -SOC_ENUM_SINGLE(AC97_MIC, 5, 4, wm9712_mic), -SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9712_rec_sel), -SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9712_rec_sel), -SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9712_ng_type), -SOC_ENUM_SINGLE(0x5c, 8, 2, wm9712_diff_sel), -}; - -static const struct snd_kcontrol_new wm9712_snd_ac97_controls[] = { -SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1), -SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1), -SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1), -SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1), -SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1), - -SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0), -SOC_SINGLE("Speaker Playback Invert Switch", AC97_MASTER, 6, 1, 0), -SOC_SINGLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 7, 1, 0), -SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_MONO, 7, 1, 0), -SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1), -SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), - -SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0), -SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0), -SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0), -SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0), -SOC_ENUM("ALC Function", wm9712_enum[0]), -SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0), -SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1), -SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0), -SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0), -SOC_ENUM("ALC NG Type", wm9712_enum[10]), -SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1), - -SOC_SINGLE("Mic Headphone Volume", AC97_VIDEO, 12, 7, 1), -SOC_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1), - -SOC_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1), -SOC_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1), -SOC_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1), - -SOC_SINGLE("PCBeep Bypass Headphone Volume", AC97_PC_BEEP, 12, 7, 1), -SOC_SINGLE("PCBeep Bypass Speaker Volume", AC97_PC_BEEP, 8, 7, 1), -SOC_SINGLE("PCBeep Bypass Phone Volume", AC97_PC_BEEP, 4, 7, 1), - -SOC_SINGLE("Aux Playback Headphone Volume", AC97_CD, 12, 7, 1), -SOC_SINGLE("Aux Playback Speaker Volume", AC97_CD, 8, 7, 1), -SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1), - -SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), -SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), - -SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0), -SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1), - -SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), -SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), -SOC_SINGLE("3D Playback Volume", AC97_3D_CONTROL, 0, 15, 0), - -SOC_ENUM("Bass Control", wm9712_enum[5]), -SOC_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1), -SOC_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1), -SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), -SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), -SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), - -SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), -SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), -SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), -SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), - -SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv), -SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv), -SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv), -}; - -/* We have to create a fake left and right HP mixers because - * the codec only has a single control that is shared by both channels. - * This makes it impossible to determine the audio path. - */ -static int mixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - u16 l, r, beep, line, phone, mic, pcm, aux; - - l = ac97_read(w->codec, HPL_MIXER); - r = ac97_read(w->codec, HPR_MIXER); - beep = ac97_read(w->codec, AC97_PC_BEEP); - mic = ac97_read(w->codec, AC97_VIDEO); - phone = ac97_read(w->codec, AC97_PHONE); - line = ac97_read(w->codec, AC97_LINE); - pcm = ac97_read(w->codec, AC97_PCM); - aux = ac97_read(w->codec, AC97_CD); - - if (l & 0x1 || r & 0x1) - ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff); - else - ac97_write(w->codec, AC97_VIDEO, mic | 0x8000); - - if (l & 0x2 || r & 0x2) - ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); - else - ac97_write(w->codec, AC97_PCM, pcm | 0x8000); - - if (l & 0x4 || r & 0x4) - ac97_write(w->codec, AC97_LINE, line & 0x7fff); - else - ac97_write(w->codec, AC97_LINE, line | 0x8000); - - if (l & 0x8 || r & 0x8) - ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); - else - ac97_write(w->codec, AC97_PHONE, phone | 0x8000); - - if (l & 0x10 || r & 0x10) - ac97_write(w->codec, AC97_CD, aux & 0x7fff); - else - ac97_write(w->codec, AC97_CD, aux | 0x8000); - - if (l & 0x20 || r & 0x20) - ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); - else - ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); - - return 0; -} - -/* Left Headphone Mixers */ -static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = { - SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0), - SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0), - SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0), - SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0), - SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0), - SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0), -}; - -/* Right Headphone Mixers */ -static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = { - SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0), - SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0), - SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0), - SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0), - SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0), - SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0), -}; - -/* Speaker Mixer */ -static const struct snd_kcontrol_new wm9712_speaker_mixer_controls[] = { - SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 11, 1, 1), - SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 11, 1, 1), - SOC_DAPM_SINGLE("Phone Bypass Switch", AC97_PHONE, 14, 1, 1), - SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 14, 1, 1), - SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 14, 1, 1), -}; - -/* Phone Mixer */ -static const struct snd_kcontrol_new wm9712_phone_mixer_controls[] = { - SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 7, 1, 1), - SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 7, 1, 1), - SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 13, 1, 1), - SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 13, 1, 1), - SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_MIC, 14, 1, 1), - SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_MIC, 13, 1, 1), -}; - -/* ALC headphone mux */ -static const struct snd_kcontrol_new wm9712_alc_mux_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[1]); - -/* out 3 mux */ -static const struct snd_kcontrol_new wm9712_out3_mux_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[2]); - -/* spk mux */ -static const struct snd_kcontrol_new wm9712_spk_mux_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[3]); - -/* Capture to Phone mux */ -static const struct snd_kcontrol_new wm9712_capture_phone_mux_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[4]); - -/* Capture left select */ -static const struct snd_kcontrol_new wm9712_capture_selectl_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[8]); - -/* Capture right select */ -static const struct snd_kcontrol_new wm9712_capture_selectr_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[9]); - -/* Mic select */ -static const struct snd_kcontrol_new wm9712_mic_src_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[7]); - -/* diff select */ -static const struct snd_kcontrol_new wm9712_diff_sel_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[11]); - -static const struct snd_soc_dapm_widget wm9712_dapm_widgets[] = { -SND_SOC_DAPM_MUX("ALC Sidetone Mux", SND_SOC_NOPM, 0, 0, - &wm9712_alc_mux_controls), -SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, - &wm9712_out3_mux_controls), -SND_SOC_DAPM_MUX("Speaker Mux", SND_SOC_NOPM, 0, 0, - &wm9712_spk_mux_controls), -SND_SOC_DAPM_MUX("Capture Phone Mux", SND_SOC_NOPM, 0, 0, - &wm9712_capture_phone_mux_controls), -SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0, - &wm9712_capture_selectl_controls), -SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0, - &wm9712_capture_selectr_controls), -SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0, - &wm9712_mic_src_controls), -SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, - &wm9712_diff_sel_controls), -SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1, - &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls), - mixer_event, SND_SOC_DAPM_POST_REG), -SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1, - &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls), - mixer_event, SND_SOC_DAPM_POST_REG), -SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1, - &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)), -SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1, - &wm9712_speaker_mixer_controls[0], - ARRAY_SIZE(wm9712_speaker_mixer_controls)), -SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_INT_PAGING, 14, 1), -SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_INT_PAGING, 13, 1), -SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_INT_PAGING, 12, 1), -SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_INT_PAGING, 11, 1), -SND_SOC_DAPM_PGA("Headphone PGA", AC97_INT_PAGING, 4, 1, NULL, 0), -SND_SOC_DAPM_PGA("Speaker PGA", AC97_INT_PAGING, 3, 1, NULL, 0), -SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0), -SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0), -SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0), -SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0), -SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1), -SND_SOC_DAPM_OUTPUT("MONOOUT"), -SND_SOC_DAPM_OUTPUT("HPOUTL"), -SND_SOC_DAPM_OUTPUT("HPOUTR"), -SND_SOC_DAPM_OUTPUT("LOUT2"), -SND_SOC_DAPM_OUTPUT("ROUT2"), -SND_SOC_DAPM_OUTPUT("OUT3"), -SND_SOC_DAPM_INPUT("LINEINL"), -SND_SOC_DAPM_INPUT("LINEINR"), -SND_SOC_DAPM_INPUT("PHONE"), -SND_SOC_DAPM_INPUT("PCBEEP"), -SND_SOC_DAPM_INPUT("MIC1"), -SND_SOC_DAPM_INPUT("MIC2"), -}; - -static const struct snd_soc_dapm_route wm9712_audio_map[] = { - /* virtual mixer - mixes left & right channels for spk and mono */ - {"AC97 Mixer", NULL, "Left DAC"}, - {"AC97 Mixer", NULL, "Right DAC"}, - - /* Left HP mixer */ - {"Left HP Mixer", "PCBeep Bypass Switch", "PCBEEP"}, - {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"}, - {"Left HP Mixer", "Phone Bypass Switch", "Phone PGA"}, - {"Left HP Mixer", "Line Bypass Switch", "Line PGA"}, - {"Left HP Mixer", "PCM Playback Switch", "Left DAC"}, - {"Left HP Mixer", "Mic Sidetone Switch", "Mic PGA"}, - {"Left HP Mixer", NULL, "ALC Sidetone Mux"}, - - /* Right HP mixer */ - {"Right HP Mixer", "PCBeep Bypass Switch", "PCBEEP"}, - {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"}, - {"Right HP Mixer", "Phone Bypass Switch", "Phone PGA"}, - {"Right HP Mixer", "Line Bypass Switch", "Line PGA"}, - {"Right HP Mixer", "PCM Playback Switch", "Right DAC"}, - {"Right HP Mixer", "Mic Sidetone Switch", "Mic PGA"}, - {"Right HP Mixer", NULL, "ALC Sidetone Mux"}, - - /* speaker mixer */ - {"Speaker Mixer", "PCBeep Bypass Switch", "PCBEEP"}, - {"Speaker Mixer", "Line Bypass Switch", "Line PGA"}, - {"Speaker Mixer", "PCM Playback Switch", "AC97 Mixer"}, - {"Speaker Mixer", "Phone Bypass Switch", "Phone PGA"}, - {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"}, - - /* Phone mixer */ - {"Phone Mixer", "PCBeep Bypass Switch", "PCBEEP"}, - {"Phone Mixer", "Line Bypass Switch", "Line PGA"}, - {"Phone Mixer", "Aux Playback Switch", "Aux DAC"}, - {"Phone Mixer", "PCM Playback Switch", "AC97 Mixer"}, - {"Phone Mixer", "Mic 1 Sidetone Switch", "Mic PGA"}, - {"Phone Mixer", "Mic 2 Sidetone Switch", "Mic PGA"}, - - /* inputs */ - {"Line PGA", NULL, "LINEINL"}, - {"Line PGA", NULL, "LINEINR"}, - {"Phone PGA", NULL, "PHONE"}, - {"Mic PGA", NULL, "MIC1"}, - {"Mic PGA", NULL, "MIC2"}, - - /* left capture selector */ - {"Left Capture Select", "Mic", "MIC1"}, - {"Left Capture Select", "Speaker Mixer", "Speaker Mixer"}, - {"Left Capture Select", "Line", "LINEINL"}, - {"Left Capture Select", "Headphone Mixer", "Left HP Mixer"}, - {"Left Capture Select", "Phone Mixer", "Phone Mixer"}, - {"Left Capture Select", "Phone", "PHONE"}, - - /* right capture selector */ - {"Right Capture Select", "Mic", "MIC2"}, - {"Right Capture Select", "Speaker Mixer", "Speaker Mixer"}, - {"Right Capture Select", "Line", "LINEINR"}, - {"Right Capture Select", "Headphone Mixer", "Right HP Mixer"}, - {"Right Capture Select", "Phone Mixer", "Phone Mixer"}, - {"Right Capture Select", "Phone", "PHONE"}, - - /* ALC Sidetone */ - {"ALC Sidetone Mux", "Stereo", "Left Capture Select"}, - {"ALC Sidetone Mux", "Stereo", "Right Capture Select"}, - {"ALC Sidetone Mux", "Left", "Left Capture Select"}, - {"ALC Sidetone Mux", "Right", "Right Capture Select"}, - - /* ADC's */ - {"Left ADC", NULL, "Left Capture Select"}, - {"Right ADC", NULL, "Right Capture Select"}, - - /* outputs */ - {"MONOOUT", NULL, "Phone Mixer"}, - {"HPOUTL", NULL, "Headphone PGA"}, - {"Headphone PGA", NULL, "Left HP Mixer"}, - {"HPOUTR", NULL, "Headphone PGA"}, - {"Headphone PGA", NULL, "Right HP Mixer"}, - - /* mono mixer */ - {"Mono Mixer", NULL, "Left HP Mixer"}, - {"Mono Mixer", NULL, "Right HP Mixer"}, - - /* Out3 Mux */ - {"Out3 Mux", "Left", "Left HP Mixer"}, - {"Out3 Mux", "Mono", "Phone Mixer"}, - {"Out3 Mux", "Left + Right", "Mono Mixer"}, - {"Out 3 PGA", NULL, "Out3 Mux"}, - {"OUT3", NULL, "Out 3 PGA"}, - - /* speaker Mux */ - {"Speaker Mux", "Speaker Mix", "Speaker Mixer"}, - {"Speaker Mux", "Headphone Mix", "Mono Mixer"}, - {"Speaker PGA", NULL, "Speaker Mux"}, - {"LOUT2", NULL, "Speaker PGA"}, - {"ROUT2", NULL, "Speaker PGA"}, -}; - -static unsigned int ac97_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - - if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || - reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || - reg == AC97_REC_GAIN) - return soc_ac97_ops.read(codec->ac97, reg); - else { - reg = reg >> 1; - - if (reg >= (ARRAY_SIZE(wm9712_reg))) - return -EIO; - - return cache[reg]; - } -} - -static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int val) -{ - u16 *cache = codec->reg_cache; - - if (reg < 0x7c) - soc_ac97_ops.write(codec->ac97, reg, val); - reg = reg >> 1; - if (reg < (ARRAY_SIZE(wm9712_reg))) - cache[reg] = val; - - return 0; -} - -static int ac97_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec =rtd->codec; - int reg; - u16 vra; - - vra = ac97_read(codec, AC97_EXTENDED_STATUS); - ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - reg = AC97_PCM_FRONT_DAC_RATE; - else - reg = AC97_PCM_LR_ADC_RATE; - - return ac97_write(codec, reg, runtime->rate); -} - -static int ac97_aux_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 vra, xsle; - - vra = ac97_read(codec, AC97_EXTENDED_STATUS); - ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); - xsle = ac97_read(codec, AC97_PCI_SID); - ac97_write(codec, AC97_PCI_SID, xsle | 0x8000); - - if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) - return -ENODEV; - - return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate); -} - -#define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000) - -static const struct snd_soc_dai_ops wm9712_dai_ops_hifi = { - .prepare = ac97_prepare, -}; - -static const struct snd_soc_dai_ops wm9712_dai_ops_aux = { - .prepare = ac97_aux_prepare, -}; - -static struct snd_soc_dai_driver wm9712_dai[] = { -{ - .name = "wm9712-hifi", - .ac97_control = 1, - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM9712_AC97_RATES, - .formats = SND_SOC_STD_AC97_FMTS,}, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM9712_AC97_RATES, - .formats = SND_SOC_STD_AC97_FMTS,}, - .ops = &wm9712_dai_ops_hifi, -}, -{ - .name = "wm9712-aux", - .playback = { - .stream_name = "Aux Playback", - .channels_min = 1, - .channels_max = 1, - .rates = WM9712_AC97_RATES, - .formats = SND_SOC_STD_AC97_FMTS,}, - .ops = &wm9712_dai_ops_aux, -} -}; - -static int wm9712_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - ac97_write(codec, AC97_POWERDOWN, 0x0000); - break; - case SND_SOC_BIAS_OFF: - /* disable everything including AC link */ - ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff); - ac97_write(codec, AC97_POWERDOWN, 0xffff); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) -{ - if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset(codec->ac97); - if (ac97_read(codec, 0) == wm9712_reg[0]) - return 1; - } - - soc_ac97_ops.reset(codec->ac97); - if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset(codec->ac97); - if (ac97_read(codec, 0) != wm9712_reg[0]) - goto err; - return 0; - -err: - printk(KERN_ERR "WM9712 AC97 reset failed\n"); - return -EIO; -} - -static int wm9712_soc_suspend(struct snd_soc_codec *codec) -{ - wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm9712_soc_resume(struct snd_soc_codec *codec) -{ - int i, ret; - u16 *cache = codec->reg_cache; - - ret = wm9712_reset(codec, 1); - if (ret < 0) { - printk(KERN_ERR "could not reset AC97 codec\n"); - return ret; - } - - wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - if (ret == 0) { - /* Sync reg_cache with the hardware after cold reset */ - for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i += 2) { - if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || - (i > 0x58 && i != 0x5c)) - continue; - soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); - } - } - - return ret; -} - -static int wm9712_soc_probe(struct snd_soc_codec *codec) -{ - int ret = 0; - - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); - if (ret < 0) { - printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); - return ret; - } - - ret = wm9712_reset(codec, 0); - if (ret < 0) { - printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); - goto reset_err; - } - - /* set alc mux to none */ - ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); - - wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls, - ARRAY_SIZE(wm9712_snd_ac97_controls)); - - return 0; - -reset_err: - snd_soc_free_ac97_codec(codec); - return ret; -} - -static int wm9712_soc_remove(struct snd_soc_codec *codec) -{ - snd_soc_free_ac97_codec(codec); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { - .probe = wm9712_soc_probe, - .remove = wm9712_soc_remove, - .suspend = wm9712_soc_suspend, - .resume = wm9712_soc_resume, - .read = ac97_read, - .write = ac97_write, - .set_bias_level = wm9712_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm9712_reg), - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, - .reg_cache_default = wm9712_reg, - .dapm_widgets = wm9712_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), - .dapm_routes = wm9712_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9712_audio_map), -}; - -static __devinit int wm9712_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); -} - -static int __devexit wm9712_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver wm9712_codec_driver = { - .driver = { - .name = "wm9712-codec", - .owner = THIS_MODULE, - }, - - .probe = wm9712_probe, - .remove = __devexit_p(wm9712_remove), -}; - -module_platform_driver(wm9712_codec_driver); - -MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9712.h b/ANDROID_3.4.5/sound/soc/codecs/wm9712.h deleted file mode 100644 index fb69c3aa..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9712.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * wm9712.h -- WM9712 Soc Audio driver - */ - -#ifndef _WM9712_H -#define _WM9712_H - -#define WM9712_DAI_AC97_HIFI 0 -#define WM9712_DAI_AC97_AUX 1 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9713.c b/ANDROID_3.4.5/sound/soc/codecs/wm9713.c deleted file mode 100644 index 2d22cc70..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9713.c +++ /dev/null @@ -1,1283 +0,0 @@ -/* - * wm9713.c -- ALSA Soc WM9713 codec support - * - * Copyright 2006 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * - * 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. - * - * Features:- - * - * o Support for AC97 Codec, Voice DAC and Aux DAC - * o Support for DAPM - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm9713.h" - -struct wm9713_priv { - u32 pll_in; /* PLL input frequency */ -}; - -static unsigned int ac97_read(struct snd_soc_codec *codec, - unsigned int reg); -static int ac97_write(struct snd_soc_codec *codec, - unsigned int reg, unsigned int val); - -/* - * WM9713 register cache - * Reg 0x3c bit 15 is used by touch driver. - */ -static const u16 wm9713_reg[] = { - 0x6174, 0x8080, 0x8080, 0x8080, - 0xc880, 0xe808, 0xe808, 0x0808, - 0x00da, 0x8000, 0xd600, 0xaaa0, - 0xaaa0, 0xaaa0, 0x0000, 0x0000, - 0x0f0f, 0x0040, 0x0000, 0x7f00, - 0x0405, 0x0410, 0xbb80, 0xbb80, - 0x0000, 0xbb80, 0x0000, 0x4523, - 0x0000, 0x2000, 0x7eff, 0xffff, - 0x0000, 0x0000, 0x0080, 0x0000, - 0x0000, 0x0000, 0xfffe, 0xffff, - 0x0000, 0x0000, 0x0000, 0xfffe, - 0x4000, 0x0000, 0x0000, 0x0000, - 0xb032, 0x3e00, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0006, - 0x0001, 0x0000, 0x574d, 0x4c13, - 0x0000, 0x0000, 0x0000 -}; - -/* virtual HP mixers regs */ -#define HPL_MIXER 0x80 -#define HPR_MIXER 0x82 -#define MICB_MUX 0x82 - -static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; -static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; -static const char *wm9713_rec_src[] = - {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone", "Speaker", - "Mono Out", "Zh"}; -static const char *wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"}; -static const char *wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"}; -static const char *wm9713_mono_pga[] = {"Vmid", "Zh", "Mono", "Inv", - "Mono Vmid", "Inv Vmid"}; -static const char *wm9713_spk_pga[] = - {"Vmid", "Zh", "Headphone", "Speaker", "Inv", "Headphone Vmid", - "Speaker Vmid", "Inv Vmid"}; -static const char *wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone", - "Headphone Vmid"}; -static const char *wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "Inv 1 Vmid"}; -static const char *wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "Inv 2 Vmid"}; -static const char *wm9713_dac_inv[] = - {"Off", "Mono", "Speaker", "Left Headphone", "Right Headphone", - "Headphone Mono", "NC", "Vmid"}; -static const char *wm9713_bass[] = {"Linear Control", "Adaptive Boost"}; -static const char *wm9713_ng_type[] = {"Constant Gain", "Mute"}; -static const char *wm9713_mic_select[] = {"Mic 1", "Mic 2 A", "Mic 2 B"}; -static const char *wm9713_micb_select[] = {"MPB", "MPA"}; - -static const struct soc_enum wm9713_enum[] = { -SOC_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer), /* record mic mixer 0 */ -SOC_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux), /* record mux hp 1 */ -SOC_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux), /* record mux mono 2 */ -SOC_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src), /* record mux left 3 */ -SOC_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src), /* record mux right 4*/ -SOC_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain), /* record step size 5 */ -SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select), /* alc source select 6*/ -SOC_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga), /* mono input select 7 */ -SOC_ENUM_SINGLE(AC97_REC_GAIN, 11, 8, wm9713_spk_pga), /* speaker left input select 8 */ -SOC_ENUM_SINGLE(AC97_REC_GAIN, 8, 8, wm9713_spk_pga), /* speaker right input select 9 */ -SOC_ENUM_SINGLE(AC97_REC_GAIN, 6, 3, wm9713_hp_pga), /* headphone left input 10 */ -SOC_ENUM_SINGLE(AC97_REC_GAIN, 4, 3, wm9713_hp_pga), /* headphone right input 11 */ -SOC_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga), /* out 3 source 12 */ -SOC_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga), /* out 4 source 13 */ -SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 13, 8, wm9713_dac_inv), /* dac invert 1 14 */ -SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */ -SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */ -SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */ -SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */ -SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */ -}; - -static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(misc_tlv, -1500, 300, 0); -static unsigned int mic_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), - 3, 3, TLV_DB_SCALE_ITEM(3000, 0, 0), -}; - -static const struct snd_kcontrol_new wm9713_snd_ac97_controls[] = { -SOC_DOUBLE_TLV("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1, out_tlv), -SOC_DOUBLE("Speaker Playback Switch", AC97_MASTER, 15, 7, 1, 1), -SOC_DOUBLE_TLV("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1, - out_tlv), -SOC_DOUBLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 7, 1, 1), -SOC_DOUBLE_TLV("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1, main_tlv), -SOC_DOUBLE_TLV("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1, main_tlv), -SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv), -SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv), -SOC_SINGLE_TLV("Mic 1 Preamp Volume", AC97_3D_CONTROL, 10, 3, 0, mic_tlv), -SOC_SINGLE_TLV("Mic 2 Preamp Volume", AC97_3D_CONTROL, 12, 3, 0, mic_tlv), - -SOC_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0), -SOC_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1), - -SOC_SINGLE("Capture Switch", AC97_CD, 15, 1, 1), -SOC_ENUM("Capture Volume Steps", wm9713_enum[5]), -SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0), -SOC_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0), - -SOC_SINGLE_TLV("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1, misc_tlv), -SOC_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0), -SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0), - -SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0), -SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0), -SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0), -SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0), -SOC_ENUM("ALC Function", wm9713_enum[6]), -SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0), -SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0), -SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0), -SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0), -SOC_ENUM("ALC NG Type", wm9713_enum[17]), -SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0), - -SOC_DOUBLE("Speaker Playback ZC Switch", AC97_MASTER, 14, 6, 1, 0), -SOC_DOUBLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0), - -SOC_SINGLE("Out4 Playback Switch", AC97_MASTER_MONO, 15, 1, 1), -SOC_SINGLE("Out4 Playback ZC Switch", AC97_MASTER_MONO, 14, 1, 0), -SOC_SINGLE_TLV("Out4 Playback Volume", AC97_MASTER_MONO, 8, 31, 1, out_tlv), - -SOC_SINGLE("Out3 Playback Switch", AC97_MASTER_MONO, 7, 1, 1), -SOC_SINGLE("Out3 Playback ZC Switch", AC97_MASTER_MONO, 6, 1, 0), -SOC_SINGLE_TLV("Out3 Playback Volume", AC97_MASTER_MONO, 0, 31, 1, out_tlv), - -SOC_SINGLE_TLV("Mono Capture Volume", AC97_MASTER_TONE, 8, 31, 1, main_tlv), -SOC_SINGLE("Mono Playback Switch", AC97_MASTER_TONE, 7, 1, 1), -SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_TONE, 6, 1, 0), -SOC_SINGLE_TLV("Mono Playback Volume", AC97_MASTER_TONE, 0, 31, 1, out_tlv), - -SOC_SINGLE_TLV("Headphone Mixer Beep Playback Volume", AC97_AUX, 12, 7, 1, - misc_tlv), -SOC_SINGLE_TLV("Speaker Mixer Beep Playback Volume", AC97_AUX, 8, 7, 1, - misc_tlv), -SOC_SINGLE_TLV("Mono Mixer Beep Playback Volume", AC97_AUX, 4, 7, 1, misc_tlv), - -SOC_SINGLE_TLV("Voice Playback Headphone Volume", AC97_PCM, 12, 7, 1, - misc_tlv), -SOC_SINGLE("Voice Playback Master Volume", AC97_PCM, 8, 7, 1), -SOC_SINGLE("Voice Playback Mono Volume", AC97_PCM, 4, 7, 1), - -SOC_SINGLE_TLV("Headphone Mixer Aux Playback Volume", AC97_REC_SEL, 12, 7, 1, - misc_tlv), - -SOC_SINGLE_TLV("Speaker Mixer Voice Playback Volume", AC97_PCM, 8, 7, 1, - misc_tlv), -SOC_SINGLE_TLV("Speaker Mixer Aux Playback Volume", AC97_REC_SEL, 8, 7, 1, - misc_tlv), - -SOC_SINGLE_TLV("Mono Mixer Voice Playback Volume", AC97_PCM, 4, 7, 1, - misc_tlv), -SOC_SINGLE_TLV("Mono Mixer Aux Playback Volume", AC97_REC_SEL, 4, 7, 1, - misc_tlv), - -SOC_SINGLE("Aux Playback Headphone Volume", AC97_REC_SEL, 12, 7, 1), -SOC_SINGLE("Aux Playback Master Volume", AC97_REC_SEL, 8, 7, 1), - -SOC_ENUM("Bass Control", wm9713_enum[16]), -SOC_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1), -SOC_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1), -SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0), -SOC_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1), -SOC_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1), - -SOC_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0), -SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0), -SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), -}; - -static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 status, rate; - - BUG_ON(event != SND_SOC_DAPM_PRE_PMD); - - /* Gracefully shut down the voice interface. */ - status = ac97_read(codec, AC97_EXTENDED_MID) | 0x1000; - rate = ac97_read(codec, AC97_HANDSET_RATE) & 0xF0FF; - ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0200); - schedule_timeout_interruptible(msecs_to_jiffies(1)); - ac97_write(codec, AC97_HANDSET_RATE, rate | 0x0F00); - ac97_write(codec, AC97_EXTENDED_MID, status); - - return 0; -} - - -/* We have to create a fake left and right HP mixers because - * the codec only has a single control that is shared by both channels. - * This makes it impossible to determine the audio path using the current - * register map, thus we add a new (virtual) register to help determine the - * audio route within the device. - */ -static int mixer_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - u16 l, r, beep, tone, phone, rec, pcm, aux; - - l = ac97_read(w->codec, HPL_MIXER); - r = ac97_read(w->codec, HPR_MIXER); - beep = ac97_read(w->codec, AC97_PC_BEEP); - tone = ac97_read(w->codec, AC97_MASTER_TONE); - phone = ac97_read(w->codec, AC97_PHONE); - rec = ac97_read(w->codec, AC97_REC_SEL); - pcm = ac97_read(w->codec, AC97_PCM); - aux = ac97_read(w->codec, AC97_AUX); - - if (event & SND_SOC_DAPM_PRE_REG) - return 0; - if ((l & 0x1) || (r & 0x1)) - ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); - else - ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); - - if ((l & 0x2) || (r & 0x2)) - ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff); - else - ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000); - - if ((l & 0x4) || (r & 0x4)) - ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); - else - ac97_write(w->codec, AC97_PHONE, phone | 0x8000); - - if ((l & 0x8) || (r & 0x8)) - ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff); - else - ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000); - - if ((l & 0x10) || (r & 0x10)) - ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); - else - ac97_write(w->codec, AC97_PCM, pcm | 0x8000); - - if ((l & 0x20) || (r & 0x20)) - ac97_write(w->codec, AC97_AUX, aux & 0x7fff); - else - ac97_write(w->codec, AC97_AUX, aux | 0x8000); - - return 0; -} - -/* Left Headphone Mixers */ -static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { -SOC_DAPM_SINGLE("Beep Playback Switch", HPL_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0), -SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0), -SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0), -}; - -/* Right Headphone Mixers */ -static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { -SOC_DAPM_SINGLE("Beep Playback Switch", HPR_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0), -SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0), -SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0), -}; - -/* headphone capture mux */ -static const struct snd_kcontrol_new wm9713_hp_rec_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[1]); - -/* headphone mic mux */ -static const struct snd_kcontrol_new wm9713_hp_mic_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[0]); - -/* Speaker Mixer */ -static const struct snd_kcontrol_new wm9713_speaker_mixer_controls[] = { -SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX, 11, 1, 1), -SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 11, 1, 1), -SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 11, 1, 1), -SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 14, 1, 1), -SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 14, 1, 1), -SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 14, 1, 1), -}; - -/* Mono Mixer */ -static const struct snd_kcontrol_new wm9713_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("Beep Playback Switch", AC97_AUX, 7, 1, 1), -SOC_DAPM_SINGLE("Voice Playback Switch", AC97_PCM, 7, 1, 1), -SOC_DAPM_SINGLE("Aux Playback Switch", AC97_REC_SEL, 7, 1, 1), -SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PHONE, 13, 1, 1), -SOC_DAPM_SINGLE("MonoIn Playback Switch", AC97_MASTER_TONE, 13, 1, 1), -SOC_DAPM_SINGLE("Bypass Playback Switch", AC97_PC_BEEP, 13, 1, 1), -SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_LINE, 7, 1, 1), -SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_LINE, 6, 1, 1), -}; - -/* mono mic mux */ -static const struct snd_kcontrol_new wm9713_mono_mic_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[2]); - -/* mono output mux */ -static const struct snd_kcontrol_new wm9713_mono_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[7]); - -/* speaker left output mux */ -static const struct snd_kcontrol_new wm9713_hp_spkl_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[8]); - -/* speaker right output mux */ -static const struct snd_kcontrol_new wm9713_hp_spkr_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[9]); - -/* headphone left output mux */ -static const struct snd_kcontrol_new wm9713_hpl_out_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[10]); - -/* headphone right output mux */ -static const struct snd_kcontrol_new wm9713_hpr_out_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[11]); - -/* Out3 mux */ -static const struct snd_kcontrol_new wm9713_out3_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[12]); - -/* Out4 mux */ -static const struct snd_kcontrol_new wm9713_out4_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[13]); - -/* DAC inv mux 1 */ -static const struct snd_kcontrol_new wm9713_dac_inv1_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[14]); - -/* DAC inv mux 2 */ -static const struct snd_kcontrol_new wm9713_dac_inv2_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[15]); - -/* Capture source left */ -static const struct snd_kcontrol_new wm9713_rec_srcl_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[3]); - -/* Capture source right */ -static const struct snd_kcontrol_new wm9713_rec_srcr_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[4]); - -/* mic source */ -static const struct snd_kcontrol_new wm9713_mic_sel_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[18]); - -/* mic source B virtual control */ -static const struct snd_kcontrol_new wm9713_micb_sel_mux_controls = -SOC_DAPM_ENUM("Route", wm9713_enum[19]); - -static const struct snd_soc_dapm_widget wm9713_dapm_widgets[] = { -SND_SOC_DAPM_MUX("Capture Headphone Mux", SND_SOC_NOPM, 0, 0, - &wm9713_hp_rec_mux_controls), -SND_SOC_DAPM_MUX("Sidetone Mux", SND_SOC_NOPM, 0, 0, - &wm9713_hp_mic_mux_controls), -SND_SOC_DAPM_MUX("Capture Mono Mux", SND_SOC_NOPM, 0, 0, - &wm9713_mono_mic_mux_controls), -SND_SOC_DAPM_MUX("Mono Out Mux", SND_SOC_NOPM, 0, 0, - &wm9713_mono_mux_controls), -SND_SOC_DAPM_MUX("Left Speaker Out Mux", SND_SOC_NOPM, 0, 0, - &wm9713_hp_spkl_mux_controls), -SND_SOC_DAPM_MUX("Right Speaker Out Mux", SND_SOC_NOPM, 0, 0, - &wm9713_hp_spkr_mux_controls), -SND_SOC_DAPM_MUX("Left Headphone Out Mux", SND_SOC_NOPM, 0, 0, - &wm9713_hpl_out_mux_controls), -SND_SOC_DAPM_MUX("Right Headphone Out Mux", SND_SOC_NOPM, 0, 0, - &wm9713_hpr_out_mux_controls), -SND_SOC_DAPM_MUX("Out 3 Mux", SND_SOC_NOPM, 0, 0, - &wm9713_out3_mux_controls), -SND_SOC_DAPM_MUX("Out 4 Mux", SND_SOC_NOPM, 0, 0, - &wm9713_out4_mux_controls), -SND_SOC_DAPM_MUX("DAC Inv Mux 1", SND_SOC_NOPM, 0, 0, - &wm9713_dac_inv1_mux_controls), -SND_SOC_DAPM_MUX("DAC Inv Mux 2", SND_SOC_NOPM, 0, 0, - &wm9713_dac_inv2_mux_controls), -SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0, - &wm9713_rec_srcl_mux_controls), -SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0, - &wm9713_rec_srcr_mux_controls), -SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0, - &wm9713_mic_sel_mux_controls), -SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0, - &wm9713_micb_sel_mux_controls), -SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1, - &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls), - mixer_event, SND_SOC_DAPM_POST_REG), -SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1, - &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls), - mixer_event, SND_SOC_DAPM_POST_REG), -SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1, - &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)), -SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1, - &wm9713_speaker_mixer_controls[0], - ARRAY_SIZE(wm9713_speaker_mixer_controls)), -SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_EXTENDED_MID, 7, 1), -SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_EXTENDED_MID, 6, 1), -SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("HP Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Line Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_MIXER("Capture Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -SND_SOC_DAPM_DAC_E("Voice DAC", "Voice Playback", AC97_EXTENDED_MID, 12, 1, - wm9713_voice_shutdown, SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", AC97_EXTENDED_MID, 11, 1), -SND_SOC_DAPM_PGA("Left ADC", AC97_EXTENDED_MID, 5, 1, NULL, 0), -SND_SOC_DAPM_PGA("Right ADC", AC97_EXTENDED_MID, 4, 1, NULL, 0), -SND_SOC_DAPM_ADC("Left HiFi ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_ADC("Right HiFi ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_ADC("Left Voice ADC", "Left Voice Capture", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_ADC("Right Voice ADC", "Right Voice Capture", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_PGA("Left Headphone", AC97_EXTENDED_MSTATUS, 10, 1, NULL, 0), -SND_SOC_DAPM_PGA("Right Headphone", AC97_EXTENDED_MSTATUS, 9, 1, NULL, 0), -SND_SOC_DAPM_PGA("Left Speaker", AC97_EXTENDED_MSTATUS, 8, 1, NULL, 0), -SND_SOC_DAPM_PGA("Right Speaker", AC97_EXTENDED_MSTATUS, 7, 1, NULL, 0), -SND_SOC_DAPM_PGA("Out 3", AC97_EXTENDED_MSTATUS, 11, 1, NULL, 0), -SND_SOC_DAPM_PGA("Out 4", AC97_EXTENDED_MSTATUS, 12, 1, NULL, 0), -SND_SOC_DAPM_PGA("Mono Out", AC97_EXTENDED_MSTATUS, 13, 1, NULL, 0), -SND_SOC_DAPM_PGA("Left Line In", AC97_EXTENDED_MSTATUS, 6, 1, NULL, 0), -SND_SOC_DAPM_PGA("Right Line In", AC97_EXTENDED_MSTATUS, 5, 1, NULL, 0), -SND_SOC_DAPM_PGA("Mono In", AC97_EXTENDED_MSTATUS, 4, 1, NULL, 0), -SND_SOC_DAPM_PGA("Mic A PGA", AC97_EXTENDED_MSTATUS, 3, 1, NULL, 0), -SND_SOC_DAPM_PGA("Mic B PGA", AC97_EXTENDED_MSTATUS, 2, 1, NULL, 0), -SND_SOC_DAPM_PGA("Mic A Pre Amp", AC97_EXTENDED_MSTATUS, 1, 1, NULL, 0), -SND_SOC_DAPM_PGA("Mic B Pre Amp", AC97_EXTENDED_MSTATUS, 0, 1, NULL, 0), -SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_EXTENDED_MSTATUS, 14, 1), -SND_SOC_DAPM_OUTPUT("MONO"), -SND_SOC_DAPM_OUTPUT("HPL"), -SND_SOC_DAPM_OUTPUT("HPR"), -SND_SOC_DAPM_OUTPUT("SPKL"), -SND_SOC_DAPM_OUTPUT("SPKR"), -SND_SOC_DAPM_OUTPUT("OUT3"), -SND_SOC_DAPM_OUTPUT("OUT4"), -SND_SOC_DAPM_INPUT("LINEL"), -SND_SOC_DAPM_INPUT("LINER"), -SND_SOC_DAPM_INPUT("MONOIN"), -SND_SOC_DAPM_INPUT("PCBEEP"), -SND_SOC_DAPM_INPUT("MIC1"), -SND_SOC_DAPM_INPUT("MIC2A"), -SND_SOC_DAPM_INPUT("MIC2B"), -SND_SOC_DAPM_VMID("VMID"), -}; - -static const struct snd_soc_dapm_route wm9713_audio_map[] = { - /* left HP mixer */ - {"Left HP Mixer", "Beep Playback Switch", "PCBEEP"}, - {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"}, - {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"}, - {"Left HP Mixer", "Bypass Playback Switch", "Left Line In"}, - {"Left HP Mixer", "PCM Playback Switch", "Left DAC"}, - {"Left HP Mixer", "MonoIn Playback Switch", "Mono In"}, - {"Left HP Mixer", NULL, "Capture Headphone Mux"}, - - /* right HP mixer */ - {"Right HP Mixer", "Beep Playback Switch", "PCBEEP"}, - {"Right HP Mixer", "Voice Playback Switch", "Voice DAC"}, - {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"}, - {"Right HP Mixer", "Bypass Playback Switch", "Right Line In"}, - {"Right HP Mixer", "PCM Playback Switch", "Right DAC"}, - {"Right HP Mixer", "MonoIn Playback Switch", "Mono In"}, - {"Right HP Mixer", NULL, "Capture Headphone Mux"}, - - /* virtual mixer - mixes left & right channels for spk and mono */ - {"AC97 Mixer", NULL, "Left DAC"}, - {"AC97 Mixer", NULL, "Right DAC"}, - {"Line Mixer", NULL, "Right Line In"}, - {"Line Mixer", NULL, "Left Line In"}, - {"HP Mixer", NULL, "Left HP Mixer"}, - {"HP Mixer", NULL, "Right HP Mixer"}, - {"Capture Mixer", NULL, "Left Capture Source"}, - {"Capture Mixer", NULL, "Right Capture Source"}, - - /* speaker mixer */ - {"Speaker Mixer", "Beep Playback Switch", "PCBEEP"}, - {"Speaker Mixer", "Voice Playback Switch", "Voice DAC"}, - {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"}, - {"Speaker Mixer", "Bypass Playback Switch", "Line Mixer"}, - {"Speaker Mixer", "PCM Playback Switch", "AC97 Mixer"}, - {"Speaker Mixer", "MonoIn Playback Switch", "Mono In"}, - - /* mono mixer */ - {"Mono Mixer", "Beep Playback Switch", "PCBEEP"}, - {"Mono Mixer", "Voice Playback Switch", "Voice DAC"}, - {"Mono Mixer", "Aux Playback Switch", "Aux DAC"}, - {"Mono Mixer", "Bypass Playback Switch", "Line Mixer"}, - {"Mono Mixer", "PCM Playback Switch", "AC97 Mixer"}, - {"Mono Mixer", "Mic 1 Sidetone Switch", "Mic A PGA"}, - {"Mono Mixer", "Mic 2 Sidetone Switch", "Mic B PGA"}, - {"Mono Mixer", NULL, "Capture Mono Mux"}, - - /* DAC inv mux 1 */ - {"DAC Inv Mux 1", "Mono", "Mono Mixer"}, - {"DAC Inv Mux 1", "Speaker", "Speaker Mixer"}, - {"DAC Inv Mux 1", "Left Headphone", "Left HP Mixer"}, - {"DAC Inv Mux 1", "Right Headphone", "Right HP Mixer"}, - {"DAC Inv Mux 1", "Headphone Mono", "HP Mixer"}, - - /* DAC inv mux 2 */ - {"DAC Inv Mux 2", "Mono", "Mono Mixer"}, - {"DAC Inv Mux 2", "Speaker", "Speaker Mixer"}, - {"DAC Inv Mux 2", "Left Headphone", "Left HP Mixer"}, - {"DAC Inv Mux 2", "Right Headphone", "Right HP Mixer"}, - {"DAC Inv Mux 2", "Headphone Mono", "HP Mixer"}, - - /* headphone left mux */ - {"Left Headphone Out Mux", "Headphone", "Left HP Mixer"}, - - /* headphone right mux */ - {"Right Headphone Out Mux", "Headphone", "Right HP Mixer"}, - - /* speaker left mux */ - {"Left Speaker Out Mux", "Headphone", "Left HP Mixer"}, - {"Left Speaker Out Mux", "Speaker", "Speaker Mixer"}, - {"Left Speaker Out Mux", "Inv", "DAC Inv Mux 1"}, - - /* speaker right mux */ - {"Right Speaker Out Mux", "Headphone", "Right HP Mixer"}, - {"Right Speaker Out Mux", "Speaker", "Speaker Mixer"}, - {"Right Speaker Out Mux", "Inv", "DAC Inv Mux 2"}, - - /* mono mux */ - {"Mono Out Mux", "Mono", "Mono Mixer"}, - {"Mono Out Mux", "Inv", "DAC Inv Mux 1"}, - - /* out 3 mux */ - {"Out 3 Mux", "Inv 1", "DAC Inv Mux 1"}, - - /* out 4 mux */ - {"Out 4 Mux", "Inv 2", "DAC Inv Mux 2"}, - - /* output pga */ - {"HPL", NULL, "Left Headphone"}, - {"Left Headphone", NULL, "Left Headphone Out Mux"}, - {"HPR", NULL, "Right Headphone"}, - {"Right Headphone", NULL, "Right Headphone Out Mux"}, - {"OUT3", NULL, "Out 3"}, - {"Out 3", NULL, "Out 3 Mux"}, - {"OUT4", NULL, "Out 4"}, - {"Out 4", NULL, "Out 4 Mux"}, - {"SPKL", NULL, "Left Speaker"}, - {"Left Speaker", NULL, "Left Speaker Out Mux"}, - {"SPKR", NULL, "Right Speaker"}, - {"Right Speaker", NULL, "Right Speaker Out Mux"}, - {"MONO", NULL, "Mono Out"}, - {"Mono Out", NULL, "Mono Out Mux"}, - - /* input pga */ - {"Left Line In", NULL, "LINEL"}, - {"Right Line In", NULL, "LINER"}, - {"Mono In", NULL, "MONOIN"}, - {"Mic A PGA", NULL, "Mic A Pre Amp"}, - {"Mic B PGA", NULL, "Mic B Pre Amp"}, - - /* left capture select */ - {"Left Capture Source", "Mic 1", "Mic A Pre Amp"}, - {"Left Capture Source", "Mic 2", "Mic B Pre Amp"}, - {"Left Capture Source", "Line", "LINEL"}, - {"Left Capture Source", "Mono In", "MONOIN"}, - {"Left Capture Source", "Headphone", "Left HP Mixer"}, - {"Left Capture Source", "Speaker", "Speaker Mixer"}, - {"Left Capture Source", "Mono Out", "Mono Mixer"}, - - /* right capture select */ - {"Right Capture Source", "Mic 1", "Mic A Pre Amp"}, - {"Right Capture Source", "Mic 2", "Mic B Pre Amp"}, - {"Right Capture Source", "Line", "LINER"}, - {"Right Capture Source", "Mono In", "MONOIN"}, - {"Right Capture Source", "Headphone", "Right HP Mixer"}, - {"Right Capture Source", "Speaker", "Speaker Mixer"}, - {"Right Capture Source", "Mono Out", "Mono Mixer"}, - - /* left ADC */ - {"Left ADC", NULL, "Left Capture Source"}, - {"Left Voice ADC", NULL, "Left ADC"}, - {"Left HiFi ADC", NULL, "Left ADC"}, - - /* right ADC */ - {"Right ADC", NULL, "Right Capture Source"}, - {"Right Voice ADC", NULL, "Right ADC"}, - {"Right HiFi ADC", NULL, "Right ADC"}, - - /* mic */ - {"Mic A Pre Amp", NULL, "Mic A Source"}, - {"Mic A Source", "Mic 1", "MIC1"}, - {"Mic A Source", "Mic 2 A", "MIC2A"}, - {"Mic A Source", "Mic 2 B", "Mic B Source"}, - {"Mic B Pre Amp", "MPB", "Mic B Source"}, - {"Mic B Source", NULL, "MIC2B"}, - - /* headphone capture */ - {"Capture Headphone Mux", "Stereo", "Capture Mixer"}, - {"Capture Headphone Mux", "Left", "Left Capture Source"}, - {"Capture Headphone Mux", "Right", "Right Capture Source"}, - - /* mono capture */ - {"Capture Mono Mux", "Stereo", "Capture Mixer"}, - {"Capture Mono Mux", "Left", "Left Capture Source"}, - {"Capture Mono Mux", "Right", "Right Capture Source"}, -}; - -static unsigned int ac97_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - - if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || - reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || - reg == AC97_CD) - return soc_ac97_ops.read(codec->ac97, reg); - else { - reg = reg >> 1; - - if (reg >= (ARRAY_SIZE(wm9713_reg))) - return -EIO; - - return cache[reg]; - } -} - -static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int val) -{ - u16 *cache = codec->reg_cache; - if (reg < 0x7c) - soc_ac97_ops.write(codec->ac97, reg, val); - reg = reg >> 1; - if (reg < (ARRAY_SIZE(wm9713_reg))) - cache[reg] = val; - - return 0; -} - -/* PLL divisors */ -struct _pll_div { - u32 divsel:1; - u32 divctl:1; - u32 lf:1; - u32 n:4; - u32 k:24; -}; - -/* The size in bits of the PLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 22) * 10) - -static void pll_factors(struct _pll_div *pll_div, unsigned int source) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod, target; - - /* The the PLL output is always 98.304MHz. */ - target = 98304000; - - /* If the input frequency is over 14.4MHz then scale it down. */ - if (source > 14400000) { - source >>= 1; - pll_div->divsel = 1; - - if (source > 14400000) { - source >>= 1; - pll_div->divctl = 1; - } else - pll_div->divctl = 0; - - } else { - pll_div->divsel = 0; - pll_div->divctl = 0; - } - - /* Low frequency sources require an additional divide in the - * loop. - */ - if (source < 8192000) { - pll_div->lf = 1; - target >>= 2; - } else - pll_div->lf = 0; - - Ndiv = target / source; - if ((Ndiv < 5) || (Ndiv > 12)) - printk(KERN_WARNING - "WM9713 PLL N value %u out of recommended range!\n", - Ndiv); - - pll_div->n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div->k = K; -} - -/** - * Please note that changing the PLL input frequency may require - * resynchronisation with the AC97 controller. - */ -static int wm9713_set_pll(struct snd_soc_codec *codec, - int pll_id, unsigned int freq_in, unsigned int freq_out) -{ - struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); - u16 reg, reg2; - struct _pll_div pll_div; - - /* turn PLL off ? */ - if (freq_in == 0) { - /* disable PLL power and select ext source */ - reg = ac97_read(codec, AC97_HANDSET_RATE); - ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080); - reg = ac97_read(codec, AC97_EXTENDED_MID); - ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200); - wm9713->pll_in = 0; - return 0; - } - - pll_factors(&pll_div, freq_in); - - if (pll_div.k == 0) { - reg = (pll_div.n << 12) | (pll_div.lf << 11) | - (pll_div.divsel << 9) | (pll_div.divctl << 8); - ac97_write(codec, AC97_LINE1_LEVEL, reg); - } else { - /* write the fractional k to the reg 0x46 pages */ - reg2 = (pll_div.n << 12) | (pll_div.lf << 11) | (1 << 10) | - (pll_div.divsel << 9) | (pll_div.divctl << 8); - - /* K [21:20] */ - reg = reg2 | (0x5 << 4) | (pll_div.k >> 20); - ac97_write(codec, AC97_LINE1_LEVEL, reg); - - /* K [19:16] */ - reg = reg2 | (0x4 << 4) | ((pll_div.k >> 16) & 0xf); - ac97_write(codec, AC97_LINE1_LEVEL, reg); - - /* K [15:12] */ - reg = reg2 | (0x3 << 4) | ((pll_div.k >> 12) & 0xf); - ac97_write(codec, AC97_LINE1_LEVEL, reg); - - /* K [11:8] */ - reg = reg2 | (0x2 << 4) | ((pll_div.k >> 8) & 0xf); - ac97_write(codec, AC97_LINE1_LEVEL, reg); - - /* K [7:4] */ - reg = reg2 | (0x1 << 4) | ((pll_div.k >> 4) & 0xf); - ac97_write(codec, AC97_LINE1_LEVEL, reg); - - reg = reg2 | (0x0 << 4) | (pll_div.k & 0xf); /* K [3:0] */ - ac97_write(codec, AC97_LINE1_LEVEL, reg); - } - - /* turn PLL on and select as source */ - reg = ac97_read(codec, AC97_EXTENDED_MID); - ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff); - reg = ac97_read(codec, AC97_HANDSET_RATE); - ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f); - wm9713->pll_in = freq_in; - - /* wait 10ms AC97 link frames for the link to stabilise */ - schedule_timeout_interruptible(msecs_to_jiffies(10)); - return 0; -} - -static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, - int source, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - return wm9713_set_pll(codec, pll_id, freq_in, freq_out); -} - -/* - * Tristate the PCM DAI lines, tristate can be disabled by calling - * wm9713_set_dai_fmt() - */ -static int wm9713_set_dai_tristate(struct snd_soc_dai *codec_dai, - int tristate) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0x9fff; - - if (tristate) - ac97_write(codec, AC97_CENTER_LFE_MASTER, reg); - - return 0; -} - -/* - * Configure WM9713 clock dividers. - * Voice DAC needs 256 FS - */ -static int wm9713_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM9713_PCMCLK_DIV: - reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xf0ff; - ac97_write(codec, AC97_HANDSET_RATE, reg | div); - break; - case WM9713_CLKA_MULT: - reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffd; - ac97_write(codec, AC97_HANDSET_RATE, reg | div); - break; - case WM9713_CLKB_MULT: - reg = ac97_read(codec, AC97_HANDSET_RATE) & 0xfffb; - ac97_write(codec, AC97_HANDSET_RATE, reg | div); - break; - case WM9713_HIFI_DIV: - reg = ac97_read(codec, AC97_HANDSET_RATE) & 0x8fff; - ac97_write(codec, AC97_HANDSET_RATE, reg | div); - break; - case WM9713_PCMBCLK_DIV: - reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xf1ff; - ac97_write(codec, AC97_CENTER_LFE_MASTER, reg | div); - break; - case WM9713_PCMCLK_PLL_DIV: - reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80; - ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x60 | div); - break; - case WM9713_HIFI_PLL_DIV: - reg = ac97_read(codec, AC97_LINE1_LEVEL) & 0xff80; - ac97_write(codec, AC97_LINE1_LEVEL, reg | 0x70 | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 gpio = ac97_read(codec, AC97_GPIO_CFG) & 0xffc5; - u16 reg = 0x8000; - - /* clock masters */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - reg |= 0x4000; - gpio |= 0x0010; - break; - case SND_SOC_DAIFMT_CBM_CFS: - reg |= 0x6000; - gpio |= 0x0018; - break; - case SND_SOC_DAIFMT_CBS_CFS: - reg |= 0x2000; - gpio |= 0x001a; - break; - case SND_SOC_DAIFMT_CBS_CFM: - gpio |= 0x0012; - break; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - reg |= 0x00c0; - break; - case SND_SOC_DAIFMT_IB_NF: - reg |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - reg |= 0x0040; - break; - } - - /* DAI format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - reg |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - reg |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - reg |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - reg |= 0x0043; - break; - } - - ac97_write(codec, AC97_GPIO_CFG, gpio); - ac97_write(codec, AC97_CENTER_LFE_MASTER, reg); - return 0; -} - -static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - reg |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - reg |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S32_LE: - reg |= 0x000c; - break; - } - - /* enable PCM interface in master mode */ - ac97_write(codec, AC97_CENTER_LFE_MASTER, reg); - return 0; -} - -static int ac97_hifi_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct snd_pcm_runtime *runtime = substream->runtime; - int reg; - u16 vra; - - vra = ac97_read(codec, AC97_EXTENDED_STATUS); - ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - reg = AC97_PCM_FRONT_DAC_RATE; - else - reg = AC97_PCM_LR_ADC_RATE; - - return ac97_write(codec, reg, runtime->rate); -} - -static int ac97_aux_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct snd_pcm_runtime *runtime = substream->runtime; - u16 vra, xsle; - - vra = ac97_read(codec, AC97_EXTENDED_STATUS); - ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1); - xsle = ac97_read(codec, AC97_PCI_SID); - ac97_write(codec, AC97_PCI_SID, xsle | 0x8000); - - if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) - return -ENODEV; - - return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate); -} - -#define WM9713_RATES (SNDRV_PCM_RATE_8000 | \ - SNDRV_PCM_RATE_11025 | \ - SNDRV_PCM_RATE_22050 | \ - SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000) - -#define WM9713_PCM_RATES (SNDRV_PCM_RATE_8000 | \ - SNDRV_PCM_RATE_11025 | \ - SNDRV_PCM_RATE_16000 | \ - SNDRV_PCM_RATE_22050 | \ - SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000) - -#define WM9713_PCM_FORMATS \ - (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ - SNDRV_PCM_FORMAT_S24_LE) - -static const struct snd_soc_dai_ops wm9713_dai_ops_hifi = { - .prepare = ac97_hifi_prepare, - .set_clkdiv = wm9713_set_dai_clkdiv, - .set_pll = wm9713_set_dai_pll, -}; - -static const struct snd_soc_dai_ops wm9713_dai_ops_aux = { - .prepare = ac97_aux_prepare, - .set_clkdiv = wm9713_set_dai_clkdiv, - .set_pll = wm9713_set_dai_pll, -}; - -static const struct snd_soc_dai_ops wm9713_dai_ops_voice = { - .hw_params = wm9713_pcm_hw_params, - .set_clkdiv = wm9713_set_dai_clkdiv, - .set_pll = wm9713_set_dai_pll, - .set_fmt = wm9713_set_dai_fmt, - .set_tristate = wm9713_set_dai_tristate, -}; - -static struct snd_soc_dai_driver wm9713_dai[] = { -{ - .name = "wm9713-hifi", - .ac97_control = 1, - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM9713_RATES, - .formats = SND_SOC_STD_AC97_FMTS,}, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM9713_RATES, - .formats = SND_SOC_STD_AC97_FMTS,}, - .ops = &wm9713_dai_ops_hifi, - }, - { - .name = "wm9713-aux", - .playback = { - .stream_name = "Aux Playback", - .channels_min = 1, - .channels_max = 1, - .rates = WM9713_RATES, - .formats = SND_SOC_STD_AC97_FMTS,}, - .ops = &wm9713_dai_ops_aux, - }, - { - .name = "wm9713-voice", - .playback = { - .stream_name = "Voice Playback", - .channels_min = 1, - .channels_max = 1, - .rates = WM9713_PCM_RATES, - .formats = WM9713_PCM_FORMATS,}, - .capture = { - .stream_name = "Voice Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM9713_PCM_RATES, - .formats = WM9713_PCM_FORMATS,}, - .ops = &wm9713_dai_ops_voice, - .symmetric_rates = 1, - }, -}; - -int wm9713_reset(struct snd_soc_codec *codec, int try_warm) -{ - if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset(codec->ac97); - if (ac97_read(codec, 0) == wm9713_reg[0]) - return 1; - } - - soc_ac97_ops.reset(codec->ac97); - if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset(codec->ac97); - if (ac97_read(codec, 0) != wm9713_reg[0]) - return -EIO; - return 0; -} -EXPORT_SYMBOL_GPL(wm9713_reset); - -static int wm9713_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 reg; - - switch (level) { - case SND_SOC_BIAS_ON: - /* enable thermal shutdown */ - reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff; - ac97_write(codec, AC97_EXTENDED_MID, reg); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - /* enable master bias and vmid */ - reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff; - ac97_write(codec, AC97_EXTENDED_MID, reg); - ac97_write(codec, AC97_POWERDOWN, 0x0000); - break; - case SND_SOC_BIAS_OFF: - /* disable everything including AC link */ - ac97_write(codec, AC97_EXTENDED_MID, 0xffff); - ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff); - ac97_write(codec, AC97_POWERDOWN, 0xffff); - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static int wm9713_soc_suspend(struct snd_soc_codec *codec) -{ - u16 reg; - - /* Disable everything except touchpanel - that will be handled - * by the touch driver and left disabled if touch is not in - * use. */ - reg = ac97_read(codec, AC97_EXTENDED_MID); - ac97_write(codec, AC97_EXTENDED_MID, reg | 0x7fff); - ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff); - ac97_write(codec, AC97_POWERDOWN, 0x6f00); - ac97_write(codec, AC97_POWERDOWN, 0xffff); - - return 0; -} - -static int wm9713_soc_resume(struct snd_soc_codec *codec) -{ - struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); - int i, ret; - u16 *cache = codec->reg_cache; - - ret = wm9713_reset(codec, 1); - if (ret < 0) { - printk(KERN_ERR "could not reset AC97 codec\n"); - return ret; - } - - wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* do we need to re-start the PLL ? */ - if (wm9713->pll_in) - wm9713_set_pll(codec, 0, wm9713->pll_in, 0); - - /* only synchronise the codec if warm reset failed */ - if (ret == 0) { - for (i = 2; i < ARRAY_SIZE(wm9713_reg) << 1; i += 2) { - if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || - i == AC97_EXTENDED_MSTATUS || i > 0x66) - continue; - soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); - } - } - - return ret; -} - -static int wm9713_soc_probe(struct snd_soc_codec *codec) -{ - struct wm9713_priv *wm9713; - int ret = 0, reg; - - wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); - if (wm9713 == NULL) - return -ENOMEM; - snd_soc_codec_set_drvdata(codec, wm9713); - - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); - if (ret < 0) - goto codec_err; - - /* do a cold reset for the controller and then try - * a warm reset followed by an optional cold reset for codec */ - wm9713_reset(codec, 0); - ret = wm9713_reset(codec, 1); - if (ret < 0) { - printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n"); - goto reset_err; - } - - wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* unmute the adc - move to kcontrol */ - reg = ac97_read(codec, AC97_CD) & 0x7fff; - ac97_write(codec, AC97_CD, reg); - - snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls, - ARRAY_SIZE(wm9713_snd_ac97_controls)); - - return 0; - -reset_err: - snd_soc_free_ac97_codec(codec); -codec_err: - kfree(wm9713); - return ret; -} - -static int wm9713_soc_remove(struct snd_soc_codec *codec) -{ - struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); - snd_soc_free_ac97_codec(codec); - kfree(wm9713); - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { - .probe = wm9713_soc_probe, - .remove = wm9713_soc_remove, - .suspend = wm9713_soc_suspend, - .resume = wm9713_soc_resume, - .read = ac97_read, - .write = ac97_write, - .set_bias_level = wm9713_set_bias_level, - .reg_cache_size = ARRAY_SIZE(wm9713_reg), - .reg_word_size = sizeof(u16), - .reg_cache_step = 2, - .reg_cache_default = wm9713_reg, - .dapm_widgets = wm9713_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), - .dapm_routes = wm9713_audio_map, - .num_dapm_routes = ARRAY_SIZE(wm9713_audio_map), -}; - -static __devinit int wm9713_probe(struct platform_device *pdev) -{ - return snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); -} - -static int __devexit wm9713_remove(struct platform_device *pdev) -{ - snd_soc_unregister_codec(&pdev->dev); - return 0; -} - -static struct platform_driver wm9713_codec_driver = { - .driver = { - .name = "wm9713-codec", - .owner = THIS_MODULE, - }, - - .probe = wm9713_probe, - .remove = __devexit_p(wm9713_remove), -}; - -module_platform_driver(wm9713_codec_driver); - -MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm9713.h b/ANDROID_3.4.5/sound/soc/codecs/wm9713.h deleted file mode 100644 index 793da863..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm9713.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * wm9713.h -- WM9713 Soc Audio driver - */ - -#ifndef _WM9713_H -#define _WM9713_H - -/* clock inputs */ -#define WM9713_CLKA_PIN 0 -#define WM9713_CLKB_PIN 1 - -/* clock divider ID's */ -#define WM9713_PCMCLK_DIV 0 -#define WM9713_CLKA_MULT 1 -#define WM9713_CLKB_MULT 2 -#define WM9713_HIFI_DIV 3 -#define WM9713_PCMBCLK_DIV 4 -#define WM9713_PCMCLK_PLL_DIV 5 -#define WM9713_HIFI_PLL_DIV 6 - -/* Calculate the appropriate bit mask for the external PCM clock divider */ -#define WM9713_PCMDIV(x) ((x - 1) << 8) - -/* Calculate the appropriate bit mask for the external HiFi clock divider */ -#define WM9713_HIFIDIV(x) ((x - 1) << 12) - -/* MCLK clock mulitipliers */ -#define WM9713_CLKA_X1 (0 << 1) -#define WM9713_CLKA_X2 (1 << 1) -#define WM9713_CLKB_X1 (0 << 2) -#define WM9713_CLKB_X2 (1 << 2) - -/* MCLK clock MUX */ -#define WM9713_CLK_MUX_A (0 << 0) -#define WM9713_CLK_MUX_B (1 << 0) - -/* Voice DAI BCLK divider */ -#define WM9713_PCMBCLK_DIV_1 (0 << 9) -#define WM9713_PCMBCLK_DIV_2 (1 << 9) -#define WM9713_PCMBCLK_DIV_4 (2 << 9) -#define WM9713_PCMBCLK_DIV_8 (3 << 9) -#define WM9713_PCMBCLK_DIV_16 (4 << 9) - -#define WM9713_DAI_AC97_HIFI 0 -#define WM9713_DAI_AC97_AUX 1 -#define WM9713_DAI_PCM_VOICE 2 - -int wm9713_reset(struct snd_soc_codec *codec, int try_warm); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm_hubs.c b/ANDROID_3.4.5/sound/soc/codecs/wm_hubs.c deleted file mode 100644 index 6c028c47..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm_hubs.c +++ /dev/null @@ -1,1086 +0,0 @@ -/* - * wm_hubs.c -- WM8993/4 common code - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8993.h" -#include "wm_hubs.h" - -const DECLARE_TLV_DB_SCALE(wm_hubs_spkmix_tlv, -300, 300, 0); -EXPORT_SYMBOL_GPL(wm_hubs_spkmix_tlv); - -static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0); -static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0); -static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1); -static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0); -static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1); -static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0); -static const unsigned int spkboost_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), - 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0); - -static const char *speaker_ref_text[] = { - "SPKVDD/2", - "VMID", -}; - -static const struct soc_enum speaker_ref = - SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text); - -static const char *speaker_mode_text[] = { - "Class D", - "Class AB", -}; - -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); - -static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) -{ - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - unsigned int reg; - int count = 0; - int timeout; - unsigned int val; - - val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; - - /* Trigger the command */ - snd_soc_write(codec, WM8993_DC_SERVO_0, val); - - dev_dbg(codec->dev, "Waiting for DC servo...\n"); - - if (hubs->dcs_done_irq) - timeout = 4; - else - timeout = 400; - - do { - count++; - - if (hubs->dcs_done_irq) - wait_for_completion_timeout(&hubs->dcs_done, - msecs_to_jiffies(250)); - else - msleep(1); - - reg = snd_soc_read(codec, WM8993_DC_SERVO_0); - dev_dbg(codec->dev, "DC servo: %x\n", reg); - } while (reg & op && count < timeout); - - if (reg & op) - dev_err(codec->dev, "Timed out waiting for DC Servo %x\n", - op); -} - -irqreturn_t wm_hubs_dcs_done(int irq, void *data) -{ - struct wm_hubs_data *hubs = data; - - complete(&hubs->dcs_done); - - return IRQ_HANDLED; -} -EXPORT_SYMBOL_GPL(wm_hubs_dcs_done); - -/* - * Startup calibration of the DC servo - */ -static void calibrate_dc_servo(struct snd_soc_codec *codec) -{ - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - s8 offset; - u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; - - switch (hubs->dcs_readback_mode) { - case 2: - dcs_reg = WM8994_DC_SERVO_4E; - break; - default: - dcs_reg = WM8993_DC_SERVO_3; - break; - } - - /* If we're using a digital only path and have a previously - * callibrated DC servo offset stored then use that. */ - if (hubs->class_w && hubs->class_w_dcs) { - dev_dbg(codec->dev, "Using cached DC servo offset %x\n", - hubs->class_w_dcs); - snd_soc_write(codec, dcs_reg, hubs->class_w_dcs); - wait_for_dc_servo(codec, - WM8993_DCS_TRIG_DAC_WR_0 | - WM8993_DCS_TRIG_DAC_WR_1); - return; - } - - if (hubs->series_startup) { - /* Set for 32 series updates */ - snd_soc_update_bits(codec, WM8993_DC_SERVO_1, - WM8993_DCS_SERIES_NO_01_MASK, - 32 << WM8993_DCS_SERIES_NO_01_SHIFT); - wait_for_dc_servo(codec, - WM8993_DCS_TRIG_SERIES_0 | - WM8993_DCS_TRIG_SERIES_1); - } else { - wait_for_dc_servo(codec, - WM8993_DCS_TRIG_STARTUP_0 | - WM8993_DCS_TRIG_STARTUP_1); - } - - /* Different chips in the family support different readback - * methods. - */ - switch (hubs->dcs_readback_mode) { - case 0: - reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) - & WM8993_DCS_INTEG_CHAN_0_MASK; - reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) - & WM8993_DCS_INTEG_CHAN_1_MASK; - break; - case 2: - case 1: - reg = snd_soc_read(codec, dcs_reg); - reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) - >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; - reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; - break; - default: - WARN(1, "Unknown DCS readback method\n"); - return; - } - - dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); - - /* Apply correction to DC servo result */ - if (hubs->dcs_codes_l || hubs->dcs_codes_r) { - dev_dbg(codec->dev, - "Applying %d/%d code DC servo correction\n", - hubs->dcs_codes_l, hubs->dcs_codes_r); - - /* HPOUT1R */ - offset = reg_r; - offset += hubs->dcs_codes_r; - dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; - - /* HPOUT1L */ - offset = reg_l; - offset += hubs->dcs_codes_l; - dcs_cfg |= (u8)offset; - - dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); - - /* Do it */ - snd_soc_write(codec, dcs_reg, dcs_cfg); - wait_for_dc_servo(codec, - WM8993_DCS_TRIG_DAC_WR_0 | - WM8993_DCS_TRIG_DAC_WR_1); - } else { - dcs_cfg = reg_r << WM8993_DCS_DAC_WR_VAL_1_SHIFT; - dcs_cfg |= reg_l; - } - - /* Save the callibrated offset if we're in class W mode and - * therefore don't have any analogue signal mixed in. */ - if (hubs->class_w && !hubs->no_cache_class_w) - hubs->class_w_dcs = dcs_cfg; -} - -/* - * Update the DC servo calibration on gain changes - */ -static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - int ret; - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - - /* Updating the analogue gains invalidates the DC servo cache */ - hubs->class_w_dcs = 0; - - /* If we're applying an offset correction then updating the - * callibration would be likely to introduce further offsets. */ - if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update) - return ret; - - /* Only need to do this if the outputs are active */ - if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) - & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) - snd_soc_update_bits(codec, - WM8993_DC_SERVO_0, - WM8993_DCS_TRIG_SINGLE_0 | - WM8993_DCS_TRIG_SINGLE_1, - WM8993_DCS_TRIG_SINGLE_0 | - WM8993_DCS_TRIG_SINGLE_1); - - return ret; -} - -static const struct snd_kcontrol_new analogue_snd_controls[] = { -SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 6, 1, 0), - -SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 6, 1, 0), - - -SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 6, 1, 0), - -SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 6, 1, 0), - -SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0, - inmix_tlv), -SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv), -SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0, - inmix_tlv), - -SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0, - inmix_tlv), -SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv), -SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0, - inmix_tlv), - -SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer Right Input Volume", - WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer Left Input Volume", - WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1, - outmix_tlv), - -SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume", - WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume", - WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN1L Volume", - WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN1R Volume", - WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume", - WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer Left Input Volume", - WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer Right Input Volume", - WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer DAC Volume", - WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv), - -SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv), -SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0), -SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0), - -SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1), -SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv), - -SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION, - 5, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION, - 4, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION, - 3, 1, 1, wm_hubs_spkmix_tlv), - -SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION, - 5, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION, - 4, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION, - 3, 1, 1, wm_hubs_spkmix_tlv), - -SOC_DOUBLE_R_TLV("Speaker Mixer Volume", - WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION, - 0, 3, 1, spkmixout_tlv), -SOC_DOUBLE_R_TLV("Speaker Volume", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 0, 63, 0, outpga_tlv), -SOC_DOUBLE_R("Speaker Switch", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 6, 1, 0), -SOC_DOUBLE_R("Speaker ZC Switch", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 7, 1, 0), -SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0, - spkboost_tlv), -SOC_ENUM("Speaker Reference", speaker_ref), -SOC_ENUM("Speaker Mode", speaker_mode), - -SOC_DOUBLE_R_EXT_TLV("Headphone Volume", - WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME, - 0, 63, 0, snd_soc_get_volsw, wm8993_put_dc_servo, - outpga_tlv), - -SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME, - WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0), -SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME, - WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0), - -SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1), -SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1), -SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1, - line_tlv), - -SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1), -SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1), -SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1, - line_tlv), -}; - -static int hp_supply_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - switch (hubs->hp_startup_mode) { - case 0: - break; - case 1: - /* Enable the headphone amp */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_HPOUT1L_ENA | - WM8993_HPOUT1R_ENA, - WM8993_HPOUT1L_ENA | - WM8993_HPOUT1R_ENA); - - /* Enable the second stage */ - snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, - WM8993_HPOUT1L_DLY | - WM8993_HPOUT1R_DLY, - WM8993_HPOUT1L_DLY | - WM8993_HPOUT1R_DLY); - break; - default: - dev_err(codec->dev, "Unknown HP startup mode %d\n", - hubs->hp_startup_mode); - break; - } - - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, - WM8993_CP_ENA, 0); - break; - } - - return 0; -} - -static int hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, - WM8993_CP_ENA, WM8993_CP_ENA); - - msleep(5); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA); - - reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY; - snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); - - snd_soc_update_bits(codec, WM8993_DC_SERVO_1, - WM8993_DCS_TIMER_PERIOD_01_MASK, 0); - - calibrate_dc_servo(codec); - - reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | - WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; - snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); - break; - - case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, - WM8993_HPOUT1L_OUTP | - WM8993_HPOUT1R_OUTP | - WM8993_HPOUT1L_RMV_SHORT | - WM8993_HPOUT1R_RMV_SHORT, 0); - - snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, - WM8993_HPOUT1L_DLY | - WM8993_HPOUT1R_DLY, 0); - - snd_soc_write(codec, WM8993_DC_SERVO_0, 0); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, - 0); - break; - } - - return 0; -} - -static int earpiece_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *control, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - reg |= WM8993_HPOUT2_IN_ENA; - snd_soc_write(codec, WM8993_ANTIPOP1, reg); - udelay(50); - break; - - case SND_SOC_DAPM_POST_PMD: - snd_soc_write(codec, WM8993_ANTIPOP1, reg); - break; - - default: - BUG(); - break; - } - - return 0; -} - -static int lineout_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *control, int event) -{ - struct snd_soc_codec *codec = w->codec; - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - bool *flag; - - switch (w->shift) { - case WM8993_LINEOUT1N_ENA_SHIFT: - flag = &hubs->lineout1n_ena; - break; - case WM8993_LINEOUT1P_ENA_SHIFT: - flag = &hubs->lineout1p_ena; - break; - case WM8993_LINEOUT2N_ENA_SHIFT: - flag = &hubs->lineout2n_ena; - break; - case WM8993_LINEOUT2P_ENA_SHIFT: - flag = &hubs->lineout2p_ena; - break; - default: - WARN(1, "Unknown line output"); - return -EINVAL; - } - - *flag = SND_SOC_DAPM_EVENT_ON(event); - - return 0; -} - -static const struct snd_kcontrol_new in1l_pga[] = { -SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0), -SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0), -}; - -static const struct snd_kcontrol_new in1r_pga[] = { -SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new in2l_pga[] = { -SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0), -}; - -static const struct snd_kcontrol_new in2r_pga[] = { -SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0), -}; - -static const struct snd_kcontrol_new mixinl[] = { -SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0), -}; - -static const struct snd_kcontrol_new mixinr[] = { -SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0), -}; - -static const struct snd_kcontrol_new left_output_mixer[] = { -SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0), -SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0), -SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_output_mixer[] = { -SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0), -SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new earpiece_mixer[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0), -}; - -static const struct snd_kcontrol_new left_speaker_boost[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0), -SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0), -SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0), -}; - -static const struct snd_kcontrol_new right_speaker_boost[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0), -SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0), -SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line1_mix[] = { -SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line1n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0), -}; - -static const struct snd_kcontrol_new line1p_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line2_mix[] = { -SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line2n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), -}; - -static const struct snd_kcontrol_new line2p_mix[] = { -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), -}; - -static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1LN"), -SND_SOC_DAPM_INPUT("IN1LP"), -SND_SOC_DAPM_INPUT("IN2LN"), -SND_SOC_DAPM_INPUT("IN2LP:VXRN"), -SND_SOC_DAPM_INPUT("IN1RN"), -SND_SOC_DAPM_INPUT("IN1RP"), -SND_SOC_DAPM_INPUT("IN2RN"), -SND_SOC_DAPM_INPUT("IN2RP:VXRP"), - -SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, - in1l_pga, ARRAY_SIZE(in1l_pga)), -SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0, - in1r_pga, ARRAY_SIZE(in1r_pga)), - -SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0, - in2l_pga, ARRAY_SIZE(in2l_pga)), -SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0, - in2r_pga, ARRAY_SIZE(in2r_pga)), - -SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, - mixinl, ARRAY_SIZE(mixinl)), -SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, - mixinr, ARRAY_SIZE(mixinr)), - -SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0, - left_output_mixer, ARRAY_SIZE(left_output_mixer)), -SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, - right_output_mixer, ARRAY_SIZE(right_output_mixer)), - -SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0), - -SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_OUT_DRV_E("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0, - hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, - earpiece_mixer, ARRAY_SIZE(earpiece_mixer)), -SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0, - NULL, 0, earpiece_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0, - left_speaker_boost, ARRAY_SIZE(left_speaker_boost)), -SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0, - right_speaker_boost, ARRAY_SIZE(right_speaker_boost)), - -SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0), -SND_SOC_DAPM_OUT_DRV("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0, - NULL, 0), -SND_SOC_DAPM_OUT_DRV("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0, - NULL, 0), - -SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0, - line1_mix, ARRAY_SIZE(line1_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0, - line2_mix, ARRAY_SIZE(line2_mix)), - -SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0, - line1n_mix, ARRAY_SIZE(line1n_mix)), -SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0, - line1p_mix, ARRAY_SIZE(line1p_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0, - line2n_mix, ARRAY_SIZE(line2n_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0, - line2p_mix, ARRAY_SIZE(line2p_mix)), - -SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0, - NULL, 0, lineout_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0, - NULL, 0, lineout_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0, - NULL, 0, lineout_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0, - NULL, 0, lineout_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_OUTPUT("SPKOUTLP"), -SND_SOC_DAPM_OUTPUT("SPKOUTLN"), -SND_SOC_DAPM_OUTPUT("SPKOUTRP"), -SND_SOC_DAPM_OUTPUT("SPKOUTRN"), -SND_SOC_DAPM_OUTPUT("HPOUT1L"), -SND_SOC_DAPM_OUTPUT("HPOUT1R"), -SND_SOC_DAPM_OUTPUT("HPOUT2P"), -SND_SOC_DAPM_OUTPUT("HPOUT2N"), -SND_SOC_DAPM_OUTPUT("LINEOUT1P"), -SND_SOC_DAPM_OUTPUT("LINEOUT1N"), -SND_SOC_DAPM_OUTPUT("LINEOUT2P"), -SND_SOC_DAPM_OUTPUT("LINEOUT2N"), -}; - -static const struct snd_soc_dapm_route analogue_routes[] = { - { "MICBIAS1", NULL, "CLK_SYS" }, - { "MICBIAS2", NULL, "CLK_SYS" }, - - { "IN1L PGA", "IN1LP Switch", "IN1LP" }, - { "IN1L PGA", "IN1LN Switch", "IN1LN" }, - - { "IN1L PGA", NULL, "VMID" }, - { "IN1R PGA", NULL, "VMID" }, - { "IN2L PGA", NULL, "VMID" }, - { "IN2R PGA", NULL, "VMID" }, - - { "IN1R PGA", "IN1RP Switch", "IN1RP" }, - { "IN1R PGA", "IN1RN Switch", "IN1RN" }, - - { "IN2L PGA", "IN2LP Switch", "IN2LP:VXRN" }, - { "IN2L PGA", "IN2LN Switch", "IN2LN" }, - - { "IN2R PGA", "IN2RP Switch", "IN2RP:VXRP" }, - { "IN2R PGA", "IN2RN Switch", "IN2RN" }, - - { "Direct Voice", NULL, "IN2LP:VXRN" }, - { "Direct Voice", NULL, "IN2RP:VXRP" }, - - { "MIXINL", "IN1L Switch", "IN1L PGA" }, - { "MIXINL", "IN2L Switch", "IN2L PGA" }, - { "MIXINL", NULL, "Direct Voice" }, - { "MIXINL", NULL, "IN1LP" }, - { "MIXINL", NULL, "Left Output Mixer" }, - { "MIXINL", NULL, "VMID" }, - - { "MIXINR", "IN1R Switch", "IN1R PGA" }, - { "MIXINR", "IN2R Switch", "IN2R PGA" }, - { "MIXINR", NULL, "Direct Voice" }, - { "MIXINR", NULL, "IN1RP" }, - { "MIXINR", NULL, "Right Output Mixer" }, - { "MIXINR", NULL, "VMID" }, - - { "ADCL", NULL, "MIXINL" }, - { "ADCR", NULL, "MIXINR" }, - - { "Left Output Mixer", "Left Input Switch", "MIXINL" }, - { "Left Output Mixer", "Right Input Switch", "MIXINR" }, - { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, - { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, - { "Left Output Mixer", "IN2LP Switch", "IN2LP:VXRN" }, - { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, - { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, - - { "Right Output Mixer", "Left Input Switch", "MIXINL" }, - { "Right Output Mixer", "Right Input Switch", "MIXINR" }, - { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, - { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, - { "Right Output Mixer", "IN2RP Switch", "IN2RP:VXRP" }, - { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, - { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, - - { "Left Output PGA", NULL, "Left Output Mixer" }, - { "Left Output PGA", NULL, "TOCLK" }, - - { "Right Output PGA", NULL, "Right Output Mixer" }, - { "Right Output PGA", NULL, "TOCLK" }, - - { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" }, - { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, - { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, - - { "Earpiece Driver", NULL, "VMID" }, - { "Earpiece Driver", NULL, "Earpiece Mixer" }, - { "HPOUT2N", NULL, "Earpiece Driver" }, - { "HPOUT2P", NULL, "Earpiece Driver" }, - - { "SPKL", "Input Switch", "MIXINL" }, - { "SPKL", "IN1LP Switch", "IN1LP" }, - { "SPKL", "Output Switch", "Left Output PGA" }, - { "SPKL", NULL, "TOCLK" }, - - { "SPKR", "Input Switch", "MIXINR" }, - { "SPKR", "IN1RP Switch", "IN1RP" }, - { "SPKR", "Output Switch", "Right Output PGA" }, - { "SPKR", NULL, "TOCLK" }, - - { "SPKL Boost", "Direct Voice Switch", "Direct Voice" }, - { "SPKL Boost", "SPKL Switch", "SPKL" }, - { "SPKL Boost", "SPKR Switch", "SPKR" }, - - { "SPKR Boost", "Direct Voice Switch", "Direct Voice" }, - { "SPKR Boost", "SPKR Switch", "SPKR" }, - { "SPKR Boost", "SPKL Switch", "SPKL" }, - - { "SPKL Driver", NULL, "VMID" }, - { "SPKL Driver", NULL, "SPKL Boost" }, - { "SPKL Driver", NULL, "CLK_SYS" }, - { "SPKL Driver", NULL, "TSHUT" }, - - { "SPKR Driver", NULL, "VMID" }, - { "SPKR Driver", NULL, "SPKR Boost" }, - { "SPKR Driver", NULL, "CLK_SYS" }, - { "SPKR Driver", NULL, "TSHUT" }, - - { "SPKOUTLP", NULL, "SPKL Driver" }, - { "SPKOUTLN", NULL, "SPKL Driver" }, - { "SPKOUTRP", NULL, "SPKR Driver" }, - { "SPKOUTRN", NULL, "SPKR Driver" }, - - { "Left Headphone Mux", "Mixer", "Left Output PGA" }, - { "Right Headphone Mux", "Mixer", "Right Output PGA" }, - - { "Headphone PGA", NULL, "Left Headphone Mux" }, - { "Headphone PGA", NULL, "Right Headphone Mux" }, - { "Headphone PGA", NULL, "VMID" }, - { "Headphone PGA", NULL, "CLK_SYS" }, - { "Headphone PGA", NULL, "Headphone Supply" }, - - { "HPOUT1L", NULL, "Headphone PGA" }, - { "HPOUT1R", NULL, "Headphone PGA" }, - - { "LINEOUT1N Driver", NULL, "VMID" }, - { "LINEOUT1P Driver", NULL, "VMID" }, - { "LINEOUT2N Driver", NULL, "VMID" }, - { "LINEOUT2P Driver", NULL, "VMID" }, - - { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, - { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, - { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, - { "LINEOUT2P", NULL, "LINEOUT2P Driver" }, -}; - -static const struct snd_soc_dapm_route lineout1_diff_routes[] = { - { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" }, - { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" }, - { "LINEOUT1 Mixer", "Output Switch", "Left Output PGA" }, - - { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" }, - { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout1_se_routes[] = { - { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" }, - { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" }, - - { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" }, - - { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, - { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout2_diff_routes[] = { - { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" }, - { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" }, - { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" }, - - { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, - { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout2_se_routes[] = { - { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" }, - { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" }, - - { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" }, - - { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, - { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" }, -}; - -int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* Latch volume update bits & default ZC on */ - snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME, - WM8993_IN1_VU, WM8993_IN1_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8993_IN1_VU, WM8993_IN1_VU); - snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_3_4_VOLUME, - WM8993_IN2_VU, WM8993_IN2_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8993_IN2_VU, WM8993_IN2_VU); - - snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_LEFT, - WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); - snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT, - WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); - - snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME, - WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC, - WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC); - snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME, - WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC, - WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC); - - snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME, - WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU, - WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME, - WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU, - WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU); - - snd_soc_add_codec_controls(codec, analogue_snd_controls, - ARRAY_SIZE(analogue_snd_controls)); - - snd_soc_dapm_new_controls(dapm, analogue_dapm_widgets, - ARRAY_SIZE(analogue_dapm_widgets)); - return 0; -} -EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls); - -int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, - int lineout1_diff, int lineout2_diff) -{ - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = &codec->dapm; - - init_completion(&hubs->dcs_done); - - snd_soc_dapm_add_routes(dapm, analogue_routes, - ARRAY_SIZE(analogue_routes)); - - if (lineout1_diff) - snd_soc_dapm_add_routes(dapm, - lineout1_diff_routes, - ARRAY_SIZE(lineout1_diff_routes)); - else - snd_soc_dapm_add_routes(dapm, - lineout1_se_routes, - ARRAY_SIZE(lineout1_se_routes)); - - if (lineout2_diff) - snd_soc_dapm_add_routes(dapm, - lineout2_diff_routes, - ARRAY_SIZE(lineout2_diff_routes)); - else - snd_soc_dapm_add_routes(dapm, - lineout2_se_routes, - ARRAY_SIZE(lineout2_se_routes)); - - return 0; -} -EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); - -int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, - int lineout1_diff, int lineout2_diff, - int lineout1fb, int lineout2fb, - int jd_scthr, int jd_thr, int micbias1_lvl, - int micbias2_lvl) -{ - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - - hubs->lineout1_se = !lineout1_diff; - hubs->lineout2_se = !lineout2_diff; - - if (!lineout1_diff) - snd_soc_update_bits(codec, WM8993_LINE_MIXER1, - WM8993_LINEOUT1_MODE, - WM8993_LINEOUT1_MODE); - if (!lineout2_diff) - snd_soc_update_bits(codec, WM8993_LINE_MIXER2, - WM8993_LINEOUT2_MODE, - WM8993_LINEOUT2_MODE); - - if (!lineout1_diff && !lineout2_diff) - snd_soc_update_bits(codec, WM8993_ANTIPOP1, - WM8993_LINEOUT_VMID_BUF_ENA, - WM8993_LINEOUT_VMID_BUF_ENA); - - if (lineout1fb) - snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, - WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB); - - if (lineout2fb) - snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, - WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB); - - snd_soc_update_bits(codec, WM8993_MICBIAS, - WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK | - WM8993_MICB1_LVL | WM8993_MICB2_LVL, - jd_scthr << WM8993_JD_SCTHR_SHIFT | - jd_thr << WM8993_JD_THR_SHIFT | - micbias1_lvl | - micbias2_lvl << WM8993_MICB2_LVL_SHIFT); - - return 0; -} -EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata); - -void wm_hubs_vmid_ena(struct snd_soc_codec *codec) -{ - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - int val = 0; - - if (hubs->lineout1_se) - val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA; - - if (hubs->lineout2_se) - val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA; - - /* Enable the line outputs while we power up */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3, val, val); -} -EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena); - -void wm_hubs_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); - int mask, val; - - switch (level) { - case SND_SOC_BIAS_STANDBY: - /* Clamp the inputs to VMID while we ramp to charge caps */ - snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG, - WM8993_INPUTS_CLAMP, WM8993_INPUTS_CLAMP); - break; - - case SND_SOC_BIAS_ON: - /* Turn off any unneded single ended outputs */ - val = 0; - mask = 0; - - if (hubs->lineout1_se) - mask |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA; - - if (hubs->lineout2_se) - mask |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA; - - if (hubs->lineout1_se && hubs->lineout1n_ena) - val |= WM8993_LINEOUT1N_ENA; - - if (hubs->lineout1_se && hubs->lineout1p_ena) - val |= WM8993_LINEOUT1P_ENA; - - if (hubs->lineout2_se && hubs->lineout2n_ena) - val |= WM8993_LINEOUT2N_ENA; - - if (hubs->lineout2_se && hubs->lineout2p_ena) - val |= WM8993_LINEOUT2P_ENA; - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3, - mask, val); - - /* Remove the input clamps */ - snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG, - WM8993_INPUTS_CLAMP, 0); - break; - - default: - break; - } -} -EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level); - -MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wm_hubs.h b/ANDROID_3.4.5/sound/soc/codecs/wm_hubs.h deleted file mode 100644 index 5705276f..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wm_hubs.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * wm_hubs.h -- WM899x common code - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM_HUBS_H -#define _WM_HUBS_H - -#include -#include - -struct snd_soc_codec; - -extern const unsigned int wm_hubs_spkmix_tlv[]; - -/* This *must* be the first element of the codec->private_data struct */ -struct wm_hubs_data { - int dcs_codes_l; - int dcs_codes_r; - int dcs_readback_mode; - int hp_startup_mode; - int series_startup; - int no_series_update; - - bool no_cache_class_w; - bool class_w; - u16 class_w_dcs; - - bool lineout1_se; - bool lineout1n_ena; - bool lineout1p_ena; - - bool lineout2_se; - bool lineout2n_ena; - bool lineout2p_ena; - - bool dcs_done_irq; - struct completion dcs_done; -}; - -extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); -extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int); -extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, - int lineout1_diff, int lineout2_diff, - int lineout1fb, int lineout2fb, - int jd_scthr, int jd_thr, - int micbias1_lvl, int micbias2_lvl); - -extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); -extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec); -extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/codecs/wmt_fm34.c b/ANDROID_3.4.5/sound/soc/codecs/wmt_fm34.c deleted file mode 100755 index cee4dce9..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wmt_fm34.c +++ /dev/null @@ -1,830 +0,0 @@ -/*++ - * linux/sound/soc/codecs/wmt_fm34.c - * WonderMedia echo cancellation driver - * - * Copyright c 2010 WonderMedia Technologies, Inc. - * - * 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, see . - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define FM34_DEVID 0x501a -#define FM34_I2C_BUS_NR 4 - -#define FM34_CTRL_NAME "wmt_echo" -static int fm34_ctrl_major = 0; -static struct cdev fm34_ctrl_dev; -static struct class *fm34_ctrl_class; - -// FM34 control interface commands -#define FM34_CMD_ECHO _IOWR('E', 0x01, int) -#define FM34_CMD_BYPASS _IOWR('E', 0x02, int) -#define FM34_CMD_INCALL_MAIN_MIC _IOWR('E', 0x04, int) -#define FM34_CMD_INCALL_HEADSET_MIC _IOWR('E', 0x08, int) -#define FM34_CMD_CAPTURE_MAIN_MIC _IOWR('E', 0x10, int) -#define FM34_CMD_CAPTURE_HEADSET_MIC _IOWR('E', 0x20, int) - -enum FM34_MODE_TYPE { - FM34_MODE_ECHO, - FM34_MODE_BYPASS, - FM34_MODE_MAX, -}; - -enum FM34_MIC_SOURCE { - FM34_INCALL_MIC_MAIN, - FM34_INCALL_MIC_HEADSET, - FM34_CAPTURE_MIC_MAIN, - FM34_CAPTURE_MIC_HEADSET, - FM34_MIC_MAX, -}; - -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); - -struct fm34_ctrl_gpo { - int enable; - int gpio; - int active; -}; - -static struct fm34_ctrl_gpo fm34_reset; -static struct fm34_ctrl_gpo fm34_powerdown; -static struct fm34_ctrl_gpo fm34_bypass; - -struct fm34 { - int (*read_dev)(struct fm34 *fm34, - const u8 wdata[], int wsize, - u8 rdata[], int rsize); - int (*write_dev)(struct fm34 *fm34, const u8 wdata[], int wsize); - void *control_data; - struct device *dev; - struct delayed_work delaywork; -}; - -static struct fm34 *fm34_context; -static enum FM34_MODE_TYPE fm_mode = FM34_MODE_MAX; -static enum FM34_MIC_SOURCE fm_mic = FM34_MIC_MAX; - -static const u8 wmt_fm34_incall_main_mic[] = { - 0xFC, 0xF3, 0x3B, 0x22, 0xC0, 0x00, 0x04, - 0xFC, 0xF3, 0x3B, 0x22, 0xC1, 0x00, 0x04, - 0xFC, 0xF3, 0x3B, 0x22, 0xC2, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x22, 0xC3, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x22, 0xC6, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x22, 0xC7, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x22, 0xC8, 0x00, 0x2C, - 0xFC, 0xF3, 0x3B, 0x22, 0xD2, 0x12, 0x94, - 0xFC, 0xF3, 0x3B, 0x22, 0xEE, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x22, 0xF2, 0x00, 0x40, - 0xFC, 0xF3, 0x3B, 0x22, 0xF6, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x22, 0xF8, 0x80, 0x05, - 0xFC, 0xF3, 0x3B, 0x22, 0xF9, 0x20, 0xFF, - 0xFC, 0xF3, 0x3B, 0x22, 0xFA, 0x22, 0x8B, - 0xFC, 0xF3, 0x3B, 0x23, 0x01, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x02, 0x01, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x03, 0x09, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x04, 0x03, 0x1E, - 0xFC, 0xF3, 0x3B, 0x23, 0x05, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x07, 0xF0, 0xF0, - 0xFC, 0xF3, 0x3B, 0x23, 0x08, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x0A, 0x1B, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x0C, 0x04, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x48, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x49, 0x06, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x6E, 0x20, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x6F, 0x0A, 0x0A, - 0xFC, 0xF3, 0x3B, 0x23, 0x70, 0x0F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x73, 0x22, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x74, 0x18, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x75, 0x12, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x77, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x7B, 0x00, 0x08, - 0xFC, 0xF3, 0x3B, 0x23, 0x86, 0x48, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x8C, 0x10, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x9C, 0x60, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x9D, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x9E, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xBD, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xCE, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xCF, 0x0A, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD0, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD1, 0x02, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD2, 0x05, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xED, 0x05, 0x40, - 0xFC, 0xF3, 0x3B, 0x23, 0xEE, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD5, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x80, 0x7F, 0xFF, - 0xFC, 0xF3, 0x3B, 0x23, 0x81, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x82, 0x04, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x83, 0x04, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x84, 0x00, 0x04, - 0xFC, 0xF3, 0x3B, 0x23, 0x85, 0x00, 0x05, - 0xFC, 0xF3, 0x3B, 0x23, 0x8E, 0x70, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x90, 0xA9, 0x87, - 0xFC, 0xF3, 0x3B, 0x23, 0x91, 0x76, 0x54, - 0xFC, 0xF3, 0x3B, 0x23, 0x93, 0x44, 0x55, - 0xFC, 0xF3, 0x3B, 0x23, 0x94, 0x55, 0x66, - 0xFC, 0xF3, 0x3B, 0x23, 0x95, 0x66, 0x77, - 0xFC, 0xF3, 0x3B, 0x23, 0x96, 0x20, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x97, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x98, 0x00, 0x20, - 0xFC, 0xF3, 0x3B, 0x23, 0xA5, 0x00, 0x06, - 0xFC, 0xF3, 0x3B, 0x23, 0xA8, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xA9, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAA, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAB, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAC, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAD, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAE, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAF, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xB0, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xB1, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x09, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xB3, 0x00, 0x20, - 0xFC, 0xF3, 0x3B, 0x23, 0xB4, 0x00, 0x18, - 0xFC, 0xF3, 0x3B, 0x23, 0x10, 0x48, 0x90, - 0xFC, 0xF3, 0x3B, 0x23, 0x2F, 0x01, 0x40, - 0xFC, 0xF3, 0x3B, 0x23, 0x32, 0x00, 0x30, - 0xFC, 0xF3, 0x3B, 0x23, 0x33, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x23, 0x37, 0x00, 0x02, - 0xFC, 0xF3, 0x3B, 0x23, 0x39, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x22, 0xFB, 0x00, 0x00 -}; - -static const u8 wmt_fm34_incall_headset_mic[] = { - 0xFC, 0xF3, 0x3B, 0x22, 0xC0, 0x00, 0x04, - 0xFC, 0xF3, 0x3B, 0x22, 0xC1, 0x00, 0x04, - 0xFC, 0xF3, 0x3B, 0x22, 0xC2, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x22, 0xC3, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x22, 0xC6, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x22, 0xC7, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x22, 0xC8, 0x00, 0x2C, - 0xFC, 0xF3, 0x3B, 0x22, 0xD2, 0x12, 0x94, - 0xFC, 0xF3, 0x3B, 0x22, 0xEE, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x22, 0xF2, 0x00, 0x40, - 0xFC, 0xF3, 0x3B, 0x22, 0xF6, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x22, 0xF8, 0x80, 0x05, - 0xFC, 0xF3, 0x3B, 0x22, 0xF9, 0x20, 0xFF, - 0xFC, 0xF3, 0x3B, 0x22, 0xFA, 0x22, 0x8B, - 0xFC, 0xF3, 0x3B, 0x23, 0x01, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x02, 0x01, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x03, 0x09, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x04, 0x03, 0x1E, - 0xFC, 0xF3, 0x3B, 0x23, 0x05, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x07, 0xF0, 0xF0, - 0xFC, 0xF3, 0x3B, 0x23, 0x08, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x0A, 0x1A, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x0C, 0x04, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x48, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x49, 0x06, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x6E, 0x20, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x6F, 0x0A, 0x0A, - 0xFC, 0xF3, 0x3B, 0x23, 0x70, 0x0F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x73, 0x22, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x74, 0x18, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x75, 0x12, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x77, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x7B, 0x00, 0x08, - 0xFC, 0xF3, 0x3B, 0x23, 0x86, 0x48, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x8C, 0x10, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x9C, 0x60, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x9D, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x9E, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xBD, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xCE, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xCF, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD0, 0x06, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD1, 0x02, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD2, 0x05, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xED, 0x05, 0x40, - 0xFC, 0xF3, 0x3B, 0x23, 0xEE, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD5, 0x20, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x80, 0x7F, 0xFF, - 0xFC, 0xF3, 0x3B, 0x23, 0x81, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x82, 0x04, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x83, 0x04, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x84, 0x00, 0x04, - 0xFC, 0xF3, 0x3B, 0x23, 0x85, 0x00, 0x05, - 0xFC, 0xF3, 0x3B, 0x23, 0x8E, 0x70, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x90, 0xA9, 0x87, - 0xFC, 0xF3, 0x3B, 0x23, 0x91, 0x76, 0x54, - 0xFC, 0xF3, 0x3B, 0x23, 0x93, 0x44, 0x55, - 0xFC, 0xF3, 0x3B, 0x23, 0x94, 0x55, 0x66, - 0xFC, 0xF3, 0x3B, 0x23, 0x95, 0x66, 0x77, - 0xFC, 0xF3, 0x3B, 0x23, 0x96, 0x20, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x97, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x98, 0x00, 0x20, - 0xFC, 0xF3, 0x3B, 0x23, 0xA5, 0x00, 0x06, - 0xFC, 0xF3, 0x3B, 0x23, 0xA8, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xA9, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAA, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAB, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAC, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAD, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAE, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xAF, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xB0, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xB1, 0x7F, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x09, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xB3, 0x00, 0x06, - 0xFC, 0xF3, 0x3B, 0x23, 0xB4, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x10, 0x48, 0x90, - 0xFC, 0xF3, 0x3B, 0x23, 0x2F, 0x01, 0x40, - 0xFC, 0xF3, 0x3B, 0x23, 0x32, 0x00, 0x30, - 0xFC, 0xF3, 0x3B, 0x23, 0x33, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x23, 0x37, 0x00, 0x02, - 0xFC, 0xF3, 0x3B, 0x23, 0x39, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x22, 0xFB, 0x00, 0x00 -}; - -static const u8 wmt_fm34_capture_main_mic[] = { - 0xFC, 0xF3, 0x3B, 0x22, 0x9F, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x22, 0xC6, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x22, 0xC7, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x22, 0xC8, 0x00, 0x2C, - 0xFC, 0xF3, 0x3B, 0x22, 0xEE, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x22, 0xF2, 0x00, 0x40, - 0xFC, 0xF3, 0x3B, 0x22, 0xF6, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x22, 0xF7, 0x01, 0x00, - 0xFC, 0xF3, 0x3B, 0x22, 0xF8, 0x80, 0x02, - 0xFC, 0xF3, 0x3B, 0x22, 0xF9, 0x67, 0xFF, - 0xFC, 0xF3, 0x3B, 0x22, 0xFA, 0x23, 0x8B, - 0xFC, 0xF3, 0x3B, 0x23, 0x01, 0x00, 0x02, - 0xFC, 0xF3, 0x3B, 0x23, 0x02, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x03, 0x29, 0x88, - 0xFC, 0xF3, 0x3B, 0x23, 0x04, 0x20, 0x0E, - 0xFC, 0xF3, 0x3B, 0x23, 0x05, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x07, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x08, 0x0C, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x0A, 0x1B, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x0C, 0x02, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x48, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x6E, 0x7F, 0xFF, - 0xFC, 0xF3, 0x3B, 0x23, 0x6F, 0x0B, 0x05, - 0xFC, 0xF3, 0x3B, 0x23, 0x70, 0x0C, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x73, 0x18, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x74, 0x21, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x75, 0x18, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x7B, 0x00, 0x08, - 0xFC, 0xF3, 0x3B, 0x23, 0x82, 0x05, 0x80, - 0xFC, 0xF3, 0x3B, 0x23, 0x83, 0x03, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x84, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x23, 0x86, 0x48, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x8C, 0x10, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x90, 0x44, 0x44, - 0xFC, 0xF3, 0x3B, 0x23, 0x91, 0x44, 0x44, - 0xFC, 0xF3, 0x3B, 0x23, 0x92, 0x44, 0x44, - 0xFC, 0xF3, 0x3B, 0x23, 0x93, 0x44, 0x44, - 0xFC, 0xF3, 0x3B, 0x23, 0xBD, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xCE, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xCF, 0x12, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD0, 0x10, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD1, 0x07, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD2, 0x05, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD5, 0x70, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xED, 0x0A, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xEE, 0x10, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x28, 0x7F, 0xFF, - 0xFC, 0xF3, 0x3B, 0x22, 0xF1, 0xD0, 0x00, - 0xFC, 0xF3, 0x3B, 0x22, 0xFB, 0x00, 0x00 -}; - -static const u8 wmt_fm34_capture_headset_mic[] = { - 0xFC, 0xF3, 0x3B, 0x22, 0x9F, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x22, 0xC6, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x22, 0xC7, 0x00, 0x0C, - 0xFC, 0xF3, 0x3B, 0x22, 0xC8, 0x00, 0x2C, - 0xFC, 0xF3, 0x3B, 0x22, 0xEE, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x22, 0xF2, 0x00, 0x40, - 0xFC, 0xF3, 0x3B, 0x22, 0xF6, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x22, 0xF7, 0x01, 0x00, - 0xFC, 0xF3, 0x3B, 0x22, 0xF8, 0x80, 0x02, - 0xFC, 0xF3, 0x3B, 0x22, 0xF9, 0x67, 0xFF, - 0xFC, 0xF3, 0x3B, 0x22, 0xFA, 0x23, 0x8B, - 0xFC, 0xF3, 0x3B, 0x23, 0x01, 0x00, 0x02, - 0xFC, 0xF3, 0x3B, 0x23, 0x02, 0x00, 0x01, - 0xFC, 0xF3, 0x3B, 0x23, 0x03, 0x29, 0x88, - 0xFC, 0xF3, 0x3B, 0x23, 0x04, 0x20, 0x0E, - 0xFC, 0xF3, 0x3B, 0x23, 0x05, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x07, 0x00, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x08, 0x0C, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x0A, 0x1A, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x0C, 0x02, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x48, 0x08, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x6E, 0x7F, 0xFF, - 0xFC, 0xF3, 0x3B, 0x23, 0x6F, 0x0B, 0x05, - 0xFC, 0xF3, 0x3B, 0x23, 0x70, 0x0C, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x73, 0x18, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x74, 0x21, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x75, 0x18, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x7B, 0x00, 0x08, - 0xFC, 0xF3, 0x3B, 0x23, 0x82, 0x05, 0x80, - 0xFC, 0xF3, 0x3B, 0x23, 0x83, 0x03, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x84, 0x00, 0x03, - 0xFC, 0xF3, 0x3B, 0x23, 0x86, 0x48, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x8C, 0x10, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x90, 0x44, 0x44, - 0xFC, 0xF3, 0x3B, 0x23, 0x91, 0x44, 0x44, - 0xFC, 0xF3, 0x3B, 0x23, 0x92, 0x44, 0x44, - 0xFC, 0xF3, 0x3B, 0x23, 0x93, 0x44, 0x44, - 0xFC, 0xF3, 0x3B, 0x23, 0xBD, 0x30, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xCE, 0x40, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xCF, 0x12, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD0, 0x10, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD1, 0x07, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD2, 0x05, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xD5, 0x70, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xED, 0x0A, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0xEE, 0x10, 0x00, - 0xFC, 0xF3, 0x3B, 0x23, 0x28, 0x7F, 0xFF, - 0xFC, 0xF3, 0x3B, 0x22, 0xF1, 0xD0, 0x00, - 0xFC, 0xF3, 0x3B, 0x22, 0xFB, 0x00, 0x00 -}; - -static int fm34_check_functionality(struct fm34 *fm34) -{ - u8 rdata1, rdata2; - int devid = 0; - const u8 wdata1[] = { - 0xFC, 0xF3, 0x27, 0x37, 0xFF - }; - const u8 wdata2[] = { - 0xFC, 0xF3, 0x60, 0x25 - }; - const u8 wdata3[] = { - 0xFC, 0xF3, 0x60, 0x26 - }; - - if (fm34->write_dev(fm34, wdata1, sizeof(wdata1))) - return 0; - - if (fm34->read_dev(fm34, wdata2, sizeof(wdata2), &rdata1, 1) || - fm34->read_dev(fm34, wdata3, sizeof(wdata3), &rdata2, 1)) - return 0; - - devid = (rdata2 << 8) | rdata1; - printk("-->fm34_check_functionality: %x\n", devid); - if (devid == FM34_DEVID) - return 1; - - return 0; -} - -static int fm34_i2c_write(struct fm34 *fm34, const u8 wdata[], int wsize) -{ - int ret; - struct i2c_client *i2c = fm34->control_data; - struct i2c_msg xfer[1]; - - /* - * [MSG1]: fill the register address data - * fill the data Tx buffer - */ - xfer[0].addr = i2c->addr; - xfer[0].flags = 0 ; - xfer[0].flags &= ~(I2C_M_RD); - xfer[0].buf = (__u8 *)wdata; - xfer[0].len = wsize; - - /* i2c_transfer returns number of messages transferred */ - ret = i2c_transfer(i2c->adapter, xfer, ARRAY_SIZE(xfer)); - if (ret != ARRAY_SIZE(xfer)) { - pr_err("fm34_i2c_write err[%d]\n", ret); - if (ret < 0) - return ret; - else - return -EIO; - } else - return 0; -} - -static int fm34_i2c_read(struct fm34 *fm34, - const u8 wdata[], int wsize, - u8 rdata[], int rsize) -{ - int ret; - struct i2c_client *i2c = fm34->control_data; - struct i2c_msg xfer[2]; - - /* [MSG1] fill the register address data */ - xfer[0].addr = i2c->addr; - xfer[0].flags = 2; /* Read the register val */ - xfer[0].buf = (__u8 *)wdata; - xfer[0].len = wsize; - - /* [MSG2] fill the data rx buffer */ - xfer[1].addr = i2c->addr; - xfer[1].flags = I2C_M_RD; /* Read the register val */ - xfer[1].len = rsize; /* only n bytes */ - xfer[1].buf = rdata; - - /* i2c_transfer returns number of messages transferred */ - ret = i2c_transfer(i2c->adapter, xfer, ARRAY_SIZE(xfer)); - if (ret != ARRAY_SIZE(xfer)) { - pr_err("vt1603_i2c_read err[%d]\n", ret); - if (ret < 0) - return ret; - else - return -EIO; - } else { - return 0; - } -} - -static void fm34_timing_init(void) -{ - // pwdn high to power up fm34 module - if (fm34_powerdown.enable) { - gpio_set_value_cansleep(fm34_powerdown.gpio, !!fm34_powerdown.active); - msleep(100); - } - - // reset fm34 module - if (fm34_reset.enable) { - gpio_set_value_cansleep(fm34_reset.gpio, !!fm34_reset.active); - msleep(10); - gpio_set_value_cansleep(fm34_reset.gpio, !fm34_reset.active); - msleep(10); - gpio_set_value_cansleep(fm34_reset.gpio, !!fm34_reset.active); - msleep(100); - } - - // disable fm34 bypass - if (fm34_bypass.enable) { - gpio_set_value_cansleep(fm34_bypass.gpio, !!fm34_bypass.active); - } -} - -static void fm34_do_work(struct work_struct *work) -{ - struct fm34 *fm34 = container_of(work, struct fm34, delaywork.work); - - fm34_timing_init(); - - if (fm34_check_functionality(fm34) == 0) { - pr_err("fm34_check_functionality: wrong device id\n"); - } - - fm34->write_dev(fm34, wmt_fm34_incall_main_mic, sizeof(wmt_fm34_incall_main_mic)); - //fm_mode = FM34_MODE_ECHO; - fm_mic = FM34_INCALL_MIC_MAIN; -} - -static int __devinit fm34_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct fm34 *fm34; - int ret; - - if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C) == 0) { - pr_err("i2c_check_functionality: can't talk I2C?\n"); - return -EIO; - } - - fm34 = kzalloc(sizeof(struct fm34), GFP_KERNEL); - if (fm34 == NULL) - return -ENOMEM; - - fm34->dev = &i2c->dev; - fm34->control_data = i2c; - fm34->read_dev = fm34_i2c_read; - fm34->write_dev = fm34_i2c_write; - - i2c_set_clientdata(i2c, fm34); - dev_set_drvdata(fm34->dev, fm34); - - INIT_DELAYED_WORK(&fm34->delaywork, fm34_do_work); - - if (fm34_powerdown.enable && gpio_is_valid(fm34_powerdown.gpio)) { - ret = gpio_request(fm34_powerdown.gpio, "FM34-powerdown"); - if (ret < 0){ - dev_warn(fm34->dev, "cann't register fm34_powerdown.gpio-%d\n", fm34_powerdown.gpio); - fm34_powerdown.enable = 0; - } - else - gpio_direction_output(fm34_powerdown.gpio, 0); - } - - if (fm34_reset.enable && gpio_is_valid(fm34_reset.gpio)) { - ret = gpio_request(fm34_reset.gpio, "FM34-reset"); - if (ret < 0) { - dev_warn(fm34->dev, "cann't register fm34_reset.gpio-%d\n", fm34_reset.gpio); - fm34_reset.enable = 0; - } - else - gpio_direction_output(fm34_reset.gpio, 0); - } - - if (fm34_bypass.enable && gpio_is_valid(fm34_bypass.gpio)) { - ret = gpio_request(fm34_bypass.gpio, "FM34-bypass"); - if (ret < 0) { - dev_warn(fm34->dev, "cann't register fm34_bypass.gpio-%d\n", fm34_bypass.gpio); - fm34_bypass.enable = 0; - } - else - gpio_direction_output(fm34_bypass.gpio, 0); - } - - fm34_timing_init(); - - if (fm34_check_functionality(fm34) == 0) { - pr_err("fm34_check_functionality: wrong device id\n"); - return -EIO; - } - - fm34_context = fm34; - - /* write the firmware to device */ - fm34->write_dev(fm34, wmt_fm34_incall_main_mic, sizeof(wmt_fm34_incall_main_mic)); - fm_mode = FM34_MODE_ECHO; // default is echo mode - fm_mic = FM34_INCALL_MIC_MAIN; - return 0; -} - -static int __devexit fm34_i2c_remove(struct i2c_client *i2c) -{ - struct fm34 *fm34 = i2c_get_clientdata(i2c); - - if (fm34_powerdown.enable) { - gpio_free(fm34_powerdown.gpio); - } - if (fm34_reset.enable) { - gpio_free(fm34_reset.gpio); - } - if (fm34_bypass.enable) { - gpio_free(fm34_bypass.gpio); - } - - kfree(fm34); - return 0; -} - -static int fm34_suspend(struct i2c_client *i2c, pm_message_t mesg) -{ - struct fm34 *fm34 = i2c_get_clientdata(i2c); - cancel_delayed_work_sync(&fm34->delaywork); - return 0; -} -static int fm34_resume(struct i2c_client *i2c) -{ - struct fm34 *fm34 = i2c_get_clientdata(i2c); - schedule_delayed_work(&fm34->delaywork, msecs_to_jiffies(2000)); - return 0; -} - -static const struct i2c_device_id fm34_i2c_id[] = { - { "wmt-fm34", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, fm34_i2c_id); - -static struct i2c_driver fm34_i2c_driver = { - .driver = { - .name = "wmt-fm34", - .owner = THIS_MODULE, - }, - .probe = fm34_i2c_probe, - .remove = __devexit_p(fm34_i2c_remove), - .suspend = fm34_suspend, - .resume = fm34_resume, - .id_table = fm34_i2c_id, -}; - -static struct i2c_board_info fm34_i2c_board_info = { - I2C_BOARD_INFO("wmt-fm34", 0xc0>>1), -}; - -static int fm34_ctrl_open (struct inode *inode, struct file *filp) -{ - printk("%s %d\n", __func__, __LINE__); - return 0; -} - -static int fm34_ctrl_release(struct inode *inode, struct file *filp) -{ - printk("%s %d\n", __func__, __LINE__); - return 0; -} - -static ssize_t fm34_ctrl_read(struct file *filp, char __user *buf, size_t size, loff_t *offp) -{ - printk("%s %d\n", __func__, __LINE__); - return size; -} - -static long fm34_ctrl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - const u8 echo[] = { 0xFC, 0xF3, 0x3B, 0x23, 0x00, 0x00, 0x00 }; - const u8 bypass[] = { 0xFC, 0xF3, 0x3B, 0x23, 0x00, 0x00, 0x01 }; - //const u8 main_mic[] = { 0xFC, 0xF3, 0x3B, 0x23, 0x0a, 0x1a, 0x00 }; - //const u8 headset_mic[] = { 0xFC, 0xF3, 0x3B, 0x23, 0x0a, 0x1b, 0x00 }; - - switch (cmd) { - case FM34_CMD_ECHO: - if (fm_mode != FM34_MODE_ECHO) { - printk("FM34 cmd: echo\n"); - if (fm34_context->write_dev(fm34_context, echo, sizeof(echo))) - return -EIO; - fm_mode = FM34_MODE_ECHO; - } - break; - - case FM34_CMD_BYPASS: - if (fm_mode != FM34_MODE_BYPASS) { - printk("FM34 cmd: bypass\n"); - if (fm34_context->write_dev(fm34_context, bypass, sizeof(bypass))) - return -EIO; - fm_mode = FM34_MODE_BYPASS; - } - break; - - case FM34_CMD_INCALL_MAIN_MIC: - if (fm_mic != FM34_INCALL_MIC_MAIN) { - printk("FM34 cmd: incall main-mic\n"); - if (fm34_reset.enable) { - gpio_set_value_cansleep(fm34_reset.gpio, !fm34_reset.active); - msleep(20); - gpio_set_value_cansleep(fm34_reset.gpio, !!fm34_reset.active); - msleep(20); - } - if (fm34_context->write_dev(fm34_context, wmt_fm34_incall_main_mic, sizeof(wmt_fm34_incall_main_mic))) - return -EIO; - fm_mic = FM34_INCALL_MIC_MAIN; - } - break; - - case FM34_CMD_INCALL_HEADSET_MIC: - if (fm_mic != FM34_INCALL_MIC_HEADSET) { - printk("FM34 cmd: incall headset-mic\n"); - if (fm34_reset.enable) { - gpio_set_value_cansleep(fm34_reset.gpio, !fm34_reset.active); - msleep(20); - gpio_set_value_cansleep(fm34_reset.gpio, !!fm34_reset.active); - msleep(20); - } - if (fm34_context->write_dev(fm34_context, wmt_fm34_incall_headset_mic, sizeof(wmt_fm34_incall_headset_mic))) - return -EIO; - fm_mic = FM34_INCALL_MIC_HEADSET; - } - break; - - case FM34_CMD_CAPTURE_MAIN_MIC: - if (fm_mic != FM34_CMD_CAPTURE_MAIN_MIC) { - printk("FM34 cmd: capture main-mic\n"); - if (fm34_reset.enable) { - gpio_set_value_cansleep(fm34_reset.gpio, !fm34_reset.active); - msleep(20); - gpio_set_value_cansleep(fm34_reset.gpio, !!fm34_reset.active); - msleep(20); - } - if (fm34_context->write_dev(fm34_context, wmt_fm34_capture_main_mic, sizeof(wmt_fm34_capture_main_mic))) - return -EIO; - fm_mic = FM34_CMD_CAPTURE_MAIN_MIC; - } - break; - - case FM34_CMD_CAPTURE_HEADSET_MIC: - if (fm_mic != FM34_CMD_CAPTURE_HEADSET_MIC) { - printk("FM34 cmd: capture headset-mic\n"); - if (fm34_reset.enable) { - gpio_set_value_cansleep(fm34_reset.gpio, !fm34_reset.active); - msleep(20); - gpio_set_value_cansleep(fm34_reset.gpio, !!fm34_reset.active); - msleep(20); - } - if (fm34_context->write_dev(fm34_context, wmt_fm34_capture_headset_mic, sizeof(wmt_fm34_capture_headset_mic))) - return -EIO; - fm_mic = FM34_CMD_CAPTURE_HEADSET_MIC; - } - break; - - default: - printk(KERN_ERR "FM34: Not support cmd[%d]\n", cmd); - break; - } - - return 0; -} - -static struct file_operations fm34_ctrl_ops = { - .owner = THIS_MODULE, - .open = fm34_ctrl_open, - .release = fm34_ctrl_release, - .read = fm34_ctrl_read, - .unlocked_ioctl = fm34_ctrl_ioctl, -}; - -static int fm34_ctrl_setup_cdev(struct cdev *dev, int minor, struct file_operations *fops) -{ - int ret, devno = MKDEV(fm34_ctrl_major, minor); - cdev_init(dev, fops); - dev->owner = THIS_MODULE; - dev->ops = fops; - ret = cdev_add(dev, devno, 1); - if (ret) - printk(KERN_ERR "Error %d adding wmt_echo %d", ret, minor); - return ret; -} - -static int __init fm34_init(void) -{ - int ret = -1; - int len = 64; - char buf[64]; - dev_t dev; - struct i2c_adapter *adapter; - struct i2c_client *client; - - ret = wmt_getsyspara("wmt.echo.cancellation", buf, &len); - if (ret == 0) { - sscanf(buf, "fm34:[%d:%d:%d]:[%d:%d:%d]:[%d:%d:%d]", - &fm34_powerdown.enable, &fm34_powerdown.gpio, &fm34_powerdown.active, - &fm34_reset.enable, &fm34_reset.gpio, &fm34_reset.active, - &fm34_bypass.enable, &fm34_bypass.gpio, &fm34_bypass.active); - } - else { - fm34_reset.enable = 0; - fm34_powerdown.enable = 0; - fm34_bypass.enable = 0; - } - - ret = alloc_chrdev_region(&dev, 0, 1, FM34_CTRL_NAME); - if (ret == 0) - fm34_ctrl_major = MAJOR(dev); - else - printk(KERN_ERR "fm34: alloc_chrdev_region failed!\n"); - - ret = fm34_ctrl_setup_cdev(&fm34_ctrl_dev, 0, &fm34_ctrl_ops); - if (ret == 0) { - fm34_ctrl_class = class_create(THIS_MODULE, FM34_CTRL_NAME); - if (IS_ERR(fm34_ctrl_class)) { - printk("fm34: class_create failed!\n"); - } - else - device_create(fm34_ctrl_class, NULL, MKDEV(fm34_ctrl_major, 0), NULL, FM34_CTRL_NAME); - } - - adapter = i2c_get_adapter(FM34_I2C_BUS_NR); - client = i2c_new_device(adapter, &fm34_i2c_board_info); - i2c_put_adapter(adapter); - - ret = i2c_add_driver(&fm34_i2c_driver); - if (ret != 0) - pr_err("Failed to register FM34 I2C driver: %d\n", ret); - return ret; -} -module_init(fm34_init); - -static void __exit fm34_exit(void) -{ - cdev_del(&fm34_ctrl_dev); - device_destroy(fm34_ctrl_class, MKDEV(fm34_ctrl_major, 0)); - class_destroy(fm34_ctrl_class); - unregister_chrdev_region(MKDEV(fm34_ctrl_major, 0), 1); - - i2c_del_driver(&fm34_i2c_driver); -} -module_exit(fm34_exit); - -MODULE_DESCRIPTION("WMT [ALSA SoC/echocancellation] driver"); -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wmt_hwdac.c b/ANDROID_3.4.5/sound/soc/codecs/wmt_hwdac.c deleted file mode 100755 index ae31bb5e..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wmt_hwdac.c +++ /dev/null @@ -1,195 +0,0 @@ -/*++ - * linux/sound/soc/codecs/wmt_hwdac.c - * WonderMedia I2S audio driver for ALSA - * - * Copyright c 2010 WonderMedia Technologies, Inc. - * - * 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, see . - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - * Debug - */ -#define AUDIO_NAME "HW_DAC" -//#define WMT_HWDAC_DEBUG 1 -//#define WMT_HWDAC_DEBUG_DETAIL 1 - -#ifdef WMT_HWDAC_DEBUG -#define DPRINTK(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -#else -#define DPRINTK(format, arg...) do {} while (0) -#endif - -#ifdef WMT_HWDAC_DEBUG_DETAIL -#define DBG_DETAIL(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": [%s]" format "\n" , __FUNCTION__, ## arg) -#else -#define DBG_DETAIL(format, arg...) do {} while (0) -#endif - -#define err(format, arg...) \ - printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) -#define info(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -#define warn(format, arg...) \ - printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) - -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); - - -static int hwdac_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - DBG_DETAIL(); - - return 0; -} - - -#define HWDAC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | \ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ - SNDRV_PCM_RATE_96000) - -#define HWDAC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_FLOAT) - -static struct snd_soc_dai_ops hwdac_dai_ops = { - .hw_params = hwdac_pcm_hw_params, -}; - -struct snd_soc_dai_driver hwdac_dai = { - .name = "HWDAC", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = HWDAC_RATES, - .formats = HWDAC_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = HWDAC_RATES, - .formats = HWDAC_FORMATS, - }, - .ops = &hwdac_dai_ops, -}; - -static int hwdac_probe(struct snd_soc_codec *codec) -{ - DBG_DETAIL(); - - return 0; -} - -/* remove everything here */ -static int hwdac_remove(struct snd_soc_codec *codec) -{ - DBG_DETAIL(); - - return 0; -} - -struct snd_soc_codec_driver soc_codec_dev_hwdac = { - .probe = hwdac_probe, - .remove = hwdac_remove, -}; - -static int __devinit hwdac_platform_probe(struct platform_device *pdev) -{ - int ret = 0; - - DBG_DETAIL(); - - ret = snd_soc_register_codec(&pdev->dev, - &soc_codec_dev_hwdac, &hwdac_dai, 1); - - if (ret) - info("snd_soc_register_codec fail"); - - return ret; -} - -static int __devexit hwdac_platform_remove(struct platform_device *pdev) -{ - DBG_DETAIL(); - - snd_soc_unregister_codec(&pdev->dev); - - return 0; -} - -static struct platform_driver wmt_hwdac_driver = { - .driver = { - .name = "wmt-i2s-hwdac", - .owner = THIS_MODULE, - }, - - .probe = hwdac_platform_probe, - .remove = __devexit_p(hwdac_platform_remove), -}; - -static int __init wmt_hwdac_platform_init(void) -{ - char buf[80]; - int varlen = 80; - char codec_name[5]; - int ret = 0; - - DBG_DETAIL(); - - /*ret = wmt_getsyspara("wmt.audio.i2s", buf, &varlen); - - if (ret == 0) { - sscanf(buf, "%5s", codec_name); - - if (strcmp(codec_name, "hwdac")) { - info("hwdac string not found"); - return -EINVAL; - } - }*/ - - return platform_driver_register(&wmt_hwdac_driver); -} -module_init(wmt_hwdac_platform_init); - -static void __exit wmt_hwdac_platform_exit(void) -{ - DBG_DETAIL(); - - platform_driver_unregister(&wmt_hwdac_driver); -} -module_exit(wmt_hwdac_platform_exit); - -MODULE_DESCRIPTION("WMT [ALSA SoC] driver"); -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.c b/ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.c deleted file mode 100755 index fd625c95..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.c +++ /dev/null @@ -1,981 +0,0 @@ -/*++ - * linux/sound/soc/codecs/wmt_vt1602.c - * WonderMedia I2S audio driver for ALSA - * - * Copyright c 2010 WonderMedia Technologies, Inc. - * - * 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, see . - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wmt_vt1602.h" - -#define VT1602_VERSION "0.20" -#define I2C_DRIVERID_VT1602 90 - -/* - * Debug - */ -#define AUDIO_NAME "VT1602" -//#define WMT_VT1602_DEBUG 1 -//#define WMT_VT1602_DEBUG_DETAIL 1 - -#ifdef WMT_VT1602_DEBUG -#define DPRINTK(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -#else -#define DPRINTK(format, arg...) do {} while (0) -#endif - -#ifdef WMT_VT1602_DEBUG_DETAIL -#define DBG_DETAIL(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": [%s]" format "\n" , __FUNCTION__, ## arg) -#else -#define DBG_DETAIL(format, arg...) do {} while (0) -#endif - -#define err(format, arg...) \ - printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) -#define info(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -#define warn(format, arg...) \ - printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) - -/* codec private data */ -struct vt1602_priv { - unsigned int sysclk; - enum snd_soc_control_type control_type; - struct snd_pcm_substream *master_substream; - struct snd_pcm_substream *slave_substream; -}; - -/* - * vt1602 register cache - * We can't read the VT1602 register space when we - * are using 2 wire for device control, so we cache them instead. - */ -static const u16 vt1602_reg[] = { - 0x0050, 0x0050, 0x007f, 0x007f, /* 0 */ - 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */ - 0x0000, 0x0000, 0x00fc, 0x00fc, /* 8 */ - 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */ - 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */ - 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ - 0x0000, 0x0000, 0x0100, 0x0000, /* 32 */ - 0x0000, 0x0100, 0x0050, 0x0050, /* 36 */ - 0x0079, 0x0079, 0x0079, /* 40 */ -}; - -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); - -#define vt1602_reset(c) snd_soc_write(c, VT1602_RESET, 0) - -/* - * VT1602 Controls - */ -static const char *vt1602_bass[] = {"Linear Control", "Adaptive Boost"}; -static const char *vt1602_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; -static const char *vt1602_treble[] = {"8kHz", "4kHz"}; -static const char *vt1602_3d_lc[] = {"200Hz", "500Hz"}; -static const char *vt1602_3d_uc[] = {"2.2kHz", "1.5kHz"}; -static const char *vt1602_3d_func[] = {"Capture", "Playback"}; -static const char *vt1602_alc_func[] = {"Off", "Right", "Left", "Stereo"}; -static const char *vt1602_ng_type[] = {"Constant PGA Gain", - "Mute ADC Output"}; -static const char *vt1602_line_mux[] = {"Line 1", "Line 2", "Line 3", "PGA", - "Differential"}; -static const char *vt1602_pga_sel[] = {"Line 1", "Line 2", "Line 3", - "Differential"}; -static const char *vt1602_out3[] = {"VREF", "ROUT1 + Vol", "MonoOut", - "ROUT1"}; -static const char *vt1602_diff_sel[] = {"Line 1", "Line 2"}; -static const char *vt1602_adcpol[] = {"Normal", "L Invert", "R Invert", - "L + R Invert"}; -static const char *vt1602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const char *vt1602_mono_mux[] = {"Stereo", "Mono (Left)", - "Mono (Right)", "Digital Mono"}; - -static const struct soc_enum vt1602_enum[] = { -SOC_ENUM_SINGLE(VT1602_BASS, 7, 2, vt1602_bass), -SOC_ENUM_SINGLE(VT1602_BASS, 6, 2, vt1602_bass_filter), -SOC_ENUM_SINGLE(VT1602_TREBLE, 6, 2, vt1602_treble), -SOC_ENUM_SINGLE(VT1602_3D, 5, 2, vt1602_3d_lc), -SOC_ENUM_SINGLE(VT1602_3D, 6, 2, vt1602_3d_uc), -SOC_ENUM_SINGLE(VT1602_3D, 7, 2, vt1602_3d_func), -SOC_ENUM_SINGLE(VT1602_ALC1, 7, 4, vt1602_alc_func), -SOC_ENUM_SINGLE(VT1602_NGATE, 1, 2, vt1602_ng_type), -SOC_ENUM_SINGLE(VT1602_LOUTM1, 0, 5, vt1602_line_mux), -SOC_ENUM_SINGLE(VT1602_ROUTM1, 0, 5, vt1602_line_mux), -SOC_ENUM_SINGLE(VT1602_LADCIN, 6, 4, vt1602_pga_sel), /* 10 */ -SOC_ENUM_SINGLE(VT1602_RADCIN, 6, 4, vt1602_pga_sel), -SOC_ENUM_SINGLE(VT1602_ADCTL2, 7, 4, vt1602_out3), -SOC_ENUM_SINGLE(VT1602_ADCIN, 8, 2, vt1602_diff_sel), -SOC_ENUM_SINGLE(VT1602_ADCDAC, 5, 4, vt1602_adcpol), -SOC_ENUM_SINGLE(VT1602_ADCDAC, 1, 4, vt1602_deemph), -SOC_ENUM_SINGLE(VT1602_ADCIN, 6, 4, vt1602_mono_mux), /* 16 */ - -}; - -static const struct snd_kcontrol_new vt1602_snd_controls[] = { - -SOC_DOUBLE_R("Capture Volume", VT1602_LINVOL, VT1602_RINVOL, 0, 63, 0), -SOC_DOUBLE_R("Capture ZC Switch", VT1602_LINVOL, VT1602_RINVOL, 6, 1, 0), -SOC_DOUBLE_R("Capture Switch", VT1602_LINVOL, VT1602_RINVOL, 7, 1, 1), - -SOC_DOUBLE_R("Headphone Playback ZC Switch", VT1602_LOUT1V, - VT1602_ROUT1V, 7, 1, 0), -SOC_DOUBLE_R("Speaker Playback ZC Switch", VT1602_LOUT2V, - VT1602_ROUT2V, 7, 1, 0), - -SOC_ENUM("Playback De-emphasis", vt1602_enum[15]), - -SOC_ENUM("Capture Polarity", vt1602_enum[14]), -SOC_SINGLE("Playback 6dB Attenuate", VT1602_ADCDAC, 7, 1, 0), -SOC_SINGLE("Capture 6dB Attenuate", VT1602_ADCDAC, 8, 1, 0), - -SOC_DOUBLE_R("Master Volume", VT1602_LOUT1V, VT1602_ROUT1V, 0, 127, 0), -//SOC_DOUBLE_R("PCM Volume", VT1602_LOUT1V, VT1602_ROUT1V, 0, 127, 0), - -/* -SOC_ENUM("Bass Boost", vt1602_enum[0]), -SOC_ENUM("Bass Filter", vt1602_enum[1]), -SOC_SINGLE("Bass Volume", VT1602_BASS, 0, 15, 1), - -SOC_SINGLE("Treble Volume", VT1602_TREBLE, 0, 15, 0), -SOC_ENUM("Treble Cut-off", vt1602_enum[2]), - -SOC_SINGLE("3D Switch", VT1602_3D, 0, 1, 0), -SOC_SINGLE("3D Volume", VT1602_3D, 1, 15, 0), -SOC_ENUM("3D Lower Cut-off", vt1602_enum[3]), -SOC_ENUM("3D Upper Cut-off", vt1602_enum[4]), -SOC_ENUM("3D Mode", vt1602_enum[5]), - -SOC_SINGLE("ALC Capture Target Volume", VT1602_ALC1, 0, 7, 0), -SOC_SINGLE("ALC Capture Max Volume", VT1602_ALC1, 4, 7, 0), -SOC_ENUM("ALC Capture Function", vt1602_enum[6]), -SOC_SINGLE("ALC Capture ZC Switch", VT1602_ALC2, 7, 1, 0), -SOC_SINGLE("ALC Capture Hold Time", VT1602_ALC2, 0, 15, 0), -SOC_SINGLE("ALC Capture Decay Time", VT1602_ALC3, 4, 15, 0), -SOC_SINGLE("ALC Capture Attack Time", VT1602_ALC3, 0, 15, 0), -SOC_SINGLE("ALC Capture NG Threshold", VT1602_NGATE, 3, 31, 0), -SOC_ENUM("ALC Capture NG Type", vt1602_enum[4]), -SOC_SINGLE("ALC Capture NG Switch", VT1602_NGATE, 0, 1, 0), -*/ - -SOC_SINGLE("Left ADC Capture Volume", VT1602_LADC, 0, 255, 0), -SOC_SINGLE("Right ADC Capture Volume", VT1602_RADC, 0, 255, 0), - -SOC_SINGLE("ZC Timeout Switch", VT1602_ADCTL1, 0, 1, 0), -SOC_SINGLE("Playback Invert Switch", VT1602_ADCTL1, 1, 1, 0), - -SOC_SINGLE("Right Speaker Playback Invert Switch", VT1602_ADCTL2, 4, 1, 0), - -/* Unimplemented */ -/* ADCDAC Bit 0 - ADCHPD */ -/* ADCDAC Bit 4 - HPOR */ -/* ADCTL1 Bit 2,3 - DATSEL */ -/* ADCTL1 Bit 4,5 - DMONOMIX */ -/* ADCTL1 Bit 6,7 - VSEL */ -/* ADCTL2 Bit 2 - LRCM */ -/* ADCTL2 Bit 3 - TRI */ -/* ADCTL3 Bit 5 - HPFLREN */ -/* ADCTL3 Bit 6 - VROI */ -/* ADCTL3 Bit 7,8 - ADCLRM */ -/* ADCIN Bit 4 - LDCM */ -/* ADCIN Bit 5 - RDCM */ - -SOC_DOUBLE_R("Mic Boost", VT1602_LADCIN, VT1602_RADCIN, 4, 3, 0), - -SOC_DOUBLE_R("Bypass Left Playback Volume", VT1602_LOUTM1, - VT1602_LOUTM2, 4, 7, 1), -SOC_DOUBLE_R("Bypass Right Playback Volume", VT1602_ROUTM1, - VT1602_ROUTM2, 4, 7, 1), -SOC_DOUBLE_R("Bypass Mono Playback Volume", VT1602_MOUTM1, - VT1602_MOUTM2, 4, 7, 1), - -SOC_SINGLE("Mono Playback ZC Switch", VT1602_MOUTV, 7, 1, 0), - -SOC_DOUBLE_R("Headphone Playback Volume", VT1602_LOUT1V, VT1602_ROUT1V, - 0, 127, 0), -SOC_DOUBLE_R("Speaker Playback Volume", VT1602_LOUT2V, VT1602_ROUT2V, - 0, 127, 0), - -SOC_SINGLE("Mono Playback Volume", VT1602_MOUTV, 0, 127, 0), - -}; - -/* - * DAPM Controls - */ - -/* Left Mixer */ -static const struct snd_kcontrol_new vt1602_left_mixer_controls[] = { -SOC_DAPM_SINGLE("Playback Switch", VT1602_LOUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", VT1602_LOUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", VT1602_LOUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", VT1602_LOUTM2, 7, 1, 0), -}; - -/* Right Mixer */ -static const struct snd_kcontrol_new vt1602_right_mixer_controls[] = { -SOC_DAPM_SINGLE("Left Playback Switch", VT1602_ROUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", VT1602_ROUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Playback Switch", VT1602_ROUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", VT1602_ROUTM2, 7, 1, 0), -}; - -/* Mono Mixer */ -static const struct snd_kcontrol_new vt1602_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("Left Playback Switch", VT1602_MOUTM1, 8, 1, 0), -SOC_DAPM_SINGLE("Left Bypass Switch", VT1602_MOUTM1, 7, 1, 0), -SOC_DAPM_SINGLE("Right Playback Switch", VT1602_MOUTM2, 8, 1, 0), -SOC_DAPM_SINGLE("Right Bypass Switch", VT1602_MOUTM2, 7, 1, 0), -}; - -/* Left Line Mux */ -static const struct snd_kcontrol_new vt1602_left_line_controls = -SOC_DAPM_ENUM("Route", vt1602_enum[8]); - -/* Right Line Mux */ -static const struct snd_kcontrol_new vt1602_right_line_controls = -SOC_DAPM_ENUM("Route", vt1602_enum[9]); - -/* Left PGA Mux */ -static const struct snd_kcontrol_new vt1602_left_pga_controls = -SOC_DAPM_ENUM("Route", vt1602_enum[10]); - -/* Right PGA Mux */ -static const struct snd_kcontrol_new vt1602_right_pga_controls = -SOC_DAPM_ENUM("Route", vt1602_enum[11]); - -/* Out 3 Mux */ -static const struct snd_kcontrol_new vt1602_out3_controls = -SOC_DAPM_ENUM("Route", vt1602_enum[12]); - -/* Differential Mux */ -static const struct snd_kcontrol_new vt1602_diffmux_controls = -SOC_DAPM_ENUM("Route", vt1602_enum[13]); - -/* Mono ADC Mux */ -static const struct snd_kcontrol_new vt1602_monomux_controls = -SOC_DAPM_ENUM("Route", vt1602_enum[16]); - -static const struct snd_soc_dapm_widget vt1602_dapm_widgets[] = { - SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0, - &vt1602_left_mixer_controls[0], - ARRAY_SIZE(vt1602_left_mixer_controls)), - SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0, - &vt1602_right_mixer_controls[0], - ARRAY_SIZE(vt1602_right_mixer_controls)), - /* - SND_SOC_DAPM_MIXER("Mono Mixer", VT1602_PWR2, 2, 0, - &vt1602_mono_mixer_controls[0], - ARRAY_SIZE(vt1602_mono_mixer_controls)), - - SND_SOC_DAPM_PGA("Right Out 2", VT1602_PWR2, 3, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 2", VT1602_PWR2, 4, 0, NULL, 0), - SND_SOC_DAPM_PGA("Right Out 1", VT1602_PWR2, 5, 0, NULL, 0), - SND_SOC_DAPM_PGA("Left Out 1", VT1602_PWR2, 6, 0, NULL, 0), - SND_SOC_DAPM_DAC("Right DAC", "Right Playback", VT1602_PWR2, 7, 0), - SND_SOC_DAPM_DAC("Left DAC", "Left Playback", VT1602_PWR2, 8, 0), - */ - /* - SND_SOC_DAPM_MICBIAS("Mic Bias", VT1602_PWR1, 1, 0), - SND_SOC_DAPM_ADC("Right ADC", "Right Capture", VT1602_PWR1, 2, 0), - SND_SOC_DAPM_ADC("Left ADC", "Left Capture", VT1602_PWR1, 3, 0), - - SND_SOC_DAPM_MUX("Left PGA Mux", VT1602_PWR1, 5, 0, - &vt1602_left_pga_controls), - SND_SOC_DAPM_MUX("Right PGA Mux", VT1602_PWR1, 4, 0, - &vt1602_right_pga_controls), - */ - SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0, - &vt1602_left_line_controls), - SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0, - &vt1602_right_line_controls), - - SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &vt1602_out3_controls), - /* - SND_SOC_DAPM_PGA("Out 3", VT1602_PWR2, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("Mono Out 1", VT1602_PWR2, 2, 0, NULL, 0), - */ - - SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, - &vt1602_diffmux_controls), - SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0, - &vt1602_monomux_controls), - SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0, - &vt1602_monomux_controls), - - SND_SOC_DAPM_OUTPUT("LOUT1"), - SND_SOC_DAPM_OUTPUT("ROUT1"), - SND_SOC_DAPM_OUTPUT("LOUT2"), - SND_SOC_DAPM_OUTPUT("ROUT2"), - SND_SOC_DAPM_OUTPUT("MONO1"), - SND_SOC_DAPM_OUTPUT("OUT3"), - SND_SOC_DAPM_OUTPUT("VREF"), - - SND_SOC_DAPM_INPUT("LINPUT1"), - SND_SOC_DAPM_INPUT("LINPUT2"), - SND_SOC_DAPM_INPUT("LINPUT3"), - SND_SOC_DAPM_INPUT("RINPUT1"), - SND_SOC_DAPM_INPUT("RINPUT2"), - SND_SOC_DAPM_INPUT("RINPUT3"), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* left mixer */ - {"Left Mixer", "Playback Switch", "Left DAC"}, - {"Left Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Left Mixer", "Right Playback Switch", "Right DAC"}, - {"Left Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* right mixer */ - {"Right Mixer", "Left Playback Switch", "Left DAC"}, - {"Right Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Right Mixer", "Playback Switch", "Right DAC"}, - {"Right Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* left out 1 */ - {"Left Out 1", NULL, "Left Mixer"}, - {"LOUT1", NULL, "Left Out 1"}, - - /* left out 2 */ - {"Left Out 2", NULL, "Left Mixer"}, - {"LOUT2", NULL, "Left Out 2"}, - - /* right out 1 */ - {"Right Out 1", NULL, "Right Mixer"}, - {"ROUT1", NULL, "Right Out 1"}, - - /* right out 2 */ - {"Right Out 2", NULL, "Right Mixer"}, - {"ROUT2", NULL, "Right Out 2"}, - - /* mono mixer */ - {"Mono Mixer", "Left Playback Switch", "Left DAC"}, - {"Mono Mixer", "Left Bypass Switch", "Left Line Mux"}, - {"Mono Mixer", "Right Playback Switch", "Right DAC"}, - {"Mono Mixer", "Right Bypass Switch", "Right Line Mux"}, - - /* mono out */ - {"Mono Out 1", NULL, "Mono Mixer"}, - {"MONO1", NULL, "Mono Out 1"}, - - /* out 3 */ - {"Out3 Mux", "VREF", "VREF"}, - {"Out3 Mux", "ROUT1 + Vol", "ROUT1"}, - {"Out3 Mux", "ROUT1", "Right Mixer"}, - {"Out3 Mux", "MonoOut", "MONO1"}, - {"Out 3", NULL, "Out3 Mux"}, - {"OUT3", NULL, "Out 3"}, - - /* Left Line Mux */ - {"Left Line Mux", "Line 1", "LINPUT1"}, - {"Left Line Mux", "Line 2", "LINPUT2"}, - {"Left Line Mux", "Line 3", "LINPUT3"}, - {"Left Line Mux", "PGA", "Left PGA Mux"}, - {"Left Line Mux", "Differential", "Differential Mux"}, - - /* Right Line Mux */ - {"Right Line Mux", "Line 1", "RINPUT1"}, - {"Right Line Mux", "Line 2", "RINPUT2"}, - {"Right Line Mux", "Line 3", "RINPUT3"}, - {"Right Line Mux", "PGA", "Right PGA Mux"}, - {"Right Line Mux", "Differential", "Differential Mux"}, - - /* Left PGA Mux */ - {"Left PGA Mux", "Line 1", "LINPUT1"}, - {"Left PGA Mux", "Line 2", "LINPUT2"}, - {"Left PGA Mux", "Line 3", "LINPUT3"}, - {"Left PGA Mux", "Differential", "Differential Mux"}, - - /* Right PGA Mux */ - {"Right PGA Mux", "Line 1", "RINPUT1"}, - {"Right PGA Mux", "Line 2", "RINPUT2"}, - {"Right PGA Mux", "Line 3", "RINPUT3"}, - {"Right PGA Mux", "Differential", "Differential Mux"}, - - /* Differential Mux */ - {"Differential Mux", "Line 1", "LINPUT1"}, - {"Differential Mux", "Line 1", "RINPUT1"}, - {"Differential Mux", "Line 2", "LINPUT2"}, - {"Differential Mux", "Line 2", "RINPUT2"}, - - /* Left ADC Mux */ - {"Left ADC Mux", "Stereo", "Left PGA Mux"}, - {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"}, - {"Left ADC Mux", "Digital Mono", "Left PGA Mux"}, - - /* Right ADC Mux */ - {"Right ADC Mux", "Stereo", "Right PGA Mux"}, - {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"}, - {"Right ADC Mux", "Digital Mono", "Right PGA Mux"}, - - /* ADC */ - {"Left ADC", NULL, "Left ADC Mux"}, - {"Right ADC", NULL, "Right ADC Mux"}, -}; - -struct _coeff_div { - u32 mclk; - u32 rate; - u16 fs; - u8 sr:5; - u8 usb:1; -}; - -/* codec hifi mclk clock divider coefficients */ -static const struct _coeff_div coeff_div[] = { - /* 8k */ - {12288000, 8000, 1536, 0x6, 0x0}, - - /* 11.025k */ - {11289600, 11025, 1024, 0x18, 0x0}, - - /* 16k */ - {12288000, 16000, 768, 0xa, 0x0}, - - /* 22.05k */ - {11289600, 22050, 512, 0x1a, 0x0}, - - /* 32k */ - {12288000, 32000, 384, 0xc, 0x0}, - - /* 44.1k */ - {11289600, 44100, 256, 0x10, 0x0}, - - /* 48k */ - {12288000, 48000, 256, 0x0, 0x0}, - - /* 88.2k */ - {11289600, 88200, 128, 0x1e, 0x0}, - - /* 96k */ - {12288000, 96000, 128, 0xe, 0x0}, -}; - -static inline int get_coeff(int mclk, int rate) -{ - int i; - - DBG_DETAIL("mclk=%d, rate=%d", mclk, rate); - - for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { - if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) - return i; - } - - printk(KERN_ERR "vt1602: could not get coeff for mclk %d @ rate %d\n", - mclk, rate); - return -EINVAL; -} - -static int vt1602_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - u16 iface = snd_soc_read(codec, VT1602_IFACE) & 0x1f3; - //int coeff = get_coeff(vt1602->sysclk, params_rate(params)); - - DBG_DETAIL(); - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0004; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0008; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x000c; - break; - } - - /* set iface & srate */ - snd_soc_write(codec, VT1602_IFACE, iface); - - return 0; -} - -static int vt1602_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, VT1602_ADCDAC) & 0xfff7; - - DBG_DETAIL(); - - if (mute) - snd_soc_write(codec, VT1602_ADCDAC, mute_reg | 0x8); - else - snd_soc_write(codec, VT1602_ADCDAC, mute_reg); - return 0; -} - -static int vt1602_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct vt1602_priv *vt1602 = snd_soc_codec_get_drvdata(codec); - - DBG_DETAIL(); - - switch (freq) { - case 11289600: - case 12000000: - case 12288000: - case 16934400: - case 18432000: - vt1602->sysclk = freq; - return 0; - } - return -EINVAL; -} - -static int vt1602_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - - DBG_DETAIL(); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - iface = 0x0040; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0090; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0080; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0010; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, VT1602_IFACE, iface); - return 0; -} - -static int vt1602_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level ) -{ - DBG_DETAIL(); - - switch (level) { - case SND_SOC_BIAS_ON: - /* set vmid to 50k and unmute dac */ - break; - case SND_SOC_BIAS_PREPARE: - /* set vmid to 5k for quick power up */ - break; - case SND_SOC_BIAS_STANDBY: - /* mute dac and set vmid to 500k, enable VREF */ - break; - case SND_SOC_BIAS_OFF: - break; - } - codec->dapm.bias_level = level; - return 0; -} - -static void vt1602_work(struct work_struct *work) -{ - struct snd_soc_codec *codec = - container_of(work, struct snd_soc_codec, dapm.delayed_work.work); - - DBG_DETAIL(); - - vt1602_set_bias_level(codec, codec->dapm.bias_level); -} - -#define VT1602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | \ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ - SNDRV_PCM_RATE_96000) - -#define VT1602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_FLOAT) - -static const struct snd_soc_dai_ops vt1602_dai_ops = { - .hw_params = vt1602_pcm_hw_params, - .digital_mute = vt1602_mute, - .set_sysclk = vt1602_set_dai_sysclk, - .set_fmt = vt1602_set_dai_fmt, -}; - -struct snd_soc_dai_driver vt1602_dai = { - .name = "VT1602", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = VT1602_RATES, - .formats = VT1602_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = VT1602_RATES, - .formats = VT1602_FORMATS,}, - .ops = &vt1602_dai_ops, -}; - -static int vt1602_suspend(struct snd_soc_codec *codec) -{ - DBG_DETAIL(); - - vt1602_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int vt1602_resume(struct snd_soc_codec *codec) -{ - DBG_DETAIL(); - - snd_soc_cache_sync(codec); - vt1602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* charge vt1602 caps */ - if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { - vt1602_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - codec->dapm.bias_level = SND_SOC_BIAS_ON; - schedule_delayed_work(&codec->dapm.delayed_work, - msecs_to_jiffies(1000)); - } - - return 0; -} - -static int wmt_vt1602_init(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret, reg; - - DBG_DETAIL(); - - /* charge output caps */ - vt1602_set_bias_level(codec, SND_SOC_BIAS_PREPARE); - codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; - schedule_delayed_work(&codec->dapm.delayed_work, msecs_to_jiffies(1000)); - - /* set the update bits */ - reg = snd_soc_read(codec, VT1602_LDAC); - snd_soc_write(codec, VT1602_LDAC, reg | 0x0100); - reg = snd_soc_read(codec, VT1602_RDAC); - snd_soc_write(codec, VT1602_RDAC, reg | 0x0100); - reg = snd_soc_read(codec, VT1602_LOUT1V); - snd_soc_write(codec, VT1602_LOUT1V, reg | 0x0100); - reg = snd_soc_read(codec, VT1602_ROUT1V); - snd_soc_write(codec, VT1602_ROUT1V, reg | 0x0100); - reg = snd_soc_read(codec, VT1602_LOUT2V); - snd_soc_write(codec, VT1602_LOUT2V, reg | 0x0100); - reg = snd_soc_read(codec, VT1602_ROUT2V); - snd_soc_write(codec, VT1602_ROUT2V, reg | 0x0100); - reg = snd_soc_read(codec, VT1602_LINVOL); - snd_soc_write(codec, VT1602_LINVOL, reg | 0x0100); - reg = snd_soc_read(codec, VT1602_RINVOL); - snd_soc_write(codec, VT1602_RINVOL, reg | 0x0100); - reg = snd_soc_read(codec, VT1602_LOUTM1); - snd_soc_write(codec, VT1602_LOUTM1, reg); - reg = snd_soc_read(codec, VT1602_LOUTM2); - snd_soc_write(codec, VT1602_LOUTM2, reg); - reg = snd_soc_read(codec, VT1602_ROUTM1); - snd_soc_write(codec, VT1602_ROUTM1, reg); - reg = snd_soc_read(codec, VT1602_ROUTM2); - snd_soc_write(codec, VT1602_ROUTM2, reg); - snd_soc_write(codec, VT1602_PWR1, 0x1FE); - snd_soc_write(codec, VT1602_PWR2, 0x1E0); - snd_soc_write(codec, VT1602_LADCIN, 0x020); - snd_soc_write(codec, VT1602_RADCIN, 0x020); - snd_soc_write(codec, VT1602_ADCTL3, 0x040); - - ret = snd_soc_add_codec_controls(codec, vt1602_snd_controls, - ARRAY_SIZE(vt1602_snd_controls)); - if (ret) { - info("snd_soc_add_codec_controls fail"); - return ret; - } - - ret = snd_soc_dapm_new_controls(dapm, vt1602_dapm_widgets, - ARRAY_SIZE(vt1602_dapm_widgets)); - if (ret) { - info("snd_soc_dapm_new_controls fail"); - return ret; - } - - ret = snd_soc_dapm_add_routes(dapm, audio_map, - ARRAY_SIZE(audio_map)); - if (ret) { - info("snd_soc_dapm_add_routes fail"); - return 0; - } - - return ret; -} - -static int vt1602_probe(struct snd_soc_codec *codec) -{ - struct vt1602_priv *vt1602 = snd_soc_codec_get_drvdata(codec); - int ret; - - pr_info("VT1602 Audio Codec %s\n", VT1602_VERSION); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, vt1602->control_type); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - ret = vt1602_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - return ret; - } - - INIT_DELAYED_WORK(&codec->dapm.delayed_work, vt1602_work); - - ret = wmt_vt1602_init(codec); - if (ret) - info("vt1602_probe fail"); - return ret; -} - -/* - * This function forces any delayed work to be queued and run. - */ -static int run_delayed_work(struct delayed_work *dwork) -{ - int ret; - - DBG_DETAIL(); - - /* cancel any work waiting to be queued. */ - ret = cancel_delayed_work(dwork); - - /* if there was any work waiting then we run it now and - * wait for it's completion */ - if (ret) { - schedule_delayed_work(dwork, 0); - flush_scheduled_work(); - } - return ret; -} - -/* remove everything here */ -static int vt1602_remove(struct snd_soc_codec *codec) -{ - DBG_DETAIL(); - - vt1602_set_bias_level(codec, SND_SOC_BIAS_OFF); - run_delayed_work(&codec->dapm.delayed_work); - - return 0; -} - -static struct snd_soc_codec_driver soc_codec_dev_vt1602 = { - .probe = vt1602_probe, - .remove = vt1602_remove, - .suspend = vt1602_suspend, - .resume = vt1602_resume, - .set_bias_level = vt1602_set_bias_level, - .reg_cache_size = ARRAY_SIZE(vt1602_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = vt1602_reg, - - /*.controls = vt1602_snd_controls, - .num_controls = ARRAY_SIZE(vt1602_snd_controls), - .dapm_widgets = vt1602_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(vt1602_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map),*/ -}; - -#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) -static int __devinit vt1602_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct vt1602_priv *vt1602; - int ret; - - DBG_DETAIL(); - - vt1602 = devm_kzalloc(&i2c->dev, sizeof(struct vt1602_priv), GFP_KERNEL); - if (vt1602 == NULL) { - info("vt1602_i2c_probe kzalloc fail"); - return -ENOMEM; - } - - i2c_set_clientdata(i2c, vt1602); - vt1602->control_type = SND_SOC_I2C; - - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_vt1602, &vt1602_dai, 1); - - return ret; -} - -static int __devexit vt1602_i2c_remove(struct i2c_client *client) -{ - DBG_DETAIL(); - - snd_soc_unregister_codec(&client->dev); - - return 0; -} - -static const struct i2c_device_id vt1602_i2c_id[] = { - { "vt1602", 1}, - { } -}; -MODULE_DEVICE_TABLE(i2c, vt1602_i2c_id); - -/* corgi i2c codec control layer */ -static struct i2c_driver vt1602_i2c_driver = { - .driver = { - .name = "vt1602", - .owner = THIS_MODULE, - }, - .probe = vt1602_i2c_probe, - .remove = __devexit_p(vt1602_i2c_remove), - .id_table = vt1602_i2c_id, -}; -#endif - -static struct i2c_board_info __initdata wmt_vt1602_board_info[] = { - { - I2C_BOARD_INFO("vt1602", 0x1a), - }, -}; - -static int __init vt1602_modinit(void) -{ - char buf[80]; - int varlen = 80; - int ret = 0; - char codec_name[6]; - struct i2c_adapter *adapter = NULL; - - DBG_DETAIL(); - - ret = wmt_getsyspara("wmt.audio.i2s", buf, &varlen); - - if (ret == 0) { - sscanf(buf, "%6s", codec_name); - - if (strcmp(codec_name, "vt1602")) { - info("vt1602 string not found"); - return -EINVAL; - } - } - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - /*i2c_register_board_info(1, wmt_vt1602_board_info, - ARRAY_SIZE(wmt_vt1602_board_info));*/ - - adapter = i2c_get_adapter(1); - if (adapter == NULL) { - err("can not get i2c adapter, client address error"); - return -ENODEV; - } - - if (i2c_new_device(adapter, wmt_vt1602_board_info) == NULL) { - err("allocate i2c client failed"); - return -ENOMEM; - } - - i2c_put_adapter(adapter); - - ret = i2c_add_driver(&vt1602_i2c_driver); - if (ret) { - info("i2c_add_driver fail"); - } -#endif - - return ret; -} -module_init(vt1602_modinit); - -static void __exit vt1602_exit(void) -{ - DBG_DETAIL(); - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&vt1602_i2c_driver); -#endif -} -module_exit(vt1602_exit); - -MODULE_DESCRIPTION("WMT [ALSA SoC] driver"); -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.h b/ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.h deleted file mode 100755 index 718c822a..00000000 --- a/ANDROID_3.4.5/sound/soc/codecs/wmt_vt1602.h +++ /dev/null @@ -1,67 +0,0 @@ -/*++ - * linux/sound/soc/codecs/wmt_vt1602.h - * WonderMedia I2S audio driver for ALSA - * - * Copyright c 2010 WonderMedia Technologies, Inc. - * - * 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, see . - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ - - -#ifndef _VT1602_H -#define _VT1602_H - -/* VT1602 register space */ - -#define VT1602_LINVOL 0x00 -#define VT1602_RINVOL 0x01 -#define VT1602_LOUT1V 0x02 -#define VT1602_ROUT1V 0x03 -#define VT1602_ADCDAC 0x05 -#define VT1602_IFACE 0x07 -#define VT1602_SRATE 0x08 -#define VT1602_LDAC 0x0a -#define VT1602_RDAC 0x0b -#define VT1602_BASS 0x0c -#define VT1602_TREBLE 0x0d -#define VT1602_RESET 0x0f -#define VT1602_3D 0x10 -#define VT1602_ALC1 0x11 -#define VT1602_ALC2 0x12 -#define VT1602_ALC3 0x13 -#define VT1602_NGATE 0x14 -#define VT1602_LADC 0x15 -#define VT1602_RADC 0x16 -#define VT1602_ADCTL1 0x17 -#define VT1602_ADCTL2 0x18 -#define VT1602_PWR1 0x19 -#define VT1602_PWR2 0x1a -#define VT1602_ADCTL3 0x1b -#define VT1602_ADCIN 0x1f -#define VT1602_LADCIN 0x20 -#define VT1602_RADCIN 0x21 -#define VT1602_LOUTM1 0x22 -#define VT1602_LOUTM2 0x23 -#define VT1602_ROUTM1 0x24 -#define VT1602_ROUTM2 0x25 -#define VT1602_MOUTM1 0x26 -#define VT1602_MOUTM2 0x27 -#define VT1602_LOUT2V 0x28 -#define VT1602_ROUT2V 0x29 -#define VT1602_MOUTV 0x2a - -#endif diff --git a/ANDROID_3.4.5/sound/soc/davinci/Kconfig b/ANDROID_3.4.5/sound/soc/davinci/Kconfig deleted file mode 100644 index 9e11a14d..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/Kconfig +++ /dev/null @@ -1,85 +0,0 @@ -config SND_DAVINCI_SOC - tristate "SoC Audio for the TI DAVINCI chip" - depends on ARCH_DAVINCI - help - Say Y or M if you want to add support for codecs attached to - the DAVINCI AC97 or I2S interface. You will also need - to select the audio interfaces to support below. - -config SND_DAVINCI_SOC_I2S - tristate - -config SND_DAVINCI_SOC_MCASP - tristate - -config SND_DAVINCI_SOC_VCIF - tristate - -config SND_DAVINCI_SOC_EVM - tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" - depends on SND_DAVINCI_SOC - depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM - select SND_DAVINCI_SOC_I2S - select SND_SOC_TLV320AIC3X - help - Say Y if you want to add support for SoC audio on TI - DaVinci DM6446, DM355 or DM365 EVM platforms. - -choice - prompt "DM365 codec select" - depends on SND_DAVINCI_SOC_EVM - depends on MACH_DAVINCI_DM365_EVM - -config SND_DM365_AIC3X_CODEC - bool "Audio Codec - AIC3101" - help - Say Y if you want to add support for AIC3101 audio codec - -config SND_DM365_VOICE_CODEC - bool "Voice Codec - CQ93VC" - select MFD_DAVINCI_VOICECODEC - select SND_DAVINCI_SOC_VCIF - select SND_SOC_CQ0093VC - help - Say Y if you want to add support for SoC On-chip voice codec -endchoice - -config SND_DM6467_SOC_EVM - tristate "SoC Audio support for DaVinci DM6467 EVM" - depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM - select SND_DAVINCI_SOC_MCASP - select SND_SOC_TLV320AIC3X - select SND_SOC_SPDIF - - help - Say Y if you want to add support for SoC audio on TI - -config SND_DAVINCI_SOC_SFFSDR - tristate "SoC Audio support for SFFSDR" - depends on SND_DAVINCI_SOC && MACH_SFFSDR - select SND_DAVINCI_SOC_I2S - select SND_SOC_PCM3008 - select SFFSDR_FPGA - help - Say Y if you want to add support for SoC audio on - Lyrtech SFFSDR board. - -config SND_DA830_SOC_EVM - tristate "SoC Audio support for DA830/OMAP-L137 EVM" - depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM - select SND_DAVINCI_SOC_MCASP - select SND_SOC_TLV320AIC3X - - help - Say Y if you want to add support for SoC audio on TI - DA830/OMAP-L137 EVM - -config SND_DA850_SOC_EVM - tristate "SoC Audio support for DA850/OMAP-L138 EVM" - depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM - select SND_DAVINCI_SOC_MCASP - select SND_SOC_TLV320AIC3X - help - Say Y if you want to add support for SoC audio on TI - DA850/OMAP-L138 EVM - diff --git a/ANDROID_3.4.5/sound/soc/davinci/Makefile b/ANDROID_3.4.5/sound/soc/davinci/Makefile deleted file mode 100644 index a93679d6..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# DAVINCI Platform Support -snd-soc-davinci-objs := davinci-pcm.o -snd-soc-davinci-i2s-objs := davinci-i2s.o -snd-soc-davinci-mcasp-objs:= davinci-mcasp.o -snd-soc-davinci-vcif-objs:= davinci-vcif.o - -obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o -obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o -obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o -obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o - -# DAVINCI Machine Support -snd-soc-evm-objs := davinci-evm.o -snd-soc-sffsdr-objs := davinci-sffsdr.o - -obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o -obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o -obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o -obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o -obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-evm.c b/ANDROID_3.4.5/sound/soc/davinci/davinci-evm.c deleted file mode 100644 index 10a2d8c7..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-evm.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * ASoC driver for TI DAVINCI EVM platform - * - * Author: Vladimir Barinov, - * Copyright: (C) 2007 MontaVista Software, Inc., - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "davinci-pcm.h" -#include "davinci-i2s.h" -#include "davinci-mcasp.h" - -#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ - SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) -static int evm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret = 0; - unsigned sysclk; - - /* ASP1 on DM355 EVM is clocked by an external oscillator */ - if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() || - machine_is_davinci_dm365_evm()) - sysclk = 27000000; - - /* ASP0 in DM6446 EVM is clocked by U55, as configured by - * board-dm644x-evm.c using GPIOs from U18. There are six - * options; here we "know" we use a 48 KHz sample rate. - */ - else if (machine_is_davinci_evm()) - sysclk = 12288000; - - else if (machine_is_davinci_da830_evm() || - machine_is_davinci_da850_evm()) - sysclk = 24576000; - - else - return -EINVAL; - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); - if (ret < 0) - return ret; - - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); - if (ret < 0) - return ret; - - /* set the codec system clock */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); - if (ret < 0) - return ret; - - return 0; -} - -static int evm_spdif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - - /* set cpu DAI configuration */ - return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); -} - -static struct snd_soc_ops evm_ops = { - .hw_params = evm_hw_params, -}; - -static struct snd_soc_ops evm_spdif_ops = { - .hw_params = evm_spdif_hw_params, -}; - -/* davinci-evm machine dapm widgets */ -static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), -}; - -/* davinci-evm machine audio_mapnections to the codec pins */ -static const struct snd_soc_dapm_route audio_map[] = { - /* Headphone connected to HPLOUT, HPROUT */ - {"Headphone Jack", NULL, "HPLOUT"}, - {"Headphone Jack", NULL, "HPROUT"}, - - /* Line Out connected to LLOUT, RLOUT */ - {"Line Out", NULL, "LLOUT"}, - {"Line Out", NULL, "RLOUT"}, - - /* Mic connected to (MIC3L | MIC3R) */ - {"MIC3L", NULL, "Mic Bias 2V"}, - {"MIC3R", NULL, "Mic Bias 2V"}, - {"Mic Bias 2V", NULL, "Mic Jack"}, - - /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */ - {"LINE1L", NULL, "Line In"}, - {"LINE2L", NULL, "Line In"}, - {"LINE1R", NULL, "Line In"}, - {"LINE2R", NULL, "Line In"}, -}; - -/* Logic for a aic3x as connected on a davinci-evm */ -static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* Add davinci-evm specific widgets */ - snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, - ARRAY_SIZE(aic3x_dapm_widgets)); - - /* Set up davinci-evm specific audio path audio_map */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - /* not connected */ - snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); - snd_soc_dapm_disable_pin(dapm, "HPLCOM"); - snd_soc_dapm_disable_pin(dapm, "HPRCOM"); - - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Line Out"); - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Line In"); - - return 0; -} - -/* davinci-evm digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link dm6446_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-pcm-audio", - .init = evm_aic3x_init, - .ops = &evm_ops, -}; - -static struct snd_soc_dai_link dm355_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp.1", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-001b", - .platform_name = "davinci-pcm-audio", - .init = evm_aic3x_init, - .ops = &evm_ops, -}; - -static struct snd_soc_dai_link dm365_evm_dai = { -#ifdef CONFIG_SND_DM365_AIC3X_CODEC - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcbsp", - .codec_dai_name = "tlv320aic3x-hifi", - .init = evm_aic3x_init, - .codec_name = "tlv320aic3x-codec.1-0018", - .ops = &evm_ops, -#elif defined(CONFIG_SND_DM365_VOICE_CODEC) - .name = "Voice Codec - CQ93VC", - .stream_name = "CQ93", - .cpu_dai_name = "davinci-vcif", - .codec_dai_name = "cq93vc-hifi", - .codec_name = "cq93vc-codec", -#endif - .platform_name = "davinci-pcm-audio", -}; - -static struct snd_soc_dai_link dm6467_evm_dai[] = { - { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name= "davinci-mcasp.0", - .codec_dai_name = "tlv320aic3x-hifi", - .platform_name ="davinci-pcm-audio", - .codec_name = "tlv320aic3x-codec.0-001a", - .init = evm_aic3x_init, - .ops = &evm_ops, - }, - { - .name = "McASP", - .stream_name = "spdif", - .cpu_dai_name= "davinci-mcasp.1", - .codec_dai_name = "dit-hifi", - .codec_name = "spdif_dit", - .platform_name = "davinci-pcm-audio", - .ops = &evm_spdif_ops, - }, -}; - -static struct snd_soc_dai_link da830_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcasp.1", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-pcm-audio", - .init = evm_aic3x_init, - .ops = &evm_ops, -}; - -static struct snd_soc_dai_link da850_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai_name= "davinci-mcasp.0", - .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.1-0018", - .platform_name = "davinci-pcm-audio", - .init = evm_aic3x_init, - .ops = &evm_ops, -}; - -/* davinci dm6446 evm audio machine driver */ -static struct snd_soc_card dm6446_snd_soc_card_evm = { - .name = "DaVinci DM6446 EVM", - .owner = THIS_MODULE, - .dai_link = &dm6446_evm_dai, - .num_links = 1, -}; - -/* davinci dm355 evm audio machine driver */ -static struct snd_soc_card dm355_snd_soc_card_evm = { - .name = "DaVinci DM355 EVM", - .owner = THIS_MODULE, - .dai_link = &dm355_evm_dai, - .num_links = 1, -}; - -/* davinci dm365 evm audio machine driver */ -static struct snd_soc_card dm365_snd_soc_card_evm = { - .name = "DaVinci DM365 EVM", - .owner = THIS_MODULE, - .dai_link = &dm365_evm_dai, - .num_links = 1, -}; - -/* davinci dm6467 evm audio machine driver */ -static struct snd_soc_card dm6467_snd_soc_card_evm = { - .name = "DaVinci DM6467 EVM", - .owner = THIS_MODULE, - .dai_link = dm6467_evm_dai, - .num_links = ARRAY_SIZE(dm6467_evm_dai), -}; - -static struct snd_soc_card da830_snd_soc_card = { - .name = "DA830/OMAP-L137 EVM", - .owner = THIS_MODULE, - .dai_link = &da830_evm_dai, - .num_links = 1, -}; - -static struct snd_soc_card da850_snd_soc_card = { - .name = "DA850/OMAP-L138 EVM", - .owner = THIS_MODULE, - .dai_link = &da850_evm_dai, - .num_links = 1, -}; - -static struct platform_device *evm_snd_device; - -static int __init evm_init(void) -{ - struct snd_soc_card *evm_snd_dev_data; - int index; - int ret; - - if (machine_is_davinci_evm()) { - evm_snd_dev_data = &dm6446_snd_soc_card_evm; - index = 0; - } else if (machine_is_davinci_dm355_evm()) { - evm_snd_dev_data = &dm355_snd_soc_card_evm; - index = 1; - } else if (machine_is_davinci_dm365_evm()) { - evm_snd_dev_data = &dm365_snd_soc_card_evm; - index = 0; - } else if (machine_is_davinci_dm6467_evm()) { - evm_snd_dev_data = &dm6467_snd_soc_card_evm; - index = 0; - } else if (machine_is_davinci_da830_evm()) { - evm_snd_dev_data = &da830_snd_soc_card; - index = 1; - } else if (machine_is_davinci_da850_evm()) { - evm_snd_dev_data = &da850_snd_soc_card; - index = 0; - } else - return -EINVAL; - - evm_snd_device = platform_device_alloc("soc-audio", index); - if (!evm_snd_device) - return -ENOMEM; - - platform_set_drvdata(evm_snd_device, evm_snd_dev_data); - ret = platform_device_add(evm_snd_device); - if (ret) - platform_device_put(evm_snd_device); - - return ret; -} - -static void __exit evm_exit(void) -{ - platform_device_unregister(evm_snd_device); -} - -module_init(evm_init); -module_exit(evm_exit); - -MODULE_AUTHOR("Vladimir Barinov"); -MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.c b/ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.c deleted file mode 100644 index 0a74b958..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor - * - * Author: Vladimir Barinov, - * Copyright: (C) 2007 MontaVista Software, Inc., - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "davinci-pcm.h" -#include "davinci-i2s.h" - - -/* - * NOTE: terminology here is confusing. - * - * - This driver supports the "Audio Serial Port" (ASP), - * found on dm6446, dm355, and other DaVinci chips. - * - * - But it labels it a "Multi-channel Buffered Serial Port" - * (McBSP) as on older chips like the dm642 ... which was - * backward-compatible, possibly explaining that confusion. - * - * - OMAP chips have a controller called McBSP, which is - * incompatible with the DaVinci flavor of McBSP. - * - * - Newer DaVinci chips have a controller called McASP, - * incompatible with ASP and with either McBSP. - * - * In short: this uses ASP to implement I2S, not McBSP. - * And it won't be the only DaVinci implemention of I2S. - */ -#define DAVINCI_MCBSP_DRR_REG 0x00 -#define DAVINCI_MCBSP_DXR_REG 0x04 -#define DAVINCI_MCBSP_SPCR_REG 0x08 -#define DAVINCI_MCBSP_RCR_REG 0x0c -#define DAVINCI_MCBSP_XCR_REG 0x10 -#define DAVINCI_MCBSP_SRGR_REG 0x14 -#define DAVINCI_MCBSP_PCR_REG 0x24 - -#define DAVINCI_MCBSP_SPCR_RRST (1 << 0) -#define DAVINCI_MCBSP_SPCR_RINTM(v) ((v) << 4) -#define DAVINCI_MCBSP_SPCR_XRST (1 << 16) -#define DAVINCI_MCBSP_SPCR_XINTM(v) ((v) << 20) -#define DAVINCI_MCBSP_SPCR_GRST (1 << 22) -#define DAVINCI_MCBSP_SPCR_FRST (1 << 23) -#define DAVINCI_MCBSP_SPCR_FREE (1 << 25) - -#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5) -#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8) -#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) -#define DAVINCI_MCBSP_RCR_RFIG (1 << 18) -#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) -#define DAVINCI_MCBSP_RCR_RFRLEN2(v) ((v) << 24) -#define DAVINCI_MCBSP_RCR_RPHASE BIT(31) - -#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) -#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8) -#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16) -#define DAVINCI_MCBSP_XCR_XFIG (1 << 18) -#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21) -#define DAVINCI_MCBSP_XCR_XFRLEN2(v) ((v) << 24) -#define DAVINCI_MCBSP_XCR_XPHASE BIT(31) - -#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8) -#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16) -#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28) -#define DAVINCI_MCBSP_SRGR_CLKSM BIT(29) - -#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0) -#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1) -#define DAVINCI_MCBSP_PCR_FSRP (1 << 2) -#define DAVINCI_MCBSP_PCR_FSXP (1 << 3) -#define DAVINCI_MCBSP_PCR_SCLKME (1 << 7) -#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8) -#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9) -#define DAVINCI_MCBSP_PCR_FSRM (1 << 10) -#define DAVINCI_MCBSP_PCR_FSXM (1 << 11) - -enum { - DAVINCI_MCBSP_WORD_8 = 0, - DAVINCI_MCBSP_WORD_12, - DAVINCI_MCBSP_WORD_16, - DAVINCI_MCBSP_WORD_20, - DAVINCI_MCBSP_WORD_24, - DAVINCI_MCBSP_WORD_32, -}; - -static const unsigned char data_type[SNDRV_PCM_FORMAT_S32_LE + 1] = { - [SNDRV_PCM_FORMAT_S8] = 1, - [SNDRV_PCM_FORMAT_S16_LE] = 2, - [SNDRV_PCM_FORMAT_S32_LE] = 4, -}; - -static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = { - [SNDRV_PCM_FORMAT_S8] = DAVINCI_MCBSP_WORD_8, - [SNDRV_PCM_FORMAT_S16_LE] = DAVINCI_MCBSP_WORD_16, - [SNDRV_PCM_FORMAT_S32_LE] = DAVINCI_MCBSP_WORD_32, -}; - -static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = { - [SNDRV_PCM_FORMAT_S8] = SNDRV_PCM_FORMAT_S16_LE, - [SNDRV_PCM_FORMAT_S16_LE] = SNDRV_PCM_FORMAT_S32_LE, -}; - -struct davinci_mcbsp_dev { - struct device *dev; - struct davinci_pcm_dma_params dma_params[2]; - void __iomem *base; -#define MOD_DSP_A 0 -#define MOD_DSP_B 1 - int mode; - u32 pcr; - struct clk *clk; - /* - * Combining both channels into 1 element will at least double the - * amount of time between servicing the dma channel, increase - * effiency, and reduce the chance of overrun/underrun. But, - * it will result in the left & right channels being swapped. - * - * If relabeling the left and right channels is not possible, - * you may want to let the codec know to swap them back. - * - * It may allow x10 the amount of time to service dma requests, - * if the codec is master and is using an unnecessarily fast bit clock - * (ie. tlvaic23b), independent of the sample rate. So, having an - * entire frame at once means it can be serviced at the sample rate - * instead of the bit clock rate. - * - * In the now unlikely case that an underrun still - * occurs, both the left and right samples will be repeated - * so that no pops are heard, and the left and right channels - * won't end up being swapped because of the underrun. - */ - unsigned enable_channel_combine:1; - - unsigned int fmt; - int clk_div; - int clk_input_pin; - bool i2s_accurate_sck; -}; - -static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, - int reg, u32 val) -{ - __raw_writel(val, dev->base + reg); -} - -static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg) -{ - return __raw_readl(dev->base + reg); -} - -static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback) -{ - u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP; - /* The clock needs to toggle to complete reset. - * So, fake it by toggling the clk polarity. - */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m); - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr); -} - -static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, - struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_platform *platform = rtd->platform; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - u32 spcr; - u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - if (spcr & mask) { - /* start off disabled */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, - spcr & ~mask); - toggle_clock(dev, playback); - } - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | - DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { - /* Start the sample generator */ - spcr |= DAVINCI_MCBSP_SPCR_GRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } - - if (playback) { - /* Stop the DMA to avoid data loss */ - /* while the transmitter is out of reset to handle XSYNCERR */ - if (platform->driver->ops->trigger) { - int ret = platform->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_STOP); - if (ret < 0) - printk(KERN_DEBUG "Playback DMA stop failed\n"); - } - - /* Enable the transmitter */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - - /* wait for any unexpected frame sync error to occur */ - udelay(100); - - /* Disable the transmitter to clear any outstanding XSYNCERR */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); - - /* Restart the DMA */ - if (platform->driver->ops->trigger) { - int ret = platform->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_START); - if (ret < 0) - printk(KERN_DEBUG "Playback DMA start failed\n"); - } - } - - /* Enable transmitter or receiver */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= mask; - - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) { - /* Start frame sync */ - spcr |= DAVINCI_MCBSP_SPCR_FRST; - } - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); -} - -static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) -{ - u32 spcr; - - /* Reset transmitter/receiver and sample rate/frame sync generators */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST); - spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); -} - -#define DEFAULT_BITPERSAMPLE 16 - -static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - unsigned int pcr; - unsigned int srgr; - bool inv_fs = false; - /* Attention srgr is updated by hw_params! */ - srgr = DAVINCI_MCBSP_SRGR_FSGM | - DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | - DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); - - dev->fmt = fmt; - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* cpu is master */ - pcr = DAVINCI_MCBSP_PCR_FSXM | - DAVINCI_MCBSP_PCR_FSRM | - DAVINCI_MCBSP_PCR_CLKXM | - DAVINCI_MCBSP_PCR_CLKRM; - break; - case SND_SOC_DAIFMT_CBM_CFS: - pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; - /* - * Selection of the clock input pin that is the - * input for the Sample Rate Generator. - * McBSP FSR and FSX are driven by the Sample Rate - * Generator. - */ - switch (dev->clk_input_pin) { - case MCBSP_CLKS: - pcr |= DAVINCI_MCBSP_PCR_CLKXM | - DAVINCI_MCBSP_PCR_CLKRM; - break; - case MCBSP_CLKR: - pcr |= DAVINCI_MCBSP_PCR_SCLKME; - break; - default: - dev_err(dev->dev, "bad clk_input_pin\n"); - return -EINVAL; - } - - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* codec is master */ - pcr = 0; - break; - default: - printk(KERN_ERR "%s:bad master\n", __func__); - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - /* Davinci doesn't support TRUE I2S, but some codecs will have - * the left and right channels contiguous. This allows - * dsp_a mode to be used with an inverted normal frame clk. - * If your codec is master and does not have contiguous - * channels, then you will have sound on only one channel. - * Try using a different mode, or codec as slave. - * - * The TLV320AIC33 is an example of a codec where this works. - * It has a variable bit clock frequency allowing it to have - * valid data on every bit clock. - * - * The TLV320AIC23 is an example of a codec where this does not - * work. It has a fixed bit clock frequency with progressively - * more empty bit clock slots between channels as the sample - * rate is lowered. - */ - inv_fs = true; - case SND_SOC_DAIFMT_DSP_A: - dev->mode = MOD_DSP_A; - break; - case SND_SOC_DAIFMT_DSP_B: - dev->mode = MOD_DSP_B; - break; - default: - printk(KERN_ERR "%s:bad format\n", __func__); - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - /* CLKRP Receive clock polarity, - * 1 - sampled on rising edge of CLKR - * valid on rising edge - * CLKXP Transmit clock polarity, - * 1 - clocked on falling edge of CLKX - * valid on rising edge - * FSRP Receive frame sync pol, 0 - active high - * FSXP Transmit frame sync pol, 0 - active high - */ - pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP); - break; - case SND_SOC_DAIFMT_IB_IF: - /* CLKRP Receive clock polarity, - * 0 - sampled on falling edge of CLKR - * valid on falling edge - * CLKXP Transmit clock polarity, - * 0 - clocked on rising edge of CLKX - * valid on falling edge - * FSRP Receive frame sync pol, 1 - active low - * FSXP Transmit frame sync pol, 1 - active low - */ - pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); - break; - case SND_SOC_DAIFMT_NB_IF: - /* CLKRP Receive clock polarity, - * 1 - sampled on rising edge of CLKR - * valid on rising edge - * CLKXP Transmit clock polarity, - * 1 - clocked on falling edge of CLKX - * valid on rising edge - * FSRP Receive frame sync pol, 1 - active low - * FSXP Transmit frame sync pol, 1 - active low - */ - pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP | - DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); - break; - case SND_SOC_DAIFMT_IB_NF: - /* CLKRP Receive clock polarity, - * 0 - sampled on falling edge of CLKR - * valid on falling edge - * CLKXP Transmit clock polarity, - * 0 - clocked on rising edge of CLKX - * valid on falling edge - * FSRP Receive frame sync pol, 0 - active high - * FSXP Transmit frame sync pol, 0 - active high - */ - break; - default: - return -EINVAL; - } - if (inv_fs == true) - pcr ^= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); - dev->pcr = pcr; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); - return 0; -} - -static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - - if (div_id != DAVINCI_MCBSP_CLKGDV) - return -ENODEV; - - dev->clk_div = div; - return 0; -} - -static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - struct davinci_pcm_dma_params *dma_params = - &dev->dma_params[substream->stream]; - struct snd_interval *i = NULL; - int mcbsp_word_length, master; - unsigned int rcr, xcr, srgr, clk_div, freq, framesize; - u32 spcr; - snd_pcm_format_t fmt; - unsigned element_cnt = 1; - - /* general line settings */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } else { - spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } - - master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; - fmt = params_format(params); - mcbsp_word_length = asp_word_length[fmt]; - - switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - freq = clk_get_rate(dev->clk); - srgr = DAVINCI_MCBSP_SRGR_FSGM | - DAVINCI_MCBSP_SRGR_CLKSM; - srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * - 8 - 1); - if (dev->i2s_accurate_sck) { - clk_div = 256; - do { - framesize = (freq / (--clk_div)) / - params->rate_num * - params->rate_den; - } while (((framesize < 33) || (framesize > 4095)) && - (clk_div)); - clk_div--; - srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1); - } else { - /* symmetric waveforms */ - clk_div = freq / (mcbsp_word_length * 16) / - params->rate_num * params->rate_den; - srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * - 16 - 1); - } - clk_div &= 0xFF; - srgr |= clk_div; - break; - case SND_SOC_DAIFMT_CBM_CFS: - srgr = DAVINCI_MCBSP_SRGR_FSGM; - clk_div = dev->clk_div - 1; - srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1); - srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1); - clk_div &= 0xFF; - srgr |= clk_div; - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Clock and frame sync given from external sources */ - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); - srgr = DAVINCI_MCBSP_SRGR_FSGM; - srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); - pr_debug("%s - %d FWID set: re-read srgr = %X\n", - __func__, __LINE__, snd_interval_value(i) - 1); - - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); - srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); - break; - default: - return -EINVAL; - } - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); - - rcr = DAVINCI_MCBSP_RCR_RFIG; - xcr = DAVINCI_MCBSP_XCR_XFIG; - if (dev->mode == MOD_DSP_B) { - rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0); - xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0); - } else { - rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); - xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); - } - /* Determine xfer data type */ - fmt = params_format(params); - if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) { - printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n"); - return -EINVAL; - } - - if (params_channels(params) == 2) { - element_cnt = 2; - if (double_fmt[fmt] && dev->enable_channel_combine) { - element_cnt = 1; - fmt = double_fmt[fmt]; - } - switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBS_CFM: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0); - rcr |= DAVINCI_MCBSP_RCR_RPHASE; - xcr |= DAVINCI_MCBSP_XCR_XPHASE; - break; - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1); - break; - default: - return -EINVAL; - } - } - dma_params->acnt = dma_params->data_type = data_type[fmt]; - dma_params->fifo_level = 0; - mcbsp_word_length = asp_word_length[fmt]; - - switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBS_CFM: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0); - break; - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); - break; - default: - return -EINVAL; - } - - rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | - DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); - xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | - DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); - else - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); - - pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr); - pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr); - pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr); - return 0; -} - -static int davinci_i2s_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - davinci_mcbsp_stop(dev, playback); - return 0; -} - -static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - int ret = 0; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_mcbsp_start(dev, substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcbsp_stop(dev, playback); - break; - default: - ret = -EINVAL; - } - return ret; -} - -static int davinci_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - - snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); - return 0; -} - -static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - davinci_mcbsp_stop(dev, playback); -} - -#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 - -static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { - .startup = davinci_i2s_startup, - .shutdown = davinci_i2s_shutdown, - .prepare = davinci_i2s_prepare, - .trigger = davinci_i2s_trigger, - .hw_params = davinci_i2s_hw_params, - .set_fmt = davinci_i2s_set_dai_fmt, - .set_clkdiv = davinci_i2s_dai_set_clkdiv, - -}; - -static struct snd_soc_dai_driver davinci_i2s_dai = { - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &davinci_i2s_dai_ops, - -}; - -static int davinci_i2s_probe(struct platform_device *pdev) -{ - struct snd_platform_data *pdata = pdev->dev.platform_data; - struct davinci_mcbsp_dev *dev; - struct resource *mem, *ioarea, *res; - enum dma_event_q asp_chan_q = EVENTQ_0; - enum dma_event_q ram_chan_q = EVENTQ_1; - int ret; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - - ioarea = devm_request_mem_region(&pdev->dev, mem->start, - resource_size(mem), - pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "McBSP region already claimed\n"); - return -EBUSY; - } - - dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev), - GFP_KERNEL); - if (!dev) - return -ENOMEM; - if (pdata) { - dev->enable_channel_combine = pdata->enable_channel_combine; - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].sram_size = - pdata->sram_size_playback; - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size = - pdata->sram_size_capture; - dev->clk_input_pin = pdata->clk_input_pin; - dev->i2s_accurate_sck = pdata->i2s_accurate_sck; - asp_chan_q = pdata->asp_chan_q; - ram_chan_q = pdata->ram_chan_q; - } - - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].asp_chan_q = asp_chan_q; - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].ram_chan_q = ram_chan_q; - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].asp_chan_q = asp_chan_q; - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q = ram_chan_q; - - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) - return -ENODEV; - clk_enable(dev->clk); - - dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); - if (!dev->base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto err_release_clk; - } - - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr = - (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); - - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = - (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG); - - /* first TX, then RX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENXIO; - goto err_release_clk; - } - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENXIO; - goto err_release_clk; - } - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; - dev->dev = &pdev->dev; - - dev_set_drvdata(&pdev->dev, dev); - - ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai); - if (ret != 0) - goto err_release_clk; - - return 0; - -err_release_clk: - clk_disable(dev->clk); - clk_put(dev->clk); - return ret; -} - -static int davinci_i2s_remove(struct platform_device *pdev) -{ - struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_dai(&pdev->dev); - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; - - return 0; -} - -static struct platform_driver davinci_mcbsp_driver = { - .probe = davinci_i2s_probe, - .remove = davinci_i2s_remove, - .driver = { - .name = "davinci-mcbsp", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(davinci_mcbsp_driver); - -MODULE_AUTHOR("Vladimir Barinov"); -MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.h b/ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.h deleted file mode 100644 index 48dac3e2..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-i2s.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor - * - * Author: Vladimir Barinov, - * Copyright: (C) 2007 MontaVista Software, Inc., - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _DAVINCI_I2S_H -#define _DAVINCI_I2S_H - -/* McBSP dividers */ -enum davinci_mcbsp_div { - DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */ -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c b/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c deleted file mode 100644 index 95441bfc..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.c +++ /dev/null @@ -1,983 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * Multi-channel Audio Serial Port Driver - * - * Author: Nirmal Pandey , - * Suresh Rajashekara - * Steve Chen - * - * Copyright: (C) 2009 MontaVista Software, Inc., - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "davinci-pcm.h" -#include "davinci-mcasp.h" - -/* - * McASP register definitions - */ -#define DAVINCI_MCASP_PID_REG 0x00 -#define DAVINCI_MCASP_PWREMUMGT_REG 0x04 - -#define DAVINCI_MCASP_PFUNC_REG 0x10 -#define DAVINCI_MCASP_PDIR_REG 0x14 -#define DAVINCI_MCASP_PDOUT_REG 0x18 -#define DAVINCI_MCASP_PDSET_REG 0x1c - -#define DAVINCI_MCASP_PDCLR_REG 0x20 - -#define DAVINCI_MCASP_TLGC_REG 0x30 -#define DAVINCI_MCASP_TLMR_REG 0x34 - -#define DAVINCI_MCASP_GBLCTL_REG 0x44 -#define DAVINCI_MCASP_AMUTE_REG 0x48 -#define DAVINCI_MCASP_LBCTL_REG 0x4c - -#define DAVINCI_MCASP_TXDITCTL_REG 0x50 - -#define DAVINCI_MCASP_GBLCTLR_REG 0x60 -#define DAVINCI_MCASP_RXMASK_REG 0x64 -#define DAVINCI_MCASP_RXFMT_REG 0x68 -#define DAVINCI_MCASP_RXFMCTL_REG 0x6c - -#define DAVINCI_MCASP_ACLKRCTL_REG 0x70 -#define DAVINCI_MCASP_AHCLKRCTL_REG 0x74 -#define DAVINCI_MCASP_RXTDM_REG 0x78 -#define DAVINCI_MCASP_EVTCTLR_REG 0x7c - -#define DAVINCI_MCASP_RXSTAT_REG 0x80 -#define DAVINCI_MCASP_RXTDMSLOT_REG 0x84 -#define DAVINCI_MCASP_RXCLKCHK_REG 0x88 -#define DAVINCI_MCASP_REVTCTL_REG 0x8c - -#define DAVINCI_MCASP_GBLCTLX_REG 0xa0 -#define DAVINCI_MCASP_TXMASK_REG 0xa4 -#define DAVINCI_MCASP_TXFMT_REG 0xa8 -#define DAVINCI_MCASP_TXFMCTL_REG 0xac - -#define DAVINCI_MCASP_ACLKXCTL_REG 0xb0 -#define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4 -#define DAVINCI_MCASP_TXTDM_REG 0xb8 -#define DAVINCI_MCASP_EVTCTLX_REG 0xbc - -#define DAVINCI_MCASP_TXSTAT_REG 0xc0 -#define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4 -#define DAVINCI_MCASP_TXCLKCHK_REG 0xc8 -#define DAVINCI_MCASP_XEVTCTL_REG 0xcc - -/* Left(even TDM Slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRA_REG 0x100 -/* Right(odd TDM slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRB_REG 0x118 -/* Left(even TDM slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRA_REG 0x130 -/* Right(odd TDM Slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRB_REG 0x148 - -/* Serializer n Control Register */ -#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180 -#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \ - (n << 2)) - -/* Transmit Buffer for Serializer n */ -#define DAVINCI_MCASP_TXBUF_REG 0x200 -/* Receive Buffer for Serializer n */ -#define DAVINCI_MCASP_RXBUF_REG 0x280 - -/* McASP FIFO Registers */ -#define DAVINCI_MCASP_WFIFOCTL (0x1010) -#define DAVINCI_MCASP_WFIFOSTS (0x1014) -#define DAVINCI_MCASP_RFIFOCTL (0x1018) -#define DAVINCI_MCASP_RFIFOSTS (0x101C) - -/* - * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management - * Register Bits - */ -#define MCASP_FREE BIT(0) -#define MCASP_SOFT BIT(1) - -/* - * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits - */ -#define AXR(n) (1<base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); -} - -static void mcasp_start_tx(struct davinci_audio_dev *dev) -{ - u8 offset = 0, i; - u32 cnt; - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); - for (i = 0; i < dev->num_serializer; i++) { - if (dev->serial_dir[i] == TX_MODE) { - offset = i; - break; - } - } - - /* wait for TX ready */ - cnt = 0; - while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) & - TXSTATE) && (cnt < 100000)) - cnt++; - - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); -} - -static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt) /* enable FIFO */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, - FIFO_ENABLE); - mcasp_start_tx(dev); - } else { - if (dev->rxnumevt) /* enable FIFO */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, - FIFO_ENABLE); - mcasp_start_rx(dev); - } -} - -static void mcasp_stop_rx(struct davinci_audio_dev *dev) -{ - mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); -} - -static void mcasp_stop_tx(struct davinci_audio_dev *dev) -{ - mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); -} - -static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt) /* disable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, - FIFO_ENABLE); - mcasp_stop_tx(dev); - } else { - if (dev->rxnumevt) /* disable FIFO */ - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, - FIFO_ENABLE); - mcasp_stop_rx(dev); - } -} - -static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - void __iomem *base = dev->base; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* codec is clock and frame slave */ - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, - ACLKX | AHCLKX | AFSX); - break; - case SND_SOC_DAIFMT_CBM_CFS: - /* codec is clock master and frame slave */ - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, - ACLKX | ACLKR); - mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, - AFSX | AFSR); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* codec is clock and frame master */ - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, - ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_NF: - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_NB_IF: - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_IB_IF: - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_NB_NF: - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int davinci_config_channel_size(struct davinci_audio_dev *dev, - int channel_size) -{ - u32 fmt = 0; - u32 mask, rotate; - - switch (channel_size) { - case DAVINCI_AUDIO_WORD_8: - fmt = 0x03; - rotate = 6; - mask = 0x000000ff; - break; - - case DAVINCI_AUDIO_WORD_12: - fmt = 0x05; - rotate = 5; - mask = 0x00000fff; - break; - - case DAVINCI_AUDIO_WORD_16: - fmt = 0x07; - rotate = 4; - mask = 0x0000ffff; - break; - - case DAVINCI_AUDIO_WORD_20: - fmt = 0x09; - rotate = 3; - mask = 0x000fffff; - break; - - case DAVINCI_AUDIO_WORD_24: - fmt = 0x0B; - rotate = 2; - mask = 0x00ffffff; - break; - - case DAVINCI_AUDIO_WORD_28: - fmt = 0x0D; - rotate = 1; - mask = 0x0fffffff; - break; - - case DAVINCI_AUDIO_WORD_32: - fmt = 0x0F; - rotate = 0; - mask = 0xffffffff; - break; - - default: - return -EINVAL; - } - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, - RXSSZ(fmt), RXSSZ(0x0F)); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, - TXSSZ(fmt), TXSSZ(0x0F)); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate), - TXROT(7)); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate), - RXROT(7)); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask); - - return 0; -} - -static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) -{ - int i; - u8 tx_ser = 0; - u8 rx_ser = 0; - - /* Default configuration */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); - - /* All PINS as McASP */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, - TXDATADMADIS); - } else { - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG, - RXDATADMADIS); - } - - for (i = 0; i < dev->num_serializer; i++) { - mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), - dev->serial_dir[i]); - if (dev->serial_dir[i] == TX_MODE) { - mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, - AXR(i)); - tx_ser++; - } else if (dev->serial_dir[i] == RX_MODE) { - mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, - AXR(i)); - rx_ser++; - } - } - - if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt * tx_ser > 64) - dev->txnumevt = 1; - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, - NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, - ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); - } - - if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { - if (dev->rxnumevt * rx_ser > 64) - dev->rxnumevt = 1; - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, - NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, - ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); - } -} - -static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) -{ - int i, active_slots; - u32 mask = 0; - - active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots; - for (i = 0; i < active_slots; i++) - mask |= (1 << i); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, - AHCLKXE); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); - - if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, - FSXMOD(dev->tdm_slots), FSXMOD(0x1FF)); - else - printk(KERN_ERR "playback tdm slot %d not supported\n", - dev->tdm_slots); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); - } else { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD); - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, - AHCLKRE); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); - - if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, - FSRMOD(dev->tdm_slots), FSRMOD(0x1FF)); - else - printk(KERN_ERR "capture tdm slot %d not supported\n", - dev->tdm_slots); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); - } -} - -/* S/PDIF */ -static void davinci_hw_dit_param(struct davinci_audio_dev *dev) -{ - /* Set the PDIR for Serialiser as output */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX); - - /* TXMASK for 24 bits */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF); - - /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 - and LSB first */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, - TXROT(6) | TXSSZ(15)); - - /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG, - AFSXE | FSXMOD(0x180)); - - /* Set the TX tdm : for all the slots */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); - - /* Set the TX clock controls : div = 1 and internal */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, - ACLKXE | TX_ASYNC); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); - - /* Only 44100 and 48000 are valid, both have the same setting */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); - - /* Enable the DIT */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN); -} - -static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - struct davinci_pcm_dma_params *dma_params = - &dev->dma_params[substream->stream]; - int word_length; - u8 fifo_level; - - davinci_hw_common_param(dev, substream->stream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - fifo_level = dev->txnumevt; - else - fifo_level = dev->rxnumevt; - - if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) - davinci_hw_dit_param(dev); - else - davinci_hw_param(dev, substream->stream); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_U8: - case SNDRV_PCM_FORMAT_S8: - dma_params->data_type = 1; - word_length = DAVINCI_AUDIO_WORD_8; - break; - - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_S16_LE: - dma_params->data_type = 2; - word_length = DAVINCI_AUDIO_WORD_16; - break; - - case SNDRV_PCM_FORMAT_U32_LE: - case SNDRV_PCM_FORMAT_S32_LE: - dma_params->data_type = 4; - word_length = DAVINCI_AUDIO_WORD_32; - break; - - default: - printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); - return -EINVAL; - } - - if (dev->version == MCASP_VERSION_2 && !fifo_level) - dma_params->acnt = 4; - else - dma_params->acnt = dma_params->data_type; - - dma_params->fifo_level = fifo_level; - davinci_config_channel_size(dev, word_length); - - return 0; -} - -static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *cpu_dai) -{ - struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!dev->clk_active) { - clk_enable(dev->clk); - dev->clk_active = 1; - } - davinci_mcasp_start(dev, substream->stream); - break; - - case SNDRV_PCM_TRIGGER_SUSPEND: - davinci_mcasp_stop(dev, substream->stream); - if (dev->clk_active) { - clk_disable(dev->clk); - dev->clk_active = 0; - } - - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcasp_stop(dev, substream->stream); - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static int davinci_mcasp_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); - - snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); - return 0; -} - -static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { - .startup = davinci_mcasp_startup, - .trigger = davinci_mcasp_trigger, - .hw_params = davinci_mcasp_hw_params, - .set_fmt = davinci_mcasp_set_dai_fmt, - -}; - -#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_U8 | \ - SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_U16_LE | \ - SNDRV_PCM_FMTBIT_S32_LE | \ - SNDRV_PCM_FMTBIT_U32_LE) - -static struct snd_soc_dai_driver davinci_mcasp_dai[] = { - { - .name = "davinci-mcasp.0", - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .ops = &davinci_mcasp_dai_ops, - - }, - { - "davinci-mcasp.1", - .playback = { - .channels_min = 1, - .channels_max = 384, - .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, - }, - .ops = &davinci_mcasp_dai_ops, - }, - -}; - -static int davinci_mcasp_probe(struct platform_device *pdev) -{ - struct davinci_pcm_dma_params *dma_data; - struct resource *mem, *ioarea, *res; - struct snd_platform_data *pdata; - struct davinci_audio_dev *dev; - int ret; - - dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), - GFP_KERNEL); - if (!dev) - return -ENOMEM; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - - ioarea = devm_request_mem_region(&pdev->dev, mem->start, - resource_size(mem), pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "Audio region already claimed\n"); - return -EBUSY; - } - - pdata = pdev->dev.platform_data; - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) - return -ENODEV; - - clk_enable(dev->clk); - dev->clk_active = 1; - - dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); - if (!dev->base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto err_release_clk; - } - - dev->op_mode = pdata->op_mode; - dev->tdm_slots = pdata->tdm_slots; - dev->num_serializer = pdata->num_serializer; - dev->serial_dir = pdata->serial_dir; - dev->codec_fmt = pdata->codec_fmt; - dev->version = pdata->version; - dev->txnumevt = pdata->txnumevt; - dev->rxnumevt = pdata->rxnumevt; - - dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_size = pdata->sram_size_playback; - dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + - mem->start); - - /* first TX, then RX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENODEV; - goto err_release_clk; - } - - dma_data->channel = res->start; - - dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; - dma_data->asp_chan_q = pdata->asp_chan_q; - dma_data->ram_chan_q = pdata->ram_chan_q; - dma_data->sram_size = pdata->sram_size_capture; - dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + - mem->start); - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENODEV; - goto err_release_clk; - } - - dma_data->channel = res->start; - dev_set_drvdata(&pdev->dev, dev); - ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]); - - if (ret != 0) - goto err_release_clk; - return 0; - -err_release_clk: - clk_disable(dev->clk); - clk_put(dev->clk); - return ret; -} - -static int davinci_mcasp_remove(struct platform_device *pdev) -{ - struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_dai(&pdev->dev); - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; - - return 0; -} - -static struct platform_driver davinci_mcasp_driver = { - .probe = davinci_mcasp_probe, - .remove = davinci_mcasp_remove, - .driver = { - .name = "davinci-mcasp", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(davinci_mcasp_driver); - -MODULE_AUTHOR("Steve Chen"); -MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.h b/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.h deleted file mode 100644 index 4681acc6..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-mcasp.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * MCASP related definitions - * - * Author: Nirmal Pandey , - * Suresh Rajashekara - * Steve Chen - * - * Copyright: (C) 2009 MontaVista Software, Inc., - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef DAVINCI_MCASP_H -#define DAVINCI_MCASP_H - -#include -#include -#include "davinci-pcm.h" - -#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 -#define DAVINCI_MCASP_I2S_DAI 0 -#define DAVINCI_MCASP_DIT_DAI 1 - -enum { - DAVINCI_AUDIO_WORD_8 = 0, - DAVINCI_AUDIO_WORD_12, - DAVINCI_AUDIO_WORD_16, - DAVINCI_AUDIO_WORD_20, - DAVINCI_AUDIO_WORD_24, - DAVINCI_AUDIO_WORD_32, - DAVINCI_AUDIO_WORD_28, /* This is only valid for McASP */ -}; - -struct davinci_audio_dev { - struct davinci_pcm_dma_params dma_params[2]; - void __iomem *base; - int sample_rate; - struct clk *clk; - unsigned int codec_fmt; - u8 clk_active; - - /* McASP specific data */ - int tdm_slots; - u8 op_mode; - u8 num_serializer; - u8 *serial_dir; - u8 version; - - /* McASP FIFO related */ - u8 txnumevt; - u8 rxnumevt; -}; - -#endif /* DAVINCI_MCASP_H */ diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.c b/ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.c deleted file mode 100644 index 97d77b29..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.c +++ /dev/null @@ -1,892 +0,0 @@ -/* - * ALSA PCM interface for the TI DAVINCI processor - * - * Author: Vladimir Barinov, - * Copyright: (C) 2007 MontaVista Software, Inc., - * added SRAM ping/pong (C) 2008 Troy Kisky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "davinci-pcm.h" - -#ifdef DEBUG -static void print_buf_info(int slot, char *name) -{ - struct edmacc_param p; - if (slot < 0) - return; - edma_read_slot(slot, &p); - printk(KERN_DEBUG "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n", - name, slot, p.opt, p.src, p.a_b_cnt, p.dst); - printk(KERN_DEBUG " src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n", - p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt); -} -#else -static void print_buf_info(int slot, char *name) -{ -} -#endif - -#define DAVINCI_PCM_FMTBITS (\ - SNDRV_PCM_FMTBIT_S8 |\ - SNDRV_PCM_FMTBIT_U8 |\ - SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S16_BE |\ - SNDRV_PCM_FMTBIT_U16_LE |\ - SNDRV_PCM_FMTBIT_U16_BE |\ - SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S24_BE |\ - SNDRV_PCM_FMTBIT_U24_LE |\ - SNDRV_PCM_FMTBIT_U24_BE |\ - SNDRV_PCM_FMTBIT_S32_LE |\ - SNDRV_PCM_FMTBIT_S32_BE |\ - SNDRV_PCM_FMTBIT_U32_LE |\ - SNDRV_PCM_FMTBIT_U32_BE) - -static struct snd_pcm_hardware pcm_hardware_playback = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME| - SNDRV_PCM_INFO_BATCH), - .formats = DAVINCI_PCM_FMTBITS, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_KNOT), - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 2, - .channels_max = 384, - .buffer_bytes_max = 128 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 8 * 1024, - .periods_min = 16, - .periods_max = 255, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware pcm_hardware_capture = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_BATCH), - .formats = DAVINCI_PCM_FMTBITS, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_KNOT), - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 2, - .channels_max = 384, - .buffer_bytes_max = 128 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 8 * 1024, - .periods_min = 16, - .periods_max = 255, - .fifo_size = 0, -}; - -/* - * How ping/pong works.... - * - * Playback: - * ram_params - copys 2*ping_size from start of SDRAM to iram, - * links to ram_link2 - * ram_link2 - copys rest of SDRAM to iram in ping_size units, - * links to ram_link - * ram_link - copys entire SDRAM to iram in ping_size uints, - * links to self - * - * asp_params - same as asp_link[0] - * asp_link[0] - copys from lower half of iram to asp port - * links to asp_link[1], triggers iram copy event on completion - * asp_link[1] - copys from upper half of iram to asp port - * links to asp_link[0], triggers iram copy event on completion - * triggers interrupt only needed to let upper SOC levels update position - * in stream on completion - * - * When playback is started: - * ram_params started - * asp_params started - * - * Capture: - * ram_params - same as ram_link, - * links to ram_link - * ram_link - same as playback - * links to self - * - * asp_params - same as playback - * asp_link[0] - same as playback - * asp_link[1] - same as playback - * - * When capture is started: - * asp_params started - */ -struct davinci_runtime_data { - spinlock_t lock; - int period; /* current DMA period */ - int asp_channel; /* Master DMA channel */ - int asp_link[2]; /* asp parameter link channel, ping/pong */ - struct davinci_pcm_dma_params *params; /* DMA params */ - int ram_channel; - int ram_link; - int ram_link2; - struct edmacc_param asp_params; - struct edmacc_param ram_params; -}; - -static void davinci_pcm_period_elapsed(struct snd_pcm_substream *substream) -{ - struct davinci_runtime_data *prtd = substream->runtime->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - prtd->period++; - if (unlikely(prtd->period >= runtime->periods)) - prtd->period = 0; -} - -static void davinci_pcm_period_reset(struct snd_pcm_substream *substream) -{ - struct davinci_runtime_data *prtd = substream->runtime->private_data; - - prtd->period = 0; -} -/* - * Not used with ping/pong - */ -static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) -{ - struct davinci_runtime_data *prtd = substream->runtime->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int period_size; - unsigned int dma_offset; - dma_addr_t dma_pos; - dma_addr_t src, dst; - unsigned short src_bidx, dst_bidx; - unsigned short src_cidx, dst_cidx; - unsigned int data_type; - unsigned short acnt; - unsigned int count; - unsigned int fifo_level; - - period_size = snd_pcm_lib_period_bytes(substream); - dma_offset = prtd->period * period_size; - dma_pos = runtime->dma_addr + dma_offset; - fifo_level = prtd->params->fifo_level; - - pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d " - "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos, - period_size); - - data_type = prtd->params->data_type; - count = period_size / data_type; - if (fifo_level) - count /= fifo_level; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - src = dma_pos; - dst = prtd->params->dma_addr; - src_bidx = data_type; - dst_bidx = 0; - src_cidx = data_type * fifo_level; - dst_cidx = 0; - } else { - src = prtd->params->dma_addr; - dst = dma_pos; - src_bidx = 0; - dst_bidx = data_type; - src_cidx = 0; - dst_cidx = data_type * fifo_level; - } - - acnt = prtd->params->acnt; - edma_set_src(prtd->asp_link[0], src, INCR, W8BIT); - edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT); - - edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx); - edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx); - - if (!fifo_level) - edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0, - ASYNC); - else - edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level, - count, fifo_level, - ABSYNC); -} - -static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data) -{ - struct snd_pcm_substream *substream = data; - struct davinci_runtime_data *prtd = substream->runtime->private_data; - - print_buf_info(prtd->ram_channel, "i ram_channel"); - pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status); - - if (unlikely(ch_status != DMA_COMPLETE)) - return; - - if (snd_pcm_running(substream)) { - spin_lock(&prtd->lock); - if (prtd->ram_channel < 0) { - /* No ping/pong must fix up link dma data*/ - davinci_pcm_enqueue_dma(substream); - } - davinci_pcm_period_elapsed(substream); - spin_unlock(&prtd->lock); - snd_pcm_period_elapsed(substream); - } -} - -static int allocate_sram(struct snd_pcm_substream *substream, unsigned size, - struct snd_pcm_hardware *ppcm) -{ - struct snd_dma_buffer *buf = &substream->dma_buffer; - struct snd_dma_buffer *iram_dma = NULL; - dma_addr_t iram_phys = 0; - void *iram_virt = NULL; - - if (buf->private_data || !size) - return 0; - - ppcm->period_bytes_max = size; - iram_virt = sram_alloc(size, &iram_phys); - if (!iram_virt) - goto exit1; - iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL); - if (!iram_dma) - goto exit2; - iram_dma->area = iram_virt; - iram_dma->addr = iram_phys; - memset(iram_dma->area, 0, size); - iram_dma->bytes = size; - buf->private_data = iram_dma; - return 0; -exit2: - if (iram_virt) - sram_free(iram_virt, size); -exit1: - return -ENOMEM; -} - -/* - * Only used with ping/pong. - * This is called after runtime->dma_addr, period_bytes and data_type are valid - */ -static int ping_pong_dma_setup(struct snd_pcm_substream *substream) -{ - unsigned short ram_src_cidx, ram_dst_cidx; - struct snd_pcm_runtime *runtime = substream->runtime; - struct davinci_runtime_data *prtd = runtime->private_data; - struct snd_dma_buffer *iram_dma = - (struct snd_dma_buffer *)substream->dma_buffer.private_data; - struct davinci_pcm_dma_params *params = prtd->params; - unsigned int data_type = params->data_type; - unsigned int acnt = params->acnt; - /* divide by 2 for ping/pong */ - unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1; - unsigned int fifo_level = prtd->params->fifo_level; - unsigned int count; - if ((data_type == 0) || (data_type > 4)) { - printk(KERN_ERR "%s: data_type=%i\n", __func__, data_type); - return -EINVAL; - } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dma_addr_t asp_src_pong = iram_dma->addr + ping_size; - ram_src_cidx = ping_size; - ram_dst_cidx = -ping_size; - edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT); - - edma_set_src_index(prtd->asp_link[0], data_type, - data_type * fifo_level); - edma_set_src_index(prtd->asp_link[1], data_type, - data_type * fifo_level); - - edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT); - } else { - dma_addr_t asp_dst_pong = iram_dma->addr + ping_size; - ram_src_cidx = -ping_size; - ram_dst_cidx = ping_size; - edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT); - - edma_set_dest_index(prtd->asp_link[0], data_type, - data_type * fifo_level); - edma_set_dest_index(prtd->asp_link[1], data_type, - data_type * fifo_level); - - edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT); - } - - if (!fifo_level) { - count = ping_size / data_type; - edma_set_transfer_params(prtd->asp_link[0], acnt, count, - 1, 0, ASYNC); - edma_set_transfer_params(prtd->asp_link[1], acnt, count, - 1, 0, ASYNC); - } else { - count = ping_size / (data_type * fifo_level); - edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level, - count, fifo_level, ABSYNC); - edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level, - count, fifo_level, ABSYNC); - } - - edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx); - edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx); - edma_set_transfer_params(prtd->ram_link, ping_size, 2, - runtime->periods, 2, ASYNC); - - /* init master params */ - edma_read_slot(prtd->asp_link[0], &prtd->asp_params); - edma_read_slot(prtd->ram_link, &prtd->ram_params); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - struct edmacc_param p_ram; - /* Copy entire iram buffer before playback started */ - prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1); - /* 0 dst_bidx */ - prtd->ram_params.src_dst_bidx = (ping_size << 1); - /* 0 dst_cidx */ - prtd->ram_params.src_dst_cidx = (ping_size << 1); - prtd->ram_params.ccnt = 1; - - /* Skip 1st period */ - edma_read_slot(prtd->ram_link, &p_ram); - p_ram.src += (ping_size << 1); - p_ram.ccnt -= 1; - edma_write_slot(prtd->ram_link2, &p_ram); - /* - * When 1st started, ram -> iram dma channel will fill the - * entire iram. Then, whenever a ping/pong asp buffer finishes, - * 1/2 iram will be filled. - */ - prtd->ram_params.link_bcntrld = - EDMA_CHAN_SLOT(prtd->ram_link2) << 5; - } - return 0; -} - -/* 1 asp tx or rx channel using 2 parameter channels - * 1 ram to/from iram channel using 1 parameter channel - * - * Playback - * ram copy channel kicks off first, - * 1st ram copy of entire iram buffer completion kicks off asp channel - * asp tcc always kicks off ram copy of 1/2 iram buffer - * - * Record - * asp channel starts, tcc kicks off ram copy - */ -static int request_ping_pong(struct snd_pcm_substream *substream, - struct davinci_runtime_data *prtd, - struct snd_dma_buffer *iram_dma) -{ - dma_addr_t asp_src_ping; - dma_addr_t asp_dst_ping; - int ret; - struct davinci_pcm_dma_params *params = prtd->params; - - /* Request ram master channel */ - ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY, - davinci_pcm_dma_irq, substream, - prtd->params->ram_chan_q); - if (ret < 0) - goto exit1; - - /* Request ram link channel */ - ret = prtd->ram_link = edma_alloc_slot( - EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); - if (ret < 0) - goto exit2; - - ret = prtd->asp_link[1] = edma_alloc_slot( - EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); - if (ret < 0) - goto exit3; - - prtd->ram_link2 = -1; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ret = prtd->ram_link2 = edma_alloc_slot( - EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY); - if (ret < 0) - goto exit4; - } - /* circle ping-pong buffers */ - edma_link(prtd->asp_link[0], prtd->asp_link[1]); - edma_link(prtd->asp_link[1], prtd->asp_link[0]); - /* circle ram buffers */ - edma_link(prtd->ram_link, prtd->ram_link); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - asp_src_ping = iram_dma->addr; - asp_dst_ping = params->dma_addr; /* fifo */ - } else { - asp_src_ping = params->dma_addr; /* fifo */ - asp_dst_ping = iram_dma->addr; - } - /* ping */ - edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT); - edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT); - edma_set_src_index(prtd->asp_link[0], 0, 0); - edma_set_dest_index(prtd->asp_link[0], 0, 0); - - edma_read_slot(prtd->asp_link[0], &prtd->asp_params); - prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN); - prtd->asp_params.opt |= TCCHEN | - EDMA_TCC(prtd->ram_channel & 0x3f); - edma_write_slot(prtd->asp_link[0], &prtd->asp_params); - - /* pong */ - edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT); - edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT); - edma_set_src_index(prtd->asp_link[1], 0, 0); - edma_set_dest_index(prtd->asp_link[1], 0, 0); - - edma_read_slot(prtd->asp_link[1], &prtd->asp_params); - prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f)); - /* interrupt after every pong completion */ - prtd->asp_params.opt |= TCINTEN | TCCHEN | - EDMA_TCC(prtd->ram_channel & 0x3f); - edma_write_slot(prtd->asp_link[1], &prtd->asp_params); - - /* ram */ - edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT); - edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT); - pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u," - "for asp:%u %u %u\n", __func__, - prtd->ram_channel, prtd->ram_link, prtd->ram_link2, - prtd->asp_channel, prtd->asp_link[0], - prtd->asp_link[1]); - return 0; -exit4: - edma_free_channel(prtd->asp_link[1]); - prtd->asp_link[1] = -1; -exit3: - edma_free_channel(prtd->ram_link); - prtd->ram_link = -1; -exit2: - edma_free_channel(prtd->ram_channel); - prtd->ram_channel = -1; -exit1: - return ret; -} - -static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) -{ - struct snd_dma_buffer *iram_dma; - struct davinci_runtime_data *prtd = substream->runtime->private_data; - struct davinci_pcm_dma_params *params = prtd->params; - int ret; - - if (!params) - return -ENODEV; - - /* Request asp master DMA channel */ - ret = prtd->asp_channel = edma_alloc_channel(params->channel, - davinci_pcm_dma_irq, substream, - prtd->params->asp_chan_q); - if (ret < 0) - goto exit1; - - /* Request asp link channels */ - ret = prtd->asp_link[0] = edma_alloc_slot( - EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY); - if (ret < 0) - goto exit2; - - iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data; - if (iram_dma) { - if (request_ping_pong(substream, prtd, iram_dma) == 0) - return 0; - printk(KERN_WARNING "%s: dma channel allocation failed," - "not using sram\n", __func__); - } - - /* Issue transfer completion IRQ when the channel completes a - * transfer, then always reload from the same slot (by a kind - * of loopback link). The completion IRQ handler will update - * the reload slot with a new buffer. - * - * REVISIT save p_ram here after setting up everything except - * the buffer and its length (ccnt) ... use it as a template - * so davinci_pcm_enqueue_dma() takes less time in IRQ. - */ - edma_read_slot(prtd->asp_link[0], &prtd->asp_params); - prtd->asp_params.opt |= TCINTEN | - EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel)); - prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5; - edma_write_slot(prtd->asp_link[0], &prtd->asp_params); - return 0; -exit2: - edma_free_channel(prtd->asp_channel); - prtd->asp_channel = -1; -exit1: - return ret; -} - -static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct davinci_runtime_data *prtd = substream->runtime->private_data; - int ret = 0; - - spin_lock(&prtd->lock); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - edma_start(prtd->asp_channel); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && - prtd->ram_channel >= 0) { - /* copy 1st iram buffer */ - edma_start(prtd->ram_channel); - } - break; - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - edma_resume(prtd->asp_channel); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - edma_pause(prtd->asp_channel); - break; - default: - ret = -EINVAL; - break; - } - - spin_unlock(&prtd->lock); - - return ret; -} - -static int davinci_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct davinci_runtime_data *prtd = substream->runtime->private_data; - - davinci_pcm_period_reset(substream); - if (prtd->ram_channel >= 0) { - int ret = ping_pong_dma_setup(substream); - if (ret < 0) - return ret; - - edma_write_slot(prtd->ram_channel, &prtd->ram_params); - edma_write_slot(prtd->asp_channel, &prtd->asp_params); - - print_buf_info(prtd->ram_channel, "ram_channel"); - print_buf_info(prtd->ram_link, "ram_link"); - print_buf_info(prtd->ram_link2, "ram_link2"); - print_buf_info(prtd->asp_channel, "asp_channel"); - print_buf_info(prtd->asp_link[0], "asp_link[0]"); - print_buf_info(prtd->asp_link[1], "asp_link[1]"); - - /* - * There is a phase offset of 2 periods between the position - * used by dma setup and the position reported in the pointer - * function. - * - * The phase offset, when not using ping-pong buffers, is due to - * the two consecutive calls to davinci_pcm_enqueue_dma() below. - * - * Whereas here, with ping-pong buffers, the phase is due to - * there being an entire buffer transfer complete before the - * first dma completion event triggers davinci_pcm_dma_irq(). - */ - davinci_pcm_period_elapsed(substream); - davinci_pcm_period_elapsed(substream); - - return 0; - } - davinci_pcm_enqueue_dma(substream); - davinci_pcm_period_elapsed(substream); - - /* Copy self-linked parameter RAM entry into master channel */ - edma_read_slot(prtd->asp_link[0], &prtd->asp_params); - edma_write_slot(prtd->asp_channel, &prtd->asp_params); - davinci_pcm_enqueue_dma(substream); - davinci_pcm_period_elapsed(substream); - - return 0; -} - -static snd_pcm_uframes_t -davinci_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct davinci_runtime_data *prtd = runtime->private_data; - unsigned int offset; - int asp_count; - unsigned int period_size = snd_pcm_lib_period_bytes(substream); - - /* - * There is a phase offset of 2 periods between the position used by dma - * setup and the position reported in the pointer function. Either +2 in - * the dma setup or -2 here in the pointer function (with wrapping, - * both) accounts for this offset -- choose the latter since it makes - * the first-time setup clearer. - */ - spin_lock(&prtd->lock); - asp_count = prtd->period - 2; - spin_unlock(&prtd->lock); - - if (asp_count < 0) - asp_count += runtime->periods; - asp_count *= period_size; - - offset = bytes_to_frames(runtime, asp_count); - if (offset >= runtime->buffer_size) - offset = 0; - - return offset; -} - -static int davinci_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct davinci_runtime_data *prtd; - struct snd_pcm_hardware *ppcm; - int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_pcm_dma_params *pa; - struct davinci_pcm_dma_params *params; - - pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - if (!pa) - return -ENODEV; - params = &pa[substream->stream]; - - ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - &pcm_hardware_playback : &pcm_hardware_capture; - allocate_sram(substream, params->sram_size, ppcm); - snd_soc_set_runtime_hwparams(substream, ppcm); - /* ensure that buffer size is a multiple of period size */ - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - return ret; - - prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL); - if (prtd == NULL) - return -ENOMEM; - - spin_lock_init(&prtd->lock); - prtd->params = params; - prtd->asp_channel = -1; - prtd->asp_link[0] = prtd->asp_link[1] = -1; - prtd->ram_channel = -1; - prtd->ram_link = -1; - prtd->ram_link2 = -1; - - runtime->private_data = prtd; - - ret = davinci_pcm_dma_request(substream); - if (ret) { - printk(KERN_ERR "davinci_pcm: Failed to get dma channels\n"); - kfree(prtd); - } - - return ret; -} - -static int davinci_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct davinci_runtime_data *prtd = runtime->private_data; - - if (prtd->ram_channel >= 0) - edma_stop(prtd->ram_channel); - if (prtd->asp_channel >= 0) - edma_stop(prtd->asp_channel); - if (prtd->asp_link[0] >= 0) - edma_unlink(prtd->asp_link[0]); - if (prtd->asp_link[1] >= 0) - edma_unlink(prtd->asp_link[1]); - if (prtd->ram_link >= 0) - edma_unlink(prtd->ram_link); - - if (prtd->asp_link[0] >= 0) - edma_free_slot(prtd->asp_link[0]); - if (prtd->asp_link[1] >= 0) - edma_free_slot(prtd->asp_link[1]); - if (prtd->asp_channel >= 0) - edma_free_channel(prtd->asp_channel); - if (prtd->ram_link >= 0) - edma_free_slot(prtd->ram_link); - if (prtd->ram_link2 >= 0) - edma_free_slot(prtd->ram_link2); - if (prtd->ram_channel >= 0) - edma_free_channel(prtd->ram_channel); - - kfree(prtd); - - return 0; -} - -static int davinci_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int davinci_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int davinci_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - -static struct snd_pcm_ops davinci_pcm_ops = { - .open = davinci_pcm_open, - .close = davinci_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = davinci_pcm_hw_params, - .hw_free = davinci_pcm_hw_free, - .prepare = davinci_pcm_prepare, - .trigger = davinci_pcm_trigger, - .pointer = davinci_pcm_pointer, - .mmap = davinci_pcm_mmap, -}; - -static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, - size_t size) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - - pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, " - "size=%d\n", (void *) buf->area, (void *) buf->addr, size); - - if (!buf->area) - return -ENOMEM; - - buf->bytes = size; - return 0; -} - -static void davinci_pcm_free(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - struct snd_dma_buffer *iram_dma; - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - iram_dma = buf->private_data; - if (iram_dma) { - sram_free(iram_dma->area, iram_dma->bytes); - kfree(iram_dma); - } - } -} - -static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32); - -static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &davinci_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = davinci_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK, - pcm_hardware_playback.buffer_bytes_max); - if (ret) - return ret; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = davinci_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE, - pcm_hardware_capture.buffer_bytes_max); - if (ret) - return ret; - } - - return 0; -} - -static struct snd_soc_platform_driver davinci_soc_platform = { - .ops = &davinci_pcm_ops, - .pcm_new = davinci_pcm_new, - .pcm_free = davinci_pcm_free, -}; - -static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); -} - -static int __devexit davinci_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver davinci_pcm_driver = { - .driver = { - .name = "davinci-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = davinci_soc_platform_probe, - .remove = __devexit_p(davinci_soc_platform_remove), -}; - -module_platform_driver(davinci_pcm_driver); - -MODULE_AUTHOR("Vladimir Barinov"); -MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.h b/ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.h deleted file mode 100644 index c0d6c9be..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-pcm.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * ALSA PCM interface for the TI DAVINCI processor - * - * Author: Vladimir Barinov, - * Copyright: (C) 2007 MontaVista Software, Inc., - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _DAVINCI_PCM_H -#define _DAVINCI_PCM_H - -#include -#include - - -struct davinci_pcm_dma_params { - int channel; /* sync dma channel ID */ - unsigned short acnt; - dma_addr_t dma_addr; /* device physical address for DMA */ - unsigned sram_size; - enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ - enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ - unsigned char data_type; /* xfer data type */ - unsigned char convert_mono_stereo; - unsigned int fifo_level; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-sffsdr.c b/ANDROID_3.4.5/sound/soc/davinci/davinci-sffsdr.c deleted file mode 100644 index f71175b2..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-sffsdr.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * ASoC driver for Lyrtech SFFSDR board. - * - * Author: Hugo Villeneuve - * Copyright (C) 2008 Lyrtech inc - * - * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow: - * Copyright: (C) 2007 MontaVista Software, Inc., - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#ifdef CONFIG_SFFSDR_FPGA -#include -#endif - -#include - -#include "../codecs/pcm3008.h" -#include "davinci-pcm.h" -#include "davinci-i2s.h" - -/* - * CLKX and CLKR are the inputs for the Sample Rate Generator. - * FSX and FSR are outputs, driven by the sample Rate Generator. - */ -#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ - SND_SOC_DAIFMT_CBM_CFS | \ - SND_SOC_DAIFMT_IB_NF) - -static int sffsdr_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int fs; - int ret = 0; - - /* Fsref can be 32000, 44100 or 48000. */ - fs = params_rate(params); - -#ifndef CONFIG_SFFSDR_FPGA - /* Without the FPGA module, the Fs is fixed at 44100 Hz */ - if (fs != 44100) { - pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n"); - return -EINVAL; - } -#endif - - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); - if (ret < 0) - return ret; - - pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); - -#ifndef CONFIG_SFFSDR_FPGA - return 0; -#else - return sffsdr_fpga_set_codec_fs(fs); -#endif -} - -static struct snd_soc_ops sffsdr_ops = { - .hw_params = sffsdr_hw_params, -}; - -/* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link sffsdr_dai = { - .name = "PCM3008", /* Codec name */ - .stream_name = "PCM3008 HiFi", - .cpu_dai_name = "davinci-mcbsp", - .codec_dai_name = "pcm3008-hifi", - .codec_name = "pcm3008-codec", - .platform_name = "davinci-pcm-audio", - .ops = &sffsdr_ops, -}; - -/* davinci-sffsdr audio machine driver */ -static struct snd_soc_card snd_soc_sffsdr = { - .name = "DaVinci SFFSDR", - .owner = THIS_MODULE, - .dai_link = &sffsdr_dai, - .num_links = 1, -}; - -/* sffsdr audio private data */ -static struct pcm3008_setup_data sffsdr_pcm3008_setup = { - .dem0_pin = GPIO(45), - .dem1_pin = GPIO(46), - .pdad_pin = GPIO(47), - .pdda_pin = GPIO(38), -}; - -struct platform_device pcm3008_codec = { - .name = "pcm3008-codec", - .id = 0, - .dev = { - .platform_data = &sffsdr_pcm3008_setup, - }, -}; - -static struct resource sffsdr_snd_resources[] = { - { - .start = DAVINCI_MCBSP_BASE, - .end = DAVINCI_MCBSP_BASE + SZ_8K - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct evm_snd_platform_data sffsdr_snd_data = { - .tx_dma_ch = DAVINCI_DMA_MCBSP_TX, - .rx_dma_ch = DAVINCI_DMA_MCBSP_RX, -}; - -static struct platform_device *sffsdr_snd_device; - -static int __init sffsdr_init(void) -{ - int ret; - - if (!machine_is_sffsdr()) - return -EINVAL; - - platform_device_register(&pcm3008_codec); - - sffsdr_snd_device = platform_device_alloc("soc-audio", 0); - if (!sffsdr_snd_device) { - printk(KERN_ERR "platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr); - platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data, - sizeof(sffsdr_snd_data)); - - ret = platform_device_add_resources(sffsdr_snd_device, - sffsdr_snd_resources, - ARRAY_SIZE(sffsdr_snd_resources)); - if (ret) { - printk(KERN_ERR "platform device add resources failed\n"); - goto error; - } - - ret = platform_device_add(sffsdr_snd_device); - if (ret) - goto error; - - return ret; - -error: - platform_device_put(sffsdr_snd_device); - return ret; -} - -static void __exit sffsdr_exit(void) -{ - platform_device_unregister(sffsdr_snd_device); - platform_device_unregister(&pcm3008_codec); -} - -module_init(sffsdr_init); -module_exit(sffsdr_exit); - -MODULE_AUTHOR("Hugo Villeneuve"); -MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/davinci/davinci-vcif.c b/ANDROID_3.4.5/sound/soc/davinci/davinci-vcif.c deleted file mode 100644 index da030ff8..00000000 --- a/ANDROID_3.4.5/sound/soc/davinci/davinci-vcif.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * ALSA SoC Voice Codec Interface for TI DAVINCI processor - * - * Copyright (C) 2010 Texas Instruments. - * - * Author: Miguel Aguilar - * - * 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 -#include -#include -#include - -#include "davinci-pcm.h" -#include "davinci-i2s.h" - -#define MOD_REG_BIT(val, mask, set) do { \ - if (set) { \ - val |= mask; \ - } else { \ - val &= ~mask; \ - } \ -} while (0) - -struct davinci_vcif_dev { - struct davinci_vc *davinci_vc; - struct davinci_pcm_dma_params dma_params[2]; -}; - -static void davinci_vcif_start(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_vcif_dev *davinci_vcif_dev = - snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; - u32 w; - - /* Start the sample generator and enable transmitter/receiver */ - w = readl(davinci_vc->base + DAVINCI_VC_CTRL); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 0); - else - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 0); - - writel(w, davinci_vc->base + DAVINCI_VC_CTRL); -} - -static void davinci_vcif_stop(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_vcif_dev *davinci_vcif_dev = - snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; - u32 w; - - /* Reset transmitter/receiver and sample rate/frame sync generators */ - w = readl(davinci_vc->base + DAVINCI_VC_CTRL); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTDAC, 1); - else - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RSTADC, 1); - - writel(w, davinci_vc->base + DAVINCI_VC_CTRL); -} - -static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai); - struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; - struct davinci_pcm_dma_params *dma_params = - &davinci_vcif_dev->dma_params[substream->stream]; - u32 w; - - /* Restart the codec before setup */ - davinci_vcif_stop(substream); - davinci_vcif_start(substream); - - /* General line settings */ - writel(DAVINCI_VC_CTRL_MASK, davinci_vc->base + DAVINCI_VC_CTRL); - - writel(DAVINCI_VC_INT_MASK, davinci_vc->base + DAVINCI_VC_INTCLR); - - writel(DAVINCI_VC_INT_MASK, davinci_vc->base + DAVINCI_VC_INTEN); - - w = readl(davinci_vc->base + DAVINCI_VC_CTRL); - - /* Determine xfer data type */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_U8: - dma_params->data_type = 0; - - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | - DAVINCI_VC_CTRL_RD_UNSIGNED | - DAVINCI_VC_CTRL_WD_BITS_8 | - DAVINCI_VC_CTRL_WD_UNSIGNED, 1); - break; - case SNDRV_PCM_FORMAT_S8: - dma_params->data_type = 1; - - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | - DAVINCI_VC_CTRL_WD_BITS_8, 1); - - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_UNSIGNED | - DAVINCI_VC_CTRL_WD_UNSIGNED, 0); - break; - case SNDRV_PCM_FORMAT_S16_LE: - dma_params->data_type = 2; - - MOD_REG_BIT(w, DAVINCI_VC_CTRL_RD_BITS_8 | - DAVINCI_VC_CTRL_RD_UNSIGNED | - DAVINCI_VC_CTRL_WD_BITS_8 | - DAVINCI_VC_CTRL_WD_UNSIGNED, 0); - break; - default: - printk(KERN_WARNING "davinci-vcif: unsupported PCM format"); - return -EINVAL; - } - - dma_params->acnt = dma_params->data_type; - - writel(w, davinci_vc->base + DAVINCI_VC_CTRL); - - return 0; -} - -static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_vcif_start(substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_vcif_stop(substream); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int davinci_vcif_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai); - - snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); - return 0; -} - -#define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000 - -static const struct snd_soc_dai_ops davinci_vcif_dai_ops = { - .startup = davinci_vcif_startup, - .trigger = davinci_vcif_trigger, - .hw_params = davinci_vcif_hw_params, -}; - -static struct snd_soc_dai_driver davinci_vcif_dai = { - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = DAVINCI_VCIF_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = DAVINCI_VCIF_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &davinci_vcif_dai_ops, - -}; - -static int davinci_vcif_probe(struct platform_device *pdev) -{ - struct davinci_vc *davinci_vc = pdev->dev.platform_data; - struct davinci_vcif_dev *davinci_vcif_dev; - int ret; - - davinci_vcif_dev = devm_kzalloc(&pdev->dev, - sizeof(struct davinci_vcif_dev), - GFP_KERNEL); - if (!davinci_vcif_dev) { - dev_dbg(&pdev->dev, - "could not allocate memory for private data\n"); - return -ENOMEM; - } - - /* DMA tx params */ - davinci_vcif_dev->davinci_vc = davinci_vc; - davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = - davinci_vc->davinci_vcif.dma_tx_channel; - davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr = - davinci_vc->davinci_vcif.dma_tx_addr; - - /* DMA rx params */ - davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = - davinci_vc->davinci_vcif.dma_rx_channel; - davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = - davinci_vc->davinci_vcif.dma_rx_addr; - - dev_set_drvdata(&pdev->dev, davinci_vcif_dev); - - ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai); - if (ret != 0) { - dev_err(&pdev->dev, "could not register dai\n"); - return ret; - } - - return 0; -} - -static int davinci_vcif_remove(struct platform_device *pdev) -{ - snd_soc_unregister_dai(&pdev->dev); - - return 0; -} - -static struct platform_driver davinci_vcif_driver = { - .probe = davinci_vcif_probe, - .remove = davinci_vcif_remove, - .driver = { - .name = "davinci-vcif", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(davinci_vcif_driver); - -MODULE_AUTHOR("Miguel Aguilar"); -MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC Voice Codec Interface"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/Kconfig b/ANDROID_3.4.5/sound/soc/ep93xx/Kconfig deleted file mode 100644 index 88143db7..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/Kconfig +++ /dev/null @@ -1,42 +0,0 @@ -config SND_EP93XX_SOC - tristate "SoC Audio support for the Cirrus Logic EP93xx series" - depends on ARCH_EP93XX && SND_SOC - select SND_SOC_DMAENGINE_PCM - help - Say Y or M if you want to add support for codecs attached to - the EP93xx I2S or AC97 interfaces. - -config SND_EP93XX_SOC_I2S - tristate - -config SND_EP93XX_SOC_AC97 - tristate - select AC97_BUS - select SND_SOC_AC97_BUS - -config SND_EP93XX_SOC_SNAPPERCL15 - tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" - depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 - select SND_EP93XX_SOC_I2S - select SND_SOC_TLV320AIC23 - help - Say Y or M here if you want to add support for I2S audio on the - Bluewater Systems Snapper CL15 module. - -config SND_EP93XX_SOC_SIMONE - tristate "SoC Audio support for Simplemachines Sim.One board" - depends on SND_EP93XX_SOC && MACH_SIM_ONE - select SND_EP93XX_SOC_AC97 - select SND_SOC_AC97_CODEC - help - Say Y or M here if you want to add support for AC97 audio on the - Simplemachines Sim.One board. - -config SND_EP93XX_SOC_EDB93XX - tristate "SoC Audio support for Cirrus Logic EDB93xx boards" - depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A) - select SND_EP93XX_SOC_I2S - select SND_SOC_CS4271 - help - Say Y or M here if you want to add support for I2S audio on the - Cirrus Logic EDB93xx boards. diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/Makefile b/ANDROID_3.4.5/sound/soc/ep93xx/Makefile deleted file mode 100644 index 5514146c..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# EP93xx Platform Support -snd-soc-ep93xx-objs := ep93xx-pcm.o -snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o -snd-soc-ep93xx-ac97-objs := ep93xx-ac97.o - -obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o -obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o -obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o - -# EP93XX Machine Support -snd-soc-snappercl15-objs := snappercl15.o -snd-soc-simone-objs := simone.o -snd-soc-edb93xx-objs := edb93xx.o - -obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o -obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o -obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/edb93xx.c b/ANDROID_3.4.5/sound/soc/ep93xx/edb93xx.c deleted file mode 100644 index e01cb02a..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/edb93xx.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SoC audio for EDB93xx - * - * Copyright (c) 2010 Alexander Sverdlin - * - * 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. - * - * This driver support CS4271 codec being master or slave, working - * in control port mode, connected either via SPI or I2C. - * The data format accepted is I2S or left-justified. - * DAPM support not implemented. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "ep93xx-pcm.h" - -static int edb93xx_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int err; - unsigned int mclk_rate; - unsigned int rate = params_rate(params); - - /* - * According to CS4271 datasheet we use MCLK/LRCK=256 for - * rates below 50kHz and 128 for higher sample rates - */ - if (rate < 50000) - mclk_rate = rate * 64 * 4; - else - mclk_rate = rate * 64 * 2; - - err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate, - SND_SOC_CLOCK_IN); - if (err) - return err; - - return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate, - SND_SOC_CLOCK_OUT); -} - -static struct snd_soc_ops edb93xx_ops = { - .hw_params = edb93xx_hw_params, -}; - -static struct snd_soc_dai_link edb93xx_dai = { - .name = "CS4271", - .stream_name = "CS4271 HiFi", - .platform_name = "ep93xx-pcm-audio", - .cpu_dai_name = "ep93xx-i2s", - .codec_name = "spi0.0", - .codec_dai_name = "cs4271-hifi", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | - SND_SOC_DAIFMT_CBS_CFS, - .ops = &edb93xx_ops, -}; - -static struct snd_soc_card snd_soc_edb93xx = { - .name = "EDB93XX", - .owner = THIS_MODULE, - .dai_link = &edb93xx_dai, - .num_links = 1, -}; - -static int __devinit edb93xx_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_edb93xx; - int ret; - - ret = ep93xx_i2s_acquire(); - if (ret) - return ret; - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - ep93xx_i2s_release(); - } - - return ret; -} - -static int __devexit edb93xx_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - ep93xx_i2s_release(); - - return 0; -} - -static struct platform_driver edb93xx_driver = { - .driver = { - .name = "edb93xx-audio", - .owner = THIS_MODULE, - }, - .probe = edb93xx_probe, - .remove = __devexit_p(edb93xx_remove), -}; - -module_platform_driver(edb93xx_driver); - -MODULE_AUTHOR("Alexander Sverdlin "); -MODULE_DESCRIPTION("ALSA SoC EDB93xx"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:edb93xx-audio"); diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-ac97.c b/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-ac97.c deleted file mode 100644 index 0678637a..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-ac97.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * ASoC driver for Cirrus Logic EP93xx AC97 controller. - * - * Copyright (c) 2010 Mika Westerberg - * - * Based on s3c-ac97 ASoC driver by Jaswinder Singh. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include "ep93xx-pcm.h" - -/* - * Per channel (1-4) registers. - */ -#define AC97CH(n) (((n) - 1) * 0x20) - -#define AC97DR(n) (AC97CH(n) + 0x0000) - -#define AC97RXCR(n) (AC97CH(n) + 0x0004) -#define AC97RXCR_REN BIT(0) -#define AC97RXCR_RX3 BIT(3) -#define AC97RXCR_RX4 BIT(4) -#define AC97RXCR_CM BIT(15) - -#define AC97TXCR(n) (AC97CH(n) + 0x0008) -#define AC97TXCR_TEN BIT(0) -#define AC97TXCR_TX3 BIT(3) -#define AC97TXCR_TX4 BIT(4) -#define AC97TXCR_CM BIT(15) - -#define AC97SR(n) (AC97CH(n) + 0x000c) -#define AC97SR_TXFE BIT(1) -#define AC97SR_TXUE BIT(6) - -#define AC97RISR(n) (AC97CH(n) + 0x0010) -#define AC97ISR(n) (AC97CH(n) + 0x0014) -#define AC97IE(n) (AC97CH(n) + 0x0018) - -/* - * Global AC97 controller registers. - */ -#define AC97S1DATA 0x0080 -#define AC97S2DATA 0x0084 -#define AC97S12DATA 0x0088 - -#define AC97RGIS 0x008c -#define AC97GIS 0x0090 -#define AC97IM 0x0094 -/* - * Common bits for RGIS, GIS and IM registers. - */ -#define AC97_SLOT2RXVALID BIT(1) -#define AC97_CODECREADY BIT(5) -#define AC97_SLOT2TXCOMPLETE BIT(6) - -#define AC97EOI 0x0098 -#define AC97EOI_WINT BIT(0) -#define AC97EOI_CODECREADY BIT(1) - -#define AC97GCR 0x009c -#define AC97GCR_AC97IFE BIT(0) - -#define AC97RESET 0x00a0 -#define AC97RESET_TIMEDRESET BIT(0) - -#define AC97SYNC 0x00a4 -#define AC97SYNC_TIMEDSYNC BIT(0) - -#define AC97_TIMEOUT msecs_to_jiffies(5) - -/** - * struct ep93xx_ac97_info - EP93xx AC97 controller info structure - * @lock: mutex serializing access to the bus (slot 1 & 2 ops) - * @dev: pointer to the platform device dev structure - * @mem: physical memory resource for the registers - * @regs: mapped AC97 controller registers - * @irq: AC97 interrupt number - * @done: bus ops wait here for an interrupt - */ -struct ep93xx_ac97_info { - struct mutex lock; - struct device *dev; - struct resource *mem; - void __iomem *regs; - int irq; - struct completion done; -}; - -/* currently ALSA only supports a single AC97 device */ -static struct ep93xx_ac97_info *ep93xx_ac97_info; - -static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = { - .name = "ac97-pcm-out", - .dma_port = EP93XX_DMA_AAC1, -}; - -static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = { - .name = "ac97-pcm-in", - .dma_port = EP93XX_DMA_AAC1, -}; - -static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info, - unsigned reg) -{ - return __raw_readl(info->regs + reg); -} - -static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info, - unsigned reg, unsigned val) -{ - __raw_writel(val, info->regs + reg); -} - -static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct ep93xx_ac97_info *info = ep93xx_ac97_info; - unsigned short val; - - mutex_lock(&info->lock); - - ep93xx_ac97_write_reg(info, AC97S1DATA, reg); - ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID); - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) { - dev_warn(info->dev, "timeout reading register %x\n", reg); - mutex_unlock(&info->lock); - return -ETIMEDOUT; - } - val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA); - - mutex_unlock(&info->lock); - return val; -} - -static void ep93xx_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, - unsigned short val) -{ - struct ep93xx_ac97_info *info = ep93xx_ac97_info; - - mutex_lock(&info->lock); - - /* - * Writes to the codec need to be done so that slot 2 is filled in - * before slot 1. - */ - ep93xx_ac97_write_reg(info, AC97S2DATA, val); - ep93xx_ac97_write_reg(info, AC97S1DATA, reg); - - ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE); - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) - dev_warn(info->dev, "timeout writing register %x\n", reg); - - mutex_unlock(&info->lock); -} - -static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct ep93xx_ac97_info *info = ep93xx_ac97_info; - - mutex_lock(&info->lock); - - /* - * We are assuming that before this functions gets called, the codec - * BIT_CLK is stopped by forcing the codec into powerdown mode. We can - * control the SYNC signal directly via AC97SYNC register. Using - * TIMEDSYNC the controller will keep the SYNC high > 1us. - */ - ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC); - ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY); - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) - dev_warn(info->dev, "codec warm reset timeout\n"); - - mutex_unlock(&info->lock); -} - -static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct ep93xx_ac97_info *info = ep93xx_ac97_info; - - mutex_lock(&info->lock); - - /* - * For doing cold reset, we disable the AC97 controller interface, clear - * WINT and CODECREADY bits, and finally enable the interface again. - */ - ep93xx_ac97_write_reg(info, AC97GCR, 0); - ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT); - ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE); - - /* - * Now, assert the reset and wait for the codec to become ready. - */ - ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET); - ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY); - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) - dev_warn(info->dev, "codec cold reset timeout\n"); - - /* - * Give the codec some time to come fully out from the reset. This way - * we ensure that the subsequent reads/writes will work. - */ - usleep_range(15000, 20000); - - mutex_unlock(&info->lock); -} - -static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id) -{ - struct ep93xx_ac97_info *info = dev_id; - unsigned status, mask; - - /* - * Just mask out the interrupt and wake up the waiting thread. - * Interrupts are cleared via reading/writing to slot 1 & 2 registers by - * the waiting thread. - */ - status = ep93xx_ac97_read_reg(info, AC97GIS); - mask = ep93xx_ac97_read_reg(info, AC97IM); - mask &= ~status; - ep93xx_ac97_write_reg(info, AC97IM, mask); - - complete(&info->done); - return IRQ_HANDLED; -} - -struct snd_ac97_bus_ops soc_ac97_ops = { - .read = ep93xx_ac97_read, - .write = ep93xx_ac97_write, - .reset = ep93xx_ac97_cold_reset, - .warm_reset = ep93xx_ac97_warm_reset, -}; -EXPORT_SYMBOL_GPL(soc_ac97_ops); - -static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai); - unsigned v = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* - * Enable compact mode, TX slots 3 & 4, and the TX FIFO - * itself. - */ - v |= AC97TXCR_CM; - v |= AC97TXCR_TX3 | AC97TXCR_TX4; - v |= AC97TXCR_TEN; - ep93xx_ac97_write_reg(info, AC97TXCR(1), v); - } else { - /* - * Enable compact mode, RX slots 3 & 4, and the RX FIFO - * itself. - */ - v |= AC97RXCR_CM; - v |= AC97RXCR_RX3 | AC97RXCR_RX4; - v |= AC97RXCR_REN; - ep93xx_ac97_write_reg(info, AC97RXCR(1), v); - } - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* - * As per Cirrus EP93xx errata described below: - * - * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf - * - * we will wait for the TX FIFO to be empty before - * clearing the TEN bit. - */ - unsigned long timeout = jiffies + AC97_TIMEOUT; - - do { - v = ep93xx_ac97_read_reg(info, AC97SR(1)); - if (time_after(jiffies, timeout)) { - dev_warn(info->dev, "TX timeout\n"); - break; - } - } while (!(v & (AC97SR_TXFE | AC97SR_TXUE))); - - /* disable the TX FIFO */ - ep93xx_ac97_write_reg(info, AC97TXCR(1), 0); - } else { - /* disable the RX FIFO */ - ep93xx_ac97_write_reg(info, AC97RXCR(1), 0); - } - break; - - default: - dev_warn(info->dev, "unknown command %d\n", cmd); - return -EINVAL; - } - - return 0; -} - -static int ep93xx_ac97_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct ep93xx_pcm_dma_params *dma_data; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dma_data = &ep93xx_ac97_pcm_out; - else - dma_data = &ep93xx_ac97_pcm_in; - - snd_soc_dai_set_dma_data(dai, substream, dma_data); - return 0; -} - -static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { - .startup = ep93xx_ac97_startup, - .trigger = ep93xx_ac97_trigger, -}; - -static struct snd_soc_dai_driver ep93xx_ac97_dai = { - .name = "ep93xx-ac97", - .id = 0, - .ac97_control = 1, - .playback = { - .stream_name = "AC97 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "AC97 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &ep93xx_ac97_dai_ops, -}; - -static int __devinit ep93xx_ac97_probe(struct platform_device *pdev) -{ - struct ep93xx_ac97_info *info; - int ret; - - info = kzalloc(sizeof(struct ep93xx_ac97_info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - dev_set_drvdata(&pdev->dev, info); - - mutex_init(&info->lock); - init_completion(&info->done); - info->dev = &pdev->dev; - - info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!info->mem) { - ret = -ENXIO; - goto fail_free_info; - } - - info->irq = platform_get_irq(pdev, 0); - if (!info->irq) { - ret = -ENXIO; - goto fail_free_info; - } - - if (!request_mem_region(info->mem->start, resource_size(info->mem), - pdev->name)) { - ret = -EBUSY; - goto fail_free_info; - } - - info->regs = ioremap(info->mem->start, resource_size(info->mem)); - if (!info->regs) { - ret = -ENOMEM; - goto fail_release_mem; - } - - ret = request_irq(info->irq, ep93xx_ac97_interrupt, IRQF_TRIGGER_HIGH, - pdev->name, info); - if (ret) - goto fail_unmap_mem; - - ep93xx_ac97_info = info; - platform_set_drvdata(pdev, info); - - ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai); - if (ret) - goto fail_free_irq; - - return 0; - -fail_free_irq: - platform_set_drvdata(pdev, NULL); - free_irq(info->irq, info); -fail_unmap_mem: - iounmap(info->regs); -fail_release_mem: - release_mem_region(info->mem->start, resource_size(info->mem)); -fail_free_info: - kfree(info); - - return ret; -} - -static int __devexit ep93xx_ac97_remove(struct platform_device *pdev) -{ - struct ep93xx_ac97_info *info = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - - /* disable the AC97 controller */ - ep93xx_ac97_write_reg(info, AC97GCR, 0); - - free_irq(info->irq, info); - iounmap(info->regs); - release_mem_region(info->mem->start, resource_size(info->mem)); - platform_set_drvdata(pdev, NULL); - kfree(info); - - return 0; -} - -static struct platform_driver ep93xx_ac97_driver = { - .probe = ep93xx_ac97_probe, - .remove = __devexit_p(ep93xx_ac97_remove), - .driver = { - .name = "ep93xx-ac97", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(ep93xx_ac97_driver); - -MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver"); -MODULE_AUTHOR("Mika Westerberg "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ep93xx-ac97"); diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-i2s.c b/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-i2s.c deleted file mode 100644 index f7a62348..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-i2s.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - * linux/sound/soc/ep93xx-i2s.c - * EP93xx I2S driver - * - * Copyright (C) 2010 Ryan Mallon - * - * Based on the original driver by: - * Copyright (C) 2007 Chase Douglas - * Copyright (C) 2006 Lennert Buytenhek - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ep93xx-pcm.h" - -#define EP93XX_I2S_TXCLKCFG 0x00 -#define EP93XX_I2S_RXCLKCFG 0x04 -#define EP93XX_I2S_GLCTRL 0x0C - -#define EP93XX_I2S_TXLINCTRLDATA 0x28 -#define EP93XX_I2S_TXCTRL 0x2C -#define EP93XX_I2S_TXWRDLEN 0x30 -#define EP93XX_I2S_TX0EN 0x34 - -#define EP93XX_I2S_RXLINCTRLDATA 0x58 -#define EP93XX_I2S_RXCTRL 0x5C -#define EP93XX_I2S_RXWRDLEN 0x60 -#define EP93XX_I2S_RX0EN 0x64 - -#define EP93XX_I2S_WRDLEN_16 (0 << 0) -#define EP93XX_I2S_WRDLEN_24 (1 << 0) -#define EP93XX_I2S_WRDLEN_32 (2 << 0) - -#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */ - -#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */ -#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */ -#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */ -#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */ -#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */ - -struct ep93xx_i2s_info { - struct clk *mclk; - struct clk *sclk; - struct clk *lrclk; - struct ep93xx_pcm_dma_params *dma_params; - struct resource *mem; - void __iomem *regs; -}; - -struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = { - [SNDRV_PCM_STREAM_PLAYBACK] = { - .name = "i2s-pcm-out", - .dma_port = EP93XX_DMA_I2S1, - }, - [SNDRV_PCM_STREAM_CAPTURE] = { - .name = "i2s-pcm-in", - .dma_port = EP93XX_DMA_I2S1, - }, -}; - -static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info, - unsigned reg, unsigned val) -{ - __raw_writel(val, info->regs + reg); -} - -static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info, - unsigned reg) -{ - return __raw_readl(info->regs + reg); -} - -static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream) -{ - unsigned base_reg; - int i; - - if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && - (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { - /* Enable clocks */ - clk_enable(info->mclk); - clk_enable(info->sclk); - clk_enable(info->lrclk); - - /* Enable i2s */ - ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1); - } - - /* Enable fifos */ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - base_reg = EP93XX_I2S_TX0EN; - else - base_reg = EP93XX_I2S_RX0EN; - for (i = 0; i < 3; i++) - ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1); -} - -static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream) -{ - unsigned base_reg; - int i; - - /* Disable fifos */ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - base_reg = EP93XX_I2S_TX0EN; - else - base_reg = EP93XX_I2S_RX0EN; - for (i = 0; i < 3; i++) - ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0); - - if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 && - (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) { - /* Disable i2s */ - ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0); - - /* Disable clocks */ - clk_disable(info->lrclk); - clk_disable(info->sclk); - clk_disable(info->mclk); - } -} - -static int ep93xx_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - - snd_soc_dai_set_dma_data(cpu_dai, substream, - &info->dma_params[substream->stream]); - return 0; -} - -static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - - ep93xx_i2s_disable(info, substream->stream); -} - -static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); - unsigned int clk_cfg, lin_ctrl; - - clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); - lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA); - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - clk_cfg |= EP93XX_I2S_CLKCFG_REL; - lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; - break; - - case SND_SOC_DAIFMT_LEFT_J: - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST; - break; - - case SND_SOC_DAIFMT_RIGHT_J: - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST; - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* CPU is master */ - clk_cfg |= EP93XX_I2S_CLKCFG_MASTER; - break; - - case SND_SOC_DAIFMT_CBM_CFM: - /* Codec is master */ - clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER; - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - /* Negative bit clock, lrclk low on left word */ - clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL); - break; - - case SND_SOC_DAIFMT_NB_IF: - /* Negative bit clock, lrclk low on right word */ - clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP; - clk_cfg |= EP93XX_I2S_CLKCFG_REL; - break; - - case SND_SOC_DAIFMT_IB_NF: - /* Positive bit clock, lrclk low on left word */ - clk_cfg |= EP93XX_I2S_CLKCFG_CKP; - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL; - break; - - case SND_SOC_DAIFMT_IB_IF: - /* Positive bit clock, lrclk low on right word */ - clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL; - break; - } - - /* Write new register values */ - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg); - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg); - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl); - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl); - return 0; -} - -static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - unsigned word_len, div, sdiv, lrdiv; - int err; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - word_len = EP93XX_I2S_WRDLEN_16; - break; - - case SNDRV_PCM_FORMAT_S24_LE: - word_len = EP93XX_I2S_WRDLEN_24; - break; - - case SNDRV_PCM_FORMAT_S32_LE: - word_len = EP93XX_I2S_WRDLEN_32; - break; - - default: - return -EINVAL; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len); - else - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len); - - /* - * EP93xx I2S module can be setup so SCLK / LRCLK value can be - * 32, 64, 128. MCLK / SCLK value can be 2 and 4. - * We set LRCLK equal to `rate' and minimum SCLK / LRCLK - * value is 64, because our sample size is 32 bit * 2 channels. - * I2S standard permits us to transmit more bits than - * the codec uses. - */ - div = clk_get_rate(info->mclk) / params_rate(params); - sdiv = 4; - if (div > (256 + 512) / 2) { - lrdiv = 128; - } else { - lrdiv = 64; - if (div < (128 + 256) / 2) - sdiv = 2; - } - - err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); - if (err) - return err; - - err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv); - if (err) - return err; - - ep93xx_i2s_enable(info, substream->stream); - return 0; -} - -static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, - unsigned int freq, int dir) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai); - - if (dir == SND_SOC_CLOCK_IN || clk_id != 0) - return -EINVAL; - - return clk_set_rate(info->mclk, freq); -} - -#ifdef CONFIG_PM -static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - - if (!dai->active) - return 0; - - ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); - ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); - - return 0; -} - -static int ep93xx_i2s_resume(struct snd_soc_dai *dai) -{ - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); - - if (!dai->active) - return 0; - - ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); - ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); - - return 0; -} -#else -#define ep93xx_i2s_suspend NULL -#define ep93xx_i2s_resume NULL -#endif - -static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { - .startup = ep93xx_i2s_startup, - .shutdown = ep93xx_i2s_shutdown, - .hw_params = ep93xx_i2s_hw_params, - .set_sysclk = ep93xx_i2s_set_sysclk, - .set_fmt = ep93xx_i2s_set_dai_fmt, -}; - -#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_driver ep93xx_i2s_dai = { - .symmetric_rates= 1, - .suspend = ep93xx_i2s_suspend, - .resume = ep93xx_i2s_resume, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = EP93XX_I2S_FORMATS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = EP93XX_I2S_FORMATS, - }, - .ops = &ep93xx_i2s_dai_ops, -}; - -static int ep93xx_i2s_probe(struct platform_device *pdev) -{ - struct ep93xx_i2s_info *info; - struct resource *res; - int err; - - info = kzalloc(sizeof(struct ep93xx_i2s_info), GFP_KERNEL); - if (!info) { - err = -ENOMEM; - goto fail; - } - - dev_set_drvdata(&pdev->dev, info); - info->dma_params = ep93xx_i2s_dma_params; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - err = -ENODEV; - goto fail_free_info; - } - - info->mem = request_mem_region(res->start, resource_size(res), - pdev->name); - if (!info->mem) { - err = -EBUSY; - goto fail_free_info; - } - - info->regs = ioremap(info->mem->start, resource_size(info->mem)); - if (!info->regs) { - err = -ENXIO; - goto fail_release_mem; - } - - info->mclk = clk_get(&pdev->dev, "mclk"); - if (IS_ERR(info->mclk)) { - err = PTR_ERR(info->mclk); - goto fail_unmap_mem; - } - - info->sclk = clk_get(&pdev->dev, "sclk"); - if (IS_ERR(info->sclk)) { - err = PTR_ERR(info->sclk); - goto fail_put_mclk; - } - - info->lrclk = clk_get(&pdev->dev, "lrclk"); - if (IS_ERR(info->lrclk)) { - err = PTR_ERR(info->lrclk); - goto fail_put_sclk; - } - - err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai); - if (err) - goto fail_put_lrclk; - - return 0; - -fail_put_lrclk: - clk_put(info->lrclk); -fail_put_sclk: - clk_put(info->sclk); -fail_put_mclk: - clk_put(info->mclk); -fail_unmap_mem: - iounmap(info->regs); -fail_release_mem: - release_mem_region(info->mem->start, resource_size(info->mem)); -fail_free_info: - kfree(info); -fail: - return err; -} - -static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) -{ - struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_dai(&pdev->dev); - clk_put(info->lrclk); - clk_put(info->sclk); - clk_put(info->mclk); - iounmap(info->regs); - release_mem_region(info->mem->start, resource_size(info->mem)); - kfree(info); - return 0; -} - -static struct platform_driver ep93xx_i2s_driver = { - .probe = ep93xx_i2s_probe, - .remove = __devexit_p(ep93xx_i2s_remove), - .driver = { - .name = "ep93xx-i2s", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(ep93xx_i2s_driver); - -MODULE_ALIAS("platform:ep93xx-i2s"); -MODULE_AUTHOR("Ryan Mallon"); -MODULE_DESCRIPTION("EP93XX I2S driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.c b/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.c deleted file mode 100644 index 162dbb74..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface - * - * Copyright (C) 2006 Lennert Buytenhek - * Copyright (C) 2006 Applied Data Systems - * - * Rewritten for the SoC audio subsystem (Based on PXA2xx code): - * Copyright (c) 2008 Ryan Mallon - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ep93xx-pcm.h" - -static const struct snd_pcm_hardware ep93xx_pcm_hardware = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - - .rates = SNDRV_PCM_RATE_8000_192000, - .rate_min = SNDRV_PCM_RATE_8000, - .rate_max = SNDRV_PCM_RATE_192000, - - .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE), - - .buffer_bytes_max = 131072, - .period_bytes_min = 32, - .period_bytes_max = 32768, - .periods_min = 1, - .periods_max = 32, - .fifo_size = 32, -}; - -static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) -{ - struct ep93xx_dma_data *data = filter_param; - - if (data->direction == ep93xx_dma_chan_direction(chan)) { - chan->private = data; - return true; - } - - return false; -} - -static int ep93xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct ep93xx_pcm_dma_params *dma_params; - struct ep93xx_dma_data *dma_data; - int ret; - - snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); - - dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL); - if (!dma_data) - return -ENOMEM; - - dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); - dma_data->port = dma_params->dma_port; - dma_data->name = dma_params->name; - dma_data->direction = snd_pcm_substream_to_dma_direction(substream); - - ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data); - if (ret) { - kfree(dma_data); - return ret; - } - - snd_dmaengine_pcm_set_data(substream, dma_data); - - return 0; -} - -static int ep93xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); - - snd_dmaengine_pcm_close(substream); - kfree(dma_data); - return 0; -} - -static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - return 0; -} - -static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - -static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - -static struct snd_pcm_ops ep93xx_pcm_ops = { - .open = ep93xx_pcm_open, - .close = ep93xx_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = ep93xx_pcm_hw_params, - .hw_free = ep93xx_pcm_hw_free, - .trigger = snd_dmaengine_pcm_trigger, - .pointer = snd_dmaengine_pcm_pointer, - .mmap = ep93xx_pcm_mmap, -}; - -static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = ep93xx_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - buf->bytes = size; - - return (buf->area == NULL) ? -ENOMEM : 0; -} - -static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area, - buf->addr); - buf->area = NULL; - } -} - -static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32); - -static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &ep93xx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = ep93xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - return ret; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = ep93xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - return ret; - } - - return 0; -} - -static struct snd_soc_platform_driver ep93xx_soc_platform = { - .ops = &ep93xx_pcm_ops, - .pcm_new = &ep93xx_pcm_new, - .pcm_free = &ep93xx_pcm_free_dma_buffers, -}; - -static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform); -} - -static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver ep93xx_pcm_driver = { - .driver = { - .name = "ep93xx-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = ep93xx_soc_platform_probe, - .remove = __devexit_p(ep93xx_soc_platform_remove), -}; - -module_platform_driver(ep93xx_pcm_driver); - -MODULE_AUTHOR("Ryan Mallon"); -MODULE_DESCRIPTION("EP93xx ALSA PCM interface"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ep93xx-pcm-audio"); diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.h b/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.h deleted file mode 100644 index 111e1121..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/ep93xx-pcm.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface - * - * Copyright (C) 2006 Lennert Buytenhek - * Copyright (C) 2006 Applied Data Systems - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _EP93XX_SND_SOC_PCM_H -#define _EP93XX_SND_SOC_PCM_H - -struct ep93xx_pcm_dma_params { - char *name; - int dma_port; -}; - -#endif /* _EP93XX_SND_SOC_PCM_H */ diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/simone.c b/ANDROID_3.4.5/sound/soc/ep93xx/simone.c deleted file mode 100644 index dd997094..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/simone.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * simone.c -- ASoC audio for Simplemachines Sim.One board - * - * Copyright (c) 2010 Mika Westerberg - * - * Based on snappercl15 machine driver by Ryan Mallon. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "ep93xx-pcm.h" - -static struct snd_soc_dai_link simone_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - .cpu_dai_name = "ep93xx-ac97", - .codec_dai_name = "ac97-hifi", - .codec_name = "ac97-codec", - .platform_name = "ep93xx-pcm-audio", -}; - -static struct snd_soc_card snd_soc_simone = { - .name = "Sim.One", - .owner = THIS_MODULE, - .dai_link = &simone_dai, - .num_links = 1, -}; - -static struct platform_device *simone_snd_ac97_device; - -static int __devinit simone_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_simone; - int ret; - - simone_snd_ac97_device = platform_device_register_simple("ac97-codec", - -1, NULL, 0); - if (IS_ERR(simone_snd_ac97_device)) - return PTR_ERR(simone_snd_ac97_device); - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - platform_device_unregister(simone_snd_ac97_device); - } - - return ret; -} - -static int __devexit simone_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - platform_device_unregister(simone_snd_ac97_device); - - return 0; -} - -static struct platform_driver simone_driver = { - .driver = { - .name = "simone-audio", - .owner = THIS_MODULE, - }, - .probe = simone_probe, - .remove = __devexit_p(simone_remove), -}; - -module_platform_driver(simone_driver); - -MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One"); -MODULE_AUTHOR("Mika Westerberg "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:simone-audio"); diff --git a/ANDROID_3.4.5/sound/soc/ep93xx/snappercl15.c b/ANDROID_3.4.5/sound/soc/ep93xx/snappercl15.c deleted file mode 100644 index a193cea3..00000000 --- a/ANDROID_3.4.5/sound/soc/ep93xx/snappercl15.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module - * - * Copyright (C) 2008 Bluewater Systems Ltd - * Author: Ryan Mallon - * - * 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. - * - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include "../codecs/tlv320aic23.h" -#include "ep93xx-pcm.h" - -#define CODEC_CLOCK 5644800 - -static int snappercl15_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int err; - - err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, - SND_SOC_CLOCK_IN); - if (err) - return err; - - err = snd_soc_dai_set_sysclk(cpu_dai, 0, CODEC_CLOCK, - SND_SOC_CLOCK_OUT); - if (err) - return err; - - return 0; -} - -static struct snd_soc_ops snappercl15_ops = { - .hw_params = snappercl15_hw_params, -}; - -static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - {"Headphone Jack", NULL, "LHPOUT"}, - {"Headphone Jack", NULL, "RHPOUT"}, - - {"LLINEIN", NULL, "Line In"}, - {"RLINEIN", NULL, "Line In"}, - - {"MICIN", NULL, "Mic Jack"}, -}; - -static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets, - ARRAY_SIZE(tlv320aic23_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; -} - -static struct snd_soc_dai_link snappercl15_dai = { - .name = "tlv320aic23", - .stream_name = "AIC23", - .cpu_dai_name = "ep93xx-i2s", - .codec_dai_name = "tlv320aic23-hifi", - .codec_name = "tlv320aic23-codec.0-001a", - .platform_name = "ep93xx-pcm-audio", - .init = snappercl15_tlv320aic23_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | - SND_SOC_DAIFMT_CBS_CFS, - .ops = &snappercl15_ops, -}; - -static struct snd_soc_card snd_soc_snappercl15 = { - .name = "Snapper CL15", - .owner = THIS_MODULE, - .dai_link = &snappercl15_dai, - .num_links = 1, -}; - -static int __devinit snappercl15_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &snd_soc_snappercl15; - int ret; - - ret = ep93xx_i2s_acquire(); - if (ret) - return ret; - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - ep93xx_i2s_release(); - } - - return ret; -} - -static int __devexit snappercl15_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - ep93xx_i2s_release(); - - return 0; -} - -static struct platform_driver snappercl15_driver = { - .driver = { - .name = "snappercl15-audio", - .owner = THIS_MODULE, - }, - .probe = snappercl15_probe, - .remove = __devexit_p(snappercl15_remove), -}; - -module_platform_driver(snappercl15_driver); - -MODULE_AUTHOR("Ryan Mallon"); -MODULE_DESCRIPTION("ALSA SoC Snapper CL15"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:snappercl15-audio"); diff --git a/ANDROID_3.4.5/sound/soc/fsl/Kconfig b/ANDROID_3.4.5/sound/soc/fsl/Kconfig deleted file mode 100644 index d754d34d..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/Kconfig +++ /dev/null @@ -1,67 +0,0 @@ -config SND_MPC52xx_DMA - tristate - -# ASoC platform support for the Freescale PowerPC SOCs that have an SSI and -# an Elo DMA controller, such as the MPC8610 and P1022. You will still need to -# select a platform driver and a codec driver. -config SND_SOC_POWERPC_SSI - tristate - depends on FSL_SOC - -config SND_SOC_MPC8610_HPCD - tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" - # I2C is necessary for the CS4270 driver - depends on MPC8610_HPCD && I2C - select SND_SOC_POWERPC_SSI - select SND_SOC_CS4270 - select SND_SOC_CS4270_VD33_ERRATA - default y if MPC8610_HPCD - help - Say Y if you want to enable audio on the Freescale MPC8610 HPCD. - -config SND_SOC_P1022_DS - tristate "ALSA SoC support for the Freescale P1022 DS board" - # I2C is necessary for the WM8776 driver - depends on P1022_DS && I2C - select SND_SOC_POWERPC_SSI - select SND_SOC_WM8776 - default y if P1022_DS - help - Say Y if you want to enable audio on the Freescale P1022 DS board. - This will also include the Wolfson Microelectronics WM8776 codec - driver. - -config SND_SOC_MPC5200_I2S - tristate "Freescale MPC5200 PSC in I2S mode driver" - depends on PPC_MPC52xx && PPC_BESTCOMM - select SND_MPC52xx_DMA - select PPC_BESTCOMM_GEN_BD - help - Say Y here to support the MPC5200 PSCs in I2S mode. - -config SND_SOC_MPC5200_AC97 - tristate "Freescale MPC5200 PSC in AC97 mode driver" - depends on PPC_MPC52xx && PPC_BESTCOMM - select SND_SOC_AC97_BUS - select SND_MPC52xx_DMA - select PPC_BESTCOMM_GEN_BD - help - Say Y here to support the MPC5200 PSCs in AC97 mode. - -config SND_MPC52xx_SOC_PCM030 - tristate "SoC AC97 Audio support for Phytec pcm030 and WM9712" - depends on PPC_MPC5200_SIMPLE - select SND_SOC_MPC5200_AC97 - select SND_SOC_WM9712 - help - Say Y if you want to add support for sound on the Phytec pcm030 - baseboard. - -config SND_MPC52xx_SOC_EFIKA - tristate "SoC AC97 Audio support for bbplan Efika and STAC9766" - depends on PPC_EFIKA - select SND_SOC_MPC5200_AC97 - select SND_SOC_STAC9766 - help - Say Y if you want to add support for sound on the Efika. - diff --git a/ANDROID_3.4.5/sound/soc/fsl/Makefile b/ANDROID_3.4.5/sound/soc/fsl/Makefile deleted file mode 100644 index b4a38c0a..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# MPC8610 HPCD Machine Support -snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o -obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o - -# P1022 DS Machine Support -snd-soc-p1022-ds-objs := p1022_ds.o -obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o - -# Freescale PowerPC SSI/DMA Platform Support -snd-soc-fsl-ssi-objs := fsl_ssi.o -snd-soc-fsl-dma-objs := fsl_dma.o -obj-$(CONFIG_SND_SOC_POWERPC_SSI) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o - -# MPC5200 Platform Support -obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o -obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o -obj-$(CONFIG_SND_SOC_MPC5200_AC97) += mpc5200_psc_ac97.o - -# MPC5200 Machine Support -obj-$(CONFIG_SND_MPC52xx_SOC_PCM030) += pcm030-audio-fabric.o -obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o - diff --git a/ANDROID_3.4.5/sound/soc/fsl/efika-audio-fabric.c b/ANDROID_3.4.5/sound/soc/fsl/efika-audio-fabric.c deleted file mode 100644 index b2acd329..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/efika-audio-fabric.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Efika driver for the PSC of the Freescale MPC52xx - * configured as AC97 interface - * - * Copyright 2008 Jon Smirl, Digispeaker - * Author: Jon Smirl - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "mpc5200_dma.h" -#include "mpc5200_psc_ac97.h" -#include "../codecs/stac9766.h" - -#define DRV_NAME "efika-audio-fabric" - -static struct snd_soc_dai_link efika_fabric_dai[] = { -{ - .name = "AC97", - .stream_name = "AC97 Analog", - .codec_dai_name = "stac9766-hifi-analog", - .cpu_dai_name = "mpc5200-psc-ac97.0", - .platform_name = "mpc5200-pcm-audio", - .codec_name = "stac9766-codec", -}, -{ - .name = "AC97", - .stream_name = "AC97 IEC958", - .codec_dai_name = "stac9766-hifi-IEC958", - .cpu_dai_name = "mpc5200-psc-ac97.1", - .platform_name = "mpc5200-pcm-audio", - .codec_name = "stac9766-codec", -}, -}; - -static struct snd_soc_card card = { - .name = "Efika", - .owner = THIS_MODULE, - .dai_link = efika_fabric_dai, - .num_links = ARRAY_SIZE(efika_fabric_dai), -}; - -static __init int efika_fabric_init(void) -{ - struct platform_device *pdev; - int rc; - - if (!of_machine_is_compatible("bplan,efika")) - return -ENODEV; - - pdev = platform_device_alloc("soc-audio", 1); - if (!pdev) { - pr_err("efika_fabric_init: platform_device_alloc() failed\n"); - return -ENODEV; - } - - platform_set_drvdata(pdev, &card); - - rc = platform_device_add(pdev); - if (rc) { - pr_err("efika_fabric_init: platform_device_add() failed\n"); - platform_device_put(pdev); - return -ENODEV; - } - return 0; -} - -module_init(efika_fabric_init); - - -MODULE_AUTHOR("Jon Smirl "); -MODULE_DESCRIPTION(DRV_NAME ": mpc5200 Efika fabric driver"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/fsl/fsl_dma.c b/ANDROID_3.4.5/sound/soc/fsl/fsl_dma.c deleted file mode 100644 index 96bb92dd..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/fsl_dma.c +++ /dev/null @@ -1,999 +0,0 @@ -/* - * Freescale DMA ALSA SoC PCM driver - * - * Author: Timur Tabi - * - * Copyright 2007-2010 Freescale Semiconductor, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - * - * This driver implements ASoC support for the Elo DMA controller, which is - * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms, - * the PCM driver is what handles the DMA buffer. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "fsl_dma.h" -#include "fsl_ssi.h" /* For the offset of stx0 and srx0 */ - -/* - * The formats that the DMA controller supports, which is anything - * that is 8, 16, or 32 bits. - */ -#define FSLDMA_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_U8 | \ - SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_U16_LE | \ - SNDRV_PCM_FMTBIT_U16_BE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S24_BE | \ - SNDRV_PCM_FMTBIT_U24_LE | \ - SNDRV_PCM_FMTBIT_U24_BE | \ - SNDRV_PCM_FMTBIT_S32_LE | \ - SNDRV_PCM_FMTBIT_S32_BE | \ - SNDRV_PCM_FMTBIT_U32_LE | \ - SNDRV_PCM_FMTBIT_U32_BE) - -#define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ - SNDRV_PCM_RATE_CONTINUOUS) - -struct dma_object { - struct snd_soc_platform_driver dai; - dma_addr_t ssi_stx_phys; - dma_addr_t ssi_srx_phys; - unsigned int ssi_fifo_depth; - struct ccsr_dma_channel __iomem *channel; - unsigned int irq; - bool assigned; - char path[1]; -}; - -/* - * The number of DMA links to use. Two is the bare minimum, but if you - * have really small links you might need more. - */ -#define NUM_DMA_LINKS 2 - -/** fsl_dma_private: p-substream DMA data - * - * Each substream has a 1-to-1 association with a DMA channel. - * - * The link[] array is first because it needs to be aligned on a 32-byte - * boundary, so putting it first will ensure alignment without padding the - * structure. - * - * @link[]: array of link descriptors - * @dma_channel: pointer to the DMA channel's registers - * @irq: IRQ for this DMA channel - * @substream: pointer to the substream object, needed by the ISR - * @ssi_sxx_phys: bus address of the STX or SRX register to use - * @ld_buf_phys: physical address of the LD buffer - * @current_link: index into link[] of the link currently being processed - * @dma_buf_phys: physical address of the DMA buffer - * @dma_buf_next: physical address of the next period to process - * @dma_buf_end: physical address of the byte after the end of the DMA - * @buffer period_size: the size of a single period - * @num_periods: the number of periods in the DMA buffer - */ -struct fsl_dma_private { - struct fsl_dma_link_descriptor link[NUM_DMA_LINKS]; - struct ccsr_dma_channel __iomem *dma_channel; - unsigned int irq; - struct snd_pcm_substream *substream; - dma_addr_t ssi_sxx_phys; - unsigned int ssi_fifo_depth; - dma_addr_t ld_buf_phys; - unsigned int current_link; - dma_addr_t dma_buf_phys; - dma_addr_t dma_buf_next; - dma_addr_t dma_buf_end; - size_t period_size; - unsigned int num_periods; -}; - -/** - * fsl_dma_hardare: define characteristics of the PCM hardware. - * - * The PCM hardware is the Freescale DMA controller. This structure defines - * the capabilities of that hardware. - * - * Since the sampling rate and data format are not controlled by the DMA - * controller, we specify no limits for those values. The only exception is - * period_bytes_min, which is set to a reasonably low value to prevent the - * DMA controller from generating too many interrupts per second. - * - * Since each link descriptor has a 32-bit byte count field, we set - * period_bytes_max to the largest 32-bit number. We also have no maximum - * number of periods. - * - * Note that we specify SNDRV_PCM_INFO_JOINT_DUPLEX here, but only because a - * limitation in the SSI driver requires the sample rates for playback and - * capture to be the same. - */ -static const struct snd_pcm_hardware fsl_dma_hardware = { - - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_PAUSE, - .formats = FSLDMA_PCM_FORMATS, - .rates = FSLDMA_PCM_RATES, - .rate_min = 5512, - .rate_max = 192000, - .period_bytes_min = 512, /* A reasonable limit */ - .period_bytes_max = (u32) -1, - .periods_min = NUM_DMA_LINKS, - .periods_max = (unsigned int) -1, - .buffer_bytes_max = 128 * 1024, /* A reasonable limit */ -}; - -/** - * fsl_dma_abort_stream: tell ALSA that the DMA transfer has aborted - * - * This function should be called by the ISR whenever the DMA controller - * halts data transfer. - */ -static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) -{ - unsigned long flags; - - snd_pcm_stream_lock_irqsave(substream, flags); - - if (snd_pcm_running(substream)) - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - - snd_pcm_stream_unlock_irqrestore(substream, flags); -} - -/** - * fsl_dma_update_pointers - update LD pointers to point to the next period - * - * As each period is completed, this function changes the the link - * descriptor pointers for that period to point to the next period. - */ -static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private) -{ - struct fsl_dma_link_descriptor *link = - &dma_private->link[dma_private->current_link]; - - /* Update our link descriptors to point to the next period. On a 36-bit - * system, we also need to update the ESAD bits. We also set (keep) the - * snoop bits. See the comments in fsl_dma_hw_params() about snooping. - */ - if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - link->source_addr = cpu_to_be32(dma_private->dma_buf_next); -#ifdef CONFIG_PHYS_64BIT - link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | - upper_32_bits(dma_private->dma_buf_next)); -#endif - } else { - link->dest_addr = cpu_to_be32(dma_private->dma_buf_next); -#ifdef CONFIG_PHYS_64BIT - link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | - upper_32_bits(dma_private->dma_buf_next)); -#endif - } - - /* Update our variables for next time */ - dma_private->dma_buf_next += dma_private->period_size; - - if (dma_private->dma_buf_next >= dma_private->dma_buf_end) - dma_private->dma_buf_next = dma_private->dma_buf_phys; - - if (++dma_private->current_link >= NUM_DMA_LINKS) - dma_private->current_link = 0; -} - -/** - * fsl_dma_isr: interrupt handler for the DMA controller - * - * @irq: IRQ of the DMA channel - * @dev_id: pointer to the dma_private structure for this DMA channel - */ -static irqreturn_t fsl_dma_isr(int irq, void *dev_id) -{ - struct fsl_dma_private *dma_private = dev_id; - struct snd_pcm_substream *substream = dma_private->substream; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct device *dev = rtd->platform->dev; - struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; - irqreturn_t ret = IRQ_NONE; - u32 sr, sr2 = 0; - - /* We got an interrupt, so read the status register to see what we - were interrupted for. - */ - sr = in_be32(&dma_channel->sr); - - if (sr & CCSR_DMA_SR_TE) { - dev_err(dev, "dma transmit error\n"); - fsl_dma_abort_stream(substream); - sr2 |= CCSR_DMA_SR_TE; - ret = IRQ_HANDLED; - } - - if (sr & CCSR_DMA_SR_CH) - ret = IRQ_HANDLED; - - if (sr & CCSR_DMA_SR_PE) { - dev_err(dev, "dma programming error\n"); - fsl_dma_abort_stream(substream); - sr2 |= CCSR_DMA_SR_PE; - ret = IRQ_HANDLED; - } - - if (sr & CCSR_DMA_SR_EOLNI) { - sr2 |= CCSR_DMA_SR_EOLNI; - ret = IRQ_HANDLED; - } - - if (sr & CCSR_DMA_SR_CB) - ret = IRQ_HANDLED; - - if (sr & CCSR_DMA_SR_EOSI) { - /* Tell ALSA we completed a period. */ - snd_pcm_period_elapsed(substream); - - /* - * Update our link descriptors to point to the next period. We - * only need to do this if the number of periods is not equal to - * the number of links. - */ - if (dma_private->num_periods != NUM_DMA_LINKS) - fsl_dma_update_pointers(dma_private); - - sr2 |= CCSR_DMA_SR_EOSI; - ret = IRQ_HANDLED; - } - - if (sr & CCSR_DMA_SR_EOLSI) { - sr2 |= CCSR_DMA_SR_EOLSI; - ret = IRQ_HANDLED; - } - - /* Clear the bits that we set */ - if (sr2) - out_be32(&dma_channel->sr, sr2); - - return ret; -} - -/** - * fsl_dma_new: initialize this PCM driver. - * - * This function is called when the codec driver calls snd_soc_new_pcms(), - * once for each .dai_link in the machine driver's snd_soc_card - * structure. - * - * snd_dma_alloc_pages() is just a front-end to dma_alloc_coherent(), which - * (currently) always allocates the DMA buffer in lowmem, even if GFP_HIGHMEM - * is specified. Therefore, any DMA buffers we allocate will always be in low - * memory, but we support for 36-bit physical addresses anyway. - * - * Regardless of where the memory is actually allocated, since the device can - * technically DMA to any 36-bit address, we do need to set the DMA mask to 36. - */ -static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - static u64 fsl_dma_dmamask = DMA_BIT_MASK(36); - int ret; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &fsl_dma_dmamask; - - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = fsl_dma_dmamask; - - /* Some codecs have separate DAIs for playback and capture, so we - * should allocate a DMA buffer only for the streams that are valid. - */ - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, - fsl_dma_hardware.buffer_bytes_max, - &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer); - if (ret) { - dev_err(card->dev, "can't alloc playback dma buffer\n"); - return ret; - } - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, - fsl_dma_hardware.buffer_bytes_max, - &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer); - if (ret) { - dev_err(card->dev, "can't alloc capture dma buffer\n"); - snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer); - return ret; - } - } - - return 0; -} - -/** - * fsl_dma_open: open a new substream. - * - * Each substream has its own DMA buffer. - * - * ALSA divides the DMA buffer into N periods. We create NUM_DMA_LINKS link - * descriptors that ping-pong from one period to the next. For example, if - * there are six periods and two link descriptors, this is how they look - * before playback starts: - * - * The last link descriptor - * ____________ points back to the first - * | | - * V | - * ___ ___ | - * | |->| |->| - * |___| |___| - * | | - * | | - * V V - * _________________________________________ - * | | | | | | | The DMA buffer is - * | | | | | | | divided into 6 parts - * |______|______|______|______|______|______| - * - * and here's how they look after the first period is finished playing: - * - * ____________ - * | | - * V | - * ___ ___ | - * | |->| |->| - * |___| |___| - * | | - * |______________ - * | | - * V V - * _________________________________________ - * | | | | | | | - * | | | | | | | - * |______|______|______|______|______|______| - * - * The first link descriptor now points to the third period. The DMA - * controller is currently playing the second period. When it finishes, it - * will jump back to the first descriptor and play the third period. - * - * There are four reasons we do this: - * - * 1. The only way to get the DMA controller to automatically restart the - * transfer when it gets to the end of the buffer is to use chaining - * mode. Basic direct mode doesn't offer that feature. - * 2. We need to receive an interrupt at the end of every period. The DMA - * controller can generate an interrupt at the end of every link transfer - * (aka segment). Making each period into a DMA segment will give us the - * interrupts we need. - * 3. By creating only two link descriptors, regardless of the number of - * periods, we do not need to reallocate the link descriptors if the - * number of periods changes. - * 4. All of the audio data is still stored in a single, contiguous DMA - * buffer, which is what ALSA expects. We're just dividing it into - * contiguous parts, and creating a link descriptor for each one. - */ -static int fsl_dma_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct device *dev = rtd->platform->dev; - struct dma_object *dma = - container_of(rtd->platform->driver, struct dma_object, dai); - struct fsl_dma_private *dma_private; - struct ccsr_dma_channel __iomem *dma_channel; - dma_addr_t ld_buf_phys; - u64 temp_link; /* Pointer to next link descriptor */ - u32 mr; - unsigned int channel; - int ret = 0; - unsigned int i; - - /* - * Reject any DMA buffer whose size is not a multiple of the period - * size. We need to make sure that the DMA buffer can be evenly divided - * into periods. - */ - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) { - dev_err(dev, "invalid buffer size\n"); - return ret; - } - - channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; - - if (dma->assigned) { - dev_err(dev, "dma channel already assigned\n"); - return -EBUSY; - } - - dma_private = dma_alloc_coherent(dev, sizeof(struct fsl_dma_private), - &ld_buf_phys, GFP_KERNEL); - if (!dma_private) { - dev_err(dev, "can't allocate dma private data\n"); - return -ENOMEM; - } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dma_private->ssi_sxx_phys = dma->ssi_stx_phys; - else - dma_private->ssi_sxx_phys = dma->ssi_srx_phys; - - dma_private->ssi_fifo_depth = dma->ssi_fifo_depth; - dma_private->dma_channel = dma->channel; - dma_private->irq = dma->irq; - dma_private->substream = substream; - dma_private->ld_buf_phys = ld_buf_phys; - dma_private->dma_buf_phys = substream->dma_buffer.addr; - - ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "fsldma-audio", - dma_private); - if (ret) { - dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", - dma_private->irq, ret); - dma_free_coherent(dev, sizeof(struct fsl_dma_private), - dma_private, dma_private->ld_buf_phys); - return ret; - } - - dma->assigned = 1; - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); - runtime->private_data = dma_private; - - /* Program the fixed DMA controller parameters */ - - dma_channel = dma_private->dma_channel; - - temp_link = dma_private->ld_buf_phys + - sizeof(struct fsl_dma_link_descriptor); - - for (i = 0; i < NUM_DMA_LINKS; i++) { - dma_private->link[i].next = cpu_to_be64(temp_link); - - temp_link += sizeof(struct fsl_dma_link_descriptor); - } - /* The last link descriptor points to the first */ - dma_private->link[i - 1].next = cpu_to_be64(dma_private->ld_buf_phys); - - /* Tell the DMA controller where the first link descriptor is */ - out_be32(&dma_channel->clndar, - CCSR_DMA_CLNDAR_ADDR(dma_private->ld_buf_phys)); - out_be32(&dma_channel->eclndar, - CCSR_DMA_ECLNDAR_ADDR(dma_private->ld_buf_phys)); - - /* The manual says the BCR must be clear before enabling EMP */ - out_be32(&dma_channel->bcr, 0); - - /* - * Program the mode register for interrupts, external master control, - * and source/destination hold. Also clear the Channel Abort bit. - */ - mr = in_be32(&dma_channel->mr) & - ~(CCSR_DMA_MR_CA | CCSR_DMA_MR_DAHE | CCSR_DMA_MR_SAHE); - - /* - * We want External Master Start and External Master Pause enabled, - * because the SSI is controlling the DMA controller. We want the DMA - * controller to be set up in advance, and then we signal only the SSI - * to start transferring. - * - * We want End-Of-Segment Interrupts enabled, because this will generate - * an interrupt at the end of each segment (each link descriptor - * represents one segment). Each DMA segment is the same thing as an - * ALSA period, so this is how we get an interrupt at the end of every - * period. - * - * We want Error Interrupt enabled, so that we can get an error if - * the DMA controller is mis-programmed somehow. - */ - mr |= CCSR_DMA_MR_EOSIE | CCSR_DMA_MR_EIE | CCSR_DMA_MR_EMP_EN | - CCSR_DMA_MR_EMS_EN; - - /* For playback, we want the destination address to be held. For - capture, set the source address to be held. */ - mr |= (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - CCSR_DMA_MR_DAHE : CCSR_DMA_MR_SAHE; - - out_be32(&dma_channel->mr, mr); - - return 0; -} - -/** - * fsl_dma_hw_params: continue initializing the DMA links - * - * This function obtains hardware parameters about the opened stream and - * programs the DMA controller accordingly. - * - * One drawback of big-endian is that when copying integers of different - * sizes to a fixed-sized register, the address to which the integer must be - * copied is dependent on the size of the integer. - * - * For example, if P is the address of a 32-bit register, and X is a 32-bit - * integer, then X should be copied to address P. However, if X is a 16-bit - * integer, then it should be copied to P+2. If X is an 8-bit register, - * then it should be copied to P+3. - * - * So for playback of 8-bit samples, the DMA controller must transfer single - * bytes from the DMA buffer to the last byte of the STX0 register, i.e. - * offset by 3 bytes. For 16-bit samples, the offset is two bytes. - * - * For 24-bit samples, the offset is 1 byte. However, the DMA controller - * does not support 3-byte copies (the DAHTS register supports only 1, 2, 4, - * and 8 bytes at a time). So we do not support packed 24-bit samples. - * 24-bit data must be padded to 32 bits. - */ -static int fsl_dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct fsl_dma_private *dma_private = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct device *dev = rtd->platform->dev; - - /* Number of bits per sample */ - unsigned int sample_bits = - snd_pcm_format_physical_width(params_format(hw_params)); - - /* Number of bytes per frame */ - unsigned int sample_bytes = sample_bits / 8; - - /* Bus address of SSI STX register */ - dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys; - - /* Size of the DMA buffer, in bytes */ - size_t buffer_size = params_buffer_bytes(hw_params); - - /* Number of bytes per period */ - size_t period_size = params_period_bytes(hw_params); - - /* Pointer to next period */ - dma_addr_t temp_addr = substream->dma_buffer.addr; - - /* Pointer to DMA controller */ - struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; - - u32 mr; /* DMA Mode Register */ - - unsigned int i; - - /* Initialize our DMA tracking variables */ - dma_private->period_size = period_size; - dma_private->num_periods = params_periods(hw_params); - dma_private->dma_buf_end = dma_private->dma_buf_phys + buffer_size; - dma_private->dma_buf_next = dma_private->dma_buf_phys + - (NUM_DMA_LINKS * period_size); - - if (dma_private->dma_buf_next >= dma_private->dma_buf_end) - /* This happens if the number of periods == NUM_DMA_LINKS */ - dma_private->dma_buf_next = dma_private->dma_buf_phys; - - mr = in_be32(&dma_channel->mr) & ~(CCSR_DMA_MR_BWC_MASK | - CCSR_DMA_MR_SAHTS_MASK | CCSR_DMA_MR_DAHTS_MASK); - - /* Due to a quirk of the SSI's STX register, the target address - * for the DMA operations depends on the sample size. So we calculate - * that offset here. While we're at it, also tell the DMA controller - * how much data to transfer per sample. - */ - switch (sample_bits) { - case 8: - mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; - ssi_sxx_phys += 3; - break; - case 16: - mr |= CCSR_DMA_MR_DAHTS_2 | CCSR_DMA_MR_SAHTS_2; - ssi_sxx_phys += 2; - break; - case 32: - mr |= CCSR_DMA_MR_DAHTS_4 | CCSR_DMA_MR_SAHTS_4; - break; - default: - /* We should never get here */ - dev_err(dev, "unsupported sample size %u\n", sample_bits); - return -EINVAL; - } - - /* - * BWC determines how many bytes are sent/received before the DMA - * controller checks the SSI to see if it needs to stop. BWC should - * always be a multiple of the frame size, so that we always transmit - * whole frames. Each frame occupies two slots in the FIFO. The - * parameter for CCSR_DMA_MR_BWC() is rounded down the next power of two - * (MR[BWC] can only represent even powers of two). - * - * To simplify the process, we set BWC to the largest value that is - * less than or equal to the FIFO watermark. For playback, this ensures - * that we transfer the maximum amount without overrunning the FIFO. - * For capture, this ensures that we transfer the maximum amount without - * underrunning the FIFO. - * - * f = SSI FIFO depth - * w = SSI watermark value (which equals f - 2) - * b = DMA bandwidth count (in bytes) - * s = sample size (in bytes, which equals frame_size * 2) - * - * For playback, we never transmit more than the transmit FIFO - * watermark, otherwise we might write more data than the FIFO can hold. - * The watermark is equal to the FIFO depth minus two. - * - * For capture, two equations must hold: - * w > f - (b / s) - * w >= b / s - * - * So, b > 2 * s, but b must also be <= s * w. To simplify, we set - * b = s * w, which is equal to - * (dma_private->ssi_fifo_depth - 2) * sample_bytes. - */ - mr |= CCSR_DMA_MR_BWC((dma_private->ssi_fifo_depth - 2) * sample_bytes); - - out_be32(&dma_channel->mr, mr); - - for (i = 0; i < NUM_DMA_LINKS; i++) { - struct fsl_dma_link_descriptor *link = &dma_private->link[i]; - - link->count = cpu_to_be32(period_size); - - /* The snoop bit tells the DMA controller whether it should tell - * the ECM to snoop during a read or write to an address. For - * audio, we use DMA to transfer data between memory and an I/O - * device (the SSI's STX0 or SRX0 register). Snooping is only - * needed if there is a cache, so we need to snoop memory - * addresses only. For playback, that means we snoop the source - * but not the destination. For capture, we snoop the - * destination but not the source. - * - * Note that failing to snoop properly is unlikely to cause - * cache incoherency if the period size is larger than the - * size of L1 cache. This is because filling in one period will - * flush out the data for the previous period. So if you - * increased period_bytes_min to a large enough size, you might - * get more performance by not snooping, and you'll still be - * okay. You'll need to update fsl_dma_update_pointers() also. - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - link->source_addr = cpu_to_be32(temp_addr); - link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | - upper_32_bits(temp_addr)); - - link->dest_addr = cpu_to_be32(ssi_sxx_phys); - link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP | - upper_32_bits(ssi_sxx_phys)); - } else { - link->source_addr = cpu_to_be32(ssi_sxx_phys); - link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP | - upper_32_bits(ssi_sxx_phys)); - - link->dest_addr = cpu_to_be32(temp_addr); - link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP | - upper_32_bits(temp_addr)); - } - - temp_addr += period_size; - } - - return 0; -} - -/** - * fsl_dma_pointer: determine the current position of the DMA transfer - * - * This function is called by ALSA when ALSA wants to know where in the - * stream buffer the hardware currently is. - * - * For playback, the SAR register contains the physical address of the most - * recent DMA transfer. For capture, the value is in the DAR register. - * - * The base address of the buffer is stored in the source_addr field of the - * first link descriptor. - */ -static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct fsl_dma_private *dma_private = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct device *dev = rtd->platform->dev; - struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; - dma_addr_t position; - snd_pcm_uframes_t frames; - - /* Obtain the current DMA pointer, but don't read the ESAD bits if we - * only have 32-bit DMA addresses. This function is typically called - * in interrupt context, so we need to optimize it. - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - position = in_be32(&dma_channel->sar); -#ifdef CONFIG_PHYS_64BIT - position |= (u64)(in_be32(&dma_channel->satr) & - CCSR_DMA_ATR_ESAD_MASK) << 32; -#endif - } else { - position = in_be32(&dma_channel->dar); -#ifdef CONFIG_PHYS_64BIT - position |= (u64)(in_be32(&dma_channel->datr) & - CCSR_DMA_ATR_ESAD_MASK) << 32; -#endif - } - - /* - * When capture is started, the SSI immediately starts to fill its FIFO. - * This means that the DMA controller is not started until the FIFO is - * full. However, ALSA calls this function before that happens, when - * MR.DAR is still zero. In this case, just return zero to indicate - * that nothing has been received yet. - */ - if (!position) - return 0; - - if ((position < dma_private->dma_buf_phys) || - (position > dma_private->dma_buf_end)) { - dev_err(dev, "dma pointer is out of range, halting stream\n"); - return SNDRV_PCM_POS_XRUN; - } - - frames = bytes_to_frames(runtime, position - dma_private->dma_buf_phys); - - /* - * If the current address is just past the end of the buffer, wrap it - * around. - */ - if (frames == runtime->buffer_size) - frames = 0; - - return frames; -} - -/** - * fsl_dma_hw_free: release resources allocated in fsl_dma_hw_params() - * - * Release the resources allocated in fsl_dma_hw_params() and de-program the - * registers. - * - * This function can be called multiple times. - */ -static int fsl_dma_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct fsl_dma_private *dma_private = runtime->private_data; - - if (dma_private) { - struct ccsr_dma_channel __iomem *dma_channel; - - dma_channel = dma_private->dma_channel; - - /* Stop the DMA */ - out_be32(&dma_channel->mr, CCSR_DMA_MR_CA); - out_be32(&dma_channel->mr, 0); - - /* Reset all the other registers */ - out_be32(&dma_channel->sr, -1); - out_be32(&dma_channel->clndar, 0); - out_be32(&dma_channel->eclndar, 0); - out_be32(&dma_channel->satr, 0); - out_be32(&dma_channel->sar, 0); - out_be32(&dma_channel->datr, 0); - out_be32(&dma_channel->dar, 0); - out_be32(&dma_channel->bcr, 0); - out_be32(&dma_channel->nlndar, 0); - out_be32(&dma_channel->enlndar, 0); - } - - return 0; -} - -/** - * fsl_dma_close: close the stream. - */ -static int fsl_dma_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct fsl_dma_private *dma_private = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct device *dev = rtd->platform->dev; - struct dma_object *dma = - container_of(rtd->platform->driver, struct dma_object, dai); - - if (dma_private) { - if (dma_private->irq) - free_irq(dma_private->irq, dma_private); - - if (dma_private->ld_buf_phys) { - dma_unmap_single(dev, dma_private->ld_buf_phys, - sizeof(dma_private->link), - DMA_TO_DEVICE); - } - - /* Deallocate the fsl_dma_private structure */ - dma_free_coherent(dev, sizeof(struct fsl_dma_private), - dma_private, dma_private->ld_buf_phys); - substream->runtime->private_data = NULL; - } - - dma->assigned = 0; - - return 0; -} - -/* - * Remove this PCM driver. - */ -static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) { - substream = pcm->streams[i].substream; - if (substream) { - snd_dma_free_pages(&substream->dma_buffer); - substream->dma_buffer.area = NULL; - substream->dma_buffer.addr = 0; - } - } -} - -/** - * find_ssi_node -- returns the SSI node that points to his DMA channel node - * - * Although this DMA driver attempts to operate independently of the other - * devices, it still needs to determine some information about the SSI device - * that it's working with. Unfortunately, the device tree does not contain - * a pointer from the DMA channel node to the SSI node -- the pointer goes the - * other way. So we need to scan the device tree for SSI nodes until we find - * the one that points to the given DMA channel node. It's ugly, but at least - * it's contained in this one function. - */ -static struct device_node *find_ssi_node(struct device_node *dma_channel_np) -{ - struct device_node *ssi_np, *np; - - for_each_compatible_node(ssi_np, NULL, "fsl,mpc8610-ssi") { - /* Check each DMA phandle to see if it points to us. We - * assume that device_node pointers are a valid comparison. - */ - np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0); - of_node_put(np); - if (np == dma_channel_np) - return ssi_np; - - np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0); - of_node_put(np); - if (np == dma_channel_np) - return ssi_np; - } - - return NULL; -} - -static struct snd_pcm_ops fsl_dma_ops = { - .open = fsl_dma_open, - .close = fsl_dma_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = fsl_dma_hw_params, - .hw_free = fsl_dma_hw_free, - .pointer = fsl_dma_pointer, -}; - -static int __devinit fsl_soc_dma_probe(struct platform_device *pdev) - { - struct dma_object *dma; - struct device_node *np = pdev->dev.of_node; - struct device_node *ssi_np; - struct resource res; - const uint32_t *iprop; - int ret; - - /* Find the SSI node that points to us. */ - ssi_np = find_ssi_node(np); - if (!ssi_np) { - dev_err(&pdev->dev, "cannot find parent SSI node\n"); - return -ENODEV; - } - - ret = of_address_to_resource(ssi_np, 0, &res); - if (ret) { - dev_err(&pdev->dev, "could not determine resources for %s\n", - ssi_np->full_name); - of_node_put(ssi_np); - return ret; - } - - dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL); - if (!dma) { - dev_err(&pdev->dev, "could not allocate dma object\n"); - of_node_put(ssi_np); - return -ENOMEM; - } - - strcpy(dma->path, np->full_name); - dma->dai.ops = &fsl_dma_ops; - dma->dai.pcm_new = fsl_dma_new; - dma->dai.pcm_free = fsl_dma_free_dma_buffers; - - /* Store the SSI-specific information that we need */ - dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0); - dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0); - - iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL); - if (iprop) - dma->ssi_fifo_depth = be32_to_cpup(iprop); - else - /* Older 8610 DTs didn't have the fifo-depth property */ - dma->ssi_fifo_depth = 8; - - of_node_put(ssi_np); - - ret = snd_soc_register_platform(&pdev->dev, &dma->dai); - if (ret) { - dev_err(&pdev->dev, "could not register platform\n"); - kfree(dma); - return ret; - } - - dma->channel = of_iomap(np, 0); - dma->irq = irq_of_parse_and_map(np, 0); - - dev_set_drvdata(&pdev->dev, dma); - - return 0; -} - -static int __devexit fsl_soc_dma_remove(struct platform_device *pdev) -{ - struct dma_object *dma = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_platform(&pdev->dev); - iounmap(dma->channel); - irq_dispose_mapping(dma->irq); - kfree(dma); - - return 0; -} - -static const struct of_device_id fsl_soc_dma_ids[] = { - { .compatible = "fsl,ssi-dma-channel", }, - {} -}; -MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids); - -static struct platform_driver fsl_soc_dma_driver = { - .driver = { - .name = "fsl-pcm-audio", - .owner = THIS_MODULE, - .of_match_table = fsl_soc_dma_ids, - }, - .probe = fsl_soc_dma_probe, - .remove = __devexit_p(fsl_soc_dma_remove), -}; - -module_platform_driver(fsl_soc_dma_driver); - -MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/soc/fsl/fsl_dma.h b/ANDROID_3.4.5/sound/soc/fsl/fsl_dma.h deleted file mode 100644 index 78fee97e..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/fsl_dma.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * mpc8610-pcm.h - ALSA PCM interface for the Freescale MPC8610 SoC - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _MPC8610_PCM_H -#define _MPC8610_PCM_H - -struct ccsr_dma { - u8 res0[0x100]; - struct ccsr_dma_channel { - __be32 mr; /* Mode register */ - __be32 sr; /* Status register */ - __be32 eclndar; /* Current link descriptor extended addr reg */ - __be32 clndar; /* Current link descriptor address register */ - __be32 satr; /* Source attributes register */ - __be32 sar; /* Source address register */ - __be32 datr; /* Destination attributes register */ - __be32 dar; /* Destination address register */ - __be32 bcr; /* Byte count register */ - __be32 enlndar; /* Next link descriptor extended address reg */ - __be32 nlndar; /* Next link descriptor address register */ - u8 res1[4]; - __be32 eclsdar; /* Current list descriptor extended addr reg */ - __be32 clsdar; /* Current list descriptor address register */ - __be32 enlsdar; /* Next list descriptor extended address reg */ - __be32 nlsdar; /* Next list descriptor address register */ - __be32 ssr; /* Source stride register */ - __be32 dsr; /* Destination stride register */ - u8 res2[0x38]; - } channel[4]; - __be32 dgsr; -}; - -#define CCSR_DMA_MR_BWC_DISABLED 0x0F000000 -#define CCSR_DMA_MR_BWC_SHIFT 24 -#define CCSR_DMA_MR_BWC_MASK 0x0F000000 -#define CCSR_DMA_MR_BWC(x) \ - ((ilog2(x) << CCSR_DMA_MR_BWC_SHIFT) & CCSR_DMA_MR_BWC_MASK) -#define CCSR_DMA_MR_EMP_EN 0x00200000 -#define CCSR_DMA_MR_EMS_EN 0x00040000 -#define CCSR_DMA_MR_DAHTS_MASK 0x00030000 -#define CCSR_DMA_MR_DAHTS_1 0x00000000 -#define CCSR_DMA_MR_DAHTS_2 0x00010000 -#define CCSR_DMA_MR_DAHTS_4 0x00020000 -#define CCSR_DMA_MR_DAHTS_8 0x00030000 -#define CCSR_DMA_MR_SAHTS_MASK 0x0000C000 -#define CCSR_DMA_MR_SAHTS_1 0x00000000 -#define CCSR_DMA_MR_SAHTS_2 0x00004000 -#define CCSR_DMA_MR_SAHTS_4 0x00008000 -#define CCSR_DMA_MR_SAHTS_8 0x0000C000 -#define CCSR_DMA_MR_DAHE 0x00002000 -#define CCSR_DMA_MR_SAHE 0x00001000 -#define CCSR_DMA_MR_SRW 0x00000400 -#define CCSR_DMA_MR_EOSIE 0x00000200 -#define CCSR_DMA_MR_EOLNIE 0x00000100 -#define CCSR_DMA_MR_EOLSIE 0x00000080 -#define CCSR_DMA_MR_EIE 0x00000040 -#define CCSR_DMA_MR_XFE 0x00000020 -#define CCSR_DMA_MR_CDSM_SWSM 0x00000010 -#define CCSR_DMA_MR_CA 0x00000008 -#define CCSR_DMA_MR_CTM 0x00000004 -#define CCSR_DMA_MR_CC 0x00000002 -#define CCSR_DMA_MR_CS 0x00000001 - -#define CCSR_DMA_SR_TE 0x00000080 -#define CCSR_DMA_SR_CH 0x00000020 -#define CCSR_DMA_SR_PE 0x00000010 -#define CCSR_DMA_SR_EOLNI 0x00000008 -#define CCSR_DMA_SR_CB 0x00000004 -#define CCSR_DMA_SR_EOSI 0x00000002 -#define CCSR_DMA_SR_EOLSI 0x00000001 - -/* ECLNDAR takes bits 32-36 of the CLNDAR register */ -static inline u32 CCSR_DMA_ECLNDAR_ADDR(u64 x) -{ - return (x >> 32) & 0xf; -} - -#define CCSR_DMA_CLNDAR_ADDR(x) ((x) & 0xFFFFFFFE) -#define CCSR_DMA_CLNDAR_EOSIE 0x00000008 - -/* SATR and DATR, combined */ -#define CCSR_DMA_ATR_PBATMU 0x20000000 -#define CCSR_DMA_ATR_TFLOWLVL_0 0x00000000 -#define CCSR_DMA_ATR_TFLOWLVL_1 0x06000000 -#define CCSR_DMA_ATR_TFLOWLVL_2 0x08000000 -#define CCSR_DMA_ATR_TFLOWLVL_3 0x0C000000 -#define CCSR_DMA_ATR_PCIORDER 0x02000000 -#define CCSR_DMA_ATR_SME 0x01000000 -#define CCSR_DMA_ATR_NOSNOOP 0x00040000 -#define CCSR_DMA_ATR_SNOOP 0x00050000 -#define CCSR_DMA_ATR_ESAD_MASK 0x0000000F - -/** - * List Descriptor for extended chaining mode DMA operations. - * - * The CLSDAR register points to the first (in a linked-list) List - * Descriptor. Each object must be aligned on a 32-byte boundary. Each - * list descriptor points to a linked-list of link Descriptors. - */ -struct fsl_dma_list_descriptor { - __be64 next; /* Address of next list descriptor */ - __be64 first_link; /* Address of first link descriptor */ - __be32 source; /* Source stride */ - __be32 dest; /* Destination stride */ - u8 res[8]; /* Reserved */ -} __attribute__ ((aligned(32), packed)); - -/** - * Link Descriptor for basic and extended chaining mode DMA operations. - * - * A Link Descriptor points to a single DMA buffer. Each link descriptor - * must be aligned on a 32-byte boundary. - */ -struct fsl_dma_link_descriptor { - __be32 source_attr; /* Programmed into SATR register */ - __be32 source_addr; /* Programmed into SAR register */ - __be32 dest_attr; /* Programmed into DATR register */ - __be32 dest_addr; /* Programmed into DAR register */ - __be64 next; /* Address of next link descriptor */ - __be32 count; /* Byte count */ - u8 res[4]; /* Reserved */ -} __attribute__ ((aligned(32), packed)); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.c b/ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.c deleted file mode 100644 index 2eb407fa..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.c +++ /dev/null @@ -1,800 +0,0 @@ -/* - * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver - * - * Author: Timur Tabi - * - * Copyright 2007-2010 Freescale Semiconductor, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "fsl_ssi.h" - -/** - * FSLSSI_I2S_RATES: sample rates supported by the I2S - * - * This driver currently only supports the SSI running in I2S slave mode, - * which means the codec determines the sample rate. Therefore, we tell - * ALSA that we support all rates and let the codec driver decide what rates - * are really supported. - */ -#define FSLSSI_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ - SNDRV_PCM_RATE_CONTINUOUS) - -/** - * FSLSSI_I2S_FORMATS: audio formats supported by the SSI - * - * This driver currently only supports the SSI running in I2S slave mode. - * - * The SSI has a limitation in that the samples must be in the same byte - * order as the host CPU. This is because when multiple bytes are written - * to the STX register, the bytes and bits must be written in the same - * order. The STX is a shift register, so all the bits need to be aligned - * (bit-endianness must match byte-endianness). Processors typically write - * the bits within a byte in the same order that the bytes of a word are - * written in. So if the host CPU is big-endian, then only big-endian - * samples will be written to STX properly. - */ -#ifdef __BIG_ENDIAN -#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_S20_3BE | \ - SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S24_BE) -#else -#define FSLSSI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE) -#endif - -/* SIER bitflag of interrupts to enable */ -#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \ - CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \ - CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \ - CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \ - CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN) - -/** - * fsl_ssi_private: per-SSI private data - * - * @ssi: pointer to the SSI's registers - * @ssi_phys: physical address of the SSI registers - * @irq: IRQ of this SSI - * @first_stream: pointer to the stream that was opened first - * @second_stream: pointer to second stream - * @playback: the number of playback streams opened - * @capture: the number of capture streams opened - * @cpu_dai: the CPU DAI for this device - * @dev_attr: the sysfs device attribute structure - * @stats: SSI statistics - * @name: name for this device - */ -struct fsl_ssi_private { - struct ccsr_ssi __iomem *ssi; - dma_addr_t ssi_phys; - unsigned int irq; - struct snd_pcm_substream *first_stream; - struct snd_pcm_substream *second_stream; - unsigned int fifo_depth; - struct snd_soc_dai_driver cpu_dai_drv; - struct device_attribute dev_attr; - struct platform_device *pdev; - - struct { - unsigned int rfrc; - unsigned int tfrc; - unsigned int cmdau; - unsigned int cmddu; - unsigned int rxt; - unsigned int rdr1; - unsigned int rdr0; - unsigned int tde1; - unsigned int tde0; - unsigned int roe1; - unsigned int roe0; - unsigned int tue1; - unsigned int tue0; - unsigned int tfs; - unsigned int rfs; - unsigned int tls; - unsigned int rls; - unsigned int rff1; - unsigned int rff0; - unsigned int tfe1; - unsigned int tfe0; - } stats; - - char name[1]; -}; - -/** - * fsl_ssi_isr: SSI interrupt handler - * - * Although it's possible to use the interrupt handler to send and receive - * data to/from the SSI, we use the DMA instead. Programming is more - * complicated, but the performance is much better. - * - * This interrupt handler is used only to gather statistics. - * - * @irq: IRQ of the SSI device - * @dev_id: pointer to the ssi_private structure for this SSI device - */ -static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) -{ - struct fsl_ssi_private *ssi_private = dev_id; - struct ccsr_ssi __iomem *ssi = ssi_private->ssi; - irqreturn_t ret = IRQ_NONE; - __be32 sisr; - __be32 sisr2 = 0; - - /* We got an interrupt, so read the status register to see what we - were interrupted for. We mask it with the Interrupt Enable register - so that we only check for events that we're interested in. - */ - sisr = in_be32(&ssi->sisr) & SIER_FLAGS; - - if (sisr & CCSR_SSI_SISR_RFRC) { - ssi_private->stats.rfrc++; - sisr2 |= CCSR_SSI_SISR_RFRC; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TFRC) { - ssi_private->stats.tfrc++; - sisr2 |= CCSR_SSI_SISR_TFRC; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_CMDAU) { - ssi_private->stats.cmdau++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_CMDDU) { - ssi_private->stats.cmddu++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_RXT) { - ssi_private->stats.rxt++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_RDR1) { - ssi_private->stats.rdr1++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_RDR0) { - ssi_private->stats.rdr0++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TDE1) { - ssi_private->stats.tde1++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TDE0) { - ssi_private->stats.tde0++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_ROE1) { - ssi_private->stats.roe1++; - sisr2 |= CCSR_SSI_SISR_ROE1; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_ROE0) { - ssi_private->stats.roe0++; - sisr2 |= CCSR_SSI_SISR_ROE0; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TUE1) { - ssi_private->stats.tue1++; - sisr2 |= CCSR_SSI_SISR_TUE1; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TUE0) { - ssi_private->stats.tue0++; - sisr2 |= CCSR_SSI_SISR_TUE0; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TFS) { - ssi_private->stats.tfs++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_RFS) { - ssi_private->stats.rfs++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TLS) { - ssi_private->stats.tls++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_RLS) { - ssi_private->stats.rls++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_RFF1) { - ssi_private->stats.rff1++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_RFF0) { - ssi_private->stats.rff0++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TFE1) { - ssi_private->stats.tfe1++; - ret = IRQ_HANDLED; - } - - if (sisr & CCSR_SSI_SISR_TFE0) { - ssi_private->stats.tfe0++; - ret = IRQ_HANDLED; - } - - /* Clear the bits that we set */ - if (sisr2) - out_be32(&ssi->sisr, sisr2); - - return ret; -} - -/** - * fsl_ssi_startup: create a new substream - * - * This is the first function called when a stream is opened. - * - * If this is the first stream open, then grab the IRQ and program most of - * the SSI registers. - */ -static int fsl_ssi_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct fsl_ssi_private *ssi_private = - snd_soc_dai_get_drvdata(rtd->cpu_dai); - int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; - - /* - * If this is the first stream opened, then request the IRQ - * and initialize the SSI registers. - */ - if (!ssi_private->first_stream) { - struct ccsr_ssi __iomem *ssi = ssi_private->ssi; - - ssi_private->first_stream = substream; - - /* - * Section 16.5 of the MPC8610 reference manual says that the - * SSI needs to be disabled before updating the registers we set - * here. - */ - clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); - - /* - * Program the SSI into I2S Slave Non-Network Synchronous mode. - * Also enable the transmit and receive FIFO. - * - * FIXME: Little-endian samples require a different shift dir - */ - clrsetbits_be32(&ssi->scr, - CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, - CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE - | (synchronous ? CCSR_SSI_SCR_SYN : 0)); - - out_be32(&ssi->stcr, - CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | - CCSR_SSI_STCR_TFSI | CCSR_SSI_STCR_TEFS | - CCSR_SSI_STCR_TSCKP); - - out_be32(&ssi->srcr, - CCSR_SSI_SRCR_RXBIT0 | CCSR_SSI_SRCR_RFEN0 | - CCSR_SSI_SRCR_RFSI | CCSR_SSI_SRCR_REFS | - CCSR_SSI_SRCR_RSCKP); - - /* - * The DC and PM bits are only used if the SSI is the clock - * master. - */ - - /* Enable the interrupts and DMA requests */ - out_be32(&ssi->sier, SIER_FLAGS); - - /* - * Set the watermark for transmit FIFI 0 and receive FIFO 0. We - * don't use FIFO 1. We program the transmit water to signal a - * DMA transfer if there are only two (or fewer) elements left - * in the FIFO. Two elements equals one frame (left channel, - * right channel). This value, however, depends on the depth of - * the transmit buffer. - * - * We program the receive FIFO to notify us if at least two - * elements (one frame) have been written to the FIFO. We could - * make this value larger (and maybe we should), but this way - * data will be written to memory as soon as it's available. - */ - out_be32(&ssi->sfcsr, - CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) | - CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2)); - - /* - * We keep the SSI disabled because if we enable it, then the - * DMA controller will start. It's not supposed to start until - * the SCR.TE (or SCR.RE) bit is set, but it does anyway. The - * DMA controller will transfer one "BWC" of data (i.e. the - * amount of data that the MR.BWC bits are set to). The reason - * this is bad is because at this point, the PCM driver has not - * finished initializing the DMA controller. - */ - } else { - if (synchronous) { - struct snd_pcm_runtime *first_runtime = - ssi_private->first_stream->runtime; - /* - * This is the second stream open, and we're in - * synchronous mode, so we need to impose sample - * sample size constraints. This is because STCCR is - * used for playback and capture in synchronous mode, - * so there's no way to specify different word - * lengths. - * - * Note that this can cause a race condition if the - * second stream is opened before the first stream is - * fully initialized. We provide some protection by - * checking to make sure the first stream is - * initialized, but it's not perfect. ALSA sometimes - * re-initializes the driver with a different sample - * rate or size. If the second stream is opened - * before the first stream has received its final - * parameters, then the second stream may be - * constrained to the wrong sample rate or size. - */ - if (!first_runtime->sample_bits) { - dev_err(substream->pcm->card->dev, - "set sample size in %s stream first\n", - substream->stream == - SNDRV_PCM_STREAM_PLAYBACK - ? "capture" : "playback"); - return -EAGAIN; - } - - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - first_runtime->sample_bits, - first_runtime->sample_bits); - } - - ssi_private->second_stream = substream; - } - - return 0; -} - -/** - * fsl_ssi_hw_params - program the sample size - * - * Most of the SSI registers have been programmed in the startup function, - * but the word length must be programmed here. Unfortunately, programming - * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can - * cause a problem with supporting simultaneous playback and capture. If - * the SSI is already playing a stream, then that stream may be temporarily - * stopped when you start capture. - * - * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the - * clock master. - */ -static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) -{ - struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); - struct ccsr_ssi __iomem *ssi = ssi_private->ssi; - unsigned int sample_size = - snd_pcm_format_width(params_format(hw_params)); - u32 wl = CCSR_SSI_SxCCR_WL(sample_size); - int enabled = in_be32(&ssi->scr) & CCSR_SSI_SCR_SSIEN; - - /* - * If we're in synchronous mode, and the SSI is already enabled, - * then STCCR is already set properly. - */ - if (enabled && ssi_private->cpu_dai_drv.symmetric_rates) - return 0; - - /* - * FIXME: The documentation says that SxCCR[WL] should not be - * modified while the SSI is enabled. The only time this can - * happen is if we're trying to do simultaneous playback and - * capture in asynchronous mode. Unfortunately, I have been enable - * to get that to work at all on the P1022DS. Therefore, we don't - * bother to disable/enable the SSI when setting SxCCR[WL], because - * the SSI will stop anyway. Maybe one day, this will get fixed. - */ - - /* In synchronous mode, the SSI uses STCCR for capture */ - if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || - ssi_private->cpu_dai_drv.symmetric_rates) - clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); - else - clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); - - return 0; -} - -/** - * fsl_ssi_trigger: start and stop the DMA transfer. - * - * This function is called by ALSA to start, stop, pause, and resume the DMA - * transfer of data. - * - * The DMA channel is in external master start and pause mode, which - * means the SSI completely controls the flow of data. - */ -static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct ccsr_ssi __iomem *ssi = ssi_private->ssi; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - setbits32(&ssi->scr, - CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); - else - setbits32(&ssi->scr, - CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); - else - clrbits32(&ssi->scr, CCSR_SSI_SCR_RE); - break; - - default: - return -EINVAL; - } - - return 0; -} - -/** - * fsl_ssi_shutdown: shutdown the SSI - * - * Shutdown the SSI if there are no other substreams open. - */ -static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); - - if (ssi_private->first_stream == substream) - ssi_private->first_stream = ssi_private->second_stream; - - ssi_private->second_stream = NULL; - - /* - * If this is the last active substream, disable the SSI. - */ - if (!ssi_private->first_stream) { - struct ccsr_ssi __iomem *ssi = ssi_private->ssi; - - clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); - } -} - -static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { - .startup = fsl_ssi_startup, - .hw_params = fsl_ssi_hw_params, - .shutdown = fsl_ssi_shutdown, - .trigger = fsl_ssi_trigger, -}; - -/* Template for the CPU dai driver structure */ -static struct snd_soc_dai_driver fsl_ssi_dai_template = { - .playback = { - /* The SSI does not support monaural audio. */ - .channels_min = 2, - .channels_max = 2, - .rates = FSLSSI_I2S_RATES, - .formats = FSLSSI_I2S_FORMATS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = FSLSSI_I2S_RATES, - .formats = FSLSSI_I2S_FORMATS, - }, - .ops = &fsl_ssi_dai_ops, -}; - -/* Show the statistics of a flag only if its interrupt is enabled. The - * compiler will optimze this code to a no-op if the interrupt is not - * enabled. - */ -#define SIER_SHOW(flag, name) \ - do { \ - if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \ - length += sprintf(buf + length, #name "=%u\n", \ - ssi_private->stats.name); \ - } while (0) - - -/** - * fsl_sysfs_ssi_show: display SSI statistics - * - * Display the statistics for the current SSI device. To avoid confusion, - * we only show those counts that are enabled. - */ -static ssize_t fsl_sysfs_ssi_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fsl_ssi_private *ssi_private = - container_of(attr, struct fsl_ssi_private, dev_attr); - ssize_t length = 0; - - SIER_SHOW(RFRC_EN, rfrc); - SIER_SHOW(TFRC_EN, tfrc); - SIER_SHOW(CMDAU_EN, cmdau); - SIER_SHOW(CMDDU_EN, cmddu); - SIER_SHOW(RXT_EN, rxt); - SIER_SHOW(RDR1_EN, rdr1); - SIER_SHOW(RDR0_EN, rdr0); - SIER_SHOW(TDE1_EN, tde1); - SIER_SHOW(TDE0_EN, tde0); - SIER_SHOW(ROE1_EN, roe1); - SIER_SHOW(ROE0_EN, roe0); - SIER_SHOW(TUE1_EN, tue1); - SIER_SHOW(TUE0_EN, tue0); - SIER_SHOW(TFS_EN, tfs); - SIER_SHOW(RFS_EN, rfs); - SIER_SHOW(TLS_EN, tls); - SIER_SHOW(RLS_EN, rls); - SIER_SHOW(RFF1_EN, rff1); - SIER_SHOW(RFF0_EN, rff0); - SIER_SHOW(TFE1_EN, tfe1); - SIER_SHOW(TFE0_EN, tfe0); - - return length; -} - -/** - * Make every character in a string lower-case - */ -static void make_lowercase(char *s) -{ - char *p = s; - char c; - - while ((c = *p)) { - if ((c >= 'A') && (c <= 'Z')) - *p = c + ('a' - 'A'); - p++; - } -} - -static int __devinit fsl_ssi_probe(struct platform_device *pdev) -{ - struct fsl_ssi_private *ssi_private; - int ret = 0; - struct device_attribute *dev_attr = NULL; - struct device_node *np = pdev->dev.of_node; - const char *p, *sprop; - const uint32_t *iprop; - struct resource res; - char name[64]; - - /* SSIs that are not connected on the board should have a - * status = "disabled" - * property in their device tree nodes. - */ - if (!of_device_is_available(np)) - return -ENODEV; - - /* Check for a codec-handle property. */ - if (!of_get_property(np, "codec-handle", NULL)) { - dev_err(&pdev->dev, "missing codec-handle property\n"); - return -ENODEV; - } - - /* We only support the SSI in "I2S Slave" mode */ - sprop = of_get_property(np, "fsl,mode", NULL); - if (!sprop || strcmp(sprop, "i2s-slave")) { - dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop); - return -ENODEV; - } - - /* The DAI name is the last part of the full name of the node. */ - p = strrchr(np->full_name, '/') + 1; - ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p), - GFP_KERNEL); - if (!ssi_private) { - dev_err(&pdev->dev, "could not allocate DAI object\n"); - return -ENOMEM; - } - - strcpy(ssi_private->name, p); - - /* Initialize this copy of the CPU DAI driver structure */ - memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template, - sizeof(fsl_ssi_dai_template)); - ssi_private->cpu_dai_drv.name = ssi_private->name; - - /* Get the addresses and IRQ */ - ret = of_address_to_resource(np, 0, &res); - if (ret) { - dev_err(&pdev->dev, "could not determine device resources\n"); - goto error_kmalloc; - } - ssi_private->ssi = of_iomap(np, 0); - if (!ssi_private->ssi) { - dev_err(&pdev->dev, "could not map device resources\n"); - ret = -ENOMEM; - goto error_kmalloc; - } - ssi_private->ssi_phys = res.start; - - ssi_private->irq = irq_of_parse_and_map(np, 0); - if (ssi_private->irq == NO_IRQ) { - dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); - ret = -ENXIO; - goto error_iomap; - } - - /* The 'name' should not have any slashes in it. */ - ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name, - ssi_private); - if (ret < 0) { - dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq); - goto error_irqmap; - } - - /* Are the RX and the TX clocks locked? */ - if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) - ssi_private->cpu_dai_drv.symmetric_rates = 1; - - /* Determine the FIFO depth. */ - iprop = of_get_property(np, "fsl,fifo-depth", NULL); - if (iprop) - ssi_private->fifo_depth = be32_to_cpup(iprop); - else - /* Older 8610 DTs didn't have the fifo-depth property */ - ssi_private->fifo_depth = 8; - - /* Initialize the the device_attribute structure */ - dev_attr = &ssi_private->dev_attr; - sysfs_attr_init(&dev_attr->attr); - dev_attr->attr.name = "statistics"; - dev_attr->attr.mode = S_IRUGO; - dev_attr->show = fsl_sysfs_ssi_show; - - ret = device_create_file(&pdev->dev, dev_attr); - if (ret) { - dev_err(&pdev->dev, "could not create sysfs %s file\n", - ssi_private->dev_attr.attr.name); - goto error_irq; - } - - /* Register with ASoC */ - dev_set_drvdata(&pdev->dev, ssi_private); - - ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv); - if (ret) { - dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); - goto error_dev; - } - - /* Trigger the machine driver's probe function. The platform driver - * name of the machine driver is taken from /compatible property of the - * device tree. We also pass the address of the CPU DAI driver - * structure. - */ - sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL); - /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */ - p = strrchr(sprop, ','); - if (p) - sprop = p + 1; - snprintf(name, sizeof(name), "snd-soc-%s", sprop); - make_lowercase(name); - - ssi_private->pdev = - platform_device_register_data(&pdev->dev, name, 0, NULL, 0); - if (IS_ERR(ssi_private->pdev)) { - ret = PTR_ERR(ssi_private->pdev); - dev_err(&pdev->dev, "failed to register platform: %d\n", ret); - goto error_dai; - } - - return 0; - -error_dai: - snd_soc_unregister_dai(&pdev->dev); - -error_dev: - dev_set_drvdata(&pdev->dev, NULL); - device_remove_file(&pdev->dev, dev_attr); - -error_irq: - free_irq(ssi_private->irq, ssi_private); - -error_irqmap: - irq_dispose_mapping(ssi_private->irq); - -error_iomap: - iounmap(ssi_private->ssi); - -error_kmalloc: - kfree(ssi_private); - - return ret; -} - -static int fsl_ssi_remove(struct platform_device *pdev) -{ - struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev); - - platform_device_unregister(ssi_private->pdev); - snd_soc_unregister_dai(&pdev->dev); - device_remove_file(&pdev->dev, &ssi_private->dev_attr); - - free_irq(ssi_private->irq, ssi_private); - irq_dispose_mapping(ssi_private->irq); - - kfree(ssi_private); - dev_set_drvdata(&pdev->dev, NULL); - - return 0; -} - -static const struct of_device_id fsl_ssi_ids[] = { - { .compatible = "fsl,mpc8610-ssi", }, - {} -}; -MODULE_DEVICE_TABLE(of, fsl_ssi_ids); - -static struct platform_driver fsl_ssi_driver = { - .driver = { - .name = "fsl-ssi-dai", - .owner = THIS_MODULE, - .of_match_table = fsl_ssi_ids, - }, - .probe = fsl_ssi_probe, - .remove = fsl_ssi_remove, -}; - -module_platform_driver(fsl_ssi_driver); - -MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.h b/ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.h deleted file mode 100644 index 21730002..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/fsl_ssi.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * fsl_ssi.h - ALSA SSI interface for the Freescale MPC8610 SoC - * - * Author: Timur Tabi - * - * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed - * under the terms of the GNU General Public License version 2. This - * program is licensed "as is" without any warranty of any kind, whether - * express or implied. - */ - -#ifndef _MPC8610_I2S_H -#define _MPC8610_I2S_H - -/* SSI Register Map */ -struct ccsr_ssi { - __be32 stx0; /* 0x.0000 - SSI Transmit Data Register 0 */ - __be32 stx1; /* 0x.0004 - SSI Transmit Data Register 1 */ - __be32 srx0; /* 0x.0008 - SSI Receive Data Register 0 */ - __be32 srx1; /* 0x.000C - SSI Receive Data Register 1 */ - __be32 scr; /* 0x.0010 - SSI Control Register */ - __be32 sisr; /* 0x.0014 - SSI Interrupt Status Register Mixed */ - __be32 sier; /* 0x.0018 - SSI Interrupt Enable Register */ - __be32 stcr; /* 0x.001C - SSI Transmit Configuration Register */ - __be32 srcr; /* 0x.0020 - SSI Receive Configuration Register */ - __be32 stccr; /* 0x.0024 - SSI Transmit Clock Control Register */ - __be32 srccr; /* 0x.0028 - SSI Receive Clock Control Register */ - __be32 sfcsr; /* 0x.002C - SSI FIFO Control/Status Register */ - __be32 str; /* 0x.0030 - SSI Test Register */ - __be32 sor; /* 0x.0034 - SSI Option Register */ - __be32 sacnt; /* 0x.0038 - SSI AC97 Control Register */ - __be32 sacadd; /* 0x.003C - SSI AC97 Command Address Register */ - __be32 sacdat; /* 0x.0040 - SSI AC97 Command Data Register */ - __be32 satag; /* 0x.0044 - SSI AC97 Tag Register */ - __be32 stmsk; /* 0x.0048 - SSI Transmit Time Slot Mask Register */ - __be32 srmsk; /* 0x.004C - SSI Receive Time Slot Mask Register */ - __be32 saccst; /* 0x.0050 - SSI AC97 Channel Status Register */ - __be32 saccen; /* 0x.0054 - SSI AC97 Channel Enable Register */ - __be32 saccdis; /* 0x.0058 - SSI AC97 Channel Disable Register */ -}; - -#define CCSR_SSI_SCR_RFR_CLK_DIS 0x00000800 -#define CCSR_SSI_SCR_TFR_CLK_DIS 0x00000400 -#define CCSR_SSI_SCR_TCH_EN 0x00000100 -#define CCSR_SSI_SCR_SYS_CLK_EN 0x00000080 -#define CCSR_SSI_SCR_I2S_MODE_MASK 0x00000060 -#define CCSR_SSI_SCR_I2S_MODE_NORMAL 0x00000000 -#define CCSR_SSI_SCR_I2S_MODE_MASTER 0x00000020 -#define CCSR_SSI_SCR_I2S_MODE_SLAVE 0x00000040 -#define CCSR_SSI_SCR_SYN 0x00000010 -#define CCSR_SSI_SCR_NET 0x00000008 -#define CCSR_SSI_SCR_RE 0x00000004 -#define CCSR_SSI_SCR_TE 0x00000002 -#define CCSR_SSI_SCR_SSIEN 0x00000001 - -#define CCSR_SSI_SISR_RFRC 0x01000000 -#define CCSR_SSI_SISR_TFRC 0x00800000 -#define CCSR_SSI_SISR_CMDAU 0x00040000 -#define CCSR_SSI_SISR_CMDDU 0x00020000 -#define CCSR_SSI_SISR_RXT 0x00010000 -#define CCSR_SSI_SISR_RDR1 0x00008000 -#define CCSR_SSI_SISR_RDR0 0x00004000 -#define CCSR_SSI_SISR_TDE1 0x00002000 -#define CCSR_SSI_SISR_TDE0 0x00001000 -#define CCSR_SSI_SISR_ROE1 0x00000800 -#define CCSR_SSI_SISR_ROE0 0x00000400 -#define CCSR_SSI_SISR_TUE1 0x00000200 -#define CCSR_SSI_SISR_TUE0 0x00000100 -#define CCSR_SSI_SISR_TFS 0x00000080 -#define CCSR_SSI_SISR_RFS 0x00000040 -#define CCSR_SSI_SISR_TLS 0x00000020 -#define CCSR_SSI_SISR_RLS 0x00000010 -#define CCSR_SSI_SISR_RFF1 0x00000008 -#define CCSR_SSI_SISR_RFF0 0x00000004 -#define CCSR_SSI_SISR_TFE1 0x00000002 -#define CCSR_SSI_SISR_TFE0 0x00000001 - -#define CCSR_SSI_SIER_RFRC_EN 0x01000000 -#define CCSR_SSI_SIER_TFRC_EN 0x00800000 -#define CCSR_SSI_SIER_RDMAE 0x00400000 -#define CCSR_SSI_SIER_RIE 0x00200000 -#define CCSR_SSI_SIER_TDMAE 0x00100000 -#define CCSR_SSI_SIER_TIE 0x00080000 -#define CCSR_SSI_SIER_CMDAU_EN 0x00040000 -#define CCSR_SSI_SIER_CMDDU_EN 0x00020000 -#define CCSR_SSI_SIER_RXT_EN 0x00010000 -#define CCSR_SSI_SIER_RDR1_EN 0x00008000 -#define CCSR_SSI_SIER_RDR0_EN 0x00004000 -#define CCSR_SSI_SIER_TDE1_EN 0x00002000 -#define CCSR_SSI_SIER_TDE0_EN 0x00001000 -#define CCSR_SSI_SIER_ROE1_EN 0x00000800 -#define CCSR_SSI_SIER_ROE0_EN 0x00000400 -#define CCSR_SSI_SIER_TUE1_EN 0x00000200 -#define CCSR_SSI_SIER_TUE0_EN 0x00000100 -#define CCSR_SSI_SIER_TFS_EN 0x00000080 -#define CCSR_SSI_SIER_RFS_EN 0x00000040 -#define CCSR_SSI_SIER_TLS_EN 0x00000020 -#define CCSR_SSI_SIER_RLS_EN 0x00000010 -#define CCSR_SSI_SIER_RFF1_EN 0x00000008 -#define CCSR_SSI_SIER_RFF0_EN 0x00000004 -#define CCSR_SSI_SIER_TFE1_EN 0x00000002 -#define CCSR_SSI_SIER_TFE0_EN 0x00000001 - -#define CCSR_SSI_STCR_TXBIT0 0x00000200 -#define CCSR_SSI_STCR_TFEN1 0x00000100 -#define CCSR_SSI_STCR_TFEN0 0x00000080 -#define CCSR_SSI_STCR_TFDIR 0x00000040 -#define CCSR_SSI_STCR_TXDIR 0x00000020 -#define CCSR_SSI_STCR_TSHFD 0x00000010 -#define CCSR_SSI_STCR_TSCKP 0x00000008 -#define CCSR_SSI_STCR_TFSI 0x00000004 -#define CCSR_SSI_STCR_TFSL 0x00000002 -#define CCSR_SSI_STCR_TEFS 0x00000001 - -#define CCSR_SSI_SRCR_RXEXT 0x00000400 -#define CCSR_SSI_SRCR_RXBIT0 0x00000200 -#define CCSR_SSI_SRCR_RFEN1 0x00000100 -#define CCSR_SSI_SRCR_RFEN0 0x00000080 -#define CCSR_SSI_SRCR_RFDIR 0x00000040 -#define CCSR_SSI_SRCR_RXDIR 0x00000020 -#define CCSR_SSI_SRCR_RSHFD 0x00000010 -#define CCSR_SSI_SRCR_RSCKP 0x00000008 -#define CCSR_SSI_SRCR_RFSI 0x00000004 -#define CCSR_SSI_SRCR_RFSL 0x00000002 -#define CCSR_SSI_SRCR_REFS 0x00000001 - -/* STCCR and SRCCR */ -#define CCSR_SSI_SxCCR_DIV2 0x00040000 -#define CCSR_SSI_SxCCR_PSR 0x00020000 -#define CCSR_SSI_SxCCR_WL_SHIFT 13 -#define CCSR_SSI_SxCCR_WL_MASK 0x0001E000 -#define CCSR_SSI_SxCCR_WL(x) \ - (((((x) / 2) - 1) << CCSR_SSI_SxCCR_WL_SHIFT) & CCSR_SSI_SxCCR_WL_MASK) -#define CCSR_SSI_SxCCR_DC_SHIFT 8 -#define CCSR_SSI_SxCCR_DC_MASK 0x00001F00 -#define CCSR_SSI_SxCCR_DC(x) \ - ((((x) - 1) << CCSR_SSI_SxCCR_DC_SHIFT) & CCSR_SSI_SxCCR_DC_MASK) -#define CCSR_SSI_SxCCR_PM_SHIFT 0 -#define CCSR_SSI_SxCCR_PM_MASK 0x000000FF -#define CCSR_SSI_SxCCR_PM(x) \ - ((((x) - 1) << CCSR_SSI_SxCCR_PM_SHIFT) & CCSR_SSI_SxCCR_PM_MASK) - -/* - * The xFCNT bits are read-only, and the xFWM bits are read/write. Use the - * CCSR_SSI_SFCSR_xFCNTy() macros to read the FIFO counters, and use the - * CCSR_SSI_SFCSR_xFWMy() macros to set the watermarks. - */ -#define CCSR_SSI_SFCSR_RFCNT1_SHIFT 28 -#define CCSR_SSI_SFCSR_RFCNT1_MASK 0xF0000000 -#define CCSR_SSI_SFCSR_RFCNT1(x) \ - (((x) & CCSR_SSI_SFCSR_RFCNT1_MASK) >> CCSR_SSI_SFCSR_RFCNT1_SHIFT) -#define CCSR_SSI_SFCSR_TFCNT1_SHIFT 24 -#define CCSR_SSI_SFCSR_TFCNT1_MASK 0x0F000000 -#define CCSR_SSI_SFCSR_TFCNT1(x) \ - (((x) & CCSR_SSI_SFCSR_TFCNT1_MASK) >> CCSR_SSI_SFCSR_TFCNT1_SHIFT) -#define CCSR_SSI_SFCSR_RFWM1_SHIFT 20 -#define CCSR_SSI_SFCSR_RFWM1_MASK 0x00F00000 -#define CCSR_SSI_SFCSR_RFWM1(x) \ - (((x) << CCSR_SSI_SFCSR_RFWM1_SHIFT) & CCSR_SSI_SFCSR_RFWM1_MASK) -#define CCSR_SSI_SFCSR_TFWM1_SHIFT 16 -#define CCSR_SSI_SFCSR_TFWM1_MASK 0x000F0000 -#define CCSR_SSI_SFCSR_TFWM1(x) \ - (((x) << CCSR_SSI_SFCSR_TFWM1_SHIFT) & CCSR_SSI_SFCSR_TFWM1_MASK) -#define CCSR_SSI_SFCSR_RFCNT0_SHIFT 12 -#define CCSR_SSI_SFCSR_RFCNT0_MASK 0x0000F000 -#define CCSR_SSI_SFCSR_RFCNT0(x) \ - (((x) & CCSR_SSI_SFCSR_RFCNT0_MASK) >> CCSR_SSI_SFCSR_RFCNT0_SHIFT) -#define CCSR_SSI_SFCSR_TFCNT0_SHIFT 8 -#define CCSR_SSI_SFCSR_TFCNT0_MASK 0x00000F00 -#define CCSR_SSI_SFCSR_TFCNT0(x) \ - (((x) & CCSR_SSI_SFCSR_TFCNT0_MASK) >> CCSR_SSI_SFCSR_TFCNT0_SHIFT) -#define CCSR_SSI_SFCSR_RFWM0_SHIFT 4 -#define CCSR_SSI_SFCSR_RFWM0_MASK 0x000000F0 -#define CCSR_SSI_SFCSR_RFWM0(x) \ - (((x) << CCSR_SSI_SFCSR_RFWM0_SHIFT) & CCSR_SSI_SFCSR_RFWM0_MASK) -#define CCSR_SSI_SFCSR_TFWM0_SHIFT 0 -#define CCSR_SSI_SFCSR_TFWM0_MASK 0x0000000F -#define CCSR_SSI_SFCSR_TFWM0(x) \ - (((x) << CCSR_SSI_SFCSR_TFWM0_SHIFT) & CCSR_SSI_SFCSR_TFWM0_MASK) - -#define CCSR_SSI_STR_TEST 0x00008000 -#define CCSR_SSI_STR_RCK2TCK 0x00004000 -#define CCSR_SSI_STR_RFS2TFS 0x00002000 -#define CCSR_SSI_STR_RXSTATE(x) (((x) >> 8) & 0x1F) -#define CCSR_SSI_STR_TXD2RXD 0x00000080 -#define CCSR_SSI_STR_TCK2RCK 0x00000040 -#define CCSR_SSI_STR_TFS2RFS 0x00000020 -#define CCSR_SSI_STR_TXSTATE(x) ((x) & 0x1F) - -#define CCSR_SSI_SOR_CLKOFF 0x00000040 -#define CCSR_SSI_SOR_RX_CLR 0x00000020 -#define CCSR_SSI_SOR_TX_CLR 0x00000010 -#define CCSR_SSI_SOR_INIT 0x00000008 -#define CCSR_SSI_SOR_WAIT_SHIFT 1 -#define CCSR_SSI_SOR_WAIT_MASK 0x00000006 -#define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT) -#define CCSR_SSI_SOR_SYNRST 0x00000001 - -#endif - diff --git a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.c b/ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.c deleted file mode 100644 index 9a3f7c5a..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Freescale MPC5200 PSC DMA - * ALSA SoC Platform driver - * - * Copyright (C) 2008 Secret Lab Technologies Ltd. - * Copyright (C) 2009 Jon Smirl, Digispeaker - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "mpc5200_dma.h" - -/* - * Interrupt handlers - */ -static irqreturn_t psc_dma_status_irq(int irq, void *_psc_dma) -{ - struct psc_dma *psc_dma = _psc_dma; - struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; - u16 isr; - - isr = in_be16(®s->mpc52xx_psc_isr); - - /* Playback underrun error */ - if (psc_dma->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP)) - psc_dma->stats.underrun_count++; - - /* Capture overrun error */ - if (psc_dma->capture.active && (isr & MPC52xx_PSC_IMR_ORERR)) - psc_dma->stats.overrun_count++; - - out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT); - - return IRQ_HANDLED; -} - -/** - * psc_dma_bcom_enqueue_next_buffer - Enqueue another audio buffer - * @s: pointer to stream private data structure - * - * Enqueues another audio period buffer into the bestcomm queue. - * - * Note: The routine must only be called when there is space available in - * the queue. Otherwise the enqueue will fail and the audio ring buffer - * will get out of sync - */ -static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s) -{ - struct bcom_bd *bd; - - /* Prepare and enqueue the next buffer descriptor */ - bd = bcom_prepare_next_buffer(s->bcom_task); - bd->status = s->period_bytes; - bd->data[0] = s->runtime->dma_addr + (s->period_next * s->period_bytes); - bcom_submit_next_buffer(s->bcom_task, NULL); - - /* Update for next period */ - s->period_next = (s->period_next + 1) % s->runtime->periods; -} - -/* Bestcomm DMA irq handler */ -static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream) -{ - struct psc_dma_stream *s = _psc_dma_stream; - - spin_lock(&s->psc_dma->lock); - /* For each finished period, dequeue the completed period buffer - * and enqueue a new one in it's place. */ - while (bcom_buffer_done(s->bcom_task)) { - bcom_retrieve_buffer(s->bcom_task, NULL, NULL); - - s->period_current = (s->period_current+1) % s->runtime->periods; - s->period_count++; - - psc_dma_bcom_enqueue_next_buffer(s); - } - spin_unlock(&s->psc_dma->lock); - - /* If the stream is active, then also inform the PCM middle layer - * of the period finished event. */ - if (s->active) - snd_pcm_period_elapsed(s->stream); - - return IRQ_HANDLED; -} - -static int psc_dma_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - -/** - * psc_dma_trigger: start and stop the DMA transfer. - * - * This function is called by ALSA to start, stop, pause, and resume the DMA - * transfer of data. - */ -static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct snd_pcm_runtime *runtime = substream->runtime; - struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); - struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; - u16 imr; - unsigned long flags; - int i; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - dev_dbg(psc_dma->dev, "START: stream=%i fbits=%u ps=%u #p=%u\n", - substream->pstr->stream, runtime->frame_bits, - (int)runtime->period_size, runtime->periods); - s->period_bytes = frames_to_bytes(runtime, - runtime->period_size); - s->period_next = 0; - s->period_current = 0; - s->active = 1; - s->period_count = 0; - s->runtime = runtime; - - /* Fill up the bestcomm bd queue and enable DMA. - * This will begin filling the PSC's fifo. - */ - spin_lock_irqsave(&psc_dma->lock, flags); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) - bcom_gen_bd_rx_reset(s->bcom_task); - else - bcom_gen_bd_tx_reset(s->bcom_task); - - for (i = 0; i < runtime->periods; i++) - if (!bcom_queue_full(s->bcom_task)) - psc_dma_bcom_enqueue_next_buffer(s); - - bcom_enable(s->bcom_task); - spin_unlock_irqrestore(&psc_dma->lock, flags); - - out_8(®s->command, MPC52xx_PSC_RST_ERR_STAT); - - break; - - case SNDRV_PCM_TRIGGER_STOP: - dev_dbg(psc_dma->dev, "STOP: stream=%i periods_count=%i\n", - substream->pstr->stream, s->period_count); - s->active = 0; - - spin_lock_irqsave(&psc_dma->lock, flags); - bcom_disable(s->bcom_task); - if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) - bcom_gen_bd_rx_reset(s->bcom_task); - else - bcom_gen_bd_tx_reset(s->bcom_task); - spin_unlock_irqrestore(&psc_dma->lock, flags); - - break; - - default: - dev_dbg(psc_dma->dev, "unhandled trigger: stream=%i cmd=%i\n", - substream->pstr->stream, cmd); - return -EINVAL; - } - - /* Update interrupt enable settings */ - imr = 0; - if (psc_dma->playback.active) - imr |= MPC52xx_PSC_IMR_TXEMP; - if (psc_dma->capture.active) - imr |= MPC52xx_PSC_IMR_ORERR; - out_be16(®s->isr_imr.imr, psc_dma->imr | imr); - - return 0; -} - - -/* --------------------------------------------------------------------- - * The PSC DMA 'ASoC platform' driver - * - * Can be referenced by an 'ASoC machine' driver - * This driver only deals with the audio bus; it doesn't have any - * interaction with the attached codec - */ - -static const struct snd_pcm_hardware psc_dma_hardware = { - .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - 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, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .period_bytes_max = 1024 * 1024, - .period_bytes_min = 32, - .periods_min = 2, - .periods_max = 256, - .buffer_bytes_max = 2 * 1024 * 1024, - .fifo_size = 512, -}; - -static int psc_dma_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct psc_dma_stream *s; - int rc; - - dev_dbg(psc_dma->dev, "psc_dma_open(substream=%p)\n", substream); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) - s = &psc_dma->capture; - else - s = &psc_dma->playback; - - snd_soc_set_runtime_hwparams(substream, &psc_dma_hardware); - - rc = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (rc < 0) { - dev_err(substream->pcm->card->dev, "invalid buffer size\n"); - return rc; - } - - s->stream = substream; - return 0; -} - -static int psc_dma_close(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct psc_dma_stream *s; - - dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream); - - if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) - s = &psc_dma->capture; - else - s = &psc_dma->playback; - - if (!psc_dma->playback.active && - !psc_dma->capture.active) { - - /* Disable all interrupts and reset the PSC */ - out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); - out_8(&psc_dma->psc_regs->command, 4 << 4); /* reset error */ - } - s->stream = NULL; - return 0; -} - -static snd_pcm_uframes_t -psc_dma_pointer(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); - struct psc_dma_stream *s; - dma_addr_t count; - - if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) - s = &psc_dma->capture; - else - s = &psc_dma->playback; - - count = s->period_current * s->period_bytes; - - return bytes_to_frames(substream->runtime, count); -} - -static int -psc_dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - return 0; -} - -static struct snd_pcm_ops psc_dma_ops = { - .open = psc_dma_open, - .close = psc_dma_close, - .hw_free = psc_dma_hw_free, - .ioctl = snd_pcm_lib_ioctl, - .pointer = psc_dma_pointer, - .trigger = psc_dma_trigger, - .hw_params = psc_dma_hw_params, -}; - -static u64 psc_dma_dmamask = DMA_BIT_MASK(32); -static int psc_dma_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_soc_dai *dai = rtd->cpu_dai; - struct snd_pcm *pcm = rtd->pcm; - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); - size_t size = psc_dma_hardware.buffer_bytes_max; - int rc = 0; - - dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", - card, dai, pcm); - - if (!card->dev->dma_mask) - card->dev->dma_mask = &psc_dma_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev, - size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer); - if (rc) - goto playback_alloc_err; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev, - size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer); - if (rc) - goto capture_alloc_err; - } - - if (rtd->codec->ac97) - rtd->codec->ac97->private_data = psc_dma; - - return 0; - - capture_alloc_err: - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) - snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer); - - playback_alloc_err: - dev_err(card->dev, "Cannot allocate buffer(s)\n"); - - return -ENOMEM; -} - -static void psc_dma_free(struct snd_pcm *pcm) -{ - struct snd_soc_pcm_runtime *rtd = pcm->private_data; - struct snd_pcm_substream *substream; - int stream; - - dev_dbg(rtd->platform->dev, "psc_dma_free(pcm=%p)\n", pcm); - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (substream) { - snd_dma_free_pages(&substream->dma_buffer); - substream->dma_buffer.area = NULL; - substream->dma_buffer.addr = 0; - } - } -} - -static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { - .ops = &psc_dma_ops, - .pcm_new = &psc_dma_new, - .pcm_free = &psc_dma_free, -}; - -static int mpc5200_hpcd_probe(struct platform_device *op) -{ - phys_addr_t fifo; - struct psc_dma *psc_dma; - struct resource res; - int size, irq, rc; - const __be32 *prop; - void __iomem *regs; - int ret; - - /* Fetch the registers and IRQ of the PSC */ - irq = irq_of_parse_and_map(op->dev.of_node, 0); - if (of_address_to_resource(op->dev.of_node, 0, &res)) { - dev_err(&op->dev, "Missing reg property\n"); - return -ENODEV; - } - regs = ioremap(res.start, resource_size(&res)); - if (!regs) { - dev_err(&op->dev, "Could not map registers\n"); - return -ENODEV; - } - - /* Allocate and initialize the driver private data */ - psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL); - if (!psc_dma) { - ret = -ENOMEM; - goto out_unmap; - } - - /* Get the PSC ID */ - prop = of_get_property(op->dev.of_node, "cell-index", &size); - if (!prop || size < sizeof *prop) { - ret = -ENODEV; - goto out_free; - } - - spin_lock_init(&psc_dma->lock); - mutex_init(&psc_dma->mutex); - psc_dma->id = be32_to_cpu(*prop); - psc_dma->irq = irq; - psc_dma->psc_regs = regs; - psc_dma->fifo_regs = regs + sizeof *psc_dma->psc_regs; - psc_dma->dev = &op->dev; - psc_dma->playback.psc_dma = psc_dma; - psc_dma->capture.psc_dma = psc_dma; - snprintf(psc_dma->name, sizeof psc_dma->name, "PSC%u", psc_dma->id); - - /* Find the address of the fifo data registers and setup the - * DMA tasks */ - fifo = res.start + offsetof(struct mpc52xx_psc, buffer.buffer_32); - psc_dma->capture.bcom_task = - bcom_psc_gen_bd_rx_init(psc_dma->id, 10, fifo, 512); - psc_dma->playback.bcom_task = - bcom_psc_gen_bd_tx_init(psc_dma->id, 10, fifo); - if (!psc_dma->capture.bcom_task || - !psc_dma->playback.bcom_task) { - dev_err(&op->dev, "Could not allocate bestcomm tasks\n"); - ret = -ENODEV; - goto out_free; - } - - /* Disable all interrupts and reset the PSC */ - out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); - /* reset receiver */ - out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_RX); - /* reset transmitter */ - out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_TX); - /* reset error */ - out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_RST_ERR_STAT); - /* reset mode */ - out_8(&psc_dma->psc_regs->command, MPC52xx_PSC_SEL_MODE_REG_1); - - /* Set up mode register; - * First write: RxRdy (FIFO Alarm) generates rx FIFO irq - * Second write: register Normal mode for non loopback - */ - out_8(&psc_dma->psc_regs->mode, 0); - out_8(&psc_dma->psc_regs->mode, 0); - - /* Set the TX and RX fifo alarm thresholds */ - out_be16(&psc_dma->fifo_regs->rfalarm, 0x100); - out_8(&psc_dma->fifo_regs->rfcntl, 0x4); - out_be16(&psc_dma->fifo_regs->tfalarm, 0x100); - out_8(&psc_dma->fifo_regs->tfcntl, 0x7); - - /* Lookup the IRQ numbers */ - psc_dma->playback.irq = - bcom_get_task_irq(psc_dma->playback.bcom_task); - psc_dma->capture.irq = - bcom_get_task_irq(psc_dma->capture.bcom_task); - - rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED, - "psc-dma-status", psc_dma); - rc |= request_irq(psc_dma->capture.irq, &psc_dma_bcom_irq, IRQF_SHARED, - "psc-dma-capture", &psc_dma->capture); - rc |= request_irq(psc_dma->playback.irq, &psc_dma_bcom_irq, IRQF_SHARED, - "psc-dma-playback", &psc_dma->playback); - if (rc) { - ret = -ENODEV; - goto out_irq; - } - - /* Save what we've done so it can be found again later */ - dev_set_drvdata(&op->dev, psc_dma); - - /* Tell the ASoC OF helpers about it */ - return snd_soc_register_platform(&op->dev, &mpc5200_audio_dma_platform); -out_irq: - free_irq(psc_dma->irq, psc_dma); - free_irq(psc_dma->capture.irq, &psc_dma->capture); - free_irq(psc_dma->playback.irq, &psc_dma->playback); -out_free: - kfree(psc_dma); -out_unmap: - iounmap(regs); - return ret; -} - -static int mpc5200_hpcd_remove(struct platform_device *op) -{ - struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); - - dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n"); - - snd_soc_unregister_platform(&op->dev); - - bcom_gen_bd_rx_release(psc_dma->capture.bcom_task); - bcom_gen_bd_tx_release(psc_dma->playback.bcom_task); - - /* Release irqs */ - free_irq(psc_dma->irq, psc_dma); - free_irq(psc_dma->capture.irq, &psc_dma->capture); - free_irq(psc_dma->playback.irq, &psc_dma->playback); - - iounmap(psc_dma->psc_regs); - kfree(psc_dma); - dev_set_drvdata(&op->dev, NULL); - - return 0; -} - -static struct of_device_id mpc5200_hpcd_match[] = { - { .compatible = "fsl,mpc5200-pcm", }, - {} -}; -MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); - -static struct platform_driver mpc5200_hpcd_of_driver = { - .probe = mpc5200_hpcd_probe, - .remove = mpc5200_hpcd_remove, - .driver = { - .owner = THIS_MODULE, - .name = "mpc5200-pcm-audio", - .of_match_table = mpc5200_hpcd_match, - } -}; - -module_platform_driver(mpc5200_hpcd_of_driver); - -MODULE_AUTHOR("Grant Likely "); -MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.h b/ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.h deleted file mode 100644 index a3c0cd53..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_dma.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Freescale MPC5200 Audio DMA driver - */ - -#ifndef __SOUND_SOC_FSL_MPC5200_DMA_H__ -#define __SOUND_SOC_FSL_MPC5200_DMA_H__ - -#define PSC_STREAM_NAME_LEN 32 - -/** - * psc_ac97_stream - Data specific to a single stream (playback or capture) - * @active: flag indicating if the stream is active - * @psc_dma: pointer back to parent psc_dma data structure - * @bcom_task: bestcomm task structure - * @irq: irq number for bestcomm task - * @period_end: physical address of end of DMA region - * @period_next_pt: physical address of next DMA buffer to enqueue - * @period_bytes: size of DMA period in bytes - * @ac97_slot_bits: Enable bits for turning on the correct AC97 slot - */ -struct psc_dma_stream { - struct snd_pcm_runtime *runtime; - int active; - struct psc_dma *psc_dma; - struct bcom_task *bcom_task; - int irq; - struct snd_pcm_substream *stream; - int period_next; - int period_current; - int period_bytes; - int period_count; - - /* AC97 state */ - u32 ac97_slot_bits; -}; - -/** - * psc_dma - Private driver data - * @name: short name for this device ("PSC0", "PSC1", etc) - * @psc_regs: pointer to the PSC's registers - * @fifo_regs: pointer to the PSC's FIFO registers - * @irq: IRQ of this PSC - * @dev: struct device pointer - * @dai: the CPU DAI for this device - * @sicr: Base value used in serial interface control register; mode is ORed - * with this value. - * @playback: Playback stream context data - * @capture: Capture stream context data - */ -struct psc_dma { - char name[32]; - struct mpc52xx_psc __iomem *psc_regs; - struct mpc52xx_psc_fifo __iomem *fifo_regs; - unsigned int irq; - struct device *dev; - spinlock_t lock; - struct mutex mutex; - u32 sicr; - uint sysclk; - int imr; - int id; - unsigned int slots; - - /* per-stream data */ - struct psc_dma_stream playback; - struct psc_dma_stream capture; - - /* Statistics */ - struct { - unsigned long overrun_count; - unsigned long underrun_count; - } stats; -}; - -/* Utility for retrieving psc_dma_stream structure from a substream */ -static inline struct psc_dma_stream * -to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) -{ - if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) - return &psc_dma->capture; - return &psc_dma->playback; -} - -#endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.c b/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.c deleted file mode 100644 index ffa00a2e..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * linux/sound/mpc5200-ac97.c -- AC97 support for the Freescale MPC52xx chip. - * - * Copyright (C) 2009 Jon Smirl, Digispeaker - * Author: Jon Smirl - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "mpc5200_dma.h" -#include "mpc5200_psc_ac97.h" - -#define DRV_NAME "mpc5200-psc-ac97" - -/* ALSA only supports a single AC97 device so static is recommend here */ -static struct psc_dma *psc_dma; - -static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - int status; - unsigned int val; - - mutex_lock(&psc_dma->mutex); - - /* Wait for command send status zero = ready */ - status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) & - MPC52xx_PSC_SR_CMDSEND), 100, 0); - if (status == 0) { - pr_err("timeout on ac97 bus (rdy)\n"); - mutex_unlock(&psc_dma->mutex); - return -ENODEV; - } - - /* Force clear the data valid bit */ - in_be32(&psc_dma->psc_regs->ac97_data); - - /* Send the read */ - out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24)); - - /* Wait for the answer */ - status = spin_event_timeout((in_be16(&psc_dma->psc_regs->sr_csr.status) & - MPC52xx_PSC_SR_DATA_VAL), 100, 0); - if (status == 0) { - pr_err("timeout on ac97 read (val) %x\n", - in_be16(&psc_dma->psc_regs->sr_csr.status)); - mutex_unlock(&psc_dma->mutex); - return -ENODEV; - } - /* Get the data */ - val = in_be32(&psc_dma->psc_regs->ac97_data); - if (((val >> 24) & 0x7f) != reg) { - pr_err("reg echo error on ac97 read\n"); - mutex_unlock(&psc_dma->mutex); - return -ENODEV; - } - val = (val >> 8) & 0xffff; - - mutex_unlock(&psc_dma->mutex); - return (unsigned short) val; -} - -static void psc_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - int status; - - mutex_lock(&psc_dma->mutex); - - /* Wait for command status zero = ready */ - status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) & - MPC52xx_PSC_SR_CMDSEND), 100, 0); - if (status == 0) { - pr_err("timeout on ac97 bus (write)\n"); - goto out; - } - /* Write data */ - out_be32(&psc_dma->psc_regs->ac97_cmd, - ((reg & 0x7f) << 24) | (val << 8)); - - out: - mutex_unlock(&psc_dma->mutex); -} - -static void psc_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; - - mutex_lock(&psc_dma->mutex); - - out_be32(®s->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR); - udelay(3); - out_be32(®s->sicr, psc_dma->sicr); - - mutex_unlock(&psc_dma->mutex); -} - -static void psc_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; - - mutex_lock(&psc_dma->mutex); - dev_dbg(psc_dma->dev, "cold reset\n"); - - mpc5200_psc_ac97_gpio_reset(psc_dma->id); - - /* Notify the PSC that a reset has occurred */ - out_be32(®s->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_ACRB); - - /* Re-enable RX and TX */ - out_8(®s->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - - mutex_unlock(&psc_dma->mutex); - - msleep(1); - psc_ac97_warm_reset(ac97); -} - -struct snd_ac97_bus_ops soc_ac97_ops = { - .read = psc_ac97_read, - .write = psc_ac97_write, - .reset = psc_ac97_cold_reset, - .warm_reset = psc_ac97_warm_reset, -}; -EXPORT_SYMBOL_GPL(soc_ac97_ops); - -static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); - struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); - - dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" - " periods=%i buffer_size=%i buffer_bytes=%i channels=%i" - " rate=%i format=%i\n", - __func__, substream, params_period_size(params), - params_period_bytes(params), params_periods(params), - params_buffer_size(params), params_buffer_bytes(params), - params_channels(params), params_rate(params), - params_format(params)); - - /* Determine the set of enable bits to turn on */ - s->ac97_slot_bits = (params_channels(params) == 1) ? 0x100 : 0x300; - if (substream->pstr->stream != SNDRV_PCM_STREAM_CAPTURE) - s->ac97_slot_bits <<= 16; - return 0; -} - -static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); - - dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream); - - if (params_channels(params) == 1) - out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000); - else - out_be32(&psc_dma->psc_regs->ac97_slots, 0x03000000); - - return 0; -} - -static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(dai); - struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - dev_dbg(psc_dma->dev, "AC97 START: stream=%i\n", - substream->pstr->stream); - - /* Set the slot enable bits */ - psc_dma->slots |= s->ac97_slot_bits; - out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots); - break; - - case SNDRV_PCM_TRIGGER_STOP: - dev_dbg(psc_dma->dev, "AC97 STOP: stream=%i\n", - substream->pstr->stream); - - /* Clear the slot enable bits */ - psc_dma->slots &= ~(s->ac97_slot_bits); - out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots); - break; - } - return 0; -} - -static int psc_ac97_probe(struct snd_soc_dai *cpu_dai) -{ - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); - struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; - - /* Go */ - out_8(®s->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - return 0; -} - -/* --------------------------------------------------------------------- - * ALSA SoC Bindings - * - * - Digital Audio Interface (DAI) template - * - create/destroy dai hooks - */ - -/** - * psc_ac97_dai_template: template CPU Digital Audio Interface - */ -static const struct snd_soc_dai_ops psc_ac97_analog_ops = { - .hw_params = psc_ac97_hw_analog_params, - .trigger = psc_ac97_trigger, -}; - -static const struct snd_soc_dai_ops psc_ac97_digital_ops = { - .hw_params = psc_ac97_hw_digital_params, -}; - -static struct snd_soc_dai_driver psc_ac97_dai[] = { -{ - .ac97_control = 1, - .probe = psc_ac97_probe, - .playback = { - .channels_min = 1, - .channels_max = 6, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S32_BE, - }, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S32_BE, - }, - .ops = &psc_ac97_analog_ops, -}, -{ - .ac97_control = 1, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_32000 | \ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE, - }, - .ops = &psc_ac97_digital_ops, -} }; - - - -/* --------------------------------------------------------------------- - * OF platform bus binding code: - * - Probe/remove operations - * - OF device match table - */ -static int __devinit psc_ac97_of_probe(struct platform_device *op) -{ - int rc; - struct snd_ac97 ac97; - struct mpc52xx_psc __iomem *regs; - - rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); - if (rc != 0) { - dev_err(&op->dev, "Failed to register DAI\n"); - return rc; - } - - psc_dma = dev_get_drvdata(&op->dev); - regs = psc_dma->psc_regs; - ac97.private_data = psc_dma; - - psc_dma->imr = 0; - out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); - - /* Configure the serial interface mode to AC97 */ - psc_dma->sicr = MPC52xx_PSC_SICR_SIM_AC97 | MPC52xx_PSC_SICR_ENAC97; - out_be32(®s->sicr, psc_dma->sicr); - - /* No slots active */ - out_be32(®s->ac97_slots, 0x00000000); - - return 0; -} - -static int __devexit psc_ac97_of_remove(struct platform_device *op) -{ - snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); - return 0; -} - -/* Match table for of_platform binding */ -static struct of_device_id psc_ac97_match[] __devinitdata = { - { .compatible = "fsl,mpc5200-psc-ac97", }, - { .compatible = "fsl,mpc5200b-psc-ac97", }, - {} -}; -MODULE_DEVICE_TABLE(of, psc_ac97_match); - -static struct platform_driver psc_ac97_driver = { - .probe = psc_ac97_of_probe, - .remove = __devexit_p(psc_ac97_of_remove), - .driver = { - .name = "mpc5200-psc-ac97", - .owner = THIS_MODULE, - .of_match_table = psc_ac97_match, - }, -}; - -module_platform_driver(psc_ac97_driver); - -MODULE_AUTHOR("Jon Smirl "); -MODULE_DESCRIPTION("mpc5200 AC97 module"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.h b/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.h deleted file mode 100644 index e881e784..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_ac97.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Freescale MPC5200 PSC in AC97 mode - * ALSA SoC Digital Audio Interface (DAI) driver - * - */ - -#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ -#define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ - -#define MPC5200_AC97_NORMAL 0 -#define MPC5200_AC97_SPDIF 1 - -#endif /* __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_i2s.c b/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_i2s.c deleted file mode 100644 index 7b530327..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/mpc5200_psc_i2s.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Freescale MPC5200 PSC in I2S mode - * ALSA SoC Digital Audio Interface (DAI) driver - * - * Copyright (C) 2008 Secret Lab Technologies Ltd. - * Copyright (C) 2009 Jon Smirl, Digispeaker - */ - -#include -#include -#include - -#include -#include -#include - -#include - -#include "mpc5200_dma.h" - -/** - * PSC_I2S_RATES: sample rates supported by the I2S - * - * This driver currently only supports the PSC running in I2S slave mode, - * which means the codec determines the sample rate. Therefore, we tell - * ALSA that we support all rates and let the codec driver decide what rates - * are really supported. - */ -#define PSC_I2S_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ - SNDRV_PCM_RATE_CONTINUOUS) - -/** - * PSC_I2S_FORMATS: audio formats supported by the PSC I2S mode - */ -#define PSC_I2S_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \ - SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE) - -static int psc_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai); - u32 mode; - - dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" - " periods=%i buffer_size=%i buffer_bytes=%i\n", - __func__, substream, params_period_size(params), - params_period_bytes(params), params_periods(params), - params_buffer_size(params), params_buffer_bytes(params)); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - mode = MPC52xx_PSC_SICR_SIM_CODEC_8; - break; - case SNDRV_PCM_FORMAT_S16_BE: - mode = MPC52xx_PSC_SICR_SIM_CODEC_16; - break; - case SNDRV_PCM_FORMAT_S24_BE: - mode = MPC52xx_PSC_SICR_SIM_CODEC_24; - break; - case SNDRV_PCM_FORMAT_S32_BE: - mode = MPC52xx_PSC_SICR_SIM_CODEC_32; - break; - default: - dev_dbg(psc_dma->dev, "invalid format\n"); - return -EINVAL; - } - out_be32(&psc_dma->psc_regs->sicr, psc_dma->sicr | mode); - - return 0; -} - -/** - * psc_i2s_set_sysclk: set the clock frequency and direction - * - * This function is called by the machine driver to tell us what the clock - * frequency and direction are. - * - * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN), - * and we don't care about the frequency. Return an error if the direction - * is not SND_SOC_CLOCK_IN. - * - * @clk_id: reserved, should be zero - * @freq: the frequency of the given clock ID, currently ignored - * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master) - */ -static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); - dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n", - cpu_dai, dir); - return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; -} - -/** - * psc_i2s_set_fmt: set the serial format. - * - * This function is called by the machine driver to tell us what serial - * format to use. - * - * This driver only supports I2S mode. Return an error if the format is - * not SND_SOC_DAIFMT_I2S. - * - * @format: one of SND_SOC_DAIFMT_xxx - */ -static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) -{ - struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai); - dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n", - cpu_dai, format); - return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; -} - -/* --------------------------------------------------------------------- - * ALSA SoC Bindings - * - * - Digital Audio Interface (DAI) template - * - create/destroy dai hooks - */ - -/** - * psc_i2s_dai_template: template CPU Digital Audio Interface - */ -static const struct snd_soc_dai_ops psc_i2s_dai_ops = { - .hw_params = psc_i2s_hw_params, - .set_sysclk = psc_i2s_set_sysclk, - .set_fmt = psc_i2s_set_fmt, -}; - -static struct snd_soc_dai_driver psc_i2s_dai[] = {{ - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = PSC_I2S_RATES, - .formats = PSC_I2S_FORMATS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = PSC_I2S_RATES, - .formats = PSC_I2S_FORMATS, - }, - .ops = &psc_i2s_dai_ops, -} }; - -/* --------------------------------------------------------------------- - * OF platform bus binding code: - * - Probe/remove operations - * - OF device match table - */ -static int __devinit psc_i2s_of_probe(struct platform_device *op) -{ - int rc; - struct psc_dma *psc_dma; - struct mpc52xx_psc __iomem *regs; - - rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); - if (rc != 0) { - pr_err("Failed to register DAI\n"); - return rc; - } - - psc_dma = dev_get_drvdata(&op->dev); - regs = psc_dma->psc_regs; - - /* Configure the serial interface mode; defaulting to CODEC8 mode */ - psc_dma->sicr = MPC52xx_PSC_SICR_DTS1 | MPC52xx_PSC_SICR_I2S | - MPC52xx_PSC_SICR_CLKPOL; - out_be32(&psc_dma->psc_regs->sicr, - psc_dma->sicr | MPC52xx_PSC_SICR_SIM_CODEC_8); - - /* Check for the codec handle. If it is not present then we - * are done */ - if (!of_get_property(op->dev.of_node, "codec-handle", NULL)) - return 0; - - /* Due to errata in the dma mode; need to line up enabling - * the transmitter with a transition on the frame sync - * line */ - - /* first make sure it is low */ - while ((in_8(®s->ipcr_acr.ipcr) & 0x80) != 0) - ; - /* then wait for the transition to high */ - while ((in_8(®s->ipcr_acr.ipcr) & 0x80) == 0) - ; - /* Finally, enable the PSC. - * Receiver must always be enabled; even when we only want - * transmit. (see 15.3.2.3 of MPC5200B User's Guide) */ - - /* Go */ - out_8(&psc_dma->psc_regs->command, - MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE); - - return 0; - -} - -static int __devexit psc_i2s_of_remove(struct platform_device *op) -{ - snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); - return 0; -} - -/* Match table for of_platform binding */ -static struct of_device_id psc_i2s_match[] __devinitdata = { - { .compatible = "fsl,mpc5200-psc-i2s", }, - { .compatible = "fsl,mpc5200b-psc-i2s", }, - {} -}; -MODULE_DEVICE_TABLE(of, psc_i2s_match); - -static struct platform_driver psc_i2s_driver = { - .probe = psc_i2s_of_probe, - .remove = __devexit_p(psc_i2s_of_remove), - .driver = { - .name = "mpc5200-psc-i2s", - .owner = THIS_MODULE, - .of_match_table = psc_i2s_match, - }, -}; - -module_platform_driver(psc_i2s_driver); - -MODULE_AUTHOR("Grant Likely "); -MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/fsl/mpc8610_hpcd.c b/ANDROID_3.4.5/sound/soc/fsl/mpc8610_hpcd.c deleted file mode 100644 index 3fea5a15..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/mpc8610_hpcd.c +++ /dev/null @@ -1,595 +0,0 @@ -/** - * Freescale MPC8610HPCD ALSA SoC Machine driver - * - * Author: Timur Tabi - * - * Copyright 2007-2010 Freescale Semiconductor, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "fsl_dma.h" -#include "fsl_ssi.h" - -/* There's only one global utilities register */ -static phys_addr_t guts_phys; - -#define DAI_NAME_SIZE 32 - -/** - * mpc8610_hpcd_data: machine-specific ASoC device data - * - * This structure contains data for a single sound platform device on an - * MPC8610 HPCD. Some of the data is taken from the device tree. - */ -struct mpc8610_hpcd_data { - struct snd_soc_dai_link dai[2]; - struct snd_soc_card card; - unsigned int dai_format; - unsigned int codec_clk_direction; - unsigned int cpu_clk_direction; - unsigned int clk_frequency; - unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */ - unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */ - unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ - char codec_dai_name[DAI_NAME_SIZE]; - char codec_name[DAI_NAME_SIZE]; - char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */ -}; - -/** - * mpc8610_hpcd_machine_probe: initialize the board - * - * This function is used to initialize the board-specific hardware. - * - * Here we program the DMACR and PMUXCR registers. - */ -static int mpc8610_hpcd_machine_probe(struct snd_soc_card *card) -{ - struct mpc8610_hpcd_data *machine_data = - container_of(card, struct mpc8610_hpcd_data, card); - struct ccsr_guts __iomem *guts; - - guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); - if (!guts) { - dev_err(card->dev, "could not map global utilities\n"); - return -ENOMEM; - } - - /* Program the signal routing between the SSI and the DMA */ - guts_set_dmacr(guts, machine_data->dma_id[0], - machine_data->dma_channel_id[0], - CCSR_GUTS_DMACR_DEV_SSI); - guts_set_dmacr(guts, machine_data->dma_id[1], - machine_data->dma_channel_id[1], - CCSR_GUTS_DMACR_DEV_SSI); - - guts_set_pmuxcr_dma(guts, machine_data->dma_id[0], - machine_data->dma_channel_id[0], 0); - guts_set_pmuxcr_dma(guts, machine_data->dma_id[1], - machine_data->dma_channel_id[1], 0); - - switch (machine_data->ssi_id) { - case 0: - clrsetbits_be32(&guts->pmuxcr, - CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI); - break; - case 1: - clrsetbits_be32(&guts->pmuxcr, - CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI); - break; - } - - iounmap(guts); - - return 0; -} - -/** - * mpc8610_hpcd_startup: program the board with various hardware parameters - * - * This function takes board-specific information, like clock frequencies - * and serial data formats, and passes that information to the codec and - * transport drivers. - */ -static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct mpc8610_hpcd_data *machine_data = - container_of(rtd->card, struct mpc8610_hpcd_data, card); - struct device *dev = rtd->card->dev; - int ret = 0; - - /* Tell the codec driver what the serial protocol is. */ - ret = snd_soc_dai_set_fmt(rtd->codec_dai, machine_data->dai_format); - if (ret < 0) { - dev_err(dev, "could not set codec driver audio format\n"); - return ret; - } - - /* - * Tell the codec driver what the MCLK frequency is, and whether it's - * a slave or master. - */ - ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, - machine_data->clk_frequency, - machine_data->codec_clk_direction); - if (ret < 0) { - dev_err(dev, "could not set codec driver clock params\n"); - return ret; - } - - return 0; -} - -/** - * mpc8610_hpcd_machine_remove: Remove the sound device - * - * This function is called to remove the sound device for one SSI. We - * de-program the DMACR and PMUXCR register. - */ -static int mpc8610_hpcd_machine_remove(struct snd_soc_card *card) -{ - struct mpc8610_hpcd_data *machine_data = - container_of(card, struct mpc8610_hpcd_data, card); - struct ccsr_guts __iomem *guts; - - guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); - if (!guts) { - dev_err(card->dev, "could not map global utilities\n"); - return -ENOMEM; - } - - /* Restore the signal routing */ - - guts_set_dmacr(guts, machine_data->dma_id[0], - machine_data->dma_channel_id[0], 0); - guts_set_dmacr(guts, machine_data->dma_id[1], - machine_data->dma_channel_id[1], 0); - - switch (machine_data->ssi_id) { - case 0: - clrsetbits_be32(&guts->pmuxcr, - CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA); - break; - case 1: - clrsetbits_be32(&guts->pmuxcr, - CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA); - break; - } - - iounmap(guts); - - return 0; -} - -/** - * mpc8610_hpcd_ops: ASoC machine driver operations - */ -static struct snd_soc_ops mpc8610_hpcd_ops = { - .startup = mpc8610_hpcd_startup, -}; - -/** - * get_node_by_phandle_name - get a node by its phandle name - * - * This function takes a node, the name of a property in that node, and a - * compatible string. Assuming the property is a phandle to another node, - * it returns that node, (optionally) if that node is compatible. - * - * If the property is not a phandle, or the node it points to is not compatible - * with the specific string, then NULL is returned. - */ -static struct device_node *get_node_by_phandle_name(struct device_node *np, - const char *name, - const char *compatible) -{ - const phandle *ph; - int len; - - ph = of_get_property(np, name, &len); - if (!ph || (len != sizeof(phandle))) - return NULL; - - np = of_find_node_by_phandle(*ph); - if (!np) - return NULL; - - if (compatible && !of_device_is_compatible(np, compatible)) { - of_node_put(np); - return NULL; - } - - return np; -} - -/** - * get_parent_cell_index -- return the cell-index of the parent of a node - * - * Return the value of the cell-index property of the parent of the given - * node. This is used for DMA channel nodes that need to know the DMA ID - * of the controller they are on. - */ -static int get_parent_cell_index(struct device_node *np) -{ - struct device_node *parent = of_get_parent(np); - const u32 *iprop; - - if (!parent) - return -1; - - iprop = of_get_property(parent, "cell-index", NULL); - of_node_put(parent); - - if (!iprop) - return -1; - - return be32_to_cpup(iprop); -} - -/** - * codec_node_dev_name - determine the dev_name for a codec node - * - * This function determines the dev_name for an I2C node. This is the name - * that would be returned by dev_name() if this device_node were part of a - * 'struct device' It's ugly and hackish, but it works. - * - * The dev_name for such devices include the bus number and I2C address. For - * example, "cs4270.0-004f". - */ -static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) -{ - const u32 *iprop; - int addr; - char temp[DAI_NAME_SIZE]; - struct i2c_client *i2c; - - of_modalias_node(np, temp, DAI_NAME_SIZE); - - iprop = of_get_property(np, "reg", NULL); - if (!iprop) - return -EINVAL; - - addr = be32_to_cpup(iprop); - - /* We need the adapter number */ - i2c = of_find_i2c_device_by_node(np); - if (!i2c) - return -ENODEV; - - snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr); - - return 0; -} - -static int get_dma_channel(struct device_node *ssi_np, - const char *name, - struct snd_soc_dai_link *dai, - unsigned int *dma_channel_id, - unsigned int *dma_id) -{ - struct resource res; - struct device_node *dma_channel_np; - const u32 *iprop; - int ret; - - dma_channel_np = get_node_by_phandle_name(ssi_np, name, - "fsl,ssi-dma-channel"); - if (!dma_channel_np) - return -EINVAL; - - /* Determine the dev_name for the device_node. This code mimics the - * behavior of of_device_make_bus_id(). We need this because ASoC uses - * the dev_name() of the device to match the platform (DMA) device with - * the CPU (SSI) device. It's all ugly and hackish, but it works (for - * now). - * - * dai->platform name should already point to an allocated buffer. - */ - ret = of_address_to_resource(dma_channel_np, 0, &res); - if (ret) - return ret; - snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", - (unsigned long long) res.start, dma_channel_np->name); - - iprop = of_get_property(dma_channel_np, "cell-index", NULL); - if (!iprop) { - of_node_put(dma_channel_np); - return -EINVAL; - } - - *dma_channel_id = be32_to_cpup(iprop); - *dma_id = get_parent_cell_index(dma_channel_np); - of_node_put(dma_channel_np); - - return 0; -} - -/** - * mpc8610_hpcd_probe: platform probe function for the machine driver - * - * Although this is a machine driver, the SSI node is the "master" node with - * respect to audio hardware connections. Therefore, we create a new ASoC - * device for each new SSI node that has a codec attached. - */ -static int mpc8610_hpcd_probe(struct platform_device *pdev) -{ - struct device *dev = pdev->dev.parent; - /* ssi_pdev is the platform device for the SSI node that probed us */ - struct platform_device *ssi_pdev = - container_of(dev, struct platform_device, dev); - struct device_node *np = ssi_pdev->dev.of_node; - struct device_node *codec_np = NULL; - struct platform_device *sound_device = NULL; - struct mpc8610_hpcd_data *machine_data; - int ret = -ENODEV; - const char *sprop; - const u32 *iprop; - - /* Find the codec node for this SSI. */ - codec_np = of_parse_phandle(np, "codec-handle", 0); - if (!codec_np) { - dev_err(dev, "invalid codec node\n"); - return -EINVAL; - } - - machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); - if (!machine_data) { - ret = -ENOMEM; - goto error_alloc; - } - - machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); - machine_data->dai[0].ops = &mpc8610_hpcd_ops; - - /* Determine the codec name, it will be used as the codec DAI name */ - ret = codec_node_dev_name(codec_np, machine_data->codec_name, - DAI_NAME_SIZE); - if (ret) { - dev_err(&pdev->dev, "invalid codec node %s\n", - codec_np->full_name); - ret = -EINVAL; - goto error; - } - machine_data->dai[0].codec_name = machine_data->codec_name; - - /* The DAI name from the codec (snd_soc_dai_driver.name) */ - machine_data->dai[0].codec_dai_name = "cs4270-hifi"; - - /* We register two DAIs per SSI, one for playback and the other for - * capture. Currently, we only support codecs that have one DAI for - * both playback and capture. - */ - memcpy(&machine_data->dai[1], &machine_data->dai[0], - sizeof(struct snd_soc_dai_link)); - - /* Get the device ID */ - iprop = of_get_property(np, "cell-index", NULL); - if (!iprop) { - dev_err(&pdev->dev, "cell-index property not found\n"); - ret = -EINVAL; - goto error; - } - machine_data->ssi_id = be32_to_cpup(iprop); - - /* Get the serial format and clock direction. */ - sprop = of_get_property(np, "fsl,mode", NULL); - if (!sprop) { - dev_err(&pdev->dev, "fsl,mode property not found\n"); - ret = -EINVAL; - goto error; - } - - if (strcasecmp(sprop, "i2s-slave") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM; - machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; - machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; - - /* In i2s-slave mode, the codec has its own clock source, so we - * need to get the frequency from the device tree and pass it to - * the codec driver. - */ - iprop = of_get_property(codec_np, "clock-frequency", NULL); - if (!iprop || !*iprop) { - dev_err(&pdev->dev, "codec bus-frequency " - "property is missing or invalid\n"); - ret = -EINVAL; - goto error; - } - machine_data->clk_frequency = be32_to_cpup(iprop); - } else if (strcasecmp(sprop, "i2s-master") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS; - machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; - machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; - } else if (strcasecmp(sprop, "lj-slave") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM; - machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; - machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; - } else if (strcasecmp(sprop, "lj-master") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS; - machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; - machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; - } else if (strcasecmp(sprop, "rj-slave") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM; - machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; - machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; - } else if (strcasecmp(sprop, "rj-master") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS; - machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; - machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; - } else if (strcasecmp(sprop, "ac97-slave") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM; - machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; - machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; - } else if (strcasecmp(sprop, "ac97-master") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS; - machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; - machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; - } else { - dev_err(&pdev->dev, - "unrecognized fsl,mode property '%s'\n", sprop); - ret = -EINVAL; - goto error; - } - - if (!machine_data->clk_frequency) { - dev_err(&pdev->dev, "unknown clock frequency\n"); - ret = -EINVAL; - goto error; - } - - /* Find the playback DMA channel to use. */ - machine_data->dai[0].platform_name = machine_data->platform_name[0]; - ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0], - &machine_data->dma_channel_id[0], - &machine_data->dma_id[0]); - if (ret) { - dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n"); - goto error; - } - - /* Find the capture DMA channel to use. */ - machine_data->dai[1].platform_name = machine_data->platform_name[1]; - ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1], - &machine_data->dma_channel_id[1], - &machine_data->dma_id[1]); - if (ret) { - dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n"); - goto error; - } - - /* Initialize our DAI data structure. */ - machine_data->dai[0].stream_name = "playback"; - machine_data->dai[1].stream_name = "capture"; - machine_data->dai[0].name = machine_data->dai[0].stream_name; - machine_data->dai[1].name = machine_data->dai[1].stream_name; - - machine_data->card.probe = mpc8610_hpcd_machine_probe; - machine_data->card.remove = mpc8610_hpcd_machine_remove; - machine_data->card.name = pdev->name; /* The platform driver name */ - machine_data->card.num_links = 2; - machine_data->card.dai_link = machine_data->dai; - - /* Allocate a new audio platform device structure */ - sound_device = platform_device_alloc("soc-audio", -1); - if (!sound_device) { - dev_err(&pdev->dev, "platform device alloc failed\n"); - ret = -ENOMEM; - goto error; - } - - /* Associate the card data with the sound device */ - platform_set_drvdata(sound_device, &machine_data->card); - - /* Register with ASoC */ - ret = platform_device_add(sound_device); - if (ret) { - dev_err(&pdev->dev, "platform device add failed\n"); - goto error_sound; - } - dev_set_drvdata(&pdev->dev, sound_device); - - of_node_put(codec_np); - - return 0; - -error_sound: - platform_device_put(sound_device); -error: - kfree(machine_data); -error_alloc: - of_node_put(codec_np); - return ret; -} - -/** - * mpc8610_hpcd_remove: remove the platform device - * - * This function is called when the platform device is removed. - */ -static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) -{ - struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); - struct snd_soc_card *card = platform_get_drvdata(sound_device); - struct mpc8610_hpcd_data *machine_data = - container_of(card, struct mpc8610_hpcd_data, card); - - platform_device_unregister(sound_device); - - kfree(machine_data); - sound_device->dev.platform_data = NULL; - - dev_set_drvdata(&pdev->dev, NULL); - - return 0; -} - -static struct platform_driver mpc8610_hpcd_driver = { - .probe = mpc8610_hpcd_probe, - .remove = __devexit_p(mpc8610_hpcd_remove), - .driver = { - /* The name must match 'compatible' property in the device tree, - * in lowercase letters. - */ - .name = "snd-soc-mpc8610hpcd", - .owner = THIS_MODULE, - }, -}; - -/** - * mpc8610_hpcd_init: machine driver initialization. - * - * This function is called when this module is loaded. - */ -static int __init mpc8610_hpcd_init(void) -{ - struct device_node *guts_np; - struct resource res; - - pr_info("Freescale MPC8610 HPCD ALSA SoC machine driver\n"); - - /* Get the physical address of the global utilities registers */ - guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); - if (of_address_to_resource(guts_np, 0, &res)) { - pr_err("mpc8610-hpcd: missing/invalid global utilities node\n"); - return -EINVAL; - } - guts_phys = res.start; - - return platform_driver_register(&mpc8610_hpcd_driver); -} - -/** - * mpc8610_hpcd_exit: machine driver exit - * - * This function is called when this driver is unloaded. - */ -static void __exit mpc8610_hpcd_exit(void) -{ - platform_driver_unregister(&mpc8610_hpcd_driver); -} - -module_init(mpc8610_hpcd_init); -module_exit(mpc8610_hpcd_exit); - -MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC machine driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/soc/fsl/p1022_ds.c b/ANDROID_3.4.5/sound/soc/fsl/p1022_ds.c deleted file mode 100644 index 982a1c94..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/p1022_ds.c +++ /dev/null @@ -1,601 +0,0 @@ -/** - * Freescale P1022DS ALSA SoC Machine driver - * - * Author: Timur Tabi - * - * Copyright 2010 Freescale Semiconductor, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "fsl_dma.h" -#include "fsl_ssi.h" - -/* P1022-specific PMUXCR and DMUXCR bit definitions */ - -#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK 0x0001c000 -#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI 0x00010000 -#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI 0x00018000 - -#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK 0x00000c00 -#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI 0x00000000 - -#define CCSR_GUTS_DMUXCR_PAD 1 /* DMA controller/channel set to pad */ -#define CCSR_GUTS_DMUXCR_SSI 2 /* DMA controller/channel set to SSI */ - -/* - * Set the DMACR register in the GUTS - * - * The DMACR register determines the source of initiated transfers for each - * channel on each DMA controller. Rather than have a bunch of repetitive - * macros for the bit patterns, we just have a function that calculates - * them. - * - * guts: Pointer to GUTS structure - * co: The DMA controller (0 or 1) - * ch: The channel on the DMA controller (0, 1, 2, or 3) - * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx) - */ -static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts, - unsigned int co, unsigned int ch, unsigned int device) -{ - unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); - - clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift); -} - -/* There's only one global utilities register */ -static phys_addr_t guts_phys; - -#define DAI_NAME_SIZE 32 - -/** - * machine_data: machine-specific ASoC device data - * - * This structure contains data for a single sound platform device on an - * P1022 DS. Some of the data is taken from the device tree. - */ -struct machine_data { - struct snd_soc_dai_link dai[2]; - struct snd_soc_card card; - unsigned int dai_format; - unsigned int codec_clk_direction; - unsigned int cpu_clk_direction; - unsigned int clk_frequency; - unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */ - unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */ - unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ - char codec_name[DAI_NAME_SIZE]; - char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */ -}; - -/** - * p1022_ds_machine_probe: initialize the board - * - * This function is used to initialize the board-specific hardware. - * - * Here we program the DMACR and PMUXCR registers. - */ -static int p1022_ds_machine_probe(struct snd_soc_card *card) -{ - struct machine_data *mdata = - container_of(card, struct machine_data, card); - struct ccsr_guts __iomem *guts; - - guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); - if (!guts) { - dev_err(card->dev, "could not map global utilities\n"); - return -ENOMEM; - } - - /* Enable SSI Tx signal */ - clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK, - CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI); - - /* Enable SSI Rx signal */ - clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK, - CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI); - - /* Enable DMA Channel for SSI */ - guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], - CCSR_GUTS_DMUXCR_SSI); - - guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], - CCSR_GUTS_DMUXCR_SSI); - - iounmap(guts); - - return 0; -} - -/** - * p1022_ds_startup: program the board with various hardware parameters - * - * This function takes board-specific information, like clock frequencies - * and serial data formats, and passes that information to the codec and - * transport drivers. - */ -static int p1022_ds_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct machine_data *mdata = - container_of(rtd->card, struct machine_data, card); - struct device *dev = rtd->card->dev; - int ret = 0; - - /* Tell the codec driver what the serial protocol is. */ - ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format); - if (ret < 0) { - dev_err(dev, "could not set codec driver audio format\n"); - return ret; - } - - /* - * Tell the codec driver what the MCLK frequency is, and whether it's - * a slave or master. - */ - ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, mdata->clk_frequency, - mdata->codec_clk_direction); - if (ret < 0) { - dev_err(dev, "could not set codec driver clock params\n"); - return ret; - } - - return 0; -} - -/** - * p1022_ds_machine_remove: Remove the sound device - * - * This function is called to remove the sound device for one SSI. We - * de-program the DMACR and PMUXCR register. - */ -static int p1022_ds_machine_remove(struct snd_soc_card *card) -{ - struct machine_data *mdata = - container_of(card, struct machine_data, card); - struct ccsr_guts __iomem *guts; - - guts = ioremap(guts_phys, sizeof(struct ccsr_guts)); - if (!guts) { - dev_err(card->dev, "could not map global utilities\n"); - return -ENOMEM; - } - - /* Restore the signal routing */ - clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK); - clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK); - guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0); - guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0); - - iounmap(guts); - - return 0; -} - -/** - * p1022_ds_ops: ASoC machine driver operations - */ -static struct snd_soc_ops p1022_ds_ops = { - .startup = p1022_ds_startup, -}; - -/** - * get_node_by_phandle_name - get a node by its phandle name - * - * This function takes a node, the name of a property in that node, and a - * compatible string. Assuming the property is a phandle to another node, - * it returns that node, (optionally) if that node is compatible. - * - * If the property is not a phandle, or the node it points to is not compatible - * with the specific string, then NULL is returned. - */ -static struct device_node *get_node_by_phandle_name(struct device_node *np, - const char *name, const char *compatible) -{ - np = of_parse_phandle(np, name, 0); - if (!np) - return NULL; - - if (!of_device_is_compatible(np, compatible)) { - of_node_put(np); - return NULL; - } - - return np; -} - -/** - * get_parent_cell_index -- return the cell-index of the parent of a node - * - * Return the value of the cell-index property of the parent of the given - * node. This is used for DMA channel nodes that need to know the DMA ID - * of the controller they are on. - */ -static int get_parent_cell_index(struct device_node *np) -{ - struct device_node *parent = of_get_parent(np); - const u32 *iprop; - int ret = -1; - - if (!parent) - return -1; - - iprop = of_get_property(parent, "cell-index", NULL); - if (iprop) - ret = be32_to_cpup(iprop); - - of_node_put(parent); - - return ret; -} - -/** - * codec_node_dev_name - determine the dev_name for a codec node - * - * This function determines the dev_name for an I2C node. This is the name - * that would be returned by dev_name() if this device_node were part of a - * 'struct device' It's ugly and hackish, but it works. - * - * The dev_name for such devices include the bus number and I2C address. For - * example, "cs4270-codec.0-004f". - */ -static int codec_node_dev_name(struct device_node *np, char *buf, size_t len) -{ - const u32 *iprop; - int addr; - char temp[DAI_NAME_SIZE]; - struct i2c_client *i2c; - - of_modalias_node(np, temp, DAI_NAME_SIZE); - - iprop = of_get_property(np, "reg", NULL); - if (!iprop) - return -EINVAL; - - addr = be32_to_cpup(iprop); - - /* We need the adapter number */ - i2c = of_find_i2c_device_by_node(np); - if (!i2c) - return -ENODEV; - - snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr); - - return 0; -} - -static int get_dma_channel(struct device_node *ssi_np, - const char *name, - struct snd_soc_dai_link *dai, - unsigned int *dma_channel_id, - unsigned int *dma_id) -{ - struct resource res; - struct device_node *dma_channel_np; - const u32 *iprop; - int ret; - - dma_channel_np = get_node_by_phandle_name(ssi_np, name, - "fsl,ssi-dma-channel"); - if (!dma_channel_np) - return -EINVAL; - - /* Determine the dev_name for the device_node. This code mimics the - * behavior of of_device_make_bus_id(). We need this because ASoC uses - * the dev_name() of the device to match the platform (DMA) device with - * the CPU (SSI) device. It's all ugly and hackish, but it works (for - * now). - * - * dai->platform name should already point to an allocated buffer. - */ - ret = of_address_to_resource(dma_channel_np, 0, &res); - if (ret) { - of_node_put(dma_channel_np); - return ret; - } - snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s", - (unsigned long long) res.start, dma_channel_np->name); - - iprop = of_get_property(dma_channel_np, "cell-index", NULL); - if (!iprop) { - of_node_put(dma_channel_np); - return -EINVAL; - } - - *dma_channel_id = be32_to_cpup(iprop); - *dma_id = get_parent_cell_index(dma_channel_np); - of_node_put(dma_channel_np); - - return 0; -} - -/** - * p1022_ds_probe: platform probe function for the machine driver - * - * Although this is a machine driver, the SSI node is the "master" node with - * respect to audio hardware connections. Therefore, we create a new ASoC - * device for each new SSI node that has a codec attached. - */ -static int p1022_ds_probe(struct platform_device *pdev) -{ - struct device *dev = pdev->dev.parent; - /* ssi_pdev is the platform device for the SSI node that probed us */ - struct platform_device *ssi_pdev = - container_of(dev, struct platform_device, dev); - struct device_node *np = ssi_pdev->dev.of_node; - struct device_node *codec_np = NULL; - struct platform_device *sound_device = NULL; - struct machine_data *mdata; - int ret = -ENODEV; - const char *sprop; - const u32 *iprop; - - /* Find the codec node for this SSI. */ - codec_np = of_parse_phandle(np, "codec-handle", 0); - if (!codec_np) { - dev_err(dev, "could not find codec node\n"); - return -EINVAL; - } - - mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL); - if (!mdata) { - ret = -ENOMEM; - goto error_put; - } - - mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev); - mdata->dai[0].ops = &p1022_ds_ops; - - /* Determine the codec name, it will be used as the codec DAI name */ - ret = codec_node_dev_name(codec_np, mdata->codec_name, DAI_NAME_SIZE); - if (ret) { - dev_err(&pdev->dev, "invalid codec node %s\n", - codec_np->full_name); - ret = -EINVAL; - goto error; - } - mdata->dai[0].codec_name = mdata->codec_name; - - /* We register two DAIs per SSI, one for playback and the other for - * capture. We support codecs that have separate DAIs for both playback - * and capture. - */ - memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link)); - - /* The DAI names from the codec (snd_soc_dai_driver.name) */ - mdata->dai[0].codec_dai_name = "wm8776-hifi-playback"; - mdata->dai[1].codec_dai_name = "wm8776-hifi-capture"; - - /* Get the device ID */ - iprop = of_get_property(np, "cell-index", NULL); - if (!iprop) { - dev_err(&pdev->dev, "cell-index property not found\n"); - ret = -EINVAL; - goto error; - } - mdata->ssi_id = be32_to_cpup(iprop); - - /* Get the serial format and clock direction. */ - sprop = of_get_property(np, "fsl,mode", NULL); - if (!sprop) { - dev_err(&pdev->dev, "fsl,mode property not found\n"); - ret = -EINVAL; - goto error; - } - - if (strcasecmp(sprop, "i2s-slave") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM; - mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; - mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; - - /* In i2s-slave mode, the codec has its own clock source, so we - * need to get the frequency from the device tree and pass it to - * the codec driver. - */ - iprop = of_get_property(codec_np, "clock-frequency", NULL); - if (!iprop || !*iprop) { - dev_err(&pdev->dev, "codec bus-frequency " - "property is missing or invalid\n"); - ret = -EINVAL; - goto error; - } - mdata->clk_frequency = be32_to_cpup(iprop); - } else if (strcasecmp(sprop, "i2s-master") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS; - mdata->codec_clk_direction = SND_SOC_CLOCK_IN; - mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; - } else if (strcasecmp(sprop, "lj-slave") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM; - mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; - mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; - } else if (strcasecmp(sprop, "lj-master") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS; - mdata->codec_clk_direction = SND_SOC_CLOCK_IN; - mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; - } else if (strcasecmp(sprop, "rj-slave") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM; - mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; - mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; - } else if (strcasecmp(sprop, "rj-master") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS; - mdata->codec_clk_direction = SND_SOC_CLOCK_IN; - mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; - } else if (strcasecmp(sprop, "ac97-slave") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM; - mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; - mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; - } else if (strcasecmp(sprop, "ac97-master") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS; - mdata->codec_clk_direction = SND_SOC_CLOCK_IN; - mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; - } else { - dev_err(&pdev->dev, - "unrecognized fsl,mode property '%s'\n", sprop); - ret = -EINVAL; - goto error; - } - - if (!mdata->clk_frequency) { - dev_err(&pdev->dev, "unknown clock frequency\n"); - ret = -EINVAL; - goto error; - } - - /* Find the playback DMA channel to use. */ - mdata->dai[0].platform_name = mdata->platform_name[0]; - ret = get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], - &mdata->dma_channel_id[0], - &mdata->dma_id[0]); - if (ret) { - dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n"); - goto error; - } - - /* Find the capture DMA channel to use. */ - mdata->dai[1].platform_name = mdata->platform_name[1]; - ret = get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1], - &mdata->dma_channel_id[1], - &mdata->dma_id[1]); - if (ret) { - dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n"); - goto error; - } - - /* Initialize our DAI data structure. */ - mdata->dai[0].stream_name = "playback"; - mdata->dai[1].stream_name = "capture"; - mdata->dai[0].name = mdata->dai[0].stream_name; - mdata->dai[1].name = mdata->dai[1].stream_name; - - mdata->card.probe = p1022_ds_machine_probe; - mdata->card.remove = p1022_ds_machine_remove; - mdata->card.name = pdev->name; /* The platform driver name */ - mdata->card.num_links = 2; - mdata->card.dai_link = mdata->dai; - - /* Allocate a new audio platform device structure */ - sound_device = platform_device_alloc("soc-audio", -1); - if (!sound_device) { - dev_err(&pdev->dev, "platform device alloc failed\n"); - ret = -ENOMEM; - goto error; - } - - /* Associate the card data with the sound device */ - platform_set_drvdata(sound_device, &mdata->card); - - /* Register with ASoC */ - ret = platform_device_add(sound_device); - if (ret) { - dev_err(&pdev->dev, "platform device add failed\n"); - goto error; - } - dev_set_drvdata(&pdev->dev, sound_device); - - of_node_put(codec_np); - - return 0; - -error: - if (sound_device) - platform_device_put(sound_device); - - kfree(mdata); -error_put: - of_node_put(codec_np); - return ret; -} - -/** - * p1022_ds_remove: remove the platform device - * - * This function is called when the platform device is removed. - */ -static int __devexit p1022_ds_remove(struct platform_device *pdev) -{ - struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); - struct snd_soc_card *card = platform_get_drvdata(sound_device); - struct machine_data *mdata = - container_of(card, struct machine_data, card); - - platform_device_unregister(sound_device); - - kfree(mdata); - sound_device->dev.platform_data = NULL; - - dev_set_drvdata(&pdev->dev, NULL); - - return 0; -} - -static struct platform_driver p1022_ds_driver = { - .probe = p1022_ds_probe, - .remove = __devexit_p(p1022_ds_remove), - .driver = { - /* - * The name must match 'compatible' property in the device tree, - * in lowercase letters. - */ - .name = "snd-soc-p1022ds", - .owner = THIS_MODULE, - }, -}; - -/** - * p1022_ds_init: machine driver initialization. - * - * This function is called when this module is loaded. - */ -static int __init p1022_ds_init(void) -{ - struct device_node *guts_np; - struct resource res; - - /* Get the physical address of the global utilities registers */ - guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); - if (of_address_to_resource(guts_np, 0, &res)) { - pr_err("snd-soc-p1022ds: missing/invalid global utils node\n"); - of_node_put(guts_np); - return -EINVAL; - } - guts_phys = res.start; - of_node_put(guts_np); - - return platform_driver_register(&p1022_ds_driver); -} - -/** - * p1022_ds_exit: machine driver exit - * - * This function is called when this driver is unloaded. - */ -static void __exit p1022_ds_exit(void) -{ - platform_driver_unregister(&p1022_ds_driver); -} - -module_init(p1022_ds_init); -module_exit(p1022_ds_exit); - -MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("Freescale P1022 DS ALSA SoC machine driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/soc/fsl/pcm030-audio-fabric.c b/ANDROID_3.4.5/sound/soc/fsl/pcm030-audio-fabric.c deleted file mode 100644 index b3af55dc..00000000 --- a/ANDROID_3.4.5/sound/soc/fsl/pcm030-audio-fabric.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Phytec pcm030 driver for the PSC of the Freescale MPC52xx - * configured as AC97 interface - * - * Copyright 2008 Jon Smirl, Digispeaker - * Author: Jon Smirl - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "mpc5200_dma.h" -#include "mpc5200_psc_ac97.h" -#include "../codecs/wm9712.h" - -#define DRV_NAME "pcm030-audio-fabric" - -static struct snd_soc_dai_link pcm030_fabric_dai[] = { -{ - .name = "AC97", - .stream_name = "AC97 Analog", - .codec_dai_name = "wm9712-hifi", - .cpu_dai_name = "mpc5200-psc-ac97.0", - .platform_name = "mpc5200-pcm-audio", - .codec_name = "wm9712-codec", -}, -{ - .name = "AC97", - .stream_name = "AC97 IEC958", - .codec_dai_name = "wm9712-aux", - .cpu_dai_name = "mpc5200-psc-ac97.1", - .platform_name = "mpc5200-pcm-audio", - .codec_name = "wm9712-codec", -}, -}; - -static struct snd_soc_card card = { - .name = "pcm030", - .owner = THIS_MODULE, - .dai_link = pcm030_fabric_dai, - .num_links = ARRAY_SIZE(pcm030_fabric_dai), -}; - -static __init int pcm030_fabric_init(void) -{ - struct platform_device *pdev; - int rc; - - if (!of_machine_is_compatible("phytec,pcm030")) - return -ENODEV; - - pdev = platform_device_alloc("soc-audio", 1); - if (!pdev) { - pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); - return -ENODEV; - } - - platform_set_drvdata(pdev, &card); - - rc = platform_device_add(pdev); - if (rc) { - pr_err("pcm030_fabric_init: platform_device_add() failed\n"); - platform_device_put(pdev); - return -ENODEV; - } - return 0; -} - -module_init(pcm030_fabric_init); - - -MODULE_AUTHOR("Jon Smirl "); -MODULE_DESCRIPTION(DRV_NAME ": mpc5200 pcm030 fabric driver"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/soc/imx/Kconfig b/ANDROID_3.4.5/sound/soc/imx/Kconfig deleted file mode 100644 index 810acaa0..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/Kconfig +++ /dev/null @@ -1,79 +0,0 @@ -menuconfig SND_IMX_SOC - tristate "SoC Audio for Freescale i.MX CPUs" - depends on ARCH_MXC - help - Say Y or M if you want to add support for codecs attached to - the i.MX SSI interface. - - -if SND_IMX_SOC - -config SND_SOC_IMX_SSI - tristate - -config SND_SOC_IMX_PCM - tristate - -config SND_MXC_SOC_FIQ - tristate - select FIQ - select SND_SOC_IMX_PCM - -config SND_MXC_SOC_MX2 - select SND_SOC_DMAENGINE_PCM - tristate - select SND_SOC_IMX_PCM - -config SND_SOC_IMX_AUDMUX - tristate - -config SND_MXC_SOC_WM1133_EV1 - tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" - depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL - select SND_SOC_WM8350 - select SND_MXC_SOC_FIQ - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Enable support for audio on the i.MX31ADS with the WM1133-EV1 - PMIC board with WM8835x fitted. - -config SND_SOC_MX27VIS_AIC32X4 - tristate "SoC audio support for Visstrim M10 boards" - depends on MACH_IMX27_VISSTRIM_M10 && I2C - select SND_SOC_TLV320AIC32X4 - select SND_MXC_SOC_MX2 - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Say Y if you want to add support for SoC audio on Visstrim SM10 - board with TLV320AIC32X4 codec. - -config SND_SOC_PHYCORE_AC97 - tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" - depends on MACH_PCM043 || MACH_PCA100 - select SND_SOC_AC97_BUS - select SND_SOC_WM9712 - select SND_MXC_SOC_FIQ - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Say Y if you want to add support for SoC audio on Phytec phyCORE - and phyCARD boards in AC97 mode - -config SND_SOC_EUKREA_TLV320 - tristate "Eukrea TLV320" - depends on MACH_EUKREA_MBIMX27_BASEBOARD \ - || MACH_EUKREA_MBIMXSD25_BASEBOARD \ - || MACH_EUKREA_MBIMXSD35_BASEBOARD \ - || MACH_EUKREA_MBIMXSD51_BASEBOARD - depends on I2C - select SND_SOC_TLV320AIC23 - select SND_MXC_SOC_FIQ - select SND_SOC_IMX_AUDMUX - select SND_SOC_IMX_SSI - help - Enable I2S based access to the TLV320AIC23B codec attached - to the SSI interface - -endif # SND_IMX_SOC diff --git a/ANDROID_3.4.5/sound/soc/imx/Makefile b/ANDROID_3.4.5/sound/soc/imx/Makefile deleted file mode 100644 index f5db3e92..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# i.MX Platform Support -snd-soc-imx-ssi-objs := imx-ssi.o -snd-soc-imx-audmux-objs := imx-audmux.o - -obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o -obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o - -obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o -snd-soc-imx-pcm-y := imx-pcm.o -snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o -snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o - -# i.MX Machine Support -snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o -snd-soc-phycore-ac97-objs := phycore-ac97.o -snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o -snd-soc-wm1133-ev1-objs := wm1133-ev1.o - -obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o -obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o -obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o -obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o diff --git a/ANDROID_3.4.5/sound/soc/imx/eukrea-tlv320.c b/ANDROID_3.4.5/sound/soc/imx/eukrea-tlv320.c deleted file mode 100644 index 7d4475cf..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/eukrea-tlv320.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * eukrea-tlv320.c -- SoC audio for eukrea_cpuimxXX in I2S mode - * - * Copyright 2010 Eric Bénard, Eukréa Electromatique - * - * based on sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c - * which is Copyright 2009 Simtec Electronics - * and on sound/soc/imx/phycore-ac97.c which is - * Copyright 2009 Sascha Hauer, Pengutronix - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../codecs/tlv320aic23.h" -#include "imx-ssi.h" -#include "imx-audmux.h" - -#define CODEC_CLOCK 12000000 - -static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret) { - pr_err("%s: failed set cpu dai format\n", __func__); - return ret; - } - - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret) { - pr_err("%s: failed set codec dai format\n", __func__); - return ret; - } - - ret = snd_soc_dai_set_sysclk(codec_dai, 0, - CODEC_CLOCK, SND_SOC_CLOCK_OUT); - if (ret) { - pr_err("%s: failed setting codec sysclk\n", __func__); - return ret; - } - snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); - - ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, - SND_SOC_CLOCK_IN); - if (ret) { - pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops eukrea_tlv320_snd_ops = { - .hw_params = eukrea_tlv320_hw_params, -}; - -static struct snd_soc_dai_link eukrea_tlv320_dai = { - .name = "tlv320aic23", - .stream_name = "TLV320AIC23", - .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "imx-fiq-pcm-audio.0", - .codec_name = "tlv320aic23-codec.0-001a", - .cpu_dai_name = "imx-ssi.0", - .ops = &eukrea_tlv320_snd_ops, -}; - -static struct snd_soc_card eukrea_tlv320 = { - .name = "cpuimx-audio", - .owner = THIS_MODULE, - .dai_link = &eukrea_tlv320_dai, - .num_links = 1, -}; - -static struct platform_device *eukrea_tlv320_snd_device; - -static int __init eukrea_tlv320_init(void) -{ - int ret; - int int_port = 0, ext_port; - - if (machine_is_eukrea_cpuimx27()) { - imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - IMX_AUDMUX_V1_PCR_SYN | - IMX_AUDMUX_V1_PCR_TFSDIR | - IMX_AUDMUX_V1_PCR_TCLKDIR | - IMX_AUDMUX_V1_PCR_RFSDIR | - IMX_AUDMUX_V1_PCR_RCLKDIR | - IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | - IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) | - IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) - ); - imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4, - IMX_AUDMUX_V1_PCR_SYN | - IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) - ); - } else if (machine_is_eukrea_cpuimx25sd() || - machine_is_eukrea_cpuimx35sd() || - machine_is_eukrea_cpuimx51sd()) { - ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3; - imx_audmux_v2_configure_port(int_port, - IMX_AUDMUX_V2_PTCR_SYN | - IMX_AUDMUX_V2_PTCR_TFSDIR | - IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) | - IMX_AUDMUX_V2_PTCR_TCLKDIR | - IMX_AUDMUX_V2_PTCR_TCSEL(ext_port), - IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port) - ); - imx_audmux_v2_configure_port(ext_port, - IMX_AUDMUX_V2_PTCR_SYN, - IMX_AUDMUX_V2_PDCR_RXDSEL(int_port) - ); - } else { - /* return happy. We might run on a totally different machine */ - return 0; - } - - eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1); - if (!eukrea_tlv320_snd_device) - return -ENOMEM; - - platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320); - ret = platform_device_add(eukrea_tlv320_snd_device); - - if (ret) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - platform_device_put(eukrea_tlv320_snd_device); - } - - return ret; -} - -static void __exit eukrea_tlv320_exit(void) -{ - platform_device_unregister(eukrea_tlv320_snd_device); -} - -module_init(eukrea_tlv320_init); -module_exit(eukrea_tlv320_exit); - -MODULE_AUTHOR("Eric Bénard "); -MODULE_DESCRIPTION("CPUIMX ALSA SoC driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/imx/imx-audmux.c b/ANDROID_3.4.5/sound/soc/imx/imx-audmux.c deleted file mode 100644 index f2370035..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/imx-audmux.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright 2012 Freescale Semiconductor, Inc. - * Copyright 2012 Linaro Ltd. - * Copyright 2009 Pengutronix, Sascha Hauer - * - * Initial development of this code was funded by - * Phytec Messtechnik GmbH, http://www.phytec.de - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "imx-audmux.h" - -#define DRIVER_NAME "imx-audmux" - -static struct clk *audmux_clk; -static void __iomem *audmux_base; - -#define IMX_AUDMUX_V2_PTCR(x) ((x) * 8) -#define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4) - -#ifdef CONFIG_DEBUG_FS -static struct dentry *audmux_debugfs_root; - -/* There is an annoying discontinuity in the SSI numbering with regard - * to the Linux number of the devices */ -static const char *audmux_port_string(int port) -{ - switch (port) { - case MX31_AUDMUX_PORT1_SSI0: - return "imx-ssi.0"; - case MX31_AUDMUX_PORT2_SSI1: - return "imx-ssi.1"; - case MX31_AUDMUX_PORT3_SSI_PINS_3: - return "SSI3"; - case MX31_AUDMUX_PORT4_SSI_PINS_4: - return "SSI4"; - case MX31_AUDMUX_PORT5_SSI_PINS_5: - return "SSI5"; - case MX31_AUDMUX_PORT6_SSI_PINS_6: - return "SSI6"; - default: - return "UNKNOWN"; - } -} - -static ssize_t audmux_read_file(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - ssize_t ret; - char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - int port = (int)file->private_data; - u32 pdcr, ptcr; - - if (!buf) - return -ENOMEM; - - if (!audmux_base) - return -ENOSYS; - - if (audmux_clk) - clk_prepare_enable(audmux_clk); - - ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port)); - pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port)); - - if (audmux_clk) - clk_disable_unprepare(audmux_clk); - - ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n", - pdcr, ptcr); - - if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "TxFS output from %s, ", - audmux_port_string((ptcr >> 27) & 0x7)); - else - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "TxFS input, "); - - if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "TxClk output from %s", - audmux_port_string((ptcr >> 22) & 0x7)); - else - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "TxClk input"); - - ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n"); - - if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) { - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "Port is symmetric"); - } else { - if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "RxFS output from %s, ", - audmux_port_string((ptcr >> 17) & 0x7)); - else - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "RxFS input, "); - - if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "RxClk output from %s", - audmux_port_string((ptcr >> 12) & 0x7)); - else - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "RxClk input"); - } - - ret += snprintf(buf + ret, PAGE_SIZE - ret, - "\nData received from %s\n", - audmux_port_string((pdcr >> 13) & 0x7)); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); - - kfree(buf); - - return ret; -} - -static const struct file_operations audmux_debugfs_fops = { - .open = simple_open, - .read = audmux_read_file, - .llseek = default_llseek, -}; - -static void __init audmux_debugfs_init(void) -{ - int i; - char buf[20]; - - audmux_debugfs_root = debugfs_create_dir("audmux", NULL); - if (!audmux_debugfs_root) { - pr_warning("Failed to create AUDMUX debugfs root\n"); - return; - } - - for (i = 0; i < MX31_AUDMUX_PORT6_SSI_PINS_6 + 1; i++) { - snprintf(buf, sizeof(buf), "ssi%d", i); - if (!debugfs_create_file(buf, 0444, audmux_debugfs_root, - (void *)i, &audmux_debugfs_fops)) - pr_warning("Failed to create AUDMUX port %d debugfs file\n", - i); - } -} - -static void __devexit audmux_debugfs_remove(void) -{ - debugfs_remove_recursive(audmux_debugfs_root); -} -#else -static inline void audmux_debugfs_init(void) -{ -} - -static inline void audmux_debugfs_remove(void) -{ -} -#endif - -enum imx_audmux_type { - IMX21_AUDMUX, - IMX31_AUDMUX, -} audmux_type; - -static struct platform_device_id imx_audmux_ids[] = { - { - .name = "imx21-audmux", - .driver_data = IMX21_AUDMUX, - }, { - .name = "imx31-audmux", - .driver_data = IMX31_AUDMUX, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, imx_audmux_ids); - -static const struct of_device_id imx_audmux_dt_ids[] = { - { .compatible = "fsl,imx21-audmux", .data = &imx_audmux_ids[0], }, - { .compatible = "fsl,imx31-audmux", .data = &imx_audmux_ids[1], }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, imx_audmux_dt_ids); - -static const uint8_t port_mapping[] = { - 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c, -}; - -int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr) -{ - if (audmux_type != IMX21_AUDMUX) - return -EINVAL; - - if (!audmux_base) - return -ENOSYS; - - if (port >= ARRAY_SIZE(port_mapping)) - return -EINVAL; - - writel(pcr, audmux_base + port_mapping[port]); - - return 0; -} -EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port); - -int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, - unsigned int pdcr) -{ - if (audmux_type != IMX31_AUDMUX) - return -EINVAL; - - if (!audmux_base) - return -ENOSYS; - - if (audmux_clk) - clk_prepare_enable(audmux_clk); - - writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port)); - writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port)); - - if (audmux_clk) - clk_disable_unprepare(audmux_clk); - - return 0; -} -EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); - -static int __devinit imx_audmux_probe(struct platform_device *pdev) -{ - struct resource *res; - const struct of_device_id *of_id = - of_match_device(imx_audmux_dt_ids, &pdev->dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - audmux_base = devm_request_and_ioremap(&pdev->dev, res); - if (!audmux_base) - return -EADDRNOTAVAIL; - - audmux_clk = clk_get(&pdev->dev, "audmux"); - if (IS_ERR(audmux_clk)) { - dev_dbg(&pdev->dev, "cannot get clock: %ld\n", - PTR_ERR(audmux_clk)); - audmux_clk = NULL; - } - - if (of_id) - pdev->id_entry = of_id->data; - audmux_type = pdev->id_entry->driver_data; - if (audmux_type == IMX31_AUDMUX) - audmux_debugfs_init(); - - return 0; -} - -static int __devexit imx_audmux_remove(struct platform_device *pdev) -{ - if (audmux_type == IMX31_AUDMUX) - audmux_debugfs_remove(); - clk_put(audmux_clk); - - return 0; -} - -static struct platform_driver imx_audmux_driver = { - .probe = imx_audmux_probe, - .remove = __devexit_p(imx_audmux_remove), - .id_table = imx_audmux_ids, - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - .of_match_table = imx_audmux_dt_ids, - } -}; - -static int __init imx_audmux_init(void) -{ - return platform_driver_register(&imx_audmux_driver); -} -subsys_initcall(imx_audmux_init); - -static void __exit imx_audmux_exit(void) -{ - platform_driver_unregister(&imx_audmux_driver); -} -module_exit(imx_audmux_exit); - -MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver"); -MODULE_AUTHOR("Sascha Hauer "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/ANDROID_3.4.5/sound/soc/imx/imx-audmux.h b/ANDROID_3.4.5/sound/soc/imx/imx-audmux.h deleted file mode 100644 index 04ebbab8..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/imx-audmux.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __IMX_AUDMUX_H -#define __IMX_AUDMUX_H - -#define MX27_AUDMUX_HPCR1_SSI0 0 -#define MX27_AUDMUX_HPCR2_SSI1 1 -#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2 -#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3 -#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4 -#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5 - -#define MX31_AUDMUX_PORT1_SSI0 0 -#define MX31_AUDMUX_PORT2_SSI1 1 -#define MX31_AUDMUX_PORT3_SSI_PINS_3 2 -#define MX31_AUDMUX_PORT4_SSI_PINS_4 3 -#define MX31_AUDMUX_PORT5_SSI_PINS_5 4 -#define MX31_AUDMUX_PORT6_SSI_PINS_6 5 - -#define MX51_AUDMUX_PORT1_SSI0 0 -#define MX51_AUDMUX_PORT2_SSI1 1 -#define MX51_AUDMUX_PORT3 2 -#define MX51_AUDMUX_PORT4 3 -#define MX51_AUDMUX_PORT5 4 -#define MX51_AUDMUX_PORT6 5 -#define MX51_AUDMUX_PORT7 6 - -/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */ -#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff) -#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8) -#define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10) -#define IMX_AUDMUX_V1_PCR_SYN (1 << 12) -#define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13) -#define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20) -#define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24) -#define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25) -#define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26) -#define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30) -#define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31) - -/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */ -#define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31) -#define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27) -#define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26) -#define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22) -#define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21) -#define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17) -#define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16) -#define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12) -#define IMX_AUDMUX_V2_PTCR_SYN (1 << 11) - -#define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13) -#define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12) -#define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8) -#define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff) - -int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr); - -int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, - unsigned int pdcr); - -#endif /* __IMX_AUDMUX_H */ diff --git a/ANDROID_3.4.5/sound/soc/imx/imx-pcm-dma-mx2.c b/ANDROID_3.4.5/sound/soc/imx/imx-pcm-dma-mx2.c deleted file mode 100644 index 6b818de2..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/imx-pcm-dma-mx2.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * imx-pcm-dma-mx2.c -- ALSA Soc Audio Layer - * - * Copyright 2009 Sascha Hauer - * - * This code is based on code copyrighted by Freescale, - * Liam Girdwood, Javier Martin and probably others. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "imx-pcm.h" - -static bool filter(struct dma_chan *chan, void *param) -{ - if (!imx_dma_is_general_purpose(chan)) - return false; - - chan->private = param; - - return true; -} - -static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); - struct imx_pcm_dma_params *dma_params; - struct dma_slave_config slave_config; - int ret; - - dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config); - if (ret) - return ret; - - slave_config.device_fc = false; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - slave_config.dst_addr = dma_params->dma_addr; - slave_config.dst_maxburst = dma_params->burstsize; - } else { - slave_config.src_addr = dma_params->dma_addr; - slave_config.src_maxburst = dma_params->burstsize; - } - - ret = dmaengine_slave_config(chan, &slave_config); - if (ret) - return ret; - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - return 0; -} - -static struct snd_pcm_hardware snd_imx_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rate_min = 8000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, - .period_bytes_min = 128, - .period_bytes_max = 65535, /* Limited by SDMA engine */ - .periods_min = 2, - .periods_max = 255, - .fifo_size = 0, -}; - -static int snd_imx_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct imx_pcm_dma_params *dma_params; - struct imx_dma_data *dma_data; - int ret; - - snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); - - dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); - dma_data->peripheral_type = IMX_DMATYPE_SSI; - dma_data->priority = DMA_PRIO_HIGH; - dma_data->dma_request = dma_params->dma; - - ret = snd_dmaengine_pcm_open(substream, filter, dma_data); - if (ret) { - kfree(dma_data); - return 0; - } - - snd_dmaengine_pcm_set_data(substream, dma_data); - - return 0; -} - -static int snd_imx_close(struct snd_pcm_substream *substream) -{ - struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); - - snd_dmaengine_pcm_close(substream); - kfree(dma_data); - - return 0; -} - -static struct snd_pcm_ops imx_pcm_ops = { - .open = snd_imx_open, - .close = snd_imx_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_imx_pcm_hw_params, - .trigger = snd_dmaengine_pcm_trigger, - .pointer = snd_dmaengine_pcm_pointer, - .mmap = snd_imx_pcm_mmap, -}; - -static struct snd_soc_platform_driver imx_soc_platform_mx2 = { - .ops = &imx_pcm_ops, - .pcm_new = imx_pcm_new, - .pcm_free = imx_pcm_free, -}; - -static int __devinit imx_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2); -} - -static int __devexit imx_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver imx_pcm_driver = { - .driver = { - .name = "imx-pcm-audio", - .owner = THIS_MODULE, - }, - .probe = imx_soc_platform_probe, - .remove = __devexit_p(imx_soc_platform_remove), -}; - -module_platform_driver(imx_pcm_driver); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-pcm-audio"); diff --git a/ANDROID_3.4.5/sound/soc/imx/imx-pcm-fiq.c b/ANDROID_3.4.5/sound/soc/imx/imx-pcm-fiq.c deleted file mode 100644 index 456b7d72..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/imx-pcm-fiq.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * imx-pcm-fiq.c -- ALSA Soc Audio Layer - * - * Copyright 2009 Sascha Hauer - * - * This code is based on code copyrighted by Freescale, - * Liam Girdwood, Javier Martin and probably others. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include "imx-ssi.h" - -struct imx_pcm_runtime_data { - int period; - int periods; - unsigned long offset; - unsigned long last_offset; - unsigned long size; - struct hrtimer hrt; - int poll_time_ns; - struct snd_pcm_substream *substream; - atomic_t running; -}; - -static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) -{ - struct imx_pcm_runtime_data *iprtd = - container_of(hrt, struct imx_pcm_runtime_data, hrt); - struct snd_pcm_substream *substream = iprtd->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - struct pt_regs regs; - unsigned long delta; - - if (!atomic_read(&iprtd->running)) - return HRTIMER_NORESTART; - - get_fiq_regs(®s); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - iprtd->offset = regs.ARM_r8 & 0xffff; - else - iprtd->offset = regs.ARM_r9 & 0xffff; - - /* How much data have we transferred since the last period report? */ - if (iprtd->offset >= iprtd->last_offset) - delta = iprtd->offset - iprtd->last_offset; - else - delta = runtime->buffer_size + iprtd->offset - - iprtd->last_offset; - - /* If we've transferred at least a period then report it and - * reset our poll time */ - if (delta >= iprtd->period) { - snd_pcm_period_elapsed(substream); - iprtd->last_offset = iprtd->offset; - } - - hrtimer_forward_now(hrt, ns_to_ktime(iprtd->poll_time_ns)); - - return HRTIMER_RESTART; -} - -static struct fiq_handler fh = { - .name = DRV_NAME, -}; - -static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct imx_pcm_runtime_data *iprtd = runtime->private_data; - - iprtd->size = params_buffer_bytes(params); - iprtd->periods = params_periods(params); - iprtd->period = params_period_bytes(params) ; - iprtd->offset = 0; - iprtd->last_offset = 0; - iprtd->poll_time_ns = 1000000000 / params_rate(params) * - params_period_size(params); - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - return 0; -} - -static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct imx_pcm_runtime_data *iprtd = runtime->private_data; - struct pt_regs regs; - - get_fiq_regs(®s); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - regs.ARM_r8 = (iprtd->period * iprtd->periods - 1) << 16; - else - regs.ARM_r9 = (iprtd->period * iprtd->periods - 1) << 16; - - set_fiq_regs(®s); - - return 0; -} - -static int fiq_enable; -static int imx_pcm_fiq; - -static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct imx_pcm_runtime_data *iprtd = runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - atomic_set(&iprtd->running, 1); - hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns), - HRTIMER_MODE_REL); - if (++fiq_enable == 1) - enable_fiq(imx_pcm_fiq); - - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - atomic_set(&iprtd->running, 0); - - if (--fiq_enable == 0) - disable_fiq(imx_pcm_fiq); - - break; - default: - return -EINVAL; - } - - return 0; -} - -static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct imx_pcm_runtime_data *iprtd = runtime->private_data; - - return bytes_to_frames(substream->runtime, iprtd->offset); -} - -static struct snd_pcm_hardware snd_imx_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rate_min = 8000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, - .period_bytes_min = 128, - .period_bytes_max = 16 * 1024, - .periods_min = 4, - .periods_max = 255, - .fifo_size = 0, -}; - -static int snd_imx_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct imx_pcm_runtime_data *iprtd; - int ret; - - iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); - if (iprtd == NULL) - return -ENOMEM; - runtime->private_data = iprtd; - - iprtd->substream = substream; - - atomic_set(&iprtd->running, 0); - hrtimer_init(&iprtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - iprtd->hrt.function = snd_hrtimer_callback; - - ret = snd_pcm_hw_constraint_integer(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) { - kfree(iprtd); - return ret; - } - - snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); - return 0; -} - -static int snd_imx_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct imx_pcm_runtime_data *iprtd = runtime->private_data; - - hrtimer_cancel(&iprtd->hrt); - - kfree(iprtd); - - return 0; -} - -static struct snd_pcm_ops imx_pcm_ops = { - .open = snd_imx_open, - .close = snd_imx_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_imx_pcm_hw_params, - .prepare = snd_imx_pcm_prepare, - .trigger = snd_imx_pcm_trigger, - .pointer = snd_imx_pcm_pointer, - .mmap = snd_imx_pcm_mmap, -}; - -static int ssi_irq = 0; - -static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_pcm *pcm = rtd->pcm; - struct snd_pcm_substream *substream; - int ret; - - ret = imx_pcm_new(rtd); - if (ret) - return ret; - - substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - if (substream) { - struct snd_dma_buffer *buf = &substream->dma_buffer; - - imx_ssi_fiq_tx_buffer = (unsigned long)buf->area; - } - - substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - if (substream) { - struct snd_dma_buffer *buf = &substream->dma_buffer; - - imx_ssi_fiq_rx_buffer = (unsigned long)buf->area; - } - - set_fiq_handler(&imx_ssi_fiq_start, - &imx_ssi_fiq_end - &imx_ssi_fiq_start); - - return 0; -} - -static void imx_pcm_fiq_free(struct snd_pcm *pcm) -{ - mxc_set_irq_fiq(ssi_irq, 0); - release_fiq(&fh); - imx_pcm_free(pcm); -} - -static struct snd_soc_platform_driver imx_soc_platform_fiq = { - .ops = &imx_pcm_ops, - .pcm_new = imx_pcm_fiq_new, - .pcm_free = imx_pcm_fiq_free, -}; - -static int __devinit imx_soc_platform_probe(struct platform_device *pdev) -{ - struct imx_ssi *ssi = platform_get_drvdata(pdev); - int ret; - - ret = claim_fiq(&fh); - if (ret) { - dev_err(&pdev->dev, "failed to claim fiq: %d", ret); - return ret; - } - - mxc_set_irq_fiq(ssi->irq, 1); - ssi_irq = ssi->irq; - - imx_pcm_fiq = ssi->irq; - - imx_ssi_fiq_base = (unsigned long)ssi->base; - - ssi->dma_params_tx.burstsize = 4; - ssi->dma_params_rx.burstsize = 6; - - ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq); - if (ret) - goto failed_register; - - return 0; - -failed_register: - mxc_set_irq_fiq(ssi_irq, 0); - release_fiq(&fh); - - return ret; -} - -static int __devexit imx_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver imx_pcm_driver = { - .driver = { - .name = "imx-fiq-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = imx_soc_platform_probe, - .remove = __devexit_p(imx_soc_platform_remove), -}; - -module_platform_driver(imx_pcm_driver); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/imx/imx-pcm.c b/ANDROID_3.4.5/sound/soc/imx/imx-pcm.c deleted file mode 100644 index 93dc360b..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/imx-pcm.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2009 Sascha Hauer - * - * This code is based on code copyrighted by Freescale, - * Liam Girdwood, Javier Martin and probably others. - * - * 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. - */ - -#include -#include -#include -#include -#include "imx-pcm.h" - -int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); - - pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); - return ret; -} -EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); - -static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = IMX_SSI_DMABUF_SIZE; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - - return 0; -} - -static u64 imx_pcm_dmamask = DMA_BIT_MASK(32); - -int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &imx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = imx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = imx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - -out: - return ret; -} -EXPORT_SYMBOL_GPL(imx_pcm_new); - -void imx_pcm_free(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} -EXPORT_SYMBOL_GPL(imx_pcm_free); diff --git a/ANDROID_3.4.5/sound/soc/imx/imx-pcm.h b/ANDROID_3.4.5/sound/soc/imx/imx-pcm.h deleted file mode 100644 index b5f5c3ac..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/imx-pcm.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2009 Sascha Hauer - * - * This code is based on code copyrighted by Freescale, - * Liam Girdwood, Javier Martin and probably others. - * - * 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. - */ - -#ifndef _IMX_PCM_H -#define _IMX_PCM_H - -/* - * Do not change this as the FIQ handler depends on this size - */ -#define IMX_SSI_DMABUF_SIZE (64 * 1024) - -struct imx_pcm_dma_params { - int dma; - unsigned long dma_addr; - int burstsize; -}; - -int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma); -int imx_pcm_new(struct snd_soc_pcm_runtime *rtd); -void imx_pcm_free(struct snd_pcm *pcm); - -#endif /* _IMX_PCM_H */ diff --git a/ANDROID_3.4.5/sound/soc/imx/imx-ssi.c b/ANDROID_3.4.5/sound/soc/imx/imx-ssi.c deleted file mode 100644 index 4f81ed45..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/imx-ssi.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - * imx-ssi.c -- ALSA Soc Audio Layer - * - * Copyright 2009 Sascha Hauer - * - * This code is based on code copyrighted by Freescale, - * Liam Girdwood, Javier Martin and probably others. - * - * 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. - * - * - * The i.MX SSI core has some nasty limitations in AC97 mode. While most - * sane processor vendors have a FIFO per AC97 slot, the i.MX has only - * one FIFO which combines all valid receive slots. We cannot even select - * which slots we want to receive. The WM9712 with which this driver - * was developed with always sends GPIO status data in slot 12 which - * we receive in our (PCM-) data stream. The only chance we have is to - * manually skip this data in the FIQ handler. With sampling rates different - * from 48000Hz not every frame has valid receive data, so the ratio - * between pcm data and GPIO status data changes. Our FIQ handler is not - * able to handle this, hence this driver only works with 48000Hz sampling - * rate. - * Reading and writing AC97 registers is another challenge. The core - * provides us status bits when the read register is updated with *another* - * value. When we read the same register two times (and the register still - * contains the same value) these status bits are not set. We work - * around this by not polling these bits but only wait a fixed delay. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "imx-ssi.h" - -#define SSI_SACNT_DEFAULT (SSI_SACNT_AC97EN | SSI_SACNT_FV) - -/* - * SSI Network Mode or TDM slots configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, - unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 sccr; - - sccr = readl(ssi->base + SSI_STCCR); - sccr &= ~SSI_STCCR_DC_MASK; - sccr |= SSI_STCCR_DC(slots - 1); - writel(sccr, ssi->base + SSI_STCCR); - - sccr = readl(ssi->base + SSI_SRCCR); - sccr &= ~SSI_STCCR_DC_MASK; - sccr |= SSI_STCCR_DC(slots - 1); - writel(sccr, ssi->base + SSI_SRCCR); - - writel(tx_mask, ssi->base + SSI_STMSK); - writel(rx_mask, ssi->base + SSI_SRMSK); - - return 0; -} - -/* - * SSI DAI format configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 strcr = 0, scr; - - scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); - - /* DAI mode */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - /* data on rising edge of bclk, frame low 1clk before data */ - strcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0; - scr |= SSI_SCR_NET; - if (ssi->flags & IMX_SSI_USE_I2S_SLAVE) { - scr &= ~SSI_I2S_MODE_MASK; - scr |= SSI_SCR_I2S_MODE_SLAVE; - } - break; - case SND_SOC_DAIFMT_LEFT_J: - /* data on rising edge of bclk, frame high with data */ - strcr |= SSI_STCR_TXBIT0; - break; - case SND_SOC_DAIFMT_DSP_B: - /* data on rising edge of bclk, frame high with data */ - strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0; - break; - case SND_SOC_DAIFMT_DSP_A: - /* data on rising edge of bclk, frame high 1clk before data */ - strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0 | SSI_STCR_TEFS; - break; - } - - /* DAI clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - strcr |= SSI_STCR_TFSI; - strcr &= ~SSI_STCR_TSCKP; - break; - case SND_SOC_DAIFMT_IB_NF: - strcr &= ~(SSI_STCR_TSCKP | SSI_STCR_TFSI); - break; - case SND_SOC_DAIFMT_NB_IF: - strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP; - break; - case SND_SOC_DAIFMT_NB_NF: - strcr &= ~SSI_STCR_TFSI; - strcr |= SSI_STCR_TSCKP; - break; - } - - /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - default: - /* Master mode not implemented, needs handling of clocks. */ - return -EINVAL; - } - - strcr |= SSI_STCR_TFEN0; - - if (ssi->flags & IMX_SSI_NET) - scr |= SSI_SCR_NET; - if (ssi->flags & IMX_SSI_SYN) - scr |= SSI_SCR_SYN; - - writel(strcr, ssi->base + SSI_STCR); - writel(strcr, ssi->base + SSI_SRCR); - writel(scr, ssi->base + SSI_SCR); - - return 0; -} - -/* - * SSI system clock configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 scr; - - scr = readl(ssi->base + SSI_SCR); - - switch (clk_id) { - case IMX_SSP_SYS_CLK: - if (dir == SND_SOC_CLOCK_OUT) - scr |= SSI_SCR_SYS_CLK_EN; - else - scr &= ~SSI_SCR_SYS_CLK_EN; - break; - default: - return -EINVAL; - } - - writel(scr, ssi->base + SSI_SCR); - - return 0; -} - -/* - * SSI Clock dividers - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 stccr, srccr; - - stccr = readl(ssi->base + SSI_STCCR); - srccr = readl(ssi->base + SSI_SRCCR); - - switch (div_id) { - case IMX_SSI_TX_DIV_2: - stccr &= ~SSI_STCCR_DIV2; - stccr |= div; - break; - case IMX_SSI_TX_DIV_PSR: - stccr &= ~SSI_STCCR_PSR; - stccr |= div; - break; - case IMX_SSI_TX_DIV_PM: - stccr &= ~0xff; - stccr |= SSI_STCCR_PM(div); - break; - case IMX_SSI_RX_DIV_2: - stccr &= ~SSI_STCCR_DIV2; - stccr |= div; - break; - case IMX_SSI_RX_DIV_PSR: - stccr &= ~SSI_STCCR_PSR; - stccr |= div; - break; - case IMX_SSI_RX_DIV_PM: - stccr &= ~0xff; - stccr |= SSI_STCCR_PM(div); - break; - default: - return -EINVAL; - } - - writel(stccr, ssi->base + SSI_STCCR); - writel(srccr, ssi->base + SSI_SRCCR); - - return 0; -} - -static int imx_ssi_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - struct imx_pcm_dma_params *dma_data; - - /* Tx/Rx config */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dma_data = &ssi->dma_params_tx; - else - dma_data = &ssi->dma_params_rx; - - snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); - - return 0; -} - -/* - * Should only be called when port is inactive (i.e. SSIEN = 0), - * although can be called multiple times by upper layers. - */ -static int imx_ssi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai); - u32 reg, sccr; - - /* Tx/Rx config */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - reg = SSI_STCCR; - else - reg = SSI_SRCCR; - - if (ssi->flags & IMX_SSI_SYN) - reg = SSI_STCCR; - - sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK; - - /* DAI data (word) size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - sccr |= SSI_SRCCR_WL(16); - break; - case SNDRV_PCM_FORMAT_S20_3LE: - sccr |= SSI_SRCCR_WL(20); - break; - case SNDRV_PCM_FORMAT_S24_LE: - sccr |= SSI_SRCCR_WL(24); - break; - } - - writel(sccr, ssi->base + reg); - - return 0; -} - -static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai); - unsigned int sier_bits, sier; - unsigned int scr; - - scr = readl(ssi->base + SSI_SCR); - sier = readl(ssi->base + SSI_SIER); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (ssi->flags & IMX_SSI_DMA) - sier_bits = SSI_SIER_TDMAE; - else - sier_bits = SSI_SIER_TIE | SSI_SIER_TFE0_EN; - } else { - if (ssi->flags & IMX_SSI_DMA) - sier_bits = SSI_SIER_RDMAE; - else - sier_bits = SSI_SIER_RIE | SSI_SIER_RFF0_EN; - } - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - scr |= SSI_SCR_TE; - else - scr |= SSI_SCR_RE; - sier |= sier_bits; - - if (++ssi->enabled == 1) - scr |= SSI_SCR_SSIEN; - - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - scr &= ~SSI_SCR_TE; - else - scr &= ~SSI_SCR_RE; - sier &= ~sier_bits; - - if (--ssi->enabled == 0) - scr &= ~SSI_SCR_SSIEN; - - break; - default: - return -EINVAL; - } - - if (!(ssi->flags & IMX_SSI_USE_AC97)) - /* rx/tx are always enabled to access ac97 registers */ - writel(scr, ssi->base + SSI_SCR); - - writel(sier, ssi->base + SSI_SIER); - - return 0; -} - -static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { - .startup = imx_ssi_startup, - .hw_params = imx_ssi_hw_params, - .set_fmt = imx_ssi_set_dai_fmt, - .set_clkdiv = imx_ssi_set_dai_clkdiv, - .set_sysclk = imx_ssi_set_dai_sysclk, - .set_tdm_slot = imx_ssi_set_dai_tdm_slot, - .trigger = imx_ssi_trigger, -}; - -static int imx_ssi_dai_probe(struct snd_soc_dai *dai) -{ - struct imx_ssi *ssi = dev_get_drvdata(dai->dev); - uint32_t val; - - snd_soc_dai_set_drvdata(dai, ssi); - - val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | - SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); - writel(val, ssi->base + SSI_SFCSR); - - return 0; -} - -static struct snd_soc_dai_driver imx_ssi_dai = { - .probe = imx_ssi_dai_probe, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &imx_ssi_pcm_dai_ops, -}; - -static struct snd_soc_dai_driver imx_ac97_dai = { - .probe = imx_ssi_dai_probe, - .ac97_control = 1, - .playback = { - .stream_name = "AC97 Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "AC97 Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &imx_ssi_pcm_dai_ops, -}; - -static void setup_channel_to_ac97(struct imx_ssi *imx_ssi) -{ - void __iomem *base = imx_ssi->base; - - writel(0x0, base + SSI_SCR); - writel(0x0, base + SSI_STCR); - writel(0x0, base + SSI_SRCR); - - writel(SSI_SCR_SYN | SSI_SCR_NET, base + SSI_SCR); - - writel(SSI_SFCSR_RFWM0(8) | - SSI_SFCSR_TFWM0(8) | - SSI_SFCSR_RFWM1(8) | - SSI_SFCSR_TFWM1(8), base + SSI_SFCSR); - - writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_STCCR); - writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_SRCCR); - - writel(SSI_SCR_SYN | SSI_SCR_NET | SSI_SCR_SSIEN, base + SSI_SCR); - writel(SSI_SOR_WAIT(3), base + SSI_SOR); - - writel(SSI_SCR_SYN | SSI_SCR_NET | SSI_SCR_SSIEN | - SSI_SCR_TE | SSI_SCR_RE, - base + SSI_SCR); - - writel(SSI_SACNT_DEFAULT, base + SSI_SACNT); - writel(0xff, base + SSI_SACCDIS); - writel(0x300, base + SSI_SACCEN); -} - -static struct imx_ssi *ac97_ssi; - -static void imx_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct imx_ssi *imx_ssi = ac97_ssi; - void __iomem *base = imx_ssi->base; - unsigned int lreg; - unsigned int lval; - - if (reg > 0x7f) - return; - - pr_debug("%s: 0x%02x 0x%04x\n", __func__, reg, val); - - lreg = reg << 12; - writel(lreg, base + SSI_SACADD); - - lval = val << 4; - writel(lval , base + SSI_SACDAT); - - writel(SSI_SACNT_DEFAULT | SSI_SACNT_WR, base + SSI_SACNT); - udelay(100); -} - -static unsigned short imx_ssi_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct imx_ssi *imx_ssi = ac97_ssi; - void __iomem *base = imx_ssi->base; - - unsigned short val = -1; - unsigned int lreg; - - lreg = (reg & 0x7f) << 12 ; - writel(lreg, base + SSI_SACADD); - writel(SSI_SACNT_DEFAULT | SSI_SACNT_RD, base + SSI_SACNT); - - udelay(100); - - val = (readl(base + SSI_SACDAT) >> 4) & 0xffff; - - pr_debug("%s: 0x%02x 0x%04x\n", __func__, reg, val); - - return val; -} - -static void imx_ssi_ac97_reset(struct snd_ac97 *ac97) -{ - struct imx_ssi *imx_ssi = ac97_ssi; - - if (imx_ssi->ac97_reset) - imx_ssi->ac97_reset(ac97); -} - -static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct imx_ssi *imx_ssi = ac97_ssi; - - if (imx_ssi->ac97_warm_reset) - imx_ssi->ac97_warm_reset(ac97); -} - -struct snd_ac97_bus_ops soc_ac97_ops = { - .read = imx_ssi_ac97_read, - .write = imx_ssi_ac97_write, - .reset = imx_ssi_ac97_reset, - .warm_reset = imx_ssi_ac97_warm_reset -}; -EXPORT_SYMBOL_GPL(soc_ac97_ops); - -static int imx_ssi_probe(struct platform_device *pdev) -{ - struct resource *res; - struct imx_ssi *ssi; - struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; - int ret = 0; - struct snd_soc_dai_driver *dai; - - ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); - if (!ssi) - return -ENOMEM; - dev_set_drvdata(&pdev->dev, ssi); - - if (pdata) { - ssi->ac97_reset = pdata->ac97_reset; - ssi->ac97_warm_reset = pdata->ac97_warm_reset; - ssi->flags = pdata->flags; - } - - ssi->irq = platform_get_irq(pdev, 0); - - ssi->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(ssi->clk)) { - ret = PTR_ERR(ssi->clk); - dev_err(&pdev->dev, "Cannot get the clock: %d\n", - ret); - goto failed_clk; - } - clk_enable(ssi->clk); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - goto failed_get_resource; - } - - if (!request_mem_region(res->start, resource_size(res), DRV_NAME)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - ret = -EBUSY; - goto failed_get_resource; - } - - ssi->base = ioremap(res->start, resource_size(res)); - if (!ssi->base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENODEV; - goto failed_ioremap; - } - - if (ssi->flags & IMX_SSI_USE_AC97) { - if (ac97_ssi) { - ret = -EBUSY; - goto failed_ac97; - } - ac97_ssi = ssi; - setup_channel_to_ac97(ssi); - dai = &imx_ac97_dai; - } else - dai = &imx_ssi_dai; - - writel(0x0, ssi->base + SSI_SIER); - - ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; - ssi->dma_params_tx.dma_addr = res->start + SSI_STX0; - - ssi->dma_params_tx.burstsize = 6; - ssi->dma_params_rx.burstsize = 4; - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); - if (res) - ssi->dma_params_tx.dma = res->start; - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx0"); - if (res) - ssi->dma_params_rx.dma = res->start; - - platform_set_drvdata(pdev, ssi); - - ret = snd_soc_register_dai(&pdev->dev, dai); - if (ret) { - dev_err(&pdev->dev, "register DAI failed\n"); - goto failed_register; - } - - ssi->soc_platform_pdev_fiq = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); - if (!ssi->soc_platform_pdev_fiq) { - ret = -ENOMEM; - goto failed_pdev_fiq_alloc; - } - - platform_set_drvdata(ssi->soc_platform_pdev_fiq, ssi); - ret = platform_device_add(ssi->soc_platform_pdev_fiq); - if (ret) { - dev_err(&pdev->dev, "failed to add platform device\n"); - goto failed_pdev_fiq_add; - } - - ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", pdev->id); - if (!ssi->soc_platform_pdev) { - ret = -ENOMEM; - goto failed_pdev_alloc; - } - - platform_set_drvdata(ssi->soc_platform_pdev, ssi); - ret = platform_device_add(ssi->soc_platform_pdev); - if (ret) { - dev_err(&pdev->dev, "failed to add platform device\n"); - goto failed_pdev_add; - } - - return 0; - -failed_pdev_add: - platform_device_put(ssi->soc_platform_pdev); -failed_pdev_alloc: - platform_device_del(ssi->soc_platform_pdev_fiq); -failed_pdev_fiq_add: - platform_device_put(ssi->soc_platform_pdev_fiq); -failed_pdev_fiq_alloc: - snd_soc_unregister_dai(&pdev->dev); -failed_register: -failed_ac97: - iounmap(ssi->base); -failed_ioremap: - release_mem_region(res->start, resource_size(res)); -failed_get_resource: - clk_disable(ssi->clk); - clk_put(ssi->clk); -failed_clk: - kfree(ssi); - - return ret; -} - -static int __devexit imx_ssi_remove(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct imx_ssi *ssi = platform_get_drvdata(pdev); - - platform_device_unregister(ssi->soc_platform_pdev); - platform_device_unregister(ssi->soc_platform_pdev_fiq); - - snd_soc_unregister_dai(&pdev->dev); - - if (ssi->flags & IMX_SSI_USE_AC97) - ac97_ssi = NULL; - - iounmap(ssi->base); - release_mem_region(res->start, resource_size(res)); - clk_disable(ssi->clk); - clk_put(ssi->clk); - kfree(ssi); - - return 0; -} - -static struct platform_driver imx_ssi_driver = { - .probe = imx_ssi_probe, - .remove = __devexit_p(imx_ssi_remove), - - .driver = { - .name = "imx-ssi", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(imx_ssi_driver); - -/* Module information */ -MODULE_AUTHOR("Sascha Hauer, "); -MODULE_DESCRIPTION("i.MX I2S/ac97 SoC Interface"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-ssi"); diff --git a/ANDROID_3.4.5/sound/soc/imx/imx-ssi.h b/ANDROID_3.4.5/sound/soc/imx/imx-ssi.h deleted file mode 100644 index 5744e86c..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/imx-ssi.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _IMX_SSI_H -#define _IMX_SSI_H - -#define SSI_STX0 0x00 -#define SSI_STX1 0x04 -#define SSI_SRX0 0x08 -#define SSI_SRX1 0x0c - -#define SSI_SCR 0x10 -#define SSI_SCR_CLK_IST (1 << 9) -#define SSI_SCR_CLK_IST_SHIFT 9 -#define SSI_SCR_TCH_EN (1 << 8) -#define SSI_SCR_SYS_CLK_EN (1 << 7) -#define SSI_SCR_I2S_MODE_NORM (0 << 5) -#define SSI_SCR_I2S_MODE_MSTR (1 << 5) -#define SSI_SCR_I2S_MODE_SLAVE (2 << 5) -#define SSI_I2S_MODE_MASK (3 << 5) -#define SSI_SCR_SYN (1 << 4) -#define SSI_SCR_NET (1 << 3) -#define SSI_SCR_RE (1 << 2) -#define SSI_SCR_TE (1 << 1) -#define SSI_SCR_SSIEN (1 << 0) - -#define SSI_SISR 0x14 -#define SSI_SISR_MASK ((1 << 19) - 1) -#define SSI_SISR_CMDAU (1 << 18) -#define SSI_SISR_CMDDU (1 << 17) -#define SSI_SISR_RXT (1 << 16) -#define SSI_SISR_RDR1 (1 << 15) -#define SSI_SISR_RDR0 (1 << 14) -#define SSI_SISR_TDE1 (1 << 13) -#define SSI_SISR_TDE0 (1 << 12) -#define SSI_SISR_ROE1 (1 << 11) -#define SSI_SISR_ROE0 (1 << 10) -#define SSI_SISR_TUE1 (1 << 9) -#define SSI_SISR_TUE0 (1 << 8) -#define SSI_SISR_TFS (1 << 7) -#define SSI_SISR_RFS (1 << 6) -#define SSI_SISR_TLS (1 << 5) -#define SSI_SISR_RLS (1 << 4) -#define SSI_SISR_RFF1 (1 << 3) -#define SSI_SISR_RFF0 (1 << 2) -#define SSI_SISR_TFE1 (1 << 1) -#define SSI_SISR_TFE0 (1 << 0) - -#define SSI_SIER 0x18 -#define SSI_SIER_RDMAE (1 << 22) -#define SSI_SIER_RIE (1 << 21) -#define SSI_SIER_TDMAE (1 << 20) -#define SSI_SIER_TIE (1 << 19) -#define SSI_SIER_CMDAU_EN (1 << 18) -#define SSI_SIER_CMDDU_EN (1 << 17) -#define SSI_SIER_RXT_EN (1 << 16) -#define SSI_SIER_RDR1_EN (1 << 15) -#define SSI_SIER_RDR0_EN (1 << 14) -#define SSI_SIER_TDE1_EN (1 << 13) -#define SSI_SIER_TDE0_EN (1 << 12) -#define SSI_SIER_ROE1_EN (1 << 11) -#define SSI_SIER_ROE0_EN (1 << 10) -#define SSI_SIER_TUE1_EN (1 << 9) -#define SSI_SIER_TUE0_EN (1 << 8) -#define SSI_SIER_TFS_EN (1 << 7) -#define SSI_SIER_RFS_EN (1 << 6) -#define SSI_SIER_TLS_EN (1 << 5) -#define SSI_SIER_RLS_EN (1 << 4) -#define SSI_SIER_RFF1_EN (1 << 3) -#define SSI_SIER_RFF0_EN (1 << 2) -#define SSI_SIER_TFE1_EN (1 << 1) -#define SSI_SIER_TFE0_EN (1 << 0) - -#define SSI_STCR 0x1c -#define SSI_STCR_TXBIT0 (1 << 9) -#define SSI_STCR_TFEN1 (1 << 8) -#define SSI_STCR_TFEN0 (1 << 7) -#define SSI_FIFO_ENABLE_0_SHIFT 7 -#define SSI_STCR_TFDIR (1 << 6) -#define SSI_STCR_TXDIR (1 << 5) -#define SSI_STCR_TSHFD (1 << 4) -#define SSI_STCR_TSCKP (1 << 3) -#define SSI_STCR_TFSI (1 << 2) -#define SSI_STCR_TFSL (1 << 1) -#define SSI_STCR_TEFS (1 << 0) - -#define SSI_SRCR 0x20 -#define SSI_SRCR_RXBIT0 (1 << 9) -#define SSI_SRCR_RFEN1 (1 << 8) -#define SSI_SRCR_RFEN0 (1 << 7) -#define SSI_FIFO_ENABLE_0_SHIFT 7 -#define SSI_SRCR_RFDIR (1 << 6) -#define SSI_SRCR_RXDIR (1 << 5) -#define SSI_SRCR_RSHFD (1 << 4) -#define SSI_SRCR_RSCKP (1 << 3) -#define SSI_SRCR_RFSI (1 << 2) -#define SSI_SRCR_RFSL (1 << 1) -#define SSI_SRCR_REFS (1 << 0) - -#define SSI_SRCCR 0x28 -#define SSI_SRCCR_DIV2 (1 << 18) -#define SSI_SRCCR_PSR (1 << 17) -#define SSI_SRCCR_WL(x) ((((x) - 2) >> 1) << 13) -#define SSI_SRCCR_DC(x) (((x) & 0x1f) << 8) -#define SSI_SRCCR_PM(x) (((x) & 0xff) << 0) -#define SSI_SRCCR_WL_MASK (0xf << 13) -#define SSI_SRCCR_DC_MASK (0x1f << 8) -#define SSI_SRCCR_PM_MASK (0xff << 0) - -#define SSI_STCCR 0x24 -#define SSI_STCCR_DIV2 (1 << 18) -#define SSI_STCCR_PSR (1 << 17) -#define SSI_STCCR_WL(x) ((((x) - 2) >> 1) << 13) -#define SSI_STCCR_DC(x) (((x) & 0x1f) << 8) -#define SSI_STCCR_PM(x) (((x) & 0xff) << 0) -#define SSI_STCCR_WL_MASK (0xf << 13) -#define SSI_STCCR_DC_MASK (0x1f << 8) -#define SSI_STCCR_PM_MASK (0xff << 0) - -#define SSI_SFCSR 0x2c -#define SSI_SFCSR_RFCNT1(x) (((x) & 0xf) << 28) -#define SSI_RX_FIFO_1_COUNT_SHIFT 28 -#define SSI_SFCSR_TFCNT1(x) (((x) & 0xf) << 24) -#define SSI_TX_FIFO_1_COUNT_SHIFT 24 -#define SSI_SFCSR_RFWM1(x) (((x) & 0xf) << 20) -#define SSI_SFCSR_TFWM1(x) (((x) & 0xf) << 16) -#define SSI_SFCSR_RFCNT0(x) (((x) & 0xf) << 12) -#define SSI_RX_FIFO_0_COUNT_SHIFT 12 -#define SSI_SFCSR_TFCNT0(x) (((x) & 0xf) << 8) -#define SSI_TX_FIFO_0_COUNT_SHIFT 8 -#define SSI_SFCSR_RFWM0(x) (((x) & 0xf) << 4) -#define SSI_SFCSR_TFWM0(x) (((x) & 0xf) << 0) -#define SSI_SFCSR_RFWM0_MASK (0xf << 4) -#define SSI_SFCSR_TFWM0_MASK (0xf << 0) - -#define SSI_STR 0x30 -#define SSI_STR_TEST (1 << 15) -#define SSI_STR_RCK2TCK (1 << 14) -#define SSI_STR_RFS2TFS (1 << 13) -#define SSI_STR_RXSTATE(x) (((x) & 0xf) << 8) -#define SSI_STR_TXD2RXD (1 << 7) -#define SSI_STR_TCK2RCK (1 << 6) -#define SSI_STR_TFS2RFS (1 << 5) -#define SSI_STR_TXSTATE(x) (((x) & 0xf) << 0) - -#define SSI_SOR 0x34 -#define SSI_SOR_CLKOFF (1 << 6) -#define SSI_SOR_RX_CLR (1 << 5) -#define SSI_SOR_TX_CLR (1 << 4) -#define SSI_SOR_INIT (1 << 3) -#define SSI_SOR_WAIT(x) (((x) & 0x3) << 1) -#define SSI_SOR_WAIT_MASK (0x3 << 1) -#define SSI_SOR_SYNRST (1 << 0) - -#define SSI_SACNT 0x38 -#define SSI_SACNT_FRDIV(x) (((x) & 0x3f) << 5) -#define SSI_SACNT_WR (1 << 4) -#define SSI_SACNT_RD (1 << 3) -#define SSI_SACNT_TIF (1 << 2) -#define SSI_SACNT_FV (1 << 1) -#define SSI_SACNT_AC97EN (1 << 0) - -#define SSI_SACADD 0x3c -#define SSI_SACDAT 0x40 -#define SSI_SATAG 0x44 -#define SSI_STMSK 0x48 -#define SSI_SRMSK 0x4c -#define SSI_SACCST 0x50 -#define SSI_SACCEN 0x54 -#define SSI_SACCDIS 0x58 - -/* SSI clock sources */ -#define IMX_SSP_SYS_CLK 0 - -/* SSI audio dividers */ -#define IMX_SSI_TX_DIV_2 0 -#define IMX_SSI_TX_DIV_PSR 1 -#define IMX_SSI_TX_DIV_PM 2 -#define IMX_SSI_RX_DIV_2 3 -#define IMX_SSI_RX_DIV_PSR 4 -#define IMX_SSI_RX_DIV_PM 5 - -#define DRV_NAME "imx-ssi" - -#include -#include -#include "imx-pcm.h" - -struct imx_ssi { - struct platform_device *ac97_dev; - - struct snd_soc_dai *imx_ac97; - struct clk *clk; - void __iomem *base; - int irq; - int fiq_enable; - unsigned int offset; - - unsigned int flags; - - void (*ac97_reset) (struct snd_ac97 *ac97); - void (*ac97_warm_reset)(struct snd_ac97 *ac97); - - struct imx_pcm_dma_params dma_params_rx; - struct imx_pcm_dma_params dma_params_tx; - - int enabled; - - struct platform_device *soc_platform_pdev; - struct platform_device *soc_platform_pdev_fiq; -}; - -#endif /* _IMX_SSI_H */ diff --git a/ANDROID_3.4.5/sound/soc/imx/mx27vis-aic32x4.c b/ANDROID_3.4.5/sound/soc/imx/mx27vis-aic32x4.c deleted file mode 100644 index f6d04ad4..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/mx27vis-aic32x4.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * mx27vis-aic32x4.c - * - * Copyright 2011 Vista Silicon S.L. - * - * Author: Javier Martin - * - * 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., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../codecs/tlv320aic32x4.h" -#include "imx-ssi.h" -#include "imx-audmux.h" - -#define MX27VIS_AMP_GAIN 0 -#define MX27VIS_AMP_MUTE 1 - -#define MX27VIS_PIN_G0 (GPIO_PORTF + 9) -#define MX27VIS_PIN_G1 (GPIO_PORTF + 8) -#define MX27VIS_PIN_SDL (GPIO_PORTE + 5) -#define MX27VIS_PIN_SDR (GPIO_PORTF + 7) - -static int mx27vis_amp_gain; -static int mx27vis_amp_mute; - -static const int mx27vis_amp_pins[] = { - MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT, - MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT, -}; - -static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - u32 dai_format; - - dai_format = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM; - - /* set codec DAI configuration */ - snd_soc_dai_set_fmt(codec_dai, dai_format); - - /* set cpu DAI configuration */ - snd_soc_dai_set_fmt(cpu_dai, dai_format); - - ret = snd_soc_dai_set_sysclk(codec_dai, 0, - 25000000, SND_SOC_CLOCK_OUT); - if (ret) { - pr_err("%s: failed setting codec sysclk\n", __func__); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, - SND_SOC_CLOCK_IN); - if (ret) { - pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops mx27vis_aic32x4_snd_ops = { - .hw_params = mx27vis_aic32x4_hw_params, -}; - -static int mx27vis_amp_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int value = ucontrol->value.integer.value[0]; - unsigned int reg = mc->reg; - int max = mc->max; - - if (value > max) - return -EINVAL; - - switch (reg) { - case MX27VIS_AMP_GAIN: - gpio_set_value(MX27VIS_PIN_G0, value & 1); - gpio_set_value(MX27VIS_PIN_G1, value >> 1); - mx27vis_amp_gain = value; - break; - case MX27VIS_AMP_MUTE: - gpio_set_value(MX27VIS_PIN_SDL, value & 1); - gpio_set_value(MX27VIS_PIN_SDR, value >> 1); - mx27vis_amp_mute = value; - break; - } - return 0; -} - -static int mx27vis_amp_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - - switch (reg) { - case MX27VIS_AMP_GAIN: - ucontrol->value.integer.value[0] = mx27vis_amp_gain; - break; - case MX27VIS_AMP_MUTE: - ucontrol->value.integer.value[0] = mx27vis_amp_mute; - break; - } - return 0; -} - -/* From 6dB to 24dB in steps of 6dB */ -static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0); - -static const struct snd_kcontrol_new mx27vis_aic32x4_controls[] = { - SOC_DAPM_PIN_SWITCH("External Mic"), - SOC_SINGLE_EXT_TLV("LO Ext Boost", MX27VIS_AMP_GAIN, 0, 3, 0, - mx27vis_amp_get, mx27vis_amp_set, mx27vis_amp_tlv), - SOC_DOUBLE_EXT("LO Ext Mute Switch", MX27VIS_AMP_MUTE, 0, 1, 1, 0, - mx27vis_amp_get, mx27vis_amp_set), -}; - -static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { - SND_SOC_DAPM_MIC("External Mic", NULL), -}; - -static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { - {"Mic Bias", NULL, "External Mic"}, - {"IN1_R", NULL, "Mic Bias"}, - {"IN2_R", NULL, "Mic Bias"}, - {"IN3_R", NULL, "Mic Bias"}, - {"IN1_L", NULL, "Mic Bias"}, - {"IN2_L", NULL, "Mic Bias"}, - {"IN3_L", NULL, "Mic Bias"}, -}; - -static struct snd_soc_dai_link mx27vis_aic32x4_dai = { - .name = "tlv320aic32x4", - .stream_name = "TLV320AIC32X4", - .codec_dai_name = "tlv320aic32x4-hifi", - .platform_name = "imx-pcm-audio.0", - .codec_name = "tlv320aic32x4.0-0018", - .cpu_dai_name = "imx-ssi.0", - .ops = &mx27vis_aic32x4_snd_ops, -}; - -static struct snd_soc_card mx27vis_aic32x4 = { - .name = "visstrim_m10-audio", - .owner = THIS_MODULE, - .dai_link = &mx27vis_aic32x4_dai, - .num_links = 1, - .controls = mx27vis_aic32x4_controls, - .num_controls = ARRAY_SIZE(mx27vis_aic32x4_controls), - .dapm_widgets = aic32x4_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets), - .dapm_routes = aic32x4_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), -}; - -static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) -{ - int ret; - - mx27vis_aic32x4.dev = &pdev->dev; - ret = snd_soc_register_card(&mx27vis_aic32x4); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", - ret); - return ret; - } - - /* Connect SSI0 as clock slave to SSI1 external pins */ - imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - IMX_AUDMUX_V1_PCR_SYN | - IMX_AUDMUX_V1_PCR_TFSDIR | - IMX_AUDMUX_V1_PCR_TCLKDIR | - IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | - IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) - ); - imx_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1, - IMX_AUDMUX_V1_PCR_SYN | - IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) - ); - - ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins, - ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP"); - if (ret) - printk(KERN_ERR "ASoC: unable to setup gpios\n"); - - return ret; -} - -static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev) -{ - snd_soc_unregister_card(&mx27vis_aic32x4); - - return 0; -} - -static struct platform_driver mx27vis_aic32x4_audio_driver = { - .driver = { - .name = "mx27vis", - .owner = THIS_MODULE, - }, - .probe = mx27vis_aic32x4_probe, - .remove = __devexit_p(mx27vis_aic32x4_remove), -}; - -module_platform_driver(mx27vis_aic32x4_audio_driver); - -MODULE_AUTHOR("Javier Martin "); -MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:mx27vis"); diff --git a/ANDROID_3.4.5/sound/soc/imx/phycore-ac97.c b/ANDROID_3.4.5/sound/soc/imx/phycore-ac97.c deleted file mode 100644 index f8da6dd1..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/phycore-ac97.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * phycore-ac97.c -- SoC audio for imx_phycore in AC97 mode - * - * Copyright 2009 Sascha Hauer, Pengutronix - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "imx-audmux.h" - -static struct snd_soc_card imx_phycore; - -static struct snd_soc_ops imx_phycore_hifi_ops = { -}; - -static struct snd_soc_dai_link imx_phycore_dai_ac97[] = { - { - .name = "HiFi", - .stream_name = "HiFi", - .codec_dai_name = "wm9712-hifi", - .codec_name = "wm9712-codec", - .cpu_dai_name = "imx-ssi.0", - .platform_name = "imx-fiq-pcm-audio.0", - .ops = &imx_phycore_hifi_ops, - }, -}; - -static struct snd_soc_card imx_phycore = { - .name = "PhyCORE-ac97-audio", - .owner = THIS_MODULE, - .dai_link = imx_phycore_dai_ac97, - .num_links = ARRAY_SIZE(imx_phycore_dai_ac97), -}; - -static struct platform_device *imx_phycore_snd_ac97_device; -static struct platform_device *imx_phycore_snd_device; - -static int __init imx_phycore_init(void) -{ - int ret; - - if (machine_is_pca100()) { - imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, - IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */ - IMX_AUDMUX_V1_PCR_TFCSEL(3) | - IMX_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */ - IMX_AUDMUX_V1_PCR_RXDSEL(3)); - imx_audmux_v1_configure_port(3, - IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */ - IMX_AUDMUX_V1_PCR_TFCSEL(0) | - IMX_AUDMUX_V1_PCR_TFSDIR | - IMX_AUDMUX_V1_PCR_RXDSEL(0)); - } else if (machine_is_pcm043()) { - imx_audmux_v2_configure_port(3, - IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ - IMX_AUDMUX_V2_PTCR_TFSEL(0) | - IMX_AUDMUX_V2_PTCR_TFSDIR, - IMX_AUDMUX_V2_PDCR_RXDSEL(0)); - imx_audmux_v2_configure_port(0, - IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ - IMX_AUDMUX_V2_PTCR_TCSEL(3) | - IMX_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */ - IMX_AUDMUX_V2_PDCR_RXDSEL(3)); - } else { - /* return happy. We might run on a totally different machine */ - return 0; - } - - imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1); - if (!imx_phycore_snd_ac97_device) - return -ENOMEM; - - platform_set_drvdata(imx_phycore_snd_ac97_device, &imx_phycore); - ret = platform_device_add(imx_phycore_snd_ac97_device); - if (ret) - goto fail1; - - imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1); - if (!imx_phycore_snd_device) { - ret = -ENOMEM; - goto fail2; - } - ret = platform_device_add(imx_phycore_snd_device); - - if (ret) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - goto fail3; - } - - return 0; - -fail3: - platform_device_put(imx_phycore_snd_device); -fail2: - platform_device_del(imx_phycore_snd_ac97_device); -fail1: - platform_device_put(imx_phycore_snd_ac97_device); - return ret; -} - -static void __exit imx_phycore_exit(void) -{ - platform_device_unregister(imx_phycore_snd_device); - platform_device_unregister(imx_phycore_snd_ac97_device); -} - -late_initcall(imx_phycore_init); -module_exit(imx_phycore_exit); - -MODULE_AUTHOR("Sascha Hauer "); -MODULE_DESCRIPTION("PhyCORE ALSA SoC driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/imx/wm1133-ev1.c b/ANDROID_3.4.5/sound/soc/imx/wm1133-ev1.c deleted file mode 100644 index fe54a690..00000000 --- a/ANDROID_3.4.5/sound/soc/imx/wm1133-ev1.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * wm1133-ev1.c - Audio for WM1133-EV1 on i.MX31ADS - * - * Copyright (c) 2010 Wolfson Microelectronics plc - * Author: Mark Brown - * - * Based on an earlier driver for the same hardware by Liam Girdwood. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "imx-ssi.h" -#include "../codecs/wm8350.h" -#include "imx-audmux.h" - -/* There is a silicon mic on the board optionally connected via a solder pad - * SP1. Define this to enable it. - */ -#undef USE_SIMIC - -struct _wm8350_audio { - unsigned int channels; - snd_pcm_format_t format; - unsigned int rate; - unsigned int sysclk; - unsigned int bclkdiv; - unsigned int clkdiv; - unsigned int lr_rate; -}; - -/* in order of power consumption per rate (lowest first) */ -static const struct _wm8350_audio wm8350_audio[] = { - /* 16bit mono modes */ - {1, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000 >> 1, - WM8350_BCLK_DIV_48, WM8350_DACDIV_3, 16,}, - - /* 16 bit stereo modes */ - {2, SNDRV_PCM_FORMAT_S16_LE, 8000, 12288000, - WM8350_BCLK_DIV_48, WM8350_DACDIV_6, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 16000, 12288000, - WM8350_BCLK_DIV_24, WM8350_DACDIV_3, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 32000, 12288000, - WM8350_BCLK_DIV_12, WM8350_DACDIV_1_5, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 48000, 12288000, - WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 96000, 24576000, - WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 11025, 11289600, - WM8350_BCLK_DIV_32, WM8350_DACDIV_4, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 22050, 11289600, - WM8350_BCLK_DIV_16, WM8350_DACDIV_2, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 44100, 11289600, - WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, - {2, SNDRV_PCM_FORMAT_S16_LE, 88200, 22579200, - WM8350_BCLK_DIV_8, WM8350_DACDIV_1, 32,}, - - /* 24bit stereo modes */ - {2, SNDRV_PCM_FORMAT_S24_LE, 48000, 12288000, - WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, - {2, SNDRV_PCM_FORMAT_S24_LE, 96000, 24576000, - WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, - {2, SNDRV_PCM_FORMAT_S24_LE, 44100, 11289600, - WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, - {2, SNDRV_PCM_FORMAT_S24_LE, 88200, 22579200, - WM8350_BCLK_DIV_4, WM8350_DACDIV_1, 64,}, -}; - -static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int i, found = 0; - snd_pcm_format_t format = params_format(params); - unsigned int rate = params_rate(params); - unsigned int channels = params_channels(params); - u32 dai_format; - - /* find the correct audio parameters */ - for (i = 0; i < ARRAY_SIZE(wm8350_audio); i++) { - if (rate == wm8350_audio[i].rate && - format == wm8350_audio[i].format && - channels == wm8350_audio[i].channels) { - found = 1; - break; - } - } - if (!found) - return -EINVAL; - - /* codec FLL input is 14.75 MHz from MCLK */ - snd_soc_dai_set_pll(codec_dai, 0, 0, 14750000, wm8350_audio[i].sysclk); - - dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM; - - /* set codec DAI configuration */ - snd_soc_dai_set_fmt(codec_dai, dai_format); - - /* set cpu DAI configuration */ - snd_soc_dai_set_fmt(cpu_dai, dai_format); - - /* TODO: The SSI driver should figure this out for us */ - switch (channels) { - case 2: - snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); - break; - case 1: - snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffe, 0xffffffe, 1, 0); - break; - default: - return -EINVAL; - } - - /* set MCLK as the codec system clock for DAC and ADC */ - snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_MCLK, - wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN); - - /* set codec BCLK division for sample rate */ - snd_soc_dai_set_clkdiv(codec_dai, WM8350_BCLK_CLKDIV, - wm8350_audio[i].bclkdiv); - - /* DAI is synchronous and clocked with DAC LRCLK & ADC LRC */ - snd_soc_dai_set_clkdiv(codec_dai, - WM8350_DACLR_CLKDIV, wm8350_audio[i].lr_rate); - snd_soc_dai_set_clkdiv(codec_dai, - WM8350_ADCLR_CLKDIV, wm8350_audio[i].lr_rate); - - /* now configure DAC and ADC clocks */ - snd_soc_dai_set_clkdiv(codec_dai, - WM8350_DAC_CLKDIV, wm8350_audio[i].clkdiv); - - snd_soc_dai_set_clkdiv(codec_dai, - WM8350_ADC_CLKDIV, wm8350_audio[i].clkdiv); - - return 0; -} - -static struct snd_soc_ops wm1133_ev1_ops = { - .hw_params = wm1133_ev1_hw_params, -}; - -static const struct snd_soc_dapm_widget wm1133_ev1_widgets[] = { -#ifdef USE_SIMIC - SND_SOC_DAPM_MIC("SiMIC", NULL), -#endif - SND_SOC_DAPM_MIC("Mic1 Jack", NULL), - SND_SOC_DAPM_MIC("Mic2 Jack", NULL), - SND_SOC_DAPM_LINE("Line In Jack", NULL), - SND_SOC_DAPM_LINE("Line Out Jack", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), -}; - -/* imx32ads soc_card audio map */ -static const struct snd_soc_dapm_route wm1133_ev1_map[] = { - -#ifdef USE_SIMIC - /* SiMIC --> IN1LN (with automatic bias) via SP1 */ - { "IN1LN", NULL, "Mic Bias" }, - { "Mic Bias", NULL, "SiMIC" }, -#endif - - /* Mic 1 Jack --> IN1LN and IN1LP (with automatic bias) */ - { "IN1LN", NULL, "Mic Bias" }, - { "IN1LP", NULL, "Mic1 Jack" }, - { "Mic Bias", NULL, "Mic1 Jack" }, - - /* Mic 2 Jack --> IN1RN and IN1RP (with automatic bias) */ - { "IN1RN", NULL, "Mic Bias" }, - { "IN1RP", NULL, "Mic2 Jack" }, - { "Mic Bias", NULL, "Mic2 Jack" }, - - /* Line in Jack --> AUX (L+R) */ - { "IN3R", NULL, "Line In Jack" }, - { "IN3L", NULL, "Line In Jack" }, - - /* Out1 --> Headphone Jack */ - { "Headphone Jack", NULL, "OUT1R" }, - { "Headphone Jack", NULL, "OUT1L" }, - - /* Out1 --> Line Out Jack */ - { "Line Out Jack", NULL, "OUT2R" }, - { "Line Out Jack", NULL, "OUT2L" }, -}; - -static struct snd_soc_jack hp_jack; - -static struct snd_soc_jack_pin hp_jack_pins[] = { - { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE }, -}; - -static struct snd_soc_jack mic_jack; - -static struct snd_soc_jack_pin mic_jack_pins[] = { - { .pin = "Mic1 Jack", .mask = SND_JACK_MICROPHONE }, - { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE }, -}; - -static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, wm1133_ev1_widgets, - ARRAY_SIZE(wm1133_ev1_widgets)); - - snd_soc_dapm_add_routes(dapm, wm1133_ev1_map, - ARRAY_SIZE(wm1133_ev1_map)); - - /* Headphone jack detection */ - snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack); - snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), - hp_jack_pins); - wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE); - - /* Microphone jack detection */ - snd_soc_jack_new(codec, "Microphone", - SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack); - snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), - mic_jack_pins); - wm8350_mic_jack_detect(codec, &mic_jack, SND_JACK_MICROPHONE, - SND_JACK_BTN_0); - - snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); - - return 0; -} - - -static struct snd_soc_dai_link wm1133_ev1_dai = { - .name = "WM1133-EV1", - .stream_name = "Audio", - .cpu_dai_name = "imx-ssi.0", - .codec_dai_name = "wm8350-hifi", - .platform_name = "imx-fiq-pcm-audio.0", - .codec_name = "wm8350-codec.0-0x1a", - .init = wm1133_ev1_init, - .ops = &wm1133_ev1_ops, - .symmetric_rates = 1, -}; - -static struct snd_soc_card wm1133_ev1 = { - .name = "WM1133-EV1", - .owner = THIS_MODULE, - .dai_link = &wm1133_ev1_dai, - .num_links = 1, -}; - -static struct platform_device *wm1133_ev1_snd_device; - -static int __init wm1133_ev1_audio_init(void) -{ - int ret; - unsigned int ptcr, pdcr; - - /* SSI0 mastered by port 5 */ - ptcr = IMX_AUDMUX_V2_PTCR_SYN | - IMX_AUDMUX_V2_PTCR_TFSDIR | - IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) | - IMX_AUDMUX_V2_PTCR_TCLKDIR | - IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); - pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5); - imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr); - - ptcr = IMX_AUDMUX_V2_PTCR_SYN; - pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0); - imx_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr); - - wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1); - if (!wm1133_ev1_snd_device) - return -ENOMEM; - - platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1); - ret = platform_device_add(wm1133_ev1_snd_device); - - if (ret) - platform_device_put(wm1133_ev1_snd_device); - - return ret; -} -module_init(wm1133_ev1_audio_init); - -static void __exit wm1133_ev1_audio_exit(void) -{ - platform_device_unregister(wm1133_ev1_snd_device); -} -module_exit(wm1133_ev1_audio_exit); - -MODULE_AUTHOR("Mark Brown "); -MODULE_DESCRIPTION("Audio for WM1133-EV1 on i.MX31ADS"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/jz4740/Kconfig b/ANDROID_3.4.5/sound/soc/jz4740/Kconfig deleted file mode 100644 index 5351cba6..00000000 --- a/ANDROID_3.4.5/sound/soc/jz4740/Kconfig +++ /dev/null @@ -1,23 +0,0 @@ -config SND_JZ4740_SOC - tristate "SoC Audio for Ingenic JZ4740 SoC" - depends on MACH_JZ4740 && SND_SOC - help - Say Y or M if you want to add support for codecs attached to - the JZ4740 I2S interface. You will also need to select the audio - interfaces to support below. - -config SND_JZ4740_SOC_I2S - depends on SND_JZ4740_SOC - tristate "SoC Audio (I2S protocol) for Ingenic JZ4740 SoC" - help - Say Y if you want to use I2S protocol and I2S codec on Ingenic JZ4740 - based boards. - -config SND_JZ4740_SOC_QI_LB60 - tristate "SoC Audio support for Qi LB60" - depends on SND_JZ4740_SOC && JZ4740_QI_LB60 - select SND_JZ4740_SOC_I2S - select SND_SOC_JZ4740_CODEC - help - Say Y if you want to add support for ASoC audio on the Qi LB60 board - a.k.a Qi Ben NanoNote. diff --git a/ANDROID_3.4.5/sound/soc/jz4740/Makefile b/ANDROID_3.4.5/sound/soc/jz4740/Makefile deleted file mode 100644 index be873c1b..00000000 --- a/ANDROID_3.4.5/sound/soc/jz4740/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Jz4740 Platform Support -# -snd-soc-jz4740-objs := jz4740-pcm.o -snd-soc-jz4740-i2s-objs := jz4740-i2s.o - -obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o -obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o - -# Jz4740 Machine Support -snd-soc-qi-lb60-objs := qi_lb60.o - -obj-$(CONFIG_SND_JZ4740_SOC_QI_LB60) += snd-soc-qi-lb60.o diff --git a/ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.c b/ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.c deleted file mode 100644 index a5af7c42..00000000 --- a/ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen - * - * 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. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "jz4740-i2s.h" -#include "jz4740-pcm.h" - -#define JZ_REG_AIC_CONF 0x00 -#define JZ_REG_AIC_CTRL 0x04 -#define JZ_REG_AIC_I2S_FMT 0x10 -#define JZ_REG_AIC_FIFO_STATUS 0x14 -#define JZ_REG_AIC_I2S_STATUS 0x1c -#define JZ_REG_AIC_CLK_DIV 0x30 -#define JZ_REG_AIC_FIFO 0x34 - -#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_MASK (0xf << 12) -#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_MASK (0xf << 8) -#define JZ_AIC_CONF_OVERFLOW_PLAY_LAST BIT(6) -#define JZ_AIC_CONF_INTERNAL_CODEC BIT(5) -#define JZ_AIC_CONF_I2S BIT(4) -#define JZ_AIC_CONF_RESET BIT(3) -#define JZ_AIC_CONF_BIT_CLK_MASTER BIT(2) -#define JZ_AIC_CONF_SYNC_CLK_MASTER BIT(1) -#define JZ_AIC_CONF_ENABLE BIT(0) - -#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12 -#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8 - -#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19) -#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16) -#define JZ_AIC_CTRL_ENABLE_RX_DMA BIT(15) -#define JZ_AIC_CTRL_ENABLE_TX_DMA BIT(14) -#define JZ_AIC_CTRL_MONO_TO_STEREO BIT(11) -#define JZ_AIC_CTRL_SWITCH_ENDIANNESS BIT(10) -#define JZ_AIC_CTRL_SIGNED_TO_UNSIGNED BIT(9) -#define JZ_AIC_CTRL_FLUSH BIT(8) -#define JZ_AIC_CTRL_ENABLE_ROR_INT BIT(6) -#define JZ_AIC_CTRL_ENABLE_TUR_INT BIT(5) -#define JZ_AIC_CTRL_ENABLE_RFS_INT BIT(4) -#define JZ_AIC_CTRL_ENABLE_TFS_INT BIT(3) -#define JZ_AIC_CTRL_ENABLE_LOOPBACK BIT(2) -#define JZ_AIC_CTRL_ENABLE_PLAYBACK BIT(1) -#define JZ_AIC_CTRL_ENABLE_CAPTURE BIT(0) - -#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET 19 -#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET 16 - -#define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12) -#define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4) -#define JZ_AIC_I2S_FMT_MSB BIT(0) - -#define JZ_AIC_I2S_STATUS_BUSY BIT(2) - -#define JZ_AIC_CLK_DIV_MASK 0xf - -struct jz4740_i2s { - struct resource *mem; - void __iomem *base; - dma_addr_t phys_base; - - struct clk *clk_aic; - struct clk *clk_i2s; - - struct jz4740_pcm_config pcm_config_playback; - struct jz4740_pcm_config pcm_config_capture; -}; - -static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, - unsigned int reg) -{ - return readl(i2s->base + reg); -} - -static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s, - unsigned int reg, uint32_t value) -{ - writel(value, i2s->base + reg); -} - -static int jz4740_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - uint32_t conf, ctrl; - - if (dai->active) - return 0; - - ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); - ctrl |= JZ_AIC_CTRL_FLUSH; - jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); - - clk_enable(i2s->clk_i2s); - - conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); - conf |= JZ_AIC_CONF_ENABLE; - jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); - - return 0; -} - -static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - uint32_t conf; - - if (dai->active) - return; - - conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); - conf &= ~JZ_AIC_CONF_ENABLE; - jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); - - clk_disable(i2s->clk_i2s); -} - -static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - - uint32_t ctrl; - uint32_t mask; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - mask = JZ_AIC_CTRL_ENABLE_PLAYBACK | JZ_AIC_CTRL_ENABLE_TX_DMA; - else - mask = JZ_AIC_CTRL_ENABLE_CAPTURE | JZ_AIC_CTRL_ENABLE_RX_DMA; - - ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ctrl |= mask; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ctrl &= ~mask; - break; - default: - return -EINVAL; - } - - jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); - - return 0; -} - -static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - - uint32_t format = 0; - uint32_t conf; - - conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); - - conf &= ~(JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - conf |= JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER; - format |= JZ_AIC_I2S_FMT_ENABLE_SYS_CLK; - break; - case SND_SOC_DAIFMT_CBM_CFS: - conf |= JZ_AIC_CONF_SYNC_CLK_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFM: - conf |= JZ_AIC_CONF_BIT_CLK_MASTER; - break; - case SND_SOC_DAIFMT_CBM_CFM: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_MSB: - format |= JZ_AIC_I2S_FMT_MSB; - break; - case SND_SOC_DAIFMT_I2S: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - default: - return -EINVAL; - } - - jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); - jz4740_i2s_write(i2s, JZ_REG_AIC_I2S_FMT, format); - - return 0; -} - -static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - enum jz4740_dma_width dma_width; - struct jz4740_pcm_config *pcm_config; - unsigned int sample_size; - uint32_t ctrl; - - ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - sample_size = 0; - dma_width = JZ4740_DMA_WIDTH_8BIT; - break; - case SNDRV_PCM_FORMAT_S16: - sample_size = 1; - dma_width = JZ4740_DMA_WIDTH_16BIT; - break; - default: - return -EINVAL; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ctrl &= ~JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK; - ctrl |= sample_size << JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET; - if (params_channels(params) == 1) - ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; - else - ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; - - pcm_config = &i2s->pcm_config_playback; - pcm_config->dma_config.dst_width = dma_width; - - } else { - ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; - ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; - - pcm_config = &i2s->pcm_config_capture; - pcm_config->dma_config.src_width = dma_width; - } - - jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); - - snd_soc_dai_set_dma_data(dai, substream, pcm_config); - - return 0; -} - -static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - struct clk *parent; - int ret = 0; - - switch (clk_id) { - case JZ4740_I2S_CLKSRC_EXT: - parent = clk_get(NULL, "ext"); - clk_set_parent(i2s->clk_i2s, parent); - break; - case JZ4740_I2S_CLKSRC_PLL: - parent = clk_get(NULL, "pll half"); - clk_set_parent(i2s->clk_i2s, parent); - ret = clk_set_rate(i2s->clk_i2s, freq); - break; - default: - return -EINVAL; - } - clk_put(parent); - - return ret; -} - -static int jz4740_i2s_suspend(struct snd_soc_dai *dai) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - uint32_t conf; - - if (dai->active) { - conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); - conf &= ~JZ_AIC_CONF_ENABLE; - jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); - - clk_disable(i2s->clk_i2s); - } - - clk_disable(i2s->clk_aic); - - return 0; -} - -static int jz4740_i2s_resume(struct snd_soc_dai *dai) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - uint32_t conf; - - clk_enable(i2s->clk_aic); - - if (dai->active) { - clk_enable(i2s->clk_i2s); - - conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); - conf |= JZ_AIC_CONF_ENABLE; - jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); - } - - return 0; -} - -static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s) -{ - struct jz4740_dma_config *dma_config; - - /* Playback */ - dma_config = &i2s->pcm_config_playback.dma_config; - dma_config->src_width = JZ4740_DMA_WIDTH_32BIT, - dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; - dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT; - dma_config->flags = JZ4740_DMA_SRC_AUTOINC; - dma_config->mode = JZ4740_DMA_MODE_SINGLE; - i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; - - /* Capture */ - dma_config = &i2s->pcm_config_capture.dma_config; - dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT, - dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE; - dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE; - dma_config->flags = JZ4740_DMA_DST_AUTOINC; - dma_config->mode = JZ4740_DMA_MODE_SINGLE; - i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO; -} - -static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - uint32_t conf; - - clk_enable(i2s->clk_aic); - - jz4740_i2c_init_pcm_config(i2s); - - conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | - (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | - JZ_AIC_CONF_OVERFLOW_PLAY_LAST | - JZ_AIC_CONF_I2S | - JZ_AIC_CONF_INTERNAL_CODEC; - - jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET); - jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); - - return 0; -} - -static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai) -{ - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); - - clk_disable(i2s->clk_aic); - return 0; -} - -static const struct snd_soc_dai_ops jz4740_i2s_dai_ops = { - .startup = jz4740_i2s_startup, - .shutdown = jz4740_i2s_shutdown, - .trigger = jz4740_i2s_trigger, - .hw_params = jz4740_i2s_hw_params, - .set_fmt = jz4740_i2s_set_fmt, - .set_sysclk = jz4740_i2s_set_sysclk, -}; - -#define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ - SNDRV_PCM_FMTBIT_S16_LE) - -static struct snd_soc_dai_driver jz4740_i2s_dai = { - .probe = jz4740_i2s_dai_probe, - .remove = jz4740_i2s_dai_remove, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = JZ4740_I2S_FMTS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = JZ4740_I2S_FMTS, - }, - .symmetric_rates = 1, - .ops = &jz4740_i2s_dai_ops, - .suspend = jz4740_i2s_suspend, - .resume = jz4740_i2s_resume, -}; - -static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev) -{ - struct jz4740_i2s *i2s; - int ret; - - i2s = kzalloc(sizeof(*i2s), GFP_KERNEL); - - if (!i2s) - return -ENOMEM; - - i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!i2s->mem) { - ret = -ENOENT; - goto err_free; - } - - i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem), - pdev->name); - if (!i2s->mem) { - ret = -EBUSY; - goto err_free; - } - - i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem)); - if (!i2s->base) { - ret = -EBUSY; - goto err_release_mem_region; - } - - i2s->phys_base = i2s->mem->start; - - i2s->clk_aic = clk_get(&pdev->dev, "aic"); - if (IS_ERR(i2s->clk_aic)) { - ret = PTR_ERR(i2s->clk_aic); - goto err_iounmap; - } - - i2s->clk_i2s = clk_get(&pdev->dev, "i2s"); - if (IS_ERR(i2s->clk_i2s)) { - ret = PTR_ERR(i2s->clk_i2s); - goto err_clk_put_aic; - } - - platform_set_drvdata(pdev, i2s); - ret = snd_soc_register_dai(&pdev->dev, &jz4740_i2s_dai); - - if (ret) { - dev_err(&pdev->dev, "Failed to register DAI\n"); - goto err_clk_put_i2s; - } - - return 0; - -err_clk_put_i2s: - clk_put(i2s->clk_i2s); -err_clk_put_aic: - clk_put(i2s->clk_aic); -err_iounmap: - iounmap(i2s->base); -err_release_mem_region: - release_mem_region(i2s->mem->start, resource_size(i2s->mem)); -err_free: - kfree(i2s); - - return ret; -} - -static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev) -{ - struct jz4740_i2s *i2s = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - - clk_put(i2s->clk_i2s); - clk_put(i2s->clk_aic); - - iounmap(i2s->base); - release_mem_region(i2s->mem->start, resource_size(i2s->mem)); - - platform_set_drvdata(pdev, NULL); - kfree(i2s); - - return 0; -} - -static struct platform_driver jz4740_i2s_driver = { - .probe = jz4740_i2s_dev_probe, - .remove = __devexit_p(jz4740_i2s_dev_remove), - .driver = { - .name = "jz4740-i2s", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(jz4740_i2s_driver); - -MODULE_AUTHOR("Lars-Peter Clausen, "); -MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:jz4740-i2s"); diff --git a/ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.h b/ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.h deleted file mode 100644 index 5e49339d..00000000 --- a/ANDROID_3.4.5/sound/soc/jz4740/jz4740-i2s.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _JZ4740_I2S_H -#define _JZ4740_I2S_H - -/* I2S clock source */ -#define JZ4740_I2S_CLKSRC_EXT 0 -#define JZ4740_I2S_CLKSRC_PLL 1 - -#define JZ4740_I2S_BIT_CLK 0 - -#endif diff --git a/ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.c b/ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.c deleted file mode 100644 index 9b8cf256..00000000 --- a/ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen - * - * 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. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include "jz4740-pcm.h" - -struct jz4740_runtime_data { - unsigned long dma_period; - dma_addr_t dma_start; - dma_addr_t dma_pos; - dma_addr_t dma_end; - - struct jz4740_dma_chan *dma; - - dma_addr_t fifo_addr; -}; - -/* identify hardware playback capabilities */ -static const struct snd_pcm_hardware jz4740_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, - - .rates = SNDRV_PCM_RATE_8000_48000, - .channels_min = 1, - .channels_max = 2, - .period_bytes_min = 16, - .period_bytes_max = 2 * PAGE_SIZE, - .periods_min = 2, - .periods_max = 128, - .buffer_bytes_max = 128 * 2 * PAGE_SIZE, - .fifo_size = 32, -}; - -static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd, - struct snd_pcm_substream *substream) -{ - unsigned long count; - - if (prtd->dma_pos == prtd->dma_end) - prtd->dma_pos = prtd->dma_start; - - if (prtd->dma_pos + prtd->dma_period > prtd->dma_end) - count = prtd->dma_end - prtd->dma_pos; - else - count = prtd->dma_period; - - jz4740_dma_disable(prtd->dma); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos); - jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr); - } else { - jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr); - jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos); - } - - jz4740_dma_set_transfer_count(prtd->dma, count); - - prtd->dma_pos += count; - - jz4740_dma_enable(prtd->dma); -} - -static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err, - void *dev_id) -{ - struct snd_pcm_substream *substream = dev_id; - struct snd_pcm_runtime *runtime = substream->runtime; - struct jz4740_runtime_data *prtd = runtime->private_data; - - snd_pcm_period_elapsed(substream); - - jz4740_pcm_start_transfer(prtd, substream); -} - -static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct jz4740_runtime_data *prtd = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct jz4740_pcm_config *config; - - config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - if (!config) - return 0; - - if (!prtd->dma) { - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - prtd->dma = jz4740_dma_request(substream, "PCM Capture"); - else - prtd->dma = jz4740_dma_request(substream, "PCM Playback"); - } - - if (!prtd->dma) - return -EBUSY; - - jz4740_dma_configure(prtd->dma, &config->dma_config); - prtd->fifo_addr = config->fifo_addr; - - jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done); - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - - prtd->dma_period = params_period_bytes(params); - prtd->dma_start = runtime->dma_addr; - prtd->dma_pos = prtd->dma_start; - prtd->dma_end = prtd->dma_start + runtime->dma_bytes; - - return 0; -} - -static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct jz4740_runtime_data *prtd = substream->runtime->private_data; - - snd_pcm_set_runtime_buffer(substream, NULL); - if (prtd->dma) { - jz4740_dma_free(prtd->dma); - prtd->dma = NULL; - } - - return 0; -} - -static int jz4740_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct jz4740_runtime_data *prtd = substream->runtime->private_data; - - if (!prtd->dma) - return -EBUSY; - - prtd->dma_pos = prtd->dma_start; - - return 0; -} - -static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct jz4740_runtime_data *prtd = runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - jz4740_pcm_start_transfer(prtd, substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - jz4740_dma_disable(prtd->dma); - break; - default: - break; - } - - return 0; -} - -static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct jz4740_runtime_data *prtd = runtime->private_data; - unsigned long byte_offset; - snd_pcm_uframes_t offset; - struct jz4740_dma_chan *dma = prtd->dma; - - /* prtd->dma_pos points to the end of the current transfer. So by - * subtracting prdt->dma_start we get the offset to the end of the - * current period in bytes. By subtracting the residue of the transfer - * we get the current offset in bytes. */ - byte_offset = prtd->dma_pos - prtd->dma_start; - byte_offset -= jz4740_dma_get_residue(dma); - - offset = bytes_to_frames(runtime, byte_offset); - if (offset >= runtime->buffer_size) - offset = 0; - - return offset; -} - -static int jz4740_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct jz4740_runtime_data *prtd; - - prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); - if (prtd == NULL) - return -ENOMEM; - - snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware); - - runtime->private_data = prtd; - - return 0; -} - -static int jz4740_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct jz4740_runtime_data *prtd = runtime->private_data; - - kfree(prtd); - - return 0; -} - -static int jz4740_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - return remap_pfn_range(vma, vma->vm_start, - substream->dma_buffer.addr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot); -} - -static struct snd_pcm_ops jz4740_pcm_ops = { - .open = jz4740_pcm_open, - .close = jz4740_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = jz4740_pcm_hw_params, - .hw_free = jz4740_pcm_hw_free, - .prepare = jz4740_pcm_prepare, - .trigger = jz4740_pcm_trigger, - .pointer = jz4740_pcm_pointer, - .mmap = jz4740_pcm_mmap, -}; - -static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = jz4740_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - - buf->area = dma_alloc_noncoherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - - buf->bytes = size; - - return 0; -} - -static void jz4740_pcm_free(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < SNDRV_PCM_STREAM_LAST; ++stream) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_noncoherent(pcm->card->dev, buf->bytes, buf->area, - buf->addr); - buf->area = NULL; - } -} - -static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32); - -static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &jz4740_pcm_dmamask; - - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = jz4740_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto err; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = jz4740_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto err; - } - -err: - return ret; -} - -static struct snd_soc_platform_driver jz4740_soc_platform = { - .ops = &jz4740_pcm_ops, - .pcm_new = jz4740_pcm_new, - .pcm_free = jz4740_pcm_free, -}; - -static int __devinit jz4740_pcm_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform); -} - -static int __devexit jz4740_pcm_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver jz4740_pcm_driver = { - .probe = jz4740_pcm_probe, - .remove = __devexit_p(jz4740_pcm_remove), - .driver = { - .name = "jz4740-pcm-audio", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(jz4740_pcm_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.h b/ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.h deleted file mode 100644 index 1220cbb4..00000000 --- a/ANDROID_3.4.5/sound/soc/jz4740/jz4740-pcm.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _JZ4740_PCM_H -#define _JZ4740_PCM_H - -#include -#include - - -struct jz4740_pcm_config { - struct jz4740_dma_config dma_config; - phys_addr_t fifo_addr; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/jz4740/qi_lb60.c b/ANDROID_3.4.5/sound/soc/jz4740/qi_lb60.c deleted file mode 100644 index e8aaff18..00000000 --- a/ANDROID_3.4.5/sound/soc/jz4740/qi_lb60.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2009, Lars-Peter Clausen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define QI_LB60_SND_GPIO JZ_GPIO_PORTB(29) -#define QI_LB60_AMP_GPIO JZ_GPIO_PORTD(4) - -static int qi_lb60_spk_event(struct snd_soc_dapm_widget *widget, - struct snd_kcontrol *ctrl, int event) -{ - int on = !SND_SOC_DAPM_EVENT_OFF(event); - - gpio_set_value(QI_LB60_SND_GPIO, on); - gpio_set_value(QI_LB60_AMP_GPIO, on); - - return 0; -} - -static const struct snd_soc_dapm_widget qi_lb60_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", qi_lb60_spk_event), - SND_SOC_DAPM_MIC("Mic", NULL), -}; - -static const struct snd_soc_dapm_route qi_lb60_routes[] = { - {"Mic", NULL, "MIC"}, - {"Speaker", NULL, "LOUT"}, - {"Speaker", NULL, "ROUT"}, -}; - -#define QI_LB60_DAIFMT (SND_SOC_DAIFMT_I2S | \ - SND_SOC_DAIFMT_NB_NF | \ - SND_SOC_DAIFMT_CBM_CFM) - -static int qi_lb60_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - snd_soc_dapm_nc_pin(dapm, "LIN"); - snd_soc_dapm_nc_pin(dapm, "RIN"); - - ret = snd_soc_dai_set_fmt(cpu_dai, QI_LB60_DAIFMT); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cpu dai format: %d\n", ret); - return ret; - } - - return 0; -} - -static struct snd_soc_dai_link qi_lb60_dai = { - .name = "jz4740", - .stream_name = "jz4740", - .cpu_dai_name = "jz4740-i2s", - .platform_name = "jz4740-pcm-audio", - .codec_dai_name = "jz4740-hifi", - .codec_name = "jz4740-codec", - .init = qi_lb60_codec_init, -}; - -static struct snd_soc_card qi_lb60 = { - .name = "QI LB60", - .owner = THIS_MODULE, - .dai_link = &qi_lb60_dai, - .num_links = 1, - - .dapm_widgets = qi_lb60_widgets, - .num_dapm_widgets = ARRAY_SIZE(qi_lb60_widgets), - .dapm_routes = qi_lb60_routes, - .num_dapm_routes = ARRAY_SIZE(qi_lb60_routes), -}; - -static const struct gpio qi_lb60_gpios[] = { - { QI_LB60_SND_GPIO, GPIOF_OUT_INIT_LOW, "SND" }, - { QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" }, -}; - -static int __devinit qi_lb60_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &qi_lb60; - int ret; - - ret = gpio_request_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); - if (ret) - return ret; - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); - } - return ret; -} - -static int __devexit qi_lb60_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios)); - return 0; -} - -static struct platform_driver qi_lb60_driver = { - .driver = { - .name = "qi-lb60-audio", - .owner = THIS_MODULE, - }, - .probe = qi_lb60_probe, - .remove = __devexit_p(qi_lb60_remove), -}; - -module_platform_driver(qi_lb60_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:qi-lb60-audio"); diff --git a/ANDROID_3.4.5/sound/soc/kirkwood/Kconfig b/ANDROID_3.4.5/sound/soc/kirkwood/Kconfig deleted file mode 100644 index c62d7152..00000000 --- a/ANDROID_3.4.5/sound/soc/kirkwood/Kconfig +++ /dev/null @@ -1,30 +0,0 @@ -config SND_KIRKWOOD_SOC - tristate "SoC Audio for the Marvell Kirkwood chip" - depends on ARCH_KIRKWOOD - help - Say Y or M if you want to add support for codecs attached to - the Kirkwood I2S interface. You will also need to select the - audio interfaces to support below. - -config SND_KIRKWOOD_SOC_I2S - tristate - -config SND_KIRKWOOD_SOC_OPENRD - tristate "SoC Audio support for Kirkwood Openrd Client" - depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE) - depends on I2C - select SND_KIRKWOOD_SOC_I2S - select SND_SOC_CS42L51 - help - Say Y if you want to add support for SoC audio on - Openrd Client. - -config SND_KIRKWOOD_SOC_T5325 - tristate "SoC Audio support for HP t5325" - depends on SND_KIRKWOOD_SOC && MACH_T5325 && I2C - select SND_KIRKWOOD_SOC_I2S - select SND_SOC_ALC5623 - help - Say Y if you want to add support for SoC audio on - the HP t5325 thin client. - diff --git a/ANDROID_3.4.5/sound/soc/kirkwood/Makefile b/ANDROID_3.4.5/sound/soc/kirkwood/Makefile deleted file mode 100644 index 3e62ae9e..00000000 --- a/ANDROID_3.4.5/sound/soc/kirkwood/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -snd-soc-kirkwood-objs := kirkwood-dma.o -snd-soc-kirkwood-i2s-objs := kirkwood-i2s.o - -obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o -obj-$(CONFIG_SND_KIRKWOOD_SOC_I2S) += snd-soc-kirkwood-i2s.o - -snd-soc-openrd-objs := kirkwood-openrd.o -snd-soc-t5325-objs := kirkwood-t5325.o - -obj-$(CONFIG_SND_KIRKWOOD_SOC_OPENRD) += snd-soc-openrd.o -obj-$(CONFIG_SND_KIRKWOOD_SOC_T5325) += snd-soc-t5325.o diff --git a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-dma.c b/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-dma.c deleted file mode 100644 index b9f16598..00000000 --- a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-dma.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * kirkwood-dma.c - * - * (c) 2010 Arnaud Patard - * (c) 2010 Arnaud Patard - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "kirkwood.h" - -#define KIRKWOOD_RATES \ - (SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) -#define KIRKWOOD_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE) - -struct kirkwood_dma_priv { - struct snd_pcm_substream *play_stream; - struct snd_pcm_substream *rec_stream; - struct kirkwood_dma_data *data; -}; - -static struct snd_pcm_hardware kirkwood_dma_snd_hw = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE), - .formats = KIRKWOOD_FORMATS, - .rates = KIRKWOOD_RATES, - .rate_min = 44100, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS, - .period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES, - .period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES, - .periods_min = KIRKWOOD_SND_MIN_PERIODS, - .periods_max = KIRKWOOD_SND_MAX_PERIODS, - .fifo_size = 0, -}; - -static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32); - -static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id) -{ - struct kirkwood_dma_priv *prdata = dev_id; - struct kirkwood_dma_data *priv = prdata->data; - unsigned long mask, status, cause; - - mask = readl(priv->io + KIRKWOOD_INT_MASK); - status = readl(priv->io + KIRKWOOD_INT_CAUSE) & mask; - - cause = readl(priv->io + KIRKWOOD_ERR_CAUSE); - if (unlikely(cause)) { - printk(KERN_WARNING "%s: got err interrupt 0x%lx\n", - __func__, cause); - writel(cause, priv->io + KIRKWOOD_ERR_CAUSE); - return IRQ_HANDLED; - } - - /* we've enabled only bytes interrupts ... */ - if (status & ~(KIRKWOOD_INT_CAUSE_PLAY_BYTES | \ - KIRKWOOD_INT_CAUSE_REC_BYTES)) { - printk(KERN_WARNING "%s: unexpected interrupt %lx\n", - __func__, status); - return IRQ_NONE; - } - - /* ack int */ - writel(status, priv->io + KIRKWOOD_INT_CAUSE); - - if (status & KIRKWOOD_INT_CAUSE_PLAY_BYTES) - snd_pcm_period_elapsed(prdata->play_stream); - - if (status & KIRKWOOD_INT_CAUSE_REC_BYTES) - snd_pcm_period_elapsed(prdata->rec_stream); - - return IRQ_HANDLED; -} - -static void -kirkwood_dma_conf_mbus_windows(void __iomem *base, int win, - unsigned long dma, - const struct mbus_dram_target_info *dram) -{ - int i; - - /* First disable and clear windows */ - writel(0, base + KIRKWOOD_AUDIO_WIN_CTRL_REG(win)); - writel(0, base + KIRKWOOD_AUDIO_WIN_BASE_REG(win)); - - /* try to find matching cs for current dma address */ - for (i = 0; i < dram->num_cs; i++) { - const struct mbus_dram_window *cs = dram->cs + i; - if ((cs->base & 0xffff0000) < (dma & 0xffff0000)) { - writel(cs->base & 0xffff0000, - base + KIRKWOOD_AUDIO_WIN_BASE_REG(win)); - writel(((cs->size - 1) & 0xffff0000) | - (cs->mbus_attr << 8) | - (dram->mbus_dram_target_id << 4) | 1, - base + KIRKWOOD_AUDIO_WIN_CTRL_REG(win)); - } - } -} - -static int kirkwood_dma_open(struct snd_pcm_substream *substream) -{ - int err; - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct snd_soc_platform *platform = soc_runtime->platform; - struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; - struct kirkwood_dma_data *priv; - struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); - const struct mbus_dram_target_info *dram; - unsigned long addr; - - priv = snd_soc_dai_get_dma_data(cpu_dai, substream); - snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw); - - /* Ensure that all constraints linked to dma burst are fulfilled */ - err = snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - priv->burst * 2, - KIRKWOOD_AUDIO_BUF_MAX-1); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - priv->burst); - if (err < 0) - return err; - - err = snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - priv->burst); - if (err < 0) - return err; - - if (prdata == NULL) { - prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL); - if (prdata == NULL) - return -ENOMEM; - - prdata->data = priv; - - err = request_irq(priv->irq, kirkwood_dma_irq, IRQF_SHARED, - "kirkwood-i2s", prdata); - if (err) { - kfree(prdata); - return -EBUSY; - } - - snd_soc_platform_set_drvdata(platform, prdata); - - /* - * Enable Error interrupts. We're only ack'ing them but - * it's useful for diagnostics - */ - writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK); - } - - dram = mv_mbus_dram_info(); - addr = virt_to_phys(substream->dma_buffer.area); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - prdata->play_stream = substream; - kirkwood_dma_conf_mbus_windows(priv->io, - KIRKWOOD_PLAYBACK_WIN, addr, dram); - } else { - prdata->rec_stream = substream; - kirkwood_dma_conf_mbus_windows(priv->io, - KIRKWOOD_RECORD_WIN, addr, dram); - } - - return 0; -} - -static int kirkwood_dma_close(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; - struct snd_soc_platform *platform = soc_runtime->platform; - struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform); - struct kirkwood_dma_data *priv; - - priv = snd_soc_dai_get_dma_data(cpu_dai, substream); - - if (!prdata || !priv) - return 0; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - prdata->play_stream = NULL; - else - prdata->rec_stream = NULL; - - if (!prdata->play_stream && !prdata->rec_stream) { - writel(0, priv->io + KIRKWOOD_ERR_MASK); - free_irq(priv->irq, prdata); - kfree(prdata); - snd_soc_platform_set_drvdata(platform, NULL); - } - - return 0; -} - -static int kirkwood_dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - - return 0; -} - -static int kirkwood_dma_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - -static int kirkwood_dma_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; - struct kirkwood_dma_data *priv; - unsigned long size, count; - - priv = snd_soc_dai_get_dma_data(cpu_dai, substream); - - /* compute buffer size in term of "words" as requested in specs */ - size = frames_to_bytes(runtime, runtime->buffer_size); - size = (size>>2)-1; - count = snd_pcm_lib_period_bytes(substream); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - writel(count, priv->io + KIRKWOOD_PLAY_BYTE_INT_COUNT); - writel(runtime->dma_addr, priv->io + KIRKWOOD_PLAY_BUF_ADDR); - writel(size, priv->io + KIRKWOOD_PLAY_BUF_SIZE); - } else { - writel(count, priv->io + KIRKWOOD_REC_BYTE_INT_COUNT); - writel(runtime->dma_addr, priv->io + KIRKWOOD_REC_BUF_ADDR); - writel(size, priv->io + KIRKWOOD_REC_BUF_SIZE); - } - - - return 0; -} - -static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream - *substream) -{ - struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai; - struct kirkwood_dma_data *priv; - snd_pcm_uframes_t count; - - priv = snd_soc_dai_get_dma_data(cpu_dai, substream); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - count = bytes_to_frames(substream->runtime, - readl(priv->io + KIRKWOOD_PLAY_BYTE_COUNT)); - else - count = bytes_to_frames(substream->runtime, - readl(priv->io + KIRKWOOD_REC_BYTE_COUNT)); - - return count; -} - -struct snd_pcm_ops kirkwood_dma_ops = { - .open = kirkwood_dma_open, - .close = kirkwood_dma_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = kirkwood_dma_hw_params, - .hw_free = kirkwood_dma_hw_free, - .prepare = kirkwood_dma_prepare, - .pointer = kirkwood_dma_pointer, -}; - -static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = kirkwood_dma_snd_hw.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->area = dma_alloc_coherent(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - buf->private_data = NULL; - - return 0; -} - -static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &kirkwood_dma_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = kirkwood_dma_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - return ret; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = kirkwood_dma_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - return ret; - } - - return 0; -} - -static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_coherent(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - -static struct snd_soc_platform_driver kirkwood_soc_platform = { - .ops = &kirkwood_dma_ops, - .pcm_new = kirkwood_dma_new, - .pcm_free = kirkwood_dma_free_dma_buffers, -}; - -static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform); -} - -static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver kirkwood_pcm_driver = { - .driver = { - .name = "kirkwood-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = kirkwood_soc_platform_probe, - .remove = __devexit_p(kirkwood_soc_platform_remove), -}; - -module_platform_driver(kirkwood_pcm_driver); - -MODULE_AUTHOR("Arnaud Patard "); -MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:kirkwood-pcm-audio"); diff --git a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-i2s.c b/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-i2s.c deleted file mode 100644 index 3cb9aa42..00000000 --- a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-i2s.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * kirkwood-i2s.c - * - * (c) 2010 Arnaud Patard - * (c) 2010 Arnaud Patard - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "kirkwood.h" - -#define DRV_NAME "kirkwood-i2s" - -#define KIRKWOOD_I2S_RATES \ - (SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) -#define KIRKWOOD_I2S_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE) - -static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long mask; - unsigned long value; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - mask = KIRKWOOD_I2S_CTL_RJ; - break; - case SND_SOC_DAIFMT_LEFT_J: - mask = KIRKWOOD_I2S_CTL_LJ; - break; - case SND_SOC_DAIFMT_I2S: - mask = KIRKWOOD_I2S_CTL_I2S; - break; - default: - return -EINVAL; - } - - /* - * Set same format for playback and record - * This avoids some troubles. - */ - value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL); - value &= ~KIRKWOOD_I2S_CTL_JUST_MASK; - value |= mask; - writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL); - - value = readl(priv->io+KIRKWOOD_I2S_RECCTL); - value &= ~KIRKWOOD_I2S_CTL_JUST_MASK; - value |= mask; - writel(value, priv->io+KIRKWOOD_I2S_RECCTL); - - return 0; -} - -static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate) -{ - unsigned long value; - - value = KIRKWOOD_DCO_CTL_OFFSET_0; - switch (rate) { - default: - case 44100: - value |= KIRKWOOD_DCO_CTL_FREQ_11; - break; - case 48000: - value |= KIRKWOOD_DCO_CTL_FREQ_12; - break; - case 96000: - value |= KIRKWOOD_DCO_CTL_FREQ_24; - break; - } - writel(value, io + KIRKWOOD_DCO_CTL); - - /* wait for dco locked */ - do { - cpu_relax(); - value = readl(io + KIRKWOOD_DCO_SPCR_STATUS); - value &= KIRKWOOD_DCO_SPCR_STATUS; - } while (value == 0); -} - -static int kirkwood_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); - - snd_soc_dai_set_dma_data(dai, substream, priv); - return 0; -} - -static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); - unsigned int i2s_reg, reg; - unsigned long i2s_value, value; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - i2s_reg = KIRKWOOD_I2S_PLAYCTL; - reg = KIRKWOOD_PLAYCTL; - } else { - i2s_reg = KIRKWOOD_I2S_RECCTL; - reg = KIRKWOOD_RECCTL; - } - - /* set dco conf */ - kirkwood_set_dco(priv->io, params_rate(params)); - - i2s_value = readl(priv->io+i2s_reg); - i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK; - - value = readl(priv->io+reg); - value &= ~KIRKWOOD_PLAYCTL_SIZE_MASK; - - /* - * Size settings in play/rec i2s control regs and play/rec control - * regs must be the same. - */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16; - value |= KIRKWOOD_PLAYCTL_SIZE_16_C; - break; - /* - * doesn't work... S20_3LE != kirkwood 20bit format ? - * - case SNDRV_PCM_FORMAT_S20_3LE: - i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20; - value |= KIRKWOOD_PLAYCTL_SIZE_20; - break; - */ - case SNDRV_PCM_FORMAT_S24_LE: - i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24; - value |= KIRKWOOD_PLAYCTL_SIZE_24; - break; - case SNDRV_PCM_FORMAT_S32_LE: - i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32; - value |= KIRKWOOD_PLAYCTL_SIZE_32; - break; - default: - return -EINVAL; - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - value &= ~KIRKWOOD_PLAYCTL_MONO_MASK; - if (params_channels(params) == 1) - value |= KIRKWOOD_PLAYCTL_MONO_BOTH; - else - value |= KIRKWOOD_PLAYCTL_MONO_OFF; - } - - writel(i2s_value, priv->io+i2s_reg); - writel(value, priv->io+reg); - - return 0; -} - -static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); - unsigned long value; - - /* - * specs says KIRKWOOD_PLAYCTL must be read 2 times before - * changing it. So read 1 time here and 1 later. - */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* stop audio, enable interrupts */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value |= KIRKWOOD_PLAYCTL_PAUSE; - writel(value, priv->io + KIRKWOOD_PLAYCTL); - - value = readl(priv->io + KIRKWOOD_INT_MASK); - value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; - writel(value, priv->io + KIRKWOOD_INT_MASK); - - /* configure audio & enable i2s playback */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value &= ~KIRKWOOD_PLAYCTL_BURST_MASK; - value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE - | KIRKWOOD_PLAYCTL_SPDIF_EN); - - if (priv->burst == 32) - value |= KIRKWOOD_PLAYCTL_BURST_32; - else - value |= KIRKWOOD_PLAYCTL_BURST_128; - value |= KIRKWOOD_PLAYCTL_I2S_EN; - writel(value, priv->io + KIRKWOOD_PLAYCTL); - break; - - case SNDRV_PCM_TRIGGER_STOP: - /* stop audio, disable interrupts */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; - writel(value, priv->io + KIRKWOOD_PLAYCTL); - - value = readl(priv->io + KIRKWOOD_INT_MASK); - value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES; - writel(value, priv->io + KIRKWOOD_INT_MASK); - - /* disable all playbacks */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN); - writel(value, priv->io + KIRKWOOD_PLAYCTL); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; - writel(value, priv->io + KIRKWOOD_PLAYCTL); - break; - - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE); - writel(value, priv->io + KIRKWOOD_PLAYCTL); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); - unsigned long value; - - value = readl(priv->io + KIRKWOOD_RECCTL); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* stop audio, enable interrupts */ - value = readl(priv->io + KIRKWOOD_RECCTL); - value |= KIRKWOOD_RECCTL_PAUSE; - writel(value, priv->io + KIRKWOOD_RECCTL); - - value = readl(priv->io + KIRKWOOD_INT_MASK); - value |= KIRKWOOD_INT_CAUSE_REC_BYTES; - writel(value, priv->io + KIRKWOOD_INT_MASK); - - /* configure audio & enable i2s record */ - value = readl(priv->io + KIRKWOOD_RECCTL); - value &= ~KIRKWOOD_RECCTL_BURST_MASK; - value &= ~KIRKWOOD_RECCTL_MONO; - value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE - | KIRKWOOD_RECCTL_SPDIF_EN); - - if (priv->burst == 32) - value |= KIRKWOOD_RECCTL_BURST_32; - else - value |= KIRKWOOD_RECCTL_BURST_128; - value |= KIRKWOOD_RECCTL_I2S_EN; - - writel(value, priv->io + KIRKWOOD_RECCTL); - break; - - case SNDRV_PCM_TRIGGER_STOP: - /* stop audio, disable interrupts */ - value = readl(priv->io + KIRKWOOD_RECCTL); - value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; - writel(value, priv->io + KIRKWOOD_RECCTL); - - value = readl(priv->io + KIRKWOOD_INT_MASK); - value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES; - writel(value, priv->io + KIRKWOOD_INT_MASK); - - /* disable all records */ - value = readl(priv->io + KIRKWOOD_RECCTL); - value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); - writel(value, priv->io + KIRKWOOD_RECCTL); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - value = readl(priv->io + KIRKWOOD_RECCTL); - value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE; - writel(value, priv->io + KIRKWOOD_RECCTL); - break; - - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - value = readl(priv->io + KIRKWOOD_RECCTL); - value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE); - writel(value, priv->io + KIRKWOOD_RECCTL); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - return kirkwood_i2s_play_trigger(substream, cmd, dai); - else - return kirkwood_i2s_rec_trigger(substream, cmd, dai); - - return 0; -} - -static int kirkwood_i2s_probe(struct snd_soc_dai *dai) -{ - struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); - unsigned long value; - unsigned int reg_data; - - /* put system in a "safe" state : */ - /* disable audio interrupts */ - writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE); - writel(0, priv->io + KIRKWOOD_INT_MASK); - - reg_data = readl(priv->io + 0x1200); - reg_data &= (~(0x333FF8)); - reg_data |= 0x111D18; - writel(reg_data, priv->io + 0x1200); - - msleep(500); - - reg_data = readl(priv->io + 0x1200); - reg_data &= (~(0x333FF8)); - reg_data |= 0x111D18; - writel(reg_data, priv->io + 0x1200); - - /* disable playback/record */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value &= ~(KIRKWOOD_PLAYCTL_I2S_EN|KIRKWOOD_PLAYCTL_SPDIF_EN); - writel(value, priv->io + KIRKWOOD_PLAYCTL); - - value = readl(priv->io + KIRKWOOD_RECCTL); - value &= ~(KIRKWOOD_RECCTL_I2S_EN | KIRKWOOD_RECCTL_SPDIF_EN); - writel(value, priv->io + KIRKWOOD_RECCTL); - - return 0; - -} - -static int kirkwood_i2s_remove(struct snd_soc_dai *dai) -{ - return 0; -} - -static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { - .startup = kirkwood_i2s_startup, - .trigger = kirkwood_i2s_trigger, - .hw_params = kirkwood_i2s_hw_params, - .set_fmt = kirkwood_i2s_set_fmt, -}; - - -static struct snd_soc_dai_driver kirkwood_i2s_dai = { - .probe = kirkwood_i2s_probe, - .remove = kirkwood_i2s_remove, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = KIRKWOOD_I2S_RATES, - .formats = KIRKWOOD_I2S_FORMATS,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = KIRKWOOD_I2S_RATES, - .formats = KIRKWOOD_I2S_FORMATS,}, - .ops = &kirkwood_i2s_dai_ops, -}; - -static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) -{ - struct resource *mem; - struct kirkwood_asoc_platform_data *data = - pdev->dev.platform_data; - struct kirkwood_dma_data *priv; - int err; - - priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "allocation failed\n"); - err = -ENOMEM; - goto error; - } - dev_set_drvdata(&pdev->dev, priv); - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "platform_get_resource failed\n"); - err = -ENXIO; - goto err_alloc; - } - - priv->mem = request_mem_region(mem->start, SZ_16K, DRV_NAME); - if (!priv->mem) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - err = -EBUSY; - goto err_alloc; - } - - priv->io = ioremap(priv->mem->start, SZ_16K); - if (!priv->io) { - dev_err(&pdev->dev, "ioremap failed\n"); - err = -ENOMEM; - goto err_iomem; - } - - priv->irq = platform_get_irq(pdev, 0); - if (priv->irq <= 0) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); - err = -ENXIO; - goto err_ioremap; - } - - if (!data) { - dev_err(&pdev->dev, "no platform data ?!\n"); - err = -EINVAL; - goto err_ioremap; - } - - priv->burst = data->burst; - - return snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai); - -err_ioremap: - iounmap(priv->io); -err_iomem: - release_mem_region(priv->mem->start, SZ_16K); -err_alloc: - kfree(priv); -error: - return err; -} - -static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev) -{ - struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); - - snd_soc_unregister_dai(&pdev->dev); - iounmap(priv->io); - release_mem_region(priv->mem->start, SZ_16K); - kfree(priv); - - return 0; -} - -static struct platform_driver kirkwood_i2s_driver = { - .probe = kirkwood_i2s_dev_probe, - .remove = __devexit_p(kirkwood_i2s_dev_remove), - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(kirkwood_i2s_driver); - -/* Module information */ -MODULE_AUTHOR("Arnaud Patard, "); -MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:kirkwood-i2s"); diff --git a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-openrd.c b/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-openrd.c deleted file mode 100644 index 80bd59c3..00000000 --- a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-openrd.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * kirkwood-openrd.c - * - * (c) 2010 Arnaud Patard - * (c) 2010 Arnaud Patard - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../codecs/cs42l51.h" - -static int openrd_client_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - unsigned int freq; - - switch (params_rate(params)) { - default: - case 44100: - freq = 11289600; - break; - case 48000: - freq = 12288000; - break; - case 96000: - freq = 24576000; - break; - } - - return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); - -} - -static struct snd_soc_ops openrd_client_ops = { - .hw_params = openrd_client_hw_params, -}; - - -static struct snd_soc_dai_link openrd_client_dai[] = { -{ - .name = "CS42L51", - .stream_name = "CS42L51 HiFi", - .cpu_dai_name = "kirkwood-i2s", - .platform_name = "kirkwood-pcm-audio", - .codec_dai_name = "cs42l51-hifi", - .codec_name = "cs42l51-codec.0-004a", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, - .ops = &openrd_client_ops, -}, -}; - - -static struct snd_soc_card openrd_client = { - .name = "OpenRD Client", - .owner = THIS_MODULE, - .dai_link = openrd_client_dai, - .num_links = ARRAY_SIZE(openrd_client_dai), -}; - -static int __devinit openrd_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &openrd_client; - int ret; - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - return ret; -} - -static int __devexit openrd_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - return 0; -} - -static struct platform_driver openrd_driver = { - .driver = { - .name = "openrd-client-audio", - .owner = THIS_MODULE, - }, - .probe = openrd_probe, - .remove = __devexit_p(openrd_remove), -}; - -module_platform_driver(openrd_driver); - -/* Module information */ -MODULE_AUTHOR("Arnaud Patard "); -MODULE_DESCRIPTION("ALSA SoC OpenRD Client"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:openrd-client-audio"); diff --git a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-t5325.c b/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-t5325.c deleted file mode 100644 index f8983635..00000000 --- a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood-t5325.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * kirkwood-t5325.c - * - * (c) 2010 Arnaud Patard - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../codecs/alc5623.h" - -static int t5325_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - unsigned int freq; - - freq = params_rate(params) * 256; - - return snd_soc_dai_set_sysclk(codec_dai, 0, freq, SND_SOC_CLOCK_IN); - -} - -static struct snd_soc_ops t5325_ops = { - .hw_params = t5325_hw_params, -}; - -static const struct snd_soc_dapm_widget t5325_dapm_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), -}; - -static const struct snd_soc_dapm_route t5325_route[] = { - { "Headphone Jack", NULL, "HPL" }, - { "Headphone Jack", NULL, "HPR" }, - - {"Speaker", NULL, "SPKOUT"}, - {"Speaker", NULL, "SPKOUTN"}, - - { "MIC1", NULL, "Mic Jack" }, - { "MIC2", NULL, "Mic Jack" }, -}; - -static int t5325_dai_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_enable_pin(dapm, "Mic Jack"); - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - snd_soc_dapm_enable_pin(dapm, "Speaker"); - - return 0; -} - -static struct snd_soc_dai_link t5325_dai[] = { -{ - .name = "ALC5621", - .stream_name = "ALC5621 HiFi", - .cpu_dai_name = "kirkwood-i2s", - .platform_name = "kirkwood-pcm-audio", - .codec_dai_name = "alc5621-hifi", - .codec_name = "alc562x-codec.0-001a", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS, - .ops = &t5325_ops, - .init = t5325_dai_init, -}, -}; - -static struct snd_soc_card t5325 = { - .name = "t5325", - .owner = THIS_MODULE, - .dai_link = t5325_dai, - .num_links = ARRAY_SIZE(t5325_dai), - - .dapm_widgets = t5325_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(t5325_dapm_widgets), - .dapm_routes = t5325_route, - .num_dapm_routes = ARRAY_SIZE(t5325_route), -}; - -static int __devinit t5325_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &t5325; - int ret; - - card->dev = &pdev->dev; - - ret = snd_soc_register_card(card); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - return ret; -} - -static int __devexit t5325_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - return 0; -} - -static struct platform_driver t5325_driver = { - .driver = { - .name = "t5325-audio", - .owner = THIS_MODULE, - }, - .probe = t5325_probe, - .remove = __devexit_p(t5325_remove), -}; - -module_platform_driver(t5325_driver); - -MODULE_AUTHOR("Arnaud Patard "); -MODULE_DESCRIPTION("ALSA SoC t5325 audio client"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:t5325-audio"); diff --git a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood.h b/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood.h deleted file mode 100644 index 9047436b..00000000 --- a/ANDROID_3.4.5/sound/soc/kirkwood/kirkwood.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * kirkwood.h - * - * (c) 2010 Arnaud Patard - * - * 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. - */ - -#ifndef _KIRKWOOD_AUDIO_H -#define _KIRKWOOD_AUDIO_H - -#define KIRKWOOD_RECORD_WIN 0 -#define KIRKWOOD_PLAYBACK_WIN 1 -#define KIRKWOOD_MAX_AUDIO_WIN 2 - -#define KIRKWOOD_AUDIO_WIN_BASE_REG(win) (0xA00 + ((win)<<3)) -#define KIRKWOOD_AUDIO_WIN_CTRL_REG(win) (0xA04 + ((win)<<3)) - - -#define KIRKWOOD_RECCTL 0x1000 -#define KIRKWOOD_RECCTL_SPDIF_EN (1<<11) -#define KIRKWOOD_RECCTL_I2S_EN (1<<10) -#define KIRKWOOD_RECCTL_PAUSE (1<<9) -#define KIRKWOOD_RECCTL_MUTE (1<<8) -#define KIRKWOOD_RECCTL_BURST_MASK (3<<5) -#define KIRKWOOD_RECCTL_BURST_128 (2<<5) -#define KIRKWOOD_RECCTL_BURST_32 (1<<5) -#define KIRKWOOD_RECCTL_MONO (1<<4) -#define KIRKWOOD_RECCTL_MONO_CHAN_RIGHT (1<<3) -#define KIRKWOOD_RECCTL_MONO_CHAN_LEFT (0<<3) -#define KIRKWOOD_RECCTL_SIZE_MASK (7<<0) -#define KIRKWOOD_RECCTL_SIZE_16 (7<<0) -#define KIRKWOOD_RECCTL_SIZE_16_C (3<<0) -#define KIRKWOOD_RECCTL_SIZE_20 (2<<0) -#define KIRKWOOD_RECCTL_SIZE_24 (1<<0) -#define KIRKWOOD_RECCTL_SIZE_32 (0<<0) - -#define KIRKWOOD_REC_BUF_ADDR 0x1004 -#define KIRKWOOD_REC_BUF_SIZE 0x1008 -#define KIRKWOOD_REC_BYTE_COUNT 0x100C - -#define KIRKWOOD_PLAYCTL 0x1100 -#define KIRKWOOD_PLAYCTL_PLAY_BUSY (1<<16) -#define KIRKWOOD_PLAYCTL_BURST_MASK (3<<11) -#define KIRKWOOD_PLAYCTL_BURST_128 (2<<11) -#define KIRKWOOD_PLAYCTL_BURST_32 (1<<11) -#define KIRKWOOD_PLAYCTL_PAUSE (1<<9) -#define KIRKWOOD_PLAYCTL_SPDIF_MUTE (1<<8) -#define KIRKWOOD_PLAYCTL_MONO_MASK (3<<5) -#define KIRKWOOD_PLAYCTL_MONO_BOTH (3<<5) -#define KIRKWOOD_PLAYCTL_MONO_OFF (0<<5) -#define KIRKWOOD_PLAYCTL_I2S_MUTE (1<<7) -#define KIRKWOOD_PLAYCTL_SPDIF_EN (1<<4) -#define KIRKWOOD_PLAYCTL_I2S_EN (1<<3) -#define KIRKWOOD_PLAYCTL_SIZE_MASK (7<<0) -#define KIRKWOOD_PLAYCTL_SIZE_16 (7<<0) -#define KIRKWOOD_PLAYCTL_SIZE_16_C (3<<0) -#define KIRKWOOD_PLAYCTL_SIZE_20 (2<<0) -#define KIRKWOOD_PLAYCTL_SIZE_24 (1<<0) -#define KIRKWOOD_PLAYCTL_SIZE_32 (0<<0) - -#define KIRKWOOD_PLAY_BUF_ADDR 0x1104 -#define KIRKWOOD_PLAY_BUF_SIZE 0x1108 -#define KIRKWOOD_PLAY_BYTE_COUNT 0x110C - -#define KIRKWOOD_DCO_CTL 0x1204 -#define KIRKWOOD_DCO_CTL_OFFSET_MASK (0xFFF<<2) -#define KIRKWOOD_DCO_CTL_OFFSET_0 (0x800<<2) -#define KIRKWOOD_DCO_CTL_FREQ_MASK (3<<0) -#define KIRKWOOD_DCO_CTL_FREQ_11 (0<<0) -#define KIRKWOOD_DCO_CTL_FREQ_12 (1<<0) -#define KIRKWOOD_DCO_CTL_FREQ_24 (2<<0) - -#define KIRKWOOD_DCO_SPCR_STATUS 0x120c -#define KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK (1<<16) - -#define KIRKWOOD_ERR_CAUSE 0x1300 -#define KIRKWOOD_ERR_MASK 0x1304 - -#define KIRKWOOD_INT_CAUSE 0x1308 -#define KIRKWOOD_INT_MASK 0x130C -#define KIRKWOOD_INT_CAUSE_PLAY_BYTES (1<<14) -#define KIRKWOOD_INT_CAUSE_REC_BYTES (1<<13) -#define KIRKWOOD_INT_CAUSE_DMA_PLAY_END (1<<7) -#define KIRKWOOD_INT_CAUSE_DMA_PLAY_3Q (1<<6) -#define KIRKWOOD_INT_CAUSE_DMA_PLAY_HALF (1<<5) -#define KIRKWOOD_INT_CAUSE_DMA_PLAY_1Q (1<<4) -#define KIRKWOOD_INT_CAUSE_DMA_REC_END (1<<3) -#define KIRKWOOD_INT_CAUSE_DMA_REC_3Q (1<<2) -#define KIRKWOOD_INT_CAUSE_DMA_REC_HALF (1<<1) -#define KIRKWOOD_INT_CAUSE_DMA_REC_1Q (1<<0) - -#define KIRKWOOD_REC_BYTE_INT_COUNT 0x1310 -#define KIRKWOOD_PLAY_BYTE_INT_COUNT 0x1314 -#define KIRKWOOD_BYTE_INT_COUNT_MASK 0xffffff - -#define KIRKWOOD_I2S_PLAYCTL 0x2508 -#define KIRKWOOD_I2S_RECCTL 0x2408 -#define KIRKWOOD_I2S_CTL_JUST_MASK (0xf<<26) -#define KIRKWOOD_I2S_CTL_LJ (0<<26) -#define KIRKWOOD_I2S_CTL_I2S (5<<26) -#define KIRKWOOD_I2S_CTL_RJ (8<<26) -#define KIRKWOOD_I2S_CTL_SIZE_MASK (3<<30) -#define KIRKWOOD_I2S_CTL_SIZE_16 (3<<30) -#define KIRKWOOD_I2S_CTL_SIZE_20 (2<<30) -#define KIRKWOOD_I2S_CTL_SIZE_24 (1<<30) -#define KIRKWOOD_I2S_CTL_SIZE_32 (0<<30) - -#define KIRKWOOD_AUDIO_BUF_MAX (16*1024*1024) - -/* Theses values come from the marvell alsa driver */ -/* need to find where they come from */ -#define KIRKWOOD_SND_MIN_PERIODS 8 -#define KIRKWOOD_SND_MAX_PERIODS 16 -#define KIRKWOOD_SND_MIN_PERIOD_BYTES 0x4000 -#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000 - -struct kirkwood_dma_data { - struct resource *mem; - void __iomem *io; - int irq; - int burst; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/mid-x86/Kconfig b/ANDROID_3.4.5/sound/soc/mid-x86/Kconfig deleted file mode 100644 index 61c10bf5..00000000 --- a/ANDROID_3.4.5/sound/soc/mid-x86/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -config SND_MFLD_MACHINE - tristate "SOC Machine Audio driver for Intel Medfield MID platform" - depends on INTEL_SCU_IPC - select SND_SOC_SN95031 - select SND_SST_PLATFORM - help - This adds support for ASoC machine driver for Intel(R) MID Medfield platform - used as alsa device in audio substem in Intel(R) MID devices - Say Y if you have such a device - If unsure select "N". - -config SND_SST_PLATFORM - tristate diff --git a/ANDROID_3.4.5/sound/soc/mid-x86/Makefile b/ANDROID_3.4.5/sound/soc/mid-x86/Makefile deleted file mode 100644 index 63988333..00000000 --- a/ANDROID_3.4.5/sound/soc/mid-x86/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -snd-soc-sst-platform-objs := sst_platform.o -snd-soc-mfld-machine-objs := mfld_machine.o - -obj-$(CONFIG_SND_SST_PLATFORM) += snd-soc-sst-platform.o -obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o diff --git a/ANDROID_3.4.5/sound/soc/mid-x86/mfld_machine.c b/ANDROID_3.4.5/sound/soc/mid-x86/mfld_machine.c deleted file mode 100644 index 2937e54d..00000000 --- a/ANDROID_3.4.5/sound/soc/mid-x86/mfld_machine.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform - * - * Copyright (C) 2010 Intel Corp - * Author: Vinod Koul - * Author: Harsha Priya - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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; version 2 of the License. - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../codecs/sn95031.h" - -#define MID_MONO 1 -#define MID_STEREO 2 -#define MID_MAX_CAP 5 -#define MFLD_JACK_INSERT 0x04 - -enum soc_mic_bias_zones { - MFLD_MV_START = 0, - /* mic bias volutage range for Headphones*/ - MFLD_MV_HP = 400, - /* mic bias volutage range for American Headset*/ - MFLD_MV_AM_HS = 650, - /* mic bias volutage range for Headset*/ - MFLD_MV_HS = 2000, - MFLD_MV_UNDEFINED, -}; - -static unsigned int hs_switch; -static unsigned int lo_dac; - -struct mfld_mc_private { - void __iomem *int_base; - u8 interrupt_status; -}; - -struct snd_soc_jack mfld_jack; - -/*Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin mfld_jack_pins[] = { - { - .pin = "Headphones", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "AMIC1", - .mask = SND_JACK_MICROPHONE, - }, -}; - -/* jack detection voltage zones */ -static struct snd_soc_jack_zone mfld_zones[] = { - {MFLD_MV_START, MFLD_MV_AM_HS, SND_JACK_HEADPHONE}, - {MFLD_MV_AM_HS, MFLD_MV_HS, SND_JACK_HEADSET}, -}; - -/* sound card controls */ -static const char *headset_switch_text[] = {"Earpiece", "Headset"}; - -static const char *lo_text[] = {"Vibra", "Headset", "IHF", "None"}; - -static const struct soc_enum headset_enum = - SOC_ENUM_SINGLE_EXT(2, headset_switch_text); - -static const struct soc_enum lo_enum = - SOC_ENUM_SINGLE_EXT(4, lo_text); - -static int headset_get_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = hs_switch; - return 0; -} - -static int headset_set_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.integer.value[0] == hs_switch) - return 0; - - if (ucontrol->value.integer.value[0]) { - pr_debug("hs_set HS path\n"); - snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); - } else { - pr_debug("hs_set EP path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); - } - snd_soc_dapm_sync(&codec->dapm); - hs_switch = ucontrol->value.integer.value[0]; - - return 0; -} - -static void lo_enable_out_pins(struct snd_soc_codec *codec) -{ - snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL"); - snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR"); - snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL"); - snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR"); - snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT"); - snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT"); - if (hs_switch) { - snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); - } else { - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); - } -} - -static int lo_get_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = lo_dac; - return 0; -} - -static int lo_set_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - - if (ucontrol->value.integer.value[0] == lo_dac) - return 0; - - /* we dont want to work with last state of lineout so just enable all - * pins and then disable pins not required - */ - lo_enable_out_pins(codec); - switch (ucontrol->value.integer.value[0]) { - case 0: - pr_debug("set vibra path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT"); - snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); - break; - - case 1: - pr_debug("set hs path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); - snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); - break; - - case 2: - pr_debug("set spkr path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL"); - snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); - break; - - case 3: - pr_debug("set null path\n"); - snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL"); - snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR"); - snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); - break; - } - snd_soc_dapm_sync(&codec->dapm); - lo_dac = ucontrol->value.integer.value[0]; - return 0; -} - -static const struct snd_kcontrol_new mfld_snd_controls[] = { - SOC_ENUM_EXT("Playback Switch", headset_enum, - headset_get_switch, headset_set_switch), - SOC_ENUM_EXT("Lineout Mux", lo_enum, - lo_get_switch, lo_set_switch), -}; - -static const struct snd_soc_dapm_widget mfld_widgets[] = { - SND_SOC_DAPM_HP("Headphones", NULL), - SND_SOC_DAPM_MIC("Mic", NULL), -}; - -static const struct snd_soc_dapm_route mfld_map[] = { - {"Headphones", NULL, "HPOUTR"}, - {"Headphones", NULL, "HPOUTL"}, - {"Mic", NULL, "AMIC1"}, -}; - -static void mfld_jack_check(unsigned int intr_status) -{ - struct mfld_jack_data jack_data; - - jack_data.mfld_jack = &mfld_jack; - jack_data.intr_id = intr_status; - - sn95031_jack_detection(&jack_data); - /* TODO: add american headset detection post gpiolib support */ -} - -static int mfld_init(struct snd_soc_pcm_runtime *runtime) -{ - struct snd_soc_codec *codec = runtime->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret_val; - - /* Add jack sense widgets */ - snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets)); - - /* Set up the map */ - snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map)); - - /* always connected */ - snd_soc_dapm_enable_pin(dapm, "Headphones"); - snd_soc_dapm_enable_pin(dapm, "Mic"); - - ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls, - ARRAY_SIZE(mfld_snd_controls)); - if (ret_val) { - pr_err("soc_add_controls failed %d", ret_val); - return ret_val; - } - /* default is earpiece pin, userspace sets it explcitly */ - snd_soc_dapm_disable_pin(dapm, "Headphones"); - /* default is lineout NC, userspace sets it explcitly */ - snd_soc_dapm_disable_pin(dapm, "LINEOUTL"); - snd_soc_dapm_disable_pin(dapm, "LINEOUTR"); - lo_dac = 3; - hs_switch = 0; - /* we dont use linein in this so set to NC */ - snd_soc_dapm_disable_pin(dapm, "LINEINL"); - snd_soc_dapm_disable_pin(dapm, "LINEINR"); - - /* Headset and button jack detection */ - ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | - SND_JACK_BTN_1, &mfld_jack); - if (ret_val) { - pr_err("jack creation failed\n"); - return ret_val; - } - - ret_val = snd_soc_jack_add_pins(&mfld_jack, - ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins); - if (ret_val) { - pr_err("adding jack pins failed\n"); - return ret_val; - } - ret_val = snd_soc_jack_add_zones(&mfld_jack, - ARRAY_SIZE(mfld_zones), mfld_zones); - if (ret_val) { - pr_err("adding jack zones failed\n"); - return ret_val; - } - - /* we want to check if anything is inserted at boot, - * so send a fake event to codec and it will read adc - * to find if anything is there or not */ - mfld_jack_check(MFLD_JACK_INSERT); - return ret_val; -} - -static struct snd_soc_dai_link mfld_msic_dailink[] = { - { - .name = "Medfield Headset", - .stream_name = "Headset", - .cpu_dai_name = "Headset-cpu-dai", - .codec_dai_name = "SN95031 Headset", - .codec_name = "sn95031", - .platform_name = "sst-platform", - .init = mfld_init, - }, - { - .name = "Medfield Speaker", - .stream_name = "Speaker", - .cpu_dai_name = "Speaker-cpu-dai", - .codec_dai_name = "SN95031 Speaker", - .codec_name = "sn95031", - .platform_name = "sst-platform", - .init = NULL, - }, - { - .name = "Medfield Vibra", - .stream_name = "Vibra1", - .cpu_dai_name = "Vibra1-cpu-dai", - .codec_dai_name = "SN95031 Vibra1", - .codec_name = "sn95031", - .platform_name = "sst-platform", - .init = NULL, - }, - { - .name = "Medfield Haptics", - .stream_name = "Vibra2", - .cpu_dai_name = "Vibra2-cpu-dai", - .codec_dai_name = "SN95031 Vibra2", - .codec_name = "sn95031", - .platform_name = "sst-platform", - .init = NULL, - }, -}; - -/* SoC card */ -static struct snd_soc_card snd_soc_card_mfld = { - .name = "medfield_audio", - .owner = THIS_MODULE, - .dai_link = mfld_msic_dailink, - .num_links = ARRAY_SIZE(mfld_msic_dailink), -}; - -static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev) -{ - struct mfld_mc_private *mc_private = (struct mfld_mc_private *) dev; - - memcpy_fromio(&mc_private->interrupt_status, - ((void *)(mc_private->int_base)), - sizeof(u8)); - return IRQ_WAKE_THREAD; -} - -static irqreturn_t snd_mfld_jack_detection(int irq, void *data) -{ - struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data; - - if (mfld_jack.codec == NULL) - return IRQ_HANDLED; - mfld_jack_check(mc_drv_ctx->interrupt_status); - - return IRQ_HANDLED; -} - -static int __devinit snd_mfld_mc_probe(struct platform_device *pdev) -{ - int ret_val = 0, irq; - struct mfld_mc_private *mc_drv_ctx; - struct resource *irq_mem; - - pr_debug("snd_mfld_mc_probe called\n"); - - /* retrive the irq number */ - irq = platform_get_irq(pdev, 0); - - /* audio interrupt base of SRAM location where - * interrupts are stored by System FW */ - mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC); - if (!mc_drv_ctx) { - pr_err("allocation failed\n"); - return -ENOMEM; - } - - irq_mem = platform_get_resource_byname( - pdev, IORESOURCE_MEM, "IRQ_BASE"); - if (!irq_mem) { - pr_err("no mem resource given\n"); - ret_val = -ENODEV; - goto unalloc; - } - mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start, - resource_size(irq_mem)); - if (!mc_drv_ctx->int_base) { - pr_err("Mapping of cache failed\n"); - ret_val = -ENOMEM; - goto unalloc; - } - /* register for interrupt */ - ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler, - snd_mfld_jack_detection, - IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx); - if (ret_val) { - pr_err("cannot register IRQ\n"); - goto unalloc; - } - /* register the soc card */ - snd_soc_card_mfld.dev = &pdev->dev; - ret_val = snd_soc_register_card(&snd_soc_card_mfld); - if (ret_val) { - pr_debug("snd_soc_register_card failed %d\n", ret_val); - goto freeirq; - } - platform_set_drvdata(pdev, mc_drv_ctx); - pr_debug("successfully exited probe\n"); - return ret_val; - -freeirq: - free_irq(irq, mc_drv_ctx); -unalloc: - kfree(mc_drv_ctx); - return ret_val; -} - -static int __devexit snd_mfld_mc_remove(struct platform_device *pdev) -{ - struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev); - - pr_debug("snd_mfld_mc_remove called\n"); - free_irq(platform_get_irq(pdev, 0), mc_drv_ctx); - snd_soc_unregister_card(&snd_soc_card_mfld); - kfree(mc_drv_ctx); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver snd_mfld_mc_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "msic_audio", - }, - .probe = snd_mfld_mc_probe, - .remove = __devexit_p(snd_mfld_mc_remove), -}; - -module_platform_driver(snd_mfld_mc_driver); - -MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver"); -MODULE_AUTHOR("Vinod Koul "); -MODULE_AUTHOR("Harsha Priya "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:msic-audio"); diff --git a/ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.c b/ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.c deleted file mode 100644 index d34563b1..00000000 --- a/ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * sst_platform.c - Intel MID Platform driver - * - * Copyright (C) 2010 Intel Corp - * Author: Vinod Koul - * Author: Harsha Priya - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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; version 2 of the License. - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * - */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include "sst_platform.h" - -static struct sst_device *sst; -static DEFINE_MUTEX(sst_lock); - -int sst_register_dsp(struct sst_device *dev) -{ - BUG_ON(!dev); - if (!try_module_get(dev->dev->driver->owner)) - return -ENODEV; - mutex_lock(&sst_lock); - if (sst) { - pr_err("we already have a device %s\n", sst->name); - module_put(dev->dev->driver->owner); - mutex_unlock(&sst_lock); - return -EEXIST; - } - pr_debug("registering device %s\n", dev->name); - sst = dev; - mutex_unlock(&sst_lock); - return 0; -} -EXPORT_SYMBOL_GPL(sst_register_dsp); - -int sst_unregister_dsp(struct sst_device *dev) -{ - BUG_ON(!dev); - if (dev != sst) - return -EINVAL; - - mutex_lock(&sst_lock); - - if (!sst) { - mutex_unlock(&sst_lock); - return -EIO; - } - - module_put(sst->dev->driver->owner); - pr_debug("unreg %s\n", sst->name); - sst = NULL; - mutex_unlock(&sst_lock); - return 0; -} -EXPORT_SYMBOL_GPL(sst_unregister_dsp); - -static struct snd_pcm_hardware sst_platform_pcm_hw = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_DOUBLE | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP| - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 | - SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 | - SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32), - .rates = (SNDRV_PCM_RATE_8000| - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000), - .rate_min = SST_MIN_RATE, - .rate_max = SST_MAX_RATE, - .channels_min = SST_MIN_CHANNEL, - .channels_max = SST_MAX_CHANNEL, - .buffer_bytes_max = SST_MAX_BUFFER, - .period_bytes_min = SST_MIN_PERIOD_BYTES, - .period_bytes_max = SST_MAX_PERIOD_BYTES, - .periods_min = SST_MIN_PERIODS, - .periods_max = SST_MAX_PERIODS, - .fifo_size = SST_FIFO_SIZE, -}; - -/* MFLD - MSIC */ -static struct snd_soc_dai_driver sst_platform_dai[] = { -{ - .name = "Headset-cpu-dai", - .id = 0, - .playback = { - .channels_min = SST_STEREO, - .channels_max = SST_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, - .capture = { - .channels_min = 1, - .channels_max = 5, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "Speaker-cpu-dai", - .id = 1, - .playback = { - .channels_min = SST_MONO, - .channels_max = SST_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "Vibra1-cpu-dai", - .id = 2, - .playback = { - .channels_min = SST_MONO, - .channels_max = SST_MONO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -{ - .name = "Vibra2-cpu-dai", - .id = 3, - .playback = { - .channels_min = SST_MONO, - .channels_max = SST_STEREO, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, - }, -}, -}; - -/* helper functions */ -static inline void sst_set_stream_status(struct sst_runtime_stream *stream, - int state) -{ - unsigned long flags; - spin_lock_irqsave(&stream->status_lock, flags); - stream->stream_status = state; - spin_unlock_irqrestore(&stream->status_lock, flags); -} - -static inline int sst_get_stream_status(struct sst_runtime_stream *stream) -{ - int state; - unsigned long flags; - - spin_lock_irqsave(&stream->status_lock, flags); - state = stream->stream_status; - spin_unlock_irqrestore(&stream->status_lock, flags); - return state; -} - -static void sst_fill_pcm_params(struct snd_pcm_substream *substream, - struct sst_pcm_params *param) -{ - - param->codec = SST_CODEC_TYPE_PCM; - param->num_chan = (u8) substream->runtime->channels; - param->pcm_wd_sz = substream->runtime->sample_bits; - param->reserved = 0; - param->sfreq = substream->runtime->rate; - param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream); - param->period_count = substream->runtime->period_size; - param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area); - pr_debug("period_cnt = %d\n", param->period_count); - pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz); -} - -static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream = - substream->runtime->private_data; - struct sst_pcm_params param = {0}; - struct sst_stream_params str_params = {0}; - int ret_val; - - /* set codec params and inform SST driver the same */ - sst_fill_pcm_params(substream, ¶m); - substream->runtime->dma_area = substream->dma_buffer.area; - str_params.sparams = param; - str_params.codec = param.codec; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - str_params.ops = STREAM_OPS_PLAYBACK; - str_params.device_type = substream->pcm->device + 1; - pr_debug("Playbck stream,Device %d\n", - substream->pcm->device); - } else { - str_params.ops = STREAM_OPS_CAPTURE; - str_params.device_type = SND_SST_DEVICE_CAPTURE; - pr_debug("Capture stream,Device %d\n", - substream->pcm->device); - } - ret_val = stream->ops->open(&str_params); - pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val); - if (ret_val < 0) - return ret_val; - - stream->stream_info.str_id = ret_val; - pr_debug("str id : %d\n", stream->stream_info.str_id); - return ret_val; -} - -static void sst_period_elapsed(void *mad_substream) -{ - struct snd_pcm_substream *substream = mad_substream; - struct sst_runtime_stream *stream; - int status; - - if (!substream || !substream->runtime) - return; - stream = substream->runtime->private_data; - if (!stream) - return; - status = sst_get_stream_status(stream); - if (status != SST_PLATFORM_RUNNING) - return; - snd_pcm_period_elapsed(substream); -} - -static int sst_platform_init_stream(struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream = - substream->runtime->private_data; - int ret_val; - - pr_debug("setting buffer ptr param\n"); - sst_set_stream_status(stream, SST_PLATFORM_INIT); - stream->stream_info.period_elapsed = sst_period_elapsed; - stream->stream_info.mad_substream = substream; - stream->stream_info.buffer_ptr = 0; - stream->stream_info.sfreq = substream->runtime->rate; - ret_val = stream->ops->device_control( - SST_SND_STREAM_INIT, &stream->stream_info); - if (ret_val) - pr_err("control_set ret error %d\n", ret_val); - return ret_val; - -} -/* end -- helper functions */ - -static int sst_platform_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sst_runtime_stream *stream; - int ret_val; - - pr_debug("sst_platform_open called\n"); - - snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw); - ret_val = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret_val < 0) - return ret_val; - - stream = kzalloc(sizeof(*stream), GFP_KERNEL); - if (!stream) - return -ENOMEM; - spin_lock_init(&stream->status_lock); - - /* get the sst ops */ - mutex_lock(&sst_lock); - if (!sst) { - pr_err("no device available to run\n"); - mutex_unlock(&sst_lock); - kfree(stream); - return -ENODEV; - } - if (!try_module_get(sst->dev->driver->owner)) { - mutex_unlock(&sst_lock); - kfree(stream); - return -ENODEV; - } - stream->ops = sst->ops; - mutex_unlock(&sst_lock); - - stream->stream_info.str_id = 0; - sst_set_stream_status(stream, SST_PLATFORM_INIT); - stream->stream_info.mad_substream = substream; - /* allocate memory for SST API set */ - runtime->private_data = stream; - - return 0; -} - -static int sst_platform_close(struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream; - int ret_val = 0, str_id; - - pr_debug("sst_platform_close called\n"); - stream = substream->runtime->private_data; - str_id = stream->stream_info.str_id; - if (str_id) - ret_val = stream->ops->close(str_id); - module_put(sst->dev->driver->owner); - kfree(stream); - return ret_val; -} - -static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream; - int ret_val = 0, str_id; - - pr_debug("sst_platform_pcm_prepare called\n"); - stream = substream->runtime->private_data; - str_id = stream->stream_info.str_id; - if (stream->stream_info.str_id) { - ret_val = stream->ops->device_control( - SST_SND_DROP, &str_id); - return ret_val; - } - - ret_val = sst_platform_alloc_stream(substream); - if (ret_val < 0) - return ret_val; - snprintf(substream->pcm->id, sizeof(substream->pcm->id), - "%d", stream->stream_info.str_id); - - ret_val = sst_platform_init_stream(substream); - if (ret_val) - return ret_val; - substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER; - return ret_val; -} - -static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - int ret_val = 0, str_id; - struct sst_runtime_stream *stream; - int str_cmd, status; - - pr_debug("sst_platform_pcm_trigger called\n"); - stream = substream->runtime->private_data; - str_id = stream->stream_info.str_id; - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - pr_debug("sst: Trigger Start\n"); - str_cmd = SST_SND_START; - status = SST_PLATFORM_RUNNING; - stream->stream_info.mad_substream = substream; - break; - case SNDRV_PCM_TRIGGER_STOP: - pr_debug("sst: in stop\n"); - str_cmd = SST_SND_DROP; - status = SST_PLATFORM_DROPPED; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - pr_debug("sst: in pause\n"); - str_cmd = SST_SND_PAUSE; - status = SST_PLATFORM_PAUSED; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - pr_debug("sst: in pause release\n"); - str_cmd = SST_SND_RESUME; - status = SST_PLATFORM_RUNNING; - break; - default: - return -EINVAL; - } - ret_val = stream->ops->device_control(str_cmd, &str_id); - if (!ret_val) - sst_set_stream_status(stream, status); - - return ret_val; -} - - -static snd_pcm_uframes_t sst_platform_pcm_pointer - (struct snd_pcm_substream *substream) -{ - struct sst_runtime_stream *stream; - int ret_val, status; - struct pcm_stream_info *str_info; - - stream = substream->runtime->private_data; - status = sst_get_stream_status(stream); - if (status == SST_PLATFORM_INIT) - return 0; - str_info = &stream->stream_info; - ret_val = stream->ops->device_control( - SST_SND_BUFFER_POINTER, str_info); - if (ret_val) { - pr_err("sst: error code = %d\n", ret_val); - return ret_val; - } - return stream->stream_info.buffer_ptr; -} - -static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); - - return 0; -} - -static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static struct snd_pcm_ops sst_platform_ops = { - .open = sst_platform_open, - .close = sst_platform_close, - .ioctl = snd_pcm_lib_ioctl, - .prepare = sst_platform_pcm_prepare, - .trigger = sst_platform_pcm_trigger, - .pointer = sst_platform_pcm_pointer, - .hw_params = sst_platform_pcm_hw_params, - .hw_free = sst_platform_pcm_hw_free, -}; - -static void sst_pcm_free(struct snd_pcm *pcm) -{ - pr_debug("sst_pcm_free called\n"); - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_pcm *pcm = rtd->pcm; - int retval = 0; - - pr_debug("sst_pcm_new called\n"); - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || - pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - retval = snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - SST_MIN_BUFFER, SST_MAX_BUFFER); - if (retval) { - pr_err("dma buffer allocationf fail\n"); - return retval; - } - } - return retval; -} -static struct snd_soc_platform_driver sst_soc_platform_drv = { - .ops = &sst_platform_ops, - .pcm_new = sst_pcm_new, - .pcm_free = sst_pcm_free, -}; - -static int sst_platform_probe(struct platform_device *pdev) -{ - int ret; - - pr_debug("sst_platform_probe called\n"); - sst = NULL; - ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); - if (ret) { - pr_err("registering soc platform failed\n"); - return ret; - } - - ret = snd_soc_register_dais(&pdev->dev, - sst_platform_dai, ARRAY_SIZE(sst_platform_dai)); - if (ret) { - pr_err("registering cpu dais failed\n"); - snd_soc_unregister_platform(&pdev->dev); - } - return ret; -} - -static int sst_platform_remove(struct platform_device *pdev) -{ - - snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sst_platform_dai)); - snd_soc_unregister_platform(&pdev->dev); - pr_debug("sst_platform_remove success\n"); - return 0; -} - -static struct platform_driver sst_platform_driver = { - .driver = { - .name = "sst-platform", - .owner = THIS_MODULE, - }, - .probe = sst_platform_probe, - .remove = sst_platform_remove, -}; - -module_platform_driver(sst_platform_driver); - -MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver"); -MODULE_AUTHOR("Vinod Koul "); -MODULE_AUTHOR("Harsha Priya "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:sst-platform"); diff --git a/ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.h b/ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.h deleted file mode 100644 index f04f4f72..00000000 --- a/ANDROID_3.4.5/sound/soc/mid-x86/sst_platform.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * sst_platform.h - Intel MID Platform driver header file - * - * Copyright (C) 2010 Intel Corp - * Author: Vinod Koul - * Author: Harsha Priya - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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; version 2 of the License. - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * - */ - -#ifndef __SST_PLATFORMDRV_H__ -#define __SST_PLATFORMDRV_H__ - -#define SST_MONO 1 -#define SST_STEREO 2 -#define SST_MAX_CAP 5 - -#define SST_MIN_RATE 8000 -#define SST_MAX_RATE 48000 -#define SST_MIN_CHANNEL 1 -#define SST_MAX_CHANNEL 5 -#define SST_MAX_BUFFER (800*1024) -#define SST_MIN_BUFFER (800*1024) -#define SST_MIN_PERIOD_BYTES 32 -#define SST_MAX_PERIOD_BYTES SST_MAX_BUFFER -#define SST_MIN_PERIODS 2 -#define SST_MAX_PERIODS (1024*2) -#define SST_FIFO_SIZE 0 -#define SST_CODEC_TYPE_PCM 1 - -struct pcm_stream_info { - int str_id; - void *mad_substream; - void (*period_elapsed) (void *mad_substream); - unsigned long long buffer_ptr; - int sfreq; -}; - -enum sst_drv_status { - SST_PLATFORM_INIT = 1, - SST_PLATFORM_STARTED, - SST_PLATFORM_RUNNING, - SST_PLATFORM_PAUSED, - SST_PLATFORM_DROPPED, -}; - -enum sst_controls { - SST_SND_ALLOC = 0x00, - SST_SND_PAUSE = 0x01, - SST_SND_RESUME = 0x02, - SST_SND_DROP = 0x03, - SST_SND_FREE = 0x04, - SST_SND_BUFFER_POINTER = 0x05, - SST_SND_STREAM_INIT = 0x06, - SST_SND_START = 0x07, - SST_MAX_CONTROLS = 0x07, -}; - -enum sst_stream_ops { - STREAM_OPS_PLAYBACK = 0, - STREAM_OPS_CAPTURE, -}; - -enum sst_audio_device_type { - SND_SST_DEVICE_HEADSET = 1, - SND_SST_DEVICE_IHF, - SND_SST_DEVICE_VIBRA, - SND_SST_DEVICE_HAPTIC, - SND_SST_DEVICE_CAPTURE, -}; - -/* PCM Parameters */ -struct sst_pcm_params { - u16 codec; /* codec type */ - u8 num_chan; /* 1=Mono, 2=Stereo */ - u8 pcm_wd_sz; /* 16/24 - bit*/ - u32 reserved; /* Bitrate in bits per second */ - u32 sfreq; /* Sampling rate in Hz */ - u32 ring_buffer_size; - u32 period_count; /* period elapsed in samples*/ - u32 ring_buffer_addr; -}; - -struct sst_stream_params { - u32 result; - u32 stream_id; - u8 codec; - u8 ops; - u8 stream_type; - u8 device_type; - struct sst_pcm_params sparams; -}; - -struct sst_ops { - int (*open) (struct sst_stream_params *str_param); - int (*device_control) (int cmd, void *arg); - int (*close) (unsigned int str_id); -}; - -struct sst_runtime_stream { - int stream_status; - struct pcm_stream_info stream_info; - struct sst_ops *ops; - spinlock_t status_lock; -}; - -struct sst_device { - char *name; - struct device *dev; - struct sst_ops *ops; -}; - -int sst_register_dsp(struct sst_device *sst); -int sst_unregister_dsp(struct sst_device *sst); -#endif diff --git a/ANDROID_3.4.5/sound/soc/mxs/Kconfig b/ANDROID_3.4.5/sound/soc/mxs/Kconfig deleted file mode 100644 index 99a997f1..00000000 --- a/ANDROID_3.4.5/sound/soc/mxs/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -menuconfig SND_MXS_SOC - tristate "SoC Audio for Freescale MXS CPUs" - depends on ARCH_MXS - select SND_SOC_DMAENGINE_PCM - help - Say Y or M if you want to add support for codecs attached to - the MXS SAIF interface. - - -if SND_MXS_SOC - -config SND_SOC_MXS_SGTL5000 - tristate "SoC Audio support for i.MX boards with sgtl5000" - depends on I2C - select SND_SOC_SGTL5000 - help - Say Y if you want to add support for SoC audio on an MXS board with - a sgtl5000 codec. - -endif # SND_MXS_SOC diff --git a/ANDROID_3.4.5/sound/soc/mxs/Makefile b/ANDROID_3.4.5/sound/soc/mxs/Makefile deleted file mode 100644 index 565b5b51..00000000 --- a/ANDROID_3.4.5/sound/soc/mxs/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# MXS Platform Support -snd-soc-mxs-objs := mxs-saif.o -snd-soc-mxs-pcm-objs := mxs-pcm.o - -obj-$(CONFIG_SND_MXS_SOC) += snd-soc-mxs.o snd-soc-mxs-pcm.o - -# i.MX Machine Support -snd-soc-mxs-sgtl5000-objs := mxs-sgtl5000.o - -obj-$(CONFIG_SND_SOC_MXS_SGTL5000) += snd-soc-mxs-sgtl5000.o diff --git a/ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.c b/ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.c deleted file mode 100644 index e373fbbc..00000000 --- a/ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * Based on sound/soc/imx/imx-pcm-dma-mx2.c - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "mxs-pcm.h" - -struct mxs_pcm_dma_data { - struct mxs_dma_data dma_data; - struct mxs_pcm_dma_params *dma_params; -}; - -static struct snd_pcm_hardware snd_mxs_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_INTERLEAVED, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE, - .channels_min = 2, - .channels_max = 2, - .period_bytes_min = 32, - .period_bytes_max = 8192, - .periods_min = 1, - .periods_max = 52, - .buffer_bytes_max = 64 * 1024, - .fifo_size = 32, - -}; - -static bool filter(struct dma_chan *chan, void *param) -{ - struct mxs_pcm_dma_data *pcm_dma_data = param; - struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params; - - if (!mxs_dma_is_apbx(chan)) - return false; - - if (chan->chan_id != dma_params->chan_num) - return false; - - chan->private = &pcm_dma_data->dma_data; - - return true; -} - -static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - return 0; -} - -static int snd_mxs_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct mxs_pcm_dma_data *pcm_dma_data; - int ret; - - pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL); - if (pcm_dma_data == NULL) - return -ENOMEM; - - pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq; - - ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data); - if (ret) { - kfree(pcm_dma_data); - return ret; - } - - snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); - - snd_dmaengine_pcm_set_data(substream, pcm_dma_data); - - return 0; -} - -static int snd_mxs_close(struct snd_pcm_substream *substream) -{ - struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream); - - snd_dmaengine_pcm_close(substream); - kfree(pcm_dma_data); - - return 0; -} - -static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - -static struct snd_pcm_ops mxs_pcm_ops = { - .open = snd_mxs_open, - .close = snd_mxs_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_mxs_pcm_hw_params, - .trigger = snd_dmaengine_pcm_trigger, - .pointer = snd_dmaengine_pcm_pointer, - .mmap = snd_mxs_pcm_mmap, -}; - -static int mxs_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = snd_mxs_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - - return 0; -} - -static u64 mxs_pcm_dmamask = DMA_BIT_MASK(32); -static int mxs_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &mxs_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = mxs_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = mxs_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - -out: - return ret; -} - -static void mxs_pcm_free(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - -static struct snd_soc_platform_driver mxs_soc_platform = { - .ops = &mxs_pcm_ops, - .pcm_new = mxs_pcm_new, - .pcm_free = mxs_pcm_free, -}; - -static int __devinit mxs_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &mxs_soc_platform); -} - -static int __devexit mxs_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - - return 0; -} - -static struct platform_driver mxs_pcm_driver = { - .driver = { - .name = "mxs-pcm-audio", - .owner = THIS_MODULE, - }, - .probe = mxs_soc_platform_probe, - .remove = __devexit_p(mxs_soc_platform_remove), -}; - -module_platform_driver(mxs_pcm_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:mxs-pcm-audio"); diff --git a/ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.h b/ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.h deleted file mode 100644 index 5f01a912..00000000 --- a/ANDROID_3.4.5/sound/soc/mxs/mxs-pcm.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef _MXS_PCM_H -#define _MXS_PCM_H - -struct mxs_pcm_dma_params { - int chan_irq; - int chan_num; -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/mxs/mxs-saif.c b/ANDROID_3.4.5/sound/soc/mxs/mxs-saif.c deleted file mode 100644 index 53f4fd8f..00000000 --- a/ANDROID_3.4.5/sound/soc/mxs/mxs-saif.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mxs-saif.h" - -static struct mxs_saif *mxs_saif[2]; - -/* - * SAIF is a little different with other normal SOC DAIs on clock using. - * - * For MXS, two SAIF modules are instantiated on-chip. - * Each SAIF has a set of clock pins and can be operating in master - * mode simultaneously if they are connected to different off-chip codecs. - * Also, one of the two SAIFs can master or drive the clock pins while the - * other SAIF, in slave mode, receives clocking from the master SAIF. - * This also means that both SAIFs must operate at the same sample rate. - * - * We abstract this as each saif has a master, the master could be - * himself or other saifs. In the generic saif driver, saif does not need - * to know the different clkmux. Saif only needs to know who is his master - * and operating his master to generate the proper clock rate for him. - * The master id is provided in mach-specific layer according to different - * clkmux setting. - */ - -static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); - - switch (clk_id) { - case MXS_SAIF_MCLK: - saif->mclk = freq; - break; - default: - return -EINVAL; - } - return 0; -} - -/* - * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK - * is provided by other SAIF, we provide a interface here to get its master - * from its master_id. - * Note that the master could be himself. - */ -static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif) -{ - return mxs_saif[saif->master_id]; -} - -/* - * Set SAIF clock and MCLK - */ -static int mxs_saif_set_clk(struct mxs_saif *saif, - unsigned int mclk, - unsigned int rate) -{ - u32 scr; - int ret; - struct mxs_saif *master_saif; - - dev_dbg(saif->dev, "mclk %d rate %d\n", mclk, rate); - - /* Set master saif to generate proper clock */ - master_saif = mxs_saif_get_master(saif); - if (!master_saif) - return -EINVAL; - - dev_dbg(saif->dev, "master saif%d\n", master_saif->id); - - /* Checking if can playback and capture simutaneously */ - if (master_saif->ongoing && rate != master_saif->cur_rate) { - dev_err(saif->dev, - "can not change clock, master saif%d(rate %d) is ongoing\n", - master_saif->id, master_saif->cur_rate); - return -EINVAL; - } - - scr = __raw_readl(master_saif->base + SAIF_CTRL); - scr &= ~BM_SAIF_CTRL_BITCLK_MULT_RATE; - scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; - - /* - * Set SAIF clock - * - * The SAIF clock should be either 384*fs or 512*fs. - * If MCLK is used, the SAIF clk ratio need to match mclk ratio. - * For 32x mclk, set saif clk as 512*fs. - * For 48x mclk, set saif clk as 384*fs. - * - * If MCLK is not used, we just set saif clk to 512*fs. - */ - clk_prepare_enable(master_saif->clk); - - if (master_saif->mclk_in_use) { - if (mclk % 32 == 0) { - scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; - ret = clk_set_rate(master_saif->clk, 512 * rate); - } else if (mclk % 48 == 0) { - scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE; - ret = clk_set_rate(master_saif->clk, 384 * rate); - } else { - /* SAIF MCLK should be either 32x or 48x */ - clk_disable_unprepare(master_saif->clk); - return -EINVAL; - } - } else { - ret = clk_set_rate(master_saif->clk, 512 * rate); - scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE; - } - - clk_disable_unprepare(master_saif->clk); - - if (ret) - return ret; - - master_saif->cur_rate = rate; - - if (!master_saif->mclk_in_use) { - __raw_writel(scr, master_saif->base + SAIF_CTRL); - return 0; - } - - /* - * Program the over-sample rate for MCLK output - * - * The available MCLK range is 32x, 48x... 512x. The rate - * could be from 8kHz to 192kH. - */ - switch (mclk / rate) { - case 32: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(4); - break; - case 64: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3); - break; - case 128: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2); - break; - case 256: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1); - break; - case 512: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0); - break; - case 48: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3); - break; - case 96: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2); - break; - case 192: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1); - break; - case 384: - scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0); - break; - default: - return -EINVAL; - } - - __raw_writel(scr, master_saif->base + SAIF_CTRL); - - return 0; -} - -/* - * Put and disable MCLK. - */ -int mxs_saif_put_mclk(unsigned int saif_id) -{ - struct mxs_saif *saif = mxs_saif[saif_id]; - u32 stat; - - if (!saif) - return -EINVAL; - - stat = __raw_readl(saif->base + SAIF_STAT); - if (stat & BM_SAIF_STAT_BUSY) { - dev_err(saif->dev, "error: busy\n"); - return -EBUSY; - } - - clk_disable_unprepare(saif->clk); - - /* disable MCLK output */ - __raw_writel(BM_SAIF_CTRL_CLKGATE, - saif->base + SAIF_CTRL + MXS_SET_ADDR); - __raw_writel(BM_SAIF_CTRL_RUN, - saif->base + SAIF_CTRL + MXS_CLR_ADDR); - - saif->mclk_in_use = 0; - return 0; -} - -/* - * Get MCLK and set clock rate, then enable it - * - * This interface is used for codecs who are using MCLK provided - * by saif. - */ -int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk, - unsigned int rate) -{ - struct mxs_saif *saif = mxs_saif[saif_id]; - u32 stat; - int ret; - struct mxs_saif *master_saif; - - if (!saif) - return -EINVAL; - - /* Clear Reset */ - __raw_writel(BM_SAIF_CTRL_SFTRST, - saif->base + SAIF_CTRL + MXS_CLR_ADDR); - - /* FIXME: need clear clk gate for register r/w */ - __raw_writel(BM_SAIF_CTRL_CLKGATE, - saif->base + SAIF_CTRL + MXS_CLR_ADDR); - - master_saif = mxs_saif_get_master(saif); - if (saif != master_saif) { - dev_err(saif->dev, "can not get mclk from a non-master saif\n"); - return -EINVAL; - } - - stat = __raw_readl(saif->base + SAIF_STAT); - if (stat & BM_SAIF_STAT_BUSY) { - dev_err(saif->dev, "error: busy\n"); - return -EBUSY; - } - - saif->mclk_in_use = 1; - ret = mxs_saif_set_clk(saif, mclk, rate); - if (ret) - return ret; - - ret = clk_prepare_enable(saif->clk); - if (ret) - return ret; - - /* enable MCLK output */ - __raw_writel(BM_SAIF_CTRL_RUN, - saif->base + SAIF_CTRL + MXS_SET_ADDR); - - return 0; -} - -/* - * SAIF DAI format configuration. - * Should only be called when port is inactive. - */ -static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) -{ - u32 scr, stat; - u32 scr0; - struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); - - stat = __raw_readl(saif->base + SAIF_STAT); - if (stat & BM_SAIF_STAT_BUSY) { - dev_err(cpu_dai->dev, "error: busy\n"); - return -EBUSY; - } - - scr0 = __raw_readl(saif->base + SAIF_CTRL); - scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \ - & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY; - scr = 0; - - /* DAI mode */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - /* data frame low 1clk before data */ - scr |= BM_SAIF_CTRL_DELAY; - scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; - break; - case SND_SOC_DAIFMT_LEFT_J: - /* data frame high with data */ - scr &= ~BM_SAIF_CTRL_DELAY; - scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; - scr &= ~BM_SAIF_CTRL_JUSTIFY; - break; - default: - return -EINVAL; - } - - /* DAI clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - scr |= BM_SAIF_CTRL_BITCLK_EDGE; - scr |= BM_SAIF_CTRL_LRCLK_POLARITY; - break; - case SND_SOC_DAIFMT_IB_NF: - scr |= BM_SAIF_CTRL_BITCLK_EDGE; - scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; - break; - case SND_SOC_DAIFMT_NB_IF: - scr &= ~BM_SAIF_CTRL_BITCLK_EDGE; - scr |= BM_SAIF_CTRL_LRCLK_POLARITY; - break; - case SND_SOC_DAIFMT_NB_NF: - scr &= ~BM_SAIF_CTRL_BITCLK_EDGE; - scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY; - break; - } - - /* - * Note: We simply just support master mode since SAIF TX can only - * work as master. - * Here the master is relative to codec side. - * Saif internally could be slave when working on EXTMASTER mode. - * We just hide this to machine driver. - */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - if (saif->id == saif->master_id) - scr &= ~BM_SAIF_CTRL_SLAVE_MODE; - else - scr |= BM_SAIF_CTRL_SLAVE_MODE; - - __raw_writel(scr | scr0, saif->base + SAIF_CTRL); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int mxs_saif_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); - snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param); - - /* clear error status to 0 for each re-open */ - saif->fifo_underrun = 0; - saif->fifo_overrun = 0; - - /* Clear Reset for normal operations */ - __raw_writel(BM_SAIF_CTRL_SFTRST, - saif->base + SAIF_CTRL + MXS_CLR_ADDR); - - /* clear clock gate */ - __raw_writel(BM_SAIF_CTRL_CLKGATE, - saif->base + SAIF_CTRL + MXS_CLR_ADDR); - - return 0; -} - -/* - * Should only be called when port is inactive. - * although can be called multiple times by upper layers. - */ -static int mxs_saif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); - u32 scr, stat; - int ret; - - /* mclk should already be set */ - if (!saif->mclk && saif->mclk_in_use) { - dev_err(cpu_dai->dev, "set mclk first\n"); - return -EINVAL; - } - - stat = __raw_readl(saif->base + SAIF_STAT); - if (stat & BM_SAIF_STAT_BUSY) { - dev_err(cpu_dai->dev, "error: busy\n"); - return -EBUSY; - } - - /* - * Set saif clk based on sample rate. - * If mclk is used, we also set mclk, if not, saif->mclk is - * default 0, means not used. - */ - ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params)); - if (ret) { - dev_err(cpu_dai->dev, "unable to get proper clk\n"); - return ret; - } - - scr = __raw_readl(saif->base + SAIF_CTRL); - - scr &= ~BM_SAIF_CTRL_WORD_LENGTH; - scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - scr |= BF_SAIF_CTRL_WORD_LENGTH(0); - break; - case SNDRV_PCM_FORMAT_S20_3LE: - scr |= BF_SAIF_CTRL_WORD_LENGTH(4); - scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; - break; - case SNDRV_PCM_FORMAT_S24_LE: - scr |= BF_SAIF_CTRL_WORD_LENGTH(8); - scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; - break; - default: - return -EINVAL; - } - - /* Tx/Rx config */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* enable TX mode */ - scr &= ~BM_SAIF_CTRL_READ_MODE; - } else { - /* enable RX mode */ - scr |= BM_SAIF_CTRL_READ_MODE; - } - - __raw_writel(scr, saif->base + SAIF_CTRL); - return 0; -} - -static int mxs_saif_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); - - /* enable FIFO error irqs */ - __raw_writel(BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN, - saif->base + SAIF_CTRL + MXS_SET_ADDR); - - return 0; -} - -static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *cpu_dai) -{ - struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); - struct mxs_saif *master_saif; - u32 delay; - - master_saif = mxs_saif_get_master(saif); - if (!master_saif) - return -EINVAL; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - dev_dbg(cpu_dai->dev, "start\n"); - - clk_enable(master_saif->clk); - if (!master_saif->mclk_in_use) - __raw_writel(BM_SAIF_CTRL_RUN, - master_saif->base + SAIF_CTRL + MXS_SET_ADDR); - - /* - * If the saif's master is not himself, we also need to enable - * itself clk for its internal basic logic to work. - */ - if (saif != master_saif) { - clk_enable(saif->clk); - __raw_writel(BM_SAIF_CTRL_RUN, - saif->base + SAIF_CTRL + MXS_SET_ADDR); - } - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* - * write a data to saif data register to trigger - * the transfer - */ - __raw_writel(0, saif->base + SAIF_DATA); - } else { - /* - * read a data from saif data register to trigger - * the receive - */ - __raw_readl(saif->base + SAIF_DATA); - } - - master_saif->ongoing = 1; - - dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n", - __raw_readl(saif->base + SAIF_CTRL), - __raw_readl(saif->base + SAIF_STAT)); - - dev_dbg(master_saif->dev, "CTRL 0x%x STAT 0x%x\n", - __raw_readl(master_saif->base + SAIF_CTRL), - __raw_readl(master_saif->base + SAIF_STAT)); - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - dev_dbg(cpu_dai->dev, "stop\n"); - - /* wait a while for the current sample to complete */ - delay = USEC_PER_SEC / master_saif->cur_rate; - - if (!master_saif->mclk_in_use) { - __raw_writel(BM_SAIF_CTRL_RUN, - master_saif->base + SAIF_CTRL + MXS_CLR_ADDR); - udelay(delay); - } - clk_disable(master_saif->clk); - - if (saif != master_saif) { - __raw_writel(BM_SAIF_CTRL_RUN, - saif->base + SAIF_CTRL + MXS_CLR_ADDR); - udelay(delay); - clk_disable(saif->clk); - } - - master_saif->ongoing = 0; - - break; - default: - return -EINVAL; - } - - return 0; -} - -#define MXS_SAIF_RATES SNDRV_PCM_RATE_8000_192000 -#define MXS_SAIF_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -static const struct snd_soc_dai_ops mxs_saif_dai_ops = { - .startup = mxs_saif_startup, - .trigger = mxs_saif_trigger, - .prepare = mxs_saif_prepare, - .hw_params = mxs_saif_hw_params, - .set_sysclk = mxs_saif_set_dai_sysclk, - .set_fmt = mxs_saif_set_dai_fmt, -}; - -static int mxs_saif_dai_probe(struct snd_soc_dai *dai) -{ - struct mxs_saif *saif = dev_get_drvdata(dai->dev); - - snd_soc_dai_set_drvdata(dai, saif); - - return 0; -} - -static struct snd_soc_dai_driver mxs_saif_dai = { - .name = "mxs-saif", - .probe = mxs_saif_dai_probe, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = MXS_SAIF_RATES, - .formats = MXS_SAIF_FORMATS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = MXS_SAIF_RATES, - .formats = MXS_SAIF_FORMATS, - }, - .ops = &mxs_saif_dai_ops, -}; - -static irqreturn_t mxs_saif_irq(int irq, void *dev_id) -{ - struct mxs_saif *saif = dev_id; - unsigned int stat; - - stat = __raw_readl(saif->base + SAIF_STAT); - if (!(stat & (BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ | - BM_SAIF_STAT_FIFO_OVERFLOW_IRQ))) - return IRQ_NONE; - - if (stat & BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ) { - dev_dbg(saif->dev, "underrun!!! %d\n", ++saif->fifo_underrun); - __raw_writel(BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ, - saif->base + SAIF_STAT + MXS_CLR_ADDR); - } - - if (stat & BM_SAIF_STAT_FIFO_OVERFLOW_IRQ) { - dev_dbg(saif->dev, "overrun!!! %d\n", ++saif->fifo_overrun); - __raw_writel(BM_SAIF_STAT_FIFO_OVERFLOW_IRQ, - saif->base + SAIF_STAT + MXS_CLR_ADDR); - } - - dev_dbg(saif->dev, "SAIF_CTRL %x SAIF_STAT %x\n", - __raw_readl(saif->base + SAIF_CTRL), - __raw_readl(saif->base + SAIF_STAT)); - - return IRQ_HANDLED; -} - -static int mxs_saif_probe(struct platform_device *pdev) -{ - struct resource *iores, *dmares; - struct mxs_saif *saif; - struct mxs_saif_platform_data *pdata; - int ret = 0; - - if (pdev->id >= ARRAY_SIZE(mxs_saif)) - return -EINVAL; - - saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL); - if (!saif) - return -ENOMEM; - - mxs_saif[pdev->id] = saif; - saif->id = pdev->id; - - pdata = pdev->dev.platform_data; - if (pdata && !pdata->master_mode) { - saif->master_id = pdata->master_id; - if (saif->master_id < 0 || - saif->master_id >= ARRAY_SIZE(mxs_saif) || - saif->master_id == saif->id) { - dev_err(&pdev->dev, "get wrong master id\n"); - return -EINVAL; - } - } else { - saif->master_id = saif->id; - } - - saif->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(saif->clk)) { - ret = PTR_ERR(saif->clk); - dev_err(&pdev->dev, "Cannot get the clock: %d\n", - ret); - return ret; - } - - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - saif->base = devm_request_and_ioremap(&pdev->dev, iores); - if (!saif->base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENODEV; - goto failed_get_resource; - } - - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!dmares) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to get dma resource: %d\n", - ret); - goto failed_get_resource; - } - saif->dma_param.chan_num = dmares->start; - - saif->irq = platform_get_irq(pdev, 0); - if (saif->irq < 0) { - ret = saif->irq; - dev_err(&pdev->dev, "failed to get irq resource: %d\n", - ret); - goto failed_get_resource; - } - - saif->dev = &pdev->dev; - ret = devm_request_irq(&pdev->dev, saif->irq, mxs_saif_irq, 0, - "mxs-saif", saif); - if (ret) { - dev_err(&pdev->dev, "failed to request irq\n"); - goto failed_get_resource; - } - - saif->dma_param.chan_irq = platform_get_irq(pdev, 1); - if (saif->dma_param.chan_irq < 0) { - ret = saif->dma_param.chan_irq; - dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", - ret); - goto failed_get_resource; - } - - platform_set_drvdata(pdev, saif); - - ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); - if (ret) { - dev_err(&pdev->dev, "register DAI failed\n"); - goto failed_get_resource; - } - - saif->soc_platform_pdev = platform_device_alloc( - "mxs-pcm-audio", pdev->id); - if (!saif->soc_platform_pdev) { - ret = -ENOMEM; - goto failed_pdev_alloc; - } - - platform_set_drvdata(saif->soc_platform_pdev, saif); - ret = platform_device_add(saif->soc_platform_pdev); - if (ret) { - dev_err(&pdev->dev, "failed to add soc platform device\n"); - goto failed_pdev_add; - } - - return 0; - -failed_pdev_add: - platform_device_put(saif->soc_platform_pdev); -failed_pdev_alloc: - snd_soc_unregister_dai(&pdev->dev); -failed_get_resource: - clk_put(saif->clk); - - return ret; -} - -static int __devexit mxs_saif_remove(struct platform_device *pdev) -{ - struct mxs_saif *saif = platform_get_drvdata(pdev); - - platform_device_unregister(saif->soc_platform_pdev); - snd_soc_unregister_dai(&pdev->dev); - clk_put(saif->clk); - - return 0; -} - -static struct platform_driver mxs_saif_driver = { - .probe = mxs_saif_probe, - .remove = __devexit_p(mxs_saif_remove), - - .driver = { - .name = "mxs-saif", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(mxs_saif_driver); - -MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("MXS ASoC SAIF driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/mxs/mxs-saif.h b/ANDROID_3.4.5/sound/soc/mxs/mxs-saif.h deleted file mode 100644 index 12c91e4e..00000000 --- a/ANDROID_3.4.5/sound/soc/mxs/mxs-saif.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - - -#ifndef _MXS_SAIF_H -#define _MXS_SAIF_H - -#define SAIF_CTRL 0x0 -#define SAIF_STAT 0x10 -#define SAIF_DATA 0x20 -#define SAIF_VERSION 0X30 - -/* SAIF_CTRL */ -#define BM_SAIF_CTRL_SFTRST 0x80000000 -#define BM_SAIF_CTRL_CLKGATE 0x40000000 -#define BP_SAIF_CTRL_BITCLK_MULT_RATE 27 -#define BM_SAIF_CTRL_BITCLK_MULT_RATE 0x38000000 -#define BF_SAIF_CTRL_BITCLK_MULT_RATE(v) \ - (((v) << 27) & BM_SAIF_CTRL_BITCLK_MULT_RATE) -#define BM_SAIF_CTRL_BITCLK_BASE_RATE 0x04000000 -#define BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN 0x02000000 -#define BM_SAIF_CTRL_FIFO_SERVICE_IRQ_EN 0x01000000 -#define BP_SAIF_CTRL_RSRVD2 21 -#define BM_SAIF_CTRL_RSRVD2 0x00E00000 - -#define BP_SAIF_CTRL_DMAWAIT_COUNT 16 -#define BM_SAIF_CTRL_DMAWAIT_COUNT 0x001F0000 -#define BF_SAIF_CTRL_DMAWAIT_COUNT(v) \ - (((v) << 16) & BM_SAIF_CTRL_DMAWAIT_COUNT) -#define BP_SAIF_CTRL_CHANNEL_NUM_SELECT 14 -#define BM_SAIF_CTRL_CHANNEL_NUM_SELECT 0x0000C000 -#define BF_SAIF_CTRL_CHANNEL_NUM_SELECT(v) \ - (((v) << 14) & BM_SAIF_CTRL_CHANNEL_NUM_SELECT) -#define BM_SAIF_CTRL_LRCLK_PULSE 0x00002000 -#define BM_SAIF_CTRL_BIT_ORDER 0x00001000 -#define BM_SAIF_CTRL_DELAY 0x00000800 -#define BM_SAIF_CTRL_JUSTIFY 0x00000400 -#define BM_SAIF_CTRL_LRCLK_POLARITY 0x00000200 -#define BM_SAIF_CTRL_BITCLK_EDGE 0x00000100 -#define BP_SAIF_CTRL_WORD_LENGTH 4 -#define BM_SAIF_CTRL_WORD_LENGTH 0x000000F0 -#define BF_SAIF_CTRL_WORD_LENGTH(v) \ - (((v) << 4) & BM_SAIF_CTRL_WORD_LENGTH) -#define BM_SAIF_CTRL_BITCLK_48XFS_ENABLE 0x00000008 -#define BM_SAIF_CTRL_SLAVE_MODE 0x00000004 -#define BM_SAIF_CTRL_READ_MODE 0x00000002 -#define BM_SAIF_CTRL_RUN 0x00000001 - -/* SAIF_STAT */ -#define BM_SAIF_STAT_PRESENT 0x80000000 -#define BP_SAIF_STAT_RSRVD2 17 -#define BM_SAIF_STAT_RSRVD2 0x7FFE0000 -#define BF_SAIF_STAT_RSRVD2(v) \ - (((v) << 17) & BM_SAIF_STAT_RSRVD2) -#define BM_SAIF_STAT_DMA_PREQ 0x00010000 -#define BP_SAIF_STAT_RSRVD1 7 -#define BM_SAIF_STAT_RSRVD1 0x0000FF80 -#define BF_SAIF_STAT_RSRVD1(v) \ - (((v) << 7) & BM_SAIF_STAT_RSRVD1) - -#define BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ 0x00000040 -#define BM_SAIF_STAT_FIFO_OVERFLOW_IRQ 0x00000020 -#define BM_SAIF_STAT_FIFO_SERVICE_IRQ 0x00000010 -#define BP_SAIF_STAT_RSRVD0 1 -#define BM_SAIF_STAT_RSRVD0 0x0000000E -#define BF_SAIF_STAT_RSRVD0(v) \ - (((v) << 1) & BM_SAIF_STAT_RSRVD0) -#define BM_SAIF_STAT_BUSY 0x00000001 - -/* SAFI_DATA */ -#define BP_SAIF_DATA_PCM_RIGHT 16 -#define BM_SAIF_DATA_PCM_RIGHT 0xFFFF0000 -#define BF_SAIF_DATA_PCM_RIGHT(v) \ - (((v) << 16) & BM_SAIF_DATA_PCM_RIGHT) -#define BP_SAIF_DATA_PCM_LEFT 0 -#define BM_SAIF_DATA_PCM_LEFT 0x0000FFFF -#define BF_SAIF_DATA_PCM_LEFT(v) \ - (((v) << 0) & BM_SAIF_DATA_PCM_LEFT) - -/* SAIF_VERSION */ -#define BP_SAIF_VERSION_MAJOR 24 -#define BM_SAIF_VERSION_MAJOR 0xFF000000 -#define BF_SAIF_VERSION_MAJOR(v) \ - (((v) << 24) & BM_SAIF_VERSION_MAJOR) -#define BP_SAIF_VERSION_MINOR 16 -#define BM_SAIF_VERSION_MINOR 0x00FF0000 -#define BF_SAIF_VERSION_MINOR(v) \ - (((v) << 16) & BM_SAIF_VERSION_MINOR) -#define BP_SAIF_VERSION_STEP 0 -#define BM_SAIF_VERSION_STEP 0x0000FFFF -#define BF_SAIF_VERSION_STEP(v) \ - (((v) << 0) & BM_SAIF_VERSION_STEP) - -#define MXS_SAIF_MCLK 0 - -#include "mxs-pcm.h" - -struct mxs_saif { - struct device *dev; - struct clk *clk; - unsigned int mclk; - unsigned int mclk_in_use; - void __iomem *base; - int irq; - struct mxs_pcm_dma_params dma_param; - unsigned int id; - unsigned int master_id; - unsigned int cur_rate; - unsigned int ongoing; - - struct platform_device *soc_platform_pdev; - u32 fifo_underrun; - u32 fifo_overrun; -}; - -extern int mxs_saif_put_mclk(unsigned int saif_id); -extern int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk, - unsigned int rate); -#endif diff --git a/ANDROID_3.4.5/sound/soc/mxs/mxs-sgtl5000.c b/ANDROID_3.4.5/sound/soc/mxs/mxs-sgtl5000.c deleted file mode 100644 index 60f052b7..00000000 --- a/ANDROID_3.4.5/sound/soc/mxs/mxs-sgtl5000.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. - * - * 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../codecs/sgtl5000.h" -#include "mxs-saif.h" - -static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int rate = params_rate(params); - u32 dai_format, mclk; - int ret; - - /* sgtl5000 does not support 512*rate when in 96000 fs */ - switch (rate) { - case 96000: - mclk = 256 * rate; - break; - default: - mclk = 512 * rate; - break; - } - - /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */ - if (mclk < 8000000 || mclk > 27000000) - return -EINVAL; - - /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */ - ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0); - if (ret) - return ret; - - /* The SAIF MCLK should be the same as SGTL5000_SYSCLK */ - ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0); - if (ret) - return ret; - - /* set codec to slave mode */ - dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS; - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, dai_format); - if (ret) - return ret; - - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); - if (ret) - return ret; - - return 0; -} - -static struct snd_soc_ops mxs_sgtl5000_hifi_ops = { - .hw_params = mxs_sgtl5000_hw_params, -}; - -static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { - { - .name = "HiFi Tx", - .stream_name = "HiFi Playback", - .codec_dai_name = "sgtl5000", - .codec_name = "sgtl5000.0-000a", - .cpu_dai_name = "mxs-saif.0", - .platform_name = "mxs-pcm-audio.0", - .ops = &mxs_sgtl5000_hifi_ops, - }, { - .name = "HiFi Rx", - .stream_name = "HiFi Capture", - .codec_dai_name = "sgtl5000", - .codec_name = "sgtl5000.0-000a", - .cpu_dai_name = "mxs-saif.1", - .platform_name = "mxs-pcm-audio.1", - .ops = &mxs_sgtl5000_hifi_ops, - }, -}; - -static struct snd_soc_card mxs_sgtl5000 = { - .name = "mxs_sgtl5000", - .owner = THIS_MODULE, - .dai_link = mxs_sgtl5000_dai, - .num_links = ARRAY_SIZE(mxs_sgtl5000_dai), -}; - -static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card = &mxs_sgtl5000; - int ret; - - /* - * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w). - * The Sgtl5000 sysclk is derived from saif0 mclk and it's range - * should be >= 8MHz and <= 27M. - */ - ret = mxs_saif_get_mclk(0, 44100 * 256, 44100); - if (ret) - return ret; - - card->dev = &pdev->dev; - platform_set_drvdata(pdev, card); - - ret = snd_soc_register_card(card); - if (ret) { - dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", - ret); - return ret; - } - - return 0; -} - -static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - mxs_saif_put_mclk(0); - - snd_soc_unregister_card(card); - - return 0; -} - -static struct platform_driver mxs_sgtl5000_audio_driver = { - .driver = { - .name = "mxs-sgtl5000", - .owner = THIS_MODULE, - }, - .probe = mxs_sgtl5000_probe, - .remove = __devexit_p(mxs_sgtl5000_remove), -}; - -module_platform_driver(mxs_sgtl5000_audio_driver); - -MODULE_AUTHOR("Freescale Semiconductor, Inc."); -MODULE_DESCRIPTION("MXS ALSA SoC Machine driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:mxs-sgtl5000"); diff --git a/ANDROID_3.4.5/sound/soc/nuc900/Kconfig b/ANDROID_3.4.5/sound/soc/nuc900/Kconfig deleted file mode 100644 index a0ed1c61..00000000 --- a/ANDROID_3.4.5/sound/soc/nuc900/Kconfig +++ /dev/null @@ -1,27 +0,0 @@ -## -## NUC900 series AC97 API -## -config SND_SOC_NUC900 - tristate "SoC Audio for NUC900 series" - depends on ARCH_W90X900 - help - This option enables support for AC97 mode on the NUC900 SoC. - -config SND_SOC_NUC900_AC97 - tristate - select AC97_BUS - select SND_AC97_CODEC - select SND_SOC_AC97_BUS - - -## -## Boards -## -config SND_SOC_NUC900EVB - tristate "NUC900 AC97 support for demo board" - depends on SND_SOC_NUC900 - select SND_SOC_NUC900_AC97 - select SND_SOC_AC97_CODEC - help - Select this option to enable audio (AC97) on the - NUC900 demoboard. diff --git a/ANDROID_3.4.5/sound/soc/nuc900/Makefile b/ANDROID_3.4.5/sound/soc/nuc900/Makefile deleted file mode 100644 index 7e46c715..00000000 --- a/ANDROID_3.4.5/sound/soc/nuc900/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# NUC900 series audio -snd-soc-nuc900-pcm-objs := nuc900-pcm.o -snd-soc-nuc900-ac97-objs := nuc900-ac97.o - -obj-$(CONFIG_SND_SOC_NUC900) += snd-soc-nuc900-pcm.o -obj-$(CONFIG_SND_SOC_NUC900_AC97) += snd-soc-nuc900-ac97.o - -# Boards -snd-soc-nuc900-audio-objs := nuc900-audio.o - -obj-$(CONFIG_SND_SOC_NUC900EVB) += snd-soc-nuc900-audio.o diff --git a/ANDROID_3.4.5/sound/soc/nuc900/nuc900-ac97.c b/ANDROID_3.4.5/sound/soc/nuc900/nuc900-ac97.c deleted file mode 100644 index 946020a6..00000000 --- a/ANDROID_3.4.5/sound/soc/nuc900/nuc900-ac97.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (c) 2009-2010 Nuvoton technology corporation. - * - * Wan ZongShun - * - * 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;version 2 of the License. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "nuc900-audio.h" - -static DEFINE_MUTEX(ac97_mutex); -struct nuc900_audio *nuc900_ac97_data; - -static int nuc900_checkready(void) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - - if (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS0) & CODEC_READY)) - return -EPERM; - - return 0; -} - -/* AC97 controller reads codec register */ -static unsigned short nuc900_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long timeout = 0x10000, val; - - mutex_lock(&ac97_mutex); - - val = nuc900_checkready(); - if (val) { - dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); - goto out; - } - - /* set the R_WB bit and write register index */ - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, R_WB | reg); - - /* set the valid frame bit and valid slots */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - val |= (VALID_FRAME | SLOT1_VALID); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val); - - udelay(100); - - /* polling the AC_R_FINISH */ - while (!(AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_R_FINISH) - && timeout--) - mdelay(1); - - if (!timeout) { - dev_err(nuc900_audio->dev, "AC97 read register time out !\n"); - val = -EPERM; - goto out; - } - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0) ; - val &= ~SLOT1_VALID; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, val); - - if (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS1) >> 2 != reg) { - dev_err(nuc900_audio->dev, - "R_INDEX of REG_ACTL_ACIS1 not match!\n"); - } - - udelay(100); - val = (AUDIO_READ(nuc900_audio->mmio + ACTL_ACIS2) & 0xFFFF); - -out: - mutex_unlock(&ac97_mutex); - return val; -} - -/* AC97 controller writes to codec register */ -static void nuc900_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long tmp, timeout = 0x10000; - - mutex_lock(&ac97_mutex); - - tmp = nuc900_checkready(); - if (tmp) - dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); - - /* clear the R_WB bit and write register index */ - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS1, reg); - - /* write register value */ - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS2, val); - - /* set the valid frame bit and valid slots */ - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - tmp |= SLOT1_VALID | SLOT2_VALID | VALID_FRAME; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); - - udelay(100); - - /* polling the AC_W_FINISH */ - while ((AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON) & AC_W_FINISH) - && timeout--) - mdelay(1); - - if (!timeout) - dev_err(nuc900_audio->dev, "AC97 write register time out !\n"); - - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - tmp &= ~(SLOT1_VALID | SLOT2_VALID); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); - - mutex_unlock(&ac97_mutex); - -} - -static void nuc900_ac97_warm_reset(struct snd_ac97 *ac97) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long val; - - mutex_lock(&ac97_mutex); - - /* warm reset AC 97 */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); - val |= AC_W_RES; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); - - udelay(100); - - val = nuc900_checkready(); - if (val) - dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); - - mutex_unlock(&ac97_mutex); -} - -static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long val; - - mutex_lock(&ac97_mutex); - - /* reset Audio Controller */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - val |= ACTL_RESET_BIT; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - val &= (~ACTL_RESET_BIT); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - /* reset AC-link interface */ - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - val |= AC_RESET; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - val &= ~AC_RESET; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - /* cold reset AC 97 */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); - val |= AC_C_RES; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_ACCON); - val &= (~AC_C_RES); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACCON, val); - - udelay(100); - - mutex_unlock(&ac97_mutex); - -} - -/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { - .read = nuc900_ac97_read, - .write = nuc900_ac97_write, - .reset = nuc900_ac97_cold_reset, - .warm_reset = nuc900_ac97_warm_reset, -} -EXPORT_SYMBOL_GPL(soc_ac97_ops); - -static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - int ret; - unsigned long val, tmp; - - ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - tmp |= (SLOT3_VALID | SLOT4_VALID | VALID_FRAME); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); - - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR); - tmp |= (P_DMA_END_IRQ | P_DMA_MIDDLE_IRQ); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, tmp); - val |= AC_PLAY; - } else { - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR); - tmp |= (R_DMA_END_IRQ | R_DMA_MIDDLE_IRQ); - - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, tmp); - val |= AC_RECORD; - } - - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - tmp = AUDIO_READ(nuc900_audio->mmio + ACTL_ACOS0); - tmp &= ~(SLOT3_VALID | SLOT4_VALID); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_ACOS0, tmp); - - AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, RESET_PRSR); - val &= ~AC_PLAY; - } else { - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, RESET_PRSR); - val &= ~AC_RECORD; - } - - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static int nuc900_ac97_probe(struct snd_soc_dai *dai) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - unsigned long val; - - mutex_lock(&ac97_mutex); - - /* enable unit clock */ - clk_enable(nuc900_audio->clk); - - /* enable audio controller and AC-link interface */ - val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); - val |= (IIS_AC_PIN_SEL | ACLINK_EN); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); - - mutex_unlock(&ac97_mutex); - - return 0; -} - -static int nuc900_ac97_remove(struct snd_soc_dai *dai) -{ - struct nuc900_audio *nuc900_audio = nuc900_ac97_data; - - clk_disable(nuc900_audio->clk); - return 0; -} - -static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = { - .trigger = nuc900_ac97_trigger, -}; - -static struct snd_soc_dai_driver nuc900_ac97_dai = { - .probe = nuc900_ac97_probe, - .remove = nuc900_ac97_remove, - .ac97_control = 1, - .playback = { - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 1, - .channels_max = 2, - }, - .capture = { - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 1, - .channels_max = 2, - }, - .ops = &nuc900_ac97_dai_ops, -}; - -static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) -{ - struct nuc900_audio *nuc900_audio; - int ret; - - if (nuc900_ac97_data) - return -EBUSY; - - nuc900_audio = kzalloc(sizeof(struct nuc900_audio), GFP_KERNEL); - if (!nuc900_audio) - return -ENOMEM; - - spin_lock_init(&nuc900_audio->lock); - - nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!nuc900_audio->res) { - ret = -ENODEV; - goto out0; - } - - if (!request_mem_region(nuc900_audio->res->start, - resource_size(nuc900_audio->res), pdev->name)) { - ret = -EBUSY; - goto out0; - } - - nuc900_audio->mmio = ioremap(nuc900_audio->res->start, - resource_size(nuc900_audio->res)); - if (!nuc900_audio->mmio) { - ret = -ENOMEM; - goto out1; - } - - nuc900_audio->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(nuc900_audio->clk)) { - ret = PTR_ERR(nuc900_audio->clk); - goto out2; - } - - nuc900_audio->irq_num = platform_get_irq(pdev, 0); - if (!nuc900_audio->irq_num) { - ret = -EBUSY; - goto out3; - } - - nuc900_ac97_data = nuc900_audio; - - ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai); - if (ret) - goto out3; - - /* enbale ac97 multifunction pin */ - mfp_set_groupg(nuc900_audio->dev, NULL); - - return 0; - -out3: - clk_put(nuc900_audio->clk); -out2: - iounmap(nuc900_audio->mmio); -out1: - release_mem_region(nuc900_audio->res->start, - resource_size(nuc900_audio->res)); -out0: - kfree(nuc900_audio); - return ret; -} - -static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) -{ - snd_soc_unregister_dai(&pdev->dev); - - clk_put(nuc900_ac97_data->clk); - iounmap(nuc900_ac97_data->mmio); - release_mem_region(nuc900_ac97_data->res->start, - resource_size(nuc900_ac97_data->res)); - - kfree(nuc900_ac97_data); - nuc900_ac97_data = NULL; - - return 0; -} - -static struct platform_driver nuc900_ac97_driver = { - .driver = { - .name = "nuc900-ac97", - .owner = THIS_MODULE, - }, - .probe = nuc900_ac97_drvprobe, - .remove = __devexit_p(nuc900_ac97_drvremove), -}; - -module_platform_driver(nuc900_ac97_driver); - -MODULE_AUTHOR("Wan ZongShun "); -MODULE_DESCRIPTION("NUC900 AC97 SoC driver!"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-ac97"); diff --git a/ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.c b/ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.c deleted file mode 100644 index 2f6e6fd6..00000000 --- a/ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2010 Nuvoton technology corporation. - * - * Wan ZongShun - * - * 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;version 2 of the License. - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "nuc900-audio.h" - -static struct snd_soc_dai_link nuc900evb_ac97_dai = { - .name = "AC97", - .stream_name = "AC97 HiFi", - .cpu_dai_name = "nuc900-ac97", - .codec_dai_name = "ac97-hifi", - .codec_name = "ac97-codec", - .platform_name = "nuc900-pcm-audio", -}; - -static struct snd_soc_card nuc900evb_audio_machine = { - .name = "NUC900EVB_AC97", - .owner = THIS_MODULE, - .dai_link = &nuc900evb_ac97_dai, - .num_links = 1, -}; - -static struct platform_device *nuc900evb_asoc_dev; - -static int __init nuc900evb_audio_init(void) -{ - int ret; - - ret = -ENOMEM; - nuc900evb_asoc_dev = platform_device_alloc("soc-audio", -1); - if (!nuc900evb_asoc_dev) - goto out; - - /* nuc900 board audio device */ - platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_audio_machine); - - ret = platform_device_add(nuc900evb_asoc_dev); - - if (ret) { - platform_device_put(nuc900evb_asoc_dev); - nuc900evb_asoc_dev = NULL; - } - -out: - return ret; -} - -static void __exit nuc900evb_audio_exit(void) -{ - platform_device_unregister(nuc900evb_asoc_dev); -} - -module_init(nuc900evb_audio_init); -module_exit(nuc900evb_audio_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("NUC900 Series ASoC audio support"); -MODULE_AUTHOR("Wan ZongShun"); diff --git a/ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.h b/ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.h deleted file mode 100644 index 59f7e8ed..00000000 --- a/ANDROID_3.4.5/sound/soc/nuc900/nuc900-audio.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2010 Nuvoton technology corporation. - * - * Wan ZongShun - * - * 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;version 2 of the License. - * - */ - -#ifndef _NUC900_AUDIO_H -#define _NUC900_AUDIO_H - -#include - -/* Audio Control Registers */ -#define ACTL_CON 0x00 -#define ACTL_RESET 0x04 -#define ACTL_RDSTB 0x08 -#define ACTL_RDST_LENGTH 0x0C -#define ACTL_RDSTC 0x10 -#define ACTL_RSR 0x14 -#define ACTL_PDSTB 0x18 -#define ACTL_PDST_LENGTH 0x1C -#define ACTL_PDSTC 0x20 -#define ACTL_PSR 0x24 -#define ACTL_IISCON 0x28 -#define ACTL_ACCON 0x2C -#define ACTL_ACOS0 0x30 -#define ACTL_ACOS1 0x34 -#define ACTL_ACOS2 0x38 -#define ACTL_ACIS0 0x3C -#define ACTL_ACIS1 0x40 -#define ACTL_ACIS2 0x44 -#define ACTL_COUNTER 0x48 - -/* bit definition of REG_ACTL_CON register */ -#define R_DMA_IRQ 0x1000 -#define T_DMA_IRQ 0x0800 -#define IIS_AC_PIN_SEL 0x0100 -#define FIFO_TH 0x0080 -#define ADC_EN 0x0010 -#define M80_EN 0x0008 -#define ACLINK_EN 0x0004 -#define IIS_EN 0x0002 - -/* bit definition of REG_ACTL_RESET register */ -#define W5691_PLAY 0x20000 -#define ACTL_RESET_BIT 0x10000 -#define RECORD_RIGHT_CHNNEL 0x08000 -#define RECORD_LEFT_CHNNEL 0x04000 -#define PLAY_RIGHT_CHNNEL 0x02000 -#define PLAY_LEFT_CHNNEL 0x01000 -#define DAC_PLAY 0x00800 -#define ADC_RECORD 0x00400 -#define M80_PLAY 0x00200 -#define AC_RECORD 0x00100 -#define AC_PLAY 0x00080 -#define IIS_RECORD 0x00040 -#define IIS_PLAY 0x00020 -#define DAC_RESET 0x00010 -#define ADC_RESET 0x00008 -#define M80_RESET 0x00004 -#define AC_RESET 0x00002 -#define IIS_RESET 0x00001 - -/* bit definition of REG_ACTL_ACCON register */ -#define AC_BCLK_PU_EN 0x20 -#define AC_R_FINISH 0x10 -#define AC_W_FINISH 0x08 -#define AC_W_RES 0x04 -#define AC_C_RES 0x02 - -/* bit definition of ACTL_RSR register */ -#define R_FIFO_EMPTY 0x04 -#define R_DMA_END_IRQ 0x02 -#define R_DMA_MIDDLE_IRQ 0x01 - -/* bit definition of ACTL_PSR register */ -#define P_FIFO_EMPTY 0x04 -#define P_DMA_END_IRQ 0x02 -#define P_DMA_MIDDLE_IRQ 0x01 - -/* bit definition of ACTL_ACOS0 register */ -#define SLOT1_VALID 0x01 -#define SLOT2_VALID 0x02 -#define SLOT3_VALID 0x04 -#define SLOT4_VALID 0x08 -#define VALID_FRAME 0x10 - -/* bit definition of ACTL_ACOS1 register */ -#define R_WB 0x80 - -#define CODEC_READY 0x10 -#define RESET_PRSR 0x00 -#define AUDIO_WRITE(addr, val) __raw_writel(val, addr) -#define AUDIO_READ(addr) __raw_readl(addr) - -struct nuc900_audio { - void __iomem *mmio; - spinlock_t lock; - dma_addr_t dma_addr[2]; - unsigned long buffersize[2]; - unsigned long irq_num; - struct snd_pcm_substream *substream; - struct resource *res; - struct clk *clk; - struct device *dev; - -}; - -extern struct nuc900_audio *nuc900_ac97_data; - -#endif /*end _NUC900_AUDIO_H */ diff --git a/ANDROID_3.4.5/sound/soc/nuc900/nuc900-pcm.c b/ANDROID_3.4.5/sound/soc/nuc900/nuc900-pcm.c deleted file mode 100644 index 37585b47..00000000 --- a/ANDROID_3.4.5/sound/soc/nuc900/nuc900-pcm.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2010 Nuvoton technology corporation. - * - * Wan ZongShun - * - * 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;version 2 of the License. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "nuc900-audio.h" - -static const struct snd_pcm_hardware nuc900_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 4*1024, - .period_bytes_min = 1*1024, - .period_bytes_max = 4*1024, - .periods_min = 1, - .periods_max = 1024, -}; - -static int nuc900_dma_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - unsigned long flags; - int ret = 0; - - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (ret < 0) - return ret; - - spin_lock_irqsave(&nuc900_audio->lock, flags); - - nuc900_audio->substream = substream; - nuc900_audio->dma_addr[substream->stream] = runtime->dma_addr; - nuc900_audio->buffersize[substream->stream] = - params_buffer_bytes(params); - - spin_unlock_irqrestore(&nuc900_audio->lock, flags); - - return ret; -} - -static void nuc900_update_dma_register(struct snd_pcm_substream *substream, - dma_addr_t dma_addr, size_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - void __iomem *mmio_addr, *mmio_len; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - mmio_addr = nuc900_audio->mmio + ACTL_PDSTB; - mmio_len = nuc900_audio->mmio + ACTL_PDST_LENGTH; - } else { - mmio_addr = nuc900_audio->mmio + ACTL_RDSTB; - mmio_len = nuc900_audio->mmio + ACTL_RDST_LENGTH; - } - - AUDIO_WRITE(mmio_addr, dma_addr); - AUDIO_WRITE(mmio_len, count); -} - -static void nuc900_dma_start(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - unsigned long val; - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); - val |= (T_DMA_IRQ | R_DMA_IRQ); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); -} - -static void nuc900_dma_stop(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - unsigned long val; - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); - val &= ~(T_DMA_IRQ | R_DMA_IRQ); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val); -} - -static irqreturn_t nuc900_dma_interrupt(int irq, void *dev_id) -{ - struct snd_pcm_substream *substream = dev_id; - struct nuc900_audio *nuc900_audio = substream->runtime->private_data; - unsigned long val; - - spin_lock(&nuc900_audio->lock); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_CON); - - if (val & R_DMA_IRQ) { - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | R_DMA_IRQ); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RSR); - - if (val & R_DMA_MIDDLE_IRQ) { - val |= R_DMA_MIDDLE_IRQ; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val); - } - - if (val & R_DMA_END_IRQ) { - val |= R_DMA_END_IRQ; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RSR, val); - } - } else if (val & T_DMA_IRQ) { - AUDIO_WRITE(nuc900_audio->mmio + ACTL_CON, val | T_DMA_IRQ); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_PSR); - - if (val & P_DMA_MIDDLE_IRQ) { - val |= P_DMA_MIDDLE_IRQ; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val); - } - - if (val & P_DMA_END_IRQ) { - val |= P_DMA_END_IRQ; - AUDIO_WRITE(nuc900_audio->mmio + ACTL_PSR, val); - } - } else { - dev_err(nuc900_audio->dev, "Wrong DMA interrupt status!\n"); - spin_unlock(&nuc900_audio->lock); - return IRQ_HANDLED; - } - - spin_unlock(&nuc900_audio->lock); - - snd_pcm_period_elapsed(substream); - - return IRQ_HANDLED; -} - -static int nuc900_dma_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int nuc900_dma_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - unsigned long flags, val; - int ret = 0; - - spin_lock_irqsave(&nuc900_audio->lock, flags); - - nuc900_update_dma_register(substream, - nuc900_audio->dma_addr[substream->stream], - nuc900_audio->buffersize[substream->stream]); - - val = AUDIO_READ(nuc900_audio->mmio + ACTL_RESET); - - switch (runtime->channels) { - case 1: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - val &= ~(PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL); - val |= PLAY_RIGHT_CHNNEL; - } else { - val &= ~(RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL); - val |= RECORD_RIGHT_CHNNEL; - } - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - break; - case 2: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - val |= (PLAY_LEFT_CHNNEL | PLAY_RIGHT_CHNNEL); - else - val |= (RECORD_LEFT_CHNNEL | RECORD_RIGHT_CHNNEL); - AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); - break; - default: - ret = -EINVAL; - } - spin_unlock_irqrestore(&nuc900_audio->lock, flags); - return ret; -} - -static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd) -{ - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - nuc900_dma_start(substream); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - nuc900_dma_stop(substream); - break; - - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int nuc900_dma_getposition(struct snd_pcm_substream *substream, - dma_addr_t *src, dma_addr_t *dst) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - - if (src != NULL) - *src = AUDIO_READ(nuc900_audio->mmio + ACTL_PDSTC); - - if (dst != NULL) - *dst = AUDIO_READ(nuc900_audio->mmio + ACTL_RDSTC); - - return 0; -} - -static snd_pcm_uframes_t nuc900_dma_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - dma_addr_t src, dst; - unsigned long res; - - nuc900_dma_getposition(substream, &src, &dst); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - res = dst - runtime->dma_addr; - else - res = src - runtime->dma_addr; - - return bytes_to_frames(substream->runtime, res); -} - -static int nuc900_dma_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio; - - snd_soc_set_runtime_hwparams(substream, &nuc900_pcm_hardware); - - nuc900_audio = nuc900_ac97_data; - - if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt, - 0, "nuc900-dma", substream)) - return -EBUSY; - - runtime->private_data = nuc900_audio; - - return 0; -} - -static int nuc900_dma_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct nuc900_audio *nuc900_audio = runtime->private_data; - - free_irq(nuc900_audio->irq_num, substream); - - return 0; -} - -static int nuc900_dma_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - -static struct snd_pcm_ops nuc900_dma_ops = { - .open = nuc900_dma_open, - .close = nuc900_dma_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = nuc900_dma_hw_params, - .hw_free = nuc900_dma_hw_free, - .prepare = nuc900_dma_prepare, - .trigger = nuc900_dma_trigger, - .pointer = nuc900_dma_pointer, - .mmap = nuc900_dma_mmap, -}; - -static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32); -static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &nuc900_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - card->dev, 4 * 1024, (4 * 1024) - 1); - - return 0; -} - -static struct snd_soc_platform_driver nuc900_soc_platform = { - .ops = &nuc900_dma_ops, - .pcm_new = nuc900_dma_new, - .pcm_free = nuc900_dma_free_dma_buffers, -}; - -static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform); -} - -static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver nuc900_pcm_driver = { - .driver = { - .name = "nuc900-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = nuc900_soc_platform_probe, - .remove = __devexit_p(nuc900_soc_platform_remove), -}; - -module_platform_driver(nuc900_pcm_driver); - -MODULE_AUTHOR("Wan ZongShun, "); -MODULE_DESCRIPTION("nuc900 Audio DMA module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/Kconfig b/ANDROID_3.4.5/sound/soc/omap/Kconfig deleted file mode 100644 index deafbfaa..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/Kconfig +++ /dev/null @@ -1,152 +0,0 @@ -config SND_OMAP_SOC - tristate "SoC Audio for the Texas Instruments OMAP chips" - depends on ARCH_OMAP - -config SND_OMAP_SOC_DMIC - tristate - -config SND_OMAP_SOC_MCBSP - tristate - -config SND_OMAP_SOC_MCPDM - tristate - -config SND_OMAP_SOC_HDMI - tristate - -config SND_OMAP_SOC_N810 - tristate "SoC Audio support for Nokia N810" - depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C - depends on OMAP_MUX - select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC3X - help - Say Y if you want to add support for SoC audio on Nokia N810. - -config SND_OMAP_SOC_RX51 - tristate "SoC Audio support for Nokia RX-51" - depends on SND_OMAP_SOC && MACH_NOKIA_RX51 - select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC3X - select SND_SOC_TPA6130A2 - help - Say Y if you want to add support for SoC audio on Nokia RX-51 - hardware. This is also known as Nokia N900 product. - -config SND_OMAP_SOC_AMS_DELTA - tristate "SoC Audio support for Amstrad E3 (Delta) videophone" - depends on SND_OMAP_SOC && MACH_AMS_DELTA - select SND_OMAP_SOC_MCBSP - select SND_SOC_CX20442 - help - Say Y if you want to add support for SoC audio device connected to - a handset and a speakerphone found on Amstrad E3 (Delta) videophone. - - Note that in order to get those devices fully supported, you have to - build the kernel with standard serial port driver included and - configured for at least 4 ports. Then, from userspace, you must load - a line discipline #19 on the modem (ttyS3) serial line. The simplest - way to achieve this is to install util-linux-ng and use the included - ldattach utility. This can be started automatically from udev, - a simple rule like this one should do the trick (it does for me): - ACTION=="add", KERNEL=="controlC0", \ - RUN+="/usr/sbin/ldattach 19 /dev/ttyS3" - -config SND_OMAP_SOC_OSK5912 - tristate "SoC Audio support for omap osk5912" - depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C - select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 - help - Say Y if you want to add support for SoC audio on osk5912. - -config SND_OMAP_SOC_OVERO - tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35" - depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35) - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the - Gumstix Overo or CompuLab CM-T35 - -config SND_OMAP_SOC_OMAP3EVM - tristate "SoC Audio support for OMAP3EVM board" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the omap3evm board. - -config SND_OMAP_SOC_AM3517EVM - tristate "SoC Audio support for OMAP3517 / AM3517 EVM" - depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C - select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 - help - Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 - EVM. - -config SND_OMAP_SOC_SDP3430 - tristate "SoC Audio support for Texas Instruments SDP3430" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on Texas Instruments - SDP3430. - -config SND_OMAP_SOC_OMAP_ABE_TWL6040 - tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" - depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 - select SND_OMAP_SOC_DMIC - select SND_OMAP_SOC_MCPDM - select SND_SOC_TWL6040 - select SND_SOC_DMIC - help - Say Y if you want to add support for SoC audio on OMAP boards using - ABE and twl6040 codec. This driver currently supports: - - SDP4430/Blaze boards - - PandaBoard (4430) - - PandaBoardES (4460) - -config SND_OMAP_SOC_OMAP4_HDMI - tristate "SoC Audio support for Texas Instruments OMAP4 HDMI" - depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS && ARCH_OMAP4 - select SND_OMAP_SOC_HDMI - help - Say Y if you want to add support for SoC HDMI audio on Texas Instruments - OMAP4 chips - -config SND_OMAP_SOC_OMAP3_PANDORA - tristate "SoC Audio support for OMAP3 Pandora" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the OMAP3 Pandora. - -config SND_OMAP_SOC_OMAP3_BEAGLE - tristate "SoC Audio support for OMAP3 Beagle and Devkit8000" - depends on TWL4030_CORE && SND_OMAP_SOC - depends on (MACH_OMAP3_BEAGLE || MACH_DEVKIT8000) - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for SoC audio on the Beagleboard or - the clone Devkit8000. - -config SND_OMAP_SOC_ZOOM2 - tristate "SoC Audio support for Zoom2" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for Soc audio on Zoom2 board. - -config SND_OMAP_SOC_IGEP0020 - tristate "SoC Audio support for IGEP v2" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020 - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for Soc audio on IGEP v2 board. diff --git a/ANDROID_3.4.5/sound/soc/omap/Makefile b/ANDROID_3.4.5/sound/soc/omap/Makefile deleted file mode 100644 index 1d656bce..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# OMAP Platform Support -snd-soc-omap-objs := omap-pcm.o -snd-soc-omap-dmic-objs := omap-dmic.o -snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o -snd-soc-omap-mcpdm-objs := omap-mcpdm.o -snd-soc-omap-hdmi-objs := omap-hdmi.o - -obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o -obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o -obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o -obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o -obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o - -# OMAP Machine Support -snd-soc-n810-objs := n810.o -snd-soc-rx51-objs := rx51.o -snd-soc-ams-delta-objs := ams-delta.o -snd-soc-osk5912-objs := osk5912.o -snd-soc-overo-objs := overo.o -snd-soc-omap3evm-objs := omap3evm.o -snd-soc-am3517evm-objs := am3517evm.o -snd-soc-sdp3430-objs := sdp3430.o -snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o -snd-soc-omap3pandora-objs := omap3pandora.o -snd-soc-omap3beagle-objs := omap3beagle.o -snd-soc-zoom2-objs := zoom2.o -snd-soc-igep0020-objs := igep0020.o -snd-soc-omap4-hdmi-objs := omap4-hdmi-card.o - -obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o -obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o -obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o -obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o -obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o -obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o -obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o -obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o -obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o -obj-$(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) += snd-soc-omap4-hdmi.o diff --git a/ANDROID_3.4.5/sound/soc/omap/am3517evm.c b/ANDROID_3.4.5/sound/soc/omap/am3517evm.c deleted file mode 100644 index 009533ab..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/am3517evm.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * am3517evm.c -- ALSA SoC support for OMAP3517 / AM3517 EVM - * - * Author: Anuj Aggarwal - * - * Based on sound/soc/omap/beagle.c by Steve Sakoman - * - * Copyright (C) 2009 Texas Instruments Incorporated - * - * 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 version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, - * whether express or implied; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -#include "../codecs/tlv320aic23.h" - -#define CODEC_CLOCK 12000000 - -static int am3517evm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, - CODEC_CLOCK, SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n"); - return ret; - } - - snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops am3517evm_ops = { - .hw_params = am3517evm_hw_params, -}; - -/* am3517evm machine dapm widgets */ -static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { - SND_SOC_DAPM_HP("Line Out", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), - SND_SOC_DAPM_MIC("Mic In", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Line Out connected to LLOUT, RLOUT */ - {"Line Out", NULL, "LOUT"}, - {"Line Out", NULL, "ROUT"}, - - {"LLINEIN", NULL, "Line In"}, - {"RLINEIN", NULL, "Line In"}, - - {"MICIN", NULL, "Mic In"}, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link am3517evm_dai = { - .name = "TLV320AIC23", - .stream_name = "AIC23", - .cpu_dai_name = "omap-mcbsp.1", - .codec_dai_name = "tlv320aic23-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "tlv320aic23-codec.2-001a", - .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &am3517evm_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_am3517evm = { - .name = "am3517evm", - .owner = THIS_MODULE, - .dai_link = &am3517evm_dai, - .num_links = 1, - - .dapm_widgets = tlv320aic23_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), -}; - -static struct platform_device *am3517evm_snd_device; - -static int __init am3517evm_soc_init(void) -{ - int ret; - - if (!machine_is_omap3517evm()) - return -ENODEV; - pr_info("OMAP3517 / AM3517 EVM SoC init\n"); - - am3517evm_snd_device = platform_device_alloc("soc-audio", -1); - if (!am3517evm_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(am3517evm_snd_device, &snd_soc_am3517evm); - - ret = platform_device_add(am3517evm_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(am3517evm_snd_device); - - return ret; -} - -static void __exit am3517evm_soc_exit(void) -{ - platform_device_unregister(am3517evm_snd_device); -} - -module_init(am3517evm_soc_init); -module_exit(am3517evm_soc_exit); - -MODULE_AUTHOR("Anuj Aggarwal "); -MODULE_DESCRIPTION("ALSA SoC OMAP3517 / AM3517 EVM"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/soc/omap/ams-delta.c b/ANDROID_3.4.5/sound/soc/omap/ams-delta.c deleted file mode 100644 index 7d4fa8ed..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/ams-delta.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * ams-delta.c -- SoC audio for Amstrad E3 (Delta) videophone - * - * Copyright (C) 2009 Janusz Krzysztofik - * - * Initially based on sound/soc/omap/osk5912.x - * Copyright (C) 2008 Mistral Solutions - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" -#include "../codecs/cx20442.h" - - -/* Board specific DAPM widgets */ -static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { - /* Handset */ - SND_SOC_DAPM_MIC("Mouthpiece", NULL), - SND_SOC_DAPM_HP("Earpiece", NULL), - /* Handsfree/Speakerphone */ - SND_SOC_DAPM_MIC("Microphone", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -/* How they are connected to codec pins */ -static const struct snd_soc_dapm_route ams_delta_audio_map[] = { - {"TELIN", NULL, "Mouthpiece"}, - {"Earpiece", NULL, "TELOUT"}, - - {"MIC", NULL, "Microphone"}, - {"Speaker", NULL, "SPKOUT"}, -}; - -/* - * Controls, functional after the modem line discipline is activated. - */ - -/* Virtual switch: audio input/output constellations */ -static const char *ams_delta_audio_mode[] = - {"Mixed", "Handset", "Handsfree", "Speakerphone"}; - -/* Selection <-> pin translation */ -#define AMS_DELTA_MOUTHPIECE 0 -#define AMS_DELTA_EARPIECE 1 -#define AMS_DELTA_MICROPHONE 2 -#define AMS_DELTA_SPEAKER 3 -#define AMS_DELTA_AGC 4 - -#define AMS_DELTA_MIXED ((1 << AMS_DELTA_EARPIECE) | \ - (1 << AMS_DELTA_MICROPHONE)) -#define AMS_DELTA_HANDSET ((1 << AMS_DELTA_MOUTHPIECE) | \ - (1 << AMS_DELTA_EARPIECE)) -#define AMS_DELTA_HANDSFREE ((1 << AMS_DELTA_MICROPHONE) | \ - (1 << AMS_DELTA_SPEAKER)) -#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC)) - -static const unsigned short ams_delta_audio_mode_pins[] = { - AMS_DELTA_MIXED, - AMS_DELTA_HANDSET, - AMS_DELTA_HANDSFREE, - AMS_DELTA_SPEAKERPHONE, -}; - -static unsigned short ams_delta_audio_agc; - -static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_context *dapm = &codec->dapm; - struct soc_enum *control = (struct soc_enum *)kcontrol->private_value; - unsigned short pins; - int pin, changed = 0; - - /* Refuse any mode changes if we are not able to control the codec. */ - if (!codec->hw_write) - return -EUNATCH; - - if (ucontrol->value.enumerated.item[0] >= control->max) - return -EINVAL; - - mutex_lock(&codec->mutex); - - /* Translate selection to bitmap */ - pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; - - /* Setup pins after corresponding bits if changed */ - pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); - if (pin != snd_soc_dapm_get_pin_status(dapm, "Mouthpiece")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(dapm, "Mouthpiece"); - else - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); - } - pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); - if (pin != snd_soc_dapm_get_pin_status(dapm, "Earpiece")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(dapm, "Earpiece"); - else - snd_soc_dapm_disable_pin(dapm, "Earpiece"); - } - pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); - if (pin != snd_soc_dapm_get_pin_status(dapm, "Microphone")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(dapm, "Microphone"); - else - snd_soc_dapm_disable_pin(dapm, "Microphone"); - } - pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); - if (pin != snd_soc_dapm_get_pin_status(dapm, "Speaker")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(dapm, "Speaker"); - else - snd_soc_dapm_disable_pin(dapm, "Speaker"); - } - pin = !!(pins & (1 << AMS_DELTA_AGC)); - if (pin != ams_delta_audio_agc) { - ams_delta_audio_agc = pin; - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(dapm, "AGCIN"); - else - snd_soc_dapm_disable_pin(dapm, "AGCIN"); - } - if (changed) - snd_soc_dapm_sync(dapm); - - mutex_unlock(&codec->mutex); - - return changed; -} - -static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct snd_soc_dapm_context *dapm = &codec->dapm; - unsigned short pins, mode; - - pins = ((snd_soc_dapm_get_pin_status(dapm, "Mouthpiece") << - AMS_DELTA_MOUTHPIECE) | - (snd_soc_dapm_get_pin_status(dapm, "Earpiece") << - AMS_DELTA_EARPIECE)); - if (pins) - pins |= (snd_soc_dapm_get_pin_status(dapm, "Microphone") << - AMS_DELTA_MICROPHONE); - else - pins = ((snd_soc_dapm_get_pin_status(dapm, "Microphone") << - AMS_DELTA_MICROPHONE) | - (snd_soc_dapm_get_pin_status(dapm, "Speaker") << - AMS_DELTA_SPEAKER) | - (ams_delta_audio_agc << AMS_DELTA_AGC)); - - for (mode = 0; mode < ARRAY_SIZE(ams_delta_audio_mode); mode++) - if (pins == ams_delta_audio_mode_pins[mode]) - break; - - if (mode >= ARRAY_SIZE(ams_delta_audio_mode)) - return -EINVAL; - - ucontrol->value.enumerated.item[0] = mode; - - return 0; -} - -static const struct soc_enum ams_delta_audio_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode), - ams_delta_audio_mode), -}; - -static const struct snd_kcontrol_new ams_delta_audio_controls[] = { - SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0], - ams_delta_get_audio_mode, ams_delta_set_audio_mode), -}; - -/* Hook switch */ -static struct snd_soc_jack ams_delta_hook_switch; -static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = { - { - .gpio = 4, - .name = "hook_switch", - .report = SND_JACK_HEADSET, - .invert = 1, - .debounce_time = 150, - } -}; - -/* After we are able to control the codec over the modem, - * the hook switch can be used for dynamic DAPM reconfiguration. */ -static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = { - /* Handset */ - { - .pin = "Mouthpiece", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Earpiece", - .mask = SND_JACK_HEADPHONE, - }, - /* Handsfree */ - { - .pin = "Microphone", - .mask = SND_JACK_MICROPHONE, - .invert = 1, - }, - { - .pin = "Speaker", - .mask = SND_JACK_HEADPHONE, - .invert = 1, - }, -}; - - -/* - * Modem line discipline, required for making above controls functional. - * Activated from userspace with ldattach, possibly invoked from udev rule. - */ - -/* To actually apply any modem controlled configuration changes to the codec, - * we must connect codec DAI pins to the modem for a moment. Be careful not - * to interfere with our digital mute function that shares the same hardware. */ -static struct timer_list cx81801_timer; -static bool cx81801_cmd_pending; -static bool ams_delta_muted; -static DEFINE_SPINLOCK(ams_delta_lock); - -static void cx81801_timeout(unsigned long data) -{ - int muted; - - spin_lock(&ams_delta_lock); - cx81801_cmd_pending = 0; - muted = ams_delta_muted; - spin_unlock(&ams_delta_lock); - - /* Reconnect the codec DAI back from the modem to the CPU DAI - * only if digital mute still off */ - if (!muted) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); -} - -/* - * Used for passing a codec structure pointer - * from the board initialization code to the tty line discipline. - */ -static struct snd_soc_codec *cx20442_codec; - -/* Line discipline .open() */ -static int cx81801_open(struct tty_struct *tty) -{ - int ret; - - if (!cx20442_codec) - return -ENODEV; - - /* - * Pass the codec structure pointer for use by other ldisc callbacks, - * both the card and the codec specific parts. - */ - tty->disc_data = cx20442_codec; - - ret = v253_ops.open(tty); - - if (ret < 0) - tty->disc_data = NULL; - - return ret; -} - -/* Line discipline .close() */ -static void cx81801_close(struct tty_struct *tty) -{ - struct snd_soc_codec *codec = tty->disc_data; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - del_timer_sync(&cx81801_timer); - - /* Prevent the hook switch from further changing the DAPM pins */ - INIT_LIST_HEAD(&ams_delta_hook_switch.pins); - - if (!codec) - return; - - v253_ops.close(tty); - - /* Revert back to default audio input/output constellation */ - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); - snd_soc_dapm_enable_pin(dapm, "Earpiece"); - snd_soc_dapm_enable_pin(dapm, "Microphone"); - snd_soc_dapm_disable_pin(dapm, "Speaker"); - snd_soc_dapm_disable_pin(dapm, "AGCIN"); - snd_soc_dapm_sync(dapm); -} - -/* Line discipline .hangup() */ -static int cx81801_hangup(struct tty_struct *tty) -{ - cx81801_close(tty); - return 0; -} - -/* Line discipline .receive_buf() */ -static void cx81801_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) -{ - struct snd_soc_codec *codec = tty->disc_data; - const unsigned char *c; - int apply, ret; - - if (!codec) - return; - - if (!codec->hw_write) { - /* First modem response, complete setup procedure */ - - /* Initialize timer used for config pulse generation */ - setup_timer(&cx81801_timer, cx81801_timeout, 0); - - v253_ops.receive_buf(tty, cp, fp, count); - - /* Link hook switch to DAPM pins */ - ret = snd_soc_jack_add_pins(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_pins), - ams_delta_hook_switch_pins); - if (ret) - dev_warn(codec->dev, - "Failed to link hook switch to DAPM pins, " - "will continue with hook switch unlinked.\n"); - - return; - } - - v253_ops.receive_buf(tty, cp, fp, count); - - for (c = &cp[count - 1]; c >= cp; c--) { - if (*c != '\r') - continue; - /* Complete modem response received, apply config to codec */ - - spin_lock_bh(&ams_delta_lock); - mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150)); - apply = !ams_delta_muted && !cx81801_cmd_pending; - cx81801_cmd_pending = 1; - spin_unlock_bh(&ams_delta_lock); - - /* Apply config pulse by connecting the codec to the modem - * if not already done */ - if (apply) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, - AMS_DELTA_LATCH2_MODEM_CODEC); - break; - } -} - -/* Line discipline .write_wakeup() */ -static void cx81801_wakeup(struct tty_struct *tty) -{ - v253_ops.write_wakeup(tty); -} - -static struct tty_ldisc_ops cx81801_ops = { - .magic = TTY_LDISC_MAGIC, - .name = "cx81801", - .owner = THIS_MODULE, - .open = cx81801_open, - .close = cx81801_close, - .hangup = cx81801_hangup, - .receive_buf = cx81801_receive, - .write_wakeup = cx81801_wakeup, -}; - - -/* - * Even if not very useful, the sound card can still work without any of the - * above functonality activated. You can still control its audio input/output - * constellation and speakerphone gain from userspace by issuing AT commands - * over the modem port. - */ - -static int ams_delta_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - - /* Set cpu DAI configuration */ - return snd_soc_dai_set_fmt(rtd->cpu_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); -} - -static struct snd_soc_ops ams_delta_ops = { - .hw_params = ams_delta_hw_params, -}; - - -/* Digital mute implemented using modem/CPU multiplexer. - * Shares hardware with codec config pulse generation */ -static bool ams_delta_muted = 1; - -static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute) -{ - int apply; - - if (ams_delta_muted == mute) - return 0; - - spin_lock_bh(&ams_delta_lock); - ams_delta_muted = mute; - apply = !cx81801_cmd_pending; - spin_unlock_bh(&ams_delta_lock); - - if (apply) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, - mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0); - return 0; -} - -/* Our codec DAI probably doesn't have its own .ops structure */ -static const struct snd_soc_dai_ops ams_delta_dai_ops = { - .digital_mute = ams_delta_digital_mute, -}; - -/* Will be used if the codec ever has its own digital_mute function */ -static int ams_delta_startup(struct snd_pcm_substream *substream) -{ - return ams_delta_digital_mute(NULL, 0); -} - -static void ams_delta_shutdown(struct snd_pcm_substream *substream) -{ - ams_delta_digital_mute(NULL, 1); -} - - -/* - * Card initialization - */ - -static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_card *card = rtd->card; - int ret; - /* Codec is ready, now add/activate board specific controls */ - - /* Store a pointer to the codec structure for tty ldisc use */ - cx20442_codec = codec; - - /* Set up digital mute if not provided by the codec */ - if (!codec_dai->driver->ops) { - codec_dai->driver->ops = &ams_delta_dai_ops; - } else { - ams_delta_ops.startup = ams_delta_startup; - ams_delta_ops.shutdown = ams_delta_shutdown; - } - - /* Add hook switch - can be used to control the codec from userspace - * even if line discipline fails */ - ret = snd_soc_jack_new(rtd->codec, "hook_switch", - SND_JACK_HEADSET, &ams_delta_hook_switch); - if (ret) - dev_warn(card->dev, - "Failed to allocate resources for hook switch, " - "will continue without one.\n"); - else { - ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_gpios), - ams_delta_hook_switch_gpios); - if (ret) - dev_warn(card->dev, - "Failed to set up hook switch GPIO line, " - "will continue with hook switch inactive.\n"); - } - - /* Register optional line discipline for over the modem control */ - ret = tty_register_ldisc(N_V253, &cx81801_ops); - if (ret) { - dev_warn(card->dev, - "Failed to register line discipline, " - "will continue without any controls.\n"); - return 0; - } - - /* Add board specific DAPM widgets and routes */ - ret = snd_soc_dapm_new_controls(dapm, ams_delta_dapm_widgets, - ARRAY_SIZE(ams_delta_dapm_widgets)); - if (ret) { - dev_warn(card->dev, - "Failed to register DAPM controls, " - "will continue without any.\n"); - return 0; - } - - ret = snd_soc_dapm_add_routes(dapm, ams_delta_audio_map, - ARRAY_SIZE(ams_delta_audio_map)); - if (ret) { - dev_warn(card->dev, - "Failed to set up DAPM routes, " - "will continue with codec default map.\n"); - return 0; - } - - /* Set up initial pin constellation */ - snd_soc_dapm_disable_pin(dapm, "Mouthpiece"); - snd_soc_dapm_enable_pin(dapm, "Earpiece"); - snd_soc_dapm_enable_pin(dapm, "Microphone"); - snd_soc_dapm_disable_pin(dapm, "Speaker"); - snd_soc_dapm_disable_pin(dapm, "AGCIN"); - snd_soc_dapm_disable_pin(dapm, "AGCOUT"); - - /* Add virtual switch */ - ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls, - ARRAY_SIZE(ams_delta_audio_controls)); - if (ret) - dev_warn(card->dev, - "Failed to register audio mode control, " - "will continue without it.\n"); - - return 0; -} - -/* DAI glue - connects codec <--> CPU */ -static struct snd_soc_dai_link ams_delta_dai_link = { - .name = "CX20442", - .stream_name = "CX20442", - .cpu_dai_name = "omap-mcbsp.1", - .codec_dai_name = "cx20442-voice", - .init = ams_delta_cx20442_init, - .platform_name = "omap-pcm-audio", - .codec_name = "cx20442-codec", - .ops = &ams_delta_ops, -}; - -/* Audio card driver */ -static struct snd_soc_card ams_delta_audio_card = { - .name = "AMS_DELTA", - .owner = THIS_MODULE, - .dai_link = &ams_delta_dai_link, - .num_links = 1, -}; - -/* Module init/exit */ -static struct platform_device *ams_delta_audio_platform_device; -static struct platform_device *cx20442_platform_device; - -static int __init ams_delta_module_init(void) -{ - int ret; - - if (!(machine_is_ams_delta())) - return -ENODEV; - - ams_delta_audio_platform_device = - platform_device_alloc("soc-audio", -1); - if (!ams_delta_audio_platform_device) - return -ENOMEM; - - platform_set_drvdata(ams_delta_audio_platform_device, - &ams_delta_audio_card); - - ret = platform_device_add(ams_delta_audio_platform_device); - if (ret) - goto err; - - /* - * Codec platform device could be registered from elsewhere (board?), - * but I do it here as it makes sense only if used with the card. - */ - cx20442_platform_device = - platform_device_register_simple("cx20442-codec", -1, NULL, 0); - return 0; -err: - platform_device_put(ams_delta_audio_platform_device); - return ret; -} -late_initcall(ams_delta_module_init); - -static void __exit ams_delta_module_exit(void) -{ - if (tty_unregister_ldisc(N_V253) != 0) - dev_warn(&ams_delta_audio_platform_device->dev, - "failed to unregister V253 line discipline\n"); - - snd_soc_jack_free_gpios(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_gpios), - ams_delta_hook_switch_gpios); - - platform_device_unregister(cx20442_platform_device); - platform_device_unregister(ams_delta_audio_platform_device); -} -module_exit(ams_delta_module_exit); - -MODULE_AUTHOR("Janusz Krzysztofik "); -MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/igep0020.c b/ANDROID_3.4.5/sound/soc/omap/igep0020.c deleted file mode 100644 index e8357819..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/igep0020.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * igep0020.c -- SoC audio for IGEP v2 - * - * Based on sound/soc/omap/overo.c by Steve Sakoman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int igep2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops igep2_ops = { - .hw_params = igep2_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link igep2_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &igep2_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_card_igep2 = { - .name = "igep2", - .owner = THIS_MODULE, - .dai_link = &igep2_dai, - .num_links = 1, -}; - -static struct platform_device *igep2_snd_device; - -static int __init igep2_soc_init(void) -{ - int ret; - - if (!machine_is_igep0020()) - return -ENODEV; - printk(KERN_INFO "IGEP v2 SoC init\n"); - - igep2_snd_device = platform_device_alloc("soc-audio", -1); - if (!igep2_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2); - - ret = platform_device_add(igep2_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(igep2_snd_device); - - return ret; -} -module_init(igep2_soc_init); - -static void __exit igep2_soc_exit(void) -{ - platform_device_unregister(igep2_snd_device); -} -module_exit(igep2_soc_exit); - -MODULE_AUTHOR("Enric Balletbo i Serra "); -MODULE_DESCRIPTION("ALSA SoC IGEP v2"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/mcbsp.c b/ANDROID_3.4.5/sound/soc/omap/mcbsp.c deleted file mode 100644 index e5f44440..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/mcbsp.c +++ /dev/null @@ -1,1040 +0,0 @@ -/* - * sound/soc/omap/mcbsp.c - * - * Copyright (C) 2004 Nokia Corporation - * Author: Samuel Ortiz - * - * Contact: Jarkko Nikula - * Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Multichannel mode not supported. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "mcbsp.h" - -static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) -{ - void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step; - - if (mcbsp->pdata->reg_size == 2) { - ((u16 *)mcbsp->reg_cache)[reg] = (u16)val; - __raw_writew((u16)val, addr); - } else { - ((u32 *)mcbsp->reg_cache)[reg] = val; - __raw_writel(val, addr); - } -} - -static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) -{ - void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step; - - if (mcbsp->pdata->reg_size == 2) { - return !from_cache ? __raw_readw(addr) : - ((u16 *)mcbsp->reg_cache)[reg]; - } else { - return !from_cache ? __raw_readl(addr) : - ((u32 *)mcbsp->reg_cache)[reg]; - } -} - -static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) -{ - __raw_writel(val, mcbsp->st_data->io_base_st + reg); -} - -static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) -{ - return __raw_readl(mcbsp->st_data->io_base_st + reg); -} - -#define MCBSP_READ(mcbsp, reg) \ - omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0) -#define MCBSP_WRITE(mcbsp, reg, val) \ - omap_mcbsp_write(mcbsp, OMAP_MCBSP_REG_##reg, val) -#define MCBSP_READ_CACHE(mcbsp, reg) \ - omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1) - -#define MCBSP_ST_READ(mcbsp, reg) \ - omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg) -#define MCBSP_ST_WRITE(mcbsp, reg, val) \ - omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val) - -static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp) -{ - dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id); - dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n", - MCBSP_READ(mcbsp, DRR2)); - dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n", - MCBSP_READ(mcbsp, DRR1)); - dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n", - MCBSP_READ(mcbsp, DXR2)); - dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n", - MCBSP_READ(mcbsp, DXR1)); - dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n", - MCBSP_READ(mcbsp, SPCR2)); - dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n", - MCBSP_READ(mcbsp, SPCR1)); - dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n", - MCBSP_READ(mcbsp, RCR2)); - dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n", - MCBSP_READ(mcbsp, RCR1)); - dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n", - MCBSP_READ(mcbsp, XCR2)); - dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n", - MCBSP_READ(mcbsp, XCR1)); - dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n", - MCBSP_READ(mcbsp, SRGR2)); - dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n", - MCBSP_READ(mcbsp, SRGR1)); - dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n", - MCBSP_READ(mcbsp, PCR0)); - dev_dbg(mcbsp->dev, "***********************\n"); -} - -static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) -{ - struct omap_mcbsp *mcbsp_tx = dev_id; - u16 irqst_spcr2; - - irqst_spcr2 = MCBSP_READ(mcbsp_tx, SPCR2); - dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2); - - if (irqst_spcr2 & XSYNC_ERR) { - dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n", - irqst_spcr2); - /* Writing zero to XSYNC_ERR clears the IRQ */ - MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2)); - } - - return IRQ_HANDLED; -} - -static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) -{ - struct omap_mcbsp *mcbsp_rx = dev_id; - u16 irqst_spcr1; - - irqst_spcr1 = MCBSP_READ(mcbsp_rx, SPCR1); - dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1); - - if (irqst_spcr1 & RSYNC_ERR) { - dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n", - irqst_spcr1); - /* Writing zero to RSYNC_ERR clears the IRQ */ - MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1)); - } - - return IRQ_HANDLED; -} - -/* - * omap_mcbsp_config simply write a config to the - * appropriate McBSP. - * You either call this function or set the McBSP registers - * by yourself before calling omap_mcbsp_start(). - */ -void omap_mcbsp_config(struct omap_mcbsp *mcbsp, - const struct omap_mcbsp_reg_cfg *config) -{ - dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n", - mcbsp->id, mcbsp->phys_base); - - /* We write the given config */ - MCBSP_WRITE(mcbsp, SPCR2, config->spcr2); - MCBSP_WRITE(mcbsp, SPCR1, config->spcr1); - MCBSP_WRITE(mcbsp, RCR2, config->rcr2); - MCBSP_WRITE(mcbsp, RCR1, config->rcr1); - MCBSP_WRITE(mcbsp, XCR2, config->xcr2); - MCBSP_WRITE(mcbsp, XCR1, config->xcr1); - MCBSP_WRITE(mcbsp, SRGR2, config->srgr2); - MCBSP_WRITE(mcbsp, SRGR1, config->srgr1); - MCBSP_WRITE(mcbsp, MCR2, config->mcr2); - MCBSP_WRITE(mcbsp, MCR1, config->mcr1); - MCBSP_WRITE(mcbsp, PCR0, config->pcr0); - if (mcbsp->pdata->has_ccr) { - MCBSP_WRITE(mcbsp, XCCR, config->xccr); - MCBSP_WRITE(mcbsp, RCCR, config->rccr); - } - /* Enable wakeup behavior */ - if (mcbsp->pdata->has_wakeup) - MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN); -} - -/** - * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register - * @id - mcbsp id - * @stream - indicates the direction of data flow (rx or tx) - * - * Returns the address of mcbsp data transmit register or data receive register - * to be used by DMA for transferring/receiving data based on the value of - * @stream for the requested mcbsp given by @id - */ -static int omap_mcbsp_dma_reg_params(struct omap_mcbsp *mcbsp, - unsigned int stream) -{ - int data_reg; - - if (mcbsp->pdata->reg_size == 2) { - if (stream) - data_reg = OMAP_MCBSP_REG_DRR1; - else - data_reg = OMAP_MCBSP_REG_DXR1; - } else { - if (stream) - data_reg = OMAP_MCBSP_REG_DRR; - else - data_reg = OMAP_MCBSP_REG_DXR; - } - - return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step; -} - -static void omap_st_on(struct omap_mcbsp *mcbsp) -{ - unsigned int w; - - if (mcbsp->pdata->enable_st_clock) - mcbsp->pdata->enable_st_clock(mcbsp->id, 1); - - /* Enable McBSP Sidetone */ - w = MCBSP_READ(mcbsp, SSELCR); - MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN); - - /* Enable Sidetone from Sidetone Core */ - w = MCBSP_ST_READ(mcbsp, SSELCR); - MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN); -} - -static void omap_st_off(struct omap_mcbsp *mcbsp) -{ - unsigned int w; - - w = MCBSP_ST_READ(mcbsp, SSELCR); - MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN)); - - w = MCBSP_READ(mcbsp, SSELCR); - MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); - - if (mcbsp->pdata->enable_st_clock) - mcbsp->pdata->enable_st_clock(mcbsp->id, 0); -} - -static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) -{ - u16 val, i; - - val = MCBSP_ST_READ(mcbsp, SSELCR); - - if (val & ST_COEFFWREN) - MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN)); - - MCBSP_ST_WRITE(mcbsp, SSELCR, val | ST_COEFFWREN); - - for (i = 0; i < 128; i++) - MCBSP_ST_WRITE(mcbsp, SFIRCR, fir[i]); - - i = 0; - - val = MCBSP_ST_READ(mcbsp, SSELCR); - while (!(val & ST_COEFFWRDONE) && (++i < 1000)) - val = MCBSP_ST_READ(mcbsp, SSELCR); - - MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN)); - - if (i == 1000) - dev_err(mcbsp->dev, "McBSP FIR load error!\n"); -} - -static void omap_st_chgain(struct omap_mcbsp *mcbsp) -{ - u16 w; - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - - w = MCBSP_ST_READ(mcbsp, SSELCR); - - MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | \ - ST_CH1GAIN(st_data->ch1gain)); -} - -int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain) -{ - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - int ret = 0; - - if (!st_data) - return -ENOENT; - - spin_lock_irq(&mcbsp->lock); - if (channel == 0) - st_data->ch0gain = chgain; - else if (channel == 1) - st_data->ch1gain = chgain; - else - ret = -EINVAL; - - if (st_data->enabled) - omap_st_chgain(mcbsp); - spin_unlock_irq(&mcbsp->lock); - - return ret; -} - -int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain) -{ - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - int ret = 0; - - if (!st_data) - return -ENOENT; - - spin_lock_irq(&mcbsp->lock); - if (channel == 0) - *chgain = st_data->ch0gain; - else if (channel == 1) - *chgain = st_data->ch1gain; - else - ret = -EINVAL; - spin_unlock_irq(&mcbsp->lock); - - return ret; -} - -static int omap_st_start(struct omap_mcbsp *mcbsp) -{ - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - - if (st_data->enabled && !st_data->running) { - omap_st_fir_write(mcbsp, st_data->taps); - omap_st_chgain(mcbsp); - - if (!mcbsp->free) { - omap_st_on(mcbsp); - st_data->running = 1; - } - } - - return 0; -} - -int omap_st_enable(struct omap_mcbsp *mcbsp) -{ - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - - if (!st_data) - return -ENODEV; - - spin_lock_irq(&mcbsp->lock); - st_data->enabled = 1; - omap_st_start(mcbsp); - spin_unlock_irq(&mcbsp->lock); - - return 0; -} - -static int omap_st_stop(struct omap_mcbsp *mcbsp) -{ - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - - if (st_data->running) { - if (!mcbsp->free) { - omap_st_off(mcbsp); - st_data->running = 0; - } - } - - return 0; -} - -int omap_st_disable(struct omap_mcbsp *mcbsp) -{ - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - int ret = 0; - - if (!st_data) - return -ENODEV; - - spin_lock_irq(&mcbsp->lock); - omap_st_stop(mcbsp); - st_data->enabled = 0; - spin_unlock_irq(&mcbsp->lock); - - return ret; -} - -int omap_st_is_enabled(struct omap_mcbsp *mcbsp) -{ - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - - if (!st_data) - return -ENODEV; - - return st_data->enabled; -} - -/* - * omap_mcbsp_set_rx_threshold configures the transmit threshold in words. - * The threshold parameter is 1 based, and it is converted (threshold - 1) - * for the THRSH2 register. - */ -void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold) -{ - if (mcbsp->pdata->buffer_size == 0) - return; - - if (threshold && threshold <= mcbsp->max_tx_thres) - MCBSP_WRITE(mcbsp, THRSH2, threshold - 1); -} - -/* - * omap_mcbsp_set_rx_threshold configures the receive threshold in words. - * The threshold parameter is 1 based, and it is converted (threshold - 1) - * for the THRSH1 register. - */ -void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold) -{ - if (mcbsp->pdata->buffer_size == 0) - return; - - if (threshold && threshold <= mcbsp->max_rx_thres) - MCBSP_WRITE(mcbsp, THRSH1, threshold - 1); -} - -/* - * omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO - */ -u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp) -{ - u16 buffstat; - - if (mcbsp->pdata->buffer_size == 0) - return 0; - - /* Returns the number of free locations in the buffer */ - buffstat = MCBSP_READ(mcbsp, XBUFFSTAT); - - /* Number of slots are different in McBSP ports */ - return mcbsp->pdata->buffer_size - buffstat; -} - -/* - * omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO - * to reach the threshold value (when the DMA will be triggered to read it) - */ -u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp) -{ - u16 buffstat, threshold; - - if (mcbsp->pdata->buffer_size == 0) - return 0; - - /* Returns the number of used locations in the buffer */ - buffstat = MCBSP_READ(mcbsp, RBUFFSTAT); - /* RX threshold */ - threshold = MCBSP_READ(mcbsp, THRSH1); - - /* Return the number of location till we reach the threshold limit */ - if (threshold <= buffstat) - return 0; - else - return threshold - buffstat; -} - -int omap_mcbsp_request(struct omap_mcbsp *mcbsp) -{ - void *reg_cache; - int err; - - reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL); - if (!reg_cache) { - return -ENOMEM; - } - - spin_lock(&mcbsp->lock); - if (!mcbsp->free) { - dev_err(mcbsp->dev, "McBSP%d is currently in use\n", - mcbsp->id); - err = -EBUSY; - goto err_kfree; - } - - mcbsp->free = false; - mcbsp->reg_cache = reg_cache; - spin_unlock(&mcbsp->lock); - - if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) - mcbsp->pdata->ops->request(mcbsp->id - 1); - - /* - * Make sure that transmitter, receiver and sample-rate generator are - * not running before activating IRQs. - */ - MCBSP_WRITE(mcbsp, SPCR1, 0); - MCBSP_WRITE(mcbsp, SPCR2, 0); - - err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, - 0, "McBSP", (void *)mcbsp); - if (err != 0) { - dev_err(mcbsp->dev, "Unable to request TX IRQ %d " - "for McBSP%d\n", mcbsp->tx_irq, - mcbsp->id); - goto err_clk_disable; - } - - if (mcbsp->rx_irq) { - err = request_irq(mcbsp->rx_irq, - omap_mcbsp_rx_irq_handler, - 0, "McBSP", (void *)mcbsp); - if (err != 0) { - dev_err(mcbsp->dev, "Unable to request RX IRQ %d " - "for McBSP%d\n", mcbsp->rx_irq, - mcbsp->id); - goto err_free_irq; - } - } - - return 0; -err_free_irq: - free_irq(mcbsp->tx_irq, (void *)mcbsp); -err_clk_disable: - if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) - mcbsp->pdata->ops->free(mcbsp->id - 1); - - /* Disable wakeup behavior */ - if (mcbsp->pdata->has_wakeup) - MCBSP_WRITE(mcbsp, WAKEUPEN, 0); - - spin_lock(&mcbsp->lock); - mcbsp->free = true; - mcbsp->reg_cache = NULL; -err_kfree: - spin_unlock(&mcbsp->lock); - kfree(reg_cache); - - return err; -} - -void omap_mcbsp_free(struct omap_mcbsp *mcbsp) -{ - void *reg_cache; - - if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) - mcbsp->pdata->ops->free(mcbsp->id - 1); - - /* Disable wakeup behavior */ - if (mcbsp->pdata->has_wakeup) - MCBSP_WRITE(mcbsp, WAKEUPEN, 0); - - if (mcbsp->rx_irq) - free_irq(mcbsp->rx_irq, (void *)mcbsp); - free_irq(mcbsp->tx_irq, (void *)mcbsp); - - reg_cache = mcbsp->reg_cache; - - /* - * Select CLKS source from internal source unconditionally before - * marking the McBSP port as free. - * If the external clock source via MCBSP_CLKS pin has been selected the - * system will refuse to enter idle if the CLKS pin source is not reset - * back to internal source. - */ - if (!cpu_class_is_omap1()) - omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC); - - spin_lock(&mcbsp->lock); - if (mcbsp->free) - dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id); - else - mcbsp->free = true; - mcbsp->reg_cache = NULL; - spin_unlock(&mcbsp->lock); - - if (reg_cache) - kfree(reg_cache); -} - -/* - * Here we start the McBSP, by enabling transmitter, receiver or both. - * If no transmitter or receiver is active prior calling, then sample-rate - * generator and frame sync are started. - */ -void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx) -{ - int enable_srg = 0; - u16 w; - - if (mcbsp->st_data) - omap_st_start(mcbsp); - - /* Only enable SRG, if McBSP is master */ - w = MCBSP_READ_CACHE(mcbsp, PCR0); - if (w & (FSXM | FSRM | CLKXM | CLKRM)) - enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) | - MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1); - - if (enable_srg) { - /* Start the sample generator */ - w = MCBSP_READ_CACHE(mcbsp, SPCR2); - MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6)); - } - - /* Enable transmitter and receiver */ - tx &= 1; - w = MCBSP_READ_CACHE(mcbsp, SPCR2); - MCBSP_WRITE(mcbsp, SPCR2, w | tx); - - rx &= 1; - w = MCBSP_READ_CACHE(mcbsp, SPCR1); - MCBSP_WRITE(mcbsp, SPCR1, w | rx); - - /* - * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec - * REVISIT: 100us may give enough time for two CLKSRG, however - * due to some unknown PM related, clock gating etc. reason it - * is now at 500us. - */ - udelay(500); - - if (enable_srg) { - /* Start frame sync */ - w = MCBSP_READ_CACHE(mcbsp, SPCR2); - MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7)); - } - - if (mcbsp->pdata->has_ccr) { - /* Release the transmitter and receiver */ - w = MCBSP_READ_CACHE(mcbsp, XCCR); - w &= ~(tx ? XDISABLE : 0); - MCBSP_WRITE(mcbsp, XCCR, w); - w = MCBSP_READ_CACHE(mcbsp, RCCR); - w &= ~(rx ? RDISABLE : 0); - MCBSP_WRITE(mcbsp, RCCR, w); - } - - /* Dump McBSP Regs */ - omap_mcbsp_dump_reg(mcbsp); -} - -void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx) -{ - int idle; - u16 w; - - /* Reset transmitter */ - tx &= 1; - if (mcbsp->pdata->has_ccr) { - w = MCBSP_READ_CACHE(mcbsp, XCCR); - w |= (tx ? XDISABLE : 0); - MCBSP_WRITE(mcbsp, XCCR, w); - } - w = MCBSP_READ_CACHE(mcbsp, SPCR2); - MCBSP_WRITE(mcbsp, SPCR2, w & ~tx); - - /* Reset receiver */ - rx &= 1; - if (mcbsp->pdata->has_ccr) { - w = MCBSP_READ_CACHE(mcbsp, RCCR); - w |= (rx ? RDISABLE : 0); - MCBSP_WRITE(mcbsp, RCCR, w); - } - w = MCBSP_READ_CACHE(mcbsp, SPCR1); - MCBSP_WRITE(mcbsp, SPCR1, w & ~rx); - - idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) | - MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1); - - if (idle) { - /* Reset the sample rate generator */ - w = MCBSP_READ_CACHE(mcbsp, SPCR2); - MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6)); - } - - if (mcbsp->st_data) - omap_st_stop(mcbsp); -} - -int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) -{ - const char *src; - - if (fck_src_id == MCBSP_CLKS_PAD_SRC) - src = "clks_ext"; - else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) - src = "clks_fclk"; - else - return -EINVAL; - - if (mcbsp->pdata->set_clk_src) - return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src); - else - return -EINVAL; -} - -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) -{ - const char *signal, *src; - - if (mcbsp->pdata->mux_signal) - return -EINVAL; - - switch (mux) { - case CLKR_SRC_CLKR: - signal = "clkr"; - src = "clkr"; - break; - case CLKR_SRC_CLKX: - signal = "clkr"; - src = "clkx"; - break; - case FSR_SRC_FSR: - signal = "fsr"; - src = "fsr"; - break; - case FSR_SRC_FSX: - signal = "fsr"; - src = "fsx"; - break; - default: - return -EINVAL; - } - - return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src); -} - -#define max_thres(m) (mcbsp->pdata->buffer_size) -#define valid_threshold(m, val) ((val) <= max_thres(m)) -#define THRESHOLD_PROP_BUILDER(prop) \ -static ssize_t prop##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%u\n", mcbsp->prop); \ -} \ - \ -static ssize_t prop##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t size) \ -{ \ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \ - unsigned long val; \ - int status; \ - \ - status = strict_strtoul(buf, 0, &val); \ - if (status) \ - return status; \ - \ - if (!valid_threshold(mcbsp, val)) \ - return -EDOM; \ - \ - mcbsp->prop = val; \ - return size; \ -} \ - \ -static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store); - -THRESHOLD_PROP_BUILDER(max_tx_thres); -THRESHOLD_PROP_BUILDER(max_rx_thres); - -static const char *dma_op_modes[] = { - "element", "threshold", "frame", -}; - -static ssize_t dma_op_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); - int dma_op_mode, i = 0; - ssize_t len = 0; - const char * const *s; - - dma_op_mode = mcbsp->dma_op_mode; - - for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) { - if (dma_op_mode == i) - len += sprintf(buf + len, "[%s] ", *s); - else - len += sprintf(buf + len, "%s ", *s); - } - len += sprintf(buf + len, "\n"); - - return len; -} - -static ssize_t dma_op_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); - const char * const *s; - int i = 0; - - for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) - if (sysfs_streq(buf, *s)) - break; - - if (i == ARRAY_SIZE(dma_op_modes)) - return -EINVAL; - - spin_lock_irq(&mcbsp->lock); - if (!mcbsp->free) { - size = -EBUSY; - goto unlock; - } - mcbsp->dma_op_mode = i; - -unlock: - spin_unlock_irq(&mcbsp->lock); - - return size; -} - -static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); - -static const struct attribute *additional_attrs[] = { - &dev_attr_max_tx_thres.attr, - &dev_attr_max_rx_thres.attr, - &dev_attr_dma_op_mode.attr, - NULL, -}; - -static const struct attribute_group additional_attr_group = { - .attrs = (struct attribute **)additional_attrs, -}; - -static ssize_t st_taps_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - ssize_t status = 0; - int i; - - spin_lock_irq(&mcbsp->lock); - for (i = 0; i < st_data->nr_taps; i++) - status += sprintf(&buf[status], (i ? ", %d" : "%d"), - st_data->taps[i]); - if (i) - status += sprintf(&buf[status], "\n"); - spin_unlock_irq(&mcbsp->lock); - - return status; -} - -static ssize_t st_taps_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); - struct omap_mcbsp_st_data *st_data = mcbsp->st_data; - int val, tmp, status, i = 0; - - spin_lock_irq(&mcbsp->lock); - memset(st_data->taps, 0, sizeof(st_data->taps)); - st_data->nr_taps = 0; - - do { - status = sscanf(buf, "%d%n", &val, &tmp); - if (status < 0 || status == 0) { - size = -EINVAL; - goto out; - } - if (val < -32768 || val > 32767) { - size = -EINVAL; - goto out; - } - st_data->taps[i++] = val; - buf += tmp; - if (*buf != ',') - break; - buf++; - } while (1); - - st_data->nr_taps = i; - -out: - spin_unlock_irq(&mcbsp->lock); - - return size; -} - -static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store); - -static const struct attribute *sidetone_attrs[] = { - &dev_attr_st_taps.attr, - NULL, -}; - -static const struct attribute_group sidetone_attr_group = { - .attrs = (struct attribute **)sidetone_attrs, -}; - -static int __devinit omap_st_add(struct omap_mcbsp *mcbsp, - struct resource *res) -{ - struct omap_mcbsp_st_data *st_data; - int err; - - st_data = devm_kzalloc(mcbsp->dev, sizeof(*mcbsp->st_data), GFP_KERNEL); - if (!st_data) - return -ENOMEM; - - st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start, - resource_size(res)); - if (!st_data->io_base_st) - return -ENOMEM; - - err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group); - if (err) - return err; - - mcbsp->st_data = st_data; - return 0; -} - -/* - * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. - * 730 has only 2 McBSP, and both of them are MPU peripherals. - */ -int __devinit omap_mcbsp_init(struct platform_device *pdev) -{ - struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); - struct resource *res; - int ret = 0; - - spin_lock_init(&mcbsp->lock); - mcbsp->free = true; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); - if (!res) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(mcbsp->dev, "invalid memory resource\n"); - return -ENOMEM; - } - } - if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), - dev_name(&pdev->dev))) { - dev_err(mcbsp->dev, "memory region already claimed\n"); - return -ENODEV; - } - - mcbsp->phys_base = res->start; - mcbsp->reg_cache_size = resource_size(res); - mcbsp->io_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!mcbsp->io_base) - return -ENOMEM; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); - if (!res) - mcbsp->phys_dma_base = mcbsp->phys_base; - else - mcbsp->phys_dma_base = res->start; - - mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx"); - mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx"); - - /* From OMAP4 there will be a single irq line */ - if (mcbsp->tx_irq == -ENXIO) { - mcbsp->tx_irq = platform_get_irq(pdev, 0); - mcbsp->rx_irq = 0; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); - if (!res) { - dev_err(&pdev->dev, "invalid rx DMA channel\n"); - return -ENODEV; - } - /* RX DMA request number, and port address configuration */ - mcbsp->dma_data[1].name = "Audio Capture"; - mcbsp->dma_data[1].dma_req = res->start; - mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1); - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); - if (!res) { - dev_err(&pdev->dev, "invalid tx DMA channel\n"); - return -ENODEV; - } - /* TX DMA request number, and port address configuration */ - mcbsp->dma_data[0].name = "Audio Playback"; - mcbsp->dma_data[0].dma_req = res->start; - mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0); - - mcbsp->fclk = clk_get(&pdev->dev, "fck"); - if (IS_ERR(mcbsp->fclk)) { - ret = PTR_ERR(mcbsp->fclk); - dev_err(mcbsp->dev, "unable to get fck: %d\n", ret); - return ret; - } - - mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; - if (mcbsp->pdata->buffer_size) { - /* - * Initially configure the maximum thresholds to a safe value. - * The McBSP FIFO usage with these values should not go under - * 16 locations. - * If the whole FIFO without safety buffer is used, than there - * is a possibility that the DMA will be not able to push the - * new data on time, causing channel shifts in runtime. - */ - mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10; - mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10; - - ret = sysfs_create_group(&mcbsp->dev->kobj, - &additional_attr_group); - if (ret) { - dev_err(mcbsp->dev, - "Unable to create additional controls\n"); - goto err_thres; - } - } else { - mcbsp->max_tx_thres = -EINVAL; - mcbsp->max_rx_thres = -EINVAL; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone"); - if (res) { - ret = omap_st_add(mcbsp, res); - if (ret) { - dev_err(mcbsp->dev, - "Unable to create sidetone controls\n"); - goto err_st; - } - } - - return 0; - -err_st: - if (mcbsp->pdata->buffer_size) - sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group); -err_thres: - clk_put(mcbsp->fclk); - return ret; -} - -void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp) -{ - if (mcbsp->pdata->buffer_size) - sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group); - - if (mcbsp->st_data) - sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group); -} diff --git a/ANDROID_3.4.5/sound/soc/omap/mcbsp.h b/ANDROID_3.4.5/sound/soc/omap/mcbsp.h deleted file mode 100644 index a944fcc9..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/mcbsp.h +++ /dev/null @@ -1,346 +0,0 @@ -/* - * sound/soc/omap/mcbsp.h - * - * OMAP Multi-Channel Buffered Serial Port - * - * Contact: Jarkko Nikula - * Peter Ujfalusi - * - * 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 - * - */ -#ifndef __ASOC_MCBSP_H -#define __ASOC_MCBSP_H - -#include "omap-pcm.h" - -/* McBSP register numbers. Register address offset = num * reg_step */ -enum { - /* Common registers */ - OMAP_MCBSP_REG_SPCR2 = 4, - OMAP_MCBSP_REG_SPCR1, - OMAP_MCBSP_REG_RCR2, - OMAP_MCBSP_REG_RCR1, - OMAP_MCBSP_REG_XCR2, - OMAP_MCBSP_REG_XCR1, - OMAP_MCBSP_REG_SRGR2, - OMAP_MCBSP_REG_SRGR1, - OMAP_MCBSP_REG_MCR2, - OMAP_MCBSP_REG_MCR1, - OMAP_MCBSP_REG_RCERA, - OMAP_MCBSP_REG_RCERB, - OMAP_MCBSP_REG_XCERA, - OMAP_MCBSP_REG_XCERB, - OMAP_MCBSP_REG_PCR0, - OMAP_MCBSP_REG_RCERC, - OMAP_MCBSP_REG_RCERD, - OMAP_MCBSP_REG_XCERC, - OMAP_MCBSP_REG_XCERD, - OMAP_MCBSP_REG_RCERE, - OMAP_MCBSP_REG_RCERF, - OMAP_MCBSP_REG_XCERE, - OMAP_MCBSP_REG_XCERF, - OMAP_MCBSP_REG_RCERG, - OMAP_MCBSP_REG_RCERH, - OMAP_MCBSP_REG_XCERG, - OMAP_MCBSP_REG_XCERH, - - /* OMAP1-OMAP2420 registers */ - OMAP_MCBSP_REG_DRR2 = 0, - OMAP_MCBSP_REG_DRR1, - OMAP_MCBSP_REG_DXR2, - OMAP_MCBSP_REG_DXR1, - - /* OMAP2430 and onwards */ - OMAP_MCBSP_REG_DRR = 0, - OMAP_MCBSP_REG_DXR = 2, - OMAP_MCBSP_REG_SYSCON = 35, - OMAP_MCBSP_REG_THRSH2, - OMAP_MCBSP_REG_THRSH1, - OMAP_MCBSP_REG_IRQST = 40, - OMAP_MCBSP_REG_IRQEN, - OMAP_MCBSP_REG_WAKEUPEN, - OMAP_MCBSP_REG_XCCR, - OMAP_MCBSP_REG_RCCR, - OMAP_MCBSP_REG_XBUFFSTAT, - OMAP_MCBSP_REG_RBUFFSTAT, - OMAP_MCBSP_REG_SSELCR, -}; - -/* OMAP3 sidetone control registers */ -#define OMAP_ST_REG_REV 0x00 -#define OMAP_ST_REG_SYSCONFIG 0x10 -#define OMAP_ST_REG_IRQSTATUS 0x18 -#define OMAP_ST_REG_IRQENABLE 0x1C -#define OMAP_ST_REG_SGAINCR 0x24 -#define OMAP_ST_REG_SFIRCR 0x28 -#define OMAP_ST_REG_SSELCR 0x2C - -/************************** McBSP SPCR1 bit definitions ***********************/ -#define RRST BIT(0) -#define RRDY BIT(1) -#define RFULL BIT(2) -#define RSYNC_ERR BIT(3) -#define RINTM(value) (((value) & 0x3) << 4) /* bits 4:5 */ -#define ABIS BIT(6) -#define DXENA BIT(7) -#define CLKSTP(value) (((value) & 0x3) << 11) /* bits 11:12 */ -#define RJUST(value) (((value) & 0x3) << 13) /* bits 13:14 */ -#define ALB BIT(15) -#define DLB BIT(15) - -/************************** McBSP SPCR2 bit definitions ***********************/ -#define XRST BIT(0) -#define XRDY BIT(1) -#define XEMPTY BIT(2) -#define XSYNC_ERR BIT(3) -#define XINTM(value) (((value) & 0x3) << 4) /* bits 4:5 */ -#define GRST BIT(6) -#define FRST BIT(7) -#define SOFT BIT(8) -#define FREE BIT(9) - -/************************** McBSP PCR bit definitions *************************/ -#define CLKRP BIT(0) -#define CLKXP BIT(1) -#define FSRP BIT(2) -#define FSXP BIT(3) -#define DR_STAT BIT(4) -#define DX_STAT BIT(5) -#define CLKS_STAT BIT(6) -#define SCLKME BIT(7) -#define CLKRM BIT(8) -#define CLKXM BIT(9) -#define FSRM BIT(10) -#define FSXM BIT(11) -#define RIOEN BIT(12) -#define XIOEN BIT(13) -#define IDLE_EN BIT(14) - -/************************** McBSP RCR1 bit definitions ************************/ -#define RWDLEN1(value) (((value) & 0x7) << 5) /* Bits 5:7 */ -#define RFRLEN1(value) (((value) & 0x7f) << 8) /* Bits 8:14 */ - -/************************** McBSP XCR1 bit definitions ************************/ -#define XWDLEN1(value) (((value) & 0x7) << 5) /* Bits 5:7 */ -#define XFRLEN1(value) (((value) & 0x7f) << 8) /* Bits 8:14 */ - -/*************************** McBSP RCR2 bit definitions ***********************/ -#define RDATDLY(value) ((value) & 0x3) /* Bits 0:1 */ -#define RFIG BIT(2) -#define RCOMPAND(value) (((value) & 0x3) << 3) /* Bits 3:4 */ -#define RWDLEN2(value) (((value) & 0x7) << 5) /* Bits 5:7 */ -#define RFRLEN2(value) (((value) & 0x7f) << 8) /* Bits 8:14 */ -#define RPHASE BIT(15) - -/*************************** McBSP XCR2 bit definitions ***********************/ -#define XDATDLY(value) ((value) & 0x3) /* Bits 0:1 */ -#define XFIG BIT(2) -#define XCOMPAND(value) (((value) & 0x3) << 3) /* Bits 3:4 */ -#define XWDLEN2(value) (((value) & 0x7) << 5) /* Bits 5:7 */ -#define XFRLEN2(value) (((value) & 0x7f) << 8) /* Bits 8:14 */ -#define XPHASE BIT(15) - -/************************* McBSP SRGR1 bit definitions ************************/ -#define CLKGDV(value) ((value) & 0x7f) /* Bits 0:7 */ -#define FWID(value) (((value) & 0xff) << 8) /* Bits 8:15 */ - -/************************* McBSP SRGR2 bit definitions ************************/ -#define FPER(value) ((value) & 0x0fff) /* Bits 0:11 */ -#define FSGM BIT(12) -#define CLKSM BIT(13) -#define CLKSP BIT(14) -#define GSYNC BIT(15) - -/************************* McBSP MCR1 bit definitions *************************/ -#define RMCM BIT(0) -#define RCBLK(value) (((value) & 0x7) << 2) /* Bits 2:4 */ -#define RPABLK(value) (((value) & 0x3) << 5) /* Bits 5:6 */ -#define RPBBLK(value) (((value) & 0x3) << 7) /* Bits 7:8 */ - -/************************* McBSP MCR2 bit definitions *************************/ -#define XMCM(value) ((value) & 0x3) /* Bits 0:1 */ -#define XCBLK(value) (((value) & 0x7) << 2) /* Bits 2:4 */ -#define XPABLK(value) (((value) & 0x3) << 5) /* Bits 5:6 */ -#define XPBBLK(value) (((value) & 0x3) << 7) /* Bits 7:8 */ - -/*********************** McBSP XCCR bit definitions *************************/ -#define XDISABLE BIT(0) -#define XDMAEN BIT(3) -#define DILB BIT(5) -#define XFULL_CYCLE BIT(11) -#define DXENDLY(value) (((value) & 0x3) << 12) /* Bits 12:13 */ -#define PPCONNECT BIT(14) -#define EXTCLKGATE BIT(15) - -/********************** McBSP RCCR bit definitions *************************/ -#define RDISABLE BIT(0) -#define RDMAEN BIT(3) -#define RFULL_CYCLE BIT(11) - -/********************** McBSP SYSCONFIG bit definitions ********************/ -#define SOFTRST BIT(1) -#define ENAWAKEUP BIT(2) -#define SIDLEMODE(value) (((value) & 0x3) << 3) -#define CLOCKACTIVITY(value) (((value) & 0x3) << 8) - -/********************** McBSP SSELCR bit definitions ***********************/ -#define SIDETONEEN BIT(10) - -/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/ -#define ST_AUTOIDLE BIT(0) - -/********************** McBSP Sidetone SGAINCR bit definitions *************/ -#define ST_CH0GAIN(value) ((value) & 0xffff) /* Bits 0:15 */ -#define ST_CH1GAIN(value) (((value) & 0xffff) << 16) /* Bits 16:31 */ - -/********************** McBSP Sidetone SFIRCR bit definitions **************/ -#define ST_FIRCOEFF(value) ((value) & 0xffff) /* Bits 0:15 */ - -/********************** McBSP Sidetone SSELCR bit definitions **************/ -#define ST_SIDETONEEN BIT(0) -#define ST_COEFFWREN BIT(1) -#define ST_COEFFWRDONE BIT(2) - -/********************** McBSP DMA operating modes **************************/ -#define MCBSP_DMA_MODE_ELEMENT 0 -#define MCBSP_DMA_MODE_THRESHOLD 1 -#define MCBSP_DMA_MODE_FRAME 2 - -/********************** McBSP WAKEUPEN bit definitions *********************/ -#define RSYNCERREN BIT(0) -#define RFSREN BIT(1) -#define REOFEN BIT(2) -#define RRDYEN BIT(3) -#define XSYNCERREN BIT(7) -#define XFSXEN BIT(8) -#define XEOFEN BIT(9) -#define XRDYEN BIT(10) -#define XEMPTYEOFEN BIT(14) - -/* Clock signal muxing options */ -#define CLKR_SRC_CLKR 0 /* CLKR signal is from the CLKR pin */ -#define CLKR_SRC_CLKX 1 /* CLKR signal is from the CLKX pin */ -#define FSR_SRC_FSR 2 /* FSR signal is from the FSR pin */ -#define FSR_SRC_FSX 3 /* FSR signal is from the FSX pin */ - -/* McBSP functional clock sources */ -#define MCBSP_CLKS_PRCM_SRC 0 -#define MCBSP_CLKS_PAD_SRC 1 - -/* we don't do multichannel for now */ -struct omap_mcbsp_reg_cfg { - u16 spcr2; - u16 spcr1; - u16 rcr2; - u16 rcr1; - u16 xcr2; - u16 xcr1; - u16 srgr2; - u16 srgr1; - u16 mcr2; - u16 mcr1; - u16 pcr0; - u16 rcerc; - u16 rcerd; - u16 xcerc; - u16 xcerd; - u16 rcere; - u16 rcerf; - u16 xcere; - u16 xcerf; - u16 rcerg; - u16 rcerh; - u16 xcerg; - u16 xcerh; - u16 xccr; - u16 rccr; -}; - -struct omap_mcbsp_st_data { - void __iomem *io_base_st; - bool running; - bool enabled; - s16 taps[128]; /* Sidetone filter coefficients */ - int nr_taps; /* Number of filter coefficients in use */ - s16 ch0gain; - s16 ch1gain; -}; - -struct omap_mcbsp { - struct device *dev; - struct clk *fclk; - spinlock_t lock; - unsigned long phys_base; - unsigned long phys_dma_base; - void __iomem *io_base; - u8 id; - /* - * Flags indicating is the bus already activated and configured by - * another substream - */ - int active; - int configured; - u8 free; - - int rx_irq; - int tx_irq; - - /* Protect the field .free, while checking if the mcbsp is in use */ - struct omap_mcbsp_platform_data *pdata; - struct omap_mcbsp_st_data *st_data; - struct omap_mcbsp_reg_cfg cfg_regs; - struct omap_pcm_dma_data dma_data[2]; - int dma_op_mode; - u16 max_tx_thres; - u16 max_rx_thres; - void *reg_cache; - int reg_cache_size; - - unsigned int fmt; - unsigned int in_freq; - int clk_div; - int wlen; -}; - -void omap_mcbsp_config(struct omap_mcbsp *mcbsp, - const struct omap_mcbsp_reg_cfg *config); -void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold); -void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold); -u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp); -u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp); -int omap_mcbsp_get_dma_op_mode(struct omap_mcbsp *mcbsp); -int omap_mcbsp_request(struct omap_mcbsp *mcbsp); -void omap_mcbsp_free(struct omap_mcbsp *mcbsp); -void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx); -void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx); - -/* McBSP functional clock source changing function */ -int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); - -/* McBSP signal muxing API */ -int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux); - -/* Sidetone specific API */ -int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); -int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); -int omap_st_enable(struct omap_mcbsp *mcbsp); -int omap_st_disable(struct omap_mcbsp *mcbsp); -int omap_st_is_enabled(struct omap_mcbsp *mcbsp); - -int __devinit omap_mcbsp_init(struct platform_device *pdev); -void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp); - -#endif /* __ASOC_MCBSP_H */ diff --git a/ANDROID_3.4.5/sound/soc/omap/n810.c b/ANDROID_3.4.5/sound/soc/omap/n810.c deleted file mode 100644 index abac4b69..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/n810.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * n810.c -- SoC audio for Nokia N810 - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Jarkko Nikula - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -#define N810_HEADSET_AMP_GPIO 10 -#define N810_SPEAKER_AMP_GPIO 101 - -enum { - N810_JACK_DISABLED, - N810_JACK_HP, - N810_JACK_HS, - N810_JACK_MIC, -}; - -static struct clk *sys_clkout2; -static struct clk *sys_clkout2_src; -static struct clk *func96m_clk; - -static int n810_spk_func; -static int n810_jack_func; -static int n810_dmic_func; - -static void n810_ext_control(struct snd_soc_dapm_context *dapm) -{ - int hp = 0, line1l = 0; - - switch (n810_jack_func) { - case N810_JACK_HS: - line1l = 1; - case N810_JACK_HP: - hp = 1; - break; - case N810_JACK_MIC: - line1l = 1; - break; - } - - if (n810_spk_func) - snd_soc_dapm_enable_pin(dapm, "Ext Spk"); - else - snd_soc_dapm_disable_pin(dapm, "Ext Spk"); - - if (hp) - snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); - else - snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); - if (line1l) - snd_soc_dapm_enable_pin(dapm, "LINE1L"); - else - snd_soc_dapm_disable_pin(dapm, "LINE1L"); - - if (n810_dmic_func) - snd_soc_dapm_enable_pin(dapm, "DMic"); - else - snd_soc_dapm_disable_pin(dapm, "DMic"); - - snd_soc_dapm_sync(dapm); -} - -static int n810_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; - - snd_pcm_hw_constraint_minmax(runtime, - SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); - - n810_ext_control(&codec->dapm); - return clk_enable(sys_clkout2); -} - -static void n810_shutdown(struct snd_pcm_substream *substream) -{ - clk_disable(sys_clkout2); -} - -static int n810_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int err; - - /* Set the codec system clock for DAC and ADC */ - err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000, - SND_SOC_CLOCK_IN); - - return err; -} - -static struct snd_soc_ops n810_ops = { - .startup = n810_startup, - .hw_params = n810_hw_params, - .shutdown = n810_shutdown, -}; - -static int n810_get_spk(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = n810_spk_func; - - return 0; -} - -static int n810_set_spk(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); - - if (n810_spk_func == ucontrol->value.integer.value[0]) - return 0; - - n810_spk_func = ucontrol->value.integer.value[0]; - n810_ext_control(&card->dapm); - - return 1; -} - -static int n810_get_jack(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = n810_jack_func; - - return 0; -} - -static int n810_set_jack(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); - - if (n810_jack_func == ucontrol->value.integer.value[0]) - return 0; - - n810_jack_func = ucontrol->value.integer.value[0]; - n810_ext_control(&card->dapm); - - return 1; -} - -static int n810_get_input(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = n810_dmic_func; - - return 0; -} - -static int n810_set_input(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); - - if (n810_dmic_func == ucontrol->value.integer.value[0]) - return 0; - - n810_dmic_func = ucontrol->value.integer.value[0]; - n810_ext_control(&card->dapm); - - return 1; -} - -static int n810_spk_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - if (SND_SOC_DAPM_EVENT_ON(event)) - gpio_set_value(N810_SPEAKER_AMP_GPIO, 1); - else - gpio_set_value(N810_SPEAKER_AMP_GPIO, 0); - - return 0; -} - -static int n810_jack_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - if (SND_SOC_DAPM_EVENT_ON(event)) - gpio_set_value(N810_HEADSET_AMP_GPIO, 1); - else - gpio_set_value(N810_HEADSET_AMP_GPIO, 0); - - return 0; -} - -static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event), - SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event), - SND_SOC_DAPM_MIC("DMic", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - {"Headphone Jack", NULL, "HPLOUT"}, - {"Headphone Jack", NULL, "HPROUT"}, - - {"Ext Spk", NULL, "LLOUT"}, - {"Ext Spk", NULL, "RLOUT"}, - - {"DMic Rate 64", NULL, "Mic Bias 2V"}, - {"Mic Bias 2V", NULL, "DMic"}, -}; - -static const char *spk_function[] = {"Off", "On"}; -static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"}; -static const char *input_function[] = {"ADC", "Digital Mic"}; -static const struct soc_enum n810_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function), - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function), -}; - -static const struct snd_kcontrol_new aic33_n810_controls[] = { - SOC_ENUM_EXT("Speaker Function", n810_enum[0], - n810_get_spk, n810_set_spk), - SOC_ENUM_EXT("Jack Function", n810_enum[1], - n810_get_jack, n810_set_jack), - SOC_ENUM_EXT("Input Select", n810_enum[2], - n810_get_input, n810_set_input), -}; - -static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - /* Not connected */ - snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); - snd_soc_dapm_nc_pin(dapm, "HPLCOM"); - snd_soc_dapm_nc_pin(dapm, "HPRCOM"); - snd_soc_dapm_nc_pin(dapm, "MIC3L"); - snd_soc_dapm_nc_pin(dapm, "MIC3R"); - snd_soc_dapm_nc_pin(dapm, "LINE1R"); - snd_soc_dapm_nc_pin(dapm, "LINE2L"); - snd_soc_dapm_nc_pin(dapm, "LINE2R"); - - return 0; -} - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link n810_dai = { - .name = "TLV320AIC33", - .stream_name = "AIC33", - .cpu_dai_name = "omap-mcbsp.2", - .platform_name = "omap-pcm-audio", - .codec_name = "tlv320aic3x-codec.2-0018", - .codec_dai_name = "tlv320aic3x-hifi", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .init = n810_aic33_init, - .ops = &n810_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_n810 = { - .name = "N810", - .owner = THIS_MODULE, - .dai_link = &n810_dai, - .num_links = 1, - - .controls = aic33_n810_controls, - .num_controls = ARRAY_SIZE(aic33_n810_controls), - .dapm_widgets = aic33_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), -}; - -static struct platform_device *n810_snd_device; - -static int __init n810_soc_init(void) -{ - int err; - struct device *dev; - - if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) - return -ENODEV; - - n810_snd_device = platform_device_alloc("soc-audio", -1); - if (!n810_snd_device) - return -ENOMEM; - - platform_set_drvdata(n810_snd_device, &snd_soc_n810); - err = platform_device_add(n810_snd_device); - if (err) - goto err1; - - dev = &n810_snd_device->dev; - - sys_clkout2_src = clk_get(dev, "sys_clkout2_src"); - if (IS_ERR(sys_clkout2_src)) { - dev_err(dev, "Could not get sys_clkout2_src clock\n"); - err = PTR_ERR(sys_clkout2_src); - goto err2; - } - sys_clkout2 = clk_get(dev, "sys_clkout2"); - if (IS_ERR(sys_clkout2)) { - dev_err(dev, "Could not get sys_clkout2\n"); - err = PTR_ERR(sys_clkout2); - goto err3; - } - /* - * Configure 12 MHz output on SYS_CLKOUT2. Therefore we must use - * 96 MHz as its parent in order to get 12 MHz - */ - func96m_clk = clk_get(dev, "func_96m_ck"); - if (IS_ERR(func96m_clk)) { - dev_err(dev, "Could not get func 96M clock\n"); - err = PTR_ERR(func96m_clk); - goto err4; - } - clk_set_parent(sys_clkout2_src, func96m_clk); - clk_set_rate(sys_clkout2, 12000000); - - BUG_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) || - (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0)); - - gpio_direction_output(N810_HEADSET_AMP_GPIO, 0); - gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0); - - return 0; -err4: - clk_put(sys_clkout2); -err3: - clk_put(sys_clkout2_src); -err2: - platform_device_del(n810_snd_device); -err1: - platform_device_put(n810_snd_device); - - return err; -} - -static void __exit n810_soc_exit(void) -{ - gpio_free(N810_SPEAKER_AMP_GPIO); - gpio_free(N810_HEADSET_AMP_GPIO); - clk_put(sys_clkout2_src); - clk_put(sys_clkout2); - clk_put(func96m_clk); - - platform_device_unregister(n810_snd_device); -} - -module_init(n810_soc_init); -module_exit(n810_soc_exit); - -MODULE_AUTHOR("Jarkko Nikula "); -MODULE_DESCRIPTION("ALSA SoC Nokia N810"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-abe-twl6040.c b/ANDROID_3.4.5/sound/soc/omap/omap-abe-twl6040.c deleted file mode 100644 index 93bb8eee..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-abe-twl6040.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * omap-abe-twl6040.c -- SoC audio for TI OMAP based boards with ABE and - * twl6040 codec - * - * Author: Misael Lopez Cruz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "omap-dmic.h" -#include "omap-mcpdm.h" -#include "omap-pcm.h" -#include "../codecs/twl6040.h" - -static int omap_abe_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_card *card = codec->card; - struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev); - int clk_id, freq; - int ret; - - clk_id = twl6040_get_clk_id(rtd->codec); - if (clk_id == TWL6040_SYSCLK_SEL_HPPLL) - freq = pdata->mclk_freq; - else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL) - freq = 32768; - else - return -EINVAL; - - /* set the codec mclk */ - ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq, - SND_SOC_CLOCK_IN); - if (ret) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - return ret; -} - -static struct snd_soc_ops omap_abe_ops = { - .hw_params = omap_abe_hw_params, -}; - -static int omap_abe_dmic_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret = 0; - - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS, - 19200000, SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set DMIC cpu system clock\n"); - return ret; - } - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_ABE_DMIC_CLK, 2400000, - SND_SOC_CLOCK_OUT); - if (ret < 0) { - printk(KERN_ERR "can't set DMIC output clock\n"); - return ret; - } - return 0; -} - -static struct snd_soc_ops omap_abe_dmic_ops = { - .hw_params = omap_abe_dmic_hw_params, -}; - -/* Headset jack */ -static struct snd_soc_jack hs_jack; - -/*Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin hs_jack_pins[] = { - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Headset Stereophone", - .mask = SND_JACK_HEADPHONE, - }, -}; - -/* SDP4430 machine DAPM */ -static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { - /* Outputs */ - SND_SOC_DAPM_HP("Headset Stereophone", NULL), - SND_SOC_DAPM_SPK("Earphone Spk", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_SPK("Vibrator", NULL), - - /* Inputs */ - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Main Handset Mic", NULL), - SND_SOC_DAPM_MIC("Sub Handset Mic", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Routings for outputs */ - {"Headset Stereophone", NULL, "HSOL"}, - {"Headset Stereophone", NULL, "HSOR"}, - - {"Earphone Spk", NULL, "EP"}, - - {"Ext Spk", NULL, "HFL"}, - {"Ext Spk", NULL, "HFR"}, - - {"Line Out", NULL, "AUXL"}, - {"Line Out", NULL, "AUXR"}, - - {"Vibrator", NULL, "VIBRAL"}, - {"Vibrator", NULL, "VIBRAR"}, - - /* Routings for inputs */ - {"HSMIC", NULL, "Headset Mic"}, - {"Headset Mic", NULL, "Headset Mic Bias"}, - - {"MAINMIC", NULL, "Main Handset Mic"}, - {"Main Handset Mic", NULL, "Main Mic Bias"}, - - {"SUBMIC", NULL, "Sub Handset Mic"}, - {"Sub Handset Mic", NULL, "Main Mic Bias"}, - - {"AFML", NULL, "Line In"}, - {"AFMR", NULL, "Line In"}, -}; - -static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm, - int connected, char *pin) -{ - if (!connected) - snd_soc_dapm_disable_pin(dapm, pin); -} - -static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_card *card = codec->card; - struct snd_soc_dapm_context *dapm = &codec->dapm; - struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev); - int hs_trim; - int ret = 0; - - /* Disable not connected paths if not used */ - twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); - twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); - twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); - twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); - twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); - twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); - twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); - - /* - * Configure McPDM offset cancellation based on the HSOTRIM value from - * twl6040. - */ - hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM); - omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim), - TWL6040_HSF_TRIM_RIGHT(hs_trim)); - - /* Headset jack detection only if it is supported */ - if (pdata->jack_detection) { - ret = snd_soc_jack_new(codec, "Headset Jack", - SND_JACK_HEADSET, &hs_jack); - if (ret) - return ret; - - ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), - hs_jack_pins); - twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); - } - - return ret; -} - -static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Digital Mic", NULL), -}; - -static const struct snd_soc_dapm_route dmic_audio_map[] = { - {"DMic", NULL, "Digital Mic"}, - {"Digital Mic", NULL, "Digital Mic1 Bias"}, -}; - -static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - ret = snd_soc_dapm_new_controls(dapm, dmic_dapm_widgets, - ARRAY_SIZE(dmic_dapm_widgets)); - if (ret) - return ret; - - return snd_soc_dapm_add_routes(dapm, dmic_audio_map, - ARRAY_SIZE(dmic_audio_map)); -} - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link twl6040_dmic_dai[] = { - { - .name = "TWL6040", - .stream_name = "TWL6040", - .cpu_dai_name = "omap-mcpdm", - .codec_dai_name = "twl6040-legacy", - .platform_name = "omap-pcm-audio", - .codec_name = "twl6040-codec", - .init = omap_abe_twl6040_init, - .ops = &omap_abe_ops, - }, - { - .name = "DMIC", - .stream_name = "DMIC Capture", - .cpu_dai_name = "omap-dmic", - .codec_dai_name = "dmic-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "dmic-codec", - .init = omap_abe_dmic_init, - .ops = &omap_abe_dmic_ops, - }, -}; - -static struct snd_soc_dai_link twl6040_only_dai[] = { - { - .name = "TWL6040", - .stream_name = "TWL6040", - .cpu_dai_name = "omap-mcpdm", - .codec_dai_name = "twl6040-legacy", - .platform_name = "omap-pcm-audio", - .codec_name = "twl6040-codec", - .init = omap_abe_twl6040_init, - .ops = &omap_abe_ops, - }, -}; - -/* Audio machine driver */ -static struct snd_soc_card omap_abe_card = { - .owner = THIS_MODULE, - - .dapm_widgets = twl6040_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets), - .dapm_routes = audio_map, - .num_dapm_routes = ARRAY_SIZE(audio_map), -}; - -static __devinit int omap_abe_probe(struct platform_device *pdev) -{ - struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); - struct snd_soc_card *card = &omap_abe_card; - int ret; - - card->dev = &pdev->dev; - - if (!pdata) { - dev_err(&pdev->dev, "Missing pdata\n"); - return -ENODEV; - } - - if (pdata->card_name) { - card->name = pdata->card_name; - } else { - dev_err(&pdev->dev, "Card name is not provided\n"); - return -ENODEV; - } - - if (!pdata->mclk_freq) { - dev_err(&pdev->dev, "MCLK frequency missing\n"); - return -ENODEV; - } - - if (pdata->has_dmic) { - card->dai_link = twl6040_dmic_dai; - card->num_links = ARRAY_SIZE(twl6040_dmic_dai); - } else { - card->dai_link = twl6040_only_dai; - card->num_links = ARRAY_SIZE(twl6040_only_dai); - } - - ret = snd_soc_register_card(card); - if (ret) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - - return ret; -} - -static int __devexit omap_abe_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - snd_soc_unregister_card(card); - - return 0; -} - -static struct platform_driver omap_abe_driver = { - .driver = { - .name = "omap-abe-twl6040", - .owner = THIS_MODULE, - .pm = &snd_soc_pm_ops, - }, - .probe = omap_abe_probe, - .remove = __devexit_p(omap_abe_remove), -}; - -module_platform_driver(omap_abe_driver); - -MODULE_AUTHOR("Misael Lopez Cruz "); -MODULE_DESCRIPTION("ALSA SoC for OMAP boards with ABE and twl6040 codec"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:omap-abe-twl6040"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-dmic.c b/ANDROID_3.4.5/sound/soc/omap/omap-dmic.c deleted file mode 100644 index 4dcb5a7e..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-dmic.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * omap-dmic.c -- OMAP ASoC DMIC DAI driver - * - * Copyright (C) 2010 - 2011 Texas Instruments - * - * Author: David Lambert - * Misael Lopez Cruz - * Liam Girdwood - * Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "omap-pcm.h" -#include "omap-dmic.h" - -struct omap_dmic { - struct device *dev; - void __iomem *io_base; - struct clk *fclk; - int fclk_freq; - int out_freq; - int clk_div; - int sysclk; - int threshold; - u32 ch_enabled; - bool active; - struct mutex mutex; -}; - -/* - * Stream DMA parameters - */ -static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { - .name = "DMIC capture", - .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, -}; - -static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) -{ - __raw_writel(val, dmic->io_base + reg); -} - -static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg) -{ - return __raw_readl(dmic->io_base + reg); -} - -static inline void omap_dmic_start(struct omap_dmic *dmic) -{ - u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG); - - /* Configure DMA controller */ - omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG, - OMAP_DMIC_DMA_ENABLE); - - omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled); -} - -static inline void omap_dmic_stop(struct omap_dmic *dmic) -{ - u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG); - omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, - ctrl & ~OMAP_DMIC_UP_ENABLE_MASK); - - /* Disable DMA request generation */ - omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG, - OMAP_DMIC_DMA_ENABLE); - -} - -static inline int dmic_is_enabled(struct omap_dmic *dmic) -{ - return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) & - OMAP_DMIC_UP_ENABLE_MASK; -} - -static int omap_dmic_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - int ret = 0; - - mutex_lock(&dmic->mutex); - - if (!dai->active) - dmic->active = 1; - else - ret = -EBUSY; - - mutex_unlock(&dmic->mutex); - - return ret; -} - -static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - - mutex_lock(&dmic->mutex); - - if (!dai->active) - dmic->active = 0; - - mutex_unlock(&dmic->mutex); -} - -static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate) -{ - int divider = -EINVAL; - - /* - * 192KHz rate is only supported with 19.2MHz/3.84MHz clock - * configuration. - */ - if (sample_rate == 192000) { - if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000) - divider = 0x6; /* Divider: 5 (192KHz sampling rate) */ - else - dev_err(dmic->dev, - "invalid clock configuration for 192KHz\n"); - - return divider; - } - - switch (dmic->out_freq) { - case 1536000: - if (dmic->fclk_freq != 24576000) - goto div_err; - divider = 0x4; /* Divider: 16 */ - break; - case 2400000: - switch (dmic->fclk_freq) { - case 12000000: - divider = 0x5; /* Divider: 5 */ - break; - case 19200000: - divider = 0x0; /* Divider: 8 */ - break; - case 24000000: - divider = 0x2; /* Divider: 10 */ - break; - default: - goto div_err; - } - break; - case 3072000: - if (dmic->fclk_freq != 24576000) - goto div_err; - divider = 0x3; /* Divider: 8 */ - break; - case 3840000: - if (dmic->fclk_freq != 19200000) - goto div_err; - divider = 0x1; /* Divider: 5 (96KHz sampling rate) */ - break; - default: - dev_err(dmic->dev, "invalid out frequency: %dHz\n", - dmic->out_freq); - break; - } - - return divider; - -div_err: - dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n", - dmic->out_freq, dmic->fclk_freq); - return -EINVAL; -} - -static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - int channels; - - dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); - if (dmic->clk_div < 0) { - dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n", - dmic->out_freq, dmic->fclk_freq); - return -EINVAL; - } - - dmic->ch_enabled = 0; - channels = params_channels(params); - switch (channels) { - case 6: - dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE; - case 4: - dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE; - case 2: - dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE; - break; - default: - dev_err(dmic->dev, "invalid number of legacy channels\n"); - return -EINVAL; - } - - /* packet size is threshold * channels */ - omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels; - snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); - - return 0; -} - -static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - u32 ctrl; - - /* Configure uplink threshold */ - omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold); - - ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG); - - /* Set dmic out format */ - ctrl &= ~(OMAP_DMIC_FORMAT | OMAP_DMIC_POLAR_MASK); - ctrl |= (OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 | - OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3); - - /* Configure dmic clock divider */ - ctrl &= ~OMAP_DMIC_CLK_DIV_MASK; - ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div); - - omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl); - - omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, - ctrl | OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 | - OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3); - - return 0; -} - -static int omap_dmic_dai_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - omap_dmic_start(dmic); - break; - case SNDRV_PCM_TRIGGER_STOP: - omap_dmic_stop(dmic); - break; - default: - break; - } - - return 0; -} - -static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id, - unsigned int freq) -{ - struct clk *parent_clk; - char *parent_clk_name; - int ret = 0; - - switch (freq) { - case 12000000: - case 19200000: - case 24000000: - case 24576000: - break; - default: - dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq); - dmic->fclk_freq = 0; - return -EINVAL; - } - - if (dmic->sysclk == clk_id) { - dmic->fclk_freq = freq; - return 0; - } - - /* re-parent not allowed if a stream is ongoing */ - if (dmic->active && dmic_is_enabled(dmic)) { - dev_err(dmic->dev, "can't re-parent when DMIC active\n"); - return -EBUSY; - } - - switch (clk_id) { - case OMAP_DMIC_SYSCLK_PAD_CLKS: - parent_clk_name = "pad_clks_ck"; - break; - case OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS: - parent_clk_name = "slimbus_clk"; - break; - case OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS: - parent_clk_name = "dmic_sync_mux_ck"; - break; - default: - dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id); - return -EINVAL; - } - - parent_clk = clk_get(dmic->dev, parent_clk_name); - if (IS_ERR(parent_clk)) { - dev_err(dmic->dev, "can't get %s\n", parent_clk_name); - return -ENODEV; - } - - mutex_lock(&dmic->mutex); - if (dmic->active) { - /* disable clock while reparenting */ - pm_runtime_put_sync(dmic->dev); - ret = clk_set_parent(dmic->fclk, parent_clk); - pm_runtime_get_sync(dmic->dev); - } else { - ret = clk_set_parent(dmic->fclk, parent_clk); - } - mutex_unlock(&dmic->mutex); - - if (ret < 0) { - dev_err(dmic->dev, "re-parent failed\n"); - goto err_busy; - } - - dmic->sysclk = clk_id; - dmic->fclk_freq = freq; - -err_busy: - clk_put(parent_clk); - - return ret; -} - -static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id, - unsigned int freq) -{ - int ret = 0; - - if (clk_id != OMAP_DMIC_ABE_DMIC_CLK) { - dev_err(dmic->dev, "output clk_id (%d) not supported\n", - clk_id); - return -EINVAL; - } - - switch (freq) { - case 1536000: - case 2400000: - case 3072000: - case 3840000: - dmic->out_freq = freq; - break; - default: - dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq); - dmic->out_freq = 0; - ret = -EINVAL; - } - - return ret; -} - -static int omap_dmic_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, int dir) -{ - struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - - if (dir == SND_SOC_CLOCK_IN) - return omap_dmic_select_fclk(dmic, clk_id, freq); - else if (dir == SND_SOC_CLOCK_OUT) - return omap_dmic_select_outclk(dmic, clk_id, freq); - - dev_err(dmic->dev, "invalid clock direction (%d)\n", dir); - return -EINVAL; -} - -static const struct snd_soc_dai_ops omap_dmic_dai_ops = { - .startup = omap_dmic_dai_startup, - .shutdown = omap_dmic_dai_shutdown, - .hw_params = omap_dmic_dai_hw_params, - .prepare = omap_dmic_dai_prepare, - .trigger = omap_dmic_dai_trigger, - .set_sysclk = omap_dmic_set_dai_sysclk, -}; - -static int omap_dmic_probe(struct snd_soc_dai *dai) -{ - struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - - pm_runtime_enable(dmic->dev); - - /* Disable lines while request is ongoing */ - pm_runtime_get_sync(dmic->dev); - omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00); - pm_runtime_put_sync(dmic->dev); - - /* Configure DMIC threshold value */ - dmic->threshold = OMAP_DMIC_THRES_MAX - 3; - return 0; -} - -static int omap_dmic_remove(struct snd_soc_dai *dai) -{ - struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - - pm_runtime_disable(dmic->dev); - - return 0; -} - -static struct snd_soc_dai_driver omap_dmic_dai = { - .name = "omap-dmic", - .probe = omap_dmic_probe, - .remove = omap_dmic_remove, - .capture = { - .channels_min = 2, - .channels_max = 6, - .rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .sig_bits = 24, - }, - .ops = &omap_dmic_dai_ops, -}; - -static __devinit int asoc_dmic_probe(struct platform_device *pdev) -{ - struct omap_dmic *dmic; - struct resource *res; - int ret; - - dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL); - if (!dmic) - return -ENOMEM; - - platform_set_drvdata(pdev, dmic); - dmic->dev = &pdev->dev; - dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS; - - mutex_init(&dmic->mutex); - - dmic->fclk = clk_get(dmic->dev, "dmic_fck"); - if (IS_ERR(dmic->fclk)) { - dev_err(dmic->dev, "cant get dmic_fck\n"); - return -ENODEV; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); - if (!res) { - dev_err(dmic->dev, "invalid dma memory resource\n"); - ret = -ENODEV; - goto err_put_clk; - } - omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(dmic->dev, "invalid dma resource\n"); - ret = -ENODEV; - goto err_put_clk; - } - omap_dmic_dai_dma_params.dma_req = res->start; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); - if (!res) { - dev_err(dmic->dev, "invalid memory resource\n"); - ret = -ENODEV; - goto err_put_clk; - } - - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), pdev->name)) { - dev_err(dmic->dev, "memory region already claimed\n"); - ret = -ENODEV; - goto err_put_clk; - } - - dmic->io_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!dmic->io_base) { - ret = -ENOMEM; - goto err_put_clk; - } - - ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai); - if (ret) - goto err_put_clk; - - return 0; - -err_put_clk: - clk_put(dmic->fclk); - return ret; -} - -static int __devexit asoc_dmic_remove(struct platform_device *pdev) -{ - struct omap_dmic *dmic = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - clk_put(dmic->fclk); - - return 0; -} - -static struct platform_driver asoc_dmic_driver = { - .driver = { - .name = "omap-dmic", - .owner = THIS_MODULE, - }, - .probe = asoc_dmic_probe, - .remove = __devexit_p(asoc_dmic_remove), -}; - -module_platform_driver(asoc_dmic_driver); - -MODULE_ALIAS("platform:omap-dmic"); -MODULE_AUTHOR("Peter Ujfalusi "); -MODULE_DESCRIPTION("OMAP DMIC ASoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-dmic.h b/ANDROID_3.4.5/sound/soc/omap/omap-dmic.h deleted file mode 100644 index 231e728b..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-dmic.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * omap-dmic.h -- OMAP Digital Microphone Controller - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _OMAP_DMIC_H -#define _OMAP_DMIC_H - -#define OMAP_DMIC_REVISION_REG 0x00 -#define OMAP_DMIC_SYSCONFIG_REG 0x10 -#define OMAP_DMIC_IRQSTATUS_RAW_REG 0x24 -#define OMAP_DMIC_IRQSTATUS_REG 0x28 -#define OMAP_DMIC_IRQENABLE_SET_REG 0x2C -#define OMAP_DMIC_IRQENABLE_CLR_REG 0x30 -#define OMAP_DMIC_IRQWAKE_EN_REG 0x34 -#define OMAP_DMIC_DMAENABLE_SET_REG 0x38 -#define OMAP_DMIC_DMAENABLE_CLR_REG 0x3C -#define OMAP_DMIC_DMAWAKEEN_REG 0x40 -#define OMAP_DMIC_CTRL_REG 0x44 -#define OMAP_DMIC_DATA_REG 0x48 -#define OMAP_DMIC_FIFO_CTRL_REG 0x4C -#define OMAP_DMIC_FIFO_DMIC1R_DATA_REG 0x50 -#define OMAP_DMIC_FIFO_DMIC1L_DATA_REG 0x54 -#define OMAP_DMIC_FIFO_DMIC2R_DATA_REG 0x58 -#define OMAP_DMIC_FIFO_DMIC2L_DATA_REG 0x5C -#define OMAP_DMIC_FIFO_DMIC3R_DATA_REG 0x60 -#define OMAP_DMIC_FIFO_DMIC3L_DATA_REG 0x64 - -/* IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR bit fields */ -#define OMAP_DMIC_IRQ (1 << 0) -#define OMAP_DMIC_IRQ_FULL (1 << 1) -#define OMAP_DMIC_IRQ_ALMST_EMPTY (1 << 2) -#define OMAP_DMIC_IRQ_EMPTY (1 << 3) -#define OMAP_DMIC_IRQ_MASK 0x07 - -/* DMIC_DMAENABLE bit fields */ -#define OMAP_DMIC_DMA_ENABLE 0x1 - -/* DMIC_CTRL bit fields */ -#define OMAP_DMIC_UP1_ENABLE (1 << 0) -#define OMAP_DMIC_UP2_ENABLE (1 << 1) -#define OMAP_DMIC_UP3_ENABLE (1 << 2) -#define OMAP_DMIC_UP_ENABLE_MASK 0x7 -#define OMAP_DMIC_FORMAT (1 << 3) -#define OMAP_DMIC_POLAR1 (1 << 4) -#define OMAP_DMIC_POLAR2 (1 << 5) -#define OMAP_DMIC_POLAR3 (1 << 6) -#define OMAP_DMIC_POLAR_MASK (0x7 << 4) -#define OMAP_DMIC_CLK_DIV(x) (((x) & 0x7) << 7) -#define OMAP_DMIC_CLK_DIV_MASK (0x7 << 7) -#define OMAP_DMIC_RESET (1 << 10) - -#define OMAP_DMICOUTFORMAT_LJUST (0 << 3) -#define OMAP_DMICOUTFORMAT_RJUST (1 << 3) - -/* DMIC_FIFO_CTRL bit fields */ -#define OMAP_DMIC_THRES_MAX 0xF - -enum omap_dmic_clk { - OMAP_DMIC_SYSCLK_PAD_CLKS, /* PAD_CLKS */ - OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS, /* SLIMBUS_CLK */ - OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS, /* DMIC_SYNC_MUX_CLK */ - OMAP_DMIC_ABE_DMIC_CLK, /* abe_dmic_clk */ -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-hdmi.c b/ANDROID_3.4.5/sound/soc/omap/omap-hdmi.c deleted file mode 100644 index 38e0defa..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-hdmi.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * omap-hdmi.c - * - * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors. - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ - * Authors: Jorge Candelaria - * Ricardo Neri - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "omap-pcm.h" -#include "omap-hdmi.h" - -#define DRV_NAME "hdmi-audio-dai" - -static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = { - .name = "HDMI playback", - .sync_mode = OMAP_DMA_SYNC_PACKET, -}; - -static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - int err; - /* - * Make sure that the period bytes are multiple of the DMA packet size. - * Largest packet size we use is 32 32-bit words = 128 bytes - */ - err = snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); - if (err < 0) - return err; - - return 0; -} - -static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int err = 0; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - omap_hdmi_dai_dma_params.packet_size = 16; - break; - case SNDRV_PCM_FORMAT_S24_LE: - omap_hdmi_dai_dma_params.packet_size = 32; - break; - default: - err = -EINVAL; - } - - omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; - - snd_soc_dai_set_dma_data(dai, substream, - &omap_hdmi_dai_dma_params); - - return err; -} - -static const struct snd_soc_dai_ops omap_hdmi_dai_ops = { - .startup = omap_hdmi_dai_startup, - .hw_params = omap_hdmi_dai_hw_params, -}; - -static struct snd_soc_dai_driver omap_hdmi_dai = { - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = OMAP_HDMI_RATES, - .formats = OMAP_HDMI_FORMATS, - }, - .ops = &omap_hdmi_dai_ops, -}; - -static __devinit int omap_hdmi_probe(struct platform_device *pdev) -{ - int ret; - struct resource *hdmi_rsrc; - - hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!hdmi_rsrc) { - dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n"); - return -EINVAL; - } - - omap_hdmi_dai_dma_params.port_addr = hdmi_rsrc->start - + OMAP_HDMI_AUDIO_DMA_PORT; - - hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!hdmi_rsrc) { - dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n"); - return -EINVAL; - } - - omap_hdmi_dai_dma_params.dma_req = hdmi_rsrc->start; - - ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai); - return ret; -} - -static int __devexit omap_hdmi_remove(struct platform_device *pdev) -{ - snd_soc_unregister_dai(&pdev->dev); - return 0; -} - -static struct platform_driver hdmi_dai_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, - .probe = omap_hdmi_probe, - .remove = __devexit_p(omap_hdmi_remove), -}; - -module_platform_driver(hdmi_dai_driver); - -MODULE_AUTHOR("Jorge Candelaria "); -MODULE_AUTHOR("Ricardo Neri "); -MODULE_DESCRIPTION("OMAP HDMI SoC Interface"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-hdmi.h b/ANDROID_3.4.5/sound/soc/omap/omap-hdmi.h deleted file mode 100644 index 34c298d5..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-hdmi.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * omap-hdmi.h - * - * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors. - * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ - * Authors: Jorge Candelaria - * Ricardo Neri - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_HDMI_H__ -#define __OMAP_HDMI_H__ - -#define OMAP_HDMI_AUDIO_DMA_PORT 0x8c - -#define OMAP_HDMI_RATES (SNDRV_PCM_RATE_32000 | \ - SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) - -#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -#endif diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.c b/ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.c deleted file mode 100644 index 6912ac7c..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * omap-mcbsp.c -- OMAP ALSA SoC DAI driver using McBSP port - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Jarkko Nikula - * Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "mcbsp.h" -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) - -#define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \ - xhandler_get, xhandler_put) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = omap_mcbsp_st_info_volsw, \ - .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long) &(struct soc_mixer_control) \ - {.min = xmin, .max = xmax} } - -enum { - OMAP_MCBSP_WORD_8 = 0, - OMAP_MCBSP_WORD_12, - OMAP_MCBSP_WORD_16, - OMAP_MCBSP_WORD_20, - OMAP_MCBSP_WORD_24, - OMAP_MCBSP_WORD_32, -}; - -/* - * Stream DMA parameters. DMA request line and port address are set runtime - * since they are different between OMAP1 and later OMAPs - */ -static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_pcm_dma_data *dma_data; - int words; - - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ - if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) - /* - * Configure McBSP threshold based on either: - * packet_size, when the sDMA is in packet mode, or - * based on the period size. - */ - if (dma_data->packet_size) - words = dma_data->packet_size; - else - words = snd_pcm_lib_period_bytes(substream) / - (mcbsp->wlen / 8); - else - words = 1; - - /* Configure McBSP internal buffer usage */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - omap_mcbsp_set_tx_threshold(mcbsp, words); - else - omap_mcbsp_set_rx_threshold(mcbsp, words); -} - -static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *buffer_size = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE); - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct omap_mcbsp *mcbsp = rule->private; - struct snd_interval frames; - int size; - - snd_interval_any(&frames); - size = mcbsp->pdata->buffer_size; - - frames.min = size / channels->min; - frames.integer = 1; - return snd_interval_refine(buffer_size, &frames); -} - -static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - int err = 0; - - if (!cpu_dai->active) - err = omap_mcbsp_request(mcbsp); - - /* - * OMAP3 McBSP FIFO is word structured. - * McBSP2 has 1024 + 256 = 1280 word long buffer, - * McBSP1,3,4,5 has 128 word long buffer - * This means that the size of the FIFO depends on the sample format. - * For example on McBSP3: - * 16bit samples: size is 128 * 2 = 256 bytes - * 32bit samples: size is 128 * 4 = 512 bytes - * It is simpler to place constraint for buffer and period based on - * channels. - * McBSP3 as example again (16 or 32 bit samples): - * 1 channel (mono): size is 128 frames (128 words) - * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words) - * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) - */ - if (mcbsp->pdata->buffer_size) { - /* - * Rule for the buffer size. We should not allow - * smaller buffer than the FIFO size to avoid underruns - */ - snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - omap_mcbsp_hwrule_min_buffersize, - mcbsp, - SNDRV_PCM_HW_PARAM_CHANNELS, -1); - - /* Make sure, that the period size is always even */ - snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); - } - - return err; -} - -static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - - if (!cpu_dai->active) { - omap_mcbsp_free(mcbsp); - mcbsp->configured = 0; - } -} - -static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *cpu_dai) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - mcbsp->active++; - omap_mcbsp_start(mcbsp, play, !play); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - omap_mcbsp_stop(mcbsp, play, !play); - mcbsp->active--; - break; - default: - err = -EINVAL; - } - - return err; -} - -static snd_pcm_sframes_t omap_mcbsp_dai_delay( - struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - u16 fifo_use; - snd_pcm_sframes_t delay; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - fifo_use = omap_mcbsp_get_tx_delay(mcbsp); - else - fifo_use = omap_mcbsp_get_rx_delay(mcbsp); - - /* - * Divide the used locations with the channel count to get the - * FIFO usage in samples (don't care about partial samples in the - * buffer). - */ - delay = fifo_use / substream->runtime->channels; - - return delay; -} - -static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; - struct omap_pcm_dma_data *dma_data; - int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; - int pkt_size = 0; - unsigned int format, div, framesize, master; - - dma_data = &mcbsp->dma_data[substream->stream]; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; - wlen = 16; - break; - case SNDRV_PCM_FORMAT_S32_LE: - dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; - wlen = 32; - break; - default: - return -EINVAL; - } - if (mcbsp->pdata->buffer_size) { - dma_data->set_threshold = omap_mcbsp_set_threshold; - /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ - if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { - int period_words, max_thrsh; - - period_words = params_period_bytes(params) / (wlen / 8); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - max_thrsh = mcbsp->max_tx_thres; - else - max_thrsh = mcbsp->max_rx_thres; - /* - * If the period contains less or equal number of words, - * we are using the original threshold mode setup: - * McBSP threshold = sDMA frame size = period_size - * Otherwise we switch to sDMA packet mode: - * McBSP threshold = sDMA packet size - * sDMA frame size = period size - */ - if (period_words > max_thrsh) { - int divider = 0; - - /* - * Look for the biggest threshold value, which - * divides the period size evenly. - */ - divider = period_words / max_thrsh; - if (period_words % max_thrsh) - divider++; - while (period_words % divider && - divider < period_words) - divider++; - if (divider == period_words) - return -EINVAL; - - pkt_size = period_words / divider; - sync_mode = OMAP_DMA_SYNC_PACKET; - } else { - sync_mode = OMAP_DMA_SYNC_FRAME; - } - } - } - - dma_data->sync_mode = sync_mode; - dma_data->packet_size = pkt_size; - - snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); - - if (mcbsp->configured) { - /* McBSP already configured by another stream */ - return 0; - } - - regs->rcr2 &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7)); - regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7)); - regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7)); - regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7)); - format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK; - wpf = channels = params_channels(params); - if (channels == 2 && (format == SND_SOC_DAIFMT_I2S || - format == SND_SOC_DAIFMT_LEFT_J)) { - /* Use dual-phase frames */ - regs->rcr2 |= RPHASE; - regs->xcr2 |= XPHASE; - /* Set 1 word per (McBSP) frame for phase1 and phase2 */ - wpf--; - regs->rcr2 |= RFRLEN2(wpf - 1); - regs->xcr2 |= XFRLEN2(wpf - 1); - } - - regs->rcr1 |= RFRLEN1(wpf - 1); - regs->xcr1 |= XFRLEN1(wpf - 1); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - /* Set word lengths */ - regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); - regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); - regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); - regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); - break; - case SNDRV_PCM_FORMAT_S32_LE: - /* Set word lengths */ - regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); - regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); - regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); - regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32); - break; - default: - /* Unsupported PCM format */ - return -EINVAL; - } - - /* In McBSP master modes, FRAME (i.e. sample rate) is generated - * by _counting_ BCLKs. Calculate frame size in BCLKs */ - master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK; - if (master == SND_SOC_DAIFMT_CBS_CFS) { - div = mcbsp->clk_div ? mcbsp->clk_div : 1; - framesize = (mcbsp->in_freq / div) / params_rate(params); - - if (framesize < wlen * channels) { - printk(KERN_ERR "%s: not enough bandwidth for desired rate and " - "channels\n", __func__); - return -EINVAL; - } - } else - framesize = wlen * channels; - - /* Set FS period and length in terms of bit clock periods */ - regs->srgr2 &= ~FPER(0xfff); - regs->srgr1 &= ~FWID(0xff); - switch (format) { - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_LEFT_J: - regs->srgr2 |= FPER(framesize - 1); - regs->srgr1 |= FWID((framesize >> 1) - 1); - break; - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - regs->srgr2 |= FPER(framesize - 1); - regs->srgr1 |= FWID(0); - break; - } - - omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs); - mcbsp->wlen = wlen; - mcbsp->configured = 1; - - return 0; -} - -/* - * This must be called before _set_clkdiv and _set_sysclk since McBSP register - * cache is initialized here - */ -static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; - bool inv_fs = false; - - if (mcbsp->configured) - return 0; - - mcbsp->fmt = fmt; - memset(regs, 0, sizeof(*regs)); - /* Generic McBSP register settings */ - regs->spcr2 |= XINTM(3) | FREE; - regs->spcr1 |= RINTM(3); - /* RFIG and XFIG are not defined in 34xx */ - if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { - regs->rcr2 |= RFIG; - regs->xcr2 |= XFIG; - } - if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { - regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; - regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - /* 1-bit data delay */ - regs->rcr2 |= RDATDLY(1); - regs->xcr2 |= XDATDLY(1); - break; - case SND_SOC_DAIFMT_LEFT_J: - /* 0-bit data delay */ - regs->rcr2 |= RDATDLY(0); - regs->xcr2 |= XDATDLY(0); - regs->spcr1 |= RJUST(2); - /* Invert FS polarity configuration */ - inv_fs = true; - break; - case SND_SOC_DAIFMT_DSP_A: - /* 1-bit data delay */ - regs->rcr2 |= RDATDLY(1); - regs->xcr2 |= XDATDLY(1); - /* Invert FS polarity configuration */ - inv_fs = true; - break; - case SND_SOC_DAIFMT_DSP_B: - /* 0-bit data delay */ - regs->rcr2 |= RDATDLY(0); - regs->xcr2 |= XDATDLY(0); - /* Invert FS polarity configuration */ - inv_fs = true; - break; - default: - /* Unsupported data format */ - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* McBSP master. Set FS and bit clocks as outputs */ - regs->pcr0 |= FSXM | FSRM | - CLKXM | CLKRM; - /* Sample rate generator drives the FS */ - regs->srgr2 |= FSGM; - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* McBSP slave */ - break; - default: - /* Unsupported master/slave configuration */ - return -EINVAL; - } - - /* Set bit clock (CLKX/CLKR) and FS polarities */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - /* - * Normal BCLK + FS. - * FS active low. TX data driven on falling edge of bit clock - * and RX data sampled on rising edge of bit clock. - */ - regs->pcr0 |= FSXP | FSRP | - CLKXP | CLKRP; - break; - case SND_SOC_DAIFMT_NB_IF: - regs->pcr0 |= CLKXP | CLKRP; - break; - case SND_SOC_DAIFMT_IB_NF: - regs->pcr0 |= FSXP | FSRP; - break; - case SND_SOC_DAIFMT_IB_IF: - break; - default: - return -EINVAL; - } - if (inv_fs == true) - regs->pcr0 ^= FSXP | FSRP; - - return 0; -} - -static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; - - if (div_id != OMAP_MCBSP_CLKGDV) - return -ENODEV; - - mcbsp->clk_div = div; - regs->srgr1 &= ~CLKGDV(0xff); - regs->srgr1 |= CLKGDV(div - 1); - - return 0; -} - -static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, - int dir) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; - int err = 0; - - if (mcbsp->active) { - if (freq == mcbsp->in_freq) - return 0; - else - return -EBUSY; - } - - if (clk_id == OMAP_MCBSP_SYSCLK_CLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || - clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT || - clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) { - mcbsp->in_freq = freq; - regs->srgr2 &= ~CLKSM; - regs->pcr0 &= ~SCLKME; - } else if (cpu_class_is_omap1()) { - /* - * McBSP CLKR/FSR signal muxing functions are only available on - * OMAP2 or newer versions - */ - return -EINVAL; - } - - switch (clk_id) { - case OMAP_MCBSP_SYSCLK_CLK: - regs->srgr2 |= CLKSM; - break; - case OMAP_MCBSP_SYSCLK_CLKS_FCLK: - if (cpu_class_is_omap1()) { - err = -EINVAL; - break; - } - err = omap2_mcbsp_set_clks_src(mcbsp, - MCBSP_CLKS_PRCM_SRC); - break; - case OMAP_MCBSP_SYSCLK_CLKS_EXT: - if (cpu_class_is_omap1()) { - err = 0; - break; - } - err = omap2_mcbsp_set_clks_src(mcbsp, - MCBSP_CLKS_PAD_SRC); - break; - - case OMAP_MCBSP_SYSCLK_CLKX_EXT: - regs->srgr2 |= CLKSM; - case OMAP_MCBSP_SYSCLK_CLKR_EXT: - regs->pcr0 |= SCLKME; - break; - - - case OMAP_MCBSP_CLKR_SRC_CLKR: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR); - break; - case OMAP_MCBSP_CLKR_SRC_CLKX: - err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX); - break; - case OMAP_MCBSP_FSR_SRC_FSR: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR); - break; - case OMAP_MCBSP_FSR_SRC_FSX: - err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX); - break; - default: - err = -ENODEV; - } - - return err; -} - -static const struct snd_soc_dai_ops mcbsp_dai_ops = { - .startup = omap_mcbsp_dai_startup, - .shutdown = omap_mcbsp_dai_shutdown, - .trigger = omap_mcbsp_dai_trigger, - .delay = omap_mcbsp_dai_delay, - .hw_params = omap_mcbsp_dai_hw_params, - .set_fmt = omap_mcbsp_dai_set_dai_fmt, - .set_clkdiv = omap_mcbsp_dai_set_clkdiv, - .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, -}; - -static int omap_mcbsp_probe(struct snd_soc_dai *dai) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai); - - pm_runtime_enable(mcbsp->dev); - - return 0; -} - -static int omap_mcbsp_remove(struct snd_soc_dai *dai) -{ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai); - - pm_runtime_disable(mcbsp->dev); - - return 0; -} - -static struct snd_soc_dai_driver omap_mcbsp_dai = { - .probe = omap_mcbsp_probe, - .remove = omap_mcbsp_remove, - .playback = { - .channels_min = 1, - .channels_max = 16, - .rates = OMAP_MCBSP_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, - }, - .capture = { - .channels_min = 1, - .channels_max = 16, - .rates = OMAP_MCBSP_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, - }, - .ops = &mcbsp_dai_ops, -}; - -static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int max = mc->max; - int min = mc->min; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = min; - uinfo->value.integer.max = max; - return 0; -} - -#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \ -static int \ -omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ - struct snd_ctl_elem_value *uc) \ -{ \ - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \ - struct soc_mixer_control *mc = \ - (struct soc_mixer_control *)kc->private_value; \ - int max = mc->max; \ - int min = mc->min; \ - int val = uc->value.integer.value[0]; \ - \ - if (val < min || val > max) \ - return -EINVAL; \ - \ - /* OMAP McBSP implementation uses index values 0..4 */ \ - return omap_st_set_chgain(mcbsp, channel, val); \ -} - -#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \ -static int \ -omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ - struct snd_ctl_elem_value *uc) \ -{ \ - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \ - s16 chgain; \ - \ - if (omap_st_get_chgain(mcbsp, channel, &chgain)) \ - return -EAGAIN; \ - \ - uc->value.integer.value[0] = chgain; \ - return 0; \ -} - -OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0) -OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1) -OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0) -OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1) - -static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - u8 value = ucontrol->value.integer.value[0]; - - if (value == omap_st_is_enabled(mcbsp)) - return 0; - - if (value) - omap_st_enable(mcbsp); - else - omap_st_disable(mcbsp); - - return 1; -} - -static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - - ucontrol->value.integer.value[0] = omap_st_is_enabled(mcbsp); - return 0; -} - -static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { - SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, - omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch0_volume, - omap_mcbsp_set_st_ch0_volume), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch1_volume, - omap_mcbsp_set_st_ch1_volume), -}; - -static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { - SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, - omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch0_volume, - omap_mcbsp_set_st_ch0_volume), - OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", - -32768, 32767, - omap_mcbsp_get_st_ch1_volume, - omap_mcbsp_set_st_ch1_volume), -}; - -int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); - - if (!mcbsp->st_data) - return -ENODEV; - - switch (cpu_dai->id) { - case 2: /* McBSP 2 */ - return snd_soc_add_dai_controls(cpu_dai, - omap_mcbsp2_st_controls, - ARRAY_SIZE(omap_mcbsp2_st_controls)); - case 3: /* McBSP 3 */ - return snd_soc_add_dai_controls(cpu_dai, - omap_mcbsp3_st_controls, - ARRAY_SIZE(omap_mcbsp3_st_controls)); - default: - break; - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); - -static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) -{ - struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct omap_mcbsp *mcbsp; - int ret; - - if (!pdata) { - dev_err(&pdev->dev, "missing platform data.\n"); - return -EINVAL; - } - mcbsp = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcbsp), GFP_KERNEL); - if (!mcbsp) - return -ENOMEM; - - mcbsp->id = pdev->id; - mcbsp->pdata = pdata; - mcbsp->dev = &pdev->dev; - platform_set_drvdata(pdev, mcbsp); - - ret = omap_mcbsp_init(pdev); - if (!ret) - return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai); - - return ret; -} - -static int __devexit asoc_mcbsp_remove(struct platform_device *pdev) -{ - struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); - - snd_soc_unregister_dai(&pdev->dev); - - if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) - mcbsp->pdata->ops->free(mcbsp->id); - - omap_mcbsp_sysfs_remove(mcbsp); - - clk_put(mcbsp->fclk); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver asoc_mcbsp_driver = { - .driver = { - .name = "omap-mcbsp", - .owner = THIS_MODULE, - }, - - .probe = asoc_mcbsp_probe, - .remove = __devexit_p(asoc_mcbsp_remove), -}; - -module_platform_driver(asoc_mcbsp_driver); - -MODULE_AUTHOR("Jarkko Nikula "); -MODULE_DESCRIPTION("OMAP I2S SoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.h b/ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.h deleted file mode 100644 index f877b16f..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-mcbsp.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * omap-mcbsp.h - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Jarkko Nikula - * Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_I2S_H__ -#define __OMAP_I2S_H__ - -/* Source clocks for McBSP sample rate generator */ -enum omap_mcbsp_clksrg_clk { - OMAP_MCBSP_SYSCLK_CLKS_FCLK, /* Internal FCLK */ - OMAP_MCBSP_SYSCLK_CLKS_EXT, /* External CLKS pin */ - OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ - OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ - OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */ - OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */ - OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */ -}; - -/* McBSP dividers */ -enum omap_mcbsp_div { - OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ -}; - -#if defined(CONFIG_SOC_OMAP2420) -#define NUM_LINKS 2 -#endif -#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -#undef NUM_LINKS -#define NUM_LINKS 3 -#endif -#if defined(CONFIG_ARCH_OMAP4) -#undef NUM_LINKS -#define NUM_LINKS 4 -#endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430) -#undef NUM_LINKS -#define NUM_LINKS 5 -#endif - -int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); - -#endif diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.c b/ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.c deleted file mode 100644 index 39705561..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * omap-mcpdm.c -- OMAP ALSA SoC DAI driver using McPDM port - * - * Copyright (C) 2009 - 2011 Texas Instruments - * - * Author: Misael Lopez Cruz - * Contact: Jorge Eduardo Candelaria - * Margarita Olaya - * Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include "omap-mcpdm.h" -#include "omap-pcm.h" - -struct omap_mcpdm { - struct device *dev; - unsigned long phys_base; - void __iomem *io_base; - int irq; - - struct mutex mutex; - - /* channel data */ - u32 dn_channels; - u32 up_channels; - - /* McPDM FIFO thresholds */ - u32 dn_threshold; - u32 up_threshold; - - /* McPDM dn offsets for rx1, and 2 channels */ - u32 dn_rx_offset; -}; - -/* - * Stream DMA parameters - */ -static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { - { - .name = "Audio playback", - .dma_req = OMAP44XX_DMA_MCPDM_DL, - .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, - .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA, - }, - { - .name = "Audio capture", - .dma_req = OMAP44XX_DMA_MCPDM_UP, - .data_type = OMAP_DMA_DATA_TYPE_S32, - .sync_mode = OMAP_DMA_SYNC_PACKET, - .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA, - }, -}; - -static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val) -{ - __raw_writel(val, mcpdm->io_base + reg); -} - -static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg) -{ - return __raw_readl(mcpdm->io_base + reg); -} - -#ifdef DEBUG -static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) -{ - dev_dbg(mcpdm->dev, "***********************\n"); - dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS_RAW)); - dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS)); - dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_SET)); - dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_CLR)); - dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_IRQWAKE_EN)); - dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_SET)); - dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_CLR)); - dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_DMAWAKEEN)); - dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL)); - dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_DN_DATA)); - dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_UP_DATA)); - dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_DN)); - dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n", - omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_UP)); - dev_dbg(mcpdm->dev, "***********************\n"); -} -#else -static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {} -#endif - -/* - * Enables the transfer through the PDM interface to/from the Phoenix - * codec by enabling the corresponding UP or DN channels. - */ -static void omap_mcpdm_start(struct omap_mcpdm *mcpdm) -{ - u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); - - ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - - ctrl |= mcpdm->dn_channels | mcpdm->up_channels; - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - - ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); -} - -/* - * Disables the transfer through the PDM interface to/from the Phoenix - * codec by disabling the corresponding UP or DN channels. - */ -static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm) -{ - u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); - - ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - - ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels); - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - - ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST); - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl); - -} - -/* - * Is the physical McPDM interface active. - */ -static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm) -{ - return omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL) & - (MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK); -} - -/* - * Configures McPDM uplink, and downlink for audio. - * This function should be called before omap_mcpdm_start. - */ -static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm) -{ - omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET, - MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL | - MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL); - - /* Enable DN RX1/2 offset cancellation feature, if configured */ - if (mcpdm->dn_rx_offset) { - u32 dn_offset = mcpdm->dn_rx_offset; - - omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); - dn_offset |= (MCPDM_DN_OFST_RX1_EN | MCPDM_DN_OFST_RX2_EN); - omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset); - } - - omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold); - omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold); - - omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET, - MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE); -} - -/* - * Cleans McPDM uplink, and downlink configuration. - * This function should be called when the stream is closed. - */ -static void omap_mcpdm_close_streams(struct omap_mcpdm *mcpdm) -{ - /* Disable irq request generation for downlink */ - omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR, - MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL); - - /* Disable DMA request generation for downlink */ - omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_DN_ENABLE); - - /* Disable irq request generation for uplink */ - omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR, - MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL); - - /* Disable DMA request generation for uplink */ - omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_UP_ENABLE); - - /* Disable RX1/2 offset cancellation */ - if (mcpdm->dn_rx_offset) - omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, 0); -} - -static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id) -{ - struct omap_mcpdm *mcpdm = dev_id; - int irq_status; - - irq_status = omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS); - - /* Acknowledge irq event */ - omap_mcpdm_write(mcpdm, MCPDM_REG_IRQSTATUS, irq_status); - - if (irq_status & MCPDM_DN_IRQ_FULL) - dev_dbg(mcpdm->dev, "DN (playback) FIFO Full\n"); - - if (irq_status & MCPDM_DN_IRQ_EMPTY) - dev_dbg(mcpdm->dev, "DN (playback) FIFO Empty\n"); - - if (irq_status & MCPDM_DN_IRQ) - dev_dbg(mcpdm->dev, "DN (playback) write request\n"); - - if (irq_status & MCPDM_UP_IRQ_FULL) - dev_dbg(mcpdm->dev, "UP (capture) FIFO Full\n"); - - if (irq_status & MCPDM_UP_IRQ_EMPTY) - dev_dbg(mcpdm->dev, "UP (capture) FIFO Empty\n"); - - if (irq_status & MCPDM_UP_IRQ) - dev_dbg(mcpdm->dev, "UP (capture) write request\n"); - - return IRQ_HANDLED; -} - -static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - - mutex_lock(&mcpdm->mutex); - - if (!dai->active) { - /* Enable watch dog for ES above ES 1.0 to avoid saturation */ - if (omap_rev() != OMAP4430_REV_ES1_0) { - u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); - - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, - ctrl | MCPDM_WD_EN); - } - omap_mcpdm_open_streams(mcpdm); - } - - mutex_unlock(&mcpdm->mutex); - - return 0; -} - -static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - - mutex_lock(&mcpdm->mutex); - - if (!dai->active) { - if (omap_mcpdm_active(mcpdm)) { - omap_mcpdm_stop(mcpdm); - omap_mcpdm_close_streams(mcpdm); - } - } - - mutex_unlock(&mcpdm->mutex); -} - -static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - int stream = substream->stream; - struct omap_pcm_dma_data *dma_data; - int channels; - int link_mask = 0; - - channels = params_channels(params); - switch (channels) { - case 5: - if (stream == SNDRV_PCM_STREAM_CAPTURE) - /* up to 3 channels for capture */ - return -EINVAL; - link_mask |= 1 << 4; - case 4: - if (stream == SNDRV_PCM_STREAM_CAPTURE) - /* up to 3 channels for capture */ - return -EINVAL; - link_mask |= 1 << 3; - case 3: - link_mask |= 1 << 2; - case 2: - link_mask |= 1 << 1; - case 1: - link_mask |= 1 << 0; - break; - default: - /* unsupported number of channels */ - return -EINVAL; - } - - dma_data = &omap_mcpdm_dai_dma_params[stream]; - - /* Configure McPDM channels, and DMA packet size */ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcpdm->dn_channels = link_mask << 3; - dma_data->packet_size = - (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels; - } else { - mcpdm->up_channels = link_mask << 0; - dma_data->packet_size = mcpdm->up_threshold * channels; - } - - snd_soc_dai_set_dma_data(dai, substream, dma_data); - - return 0; -} - -static int omap_mcpdm_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - - if (!omap_mcpdm_active(mcpdm)) { - omap_mcpdm_start(mcpdm); - omap_mcpdm_reg_dump(mcpdm); - } - - return 0; -} - -static const struct snd_soc_dai_ops omap_mcpdm_dai_ops = { - .startup = omap_mcpdm_dai_startup, - .shutdown = omap_mcpdm_dai_shutdown, - .hw_params = omap_mcpdm_dai_hw_params, - .prepare = omap_mcpdm_prepare, -}; - -static int omap_mcpdm_probe(struct snd_soc_dai *dai) -{ - struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - int ret; - - pm_runtime_enable(mcpdm->dev); - - /* Disable lines while request is ongoing */ - pm_runtime_get_sync(mcpdm->dev); - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00); - - ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, - 0, "McPDM", (void *)mcpdm); - - pm_runtime_put_sync(mcpdm->dev); - - if (ret) { - dev_err(mcpdm->dev, "Request for IRQ failed\n"); - pm_runtime_disable(mcpdm->dev); - } - - /* Configure McPDM threshold values */ - mcpdm->dn_threshold = 2; - mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3; - return ret; -} - -static int omap_mcpdm_remove(struct snd_soc_dai *dai) -{ - struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - - free_irq(mcpdm->irq, (void *)mcpdm); - pm_runtime_disable(mcpdm->dev); - - return 0; -} - -#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) -#define OMAP_MCPDM_FORMATS SNDRV_PCM_FMTBIT_S32_LE - -static struct snd_soc_dai_driver omap_mcpdm_dai = { - .probe = omap_mcpdm_probe, - .remove = omap_mcpdm_remove, - .probe_order = SND_SOC_COMP_ORDER_LATE, - .remove_order = SND_SOC_COMP_ORDER_EARLY, - .playback = { - .channels_min = 1, - .channels_max = 5, - .rates = OMAP_MCPDM_RATES, - .formats = OMAP_MCPDM_FORMATS, - .sig_bits = 24, - }, - .capture = { - .channels_min = 1, - .channels_max = 3, - .rates = OMAP_MCPDM_RATES, - .formats = OMAP_MCPDM_FORMATS, - .sig_bits = 24, - }, - .ops = &omap_mcpdm_dai_ops, -}; - -void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd, - u8 rx1, u8 rx2) -{ - struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(rtd->cpu_dai); - - mcpdm->dn_rx_offset = MCPDM_DNOFST_RX1(rx1) | MCPDM_DNOFST_RX2(rx2); -} -EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets); - -static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) -{ - struct omap_mcpdm *mcpdm; - struct resource *res; - int ret = 0; - - mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); - if (!mcpdm) - return -ENOMEM; - - platform_set_drvdata(pdev, mcpdm); - - mutex_init(&mcpdm->mutex); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no resource\n"); - goto err_res; - } - - if (!request_mem_region(res->start, resource_size(res), "McPDM")) { - ret = -EBUSY; - goto err_res; - } - - mcpdm->io_base = ioremap(res->start, resource_size(res)); - if (!mcpdm->io_base) { - ret = -ENOMEM; - goto err_iomap; - } - - mcpdm->irq = platform_get_irq(pdev, 0); - if (mcpdm->irq < 0) { - ret = mcpdm->irq; - goto err_irq; - } - - mcpdm->dev = &pdev->dev; - - ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); - if (!ret) - return 0; - -err_irq: - iounmap(mcpdm->io_base); -err_iomap: - release_mem_region(res->start, resource_size(res)); -err_res: - kfree(mcpdm); - return ret; -} - -static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) -{ - struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev); - struct resource *res; - - snd_soc_unregister_dai(&pdev->dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iounmap(mcpdm->io_base); - release_mem_region(res->start, resource_size(res)); - - kfree(mcpdm); - return 0; -} - -static struct platform_driver asoc_mcpdm_driver = { - .driver = { - .name = "omap-mcpdm", - .owner = THIS_MODULE, - }, - - .probe = asoc_mcpdm_probe, - .remove = __devexit_p(asoc_mcpdm_remove), -}; - -module_platform_driver(asoc_mcpdm_driver); - -MODULE_AUTHOR("Misael Lopez Cruz "); -MODULE_DESCRIPTION("OMAP PDM SoC Interface"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.h b/ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.h deleted file mode 100644 index de8cf265..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-mcpdm.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * omap-mcpdm.h - * - * Copyright (C) 2009 - 2011 Texas Instruments - * - * Contact: Misael Lopez Cruz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_MCPDM_H__ -#define __OMAP_MCPDM_H__ - -#define MCPDM_REG_REVISION 0x00 -#define MCPDM_REG_SYSCONFIG 0x10 -#define MCPDM_REG_IRQSTATUS_RAW 0x24 -#define MCPDM_REG_IRQSTATUS 0x28 -#define MCPDM_REG_IRQENABLE_SET 0x2C -#define MCPDM_REG_IRQENABLE_CLR 0x30 -#define MCPDM_REG_IRQWAKE_EN 0x34 -#define MCPDM_REG_DMAENABLE_SET 0x38 -#define MCPDM_REG_DMAENABLE_CLR 0x3C -#define MCPDM_REG_DMAWAKEEN 0x40 -#define MCPDM_REG_CTRL 0x44 -#define MCPDM_REG_DN_DATA 0x48 -#define MCPDM_REG_UP_DATA 0x4C -#define MCPDM_REG_FIFO_CTRL_DN 0x50 -#define MCPDM_REG_FIFO_CTRL_UP 0x54 -#define MCPDM_REG_DN_OFFSET 0x58 - -/* - * MCPDM_IRQ bit fields - * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR - */ - -#define MCPDM_DN_IRQ (1 << 0) -#define MCPDM_DN_IRQ_EMPTY (1 << 1) -#define MCPDM_DN_IRQ_ALMST_EMPTY (1 << 2) -#define MCPDM_DN_IRQ_FULL (1 << 3) - -#define MCPDM_UP_IRQ (1 << 8) -#define MCPDM_UP_IRQ_EMPTY (1 << 9) -#define MCPDM_UP_IRQ_ALMST_FULL (1 << 10) -#define MCPDM_UP_IRQ_FULL (1 << 11) - -#define MCPDM_DOWNLINK_IRQ_MASK 0x00F -#define MCPDM_UPLINK_IRQ_MASK 0xF00 - -/* - * MCPDM_DMAENABLE bit fields - */ - -#define MCPDM_DMA_DN_ENABLE (1 << 0) -#define MCPDM_DMA_UP_ENABLE (1 << 1) - -/* - * MCPDM_CTRL bit fields - */ - -#define MCPDM_PDM_UPLINK_EN(x) (1 << (x - 1)) /* ch1 is at bit 0 */ -#define MCPDM_PDM_DOWNLINK_EN(x) (1 << (x + 2)) /* ch1 is at bit 3 */ -#define MCPDM_PDMOUTFORMAT (1 << 8) -#define MCPDM_CMD_INT (1 << 9) -#define MCPDM_STATUS_INT (1 << 10) -#define MCPDM_SW_UP_RST (1 << 11) -#define MCPDM_SW_DN_RST (1 << 12) -#define MCPDM_WD_EN (1 << 14) -#define MCPDM_PDM_UP_MASK 0x7 -#define MCPDM_PDM_DN_MASK (0x1f << 3) - - -#define MCPDM_PDMOUTFORMAT_LJUST (0 << 8) -#define MCPDM_PDMOUTFORMAT_RJUST (1 << 8) - -/* - * MCPDM_FIFO_CTRL bit fields - */ - -#define MCPDM_UP_THRES_MAX 0xF -#define MCPDM_DN_THRES_MAX 0xF - -/* - * MCPDM_DN_OFFSET bit fields - */ - -#define MCPDM_DN_OFST_RX1_EN (1 << 0) -#define MCPDM_DNOFST_RX1(x) ((x & 0x1f) << 1) -#define MCPDM_DN_OFST_RX2_EN (1 << 8) -#define MCPDM_DNOFST_RX2(x) ((x & 0x1f) << 9) - -void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd, - u8 rx1, u8 rx2); - -#endif /* End of __OMAP_MCPDM_H__ */ diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-pcm.c b/ANDROID_3.4.5/sound/soc/omap/omap-pcm.c deleted file mode 100644 index 5a649da9..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-pcm.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * omap-pcm.c -- ALSA PCM interface for the OMAP SoC - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Jarkko Nikula - * Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include "omap-pcm.h" - -static const struct snd_pcm_hardware omap_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .period_bytes_min = 32, - .period_bytes_max = 64 * 1024, - .periods_min = 2, - .periods_max = 255, - .buffer_bytes_max = 128 * 1024, -}; - -struct omap_runtime_data { - spinlock_t lock; - struct omap_pcm_dma_data *dma_data; - int dma_ch; - int period_index; -}; - -static void omap_pcm_dma_irq(int ch, u16 stat, void *data) -{ - struct snd_pcm_substream *substream = data; - struct snd_pcm_runtime *runtime = substream->runtime; - struct omap_runtime_data *prtd = runtime->private_data; - unsigned long flags; - - if ((cpu_is_omap1510())) { - /* - * OMAP1510 doesn't fully support DMA progress counter - * and there is no software emulation implemented yet, - * so have to maintain our own progress counters - * that can be used by omap_pcm_pointer() instead. - */ - spin_lock_irqsave(&prtd->lock, flags); - if ((stat == OMAP_DMA_LAST_IRQ) && - (prtd->period_index == runtime->periods - 1)) { - /* we are in sync, do nothing */ - spin_unlock_irqrestore(&prtd->lock, flags); - return; - } - if (prtd->period_index >= 0) { - if (stat & OMAP_DMA_BLOCK_IRQ) { - /* end of buffer reached, loop back */ - prtd->period_index = 0; - } else if (stat & OMAP_DMA_LAST_IRQ) { - /* update the counter for the last period */ - prtd->period_index = runtime->periods - 1; - } else if (++prtd->period_index >= runtime->periods) { - /* end of buffer missed? loop back */ - prtd->period_index = 0; - } - } - spin_unlock_irqrestore(&prtd->lock, flags); - } - - snd_pcm_period_elapsed(substream); -} - -/* this may get called several times by oss emulation */ -static int omap_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct omap_runtime_data *prtd = runtime->private_data; - struct omap_pcm_dma_data *dma_data; - - int err = 0; - - dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - /* return if this is a bufferless transfer e.g. - * codec <--> BT codec or GSM modem -- lg FIXME */ - if (!dma_data) - return 0; - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = params_buffer_bytes(params); - - if (prtd->dma_data) - return 0; - prtd->dma_data = dma_data; - err = omap_request_dma(dma_data->dma_req, dma_data->name, - omap_pcm_dma_irq, substream, &prtd->dma_ch); - if (!err) { - /* - * Link channel with itself so DMA doesn't need any - * reprogramming while looping the buffer - */ - omap_dma_link_lch(prtd->dma_ch, prtd->dma_ch); - } - - return err; -} - -static int omap_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct omap_runtime_data *prtd = runtime->private_data; - - if (prtd->dma_data == NULL) - return 0; - - omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch); - omap_free_dma(prtd->dma_ch); - prtd->dma_data = NULL; - - snd_pcm_set_runtime_buffer(substream, NULL); - - return 0; -} - -static int omap_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct omap_runtime_data *prtd = runtime->private_data; - struct omap_pcm_dma_data *dma_data = prtd->dma_data; - struct omap_dma_channel_params dma_params; - int bytes; - - /* return if this is a bufferless transfer e.g. - * codec <--> BT codec or GSM modem -- lg FIXME */ - if (!prtd->dma_data) - return 0; - - memset(&dma_params, 0, sizeof(dma_params)); - dma_params.data_type = dma_data->data_type; - dma_params.trigger = dma_data->dma_req; - dma_params.sync_mode = dma_data->sync_mode; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; - dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; - dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC; - dma_params.src_start = runtime->dma_addr; - dma_params.dst_start = dma_data->port_addr; - dma_params.dst_port = OMAP_DMA_PORT_MPUI; - dma_params.dst_fi = dma_data->packet_size; - } else { - dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT; - dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; - dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC; - dma_params.src_start = dma_data->port_addr; - dma_params.dst_start = runtime->dma_addr; - dma_params.src_port = OMAP_DMA_PORT_MPUI; - dma_params.src_fi = dma_data->packet_size; - } - /* - * Set DMA transfer frame size equal to ALSA period size and frame - * count as no. of ALSA periods. Then with DMA frame interrupt enabled, - * we can transfer the whole ALSA buffer with single DMA transfer but - * still can get an interrupt at each period bounary - */ - bytes = snd_pcm_lib_period_bytes(substream); - dma_params.elem_count = bytes >> dma_data->data_type; - dma_params.frame_count = runtime->periods; - omap_set_dma_params(prtd->dma_ch, &dma_params); - - if ((cpu_is_omap1510())) - omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | - OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); - else if (!substream->runtime->no_period_wakeup) - omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); - else { - /* - * No period wakeup: - * we need to disable BLOCK_IRQ, which is enabled by the omap - * dma core at request dma time. - */ - omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ); - } - - if (!(cpu_class_is_omap1())) { - omap_set_dma_src_burst_mode(prtd->dma_ch, - OMAP_DMA_DATA_BURST_16); - omap_set_dma_dest_burst_mode(prtd->dma_ch, - OMAP_DMA_DATA_BURST_16); - } - - return 0; -} - -static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct omap_runtime_data *prtd = runtime->private_data; - struct omap_pcm_dma_data *dma_data = prtd->dma_data; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&prtd->lock, flags); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - prtd->period_index = 0; - /* Configure McBSP internal buffer usage */ - if (dma_data->set_threshold) - dma_data->set_threshold(substream); - - omap_start_dma(prtd->dma_ch); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - prtd->period_index = -1; - omap_stop_dma(prtd->dma_ch); - break; - default: - ret = -EINVAL; - } - spin_unlock_irqrestore(&prtd->lock, flags); - - return ret; -} - -static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct omap_runtime_data *prtd = runtime->private_data; - dma_addr_t ptr; - snd_pcm_uframes_t offset; - - if (cpu_is_omap1510()) { - offset = prtd->period_index * runtime->period_size; - } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - ptr = omap_get_dma_dst_pos(prtd->dma_ch); - offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); - } else { - ptr = omap_get_dma_src_pos(prtd->dma_ch); - offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); - } - - if (offset >= runtime->buffer_size) - offset = 0; - - return offset; -} - -static int omap_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct omap_runtime_data *prtd; - int ret; - - snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); - - /* Ensure that buffer size is a multiple of period size */ - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); - if (prtd == NULL) { - ret = -ENOMEM; - goto out; - } - spin_lock_init(&prtd->lock); - runtime->private_data = prtd; - -out: - return ret; -} - -static int omap_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - kfree(runtime->private_data); - return 0; -} - -static int omap_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - -static struct snd_pcm_ops omap_pcm_ops = { - .open = omap_pcm_open, - .close = omap_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = omap_pcm_hw_params, - .hw_free = omap_pcm_hw_free, - .prepare = omap_pcm_prepare, - .trigger = omap_pcm_trigger, - .pointer = omap_pcm_pointer, - .mmap = omap_pcm_mmap, -}; - -static u64 omap_pcm_dmamask = DMA_BIT_MASK(64); - -static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, - int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = omap_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - - buf->bytes = size; - return 0; -} - -static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - -static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_card *card = rtd->card->snd_card; - struct snd_pcm *pcm = rtd->pcm; - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &omap_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(64); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = omap_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = omap_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - -out: - /* free preallocated buffers in case of error */ - if (ret) - omap_pcm_free_dma_buffers(pcm); - - return ret; -} - -static struct snd_soc_platform_driver omap_soc_platform = { - .ops = &omap_pcm_ops, - .pcm_new = omap_pcm_new, - .pcm_free = omap_pcm_free_dma_buffers, -}; - -static __devinit int omap_pcm_probe(struct platform_device *pdev) -{ - return snd_soc_register_platform(&pdev->dev, - &omap_soc_platform); -} - -static int __devexit omap_pcm_remove(struct platform_device *pdev) -{ - snd_soc_unregister_platform(&pdev->dev); - return 0; -} - -static struct platform_driver omap_pcm_driver = { - .driver = { - .name = "omap-pcm-audio", - .owner = THIS_MODULE, - }, - - .probe = omap_pcm_probe, - .remove = __devexit_p(omap_pcm_remove), -}; - -module_platform_driver(omap_pcm_driver); - -MODULE_AUTHOR("Jarkko Nikula "); -MODULE_DESCRIPTION("OMAP PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap-pcm.h b/ANDROID_3.4.5/sound/soc/omap/omap-pcm.h deleted file mode 100644 index b92248cb..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap-pcm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * omap-pcm.h - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Jarkko Nikula - * Peter Ujfalusi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_PCM_H__ -#define __OMAP_PCM_H__ - -struct snd_pcm_substream; - -struct omap_pcm_dma_data { - char *name; /* stream identifier */ - int dma_req; /* DMA request line */ - unsigned long port_addr; /* transmit/receive register */ - void (*set_threshold)(struct snd_pcm_substream *substream); - int data_type; /* data type 8,16,32 */ - int sync_mode; /* DMA sync mode */ - int packet_size; /* packet size only in PACKET mode */ -}; - -#endif diff --git a/ANDROID_3.4.5/sound/soc/omap/omap3beagle.c b/ANDROID_3.4.5/sound/soc/omap/omap3beagle.c deleted file mode 100644 index 2830dfd0..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap3beagle.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * omap3beagle.c -- SoC audio for OMAP3 Beagle - * - * Author: Steve Sakoman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int omap3beagle_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - unsigned int fmt; - int ret; - - switch (params_channels(params)) { - case 2: /* Stereo I2S mode */ - fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM; - break; - case 4: /* Four channel TDM mode */ - fmt = SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM; - break; - default: - return -EINVAL; - } - - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, fmt); - if (ret < 0) { - printk(KERN_ERR "can't set codec DAI configuration\n"); - return ret; - } - - /* Set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); - if (ret < 0) { - printk(KERN_ERR "can't set cpu DAI configuration\n"); - return ret; - } - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops omap3beagle_ops = { - .hw_params = omap3beagle_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link omap3beagle_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .platform_name = "omap-pcm-audio", - .codec_dai_name = "twl4030-hifi", - .codec_name = "twl4030-codec", - .ops = &omap3beagle_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_omap3beagle = { - .name = "omap3beagle", - .owner = THIS_MODULE, - .dai_link = &omap3beagle_dai, - .num_links = 1, -}; - -static struct platform_device *omap3beagle_snd_device; - -static int __init omap3beagle_soc_init(void) -{ - int ret; - - if (!(machine_is_omap3_beagle() || machine_is_devkit8000())) - return -ENODEV; - pr_info("OMAP3 Beagle/Devkit8000 SoC init\n"); - - omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); - if (!omap3beagle_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle); - - ret = platform_device_add(omap3beagle_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(omap3beagle_snd_device); - - return ret; -} - -static void __exit omap3beagle_soc_exit(void) -{ - platform_device_unregister(omap3beagle_snd_device); -} - -module_init(omap3beagle_soc_init); -module_exit(omap3beagle_soc_exit); - -MODULE_AUTHOR("Steve Sakoman "); -MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap3evm.c b/ANDROID_3.4.5/sound/soc/omap/omap3evm.c deleted file mode 100644 index 3d468c91..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap3evm.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * omap3evm.c -- ALSA SoC support for OMAP3 EVM - * - * Author: Anuj Aggarwal - * - * Based on sound/soc/omap/beagle.c by Steve Sakoman - * - * Copyright (C) 2008 Texas Instruments, Incorporated - * - * 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 version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, - * whether express or implied; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -static int omap3evm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops omap3evm_ops = { - .hw_params = omap3evm_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link omap3evm_dai = { - .name = "TWL4030", - .stream_name = "TWL4030", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM, - .ops = &omap3evm_ops, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_omap3evm = { - .name = "omap3evm", - .owner = THIS_MODULE, - .dai_link = &omap3evm_dai, - .num_links = 1, -}; - -static struct platform_device *omap3evm_snd_device; - -static int __init omap3evm_soc_init(void) -{ - int ret; - - if (!machine_is_omap3evm()) - return -ENODEV; - pr_info("OMAP3 EVM SoC init\n"); - - omap3evm_snd_device = platform_device_alloc("soc-audio", -1); - if (!omap3evm_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm); - ret = platform_device_add(omap3evm_snd_device); - if (ret) - goto err1; - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(omap3evm_snd_device); - - return ret; -} - -static void __exit omap3evm_soc_exit(void) -{ - platform_device_unregister(omap3evm_snd_device); -} - -module_init(omap3evm_soc_init); -module_exit(omap3evm_soc_exit); - -MODULE_AUTHOR("Anuj Aggarwal "); -MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap3pandora.c b/ANDROID_3.4.5/sound/soc/omap/omap3pandora.c deleted file mode 100644 index 4c3a0978..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap3pandora.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * omap3pandora.c -- SoC audio for Pandora Handheld Console - * - * Author: Gražvydas Ignotas - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" - -#define OMAP3_PANDORA_DAC_POWER_GPIO 118 -#define OMAP3_PANDORA_AMP_POWER_GPIO 14 - -#define PREFIX "ASoC omap3pandora: " - -static struct regulator *omap3pandora_dac_reg; - -static int omap3pandora_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - int ret; - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - pr_err(PREFIX "can't set codec system clock\n"); - return ret; - } - - /* Set McBSP clock to external */ - ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, - 256 * params_rate(params), - SND_SOC_CLOCK_IN); - if (ret < 0) { - pr_err(PREFIX "can't set cpu system clock\n"); - return ret; - } - - ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8); - if (ret < 0) { - pr_err(PREFIX "can't set SRG clock divider\n"); - return ret; - } - - return 0; -} - -static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - /* - * The PCM1773 DAC datasheet requires 1ms delay between switching - * VCC power on/off and /PD pin high/low - */ - if (SND_SOC_DAPM_EVENT_ON(event)) { - regulator_enable(omap3pandora_dac_reg); - mdelay(1); - gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); - } else { - gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0); - mdelay(1); - regulator_disable(omap3pandora_dac_reg); - } - - return 0; -} - -static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - if (SND_SOC_DAPM_EVENT_ON(event)) - gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1); - else - gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0); - - return 0; -} - -/* - * Audio paths on Pandora board: - * - * |O| ---> PCM DAC +-> AMP -> Headphone Jack - * |M| A +--------> Line Out - * |A| <~~clk~~+ - * |P| <--- TWL4030 <--------- Line In and MICs - */ -static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { - SND_SOC_DAPM_DAC_E("PCM DAC", "HiFi Playback", SND_SOC_NOPM, - 0, 0, omap3pandora_dac_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM, - 0, 0, NULL, 0, omap3pandora_hp_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), -}; - -static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Mic (internal)", NULL), - SND_SOC_DAPM_MIC("Mic (external)", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), -}; - -static const struct snd_soc_dapm_route omap3pandora_out_map[] = { - {"PCM DAC", NULL, "APLL Enable"}, - {"Headphone Amplifier", NULL, "PCM DAC"}, - {"Line Out", NULL, "PCM DAC"}, - {"Headphone Jack", NULL, "Headphone Amplifier"}, -}; - -static const struct snd_soc_dapm_route omap3pandora_in_map[] = { - {"AUXL", NULL, "Line In"}, - {"AUXR", NULL, "Line In"}, - - {"MAINMIC", NULL, "Mic Bias 1"}, - {"Mic Bias 1", NULL, "Mic (internal)"}, - - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 2", NULL, "Mic (external)"}, -}; - -static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - /* All TWL4030 output pins are floating */ - snd_soc_dapm_nc_pin(dapm, "EARPIECE"); - snd_soc_dapm_nc_pin(dapm, "PREDRIVEL"); - snd_soc_dapm_nc_pin(dapm, "PREDRIVER"); - snd_soc_dapm_nc_pin(dapm, "HSOL"); - snd_soc_dapm_nc_pin(dapm, "HSOR"); - snd_soc_dapm_nc_pin(dapm, "CARKITL"); - snd_soc_dapm_nc_pin(dapm, "CARKITR"); - snd_soc_dapm_nc_pin(dapm, "HFL"); - snd_soc_dapm_nc_pin(dapm, "HFR"); - snd_soc_dapm_nc_pin(dapm, "VIBRA"); - - ret = snd_soc_dapm_new_controls(dapm, omap3pandora_out_dapm_widgets, - ARRAY_SIZE(omap3pandora_out_dapm_widgets)); - if (ret < 0) - return ret; - - return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map, - ARRAY_SIZE(omap3pandora_out_map)); -} - -static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - int ret; - - /* Not comnnected */ - snd_soc_dapm_nc_pin(dapm, "HSMIC"); - snd_soc_dapm_nc_pin(dapm, "CARKITMIC"); - snd_soc_dapm_nc_pin(dapm, "DIGIMIC0"); - snd_soc_dapm_nc_pin(dapm, "DIGIMIC1"); - - ret = snd_soc_dapm_new_controls(dapm, omap3pandora_in_dapm_widgets, - ARRAY_SIZE(omap3pandora_in_dapm_widgets)); - if (ret < 0) - return ret; - - return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map, - ARRAY_SIZE(omap3pandora_in_map)); -} - -static struct snd_soc_ops omap3pandora_ops = { - .hw_params = omap3pandora_hw_params, -}; - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link omap3pandora_dai[] = { - { - .name = "PCM1773", - .stream_name = "HiFi Out", - .cpu_dai_name = "omap-mcbsp.2", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, - .ops = &omap3pandora_ops, - .init = omap3pandora_out_init, - }, { - .name = "TWL4030", - .stream_name = "Line/Mic In", - .cpu_dai_name = "omap-mcbsp.4", - .codec_dai_name = "twl4030-hifi", - .platform_name = "omap-pcm-audio", - .codec_name = "twl4030-codec", - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, - .ops = &omap3pandora_ops, - .init = omap3pandora_in_init, - } -}; - -/* SoC card */ -static struct snd_soc_card snd_soc_card_omap3pandora = { - .name = "omap3pandora", - .owner = THIS_MODULE, - .dai_link = omap3pandora_dai, - .num_links = ARRAY_SIZE(omap3pandora_dai), -}; - -static struct platform_device *omap3pandora_snd_device; - -static int __init omap3pandora_soc_init(void) -{ - int ret; - - if (!machine_is_omap3_pandora()) - return -ENODEV; - - pr_info("OMAP3 Pandora SoC init\n"); - - ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power"); - if (ret) { - pr_err(PREFIX "Failed to get DAC power GPIO\n"); - return ret; - } - - ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0); - if (ret) { - pr_err(PREFIX "Failed to set DAC power GPIO direction\n"); - goto fail0; - } - - ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power"); - if (ret) { - pr_err(PREFIX "Failed to get amp power GPIO\n"); - goto fail0; - } - - ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0); - if (ret) { - pr_err(PREFIX "Failed to set amp power GPIO direction\n"); - goto fail1; - } - - omap3pandora_snd_device = platform_device_alloc("soc-audio", -1); - if (omap3pandora_snd_device == NULL) { - pr_err(PREFIX "Platform device allocation failed\n"); - ret = -ENOMEM; - goto fail1; - } - - platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora); - - ret = platform_device_add(omap3pandora_snd_device); - if (ret) { - pr_err(PREFIX "Unable to add platform device\n"); - goto fail2; - } - - omap3pandora_dac_reg = regulator_get(&omap3pandora_snd_device->dev, "vcc"); - if (IS_ERR(omap3pandora_dac_reg)) { - pr_err(PREFIX "Failed to get DAC regulator from %s: %ld\n", - dev_name(&omap3pandora_snd_device->dev), - PTR_ERR(omap3pandora_dac_reg)); - ret = PTR_ERR(omap3pandora_dac_reg); - goto fail3; - } - - return 0; - -fail3: - platform_device_del(omap3pandora_snd_device); -fail2: - platform_device_put(omap3pandora_snd_device); -fail1: - gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO); -fail0: - gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO); - return ret; -} -module_init(omap3pandora_soc_init); - -static void __exit omap3pandora_soc_exit(void) -{ - regulator_put(omap3pandora_dac_reg); - platform_device_unregister(omap3pandora_snd_device); - gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO); - gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO); -} -module_exit(omap3pandora_soc_exit); - -MODULE_AUTHOR("Grazvydas Ignotas "); -MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/sound/soc/omap/omap4-hdmi-card.c b/ANDROID_3.4.5/sound/soc/omap/omap4-hdmi-card.c deleted file mode 100644 index 28d689b2..00000000 --- a/ANDROID_3.4.5/sound/soc/omap/omap4-hdmi-card.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * omap4-hdmi-card.c - * - * OMAP ALSA SoC machine driver for TI OMAP4 HDMI - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ - * Author: Ricardo Neri - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include